[osgearth] 03/10: Imported Upstream version 2.8~rc1+dfsg

Bas Couwenberg sebastic at debian.org
Sat Sep 3 12:42:28 UTC 2016


This is an automated email from the git hooks/post-receive script.

sebastic pushed a commit to branch experimental
in repository osgearth.

commit 93221a8a1e5978f79b69b35ff394b64d69568db4
Author: Bas Couwenberg <sebastic at xs4all.nl>
Date:   Sat Sep 3 13:00:44 2016 +0200

    Imported Upstream version 2.8~rc1+dfsg
---
 .travis.yml                                        |    42 +
 CMakeLists.txt                                     |    30 +-
 CMakeModules/ConfigureShaders.cmake.in             |    14 +-
 CMakeModules/FindMiniZip.cmake                     |    70 -
 CMakeModules/FindPoco.cmake                        |    69 +
 CMakeModules/FindRocksDB.cmake                     |    42 +
 CMakeModules/FindSilverLining.cmake                |    30 +-
 CMakeModules/FindTriton.cmake                      |    24 +-
 CMakeModules/OsgEarthMacroUtils.cmake              |    12 -
 README.md                                          |    23 +
 README.txt                                         |    20 -
 docs/CMakeLists.txt                                |     1 -
 docs/Doxyfile                                      |  2353 +
 docs/source/data.rst                               |     2 +-
 docs/source/developer/shader_composition.rst       |    22 +-
 docs/source/developer/utilities.rst                |     8 +-
 docs/source/faq.rst                                |    19 +-
 .../source/references/drivers/cache/filesystem.rst |     2 +-
 .../drivers/model/feature_model_shared_props.rst   |     4 +-
 .../references/drivers/model/feature_stencil.rst   |    41 -
 docs/source/references/drivers/model/index.rst     |     1 -
 docs/source/references/drivers/model/simple.rst    |     2 +-
 docs/source/references/earthfile.rst               |    25 +-
 docs/source/references/symbology.rst               |    13 +-
 docs/source/releasenotes.rst                       |    46 +
 docs/source/startup.rst                            |    44 +-
 docs/source/user/caching.rst                       |     2 +-
 docs/source/user/features.rst                      |    67 +
 src/CMakeLists.txt                                 |    35 +-
 src/applications/CMakeLists.txt                    |   118 +-
 src/applications/osgearth_3pv/CMakeLists.txt       |     7 +
 src/applications/osgearth_3pv/osgearth_3pv.cpp     |   263 +
 .../osgearth_annotation/osgearth_annotation.cpp    |   294 +-
 src/applications/osgearth_atlas/osgearth_atlas.cpp |    29 +-
 .../osgearth_backfill/osgearth_backfill.cpp        |     2 +-
 src/applications/osgearth_boundarygen/BoundaryUtil |     2 +-
 .../osgearth_boundarygen/BoundaryUtil.cpp          |     4 +-
 .../osgearth_boundarygen/VertexCollectionVisitor   |     2 +-
 .../VertexCollectionVisitor.cpp                    |     2 +-
 .../osgearth_boundarygen/boundarygen.cpp           |     2 +-
 .../osgearth_cache_test/osgearth_cache_test.cpp    |    12 +-
 src/applications/osgearth_city/osgearth_city.cpp   |     7 +-
 src/applications/osgearth_clamp/osgearth_clamp.cpp |     2 +-
 .../osgearth_clipplane/osgearth_clipplane.cpp      |     4 +-
 .../osgearth_colorfilter/osgearth_colorfilter.cpp  |     2 +-
 .../osgearth_computerangecallback/CMakeLists.txt   |     7 +
 .../osgearth_computerangecallback.cpp              |   122 +
 .../osgearth_controls/osgearth_controls.cpp        |    20 +-
 src/applications/osgearth_conv/osgearth_conv.cpp   |    29 +-
 .../osgearth_createtile/osgearth_createtile.cpp    |    85 +-
 src/applications/osgearth_datetime/CMakeLists.txt  |     7 +
 .../osgearth_datetime/osgearth_datetime.cpp        |   198 +
 .../osgearth_deformation/CMakeLists.txt            |     7 +
 .../osgearth_deformation/osgearth_deformation.cpp  |   599 +
 src/applications/osgearth_demo/osgearth_demo.cpp   |     3 +
 .../osgearth_elevation/osgearth_elevation.cpp      |    67 +-
 src/applications/osgearth_ephemeris/CMakeLists.txt |     7 +
 .../osgearth_ephemeris/osgearth_ephemeris.cpp      |   144 +
 .../osgearth_featureeditor.cpp                     |    21 +-
 .../osgearth_featurefilter.cpp                     |     2 +-
 .../osgearth_featureinfo/osgearth_featureinfo.cpp  |     7 +-
 .../osgearth_featurequery.cpp                      |     2 +-
 .../osgearth_features/osgearth_features.cpp        |    24 +-
 src/applications/osgearth_fog/osgearth_fog.cpp     |   133 +-
 .../osgearth_graticule/osgearth_graticule.cpp      |     2 +-
 src/applications/osgearth_horizon/CMakeLists.txt   |     7 +
 .../osgearth_horizon/osgearth_horizon.cpp          |   172 +
 src/applications/osgearth_http/CMakeLists.txt      |     7 +
 src/applications/osgearth_http/osgearth_http.cpp   |    48 +
 .../osgearth_imageoverlay.cpp                      |     2 +-
 src/applications/osgearth_los/osgearth_los.cpp     |     2 +-
 src/applications/osgearth_manip/osgearth_manip.cpp |   115 +-
 src/applications/osgearth_map/osgearth_map.cpp     |     2 +-
 .../osgearth_measure/osgearth_measure.cpp          |     4 +-
 .../osgearth_minimap/osgearth_minimap.cpp          |     2 +-
 src/applications/osgearth_mrt/osgearth_mrt.cpp     |    13 +-
 .../osgearth_occlusionculling.cpp                  |     8 +-
 .../osgearth_overlayviewer.cpp                     |    27 +-
 .../osgearth_package/osgearth_package.cpp          |     7 +-
 .../osgearth_package_qt/CMakeLists.txt             |    11 +-
 src/applications/osgearth_package_qt/ExportDialog  |     2 +-
 .../osgearth_package_qt/ExportDialog.cpp           |     2 +-
 .../osgearth_package_qt/PackageQtMainWindow        |     2 +-
 .../osgearth_package_qt/SceneController.cpp        |     2 +-
 .../osgearth_package_qt/SceneController.h          |     2 +-
 .../osgearth_package_qt/TMSExporter.cpp            |     2 +-
 src/applications/osgearth_package_qt/TMSExporter.h |     2 +-
 src/applications/osgearth_package_qt/WaitDialog    |     2 +-
 .../osgearth_package_qt/WaitDialog.cpp             |     2 +-
 .../osgearth_package_qt/package_qt.cpp             |     2 +-
 .../osgearth_pagingtest/CMakeLists.txt             |     8 +
 .../osgearth_pagingtest/osgearth_pagingtest.cpp    |   334 +
 src/applications/osgearth_pick/osgearth_pick.cpp   |    27 +-
 src/applications/osgearth_qt/CMakeLists.txt        |    44 -
 src/applications/osgearth_qt/DemoMainWindow        |   201 -
 src/applications/osgearth_qt/demo_style.qss        |    22 -
 src/applications/osgearth_qt/images.qrc            |     5 -
 .../osgearth_qt/images/terrain_profile.png         |   Bin 358 -> 0 bytes
 src/applications/osgearth_qt/osgearth_qt.cpp       |   415 -
 src/applications/osgearth_qt_simple/CMakeLists.txt |    11 +-
 .../osgearth_qt_simple/osgearth_qt_simple.cpp      |     3 +-
 .../osgearth_qt_windows/CMakeLists.txt             |    11 +-
 .../osgearth_qt_windows/osgearth_qt_windows.cpp    |     4 +-
 src/applications/osgearth_seed/osgearth_seed.cpp   |    73 +-
 .../osgearth_sequencecontrol.cpp                   |     4 +-
 src/applications/osgearth_server/CMakeLists.txt    |    13 +
 .../osgearth_server/osgearth_server.cpp            |   623 +
 .../osgearth_shadercomp/osgearth_shadercomp.cpp    |   270 +-
 .../osgearth_shadergen/osgearth_shadergen.cpp      |     2 +-
 .../osgearth_sharedlayer/osgearth_sharedlayer.cpp  |     2 +-
 .../osgearth_silverlining/CMakeLists.txt           |     9 +
 .../osgearth_silverlining.cpp                      |   242 +
 src/applications/osgearth_skyview/CMakeLists.txt   |    14 +
 src/applications/osgearth_skyview/SkyManipulator   |    40 +
 .../osgearth_skyview/SkyManipulator.cpp            |   120 +
 .../osgearth_skyview/osgearth_skyview.cpp          |   108 +
 src/applications/osgearth_splat/CMakeLists.txt     |    10 +
 src/applications/osgearth_splat/osgearth_splat.cpp |   135 +
 src/applications/osgearth_srstest/CMakeLists.txt   |     7 +
 .../osgearth_srstest/osgearth_srstest.cpp          |    70 +
 .../osgearth_terrainprofile.cpp                    |     2 +-
 src/applications/osgearth_tfs/osgearth_tfs.cpp     |     9 +-
 .../osgearth_tileindex/osgearth_tileindex.cpp      |     2 +-
 .../osgearth_tilesource/osgearth_tilesource.cpp    |     6 +-
 src/applications/osgearth_toc/osgearth_toc.cpp     |    44 +-
 .../osgearth_tracks/osgearth_tracks.cpp            |    34 +-
 .../osgearth_transform/osgearth_transform.cpp      |     2 +-
 src/applications/osgearth_triton/CMakeLists.txt    |     9 +
 .../osgearth_triton/osgearth_triton.cpp            |   189 +
 .../osgearth_version/osgearth_version.cpp          |     2 +-
 .../osgearth_viewer/osgearth_viewer.cpp            |    39 +-
 src/applications/osgearth_wfs/CMakeLists.txt       |     7 +
 src/applications/osgearth_wfs/osgearth_wfs.cpp     |   116 +
 src/applications/osgearth_xfbtest/CMakeLists.txt   |     7 +
 .../osgearth_xfbtest/osgearth_xfbtest.cpp          |   438 +
 src/osgEarth/AlphaEffect                           |     3 +-
 src/osgEarth/AlphaEffect.cpp                       |    82 +-
 src/osgEarth/AlphaEffect.frag.glsl                 |     8 +-
 src/osgEarth/AutoScale                             |     5 +-
 src/osgEarth/AutoScale.cpp                         |     8 +-
 src/osgEarth/Bounds                                |     2 +-
 src/osgEarth/Bounds.cpp                            |     2 +-
 src/osgEarth/CMakeLists.txt                        |    69 +-
 src/osgEarth/Cache                                 |    89 +-
 src/osgEarth/Cache.cpp                             |    85 +-
 src/osgEarth/CacheBin                              |    55 +-
 src/osgEarth/CacheBin.cpp                          |   379 +
 src/osgEarth/CacheEstimator                        |     2 +-
 src/osgEarth/CacheEstimator.cpp                    |     4 +-
 src/osgEarth/CachePolicy                           |    22 +-
 src/osgEarth/CachePolicy.cpp                       |    71 +-
 src/osgEarth/CacheSeed                             |     2 +-
 src/osgEarth/CacheSeed.cpp                         |     2 +-
 src/osgEarth/Capabilities                          |     2 +-
 src/osgEarth/Capabilities.cpp                      |    10 +-
 src/osgEarth/ClampableNode.cpp                     |     3 +-
 src/osgEarth/Clamping                              |    12 +-
 src/osgEarth/Clamping.cpp                          |    16 +-
 src/osgEarth/ClampingTechnique                     |     5 +-
 src/osgEarth/ClampingTechnique.cpp                 |     8 +-
 src/osgEarth/ColorFilter                           |     5 +-
 src/osgEarth/ColorFilter.cpp                       |     2 +-
 src/osgEarth/Common                                |    17 +-
 src/osgEarth/CompositeTileSource                   |     2 +-
 src/osgEarth/CompositeTileSource.cpp               |    47 +-
 src/osgEarth/Config                                |   130 +-
 src/osgEarth/Config.cpp                            |    80 +-
 src/osgEarth/Containers                            |   128 +-
 src/osgEarth/Cube                                  |     2 +-
 src/osgEarth/Cube.cpp                              |     4 +-
 src/osgEarth/CullingUtils                          |    49 +-
 src/osgEarth/CullingUtils.cpp                      |   262 +-
 src/osgEarth/DPLineSegmentIntersector              |     2 +-
 src/osgEarth/DPLineSegmentIntersector.cpp          |   181 +-
 src/osgEarth/DateTime.cpp                          |     6 +-
 src/osgEarth/DateTimeRange                         |    52 +
 src/osgEarth/DateTimeRange.cpp                     |    91 +
 src/osgEarth/Decluttering                          |   178 -
 src/osgEarth/Decluttering.cpp                      |   807 -
 src/osgEarth/DepthOffset                           |     2 +-
 src/osgEarth/DepthOffset.cpp                       |     2 +-
 src/osgEarth/DepthOffset.vert.glsl                 |     6 +-
 src/osgEarth/DrapeableNode                         |    27 +-
 src/osgEarth/DrapeableNode.cpp                     |    77 +-
 src/osgEarth/Draping.frag.glsl                     |    12 +-
 src/osgEarth/Draping.vert.glsl                     |     8 +-
 src/osgEarth/DrapingCullSet                        |    76 +
 src/osgEarth/DrapingCullSet.cpp                    |   155 +
 src/osgEarth/DrapingTechnique                      |    13 +-
 src/osgEarth/DrapingTechnique.cpp                  |   191 +-
 src/osgEarth/DrawInstanced                         |    14 +-
 src/osgEarth/DrawInstanced.cpp                     |    26 +-
 src/osgEarth/ECEF                                  |     2 +-
 src/osgEarth/ECEF.cpp                              |     2 +-
 src/osgEarth/ElevationField                        |    79 -
 src/osgEarth/ElevationField.cpp                    |   139 -
 src/osgEarth/ElevationLOD                          |     2 +-
 src/osgEarth/ElevationLOD.cpp                      |    29 +-
 src/osgEarth/ElevationLayer                        |    14 +-
 src/osgEarth/ElevationLayer.cpp                    |    63 +-
 src/osgEarth/ElevationQuery                        |    27 +-
 src/osgEarth/ElevationQuery.cpp                    |    77 +-
 src/osgEarth/Export                                |     2 +-
 src/osgEarth/Extension                             |   105 +-
 src/osgEarth/Extension.cpp                         |    25 +-
 src/osgEarth/FadeEffect                            |     2 +-
 src/osgEarth/FadeEffect.cpp                        |     2 +-
 src/osgEarth/FileUtils                             |     7 +-
 src/osgEarth/FileUtils.cpp                         |    19 +-
 src/osgEarth/GLSLChunker                           |    63 +
 src/osgEarth/GLSLChunker.cpp                       |   228 +
 src/osgEarth/GPUClamping.frag.glsl                 |     9 +-
 src/osgEarth/GPUClamping.vert.glsl                 |    44 +-
 src/osgEarth/GPUClamping.vert.lib.glsl             |     4 +-
 src/osgEarth/GeoCommon                             |     2 +-
 src/osgEarth/GeoData                               |     6 +-
 src/osgEarth/GeoData.cpp                           |    70 +-
 src/osgEarth/GeoMath                               |     2 +-
 src/osgEarth/GeoMath.cpp                           |     2 +-
 src/osgEarth/GeoTransform                          |    31 +-
 src/osgEarth/GeoTransform.cpp                      |    57 +-
 src/osgEarth/Geoid                                 |     2 +-
 src/osgEarth/Geoid.cpp                             |     2 +-
 src/osgEarth/GeometryClamper                       |    99 +
 src/osgEarth/GeometryClamper.cpp                   |   198 +
 src/osgEarth/HTTPClient                            |     3 +-
 src/osgEarth/HTTPClient.cpp                        |   302 +-
 src/osgEarth/HeightFieldUtils                      |     6 +-
 src/osgEarth/HeightFieldUtils.cpp                  |    38 +-
 src/osgEarth/Horizon                               |   128 +-
 src/osgEarth/Horizon.cpp                           |   481 +-
 src/osgEarth/IOTypes                               |    14 +-
 src/osgEarth/IOTypes.cpp                           |    15 +-
 src/osgEarth/ImageLayer                            |     4 +-
 src/osgEarth/ImageLayer.cpp                        |    93 +-
 src/osgEarth/ImageMosaic                           |     2 +-
 src/osgEarth/ImageMosaic.cpp                       |    45 +-
 src/osgEarth/ImageToHeightFieldConverter           |     2 +-
 src/osgEarth/ImageToHeightFieldConverter.cpp       |     8 +-
 src/osgEarth/ImageUtils                            |    47 +-
 src/osgEarth/ImageUtils.cpp                        |   163 +-
 src/osgEarth/Instancing.vert.glsl                  |    18 +-
 src/osgEarth/IntersectionPicker                    |     2 +-
 src/osgEarth/IntersectionPicker.cpp                |     4 +-
 src/osgEarth/JsonUtils                             |     8 +-
 src/osgEarth/JsonUtils.cpp                         |    25 +-
 src/osgEarth/Layer                                 |     2 +-
 src/osgEarth/Layer.cpp                             |     2 +-
 src/osgEarth/LineFunctor                           |     2 +-
 src/osgEarth/LocalTangentPlane                     |     2 +-
 src/osgEarth/LocalTangentPlane.cpp                 |     2 +-
 src/osgEarth/Locators                              |    13 +-
 src/osgEarth/Locators.cpp                          |     2 +-
 src/osgEarth/Map                                   |    37 +-
 src/osgEarth/Map.cpp                               |   173 +-
 src/osgEarth/MapCallback                           |     2 +-
 src/osgEarth/MapCallback.cpp                       |     2 +-
 src/osgEarth/MapFrame                              |    19 +-
 src/osgEarth/MapFrame.cpp                          |    24 +-
 src/osgEarth/MapInfo                               |     2 +-
 src/osgEarth/MapInfo.cpp                           |     2 +-
 src/osgEarth/MapModelChange                        |     2 +-
 src/osgEarth/MapNode                               |    40 +-
 src/osgEarth/MapNode.cpp                           |   249 +-
 src/osgEarth/MapNodeObserver                       |     2 +-
 src/osgEarth/MapNodeOptions                        |     2 +-
 src/osgEarth/MapNodeOptions.cpp                    |     2 +-
 src/osgEarth/MapOptions                            |    15 +-
 src/osgEarth/MapOptions.cpp                        |     6 +-
 src/osgEarth/MaskLayer                             |    17 +-
 src/osgEarth/MaskLayer.cpp                         |    53 +-
 src/osgEarth/MaskNode                              |     2 +-
 src/osgEarth/MaskNode.cpp                          |     2 +-
 src/osgEarth/MaskSource                            |    42 +-
 src/osgEarth/MaskSource.cpp                        |    18 +-
 src/osgEarth/MemCache                              |     2 +-
 src/osgEarth/MemCache.cpp                          |    24 +-
 src/osgEarth/Memory                                |    52 +
 src/osgEarth/Memory.cpp                            |   175 +
 src/osgEarth/MimeTypes.cpp                         |     2 +-
 src/osgEarth/ModelLayer                            |    55 +-
 src/osgEarth/ModelLayer.cpp                        |   183 +-
 src/osgEarth/ModelSource                           |    48 +-
 src/osgEarth/ModelSource.cpp                       |    30 +-
 src/osgEarth/NativeProgramAdapter                  |     2 +-
 src/osgEarth/NodeUtils                             |    27 +-
 src/osgEarth/NodeUtils.cpp                         |     2 +-
 src/osgEarth/Notify                                |     7 +-
 src/osgEarth/Notify.cpp                            |     9 +-
 src/osgEarth/ObjectIndex                           |    33 +-
 src/osgEarth/ObjectIndex.cpp                       |   110 +-
 src/osgEarth/OverlayDecorator                      |    32 +-
 src/osgEarth/OverlayDecorator.cpp                  |   106 +-
 src/osgEarth/OverlayNode.cpp                       |     4 +-
 src/osgEarth/PhongLightingEffect                   |     1 -
 src/osgEarth/PhongLightingEffect.cpp               |    17 +-
 src/osgEarth/Picker                                |     2 +-
 src/osgEarth/PrimitiveIntersector                  |     2 +-
 src/osgEarth/PrimitiveIntersector.cpp              |     8 +-
 src/osgEarth/Profile                               |     2 +-
 src/osgEarth/Profile.cpp                           |    28 +-
 src/osgEarth/Profiler                              |     2 +-
 src/osgEarth/Profiler.cpp                          |     2 +-
 src/osgEarth/Progress                              |    29 +-
 src/osgEarth/Progress.cpp                          |    31 +-
 src/osgEarth/QuadTree                              |   199 +
 src/osgEarth/QuadTree.cpp                          |   825 +
 src/osgEarth/Random                                |     7 +-
 src/osgEarth/Random.cpp                            |    11 +-
 src/osgEarth/Registry                              |    47 +-
 src/osgEarth/Registry.cpp                          |   193 +-
 src/osgEarth/ResourceReleaser                      |    58 +
 src/osgEarth/ResourceReleaser.cpp                  |    74 +
 src/osgEarth/Revisioning                           |     5 +-
 src/osgEarth/Revisioning.cpp                       |     2 +-
 src/osgEarth/ScreenSpaceLayout                     |   204 +
 src/osgEarth/ScreenSpaceLayout.cpp                 |   945 +
 src/osgEarth/ShaderFactory                         |    23 +-
 src/osgEarth/ShaderFactory.cpp                     |  1013 +-
 src/osgEarth/ShaderGenerator                       |     7 +
 src/osgEarth/ShaderGenerator.cpp                   |    45 +-
 src/osgEarth/ShaderLoader                          |    33 +-
 src/osgEarth/ShaderLoader.cpp                      |   229 +-
 src/osgEarth/ShaderUtils                           |     8 +-
 src/osgEarth/ShaderUtils.cpp                       |   195 +-
 src/osgEarth/Shaders.cpp.in                        |    16 +-
 src/osgEarth/Shadowing                             |    41 +
 src/osgEarth/Shadowing.cpp                         |    42 +
 src/osgEarth/SharedSARepo                          |     2 +-
 src/osgEarth/SpatialReference                      |     6 +-
 src/osgEarth/SpatialReference.cpp                  |    65 +-
 src/osgEarth/StateSetCache                         |    20 +-
 src/osgEarth/StateSetCache.cpp                     |     2 +-
 src/osgEarth/StateSetLOD                           |     2 +-
 src/osgEarth/StateSetLOD.cpp                       |     2 +-
 src/osgEarth/Status                                |    75 +
 src/osgEarth/Status.cpp                            |    47 +
 src/osgEarth/StringUtils                           |    10 +-
 src/osgEarth/StringUtils.cpp                       |    62 +-
 src/osgEarth/TaskService                           |     2 +-
 src/osgEarth/TaskService.cpp                       |    12 +-
 src/osgEarth/Terrain                               |     6 +-
 src/osgEarth/Terrain.cpp                           |    18 +-
 src/osgEarth/TerrainEffect                         |     2 +-
 src/osgEarth/TerrainEngineNode                     |   175 +-
 src/osgEarth/TerrainEngineNode.cpp                 |   118 +-
 src/osgEarth/TerrainEngineRequirements             |    39 +
 src/osgEarth/TerrainLayer                          |   153 +-
 src/osgEarth/TerrainLayer.cpp                      |   785 +-
 src/osgEarth/TerrainOptions                        |    34 +-
 src/osgEarth/TerrainOptions.cpp                    |    33 +-
 src/osgEarth/TerrainTileModel                      |   234 +
 src/osgEarth/TerrainTileModel.cpp                  |   124 +
 src/osgEarth/TerrainTileModelFactory               |   128 +
 src/osgEarth/TerrainTileModelFactory.cpp           |   399 +
 src/osgEarth/TerrainTileNode                       |    50 +-
 src/osgEarth/Tessellator                           |     2 +-
 src/osgEarth/Tessellator.cpp                       |     2 +-
 src/osgEarth/TextureBufferSerializer.cpp           |    37 +
 src/osgEarth/TextureCompositor                     |     2 +-
 src/osgEarth/TextureCompositor.cpp                 |     2 +-
 src/osgEarth/ThreadingUtils                        |     2 +-
 src/osgEarth/ThreadingUtils.cpp                    |     2 +-
 src/osgEarth/TileHandler                           |     2 +-
 src/osgEarth/TileHandler.cpp                       |     2 +-
 src/osgEarth/TileKey                               |     4 +-
 src/osgEarth/TileKey.cpp                           |     2 +-
 src/osgEarth/TileKeyDataStore                      |    40 +
 src/osgEarth/TilePatchCallback                     |    79 +
 src/osgEarth/TilePatchCallback.cpp                 |    26 +
 src/osgEarth/TileSource                            |    71 +-
 src/osgEarth/TileSource.cpp                        |   216 +-
 src/osgEarth/TileVisitor                           |     2 +-
 src/osgEarth/TileVisitor.cpp                       |    15 +-
 src/osgEarth/TimeControl                           |     2 +-
 src/osgEarth/TimeControl.cpp                       |     2 +-
 src/osgEarth/TraversalData                         |    92 +-
 src/osgEarth/TraversalData.cpp                     |   122 +-
 src/osgEarth/URI                                   |    30 +-
 src/osgEarth/URI.cpp                               |    93 +-
 src/osgEarth/Units                                 |    14 +-
 src/osgEarth/Units.cpp                             |    68 +-
 src/osgEarth/Utils                                 |     7 +-
 src/osgEarth/Utils.cpp                             |    67 +-
 src/osgEarth/Version                               |     7 +-
 src/osgEarth/Version.cpp                           |    14 +-
 src/osgEarth/VerticalDatum                         |     2 +-
 src/osgEarth/VerticalDatum.cpp                     |     6 +-
 src/osgEarth/Viewpoint                             |     5 +-
 src/osgEarth/Viewpoint.cpp                         |     2 +-
 src/osgEarth/VirtualProgram                        |   166 +-
 src/osgEarth/VirtualProgram.cpp                    |   529 +-
 src/osgEarth/XmlUtils                              |     6 +-
 src/osgEarth/XmlUtils.cpp                          |   106 +-
 src/osgEarth/optional                              |     5 +-
 src/osgEarth/tinyxml.h                             |     2 +-
 src/osgEarthAnnotation/AnnotationData              |    36 +-
 src/osgEarthAnnotation/AnnotationData.cpp          |     3 +-
 src/osgEarthAnnotation/AnnotationEditing           |    18 +-
 src/osgEarthAnnotation/AnnotationEditing.cpp       |    37 +-
 src/osgEarthAnnotation/AnnotationExtension         |    61 +
 src/osgEarthAnnotation/AnnotationExtension.cpp     |    91 +
 src/osgEarthAnnotation/AnnotationNode              |   145 +-
 src/osgEarthAnnotation/AnnotationNode.cpp          |   328 +-
 src/osgEarthAnnotation/AnnotationRegistry          |     9 +-
 src/osgEarthAnnotation/AnnotationRegistry.cpp      |    31 +-
 src/osgEarthAnnotation/AnnotationSettings          |     2 +-
 src/osgEarthAnnotation/AnnotationSettings.cpp      |     2 +-
 src/osgEarthAnnotation/AnnotationUtils             |    38 +-
 src/osgEarthAnnotation/AnnotationUtils.cpp         |   347 +-
 src/osgEarthAnnotation/BboxDrawable                |    47 +
 src/osgEarthAnnotation/BboxDrawable.cpp            |    81 +
 src/osgEarthAnnotation/CMakeLists.txt              |    12 +-
 src/osgEarthAnnotation/CircleNode                  |    32 +-
 src/osgEarthAnnotation/CircleNode.cpp              |    79 +-
 src/osgEarthAnnotation/Common                      |     2 +-
 src/osgEarthAnnotation/Decoration                  |     7 +-
 src/osgEarthAnnotation/Decoration.cpp              |    16 +-
 src/osgEarthAnnotation/Draggers                    |    55 +-
 src/osgEarthAnnotation/Draggers.cpp                |   160 +-
 src/osgEarthAnnotation/EllipseNode                 |    27 +-
 src/osgEarthAnnotation/EllipseNode.cpp             |    73 +-
 src/osgEarthAnnotation/Export                      |     2 +-
 src/osgEarthAnnotation/FeatureEditing              |     2 +-
 src/osgEarthAnnotation/FeatureEditing.cpp          |     2 +-
 src/osgEarthAnnotation/FeatureNode                 |    41 +-
 src/osgEarthAnnotation/FeatureNode.cpp             |   240 +-
 src/osgEarthAnnotation/GeoPositionNode             |   141 +
 src/osgEarthAnnotation/GeoPositionNode.cpp         |   307 +
 src/osgEarthAnnotation/GeoPositionNodeAutoScaler   |    58 +
 .../GeoPositionNodeAutoScaler.cpp                  |    53 +
 src/osgEarthAnnotation/HighlightDecoration         |     4 +-
 src/osgEarthAnnotation/HighlightDecoration.cpp     |     6 +-
 src/osgEarthAnnotation/ImageOverlay                |    25 +-
 src/osgEarthAnnotation/ImageOverlay.cpp            |    89 +-
 src/osgEarthAnnotation/ImageOverlayEditor          |     2 +-
 src/osgEarthAnnotation/ImageOverlayEditor.cpp      |     5 +-
 src/osgEarthAnnotation/LabelNode                   |    27 +-
 src/osgEarthAnnotation/LabelNode.cpp               |   173 +-
 src/osgEarthAnnotation/LocalGeometryNode           |    44 +-
 src/osgEarthAnnotation/LocalGeometryNode.cpp       |   251 +-
 src/osgEarthAnnotation/LocalizedNode               |   159 -
 src/osgEarthAnnotation/LocalizedNode.cpp           |   354 -
 src/osgEarthAnnotation/ModelNode                   |    13 +-
 src/osgEarthAnnotation/ModelNode.cpp               |    71 +-
 src/osgEarthAnnotation/OrthoNode                   |   158 -
 src/osgEarthAnnotation/OrthoNode.cpp               |   413 -
 src/osgEarthAnnotation/PlaceNode                   |    36 +-
 src/osgEarthAnnotation/PlaceNode.cpp               |   254 +-
 src/osgEarthAnnotation/RectangleNode               |    12 +-
 src/osgEarthAnnotation/RectangleNode.cpp           |    31 +-
 src/osgEarthAnnotation/ScaleDecoration             |     4 +-
 src/osgEarthAnnotation/TrackNode                   |    12 +-
 src/osgEarthAnnotation/TrackNode.cpp               |    62 +-
 src/osgEarthDrivers/CMakeLists.txt                 |     2 +-
 src/osgEarthDrivers/agglite/AGGLiteOptions         |     2 +-
 .../agglite/AGGLiteRasterizerTileSource.cpp        |     6 +-
 src/osgEarthDrivers/arcgis/ArcGISOptions           |     2 +-
 src/osgEarthDrivers/arcgis/Extent.h                |     2 +-
 src/osgEarthDrivers/arcgis/MapService.cpp          |     9 +-
 src/osgEarthDrivers/arcgis/MapService.h            |     2 +-
 src/osgEarthDrivers/arcgis/ReaderWriterArcGIS.cpp  |    11 +-
 .../ReaderWriterArcGISMapCache.cpp                 |     4 +-
 src/osgEarthDrivers/bing/BingOptions               |     6 +-
 src/osgEarthDrivers/bing/BingTileSource.cpp        |    36 +-
 .../bumpmap/BumpMap.frag.common.glsl               |    26 +
 .../bumpmap/BumpMap.frag.progressive.glsl          |    60 +
 .../bumpmap/BumpMap.frag.simple.glsl               |    29 +
 src/osgEarthDrivers/bumpmap/BumpMap.vert.view.glsl |    52 +
 src/osgEarthDrivers/bumpmap/BumpMapExtension       |    75 +
 src/osgEarthDrivers/bumpmap/BumpMapExtension.cpp   |   106 +
 src/osgEarthDrivers/bumpmap/BumpMapOptions         |   118 +
 src/osgEarthDrivers/bumpmap/BumpMapPlugin.cpp      |    28 +
 src/osgEarthDrivers/bumpmap/BumpMapShaders         |    39 +
 src/osgEarthDrivers/bumpmap/BumpMapShaders.cpp.in  |    19 +
 src/osgEarthDrivers/bumpmap/BumpMapTerrainEffect   |    86 +
 .../bumpmap/BumpMapTerrainEffect.cpp               |   146 +
 src/osgEarthDrivers/bumpmap/CMakeLists.txt         |    43 +
 .../cache_filesystem/FileSystemCache               |     2 +-
 .../cache_filesystem/FileSystemCache.cpp           |   182 +-
 src/osgEarthDrivers/cache_leveldb/LevelDBCache     |     2 +-
 src/osgEarthDrivers/cache_leveldb/LevelDBCache.cpp |    11 +-
 src/osgEarthDrivers/cache_leveldb/LevelDBCacheBin  |    58 +-
 .../cache_leveldb/LevelDBCacheBin.cpp              |    66 +-
 .../cache_leveldb/LevelDBCacheDriver.cpp           |     4 +-
 .../cache_leveldb/LevelDBCacheOptions              |     2 +-
 src/osgEarthDrivers/cache_leveldb/Tracker          |     2 +-
 src/osgEarthDrivers/cache_rocksdb/CMakeLists.txt   |    30 +
 src/osgEarthDrivers/cache_rocksdb/RocksDBCache     |    77 +
 src/osgEarthDrivers/cache_rocksdb/RocksDBCache.cpp |   258 +
 src/osgEarthDrivers/cache_rocksdb/RocksDBCacheBin  |   144 +
 .../cache_rocksdb/RocksDBCacheBin.cpp              |   688 +
 .../cache_rocksdb/RocksDBCacheDriver.cpp           |    57 +
 .../cache_rocksdb/RocksDBCacheOptions              |   153 +
 src/osgEarthDrivers/cache_rocksdb/Tracker          |   113 +
 src/osgEarthDrivers/colorramp/ColorRampOptions     |     2 +-
 .../colorramp/ColorRampTileSource.cpp              |    11 +-
 src/osgEarthDrivers/debug/DebugOptions             |     2 +-
 src/osgEarthDrivers/debug/DebugTileSource.cpp      |     4 +-
 src/osgEarthDrivers/detail/CMakeLists.txt          |    42 +
 src/osgEarthDrivers/detail/Detail.frag.glsl        |    15 +
 src/osgEarthDrivers/detail/Detail.vert.view.glsl   |    20 +
 src/osgEarthDrivers/detail/DetailExtension         |    73 +
 src/osgEarthDrivers/detail/DetailExtension.cpp     |    79 +
 src/osgEarthDrivers/detail/DetailOptions           |   101 +
 src/osgEarthDrivers/detail/DetailPlugin.cpp        |    56 +
 src/osgEarthDrivers/detail/DetailShaders           |    39 +
 src/osgEarthDrivers/detail/DetailShaders.cpp.in    |    15 +
 src/osgEarthDrivers/detail/DetailTerrainEffect     |    62 +
 src/osgEarthDrivers/detail/DetailTerrainEffect.cpp |   113 +
 src/osgEarthDrivers/earth/CMakeLists.txt           |     4 +-
 src/osgEarthDrivers/earth/EarthFileSerializer      |    43 +-
 src/osgEarthDrivers/earth/EarthFileSerializer1.cpp |     2 +-
 src/osgEarthDrivers/earth/EarthFileSerializer2.cpp |   514 +-
 src/osgEarthDrivers/earth/ReaderWriterOsgEarth.cpp |    92 +-
 .../engine_byo/BYOTerrainEngineDriver.cpp          |     4 +-
 .../engine_byo/BYOTerrainEngineNode                |     6 +-
 .../engine_byo/BYOTerrainEngineNode.cpp            |    10 +-
 .../engine_byo/BYOTerrainEngineOptions             |     2 +-
 src/osgEarthDrivers/engine_byo/Common              |     2 +-
 src/osgEarthDrivers/engine_mp/CMakeLists.txt       |     6 +-
 src/osgEarthDrivers/engine_mp/Common               |     2 +-
 .../engine_mp/DynamicLODScaleCallback              |     2 +-
 src/osgEarthDrivers/engine_mp/FileLocationCallback |     2 +-
 src/osgEarthDrivers/engine_mp/GeometryPool         |    92 +
 src/osgEarthDrivers/engine_mp/GeometryPool.cpp     |   254 +
 src/osgEarthDrivers/engine_mp/HeightFieldCache     |     4 +-
 src/osgEarthDrivers/engine_mp/HeightFieldCache.cpp |     8 +-
 src/osgEarthDrivers/engine_mp/KeyNodeFactory       |     2 +-
 src/osgEarthDrivers/engine_mp/KeyNodeFactory.cpp   |     2 +-
 .../engine_mp/MPEngine.NormalMap.frag.glsl         |    37 +
 .../engine_mp/MPEngine.NormalMap.vert.glsl         |    23 +
 src/osgEarthDrivers/engine_mp/MPEngine.frag.glsl   |    15 +-
 .../engine_mp/MPEngine.vert.model.glsl             |    20 +-
 .../engine_mp/MPEngine.vert.pooled.glsl            |    24 +
 .../engine_mp/MPEngine.vert.view.glsl              |    10 +-
 src/osgEarthDrivers/engine_mp/MPGeometry           |    18 +-
 src/osgEarthDrivers/engine_mp/MPGeometry.cpp       |   117 +-
 src/osgEarthDrivers/engine_mp/MPShaders            |     8 +-
 src/osgEarthDrivers/engine_mp/MPShaders.cpp.in     |    20 +-
 .../engine_mp/MPTerrainEngineDriver.cpp            |     6 +-
 src/osgEarthDrivers/engine_mp/MPTerrainEngineNode  |    19 +-
 .../engine_mp/MPTerrainEngineNode.cpp              |   457 +-
 .../engine_mp/MPTerrainEngineOptions               |    24 +-
 src/osgEarthDrivers/engine_mp/MaskGenerator        |    81 +
 src/osgEarthDrivers/engine_mp/MaskGenerator.cpp    |    29 +
 .../engine_mp/QuickReleaseGLObjects                |    94 -
 src/osgEarthDrivers/engine_mp/RenderBindings       |    70 +
 src/osgEarthDrivers/engine_mp/SingleKeyNodeFactory |    15 +-
 .../engine_mp/SingleKeyNodeFactory.cpp             |   118 +-
 src/osgEarthDrivers/engine_mp/SurfaceNode          |    53 +
 src/osgEarthDrivers/engine_mp/SurfaceNode.cpp      |     0
 src/osgEarthDrivers/engine_mp/SurfaceNodeFactory   |   130 +
 .../engine_mp/SurfaceNodeFactory.cpp               |   344 +
 src/osgEarthDrivers/engine_mp/TerrainNode          |    17 +-
 src/osgEarthDrivers/engine_mp/TerrainNode.cpp      |    62 +-
 src/osgEarthDrivers/engine_mp/TileDrawable         |   156 +
 src/osgEarthDrivers/engine_mp/TileDrawable.cpp     |   534 +
 src/osgEarthDrivers/engine_mp/TileGroup            |     7 +-
 src/osgEarthDrivers/engine_mp/TileGroup.cpp        |    18 +-
 src/osgEarthDrivers/engine_mp/TileGroupFactory     |   100 +
 src/osgEarthDrivers/engine_mp/TileGroupFactory.cpp |   383 +
 src/osgEarthDrivers/engine_mp/TileModel            |    16 +-
 src/osgEarthDrivers/engine_mp/TileModel.cpp        |    55 +-
 src/osgEarthDrivers/engine_mp/TileModelCompiler    |     2 +-
 .../engine_mp/TileModelCompiler.cpp                |   116 +-
 src/osgEarthDrivers/engine_mp/TileModelFactory     |     5 +-
 src/osgEarthDrivers/engine_mp/TileModelFactory.cpp |     9 +-
 src/osgEarthDrivers/engine_mp/TileNode             |    13 +-
 src/osgEarthDrivers/engine_mp/TileNode.cpp         |    37 +-
 src/osgEarthDrivers/engine_mp/TileNodeRegistry     |    34 +-
 src/osgEarthDrivers/engine_mp/TileNodeRegistry.cpp |   125 +-
 src/osgEarthDrivers/engine_mp/TilePagedLOD         |    10 +-
 src/osgEarthDrivers/engine_mp/TilePagedLOD.cpp     |    87 +-
 src/osgEarthDrivers/engine_rex/CMakeLists.txt      |    69 +
 src/osgEarthDrivers/engine_rex/Common              |    24 +
 .../engine_rex/ElevationTextureUtils               |    73 +
 .../engine_rex/ElevationTextureUtils.cpp           |   119 +
 src/osgEarthDrivers/engine_rex/EngineContext       |   135 +
 src/osgEarthDrivers/engine_rex/EngineContext.cpp   |   232 +
 src/osgEarthDrivers/engine_rex/GeometryPool        |   138 +
 src/osgEarthDrivers/engine_rex/GeometryPool.cpp    |   421 +
 src/osgEarthDrivers/engine_rex/LoadTileData        |    51 +
 src/osgEarthDrivers/engine_rex/LoadTileData.cpp    |   268 +
 src/osgEarthDrivers/engine_rex/Loader              |   227 +
 src/osgEarthDrivers/engine_rex/Loader.cpp          |   483 +
 src/osgEarthDrivers/engine_rex/MPTexture           |   106 +
 src/osgEarthDrivers/engine_rex/MPTexture.cpp       |   171 +
 src/osgEarthDrivers/engine_rex/MaskGenerator       |   102 +
 src/osgEarthDrivers/engine_rex/MaskGenerator.cpp   |   532 +
 src/osgEarthDrivers/engine_rex/ProxyGeometry       |    75 +
 src/osgEarthDrivers/engine_rex/ProxyGeometry.cpp   |   234 +
 src/osgEarthDrivers/engine_rex/ProxySurfaceNode    |    58 +
 .../engine_rex/ProxySurfaceNode.cpp                |    55 +
 src/osgEarthDrivers/engine_rex/RenderBindings      |    97 +
 .../engine_rex/RexEngine.Morphing.vert.glsl        |    87 +
 .../engine_rex/RexEngine.NormalMap.frag.glsl       |    37 +
 .../engine_rex/RexEngine.NormalMap.vert.glsl       |    22 +
 .../engine_rex/RexEngine.SDK.vert.glsl             |    79 +
 src/osgEarthDrivers/engine_rex/RexEngine.frag.glsl |    84 +
 src/osgEarthDrivers/engine_rex/RexEngine.gs.glsl   |    43 +
 src/osgEarthDrivers/engine_rex/RexEngine.tcs.glsl  |     3 +
 src/osgEarthDrivers/engine_rex/RexEngine.tes.glsl  |    10 +
 src/osgEarthDrivers/engine_rex/RexEngine.vert.glsl |    35 +
 .../engine_rex/RexEngine.vert.view.glsl            |    65 +
 .../engine_rex/RexTerrainEngineDriver.cpp          |    72 +
 .../engine_rex/RexTerrainEngineNode                |   192 +
 .../engine_rex/RexTerrainEngineNode.cpp            |  1070 +
 .../engine_rex/RexTerrainEngineOptions             |   163 +
 src/osgEarthDrivers/engine_rex/SelectionInfo       |    77 +
 src/osgEarthDrivers/engine_rex/SelectionInfo.cpp   |   120 +
 src/osgEarthDrivers/engine_rex/Shaders             |    39 +
 src/osgEarthDrivers/engine_rex/Shaders.cpp.in      |    32 +
 src/osgEarthDrivers/engine_rex/SurfaceNode         |   124 +
 src/osgEarthDrivers/engine_rex/SurfaceNode.cpp     |   418 +
 src/osgEarthDrivers/engine_rex/TileDrawable        |   166 +
 src/osgEarthDrivers/engine_rex/TileDrawable.cpp    |   689 +
 src/osgEarthDrivers/engine_rex/TileNode            |   175 +
 src/osgEarthDrivers/engine_rex/TileNode.cpp        |   732 +
 src/osgEarthDrivers/engine_rex/TileNodeRegistry    |   239 +
 .../engine_rex/TileNodeRegistry.cpp                |   278 +
 src/osgEarthDrivers/engine_rex/Unloader            |    73 +
 src/osgEarthDrivers/engine_rex/Unloader.cpp        |   124 +
 src/osgEarthDrivers/fastdxt/CMakeLists.txt         |     6 +-
 .../feature_elevation/FeatureElevationOptions      |    12 +-
 .../ReaderWriterFeatureElevation.cpp               |   249 +-
 .../feature_mapnikvectortiles/CMakeLists.txt       |    25 +
 .../feature_mapnikvectortiles/FeatureSourceMVT.cpp |   315 +
 .../feature_mapnikvectortiles/MVTFeatureOptions    |    76 +
 src/osgEarthDrivers/feature_ogr/FeatureCursorOGR   |     3 +-
 .../feature_ogr/FeatureCursorOGR.cpp               |   144 +-
 .../feature_ogr/FeatureSourceOGR.cpp               |   266 +-
 src/osgEarthDrivers/feature_ogr/OGRFeatureOptions  |     2 +-
 .../feature_raster/FeatureSourceRaster.cpp         |    50 +-
 .../feature_tfs/FeatureSourceTFS.cpp               |   222 +-
 src/osgEarthDrivers/feature_tfs/TFSFeatureOptions  |    22 +-
 .../feature_wfs/FeatureSourceWFS.cpp               |   174 +-
 src/osgEarthDrivers/feature_wfs/WFSFeatureOptions  |     2 +-
 .../featurefilter_intersect/CMakeLists.txt         |    15 +
 .../IntersectFeatureFilter.cpp                     |   196 +
 .../IntersectFeatureFilterOptions                  |    78 +
 .../featurefilter_join/CMakeLists.txt              |    15 +
 .../featurefilter_join/JoinFeatureFilter.cpp       |   160 +
 .../featurefilter_join/JoinFeatureFilterOptions    |    67 +
 src/osgEarthDrivers/gdal/GDALOptions               |     2 +-
 src/osgEarthDrivers/gdal/ReaderWriterGDAL.cpp      |   179 +-
 src/osgEarthDrivers/kml/CMakeLists.txt             |    10 +-
 src/osgEarthDrivers/kml/KML                        |    24 +-
 src/osgEarthDrivers/kml/KMLOptions                 |     2 +-
 src/osgEarthDrivers/kml/KMLReader                  |     2 +-
 src/osgEarthDrivers/kml/KMLReader.cpp              |    12 +-
 src/osgEarthDrivers/kml/KML_Common                 |    17 +-
 src/osgEarthDrivers/kml/KML_Container              |     2 +-
 src/osgEarthDrivers/kml/KML_Document               |     2 +-
 src/osgEarthDrivers/kml/KML_Document.cpp           |     2 +-
 src/osgEarthDrivers/kml/KML_Feature                |     2 +-
 src/osgEarthDrivers/kml/KML_Feature.cpp            |    27 +-
 src/osgEarthDrivers/kml/KML_Folder                 |     2 +-
 src/osgEarthDrivers/kml/KML_Folder.cpp             |     2 +-
 src/osgEarthDrivers/kml/KML_Geometry               |     2 +-
 src/osgEarthDrivers/kml/KML_Geometry.cpp           |    14 +-
 src/osgEarthDrivers/kml/KML_GroundOverlay          |     2 +-
 src/osgEarthDrivers/kml/KML_GroundOverlay.cpp      |     2 +-
 src/osgEarthDrivers/kml/KML_IconStyle              |     2 +-
 src/osgEarthDrivers/kml/KML_IconStyle.cpp          |    14 +-
 src/osgEarthDrivers/kml/KML_LabelStyle             |     2 +-
 src/osgEarthDrivers/kml/KML_LabelStyle.cpp         |     2 +-
 src/osgEarthDrivers/kml/KML_LineString             |     2 +-
 src/osgEarthDrivers/kml/KML_LineString.cpp         |     2 +-
 src/osgEarthDrivers/kml/KML_LineStyle              |     2 +-
 src/osgEarthDrivers/kml/KML_LineStyle.cpp          |     7 +-
 src/osgEarthDrivers/kml/KML_LinearRing             |     2 +-
 src/osgEarthDrivers/kml/KML_LinearRing.cpp         |     2 +-
 src/osgEarthDrivers/kml/KML_Model                  |     2 +-
 src/osgEarthDrivers/kml/KML_Model.cpp              |     2 +-
 src/osgEarthDrivers/kml/KML_MultiGeometry          |     2 +-
 src/osgEarthDrivers/kml/KML_MultiGeometry.cpp      |     2 +-
 src/osgEarthDrivers/kml/KML_NetworkLink.cpp        |     7 +-
 src/osgEarthDrivers/kml/KML_NetworkLinkControl     |     2 +-
 src/osgEarthDrivers/kml/KML_NetworkLinkControl.cpp |     2 +-
 src/osgEarthDrivers/kml/KML_Object                 |     2 +-
 src/osgEarthDrivers/kml/KML_Object.cpp             |     2 +-
 src/osgEarthDrivers/kml/KML_Overlay                |     2 +-
 src/osgEarthDrivers/kml/KML_Overlay.cpp            |     2 +-
 src/osgEarthDrivers/kml/KML_PhotoOverlay           |     2 +-
 src/osgEarthDrivers/kml/KML_PhotoOverlay.cpp       |     2 +-
 src/osgEarthDrivers/kml/KML_Placemark.cpp          |    78 +-
 src/osgEarthDrivers/kml/KML_Point                  |     2 +-
 src/osgEarthDrivers/kml/KML_Point.cpp              |     2 +-
 src/osgEarthDrivers/kml/KML_PolyStyle              |     2 +-
 src/osgEarthDrivers/kml/KML_PolyStyle.cpp          |     2 +-
 src/osgEarthDrivers/kml/KML_Polygon                |     2 +-
 src/osgEarthDrivers/kml/KML_Polygon.cpp            |     6 +-
 src/osgEarthDrivers/kml/KML_Root                   |     2 +-
 src/osgEarthDrivers/kml/KML_Root.cpp               |     2 +-
 src/osgEarthDrivers/kml/KML_Schema                 |     2 +-
 src/osgEarthDrivers/kml/KML_Schema.cpp             |     2 +-
 src/osgEarthDrivers/kml/KML_ScreenOverlay          |     2 +-
 src/osgEarthDrivers/kml/KML_ScreenOverlay.cpp      |     2 +-
 src/osgEarthDrivers/kml/KML_Style                  |     2 +-
 src/osgEarthDrivers/kml/KML_Style.cpp              |     2 +-
 src/osgEarthDrivers/kml/KML_StyleMap               |     2 +-
 src/osgEarthDrivers/kml/KML_StyleMap.cpp           |     2 +-
 src/osgEarthDrivers/kml/KML_StyleSelector          |     2 +-
 src/osgEarthDrivers/kml/KMZArchive                 |    20 +-
 src/osgEarthDrivers/kml/KMZArchive.cpp             |   238 +-
 src/osgEarthDrivers/kml/ReaderWriterKML.cpp        |    37 +-
 src/osgEarthDrivers/kml/rapidxml_ext.hpp           |    15 +-
 .../label_annotation/AnnotationLabelSource.cpp     |    37 +-
 src/osgEarthDrivers/mapinspector/CMakeLists.txt    |    26 +
 .../mapinspector/MapInspectorExtension             |    84 +
 .../mapinspector/MapInspectorExtension.cpp         |   116 +
 src/osgEarthDrivers/mapinspector/MapInspectorUI    |    49 +
 .../mapinspector/MapInspectorUI.cpp                |   162 +
 .../mask_feature/FeatureMaskOptions                |     2 +-
 .../mask_feature/FeatureMaskSource.cpp             |    40 +-
 src/osgEarthDrivers/mbtiles/MBTilesPlugin.cpp      |     2 +-
 src/osgEarthDrivers/mbtiles/MBTilesTileSource.cpp  |    99 +-
 .../model_feature_geom/FeatureGeomModelOptions     |     2 +-
 .../model_feature_geom/FeatureGeomModelSource.cpp  |    13 +-
 .../FeatureStencilModelSource.cpp                  |   380 -
 .../model_simple/SimpleModelOptions                |     2 +-
 .../model_simple/SimpleModelSource.cpp             |    11 +-
 src/osgEarthDrivers/monitor/CMakeLists.txt         |    28 +
 src/osgEarthDrivers/monitor/MonitorExtension       |    82 +
 src/osgEarthDrivers/monitor/MonitorExtension.cpp   |   127 +
 src/osgEarthDrivers/monitor/MonitorPlugin.cpp      |    55 +
 src/osgEarthDrivers/monitor/MonitorUI              |    46 +
 src/osgEarthDrivers/monitor/MonitorUI.cpp          |    69 +
 src/osgEarthDrivers/noise/CMakeLists.txt           |    24 +
 src/osgEarthDrivers/noise/NoiseExtension           |    74 +
 src/osgEarthDrivers/noise/NoiseExtension.cpp       |    80 +
 src/osgEarthDrivers/noise/NoiseOptions             |    82 +
 src/osgEarthDrivers/noise/NoiseTerrainEffect       |    65 +
 src/osgEarthDrivers/noise/NoiseTerrainEffect.cpp   |   167 +
 src/osgEarthDrivers/ocean_simple/CMakeLists.txt    |    31 +-
 .../ocean_simple/ElevationProxyImageLayer          |     6 +-
 .../ocean_simple/ElevationProxyImageLayer.cpp      |     8 +-
 src/osgEarthDrivers/ocean_simple/Shaders.cpp.in    |    14 +
 .../ocean_simple/SimpleOcean.FS.glsl               |   114 +
 .../ocean_simple/SimpleOcean.VS.glsl               |   102 +
 .../ocean_simple/SimpleOceanDriver.cpp             |   146 +-
 src/osgEarthDrivers/ocean_simple/SimpleOceanNode   |    16 +-
 .../ocean_simple/SimpleOceanNode.cpp               |   117 +-
 .../ocean_simple/SimpleOceanOptions                |    17 +-
 .../ocean_simple/SimpleOceanShaders                |   297 +-
 src/osgEarthDrivers/ocean_triton/CMakeLists.txt    |    15 +-
 src/osgEarthDrivers/ocean_triton/TritonContext     |    85 -
 src/osgEarthDrivers/ocean_triton/TritonContext.cpp |   141 -
 src/osgEarthDrivers/ocean_triton/TritonDrawable    |    85 -
 .../ocean_triton/TritonDrawable.cpp                |   558 -
 src/osgEarthDrivers/ocean_triton/TritonDriver.cpp  |    90 +-
 src/osgEarthDrivers/ocean_triton/TritonNode        |    61 -
 src/osgEarthDrivers/ocean_triton/TritonNode.cpp    |    84 -
 src/osgEarthDrivers/ocean_triton/TritonOptions     |    83 -
 src/osgEarthDrivers/osg/OSGOptions                 |     2 +-
 src/osgEarthDrivers/osg/OSGTileSource.cpp          |     8 +-
 src/osgEarthDrivers/quadkey/QuadKeyOptions         |     2 +-
 .../quadkey/ReaderWriterQuadKey.cpp                |     8 +-
 .../refresh/ReaderWriterRefresh.cpp                |     4 +-
 src/osgEarthDrivers/refresh/RefreshOptions         |     2 +-
 .../script_engine_duktape/CMakeLists.txt           |     1 +
 .../script_engine_duktape/DuktapeEngine            |     5 +-
 .../script_engine_duktape/DuktapeEngine.cpp        |   107 +-
 .../script_engine_duktape/JSGeometry               |     4 +-
 .../script_engine_duktape/Plugin.cpp               |     6 +-
 .../script_engine_duktape/duk_config.h             |  3643 +
 .../script_engine_duktape/duktape.c                | 71505 ++++++++++++-------
 .../script_engine_duktape/duktape.h                |  3472 +-
 src/osgEarthDrivers/sky_gl/CMakeLists.txt          |     1 +
 src/osgEarthDrivers/sky_gl/GLSkyDriver.cpp         |    62 -
 src/osgEarthDrivers/sky_gl/GLSkyExtension.cpp      |   153 +
 src/osgEarthDrivers/sky_gl/GLSkyNode               |     6 +-
 src/osgEarthDrivers/sky_gl/GLSkyNode.cpp           |     4 +-
 src/osgEarthDrivers/sky_gl/GLSkyOptions            |     6 +-
 src/osgEarthDrivers/sky_gl/GLSkyShaders            |    14 +-
 .../sky_silverlining/CMakeLists.txt                |    13 +-
 .../sky_silverlining/SilverLiningCloudsDrawable    |    64 -
 .../SilverLiningCloudsDrawable.cpp                 |    83 -
 .../sky_silverlining/SilverLiningContext           |   108 -
 .../sky_silverlining/SilverLiningContext.cpp       |   242 -
 .../sky_silverlining/SilverLiningDriver.cpp        |   130 +-
 .../sky_silverlining/SilverLiningNode              |    69 -
 .../sky_silverlining/SilverLiningNode.cpp          |   176 -
 .../sky_silverlining/SilverLiningOptions           |   101 -
 .../sky_silverlining/SilverLiningSkyDrawable       |    56 -
 .../sky_silverlining/SilverLiningSkyDrawable.cpp   |   110 -
 src/osgEarthDrivers/sky_simple/CMakeLists.txt      |     2 +-
 .../sky_simple/SimpleSky.Atmosphere.frag.glsl      |     6 +-
 .../sky_simple/SimpleSky.Atmosphere.vert.glsl      |     6 +-
 .../sky_simple/SimpleSky.Ground.ONeil.frag.glsl    |    18 +-
 .../sky_simple/SimpleSky.Ground.ONeil.vert.glsl    |    10 +-
 .../sky_simple/SimpleSky.Stars.frag.glsl           |     6 +-
 .../sky_simple/SimpleSky.Stars.vert.glsl           |     6 +-
 src/osgEarthDrivers/sky_simple/SimpleSkyDriver.cpp |    63 -
 .../sky_simple/SimpleSkyExtension.cpp              |   124 +
 src/osgEarthDrivers/sky_simple/SimpleSkyNode       |     7 +-
 src/osgEarthDrivers/sky_simple/SimpleSkyNode.cpp   |    22 +-
 src/osgEarthDrivers/sky_simple/SimpleSkyOptions    |     8 +-
 src/osgEarthDrivers/sky_simple/SimpleSkyShaders    |     6 +-
 .../sky_simple/SimpleSkyShaders.cpp.in             |    26 +-
 src/osgEarthDrivers/skyview/CMakeLists.txt         |    15 +
 src/osgEarthDrivers/skyview/SkyViewOptions         |    71 +
 src/osgEarthDrivers/skyview/SkyViewTileSource.cpp  |   130 +
 src/osgEarthDrivers/splat_mask/SplatMaskDriver.cpp |     6 +-
 src/osgEarthDrivers/splat_mask/SplatMaskOptions    |     2 +-
 src/osgEarthDrivers/template/CMakeLists.txt        |    11 +
 src/osgEarthDrivers/template/NLTemplate.cpp        |   491 +
 src/osgEarthDrivers/template/NLTemplate.h          |   179 +
 .../template/NL_Template_LICENSE.txt               |    20 +
 .../template/ReaderWriterTemplate.cpp              |   101 +
 .../template_matclass/TemplateMatClassDriver.cpp   |    16 +-
 .../template_matclass/TemplateMatClassOptions      |     2 +-
 src/osgEarthDrivers/terrainshader/CMakeLists.txt   |    23 +
 .../terrainshader/TerrainShaderExtension           |    70 +
 .../terrainshader/TerrainShaderExtension.cpp       |   228 +
 .../terrainshader/TerrainShaderOptions             |   177 +
 .../tilecache/ReaderWriterTileCache.cpp            |     4 +-
 src/osgEarthDrivers/tilecache/TileCacheOptions     |     2 +-
 .../tileindex/ReaderWriterTileIndex.cpp            |     6 +-
 src/osgEarthDrivers/tileindex/TileIndexOptions     |     2 +-
 .../tileservice/ReaderWriterTileService.cpp        |     4 +-
 src/osgEarthDrivers/tileservice/TileServiceOptions |     2 +-
 src/osgEarthDrivers/tms/TMSOptions                 |    14 +-
 src/osgEarthDrivers/tms/TMSPlugin.cpp              |     4 +-
 src/osgEarthDrivers/tms/TMSTileSource              |     2 +-
 src/osgEarthDrivers/tms/TMSTileSource.cpp          |    25 +-
 src/osgEarthDrivers/vdatum_egm2008/EGM2008.cpp     |     4 +-
 src/osgEarthDrivers/vdatum_egm2008/EGM2008Grid.h   |     2 +-
 src/osgEarthDrivers/vdatum_egm84/EGM84.cpp         |     4 +-
 src/osgEarthDrivers/vdatum_egm84/EGM84Grid.h       |     2 +-
 src/osgEarthDrivers/vdatum_egm96/EGM96.cpp         |     4 +-
 src/osgEarthDrivers/vdatum_egm96/EGM96Grid.h       | 53253 +++++++-------
 src/osgEarthDrivers/viewpoints/CMakeLists.txt      |    24 +
 src/osgEarthDrivers/viewpoints/ViewpointsExtension |    86 +
 .../viewpoints/ViewpointsExtension.cpp             |   244 +
 .../viewpoints/ViewpointsPlugin.cpp                |    55 +
 src/osgEarthDrivers/vpb/ReaderWriterVPB.cpp        |     4 +-
 src/osgEarthDrivers/vpb/VPBOptions                 |     2 +-
 src/osgEarthDrivers/wcs/CMakeLists.txt             |     4 +-
 src/osgEarthDrivers/wcs/ReaderWriterWCS.cpp        |     4 +-
 src/osgEarthDrivers/wcs/WCS11Source.cpp            |     4 +-
 src/osgEarthDrivers/wcs/WCS11Source.h              |     2 +-
 src/osgEarthDrivers/wcs/WCSOptions                 |     2 +-
 src/osgEarthDrivers/wms/ReaderWriterWMS.cpp        |     8 +-
 src/osgEarthDrivers/wms/TileService                |     2 +-
 src/osgEarthDrivers/wms/TileService.cpp            |     2 +-
 src/osgEarthDrivers/wms/WMSOptions                 |     2 +-
 src/osgEarthDrivers/xyz/ReaderWriterXYZ.cpp        |    10 +-
 src/osgEarthDrivers/xyz/XYZOptions                 |     2 +-
 src/osgEarthDrivers/yahoo/ReaderWriterYahoo.cpp    |    22 +-
 src/osgEarthDrivers/yahoo/YahooOptions             |     2 +-
 src/osgEarthDriversDisabled/geobuf/CMakeLists.txt  |    22 +
 .../geobuf/ReaderWriterGeobuf.cpp                  |    90 +
 src/osgEarthDriversDisabled/geobuf/geobuf.proto    |    66 +
 .../model_feature_stencil/CMakeLists.txt           |     0
 .../FeatureStencilModelOptions                     |     0
 .../FeatureStencilModelSource.cpp                  |   380 +
 .../model_feature_stencil/StencilUtils.cpp         |     0
 .../model_feature_stencil/StencilUtils.h           |     0
 .../billboard/BillboardExtension                   |    71 -
 .../billboard/BillboardExtension.cpp               |   288 -
 src/osgEarthExtensions/billboard/BillboardOptions  |   111 -
 .../billboard/BillboardPlugin.cpp                  |    56 -
 src/osgEarthExtensions/billboard/BillboardShaders  |   106 -
 src/osgEarthExtensions/billboard/CMakeLists.txt    |    27 -
 .../bumpmap/BumpMap.frag.common.glsl               |    26 -
 .../bumpmap/BumpMap.frag.progressive.glsl          |    56 -
 .../bumpmap/BumpMap.frag.simple.glsl               |    23 -
 .../bumpmap/BumpMap.vert.model.glsl                |    60 -
 .../bumpmap/BumpMap.vert.view.glsl                 |    12 -
 src/osgEarthExtensions/bumpmap/BumpMapExtension    |    73 -
 .../bumpmap/BumpMapExtension.cpp                   |    98 -
 src/osgEarthExtensions/bumpmap/BumpMapOptions      |   110 -
 src/osgEarthExtensions/bumpmap/BumpMapPlugin.cpp   |    56 -
 src/osgEarthExtensions/bumpmap/BumpMapShaders      |    39 -
 .../bumpmap/BumpMapShaders.cpp.in                  |    24 -
 .../bumpmap/BumpMapTerrainEffect                   |    82 -
 .../bumpmap/BumpMapTerrainEffect.cpp               |   140 -
 src/osgEarthExtensions/bumpmap/CMakeLists.txt      |    46 -
 src/osgEarthExtensions/mapinspector/CMakeLists.txt |    27 -
 .../mapinspector/MapInspectorExtension             |    84 -
 .../mapinspector/MapInspectorExtension.cpp         |   112 -
 .../mapinspector/MapInspectorPlugin.cpp            |    55 -
 src/osgEarthExtensions/mapinspector/MapInspectorUI |    49 -
 .../mapinspector/MapInspectorUI.cpp                |   162 -
 src/osgEarthExtensions/noise/CMakeLists.txt        |    25 -
 src/osgEarthExtensions/noise/NoiseExtension        |    73 -
 src/osgEarthExtensions/noise/NoiseExtension.cpp    |    78 -
 src/osgEarthExtensions/noise/NoiseOptions          |    68 -
 src/osgEarthExtensions/noise/NoisePlugin.cpp       |    56 -
 src/osgEarthExtensions/noise/NoiseTerrainEffect    |    62 -
 .../noise/NoiseTerrainEffect.cpp                   |   166 -
 src/osgEarthExtensions/normalmap/CMakeLists.txt    |    43 -
 .../normalmap/NormalMap.frag.glsl                  |    27 -
 .../normalmap/NormalMap.vert.glsl                  |    25 -
 .../normalmap/NormalMapExtension                   |    73 -
 .../normalmap/NormalMapExtension.cpp               |    80 -
 src/osgEarthExtensions/normalmap/NormalMapOptions  |    72 -
 .../normalmap/NormalMapPlugin.cpp                  |    56 -
 src/osgEarthExtensions/normalmap/NormalMapShaders  |    33 -
 .../normalmap/NormalMapShaders.cpp.in              |    14 -
 .../normalmap/NormalMapTerrainEffect               |    64 -
 .../normalmap/NormalMapTerrainEffect.cpp           |   136 -
 src/osgEarthExtensions/splat/Biome                 |    83 -
 src/osgEarthExtensions/splat/Biome.cpp             |    73 -
 src/osgEarthExtensions/splat/BiomeSelector         |    53 -
 src/osgEarthExtensions/splat/BiomeSelector.cpp     |   143 -
 src/osgEarthExtensions/splat/CMakeLists.txt        |    60 -
 src/osgEarthExtensions/splat/LandUseTileSource     |   180 -
 src/osgEarthExtensions/splat/LandUseTileSource.cpp |   283 -
 .../splat/Splat.frag.common.glsl                   |    29 -
 .../splat/Splat.frag.getRenderInfo.glsl            |    18 -
 src/osgEarthExtensions/splat/Splat.frag.glsl       |   275 -
 src/osgEarthExtensions/splat/Splat.types.glsl      |    21 -
 src/osgEarthExtensions/splat/Splat.util.glsl       |    64 -
 src/osgEarthExtensions/splat/Splat.vert.model.glsl |    14 -
 src/osgEarthExtensions/splat/Splat.vert.view.glsl  |    24 -
 src/osgEarthExtensions/splat/SplatCatalog          |   178 -
 src/osgEarthExtensions/splat/SplatCatalog.cpp      |   389 -
 src/osgEarthExtensions/splat/SplatCoverageLegend   |   108 -
 .../splat/SplatCoverageLegend.cpp                  |    78 -
 src/osgEarthExtensions/splat/SplatExport           |    63 -
 src/osgEarthExtensions/splat/SplatExtension        |    83 -
 src/osgEarthExtensions/splat/SplatExtension.cpp    |   239 -
 src/osgEarthExtensions/splat/SplatOptions          |   151 -
 src/osgEarthExtensions/splat/SplatPlugin.cpp       |    56 -
 src/osgEarthExtensions/splat/SplatShaders          |    46 -
 src/osgEarthExtensions/splat/SplatShaders.cpp.in   |    34 -
 src/osgEarthExtensions/splat/SplatTerrainEffect    |   138 -
 .../splat/SplatTerrainEffect.cpp                   |   513 -
 .../terrainshader/CMakeLists.txt                   |    24 -
 .../terrainshader/TerrainShaderExtension           |    68 -
 .../terrainshader/TerrainShaderExtension.cpp       |   121 -
 .../terrainshader/TerrainShaderOptions             |    87 -
 .../terrainshader/TerrainShaderPlugin.cpp          |    56 -
 src/osgEarthExtensions/viewpoints/CMakeLists.txt   |    24 -
 .../viewpoints/ViewpointsExtension                 |    83 -
 .../viewpoints/ViewpointsExtension.cpp             |   242 -
 .../viewpoints/ViewpointsPlugin.cpp                |    55 -
 src/osgEarthFeatures/AltitudeFilter                |     2 +-
 src/osgEarthFeatures/AltitudeFilter.cpp            |   149 +-
 src/osgEarthFeatures/BufferFilter                  |     2 +-
 src/osgEarthFeatures/BufferFilter.cpp              |     2 +-
 src/osgEarthFeatures/BuildGeometryFilter           |    11 +-
 src/osgEarthFeatures/BuildGeometryFilter.cpp       |   487 +-
 src/osgEarthFeatures/BuildTextFilter               |     2 +-
 src/osgEarthFeatures/BuildTextFilter.cpp           |     2 +-
 src/osgEarthFeatures/BuildTextOperator             |    54 -
 src/osgEarthFeatures/BuildTextOperator.cpp         |   241 -
 src/osgEarthFeatures/CMakeLists.txt                |    53 +-
 src/osgEarthFeatures/CentroidFilter                |     2 +-
 src/osgEarthFeatures/CentroidFilter.cpp            |     2 +-
 src/osgEarthFeatures/Common                        |     2 +-
 src/osgEarthFeatures/ConvertTypeFilter             |     2 +-
 src/osgEarthFeatures/ConvertTypeFilter.cpp         |     2 +-
 src/osgEarthFeatures/CropFilter                    |     2 +-
 src/osgEarthFeatures/CropFilter.cpp                |     2 +-
 src/osgEarthFeatures/ExtrudeGeometryFilter         |    22 +-
 src/osgEarthFeatures/ExtrudeGeometryFilter.cpp     |    35 +-
 src/osgEarthFeatures/Feature                       |    15 +-
 src/osgEarthFeatures/Feature.cpp                   |    89 +-
 src/osgEarthFeatures/FeatureCursor                 |     4 +-
 src/osgEarthFeatures/FeatureCursor.cpp             |    17 +-
 src/osgEarthFeatures/FeatureDisplayLayout          |    14 +-
 src/osgEarthFeatures/FeatureDisplayLayout.cpp      |     7 +-
 src/osgEarthFeatures/FeatureDrawSet                |     2 +-
 src/osgEarthFeatures/FeatureDrawSet.cpp            |     2 +-
 src/osgEarthFeatures/FeatureIndex                  |     5 +-
 src/osgEarthFeatures/FeatureListSource             |     5 +-
 src/osgEarthFeatures/FeatureListSource.cpp         |     5 +-
 src/osgEarthFeatures/FeatureModelGraph             |    76 +-
 src/osgEarthFeatures/FeatureModelGraph.cpp         |   574 +-
 src/osgEarthFeatures/FeatureModelSource            |    29 +-
 src/osgEarthFeatures/FeatureModelSource.cpp        |    98 +-
 src/osgEarthFeatures/FeatureSource                 |    72 +-
 src/osgEarthFeatures/FeatureSource.cpp             |   126 +-
 src/osgEarthFeatures/FeatureSourceIndexNode        |    47 +-
 src/osgEarthFeatures/FeatureSourceIndexNode.cpp    |   284 +-
 src/osgEarthFeatures/FeatureTileSource             |     8 +-
 src/osgEarthFeatures/FeatureTileSource.cpp         |   207 +-
 src/osgEarthFeatures/Filter                        |    32 +-
 src/osgEarthFeatures/Filter.cpp                    |    57 +-
 src/osgEarthFeatures/FilterContext                 |     2 +-
 src/osgEarthFeatures/FilterContext.cpp             |     4 +-
 src/osgEarthFeatures/GeometryCompiler              |    19 +-
 src/osgEarthFeatures/GeometryCompiler.cpp          |    47 +-
 src/osgEarthFeatures/GeometryUtils                 |     2 +-
 src/osgEarthFeatures/GeometryUtils.cpp             |     4 +-
 src/osgEarthFeatures/LabelSource                   |     2 +-
 src/osgEarthFeatures/LabelSource.cpp               |     6 +-
 src/osgEarthFeatures/MVT                           |    40 +
 src/osgEarthFeatures/MVT.cpp                       |   242 +
 src/osgEarthFeatures/MarkerFactory                 |    71 -
 src/osgEarthFeatures/MarkerFactory.cpp             |   208 -
 src/osgEarthFeatures/MeshClamper                   |    88 -
 src/osgEarthFeatures/MeshClamper.cpp               |   207 -
 src/osgEarthFeatures/OgrUtils                      |     2 +-
 src/osgEarthFeatures/OgrUtils.cpp                  |    15 +-
 src/osgEarthFeatures/OptimizerHints                |     2 +-
 src/osgEarthFeatures/OptimizerHints.cpp            |     2 +-
 src/osgEarthFeatures/PolygonizeLines               |     4 +-
 src/osgEarthFeatures/PolygonizeLines.cpp           |     8 +-
 src/osgEarthFeatures/ResampleFilter                |    89 +-
 src/osgEarthFeatures/ResampleFilter.cpp            |    52 +-
 src/osgEarthFeatures/ScaleFilter                   |     2 +-
 src/osgEarthFeatures/ScaleFilter.cpp               |     2 +-
 src/osgEarthFeatures/ScatterFilter                 |     3 +-
 src/osgEarthFeatures/ScatterFilter.cpp             |    14 +-
 src/osgEarthFeatures/Script                        |     8 +-
 src/osgEarthFeatures/ScriptEngine                  |    13 +-
 src/osgEarthFeatures/ScriptEngine.cpp              |    19 +-
 src/osgEarthFeatures/ScriptFilter                  |   105 +
 src/osgEarthFeatures/ScriptFilter.cpp              |   104 +
 src/osgEarthFeatures/Session                       |     2 +-
 src/osgEarthFeatures/Session.cpp                   |    14 +-
 src/osgEarthFeatures/SubstituteModelFilter         |     2 +-
 src/osgEarthFeatures/SubstituteModelFilter.cpp     |   106 +-
 src/osgEarthFeatures/TessellateOperator            |     2 +-
 src/osgEarthFeatures/TessellateOperator.cpp        |     2 +-
 src/osgEarthFeatures/TextSymbolizer                |     2 +-
 src/osgEarthFeatures/TextSymbolizer.cpp            |     2 +-
 src/osgEarthFeatures/TransformFilter               |     2 +-
 src/osgEarthFeatures/TransformFilter.cpp           |     2 +-
 src/osgEarthFeatures/VirtualFeatureSource          |    11 +-
 src/osgEarthFeatures/VirtualFeatureSource.cpp      |    18 +-
 src/osgEarthFeatures/vector_tile.proto             |    92 +
 src/osgEarthProcedural/CMakeLists.txt              |    67 +
 src/osgEarthProcedural/Common                      |    32 +
 src/osgEarthProcedural/CoverageLegend              |    99 +
 src/osgEarthProcedural/CoverageLegend.cpp          |    77 +
 src/osgEarthProcedural/Export                      |    74 +
 src/osgEarthProcedural/Shaders                     |    31 +
 src/osgEarthProcedural/Shaders.cpp.in              |     9 +
 src/osgEarthProcedural/SimplexNoise                |   159 +
 src/osgEarthProcedural/SimplexNoise.cpp            |   556 +
 src/osgEarthProcedural/SplatCatalog                |   161 +
 src/osgEarthProcedural/SplatCatalog.cpp            |   343 +
 src/osgEarthQt/Actions                             |     2 +-
 src/osgEarthQt/AnnotationListWidget.cpp            |    12 +-
 src/osgEarthQt/CMakeLists.txt                      |   213 +-
 src/osgEarthQt/CollapsiblePairWidget               |     2 +-
 src/osgEarthQt/CollapsiblePairWidget.cpp           |     2 +-
 src/osgEarthQt/Common                              |     2 +-
 src/osgEarthQt/DataManager                         |     2 +-
 src/osgEarthQt/DataManager.cpp                     |    12 +-
 src/osgEarthQt/GuiActions                          |     2 +-
 src/osgEarthQt/LOSControlWidget                    |     2 +-
 src/osgEarthQt/LOSControlWidget.cpp                |     2 +-
 src/osgEarthQt/LOSCreationDialog                   |     2 +-
 src/osgEarthQt/LOSCreationDialog.cpp               |    12 +-
 src/osgEarthQt/LayerManagerWidget                  |     2 +-
 src/osgEarthQt/LayerManagerWidget.cpp              |     4 +-
 src/osgEarthQt/MapCatalogWidget                    |     2 +-
 src/osgEarthQt/MapCatalogWidget.cpp                |    42 +-
 src/osgEarthQt/TerrainProfileGraph                 |     2 +-
 src/osgEarthQt/TerrainProfileGraph.cpp             |     2 +-
 src/osgEarthQt/TerrainProfileWidget                |     2 +-
 src/osgEarthQt/TerrainProfileWidget.cpp            |     2 +-
 src/osgEarthQt/ViewWidget                          |     2 +-
 src/osgEarthQt/ViewWidget.cpp                      |     2 +-
 src/osgEarthQt/ViewerWidget                        |     2 +-
 src/osgEarthQt/ViewerWidget.cpp                    |     4 +-
 src/osgEarthSilverLining/CMakeLists.txt            |    71 +
 src/osgEarthSilverLining/Common                    |    32 +
 src/osgEarthSilverLining/Export                    |    74 +
 src/osgEarthSilverLining/SilverLiningAPIWrapper    |   202 +
 .../SilverLiningAPIWrapper.cpp                     |   128 +
 src/osgEarthSilverLining/SilverLiningCallback      |    48 +
 .../SilverLiningCloudsDrawable                     |    66 +
 .../SilverLiningCloudsDrawable.cpp                 |   103 +
 src/osgEarthSilverLining/SilverLiningContext       |   123 +
 src/osgEarthSilverLining/SilverLiningContext.cpp   |   295 +
 src/osgEarthSilverLining/SilverLiningContextNode   |    80 +
 .../SilverLiningContextNode.cpp                    |   158 +
 src/osgEarthSilverLining/SilverLiningNode          |    91 +
 src/osgEarthSilverLining/SilverLiningNode.cpp      |   199 +
 src/osgEarthSilverLining/SilverLiningOptions       |   102 +
 src/osgEarthSilverLining/SilverLiningSkyDrawable   |    57 +
 .../SilverLiningSkyDrawable.cpp                    |   139 +
 src/osgEarthSplat/BiomeRegion                      |    84 +
 src/osgEarthSplat/BiomeRegion.cpp                  |    76 +
 src/osgEarthSplat/BiomeRegionSelector              |    56 +
 src/osgEarthSplat/BiomeRegionSelector.cpp          |   143 +
 src/osgEarthSplat/CMakeLists.txt                   |    99 +
 src/osgEarthSplat/Coverage                         |   118 +
 src/osgEarthSplat/Coverage.cpp                     |   103 +
 src/osgEarthSplat/Export                           |    63 +
 src/osgEarthSplat/LandCover                        |   445 +
 src/osgEarthSplat/LandCover.FS.glsl                |    49 +
 src/osgEarthSplat/LandCover.GS.glsl                |   334 +
 src/osgEarthSplat/LandCover.TCS.glsl               |    55 +
 src/osgEarthSplat/LandCover.TES.glsl               |    50 +
 src/osgEarthSplat/LandCover.cpp                    |   438 +
 src/osgEarthSplat/LandCoverTerrainEffect           |    87 +
 src/osgEarthSplat/LandCoverTerrainEffect.cpp       |   238 +
 src/osgEarthSplat/LandCoverTilePatchCallback       |    58 +
 src/osgEarthSplat/LandCoverTilePatchCallback.cpp   |    89 +
 src/osgEarthSplat/LandUseTileSource                |   184 +
 src/osgEarthSplat/LandUseTileSource.cpp            |   282 +
 .../splat => osgEarthSplat}/ModelSplatter          |     0
 .../splat => osgEarthSplat}/ModelSplatter.cpp      |     0
 src/osgEarthSplat/NoiseTextureFactory              |    39 +
 src/osgEarthSplat/NoiseTextureFactory.cpp          |   119 +
 .../splat => osgEarthSplat}/Splat.Noise.glsl       |     0
 src/osgEarthSplat/Splat.frag.common.glsl           |    35 +
 src/osgEarthSplat/Splat.frag.glsl                  |   309 +
 src/osgEarthSplat/Splat.types.glsl                 |    22 +
 src/osgEarthSplat/Splat.util.glsl                  |    99 +
 src/osgEarthSplat/Splat.vert.model.glsl            |    15 +
 src/osgEarthSplat/Splat.vert.view.glsl             |    24 +
 src/osgEarthSplat/SplatCatalog                     |   172 +
 src/osgEarthSplat/SplatCatalog.cpp                 |   390 +
 src/osgEarthSplat/SplatCoverageLegend              |   112 +
 src/osgEarthSplat/SplatCoverageLegend.cpp          |    93 +
 src/osgEarthSplat/SplatExtension                   |    90 +
 src/osgEarthSplat/SplatExtension.cpp               |   177 +
 src/osgEarthSplat/SplatOptions                     |    94 +
 src/osgEarthSplat/SplatShaders                     |    57 +
 src/osgEarthSplat/SplatShaders.cpp.in              |    47 +
 src/osgEarthSplat/SplatTerrainEffect               |   111 +
 src/osgEarthSplat/SplatTerrainEffect.cpp           |   232 +
 src/osgEarthSplat/Surface                          |   115 +
 src/osgEarthSplat/Surface.cpp                      |   227 +
 src/osgEarthSplat/Zone                             |   155 +
 src/osgEarthSplat/Zone.cpp                         |   196 +
 src/osgEarthSymbology/AltitudeSymbol               |     2 +-
 src/osgEarthSymbology/AltitudeSymbol.cpp           |    32 +-
 src/osgEarthSymbology/BBoxSymbol                   |    80 +
 src/osgEarthSymbology/BBoxSymbol.cpp               |    94 +
 src/osgEarthSymbology/BillboardResource            |    70 +
 src/osgEarthSymbology/BillboardResource.cpp        |    57 +
 src/osgEarthSymbology/BillboardSymbol              |    82 +
 src/osgEarthSymbology/BillboardSymbol.cpp          |    81 +
 src/osgEarthSymbology/CMakeLists.txt               |     6 +
 src/osgEarthSymbology/Color                        |     2 +-
 src/osgEarthSymbology/Color.cpp                    |     2 +-
 src/osgEarthSymbology/Common                       |     2 +-
 src/osgEarthSymbology/CoverageSymbol               |     2 +-
 src/osgEarthSymbology/CoverageSymbol.cpp           |     2 +-
 src/osgEarthSymbology/CssUtils                     |     2 +-
 src/osgEarthSymbology/CssUtils.cpp                 |     2 +-
 src/osgEarthSymbology/Expression                   |    11 +-
 src/osgEarthSymbology/Expression.cpp               |    25 +-
 src/osgEarthSymbology/ExtrusionSymbol              |     2 +-
 src/osgEarthSymbology/ExtrusionSymbol.cpp          |     2 +-
 src/osgEarthSymbology/Fill                         |     2 +-
 src/osgEarthSymbology/Fill.cpp                     |     2 +-
 src/osgEarthSymbology/GEOS                         |     2 +-
 src/osgEarthSymbology/GEOS.cpp                     |    26 +-
 src/osgEarthSymbology/Geometry                     |    30 +-
 src/osgEarthSymbology/Geometry.cpp                 |   114 +-
 .../GeometryExtrudeSymbolizer.cpp                  |   298 -
 src/osgEarthSymbology/GeometryFactory              |     2 +-
 src/osgEarthSymbology/GeometryFactory.cpp          |     2 +-
 src/osgEarthSymbology/GeometryRasterizer           |     2 +-
 src/osgEarthSymbology/GeometryRasterizer.cpp       |     2 +-
 src/osgEarthSymbology/IconResource                 |     2 +-
 src/osgEarthSymbology/IconResource.cpp             |     7 +-
 src/osgEarthSymbology/IconSymbol                   |     2 +-
 src/osgEarthSymbology/IconSymbol.cpp               |     6 +-
 src/osgEarthSymbology/InstanceResource             |     4 +-
 src/osgEarthSymbology/InstanceResource.cpp         |     2 +-
 src/osgEarthSymbology/InstanceSymbol               |     5 +-
 src/osgEarthSymbology/InstanceSymbol.cpp           |    14 +-
 src/osgEarthSymbology/LineSymbol                   |     2 +-
 src/osgEarthSymbology/LineSymbol.cpp               |     2 +-
 src/osgEarthSymbology/MarkerResource               |     2 +-
 src/osgEarthSymbology/MarkerResource.cpp           |     2 +-
 src/osgEarthSymbology/MarkerSymbol                 |     2 +-
 src/osgEarthSymbology/MarkerSymbol.cpp             |     4 +-
 src/osgEarthSymbology/MeshConsolidator             |     2 +-
 src/osgEarthSymbology/MeshConsolidator.cpp         |     4 +-
 src/osgEarthSymbology/MeshFlattener                |     8 +-
 src/osgEarthSymbology/MeshFlattener.cpp            |    64 +-
 src/osgEarthSymbology/MeshSubdivider               |     2 +-
 src/osgEarthSymbology/MeshSubdivider.cpp           |    31 +-
 src/osgEarthSymbology/ModelResource                |    23 +-
 src/osgEarthSymbology/ModelResource.cpp            |    75 +-
 src/osgEarthSymbology/ModelSymbol                  |    43 +-
 src/osgEarthSymbology/ModelSymbol.cpp              |    66 +-
 src/osgEarthSymbology/PointSymbol                  |     2 +-
 src/osgEarthSymbology/PointSymbol.cpp              |     2 +-
 src/osgEarthSymbology/PolygonSymbol                |     2 +-
 src/osgEarthSymbology/PolygonSymbol.cpp            |     2 +-
 src/osgEarthSymbology/Query                        |     6 +-
 src/osgEarthSymbology/Query.cpp                    |    12 +-
 src/osgEarthSymbology/RenderSymbol                 |     7 +-
 src/osgEarthSymbology/RenderSymbol.cpp             |    13 +-
 src/osgEarthSymbology/Resource                     |     5 +-
 src/osgEarthSymbology/Resource.cpp                 |     2 +-
 src/osgEarthSymbology/ResourceCache                |    17 +-
 src/osgEarthSymbology/ResourceCache.cpp            |    23 +-
 src/osgEarthSymbology/ResourceLibrary              |    18 +-
 src/osgEarthSymbology/ResourceLibrary.cpp          |    68 +-
 src/osgEarthSymbology/Skins                        |    57 +-
 src/osgEarthSymbology/Skins.cpp                    |   147 +-
 src/osgEarthSymbology/StencilVolumeNode            |     2 +-
 src/osgEarthSymbology/StencilVolumeNode.cpp        |     4 +-
 src/osgEarthSymbology/Stroke                       |     2 +-
 src/osgEarthSymbology/Stroke.cpp                   |     2 +-
 src/osgEarthSymbology/Style                        |     2 +-
 src/osgEarthSymbology/Style.cpp                    |     2 +-
 src/osgEarthSymbology/StyleSelector                |     2 +-
 src/osgEarthSymbology/StyleSelector.cpp            |     2 +-
 src/osgEarthSymbology/StyleSheet                   |     6 +-
 src/osgEarthSymbology/StyleSheet.cpp               |    20 +-
 src/osgEarthSymbology/Symbol                       |     4 +-
 src/osgEarthSymbology/Symbol.cpp                   |     2 +-
 src/osgEarthSymbology/Tags                         |     9 +-
 src/osgEarthSymbology/TextSymbol                   |    31 +-
 src/osgEarthSymbology/TextSymbol.cpp               |   160 +-
 src/osgEarthTriton/CMakeLists.txt                  |    69 +
 src/osgEarthTriton/Common                          |    32 +
 src/osgEarthTriton/Export                          |    74 +
 src/osgEarthTriton/Shaders/user-functions.glsl     |    81 +
 src/osgEarthTriton/TritonAPIWrapper                |   102 +
 src/osgEarthTriton/TritonAPIWrapper.cpp            |    85 +
 src/osgEarthTriton/TritonCallback                  |    40 +
 src/osgEarthTriton/TritonContext                   |    99 +
 src/osgEarthTriton/TritonContext.cpp               |   185 +
 src/osgEarthTriton/TritonDrawable                  |    95 +
 src/osgEarthTriton/TritonDrawable.cpp              |   718 +
 src/osgEarthTriton/TritonNode                      |    70 +
 src/osgEarthTriton/TritonNode.cpp                  |   100 +
 src/osgEarthTriton/TritonOptions                   |   109 +
 src/osgEarthUtil/ActivityMonitorTool               |     2 +-
 src/osgEarthUtil/ActivityMonitorTool.cpp           |     2 +-
 src/osgEarthUtil/AnnotationEvents                  |     4 +-
 src/osgEarthUtil/AnnotationEvents.cpp              |     2 +-
 src/osgEarthUtil/ArcGIS                            |     2 +-
 src/osgEarthUtil/ArcGIS.cpp                        |     2 +-
 src/osgEarthUtil/AtlasBuilder                      |     2 +-
 src/osgEarthUtil/AtlasBuilder.cpp                  |    13 +-
 src/osgEarthUtil/AutoClipPlaneHandler              |     2 +-
 src/osgEarthUtil/AutoClipPlaneHandler.cpp          |     4 +-
 src/osgEarthUtil/BrightnessContrastColorFilter     |     2 +-
 src/osgEarthUtil/BrightnessContrastColorFilter.cpp |     2 +-
 src/osgEarthUtil/CMYKColorFilter                   |     2 +-
 src/osgEarthUtil/CMYKColorFilter.cpp               |     2 +-
 src/osgEarthUtil/CMakeLists.txt                    |     6 +-
 src/osgEarthUtil/ChromaKeyColorFilter              |     2 +-
 src/osgEarthUtil/ChromaKeyColorFilter.cpp          |     2 +-
 src/osgEarthUtil/ClampCallback                     |     2 +-
 src/osgEarthUtil/ClampCallback.cpp                 |    18 +-
 src/osgEarthUtil/Common                            |     2 +-
 src/osgEarthUtil/ContourMap                        |    76 +-
 src/osgEarthUtil/ContourMap.cpp                    |   116 +-
 src/osgEarthUtil/ContourMap.frag.glsl              |    17 +-
 src/osgEarthUtil/ContourMap.vert.glsl              |    14 +-
 src/osgEarthUtil/Controls                          |    41 +-
 src/osgEarthUtil/Controls.cpp                      |    64 +-
 src/osgEarthUtil/DataScanner                       |     2 +-
 src/osgEarthUtil/DataScanner.cpp                   |     2 +-
 src/osgEarthUtil/EarthManipulator                  |   136 +-
 src/osgEarthUtil/EarthManipulator.cpp              |   457 +-
 src/osgEarthUtil/Ephemeris                         |     2 +-
 src/osgEarthUtil/Ephemeris.cpp                     |   189 +-
 src/osgEarthUtil/ExampleResources                  |    19 +-
 src/osgEarthUtil/ExampleResources.cpp              |   509 +-
 src/osgEarthUtil/Export                            |     2 +-
 src/osgEarthUtil/FeatureQueryTool                  |     2 +-
 src/osgEarthUtil/FeatureQueryTool.cpp              |     2 +-
 src/osgEarthUtil/Fog                               |    12 +
 src/osgEarthUtil/Fog.cpp                           |    25 +
 src/osgEarthUtil/Fog.frag.glsl                     |    10 +-
 src/osgEarthUtil/Fog.vert.glsl                     |    29 +-
 src/osgEarthUtil/Formatter                         |     2 +-
 src/osgEarthUtil/GLSLColorFilter                   |     2 +-
 src/osgEarthUtil/GLSLColorFilter.cpp               |     2 +-
 src/osgEarthUtil/GammaColorFilter                  |     2 +-
 src/osgEarthUtil/GammaColorFilter.cpp              |     2 +-
 src/osgEarthUtil/GeodeticGraticule                 |     2 +-
 src/osgEarthUtil/GeodeticGraticule.cpp             |    26 +-
 src/osgEarthUtil/Graticule.frag.glsl               |    17 +-
 src/osgEarthUtil/Graticule.vert.glsl               |    14 +-
 src/osgEarthUtil/GraticuleExtension                |     9 +-
 src/osgEarthUtil/GraticuleExtension.cpp            |    38 +-
 src/osgEarthUtil/GraticuleNode                     |     3 +-
 src/osgEarthUtil/GraticuleNode.cpp                 |   106 +-
 src/osgEarthUtil/GraticuleOptions                  |     4 +-
 src/osgEarthUtil/GraticuleTerrainEffect.cpp        |     4 +-
 src/osgEarthUtil/HSLColorFilter                    |     2 +-
 src/osgEarthUtil/HSLColorFilter.cpp                |     2 +-
 src/osgEarthUtil/HTM                               |   115 +-
 src/osgEarthUtil/HTM.cpp                           |   471 +-
 src/osgEarthUtil/LODBlending                       |   106 +-
 src/osgEarthUtil/LODBlending.cpp                   |   166 +-
 src/osgEarthUtil/LatLongFormatter                  |     2 +-
 src/osgEarthUtil/LatLongFormatter.cpp              |     2 +-
 src/osgEarthUtil/LineOfSight                       |     2 +-
 src/osgEarthUtil/LinearLineOfSight                 |     2 +-
 src/osgEarthUtil/LinearLineOfSight.cpp             |     2 +-
 src/osgEarthUtil/LogDepthBuffer.VertOnly.vert.glsl |     6 +-
 src/osgEarthUtil/LogDepthBuffer.frag.glsl          |     6 +-
 src/osgEarthUtil/LogDepthBuffer.vert.glsl          |     6 +-
 src/osgEarthUtil/LogarithmicDepthBuffer            |     2 +-
 src/osgEarthUtil/LogarithmicDepthBuffer.cpp        |     2 +-
 src/osgEarthUtil/MGRSFormatter                     |     2 +-
 src/osgEarthUtil/MGRSFormatter.cpp                 |     2 +-
 src/osgEarthUtil/MGRSGraticule                     |     2 +-
 src/osgEarthUtil/MGRSGraticule.cpp                 |    12 +-
 src/osgEarthUtil/MeasureTool                       |     2 +-
 src/osgEarthUtil/MeasureTool.cpp                   |    17 +-
 src/osgEarthUtil/MouseCoordsTool                   |     2 +-
 src/osgEarthUtil/MouseCoordsTool.cpp               |    19 +-
 src/osgEarthUtil/NightColorFilter                  |     2 +-
 src/osgEarthUtil/NightColorFilter.cpp              |     2 +-
 src/osgEarthUtil/ObjectLocator                     |     2 +-
 src/osgEarthUtil/Ocean                             |    25 +-
 src/osgEarthUtil/Ocean.cpp                         |    58 +-
 src/osgEarthUtil/PolyhedralLineOfSight             |    11 +-
 src/osgEarthUtil/PolyhedralLineOfSight.cpp         |    17 +-
 src/osgEarthUtil/RGBColorFilter                    |     2 +-
 src/osgEarthUtil/RGBColorFilter.cpp                |     2 +-
 src/osgEarthUtil/RTTPicker                         |     2 +-
 src/osgEarthUtil/RTTPicker.cpp                     |    57 +-
 src/osgEarthUtil/RadialLineOfSight                 |     2 +-
 src/osgEarthUtil/RadialLineOfSight.cpp             |    13 +-
 src/osgEarthUtil/Shaders                           |     5 +-
 src/osgEarthUtil/Shaders.cpp.in                    |    23 +-
 src/osgEarthUtil/Shadowing                         |    20 +-
 src/osgEarthUtil/Shadowing.cpp                     |   162 +-
 src/osgEarthUtil/Shadowing.frag.glsl               |    89 +
 src/osgEarthUtil/Shadowing.vert.glsl               |    18 +
 src/osgEarthUtil/SimplePager                       |   145 +
 src/osgEarthUtil/SimplePager.cpp                   |   362 +
 src/osgEarthUtil/SimplexNoise                      |     4 +-
 src/osgEarthUtil/SimplexNoise.cpp                  |    11 +-
 src/osgEarthUtil/Sky                               |    21 +-
 src/osgEarthUtil/Sky.cpp                           |    52 +-
 src/osgEarthUtil/SpatialData                       |     2 +-
 src/osgEarthUtil/SpatialData.cpp                   |    20 +-
 src/osgEarthUtil/StarData                          |     2 +-
 src/osgEarthUtil/TFS                               |     2 +-
 src/osgEarthUtil/TFS.cpp                           |     2 +-
 src/osgEarthUtil/TFSPackager                       |     2 +-
 src/osgEarthUtil/TFSPackager.cpp                   |     2 +-
 src/osgEarthUtil/TMS                               |    11 +-
 src/osgEarthUtil/TMS.cpp                           |    51 +-
 src/osgEarthUtil/TMSBackFiller                     |     2 +-
 src/osgEarthUtil/TMSBackFiller.cpp                 |     8 +-
 src/osgEarthUtil/TMSPackager                       |    13 +-
 src/osgEarthUtil/TMSPackager.cpp                   |    72 +-
 src/osgEarthUtil/TerrainProfile                    |     2 +-
 src/osgEarthUtil/TerrainProfile.cpp                |     2 +-
 src/osgEarthUtil/TileIndex                         |     2 +-
 src/osgEarthUtil/TileIndex.cpp                     |    16 +-
 src/osgEarthUtil/TileIndexBuilder                  |     2 +-
 src/osgEarthUtil/TileIndexBuilder.cpp              |     2 +-
 src/osgEarthUtil/UTMGraticule                      |     2 +-
 src/osgEarthUtil/UTMGraticule.cpp                  |     2 +-
 src/osgEarthUtil/WFS                               |     2 +-
 src/osgEarthUtil/WFS.cpp                           |     8 +-
 src/osgEarthUtil/WMS                               |     2 +-
 src/osgEarthUtil/WMS.cpp                           |     2 +-
 tests/annotation.earth                             |   347 +-
 tests/annotation_flat.earth                        |   334 +-
 tests/arcgisonline.earth                           |     5 +-
 tests/billboard.earth                              |    39 -
 tests/boston-gpu.earth                             |    25 +-
 tests/boston.earth                                 |    24 +-
 tests/boston_buildings.earth                       |    17 +-
 tests/boston_projected.earth                       |    16 +-
 tests/boston_viewpoints.xml                        |     4 +
 tests/bumpmap.earth                                |    27 +
 tests/clouds.earth                                 |    39 +
 tests/colorramp.earth                              |     4 +-
 tests/contourmap.earth                             |    16 +
 tests/dc_viewpoints.xml                            |     2 +
 tests/detail_texture.earth                         |    20 +
 tests/errors.earth                                 |    32 +
 tests/fade_elevation.earth                         |    59 +
 tests/feature_clip_plane.earth                     |     1 +
 tests/feature_country_boundaries.earth             |    42 +
 tests/feature_custom_filters.earth                 |     4 +-
 tests/feature_draped_polygons.earth                |    34 +-
 tests/feature_elevation.earth                      |    49 +
 tests/feature_extrude.earth                        |    27 +-
 tests/feature_labels.earth                         |    29 +-
 tests/feature_labels_script.earth                  |     2 +-
 tests/feature_model_scatter.earth                  |    47 +-
 tests/feature_offset_polygons.earth                |    62 +-
 tests/feature_poles.earth                          |    64 +
 tests/feature_population_cylinders.earth           |     2 +-
 tests/feature_raster.earth                         |   119 +
 tests/feature_rasterize.earth                      |     5 -
 tests/feature_rasterize_2.earth                    |    21 +-
 tests/feature_scripted_styling.earth               |     4 +-
 tests/feature_scripted_styling_2.earth             |     4 +-
 tests/feature_style_selector.earth                 |    12 +-
 tests/feature_tfs_scripting.earth                  |     5 +-
 tests/feature_wfs.earth                            |    20 +-
 tests/gdal_tiff.earth                              |     2 +-
 tests/geomshader.earth                             |    62 +
 tests/glsl.earth                                   |    30 +-
 tests/graticule.earth                              |    43 +-
 tests/hires-inset.earth                            |     8 +-
 tests/intersect_filter.earth                       |    58 +
 tests/ldb.earth                                    |    30 +-
 tests/mapquest_open_aerial.earth                   |    25 -
 tests/mapquest_osm.earth                           |    26 -
 tests/mapquest_with_srtm.earth                     |    30 -
 tests/mb_tiles.earth                               |    12 +-
 tests/mercator_to_plate_carre.earth                |    10 +-
 tests/min_max_level.earth                          |    17 +-
 tests/min_max_range.earth                          |    21 +-
 tests/min_max_range_rex.earth                      |    23 +
 tests/multiple_heightfields.earth                  |     5 +-
 tests/night.earth                                  |     4 +-
 tests/nodata.earth                                 |     8 +-
 tests/noise.earth                                  |   118 +-
 tests/normalmap.earth                              |    14 +-
 tests/ocean.earth                                  |    46 +-
 tests/openstreetmap_buildings.earth                |    93 +
 tests/openstreetmap_flat.earth                     |     7 +-
 tests/openstreetmap_full.earth                     |   239 +
 tests/osgearth_server/README.md                    |     4 +
 tests/osgearth_server/css/l.geosearch.css          |    65 +
 tests/osgearth_server/images/Thumbs.db             |   Bin 0 -> 4608 bytes
 tests/osgearth_server/images/alert.png             |   Bin 0 -> 1094 bytes
 tests/osgearth_server/images/geosearch.png         |   Bin 0 -> 699 bytes
 tests/osgearth_server/images/layers-2x.png         |   Bin 0 -> 2898 bytes
 tests/osgearth_server/images/layers.png            |   Bin 0 -> 1502 bytes
 tests/osgearth_server/images/marker-icon-2x.png    |   Bin 0 -> 4033 bytes
 tests/osgearth_server/images/marker-icon.png       |   Bin 0 -> 1747 bytes
 tests/osgearth_server/images/marker-shadow.png     |   Bin 0 -> 797 bytes
 tests/osgearth_server/images/spinner.gif           |   Bin 0 -> 1397 bytes
 tests/osgearth_server/images/transparent.png       |   Bin 0 -> 951 bytes
 tests/osgearth_server/index.html                   |    20 +
 tests/osgearth_server/js/l.control.geosearch.js    |   204 +
 .../js/l.geosearch.provider.nominatim.js           |    70 +
 tests/osgearth_server/leaflet.css                  |   479 +
 tests/osgearth_server/leaflet.js                   |  9168 +++
 tests/photosphere1.earth                           |    30 +
 tests/photosphere2.earth                           |    30 +
 tests/readymap-osm.earth                           |     4 +-
 tests/readymap-priority.earth                      |    35 +
 tests/readymap-rex.earth                           |    31 +
 tests/readymap.earth                               |     8 +-
 tests/readymap_elevation.xml                       |     3 +
 tests/readymap_imagery.xml                         |     3 +
 tests/readymap_include.earth                       |    12 +
 tests/readymap_pixel_size.earth                    |    31 +
 tests/readymap_template.earth                      |    23 +
 tests/silverlining.earth                           |    22 +-
 tests/simple_model.earth                           |    18 +-
 tests/skyview1.earth                               |    30 +
 tests/skyview2.earth                               |    30 +
 tests/splat-edit.bat                               |     4 +-
 tests/splat-gpunoise.bat                           |     2 +-
 tests/splat-ranges.earth                           |    55 +
 tests/splat-server.earth                           |   105 +
 tests/splat-test.earth                             |    57 -
 tests/splat-with-imagery.earth                     |    52 -
 tests/splat-with-vectors.earth                     |   109 +
 tests/splat.bat                                    |    21 +-
 tests/splat.earth                                  |    78 +
 tests/stamen_watercolor.earth                      |     4 +-
 tests/{dc_state_plane.earth => state_plane.earth}  |     0
 tests/tess-coastlines.earth                        |   157 +
 tests/tess-masking.earth                           |   176 +
 tests/tess-terrain.earth                           |   146 +
 tests/tess_screen_space.earth                      |   120 +
 tests/test-morphing.earth                          |    50 +
 tests/triton.earth                                 |    45 +-
 tests/triton_drop_shader.earth                     |    73 +
 tests/vertical_scale.earth                         |    29 -
 tests/viewpoints.xml                               |    65 +
 1469 files changed, 155268 insertions(+), 80120 deletions(-)

diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 0000000..afdce64
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,42 @@
+env:
+  global:
+   # The next declaration is the encrypted COVERITY_SCAN_TOKEN, created
+   #   via the "travis encrypt" command using the project repo's public key
+   - secure: "vLe6I4mS64oabuhMJ5NHyJLJHxudgErRoKpoXZP9/8A6rx/TmZ/gYCmtENmKublSIyOmjoVoZ8lvw10a1zCgnlQEjdijxwPvO1IN4XlesjhbxFRysmYAQZsFifZ91ta/0Ajw6NV6ofhmWCBRUc2yCEexnf+xvj80+v6tq2q3YFIL0shHjm7c3Z5nOuKPTsxLEAtHYurUM3ao4gcppc5lOeOT+r+ENE0MCQwSKOXiXh4BWCkP9cQvKel8ineBl3T6qRrT0OQQ/OBeSba/orVrf6Y3Ls+BYM48NjxG0TN2PIP68eJVQnvPNZ+j42MypkrFckcJDM/N/1pI6ZiY0PrzPMX3SisP5WDKimowWuyaI/pdOO2tBqPIIdZvuAoUyh5MYBBHLGeHf4jCD+YwY2JcOdStHgkp4NE2JqjXvP9V4TizFjrZ1jb+MXHwVKF4mleo6Eoq+qOdj8Y9iFhwmpuf9oGgoEIWR4 [...]
+os: linux
+dist: trusty
+sudo: required
+language: cpp
+compiler:
+- gcc
+before_install:
+# Try coverity workaround here:  https://github.com/travis-ci/travis-ci/issues/6142
+- echo -n | openssl s_client -connect scan.coverity.com:443 | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' | sudo tee -a /etc/ssl/certs/ca-certificates.crt
+#- sudo add-apt-repository -y ppa:ubuntugis/ubuntugis-unstable
+- sudo echo "deb http://dl.bintray.com/jasonbeverage/pelicanmapping trusty main" | sudo tee -a /etc/apt/sources.list
+- sudo apt-get update -qq
+- sudo apt-get install -y cmake
+#- sudo apt-get install -y libopenscenegraph-dev
+- sudo apt-get install -y --force-yes openscenegraph=3.4.0
+- sudo apt-get install -y libgdal-dev
+- sudo apt-get install -y libgeos-dev
+- sudo apt-get install -y libsqlite3-dev
+- sudo apt-get install -y protobuf-compiler libprotobuf-dev
+# Debug print out osgversion
+- osgversion
+script:
+- if [ "${COVERITY_SCAN_BRANCH}" != 1 ]; then cmake -DCMAKE_BUILD_TYPE=Release . && make -j3 ; fi
+notifications:
+  email:
+    recipients:
+    - jasonbeverage at pelicanmapping.com
+    - gwaldron at pelicanmapping.com
+addons:
+  coverity_scan:
+    project:
+      name: "gwaldron/osgearth"
+      description: "osgEarth"
+    notification_email: jasonbeverage at pelicanmapping.com
+    build_command_prepend: cmake -DCMAKE_BUILD_TYPE=Release -DBUILD_OSGEARTH_EXAMPLES=OFF .
+    build_command: make -j3
+    branch_pattern: coverity_scan
\ No newline at end of file
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 38ab336..2b0a89a 100755
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -8,6 +8,14 @@ if(COMMAND cmake_policy)
     # Works around warnings about escaped quotes in ADD_DEFINITIONS
     # statements.
     cmake_policy(SET CMP0005 OLD)
+    
+    
+    IF(COMMAND cmake_policy)
+            IF(${CMAKE_MAJOR_VERSION} GREATER 2)
+                # Qt5 qt5_use_modules usage was causing "Policy CMP0043 is not set: Ignore COMPILE_DEFINITIONS_<Config> properties." warnings
+                cmake_policy(SET CMP0043 NEW)
+            ENDIF()
+    ENDIF()
 
     # disable autolinking to qtmain as we have our own main() functions (new in Qt 5.1)
     if(NOT "${CMAKE_VERSION}" VERSION_LESS 2.8.11)
@@ -24,7 +32,7 @@ SET_PROPERTY( GLOBAL PROPERTY PREDEFINED_TARGETS_FOLDER "CMake Targets" )
 PROJECT(OSGEARTH)
 
 SET(OSGEARTH_MAJOR_VERSION 2)
-SET(OSGEARTH_MINOR_VERSION 6)
+SET(OSGEARTH_MINOR_VERSION 9)
 SET(OSGEARTH_PATCH_VERSION 0)
 SET(OSGEARTH_SOVERSION     0)
 
@@ -121,17 +129,19 @@ FIND_PACKAGE(GDAL)
 FIND_PACKAGE(GEOS)
 FIND_PACKAGE(Sqlite3)
 FIND_PACKAGE(ZLIB)
+FIND_PACKAGE(Poco)
 
 FIND_PACKAGE(LevelDB)
+FIND_PACKAGE(RocksDB)
 
-FIND_PACKAGE(SilverLining)
-FIND_PACKAGE(Triton)
-FIND_PACKAGE(Protobuf)
+FIND_PACKAGE(SilverLining QUIET)
+FIND_PACKAGE(Triton QUIET)
+
+FIND_PACKAGE(Protobuf QUIET)
 
 # JavaScript Engines:
 SET(V8_DIR "" CACHE PATH "set to base V8 install path")
 FIND_PACKAGE(V8)
-FIND_PACKAGE(JavaScriptCore)
 
 SET (WITH_EXTERNAL_DUKTAPE FALSE CACHE BOOL "Use bundled or system wide version of Duktape")
 IF (WITH_EXTERNAL_DUKTAPE)
@@ -155,7 +165,8 @@ ELSE()
     ENDIF (QT4_FOUND)
 ENDIF ()
 
-OPTION(OSGEARTH_USE_QT "Enable to use Qt (build Qt-dependent libraries, plugins and examples)" ON)
+OPTION(OSGEARTH_USE_QT "Enable to use Qt (build Qt-dependent libraries, plugins and examples)" OFF)
+OPTION(OSGEARTH_QT_BUILD_LEGACY_WIDGETS "Build the legacy Qt widgets" OFF)
 
 # option to install shaders:
 OPTION(OSGEARTH_INSTALL_SHADERS "Whether to deploy GLSL shaders when doing a Make INSTALL" OFF)
@@ -165,10 +176,6 @@ IF (WITH_EXTERNAL_TINYXML)
     FIND_PACKAGE(TinyXML)
 ENDIF (WITH_EXTERNAL_TINYXML)
 
-IF (ZLIB_FOUND)
-    FIND_PACKAGE(MiniZip)
-ENDIF (ZLIB_FOUND)
-
 IF(UNIX)
     # Not sure what this will do on Cygwin and Msys
     # Also, remember OS X X11 is a user installed option so it may not exist.
@@ -320,6 +327,9 @@ ELSE (INSTALL_TO_OSG_DIR)
 ENDIF(INSTALL_TO_OSG_DIR)
 
 
+# osgEarth Examples
+OPTION(BUILD_OSGEARTH_EXAMPLES "Enable to build osgEarth Examples" ON)
+
 INCLUDE(OsgEarthMacroUtils)
 
 DETECT_OSG_VERSION()
diff --git a/CMakeModules/ConfigureShaders.cmake.in b/CMakeModules/ConfigureShaders.cmake.in
index 6336562..cc67041 100644
--- a/CMakeModules/ConfigureShaders.cmake.in
+++ b/CMakeModules/ConfigureShaders.cmake.in
@@ -19,11 +19,21 @@ foreach(file ${glsl_files})
     set(contents "${contents}\n")
 
     # replace hashtags with a marker string to avoid breaking the MULTILINE macro:
-	string(REGEX REPLACE "#" "$__HASHTAG__" tempString "${contents}")
+	# string(REGEX REPLACE "#" "$__HASHTAG__" tempString "${contents}")
+
+    # replace comment symbols to avoid breaking the MULTILINE macro:
+    # string(REGEX REPLACE "//"   "$__BEGINEOLCOMMENT__"   tempString2 "${tempString}")
+    # string(REGEX REPLACE "/\\*" "$__BEGINBLOCKCOMMENT__" tempString  "${tempString2}")
+    # string(REGEX REPLACE "\\*/" "$__ENDBLOCKCOMMENT__"   tempString2 "${tempString}")
+    # string(REGEX REPLACE "'"    "$__APOSTROPHE__"        tempString  "${tempString2}")
+    # string(REGEX REPLACE "\""   "$__QUOTE__"             tempString2 "${tempString}")
 
     # replace newlines with printable newlines, and overwrite the original
     # file name with the processed contents.
-	string(REGEX REPLACE "\n" "\\\\n\n" ${file} "${tempString}")
+	# string(REGEX REPLACE "\n" "\\\\n\n" ${file} "${tempString2}")
+
+	string(REGEX REPLACE  "\n"  "%EOL%"    tempString  "${contents}"   )
+    string(REGEX REPLACE  "\""  "%QUOTE%"  ${file}     "${tempString}" )
 
 endforeach(file)
 
diff --git a/CMakeModules/FindMiniZip.cmake b/CMakeModules/FindMiniZip.cmake
deleted file mode 100644
index 345386d..0000000
--- a/CMakeModules/FindMiniZip.cmake
+++ /dev/null
@@ -1,70 +0,0 @@
-# Locate minizip library
-# This module defines
-# MINIZIP_LIBRARY
-# MINIZIP_FOUND, if false, do not try to link to libzip 
-# MINIZIP_INCLUDE_DIR, where to find the headers
-#
-
-# prefer pkg-config
-IF(UNIX)
-	INCLUDE(FindPkgConfig)
-	IF(PKG_CONFIG_FOUND)
-		pkg_check_modules(MINIZIP QUIET minizip)
-		IF(MINIZIP_FOUND)
-			# pkgconfig does not define the singular names
-			SET(MINIZIP_LIBRARY ${MINIZIP_LIBRARIES} CACHE STRING "Minizip libraries to link against")
-			SET(MINIZIP_INCLUDE_DIR ${MINIZIP_INCLUDE_DIRS} CACHE STRING "Minizip include dirs to look for headers")
-			link_directories(${MINIZIP_LIBRARY_DIRS})
-			ADD_DEFINITIONS(-DOSGEARTH_HAVE_MINIZIP)
-		ENDIF(MINIZIP_FOUND)
-	ENDIF(PKG_CONFIG_FOUND)
-ENDIF(UNIX)
-
-# fallback logic
-IF(NOT MINIZIP_FOUND)
-	FIND_PATH(MINIZIP_INCLUDE_DIR zip.h
-		${CMAKE_SOURCE_DIR}/src/3rdparty/minizip
-		$ENV{MINIZIP_DIR}/include
-		$ENV{MINIZIP_DIR}
-		$ENV{OSGDIR}/include
-		$ENV{OSGDIR}
-		$ENV{OSG_ROOT}/include
-		~/Library/Frameworks
-		/Library/Frameworks
-		/usr/local/include
-		/usr/include
-		/sw/include # Fink
-		/opt/local/include # DarwinPorts
-		/opt/csw/include # Blastwave
-		/opt/include
-		[HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Control\\Session\ Manager\\Environment;OSG_ROOT]/include
-		/usr/freeware/include
-	)
-
-	FIND_LIBRARY(MINIZIP_LIBRARY 
-		NAMES minizip
-		PATHS
-		${CMAKE_SOURCE_DIR}/src/3rdparty/minizip
-		$ENV{MINIZIP_DIR}/lib
-		$ENV{MINIZIP_DIR}
-		$ENV{OSGDIR}/lib
-		$ENV{OSGDIR}
-		$ENV{OSG_ROOT}/lib
-		~/Library/Frameworks
-		/Library/Frameworks
-		/usr/local/lib
-		/usr/lib
-		/sw/lib
-		/opt/local/lib
-		/opt/csw/lib
-		/opt/lib
-		[HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Control\\Session\ Manager\\Environment;OSG_ROOT]/lib
-		/usr/freeware/lib64
-	)
-
-	SET(MINIZIP_FOUND "NO")
-	IF(MINIZIP_LIBRARY AND MINIZIP_INCLUDE_DIR)
-		SET(MINIZIP_FOUND "YES")
-		ADD_DEFINITIONS(-DOSGEARTH_HAVE_MINIZIP)
-	ENDIF(MINIZIP_LIBRARY AND MINIZIP_INCLUDE_DIR)
-ENDIF(NOT MINIZIP_FOUND)
diff --git a/CMakeModules/FindPoco.cmake b/CMakeModules/FindPoco.cmake
new file mode 100644
index 0000000..07ef07c
--- /dev/null
+++ b/CMakeModules/FindPoco.cmake
@@ -0,0 +1,69 @@
+# Locate Poco libraries.
+# This module defines
+# POCO_NET_LIBRARY
+# POCO_FOUNDATION_LIBRARY
+# POCO_FOUND, if false, do not try to link to Poco
+# POCO_INCLUDE_DIR, where to find the headers
+
+SET(POCO_DIR "" CACHE PATH "Set to base Poco install path")
+
+FIND_PATH(POCO_INCLUDE_DIR Poco/Poco.h
+    ${POCO_DIR}/include
+    $ENV{POCO_DIR}/include
+    $ENV{POCO_DIR}/Source/lib #Windows Binary Installer
+    $ENV{POCO_DIR}
+    ~/Library/Frameworks
+    /Library/Frameworks
+    /usr/local/include
+    /usr/include
+    /sw/include # Fink
+    /opt/local/include # DarwinPorts
+    /opt/csw/include # Blastwave
+    /opt/include
+    /usr/freeware/include
+    /devel
+)
+
+
+MACRO( FIND_POCO_LIBRARY MYLIBRARY MYLIBRARYNAME )
+
+FIND_LIBRARY(${MYLIBRARY}
+    NAMES
+        ${MYLIBRARYNAME}
+    PATHS
+        ${POCO_DIR}
+        $ENV{POCO_DIR}
+        $ENV{POCO_DIR}
+        ~/Library/Frameworks
+        /Library/Frameworks
+        /usr/local
+        /usr
+        /sw
+        /opt/local
+        /opt/csw
+        /opt
+        /usr/freeware
+    PATH_SUFFIXES
+        /lib/
+        /lib64/
+        /build/lib/
+        /build/lib64/
+        /Build/lib/
+        /Build/lib64/
+     )
+
+ENDMACRO(FIND_POCO_LIBRARY LIBRARY LIBRARYNAME)
+
+FIND_POCO_LIBRARY(POCO_FOUNDATION_LIBRARY PocoFoundation)
+FIND_POCO_LIBRARY(POCO_FOUNDATION_LIBRARY_DEBUG PocoFoundationd)
+FIND_POCO_LIBRARY(POCO_NET_LIBRARY PocoNet)
+FIND_POCO_LIBRARY(POCO_NET_LIBRARY_DEBUG PocoNetd)
+FIND_POCO_LIBRARY(POCO_UTIL_LIBRARY PocoUtil)
+FIND_POCO_LIBRARY(POCO_UTIL_LIBRARY_DEBUG PocoUtild)
+
+SET(POCO_FOUND "NO")
+IF(POCO_FOUNDATION_LIBRARY AND POCO_NET_LIBRARY AND POCO_UTIL_LIBRARY AND POCO_INCLUDE_DIR)
+    SET(POCO_FOUND "YES")
+ENDIF()
+
+
diff --git a/CMakeModules/FindRocksDB.cmake b/CMakeModules/FindRocksDB.cmake
new file mode 100644
index 0000000..21d16a7
--- /dev/null
+++ b/CMakeModules/FindRocksDB.cmake
@@ -0,0 +1,42 @@
+# Locate RocksDB
+
+FIND_PATH(ROCKSDB_INCLUDE_DIR rocksdb/db.h
+  PATHS
+  ${ROCKSDB_DIR}
+  NO_DEFAULT_PATH
+  PATH_SUFFIXES include
+)
+
+find_library(ROCKSDB_LIBRARY NAMES ROCKSDBLIB
+             PATHS
+               ${ROCKSDB_DIR}
+               ${ROCKSDB_DIR}/bin/Release
+               ${ROCKSDB_DIR}/bin64_vs2013/Release
+             PATH_SUFFIXES lib lib64
+	    )
+
+
+find_library(ROCKSDB_LIBRARY_DEBUG NAMES ROCKSDBLIB
+             PATHS
+               ${ROCKSDB_DIR}
+               ${ROCKSDB_DIR}/bin/Debug
+               ${ROCKSDB_DIR}/bin64_vs2013/Debug
+             PATH_SUFFIXES lib lib64
+	    )
+
+if( ROCKSDB_LIBRARY )
+  MESSAGE(STATUS "FOUND ROCKSDB_LIBRARY")
+endif()
+
+if (ROCKSDB_INCLUDE_DIR)
+  MESSAGE(STATUS "FOUND ROCKSDB_INCLUDE_DIR")
+endif()
+  
+
+set( ROCKSDB_FOUND "NO" )
+if( ROCKSDB_LIBRARY AND ROCKSDB_INCLUDE_DIR )
+    set( ROCKSDB_FOUND "YES" )
+    MESSAGE(STATUS "Found RocksDB library: " ${ROCKSDB_LIBRARY})
+else()
+    MESSAGE(STATUS "Could not find ROCKSDB")
+endif()
diff --git a/CMakeModules/FindSilverLining.cmake b/CMakeModules/FindSilverLining.cmake
index c861efc..afeaff2 100644
--- a/CMakeModules/FindSilverLining.cmake
+++ b/CMakeModules/FindSilverLining.cmake
@@ -1,13 +1,13 @@
 # Locate SilverLining
 # This module defines
 # SILVERLINING_LIBRARY
-# SILVERLINING_FOUND, if false, do not try to link to SilverLining 
+# SILVERLINING_FOUND, if false, do not try to link to SilverLining
 # SILVERLINING_INCLUDE_DIR, where to find the headers
 #
 # $SILVERLINING_DIR is an environment variable that would
 # correspond to the ./configure --prefix=$SILVERLINING_DIR
 #
-# Created by Robert Hauck. 
+# Created by Robert Hauck.
 
 SET(SILVERLINING_DIR "" CACHE PATH "Location of SilverLining SDK")
 
@@ -43,6 +43,22 @@ IF (MSVC11)
 	ENDIF (CMAKE_CL_64)
 ENDIF (MSVC11)
 
+IF (MSVC12)
+	IF (CMAKE_CL_64)
+		SET(SILVERLINING_ARCH "vc12/x64")
+	ELSE (CMAKE_CL_64)
+		SET(SILVERLINING_ARCH "vc12/win32")
+	ENDIF (CMAKE_CL_64)
+ENDIF (MSVC12)
+
+IF (MSVC14)
+	IF (CMAKE_CL_64)
+		SET(SILVERLINING_ARCH "vc14/x64")
+	ELSE (CMAKE_CL_64)
+		SET(SILVERLINING_ARCH "vc14/win32")
+	ENDIF (CMAKE_CL_64)
+ENDIF (MSVC14)
+
 IF (MSVC71)
 	SET(SILVERLINING_ARCH "vc7")
 ENDIF (MSVC71)
@@ -96,14 +112,16 @@ MACRO(FIND_SILVERLINING_LIBRARY MYLIBRARY MYLIBRARYNAME)
 ENDMACRO(FIND_SILVERLINING_LIBRARY MYLIBRARY MYLIBRARYNAME)
 
 
-FIND_SILVERLINING_LIBRARY(SILVERLINING_LIBRARY_RELEASE "SilverLining-MT-DLL;SilverLining;SilverLiningOpenGL")
+#FIND_SILVERLINING_LIBRARY(SILVERLINING_LIBRARY_RELEASE "SilverLining-MT-DLL;SilverLining;SilverLiningOpenGL")
+#FIND_SILVERLINING_LIBRARY(SILVERLINING_LIBRARY_DEBUG "SilverLining-MTD-DLL;SilverLiningOpenGL")
+FIND_SILVERLINING_LIBRARY(SILVERLINING_LIBRARY       "SilverLining-MT-DLL;SilverLining;SilverLiningOpenGL")
 FIND_SILVERLINING_LIBRARY(SILVERLINING_LIBRARY_DEBUG "SilverLining-MTD-DLL;SilverLiningOpenGL")
 
 SET(SILVERLINING_FOUND FALSE)
-IF (SILVERLINING_INCLUDE_DIR AND SILVERLINING_LIBRARY_RELEASE AND SILVERLINING_LIBRARY_DEBUG)
+IF (SILVERLINING_INCLUDE_DIR AND SILVERLINING_LIBRARY AND SILVERLINING_LIBRARY_DEBUG)
    SET(SILVERLINING_FOUND TRUE)
-   SET(SILVERLINING_LIBRARY debug ${SILVERLINING_LIBRARY_DEBUG} optimized ${SILVERLINING_LIBRARY_RELEASE})
-ENDIF (SILVERLINING_INCLUDE_DIR AND SILVERLINING_LIBRARY_RELEASE AND SILVERLINING_LIBRARY_DEBUG)
+   #SET(SILVERLINING_LIBRARY debug ${SILVERLINING_LIBRARY_DEBUG} optimized ${SILVERLINING_LIBRARY_RELEASE})
+ENDIF (SILVERLINING_INCLUDE_DIR AND SILVERLINING_LIBRARY AND SILVERLINING_LIBRARY_DEBUG)
 
 IF (SILVERLINING_FOUND)
    IF (NOT SILVERLINING_FIND_QUIETLY)
diff --git a/CMakeModules/FindTriton.cmake b/CMakeModules/FindTriton.cmake
index 91d495f..4c59935 100644
--- a/CMakeModules/FindTriton.cmake
+++ b/CMakeModules/FindTriton.cmake
@@ -43,6 +43,22 @@ IF (MSVC11)
 	ENDIF (CMAKE_CL_64)
 ENDIF (MSVC11)
 
+IF (MSVC12)
+	IF (CMAKE_CL_64)
+		SET(TRITON_ARCH "vc12/x64")
+	ELSE (CMAKE_CL_64)
+		SET(TRITON_ARCH "vc12/win32")
+	ENDIF (CMAKE_CL_64)
+ENDIF (MSVC12)
+
+IF (MSVC14)
+	IF (CMAKE_CL_64)
+		SET(TRITON_ARCH "vc14/x64")
+	ELSE (CMAKE_CL_64)
+		SET(TRITON_ARCH "vc14/win32")
+	ENDIF (CMAKE_CL_64)
+ENDIF (MSVC14)
+
 IF (MSVC71)
 	SET(TRITON_ARCH "vc7")
 ENDIF (MSVC71)
@@ -96,14 +112,14 @@ MACRO(FIND_TRITON_LIBRARY MYLIBRARY MYLIBRARYNAME)
 ENDMACRO(FIND_TRITON_LIBRARY MYLIBRARY MYLIBRARYNAME)
 
 
-FIND_TRITON_LIBRARY(TRITON_LIBRARY_RELEASE "Triton-MT-DLL;Triton")
+FIND_TRITON_LIBRARY(TRITON_LIBRARY       "Triton-MT-DLL;Triton")
 FIND_TRITON_LIBRARY(TRITON_LIBRARY_DEBUG "Triton-MTD-DLL;Triton")
 
 SET(TRITON_FOUND FALSE)
-IF (TRITON_INCLUDE_DIR AND TRITON_LIBRARY_RELEASE AND TRITON_LIBRARY_DEBUG)
+IF (TRITON_INCLUDE_DIR AND TRITON_LIBRARY AND TRITON_LIBRARY_DEBUG)
    SET(TRITON_FOUND TRUE)
-   SET(TRITON_LIBRARY debug ${TRITON_LIBRARY_DEBUG} optimized ${TRITON_LIBRARY_RELEASE})
-ENDIF (TRITON_INCLUDE_DIR AND TRITON_LIBRARY_RELEASE AND TRITON_LIBRARY_DEBUG)
+   #SET(TRITON_LIBRARY debug ${TRITON_LIBRARY_DEBUG} optimized ${TRITON_LIBRARY_RELEASE})
+ENDIF (TRITON_INCLUDE_DIR AND TRITON_LIBRARY AND TRITON_LIBRARY_DEBUG)
 
 IF (TRITON_FOUND)
    IF (NOT TRITON_FIND_QUIETLY)
diff --git a/CMakeModules/OsgEarthMacroUtils.cmake b/CMakeModules/OsgEarthMacroUtils.cmake
index 492e916..ccd5a69 100644
--- a/CMakeModules/OsgEarthMacroUtils.cmake
+++ b/CMakeModules/OsgEarthMacroUtils.cmake
@@ -222,12 +222,6 @@ MACRO(SETUP_PLUGIN PLUGIN_NAME)
         ADD_LIBRARY(${TARGET_TARGETNAME} STATIC ${TARGET_SRC} ${TARGET_H} ${TARGET_GLSL} ${TARGET_IN})
     ENDIF(DYNAMIC_OSGEARTH)
 
-    #not sure if needed, but for plugins only msvc need the d suffix
-    IF(NOT MSVC)
-      IF(NOT UNIX)
-           SET_TARGET_PROPERTIES(${TARGET_TARGETNAME} PROPERTIES DEBUG_POSTFIX "")
-      ENDIF(NOT UNIX)
-    ENDIF(NOT MSVC)
     SET_TARGET_PROPERTIES(${TARGET_TARGETNAME} PROPERTIES PROJECT_LABEL "${TARGET_LABEL}")
 
     SETUP_LINK_LIBRARIES()
@@ -294,12 +288,6 @@ MACRO(SETUP_EXTENSION PLUGIN_NAME)
         ADD_LIBRARY(${TARGET_TARGETNAME} STATIC ${TARGET_SRC} ${TARGET_H} ${TARGET_GLSL} ${TARGET_IN})
     ENDIF(DYNAMIC_OSGEARTH)
 
-    #not sure if needed, but for plugins only msvc need the d suffix
-    IF(NOT MSVC)
-      IF(NOT UNIX)
-           SET_TARGET_PROPERTIES(${TARGET_TARGETNAME} PROPERTIES DEBUG_POSTFIX "")
-      ENDIF(NOT UNIX)
-    ENDIF(NOT MSVC)
     SET_TARGET_PROPERTIES(${TARGET_TARGETNAME} PROPERTIES PROJECT_LABEL "${TARGET_LABEL}")
 
     SETUP_LINK_LIBRARIES()
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..c1de71c
--- /dev/null
+++ b/README.md
@@ -0,0 +1,23 @@
+[![Build Status](https://travis-ci.org/gwaldron/osgearth.svg?branch=master)](https://travis-ci.org/gwaldron/osgearth)
+[![Coverity Status](https://scan.coverity.com/projects/9251/badge.svg)](https://scan.coverity.com/projects/gwaldron-osgearth)
+
+osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+Copyright 2015 Pelican Mapping
+
+http://osgearth.org
+
+osgEarth is free software; you can redistribute it and/or modify
+it under the terms of the GNU Lesser General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+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.
+
+You should have received a copy of the GNU Lesser General Public License
+along with this program.  If not, see <http://www.gnu.org/licenses/>
diff --git a/README.txt b/README.txt
deleted file mode 100644
index a4b0171..0000000
--- a/README.txt
+++ /dev/null
@@ -1,20 +0,0 @@
-osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-Copyright 2015 Pelican Mapping
-
-http://osgearth.org
-
-osgEarth is free software; you can redistribute it and/or modify
-it under the terms of the GNU Lesser General Public License as published by
-the Free Software Foundation; either version 2 of the License, or
-(at your option) any later version.
-
-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.
-
-You should have received a copy of the GNU Lesser General Public License
-along with this program.  If not, see <http://www.gnu.org/licenses/>
diff --git a/docs/CMakeLists.txt b/docs/CMakeLists.txt
index f1ee836..63aeb90 100644
--- a/docs/CMakeLists.txt
+++ b/docs/CMakeLists.txt
@@ -49,7 +49,6 @@ set( DOCS_REFERENCES_DRIVERS_MODEL
     source/references/drivers/model/feature_geom.rst
     source/references/drivers/model/feature_model_shared_blocks.rst
     source/references/drivers/model/feature_model_shared_props.rst
-    source/references/drivers/model/feature_stencil.rst
     source/references/drivers/model/index.rst
     source/references/drivers/model/simple.rst
 )
diff --git a/docs/Doxyfile b/docs/Doxyfile
new file mode 100644
index 0000000..599f020
--- /dev/null
+++ b/docs/Doxyfile
@@ -0,0 +1,2353 @@
+# Doxyfile 1.8.8
+
+# This file describes the settings to be used by the documentation system
+# doxygen (www.doxygen.org) for a project.
+#
+# All text after a double hash (##) is considered a comment and is placed in
+# front of the TAG it is preceding.
+#
+# All text after a single hash (#) is considered a comment and will be ignored.
+# The format is:
+# TAG = value [value, ...]
+# For lists, items can also be appended using:
+# TAG += value [value, ...]
+# Values that contain spaces should be placed between quotes (\" \").
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+
+# This tag specifies the encoding used for all characters in the config file
+# that follow. The default is UTF-8 which is also the encoding used for all text
+# before the first occurrence of this tag. Doxygen uses libiconv (or the iconv
+# built into libc) for the transcoding. See http://www.gnu.org/software/libiconv
+# for the list of possible encodings.
+# The default value is: UTF-8.
+
+DOXYFILE_ENCODING      = UTF-8
+
+# The PROJECT_NAME tag is a single word (or a sequence of words surrounded by
+# double-quotes, unless you are using Doxywizard) that should identify the
+# project for which the documentation is generated. This name is used in the
+# title of most generated pages and in a few other places.
+# The default value is: My Project.
+
+PROJECT_NAME           = "My Project"
+
+# The PROJECT_NUMBER tag can be used to enter a project or revision number. This
+# could be handy for archiving the generated documentation or if some version
+# control system is used.
+
+PROJECT_NUMBER         =
+
+# Using the PROJECT_BRIEF tag one can provide an optional one line description
+# for a project that appears at the top of each page and should give viewer a
+# quick idea about the purpose of the project. Keep the description short.
+
+PROJECT_BRIEF          =
+
+# With the PROJECT_LOGO tag one can specify an logo or icon that is included in
+# the documentation. The maximum height of the logo should not exceed 55 pixels
+# and the maximum width should not exceed 200 pixels. Doxygen will copy the logo
+# to the output directory.
+
+PROJECT_LOGO           =
+
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path
+# into which the generated documentation will be written. If a relative path is
+# entered, it will be relative to the location where doxygen was started. If
+# left blank the current directory will be used.
+
+OUTPUT_DIRECTORY       = APIDocumentation
+
+# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create 4096 sub-
+# directories (in 2 levels) under the output directory of each output format and
+# will distribute the generated files over these directories. Enabling this
+# option can be useful when feeding doxygen a huge amount of source files, where
+# putting all generated files in the same directory would otherwise causes
+# performance problems for the file system.
+# The default value is: NO.
+
+CREATE_SUBDIRS         = NO
+
+# If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII
+# characters to appear in the names of generated files. If set to NO, non-ASCII
+# characters will be escaped, for example _xE3_x81_x84 will be used for Unicode
+# U+3044.
+# The default value is: NO.
+
+ALLOW_UNICODE_NAMES    = NO
+
+# The OUTPUT_LANGUAGE tag is used to specify the language in which all
+# documentation generated by doxygen is written. Doxygen will use this
+# information to generate all constant output in the proper language.
+# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese,
+# Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States),
+# Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian,
+# Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages),
+# Korean, Korean-en (Korean with English messages), Latvian, Lithuanian,
+# Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian,
+# Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish,
+# Ukrainian and Vietnamese.
+# The default value is: English.
+
+OUTPUT_LANGUAGE        = English
+
+# If the BRIEF_MEMBER_DESC tag is set to YES doxygen will include brief member
+# descriptions after the members that are listed in the file and class
+# documentation (similar to Javadoc). Set to NO to disable this.
+# The default value is: YES.
+
+BRIEF_MEMBER_DESC      = YES
+
+# If the REPEAT_BRIEF tag is set to YES doxygen will prepend the brief
+# description of a member or function before the detailed description
+#
+# Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
+# brief descriptions will be completely suppressed.
+# The default value is: YES.
+
+REPEAT_BRIEF           = YES
+
+# This tag implements a quasi-intelligent brief description abbreviator that is
+# used to form the text in various listings. Each string in this list, if found
+# as the leading text of the brief description, will be stripped from the text
+# and the result, after processing the whole list, is used as the annotated
+# text. Otherwise, the brief description is used as-is. If left blank, the
+# following values are used ($name is automatically replaced with the name of
+# the entity):The $name class, The $name widget, The $name file, is, provides,
+# specifies, contains, represents, a, an and the.
+
+ABBREVIATE_BRIEF       =
+
+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
+# doxygen will generate a detailed section even if there is only a brief
+# description.
+# The default value is: NO.
+
+ALWAYS_DETAILED_SEC    = NO
+
+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all
+# inherited members of a class in the documentation of that class as if those
+# members were ordinary class members. Constructors, destructors and assignment
+# operators of the base classes will not be shown.
+# The default value is: NO.
+
+INLINE_INHERITED_MEMB  = NO
+
+# If the FULL_PATH_NAMES tag is set to YES doxygen will prepend the full path
+# before files name in the file list and in the header files. If set to NO the
+# shortest path that makes the file name unique will be used
+# The default value is: YES.
+
+FULL_PATH_NAMES        = YES
+
+# The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path.
+# Stripping is only done if one of the specified strings matches the left-hand
+# part of the path. The tag can be used to show relative paths in the file list.
+# If left blank the directory from which doxygen is run is used as the path to
+# strip.
+#
+# Note that you can specify absolute paths here, but also relative paths, which
+# will be relative from the directory where doxygen is started.
+# This tag requires that the tag FULL_PATH_NAMES is set to YES.
+
+STRIP_FROM_PATH        =
+
+# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the
+# path mentioned in the documentation of a class, which tells the reader which
+# header file to include in order to use a class. If left blank only the name of
+# the header file containing the class definition is used. Otherwise one should
+# specify the list of include paths that are normally passed to the compiler
+# using the -I flag.
+
+STRIP_FROM_INC_PATH    =
+
+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but
+# less readable) file names. This can be useful is your file systems doesn't
+# support long names like on DOS, Mac, or CD-ROM.
+# The default value is: NO.
+
+SHORT_NAMES            = NO
+
+# If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the
+# first line (until the first dot) of a Javadoc-style comment as the brief
+# description. If set to NO, the Javadoc-style will behave just like regular Qt-
+# style comments (thus requiring an explicit @brief command for a brief
+# description.)
+# The default value is: NO.
+
+JAVADOC_AUTOBRIEF      = YES
+
+# If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first
+# line (until the first dot) of a Qt-style comment as the brief description. If
+# set to NO, the Qt-style will behave just like regular Qt-style comments (thus
+# requiring an explicit \brief command for a brief description.)
+# The default value is: NO.
+
+QT_AUTOBRIEF           = YES
+
+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a
+# multi-line C++ special comment block (i.e. a block of //! or /// comments) as
+# a brief description. This used to be the default behavior. The new default is
+# to treat a multi-line C++ comment block as a detailed description. Set this
+# tag to YES if you prefer the old behavior instead.
+#
+# Note that setting this tag to YES also means that rational rose comments are
+# not recognized any more.
+# The default value is: NO.
+
+MULTILINE_CPP_IS_BRIEF = NO
+
+# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the
+# documentation from any documented member that it re-implements.
+# The default value is: YES.
+
+INHERIT_DOCS           = YES
+
+# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce a
+# new page for each member. If set to NO, the documentation of a member will be
+# part of the file/class/namespace that contains it.
+# The default value is: NO.
+
+SEPARATE_MEMBER_PAGES  = NO
+
+# The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen
+# uses this value to replace tabs by spaces in code fragments.
+# Minimum value: 1, maximum value: 16, default value: 4.
+
+TAB_SIZE               = 4
+
+# This tag can be used to specify a number of aliases that act as commands in
+# the documentation. An alias has the form:
+# name=value
+# For example adding
+# "sideeffect=@par Side Effects:\n"
+# will allow you to put the command \sideeffect (or @sideeffect) in the
+# documentation, which will result in a user-defined paragraph with heading
+# "Side Effects:". You can put \n's in the value part of an alias to insert
+# newlines.
+
+ALIASES                =
+
+# This tag can be used to specify a number of word-keyword mappings (TCL only).
+# A mapping has the form "name=value". For example adding "class=itcl::class"
+# will allow you to use the command class in the itcl::class meaning.
+
+TCL_SUBST              =
+
+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources
+# only. Doxygen will then generate output that is more tailored for C. For
+# instance, some of the names that are used will be different. The list of all
+# members will be omitted, etc.
+# The default value is: NO.
+
+OPTIMIZE_OUTPUT_FOR_C  = NO
+
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or
+# Python sources only. Doxygen will then generate output that is more tailored
+# for that language. For instance, namespaces will be presented as packages,
+# qualified scopes will look different, etc.
+# The default value is: NO.
+
+OPTIMIZE_OUTPUT_JAVA   = NO
+
+# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran
+# sources. Doxygen will then generate output that is tailored for Fortran.
+# The default value is: NO.
+
+OPTIMIZE_FOR_FORTRAN   = NO
+
+# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL
+# sources. Doxygen will then generate output that is tailored for VHDL.
+# The default value is: NO.
+
+OPTIMIZE_OUTPUT_VHDL   = NO
+
+# Doxygen selects the parser to use depending on the extension of the files it
+# parses. With this tag you can assign which parser to use for a given
+# extension. Doxygen has a built-in mapping, but you can override or extend it
+# using this tag. The format is ext=language, where ext is a file extension, and
+# language is one of the parsers supported by doxygen: IDL, Java, Javascript,
+# C#, C, C++, D, PHP, Objective-C, Python, Fortran (fixed format Fortran:
+# FortranFixed, free formatted Fortran: FortranFree, unknown formatted Fortran:
+# Fortran. In the later case the parser tries to guess whether the code is fixed
+# or free formatted code, this is the default for Fortran type files), VHDL. For
+# instance to make doxygen treat .inc files as Fortran files (default is PHP),
+# and .f files as C (default is Fortran), use: inc=Fortran f=C.
+#
+# Note For files without extension you can use no_extension as a placeholder.
+#
+# Note that for custom extensions you also need to set FILE_PATTERNS otherwise
+# the files are not read by doxygen.
+
+EXTENSION_MAPPING      =
+
+# If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments
+# according to the Markdown format, which allows for more readable
+# documentation. See http://daringfireball.net/projects/markdown/ for details.
+# The output of markdown processing is further processed by doxygen, so you can
+# mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in
+# case of backward compatibilities issues.
+# The default value is: YES.
+
+MARKDOWN_SUPPORT       = YES
+
+# When enabled doxygen tries to link words that correspond to documented
+# classes, or namespaces to their corresponding documentation. Such a link can
+# be prevented in individual cases by by putting a % sign in front of the word
+# or globally by setting AUTOLINK_SUPPORT to NO.
+# The default value is: YES.
+
+AUTOLINK_SUPPORT       = YES
+
+# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want
+# to include (a tag file for) the STL sources as input, then you should set this
+# tag to YES in order to let doxygen match functions declarations and
+# definitions whose arguments contain STL classes (e.g. func(std::string);
+# versus func(std::string) {}). This also make the inheritance and collaboration
+# diagrams that involve STL classes more complete and accurate.
+# The default value is: NO.
+
+BUILTIN_STL_SUPPORT    = NO
+
+# If you use Microsoft's C++/CLI language, you should set this option to YES to
+# enable parsing support.
+# The default value is: NO.
+
+CPP_CLI_SUPPORT        = NO
+
+# Set the SIP_SUPPORT tag to YES if your project consists of sip (see:
+# http://www.riverbankcomputing.co.uk/software/sip/intro) sources only. Doxygen
+# will parse them like normal C++ but will assume all classes use public instead
+# of private inheritance when no explicit protection keyword is present.
+# The default value is: NO.
+
+SIP_SUPPORT            = NO
+
+# For Microsoft's IDL there are propget and propput attributes to indicate
+# getter and setter methods for a property. Setting this option to YES will make
+# doxygen to replace the get and set methods by a property in the documentation.
+# This will only work if the methods are indeed getting or setting a simple
+# type. If this is not the case, or you want to show the methods anyway, you
+# should set this option to NO.
+# The default value is: YES.
+
+IDL_PROPERTY_SUPPORT   = YES
+
+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
+# tag is set to YES, then doxygen will reuse the documentation of the first
+# member in the group (if any) for the other members of the group. By default
+# all members of a group must be documented explicitly.
+# The default value is: NO.
+
+DISTRIBUTE_GROUP_DOC   = NO
+
+# Set the SUBGROUPING tag to YES to allow class member groups of the same type
+# (for instance a group of public functions) to be put as a subgroup of that
+# type (e.g. under the Public Functions section). Set it to NO to prevent
+# subgrouping. Alternatively, this can be done per class using the
+# \nosubgrouping command.
+# The default value is: YES.
+
+SUBGROUPING            = YES
+
+# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions
+# are shown inside the group in which they are included (e.g. using \ingroup)
+# instead of on a separate page (for HTML and Man pages) or section (for LaTeX
+# and RTF).
+#
+# Note that this feature does not work in combination with
+# SEPARATE_MEMBER_PAGES.
+# The default value is: NO.
+
+INLINE_GROUPED_CLASSES = NO
+
+# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions
+# with only public data fields or simple typedef fields will be shown inline in
+# the documentation of the scope in which they are defined (i.e. file,
+# namespace, or group documentation), provided this scope is documented. If set
+# to NO, structs, classes, and unions are shown on a separate page (for HTML and
+# Man pages) or section (for LaTeX and RTF).
+# The default value is: NO.
+
+INLINE_SIMPLE_STRUCTS  = NO
+
+# When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or
+# enum is documented as struct, union, or enum with the name of the typedef. So
+# typedef struct TypeS {} TypeT, will appear in the documentation as a struct
+# with name TypeT. When disabled the typedef will appear as a member of a file,
+# namespace, or class. And the struct will be named TypeS. This can typically be
+# useful for C code in case the coding convention dictates that all compound
+# types are typedef'ed and only the typedef is referenced, never the tag name.
+# The default value is: NO.
+
+TYPEDEF_HIDES_STRUCT   = NO
+
+# The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This
+# cache is used to resolve symbols given their name and scope. Since this can be
+# an expensive process and often the same symbol appears multiple times in the
+# code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small
+# doxygen will become slower. If the cache is too large, memory is wasted. The
+# cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range
+# is 0..9, the default is 0, corresponding to a cache size of 2^16=65536
+# symbols. At the end of a run doxygen will report the cache usage and suggest
+# the optimal cache size from a speed point of view.
+# Minimum value: 0, maximum value: 9, default value: 0.
+
+LOOKUP_CACHE_SIZE      = 0
+
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+
+# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in
+# documentation are documented, even if no documentation was available. Private
+# class members and static file members will be hidden unless the
+# EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES.
+# Note: This will also disable the warnings about undocumented members that are
+# normally produced when WARNINGS is set to YES.
+# The default value is: NO.
+
+EXTRACT_ALL            = YES
+
+# If the EXTRACT_PRIVATE tag is set to YES all private members of a class will
+# be included in the documentation.
+# The default value is: NO.
+
+EXTRACT_PRIVATE        = NO
+
+# If the EXTRACT_PACKAGE tag is set to YES all members with package or internal
+# scope will be included in the documentation.
+# The default value is: NO.
+
+EXTRACT_PACKAGE        = NO
+
+# If the EXTRACT_STATIC tag is set to YES all static members of a file will be
+# included in the documentation.
+# The default value is: NO.
+
+EXTRACT_STATIC         = NO
+
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) defined
+# locally in source files will be included in the documentation. If set to NO
+# only classes defined in header files are included. Does not have any effect
+# for Java sources.
+# The default value is: YES.
+
+EXTRACT_LOCAL_CLASSES  = YES
+
+# This flag is only useful for Objective-C code. When set to YES local methods,
+# which are defined in the implementation section but not in the interface are
+# included in the documentation. If set to NO only methods in the interface are
+# included.
+# The default value is: NO.
+
+EXTRACT_LOCAL_METHODS  = NO
+
+# If this flag is set to YES, the members of anonymous namespaces will be
+# extracted and appear in the documentation as a namespace called
+# 'anonymous_namespace{file}', where file will be replaced with the base name of
+# the file that contains the anonymous namespace. By default anonymous namespace
+# are hidden.
+# The default value is: NO.
+
+EXTRACT_ANON_NSPACES   = NO
+
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all
+# undocumented members inside documented classes or files. If set to NO these
+# members will be included in the various overviews, but no documentation
+# section is generated. This option has no effect if EXTRACT_ALL is enabled.
+# The default value is: NO.
+
+HIDE_UNDOC_MEMBERS     = NO
+
+# If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all
+# undocumented classes that are normally visible in the class hierarchy. If set
+# to NO these classes will be included in the various overviews. This option has
+# no effect if EXTRACT_ALL is enabled.
+# The default value is: NO.
+
+HIDE_UNDOC_CLASSES     = NO
+
+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend
+# (class|struct|union) declarations. If set to NO these declarations will be
+# included in the documentation.
+# The default value is: NO.
+
+HIDE_FRIEND_COMPOUNDS  = NO
+
+# If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any
+# documentation blocks found inside the body of a function. If set to NO these
+# blocks will be appended to the function's detailed documentation block.
+# The default value is: NO.
+
+HIDE_IN_BODY_DOCS      = NO
+
+# The INTERNAL_DOCS tag determines if documentation that is typed after a
+# \internal command is included. If the tag is set to NO then the documentation
+# will be excluded. Set it to YES to include the internal documentation.
+# The default value is: NO.
+
+INTERNAL_DOCS          = NO
+
+# If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file
+# names in lower-case letters. If set to YES upper-case letters are also
+# allowed. This is useful if you have classes or files whose names only differ
+# in case and if your file system supports case sensitive file names. Windows
+# and Mac users are advised to set this option to NO.
+# The default value is: system dependent.
+
+CASE_SENSE_NAMES       = YES
+
+# If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with
+# their full class and namespace scopes in the documentation. If set to YES the
+# scope will be hidden.
+# The default value is: NO.
+
+HIDE_SCOPE_NAMES       = NO
+
+# If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of
+# the files that are included by a file in the documentation of that file.
+# The default value is: YES.
+
+SHOW_INCLUDE_FILES     = YES
+
+# If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each
+# grouped member an include statement to the documentation, telling the reader
+# which file to include in order to use the member.
+# The default value is: NO.
+
+SHOW_GROUPED_MEMB_INC  = NO
+
+# If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include
+# files with double quotes in the documentation rather than with sharp brackets.
+# The default value is: NO.
+
+FORCE_LOCAL_INCLUDES   = NO
+
+# If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the
+# documentation for inline members.
+# The default value is: YES.
+
+INLINE_INFO            = YES
+
+# If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the
+# (detailed) documentation of file and class members alphabetically by member
+# name. If set to NO the members will appear in declaration order.
+# The default value is: YES.
+
+SORT_MEMBER_DOCS       = YES
+
+# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief
+# descriptions of file, namespace and class members alphabetically by member
+# name. If set to NO the members will appear in declaration order. Note that
+# this will also influence the order of the classes in the class list.
+# The default value is: NO.
+
+SORT_BRIEF_DOCS        = NO
+
+# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the
+# (brief and detailed) documentation of class members so that constructors and
+# destructors are listed first. If set to NO the constructors will appear in the
+# respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS.
+# Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief
+# member documentation.
+# Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting
+# detailed member documentation.
+# The default value is: NO.
+
+SORT_MEMBERS_CTORS_1ST = NO
+
+# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy
+# of group names into alphabetical order. If set to NO the group names will
+# appear in their defined order.
+# The default value is: NO.
+
+SORT_GROUP_NAMES       = NO
+
+# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by
+# fully-qualified names, including namespaces. If set to NO, the class list will
+# be sorted only by class name, not including the namespace part.
+# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
+# Note: This option applies only to the class list, not to the alphabetical
+# list.
+# The default value is: NO.
+
+SORT_BY_SCOPE_NAME     = NO
+
+# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper
+# type resolution of all parameters of a function it will reject a match between
+# the prototype and the implementation of a member function even if there is
+# only one candidate or it is obvious which candidate to choose by doing a
+# simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still
+# accept a match between prototype and implementation in such cases.
+# The default value is: NO.
+
+STRICT_PROTO_MATCHING  = NO
+
+# The GENERATE_TODOLIST tag can be used to enable ( YES) or disable ( NO) the
+# todo list. This list is created by putting \todo commands in the
+# documentation.
+# The default value is: YES.
+
+GENERATE_TODOLIST      = YES
+
+# The GENERATE_TESTLIST tag can be used to enable ( YES) or disable ( NO) the
+# test list. This list is created by putting \test commands in the
+# documentation.
+# The default value is: YES.
+
+GENERATE_TESTLIST      = YES
+
+# The GENERATE_BUGLIST tag can be used to enable ( YES) or disable ( NO) the bug
+# list. This list is created by putting \bug commands in the documentation.
+# The default value is: YES.
+
+GENERATE_BUGLIST       = YES
+
+# The GENERATE_DEPRECATEDLIST tag can be used to enable ( YES) or disable ( NO)
+# the deprecated list. This list is created by putting \deprecated commands in
+# the documentation.
+# The default value is: YES.
+
+GENERATE_DEPRECATEDLIST= YES
+
+# The ENABLED_SECTIONS tag can be used to enable conditional documentation
+# sections, marked by \if <section_label> ... \endif and \cond <section_label>
+# ... \endcond blocks.
+
+ENABLED_SECTIONS       =
+
+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the
+# initial value of a variable or macro / define can have for it to appear in the
+# documentation. If the initializer consists of more lines than specified here
+# it will be hidden. Use a value of 0 to hide initializers completely. The
+# appearance of the value of individual variables and macros / defines can be
+# controlled using \showinitializer or \hideinitializer command in the
+# documentation regardless of this setting.
+# Minimum value: 0, maximum value: 10000, default value: 30.
+
+MAX_INITIALIZER_LINES  = 30
+
+# Set the SHOW_USED_FILES tag to NO to disable the list of files generated at
+# the bottom of the documentation of classes and structs. If set to YES the list
+# will mention the files that were used to generate the documentation.
+# The default value is: YES.
+
+SHOW_USED_FILES        = YES
+
+# Set the SHOW_FILES tag to NO to disable the generation of the Files page. This
+# will remove the Files entry from the Quick Index and from the Folder Tree View
+# (if specified).
+# The default value is: YES.
+
+SHOW_FILES             = YES
+
+# Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces
+# page. This will remove the Namespaces entry from the Quick Index and from the
+# Folder Tree View (if specified).
+# The default value is: YES.
+
+SHOW_NAMESPACES        = YES
+
+# The FILE_VERSION_FILTER tag can be used to specify a program or script that
+# doxygen should invoke to get the current version for each file (typically from
+# the version control system). Doxygen will invoke the program by executing (via
+# popen()) the command command input-file, where command is the value of the
+# FILE_VERSION_FILTER tag, and input-file is the name of an input file provided
+# by doxygen. Whatever the program writes to standard output is used as the file
+# version. For an example see the documentation.
+
+FILE_VERSION_FILTER    =
+
+# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed
+# by doxygen. The layout file controls the global structure of the generated
+# output files in an output format independent way. To create the layout file
+# that represents doxygen's defaults, run doxygen with the -l option. You can
+# optionally specify a file name after the option, if omitted DoxygenLayout.xml
+# will be used as the name of the layout file.
+#
+# Note that if you run doxygen from a directory containing a file called
+# DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE
+# tag is left empty.
+
+LAYOUT_FILE            =
+
+# The CITE_BIB_FILES tag can be used to specify one or more bib files containing
+# the reference definitions. This must be a list of .bib files. The .bib
+# extension is automatically appended if omitted. This requires the bibtex tool
+# to be installed. See also http://en.wikipedia.org/wiki/BibTeX for more info.
+# For LaTeX the style of the bibliography can be controlled using
+# LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the
+# search path. See also \cite for info how to create references.
+
+CITE_BIB_FILES         =
+
+#---------------------------------------------------------------------------
+# Configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+
+# The QUIET tag can be used to turn on/off the messages that are generated to
+# standard output by doxygen. If QUIET is set to YES this implies that the
+# messages are off.
+# The default value is: NO.
+
+QUIET                  = NO
+
+# The WARNINGS tag can be used to turn on/off the warning messages that are
+# generated to standard error ( stderr) by doxygen. If WARNINGS is set to YES
+# this implies that the warnings are on.
+#
+# Tip: Turn warnings on while writing the documentation.
+# The default value is: YES.
+
+WARNINGS               = YES
+
+# If the WARN_IF_UNDOCUMENTED tag is set to YES, then doxygen will generate
+# warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag
+# will automatically be disabled.
+# The default value is: YES.
+
+WARN_IF_UNDOCUMENTED   = YES
+
+# If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for
+# potential errors in the documentation, such as not documenting some parameters
+# in a documented function, or documenting parameters that don't exist or using
+# markup commands wrongly.
+# The default value is: YES.
+
+WARN_IF_DOC_ERROR      = YES
+
+# This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that
+# are documented, but have no documentation for their parameters or return
+# value. If set to NO doxygen will only warn about wrong or incomplete parameter
+# documentation, but not about the absence of documentation.
+# The default value is: NO.
+
+WARN_NO_PARAMDOC       = NO
+
+# The WARN_FORMAT tag determines the format of the warning messages that doxygen
+# can produce. The string should contain the $file, $line, and $text tags, which
+# will be replaced by the file and line number from which the warning originated
+# and the warning text. Optionally the format may contain $version, which will
+# be replaced by the version of the file (if it could be obtained via
+# FILE_VERSION_FILTER)
+# The default value is: $file:$line: $text.
+
+WARN_FORMAT            = "$file:$line: $text"
+
+# The WARN_LOGFILE tag can be used to specify a file to which warning and error
+# messages should be written. If left blank the output is written to standard
+# error (stderr).
+
+WARN_LOGFILE           =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the input files
+#---------------------------------------------------------------------------
+
+# The INPUT tag is used to specify the files and/or directories that contain
+# documented source files. You may enter file names like myfile.cpp or
+# directories like /usr/src/myproject. Separate the files or directories with
+# spaces.
+# Note: If this tag is empty the current directory is searched.
+
+INPUT                  = ../src
+
+# This tag can be used to specify the character encoding of the source files
+# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
+# libiconv (or the iconv built into libc) for the transcoding. See the libiconv
+# documentation (see: http://www.gnu.org/software/libiconv) for the list of
+# possible encodings.
+# The default value is: UTF-8.
+
+INPUT_ENCODING         = UTF-8
+
+# If the value of the INPUT tag contains directories, you can use the
+# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and
+# *.h) to filter out the source-files in the directories. If left blank the
+# following patterns are tested:*.c, *.cc, *.cxx, *.cpp, *.c++, *.java, *.ii,
+# *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, *.hh, *.hxx, *.hpp,
+# *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc, *.m, *.markdown,
+# *.md, *.mm, *.dox, *.py, *.f90, *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf,
+# *.qsf, *.as and *.js.
+
+FILE_PATTERNS          = *
+
+# The RECURSIVE tag can be used to specify whether or not subdirectories should
+# be searched for input files as well.
+# The default value is: NO.
+
+RECURSIVE              = YES
+
+# The EXCLUDE tag can be used to specify files and/or directories that should be
+# excluded from the INPUT source files. This way you can easily exclude a
+# subdirectory from a directory tree whose root is specified with the INPUT tag.
+#
+# Note that relative paths are relative to the directory from which doxygen is
+# run.
+
+EXCLUDE                =
+
+# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or
+# directories that are symbolic links (a Unix file system feature) are excluded
+# from the input.
+# The default value is: NO.
+
+EXCLUDE_SYMLINKS       = NO
+
+# If the value of the INPUT tag contains directories, you can use the
+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
+# certain files from those directories.
+#
+# Note that the wildcards are matched against the file with absolute path, so to
+# exclude all test directories for example use the pattern */test/*
+
+EXCLUDE_PATTERNS       =
+
+# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
+# (namespaces, classes, functions, etc.) that should be excluded from the
+# output. The symbol name can be a fully qualified name, a word, or if the
+# wildcard * is used, a substring. Examples: ANamespace, AClass,
+# AClass::ANamespace, ANamespace::*Test
+#
+# Note that the wildcards are matched against the file with absolute path, so to
+# exclude all test directories use the pattern */test/*
+
+EXCLUDE_SYMBOLS        =
+
+# The EXAMPLE_PATH tag can be used to specify one or more files or directories
+# that contain example code fragments that are included (see the \include
+# command).
+
+EXAMPLE_PATH           =
+
+# If the value of the EXAMPLE_PATH tag contains directories, you can use the
+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and
+# *.h) to filter out the source-files in the directories. If left blank all
+# files are included.
+
+EXAMPLE_PATTERNS       =
+
+# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
+# searched for input files to be used with the \include or \dontinclude commands
+# irrespective of the value of the RECURSIVE tag.
+# The default value is: NO.
+
+EXAMPLE_RECURSIVE      = NO
+
+# The IMAGE_PATH tag can be used to specify one or more files or directories
+# that contain images that are to be included in the documentation (see the
+# \image command).
+
+IMAGE_PATH             =
+
+# The INPUT_FILTER tag can be used to specify a program that doxygen should
+# invoke to filter for each input file. Doxygen will invoke the filter program
+# by executing (via popen()) the command:
+#
+# <filter> <input-file>
+#
+# where <filter> is the value of the INPUT_FILTER tag, and <input-file> is the
+# name of an input file. Doxygen will then use the output that the filter
+# program writes to standard output. If FILTER_PATTERNS is specified, this tag
+# will be ignored.
+#
+# Note that the filter must not add or remove lines; it is applied before the
+# code is scanned, but not when the output code is generated. If lines are added
+# or removed, the anchors will not be placed correctly.
+
+INPUT_FILTER           =
+
+# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
+# basis. Doxygen will compare the file name with each pattern and apply the
+# filter if there is a match. The filters are a list of the form: pattern=filter
+# (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how
+# filters are used. If the FILTER_PATTERNS tag is empty or if none of the
+# patterns match the file name, INPUT_FILTER is applied.
+
+FILTER_PATTERNS        =
+
+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
+# INPUT_FILTER ) will also be used to filter the input files that are used for
+# producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES).
+# The default value is: NO.
+
+FILTER_SOURCE_FILES    = NO
+
+# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file
+# pattern. A pattern will override the setting for FILTER_PATTERN (if any) and
+# it is also possible to disable source filtering for a specific pattern using
+# *.ext= (so without naming a filter).
+# This tag requires that the tag FILTER_SOURCE_FILES is set to YES.
+
+FILTER_SOURCE_PATTERNS =
+
+# If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that
+# is part of the input, its contents will be placed on the main page
+# (index.html). This can be useful if you have a project on for instance GitHub
+# and want to reuse the introduction page also for the doxygen output.
+
+USE_MDFILE_AS_MAINPAGE =
+
+#---------------------------------------------------------------------------
+# Configuration options related to source browsing
+#---------------------------------------------------------------------------
+
+# If the SOURCE_BROWSER tag is set to YES then a list of source files will be
+# generated. Documented entities will be cross-referenced with these sources.
+#
+# Note: To get rid of all source code in the generated output, make sure that
+# also VERBATIM_HEADERS is set to NO.
+# The default value is: NO.
+
+SOURCE_BROWSER         = NO
+
+# Setting the INLINE_SOURCES tag to YES will include the body of functions,
+# classes and enums directly into the documentation.
+# The default value is: NO.
+
+INLINE_SOURCES         = NO
+
+# Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any
+# special comment blocks from generated source code fragments. Normal C, C++ and
+# Fortran comments will always remain visible.
+# The default value is: YES.
+
+STRIP_CODE_COMMENTS    = YES
+
+# If the REFERENCED_BY_RELATION tag is set to YES then for each documented
+# function all documented functions referencing it will be listed.
+# The default value is: NO.
+
+REFERENCED_BY_RELATION = NO
+
+# If the REFERENCES_RELATION tag is set to YES then for each documented function
+# all documented entities called/used by that function will be listed.
+# The default value is: NO.
+
+REFERENCES_RELATION    = NO
+
+# If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set
+# to YES, then the hyperlinks from functions in REFERENCES_RELATION and
+# REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will
+# link to the documentation.
+# The default value is: YES.
+
+REFERENCES_LINK_SOURCE = YES
+
+# If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the
+# source code will show a tooltip with additional information such as prototype,
+# brief description and links to the definition and documentation. Since this
+# will make the HTML file larger and loading of large files a bit slower, you
+# can opt to disable this feature.
+# The default value is: YES.
+# This tag requires that the tag SOURCE_BROWSER is set to YES.
+
+SOURCE_TOOLTIPS        = YES
+
+# If the USE_HTAGS tag is set to YES then the references to source code will
+# point to the HTML generated by the htags(1) tool instead of doxygen built-in
+# source browser. The htags tool is part of GNU's global source tagging system
+# (see http://www.gnu.org/software/global/global.html). You will need version
+# 4.8.6 or higher.
+#
+# To use it do the following:
+# - Install the latest version of global
+# - Enable SOURCE_BROWSER and USE_HTAGS in the config file
+# - Make sure the INPUT points to the root of the source tree
+# - Run doxygen as normal
+#
+# Doxygen will invoke htags (and that will in turn invoke gtags), so these
+# tools must be available from the command line (i.e. in the search path).
+#
+# The result: instead of the source browser generated by doxygen, the links to
+# source code will now point to the output of htags.
+# The default value is: NO.
+# This tag requires that the tag SOURCE_BROWSER is set to YES.
+
+USE_HTAGS              = NO
+
+# If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a
+# verbatim copy of the header file for each class for which an include is
+# specified. Set to NO to disable this.
+# See also: Section \class.
+# The default value is: YES.
+
+VERBATIM_HEADERS       = YES
+
+# If the CLANG_ASSISTED_PARSING tag is set to YES, then doxygen will use the
+# clang parser (see: http://clang.llvm.org/) for more accurate parsing at the
+# cost of reduced performance. This can be particularly helpful with template
+# rich C++ code for which doxygen's built-in parser lacks the necessary type
+# information.
+# Note: The availability of this option depends on whether or not doxygen was
+# compiled with the --with-libclang option.
+# The default value is: NO.
+
+CLANG_ASSISTED_PARSING = NO
+
+# If clang assisted parsing is enabled you can provide the compiler with command
+# line options that you would normally use when invoking the compiler. Note that
+# the include paths will already be set by doxygen for the files and directories
+# specified with INPUT and INCLUDE_PATH.
+# This tag requires that the tag CLANG_ASSISTED_PARSING is set to YES.
+
+CLANG_OPTIONS          =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+
+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all
+# compounds will be generated. Enable this if the project contains a lot of
+# classes, structs, unions or interfaces.
+# The default value is: YES.
+
+ALPHABETICAL_INDEX     = YES
+
+# The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in
+# which the alphabetical index list will be split.
+# Minimum value: 1, maximum value: 20, default value: 5.
+# This tag requires that the tag ALPHABETICAL_INDEX is set to YES.
+
+COLS_IN_ALPHA_INDEX    = 5
+
+# In case all classes in a project start with a common prefix, all classes will
+# be put under the same header in the alphabetical index. The IGNORE_PREFIX tag
+# can be used to specify a prefix (or a list of prefixes) that should be ignored
+# while generating the index headers.
+# This tag requires that the tag ALPHABETICAL_INDEX is set to YES.
+
+IGNORE_PREFIX          =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the HTML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_HTML tag is set to YES doxygen will generate HTML output
+# The default value is: YES.
+
+GENERATE_HTML          = YES
+
+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: html.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_OUTPUT            = html
+
+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each
+# generated HTML page (for example: .htm, .php, .asp).
+# The default value is: .html.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_FILE_EXTENSION    = .html
+
+# The HTML_HEADER tag can be used to specify a user-defined HTML header file for
+# each generated HTML page. If the tag is left blank doxygen will generate a
+# standard header.
+#
+# To get valid HTML the header file that includes any scripts and style sheets
+# that doxygen needs, which is dependent on the configuration options used (e.g.
+# the setting GENERATE_TREEVIEW). It is highly recommended to start with a
+# default header using
+# doxygen -w html new_header.html new_footer.html new_stylesheet.css
+# YourConfigFile
+# and then modify the file new_header.html. See also section "Doxygen usage"
+# for information on how to generate the default header that doxygen normally
+# uses.
+# Note: The header is subject to change so you typically have to regenerate the
+# default header when upgrading to a newer version of doxygen. For a description
+# of the possible markers and block names see the documentation.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_HEADER            =
+
+# The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each
+# generated HTML page. If the tag is left blank doxygen will generate a standard
+# footer. See HTML_HEADER for more information on how to generate a default
+# footer and what special commands can be used inside the footer. See also
+# section "Doxygen usage" for information on how to generate the default footer
+# that doxygen normally uses.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_FOOTER            =
+
+# The HTML_STYLESHEET tag can be used to specify a user-defined cascading style
+# sheet that is used by each HTML page. It can be used to fine-tune the look of
+# the HTML output. If left blank doxygen will generate a default style sheet.
+# See also section "Doxygen usage" for information on how to generate the style
+# sheet that doxygen normally uses.
+# Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as
+# it is more robust and this tag (HTML_STYLESHEET) will in the future become
+# obsolete.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_STYLESHEET        =
+
+# The HTML_EXTRA_STYLESHEET tag can be used to specify additional user-defined
+# cascading style sheets that are included after the standard style sheets
+# created by doxygen. Using this option one can overrule certain style aspects.
+# This is preferred over using HTML_STYLESHEET since it does not replace the
+# standard style sheet and is therefor more robust against future updates.
+# Doxygen will copy the style sheet files to the output directory.
+# Note: The order of the extra stylesheet files is of importance (e.g. the last
+# stylesheet in the list overrules the setting of the previous ones in the
+# list). For an example see the documentation.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_EXTRA_STYLESHEET  =
+
+# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or
+# other source files which should be copied to the HTML output directory. Note
+# that these files will be copied to the base HTML output directory. Use the
+# $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these
+# files. In the HTML_STYLESHEET file, use the file name only. Also note that the
+# files will be copied as-is; there are no commands or markers available.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_EXTRA_FILES       =
+
+# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen
+# will adjust the colors in the stylesheet and background images according to
+# this color. Hue is specified as an angle on a colorwheel, see
+# http://en.wikipedia.org/wiki/Hue for more information. For instance the value
+# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300
+# purple, and 360 is red again.
+# Minimum value: 0, maximum value: 359, default value: 220.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_COLORSTYLE_HUE    = 220
+
+# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors
+# in the HTML output. For a value of 0 the output will use grayscales only. A
+# value of 255 will produce the most vivid colors.
+# Minimum value: 0, maximum value: 255, default value: 100.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_COLORSTYLE_SAT    = 100
+
+# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the
+# luminance component of the colors in the HTML output. Values below 100
+# gradually make the output lighter, whereas values above 100 make the output
+# darker. The value divided by 100 is the actual gamma applied, so 80 represents
+# a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not
+# change the gamma.
+# Minimum value: 40, maximum value: 240, default value: 80.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_COLORSTYLE_GAMMA  = 80
+
+# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML
+# page will contain the date and time when the page was generated. Setting this
+# to NO can help when comparing the output of multiple runs.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_TIMESTAMP         = YES
+
+# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
+# documentation will contain sections that can be hidden and shown after the
+# page has loaded.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_DYNAMIC_SECTIONS  = NO
+
+# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries
+# shown in the various tree structured indices initially; the user can expand
+# and collapse entries dynamically later on. Doxygen will expand the tree to
+# such a level that at most the specified number of entries are visible (unless
+# a fully collapsed tree already exceeds this amount). So setting the number of
+# entries 1 will produce a full collapsed tree by default. 0 is a special value
+# representing an infinite number of entries and will result in a full expanded
+# tree by default.
+# Minimum value: 0, maximum value: 9999, default value: 100.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_INDEX_NUM_ENTRIES = 100
+
+# If the GENERATE_DOCSET tag is set to YES, additional index files will be
+# generated that can be used as input for Apple's Xcode 3 integrated development
+# environment (see: http://developer.apple.com/tools/xcode/), introduced with
+# OSX 10.5 (Leopard). To create a documentation set, doxygen will generate a
+# Makefile in the HTML output directory. Running make will produce the docset in
+# that directory and running make install will install the docset in
+# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at
+# startup. See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html
+# for more information.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_DOCSET        = NO
+
+# This tag determines the name of the docset feed. A documentation feed provides
+# an umbrella under which multiple documentation sets from a single provider
+# (such as a company or product suite) can be grouped.
+# The default value is: Doxygen generated docs.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_FEEDNAME        = "Doxygen generated docs"
+
+# This tag specifies a string that should uniquely identify the documentation
+# set bundle. This should be a reverse domain-name style string, e.g.
+# com.mycompany.MyDocSet. Doxygen will append .docset to the name.
+# The default value is: org.doxygen.Project.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_BUNDLE_ID       = org.doxygen.Project
+
+# The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify
+# the documentation publisher. This should be a reverse domain-name style
+# string, e.g. com.mycompany.MyDocSet.documentation.
+# The default value is: org.doxygen.Publisher.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_PUBLISHER_ID    = org.doxygen.Publisher
+
+# The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher.
+# The default value is: Publisher.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_PUBLISHER_NAME  = Publisher
+
+# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three
+# additional HTML index files: index.hhp, index.hhc, and index.hhk. The
+# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop
+# (see: http://www.microsoft.com/en-us/download/details.aspx?id=21138) on
+# Windows.
+#
+# The HTML Help Workshop contains a compiler that can convert all HTML output
+# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML
+# files are now used as the Windows 98 help format, and will replace the old
+# Windows help format (.hlp) on all Windows platforms in the future. Compressed
+# HTML files also contain an index, a table of contents, and you can search for
+# words in the documentation. The HTML workshop also contains a viewer for
+# compressed HTML files.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_HTMLHELP      = NO
+
+# The CHM_FILE tag can be used to specify the file name of the resulting .chm
+# file. You can add a path in front of the file if the result should not be
+# written to the html output directory.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+CHM_FILE               =
+
+# The HHC_LOCATION tag can be used to specify the location (absolute path
+# including file name) of the HTML help compiler ( hhc.exe). If non-empty
+# doxygen will try to run the HTML help compiler on the generated index.hhp.
+# The file has to be specified with full path.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+HHC_LOCATION           =
+
+# The GENERATE_CHI flag controls if a separate .chi index file is generated (
+# YES) or that it should be included in the master .chm file ( NO).
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+GENERATE_CHI           = NO
+
+# The CHM_INDEX_ENCODING is used to encode HtmlHelp index ( hhk), content ( hhc)
+# and project file content.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+CHM_INDEX_ENCODING     =
+
+# The BINARY_TOC flag controls whether a binary table of contents is generated (
+# YES) or a normal table of contents ( NO) in the .chm file. Furthermore it
+# enables the Previous and Next buttons.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+BINARY_TOC             = NO
+
+# The TOC_EXPAND flag can be set to YES to add extra items for group members to
+# the table of contents of the HTML help documentation and to the tree view.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+TOC_EXPAND             = NO
+
+# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and
+# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that
+# can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help
+# (.qch) of the generated HTML documentation.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_QHP           = NO
+
+# If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify
+# the file name of the resulting .qch file. The path specified is relative to
+# the HTML output folder.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QCH_FILE               =
+
+# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help
+# Project output. For more information please see Qt Help Project / Namespace
+# (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#namespace).
+# The default value is: org.doxygen.Project.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_NAMESPACE          = org.doxygen.Project
+
+# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt
+# Help Project output. For more information please see Qt Help Project / Virtual
+# Folders (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#virtual-
+# folders).
+# The default value is: doc.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_VIRTUAL_FOLDER     = doc
+
+# If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom
+# filter to add. For more information please see Qt Help Project / Custom
+# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom-
+# filters).
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_CUST_FILTER_NAME   =
+
+# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the
+# custom filter to add. For more information please see Qt Help Project / Custom
+# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom-
+# filters).
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_CUST_FILTER_ATTRS  =
+
+# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this
+# project's filter section matches. Qt Help Project / Filter Attributes (see:
+# http://qt-project.org/doc/qt-4.8/qthelpproject.html#filter-attributes).
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_SECT_FILTER_ATTRS  =
+
+# The QHG_LOCATION tag can be used to specify the location of Qt's
+# qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the
+# generated .qhp file.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHG_LOCATION           =
+
+# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be
+# generated, together with the HTML files, they form an Eclipse help plugin. To
+# install this plugin and make it available under the help contents menu in
+# Eclipse, the contents of the directory containing the HTML and XML files needs
+# to be copied into the plugins directory of eclipse. The name of the directory
+# within the plugins directory should be the same as the ECLIPSE_DOC_ID value.
+# After copying Eclipse needs to be restarted before the help appears.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_ECLIPSEHELP   = NO
+
+# A unique identifier for the Eclipse help plugin. When installing the plugin
+# the directory name containing the HTML and XML files should also have this
+# name. Each documentation set should have its own identifier.
+# The default value is: org.doxygen.Project.
+# This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES.
+
+ECLIPSE_DOC_ID         = org.doxygen.Project
+
+# If you want full control over the layout of the generated HTML pages it might
+# be necessary to disable the index and replace it with your own. The
+# DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top
+# of each HTML page. A value of NO enables the index and the value YES disables
+# it. Since the tabs in the index contain the same information as the navigation
+# tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+DISABLE_INDEX          = NO
+
+# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index
+# structure should be generated to display hierarchical information. If the tag
+# value is set to YES, a side panel will be generated containing a tree-like
+# index structure (just like the one that is generated for HTML Help). For this
+# to work a browser that supports JavaScript, DHTML, CSS and frames is required
+# (i.e. any modern browser). Windows users are probably better off using the
+# HTML help feature. Via custom stylesheets (see HTML_EXTRA_STYLESHEET) one can
+# further fine-tune the look of the index. As an example, the default style
+# sheet generated by doxygen has an example that shows how to put an image at
+# the root of the tree instead of the PROJECT_NAME. Since the tree basically has
+# the same information as the tab index, you could consider setting
+# DISABLE_INDEX to YES when enabling this option.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_TREEVIEW      = NO
+
+# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that
+# doxygen will group on one line in the generated HTML documentation.
+#
+# Note that a value of 0 will completely suppress the enum values from appearing
+# in the overview section.
+# Minimum value: 0, maximum value: 20, default value: 4.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+ENUM_VALUES_PER_LINE   = 4
+
+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used
+# to set the initial width (in pixels) of the frame in which the tree is shown.
+# Minimum value: 0, maximum value: 1500, default value: 250.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+TREEVIEW_WIDTH         = 250
+
+# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open links to
+# external symbols imported via tag files in a separate window.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+EXT_LINKS_IN_WINDOW    = NO
+
+# Use this tag to change the font size of LaTeX formulas included as images in
+# the HTML documentation. When you change the font size after a successful
+# doxygen run you need to manually remove any form_*.png images from the HTML
+# output directory to force them to be regenerated.
+# Minimum value: 8, maximum value: 50, default value: 10.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+FORMULA_FONTSIZE       = 10
+
+# Use the FORMULA_TRANPARENT tag to determine whether or not the images
+# generated for formulas are transparent PNGs. Transparent PNGs are not
+# supported properly for IE 6.0, but are supported on all modern browsers.
+#
+# Note that when changing this option you need to delete any form_*.png files in
+# the HTML output directory before the changes have effect.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+FORMULA_TRANSPARENT    = YES
+
+# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see
+# http://www.mathjax.org) which uses client side Javascript for the rendering
+# instead of using prerendered bitmaps. Use this if you do not have LaTeX
+# installed or if you want to formulas look prettier in the HTML output. When
+# enabled you may also need to install MathJax separately and configure the path
+# to it using the MATHJAX_RELPATH option.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+USE_MATHJAX            = NO
+
+# When MathJax is enabled you can set the default output format to be used for
+# the MathJax output. See the MathJax site (see:
+# http://docs.mathjax.org/en/latest/output.html) for more details.
+# Possible values are: HTML-CSS (which is slower, but has the best
+# compatibility), NativeMML (i.e. MathML) and SVG.
+# The default value is: HTML-CSS.
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_FORMAT         = HTML-CSS
+
+# When MathJax is enabled you need to specify the location relative to the HTML
+# output directory using the MATHJAX_RELPATH option. The destination directory
+# should contain the MathJax.js script. For instance, if the mathjax directory
+# is located at the same level as the HTML output directory, then
+# MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax
+# Content Delivery Network so you can quickly see the result without installing
+# MathJax. However, it is strongly recommended to install a local copy of
+# MathJax from http://www.mathjax.org before deployment.
+# The default value is: http://cdn.mathjax.org/mathjax/latest.
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_RELPATH        = http://cdn.mathjax.org/mathjax/latest
+
+# The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax
+# extension names that should be enabled during MathJax rendering. For example
+# MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_EXTENSIONS     =
+
+# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces
+# of code that will be used on startup of the MathJax code. See the MathJax site
+# (see: http://docs.mathjax.org/en/latest/output.html) for more details. For an
+# example see the documentation.
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_CODEFILE       =
+
+# When the SEARCHENGINE tag is enabled doxygen will generate a search box for
+# the HTML output. The underlying search engine uses javascript and DHTML and
+# should work on any modern browser. Note that when using HTML help
+# (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET)
+# there is already a search function so this one should typically be disabled.
+# For large projects the javascript based search engine can be slow, then
+# enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to
+# search using the keyboard; to jump to the search box use <access key> + S
+# (what the <access key> is depends on the OS and browser, but it is typically
+# <CTRL>, <ALT>/<option>, or both). Inside the search box use the <cursor down
+# key> to jump into the search results window, the results can be navigated
+# using the <cursor keys>. Press <Enter> to select an item or <escape> to cancel
+# the search. The filter options can be selected when the cursor is inside the
+# search box by pressing <Shift>+<cursor down>. Also here use the <cursor keys>
+# to select a filter and <Enter> or <escape> to activate or cancel the filter
+# option.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+SEARCHENGINE           = YES
+
+# When the SERVER_BASED_SEARCH tag is enabled the search engine will be
+# implemented using a web server instead of a web client using Javascript. There
+# are two flavors of web server based searching depending on the EXTERNAL_SEARCH
+# setting. When disabled, doxygen will generate a PHP script for searching and
+# an index file used by the script. When EXTERNAL_SEARCH is enabled the indexing
+# and searching needs to be provided by external tools. See the section
+# "External Indexing and Searching" for details.
+# The default value is: NO.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+SERVER_BASED_SEARCH    = NO
+
+# When EXTERNAL_SEARCH tag is enabled doxygen will no longer generate the PHP
+# script for searching. Instead the search results are written to an XML file
+# which needs to be processed by an external indexer. Doxygen will invoke an
+# external search engine pointed to by the SEARCHENGINE_URL option to obtain the
+# search results.
+#
+# Doxygen ships with an example indexer ( doxyindexer) and search engine
+# (doxysearch.cgi) which are based on the open source search engine library
+# Xapian (see: http://xapian.org/).
+#
+# See the section "External Indexing and Searching" for details.
+# The default value is: NO.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+EXTERNAL_SEARCH        = NO
+
+# The SEARCHENGINE_URL should point to a search engine hosted by a web server
+# which will return the search results when EXTERNAL_SEARCH is enabled.
+#
+# Doxygen ships with an example indexer ( doxyindexer) and search engine
+# (doxysearch.cgi) which are based on the open source search engine library
+# Xapian (see: http://xapian.org/). See the section "External Indexing and
+# Searching" for details.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+SEARCHENGINE_URL       =
+
+# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the unindexed
+# search data is written to a file for indexing by an external tool. With the
+# SEARCHDATA_FILE tag the name of this file can be specified.
+# The default file is: searchdata.xml.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+SEARCHDATA_FILE        = searchdata.xml
+
+# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the
+# EXTERNAL_SEARCH_ID tag can be used as an identifier for the project. This is
+# useful in combination with EXTRA_SEARCH_MAPPINGS to search through multiple
+# projects and redirect the results back to the right project.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+EXTERNAL_SEARCH_ID     =
+
+# The EXTRA_SEARCH_MAPPINGS tag can be used to enable searching through doxygen
+# projects other than the one defined by this configuration file, but that are
+# all added to the same external search index. Each project needs to have a
+# unique id set via EXTERNAL_SEARCH_ID. The search mapping then maps the id of
+# to a relative location where the documentation can be found. The format is:
+# EXTRA_SEARCH_MAPPINGS = tagname1=loc1 tagname2=loc2 ...
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+EXTRA_SEARCH_MAPPINGS  =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_LATEX tag is set to YES doxygen will generate LaTeX output.
+# The default value is: YES.
+
+GENERATE_LATEX         = NO
+
+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: latex.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_OUTPUT           = latex
+
+# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
+# invoked.
+#
+# Note that when enabling USE_PDFLATEX this option is only used for generating
+# bitmaps for formulas in the HTML output, but not in the Makefile that is
+# written to the output directory.
+# The default file is: latex.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_CMD_NAME         = latex
+
+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to generate
+# index for LaTeX.
+# The default file is: makeindex.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+MAKEINDEX_CMD_NAME     = makeindex
+
+# If the COMPACT_LATEX tag is set to YES doxygen generates more compact LaTeX
+# documents. This may be useful for small projects and may help to save some
+# trees in general.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+COMPACT_LATEX          = NO
+
+# The PAPER_TYPE tag can be used to set the paper type that is used by the
+# printer.
+# Possible values are: a4 (210 x 297 mm), letter (8.5 x 11 inches), legal (8.5 x
+# 14 inches) and executive (7.25 x 10.5 inches).
+# The default value is: a4.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+PAPER_TYPE             = a4
+
+# The EXTRA_PACKAGES tag can be used to specify one or more LaTeX package names
+# that should be included in the LaTeX output. To get the times font for
+# instance you can specify
+# EXTRA_PACKAGES=times
+# If left blank no extra packages will be included.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+EXTRA_PACKAGES         =
+
+# The LATEX_HEADER tag can be used to specify a personal LaTeX header for the
+# generated LaTeX document. The header should contain everything until the first
+# chapter. If it is left blank doxygen will generate a standard header. See
+# section "Doxygen usage" for information on how to let doxygen write the
+# default header to a separate file.
+#
+# Note: Only use a user-defined header if you know what you are doing! The
+# following commands have a special meaning inside the header: $title,
+# $datetime, $date, $doxygenversion, $projectname, $projectnumber,
+# $projectbrief, $projectlogo. Doxygen will replace $title with the empy string,
+# for the replacement values of the other commands the user is refered to
+# HTML_HEADER.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_HEADER           =
+
+# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for the
+# generated LaTeX document. The footer should contain everything after the last
+# chapter. If it is left blank doxygen will generate a standard footer. See
+# LATEX_HEADER for more information on how to generate a default footer and what
+# special commands can be used inside the footer.
+#
+# Note: Only use a user-defined footer if you know what you are doing!
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_FOOTER           =
+
+# The LATEX_EXTRA_FILES tag can be used to specify one or more extra images or
+# other source files which should be copied to the LATEX_OUTPUT output
+# directory. Note that the files will be copied as-is; there are no commands or
+# markers available.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_EXTRA_FILES      =
+
+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated is
+# prepared for conversion to PDF (using ps2pdf or pdflatex). The PDF file will
+# contain links (just like the HTML output) instead of page references. This
+# makes the output suitable for online browsing using a PDF viewer.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+PDF_HYPERLINKS         = YES
+
+# If the USE_PDFLATEX tag is set to YES, doxygen will use pdflatex to generate
+# the PDF file directly from the LaTeX files. Set this option to YES to get a
+# higher quality PDF documentation.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+USE_PDFLATEX           = YES
+
+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \batchmode
+# command to the generated LaTeX files. This will instruct LaTeX to keep running
+# if errors occur, instead of asking the user for help. This option is also used
+# when generating formulas in HTML.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_BATCHMODE        = NO
+
+# If the LATEX_HIDE_INDICES tag is set to YES then doxygen will not include the
+# index chapters (such as File Index, Compound Index, etc.) in the output.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_HIDE_INDICES     = NO
+
+# If the LATEX_SOURCE_CODE tag is set to YES then doxygen will include source
+# code with syntax highlighting in the LaTeX output.
+#
+# Note that which sources are shown also depends on other settings such as
+# SOURCE_BROWSER.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_SOURCE_CODE      = NO
+
+# The LATEX_BIB_STYLE tag can be used to specify the style to use for the
+# bibliography, e.g. plainnat, or ieeetr. See
+# http://en.wikipedia.org/wiki/BibTeX and \cite for more info.
+# The default value is: plain.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_BIB_STYLE        = plain
+
+#---------------------------------------------------------------------------
+# Configuration options related to the RTF output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_RTF tag is set to YES doxygen will generate RTF output. The
+# RTF output is optimized for Word 97 and may not look too pretty with other RTF
+# readers/editors.
+# The default value is: NO.
+
+GENERATE_RTF           = NO
+
+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: rtf.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_OUTPUT             = rtf
+
+# If the COMPACT_RTF tag is set to YES doxygen generates more compact RTF
+# documents. This may be useful for small projects and may help to save some
+# trees in general.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+COMPACT_RTF            = NO
+
+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated will
+# contain hyperlink fields. The RTF file will contain links (just like the HTML
+# output) instead of page references. This makes the output suitable for online
+# browsing using Word or some other Word compatible readers that support those
+# fields.
+#
+# Note: WordPad (write) and others do not support links.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_HYPERLINKS         = NO
+
+# Load stylesheet definitions from file. Syntax is similar to doxygen's config
+# file, i.e. a series of assignments. You only have to provide replacements,
+# missing definitions are set to their default value.
+#
+# See also section "Doxygen usage" for information on how to generate the
+# default style sheet that doxygen normally uses.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_STYLESHEET_FILE    =
+
+# Set optional variables used in the generation of an RTF document. Syntax is
+# similar to doxygen's config file. A template extensions file can be generated
+# using doxygen -e rtf extensionFile.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_EXTENSIONS_FILE    =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the man page output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_MAN tag is set to YES doxygen will generate man pages for
+# classes and files.
+# The default value is: NO.
+
+GENERATE_MAN           = NO
+
+# The MAN_OUTPUT tag is used to specify where the man pages will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it. A directory man3 will be created inside the directory specified by
+# MAN_OUTPUT.
+# The default directory is: man.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_OUTPUT             = man
+
+# The MAN_EXTENSION tag determines the extension that is added to the generated
+# man pages. In case the manual section does not start with a number, the number
+# 3 is prepended. The dot (.) at the beginning of the MAN_EXTENSION tag is
+# optional.
+# The default value is: .3.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_EXTENSION          = .3
+
+# The MAN_SUBDIR tag determines the name of the directory created within
+# MAN_OUTPUT in which the man pages are placed. If defaults to man followed by
+# MAN_EXTENSION with the initial . removed.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_SUBDIR             =
+
+# If the MAN_LINKS tag is set to YES and doxygen generates man output, then it
+# will generate one additional man file for each entity documented in the real
+# man page(s). These additional files only source the real man page, but without
+# them the man command would be unable to find the correct page.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_LINKS              = NO
+
+#---------------------------------------------------------------------------
+# Configuration options related to the XML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_XML tag is set to YES doxygen will generate an XML file that
+# captures the structure of the code including all documentation.
+# The default value is: NO.
+
+GENERATE_XML           = NO
+
+# The XML_OUTPUT tag is used to specify where the XML pages will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: xml.
+# This tag requires that the tag GENERATE_XML is set to YES.
+
+XML_OUTPUT             = xml
+
+# If the XML_PROGRAMLISTING tag is set to YES doxygen will dump the program
+# listings (including syntax highlighting and cross-referencing information) to
+# the XML output. Note that enabling this will significantly increase the size
+# of the XML output.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_XML is set to YES.
+
+XML_PROGRAMLISTING     = YES
+
+#---------------------------------------------------------------------------
+# Configuration options related to the DOCBOOK output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_DOCBOOK tag is set to YES doxygen will generate Docbook files
+# that can be used to generate PDF.
+# The default value is: NO.
+
+GENERATE_DOCBOOK       = NO
+
+# The DOCBOOK_OUTPUT tag is used to specify where the Docbook pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be put in
+# front of it.
+# The default directory is: docbook.
+# This tag requires that the tag GENERATE_DOCBOOK is set to YES.
+
+DOCBOOK_OUTPUT         = docbook
+
+# If the DOCBOOK_PROGRAMLISTING tag is set to YES doxygen will include the
+# program listings (including syntax highlighting and cross-referencing
+# information) to the DOCBOOK output. Note that enabling this will significantly
+# increase the size of the DOCBOOK output.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_DOCBOOK is set to YES.
+
+DOCBOOK_PROGRAMLISTING = NO
+
+#---------------------------------------------------------------------------
+# Configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_AUTOGEN_DEF tag is set to YES doxygen will generate an AutoGen
+# Definitions (see http://autogen.sf.net) file that captures the structure of
+# the code including all documentation. Note that this feature is still
+# experimental and incomplete at the moment.
+# The default value is: NO.
+
+GENERATE_AUTOGEN_DEF   = NO
+
+#---------------------------------------------------------------------------
+# Configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_PERLMOD tag is set to YES doxygen will generate a Perl module
+# file that captures the structure of the code including all documentation.
+#
+# Note that this feature is still experimental and incomplete at the moment.
+# The default value is: NO.
+
+GENERATE_PERLMOD       = NO
+
+# If the PERLMOD_LATEX tag is set to YES doxygen will generate the necessary
+# Makefile rules, Perl scripts and LaTeX code to be able to generate PDF and DVI
+# output from the Perl module output.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_PERLMOD is set to YES.
+
+PERLMOD_LATEX          = NO
+
+# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be nicely
+# formatted so it can be parsed by a human reader. This is useful if you want to
+# understand what is going on. On the other hand, if this tag is set to NO the
+# size of the Perl module output will be much smaller and Perl will parse it
+# just the same.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_PERLMOD is set to YES.
+
+PERLMOD_PRETTY         = YES
+
+# The names of the make variables in the generated doxyrules.make file are
+# prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. This is useful
+# so different doxyrules.make files included by the same Makefile don't
+# overwrite each other's variables.
+# This tag requires that the tag GENERATE_PERLMOD is set to YES.
+
+PERLMOD_MAKEVAR_PREFIX =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor
+#---------------------------------------------------------------------------
+
+# If the ENABLE_PREPROCESSING tag is set to YES doxygen will evaluate all
+# C-preprocessor directives found in the sources and include files.
+# The default value is: YES.
+
+ENABLE_PREPROCESSING   = YES
+
+# If the MACRO_EXPANSION tag is set to YES doxygen will expand all macro names
+# in the source code. If set to NO only conditional compilation will be
+# performed. Macro expansion can be done in a controlled way by setting
+# EXPAND_ONLY_PREDEF to YES.
+# The default value is: NO.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+MACRO_EXPANSION        = NO
+
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES then
+# the macro expansion is limited to the macros specified with the PREDEFINED and
+# EXPAND_AS_DEFINED tags.
+# The default value is: NO.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+EXPAND_ONLY_PREDEF     = NO
+
+# If the SEARCH_INCLUDES tag is set to YES the includes files in the
+# INCLUDE_PATH will be searched if a #include is found.
+# The default value is: YES.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+SEARCH_INCLUDES        = YES
+
+# The INCLUDE_PATH tag can be used to specify one or more directories that
+# contain include files that are not input files but should be processed by the
+# preprocessor.
+# This tag requires that the tag SEARCH_INCLUDES is set to YES.
+
+INCLUDE_PATH           =
+
+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
+# patterns (like *.h and *.hpp) to filter out the header-files in the
+# directories. If left blank, the patterns specified with FILE_PATTERNS will be
+# used.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+INCLUDE_FILE_PATTERNS  =
+
+# The PREDEFINED tag can be used to specify one or more macro names that are
+# defined before the preprocessor is started (similar to the -D option of e.g.
+# gcc). The argument of the tag is a list of macros of the form: name or
+# name=definition (no spaces). If the definition and the "=" are omitted, "=1"
+# is assumed. To prevent a macro definition from being undefined via #undef or
+# recursively expanded use the := operator instead of the = operator.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+PREDEFINED             =
+
+# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this
+# tag can be used to specify a list of macro names that should be expanded. The
+# macro definition that is found in the sources will be used. Use the PREDEFINED
+# tag if you want to use a different macro definition that overrules the
+# definition found in the source code.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+EXPAND_AS_DEFINED      =
+
+# If the SKIP_FUNCTION_MACROS tag is set to YES then doxygen's preprocessor will
+# remove all references to function-like macros that are alone on a line, have
+# an all uppercase name, and do not end with a semicolon. Such function macros
+# are typically used for boiler-plate code, and will confuse the parser if not
+# removed.
+# The default value is: YES.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+SKIP_FUNCTION_MACROS   = YES
+
+#---------------------------------------------------------------------------
+# Configuration options related to external references
+#---------------------------------------------------------------------------
+
+# The TAGFILES tag can be used to specify one or more tag files. For each tag
+# file the location of the external documentation should be added. The format of
+# a tag file without this location is as follows:
+# TAGFILES = file1 file2 ...
+# Adding location for the tag files is done as follows:
+# TAGFILES = file1=loc1 "file2 = loc2" ...
+# where loc1 and loc2 can be relative or absolute paths or URLs. See the
+# section "Linking to external documentation" for more information about the use
+# of tag files.
+# Note: Each tag file must have a unique name (where the name does NOT include
+# the path). If a tag file is not located in the directory in which doxygen is
+# run, you must also specify the path to the tagfile here.
+
+TAGFILES               =
+
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create a
+# tag file that is based on the input files it reads. See section "Linking to
+# external documentation" for more information about the usage of tag files.
+
+GENERATE_TAGFILE       =
+
+# If the ALLEXTERNALS tag is set to YES all external class will be listed in the
+# class index. If set to NO only the inherited external classes will be listed.
+# The default value is: NO.
+
+ALLEXTERNALS           = NO
+
+# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed in
+# the modules index. If set to NO, only the current project's groups will be
+# listed.
+# The default value is: YES.
+
+EXTERNAL_GROUPS        = YES
+
+# If the EXTERNAL_PAGES tag is set to YES all external pages will be listed in
+# the related pages index. If set to NO, only the current project's pages will
+# be listed.
+# The default value is: YES.
+
+EXTERNAL_PAGES         = YES
+
+# The PERL_PATH should be the absolute path and name of the perl script
+# interpreter (i.e. the result of 'which perl').
+# The default file (with absolute path) is: /usr/bin/perl.
+
+PERL_PATH              = /usr/bin/perl
+
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool
+#---------------------------------------------------------------------------
+
+# If the CLASS_DIAGRAMS tag is set to YES doxygen will generate a class diagram
+# (in HTML and LaTeX) for classes with base or super classes. Setting the tag to
+# NO turns the diagrams off. Note that this option also works with HAVE_DOT
+# disabled, but it is recommended to install and use dot, since it yields more
+# powerful graphs.
+# The default value is: YES.
+
+CLASS_DIAGRAMS         = YES
+
+# You can define message sequence charts within doxygen comments using the \msc
+# command. Doxygen will then run the mscgen tool (see:
+# http://www.mcternan.me.uk/mscgen/)) to produce the chart and insert it in the
+# documentation. The MSCGEN_PATH tag allows you to specify the directory where
+# the mscgen tool resides. If left empty the tool is assumed to be found in the
+# default search path.
+
+MSCGEN_PATH            =
+
+# You can include diagrams made with dia in doxygen documentation. Doxygen will
+# then run dia to produce the diagram and insert it in the documentation. The
+# DIA_PATH tag allows you to specify the directory where the dia binary resides.
+# If left empty dia is assumed to be found in the default search path.
+
+DIA_PATH               =
+
+# If set to YES, the inheritance and collaboration graphs will hide inheritance
+# and usage relations if the target is undocumented or is not a class.
+# The default value is: YES.
+
+HIDE_UNDOC_RELATIONS   = YES
+
+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
+# available from the path. This tool is part of Graphviz (see:
+# http://www.graphviz.org/), a graph visualization toolkit from AT&T and Lucent
+# Bell Labs. The other options in this section have no effect if this option is
+# set to NO
+# The default value is: YES.
+
+HAVE_DOT               = YES
+
+# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is allowed
+# to run in parallel. When set to 0 doxygen will base this on the number of
+# processors available in the system. You can set it explicitly to a value
+# larger than 0 to get control over the balance between CPU load and processing
+# speed.
+# Minimum value: 0, maximum value: 32, default value: 0.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_NUM_THREADS        = 0
+
+# When you want a differently looking font in the dot files that doxygen
+# generates you can specify the font name using DOT_FONTNAME. You need to make
+# sure dot is able to find the font, which can be done by putting it in a
+# standard location or by setting the DOTFONTPATH environment variable or by
+# setting DOT_FONTPATH to the directory containing the font.
+# The default value is: Helvetica.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_FONTNAME           = Helvetica
+
+# The DOT_FONTSIZE tag can be used to set the size (in points) of the font of
+# dot graphs.
+# Minimum value: 4, maximum value: 24, default value: 10.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_FONTSIZE           = 10
+
+# By default doxygen will tell dot to use the default font as specified with
+# DOT_FONTNAME. If you specify a different font using DOT_FONTNAME you can set
+# the path where dot can find it using this tag.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_FONTPATH           =
+
+# If the CLASS_GRAPH tag is set to YES then doxygen will generate a graph for
+# each documented class showing the direct and indirect inheritance relations.
+# Setting this tag to YES will force the CLASS_DIAGRAMS tag to NO.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+CLASS_GRAPH            = YES
+
+# If the COLLABORATION_GRAPH tag is set to YES then doxygen will generate a
+# graph for each documented class showing the direct and indirect implementation
+# dependencies (inheritance, containment, and class references variables) of the
+# class with other documented classes.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+COLLABORATION_GRAPH    = YES
+
+# If the GROUP_GRAPHS tag is set to YES then doxygen will generate a graph for
+# groups, showing the direct groups dependencies.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+GROUP_GRAPHS           = YES
+
+# If the UML_LOOK tag is set to YES doxygen will generate inheritance and
+# collaboration diagrams in a style similar to the OMG's Unified Modeling
+# Language.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+UML_LOOK               = NO
+
+# If the UML_LOOK tag is enabled, the fields and methods are shown inside the
+# class node. If there are many fields or methods and many nodes the graph may
+# become too big to be useful. The UML_LIMIT_NUM_FIELDS threshold limits the
+# number of items for each type to make the size more manageable. Set this to 0
+# for no limit. Note that the threshold may be exceeded by 50% before the limit
+# is enforced. So when you set the threshold to 10, up to 15 fields may appear,
+# but if the number exceeds 15, the total amount of fields shown is limited to
+# 10.
+# Minimum value: 0, maximum value: 100, default value: 10.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+UML_LIMIT_NUM_FIELDS   = 10
+
+# If the TEMPLATE_RELATIONS tag is set to YES then the inheritance and
+# collaboration graphs will show the relations between templates and their
+# instances.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+TEMPLATE_RELATIONS     = NO
+
+# If the INCLUDE_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are set to
+# YES then doxygen will generate a graph for each documented file showing the
+# direct and indirect include dependencies of the file with other documented
+# files.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+INCLUDE_GRAPH          = YES
+
+# If the INCLUDED_BY_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are
+# set to YES then doxygen will generate a graph for each documented file showing
+# the direct and indirect include dependencies of the file with other documented
+# files.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+INCLUDED_BY_GRAPH      = YES
+
+# If the CALL_GRAPH tag is set to YES then doxygen will generate a call
+# dependency graph for every global function or class method.
+#
+# Note that enabling this option will significantly increase the time of a run.
+# So in most cases it will be better to enable call graphs for selected
+# functions only using the \callgraph command.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+CALL_GRAPH             = NO
+
+# If the CALLER_GRAPH tag is set to YES then doxygen will generate a caller
+# dependency graph for every global function or class method.
+#
+# Note that enabling this option will significantly increase the time of a run.
+# So in most cases it will be better to enable caller graphs for selected
+# functions only using the \callergraph command.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+CALLER_GRAPH           = NO
+
+# If the GRAPHICAL_HIERARCHY tag is set to YES then doxygen will graphical
+# hierarchy of all classes instead of a textual one.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+GRAPHICAL_HIERARCHY    = YES
+
+# If the DIRECTORY_GRAPH tag is set to YES then doxygen will show the
+# dependencies a directory has on other directories in a graphical way. The
+# dependency relations are determined by the #include relations between the
+# files in the directories.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DIRECTORY_GRAPH        = YES
+
+# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
+# generated by dot.
+# Note: If you choose svg you need to set HTML_FILE_EXTENSION to xhtml in order
+# to make the SVG files visible in IE 9+ (other browsers do not have this
+# requirement).
+# Possible values are: png, png:cairo, png:cairo:cairo, png:cairo:gd, png:gd,
+# png:gd:gd, jpg, jpg:cairo, jpg:cairo:gd, jpg:gd, jpg:gd:gd, gif, gif:cairo,
+# gif:cairo:gd, gif:gd, gif:gd:gd and svg.
+# The default value is: png.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_IMAGE_FORMAT       = png
+
+# If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to
+# enable generation of interactive SVG images that allow zooming and panning.
+#
+# Note that this requires a modern browser other than Internet Explorer. Tested
+# and working are Firefox, Chrome, Safari, and Opera.
+# Note: For IE 9+ you need to set HTML_FILE_EXTENSION to xhtml in order to make
+# the SVG files visible. Older versions of IE do not have SVG support.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+INTERACTIVE_SVG        = NO
+
+# The DOT_PATH tag can be used to specify the path where the dot tool can be
+# found. If left blank, it is assumed the dot tool can be found in the path.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_PATH               =
+
+# The DOTFILE_DIRS tag can be used to specify one or more directories that
+# contain dot files that are included in the documentation (see the \dotfile
+# command).
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOTFILE_DIRS           =
+
+# The MSCFILE_DIRS tag can be used to specify one or more directories that
+# contain msc files that are included in the documentation (see the \mscfile
+# command).
+
+MSCFILE_DIRS           =
+
+# The DIAFILE_DIRS tag can be used to specify one or more directories that
+# contain dia files that are included in the documentation (see the \diafile
+# command).
+
+DIAFILE_DIRS           =
+
+# When using plantuml, the PLANTUML_JAR_PATH tag should be used to specify the
+# path where java can find the plantuml.jar file. If left blank, it is assumed
+# PlantUML is not used or called during a preprocessing step. Doxygen will
+# generate a warning when it encounters a \startuml command in this case and
+# will not generate output for the diagram.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+PLANTUML_JAR_PATH      =
+
+# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of nodes
+# that will be shown in the graph. If the number of nodes in a graph becomes
+# larger than this value, doxygen will truncate the graph, which is visualized
+# by representing a node as a red box. Note that doxygen if the number of direct
+# children of the root node in a graph is already larger than
+# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note that
+# the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH.
+# Minimum value: 0, maximum value: 10000, default value: 50.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_GRAPH_MAX_NODES    = 50
+
+# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the graphs
+# generated by dot. A depth value of 3 means that only nodes reachable from the
+# root by following a path via at most 3 edges will be shown. Nodes that lay
+# further from the root node will be omitted. Note that setting this option to 1
+# or 2 may greatly reduce the computation time needed for large code bases. Also
+# note that the size of a graph can be further restricted by
+# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction.
+# Minimum value: 0, maximum value: 1000, default value: 0.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+MAX_DOT_GRAPH_DEPTH    = 0
+
+# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
+# background. This is disabled by default, because dot on Windows does not seem
+# to support this out of the box.
+#
+# Warning: Depending on the platform used, enabling this option may lead to
+# badly anti-aliased labels on the edges of a graph (i.e. they become hard to
+# read).
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_TRANSPARENT        = NO
+
+# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output
+# files in one run (i.e. multiple -o and -T options on the command line). This
+# makes dot run faster, but since only newer versions of dot (>1.8.10) support
+# this, this feature is disabled by default.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_MULTI_TARGETS      = NO
+
+# If the GENERATE_LEGEND tag is set to YES doxygen will generate a legend page
+# explaining the meaning of the various boxes and arrows in the dot generated
+# graphs.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+GENERATE_LEGEND        = YES
+
+# If the DOT_CLEANUP tag is set to YES doxygen will remove the intermediate dot
+# files that are used to generate the various graphs.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_CLEANUP            = YES
+EXTENSION_MAPPING = no_extension=C++
diff --git a/docs/source/data.rst b/docs/source/data.rst
index 3230ad2..84ec9b3 100644
--- a/docs/source/data.rst
+++ b/docs/source/data.rst
@@ -78,7 +78,7 @@ Tips for Preparing your own Data
     
     **Reproject your data**
 
-    osgEarth will reproject your data on your fly if it does not have the necessary
+    osgEarth will reproject your data on-the-fly if it does not have the necessary
     coordinate system.  For instance, if you are trying to view a UTM image on a
     geodetic globe (epsg:4326).  However, osgEarth will run much faster if your data
     is already in the correct coordinate system.  You can use any tool you want to 
diff --git a/docs/source/developer/shader_composition.rst b/docs/source/developer/shader_composition.rst
index b6a0822..240ed30 100644
--- a/docs/source/developer/shader_composition.rst
+++ b/docs/source/developer/shader_composition.rst
@@ -7,21 +7,21 @@ automatically select an appropriate mode to use.
 
 Since osgEarth relies on shaders, you as a developer may wish to customize
 the rendering or add your own effects and features in GLSL. Anyone who has
-wokred with shaders has run into the same challenges:
+worked with shaders has run into the same challenges:
 
-* Shader programs as monolithic. Adding new shader code requires you to
+* Shader programs are monolithic. Adding new shader code requires you to
   copy, modify, and replace the existing code so you don't lose its
   functionality.
 * Keeping your changes in sync with changes to the original code's 
   shaders is a maintenance nightmare.
 * Maintaining multiple versions of shader main()s is cumbersome and
   difficult.
-* Maintaining the dreaded "uber shader" becomes unmanagable as the 
+* Maintaining the dreaded "uber shader" becomes unmanageable as the 
   GLSL code base grows in complexity and you add more features.
   
 *Shader Composition* solves these problems by *modularizing* the shader
 pipeline. You can add and remove *functions* at any point in the program
-without and copying, pasting, or hacking other people's GLSL code.
+without copying, pasting, or hacking other people's GLSL code.
 
 Next we will discuss the structure of osgEarth's shader composition framework.
 
@@ -120,7 +120,7 @@ For example, let's use user functions to create a simple "haze" effect::
 
     // haze_vertex:
     varying vec3 v_pos;
-    void setup_have(inout vec4 vertexView)
+    void setup_haze(inout vec4 vertexView)
     {
         v_pos = vertexView.xyz;
     }
@@ -190,9 +190,9 @@ The FRAGMENT locations are as follows.
 Shader Packages
 ---------------
 
-Earlier we shows you how to inject functions using ``VirtualProgram``. 
+Earlier we showed you how to inject functions using ``VirtualProgram``. 
 The Shader Composition Framework also provides the concept of a ``ShaderPackage`` that supports
-more advances methods of shader management. We will talk about some of those now.
+more advanced methods of shader management. We will talk about some of those now.
 
 
 VirtualProgram Metadata
@@ -214,9 +214,9 @@ Here is an example::
 
     #version 110
     
-    #pragma vp_entryPoint  "color_it_red"
-    #pragma vp_location    "fragment_coloring"
-    #pragam vp_order       "1.0"
+    #pragma vp_entryPoint  color_it_red
+    #pragma vp_location    fragment_coloring
+    #pragma vp_order       1.0
     
     void color_it_red(inout vec4 color)
     {
@@ -274,7 +274,7 @@ The ``ShaderPackage`` support the concept if *include files*. Your GLSL code
 can *include* any other shaders in the same package by referencing their file names.
 Use a custom ``#pragma`` to include another file::
 
-    #pragma include "myCode.vertex.glsl"
+    #pragma include myCode.vertex.glsl
 
 Just as in C++, the *include* will load the other file (or source code) directly
 inline. So the file you are including must be structured as if you had placed it right
diff --git a/docs/source/developer/utilities.rst b/docs/source/developer/utilities.rst
index ef890cb..da7b3d2 100644
--- a/docs/source/developer/utilities.rst
+++ b/docs/source/developer/utilities.rst
@@ -29,7 +29,7 @@ DataScanner
 
 The ``DataScanner`` will recursively search a directory tree on the local filesystem
 for files that it can load as ``ImageLayer`` objects. It is a quick and easy way to 
-load a full directory of images at layers.
+load a full directory of images as layers.
 
 **NOTE** that only the *MP Terrain Engine* supports an unlimited number of image layers,
 so it is wise to use that engine in conjunction with the DataScanner.
@@ -51,7 +51,7 @@ DetailTexture
 -------------
 
 ``DetailTexture`` is a terrain controller that will apply a non-geospatial texture
-cross the terrain. This is an old trick that you can use to generate "noise" that makes
+across the terrain. This is an old trick that you can use to generate "noise" that makes
 a low resolution terrain appear more detailed::
 
     DetailTexture* detail = new DetailTexture();
@@ -158,7 +158,7 @@ You can also specify options for the output string:
 MGRSFormatter
 ~~~~~~~~~~~~~
 
-The ``MGRSFormatter`` echos a string according to the `Military Grid Reference System`_. 
+The ``MGRSFormatter`` constructs a string according to the `Military Grid Reference System`_. 
 Technically, an MGRS coordinate represents a *region* rather than an exact point, so you
 have to specifiy a *precision* qualifier to control the size of the represented region.
 Example::
@@ -225,7 +225,7 @@ this. The setup looks like this in the earth file::
         <normal_map>true</normal_map>
     </image>
     
-The **noise driver** generates Perlin noise; this will will the image with pseudo-
+The **noise driver** generates Perlin noise; this will fill the image with pseudo-
 random normal vectors. (Setting ``normal_map`` to ``true`` is what tells the driver
 to make normal vectors instead of RGB values. You should also set ``shared`` to 
 ``true``; this will make the normal map available to the shader pipeline so that it
diff --git a/docs/source/faq.rst b/docs/source/faq.rst
index de96386..218267e 100644
--- a/docs/source/faq.rst
+++ b/docs/source/faq.rst
@@ -34,7 +34,24 @@ How do I place a 3D model on the map?
         osg::Matrix matrix;
         point.createLocalToWorld( matrix );
         myMatrixTransform->setMatrix( matrix );
-    
+
+
+I added a node, but it has no texture/lighting/etc. in osgEarth. Why?
+.....................................................................
+
+    Everything under an osgEarth scene graph is rendered with shaders.
+    So, when using your own models (or creating geometry by hand) you 
+    need to create shader components in order for them to render properly.
+
+    osgEarth has a built-in shader generator for this purpose. Run the
+    shader generator on your node like so:
+
+        osgEarth::Registry::shaderGenerator().run( myNode );
+
+    After that, your node will contain shader snippets that allows osgEarth
+    to render it properly and for it to work with other osgEarth features
+    like sky lighting.
+
 
 How do make the terrain transparent?
 ....................................
diff --git a/docs/source/references/drivers/cache/filesystem.rst b/docs/source/references/drivers/cache/filesystem.rst
index 4b5efd5..e5671cb 100644
--- a/docs/source/references/drivers/cache/filesystem.rst
+++ b/docs/source/references/drivers/cache/filesystem.rst
@@ -22,7 +22,7 @@ Notes::
 	property on map layers to customize the naming to some extent.
 	
 	This cache supports expiration, but does NOT support size limits --
-	there is to way to cap the size of the cache.
+	there is no way to cap the size of the cache.
 	
 	Cache access is serialized since we are reading and writing
 	individual files on disk.
diff --git a/docs/source/references/drivers/model/feature_model_shared_props.rst b/docs/source/references/drivers/model/feature_model_shared_props.rst
index 70470b5..e54e00d 100644
--- a/docs/source/references/drivers/model/feature_model_shared_props.rst
+++ b/docs/source/references/drivers/model/feature_model_shared_props.rst
@@ -10,6 +10,6 @@ to those above):
     :feature_name:          Expression evaluating to the attribute name containing the feature name
     :feature_indexing:      Whether to index features for query (default is ``false``)
     :lighting:              Whether to override and set the lighting mode on this layer (t/f)
-    :max_granularity:       Anglular threshold at which to subdivide lines on a globe (degrees)
+    :max_granularity:       Angular threshold at which to subdivide lines on a globe (degrees)
     :shader_policy:         Options for shader generation (see: `Shader Policy`_)
-	:use_texture_arrays:    Whether to use texture arrays for wall and roof skins if you're card supports them.  (default is ``true``)
+    :use_texture_arrays:    Whether to use texture arrays for wall and roof skins if your card supports them.  (default is ``true``)
diff --git a/docs/source/references/drivers/model/feature_stencil.rst b/docs/source/references/drivers/model/feature_stencil.rst
deleted file mode 100644
index b8f80ef..0000000
--- a/docs/source/references/drivers/model/feature_stencil.rst
+++ /dev/null
@@ -1,41 +0,0 @@
-Feature Stencil
-===============
-This plugin "drapes" vector feature data over the terrain using a
-stencil buffering technique.
-
-Example usage::
-
-    <model driver="feature_stencil">
-        <features name="world" driver="ogr">
-            <url>../data/world.shp</url>
-        </features>
-             
-        <styles>
-            <style type="text/css">
-                world {
-                   stroke:         #ffff007f;
-                   stroke-width:   0.1;
-                }            
-            </style>
-        </styles>
-    </model>
-    
-Properties:
-
-    :extrusion_distance:  How far to extrude stencil volumes (meters)
-    :inverted:            Whether to stencil the inversion of the feature data (true/false)
-    :mask:                Whether to use the stenciled region as a terrain mask (true/false)
-    :show_volumes:        For debugging; draws the actual stencil volume geometry
-
-.. include:: feature_model_shared_props.rst
-
-Also see:
-
-    ``feature_stencil_line_draping.earth`` sample in the repo
-    
-Notes:
-
-* This plugin does NOT support paging (display layouts).
-
-
-.. include:: feature_model_shared_blocks.rst
diff --git a/docs/source/references/drivers/model/index.rst b/docs/source/references/drivers/model/index.rst
index e33a8b3..30838ef 100644
--- a/docs/source/references/drivers/model/index.rst
+++ b/docs/source/references/drivers/model/index.rst
@@ -8,6 +8,5 @@ load and display external 3D models.
    :maxdepth: 1
 
    feature_geom
-   feature_stencil
    simple
    
\ No newline at end of file
diff --git a/docs/source/references/drivers/model/simple.rst b/docs/source/references/drivers/model/simple.rst
index f23b09f..2383d35 100644
--- a/docs/source/references/drivers/model/simple.rst
+++ b/docs/source/references/drivers/model/simple.rst
@@ -5,7 +5,7 @@ map coordinates.
 
 Example usage::
 
-    <model name = "cow" driver="simple">
+    <model name ="model" driver="simple">
         <url>../data/red_flag.osg.100,100,100.scale</url>
         <location>-74.018 40.717 10</location>
     </model>
diff --git a/docs/source/references/earthfile.rst b/docs/source/references/earthfile.rst
index 9cf8ffe..939b740 100644
--- a/docs/source/references/earthfile.rst
+++ b/docs/source/references/earthfile.rst
@@ -44,7 +44,6 @@ the entire map.
     <map>
         <options lighting                 = "true"
                  elevation_interpolation  = "bilinear"
-                 elevation_tile_size      = "17"
                  overlay_texture_size     = "4096"
                  overlay_blending         = "true"
                  overlay_resolution_ratio = "3.0" >
@@ -103,7 +102,8 @@ These options control the rendering of the terrain surface.
                      color                 = "#ffffffff"
                      tile_size             = "17"
                      normalize_edges       = "false"
-                     elevation_smoothing   = "false">
+                     elevation_smoothing   = "false"
+                     normal_maps           = "false">
 
 +-----------------------+--------------------------------------------------------------------+
 | Property              | Description                                                        |
@@ -117,7 +117,7 @@ These options control the rendering of the terrain surface.
 +-----------------------+--------------------------------------------------------------------+
 | min_tile_range_factor | Determines how close you need to be to a terrain tile for it to    |
 |                       | display. The value is the ratio of a tile's extent to its          |
-|                       | For example, if a tile is 10km is radius, and the MTRF=6, then the |
+|                       | For example, if a tile has a 10km radius, and the MTRF=6, then the |
 |                       | tile will become visible at a range of about 60km.                 |
 +-----------------------+--------------------------------------------------------------------+
 | min_lod               | The lowest level of detail that the terrain is guaranteed to       |
@@ -153,7 +153,17 @@ These options control the rendering of the terrain surface.
 |                       | Doing so will give a smoother appearance to disparate height field |
 |                       | data, but elevations will not be as accurate. Default = false      |
 +-----------------------+--------------------------------------------------------------------+
-
+| normal_maps           | Whether to generate and use normal maps in place of geometry       |
+|                       | normals. Normal maps are used with lighting to create the          |
+|                       | appearance of higher-resolution terrain than can be represented    |
+|                       | with triangles alone. Default is engine-dependent.                 |
++-----------------------+--------------------------------------------------------------------+
+| min_expiry_frames     | The number of frames that a terrain tile hasn't been seen before   |
+|                       | it can be considered for expiration. Default = 0                   |
++-----------------------+--------------------------------------------------------------------+
+| min_expiry_time       | The number of seconds that a terrain tile hasn't been culled before|
+|                       | it can be considered for expiration. Default = 0                   |
++-----------------------+--------------------------------------------------------------------+
 
 
 .. _ImageLayer:
@@ -175,6 +185,7 @@ An *image layer* is a raster image overlaid on the map's geometry.
                max_level      = "23"
                min_resolution = "100.0"
                max_resolution = "0.0"
+               max_data_level = "23"
                enabled        = "true"
                visible        = "true"
                shared         = "false"
@@ -341,8 +352,8 @@ A *Model Layer* renders non-terrain data, like vector features or external 3D mo
     <map>
         <model name    = "my model layer"
                driver  = "feature_geom"
-               enabled = true
-               visible = true >
+               enabled = "true"
+               visible = "true" >
 
 
 +-----------------------+--------------------------------------------------------------------+
@@ -413,7 +424,7 @@ tiling scheme that it should use to render map tiles.
 | Property              | Description                                                        |
 +=======================+====================================================================+
 | srs                   | Spatial reference system of the map. This can be a WKT string, an  |
-|                       | ESPG code, a PROJ4 initialization string, or a stock profile name. |
+|                       | EPSG code, a PROJ4 initialization string, or a stock profile name. |
 |                       | Please refer to :doc:`/user/spatialreference` for details.         |
 +-----------------------+--------------------------------------------------------------------+
 | vdatum                | Vertical datum of the profile, which describes how to treat        |
diff --git a/docs/source/references/symbology.rst b/docs/source/references/symbology.rst
index be3a7cd..a65ff89 100644
--- a/docs/source/references/symbology.rst
+++ b/docs/source/references/symbology.rst
@@ -40,7 +40,7 @@ property includes the value type in parantheses following its description.
   :integer:               Integral number
   :numeric_expr:          Expression (simple or JavaScript) resolving to a number
   :string:                Simple text string
-  :string_expr:           Expression (simple or JacaScript) resolving to a text string
+  :string_expr:           Expression (simple or JavaScript) resolving to a text string
   :uri_string:            String denoting a resource location (like a URL or file path).
                           URIs can be absolute or relative; relative URIs are always
                           relative to the location of the *referrer*, i.e. the entity
@@ -128,7 +128,7 @@ the terrain under its location.
 |                       |   :gpu:    clamp geometry to the terrain on the GPU                |
 |                       |   :scene:  re-clamp geometry to new paged tiles (annotations only) |
 +-----------------------+--------------------------------------------------------------------+
-| altitude-binding      | Granulatiry at which to sample the terrain when                    |
+| altitude-binding      | Granularity at which to sample the terrain when                    |
 |                       | ``altitude-technique`` is ``map``:                                 |
 |                       |   :vertex:   clamp every vertex                                    |
 |                       |   :centroid: only clamp the centroid of each feature               |
@@ -333,6 +333,11 @@ as some osgEarth-specific settings that are not specific to any other symbol typ
 +-------------------------------+--------------------------------------------------------------+
 | render-lighting               | Enable or disable GL lighting. (boolean)                     |
 +-------------------------------+--------------------------------------------------------------+
+| render-transparent            | hint to render in the                                        |
+|                               | transparent (depth-sorted) bin (boolean)                     |
++-------------------------------+--------------------------------------------------------------+
+| render-bin                    | render bin to use for sorting (string)                       |
++-------------------------------+--------------------------------------------------------------+
 | render-depth-offset           | Enable or disable Depth Offseting. Depth offsetting is a     |
 |                               | GPU technique that modifies a fragment's depth value,        |
 |                               | simulating the rendering of that object closer or farther    |
@@ -377,6 +382,10 @@ The *text symbol* (SDK: ``TextSymbol``) controls the existance and appearance of
 +--------------------------------+--------------------------------------------------------------------+
 | text-halo-offset               | Outline thickness (float, pixels)                                  |
 +--------------------------------+--------------------------------------------------------------------+
+| text-offset-x                  | The x offset of the text in pixels                                 |
++--------------------------------+--------------------------------------------------------------------+
+| text-offset-y                  | The y offset of the text in pixels                                 |
++--------------------------------+--------------------------------------------------------------------+
 | text-align                     | Alignment of the text string relative to its anchor point:         |
 |                                |   * ``left-top``                                                   |
 |                                |   * ``left-center``                                                |
diff --git a/docs/source/releasenotes.rst b/docs/source/releasenotes.rst
index 1de1b71..c807ac7 100644
--- a/docs/source/releasenotes.rst
+++ b/docs/source/releasenotes.rst
@@ -1,6 +1,52 @@
 Release Notes
 =============
 
+Version 2.8 DRAFT (September 2016)
+---------------------------
+
+* Disabled feature tesselation tiling in BuildGeometryFilter unless max_polygon_tiling_angle is explicitly set.  Cropping code was causing issues especially around the poles.  Need to come up with a more general solution in the future.
+* Better support for osg::Fog in VirtualPrograms with FogEffect.  Implemented multiple fog modes.
+* Always applying min_range and max_range in MPGeometry to prevent uniform leakage.
+* Proper support for centroid clamping for MultiPolygons.
+* New requirement to call open() on TileSources and Layers when creating at runtime.  This lets you explicitly get the Status of a layer and report errors to users.
+* Fixes to EGM96 vertical datum grid.
+* BUILD_OSGEARTH_EXAMPLES cmake option for disabling building examples.
+* Added nearest sampling support for heightfields
+* New feature_join for adding attributes from intersecting 
+* osgearth_deformation demo
+* Scatter filter support for pointsets.  Simply places models at each point in the PointSet.
+* Performance optimizations when discarding features in javascript style selectors when returning null styles
+* Feature geometry caching support
+* New min_expiry_frames and min_expiry_time options to TerrainOptions.
+* Proper createTile implementation for Rex engine.
+* RocksDB cache plugin.
+* New osgearth_server application (based on Poco networking libraries).  Serve up osgEarth tiles rendered on the GPU to your favorite web mapping tools like Leaflet, OpenLayers and Cesium!
+* Packager now supports writing to MBTiles
+* New osgearth_skyview example for drawing an "inside out" earth.  Turns out osgearth is a great photosphere viewer!
+* Experimental WinInet support to replace CURL.  New osgearth_http test app.  
+* Upgraded duktape to version 1.4.0
+* Memory usage testing support (osgearth_viewer --monitor to enable)
+* New osgearth_3pv utility application.
+* Better support for pretiled datasets like TFS and Mapnik Vector Tiles in FeatureRasterSource (and agglite driver)
+* Better support for node tethering in EarthManipulator
+* Doxygen support
+* New openstreetmap vector tiles demos (openstreetmap_buildings.earth and openstreetmap_full.earth)
+* Support for Mapnik Vector Tiles datasets
+* Fixed improper inversion of y tilekey in FeatureModelGraph and updated all drivers.
+* CURLOPT_ENCODING support.  If you've built curl against zlib, proper HTTP headers for gzip and deflate will be added and automatically decompressed.
+* New osgearth_splat example
+* New osgEarthSplat NodeKit
+* New "template" plugin based on NLTemplate that allows you to write templatized earth files
+* Support for xi:include in earth files
+* Minimum OpenSceneGraph version is 3.4.0
+* Removed MINIZIP dependency
+* New Triton and Silverlining NodeKits
+* New feature_elevation driver that produces features from 
+* New raster to feature driver for turning rasters to features
+* 330 compatibiity default shader version for GLSL
+* Normal mapping integrated into MP, removed normal map extension.
+* TravisCI and Coverity support
+
 Version 2.7 (July 2015)
 ---------------------------
 
diff --git a/docs/source/startup.rst b/docs/source/startup.rst
index b37a047..a2c1302 100644
--- a/docs/source/startup.rst
+++ b/docs/source/startup.rst
@@ -23,29 +23,28 @@ Get the Source Code
 
     To download a tarball or ZIP archive of the source code, visit the
     `osgEarth Tags`_ and select the one you want. The latest official release
-    will be at the top.
+    will be at or near the top.
 
 
 Get the Dependencies
 --------------------
 
-**Required dependencies**:
+**Required dependencies**
 
-    * OpenSceneGraph_ 3.0.1 or later, with the CURL plugin enabled.
-    * GDAL_ 1.6 or later - Geospatial Data Abstraction Layer
+    * OpenSceneGraph_ 3.2.1 or later
+    * GDAL_ 1.9.2 or later - Geospatial Data Abstraction Layer
     * CURL_ - HTTP transfer library (comes with OpenSceneGraph_ 3rd party library distros)
+      
+**Recommended pre-built dependencies**
+
+    * AlphaPixel_ has pre-built OSG_ and 3rd-party dependencies for various architectures.
+    * Pre-built `GDAL binaries`_ for various architectures.
     
-**Optional depedencies**: osgEarth will compile without them, but some functionality
-will be missing:
+**Optional depedencies**: osgEarth will compile without them. Look and decide what you need
 
     * GEOS_ 3.2.0 or later - C++ library for topological operations.
       osgEarth uses GEOS to perform various geometry operations like buffering and intersections.
       If you plan to use vector feature data in osgEarth, you probably want this.
-    
-    * Minizip_ - ZIP file extractor; include this if you want to read KMZ files.
-      
-    * QT_ - Cross-platform UI framework. Point the ``QT_QMAKE_EXECUTABLE`` CMake variable
-      to the ``qmake.exe`` you want to use and CMake will populate all the other QT variables.
 
     * LevelDB_ - Google's embedded key/value store. Include this if you want to build
       osgEarth's optional "leveldb" cache driver.
@@ -54,23 +53,12 @@ will be missing:
 	  Used for accessing sqlite/mbtiles datasets. You may need these tips to create the necessary
 	  .lib file from the .def and .dll files included in the Windows binaries:
 	  http://eli.thegreenplace.net/2009/09/23/compiling-sqlite-on-windows
-    
-**Deprecated dependencies**: osgEarth can still use these, but they will probably go away
-in the future:
-
-    * V8_ - Google's JavaScript engine. Include this if you're a Windows user and you want
-      to embed JavaScript code in your earth files. We recommend you use Duktape instead.
-      
-    * JavaScriptCore_ - Apple's JavaScript engine. Include this if you're an OSX or IOS user
-      and you want to embed JavaScript code in your earth files. We receommend you use
-      Duktape instead.
       
-**Optional: get pre-built dependencies**
+    * QT_ - Cross-platform UI framework. Used to built the osgEarthQt support library, which is
+      useful (though not required) for building Qt applications that us osgEarth.  Point the
+      ``QT_QMAKE_EXECUTABLE`` CMake variable to the ``qmake.exe`` you want to use and CMake will
+      populate all the other QT variables.
 
-    * AlphaPixel_ has pre-built OSG_ and 3rd-party dependencies for various architectures.
-    * `Mike Weiblen`_ has some pre-built OSG_ binaries and dependencies too.
-    * FWTools_ has pre-built GDAL binaries with all the fixins.
-    * Pre-built `GDAL binaries`_ for various architectures.
     
 Build it
 --------
@@ -108,10 +96,8 @@ Here are a few tips.
 .. _CURL:           http://curl.haxx.se/libcurl/
 .. _GEOS:           http://trac.osgeo.org/geos/ 
 .. _GDAL:           http://www.gdal.org/
-.. _GDAL binaries:  http://vbkto.dyndns.org:1280/sdk/Default.aspx
+.. _GDAL binaries:  http://www.gisinternals.com/
 .. _FWTools:        http://fwtools.maptools.org/
-.. _Minizip:        http://www.winimage.com/zLibDll/minizip.html
-.. _V8:             http://code.google.com/p/v8/
 .. _AlphaPixel:     http://openscenegraph.alphapixel.com/osg/downloads/openscenegraph-third-party-library-downloads
 .. _Mike Weiblen:   http://mew.cx/osg/
 .. _the forum:      http://forum.osgearth.org
diff --git a/docs/source/user/caching.rst b/docs/source/user/caching.rst
index 01dae30..cca4700 100644
--- a/docs/source/user/caching.rst
+++ b/docs/source/user/caching.rst
@@ -47,7 +47,7 @@ In code you can set a global cache in the osgEarth resgistry::
 
 Caching Policies
 ----------------
-Once you have a cache set up, osgEarth will use it be default for all your
+Once you have a cache set up, osgEarth will use it by default for all your
 imagery and elevation layers. If you want to override this behavior, you can
 use a *cache policy*. A cache policy tells osgEarth if and how a certain object 
 should utilize the cache.
diff --git a/docs/source/user/features.rst b/docs/source/user/features.rst
index 2a8a9f4..a26b8be 100644
--- a/docs/source/user/features.rst
+++ b/docs/source/user/features.rst
@@ -359,6 +359,40 @@ More below.
 Paging breaks the data up into tiles. The ``tile_size`` is the width (in meters)
 of each paged tile.
 
+Cropping features
+~~~~~~~~~~~~~~~~~
+
+By default, if a feature intersects the tile, it will be included even if it extends outside 
+extents of the tile.  This is useful for things like extruded buildings where it doesn't make sense
+to try to chop them to fit exactly in the tiles because you don't want to see half a building page in.
+Buildings are also generally small, so the distance that they will extend outside the tile is relatively small.
+
+For things like roads or country borders that are linear features, it might make more sense to crop
+them to fit the tile exactly.  Visually a line won't look that bad if you see part if it page in.
+You can enable feature cropping on a layout by setting the ``crop_features`` attribute to true on the layout.
+
+For example::
+
+  <model name="roads" driver="feature_geom">
+        <features name="roads" driver="ogr" build_spatial_index="true">
+              <url>roads.shp</url>
+        </features>
+          
+        <layout crop_features="true" tile_size="1000">
+            <level max_range="5000"/>
+        </layout>
+          
+        <styles>
+            <style type="text/css">
+                roads {
+                    stroke:  #ffff7f7f;
+                  }
+            </style>
+        </styles>        
+  </model>
+
+
+
 Levels
 ~~~~~~
 
@@ -374,3 +408,36 @@ sending large batches of similar geometry to the graphics card, tweaking the
 tile size can help with performance and throughput. Unfortunately there's no way
 for osgEarth to know exactly what the "best" tile size will be in advance;
 so, you have the opportunity to tweak using this setting.
+
+Layout Settings
+~~~~~~~~~~~~~~~
+
+    :tile_size:         The size (in one dimension) of each tile of features in the layout
+                        at the maximum range. Maximum range must be set for this to take effect.                                                      
+    :tile_size_factor:  The ratio of visibility range to feature tile radius. Default is 15.
+                        Increase this to produce more, smaller tiles at a given visibility
+                        range; decrease this to produce fewer, larger tiles.
+                        For example, for factor=15, at a visibility range of (say) 120,000m
+                        the system will attempt to create tiles that are approximately
+                        8,000m in radius. (120,000 / 15 = 8,000).
+    :max_range:         The desired max range for pre-tiled feature sources like TFS.  The tileSizeFactor will be automatically computed
+                        based on the first level of the feature profile so that it shows up at that range.
+    :min_range:         Minimum visibility range for all tiles in the layout.
+    :crop_features:     Whether to crop geometry to fit within the cell extents when chopping
+                        a feature level up into grid cells. By default, this is false, meaning 
+                        that a feature whose centroid falls within the cell will be included.
+                        Setting this to true means that if any part of the feature falls within
+                        the working cell, it will be cropped to the cell extents and used.
+    :priority_offset:   Sets the offset that will be applied to the computed paging priority
+                        of tiles in this layout. Adjusting this can affect the priority of this
+                        data with respect to other paged data in the scene (like terrain or other
+                        feature layers).
+                        Default = 0.0
+    :priority_scale:    Sets the scale factor to be applied to the computed paging priority
+                        of tiles in this layout. Adjusting this can affect the priority of this
+                        data with respect to other paged data in the scene (like terrain or other
+                        feature layers).
+                        Default = 1.0.
+    :min_expiry_time:   Minimum time, in second, before a feature tile is eligible for pageout.
+                        Set this to a negative number to disable expiration altogether (i.e., tiles
+                        will never page out).
\ No newline at end of file
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index caa6e46..d89c344 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -3,27 +3,44 @@ FOREACH( lib
          osgEarth
          osgEarthAnnotation
          osgEarthFeatures
-         osgEarthUtil
          osgEarthSymbology
- )
+         osgEarthUtil )
 
     ADD_SUBDIRECTORY(${lib})
     
-    SET_PROPERTY(TARGET ${lib} PROPERTY FOLDER "Libs")
+    SET_PROPERTY(TARGET ${lib} PROPERTY FOLDER "Core")
 
 ENDFOREACH( lib )
 
+
+FOREACH( lib
+         osgEarthQt
+         osgEarthSplat
+         osgEarthSilverLining
+         osgEarthTriton )
+    add_subdirectory( ${lib} )    
+ENDFOREACH( lib )
+
 ADD_SUBDIRECTORY( osgEarthDrivers )
-ADD_SUBDIRECTORY( osgEarthExtensions )
 
 IF(NOT OSG_BUILD_PLATFORM_IPHONE AND NOT OSG_BUILD_PLATFORM_IPHONE_SIMULATOR AND NOT ANDROID)
-ADD_SUBDIRECTORY( applications )
+    ADD_SUBDIRECTORY( applications )
 ENDIF()
 
-IF (Qt5Widgets_FOUND OR QT4_FOUND AND NOT ANDROID AND OSGEARTH_USE_QT)
-    ADD_SUBDIRECTORY(osgEarthQt)
-    SET_PROPERTY(TARGET osgEarthQt PROPERTY FOLDER "Libs")
-ENDIF()
+#IF (Qt5Widgets_FOUND OR QT4_FOUND AND NOT ANDROID AND OSGEARTH_USE_QT)
+#    ADD_SUBDIRECTORY(osgEarthQt)
+#    SET_PROPERTY(TARGET osgEarthQt PROPERTY FOLDER "Libs")
+#ENDIF()
+
+#IF (SILVERLINING_FOUND)
+#    ADD_SUBDIRECTORY(osgEarthSilverLining)
+    #SET_PROPERTY(TARGET osgEarthSilverLining PROPERTY FOLDER "Extensions")
+#ENDIF()
+
+#IF (TRITON_FOUND)
+    #ADD_SUBDIRECTORY(osgEarthTriton)
+    #SET_PROPERTY(TARGET osgEarthTriton PROPERTY FOLDER "Extensions")
+#ENDIF()
 
 IF(MSVC80)
   OPTION(OSGEARTH_MSVC_GENERATE_PLUGINS_AND_WRAPPERS_MANIFESTS "Generate or not manifests files under VS8 for dynamically loaded dlls" ON)
diff --git a/src/applications/CMakeLists.txt b/src/applications/CMakeLists.txt
index ac1152f..2b5d1e4 100644
--- a/src/applications/CMakeLists.txt
+++ b/src/applications/CMakeLists.txt
@@ -37,57 +37,81 @@ ADD_SUBDIRECTORY(osgearth_backfill)
 ADD_SUBDIRECTORY(osgearth_overlayviewer)
 ADD_SUBDIRECTORY(osgearth_version)
 ADD_SUBDIRECTORY(osgearth_tileindex)
-IF (Qt5Widgets_FOUND OR QT4_FOUND AND NOT ANDROID AND OSGEARTH_USE_QT)
+ADD_SUBDIRECTORY(osgearth_atlas)
+ADD_SUBDIRECTORY(osgearth_conv)
+ADD_SUBDIRECTORY(osgearth_3pv)
+
+IF (Qt5Widgets_FOUND OR QT4_FOUND AND NOT ANDROID AND OSGEARTH_USE_QT AND OSGEARTH_QT_BUILD_LEGACY_WIDGETS)
     ADD_SUBDIRECTORY(osgearth_package_qt)
 ENDIF()
 
-SET(TARGET_DEFAULT_LABEL_PREFIX "Sample")
-SET(TARGET_DEFAULT_APPLICATION_FOLDER "Samples")
-ADD_SUBDIRECTORY(osgearth_clamp)
-ADD_SUBDIRECTORY(osgearth_manip)
-ADD_SUBDIRECTORY(osgearth_toc)
-ADD_SUBDIRECTORY(osgearth_createtile)
-ADD_SUBDIRECTORY(osgearth_elevation)
-ADD_SUBDIRECTORY(osgearth_features)
-ADD_SUBDIRECTORY(osgearth_featureinfo)
-ADD_SUBDIRECTORY(osgearth_featurefilter)
-ADD_SUBDIRECTORY(osgearth_los)
-ADD_SUBDIRECTORY(osgearth_terrainprofile)
-ADD_SUBDIRECTORY(osgearth_map)
-ADD_SUBDIRECTORY(osgearth_annotation)
-ADD_SUBDIRECTORY(osgearth_tracks)
-ADD_SUBDIRECTORY(osgearth_transform)
+IF(BUILD_OSGEARTH_EXAMPLES)
+    SET(TARGET_DEFAULT_LABEL_PREFIX "Sample")
+    SET(TARGET_DEFAULT_APPLICATION_FOLDER "Samples")
+    ADD_SUBDIRECTORY(osgearth_clamp)
+    ADD_SUBDIRECTORY(osgearth_manip)
+    ADD_SUBDIRECTORY(osgearth_toc)
+    ADD_SUBDIRECTORY(osgearth_createtile)
+    ADD_SUBDIRECTORY(osgearth_elevation)
+    ADD_SUBDIRECTORY(osgearth_features)
+    ADD_SUBDIRECTORY(osgearth_featureinfo)
+    ADD_SUBDIRECTORY(osgearth_featurefilter)
+    ADD_SUBDIRECTORY(osgearth_los)
+    ADD_SUBDIRECTORY(osgearth_terrainprofile)
+    ADD_SUBDIRECTORY(osgearth_map)
+    ADD_SUBDIRECTORY(osgearth_annotation)
+    ADD_SUBDIRECTORY(osgearth_tracks)
+    ADD_SUBDIRECTORY(osgearth_transform)
+    ADD_SUBDIRECTORY(osgearth_horizon)
+    ADD_SUBDIRECTORY(osgearth_http)
 
-IF(NOT ${OPENSCENEGRAPH_VERSION} VERSION_LESS "2.9.6")
-    ADD_SUBDIRECTORY(osgearth_featureeditor)
-ENDIF()
+    IF(NOT ${OPENSCENEGRAPH_VERSION} VERSION_LESS "2.9.6")
+        ADD_SUBDIRECTORY(osgearth_featureeditor)
+    ENDIF()
 
-ADD_SUBDIRECTORY(osgearth_measure)
-ADD_SUBDIRECTORY(osgearth_controls)
-ADD_SUBDIRECTORY(osgearth_shadercomp)
-ADD_SUBDIRECTORY(osgearth_tilesource)
-ADD_SUBDIRECTORY(osgearth_imageoverlay)
-ADD_SUBDIRECTORY(osgearth_city)
-ADD_SUBDIRECTORY(osgearth_graticule)
-ADD_SUBDIRECTORY(osgearth_featurequery)
-ADD_SUBDIRECTORY(osgearth_occlusionculling)
-ADD_SUBDIRECTORY(osgearth_colorfilter)
-ADD_SUBDIRECTORY(osgearth_sequencecontrol)
-ADD_SUBDIRECTORY(osgearth_minimap)
-ADD_SUBDIRECTORY(osgearth_sharedlayer)
-ADD_SUBDIRECTORY(osgearth_mrt)
-ADD_SUBDIRECTORY(osgearth_fog)
-ADD_SUBDIRECTORY(osgearth_shadergen)
-ADD_SUBDIRECTORY(osgearth_atlas)
-ADD_SUBDIRECTORY(osgearth_conv)
-ADD_SUBDIRECTORY(osgearth_clipplane)
-ADD_SUBDIRECTORY(osgearth_cache_test)
-ADD_SUBDIRECTORY(osgearth_pick)
+    ADD_SUBDIRECTORY(osgearth_measure)
+    ADD_SUBDIRECTORY(osgearth_controls)
+    ADD_SUBDIRECTORY(osgearth_shadercomp)
+    ADD_SUBDIRECTORY(osgearth_tilesource)
+    ADD_SUBDIRECTORY(osgearth_imageoverlay)
+    ADD_SUBDIRECTORY(osgearth_city)
+    ADD_SUBDIRECTORY(osgearth_graticule)
+    ADD_SUBDIRECTORY(osgearth_featurequery)
+    ADD_SUBDIRECTORY(osgearth_occlusionculling)
+    ADD_SUBDIRECTORY(osgearth_colorfilter)
+    ADD_SUBDIRECTORY(osgearth_sequencecontrol)
+    ADD_SUBDIRECTORY(osgearth_minimap)
+    ADD_SUBDIRECTORY(osgearth_sharedlayer)
+    ADD_SUBDIRECTORY(osgearth_mrt)
+    ADD_SUBDIRECTORY(osgearth_fog)
+    ADD_SUBDIRECTORY(osgearth_shadergen)
+    ADD_SUBDIRECTORY(osgearth_clipplane)
+    ADD_SUBDIRECTORY(osgearth_cache_test)
+    ADD_SUBDIRECTORY(osgearth_pick)
+    ADD_SUBDIRECTORY(osgearth_wfs)
+    ADD_SUBDIRECTORY(osgearth_datetime)
+    ADD_SUBDIRECTORY(osgearth_pagingtest)
+    ADD_SUBDIRECTORY(osgearth_xfbtest)
+    ADD_SUBDIRECTORY(osgearth_ephemeris)
+    ADD_SUBDIRECTORY(osgearth_computerangecallback)
+    ADD_SUBDIRECTORY(osgearth_splat)
+    ADD_SUBDIRECTORY(osgearth_skyview)
+    ADD_SUBDIRECTORY(osgearth_server)
+    ADD_SUBDIRECTORY(osgearth_deformation)
+    ADD_SUBDIRECTORY(osgearth_srstest)
 
-IF (Qt5Widgets_FOUND OR QT4_FOUND AND NOT ANDROID AND OSGEARTH_USE_QT)
-    ADD_SUBDIRECTORY(osgearth_qt)
-    ADD_SUBDIRECTORY(osgearth_qt_simple)
-    ADD_SUBDIRECTORY(osgearth_qt_windows)
-    ADD_SUBDIRECTORY(osgearth_demo)
-ENDIF()
+
+    IF (Qt5Widgets_FOUND OR QT4_FOUND AND NOT ANDROID AND OSGEARTH_USE_QT)
+        ADD_SUBDIRECTORY(osgearth_qt_simple)
+        ADD_SUBDIRECTORY(osgearth_qt_windows)
+    ENDIF()
+
+    IF(SILVERLINING_FOUND)
+        ADD_SUBDIRECTORY(osgearth_silverlining)
+    ENDIF(SILVERLINING_FOUND)
+
+    IF(TRITON_FOUND)
+        ADD_SUBDIRECTORY(osgearth_triton)
+    ENDIF(TRITON_FOUND)
+ENDIF(BUILD_OSGEARTH_EXAMPLES)
 
diff --git a/src/applications/osgearth_3pv/CMakeLists.txt b/src/applications/osgearth_3pv/CMakeLists.txt
new file mode 100644
index 0000000..e1dc876
--- /dev/null
+++ b/src/applications/osgearth_3pv/CMakeLists.txt
@@ -0,0 +1,7 @@
+INCLUDE_DIRECTORIES(${OSG_INCLUDE_DIRS} )
+SET(TARGET_LIBRARIES_VARS OSG_LIBRARY OSGDB_LIBRARY OSGUTIL_LIBRARY OSGVIEWER_LIBRARY OPENTHREADS_LIBRARY)
+
+SET(TARGET_SRC osgearth_3pv.cpp )
+
+#### end var setup  ###
+SETUP_APPLICATION(osgearth_3pv)
\ No newline at end of file
diff --git a/src/applications/osgearth_3pv/osgearth_3pv.cpp b/src/applications/osgearth_3pv/osgearth_3pv.cpp
new file mode 100644
index 0000000..36ae763
--- /dev/null
+++ b/src/applications/osgearth_3pv/osgearth_3pv.cpp
@@ -0,0 +1,263 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+* Copyright 2016 Pelican Mapping
+* http://osgearth.org
+*
+* osgEarth is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* 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.
+*
+* You should have received a copy of the GNU Lesser General Public License
+* along with this program.  If not, see <http://www.gnu.org/licenses/>
+*/
+
+#include <osgViewer/Viewer>
+#include <osgEarth/Notify>
+#include <osgEarthUtil/EarthManipulator>
+#include <osgEarthUtil/ExampleResources>
+#include <osgEarthUtil/MouseCoordsTool>
+#include <osgEarthUtil/Controls>
+
+#include <osgEarth/Units>
+#include <osgEarth/Viewpoint>
+#include <osgEarth/Horizon>
+#include <osgEarth/TraversalData>
+
+#include <osgEarthAnnotation/PlaceNode>
+
+#define LC "[viewer] "
+
+using namespace osgEarth;
+using namespace osgEarth::Util;
+using namespace osgEarth::Annotation;
+namespace ui = osgEarth::Util::Controls;
+
+
+#include <osg/Geometry>
+#include <osg/Depth>
+#include <osg/LineStipple>
+#include <osg/DisplaySettings>
+#include <osg/MatrixTransform>
+#include <osg/LineWidth>
+#include <osgDB/ReadFile>
+#include <osgViewer/CompositeViewer>
+#include <osgGA/TrackballManipulator>
+
+
+struct PlacerCallback : public MouseCoordsTool::Callback
+{
+    PlaceNode* _place;
+    osg::View* _eyeView;
+    PlacerCallback(PlaceNode* place, osgViewer::View* eyeView) : _place(place), _eyeView(eyeView) { }
+
+    // called when valid map coordinates are found under the mouse
+    void set(const GeoPoint& coords, osg::View* view, MapNode* mapNode)
+    {
+        _place->setPosition(coords);
+        _place->setNodeMask(~0);
+
+        osg::Vec3d eyeWorld, c, u;
+        _eyeView->getCamera()->getViewMatrixAsLookAt(eyeWorld, c, u);
+        osg::Vec3d placeWorld;
+        coords.toWorld(placeWorld);
+        
+        _place->setText( Stringify() << "Range: " << (int)(eyeWorld-placeWorld).length() << "m" );
+    }
+
+    // called when no map coords are found under the mouse
+    void reset(osg::View* view, MapNode* mapNode)
+    {
+        _place->setNodeMask(0);
+    }
+};
+
+
+// Given a Camera, create a wireframe representation of its
+// view frustum. Create a default representation if camera==NULL.
+osg::Node*
+makeFrustumFromCamera( osg::Camera* camera )
+{
+    // Projection and ModelView matrices
+    osg::Matrixd proj;
+    osg::Matrixd mv;
+    if (camera)
+    {
+        proj = camera->getProjectionMatrix();
+        mv = camera->getViewMatrix();
+    }
+    else
+    {
+        // Create some kind of reasonable default Projection matrix.
+        proj.makePerspective( 30., 1., 1., 10. );
+        // leave mv as identity
+    }
+
+    // Get near and far from the Projection matrix.
+    const double near = proj(3,2) / (proj(2,2)-1.0);
+    const double far = proj(3,2) / (1.0+proj(2,2));
+
+    // Get the sides of the near plane.
+    const double nLeft = near * (proj(2,0)-1.0) / proj(0,0);
+    const double nRight = near * (1.0+proj(2,0)) / proj(0,0);
+    const double nTop = near * (1.0+proj(2,1)) / proj(1,1);
+    const double nBottom = near * (proj(2,1)-1.0) / proj(1,1);
+
+    // Get the sides of the far plane.
+    const double fLeft = far * (proj(2,0)-1.0) / proj(0,0);
+    const double fRight = far * (1.0+proj(2,0)) / proj(0,0);
+    const double fTop = far * (1.0+proj(2,1)) / proj(1,1);
+    const double fBottom = far * (proj(2,1)-1.0) / proj(1,1);
+
+    // Our vertex array needs only 9 vertices: The origin, and the
+    // eight corners of the near and far planes.
+    osg::Vec3Array* v = new osg::Vec3Array;
+    v->resize( 9 );
+    (*v)[0].set( 0., 0., 0. );
+    (*v)[1].set( nLeft, nBottom, -near );
+    (*v)[2].set( nRight, nBottom, -near );
+    (*v)[3].set( nRight, nTop, -near );
+    (*v)[4].set( nLeft, nTop, -near );
+    (*v)[5].set( fLeft, fBottom, -far );
+    (*v)[6].set( fRight, fBottom, -far );
+    (*v)[7].set( fRight, fTop, -far );
+    (*v)[8].set( fLeft, fTop, -far );
+
+    osg::Geometry* geom = new osg::Geometry;
+    geom->setUseDisplayList( false );
+    geom->setVertexArray( v );
+
+    osg::Vec4Array* c = new osg::Vec4Array;
+    c->push_back( osg::Vec4( 1., 1., 0., 1. ) );
+    geom->setColorArray( c );
+    geom->setColorBinding( osg::Geometry::BIND_OVERALL );
+
+    GLushort idxLines[8] = {
+        0, 5, 0, 6, 0, 7, 0, 8 };
+    GLushort idxLoops0[4] = {
+        1, 2, 3, 4 };
+    GLushort idxLoops1[4] = {
+        5, 6, 7, 8 };
+    geom->addPrimitiveSet( new osg::DrawElementsUShort( osg::PrimitiveSet::LINES, 8, idxLines ) );
+    geom->addPrimitiveSet( new osg::DrawElementsUShort( osg::PrimitiveSet::LINE_LOOP, 4, idxLoops0 ) );
+    geom->addPrimitiveSet( new osg::DrawElementsUShort( osg::PrimitiveSet::LINE_LOOP, 4, idxLoops1 ) );
+
+    osg::Geode* geode = new osg::Geode;
+    geode->addDrawable( geom );
+
+    geode->getOrCreateStateSet()->setMode( GL_LIGHTING, osg::StateAttribute::OFF | osg::StateAttribute::PROTECTED );
+    geode->getOrCreateStateSet()->setAttributeAndModes(new osg::LineWidth(2.0f), 1);
+
+
+    // Create parent MatrixTransform to transform the view volume by
+    // the inverse ModelView matrix.
+    osg::MatrixTransform* mt = new osg::MatrixTransform;
+    mt->setMatrix( osg::Matrixd::inverse( mv ) );
+    mt->addChild( geode );
+
+    osg::Group* g0 = new osg::Group();
+    g0->addChild(mt);
+    g0->getOrCreateStateSet()->setAttributeAndModes(new osg::Depth(osg::Depth::ALWAYS, 0, 1, false), 1);
+    g0->getOrCreateStateSet()->setAttributeAndModes(new osg::LineStipple(1, 0x000F), 1);
+    g0->getOrCreateStateSet()->setRenderBinDetails(2, "RenderBin");
+
+    osg::Group* g1 = new osg::Group();
+    g1->addChild(mt);
+    g1->getOrCreateStateSet()->setRenderBinDetails(3, "RenderBin");
+
+    osg::Group* gr = new osg::Group();
+    gr->addChild(g0);
+    gr->addChild(g1);
+    gr->getOrCreateStateSet()->setRenderBinDetails(1, "RenderBin");
+
+    return gr;
+}
+
+
+int
+main( int argc, char** argv )
+{
+    osg::ArgumentParser arguments( &argc, argv );
+
+    osg::ref_ptr< osg::Group > root = new osg::Group;
+
+    osgViewer::CompositeViewer viewer( arguments );
+    viewer.setThreadingModel(viewer.SingleThreaded);
+
+    // Child 0: We'll replace this every frame with an updated representation
+    //   of the view frustum.
+    root->addChild( makeFrustumFromCamera( NULL ) );
+
+    osg::Group* scene = new osg::Group();
+    root->addChild( scene );
+
+
+    // Turn on FSAA, makes the lines look better.
+    osg::DisplaySettings::instance()->setNumMultiSamples( 4 );
+
+    // Create View 0 -- Just the loaded model.
+    {
+        osgViewer::View* view = new osgViewer::View;
+        viewer.addView( view );
+
+        view->setUpViewInWindow( 20, 20, 800, 800 );
+        view->setSceneData( scene );
+        view->setCameraManipulator( new EarthManipulator() );
+    }
+
+    // Create view 1 -- Contains the loaded moel, as well as a wireframe frustum derived from View 0's Camera.
+    {
+        osgViewer::View* view = new osgViewer::View;
+        viewer.addView( view );
+
+        view->setUpViewInWindow( 850, 20, 800, 800 );
+        view->setSceneData( root.get() );
+        view->setCameraManipulator( new EarthManipulator() );
+    }
+
+    MapNodeHelper helper;
+    osg::ref_ptr<osg::Node> node = helper.load(arguments, viewer.getView(0));
+    if (!node.valid())
+    {
+        return -1;
+    }
+    scene->addChild( node );
+
+    helper.configureView( viewer.getView(0) );
+    helper.configureView( viewer.getView(1) );
+
+    MapNode* mapNode = MapNode::get(node.get());
+
+    osg::ref_ptr<osg::Image> icon = osgDB::readImageFile("../data/placemark32.png");
+    PlaceNode* place = new PlaceNode(mapNode, GeoPoint::INVALID, icon.get(), "");
+    place->getOrCreateStateSet()->setRenderBinDetails(10, "DepthSortedBin");
+    place->setDynamic(true);
+    place->setNodeMask(0);
+    viewer.getView(0)->getCamera()->addChild( place );
+
+    MouseCoordsTool* mct = new MouseCoordsTool(mapNode);
+    mct->addCallback( new PlacerCallback(place, viewer.getView(0)) );
+    viewer.getView(1)->addEventHandler( mct );
+
+    mapNode->addChild(new HorizonNode());
+
+    viewer.getView(1)->getCamera()->addCullCallback( new VisitorData::Install("osgEarth.Stealth") );
+
+    while (!viewer.done())
+    {
+        // Update the wireframe frustum
+        root->removeChild( 0, 1 );
+        root->insertChild( 0, makeFrustumFromCamera( viewer.getView( 0 )->getCamera() ) );
+
+        viewer.frame();
+    }
+    return 0;
+}
diff --git a/src/applications/osgearth_annotation/osgearth_annotation.cpp b/src/applications/osgearth_annotation/osgearth_annotation.cpp
index f2c1b1d..f5e468d 100644
--- a/src/applications/osgearth_annotation/osgearth_annotation.cpp
+++ b/src/applications/osgearth_annotation/osgearth_annotation.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
@@ -21,19 +21,11 @@
 */
 
 #include <osgEarth/MapNode>
-#include <osgEarth/Decluttering>
-#include <osgEarth/ECEF>
-#include <osgEarth/Registry>
 
 #include <osgEarthUtil/EarthManipulator>
-#include <osgEarthUtil/AnnotationEvents>
-#include <osgEarthUtil/AutoClipPlaneHandler>
 #include <osgEarthUtil/ExampleResources>
 
-#include <osgEarthAnnotation/AnnotationEditing>
-#include <osgEarthAnnotation/AnnotationRegistry>
 #include <osgEarthAnnotation/ImageOverlay>
-#include <osgEarthAnnotation/ImageOverlayEditor>
 #include <osgEarthAnnotation/CircleNode>
 #include <osgEarthAnnotation/RectangleNode>
 #include <osgEarthAnnotation/EllipseNode>
@@ -41,23 +33,20 @@
 #include <osgEarthAnnotation/LabelNode>
 #include <osgEarthAnnotation/LocalGeometryNode>
 #include <osgEarthAnnotation/FeatureNode>
-#include <osgEarthAnnotation/HighlightDecoration>
-#include <osgEarthAnnotation/ScaleDecoration>
-#include <osgEarthUtil/ActivityMonitorTool>
+
+#include <osgEarthAnnotation/AnnotationEditing>
+#include <osgEarthAnnotation/ImageOverlayEditor>
 
 #include <osgEarthSymbology/GeometryFactory>
 
 #include <osgViewer/Viewer>
-#include <osgViewer/ViewerEventHandlers>
-#include <osgGA/StateSetManipulator>
-#include <osgGA/EventVisitor>
-#include <osgDB/WriteFile>
 
 using namespace osgEarth;
 using namespace osgEarth::Annotation;
 using namespace osgEarth::Features;
 using namespace osgEarth::Util;
-using namespace osgEarth::Util::Controls;
+
+//------------------------------------------------------------------
 
 int
 usage( char** argv )
@@ -66,65 +55,8 @@ usage( char** argv )
     return -1;
 }
 
-osg::Vec4
-randomColor()
-{
-    float r = (float)rand() / (float)RAND_MAX;
-    float g = (float)rand() / (float)RAND_MAX;
-    float b = (float)rand() / (float)RAND_MAX;
-    return osg::Vec4(r,g,b,1.0f);
-}
-
-
 //------------------------------------------------------------------
 
-/**
- * Event handler that processes events fired from the
- * AnnotationEventCallback
- */
-struct MyAnnoEventHandler : public AnnotationEventHandler
-{
-    void onHoverEnter( AnnotationNode* anno, const EventArgs& args )
-    {
-        anno->setDecoration( "hover" );
-        Registry::instance()->startActivity( "Hovering " + anno->getText() );
-        Registry::instance()->endActivity( _lastClick );
-    }
-
-    void onHoverLeave( AnnotationNode* anno, const EventArgs& args )
-    {
-        anno->clearDecoration();
-        Registry::instance()->endActivity( "Hovering " + anno->getText() );
-        Registry::instance()->endActivity( _lastClick );
-    }
-
-    virtual void onClick( AnnotationNode* anno, const EventArgs& details )
-    {
-        Registry::instance()->endActivity( _lastClick );
-        _lastClick = "Clicked " + anno->getText();
-        Registry::instance()->startActivity( _lastClick );
-    }
-
-    std::string _lastClick;
-};
-
-//------------------------------------------------------------------
-
-struct ToggleNodeHandler : public ControlEventHandler
-{
-    ToggleNodeHandler( osg::Node* node ) : _node(node) { }
-
-    void onValueChanged( Control* control, bool value )
-    {
-        _node->setNodeMask( value ? ~0 : 0 );
-    }
-
-    osg::Node* _node;
-};
-
-//------------------------------------------------------------------
-
-
 int
 main(int argc, char** argv)
 {
@@ -152,34 +84,13 @@ main(int argc, char** argv)
     osg::Group* annoGroup = new osg::Group();
     root->addChild( annoGroup );
 
-    //A group for all the editors
-    osg::Group* editorGroup = new osg::Group;
-    root->addChild( editorGroup );
-    editorGroup->setNodeMask( 0 );
-
-    HBox* box = ControlCanvas::getOrCreate(&viewer)->addControl( new HBox() );
-    box->setChildSpacing( 5 );
-    //Add a toggle button to toggle editing
-    CheckBoxControl* editCheckbox = new CheckBoxControl( false );
-    editCheckbox->addEventHandler( new ToggleNodeHandler( editorGroup ) );
-    box->addControl( editCheckbox );
-    LabelControl* labelControl = new LabelControl( "Edit Annotations" );
-    labelControl->setFontSize( 24.0f );
-    box->addControl( labelControl  );
-
-    // Activity monitor:
-    VBox* activityBox = ControlCanvas::getOrCreate(&viewer)->addControl( new VBox() );
-    activityBox->setHorizAlign(activityBox->ALIGN_RIGHT);
-    activityBox->setVertAlign(activityBox->ALIGN_BOTTOM);
-    activityBox->setBackColor(0,0,0,0.75);
-    viewer.addEventHandler(new ActivityMonitorTool(activityBox));
-
-    // Make a group for 2D items, and activate the decluttering engine. Decluttering
-    // will migitate overlap between elements that occupy the same screen real estate.
+    // Make a group for labels
     osg::Group* labelGroup = new osg::Group();
-    Decluttering::setEnabled( labelGroup->getOrCreateStateSet(), true );
     annoGroup->addChild( labelGroup );
 
+    osg::Group* editGroup = new osg::Group();
+    root->addChild( editGroup );
+
     // Style our labels:
     Style labelStyle;
     labelStyle.getOrCreate<TextSymbol>()->alignment() = TextSymbol::ALIGN_CENTER_CENTER;
@@ -192,27 +103,29 @@ main(int argc, char** argv)
 
     // A series of place nodes (an icon with a text label)
     {
-        Style pin;
-        pin.getOrCreate<IconSymbol>()->url()->setLiteral( "../data/placemark32.png" );
+        Style pm;
+        pm.getOrCreate<IconSymbol>()->url()->setLiteral( "../data/placemark32.png" );
+        pm.getOrCreate<IconSymbol>()->declutter() = true;
+        pm.getOrCreate<TextSymbol>()->halo() = Color("#5f5f5f");
 
         // bunch of pins:
-        labelGroup->addChild( new PlaceNode(mapNode, GeoPoint(geoSRS, -74.00, 40.71), "New York"      , pin));
-        labelGroup->addChild( new PlaceNode(mapNode, GeoPoint(geoSRS, -77.04, 38.85), "Washington, DC", pin));
-        labelGroup->addChild( new PlaceNode(mapNode, GeoPoint(geoSRS,-118.40, 33.93), "Los Angeles"   , pin));
-        labelGroup->addChild( new PlaceNode(mapNode, GeoPoint(geoSRS, -71.03, 42.37), "Boston"        , pin));
-        labelGroup->addChild( new PlaceNode(mapNode, GeoPoint(geoSRS,-157.93, 21.35), "Honolulu"      , pin));
-        labelGroup->addChild( new PlaceNode(mapNode, GeoPoint(geoSRS, 139.75, 35.68), "Tokyo"         , pin));
-        labelGroup->addChild( new PlaceNode(mapNode, GeoPoint(geoSRS, -90.25, 29.98), "New Orleans"   , pin));
-        labelGroup->addChild( new PlaceNode(mapNode, GeoPoint(geoSRS, -80.28, 25.82), "Miami"         , pin));
-        labelGroup->addChild( new PlaceNode(mapNode, GeoPoint(geoSRS,-117.17, 32.72), "San Diego"     , pin));
+        labelGroup->addChild( new PlaceNode(mapNode, GeoPoint(geoSRS, -74.00, 40.71), "New York"      , pm));
+        labelGroup->addChild( new PlaceNode(mapNode, GeoPoint(geoSRS, -77.04, 38.85), "Washington, DC", pm));
+        labelGroup->addChild( new PlaceNode(mapNode, GeoPoint(geoSRS,-118.40, 33.93), "Los Angeles"   , pm));
+        labelGroup->addChild( new PlaceNode(mapNode, GeoPoint(geoSRS, -71.03, 42.37), "Boston"        , pm));
+        labelGroup->addChild( new PlaceNode(mapNode, GeoPoint(geoSRS,-157.93, 21.35), "Honolulu"      , pm));
+        labelGroup->addChild( new PlaceNode(mapNode, GeoPoint(geoSRS, 139.75, 35.68), "Tokyo"         , pm));
+        labelGroup->addChild( new PlaceNode(mapNode, GeoPoint(geoSRS, -90.25, 29.98), "New Orleans"   , pm));
+        labelGroup->addChild( new PlaceNode(mapNode, GeoPoint(geoSRS, -80.28, 25.82), "Miami"         , pm));
+        labelGroup->addChild( new PlaceNode(mapNode, GeoPoint(geoSRS,-117.17, 32.72), "San Diego"     , pm));
 
         // test with an LOD:
         osg::LOD* lod = new osg::LOD();
-        lod->addChild( new PlaceNode(mapNode, GeoPoint(geoSRS, 14.68, 50.0), "Prague", pin), 0.0, 1e6);
+        lod->addChild( new PlaceNode(mapNode, GeoPoint(geoSRS, 14.68, 50.0), "Prague", pm), 0.0, 2e6);
         labelGroup->addChild( lod );
 
         // absolute altitude:
-        labelGroup->addChild( new PlaceNode(mapNode, GeoPoint(geoSRS, -87.65, 41.90, 1000, ALTMODE_ABSOLUTE), "Chicago"       , pin));
+        labelGroup->addChild( new PlaceNode(mapNode, GeoPoint(geoSRS, -87.65, 41.90, 1000, ALTMODE_ABSOLUTE), "Chicago", pm));
     }
 
     //--------------------------------------------------------------------
@@ -224,13 +137,20 @@ main(int argc, char** argv)
         geom->push_back( osg::Vec3d(-60, 40, 0) );
         geom->push_back( osg::Vec3d(-60, 60, 0) );
         geom->push_back( osg::Vec3d(0,   60, 0) );
+
+        Feature* feature = new Feature(geom, geoSRS);
+        feature->geoInterp() = GEOINTERP_RHUMB_LINE;
+
         Style geomStyle;
         geomStyle.getOrCreate<LineSymbol>()->stroke()->color() = Color::Cyan;
         geomStyle.getOrCreate<LineSymbol>()->stroke()->width() = 5.0f;
+        geomStyle.getOrCreate<LineSymbol>()->tessellationSize() = 75000;
         geomStyle.getOrCreate<AltitudeSymbol>()->clamping() = AltitudeSymbol::CLAMP_TO_TERRAIN;
         geomStyle.getOrCreate<AltitudeSymbol>()->technique() = AltitudeSymbol::TECHNIQUE_GPU;
-        FeatureNode* gnode = new FeatureNode(mapNode, new Feature(geom, geoSRS), geomStyle);
-        annoGroup->addChild( gnode );
+        
+        FeatureNode* fnode = new FeatureNode(mapNode, feature, geomStyle);
+        
+        annoGroup->addChild( fnode );
 
         labelGroup->addChild( new LabelNode(mapNode, GeoPoint(geoSRS,-30, 50), "Rhumb line polygon", labelStyle) );
     }
@@ -245,11 +165,17 @@ main(int argc, char** argv)
         geom->push_back(  160., -45. );
         geom->push_back( -150., -40. );
         Style geomStyle;
+
+        Feature* feature = new Feature(geom, geoSRS);
+        feature->geoInterp() = GEOINTERP_RHUMB_LINE;
+
         geomStyle.getOrCreate<LineSymbol>()->stroke()->color() = Color::Lime;
         geomStyle.getOrCreate<LineSymbol>()->stroke()->width() = 3.0f;
+        geomStyle.getOrCreate<LineSymbol>()->tessellationSize() = 75000;
         geomStyle.getOrCreate<AltitudeSymbol>()->clamping() = AltitudeSymbol::CLAMP_TO_TERRAIN;
         geomStyle.getOrCreate<AltitudeSymbol>()->technique() = AltitudeSymbol::TECHNIQUE_GPU;
-        FeatureNode* gnode = new FeatureNode(mapNode, new Feature(geom, geoSRS), geomStyle);
+
+        FeatureNode* gnode = new FeatureNode(mapNode, feature, geomStyle);
         annoGroup->addChild( gnode );
 
         labelGroup->addChild( new LabelNode(mapNode, GeoPoint(geoSRS, -175, -35), "Antimeridian polygon", labelStyle) );
@@ -267,15 +193,18 @@ main(int argc, char** argv)
         path->push_back( osg::Vec3d(-74, 40.714, 0) );   // New York
         path->push_back( osg::Vec3d(139.75, 35.68, 0) ); // Tokyo
 
+        Feature* pathFeature = new Feature(path, geoSRS);
+        pathFeature->geoInterp() = GEOINTERP_GREAT_CIRCLE;
+
         Style pathStyle;
-        pathStyle.getOrCreate<LineSymbol>()->stroke()->color() = Color::Red;
-        pathStyle.getOrCreate<LineSymbol>()->stroke()->width() = 3.0f;
+        pathStyle.getOrCreate<LineSymbol>()->stroke()->color() = Color::White;
+        pathStyle.getOrCreate<LineSymbol>()->stroke()->width() = 1.0f;
+        pathStyle.getOrCreate<LineSymbol>()->tessellationSize() = 75000;
+        pathStyle.getOrCreate<PointSymbol>()->size() = 5;
+        pathStyle.getOrCreate<PointSymbol>()->fill()->color() = Color::Red;
         pathStyle.getOrCreate<AltitudeSymbol>()->clamping() = AltitudeSymbol::CLAMP_TO_TERRAIN;
         pathStyle.getOrCreate<AltitudeSymbol>()->technique() = AltitudeSymbol::TECHNIQUE_GPU;
 
-        Feature* pathFeature = new Feature(path, geoSRS);
-        pathFeature->geoInterp() = GEOINTERP_GREAT_CIRCLE;
-
         //OE_INFO << "Path extent = " << pathFeature->getExtent().toString() << std::endl;
 
         pathNode = new FeatureNode(mapNode, pathFeature, pathStyle);
@@ -300,7 +229,7 @@ main(int argc, char** argv)
             circleStyle, Angle(-45.0, Units::DEGREES), Angle(45.0, Units::DEGREES), true);
         annoGroup->addChild( circle );
 
-        editorGroup->addChild( new CircleNodeEditor( circle ) );
+        editGroup->addChild( new CircleNodeEditor(circle) );
     }
 
 	{
@@ -316,7 +245,7 @@ main(int argc, char** argv)
 			circleStyle, Angle(45.0, Units::DEGREES), Angle(360.0 - 45.0, Units::DEGREES), true);
 		annoGroup->addChild( circle );
 
-		editorGroup->addChild( new CircleNodeEditor( circle ) );
+        editGroup->addChild( new CircleNodeEditor(circle) );
 	}
 
     //--------------------------------------------------------------------
@@ -337,7 +266,8 @@ main(int argc, char** argv)
             Angle(360.0 - 45.0, Units::DEGREES), 
             true);
         annoGroup->addChild( ellipse );
-        editorGroup->addChild( new EllipseNodeEditor( ellipse ) );
+
+        editGroup->addChild( new EllipseNodeEditor(ellipse) );
     }
 	{
 		Style ellipseStyle;
@@ -354,7 +284,8 @@ main(int argc, char** argv)
             Angle(40.0, Units::DEGREES), 
             true);
 		annoGroup->addChild( ellipse );
-		editorGroup->addChild( new EllipseNodeEditor( ellipse ) );
+
+        editGroup->addChild( new EllipseNodeEditor(ellipse) );
 	}
     
     //--------------------------------------------------------------------
@@ -373,7 +304,7 @@ main(int argc, char** argv)
             rectStyle);
         annoGroup->addChild( rect );
 
-        editorGroup->addChild( new RectangleNodeEditor( rect ) );
+        editGroup->addChild( new RectangleNodeEditor(rect) );
     }    
 
     //--------------------------------------------------------------------
@@ -411,121 +342,14 @@ main(int argc, char** argv)
             imageOverlay->setBounds( Bounds( -100.0, 35.0, -90.0, 40.0) );
             annoGroup->addChild( imageOverlay );
 
-            editorGroup->addChild( new ImageOverlayEditor( imageOverlay ) );
-        }
-    }
-
-    /*
-    // Add a bunch of features as individual FeatureNodes.  This is slow.
-    {
-        // A lat/lon grid, showing lots of features as individual feature nodes
-        for (unsigned int i = 0; i < 360; i++)
-        {
-            for (unsigned int j = 0; j < 180; j++)
-            {
-                double w = -180.0 + (double)(i);
-                double e = w + 1.0;
-                double s = -90 + (double)(j);
-                double n = s + 1.0;
-
-                Geometry* geometry = new Polygon();
-                geometry->push_back( w, s );
-                geometry->push_back( e, s );
-                geometry->push_back( e, n );
-                geometry->push_back( w, n );
-                
-                Style style;
-                style.getOrCreate<LineSymbol>()->stroke()->color() = Color::Red;
-                style.getOrCreate<LineSymbol>()->stroke()->width() = 3.0f;
-
-                Feature*     feature = new Feature(geometry, geoSRS, style);
-                FeatureNode* featureNode = new FeatureNode(mapNode, feature);
-                annoGroup->addChild( featureNode );
-            }
-        }
-    }
-    */
-
-    /*
-     // Add a bunch of features to a single FeatureNodes.  This is slow.
-    {
-        FeatureList features;
-
-        Style style;
-        style.getOrCreate<LineSymbol>()->stroke()->color() = Color::Red;
-        style.getOrCreate<LineSymbol>()->stroke()->width() = 3.0f;
-
-        // A lat/lon grid, showing lots of features within a single FeatureNode
-        for (unsigned int i = 0; i < 360; i++)
-        {
-            for (unsigned int j = 0; j < 180; j++)
-            {
-                double w = -180.0 + (double)(i);
-                double e = w + 1.0;
-                double s = -90 + (double)(j);
-                double n = s + 1.0;
-
-                Geometry* geometry = new Polygon();
-                geometry->push_back( w, s );
-                geometry->push_back( e, s );
-                geometry->push_back( e, n );
-                geometry->push_back( w, n );
-
-                Feature*     feature = new Feature(geometry, geoSRS );
-                features.push_back( feature );
-            }
+            editGroup->addChild( new ImageOverlayEditor(imageOverlay) );
         }
-
-        FeatureNode* featureNode = new FeatureNode( mapNode, features );
-        featureNode->setStyle( style );
-        annoGroup->addChild( featureNode );
     }
-    */
-    
-    //--------------------------------------------------------------------
-
-    // install decoration. These change the appearance of an Annotation
-    // based on some user action.
-
-    // highlight annotation upon hover by default:
-    
-    DecorationInstaller highlightInstaller("hover", new HighlightDecoration());
-    annoGroup->accept( highlightInstaller );
-
-    // scale labels when hovering:
-    DecorationInstaller scaleInstaller("hover", new ScaleDecoration(1.1f));
-    labelGroup->accept( scaleInstaller );
-
-    // install an event handler for picking and hovering.
-    AnnotationEventCallback* cb = new AnnotationEventCallback();
-    cb->addHandler( new MyAnnoEventHandler() );
-
-    annoGroup->addEventCallback( cb );
 
     //--------------------------------------------------------------------
 
     // initialize the viewer:    
-    viewer.setSceneData( root );
-
-    viewer.getCamera()->addCullCallback( new AutoClipPlaneCullCallback(mapNode) );
-    viewer.addEventHandler(new osgViewer::StatsHandler());
-    viewer.addEventHandler(new osgViewer::WindowSizeHandler());
-    viewer.addEventHandler(new osgGA::StateSetManipulator(viewer.getCamera()->getOrCreateStateSet()));
-    
+    viewer.setSceneData( root );    
     viewer.getCamera()->setSmallFeatureCullingPixelSize(-1.0f);
-
-    while (!viewer.done())
-    {
-        if (viewer.getFrameStamp()->getFrameNumber() % 100 == 0)
-        {
-            // Change the color of the great circle path every 100 frames
-            Style pathStyle = pathNode->getStyle();
-            pathStyle.getOrCreate<LineSymbol>()->stroke()->color() = randomColor();
-            pathNode->setStyle( pathStyle );
-        }
-        
-        viewer.frame();
-    }
-
-    return 0;
+    return viewer.run();
 }
diff --git a/src/applications/osgearth_atlas/osgearth_atlas.cpp b/src/applications/osgearth_atlas/osgearth_atlas.cpp
index b01d1c0..bad44c1 100644
--- a/src/applications/osgearth_atlas/osgearth_atlas.cpp
+++ b/src/applications/osgearth_atlas/osgearth_atlas.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
@@ -26,6 +26,7 @@
 #include <osgEarthUtil/AtlasBuilder>
 #include <osgEarthSymbology/ResourceLibrary>
 #include <osgEarthSymbology/Skins>
+#include <osgEarth/Utils>
 
 #include <osg/ArgumentParser>
 #include <osgDB/FileUtils>
@@ -137,8 +138,11 @@ build(osg::ArgumentParser& arguments)
     if ( !builder.build(lib.get(), outImageFile, atlas) )
         return usage("Failed to build atlas");
 
-    // write the atlas images.
-    osgDB::writeImageFile(*atlas._images.begin()->get(), outImageFile);
+    // write the atlas images. don't flip DDS's.
+    osg::ref_ptr<osgDB::Options> writeOptions = new osgDB::Options();
+    writeOptions->setOptionString("ddsNoAutoFlipWrite");
+
+    osgDB::writeImageFile(*atlas._images.begin()->get(), outImageFile, writeOptions.get());
     OE_INFO << LC << "Wrote output image to \"" << outImageFile << "\"" << std::endl;
     
     // write any aux images.
@@ -150,7 +154,7 @@ build(osg::ArgumentParser& arguments)
             "_" + auxPatterns[i] + "." +
             osgDB::getFileExtension(outImageFile);
 
-        osgDB::writeImageFile(*atlas._images[i+1].get(), auxAtlasFile);
+        osgDB::writeImageFile(*atlas._images[i + 1].get(), auxAtlasFile, writeOptions.get());
         
         OE_INFO << LC << "Wrote auxiliary image to \"" << auxAtlasFile << "\"" << std::endl;
     }
@@ -219,6 +223,10 @@ show(osg::ArgumentParser& arguments)
     osgEarth::ImageUtils::flattenImage(image, images);
     osg::Geode* geode = osg::createGeodeForImage(images[layer].get());
 
+    const osg::BoundingBox& bbox = osgEarth::Utils::getBoundingBox(geode->getDrawable(0));
+    float width = bbox.xMax() - bbox.xMin();
+    float height = bbox.zMax() - bbox.zMin();
+
     // geometry for the skins in that layer:
     osg::Geode* geode2 = new osg::Geode();
     osg::Geometry* geom = new osg::Geometry();
@@ -231,15 +239,16 @@ show(osg::ArgumentParser& arguments)
     geom->setColorBinding(geom->BIND_OVERALL);
     osgEarth::Symbology::SkinResourceVector skins;
     lib->getSkins(skins);
+    OE_WARN << "num = " << skins.size() << "\n";
+
     for(unsigned k=0; k<skins.size(); ++k)
     {
-        if (skins[k]->imageLayer() == layer &&
-            skins[k]->isTiled() == false)
+        if (skins[k]->imageLayer() == layer && skins[k]->atlasHint() != false)
         {
-            float x = -1.0f + 2.0*skins[k]->imageBiasS().value();
-            float y = -1.0f + 2.0*skins[k]->imageBiasT().value();
-            float s = 2.0*skins[k]->imageScaleS().value();
-            float t = 2.0*skins[k]->imageScaleT().value();
+            float x = bbox.xMin() + width*skins[k]->imageBiasS().value();
+            float y = bbox.zMin() + height*skins[k]->imageBiasT().value();
+            float s = width*skins[k]->imageScaleS().value();
+            float t = height*skins[k]->imageScaleT().value();
 
             v->push_back(osg::Vec3(x,     -0.01f, y    ));
             v->push_back(osg::Vec3(x + s, -0.01f, y    ));
diff --git a/src/applications/osgearth_backfill/osgearth_backfill.cpp b/src/applications/osgearth_backfill/osgearth_backfill.cpp
index afdaed7..f664eac 100644
--- a/src/applications/osgearth_backfill/osgearth_backfill.cpp
+++ b/src/applications/osgearth_backfill/osgearth_backfill.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/applications/osgearth_boundarygen/BoundaryUtil b/src/applications/osgearth_boundarygen/BoundaryUtil
index 7856b5a..9fb18fc 100644
--- a/src/applications/osgearth_boundarygen/BoundaryUtil
+++ b/src/applications/osgearth_boundarygen/BoundaryUtil
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/applications/osgearth_boundarygen/BoundaryUtil.cpp b/src/applications/osgearth_boundarygen/BoundaryUtil.cpp
index 74941d1..66fb5e7 100644
--- a/src/applications/osgearth_boundarygen/BoundaryUtil.cpp
+++ b/src/applications/osgearth_boundarygen/BoundaryUtil.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
@@ -506,7 +506,7 @@ BoundaryUtil::findMeshBoundary( osg::Node* node, bool geocentric )
     node->accept( buildTopoVisitor );
 
     OE_DEBUG << "Found " << topology._verts.size() << " unique verts" << std::endl;
-    dumpPointCloud(topology);
+    //dumpPointCloud(topology);
 
     // starting with the minimum-Y vertex (which is guaranteed to be in the boundary)
     // traverse the outside of the point set. Do this by sorting all the edges by
diff --git a/src/applications/osgearth_boundarygen/VertexCollectionVisitor b/src/applications/osgearth_boundarygen/VertexCollectionVisitor
index a723ba9..3d92c51 100644
--- a/src/applications/osgearth_boundarygen/VertexCollectionVisitor
+++ b/src/applications/osgearth_boundarygen/VertexCollectionVisitor
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/applications/osgearth_boundarygen/VertexCollectionVisitor.cpp b/src/applications/osgearth_boundarygen/VertexCollectionVisitor.cpp
index 0353825..edba9e7 100644
--- a/src/applications/osgearth_boundarygen/VertexCollectionVisitor.cpp
+++ b/src/applications/osgearth_boundarygen/VertexCollectionVisitor.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/applications/osgearth_boundarygen/boundarygen.cpp b/src/applications/osgearth_boundarygen/boundarygen.cpp
index c7df676..d33f91c 100644
--- a/src/applications/osgearth_boundarygen/boundarygen.cpp
+++ b/src/applications/osgearth_boundarygen/boundarygen.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/applications/osgearth_cache_test/osgearth_cache_test.cpp b/src/applications/osgearth_cache_test/osgearth_cache_test.cpp
index 25e6a06..2056a07 100644
--- a/src/applications/osgearth_cache_test/osgearth_cache_test.cpp
+++ b/src/applications/osgearth_cache_test/osgearth_cache_test.cpp
@@ -42,7 +42,7 @@ quit(const std::string& msg)
 int
 main(int argc, char** argv)
 {
-    osg::ref_ptr<Cache> cache = Registry::instance()->getCache();
+    osg::ref_ptr<Cache> cache = Registry::instance()->getDefaultCache();
     if ( !cache.valid() )
     {
         return quit( "Please configure a cache path in your environment (OSGEARTH_CACHE_PATH)." );
@@ -58,10 +58,10 @@ main(int argc, char** argv)
         std::string value( "What is the sound of one hand clapping?" );
         osg::ref_ptr<StringObject> s = new StringObject( value );
 
-        if ( !bin->write("string_key", s.get()) )
+        if ( !bin->write("string_key", s.get(), 0L) )
             return quit( "String write failed." );
 
-        ReadResult r = bin->readString("string_key");
+        ReadResult r = bin->readString("string_key", 0L);
         if ( r.failed() )
             return quit( Stringify() << "String read failed - " << r.getResultCodeString() );
 
@@ -75,10 +75,10 @@ main(int argc, char** argv)
     {
         osg::ref_ptr<osg::Image> image = ImageUtils::createOnePixelImage(osg::Vec4(1,0,0,1));
 
-        if ( !bin->write("image_key", image.get()) )
+        if ( !bin->write("image_key", image.get(), 0L) )
             return quit("Image write failed.");
 
-        ReadResult r = bin->readImage("image_key");
+        ReadResult r = bin->readImage("image_key", 0L);
         if ( r.failed() )
             return quit( Stringify() << "Image read failed - " << r.getResultCodeString() );
 
@@ -89,7 +89,7 @@ main(int argc, char** argv)
     }
 
     // Need to properly shut down the cache here
-    Registry::instance()->setCache( 0L );
+    cache = 0L;
 
     OE_NOTICE << "All tests passed." << std::endl;
     return 0;
diff --git a/src/applications/osgearth_city/osgearth_city.cpp b/src/applications/osgearth_city/osgearth_city.cpp
index 781fe53..a6116da 100644
--- a/src/applications/osgearth_city/osgearth_city.cpp
+++ b/src/applications/osgearth_city/osgearth_city.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
@@ -205,7 +205,10 @@ void addStreets(Map* map)
     // a resampling filter will ensure that the length of each segment falls
     // within the specified range. That can be helpful to avoid cropping 
     // very long lines segments.
-    feature_opt.filters().push_back( new ResampleFilter(0.0, 25.0) );
+    ResampleFilterOptions resample;
+    resample.minLength() = 0.0f;
+    resample.maxLength() = 25.0f;
+    feature_opt.filters().push_back( resample );
 
     // a style:
     Style style;
diff --git a/src/applications/osgearth_clamp/osgearth_clamp.cpp b/src/applications/osgearth_clamp/osgearth_clamp.cpp
index 6218371..d813544 100644
--- a/src/applications/osgearth_clamp/osgearth_clamp.cpp
+++ b/src/applications/osgearth_clamp/osgearth_clamp.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/applications/osgearth_clipplane/osgearth_clipplane.cpp b/src/applications/osgearth_clipplane/osgearth_clipplane.cpp
index cf6b5af..a12f981 100644
--- a/src/applications/osgearth_clipplane/osgearth_clipplane.cpp
+++ b/src/applications/osgearth_clipplane/osgearth_clipplane.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
@@ -56,7 +56,7 @@ usage(const char* name)
 
 // Vertex shader to activate clip planes in GLSL:
 const char* clipvs =
-    "#version 110 \n"
+    "#version " GLSL_VERSION_STR "\n"
     "void oe_clip_vert(inout vec4 vertex_view) { \n"
     "   gl_ClipVertex = vertex_view; \n"
     "}\n";
diff --git a/src/applications/osgearth_colorfilter/osgearth_colorfilter.cpp b/src/applications/osgearth_colorfilter/osgearth_colorfilter.cpp
index 460a22b..fe65f48 100644
--- a/src/applications/osgearth_colorfilter/osgearth_colorfilter.cpp
+++ b/src/applications/osgearth_colorfilter/osgearth_colorfilter.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/applications/osgearth_computerangecallback/CMakeLists.txt b/src/applications/osgearth_computerangecallback/CMakeLists.txt
new file mode 100644
index 0000000..eba5aea
--- /dev/null
+++ b/src/applications/osgearth_computerangecallback/CMakeLists.txt
@@ -0,0 +1,7 @@
+INCLUDE_DIRECTORIES(${OSG_INCLUDE_DIRS} )
+SET(TARGET_LIBRARIES_VARS OSG_LIBRARY OSGDB_LIBRARY OSGUTIL_LIBRARY OSGVIEWER_LIBRARY OPENTHREADS_LIBRARY)
+
+SET(TARGET_SRC osgearth_computerangecallback.cpp )
+
+#### end var setup  ###
+SETUP_APPLICATION(osgearth_computerangecallback)
\ No newline at end of file
diff --git a/src/applications/osgearth_computerangecallback/osgearth_computerangecallback.cpp b/src/applications/osgearth_computerangecallback/osgearth_computerangecallback.cpp
new file mode 100644
index 0000000..be37189
--- /dev/null
+++ b/src/applications/osgearth_computerangecallback/osgearth_computerangecallback.cpp
@@ -0,0 +1,122 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+* Copyright 2016 Pelican Mapping
+* http://osgearth.org
+*
+* osgEarth is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* 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.
+*
+* You should have received a copy of the GNU Lesser General Public License
+* along with this program.  If not, see <http://www.gnu.org/licenses/>
+*/
+
+#include <osgViewer/Viewer>
+#include <osgEarth/Notify>
+#include <osgEarth/TerrainEngineNode>
+#include <osgEarthUtil/EarthManipulator>
+#include <osgEarthUtil/ExampleResources>
+
+#define LC "[viewer] "
+
+using namespace osgEarth;
+using namespace osgEarth::Util;
+
+int
+usage(const char* name)
+{
+    OE_NOTICE 
+        << "\nUsage: " << name << " file.earth" << std::endl
+        << MapNodeHelper().usage() << std::endl;
+
+    return 0;
+}
+
+struct MyComputeRangeCallback : public osgEarth::ComputeRangeCallback
+{
+    virtual float operator()(osg::Node* node, osg::NodeVisitor& nv)
+    {
+        osgUtil::CullVisitor* cv = dynamic_cast<osgUtil::CullVisitor*>(&nv);
+        if (cv)
+        {
+            // This code assumes that the range_mode is PIXEL_SIZE_ON_SCREEN and computes the pixel size on screen 
+            // without just using the vertical field of view.
+            float distance = nv.getDistanceToViewPoint(node->getBound().center(),true);
+            float radius = node->getBound().radius();
+
+            double fov, ar, near, far;
+            cv->getCurrentCamera()->getProjectionMatrixAsPerspective(fov, ar, near,far);
+
+            osg::Viewport* viewPort = cv->getCurrentCamera()->getViewport();
+            double angularSize = osg::RadiansToDegrees( 2.0*atan(radius/distance) );
+            double dpp = osg::maximum(fov, 1.0e-17) / viewPort->height();
+            float pixelSize = angularSize / dpp;
+            return pixelSize;
+        }
+
+        // Fall back to the base calculation.
+        return -1.0;
+    }
+};
+
+int
+main(int argc, char** argv)
+{
+    osg::ArgumentParser arguments(&argc,argv);
+
+    // help?
+    if ( arguments.read("--help") )
+        return usage(argv[0]);
+
+    // create a viewer:
+    osgViewer::Viewer viewer(arguments);
+
+    // Tell the database pager to not modify the unref settings
+    viewer.getDatabasePager()->setUnrefImageDataAfterApplyPolicy( false, false );
+
+    // thread-safe initialization of the OSG wrapper manager. Calling this here
+    // prevents the "unsupported wrapper" messages from OSG
+    osgDB::Registry::instance()->getObjectWrapperManager()->findWrapper("osg::Image");
+
+    // install our default manipulator (do this before calling load)
+    viewer.setCameraManipulator( new EarthManipulator(arguments) );
+
+    // disable the small-feature culling
+    viewer.getCamera()->setSmallFeatureCullingPixelSize(-1.0f);
+
+    // set a near/far ratio that is smaller than the default. This allows us to get
+    // closer to the ground without near clipping. If you need more, use --logdepth
+    viewer.getCamera()->setNearFarRatio(0.0001);
+
+
+    // load an earth file, and support all or our example command-line options
+    // and earth file <external> tags    
+    osg::Node* node = MapNodeHelper().load( arguments, &viewer );
+    if ( node )
+    {
+        viewer.setSceneData( node );
+
+        // Set a custom ComputeRangeCallback on the MapNode
+        MapNode* mapNode = MapNode::findMapNode(node);
+        mapNode->getTerrainEngine()->setComputeRangeCallback( new MyComputeRangeCallback() );
+
+
+        while(!viewer.done())
+        {
+            viewer.frame();
+        }
+    }
+    else
+    {
+        return usage(argv[0]);
+    }
+}
diff --git a/src/applications/osgearth_controls/osgearth_controls.cpp b/src/applications/osgearth_controls/osgearth_controls.cpp
index eff9e95..9220327 100644
--- a/src/applications/osgearth_controls/osgearth_controls.cpp
+++ b/src/applications/osgearth_controls/osgearth_controls.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
@@ -37,7 +37,7 @@ using namespace osgEarth::Util::Controls;
 
 
 void createControls( ControlCanvas* );
-ImageControl* s_imageControl;
+ImageControl* s_imageControl = 0L;
 
 
 int main(int argc, char** argv)
@@ -45,10 +45,15 @@ int main(int argc, char** argv)
     osg::ArgumentParser arguments(&argc,argv);       
     osgViewer::Viewer viewer(arguments);
 
-    osg::Group* root = new osg::Group();
     osg::Node* node = osgEarth::Util::MapNodeHelper().load(arguments, &viewer);
-    if ( node )
-        root->addChild( node );
+    if (!node)
+    {
+        OE_WARN << "No earth file on the command line." << std::endl;
+        return -1;
+    }
+    
+    osg::Group* root = new osg::Group();
+    root->addChild( node );
 
     // create a surface to house the controls
     ControlCanvas* cs = ControlCanvas::getOrCreate( &viewer );
@@ -89,7 +94,8 @@ struct RotateImage : public ControlEventHandler
 {
     void onValueChanged( Control* control, float value )
     {
-        s_imageControl->setRotation( Angular(value) );
+        if (s_imageControl)
+            s_imageControl->setRotation( Angular(value) );
     }
 };
 
@@ -106,7 +112,7 @@ createControls( ControlCanvas* cs )
         center->setVertAlign( Control::ALIGN_CENTER );
 
         // Add an image:
-        osg::ref_ptr<osg::Image> image = osgDB::readImageFile("http://osgearth.org/images/octocat-icon.png");
+        osg::ref_ptr<osg::Image> image = osgDB::readImageFile("../data/osgearth.gif");
         if ( image.valid() )
         {
             s_imageControl = new ImageControl( image.get() );
diff --git a/src/applications/osgearth_conv/osgearth_conv.cpp b/src/applications/osgearth_conv/osgearth_conv.cpp
index c0f7c2c..e6fb7b3 100644
--- a/src/applications/osgearth_conv/osgearth_conv.cpp
+++ b/src/applications/osgearth_conv/osgearth_conv.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
@@ -44,6 +44,8 @@ int usage(char** argv)
         << "\n    --profile [profile def]             : set an output profile (optional; default = same as input)"
         << "\n    --min-level [int]                   : minimum level of detail"
         << "\n    --max-level [int]                   : maximum level of detail"
+        << "\n    --osg-options [OSG options string]  : options to pass to OSG readers/writers"
+        << "\n    --extents [minLat] [minLong] [maxLat] [maxLong] : Lat/Long extends to copy"
         << std::endl;
         
     return 0;
@@ -103,8 +105,9 @@ struct ImageLayerToTileSource : public TileHandler
     {
         bool ok = false;
         GeoImage image = _source->createImage(key);
-        if ( image.valid() )
-            ok = _dest->storeImage(key, image.getImage(), 0L);
+        if (image.valid())
+            ok = _dest->storeImage(key, image.getImage(), 0L);        
+
         return ok;
     }
     
@@ -207,6 +210,10 @@ struct ProgressReporter : public osgEarth::ProgressCallback
  *
  *      --extents [minLat] [minLong] [maxLat] [maxLong] : Lat/Long extends to copy (*)
  *
+ * OSG arguments:
+ *
+ *      -O <string>           : OSG Options string (plugin options)
+ *
  * Of course, the output driver must support writing (by implementing
  * the ReadWriteTileSource interface).
  */
@@ -226,6 +233,15 @@ main(int argc, char** argv)
     while( args.read("--in", key, value) )
         inConf.set(key, value);
 
+    osg::ref_ptr<osgDB::Options> dbo = new osgDB::Options();
+    
+    // plugin options, if the user passed them in:
+    std::string str;
+    while(args.read("--osg-options", str) || args.read("-O", str))
+    {
+        dbo->setOptionString( str );
+    }
+
     TileSourceOptions inOptions(inConf);
     osg::ref_ptr<TileSource> input = TileSourceFactory::create(inOptions);
     if ( !input.valid() )
@@ -234,7 +250,7 @@ main(int argc, char** argv)
         return -1;
     }
 
-    TileSource::Status inputStatus = input->open();
+    Status inputStatus = input->open( input->MODE_READ, dbo.get() );
     if ( inputStatus.isError() )
     {
         OE_WARN << LC << "Error initializing input" << std::endl;
@@ -282,7 +298,10 @@ main(int argc, char** argv)
         return -1;
     }
 
-    TileSource::Status outputStatus = output->open(TileSource::MODE_WRITE | TileSource::MODE_CREATE);
+    Status outputStatus = output->open(
+        TileSource::MODE_WRITE | TileSource::MODE_CREATE,
+        dbo.get() );
+
     if ( outputStatus.isError() )
     {
         OE_WARN << LC << "Error initializing output" << std::endl;
diff --git a/src/applications/osgearth_createtile/osgearth_createtile.cpp b/src/applications/osgearth_createtile/osgearth_createtile.cpp
index 5eac5fb..56806ba 100644
--- a/src/applications/osgearth_createtile/osgearth_createtile.cpp
+++ b/src/applications/osgearth_createtile/osgearth_createtile.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
@@ -36,9 +36,11 @@
 #include <osgEarth/ElevationQuery>
 #include <osgEarth/StringUtils>
 #include <osgEarth/Terrain>
+#include <osgEarth/GeoTransform>
 #include <osgEarthUtil/EarthManipulator>
 #include <osgEarthUtil/Controls>
 #include <osgEarthUtil/LatLongFormatter>
+#include <osgEarthUtil/ExampleResources>
 #include <osg/TriangleFunctor>
 #include <osgDB/WriteFile>
 #include <iomanip>
@@ -48,6 +50,7 @@ using namespace osgEarth::Util;
 
 static MapNode*       s_mapNode     = 0L;
 static osg::Group*    s_root        = 0L;
+static osg::ref_ptr< osg::Node >  marker = osgDB::readNodeFile("../data/red_flag.osg");
 
 struct CollectTriangles
 {
@@ -96,7 +99,8 @@ struct CollectTrianglesVisitor : public osg::NodeVisitor
             for (unsigned int j = 0; j < triangleCollector.verts->size(); j++)
             {
                 osg::Matrix& matrix = _matrixStack.back();
-                _vertices->push_back((*triangleCollector.verts)[j] * matrix);
+                osg::Vec3d v = (*triangleCollector.verts)[j];
+                _vertices->push_back(v * matrix);
             }
         }
     }
@@ -121,7 +125,6 @@ struct CollectTrianglesVisitor : public osg::NodeVisitor
                 anchor = (*_vertices)[i];
                 first = false;
             }
-
             verts->push_back((*_vertices)[i] - anchor);
         }
 
@@ -132,10 +135,18 @@ struct CollectTrianglesVisitor : public osg::NodeVisitor
 
         osg::Geode* geode = new osg::Geode;
         geode->addDrawable(geom);
+        geode->setCullingActive( false );
         geom->addPrimitiveSet(new osg::DrawArrays(GL_TRIANGLES, 0, verts->size()));
         mt->addChild(geode);
-        mt->getOrCreateStateSet()->setMode(GL_DEPTH_TEST, osg::StateAttribute::OFF);
+        //mt->getOrCreateStateSet()->setMode(GL_DEPTH_TEST, osg::StateAttribute::OFF);
         mt->getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
+        mt->getOrCreateStateSet()->setRenderBinDetails(99, "RenderBin");
+
+        osg::BoundingSphere bs = mt->getBound();
+        bs.radius() = bs.radius() * 100;
+        mt->setInitialBound(bs);
+        mt->dirtyBound();
+
         return mt;
     }
 
@@ -151,7 +162,6 @@ struct CollectTrianglesVisitor : public osg::NodeVisitor
 
 
 
-
 // An event handler that will create a tile that can be used for intersections
 struct CreateTileHandler : public osgGA::GUIEventHandler
 {
@@ -174,20 +184,41 @@ struct CreateTileHandler : public osgGA::GUIEventHandler
             GeoPoint mapPoint;
             mapPoint.fromWorld( s_mapNode->getMapSRS(), world );
 
-            TileKey key = s_mapNode->getMap()->getProfile()->createTileKey(mapPoint.x(), mapPoint.y(), 13);
+            // Depending on the level of detail key you request, you will get a mesh that should line up exactly with the highest resolution mesh that the terrain engine will draw.
+            // At level 15 that is a 257x257 heightfield.  If you select a higher lod, the mesh will be less dense.
+            TileKey key = s_mapNode->getMap()->getProfile()->createTileKey(mapPoint.x(), mapPoint.y(), 15);            
             OE_NOTICE << "Creating tile " << key.str() << std::endl;
             osg::ref_ptr<osg::Node> node = s_mapNode->getTerrainEngine()->createTile(key);
             if (node.valid())
-            {
+            {   
+                // Extract the triangles from the node that was created and do our own rendering.  Simulates what you would do when passing in the triangles to a physics engine.
                 OE_NOTICE << "Created tile for " << key.str() << std::endl;
                 CollectTrianglesVisitor v;
                 node->accept(v);
+                node = v.buildNode();
+
+                if (_node.valid())
+                {
+                    s_root->removeChild( _node.get() );
+                }
+
+                osg::Group* group = new osg::Group;
+                
+                // Show the actual mesh.
+                group->addChild( node.get() );
+
+                _node = group;
+
+                // Clamp the marker to the intersection of the triangles created by osgEarth.  This should line up with the mesh that is actually rendered.
+                double z = 0.0;
+                s_mapNode->getTerrain()->getHeight( node, s_mapNode->getMapSRS(), mapPoint.x(), mapPoint.y(), &z);
+
+                GeoTransform* xform = new GeoTransform();
+                xform->setPosition( osgEarth::GeoPoint(s_mapNode->getMapSRS(),mapPoint.x(),  mapPoint.y(), z, ALTMODE_ABSOLUTE) );
+                xform->addChild( marker.get() );
+                group->addChild( xform );
 
-                osg::ref_ptr<osg::Node> output = v.buildNode();
-                osgDB::writeNodeFile( *output.get(), "createtile.osgt" );
-                OE_NOTICE << "Wrote tile to createtile.osgt\n";
-                //osgDB::writeNodeFile(v.buildNode(
-                //s_root->addChild(v.buildNode());
+                s_root->addChild( _node.get() );
             }
             else
             {
@@ -206,6 +237,8 @@ struct CreateTileHandler : public osgGA::GUIEventHandler
 
         return false;
     }
+
+    osg::ref_ptr< osg::Node > _node;
 };
 
 
@@ -215,29 +248,29 @@ int main(int argc, char** argv)
 
     osgViewer::Viewer viewer(arguments);
 
-    s_mapNode = MapNode::load(arguments);
-    if ( !s_mapNode )
-    {
-        OE_WARN << "Unable to load earth file." << std::endl;
-        return -1;
-    }
-
     s_root = new osg::Group();
-    viewer.setSceneData( s_root );
-
+    
     // install the programmable manipulator.
     viewer.setCameraManipulator( new osgEarth::Util::EarthManipulator() );
 
     // The MapNode will render the Map object in the scene graph.
-    s_root->addChild( s_mapNode );
+    osg::Node* node = MapNodeHelper().load(arguments, &viewer);
+    s_mapNode = MapNode::findMapNode(node);
+    s_root->addChild( node );
+
+    // disable the small-feature culling
+    viewer.getCamera()->setSmallFeatureCullingPixelSize(-1.0f);
+
+    // set a near/far ratio that is smaller than the default. This allows us to get
+    // closer to the ground without near clipping. If you need more, use --logdepth
+    viewer.getCamera()->setNearFarRatio(0.0001);
+    viewer.getCamera()->setComputeNearFarMode( osg::CullSettings::COMPUTE_NEAR_FAR_USING_BOUNDING_VOLUMES );
+
 
     // An event handler that will respond to mouse clicks:
     viewer.addEventHandler( new CreateTileHandler() );
 
-    // add some stock OSG handlers:
-    viewer.addEventHandler(new osgViewer::StatsHandler());
-    viewer.addEventHandler(new osgViewer::WindowSizeHandler());
-    viewer.addEventHandler(new osgGA::StateSetManipulator(viewer.getCamera()->getOrCreateStateSet()));
+    viewer.setSceneData( s_root );
 
     return viewer.run();
 }
diff --git a/src/applications/osgearth_datetime/CMakeLists.txt b/src/applications/osgearth_datetime/CMakeLists.txt
new file mode 100644
index 0000000..5277399
--- /dev/null
+++ b/src/applications/osgearth_datetime/CMakeLists.txt
@@ -0,0 +1,7 @@
+INCLUDE_DIRECTORIES(${OSG_INCLUDE_DIRS} )
+SET(TARGET_LIBRARIES_VARS OSG_LIBRARY OSGDB_LIBRARY OSGUTIL_LIBRARY OSGVIEWER_LIBRARY OPENTHREADS_LIBRARY)
+
+SET(TARGET_SRC osgearth_datetime.cpp )
+
+#### end var setup  ###
+SETUP_APPLICATION(osgearth_datetime)
\ No newline at end of file
diff --git a/src/applications/osgearth_datetime/osgearth_datetime.cpp b/src/applications/osgearth_datetime/osgearth_datetime.cpp
new file mode 100644
index 0000000..2df042b
--- /dev/null
+++ b/src/applications/osgearth_datetime/osgearth_datetime.cpp
@@ -0,0 +1,198 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+* Copyright 2016 Pelican Mapping
+* http://osgearth.org
+*
+* osgEarth is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* 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.
+*
+* You should have received a copy of the GNU Lesser General Public License
+* along with this program.  If not, see <http://www.gnu.org/licenses/>
+*/
+
+#include <osgEarth/MapNode>
+#include <osgEarth/ScreenSpaceLayout>
+#include <osgEarth/ECEF>
+#include <osgEarth/Registry>
+
+#include <osgEarthUtil/EarthManipulator>
+#include <osgEarthUtil/AnnotationEvents>
+#include <osgEarthUtil/AutoClipPlaneHandler>
+#include <osgEarthUtil/ExampleResources>
+
+#include <osgEarthAnnotation/AnnotationData>
+
+#include <osgEarthDrivers/kml/KML>
+
+#include <osgViewer/Viewer>
+#include <osgViewer/ViewerEventHandlers>
+#include <osgGA/StateSetManipulator>
+#include <osgGA/EventVisitor>
+#include <osgDB/WriteFile>
+
+using namespace osgEarth;
+using namespace osgEarth::Annotation;
+using namespace osgEarth::Drivers;
+using namespace osgEarth::Util;
+using namespace osgEarth::Util::Controls;
+
+struct CollectDateTimeRangeVisitor : public osg::NodeVisitor
+{
+    DateTimeRange range;
+
+    CollectDateTimeRangeVisitor() : osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN) { }
+
+    virtual void apply(osg::Node& node)
+    {
+        AnnotationData* data = dynamic_cast<AnnotationData*>(node.getUserData());
+        if (data &&
+            (data->getDateTimeRange().begin().isSet() || data->getDateTimeRange().end().isSet()))
+        {
+            range.expandBy(data->getDateTimeRange());
+        }
+
+        traverse(node);
+    }    
+};
+
+struct CullNodeByDateTimeRange : public osg::NodeCallback
+{
+    DateTimeRange range;
+
+    void operator()(osg::Node* node, osg::NodeVisitor* nv)
+    {        
+        AnnotationData* data = dynamic_cast<AnnotationData*>(node->getUserData());
+        if (data && !data->getDateTimeRange().intersects(range))
+        {
+            return;
+        }
+
+        traverse(node, nv);
+    }
+};
+
+struct AssignCullCallbakVisitor : public osg::NodeVisitor
+{
+    CullNodeByDateTimeRange* callback;
+
+    AssignCullCallbakVisitor(CullNodeByDateTimeRange* cb) :
+        osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN),
+        callback(cb)
+    { }
+
+    virtual void apply(osg::Node& node)
+    {
+        AnnotationData* data = dynamic_cast<AnnotationData*>(node.getUserData());
+        if (data &&
+            (data->getDateTimeRange().begin().isSet() || data->getDateTimeRange().end().isSet()))
+        {
+            node.addCullCallback(callback);
+        }
+
+        traverse(node);
+    }    
+};
+
+struct TimeSliderHandler : public ControlEventHandler
+{
+    osg::ref_ptr<CullNodeByDateTimeRange> callback;
+    DateTimeRange fullRange;
+
+    TimeSliderHandler(CullNodeByDateTimeRange* cb, DateTimeRange r) :
+        callback(cb),
+        fullRange(r)
+    {
+    }
+
+    void onValueChanged(Control* control, float value)
+    {
+        TimeStamp beginTs = fullRange.begin()->asTimeStamp();
+        TimeStamp endTs = fullRange.end()->asTimeStamp();
+        TimeStamp delta = endTs - beginTs;
+
+        callback->range.begin() = DateTime(beginTs + delta * (value / 100));
+        callback->range.end() = DateTime(beginTs + delta * ((value + 1) / 100));
+    }
+};
+
+int
+usage( char** argv )
+{
+    OE_WARN << "Usage: " << argv[0] << " <earthfile> --kml <kmlfile>" << std::endl;
+    return -1;
+}
+
+int
+main(int argc, char** argv)
+{
+    osg::Group* root = new osg::Group();
+
+    // try to load an earth file.
+    osg::ArgumentParser arguments(&argc,argv);
+    
+    osgViewer::Viewer viewer(arguments);
+    viewer.getDatabasePager()->setUnrefImageDataAfterApplyPolicy(false, false);
+    viewer.setCameraManipulator( new EarthManipulator() );
+    viewer.getCamera()->setSmallFeatureCullingPixelSize(-1.0f);
+    viewer.getCamera()->setNearFarRatio(0.00002);
+
+    // load an earth file and parse demo arguments
+    osg::Node* node = MapNodeHelper().load(arguments, &viewer);
+    if ( !node )
+        return usage(argv);
+
+    root->addChild( node );
+
+    // find the map node that we loaded.
+    MapNode* mapNode = MapNode::findMapNode(node);
+    if ( !mapNode )
+        return usage(argv);
+
+    //--------------------------------------------------------------------
+
+    CollectDateTimeRangeVisitor collectVisitor;
+    collectVisitor.setNodeMaskOverride(~0);
+    node->accept(collectVisitor);
+    
+    osg::ref_ptr<CullNodeByDateTimeRange> callback = new CullNodeByDateTimeRange;
+    
+    AssignCullCallbakVisitor assignVisitor(callback);
+    assignVisitor.setNodeMaskOverride(~0);
+    node->accept(assignVisitor);
+
+    ControlCanvas* cs = ControlCanvas::getOrCreate(&viewer);
+
+    HSliderControl* slider = new HSliderControl(0, 100);
+    slider->setHorizAlign(Control::ALIGN_LEFT);
+    slider->setVertAlign(Control::ALIGN_TOP);
+    slider->setBackColor(.6, 0, 0, 1);
+    slider->setHeight(25);
+    slider->setWidth(300);    
+    slider->addEventHandler(new TimeSliderHandler(callback, collectVisitor.range));
+    slider->setValue(0.0);
+    cs->addControl(slider);
+
+    //--------------------------------------------------------------------
+
+    // initialize the viewer:    
+    viewer.setSceneData( root );
+
+    viewer.getCamera()->addCullCallback( new AutoClipPlaneCullCallback(mapNode) );
+    viewer.addEventHandler(new osgViewer::StatsHandler());
+    viewer.addEventHandler(new osgViewer::WindowSizeHandler());
+    viewer.addEventHandler(new osgGA::StateSetManipulator(viewer.getCamera()->getOrCreateStateSet()));
+    
+    viewer.run();
+
+    return 0;
+}
diff --git a/src/applications/osgearth_deformation/CMakeLists.txt b/src/applications/osgearth_deformation/CMakeLists.txt
new file mode 100644
index 0000000..1802175
--- /dev/null
+++ b/src/applications/osgearth_deformation/CMakeLists.txt
@@ -0,0 +1,7 @@
+INCLUDE_DIRECTORIES(${OSG_INCLUDE_DIRS} )
+SET(TARGET_LIBRARIES_VARS OSG_LIBRARY OSGDB_LIBRARY OSGUTIL_LIBRARY OSGVIEWER_LIBRARY OPENTHREADS_LIBRARY)
+
+SET(TARGET_SRC osgearth_deformation.cpp )
+
+#### end var setup  ###
+SETUP_APPLICATION(osgearth_deformation)
diff --git a/src/applications/osgearth_deformation/osgearth_deformation.cpp b/src/applications/osgearth_deformation/osgearth_deformation.cpp
new file mode 100644
index 0000000..fe13231
--- /dev/null
+++ b/src/applications/osgearth_deformation/osgearth_deformation.cpp
@@ -0,0 +1,599 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+* Copyright 2016 Pelican Mapping
+* http://osgearth.org
+*
+* osgEarth is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* 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.
+*
+* You should have received a copy of the GNU Lesser General Public License
+* along with this program.  If not, see <http://www.gnu.org/licenses/>
+*/
+
+#include <osgGA/StateSetManipulator>
+#include <osgGA/GUIEventHandler>
+#include <osgViewer/Viewer>
+#include <osgViewer/ViewerEventHandlers>
+#include <osgUtil/LineSegmentIntersector>
+#include <osgEarth/MapNode>
+#include <osgEarth/TerrainEngineNode>
+#include <osgEarth/ElevationQuery>
+#include <osgEarth/StringUtils>
+#include <osgEarth/Terrain>
+#include <osgEarth/VerticalDatum>
+#include <osgEarth/Registry>
+#include <osgEarthUtil/EarthManipulator>
+#include <osgEarthUtil/Controls>
+#include <osgEarthUtil/LatLongFormatter>
+#include <osgEarthUtil/ExampleResources>
+#include <osgEarthSymbology/Geometry>
+#include <osgEarthSymbology/GeometryRasterizer>
+#include <osgEarthUtil/EarthManipulator>
+#include <osgEarthUtil/AutoClipPlaneHandler>
+#include <osgEarthFeatures/Feature>
+#include <osgEarthAnnotation/FeatureNode>
+#include <osgEarthSymbology/GeometryFactory>
+#include <iomanip>
+
+
+using namespace osgEarth;
+using namespace osgEarth::Annotation;
+using namespace osgEarth::Features;
+using namespace osgEarth::Util;
+using namespace osgEarth::Symbology;
+
+
+class Deformation
+{
+public:
+    Deformation(Feature* feature, double offset):
+      _feature(feature),
+          _offset(offset)
+      {
+      }
+
+      osg::ref_ptr< Feature > _feature;
+      double _offset;
+};
+
+typedef std::vector< Deformation > DeformationList;
+
+typedef std::map< TileKey, osg::ref_ptr< osg::HeightField > > HeightFieldMap;
+
+
+/**
+* Applies the deformation to the heightfield with the given key.
+*/
+static void deformHeightField(const Deformation& deformation, const TileKey& key, osg::HeightField* heightField)
+{   
+    osgEarth::Symbology::Polygon* boundary = dynamic_cast<osgEarth::Symbology::Polygon*>(deformation._feature->getGeometry());
+    if (!boundary)
+    {
+        OE_WARN << "NOT A POLYGON" << std::endl;
+        return;
+    }
+
+    //Get the extents of the tile
+    double xmin, ymin, xmax, ymax;
+    key.getExtent().getBounds(xmin, ymin, xmax, ymax);
+
+    int tileSize = heightField->getNumColumns();
+
+    // Iterate over the output heightfield and sample the data that was read into it.
+    double dx = (xmax - xmin) / (tileSize-1);
+    double dy = (ymax - ymin) / (tileSize-1);     
+
+
+    const SpatialReference* srs = SpatialReference::create("wgs84");
+
+    for (int c = 0; c < tileSize; ++c)
+    {
+        double geoX = xmin + (dx * (double)c);
+        for (int r = 0; r < tileSize; ++r)
+        {
+            double geoY = ymin + (dy * (double)r);
+
+            GeoPoint geo(srs, geoX, geoY, 0.0, ALTMODE_ABSOLUTE);
+            if ( boundary->contains2D(geo.x(), geo.y()) )
+            {
+                heightField->setHeight(c, r, deformation._offset);
+            }                
+        }
+    }
+}
+
+static void applyBlast(GeoPoint& center, double radius, double offset, const TileKey& key, osg::HeightField* heightField)
+{
+    //Get the extents of the tile
+    double xmin, ymin, xmax, ymax;
+    key.getExtent().getBounds(xmin, ymin, xmax, ymax);
+
+    int tileSize = heightField->getNumColumns();
+
+    // Iterate over the output heightfield and sample the data that was read into it.
+    double dx = (xmax - xmin) / (tileSize-1);
+    double dy = (ymax - ymin) / (tileSize-1);     
+
+    const SpatialReference* srs = SpatialReference::create("wgs84");
+
+    for (int c = 0; c < tileSize; ++c)
+    {
+        double geoX = xmin + (dx * (double)c);
+        for (int r = 0; r < tileSize; ++r)
+        {
+            double geoY = ymin + (dy * (double)r);
+
+            GeoPoint geo(srs, geoX, geoY, center.z(), ALTMODE_ABSOLUTE);
+
+            double distance = geo.distanceTo( center );
+            double ratio = distance / radius;
+            if (ratio <= 1.0)
+            {
+                double weight = 1.0 - osg::clampBetween(ratio, 0.0, 1.0);
+                if (weight > 0)
+                {
+                    float h = center.z() + offset * weight;
+                    heightField->setHeight(c, r, h);
+                }
+            }
+            
+            /*
+
+
+            if ( boundary->contains2D(geo.x(), geo.y()) )
+            {
+                float h = heightField->getHeight( c, r );
+                if (h == NO_DATA_VALUE)
+                {
+                    //h = deformation._offset;
+                }
+                else
+                {
+                    //h += deformation._offset;                    
+                    h = deformation._offset;
+                }
+                heightField->setHeight(c, r, h);
+            } 
+            */
+        }
+    }
+}
+
+/*
+void getHeightFieldsForDeformation(const Deformation& deformation, MapFrame& map, unsigned int level, HeightFieldMap& results)
+{
+    // Get the extent of the deformation feature.
+    GeoExtent extent(deformation._feature->getSRS(), deformation._feature->getGeometry()->getBounds());
+
+    TileKey ll = map.getProfile()->createTileKey(extent.xMin(), extent.yMin(), level);
+    TileKey ur = map.getProfile()->createTileKey(extent.xMax(), extent.yMax(), level);        
+
+    for (unsigned int c = ll.getTileX(); c <= ur.getTileX(); c++)
+    {
+        for (unsigned int r = ur.getTileY(); r <= ll.getTileY(); r++)
+        {
+            TileKey key(level, c, r, map.getProfile());
+            //Allocate a new heightfield
+            osg::ref_ptr< osg::HeightField > hf = new osg::HeightField;
+            hf->allocate(257, 257);
+            for (unsigned int i = 0; i < hf->getHeightList().size(); ++i) hf->getHeightList()[i] = NO_DATA_VALUE;
+            // We don't actually need to populate it unless we are doing some logic on it, right?
+            //map.populateHeightField(hf, key, false, 0);
+            results[ key ] = hf.get();            
+        }
+    }
+}
+*/
+
+
+
+
+class DeformationTileSource : public TileSource
+{
+public: 
+    // Constructor that takes the user-provided options.
+    DeformationTileSource(const TileSourceOptions& options) : TileSource(options)
+    {
+    }
+
+    // Called by the terrain engine when a layer using this driver is first added.
+    Status initialize(const osgDB::Options* dbOptions)
+    {
+        if ( !getProfile() )
+        {
+            setProfile( Registry::instance()->getGlobalGeodeticProfile() );
+        }
+        return STATUS_OK;
+    }
+
+    // Tells the layer not to cache data from this tile source.
+    CachePolicy getCachePolicyHint(const Profile* profile) const 
+    {
+        return CachePolicy::NO_CACHE;
+    }
+
+    osg::HeightField* createHeightField(const TileKey& key, ProgressCallback* progress)
+    {
+        OpenThreads::ScopedLock< OpenThreads::Mutex > lk(_mutex);
+
+        // See if we have a neightfield in the cache
+        HeightFieldMap::iterator itr = _heightfields.find( key );
+        if (itr != _heightfields.end())
+        {
+            osg::HeightField* hf = itr->second.get();
+            return hf;
+        }
+        return 0;        
+    }
+
+    /*
+    void addDeformation(const Deformation& deformation)
+    {
+        OpenThreads::ScopedLock< OpenThreads::Mutex > lk(_mutex);
+        _deformations.push_back( deformation );
+
+        // Get the heightfields that might be effect by the deformation
+        HeightFieldMap heightfields;
+        for (unsigned int i = 5; i < 10; i++)
+        {
+            getOrCreateHeightFieldsForDeformation( deformation, i, heightfields);
+        }
+
+        OE_NOTICE << "Applying deformation to " << heightfields.size() << " heightfields" << std::endl;
+
+        // Actually apply the deformation
+        for (HeightFieldMap::iterator itr = heightfields.begin(); itr != heightfields.end(); ++itr)
+        {
+            deformHeightField( deformation, itr->first, itr->second.get());
+        }
+    }
+    */
+
+    void addHeightField(const TileKey& key, osg::HeightField* heightfield)
+    {
+        OpenThreads::ScopedLock< OpenThreads::Mutex > lk(_mutex);
+        _heightfields[ key ] = heightfield;
+    }
+
+    virtual int getPixelsPerTile() const
+    {
+        return 257;
+    }
+
+    /**
+    * Gets or creates the heightfields that would be effected by the given deformation
+    */
+    void getOrCreateHeightFieldsForDeformation(const Deformation& deformation, unsigned int level, HeightFieldMap& results)
+    {
+        OpenThreads::ScopedLock< OpenThreads::Mutex > lk(_mutex);
+
+        // Get the extent of the deformation feature.
+        GeoExtent extent(deformation._feature->getSRS(), deformation._feature->getGeometry()->getBounds());
+
+        TileKey ll = getProfile()->createTileKey(extent.xMin(), extent.yMin(), level);
+        TileKey ur = getProfile()->createTileKey(extent.xMax(), extent.yMax(), level);        
+
+        for (unsigned int c = ll.getTileX(); c <= ur.getTileX(); c++)
+        {
+            for (unsigned int r = ur.getTileY(); r <= ll.getTileY(); r++)
+            {
+                TileKey key(level, c, r, getProfile());
+
+                osg::ref_ptr< osg::HeightField > hf;
+
+                HeightFieldMap::iterator itr = _heightfields.find( key );
+                if (itr == _heightfields.end())
+                {
+                    //Allocate a new heightfield
+                    hf = new osg::HeightField;
+                    hf->allocate(getPixelsPerTile(), getPixelsPerTile());
+                    for (unsigned int i = 0; i < hf->getHeightList().size(); ++i) hf->getHeightList()[i] = NO_DATA_VALUE;
+                    _heightfields[ key ] = hf.get();
+                    results[ key ] = hf.get();
+                }
+                else
+                {                
+                    results[ key ] = itr->second.get();
+                }
+            }
+        }
+    }
+
+
+
+
+
+
+    OpenThreads::Mutex _mutex;
+    std::vector< Deformation > _deformations;
+
+    HeightFieldMap _heightfields;
+
+};
+
+static MapNode*       s_mapNode     = 0L;
+static DeformationTileSource* s_deformations = 0L;
+
+enum Tool
+{
+    TOOL_CIRCLE,
+    TOOL_RECTANGLE,
+    TOOL_BLAST
+};
+
+struct DeformationHandler : public osgGA::GUIEventHandler 
+{
+    DeformationHandler(osg::Group* root)
+        : _mouseDown( false ),
+        _terrain  ( s_mapNode->getTerrain() ),
+        _tool(TOOL_CIRCLE),
+        _root(root),
+        _offset(-100.0f),
+        _radius(100.0),
+        _query( s_mapNode->getMap() )
+    {
+        _map = s_mapNode->getMap();
+        _query.setMaxTilesToCache(10);
+        _query.setFallBackOnNoData( false );
+    }
+
+    void update( float x, float y, osgViewer::View* view )
+    {
+        bool yes = false;
+
+        // look under the mouse:
+        osg::Vec3d world;
+        osgUtil::LineSegmentIntersector::Intersections hits;
+        if ( view->computeIntersections(x, y, hits) )
+        {
+            world = hits.begin()->getWorldIntersectPoint();
+
+            // convert to map coords:
+            GeoPoint mapPoint;
+            mapPoint.fromWorld( _terrain->getSRS(), world );
+            mapPoint.z() = 0;
+
+            // do an elevation query:
+            double query_resolution = 0; // max.
+            double out_hamsl        = 0.0;
+            double out_resolution   = 0.0;
+
+            bool ok = _query.getElevation( 
+                mapPoint,
+                out_hamsl,
+                query_resolution, 
+                &out_resolution );
+            mapPoint.z() = out_hamsl;
+            _mapPoint = mapPoint;
+
+            
+
+            GeometryFactory factory(SpatialReference::create("wgs84"));
+            Geometry* geom = 0;
+            if (_tool == TOOL_RECTANGLE)
+            {
+                geom = factory.createRectangle(mapPoint.vec3d(), _radius,_radius);
+            }
+            else if (_tool == TOOL_CIRCLE || _tool == TOOL_BLAST)
+            {
+                geom = factory.createCircle(mapPoint.vec3d(), _radius);
+            }
+
+            Feature* feature = new Feature(geom, SpatialReference::create("wgs84"));
+
+            if (_featureNode.valid())
+            {
+                _root->removeChild( _featureNode );
+                _featureNode = 0;
+            }
+
+            Style style;
+            style.getOrCreateSymbol<AltitudeSymbol>()->clamping() = AltitudeSymbol::CLAMP_TO_TERRAIN;
+            style.getOrCreateSymbol<AltitudeSymbol>()->technique() = AltitudeSymbol::TECHNIQUE_DRAPE;
+            if (_tool != TOOL_BLAST)
+            {
+                style.getOrCreateSymbol<PolygonSymbol>()->fill()->color() = Color(Color::Cyan, 0.5);
+            }
+            else
+            {
+                style.getOrCreateSymbol<PolygonSymbol>()->fill()->color() = Color(Color::Red, 0.5);
+            }
+
+            _featureNode = new FeatureNode( s_mapNode,
+                feature,
+                style);
+            _root->addChild( _featureNode );
+        }
+    }
+
+    bool handle( const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa )
+    {
+        if (ea.getEventType() == osgGA::GUIEventAdapter::MOVE ||
+            ea.getEventType() == osgGA::GUIEventAdapter::DRAG)
+        {
+            osgViewer::View* view = static_cast<osgViewer::View*>(aa.asView());
+            update( ea.getX(), ea.getY(), view );
+            if (_mouseDown)
+            {                
+                applyDeformation();
+            }
+        }
+        if (ea.getEventType() == osgGA::GUIEventAdapter::PUSH && ea.getButton() == osgGA::GUIEventAdapter::MIDDLE_MOUSE_BUTTON)
+        {
+            _mouseDown = true;
+            osgViewer::View* view = static_cast<osgViewer::View*>(aa.asView());
+            update( ea.getX(), ea.getY(), view );
+            applyDeformation();
+        }
+        if (ea.getEventType() == osgGA::GUIEventAdapter::RELEASE && ea.getButton() == osgGA::GUIEventAdapter::MIDDLE_MOUSE_BUTTON)
+        {
+            _mouseDown = false;
+        }
+        else if (ea.getEventType() == osgGA::GUIEventAdapter::KEYDOWN)
+        {
+            if (ea.getKey() == 'k')
+            {
+                if (_tool == TOOL_CIRCLE)
+                {
+                    OE_NOTICE << "Switching to rectangle tool" << std::endl;
+                    _tool = TOOL_RECTANGLE;
+                }
+                else if (_tool == TOOL_RECTANGLE)
+                {
+                    OE_NOTICE << "Switching to blast tool" << std::endl;
+                    _tool = TOOL_BLAST;
+                }
+                else if (_tool == TOOL_BLAST)
+                {
+                    OE_NOTICE << "Switching to circle tool" << std::endl;
+                    _tool = TOOL_CIRCLE;
+                }
+                return true;
+            }
+            else if (ea.getKey() == 'o')
+            {
+                _offset -= 10;
+                OE_NOTICE << "Offset " << _offset << std::endl;
+                return true;
+            }
+            else if (ea.getKey() == 'O')
+            {
+                _offset += 10;
+                OE_NOTICE << "Offset " << _offset << std::endl;
+                return true;
+            }
+            else if (ea.getKey() == 'r')
+            {
+                _radius = osg::clampAbove(_radius - 10.0, 1.0);
+                OE_NOTICE << "Radius = " << _radius << std::endl;
+            }
+            else if (ea.getKey() == 'R')
+            {
+                _radius += 10;
+                OE_NOTICE << "Radius = " << _radius << std::endl;
+            }
+        }
+
+        return false;
+    }
+
+    void applyDeformation()
+    {
+        if (_featureNode)
+        {
+            Feature* feature = _featureNode->getFeature();
+            OE_NOTICE << "Adding deformation " << feature->getGeoJSON() << std::endl;
+
+            Deformation deformation(feature, _offset);
+            // Instead of applying the deformation, we are going to add a heightfield ourselves.
+            //s_deformations->addDeformation(Deformation(feature, _offset));
+
+
+            MapFrame frame(s_mapNode->getMap());
+            // Get the heightfields that might be effect by the deformation
+            HeightFieldMap heightfields;
+            for (unsigned int i = 0; i < 14; i++)
+            {
+                //getHeightFieldsForDeformation(deformation, frame, i, heightfields);
+                s_deformations->getOrCreateHeightFieldsForDeformation(deformation, i, heightfields);
+            }
+
+            OE_NOTICE << "Deforming " << heightfields.size() << std::endl;
+
+            // Actually apply the deformation
+            for (HeightFieldMap::iterator itr = heightfields.begin(); itr != heightfields.end(); ++itr)
+            {
+                // Deform heightfield based on a polygon
+                if (_tool == TOOL_CIRCLE || _tool == TOOL_RECTANGLE)
+                {
+                    // Set the offset to be absolute since we aren't using offset heightfield anymore.
+                    deformation._offset = _mapPoint.z() + _offset;
+                    deformHeightField( deformation, itr->first, itr->second.get());
+                }
+                else if (_tool == TOOL_BLAST)
+                {
+                    // Apply a simple blast radius
+                    applyBlast(_mapPoint, _radius, -_radius, itr->first, itr->second);
+                }
+                s_deformations->addHeightField( itr->first, itr->second.get());
+            }
+
+            osgEarth::Registry::instance()->clearBlacklist();
+            s_deformations->getBlacklist()->clear();
+            s_mapNode->getTerrainEngine()->dirtyTerrain();            
+        }
+    }
+
+    const Map*       _map;
+    const Terrain*   _terrain;
+    bool             _mouseDown;
+    Tool _tool;
+    osg::Group* _root;
+    float _offset;
+    double _radius;
+    GeoPoint _mapPoint;
+    osg::ref_ptr < FeatureNode > _featureNode;
+    ElevationQuery   _query;
+};
+
+
+int main(int argc, char** argv)
+{
+    osg::ArgumentParser arguments(&argc,argv);
+
+    osgViewer::Viewer viewer(arguments);
+
+    s_mapNode = 0L;
+    osg::Node* earthFile = MapNodeHelper().load(arguments, &viewer);
+    if (earthFile)
+        s_mapNode = MapNode::get(earthFile);
+
+    if ( !s_mapNode )
+    {
+        OE_WARN << "Unable to load earth file." << std::endl;
+        return -1;
+    }
+
+    TileSourceOptions tileSourceOptions;
+    tileSourceOptions.L2CacheSize() = 0;
+    s_deformations = new DeformationTileSource(tileSourceOptions);
+    s_deformations->open();
+
+    ElevationLayerOptions elevationOpt;
+    //elevationOpt.offset() = true;
+    elevationOpt.name() = "deformation";
+    // This is the only way to get the l2 cache size to pass down even though we're not actually creating a tilesource from the options.
+    elevationOpt.driver() = tileSourceOptions;
+
+    ElevationLayer* layer = new ElevationLayer(elevationOpt, s_deformations);
+    layer->open();
+    s_mapNode->getMap()->addElevationLayer(layer);
+
+    osg::Group* root = new osg::Group();
+    viewer.setSceneData( root );
+
+    // install the programmable manipulator.
+    viewer.setCameraManipulator( new osgEarth::Util::EarthManipulator() );
+
+    // The MapNode will render the Map object in the scene graph.
+    root->addChild( earthFile );
+
+    viewer.addEventHandler( new DeformationHandler(root) );
+
+    // add some stock OSG handlers:
+    viewer.addEventHandler(new osgViewer::StatsHandler());
+    viewer.addEventHandler(new osgViewer::WindowSizeHandler());
+    viewer.addEventHandler(new osgGA::StateSetManipulator(viewer.getCamera()->getOrCreateStateSet()));
+
+    return viewer.run();
+}
diff --git a/src/applications/osgearth_demo/osgearth_demo.cpp b/src/applications/osgearth_demo/osgearth_demo.cpp
index 989d661..98d6b35 100644
--- a/src/applications/osgearth_demo/osgearth_demo.cpp
+++ b/src/applications/osgearth_demo/osgearth_demo.cpp
@@ -65,6 +65,9 @@ main(int argc, char** argv)
     osg::ArgumentParser arguments(&argc,argv);
     osgViewer::Viewer viewer(arguments);
 
+    // Qt+OSG only works in single-threaded mode.
+    viewer.setThreadingModel(viewer.SingleThreaded);
+
     // set up the motion model.
     viewer.setCameraManipulator( new EarthManipulator() );
 
diff --git a/src/applications/osgearth_elevation/osgearth_elevation.cpp b/src/applications/osgearth_elevation/osgearth_elevation.cpp
index fcb4144..883d0a9 100644
--- a/src/applications/osgearth_elevation/osgearth_elevation.cpp
+++ b/src/applications/osgearth_elevation/osgearth_elevation.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
@@ -30,23 +30,28 @@
 #include <osgEarth/ElevationQuery>
 #include <osgEarth/StringUtils>
 #include <osgEarth/Terrain>
+#include <osgEarth/VerticalDatum>
 #include <osgEarthUtil/EarthManipulator>
 #include <osgEarthUtil/Controls>
 #include <osgEarthUtil/LatLongFormatter>
 #include <osgEarthUtil/ExampleResources>
+#include <osgEarthAnnotation/PlaceNode>
 #include <iomanip>
 
 using namespace osgEarth;
 using namespace osgEarth::Util;
 using namespace osgEarth::Util::Controls;
+using namespace osgEarth::Annotation;
 
 static MapNode*       s_mapNode     = 0L;
 static LabelControl*  s_posLabel    = 0L;
 static LabelControl*  s_vdaLabel    = 0L;
 static LabelControl*  s_mslLabel    = 0L;
 static LabelControl*  s_haeLabel    = 0L;
+static LabelControl*  s_egm96Label  = 0L;
 static LabelControl*  s_mapLabel    = 0L;
 static LabelControl*  s_resLabel    = 0L;
+static PlaceNode*     s_marker      = 0L;
 
 
 // An event handler that will print out the elevation at the clicked point
@@ -79,7 +84,7 @@ struct QueryElevationHandler : public osgGA::GUIEventHandler
             mapPoint.fromWorld( _terrain->getSRS(), world );
 
             // do an elevation query:
-            double query_resolution = 0; // 1/10th of a degree
+            double query_resolution = 0; // max.
             double out_hamsl        = 0.0;
             double out_resolution   = 0.0;
 
@@ -107,6 +112,17 @@ struct QueryElevationHandler : public osgGA::GUIEventHandler
                 s_haeLabel->setText( Stringify() << mapPointGeodetic.z() );
                 s_resLabel->setText( Stringify() << out_resolution );
 
+                double egm96z = mapPoint.z();
+
+                VerticalDatum::transform(
+                    mapPointGeodetic.getSRS()->getVerticalDatum(),
+                    VerticalDatum::get("egm96"),
+                    mapPointGeodetic.y(),
+                    mapPointGeodetic.x(),
+                    egm96z);
+                
+                s_egm96Label->setText(Stringify() << egm96z);
+
                 yes = true;
             }
 
@@ -114,6 +130,9 @@ struct QueryElevationHandler : public osgGA::GUIEventHandler
             GeoPoint isectPoint;
             isectPoint.fromWorld( _terrain->getSRS()->getGeodeticSRS(), world );
             s_mapLabel->setText( Stringify() << isectPoint.alt() );
+
+            // and move the marker.
+            s_marker->setPosition(mapPoint);
         }
 
         if (!yes)
@@ -122,16 +141,18 @@ struct QueryElevationHandler : public osgGA::GUIEventHandler
             s_mslLabel->setText( "-" );
             s_haeLabel->setText( "-" );
             s_resLabel->setText( "-" );
+            s_egm96Label->setText("-");
         }
     }
 
     bool handle( const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa )
     {
-        if (ea.getEventType() == osgGA::GUIEventAdapter::MOVE &&
-            aa.asView()->getFrameStamp()->getFrameNumber() % 10 == 0)
+        if (ea.getEventType() == ea.DOUBLECLICK &&
+            ea.getButton() == ea.LEFT_MOUSE_BUTTON)
         {
             osgViewer::View* view = static_cast<osgViewer::View*>(aa.asView());
             update( ea.getX(), ea.getY(), view );
+            return true;
         }
 
         return false;
@@ -173,19 +194,31 @@ int main(int argc, char** argv)
 
     // Make the readout:
     Grid* grid = new Grid();
-    grid->setControl(0,0,new LabelControl("Coords (Lat, Long):"));
-    grid->setControl(0,1,new LabelControl("Vertical Datum:"));
-    grid->setControl(0,2,new LabelControl("Height (MSL):"));
-    grid->setControl(0,3,new LabelControl("Height (HAE):"));
-    grid->setControl(0,4,new LabelControl("Isect  (HAE):"));
-    grid->setControl(0,5,new LabelControl("Resolution:"));
-
-    s_posLabel = grid->setControl(1,0,new LabelControl(""));
-    s_vdaLabel = grid->setControl(1,1,new LabelControl(""));
-    s_mslLabel = grid->setControl(1,2,new LabelControl(""));
-    s_haeLabel = grid->setControl(1,3,new LabelControl(""));
-    s_mapLabel = grid->setControl(1,4,new LabelControl(""));
-    s_resLabel = grid->setControl(1,5,new LabelControl(""));
+    grid->setBackColor(osg::Vec4(0,0,0,0.5));
+    int r=0;
+    grid->setControl(0,r++,new LabelControl("Double-click to sample elevation", osg::Vec4(1,1,0,1)));
+    grid->setControl(0,r++,new LabelControl("Coords (Lat, Long):"));
+    grid->setControl(0,r++,new LabelControl("Map vertical datum:"));
+    grid->setControl(0,r++,new LabelControl("Height above geoid:"));
+    grid->setControl(0,r++,new LabelControl("Height above ellipsoid:"));
+    grid->setControl(0,r++,new LabelControl("Scene graph intersection:"));
+    grid->setControl(0,r++,new LabelControl("EGM96 elevation:"));
+    grid->setControl(0,r++,new LabelControl("Query resolution:"));
+
+    r = 1;
+    s_posLabel = grid->setControl(1,r++,new LabelControl(""));
+    s_vdaLabel = grid->setControl(1,r++,new LabelControl(""));
+    s_mslLabel = grid->setControl(1,r++,new LabelControl(""));
+    s_haeLabel = grid->setControl(1,r++,new LabelControl(""));
+    s_mapLabel = grid->setControl(1,r++,new LabelControl(""));
+    s_egm96Label = grid->setControl(1,r++,new LabelControl(""));
+    s_resLabel = grid->setControl(1,r++,new LabelControl(""));
+
+    s_marker = new PlaceNode();
+    s_marker->setMapNode( s_mapNode );
+    s_marker->setIconImage(osgDB::readImageFile("../data/placemark32.png"));
+    s_marker->setDynamic(true);
+    root->addChild( s_marker );
 
     const SpatialReference* mapSRS = s_mapNode->getMapSRS();
     s_vdaLabel->setText( mapSRS->getVerticalDatum() ? 
diff --git a/src/applications/osgearth_ephemeris/CMakeLists.txt b/src/applications/osgearth_ephemeris/CMakeLists.txt
new file mode 100644
index 0000000..94ce82f
--- /dev/null
+++ b/src/applications/osgearth_ephemeris/CMakeLists.txt
@@ -0,0 +1,7 @@
+INCLUDE_DIRECTORIES(${OSG_INCLUDE_DIRS} )
+SET(TARGET_LIBRARIES_VARS OSG_LIBRARY OSGDB_LIBRARY OSGUTIL_LIBRARY OSGVIEWER_LIBRARY OPENTHREADS_LIBRARY)
+
+SET(TARGET_SRC osgearth_ephemeris.cpp )
+
+#### end var setup  ###
+SETUP_APPLICATION(osgearth_ephemeris)
\ No newline at end of file
diff --git a/src/applications/osgearth_ephemeris/osgearth_ephemeris.cpp b/src/applications/osgearth_ephemeris/osgearth_ephemeris.cpp
new file mode 100644
index 0000000..797a98c
--- /dev/null
+++ b/src/applications/osgearth_ephemeris/osgearth_ephemeris.cpp
@@ -0,0 +1,144 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+* Copyright 2016 Pelican Mapping
+* http://osgearth.org
+*
+* osgEarth is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* 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.
+*
+* You should have received a copy of the GNU Lesser General Public License
+* along with this program.  If not, see <http://www.gnu.org/licenses/>
+*/
+
+#include <osgViewer/Viewer>
+#include <osgEarth/Notify>
+#include <osgEarthUtil/EarthManipulator>
+#include <osgEarthUtil/ExampleResources>
+#include <osgEarthUtil/Ephemeris>
+#include <osgEarthUtil/Sky>
+#include <osgEarthUtil/LatLongFormatter>
+#include <osgEarthUtil/Controls>
+#include <osgEarthAnnotation/PlaceNode>
+
+#define LC "[osgearth_ephemeris] "
+
+using namespace osgEarth;
+using namespace osgEarth::Util;
+using namespace osgEarth::Annotation;
+
+namespace ui = osgEarth::Util::Controls;
+
+int
+usage(const char* name)
+{
+    OE_NOTICE 
+        << "\nUsage: " << name << " <file.earth> --sky" << std::endl
+        << MapNodeHelper().usage() << std::endl;
+
+    return 0;
+}
+
+struct App
+{
+    osg::ref_ptr<PlaceNode> sunPos;
+    osg::ref_ptr<PlaceNode> moonPos;
+    SkyNode* sky;
+};
+
+
+int
+main(int argc, char** argv)
+{
+    osg::ArgumentParser arguments(&argc,argv);
+
+    // help?
+    if ( arguments.read("--help") )
+        return usage(argv[0]);
+
+    if ( arguments.find("--sky") < 0 )
+        return usage(argv[0]);
+
+    osgViewer::Viewer viewer(arguments);
+
+    EarthManipulator* em = new EarthManipulator(arguments);
+    em->getSettings()->setMinMaxPitch(-89, 89);
+    viewer.setCameraManipulator( em );
+
+    viewer.getCamera()->setSmallFeatureCullingPixelSize(-1.0f);
+
+    osg::ref_ptr<osg::Image> mark = osgDB::readImageFile("../data/placemark32.png");
+    
+    App app;
+
+    // load an earth file, and support all or our example command-line options
+    // and earth file <external> tags    
+    osg::Node* node = MapNodeHelper().load( arguments, &viewer );
+    if ( node )
+    {
+        osg::Group* root = new osg::Group();
+        root->addChild( node );
+
+        MapNode* mapNode = MapNode::get(node);
+
+        app.sunPos = new PlaceNode(mapNode, GeoPoint(), mark.get(), "Sun");
+        app.sunPos->setDynamic(true);
+        root->addChild( app.sunPos.get() );
+
+        app.moonPos = new PlaceNode(mapNode, GeoPoint(), mark.get(), "Moon");
+        app.moonPos->setDynamic(true);
+
+        root->addChild( app.moonPos.get() );        
+
+
+        app.sky = osgEarth::findTopMostNodeOfType<SkyNode>(node);        
+        const Ephemeris* ephemeris = 0L;
+        if ( app.sky )
+        {
+            ephemeris = app.sky->getEphemeris();
+        }
+
+        LatLongFormatter llf;
+        llf.setOptions( LatLongFormatter::Options(llf.FORMAT_DEGREES_MINUTES_SECONDS) );
+        llf.setPrecision( 4 );
+
+        viewer.setSceneData( root );
+
+        while(!viewer.done())
+        {
+            viewer.frame();
+
+            if ( ephemeris )
+            {
+                const DateTime& dt = app.sky->getDateTime();
+
+                osg::Vec3d sunECEF = ephemeris->getSunPositionECEF(dt);
+                GeoPoint sun;
+                sun.fromWorld(mapNode->getMapSRS(), sunECEF);
+                sun.alt() = 0.0;
+                app.sunPos->setPosition( sun );
+                app.sunPos->setText( "Sun\n" + llf.format(sun) );
+
+                osg::Vec3d moonECEF = ephemeris->getMoonPositionECEF(dt);
+                GeoPoint moon;
+                moon.fromWorld(mapNode->getMapSRS(), moonECEF);
+                moon.alt() = 0.0;
+                app.moonPos->setPosition( moon );
+                app.moonPos->setText( "Moon\n" + llf.format(moon) );
+            }
+        }
+    }
+    else
+    {
+        return usage(argv[0]);
+    }
+}
diff --git a/src/applications/osgearth_featureeditor/osgearth_featureeditor.cpp b/src/applications/osgearth_featureeditor/osgearth_featureeditor.cpp
index 070fcfa..432e994 100644
--- a/src/applications/osgearth_featureeditor/osgearth_featureeditor.cpp
+++ b/src/applications/osgearth_featureeditor/osgearth_featureeditor.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
@@ -30,6 +30,7 @@
 #include <osgEarthUtil/EarthManipulator>
 #include <osgEarthUtil/AutoClipPlaneHandler>
 #include <osgEarth/Utils>
+#include <osgEarthFeatures/GeometryUtils>
 
 #include <osgEarthSymbology/Style>
 
@@ -37,7 +38,6 @@
 #include <osgEarthDrivers/feature_ogr/OGRFeatureOptions>
 #include <osgEarthDrivers/agglite/AGGLiteOptions>
 #include <osgEarthDrivers/model_feature_geom/FeatureGeomModelOptions>
-#include <osgEarthDrivers/model_feature_stencil/FeatureStencilModelOptions>
 
 #include <osgEarthUtil/Controls>
 
@@ -132,7 +132,7 @@ struct EditModeHandler : public ControlEventHandler
         if (!s_editor.valid())
         {            
             Style style = s_featureNode->getStyle();
-            style.getOrCreate<LineSymbol>()->stroke()->stipple() = 0x00FF;            
+            style.getOrCreate<LineSymbol>()->stroke()->stipple() = 0x00FF;                        
             s_featureNode->setStyle( style );            
             s_editor = new FeatureEditor( s_featureNode );
             s_editorsRoot->addChild( s_editor.get() );            
@@ -163,12 +163,13 @@ Style buildStyle( const osg::Vec4 &color, float width )
 
     LineSymbol* ls = style.getOrCreateSymbol<LineSymbol>();
     ls->stroke()->color() = color;
-    ls->stroke()->width() = width;    
-    ls->tessellation() = 10;
-
+    ls->stroke()->width() = width;        
+    
     AltitudeSymbol* as = style.getOrCreate<AltitudeSymbol>();
     as->clamping() = AltitudeSymbol::CLAMP_TO_TERRAIN;
-    as->technique() = AltitudeSymbol::TECHNIQUE_SCENE;
+    as->technique() = AltitudeSymbol::TECHNIQUE_DRAPE;
+
+    style.getOrCreate<PolygonSymbol>()->fill()->color() = Color::Red;
 
     RenderSymbol* rs = style.getOrCreateSymbol<RenderSymbol>();
     rs->depthOffset()->enabled() = true;
@@ -211,8 +212,10 @@ int main(int argc, char** argv)
     // Define a style for the feature data.
     Style style = buildStyle( Color::Yellow, 2.0f );    
 
-    LineString* line = new LineString();    
-    Feature* feature = new Feature(line, s_mapNode->getMapSRS(), Style(), s_fid++);
+    //LineString* line = new LineString();    
+    Geometry* geom = GeometryUtils::geometryFromWKT("POLYGON((191.026667 87.63333,114.75 78,89.5 77.333336,81.833336 75.333336,70.683334 74.5,70.916664 73.666664,68.666664 73.666664,66.291664 71.505,57.65 71.166664,58 73.9,48.616665 73,49.198334 71.43,49.5 70.5,43.266666 68.666664,32.083332 71.5,32.083332 74,35 74,35 81,32 81,32 90,191.026667 87.63333))");
+    OE_NOTICE << "Geometry " << GeometryUtils::geometryToWKT(geom) << std::endl;
+    Feature* feature = new Feature(geom, s_mapNode->getMapSRS(), Style(), s_fid++);
     s_featureNode = new FeatureNode( s_mapNode, feature );    
     s_featureNode->setStyle( style );
     
diff --git a/src/applications/osgearth_featurefilter/osgearth_featurefilter.cpp b/src/applications/osgearth_featurefilter/osgearth_featurefilter.cpp
index f3c5f51..068c035 100644
--- a/src/applications/osgearth_featurefilter/osgearth_featurefilter.cpp
+++ b/src/applications/osgearth_featurefilter/osgearth_featurefilter.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/applications/osgearth_featureinfo/osgearth_featureinfo.cpp b/src/applications/osgearth_featureinfo/osgearth_featureinfo.cpp
index fbeead7..db4fd2f 100644
--- a/src/applications/osgearth_featureinfo/osgearth_featureinfo.cpp
+++ b/src/applications/osgearth_featureinfo/osgearth_featureinfo.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
@@ -165,8 +165,9 @@ int main(int argc, char** argv)
     featureOpt.openWrite() = write;
 
     osg::ref_ptr< FeatureSource > features = FeatureSourceFactory::create( featureOpt );
-    features->initialize();
-    features->getFeatureProfile();
+    Status s = features->open();
+    if (s.isError())
+        return usage(s.message());
 
     //Delete any features if requested
     if (toDelete.size() > 0)
diff --git a/src/applications/osgearth_featurequery/osgearth_featurequery.cpp b/src/applications/osgearth_featurequery/osgearth_featurequery.cpp
index 5f21cd1..cc447f4 100644
--- a/src/applications/osgearth_featurequery/osgearth_featurequery.cpp
+++ b/src/applications/osgearth_featurequery/osgearth_featurequery.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/applications/osgearth_features/osgearth_features.cpp b/src/applications/osgearth_features/osgearth_features.cpp
index 2bb1ed8..a5c10fb 100644
--- a/src/applications/osgearth_features/osgearth_features.cpp
+++ b/src/applications/osgearth_features/osgearth_features.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
@@ -37,7 +37,6 @@
 #include <osgEarthDrivers/feature_ogr/OGRFeatureOptions>
 #include <osgEarthDrivers/agglite/AGGLiteOptions>
 #include <osgEarthDrivers/model_feature_geom/FeatureGeomModelOptions>
-#include <osgEarthDrivers/model_feature_stencil/FeatureStencilModelOptions>
 
 #include <osgDB/WriteFile>
 
@@ -52,7 +51,6 @@ int usage( const std::string& app )
     OE_NOTICE "\n" << app << "\n"
         << "    --rasterize           : draw features as rasterized image tiles \n"
         << "    --overlay             : draw features as projection texture \n"
-        << "    --stencil             : draw features using the stencil buffer \n"
         << "    --mem                 : load features from memory \n"
         << "    --labels              : add feature labels \n"
         << "\n"
@@ -73,12 +71,9 @@ int main(int argc, char** argv)
 
     bool useRaster  = arguments.read("--rasterize");
     bool useOverlay = arguments.read("--overlay");
-    bool useStencil = arguments.read("--stencil");
     bool useMem     = arguments.read("--mem");
     bool useLabels  = arguments.read("--labels");
 
-    if ( useStencil )
-        osg::DisplaySettings::instance()->setMinimumNumStencilBits( 8 );
 
     osgViewer::Viewer viewer(arguments);
 
@@ -130,18 +125,7 @@ int main(int argc, char** argv)
     // Process cmdline args
     MapNodeHelper().parse(mapNode, arguments, &viewer, root, new LabelControl("Features Demo"));
    
-    if (useStencil)
-    {
-        FeatureStencilModelOptions stencilOptions;
-        stencilOptions.featureOptions() = featureOptions;
-        stencilOptions.styles() = new StyleSheet();
-        stencilOptions.styles()->addStyle( style );
-        stencilOptions.enableLighting() = false;
-        stencilOptions.depthTestEnabled() = false;
-        ls->stroke()->width() = 0.1f;
-        map->addModelLayer( new ModelLayer("my features", stencilOptions) );
-    }
-    else if (useRaster)
+    if (useRaster)
     {
         AGGLiteOptions rasterOptions;
         rasterOptions.featureOptions() = featureOptions;
@@ -186,9 +170,7 @@ int main(int argc, char** argv)
         map->addModelLayer( new ModelLayer("labels", geomOptions) );
     }
 
-    if ( !useStencil )
-        viewer.getCamera()->addCullCallback( new osgEarth::Util::AutoClipPlaneCullCallback(mapNode) );
-
+    
     // add some stock OSG handlers:
     viewer.addEventHandler(new osgViewer::StatsHandler());
     viewer.addEventHandler(new osgViewer::WindowSizeHandler());
diff --git a/src/applications/osgearth_fog/osgearth_fog.cpp b/src/applications/osgearth_fog/osgearth_fog.cpp
index 2873dae..d85eeac 100644
--- a/src/applications/osgearth_fog/osgearth_fog.cpp
+++ b/src/applications/osgearth_fog/osgearth_fog.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
@@ -21,95 +21,80 @@
 */
 
 #include <osg/Notify>
+#include <osg/MatrixTransform>
+#include <osgGA/TrackballManipulator>
 #include <osgViewer/Viewer>
-#include <osgEarth/MapNode>
-#include <osgEarthUtil/EarthManipulator>
-#include <osgEarthUtil/ExampleResources>
+#include <osgEarth/Registry>
+#include <osgDB/ReadFile>
+
 #include <osgEarthUtil/Fog>
 #include <osg/Fog>
 
-
-#define LC "[viewer] "
-
 using namespace osgEarth;
 using namespace osgEarth::Util;
 
 int
-usage(const char* name)
-{
-    OE_NOTICE 
-        << "\nUsage: " << name << " file.earth" << std::endl
-        << MapNodeHelper().usage() << std::endl;
-
-    return 0;
-}
-
-int
 main(int argc, char** argv)
 {
     osg::ArgumentParser arguments(&argc,argv);
 
-    // help?
-    if ( arguments.read("--help") )
-        return usage(argv[0]);
-
-    if ( arguments.read("--stencil") )
-        osg::DisplaySettings::instance()->setMinimumNumStencilBits( 8 );
-
     // create a viewer:
     osgViewer::Viewer viewer(arguments);
 
-    //Tell the database pager to not modify the unref settings
-    viewer.getDatabasePager()->setUnrefImageDataAfterApplyPolicy( false, false );
-
-    // install our default manipulator (do this before calling load)
-    viewer.setCameraManipulator( new EarthManipulator() );
-
-    // load an earth file, and support all or our example command-line options
-    // and earth file <external> tags    
-    osg::Node* node = MapNodeHelper().load( arguments, &viewer );    
-    if ( node )
-    {
-        MapNode* mapNode = MapNode::findMapNode( node );
-
-        FogEffect* fogEffect = new FogEffect;
-        fogEffect->attach( node->getOrCreateStateSet() );
-        
-        float maxDensity = 0.000125; 
-        float fogStartHeight = 10000.0f;        
-
-        // Setup a Fog state attribute
-        osg::Vec4 fogColor(0.66f, 0.7f, 0.81f, 1.0f);
-        osg::Fog* fog = new osg::Fog;        
-        fog->setColor( fogColor ); //viewer.getCamera()->getClearColor() );                
-        fog->setDensity( 0 );
-        node->getOrCreateStateSet()->setAttributeAndModes( fog, osg::StateAttribute::ON );                
-
-        viewer.setSceneData( node );
-
-        // configure the near/far so we don't clip things that are up close
-        viewer.getCamera()->setNearFarRatio(0.00002);
-        viewer.getCamera()->setSmallFeatureCullingPixelSize(-1.0f);
-
-        while (!viewer.done())
+    osg::Group* root = new osg::Group();    
+
+    // Setup a Fog state attribute    
+    osg::Fog* fog = new osg::Fog;            
+    fog->setColor( viewer.getCamera()->getClearColor() );                
+    fog->setDensity( 0.02 );    
+    fog->setMode(osg::Fog::LINEAR);
+    fog->setStart(5.0);
+    fog->setEnd(50.0);
+    root->getOrCreateStateSet()->setAttributeAndModes( fog, osg::StateAttribute::ON );                
+    
+    // Attach the FogCallback to keep the Fog uniforms up to date.
+    fog->setUpdateCallback(new FogCallback()); 
+
+    // Add the regular cow.
+    root->addChild(osgDB::readNodeFile("cow.osg"));
+
+    // Add a shader based cow to the right for comparison.
+    osg::MatrixTransform* mt = new osg::MatrixTransform;    
+    osg::Node* cowShader = osgDB::readNodeFile("cow.osg.10,0,0.trans");    
+    osgEarth::Registry::instance()->shaderGenerator().run(cowShader);    
+    
+    // Attach the fog effect so fog will take effect.
+    FogEffect* fogEffect = new FogEffect;
+    fogEffect->attach( cowShader->getOrCreateStateSet() );
+    mt->addChild( cowShader );
+    root->addChild(mt);
+
+    viewer.setCameraManipulator(new osgGA::TrackballManipulator());
+    
+    viewer.setSceneData( root );
+
+    while (!viewer.done())
+    {        
+        // Change fog modes ever 200 frames.
+        if (viewer.getFrameStamp()->getFrameNumber() % 200 == 0)
         {
-            // Get the height above the terrain
-            osg::Vec3d eye, center, up;
-            viewer.getCamera()->getViewMatrixAsLookAt(eye,center, up);
-            GeoPoint map;
-            map.fromWorld( mapNode->getMapSRS(), eye );            
-            
-            // Compute the fog density based on the camera height
-            float ratio = ((fogStartHeight - map.z()) / fogStartHeight);
-            ratio = osg::clampBetween(ratio, 0.0f, 1.0f);
-            float density = ratio * maxDensity;
-            fog->setDensity( density );            
-            viewer.frame();
-        }        
-    }
-    else
-    {
-        return usage(argv[0]);
+            if (fog->getMode() == osg::Fog::LINEAR)
+            {
+                fog->setMode(osg::Fog::EXP);
+                OE_NOTICE << "switching to osg::Fog::EXP" << std::endl;
+            }
+            else if (fog->getMode() == osg::Fog::EXP)
+            {
+                fog->setMode(osg::Fog::EXP2);
+                OE_NOTICE << "switching to osg::Fog::EXP2" << std::endl;
+            }
+            else
+            {
+                fog->setMode(osg::Fog::LINEAR);
+                OE_NOTICE << "switching to osg::Fog::LINEAR" << std::endl;
+            }
+        }
+        viewer.frame();
     }
     return 0;
 }
diff --git a/src/applications/osgearth_graticule/osgearth_graticule.cpp b/src/applications/osgearth_graticule/osgearth_graticule.cpp
index ab31968..45164fd 100644
--- a/src/applications/osgearth_graticule/osgearth_graticule.cpp
+++ b/src/applications/osgearth_graticule/osgearth_graticule.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/applications/osgearth_horizon/CMakeLists.txt b/src/applications/osgearth_horizon/CMakeLists.txt
new file mode 100644
index 0000000..f261a3d
--- /dev/null
+++ b/src/applications/osgearth_horizon/CMakeLists.txt
@@ -0,0 +1,7 @@
+INCLUDE_DIRECTORIES(${OSG_INCLUDE_DIRS} )
+SET(TARGET_LIBRARIES_VARS OSG_LIBRARY OSGDB_LIBRARY OSGUTIL_LIBRARY OSGVIEWER_LIBRARY OPENTHREADS_LIBRARY)
+
+SET(TARGET_SRC osgearth_horizon.cpp )
+
+#### end var setup  ###
+SETUP_APPLICATION(osgearth_horizon)
\ No newline at end of file
diff --git a/src/applications/osgearth_horizon/osgearth_horizon.cpp b/src/applications/osgearth_horizon/osgearth_horizon.cpp
new file mode 100644
index 0000000..60f85bb
--- /dev/null
+++ b/src/applications/osgearth_horizon/osgearth_horizon.cpp
@@ -0,0 +1,172 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+* Copyright 2016 Pelican Mapping
+* http://osgearth.org
+*
+* osgEarth is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* 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.
+*
+* You should have received a copy of the GNU Lesser General Public License
+* along with this program.  If not, see <http://www.gnu.org/licenses/>
+*/
+
+#include <osgViewer/Viewer>
+#include <osgEarth/Notify>
+#include <osgEarth/GeoTransform>
+#include <osgEarth/MapNode>
+#include <osgEarthUtil/EarthManipulator>
+#include <osgEarthUtil/ExampleResources>
+#include <osgEarthAnnotation/AnnotationUtils>
+#include <osgEarth/Horizon>
+#include <osgEarth/Registry>
+#include <osgEarthUtil/ActivityMonitorTool>
+
+#include <osg/Shape>
+#include <osg/ShapeDrawable>
+#include <osg/NodeCallback>
+
+#define LC "[viewer] "
+
+using namespace osgEarth;
+using namespace osgEarth::Util;
+using namespace osgEarth::Annotation;
+
+int
+usage(const char* name)
+{
+    OE_NOTICE 
+        << "\nUsage: " << name << " file.earth" << std::endl
+        << MapNodeHelper().usage() << std::endl;
+
+    return 0;
+}
+
+#define RADIUS  500000.0f
+#define RADIUS2 200000.0f
+
+struct MyComputeBoundCallback : public osg::Node::ComputeBoundingSphereCallback
+{
+    double _radius;
+    MyComputeBoundCallback(float radius) : _radius(radius) { }
+    osg::BoundingSphere computeBound(const osg::Node&) const
+    {
+        return osg::BoundingSphere(osg::Vec3f(0,0,0), _radius);
+    }
+};
+
+struct SetHorizonCallback : public osg::NodeCallback
+{
+    osg::ref_ptr<Horizon> _horizonProto;
+    void operator()(osg::Node* node, osg::NodeVisitor* nv)
+    {
+        osg::ref_ptr<Horizon> horizon = osg::clone(_horizonProto.get(), osg::CopyOp::DEEP_COPY_ALL);
+        horizon->setEye( nv->getViewPoint() );
+        horizon->put( *nv );        
+        traverse(node, nv);
+    }
+};
+
+osg::Node*
+installGeometry1(const SpatialReference* srs)
+{
+    osg::Geode* geode = new osg::Geode();
+    geode->setComputeBoundingSphereCallback( new MyComputeBoundCallback(RADIUS) );
+    geode->addDrawable( new osg::ShapeDrawable( new osg::Sphere(osg::Vec3f(0,0,0), RADIUS) ) );
+    osg::Vec3f center = geode->getBound().center();
+    GeoTransform* xform = new GeoTransform();
+    xform->setPosition( GeoPoint(srs, 0.0, 0.0, 0.0, ALTMODE_ABSOLUTE) );
+    xform->addChild( geode );
+    return xform;
+}
+
+osg::Node*
+installGeometry2(const SpatialReference* srs)
+{
+    osg::Geode* geode = new osg::Geode();
+    geode->setComputeBoundingSphereCallback( new MyComputeBoundCallback(RADIUS2) );
+    geode->addDrawable( new osg::ShapeDrawable( new osg::Sphere(osg::Vec3f(0,0,0), RADIUS2) ) );
+    osg::Vec3f center = geode->getBound().center();
+    GeoTransform* xform = new GeoTransform();
+    xform->setPosition( GeoPoint(srs, 180.0, 0.0, 0.0, ALTMODE_ABSOLUTE) );
+    xform->addChild( geode );
+    return xform;
+}
+
+int
+main(int argc, char** argv)
+{
+    osg::ArgumentParser arguments(&argc,argv);
+
+    // help?
+    if ( arguments.read("--help") )
+        return usage(argv[0]);
+
+    // create a viewer:
+    osgViewer::Viewer viewer(arguments);
+
+    // Tell the database pager to not modify the unref settings
+    viewer.getDatabasePager()->setUnrefImageDataAfterApplyPolicy( false, false );
+
+    // install our default manipulator (do this before calling load)
+    viewer.setCameraManipulator( new EarthManipulator(arguments) );
+
+    // load an earth file, and support all or our example command-line options
+    // and earth file <external> tags    
+    osg::Node* node = MapNodeHelper().load( arguments, &viewer );
+    if ( node )
+    {
+        osg::Group* root = new osg::Group();
+        viewer.setSceneData( root );
+        root->addChild( node );
+
+        const SpatialReference* srs = MapNode::get(node)->getMapSRS();
+        SetHorizonCallback* set = new SetHorizonCallback();
+        set->_horizonProto = new Horizon(srs);
+        root->addCullCallback( set );
+
+        osg::Node* item1 = installGeometry1(srs);
+        root->addChild( item1 );
+
+        osg::Node* item2 = installGeometry2(srs);
+        root->addChild( item2 );
+
+        osg::ref_ptr<Horizon> horizon = new Horizon(srs);
+
+        HorizonCullCallback* callback = new HorizonCullCallback();
+        item2->addCullCallback( callback );
+
+        while (!viewer.done())
+        {
+            viewer.frame();
+
+            osg::Vec3d eye, center, up;
+            viewer.getCamera()->getViewMatrixAsLookAt(eye, center, up);
+            horizon->setEye( eye );
+
+            if ( horizon->isVisible( item1->getBound() ) )
+            {
+                Registry::instance()->endActivity( "large sphere" );
+                Registry::instance()->startActivity( "large sphere", "VISIBLE" );
+            }
+            else
+            {
+                Registry::instance()->endActivity( "large sphere" );
+                Registry::instance()->startActivity( "large sphere", "occluded" );
+            }
+        }
+    }
+    else
+    {
+        return usage(argv[0]);
+    }
+}
diff --git a/src/applications/osgearth_http/CMakeLists.txt b/src/applications/osgearth_http/CMakeLists.txt
new file mode 100644
index 0000000..43d608c
--- /dev/null
+++ b/src/applications/osgearth_http/CMakeLists.txt
@@ -0,0 +1,7 @@
+INCLUDE_DIRECTORIES(${OSG_INCLUDE_DIRS} )
+SET(TARGET_LIBRARIES_VARS OSG_LIBRARY OSGDB_LIBRARY OSGUTIL_LIBRARY OSGVIEWER_LIBRARY OPENTHREADS_LIBRARY)
+
+SET(TARGET_SRC osgearth_http.cpp )
+
+#### end var setup  ###
+SETUP_APPLICATION(osgearth_http)
\ No newline at end of file
diff --git a/src/applications/osgearth_http/osgearth_http.cpp b/src/applications/osgearth_http/osgearth_http.cpp
new file mode 100644
index 0000000..2233d76
--- /dev/null
+++ b/src/applications/osgearth_http/osgearth_http.cpp
@@ -0,0 +1,48 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+* Copyright 2016 Pelican Mapping
+* http://osgearth.org
+*
+* osgEarth is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* 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.
+*
+* You should have received a copy of the GNU Lesser General Public License
+* along with this program.  If not, see <http://www.gnu.org/licenses/>
+*/
+#include <osgEarth/HTTPClient>
+#include <osgEarth/Notify>
+#include <osgEarth/Config>
+
+using namespace osgEarth;
+
+int
+main(int argc, char** argv)
+{
+    HTTPClient http;
+
+    std::string url = "http://readymap.org";
+
+    HTTPResponse response = http.get( url );
+
+    if ( response.isOK() )
+    {
+        std::string content = response.getPartAsString(0);
+        OE_NOTICE << content << std::endl;
+    }
+    else
+    {
+        OE_WARN << "Request failed; error = " << response.getCode() << std::endl;
+    }
+
+    return 0;
+}
diff --git a/src/applications/osgearth_imageoverlay/osgearth_imageoverlay.cpp b/src/applications/osgearth_imageoverlay/osgearth_imageoverlay.cpp
index 6ebee99..8435073 100644
--- a/src/applications/osgearth_imageoverlay/osgearth_imageoverlay.cpp
+++ b/src/applications/osgearth_imageoverlay/osgearth_imageoverlay.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/applications/osgearth_los/osgearth_los.cpp b/src/applications/osgearth_los/osgearth_los.cpp
index 751d007..5373f3d 100644
--- a/src/applications/osgearth_los/osgearth_los.cpp
+++ b/src/applications/osgearth_los/osgearth_los.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/applications/osgearth_manip/osgearth_manip.cpp b/src/applications/osgearth_manip/osgearth_manip.cpp
index 41589df..b1cc2b5 100644
--- a/src/applications/osgearth_manip/osgearth_manip.cpp
+++ b/src/applications/osgearth_manip/osgearth_manip.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
@@ -43,6 +43,7 @@
 #include <osgEarthAnnotation/AnnotationUtils>
 #include <osgEarthAnnotation/LabelNode>
 #include <osgEarthSymbology/Style>
+#include <osgEarth/ScreenSpaceLayout>
 
 using namespace osgEarth::Util;
 using namespace osgEarth::Util::Controls;
@@ -82,7 +83,7 @@ namespace
             "double-click :",      "zoom to point",
             "scroll wheel :",      "zoom in/out",
             "arrows :",            "pan",
-            "1-6 :",               "fly to preset viewpoints",
+            //"1-6 :",               "fly to preset viewpoints",
             "shift-right-mouse :", "locked panning",
             "u :",                 "toggle azimuth lock",
             "o :",                 "toggle perspective/ortho",
@@ -91,9 +92,10 @@ namespace
             "t :",                 "cycle tethermode",
             "b :",                 "break tether",
             "a :",                 "toggle viewpoint arcing",
-            "z :",                 "toggle throwing",
+            "q :",                 "toggle throwing",
             "k :",                 "toggle collision",
-            "L :",                 "toggle log depth buffer"
+            "L :",                 "toggle log depth buffer",
+            ") :",                 "toggle sceen space layout"
         };
 
         Grid* g = new Grid();
@@ -189,6 +191,43 @@ namespace
     };
 
     /**
+     * Toggles screen space layout on the sismulated objects
+     */
+    struct ToggleSSL : public osgGA::GUIEventHandler
+    {
+        ToggleSSL(osg::Group* g, char key) : _group(g), _key(key), _installed(false) { }
+
+        bool handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa)
+        {
+            if (ea.getEventType() == ea.KEYDOWN && ea.getKey() == _key)
+            {
+                if ( !_installed )
+                {
+                    ScreenSpaceLayout::activate(_group->getOrCreateStateSet());
+                }
+                else
+                {
+                    ScreenSpaceLayout::deactivate(_group->getOrCreateStateSet());
+                }
+
+                _installed = !_installed;
+                return true;
+            }
+            return false;
+        }
+
+        void getUsage(osg::ApplicationUsage& usage) const
+        {
+            using namespace std;
+            usage.addKeyboardMouseBinding(string(1, _key), string("Toggle SSL"));
+        }
+
+        char _key;
+        osg::Group* _group;
+        bool _installed;
+    };
+
+    /**
      * Handler to toggle "azimuth locking", which locks the camera's relative Azimuth
      * while panning. For example, it can maintain "north-up" as you pan around. The
      * caveat is that when azimuth is locked you cannot cross the poles.
@@ -493,29 +532,25 @@ namespace
         {
             if ( !model )
             { 
-                _model = AnnotationUtils::createHemisphere(250.0, osg::Vec4(1,.7,.4,1)); //, 90.0f); //AnnotationUtils::createSphere( 250.0, osg::Vec4(1,.7,.4,1) );
+                _model = AnnotationUtils::createHemisphere(250.0, osg::Vec4(1,.7,.4,1));
             }
-            
-            _xform = new GeoTransform();
-            _xform->setTerrain(mapnode->getTerrain());
-
-            _pat = new osg::PositionAttitudeTransform();
-            _pat->addChild( _model );
 
-            _xform->addChild( _pat );
-
-            _cam = new osg::Camera();
-            _cam->setRenderOrder( osg::Camera::NESTED_RENDER, 1 );
-            _cam->addChild( _xform );
+            _geo = new GeoPositionNode(mapnode);
+            _geo->getPositionAttitudeTransform()->addChild(_model);
 
             Style style;
-            style.getOrCreate<TextSymbol>()->size() = 32.0f;
-            style.getOrCreate<TextSymbol>()->declutter() = false;
-            _label = new LabelNode(_mapnode, GeoPoint(), _name, style);
+            TextSymbol* text = style.getOrCreate<TextSymbol>();
+            text->size() = 32.0f;
+            text->declutter() = false;
+            text->pixelOffset()->set(50, 50);
+            
+            _label = new LabelNode(_name, style);
             _label->setDynamic( true );
-            _cam->addChild( _label );
+            _label->setHorizonCulling(false);
 
-            root->addChild( _cam.get() );
+            _geo->getPositionAttitudeTransform()->addChild(_label);
+
+            root->addChild(_geo.get());
         }
 
         bool handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa)
@@ -523,30 +558,29 @@ namespace
             if ( ea.getEventType() == ea.FRAME )
             {
                 double t0 = osg::Timer::instance()->time_s();
-                double t = fmod( t0, 600.0 ) / 600.0;
+                double t = fmod( t0, 6000.0 ) / 6000.0;
                 double lat, lon;
                 GeoMath::interpolate( D2R*_lat0, D2R*_lon0, D2R*_lat1, D2R*_lon1, t, lat, lon );
                 GeoPoint p( SpatialReference::create("wgs84"), R2D*lon, R2D*lat, 2500.0 );
                 double bearing = GeoMath::bearing(D2R*_lat0, D2R*_lon0, lat, lon);
 
                 float a = sin(t0*0.2);
-                bearing += a * 0.5 * osg::PI;
-                float pitch = 0.0; //a * 0.1 * osg::PI;
-
-                _xform->setPosition( p );
+                //bearing += a * 0.5 * osg::PI;
+                float pitch = 0.0;
 
-                _pat->setAttitude(
-                    osg::Quat(pitch, osg::Vec3d(1,0,0)) *
-                    osg::Quat(bearing, osg::Vec3d(0,0,-1)));
+                _geo->setPosition(p);
 
-                _label->setPosition( p );
+                _geo->setLocalRotation(
+                    osg::Quat(pitch, osg::Vec3d(1, 0, 0)) *
+                    osg::Quat(bearing, osg::Vec3d(0, 0, -1)));
             }
             else if ( ea.getEventType() == ea.KEYDOWN )
             {
                 if ( ea.getKey() == _key )
                 {                                
                     Viewpoint vp = _manip->getViewpoint();
-                    vp.setNode( _pat.get() );
+                    //vp.setNode( _pat.get() );
+                    vp.setNode(_model);
                     vp.range() = 25000.0;
                     vp.pitch() = -45.0;
                     _manip->setViewpoint(vp, 2.0);
@@ -560,14 +594,13 @@ namespace
         char                               _key;
         MapNode*                           _mapnode;
         EarthManipulator*                  _manip;
-        osg::ref_ptr<osg::Camera>          _cam;
-        osg::ref_ptr<GeoTransform>         _xform;
-        osg::ref_ptr<osg::PositionAttitudeTransform> _pat;
         double                             _lat0, _lon0, _lat1, _lon1;
         LabelNode*                         _label;
         osg::Node*                         _model;
         float                              _heading;
         float                              _pitch;
+
+        osg::ref_ptr<GeoPositionNode>      _geo;
     };
 }
 
@@ -608,17 +641,20 @@ int main(int argc, char** argv)
     osg::Node* model = 0L;
     std::string modelFile;
     if (arguments.read("--model", modelFile))
-        model = osgDB::readNodeFile(modelFile);
+        model = osgDB::readNodeFile(modelFile + ".osgearth_shadergen");
+
+    osg::Group* sims = new osg::Group();
+    root->addChild( sims );
 
     // Simulator for tethering:
-    Simulator* sim1 = new Simulator(root, manip, mapNode, model, "Thing 1", '8');
+    Simulator* sim1 = new Simulator(sims, manip, mapNode, model, "Thing 1", '8');
     sim1->_lat0 = 55.0;
     sim1->_lon0 = 45.0;
     sim1->_lat1 = -55.0;
     sim1->_lon1 = -45.0;
     viewer.addEventHandler(sim1);
 
-    Simulator* sim2 = new Simulator(root, manip, mapNode, model, "Thing 2", '9');
+    Simulator* sim2 = new Simulator(sims, manip, mapNode, model, "Thing 2", '9');
     sim2->_name = "Thing 2";
     sim2->_lat0 = 54.0;
     sim2->_lon0 = 45.0;
@@ -649,16 +685,17 @@ int main(int argc, char** argv)
 
     manip->setTetherCallback( new TetherCB() );
     
-    viewer.addEventHandler(new FlyToViewpointHandler( manip ));
+    //viewer.addEventHandler(new FlyToViewpointHandler( manip ));
     viewer.addEventHandler(new LockAzimuthHandler('u', manip));
     viewer.addEventHandler(new ToggleArcViewpointTransitionsHandler('a', manip));
-    viewer.addEventHandler(new ToggleThrowingHandler('z', manip));
+    viewer.addEventHandler(new ToggleThrowingHandler('q', manip));
     viewer.addEventHandler(new ToggleCollisionHandler('k', manip));
     viewer.addEventHandler(new ToggleProjMatrix('o', manip));
     viewer.addEventHandler(new BreakTetherHandler('b', manip));
     viewer.addEventHandler(new CycleTetherMode('t', manip));
     viewer.addEventHandler(new SetPositionOffset(manip));
     viewer.addEventHandler(new ToggleLDB('L'));
+    viewer.addEventHandler(new ToggleSSL(sims, ')'));
 
     viewer.getCamera()->setSmallFeatureCullingPixelSize(-1.0f);
 
diff --git a/src/applications/osgearth_map/osgearth_map.cpp b/src/applications/osgearth_map/osgearth_map.cpp
index e9e7c4f..5e7a833 100644
--- a/src/applications/osgearth_map/osgearth_map.cpp
+++ b/src/applications/osgearth_map/osgearth_map.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/applications/osgearth_measure/osgearth_measure.cpp b/src/applications/osgearth_measure/osgearth_measure.cpp
index f0c0051..29d6eff 100644
--- a/src/applications/osgearth_measure/osgearth_measure.cpp
+++ b/src/applications/osgearth_measure/osgearth_measure.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
@@ -144,7 +144,7 @@ main(int argc, char** argv)
     grid->setChildSpacing( 10 );
     grid->setChildVertAlign( Control::ALIGN_CENTER );
     grid->setAbsorbEvents( true );
-    grid->setVertAlign( Control::ALIGN_BOTTOM );    
+    grid->setVertAlign( Control::ALIGN_TOP );   
 
     canvas->addControl( grid );
 
diff --git a/src/applications/osgearth_minimap/osgearth_minimap.cpp b/src/applications/osgearth_minimap/osgearth_minimap.cpp
index a605354..40c5e7d 100644
--- a/src/applications/osgearth_minimap/osgearth_minimap.cpp
+++ b/src/applications/osgearth_minimap/osgearth_minimap.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/applications/osgearth_mrt/osgearth_mrt.cpp b/src/applications/osgearth_mrt/osgearth_mrt.cpp
index 6c15366..2b7bf92 100644
--- a/src/applications/osgearth_mrt/osgearth_mrt.cpp
+++ b/src/applications/osgearth_mrt/osgearth_mrt.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
@@ -55,21 +55,22 @@ createMRTPass(App& app, osg::Node* sceneGraph)
     rtt->attach(osg::Camera::BufferComponent(osg::Camera::COLOR_BUFFER0), app.gcolor);
     rtt->attach(osg::Camera::BufferComponent(osg::Camera::COLOR_BUFFER1), app.gnormal);
     rtt->attach(osg::Camera::BufferComponent(osg::Camera::COLOR_BUFFER2), app.gdepth);
+    rtt->setCullingMode(rtt->getCullingMode() & ~osg::CullSettings::SMALL_FEATURE_CULLING); 
 
     static const char* vertSource =
-        "varying float mrt_depth;\n"
+        "out float mrt_depth;\n"
         "void oe_mrt_vertex(inout vec4 vertexClip)\n"
         "{\n"
         "    mrt_depth = (vertexClip.z/vertexClip.w)*0.5+1.0;\n"
         "}\n";
 
     static const char* fragSource =
-        "varying float mrt_depth;\n"
-        "vec3 oe_global_Normal; \n"
+        "in float mrt_depth;\n"
+        "in vec3 vp_Normal; \n"
         "void oe_mrt_fragment(inout vec4 color)\n"
         "{\n"
         "    gl_FragData[0] = color; \n"
-        "    gl_FragData[1] = vec4((oe_global_Normal+1.0)/2.0,1.0);\n"
+        "    gl_FragData[1] = vec4((vp_Normal+1.0)/2.0,1.0);\n"
         "    gl_FragData[2] = vec4(mrt_depth,mrt_depth,mrt_depth,1.0); \n"
         "}\n";
 
@@ -132,7 +133,7 @@ createFramebufferPass(App& app)
         "}\n";
 
     static const char* fragSource =
-        "#version 120\n"
+        "#version " GLSL_VERSION_STR "\n"
         "#extension GL_ARB_texture_rectangle : enable\n"
         "uniform sampler2DRect gcolor;\n"
         "uniform sampler2DRect gnormal;\n"
diff --git a/src/applications/osgearth_occlusionculling/osgearth_occlusionculling.cpp b/src/applications/osgearth_occlusionculling/osgearth_occlusionculling.cpp
index 39ea18d..d1622e8 100644
--- a/src/applications/osgearth_occlusionculling/osgearth_occlusionculling.cpp
+++ b/src/applications/osgearth_occlusionculling/osgearth_occlusionculling.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
@@ -21,7 +21,7 @@
 */
 
 #include <osgEarth/MapNode>
-#include <osgEarth/Decluttering>
+#include <osgEarth/ScreenSpaceLayout>
 #include <osgEarth/ECEF>
 
 #include <osgEarthUtil/EarthManipulator>
@@ -94,10 +94,6 @@ main(int argc, char** argv)
     // Make a group for 2D items, and activate the decluttering engine. Decluttering
     // will migitate overlap between elements that occupy the same screen real estate.
     osg::Group* labelGroup = new osg::Group();
-    if (declutter)
-    {
-        Decluttering::setEnabled( labelGroup->getOrCreateStateSet(), true );
-    }
     root->addChild( labelGroup );
     
     // set up a style to use for placemarks:
diff --git a/src/applications/osgearth_overlayviewer/osgearth_overlayviewer.cpp b/src/applications/osgearth_overlayviewer/osgearth_overlayviewer.cpp
index d8dd107..2492a19 100644
--- a/src/applications/osgearth_overlayviewer/osgearth_overlayviewer.cpp
+++ b/src/applications/osgearth_overlayviewer/osgearth_overlayviewer.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
@@ -23,6 +23,7 @@
 #include <osg/Notify>
 #include <osg/Depth>
 #include <osg/LineWidth>
+#include <osg/LineStipple>
 #include <osgGA/StateSetManipulator>
 #include <osgGA/AnimationPathManipulator>
 #include <osgViewer/CompositeViewer>
@@ -105,13 +106,27 @@ namespace
                 }
                 else
                 {
-                    dump->getOrCreateStateSet()->setAttributeAndModes(new osg::Depth(
-                        osg::Depth::LEQUAL, 0, 1, false), 1 | osg::StateAttribute::OVERRIDE);
-                    dump->getOrCreateStateSet()->setMode(GL_BLEND,1);
-                    dump->getOrCreateStateSet()->setAttributeAndModes(new osg::LineWidth(1.5f), 1);
+                    // note: the dumped geometry has some state in it (from ConvexPolyhedron::dumpGeometry)
+                    // so we need to override it.
+                    osg::Group* g = new osg::Group();
+                    osg::StateSet* gss = g->getOrCreateStateSet();
+                    gss->setAttributeAndModes(new osg::LineWidth(1.5f), 1);
+                    gss->setRenderBinDetails(90210, "DepthSortedBin");
+
+                    osg::Group* g0 = new osg::Group();
+                    g->addChild( g0 );
+                    osg::StateSet* g0ss = g0->getOrCreateStateSet();
+                    g0ss->setAttributeAndModes(new osg::LineStipple(1, 0x000F), 1);
+                    g0->addChild( dump );
+
+                    osg::Group* g1 = new osg::Group();
+                    g->addChild( g1 );
+                    osg::StateSet* g1ss = g1->getOrCreateStateSet();
+                    g1ss->setMode(GL_DEPTH_TEST, osg::StateAttribute::OVERRIDE | 1);
+                    g1->addChild( dump );
 
                     _parent->removeChildren(1, _parent->getNumChildren()-1);
-                    _parent->addChild( dump );
+                    _parent->addChild( g );
 
                     toggle(_parent, "camera", s_cameraCheck->getValue());
                     //toggle(_parent, "overlay", s_overlayCheck->getValue());
diff --git a/src/applications/osgearth_package/osgearth_package.cpp b/src/applications/osgearth_package/osgearth_package.cpp
index 1f22e66..9cebc51 100644
--- a/src/applications/osgearth_package/osgearth_package.cpp
+++ b/src/applications/osgearth_package/osgearth_package.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -165,8 +165,9 @@ makeTMS( osg::ArgumentParser& args )
         featureOpt.url() = index;        
 
         osg::ref_ptr< FeatureSource > features = FeatureSourceFactory::create( featureOpt );
-        features->initialize();
-        features->getFeatureProfile();
+        Status s = features->open();
+        if (s.isError())
+            return usage(s.message());
 
         osg::ref_ptr< FeatureCursor > cursor = features->createFeatureCursor();
         while (cursor.valid() && cursor->hasMore())
diff --git a/src/applications/osgearth_package_qt/CMakeLists.txt b/src/applications/osgearth_package_qt/CMakeLists.txt
index ba6ceb0..5b9ccb1 100644
--- a/src/applications/osgearth_package_qt/CMakeLists.txt
+++ b/src/applications/osgearth_package_qt/CMakeLists.txt
@@ -18,11 +18,12 @@ IF(Qt5Widgets_FOUND)
     QT5_ADD_RESOURCES( LIB_RC_SRCS ${LIB_QT_RCS} )
     QT5_WRAP_UI( UI_HDRS ${UI_FILES} )
     QT5_WRAP_CPP( UI_SRCS ${UI_HDRS} )
-    IF(Qt5Widgets_VERSION VERSION_LESS 5.2.0)
-        QT5_WRAP_CPP( MOC_SRCS ${MOC_HDRS} OPTIONS "-f" )
-    ELSE()
-        QT5_WRAP_CPP( MOC_SRCS ${MOC_HDRS} )
-    ENDIF()
+    SET(MOC_SRCS)
+    FOREACH( MOC_HDR ${MOC_HDRS} )
+        GET_FILENAME_COMPONENT( MOC_HDR_ABS ${MOC_HDR} ABSOLUTE )
+        QT5_WRAP_CPP( MOC_SRC ${MOC_HDR} OPTIONS "-f${MOC_HDR_ABS}" )
+        LIST( APPEND MOC_SRCS ${MOC_SRC} )
+    ENDFOREACH()
 ELSE()
     INCLUDE( ${QT_USE_FILE} )
     QT4_ADD_RESOURCES( LIB_RC_SRCS ${LIB_QT_RCS} )
diff --git a/src/applications/osgearth_package_qt/ExportDialog b/src/applications/osgearth_package_qt/ExportDialog
index 658fcfc..b9fc2aa 100644
--- a/src/applications/osgearth_package_qt/ExportDialog
+++ b/src/applications/osgearth_package_qt/ExportDialog
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/applications/osgearth_package_qt/ExportDialog.cpp b/src/applications/osgearth_package_qt/ExportDialog.cpp
index b8fc655..57a5ffe 100644
--- a/src/applications/osgearth_package_qt/ExportDialog.cpp
+++ b/src/applications/osgearth_package_qt/ExportDialog.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/applications/osgearth_package_qt/PackageQtMainWindow b/src/applications/osgearth_package_qt/PackageQtMainWindow
index c495f62..15d5629 100644
--- a/src/applications/osgearth_package_qt/PackageQtMainWindow
+++ b/src/applications/osgearth_package_qt/PackageQtMainWindow
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/applications/osgearth_package_qt/SceneController.cpp b/src/applications/osgearth_package_qt/SceneController.cpp
index 42f9640..5f21dfa 100644
--- a/src/applications/osgearth_package_qt/SceneController.cpp
+++ b/src/applications/osgearth_package_qt/SceneController.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/applications/osgearth_package_qt/SceneController.h b/src/applications/osgearth_package_qt/SceneController.h
index a16c31e..164cd19 100644
--- a/src/applications/osgearth_package_qt/SceneController.h
+++ b/src/applications/osgearth_package_qt/SceneController.h
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/applications/osgearth_package_qt/TMSExporter.cpp b/src/applications/osgearth_package_qt/TMSExporter.cpp
index ec11a39..94bd8aa 100644
--- a/src/applications/osgearth_package_qt/TMSExporter.cpp
+++ b/src/applications/osgearth_package_qt/TMSExporter.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/applications/osgearth_package_qt/TMSExporter.h b/src/applications/osgearth_package_qt/TMSExporter.h
index a3b0752..44d81ee 100644
--- a/src/applications/osgearth_package_qt/TMSExporter.h
+++ b/src/applications/osgearth_package_qt/TMSExporter.h
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/applications/osgearth_package_qt/WaitDialog b/src/applications/osgearth_package_qt/WaitDialog
index 37672ee..c317ffb 100644
--- a/src/applications/osgearth_package_qt/WaitDialog
+++ b/src/applications/osgearth_package_qt/WaitDialog
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/applications/osgearth_package_qt/WaitDialog.cpp b/src/applications/osgearth_package_qt/WaitDialog.cpp
index 637d632..5a93242 100644
--- a/src/applications/osgearth_package_qt/WaitDialog.cpp
+++ b/src/applications/osgearth_package_qt/WaitDialog.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/applications/osgearth_package_qt/package_qt.cpp b/src/applications/osgearth_package_qt/package_qt.cpp
index 11ed9b8..ee32fa4 100644
--- a/src/applications/osgearth_package_qt/package_qt.cpp
+++ b/src/applications/osgearth_package_qt/package_qt.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/applications/osgearth_pagingtest/CMakeLists.txt b/src/applications/osgearth_pagingtest/CMakeLists.txt
new file mode 100644
index 0000000..68a5392
--- /dev/null
+++ b/src/applications/osgearth_pagingtest/CMakeLists.txt
@@ -0,0 +1,8 @@
+INCLUDE_DIRECTORIES(${OSG_INCLUDE_DIRS} )
+
+SET(TARGET_LIBRARIES_VARS OSG_LIBRARY OSGDB_LIBRARY OSGUTIL_LIBRARY OSGVIEWER_LIBRARY OPENTHREADS_LIBRARY)
+
+SET(TARGET_SRC osgearth_pagingtest.cpp )
+
+#### end var setup  ###
+SETUP_APPLICATION(osgearth_pagingtest)
\ No newline at end of file
diff --git a/src/applications/osgearth_pagingtest/osgearth_pagingtest.cpp b/src/applications/osgearth_pagingtest/osgearth_pagingtest.cpp
new file mode 100644
index 0000000..1e22070
--- /dev/null
+++ b/src/applications/osgearth_pagingtest/osgearth_pagingtest.cpp
@@ -0,0 +1,334 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+* Copyright 2016 Pelican Mapping
+* http://osgearth.org
+*
+* osgEarth is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* 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.
+*
+* You should have received a copy of the GNU Lesser General Public License
+* along with this program.  If not, see <http://www.gnu.org/licenses/>
+*/
+
+#include <osg/Notify>
+#include <osgGA/StateSetManipulator>
+#include <osgViewer/Viewer>
+#include <osgViewer/ViewerEventHandlers>
+#include <osgEarth/Map>
+#include <osgEarth/MapNode>
+#include <osgEarthUtil/ExampleResources>
+#include <osgEarthUtil/EarthManipulator>
+#include <osgEarthAnnotation/FeatureNode>
+#include <osg/PagedLOD>
+#include <osgDB/FileNameUtils>
+#include <osgDB/ReaderWriter>
+#include <osgEarth/SpatialReference>
+#include <osgEarthUtil/SimplePager>
+
+#include <osg/ShapeDrawable>
+
+#include <osgEarthSymbology/Style>
+#include <osgEarthSymbology/Query>
+#include <osgEarthFeatures/ConvertTypeFilter>
+
+#include <osgEarthDrivers/gdal/GDALOptions>
+#include <osgEarthDrivers/feature_ogr/OGRFeatureOptions>
+#include <osgEarthDrivers/agglite/AGGLiteOptions>
+#include <osgEarthDrivers/model_feature_geom/FeatureGeomModelOptions>
+
+#include <osgEarthDrivers/feature_mapnikvectortiles/MVTFeatureOptions>
+
+#include <osgDB/WriteFile>
+
+using namespace osgEarth;
+using namespace osgEarth::Features;
+using namespace osgEarth::Drivers;
+using namespace osgEarth::Symbology;
+using namespace osgEarth::Annotation;
+using namespace osgEarth::Util;
+
+osg::Vec4
+randomColor()
+{
+    float r = (float)rand() / (float)RAND_MAX;
+    float g = (float)rand() / (float)RAND_MAX;
+    float b = (float)rand() / (float)RAND_MAX;
+    return osg::Vec4(r,g,b,1.0f);
+}
+
+class BoxSimplePager : public SimplePager
+{
+public:
+    BoxSimplePager(const osgEarth::Profile* profile):
+      SimplePager( profile )
+    {
+    }
+
+    virtual osg::Node* createNode(const TileKey& key, ProgressCallback*)
+    {        
+        osg::BoundingSphere bounds = getBounds( key );
+
+        osg::MatrixTransform* mt = new osg::MatrixTransform;
+        mt->setMatrix(osg::Matrixd::translate( bounds.center() ) );
+        osg::Geode* geode = new osg::Geode;
+        osg::ShapeDrawable* sd = new osg::ShapeDrawable( new osg::Box(osg::Vec3f(0,0,0), bounds.radius(), bounds.radius(), bounds.radius()) );
+        sd->setColor( randomColor() );
+        geode->addDrawable( sd );
+        mt->addChild(geode);
+        return mt;
+    }
+};
+
+class FeaturePager : public SimplePager
+{
+public:
+    FeaturePager( FeatureSource* features, const Style& style, MapNode* mapNode):
+      SimplePager( features->getFeatureProfile()->getProfile() ),
+          _features( features ),
+          _style( style ),
+          _mapNode( mapNode )
+      {
+          setMinLevel( features->getFeatureProfile()->getFirstLevel());
+          setMaxLevel( features->getFeatureProfile()->getMaxLevel());
+      }
+      
+      virtual osg::Node* createNode(const TileKey& key, ProgressCallback* progress)
+      {
+          // Get features for this key
+          osgEarth::Symbology::Query query;
+          query.tileKey() = key;          
+
+          osg::ref_ptr< FeatureCursor > cursor = _features->createFeatureCursor( query );
+          if (cursor)
+          {              
+              FeatureList features;
+              cursor->fill( features );
+
+              Style style = _style;
+
+              // See if we have a style for a given lod, otherwise use the default style
+              StyleLODMap::iterator itr = _styleMap.find( key.getLevelOfDetail() );
+              if (itr != _styleMap.end())
+              {
+                  style = itr->second;
+              }
+
+              FeatureNode* featureNode = new FeatureNode(_mapNode, features, style, GeometryCompilerOptions(), _styleSheet.get() );
+              return featureNode;
+          }
+          else
+          {
+              // We got nothing, so return nothing.
+              return 0;
+          }
+      }
+
+
+      // Set a style per lod
+      void setLODStyle(unsigned int lod, const Style& style)
+      {
+          _styleMap[lod] = style;
+      }
+
+      StyleSheet* getStyleSheet() const
+      {
+          return _styleSheet;
+      }
+
+      void setStyleSheet(StyleSheet* styleSheet)
+      {
+          _styleSheet = styleSheet;
+      }
+
+      typedef std::map<unsigned int, Style > StyleLODMap;
+      StyleLODMap _styleMap;
+
+      osg::ref_ptr < FeatureSource > _features;
+      osg::ref_ptr < StyleSheet > _styleSheet;
+      Style _style;
+      osg::ref_ptr< MapNode > _mapNode;
+};
+
+Style getStyle(const osg::Vec4& color, double extrusionHeight)
+{
+    Style style;
+    style.getOrCreate<PolygonSymbol>()->fill()->color() = color;
+    style.getOrCreate<AltitudeSymbol>()->clamping() = AltitudeSymbol::CLAMP_TO_TERRAIN;
+    style.getOrCreate<AltitudeSymbol>()->technique() = AltitudeSymbol::TECHNIQUE_DRAPE;
+    /*
+    if (extrusionHeight > 0)
+    {
+        style.getOrCreate<ExtrusionSymbol>()->height() = extrusionHeight;
+    }
+    */
+    return style;
+}
+
+//
+// NOTE: run this sample from the repo/tests directory.
+//
+int main(int argc, char** argv)
+{
+    osg::ArgumentParser arguments(&argc,argv);
+
+    osgViewer::Viewer viewer(arguments);
+
+    // Tell the database pager to not modify the unref settings
+    viewer.getDatabasePager()->setUnrefImageDataAfterApplyPolicy( false, false );
+
+    // install our default manipulator (do this before calling load)
+    viewer.setCameraManipulator( new EarthManipulator(arguments) );
+
+    osg::Group* root = new osg::Group;
+
+    osg::Node* node = MapNodeHelper().load( arguments, &viewer );
+    root->addChild( node );
+
+    MapNode* mapNode = MapNode::findMapNode( node );
+
+    bool additive = false;
+    if (arguments.read("--additive"))
+    {
+        additive = true;
+    }
+
+    bool spheres = false;
+    if (arguments.read("--spheres"))
+    {
+        spheres = true;
+    }
+
+    bool boxes = false;
+    if (arguments.read("--boxes"))
+    {
+        boxes = true;
+    }
+
+    bool features = false;
+    if (arguments.read("--features"))
+    {
+        features = true;
+    }
+
+    if (!spheres && !boxes && !features)
+    {
+        spheres = true;
+    }
+
+    SimplePager* pager = 0;
+
+    if (spheres)
+    {
+        pager = new SimplePager( mapNode->getMap()->getProfile() );
+        pager->setAdditive( additive );    
+        pager->build();    
+        root->addChild( pager );
+
+    }
+    else if (boxes)
+    {
+        pager = new BoxSimplePager( mapNode->getMap()->getProfile() );
+        pager->setAdditive( additive );    
+        pager->build();    
+        root->addChild( pager );
+
+    }
+    else if (features)
+    {
+        std::vector< std::string > filenames;
+        for(int pos=1;pos<arguments.argc();++pos)
+        {
+            if (!arguments.isOption(pos))
+            {
+                std::string filename = arguments[ pos ];
+                if (osgDB::getFileExtension( filename ) == "mbtiles")
+                {
+                    filenames.push_back( filename );                
+                }
+            }
+        }
+
+        for (unsigned int i = 0; i < filenames.size(); i++)
+        {
+            OE_NOTICE << "Loading " << filenames[i] << std::endl;
+
+
+            MVTFeatureOptions featureOpt;
+            featureOpt.url() = filenames[i];
+
+            osg::ref_ptr< FeatureSource > features = FeatureSourceFactory::create( featureOpt );
+            Status s = features->open();
+            if (s.isError()) {
+                OE_WARN << s.message() << "\n";
+                return -1;
+            }
+
+            FeaturePager* featurePager = new FeaturePager(features, getStyle(randomColor(), 0.0), mapNode);
+
+            // Style 13 is where the full resolution data comes, in so use a fancy textured and extruded style
+            // a style for the building data:
+            Style buildingStyle;
+            buildingStyle.setName( "buildings" );
+
+            // Extrude the shapes into 3D buildings.
+            ExtrusionSymbol* extrusion = buildingStyle.getOrCreate<ExtrusionSymbol>();
+            extrusion->heightExpression() = 50.0;
+            extrusion->flatten() = true;
+            extrusion->wallStyleName() = "building-wall";
+            extrusion->roofStyleName() = "building-roof";
+
+            // a style for the wall textures:
+            Style wallStyle;
+            wallStyle.setName( "building-wall" );
+            SkinSymbol* wallSkin = wallStyle.getOrCreate<SkinSymbol>();
+            wallSkin->library() = "us_resources";
+            wallSkin->addTag( "building" );
+            wallSkin->randomSeed() = 1;
+
+            // a style for the rooftop textures:
+            Style roofStyle;
+            roofStyle.setName( "building-roof" );
+            SkinSymbol* roofSkin = roofStyle.getOrCreate<SkinSymbol>();
+            roofSkin->library() = "us_resources";
+            roofSkin->addTag( "rooftop" );
+            roofSkin->randomSeed() = 1;
+            roofSkin->isTiled() = true;
+
+            // assemble a stylesheet and add our styles to it:
+            StyleSheet* styleSheet = new StyleSheet();
+            styleSheet->addStyle( buildingStyle );
+            styleSheet->addStyle( wallStyle );
+            styleSheet->addStyle( roofStyle );
+
+            // load a resource library that contains the building textures.
+            ResourceLibrary* reslib = new ResourceLibrary( "us_resources", "../data/resources/textures_us/catalog.xml" );
+            styleSheet->addResourceLibrary( reslib );
+
+
+            // Give the FeaturePager it's overall stylesheet.
+            featurePager->setStyleSheet( styleSheet );
+
+            featurePager->setLODStyle(14, buildingStyle );
+
+            featurePager->setAdditive( additive );    
+            featurePager->build();    
+            root->addChild( featurePager );
+
+        }
+    }
+
+    viewer.setSceneData( root );
+       
+    
+    return viewer.run();
+}
diff --git a/src/applications/osgearth_pick/osgearth_pick.cpp b/src/applications/osgearth_pick/osgearth_pick.cpp
index 7251236..6f75fc6 100644
--- a/src/applications/osgearth_pick/osgearth_pick.cpp
+++ b/src/applications/osgearth_pick/osgearth_pick.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
@@ -68,7 +68,7 @@ struct TestIsectPicker : public osgGA::GUIEventHandler
                     ObjectID oid = *oids.begin();
                     osg::ref_ptr<FeatureIndex> fi = index->get<FeatureIndex>(oid);
                     if ( fi.valid() ) {
-                        OE_NOTICE << "Old Picker found OID " << oid << "\n";
+                        OE_NOTICE << "IsectPicker: found OID " << oid << "\n";
                         Feature* f = fi->getFeature(oid);
                         if ( f ) {
                             OE_NOTICE << "...feature ID = " << f->getFID() << "\n";
@@ -76,20 +76,20 @@ struct TestIsectPicker : public osgGA::GUIEventHandler
                     }      
                     osg::ref_ptr<Feature> f = index->get<Feature>(oid);
                     if ( f.valid() ) {
-                        OE_NOTICE << "Old Picker found OID " << oid << "\n";
+                        OE_NOTICE << "IsectPicker: found OID " << oid << "\n";
                         OE_NOTICE << "...feature ID = " << f->getFID() << "\n";
                     }
                     osg::ref_ptr<AnnotationNode> a = index->get<AnnotationNode>(oid);
                     if ( a ) {
-                        OE_NOTICE << "Old Picker found annotation " << a->getName() << "\n";
+                        OE_NOTICE << "IsectPicker: found annotation " << a->getName() << "\n";
                     }
                 }
                 else {
-                    OE_NOTICE << "picked, but no OIDs\n";
+                    OE_NOTICE << "IsectPicker: picked, but no OIDs\n";
                 }
             }
             else {
-                OE_NOTICE << "no intersect\n";
+                OE_NOTICE << "IsectPicker: no intersect\n";
             }
         }
         return false;
@@ -129,8 +129,8 @@ struct MyPickCallback : public RTTPicker::Callback
             // None of the above.. clear.
             else
             {
-                s_fidLabel->setText( Stringify() << "oid = " << id );
-                s_nameLabel->setText( "Name = " );
+                s_fidLabel->setText( Stringify() << "unknown oid = " << id );
+                s_nameLabel->setText( " " );
             }
         }
 
@@ -140,7 +140,7 @@ struct MyPickCallback : public RTTPicker::Callback
     void onMiss()
     {
         s_fidLabel->setText( "No pick." );
-        s_nameLabel->setText( "Name = " );
+        s_nameLabel->setText( " " );
         s_highlightUniform->set( 0u );
     }
 
@@ -156,7 +156,7 @@ struct MyPickCallback : public RTTPicker::Callback
 // Shaders that will highlight the currently "picked" feature.
 
 const char* highlightVert =
-    "#version 130\n"
+    "#version " GLSL_VERSION_STR "\n"
     "uniform uint objectid_to_highlight; \n"
     "uint oe_index_objectid;      // Stage global containing object id \n"
     "flat out int selected; \n"
@@ -166,12 +166,12 @@ const char* highlightVert =
     "} \n";
 
 const char* highlightFrag =
-    "#version 130\n"
+    "#version " GLSL_VERSION_STR "\n"
     "flat in int selected; \n"
     "void highlightFragment(inout vec4 color) \n"
     "{ \n"
     "    if ( selected == 1 ) \n"
-    "        color.rgb = mix(color.rgb, clamp(vec3(0.5,0.5,2.0)*(1.0-color.rgb), 0.0, 1.0), 0.5); \n"
+    "        color.rgb = mix(color.rgb, clamp(vec3(0.5,2.0,2.0)*(1.0-color.rgb), 0.0, 1.0), 0.5); \n"
     "} \n";
 
 void installHighlighter(osg::StateSet* stateSet, int attrLocation)
@@ -196,6 +196,7 @@ void
 setupRTTView(osgViewer::View* view, osg::Texture* rttTex)
 {
     view->setCameraManipulator(0L);
+    view->getCamera()->setName( "osgearth_pick RTT view" );
     view->getCamera()->setViewport(0,0,256,256);
     view->getCamera()->setClearColor(osg::Vec4(1,1,1,1));
     view->getCamera()->setProjectionMatrixAsOrtho2D(-.5,.5,-.5,.5);
@@ -309,6 +310,8 @@ main(int argc, char** argv)
             MapNode::get(node)->getOrCreateStateSet(),
             Registry::objectIndex()->getObjectIDAttribLocation() );
 
+        mainView->getCamera()->setName( "Main view" );
+
         return viewer.run();
     }
     else
diff --git a/src/applications/osgearth_qt/CMakeLists.txt b/src/applications/osgearth_qt/CMakeLists.txt
deleted file mode 100644
index 0e6cf54..0000000
--- a/src/applications/osgearth_qt/CMakeLists.txt
+++ /dev/null
@@ -1,44 +0,0 @@
-INCLUDE_DIRECTORIES(${OSG_INCLUDE_DIRS} ${QT_INCLUDES} )
-
-SET(MOC_HDRS
-    DemoMainWindow
-)
-
-# Qt resource files
-set(LIB_QT_RCS
-    images.qrc
-)
-
-IF(Qt5Widgets_FOUND)
-    QT5_ADD_RESOURCES( LIB_RC_SRCS ${LIB_QT_RCS} )
-    IF(Qt5Widgets_VERSION VERSION_LESS 5.2.0)
-        QT5_WRAP_CPP( MOC_SRCS ${MOC_HDRS} OPTIONS "-f" )
-    ELSE()
-        QT5_WRAP_CPP( MOC_SRCS ${MOC_HDRS} )
-    ENDIF()
-ELSE()
-    INCLUDE( ${QT_USE_FILE} )
-    QT4_ADD_RESOURCES( LIB_RC_SRCS ${LIB_QT_RCS} )
-    QT4_WRAP_CPP( MOC_SRCS ${MOC_HDRS} OPTIONS "-f" )
-ENDIF()
-
-SET(TARGET_H
-    DemoMainWindow
-    ${LIB_QT_RCS}
-)
-
-SET(TARGET_SRC
-    ${MOC_SRCS}
-    ${LIB_RC_SRCS}
-    osgearth_qt.cpp
-)
-
-SET(TARGET_ADDED_LIBRARIES
-    osgEarthQt
-    ${QT_QTCORE_LIBRARY}
-    ${QT_QTGUI_LIBRARY}
-    ${QT_QTOPENGL_LIBRARY}
-)
-
-#### end var setup  ###
-SETUP_APPLICATION(osgearth_qt)
diff --git a/src/applications/osgearth_qt/DemoMainWindow b/src/applications/osgearth_qt/DemoMainWindow
deleted file mode 100644
index bcfafda..0000000
--- a/src/applications/osgearth_qt/DemoMainWindow
+++ /dev/null
@@ -1,201 +0,0 @@
-/* -*-c++-*- */
-/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
-* http://osgearth.org
-*
-* osgEarth is free software; you can redistribute it and/or modify
-* it under the terms of the GNU Lesser General Public License as published by
-* the Free Software Foundation; either version 2 of the License, or
-* (at your option) any later version.
-*
-* 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.
-*
-* You should have received a copy of the GNU Lesser General Public License
-* along with this program.  If not, see <http://www.gnu.org/licenses/>
-*/
-
-#include <osgEarthQt/AnnotationToolbar>
-#include <osgEarthQt/Common>
-#include <osgEarthQt/DataManager>
-#include <osgEarthQt/MapCatalogWidget>
-#include <osgEarthQt/TerrainProfileWidget>
-#include <osgEarthQt/ViewerWidget>
-
-#include <osgEarthAnnotation/AnnotationNode>
-#include <osgEarthAnnotation/PlaceNode>
-#include <osgEarthAnnotation/ScaleDecoration>
-#include <osgEarthDrivers/gdal/GDALOptions>
-#include <osgEarth/GeoData>
-
-#include <QAction>
-#include <QDockWidget>
-#include <QtGui>
-#include <QMainWindow>
-#include <QToolBar>
-
-
-class DemoMainWindow : public QMainWindow
-{
-    Q_OBJECT
-
-public:
-
-    DemoMainWindow(osgEarth::QtGui::DataManager* manager, osgEarth::MapNode* mapNode, osg::Group* annotationRoot)
-        : _manager(manager), _mapNode(mapNode), _annoRoot(annotationRoot), _layerAdded(false), _terrainProfileDock(0L), _viewerWidget(0L)
-    {
-        initUi(); 
-    }
-
-    void setViewerWidget(osgEarth::QtGui::ViewerWidget* viewerWidget)
-    {
-        setCentralWidget(viewerWidget);
-        _viewerWidget = viewerWidget;
-
-        _views.clear();
-        _viewerWidget->getViews( _views );
-
-        _annotationToolbar->setActiveViews(_views);
-    }
-
-    void setTerrainProfileWidget(osgEarth::QtGui::TerrainProfileWidget* widget)
-    {
-        if (!_terrainProfileDock)
-        {
-            _terrainProfileDock = new QDockWidget;
-            _terrainProfileDock->setAllowedAreas(Qt::BottomDockWidgetArea);
-            _terrainProfileDock->setFeatures(QDockWidget::NoDockWidgetFeatures);
-            addDockWidget(Qt::BottomDockWidgetArea, _terrainProfileDock);
-            _terrainProfileDock->setVisible(_terrainProfileAction->isChecked());
-        }
-
-        _terrainProfileDock->setWidget(widget);
-    }
-
-    private slots:
-
-        void addRemoveLayer()
-        {
-            if (!_testLayer.valid())
-            {
-                osgEarth::Drivers::GDALOptions layerOpt;
-                layerOpt.url() = osgEarth::URI("../data/nyc-inset-wgs84.tif");
-                _testLayer = new osgEarth::ImageLayer(osgEarth::ImageLayerOptions("ny_inset", layerOpt));
-            }
-
-            if (!_layerAdded)
-            {
-                _manager->map()->addImageLayer(_testLayer.get());
-                _layerAdded = true;
-                _addRemoveLayerAction->setText(tr("&Remove Layer"));
-                _addRemoveLayerAction->setToolTip("Remove an image layer");
-            }
-            else
-            {
-                _manager->map()->removeImageLayer(_testLayer.get());
-                _layerAdded = false;
-                _addRemoveLayerAction->setText(tr("&Add Layer"));
-                _addRemoveLayerAction->setToolTip("Add an image layer");
-            }
-        }
-
-    void addAnnotation()
-    {
-        osgEarth::Annotation::PlaceNode* annotation = new osgEarth::Annotation::PlaceNode(
-            _mapNode.get(), 
-            osgEarth::GeoPoint(_mapNode->getMapSRS(), -74.0, 40.714),
-            osgDB::readImageFile("../data/placemark32.png"),
-            "New York");
-
-        osgEarth::Annotation::AnnotationData* annoData = new osgEarth::Annotation::AnnotationData();
-        annoData->setName("New York");
-        annoData->setViewpoint(osgEarth::Viewpoint("New Tork", -74, 40.714, 0, 0.0, -90.0, 1e5));
-        annotation->setAnnotationData(annoData);
-
-        annotation->installDecoration("selected", new osgEarth::Annotation::ScaleDecoration(2.0f));
-
-        _manager->addAnnotation(annotation, _annoRoot.get());
-
-        _addAnnotationAction->setDisabled(true);
-    }
-
-    void terrainProfileToggled(bool checked)
-    {
-        if (_terrainProfileDock)
-            _terrainProfileDock->setVisible(checked);
-    }
-
-protected:
-
-    void closeEvent(QCloseEvent *event)
-    {
-        if (_viewerWidget)
-        {
-            _viewerWidget->getViewer()->setDone(true);
-        }
-
-        event->accept();
-    }
-
-private:
-
-    void initUi()
-    {
-        setWindowTitle(tr("osgEarth Qt"));
-        //setWindowIcon(QIcon(":/resources/images/pmicon32.png"));
-
-        createActions();
-        createToolbars();
-    }
-
-	void createActions()
-    {
-        _addRemoveLayerAction = new QAction(tr("&Add Layer"), this);
-        _addRemoveLayerAction->setToolTip(tr("Add an image layer"));
-        connect(_addRemoveLayerAction, SIGNAL(triggered()), this, SLOT(addRemoveLayer()));
-        _addRemoveLayerAction->setDisabled(!_manager.valid());
-
-        _addAnnotationAction = new QAction(/*QIcon(":/images/open.png"),*/ tr("&Add Annotation"), this);
-        _addAnnotationAction->setToolTip(tr("Add an annotation"));
-        connect(_addAnnotationAction, SIGNAL(triggered()), this, SLOT(addAnnotation()));
-        _addAnnotationAction->setDisabled(!_manager.valid() || !_mapNode.valid() || !_annoRoot.valid());
-
-        _terrainProfileAction = new QAction(QIcon(":/images/terrain_profile.png"), tr(""), this);
-        _terrainProfileAction->setToolTip(tr("Terrain Profile Tool"));
-        _terrainProfileAction->setCheckable(true);
-        connect(_terrainProfileAction, SIGNAL(toggled(bool)), this, SLOT(terrainProfileToggled(bool)));
-    }
-
-	void createToolbars()
-    {
-        _fileToolbar = addToolBar(tr("File Toolbar"));
-        _fileToolbar->setObjectName(tr("FILE_TOOLBAR"));
-        _fileToolbar->setIconSize(QSize(24, 24));
-        _fileToolbar->addAction(_addRemoveLayerAction);
-        _fileToolbar->addAction(_addAnnotationAction);
-        _fileToolbar->addSeparator();
-        _fileToolbar->addAction(_terrainProfileAction);
-
-        _annotationToolbar = new osgEarth::QtGui::AnnotationToolbar(_annoRoot, _mapNode, _manager);
-        addToolBar(_annotationToolbar);
-    }
-	
-    osg::ref_ptr<osgEarth::QtGui::DataManager> _manager;
-    osg::ref_ptr<osgEarth::MapNode> _mapNode;
-    osg::ref_ptr<osg::Group> _annoRoot;
-    osg::ref_ptr<osgEarth::ImageLayer> _testLayer;
-    osgEarth::QtGui::ViewerWidget* _viewerWidget;
-    osgEarth::QtGui::AnnotationToolbar* _annotationToolbar;
-    osgEarth::QtGui::ViewVector _views;
-    bool _layerAdded;
-    QAction *_addRemoveLayerAction;
-    QAction *_addAnnotationAction;
-    QAction *_terrainProfileAction;
-    QToolBar *_fileToolbar;
-    QDockWidget *_terrainProfileDock;
-};
diff --git a/src/applications/osgearth_qt/demo_style.qss b/src/applications/osgearth_qt/demo_style.qss
deleted file mode 100644
index 4c7fb02..0000000
--- a/src/applications/osgearth_qt/demo_style.qss
+++ /dev/null
@@ -1,22 +0,0 @@
-#oeFrameContainer, #oeFrameContainer * {
-  background-color: darkgrey;
-  color: white;
-} 
-
-#oeItem, #oeItem * {
-  background-color: lightgrey;
-  color: white;
-}
-
-#oeItemHeader, #oeItemHeader * {
-  background-color: orange;
-  color: white;
-} 
-
-#oeDropTarget, #oeDropTarget * {
-  background: qlineargradient(x1:0 y1:0, x2:0 y2:1, stop:0 orange, stop:1 lightgrey);
-}
-
-QTreeView::item::has-children {
-  background-color: orange;
-}
\ No newline at end of file
diff --git a/src/applications/osgearth_qt/images.qrc b/src/applications/osgearth_qt/images.qrc
deleted file mode 100644
index f46f77f..0000000
--- a/src/applications/osgearth_qt/images.qrc
+++ /dev/null
@@ -1,5 +0,0 @@
-<RCC>
-    <qresource prefix="/">
-        <file>images/terrain_profile.png</file>
-    </qresource>
-</RCC>
diff --git a/src/applications/osgearth_qt/images/terrain_profile.png b/src/applications/osgearth_qt/images/terrain_profile.png
deleted file mode 100644
index a4524c3..0000000
Binary files a/src/applications/osgearth_qt/images/terrain_profile.png and /dev/null differ
diff --git a/src/applications/osgearth_qt/osgearth_qt.cpp b/src/applications/osgearth_qt/osgearth_qt.cpp
deleted file mode 100644
index b0b8d5a..0000000
--- a/src/applications/osgearth_qt/osgearth_qt.cpp
+++ /dev/null
@@ -1,415 +0,0 @@
-/* -*-c++-*- */
-/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
-* http://osgearth.org
-*
-* osgEarth is free software; you can redistribute it and/or modify
-* it under the terms of the GNU Lesser General Public License as published by
-* the Free Software Foundation; either version 2 of the License, or
-* (at your option) any later version.
-*
-* 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.
-*
-* You should have received a copy of the GNU Lesser General Public License
-* along with this program.  If not, see <http://www.gnu.org/licenses/>
-*/
-
-#include <osg/Notify>
-#include <osg/Version>
-#include <osgEarth/ImageUtils>
-#include <osgEarth/MapNode>
-#include <osgEarthAnnotation/AnnotationData>
-#include <osgEarthAnnotation/AnnotationNode>
-#include <osgEarthAnnotation/PlaceNode>
-#include <osgEarthAnnotation/ScaleDecoration>
-#include <osgEarthAnnotation/TrackNode>
-#include <osgEarthQt/ViewerWidget>
-#include <osgEarthQt/LayerManagerWidget>
-#include <osgEarthQt/MapCatalogWidget>
-#include <osgEarthQt/DataManager>
-#include <osgEarthQt/AnnotationListWidget>
-#include <osgEarthQt/LOSControlWidget>
-#include <osgEarthQt/TerrainProfileWidget>
-#include <osgEarthUtil/AnnotationEvents>
-#include <osgEarthUtil/AutoClipPlaneHandler>
-#include <osgEarthUtil/EarthManipulator>
-#include <osgEarthUtil/Sky>
-#include <osgEarthUtil/Ocean>
-
-#include <QAction>
-#include <QDockWidget>
-#include <QMainWindow>
-#include <QToolBar>
-#include <QApplication>
-
-#include "DemoMainWindow"
-
-#ifdef Q_WS_X11
-#include <X11/Xlib.h>
-#endif
-
-
-using namespace osgEarth::Util;
-
-#define TRACK_ICON_URL    "../data/m2525_air.png"
-#define TRACK_ICON_SIZE   24
-#define TRACK_FIELD_NAME  "name"
-
-static osg::ref_ptr<osg::Group> s_annoGroup;
-static osgEarth::Util::SkyNode* s_sky=0L;
-static osgEarth::Util::OceanNode* s_ocean=0L;
-
-//------------------------------------------------------------------
-
-int
-usage( const std::string& msg )
-{
-    OE_NOTICE << msg << std::endl;
-    OE_NOTICE << std::endl;
-    OE_NOTICE << "USAGE: osgearth_qt [options] file.earth" << std::endl;
-    OE_NOTICE << "   --multi n               : use a multi-pane viewer with n initial views" << std::endl;
-    OE_NOTICE << "   --stylesheet filename   : optional Qt stylesheet" << std::endl;
-    OE_NOTICE << "   --run-on-demand         : use the OSG ON_DEMAND frame scheme" << std::endl;
-    OE_NOTICE << "   --tracks                : create some moving track data" << std::endl;
-        
-    return -1;
-}
-
-//------------------------------------------------------------------
-
-/**
- * Event handler that processes events fired from the
- * AnnotationEventCallback
- */
-struct MyAnnoEventHandler : public AnnotationEventHandler
-{
-  MyAnnoEventHandler(osgEarth::QtGui::DataManager* manager) : _manager(manager) {}
-
-  void onClick( AnnotationNode* node, const EventArgs& details )
-  {
-    if (_manager.valid() && details.buttons == osgGA::GUIEventAdapter::LEFT_MOUSE_BUTTON)
-    {
-      if (details.modkeys & osgGA::GUIEventAdapter::MODKEY_CTRL)
-      {
-        if (_manager->isSelected(node))
-          _manager->removeSelectedAnnotation(node);
-        else
-          _manager->addSelectedAnnotation(node);
-      }
-      else
-      {
-        _manager->clearSelectedAnnotations();
-        _manager->addSelectedAnnotation(node);
-      }
-    }   
-  }
-
-
-  osg::ref_ptr<osgEarth::QtGui::DataManager> _manager;
-};
-
-//------------------------------------------------------------------
-// Methods for demo track simulation
-
-struct TrackSim : public osg::Referenced
-{
-  TrackSim(TrackNode* track, const osg::Vec3d& center, float radius, double time, osgEarth::MapNode* mapNode)
-    : _track(track), _mapNode(mapNode), _radius(radius), _time(time)
-  {
-    //Get the center point in geocentric
-    GeoPoint centerMap(mapNode->getMapSRS(), center, ALTMODE_ABSOLUTE);
-    centerMap.toWorld( _center, mapNode->getTerrain() );
-    //mapNode->getMap()->toWorldPoint( centerMap, _center );
-
-    _up = _center;
-    _up.normalize();
-
-    //Get the "side" vector
-    _side = _up ^ osg::Vec3d(0,0,1);
-  }
-
-  void update(double time)
-  {
-    double angle = (time / _time);
-    angle = (angle - (int)angle) * osg::PI * 2.0;
-
-    osg::Quat quat(angle, _up );
-    osg::Vec3d spoke = quat * (_side * _radius);
-    osg::Vec3d end = _center + spoke;
-
-    GeoPoint mapPos;
-    mapPos.fromWorld( _mapNode->getMapSRS(), end );
-    //_mapNode->getMap()->worldPointToMapPoint(end, mapPos);
-
-    _track->setPosition(mapPos);
-  }
-
-  TrackNode* _track;
-  osgEarth::MapNode* _mapNode;
-  osg::Vec3d _center, _side, _up;
-  float _radius;
-  double _time;
-};
-typedef std::vector< osg::ref_ptr<TrackSim> > TrackSimVector;
-
-/** Update operation that runs the simulators. */
-struct TrackSimUpdate : public osg::Operation
-{
-  TrackSimUpdate(TrackSimVector& sims) : osg::Operation("tracksim", true), _sims(sims) { }
-
-  void operator()(osg::Object* obj)
-  {
-    osg::View* view = dynamic_cast<osg::View*>(obj);
-    double t = view->getFrameStamp()->getSimulationTime();
-
-    for(TrackSimVector::iterator i = _sims.begin(); i != _sims.end(); ++i)
-      i->get()->update(t);
-  }
-
-  TrackSimVector& _sims;
-};
-
-TrackNode* createTrack(TrackNodeFieldSchema& schema, osg::Image* image, const std::string& name, MapNode* mapNode, const osg::Vec3d& center, double radius, double time, TrackSimVector& trackSims)
-{
-  TrackNode* track = new TrackNode(mapNode, GeoPoint(mapNode->getMapSRS(),center,ALTMODE_ABSOLUTE), image, schema);
-  track->setFieldValue(TRACK_FIELD_NAME, name);
-
-  AnnotationData* data = new AnnotationData();
-  data->setName(name);
-  data->setViewpoint(osgEarth::Viewpoint(0L, center.x(), center.y(), center.z(), 0.0, -90.0, 1e5));
-  track->setAnnotationData( data );
-
-  trackSims.push_back(new TrackSim(track, center, radius, time, mapNode));
-
-  return track;
-}
-
-void createTrackSchema(TrackNodeFieldSchema& schema)
-{
-    // draw the track name above the icon:
-    TextSymbol* nameSymbol = new TextSymbol();
-    nameSymbol->pixelOffset()->set( 0, 2+TRACK_ICON_SIZE/2 );
-    nameSymbol->alignment() = TextSymbol::ALIGN_CENTER_BOTTOM;
-    nameSymbol->halo()->color() = Color::Black;
-    schema[TRACK_FIELD_NAME] = TrackNodeField(nameSymbol, false);
-}
-
-//------------------------------------------------------------------
-
-int
-main(int argc, char** argv)
-{
-    osg::ArgumentParser arguments(&argc,argv);
-    osg::DisplaySettings::instance()->setMinimumNumStencilBits(8);
-
-    std::string stylesheet;
-    bool styled = arguments.read("--stylesheet", stylesheet);
-
-    bool on_demand = arguments.read("--run-on-demand");
-
-    bool trackData = arguments.read("--tracks");
-
-    bool testUseExistingViewer = arguments.read("--use-existing");
-
-
-    // load the .earth file from the command line.
-    osg::Node* earthNode = osgDB::readNodeFiles( arguments );
-    if (!earthNode)
-        return usage( "Unable to load earth model." );
- 
-
-    osg::Group* root = new osg::Group();
-    root->addChild( earthNode );
-
-    s_annoGroup = new osg::Group();
-    root->addChild( s_annoGroup );
-
-  #ifdef Q_WS_X11
-    XInitThreads();
-  #endif
-
-    QApplication app(argc, argv);
-
-    osg::ref_ptr<osgEarth::MapNode> mapNode = osgEarth::MapNode::findMapNode( earthNode );
-    osg::ref_ptr<osgEarth::QtGui::DataManager> dataManager = new osgEarth::QtGui::DataManager(mapNode.get());
-    DemoMainWindow appWin(dataManager.get(), mapNode.get(), s_annoGroup);
-
-    // install an event handler for picking and selection
-    AnnotationEventCallback* cb = new AnnotationEventCallback();
-    cb->addHandler(new MyAnnoEventHandler(dataManager.get()));
-    s_annoGroup->addEventCallback(cb);
-    
-    osgEarth::QtGui::ViewVector views;
-    osg::ref_ptr<osgViewer::ViewerBase> viewer;
-
-    osgEarth::QtGui::ViewerWidget* viewerWidget = 0L;
-
-    if ( testUseExistingViewer )
-    {
-        // tests: create a pre-existing viewer and install that in the widget.
-        osgViewer::Viewer* v = new osgViewer::Viewer();
-        v->setSceneData(root);
-        v->setThreadingModel(osgViewer::Viewer::DrawThreadPerContext);
-        v->setCameraManipulator(new osgEarth::Util::EarthManipulator());
-        viewerWidget = new osgEarth::QtGui::ViewerWidget(v);
-    }
-
-    else
-    {
-        // tests: implicity creating a viewer.
-        viewerWidget = new osgEarth::QtGui::ViewerWidget( root );
-    }
-
-#if OSG_MIN_VERSION_REQUIRED(3,3,2)
-    // Enable touch events on the viewer
-    viewerWidget->getGraphicsWindow()->setTouchEventsEnabled(true);
-#endif
-
-    //osgEarth::QtGui::ViewerWidget* viewerWidget = new osgEarth::QtGui::ViewerWidget(root);
-    //viewerWidget->setGeometry(50, 50, 1024, 768);
-
-    viewerWidget->getViews( views );
-
-    for(osgEarth::QtGui::ViewVector::iterator i = views.begin(); i != views.end(); ++i )
-    {
-        i->get()->getCamera()->addCullCallback(new osgEarth::Util::AutoClipPlaneCullCallback(mapNode));
-    }
-    appWin.setViewerWidget(viewerWidget);
-
-    if (mapNode.valid())
-    {
-        const Config& externals = mapNode->externalConfig();
-
-        if (mapNode->getMap()->isGeocentric())
-        {
-            // Sky model.
-            Config skyConf = externals.child("sky");
-
-            double hours = skyConf.value("hours", 12.0);
-            s_sky = osgEarth::Util::SkyNode::create(mapNode);
-            s_sky->setDateTime( DateTime(2011, 3, 6, hours) );
-            for(osgEarth::QtGui::ViewVector::iterator i = views.begin(); i != views.end(); ++i )
-                s_sky->attach( *i, 0 );
-            root->addChild(s_sky);
-
-            // Ocean surface.
-            if (externals.hasChild("ocean"))
-            {
-                s_ocean = osgEarth::Util::OceanNode::create(
-                    osgEarth::Util::OceanOptions(externals.child("ocean")),
-                    mapNode.get());
-
-                if (s_ocean)
-                    root->addChild(s_ocean);
-            }
-        }
-    }
-
-    viewer = viewerWidget->getViewer();
-
-    // activate "on demand" rendering if requested:
-    if ( on_demand )
-    {
-        viewer->setRunFrameScheme( osgViewer::ViewerBase::ON_DEMAND );
-        OE_NOTICE << "On-demand rendering activated" << std::endl;
-    }
-
-
-    TrackSimVector trackSims;
-    if ( trackData )
-    {
-        // create demo tracks
-        osg::ref_ptr<osg::Image> srcImage = osgDB::readImageFile(TRACK_ICON_URL);
-        osg::ref_ptr<osg::Image> image;
-        ImageUtils::resizeImage(srcImage.get(), TRACK_ICON_SIZE, TRACK_ICON_SIZE, image);
-
-        TrackNodeFieldSchema schema;
-        createTrackSchema(schema);
-        dataManager->addAnnotation(createTrack(schema, image, "Plane 1", mapNode.get(), osg::Vec3d(-121.463, 46.3548, 1500.71), 10000, 24, trackSims), s_annoGroup);
-        dataManager->addAnnotation(createTrack(schema, image, "Plane 2", mapNode.get(), osg::Vec3d(-121.656, 46.0935, 4133.06), 10000, 8, trackSims), s_annoGroup);
-        dataManager->addAnnotation(createTrack(schema, image, "Plane 3", mapNode.get(), osg::Vec3d(-121.321, 46.2589, 1390.09), 10000, 12, trackSims), s_annoGroup);
-
-        viewer->addUpdateOperation(new TrackSimUpdate(trackSims));
-    }
-
-    if(viewer.valid())
-      viewer->setThreadingModel(osgViewer::ViewerBase::SingleThreaded);
-
-
-    // create catalog widget and add as a docked widget to the main window
-    QDockWidget *catalogDock = new QDockWidget(QWidget::tr("Layers"));
-    catalogDock->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea);
-    osgEarth::QtGui::MapCatalogWidget* layerCatalog = new osgEarth::QtGui::MapCatalogWidget(dataManager.get(), osgEarth::QtGui::MapCatalogWidget::ALL_LAYERS);
-    layerCatalog->setActiveViews(views);
-    layerCatalog->setHideEmptyGroups(true);
-    catalogDock->setWidget(layerCatalog);
-    appWin.addDockWidget(Qt::LeftDockWidgetArea, catalogDock);
-
-
-    // create and dock an annotation list widget
-    QDockWidget *annoDock = new QDockWidget;
-    annoDock->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea);
-    osgEarth::QtGui::AnnotationListWidget* annoList = new osgEarth::QtGui::AnnotationListWidget(dataManager.get());
-    annoList->setActiveViews(views);
-    annoDock->setWidget(annoList);
-    appWin.addDockWidget(Qt::LeftDockWidgetArea, annoDock);
-
-
-    // create a second catalog widget for viewpoints
-    QDockWidget *vpDock = new QDockWidget;
-    vpDock->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea);
-    osgEarth::QtGui::MapCatalogWidget* vpCatalog = new osgEarth::QtGui::MapCatalogWidget(dataManager.get(), osgEarth::QtGui::MapCatalogWidget::VIEWPOINTS);
-    vpCatalog->setActiveViews(views);
-    vpDock->setWidget(vpCatalog);
-    appWin.addDockWidget(Qt::LeftDockWidgetArea, vpDock);
-
-
-    // create layer manager widget and add as a docked widget on the right
-    QDockWidget *layersDock = new QDockWidget(QWidget::tr("Image Layers"));
-    layersDock->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea);
-    osgEarth::QtGui::LayerManagerWidget* layerManager = new osgEarth::QtGui::LayerManagerWidget(dataManager.get(), osgEarth::QtGui::LayerManagerWidget::IMAGE_LAYERS);
-    layerManager->setActiveViews(views);
-    layersDock->setWidget(layerManager);
-    appWin.addDockWidget(Qt::RightDockWidgetArea, layersDock);
-
-
-    // create and dock a LOSControlWidget
-    QDockWidget *losDock = new QDockWidget;
-    losDock->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea);
-    osgEarth::QtGui::LOSControlWidget* losControl = new osgEarth::QtGui::LOSControlWidget(root, mapNode.get(), dataManager.get());
-    losControl->setActiveViews(views);
-    losDock->setWidget(losControl);
-    appWin.addDockWidget(Qt::RightDockWidgetArea, losDock);
-
-    // create terrain profile widget
-    osgEarth::QtGui::TerrainProfileWidget* terrainProfiler = new osgEarth::QtGui::TerrainProfileWidget(root, mapNode.get());
-    terrainProfiler->setActiveViews(views);
-    appWin.setTerrainProfileWidget(terrainProfiler);
-
-
-    // attempt to load .qss stylesheet if one was provided
-    if (styled)
-    {
-      QFile file(QString(stylesheet.c_str()));
-      if (file.exists())
-      {
-        file.open(QFile::ReadOnly);
-        QString qstylesheet = QLatin1String(file.readAll());
-        app.setStyleSheet(qstylesheet);
-        layerManager->setStyleSheet(qstylesheet);
-        annoList->setStyleSheet(qstylesheet);
-        losControl->setStyleSheet(qstylesheet);
-      }
-    }
-
-    appWin.setGeometry(100, 100, 1280, 800);
-    appWin.show();
-
-    return app.exec();
-}
diff --git a/src/applications/osgearth_qt_simple/CMakeLists.txt b/src/applications/osgearth_qt_simple/CMakeLists.txt
index 3b8249e..17f55aa 100644
--- a/src/applications/osgearth_qt_simple/CMakeLists.txt
+++ b/src/applications/osgearth_qt_simple/CMakeLists.txt
@@ -8,11 +8,12 @@ SET(MOC_HDRS
 )
 
 IF(Qt5Widgets_FOUND)
-    IF(Qt5Widgets_VERSION VERSION_LESS 5.2.0)
-        QT5_WRAP_CPP( MOC_SRCS ${MOC_HDRS} OPTIONS "-f" )
-    ELSE()
-        QT5_WRAP_CPP( MOC_SRCS ${MOC_HDRS} )
-    ENDIF()
+    SET(MOC_SRCS)
+    FOREACH( MOC_HDR ${MOC_HDRS} )
+        GET_FILENAME_COMPONENT( MOC_HDR_ABS ${MOC_HDR} ABSOLUTE )
+        QT5_WRAP_CPP( MOC_SRC ${MOC_HDR} OPTIONS "-f${MOC_HDR_ABS}" )
+        LIST( APPEND MOC_SRCS ${MOC_SRC} )
+    ENDFOREACH()
 ENDIF()
 
 IF(QT4_FOUND)
diff --git a/src/applications/osgearth_qt_simple/osgearth_qt_simple.cpp b/src/applications/osgearth_qt_simple/osgearth_qt_simple.cpp
index cb458ba..b49f2bd 100644
--- a/src/applications/osgearth_qt_simple/osgearth_qt_simple.cpp
+++ b/src/applications/osgearth_qt_simple/osgearth_qt_simple.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
@@ -61,6 +61,7 @@ main(int argc, char** argv)
 
 
     osgViewer::Viewer viewer(arguments);
+    viewer.setThreadingModel( viewer.SingleThreaded );
     viewer.setRunFrameScheme( viewer.ON_DEMAND );
     viewer.setCameraManipulator( new EarthManipulator() );
 
diff --git a/src/applications/osgearth_qt_windows/CMakeLists.txt b/src/applications/osgearth_qt_windows/CMakeLists.txt
index b466d36..597f6e6 100644
--- a/src/applications/osgearth_qt_windows/CMakeLists.txt
+++ b/src/applications/osgearth_qt_windows/CMakeLists.txt
@@ -4,11 +4,12 @@ SET(MOC_HDRS
 )
 
 IF(Qt5Widgets_FOUND)
-    IF(Qt5Widgets_VERSION VERSION_LESS 5.2.0)
-        QT5_WRAP_CPP( MOC_SRCS ${MOC_HDRS} OPTIONS "-f" )
-    ELSE()
-        QT5_WRAP_CPP( MOC_SRCS ${MOC_HDRS} )
-    ENDIF()
+    SET(MOC_SRCS)
+    FOREACH( MOC_HDR ${MOC_HDRS} )
+        GET_FILENAME_COMPONENT( MOC_HDR_ABS ${MOC_HDR} ABSOLUTE )
+        QT5_WRAP_CPP( MOC_SRC ${MOC_HDR} OPTIONS "-f${MOC_HDR_ABS}" )
+        LIST( APPEND MOC_SRCS ${MOC_SRC} )
+    ENDFOREACH()
 ELSE()
     INCLUDE( ${QT_USE_FILE} )
     QT4_WRAP_CPP( MOC_SRCS ${MOC_HDRS} OPTIONS "-f" )
diff --git a/src/applications/osgearth_qt_windows/osgearth_qt_windows.cpp b/src/applications/osgearth_qt_windows/osgearth_qt_windows.cpp
index d87b1b1..d4f7a6a 100644
--- a/src/applications/osgearth_qt_windows/osgearth_qt_windows.cpp
+++ b/src/applications/osgearth_qt_windows/osgearth_qt_windows.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
@@ -73,6 +73,8 @@ struct MyMainWindow : public QMainWindow, public ViewController
     MyMainWindow(osg::ArgumentParser& args, osg::Node* scene) 
         : _viewer(args), _scene(scene)
     {
+        _viewer.setThreadingModel(_viewer.SingleThreaded);
+
         // we have to add a starting view, otherwise the CV will automatically
         // mark itself as done :/
         addView();
diff --git a/src/applications/osgearth_seed/osgearth_seed.cpp b/src/applications/osgearth_seed/osgearth_seed.cpp
index e73ec74..5957a6a 100644
--- a/src/applications/osgearth_seed/osgearth_seed.cpp
+++ b/src/applications/osgearth_seed/osgearth_seed.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
@@ -173,17 +173,23 @@ int
         featureOpt.url() = index;        
 
         osg::ref_ptr< FeatureSource > features = FeatureSourceFactory::create( featureOpt );
-        features->initialize();
-        features->getFeatureProfile();
+        Status status = features->open();
 
-        osg::ref_ptr< FeatureCursor > cursor = features->createFeatureCursor();
-        while (cursor.valid() && cursor->hasMore())
+        if (status.isOK())
         {
-            osg::ref_ptr< Feature > feature = cursor->nextFeature();
-            osgEarth::Bounds featureBounds = feature->getGeometry()->getBounds();
-            GeoExtent ext( feature->getSRS(), featureBounds );
-            ext = ext.transform( mapNode->getMapSRS() );
-            bounds.push_back( ext.bounds() );            
+            osg::ref_ptr< FeatureCursor > cursor = features->createFeatureCursor();
+            while (cursor.valid() && cursor->hasMore())
+            {
+                osg::ref_ptr< Feature > feature = cursor->nextFeature();
+                osgEarth::Bounds featureBounds = feature->getGeometry()->getBounds();
+                GeoExtent ext( feature->getSRS(), featureBounds );
+                ext = ext.transform( mapNode->getMapSRS() );
+                bounds.push_back( ext.bounds() );            
+            }
+        }
+        else
+        {
+            OE_WARN << status.message() << "\n";
         }
     }
 
@@ -383,8 +389,7 @@ int
     return 0;
 }
 
-int
-    list( osg::ArgumentParser& args )
+int list( osg::ArgumentParser& args )
 {
     osg::ref_ptr<osg::Node> node = osgDB::readNodeFiles( args );
     if ( !node.valid() )
@@ -413,7 +418,6 @@ int
     for( TerrainLayerVector::iterator i =layers.begin(); i != layers.end(); ++i )
     {
         TerrainLayer* layer = i->get();
-        TerrainLayer::CacheBinMetadata meta;
 
         bool useMFP =
             layer->getProfile() &&
@@ -422,9 +426,10 @@ int
 
         const Profile* cacheProfile = useMFP ? layer->getProfile() : map->getProfile();
 
-        if ( layer->getCacheBinMetadata( cacheProfile, meta ) )
+        TerrainLayer::CacheBinMetadata* meta = layer->getCacheBinMetadata(cacheProfile);
+        if (meta)
         {
-            Config conf = meta.getConfig();
+            Config conf = meta->getConfig();
             std::cout << "Layer \"" << layer->getName() << "\", cache metadata =" << std::endl
                 << conf.toJSON(true) << std::endl;
         }
@@ -447,10 +452,8 @@ struct Entry
 
 
 int
-    purge( osg::ArgumentParser& args )
+purge( osg::ArgumentParser& args )
 {
-    //return usage( "Sorry, but purge is not yet implemented." );
-
     osg::ref_ptr<osg::Node> node = osgDB::readNodeFiles( args );
     if ( !node.valid() )
         return usage( "Failed to read .earth file." );
@@ -480,13 +483,17 @@ int
 
         const Profile* cacheProfile = useMFP ? layer->getProfile() : map->getProfile();
 
-        CacheBin* bin = layer->getCacheBin( cacheProfile );
-        if ( bin )
+        CacheSettings* cacheSettings = layer->getCacheSettings();
+        if (cacheSettings)
         {
-            entries.push_back(Entry());
-            entries.back()._isImage = true;
-            entries.back()._name = i->get()->getName();
-            entries.back()._bin = bin;
+            CacheBin* bin = cacheSettings->getCacheBin();
+            if ( bin )
+            {
+                entries.push_back(Entry());
+                entries.back()._isImage = true;
+                entries.back()._name = i->get()->getName();
+                entries.back()._bin = bin;
+            }
         }
     }
 
@@ -502,14 +509,18 @@ int
             mapNode->getMapNodeOptions().getTerrainOptions().enableMercatorFastPath() == true;
 
         const Profile* cacheProfile = useMFP ? layer->getProfile() : map->getProfile();
-
-        CacheBin* bin = i->get()->getCacheBin( cacheProfile );
-        if ( bin )
+        
+        CacheSettings* cacheSettings = layer->getCacheSettings();
+        if (cacheSettings)
         {
-            entries.push_back(Entry());
-            entries.back()._isImage = false;
-            entries.back()._name = i->get()->getName();
-            entries.back()._bin = bin;
+            CacheBin* bin = cacheSettings->getCacheBin();
+            if (bin)
+            {
+                entries.push_back(Entry());
+                entries.back()._isImage = false;
+                entries.back()._name = i->get()->getName();
+                entries.back()._bin = bin;
+            }
         }
     }
 
diff --git a/src/applications/osgearth_sequencecontrol/osgearth_sequencecontrol.cpp b/src/applications/osgearth_sequencecontrol/osgearth_sequencecontrol.cpp
index acb41be..fde3348 100644
--- a/src/applications/osgearth_sequencecontrol/osgearth_sequencecontrol.cpp
+++ b/src/applications/osgearth_sequencecontrol/osgearth_sequencecontrol.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
@@ -51,7 +51,7 @@ struct UpdateLabel : public osg::Operation
     {
         osgViewer::View* view = dynamic_cast<osgViewer::View*>(obj);
         unsigned index = _sc->getCurrentSequenceFrameIndex(view->getFrameStamp());
-        if ( index >= 0 && index != _prevIndex )
+        if ( index != _prevIndex )
         {
             const std::vector<osgEarth::SequenceFrameInfo>& frames = _sc->getSequenceFrameInfo();
             _label->setText( frames[index].timeIdentifier );
diff --git a/src/applications/osgearth_server/CMakeLists.txt b/src/applications/osgearth_server/CMakeLists.txt
new file mode 100644
index 0000000..6e47fdc
--- /dev/null
+++ b/src/applications/osgearth_server/CMakeLists.txt
@@ -0,0 +1,13 @@
+IF(POCO_FOUND)
+
+INCLUDE_DIRECTORIES(${OSG_INCLUDE_DIRS} ${POCO_INCLUDE_DIR})
+SET(TARGET_LIBRARIES_VARS OSG_LIBRARY OSGDB_LIBRARY OSGUTIL_LIBRARY OSGVIEWER_LIBRARY OPENTHREADS_LIBRARY POCO_FOUNDATION_LIBRARY POCO_NET_LIBRARY POCO_UTIL_LIBRARY)
+
+SET(TARGET_SRC
+    osgearth_server.cpp
+ )
+
+#### end var setup  ###
+SETUP_APPLICATION(osgearth_server)
+
+ENDIF(POCO_FOUND)
\ No newline at end of file
diff --git a/src/applications/osgearth_server/osgearth_server.cpp b/src/applications/osgearth_server/osgearth_server.cpp
new file mode 100644
index 0000000..231ed4f
--- /dev/null
+++ b/src/applications/osgearth_server/osgearth_server.cpp
@@ -0,0 +1,623 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+* Copyright 2015 Pelican Mapping
+* http://osgearth.org
+*
+* osgEarth is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* 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.
+*
+* You should have received a copy of the GNU Lesser General Public License
+* along with this program.  If not, see <http://www.gnu.org/licenses/>
+*/
+
+#include <osgViewer/Viewer>
+#include <osgViewer/ViewerEventHandlers>
+#include <osgEarth/Notify>
+#include <osgEarth/Registry>
+#include <osgEarth/TerrainEngineNode>
+#include <osgEarthUtil/ExampleResources>
+#include <osgDB/ReaderWriter>
+#include <osgDB/ReadFile>
+#include <osgDB/Registry>
+#include <osgDB/FileNameUtils>
+
+#include <Poco/Net/HTTPServer.h>
+#include <Poco/Net/HTTPRequestHandler.h>
+#include <Poco/Net/HTTPRequestHandlerFactory.h>
+#include <Poco/Net/HTTPServerParams.h>
+#include <Poco/Net/HTTPServerRequest.h>
+#include <Poco/Net/HTTPServerResponse.h>
+#include <Poco/Net/HTTPServerParams.h>
+#include <Poco/Net/ServerSocket.h>
+#include <Poco/Timestamp.h>
+#include <Poco/DateTimeFormatter.h>
+#include <Poco/DateTimeFormat.h>
+#include <Poco/Exception.h>
+#include <Poco/ThreadPool.h>
+#include <Poco/Util/ServerApplication.h>
+#include <Poco/Util/Option.h>
+#include <Poco/Util/OptionSet.h>
+#include <Poco/Util/HelpFormatter.h>
+#include <iostream>
+
+using Poco::Net::ServerSocket;
+using Poco::Net::HTTPRequestHandler;
+using Poco::Net::HTTPRequestHandlerFactory;
+using Poco::Net::HTTPServer;
+using Poco::Net::HTTPServerRequest;
+using Poco::Net::HTTPServerResponse;
+using Poco::Net::HTTPServerParams;
+using Poco::Timestamp;
+using Poco::DateTimeFormatter;
+using Poco::DateTimeFormat;
+using Poco::ThreadPool;
+using Poco::Util::ServerApplication;
+using Poco::Util::Application;
+using Poco::Util::Option;
+using Poco::Util::OptionSet;
+using Poco::Util::OptionCallback;
+using Poco::Util::HelpFormatter;
+
+
+#define LC "[viewer] "
+
+using namespace osgEarth;
+using namespace osgEarth::Util;
+using namespace osgViewer;
+
+class WindowCaptureCallback : public osg::Camera::DrawCallback
+{
+    public:
+       
+        enum FramePosition
+        {
+            START_FRAME,
+            END_FRAME
+        };
+    
+        struct ContextData : public osg::Referenced
+        {
+        
+            ContextData(osg::GraphicsContext* gc, GLenum readBuffer):
+                _gc(gc),
+                _readBuffer(readBuffer),
+                _pixelFormat(GL_BGRA),
+                _type(GL_UNSIGNED_BYTE),
+                _width(0),
+                _height(0),
+                _currentImageIndex(0),
+                _currentPboIndex(0)
+            {
+                if (gc->getTraits())
+                {
+                    if (gc->getTraits()->alpha)
+                    {
+                        osg::notify(osg::NOTICE)<<"Select GL_BGRA read back format"<<std::endl;
+                        _pixelFormat = GL_BGRA;
+                    }
+                    else 
+                    {
+                        osg::notify(osg::NOTICE)<<"Select GL_BGR read back format"<<std::endl;
+                        _pixelFormat = GL_BGR; 
+                    }
+                }
+            
+                getSize(gc, _width, _height);
+                
+                std::cout<<"Window size "<<_width<<", "<<_height<<std::endl;
+            
+                // single buffered image
+                _imageBuffer.push_back(new osg::Image);
+
+                _pboBuffer.push_back(0);
+            }
+            
+            void getSize(osg::GraphicsContext* gc, int& width, int& height)
+            {
+                if (gc->getTraits())
+                {
+                    width = gc->getTraits()->width;
+                    height = gc->getTraits()->height;
+                }
+            }
+           
+
+            void read()
+            {
+#if OSG_VERSION_GREATER_OR_EQUAL(3,4,0)
+                osg::GLExtensions* ext = osg::GLExtensions::Get(_gc->getState()->getContextID(),true);
+#else
+                osg::GLBufferObject::Extensions* ext = osg::GLBufferObject::getExtensions(_gc->getState()->getContextID(),true);
+#endif
+
+#if OSG_VERSION_GREATER_OR_EQUAL(3,4,0)
+                if (ext->isPBOSupported && !_pboBuffer.empty())
+#else
+                if (ext->isPBOSupported() && !_pboBuffer.empty())
+#endif
+                {
+                        singlePBO(ext);
+                }
+            }
+           
+#if OSG_VERSION_GREATER_OR_EQUAL(3,4,0)
+            void singlePBO(osg::GLExtensions* ext);
+#else
+            void singlePBO(osg::GLBufferObject::Extensions* ext);
+#endif
+
+       
+            typedef std::vector< osg::ref_ptr<osg::Image> >             ImageBuffer;
+            typedef std::vector< GLuint > PBOBuffer;
+
+       
+            osg::GraphicsContext*   _gc;
+            GLenum                  _readBuffer;
+            
+            GLenum                  _pixelFormat;
+            GLenum                  _type;
+            int                     _width;
+            int                     _height;
+            
+            unsigned int            _currentImageIndex;
+            ImageBuffer             _imageBuffer;
+            
+            unsigned int            _currentPboIndex;
+            PBOBuffer               _pboBuffer;
+
+            osg::ref_ptr< osg::Image > _lastImage;
+        };
+    
+        WindowCaptureCallback(FramePosition position, GLenum readBuffer):
+            _position(position),
+            _readBuffer(readBuffer)
+        {
+        }
+
+        FramePosition getFramePosition() const { return _position; }
+
+        ContextData* createContextData(osg::GraphicsContext* gc) const
+        {
+            return new ContextData(gc, _readBuffer);
+        }
+        
+        ContextData* getContextData(osg::GraphicsContext* gc) const
+        {
+            OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex);
+            osg::ref_ptr<ContextData>& data = _contextDataMap[gc];
+            if (!data) data = createContextData(gc);
+            
+            return data.get();
+        }
+
+        virtual void operator () (osg::RenderInfo& renderInfo) const
+        {
+            glReadBuffer(_readBuffer);
+
+            osg::GraphicsContext* gc = renderInfo.getState()->getGraphicsContext();
+            osg::ref_ptr<ContextData> cd = getContextData(gc);
+            cd->read();
+            const_cast<WindowCaptureCallback*>(this)->_image = cd->_lastImage.get();
+        }
+        
+        typedef std::map<osg::GraphicsContext*, osg::ref_ptr<ContextData> > ContextDataMap;
+
+        FramePosition               _position;
+        GLenum                      _readBuffer;
+        mutable OpenThreads::Mutex  _mutex;
+        mutable ContextDataMap      _contextDataMap;
+        osg::ref_ptr< osg::Image>   _image;
+        
+        
+};
+
+#if OSG_VERSION_GREATER_OR_EQUAL(3,4,0)
+            void WindowCaptureCallback::ContextData::singlePBO(osg::GLExtensions* ext)
+#else
+            void WindowCaptureCallback::ContextData::singlePBO(osg::GLBufferObject::Extensions* ext)
+#endif
+{ 
+    unsigned int nextImageIndex = (_currentImageIndex+1)%_imageBuffer.size();
+
+    int width=0, height=0;
+    getSize(_gc, width, height);
+    if (width!=_width || _height!=height)
+    {
+        std::cout<<"   Window resized "<<width<<", "<<height<<std::endl;
+        _width = width;
+        _height = height;
+    }
+
+    GLuint& pbo = _pboBuffer[0];
+    
+    osg::Image* image = _imageBuffer[_currentImageIndex].get();
+    if (image->s() != _width || 
+        image->t() != _height)
+    {
+        osg::notify(osg::NOTICE)<<"Allocating image "<<std::endl;
+        image->allocateImage(_width, _height, 1, _pixelFormat, _type);
+        
+        if (pbo!=0)
+        {
+            osg::notify(osg::NOTICE)<<"deleting pbo "<<pbo<<std::endl;
+            ext->glDeleteBuffers (1, &pbo);
+            pbo = 0;
+        }
+    }
+    
+    
+    if (pbo==0)
+    {
+        ext->glGenBuffers(1, &pbo);
+        ext->glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, pbo);
+        ext->glBufferData(GL_PIXEL_PACK_BUFFER_ARB, image->getTotalSizeInBytes(), 0, GL_STREAM_READ);
+
+        osg::notify(osg::NOTICE)<<"Generating pbo "<<pbo<<std::endl;
+    }
+    else
+    {
+        ext->glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, pbo);
+    }
+
+#if 1
+    glReadPixels(0, 0, _width, _height, _pixelFormat, _type, 0);
+#endif    
+
+    GLubyte* src = (GLubyte*)ext->glMapBuffer(GL_PIXEL_PACK_BUFFER_ARB,
+                                              GL_READ_ONLY_ARB);
+    if(src)
+    {
+        memcpy(image->data(), src, image->getTotalSizeInBytes());
+        
+        ext->glUnmapBuffer(GL_PIXEL_PACK_BUFFER_ARB);
+    }
+
+    ext->glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, 0);
+
+    _lastImage = new osg::Image(*image);
+
+    _currentImageIndex = nextImageIndex;
+}
+
+
+
+int
+usage(const char* name)
+{
+    OE_NOTICE 
+        << "\nUsage: " << name << " file.earth" << std::endl
+        << MapNodeHelper().usage() << std::endl;
+
+    return 0;
+}
+
+#define LOD_COUNT 26
+
+// Note:  These are taken from Splat.frag.glsl so they line up exactly.
+const float oe_LODRanges[LOD_COUNT] = {
+       100000000.0, // 0
+        75000000.0, // 1
+        50000000.0, // 2
+        10000000.0, // 3
+         7500000.0, // 4
+         5000000.0, // 5
+         2500000.0, // 6
+         1000000.0, // 7
+          500000.0, // 8
+          225000.0, // 9
+          150000.0, // 10
+           80000.0, // 11
+           30000.0, // 12
+           14000.0, // 13
+            4000.0, // 14
+            2500.0, // 15
+            1000.0, // 16
+             500.0, // 17
+             250.0, // 18
+             125.0, // 19
+              50.0, // 20
+              25.0, // 21
+              12.0, // 22
+               6.0, // 23
+               3.0, // 24
+               1.0  // 25
+};
+
+
+
+
+class TileImageServer
+{
+public:
+    TileImageServer(MapNode* mapNode):
+      _mapNode(mapNode),
+      _viewer(0),
+      _windowCaptureCallback(0)
+      {
+          _viewer = new osgViewer::Viewer;
+          _viewer->getCamera()->setSmallFeatureCullingPixelSize(-1.0f);
+          _viewer->setThreadingModel(osgViewer::ViewerBase::SingleThreaded);
+          float half = 256.0/2.0;
+          _viewer->getCamera()->setProjectionMatrixAsOrtho2D(-half, half, -half, half);
+
+          osg::GraphicsContext* gc = createGraphicsContext();
+          if (gc)
+          {
+              OE_NOTICE << "Created graphics context" << std::endl;
+              _viewer->getCamera()->setGraphicsContext( gc );
+              _viewer->getCamera()->setViewport(new osg::Viewport(0,0,256,256));
+          }
+          else
+          {
+              OE_NOTICE << "Failed to create graphics context" << std::endl;
+          }
+
+          _windowCaptureCallback = new WindowCaptureCallback(WindowCaptureCallback::END_FRAME, GL_BACK);
+
+           GLenum buffer = GL_BACK;
+           _viewer->getCamera()->setDrawBuffer(buffer);
+           _viewer->getCamera()->setReadBuffer(buffer);
+           
+
+          _root = new osg::Group;
+
+          _root->addChild(mapNode);
+
+          _viewer->setSceneData( _root.get() );
+
+          _viewer->realize();
+      }
+
+      osg::GraphicsContext* createGraphicsContext()
+      {       
+          osg::ref_ptr<osg::GraphicsContext::Traits> traits = new osg::GraphicsContext::Traits;  
+          traits->x = 0;
+          traits->y = 0;
+          traits->width = 256;
+          traits->height = 256;
+          traits->windowDecoration = false;
+          traits->doubleBuffer = true;
+          traits->sharedContext = 0;
+          traits->pbuffer = true;
+          return osg::GraphicsContext::createGraphicsContext(traits.get());
+      }
+
+      ~TileImageServer()
+      {
+          if (_viewer)
+          {
+              delete _viewer;
+          }
+      }
+
+      osg::Image* getTile(unsigned int z, unsigned int x, unsigned int y)
+      {
+          OpenThreads::ScopedLock< OpenThreads::Mutex> lk(_mutex);
+
+          // Invert the y
+          unsigned cols=0, rows=0;
+          _mapNode->getMap()->getProfile()->getNumTiles( z, cols, rows );
+          y = rows - y - 1;
+
+
+          TileKey key(z, x, y, _mapNode->getMap()->getProfile());
+
+          OE_DEBUG << "key=" << key.str() << std::endl;
+
+          // Set the projection matrix to capture the tile.                    
+          OE_DEBUG << "Key extent " << z << "(" << x << ", " << y << ") = " << key.getExtent().toString() << std::endl;
+          //_viewer->getCamera()->setProjectionMatrixAsOrtho2D(key.getExtent().xMin(), key.getExtent().xMax(), key.getExtent().yMin(), key.getExtent().yMax());
+          unsigned int heightIndex = osg::clampBetween(z, 0u, LOD_COUNT -1u);
+
+          // Multiply by the min_tile_range_factor to get close to what the correct distance would be for this tile.
+          double height = oe_LODRanges[heightIndex] * *_mapNode->getMapNodeOptions().getTerrainOptions().minTileRangeFactor();
+          osg::Vec3d center = key.getExtent().getCentroid();
+          osg::Vec3d eye = center + osg::Vec3d(0,0,height);
+          _viewer->getCamera()->setViewMatrixAsLookAt(eye, center, osg::Vec3d(0,1,0));
+          _viewer->getCamera()->setProjectionMatrixAsOrtho2D(-key.getExtent().width()/2.0,  key.getExtent().width()/2.0,
+                                                             -key.getExtent().height()/2.0, key.getExtent().height()/2.0);
+          _viewer->frame();
+          int numFrames = 0;
+
+          while (_viewer->getDatabasePager()->getRequestsInProgress())
+          {
+              OE_DEBUG << "Waiting on key  " << key.str() << std::endl
+                        << "   file requests = " << _viewer->getDatabasePager()->getFileRequestListSize() << std::endl
+                        << "   data to compile = " << _viewer->getDatabasePager()->getDataToCompileListSize() << std::endl
+                        << "   data to merge = " << _viewer->getDatabasePager()->getDataToMergeListSize() << std::endl;
+              _viewer->frame();
+              numFrames++;
+          }
+
+          OE_DEBUG << "Took " << numFrames << " to load data for " << key.str() << std::endl;
+
+          _viewer->getCamera()->setFinalDrawCallback(_windowCaptureCallback);
+          _viewer->frame();
+          _viewer->frame();
+          _viewer->getCamera()->setFinalDrawCallback( 0 );
+                   
+          if (_windowCaptureCallback->_image)
+          {
+              return new osg::Image(*_windowCaptureCallback->_image);
+          }
+          return 0;
+      }
+
+    osgViewer::Viewer *_viewer;
+    osg::ref_ptr< MapNode > _mapNode;
+    osg::ref_ptr< osg::Group > _root;
+    osg::ref_ptr< WindowCaptureCallback > _windowCaptureCallback;
+    OpenThreads::Mutex _mutex;
+};
+
+
+static TileImageServer* _server;
+
+class TileRequestHandler: public HTTPRequestHandler
+{
+public:
+    TileRequestHandler()
+    {
+    }
+
+    void handleRequest(HTTPServerRequest& request,
+                       HTTPServerResponse& response)
+    {
+        StringTokenizer tok("/");
+        StringVector tized;
+        tok.tokenize(request.getURI(), tized);            
+        if ( tized.size() == 4 )
+        {
+            int z = as<int>(tized[1], 0);
+            int x = as<int>(tized[2], 0);
+            unsigned int y = as<int>(osgDB::getNameLessExtension(tized[3]),0);
+            std::string ext = osgDB::getFileExtension(tized[3]);
+
+            OE_DEBUG << "z=" << z << std::endl;
+            OE_DEBUG << "x=" << x << std::endl;
+            OE_DEBUG << "y=" << y << std::endl;              
+            OE_DEBUG << "ext=" << ext << std::endl;
+
+            response.setChunkedTransferEncoding(true);
+
+            osg::ref_ptr< osg::Image > image = _server->getTile(z, x, y);
+            
+            if (image)
+            {
+                osgDB::ReaderWriter* rw = osgDB::Registry::instance()->getReaderWriterForExtension(ext);
+                if (rw)
+                {
+                    std::string mime = "image/png";
+                    if (ext == "jpeg" || ext == "jpg")
+                    {
+                        mime = "image/jpeg";
+                    }                    
+                    response.setContentType(mime);
+                    std::ostream& ostr = response.send();                 
+                    rw->writeImage(*image.get(), ostr);                    
+                }             
+
+            }
+        }
+ 
+        response.setStatus(Poco::Net::HTTPResponse::HTTP_NOT_FOUND);                
+    }
+
+private:
+    std::string _format;
+};
+
+class TileRequestHandlerFactory : public HTTPRequestHandlerFactory
+{
+    public:
+    TileRequestHandlerFactory()
+    {
+    }
+
+    HTTPRequestHandler* createRequestHandler(
+        const HTTPServerRequest& request)
+    {        
+        StringTokenizer tok("/");
+        StringVector tized;
+        tok.tokenize(request.getURI(), tized);            
+        if ( tized.size() == 4 )
+        {
+            int z = as<int>(tized[1], 0);
+            int x = as<int>(tized[2], 0);
+            unsigned int y = as<int>(osgDB::getNameLessExtension(tized[3]),0);
+            std::string ext = osgDB::getFileExtension(tized[3]);
+
+            OE_DEBUG << "z=" << z << std::endl;
+            OE_DEBUG << "x=" << x << std::endl;
+            OE_DEBUG << "y=" << y << std::endl;              
+            OE_DEBUG << "ext=" << ext << std::endl;
+
+            return new TileRequestHandler();
+        }
+
+        return 0;
+    }
+};
+
+class TileHTTPServer: public Poco::Util::ServerApplication
+{
+public:
+    TileHTTPServer(int port):
+      _port(port)
+    {
+    }
+
+    ~TileHTTPServer()
+    {
+    }
+
+protected:
+    void initialize(Application& self)
+    {
+        loadConfiguration();
+        ServerApplication::initialize(self);
+    }
+
+    void uninitialize()
+    {
+        ServerApplication::uninitialize();
+    }
+
+    int main(const std::vector<std::string>& args)
+    {
+        ServerSocket svs(_port);
+        HTTPServer srv(new TileRequestHandlerFactory(), svs, new HTTPServerParams);
+        srv.start();
+        waitForTerminationRequest();
+        srv.stop();
+        return Application::EXIT_OK;
+    }
+
+private:
+    int _port;
+};
+
+
+
+int
+main(int argc, char** argv)
+{
+    osg::ArgumentParser arguments(&argc,argv);
+
+    // help?
+    if ( arguments.read("--help") )
+        return usage(argv[0]);
+
+    int port = 8000;
+    arguments.read("--port", port);
+    OE_NOTICE << "Listening on port " << port << std::endl;
+
+    // thread-safe initialization of the OSG wrapper manager. Calling this here
+    // prevents the "unsupported wrapper" messages from OSG
+    osgDB::Registry::instance()->getObjectWrapperManager()->findWrapper("osg::Image");
+
+        // load an earth file, and support all or our example command-line options
+    // and earth file <external> tags    
+    osg::ref_ptr< osg::Node> node = osgDB::readNodeFiles( arguments );
+    osg::ref_ptr< MapNode > mapNode = MapNode::findMapNode( node );
+
+    if (mapNode.valid())
+    {
+        OE_NOTICE << "Found map node" << std::endl;
+    }
+
+    _server = new TileImageServer( mapNode.get() );
+
+    TileHTTPServer app(port);
+    return app.run(argc, argv);
+}
diff --git a/src/applications/osgearth_shadercomp/osgearth_shadercomp.cpp b/src/applications/osgearth_shadercomp/osgearth_shadercomp.cpp
index 332cf80..d744fb0 100644
--- a/src/applications/osgearth_shadercomp/osgearth_shadercomp.cpp
+++ b/src/applications/osgearth_shadercomp/osgearth_shadercomp.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
@@ -29,7 +29,9 @@
  * to add functionality.
  */
 #include <osg/Notify>
+#include <osg/CullFace>
 #include <osgDB/ReadFile>
+#include <osgDB/WriteFile>
 #include <osgGA/StateSetManipulator>
 #include <osgViewer/Viewer>
 #include <osgViewer/ViewerEventHandlers>
@@ -56,6 +58,9 @@ int usage( const std::string& msg )
         << "           [--test4]    : Run the memory test \n"
         << "           [--test5]    : Run the Program state set test \n"
         << "           [--test6]    : Run the 2-camera test \n"
+        << "           [--test7]    : Run the geometry shader injection test \n"
+        << "           [--test8]    : Run the VP serialization test \n"
+        << "           [--test9]    : Run the 64-bit shader test \n"
         << std::endl;
 
     return -1;
@@ -69,7 +74,7 @@ osg::Geode* makeGeom( float v )
     osg::Vec3Array* verts = new osg::Vec3Array();
     verts->push_back( osg::Vec3(v-1, 0, 0) );
     verts->push_back( osg::Vec3(v+1, 0, 0) );
-    verts->push_back( osg::Vec3(  0, 0, 2) );
+    verts->push_back( osg::Vec3(  v, 0, 2) );
     geom->setVertexArray( verts );
     geom->setUseDisplayList(false);
     geom->setUseVertexBufferObjects(true);
@@ -375,6 +380,208 @@ namespace TEST_6
 
 //-------------------------------------------------------------------------
 
+namespace TEST_7
+{
+    const char* vert =
+        "#version 120\n"
+        "out float oe_red; \n"
+        "void myVertShader(inout vec4 vertex) { \n"
+        "    oe_red = 1.0; \n"
+        "} \n";
+
+    const char* geom =
+        "#version 330\n"
+        "#pragma vp_name ShaderComp Test 7 Geom Shader (Triangle Viewer)\n"
+
+        "layout(triangles) in; \n"
+        "layout(triangle_strip) out; \n"
+        "layout(max_vertices = 3) out; \n"
+        
+        "void VP_LoadVertex(in int); \n"
+        "void VP_EmitVertex(); \n"
+
+        "uniform float osg_FrameTime; \n"
+
+        "void myGeomShader() \n"
+        "{ \n"
+        "    float strength = 0.25 + sin(osg_FrameTime*2.0)*0.25; \n"
+        "    vec4 cen = (gl_in[0].gl_Position + gl_in[1].gl_Position + gl_in[2].gl_Position)/3.0; \n"        
+        "    for(int i=0; i < 3; ++i ) \n"
+        "    { \n"
+        "        VP_LoadVertex(i); \n"
+        "        vec4 pos = gl_in[i].gl_Position; \n"
+        "        pos += vec4(normalize(cen.xyz-pos.xyz) * distance(cen, pos) * strength, 0.0); \n"
+        "        gl_Position = pos; \n"
+        "        VP_EmitVertex(); \n"
+        "    } \n"
+        "    EndPrimitive(); \n"
+        "} \n";
+
+    const char* frag =
+        "#version 120\n"
+        "in float oe_red; \n"
+        "void myFragShader(inout vec4 color) \n"
+        "{ \n"
+        "    // nop\n"
+        "} \n";
+
+    osg::StateAttribute* createVP()
+    {
+        osgEarth::VirtualProgram* vp = new osgEarth::VirtualProgram();
+        vp->setFunction( "myVertShader", vert, osgEarth::ShaderComp::LOCATION_VERTEX_MODEL );
+        vp->setFunction( "myGeomShader", geom, osgEarth::ShaderComp::LOCATION_GEOMETRY );
+        vp->setFunction( "myFragShader", frag, osgEarth::ShaderComp::LOCATION_FRAGMENT_COLORING );
+        vp->setShaderLogging(true, "test7.glsl");
+        return vp;
+    }
+
+    osg::Group* run( osg::Node* earth )
+    {   
+        osg::Group* g = new osg::Group();
+        g->addChild( earth );
+        g->getOrCreateStateSet()->setAttribute( createVP() );
+        g->getOrCreateStateSet()->setAttributeAndModes(new osg::CullFace(osg::CullFace::BACK));
+        return g;
+    }
+}
+
+//-------------------------------------------------------------------------
+
+// Serialization test.
+namespace TEST_8
+{
+    osg::Node* run()
+    {
+        osg::ref_ptr<osg::Node> node = TEST_5::run();
+        osgDB::writeNodeFile(*node, "out.osgt");
+        OE_NOTICE << "Wrote to out.osgt" << std::endl;
+
+        node = 0L;
+        node = osgDB::readNodeFile("out.osgt");
+        if (!node) {
+            OE_WARN << "Readback failed!!" << std::endl;
+            exit(0);
+        }
+
+        return node.release();
+    }
+}
+
+//-------------------------------------------------------------------------
+
+// Double-precision GLSL Test.
+//
+// This test will turn terrain verts RED if their distance from the earth's
+// center exceeds a certain number. Zoom down to a region where there is a
+// boundary between red verts and normally-colored verts. If you use the 32-bit
+// version of the vertex shader, small movements in the camera will cause 
+// red triangles to jump in and out as the world vertex position overflows
+// the 32-bit values. If you use the 64-bit version, this no longer happens.
+//
+// For the 64-bit version, the OSG built-in uniform osg_ViewMatrixInverse is
+// insufficient (since it's only single-precision). So we have to install a
+// 64-bit version using a cull callback.
+namespace TEST_9
+{
+    osg::Node* run(osg::Node* earthfile)
+    {
+        // 32-bit vertex shader, for reference only. This shader will exceed
+        // the single-precision capacity and cause "jumping verts" at the 
+        // camera make small movements.
+        const char* vs32 =
+            "#version 330 \n"
+            "uniform mat4 osg_ViewMatrixInverse; \n"
+            "flat out float isRed; \n"
+
+            "void vertex(inout vec4 v32) \n"
+            "{ \n"
+            "    vec4 world = osg_ViewMatrixInverse * v32; \n"
+            "    world /= world.w; \n"
+            "    float len = length(world); \n"
+
+            "    const float R = 6371234.5678; \n"
+            
+            "    isRed = 0.0; \n"
+            "    if (len > R) \n"
+            "        isRed = 1.0;"
+
+            "}\n";
+
+        // 64-bit vertex shader. This shader uses a double-precision inverse
+        // view matrix and calculates the altitude all in double precision;
+        // therefore the "jumping verts" problem in the 32-bit version is 
+        // resolved. (Mostly-- you will still see the jumping if you view the 
+        // earth from orbit, because the 32-bit vertex itself is very far from
+        // the camera in view coordinates. If that is an issue, you need to pass
+        // in 64-bit vertex attributes.)
+        const char* vs64 = 
+            "#version 330 \n"
+            "#extension GL_ARB_gpu_shader_fp64 : enable \n"
+            "uniform dmat4 u_ViewMatrixInverse64; \n"            // must use a 64-bit VMI.
+            "flat out float isRed; \n"
+            "flat out double vary64; \n"                         // just to test shadercomp framework
+
+            "void vertex(inout vec4 v32) \n"
+            "{ \n"
+            "    dvec4 v64 = dvec4(v32); \n"                     // upcast to 64-bit, no precision loss
+                                                                 // unless camera is very far away
+
+            "    dvec4 world = u_ViewMatrixInverse64 * v64; \n"  // xform into world coords
+            "    world /= world.w; \n"                           // divide by w
+            "    double len = length(world.xyz); \n"             // get double-precision vector length.
+
+            "    const double R = 6371234.5678; \n"              // arbitrary earth radius threshold
+            
+            "    isRed = (len > R) ? 1.0 : 0.0; \n"
+            "}\n";
+
+        // frag shader: color the terrain red if the incoming varying is non-zero.
+        const char* fs =
+            "#version 330 \n"
+            "#extension GL_ARB_gpu_shader_fp64 : enable \n"
+            "flat in float isRed; \n"
+            "flat in double vary64; \n"
+            "void fragment(inout vec4 color) \n"
+            "{ \n"
+            "    if (isRed > 0.0f) { \n"
+            "        color.r = 1.0; \n"
+            "        color.gb *= 0.5; \n"
+            "    } \n"
+            "} \n";
+
+        // installs a double-precision inverse view matrix for our shader to use.
+        struct VMI64Callback : public osg::NodeCallback
+        {
+            void operator()(osg::Node* node, osg::NodeVisitor* nv)
+            {
+                osgUtil::CullVisitor* cv = dynamic_cast<osgUtil::CullVisitor*>(nv);
+
+                osg::Uniform* u = new osg::Uniform(osg::Uniform::DOUBLE_MAT4, "u_ViewMatrixInverse64");
+                u->set(cv->getCurrentCamera()->getInverseViewMatrix());
+                
+                osg::ref_ptr<osg::StateSet> ss = new osg::StateSet();
+                ss->addUniform(u);
+                cv->pushStateSet(ss.get());
+
+                traverse(node, nv);
+
+                cv->popStateSet();
+            }
+        };
+        earthfile->setCullCallback(new VMI64Callback());
+
+        osg::StateSet* ss = earthfile->getOrCreateStateSet();
+        VirtualProgram* vp = VirtualProgram::getOrCreate(ss);
+        vp->setFunction("vertex",   vs64, ShaderComp::LOCATION_VERTEX_VIEW);
+        vp->setFunction("fragment", fs,   ShaderComp::LOCATION_FRAGMENT_COLORING);
+
+
+        return earthfile;
+    }
+}
+
+//-------------------------------------------------------------------------
+
 int main(int argc, char** argv)
 {
     osg::ArgumentParser arguments(&argc,argv);
@@ -386,7 +593,12 @@ int main(int argc, char** argv)
     bool test4 = arguments.read("--test4");
     bool test5 = arguments.read("--test5");
     bool test6 = arguments.read("--test6");
-    bool ok    = test1 || test2 || test3 || test4 || test5 || test6;
+    bool test7 = arguments.read("--test7");
+    bool test8 = arguments.read("--test8");
+    bool test9 = arguments.read("--test9");
+    bool ok    = test1 || test2 || test3 || test4 || test5 || test6 || test7 || test8||test9;
+
+    bool ui = !arguments.read("--noui");
 
     if ( !ok )
     {
@@ -395,14 +607,17 @@ int main(int argc, char** argv)
 
     osg::Group* root = new osg::Group();
     viewer.setSceneData( root );
-
-    // add a canvas:
-    ControlCanvas* canvas = new ControlCanvas();
-    root->addChild( canvas );
-
-    // and a label:
+    
     LabelControl* label = new LabelControl();
-    canvas->addControl(label);
+    if ( ui )
+    {
+        // add a canvas:
+        ControlCanvas* canvas = new ControlCanvas();
+        root->addChild( canvas );
+
+        // and a label:
+        canvas->addControl(label);
+    }
 
     if ( test1 || test2 || test3 || test4 || test6 )
     {
@@ -415,27 +630,27 @@ int main(int argc, char** argv)
         if ( test1 )
         {
             root->addChild( TEST_1::run(earthNode) );
-            label->setText( "Function injection test: the map appears hazy at high altitude." );
+            if (ui) label->setText( "Function injection test: the map appears hazy at high altitude." );
         }
         else if ( test2 )
         {
             root->addChild( TEST_2::run(earthNode) );
-            label->setText( "Accept callback test: the map turns red when viewport width > 1000" );
+            if (ui) label->setText( "Accept callback test: the map turns red when viewport width > 1000" );
         }
         else if ( test3 )
         {
             root->addChild( TEST_3::run(earthNode) );
-            label->setText( "Shader LOD test: the map turns red between 500K and 1M meters altitude" );
+            if (ui) label->setText( "Shader LOD test: the map turns red between 500K and 1M meters altitude" );
         }
         else if ( test4 )
         {
             root->addChild( TEST_4::run(earthNode) );
-            label->setText("Memory management test; monitor memory for stability");
+            if (ui) label->setText("Memory management test; monitor memory for stability");
         }
         else if ( test6 )
         {
             root->addChild( TEST_6::run(earthNode) );
-            label->setText("State Memory Stack test; top row, both=blue. bottom left=red, bottom right=normal.");
+            if (ui) label->setText("State Memory Stack test; top row, both=blue. bottom left=red, bottom right=normal.");
         }
         
         viewer.setCameraManipulator( new osgEarth::Util::EarthManipulator() );
@@ -444,8 +659,31 @@ int main(int argc, char** argv)
     {
         osgEarth::Registry::instance()->getCapabilities();
         root->addChild( TEST_5::run() );
-        label->setText( "Leakage test: red tri on the left, blue on the right." );
+        if (ui) label->setText( "Leakage test: red tri on the left, blue on the right." );
+    }
+    else if ( test7 )
+    {
+        root->addChild( TEST_7::run( osgDB::readNodeFiles(arguments) ) );
+        if (ui) label->setText("Geometry Shader Injection Test.");
+    }
+    else if (test8)
+    {
+        root->addChild( TEST_8::run() );
+        if (ui) label->setText("Serialization test");
     }
+    else if (test9)
+    {
+        osg::Node* earthNode = osgDB::readNodeFile( "readymap.earth" );
+        if (!earthNode)
+        {
+            return usage( "Unable to load earth model." );
+        }
+        
+        root->addChild(TEST_9::run(earthNode));
+        if (ui) label->setText("DP Shader Test - see code comments");
+        viewer.setCameraManipulator( new osgEarth::Util::EarthManipulator() );
+    }
+
 
     // add some stock OSG handlers:
     viewer.addEventHandler(new osgViewer::StatsHandler());
diff --git a/src/applications/osgearth_shadergen/osgearth_shadergen.cpp b/src/applications/osgearth_shadergen/osgearth_shadergen.cpp
index 6ddf7f6..9960fce 100644
--- a/src/applications/osgearth_shadergen/osgearth_shadergen.cpp
+++ b/src/applications/osgearth_shadergen/osgearth_shadergen.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/applications/osgearth_sharedlayer/osgearth_sharedlayer.cpp b/src/applications/osgearth_sharedlayer/osgearth_sharedlayer.cpp
index 844d6b7..02a6dce 100644
--- a/src/applications/osgearth_sharedlayer/osgearth_sharedlayer.cpp
+++ b/src/applications/osgearth_sharedlayer/osgearth_sharedlayer.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/applications/osgearth_silverlining/CMakeLists.txt b/src/applications/osgearth_silverlining/CMakeLists.txt
new file mode 100644
index 0000000..f8310d4
--- /dev/null
+++ b/src/applications/osgearth_silverlining/CMakeLists.txt
@@ -0,0 +1,9 @@
+INCLUDE_DIRECTORIES(${OSG_INCLUDE_DIRS})
+SET(TARGET_LIBRARIES_VARS OSG_LIBRARY OSGDB_LIBRARY OSGUTIL_LIBRARY OSGVIEWER_LIBRARY OPENTHREADS_LIBRARY)
+
+SET(TARGET_COMMON_LIBRARIES ${TARGET_COMMON_LIBRARIES} osgEarthUtil osgEarthSilverLining)
+
+SET(TARGET_SRC osgearth_silverlining.cpp )
+
+#### end var setup  ###
+SETUP_APPLICATION(osgearth_silverlining)
diff --git a/src/applications/osgearth_silverlining/osgearth_silverlining.cpp b/src/applications/osgearth_silverlining/osgearth_silverlining.cpp
new file mode 100644
index 0000000..f808e00
--- /dev/null
+++ b/src/applications/osgearth_silverlining/osgearth_silverlining.cpp
@@ -0,0 +1,242 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+* Copyright 2008-2014 Pelican Mapping
+* http://osgearth.org
+*
+* osgEarth is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public License
+* along with this program.  If not, see <http://www.gnu.org/licenses/>
+*/
+#include <osgViewer/Viewer>
+#include <osgDB/FileNameUtils>
+#include <osgEarthUtil/ExampleResources>
+#include <osgEarthUtil/EarthManipulator>
+#include <osgEarthUtil/Controls>
+#include <osgEarthSilverLining/SilverLiningNode>
+
+#define LC "[osgearth_silverlining] "
+
+using namespace osgEarth;
+using namespace osgEarth::Util;
+using namespace osgEarth::SilverLining;
+
+namespace ui = osgEarth::Util::Controls;
+
+
+struct Settings
+{
+    SkyNode*         sky;
+    optional<double> visibility;
+    optional<double> rain;
+    optional<double> snow;
+    optional<bool>   lighting;
+    
+    void apply(Atmosphere& atmo)
+    {
+        if (visibility.isSet())
+        {
+            atmo.GetConditions().SetVisibility(visibility.get());
+            visibility.clear();
+        }
+
+        if (rain.isSet())
+        {
+            atmo.GetConditions().SetPrecipitation(CloudLayer::NONE, 0.0);
+            atmo.GetConditions().SetPrecipitation(CloudLayer::RAIN, rain.get());
+            rain.clear();
+        }
+
+        if (snow.isSet())
+        {
+            atmo.GetConditions().SetPrecipitation(CloudLayer::NONE, 0.0);
+            atmo.GetConditions().SetPrecipitation(CloudLayer::DRY_SNOW, snow.get());
+            snow.clear();
+        }
+
+        if (lighting.isSet())
+        {
+            sky->setLighting(lighting.get());
+            lighting.clear();
+        }
+    }
+};
+Settings s_settings;
+
+
+template<typename T> struct Set : public ui::ControlEventHandler
+{
+    optional<T>& _var;
+    Set(optional<T>& var) : _var(var) { }
+    void onValueChanged(ui::Control*, T value) { _var = value; }
+};
+
+struct SetDateTime : public ui::ControlEventHandler
+{
+    void onValueChanged(ui::Control*, double value)
+    {
+        DateTime now;
+        DateTime skyTime(now.year(), now.month(), now.day(), value);
+        s_settings.sky->setDateTime(skyTime);
+    }
+};
+
+
+Container* createUI()
+{
+    VBox* box = new VBox();
+    box->setBackColor(0,0,0,0.5);
+    Grid* grid = box->addControl(new Grid());
+    int r=0;
+    //grid->setControl(0, r, new LabelControl("Visibility"));
+    //HSliderControl* vis = grid->setControl(1, r, new HSliderControl(100.0f, 1000000.0f, 1000000.0f, new Set<double>(s_settings.visibility)));
+    //vis->setHorizFill(true, 175);
+    //grid->setControl(2, r, new LabelControl(vis));
+    //++r;
+    grid->setControl(0, r, new LabelControl("Rain"));
+    grid->setControl(1, r, new HSliderControl(0, 100, 0, new Set<double>(s_settings.rain)));
+    ++r;
+    grid->setControl(0, r, new LabelControl("Snow"));
+    grid->setControl(1, r, new HSliderControl(0, 100, 0, new Set<double>(s_settings.snow)));
+    ++r;
+    grid->setControl(0, r, new LabelControl("Time"));
+    grid->setControl(1, r, new HSliderControl(0, 24, 0, new SetDateTime()));
+    ++r;
+    grid->setControl(0, r, new LabelControl("Lighting"));
+    grid->setControl(1, r, new CheckBoxControl(false, new Set<bool>(s_settings.lighting)));
+    ++r;
+    grid->getControl(1, r-1)->setHorizFill(true,200);
+    return box;
+}
+
+
+struct SLCallback : public osgEarth::SilverLining::Callback
+{
+    void onInitialize(Atmosphere& atmosphere)
+    {
+        CloudLayer cumulus = CloudLayerFactory::Create(CUMULUS_CONGESTUS);
+        cumulus.SetIsInfinite(true);
+        cumulus.SetBaseAltitude(3000);
+        cumulus.SetThickness(50);
+        cumulus.SetBaseLength(100000);
+        cumulus.SetBaseWidth(100000);
+        cumulus.SetDensity(1.0);
+        cumulus.SetLayerPosition(0,0);
+        cumulus.SetFadeTowardEdges(true);
+        cumulus.SetAlpha(0.8);
+        cumulus.SetCloudAnimationEffects(0.1, false, 0, 0);
+        cumulus.SeedClouds(atmosphere);
+        atmosphere.GetConditions().AddCloudLayer(cumulus);
+        
+        atmosphere.EnableLensFlare(true);
+    }
+
+    void onDrawSky(Atmosphere& atmosphere)
+    {
+        //nop
+    }
+
+    void onDrawClouds(Atmosphere& atmosphere)
+    {
+        s_settings.apply(atmosphere);
+    }
+};
+
+int
+usage(const char* name)
+{
+    OE_DEBUG 
+        << "\nUsage: " << name << " file.earth" << std::endl
+        << osgEarth::Util::MapNodeHelper().usage() << std::endl;
+
+    return 0;
+}
+
+int
+main(int argc, char** argv)
+{
+    osg::ArgumentParser arguments(&argc,argv);
+
+    // help?
+    if ( arguments.read("--help") )
+        return usage(argv[0]);
+
+    // create a viewer:
+    osgViewer::Viewer viewer(arguments);
+
+    // Tell the database pager to not modify the unref settings
+    viewer.getDatabasePager()->setUnrefImageDataAfterApplyPolicy( false, false );
+
+    // install our default manipulator (do this before calling load)
+    viewer.setCameraManipulator( new osgEarth::Util::EarthManipulator() );
+
+    // load an earth file, and support all or our example command-line options
+    // and earth file <external> tags    
+    osg::Group* node = MapNodeHelper().load(arguments, &viewer, createUI());
+    if ( node )
+    {
+        // Make sure we don't already have a sky.
+        SkyNode* skyNode = osgEarth::findTopMostNodeOfType<SkyNode>(node);
+        if (skyNode)
+        {
+            OE_WARN << LC << "Earth file already has a Sky. This example requires an "
+                "earth file that does not use a sky already.\n";
+            return -1;
+        }
+
+        viewer.getCamera()->setNearFarRatio(0.00002);
+        viewer.getCamera()->setSmallFeatureCullingPixelSize(-1.0f);
+
+        MapNode* mapNode = MapNode::findMapNode( node );
+
+        // Create SilverLiningNode from SilverLiningOptions
+        osgEarth::SilverLining::SilverLiningOptions slOptions;
+        slOptions.user() = "my_user_name";
+        slOptions.licenseCode() = "my_license_code";
+        slOptions.cloudsMaxAltitude() = 100000;
+
+        const char* ev_sl = ::getenv("SILVERLINING_PATH");
+        if ( ev_sl )
+        {
+            slOptions.resourcePath() = osgDB::concatPaths(
+                std::string(ev_sl),
+                "Resources" );
+        }
+        else
+        {
+            OE_WARN << LC
+                << "No resource path! SilverLining might not initialize properly. "
+                << "Consider setting the SILVERLINING_PATH environment variable."
+                << std::endl;
+        }
+
+        // TODO: uncommenting the callback on the following line results in a crash when SeedClouds is called.
+        s_settings.sky = new SilverLiningNode(
+            mapNode->getMapSRS(),
+            slOptions,
+            new SLCallback() );
+
+        // insert the new sky above the map node.
+        osgEarth::insertParent(s_settings.sky, mapNode);
+        
+        // use the topmost node.
+        viewer.setSceneData(osgEarth::findTopOfGraph(node));
+
+        // connects the sky's light to the viewer.
+        s_settings.sky->attach(&viewer);
+
+        return viewer.run();
+    }
+    else
+    {
+        return usage(argv[0]);
+    }
+}
diff --git a/src/applications/osgearth_skyview/CMakeLists.txt b/src/applications/osgearth_skyview/CMakeLists.txt
new file mode 100644
index 0000000..a45fa26
--- /dev/null
+++ b/src/applications/osgearth_skyview/CMakeLists.txt
@@ -0,0 +1,14 @@
+INCLUDE_DIRECTORIES(${OSG_INCLUDE_DIRS} )
+SET(TARGET_LIBRARIES_VARS OSG_LIBRARY OSGDB_LIBRARY OSGUTIL_LIBRARY OSGVIEWER_LIBRARY OPENTHREADS_LIBRARY)
+
+SET(TARGET_H
+    SkyManipulator
+)
+
+SET(TARGET_SRC
+    SkyManipulator.cpp
+    osgearth_skyview.cpp
+)
+
+#### end var setup  ###
+SETUP_APPLICATION(osgearth_skyview)
\ No newline at end of file
diff --git a/src/applications/osgearth_skyview/SkyManipulator b/src/applications/osgearth_skyview/SkyManipulator
new file mode 100644
index 0000000..5de90c0
--- /dev/null
+++ b/src/applications/osgearth_skyview/SkyManipulator
@@ -0,0 +1,40 @@
+#ifndef OSGEARTH_SKYMANIPULATOR_H
+#define OSGEARTH_SKYMANIPULATOR_H
+
+#include <osgGA/CameraManipulator>
+
+class SkyManipulator : public osgGA::CameraManipulator
+{
+public:
+    SkyManipulator();
+
+    /** set the position of the matrix manipulator using a 4x4 Matrix.*/
+    virtual void setByMatrix(const osg::Matrixd& matrix);
+
+    /** set the position of the matrix manipulator using a 4x4 Matrix.*/
+    virtual void setByInverseMatrix(const osg::Matrixd& matrix);
+
+    /** get the position of the manipulator as 4x4 Matrix.*/
+    virtual osg::Matrixd getMatrix() const;
+
+    /** get the position of the manipulator as a inverse matrix of the manipulator, typically used as a model view matrix.*/
+    virtual osg::Matrixd getInverseMatrix() const;
+
+    osg::Quat getRotation() const;
+
+    // handle events, return true if handled, false otherwise.
+    virtual bool handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& us);
+
+    // Move the camera to the default position.
+    virtual void home(double /*unused*/);
+    virtual void home(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& us);
+
+    double _heading;
+    double _pitch;
+    double _distance;
+
+    float _prevX, _prevY;
+};
+
+
+#endif
\ No newline at end of file
diff --git a/src/applications/osgearth_skyview/SkyManipulator.cpp b/src/applications/osgearth_skyview/SkyManipulator.cpp
new file mode 100644
index 0000000..0741e07
--- /dev/null
+++ b/src/applications/osgearth_skyview/SkyManipulator.cpp
@@ -0,0 +1,120 @@
+#include "SkyManipulator"
+#include <iostream>
+
+
+SkyManipulator::SkyManipulator():
+_heading(0.0),
+_pitch(0.0),
+_distance(1.0),
+_prevX(FLT_MAX),
+_prevY(FLT_MAX)
+{
+}
+
+void SkyManipulator::setByMatrix(const osg::Matrixd& matrix)
+{
+}
+
+void SkyManipulator::setByInverseMatrix(const osg::Matrixd& matrix)
+{
+}
+
+osg::Matrixd SkyManipulator::getMatrix() const
+{
+    osg::Quat rot = getRotation();
+    return osg::Matrixd::translate(0,0,-_distance) *  
+           osg::Matrixd::rotate(rot);
+}
+
+osg::Matrixd SkyManipulator::getInverseMatrix() const
+{
+    return osg::Matrixd::inverse(getMatrix());
+}
+
+bool SkyManipulator::handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa)
+{
+    double maxDistance = osg::WGS_84_RADIUS_EQUATOR;
+
+    if (ea.getEventType() == osgGA::GUIEventAdapter::SCROLL)
+    {
+        
+        double speed = 0.1;
+        double diff = (maxDistance - _distance) * speed;
+
+        if (ea.getScrollingMotion() == osgGA::GUIEventAdapter::SCROLL_UP)
+        {
+            _distance += diff;
+        }
+        else
+        {
+            _distance -= diff;
+        }
+
+        _distance = osg::clampBetween(_distance, 0.0, maxDistance);
+        
+        return true;
+    }
+    else if (ea.getEventType() == osgGA::GUIEventAdapter::DRAG)
+    {
+        if (_prevX != FLT_MAX && _prevY != FLT_MAX)
+        {
+            float dx = ea.getX() - _prevX;
+            float dy = ea.getY() - _prevY;
+
+            double maxSpeed = osg::PI * 2.0 / 300.0;
+            double minSpeed = osg::PI * 2.0 / 30000.0;
+
+            double speed = minSpeed + (1.0 - _distance / maxDistance) * (maxSpeed - minSpeed);
+
+            _heading -= dx * speed;
+            _pitch -= dy * speed;
+        }
+
+        _prevX = ea.getX();
+        _prevY = ea.getY();
+        return true;
+    }
+    else if (ea.getEventType() == osgGA::GUIEventAdapter::PUSH)
+    {
+        _prevX = ea.getX();
+        _prevY = ea.getY();
+    }
+    else if (ea.getEventType() == osgGA::GUIEventAdapter::RELEASE)
+    {
+        _prevX = FLT_MAX;
+        _prevY = FLT_MAX;
+    }
+    else if (ea.getEventType() == osgGA::GUIEventAdapter::KEYDOWN)
+    {
+        if (ea.getKey()== osgGA::GUIEventAdapter::KEY_Space)
+        {
+            home(0.0);
+        }
+    }
+        
+    
+    return false;
+}
+
+osg::Quat SkyManipulator::getRotation() const
+{
+    osg::Quat azim_q (  _heading,            osg::Vec3d(0,0,1) );
+    osg::Quat pitch_q( -_pitch-osg::PI_2, osg::Vec3d(1,0,0) );
+    osg::Matrix newRot = osg::Matrixd( azim_q * pitch_q );
+    return osg::Matrixd::inverse(newRot).getRotate();  
+}
+
+void
+SkyManipulator::home(double unused)
+{
+    _heading = 0.0;
+    _pitch = 0.0;
+    _distance = 0.0;
+}
+
+void
+SkyManipulator::home(const osgGA::GUIEventAdapter& ,osgGA::GUIActionAdapter& us)
+{
+    home( 0.0 );
+    us.requestRedraw();
+}
\ No newline at end of file
diff --git a/src/applications/osgearth_skyview/osgearth_skyview.cpp b/src/applications/osgearth_skyview/osgearth_skyview.cpp
new file mode 100644
index 0000000..aa1106f
--- /dev/null
+++ b/src/applications/osgearth_skyview/osgearth_skyview.cpp
@@ -0,0 +1,108 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+* Copyright 2016 Pelican Mapping
+* http://osgearth.org
+*
+* osgEarth is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* 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.
+*
+* You should have received a copy of the GNU Lesser General Public License
+* along with this program.  If not, see <http://www.gnu.org/licenses/>
+*/
+
+#include <osgViewer/Viewer>
+#include <osg/CullFace>
+#include <osgEarth/Notify>
+#include <osgEarthUtil/ExampleResources>
+#include "SkyManipulator"
+
+
+#define LC "[viewer] "
+
+using namespace osgEarth;
+using namespace osgEarth::Util;
+
+int
+usage(const char* name)
+{
+    OE_NOTICE 
+        << "\nUsage: " << name << " file.earth" << std::endl
+        << MapNodeHelper().usage() << std::endl;
+
+    return 0;
+}
+
+int
+main(int argc, char** argv)
+{
+    osg::ArgumentParser arguments(&argc,argv);
+
+    // help?
+    if ( arguments.read("--help") )
+        return usage(argv[0]);
+
+    // Increase the fov to provide a more immersive experience.
+    float vfov = 100.0f;
+    arguments.read("--vfov", vfov);
+
+    // create a viewer:
+    osgViewer::Viewer viewer(arguments);
+
+    // Tell the database pager to not modify the unref settings
+    viewer.getDatabasePager()->setUnrefImageDataAfterApplyPolicy( false, false );
+
+    // thread-safe initialization of the OSG wrapper manager. Calling this here
+    // prevents the "unsupported wrapper" messages from OSG
+    osgDB::Registry::instance()->getObjectWrapperManager()->findWrapper("osg::Image");
+
+    // disable the small-feature culling
+    viewer.getCamera()->setSmallFeatureCullingPixelSize(-1.0f);
+
+    // set a near/far ratio that is smaller than the default. This allows us to get
+    // closer to the ground without near clipping. If you need more, use --logdepth
+    viewer.getCamera()->setNearFarRatio(0.0001);
+
+    if ( vfov > 0.0 )
+    {
+        double fov, ar, n, f;
+        viewer.getCamera()->getProjectionMatrixAsPerspective(fov, ar, n, f);
+        viewer.getCamera()->setProjectionMatrixAsPerspective(vfov, ar, n, f);
+    }
+
+    // load an earth file, and support all or our example command-line options
+    // and earth file <external> tags    
+    osg::Node* node = MapNodeHelper().load( arguments, &viewer );
+
+    //Set our custom manipulator
+    viewer.setCameraManipulator(new SkyManipulator());
+    //viewer.setCameraManipulator( new osgGA::FirstPersonManipulator() );
+
+    
+    
+    if ( node )
+    {
+        // Disable backface culling
+       node->getOrCreateStateSet()->setMode(GL_CULL_FACE, osg::StateAttribute::OFF | osg::StateAttribute::OVERRIDE);
+
+
+        viewer.setSceneData( node );
+        while(!viewer.done())
+        {
+            viewer.frame();            
+        }
+    }
+    else
+    {
+        return usage(argv[0]);
+    }
+}
diff --git a/src/applications/osgearth_splat/CMakeLists.txt b/src/applications/osgearth_splat/CMakeLists.txt
new file mode 100644
index 0000000..f4253c8
--- /dev/null
+++ b/src/applications/osgearth_splat/CMakeLists.txt
@@ -0,0 +1,10 @@
+INCLUDE_DIRECTORIES(${OSG_INCLUDE_DIRS} )
+
+SET(TARGET_LIBRARIES_VARS OSG_LIBRARY OSGDB_LIBRARY OSGUTIL_LIBRARY OSGVIEWER_LIBRARY OPENTHREADS_LIBRARY)
+
+SET(TARGET_COMMON_LIBRARIES ${TARGET_COMMON_LIBRARIES} osgEarthSplat)
+
+SET(TARGET_SRC osgearth_splat.cpp )
+
+#### end var setup  ###
+SETUP_APPLICATION(osgearth_splat)
\ No newline at end of file
diff --git a/src/applications/osgearth_splat/osgearth_splat.cpp b/src/applications/osgearth_splat/osgearth_splat.cpp
new file mode 100644
index 0000000..e429cde
--- /dev/null
+++ b/src/applications/osgearth_splat/osgearth_splat.cpp
@@ -0,0 +1,135 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+* Copyright 2016 Pelican Mapping
+* http://osgearth.org
+*
+* osgEarth is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* 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.
+*
+* You should have received a copy of the GNU Lesser General Public License
+* along with this program.  If not, see <http://www.gnu.org/licenses/>
+*/
+
+#include <osgViewer/Viewer>
+#include <osgEarth/Notify>
+#include <osgEarth/VirtualProgram>
+#include <osgEarthUtil/EarthManipulator>
+#include <osgEarthUtil/ExampleResources>
+
+#include <osgEarthSplat/LandCoverTerrainEffect>
+#include <osgEarthSplat/SplatExtension>
+
+#define LC "[viewer] "
+
+using namespace osgEarth;
+using namespace osgEarth::Util;
+using namespace osgEarth::Splat;
+
+int
+usage(const char* name)
+{
+    OE_NOTICE 
+        << "\nUsage: " << name << " file.earth" << std::endl
+        << MapNodeHelper().usage() << std::endl;
+
+    return 0;
+}
+
+const char* color_landcover =
+    "#version 120\n"
+    "void color_landcover(inout vec4 color) \n"
+    "{ \n"
+    "    color = vec4(1,0,0,1);\n"
+    "} \n";
+
+int
+main(int argc, char** argv)
+{
+    osg::ArgumentParser arguments(&argc,argv);
+
+    // help?
+    if ( arguments.read("--help") )
+        return usage(argv[0]);
+
+    // create a viewer:
+    osgViewer::Viewer viewer(arguments);
+
+    // Tell the database pager to not modify the unref settings
+    viewer.getDatabasePager()->setUnrefImageDataAfterApplyPolicy( false, false );
+
+    // install our default manipulator (do this before calling load)
+    viewer.setCameraManipulator( new EarthManipulator(arguments) );
+
+    // disable the small-feature culling
+    viewer.getCamera()->setSmallFeatureCullingPixelSize(-1.0f);
+
+    // set a near/far ratio that is smaller than the default. This allows us to get
+    // closer to the ground without near clipping. If you need more, use --logdepth
+    viewer.getCamera()->setNearFarRatio(0.0001);
+
+    // load an earth file, and support all or our example command-line options
+    // and earth file <external> tags    
+    osg::Node* node = MapNodeHelper().load( arguments, &viewer );
+    if ( node )
+    {
+
+        // Get the MapNode
+        MapNode* mapNode = MapNode::findMapNode( node );
+
+        // Find the Splat Extension
+        SplatExtension* splatExtension = mapNode->getExtension<SplatExtension>();
+        if (splatExtension)
+        {
+            OE_NOTICE << "Found Splat Extension" << std::endl;
+        }
+
+        LandCoverTerrainEffect* landCoverEffect = mapNode->getTerrainEngine()->getEffect<LandCoverTerrainEffect>();
+        if (landCoverEffect)
+        {
+            OE_NOTICE << "Found landcover terrain effect" << std::endl;
+
+            for (Zones::const_iterator zoneItr = landCoverEffect->getZones().begin();
+                zoneItr != landCoverEffect->getZones().end();
+                ++zoneItr)
+            {
+                // Get the StateSet for each of the LandCoverLayers
+                for (LandCoverLayers::iterator landCoverItr = zoneItr->get()->getLandCover()->getLayers().begin();
+                    landCoverItr != zoneItr->get()->getLandCover()->getLayers().end();
+                    ++landCoverItr)
+                {
+                    // Get the stateset for the layer.
+                    osg::StateSet* stateset = landCoverItr->get()->getOrCreateStateSet();
+
+                    // Get the VirtualProgram for this layer.
+                    VirtualProgram* vp = VirtualProgram::getOrCreate(stateset);
+
+                    // Make the "tree" layer all red.
+                    if (landCoverItr->get()->getName() == "trees")
+                    {                                         
+                        vp->setFunction( "color_landcover", color_landcover, ShaderComp::LOCATION_FRAGMENT_LIGHTING);
+                    }
+                }
+            }
+        }
+
+        viewer.setSceneData( node );
+        while(!viewer.done())
+        {
+            viewer.frame();
+        }
+    }
+    else
+    {
+        return usage(argv[0]);
+    }
+}
diff --git a/src/applications/osgearth_srstest/CMakeLists.txt b/src/applications/osgearth_srstest/CMakeLists.txt
new file mode 100644
index 0000000..ba57830
--- /dev/null
+++ b/src/applications/osgearth_srstest/CMakeLists.txt
@@ -0,0 +1,7 @@
+INCLUDE_DIRECTORIES(${OSG_INCLUDE_DIRS} )
+SET(TARGET_LIBRARIES_VARS OSG_LIBRARY OSGDB_LIBRARY OSGUTIL_LIBRARY OSGVIEWER_LIBRARY OPENTHREADS_LIBRARY)
+
+SET(TARGET_SRC osgearth_srstest.cpp)
+
+#### end var setup  ###
+SETUP_APPLICATION(osgearth_srstest)
\ No newline at end of file
diff --git a/src/applications/osgearth_srstest/osgearth_srstest.cpp b/src/applications/osgearth_srstest/osgearth_srstest.cpp
new file mode 100644
index 0000000..7928b68
--- /dev/null
+++ b/src/applications/osgearth_srstest/osgearth_srstest.cpp
@@ -0,0 +1,70 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+* Copyright 2016 Pelican Mapping
+* http://osgearth.org
+*
+* osgEarth is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* 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.
+*
+* You should have received a copy of the GNU Lesser General Public License
+* along with this program.  If not, see <http://www.gnu.org/licenses/>
+*/
+#include <osgEarth/SpatialReference>
+#include <osgEarth/StringUtils>
+#include <iostream>
+
+bool eq(const double& a, const double& b, double e =1e-6) {
+    return fabs(a - b) <= e;
+}
+
+bool eq(const osg::Vec3d& a, const osg::Vec3d& b, double e =1e-6) {
+    return fabs(a.x() - b.x()) <= e && fabs(a.y() - b.y()) <= e && fabs(a.z() - b.z()) <= e;
+}
+
+int fail(const std::string& test, const std::string& msg) {
+    std::cout << test << ": " << msg << std::endl;
+    return -1;
+}
+
+int
+main(int argc, char** argv)
+{
+    using namespace osgEarth;
+
+    std::string test;
+
+    // Vertical datum tests.
+    // Reference: http://earth-info.nga.mil/GandG/wgs84/gravitymod/egm96/intpt.html
+    {
+        test = "Convert geodetic Z to EGM96";
+        const SpatialReference* wgs84 = SpatialReference::get("wgs84");
+        const SpatialReference* wgs84_egm96 = SpatialReference::get("wgs84", "egm96");        
+        osg::Vec3d input[4] = {
+            osg::Vec3d( 0,  0,  17.16),
+            osg::Vec3d( 90, 0, -63.24),
+            osg::Vec3d(180, 0,  21.15),
+            osg::Vec3d(-90, 0,  -4.29)
+        };
+        osg::Vec3d output;
+        for (int i = 0; i<4; ++i) {
+            osg::Vec3d output;
+            if (!wgs84->transform(input[i], wgs84_egm96, output))
+                std::cout << test << ": transform failed for texst #" << i << std::endl;
+            else if (!eq(output.z(), 0.0, 0.01)) {
+                std::cout << test << ": output doesn't match for test #" << i << "; expected Z=0, got Z=" << output.z() << std::endl;
+            }
+        }
+    }
+
+    return 0;
+}
diff --git a/src/applications/osgearth_terrainprofile/osgearth_terrainprofile.cpp b/src/applications/osgearth_terrainprofile/osgearth_terrainprofile.cpp
index 39cf919..9c80a95 100644
--- a/src/applications/osgearth_terrainprofile/osgearth_terrainprofile.cpp
+++ b/src/applications/osgearth_terrainprofile/osgearth_terrainprofile.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/applications/osgearth_tfs/osgearth_tfs.cpp b/src/applications/osgearth_tfs/osgearth_tfs.cpp
index b2dbb26..45bd00f 100644
--- a/src/applications/osgearth_tfs/osgearth_tfs.cpp
+++ b/src/applications/osgearth_tfs/osgearth_tfs.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
@@ -162,11 +162,10 @@ int main(int argc, char** argv)
         return 1;
     }
 
-    features->initialize();
-    const FeatureProfile* profile = features->getFeatureProfile();
-    if (!profile)
+    Status s = features->open();
+    if (s.isError())
     {
-        OE_NOTICE << "Failed to create a valid profile for " << filename << std::endl;
+        OE_NOTICE << s.message() << ": " << filename << std::endl;
         return 1;
     }
 
diff --git a/src/applications/osgearth_tileindex/osgearth_tileindex.cpp b/src/applications/osgearth_tileindex/osgearth_tileindex.cpp
index dc6c1b0..dc2d36d 100644
--- a/src/applications/osgearth_tileindex/osgearth_tileindex.cpp
+++ b/src/applications/osgearth_tileindex/osgearth_tileindex.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/applications/osgearth_tilesource/osgearth_tilesource.cpp b/src/applications/osgearth_tilesource/osgearth_tilesource.cpp
index 940055e..d583b8b 100644
--- a/src/applications/osgearth_tilesource/osgearth_tilesource.cpp
+++ b/src/applications/osgearth_tilesource/osgearth_tilesource.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
@@ -103,7 +103,9 @@ int main(int argc, char** argv)
 
     // Create out image layer with a custom tile source.
     ImageLayerOptions options( "custom" );
-    map->addImageLayer( new ImageLayer(options, new CustomTileSource()) );
+    CustomTileSource* tileSource = new CustomTileSource();
+    tileSource->open();
+    map->addImageLayer( new ImageLayer(options, tileSource) );
 
     // That's it, the map is ready; now create a MapNode to render the Map:
     MapNode* mapNode = new MapNode( map );
diff --git a/src/applications/osgearth_toc/osgearth_toc.cpp b/src/applications/osgearth_toc/osgearth_toc.cpp
index 5849549..6f07547 100644
--- a/src/applications/osgearth_toc/osgearth_toc.cpp
+++ b/src/applications/osgearth_toc/osgearth_toc.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
@@ -260,7 +260,7 @@ createControlPanel( osgViewer::View* view )
     s_masterGrid->setChildSpacing( 10 );
     s_masterGrid->setChildVertAlign( Control::ALIGN_CENTER );
     s_masterGrid->setAbsorbEvents( true );
-    s_masterGrid->setVertAlign( Control::ALIGN_BOTTOM );
+    s_masterGrid->setVertAlign( Control::ALIGN_TOP );
 
     //The image layers
     s_imageBox = new Grid();
@@ -270,7 +270,7 @@ createControlPanel( osgViewer::View* view )
     s_imageBox->setChildSpacing( 10 );
     s_imageBox->setChildVertAlign( Control::ALIGN_CENTER );
     s_imageBox->setAbsorbEvents( true );
-    s_imageBox->setVertAlign( Control::ALIGN_BOTTOM );
+    s_imageBox->setVertAlign( Control::ALIGN_TOP );
     s_masterGrid->setControl( 0, 0, s_imageBox );
 
     //the elevation layers
@@ -281,7 +281,7 @@ createControlPanel( osgViewer::View* view )
     s_elevationBox->setChildSpacing( 10 );
     s_elevationBox->setChildVertAlign( Control::ALIGN_CENTER );
     s_elevationBox->setAbsorbEvents( true );
-    s_elevationBox->setVertAlign( Control::ALIGN_BOTTOM );
+    s_elevationBox->setVertAlign( Control::ALIGN_TOP );
     s_masterGrid->setControl( 1, 0, s_elevationBox );
 
     //The image layers
@@ -292,7 +292,7 @@ createControlPanel( osgViewer::View* view )
     s_modelBox->setChildSpacing( 10 );
     s_modelBox->setChildVertAlign( Control::ALIGN_CENTER );
     s_modelBox->setAbsorbEvents( true );
-    s_modelBox->setVertAlign( Control::ALIGN_BOTTOM );
+    s_modelBox->setVertAlign( Control::ALIGN_TOP );
     s_masterGrid->setControl( 2, 0, s_modelBox );
 
     canvas->addControl( s_masterGrid );
@@ -301,14 +301,17 @@ createControlPanel( osgViewer::View* view )
 void
 createLayerItem( Grid* grid, int gridRow, int layerIndex, int numLayers, TerrainLayer* layer, bool isActive )
 {
+    int gridCol = 0;
+
     // a checkbox to enable/disable the layer:
     CheckBoxControl* enabled = new CheckBoxControl( layer->getVisible() );
     enabled->addEventHandler( new LayerVisibleHandler(layer) );
-    grid->setControl( 0, gridRow, enabled );
+    grid->setControl( gridCol++, gridRow, enabled );
 
     // the layer name
     LabelControl* name = new LabelControl( layer->getName() );
-    grid->setControl( 1, gridRow, name );
+    grid->setControl( gridCol, gridRow, name );
+    gridCol++;
 
     ImageLayer* imageLayer = dynamic_cast< ImageLayer* > (layer );
     if (imageLayer)
@@ -318,8 +321,16 @@ createLayerItem( Grid* grid, int gridRow, int layerIndex, int numLayers, Terrain
         opacity->setWidth( 125 );
         opacity->setHeight( 12 );
         opacity->addEventHandler( new LayerOpacityHandler(imageLayer) );
-        grid->setControl( 2, gridRow, opacity );
+        grid->setControl( gridCol, gridRow, opacity );
     }
+    gridCol++;
+
+    // status indicator
+    LabelControl* statusLabel = layer->getStatus().isOK()
+        ? new LabelControl("[ok]", osg::Vec4(0,1,0,1))
+        : new LabelControl("[error]", osg::Vec4(1,0,0,1));
+    grid->setControl( gridCol, gridRow, statusLabel );
+    gridCol++;
 
     // move buttons
     if ( layerIndex < numLayers-1 && isActive )
@@ -328,16 +339,19 @@ createLayerItem( Grid* grid, int gridRow, int layerIndex, int numLayers, Terrain
         upButton->setBackColor( .4,.4,.4,1 );
         upButton->setActiveColor( .8,0,0,1 );
         upButton->addEventHandler( new MoveLayerHandler( layer, layerIndex+1 ) );
-        grid->setControl( 3, gridRow, upButton );
+        grid->setControl( gridCol, gridRow, upButton );
     }
+    gridCol++;
+
     if ( layerIndex > 0 && isActive)
     {
         LabelControl* upButton = new LabelControl( "DOWN", 14 );
         upButton->setBackColor( .4,.4,.4,1 );
         upButton->setActiveColor( .8,0,0,1 );
         upButton->addEventHandler( new MoveLayerHandler( layer, layerIndex-1 ) );
-        grid->setControl( 4, gridRow, upButton );
+        grid->setControl( gridCol, gridRow, upButton );
     }
+    gridCol++;
 
     // add/remove button:
     LabelControl* addRemove = new LabelControl( isActive? "REMOVE" : "ADD", 14 );
@@ -348,7 +362,8 @@ createLayerItem( Grid* grid, int gridRow, int layerIndex, int numLayers, Terrain
         addRemove->addEventHandler( new RemoveLayerHandler(layer) );
     else
         addRemove->addEventHandler( new AddLayerHandler(layer) );
-    grid->setControl( 5, gridRow, addRemove );
+    grid->setControl( gridCol, gridRow, addRemove );
+    gridCol++;
 }
 
 void
@@ -363,12 +378,17 @@ createModelLayerItem( Grid* grid, int gridRow, ModelLayer* layer, bool isActive
     LabelControl* name = new LabelControl( layer->getName() );
     grid->setControl( 1, gridRow, name );
 
+    LabelControl* statusLabel = layer->getStatus().isOK()
+        ? new LabelControl("[ok]", osg::Vec4(0, 1, 0, 1))
+        : new LabelControl("[error]", osg::Vec4(1, 0, 0, 1));
+    grid->setControl(2, gridRow, statusLabel);
+
     // an opacity slider
     HSliderControl* opacity = new HSliderControl( 0.0f, 1.0f, layer->getOpacity() );
     opacity->setWidth( 125 );
     opacity->setHeight( 12 );
     opacity->addEventHandler( new ModelLayerOpacityHandler(layer) );
-    grid->setControl( 2, gridRow, opacity );
+    grid->setControl( 3, gridRow, opacity );
 }
 
 void
diff --git a/src/applications/osgearth_tracks/osgearth_tracks.cpp b/src/applications/osgearth_tracks/osgearth_tracks.cpp
index 77481c7..4eb0fb9 100644
--- a/src/applications/osgearth_tracks/osgearth_tracks.cpp
+++ b/src/applications/osgearth_tracks/osgearth_tracks.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
@@ -26,7 +26,7 @@
 #include <osgEarth/GeoMath>
 #include <osgEarth/Units>
 #include <osgEarth/StringUtils>
-#include <osgEarth/Decluttering>
+#include <osgEarth/ScreenSpaceLayout>
 #include <osgEarthUtil/ExampleResources>
 #include <osgEarthUtil/EarthManipulator>
 #include <osgEarthUtil/MGRSFormatter>
@@ -69,7 +69,7 @@ static MGRSFormatter s_format(MGRSFormatter::PRECISION_10000M);
 bool                g_showCoords        = true;
 optional<float>     g_duration          = 60.0;
 unsigned            g_numTracks         = 500;
-DeclutteringOptions g_dcOptions;
+ScreenSpaceLayoutOptions g_dcOptions;
 
 
 /** Prints an error message */
@@ -191,11 +191,7 @@ createTrackNodes( MapNode* mapNode, osg::Group* parent, const TrackNodeFieldSche
         track->setFieldValue( FIELD_NUMBER,   Stringify() << (1 + prng.next(9)) );
 
         // add a priority
-        AnnotationData* data = new AnnotationData();
-        data->setPriority( float(i) );
-        track->setAnnotationData( data );
-
-        Decluttering::setEnabled(track->getOrCreateStateSet(), true);
+        track->setPriority( float(i) );
 
         parent->addChild( track );
 
@@ -212,20 +208,20 @@ createTrackNodes( MapNode* mapNode, osg::Group* parent, const TrackNodeFieldSche
 
 
 /** creates some UI controls for adjusting the decluttering parameters. */
-void
+Container*
 createControls( osgViewer::View* view )
 {
-    ControlCanvas* canvas = ControlCanvas::getOrCreate(view);
+    //ControlCanvas* canvas = ControlCanvas::getOrCreate(view);
     
     // title bar
-    VBox* vbox = canvas->addControl(new VBox(Control::ALIGN_NONE, Control::ALIGN_BOTTOM, 2, 1 ));
+    VBox* vbox = new VBox(Control::ALIGN_NONE, Control::ALIGN_BOTTOM, 2, 1 );
     vbox->setBackColor( Color(Color::Black, 0.5) );
     vbox->addControl( new LabelControl("osgEarth Tracks Demo", Color::Yellow) );
     
     // checkbox that toggles decluttering of tracks
     struct ToggleDecluttering : public ControlEventHandler {
         void onValueChanged( Control* c, bool on ) {
-            Decluttering::setEnabled( on );
+            ScreenSpaceLayout::setDeclutteringEnabled( on );
         }
     };
     HBox* dcToggle = vbox->addControl( new HBox() );
@@ -258,7 +254,7 @@ createControls( osgViewer::View* view )
         void onValueChanged( Control* c, float value ) {
             _param = value;
             _label->setText( Stringify() << std::fixed << std::setprecision(1) << value );
-            Decluttering::setOptions( g_dcOptions );
+            ScreenSpaceLayout::setOptions( g_dcOptions );
         }
     };
 
@@ -287,6 +283,8 @@ createControls( osgViewer::View* view )
     LabelControl* deactLabel = grid->setControl( 2, r, new LabelControl(Stringify() << std::fixed << std::setprecision(1) << *g_dcOptions.outAnimationTime()) );
     grid->setControl( 1, r, new HSliderControl( 
         0.0, 2.0, *g_dcOptions.outAnimationTime(), new ChangeFloatOption(g_dcOptions.outAnimationTime(), deactLabel) ) );
+
+    return vbox;
 }
 
 
@@ -304,7 +302,8 @@ main(int argc, char** argv)
     viewer.setCameraManipulator( new EarthManipulator );
 
     // load a map from an earth file.
-    osg::Node* earth = MapNodeHelper().load(arguments, &viewer);
+    osg::Node* earth = MapNodeHelper().load(arguments, &viewer, createControls(&viewer));
+
     MapNode* mapNode = MapNode::findMapNode(earth);
     if ( !mapNode )
         return usage("Missing required .earth file" );
@@ -331,18 +330,15 @@ main(int argc, char** argv)
     // sorting, which looks at the AnnotationData::priority field for each drawable.
     // (By default, objects are sorted by disatnce-to-camera.) Finally, we customize 
     // a couple of the decluttering options to get the animation effects we want.
-    g_dcOptions = Decluttering::getOptions();
+    g_dcOptions = ScreenSpaceLayout::getOptions();
     g_dcOptions.inAnimationTime()  = 1.0f;
     g_dcOptions.outAnimationTime() = 1.0f;
     g_dcOptions.sortByPriority()   = true;
-    Decluttering::setOptions( g_dcOptions );
+    ScreenSpaceLayout::setOptions( g_dcOptions );
 
     // attach the simulator to the viewer.
     viewer.addUpdateOperation( new TrackSimUpdate(trackSims) );
     viewer.setRunFrameScheme( viewer.CONTINUOUS );
-
-    // configure a UI for controlling the demo
-    createControls( &viewer );
     
     viewer.getCamera()->setSmallFeatureCullingPixelSize(-1.0f);
     viewer.run();
diff --git a/src/applications/osgearth_transform/osgearth_transform.cpp b/src/applications/osgearth_transform/osgearth_transform.cpp
index 528bd2e..2549d35 100644
--- a/src/applications/osgearth_transform/osgearth_transform.cpp
+++ b/src/applications/osgearth_transform/osgearth_transform.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/applications/osgearth_triton/CMakeLists.txt b/src/applications/osgearth_triton/CMakeLists.txt
new file mode 100644
index 0000000..6489b47
--- /dev/null
+++ b/src/applications/osgearth_triton/CMakeLists.txt
@@ -0,0 +1,9 @@
+INCLUDE_DIRECTORIES(${OSG_INCLUDE_DIRS})
+SET(TARGET_LIBRARIES_VARS OSG_LIBRARY OSGDB_LIBRARY OSGUTIL_LIBRARY OSGVIEWER_LIBRARY OPENTHREADS_LIBRARY)
+
+SET(TARGET_COMMON_LIBRARIES ${TARGET_COMMON_LIBRARIES} osgEarthUtil osgEarthTriton)
+
+SET(TARGET_SRC osgearth_triton.cpp )
+
+#### end var setup  ###
+SETUP_APPLICATION(osgearth_triton)
diff --git a/src/applications/osgearth_triton/osgearth_triton.cpp b/src/applications/osgearth_triton/osgearth_triton.cpp
new file mode 100644
index 0000000..d36e320
--- /dev/null
+++ b/src/applications/osgearth_triton/osgearth_triton.cpp
@@ -0,0 +1,189 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+* Copyright 2008-2014 Pelican Mapping
+* http://osgearth.org
+*
+* osgEarth is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public License
+* along with this program.  If not, see <http://www.gnu.org/licenses/>
+*/
+#include <osgViewer/Viewer>
+#include <osgDB/FileNameUtils>
+#include <osgEarthUtil/EarthManipulator>
+#include <osgEarthUtil/ExampleResources>
+#include <osgEarthUtil/Controls>
+#include <osgEarthTriton/TritonNode>
+
+#define LC "[osgearth_sundog] "
+
+using namespace osgEarth;
+using namespace osgEarth::Util;
+using namespace osgEarth::Triton;
+namespace ui = osgEarth::Util::Controls;
+
+struct Settings
+{
+    TritonNode* triton;
+    optional<double> chop;
+    optional<double> seaState;
+    optional<float> alpha;
+    
+    void apply(Environment& env, Ocean& ocean)
+    {
+        if (chop.isSet())
+        {
+            ocean.SetChoppiness(chop.get());
+            chop.clear();
+        }
+
+        if (seaState.isSet())
+        {
+            env.SimulateSeaState(seaState.get(), 0.0);
+            seaState.clear();
+        }
+
+        if (alpha.isSet())
+        {
+            triton->setAlpha( alpha.get() );
+        }
+    }
+};
+Settings s_settings;
+
+
+template<typename T> struct Set : public ui::ControlEventHandler
+{
+    optional<T>& _var;
+    Set(optional<T>& var) : _var(var) { }
+    void onValueChanged(ui::Control*, double value) { _var = value; }
+};
+
+
+Container* createUI()
+{
+    VBox* box = new VBox();
+    box->setBackColor(0,0,0,0.5);
+    Grid* grid = box->addControl(new Grid());
+    int r=0;
+    grid->setControl(0, r, new LabelControl("Chop"));
+    grid->setControl(1, r, new HSliderControl(0, 3, 0, new Set<double>(s_settings.chop)));
+    ++r;
+    grid->setControl(0, r, new LabelControl("Sea State"));
+    grid->setControl(1, r, new HSliderControl(0, 12, 5, new Set<double>(s_settings.seaState)));
+    ++r;  
+    grid->setControl(0, r, new LabelControl("Alpha"));
+    grid->setControl(1, r, new HSliderControl(0, 1.0, 1.0, new Set<float>(s_settings.alpha)));
+    ++r;
+    grid->getControl(1, r-1)->setHorizFill(true,200);
+
+    return box;
+}
+
+class TritonCallback : public osgEarth::Triton::Callback
+{
+public:
+    void onInitialize(Environment& env, Ocean& ocean)
+    {
+        //todo
+    }
+
+    void onDrawOcean(Environment& env, Ocean& ocean)
+    {
+        s_settings.apply(env, ocean);
+    }
+};
+
+
+int
+usage(const char* name)
+{
+    OE_DEBUG 
+        << "\nUsage: " << name << " file.earth" << std::endl
+        << osgEarth::Util::MapNodeHelper().usage() << std::endl;
+
+    return 0;
+}
+
+int
+main(int argc, char** argv)
+{
+    osg::ArgumentParser arguments(&argc,argv);
+
+    // help?
+    if ( arguments.read("--help") )
+        return usage(argv[0]);
+
+    // create a viewer:
+    osgViewer::Viewer viewer(arguments);
+
+    // Tell the database pager to not modify the unref settings
+    viewer.getDatabasePager()->setUnrefImageDataAfterApplyPolicy( false, false );
+
+    // install our default manipulator (do this before calling load)
+    viewer.setCameraManipulator( new osgEarth::Util::EarthManipulator() );
+
+    // load an earth file, and support all or our example command-line options
+    // and earth file <external> tags    
+    osg::Group* node = osgEarth::Util::MapNodeHelper().load(arguments, &viewer, createUI());
+    if ( node )
+    {        
+        viewer.getCamera()->setNearFarRatio(0.00002);
+        viewer.getCamera()->setSmallFeatureCullingPixelSize(-1.0f);
+
+        viewer.setSceneData( node );
+
+        MapNode* mapNode = MapNode::findMapNode( node );
+
+        // Create TritonNode from TritonOptions
+        osgEarth::Triton::TritonOptions tritonOptions;
+        tritonOptions.user()        = "my_user_name";
+        tritonOptions.licenseCode() = "my_license_code";
+        tritonOptions.maxAltitude() = 10000;
+
+        const char* ev_t = ::getenv("TRITON_PATH");
+        if ( ev_t )
+        {
+            tritonOptions.resourcePath() = osgDB::concatPaths(
+                std::string(ev_t),
+                "Resources" );
+
+            OE_INFO << LC 
+                << "Setting resource path to << " << tritonOptions.resourcePath().get()
+                << std::endl;
+        }
+        else
+        {
+            OE_WARN << LC
+                << "No resource path! Triton might not initialize properly. "
+                << "Consider setting the TRITON_PATH environment variable."
+                << std::endl;
+        }
+
+        s_settings.triton = new TritonNode(
+            mapNode,
+            tritonOptions,
+            new TritonCallback() );
+
+        // Insert under a sky if there is one.
+        SkyNode* sky = osgEarth::findTopMostNodeOfType<SkyNode>(node);
+        if (sky)
+            sky->addChild( s_settings.triton );
+        else
+            node->addChild( s_settings.triton );
+
+        return viewer.run();
+    }
+    else
+    {
+        return usage(argv[0]);
+    }
+}
diff --git a/src/applications/osgearth_version/osgearth_version.cpp b/src/applications/osgearth_version/osgearth_version.cpp
index 94ae058..d1fa556 100644
--- a/src/applications/osgearth_version/osgearth_version.cpp
+++ b/src/applications/osgearth_version/osgearth_version.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/applications/osgearth_viewer/osgearth_viewer.cpp b/src/applications/osgearth_viewer/osgearth_viewer.cpp
index 62edb19..2e4b118 100644
--- a/src/applications/osgearth_viewer/osgearth_viewer.cpp
+++ b/src/applications/osgearth_viewer/osgearth_viewer.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
@@ -25,8 +25,8 @@
 #include <osgEarthUtil/EarthManipulator>
 #include <osgEarthUtil/ExampleResources>
 
-#include <osgEarth/Units>
-#include <osgEarth/Viewpoint>
+#include <osgEarth/Cache>
+#include <osgEarthDrivers/cache_filesystem/FileSystemCache>
 
 #define LC "[viewer] "
 
@@ -52,28 +52,43 @@ main(int argc, char** argv)
     if ( arguments.read("--help") )
         return usage(argv[0]);
 
-    if ( arguments.read("--stencil") )
-        osg::DisplaySettings::instance()->setMinimumNumStencilBits( 8 );
+    float vfov = -1.0f;
+    arguments.read("--vfov", vfov);
 
     // create a viewer:
     osgViewer::Viewer viewer(arguments);
 
     // Tell the database pager to not modify the unref settings
-    viewer.getDatabasePager()->setUnrefImageDataAfterApplyPolicy( false, false );
+    viewer.getDatabasePager()->setUnrefImageDataAfterApplyPolicy( true, false );
+
+    // thread-safe initialization of the OSG wrapper manager. Calling this here
+    // prevents the "unsupported wrapper" messages from OSG
+    osgDB::Registry::instance()->getObjectWrapperManager()->findWrapper("osg::Image");
 
     // install our default manipulator (do this before calling load)
-    viewer.setCameraManipulator( new EarthManipulator() );    
+    viewer.setCameraManipulator( new EarthManipulator(arguments) );
+
+    // disable the small-feature culling
+    viewer.getCamera()->setSmallFeatureCullingPixelSize(-1.0f);
+
+    // set a near/far ratio that is smaller than the default. This allows us to get
+    // closer to the ground without near clipping. If you need more, use --logdepth
+    viewer.getCamera()->setNearFarRatio(0.0001);
+
+    if ( vfov > 0.0 )
+    {
+        double fov, ar, n, f;
+        viewer.getCamera()->getProjectionMatrixAsPerspective(fov, ar, n, f);
+        viewer.getCamera()->setProjectionMatrixAsPerspective(vfov, ar, n, f);
+    }
 
     // load an earth file, and support all or our example command-line options
     // and earth file <external> tags    
-    osg::Node* node = MapNodeHelper().load( arguments, &viewer );
+    osg::Node* node = MapNodeHelper().load(arguments, &viewer);
     if ( node )
     {
         viewer.setSceneData( node );
-
-        viewer.getCamera()->setSmallFeatureCullingPixelSize(-1.0f);
-
-        return viewer.run();
+        viewer.run();
     }
     else
     {
diff --git a/src/applications/osgearth_wfs/CMakeLists.txt b/src/applications/osgearth_wfs/CMakeLists.txt
new file mode 100644
index 0000000..b195075
--- /dev/null
+++ b/src/applications/osgearth_wfs/CMakeLists.txt
@@ -0,0 +1,7 @@
+INCLUDE_DIRECTORIES(${OSG_INCLUDE_DIRS} )
+SET(TARGET_LIBRARIES_VARS OSG_LIBRARY OSGDB_LIBRARY OSGUTIL_LIBRARY OSGVIEWER_LIBRARY OPENTHREADS_LIBRARY)
+
+SET(TARGET_SRC osgearth_wfs.cpp )
+
+#### end var setup  ###
+SETUP_APPLICATION(osgearth_wfs)
\ No newline at end of file
diff --git a/src/applications/osgearth_wfs/osgearth_wfs.cpp b/src/applications/osgearth_wfs/osgearth_wfs.cpp
new file mode 100644
index 0000000..351703b
--- /dev/null
+++ b/src/applications/osgearth_wfs/osgearth_wfs.cpp
@@ -0,0 +1,116 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+* Copyright 2016 Pelican Mapping
+* http://osgearth.org
+*
+* osgEarth is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* 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.
+*
+* You should have received a copy of the GNU Lesser General Public License
+* along with this program.  If not, see <http://www.gnu.org/licenses/>
+*/
+
+#include <osgViewer/Viewer>
+#include <osgEarth/Notify>
+#include <osgEarthUtil/EarthManipulator>
+#include <osgEarthUtil/ExampleResources>
+
+#include <osgEarth/Units>
+#include <osgEarth/MapNode>
+
+// include for WFS feature driver:
+#include <osgEarthDrivers/feature_wfs/WFSFeatureOptions>
+
+// include for feature geometry model renderer:
+#include <osgEarthDrivers/model_feature_geom/FeatureGeomModelOptions>
+#include <osgEarthSymbology/Style>
+
+
+#define LC "[wfs example] "
+
+using namespace osgEarth;
+using namespace osgEarth::Util;
+using namespace osgEarth::Features;
+using namespace osgEarth::Symbology;
+
+int
+usage(const char* name)
+{
+    OE_NOTICE 
+        << "\nUsage: " << name << " file.earth" << std::endl
+        << MapNodeHelper().usage() << std::endl;
+
+    return 0;
+}
+
+int
+main(int argc, char** argv)
+{
+    osg::ArgumentParser arguments(&argc,argv);
+    if ( arguments.read("--help") )
+        return usage(argv[0]);
+
+    // general setup:
+    osgViewer::Viewer viewer(arguments);
+    viewer.getDatabasePager()->setUnrefImageDataAfterApplyPolicy( false, false );
+    viewer.setCameraManipulator( new EarthManipulator(arguments) );
+    viewer.getCamera()->setSmallFeatureCullingPixelSize(-1.0f);
+    viewer.getCamera()->setNearFarRatio(0.00002);
+
+    // load an earth file, and support all or our example command-line options
+    // and earth file <external> tags    
+    osg::Node* node = MapNodeHelper().load( arguments, &viewer );
+    if ( node )
+    {        
+        MapNode* mapNode = MapNode::get(node);
+        if ( !mapNode )
+            return usage(argv[0]);
+
+        // Create the WFS driver:
+        osgEarth::Drivers::WFSFeatureOptions wfs;
+        wfs.url()          = osgEarth::URI("http://demo.opengeo.org/geoserver/wfs"); 
+        wfs.typeName()     = "states"; 
+        wfs.outputFormat() = "json";     // JSON or GML
+
+        // Configure a rendering style:
+        Style style;
+        style.setName( "states" ); 
+
+        LineSymbol* line = style.getOrCreate<LineSymbol>(); 
+        line->stroke()->color() = Color::Yellow; 
+        line->stroke()->width() = 5.0f;
+        line->stroke()->widthUnits() = Units::PIXELS;
+
+        AltitudeSymbol* alt = style.getOrCreate<AltitudeSymbol>();
+        alt->clamping()  = AltitudeSymbol::CLAMP_TO_TERRAIN;
+        alt->technique() = AltitudeSymbol::TECHNIQUE_DRAPE;
+
+        // Configure a model layer to render the features:
+        osgEarth::Drivers::FeatureGeomModelOptions geom; 
+        geom.featureOptions() = wfs;
+        geom.styles()         = new StyleSheet(); 
+        geom.styles()->addStyle(style); 
+
+        // Make the new layer and add it to the map.
+        ModelLayerOptions layerOptions("states", geom); 
+        ModelLayer* layer = new ModelLayer(layerOptions); 
+        mapNode->getMap()->addModelLayer(layer);
+        
+        viewer.setSceneData( node );
+        return viewer.run();
+    }
+    else
+    {
+        return usage(argv[0]);
+    }
+}
diff --git a/src/applications/osgearth_xfbtest/CMakeLists.txt b/src/applications/osgearth_xfbtest/CMakeLists.txt
new file mode 100644
index 0000000..980970f
--- /dev/null
+++ b/src/applications/osgearth_xfbtest/CMakeLists.txt
@@ -0,0 +1,7 @@
+INCLUDE_DIRECTORIES(${OSG_INCLUDE_DIRS} )
+SET(TARGET_LIBRARIES_VARS OSG_LIBRARY OSGDB_LIBRARY OSGUTIL_LIBRARY OSGVIEWER_LIBRARY OPENTHREADS_LIBRARY)
+
+SET(TARGET_SRC osgearth_xfbtest.cpp )
+
+#### end var setup  ###
+SETUP_APPLICATION(osgearth_xfbtest)
\ No newline at end of file
diff --git a/src/applications/osgearth_xfbtest/osgearth_xfbtest.cpp b/src/applications/osgearth_xfbtest/osgearth_xfbtest.cpp
new file mode 100644
index 0000000..5bec125
--- /dev/null
+++ b/src/applications/osgearth_xfbtest/osgearth_xfbtest.cpp
@@ -0,0 +1,438 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+* Copyright 2016 Pelican Mapping
+* http://osgearth.org
+*
+* osgEarth is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* 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.
+*
+* You should have received a copy of the GNU Lesser General Public License
+* along with this program.  If not, see <http://www.gnu.org/licenses/>
+*/
+#include <osg/Version>
+#include <osg/Notify>
+
+#if OSG_VERSION_GREATER_OR_EQUAL(3,4,0)
+
+#include <osgViewer/Viewer>
+#include <osgViewer/ViewerEventHandlers>
+#include <osgGA/TrackballManipulator>
+#include <osgGA/StateSetManipulator>
+
+#include <osg/Geometry>
+#include <osg/Depth>
+#include <osg/Point>
+#include <osg/VertexAttribDivisor>
+#include <osgDB/ReadFile>
+#include <osgUtil/Optimizer>
+
+#include <osgEarth/Capabilities>
+#include <osgEarth/Registry>
+#include <osgEarth/ShaderGenerator>
+#include <osgEarth/ShaderLoader>
+
+
+
+#ifndef GL_TRANSFORM_FEEDBACK_BUFFER
+    #define GL_TRANSFORM_FEEDBACK_BUFFER      0x8C8E
+#endif
+
+#ifndef TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN
+    #define TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN 0x8c88
+#endif
+
+
+using namespace osgEarth;
+
+const char* IG_VS =
+    "#version 330\n"
+    "in vec4 xfb_position;\n"
+    "void oe_instancing_setPos(inout vec4 vertex) { \n"
+    "    vertex.xyz += xfb_position.xyz; \n"
+    "} \n";
+
+static int s_numInstancesToDraw = 0;
+
+/**
+ * Draw callback that goes on the instanced geometry, and draws exactly the number of 
+ * instances required (instead of reading the information from PrimitiveSet::getNumInstances)
+ */
+struct InstanceDrawCallback : public osg::Drawable::DrawCallback
+{
+    InstanceDrawCallback() { }
+
+    void drawImplementation(osg::RenderInfo& renderInfo, const osg::Drawable* drawable) const
+    {
+        const osg::Geometry* geom = static_cast<const osg::Geometry*>(drawable);
+        geom->drawVertexArraysImplementation(renderInfo);
+        for(int i=0; i<geom->getNumPrimitiveSets(); ++i)
+        {
+            const osg::PrimitiveSet* pset = geom->getPrimitiveSet(i);
+            const osg::DrawArrays* da = dynamic_cast<const osg::DrawArrays*>(pset);
+            if ( da )
+            {
+                renderInfo.getState()->glDrawArraysInstanced( da->getMode(), da->getFirst(), da->getCount(), s_numInstancesToDraw);
+            }
+            else
+            {
+                const osg::DrawElements* de = dynamic_cast<const osg::DrawElements*>(pset);
+                if ( de )
+                {
+                    GLenum dataType = const_cast<osg::DrawElements*>(de)->getDataType();
+                    renderInfo.getState()->glDrawElementsInstanced( de->getMode(), de->getNumIndices(), dataType, de->getDataPointer(), s_numInstancesToDraw );
+                }
+            }
+        }
+    }
+};
+
+
+struct InstanceGroup : public osg::Group
+{
+    InstanceGroup()
+    {
+        osg::StateSet* ss = getOrCreateStateSet();
+        VirtualProgram* vp = VirtualProgram::getOrCreate(ss);
+        vp->setFunction("oe_instancing_setPos", IG_VS, ShaderComp::LOCATION_VERTEX_MODEL, -FLT_MAX);
+
+        _xfb = new osg::Vec4Array();
+        _xfb->resizeArray( 1u );
+
+        // In practice, we will pre-set a bounding sphere/box for a tile
+        this->setCullingActive(false);
+    }
+
+    void configure(int slot, unsigned numInstances)
+    {
+        _slot = slot;
+        _numInstances = numInstances;
+
+        osg::StateSet* ss = getOrCreateStateSet();
+
+        _xfb->resizeArray( numInstances );
+
+        VirtualProgram* vp = VirtualProgram::get(ss);
+        
+        vp->removeBindAttribLocation( "xfb_position" );
+        vp->addBindAttribLocation( "xfb_position", _slot );
+
+        ss->setAttribute( new osg::VertexAttribDivisor(_slot, 1) );
+
+        _drawCallback = new InstanceDrawCallback();
+
+        Setup setup(this);
+        this->accept( setup );
+    }
+
+    osg::Array* getControlPoints() const
+    {
+        return _xfb.get();
+    }
+
+    osg::BoundingSphere computeBound() const
+    {
+        osg::BoundingSphere bs;
+
+        const osg::Vec4Array* points = static_cast<const osg::Vec4Array*>(_xfb.get());
+        osg::BoundingSphere instanceBS = osg::Group::computeBound();
+        for(int i=0; i<points->getNumElements(); ++i)
+        {
+            osg::Vec3f center( (*points)[i].x(), (*points)[i].y(), (*points)[i].z() );
+            bs.expandBy( osg::BoundingSphere(center + instanceBS.center(), instanceBS.radius()) );
+        }
+
+        OE_WARN << "BS = " << bs.center().x() << ", " << bs.center().y() << ", " << bs.center().z() << ", r=" << bs.radius() << "\n";
+        return bs;
+    }
+
+    struct Setup : public osg::NodeVisitor 
+    {
+        Setup(InstanceGroup* ig) : _ig(ig), osg::NodeVisitor()
+        {
+            setTraversalMode( TRAVERSE_ALL_CHILDREN );
+            this->setNodeMaskOverride( ~0 );
+            _count = 0;
+        }
+
+        void apply(osg::Geode& geode)
+        {
+            for(int i=0; i<geode.getNumDrawables(); ++i)
+            {
+                osg::Geometry* g = geode.getDrawable(i)->asGeometry();
+                if ( g )
+                {
+                    // Must ensure that VBOs are used:
+                    g->setUseVertexBufferObjects(true);
+                    g->setUseDisplayList(false);
+
+                    // Bind our transform feedback buffer to the geometry:
+                    g->setVertexAttribArray    ( _ig->_slot, _ig->_xfb.get() );
+                    g->setVertexAttribBinding  ( _ig->_slot, g->BIND_PER_VERTEX );
+                    g->setVertexAttribNormalize( _ig->_slot, false );
+
+                    // Set up a draw callback to intecept draw calls so we can vary 
+                    // the instance count per frame.
+                    g->setDrawCallback( _ig->_drawCallback.get() );
+
+                    // disable frustum culling because the instance doesn't have a real location
+                    g->setCullingActive(false);
+
+                    ++_count;
+                }
+            }
+        }
+
+        InstanceGroup* _ig;
+        int _count;
+    };
+    
+    unsigned _numInstances;
+    int _slot;
+    osg::ref_ptr<osg::Array> _xfb;
+    osg::ref_ptr<osg::Drawable::DrawCallback> _drawCallback;
+};
+
+
+#define XFB_SLOT 7
+
+// Generator that just writes each incoming vertex to the XFB.
+const char* VS_GENERATOR =
+    "#version " GLSL_VERSION_STR "\n"
+    "out vec4 position; \n"
+    "void main(void) { \n"
+    "    position = gl_Vertex; \n"
+    "} \n";
+
+// Geometry shader perform GPU culling on the control point set.
+// The "cullingRadius" bit isn't working quite right; not sure why atm.
+const char* GS_GENERATOR =
+    "#version " GLSL_VERSION_STR "\n"
+    "layout(points) in; \n"
+    "layout(points, max_vertices=1) out; \n"
+    "uniform float cullingRadius; \n"
+    "in vec4 position[1]; \n"
+    "out vec4 xfb_output; \n"
+    "void main(void) { \n"
+    "    vec4 vertView = gl_ModelViewMatrix * position[0]; \n"
+    "    vertView.xy -= cullingRadius*sign(vertView.xy); \n"
+    "    vec4 vertClip = gl_ProjectionMatrix * vertView; \n"
+    "    float w = abs(vertClip.w); \n"
+    "    if ( abs(vertClip.x) <= w && abs(vertClip.y) <= w && abs(vertClip.z) <= w ) { \n"
+    "        xfb_output = position[0]; \n"
+    "        EmitVertex(); \n"
+    "        EndPrimitive(); \n"
+    "    } \n"
+    "} \n";
+
+osg::Program* makeGeneratorProgram()
+{
+    osg::Program* program = new osg::Program();
+    program->addShader( new osg::Shader(osg::Shader::VERTEX, VS_GENERATOR) );
+    program->addShader( new osg::Shader(osg::Shader::GEOMETRY, GS_GENERATOR) );
+    program->addTransformFeedBackVarying( "xfb_output" );
+    program->setTransformFeedBackMode( GL_INTERLEAVED_ATTRIBS );
+
+    return program;
+}
+
+void makeVisibleVP(osg::StateSet* ss)
+{
+    VirtualProgram* vp = VirtualProgram::getOrCreate(ss);
+    vp->setFunction("oe_instancing_setPos", IG_VS, ShaderComp::LOCATION_VERTEX_MODEL, -FLT_MAX);
+    vp->addBindAttribLocation( "xfb_position", XFB_SLOT );
+}
+
+
+struct RenderToXFB : public osg::Drawable::DrawCallback
+{
+    /**
+     * Constructs a Transform Feedback draw callback.
+     *
+     * @param[in ] xfb Transform Feedback control points
+     *
+     * NOTE: You must add the XF buffer array to its final geometry (or geometries)
+     * before creating this callback. Otherwise, it will not be able to calculate
+     * a correct offset into the VBO.
+     */
+    RenderToXFB(osg::Array* xfb)
+    {
+        _vbo = xfb->getVertexBufferObject();
+        int numBufferData = _vbo->getNumBufferData();
+        _offset = 0;
+        _size = 0;
+        for(int i=0; i<numBufferData; ++i)
+        {
+            _size = _vbo->getBufferData(i)->getTotalDataSize();
+            if ( _vbo->getBufferData(i)->getDataPointer() == xfb->getDataPointer() )
+                break;
+            else
+                _offset += _size;
+        }
+        OE_DEBUG << "offset = " << _offset << "; size = " << _size << "\n";
+
+        _queries.resize(64);
+        _queries.setAllElementsTo( INT_MAX );
+    }
+    
+    void drawImplementation(osg::RenderInfo& renderInfo, const osg::Drawable* drawable) const
+    {
+        unsigned contextID = renderInfo.getState()->getContextID();
+        osg::GLBufferObject* bo = _vbo->getOrCreateGLBufferObject(contextID);
+        if ( bo->isDirty() )
+            bo->compileBuffer();
+
+        GLuint objID = bo->getGLObjectID();
+
+        osg::GLExtensions* ext = renderInfo.getState()->get<osg::GLExtensions>();
+           
+        GLuint numPrims = 0;
+        GLuint& query = _queries[contextID];
+        if ( query == INT_MAX )
+        {
+            ext->glGenQueries(1, &query);
+        }
+        else
+        {     
+        
+            ext->glGetQueryObjectuiv(query, GL_QUERY_RESULT, &numPrims);        
+            s_numInstancesToDraw = numPrims;
+        }
+
+
+        ext->glBindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, objID, _offset, _size);
+        //if ( renderInfo.getState()->checkGLErrors("PRE:glBindBufferBase") ) exit(0);
+
+        glEnable(GL_RASTERIZER_DISCARD);
+        //if ( renderInfo.getState()->checkGLErrors("PRE:glEnable(GL_RASTERIZER_DISCARD)") ) exit(0);
+
+
+        ext->glBeginQuery(TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, query);
+
+        ext->glBeginTransformFeedback(GL_POINTS); // get from input geom?
+        //if ( renderInfo.getState()->checkGLErrors("PRE:glBeginTransformFeedback(GL_POINTS)") ) exit(0);
+        
+
+        drawable->drawImplementation(renderInfo);
+
+        
+        ext->glEndTransformFeedback();
+        //if ( renderInfo.getState()->checkGLErrors("POST:glEndTransformFeedback") ) exit(0);
+        ext->glEndQuery(TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN);
+
+        glDisable(GL_RASTERIZER_DISCARD);
+        //if ( renderInfo.getState()->checkGLErrors("POST:glDisable(GL_RASTERIZER_DISCARD)") ) exit(0);
+
+        ext->glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, 0);
+        //if ( renderInfo.getState()->checkGLErrors("POST:glBindBufferBase") ) exit(0);
+
+    }
+    osg::ref_ptr<osg::BufferObject> _vbo;
+    int _offset, _size;
+    mutable osg::buffered_object<GLuint> _queries;
+};
+
+
+
+osg::Geometry* makeGeneratorGeometry(osg::Array* xfb, int dim, float width)
+{
+    osg::Geometry* geom = new osg::Geometry();
+    geom->setUseVertexBufferObjects(true);
+    geom->setUseDisplayList(false);
+
+    // input points -- 
+    osg::Vec3Array* verts = new osg::Vec3Array();
+    for(int i=0; i<dim; ++i)
+        for(int j=0; j<dim; ++j)
+            verts->push_back(osg::Vec3(i*width, j*width, 0));
+    geom->setVertexArray( verts );
+
+    osg::DrawArrays* da = new osg::DrawArrays(GL_POINTS, 0, dim*dim);
+    geom->addPrimitiveSet( da );
+
+    // Add a custom draw callback that will render the control points 
+    // into the the XF buffer. (Must add this callbacks AFTER setting up the geometry)
+    geom->setDrawCallback( new RenderToXFB(xfb) );
+
+    // Still trying to figure out exactly how this geometry gets culled -gw
+    // If you zoom to the middle of the field, it culls.
+    geom->setCullingActive(false);
+
+    return geom;
+}
+
+osg::Node* makeSceneGraph()
+{
+    osg::Group* root = new osg::Group();
+    root->getOrCreateStateSet()->setRenderBinDetails(0, "TraversalOrderBin");
+    //root->getOrCreateStateSet()->setAttributeAndModes(new osg::Point(10.0f));
+    //root->getOrCreateStateSet()->setAttributeAndModes(new osg::Depth(osg::Depth::LESS, 0, 1, false));
+    
+    // Model to instance:
+    osg::Node* instancedModel = osgDB::readNodeFile("../data/tree.ive.osgearth_shadergen");
+    float radius = instancedModel->getBound().radius();
+
+    // Reference axis.
+    //std::string axis = Stringify() << "../data/axes.osgt.(" << radius << ").scale";
+    //root->addChild( osgDB::readNodeFile(axis) );
+
+    const int dim = 256;
+    const int maxNumInstances = dim*dim;
+    OE_NOTICE "Rendering " << maxNumInstances << " instances; radius = " << radius << "\n";
+
+    // This is the group containing the instanced model. The "configure" method will set up
+    // the instance model for dynamic XFB instancing.
+    InstanceGroup* ig = new InstanceGroup();
+    ig->addChild( instancedModel );
+    ig->configure( XFB_SLOT, maxNumInstances );
+    root->addChild( ig );
+
+    // construct the geometry that will generate the instancing control points and render them
+    // into the Transform Feedback buffer.
+    osg::Geometry* genGeom = makeGeneratorGeometry( ig->getControlPoints(), dim, radius );
+    genGeom->getOrCreateStateSet()->setAttribute( makeGeneratorProgram() );
+    genGeom->getOrCreateStateSet()->addUniform( new osg::Uniform("cullingRadius", radius) ); // since we don't know where ther center point is
+    osg::Geode* genGeode = new osg::Geode();
+    genGeode->addDrawable( genGeom );    
+    
+    root->addChild( ig );
+    root->addChild( genGeode );
+
+    return root;
+}
+
+int
+main(int argc, char** argv)
+{
+    osgEarth::Registry::capabilities();
+
+    osg::ArgumentParser arguments(&argc,argv);
+    osgViewer::Viewer viewer(arguments);
+    viewer.setCameraManipulator( new osgGA::TrackballManipulator() );
+
+    viewer.addEventHandler( new osgViewer::StatsHandler() );    
+    viewer.addEventHandler( new osgGA::StateSetManipulator(viewer.getCamera()->getOrCreateStateSet()) );
+    
+    viewer.getCamera()->setSmallFeatureCullingPixelSize(-1.0f);
+
+    viewer.setSceneData( makeSceneGraph() );
+
+    viewer.run();
+}
+
+#else
+int main(int argc, char** argv)
+{
+    OSG_WARN << "Sorry, but XFB requires at least OSG 3.4.0." << std::endl;
+    return -1;
+}
+#endif
\ No newline at end of file
diff --git a/src/osgEarth/AlphaEffect b/src/osgEarth/AlphaEffect
index 6984d8f..4c8b277 100644
--- a/src/osgEarth/AlphaEffect
+++ b/src/osgEarth/AlphaEffect
@@ -60,11 +60,12 @@ namespace osgEarth
 
         typedef std::list< osg::observer_ptr<osg::StateSet> > StateSetList;
 
-        bool                       _active;
+        bool                       _installed;
         StateSetList               _statesets;
         osg::ref_ptr<osg::Uniform> _alphaUniform;
 
         void init();
+        void install(osg::StateSet*);
     };
 
 } // namespace osgEarth::Util
diff --git a/src/osgEarth/AlphaEffect.cpp b/src/osgEarth/AlphaEffect.cpp
index 5b0a325..1dbb5e6 100644
--- a/src/osgEarth/AlphaEffect.cpp
+++ b/src/osgEarth/AlphaEffect.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
@@ -29,6 +29,8 @@
 
 using namespace osgEarth;
 
+#define LC "[AlphaEffect] "
+
 AlphaEffect::AlphaEffect()
 {
     init();
@@ -43,12 +45,9 @@ AlphaEffect::AlphaEffect(osg::StateSet* stateset)
 void
 AlphaEffect::init()
 {
-    _active = Registry::capabilities().supportsGLSL(110u);
-    if ( _active )
-    {
-        _alphaUniform = new osg::Uniform(osg::Uniform::FLOAT, "oe_alphaEffect_alpha");
-        _alphaUniform->set( 1.0f );
-    }
+    _installed = false;
+    _alphaUniform = new osg::Uniform(osg::Uniform::FLOAT, "oe_alphaEffect_alpha");
+    _alphaUniform->set( 1.0f );
 }
 
 AlphaEffect::~AlphaEffect()
@@ -59,56 +58,71 @@ AlphaEffect::~AlphaEffect()
 void
 AlphaEffect::setAlpha(float value)
 {
-    if ( _active )
+    float oldValue;
+    _alphaUniform->get(oldValue);
+
+    if (value != oldValue)
+    {        
         _alphaUniform->set( value );
+
+        if (!_installed)
+        {
+            for (StateSetList::iterator it = _statesets.begin(); it != _statesets.end(); ++it)
+            {
+                osg::ref_ptr<osg::StateSet> stateset;
+                if ((*it).lock(stateset))
+                {
+                    install(stateset.get());
+                }
+            }
+            _installed = true;
+        }
+    }
 }
 
 float
 AlphaEffect::getAlpha() const
 {
     float value = 1.0f;
-    if (_active)
-        _alphaUniform->get(value);
+    _alphaUniform->get(value);
     return value;
 }
 
 void
 AlphaEffect::attach(osg::StateSet* stateset)
 {
-    if ( stateset && _active )
+    if ( stateset )
     {
         _statesets.push_back(stateset);
-        VirtualProgram* vp = VirtualProgram::getOrCreate(stateset);
-        vp->setName( "osgEarth.AlphaEffect" );
-        Shaders pkg;
-        pkg.load( vp, pkg.AlphaEffectFragment );
-        stateset->addUniform( _alphaUniform.get() );
+        if (_installed)
+        {
+            install(stateset);
+        }
     }
 }
 
 void
 AlphaEffect::detach()
 {
-    if (!_active)
-        return;
-
-    for (StateSetList::iterator it = _statesets.begin(); it != _statesets.end(); ++it)
+    if (_installed)
     {
-        osg::ref_ptr<osg::StateSet> stateset;
-        if ( (*it).lock(stateset) )
+        for (StateSetList::iterator it = _statesets.begin(); it != _statesets.end(); ++it)
         {
-            detach( stateset );
-            (*it) = 0L;
+            osg::ref_ptr<osg::StateSet> stateset;
+            if ( (*it).lock(stateset) )
+            {
+                detach( stateset );
+                (*it) = 0L;
+            }
         }
     }
-
     _statesets.clear();
 }
 
 void
 AlphaEffect::detach(osg::StateSet* stateset)
 {
-    if ( stateset && _active )
+    if ( stateset && _installed )
     {
         stateset->removeUniform( _alphaUniform.get() );
         VirtualProgram* vp = VirtualProgram::get( stateset );
@@ -119,3 +133,19 @@ AlphaEffect::detach(osg::StateSet* stateset)
         }
     }
 }
+
+void
+AlphaEffect::install(osg::StateSet* stateset)
+{
+    if (stateset)
+    {
+        VirtualProgram* vp = VirtualProgram::getOrCreate(stateset);
+        if (vp)
+        {
+            vp->setName( "osgEarth.AlphaEffect" );
+            Shaders pkg;
+            pkg.load(vp, pkg.AlphaEffectFragment);
+            stateset->addUniform(_alphaUniform.get());
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/osgEarth/AlphaEffect.frag.glsl b/src/osgEarth/AlphaEffect.frag.glsl
index 7a3501a..1c90358 100644
--- a/src/osgEarth/AlphaEffect.frag.glsl
+++ b/src/osgEarth/AlphaEffect.frag.glsl
@@ -1,8 +1,8 @@
-#version 110
+#version $GLSL_VERSION_STR
 
-#pragma vp_entryPoint "oe_alphaEffect_frag"
-#pragma vp_location   "fragment_coloring"
-#pragma vp_order      "0.5"
+#pragma vp_entryPoint oe_alphaEffect_frag
+#pragma vp_location   fragment_coloring
+#pragma vp_order      0.5
 
 uniform float oe_alphaEffect_alpha;
 
diff --git a/src/osgEarth/AutoScale b/src/osgEarth/AutoScale
index a2cfa7b..1bdbe4c 100644
--- a/src/osgEarth/AutoScale
+++ b/src/osgEarth/AutoScale
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
@@ -28,6 +28,9 @@
 namespace osgEarth
 {
     /**
+     * @deprecated
+     * Consider GeoPositionNodeAutoScaler instead
+     *
      * Usage: set your render bin to AUTO_SCALE_BIN and your
      * geometry will automatically draw at one pixel per meter.
      *
diff --git a/src/osgEarth/AutoScale.cpp b/src/osgEarth/AutoScale.cpp
index 21b32ff..7dbdbe5 100644
--- a/src/osgEarth/AutoScale.cpp
+++ b/src/osgEarth/AutoScale.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -82,7 +82,7 @@ namespace
             _stateset = new osg::StateSet();
 
             VirtualProgram* vp = VirtualProgram::getOrCreate(_stateset.get());
-            vp->setFunction( "oe_autoscale_vertex", vs, ShaderComp::LOCATION_VERTEX_VIEW, 0.5f );
+            vp->setFunction( "oe_autoscale_vertex", vs, ShaderComp::LOCATION_VERTEX_VIEW, 0L, 0.5f );
 
             _zp = _stateset->getOrCreateUniform("oe_autoscale_zp", osg::Uniform::FLOAT);
         }
@@ -134,5 +134,5 @@ namespace
 }
 
 /** static registration of the bin */
-extern "C" void osgEarth_AutoScaleBin_registration(void) {}
-static osgEarthRegisterRenderBinProxy<AutoScaleRenderBin> s_regbin(AUTO_SCALE_BIN_NAME);
+//extern "C" void osgEarth_AutoScaleBin_registration(void) {}
+//static osgEarthRegisterRenderBinProxy<AutoScaleRenderBin> s_regbin(AUTO_SCALE_BIN_NAME);
diff --git a/src/osgEarth/Bounds b/src/osgEarth/Bounds
index 425c826..5e5e5f5 100644
--- a/src/osgEarth/Bounds
+++ b/src/osgEarth/Bounds
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarth/Bounds.cpp b/src/osgEarth/Bounds.cpp
index b7cfec2..3f5a8b0 100644
--- a/src/osgEarth/Bounds.cpp
+++ b/src/osgEarth/Bounds.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarth/CMakeLists.txt b/src/osgEarth/CMakeLists.txt
index fbc3ac7..4104e34 100644
--- a/src/osgEarth/CMakeLists.txt
+++ b/src/osgEarth/CMakeLists.txt
@@ -9,12 +9,21 @@ MARK_AS_ADVANCED(CURL_IS_STATIC)
 
 ADD_DEFINITIONS(-DTIXML_USE_STL)
 
+# Builds the HTTPClient with WIN_INET instead of CURL
+OPTION(OSGEARTH_USE_WININET_FOR_HTTP "Whether to use the WinInet library for HTTP requests (instead of cURL)" OFF)
+if (OSGEARTH_USE_WININET_FOR_HTTP)
+    ADD_DEFINITIONS(-DOSGEARTH_USE_WININET_FOR_HTTP)
+endif (OSGEARTH_USE_WININET_FOR_HTTP)
+
 IF(WIN32)
-    SET(CMAKE_SHARED_LINKER_FLAGS_DEBUG "${CMAKE_SHARED_LINKER_FLAGS_DEBUG} /NODEFAULTLIB:MSVCRT")
+    IF(MSVC)
+        SET(CMAKE_SHARED_LINKER_FLAGS_DEBUG "${CMAKE_SHARED_LINKER_FLAGS_DEBUG} /NODEFAULTLIB:MSVCRT")
+    ENDIF(MSVC)
     IF(CURL_IS_STATIC)
         ADD_DEFINITIONS(-DCURL_STATICLIB)
         SET(TARGET_EXTERNAL_LIBRARIES ws2_32 winmm wldap32)
     ENDIF(CURL_IS_STATIC)
+    LIST(APPEND TARGET_EXTERNAL_LIBRARIES psapi)
 ENDIF(WIN32)
 
 SET(LIB_NAME osgEarth)
@@ -62,26 +71,28 @@ SET(LIB_PUBLIC_HEADERS
     Cube
     CullingUtils
     DateTime
-    Decluttering
+    DateTimeRange
     DepthOffset
     DPLineSegmentIntersector
     DrapeableNode
+    DrapingCullSet
     DrapingTechnique
     DrawInstanced
     ECEF
-    ElevationField
     ElevationLayer
     ElevationLOD
     ElevationQuery
     Export
-	Extension
+    Extension
     FadeEffect
     FileUtils
     GeoCommon
     GeoData
     Geoid
     GeoMath
-	GeoTransform
+    GeoTransform
+    GeometryClamper
+    GLSLChunker
     HeightFieldUtils
     Horizon
     HTTPClient
@@ -107,6 +118,7 @@ SET(LIB_PUBLIC_HEADERS
     MaskLayer
     MaskNode
     MaskSource
+    Memory
     MemCache
     ModelLayer
     ModelSource
@@ -117,25 +129,30 @@ SET(LIB_PUBLIC_HEADERS
     ObjectIndex
     OverlayDecorator
     OverlayNode
-	PhongLightingEffect
+    PhongLightingEffect
     Picker
     IntersectionPicker
     PrimitiveIntersector
     Profile
     Profiler
     Progress
+    QuadTree
     Random
     Registry
+    ResourceReleaser
     Revisioning
+    ScreenSpaceLayout
     Shaders
     ShaderFactory
     ShaderGenerator
     ShaderLoader
     ShaderUtils
-	SharedSARepo
+    Shadowing
+    SharedSARepo
     SpatialReference
     StateSetCache
-	StateSetLOD
+    StateSetLOD
+    Status
     StringUtils
     TaskService
     Terrain
@@ -143,12 +160,17 @@ SET(LIB_PUBLIC_HEADERS
     TerrainLayer
     TerrainOptions
     TerrainEngineNode
+    TerrainEngineRequirements
+    TerrainTileModel
+    TerrainTileModelFactory
     TerrainTileNode
+    TileKeyDataStore
+    TilePatchCallback
     Tessellator
     TextureCompositor
     TileKey
     TileHandler
-	TileSource
+    TileSource
     TileVisitor
     TimeControl
     TraversalData
@@ -200,6 +222,7 @@ set(TARGET_SRC
     AutoScale.cpp
     Bounds.cpp
     Cache.cpp
+    CacheBin.cpp
     CacheEstimator.cpp
     CachePolicy.cpp
     CacheSeed.cpp
@@ -213,24 +236,26 @@ set(TARGET_SRC
     Cube.cpp
     CullingUtils.cpp
     DateTime.cpp
-    Decluttering.cpp
+    DateTimeRange.cpp
     DepthOffset.cpp
     DPLineSegmentIntersector.cpp
     DrapeableNode.cpp
+    DrapingCullSet.cpp
     DrapingTechnique.cpp
     DrawInstanced.cpp
     ECEF.cpp
-    ElevationField.cpp
     ElevationLayer.cpp
     ElevationLOD.cpp
     ElevationQuery.cpp
-	Extension.cpp
+    Extension.cpp
     FadeEffect.cpp
     FileUtils.cpp
     GeoData.cpp
     Geoid.cpp
     GeoMath.cpp
-	GeoTransform.cpp
+    GeoTransform.cpp
+    GeometryClamper.cpp
+    GLSLChunker.cpp
     HeightFieldUtils.cpp
     Horizon.cpp
     HTTPClient.cpp
@@ -254,6 +279,7 @@ set(TARGET_SRC
     MaskNode.cpp
     MaskSource.cpp
     MemCache.cpp
+    Memory.cpp
     MimeTypes.cpp
     ModelLayer.cpp
     ModelSource.cpp
@@ -262,32 +288,41 @@ set(TARGET_SRC
     ObjectIndex.cpp
     OverlayDecorator.cpp
     OverlayNode.cpp
-	PhongLightingEffect.cpp
+    PhongLightingEffect.cpp
     IntersectionPicker.cpp
     PrimitiveIntersector.cpp
     Profile.cpp
     Profiler.cpp
     Progress.cpp
+    QuadTree.cpp
     Random.cpp
     Registry.cpp
+    ResourceReleaser.cpp
     Revisioning.cpp
+    ScreenSpaceLayout.cpp
     ShaderFactory.cpp
     ShaderGenerator.cpp
     ShaderLoader.cpp
     ShaderUtils.cpp
+    Shadowing.cpp
     SpatialReference.cpp
     StateSetCache.cpp
-	StateSetLOD.cpp
+    StateSetLOD.cpp
+    Status.cpp
     StringUtils.cpp
     TaskService.cpp
     Terrain.cpp
     TerrainLayer.cpp
     TerrainOptions.cpp
     TerrainEngineNode.cpp
+    TerrainTileModel.cpp
+    TerrainTileModelFactory.cpp
     Tessellator.cpp
+    TextureBufferSerializer.cpp
     TextureCompositor.cpp
     TileKey.cpp
     TileHandler.cpp
+    TilePatchCallback.cpp
     TileVisitor.cpp
     TileSource.cpp
     TimeControl.cpp
@@ -305,11 +340,11 @@ set(TARGET_SRC
 
 
 ADD_LIBRARY(
-	${LIB_NAME} ${OSGEARTH_USER_DEFINED_DYNAMIC_OR_STATIC}
+    ${LIB_NAME} ${OSGEARTH_USER_DEFINED_DYNAMIC_OR_STATIC}
     ${LIB_PUBLIC_HEADERS}
     ${TINYXML_SRC}
     ${VERSION_GIT_SOURCE}
-	${TARGET_SRC}
+    ${TARGET_SRC}
     ${TARGET_GLSL}
     ${TARGET_IN} )
 
diff --git a/src/osgEarth/Cache b/src/osgEarth/Cache
index a3979db..10d36c6 100644
--- a/src/osgEarth/Cache
+++ b/src/osgEarth/Cache
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
@@ -25,10 +25,12 @@
 
 #include <osgEarth/Common>
 #include <osgEarth/CacheBin>
+#include <osgEarth/CachePolicy>
 #include <osgEarth/Config>
 #include <osgEarth/TileKey>
 #include <osgEarth/Containers>
 #include <sys/types.h>
+#include <map>
 
 // environment variables
 #define OSGEARTH_ENV_CACHE_DRIVER  "OSGEARTH_CACHE_DRIVER"
@@ -39,6 +41,70 @@
 
 namespace osgEarth
 {
+#define DEFAULT_BIN_ID ""
+
+    class Cache;
+    class CachePolicy;
+
+    /**
+     * CacheSettings is an object stored in the osgDB::Options structure that
+     * propagates throughout the osgEarth data model. It represents a Cache state
+     * that includes the actual Cache, the active CacheBin, and a policy.
+     */
+    class OSGEARTH_EXPORT CacheSettings : public osg::Object
+    {
+    public:
+        META_Object(osgEarth,CacheSettings);
+
+        typedef UID ID;
+
+        typedef std::string BinID;
+
+        /** default constructor */
+        CacheSettings();
+
+        /** copier */
+        CacheSettings(const CacheSettings& rhs, const osg::CopyOp& copy =osg::CopyOp::SHALLOW_COPY);
+
+        /** Whether this object support an active cache. */
+        bool isCacheEnabled() const;
+        bool isCacheDisabled() const { return !isCacheEnabled(); }
+        
+        /** Cache used by these settings */
+        Cache* getCache() const { return _cache.get(); }
+        void setCache(Cache* cache) { _cache = cache; }
+
+        /** Sets the active cache bin to use under these settings. */
+        void setCacheBin(CacheBin* bin) { _activeBin = bin; }
+        CacheBin* getCacheBin() { return _activeBin.get(); }
+
+        /** The caching policy in effect for all bins; this starts out the same as
+          * defaultCachePolicy() but you can change it. */
+        optional<CachePolicy>& cachePolicy() { return _policy; }
+        const optional<CachePolicy>& cachePolicy() const { return _policy; }
+
+        /** Integrates an outside cache policy with the one in these settings. This method
+          * also takes care of global (registry) override policy. */
+        void integrateCachePolicy(const optional<CachePolicy>& policy);
+        
+        /** Get/Set the settings in a read-options structure. */
+        static CacheSettings* get(const osgDB::Options* readOptions);
+        void store(osgDB::Options* readOptions);
+
+        /** for debugging */
+        std::string toString() const;
+
+    protected:
+        virtual ~CacheSettings() { }
+
+        osg::ref_ptr<Cache>      _cache;
+        osg::ref_ptr<CacheBin>   _activeBin;
+        optional<CachePolicy>    _policy;
+        mutable Threading::Mutex _mutex;
+    };
+
+//--------------------------------------------------------------------
+
     /**
      * Base class for Cache options.
      */
@@ -84,7 +150,6 @@ namespace osgEarth
     protected:
         Cache( const CacheOptions& options =CacheOptions() );
         Cache( const Cache& rhs, const osg::CopyOp& op =osg::CopyOp::DEEP_COPY_ALL );
-        META_Object( osgEarth, Cache );
 
         /** dtor */
         virtual ~Cache();
@@ -110,11 +175,11 @@ namespace osgEarth
         virtual CacheBin* getOrCreateDefaultBin() { return _defaultBin.get(); }
 
         /**
-         * Creates (and returns a pointer to) a new Cache Bin.
+         * Creates (and returns a pointer to) a new Cache Bin, or returns an
+         * already-existing one with that ID.
          * @param binID Name of the new bin
-         * @param rw    Read/write driver that will handle serialization for the bin
          */
-        virtual CacheBin* addBin( const std::string& binID ) { return 0L; }
+        virtual CacheBin* addBin(const std::string& binID) =0;
 
         /**
          * Removes a cache bin from the cache.
@@ -144,20 +209,6 @@ namespace osgEarth
          */
         virtual bool clear() { return false; }
 
-        /**
-         * Store this to an osgDB::Options
-         */
-        void apply( osgDB::Options* options ) {
-            if ( options ) options->setPluginData( "osgEarth::Cache", this );
-        }
-
-        /**
-         * Fetch pointer from a osgDB::Options
-         */
-        static Cache* get( const osgDB::Options* options ) {
-            return options ? const_cast<Cache*>( static_cast<const Cache*>( options->getPluginData("osgEarth::Cache") ) ) : 0L;
-        }
-
     protected:
         bool                   _ok;
         CacheOptions           _options;
diff --git a/src/osgEarth/Cache.cpp b/src/osgEarth/Cache.cpp
index 7cde03e..aacb299 100644
--- a/src/osgEarth/Cache.cpp
+++ b/src/osgEarth/Cache.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -20,22 +20,97 @@
 #include <osgEarth/Registry>
 #include <osgEarth/ThreadingUtils>
 
+#include <osg/UserDataContainer>
 #include <osgDB/FileNameUtils>
 #include <osgDB/FileUtils>
 #include <osgDB/ReadFile>
 #include <osgDB/Registry>
+#include <osgDB/ReaderWriter>
 
 using namespace osgEarth;
 using namespace osgEarth::Threading;
 
 #define LC "[Cache] "
 
+//------------------------------------------------------------------------
+
 CacheOptions::~CacheOptions()
 {
 }
 
 //------------------------------------------------------------------------
 
+#define CACHESETTINGS_UDC_NAME "osgEarth.CacheSettings"
+
+CacheSettings::CacheSettings()
+{
+    setName(CACHESETTINGS_UDC_NAME);
+}
+
+CacheSettings::CacheSettings(const CacheSettings& rhs, const osg::CopyOp& copy) :
+osg::Object(rhs, copy),
+_cache(rhs._cache.get()),
+_policy(rhs._policy),
+_activeBin(rhs._activeBin.get())
+{
+    //nop
+}
+        
+bool
+CacheSettings::isCacheEnabled() const
+{
+    return _cache.valid() && _policy->isCacheEnabled();
+}
+
+void
+CacheSettings::integrateCachePolicy(const optional<CachePolicy>& policy)
+{
+    // integrate the fields that are passed in first:
+    if ( policy.isSet() )
+        cachePolicy()->mergeAndOverride( policy );
+
+    // then resolve with global overrides from the registry.
+    Registry::instance()->resolveCachePolicy( cachePolicy() );
+}
+
+void
+CacheSettings::store(osgDB::Options* readOptions)
+{
+    if (readOptions)
+    {
+        osg::UserDataContainer* udc = readOptions->getOrCreateUserDataContainer();
+        unsigned index = udc->getUserObjectIndex(CACHESETTINGS_UDC_NAME);
+        udc->removeUserObject(index);
+        udc->addUserObject(this);
+    }
+}
+ 
+CacheSettings*
+CacheSettings::get(const osgDB::Options* readOptions)
+{
+    CacheSettings* obj = 0L;
+    if (readOptions)
+    {
+        const osg::UserDataContainer* udc = readOptions->getUserDataContainer();
+        if (udc) {
+            osg::Object* temp = const_cast<osg::Object*>(udc->getUserObject(CACHESETTINGS_UDC_NAME));
+            obj = dynamic_cast<CacheSettings*>(temp);
+        }
+    }
+    return obj;
+}
+
+std::string
+CacheSettings::toString() const
+{
+    return Stringify()
+        << "cache=" << (_cache.valid() ? _cache->className() : "none")
+        << "; policy=" << _policy->usageString()
+        << "; bin=" << (_activeBin.get() ? "yes" : "no");
+}
+
+//------------------------------------------------------------------------
+
 Cache::Cache( const CacheOptions& options ) :
 _ok     ( true ),
 _options( options )
@@ -95,7 +170,7 @@ CacheFactory::create( const CacheOptions& options )
         std::string driverExt = std::string(".osgearth_cache_") + options.getDriver();
         osgDB::ReaderWriter::ReadResult rr = osgDB::readObjectFile( driverExt, rwopt.get() );
         result = dynamic_cast<Cache*>( rr.getObject() );
-        if ( !result )
+        if ( !result.valid() )
         {
             OE_WARN << LC << "Failed to load cache plugin for type \"" << options.getDriver() << "\"" << std::endl;
         }
@@ -108,9 +183,13 @@ CacheFactory::create( const CacheOptions& options )
 const CacheOptions&
 CacheDriver::getCacheOptions( const osgDB::ReaderWriter::Options* rwopt ) const 
 {
-    return *static_cast<const CacheOptions*>( rwopt->getPluginData( CACHE_OPTIONS_TAG ) );
+    static CacheOptions s_default;
+    const void* data = rwopt->getPluginData(CACHE_OPTIONS_TAG);
+    return data ? *static_cast<const CacheOptions*>(data) : s_default;
 }
 
 CacheDriver::~CacheDriver()
 {
 }
+
+//------------------------------------------------------------------------
diff --git a/src/osgEarth/CacheBin b/src/osgEarth/CacheBin
index fae3516..56c15a0 100644
--- a/src/osgEarth/CacheBin
+++ b/src/osgEarth/CacheBin
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
@@ -34,7 +34,7 @@ namespace osgEarth
      * application modules to compartmentalize their data withing a single
      * cache location.
      */
-    class /*no export*/ CacheBin : public osg::Referenced
+    class OSGEARTH_EXPORT CacheBin : public osg::Referenced
     {
     public:
         /** returned by the getRecordStatus() function */
@@ -51,7 +51,7 @@ namespace osgEarth
          * @param driver ReaderWriter that serializes data for this caching bin.
          */
         CacheBin( const std::string& binID )
-            : _binID(binID), _hashKeys(false), _minTime(0) { }
+            : _binID(binID), _hashKeys(true), _minTime(0) { }
 
         /** dtor */
         virtual ~CacheBin() { }
@@ -72,29 +72,41 @@ namespace osgEarth
          * Reads an object from the cache bin.
          * @param key     Lookup key to read         
          */
-        virtual ReadResult readObject(const std::string& key) =0;
+        virtual ReadResult readObject(const std::string& key, const osgDB::Options* dbo) =0;
 
         /**
          * Reads an image from the cache bin.
          * @param key     Lookup key to read         
          */
-        virtual ReadResult readImage(const std::string& key) =0;
+        virtual ReadResult readImage(const std::string& key, const osgDB::Options* dbo) = 0;
 
         /**
          * Reads a string buffer from the cache bin.
          * @param key    Lookup key to read.
          */
-        virtual ReadResult readString(const std::string& key) =0;
+        virtual ReadResult readString(const std::string& key, const osgDB::Options* dbo) = 0;
 
         /**
          * Writes an object (or an image) to the cache bin.
          * @param key    Lookup key to write to
          * @param object Object to serialize to the cache
          */
-        virtual bool write( 
-            const std::string& key, 
-            const osg::Object* object,
-            const Config&      metadata =Config() ) =0;
+        virtual bool write(
+            const std::string&    key,
+            const osg::Object*    object,
+            const Config&         metadata,
+            const osgDB::Options* dbo) = 0;
+
+        bool write(
+            const std::string&    key,
+            const osg::Object*    object,
+            const osgDB::Options* dbo) { return write(key, object, Config(), dbo); }
+
+        bool writeNode(
+            const std::string&    key,
+            osg::Node*            node,
+            const Config&         metadata,
+            const osgDB::Options* writeOptions);
 
         /**
          * Gets the status of a key, i.e. not found, valid or expired.
@@ -130,30 +142,28 @@ namespace osgEarth
         virtual bool clear() { return false; }
 
         /**
-         * Compacts the cache bin (where applicable)
+         * Compacts the cache bin (where applicable in the implementation,
+         * no-op otherwise)
          */
         virtual bool compact() { return false; }
 
         /**
          * Returns the approximate disk space being used by this cache,
-         * or 0 if unavailable.
+         * or 0 if the information is unavailable.
          */
         virtual unsigned getStorageSize() { return 0u; }
 
         /**
-         * Store this pointer in an options structure
+         * Metadata associated with a cache bin.
          */
-        void apply( osgDB::Options* options ) const {
-            if ( options ) options->setPluginData( "osgEarth::CacheBin", (void*)this );
-        }
-
+        void setMetadata(osg::Referenced* data) { _metadata = data; }
+        osg::Referenced* getMetadata() { return _metadata.get(); }
+        
         /**
-         * Retrieve pointer from an options struture
+         * If key-hashing is enabled, this method returns the hashed key
+         * corresponding to a raw input key.
          */
-        static CacheBin* get( const osgDB::Options* options ) {
-            return options ? const_cast<CacheBin*>(static_cast<const CacheBin*>(options->getPluginData("osgEarth::CacheBin"))) : 0L;
-        }
-
+        virtual std::string getHashedKey(const std::string& key) const =0;
 
     public: //deprecated
 
@@ -165,6 +175,7 @@ namespace osgEarth
         std::string _binID;
         bool        _hashKeys;
         TimeStamp   _minTime;
+        osg::ref_ptr<osg::Referenced> _metadata;
     };
 }
 
diff --git a/src/osgEarth/CacheBin.cpp b/src/osgEarth/CacheBin.cpp
new file mode 100644
index 0000000..a2faf82
--- /dev/null
+++ b/src/osgEarth/CacheBin.cpp
@@ -0,0 +1,379 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+ * Copyright 2016 Pelican Mapping
+ * http://osgearth.org
+ *
+ * osgEarth is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ */
+#include <osgEarth/CacheBin>
+#include <osgEarth/ImageUtils>
+#include <osgEarth/ThreadingUtils>
+#include <osgEarth/Registry>
+#include <osgEarth/Cache>
+
+#include <osgDB/ReaderWriter>
+#include <osgDB/FileNameUtils>
+#include <osgDB/Registry>
+#include <osg/NodeVisitor>
+#include <osg/Texture>
+#include <osg/Image>
+#include <osg/TextureBuffer>
+
+using namespace osgEarth;
+
+namespace
+{
+#undef  LC
+#define LC "[PrepareForCaching] "
+    
+    /**
+     * Visitor that preps a scene graph for writing to the cache. 
+     *
+     * There are various things that need to happen:
+     *
+     * - Remove any user data containers, since these will not serialize and
+     *   will cause the OSG serializer to fail.
+     *
+     * - Replace texture image filenames to point at objects in the cache.
+     *   Before doing this, however, you need to run the WriteImagesToCache
+     *   visitor.
+     */
+    struct PrepareForCaching : public osg::NodeVisitor
+    {
+        unsigned _textures;         // profiling 
+        unsigned _userDataClears;   // profiling
+
+        PrepareForCaching() : osg::NodeVisitor()
+        {
+            setTraversalMode(TRAVERSE_ALL_CHILDREN);
+            setNodeMaskOverride(~0);
+            _textures = 0;
+            _userDataClears = 0;
+        }
+
+        void apply(osg::Node& node)
+        {
+            apply(node.getStateSet());
+            applyUserData(node);
+            traverse(node);
+        }
+
+        void apply(osg::Geode& geode)
+        {
+            for (unsigned i = 0; i < geode.getNumDrawables(); ++i)
+            {
+                apply(geode.getDrawable(i));
+            }
+            apply(static_cast<osg::Node&>(geode));
+        }
+
+        void apply(osg::Drawable* drawable)
+        {
+            if (!drawable) return;
+            apply(drawable->getStateSet());
+            applyUserData(*drawable);
+            
+            osg::Geometry* geom = drawable->asGeometry();
+            if (geom)
+                apply(geom);
+        }
+
+        void apply(osg::Geometry* geom)
+        {
+            // This detects any NULL vertex attribute arrays and then populates them.
+            // Do this because a NULL VAA will crash the OSG serialization reader (osg 3.4.0)
+            osg::Geometry::ArrayList& arrays = geom->getVertexAttribArrayList();
+            for (osg::Geometry::ArrayList::iterator i = arrays.begin(); i != arrays.end(); ++i)
+            {
+                if (i->get() == 0L)
+                {
+                    *i = new osg::FloatArray();
+                    i->get()->setBinding( osg::Array::BIND_OFF );
+                }
+            }
+        }
+
+        void apply(osg::StateSet* ss)
+        {
+            if (!ss) return;
+
+            osg::StateSet::AttributeList& a0 = ss->getAttributeList();
+            for (osg::StateSet::AttributeList::iterator i = a0.begin(); i != a0.end(); ++i)
+            {
+                osg::StateAttribute* sa = i->second.first.get();
+                applyUserData(*sa);
+            }
+
+            // Disable the texture image-unref feature so we can share the resource 
+            // across cached tiles.
+            osg::StateSet::TextureAttributeList& a = ss->getTextureAttributeList();
+            for (osg::StateSet::TextureAttributeList::iterator i = a.begin(); i != a.end(); ++i)
+            {       
+                osg::StateSet::AttributeList& b = *i;
+                for (osg::StateSet::AttributeList::iterator j = b.begin(); j != b.end(); ++j)
+                {
+                    osg::StateAttribute* sa = j->second.first.get();
+                    if (sa)
+                    {
+                        osg::Texture* tex = dynamic_cast<osg::Texture*>(sa);
+                        if (tex)
+                        {              
+                            tex->setUnRefImageDataAfterApply(false);               
+
+                            // OSG's DatabasePager attaches "marker objects" to Textures' UserData when it runs a
+                            // FindCompileableGLObjectsVisitor. This operation is not thread-safe; it doesn't
+                            // account for the possibility that the texture may already be in use elsewhere.
+                            //
+                            // To prevent a threading violation, and the ensuing crash that reliably occurs
+                            // in Release mode (but not Debug for whatever reason) we are forced to make a
+                            // shallow clone of the Texture object and use that for serialization instead of
+                            // the original, since the original may change in the middle of the process.
+                            // We then replace the original with our close locally and serialize it safely.
+                            //
+                            // This "hack" prevents a crash in OSG 3.4.0 when trying to modify and then write
+                            // serialize the scene graph containing these shared texture objects.
+                            // Kudos to Jason B for figuring this one out.
+
+                            osg::Texture* texClone = osg::clone(tex, osg::CopyOp::SHALLOW_COPY);
+                            if ( texClone )
+                            {
+                                for (unsigned k = 0; k < texClone->getNumImages(); ++k)
+                                {
+                                    osg::Image* image = texClone->getImage(k);
+                                    if ( image )
+                                    {
+                                        applyUserData(*image);
+                                    }
+                                }
+
+                                applyUserData(*texClone);
+
+                                j->second.first = texClone;
+                            }
+                            else
+                            {
+                                OE_WARN << LC << "Texture clone failed.\n";
+                            }
+                        }
+                        else
+                        {
+                            applyUserData(*sa);
+                        }
+                    }
+                }
+            }
+
+            applyUserData(*ss);
+        }
+
+        void applyUserData(osg::Object& object)
+        {
+            if (object.getUserData())
+            {
+                _userDataClears++;
+            }
+            object.setUserDataContainer(0L);
+        }
+    };
+
+    
+#undef  LC
+#define LC "[WriteImagesToCache] "
+        
+    /**
+     * Traverses a graph, located externally referenced images, and writes
+     * them to the cache using a unique cache key. Then this will change the
+     * image's FileName to point at the cached image instead of the original
+     * source. The caches image key includes the .osgearth_cachebin extension,
+     * which will invoke a pseudoloader that redirects the read to the cache bin.
+     *
+     * When you later go to read from the cache, the CacheBin must
+     * be in the osgDB::Options used to invoke the read.
+     */
+    struct WriteExternalReferencesToCache : public osgEarth::TextureAndImageVisitor
+    {
+        CacheBin*               _bin;
+        const osgDB::Options*   _writeOptions;
+        static Threading::Mutex _globalMutex;
+
+        // constructor
+        WriteExternalReferencesToCache(CacheBin* bin, const osgDB::Options* writeOptions)
+            : TextureAndImageVisitor(), _bin(bin), _writeOptions(writeOptions)
+        {
+            setTraversalMode( TRAVERSE_ALL_CHILDREN );
+            setNodeMaskOverride( ~0L );
+        }
+
+        void apply(osg::Texture& tex)
+        {
+            if (dynamic_cast<osg::TextureBuffer*>(&tex) != 0L)
+            {
+                // skip texture buffers, they need no prep and 
+                // will be inlined as long as they have a write hint
+                // set to STORE_INLINE.
+            }
+            else
+            {
+                osgEarth::TextureAndImageVisitor::apply(tex);
+            }
+        }
+
+        void apply(osg::Image& image)
+        {
+            std::string path = image.getFileName();
+            if (path.empty())
+            {
+                OE_WARN << LC << "ERROR image with blank filename.\n";
+            }
+
+            if (!osgEarth::endsWith(path, ".osgearth_cachebin"))
+            {
+                // take a plugin-global mutex to avoid two threads altering the image
+                // at the same time
+                Threading::ScopedMutexLock lock(_globalMutex);
+
+                if (!osgEarth::endsWith(path, ".osgearth_cachebin"))
+                {
+                    // get the hashed key that the cache bin will use to actually write the image,
+                    // and replace the image filename with it.
+                    std::string cacheKey = path;
+                    std::string hashKey = _bin->getHashedKey(cacheKey);
+
+                    // Append the pseudoloader suffix so our PL can locate the image in the cache.
+                    image.setFileName(cacheKey + ".osgearth_cachebin");
+                    image.setWriteHint(osg::Image::EXTERNAL_FILE);
+
+                    // If an object with the same key is already cached, skip it.
+                    CacheBin::RecordStatus rs = _bin->getRecordStatus(cacheKey);
+                    if (rs != CacheBin::STATUS_OK)
+                    {
+                        // The OSGB serializer won't actually write the image data without this:
+                        osg::ref_ptr<osgDB::Options> dbo = Registry::cloneOrCreateOptions(_writeOptions);
+                        dbo->setPluginStringData("WriteImageHint", "IncludeData");
+
+                        OE_INFO << LC << "Writing image \"" << image.getFileName() << "\" to the cache\n";
+
+                        if (!_bin->write(cacheKey, &image, dbo.get()))
+                        {
+                            OE_WARN << LC << "...error, write failed!\n";
+                        }
+                    }
+                    else
+                    {
+                        //OE_INFO << LC << "..Image \"" << path << "\" already cached\n";
+                    }
+                }
+            }
+        }
+    };
+
+    
+    Threading::Mutex WriteExternalReferencesToCache::_globalMutex;
+}
+
+
+bool
+CacheBin::writeNode(const std::string&    key,
+                    osg::Node*            node,
+                    const Config&         metadata,
+                    const osgDB::Options* writeOptions)
+{
+    // Preparation step - removes things like UserDataContainers
+    PrepareForCaching prep;
+    node->accept( prep );
+
+    // Write external refs (like texture images) to the cache bin
+    WriteExternalReferencesToCache writeRefs(this, writeOptions);
+    node->accept( writeRefs );
+
+    // finally, write the graph to the bin:
+    write(key, node, metadata, writeOptions);
+
+    return true;
+}
+
+
+#undef  LC
+#define LC "[ReadImageFromCachePseudoLoader] "
+
+namespace
+{
+    /**
+     * Pseudoloader that looks for anything with an "osgearth_cachebin" extension
+     * and tries to load it from a CacheBin stored in the Options. This is useful
+     * when caching nodes that reference external texture images that are also
+     * stored in the cache bin.
+     *
+     * For this to work, you must change the image filenames in your graph so that
+     * they are in the form "cachekey.osgearth_cachebin". Then the pseudoloader will
+     * intercept the load and load them from the cache. Obviously this requires that
+     * you write both the images and the graph to the same cachebin during the
+     * same operation.
+     */
+    struct osgEarthReadImageFromCachePseudoLoader : public osgDB::ReaderWriter
+    {
+        osgEarthReadImageFromCachePseudoLoader()
+        {
+            this->supportsExtension("osgearth_cachebin", "osgEarth CacheBin Pseudoloader");
+        }
+
+        ReadResult readObject(const std::string& url, const osgDB::Options* readOptions) const
+        {
+            if (osgDB::getLowerCaseFileExtension(url) != "osgearth_cachebin")
+                return ReadResult::FILE_NOT_HANDLED;
+
+            CacheSettings* cacheSettings = CacheSettings::get(readOptions);
+            if (!cacheSettings || !cacheSettings->isCacheEnabled() || !cacheSettings->getCacheBin())
+            {
+                return ReadResult::FILE_NOT_FOUND;
+            }
+
+            std::string key = osgDB::getNameLessExtension(url);
+            
+            OE_DEBUG << LC << "Reading \"" << key << "\"\n";
+
+            osgEarth::ReadResult rr = cacheSettings->getCacheBin()->readObject(key, readOptions);
+            
+            return rr.succeeded() ?
+                ReadResult(rr.getObject()) :
+                ReadResult::FILE_NOT_FOUND;
+        }
+
+        ReadResult readImage(const std::string& url, const osgDB::Options* readOptions) const
+        {
+            if (osgDB::getLowerCaseFileExtension(url) != "osgearth_cachebin")
+                return ReadResult::FILE_NOT_HANDLED;
+            
+            CacheSettings* cacheSettings = CacheSettings::get(readOptions);
+            if (!cacheSettings || !cacheSettings->isCacheEnabled() || !cacheSettings->getCacheBin())
+            {
+                OE_DEBUG << LC << "Cache not enabled...!\n";
+                return ReadResult::FILE_NOT_FOUND;
+            }
+
+            std::string key = osgDB::getNameLessExtension(url);
+            
+            OE_DEBUG << LC << "Reading \"" << key << "\"\n";
+
+            osgEarth::ReadResult rr = cacheSettings->getCacheBin()->readImage(key, readOptions);
+            
+            return rr.succeeded() ?
+                ReadResult(rr.getImage()) :
+                ReadResult::FILE_NOT_FOUND;
+        }
+    };
+
+    REGISTER_OSGPLUGIN(osgearth_cachebin, osgEarthReadImageFromCachePseudoLoader);
+
+}
diff --git a/src/osgEarth/CacheEstimator b/src/osgEarth/CacheEstimator
index f9781de..4639ec9 100644
--- a/src/osgEarth/CacheEstimator
+++ b/src/osgEarth/CacheEstimator
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarth/CacheEstimator.cpp b/src/osgEarth/CacheEstimator.cpp
index 51d5aa1..e5ba765 100644
--- a/src/osgEarth/CacheEstimator.cpp
+++ b/src/osgEarth/CacheEstimator.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -60,7 +60,7 @@ CacheEstimator::getNumTiles() const
         }
         else
         {
-            for (std::vector< GeoExtent >::const_iterator itr = _extents.begin(); itr != _extents.end(); itr++)
+            for (std::vector< GeoExtent >::const_iterator itr = _extents.begin(); itr != _extents.end(); ++itr)
             {
                 const GeoExtent& extent = *itr;
                 double boundsArea = extent.area();
diff --git a/src/osgEarth/CachePolicy b/src/osgEarth/CachePolicy
index 68b1e3f..720184b 100644
--- a/src/osgEarth/CachePolicy
+++ b/src/osgEarth/CachePolicy
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
@@ -67,10 +67,10 @@ namespace osgEarth
         CachePolicy( const Config& conf );
 
         /** construct a cache policy be reading it from an osgDB::Options */
-        static bool fromOptions( const osgDB::Options* dbOptions, optional<CachePolicy>& out_policy );
+        //static optional<CachePolicy> get(const osgDB::Options* options);
 
         /** Stores this cache policy in a DB Options. */
-        void apply( osgDB::Options* options );
+        //void store( osgDB::Options* options ) const;
 
         /** Merges any set properties in another CP into this one, override existing values. */
         void mergeAndOverride(const CachePolicy& rhs);
@@ -99,9 +99,19 @@ namespace osgEarth
         optional<TimeStamp>& minTime() { return _minTime; }
         const optional<TimeStamp>& minTime() const { return _minTime; }
 
+        /** Whether any of the fields are set */
+        bool empty() const;
 
     public: // convenience functions.
 
+        bool isCacheEnabled() const {
+            return isCacheReadable() || isCacheWriteable();
+        }
+
+        bool isCacheDisabled() const {
+            return !isCacheEnabled();
+        }
+
         bool isCacheReadable() const { 
             return *_usage == USAGE_READ_WRITE || *_usage == USAGE_CACHE_ONLY || *_usage == USAGE_READ_ONLY;
         }
@@ -110,12 +120,18 @@ namespace osgEarth
             return *_usage == USAGE_READ_WRITE;
         }
 
+        bool isCacheOnly() const {
+            return *_usage == USAGE_CACHE_ONLY;
+        }
+
         bool operator == ( const CachePolicy& rhs ) const;
 
         bool operator != ( const CachePolicy& rhs ) const {
             return ! operator==(rhs);
         }
 
+        CachePolicy& operator = ( const CachePolicy& rhs );
+
         // returns a readable string describing usage
         std::string usageString() const;
 
diff --git a/src/osgEarth/CachePolicy.cpp b/src/osgEarth/CachePolicy.cpp
index 12ebb3d..ab89349 100644
--- a/src/osgEarth/CachePolicy.cpp
+++ b/src/osgEarth/CachePolicy.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -17,6 +17,7 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>
  */
 #include <osgEarth/CachePolicy>
+#include <osgEarth/Cache>
 #include <limits.h>
 
 using namespace osgEarth;
@@ -62,33 +63,30 @@ _minTime( rhs._minTime )
     //nop
 }
 
-bool
-CachePolicy::fromOptions( const osgDB::Options* dbOptions, optional<CachePolicy>& out )
-{
-    if ( dbOptions )
-    {
-        std::string jsonString = dbOptions->getPluginStringData( "osgEarth::CachePolicy" );
-        if ( !jsonString.empty() )
-        {
-            Config conf;
-            conf.fromJSON( jsonString );
-            CachePolicy temp( conf );
-            out->mergeAndOverride( temp );
-            return true;
-        }
-    }
-    return false;
-}
-
-void
-CachePolicy::apply( osgDB::Options* dbOptions )
-{
-    if ( dbOptions )
-    {
-        Config conf = getConfig();
-        dbOptions->setPluginStringData( "osgEarth::CachePolicy", conf.toJSON() );
-    }
-}
+//optional<CachePolicy>
+//CachePolicy::get(const osgDB::Options* readOptions)
+//{
+//    optional<CachePolicy> policy;
+//    if (readOptions)
+//    {
+//        CacheSettings* settings = CacheSettings::get(readOptions);
+//        if (settings)
+//        {
+//            policy = settings->cachePolicy().get();
+//        }
+//    }
+//    return policy;
+//}
+
+//void
+//CachePolicy::store(osgDB::Options* dbOptions) const
+//{
+//    if ( dbOptions )
+//    {
+//        Config conf = getConfig();
+//        dbOptions->setPluginStringData( "osgEarth::CachePolicy", conf.toJSON() );
+//    }
+//}
 
 void
 CachePolicy::mergeAndOverride(const CachePolicy& rhs)
@@ -136,6 +134,16 @@ CachePolicy::operator == (const CachePolicy& rhs) const
         (_minTime.get() == rhs._minTime.get());
 }
 
+CachePolicy&
+CachePolicy::operator = ( const CachePolicy& rhs )
+{
+    _usage  = optional<Usage>(rhs._usage);
+    _maxAge = optional<TimeSpan>(rhs._maxAge);
+    _minTime = optional<TimeStamp>(rhs._minTime);
+
+    return *this;
+}
+
 std::string
 CachePolicy::usageString() const
 {
@@ -146,6 +154,13 @@ CachePolicy::usageString() const
     return "unknown";
 }
 
+bool
+CachePolicy::empty() const
+{
+    bool isSet = _usage.isSet() || _maxAge.isSet() || _minTime.isSet();
+    return !isSet;
+}
+
 void
 CachePolicy::fromConfig( const Config& conf )
 {
diff --git a/src/osgEarth/CacheSeed b/src/osgEarth/CacheSeed
index 2c88a74..11d179a 100644
--- a/src/osgEarth/CacheSeed
+++ b/src/osgEarth/CacheSeed
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarth/CacheSeed.cpp b/src/osgEarth/CacheSeed.cpp
index 6a3bc25..58f1b99 100644
--- a/src/osgEarth/CacheSeed.cpp
+++ b/src/osgEarth/CacheSeed.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarth/Capabilities b/src/osgEarth/Capabilities
index 5afde8a..b3bf905 100644
--- a/src/osgEarth/Capabilities
+++ b/src/osgEarth/Capabilities
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarth/Capabilities.cpp b/src/osgEarth/Capabilities.cpp
index e0d174c..5f48302 100644
--- a/src/osgEarth/Capabilities.cpp
+++ b/src/osgEarth/Capabilities.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -295,7 +295,6 @@ _maxTextureBufferSize   ( 0 )
             osg::isGLExtensionSupported( id, "GL_ARB_texture_non_power_of_two" );
         OE_INFO << LC << "  NPOT textures = " << SAYBOOL(_supportsNonPowerOfTwoTextures) << std::endl;
 
-#if OSG_VERSION_GREATER_OR_EQUAL(3, 1, 7)
         _supportsTextureBuffer = 
             osg::isGLExtensionOrVersionSupported( id, "GL_ARB_texture_buffer_object", 3.0 ) ||
             osg::isGLExtensionOrVersionSupported( id, "GL_EXT_texture_buffer_object", 3.0 );
@@ -304,13 +303,16 @@ _maxTextureBufferSize   ( 0 )
         {
             glGetIntegerv( GL_MAX_TEXTURE_BUFFER_SIZE, &_maxTextureBufferSize );
         }
-#endif
 
         OE_INFO << LC << "  Texture buffers = " << SAYBOOL(_supportsTextureBuffer) << std::endl;
         if ( _supportsTextureBuffer )
         {
             OE_INFO << LC << "  Texture buffer max size = " << _maxTextureBufferSize << std::endl;
-        }            
+        }       
+
+        bool supportsTransformFeedback =
+            osg::isGLExtensionSupported( id, "GL_ARB_transform_feedback2" );
+        OE_INFO << LC << "  Transform feedback = " << SAYBOOL(supportsTransformFeedback) << "\n";
 
 
         // Writing to gl_FragDepth is not supported under GLES:
diff --git a/src/osgEarth/ClampableNode.cpp b/src/osgEarth/ClampableNode.cpp
index 5387ff0..a9981bc 100644
--- a/src/osgEarth/ClampableNode.cpp
+++ b/src/osgEarth/ClampableNode.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -22,7 +22,6 @@
 #include <osgEarth/DepthOffset>
 #include <osgEarth/OverlayDecorator>
 #include <osgEarth/MapNode>
-#include <osgEarth/VirtualProgram>
 
 #define LC "[ClampableNode] "
 
diff --git a/src/osgEarth/Clamping b/src/osgEarth/Clamping
index caf8db0..d45d1c5 100644
--- a/src/osgEarth/Clamping
+++ b/src/osgEarth/Clamping
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
@@ -54,6 +54,12 @@ namespace osgEarth
         // Name of the uniform used to apply an altitude offset to clamped geometry
         static const char* AltitudeOffsetUniformName;
 
+        // GLSL attribute binding location for clamping vertex heights
+        static const int HeightsAttrLocation;
+
+        // Name of the clamping heights array attribute
+        static const char* HeightsAttrName;
+
         // When setting clamping vertex attributes, use these constants in
         // the alpha channel to indicate whether the vertex is to be clamped
         // to the reference vertex in the attribute data, or to the ground.
@@ -72,6 +78,10 @@ namespace osgEarth
         static void applyDefaultClampingAttrs(
             osg::Geometry* geom,
             float          verticalOffset =0.0f);
+
+        static void setHeights(
+            osg::Geometry*   geom,
+            osg::FloatArray* heights );
     };
 }
 
diff --git a/src/osgEarth/Clamping.cpp b/src/osgEarth/Clamping.cpp
index 8745ec2..a89535c 100644
--- a/src/osgEarth/Clamping.cpp
+++ b/src/osgEarth/Clamping.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
@@ -32,6 +32,9 @@ const char* Clamping::AnchorAttrName            = "oe_clamp_attrs";
 const char* Clamping::HasAttrsUniformName       = "oe_clamp_hasAttrs";
 const char* Clamping::AltitudeOffsetUniformName = "oe_clamp_altitudeOffset";
 
+const int   Clamping::HeightsAttrLocation       = osg::Drawable::FOG_COORDS;
+const char* Clamping::HeightsAttrName           = "oe_clamp_height";
+
 const float Clamping::ClampToAnchor = 1.0f;
 const float Clamping::ClampToGround = 0.0f;
 
@@ -108,3 +111,14 @@ Clamping::installHasAttrsUniform(osg::StateSet* stateset)
         stateset->addUniform( new osg::Uniform(Clamping::HasAttrsUniformName, true) );
     }
 }
+
+void
+Clamping::setHeights(osg::Geometry* geom, osg::FloatArray* hats)
+{
+    if ( geom )
+    {
+        geom->setVertexAttribArray( HeightsAttrLocation, hats );
+        geom->setVertexAttribBinding( HeightsAttrLocation, geom->BIND_PER_VERTEX );
+        geom->setVertexAttribNormalize( HeightsAttrLocation, false );
+    }
+}
diff --git a/src/osgEarth/ClampingTechnique b/src/osgEarth/ClampingTechnique
index 31603eb..6be9095 100644
--- a/src/osgEarth/ClampingTechnique
+++ b/src/osgEarth/ClampingTechnique
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
@@ -24,8 +24,6 @@
 
 #include <osgEarth/Common>
 #include <osgEarth/OverlayDecorator>
-#include <osg/TexGenNode>
-#include <osg/Uniform>
 
 #define OSGEARTH_CLAMPING_BIN           "osgEarth::ClampingBin"
 
@@ -96,7 +94,6 @@ namespace osgEarth
 
         void onUninstall( TerrainEngineNode* engine );
 
-
     protected:
         virtual ~ClampingTechnique() { }
 
diff --git a/src/osgEarth/ClampingTechnique.cpp b/src/osgEarth/ClampingTechnique.cpp
index 8a5608c..25116d7 100644
--- a/src/osgEarth/ClampingTechnique.cpp
+++ b/src/osgEarth/ClampingTechnique.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
@@ -196,7 +196,8 @@ static osgEarthRegisterRenderBinProxy<ClampingRenderBin> s_regbin(OSGEARTH_CLAMP
 //---------------------------------------------------------------------------
 
 ClampingTechnique::ClampingTechnique() :
-_textureSize( 1024 )
+_textureSize( 1024 ),
+_engine(0L)
 {
     // disable if GLSL is not supported
     _supported = Registry::capabilities().supportsGLSL();
@@ -359,6 +360,9 @@ ClampingTechnique::setUpCamera(OverlayDecorator::TechRTTParams& params)
     vp->addBindAttribLocation( Clamping::AnchorAttrName, Clamping::AnchorAttrLocation );
     local->_groupStateSet->addUniform( new osg::Uniform(Clamping::HasAttrsUniformName, false) );
 
+    // Bind clamping heights location.
+    vp->addBindAttribLocation( Clamping::HeightsAttrName, Clamping::HeightsAttrLocation );
+
     osgEarth::Shaders pkg;
     pkg.load(vp, pkg.GPUClampingVertex);
     pkg.load(vp, pkg.GPUClampingFragment);
diff --git a/src/osgEarth/ColorFilter b/src/osgEarth/ColorFilter
index d03fcf9..29d160a 100644
--- a/src/osgEarth/ColorFilter
+++ b/src/osgEarth/ColorFilter
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -71,6 +71,7 @@ namespace osgEarth
 
     //--------------------------------------------------------------------
 
+    class ColorFilterFactory;
 
     /**
      * Registry for ColorFilter serialization support.
@@ -96,7 +97,7 @@ namespace osgEarth
         /**
          * Adds a ColorFilter type to the registry
          */
-        void add( const std::string& key, class ColorFilterFactory* factory );
+        void add( const std::string& key, ColorFilterFactory* factory );
 
 
     public:
diff --git a/src/osgEarth/ColorFilter.cpp b/src/osgEarth/ColorFilter.cpp
index d3eb215..fe1bb18 100644
--- a/src/osgEarth/ColorFilter.cpp
+++ b/src/osgEarth/ColorFilter.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarth/Common b/src/osgEarth/Common
index d17931b..5141a13 100644
--- a/src/osgEarth/Common
+++ b/src/osgEarth/Common
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -23,6 +23,7 @@
 #include <osgEarth/Export>
 #include <osgEarth/Notify>
 #include <osg/Version>
+#include <osg/ref_ptr>
 
 // define the OSG Version checks for older OSG versions
 
@@ -42,6 +43,20 @@ namespace osgEarth
 {
     // application-wide unique ID.
     typedef int UID;
+
+    // reference counted unique UID.
+    struct OSGEARTH_EXPORT RefUID : public osg::Referenced {
+        RefUID() : _uid(0) { }
+        RefUID(UID uid) : _uid(uid) { }
+        operator UID() const { return _uid; }
+        UID _uid;
+    };
 }
 
+#ifdef _MSC_VER
+// VS ignores
+#pragma warning (disable: 4224)
+#pragma warning (disable: 4180)
+#endif
+
 #endif // OSGEARTH_COMMON_H
diff --git a/src/osgEarth/CompositeTileSource b/src/osgEarth/CompositeTileSource
index 0ab1c0f..25cbaaf 100644
--- a/src/osgEarth/CompositeTileSource
+++ b/src/osgEarth/CompositeTileSource
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarth/CompositeTileSource.cpp b/src/osgEarth/CompositeTileSource.cpp
index 68cfa9a..8864753 100644
--- a/src/osgEarth/CompositeTileSource.cpp
+++ b/src/osgEarth/CompositeTileSource.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -62,6 +62,8 @@ CompositeTileSourceOptions::getConfig() const
     {
         if ( i->_imageLayerOptions.isSet() )
             conf.add( "image", i->_imageLayerOptions->getConfig() );
+        else if ( i->_elevationLayerOptions.isSet() )
+            conf.add( "elevation", i->_elevationLayerOptions->getConfig() );
     }
 
     return conf;
@@ -77,19 +79,19 @@ CompositeTileSourceOptions::mergeConfig( const Config& conf )
 void 
 CompositeTileSourceOptions::fromConfig( const Config& conf )
 {    
-    const ConfigSet& images = conf.children("image");
+    const ConfigSet& images = conf.hasChild("images") ? conf.child("images").children() : conf.children("image");
     for( ConfigSet::const_iterator i = images.begin(); i != images.end(); ++i )
     {
         add( ImageLayerOptions( *i ) );
     }
 
-    const ConfigSet& elevations = conf.children("elevation");
+    const ConfigSet& elevations = conf.hasChild("elevations") ? conf.child("elevations").children() : conf.children("elevation");
     for( ConfigSet::const_iterator i = elevations.begin(); i != elevations.end(); ++i )
     {
         add( ElevationLayerOptions( *i ) );
     }
-
-    const ConfigSet& heightfields = conf.children("heightfield");
+    
+    const ConfigSet& heightfields = conf.hasChild("heightfields") ? conf.child("heightfields").children() : conf.children("heightfield");
     for( ConfigSet::const_iterator i = heightfields.begin(); i != heightfields.end(); ++i )
     {
         add( ElevationLayerOptions( *i ) );
@@ -289,7 +291,7 @@ osg::HeightField* CompositeTileSource::createHeightField(
     }  
 
     // Populate the heightfield and return it if it's valid
-    if (_elevationLayers.populateHeightField(heightField.get(), key, 0, INTERP_AVERAGE, progress))
+    if (_elevationLayers.populateHeightField(heightField.get(), key, 0, INTERP_BILINEAR, progress))
     {                
         return heightField.release();
     }
@@ -348,46 +350,51 @@ CompositeTileSource::add( ElevationLayer* layer )
 }
 
 
-TileSource::Status
+Status
 CompositeTileSource::initialize(const osgDB::Options* dbOptions)
 {
     _dbOptions = Registry::instance()->cloneOrCreateOptions(dbOptions);
 
-    osg::ref_ptr<const Profile> profile = getProfile();    
+    osg::ref_ptr<const Profile> profile = getProfile();
 
     for(CompositeTileSourceOptions::ComponentVector::iterator i = _options._components.begin();
         i != _options._components.end(); )
     {        
-        if ( i->_imageLayerOptions.isSet() )
+        if ( i->_imageLayerOptions.isSet() && !i->_layer.valid() )
         {
             // Disable the l2 cache for composite layers so that we don't get run out of memory on very large datasets.
             i->_imageLayerOptions->driver()->L2CacheSize() = 0;
 
             osg::ref_ptr< ImageLayer > layer = new ImageLayer(*i->_imageLayerOptions);
-            if (!layer->getTileSource())
+            layer->setReadOptions(_dbOptions.get());
+            Status status = layer->open();
+            if (status.isOK())
             {
-                OE_WARN << LC << "Could not find a TileSource for driver [" << i->_imageLayerOptions->driver()->getDriver() << "]" << std::endl;
+                i->_layer = layer;
+                _imageLayers.push_back( layer );
+                OE_INFO << LC << " .. added image layer " << layer->getName() << " (" << i->_imageLayerOptions->driver()->getDriver() << ")\n";
             }
             else
             {
-                i->_layer = layer;
-                _imageLayers.push_back( layer );
+                OE_WARN << LC << "Could not open image layer (" << layer->getName() << ") ... " << status.message() << std::endl;
             }            
         }
-        else if (i->_elevationLayerOptions.isSet())
+        else if (i->_elevationLayerOptions.isSet() && !i->_layer.valid())
         {
             // Disable the l2 cache for composite layers so that we don't get run out of memory on very large datasets.
             i->_elevationLayerOptions->driver()->L2CacheSize() = 0;
 
-            osg::ref_ptr< ElevationLayer > layer = new ElevationLayer(*i->_elevationLayerOptions);            
-            if (!layer->getTileSource())
+            osg::ref_ptr< ElevationLayer > layer = new ElevationLayer(*i->_elevationLayerOptions);   
+            layer->setReadOptions(_dbOptions.get());
+            Status status = layer->open();
+            if (status.isOK())
             {
-                   OE_WARN << LC << "Could not find a TileSource for driver [" << i->_elevationLayerOptions->driver()->getDriver() << "]" << std::endl;
+                i->_layer = layer;
+                _elevationLayers.push_back( layer.get() );                
             }
             else
             {
-                i->_layer = layer;
-                _elevationLayers.push_back( layer.get() );                
+                OE_WARN << LC << "Could not open elevation layer (" << layer->getName() << ") ... " << status.message() << std::endl;
             }
         }
 
@@ -443,7 +450,7 @@ namespace
             supportsExtension( "osgearth_composite", "Composite tile source driver" );
         }
 
-        virtual const char* className()
+        const char* className() const //override
         {
             return "CompositeTileSourceDriver";
         }
diff --git a/src/osgEarth/Config b/src/osgEarth/Config
index 7b2d66e..fda8ed3 100644
--- a/src/osgEarth/Config
+++ b/src/osgEarth/Config
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -54,46 +54,80 @@ namespace osgEarth
     class OSGEARTH_EXPORT Config
     {
     public:
-        Config() { }
+        Config()
+            : _isLocation(false) { }
 
         Config( const std::string& key )
-            : _key(key) { }
+            : _key(key), _isLocation(false) { }
 
         Config( const std::string& key, const std::string& value ) 
-            : _key( key ), _defaultValue( value ) { }
+            : _key( key ), _defaultValue( value ), _isLocation(false) { }
 
+        /** Copy ctor */
         Config( const Config& rhs ) 
-            : _key(rhs._key), _defaultValue(rhs._defaultValue), _children(rhs._children), _referrer(rhs._referrer), _refMap(rhs._refMap) { }
+            : _key(rhs._key), _defaultValue(rhs._defaultValue), _children(rhs._children), _referrer(rhs._referrer), _isLocation(rhs._isLocation), _externalRef(rhs._externalRef), _refMap(rhs._refMap) { }
 
         virtual ~Config();
 
-        /** Context for resolving relative URIs that occur in this Config */
+        /**
+         * Referrer is the context for resolving relative pathnames that occur in this object.
+         * For example, if the value is a filename "file.txt" and the referrer is "C:/temp/a.earth",
+         * then the full path of the file is "C:/temp/file.txt".
+         *
+         * Calling this sets a referrer on this object and its children. 
+         */
         void setReferrer( const std::string& value );
-        void inheritReferrer( const std::string& value );
+
+        /** Access this object's "relative-to" location. */
         const std::string& referrer() const { return _referrer; }
 
+        /** Referrer associated with a key */
+        const std::string referrer( const std::string& key ) const {
+            return child(key).referrer();
+        }
+
+        /** Sets whether this Config's value represents a location, i.e. a URI, filename, or
+            other string that can be relocated to be relative to a different referrer. */
+        void setIsLocation(bool tf) { _isLocation = tf; }
+        bool isLocation() const     { return _isLocation; }
+
+        /** Hint that this Config came from an externally referenced resource. */
+        const std::string& externalRef() const { return _externalRef;}
+        void setExternalRef(const std::string& externalRef) { _externalRef = externalRef; }
+
+        /** Populate this object from an XML input stream. */
         bool fromXML( std::istream& in );
 
+        /** Encode this object as JSON. */
         std::string toJSON( bool pretty =false ) const;
 
+        /** Populate this object from a JSON string. */
         bool fromJSON( const std::string& json );
+        static Config readJSON(const std::string& json);
 
+        /** True if this object contains no data. */
         bool empty() const {
             return _key.empty() && _defaultValue.empty() && _children.empty();
         }
 
+        /** True is this object is a simple key/value pair with no children. */
         bool isSimple() const {
             return !_key.empty() && !_defaultValue.empty() && _children.empty();
         }
 
+        /** The key value for this object */
         std::string& key() { return _key; }
         const std::string& key() const { return _key; }
 
+        /** The value corresponding to the key */
         const std::string& value() const { return _defaultValue; }
         std::string& value() { return _defaultValue; }
 
+        /** Child objects. */
+        ConfigSet& children() { return _children; }
         const ConfigSet& children() const { return _children; }
 
+        /** A collection of all the children of this object with a particular key */
         const ConfigSet children( const std::string& key ) const {
             ConfigSet r;
             for(ConfigSet::const_iterator i = _children.begin(); i != _children.end(); i++ ) {
@@ -103,6 +137,7 @@ namespace osgEarth
             return r;
         }
 
+        /** Whether this object has a child with a given key */
         bool hasChild( const std::string& key ) const {
             for(ConfigSet::const_iterator i = _children.begin(); i != _children.end(); i++ )
                 if ( i->key() == key )
@@ -110,6 +145,7 @@ namespace osgEarth
             return false;
         }
 
+        /** Removes all children with the given key */
         void remove( const std::string& key ) {
             for(ConfigSet::iterator i = _children.begin(); i != _children.end(); ) {
                 if ( i->key() == key )
@@ -119,17 +155,25 @@ namespace osgEarth
             }
         }
 
+        /** Copy of the first child with the given key */
         Config child( const std::string& key ) const;
 
+        /** Pointer to the first child with the given key, or NULL if none exist */
         const Config* child_ptr( const std::string& key ) const;
 
+        /** Mutable pointer to the first child with the given key, or NULL if none exist */
         Config* mutable_child( const std::string& key );
 
+        /** Merge the contents of another Config object into this object.. danger, read the code
+            before you use this */
         void merge( const Config& rhs );
 
+        /** Locate (recursively) the first descendant object with this key, optionally checking
+            the current object as well */
         Config* find( const std::string& key, bool checkThis =true );
         const Config* find( const std::string& key, bool checkThis =true) const;
 
+        /** Adds an optional value as a child, but only if its value is set */
         template<typename T>
         void addIfSet( const std::string& key, const optional<T>& opt ) {
             if ( opt.isSet() ) {
@@ -137,6 +181,7 @@ namespace osgEarth
             }
         }
         
+        /** Adds a referenced object as a child, but only if its value is set */
         template<typename T>
         void addObjIfSet( const std::string& key, const osg::ref_ptr<T>& opt ) {
             if ( opt.valid() ) {
@@ -146,6 +191,7 @@ namespace osgEarth
             }
         }
 
+        /** Adds an optional object as a child, but only if its value is set */
         template<typename T>
         void addObjIfSet( const std::string& key, const optional<T>& obj ) {
             if ( obj.isSet() ) {
@@ -155,36 +201,40 @@ namespace osgEarth
             }
         }
 
+        /** Adds an enumeration value as a child, but only if its value is set */
         template<typename X, typename Y>
         void addIfSet( const std::string& key, const std::string& val, const optional<X>& target, const Y& targetValue ) {
             if ( target.isSetTo( targetValue ) )
                 add( key, val );
         }
 
+        /** Add a value as a child */
         template<typename T>
         void add( const std::string& key, const T& value ) {
             _children.push_back( Config(key, Stringify() << value) );
-            //_children.back().setReferrer( _referrer );
-            _children.back().inheritReferrer( _referrer );
+            _children.back().setReferrer( _referrer );
         }
 
+        /** Add a Config as a child */
         void add( const Config& conf ) {
             _children.push_back( conf );
-            //_children.back().setReferrer( _referrer );
-            _children.back().inheritReferrer( _referrer );
+            _children.back().setReferrer( _referrer );
         }
 
+        /** Add a config as a child, assigning it a key */
         void add( const std::string& key, const Config& conf ) {
             Config temp = conf;
             temp.key() = key;
             add( temp );
         }
 
+        /** Add a set of config objects as children. */
         void add( const ConfigSet& set ) {
             for( ConfigSet::const_iterator i = set.begin(); i != set.end(); i++ )
                 add( *i );
         }
 
+        /** Adds an object as a child. */
         template<typename T>
         void addObj( const std::string& key, const T& value ) {
             Config conf = value.getConfig();
@@ -192,6 +242,7 @@ namespace osgEarth
             add( conf );
         }
 
+        /** Adds or replaces a value as a child, but only if it is set */
         template<typename T>
         void updateIfSet( const std::string& key, const optional<T>& opt ) {
             if ( opt.isSet() ) {
@@ -200,6 +251,7 @@ namespace osgEarth
             }
         }
         
+        /** Adds or replaces a referenced object as a child, but only if it is set */
         template<typename T>
         void updateObjIfSet( const std::string& key, const osg::ref_ptr<T>& opt ) {
             if ( opt.valid() ) {
@@ -209,7 +261,8 @@ namespace osgEarth
                 add( conf );
             }
         }
-
+        
+        /** Adds or replaces an object as a child, but only if it is set */
         template<typename T>
         void updateObjIfSet( const std::string& key, const optional<T>& obj ) {
             if ( obj.isSet() ) {
@@ -219,7 +272,8 @@ namespace osgEarth
                 add( conf );
             }
         }
-
+        
+        /** Adds or replaces an enumeration value as a child, but only if it is set */
         template<typename X, typename Y>
         void updateIfSet( const std::string& key, const std::string& val, const optional<X>& target, const Y& targetValue ) {
             if ( target.isSetTo( targetValue ) ) {
@@ -227,17 +281,20 @@ namespace osgEarth
                 add( key, val );
             }
         }
-
+        
+        /** Adds or replaces value as a child */
         template<typename T>
         void update( const std::string& key, const T& value ) {
             update( Config(key, Stringify() << value) );
         }
 
+        /** Adds or replaces a config as a child. */
         void update( const Config& conf ) {
             remove(conf.key());
             add( conf );
         }
 
+        /** Adds or replaces an object as a child */
         template<typename T>
         void updateObj( const std::string& key, const T& value ) {
             remove(key);
@@ -246,15 +303,18 @@ namespace osgEarth
             add( conf );
         }
 
+        /** Same as update */
         template<typename T>
         void set( const std::string& key, const T& value ) {
             update( key, value );
         }
 
+        /** Whether this object has the key OR has a child with the key */
         bool hasValue( const std::string& key ) const {
             return !value(key).empty();
         }
 
+        /** The value of this object (if the key matches) or a matching child object */
         const std::string value( const std::string& key ) const {
             std::string r = trim(child(key).value());
             if ( r.empty() && _key == key )
@@ -262,11 +322,7 @@ namespace osgEarth
             return r;
         }
 
-        const std::string referrer( const std::string& key ) const {
-            return child(key).referrer();
-        }
-
-        // populates a primitive value.
+        /** Value cast to a particular primitive type (with fallback in case casting fails) */
         template<typename T>
         T value( const std::string& key, T fallback ) const {
             std::string r;
@@ -275,11 +331,12 @@ namespace osgEarth
             return osgEarth::as<T>( r, fallback );
         }
 
+        /** Value case to a boolean */
         bool boolValue( bool fallback ) const {
             return osgEarth::as<bool>( _defaultValue, fallback );
         }
 
-        // populates the output value iff the Config exists.
+        /** Populates the output value iff the Config exists. */
         template<typename T>
         bool getIfSet( const std::string& key, optional<T>& output ) const {
             std::string r;
@@ -292,8 +349,8 @@ namespace osgEarth
             else
                 return false;
         }
-
-        // for Configurable's
+        
+        /** Populates the output object iff the Config exists. */
         template<typename T>
         bool getObjIfSet( const std::string& key, optional<T>& output ) const {
             if ( hasChild( key ) ) {
@@ -303,8 +360,8 @@ namespace osgEarth
             else
                 return false;
         }
-
-        // populates a Referenced that takes a Config in the constructor.
+        
+        /** Populates the output referenced value iff the Config exists. */
         template<typename T>
         bool getObjIfSet( const std::string& key, osg::ref_ptr<T>& output ) const {
             if ( hasChild( key ) ) {
@@ -314,7 +371,8 @@ namespace osgEarth
             else
                 return false;
         }
-
+        
+        /** Populates the output object value iff the Config exists. */
         template<typename T>
         bool getObjIfSet( const std::string& key, T& output ) const {
             if ( hasChild(key) ) {
@@ -323,7 +381,8 @@ namespace osgEarth
             }
             return false;
         }
-
+        
+        /** Populates the output enumerable pair iff the Config exists. */
         template<typename X, typename Y>
         bool getIfSet( const std::string& key, const std::string& val, optional<X>& target, const Y& targetValue ) const {
             if ( hasValue( key ) && value( key ) == val ) {
@@ -333,7 +392,8 @@ namespace osgEarth
             else 
                 return false;
         }
-
+        
+        /** Populates the output enumerable pair iff the Config exists. */
         template<typename X, typename Y>
         bool getIfSet( const std::string& key, const std::string& val, X& target, const Y& targetValue ) const {
             if ( hasValue(key) && value(key) == val ) {
@@ -342,7 +402,8 @@ namespace osgEarth
             }
             return false;
         }
-
+        
+        /** Populates the ouptut value iff the Config exists. */
         template<typename T>
         bool getIfSet( const std::string& key, T& output ) const {
             if ( hasValue(key) ) {
@@ -353,7 +414,6 @@ namespace osgEarth
         }
 
         /** support for conveying non-serializable objects in a Config (in memory only) */
-
         typedef std::map<std::string, osg::ref_ptr<osg::Referenced> > RefMap;
 
         void addNonSerializable( const std::string& key, osg::Referenced* obj ) {
@@ -370,16 +430,17 @@ namespace osgEarth
             return i == _refMap.end() ? 0 : dynamic_cast<X*>( i->second.get() );
         }
 
-        // remove everything from (this) that also appears in rhs
+        // remove everything from (this) that also appears in rhs (diff)
         Config operator - ( const Config& rhs ) const;
 
     protected:
         std::string _key;
         std::string _defaultValue;
         ConfigSet   _children;   
-        std::string _referrer;        
-
-        RefMap _refMap;
+        std::string _referrer;
+        bool        _isLocation;
+        std::string _externalRef;
+        RefMap      _refMap;
     };
 
 
@@ -417,8 +478,7 @@ namespace osgEarth
     template<> inline
     void Config::add<std::string>( const std::string& key, const std::string& value ) {
         _children.push_back( Config( key, value ) );
-        //_children.back().setReferrer( _referrer );
-        _children.back().inheritReferrer( _referrer );
+        _children.back().setReferrer( _referrer );
     }
 
     template<> inline
diff --git a/src/osgEarth/Config.cpp b/src/osgEarth/Config.cpp
index 383fb90..e29ec36 100644
--- a/src/osgEarth/Config.cpp
+++ b/src/osgEarth/Config.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
@@ -32,6 +32,8 @@
 
 using namespace osgEarth;
 
+#define LC "[Config] "
+
 Config::~Config()
 {
 }
@@ -39,23 +41,33 @@ Config::~Config()
 void
 Config::setReferrer( const std::string& referrer )
 {
-    _referrer = referrer;
-    for( ConfigSet::iterator i = _children.begin(); i != _children.end(); i++ )
-    { 
-        i->setReferrer( osgEarth::getFullPath(_referrer, i->_referrer) );
+    if ( referrer.empty() )
+        return;
+
+    std::string absReferrer;
+    if( !osgDB::containsServerAddress( referrer ) ) {
+        absReferrer = osgEarth::getAbsolutePath( referrer );
+
+        if( osgEarth::isRelativePath( absReferrer ) )
+        {
+            OE_WARN << LC << "ILLEGAL: call to setReferrer with relative path:  "
+                "key=" << key() << "; referrer=" << referrer << "\n";
+            return;
+        }
+    }
+    else {
+        absReferrer = referrer;
     }
-}
 
-void
-Config::inheritReferrer( const std::string& referrer )
-{
-    if ( _referrer.empty() || !osgEarth::isRelativePath(referrer) )
+    // Don't overwrite an existing referrer:
+    if ( _referrer.empty() )
     {
-        setReferrer( referrer );
+        _referrer = absReferrer;
     }
-    else if ( !referrer.empty() )
-    {
-        setReferrer( osgDB::concatPaths(_referrer, referrer) );
+
+    for( ConfigSet::iterator i = _children.begin(); i != _children.end(); i++ )
+    { 
+        i->setReferrer( absReferrer );
     }
 }
 
@@ -208,20 +220,28 @@ namespace
                         {
                             Config& c = i->second[0];
                             if ( c.isSimple() )
+                            {
                                 value[i->first] = c.value();
+                            }
                             else
-                                value[i->first] = conf2json(c, nicer, depth+1);
+                            {
+                                Json::Value child = conf2json(c, nicer, depth+1);
+                                if (child.isObject())
+                                {
+                                    value[i->first] = child;
+                                }   
+                            }
                         }
                         else
                         {
-                            std::string array_key = Stringify() << i->first << "_$set";
+                            std::string array_key = Stringify() << i->first << "__array__";
                             Json::Value array_value( Json::arrayValue );
                             for( std::vector<Config>::iterator j = i->second.begin(); j != i->second.end(); ++j )
                             {
                                 array_value.append( conf2json(*j, nicer, depth+1) );
                             }
-                            value = array_value;
-                            //value[array_key] = array_value;
+                            value[array_key] = array_value;
+                            //value = array_value;
                         }
                     }
                 }
@@ -283,14 +303,24 @@ namespace
                 }
                 else if ( value.isArray() )
                 {
-                    if ( endsWith(*i, "_$set") )
+                    if ( endsWith(*i, "__array__") )
+                    {
+                        std::string key = i->substr(0, i->length()-9);
+                        for( Json::Value::const_iterator j = value.begin(); j != value.end(); ++j )
+                        {
+                            Config child;
+                            json2conf( *j, child, depth+1 );
+                            conf.add( key, child );
+                        }
+                    }
+                    else if ( endsWith(*i, "_$set") ) // backwards compatibility
                     {
                         std::string key = i->substr(0, i->length()-5);
                         for( Json::Value::const_iterator j = value.begin(); j != value.end(); ++j )
                         {
-                            Config child( key );
+                            Config child;
                             json2conf( *j, child, depth+1 );
-                            conf.add( child );
+                            conf.add( key, child );
                         }
                     }
                     else
@@ -366,6 +396,14 @@ Config::fromJSON( const std::string& input )
 }
 
 Config
+Config::readJSON(const std::string& json)
+{
+    Config conf;
+    conf.fromJSON(json);
+    return conf;
+}
+
+Config
 Config::operator - ( const Config& rhs ) const
 {
     Config result( *this );
diff --git a/src/osgEarth/Containers b/src/osgEarth/Containers
index 067575e..881b03c 100644
--- a/src/osgEarth/Containers
+++ b/src/osgEarth/Containers
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
@@ -34,6 +34,58 @@
 
 namespace osgEarth
 {
+    template<typename DATA>
+    struct fast_set
+    {
+        typedef DATA                 entry_t;
+        typedef std::vector<entry_t> container_t;
+
+        container_t _data;
+
+        typedef typename container_t::iterator       iterator;
+        typedef typename container_t::const_iterator const_iterator;
+
+        iterator find(const DATA& value) {
+            for( iterator i = _data.begin(); i != _data.end(); ++i ) {
+                if ( (*i) == value ) {
+                    return i;
+                }
+            }
+            return _data.end();
+        }
+
+        const_iterator find(const DATA& value) const {
+            for( const_iterator i = _data.begin(); i != _data.end(); ++i ) {
+                if ( (*i) == value ) {
+                    return i;
+                }
+            }
+            return _data.end();
+        }
+
+        std::pair<iterator,bool> insert(const DATA& value) {
+            for( iterator i = _data.begin(); i != _data.end(); ++i ) {
+                if ( (*i) == value ) {
+                    *i = value;
+                    return std::make_pair(i, false);
+                }
+            }
+            _data.push_back(value);
+            iterator n = _data.end(); --n;
+            return std::make_pair(n, true);
+        }
+
+        const_iterator begin() const { return _data.begin(); }
+        const_iterator end() const { return _data.end(); }
+        iterator begin() { return _data.begin(); }
+        iterator end() { return _data.end(); }
+        bool empty() const { return _data.empty(); }
+        void clear() { _data.clear(); }        
+        void erase(iterator i) { _data.erase(i); }
+        void erase(const DATA& data) { iterator i = find(data); if (i != _data.end()) _data.erase(i); }
+        int size() const { return _data.size(); }
+    };
+
     /**
      * A std::map-like map that uses a vector and a getUID method for keying.
      * DATA must have a getUID() method.
@@ -45,7 +97,7 @@ namespace osgEarth
             inline const KEY&  key()  const { return _key; }
             inline const DATA& data() const { return _data; }
             inline DATA&       data()       { return _data; }
-            KEY   _key;
+            KEY  _key;
             DATA _data;
         };
         typedef std::vector<ENTRY> container_t;
@@ -65,7 +117,6 @@ namespace osgEarth
                 }
             }
             _container.resize(_container.size()+1);
-            //_container.push_back(ENTRY());
             _container.back()._key = key;
             return _container.back()._data;
         }
@@ -96,13 +147,6 @@ namespace osgEarth
         inline bool empty() const { return _container.empty(); }
 
         inline void clear() { _container.clear(); }
-        
-        //iterator erase(iterator& i) {
-        //    iterator j = i; ++j;
-        //    *i = _data.at(_data.size()-1);
-        //    _data.resize(_data.size()-1);
-        //    return j;
-        //}
 
         inline void erase(const KEY& key) {
             for(unsigned i=0; i<_container.size(); ++i) {
@@ -131,27 +175,19 @@ namespace osgEarth
     template<typename KEY, typename DATA>
     struct fast_map
     {
-        typedef std::pair<KEY,DATA> entry_t;
-        typedef std::list<entry_t>  list_t;
+        typedef std::pair<KEY,DATA>  entry_t;
+        typedef std::vector<entry_t> container_t;
 
-        typedef typename list_t::iterator       iterator;
-        typedef typename list_t::const_iterator const_iterator;
+        typedef typename container_t::iterator       iterator;
+        typedef typename container_t::const_iterator const_iterator;
 
-        list_t _data;
-        KEY    _lastKey;
+        container_t _data;
+        KEY         _lastKey;
 
         DATA& operator[] (const KEY& key) {
             for( iterator i = _data.begin(); i != _data.end(); ++i ) {
                 if ( i->first == key ) {
-                    if ( _lastKey == key && i != _data.begin() ) {
-                        _data.insert(begin(), *i);
-                        _data.erase(i);
-                        return _data.front().second;
-                    }
-                    else {
-                        _lastKey = key;
-                        return i->second;
-                    }
+                    return i->second;
                 }
             }
             _data.push_back(entry_t(key,DATA()));
@@ -183,9 +219,17 @@ namespace osgEarth
 
         bool empty() const { return _data.empty(); }
 
-        void clear() { _data.clear(); }
+        void clear() {
+            _data.clear();
+        }
         
-        iterator erase(iterator& i) { return _data.erase( i ); }
+        iterator erase(iterator i) {
+            return _data.erase( i );
+        }
+
+        iterator erase(iterator i0, iterator i1) {
+            return _data.erase(i0, i1);
+        }
 
         void erase(const KEY& key) {
             iterator i = find(key);
@@ -247,12 +291,17 @@ namespace osgEarth
             friend class LRUCache;
         };
 
+        struct Functor {
+            virtual void operator()(const K& key, const T& value) =0;
+        };
+
     protected:
         typedef typename std::list<K>::iterator      lru_iter;
         typedef typename std::list<K>                lru_type;
         typedef typename std::pair<T, lru_iter>      map_value_type;
         typedef typename std::map<K, map_value_type> map_type;
         typedef typename map_type::iterator          map_iter;
+        typedef typename map_type::const_iterator    map_const_iter;
 
         map_type _map;
         lru_type _lru;
@@ -345,7 +394,17 @@ namespace osgEarth
 
         CacheStats getStats() const {
             return CacheStats(
-                _lru.size(), _max, _queries, _queries > 0 ? (float)_hits/(float)_queries : 0.0f );
+                _map.size(), _max, _queries, _queries > 0 ? (float)_hits/(float)_queries : 0.0f );
+        }
+
+        void iterate(Functor& functor) const {
+            if (_threadsafe) {
+                Threading::ScopedMutexLock lock(_mutex);
+                iterate_impl(functor);
+            }
+            else {
+                iterate_impl(functor);
+            }
         }
 
     private:
@@ -365,7 +424,7 @@ namespace osgEarth
                 _map[key] = std::make_pair(value, last);
             }
 
-            if ( _lru.size() > _max ) {
+            if ( _map.size() > _max ) {
                 for( unsigned i=0; i < _buf; ++i ) {
                     const K& key = _lru.front();
                     _map.erase( key );
@@ -385,11 +444,7 @@ namespace osgEarth
                 _hits++;
                 result._value = mi->second.first;
                 result._valid = true;
-                //return Record( &(mi->second.first) );
             }
-            //else {
-            //    return Record( 0L );
-            //}
         }
 
         bool has_impl( const K& key ) {
@@ -414,13 +469,18 @@ namespace osgEarth
         void setMaxSize_impl( unsigned max ) {
             _max = max;
             _buf = max/10;
-            while( _lru.size() > _max ) {
+            while( _map.size() > _max ) {
                 const K& key = _lru.front();
                 _map.erase( key );
                 _lru.pop_front();
             }
         }
 
+        void iterate_impl(Functor& f) const {
+            for (map_const_iter i = _map.begin(); i != _map.end(); ++i) {
+                f(i->first, i->second.first);
+            }
+        }
     };
 
     //--------------------------------------------------------------------
diff --git a/src/osgEarth/Cube b/src/osgEarth/Cube
index dcee0d6..1345bcc 100644
--- a/src/osgEarth/Cube
+++ b/src/osgEarth/Cube
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarth/Cube.cpp b/src/osgEarth/Cube.cpp
index 624ea27..c47970b 100644
--- a/src/osgEarth/Cube.cpp
+++ b/src/osgEarth/Cube.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -394,7 +394,7 @@ CubeFaceLocator::convertModelToLocal(const osg::Vec3d& world, osg::Vec3d& local)
 // --------------------------------------------------------------------------
 
 CubeSpatialReference::CubeSpatialReference( void* handle ) :
-SpatialReference( handle, "OSGEARTH" )
+SpatialReference(handle, std::string("OSGEARTH"))
 {
     _key.horiz      = "unified-cube";
     _key.horizLower = "unified-cube";
diff --git a/src/osgEarth/CullingUtils b/src/osgEarth/CullingUtils
index b608558..e6fd86f 100644
--- a/src/osgEarth/CullingUtils
+++ b/src/osgEarth/CullingUtils
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -23,6 +23,9 @@
 #include <osgEarth/Common>
 #include <osgEarth/optional>
 #include <osgEarth/SpatialReference>
+#include <osgEarth/Horizon>
+#include <osgEarth/GeoTransform>
+
 #include <osg/NodeCallback>
 #include <osg/ClusterCullingCallback>
 #include <osg/CoordinateSystemNode>
@@ -75,7 +78,12 @@ namespace osgEarth
         /**
          * Creates a cluster culling callback with the standard parameters.
          */
-        static osg::NodeCallback* create(const osg::Vec3& controlPoint, const osg::Vec3& normal, float deviation, float radius);
+        static osg::NodeCallback* create(const osg::Vec3& controlPoint, const osg::Vec3& normal, float deviation, float radius);        
+
+        /**
+         * Creates a cluster culling callback based on an extent (for geocentric tiles).
+         */
+        static osg::NodeCallback* create(const class GeoExtent& extent);
     };
 
     
@@ -124,16 +132,15 @@ namespace osgEarth
 
     /**
      * Simple occlusion culling callback that does a ray interseciton between the eyepoint
-     * and a world point and doesn't draw if there are intersections with the node.
+     * and a A GeoTransform node.
      */
-    struct OSGEARTH_EXPORT OcclusionCullingCallback : public osg::NodeCallback {
-        OcclusionCullingCallback( const SpatialReference* srs, const osg::Vec3d& world, osg::Node* node);
+    struct OSGEARTH_EXPORT OcclusionCullingCallback : public osg::NodeCallback
+    {
+        OcclusionCullingCallback(GeoTransform* xform);
 
-        const osg::Vec3d& getWorld() const;
-        void setWorld( const osg::Vec3d& world);
+        /** Maximum eye altitude at which to perform the occlusion culling test */
         double getMaxAltitude() const;
         void setMaxAltitude( double value);
-        void operator()(osg::Node* node, osg::NodeVisitor* nv);
 
         /**
         * Gets the maximum number of ms that the OcclusionCullingCallback can run on each frame.
@@ -147,12 +154,13 @@ namespace osgEarth
         */
         static void setMaxFrameTime( double ms );
 
+    public: //NodeCallback
+        
+        void operator()(osg::Node* node, osg::NodeVisitor* nv);
+
     private:
 
-        osg::ref_ptr< osg::Node > _node;
-        osg::ref_ptr< const osgEarth::SpatialReference > _srs;
-        osg::Vec3d _world;
-        osg::Vec3d _prevWorld;
+        osg::observer_ptr<GeoTransform> _xform;
         osg::Vec3d _prevEye;
         bool _visible;
         double _maxAltitude;
@@ -166,15 +174,6 @@ namespace osgEarth
     {
         static osgUtil::CullVisitor* asCullVisitor(osg::NodeVisitor* nv);
         static osgUtil::CullVisitor* asCullVisitor(osg::NodeVisitor& nv) { return asCullVisitor(&nv); }
-
-        /** General user data to calculate once and pass down with a CullVisitor. */
-        struct CullUserData : public osg::Referenced
-        {
-            optional<double> _cameraAltitude;
-        };
-
-        static CullUserData* getCullUserData(osgUtil::CullVisitor* cv) {
-            return cv ? dynamic_cast<CullUserData*>(cv->getUserData()) : 0L; }
     };
 
     /**
@@ -269,9 +268,15 @@ namespace osgEarth
         void operator()(osg::Node* node, osg::NodeVisitor* nv);
 
     protected:
-        osg::Vec3d                        _radii;
+        osg::ref_ptr<Horizon>             _horizon;
         osg::observer_ptr<osg::ClipPlane> _clipPlane;
     };
+
+
+    struct OSGEARTH_EXPORT CullDebugger
+    {
+        Config dumpRenderBin(osgUtil::RenderBin* bin) const;
+    };
 }
 
 #endif // OSGEARTH_CULLING_UTILS_H
diff --git a/src/osgEarth/CullingUtils.cpp b/src/osgEarth/CullingUtils.cpp
index a4b82fd..1440a24 100644
--- a/src/osgEarth/CullingUtils.cpp
+++ b/src/osgEarth/CullingUtils.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -140,7 +140,9 @@ namespace
     {
         ComputeVisitor()
             : osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN), 
-              _maxRadius2(0.0f) { }
+              _maxRadius2(0.0f),
+              _maxNormalLen(0.0f),
+              _pass(0u) { }
 
         void run( osg::Node* node, const osg::Vec3d& centerECEF )
         {
@@ -250,7 +252,8 @@ namespace
     {
         ComputeClusterCullingParams( const osg::Vec3d& ecefControlPoint )
             : osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN),
-              _minDeviation( 1.0 )
+              _minDeviation( 1.0 ),
+              _maxOffset(0)
         {
             _ecefControl = ecefControlPoint;
             _ecefNormal = ecefControlPoint;
@@ -284,7 +287,7 @@ namespace
         }
         
         std::vector<osg::Matrixd> _matrixStack;
-        double _maxOffset, _maxRadius, _minDeviation;
+        double _maxOffset, _minDeviation;
         osg::Vec3d _ecefControl, _ecefNormal;
     };
 }
@@ -485,6 +488,57 @@ ClusterCullingFactory::create(const osg::Vec3& controlPoint,
     return ccc;
 }
 
+osg::NodeCallback*
+ClusterCullingFactory::create(const GeoExtent& extent)
+{
+    GeoPoint centerPoint;
+    extent.getCentroid( centerPoint );
+
+    // select the farthest corner:
+    GeoPoint edgePoint;
+    if ( centerPoint.y() >= 0.0 )
+        edgePoint = GeoPoint(extent.getSRS(), extent.xMin(), extent.yMin(), 0.0, ALTMODE_ABSOLUTE);
+    else
+        edgePoint = GeoPoint(extent.getSRS(), extent.xMin(), extent.yMax(), 0.0, ALTMODE_ABSOLUTE);
+
+    // convert both to ECEF and make unit vectors:
+    osg::Vec3d center, centerNormal, edge, edgeNormal;
+
+    centerPoint.toWorld( center );
+    edgePoint.toWorld( edge );
+
+    edgeNormal = edge;
+    edgeNormal.normalize();
+
+    centerNormal = center;
+    centerNormal.normalize();
+
+    // determine the height above the center point necessary to see the edge point:
+    double dp = centerNormal * edgeNormal;
+    double centerLen = center.length();
+    double height = (edge.length() / dp) - centerLen;
+
+    // set the control point at that height:
+    osg::Vec3d controlPoint = center + centerNormal*height;
+
+    // cluster culling only occurs beyond the maximum radius:
+    double maxRadius = (controlPoint-edge).length();
+
+    // determine the maximum visibility angle (i.e. minimum dot product
+    // of the center up vector and the vector from the control point to 
+    // the edge point)
+    osg::Vec3d cpToEdge = edge - controlPoint;
+    cpToEdge.normalize();                
+    double minDeviation = centerNormal * cpToEdge;
+    
+    // create and return the callback.
+    return create(
+        controlPoint,
+        centerNormal,
+        minDeviation,
+        maxRadius);
+}
+
 //------------------------------------------------------------------------
 
 CullNodeByNormal::CullNodeByNormal( const osg::Vec3d& normal )
@@ -528,10 +582,18 @@ DisableSubgraphCulling::operator()(osg::Node* n, osg::NodeVisitor* v)
 // The max frame time in ms
 double OcclusionCullingCallback::_maxFrameTime = 10.0;
 
-OcclusionCullingCallback::OcclusionCullingCallback(const osgEarth::SpatialReference *srs, const osg::Vec3d& world, osg::Node* node):
-_srs        ( srs ),
-_world      ( world ),
-_node       ( node ),
+//OcclusionCullingCallback::OcclusionCullingCallback(const osgEarth::SpatialReference *srs, const osg::Vec3d& world, osg::Node* node):
+//_srs        ( srs ),
+//_world      ( world ),
+//_node       ( node ),
+//_visible    ( true ),
+//_maxAltitude( 200000 )
+//{
+//    //nop
+//}
+//
+OcclusionCullingCallback::OcclusionCullingCallback(GeoTransform* xform) :
+_xform      ( xform ),
 _visible    ( true ),
 _maxAltitude( 200000 )
 {
@@ -548,16 +610,6 @@ void OcclusionCullingCallback::setMaxFrameTime( double ms )
     _maxFrameTime = ms;
 }
 
-const osg::Vec3d& OcclusionCullingCallback::getWorld() const
-{
-    return _world;
-}
-
-void OcclusionCullingCallback::setWorld( const osg::Vec3d& world)
-{
-    _world = world;
-}
-
 double OcclusionCullingCallback::getMaxAltitude() const
 {
     return _maxAltitude;
@@ -593,51 +645,59 @@ void OcclusionCullingCallback::operator()(osg::Node* node, osg::NodeVisitor* nv)
 
         osg::Vec3d eye = cv->getViewPoint();
 
-        if (_prevEye != eye || _prevWorld != _world)
+        if (_prevEye != eye)
         {
             if (remainingTime > 0.0)
             {
-                double alt = 0.0;
-
-                if ( _srs && !_srs->isProjected() )
-                {
-                    osgEarth::GeoPoint mapPoint;
-                    mapPoint.fromWorld( _srs.get(), eye );
-                    alt = mapPoint.z();
-                }
-                else
+                osg::ref_ptr<GeoTransform> geo;
+                if ( _xform.lock(geo) )
                 {
-                    alt = eye.z();
-                }
+                    double alt = 0.0;
 
+                    osg::ref_ptr<Terrain> terrain = geo->getTerrain();
+                    if ( terrain.valid() && !terrain->getSRS()->isProjected() )
+                    {
+                        osgEarth::GeoPoint mapPoint;
+                        mapPoint.fromWorld( terrain->getSRS(), eye );
+                        alt = mapPoint.z();
+                    }
+                    else
+                    {
+                        alt = eye.z();
+                    }
 
-                //Only do the intersection if we are close enough for it to matter
-                if (alt <= _maxAltitude && _node.valid())
-                {
-                    //Compute the intersection from the eye to the world point
-                    osg::Timer_t startTick = osg::Timer::instance()->tick();
-                    osg::Vec3d start = eye;
-                    osg::Vec3d end = _world;
-                    DPLineSegmentIntersector* i = new DPLineSegmentIntersector( start, end );
-                    i->setIntersectionLimit( osgUtil::Intersector::LIMIT_NEAREST );
-                    osgUtil::IntersectionVisitor iv;
-                    iv.setIntersector( i );
-                    _node->accept( iv );
-                    osgUtil::LineSegmentIntersector::Intersections& results = i->getIntersections();
-                    _visible = results.empty();
-                    osg::Timer_t endTick = osg::Timer::instance()->tick();
-                    double elapsed = osg::Timer::instance()->delta_m( startTick, endTick );
-                    remainingTime -= elapsed;
-                }
-                else
-                {
-                    _visible = true;
-                }
+                    //Only do the intersection if we are close enough for it to matter
+                    if (alt <= _maxAltitude && terrain.valid())
+                    {
+                        //Compute the intersection from the eye to the world point
+                        osg::Timer_t startTick = osg::Timer::instance()->tick();
+                        osg::Vec3d start = eye;
+                        osg::Vec3d end = osg::Vec3d(0,0,0) * geo->getMatrix();
+
+                        // shorten the intersector by 1m to prevent flickering.
+                        osg::Vec3d vec = end-start; vec.normalize();
+                        end -= vec*1.0;
+
+                        DPLineSegmentIntersector* i = new DPLineSegmentIntersector( start, end );
+                        i->setIntersectionLimit( osgUtil::Intersector::LIMIT_NEAREST );
+                        osgUtil::IntersectionVisitor iv;
+                        iv.setIntersector( i );
+                        terrain->accept( iv );
+                        osgUtil::LineSegmentIntersector::Intersections& results = i->getIntersections();
+                        _visible = results.empty();
+                        osg::Timer_t endTick = osg::Timer::instance()->tick();
+                        double elapsed = osg::Timer::instance()->delta_m( startTick, endTick );
+                        remainingTime -= elapsed;
+                    }
+                    else
+                    {
+                        _visible = true;
+                    }
 
-                numCompleted++;
+                    numCompleted++;
 
-                _prevEye = eye;
-                _prevWorld = _world;
+                    _prevEye = eye;
+                }
             }
             else
             {
@@ -1007,10 +1067,11 @@ LODScaleGroup::traverse(osg::NodeVisitor& nv)
 ClipToGeocentricHorizon::ClipToGeocentricHorizon(const osgEarth::SpatialReference* srs,
                                                  osg::ClipPlane*                   clipPlane)
 {
-    _radii.set(
-        srs->getEllipsoid()->getRadiusEquator(),
-        srs->getEllipsoid()->getRadiusEquator(),
-        srs->getEllipsoid()->getRadiusPolar() );
+    if ( srs )
+    {
+        _horizon = new Horizon();
+        _horizon->setEllipsoid( *srs->getEllipsoid() );
+    }
 
     _clipPlane = clipPlane;
 }
@@ -1021,26 +1082,79 @@ ClipToGeocentricHorizon::operator()(osg::Node* node, osg::NodeVisitor* nv)
     osg::ref_ptr<osg::ClipPlane> clipPlane;
     if ( _clipPlane.lock(clipPlane) )
     {
-        osg::Vec3d eye = nv->getEyePoint();
+        osg::ref_ptr<Horizon> horizon = Horizon::get(*nv);
+        if ( !horizon.valid() ) 
+        {
+            horizon = new Horizon(*_horizon.get());
+            horizon->setEye( nv->getViewPoint() );
+        }
 
-        // viewer in ellipsoidal unit space:
-        osg::Vec3d unitEye( eye.x()/_radii.x(), eye.y()/_radii.y(), eye.z()/_radii.z());
+        osg::Plane horizonPlane;
+        horizon->getPlane( horizonPlane );
 
-        // calculate scaled distance from center to viewer:
-        double unitEyeLen = unitEye.length();
+        _clipPlane->setClipPlane( horizonPlane );
+    }
+    traverse(node, nv);
+}
 
-        // calculate scaled distance from center to horizon plane:
-        double unitHorizonPlaneLen = 1.0/unitEyeLen;
+//......................................................................
 
-        // convert back to real space:
-        double eyeLen = eye.length();
-        double horizonPlaneLen = eyeLen * unitHorizonPlaneLen/unitEyeLen;
+namespace
+{
+    Config dumpStateGraph(osgUtil::StateGraph* sg)
+    {
+        Config conf("StateGraph");
 
-        // normalize the eye vector:
-        eye /= eyeLen;
+        Config leaves("Leaves");
+        for(osgUtil::StateGraph::LeafList::const_iterator i = sg->_leaves.begin(); i != sg->_leaves.end(); ++i)
+        {
+            Config leaf("Leaf");
+            leaf.add("Name", i->get()->getDrawable()->getName());
+            leaf.add("Depth", i->get()->_depth);
+            leaves.add( leaf );
+        }
+        if ( !leaves.empty() )
+            conf.add(leaves);
 
-        // compute a new clip plane:
-        clipPlane->setClipPlane(osg::Plane(eye, eye*horizonPlaneLen));
+        Config kids("Children");
+        for(osgUtil::StateGraph::ChildList::const_iterator i = sg->_children.begin(); i != sg->_children.end(); ++i)
+        {
+            kids.add( dumpStateGraph(i->second.get()) );
+        }
+        if ( !kids.children().empty() )
+            conf.add(kids);
+
+        return conf;
     }
-    traverse(node, nv);
+}
+
+Config
+CullDebugger::dumpRenderBin(osgUtil::RenderBin* bin) const
+{
+    Config conf("RenderBin");
+    if ( !bin->getName().empty() )
+        conf.set("Name", bin->getName());
+    conf.set("BinNum", bin->getBinNum());
+    
+    Config sg("StateGraphList");
+    sg.add("NumChildren", bin->getStateGraphList().size());
+
+    for(osgUtil::RenderBin::StateGraphList::const_iterator i = bin->getStateGraphList().begin(); i != bin->getStateGraphList().end(); ++i)
+    {
+        sg.add( dumpStateGraph(*i) );
+    }
+
+    if ( !sg.children().empty() )
+        conf.add(sg);
+
+    Config rb("_children");
+    for(osgUtil::RenderBin::RenderBinList::const_iterator i = bin->getRenderBinList().begin(); i != bin->getRenderBinList().end(); ++i)
+    {
+        osgUtil::RenderBin* childBin = i->second.get();
+        rb.add( dumpRenderBin(childBin) );
+    }
+    if ( !rb.children().empty() )
+        conf.add(rb);
+
+    return conf;
 }
diff --git a/src/osgEarth/DPLineSegmentIntersector b/src/osgEarth/DPLineSegmentIntersector
index 2193903..2ce1a5d 100644
--- a/src/osgEarth/DPLineSegmentIntersector
+++ b/src/osgEarth/DPLineSegmentIntersector
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarth/DPLineSegmentIntersector.cpp b/src/osgEarth/DPLineSegmentIntersector.cpp
index 7d2897b..1d151a7 100644
--- a/src/osgEarth/DPLineSegmentIntersector.cpp
+++ b/src/osgEarth/DPLineSegmentIntersector.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -18,8 +18,9 @@
  */
 #include <osgEarth/DPLineSegmentIntersector>
 #include <osgEarth/Utils>
-#include <osg/KdTree>
 #include <osg/TriangleFunctor>
+#include <osg/KdTree>
+#include <osgEarth/QuadTree>
 
 using namespace osgEarth;
 
@@ -253,75 +254,151 @@ DPLineSegmentIntersector::clone(osgUtil::IntersectionVisitor& iv)
     lsi->_intersectionLimit = this->_intersectionLimit;
     return lsi.release();
 }
-        
-void
-DPLineSegmentIntersector::intersect(osgUtil::IntersectionVisitor& iv, osg::Drawable* drawable)
+
+void intersectWithKdTree(osgUtil::IntersectionVisitor& iv, osg::Drawable* drawable
+    , const osg::Vec3d s, const osg::Vec3d e
+    , const osg::Vec3d _start, const osg::Vec3d _end
+    , osg::KdTree* kdTree
+    , DPLineSegmentIntersector& intersector)
 {
-    if (reachedLimit()) return;
+    osg::KdTree::LineSegmentIntersections intersections;
+    intersections.reserve(4);
+    if (kdTree->intersect(s,e,intersections))
+    {
+        // OSG_NOTICE<<"Got KdTree intersections"<<std::endl;
+        for(osg::KdTree::LineSegmentIntersections::iterator itr = intersections.begin();
+            itr != intersections.end();
+            ++itr)
+        {
+            osg::KdTree::LineSegmentIntersection& lsi = *(itr);
 
-    osg::Vec3d s(_start), e(_end);
-    if ( !intersectAndClip( s, e, Utils::getBoundingBox(drawable))) return;
+            // get ratio in s,e range
+            double ratio = lsi.ratio;
 
-    if (iv.getDoDummyTraversal()) return;
+            // remap ratio into _start, _end range
+            double remap_ratio = ((s-_start).length() + ratio * (e-s).length() )/(_end-_start).length();
 
-    osg::KdTree* kdTree = iv.getUseKdTreeWhenAvailable() ? dynamic_cast<osg::KdTree*>(drawable->getShape()) : 0;
-    if (kdTree)
-    {
-        osg::KdTree::LineSegmentIntersections intersections;
-        intersections.reserve(4);
-        if (kdTree->intersect(s,e,intersections))
-        {
-            // OSG_NOTICE<<"Got KdTree intersections"<<std::endl;
-            for(osg::KdTree::LineSegmentIntersections::iterator itr = intersections.begin();
-                itr != intersections.end();
-                ++itr)
+
+            osgUtil::LineSegmentIntersector::Intersection hit;
+            hit.ratio = remap_ratio;
+            hit.matrix = iv.getModelMatrix();
+            hit.nodePath = iv.getNodePath();
+            hit.drawable = drawable;
+            hit.primitiveIndex = lsi.primitiveIndex;
+
+            hit.localIntersectionPoint = _start*(1.0-remap_ratio) + _end*remap_ratio;
+
+            // OSG_NOTICE<<"KdTree: ratio="<<hit.ratio<<" ("<<hit.localIntersectionPoint<<")"<<std::endl;
+
+            hit.localIntersectionNormal = lsi.intersectionNormal;
+
+            hit.indexList.reserve(3);
+            hit.ratioList.reserve(3);
+            if (lsi.r0!=0.0f)
             {
-                osg::KdTree::LineSegmentIntersection& lsi = *(itr);
+                hit.indexList.push_back(lsi.p0);
+                hit.ratioList.push_back(lsi.r0);
+            }
 
-                // get ratio in s,e range
-                double ratio = lsi.ratio;
+            if (lsi.r1!=0.0f)
+            {
+                hit.indexList.push_back(lsi.p1);
+                hit.ratioList.push_back(lsi.r1);
+            }
 
-                // remap ratio into _start, _end range
-                double remap_ratio = ((s-_start).length() + ratio * (e-s).length() )/(_end-_start).length();
+            if (lsi.r2!=0.0f)
+            {
+                hit.indexList.push_back(lsi.p2);
+                hit.ratioList.push_back(lsi.r2);
+            }
 
+            intersector.insertIntersection(hit);
+        }
+    }
+}
+        
+void intersectWithQuadTree(osgUtil::IntersectionVisitor& iv, osg::Drawable* drawable
+    , const osg::Vec3d s, const osg::Vec3d e
+    , const osg::Vec3d _start, const osg::Vec3d _end
+    , QuadTree* quadTree
+    , DPLineSegmentIntersector& intersector)
+{
+    QuadTree::LineSegmentIntersections intersections;
+    intersections.reserve(4);
+    if (quadTree->intersect(s,e,intersections))
+    {
+        // OSG_NOTICE<<"Got QuadTree intersections"<<std::endl;
+        for(QuadTree::LineSegmentIntersections::iterator itr = intersections.begin();
+            itr != intersections.end();
+            ++itr)
+        {
+            QuadTree::LineSegmentIntersection& lsi = *(itr);
 
-                Intersection hit;
-                hit.ratio = remap_ratio;
-                hit.matrix = iv.getModelMatrix();
-                hit.nodePath = iv.getNodePath();
-                hit.drawable = drawable;
-                hit.primitiveIndex = lsi.primitiveIndex;
+            // get ratio in s,e range
+            double ratio = lsi.ratio;
 
-                hit.localIntersectionPoint = _start*(1.0-remap_ratio) + _end*remap_ratio;
+            // remap ratio into _start, _end range
+            double remap_ratio = ((s-_start).length() + ratio * (e-s).length() )/(_end-_start).length();
 
-                // OSG_NOTICE<<"KdTree: ratio="<<hit.ratio<<" ("<<hit.localIntersectionPoint<<")"<<std::endl;
 
-                hit.localIntersectionNormal = lsi.intersectionNormal;
+            osgUtil::LineSegmentIntersector::Intersection hit;
+            hit.ratio = remap_ratio;
+            hit.matrix = iv.getModelMatrix();
+            hit.nodePath = iv.getNodePath();
+            hit.drawable = drawable;
+            hit.primitiveIndex = lsi.primitiveIndex;
 
-                hit.indexList.reserve(3);
-                hit.ratioList.reserve(3);
-                if (lsi.r0!=0.0f)
-                {
-                    hit.indexList.push_back(lsi.p0);
-                    hit.ratioList.push_back(lsi.r0);
-                }
+            hit.localIntersectionPoint = _start*(1.0-remap_ratio) + _end*remap_ratio;
 
-                if (lsi.r1!=0.0f)
-                {
-                    hit.indexList.push_back(lsi.p1);
-                    hit.ratioList.push_back(lsi.r1);
-                }
+            // OSG_NOTICE<<"QuadTree: ratio="<<hit.ratio<<" ("<<hit.localIntersectionPoint<<")"<<std::endl;
 
-                if (lsi.r2!=0.0f)
-                {
-                    hit.indexList.push_back(lsi.p2);
-                    hit.ratioList.push_back(lsi.r2);
-                }
+            hit.localIntersectionNormal = lsi.intersectionNormal;
+
+            hit.indexList.reserve(3);
+            hit.ratioList.reserve(3);
+            if (lsi.r0!=0.0f)
+            {
+                hit.indexList.push_back(lsi.p0);
+                hit.ratioList.push_back(lsi.r0);
+            }
+
+            if (lsi.r1!=0.0f)
+            {
+                hit.indexList.push_back(lsi.p1);
+                hit.ratioList.push_back(lsi.r1);
+            }
 
-                insertIntersection(hit);
+            if (lsi.r2!=0.0f)
+            {
+                hit.indexList.push_back(lsi.p2);
+                hit.ratioList.push_back(lsi.r2);
             }
+
+            intersector.insertIntersection(hit);
         }
+    }
+}
+void
+DPLineSegmentIntersector::intersect(osgUtil::IntersectionVisitor& iv, osg::Drawable* drawable)
+{
+    if (reachedLimit()) return;
+
+    osg::Vec3d s(_start), e(_end);
+    if ( !intersectAndClip( s, e, Utils::getBoundingBox(drawable))) return;
+
+    if (iv.getDoDummyTraversal()) return;
+
+    osg::KdTree* kdTree = iv.getUseKdTreeWhenAvailable() ? dynamic_cast<osg::KdTree*>(drawable->getShape()) : 0;
+    if (kdTree)
+    {
+        intersectWithKdTree(iv, drawable, s, e, _start, _end, kdTree, *this);
+        return;
+    }
 
+    QuadTree* quadTree = iv.getUseKdTreeWhenAvailable() ? dynamic_cast<QuadTree*>(drawable->getShape()) : 0;
+    if (quadTree)
+    {
+        intersectWithQuadTree(iv, drawable, s, e, _start, _end, quadTree, *this);
         return;
     }
 
diff --git a/src/osgEarth/DateTime.cpp b/src/osgEarth/DateTime.cpp
index 89f26f7..4aed937 100644
--- a/src/osgEarth/DateTime.cpp
+++ b/src/osgEarth/DateTime.cpp
@@ -94,10 +94,13 @@ DateTime::DateTime(int year, int month, int day, double hour)
     else memset( &_tm, 0, sizeof(tm) );
 }
 
-DateTime::DateTime(const std::string& input)
+DateTime::DateTime(const std::string& input) :
+_time_t(0)
 {
     bool ok = false;
     int year, month, day, hour, min, sec;
+    
+    ::memset( &_tm, 0, sizeof(tm) );
 
     if (sscanf(input.c_str(), "%4d-%2d-%2dT%2d:%2d:%2d", &year, &month, &day, &hour, &min, &sec) == 6)
     {
@@ -146,7 +149,6 @@ DateTime::DateTime(const std::string& input)
         _time_t =  this->timegm( &_tm );
         tm* temp = ::gmtime( &_time_t );
         if ( temp ) _tm = *temp;
-        else memset( &_tm, 0, sizeof(tm) );
     }
 }
 
diff --git a/src/osgEarth/DateTimeRange b/src/osgEarth/DateTimeRange
new file mode 100644
index 0000000..a1c7bd0
--- /dev/null
+++ b/src/osgEarth/DateTimeRange
@@ -0,0 +1,52 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+* Copyright 2008-2012 Pelican Mapping
+* http://osgearth.org
+*
+* osgEarth is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* 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.
+*
+* You should have received a copy of the GNU Lesser General Public License
+* along with this program.  If not, see <http://www.gnu.org/licenses/>
+*/
+#ifndef OSGEARTH_DATE_TIME_RANGE_H
+#define OSGEARTH_DATE_TIME_RANGE_H
+
+#include <osgEarth/DateTime>
+#include <osgEarth/optional>
+
+namespace osgEarth
+{
+    class OSGEARTH_EXPORT DateTimeRange
+    {
+    public:
+        optional<DateTime>& begin() { return _begin; }
+        const optional<DateTime>& begin() const { return _begin; }
+
+        optional<DateTime>& end() { return _end; }
+        const optional<DateTime>& end() const { return _end; }
+
+        void expandBy(const DateTime& other);
+        void expandBy(const DateTimeRange& other);
+
+        bool intersects(const DateTime& other) const;
+        bool intersects(const DateTimeRange& other) const;
+
+    private:
+        optional<DateTime> _begin;
+        optional<DateTime> _end;
+    };
+
+} // namespace osgEarth
+
+#endif // OSGEARTH_DATE_TIME_RANGE_H
diff --git a/src/osgEarth/DateTimeRange.cpp b/src/osgEarth/DateTimeRange.cpp
new file mode 100644
index 0000000..f064e16
--- /dev/null
+++ b/src/osgEarth/DateTimeRange.cpp
@@ -0,0 +1,91 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+* Copyright 2008-2012 Pelican Mapping
+* http://osgearth.org
+*
+* osgEarth is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* 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.
+*
+* You should have received a copy of the GNU Lesser General Public License
+* along with this program.  If not, see <http://www.gnu.org/licenses/>
+*/
+#include <osgEarth/DateTimeRange>
+
+using namespace osgEarth;
+
+void DateTimeRange::expandBy(const DateTime& other)
+{
+    if (!_begin.isSet() || _begin->asTimeStamp() > other.asTimeStamp())
+    {
+        _begin = other;
+    }
+
+    if (!_end.isSet() || _end->asTimeStamp() < other.asTimeStamp())
+    {
+        _end = other;
+    }
+}
+
+void DateTimeRange::expandBy(const DateTimeRange& other)
+{
+    if (other.begin().isSet())
+    {
+        expandBy(other.begin().get());
+    }
+
+    if (other.end().isSet())
+    {
+        expandBy(other.end().get());
+    }
+}
+
+bool DateTimeRange::intersects(const DateTime& other) const
+{
+    return ((!_begin.isSet() || _begin->asTimeStamp() <= other.asTimeStamp()) &&
+            (!_end.isSet() || _end->asTimeStamp() >= other.asTimeStamp()));
+}
+
+bool DateTimeRange::intersects(const DateTimeRange& other) const
+{
+    if (!_begin.isSet() && !_end.isSet()) //infinite range
+    {
+        return true;
+    }
+
+    if (!other.begin().isSet() && !other.end().isSet()) //other is infinite range
+    {
+        return true;
+    }
+
+    if (other.begin().isSet() && intersects(other.begin().get()))
+    {
+        return true;
+    }
+
+    if (other.end().isSet() && intersects(other.end().get()))
+    {
+        return true;
+    }
+
+    if (_begin.isSet() && other.intersects(_begin.get()))
+    {
+        return true;
+    }
+
+    if (_end.isSet() && other.intersects(_end.get()))
+    {
+        return true;
+    }
+
+    return false;
+}
\ No newline at end of file
diff --git a/src/osgEarth/Decluttering b/src/osgEarth/Decluttering
deleted file mode 100644
index e833e3b..0000000
--- a/src/osgEarth/Decluttering
+++ /dev/null
@@ -1,178 +0,0 @@
-/* -*-c++-*- */
-/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
-* http://osgearth.org
-*
-* osgEarth is free software; you can redistribute it and/or modify
-* it under the terms of the GNU Lesser General Public License as published by
-* the Free Software Foundation; either version 2 of the License, or
-* (at your option) any later version.
-*
-* 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.
-*
-* You should have received a copy of the GNU Lesser General Public License
-* along with this program.  If not, see <http://www.gnu.org/licenses/>
-*/
-#ifndef OSGEARTH_DECLUTTER_RENDER_BIN_H
-#define OSGEARTH_DECLUTTER_RENDER_BIN_H 1
-
-#include <osgEarth/Common>
-#include <osgEarth/Config>
-#include <osg/Drawable>
-#include <osgUtil/RenderLeaf>
-#include <limits.h>
-
-/**
- * To apply the "decluttering" algorithm to a subgraph, call
- *
- * Decluttering::setEnabled( node->getOrCreateStateSet(), true );
- */
-
-#define OSGEARTH_DECLUTTER_BIN "osgearth_declutter"
-
-namespace osgEarth
-{
-    /**
-     * Marker class hinting that an implementation supports the decluttering
-     * render bin.
-     */
-    class SupportsDecluttering
-    {
-        //nop
-    };
-
-    /**
-     * Interface that exposes set/getPriority for priority sorting
-     */
-    class PriorityProvider
-    {
-    public:
-        virtual void setPriority(float value) =0;
-        virtual float getPriority() const =0;
-
-    protected:
-        virtual ~PriorityProvider() { }
-    };
-
-    /**
-     * Custom functor that compares two RenderLeaf's and returns TRUE if the left-hand one
-     * is higher priority, otherwise FALSE. You can call setDeclutterPriorityFunctor()
-     * to set a custom priority-sorting functor.
-     */
-    struct DeclutterSortFunctor : public osg::Referenced
-    {
-        virtual bool operator() ( const osgUtil::RenderLeaf* lhs, const osgUtil::RenderLeaf* rhs ) const =0;
-        virtual ~DeclutterSortFunctor() { }
-    };
-
-    /**
-     * A decluttering functor that sorts by the priority field in AnnotationData.
-     * AnnotationData should be attached to each Drawable's user data.
-     */
-    struct OSGEARTH_EXPORT DeclutterByPriority : public DeclutterSortFunctor
-    {
-        virtual bool operator()(const osgUtil::RenderLeaf* lhs, const osgUtil::RenderLeaf* rhs ) const;
-        virtual ~DeclutterByPriority() { }
-    };
-
-    /**
-     * Options to control the annotation decluttering engine.
-     */
-    class OSGEARTH_EXPORT DeclutteringOptions
-    {
-    public:
-        DeclutteringOptions( const Config& conf =Config() )
-            : _minAnimAlpha         ( 0.35f ),
-              _minAnimScale         ( 0.45f ),
-              _inAnimTime           ( 0.40f ),
-              _outAnimTime          ( 0.00f ),
-              _sortByPriority       ( false ),
-              _maxObjects           ( INT_MAX )
-        {
-            fromConfig(conf);
-        }
-
-        virtual ~DeclutteringOptions() { }
-
-        /** Alpha value of a fully-occluded object */
-        optional<float>& minAnimationAlpha() { return _minAnimAlpha; }
-        const optional<float>& minAnimationAlpha() const { return _minAnimAlpha; }
-
-        /** Scale factor of a fully-occluded object */
-        optional<float>& minAnimationScale() { return _minAnimScale; }
-        const optional<float>& minAnimationScale() const { return _minAnimScale; }
-
-        /** Time (in seconds) for an object to transition from occluded to visible */
-        optional<float>& inAnimationTime() { return _inAnimTime; }
-        const optional<float>& inAnimationTime() const { return _inAnimTime; }
-
-        /** Time (in seconds) for an object to transition from visible to occluded */
-        optional<float>& outAnimationTime() { return _outAnimTime; }
-        const optional<float>& outAnimationTime() const { return _outAnimTime; }
-
-        /** If set, activate the AnnotationData priority-based sorting */
-        optional<bool>& sortByPriority() { return _sortByPriority; }
-        const optional<bool>& sortByPriority() const { return _sortByPriority; }
-
-        /** Maximum number of objects to draw after sorting */
-        optional<unsigned>& maxObjects() { return _maxObjects; }
-        const optional<unsigned>& maxObjects() const { return _maxObjects; }
-
-    public:
-
-        Config getConfig() const;
-
-    protected:
-        optional<float>    _minAnimAlpha;
-        optional<float>    _minAnimScale;
-        optional<float>    _inAnimTime;
-        optional<float>    _outAnimTime;
-        optional<bool>     _sortByPriority;
-        optional<unsigned> _maxObjects;
-
-        void fromConfig( const Config& conf );
-    };
-
-    struct OSGEARTH_EXPORT Decluttering
-    {
-        /**
-         * Enables or disables decluttering on a stateset.
-         */
-        static void setEnabled( osg::StateSet* stateSet, bool enabled, int binNum =13 );
-
-        /**
-         * Enables or disables decluttering globally.
-         */
-        static void setEnabled( bool enabled );
-
-        /**
-         * Sets a functor to use to determine render leaf priority for declutter sorting.
-         */
-        static void setSortFunctor( DeclutterSortFunctor* f );
-
-        /**
-         * Clears a custom priority functor that was set using setDeclutterPriorityFunctor,
-         * reverting to the default behavior (which is to sort by distance from the camera).
-         */
-        static void clearSortFunctor();
-
-        /**
-         * Applies the provided options to the decluttering engine.
-         */
-        static void setOptions( const DeclutteringOptions& options );
-
-        /**
-         * Fetches the current decluttering options
-         */
-        static const DeclutteringOptions& getOptions();
-    };
-
-} // namespace osgEarth
-
-#endif //OSGEARTH_DECLUTTER_RENDER_BIN_H
diff --git a/src/osgEarth/Decluttering.cpp b/src/osgEarth/Decluttering.cpp
deleted file mode 100644
index 6ee6705..0000000
--- a/src/osgEarth/Decluttering.cpp
+++ /dev/null
@@ -1,807 +0,0 @@
-/* -*-c++-*- */
-/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
-* http://osgearth.org
-*
-* osgEarth is free software; you can redistribute it and/or modify
-* it under the terms of the GNU Lesser General Public License as published by
-* the Free Software Foundation; either version 2 of the License, or
-* (at your option) any later version.
-*
-* 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.
-*
-* You should have received a copy of the GNU Lesser General Public License
-* along with this program.  If not, see <http://www.gnu.org/licenses/>
-*/
-#include <osgEarth/Decluttering>
-#include <osgEarth/ThreadingUtils>
-#include <osgEarth/Containers>
-#include <osgEarth/Utils>
-#include <osgEarth/VirtualProgram>
-#include <osgUtil/RenderBin>
-#include <osgUtil/StateGraph>
-#include <osgText/Text>
-#include <osg/UserDataContainer>
-#include <set>
-#include <algorithm>
-
-#define LC "[Declutter] "
-
-#define FADE_UNIFORM_NAME "oe_declutter_fade"
-
-using namespace osgEarth;
-
-//----------------------------------------------------------------------------
-
-namespace
-{
-    // Sort wrapper to satisfy the template processor.
-    struct SortContainer
-    {
-        SortContainer( DeclutterSortFunctor& f ) : _f(f) { }
-        const DeclutterSortFunctor& _f;
-        bool operator()( const osgUtil::RenderLeaf* lhs, const osgUtil::RenderLeaf* rhs ) const 
-        {
-            return _f(lhs, rhs);
-        }
-    };
-
-    // Custom sorting functor that sorts drawables front-to-back, and when drawables share the
-    // same parent Geode, sorts them in traversal order.
-    struct SortFrontToBackPreservingGeodeTraversalOrder
-    {
-        bool operator()( const osgUtil::RenderLeaf* lhs, const osgUtil::RenderLeaf* rhs ) const
-        {
-            const osg::Node* lhsParentNode = lhs->getDrawable()->getParent(0);
-            if ( lhsParentNode == rhs->getDrawable()->getParent(0) )
-            {
-                const osg::Geode* geode = static_cast<const osg::Geode*>(lhsParentNode);
-                return geode->getDrawableIndex(lhs->getDrawable()) > geode->getDrawableIndex(rhs->getDrawable());
-            }
-            else
-            {
-                return ( lhs->_depth < rhs->_depth );
-            }
-        }
-    };
-
-    // Data structure shared across entire decluttering system.
-    struct DeclutterContext : public osg::Referenced
-    {
-        DeclutteringOptions _options;
-    };
-
-    // records information about each drawable.
-    // TODO: a way to clear out this list when drawables go away
-    struct DrawableInfo
-    {
-        DrawableInfo() : _lastAlpha(1.0), _lastScale(1.0) { }
-        float _lastAlpha, _lastScale;
-    };
-
-    typedef std::map<const osg::Drawable*, DrawableInfo> DrawableMemory;
-    
-    typedef std::pair<const osg::Node*, osg::BoundingBox> RenderLeafBox;
-
-    // Data structure stored one-per-View.
-    struct PerCamInfo
-    {
-        PerCamInfo() : _firstFrame(true) { }
-
-        // remembers the state of each drawable from the previous pass
-        DrawableMemory _memory;
-        
-        // re-usable structures (to avoid unnecessary re-allocation)
-        osgUtil::RenderBin::RenderLeafList _passed;
-        osgUtil::RenderBin::RenderLeafList _failed;
-        std::vector<RenderLeafBox>         _used;
-
-        // time stamp of the previous pass, for calculating animation speed
-        //double _lastTimeStamp;
-        osg::Timer_t _lastTimeStamp;
-        bool _firstFrame;
-    };
-
-    static bool s_enabledGlobally = true;
-
-    static const char* s_faderFS =
-        "#version " GLSL_VERSION_STR "\n"
-        GLSL_DEFAULT_PRECISION_FLOAT "\n"
-        "uniform float " FADE_UNIFORM_NAME ";\n"
-        "void oe_declutter_apply_fade(inout vec4 color) { \n"
-        "    color.a *= " FADE_UNIFORM_NAME ";\n"
-        "}\n";
-}
-
-//----------------------------------------------------------------------------
-
-void
-DeclutteringOptions::fromConfig( const Config& conf )
-{
-    conf.getIfSet( "min_animation_scale", _minAnimScale );
-    conf.getIfSet( "min_animation_alpha", _minAnimAlpha );
-    conf.getIfSet( "in_animation_time",   _inAnimTime );
-    conf.getIfSet( "out_animation_time",  _outAnimTime );
-    conf.getIfSet( "sort_by_priority",    _sortByPriority );
-    conf.getIfSet( "max_objects",         _maxObjects );
-}
-
-Config
-DeclutteringOptions::getConfig() const
-{
-    Config conf;
-    conf.addIfSet( "min_animation_scale", _minAnimScale );
-    conf.addIfSet( "min_animation_alpha", _minAnimAlpha );
-    conf.addIfSet( "in_animation_time",   _inAnimTime );
-    conf.addIfSet( "out_animation_time",  _outAnimTime );
-    conf.addIfSet( "sort_by_priority",    _sortByPriority );
-    conf.addIfSet( "max_objects",         _maxObjects );
-    return conf;
-}
-
-//----------------------------------------------------------------------------
-
-/**
- * A custom RenderLeaf sorting algorithm for decluttering objects.
- *
- * First we sort the leaves front-to-back so that objects closer to the camera
- * get higher priority. If you have installed a custom sorting functor,
- * this is used instead.
- *
- * Next, we go though all the drawables and remove any that try to occupy
- * already-occupied real estate in the 2D viewport. Objects that fail the test
- * go on a "failed" list and are either completely removed from the display
- * or transitioned to a secondary visual state (scaled down, alpha'd down)
- * dependeing on the options setup.
- *
- * Drawables with the same parent (i.e., Geode) are treated as a group. As
- * soon as one passes the occlusion test, all its siblings will automatically
- * pass as well.
- */
-struct /*internal*/ DeclutterSort : public osgUtil::RenderBin::SortCallback
-{
-    DeclutterSortFunctor* _customSortFunctor;
-    DeclutterContext*     _context;
-
-    PerObjectFastMap<osg::Camera*, PerCamInfo> _perCam;
-
-    /**
-     * Constructs the new sorter.
-     * @param f Custom declutter sorting predicate. Pass NULL to use the 
-     *          default sorter (sort by distance-to-camera).
-     */
-    DeclutterSort( DeclutterContext* context, DeclutterSortFunctor* f = 0L )
-        : _context(context), _customSortFunctor(f)
-    {
-        //nop
-    }
-
-    // override.
-    // Sorts the bin. This runs in the CULL thread after the CULL traversal has completed.
-    void sortImplementation(osgUtil::RenderBin* bin)
-    {
-        osgUtil::RenderBin::RenderLeafList& leaves = bin->getRenderLeafList();
-
-        // first, sort the leaves:
-        if ( _customSortFunctor && s_enabledGlobally )
-        {
-            // if there's a custom sorting function installed
-            bin->copyLeavesFromStateGraphListToRenderLeafList();
-            std::sort( leaves.begin(), leaves.end(), SortContainer( *_customSortFunctor ) );
-        }
-        else
-        {
-            // default behavior:
-            bin->copyLeavesFromStateGraphListToRenderLeafList();
-            std::sort( leaves.begin(), leaves.end(), SortFrontToBackPreservingGeodeTraversalOrder() );
-        }
-
-        // nothing to sort? bail out
-        if ( leaves.size() == 0 )
-            return;
-
-        // access the view-specific persistent data:
-        osg::Camera* cam   = bin->getStage()->getCamera();                
-        PerCamInfo& local = _perCam.get( cam );
-
-        osg::Timer_t now = osg::Timer::instance()->tick();
-        if (local._firstFrame)
-        {            
-            local._firstFrame = false;
-            local._lastTimeStamp = now;
-        }
-
-        // calculate the elapsed time since the previous pass; we'll use this for
-        // the animations                
-        float elapsedSeconds = osg::Timer::instance()->delta_s(local._lastTimeStamp, now);
-        local._lastTimeStamp = now;
-
-        // Reset the local re-usable containers
-        local._passed.clear();          // drawables that pass occlusion test
-        local._failed.clear();          // drawables that fail occlusion test
-        local._used.clear();            // list of occupied bounding boxes in screen space
-
-        // compute a window matrix so we can do window-space culling. If this is an RTT camera
-        // with a reference camera attachment, we actually want to declutter in the window-space
-        // of the reference camera.
-        const osg::Viewport* vp = cam->getViewport();
-
-        osg::Matrix windowMatrix = vp->computeWindowMatrix();
-
-        osg::Vec3f  refCamScale(1.0f, 1.0f, 1.0f);
-        osg::Matrix refCamScaleMat;
-        osg::Matrix refWindowMatrix = windowMatrix;
-
-        if ( cam->isRenderToTextureCamera() )
-        {
-            osg::Camera* refCam = dynamic_cast<osg::Camera*>(cam->getUserData());
-            if ( refCam )
-            {
-                const osg::Viewport* refVP = refCam->getViewport();
-                refCamScale.set( vp->width() / refVP->width(), vp->height() / refVP->height(), 1.0 );
-                refCamScaleMat.makeScale( refCamScale );
-                refWindowMatrix = refVP->computeWindowMatrix();
-            }
-        }
-
-        // Track the parent nodes of drawables that are obscured (and culled). Drawables
-        // with the same parent node (typically a Geode) are considered to be grouped and
-        // will be culled as a group.
-        std::set<const osg::Node*> culledParents;
-
-        const DeclutteringOptions& options = _context->_options;
-        unsigned limit = *options.maxObjects();
-
-        // Go through each leaf and test for visibility.
-        // Enforce the "max objects" limit along the way.
-        for(osgUtil::RenderBin::RenderLeafList::iterator i = leaves.begin(); 
-            i != leaves.end() && local._passed.size() < limit; 
-            ++i )
-        {
-            bool visible = true;
-
-            osgUtil::RenderLeaf* leaf = *i;
-            const osg::Drawable* drawable = leaf->getDrawable();
-            const osg::Node*     drawableParent = drawable->getParent(0);
-
-            // transform the bounding box of the drawable into window-space.
-            osg::BoundingBox box = Utils::getBoundingBox(drawable);
-
-            static osg::Vec4d s_zero_w(0,0,0,1);
-            osg::Matrix MVP = (*leaf->_modelview.get()) * (*leaf->_projection.get());
-            osg::Vec4d clip = s_zero_w * MVP;
-            osg::Vec3d clip_ndc( clip.x()/clip.w(), clip.y()/clip.w(), clip.z()/clip.w() );
-            osg::Vec3f winPos = clip_ndc * windowMatrix;
-
-            // this accounts for the size difference when using a reference camera (RTT/picking)
-            box.xMin() *= refCamScale.x();
-            box.xMax() *= refCamScale.x();
-            box.yMin() *= refCamScale.y();
-            box.yMax() *= refCamScale.y();
-
-            osg::Vec2f offset( -box.xMin(), -box.yMin() );
-
-            box.set(
-                winPos.x() + box.xMin(),
-                winPos.y() + box.yMin(),
-                winPos.z(),
-                winPos.x() + box.xMax(),
-                winPos.y() + box.yMax(),
-                winPos.z() );
-
-            // if this leaf is already in a culled group, skip it.
-            if ( s_enabledGlobally )
-            {
-                if ( culledParents.find(drawableParent) != culledParents.end() )
-                {
-                    visible = false;
-                }
-                else
-                {
-                    // weed out any drawables that are obscured by closer drawables.
-                    // TODO: think about a more efficient algorithm - right now we are just using
-                    // brute force to compare all bbox's
-                    for( std::vector<RenderLeafBox>::const_iterator j = local._used.begin(); j != local._used.end(); ++j )
-                    {
-                        // only need a 2D test since we're in clip space
-                        bool isClear =
-                            box.xMin() > j->second.xMax() ||
-                            box.xMax() < j->second.xMin() ||
-                            box.yMin() > j->second.yMax() ||
-                            box.yMax() < j->second.yMin();
-
-                        // if there's an overlap (and the conflict isn't from the same drawable
-                        // parent, which is acceptable), then the leaf is culled.
-                        if ( !isClear && drawableParent != j->first )
-                        {
-                            visible = false;
-                            break;
-                        }
-                    }
-                }
-            }
-
-            if ( visible )
-            {
-                // passed the test, so add the leaf's bbox to the "used" list, and add the leaf
-                // to the final draw list.
-                //local._used.push_back( std::make_pair(drawableParent, box) );
-                local._used.push_back( std::make_pair(drawableParent, box) );
-                local._passed.push_back( leaf );
-            }
-
-            else
-            {
-                // culled, so put the parent in the parents list so that any future leaves
-                // with the same parent will be trivially rejected
-                culledParents.insert( drawable->getParent(0) );
-                local._failed.push_back( leaf );
-            }
-
-            // modify the leaf's modelview matrix to correctly position it in the 2D ortho
-            // projection when it's drawn later. We'll also preserve the scale.
-            osg::Matrix newModelView;
-            newModelView.makeTranslate( box.xMin() + offset.x(), box.yMin() + offset.y(), 0 );
-            newModelView.preMultScale( leaf->_modelview->getScale() * refCamScaleMat );
-            
-            // Leaf modelview matrixes are shared (by objects in the traversal stack) so we 
-            // cannot just replace it unfortunately. Have to make a new one. Perhaps a nice
-            // allocation pool is in order here
-            leaf->_modelview = new osg::RefMatrix( newModelView );
-        }
-
-        // copy the final draw list back into the bin, rejecting any leaves whose parents
-        // are in the cull list.
-
-        if ( s_enabledGlobally )
-        {
-            leaves.clear();
-            for( osgUtil::RenderBin::RenderLeafList::const_iterator i=local._passed.begin(); i != local._passed.end(); ++i )
-            {
-                osgUtil::RenderLeaf* leaf     = *i;
-                const osg::Drawable* drawable = leaf->getDrawable();
-
-                if ( culledParents.find( drawable->getParent(0) ) == culledParents.end() )
-                {
-                    DrawableInfo& info = local._memory[drawable];
-
-                    bool fullyIn = true;
-
-                    // scale in until at full scale:
-                    if ( info._lastScale != 1.0f )
-                    {
-                        fullyIn = false;
-                        info._lastScale += elapsedSeconds / std::max(*options.inAnimationTime(), 0.001f);
-                        if ( info._lastScale > 1.0f )
-                            info._lastScale = 1.0f;
-                    }
-
-                    if ( info._lastScale != 1.0f )
-                        leaf->_modelview->preMult( osg::Matrix::scale(info._lastScale,info._lastScale,1) );
-                    
-                    // fade in until at full alpha:
-                    if ( info._lastAlpha != 1.0f )
-                    {
-                        fullyIn = false;
-                        info._lastAlpha += elapsedSeconds / std::max(*options.inAnimationTime(), 0.001f);
-                        if ( info._lastAlpha > 1.0f )
-                            info._lastAlpha = 1.0f;
-                    }
-
-                    leaf->_depth = info._lastAlpha;
-                    leaves.push_back( leaf );                
-                }
-                else
-                {
-                    local._failed.push_back(leaf);
-                }
-            }
-
-            // next, go through the FAILED list and sort them into failure bins so we can draw
-            // them using a different technique if necessary.
-            for( osgUtil::RenderBin::RenderLeafList::const_iterator i=local._failed.begin(); i != local._failed.end(); ++i )
-            {
-                osgUtil::RenderLeaf* leaf =     *i;
-                const osg::Drawable* drawable = leaf->getDrawable();
-
-                DrawableInfo& info = local._memory[drawable];
-
-                bool isText = dynamic_cast<const osgText::Text*>(drawable) != 0L;
-                bool fullyOut = true;
-
-                if ( info._lastScale != *options.minAnimationScale() )
-                {
-                    fullyOut = false;
-                    info._lastScale -= elapsedSeconds / std::max(*options.outAnimationTime(), 0.001f);
-                    if ( info._lastScale < *options.minAnimationScale() )
-                        info._lastScale = *options.minAnimationScale();
-                }
-
-                if ( info._lastAlpha != *options.minAnimationAlpha() )
-                {
-                    fullyOut = false;
-                    info._lastAlpha -= elapsedSeconds / std::max(*options.outAnimationTime(), 0.001f);
-                    if ( info._lastAlpha < *options.minAnimationAlpha() )
-                        info._lastAlpha = *options.minAnimationAlpha();
-                }
-
-                leaf->_depth = info._lastAlpha;
-
-                if ( !isText || !fullyOut )
-                {
-                    if ( info._lastAlpha > 0.01f && info._lastScale >= 0.0f )
-                    {
-                        leaves.push_back( leaf );
-
-                        // scale it:
-                        if ( info._lastScale != 1.0f )
-                            leaf->_modelview->preMult( osg::Matrix::scale(info._lastScale,info._lastScale,1) );
-                    }
-                }
-            }
-        }
-    }
-};
-
-/**
- * Custom draw routine for our declutter render bin.
- */
-struct DeclutterDraw : public osgUtil::RenderBin::DrawCallback
-{
-    DeclutterContext*                         _context;
-    PerThread< osg::ref_ptr<osg::RefMatrix> > _ortho2D;
-    osg::ref_ptr<osg::Uniform>                _fade;
-
-    /**
-     * Constructs the decluttering draw callback.
-     * @param context A shared context among all decluttering objects.
-     */
-    DeclutterDraw( DeclutterContext* context )
-        : _context( context )
-    {
-        // create the fade uniform.
-        _fade = new osg::Uniform( osg::Uniform::FLOAT, FADE_UNIFORM_NAME );
-        _fade->set( 1.0f );
-    }
-
-    /**
-     * Draws a bin. Most of this code is copied from osgUtil::RenderBin::drawImplementation.
-     * The modifications are (a) skipping code to render child bins, (b) setting a bin-global
-     * projection matrix in orthographic space, and (c) calling our custom "renderLeaf()" method 
-     * instead of RenderLeaf::render()
-     */
-    void drawImplementation( osgUtil::RenderBin* bin, osg::RenderInfo& renderInfo, osgUtil::RenderLeaf*& previous )
-    {
-        osg::State& state = *renderInfo.getState();
-
-        unsigned int numToPop = (previous ? osgUtil::StateGraph::numToPop(previous->_parent) : 0);
-        if (numToPop>1) --numToPop;
-        unsigned int insertStateSetPosition = state.getStateSetStackSize() - numToPop;
-
-        if (bin->getStateSet())
-        {
-            state.insertStateSet(insertStateSetPosition, bin->getStateSet());
-        }
-
-        // apply a window-space projection matrix.
-        const osg::Viewport* vp = renderInfo.getCurrentCamera()->getViewport();
-        if ( vp )
-        {
-            //TODO see which is faster
-
-            osg::ref_ptr<osg::RefMatrix>& m = _ortho2D.get();
-            if ( !m.valid() )
-                m = new osg::RefMatrix();
-
-            m->makeOrtho2D( vp->x(), vp->x()+vp->width()-1, vp->y(), vp->y()+vp->height()-1 );
-            state.applyProjectionMatrix( m.get() );
-
-            //osg::ref_ptr<osg::RefMatrix> rm = new osg::RefMatrix( osg::Matrix::ortho2D(
-            //    vp->x(), vp->x()+vp->width()-1,
-            //    vp->y(), vp->y()+vp->height()-1 ) );
-            //state.applyProjectionMatrix( rm.get() );
-        }
-
-        // render the list
-        osgUtil::RenderBin::RenderLeafList& leaves = bin->getRenderLeafList();
-        for(osgUtil::RenderBin::RenderLeafList::reverse_iterator rlitr = leaves.rbegin();
-            rlitr!= leaves.rend();
-            ++rlitr)
-        {
-            osgUtil::RenderLeaf* rl = *rlitr;
-            renderLeaf( rl, renderInfo, previous );
-            previous = rl;
-        }
-
-        if ( bin->getStateSet() )
-        {
-            state.removeStateSet(insertStateSetPosition);
-        }
-    }
-
-    /**
-     * Renders a single leaf. We already applied the projection matrix, so here we only
-     * need to apply a modelview matrix that specifies the ortho offset of the drawable.
-     *
-     * Most of this code is copied from RenderLeaf::draw() -- but I removed all the code
-     * dealing with nested bins, since decluttering does not support them.
-     */
-    void renderLeaf( osgUtil::RenderLeaf* leaf, osg::RenderInfo& renderInfo, osgUtil::RenderLeaf*& previous )
-    {
-        osg::State& state = *renderInfo.getState();
-
-        // don't draw this leaf if the abort rendering flag has been set.
-        if (state.getAbortRendering())
-        {
-            //cout << "early abort"<<endl;
-            return;
-        }
-
-        state.applyModelViewMatrix( leaf->_modelview.get() );
-
-        if (previous)
-        {
-            // apply state if required.
-            osgUtil::StateGraph* prev_rg = previous->_parent;
-            osgUtil::StateGraph* prev_rg_parent = prev_rg->_parent;
-            osgUtil::StateGraph* rg = leaf->_parent;
-            if (prev_rg_parent!=rg->_parent)
-            {
-                osgUtil::StateGraph::moveStateGraph(state,prev_rg_parent,rg->_parent);
-
-                // send state changes and matrix changes to OpenGL.
-                state.apply(rg->getStateSet());
-
-            }
-            else if (rg!=prev_rg)
-            {
-                // send state changes and matrix changes to OpenGL.
-                state.apply(rg->getStateSet());
-            }
-        }
-        else
-        {
-            // apply state if required.
-            osgUtil::StateGraph::moveStateGraph(state,NULL,leaf->_parent->_parent);
-
-            state.apply(leaf->_parent->getStateSet());
-        }
-
-        // if we are using osg::Program which requires OSG's generated uniforms to track
-        // modelview and projection matrices then apply them now.
-        if (state.getUseModelViewAndProjectionUniforms()) 
-            state.applyModelViewAndProjectionUniformsIfRequired();
-        
-        // apply the fading uniform
-        const osg::Program::PerContextProgram* pcp = state.getLastAppliedProgramObject();
-        if ( pcp )
-        {
-            // todo: find a way to optimize this..?
-            _fade->set( s_enabledGlobally ? leaf->_depth : 1.0f );
-            pcp->apply( *_fade.get() );
-        }
-    
-        // draw the drawable
-        leaf->_drawable->draw(renderInfo);
-        
-        if (leaf->_dynamic)
-        {
-            state.decrementDynamicObjectCount();
-        }
-    }
-};
-
-//----------------------------------------------------------------------------
-
-/**
- * The actual custom render bin
- * This wants to be in the global scope for the dynamic registration to work,
- * hence the annoyinging long class name
- */
-class osgEarthDeclutterRenderBin : public osgUtil::RenderBin
-{
-public:
-    osgEarthDeclutterRenderBin()
-    {
-        this->setName( OSGEARTH_DECLUTTER_BIN );
-        _context = new DeclutterContext();
-        clearSortingFunctor();
-        setDrawCallback( new DeclutterDraw(_context.get()) );
-
-        // needs its own state set for special magic.
-        osg::StateSet* stateSet = new osg::StateSet();
-        this->setStateSet( stateSet );
-
-        // set up a VP to do fading.
-        VirtualProgram* vp = VirtualProgram::getOrCreate(stateSet);
-        vp->setFunction( "oe_declutter_apply_fade", s_faderFS, ShaderComp::LOCATION_FRAGMENT_COLORING, 0.5f );
-    }
-
-    void setSortingFunctor( DeclutterSortFunctor* f )
-    {
-        _f = f;
-        setSortCallback( new DeclutterSort(_context.get(), f) );
-    }
-
-    void clearSortingFunctor()
-    {
-        setSortCallback( new DeclutterSort(_context.get()) );
-    }
-
-    osg::ref_ptr<DeclutterSortFunctor> _f;
-    osg::ref_ptr<DeclutterContext>     _context;
-};
-
-//----------------------------------------------------------------------------
-
-//static
-
-#define STATESET_ID "osgEarth::Decluttering::prevStateSet"
-
-void
-Decluttering::setEnabled( osg::StateSet* stateSet, bool enable, int binNum )
-{
-    // note: even though we're fiddling with the StateSet, I don't think we need
-    // to mark it as DYNAMIC .... but we'll see
-    if ( stateSet )
-    {
-        if ( enable )
-        {
-            osg::StateSet* prevStateSet = 0L;
-            osg::UserDataContainer* udc = stateSet->getOrCreateUserDataContainer();
-            unsigned index = udc->getUserObjectIndex( STATESET_ID );
-            if ( index < udc->getNumUserObjects() )
-            {
-                prevStateSet = dynamic_cast<osg::StateSet*>( udc->getUserObject(index) );
-            }
-
-            if ( !prevStateSet )
-            {
-                prevStateSet = new osg::StateSet();
-                prevStateSet->setName( STATESET_ID );
-                prevStateSet->setBinName( stateSet->getBinName() );
-                prevStateSet->setBinNumber( stateSet->getBinNumber() );
-                prevStateSet->setRenderBinMode( stateSet->getRenderBinMode() );
-                prevStateSet->setNestRenderBins( stateSet->getNestRenderBins() );
-                udc->addUserObject( prevStateSet );
-            }
-
-            // the OVERRIDE prevents subsequent statesets from disabling the decluttering bin,
-            // I guess. This wasn't needed in OSG 3.1.4 but now it is.
-            stateSet->setRenderBinDetails(
-                binNum,
-                OSGEARTH_DECLUTTER_BIN,
-                osg::StateSet::OVERRIDE_RENDERBIN_DETAILS);
-
-            // Force a single shared decluttering bin per render stage
-            stateSet->setNestRenderBins( false );
-        }
-        else
-        {
-            osg::UserDataContainer* udc = stateSet->getOrCreateUserDataContainer();
-            unsigned index = udc->getUserObjectIndex( STATESET_ID );
-            if ( index < udc->getNumUserObjects() )
-            {
-                osg::StateSet* prevStateSet = dynamic_cast<osg::StateSet*>( udc->getUserObject(index) );
-                stateSet->setBinName( prevStateSet->getBinName() );
-                stateSet->setBinNumber( prevStateSet->getBinNumber() );
-                stateSet->setRenderBinMode( prevStateSet->getRenderBinMode() );
-                stateSet->setNestRenderBins( prevStateSet->getNestRenderBins() );
-                udc->removeUserObject( index );
-            }
-        }
-    }
-}
-
-void
-Decluttering::setEnabled( bool enabled )
-{
-    s_enabledGlobally = enabled;
-}
-
-void
-Decluttering::setSortFunctor( DeclutterSortFunctor* functor )
-{
-    // pull our prototype
-    osgEarthDeclutterRenderBin* bin = dynamic_cast<osgEarthDeclutterRenderBin*>(
-        osgUtil::RenderBin::getRenderBinPrototype( OSGEARTH_DECLUTTER_BIN ) );
-
-    if ( bin )
-    {
-        bin->setSortingFunctor( functor );
-    }
-}
-
-void
-Decluttering::clearSortFunctor()
-{
-    // pull our prototype
-    osgEarthDeclutterRenderBin* bin = dynamic_cast<osgEarthDeclutterRenderBin*>(
-        osgUtil::RenderBin::getRenderBinPrototype( OSGEARTH_DECLUTTER_BIN ) );
-
-    if ( bin )
-    {
-        bin->clearSortingFunctor();
-    }
-}
-
-void
-Decluttering::setOptions( const DeclutteringOptions& options )
-{
-    // pull our prototype
-    osgEarthDeclutterRenderBin* bin = dynamic_cast<osgEarthDeclutterRenderBin*>(
-        osgUtil::RenderBin::getRenderBinPrototype( OSGEARTH_DECLUTTER_BIN ) );
-
-    if ( bin )
-    {
-        // activate priority-sorting through the options.
-        if ( options.sortByPriority().isSetTo( true ) &&
-             bin->_context->_options.sortByPriority() == false )
-        {
-            Decluttering::setSortFunctor(new DeclutterByPriority());
-        }
-        
-        // communicate the new options on the shared context.
-        bin->_context->_options = options;
-    }
-}
-
-const DeclutteringOptions&
-Decluttering::getOptions()
-{
-    static DeclutteringOptions s_defaultOptions;
-
-    // pull our prototype
-    osgEarthDeclutterRenderBin* bin = dynamic_cast<osgEarthDeclutterRenderBin*>(
-        osgUtil::RenderBin::getRenderBinPrototype( OSGEARTH_DECLUTTER_BIN ) );
-
-    if ( bin )
-    {
-        return bin->_context->_options;
-    }
-    else
-    {
-        return s_defaultOptions;
-    }
-}
-
-//----------------------------------------------------------------------------
-
-bool
-DeclutterByPriority::operator()(const osgUtil::RenderLeaf* lhs, const osgUtil::RenderLeaf* rhs ) const
-{
-    float diff = 0.0f;
-    const PriorityProvider* lhsData = dynamic_cast<const PriorityProvider*>(lhs->getDrawable()->getUserData());
-    if ( lhsData )
-    {
-        const PriorityProvider* rhsData = dynamic_cast<const PriorityProvider*>(rhs->getDrawable()->getUserData());
-        if ( rhsData )
-        {
-            diff = lhsData->getPriority() - rhsData->getPriority();
-        }
-    }
-
-    if ( diff != 0.0f )
-        return diff > 0.0f;
-
-    // first fallback on depth:
-    diff = lhs->_depth - rhs->_depth;
-    if ( diff != 0.0f )
-        return diff < 0.0f;
-
-    // then fallback on traversal order.
-    diff = float(lhs->_traversalNumber) - float(rhs->_traversalNumber);
-    return diff < 0.0f;
-}
-
-//----------------------------------------------------------------------------
-
-/** the actual registration. */
-extern "C" void osgEarth_declutter(void) {}
-static osgEarthRegisterRenderBinProxy<osgEarthDeclutterRenderBin> s_regbin(OSGEARTH_DECLUTTER_BIN);
diff --git a/src/osgEarth/DepthOffset b/src/osgEarth/DepthOffset
index 0471852..4b4ed6a 100644
--- a/src/osgEarth/DepthOffset
+++ b/src/osgEarth/DepthOffset
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarth/DepthOffset.cpp b/src/osgEarth/DepthOffset.cpp
index dfe4cfc..0ff7b01 100644
--- a/src/osgEarth/DepthOffset.cpp
+++ b/src/osgEarth/DepthOffset.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarth/DepthOffset.vert.glsl b/src/osgEarth/DepthOffset.vert.glsl
index c22e2a8..2ddee8c 100644
--- a/src/osgEarth/DepthOffset.vert.glsl
+++ b/src/osgEarth/DepthOffset.vert.glsl
@@ -1,9 +1,9 @@
 #version $GLSL_VERSION_STR
 $GLSL_DEFAULT_PRECISION_FLOAT
 
-#pragma vp_entryPoint "oe_depthOffset_vertex"
-#pragma vp_location   "vertex_view"
-#pragma vp_order      "0.8"
+#pragma vp_entryPoint oe_depthOffset_vertex
+#pragma vp_location   vertex_view
+#pragma vp_order      0.8
 
 uniform float oe_depthOffset_minBias;
 uniform float oe_depthOffset_maxBias;
diff --git a/src/osgEarth/DrapeableNode b/src/osgEarth/DrapeableNode
index 8de53d6..c0f2bbc 100644
--- a/src/osgEarth/DrapeableNode
+++ b/src/osgEarth/DrapeableNode
@@ -21,7 +21,7 @@
 #define OSGEARTH_DRAPEABLE_NODE_H 1
 
 #include <osgEarth/Common>
-#include <osgEarth/OverlayNode>
+#include <osgEarth/optional>
 #include <osg/Group>
 
 namespace osgEarth
@@ -35,28 +35,35 @@ namespace osgEarth
      * Usage: Create this node and put it anywhere in the scene graph. The
      * subgraph of this node will be draped on the MapNode's terrain.
      */
-    class OSGEARTH_EXPORT DrapeableNode : public OverlayNode
+    class OSGEARTH_EXPORT DrapeableNode : public osg::Group
     {
     public:
+        META_Object(osgEarth, DrapeableNode);
+
         /**
          * Constructs a new drapeable node.
          */
-        DrapeableNode( MapNode* mapNode, bool active =true );
+        DrapeableNode();
+
+        /** Copy */
+        DrapeableNode(const DrapeableNode& rhs, const osg::CopyOp& copy);
+
+        /**
+         * Whether draping is enabled.
+         */
+        void setDrapingEnabled(bool value);
+        bool getDrapingEnabled() const     { return _drapingEnabled; }
 
-        /** Sets the rendering order of the draped geometry */
-        void setRenderOrder(int order);
-        const optional<int>& renderOrder() const { return _renderOrder; }
+    public: // osg::Group/Node
 
-        /** Backwards compatibility */
-        void setDraped( bool value ) { setActive(value); }
-        bool getDraped() const { return getActive(); }
+        virtual void traverse(osg::NodeVisitor& nv);
 
 
     protected:
         /** dtor */
         virtual ~DrapeableNode() { }
 
-        optional<int> _renderOrder;
+        bool _drapingEnabled;
     };
 
 } // namespace osgEarth
diff --git a/src/osgEarth/DrapeableNode.cpp b/src/osgEarth/DrapeableNode.cpp
index 13a9a2a..1f6b488 100644
--- a/src/osgEarth/DrapeableNode.cpp
+++ b/src/osgEarth/DrapeableNode.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -18,36 +18,77 @@
  */
 
 #include <osgEarth/DrapeableNode>
-#include <osgEarth/OverlayDecorator>
-#include <osgEarth/DrapingTechnique>
-#include <osgEarth/MapNode>
+#include <osgEarth/DrapingCullSet>
+#include <osgEarth/Registry>
+#include <osgEarth/CullingUtils>
 
 #define LC "[DrapeableNode] "
 
 using namespace osgEarth;
 
-//------------------------------------------------------------------------
 
-namespace
+DrapeableNode::DrapeableNode() :
+_drapingEnabled( true )
 {
-    static osg::Group* getTechniqueGroup(MapNode* m)
-    {
-        return m ? m->getOverlayDecorator()->getGroup<DrapingTechnique>() : 0L;
-    }
+    // Unfortunetly, there's no way to return a correct bounding sphere for
+    // the node since the draping will move it to the ground. The bounds
+    // check has to be done by the Draping Camera at cull time. Therefore we
+    // have to ensure that this node makes it into the draping cull set so it
+    // can be frustum-culled at the proper time.
+    setCullingActive( !_drapingEnabled );
 }
 
-//------------------------------------------------------------------------
+DrapeableNode::DrapeableNode(const DrapeableNode& rhs, const osg::CopyOp& copy) :
+osg::Group(rhs, copy)
+{
+    _drapingEnabled = rhs._drapingEnabled;
+}
 
-DrapeableNode::DrapeableNode( MapNode* mapNode, bool draped ) :
-OverlayNode( mapNode, draped, &getTechniqueGroup )
+void
+DrapeableNode::setDrapingEnabled(bool value)
 {
-    //nop
+    if ( value != _drapingEnabled )
+    {
+        _drapingEnabled = value;
+        setCullingActive( !_drapingEnabled );
+    }
 }
 
 void
-DrapeableNode::setRenderOrder(int order)
+DrapeableNode::traverse(osg::NodeVisitor& nv)
+{
+    if ( _drapingEnabled && nv.getVisitorType() == nv.CULL_VISITOR )
+    {
+        // access the cull visitor:
+        osgUtil::CullVisitor* cv = Culling::asCullVisitor(nv);
+
+        // find the cull set for this camera:
+        DrapingCullSet& cullSet = DrapingCullSet::get( cv->getCurrentCamera() );
+        cullSet.push( this, cv->getNodePath(), nv.getFrameStamp() );
+    }
+    else
+    {
+        osg::Group::traverse( nv );
+    }
+}
+
+//...........................................................................
+
+#undef  LC
+#define LC "[DrapeableNode Serializer] "
+
+#include <osgDB/ObjectWrapper>
+#include <osgDB/InputStream>
+#include <osgDB/OutputStream>
+
+namespace
 {
-    _renderOrder = order;
-    osg::StateSet* s = _overlayProxyContainer->getOrCreateStateSet();
-    s->setRenderBinDetails(order, "RenderBin");
+    REGISTER_OBJECT_WRAPPER(
+        DrapeableNode,
+        new osgEarth::DrapeableNode,
+        osgEarth::DrapeableNode,
+        "osg::Object osg::Node osg::Group osgEarth::DrapeableNode")
+    {
+        ADD_BOOL_SERIALIZER(DrapingEnabled, true);
+    }
 }
diff --git a/src/osgEarth/Draping.frag.glsl b/src/osgEarth/Draping.frag.glsl
index 3ef7e0b..45da38b 100644
--- a/src/osgEarth/Draping.frag.glsl
+++ b/src/osgEarth/Draping.frag.glsl
@@ -1,15 +1,15 @@
 #version $GLSL_VERSION_STR
 $GLSL_DEFAULT_PRECISION_FLOAT
 
-#pragma vp_entryPoint "oe_overlay_fragment"
-#pragma vp_location   "fragment_coloring"
-#pragma vp_order      "0.6"
+#pragma vp_entryPoint oe_overlay_fragment
+#pragma vp_location   fragment_coloring
+#pragma vp_order      0.6
 
-uniform bool      oe_isPickCamera;
+uniform bool oe_isPickCamera;
 uniform sampler2D oe_overlay_tex;
-varying vec4      oe_overlay_texcoord;
+in vec4 oe_overlay_texcoord;
 
-void oe_overlay_fragment( inout vec4 color )
+void oe_overlay_fragment(inout vec4 color)
 {
     vec4 texel = texture2DProj(oe_overlay_tex, oe_overlay_texcoord);
     vec4 blendedTexel = vec4( mix( color.rgb, texel.rgb, texel.a ), color.a);
diff --git a/src/osgEarth/Draping.vert.glsl b/src/osgEarth/Draping.vert.glsl
index 3da1f21..ce8c4b1 100644
--- a/src/osgEarth/Draping.vert.glsl
+++ b/src/osgEarth/Draping.vert.glsl
@@ -1,11 +1,13 @@
 #version $GLSL_VERSION_STR
 $GLSL_DEFAULT_PRECISION_FLOAT
 
-#pragma vp_entryPoint "oe_overlay_vertex"
-#pragma vp_location   "vertex_view"
+#pragma vp_entryPoint oe_overlay_vertex
+#pragma vp_location   vertex_view
 
 uniform mat4 oe_overlay_texmatrix;
-varying vec4 oe_overlay_texcoord;
+uniform float oe_overlay_rttLimitZ;
+
+out vec4 oe_overlay_texcoord;
 
 void oe_overlay_vertex(inout vec4 vertexVIEW)
 {
diff --git a/src/osgEarth/DrapingCullSet b/src/osgEarth/DrapingCullSet
new file mode 100644
index 0000000..c9db48a
--- /dev/null
+++ b/src/osgEarth/DrapingCullSet
@@ -0,0 +1,76 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+* Copyright 2016 Pelican Mapping
+* http://osgearth.org
+*
+* osgEarth is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* 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.
+*
+* You should have received a copy of the GNU Lesser General Public License
+* along with this program.  If not, see <http://www.gnu.org/licenses/>
+*/
+#ifndef OSGEARTH_DRAPING_CULL_SET
+#define OSGEARTH_DRAPING_CULL_SET
+
+#include <osgEarth/Common>
+#include <osgEarth/Containers>
+#include <osgEarth/DrapeableNode>
+#include <osg/Camera>
+#include <osg/ObserverNodePath>
+
+namespace osgEarth
+{
+    /**
+     * Culling set for tracking groups whose contents should be "draped",
+     * i.e. rendered to a texture and projected onto the terrain.
+     */
+    class OSGEARTH_EXPORT DrapingCullSet
+    {
+    public:
+        /** Gets the per-thread cull set associated with a camera. */
+        static DrapingCullSet& get(const osg::Camera*);
+
+    public:
+        struct Entry
+        {            
+            osg::ref_ptr<osg::Group>     _node;
+            osg::ref_ptr<osg::RefMatrix> _matrix;
+            osg::ObserverNodePath        _path;
+            int                          _frame;
+        };
+
+    public:
+        DrapingCullSet();
+        ~DrapingCullSet() { } // not virtual
+
+        /** Pushes a node and its matrix into the cull set */
+        void push(DrapeableNode* node, const osg::NodePath& path, const osg::FrameStamp* stamp);
+
+        /** Runs a node visitor on the cull set, optionally popping as it goes along. */
+        void accept(osg::NodeVisitor& nv);
+
+        /** Bounds of this set */
+        const osg::BoundingSphere& getBound() const { return _bs; }
+
+        /** Number of elements in the set */
+        unsigned size() const { return _entries.size(); }
+
+    private:
+        std::vector<Entry>  _entries;
+        osg::BoundingSphere _bs;
+        bool                _frameCulled;
+    };
+
+} // namespace osgEarth
+
+#endif // OSGEARTH_DRAPING_CULL_SET
diff --git a/src/osgEarth/DrapingCullSet.cpp b/src/osgEarth/DrapingCullSet.cpp
new file mode 100644
index 0000000..0d07dae
--- /dev/null
+++ b/src/osgEarth/DrapingCullSet.cpp
@@ -0,0 +1,155 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+* Copyright 2016 Pelican Mapping
+* http://osgearth.org
+*
+* osgEarth is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* 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.
+*
+* You should have received a copy of the GNU Lesser General Public License
+* along with this program.  If not, see <http://www.gnu.org/licenses/>
+*/
+#include <osgEarth/DrapingCullSet>
+#include <osgUtil/CullVisitor>
+
+#define LC "[DrapingCullSet] "
+
+using namespace osgEarth;
+
+
+
+
+DrapingCullSet&
+DrapingCullSet::get(const osg::Camera* cam)
+{    
+    static PerObjectFastMap<const osg::Camera*, DrapingCullSet> sets;
+
+    // Known issue: it is possible for a draping cull set to be "orphaned" - this
+    // would happen if the cull set were populated and then not used. This is a
+    // very unlikely scenario (because the scene graph would have to change mid-cull)
+    // but nevertheless possible.
+    return sets.get(cam);
+}
+
+DrapingCullSet::DrapingCullSet() :
+_frameCulled( true )
+{
+    // nop
+}
+
+void
+DrapingCullSet::push(DrapeableNode* node, const osg::NodePath& path, const osg::FrameStamp* fs)
+{
+    // Reset the set if this is the first push after a cull.
+    if ( _frameCulled )
+    {
+        _frameCulled = false;
+        _entries.clear();
+        _bs.init();
+    }
+
+    _entries.push_back( Entry() );
+    Entry& entry = _entries.back();
+    entry._node = node;
+    entry._path.setNodePath( path );
+    entry._matrix = new osg::RefMatrix( osg::computeLocalToWorld(path) );
+    entry._frame = fs ? fs->getFrameNumber() : 0;
+    _bs.expandBy( node->getBound() );
+}
+
+void
+DrapingCullSet::accept(osg::NodeVisitor& nv)
+{
+    if ( nv.getVisitorType() == nv.CULL_VISITOR )
+    {
+        osgUtil::CullVisitor* cv = static_cast<osgUtil::CullVisitor*>( &nv );
+
+        // We will use the visitor's path to prevent doubely-applying the statesets
+        // of common ancestors
+        const osg::NodePath& nvPath = nv.getNodePath();
+
+        int frame = nv.getFrameStamp() ? nv.getFrameStamp()->getFrameNumber() : 0u;
+
+        for( std::vector<Entry>::iterator entry = _entries.begin(); entry != _entries.end(); ++entry )
+        {
+            if ( frame - entry->_frame > 1 )
+                continue;
+
+            // If there's an active (non-identity matrix), apply it
+            if ( entry->_matrix.valid() )
+            {
+                entry->_matrix->postMult( *cv->getModelViewMatrix() );
+                cv->pushModelViewMatrix( entry->_matrix.get(), osg::Transform::RELATIVE_RF );
+            }
+
+            // After pushing the matrix, we can perform the culling bounds test.
+            if ( !cv->isCulled( entry->_node->getBound() ) )
+            {
+                // Apply the statesets in the entry's node path, but skip over the ones that are
+                // shared with the current visitor's path since they are already in effect.
+                // Count them so we can pop them later.
+                int numStateSets = 0;
+                osg::RefNodePath nodePath;
+                if ( entry->_path.getRefNodePath(nodePath) )
+                {
+                    for(unsigned i=0; i<nodePath.size(); ++i)
+                    {
+                        if (nodePath[i].valid())
+                        {
+                            if (i >= nvPath.size() || nvPath[i] != nodePath[i].get())
+                            {
+                                osg::StateSet* stateSet = nodePath[i]->getStateSet();
+                                if ( stateSet )
+                                {
+                                    cv->pushStateSet( stateSet );
+                                    ++numStateSets;
+                                }
+                            }
+                        }
+                    }
+                }
+
+                // Cull the DrapeableNode's children (but not the DrapeableNode itself!)
+                // TODO: make sure we aren't skipping any cull callbacks, etc. by calling traverse 
+                // instead of accept. (Cannot call accept b/c that calls traverse)
+                for(unsigned i=0; i<entry->_node->getNumChildren(); ++i)
+                {
+                    entry->_node->getChild(i)->accept( nv );
+                }
+            
+                // pop the same number we pushed
+                for(int i=0; i<numStateSets; ++i)
+                {
+                    cv->popStateSet();
+                }
+            }
+
+            // pop the model view:
+            if ( entry->_matrix.valid() )
+            {
+                cv->popModelViewMatrix();
+            }
+        }
+
+        // mark this set so it will reset for the next frame
+        _frameCulled = true;
+    }
+
+    else
+    {
+        for( std::vector<Entry>::iterator entry = _entries.begin(); entry != _entries.end(); ++entry )
+        {
+            
+        }
+    }
+}
diff --git a/src/osgEarth/DrapingTechnique b/src/osgEarth/DrapingTechnique
index d6f7f90..827894e 100644
--- a/src/osgEarth/DrapingTechnique
+++ b/src/osgEarth/DrapingTechnique
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
@@ -24,8 +24,10 @@
 
 #include <osgEarth/Common>
 #include <osgEarth/OverlayDecorator>
+#include <osgEarth/DrapeableNode>
 #include <osg/TexGenNode>
 #include <osg/Uniform>
+#include <vector>
 
 namespace osgEarth
 {
@@ -80,7 +82,7 @@ namespace osgEarth
         bool getOverlayBlending() const { return _rttBlending; }
 
         /**
-         * Whether to attach the RTT to camera to the stencil buffer.  Default = true.
+         * Whether to attach the RTT to camera to the stencil buffer.  Default = false.
          * Some older cards don't have very good support 
          */
         void setAttachStencil( bool value );
@@ -98,9 +100,6 @@ namespace osgEarth
         virtual bool hasData(
             OverlayDecorator::TechRTTParams& params) const;
 
-        void reestablish(
-            TerrainEngineNode* engine );
-
         void preCullTerrain(
             OverlayDecorator::TechRTTParams& params,
             osgUtil::CullVisitor*            cv );
@@ -112,7 +111,9 @@ namespace osgEarth
         void onInstall( TerrainEngineNode* engine );
 
         void onUninstall( TerrainEngineNode* engine );
-
+        
+        const osg::BoundingSphere& getBound(
+            OverlayDecorator::TechRTTParams& params) const;
 
     protected:
         virtual ~DrapingTechnique() { }
diff --git a/src/osgEarth/DrapingTechnique.cpp b/src/osgEarth/DrapingTechnique.cpp
index 4328777..e211e4b 100644
--- a/src/osgEarth/DrapingTechnique.cpp
+++ b/src/osgEarth/DrapingTechnique.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
@@ -20,11 +20,13 @@
 * along with this program.  If not, see <http://www.gnu.org/licenses/>
 */
 #include <osgEarth/DrapingTechnique>
+#include <osgEarth/DrapingCullSet>
 #include <osgEarth/Capabilities>
 #include <osgEarth/Registry>
 #include <osgEarth/ShaderFactory>
 #include <osgEarth/VirtualProgram>
 #include <osgEarth/Shaders>
+#include <osgEarth/CullingUtils>
 
 #include <osg/BlendFunc>
 #include <osg/TexGen>
@@ -40,8 +42,43 @@ using namespace osgEarth;
 
 //---------------------------------------------------------------------------
 
+#undef  LC
+#define LC "[DrapingCamera] "
+
 namespace
 {
+    /**
+     * A camera that will traverse the per-thread DrapingCullSet instead of
+     * its own children.
+     */
+    class DrapingCamera : public osg::Camera
+    {
+    public:
+        DrapingCamera() : osg::Camera(), _camera(0L)
+        {
+            setCullingActive( false );
+        }
+
+    public: // osg::Node
+
+        void accept(osg::NodeVisitor& nv, const osg::Camera* camera)
+        {
+            _camera = camera;
+            osg::Camera::accept( nv );
+        }
+
+        void traverse(osg::NodeVisitor& nv)
+        {            
+            DrapingCullSet& cullSet = DrapingCullSet::get(_camera);
+            cullSet.accept( nv );
+        }
+
+    protected:
+        virtual ~DrapingCamera() { }
+        const osg::Camera* _camera;
+    };
+
+
     // Additional per-view data stored by the draping technique.
     struct LocalPerViewData : public osg::Referenced
     {
@@ -49,6 +86,8 @@ namespace
     };
 }
 
+//---------------------------------------------------------------------------
+
 namespace
 {
     struct Line2d
@@ -96,10 +135,7 @@ namespace
     void optimizeProjectionMatrix(OverlayDecorator::TechRTTParams& params, double maxFarNearRatio)
     {
         LocalPerViewData& local = *static_cast<LocalPerViewData*>(params._techniqueData.get());
-
-        //TODO: add this to the local
-        //local._rttLimitZ->set( 0.0f );
-
+        
         // t0,t1,t2,t3 will form a polygon that tightly fits the
         // main camera's frustum. Texture near the camera will get
         // more resolution then texture far away.
@@ -279,21 +315,14 @@ namespace
 
         // apply the result to the projection matrix.
         params._rttProjMatrix.postMult( M );
-
-        // btw, this new clip matrix distorts the Z coordinate as
-        // y approaches +1. That can cause bleed-through in a geocentric
-        // terrain from the other side of the globe. To prevent that, sample a 
-        // point at the near plane and record that as the Maximum allowable
-        // Z coordinate; a vertex shader in the RTT camera will enforce this.
-        osg::Vec4d sampleFar = osg::Vec4d(0,1,1,1) * M;
-
-        //TODO: add this to the shader.
-        //local._rttLimitZ->set( (float)sampleFar.z() );
     }
 }
 
 //---------------------------------------------------------------------------
 
+#undef  LC
+#define LC "[DrapingTechnique] "
+
 DrapingTechnique::DrapingTechnique() :
 _textureUnit     ( 1 ),
 _textureSize     ( 1024 ),
@@ -314,47 +343,60 @@ _maxFarNearRatio ( 5.0 )
 bool
 DrapingTechnique::hasData(OverlayDecorator::TechRTTParams& params) const
 {
-    return params._group->getNumChildren() > 0;
+    return getBound(params).valid();
 }
 
+#if OSG_MIN_VERSION_REQUIRED(3,4,0)
 
-void
-DrapingTechnique::reestablish(TerrainEngineNode* engine)
+// Customized texture class will disable texture filtering when rendering under a pick camera.
+class DrapingTexture : public osg::Texture2D
 {
-    if ( !_textureUnit.isSet() )
-    {
-        // apply the user-request texture unit, if applicable:
-        if ( _explicitTextureUnit.isSet() )
+public:
+    virtual void apply(osg::State& state) const {
+        osg::State::UniformMap::const_iterator i = state.getUniformMap().find("oe_isPickCamera");
+        bool isPickCamera = false;
+        if (i != state.getUniformMap().end())
         {
-            if ( !_textureUnit.isSet() || *_textureUnit != *_explicitTextureUnit )
+            if (!i->second.uniformVec.empty())
             {
-                _textureUnit = *_explicitTextureUnit;
+                i->second.uniformVec.back().first->get(isPickCamera);
             }
         }
 
-        // otherwise, automatically allocate a texture unit if necessary:
-        else if ( !_textureUnit.isSet() )
+        if (isPickCamera)
         {
-            int texUnit;
-            if ( engine->getResources()->reserveTextureImageUnit(texUnit, "DrapingTechnique") )
-            {
-                _textureUnit = texUnit;
-                OE_INFO << LC << "Reserved texture image unit " << *_textureUnit << std::endl;
-            }
-            else
-            {
-                OE_WARN << LC << "Uh oh, no texture image units available." << std::endl;
-            }
+            FilterMode minFilter = _min_filter;
+            FilterMode magFilter = _mag_filter;
+            DrapingTexture* ncThis = const_cast<DrapingTexture*>(this);
+            ncThis->_min_filter = NEAREST;
+            ncThis->_mag_filter = NEAREST;
+            ncThis->dirtyTextureParameters();
+            osg::Texture2D::apply(state);
+            ncThis->_min_filter = minFilter;
+            ncThis->_mag_filter = magFilter;
+            ncThis->dirtyTextureParameters();
+        }
+        else
+        {
+            osg::Texture2D::apply(state);
         }
     }
-}
+};
 
+#endif
 
 void
 DrapingTechnique::setUpCamera(OverlayDecorator::TechRTTParams& params)
 {
     // create the projected texture:
+
+#if OSG_MIN_VERSION_REQUIRED(3,4,0)
+    osg::Texture2D* projTexture = new DrapingTexture(); 
+#else 
     osg::Texture2D* projTexture = new osg::Texture2D();
+    OE_WARN << LC << "RTT Picking of draped geometry may not work propertly under OSG < 3.4" << std::endl;
+#endif
+
     projTexture->setTextureSize( *_textureSize, *_textureSize );
     projTexture->setInternalFormat( GL_RGBA );
     projTexture->setSourceFormat( GL_RGBA );
@@ -367,7 +409,7 @@ DrapingTechnique::setUpCamera(OverlayDecorator::TechRTTParams& params)
     projTexture->setBorderColor( osg::Vec4(0,0,0,0) );
 
     // set up the RTT camera:
-    params._rttCamera = new osg::Camera();
+    params._rttCamera = new DrapingCamera(); //new osg::Camera();
     params._rttCamera->setClearColor( osg::Vec4f(0,0,0,0) );
     // this ref frame causes the RTT to inherit its viewpoint from above (in order to properly
     // process PagedLOD's etc. -- it doesn't affect the perspective of the RTT camera though)
@@ -400,11 +442,11 @@ DrapingTechnique::setUpCamera(OverlayDecorator::TechRTTParams& params)
         }
 
         params._rttCamera->setClearStencil( 0 );
-        params._rttCamera->setClearMask( GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT ); //GL_DEPTH_BUFFER_BIT |  );
+        params._rttCamera->setClearMask( GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT );
     }
     else
     {
-        params._rttCamera->setClearMask( GL_COLOR_BUFFER_BIT ); //| GL_DEPTH_BUFFER_BIT );
+        params._rttCamera->setClearMask( GL_COLOR_BUFFER_BIT );
     }
 
     // set up a StateSet for the RTT camera.
@@ -458,10 +500,28 @@ DrapingTechnique::setUpCamera(OverlayDecorator::TechRTTParams& params)
     LocalPerViewData* local = new LocalPerViewData();
     params._techniqueData = local;
     
+    if ( _maxFarNearRatio > 1.0 )
+    {
+        // Custom clipper that accounts for the projection matrix warping.
+        // Without this, you will get geometry beyond the original ortho far plane.
+        // (i.e. geometry from beyond the horizon will show through the earth)
+        // When the projection matrix has been warped, verts with Z=1.0 are no longer
+        // always on the far plane (only when y=-1) because of the perspective divide (w).
+        // So we need to test the Z directly (without w) and clip. NOTE: this seems to work
+        // fine, although I think it would be proper to clip at the fragment level with 
+        // alpha. We shall see.
+        const char* warpClip =
+            "#version " GLSL_VERSION_STR "\n"
+            "void oe_overlay_warpClip(inout vec4 vclip) { \n"
+            "    if (vclip.z > 1.0) vclip.z = vclip.w+1.0; \n"
+            "} \n";
+        VirtualProgram* rtt_vp = VirtualProgram::getOrCreate(rttStateSet);
+        rtt_vp->setFunction( "oe_overlay_warpClip", warpClip, ShaderComp::LOCATION_VERTEX_CLIP );
+    }
 
     // Assemble the terrain shaders that will apply projective texturing.
     VirtualProgram* terrain_vp = VirtualProgram::getOrCreate(params._terrainStateSet);
-    terrain_vp->setName( "DrapingTechnique terrain shaders");
+    terrain_vp->setName( "Draping terrain shaders");
 
     // sampler for projected texture:
     params._terrainStateSet->getOrCreateUniform(
@@ -482,12 +542,51 @@ void
 DrapingTechnique::preCullTerrain(OverlayDecorator::TechRTTParams& params,
                                  osgUtil::CullVisitor*             cv )
 {
-    if ( !params._rttCamera.valid() && params._group->getNumChildren() > 0 && _textureUnit.isSet() )
+    // allocate a texture image unit the first time through.
+    if ( !_textureUnit.isSet() )
+    {
+        static Threading::Mutex m;
+        m.lock();
+        if ( !_textureUnit.isSet() )
+        {
+            // apply the user-request texture unit, if applicable:
+            if ( _explicitTextureUnit.isSet() )
+            {
+                if ( !_textureUnit.isSet() || *_textureUnit != *_explicitTextureUnit )
+                {
+                    _textureUnit = *_explicitTextureUnit;
+                }
+            }
+
+            // otherwise, automatically allocate a texture unit if necessary:
+            else if ( !_textureUnit.isSet() )
+            {
+                int texUnit;
+                if ( params._terrainResources->reserveTextureImageUnit(texUnit, "Draping") )
+                {
+                    _textureUnit = texUnit;
+                    OE_INFO << LC << "Reserved texture image unit " << *_textureUnit << std::endl;
+                }
+                else
+                {
+                    OE_WARN << LC << "No texture image units available." << std::endl;
+                }
+            }
+        }
+        m.unlock();
+    }
+
+    if ( !params._rttCamera.valid() && _textureUnit.isSet() )
     {
         setUpCamera( params );
     }
 }
-
+       
+const osg::BoundingSphere&
+DrapingTechnique::getBound(OverlayDecorator::TechRTTParams& params) const
+{
+    return DrapingCullSet::get(params._mainCamera).getBound();
+}
 
 void
 DrapingTechnique::cullOverlayGroup(OverlayDecorator::TechRTTParams& params,
@@ -495,6 +594,8 @@ DrapingTechnique::cullOverlayGroup(OverlayDecorator::TechRTTParams& params,
 {
     if ( params._rttCamera.valid() )
     {
+        LocalPerViewData& local = *static_cast<LocalPerViewData*>(params._techniqueData.get());
+
         // this xforms from clip [-1..1] to texture [0..1] space
         static osg::Matrix s_scaleBiasMat = 
             osg::Matrix::translate(1.0,1.0,1.0) * 
@@ -511,8 +612,6 @@ DrapingTechnique::cullOverlayGroup(OverlayDecorator::TechRTTParams& params,
 
         osg::Matrix VPT = params._rttViewMatrix * params._rttProjMatrix * s_scaleBiasMat;
 
-        LocalPerViewData& local = *static_cast<LocalPerViewData*>(params._techniqueData.get());
-
         if ( local._texGenUniform.valid() )
         {
             // premultiply the inv view matrix so we don't have precision problems in the shader 
@@ -533,7 +632,7 @@ DrapingTechnique::cullOverlayGroup(OverlayDecorator::TechRTTParams& params,
         }
 
         // traverse the overlay group (via the RTT camera).
-        params._rttCamera->accept( *cv );
+        static_cast<DrapingCamera*>(params._rttCamera.get())->accept( *cv, cv->getCurrentCamera() );
     }
 }
 
diff --git a/src/osgEarth/DrawInstanced b/src/osgEarth/DrawInstanced
index 0297904..f0a863d 100644
--- a/src/osgEarth/DrawInstanced
+++ b/src/osgEarth/DrawInstanced
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -77,11 +77,11 @@ namespace osgEarth
 
         /**
          * Creates a virtual shader program that implements DrawInstanced rendering.
-         * You should prepare the scene graph with the ConvertToDrawInstanced
-         * visitor first.
-         * Called by convertGraphToUseDrawInstanced().
+         * You should prepare the scene graph first by calling
+         * convertGraphToUseDrawInstanced().
+         * @return false If instancing is not available
          */
-        extern OSGEARTH_EXPORT void install(osg::StateSet* stateset);
+        extern OSGEARTH_EXPORT bool install(osg::StateSet* stateset);
         extern OSGEARTH_EXPORT void remove (osg::StateSet* stateset);
 
 
@@ -89,8 +89,10 @@ namespace osgEarth
          * Processes a scene graph and converts all the top-level MatrixTransform
          * nodes into shader uniforms that can be used with the VirtualProgram
          * created by createDrawInstacedShaders.
+         * NOTE: You must also call install(StateSet) to activate instancing.
+         * @return false If instancing is not available
          */
-        extern OSGEARTH_EXPORT void convertGraphToUseDrawInstanced( 
+        extern OSGEARTH_EXPORT bool convertGraphToUseDrawInstanced( 
             osg::Group* graph );
 
         /**
diff --git a/src/osgEarth/DrawInstanced.cpp b/src/osgEarth/DrawInstanced.cpp
index d4e70f4..13e1316 100644
--- a/src/osgEarth/DrawInstanced.cpp
+++ b/src/osgEarth/DrawInstanced.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -232,12 +232,14 @@ ConvertToDrawInstanced::apply(osg::LOD& lod)
 }
 
 
-void
+bool
 DrawInstanced::install(osg::StateSet* stateset)
 {
     if ( !stateset )
-        return;
-
+        return false;
+    
+    if ( !Registry::capabilities().supportsDrawInstanced() )
+        return false;
 
     VirtualProgram* vp = VirtualProgram::getOrCreate(stateset);
     
@@ -245,6 +247,8 @@ DrawInstanced::install(osg::StateSet* stateset)
     pkg.load( vp, pkg.InstancingVertex );
 
     stateset->getOrCreateUniform("oe_di_postex_TBO", osg::Uniform::SAMPLER_BUFFER)->set(POSTEX_TBO_UNIT);
+
+    return true;
 }
 
 
@@ -262,13 +266,15 @@ DrawInstanced::remove(osg::StateSet* stateset)
     pkg.unload( vp, pkg.InstancingVertex );
 
     stateset->removeUniform("oe_di_postex_TBO");
-    stateset->removeUniform("oe_di_postex_TBO_size");
 }
 
 
-void
+bool
 DrawInstanced::convertGraphToUseDrawInstanced( osg::Group* parent )
 {
+    if ( !Registry::capabilities().supportsDrawInstanced() )
+        return false;
+
     // place a static bounding sphere on the graph since we intend to alter
     // the structure of the subgraph.
     const osg::BoundingSphere& bs = parent->getBound();
@@ -411,18 +417,24 @@ DrawInstanced::convertGraphToUseDrawInstanced( osg::Group* parent )
         posTBO->setInternalFormat( GL_RGBA32F_ARB );
         posTBO->setUnRefImageDataAfterApply( true );
 
+        // so the TBO will serialize properly.
+        image->setWriteHint(osg::Image::STORE_INLINE);
+
         // Tell the SG to skip the positioning texture.
         ShaderGenerator::setIgnoreHint(posTBO, true);
 
         osg::StateSet* stateset = instanceGroup->getOrCreateStateSet();
         stateset->setTextureAttribute(POSTEX_TBO_UNIT, posTBO);
-        stateset->getOrCreateUniform("oe_di_postex_TBO_size", osg::Uniform::INT)->set((int)tboSize);
 
 		// add the node as a child:
         instanceGroup->addChild( node );
 
         parent->addChild( instanceGroup );
+
+        //OE_INFO << LC << "ConvertToDI: instances=" << numInstancesToStore << "\n";
     }
+
+    return true;
 }
 
 
diff --git a/src/osgEarth/ECEF b/src/osgEarth/ECEF
index 1e6d9dc..6327c1e 100644
--- a/src/osgEarth/ECEF
+++ b/src/osgEarth/ECEF
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarth/ECEF.cpp b/src/osgEarth/ECEF.cpp
index 6f656fe..a2bbfdb 100644
--- a/src/osgEarth/ECEF.cpp
+++ b/src/osgEarth/ECEF.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarth/ElevationField b/src/osgEarth/ElevationField
deleted file mode 100644
index 820987f..0000000
--- a/src/osgEarth/ElevationField
+++ /dev/null
@@ -1,79 +0,0 @@
-/* -*-c++-*- */
-/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
- * http://osgearth.org
- *
- * osgEarth is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>
- */
-#ifndef OSGEARTH_ELEVATION_FIELD_H
-#define OSGEARTH_ELEVATION_FIELD_H 1
-
-#include <osgEarth/Common>
-#include <osgEarth/GeoCommon>
-#include <osg/Object>
-#include <osg/Vec3f>
-
-namespace osgEarth
-{
-    /**
-     * A grid of elevation data.
-     */
-    class OSGEARTH_EXPORT ElevationField : public osg::Object
-    {
-    public:
-        META_Object(osgEarth, ElevationField);
-
-        /** Constructor */
-        ElevationField();
-
-        /**
-         * Sets the width and height (in samples) of the field.
-         * This will wipe out any existing data.
-         */
-        void setSize(unsigned width, unsigned height);
-
-        /**
-         * Gets the height value at sample x,y.
-         */
-        float getHeight(unsigned x, unsigned y) const;
-
-        /**
-         * If the data is "dirty", recalculate derived values like
-         * slope, curvature, min and max.
-         */
-        void update(float spacing);
-
-
-    protected:
-        unsigned                _width, _height;
-        std::vector<float>      _heights;
-        std::vector<float>      _slopes;
-        std::vector<float>      _curvatures;
-        std::vector<float>      _aspects;
-        std::vector<osg::Vec3f> _normals;
-        float                   _min, _max;
-        bool                    _dirty;
-        float                   _spacing;
-
-    protected:
-        virtual ~ElevationField() { }
-
-        // Copy CTOR hidden for now
-        ElevationField(const ElevationField& rhs, const osg::CopyOp& copy) { }
-
-        void computeSlopeAndCurvature();
-    };
-}
-
-#endif // OSGEARTH_ELEVATION_FIELD_H
diff --git a/src/osgEarth/ElevationField.cpp b/src/osgEarth/ElevationField.cpp
deleted file mode 100644
index fda839b..0000000
--- a/src/osgEarth/ElevationField.cpp
+++ /dev/null
@@ -1,139 +0,0 @@
-/* -*-c++-*- */
-/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
- * http://osgearth.org
- *
- * osgEarth is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>
- */
-#include <osgEarth/ElevationField>
-#include <osg/Vec3>
-
-using namespace osgEarth;
-
-ElevationField::ElevationField() :
-_width ( 0 ),
-_height( 0 ),
-_dirty ( false )
-{
-    //nop
-}
-
-void
-ElevationField::setSize(unsigned width, unsigned height)
-{
-    _width  = width;
-    _height = height;
-
-    // The heights vector has a one-sample border all the way around.
-    _heights.resize( (width+2)*(height+2) );
-    _heights.assign( (width+2)*(height+2), 0.0f );
-
-    // Initialize the "border" samples to "NO DATA".
-    for(unsigned s=0; s<(_width+2); ++s)
-    {
-        _heights[s] = NO_DATA_VALUE;
-        _heights[_width*(_height+1) + s] = NO_DATA_VALUE;
-    }
-    for(unsigned t=1; t<(_height+1); ++t)
-    {
-        _heights[_width*t] = NO_DATA_VALUE;
-        _heights[(_width*t)+(_width-1)] = NO_DATA_VALUE;
-    }
-
-    _slopes.resize( width*height );
-    _slopes.assign( width*height, NO_DATA_VALUE );
-
-    _curvatures.resize( width*height );
-    _curvatures.assign( width*height, NO_DATA_VALUE );
-
-    _dirty = true;
-}
-
-float
-ElevationField::getHeight(unsigned x, unsigned y) const
-{
-    return _heights[(_width+2)*y + (x+1)];
-}
-
-void
-ElevationField::update(float spacing)
-{
-    _spacing = spacing;
-    _dirty = false;
-    computeSlopeAndCurvature();
-}
-
-
-void
-ElevationField::computeSlopeAndCurvature()
-{
-    unsigned w = _width+2, h = _height+2;
-    
-    float L = _spacing;
-    osg::Vec3 up(0, 0, 1);
-
-    _slopes.clear();
-    _curvatures.clear();
-
-    for(unsigned t=1; t<_height-1; ++t)
-    {
-        for(unsigned s=1; s<_width-1; ++s)
-        {
-            float centerZ = _heights[t*w + s];
-
-            osg::Vec3
-                west (-L,  0, 0),
-                east ( L,  0, 0),
-                north( 0, -L, 0),
-                south( 0,  L, 0);
-
-            west.z() = _heights[t*w + s-1];
-            east.z() = _heights[t*w + s+1];
-
-            if ( west.z() == NO_DATA_VALUE )
-                west.z() = east.z() + 2.0*(centerZ-east.z());
-
-            if ( east.z() == NO_DATA_VALUE )
-                east.z() = west.z() + 2.0*(centerZ-west.z());
-            
-            south.z() = _heights[(t+1)*w + s];
-            north.z() = _heights[(t-1)*w + s];
-
-            if ( south.z() == NO_DATA_VALUE )
-                south.z() = north.z() + 2.0*(centerZ-north.z());
-
-            if ( north.z() == NO_DATA_VALUE )
-                north.z() = south.z() + 2.0*(centerZ-south.z());
-
-            // Normal vector: cross of two crossing vectors.
-            osg::Vec3 normal = (east-west) ^ (north-south);
-            normal.normalize();
-            _normals.push_back(normal);
-            
-            // Slope [0..1]; 0=flat, 1=vertical. Dot product of the UP vector and the 
-            // normal vector at a point.
-            float slope = up * normal;
-            _slopes.push_back(slope);
-
-            // Curvature: http://goo.gl/mOcl93
-            float L2 = L*L;
-            float D = (0.5*(west.z() + east.z()) - centerZ) / L2;
-            float E = (0.5*(south.z() + north.z()) - centerZ) / L2;
-
-            // Curvature = [0...)?
-            float curvature = -2.0*(D+E); //*100.0;
-            _curvatures.push_back(curvature);
-        }
-    }
-}
diff --git a/src/osgEarth/ElevationLOD b/src/osgEarth/ElevationLOD
index 9747988..c072941 100644
--- a/src/osgEarth/ElevationLOD
+++ b/src/osgEarth/ElevationLOD
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarth/ElevationLOD.cpp b/src/osgEarth/ElevationLOD.cpp
index 91bdc58..c88e4a6 100644
--- a/src/osgEarth/ElevationLOD.cpp
+++ b/src/osgEarth/ElevationLOD.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -137,28 +137,19 @@ void ElevationLOD::traverse( osg::NodeVisitor& nv)
                 double alt;
 
                 // first see if we have a precalculated elevation:
-                osgUtil::CullVisitor*  cv = Culling::asCullVisitor(nv);
-                Culling::CullUserData* ud = Culling::getCullUserData(cv);
-                if ( ud && ud->_cameraAltitude.isSet() )
+                osgUtil::CullVisitor* cv = Culling::asCullVisitor(nv);
+
+                osg::Vec3d eye = cv->getViewPoint();
+
+                if ( _srs && !_srs->isProjected() )
                 {
-                    // yes; use it
-                    alt = ud->_cameraAltitude.get();
+                    GeoPoint mapPoint;
+                    mapPoint.fromWorld( _srs.get(), eye );
+                    alt = mapPoint.z();
                 }
                 else
                 {
-                    // no; need to calculate elevation here:
-                    osg::Vec3d eye = cv->getViewPoint();
-
-                    if ( _srs && !_srs->isProjected() )
-                    {
-                        GeoPoint mapPoint;
-                        mapPoint.fromWorld( _srs.get(), eye );
-                        alt = mapPoint.z();
-                    }
-                    else
-                    {
-                        alt = eye.z();
-                    }
+                    alt = eye.z();
                 }
 
                 // account for the LOD scale
diff --git a/src/osgEarth/ElevationLayer b/src/osgEarth/ElevationLayer
index 2d247ca..487049c 100644
--- a/src/osgEarth/ElevationLayer
+++ b/src/osgEarth/ElevationLayer
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -145,8 +145,6 @@ namespace osgEarth
             const TileKey&     key,
             ProgressCallback*  progress );
         
-        virtual std::string suggestCacheFormat() const;
-
     private:
         ElevationLayerOptions _runtimeOptions;
 
@@ -186,16 +184,6 @@ namespace osgEarth
 
         /** Copy ctor */
         ElevationLayerVector(const ElevationLayerVector& rhs);
-
-        /**
-         * Sets a tile size that createHeightField will always return.
-         * By default, it will return a heightfield whose tile size matches
-         * that of the largest tile size found in the source data layers.
-         */
-        void setExpressTileSize( unsigned tileSize );
-
-    private:
-        optional<unsigned> _expressTileSize;        
     };
 
 } // namespace osgEarth
diff --git a/src/osgEarth/ElevationLayer.cpp b/src/osgEarth/ElevationLayer.cpp
index d11e3a6..ff33a80 100644
--- a/src/osgEarth/ElevationLayer.cpp
+++ b/src/osgEarth/ElevationLayer.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -157,13 +157,7 @@ _runtimeOptions( options )
 void
 ElevationLayer::init()
 {
-    //nop
-}
-
-std::string
-ElevationLayer::suggestCacheFormat() const
-{
-    return "tif";
+    TerrainLayer::init();
 }
 
 void
@@ -376,8 +370,10 @@ GeoHeightField
 ElevationLayer::createHeightField(const TileKey&    key,
                                   ProgressCallback* progress )
 {
-    GeoHeightField result;
-    osg::ref_ptr<osg::HeightField> hf;
+    if (getStatus().isError())
+    {
+        return GeoHeightField::INVALID;
+    }
 
     // If the layer is disabled, bail out.
     if ( getEnabled() == false )
@@ -385,12 +381,20 @@ ElevationLayer::createHeightField(const TileKey&    key,
         return GeoHeightField::INVALID;
     }
 
+    GeoHeightField result;
+    osg::ref_ptr<osg::HeightField> hf;
+
     // Check the memory cache first
     bool fromMemCache = false;
+
+    // cache key combines the key with the full signature (incl vdatum)
+    std::string cacheKey = Stringify() << key.str() << "_" << key.getProfile()->getFullSignature();
+    const CachePolicy& policy = getCacheSettings()->cachePolicy().get();
+
     if ( _memCache.valid() )
     {
-        CacheBin* bin = _memCache->getOrCreateBin( key.getProfile()->getFullSignature() );        
-        ReadResult cacheResult = bin->readObject(key.str() );
+        CacheBin* bin = _memCache->getOrCreateDefaultBin();
+        ReadResult cacheResult = bin->readObject(cacheKey, 0L);
         if ( cacheResult.succeeded() )
         {
             result = GeoHeightField(
@@ -399,7 +403,6 @@ ElevationLayer::createHeightField(const TileKey&    key,
 
             fromMemCache = true;
         }
-        //_memCache->dumpStats(key.getProfile()->getFullSignature());
     }
 
     if ( !result.valid() )
@@ -408,18 +411,16 @@ ElevationLayer::createHeightField(const TileKey&    key,
         CacheBin* cacheBin = getCacheBin( key.getProfile() );
 
         // validate that we have either a valid tile source, or we're cache-only.
-        if ( ! (getTileSource() || (isCacheOnly() && cacheBin) ) )
+        if ( ! (getTileSource() || (policy.isCacheOnly() && cacheBin) ) )
         {
-            OE_WARN << LC << "Error: layer does not have a valid TileSource, cannot create heightfield" << std::endl;
-            _runtimeOptions.enabled() = false;
+            disable("Error: layer does not have a valid TileSource, cannot create heightfield");
             return GeoHeightField::INVALID;
         }
 
         // validate the existance of a valid layer profile.
-        if ( !isCacheOnly() && !getProfile() )
+        if ( !policy.isCacheOnly() && !getProfile() )
         {
-            OE_WARN << LC << "Could not establish a valid profile" << std::endl;
-            _runtimeOptions.enabled() = false;
+            disable("Could not establish a valid profile");
             return GeoHeightField::INVALID;
         }
 
@@ -429,12 +430,12 @@ ElevationLayer::createHeightField(const TileKey&    key,
 
         osg::ref_ptr< osg::HeightField > cachedHF;
 
-        if ( cacheBin && getCachePolicy().isCacheReadable() )
+        if ( cacheBin && policy.isCacheReadable() )
         {
-            ReadResult r = cacheBin->readObject( key.str() );
+            ReadResult r = cacheBin->readObject(cacheKey, 0L);
             if ( r.succeeded() )
             {            
-                bool expired = getCachePolicy().isExpired(r.lastModifiedTime());
+                bool expired = policy.isExpired(r.lastModifiedTime());
                 cachedHF = r.get<osg::HeightField>();
                 if ( cachedHF && validateHeightField(cachedHF) )
                 {
@@ -448,7 +449,7 @@ ElevationLayer::createHeightField(const TileKey&    key,
         }
 
         // if we're cache-only, but didn't get data from the cache, fail silently.
-        if ( !hf.valid() && isCacheOnly() )
+        if ( !hf.valid() && policy.isCacheOnly() )
         {
             return GeoHeightField::INVALID;
         }
@@ -476,9 +477,9 @@ ElevationLayer::createHeightField(const TileKey&    key,
             if ( hf            && 
                  cacheBin      && 
                  !fromCache    &&
-                 getCachePolicy().isCacheWriteable() )
+                 policy.isCacheWriteable() )
             {
-                cacheBin->write( key.str(), hf );
+                cacheBin->write(cacheKey, hf, 0L);
             }
 
             // We have an expired heightfield from the cache and no new data from the TileSource.  So just return the cached data.
@@ -513,8 +514,8 @@ ElevationLayer::createHeightField(const TileKey&    key,
     // write to mem cache if needed:
     if ( result.valid() && !fromMemCache && _memCache.valid() )
     {
-        CacheBin* bin = _memCache->getOrCreateBin( key.getProfile()->getFullSignature() ); 
-        bin->write(key.str(), result.getHeightField());
+        CacheBin* bin = _memCache->getOrCreateDefaultBin();
+        bin->write(cacheKey, result.getHeightField(), 0L);
     }
 
     // post-processing:
@@ -560,18 +561,12 @@ ElevationLayerVector::ElevationLayerVector()
 
 
 ElevationLayerVector::ElevationLayerVector(const ElevationLayerVector& rhs) :
-osg::MixinVector< osg::ref_ptr<ElevationLayer> >( rhs ),
-_expressTileSize( rhs._expressTileSize )
+osg::MixinVector< osg::ref_ptr<ElevationLayer> >( rhs )
 {
     //nop
 }
 
 
-void
-ElevationLayerVector::setExpressTileSize(unsigned tileSize)
-{
-    _expressTileSize = tileSize;
-}
 
 namespace
 {
diff --git a/src/osgEarth/ElevationQuery b/src/osgEarth/ElevationQuery
index d8e4d14..b3ab47f 100644
--- a/src/osgEarth/ElevationQuery
+++ b/src/osgEarth/ElevationQuery
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -37,7 +37,11 @@ namespace osgEarth
 
             void pruneUnusedDatabaseCache();
 
+#if OSG_VERSION_GREATER_OR_EQUAL(3,5,0)
+            virtual osg::ref_ptr<osg::Node> readNodeFile(const std::string& filename);
+#else
             virtual osg::Node* readNodeFile(const std::string& filename);
+#endif
 
         protected:
 
@@ -51,7 +55,7 @@ namespace osgEarth
 
     /**
      * ElevationQuery (EQ) lets you query the elevation at any point on a map.
-     * 
+     *
      * Rather than intersecting with a loaded scene graph, EQ uses the osgEarth
      * engine to directly access the best terrain tile for elevation query. You
      * give it the DEM resolution at which you want an elevation point, and it will
@@ -67,6 +71,8 @@ namespace osgEarth
     class OSGEARTH_EXPORT ElevationQuery
     {
     public:
+        ElevationQuery();
+
         /**
          * Constructs a new elevation manager.
          *
@@ -74,7 +80,7 @@ namespace osgEarth
          *      Map against which to perform elevation queries.
          */
         ElevationQuery( const Map* map );
-        
+
         /**
          * Constructs a new elevation manager.
          *
@@ -86,6 +92,9 @@ namespace osgEarth
         /** dtor */
         virtual ~ElevationQuery() { }
 
+        /** Sets a new map frame */
+        void setMapFrame(const MapFrame& frame);
+
         /**
          * Gets the terrain elevation at a point, given a terrain resolution.
          *
@@ -98,16 +107,16 @@ namespace osgEarth
          *      Pass in 0 (zero) to use the best available resolution.
          * @param out_resolution
          *      Resolution of the resulting elevation value (if the method returns true).
-         * 
+         *
          * @return True if the query succeeded, false upon failure.
          */
         bool getElevation(
             const GeoPoint& point,
             double&         out_elevation,
             double          desiredResolution    =0.0,
-            double*         out_actualResolution =0L );      
+            double*         out_actualResolution =0L );
 
-        /** 
+        /**
          * Gets elevations for a whole array of points, storing the result in the
          * "z" element. If "ignoreZ" is false, the new Z value will be offset by
          * the original Z value.
@@ -144,7 +153,7 @@ namespace osgEarth
          * Gets the maximum cache size for elevation tiles.
          */
         int getMaxTilesToCache() const;
-        
+
         /**
         * Sets the maximum level override for elevation queries.
         * A value of -1 turns off the override.
@@ -182,8 +191,6 @@ namespace osgEarth
 
     private:
         MapFrame     _mapf;
-        unsigned     _maxCacheSize;
-        int          _tileSize;        
         int          _maxLevelOverride;
         bool         _fallBackOnNoData;
 
@@ -201,7 +208,7 @@ namespace osgEarth
         void sync();
         void gatherPatchLayers();
 
-        bool getElevationImpl(            
+        bool getElevationImpl(
             const GeoPoint& point,
             double&         out_elevation,
             double          desiredResolution,
diff --git a/src/osgEarth/ElevationQuery.cpp b/src/osgEarth/ElevationQuery.cpp
index 5fb8222..39d8ea6 100644
--- a/src/osgEarth/ElevationQuery.cpp
+++ b/src/osgEarth/ElevationQuery.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -55,7 +55,11 @@ void ElevationQueryCacheReadCallback::pruneUnusedDatabaseCache()
 {
 }
 
+#if OSG_VERSION_GREATER_OR_EQUAL(3,5,0)
+osg::ref_ptr<osg::Node> ElevationQueryCacheReadCallback::readNodeFile(const std::string& filename)
+#else
 osg::Node* ElevationQueryCacheReadCallback::readNodeFile(const std::string& filename)
+#endif
 {
     // first check to see if file is already loaded.
     {
@@ -71,7 +75,7 @@ osg::Node* ElevationQueryCacheReadCallback::readNodeFile(const std::string& file
     }
 
     // now load the file.
-    osg::ref_ptr<osg::Node> node = osgDB::readNodeFile(filename);
+    osg::ref_ptr<osg::Node> node = osgDB::readRefNodeFile(filename);
 
     // insert into the cache.
     if (node.valid())
@@ -105,7 +109,16 @@ osg::Node* ElevationQueryCacheReadCallback::readNodeFile(const std::string& file
         }
     }
 
+#if OSG_VERSION_GREATER_OR_EQUAL(3,5,0)
+    return node;
+#else
     return node.release();
+#endif
+}
+
+ElevationQuery::ElevationQuery()
+{
+    postCTOR();
 }
 
 ElevationQuery::ElevationQuery(const Map* map) :
@@ -121,6 +134,13 @@ _mapf( mapFrame )
 }
 
 void
+ElevationQuery::setMapFrame(const MapFrame& frame)
+{
+    _mapf = frame;
+    postCTOR();
+}
+
+void
 ElevationQuery::postCTOR()
 {
     // defaults:
@@ -128,6 +148,7 @@ ElevationQuery::postCTOR()
     _queries          = 0.0;
     _totalTime        = 0.0;
     _fallBackOnNoData = false;
+    _cache.clear();
     _cache.setMaxSize( 500 );
 
     // set read callback for IntersectionVisitor
@@ -192,7 +213,7 @@ ElevationQuery::getMaxLevel( double x, double y, const SpatialReference* srs, co
                     srs->transform(tsCoord, tsSRS, tsCoord);
                 else
                     tsSRS = srs;
-                
+
                 for (osgEarth::DataExtentList::iterator j = ts->getDataExtents().begin(); j != ts->getDataExtents().end(); j++)
                 {
                     if (j->maxLevel().isSet() &&
@@ -201,7 +222,7 @@ ElevationQuery::getMaxLevel( double x, double y, const SpatialReference* srs, co
                     {
                         layerMaxLevel = j->maxLevel().value();
                     }
-                }            
+                }
             }
             else
             {
@@ -230,7 +251,13 @@ ElevationQuery::getMaxLevel( double x, double y, const SpatialReference* srs, co
         // Adjust for the tile size resolution differential, if supported by the layer.
         if ( layerMaxLevel.isSet() )
         {
-#if 0
+			// TODO:  This native max resolution of the layer has already been computed here.
+			//        The following block attempts to compute a higher resolution to undo the resolution
+			//        mapping that populateHeightField will eventually do.  So for example, you might compute a maximum level of
+			//        10 here, and this will adjust it to 14 with the knowledge that populateHeightField will adjust the 14 back to 10.
+			//        The use of populateHeightField needs to be replaced by code that just works with the native resolution of the
+			//        layers instead.
+#if 1
             int layerTileSize = layer->getTileSize();
             if (layerTileSize > targetTileSizePOT)
             {
@@ -257,15 +284,15 @@ ElevationQuery::getMaxLevel( double x, double y, const SpatialReference* srs, co
 void
 ElevationQuery::setMaxTilesToCache( int value )
 {
-    _cache.setMaxSize( value );   
+    _cache.setMaxSize( value );
 }
 
 int
 ElevationQuery::getMaxTilesToCache() const
 {
-    return _cache.getMaxSize();    
+    return _cache.getMaxSize();
 }
-        
+
 void
 ElevationQuery::setMaxLevelOverride(int maxLevelOverride)
 {
@@ -382,7 +409,7 @@ ElevationQuery::getElevationImpl(const GeoPoint& point, /* abs */
 
                     osg::Vec3d start( surface + nvector*5e5 );
                     osg::Vec3d end  ( surface - nvector*5e5 );
-                
+
                     // first time through, set up the intersector on demand
                     if ( !_patchLayersLSI.valid() )
                     {
@@ -427,11 +454,11 @@ ElevationQuery::getElevationImpl(const GeoPoint& point, /* abs */
     {
         // this means there are no heightfields.
         out_elevation = 0.0;
-        return true;        
+        return true;
     }
 
-    // tile size (resolution of elevation tiles) 
-    unsigned tileSize = 17; // ???
+    // tile size (resolution of elevation tiles)
+    unsigned tileSize = 33; // ???
 
     // This is the max resolution that we actually have data at this point
     int bestAvailLevel = getMaxLevel( point.x(), point.y(), point.getSRS(), _mapf.getProfile(), tileSize );
@@ -463,7 +490,7 @@ ElevationQuery::getElevationImpl(const GeoPoint& point, /* abs */
             OE_WARN << LC << "Fail: coord transform failed" << std::endl;
             return false;
         }
-    }    
+    }
 
     // get the tilekey corresponding to the tile we need:
     TileKey key = _mapf.getProfile()->createTileKey( mapPoint.x(), mapPoint.y(), bestAvailLevel );
@@ -472,22 +499,22 @@ ElevationQuery::getElevationImpl(const GeoPoint& point, /* abs */
         OE_WARN << LC << "Fail: coords fall outside map" << std::endl;
         return false;
     }
-        
-    bool result = false; 
+
+    bool result = false;
 
     while ( !result && key.valid() )
     {
         GeoHeightField geoHF;
-        
+
         // Try to get the hf from the cache
         TileCache::Record record;
         if ( _cache.get( key, record ) )
-        {                        
+        {
             geoHF = record.value();
         }
         else
         {
-            // Create it            
+            // Create it
             osg::ref_ptr<osg::HeightField> hf = new osg::HeightField();
             hf->allocate( tileSize, tileSize );
 
@@ -495,26 +522,26 @@ ElevationQuery::getElevationImpl(const GeoPoint& point, /* abs */
             hf->getFloatArray()->assign( hf->getFloatArray()->size(), NO_DATA_VALUE );
 
             if (_mapf.populateHeightField(hf, key, false /*heightsAsHAE*/, 0L))
-            {                
+            {
                 geoHF = GeoHeightField( hf.get(), key.getExtent() );
                 _cache.insert( key, geoHF );
             }
         }
 
         if (geoHF.valid())
-        {            
-            float elevation = 0.0f;                 
-            result = geoHF.getElevation( mapPoint.getSRS(), mapPoint.x(), mapPoint.y(), _mapf.getMapInfo().getElevationInterpolation(), mapPoint.getSRS(), elevation);                              
+        {
+            float elevation = 0.0f;
+            result = geoHF.getElevation( mapPoint.getSRS(), mapPoint.x(), mapPoint.y(), _mapf.getMapInfo().getElevationInterpolation(), mapPoint.getSRS(), elevation);
             if (result && elevation != NO_DATA_VALUE)
             {
-                out_elevation = (double)elevation;                
+                out_elevation = (double)elevation;
 
                 // report the actual resolution of the heightfield.
                 if ( out_actualResolution )
                     *out_actualResolution = geoHF.getXInterval();
             }
             else
-            {                               
+            {
                 result = false;
             }
         }
@@ -528,7 +555,7 @@ ElevationQuery::getElevationImpl(const GeoPoint& point, /* abs */
             key = key.createParentKey();
         }
     }
-         
+
 
     osg::Timer_t end = osg::Timer::instance()->tick();
     _queries++;
diff --git a/src/osgEarth/Export b/src/osgEarth/Export
index 4c75699..c793f99 100644
--- a/src/osgEarth/Export
+++ b/src/osgEarth/Export
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarth/Extension b/src/osgEarth/Extension
index 4d831e2..f4acc13 100644
--- a/src/osgEarth/Extension
+++ b/src/osgEarth/Extension
@@ -21,24 +21,27 @@
 #define OSGEARTH_EXTENSION_H 1
 
 #include <osgEarth/Common>
+#include <osgEarth/Config>
 #include <osg/Object>
 #include <osgDB/Options>
+#include <osgDB/ReaderWriter>
+#include <osgDB/FileNameUtils>
+#include <osgDB/Registry>
 
-namespace osgEarth
-{
-    class ConfigOptions;
-}
 
 namespace osgEarth
 {
     /**
      * An Extension is an object that can be loaded on demand (from a plugin) 
-     * and can have multiple object-specific interfaces.
+     * and can have multiple object-specific interfaces. Its main function is
+     * to enable activation and configuration of a plugin feature from an
+     * osgEarth .earth file.
      *
      * For example, the pattern for declaring an Extension that connects to a
      * MapNode looks like:
      *
-     *   public MyExtension : public Extension, public ExtensionInterface<MapNode>
+     *   public MyExtension : public Extension,
+     *                        public ExtensionInterface<MapNode>
      *
      * You can implement more than one interface. This one would connect to a
      * MapNode and to a UI Control:
@@ -46,6 +49,14 @@ namespace osgEarth
      *   public MyExtension : public Extension,
      *                        public ExtensionInterface<MapNode>,
      *                        public ExtensionInterface<Control>
+     *
+     * You can register an Extension so that one can activate and configure it
+     * from a .earth file. Use the registration macro:
+     *
+     *   REGISTER_OSGEARTH_EXTENSION( osgearth_extension, ExtentionClassName );
+     *
+     * Where the string "extension" in osgearth_extension is the key string 
+     * that will appear in the earth file under the <map> element.
      */
     class OSGEARTH_EXPORT Extension : public osg::Object // header-only
     {
@@ -53,11 +64,23 @@ namespace osgEarth
         /**
          * Sets DB options that this extension should use when doing IO operations.
          */
-        virtual void setDBOptions(const osgDB::Options* options) { }
+        virtual void setDBOptions(const osgDB::Options* readOptions) { }
 
+        /**
+         * Gets the configuration options that can be used to re-configure
+         * this Extension. Necessary for serialization.
+         */
+        virtual const ConfigOptions& getConfigOptions() const;
+
+        /**
+         * Convenience function for casting the extension to another one of its
+         * interfaces.
+         */
+        template<typename T> T* as() { return dynamic_cast<T*>(this); }
+        template<typename T> const T* as() const { return dynamic_cast<T*>(this); }
 
     protected:
-        Extension() { }
+        Extension();
 
     protected:
         virtual ~Extension() { }
@@ -72,6 +95,9 @@ namespace osgEarth
          * Fetch configuration options from a plugin loader
          */
         static const ConfigOptions& getConfigOptions(const osgDB::Options*);
+
+    private:
+        ConfigOptions _defaultOptions;
     };
 
     
@@ -101,6 +127,69 @@ namespace osgEarth
         }
     };
 
+    // convenience define for extensions
+#define META_osgEarth_Extension(CLASS) \
+    META_Object(osgEarth,CLASS); \
+    CLASS () { } \
+    CLASS (const CLASS & rhs, const osg::CopyOp& op) { } \
+    virtual ~ CLASS() { }
+
+    
+    template<class T>
+    class RegisterExtensionLoader
+    {
+        public:
+            RegisterExtensionLoader(const std::string& name)
+            {
+                if (osgDB::Registry::instance())
+                {
+                    _rw = new T(name);
+                    osgDB::Registry::instance()->addReaderWriter(_rw.get());
+                }
+            }
+
+            ~RegisterExtensionLoader()
+            {
+                if (osgDB::Registry::instance())
+                {
+                    osgDB::Registry::instance()->removeReaderWriter(_rw.get());
+                }
+            }
+
+            T* get() { return _rw.get(); }
+
+        protected:
+            osg::ref_ptr<T> _rw;
+    };
+
+    /**
+     * This template declares and registers an extension-loading plugin.
+     */
+    template<typename T>
+    class ExtensionLoader : public osgDB::ReaderWriter
+    {
+    public: // Plugin stuff
+        ExtensionLoader(const std::string& name) {
+            supportsExtension( name, name );
+        }
+
+        virtual ~ExtensionLoader() { }
+
+        ReadResult readObject(const std::string& filename, const osgDB::Options* dbOptions) const
+        {
+          if ( !acceptsExtension(osgDB::getLowerCaseFileExtension(filename)) )
+                return ReadResult::FILE_NOT_HANDLED;
+
+          return ReadResult( new T(Extension::getConfigOptions(dbOptions)) );
+        }
+    };
+
 } // namespace osgEarth
 
+
+#define REGISTER_OSGEARTH_EXTENSION(NAME,CLASS) \
+    extern "C" void osgdb_##NAME(void) {} \
+    static osgEarth::RegisterExtensionLoader< osgEarth::ExtensionLoader<CLASS> > g_proxy_##CLASS_##NAME( #NAME );
+
+
 #endif
diff --git a/src/osgEarth/Extension.cpp b/src/osgEarth/Extension.cpp
index 861fedc..34c69c6 100644
--- a/src/osgEarth/Extension.cpp
+++ b/src/osgEarth/Extension.cpp
@@ -28,12 +28,23 @@ using namespace osgEarth;
 #define EXTENSION_OPTIONS_TAG "__osgEarth::ExtensionOptions"
 
 
+Extension::Extension()
+{
+    //nop
+}
+
+const ConfigOptions&
+Extension::getConfigOptions() const
+{
+    return _defaultOptions;
+}
+
 Extension*
 Extension::create(const std::string& name, const ConfigOptions& options)
 {
     if ( name.empty() )
     {
-        OE_WARN << LC << "ILLEGAL- no driver set for tile source" << std::endl;
+        OE_WARN << LC << "ILLEGAL- Extension::create requires a plugin name" << std::endl;
         return 0L;
     }
 
@@ -58,6 +69,13 @@ Extension::create(const std::string& name, const ConfigOptions& options)
         return 0L;
     }
 
+    // for automatic serialization, in the event that the subclass does not
+    // implement getConfigOptions.
+    extension->_defaultOptions = options;
+
+    if (extension->getName().empty())
+        extension->setName(name);
+
     rr.takeObject();
     return extension;
 }
@@ -66,6 +84,7 @@ Extension::create(const std::string& name, const ConfigOptions& options)
 const ConfigOptions&
 Extension::getConfigOptions(const osgDB::Options* options)
 {
-    return *static_cast<const ConfigOptions*>(
-        options->getPluginData( EXTENSION_OPTIONS_TAG ) );
+    static ConfigOptions s_default;
+    const void* data = options->getPluginData(EXTENSION_OPTIONS_TAG);
+    return data ? *static_cast<const ConfigOptions*>(data) : s_default;
 }
diff --git a/src/osgEarth/FadeEffect b/src/osgEarth/FadeEffect
index 77cffee..ec558f9 100644
--- a/src/osgEarth/FadeEffect
+++ b/src/osgEarth/FadeEffect
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarth/FadeEffect.cpp b/src/osgEarth/FadeEffect.cpp
index 66a1665..a32d0fb 100644
--- a/src/osgEarth/FadeEffect.cpp
+++ b/src/osgEarth/FadeEffect.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarth/FileUtils b/src/osgEarth/FileUtils
index 0087852..5fedd29 100644
--- a/src/osgEarth/FileUtils
+++ b/src/osgEarth/FileUtils
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -27,6 +27,11 @@
 namespace osgEarth
 {
     /**
+     * Converts a filename to an absolute path.
+     */
+    extern OSGEARTH_EXPORT std::string getAbsolutePath(const std::string& input);
+
+    /**
      * Determines whether a given filename is a relative path
      */
     extern OSGEARTH_EXPORT bool isRelativePath(const std::string& fileName);
diff --git a/src/osgEarth/FileUtils.cpp b/src/osgEarth/FileUtils.cpp
index 85e592b..f556c83 100644
--- a/src/osgEarth/FileUtils.cpp
+++ b/src/osgEarth/FileUtils.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -128,6 +128,13 @@
 
 using namespace osgEarth;
 
+
+std::string
+osgEarth::getAbsolutePath(const std::string& path)
+{
+    return osgDB::convertFileNameToUnixStyle( osgDB::getRealPath(path) );
+}
+
 bool osgEarth::isRelativePath(const std::string& fileName)
 {
     //If it is a URL, it is not relative
@@ -145,7 +152,7 @@ bool osgEarth::isRelativePath(const std::string& fileName)
     return true;
 #else
     //Absolute paths in Unix will start with a '/'
-    return !(fileName.size() >= 1 && fileName[0] == '/');
+    return !(native.size() >= 1 && native[0] == '/');
 #endif
 }
 
@@ -270,14 +277,14 @@ std::string osgEarth::getTempName(const std::string& prefix, const std::string&
 {
     //tmpname is kind of busted on Windows, it always returns a file of the form \blah which gets put in your root directory but
     //oftentimes can't get opened by some drivers b/c it doesn't have a drive letter in front of it.
-    bool valid = false;
-    while (!valid)
+    while (true)
     {
         std::stringstream ss;
         ss << prefix << "~" << rand() << suffix;
-        if (!osgDB::fileExists(ss.str())) return ss.str();
+        if (!osgDB::fileExists(ss.str()))
+            return ss.str();
     }
-    return "";
+//    return "";
 }
 
 bool osgEarth::makeDirectory( const std::string &path )
diff --git a/src/osgEarth/GLSLChunker b/src/osgEarth/GLSLChunker
new file mode 100644
index 0000000..f9dfe40
--- /dev/null
+++ b/src/osgEarth/GLSLChunker
@@ -0,0 +1,63 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+ * Copyright 2016 Pelican Mapping
+ * http://osgearth.org
+ *
+ * osgEarth is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ */
+#ifndef OSGEARTH_GLSL_CHUNKER_H
+#define OSGEARTH_GLSL_CHUNKER_H 1
+
+#include <osgEarth/Common>
+#include <vector>
+
+namespace osgEarth
+{
+    /**
+     * Utility that reads GLSL source code and lexes it into chunks that
+     * you can then perform operations on.
+     */
+    class OSGEARTH_EXPORT GLSLChunker
+    {
+    public:
+        struct Chunk {
+            enum Type { TYPE_STATEMENT, TYPE_DIRECTIVE, TYPE_FUNCTION, TYPE_COMMENT };
+            Type type;
+            std::string text;
+            std::vector<std::string> tokens;
+        };
+
+        typedef std::vector<Chunk> Chunks;
+
+
+
+    public:
+        /** Read GLSL into chunks */
+        void read(const std::string& input, Chunks& output) const;
+
+        /** Write chunks (read using the read() method) back to GLSL */
+        void write(const Chunks& input, std::string& output) const;
+
+        /** Search and replace a string */
+        void replace(Chunks& input, const std::string& target, const std::string& replacement) const;
+
+        /** Dump chunks to notify (for debugging) */
+        void dump(const std::string&, const Chunks&) const;
+
+        /** Create a chunk from a line. */
+        Chunk chunkLine(const std::string& line) const;
+    };
+}
+
+#endif // OSGEARTH_GLSL_CHUNKER_H
diff --git a/src/osgEarth/GLSLChunker.cpp b/src/osgEarth/GLSLChunker.cpp
new file mode 100644
index 0000000..b778f41
--- /dev/null
+++ b/src/osgEarth/GLSLChunker.cpp
@@ -0,0 +1,228 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+ * Copyright 2016 Pelican Mapping
+ * http://osgearth.org
+ *
+ * osgEarth is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ */
+#include <osgEarth/GLSLChunker>
+#include <osgEarth/StringUtils>
+#include <sstream>
+
+using namespace osgEarth;
+
+
+void
+GLSLChunker::dump(const std::string& msg, const Chunks& chunks) const
+{
+    OE_INFO << msg << "\n";
+    for (Chunks::const_iterator i = chunks.begin(); i != chunks.end(); ++i)
+    {
+        std::string type = 
+            i->type == Chunk::TYPE_DIRECTIVE ? "DIRECTIVE" :
+            i->type == Chunk::TYPE_COMMENT ? "COMMENT" :
+            i->type == Chunk::TYPE_STATEMENT ? "STATEMENT" :
+            i->type == Chunk::TYPE_FUNCTION ? "FUNCTION" :
+            "????????";
+
+        OE_INFO << "   " << type << ": " << i->text << std::endl;
+    }
+}
+
+#define ADVANCE \
+    in >> std::noskipws >> c0; \
+    c1 = in.peek()
+
+#define SAVE \
+    output.push_back(Chunk()); \
+    output.back().text = chunk.str(); \
+    std::string tok = token.str(); \
+    if ( !tok.empty() ) tokens.push_back(tok); \
+    output.back().tokens = tokens; \
+    output.back().type = type; \
+    chunk.str(std::string()); chunk.clear(); \
+    token.str(std::string()); token.clear(); \
+    tokens.clear(); \
+    inChunk = false; \
+    isBlockComment = false
+
+#define TOKENIZE \
+    if (::isspace(c0)) { \
+        std::string tok = token.str(); \
+        if (!tok.empty()) tokens.push_back(tok); \
+        token.str(std::string()); token.clear(); \
+    } \
+    else token << c0
+
+
+void
+GLSLChunker::read(const std::string& input, Chunks& output) const
+{
+    char c0(0), c1(0);
+    int braceLevel = 0;
+    int parenLevel = 0;
+    bool isBlockComment = false;
+
+    // pad the input with a final newline so we always get the final line.
+    std::string paddedInput(input);
+    paddedInput.append("\n");
+
+    std::istringstream in(paddedInput);
+    std::ostringstream chunk;
+    std::ostringstream token;
+    std::vector<std::string> tokens;
+
+    bool inChunk = false;
+    Chunk::Type type;
+
+    while (in)
+    {
+        ADVANCE;
+
+        // are we inside a chunk?
+        if (inChunk)
+        {
+            if (type == Chunk::TYPE_DIRECTIVE && c0 == '\n')
+            {
+                SAVE;
+            }
+
+            else if (type == Chunk::TYPE_STATEMENT && c0 == ';' && braceLevel == 0)
+            {
+                chunk << c0;
+                TOKENIZE;
+                SAVE;
+            }
+
+            else if (type == Chunk::TYPE_FUNCTION && c0 == '}' && braceLevel == 1)
+            {
+                --braceLevel;
+                chunk << c0;
+                TOKENIZE;
+                SAVE;
+            }
+
+            else if (type == Chunk::TYPE_COMMENT && c0 == '\n' && !isBlockComment)
+            {
+                SAVE;
+            }
+
+            else if (type == Chunk::TYPE_COMMENT && c0 == '*' && c1 == '/' && isBlockComment)
+            {
+                chunk << c0;
+                TOKENIZE;
+                ADVANCE;
+                chunk << c0;
+                TOKENIZE;
+                SAVE;
+            }
+
+            else {
+                chunk << c0;
+            }
+
+            if (inChunk)
+            {
+                TOKENIZE;
+
+                if (c0 == '(') {
+                    ++parenLevel;
+                }
+
+                else if (c0 == ')') {
+                    --parenLevel;
+                }
+
+                else if (c0 == '{') {
+                    ++braceLevel;
+                    // if we were in a statement, the precense of an open-brace converts it to a FUNCTION
+                    // unless we can detect that it's a struct.
+                    if (type == Chunk::TYPE_STATEMENT) {
+                        if (tokens.empty() || tokens[0] != "struct") {
+                            type = Chunk::TYPE_FUNCTION;
+                        }
+                    }
+                }
+
+                else if (c0 == '}') {
+                    --braceLevel;
+                }
+            }
+        }
+
+        else // !inChunk
+        {
+            // not in a chunk; try to start a new one.
+
+            if (c0 == '/' && c1 == '/') {
+                type = Chunk::TYPE_COMMENT;
+                isBlockComment = false;
+                inChunk = true;
+                chunk << c0;
+                TOKENIZE;
+            }
+            else if (c0 == '/' && c1 == '*') {
+                type = Chunk::TYPE_COMMENT;
+                isBlockComment = true;
+                inChunk = true;
+                chunk << c0;
+                TOKENIZE;
+            }
+            else if (c0 == '#') {
+                type = Chunk::TYPE_DIRECTIVE;
+                inChunk = true;
+                chunk << c0;
+                TOKENIZE;
+            }
+            else if (!::isspace(c0)) {
+                type = Chunk::TYPE_STATEMENT;
+                inChunk = true;
+                chunk << c0;
+                TOKENIZE;
+            }
+        }
+    }
+}
+
+
+void
+GLSLChunker::write(const Chunks& input, std::string& output) const
+{
+    std::stringstream buf;
+    for(int i=0; i<input.size(); ++i)
+    {
+        buf << input[i].text << "\n";
+    }
+    output = buf.str();
+}
+
+GLSLChunker::Chunk
+GLSLChunker::chunkLine(const std::string& line) const
+{
+    Chunks chunks;
+    read(line, chunks);
+    return chunks.size() > 0 ? chunks[0] : Chunk();
+}
+
+void
+GLSLChunker::replace(Chunks& input, const std::string& pattern, const std::string& replacement) const
+{
+    for(int i=0; i<input.size(); ++i)
+    {
+        Chunk& chunk = input[i];
+        osgEarth::replaceIn(chunk.text, pattern, replacement);
+        for (unsigned t = 0; t<chunk.tokens.size(); ++t)
+            osgEarth::replaceIn(chunk.tokens[t], pattern, replacement);
+    }
+}
diff --git a/src/osgEarth/GPUClamping.frag.glsl b/src/osgEarth/GPUClamping.frag.glsl
index 00ca4e3..201178a 100644
--- a/src/osgEarth/GPUClamping.frag.glsl
+++ b/src/osgEarth/GPUClamping.frag.glsl
@@ -1,8 +1,9 @@
-#version 110
-#pragma vp_entryPoint "oe_clamp_fragment"
-#pragma vp_location   "fragment_coloring"
+#version $GLSL_VERSION_STR
 
-varying float oe_clamp_alpha;
+#pragma vp_entryPoint oe_clamp_fragment
+#pragma vp_location   fragment_coloring
+
+in float oe_clamp_alpha;
 
 void oe_clamp_fragment(inout vec4 color)
 {
diff --git a/src/osgEarth/GPUClamping.vert.glsl b/src/osgEarth/GPUClamping.vert.glsl
index 81376d6..c744e88 100644
--- a/src/osgEarth/GPUClamping.vert.glsl
+++ b/src/osgEarth/GPUClamping.vert.glsl
@@ -1,19 +1,20 @@
-#version 120
+#version $GLSL_VERSION_STR
 
-#pragma vp_entryPoint "oe_clamp_vertex"
-#pragma vp_location   "vertex_view"
-#pragma vp_order      "0.5"
+#pragma vp_entryPoint oe_clamp_vertex
+#pragma vp_location   vertex_view
+#pragma vp_order      0.5
 
-#pragma include "GPUClamping.vert.lib.glsl"
+#pragma include GPUClamping.vert.lib.glsl
 
-attribute vec4 oe_clamp_attrs;
-attribute float oe_clamp_offset;
-uniform bool oe_clamp_hasAttrs;
+in vec4 oe_clamp_attrs;     // vertex attribute
+in float oe_clamp_height;   // vertex attribute
+
+out float oe_clamp_alpha;
 
-uniform bool  oe_isGeocentric;
+uniform bool oe_clamp_hasAttrs;
+uniform bool oe_isGeocentric;
 uniform float oe_clamp_altitudeOffset;
 uniform float oe_clamp_horizonDistance2;
-varying float oe_clamp_alpha;
 
 void oe_clamp_vertex(inout vec4 vertexView)
 {
@@ -43,7 +44,7 @@ void oe_clamp_vertex(inout vec4 vertexView)
         float depth;
         oe_getClampedViewVertex(pointToClamp, clampedPoint, depth);
 
-        float dh = 0.0;
+        float dh = verticalOffset + oe_clamp_altitudeOffset;
 
         if ( relativeToAnchor )
         {
@@ -51,24 +52,21 @@ void oe_clamp_vertex(inout vec4 vertexView)
             // distance from the anchor point to the terrain. Since distance() is unsigned,
             // we use the vector dot product to calculate whether to adjust up or down.
             float dist = distance(pointToClamp, clampedPoint);
-            float dir = dot(clampedPoint-pointToClamp, vertexView-pointToClamp) < 0.0 ? -1.0 : 1.0;
+            float dir  = sign(dot(clampedPoint-pointToClamp, vertexView-pointToClamp));
             dh += (dist * dir);
         }
         else
         {
             // if we are clamping to the terrain, the vertex becomes the
-            // clamped point.
-            vertexView.xyz = clampedPoint.xyz/clampedPoint.w;
-        }
-
-        // apply the z-offset if there is one.
-        float hOffset = dh + oe_clamp_altitudeOffset + verticalOffset;
-        if ( hOffset != 0.0 )
-        {
-            vec3 up;
-            oe_getClampingUpVector(up);
-            vertexView.xyz += up * hOffset;
+            // clamped point
+            vertexView.xyz = clampedPoint.xyz;
+            dh += oe_clamp_height;
         }
+        
+        // calculate the up vector along which clamping will occur (in either direction)
+        vec3 up;
+        oe_getClampingUpVector( up );
+        vertexView.xyz += up*dh;
 
         // if the clamped depth value is near the far plane, suppress drawing
         // to avoid rendering anomalies.
diff --git a/src/osgEarth/GPUClamping.vert.lib.glsl b/src/osgEarth/GPUClamping.vert.lib.glsl
index 17b3a48..3c24583 100644
--- a/src/osgEarth/GPUClamping.vert.lib.glsl
+++ b/src/osgEarth/GPUClamping.vert.lib.glsl
@@ -12,9 +12,7 @@ uniform mat4 oe_clamp_depthClip2cameraView;
 // Given a vertex in view space, clamp it to the "ground" as represented
 // by an orthographic depth texture. Return the clamped vertex in view space,
 // along with the associated depth value.
-void oe_getClampedViewVertex(in  vec4  vertView,
-                             out vec4  out_clampedVertView,
-                             out float out_depth)
+void oe_getClampedViewVertex(in vec4 vertView, out vec4 out_clampedVertView, out float out_depth)
 {
     // transform the vertex into the depth texture's clip coordinates.
     vec4 vertDepthClip = oe_clamp_cameraView2depthClip * vertView;
diff --git a/src/osgEarth/GeoCommon b/src/osgEarth/GeoCommon
index 391157e..2505b6e 100644
--- a/src/osgEarth/GeoCommon
+++ b/src/osgEarth/GeoCommon
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarth/GeoData b/src/osgEarth/GeoData
index 4ba6465..9f4ee95 100644
--- a/src/osgEarth/GeoData
+++ b/src/osgEarth/GeoData
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -527,9 +527,11 @@ namespace osgEarth
         virtual ~DataExtent() { }
 
         /** The minimum LOD of the extent */
+        optional<unsigned>& minLevel() { return _minLevel; }
         const optional<unsigned>& minLevel() const { return _minLevel; }
 
         /** The maximum LOD of the extent */
+        optional<unsigned>& maxLevel() { return _maxLevel; }
         const optional<unsigned>& maxLevel() const { return _maxLevel; }
 
     private:
@@ -712,7 +714,7 @@ namespace osgEarth
          * Subsamples the heightfield, returning a new heightfield corresponding to
          * the destEx extent. The destEx must be a smaller, inset area of sourceEx.
          */
-        GeoHeightField createSubSample( const GeoExtent& destEx, ElevationInterpolation interpolation) const;
+        GeoHeightField createSubSample( const GeoExtent& destEx, unsigned int width, unsigned int height, ElevationInterpolation interpolation) const;
 
         /**
          * Gets the geospatial extent of the heightfield.
diff --git a/src/osgEarth/GeoData.cpp b/src/osgEarth/GeoData.cpp
index ad75735..ca9faf6 100644
--- a/src/osgEarth/GeoData.cpp
+++ b/src/osgEarth/GeoData.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -509,7 +509,7 @@ GeoPoint::distanceTo(const GeoPoint& rhs) const
         }
         else
         {
-            GeoPoint rhsT = transform(rhs.getSRS());
+            GeoPoint rhsT = rhs.transform(getSRS());
             return (vec3d() - rhsT.vec3d()).length();
         }
     }
@@ -833,43 +833,41 @@ GeoExtent::contains(double x, double y, const SpatialReference* srs) const
     if ( isInvalid() )
         return false;
 
-    double local_x = x, local_y = y;
-
     osg::Vec3d xy( x, y, 0 );
     osg::Vec3d localxy = xy;
 
     if (srs &&
         !srs->isEquivalentTo( _srs.get() ) &&
         !srs->transform(xy, _srs.get(), localxy) )
-    {
+    {    
         return false;
     }
     else
     {
         // normalize a geographic longitude to -180:+180
         if ( _srs->isGeographic() )
-            local_x = normalizeLongitude( local_x );            
+            localxy.x() = normalizeLongitude( localxy.x() );            
 
         //Account for small rounding errors along the edges of the extent
-        if (osg::equivalent(_west, local_x)) local_x = _west;
-        if (osg::equivalent(_east, local_x)) local_x = _east;
-        if (osg::equivalent(_south, local_y)) local_y = _south;
-        if (osg::equivalent(_north, local_y)) local_y = _north;
+        if (osg::equivalent(_west, localxy.x())) localxy.x() = _west;
+        if (osg::equivalent(_east, localxy.x())) localxy.x() = _east;
+        if (osg::equivalent(_south, localxy.y())) localxy.y() = _south;
+        if (osg::equivalent(_north, localxy.y())) localxy.y() = _north;
 
         if ( crossesAntimeridian() )
         {
-            if ( local_x > 0.0 )
+            if ( localxy.x() > 0.0 )
             {
-                return local_x >= _west && local_x <= 180.0 && local_y >= _south && local_y <= _north;
+                return localxy.x() >= _west && localxy.x() <= 180.0 && localxy.y() >= _south && localxy.y() <= _north;
             }
             else
             {
-                return local_x >= -180.0 && local_x <= _east && local_y >= _south && local_y <= _north;
+                return localxy.x() >= -180.0 && localxy.x() <= _east && localxy.y() >= _south && localxy.y() <= _north;
             }
         }
         else
         {
-            return local_x >= _west && local_x <= _east && local_y >= _south && local_y <= _north;
+            return localxy.x() >= _west && localxy.x() <= _east && localxy.y() >= _south && localxy.y() <= _north;
         }
     }
 }
@@ -1911,7 +1909,7 @@ GeoImage::reproject(const SpatialReference* to_srs, const GeoExtent* to_extent,
     }
     else
     {
-         destExtent = getExtent().transform(to_srs);    
+        destExtent = getExtent().transform(to_srs);    
     }
 
     osg::Image* resultImage = 0L;
@@ -1926,7 +1924,7 @@ GeoImage::reproject(const SpatialReference* to_srs, const GeoExtent* to_extent,
     {
         // if either of the SRS is a custom projection, we have to do a manual reprojection since
         // GDAL will not recognize the SRS.
-        resultImage = manualReproject(getImage(), getExtent(), *to_extent, useBilinearInterpolation && isNormalized, width, height);
+        resultImage = manualReproject(getImage(), getExtent(), destExtent, useBilinearInterpolation && isNormalized, width, height);
     }
     else
     {
@@ -2008,14 +2006,16 @@ _maxHeight  ( 0.0f )
 GeoHeightField::GeoHeightField(osg::HeightField* heightField,
                                const GeoExtent&  extent) :
 _heightField( heightField ),
-_extent     ( extent )
+_extent     ( extent ),
+_minHeight( FLT_MAX ),
+_maxHeight( -FLT_MAX )
 {
     if ( _heightField.valid() && extent.isInvalid() )
     {
         OE_WARN << LC << "Created with a valid heightfield AND INVALID extent" << std::endl;
     }
 
-    else if ( _heightField )
+    else if ( _heightField.valid() )
     {
         double minx, miny, maxx, maxy;
         _extent.getBounds(minx, miny, maxx, maxy);
@@ -2025,7 +2025,6 @@ _extent     ( extent )
         _heightField->setYInterval( (maxy - miny)/(double)(_heightField->getNumRows()-1) );
         _heightField->setBorderWidth( 0 );
 
-        _minHeight = FLT_MAX, _maxHeight = -FLT_MAX;
         const osg::HeightField::HeightList& heights = _heightField->getHeightList();
         for( unsigned i=0; i<heights.size(); ++i )
         {
@@ -2075,7 +2074,9 @@ GeoHeightField::getElevation(const SpatialReference* inputSRS,
             interp);
 
         // if the vertical datums don't match, do a conversion:
-        if ( out_elevation != NO_DATA_VALUE && !extentSRS->isVertEquivalentTo(outputSRS) )
+        if (out_elevation != NO_DATA_VALUE && 
+            outputSRS && 
+            !extentSRS->isVertEquivalentTo(outputSRS) )
         {
             // if the caller provided a custom output SRS, perform the appropriate
             // Z transformation. This requires a lat/long point:
@@ -2088,7 +2089,7 @@ GeoHeightField::getElevation(const SpatialReference* inputSRS,
 
             VerticalDatum::transform(
                 extentSRS->getVerticalDatum(),
-                outputSRS ? outputSRS->getVerticalDatum() : 0L,
+                outputSRS->getVerticalDatum(),
                 geolocal.y(), geolocal.x(), out_elevation);
         }
 
@@ -2102,38 +2103,32 @@ GeoHeightField::getElevation(const SpatialReference* inputSRS,
 }
 
 GeoHeightField
-GeoHeightField::createSubSample( const GeoExtent& destEx, ElevationInterpolation interpolation) const
+GeoHeightField::createSubSample( const GeoExtent& destEx, unsigned int width, unsigned int height, ElevationInterpolation interpolation) const
 {
     double div = destEx.width()/_extent.width();
     if ( div >= 1.0f )
         return GeoHeightField::INVALID;
 
-    int w = _heightField->getNumColumns();
-    int h = _heightField->getNumRows();
-    double xInterval = _extent.width() / (double)(_heightField->getNumColumns()-1);
-    double yInterval = _extent.height() / (double)(_heightField->getNumRows()-1);
-    double dx = xInterval * div;
-    double dy = yInterval * div;
+    double dx = destEx.width()/(double)(width-1);
+    double dy = destEx.height()/(double)(height-1);    
 
     osg::HeightField* dest = new osg::HeightField();
-    dest->allocate( w, h );
+    dest->allocate( width, height );
     dest->setXInterval( dx );
     dest->setYInterval( dy );
 
-    // copy over the skirt height, adjusting it for tile size.
-    dest->setSkirtHeight( _heightField->getSkirtHeight() * div );
-
     double x, y;
     int col, row;
 
     double x0 = (destEx.xMin()-_extent.xMin())/_extent.width();
     double y0 = (destEx.yMin()-_extent.yMin())/_extent.height();
-    double xstep = div/double(w-1);
-    double ystep = div/double(h-1);
 
-    for( x = x0, col = 0; col < w; x += xstep, col++ )
+    double xstep = div / (double)(width-1);
+    double ystep = div / (double)(height-1);
+    
+    for( x = x0, col = 0; col < width; x += xstep, col++ )
     {
-        for( y = y0, row = 0; row < h; y += ystep, row++ )
+        for( y = y0, row = 0; row < height; y += ystep, row++ )
         {
             float height = HeightFieldUtils::getHeightAtNormalizedLocation(
                 _heightField.get(), x, y, interpolation );
@@ -2141,9 +2136,6 @@ GeoHeightField::createSubSample( const GeoExtent& destEx, ElevationInterpolation
         }
     }
 
-    osg::Vec3d orig( destEx.xMin(), destEx.yMin(), _heightField->getOrigin().z() );
-    dest->setOrigin( orig );
-
     return GeoHeightField( dest, destEx ); // Q: is the VDATUM accounted for?
 }
 
diff --git a/src/osgEarth/GeoMath b/src/osgEarth/GeoMath
index 740a76e..2772e15 100644
--- a/src/osgEarth/GeoMath
+++ b/src/osgEarth/GeoMath
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarth/GeoMath.cpp b/src/osgEarth/GeoMath.cpp
index bbeb51f..693d54c 100644
--- a/src/osgEarth/GeoMath.cpp
+++ b/src/osgEarth/GeoMath.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarth/GeoTransform b/src/osgEarth/GeoTransform
index 0859d02..25b0639 100644
--- a/src/osgEarth/GeoTransform
+++ b/src/osgEarth/GeoTransform
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -61,6 +61,7 @@ namespace osgEarth
          * positions.
          */
         void setTerrain(Terrain* terrain);
+        osg::ref_ptr<Terrain> getTerrain() const { osg::ref_ptr<Terrain> t; _terrain.lock(t); return t; }
 
         /**
          * Enabling this will cause the object to automatically 
@@ -71,6 +72,32 @@ namespace osgEarth
          */
         void setAutoRecomputeHeights(bool value);
 
+    public:
+        /** Callback that lets the user intercept the compute*Matrix functions during a traversal. */
+        class OSGEARTH_EXPORT ComputeMatrixCallback : public osg::Referenced
+        {
+        public:
+            virtual bool computeLocalToWorldMatrix(const GeoTransform* xform, osg::Matrix& m, osg::NodeVisitor* nv) const;
+            virtual bool computeWorldToLocalMatrix(const GeoTransform* xform, osg::Matrix& m, osg::NodeVisitor* nv) const;
+        };
+
+        /** Installs a compute matrix callback */
+        void setComputeMatrixCallback(ComputeMatrixCallback* cb);
+
+
+    public: // osg::Transform
+
+        virtual bool computeLocalToWorldMatrix(osg::Matrix& m, osg::NodeVisitor* nv) const {
+            return _computeMatrixCallback.valid()
+                ? _computeMatrixCallback->computeLocalToWorldMatrix(this, m, nv)
+                : osg::MatrixTransform::computeLocalToWorldMatrix(m, nv);
+        }
+
+        virtual bool computeWorldToLocalMatrix(osg::Matrix& m, osg::NodeVisitor* nv) const {
+            return _computeMatrixCallback.valid()
+                ? _computeMatrixCallback->computeWorldToLocalMatrix(this, m, nv)
+                : osg::MatrixTransform::computeWorldToLocalMatrix(m, nv);
+        }
 
     public: // TerrainCallback interface
 
@@ -87,6 +114,8 @@ namespace osgEarth
         bool                       _autoRecompute;
         bool                       _autoRecomputeReady;
 
+        osg::ref_ptr<ComputeMatrixCallback> _computeMatrixCallback;
+
         void configureAutoRecompute(Terrain* terrain);
     };
 
diff --git a/src/osgEarth/GeoTransform.cpp b/src/osgEarth/GeoTransform.cpp
index 1ddd2f6..afb4437 100644
--- a/src/osgEarth/GeoTransform.cpp
+++ b/src/osgEarth/GeoTransform.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -19,6 +19,10 @@
 #include <osgEarth/GeoTransform>
 #include <osgEarth/Terrain>
 
+#define LC "[GeoTransform] "
+
+#define OE_TEST OE_DEBUG
+
 using namespace osgEarth;
 
 GeoTransform::GeoTransform() :
@@ -42,6 +46,11 @@ void
 GeoTransform::setTerrain(Terrain* terrain)
 {
     _terrain = terrain;
+
+    // Change in the terrain means we need to recompute the position
+    // if one is set.
+    if ( _position.isValid() )
+        setPosition( _position );
 }
 
 void
@@ -65,13 +74,18 @@ GeoTransform::setPosition(const GeoPoint& position)
     if ( !position.isValid() )
         return false;
 
+    _position = position;
+
     // relative Z or reprojection require a terrain:
     osg::ref_ptr<Terrain> terrain;
     _terrain.lock(terrain);
 
     // relative Z requires a terrain:
     if (position.altitudeMode() == ALTMODE_RELATIVE && !terrain.valid())
+    {
+        OE_TEST << LC << "setPosition failed condition 1\n";
         return false;
+    }
 
     GeoPoint p;
 
@@ -83,20 +97,23 @@ GeoTransform::setPosition(const GeoPoint& position)
 
     // bail if the transformation failed:
     if ( !p.isValid() )
+    {
+        OE_TEST << LC << "setPosition failed condition 2\n";
         return false;
+    }
 
     // convert to absolute height:
     if ( !p.makeAbsolute(_terrain.get()) )
+    {
+        OE_TEST << LC << "setPosition failed condition 3\n";
         return false;
+    }
 
     // assemble the matrix:
     osg::Matrixd local2world;
     p.createLocalToWorld( local2world );
     this->setMatrix( local2world );
 
-    // save the last know position
-    _position = position;
-
     // install auto-recompute?
     if (_autoRecompute &&
         _position.altitudeMode() == ALTMODE_RELATIVE &&
@@ -119,10 +136,42 @@ GeoTransform::onTileAdded(const TileKey&          key,
                           TerrainCallbackContext& context)
 {
    if (!_position.isValid() || _position.altitudeMode() != ALTMODE_RELATIVE)
+   {
+       OE_TEST << LC << "onTileAdded fail condition 1\n";
        return;
+   }
 
    if (!key.getExtent().contains(_position))
+   {
+       OE_DEBUG << LC << "onTileAdded fail condition 2\n";
        return;
+   }
 
    setPosition(_position);
 }
+
+void
+GeoTransform::setComputeMatrixCallback(GeoTransform::ComputeMatrixCallback* cb)
+{
+    _computeMatrixCallback = cb;
+}
+
+bool
+GeoTransform::ComputeMatrixCallback::computeLocalToWorldMatrix(const GeoTransform* xform, osg::Matrix& m, osg::NodeVisitor* nv) const
+{
+    if (xform->getReferenceFrame() == xform->RELATIVE_RF)
+        m.preMult(xform->getMatrix());
+    else
+        m = xform->getMatrix();
+    return true;
+}
+
+bool
+GeoTransform::ComputeMatrixCallback::computeWorldToLocalMatrix(const GeoTransform* xform, osg::Matrix& m, osg::NodeVisitor* nv) const
+{
+    if (xform->getReferenceFrame() == xform->RELATIVE_RF)
+        m.postMult(xform->getInverseMatrix());
+    else
+        m = xform->getInverseMatrix();
+    return true;
+}
diff --git a/src/osgEarth/Geoid b/src/osgEarth/Geoid
index e7013d0..f44b49a 100644
--- a/src/osgEarth/Geoid
+++ b/src/osgEarth/Geoid
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarth/Geoid.cpp b/src/osgEarth/Geoid.cpp
index 149cccd..aa4a82b 100644
--- a/src/osgEarth/Geoid.cpp
+++ b/src/osgEarth/Geoid.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarth/GeometryClamper b/src/osgEarth/GeometryClamper
new file mode 100644
index 0000000..c033fd5
--- /dev/null
+++ b/src/osgEarth/GeometryClamper
@@ -0,0 +1,99 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+ * Copyright 2016 Pelican Mapping
+ * http://osgearth.org
+ *
+ * osgEarth is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+#ifndef OSGEARTH_GEOMETRY_CLAMPER
+#define OSGEARTH_GEOMETRY_CLAMPER 1
+
+#include <osgEarth/Common>
+#include <osgEarth/SpatialReference>
+#include <osgEarth/Terrain>
+#include <osgEarth/DPLineSegmentIntersector>
+#include <osg/NodeVisitor>
+#include <osg/fast_back_stack>
+
+namespace osgEarth
+{
+    /**
+     * Utility that takes existing OSG geometry and modifies it so that
+     * it "conforms" with a terrain patch.
+     */
+    class OSGEARTH_EXPORT GeometryClamper : public osg::NodeVisitor
+    {
+    public:
+        GeometryClamper();
+
+        virtual ~GeometryClamper() { }
+
+        void setTerrainPatch(osg::Node* node) { _terrainPatch = node; }
+        osg::Node* getTerrainPatch() const { return _terrainPatch.get(); }
+
+        void setTerrainSRS(const SpatialReference* srs) { _terrainSRS = srs; }
+        const SpatialReference* getTerrainSRS() const   { return _terrainSRS.get(); }
+
+        void setPreserveZ(bool value) { _preserveZ = value; }
+        bool getPreserveZ() const     { return _preserveZ; }
+
+        void setScale(float scale) { _scale = scale; }
+        float getScale() const     { return _scale; }
+
+        void setOffset(float offset) { _offset = offset; }
+        float getOffset() const      { return _offset; }
+
+    public: // osg::NodeVisitor
+
+        void apply( osg::Geode& );
+        void apply( osg::Transform& );
+
+    protected:
+
+        osg::ref_ptr<osg::Node>              _terrainPatch;
+        osg::ref_ptr<const SpatialReference> _terrainSRS;
+        bool                                 _preserveZ;
+        float                                _scale;
+        float                                _offset;
+        osg::fast_back_stack<osg::Matrixd>   _matrixStack;
+        osg::ref_ptr<DPLineSegmentIntersector> _lsi;
+    };
+
+
+    class GeometryClamperCallback : public osgEarth::TerrainCallback
+    {
+    public:
+        GeometryClamperCallback();
+
+        virtual ~GeometryClamperCallback() { }
+
+        /** Access to configure the underlying clamper */
+        GeometryClamper& getClamper()             { return _clamper; }
+        const GeometryClamper& getClamper() const { return _clamper; }
+
+    public: // TerrainCallback
+        
+        virtual void onTileAdded(
+            const TileKey&          key, 
+            osg::Node*              tile, 
+            TerrainCallbackContext& context);
+
+    protected:
+        GeometryClamper _clamper;
+    };
+
+} // namespace osgEarth
+
+#endif // OSGEARTH_GEOMETRY_CLAMPER
diff --git a/src/osgEarth/GeometryClamper.cpp b/src/osgEarth/GeometryClamper.cpp
new file mode 100644
index 0000000..686a434
--- /dev/null
+++ b/src/osgEarth/GeometryClamper.cpp
@@ -0,0 +1,198 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+ * Copyright 2016 Pelican Mapping
+ * http://osgearth.org
+ *
+ * osgEarth is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ */
+#include <osgEarth/GeometryClamper>
+
+#include <osgUtil/IntersectionVisitor>
+
+#include <osg/Geode>
+#include <osg/Geometry>
+#include <osg/UserDataContainer>
+
+#define LC "[GeometryClamper] "
+
+using namespace osgEarth;
+
+#define ZOFFSETS_NAME "GeometryClamper::zOffsets"
+
+//-----------------------------------------------------------------------
+
+GeometryClamper::GeometryClamper() :
+osg::NodeVisitor( osg::NodeVisitor::TRAVERSE_ALL_CHILDREN ),
+_preserveZ      ( false ),
+_scale          ( 1.0f ),
+_offset         ( 0.0f )
+{
+    this->setNodeMaskOverride( ~0 );
+    _lsi = new osgEarth::DPLineSegmentIntersector(osg::Vec3d(0,0,0), osg::Vec3d(0,0,0));
+}
+
+void
+GeometryClamper::apply(osg::Transform& xform)
+{
+    osg::Matrixd matrix;
+    if ( !_matrixStack.empty() ) matrix = _matrixStack.back();
+    xform.computeLocalToWorldMatrix( matrix, this );
+    _matrixStack.push_back( matrix );
+    traverse(xform);
+    _matrixStack.pop_back();
+}
+
+void
+GeometryClamper::apply(osg::Geode& geode)
+{
+    if ( !_terrainSRS.valid() )
+        return;
+
+    const osg::Matrixd& local2world = _matrixStack.back();
+    osg::Matrix world2local;
+    world2local.invert( local2world );
+
+    const osg::EllipsoidModel* em = _terrainSRS->getEllipsoid();
+    osg::Vec3d n_vector(0,0,1), start, end, msl;
+
+    bool isGeocentric = _terrainSRS->isGeographic();
+
+    osgUtil::IntersectionVisitor iv( _lsi.get() );
+
+    double r = std::min( em->getRadiusEquator(), em->getRadiusPolar() );
+
+    unsigned count = 0;
+
+    for( unsigned i=0; i<geode.getNumDrawables(); ++i )
+    {
+        bool geomDirty = false;
+        osg::Geometry* geom = geode.getDrawable(i)->asGeometry();
+        if ( geom )
+        {
+            osg::Vec3Array*  verts = static_cast<osg::Vec3Array*>(geom->getVertexArray());
+            osg::FloatArray* zOffsets = 0L;
+
+            // if preserve-Z is on, check for our elevations array. Create it if is doesn't
+            // already exist.
+            bool buildZOffsets = false;
+            if ( _preserveZ )
+            {
+                osg::UserDataContainer* udc = geom->getOrCreateUserDataContainer();
+                unsigned n = udc->getUserObjectIndex( ZOFFSETS_NAME );
+                if ( n < udc->getNumUserObjects() )
+                {
+                    zOffsets = dynamic_cast<osg::FloatArray*>(udc->getUserObject(n));
+                }
+
+                else
+                {
+                    zOffsets = new osg::FloatArray();
+                    zOffsets->setName( ZOFFSETS_NAME );
+                    zOffsets->reserve( verts->size() );
+                    udc->addUserObject( zOffsets );
+                    buildZOffsets = true;
+                }
+            }
+
+            for( unsigned k=0; k<verts->size(); ++k )
+            {
+                osg::Vec3d vw = (*verts)[k];
+                vw = vw * local2world;
+
+                if ( isGeocentric )
+                {
+                    // normal to the ellipsoid:
+                    n_vector = em->computeLocalUpVector(vw.x(),vw.y(),vw.z());
+
+                    // if we need to build to z-offsets array, calculate the z offset now:
+                    if ( buildZOffsets || _scale != 1.0 )
+                    {
+                        double lat,lon,hae;
+                        em->convertXYZToLatLongHeight(vw.x(), vw.y(), vw.z(), lat, lon, hae);
+
+                        if ( buildZOffsets )
+                        {
+                            zOffsets->push_back( (*verts)[k].z() );
+                        }
+
+                        if ( _scale != 1.0 )
+                        {
+                            msl = vw - n_vector*hae;
+                        }
+                    }
+                }
+
+                else if ( buildZOffsets ) // flat map
+                {
+                    zOffsets->push_back( float(vw.z()) );
+                }
+
+                _lsi->reset();
+                _lsi->setStart( vw + n_vector*r*_scale );
+                _lsi->setEnd( vw - n_vector*r );
+                _lsi->setIntersectionLimit( _lsi->LIMIT_NEAREST );
+
+                _terrainPatch->accept( iv );
+
+                if ( _lsi->containsIntersections() )
+                {
+                    osg::Vec3d fw = _lsi->getFirstIntersection().getWorldIntersectPoint();
+                    if ( _scale != 1.0 )
+                    {
+                        osg::Vec3d delta = fw - msl;
+                        fw += delta*_scale;
+                    }
+                    if ( _offset != 0.0 )
+                    {
+                        fw += n_vector*_offset;
+                    }
+                    if ( _preserveZ && (zOffsets != 0L) )
+                    {
+                        fw += n_vector * (*zOffsets)[k];
+                    }
+
+                    (*verts)[k] = (fw * world2local);
+                    geomDirty = true;
+                    ++count;
+                }
+            }
+
+            if ( geomDirty )
+            {
+                geom->dirtyBound();
+                if ( geom->getUseVertexBufferObjects() )
+                {
+                    verts->getVertexBufferObject()->setUsage( GL_DYNAMIC_DRAW_ARB );
+                    verts->dirty();
+                }
+                else
+                {
+                    geom->dirtyDisplayList();
+                }
+            }
+        }
+
+        OE_DEBUG << LC << "clamped " << count << " verts." << std::endl;
+    }
+}
+
+
+
+void
+GeometryClamperCallback::onTileAdded(const TileKey&          key, 
+                                     osg::Node*              tile, 
+                                     TerrainCallbackContext& context)
+{
+    tile->accept( _clamper );
+}
diff --git a/src/osgEarth/HTTPClient b/src/osgEarth/HTTPClient
index f476119..bd64272 100644
--- a/src/osgEarth/HTTPClient
+++ b/src/osgEarth/HTTPClient
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -189,6 +189,7 @@ namespace osgEarth
         std::string _mimeType;
         bool        _cancelled;
         double      _duration_s;
+        TimeStamp   _lastModified;
 
         Config getHeadersAsConfig() const;
 
diff --git a/src/osgEarth/HTTPClient.cpp b/src/osgEarth/HTTPClient.cpp
index 8f9fc0d..eeececa 100644
--- a/src/osgEarth/HTTPClient.cpp
+++ b/src/osgEarth/HTTPClient.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -34,6 +34,12 @@
 #include <algorithm>
 #include <curl/curl.h>
 
+// Whether to use WinInet instead of cURL - CMAKE option
+#ifdef OSGEARTH_USE_WININET_FOR_HTTP
+#include <WinInet.h>
+#pragma comment(lib, "wininet.lib")
+#endif
+
 #define LC "[HTTPClient] "
 
 //#define OE_TEST OE_NOTICE
@@ -263,9 +269,11 @@ HTTPRequest::getURL() const
 
 /****************************************************************************/
 
-HTTPResponse::HTTPResponse( long _code )
-: _response_code( _code ),
-  _cancelled(false)
+HTTPResponse::HTTPResponse( long _code ) :
+_response_code( _code ),
+_cancelled(false),
+_duration_s(0.0),
+_lastModified(0u)
 {
     _parts.reserve(1);
 }
@@ -274,7 +282,9 @@ HTTPResponse::HTTPResponse( const HTTPResponse& rhs ) :
 _response_code( rhs._response_code ),
 _parts( rhs._parts ),
 _mimeType( rhs._mimeType ),
-_cancelled( rhs._cancelled )
+_cancelled( rhs._cancelled ),
+_duration_s(0.0),
+_lastModified(0u)
 {
     //nop
 }
@@ -316,8 +326,8 @@ HTTPResponse::getPartStream( unsigned int n ) const {
 
 std::string
 HTTPResponse::getPartAsString( unsigned int n ) const {
-     std::string streamStr;
-     streamStr = _parts[n]->_stream.str();
+    std::string streamStr;
+    streamStr = _parts[n]->_stream.str();    
     return streamStr;
 }
 
@@ -381,7 +391,8 @@ HTTPClient::getClient()
 HTTPClient::HTTPClient() :
 _initialized    ( false ),
 _curl_handle    ( 0L ),
-_simResponseCode( -1L )
+_simResponseCode( -1L ),
+_previousHttpAuthentication(0L)
 {
     //nop
     //do no CURL calls here.
@@ -418,6 +429,13 @@ HTTPClient::initializeImpl()
         OE_WARN << LC << "Simulating a network error with Response Code = " << _simResponseCode << std::endl;
     }
 
+    // Check to HTTP disabling (for testing)
+    const char* disable = getenv("OSGEARTH_HTTP_DISABLE");
+    if (disable)
+    {
+        _simResponseCode = 503L; // SERVICE UNAVAILABLE
+    }
+
     // Dumps out HTTP request/response info
     if ( ::getenv("OSGEARTH_HTTP_DEBUG") )
     {
@@ -436,6 +454,10 @@ HTTPClient::initializeImpl()
     curl_easy_setopt( _curl_handle, CURLOPT_NOPROGRESS, (void*)0 ); //0=enable.
     curl_easy_setopt( _curl_handle, CURLOPT_FILETIME, true );
 
+    // Enable automatic CURL decompression of known types. An empty string will automatically add all supported encoding types that are built into curl.
+    // Note that you must have curl built against zlib to support gzip or deflate encoding.
+    curl_easy_setopt( _curl_handle, CURLOPT_ENCODING, "");
+
     osg::ref_ptr< CurlConfigHandler > curlConfigHandler = getCurlConfigHandler();
     if (curlConfigHandler.valid()) {
         curlConfigHandler->onInitialize(_curl_handle);
@@ -695,6 +717,246 @@ HTTPClient::download(const std::string& uri,
     return getClient().doDownload( uri, localPath );
 }
 
+
+#ifdef OSGEARTH_USE_WININET_FOR_HTTP
+
+namespace
+{
+    std::string GetLastErrorAsString()
+    {
+        //Get the error message, if any.
+        DWORD errorMessageID = ::GetLastError();
+        if(errorMessageID == 0)
+            return std::string("Error Code 0"); //No error message has been recorded
+
+        LPSTR messageBuffer = nullptr;
+        size_t size = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
+                                     NULL, errorMessageID, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)&messageBuffer, 0, NULL);
+
+        std::string message(messageBuffer, size);
+
+        //Free the buffer.
+        LocalFree(messageBuffer);
+
+        message = Stringify() << "[Code " << errorMessageID << "] " << message;
+
+        return message;
+    }
+}
+
+HTTPResponse
+HTTPClient::doGet(const HTTPRequest&    request,
+                  const osgDB::Options* options, 
+                  ProgressCallback*     progress) const
+{
+    OE_START_TIMER(http_get);
+
+    std::string url = request.getURL();
+    // Rewrite the url if the url rewriter is available  
+    osg::ref_ptr< URLRewriter > rewriter = getURLRewriter();
+    if ( rewriter.valid() )
+    {
+        std::string oldURL = url;
+        url = rewriter->rewrite( oldURL );
+        OE_DEBUG << LC << "Rewrote URL " << oldURL << " to " << url << std::endl;
+    }
+
+    HINTERNET hInternet = InternetOpen(
+        getUserAgent().c_str(),
+        //"Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; AS; rv:11.0) like Gecko",
+        INTERNET_OPEN_TYPE_PRECONFIG, 
+        NULL,       // proxy
+        NULL,       // proxy bypass
+        0);         // flags
+
+    if( !hInternet )
+    {
+        OE_WARN << LC << "InternetOpen failed: " << GetLastErrorAsString() << std::endl;
+        return HTTPResponse(0);
+    }
+
+    // clears any session cookies..?
+    InternetSetOption( 0, INTERNET_OPTION_END_BROWSER_SESSION, NULL, 0 );
+    
+    // parse the URL:
+    URL_COMPONENTS urlcomp;
+    ZeroMemory(&urlcomp, sizeof(urlcomp));
+	urlcomp.dwStructSize = sizeof(urlcomp);
+	urlcomp.dwHostNameLength = 1;
+    urlcomp.dwUserNameLength = 1;
+    urlcomp.dwPasswordLength = 1;
+    urlcomp.dwUrlPathLength  = 1;
+
+    if ( !InternetCrackUrl(url.c_str(), 0, 0L, &urlcomp) )
+    {
+        OE_WARN << LC << "InternetCrackUrl failed for " << url << ": " << GetLastErrorAsString() << std::endl;
+        InternetCloseHandle( hInternet );
+        return HTTPResponse(0);
+    }
+    
+    WORD port =
+        urlcomp.nPort != 0 ? urlcomp.nPort :
+        urlcomp.nScheme == INTERNET_SCHEME_HTTPS ? INTERNET_DEFAULT_HTTPS_PORT :
+        INTERNET_DEFAULT_HTTP_PORT;
+
+    std::string hostName( urlcomp.lpszHostName );
+    int slash = hostName.find_first_of('/');
+    if ( slash != std::string::npos )
+        hostName = hostName.substr(0, slash);
+
+    OE_DEBUG
+        << "\n"
+        << "Host name = " << hostName << "\n"
+        << "Url path = " << urlcomp.lpszUrlPath << "\n"
+        << "Port = " << port << "\n";
+    
+    DWORD openFlags =
+        //INTERNET_FLAG_PRAGMA_NOCACHE |
+        INTERNET_FLAG_RELOAD |
+        INTERNET_FLAG_NO_CACHE_WRITE |
+        INTERNET_FLAG_KEEP_CONNECTION;
+
+    if ( urlcomp.nScheme == INTERNET_SCHEME_HTTPS)
+    {
+        openFlags |= INTERNET_FLAG_SECURE;
+    }
+
+    // InternetOpenUrl is a lot less code, but we have to use the InternetConnnect +
+    // HttpOpenRequest + HttpSendRequest approach in order to support system dialogs
+    // for PKI certificates and username/password queries.
+    
+    HINTERNET hConnection = InternetConnect(
+        hInternet,
+        hostName.c_str(),
+        port,
+        "", // username
+        "", // password
+        INTERNET_SERVICE_HTTP,
+        0,  // flags
+        INTERNET_NO_CALLBACK); // context
+
+    if ( !hConnection )
+    {
+        OE_WARN << LC << "InternetConnect failed for " << url << ": " << GetLastErrorAsString() << std::endl;
+        InternetCloseHandle( hInternet );
+        return HTTPResponse(0);
+    }
+
+    HINTERNET hRequest = HttpOpenRequest(
+        hConnection,            // handle from InternetConnect
+        "GET",                  // verb
+        urlcomp.lpszUrlPath,    // path
+        NULL,                   // HTTP version (NULL = default)
+        NULL,                   // Referrer
+        NULL,                   // Accept types
+        openFlags,              // flags
+        INTERNET_NO_CALLBACK);                  // context (user data)
+
+    if ( !hRequest )
+    {
+        OE_WARN << LC << "HttpOpenRequest failed for " << url << ": " << GetLastErrorAsString() << std::endl;
+        InternetCloseHandle( hConnection );
+        InternetCloseHandle( hInternet );
+        return HTTPResponse(0);
+    }
+
+    while( !HttpSendRequest(hRequest, NULL, 0, NULL, 0) )
+    {
+        DWORD errorNum = GetLastError();
+            
+        // Request for client cert; open system dialog.
+        if ( errorNum == ERROR_INTERNET_CLIENT_AUTH_CERT_NEEDED )
+        {
+            OE_WARN << LC << "Server reports ERROR_INTERNET_CLIENT_AUTH_CERT_NEEDED!\n";
+
+            // Return ERROR_SUCCESS regardless of clicking on OK or Cancel
+            DWORD dialogResult = InternetErrorDlg(
+                GetDesktopWindow(), 
+                hRequest,
+                ERROR_INTERNET_CLIENT_AUTH_CERT_NEEDED,
+                FLAGS_ERROR_UI_FILTER_FOR_ERRORS | FLAGS_ERROR_UI_FLAGS_GENERATE_DATA | FLAGS_ERROR_UI_FLAGS_CHANGE_OPTIONS, 
+                NULL );
+
+            if ( dialogResult != ERROR_SUCCESS )
+            {
+                OE_WARN << LC << "InternetErrorDlg failed to produce client cert " << url << ": " << GetLastErrorAsString() << std::endl;
+                InternetCloseHandle( hRequest );
+                InternetCloseHandle( hConnection );
+                InternetCloseHandle( hInternet );
+                return HTTPResponse(0);
+            }
+        }
+
+        else
+        {
+            OE_WARN << LC << "HttpSendRequest failed to open " << url << ": " << GetLastErrorAsString() << std::endl;
+            InternetCloseHandle( hRequest );
+            InternetCloseHandle( hConnection );
+            InternetCloseHandle( hInternet );
+            return HTTPResponse(0);
+        }
+    }
+
+    int statusCode = 0;
+    std::string contentType;
+
+    char  buffer[4096];
+    DWORD bufferLen = 4096;
+    DWORD index = 0;
+
+    if ( HttpQueryInfo(hRequest, HTTP_QUERY_STATUS_CODE, buffer, &bufferLen, &index) )
+    {             
+        statusCode = as<int>( std::string(buffer, bufferLen), 0 );
+    }
+    
+    HTTPResponse response(statusCode);
+
+    bufferLen = 4096, index = 0;
+    if ( HttpQueryInfo(hRequest, HTTP_QUERY_CONTENT_TYPE, buffer, &bufferLen, &index) )
+    {
+        response._mimeType = std::string(buffer, bufferLen);
+    }
+
+    bufferLen = 4096, index = 0;
+    if ( HttpQueryInfo(hRequest, HTTP_QUERY_LAST_MODIFIED, buffer, &bufferLen, &index) )
+    {
+        response._lastModified = as<long>(std::string(buffer, bufferLen), 0L);
+    }
+
+    response._mimeType = contentType;
+
+    if ( statusCode == 200 )
+    {    
+        osg::ref_ptr<HTTPResponse::Part> part = new HTTPResponse::Part();
+
+        DWORD numBytesRead = 0;
+        while( InternetReadFile(hRequest, buffer, 4096, &numBytesRead) && numBytesRead )
+        {
+            part->_stream << std::string(buffer, numBytesRead);
+        }
+
+        response._parts.push_back( part.get() );
+    }
+
+    InternetCloseHandle( hRequest );
+    InternetCloseHandle( hConnection );
+    InternetCloseHandle( hInternet );
+
+    response._duration_s = OE_STOP_TIMER(http_get);
+
+    if ( progress )
+    {
+        progress->stats("http_get_time") += OE_GET_TIMER(http_get);
+        progress->stats("http_get_count") += 1;
+        if ( response._cancelled )
+            progress->stats("http_cancel_count") += 1;
+    }
+    
+    return response;
+}
+
+#else // OSGEARTH_USE_WININET_FOR_HTTP
+
 HTTPResponse
 HTTPClient::doGet(const HTTPRequest&    request,
                   const osgDB::Options* options, 
@@ -703,6 +965,8 @@ HTTPClient::doGet(const HTTPRequest&    request,
     initialize();
 
     OE_START_TIMER(http_get);
+    
+    std::string url = request.getURL();
 
     const osgDB::AuthenticationMap* authenticationMap = (options && options->getAuthenticationMap()) ? 
             options->getAuthenticationMap() :
@@ -798,14 +1062,13 @@ HTTPClient::doGet(const HTTPRequest&    request,
         curl_easy_setopt( _curl_handle, CURLOPT_PROXY, 0 );
     }
 
-    std::string url = request.getURL();
     // Rewrite the url if the url rewriter is available  
     osg::ref_ptr< URLRewriter > rewriter = getURLRewriter();
     if ( rewriter.valid() )
     {
         std::string oldURL = url;
         url = rewriter->rewrite( oldURL );
-        OE_INFO << LC << "Rewrote URL " << oldURL << " to " << url << std::endl;
+        OE_DEBUG << LC << "Rewrote URL " << oldURL << " to " << url << std::endl;
     }
 
     const osgDB::AuthenticationDetails* details = authenticationMap ?
@@ -846,7 +1109,7 @@ HTTPClient::doGet(const HTTPRequest&    request,
             const_cast<HTTPClient*>(this)->_previousHttpAuthentication = 0;
         }
 #endif
-    }
+    }  
 
 
     // Set any headers
@@ -859,11 +1122,11 @@ HTTPClient::doGet(const HTTPRequest&    request,
             buf << itr->first << ": " << itr->second;
             headers = curl_slist_append(headers, buf.str().c_str());
         }
-    }    
+    }
 
     // Disable the default Pragma: no-cache that curl adds by default.
     headers = curl_slist_append(headers, "Pragma: ");
-    curl_easy_setopt(_curl_handle, CURLOPT_HTTPHEADER, headers);
+    curl_easy_setopt(_curl_handle, CURLOPT_HTTPHEADER, headers); 
     
     osg::ref_ptr<HTTPResponse::Part> part = new HTTPResponse::Part();
     StreamObject sp( &part->_stream );
@@ -933,6 +1196,9 @@ HTTPClient::doGet(const HTTPRequest&    request,
         response._mimeType = content_type_cp;    
     } 
 
+    // read the file time:
+    response._lastModified = getCurlFileTime( _curl_handle );
+
     // upon success, parse the data:
     if ( res != CURLE_ABORTED_BY_CALLBACK && res != CURLE_OPERATION_TIMEDOUT )
     {        
@@ -1035,6 +1301,8 @@ HTTPClient::doGet(const HTTPRequest&    request,
     return response;
 }
 
+#endif // USE_WININET
+
 bool
 HTTPClient::doDownload(const std::string& url, const std::string& filename)
 {
@@ -1151,7 +1419,7 @@ HTTPClient::doReadImage(const HTTPRequest&    request,
         }
         
         // last-modified (file time)
-        result.setLastModifiedTime( getCurlFileTime(_curl_handle) );
+        result.setLastModifiedTime( response._lastModified ); //getCurlFileTime(_curl_handle) );
         
         // Time of query
         result.setDuration( response.getDuration() );
@@ -1230,7 +1498,7 @@ HTTPClient::doReadNode(const HTTPRequest&    request,
         }
         
         // last-modified (file time)
-        result.setLastModifiedTime( getCurlFileTime(_curl_handle) );
+        result.setLastModifiedTime( response._lastModified ); //getCurlFileTime(_curl_handle) );
     }
     else
     {
@@ -1302,7 +1570,7 @@ HTTPClient::doReadObject(const HTTPRequest&    request,
         }
         
         // last-modified (file time)
-        result.setLastModifiedTime( getCurlFileTime(_curl_handle) );
+        result.setLastModifiedTime( response._lastModified ); //getCurlFileTime(_curl_handle) );
     }
     else
     {
@@ -1384,7 +1652,7 @@ HTTPClient::doReadString(const HTTPRequest&    request,
     result.setMetadata( response.getHeadersAsConfig() );
 
     // last-modified (file time)
-    result.setLastModifiedTime( getCurlFileTime(_curl_handle) );
+    result.setLastModifiedTime( response._lastModified ); //getCurlFileTime(_curl_handle) );
 
     return result;
 }
diff --git a/src/osgEarth/HeightFieldUtils b/src/osgEarth/HeightFieldUtils
index b5b6b08..56ff28e 100644
--- a/src/osgEarth/HeightFieldUtils
+++ b/src/osgEarth/HeightFieldUtils
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
@@ -188,9 +188,9 @@ namespace osgEarth
          * the ellipsoid model.
          */
         static osg::NodeCallback* createClusterCullingCallback(
-            osg::HeightField*          grid, 
+            const osg::HeightField*    grid, 
             const osg::EllipsoidModel* em, 
-            float verticalScale =1.0f );
+            float                      verticalScale =1.0f );
 
         /**
          * Convert a heightfield (and its neighbors) into a normal map* image.
diff --git a/src/osgEarth/HeightFieldUtils.cpp b/src/osgEarth/HeightFieldUtils.cpp
index 98b080f..351bd0c 100644
--- a/src/osgEarth/HeightFieldUtils.cpp
+++ b/src/osgEarth/HeightFieldUtils.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -190,12 +190,9 @@ HeightFieldUtils::getHeightAtPixel(const osg::HeightField* hf, double c, double
             {
                 //OE_NOTICE << "Bilinear" << std::endl;
                 //Bilinear interpolate
-                float r1 = ((double)colMax - c) * llHeight + (c - (double)colMin) * lrHeight;
-                float r2 = ((double)colMax - c) * ulHeight + (c - (double)colMin) * urHeight;
-
-                //OE_INFO << "r1, r2 = " << r1 << " , " << r2 << std::endl;
-
-                result = ((double)rowMax - r) * r1 + (r - (double)rowMin) * r2;
+                double r1 = ((double)colMax - c) * (double)llHeight + (c - (double)colMin) * (double)lrHeight;
+                double r2 = ((double)colMax - c) * (double)ulHeight + (c - (double)colMin) * (double)urHeight;
+                result = ((double)rowMax - r) * (double)r1 + (r - (double)rowMin) * (double)r2;
             }
         }
         else if (interpolation == INTERP_AVERAGE)
@@ -325,10 +322,9 @@ HeightFieldUtils::scaleHeightFieldToDegrees( osg::HeightField* hf )
         //TODO: adjust this calculation based on the actual EllipsoidModel.
         float scale = 1.0f/111319.0f;
 
-        for (unsigned int i = 0; i < hf->getHeightList().size(); ++i)
-        {
-            hf->getHeightList()[i] *= scale;
-        }
+        osg::HeightField::HeightList& heights = hf->getHeightList();
+        for(unsigned i=0; i<heights.size(); ++i)
+            heights[i] *= scale;
     }
     else
     {
@@ -461,10 +457,7 @@ HeightFieldUtils::createReferenceHeightField(const GeoExtent& ex,
     }
     else
     {
-        for(unsigned int i=0; i<hf->getHeightList().size(); i++ )
-        {
-            hf->getHeightList()[i] = 0.0;
-        }
+        hf->getFloatArray()->assign(numCols*numRows, 0.0f);
     }
 
     hf->setBorderWidth( 0 );
@@ -503,18 +496,17 @@ HeightFieldUtils::resolveInvalidHeights(osg::HeightField* grid,
     }
     else
     {
-        for(unsigned int i=0; i<grid->getHeightList().size(); i++ )
+        osg::HeightField::HeightList& heights = grid->getHeightList();
+        for(unsigned i=0; i<heights.size(); ++i)
         {
-            if ( grid->getHeightList()[i] == invalidValue )
-            {
-                grid->getHeightList()[i] = 0.0;
-            }
+            if ( heights[i] == invalidValue )
+                heights[i] = 0.0f;
         }
     }
 }
 
 osg::NodeCallback*
-HeightFieldUtils::createClusterCullingCallback(osg::HeightField*          grid, 
+HeightFieldUtils::createClusterCullingCallback(const osg::HeightField*    grid, 
                                                const osg::EllipsoidModel* et, 
                                                float                      verticalScale )
 {
@@ -607,6 +599,8 @@ HeightFieldUtils::convertToNormalMap(const HeightFieldNeighborhood& hood,
                                      const SpatialReference*        hoodSRS)
 {
     const osg::HeightField* hf = hood._center.get();
+    if ( !hf )
+        return 0L;
     
     osg::Image* image = new osg::Image();
     image->allocateImage(hf->getNumColumns(), hf->getNumRows(), 1, GL_RGBA, GL_UNSIGNED_BYTE);
@@ -743,4 +737,4 @@ FillNoDataOperator::operator ()(osg::HeightField *heightField)
         }
     }
 }
-#endif
\ No newline at end of file
+#endif
diff --git a/src/osgEarth/Horizon b/src/osgEarth/Horizon
index 3ff932d..f29b2f4 100644
--- a/src/osgEarth/Horizon
+++ b/src/osgEarth/Horizon
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -25,25 +25,45 @@
 #include <osg/NodeCallback>
 #include <osg/Vec3d>
 #include <osg/Shape>
+#include <osg/observer_ptr>
+#include <osg/Version>
+#include <osg/ValueObject>
+#include <osg/MatrixTransform>
+
+#if OSG_VERSION_GREATER_OR_EQUAL(3,4,0)
+#    define OSGEARTH_HORIZON_SUPPORTS_NODEVISITOR
+#endif
 
 namespace osgEarth
 {
     /**
      * Horizon operations (for a geocentric map).
      */
-    class OSGEARTH_EXPORT Horizon
+    class OSGEARTH_EXPORT Horizon : public osg::Object
     {
     public:
+        META_Object(osgEarth, Horizon);
+
+        // Retrieve a Horizon object from the NodeVisitor. Returns NULL
+        // if this operation is not supported.
+        static Horizon* get(osg::NodeVisitor& nv);
+
+        // Stores this object in the NodeVisitor. Returns false if the
+        // operation is not supported.
+        bool put(osg::NodeVisitor& nv);
+
+    public:
         /** Construct a horizon using a default WGS84 ellipsoid model. */
         Horizon();
 
         /** Construct a horizon providing the ellipsoid model. */
         Horizon(const osg::EllipsoidModel& ellipsoid);
 
-        /** Copy */
-        Horizon(const Horizon& rhs);
+        /** Construct a horizon from a spatial reference. */
+        Horizon(const SpatialReference* srs);
 
-        virtual ~Horizon() { }
+        /** Copy */
+        Horizon(const Horizon& rhs, const osg::CopyOp& op = osg::CopyOp::DEEP_COPY_ALL);
 
         /**
          * Ellipsoid model to use for occlusion testing
@@ -51,15 +71,42 @@ namespace osgEarth
         void setEllipsoid(const osg::EllipsoidModel& ellipsoid);
 
         /**
+         * Set the minimum allowable height-above-ellipsoid to consider when doing
+         * horizon visibility testing.
+         */
+        void setMinHAE(double meters);
+        double getMinHAE() const { return _minHAE; }
+
+        /**
          * Sets the eye position to use when testing for occlusion.
          */
         void setEye(const osg::Vec3d& eyeECEF);
+        
+        /**
+         * Whether a point is visible over the horizon.
+         * Specify an optional radius to test a sphere.
+         */
+        bool isVisible(const osg::Vec3d& point, double radius =0.0) const;
+
+        /**
+         * Whether "target" with bounding radius "radius" is visible from "eye".
+         * This function does not require you to call setEye.
+         */
+        bool isVisible(const osg::Vec3d& eye, const osg::Vec3d& target, double radius) const;
+                
+        /**
+         * Whether a bounding sphere is visible over the horizon.
+         */
+        bool isVisible(const osg::BoundingSphere& bs) const {
+            return isVisible(bs.center(), bs.radius());
+        }
 
         /**
-         * Whether a world point is occluded by the horizon. You can
-         * optionally pass in a radius to test against a sphere.
+         * Whether the horizon occludes a point/sphere.
          */
-        bool occludes(const osg::Vec3d& pointECEF, double radius =0.0) const;
+        bool occludes(const osg::Vec3d& point, double radius =0.0) const {
+            return !isVisible(point, radius);
+        }
 
         /**
          * Sets the output variable to the horizon plane plane with its
@@ -69,11 +116,22 @@ namespace osgEarth
         
     protected:
 
-        osg::Vec3d _cv;
-        double     _vhMag2;
+        virtual ~Horizon() { }
+
+        bool       _valid;
+        osg::Vec3d _eye;
+        osg::Vec3d _eyeUnit;
+        osg::Vec3d _VC;       
+        double     _VCmag;    // distance from eye to center (scaled)
+        double     _VCmag2;   // distance from eye to center squared (scaled)
+        double     _VHmag2;   // distance from eye to horizon squared (scaled)
+        double     _coneCos;  // cosine of half-cone
+        double     _coneTan;  // tangent of half-cone
+
         osg::Vec3d _scale;
         osg::Vec3d _scaleInv;
-        osg::Vec3d _scaleToMinHAE;
+        double     _minVCmag;
+        double     _minHAE;
     };
 
 
@@ -86,16 +144,34 @@ namespace osgEarth
     public:
         /** Construct the callback with a default Horizon model. */
         HorizonCullCallback();
-        
-        /** Construct a cull callback with the specified horizon */
-        HorizonCullCallback(const Horizon& horizon);
 
-        /** Enable/disable */
+        /**
+         * Whether to cull by the center point only, or by the bounding sphere.
+         */
+        void setCullByCenterPointOnly(bool value) { _centerOnly = value; }
+        bool getCullByCenterPointOnly() const { return _centerOnly; }
+
+        /**
+         * Enable or disable the culler
+         */
         void setEnabled(bool value) { _enabled = value; }
+        bool getEnabled() const { return _enabled; }
 
-        /** The horizon to use for culling. */
-        void setHorizon(const Horizon& horizon) { _horizon = horizon; }
-        const Horizon& getHorizon() const       { return _horizon; }
+        /**
+         * Sets an alternate node whose bounds will be used to perform
+         * the culling test. By default, the culling test is performed
+         * against the node to which this callback is attached.
+         */
+        void setProxyNode(osg::Node* node) { _proxy = node; }
+        osg::observer_ptr<osg::Node>& getProxyNode() { return _proxy; }
+        const osg::observer_ptr<osg::Node>& getProxyNode() const { return _proxy; }
+
+        /**
+         * Horizon to cull againts
+         */
+        void setHorizon(Horizon* horizon) { _horizonProto = horizon; }
+        Horizon* getHorizon() { return _horizonProto.get(); }
+        const Horizon* getHorizon() const { return _horizonProto.get(); }
 
     public: // osg::NodeCallback
         void operator()(osg::Node* node, osg::NodeVisitor* nv);
@@ -103,12 +179,24 @@ namespace osgEarth
     protected:
         virtual ~HorizonCullCallback() { }
 
+        bool isVisible(osg::Node* node, osg::NodeVisitor* nv);
+
     private:
-        bool    _enabled;
-        Horizon _horizon;
+        bool _centerOnly;
+        bool _enabled;
+        osg::ref_ptr<Horizon> _horizonProto;
+        osg::observer_ptr<osg::Node> _proxy;
     };
 
 
+    // Debugging node for visualizing the horizon in stealth mode
+    class OSGEARTH_EXPORT HorizonNode : public osg::MatrixTransform
+    {
+    public:
+        HorizonNode();
+        void traverse(osg::NodeVisitor& nv);
+    };
+
 }
 
 #endif // OSGEARTH_HORIZON_H
diff --git a/src/osgEarth/Horizon.cpp b/src/osgEarth/Horizon.cpp
index 25ebbc5..0c7dd45 100644
--- a/src/osgEarth/Horizon.cpp
+++ b/src/osgEarth/Horizon.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -17,35 +17,80 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>
  */
 #include <osgEarth/Horizon>
+#include <osgUtil/CullVisitor>
 #include <osg/Transform>
 #include <osgEarth/Registry>
+#include <osg/ValueObject>
+#include <osg/Geometry>
+#include <osg/Geode>
+
+#define LC "[Horizon] "
+
+#define OSGEARTH_HORIZON_UDC_NAME "osgEarth.Horizon"
 
 using namespace osgEarth;
 
-Horizon::Horizon()
+Horizon::Horizon() :
+_valid( false ),
+_VCmag(0), _VCmag2(0), _VHmag2(0), _coneCos(0), _coneTan(0), _minVCmag(0), _minHAE(0)
 {
+    setName(OSGEARTH_HORIZON_UDC_NAME);
     setEllipsoid(osg::EllipsoidModel());
 }
 
-Horizon::Horizon(const osg::EllipsoidModel& e)
+Horizon::Horizon(const osg::EllipsoidModel& e) :
+_valid( false ),
+_VCmag(0), _VCmag2(0), _VHmag2(0), _coneCos(0), _coneTan(0), _minVCmag(0), _minHAE(0)
 {
+    setName(OSGEARTH_HORIZON_UDC_NAME);
     setEllipsoid( e );
 }
 
-Horizon::Horizon(const Horizon& rhs) :
-_scale        ( rhs._scale ),
-_scaleInv     ( rhs._scaleInv ),
-_cv           ( rhs._cv ),
-_vhMag2       ( rhs._vhMag2 ),
-_scaleToMinHAE( rhs._scaleToMinHAE )
+Horizon::Horizon(const SpatialReference* srs) :
+_valid( false ),
+_VCmag(0), _VCmag2(0), _VHmag2(0), _coneCos(0), _coneTan(0), _minVCmag(0), _minHAE(0)
 {
-    //nop
+    setName(OSGEARTH_HORIZON_UDC_NAME);
+    if ( srs && !srs->isProjected() )
+    {
+        setEllipsoid( *srs->getEllipsoid() );
+    }
+}
+
+Horizon::Horizon(const Horizon& rhs, const osg::CopyOp& op) :
+osg::Object( rhs, op ),
+_valid   ( rhs._valid ),
+_scale   ( rhs._scale ),
+_scaleInv( rhs._scaleInv ),
+_eye     ( rhs._eye ),
+_eyeUnit ( rhs._eyeUnit ),
+_VC      ( rhs._VC ),
+_VCmag   ( rhs._VCmag ),
+_VCmag2  ( rhs._VCmag2 ),
+_VHmag2  ( rhs._VHmag2 ),
+_coneCos ( rhs._coneCos ),
+_coneTan ( rhs._coneTan ),
+_minVCmag( rhs._minVCmag ),
+_minHAE  ( rhs._minHAE )
+{
+    // nop
+}
+
+bool
+Horizon::put(osg::NodeVisitor& nv)
+{
+    return VisitorData::store( nv, OSGEARTH_HORIZON_UDC_NAME, this );
+}
+
+Horizon* Horizon::get(osg::NodeVisitor& nv)
+{
+    return VisitorData::fetch<Horizon>( nv, OSGEARTH_HORIZON_UDC_NAME );
 }
 
 void
 Horizon::setEllipsoid(const osg::EllipsoidModel& e)
 {
-    _scaleInv.set( 
+    _scaleInv.set(
         e.getRadiusEquator(),
         e.getRadiusEquator(),
         e.getRadiusPolar() );
@@ -55,146 +100,406 @@ Horizon::setEllipsoid(const osg::EllipsoidModel& e)
         1.0 / e.getRadiusEquator(),
         1.0 / e.getRadiusPolar() );
 
-    // Minimum allowable HAE for calculating horizon distance.
-    const double minHAE = 100.0;
+    _minHAE = 500.0;
+    _minVCmag = 1.0 + (_scale*_minHAE).length();
 
-    //double maxRadius = std::max(e.getRadiusEquator(), e.getRadiusPolar());
-    //double minHAEScaled = 1.0 + minHAE/maxRadius;
-    //_minHAEScaled2 = minHAEScaled * minHAEScaled;
+    // just so we don't have gargabe values
+    setEye( osg::Vec3d(1e7, 0, 0) );
 
-    _scaleToMinHAE = (_scale*minHAE) + osg::Vec3d(1,1,1);
+    _valid = true;
 }
 
 void
-Horizon::setEye(const osg::Vec3d& eyeECEF)
+Horizon::setMinHAE(double value)
 {
-    _cv = osg::componentMultiply(eyeECEF, _scale);
+    _minHAE = value;
+    _minVCmag = 1.0 + (_scale*_minHAE).length();
+}
+
+void
+Horizon::setEye(const osg::Vec3d& eye)
+{
+    if ( eye != _eye )
+    {
+        _eye = eye;
+        _eyeUnit = eye;
+        _eyeUnit.normalize();
+
+        _VC     = osg::componentMultiply( -_eye, _scale );  // viewer->center (scaled)
+        _VCmag  = std::max( _VC.length(), _minVCmag );      // clamped to the min HAE
+        _VCmag2 = _VCmag*_VCmag;
+        _VHmag2 = _VCmag2 - 1.0;  // viewer->horizon line (scaled)
+
+        double VPmag = _VCmag - 1.0/_VCmag; // viewer->horizon plane dist (scaled)
+        double VHmag = sqrtf( _VHmag2 );
+
+        _coneCos = VPmag / VHmag; // cos of half-angle of horizon cone
+        _coneTan = tan(acos(_coneCos));
+    }
+}
+
+bool
+Horizon::isVisible(const osg::Vec3d& target,
+                   double            radius) const
+{
+    if ( _valid == false || radius >= _scaleInv.x() || radius >= _scaleInv.y() || radius >= _scaleInv.z() )
+        return true;
+
+    // First check the object against the horizon plane, a plane that intersects the
+    // ellipsoid, whose normal is the vector from the eyepoint to the center of the
+    // ellipsoid.
+    // ref: https://cesiumjs.org/2013/04/25/Horizon-culling/
 
-    double cvMag2 = _cv*_cv;
+    // Viewer-to-target vector
+    osg::Vec3d VT;
 
-    osg::Vec3d minCV = _cv;
-    minCV.normalize();
-    minCV = osg::componentMultiply(minCV, _scaleToMinHAE);
-    double min_cvMag2 = minCV*minCV;
+    // move the target closer to the horizon plane by "radius".
+    VT = (target + _eyeUnit*radius) - _eye;
 
-#if 0 // debugging
-    osg::Vec3d msl = _cv;
-    msl.normalize();
-    msl = osg::componentMultiply(msl, _scale+osg::Vec3d(1,1,1));
-    msl = osg::componentMultiply(msl, _scaleInv);
-    double alt = eyeECEF.length() - msl.length();
-#endif
+    // transform into unit space:
+    VT = osg::componentMultiply( VT, _scale );
 
-    if ( cvMag2 >= min_cvMag2 )
+    // If the target is above the eye, it's visible
+    double VTdotVC = VT*_VC;
+    if ( VTdotVC <= 0.0 )
     {
-        _vhMag2 = cvMag2-1.0;
+        return true;
     }
-    else
+
+    // If the eye is below the ellipsoid, but the target is below the eye
+    // (since the above test failed) the target is occluded.
+    // NOTE: it might be better instead to check for a maximum distance from
+    // the eyepoint instead.
+    if ( _VCmag < 0.0 )
     {
-        _cv = minCV;
-        _vhMag2 = (_cv*_cv)-1.0;
+        return false;
     }
-    
-#if 0 // debugging
-    osg::Vec3d vh = _cv;
-    vh.normalize();
-    vh = osg::componentMultiply(vh, (_scale*sqrt(_vhMag2))+osg::Vec3d(1,1,1));
-    vh = _scaleInv * sqrt(_vhMag2);
 
-    static int count=0;
-    if (count++ %60 == 0) {
-        OE_NOTICE << "cvmag2="<< cvMag2 << "; minMag2="<< min_cvMag2 << "; vhMag2=" << _vhMag2 << "; alt=" << alt << "; vh=" << vh.length() << "\n";
+    // Now we know that the eye is above the ellipsoid, so there is a valid horizon plane.
+    // If the point is in front of that horizon plane, it's visible and we're done
+    if ( VTdotVC <= _VHmag2 )
+    {
+        return true;
     }
-#endif
+
+    // The sphere is completely behind the horizon plane. So now intersect the
+    // sphere with the horizon cone, a cone eminating from the eyepoint along the
+    // eye->center vetor. If the sphere is entirely within the cone, it is occluded
+    // by the spheroid (not ellipsoid, sorry)
+    // ref: http://www.cbloom.com/3d/techdocs/culling.txt
+    VT = target - _eye;
+
+    double a = VT * -_eyeUnit;
+    double b = a * _coneTan;
+    double c = sqrt( VT*VT - a*a );
+    double d = c - b;
+    double e = d * _coneCos;
+
+    if ( e > -radius )
+    {
+        // sphere is at least partially outside the cone (visible)
+        return true;
+    }
+
+    // occluded.
+    return false;
 }
 
+
 bool
-Horizon::occludes(const osg::Vec3d& targetECEF,
-                  double            radius) const
+Horizon::isVisible(const osg::Vec3d& eye,
+                   const osg::Vec3d& target,
+                   double            radius) const
 {
-    // ref: https://cesiumjs.org/2013/04/25/Horizon-culling/
+    if ( _valid == false || radius >= _scaleInv.x() || radius >= _scaleInv.y() || radius >= _scaleInv.z() )
+        return true;
+
+    optional<osg::Vec3d> eyeUnit;
 
-    osg::Vec3d tc = targetECEF;
+    osg::Vec3d VC = osg::componentMultiply(-eye, _scale);  // viewer->center (scaled)
 
+    // First check the object against the horizon plane, a plane that intersects the
+    // ellipsoid, whose normal is the vector from the eyepoint to the center of the
+    // ellipsoid.
+    // ref: https://cesiumjs.org/2013/04/25/Horizon-culling/
+
+    // Viewer-to-target
+    osg::Vec3d delta(0,0,0);
     if ( radius > 0.0 )
     {
-        // shift the target point outward to account for its bounding radius.
-        double targetLen2 = tc.length2();
-        osg::Vec3d targetUnit = tc;
-        targetUnit.normalize();
-        tc += targetUnit * radius;
+        eyeUnit = eye;
+        eyeUnit->normalize();
+        delta.set( eyeUnit.get()*radius );
+    }
+    osg::Vec3d VT( target+delta - eye );
+
+    // transform into unit space:
+    VT = osg::componentMultiply( VT, _scale );
+
+    // If the target is above the eye, it's visible
+    double VTdotVC = VT*VC;
+    if ( VTdotVC <= 0.0 )
+    {
+        return true;
+    }
+
+    // If the eye is below the ellipsoid, but the target is below the eye
+    // (since the above test failed) the target is occluded.
+    // NOTE: it might be better instead to check for a maximum distance from
+    // the eyepoint instead.
+    double VCmag = std::max( VC.length(), _minVCmag );      // clamped to the min HAE
+    if ( VCmag < 0.0 )
+    {
+        return false;
     }
-    
-    tc = osg::componentMultiply(tc, _scale);
 
-    osg::Vec3d vt = tc - _cv;
-    double vtMag2 = vt.length2();
-    double vtDotVc = -(vt*_cv);
+    // Now we know that the eye is above the ellipsoid, so there is a valid horizon plane.
+    // If the point is in front of that horizon plane, it's visible and we're done
+    double VHmag2 = VCmag*VCmag - 1.0;  // viewer->horizon line (scaled)
+    if ( VTdotVC <= VHmag2 )
+    {
+        return true;
+    }
 
-    bool behindHorizonPlane = (vtDotVc > _vhMag2);
-    bool insideHorizonCone  = (vtDotVc*vtDotVc / vtMag2) > _vhMag2;
+    // The sphere is completely behind the horizon plane. So now intersect the
+    // sphere with the horizon cone, a cone eminating from the eyepoint along the
+    // eye->center vetor. If the sphere is entirely within the cone, it is occluded
+    // by the spheroid (not ellipsoid, sorry)
+    // ref: http://www.cbloom.com/3d/techdocs/culling.txt
+    VT = target - eye;
+
+    double VPmag  = VCmag - 1.0/VCmag; // viewer->horizon plane dist (scaled)
+    double VHmag  = sqrtf( VHmag2 );
+    double coneCos = VPmag / VHmag; // cos of half-angle of horizon cone
+    double coneTan = tan(acos(coneCos));
+
+    if ( !eyeUnit.isSet() ) {
+        eyeUnit = eye;
+        eyeUnit->normalize();
+    }
+    double a = VT * -eyeUnit.get();
+    double b = a * coneTan;
+    double c = sqrt( VT*VT - a*a );
+    double d = c - b;
+    double e = d * coneCos;
 
-    return behindHorizonPlane && insideHorizonCone;
+    if ( e > -radius )
+    {
+        // sphere is at least partially outside the cone (visible)
+        return true;
+    }
+
+    // occluded.
+    return false;
 }
 
+
 bool
 Horizon::getPlane(osg::Plane& out_plane) const
 {
     // calculate scaled distance from center to viewer:
-    double magVC = _cv.length();
-    if ( magVC == 0.0 )
+    if ( _valid == false || _VCmag2 == 0.0 )
         return false;
 
-    // calculate scaled distance from center to horizon plane:
-    double magPC = 1.0/magVC;
-
-    osg::Vec3d normal = _cv;
-    normal.normalize();
+    double PCmag;
+    if ( _VCmag > 0.0 )
+    {
+        // eyepoint is above ellipsoid? Calculate scaled distance from center to horizon plane
+        PCmag = 1.0/_VCmag;
+    }
+    else
+    {
+        // eyepoint is below the ellipsoid? plane passes through the eyepoint.
+        PCmag = _VCmag;
+    }
 
-    osg::Vec3d pcWorld = osg::componentMultiply(normal*magPC, _scaleInv);
+    osg::Vec3d pcWorld = osg::componentMultiply(_eyeUnit*PCmag, _scaleInv);
     double dist = pcWorld.length();
 
     // compute a new clip plane:
-    out_plane.set(normal, -dist);
+    out_plane.set(_eyeUnit, -dist);
     return true;
 }
 
 //........................................................................
 
+
 HorizonCullCallback::HorizonCullCallback() :
-_enabled( true )
+_enabled   ( true ),
+_centerOnly( false )
 {
     //nop
 }
 
-HorizonCullCallback::HorizonCullCallback(const Horizon& horizon) :
-_horizon( horizon ),
-_enabled( true )
+bool
+HorizonCullCallback::isVisible(osg::Node* node, osg::NodeVisitor* nv)
 {
-    //nop
-}
+    if ( !node )
+        return false;
 
-void
-HorizonCullCallback::operator()(osg::Node* node, osg::NodeVisitor* nv)
-{
-    bool visible = true;
+    osg::NodePath np = nv->getNodePath();
+    osg::Matrix local2world;
+    Horizon* horizon = Horizon::get(*nv);
 
-    if ( _enabled && node && nv && nv->getVisitorType() == nv->CULL_VISITOR )
+    // If we fetched the Horizon from the nodevisitor...
+    if ( horizon )
     {
-        osg::Matrix local2world = osg::computeLocalToWorld(nv->getNodePath());
+        // pop the last node in the path (which is the node this callback is on)
+        // to prevent double-transforming the bounding sphere's center point
+        if (!np.empty() && np.back() == node)
+            np.pop_back();
+        local2world = osg::computeLocalToWorld(np);
 
+        const osg::BoundingSphere& bs = node->getBound();
+        double radius = _centerOnly ? 0.0 : bs.radius();
+        return horizon->isVisible( bs.center()*local2world, radius );
+    }
+
+    // If we are cloning the horizon from a prototype...
+    else if ( _horizonProto.valid() )
+    {
         // make a local copy to support multi-threaded cull
-        Horizon horizon(_horizon);
-        horizon.setEye( osg::Vec3d(nv->getViewPoint()) * local2world );
+        local2world  = osg::computeLocalToWorld(np);
+        osg::Vec3d eye = osg::Vec3d(nv->getViewPoint()) * local2world;
+
+        // pop the last node in the path (which is the node this callback is on)
+        // to prevent double-transforming the bounding sphere's center point
+        np.pop_back();
+        local2world = osg::computeLocalToWorld(np);
+
+        osg::ref_ptr<Horizon> horizonCopy = osg::clone(_horizonProto.get(), osg::CopyOp::DEEP_COPY_ALL);
+        horizonCopy->setEye( eye );
 
         const osg::BoundingSphere& bs = node->getBound();
+        double radius = _centerOnly ? 0.0 : bs.radius();
+        return horizonCopy->isVisible( bs.center()*local2world, radius );
+    }
+
+    // If the user forgot to install a horizon at all...
+    else
+    {
+        // No horizon data... just assume visibility
+        OE_WARN << LC << "No horizon info installed in callback\n";
+        return true;
+    }
+}
 
-        visible = !horizon.occludes( bs.center() * local2world, bs.radius() );
+void
+HorizonCullCallback::operator()(osg::Node* node, osg::NodeVisitor* nv)
+{
+    if ( _enabled )
+    {
+        if ( _proxy.valid() )
+        {
+            osg::ref_ptr<osg::Node> proxy;
+            if ( _proxy.lock(proxy) )
+            {
+                if ( isVisible(proxy.get(), nv) )
+                {
+                    traverse(node, nv);
+                    return;
+                }
+            }
+        }
+
+        if ( isVisible(node, nv) )
+        {
+            traverse(node, nv);
+        }
     }
 
-    if ( visible )
+    else
     {
         traverse(node, nv);
     }
 }
 
+
+
+
+HorizonNode::HorizonNode()
+{
+    const float r = 25.0f;
+    osg::DrawElements* de = new osg::DrawElementsUByte(GL_QUADS);
+    de->addElement(0);
+    de->addElement(1);
+
+    osg::Vec3Array* verts = new osg::Vec3Array();
+    for (unsigned x = 0; x<=(unsigned)r; ++x) {
+        verts->push_back(osg::Vec3(-0.5f + float(x) / r, -0.5f, 0.0f));
+        verts->push_back(osg::Vec3(-0.5f + float(x) / r,  0.5f, 0.0f));
+    }
+
+    de->addElement(verts->size()-1);
+    de->addElement(verts->size()-2);
+
+    for (unsigned y=0; y<=(unsigned)r; ++y) {
+        verts->push_back(osg::Vec3(-0.5f, -0.5f + float(y)/r, 0.0f));
+        verts->push_back(osg::Vec3( 0.5f, -0.5f + float(y)/r, 0.0f));
+    }
+
+    osg::Vec4Array* colors = new osg::Vec4Array();
+    colors->push_back(osg::Vec4(1,0,0,0.5f));
+
+    osg::Geometry* geom = new osg::Geometry();
+    geom->setVertexArray(verts);
+    geom->setColorArray(colors);
+    geom->setColorBinding(geom->BIND_OVERALL);
+    geom->addPrimitiveSet(new osg::DrawArrays(GL_LINES, 0, verts->size()));
+    
+    geom->addPrimitiveSet(de);
+
+    osg::Geode* geode = new osg::Geode();
+    geode->addDrawable(geom);
+    geom->getOrCreateStateSet()->setMode(GL_BLEND, 1);
+    geom->getOrCreateStateSet()->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
+
+    this->addChild(geode);
+
+    setMatrix(osg::Matrix::scale(15e6, 15e6, 15e6));
+}
+
+void
+HorizonNode::traverse(osg::NodeVisitor& nv)
+{
+    bool isStealth = (VisitorData::isSet(nv, "osgEarth.Stealth"));
+
+    if (nv.getVisitorType() == nv.CULL_VISITOR)
+    {
+        if (!isStealth)
+        {
+            //Horizon* h = Horizon::get(nv);
+            osg::ref_ptr<Horizon> h = new Horizon();
+
+            osgUtil::CullVisitor* cv = dynamic_cast<osgUtil::CullVisitor*>(&nv);
+
+            osg::Vec3d eye = osg::Vec3d(0,0,0) * cv->getCurrentCamera()->getInverseViewMatrix();
+            h->setEye(eye);
+
+            osg::Plane plane;
+            if (h->getPlane(plane))
+            {
+                osg::Quat q;
+                q.makeRotate(osg::Plane::Vec3_type(0,0,1), plane.getNormal());
+
+                double dist = plane.distance(osg::Vec3d(0,0,0));
+
+                osg::Matrix m;
+                m.preMultRotate(q);
+                m.preMultTranslate(osg::Vec3d(0, 0, -dist));
+                m.preMultScale(osg::Vec3d(15e6, 15e6, 15e6));
+
+                setMatrix(m);
+            }
+        }
+        else
+        {
+            osg::MatrixTransform::traverse(nv);
+        }
+    }
+       
+    else
+    {
+        osg::MatrixTransform::traverse(nv);
+    }
+}
\ No newline at end of file
diff --git a/src/osgEarth/IOTypes b/src/osgEarth/IOTypes
index 7c04caf..82b94f5 100644
--- a/src/osgEarth/IOTypes
+++ b/src/osgEarth/IOTypes
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
@@ -88,27 +88,27 @@ namespace osgEarth
 
         /** Construct a result with no object */
         ReadResult( Code code =RESULT_NOT_FOUND )
-            : _code(code), _fromCache(false), _lmt(0) { }
+            : _code(code), _fromCache(false), _lmt(0), _duration_s(0.0) { }
 
         /** Construct a result with code and data */
         ReadResult( Code code, osg::Object* result )
-            : _code(code), _result(result), _fromCache(false), _lmt(0) { }
+            : _code(code), _result(result), _fromCache(false), _lmt(0), _duration_s(0.0) { }
 
         /** Construct a result with data, possible with an error code */
         ReadResult( Code code, osg::Object* result, const Config& meta )
-            : _code(code), _result(result), _meta(meta), _fromCache(false), _lmt(0) { }
+            : _code(code), _result(result), _meta(meta), _fromCache(false), _lmt(0), _duration_s(0.0) { }
 
         /** Construct a successful result (implicit OK code) */
         ReadResult( osg::Object* result )
-            : _code(RESULT_OK), _result(result), _fromCache(false), _lmt(0) { }
+            : _code(RESULT_OK), _result(result), _fromCache(false), _lmt(0), _duration_s(0.0) { }
 
         /** Construct a successful result with metadata */
         ReadResult( osg::Object* result, const Config& meta )
-            : _code(RESULT_OK), _result(result), _meta(meta), _fromCache(false), _lmt(0) { }
+            : _code(RESULT_OK), _result(result), _meta(meta), _fromCache(false), _lmt(0), _duration_s(0.0) { }
 
         /** Copy construct */
         ReadResult( const ReadResult& rhs )
-            : _code(rhs._code), _result(rhs._result.get()), _meta(rhs._meta), _fromCache(rhs._fromCache), _lmt(rhs._lmt) { }
+            : _code(rhs._code), _result(rhs._result.get()), _meta(rhs._meta), _fromCache(rhs._fromCache), _lmt(rhs._lmt), _duration_s(rhs._duration_s) { }
 
         /** dtor */
         virtual ~ReadResult() { }
diff --git a/src/osgEarth/IOTypes.cpp b/src/osgEarth/IOTypes.cpp
index f1775b7..047305c 100644
--- a/src/osgEarth/IOTypes.cpp
+++ b/src/osgEarth/IOTypes.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -69,12 +69,15 @@ URIReadCallback::~URIReadCallback()
  * that means that StringObject instances can be read/written to an .osgb
  * file. We use this for caching string data (XML, JSON files for example).
  */
-REGISTER_OBJECT_WRAPPER(StringObject,
-                        new osgEarth::StringObject,
-                        osgEarth::StringObject,
-                        "osgEarth::StringObject")
+namespace
 {
-    ADD_STRING_SERIALIZER( String, "" );  // _str
+    REGISTER_OBJECT_WRAPPER(StringObject,
+                            new osgEarth::StringObject,
+                            osgEarth::StringObject,
+                            "osgEarth::StringObject")
+    {
+        ADD_STRING_SERIALIZER( String, "" );  // _str
+    }
 }
 
 //------------------------------------------------------------------------
diff --git a/src/osgEarth/ImageLayer b/src/osgEarth/ImageLayer
index 4f3f842..6262c8c 100644
--- a/src/osgEarth/ImageLayer
+++ b/src/osgEarth/ImageLayer
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -335,7 +335,7 @@ namespace osgEarth
 
     public: // TerrainLayer override
 
-        CacheBin* getCacheBin( const Profile* profile );
+        //CacheBin* getCacheBin( const Profile* profile );
 
     protected:
 
diff --git a/src/osgEarth/ImageLayer.cpp b/src/osgEarth/ImageLayer.cpp
index 0533276..6c2a6a2 100644
--- a/src/osgEarth/ImageLayer.cpp
+++ b/src/osgEarth/ImageLayer.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -70,7 +70,7 @@ ImageLayerOptions::setDefaults()
     _magFilter.init( osg::Texture::LINEAR );
     _texcomp.init( osg::Texture::USE_IMAGE_DATA_FORMAT ); // none
     _shared.init( false );
-    _coverage.init( false );
+    _coverage.init( false );    
 }
 
 void
@@ -300,6 +300,8 @@ _runtimeOptions( options )
 void
 ImageLayer::init()
 {
+    TerrainLayer::init();
+
     // Set the tile size to 256 if it's not explicitly set.
     if (!_runtimeOptions.driver()->tileSize().isSet())
     {
@@ -307,13 +309,16 @@ ImageLayer::init()
     }
 
     _emptyImage = ImageUtils::createEmptyImage();
-    //*((unsigned*)_emptyImage->data()) = 0x7F0000FF;
 
     if ( _runtimeOptions.shareTexUniformName().isSet() )
         _shareTexUniformName = _runtimeOptions.shareTexUniformName().get();
+    else
+        _shareTexUniformName.init( Stringify() << "layer_" << getUID() << "_tex" );
 
     if ( _runtimeOptions.shareTexMatUniformName().isSet() )
         _shareTexMatUniformName = _runtimeOptions.shareTexMatUniformName().get();
+    else
+        _shareTexMatUniformName.init( Stringify()  << "layer_" << getUID() << "_texMatrix" );
 }
 
 void
@@ -419,7 +424,7 @@ ImageLayer::getOrCreatePreCacheOp()
                 _targetProfileHint->isEquivalentTo( getProfile() );
 
             ImageLayerPreCacheOperation* op = new ImageLayerPreCacheOperation();
-            op->_processor.init( _runtimeOptions, _dbOptions.get(), layerInTargetProfile );
+            op->_processor.init( _runtimeOptions, _readOptions.get(), layerInTargetProfile );
 
             _preCacheOp = op;
         }
@@ -428,20 +433,25 @@ ImageLayer::getOrCreatePreCacheOp()
 }
 
 
-CacheBin*
-ImageLayer::getCacheBin( const Profile* profile)
-{
-    // specialize ImageLayer to only consider the horizontal signature (ignore vertical
-    // datum component for images)
-    std::string binId = *_runtimeOptions.cacheId() + "_" + profile->getHorizSignature();
-    return TerrainLayer::getCacheBin( profile, binId );
-}
+//CacheBin*
+//ImageLayer::getCacheBin( const Profile* profile)
+//{
+//    // specialize ImageLayer to only consider the horizontal signature (ignore vertical
+//    // datum component for images)
+//    std::string binId = *_runtimeOptions.cacheId() + "_" + profile->getHorizSignature();
+//    return TerrainLayer::getCacheBin( profile, binId );
+//}
 
 
 GeoImage
 ImageLayer::createImage(const TileKey&    key,
                         ProgressCallback* progress)
 {
+    if (getStatus().isError())
+    {
+        return GeoImage::INVALID;
+    }
+
     return createImageInKeyProfile( key, progress );
 }
 
@@ -450,7 +460,10 @@ GeoImage
 ImageLayer::createImageInNativeProfile(const TileKey&    key,
                                        ProgressCallback* progress)
 {
-    GeoImage result;
+    if (getStatus().isError())
+    {
+        return GeoImage::INVALID;
+    }
 
     const Profile* nativeProfile = getProfile();
     if ( !nativeProfile )
@@ -458,6 +471,9 @@ ImageLayer::createImageInNativeProfile(const TileKey&    key,
         OE_WARN << LC << "Could not establish the profile" << std::endl;
         return GeoImage::INVALID;
     }
+    
+
+    GeoImage result;
 
     if ( key.getProfile()->isHorizEquivalentTo(nativeProfile) )
     {
@@ -513,7 +529,10 @@ GeoImage
 ImageLayer::createImageInKeyProfile(const TileKey&    key, 
                                     ProgressCallback* progress)
 {
-    GeoImage result;
+    if (getStatus().isError())
+    {
+        return GeoImage::INVALID;
+    }
 
     // If the layer is disabled, bail out.
     if ( !getEnabled() )
@@ -527,51 +546,59 @@ ImageLayer::createImageInKeyProfile(const TileKey&    key,
         return GeoImage::INVALID;
     }
 
+
+    GeoImage result;
+
     OE_DEBUG << LC << "create image for \"" << key.str() << "\", ext= "
         << key.getExtent().toString() << std::endl;
+
+    // the cache key combines the Key and the horizontal profile.
+    std::string cacheKey = Stringify() << key.str() << "_" << key.getProfile()->getHorizSignature();
+    const CachePolicy& policy = getCacheSettings()->cachePolicy().get();
     
     // Check the layer L2 cache first
     if ( _memCache.valid() )
     {
-        CacheBin* bin = _memCache->getOrCreateBin( key.getProfile()->getFullSignature() );        
-        ReadResult result = bin->readObject(key.str() );
+        CacheBin* bin = _memCache->getOrCreateDefaultBin();
+        ReadResult result = bin->readObject(cacheKey, 0L);
         if ( result.succeeded() )
             return GeoImage(static_cast<osg::Image*>(result.releaseObject()), key.getExtent());
-        //_memCache->dumpStats(key.getProfile()->getFullSignature());
     }
 
     // locate the cache bin for the target profile for this layer:
     CacheBin* cacheBin = getCacheBin( key.getProfile() );
 
     // validate that we have either a valid tile source, or we're cache-only.
-    if ( ! (getTileSource() || (isCacheOnly() && cacheBin) ) )
+    if (getTileSource() || (cacheBin && policy.isCacheOnly()))
     {
-        OE_WARN << LC << "Error: layer does not have a valid TileSource, cannot create image " << std::endl;
-        _runtimeOptions.enabled() = false;
+        //nop = OK.
+    }
+    else
+    {
+        disable("Error: layer does not have a valid TileSource, cannot create image");
         return GeoImage::INVALID;
     }
 
     // validate the existance of a valid layer profile (unless we're in cache-only mode, in which
     // case there is no layer profile)
-    if ( !isCacheOnly() && !getProfile() )
+    if ( !policy.isCacheOnly() && !getProfile() )
     {
-        OE_WARN << LC << "Could not establish a valid profile" << std::endl;
-        _runtimeOptions.enabled() = false;
+        disable("Could not establish a valid profile");
         return GeoImage::INVALID;
     }
 
-    osg::ref_ptr< osg::Image > cachedImage;        
+    osg::ref_ptr< osg::Image > cachedImage;
 
     // First, attempt to read from the cache. Since the cached data is stored in the
     // map profile, we can try this first.
-    if ( cacheBin && getCachePolicy().isCacheReadable() )
+    if ( cacheBin && policy.isCacheReadable() )
     {
-        ReadResult r = cacheBin->readImage( key.str() );
+        ReadResult r = cacheBin->readImage(cacheKey, 0L);
         if ( r.succeeded() )
         {
             cachedImage = r.releaseImage();
             ImageUtils::fixInternalFormat( cachedImage.get() );            
-            bool expired = getCachePolicy().isExpired(r.lastModifiedTime());
+            bool expired = policy.isExpired(r.lastModifiedTime());
             if (!expired)
             {
                 OE_DEBUG << "Got cached image for " << key.str() << std::endl;                
@@ -585,7 +612,7 @@ ImageLayer::createImageInKeyProfile(const TileKey&    key,
     }
     
     // The data was not in the cache. If we are cache-only, fail sliently
-    if ( isCacheOnly() )
+    if ( policy.isCacheOnly() )
     {
         // If it's cache only and we have an expired but cached image, just return it.
         if (cachedImage.valid())
@@ -610,22 +637,22 @@ ImageLayer::createImageInKeyProfile(const TileKey&    key,
     // memory cache first:
     if ( result.valid() && _memCache.valid() )
     {
-        CacheBin* bin = _memCache->getOrCreateBin( key.getProfile()->getFullSignature() ); 
-        bin->write(key.str(), result.getImage());
+        CacheBin* bin = _memCache->getOrCreateDefaultBin();
+        bin->write(cacheKey, result.getImage(), 0L);
     }
 
     // If we got a result, the cache is valid and we are caching in the map profile,
     // write to the map cache.
     if (result.valid()  &&
         cacheBin        && 
-        getCachePolicy().isCacheWriteable() )
+        policy.isCacheWriteable())
     {
         if ( key.getExtent() != result.getExtent() )
         {
             OE_INFO << LC << "WARNING! mismatched extents." << std::endl;
         }
 
-        cacheBin->write( key.str(), result.getImage() );
+        cacheBin->write(cacheKey, result.getImage(), 0L);
     }
 
     if ( result.valid() )
@@ -832,7 +859,7 @@ ImageLayer::assembleImageFromTileSource(const TileKey&    key,
             {
                 // a tile completely failed, even with fallback. Eject.
                 OE_DEBUG << LC << "Couldn't fallback on tiles for ImageMosaic" << std::endl;
-                return GeoImage::INVALID;
+                // let it go. The empty areas will be filled with alpha by ImageMosaic.
             }
         }
 
diff --git a/src/osgEarth/ImageMosaic b/src/osgEarth/ImageMosaic
index 13c5647..2237580 100644
--- a/src/osgEarth/ImageMosaic
+++ b/src/osgEarth/ImageMosaic
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarth/ImageMosaic.cpp b/src/osgEarth/ImageMosaic.cpp
index 392fb48..b8ea0b9 100644
--- a/src/osgEarth/ImageMosaic.cpp
+++ b/src/osgEarth/ImageMosaic.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -74,15 +74,24 @@ ImageMosaic::createImage()
         return 0;
     }
 
-    unsigned int tileWidth = _images[0]._image->s();
-    unsigned int tileHeight = _images[0]._image->t();
+    // find the first valid tile and use its size as the mosaic tile size
+    TileImage* tile = 0L;
+    for (int i = 0; i<_images.size() && !tile; ++i)
+        if (_images[i]._image.valid())
+            tile = &_images[i];
+
+    if ( !tile )
+        return 0L;
+
+    unsigned int tileWidth = tile->_image->s();
+    unsigned int tileHeight = tile->_image->t();
 
     //OE_NOTICE << "TileDim " << tileWidth << ", " << tileHeight << std::endl;
 
-    unsigned int minTileX = _images[0]._tileX;
-    unsigned int minTileY = _images[0]._tileY;
-    unsigned int maxTileX = _images[0]._tileX;
-    unsigned int maxTileY = _images[0]._tileY;
+    unsigned int minTileX = tile->_tileX;
+    unsigned int minTileY = tile->_tileY;
+    unsigned int maxTileX = tile->_tileX;
+    unsigned int maxTileY = tile->_tileY;
 
     //Compute the tile size.
     for (TileImageList::iterator i = _images.begin(); i != _images.end(); ++i)
@@ -101,22 +110,30 @@ ImageMosaic::createImage()
     unsigned int pixelsHigh = tilesHigh * tileHeight;
 
     osg::ref_ptr<osg::Image> image = new osg::Image;
-    image->allocateImage(pixelsWide, pixelsHigh, 1, _images[0]._image->getPixelFormat(), _images[0]._image->getDataType());
-    image->setInternalTextureFormat(_images[0]._image->getInternalTextureFormat());
-    ImageUtils::markAsNormalized(image.get(), ImageUtils::isNormalized(_images[0].getImage()));
+    image->allocateImage(pixelsWide, pixelsHigh, 1, tile->_image->getPixelFormat(), tile->_image->getDataType());
+    image->setInternalTextureFormat(tile->_image->getInternalTextureFormat());
+    ImageUtils::markAsNormalized(image.get(), ImageUtils::isNormalized(tile->getImage()));
 
     //Initialize the image to be completely white!
-    memset(image->data(), 0xFF, image->getImageSizeInBytes());
+    //memset(image->data(), 0xFF, image->getImageSizeInBytes());
+
+    ImageUtils::PixelWriter write(image.get());
+    for (unsigned t = 0; t < pixelsHigh; ++t)
+        for (unsigned s = 0; s < pixelsWide; ++s)
+            write(osg::Vec4(1,1,1,0), s, t);
 
     //Composite the incoming images into the master image
     for (TileImageList::iterator i = _images.begin(); i != _images.end(); ++i)
     {
-        osg::Image* sourceTile = i->getImage();
-
         //Determine the indices in the master image for this image
         int dstX = (i->_tileX - minTileX) * tileWidth;
         int dstY = (maxTileY - i->_tileY) * tileHeight;
-        ImageUtils::copyAsSubImage(sourceTile, image.get(), dstX, dstY);
+
+        osg::Image* sourceTile = i->getImage();
+        if ( sourceTile )
+        {
+            ImageUtils::copyAsSubImage(sourceTile, image.get(), dstX, dstY);
+        }
     }
 
     return image.release();
diff --git a/src/osgEarth/ImageToHeightFieldConverter b/src/osgEarth/ImageToHeightFieldConverter
index b53fc3f..810cca3 100644
--- a/src/osgEarth/ImageToHeightFieldConverter
+++ b/src/osgEarth/ImageToHeightFieldConverter
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarth/ImageToHeightFieldConverter.cpp b/src/osgEarth/ImageToHeightFieldConverter.cpp
index c6fe55b..45a6f98 100644
--- a/src/osgEarth/ImageToHeightFieldConverter.cpp
+++ b/src/osgEarth/ImageToHeightFieldConverter.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
@@ -29,12 +29,6 @@
 using namespace osgEarth;
 
 static bool
-isNoData( short s )
-{
-  return s == SHRT_MAX || s == -SHRT_MAX;
-}
-
-static bool
 isNoData( float f )
 {
   return f == FLT_MAX || f == -FLT_MAX;
diff --git a/src/osgEarth/ImageUtils b/src/osgEarth/ImageUtils
index fcb6138..9042a4f 100644
--- a/src/osgEarth/ImageUtils
+++ b/src/osgEarth/ImageUtils
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -21,9 +21,11 @@
 #define OSGEARTH_IMAGEUTILS_H
 
 #include <osgEarth/Common>
+#include <osgEarth/Bounds>
 #include <osg/Image>
 #include <osg/Texture>
 #include <osg/GL>
+#include <osg/NodeVisitor>
 #include <vector>
 
 //These formats were not added to OSG until after 2.8.3 so we need to define them to use them.
@@ -311,6 +313,17 @@ namespace osgEarth
             osg::Texture::InternalFormatMode& out_mode);
 
         /**
+         * Replaces "no data" values in the target image with the corresponding
+         * value found in the "reference" image. The images much be GL_LUMINANCE
+         * data types.
+         */
+        static bool replaceNoDataValues(
+            osg::Image*       target,
+            const Bounds&     targetBounds,
+            const osg::Image* reference,
+            const Bounds&     referenceBounds);
+
+        /**
          * 
          */
         static osg::Image* upSampleNN(const osg::Image* src, int quadrant);
@@ -327,6 +340,9 @@ namespace osgEarth
              */
             PixelReader(const osg::Image* image);
 
+            /** Whether to use bilinear interpolation when reading with u,v coords (default=true) */
+            void setBilinear(bool value) { _bilinear = value; }
+
             /** Whether PixelReader supports a given format/datatype combiniation. */
             static bool supports( GLenum pixelFormat, GLenum dataType );
 
@@ -346,12 +362,7 @@ namespace osgEarth
             }
 
             /** Reads a color from the image by unit coords [0..1] */
-            osg::Vec4 operator()(float s, float t, int r=0, int m=0) const {
-                return (*_reader)(this,
-                    (int)(s * (float)(_image->s()-1)),
-                    (int)(t * (float)(_image->t()-1)),
-                    r, m);
-            }
+            osg::Vec4 operator()(float u, float v, int r=0, int m=0) const;
 
             // internals:
             const unsigned char* data(int s=0, int t=0, int r=0, int m=0) const {
@@ -367,6 +378,7 @@ namespace osgEarth
             unsigned _rowMult;
             unsigned _imageSize;
             bool     _normalized;
+            bool     _bilinear;
         };
         
         /**
@@ -483,6 +495,27 @@ namespace osgEarth
             }
         };
     };
+
+    /** Visitor that finds and operates on textures and images */
+    class OSGEARTH_EXPORT TextureAndImageVisitor : public osg::NodeVisitor
+    {
+    public:
+        TextureAndImageVisitor();
+        virtual ~TextureAndImageVisitor() { }
+
+    public:
+        /** Visits a texture and, by default, all its components images */
+        virtual void apply(osg::Texture& texture);
+
+        /** Visits an image inside a texture */
+        virtual void apply(osg::Image& image) { }
+
+    public: // osg::NodeVisitor
+        virtual void apply(osg::Node& node);
+        virtual void apply(osg::Geode& geode);
+        virtual void apply(osg::Drawable& drawable);
+        virtual void apply(osg::StateSet& stateSet);
+    };
 }
 
 #endif //OSGEARTH_IMAGEUTILS_H
diff --git a/src/osgEarth/ImageUtils.cpp b/src/osgEarth/ImageUtils.cpp
index 40970e6..f557b25 100644
--- a/src/osgEarth/ImageUtils.cpp
+++ b/src/osgEarth/ImageUtils.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -22,6 +22,7 @@
 #include <osgEarth/Registry>
 #include <osgEarth/Capabilities>
 #include <osgEarth/Random>
+#include <osgEarth/GeoCommon>
 #include <osg/Notify>
 #include <osg/Texture>
 #include <osg/ImageSequence>
@@ -911,6 +912,49 @@ ImageUtils::computeTextureCompressionMode(const osg::Image*                 imag
     return false;
 }
 
+bool 
+ImageUtils::replaceNoDataValues(osg::Image*       target,
+                                const Bounds&     targetBounds,
+                                const osg::Image* reference,
+                                const Bounds&     referenceBounds)
+{
+    if (target == 0L ||
+        reference == 0L ||
+        !targetBounds.intersects(referenceBounds) )
+    {
+        return false;
+    }
+
+    float
+        xscale = targetBounds.width()/referenceBounds.width(),
+        yscale = targetBounds.height()/referenceBounds.height();
+
+    float
+        xbias = targetBounds.xMin() - referenceBounds.xMin(),
+        ybias = targetBounds.yMin() - referenceBounds.yMin();
+
+    PixelReader readTarget(target);
+    PixelWriter writeTarget(target);
+    PixelReader readReference(reference);
+
+    for(int s=0; s<target->s(); ++s)
+    {
+        for(int t=0; t<target->t(); ++t)
+        {
+            osg::Vec4f pixel = readTarget(s, t);
+            if ( pixel.r() == NO_DATA_VALUE )
+            {
+                float nx = (float)s / (float)(target->s()-1);
+                float ny = (float)t / (float)(target->t()-1);
+                osg::Vec4f refValue = readReference( xscale*nx+xbias, yscale*ny+ybias );
+                writeTarget(refValue, s, t);
+            }
+        }
+    }
+
+    return true;
+}
+
 bool
 ImageUtils::canConvert( const osg::Image* image, GLenum pixelFormat, GLenum dataType )
 {
@@ -1655,7 +1699,8 @@ namespace
 }
     
 ImageUtils::PixelReader::PixelReader(const osg::Image* image) :
-_image     (image)
+_image     (image),
+_bilinear  (false)
 {
     _normalized = ImageUtils::isNormalized(image);
     _colMult = _image->getPixelSizeInBits() / 8;
@@ -1670,6 +1715,45 @@ _image     (image)
     }
 }
 
+osg::Vec4
+ImageUtils::PixelReader::operator()(float u, float v, int r, int m) const
+ {
+     if ( _bilinear )
+     {
+         float sizeS = (float)(_image->s()-1);
+         float sizeT = (float)(_image->t()-1);
+
+         // u, v => [0..1]
+         float s = u * sizeS;
+         float t = v * sizeT;
+
+         float s0 = std::max(floorf(s), 0.0f);
+         float s1 = std::min(s0+1.0f, sizeS);
+         float smix = s0 < s1 ? (s-s0)/(s1-s0) : 0.0f;
+
+         float t0 = std::max(floorf(t), 0.0f);
+         float t1 = std::min(t0+1.0f, sizeT);
+         float tmix = t0 < t1 ? (t-t0)/(t1-t0) : 0.0f;
+
+         osg::Vec4 UL = (*_reader)(this, (int)s0, (int)t0, r, m); // upper left
+         osg::Vec4 UR = (*_reader)(this, (int)s1, (int)t0, r, m); // upper right
+         osg::Vec4 LL = (*_reader)(this, (int)s0, (int)t1, r, m); // lower left
+         osg::Vec4 LR = (*_reader)(this, (int)s1, (int)t1, r, m); // lower right
+
+         osg::Vec4 TOP = UL*(1.0f-smix) + UR*smix;
+         osg::Vec4 BOT = LL*(1.0f-smix) + LR*smix;
+
+         return TOP*(1.0f-tmix) + BOT*tmix;
+     }
+     else
+     {
+         return (*_reader)(this,
+             (int)(u * (float)(_image->s()-1)),
+             (int)(v * (float)(_image->t()-1)),
+             r, m);
+     }
+}
+
 bool
 ImageUtils::PixelReader::supports( GLenum pixelFormat, GLenum dataType )
 {
@@ -1764,3 +1848,78 @@ ImageUtils::PixelWriter::supports( GLenum pixelFormat, GLenum dataType )
 {
     return getWriter(pixelFormat, dataType) != 0L;
 }
+
+TextureAndImageVisitor::TextureAndImageVisitor() :
+osg::NodeVisitor()
+{
+    setNodeMaskOverride( ~0L );
+    setTraversalMode(TRAVERSE_ALL_CHILDREN);
+}
+
+void
+TextureAndImageVisitor::apply(osg::Texture& texture)
+{
+    for (unsigned k = 0; k < texture.getNumImages(); ++k)
+    {
+        osg::Image* image = texture.getImage(k);
+        if (image)
+        {
+            apply(*image);
+        }
+    }
+}
+
+void
+TextureAndImageVisitor::apply(osg::Node& node)
+{
+    if (node.getStateSet())
+        apply(*node.getStateSet());
+
+    traverse(node);
+}
+
+void
+TextureAndImageVisitor::apply(osg::Geode& geode)
+{
+    if (geode.getStateSet())
+        apply(*geode.getStateSet());
+
+    for (unsigned i = 0; i < geode.getNumDrawables(); ++i) {
+        apply(*geode.getDrawable(i));
+        //if (geode.getDrawable(i) && geode.getDrawable(i)->getStateSet())
+        //    apply(*geode.getDrawable(i)->getStateSet());
+    }
+
+    //traverse(geode);
+}
+
+void
+TextureAndImageVisitor::apply(osg::Drawable& drawable)
+{
+    if (drawable.getStateSet())
+        apply(*drawable.getStateSet());
+
+    //traverse(drawable);
+}
+
+void
+TextureAndImageVisitor::apply(osg::StateSet& stateSet)
+{
+    osg::StateSet::TextureAttributeList& a = stateSet.getTextureAttributeList();
+    for (osg::StateSet::TextureAttributeList::iterator i = a.begin(); i != a.end(); ++i)
+    {
+        osg::StateSet::AttributeList& b = *i;
+        for (osg::StateSet::AttributeList::iterator j = b.begin(); j != b.end(); ++j)
+        {
+            osg::StateAttribute* sa = j->second.first.get();
+            if (sa)
+            {
+                osg::Texture* tex = dynamic_cast<osg::Texture*>(sa);
+                if (tex)
+                {
+                    apply(*tex);
+                }
+            }
+        }
+    }
+}
diff --git a/src/osgEarth/Instancing.vert.glsl b/src/osgEarth/Instancing.vert.glsl
index 92d34b5..08ae434 100644
--- a/src/osgEarth/Instancing.vert.glsl
+++ b/src/osgEarth/Instancing.vert.glsl
@@ -1,16 +1,16 @@
-#version 130
+#version $GLSL_VERSION_STR
 #extension GL_EXT_gpu_shader4 : enable
 #extension GL_ARB_draw_instanced: enable
 
-#pragma vp_entryPoint "oe_di_setInstancePosition"
-#pragma vp_location   "vertex_model"
-#pragma vp_order      "0.0"
+#pragma vp_entryPoint oe_di_setInstancePosition
+#pragma vp_location   vertex_model
+#pragma vp_order      0.0
 
 uniform samplerBuffer oe_di_postex_TBO;
-uniform int			  oe_di_postex_TBO_size;
 
 // Stage-global containing object ID
 uint oe_index_objectid;
+vec3 vp_Normal;
 
 void oe_di_setInstancePosition(inout vec4 VertexMODEL)
 { 
@@ -27,5 +27,11 @@ void oe_di_setInstancePosition(inout vec4 VertexMODEL)
     
     // rebuild positioning matrix and transform the vert. (Note, the matrix is actually
     // transposed so we have to reverse the multiplication order.)
-    VertexMODEL = VertexMODEL * mat4(m0, m1, m2, vec4(0,0,0,1));
+    mat4 xform = mat4(m0, m1, m2, vec4(0,0,0,1));
+
+    VertexMODEL = VertexMODEL * xform;
+
+    // rotate the normal vector in the same manner.
+    vp_Normal = vp_Normal * mat3(xform);
 }
+
diff --git a/src/osgEarth/IntersectionPicker b/src/osgEarth/IntersectionPicker
index 705f681..3d925b5 100644
--- a/src/osgEarth/IntersectionPicker
+++ b/src/osgEarth/IntersectionPicker
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarth/IntersectionPicker.cpp b/src/osgEarth/IntersectionPicker.cpp
index 939f76a..b8f71b3 100644
--- a/src/osgEarth/IntersectionPicker.cpp
+++ b/src/osgEarth/IntersectionPicker.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -125,7 +125,7 @@ IntersectionPicker::pick( float x, float y, Hits& results ) const
     //picker->setIntersectionLimit( osgUtil::Intersector::LIMIT_ONE_PER_DRAWABLE );
 
     // in MODEL mode, we need to window and proj matrixes in order to support some of the 
-    // features in osgEarth (like Annotation::OrthoNode).
+    // features in osgEarth (like Annotation::GeoPositionNode).
     if ( _root.valid() )
     {
         iv.pushWindowMatrix( new osg::RefMatrix(windowMatrix) );
diff --git a/src/osgEarth/JsonUtils b/src/osgEarth/JsonUtils
index 4275ab8..f7c59c9 100644
--- a/src/osgEarth/JsonUtils
+++ b/src/osgEarth/JsonUtils
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -919,7 +919,7 @@ public: // overridden from ValueArrayAllocator
    /** \brief Experimental and untested: base class for Value iterators.
     *
     */
-   class ValueIteratorBase
+   class JSON_API ValueIteratorBase
    {
    public:
       typedef unsigned int size_t;
@@ -987,7 +987,7 @@ public: // overridden from ValueArrayAllocator
    /** \brief Experimental and untested: const iterator for object and array value.
     *
     */
-   class ValueConstIterator : public ValueIteratorBase
+   class JSON_API ValueConstIterator : public ValueIteratorBase
    {
       friend class Value;
    public:
@@ -1045,7 +1045,7 @@ public: // overridden from ValueArrayAllocator
 
    /** \brief Experimental and untested: iterator for object and array value.
     */
-   class ValueIterator : public ValueIteratorBase
+   class JSON_API ValueIterator : public ValueIteratorBase
    {
       friend class Value;
    public:
diff --git a/src/osgEarth/JsonUtils.cpp b/src/osgEarth/JsonUtils.cpp
index 5825d88..bc27049 100644
--- a/src/osgEarth/JsonUtils.cpp
+++ b/src/osgEarth/JsonUtils.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -572,6 +572,7 @@ Value::Value( ValueType type )
 
 Value::Value( Int value )
    : type_( intValue )
+   , allocated_( 0 )
    , comments_( 0 )
 # ifdef JSON_VALUE_USE_INTERNAL_MAP
    , itemIsUsed_( 0 )
@@ -583,6 +584,7 @@ Value::Value( Int value )
 
 Value::Value( UInt value )
    : type_( uintValue )
+   , allocated_( 0 )
    , comments_( 0 )
 # ifdef JSON_VALUE_USE_INTERNAL_MAP
    , itemIsUsed_( 0 )
@@ -593,6 +595,7 @@ Value::Value( UInt value )
 
 Value::Value( double value )
    : type_( realValue )
+   , allocated_( 0 )
    , comments_( 0 )
 # ifdef JSON_VALUE_USE_INTERNAL_MAP
    , itemIsUsed_( 0 )
@@ -652,6 +655,7 @@ Value::Value( const CppTL::ConstString &value )
 
 Value::Value( bool value )
    : type_( booleanValue )
+   , allocated_(false)
    , comments_( 0 )
 # ifdef JSON_VALUE_USE_INTERNAL_MAP
    , itemIsUsed_( 0 )
@@ -663,6 +667,7 @@ Value::Value( bool value )
 
 Value::Value( const Value &other )
    : type_( other.type_ )
+   , allocated_(false)
    , comments_( 0 )
 # ifdef JSON_VALUE_USE_INTERNAL_MAP
    , itemIsUsed_( 0 )
@@ -1776,7 +1781,8 @@ Value::end()
 // //////////////////////////////////////////////////////////////////
 
 PathArgument::PathArgument()
-   : kind_( kindNone )
+   : index_(0)
+   , kind_( kindNone )
 {
 }
 
@@ -1791,6 +1797,7 @@ PathArgument::PathArgument( Value::UInt index )
 PathArgument::PathArgument( const char *key )
    : key_( key )
    , kind_( kindKey )
+   , index_(0)
 {
 }
 
@@ -1798,6 +1805,7 @@ PathArgument::PathArgument( const char *key )
 PathArgument::PathArgument( const std::string &key )
    : key_( key.c_str() )
    , kind_( kindKey )
+   , index_(0)
 {
 }
 
@@ -2016,8 +2024,15 @@ namespace osgEarth {
 // Class Reader
 // //////////////////////////////////////////////////////////////////
 
-Reader::Reader()
+Reader::Reader() :
+begin_(0),
+end_(0),
+current_(0),
+lastValueEnd_(0),
+lastValue_(0),
+collectComments_(false)
 {
+    //nop
 }
 
 bool
@@ -2497,7 +2512,7 @@ Reader::decodeDouble( Token &token )
    int length = int(token.end_ - token.start_);
    if ( length <= bufferSize )
    {
-      Char buffer[bufferSize];
+      Char buffer[bufferSize+1];
       memcpy( buffer, token.start_, length );
       buffer[length] = 0;
       count = sscanf( buffer, "%lf", &value );
@@ -2959,6 +2974,7 @@ FastWriter::writeValue( const Value &value )
 StyledWriter::StyledWriter()
    : rightMargin_( 74 )
    , indentSize_( 3 )
+   , addChildValues_(false)
 {
 }
 
@@ -3235,6 +3251,7 @@ StyledStreamWriter::StyledStreamWriter( std::string indentation )
    : document_(NULL)
    , rightMargin_( 74 )
    , indentation_( indentation )
+   , addChildValues_(false)
 {
 }
 
diff --git a/src/osgEarth/Layer b/src/osgEarth/Layer
index 417c0dd..2366975 100644
--- a/src/osgEarth/Layer
+++ b/src/osgEarth/Layer
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarth/Layer.cpp b/src/osgEarth/Layer.cpp
index e716a25..a8e6b61 100644
--- a/src/osgEarth/Layer.cpp
+++ b/src/osgEarth/Layer.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarth/LineFunctor b/src/osgEarth/LineFunctor
index 894e33d..d2204bf 100644
--- a/src/osgEarth/LineFunctor
+++ b/src/osgEarth/LineFunctor
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarth/LocalTangentPlane b/src/osgEarth/LocalTangentPlane
index 8e5a839..d472e02 100644
--- a/src/osgEarth/LocalTangentPlane
+++ b/src/osgEarth/LocalTangentPlane
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarth/LocalTangentPlane.cpp b/src/osgEarth/LocalTangentPlane.cpp
index b29fc31..ffe09e1 100644
--- a/src/osgEarth/LocalTangentPlane.cpp
+++ b/src/osgEarth/LocalTangentPlane.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarth/Locators b/src/osgEarth/Locators
index d39ef4f..445c11f 100644
--- a/src/osgEarth/Locators
+++ b/src/osgEarth/Locators
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -26,6 +26,9 @@
 
 namespace osgEarth
 {
+    class MapInfo;
+    class TileKey;
+
     /**
      * Locator that stores the extent of its source data (which might be different
      * than the extent of the locator's transform). This locator can also automatically
@@ -46,11 +49,11 @@ namespace osgEarth
         /** dtor */
         virtual ~GeoLocator() { }
 
-        static GeoLocator* createForKey( const class TileKey& key, const class MapInfo& mapInfo );
-        static GeoLocator* createForExtent( const GeoExtent& extent, const class MapInfo& mapInfo);
+        static GeoLocator* createForKey( const TileKey& key, const MapInfo& mapInfo );
+        static GeoLocator* createForExtent( const GeoExtent& extent, const MapInfo& mapInfo);
 
-        GeoLocator* createSameTypeForKey(const class TileKey& key, const class MapInfo& mapInfo );
-        virtual GeoLocator* createSameTypeForExtent(const GeoExtent& extent, const class MapInfo& mapInfo);
+        GeoLocator* createSameTypeForKey(const TileKey& key, const MapInfo& mapInfo );
+        virtual GeoLocator* createSameTypeForExtent(const GeoExtent& extent, const MapInfo& mapInfo);
 
         void setDataExtent( const GeoExtent& extent );
         const GeoExtent& getDataExtent() const;
diff --git a/src/osgEarth/Locators.cpp b/src/osgEarth/Locators.cpp
index 2968aad..fb3e825 100644
--- a/src/osgEarth/Locators.cpp
+++ b/src/osgEarth/Locators.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarth/Map b/src/osgEarth/Map
index 0e1ea26..ee63fb7 100644
--- a/src/osgEarth/Map
+++ b/src/osgEarth/Map
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -288,33 +288,7 @@ namespace osgEarth
          * Gets the readable name of this map.
          */
         const std::string& getName() const { return _name; }
-        
-        /**
-         * Creates a flat heightfield (MSL) for the given tilekey.
-         */
-        osg::HeightField* createReferenceHeightField(
-            const TileKey& key,
-            bool           expressHeightsAsHAE =true) const;
-        
-#if 0
-        /**
-         * Populates a heightfield with data from the elevation layers
-         * in the map. The method will create a new heightfield if you
-         * don't supply one to populate.
-         *
-         * NOTE: By default, this method will populate the heightfield with HAE (height
-         * above ellipsoid) values, even if the TileKey profile has an MSL vertical
-         * datum. That is because this method is usually called to produce a renderable
-         * height field. You can override this behavior by passing in convertToHAE=false.
-         */
-        bool populateHeightField(
-            osg::ref_ptr<osg::HeightField>& hf,
-            const TileKey&                  key,
-            bool                            expressHeightsAsHAE =true,
-            ElevationSamplePolicy           samplePolicy        =SAMPLE_FIRST_VALID,
-            ProgressCallback*               progress            =0L) const;
-#endif
-
+              
         /**
          * Sets the Cache for this Map. Set to NULL for no cache.
          */
@@ -358,7 +332,7 @@ namespace osgEarth
         /**
          * Gets the database options associated with this map.
          */
-        const osgDB::Options* getDBOptions() const { return _dbOptions.get(); }
+        const osgDB::Options* getReadOptions() const { return _readOptions.get(); }
 
         const Profile* getProfileNoVDatum() const { return _profileNoVDatum.get(); }
 
@@ -378,12 +352,11 @@ namespace osgEarth
         MaskLayerVector _terrainMaskLayers;
         MapCallbackList _mapCallbacks;
         osg::ref_ptr<const osgDB::Options> _globalOptions;
-        Threading::ReadWriteMutex _mapDataMutex;
+        mutable Threading::ReadWriteMutex _mapDataMutex;
         osg::ref_ptr<const Profile> _profile;
         osg::ref_ptr<const Profile> _profileNoVDatum;
-        osg::ref_ptr<Cache> _cache;
         Revision _dataModelRevision;
-        osg::ref_ptr<osgDB::Options> _dbOptions;
+        osg::ref_ptr<osgDB::Options> _readOptions;
 
         struct ElevationLayerCB : public ElevationLayerCallback {
             osg::observer_ptr<Map> _map;
diff --git a/src/osgEarth/Map.cpp b/src/osgEarth/Map.cpp
index 8964df4..eef6afa 100644
--- a/src/osgEarth/Map.cpp
+++ b/src/osgEarth/Map.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -69,25 +69,35 @@ _dataModelRevision   ( 0 )
             << _mapOptions.cachePolicy()->usageString() << ")" << std::endl;
     }
 
-    // Combine the CachePolicy in the map options with the settings in
-    // the registry.
-    Registry::instance()->resolveCachePolicy( _mapOptions.cachePolicy() );
-
     // the map-side dbOptions object holds I/O information for all components.
-    _dbOptions = osg::clone( Registry::instance()->getDefaultOptions() );
+    _readOptions = osg::clone( Registry::instance()->getDefaultOptions() );
 
-    // we do our own caching
-    _dbOptions->setObjectCacheHint( osgDB::Options::CACHE_NONE );
+    // put the CacheSettings object in there. We will propogate this throughout
+    // the data model and the renderer.
+    CacheSettings* cacheSettings = new CacheSettings();
 
-    // store the IO information in the top-level DB Options:
-    _mapOptions.cachePolicy()->apply( _dbOptions.get() );
-    URIContext( _mapOptions.referrer() ).apply( _dbOptions.get() );
+    // Set up a cache if there's one in the options:
+    if (_mapOptions.cache().isSet())
+        cacheSettings->setCache(CacheFactory::create(_mapOptions.cache().get()));
+
+    // Otherwise use the registry default cache if there is one:
+    if (cacheSettings->getCache() == 0L)
+        cacheSettings->setCache(Registry::instance()->getDefaultCache());
+
+    // Integrate local cache policy (which can be overridden by the environment)
+    cacheSettings->integrateCachePolicy(_mapOptions.cachePolicy());
+
+    // store in the options so we can propagate it to layers, etc.
+    cacheSettings->store(_readOptions.get());
+
+    OE_INFO << LC << cacheSettings->toString() << "\n";
 
-    // apply an express tile size if there is one.
-    if ( _mapOptions.elevationTileSize().isSet() )
-    {
-        _elevationLayers.setExpressTileSize( *_mapOptions.elevationTileSize() );
-    }
+
+    // remember the referrer for relative-path resolution:
+    URIContext( _mapOptions.referrer() ).store( _readOptions.get() );
+
+    // we do our own caching
+    _readOptions->setObjectCacheHint( osgDB::Options::CACHE_NONE );
 
     // set up a callback that the Map will use to detect Elevation Layer
     // visibility changes
@@ -305,8 +315,6 @@ Map::setName( const std::string& name ) {
 Revision
 Map::getDataModelRevision() const
 {
-    //Don't really need this here.
-    //Threading::ScopedReadLock lock( const_cast<Map*>(this)->_mapDataMutex );
     return _dataModelRevision;
 }
 
@@ -321,53 +329,17 @@ Map::getProfile() const
 Cache*
 Map::getCache() const
 {
-    if ( !_cache.valid() )
-    {
-        Cache* cache = 0L;
-        
-        // if there's a cache in the registry, install it now.
-        if ( Registry::instance()->getCache() )
-        {
-            cache = Registry::instance()->getCache();
-        }
-
-        // or, if a cache is defined in the options, use that.
-        else if ( _mapOptions.cache().isSet() )
-        {
-            cache = CacheFactory::create( _mapOptions.cache().get() );
-        }
-
-        if ( cache )
-        {
-            const_cast<Map*>(this)->setCache( cache );
-        }
-    }
-    return _cache.get();
+    CacheSettings* cacheSettings = CacheSettings::get(_readOptions.get());
+    return cacheSettings ? cacheSettings->getCache() : 0L;
 }
 
 void
-Map::setCache( Cache* cache )
+Map::setCache(Cache* cache)
 {
-    if (_cache.get() != cache)
-    {
-        _cache = cache;
-
-        if ( _cache.valid() )
-        {
-            _cache->apply( _dbOptions.get() );
-        }
-
-        // Propagate the cache to any of our layers
-        for (ImageLayerVector::iterator i = _imageLayers.begin(); i != _imageLayers.end(); ++i)
-        {
-            i->get()->setDBOptions( _dbOptions.get() );
-        }
-
-        for (ElevationLayerVector::iterator i = _elevationLayers.begin(); i != _elevationLayers.end(); ++i)
-        {
-            i->get()->setDBOptions( _dbOptions.get() );
-        }
-    }
+    // note- probably unsafe to do this after initializing the terrain. so don't.
+    CacheSettings* cacheSettings = CacheSettings::get(_readOptions.get());
+    if (cacheSettings && cacheSettings->getCache() != cache)
+        cacheSettings->setCache(cache);
 }
 
 void 
@@ -417,10 +389,7 @@ Map::addImageLayer( ImageLayer* layer )
     if ( layer )
     {
         // Set the DB options for the map from the layer, including the cache policy.
-        layer->setDBOptions( _dbOptions.get() );
-
-        // propagate the cache to the layer:
-        layer->setCache( this->getCache() );
+        layer->setReadOptions( _readOptions.get() );
 
         // Tell the layer the map profile, if possible:
         if ( _profile.valid() )
@@ -428,6 +397,9 @@ Map::addImageLayer( ImageLayer* layer )
             layer->setTargetProfileHint( _profile.get() );
         }
 
+        // open the layer:
+        layer->open();
+
         int newRevision;
 
         // Add the layer to our stack.
@@ -456,14 +428,16 @@ Map::insertImageLayer( ImageLayer* layer, unsigned int index )
     if ( layer )
     {
         //Set options for the map from the layer
-        layer->setDBOptions( _dbOptions.get() );
-
-        //Set the Cache for the MapLayer to our cache.
-        layer->setCache( this->getCache() );
+        layer->setReadOptions( _readOptions.get() );
 
         // Tell the layer the map profile, if possible:
         if ( _profile.valid() )
+        {
             layer->setTargetProfileHint( _profile.get() );
+        }
+
+        // open the layer:
+        layer->open();
 
         int newRevision;
 
@@ -485,7 +459,7 @@ Map::insertImageLayer( ImageLayer* layer, unsigned int index )
             i->get()->onMapModelChanged( MapModelChange(
                 MapModelChange::ADD_IMAGE_LAYER, newRevision, layer, index) );
         }   
-    }   
+    } 
 }
 
 void
@@ -496,15 +470,14 @@ Map::addElevationLayer( ElevationLayer* layer )
     if ( layer )
     {
         //Set options for the map from the layer
-        layer->setDBOptions( _dbOptions.get() );
+        layer->setReadOptions( _readOptions.get() );
 
-        //Set the Cache for the MapLayer to our cache.
-        layer->setCache( this->getCache() );
-        
         // Tell the layer the map profile, if possible:
         if ( _profile.valid() )
             layer->setTargetProfileHint( _profile.get() );
 
+        layer->open();
+
         int newRevision;
 
         // Add the layer to our stack.
@@ -711,7 +684,10 @@ Map::addModelLayer( ModelLayer* layer )
         }
 
         // initialize the model layer
-        layer->initialize( _dbOptions.get() );
+        layer->setReadOptions(_readOptions.get());
+
+        // open it and check the status
+        layer->open();
 
         // a seprate block b/c we don't need the mutex
         for( MapCallbackList::iterator i = _mapCallbacks.begin(); i != _mapCallbacks.end(); i++ )
@@ -735,7 +711,10 @@ Map::insertModelLayer( ModelLayer* layer, unsigned int index )
         }
 
         // initialize the model layer
-        layer->initialize( _dbOptions.get() );
+        layer->setReadOptions(_readOptions.get());
+
+        // open and get the status
+        layer->open();
 
         // a seprate block b/c we don't need the mutex
         for( MapCallbackList::iterator i = _mapCallbacks.begin(); i != _mapCallbacks.end(); i++ )
@@ -835,7 +814,9 @@ Map::addTerrainMaskLayer( MaskLayer* layer )
             newRevision = ++_dataModelRevision;
         }
 
-        layer->initialize( _dbOptions.get(), this );
+        layer->setReadOptions(_readOptions.get());
+
+        layer->open();
 
         // a separate block b/c we don't need the mutex   
         for( MapCallbackList::iterator i = _mapCallbacks.begin(); i != _mapCallbacks.end(); i++ )
@@ -1108,42 +1089,6 @@ Map::calculateProfile()
     }
 }
 
-osg::HeightField*
-Map::createReferenceHeightField(const TileKey& key,
-                                bool           expressHeightsAsHAE) const
-{
-    unsigned size = std::max(*_mapOptions.elevationTileSize(), 2u);
-    return HeightFieldUtils::createReferenceHeightField(key.getExtent(), size, size, expressHeightsAsHAE);
-}
-
-#if 0
-bool
-Map::populateHeightField(osg::ref_ptr<osg::HeightField>& hf,
-                         const TileKey&                  key,
-                         bool                            convertToHAE,
-                         ElevationSamplePolicy           samplePolicy, // deprecated (unused)
-                         bool                            fallbackIfPossible,
-                         ProgressCallback*               progress) const
-{
-    Threading::ScopedReadLock lock( const_cast<Map*>(this)->_mapDataMutex );
-
-    ElevationInterpolation interp = getMapOptions().elevationInterpolation().get();    
-
-    if ( !hf.valid() )
-    {
-        hf = createReferenceHeightField(key, convertToHAE);
-    }
-
-    return _elevationLayers.populateHeightField(
-        hf.get(),
-        key,
-        convertToHAE ? _profileNoVDatum.get() : 0L,
-        interp,
-        fallbackIfPossible,
-        progress );
-}
-#endif
-
 const SpatialReference*
 Map::getWorldSRS() const
 {
@@ -1171,8 +1116,6 @@ Map::sync( MapFrame& frame ) const
         if ( frame._parts & ELEVATION_LAYERS )
         {
             frame._elevationLayers = _elevationLayers;
-            if ( _mapOptions.elevationTileSize().isSet() )
-                frame._elevationLayers.setExpressTileSize( *_mapOptions.elevationTileSize() );
         }
 
         if ( frame._parts & MODEL_LAYERS )
diff --git a/src/osgEarth/MapCallback b/src/osgEarth/MapCallback
index 6daaae8..36bd9a5 100644
--- a/src/osgEarth/MapCallback
+++ b/src/osgEarth/MapCallback
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarth/MapCallback.cpp b/src/osgEarth/MapCallback.cpp
index 9f34ba7..82d9a37 100644
--- a/src/osgEarth/MapCallback.cpp
+++ b/src/osgEarth/MapCallback.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarth/MapFrame b/src/osgEarth/MapFrame
index 166c2ff..f6ea581 100644
--- a/src/osgEarth/MapFrame
+++ b/src/osgEarth/MapFrame
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -27,6 +27,8 @@
 
 namespace osgEarth
 {
+    class Profile;
+
     /**
      * A "snapshot in time" of a Map model revision. Use this class to get a safe "copy" of
      * the map model lists that you can use without worrying about the model changing underneath
@@ -50,21 +52,6 @@ namespace osgEarth
 
         bool isValid() const;
 
-        /**
-         * Constructs a new map frame and connects it to a map.
-         */
-        //MapFrame(
-        //    const Map*         map, 
-        //    Map::ModelParts    parts =Map::TERRAIN_LAYERS,
-        //    const std::string& name  ="" );
-
-        /**
-         * A copy constructor with a new name (no sync happens)
-         */
-       // MapFrame(
-        //    const MapFrame& frame, 
-        //    const std::string& name ="" );
-
         /** dtor */
         virtual ~MapFrame() { }
 
diff --git a/src/osgEarth/MapFrame.cpp b/src/osgEarth/MapFrame.cpp
index 3533389..55d9bf1 100644
--- a/src/osgEarth/MapFrame.cpp
+++ b/src/osgEarth/MapFrame.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -17,6 +17,7 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>
  */
 #include <osgEarth/MapFrame>
+#include <osgEarth/Cache>
 
 using namespace osgEarth;
 
@@ -25,7 +26,8 @@ using namespace osgEarth;
 MapFrame::MapFrame() :
 _initialized    ( false ),
 _highestMinLevel( 0 ),
-_mapInfo       ( 0L )
+_mapInfo       ( 0L ),
+_parts(Map::ENTIRE_MODEL)
 {
     //nop
 }
@@ -172,12 +174,6 @@ MapFrame::populateHeightField(osg::ref_ptr<osg::HeightField>& hf,
     if ( _map.lock(map) )
     {        
         ElevationInterpolation interp = map->getMapOptions().elevationInterpolation().get();    
-
-        if ( !hf.valid() )
-        {
-            hf = map->createReferenceHeightField(key, convertToHAE);
-        }
-
         return _elevationLayers.populateHeightField(
             hf.get(),
             key,
@@ -253,11 +249,11 @@ MapFrame::isCached( const TileKey& key ) const
             continue;
 
         // If we're cache only we should be fast
-        if (layer->isCacheOnly())
+        if (layer->getCacheSettings()->cachePolicy()->isCacheOnly())
             continue;
 
-        // no-cache mode? always slow
-        if (layer->isNoCache())
+        // no-cache? always slow
+        if (layer->getCacheSettings()->cachePolicy()->isCacheDisabled())
             return false;
 
         // No tile source? skip it
@@ -285,11 +281,11 @@ MapFrame::isCached( const TileKey& key ) const
             continue;
 
         //If we're cache only we should be fast
-        if (layer->isCacheOnly())
+        if (layer->getCacheSettings()->cachePolicy()->isCacheOnly())
             continue;
 
-        // no-cache mode? always high-latency.
-        if (layer->isNoCache())
+        // no-cache? always high-latency.
+        if (layer->getCacheSettings()->cachePolicy()->isCacheDisabled())
             return false;
 
         osg::ref_ptr< TileSource > source = layer->getTileSource();
diff --git a/src/osgEarth/MapInfo b/src/osgEarth/MapInfo
index 5b5b680..c19790c 100644
--- a/src/osgEarth/MapInfo
+++ b/src/osgEarth/MapInfo
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarth/MapInfo.cpp b/src/osgEarth/MapInfo.cpp
index dc79e96..d55ae1f 100644
--- a/src/osgEarth/MapInfo.cpp
+++ b/src/osgEarth/MapInfo.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarth/MapModelChange b/src/osgEarth/MapModelChange
index 8710887..3a169c0 100644
--- a/src/osgEarth/MapModelChange
+++ b/src/osgEarth/MapModelChange
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarth/MapNode b/src/osgEarth/MapNode
index 73f0b64..c9dc4b6 100644
--- a/src/osgEarth/MapNode
+++ b/src/osgEarth/MapNode
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
@@ -26,15 +26,15 @@
 #include <osgEarth/Common>
 #include <osgEarth/Map>
 #include <osgEarth/MapNodeOptions>
-#include <osgEarth/SpatialReference>
-#include <osgEarth/TerrainEngineNode>
 #include <osgEarth/Extension>
 
 namespace osgEarth
 {
     class OverlayDecorator;
     class Terrain;
+    class TerrainEngineNode;
     class MapNodeCullData;
+    class SpatialReference;
 
     /**
      * OSG Node that forms the root of an osgEarth map. This node is a "view" component
@@ -44,9 +44,18 @@ namespace osgEarth
     {
     public:
         /**
-         * Attempts to load a MapNOde from a ".earth" file in the arguments list
+         * Attempts to load a MapNode from a ".earth" file in the arguments list
          */
-        static MapNode* load( class osg::ArgumentParser& arguments );
+        static MapNode* load(
+            class osg::ArgumentParser& arguments);
+
+        /**
+         * Attempts to load a MapNode from an ".earth" file, with a set of default
+         * map and terrain options.
+         */
+        static MapNode* load(
+            class osg::ArgumentParser& arguments,
+            const MapNodeOptions&      defaultOptions);
 
     public:
         /**
@@ -186,6 +195,23 @@ namespace osgEarth
          */
         const std::vector< osg::ref_ptr<Extension> >& getExtensions() const { return _extensions; }
 
+        /**
+         * Find an extension by type and return it.
+         */
+        template<typename T>
+        T* getExtension() const {
+            for(std::vector< osg::ref_ptr<Extension> >::const_iterator i = _extensions.begin(); i != _extensions.end(); ++i) {
+                T* e = dynamic_cast<T*>(i->get());
+                if ( e ) return e;
+            }
+            return 0L;
+        }
+
+        /**
+         * Opens all layers that are not already open.
+         */
+        void openMapLayers();
+
 
     public: // special purpose
 
@@ -228,6 +254,8 @@ namespace osgEarth
 
         std::vector< osg::ref_ptr<Extension> > _extensions;
 
+        Revisioned _mapRevisionMonitor;
+
     public: // MapCallback proxy
 
         void onModelLayerAdded( ModelLayer*, unsigned int );
@@ -247,10 +275,12 @@ namespace osgEarth
     
         void init();
 
+#if 0
         MapNodeCullData* getCullData(osg::Camera* camera) const;
         typedef std::map<osg::Camera*, osg::ref_ptr<MapNodeCullData> > CullDataMap;
         mutable CullDataMap _cullData;
         mutable Threading::ReadWriteMutex _cullDataMutex;
+#endif
     };
 
 } // namespace osgEarth
diff --git a/src/osgEarth/MapNode.cpp b/src/osgEarth/MapNode.cpp
index 7db970c..dc22be0 100644
--- a/src/osgEarth/MapNode.cpp
+++ b/src/osgEarth/MapNode.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
@@ -37,6 +37,8 @@
 #include <osgEarth/TerrainEngineNode>
 #include <osgEarth/TextureCompositor>
 #include <osgEarth/ShaderGenerator>
+#include <osgEarth/SpatialReference>
+#include <osgEarth/MapModelChange>
 #include <osgEarth/URI>
 #include <osg/ArgumentParser>
 #include <osg/PagedLOD>
@@ -47,7 +49,7 @@ using namespace osgEarth;
 
 //---------------------------------------------------------------------------
 
-namespace 
+namespace
 {
     // adapter that lets MapNode listen to Map events
     struct MapNodeMapCallbackProxy : public MapCallback
@@ -100,13 +102,13 @@ public:
       }
 
       virtual void apply(osg::PagedLOD& node)
-      {        
-          //The PagedLOD node will contain two filenames, the first is empty and is the actual geometry of the          
+      {
+          //The PagedLOD node will contain two filenames, the first is empty and is the actual geometry of the
           //tile and the second is the filename of the next tile.
           if (node.getNumFileNames() > 1)
           {
               //Get the child filename
-              const std::string &filename = node.getFileName(1);              
+              const std::string &filename = node.getFileName(1);
               if (osgEarth::Registry::instance()->isBlacklisted(filename))
               {
                   //If the tile is blacklisted, we set the actual geometry, child 0, to always display
@@ -125,16 +127,16 @@ public:
                       if (node.getRangeMode() == osg::LOD::PIXEL_SIZE_ON_SCREEN)
                       {
                           node.setRange( 0, ranges->_minRange, ranges->_maxRange );
-                          node.setRange( 1, ranges->_maxRange, FLT_MAX );                          
+                          node.setRange( 1, ranges->_maxRange, FLT_MAX );
                       }
                       else
-                      {                          
+                      {
                           node.setRange(0, ranges->_minRange, ranges->_maxRange);
                           node.setRange(1, 0, ranges->_minRange);
                       }
-                  }                  
+                  }
               }
-              
+
           }
           traverse(node);
       }
@@ -157,7 +159,27 @@ MapNode::load(osg::ArgumentParser& args)
                 return r.release<MapNode>();
             }
         }
-    }    
+    }
+    return 0L;
+}
+
+MapNode*
+MapNode::load(osg::ArgumentParser& args, const MapNodeOptions& defaults)
+{
+    for( int i=1; i<args.argc(); ++i )
+    {
+        if ( args[i] && endsWith(args[i], ".earth") )
+        {
+            osg::ref_ptr<osgDB::Options> dbo = new osgDB::Options();
+            std::string optionsJSON = defaults.getConfig().toJSON();
+            dbo->setPluginStringData( "osgEarth.defaultOptions", optionsJSON );
+            ReadResult r = URI(args[i]).readNode( dbo.get() );
+            if ( r.succeeded() )
+            {
+                return r.release<MapNode>();
+            }
+        }
+    }
     return 0L;
 }
 
@@ -207,7 +229,7 @@ MapNode::init()
     // deleting during startup. It is possible that during startup, a driver
     // will load that will take a reference to the MapNode (like in a
     // ModelSource node operation) and we don't want that deleting the MapNode
-    // out from under us. 
+    // out from under us.
     // This is paired by an unref_nodelete() at the end of this method.
     this->ref();
 
@@ -238,14 +260,14 @@ MapNode::init()
     // will make their way to any read* calls down the pipe
     const osgDB::Options* global_options = _map->getGlobalOptions();
 
-    osg::ref_ptr<osgDB::Options> local_options = global_options ? 
+    osg::ref_ptr<osgDB::Options> local_options = global_options ?
         Registry::instance()->cloneOrCreateOptions( global_options ) :
         NULL;
 
     if ( local_options.valid() )
     {
         OE_INFO << LC
-            << "Options string = " 
+            << "Options string = "
             << (local_options.valid()? local_options->getOptionString() : "<empty>")
             << std::endl;
     }
@@ -272,8 +294,8 @@ MapNode::init()
         _terrainEngineContainer->getOrCreateStateSet()->addUniform(
             Registry::shaderFactory()->createUniformForGLMode(GL_LIGHTING, *terrainOptions.enableLighting()) );
 
-        _terrainEngineContainer->getOrCreateStateSet()->setMode( 
-            GL_LIGHTING, 
+        _terrainEngineContainer->getOrCreateStateSet()->setMode(
+            GL_LIGHTING,
             terrainOptions.enableLighting().value() ? 1 : 0 );
     }
 
@@ -281,7 +303,7 @@ MapNode::init()
     {
         // inform the terrain engine of the map information now so that it can properly
         // initialize it's CoordinateSystemNode. This is necessary in order to support
-        // manipulators and to set up the texture compositor prior to frame-loop 
+        // manipulators and to set up the texture compositor prior to frame-loop
         // initialization.
         _terrainEngine->preInitialize( _map.get(), terrainOptions );
         _terrainEngineContainer->addChild( _terrainEngine );
@@ -297,7 +319,7 @@ MapNode::init()
     // model layer will still work OK though.
     _models = new osg::Group();
     _models->setName( "osgEarth::MapNode.modelsGroup" );
-    _models->getOrCreateStateSet()->setRenderBinDetails(2, "RenderBin");
+    //_models->getOrCreateStateSet()->setRenderBinDetails(1, "RenderBin");
     addChild( _models.get() );
 
     // a decorator for overlay models:
@@ -322,6 +344,7 @@ MapNode::init()
         if ( _mapNodeOptions.overlayResolutionRatio().isSet() )
             draping->setResolutionRatio( *_mapNodeOptions.overlayResolutionRatio() );
 
+        draping->reestablish( getTerrainEngine() );
         _overlayDecorator->addTechnique( draping );
     }
 
@@ -330,7 +353,6 @@ MapNode::init()
         _overlayDecorator->addTechnique( new ClampingTechnique() );
     }
 
-
     addTerrainDecorator( _overlayDecorator );
 
     // install any pre-existing model layers:
@@ -351,11 +373,11 @@ MapNode::init()
     if ( _mapNodeOptions.enableLighting().isSet() )
     {
         stateset->addUniform(Registry::shaderFactory()->createUniformForGLMode(
-            GL_LIGHTING, 
+            GL_LIGHTING,
             _mapNodeOptions.enableLighting().value() ? 1 : 0));
 
-        stateset->setMode( 
-            GL_LIGHTING, 
+        stateset->setMode(
+            GL_LIGHTING,
             _mapNodeOptions.enableLighting().value() ? 1 : 0);
     }
 
@@ -366,18 +388,27 @@ MapNode::init()
         OE_INFO << LC << "Adding ellipsoid uniforms.\n";
 
         // for a geocentric map, use an ellipsoid unit-frame transform and its inverse:
-        osg::Vec3d ellipFrameInverse(
-            _map->getSRS()->getEllipsoid()->getRadiusEquator(),
-            _map->getSRS()->getEllipsoid()->getRadiusEquator(),
-            _map->getSRS()->getEllipsoid()->getRadiusPolar());
-        stateset->addUniform( new osg::Uniform("oe_ellipsoidFrameInverse", osg::Vec3f(ellipFrameInverse)) );
-
-        osg::Vec3d ellipFrame = osg::componentDivide(osg::Vec3d(1.0,1.0,1.0), ellipFrameInverse);
-        stateset->addUniform( new osg::Uniform("oe_ellipsoidFrame", osg::Vec3f(ellipFrame)) );
+        if (_map->getSRS() != NULL && _map->getSRS()->getEllipsoid() != NULL)
+        {
+            osg::Vec3d ellipFrameInverse(
+                _map->getSRS()->getEllipsoid()->getRadiusEquator(),
+                _map->getSRS()->getEllipsoid()->getRadiusEquator(),
+                _map->getSRS()->getEllipsoid()->getRadiusPolar());
+            stateset->addUniform( new osg::Uniform("oe_ellipsoidFrameInverse", osg::Vec3f(ellipFrameInverse)) );
+
+            osg::Vec3d ellipFrame = osg::componentDivide(osg::Vec3d(1.0,1.0,1.0), ellipFrameInverse);
+            stateset->addUniform( new osg::Uniform("oe_ellipsoidFrame", osg::Vec3f(ellipFrame)) );
+        }
+        else
+        {
+            stateset->addUniform( new osg::Uniform("oe_ellipsoidFrameInverse", osg::Vec3f()) );
+            stateset->addUniform( new osg::Uniform("oe_ellipsoidFrame", osg::Vec3f()) );
+        }
     }
 
     // install the default rendermode uniform:
     stateset->addUniform( new osg::Uniform("oe_isPickCamera", false) );
+    stateset->addUniform( new osg::Uniform("oe_isShadowCamera", false) );
 
     dirtyBound();
 
@@ -394,7 +425,7 @@ MapNode::~MapNode()
 
     ModelLayerVector modelLayers;
     _map->getModelLayers( modelLayers );
-    //Remove our model callback from any of the model layers in the map    
+    //Remove our model callback from any of the model layers in the map
     for (osgEarth::ModelLayerVector::iterator itr = modelLayers.begin(); itr != modelLayers.end(); ++itr)
     {
         this->onModelLayerRemoved( itr->get() );
@@ -437,6 +468,8 @@ MapNode::getMapSRS() const
 Terrain*
 MapNode::getTerrain()
 {
+    if (getTerrainEngine() == NULL)
+          return NULL;
     return getTerrainEngine()->getTerrain();
 }
 
@@ -469,13 +502,18 @@ MapNode::addExtension(Extension* extension, const osgDB::Options* options)
         // set the IO options is they were provided:
         if ( options )
             extension->setDBOptions( options );
-        
+
+        else if ( getMap()->getReadOptions() )
+            extension->setDBOptions( getMap()->getReadOptions() );
+
         // start it.
         ExtensionInterface<MapNode>* extensionIF = ExtensionInterface<MapNode>::get(extension);
         if ( extensionIF )
         {
             extensionIF->connect( this );
         }
+
+        OE_INFO << LC << "Added extension [" << extension->getName() << "]\n";
     }
 }
 
@@ -545,27 +583,26 @@ MapNode::onModelLayerAdded( ModelLayer* layer, unsigned int index )
 {
     if ( !layer->getEnabled() )
         return;
-    
+
     // install a noe operation that will associate this mapnode with
     // any MapNodeObservers loaded by the model layer:
     ModelSource* modelSource = layer->getModelSource();
     if ( modelSource )
     {
-        // install a post-processing callback on the ModelLayer's source 
+        // install a post-processing callback on the ModelLayer's source
         // so we can update the MapNode on new data that comes in:
         modelSource->addPostMergeOperation( new MapNodeObserverInstaller(this) );
     }
 
     // create the scene graph:
-    //osg::Node* node = layer->getOrCreateSceneGraph( _map.get(), _map->getDBOptions(), 0L );
-    osg::Node* node = layer->getOrCreateSceneGraph( _map.get(), 0L );
+    osg::Node* node = layer->getOrCreateSceneGraph( _map.get(), _map->getReadOptions(), 0L );
 
     if ( node )
     {
         if ( _modelLayerNodes.find( layer ) != _modelLayerNodes.end() )
         {
             OE_WARN
-                << "Illegal: tried to add the name model layer more than once: " 
+                << "Illegal: tried to add the name model layer more than once: "
                 << layer->getName()
                 << std::endl;
         }
@@ -588,8 +625,17 @@ MapNode::onModelLayerAdded( ModelLayer* layer, unsigned int index )
                 // enfore a rendering bin if necessary:
                 if ( ms->getOptions().renderOrder().isSet() )
                 {
-                    node->getOrCreateStateSet()->setRenderBinDetails(
-                        ms->getOptions().renderOrder().value(), "RenderBin" );
+                    osg::StateSet* mss = node->getOrCreateStateSet();
+                    mss->setRenderBinDetails(
+                        ms->getOptions().renderOrder().value(),
+                        mss->getBinName().empty() ? "DepthSortedBin" : mss->getBinName());
+                }
+                if ( ms->getOptions().renderBin().isSet() )
+                {
+                    osg::StateSet* mss = node->getOrCreateStateSet();
+                    mss->setRenderBinDetails(
+                        mss->getBinNumber(),
+                        ms->getOptions().renderBin().get() );
                 }
             }
 
@@ -619,10 +665,10 @@ MapNode::onModelLayerRemoved( ModelLayer* layer )
             {
                 _models->removeChild( node );
             }
-            
+
             _modelLayerNodes.erase( i );
         }
-        
+
         dirtyBound();
     }
 }
@@ -641,7 +687,7 @@ MapNode::onModelLayerMoved( ModelLayer* layer, unsigned int oldIndex, unsigned i
             _models->removeChild( node.get() );
             _models->insertChild( newIndex, node.get() );
         }
-        
+
         dirtyBound();
     }
 }
@@ -662,7 +708,7 @@ namespace
 
 void
 MapNode::addTerrainDecorator(osg::Group* decorator)
-{    
+{
     if ( _terrainEngine )
     {
         decorator->addChild( _terrainEngine );
@@ -700,6 +746,47 @@ MapNode::removeTerrainDecorator(osg::Group* decorator)
     }
 }
 
+namespace
+{
+    template<typename T> void tryOpenLayer(T* layer)
+    {
+        if (!layer->getStatus().isError())
+        {
+            const Status& status = layer->open();
+            if (status.isError())
+            {
+                OE_WARN << LC << "Failed to open layer \"" << layer->getName() << "\" ... " << status.message() << std::endl;
+            }
+        }
+    }
+}
+
+void
+MapNode::openMapLayers()
+{
+    MapFrame frame(_map.get());
+
+    for (unsigned i = 0; i < frame.imageLayers().size(); ++i)
+    {
+        tryOpenLayer(frame.getImageLayerAt(i));
+    }
+
+    for (unsigned i = 0; i < frame.elevationLayers().size(); ++i)
+    {
+        tryOpenLayer(frame.getElevationLayerAt(i));
+    }
+
+    for (unsigned i = 0; i < frame.modelLayers().size(); ++i)
+    {
+        tryOpenLayer(frame.getModelLayerAt(i));
+    }
+
+    for (unsigned i = 0; i < frame.terrainMaskLayers().size(); ++i)
+    {
+        tryOpenLayer(frame.terrainMaskLayers().at(i).get());
+    }
+}
+
 void
 MapNode::traverse( osg::NodeVisitor& nv )
 {
@@ -714,50 +801,26 @@ MapNode::traverse( osg::NodeVisitor& nv )
             _terrainEngine->accept( v );
         }
 
+        // This is a placeholder for later, if we decide to delay the automatic opening of
+        // layers until the first traversal.
+#if 0
+        // if the model has changed, we need to queue up an update so we can open new layers.
+        if (_mapRevisionMonitor.outOfSyncWith(_map->getDataModelRevision()))
+        {
+            openMapLayers();
+            _mapRevisionMonitor.sync(_map->getDataModelRevision());
+        }
+#endif
+
         // traverse:
         std::for_each( _children.begin(), _children.end(), osg::NodeAcceptOp(nv) );
     }
 
-    else if ( nv.getVisitorType() == nv.CULL_VISITOR )
+    else if (nv.getVisitorType() == nv.UPDATE_VISITOR || nv.getVisitorType() == nv.CULL_VISITOR)
     {
-        osgUtil::CullVisitor* cv = Culling::asCullVisitor(nv);
-        if ( cv )
-        {
-            // insert traversal data for this camera:
-            osg::ref_ptr<osg::Referenced> oldUserData = cv->getUserData();
-            MapNodeCullData* cullData = getCullData( cv->getCurrentCamera() );
-            cv->setUserData( cullData );
-
-            cullData->_mapNode = this;
-
-            // calculate altitude:
-            osg::Vec3d eye = cv->getViewPoint();
-            const SpatialReference* srs = getMapSRS();
-            if ( srs && !srs->isProjected() )
-            {
-                GeoPoint lla;
-                lla.fromWorld( srs, eye );
-                cullData->_cameraAltitude = lla.alt();
-                cullData->_cameraAltitudeUniform->set( (float)lla.alt() );
-                //OE_INFO << lla.alt() << std::endl;
-            }
-            else
-            {
-                cullData->_cameraAltitude = eye.z();
-                cullData->_cameraAltitudeUniform->set( (float)eye.z() );
-            }
-
-            // window matrix:
-            cullData->_windowMatrixUniform->set( cv->getWindowMatrix() );
-
-            // traverse:
-            cv->pushStateSet( cullData->_stateSet.get() );
-            std::for_each( _children.begin(), _children.end(), osg::NodeAcceptOp(nv) );
-            cv->popStateSet();
-
-            // restore:
-            cv->setUserData( oldUserData.get() );
-        }
+        // put the MapNode in the visitor data and traverse.
+        VisitorData::store(nv, "osgEarth::MapNode", this);
+        std::for_each( _children.begin(), _children.end(), osg::NodeAcceptOp(nv) );
     }
 
     else
@@ -765,27 +828,3 @@ MapNode::traverse( osg::NodeVisitor& nv )
         osg::Group::traverse( nv );
     }
 }
-
-MapNodeCullData*
-MapNode::getCullData(osg::Camera* key) const
-{
-    // first look it up:
-    {
-        Threading::ScopedReadLock shared( _cullDataMutex );
-        CullDataMap::const_iterator i = _cullData.find( key );
-        if ( i != _cullData.end() )
-            return i->second.get();
-    }
-    // if it's not there, make it, but double-check.
-    {
-        Threading::ScopedWriteLock exclusive( _cullDataMutex );
-        
-        CullDataMap::const_iterator i = _cullData.find( key );
-        if ( i != _cullData.end() )
-            return i->second.get();
-
-        MapNodeCullData* cullData = new MapNodeCullData();
-        _cullData[key] = cullData;
-        return cullData;
-    }
-}
diff --git a/src/osgEarth/MapNodeObserver b/src/osgEarth/MapNodeObserver
index 073f414..ea11487 100644
--- a/src/osgEarth/MapNodeObserver
+++ b/src/osgEarth/MapNodeObserver
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarth/MapNodeOptions b/src/osgEarth/MapNodeOptions
index 3e17046..9c633df 100644
--- a/src/osgEarth/MapNodeOptions
+++ b/src/osgEarth/MapNodeOptions
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarth/MapNodeOptions.cpp b/src/osgEarth/MapNodeOptions.cpp
index 7004e17..2447ec3 100644
--- a/src/osgEarth/MapNodeOptions.cpp
+++ b/src/osgEarth/MapNodeOptions.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarth/MapOptions b/src/osgEarth/MapOptions
index 73b2dc0..5a74e39 100644
--- a/src/osgEarth/MapOptions
+++ b/src/osgEarth/MapOptions
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
@@ -51,8 +51,7 @@ namespace osgEarth
               _cachePolicy           ( ),
               _cstype                ( CSTYPE_GEOCENTRIC ),
               _referenceURI          ( "" ),
-              _elevationInterpolation( INTERP_BILINEAR ),
-              _elevTileSize          ( 17 )
+              _elevationInterpolation( INTERP_BILINEAR )
         {
             fromConfig(_conf);
         }
@@ -98,14 +97,7 @@ namespace osgEarth
         optional<ElevationInterpolation>& elevationInterpolation(void) { return _elevationInterpolation; }
         const optional<ElevationInterpolation>& elevationInterpolation(void) const { return _elevationInterpolation;}
 
-        /**
-         * Dimension of elevation tiles. By default, the engine will return 
-         * elevation tiles sized to the largest available source tile. This forces
-         * a set size.
-         */
-        optional<unsigned>& elevationTileSize() { return _elevTileSize; }
-        const optional<unsigned>& elevationTileSize() const { return _elevTileSize; }
-
+        
     public:
         /**
          * A reference location that drivers can use to load data from relative locations.
@@ -132,7 +124,6 @@ namespace osgEarth
         optional<CoordinateSystemType>   _cstype;
         optional<std::string>            _referenceURI;
         optional<ElevationInterpolation> _elevationInterpolation;
-        optional<unsigned>               _elevTileSize;
     };
 }
 
diff --git a/src/osgEarth/MapOptions.cpp b/src/osgEarth/MapOptions.cpp
index cc6005b..dc95195 100644
--- a/src/osgEarth/MapOptions.cpp
+++ b/src/osgEarth/MapOptions.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -46,8 +46,6 @@ MapOptions::fromConfig( const Config& conf )
     conf.getIfSet( "elevation_interpolation", "average",     _elevationInterpolation, INTERP_AVERAGE);
     conf.getIfSet( "elevation_interpolation", "bilinear",    _elevationInterpolation, INTERP_BILINEAR);
     conf.getIfSet( "elevation_interpolation", "triangulate", _elevationInterpolation, INTERP_TRIANGULATE);
-
-    conf.getIfSet( "elevation_tile_size", _elevTileSize );
 }
 
 Config
@@ -70,7 +68,5 @@ MapOptions::getConfig() const
     conf.updateIfSet( "elevation_interpolation", "bilinear",    _elevationInterpolation, INTERP_BILINEAR);
     conf.updateIfSet( "elevation_interpolation", "triangulate", _elevationInterpolation, INTERP_TRIANGULATE);
 
-    conf.updateIfSet( "elevation_tile_size", _elevTileSize );
-
     return conf;
 }
diff --git a/src/osgEarth/MaskLayer b/src/osgEarth/MaskLayer
index a832048..e856a4a 100644
--- a/src/osgEarth/MaskLayer
+++ b/src/osgEarth/MaskLayer
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -127,7 +127,17 @@ namespace osgEarth
 
     public:
 
-        void initialize( const osgDB::Options* dbOptions, const Map* map );
+        void setReadOptions(const osgDB::Options* readOptions);
+
+        const Status& open();
+
+        const Status& getStatus() const { return _status; }
+
+    protected:
+
+        Status initialize();
+
+        void setStatus(const Status& value) { _status = value; }
 
     private:
         MaskLayerOptions              _initOptions;
@@ -135,8 +145,9 @@ namespace osgEarth
         osg::ref_ptr<MaskSource>      _maskSource;
         Revision                      _maskSourceRev;
         osg::ref_ptr<osg::Vec3dArray> _boundary;
-        osg::ref_ptr<osgDB::Options>  _dbOptions;
+        osg::ref_ptr<osgDB::Options>  _readOptions;
         OpenThreads::Mutex            _mutex;
+        Status                        _status;
 
         void copyOptions();
     };
diff --git a/src/osgEarth/MaskLayer.cpp b/src/osgEarth/MaskLayer.cpp
index 6c3a914..fab35c4 100644
--- a/src/osgEarth/MaskLayer.cpp
+++ b/src/osgEarth/MaskLayer.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -18,6 +18,7 @@
  */
 #include <osgEarth/MaskLayer>
 #include <osgEarth/Map>
+#include <osgEarth/Registry>
 
 #define LC "[MaskLayer] "
 
@@ -100,24 +101,50 @@ MaskLayer::copyOptions()
 }
 
 void
-MaskLayer::initialize( const osgDB::Options* dbOptions, const Map* map )
+MaskLayer::setReadOptions(const osgDB::Options* readOptions)
 {
-    _dbOptions = osg::clone(dbOptions);
+    _readOptions = Registry::cloneOrCreateOptions(readOptions);
+}
 
+const Status&
+MaskLayer::open()
+{
+    _status = initialize();
+    return _status;
+}
+
+Status
+MaskLayer::initialize()
+{
     if ( !_maskSource.valid() && _initOptions.driver().isSet() )
     {
         _maskSource = MaskSourceFactory::create( *_initOptions.driver() );
+        if (!_maskSource.valid())
+        {
+            return Status::Error(Status::ServiceUnavailable, Stringify()<<"Failed to create mask driver (" << _initOptions.driver()->getDriver() << ")");
+        }
     }
 
     if ( _maskSource.valid() )
     {
-        _maskSource->initialize( dbOptions );
+        const Status& sourceStatus = _maskSource->open(_readOptions.get());  
+        if (sourceStatus.isError())
+        {
+            return sourceStatus;
+        }
     }
+
+    return Status::OK();
 }
 
 osg::Vec3dArray*
 MaskLayer::getOrCreateMaskBoundary( float heightScale, const SpatialReference *srs, ProgressCallback* progress )
 {
+    if (getStatus().isError())
+    {
+        return 0L;
+    }
+
     OpenThreads::ScopedLock< OpenThreads::Mutex > lock( _mutex );
     if ( _maskSource.valid() )
     {
@@ -130,13 +157,21 @@ MaskLayer::getOrCreateMaskBoundary( float heightScale, const SpatialReference *s
         if ( !_boundary.valid() )
         {
 			_boundary = _maskSource->createBoundary( srs, progress );
-
-			for (osg::Vec3dArray::iterator vIt = _boundary->begin(); vIt != _boundary->end(); ++vIt)
-				vIt->z() = vIt->z() * heightScale;
-
-            _maskSource->sync( _maskSourceRev );
+            
+            if (_boundary.valid())
+            {
+			    for (osg::Vec3dArray::iterator vIt = _boundary->begin(); vIt != _boundary->end(); ++vIt)
+    				vIt->z() = vIt->z() * heightScale;
+
+                _maskSource->sync( _maskSourceRev );
+            }
         }
     }
 
+    if (!_boundary.valid())
+    {
+        setStatus(Status::Error("Failed to create masking boundary"));
+    }
+
     return _boundary.get();
 }
diff --git a/src/osgEarth/MaskNode b/src/osgEarth/MaskNode
index e0fab45..755c1fd 100644
--- a/src/osgEarth/MaskNode
+++ b/src/osgEarth/MaskNode
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarth/MaskNode.cpp b/src/osgEarth/MaskNode.cpp
index cee7e96..e557af4 100644
--- a/src/osgEarth/MaskNode.cpp
+++ b/src/osgEarth/MaskNode.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarth/MaskSource b/src/osgEarth/MaskSource
index 1f9fea8..0fa54d4 100644
--- a/src/osgEarth/MaskSource
+++ b/src/osgEarth/MaskSource
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -24,6 +24,7 @@
 #include <osgEarth/Config>
 #include <osgEarth/Revisioning>
 #include <osgEarth/SpatialReference>
+#include <osgEarth/Status>
 #include <osg/Referenced>
 
 namespace osgEarth
@@ -54,6 +55,7 @@ namespace osgEarth
         void fromConfig( const Config& conf );
     };
 
+
     /**
      * MaskSource is a plugin object that generates a masking goemetry
      */
@@ -66,16 +68,41 @@ namespace osgEarth
         virtual ~MaskSource();
 
         /**
+         * Attempt to open the mask source, and return an initial status.
+         */
+        const Status& open(const osgDB::Options* readOptions);
+
+        /**
+         * Status of this source. *
+         */
+        const Status& getStatus() const { return _status; }
+
+        /**
          * Subclass implements this method to create the boundary geometry.
          */
         virtual osg::Vec3dArray* createBoundary(
             const SpatialReference* srs, 
-            ProgressCallback*       progress =0L ) =0;
-
-    public:
-        virtual void initialize(const osgDB::Options* dbOptions) { }
+            ProgressCallback*       progress) =0;
 
+        /**
+         * The initialization options 
+         */
         const MaskSourceOptions& getOptions() const { return _options; }
+
+
+    protected:
+
+        /**
+         * One time initialization of the source. Called by open(), and
+         * returns the initial Status.
+         */
+        virtual Status initialize(const osgDB::Options* dbOptions) =0;
+
+        /**
+         * Subclass can call this to set a status in case something fails
+         */
+        void setStatus(const Status& value) { _status = value; }
+
     public: 
 
         // META_Object specialization:
@@ -87,6 +114,7 @@ namespace osgEarth
 
     private:
         const MaskSourceOptions _options;
+        Status _status;
 
         friend class Map;
         friend class MaskSourceFactory;
@@ -97,7 +125,7 @@ namespace osgEarth
     class OSGEARTH_EXPORT MaskSourceDriver : public osgDB::ReaderWriter
     {
     protected:        
-        const MaskSourceOptions& getMaskSourceOptions( const osgDB::ReaderWriter::Options* rwOpt ) const;
+        const MaskSourceOptions& getMaskSourceOptions(const osgDB::Options* readOptions) const;
         virtual ~MaskSourceDriver();
     };
 
@@ -106,7 +134,7 @@ namespace osgEarth
     class OSGEARTH_EXPORT MaskSourceFactory
     {   
 	public:
-        static MaskSource* create( const MaskSourceOptions& options );
+        static MaskSource* create(const MaskSourceOptions& options);
         virtual ~MaskSourceFactory();
     };
 }
diff --git a/src/osgEarth/MaskSource.cpp b/src/osgEarth/MaskSource.cpp
index 239059d..dfbfaf7 100644
--- a/src/osgEarth/MaskSource.cpp
+++ b/src/osgEarth/MaskSource.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -28,6 +28,7 @@ using namespace OpenThreads;
 
 MaskSourceOptions::~MaskSourceOptions()
 {
+    //nop
 }
 
 void
@@ -55,16 +56,26 @@ MaskSourceOptions::getConfig() const
 MaskSource::MaskSource( const MaskSourceOptions& options ) :
 _options( options )
 {
+    //nop
 }
 
 MaskSource::~MaskSource()
 {
+    //nop
+}
+
+const Status&
+MaskSource::open(const osgDB::Options* readOptions)
+{
+    _status = initialize(readOptions);
+    return _status;
 }
 
 //------------------------------------------------------------------------
 
 MaskSourceDriver::~MaskSourceDriver()
 {
+    //nop
 }
 
 //------------------------------------------------------------------------
@@ -75,6 +86,7 @@ MaskSourceDriver::~MaskSourceDriver()
 
 MaskSourceFactory::~MaskSourceFactory()
 {
+    //nop
 }
 
 MaskSource*
@@ -112,5 +124,7 @@ MaskSourceFactory::create( const MaskSourceOptions& options )
 const MaskSourceOptions&
 MaskSourceDriver::getMaskSourceOptions( const osgDB::ReaderWriter::Options* options ) const
 {
-    return *static_cast<const MaskSourceOptions*>( options->getPluginData( MASK_SOURCE_OPTIONS_TAG ) );
+    static MaskSourceOptions s_default;
+    const void* data = options->getPluginData(MASK_SOURCE_OPTIONS_TAG);
+    return data ? *static_cast<const MaskSourceOptions*>(data) : s_default;
 }
diff --git a/src/osgEarth/MemCache b/src/osgEarth/MemCache
index ff16446..5582fc7 100644
--- a/src/osgEarth/MemCache
+++ b/src/osgEarth/MemCache
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarth/MemCache.cpp b/src/osgEarth/MemCache.cpp
index e930841..ff73a0e 100644
--- a/src/osgEarth/MemCache.cpp
+++ b/src/osgEarth/MemCache.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -41,7 +41,7 @@ namespace
             //nop
         }
 
-        ReadResult readObject(const std::string& key )
+        ReadResult readObject(const std::string& key, const osgDB::Options*)
         {
             MemCacheLRU::Record rec;
             _lru.get(key, rec);
@@ -63,17 +63,17 @@ namespace
             }
         }
 
-        ReadResult readImage(const std::string& key)
+        ReadResult readImage(const std::string& key, const osgDB::Options* readOptions)
         {
-            return readObject( key );
+            return readObject(key, readOptions);
         }
 
-        ReadResult readString(const std::string& key)
+        ReadResult readString(const std::string& key, const osgDB::Options* readOptions)
         {
-            return readObject( key );
+            return readObject(key, readOptions);
         }
 
-        bool write( const std::string& key, const osg::Object* object, const Config& meta )
+        bool write( const std::string& key, const osg::Object* object, const Config& meta, const osgDB::Options* writeOptions)
         {
             if ( object ) 
             {
@@ -109,6 +109,11 @@ namespace
             return true;
         }
 
+        std::string getHashedKey(const std::string& key) const
+        {
+            return key;
+        }
+
         MemCacheLRU _lru;
     };
     
@@ -119,7 +124,10 @@ namespace
 //------------------------------------------------------------------------
 
 MemCache::MemCache( unsigned maxBinSize ) :
-_maxBinSize( std::max(maxBinSize, 1u) )
+_maxBinSize( std::max(maxBinSize, 1u) ),
+_reads(0),
+_writes(0),
+_hits(0)
 {
     //nop
 }
diff --git a/src/osgEarth/Memory b/src/osgEarth/Memory
new file mode 100644
index 0000000..d27d034
--- /dev/null
+++ b/src/osgEarth/Memory
@@ -0,0 +1,52 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+* Copyright 2016 Pelican Mapping
+* http://osgearth.org
+*
+* osgEarth is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* 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.
+*
+* You should have received a copy of the GNU Lesser General Public License
+* along with this program.  If not, see <http://www.gnu.org/licenses/>
+*/
+
+#ifndef OSGEARTH_MEMORY_H
+#define OSGEARTH_MEMORY_H 1
+
+#include <osgEarth/Common>
+
+namespace osgEarth
+{
+    class OSGEARTH_EXPORT Memory
+    {
+    public:
+        /** Physical memory usage, in bytes, for the calling process. (aka working set or resident set) */
+        static unsigned getProcessPhysicalUsage();
+
+        /** Peak physical memory usage, in bytes, for the calling process since it started. */
+        static unsigned getProcessPeakPhysicalUsage();
+
+        /** Private bytes allocated solely to this process */
+        static unsigned getProcessPrivateUsage();
+
+        /** Maximum bytes allocated privately to thie process (peak pagefile usage) */
+        static unsigned getProcessPeakPrivateUsage();
+
+    private:
+        // Not creatable.
+        Memory() { }
+    };
+}
+
+
+#endif // OSGEARTH_MEMORY_H
diff --git a/src/osgEarth/Memory.cpp b/src/osgEarth/Memory.cpp
new file mode 100644
index 0000000..016fab4
--- /dev/null
+++ b/src/osgEarth/Memory.cpp
@@ -0,0 +1,175 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+* Copyright 2016 Pelican Mapping
+* http://osgearth.org
+*
+* osgEarth is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* 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.
+*
+* You should have received a copy of the GNU Lesser General Public License
+* along with this program.  If not, see <http://www.gnu.org/licenses/>
+*/
+#include <osgEarth/Memory>
+
+using namespace osgEarth;
+
+/*
+ * ADAPTED FROM:
+ * http://nadeausoftware.com/articles/2012/07/c_c_tip_how_get_process_resident_set_size_physical_memory_use
+ *
+ * Author:  David Robert Nadeau
+ * Site:    http://NadeauSoftware.com/
+ * License: Creative Commons Attribution 3.0 Unported License
+ *          http://creativecommons.org/licenses/by/3.0/deed.en_US
+ */
+
+#if defined(_WIN32)
+#include <windows.h>
+#include <psapi.h>
+#pragma comment(lib, "psapi.lib")
+
+#elif defined(__unix__) || defined(__unix) || defined(unix) || (defined(__APPLE__) && defined(__MACH__))
+#include <unistd.h>
+#include <sys/resource.h>
+
+#if defined(__APPLE__) && defined(__MACH__)
+#include <mach/mach.h>
+
+#elif (defined(_AIX) || defined(__TOS__AIX__)) || (defined(__sun__) || defined(__sun) || defined(sun) && (defined(__SVR4) || defined(__svr4__)))
+#include <fcntl.h>
+#include <procfs.h>
+
+#elif defined(__linux__) || defined(__linux) || defined(linux) || defined(__gnu_linux__)
+#include <stdio.h>
+
+#endif
+
+#else
+//#error "Cannot define getPeakRSS( ) or getCurrentRSS( ) for an unknown OS."
+#endif
+
+
+/**
+ * Returns the peak (maximum so far) resident set size (physical
+ * memory use) measured in bytes, or zero if the value cannot be
+ * determined on this OS.
+ */
+unsigned
+Memory::getProcessPeakPhysicalUsage()
+{
+#if defined(_WIN32)
+    /* Windows -------------------------------------------------- */
+    PROCESS_MEMORY_COUNTERS info;
+    GetProcessMemoryInfo( GetCurrentProcess( ), &info, sizeof(info) );
+    return (size_t)info.PeakWorkingSetSize;
+
+#elif (defined(_AIX) || defined(__TOS__AIX__)) || (defined(__sun__) || defined(__sun) || defined(sun) && (defined(__SVR4) || defined(__svr4__)))
+    /* AIX and Solaris ------------------------------------------ */
+    struct psinfo psinfo;
+    int fd = -1;
+    if ( (fd = open( "/proc/self/psinfo", O_RDONLY )) == -1 )
+        return (size_t)0L;      /* Can't open? */
+    if ( read( fd, &psinfo, sizeof(psinfo) ) != sizeof(psinfo) )
+    {
+        close( fd );
+        return (size_t)0L;      /* Can't read? */
+    }
+    close( fd );
+    return (size_t)(psinfo.pr_rssize * 1024L);
+
+#elif defined(__unix__) || defined(__unix) || defined(unix) || (defined(__APPLE__) && defined(__MACH__))
+    /* BSD, Linux, and OSX -------------------------------------- */
+    struct rusage rusage;
+    getrusage( RUSAGE_SELF, &rusage );
+#if defined(__APPLE__) && defined(__MACH__)
+    return (size_t)rusage.ru_maxrss;
+#else
+    return (size_t)(rusage.ru_maxrss * 1024L);
+#endif
+
+#else
+    /* Unknown OS ----------------------------------------------- */
+    return (size_t)0L;          /* Unsupported. */
+#endif
+}
+
+
+
+/**
+ * Returns the current resident set size (physical memory use) measured
+ * in bytes, or zero if the value cannot be determined on this OS.
+ */
+unsigned
+Memory::getProcessPhysicalUsage()
+{
+#if defined(_WIN32)
+    /* Windows -------------------------------------------------- */
+    PROCESS_MEMORY_COUNTERS_EX info;
+    GetProcessMemoryInfo( GetCurrentProcess( ), (PROCESS_MEMORY_COUNTERS*)&info, sizeof(info) );
+    return (size_t)info.WorkingSetSize;
+
+#elif defined(__APPLE__) && defined(__MACH__)
+    /* OSX ------------------------------------------------------ */
+    struct mach_task_basic_info info;
+    mach_msg_type_number_t infoCount = MACH_TASK_BASIC_INFO_COUNT;
+    if ( task_info( mach_task_self( ), MACH_TASK_BASIC_INFO,
+        (task_info_t)&info, &infoCount ) != KERN_SUCCESS )
+        return (size_t)0L;      /* Can't access? */
+    return (size_t)info.resident_size;
+
+#elif defined(__linux__) || defined(__linux) || defined(linux) || defined(__gnu_linux__)
+    /* Linux ---------------------------------------------------- */
+    long rss = 0L;
+    FILE* fp = NULL;
+    if ( (fp = fopen( "/proc/self/statm", "r" )) == NULL )
+        return (size_t)0L;      /* Can't open? */
+    if ( fscanf( fp, "%*s%ld", &rss ) != 1 )
+    {
+        fclose( fp );
+        return (size_t)0L;      /* Can't read? */
+    }
+    fclose( fp );
+    return (unsigned) ((size_t)rss * (size_t)sysconf( _SC_PAGESIZE));
+
+#else
+    /* AIX, BSD, Solaris, and Unknown OS ------------------------ */
+    return (size_t)0L;          /* Unsupported. */
+#endif
+}
+
+unsigned
+Memory::getProcessPrivateUsage()
+{
+#if defined(_WIN32)
+    /* Windows -------------------------------------------------- */
+    PROCESS_MEMORY_COUNTERS_EX info;
+    GetProcessMemoryInfo( GetCurrentProcess( ), (PROCESS_MEMORY_COUNTERS*)&info, sizeof(info) );
+    return (size_t)info.PrivateUsage;
+#else
+    return (size_t)0L;
+#endif
+}
+
+
+unsigned
+Memory::getProcessPeakPrivateUsage()
+{
+#if defined(_WIN32)
+    /* Windows -------------------------------------------------- */
+    PROCESS_MEMORY_COUNTERS_EX info;
+    GetProcessMemoryInfo( GetCurrentProcess( ), (PROCESS_MEMORY_COUNTERS*)&info, sizeof(info) );
+    return (size_t)info.PeakPagefileUsage;
+#else
+    return (size_t)0L;
+#endif
+}
diff --git a/src/osgEarth/MimeTypes.cpp b/src/osgEarth/MimeTypes.cpp
index c1312b7..8e66a4d 100644
--- a/src/osgEarth/MimeTypes.cpp
+++ b/src/osgEarth/MimeTypes.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarth/ModelLayer b/src/osgEarth/ModelLayer
index e716a04..f9369dc 100644
--- a/src/osgEarth/ModelLayer
+++ b/src/osgEarth/ModelLayer
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -23,7 +23,7 @@
 #include <osgEarth/Common>
 #include <osgEarth/AlphaEffect>
 #include <osgEarth/Layer>
-#include <osgEarth/CachePolicy>
+#include <osgEarth/Cache>
 #include <osgEarth/Config>
 #include <osgEarth/ModelSource>
 #include <osgEarth/MaskSource>
@@ -52,9 +52,15 @@ namespace osgEarth
             const std::string&        name, 
             const ModelSourceOptions& driverOptions =ModelSourceOptions() );
 
+        /** Copy ctor*/
+        ModelLayerOptions(const ModelLayerOptions& rhs);
+
         /** dtor */
         virtual ~ModelLayerOptions() { }
 
+        /** Assignment operator */
+        ModelLayerOptions& operator = (const ModelLayerOptions&);
+
         /**
          * The readable name of the layer.
          */
@@ -118,6 +124,12 @@ namespace osgEarth
         optional<CachePolicy>& cachePolicy() { return _cachePolicy; }
         const optional<CachePolicy>& cachePolicy() const { return _cachePolicy; }
 
+        /**
+         * Express cacheid (overrides an automatically generated cache id)
+         */
+        optional<std::string>& cacheId() { return _cacheId; }
+        const optional<std::string>& cacheId() const { return _cacheId; }
+
 
     public:
         virtual Config getConfig() const;
@@ -137,6 +149,7 @@ namespace osgEarth
         optional<unsigned>           _maskMinLevel;
         optional<bool>               _terrainPatch;
         optional<CachePolicy>        _cachePolicy;
+        optional<std::string>        _cacheId;
     };
 
     /**
@@ -184,7 +197,7 @@ namespace osgEarth
         /** 
          * Gets the name of this model layer
          */
-        const std::string& getName() const { return *_runtimeOptions.name(); }
+        const std::string& getName() const { return _runtimeOptions.name().get(); }
 
         /**
          * Gets the initialization options for this layer.
@@ -224,9 +237,20 @@ namespace osgEarth
     public:
 
         /**
-         * Perform one-time initialize of the model layer.
+         * Sets the read options for this layer to user; this includes
+         * Cache and CachePolicy information potentially.
          */
-        void initialize( const osgDB::Options* options );
+        void setReadOptions(const osgDB::Options* readOptions);
+
+        /**
+         * Perform one-time initialization of the model layer.
+         */
+        const Status& open();
+
+        /**
+         * Status of this layer.
+         */
+        const Status& getStatus() const { return _status; }
 
         /**
          * Creates the scene graph representing this model layer for the given Map,
@@ -238,19 +262,13 @@ namespace osgEarth
          * Gets a scene graph what was previously created with getOrCreateSceneGraph.
          */
         osg::Node* getSceneGraph(const UID& mapUID) const;
-        
-        /**
-         * This layer's caching policy
-         */
-        void setCachePolicy(const CachePolicy& cachePolicy);
-        const CachePolicy& getCachePolicy() const;
 
     public: // deprecated
         
         /** @deprecated */
         osg::Node* getOrCreateSceneGraph( 
             const Map*            map, 
-            const osgDB::Options* dbOptions,
+            const osgDB::Options* readOptions,
             ProgressCallback*     progress ) { return getOrCreateSceneGraph(map, progress); }
 
     public: // properties
@@ -281,6 +299,13 @@ namespace osgEarth
         /** Removes a property notification callback from this layer */
         void removeCallback( ModelLayerCallback* cb );
 
+    protected:
+
+        /**
+         * Set the status in case something fails
+         */
+        void setStatus(const Status& value) { _status = value; }
+
     private:
         osg::ref_ptr<ModelSource>     _modelSource;
         osg::ref_ptr<MaskSource>      _maskSource;
@@ -290,7 +315,9 @@ namespace osgEarth
         ModelLayerCallbackList        _callbacks;
         osg::ref_ptr<AlphaEffect>     _alphaEffect;
         osg::ref_ptr<osg::Vec3dArray> _maskBoundary;
-        osg::ref_ptr<osgDB::Options>  _dbOptions;
+        osg::ref_ptr<osgDB::Options>  _readOptions;
+        osg::ref_ptr<CacheSettings>   _cacheSettings;
+        Status                        _status;
 
         typedef fast_map<UID, osg::observer_ptr<osg::Node> > Graphs;
         Graphs _graphs;
@@ -302,8 +329,6 @@ namespace osgEarth
         void copyOptions();
 
         void setLightingEnabledNoLock(bool value);
-        
-        void initializeCachePolicy(const osgDB::Options* options);
     };
 
     typedef std::vector< osg::ref_ptr<ModelLayer> > ModelLayerVector;
diff --git a/src/osgEarth/ModelLayer.cpp b/src/osgEarth/ModelLayer.cpp
index 956cd54..2984a81 100644
--- a/src/osgEarth/ModelLayer.cpp
+++ b/src/osgEarth/ModelLayer.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -38,6 +38,10 @@ namespace
     {
         NodeModelSource( osg::Node* node ) : _node(node) { }
 
+        Status initialize(const osgDB::Options* readOptions) {
+            return Status::OK();
+        }
+
         osg::Node* createNodeImplementation(const Map* map, ProgressCallback* progress) {
             return _node.get();
         }
@@ -64,6 +68,41 @@ ConfigOptions()
     _driver = driverOptions;
 }
 
+ModelLayerOptions::ModelLayerOptions(const ModelLayerOptions& rhs) :
+ConfigOptions(rhs.getConfig())
+{
+    _name = optional<std::string>(rhs._name);
+    _driver = optional<ModelSourceOptions>(rhs._driver);
+    _enabled = optional<bool>(rhs._enabled);
+    _visible = optional<bool>(rhs._visible);
+    _opacity = optional<float>(rhs._opacity);
+    _lighting = optional<bool>(rhs._lighting);
+    _maskOptions = optional<MaskSourceOptions>(rhs._maskOptions);
+    _maskMinLevel = optional<unsigned>(rhs._maskMinLevel);
+    _terrainPatch = optional<bool>(rhs._terrainPatch);
+    _cachePolicy = optional<CachePolicy>(rhs._cachePolicy);
+    _cacheId = optional<std::string>(rhs._cacheId);
+}
+
+ModelLayerOptions& ModelLayerOptions::operator =(const ModelLayerOptions& rhs)
+{
+    ConfigOptions::operator =(rhs);
+
+    _name = optional<std::string>(rhs._name);
+    _driver = optional<ModelSourceOptions>(rhs._driver);
+    _enabled = optional<bool>(rhs._enabled);
+    _visible = optional<bool>(rhs._visible);
+    _opacity = optional<float>(rhs._opacity);
+    _lighting = optional<bool>(rhs._lighting);
+    _maskOptions = optional<MaskSourceOptions>(rhs._maskOptions);
+    _maskMinLevel = optional<unsigned>(rhs._maskMinLevel);
+    _terrainPatch = optional<bool>(rhs._terrainPatch);
+    _cachePolicy = optional<CachePolicy>(rhs._cachePolicy);
+    _cacheId = optional<std::string>(rhs._cacheId);
+
+    return *this;
+}
+
 void
 ModelLayerOptions::setDefaults()
 {
@@ -73,7 +112,9 @@ ModelLayerOptions::setDefaults()
     _opacity.init     ( 1.0f );
     _maskMinLevel.init( 0 );
     _terrainPatch.init( false );
-    _cachePolicy.init ( CachePolicy() );
+
+    // Expressly set it here since we want no caching by default on a model layer.
+    _cachePolicy = CachePolicy::NO_CACHE;
 }
 
 Config
@@ -90,6 +131,7 @@ ModelLayerOptions::getConfig() const
     conf.updateIfSet( "patch",          _terrainPatch );  
 
     conf.updateObjIfSet( "cache_policy", _cachePolicy );  
+    conf.updateIfSet("cacheid", _cacheId);
 
     // Merge the ModelSource options
     if ( driver().isSet() )
@@ -114,6 +156,7 @@ ModelLayerOptions::fromConfig( const Config& conf )
     conf.getIfSet( "patch",          _terrainPatch );
 
     conf.getObjIfSet( "cache_policy", _cachePolicy );  
+    conf.getIfSet("cacheid", _cacheId);
 
     if ( conf.hasValue("driver") )
         driver() = ModelSourceOptions(conf);
@@ -171,73 +214,102 @@ ModelLayer::copyOptions()
     _alphaEffect->setAlpha( *_initOptions.opacity() );
 }
 
-void
-ModelLayer::initialize(const osgDB::Options* dbOptions)
+const Status&
+ModelLayer::open()
 {
     if ( !_modelSource.valid() && _initOptions.driver().isSet() )
     {
-        OE_INFO << LC << "Initializing model layer \"" << getName() << "\", driver=\"" << _initOptions.driver()->getDriver() << "\"" << std::endl;
-        
-        // set up the db options and caching policy first
-        _dbOptions = Registry::instance()->cloneOrCreateOptions(dbOptions);
-        initializeCachePolicy( _dbOptions.get() );
+        std::string driverName = _initOptions.driver()->getDriver();
 
-        // the model source:
+        OE_INFO << LC << "Opening model layer \"" << getName() << "\", driver=\"" << driverName << "\"" << std::endl;
+        
+        // Try to create the model source:
         _modelSource = ModelSourceFactory::create( *_initOptions.driver() );
         if ( _modelSource.valid() )
         {
             _modelSource->setName( this->getName() );
 
-            _modelSource->initialize( _dbOptions.get() );
-
-            // the mask, if there is one:
-            if ( !_maskSource.valid() && _initOptions.maskOptions().isSet() )
+            const Status& modelStatus = _modelSource->open( _readOptions.get() );
+            if (modelStatus.isOK())
             {
-                OE_INFO << LC << "...initializing mask, driver=\"" << _initOptions.maskOptions()->getDriver() << std::endl;
-
-                _maskSource = MaskSourceFactory::create( *_initOptions.maskOptions() );
-                if ( _maskSource.valid() )
+                // the mask, if there is one:
+                if ( !_maskSource.valid() && _initOptions.maskOptions().isSet() )
                 {
-                    _maskSource->initialize( _dbOptions.get() );
-                }
-                else
-                {
-                    OE_INFO << LC << "...mask init failed!" << std::endl;
+                    OE_INFO << LC << "...initializing mask, driver=" << driverName << std::endl;
+
+                    _maskSource = MaskSourceFactory::create( *_initOptions.maskOptions() );
+                    if ( _maskSource.valid() )
+                    {
+                        const Status& maskStatus = _maskSource->open(_readOptions.get());
+                        if (maskStatus.isError())
+                        {
+                            _status = maskStatus;
+                        }
+                    }
+                    else
+                    {
+                        _status = Status::Error(Status::ServiceUnavailable, Stringify() << "Cannot find mask driver \"" << _initOptions.maskOptions()->getDriver() << "\"");
+                    }
                 }
             }
+            else
+            {
+                // propagate the model source's error status
+                _status = modelStatus;
+            }
+        }
+        else
+        {
+            _status = Status::Error(Status::ServiceUnavailable, Stringify() << "Failed to create driver \"" << driverName << "\"");
         }
     }
+
+    return _status;
 }
 
 void
-ModelLayer::initializeCachePolicy(const osgDB::Options* options)
+ModelLayer::setReadOptions(const osgDB::Options* readOptions)
 {
-    // Start with the cache policy passed in by the Map.
-    optional<CachePolicy> cp;
-    CachePolicy::fromOptions(options, cp);
+    _readOptions = Registry::cloneOrCreateOptions(readOptions);
 
-    // if this layer specifies cache policy info, that will override 
-    // whatever the map passed in:
-    if ( _initOptions.cachePolicy().isSet() )
-        cp->mergeAndOverride( _initOptions.cachePolicy() );
+    // Create some local cache settings for this layer:
+    CacheSettings* oldSettings = CacheSettings::get(readOptions);
+    _cacheSettings = oldSettings ? new CacheSettings(*oldSettings) : new CacheSettings();
 
-    // finally resolve with global overrides:
-    Registry::instance()->resolveCachePolicy( cp );
+    // bring in the new policy for this layer if there is one:
+    _cacheSettings->integrateCachePolicy(_initOptions.cachePolicy());
 
-    setCachePolicy( cp.get() );
-}
+    // if caching is a go, install a bin.
+    if (_cacheSettings->isCacheEnabled())
+    {
+        std::string binID;
+        if (_initOptions.cacheId().isSet() && !_initOptions.cacheId()->empty())
+        {
+            binID = _initOptions.cacheId().get();
+        }
+        else
+        {
+            Config conf = _initOptions.driver()->getConfig();
+            binID = hashToString(conf.toJSON(false));
+        }
 
-void
-ModelLayer::setCachePolicy( const CachePolicy& cp )
-{
-    _runtimeOptions.cachePolicy() = cp;
-    _runtimeOptions.cachePolicy()->apply( _dbOptions.get() );
-}
+        // make our cacheing bin!
+        CacheBin* bin = _cacheSettings->getCache()->addBin(binID);
+        if (bin)
+        {
+            OE_INFO << LC << "Layer \"" << getName() << "\" cache bin is [" << binID << "]\n";
+            _cacheSettings->setCacheBin( bin );
+        }
+        else
+        {
+            // failed to create the bin, so fall back on no cache mode.
+            OE_WARN << LC << "Layer " << getName() << " failed to open a cache bin [" << binID << "], disabling caching\n";
+            _cacheSettings->cachePolicy() = CachePolicy::NO_CACHE;
+        }
+    }
 
-const CachePolicy&
-ModelLayer::getCachePolicy() const
-{
-    return _runtimeOptions.cachePolicy().value();
+    // Store it for further propagation!
+    _cacheSettings->store(_readOptions.get());
 }
 
 osg::Node*
@@ -252,6 +324,9 @@ osg::Node*
 ModelLayer::getOrCreateSceneGraph(const Map*        map,
                                   ProgressCallback* progress )
 {
+    if (getStatus().isError())
+        return 0L;
+
     // exclusive lock for cache lookup/update.
     Threading::ScopedMutexLock lock( _mutex );
 
@@ -424,7 +499,7 @@ ModelLayer::getOrCreateMaskBoundary(float                   heightScale,
                                     const SpatialReference* srs, 
                                     ProgressCallback*       progress )
 {
-    if ( _maskSource.valid() && !_maskBoundary.valid() )
+    if (_maskSource.valid() && !_maskBoundary.valid() && getStatus().isOK())
     {
         Threading::ScopedMutexLock excl(_mutex);
 
@@ -432,12 +507,18 @@ ModelLayer::getOrCreateMaskBoundary(float                   heightScale,
         {
             // make the geometry:
             _maskBoundary = _maskSource->createBoundary( srs, progress );
-
-            // scale to the height scale factor:
-            for (osg::Vec3dArray::iterator vIt = _maskBoundary->begin(); vIt != _maskBoundary->end(); ++vIt)
-                vIt->z() = vIt->z() * heightScale;
+            if (_maskBoundary.valid())
+            {
+                // scale to the height scale factor:
+                for (osg::Vec3dArray::iterator vIt = _maskBoundary->begin(); vIt != _maskBoundary->end(); ++vIt)
+                    vIt->z() = vIt->z() * heightScale;
+            }
+            else
+            {
+                setStatus(Status::Error("Failed to create masking boundary"));
+            }
         }
     }
 
     return _maskBoundary.get();
-}
\ No newline at end of file
+}
diff --git a/src/osgEarth/ModelSource b/src/osgEarth/ModelSource
index e8c54f9..2ef4f3e 100644
--- a/src/osgEarth/ModelSource
+++ b/src/osgEarth/ModelSource
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -26,6 +26,7 @@
 #include <osgEarth/NodeUtils>
 #include <osgEarth/Revisioning>
 #include <osgEarth/ThreadingUtils>
+#include <osgEarth/Status>
 #include <osg/Referenced>
 
 namespace osgEarth
@@ -58,6 +59,9 @@ namespace osgEarth
         optional<int>& renderOrder() { return _renderOrder; }
         const optional<int>& renderOrder() const { return _renderOrder; }
 
+        optional<std::string>& renderBin() { return _renderBin; }
+        const optional<std::string>& renderBin() const { return _renderBin; }
+
         /** whether to read the depth buffer when rendering */
         optional<bool>& depthTestEnabled() { return _depthTestEnabled; }
         const optional<bool>& depthTestEnabled() const { return _depthTestEnabled; }
@@ -73,6 +77,7 @@ namespace osgEarth
 
         optional<float> _minRange, _maxRange;
         optional<int> _renderOrder;
+        optional<std::string> _renderBin;
         optional<bool> _depthTestEnabled;
         optional<bool> _overlay;
     };
@@ -89,17 +94,22 @@ namespace osgEarth
         /** dtor */
         virtual ~ModelSource();
 
-        osg::Node* createNode(
-            const Map*        map,
-            ProgressCallback* progress );
+        /**
+         * Opens the model source and returns a status. 
+         */
+        const Status& open(const osgDB::Options* readOptions);
 
         /**
-         * Subclass implements this method to create a scene graph within the
-         * context of the provided Map.
+         * Status after calling open.
          */
-        virtual osg::Node* createNodeImplementation(
+        const Status& getStatus() const { return _status; }
+
+        /**
+         * Creates the top level node for this model source.
+         */
+        osg::Node* createNode(
             const Map*        map,
-            ProgressCallback* progress ) =0;
+            ProgressCallback* progress );
 
         /**
          * Add a post processing operation that will run (possibly in a pager
@@ -140,9 +150,6 @@ namespace osgEarth
 
     public:
 
-        /** Perform any one-time initialization */
-        virtual void initialize( const osgDB::Options* dbOptions ) { }
-
         /** Get the options used to create this model source */
         const ModelSourceOptions& getOptions() const { return _options; }
 
@@ -153,6 +160,21 @@ namespace osgEarth
         DataExtentList& getDataExtents() { return _dataExtents; }
 
     protected:
+
+        /**
+         * Perform one-time initialization and return the initial status.
+         * This is called internally by open().
+         */
+        virtual Status initialize(const osgDB::Options* readOptions) =0;
+
+        /**
+         * Subclass implements this method to create a scene graph within the
+         * context of the provided Map.
+         */
+        virtual osg::Node* createNodeImplementation(
+            const Map*        map,
+            ProgressCallback* progress ) =0;
+
         /**
          * Fire the callbacks. The implementation class should call this whenever it adds
          * a new node.
@@ -163,6 +185,9 @@ namespace osgEarth
 
         osg::ref_ptr<RefNodeOperationVector> _postMergeOps;
         osg::ref_ptr<RefNodeOperationVector> _preMergeOps;
+        
+        /** Subclass can set the status with this */
+        void setStatus(const Status& value) { _status = value; }
 
     private:
         const ModelSourceOptions _options;
@@ -170,6 +195,7 @@ namespace osgEarth
         optional<double> _maxRange;
         optional<int>    _renderOrder;
         DataExtentList   _dataExtents;
+        Status _status;
 
         friend class Map;
         friend class MapEngine;
diff --git a/src/osgEarth/ModelSource.cpp b/src/osgEarth/ModelSource.cpp
index 9eb16ac..3aa4e2c 100644
--- a/src/osgEarth/ModelSource.cpp
+++ b/src/osgEarth/ModelSource.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -33,6 +33,7 @@ DriverConfigOptions( options ),
 _minRange          ( 0.0f ),
 _maxRange          ( FLT_MAX ),
 _renderOrder       ( 11 ),
+_renderBin         ( "DepthSortedBin" ),
 _depthTestEnabled  ( true )
 { 
     fromConfig(_conf);
@@ -40,6 +41,7 @@ _depthTestEnabled  ( true )
 
 ModelSourceOptions::~ModelSourceOptions()
 {
+    //nop
 }
 
 void
@@ -48,6 +50,7 @@ ModelSourceOptions::fromConfig( const Config& conf )
     conf.getIfSet<float>( "min_range", _minRange );
     conf.getIfSet<float>( "max_range", _maxRange );
     conf.getIfSet<int>( "render_order", _renderOrder );
+    conf.getIfSet("render_bin", _renderBin );
     conf.getIfSet<bool>( "depth_test_enabled", _depthTestEnabled );
 }
 
@@ -65,6 +68,7 @@ ModelSourceOptions::getConfig() const
     conf.updateIfSet( "min_range", _minRange );
     conf.updateIfSet( "max_range", _maxRange );
     conf.updateIfSet( "render_order", _renderOrder );
+    conf.updateIfSet( "render_bin", _renderBin );
     conf.updateIfSet( "depth_test_enabled", _depthTestEnabled );
     return conf;
 }
@@ -83,11 +87,22 @@ ModelSource::~ModelSource()
    //nop
 }
 
+const Status&
+ModelSource::open(const osgDB::Options* readOptions)
+{
+    _status = initialize(readOptions);
+    return _status;
+}
 
 osg::Node* 
 ModelSource::createNode(const Map*        map,
                         ProgressCallback* progress )
 {
+    if (getStatus().isError())
+    {
+        return 0L;
+    }
+
     osg::Node* node = createNodeImplementation(map, progress);
     if ( node )
     {
@@ -180,6 +195,7 @@ ModelSource::firePostProcessors( osg::Node* node )
 
 ModelSourceFactory::~ModelSourceFactory()
 {
+    //nop
 }
 
 ModelSource*
@@ -195,10 +211,10 @@ ModelSourceFactory::create( const ModelSourceOptions& options )
         rwopts->setPluginData( MODEL_SOURCE_OPTIONS_TAG, (void*)&options );
 
         modelSource = dynamic_cast<ModelSource*>( osgDB::readObjectFile( driverExt, rwopts.get() ) );
-        if ( !modelSource )
-        {
-            OE_WARN << "FAILED to load model source driver \"" << options.getDriver() << "\"" << std::endl;
-        }
+        //if ( !modelSource )
+        //{
+        //    OE_WARN << "FAILED to load model source driver \"" << options.getDriver() << "\"" << std::endl;
+        //}
     }
     else
     {
@@ -213,7 +229,9 @@ ModelSourceFactory::create( const ModelSourceOptions& options )
 const ModelSourceOptions&
 ModelSourceDriver::getModelSourceOptions( const osgDB::ReaderWriter::Options* options ) const
 {
-    return *static_cast<const ModelSourceOptions*>( options->getPluginData( MODEL_SOURCE_OPTIONS_TAG ) );
+    static ModelSourceOptions s_default;
+    const void* data = options->getPluginData(MODEL_SOURCE_OPTIONS_TAG);
+    return data ? *static_cast<const ModelSourceOptions*>(data) : s_default;
 }
 
 ModelSourceDriver::~ModelSourceDriver()
diff --git a/src/osgEarth/NativeProgramAdapter b/src/osgEarth/NativeProgramAdapter
index 9478884..e4dcdb3 100644
--- a/src/osgEarth/NativeProgramAdapter
+++ b/src/osgEarth/NativeProgramAdapter
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarth/NodeUtils b/src/osgEarth/NodeUtils
index acf4c92..ca6de4e 100644
--- a/src/osgEarth/NodeUtils
+++ b/src/osgEarth/NodeUtils
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
@@ -236,6 +236,12 @@ namespace osgEarth
         return result;
     }
 
+    /** Find the top of the scene graph through parent 0 */
+    inline osg::Node* findTopOfGraph(osg::Node* node)
+    {
+        return node && node->getNumParents() > 0 ? findTopOfGraph(node->getParent(0)) : node;
+    }
+
     /**
      * Replace one group with another
      */
@@ -270,6 +276,25 @@ namespace osgEarth
         }
     }
 
+    /** Insert a group above a node. */
+    inline void insertParent(osg::Group* newParent, osg::Node* existingChild)
+    {
+        if ( newParent && existingChild )
+        {
+            newParent->addChild(existingChild);
+
+            for (unsigned i = 0; i < existingChild->getNumParents(); ++i)
+            {
+                osg::Group* parent = existingChild->getParent(i);
+                if ( parent != newParent )
+                {
+                    parent->removeChild( existingChild );
+                    parent->addChild( newParent );
+                }
+            }
+        }
+    }
+
     /**
      * Remove all a group's children.
      */
diff --git a/src/osgEarth/NodeUtils.cpp b/src/osgEarth/NodeUtils.cpp
index a3c147e..4fa0378 100644
--- a/src/osgEarth/NodeUtils.cpp
+++ b/src/osgEarth/NodeUtils.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarth/Notify b/src/osgEarth/Notify
index d589f5c..9b2492c 100644
--- a/src/osgEarth/Notify
+++ b/src/osgEarth/Notify
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -55,7 +55,8 @@ namespace osgEarth
 #define OE_DEBUG OE_NOTIFY(osg::DEBUG_INFO,"[osgEarth]  ")
 #define OE_NULL if(false) osgEarth::notify(osg::ALWAYS)
 
-#define OE_START_TIMER(VAR) osg::Timer_t VAR##_timer = osg::Timer::instance()->tick()
-#define OE_STOP_TIMER(VAR) osg::Timer::instance()->delta_s( VAR##_timer, osg::Timer::instance()->tick() )
+#define OE_START_TIMER(VAR) osg::Timer_t VAR##_oe_timer = osg::Timer::instance()->tick()
+#define OE_STOP_TIMER(VAR) osg::Timer::instance()->delta_s( VAR##_oe_timer, osg::Timer::instance()->tick() )
+#define OE_GET_TIMER(VAR) osg::Timer::instance()->delta_s( VAR##_oe_timer, osg::Timer::instance()->tick() )
 
 #endif // OSGEARTH_NOTIFY_H
diff --git a/src/osgEarth/Notify.cpp b/src/osgEarth/Notify.cpp
index 1f4c6ab..4128453 100644
--- a/src/osgEarth/Notify.cpp
+++ b/src/osgEarth/Notify.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -121,14 +121,17 @@ class NullStreamBuffer : public std::streambuf
 
 struct NullStream : public std::ostream
 {
-    NullStream():
-        std::ostream(new NullStreamBuffer) {}
+    NullStream() :
+         std::ostream(_nsb = new NullStreamBuffer) {}
         
     virtual ~NullStream()
     {
         delete rdbuf();
         rdbuf(0);
+        //delete _nsb;
     }
+
+    NullStreamBuffer* _nsb;
 };
 
 std::ostream&
diff --git a/src/osgEarth/ObjectIndex b/src/osgEarth/ObjectIndex
index 8db7011..a75056d 100644
--- a/src/osgEarth/ObjectIndex
+++ b/src/osgEarth/ObjectIndex
@@ -36,14 +36,13 @@
 
 namespace osgEarth
 {
-
-#if OSG_VERSION_GREATER_OR_EQUAL(3,1,8)
+//#if OSG_VERSION_GREATER_OR_EQUAL(3,1,8)
     typedef unsigned       ObjectID;
     typedef osg::UIntArray ObjectIDArray;
-#else
-    typedef int            ObjectID;
-    typedef osg::IntArray  ObjectIDArray;
-#endif
+//#else
+//    typedef int            ObjectID;
+//    typedef osg::IntArray  ObjectIDArray;
+//#endif
 
     /** 
      * Virutal interface class for building an object index.
@@ -148,6 +147,16 @@ namespace osgEarth
          */
         const ShaderPackage& getShaderPackage() const { return _shaders; }
 
+        /**
+         * Returns a set of ObjectIDs used in a drawable. Returns false is none are found
+         */
+        bool getObjectIDs(const osg::Drawable* drawable, std::set<ObjectID>& output) const;
+
+        /**
+         * Returns an ObjectID set on a node. Returns false if none is found
+         */
+        bool getObjectID(osg::Node* node, ObjectID& output) const;
+
 
     public: // ObjectIndexBuilder<osg::Referenced>
 
@@ -189,6 +198,18 @@ namespace osgEarth
          */
         void tagNode(osg::Node* node, ObjectID id) const;
 
+        /**
+         * For each ObjectID found in a drawable, update it with a new Object ID and
+         * populate an output table that maps the old ID to the new ID. Internal function
+         * used for serialization support.
+         */
+        bool updateObjectIDs(osg::Drawable* drawable, std::map<ObjectID, ObjectID>& oldNewTable, osg::Referenced* obj);
+
+        /**
+         * On a node, replace an existing objectID with a new one and return the mapping.
+         * Internal function used for serialization support.
+         */
+        bool updateObjectID(osg::Node* node, std::map<ObjectID, ObjectID>& oldNewTable, osg::Referenced* obj);
 
     protected:
         virtual ~ObjectIndex() { }
diff --git a/src/osgEarth/ObjectIndex.cpp b/src/osgEarth/ObjectIndex.cpp
index 85a46fa..b8c8b76 100644
--- a/src/osgEarth/ObjectIndex.cpp
+++ b/src/osgEarth/ObjectIndex.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
@@ -40,17 +40,17 @@ using namespace osgEarth;
 namespace
 {
     const char* indexVertexInit =
-        "#version 330\n"
+        "#version " GLSL_VERSION_STR "\n"
 
-        "#pragma vp_entryPoint \"oe_index_setObjectID\" \n"
-        "#pragma vp_location   \"vertex_model\" \n"
-        "#pragma vp_order      \"first\" \n"
+        "#pragma vp_entryPoint oe_index_readObjectID \n"
+        "#pragma vp_location   vertex_model \n"
+        "#pragma vp_order      first \n"
 
         "uniform uint oe_index_objectid_uniform; \n"   // override objectid if > 0
         "in uint      oe_index_objectid_attr; \n"      // Vertex attribute containing the object ID.
         "uint         oe_index_objectid; \n"           // Stage global containing the Object ID.
 
-        "void oe_index_setObjectID(inout vec4 vertex) \n"
+        "void oe_index_readObjectID(inout vec4 vertex) \n"
         "{ \n"
         "    if ( oe_index_objectid_uniform > 0u ) \n"
         "        oe_index_objectid = oe_index_objectid_uniform; \n"
@@ -232,3 +232,101 @@ ObjectIndex::tagNode(osg::Node* node, ObjectID id) const
         stateSet->addUniform( new osg::Uniform(_oidUniformName.c_str(), id) );
     }
 }
+
+bool
+ObjectIndex::getObjectIDs(const osg::Drawable* drawable, std::set<ObjectID>& output) const
+{
+    if (!drawable) return false;
+    
+    const osg::Geometry* geometry = drawable->asGeometry();
+    if (!geometry) return false;
+
+    const ObjectIDArray* oids = dynamic_cast<const ObjectIDArray*>(geometry->getVertexAttribArray(_attribLocation));
+    if ( !oids ) return false;
+    if (oids->empty()) return false;
+
+    for (ObjectIDArray::const_iterator i = oids->begin(); i != oids->end(); ++i)
+        output.insert( *i );
+
+    return true;
+}
+
+bool
+ObjectIndex::getObjectID(osg::Node* node, ObjectID& output) const
+{
+    if (!node) return false;
+
+    osg::StateSet* stateSet = node->getStateSet();
+    if (!stateSet) return false;
+
+    osg::Uniform* uniform = stateSet->getUniform(_oidUniformName.c_str());
+    if ( !uniform ) return false;
+
+    uniform->get(output);
+    return true;
+}
+
+bool
+ObjectIndex::updateObjectIDs(osg::Drawable* drawable,
+                             std::map<ObjectID, ObjectID>& oldNewMap,
+                             osg::Referenced* object)
+{
+    // in a drawable, replaces each OIDs in map.first with the corresponding OID in map.second
+    if (!drawable) return false;
+
+    osg::Geometry* geometry = drawable->asGeometry();
+    if (!geometry) return false;
+
+    ObjectIDArray* oids = dynamic_cast<ObjectIDArray*>(geometry->getVertexAttribArray(_attribLocation));
+    if ( !oids ) return false;
+    if (oids->empty()) return false;
+    
+    for (ObjectIDArray::iterator i = oids->begin(); i != oids->end(); ++i)
+    {
+        ObjectID newoid;
+        std::map<ObjectID, ObjectID>::iterator k = oldNewMap.find(*i);
+        if (k != oldNewMap.end()) {
+            newoid = k->second;
+        }
+        else {
+            newoid = insert(object);
+            oldNewMap[*i] = newoid;
+        }
+        *i = newoid;
+    }
+
+    oids->dirty();
+
+    return true;
+}
+
+bool
+ObjectIndex::updateObjectID(osg::Node* node,
+                            std::map<ObjectID, ObjectID>& oldNewMap,
+                            osg::Referenced* object)
+{
+    if (!node) return false;
+
+    osg::StateSet* stateSet = node->getStateSet();
+    if (!stateSet) return false;
+
+    osg::Uniform* uniform = stateSet->getUniform(_oidUniformName.c_str());
+    if ( !uniform ) return false;
+
+    ObjectID oldoid;
+    uniform->get(oldoid);
+
+    ObjectID newoid;
+    std::map<ObjectID, ObjectID>::iterator k = oldNewMap.find(oldoid);
+    if (k != oldNewMap.end()) {
+        newoid = k->second;
+    }
+    else {
+        newoid = insert(object);
+        oldNewMap[oldoid] = newoid;
+    }
+
+    uniform->set(newoid);
+
+    return true;
+}
diff --git a/src/osgEarth/OverlayDecorator b/src/osgEarth/OverlayDecorator
index 69e92da..9fccfa4 100644
--- a/src/osgEarth/OverlayDecorator
+++ b/src/osgEarth/OverlayDecorator
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
@@ -69,9 +69,25 @@ namespace osgEarth
          */
         void setOverlayGraphTraversalMask( unsigned mask );
 
+        /**
+         * Sets the maximum horizon distance to enforce when calculating
+         * the draping extents. Constraining the distance will mean that you won't
+         * see draped geometry past a certain point, but you will potentially get
+         * higher quality for the geometry you do see (with fewer aliasing artifacts).
+         */
         double getMaxHorizonDistance() const;
         void setMaxHorizonDistance( double horizonDistance );
 
+        /**
+         * Maximum height (above and below) the terrain MSL/ellipsoid at which
+         * to drape geometry. Geometry above the max or below the -max will not
+         * appear. This is only important to maintain Z buffering precision in the
+         * draped geometry; however, it is usually a better idea to draw draped
+         * geometry without blending or z-testing anyway.
+         * Default is 500,000 meters.
+         */
+        void setMaximumHeight(double value) { _maxHeight = value; }
+        double getMaximumHeight() const { return _maxHeight; }
 
     public: // TerrainDecorator
         virtual void onInstall( TerrainEngineNode* engine );
@@ -99,8 +115,8 @@ namespace osgEarth
             osg::Group*                   _group;            // contains the overlay graphics
             osg::StateSet*                _terrainStateSet;  // same object as in PerViewData (shared across techniques)
             osg::ref_ptr<osg::Referenced> _techniqueData;    // technique sets this if needed
-            const double*                 _horizonDistance;  // points to the PVD horizon distance.
-            osg::Group*                   _terrainParent;    // the terrain is in getChild(0).
+            const double*                 _horizonDistance;  // points to the PVD horizon distance
+            TextureCompositor*            _terrainResources; // for accessing image units
             osg::Vec3d                    _eyeWorld;         // eyepoint in world coords
             osgShadow::ConvexPolyhedron   _visibleFrustumPH; // polyhedron representing the frustum
         };
@@ -122,14 +138,9 @@ namespace osgEarth
         optional<int>                 _textureSize;
         bool                          _useShaders;
         bool                          _isGeocentric;
-        bool                          _mipmapping;
-        bool                          _rttBlending;
-        bool                          _updatePending;
         unsigned                      _rttTraversalMask;
-        
+        double                        _maxHeight;
         double                        _maxHorizonDistance;
-        bool                          _attachStencil;
-        
         unsigned                      _totalOverlayChildren;
 
         osg::ref_ptr<const SpatialReference>    _srs;
@@ -186,6 +197,9 @@ namespace osgEarth
         virtual bool hasData(
             OverlayDecorator::TechRTTParams& params) const { return true; }
 
+        virtual const osg::BoundingSphere& getBound(
+            OverlayDecorator::TechRTTParams& params) const { return params._group->getBound(); }
+
         virtual void onInstall( TerrainEngineNode* engine ) { }
 
         virtual void onUninstall( TerrainEngineNode* engine ) { }
diff --git a/src/osgEarth/OverlayDecorator.cpp b/src/osgEarth/OverlayDecorator.cpp
index c50ff5c..ccd4317 100755
--- a/src/osgEarth/OverlayDecorator.cpp
+++ b/src/osgEarth/OverlayDecorator.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
@@ -285,7 +285,9 @@ _useShaders          ( true ),
 _dumpRequested       ( false ),
 _rttTraversalMask    ( ~0 ),
 _maxHorizonDistance  ( DBL_MAX ),
-_totalOverlayChildren( 0 )
+_totalOverlayChildren( 0 ),
+_maxHeight           ( 500000.0 ),
+_isGeocentric(true)
 {
     //nop.
 }
@@ -356,7 +358,7 @@ OverlayDecorator::initializePerViewData( PerViewData& pvd, osg::Camera* cam )
         params._group = _overlayGroups[i].get();
         params._terrainStateSet = pvd._sharedTerrainStateSet.get(); // share it.
         params._horizonDistance = &pvd._sharedHorizonDistance;      // share it.
-        params._terrainParent = this;
+        params._terrainResources = _engine->getResources();
         params._mainCamera = cam;
     }
 }
@@ -411,14 +413,11 @@ OverlayDecorator::cullTerrainAndCalculateRTTParams(osgUtil::CullVisitor* cv,
     osg::Vec3d worldUp;
 
     // Radius at eyepoint (geocentric)
-    double R;
+    double R = 0;
 
     // height above sea level
     double hasl;
 
-    // weight of the HASL value when calculating extent compensation
-    double haslWeight;
-
     // approximate distance to the visible horizon
     double horizonDistance;
 
@@ -437,7 +436,7 @@ OverlayDecorator::cullTerrainAndCalculateRTTParams(osgUtil::CullVisitor* cv,
         
         //Actually sample the terrain to get the height and adjust the eye position so it's a tighter fit to the real data.
         double height;
-        if (_engine->getTerrain()->getHeight(geoSRS, geodetic.x(), geodetic.y(), &height)) // SpatialReference::create("epsg:4326"), osg::RadiansToDegrees( lon ), osg::RadiansToDegrees( lat ), &height))
+        if (_engine->getTerrain()->getHeight(geoSRS, geodetic.x(), geodetic.y(), &height))
         {
             geodetic.z() -= height;
         }
@@ -466,14 +465,10 @@ OverlayDecorator::cullTerrainAndCalculateRTTParams(osgUtil::CullVisitor* cv,
     // update the shared horizon distance.
     pvd._sharedHorizonDistance = horizonDistance;
 
-    // create a "weighting" that weights HASL against the camera's pitch.
-    osg::Vec3d lookVector = cv->getLookVectorLocal();
-    haslWeight = osg::absolute(worldUp * lookVector);
-
     // unit look-vector of the eye:
     osg::Vec3d camEye, camTo, camUp;
     const osg::Matrix& mvMatrix = *cv->getModelViewMatrix();
-    mvMatrix.getLookAt( camEye, camTo, camUp, 1.0); //eyeLen);
+    mvMatrix.getLookAt( camEye, camTo, camUp, 1.0);
     osg::Vec3 camLook = camTo-camEye;
     camLook.normalize();
 
@@ -561,13 +556,16 @@ OverlayDecorator::cullTerrainAndCalculateRTTParams(osgUtil::CullVisitor* cv,
     // the Ortho Z as mush as possible in order to maintain depth precision. Perhaps
     // later we can split this out and have each technique calculation its own View and
     // Proj matrix.
-
-    // For now: our RTT camera z range will be based on this equation:
-    double zspan = std::max(50000.0, hasl+25000.0);
+    
     osg::Vec3d up = camLook;
+    osg::Vec3d rttEye;
+
     if ( _isGeocentric )
     {
-        osg::Vec3d rttEye = eye+worldUp*zspan;
+        osg::Vec3d center = eye;
+        center.normalize();
+        center *= R;
+        rttEye = center + worldUp*_maxHeight;
         //establish a valid up vector
         osg::Vec3d rttLook = -rttEye;
         rttLook.normalize();
@@ -575,15 +573,18 @@ OverlayDecorator::cullTerrainAndCalculateRTTParams(osgUtil::CullVisitor* cv,
             up.set( camUp );
 
         // do NOT look at (0,0,0); must look down the ellipsoid up vector.
-        rttViewMatrix.makeLookAt( rttEye, rttEye-worldUp*zspan, up );
+        rttViewMatrix.makeLookAt( rttEye, center, up );
     }
     else
     {
+        osg::Vec3d center( camEye.x(), camEye.y(), 0.0 );
+        rttEye = center + worldUp*_maxHeight;
+
         osg::Vec3d rttLook(0, 0, -1);
         if ( fabs(rttLook * camLook) > 0.9999 )
             up.set( camUp );
 
-        rttViewMatrix.makeLookAt( camEye + worldUp*zspan, camEye - worldUp*zspan, up );
+        rttViewMatrix.makeLookAt( rttEye, center, up );
     }
 
     // Build a polyhedron for the new frustum so we can slice it.
@@ -613,7 +614,7 @@ OverlayDecorator::cullTerrainAndCalculateRTTParams(osgUtil::CullVisitor* cv,
         const osg::BoundingSphere& visibleOverlayBS = cvb._bs;
         OE_WARN << "VBS radius = " << visibleOverlayBS.radius() << std::endl;
 #else
-        const osg::BoundingSphere& visibleOverlayBS = params._group->getBound();
+        const osg::BoundingSphere& visibleOverlayBS = _techniques[t]->getBound(params);
 #endif
         if ( visibleOverlayBS.valid() )
         {
@@ -658,32 +659,43 @@ OverlayDecorator::cullTerrainAndCalculateRTTParams(osgUtil::CullVisitor* cv,
         // TODO: when verts = 0 should we do something different? or use the previous
         // frame's view matrix?
         if ( verts.size() > 0 )
-        {
-            // calculate an orthographic RTT projection matrix based on the view-space
-            // bounds of the vertex list (i.e. the extents surrounding the RTT camera 
-            // that bounds all the polyherdron verts in its XY plane)
-            double xmin, ymin, xmax, ymax, maxDist;
-            getExtentInSilhouette(rttViewMatrix, eye, verts, xmin, ymin, xmax, ymax, maxDist);
-
-            // make sure the ortho camera penetrates the terrain. This is a must for depth buffer sampling
-            double dist = std::max(hasl*1.5, std::min(maxDist, eyeLen));
-
-            // in ecef it can't go past the horizon though, or you get bleed thru
-            if ( _isGeocentric )
-                dist = std::min(dist, eyeLen);
-
-            // Even through using xmin and xmax directly results in a tighter fit, 
-            // it offsets the eyepoint from the center of the projection frustum.
-            // This causes problems for the draping projection matrix optimizer, so
-            // for now instead of re-doing that code we will just center the eyepoint
-            // here by using the larger of xmin and xmax. -gw.
-#if 1
-            double x = std::max( fabs(xmin), fabs(xmax) );
-            rttProjMatrix.makeOrtho(-x, x, ymin, ymax, 0.0, dist+zspan);
-#else
-            //Note: this was the original setup, which is technically optimal:
-            rttProjMatrix.makeOrtho(xmin, xmax, ymin, ymax, 0.0, dist+zspan);
+        {            
+            double xmin, ymin, xmax, ymax, orthoNear, orthoFar, maxDist;
+
+#if 0
+            // testing "lock to ortho viewport".
+            bool lockToOrthoFrustum = false; // experimental
+            if ( lockToOrthoFrustum && osg::equivalent(projMatrix(3,3), 1.0) )
+            {
+                projMatrix.getOrtho(xmin, xmax, ymin, ymax, orthoNear, orthoFar);
+            }
+
+            else
 #endif
+            {
+                // calculate an orthographic RTT projection matrix based on the view-space
+                // bounds of the vertex list (i.e. the extents surrounding the RTT camera 
+                // that bounds all the polyherdron verts in its XY plane)
+                getExtentInSilhouette(rttViewMatrix, eye, verts, xmin, ymin, xmax, ymax, maxDist);
+
+                // Even through using xmin and xmax directly results in a tighter fit, 
+                // it offsets the eyepoint from the center of the projection frustum.
+                // This causes problems for the draping projection matrix optimizer, so
+                // for now instead of re-doing that code we will just center the eyepoint
+                // here by using the larger of xmin and xmax. -gw.                
+                double x = std::max( fabs(xmin), fabs(xmax) );
+                xmin = -x, xmax = x;
+            }
+
+            // extends the frustum as far as it will safely go.
+            // this may result in Z fighting. either ignore that, assuming that draped geometry
+            // should probaly not use depth testing anyway, or address it later
+            double rttLen = rttEye.length();
+            orthoNear = 0.0; // at the rtt camera
+            orthoFar  = _isGeocentric ? rttLen : (rttLen + _maxHeight);
+
+            rttProjMatrix.makeOrtho(xmin, xmax, ymin, ymax, orthoNear, orthoFar);
+
 
             // Clamp the view frustum's N/F to the visible geometry. This clamped
             // frustum is the one we'll send to the technique.
@@ -750,7 +762,7 @@ OverlayDecorator::cullTerrainAndCalculateRTTParams(osgUtil::CullVisitor* cv,
             dsgmt->addChild( dsg );
 
             osg::Group* g = new osg::Group();
-            g->getOrCreateStateSet()->setAttribute(new osg::Program(), 0);
+            //g->getOrCreateStateSet()->setAttribute(new osg::Program(), 0);
             g->addChild(camNode);
             //g->addChild(overlay);
             g->addChild(intersection);
@@ -806,7 +818,7 @@ OverlayDecorator::traverse( osg::NodeVisitor& nv )
     // cull visitor's current camera view and work with that:
     if ( nv.getVisitorType() == nv.CULL_VISITOR )
     {
-        osgUtil::CullVisitor* cv = Culling::asCullVisitor(nv);
+        osgUtil::CullVisitor* cv = static_cast<osgUtil::CullVisitor*>(&nv);
         osg::Camera* camera = cv->getCurrentCamera();
 
         if ( camera != 0L && (_rttTraversalMask & nv.getTraversalMask()) != 0 )
diff --git a/src/osgEarth/OverlayNode.cpp b/src/osgEarth/OverlayNode.cpp
index 6d25e16..57712d3 100644
--- a/src/osgEarth/OverlayNode.cpp
+++ b/src/osgEarth/OverlayNode.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -324,7 +324,7 @@ OverlayNode::traverse( osg::NodeVisitor& nv )
                Currently this is only imlpemented for our custom PrimitiveIntersector.
             */
             osgUtil::IntersectionVisitor* iv = dynamic_cast<osgUtil::IntersectionVisitor*>(&nv);
-            osgEarth::PrimitiveIntersector* pi = dynamic_cast<osgEarth::PrimitiveIntersector *>(iv->getIntersector());
+            osgEarth::PrimitiveIntersector* pi = iv ? dynamic_cast<osgEarth::PrimitiveIntersector *>(iv->getIntersector()) : 0L;
 
             osg::ref_ptr<MapNode> mapNode;
             if (pi && !pi->getOverlayIgnore() && _mapNode.lock(mapNode))
diff --git a/src/osgEarth/PhongLightingEffect b/src/osgEarth/PhongLightingEffect
index 6c14caf..b6121c7 100644
--- a/src/osgEarth/PhongLightingEffect
+++ b/src/osgEarth/PhongLightingEffect
@@ -65,7 +65,6 @@ namespace osgEarth
 
         bool _supported;
         StateSetList _statesets;
-        bool _createLightingUniform;
         osg::ref_ptr<osg::Uniform> _lightingUniform;
 
         void init();
diff --git a/src/osgEarth/PhongLightingEffect.cpp b/src/osgEarth/PhongLightingEffect.cpp
index b40adf0..abb6096 100644
--- a/src/osgEarth/PhongLightingEffect.cpp
+++ b/src/osgEarth/PhongLightingEffect.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
@@ -44,13 +44,13 @@ namespace
         "uniform bool oe_mode_GL_LIGHTING; \n"
         "varying vec4 oe_lighting_adjustment; \n"
         "varying vec4 oe_lighting_zero_vec; \n"
-        "varying vec3 oe_Normal; \n"
+        "varying vec3 vp_Normal; \n"
 
         "void oe_phong_vertex(inout vec4 VertexVIEW) \n"
         "{ \n"
         "    if ( oe_mode_GL_LIGHTING == false ) return; \n"
         "    oe_lighting_adjustment = vec4(1.0); \n"
-        "    vec3 N = oe_Normal; \n"
+        "    vec3 N = vp_Normal; \n"
         "    float NdotL = dot( N, normalize(gl_LightSource[0].position.xyz) ); \n"
         "    NdotL = max( 0.0, NdotL ); \n"
 
@@ -94,7 +94,8 @@ namespace
         GLSL_DEFAULT_PRECISION_FLOAT "\n"
         
         "uniform bool oe_mode_GL_LIGHTING; \n"
-        "varying vec3 oe_phong_vertexView3; \n"
+
+        "out vec3 oe_phong_vertexView3; \n"
 
         "void oe_phong_vertex(inout vec4 VertexVIEW) \n"
         "{ \n"
@@ -107,16 +108,16 @@ namespace
         GLSL_DEFAULT_PRECISION_FLOAT "\n"
 
         "uniform bool oe_mode_GL_LIGHTING; \n"
-        "varying vec3 oe_phong_vertexView3; \n"
 
-        "vec3 oe_global_Normal; \n"
+        "in vec3 oe_phong_vertexView3; \n"
+        "in vec3 vp_Normal; \n"
 
         "void oe_phong_fragment(inout vec4 color) \n"
         "{ \n"        
         "    if ( oe_mode_GL_LIGHTING == false ) return; \n"
 
         "    vec3 L = normalize(gl_LightSource[0].position.xyz); \n"
-        "    vec3 N = normalize(oe_global_Normal); \n"
+        "    vec3 N = vp_Normal; \n"//normalize(vp_Normal); \n"
         
         "    vec4 ambient = gl_FrontLightProduct[0].ambient; \n"
 
@@ -128,7 +129,7 @@ namespace
         "    if (NdotL > 0.0) \n"
         "    { \n"
         "        vec3 V = normalize(oe_phong_vertexView3); \n"
-        "        vec3 H = normalize(L-V); \n"
+        "        vec3 H = reflect(-L,N); \n"
         "        float HdotN = max(dot(H,N), 0.0); \n"
         "        float shine = clamp(gl_FrontMaterial.shininess, 1.0, 128.0); \n"
         "        specular = gl_FrontLightProduct[0].specular * pow(HdotN, shine); \n"
diff --git a/src/osgEarth/Picker b/src/osgEarth/Picker
index d6b15df..3fc02fc 100644
--- a/src/osgEarth/Picker
+++ b/src/osgEarth/Picker
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarth/PrimitiveIntersector b/src/osgEarth/PrimitiveIntersector
index b1d6da5..726b482 100644
--- a/src/osgEarth/PrimitiveIntersector
+++ b/src/osgEarth/PrimitiveIntersector
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarth/PrimitiveIntersector.cpp b/src/osgEarth/PrimitiveIntersector.cpp
index f58fa50..7cef9c1 100644
--- a/src/osgEarth/PrimitiveIntersector.cpp
+++ b/src/osgEarth/PrimitiveIntersector.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -314,8 +314,12 @@ struct PrimitiveIntersectorFunctor
 //
 //  PrimitiveIntersector
 //
-PrimitiveIntersector::PrimitiveIntersector()
+PrimitiveIntersector::PrimitiveIntersector() :
+_parent(0),
+_thicknessVal(0),
+_overlayIgnore(false)
 {
+    //nop
 }
 
 PrimitiveIntersector::PrimitiveIntersector(CoordinateFrame cf, double x, double y, double thickness):
diff --git a/src/osgEarth/Profile b/src/osgEarth/Profile
index 89a9a3a..37155ba 100644
--- a/src/osgEarth/Profile
+++ b/src/osgEarth/Profile
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarth/Profile.cpp b/src/osgEarth/Profile.cpp
index 034a563..7a28990 100644
--- a/src/osgEarth/Profile.cpp
+++ b/src/osgEarth/Profile.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -531,14 +531,22 @@ Profile::createTileKey( double x, double y, unsigned int level ) const
 {
     if ( _extent.contains( x, y ) )
     {
-        unsigned int tilesX = (unsigned int)_numTilesWideAtLod0 * (1 << (unsigned int)level);
-        unsigned int tilesY = (unsigned int)_numTilesHighAtLod0 * (1 << (unsigned int)level);
+        unsigned tilesX = _numTilesWideAtLod0 * (1 << (unsigned)level);
+        unsigned tilesY = _numTilesHighAtLod0 * (1 << (unsigned)level);
 
-        if (((_numTilesWideAtLod0 != 0) && ((tilesX / _numTilesWideAtLod0) != (1 << (unsigned int) level))) ||
-            ((_numTilesHighAtLod0 != 0) && ((tilesY / _numTilesHighAtLod0) != (1 << (unsigned int) level))))
-        {	// check for overflow condition
-            return (TileKey::INVALID);
-        }
+        // overflow checks:
+
+        if (_numTilesWideAtLod0 == 0u || ((tilesX / _numTilesWideAtLod0) != (1 << (unsigned)level)))
+            return TileKey::INVALID;
+
+        if (_numTilesHighAtLod0 == 0u || ((tilesY / _numTilesHighAtLod0) != (1 << (unsigned)level)))
+            return TileKey::INVALID;
+
+        //if (((_numTilesWideAtLod0 != 0) && ((tilesX / _numTilesWideAtLod0) != (1 << (unsigned int) level))) ||
+        //    ((_numTilesHighAtLod0 != 0) && ((tilesY / _numTilesHighAtLod0) != (1 << (unsigned int) level))))
+        //{	// check for overflow condition
+        //    return (TileKey::INVALID);
+        //}
 
         double rx = (x - _extent.xMin()) / _extent.width();
         int tileX = osg::clampBelow( (unsigned int)(rx * (double)tilesX), tilesX-1 );
@@ -741,8 +749,8 @@ Profile::getEquivalentLOD( const Profile* rhsProfile, unsigned rhsLOD ) const
         return rhsLOD;
 
     // Special check for geodetic to mercator or vise versa, they should match up in LOD.
-    if (rhsProfile->isEquivalentTo(Registry::instance()->getSphericalMercatorProfile()) && isEquivalentTo(Registry::instance()->getGlobalGeodeticProfile()) ||
-        rhsProfile->isEquivalentTo(Registry::instance()->getGlobalGeodeticProfile()) && isEquivalentTo(Registry::instance()->getSphericalMercatorProfile()))
+    if ((rhsProfile->isEquivalentTo(Registry::instance()->getSphericalMercatorProfile()) && isEquivalentTo(Registry::instance()->getGlobalGeodeticProfile())) ||
+        (rhsProfile->isEquivalentTo(Registry::instance()->getGlobalGeodeticProfile()) && isEquivalentTo(Registry::instance()->getSphericalMercatorProfile())))
     {
         return rhsLOD;
     }
diff --git a/src/osgEarth/Profiler b/src/osgEarth/Profiler
index cf5fd7a..8daff41 100644
--- a/src/osgEarth/Profiler
+++ b/src/osgEarth/Profiler
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarth/Profiler.cpp b/src/osgEarth/Profiler.cpp
index 060fe9d..a21847f 100644
--- a/src/osgEarth/Profiler.cpp
+++ b/src/osgEarth/Profiler.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarth/Progress b/src/osgEarth/Progress
index 60e069b..51a8a36 100644
--- a/src/osgEarth/Progress
+++ b/src/osgEarth/Progress
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -38,6 +38,11 @@ namespace osgEarth
         virtual ~ProgressCallback() { }
 
         /**
+         * Report an error and set the canceled flag to true.
+         */
+        virtual void reportError(const std::string& msg);
+
+        /**
         * Callback function that will be called.
         * @param current
         *        The amount of work done in the current stage
@@ -89,7 +94,16 @@ namespace osgEarth
          */
         virtual bool isCanceled() { return _canceled; }
 
+        /**
+         * Whether reportError was called
+         */
+        virtual bool failed() { return _failed; }
+
+        /**
+         * Status/error message
+         */
         std::string& message() { return _message; }
+        const std::string& message() const { return _message; }
 
         /**
          * Resets the canceled flag.
@@ -109,14 +123,19 @@ namespace osgEarth
         /**
          * Access user stats
          */
-        fast_map<std::string,double>& stats() { return _stats; }
+        typedef fast_map<std::string,double> Stats;
+        Stats& stats() { return _stats; }
+        double& stats(const std::string& name);
+        bool& collectStats() { return _collectStats; } 
+        const bool& collectStats() const { return _collectStats; }        
 
     protected:
-        volatile unsigned _numStages;
         std::string       _message;
         mutable  bool     _needsRetry;
         mutable  bool     _canceled;
-        mutable  fast_map<std::string, double> _stats;
+        mutable  bool     _failed;
+        mutable  Stats    _stats;
+        mutable  bool     _collectStats;
     };
 
 
@@ -132,6 +151,8 @@ namespace osgEarth
         ConsoleProgressCallback();
         virtual ~ConsoleProgressCallback() { }
 
+        virtual void reportError(const std::string& msg);
+
         /**
         * Callback function that will be called.
         * @param current
diff --git a/src/osgEarth/Progress.cpp b/src/osgEarth/Progress.cpp
index 2dcb63f..a803a45 100644
--- a/src/osgEarth/Progress.cpp
+++ b/src/osgEarth/Progress.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -25,11 +25,19 @@ using namespace osgEarth;
 ProgressCallback::ProgressCallback() :
 osg::Referenced( true ),
 _canceled      ( false ),
-_needsRetry    ( false )
+_failed        ( false ),
+_needsRetry    ( false ),
+_collectStats  ( false )
 {
     //NOP
 }
 
+void ProgressCallback::reportError(const std::string& msg)
+{
+    _message = msg;
+    _failed = true;
+}
+
 bool ProgressCallback::reportProgress(double             current,
                                       double             total,
                                       unsigned           stage,
@@ -39,6 +47,18 @@ bool ProgressCallback::reportProgress(double             current,
     return false;
 }
 
+double& ProgressCallback::stats(const std::string& key)
+{
+    Stats::iterator i = _stats.find(key);
+    if ( i == _stats.end() )
+    {
+        double& value = _stats[key];
+        value = 0.0;
+        return value;
+    }
+    return i->second;
+}
+
 /******************************************************************************/
 ConsoleProgressCallback::ConsoleProgressCallback() :
 ProgressCallback()
@@ -46,6 +66,13 @@ ProgressCallback()
     //NOP
 }
 
+void
+ConsoleProgressCallback::reportError(const std::string& msg)
+{
+    ProgressCallback::reportError(msg);
+    OE_NOTICE << "Error: " << msg << std::endl;
+}
+
 bool
 ConsoleProgressCallback::reportProgress(double current, double total, 
                                         unsigned stage, unsigned numStages,
diff --git a/src/osgEarth/QuadTree b/src/osgEarth/QuadTree
new file mode 100644
index 0000000..c7b5662
--- /dev/null
+++ b/src/osgEarth/QuadTree
@@ -0,0 +1,199 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+* Copyright 2008-2014 Pelican Mapping
+* http://osgearth.org
+*
+* osgEarth is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public License
+* along with this program.  If not, see <http://www.gnu.org/licenses/>
+*/
+#ifndef OSGEARTH_QUAD_TREE
+#define OSGEARTH_QUAD_TREE 1
+
+#include <osgEarth/Common>
+
+#include <osg/Shape>
+#include <osg/Geometry>
+
+#include <map>
+
+namespace osgEarth
+{
+    class OSGEARTH_EXPORT QuadTree : public osg::Shape
+    {
+        public:
+
+            QuadTree();
+
+            QuadTree(const QuadTree& rhs, const osg::CopyOp& copyop=osg::CopyOp::SHALLOW_COPY);
+
+            META_Shape(osg, QuadTree)
+
+            struct OSGEARTH_EXPORT BuildOptions
+            {
+                BuildOptions();
+
+                unsigned int _numVerticesProcessed;
+                unsigned int _targetNumTrianglesPerLeaf;
+                unsigned int _maxNumLevels;
+                unsigned int _numTriangles;
+            };
+
+
+            /** Build the quadtree from the specified source geometry object.
+              * retun true on success. */
+            virtual bool build(BuildOptions& buildOptions, osg::Geometry* geometry);
+
+            struct LineSegmentIntersection
+            {
+                LineSegmentIntersection():
+                    ratio(-1.0),
+                    p0(0),
+                    p1(0),
+                    p2(0),
+                    r0(0.0f),
+                    r1(0.0f),
+                    r2(0.0f),
+                    primitiveIndex(0) {}
+
+                bool operator < (const LineSegmentIntersection& rhs) const { return ratio < rhs.ratio; }
+
+                typedef std::vector<unsigned int>   IndexList;
+                typedef std::vector<double>         RatioList;
+
+                double                          ratio;
+                osg::Vec3d                      intersectionPoint;
+                osg::Vec3                       intersectionNormal;
+
+                unsigned int                    p0;
+                unsigned int                    p1;
+                unsigned int                    p2;
+                float                           r0;
+                float                           r1;
+                float                           r2;
+
+                unsigned int                    primitiveIndex;
+            };
+
+
+            typedef std::vector<LineSegmentIntersection> LineSegmentIntersections;
+
+            /** compute the intersection of a line segment and the quadtree, return true if an intersection has been found.*/
+            virtual bool intersect(const osg::Vec3d& start, const osg::Vec3d& end, LineSegmentIntersections& intersections) const;
+
+
+            typedef int value_type;
+
+            struct QuadNode
+            {
+                QuadNode():
+                    first(0),
+                    second(0) {}
+
+                QuadNode(value_type f, value_type s):
+                    first(f),
+                    second(s) {}
+
+                osg::BoundingBox bb;
+
+                value_type first;
+                value_type second;
+            };
+
+            struct Triangle
+            {
+                Triangle():
+                    p0(0),p1(0),p2(0) {}
+
+                Triangle(unsigned int ip0, unsigned int ip1, unsigned int ip2):
+                    p0(ip0), p1(ip1), p2(ip2) {}
+
+                bool operator < (const Triangle& rhs) const
+                {
+                    if (p0<rhs.p0) return true;
+                    if (p0>rhs.p0) return false;
+                    if (p1<rhs.p1) return true;
+                    if (p1>rhs.p1) return false;
+                    return p2<rhs.p2;
+                }
+
+                unsigned int p0;
+                unsigned int p1;
+                unsigned int p2;
+            };
+
+            typedef std::vector< QuadNode >     QuadNodeList;
+            typedef std::vector< Triangle >     TriangleList;
+
+            int addNode(const QuadNode& node)
+            {
+                int num = static_cast<int>(_quadNodes.size());
+                _quadNodes.push_back(node);
+                return num;
+            }
+
+            QuadNode& getNode(int nodeNum) { return _quadNodes[nodeNum]; }
+            const QuadNode& getNode(int nodeNum) const { return _quadNodes[nodeNum]; }
+
+            QuadNodeList& getNodes() { return _quadNodes; }
+            const QuadNodeList& getNodes() const { return _quadNodes; }
+
+            void setVertices(osg::Vec3Array* vertices) { _vertices = vertices; }
+            const osg::Vec3Array* getVertices() const { return _vertices.get(); }
+
+            unsigned int addTriangle(const Triangle& tri)
+            {
+                unsigned int num = static_cast<unsigned int>(_triangles.size());
+                _triangles.push_back(tri);
+                return num;
+            }
+
+            Triangle& getTriangle(unsigned int i) { return _triangles[i]; }
+            const Triangle& getTriangle(unsigned int i) const { return _triangles[i]; }
+
+            TriangleList& getTriangles() { return _triangles; }
+            const TriangleList& getTriangles() const { return _triangles; }
+
+
+        protected:
+
+            osg::ref_ptr<osg::Vec3Array>        _vertices;
+            QuadNodeList                        _quadNodes;
+            TriangleList                        _triangles;
+
+    };
+
+    class QuadTreeBuilder : public osg::NodeVisitor
+    {
+        public:
+
+            QuadTreeBuilder();
+
+            QuadTreeBuilder(const QuadTreeBuilder& rhs);
+
+            META_NodeVisitor(osg, QuadTreeBuilder)
+
+            virtual QuadTreeBuilder* clone() { return new QuadTreeBuilder(*this); }
+
+            void apply(osg::Geode& geode);
+
+            QuadTree::BuildOptions _buildOptions;
+
+            osg::ref_ptr<QuadTree> _quadTreePrototype;
+        protected:
+
+            virtual ~QuadTreeBuilder() {}
+    };
+
+} // namespace osgEarth
+
+#endif // OSGEARTH_QUAD_TREE
diff --git a/src/osgEarth/QuadTree.cpp b/src/osgEarth/QuadTree.cpp
new file mode 100644
index 0000000..6b3addf
--- /dev/null
+++ b/src/osgEarth/QuadTree.cpp
@@ -0,0 +1,825 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+* Copyright 2008-2014 Pelican Mapping
+* http://osgearth.org
+*
+* osgEarth is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public License
+* along with this program.  If not, see <http://www.gnu.org/licenses/>
+*/
+#undef NDEBUG
+#include <cassert>
+#include "QuadTree"
+#include <osg/Geode>
+#include <osg/TriangleIndexFunctor>
+#include <osg/Timer>
+
+#include <osg/io_utils>
+
+using namespace osgEarth;
+
+//#define VERBOSE_OUTPUT
+
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// BuildQuadTree Declarartion - class used for building an single QuadTree
+
+struct BuildQuadTree
+{
+    BuildQuadTree(QuadTree& quadTree):
+        _quadTree(quadTree) {}
+
+    typedef std::vector< osg::Vec3 >            CenterList;
+    typedef std::vector< unsigned int >         Indices;
+    typedef std::vector< unsigned int >         AxisStack;
+
+    bool build(QuadTree::BuildOptions& options, osg::Geometry* geometry);
+
+    void computeDivisions(QuadTree::BuildOptions& options);
+
+    int divide(QuadTree::BuildOptions& options, osg::BoundingBox& bb, int nodeIndex, unsigned int level);
+
+    QuadTree&           _quadTree;
+
+    osg::BoundingBox    _bb;
+    AxisStack           _axisStack;
+    Indices             _primitiveIndices;
+    CenterList          _centers;
+
+protected:
+
+    BuildQuadTree& operator = (const BuildQuadTree&) { return *this; }
+};
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// Functor for collecting triangle indices from Geometry
+struct TriangleIndicesCollector
+{
+    TriangleIndicesCollector():
+        _buildQuadTree(0)
+    {
+    }
+
+    inline void operator () (unsigned int p0, unsigned int p1, unsigned int p2)
+    {
+        const osg::Vec3& v0 = (*(_buildQuadTree->_quadTree.getVertices()))[p0];
+        const osg::Vec3& v1 = (*(_buildQuadTree->_quadTree.getVertices()))[p1];
+        const osg::Vec3& v2 = (*(_buildQuadTree->_quadTree.getVertices()))[p2];
+
+        unsigned int i = _buildQuadTree->_quadTree.addTriangle(QuadTree::Triangle(p0,p1,p2));
+
+        osg::BoundingBox bb(v0,v0);
+        bb.expandBy(v1);
+        bb.expandBy(v2);
+
+        _buildQuadTree->_centers.push_back(bb.center());
+        _buildQuadTree->_primitiveIndices.push_back(i);
+
+    }
+
+    BuildQuadTree* _buildQuadTree;
+};
+
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// BuildQuadTree Implementation
+
+bool BuildQuadTree::build(QuadTree::BuildOptions& options, osg::Geometry* geometry)
+{
+
+#ifdef VERBOSE_OUTPUT
+    OSG_NOTICE<<"QuadTreeBuilder::createQuadTree()"<<std::endl;
+#endif
+
+    osg::Vec3Array* vertices = dynamic_cast<osg::Vec3Array*>(geometry->getVertexArray());
+    if (!vertices) return false;
+
+    if (vertices->size() <= options._targetNumTrianglesPerLeaf) return false;
+    
+#if OSG_VERSION_GREATER_OR_EQUAL(3,3,2)
+    _bb = geometry->getBoundingBox();
+#else
+    _bb = geometry->getBound();
+#endif
+
+    _quadTree.setVertices(vertices);
+
+    unsigned int estimatedSize = (unsigned int)(2.0*float(vertices->size())/float(options._targetNumTrianglesPerLeaf));
+
+#ifdef VERBOSE_OUTPUT
+    OSG_NOTICE<<"quadTree->_quadNodes.reserve()="<<estimatedSize<<std::endl<<std::endl;
+#endif
+
+    _quadTree.getNodes().reserve(estimatedSize*5);
+
+    computeDivisions(options);
+
+    options._numVerticesProcessed += vertices->size();
+
+    _primitiveIndices.reserve(options._numTriangles);
+    _centers.reserve(options._numTriangles);
+
+    _quadTree.getTriangles().reserve(options._numTriangles);
+
+
+    osg::TriangleIndexFunctor<TriangleIndicesCollector> collectTriangleIndices;
+    collectTriangleIndices._buildQuadTree = this;
+    geometry->accept(collectTriangleIndices);
+
+    _primitiveIndices.reserve(vertices->size());
+
+    QuadTree::QuadNode node(-1, _primitiveIndices.size());
+    node.bb = _bb;
+
+    int nodeNum = _quadTree.addNode(node);
+
+    osg::BoundingBox bb = _bb;
+    nodeNum = divide(options, bb, nodeNum, 0);
+
+    // now reorder the triangle list so that it's in order as per the primitiveIndex list.
+    QuadTree::TriangleList triangleList(_quadTree.getTriangles().size());
+    for(unsigned int i=0; i<_primitiveIndices.size(); ++i)
+    {
+        triangleList[i] = _quadTree.getTriangle(_primitiveIndices[i]);
+    }
+
+    _quadTree.getTriangles().swap(triangleList);
+
+
+#ifdef VERBOSE_OUTPUT
+    OSG_NOTICE<<"Root nodeNum="<<nodeNum<<std::endl;
+#endif
+
+
+//    OSG_NOTICE<<"_quadNodes.size()="<<_quadNodes.size()<<"  estimated size = "<<estimatedSize<<std::endl;
+//    OSG_NOTICE<<"_quadLeaves.size()="<<_quadLeaves.size()<<"  estimated size = "<<estimatedSize<<std::endl<<std::endl;
+
+
+    return !_quadTree.getNodes().empty();
+}
+
+void BuildQuadTree::computeDivisions(QuadTree::BuildOptions& options)
+{
+    osg::Vec3 dimensions(_bb.xMax()-_bb.xMin(),
+                         _bb.yMax()-_bb.yMin(),
+                         _bb.zMax()-_bb.zMin());
+
+#ifdef VERBOSE_OUTPUT
+    OSG_NOTICE<<"computeDivisions("<<options._maxNumLevels<<") "<<dimensions<< " { "<<std::endl;
+#endif
+
+    _axisStack.reserve(options._maxNumLevels);
+
+    for(unsigned int level=0; level<options._maxNumLevels; ++level)
+    {
+        int axis = (dimensions[0]>=dimensions[1])? 0 : 1;
+
+        _axisStack.push_back(axis);
+        dimensions[axis] *= 0.5f;
+
+#ifdef VERBOSE_OUTPUT
+        OSG_NOTICE<<"  "<<level<<", "<<dimensions<<", "<<axis<<std::endl;
+#endif
+    }
+
+#ifdef VERBOSE_OUTPUT
+    OSG_NOTICE<<"}"<<std::endl;
+#endif
+}
+
+int BuildQuadTree::divide(QuadTree::BuildOptions& options, osg::BoundingBox& bb, int nodeIndex, unsigned int level)
+{
+    QuadTree::QuadNode& node = _quadTree.getNode(nodeIndex);
+
+    bool needToDivide = level < _axisStack.size() &&
+                        (node.first<0 && static_cast<unsigned int>(node.second)>options._targetNumTrianglesPerLeaf);
+
+    if (!needToDivide)
+    {
+        if (node.first<0)
+        {
+            int istart = -node.first-1;
+            int iend = istart+node.second-1;
+
+            // leaf is done, now compute bound on it.
+            node.bb.init();
+            for(int i=istart; i<=iend; ++i)
+            {
+                const QuadTree::Triangle& tri = _quadTree.getTriangle(_primitiveIndices[i]);
+                const osg::Vec3& v0 = (*_quadTree.getVertices())[tri.p0];
+                const osg::Vec3& v1 = (*_quadTree.getVertices())[tri.p1];
+                const osg::Vec3& v2 = (*_quadTree.getVertices())[tri.p2];
+                node.bb.expandBy(v0);
+                node.bb.expandBy(v1);
+                node.bb.expandBy(v2);
+
+            }
+
+            if (node.bb.valid())
+            {
+                float epsilon = 1e-6f;
+                node.bb._min.x() -= epsilon;
+                node.bb._min.y() -= epsilon;
+                node.bb._min.z() -= epsilon;
+                node.bb._max.x() += epsilon;
+                node.bb._max.y() += epsilon;
+                node.bb._max.z() += epsilon;
+            }
+
+#ifdef VERBOSE_OUTPUT
+            if (!node.bb.valid())
+            {
+                OSG_NOTICE<<"After reset "<<node.first<<","<<node.second<<std::endl;
+                OSG_NOTICE<<"  bb._min ("<<node.bb._min<<")"<<std::endl;
+                OSG_NOTICE<<"  bb._max ("<<node.bb._max<<")"<<std::endl;
+            }
+            else
+            {
+                OSG_NOTICE<<"Set bb for nodeIndex = "<<nodeIndex<<std::endl;
+            }
+#endif
+        }
+
+        return nodeIndex;
+
+    }
+
+    int axis = _axisStack[level];
+
+#ifdef VERBOSE_OUTPUT
+    OSG_NOTICE<<"divide("<<nodeIndex<<", "<<level<< "), axis="<<axis<<std::endl;
+#endif
+
+    if (node.first<0)
+    {
+        // leaf node as first <= 0, so look at dividing it.
+
+        int istart = -node.first-1;
+        int iend = istart+node.second-1;
+
+        //OSG_NOTICE<<"  divide leaf"<<std::endl;
+
+        float original_min = bb._min[axis];
+        float original_max = bb._max[axis];
+
+        float mid = (original_min+original_max)*0.5f;
+
+        int originalLeftChildIndex = 0;
+        int originalRightChildIndex = 0;
+        bool insitueDivision = false;
+
+        {
+            //osg::Vec3Array* vertices = quadTree._vertices.get();
+            int left = istart;
+            int right = iend;
+
+            while(left<right)
+            {
+                while(left<right && (_centers[_primitiveIndices[left]][axis]<=mid)) { ++left; }
+
+                while(left<right && (_centers[_primitiveIndices[right]][axis]>mid)) { --right; }
+
+                while(left<right && (_centers[_primitiveIndices[right]][axis]>mid)) { --right; }
+
+                if (left<right)
+                {
+                    std::swap(_primitiveIndices[left], _primitiveIndices[right]);
+                    ++left;
+                    --right;
+                }
+            }
+
+            if (left==right)
+            {
+                if (_centers[_primitiveIndices[left]][axis]<=mid) ++left;
+                else --right;
+            }
+
+            QuadTree::QuadNode leftLeaf(-istart-1, (right-istart)+1);
+            QuadTree::QuadNode rightLeaf(-left-1, (iend-left)+1);
+
+#if 0
+            OSG_NOTICE<<"In  node.first     ="<<node.first     <<" node.second     ="<<node.second<<std::endl;
+            OSG_NOTICE<<"    leftLeaf.first ="<<leftLeaf.first <<" leftLeaf.second ="<<leftLeaf.second<<std::endl;
+            OSG_NOTICE<<"    rightLeaf.first="<<rightLeaf.first<<" rightLeaf.second="<<rightLeaf.second<<std::endl;
+            OSG_NOTICE<<"    left="<<left<<" right="<<right<<std::endl;
+
+            if (node.second != (leftLeaf.second +rightLeaf.second))
+            {
+                OSG_NOTICE<<"*** Error in size, leaf.second="<<node.second
+                                        <<", leftLeaf.second="<<leftLeaf.second
+                                        <<", rightLeaf.second="<<rightLeaf.second<<std::endl;
+            }
+            else
+            {
+                OSG_NOTICE<<"Size OK, leaf.second="<<node.second
+                                        <<", leftLeaf.second="<<leftLeaf.second
+                                        <<", rightLeaf.second="<<rightLeaf.second<<std::endl;
+            }
+#endif
+
+            if (leftLeaf.second<=0)
+            {
+                //OSG_NOTICE<<"LeftLeaf empty"<<std::endl;
+                originalLeftChildIndex = 0;
+                //originalRightChildIndex = addNode(rightLeaf);
+                originalRightChildIndex = nodeIndex;
+                insitueDivision = true;
+            }
+            else if (rightLeaf.second<=0)
+            {
+                //OSG_NOTICE<<"RightLeaf empty"<<std::endl;
+                // originalLeftChildIndex = addNode(leftLeaf);
+                originalLeftChildIndex = nodeIndex;
+                originalRightChildIndex = 0;
+                insitueDivision = true;
+            }
+            else
+            {
+                originalLeftChildIndex = _quadTree.addNode(leftLeaf);
+                originalRightChildIndex = _quadTree.addNode(rightLeaf);
+            }
+        }
+
+
+        float restore = bb._max[axis];
+        bb._max[axis] = mid;
+
+        //OSG_NOTICE<<"  divide leftLeaf "<<quadTree.getNode(nodeNum).first<<std::endl;
+        int leftChildIndex = originalLeftChildIndex!=0 ? divide(options, bb, originalLeftChildIndex, level+1) : 0;
+
+        bb._max[axis] = restore;
+
+        restore = bb._min[axis];
+        bb._min[axis] = mid;
+
+        //OSG_NOTICE<<"  divide rightLeaf "<<quadTree.getNode(nodeNum).second<<std::endl;
+        int rightChildIndex = originalRightChildIndex!=0 ? divide(options, bb, originalRightChildIndex, level+1) : 0;
+
+        bb._min[axis] = restore;
+
+
+        if (!insitueDivision)
+        {
+            // take a second reference to node we are working on as the std::vector<> resize could
+            // have invalidate the previous node ref.
+            QuadTree::QuadNode& newNodeRef = _quadTree.getNode(nodeIndex);
+
+            newNodeRef.first = leftChildIndex;
+            newNodeRef.second = rightChildIndex;
+
+            insitueDivision = true;
+
+            newNodeRef.bb.init();
+            if (leftChildIndex!=0) newNodeRef.bb.expandBy(_quadTree.getNode(leftChildIndex).bb);
+            if (rightChildIndex!=0) newNodeRef.bb.expandBy(_quadTree.getNode(rightChildIndex).bb);
+
+            if (!newNodeRef.bb.valid())
+            {
+                OSG_NOTICE<<"leftChildIndex="<<leftChildIndex<<" && originalLeftChildIndex="<<originalLeftChildIndex<<std::endl;
+                OSG_NOTICE<<"rightChildIndex="<<rightChildIndex<<" && originalRightChildIndex="<<originalRightChildIndex<<std::endl;
+
+                OSG_NOTICE<<"Invalid BB leftChildIndex="<<leftChildIndex<<", "<<rightChildIndex<<std::endl;
+                OSG_NOTICE<<"  bb._min ("<<newNodeRef.bb._min<<")"<<std::endl;
+                OSG_NOTICE<<"  bb._max ("<<newNodeRef.bb._max<<")"<<std::endl;
+
+                if (leftChildIndex!=0)
+                {
+                    OSG_NOTICE<<"  getNode(leftChildIndex).bb min = "<<_quadTree.getNode(leftChildIndex).bb._min<<std::endl;
+                    OSG_NOTICE<<"                                 max = "<<_quadTree.getNode(leftChildIndex).bb._max<<std::endl;
+                }
+                if (rightChildIndex!=0)
+                {
+                    OSG_NOTICE<<"  getNode(rightChildIndex).bb min = "<<_quadTree.getNode(rightChildIndex).bb._min<<std::endl;
+                    OSG_NOTICE<<"                              max = "<<_quadTree.getNode(rightChildIndex).bb._max<<std::endl;
+                }
+            }
+        }
+    }
+    else
+    {
+        OSG_NOTICE<<"NOT expecting to get here"<<std::endl;
+    }
+
+    return nodeIndex;
+
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// IntersectQuadTree
+//
+struct IntersectQuadTree
+{
+    IntersectQuadTree(const osg::Vec3Array& vertices,
+                    const QuadTree::QuadNodeList& nodes,
+                    const QuadTree::TriangleList& triangles,
+                    QuadTree::LineSegmentIntersections& intersections,
+                    const osg::Vec3d& s, const osg::Vec3d& e):
+                        _vertices(vertices),
+                        _quadNodes(nodes),
+                        _triangles(triangles),
+                        _intersections(intersections),
+                        _s(s),
+                        _e(e)
+    {
+        _d = e - s;
+        _length = _d.length();
+        _inverse_length = _length!=0.0f ? 1.0f/_length : 0.0;
+        _d *= _inverse_length;
+
+        _d_invX = _d.x()!=0.0f ? _d/_d.x() : osg::Vec3(0.0f,0.0f,0.0f);
+        _d_invY = _d.y()!=0.0f ? _d/_d.y() : osg::Vec3(0.0f,0.0f,0.0f);
+        _d_invZ = _d.z()!=0.0f ? _d/_d.z() : osg::Vec3(0.0f,0.0f,0.0f);
+    }
+
+    void intersect(const QuadTree::QuadNode& node, const osg::Vec3& s, const osg::Vec3& e) const;
+    bool intersectAndClip(osg::Vec3& s, osg::Vec3& e, const osg::BoundingBox& bb) const;
+
+    const osg::Vec3Array&               _vertices;
+    const QuadTree::QuadNodeList&           _quadNodes;
+    const QuadTree::TriangleList&         _triangles;
+    QuadTree::LineSegmentIntersections&   _intersections;
+
+    osg::Vec3 _s;
+    osg::Vec3 _e;
+
+    osg::Vec3 _d;
+    float     _length;
+    float     _inverse_length;
+
+    osg::Vec3 _d_invX;
+    osg::Vec3 _d_invY;
+    osg::Vec3 _d_invZ;
+
+
+protected:
+
+    IntersectQuadTree& operator = (const IntersectQuadTree&) { return *this; }
+};
+
+
+void IntersectQuadTree::intersect(const QuadTree::QuadNode& node, const osg::Vec3& ls, const osg::Vec3& le) const
+{
+    static const float esplison = 1e-10f;
+    if (node.first<0)
+    {
+        // treat as a leaf
+
+        //OSG_NOTICE<<"QuadTree::intersect("<<&leaf<<")"<<std::endl;
+        int istart = -node.first-1;
+        int iend = istart + node.second;
+
+        for(int i=istart; i<iend; ++i)
+        {
+            //const Triangle& tri = _triangles[_primitiveIndices[i]];
+            const QuadTree::Triangle& tri = _triangles[i];
+            // OSG_NOTICE<<"   tri("<<tri.p1<<","<<tri.p2<<","<<tri.p3<<")"<<std::endl;
+
+            const osg::Vec3& v0 = _vertices[tri.p0];
+            const osg::Vec3& v1 = _vertices[tri.p1];
+            const osg::Vec3& v2 = _vertices[tri.p2];
+
+            osg::Vec3 T = _s - v0;
+            osg::Vec3 E2 = v2 - v0;
+            osg::Vec3 E1 = v1 - v0;
+
+            osg::Vec3 P =  _d ^ E2;
+
+            float det = P * E1;
+
+            float r,r0,r1,r2;
+
+            if (det>esplison)
+            {
+                float u = (P*T);
+                if (u<0.0 || u>det) continue;
+
+                osg::Vec3 Q = T ^ E1;
+                float v = (Q*_d);
+                if (v<0.0 || v>det) continue;
+
+                if ((u+v)> det) continue;
+
+                float inv_det = 1.0f/det;
+                float t = (Q*E2)*inv_det;
+                if (t<0.0 || t>_length) continue;
+
+                u *= inv_det;
+                v *= inv_det;
+
+                r0 = 1.0f-u-v;
+                r1 = u;
+                r2 = v;
+                r = t * _inverse_length;
+            }
+            else if (det<-esplison)
+            {
+
+                float u = (P*T);
+                if (u>0.0 || u<det) continue;
+
+                osg::Vec3 Q = T ^ E1;
+                float v = (Q*_d);
+                if (v>0.0 || v<det) continue;
+
+                if ((u+v) < det) continue;
+
+                float inv_det = 1.0f/det;
+                float t = (Q*E2)*inv_det;
+                if (t<0.0 || t>_length) continue;
+
+                u *= inv_det;
+                v *= inv_det;
+
+                r0 = 1.0f-u-v;
+                r1 = u;
+                r2 = v;
+                r = t * _inverse_length;
+            }
+            else
+            {
+                continue;
+            }
+
+            osg::Vec3 in = v0*r0 + v1*r1 + v2*r2;
+            osg::Vec3 normal = E1^E2;
+            normal.normalize();
+
+#if 1
+            _intersections.push_back(QuadTree::LineSegmentIntersection());
+            QuadTree::LineSegmentIntersection& intersection = _intersections.back();
+
+            intersection.ratio = r;
+            intersection.primitiveIndex = i;
+            intersection.intersectionPoint = in;
+            intersection.intersectionNormal = normal;
+
+            intersection.p0 = tri.p0;
+            intersection.p1 = tri.p1;
+            intersection.p2 = tri.p2;
+            intersection.r0 = r0;
+            intersection.r1 = r1;
+            intersection.r2 = r2;
+
+#endif
+            // OSG_NOTICE<<"  got intersection ("<<in<<") ratio="<<r<<std::endl;
+        }
+    }
+    else
+    {
+        if (node.first>0)
+        {
+            osg::Vec3 l(ls), e(le);
+            if (intersectAndClip(l,e, _quadNodes[node.first].bb))
+            {
+                intersect(_quadNodes[node.first], l, e);
+            }
+        }
+        if (node.second>0)
+        {
+            osg::Vec3 l(ls), e(le);
+            if (intersectAndClip(l,e, _quadNodes[node.second].bb))
+            {
+                intersect(_quadNodes[node.second], l, e);
+            }
+        }
+    }
+}
+
+bool IntersectQuadTree::intersectAndClip(osg::Vec3& s, osg::Vec3& e, const osg::BoundingBox& bb) const
+{
+    //return true;
+
+    //if (!bb.valid()) return true;
+
+    // compate s and e against the xMin to xMax range of bb.
+    if (s.x()<=e.x())
+    {
+
+        // trivial reject of segment wholely outside.
+        if (e.x()<bb.xMin()) return false;
+        if (s.x()>bb.xMax()) return false;
+
+        if (s.x()<bb.xMin())
+        {
+            // clip s to xMin.
+            s = s+_d_invX*(bb.xMin()-s.x());
+        }
+
+        if (e.x()>bb.xMax())
+        {
+            // clip e to xMax.
+            e = s+_d_invX*(bb.xMax()-s.x());
+        }
+    }
+    else
+    {
+        if (s.x()<bb.xMin()) return false;
+        if (e.x()>bb.xMax()) return false;
+
+        if (e.x()<bb.xMin())
+        {
+            // clip s to xMin.
+            e = s+_d_invX*(bb.xMin()-s.x());
+        }
+
+        if (s.x()>bb.xMax())
+        {
+            // clip e to xMax.
+            s = s+_d_invX*(bb.xMax()-s.x());
+        }
+    }
+
+    // compate s and e against the yMin to yMax range of bb.
+    if (s.y()<=e.y())
+    {
+
+        // trivial reject of segment wholely outside.
+        if (e.y()<bb.yMin()) return false;
+        if (s.y()>bb.yMax()) return false;
+
+        if (s.y()<bb.yMin())
+        {
+            // clip s to yMin.
+            s = s+_d_invY*(bb.yMin()-s.y());
+        }
+
+        if (e.y()>bb.yMax())
+        {
+            // clip e to yMax.
+            e = s+_d_invY*(bb.yMax()-s.y());
+        }
+    }
+    else
+    {
+        if (s.y()<bb.yMin()) return false;
+        if (e.y()>bb.yMax()) return false;
+
+        if (e.y()<bb.yMin())
+        {
+            // clip s to yMin.
+            e = s+_d_invY*(bb.yMin()-s.y());
+        }
+
+        if (s.y()>bb.yMax())
+        {
+            // clip e to yMax.
+            s = s+_d_invY*(bb.yMax()-s.y());
+        }
+    }
+
+    // compate s and e against the zMin to zMax range of bb.
+    if (s.z()<=e.z())
+    {
+
+        // trivial reject of segment wholely outside.
+        if (e.z()<bb.zMin()) return false;
+        if (s.z()>bb.zMax()) return false;
+
+        if (s.z()<bb.zMin())
+        {
+            // clip s to zMin.
+            s = s+_d_invZ*(bb.zMin()-s.z());
+        }
+
+        if (e.z()>bb.zMax())
+        {
+            // clip e to zMax.
+            e = s+_d_invZ*(bb.zMax()-s.z());
+        }
+    }
+    else
+    {
+        if (s.z()<bb.zMin()) return false;
+        if (e.z()>bb.zMax()) return false;
+
+        if (e.z()<bb.zMin())
+        {
+            // clip s to zMin.
+            e = s+_d_invZ*(bb.zMin()-s.z());
+        }
+
+        if (s.z()>bb.zMax())
+        {
+            // clip e to zMax.
+            s = s+_d_invZ*(bb.zMax()-s.z());
+        }
+    }
+
+    // OSG_NOTICE<<"clampped segment "<<s<<" "<<e<<std::endl;
+
+    // if (s==e) return false;
+
+    return true;
+}
+
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// QuadTree::BuildOptions
+
+QuadTree::BuildOptions::BuildOptions():
+_numVerticesProcessed(0),
+_targetNumTrianglesPerLeaf(4),
+_maxNumLevels(32),
+_numTriangles(0)
+{
+    //nop
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// QuadTree
+
+QuadTree::QuadTree()
+{
+}
+
+QuadTree::QuadTree(const QuadTree& rhs, const osg::CopyOp& copyop):
+    Shape(rhs, copyop),
+    _vertices(rhs._vertices),
+    _quadNodes(rhs._quadNodes),
+    _triangles(rhs._triangles)
+{
+}
+
+bool QuadTree::build(BuildOptions& options, osg::Geometry* geometry)
+{
+    BuildQuadTree build(*this);
+    return build.build(options, geometry);
+}
+
+bool QuadTree::intersect(const osg::Vec3d& start, const osg::Vec3d& end, LineSegmentIntersections& intersections) const
+{
+    if (_quadNodes.empty())
+    {
+        OSG_NOTICE<<"Warning: _quadTree is empty"<<std::endl;
+        return false;
+    }
+
+    unsigned int numIntersectionsBefore = intersections.size();
+
+    IntersectQuadTree intersector(*_vertices,
+                                _quadNodes,
+                                _triangles,
+                                intersections,
+                                start, end);
+
+    intersector.intersect(getNode(0), start, end);
+
+    return numIntersectionsBefore != intersections.size();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// QuadTreeBuilder
+QuadTreeBuilder::QuadTreeBuilder():
+    osg::NodeVisitor()
+{
+    setTraversalMode( TRAVERSE_ALL_CHILDREN );
+    this->setNodeMaskOverride( ~0 );
+
+    _quadTreePrototype = new QuadTree;
+}
+
+QuadTreeBuilder::QuadTreeBuilder(const QuadTreeBuilder& rhs) :
+    osg::NodeVisitor( rhs ),
+    _buildOptions(rhs._buildOptions),
+    _quadTreePrototype(rhs._quadTreePrototype)
+{
+}
+
+void QuadTreeBuilder::apply(osg::Geode& geode)
+{
+    for(unsigned int i=0; i<geode.getNumDrawables(); ++i)
+    {
+
+        osg::Geometry* geom = geode.getDrawable(i)->asGeometry();
+        if (geom)
+        {
+            QuadTree* previous = dynamic_cast<QuadTree*>(geom->getShape());
+            if (previous) continue;
+
+            osg::ref_ptr<osg::Object> obj = _quadTreePrototype->cloneType();
+            osg::ref_ptr<QuadTree> quadTree = dynamic_cast<QuadTree*>(obj.get());
+
+            if (quadTree.valid() && quadTree->build(_buildOptions, geom))
+            {
+                geom->setShape(quadTree.get());
+            }
+        }
+    }
+}
diff --git a/src/osgEarth/Random b/src/osgEarth/Random
index 6baaf9d..d98b1a0 100644
--- a/src/osgEarth/Random
+++ b/src/osgEarth/Random
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
@@ -63,6 +63,11 @@ namespace osgEarth
         virtual ~Random() { }
 
         /**
+         * Seeds the PRNG with a new seed.
+         */
+        void seed(unsigned s);
+
+        /**
          * Resets the PRNG to its initial state (initial seed).
          */
         void reset();
diff --git a/src/osgEarth/Random.cpp b/src/osgEarth/Random.cpp
index 4f96ce6..5bda04c 100644
--- a/src/osgEarth/Random.cpp
+++ b/src/osgEarth/Random.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -47,7 +47,7 @@ _seed  ( (unsigned)::time(0L) )
 
 Random::Random( unsigned seed, Random::Method method ) :
 _method( method ),
-_seed  ( seed == 0 ? (unsigned)::time(0L) : seed ) // seed=0 => time-based
+_seed  ( seed )
 {
     _next = _seed;
 }
@@ -61,6 +61,13 @@ _next  ( rhs._next )
 }
 
 void
+Random::seed(unsigned value)
+{
+    _seed = value;
+    reset();
+}
+
+void
 Random::reset()
 {
     _next = _seed;
diff --git a/src/osgEarth/Registry b/src/osgEarth/Registry
index 428360f..a271ece 100644
--- a/src/osgEarth/Registry
+++ b/src/osgEarth/Registry
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -23,6 +23,8 @@
 #include <osgEarth/Common>
 #include <osgEarth/CachePolicy>
 #include <osgEarth/SharedSARepo>
+#include <osgEarth/Containers>
+#include <osgEarth/TraversalData>
 #include <osgEarth/ShaderGenerator>
 #include <OpenThreads/ReentrantMutex>
 #include <OpenThreads/ScopedLock>
@@ -79,21 +81,24 @@ namespace osgEarth
         /** Access to the application-wide GDAL serialization mutex. GDAL is not thread-safe. */
         OpenThreads::ReentrantMutex& getGDALMutex();
 
-        /** The system-wide default cache. */
-        Cache* getCache() const;
-        void setCache( Cache* cache );
+        /** Gets a default cache object - based on environment settings - unless setDefaultCache
+            was called to override it. */
+        Cache* getDefaultCache() const;
+
+        /** Sets a default cache that a Map will use if none other is specified. */
+        void setDefaultCache(Cache* cache);
 
         /** The default cache policy (used when no policy is set elsewhere) */
-        const optional<CachePolicy>& defaultCachePolicy() const { return _defaultCachePolicy; }
+        const optional<CachePolicy>& defaultCachePolicy() const;
         void setDefaultCachePolicy( const CachePolicy& policy );
 
         /** The override cache policy (overrides all others if set) */
-        const optional<CachePolicy>& overrideCachePolicy() const { return _overrideCachePolicy; }
+        const optional<CachePolicy>& overrideCachePolicy() const;
         void setOverrideCachePolicy( const CachePolicy& policy );
 
         /** The default cache driver. */
         void setDefaultCacheDriverName( const std::string& name );
-        const std::string& getDefaultCacheDriverName() const { return _cacheDriver; }
+        const std::string& getDefaultCacheDriverName() const;
 
         /**
          * Given a CachePolicy, composites in the default and override cache policies
@@ -132,6 +137,7 @@ namespace osgEarth
         /**
          * The graphics hardware capabilities for this platform.
          */
+        bool hasCapabilities() const;
         const Capabilities& getCapabilities() const;
         void setCapabilities( Capabilities* caps );
         static const Capabilities& capabilities() { return instance()->getCapabilities(); }
@@ -245,6 +251,16 @@ namespace osgEarth
         optional<bool>& unRefImageDataAfterApply() { return _unRefImageDataAfterApply; }
         const optional<bool>& unRefImageDataAfterApply() const { return _unRefImageDataAfterApply; }
 
+        /**
+         * Adds a texture image unit number that osgEarth should never use.
+         */
+        void setTextureImageUnitOffLimits(int unit);
+        const std::set<int> getOffLimitsTextureImageUnits() const;
+
+        /** General purpose transient data store to support VisitorData in pre-osg 3.4 */
+        TransientUserDataStore& dataStore() { return _dataStore; }
+        const TransientUserDataStore& dataStore() const { return _dataStore; }
+
     protected:
         virtual ~Registry();
         Registry();
@@ -259,12 +275,14 @@ namespace osgEarth
         osg::ref_ptr<const Profile> _spherical_mercator_profile;
         osg::ref_ptr<const Profile> _cube_profile;
 
-        Threading::ReadWriteMutex _regMutex;  
+        mutable Threading::Mutex _regMutex;  
         int _numGdalMutexGets;
 
-        osg::ref_ptr<Cache> _cache;
-        optional<CachePolicy> _defaultCachePolicy;
-        optional<CachePolicy> _overrideCachePolicy;
+        mutable osg::ref_ptr<Cache>   _defaultCache;
+        mutable optional<CachePolicy> _defaultCachePolicy;
+        mutable optional<CachePolicy> _overrideCachePolicy;
+
+        mutable bool _overrideCachePolicyInitialized;
 
         typedef std::set<std::string> StringSet;
         StringSet _blacklistedFilenames;
@@ -296,7 +314,8 @@ namespace osgEarth
         osg::ref_ptr<StateSetCache> _stateSetCache;
 
         std::string _terrainEngineDriver;
-        std::string _cacheDriver;
+
+        mutable optional<std::string> _cacheDriver;
 
         typedef std::pair<std::string,std::string> Activity;
         struct ActivityLess {
@@ -312,6 +331,10 @@ namespace osgEarth
         optional<bool> _unRefImageDataAfterApply;
 
         osg::ref_ptr<ObjectIndex> _objectIndex;
+
+        std::set<int> _offLimitsTextureImageUnits;
+
+        TransientUserDataStore _dataStore;
     };
 }
 
diff --git a/src/osgEarth/Registry.cpp b/src/osgEarth/Registry.cpp
index c99250e..32a9439 100644
--- a/src/osgEarth/Registry.cpp
+++ b/src/osgEarth/Registry.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -63,7 +63,8 @@ _uidGen             ( 0 ),
 _caps               ( 0L ),
 _defaultFont        ( 0L ),
 _terrainEngineDriver( "mp" ),
-_cacheDriver        ( "filesystem" )
+_cacheDriver        ( "filesystem" ),
+_overrideCachePolicyInitialized( false )
 {
     // set up GDAL and OGR.
     OGRRegisterAll();
@@ -97,7 +98,7 @@ _cacheDriver        ( "filesystem" )
 
     // activate KMZ support
     osgDB::Registry::instance()->addArchiveExtension  ( "kmz" );
-    osgDB::Registry::instance()->addFileExtensionAlias( "kmz", "kml" );
+    //osgDB::Registry::instance()->addFileExtensionAlias( "kmz", "kml" );
 
     osgDB::Registry::instance()->addMimeTypeExtensionMapping( "application/vnd.google-earth.kml+xml", "kml" );
     osgDB::Registry::instance()->addMimeTypeExtensionMapping( "application/vnd.google-earth.kmz",     "kmz" );
@@ -117,59 +118,6 @@ _cacheDriver        ( "filesystem" )
     // set up our default r/w options to NOT cache archives!
     _defaultOptions = new osgDB::Options();
     _defaultOptions->setObjectCacheHint( osgDB::Options::CACHE_NONE );
-    
-    // activate no-cache mode from the environment
-    if ( ::getenv(OSGEARTH_ENV_NO_CACHE) )
-    {
-        _overrideCachePolicy = CachePolicy::NO_CACHE;
-        OE_INFO << LC << "NO-CACHE MODE set from environment" << std::endl;
-    }
-    else
-    {
-        // activate cache-only mode from the environment
-        if ( ::getenv(OSGEARTH_ENV_CACHE_ONLY) )
-        {
-            _overrideCachePolicy->usage() = CachePolicy::USAGE_CACHE_ONLY;
-            OE_INFO << LC << "CACHE-ONLY MODE set from environment" << std::endl;
-        }
-
-        // see if the environment specifies a default caching driver.
-        const char* cacheDriver = ::getenv(OSGEARTH_ENV_CACHE_DRIVER);
-        if ( cacheDriver )
-        {
-            setDefaultCacheDriverName( cacheDriver );
-            OE_INFO << LC << "Cache driver set from environment: "
-                << getDefaultCacheDriverName() << std::endl;
-        }        
-
-        // cache max age?
-        const char* cacheMaxAge = ::getenv(OSGEARTH_ENV_CACHE_MAX_AGE);
-        if ( cacheMaxAge )
-        {
-            TimeSpan maxAge = osgEarth::as<long>( std::string(cacheMaxAge), INT_MAX );
-            _overrideCachePolicy->maxAge() = maxAge;
-        }
-
-        // see if there's a cache in the envvar; if so, create a cache.
-        // Note: the value of the OSGEARTH_CACHE_PATH is not used here; rather
-        // it's used in the driver(s) itself.
-        const char* cachePath = ::getenv(OSGEARTH_ENV_CACHE_PATH);
-        if ( cachePath )
-        {
-            CacheOptions options;
-            options.setDriver( getDefaultCacheDriverName() );
-
-            osg::ref_ptr<Cache> cache = CacheFactory::create(options);
-            if ( cache->isOK() )
-            {
-                setCache( cache.get() );
-            }
-            else
-            {
-                OE_WARN << LC << "FAILED to initialize cache from environment" << std::endl;
-            }
-        }
-    }
 
     const char* teStr = ::getenv(OSGEARTH_ENV_TERRAIN_ENGINE_DRIVER);
     if ( teStr )
@@ -222,7 +170,7 @@ Registry::instance(bool erase)
 void 
 Registry::destruct()
 {
-    _cache = 0L;
+    //nop
 }
 
 
@@ -319,17 +267,12 @@ void
 Registry::setDefaultCachePolicy( const CachePolicy& value )
 {
     _defaultCachePolicy = value;
-    if ( !_overrideCachePolicy.isSet() )
-        _defaultCachePolicy->apply(_defaultOptions.get());
-    else
-        _overrideCachePolicy->apply(_defaultOptions.get());
 }
 
 void
 Registry::setOverrideCachePolicy( const CachePolicy& value )
 {
     _overrideCachePolicy = value;
-    _overrideCachePolicy->apply( _defaultOptions.get() );
 }
 
 bool
@@ -356,18 +299,105 @@ Registry::resolveCachePolicy(optional<CachePolicy>& cp) const
     return cp.isSet();
 }
 
+const std::string&
+Registry::getDefaultCacheDriverName() const
+{
+    if (!_cacheDriver.isSet())
+    {
+        Threading::ScopedMutexLock lock(_regMutex);
+
+        if (!_cacheDriver.isSet())
+        {
+            // see if the environment specifies a default caching driver.
+            const char* value = ::getenv(OSGEARTH_ENV_CACHE_DRIVER);
+            if ( value )
+            {
+                _cacheDriver = value;
+                OE_DEBUG << LC << "Cache driver set from environment: " << value << std::endl;
+            }        
+        }
+    }
+    return _cacheDriver.get();
+}
+
+const optional<CachePolicy>&
+Registry::defaultCachePolicy() const
+{
+    return _defaultCachePolicy;
+}
+
+const optional<CachePolicy>&
+Registry::overrideCachePolicy() const
+{
+    if ( !_overrideCachePolicyInitialized )
+    {
+        Threading::ScopedMutexLock lock(_regMutex);
+
+        if ( !_overrideCachePolicyInitialized )
+        {
+            // activate no-cache mode from the environment
+            if ( ::getenv(OSGEARTH_ENV_NO_CACHE) )
+            {
+                _overrideCachePolicy = CachePolicy::NO_CACHE;
+                OE_INFO << LC << "NO-CACHE MODE set from environment" << std::endl;
+            }
+            else
+            {
+                // activate cache-only mode from the environment
+                if ( ::getenv(OSGEARTH_ENV_CACHE_ONLY) )
+                {
+                    _overrideCachePolicy->usage() = CachePolicy::USAGE_CACHE_ONLY;
+                    OE_INFO << LC << "CACHE-ONLY MODE set from environment" << std::endl;
+                }
+
+                // cache max age?
+                const char* cacheMaxAge = ::getenv(OSGEARTH_ENV_CACHE_MAX_AGE);
+                if ( cacheMaxAge )
+                {
+                    TimeSpan maxAge = osgEarth::as<long>( std::string(cacheMaxAge), INT_MAX );
+                    _overrideCachePolicy->maxAge() = maxAge;
+                }
+            }
+
+            _overrideCachePolicyInitialized = true;
+        }
+    }
+    return _overrideCachePolicy;
+}
+
 osgEarth::Cache*
-Registry::getCache() const
+Registry::getDefaultCache() const
 {
-	return _cache.get();
+    if (!_defaultCache.valid())
+    {
+        std::string driverName = getDefaultCacheDriverName();
+
+        Threading::ScopedMutexLock lock(_regMutex);
+        if (!_defaultCache.valid())
+        {
+            const char* noCache = ::getenv(OSGEARTH_ENV_NO_CACHE);
+            if (noCache == 0L)
+            {
+                // see if there's a cache in the envvar; if so, create a cache.
+                // Note: the value of the OSGEARTH_CACHE_PATH is not used here; rather
+                // it's used in the driver(s) itself.
+                const char* cachePath = ::getenv(OSGEARTH_ENV_CACHE_PATH);
+                if (cachePath && !driverName.empty())
+                {
+                    CacheOptions cacheOptions;
+                    cacheOptions.setDriver(driverName);
+                    _defaultCache = CacheFactory::create(cacheOptions);
+                }
+            }
+        }
+    }
+    return _defaultCache.get();
 }
 
 void
-Registry::setCache( osgEarth::Cache* cache )
+Registry::setDefaultCache(Cache* cache)
 {
-	_cache = cache;
-    if ( cache )
-        cache->apply( _defaultOptions.get() );
+    _defaultCache = cache;
 }
 
 bool
@@ -401,6 +431,12 @@ Registry::getNumBlacklistedFilenames()
     return _blacklistedFilenames.size();
 }
 
+bool
+Registry::hasCapabilities() const
+{
+    return _caps.valid();
+}
+
 const Capabilities&
 Registry::getCapabilities() const
 {
@@ -465,14 +501,14 @@ Registry::getURIReadCallback() const
 void
 Registry::setDefaultFont( osgText::Font* font )
 {
-    Threading::ScopedWriteLock exclusive(_regMutex);
+    Threading::ScopedMutexLock exclusive(_regMutex);
     _defaultFont = font;
 }
 
 osgText::Font*
 Registry::getDefaultFont()
 {
-    Threading::ScopedReadLock shared(_regMutex);
+    Threading::ScopedMutexLock shared(_regMutex);
     return _defaultFont.get();
 }
 
@@ -494,7 +530,7 @@ osgDB::Options*
 Registry::cloneOrCreateOptions(const osgDB::Options* input)
 {
     osgDB::Options* newOptions = 
-        input ? static_cast<osgDB::Options*>(input->clone(osg::CopyOp::SHALLOW_COPY)) : 
+        input ? static_cast<osgDB::Options*>(input->clone(osg::CopyOp::DEEP_COPY_USERDATA)) : 
         new osgDB::Options();
 
     // clear the CACHE_ARCHIVES flag because it is evil
@@ -579,6 +615,7 @@ Registry::startActivity(const std::string& activity,
                         const std::string& value)
 {
     Threading::ScopedMutexLock lock(_activityMutex);
+    _activities.erase(Activity(activity,std::string()));
     _activities.insert(Activity(activity,value));
 }
 
@@ -636,6 +673,20 @@ Registry::getMimeTypeForExtension(const std::string& ext)
     return std::string();
 }
 
+void
+Registry::setTextureImageUnitOffLimits(int unit)
+{
+    Threading::ScopedMutexLock exclusive(_regMutex);
+    _offLimitsTextureImageUnits.insert(unit);
+}
+
+const std::set<int>
+Registry::getOffLimitsTextureImageUnits() const
+{
+    Threading::ScopedMutexLock exclusive(_regMutex);
+    return _offLimitsTextureImageUnits;
+}
+
 
 //Simple class used to add a file extension alias for the earth_tile to the earth plugin
 class RegisterEarthTileExtension
diff --git a/src/osgEarth/ResourceReleaser b/src/osgEarth/ResourceReleaser
new file mode 100644
index 0000000..b781761
--- /dev/null
+++ b/src/osgEarth/ResourceReleaser
@@ -0,0 +1,58 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+ * Copyright 2008-2014 Pelican Mapping
+ * http://osgearth.org
+ *
+ * osgEarth is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ */
+#ifndef OSGEARTH_RESOURCE_RELEASER
+#define OSGEARTH_RESOURCE_RELEASER 1
+
+#include <osgEarth/Common>
+#include <osgEarth/ThreadingUtils>
+#include <osg/Drawable>
+#include <vector>
+
+namespace osgEarth
+{
+    /**
+     * Scene graph node that will call releaseGLObjects() on objects
+     * during the Draw traversal.
+     */
+    class OSGEARTH_EXPORT ResourceReleaser : public osg::Drawable
+    {
+    public:
+        typedef std::vector<osg::ref_ptr<osg::Object> > ObjectList;
+
+        /** Construct a releaser. */
+        ResourceReleaser();
+
+        /** Submit and object for release. */
+        void push(osg::Object* node);
+
+        /** Submit a collection of objects for release. */
+        void push(const ObjectList& nodes);
+
+    public: // osg::Drawable
+
+        /** Calls releaseGLObjects() on all objects in the list, then clears the list. */
+        void drawImplementation(osg::RenderInfo& ri) const;
+
+    private:
+        mutable ObjectList _toRelease;
+        mutable Threading::Mutex _mutex;
+    };
+}
+
+#endif // OSGEARTH_RESOURCE_RELEASER
diff --git a/src/osgEarth/ResourceReleaser.cpp b/src/osgEarth/ResourceReleaser.cpp
new file mode 100644
index 0000000..d7b0cf5
--- /dev/null
+++ b/src/osgEarth/ResourceReleaser.cpp
@@ -0,0 +1,74 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+ * Copyright 2008-2014 Pelican Mapping
+ * http://osgearth.org
+ *
+ * osgEarth is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ */
+#include <osgEarth/ResourceReleaser>
+#include <osg/Version>
+
+using namespace osgEarth;
+
+#define LC "[ResourceReleaser] "
+
+
+ResourceReleaser::ResourceReleaser()
+{
+#if OSG_VERSION_GREATER_OR_EQUAL(3,4,0)
+    // ensure this node always gets traversed:
+    this->setCullingActive(false);
+#endif
+
+    // ensure the draw runs synchronously:
+    this->setDataVariance(DYNAMIC);
+
+    // force the draw to run every frame:
+    this->setUseDisplayList(false);
+}
+
+void
+ResourceReleaser::push(osg::Object* node)
+{
+    Threading::ScopedMutexLock lock(_mutex);
+    _toRelease.push_back(node);
+}
+
+void
+ResourceReleaser::push(const ObjectList& nodes)
+{
+    Threading::ScopedMutexLock lock(_mutex);
+    _toRelease.reserve(_toRelease.size() + nodes.size());
+    for (unsigned i = 0; i<nodes.size(); ++i)
+        _toRelease.push_back(nodes[i].get());
+}
+
+void
+ResourceReleaser::drawImplementation(osg::RenderInfo& ri) const
+{
+    if (!_toRelease.empty())
+    {
+        Threading::ScopedMutexLock lock(_mutex);
+        if (!_toRelease.empty())
+        {
+            for (ObjectList::const_iterator i = _toRelease.begin(); i != _toRelease.end(); ++i)
+            {
+                osg::Object* node = i->get();
+                node->releaseGLObjects(ri.getState());
+            }
+            OE_DEBUG << LC << "Released " << _toRelease.size() << " objects\n";
+            _toRelease.clear();
+        }
+    }
+}
diff --git a/src/osgEarth/Revisioning b/src/osgEarth/Revisioning
index 027edd8..beabb4d 100644
--- a/src/osgEarth/Revisioning
+++ b/src/osgEarth/Revisioning
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -91,7 +91,6 @@ namespace osgEarth
             return _alwaysDirty ? false : _revision == externalRevision;
         }
 
-    protected:
         Revisioned() : _alwaysDirty(false) { }
 
         /** dtor */
@@ -110,7 +109,7 @@ namespace osgEarth
 
 
     /**
-     * A TrackedMutable object is an object that can mark itself, and optionally
+     * A DirtyNotifier object is an object that can mark itself, and optionally
      * its dependent parents, dirty. This is analagous to OSG's "dirtyBound"
      * concept that can propagate up through a scene graph.
      *
diff --git a/src/osgEarth/Revisioning.cpp b/src/osgEarth/Revisioning.cpp
index 2a3d071..4af4634 100644
--- a/src/osgEarth/Revisioning.cpp
+++ b/src/osgEarth/Revisioning.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarth/ScreenSpaceLayout b/src/osgEarth/ScreenSpaceLayout
new file mode 100644
index 0000000..73dda9a
--- /dev/null
+++ b/src/osgEarth/ScreenSpaceLayout
@@ -0,0 +1,204 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+* Copyright 2016 Pelican Mapping
+* http://osgearth.org
+*
+* osgEarth is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* 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.
+*
+* You should have received a copy of the GNU Lesser General Public License
+* along with this program.  If not, see <http://www.gnu.org/licenses/>
+*/
+#ifndef OSGEARTH_SCREEN_SPACE_LAYOUT_H
+#define OSGEARTH_SCREEN_SPACE_LAYOUT_H 1
+
+#include <osgEarth/Common>
+#include <osgEarth/Config>
+#include <osg/Drawable>
+#include <osgUtil/RenderLeaf>
+#include <limits.h>
+
+#define OSGEARTH_SCREEN_SPACE_LAYOUT_BIN "osgearth_ScreenSpaceLayoutBin"
+
+namespace osgEarth
+{
+    /**
+     * Interface that exposes layout information.
+     */
+    class ScreenSpaceLayoutData : public osg::Referenced
+    {
+    public:
+        /** Install and return a LayoutData on a drawable. */
+        static ScreenSpaceLayoutData* getOrCreate(osg::Drawable* drawable) {
+            if (!drawable) return 0L;
+            ScreenSpaceLayoutData* ld = dynamic_cast<ScreenSpaceLayoutData*>(drawable->getUserData());
+            if (!ld) {
+                ld = new ScreenSpaceLayoutData();
+                drawable->setUserData(ld);
+            }
+            return ld;
+        }
+
+        /** Constructor */
+        ScreenSpaceLayoutData() :
+            _priority(0.0f),
+            _pixelOffset(0, 0) { }
+
+        /** Decluttering priority - FLT_MAX means don't declutter */
+        void setPriority(float value) { _priority = value; }
+        float getPriority() const     { return _priority; }
+
+        /** Offset from geoposition in screen pixels */
+        void setPixelOffset(const osg::Vec2s& value) { _pixelOffset = value; }
+        const osg::Vec2s& getPixelOffset() const     { return _pixelOffset; }
+
+        /** World point for label rotation reference */
+        void setAnchorPoint(const osg::Vec3d& value) { _anchorPoint = value; }
+        const osg::Vec3d& getAnchorPoint() const { return _anchorPoint; }
+
+        /** Reference point for label rotation reference */
+        void setProjPoint(const osg::Vec3d& value) { _refPoint = value; }
+        const osg::Vec3d& getProjPoint() const { return _refPoint; }
+
+    public:
+        float      _priority;
+        osg::Vec2s _pixelOffset;
+        osg::Vec3d _anchorPoint, _refPoint;
+
+    public:
+        virtual ~ScreenSpaceLayoutData() { }
+    };
+
+    /**
+     * Custom functor that compares two RenderLeaf's and returns TRUE if the left-hand one
+     * is higher priority, otherwise FALSE. You can call setDeclutterPriorityFunctor()
+     * to set a custom priority-sorting functor.
+     */
+    struct DeclutterSortFunctor : public osg::Referenced
+    {
+        virtual bool operator() ( const osgUtil::RenderLeaf* lhs, const osgUtil::RenderLeaf* rhs ) const =0;
+        virtual ~DeclutterSortFunctor() { }
+    };
+
+    /**
+     * Options to control the annotation decluttering engine.
+     */
+    class OSGEARTH_EXPORT ScreenSpaceLayoutOptions : public ConfigOptions
+    {
+    public:
+        ScreenSpaceLayoutOptions( const ConfigOptions& co =ConfigOptions() )
+            : ConfigOptions         ( co ),
+              _minAnimAlpha         ( 0.35f ),
+              _minAnimScale         ( 0.45f ),
+              _inAnimTime           ( 0.40f ),
+              _outAnimTime          ( 0.00f ),
+              _sortByPriority       ( false ),
+              _snapToPixel          ( true ),
+              _maxObjects           ( INT_MAX )
+        {
+            fromConfig(_conf);
+        }
+
+        virtual ~ScreenSpaceLayoutOptions() { }
+
+        /** Alpha value of a fully-occluded object */
+        optional<float>& minAnimationAlpha() { return _minAnimAlpha; }
+        const optional<float>& minAnimationAlpha() const { return _minAnimAlpha; }
+
+        /** Scale factor of a fully-occluded object */
+        optional<float>& minAnimationScale() { return _minAnimScale; }
+        const optional<float>& minAnimationScale() const { return _minAnimScale; }
+
+        /** Time (in seconds) for an object to transition from occluded to visible */
+        optional<float>& inAnimationTime() { return _inAnimTime; }
+        const optional<float>& inAnimationTime() const { return _inAnimTime; }
+
+        /** Time (in seconds) for an object to transition from visible to occluded */
+        optional<float>& outAnimationTime() { return _outAnimTime; }
+        const optional<float>& outAnimationTime() const { return _outAnimTime; }
+
+        /** If set, activate the AnnotationData priority-based sorting */
+        optional<bool>& sortByPriority() { return _sortByPriority; }
+        const optional<bool>& sortByPriority() const { return _sortByPriority; }
+
+        /** Whether to always start rendering text on a pixel boundary, thereby 
+          * minimizing filtering artifacts. */
+        optional<bool>& snapToPixel() { return _snapToPixel; }
+        const optional<bool>& snapToPixel() const { return _snapToPixel; }
+
+        /** Maximum number of objects to draw after sorting */
+        optional<unsigned>& maxObjects() { return _maxObjects; }
+        const optional<unsigned>& maxObjects() const { return _maxObjects; }
+
+    public:
+
+        Config getConfig() const;
+
+    protected:
+        optional<float>    _minAnimAlpha;
+        optional<float>    _minAnimScale;
+        optional<float>    _inAnimTime;
+        optional<float>    _outAnimTime;
+        optional<bool>     _sortByPriority;
+        optional<bool>     _snapToPixel;
+        optional<unsigned> _maxObjects;
+
+        void fromConfig( const Config& conf );
+    };
+
+    struct OSGEARTH_EXPORT ScreenSpaceLayout
+    {
+        /**
+         * Assigns a stateset to the screen-space layout engine.
+         * Drawables rendered while this stateset is active will be projected from
+         * scene space to 2D screen space with optional decluttering.
+         */
+        static void activate(osg::StateSet* stateSet, int binNum =13);
+
+        /**
+         * Deactivates the use of the screen-space layout engine for a stateset.
+         */
+        static void deactivate(osg::StateSet* stateSet);
+
+        /**
+         * Enables or disables decluttering globally.
+         */
+        static void setDeclutteringEnabled(bool enabled);
+
+        /**
+         * Applies the provided options to the layout engine.
+         */
+        static void setOptions(const ScreenSpaceLayoutOptions& options);
+
+        /**
+         * Fetches the current layout options
+         */
+        static const ScreenSpaceLayoutOptions& getOptions();
+
+    public: // advanced
+
+        /**
+         * Sets a functor to use to determine render leaf priority for declutter sorting.
+         */
+        static void setSortFunctor( DeclutterSortFunctor* f );
+
+        /**
+         * Clears a custom priority functor that was set using setDeclutterPriorityFunctor,
+         * reverting to the default behavior (which is to sort by distance from the camera).
+         */
+        static void clearSortFunctor();
+    };
+
+} // namespace osgEarth
+
+#endif //OSGEARTH_SCREEN_SPACE_LAYOUT_H
diff --git a/src/osgEarth/ScreenSpaceLayout.cpp b/src/osgEarth/ScreenSpaceLayout.cpp
new file mode 100644
index 0000000..0d11511
--- /dev/null
+++ b/src/osgEarth/ScreenSpaceLayout.cpp
@@ -0,0 +1,945 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+* Copyright 2016 Pelican Mapping
+* http://osgearth.org
+*
+* osgEarth is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* 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.
+*
+* You should have received a copy of the GNU Lesser General Public License
+* along with this program.  If not, see <http://www.gnu.org/licenses/>
+*/
+#include <osgEarth/ScreenSpaceLayout>
+#include <osgEarth/ThreadingUtils>
+#include <osgEarth/Containers>
+#include <osgEarth/Utils>
+#include <osgEarth/VirtualProgram>
+#include <osgEarth/Extension>
+#include <osgEarthAnnotation/BboxDrawable>
+#include <osgUtil/RenderBin>
+#include <osgUtil/StateGraph>
+#include <osgText/Text>
+#include <osg/UserDataContainer>
+#include <osg/ValueObject>
+#include <set>
+#include <algorithm>
+
+#define LC "[ScreenSpaceLayout] "
+
+#define FADE_UNIFORM_NAME "oe_declutter_fade"
+
+using namespace osgEarth;
+
+//----------------------------------------------------------------------------
+
+namespace
+{
+    // Sort wrapper to satisfy the template processor.
+    struct SortContainer
+    {
+        SortContainer( DeclutterSortFunctor& f ) : _f(f) { }
+        const DeclutterSortFunctor& _f;
+        bool operator()( const osgUtil::RenderLeaf* lhs, const osgUtil::RenderLeaf* rhs ) const 
+        {
+            return _f(lhs, rhs);
+        }
+    };
+
+    // Custom sorting functor that sorts drawables front-to-back, and when drawables share the
+    // same parent Geode, sorts them in traversal order.
+    struct SortFrontToBackPreservingGeodeTraversalOrder
+    {
+        bool operator()( const osgUtil::RenderLeaf* lhs, const osgUtil::RenderLeaf* rhs ) const
+        {
+            const osg::Node* lhsParentNode = lhs->getDrawable()->getParent(0);
+            if ( lhsParentNode == rhs->getDrawable()->getParent(0) )
+            {
+                const osg::Geode* geode = static_cast<const osg::Geode*>(lhsParentNode);
+                return geode->getDrawableIndex(lhs->getDrawable()) > geode->getDrawableIndex(rhs->getDrawable());
+            }
+            else
+            {
+                return ( lhs->_depth < rhs->_depth );
+            }
+        }
+    };
+
+    // Custom sorting functor that sorts drawables by Priority, and when drawables share the
+    // same parent Geode, sorts them in traversal order.
+    struct SortByPriorityPreservingGeodeTraversalOrder : public DeclutterSortFunctor
+    {
+        bool operator()( const osgUtil::RenderLeaf* lhs, const osgUtil::RenderLeaf* rhs ) const
+        {
+            const osg::Node* lhsParentNode = lhs->getDrawable()->getParent(0);
+            if ( lhsParentNode == rhs->getDrawable()->getParent(0) )
+            {
+                const osg::Geode* geode = static_cast<const osg::Geode*>(lhsParentNode);
+                return geode->getDrawableIndex(lhs->getDrawable()) > geode->getDrawableIndex(rhs->getDrawable());
+            }
+
+            else
+            {            
+                const ScreenSpaceLayoutData* lhsdata = dynamic_cast<const ScreenSpaceLayoutData*>(lhs->getDrawable()->getUserData());
+                float lhsPriority = lhsdata ? lhsdata->_priority : 0.0f;
+    
+                const ScreenSpaceLayoutData* rhsdata = dynamic_cast<const ScreenSpaceLayoutData*>(rhs->getDrawable()->getUserData());
+                float rhsPriority = rhsdata ? rhsdata->_priority : 0.0f;
+
+                float diff = lhsPriority - rhsPriority;
+
+                if ( diff != 0.0f )
+                    return diff > 0.0f;
+
+                // first fallback on depth:
+                diff = lhs->_depth - rhs->_depth;
+                if ( diff != 0.0f )
+                    return diff < 0.0f;
+
+                // then fallback on traversal order.
+                diff = float(lhs->_traversalNumber) - float(rhs->_traversalNumber);
+                return diff < 0.0f;
+            }
+        }
+    };
+
+    // Data structure shared across entire layout system.
+    struct ScreenSpaceLayoutContext : public osg::Referenced
+    {
+        ScreenSpaceLayoutOptions _options;
+    };
+
+    // records information about each drawable.
+    // TODO: a way to clear out this list when drawables go away
+    struct DrawableInfo
+    {
+        DrawableInfo() : _lastAlpha(1.0), _lastScale(1.0), _lastXY(-1.0, -1.0) { }
+        float _lastAlpha, _lastScale;
+        osg::Vec2d _lastXY;
+    };
+
+    typedef std::map<const osg::Drawable*, DrawableInfo> DrawableMemory;
+    
+    typedef std::pair<const osg::Node*, osg::BoundingBox> RenderLeafBox;
+
+    // Data structure stored one-per-View.
+    struct PerCamInfo
+    {
+        PerCamInfo() : _lastTimeStamp(0), _firstFrame(true) { }
+
+        // remembers the state of each drawable from the previous pass
+        DrawableMemory _memory;
+        
+        // re-usable structures (to avoid unnecessary re-allocation)
+        osgUtil::RenderBin::RenderLeafList _passed;
+        osgUtil::RenderBin::RenderLeafList _failed;
+        std::vector<RenderLeafBox>         _used;
+
+        // time stamp of the previous pass, for calculating animation speed
+        osg::Timer_t _lastTimeStamp;
+        bool _firstFrame;
+    };
+
+    static bool s_declutteringEnabledGlobally = true;
+
+    static const char* s_faderFS =
+        "#version " GLSL_VERSION_STR "\n"
+        GLSL_DEFAULT_PRECISION_FLOAT "\n"
+        "uniform float " FADE_UNIFORM_NAME ";\n"
+        "void oe_declutter_apply_fade(inout vec4 color) { \n"
+        "    color.a *= " FADE_UNIFORM_NAME ";\n"
+        "}\n";
+}
+
+//----------------------------------------------------------------------------
+
+void
+ScreenSpaceLayoutOptions::fromConfig( const Config& conf )
+{
+    conf.getIfSet( "min_animation_scale", _minAnimScale );
+    conf.getIfSet( "min_animation_alpha", _minAnimAlpha );
+    conf.getIfSet( "in_animation_time",   _inAnimTime );
+    conf.getIfSet( "out_animation_time",  _outAnimTime );
+    conf.getIfSet( "sort_by_priority",    _sortByPriority );
+    conf.getIfSet( "snap_to_pixel",       _snapToPixel );
+    conf.getIfSet( "max_objects",         _maxObjects );
+}
+
+Config
+ScreenSpaceLayoutOptions::getConfig() const
+{
+    Config conf;
+    conf.addIfSet( "min_animation_scale", _minAnimScale );
+    conf.addIfSet( "min_animation_alpha", _minAnimAlpha );
+    conf.addIfSet( "in_animation_time",   _inAnimTime );
+    conf.addIfSet( "out_animation_time",  _outAnimTime );
+    conf.addIfSet( "sort_by_priority",    _sortByPriority );
+    conf.addIfSet( "snap_to_pixel",       _snapToPixel );
+    conf.addIfSet( "max_objects",         _maxObjects );
+    return conf;
+}
+
+//----------------------------------------------------------------------------
+
+/**
+ * A custom RenderLeaf sorting algorithm for decluttering objects.
+ *
+ * First we sort the leaves front-to-back so that objects closer to the camera
+ * get higher priority. If you have installed a custom sorting functor,
+ * this is used instead.
+ *
+ * Next, we go though all the drawables and remove any that try to occupy
+ * already-occupied real estate in the 2D viewport. Objects that fail the test
+ * go on a "failed" list and are either completely removed from the display
+ * or transitioned to a secondary visual state (scaled down, alpha'd down)
+ * dependeing on the options setup.
+ *
+ * Drawables with the same parent (i.e., Geode) are treated as a group. As
+ * soon as one passes the occlusion test, all its siblings will automatically
+ * pass as well.
+ */
+struct /*internal*/ DeclutterSort : public osgUtil::RenderBin::SortCallback
+{
+    DeclutterSortFunctor* _customSortFunctor;
+    ScreenSpaceLayoutContext* _context;
+
+    PerObjectFastMap<osg::Camera*, PerCamInfo> _perCam;
+
+    /**
+     * Constructs the new sorter.
+     * @param f Custom declutter sorting predicate. Pass NULL to use the 
+     *          default sorter (sort by distance-to-camera).
+     */
+    DeclutterSort( ScreenSpaceLayoutContext* context, DeclutterSortFunctor* f = 0L )
+        : _context(context), _customSortFunctor(f)
+    {
+        //nop
+    }
+
+    // override.
+    // Sorts the bin. This runs in the CULL thread after the CULL traversal has completed.
+    void sortImplementation(osgUtil::RenderBin* bin)
+    {
+        osgUtil::RenderBin::RenderLeafList& leaves = bin->getRenderLeafList();
+
+        // first, sort the leaves:
+        if ( _customSortFunctor && s_declutteringEnabledGlobally )
+        {
+            // if there's a custom sorting function installed
+            bin->copyLeavesFromStateGraphListToRenderLeafList();
+            std::sort( leaves.begin(), leaves.end(), SortContainer( *_customSortFunctor ) );
+        }
+        else
+        {
+            // default behavior:
+            bin->copyLeavesFromStateGraphListToRenderLeafList();
+            std::sort( leaves.begin(), leaves.end(), SortFrontToBackPreservingGeodeTraversalOrder() );
+        }
+
+        // nothing to sort? bail out
+        if ( leaves.size() == 0 )
+            return;
+
+        // access the view-specific persistent data:
+        osg::Camera* cam   = bin->getStage()->getCamera();                
+        PerCamInfo& local = _perCam.get( cam );
+
+        osg::Timer_t now = osg::Timer::instance()->tick();
+        if (local._firstFrame)
+        {            
+            local._firstFrame = false;
+            local._lastTimeStamp = now;
+        }
+
+        // calculate the elapsed time since the previous pass; we'll use this for
+        // the animations                
+        float elapsedSeconds = osg::Timer::instance()->delta_s(local._lastTimeStamp, now);
+        local._lastTimeStamp = now;
+
+        // Reset the local re-usable containers
+        local._passed.clear();          // drawables that pass occlusion test
+        local._failed.clear();          // drawables that fail occlusion test
+        local._used.clear();            // list of occupied bounding boxes in screen space
+
+        // compute a window matrix so we can do window-space culling. If this is an RTT camera
+        // with a reference camera attachment, we actually want to declutter in the window-space
+        // of the reference camera. (e.g., for picking).
+        const osg::Viewport* vp = cam->getViewport();
+
+        osg::Matrix windowMatrix = vp->computeWindowMatrix();
+
+        osg::Vec3f  refCamScale(1.0f, 1.0f, 1.0f);
+        osg::Matrix refCamScaleMat;
+        osg::Matrix refWindowMatrix = windowMatrix;
+
+        if ( cam->isRenderToTextureCamera() )
+        {
+            osg::Camera* refCam = dynamic_cast<osg::Camera*>(cam->getUserData());
+            if ( refCam )
+            {
+                const osg::Viewport* refVP = refCam->getViewport();
+                refCamScale.set( vp->width() / refVP->width(), vp->height() / refVP->height(), 1.0 );
+                refCamScaleMat.makeScale( refCamScale );
+                refWindowMatrix = refVP->computeWindowMatrix();
+            }
+        }
+
+        // Track the parent nodes of drawables that are obscured (and culled). Drawables
+        // with the same parent node (typically a Geode) are considered to be grouped and
+        // will be culled as a group.
+        std::set<const osg::Node*> culledParents;
+
+        const ScreenSpaceLayoutOptions& options = _context->_options;
+        unsigned limit = *options.maxObjects();
+
+        bool snapToPixel = options.snapToPixel() == true;
+
+        osg::Matrix camVPW;
+        camVPW.postMult(cam->getViewMatrix());
+        camVPW.postMult(cam->getProjectionMatrix());
+        camVPW.postMult(refWindowMatrix);
+        //if (cam->getViewport())
+        //    camVPW.postMult(cam->getViewport()->computeWindowMatrix());
+
+        // Go through each leaf and test for visibility.
+        // Enforce the "max objects" limit along the way.
+        for(osgUtil::RenderBin::RenderLeafList::iterator i = leaves.begin(); 
+            i != leaves.end() && local._passed.size() < limit; 
+            ++i )
+        {
+            bool visible = true;
+
+            osgUtil::RenderLeaf* leaf = *i;
+            const osg::Drawable* drawable = leaf->getDrawable();
+            const osg::Node*     drawableParent = drawable->getParent(0);
+
+            const ScreenSpaceLayoutData* layoutData = dynamic_cast<const ScreenSpaceLayoutData*>(drawable->getUserData());
+
+            // transform the bounding box of the drawable into window-space.
+            osg::BoundingBox box = Utils::getBoundingBox(drawable);
+
+            osg::Vec3f offset;
+            osg::Quat rot;
+
+            if (layoutData)
+            {
+                // local transformation data
+                // and management of the label orientation (must be always readable)
+
+                bool isText = dynamic_cast<const osgText::Text*>(drawable) != 0L;
+
+                osg::Vec3d loc = layoutData->getAnchorPoint() * camVPW;
+                osg::Vec3d proj = layoutData->getProjPoint() * camVPW;
+                proj -= loc;
+                
+                float angle = atan2(proj.y(), proj.x());
+
+                if ( isText && (angle < - osg::PI / 2. || angle > osg::PI / 2.) )
+                {
+                    // avoid the label characters to be inverted:
+                    // use a symetric translation and adapt the rotation to be in the desired angles
+                    offset.set( -layoutData->_pixelOffset.x() - box.xMax() - box.xMin(),
+                                -layoutData->_pixelOffset.y() - box.yMax() - box.yMin(),
+                                0.f );
+                    angle -= osg::PI;
+                }
+                else
+                {
+                    offset.set( layoutData->_pixelOffset.x(), layoutData->_pixelOffset.y(), 0.f );
+                }
+
+                // handle the local rotation
+                if ( angle != 0.f )
+                {
+                    rot.makeRotate ( angle, osg::Vec3d(0, 0, 1) );
+                    osg::Vec3f ld = rot * ( osg::Vec3f(box.xMin(), box.yMin(), 0.) );
+                    osg::Vec3f lu = rot * ( osg::Vec3f(box.xMin(), box.yMax(), 0.) );
+                    osg::Vec3f ru = rot * ( osg::Vec3f(box.xMax(), box.yMax(), 0.) );
+                    osg::Vec3f rd = rot * ( osg::Vec3f(box.xMax(), box.yMin(), 0.) );
+                    if ( angle > - osg::PI / 2. && angle < osg::PI / 2.)
+                        box.set( std::min(ld.x(), lu.x()), std::min(ld.y(), rd.y()), 0,
+                            std::max(rd.x(), ru.x()), std::max(lu.y(), ru.y()), 0 );
+                    else
+                        box.set( std::min(ld.x(), lu.x()), std::min(lu.y(), ru.y()), 0,
+                            std::max(ld.x(), lu.x()), std::max(ld.y(), rd.y()), 0 );
+                }
+
+                offset = refCamScaleMat * offset;
+
+                // handle the local translation
+                box.xMin() += offset.x();
+                box.xMax() += offset.x();
+                box.yMin() += offset.y();
+                box.yMax() += offset.y();
+            }
+
+            static osg::Vec4d s_zero_w(0,0,0,1);
+            osg::Matrix MVP = (*leaf->_modelview.get()) * (*leaf->_projection.get());
+            osg::Vec4d clip = s_zero_w * MVP;
+            osg::Vec3d clip_ndc( clip.x()/clip.w(), clip.y()/clip.w(), clip.z()/clip.w() );
+            
+            // if we are using a reference camera (like for picking), we do the decluttering in
+            // its viewport so that they match. 
+            osg::Vec3f winPos    = clip_ndc * windowMatrix;
+            osg::Vec3f refWinPos = clip_ndc * refWindowMatrix;
+
+            // The "declutter" box is the box we use to reserve screen space.
+            // This must be unquantized regardless of whether snapToPixel is set.
+            box.set(
+                floor(refWinPos.x() + box.xMin()),
+                floor(refWinPos.y() + box.yMin()),
+                refWinPos.z(),
+                ceil(refWinPos.x() + box.xMax()),
+                ceil(refWinPos.y() + box.yMax()),
+                refWinPos.z() );
+
+            // if snapping is enabled, only snap when the camera stops moving.
+            bool quantize = snapToPixel;
+            if ( quantize )
+            {
+                DrawableInfo& info = local._memory[drawable];
+                
+                if ( info._lastXY.x() == winPos.x() && info._lastXY.y() == winPos.y() )
+                {
+                    // Quanitize the window draw coordinates to mitigate text rendering filtering anomalies.
+                    // Drawing text glyphs on pixel boundaries mitigates aliasing.
+                    // Adding 0.5 will cause the GPU to sample the glyph texels exactly on center.
+                    winPos.x() = floor(winPos.x()) + 0.5;
+                    winPos.y() = floor(winPos.y()) + 0.5;
+                }
+                else
+                {
+                    info._lastXY.set( winPos.x(), winPos.y() );
+                }
+            }            
+
+            if ( s_declutteringEnabledGlobally )
+            {
+                // A max priority => never occlude.
+                float priority = layoutData ? layoutData->_priority : 0.0f;
+
+                if ( priority == FLT_MAX )
+                {
+                    visible = true;
+                }
+                
+                // if this leaf is already in a culled group, skip it.
+                else if ( culledParents.find(drawableParent) != culledParents.end() )
+                {
+                    visible = false;
+                }
+
+                else
+                {
+                    // weed out any drawables that are obscured by closer drawables.
+                    // TODO: think about a more efficient algorithm - right now we are just using
+                    // brute force to compare all bbox's
+                    for( std::vector<RenderLeafBox>::const_iterator j = local._used.begin(); j != local._used.end(); ++j )
+                    {
+                        // only need a 2D test since we're in clip space
+                        bool isClear =
+                            box.xMin() > j->second.xMax() ||
+                            box.xMax() < j->second.xMin() ||
+                            box.yMin() > j->second.yMax() ||
+                            box.yMax() < j->second.yMin();
+
+                        // if there's an overlap (and the conflict isn't from the same drawable
+                        // parent, which is acceptable), then the leaf is culled.
+                        if ( !isClear && drawableParent != j->first )
+                        {
+                            visible = false;
+                            break;
+                        }
+                    }
+                }
+            }
+
+            if ( visible )
+            {
+                // passed the test, so add the leaf's bbox to the "used" list, and add the leaf
+                // to the final draw list.
+                local._used.push_back( std::make_pair(drawableParent, box) );
+                local._passed.push_back( leaf );
+            }
+
+            else
+            {
+                // culled, so put the parent in the parents list so that any future leaves
+                // with the same parent will be trivially rejected
+                culledParents.insert( drawable->getParent(0) );
+                local._failed.push_back( leaf );
+            }
+
+            // modify the leaf's modelview matrix to correctly position it in the 2D ortho
+            // projection when it's drawn later. We'll also preserve the scale.
+            osg::Matrix newModelView;
+            if ( rot.zeroRotation() )
+            {
+                newModelView.makeTranslate( osg::Vec3f(winPos.x() + offset.x(), winPos.y() + offset.y(), 0) );
+                newModelView.preMultScale( leaf->_modelview->getScale() * refCamScaleMat );
+            }
+            else
+            {
+                offset = rot * offset;
+                newModelView.makeTranslate( osg::Vec3f(winPos.x() + offset.x(), winPos.y() + offset.y(), 0) );
+                newModelView.preMultScale( leaf->_modelview->getScale() * refCamScaleMat );
+                newModelView.preMultRotate( rot );
+            }
+            
+            // Leaf modelview matrixes are shared (by objects in the traversal stack) so we 
+            // cannot just replace it unfortunately. Have to make a new one. Perhaps a nice
+            // allocation pool is in order here
+            leaf->_modelview = new osg::RefMatrix( newModelView );
+        }
+
+        // copy the final draw list back into the bin, rejecting any leaves whose parents
+        // are in the cull list.
+
+        if ( s_declutteringEnabledGlobally )
+        {
+            leaves.clear();
+            for( osgUtil::RenderBin::RenderLeafList::const_iterator i=local._passed.begin(); i != local._passed.end(); ++i )
+            {
+                osgUtil::RenderLeaf* leaf     = *i;
+                const osg::Drawable* drawable = leaf->getDrawable();
+
+                if ( culledParents.find( drawable->getParent(0) ) == culledParents.end() )
+                {
+                    DrawableInfo& info = local._memory[drawable];
+
+                    bool fullyIn = true;
+
+                    // scale in until at full scale:
+                    if ( info._lastScale != 1.0f )
+                    {
+                        fullyIn = false;
+                        info._lastScale += elapsedSeconds / std::max(*options.inAnimationTime(), 0.001f);
+                        if ( info._lastScale > 1.0f )
+                            info._lastScale = 1.0f;
+                    }
+
+                    if ( info._lastScale != 1.0f )
+                        leaf->_modelview->preMult( osg::Matrix::scale(info._lastScale,info._lastScale,1) );
+                    
+                    // fade in until at full alpha:
+                    if ( info._lastAlpha != 1.0f )
+                    {
+                        fullyIn = false;
+                        info._lastAlpha += elapsedSeconds / std::max(*options.inAnimationTime(), 0.001f);
+                        if ( info._lastAlpha > 1.0f )
+                            info._lastAlpha = 1.0f;
+                    }
+
+                    leaf->_depth = info._lastAlpha;
+                    leaves.push_back( leaf );                
+                }
+                else
+                {
+                    local._failed.push_back(leaf);
+                }
+            }
+
+            // next, go through the FAILED list and sort them into failure bins so we can draw
+            // them using a different technique if necessary.
+            for( osgUtil::RenderBin::RenderLeafList::const_iterator i=local._failed.begin(); i != local._failed.end(); ++i )
+            {
+                osgUtil::RenderLeaf* leaf =     *i;
+                const osg::Drawable* drawable = leaf->getDrawable();
+
+                DrawableInfo& info = local._memory[drawable];
+
+                bool isText = dynamic_cast<const osgText::Text*>(drawable) != 0L;
+                bool isBbox = dynamic_cast<const osgEarth::Annotation::BboxDrawable*>(drawable) != 0L;
+                bool fullyOut = true;
+
+                if ( info._lastScale != *options.minAnimationScale() )
+                {
+                    fullyOut = false;
+                    info._lastScale -= elapsedSeconds / std::max(*options.outAnimationTime(), 0.001f);
+                    if ( info._lastScale < *options.minAnimationScale() )
+                        info._lastScale = *options.minAnimationScale();
+                }
+
+                if ( info._lastAlpha != *options.minAnimationAlpha() )
+                {
+                    fullyOut = false;
+                    info._lastAlpha -= elapsedSeconds / std::max(*options.outAnimationTime(), 0.001f);
+                    if ( info._lastAlpha < *options.minAnimationAlpha() )
+                        info._lastAlpha = *options.minAnimationAlpha();
+                }
+
+                leaf->_depth = info._lastAlpha;
+
+                if ( (!isText && !isBbox) || !fullyOut )
+                {
+                    if ( info._lastAlpha > 0.01f && info._lastScale >= 0.0f )
+                    {
+                        leaves.push_back( leaf );
+
+                        // scale it:
+                        if ( info._lastScale != 1.0f )
+                            leaf->_modelview->preMult( osg::Matrix::scale(info._lastScale,info._lastScale,1) );
+                    }
+                }
+            }
+        }
+    }
+};
+
+namespace
+{
+    /**
+     * Custom draw routine for our declutter render bin.
+     */
+    struct DeclutterDraw : public osgUtil::RenderBin::DrawCallback
+    {
+        ScreenSpaceLayoutContext*                  _context;
+        PerThread< osg::ref_ptr<osg::RefMatrix> > _ortho2D;
+        osg::ref_ptr<osg::Uniform>                _fade;
+
+        /**
+         * Constructs the decluttering draw callback.
+         * @param context A shared context among all decluttering objects.
+         */
+        DeclutterDraw( ScreenSpaceLayoutContext* context )
+            : _context( context )
+        {
+            // create the fade uniform.
+            _fade = new osg::Uniform( osg::Uniform::FLOAT, FADE_UNIFORM_NAME );
+            _fade->set( 1.0f );
+        }
+
+        /**
+         * Draws a bin. Most of this code is copied from osgUtil::RenderBin::drawImplementation.
+         * The modifications are (a) skipping code to render child bins, (b) setting a bin-global
+         * projection matrix in orthographic space, and (c) calling our custom "renderLeaf()" method 
+         * instead of RenderLeaf::render()
+         */
+        void drawImplementation( osgUtil::RenderBin* bin, osg::RenderInfo& renderInfo, osgUtil::RenderLeaf*& previous )
+        {
+            osg::State& state = *renderInfo.getState();
+
+            unsigned int numToPop = (previous ? osgUtil::StateGraph::numToPop(previous->_parent) : 0);
+            if (numToPop>1) --numToPop;
+            unsigned int insertStateSetPosition = state.getStateSetStackSize() - numToPop;
+
+            if (bin->getStateSet())
+            {
+                state.insertStateSet(insertStateSetPosition, bin->getStateSet());
+            }
+
+            // apply a window-space projection matrix.
+            const osg::Viewport* vp = renderInfo.getCurrentCamera()->getViewport();
+            if ( vp )
+            {
+                //TODO see which is faster
+
+                osg::ref_ptr<osg::RefMatrix>& m = _ortho2D.get();
+                if ( !m.valid() )
+                    m = new osg::RefMatrix();
+
+                //m->makeOrtho2D( vp->x(), vp->x()+vp->width()-1, vp->y(), vp->y()+vp->height()-1 );
+                m->makeOrtho( vp->x(), vp->x()+vp->width()-1, vp->y(), vp->y()+vp->height()-1, -1000, 1000);
+                state.applyProjectionMatrix( m.get() );
+            }
+
+            // render the list
+            osgUtil::RenderBin::RenderLeafList& leaves = bin->getRenderLeafList();
+            for(osgUtil::RenderBin::RenderLeafList::reverse_iterator rlitr = leaves.rbegin();
+                rlitr!= leaves.rend();
+                ++rlitr)
+            {
+                osgUtil::RenderLeaf* rl = *rlitr;
+                renderLeaf( rl, renderInfo, previous );
+                previous = rl;
+            }
+
+            if ( bin->getStateSet() )
+            {
+                state.removeStateSet(insertStateSetPosition);
+            }
+        }
+
+        /**
+         * Renders a single leaf. We already applied the projection matrix, so here we only
+         * need to apply a modelview matrix that specifies the ortho offset of the drawable.
+         *
+         * Most of this code is copied from RenderLeaf::draw() -- but I removed all the code
+         * dealing with nested bins, since decluttering does not support them.
+         */
+        void renderLeaf( osgUtil::RenderLeaf* leaf, osg::RenderInfo& renderInfo, osgUtil::RenderLeaf*& previous )
+        {
+            osg::State& state = *renderInfo.getState();
+
+            // don't draw this leaf if the abort rendering flag has been set.
+            if (state.getAbortRendering())
+            {
+                //cout << "early abort"<<endl;
+                return;
+            }
+
+            state.applyModelViewMatrix( leaf->_modelview.get() );
+
+            if (previous)
+            {
+                // apply state if required.
+                osgUtil::StateGraph* prev_rg = previous->_parent;
+                osgUtil::StateGraph* prev_rg_parent = prev_rg->_parent;
+                osgUtil::StateGraph* rg = leaf->_parent;
+                if (prev_rg_parent!=rg->_parent)
+                {
+                    osgUtil::StateGraph::moveStateGraph(state,prev_rg_parent,rg->_parent);
+
+                    // send state changes and matrix changes to OpenGL.
+                    state.apply(rg->getStateSet());
+
+                }
+                else if (rg!=prev_rg)
+                {
+                    // send state changes and matrix changes to OpenGL.
+                    state.apply(rg->getStateSet());
+                }
+            }
+            else
+            {
+                // apply state if required.
+                osgUtil::StateGraph::moveStateGraph(state,NULL,leaf->_parent->_parent);
+
+                state.apply(leaf->_parent->getStateSet());
+            }
+
+            // if we are using osg::Program which requires OSG's generated uniforms to track
+            // modelview and projection matrices then apply them now.
+            if (state.getUseModelViewAndProjectionUniforms()) 
+                state.applyModelViewAndProjectionUniformsIfRequired();
+        
+            // apply the fading uniform
+            const osg::Program::PerContextProgram* pcp = state.getLastAppliedProgramObject();
+            if ( pcp )
+            {
+                // todo: find a way to optimize this..?
+                _fade->set( s_declutteringEnabledGlobally ? leaf->_depth : 1.0f );
+                pcp->apply( *_fade.get() );
+            }
+    
+            // draw the drawable
+            leaf->_drawable->draw(renderInfo);
+        
+            if (leaf->_dynamic)
+            {
+                state.decrementDynamicObjectCount();
+            }
+        }
+    };
+}
+
+//----------------------------------------------------------------------------
+
+/**
+ * The actual custom render bin
+ * This wants to be in the global scope for the dynamic registration to work,
+ * hence the annoyinging long class name
+ */
+class osgEarthScreenSpaceLayoutRenderBin : public osgUtil::RenderBin
+{
+public:
+    osgEarthScreenSpaceLayoutRenderBin()
+    {
+        _vpInstalled = false;
+
+        this->setName( OSGEARTH_SCREEN_SPACE_LAYOUT_BIN );
+        _context = new ScreenSpaceLayoutContext();
+        clearSortingFunctor();
+        setDrawCallback( new DeclutterDraw(_context.get()) );
+
+        // needs its own state set for special magic.
+        osg::StateSet* stateSet = new osg::StateSet();
+        this->setStateSet( stateSet );
+
+        //VirtualProgram* vp = VirtualProgram::getOrCreate(stateSet);
+        //vp->setFunction( "oe_declutter_apply_fade", s_faderFS, ShaderComp::LOCATION_FRAGMENT_COLORING, 0.5f );
+    }
+
+    osgEarthScreenSpaceLayoutRenderBin(const osgEarthScreenSpaceLayoutRenderBin& rhs, const osg::CopyOp& copy)
+        : osgUtil::RenderBin(rhs, copy),
+        _f(rhs._f.get()),
+        _context(rhs._context.get())
+    {        
+        // Set up a VP to do fading. Do it here so it doesn't happen until the first time 
+        // we clone the render bin. This play nicely with static initialization.
+        if (!_vpInstalled)
+        {
+            Threading::ScopedMutexLock lock(_vpMutex);
+            if (!_vpInstalled)
+            {
+                VirtualProgram* vp = VirtualProgram::getOrCreate(getStateSet());
+                vp->setFunction( "oe_declutter_apply_fade", s_faderFS, ShaderComp::LOCATION_FRAGMENT_COLORING, 0.5f );
+                _vpInstalled = true;
+                OE_INFO << LC << "Decluttering VP installed\n";
+            }
+        }
+    }
+    
+    virtual osg::Object* clone(const osg::CopyOp& copyop) const
+    {
+        return new osgEarthScreenSpaceLayoutRenderBin(*this, copyop);
+    }
+
+    void setSortingFunctor( DeclutterSortFunctor* f )
+    {
+        _f = f;
+        setSortCallback( new DeclutterSort(_context.get(), f) );
+    }
+
+    void clearSortingFunctor()
+    {
+        setSortCallback( new DeclutterSort(_context.get()) );
+    }
+
+    osg::ref_ptr<DeclutterSortFunctor> _f;
+    osg::ref_ptr<ScreenSpaceLayoutContext> _context;
+    static Threading::Mutex _vpMutex;
+    static bool _vpInstalled;
+};
+
+Threading::Mutex osgEarthScreenSpaceLayoutRenderBin::_vpMutex;
+bool osgEarthScreenSpaceLayoutRenderBin::_vpInstalled = false;
+
+//----------------------------------------------------------------------------
+
+void
+ScreenSpaceLayout::activate(osg::StateSet* stateSet, int binNum)
+{
+    if ( stateSet )
+    {
+        // the OVERRIDE prevents subsequent statesets from disabling the layout bin
+        stateSet->setRenderBinDetails(
+            binNum,
+            OSGEARTH_SCREEN_SPACE_LAYOUT_BIN,
+            osg::StateSet::OVERRIDE_RENDERBIN_DETAILS);
+
+        // Force a single shared layout bin per render stage
+        stateSet->setNestRenderBins( false );
+    }
+}
+
+void
+ScreenSpaceLayout::deactivate(osg::StateSet* stateSet)
+{
+    if (stateSet)
+    {
+        stateSet->setRenderBinToInherit();
+        stateSet->setNestRenderBins(true);
+    }
+}
+
+void
+ScreenSpaceLayout::setDeclutteringEnabled(bool enabled)
+{
+    s_declutteringEnabledGlobally = enabled;
+}
+
+void
+ScreenSpaceLayout::setSortFunctor( DeclutterSortFunctor* functor )
+{
+    // pull our prototype
+    osgEarthScreenSpaceLayoutRenderBin* bin = dynamic_cast<osgEarthScreenSpaceLayoutRenderBin*>(
+        osgUtil::RenderBin::getRenderBinPrototype( OSGEARTH_SCREEN_SPACE_LAYOUT_BIN ) );
+
+    if ( bin )
+    {
+        bin->setSortingFunctor( functor );
+    }
+}
+
+void
+ScreenSpaceLayout::clearSortFunctor()
+{
+    // pull our prototype
+    osgEarthScreenSpaceLayoutRenderBin* bin = dynamic_cast<osgEarthScreenSpaceLayoutRenderBin*>(
+        osgUtil::RenderBin::getRenderBinPrototype( OSGEARTH_SCREEN_SPACE_LAYOUT_BIN ) );
+
+    if ( bin )
+    {
+        bin->clearSortingFunctor();
+    }
+}
+
+void
+ScreenSpaceLayout::setOptions( const ScreenSpaceLayoutOptions& options )
+{
+    // pull our prototype
+    osgEarthScreenSpaceLayoutRenderBin* bin = dynamic_cast<osgEarthScreenSpaceLayoutRenderBin*>(
+        osgUtil::RenderBin::getRenderBinPrototype( OSGEARTH_SCREEN_SPACE_LAYOUT_BIN ) );
+
+    if ( bin )
+    {
+        // activate priority-sorting through the options.
+        if ( options.sortByPriority().isSetTo( true ) &&
+             bin->_context->_options.sortByPriority() == false )
+        {
+            ScreenSpaceLayout::setSortFunctor(new SortByPriorityPreservingGeodeTraversalOrder());
+        }
+        
+        // communicate the new options on the shared context.
+        bin->_context->_options = options;
+    }
+}
+
+const ScreenSpaceLayoutOptions&
+ScreenSpaceLayout::getOptions()
+{
+    static ScreenSpaceLayoutOptions s_defaultOptions;
+
+    // pull our prototype
+    osgEarthScreenSpaceLayoutRenderBin* bin = dynamic_cast<osgEarthScreenSpaceLayoutRenderBin*>(
+        osgUtil::RenderBin::getRenderBinPrototype( OSGEARTH_SCREEN_SPACE_LAYOUT_BIN ) );
+
+    if ( bin )
+    {
+        return bin->_context->_options;
+    }
+    else
+    {
+        return s_defaultOptions;
+    }
+}
+
+//----------------------------------------------------------------------------
+
+/** the actual registration. */
+extern "C" void osgEarth_declutter(void) {}
+static osgEarthRegisterRenderBinProxy<osgEarthScreenSpaceLayoutRenderBin> s_regbin(OSGEARTH_SCREEN_SPACE_LAYOUT_BIN);
+
+
+//----------------------------------------------------------------------------
+
+// Extension for configuring the decluterring/SSL options from an Earth file.
+namespace osgEarth
+{
+    class ScreenSpaceLayoutExtension : public Extension,
+                                       public ScreenSpaceLayoutOptions
+    {
+    public:
+        META_osgEarth_Extension(ScreenSpaceLayoutExtension);
+
+        ScreenSpaceLayoutExtension(const ConfigOptions& co) : ScreenSpaceLayoutOptions(co)
+        {
+            // sets the global default options.
+            ScreenSpaceLayout::setOptions(*this);
+        }
+    };
+
+    REGISTER_OSGEARTH_EXTENSION(osgearth_screen_space_layout, ScreenSpaceLayoutExtension);
+    REGISTER_OSGEARTH_EXTENSION(osgearth_decluttering,        ScreenSpaceLayoutExtension);
+}
+                                       
\ No newline at end of file
diff --git a/src/osgEarth/ShaderFactory b/src/osgEarth/ShaderFactory
index 52261ff..166d149 100644
--- a/src/osgEarth/ShaderFactory
+++ b/src/osgEarth/ShaderFactory
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
@@ -62,20 +62,12 @@ namespace osgEarth
         ShaderFactory();
 
         /**
-         * Creates a vertex shader main() function for use with VirtualPrograms.
-         * Do not call this function directly; VirtualProgram will call it to
-         * install its main() vertex function.
+         * Creates a Shader for each of the stages represented in the function map.
          */
-        virtual osg::Shader* createVertexShaderMain(
-            const ShaderComp::FunctionLocationMap& functions) const;
-        
-        /**
-         * Creates a fragment shader main() function for use with VirtualPrograms.
-         * Do not call this function directly; VirtualProgram will call it to
-         * install its main() fragment function.
-         */
-        virtual osg::Shader* createFragmentShaderMain(
-            const ShaderComp::FunctionLocationMap& functions) const;
+        virtual ShaderComp::StageMask createMains(
+            const ShaderComp::FunctionLocationMap&    functions,
+            const VirtualProgram::ShaderMap&          in_shaders,
+            std::vector< osg::ref_ptr<osg::Shader> >& out_mains) const;
 
         /**
          * Builds a shader function that executes an image filter chain.
@@ -121,6 +113,9 @@ namespace osgEarth
     };
 
 
+
+
+
 } // namespace osgEarth
 
 #endif // OSGEARTH_SHADER_FACTORY_H
diff --git a/src/osgEarth/ShaderFactory.cpp b/src/osgEarth/ShaderFactory.cpp
index 44ed8a2..66823a0 100755
--- a/src/osgEarth/ShaderFactory.cpp
+++ b/src/osgEarth/ShaderFactory.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -19,6 +19,7 @@
 #include <osgEarth/ShaderFactory>
 
 #include <osgEarth/ShaderUtils>
+#include <osgEarth/ShaderLoader>
 #include <osgEarth/Registry>
 #include <osgEarth/Capabilities>
 #include <osg/Shader>
@@ -67,232 +68,944 @@ ShaderFactory::ShaderFactory()
     _fragStageOrder = FRAGMENT_STAGE_ORDER_COLORING_LIGHTING;
 }
 
-osg::Shader*
-ShaderFactory::createVertexShaderMain(const FunctionLocationMap& functions) const
+
+#define SPACE_MODEL 0
+#define SPACE_VIEW  1
+#define SPACE_CLIP  2
+
+namespace
+{
+    struct Variable
+    {
+        std::string interp;      // interpolation qualifer (flat, etc.)
+        std::string type;        // float, vec4, etc.
+        std::string name;        // name without any array specifiers, etc.
+        std::string declaration; // name including array specifiers (for decl)
+        int         arraySize;   // 0 if not an array; else array size.
+    };
+
+    typedef std::vector<Variable> Variables;
+}
+
+
+ShaderComp::StageMask
+ShaderFactory::createMains(const ShaderComp::FunctionLocationMap&    functions,
+                           const VirtualProgram::ShaderMap&          in_shaders,
+                           std::vector< osg::ref_ptr<osg::Shader> >& out_shaders) const
 {
-    // collect the "model" stage functions:
-    FunctionLocationMap::const_iterator i = functions.find( LOCATION_VERTEX_MODEL );
-    const OrderedFunctionMap* modelStage = i != functions.end() ? &i->second : 0L;
+    StageMask stages =
+        ShaderComp::STAGE_VERTEX |
+        ShaderComp::STAGE_FRAGMENT;
+
+    FunctionLocationMap::const_iterator f;
+
+    // collect the "model" stage vertex functions:
+    f = functions.find( LOCATION_VERTEX_MODEL );
+    const OrderedFunctionMap* modelStage = f != functions.end() ? &f->second : 0L;
+
+    // collect the "view" stage vertex functions:
+    f = functions.find( LOCATION_VERTEX_VIEW );
+    const OrderedFunctionMap* viewStage = f != functions.end() ? &f->second : 0L;
+
+    // geometry shader functions:
+    f = functions.find( LOCATION_TESS_CONTROL );
+    const OrderedFunctionMap* tessControlStage = f != functions.end() ? &f->second : 0L;
 
-    // collect the "view" stage functions:
-    FunctionLocationMap::const_iterator j = functions.find( LOCATION_VERTEX_VIEW );
-    const OrderedFunctionMap* viewStage = j != functions.end() ? &j->second : 0L;
+    // geometry shader functions:
+    f = functions.find( LOCATION_TESS_EVALUATION );
+    const OrderedFunctionMap* tessEvalStage = f != functions.end() ? &f->second : 0L;
+
+    // geometry shader functions:
+    f = functions.find( LOCATION_GEOMETRY );
+    const OrderedFunctionMap* geomStage = f != functions.end() ? &f->second : 0L;
 
     // collect the "clip" stage functions:
-    FunctionLocationMap::const_iterator k = functions.find( LOCATION_VERTEX_CLIP );
-    const OrderedFunctionMap* clipStage = k != functions.end() ? &k->second : 0L;
+    f = functions.find( LOCATION_VERTEX_CLIP );
+    const OrderedFunctionMap* clipStage = f != functions.end() ? &f->second : 0L;
 
-    // header:
-    std::stringstream buf;
-    buf << 
-        "#version " GLSL_VERSION_STR "\n"
-        GLSL_DEFAULT_PRECISION_FLOAT "\n"
-        "uniform float " << RANGE << ";\n";
+    // fragment shader coloring functions:
+    f = functions.find( LOCATION_FRAGMENT_COLORING );
+    const OrderedFunctionMap* coloringStage = f != functions.end() ? &f->second : 0L;
 
-    // prototypes for model stage methods:
-    if ( modelStage )
+    // fragment shader lighting functions:
+    f = functions.find( LOCATION_FRAGMENT_LIGHTING );
+    const OrderedFunctionMap* lightingStage = f != functions.end() ? &f->second : 0L;
+
+    // fragment shader lighting functions:
+    f = functions.find( LOCATION_FRAGMENT_OUTPUT );
+    const OrderedFunctionMap* outputStage = f != functions.end() ? &f->second : 0L;
+
+    // what do we need to build?
+    bool hasGS  = geomStage        && !geomStage->empty();
+    bool hasTCS = tessControlStage && !tessControlStage->empty();
+    bool hasTES = tessEvalStage    && !tessEvalStage->empty();
+    bool hasFS  = true;
+    bool hasVS  = true;
+    
+    // where to insert the view/clip stage vertex functions:
+    bool viewStageInGS  = hasGS;
+    bool viewStageInTES = !viewStageInGS && hasTES;
+    bool viewStageInVS  = !viewStageInTES && !viewStageInGS;
+    
+    bool clipStageInGS  = hasGS;
+    bool clipStageInTES = hasTES && !hasGS;
+    bool clipStageInVS  = !clipStageInGS && !clipStageInTES;
+
+    // search for pragma varyings and build up our interface block definitions.
+    typedef std::set<std::string> VarDefs;
+    VarDefs varDefs;
+
+    // built-ins:
+    varDefs.insert( "vec4 vp_Color" );
+    varDefs.insert( "vec3 vp_Normal" );
+    varDefs.insert( "vec4 vp_Vertex" );
+
+    // parse the vp_varyings (which were injected by the ShaderLoader)
+    for(VirtualProgram::ShaderMap::const_iterator s = in_shaders.begin(); s != in_shaders.end(); ++s )
     {
-        for( OrderedFunctionMap::const_iterator i = modelStage->begin(); i != modelStage->end(); ++i )
+        osg::Shader* shader = s->data()._shader->getNominalShader();
+        if ( shader )
         {
-            buf << "void " << i->second._name << "(inout vec4 VertexMODEL); \n";
+            ShaderLoader::getAllPragmaValues(shader->getShaderSource(), "vp_varying", varDefs);
         }
     }
 
-    // prototypes for view stage methods:
-    if ( viewStage )
+    Variables vars;
+    for(VarDefs::iterator i = varDefs.begin(); i != varDefs.end(); ++i) 
     {
-        for( OrderedFunctionMap::const_iterator i = viewStage->begin(); i != viewStage->end(); ++i )
+        std::vector<std::string> tokens;        
+        StringTokenizer st;
+        st.addDelims( " \t", false );
+        st.addDelims( "[]", true );
+        st.tokenize( *i, tokens ); //(*i, tokens, " \t", "", false, true);
+        if ( tokens.size() >= 2 )
         {
-            buf << "void " << i->second._name << "(inout vec4 VertexVIEW); \n";
+            int p=0;
+            Variable v;
+            if ( tokens[p] == "flat" || tokens[p] == "nonperspective" || tokens[p] == "smooth" )
+            {
+                v.interp = tokens[p++];
+            }
+
+            if ( p+1 < tokens.size() )
+            {
+                v.type = tokens[p++];
+                v.name = tokens[p++];
+
+                // check for array
+                if ( p+2 < tokens.size() && tokens[p] == "[" && tokens[p+2] == "]" )
+                {
+                    v.declaration = Stringify() << v.type << " " << v.name << tokens[p] << tokens[p+1] << tokens[p+2];
+                    v.arraySize = as<int>(tokens[p+1], 0);
+                }
+                else
+                {
+                    v.declaration = Stringify() << v.type << " " << v.name;
+                    v.arraySize = 0;
+                }
+            }
+
+            if ( !v.type.empty() && !v.name.empty() && !v.declaration.empty() )
+            {
+                vars.push_back( v );
+            }
         }
     }
 
-    // prototypes for clip stage methods:
-    if ( clipStage )
+    std::string
+        gl_Color                     = "gl_Color",
+        gl_Vertex                    = "gl_Vertex",
+        gl_Normal                    = "gl_Normal",
+        gl_Position                  = "gl_Position",
+        gl_ModelViewMatrix           = "gl_ModelViewMatrix",
+        gl_ProjectionMatrix          = "gl_ProjectionMatrix",
+        gl_ModelViewProjectionMatrix = "gl_ModelViewProjectionMatrix",
+        gl_NormalMatrix              = "gl_NormalMatrix",
+        gl_FrontColor                = "gl_FrontColor";
+
+    std::string glMatrixUniforms = "";
+
+    #define GLSL_330 GLSL_VERSION_STR // "330 compatibility"
+
+#if defined(OSG_GL3_AVAILABLE) || defined(OSG_GL4_AVAILABLE)
+#   define GLSL_400 "400"
+#else
+#   define GLSL_400 "400 compatibility"
+#endif
+
+    // use GLSL 400 if it's avaiable since that will give the developer
+    // access to double-precision types.
+    bool use400 = 
+        Registry::instance()->hasCapabilities() &&
+        Registry::capabilities().getGLSLVersionInt() >= 400;
+
+    std::string tcs_glsl_version(GLSL_400);
+    std::string tes_glsl_version(GLSL_400);
+
+    std::string vs_glsl_version = use400 ? GLSL_400 : GLSL_330;
+    std::string fs_glsl_version = use400 ? GLSL_400 : GLSL_330;
+    std::string gs_glsl_version = use400 ? GLSL_400 : GLSL_330;
+
+    // build the vertex data interface block definition:
+    std::string vertdata;
     {
-        for( OrderedFunctionMap::const_iterator i = clipStage->begin(); i != clipStage->end(); ++i )
-        {
-            buf << "void " << i->second._name << "(inout vec4 VertexCLIP); \n";
-        }
+        std::stringstream buf;
+        buf << "VP_PerVertex { \n";
+        for(Variables::const_iterator i = vars.begin(); i != vars.end(); ++i)
+            buf << INDENT << i->interp << (i->interp.empty()?"":" ") << i->declaration << "; \n";
+        buf << "}";
+        vertdata = buf.str();
     }
 
-    // main:
-    buf <<
-        "varying vec4 osg_FrontColor; \n"
-        "varying vec3 oe_Normal; \n"
-        "void main(void) \n"
-        "{ \n"
-        INDENT "osg_FrontColor = gl_Color; \n"
-        INDENT "vec4 vertex = gl_Vertex; \n";
-
-    // call Model stage methods.
-    if ( modelStage )
+    // TODO: perhaps optimize later to not include things we don't need in the FS
+    std::string fragdata = vertdata;
+
+    // Build the vertex shader.
+    if ( hasVS )
     {
-        buf << INDENT "oe_Normal = gl_Normal; \n";
+        stages |= ShaderComp::STAGE_VERTEX;
 
-        for( OrderedFunctionMap::const_iterator i = modelStage->begin(); i != modelStage->end(); ++i )
+        std::stringstream buf;
+
+        buf <<
+            "#version " << vs_glsl_version << "\n"
+            "#pragma vp_name VP Vertex Shader Main\n"
+            "#extension GL_ARB_gpu_shader5 : enable \n";
+
+        buf << "\n// Vertex stage globals:\n";
+        for(Variables::const_iterator i = vars.begin(); i != vars.end(); ++i)
+            buf << i->declaration << "; \n";
+        
+        buf << "\n// Vertex stage outputs:\n";
+        if ( hasGS || hasTCS )
+            buf << "out " << vertdata << " vp_out; \n";
+        else
+            buf << "out " << fragdata << " vp_out; \n";
+
+        // prototype functions:
+        if ( modelStage || (viewStage && viewStageInVS) || (clipStage && clipStageInVS) )
         {
-            insertRangeConditionals( i->second, buf );
-            buf << INDENT << i->second._name << "(vertex); \n";
+            buf << "\n// Function declarations:\n";
         }
 
-        buf << INDENT << "oe_Normal = normalize(gl_NormalMatrix * oe_Normal); \n";
-    }
-    else
-    {
-        buf << INDENT << "oe_Normal = normalize(gl_NormalMatrix * gl_Normal); \n";
-    }
+        if ( modelStage )
+        {
+            for( OrderedFunctionMap::const_iterator i = modelStage->begin(); i != modelStage->end(); ++i )
+            {
+                buf << "void " << i->second._name << "(inout vec4); \n";
+            }
+        }
 
-    // call View stage methods.
-    if ( viewStage )
-    {
-        buf << INDENT "vertex = gl_ModelViewMatrix * vertex; \n";
+        // prototypes for view stage methods:
+        if ( viewStage != 0L && viewStageInVS )
+        {
+            for( OrderedFunctionMap::const_iterator i = viewStage->begin(); i != viewStage->end(); ++i )
+            {
+                buf << "void " << i->second._name << "(inout vec4); \n";
+            }
+        }
 
-        for( OrderedFunctionMap::const_iterator i = viewStage->begin(); i != viewStage->end(); ++i )
+        // prototypes for clip stage methods:
+        if ( clipStage != 0L && clipStageInVS )
         {
-            insertRangeConditionals( i->second, buf );
-            buf << INDENT << i->second._name << "(vertex); \n";
+            for( OrderedFunctionMap::const_iterator i = clipStage->begin(); i != clipStage->end(); ++i )
+            {
+                buf << "void " << i->second._name << "(inout vec4); \n";
+            }
         }
-    }
 
-    // call Clip stage methods.
-    if ( clipStage )
-    {
-        if ( viewStage )
+        buf <<
+            "\nvoid main(void) \n"
+            "{ \n"
+            INDENT "vp_Vertex = " << gl_Vertex << "; \n"
+            INDENT "vp_Normal = " << gl_Normal << "; \n"
+            INDENT "vp_Color  = " << gl_Color  << "; \n";
+
+        if ( modelStage )
+        {
+            for( OrderedFunctionMap::const_iterator i = modelStage->begin(); i != modelStage->end(); ++i )
+            {
+                //insertRangeConditionals( i->second, buf );
+                buf << INDENT << i->second._name << "(vp_Vertex); \n";
+            }
+        }
+
+        if ( viewStageInVS )
+        {
+            if ( viewStage )
+            {
+                buf <<
+                    INDENT << "vp_Vertex = " << gl_ModelViewMatrix << " * vp_Vertex; \n"
+                    INDENT << "vp_Normal = normalize(" << gl_NormalMatrix    << " * vp_Normal); \n";
+
+                for( OrderedFunctionMap::const_iterator i = viewStage->begin(); i != viewStage->end(); ++i )
+                {
+                    buf << INDENT << i->second._name << "(vp_Vertex); \n";
+                }
+            }
+
+            if ( clipStageInVS )
+            {
+                if ( clipStage )
+                {
+                    if ( viewStage )
+                    {
+                        buf << INDENT << "vp_Vertex = " << gl_ProjectionMatrix << " * vp_Vertex; \n";
+                    }
+                    else
+                    {
+                        buf <<
+                            INDENT << "vp_Vertex = " << gl_ModelViewProjectionMatrix << " * vp_Vertex; \n"
+                            INDENT << "vp_Normal = normalize(" << gl_NormalMatrix << " * vp_Normal); \n";
+                    }
+
+                    for( OrderedFunctionMap::const_iterator i = clipStage->begin(); i != clipStage->end(); ++i )
+                    {
+                        buf << INDENT << i->second._name << "(vp_Vertex); \n";
+                    }
+                }
+            }
+        }
+
+        // if there are no further vertex-processing stages, transform the position into clip coordinates
+        // for the fragment shader now:
+        if ( !hasGS && !hasTCS )
         {
-            buf << INDENT "vertex = gl_ProjectionMatrix * vertex; \n";
+            if ( clipStage )
+                buf << INDENT "gl_Position = vp_Vertex; \n";
+            else if ( viewStage )
+                buf << INDENT "gl_Position = " << gl_ProjectionMatrix << " * vp_Vertex; \n";
+            else
+                buf << INDENT "gl_Position = " << gl_ModelViewProjectionMatrix << " * vp_Vertex; \n";
         }
+
+        // otherwise, pass it along as-is.
         else
         {
-            buf << INDENT "vertex = gl_ModelViewProjectionMatrix * vertex; \n";
+            buf << INDENT "gl_Position = vp_Vertex; \n";
         }
 
-        for( OrderedFunctionMap::const_iterator i = clipStage->begin(); i != clipStage->end(); ++i )
+
+        if ( hasTCS || hasGS || hasFS )
         {
-            insertRangeConditionals( i->second, buf );
-            buf << INDENT << i->second._name << "(vertex); \n";
+            // Copy stage globals to output block:
+            for(Variables::const_iterator i = vars.begin(); i != vars.end(); ++i)
+                buf << INDENT << "vp_out." << i->name << " = " << i->name << "; \n";
         }
-    }
 
-    // finally, emit the position vertex.
-    if ( clipStage )
-    {
-        buf << INDENT "gl_Position = vertex; \n";
-    }
-    else if ( viewStage )
-    {
-        buf << INDENT "gl_Position = gl_ProjectionMatrix * vertex; \n";
+        buf << "} \n";
+
+        osg::Shader* vertexShader = new osg::Shader( osg::Shader::VERTEX, buf.str() );
+        vertexShader->setName( "main(vertex)" );
+        out_shaders.push_back( vertexShader );
     }
-    else
+
+
+    //.................................................................................
+    
+#if !defined(OSG_GL_FIXED_FUNCTION_AVAILABLE)
+
+    // for all stages EXCEPT vertex, we will switch over to the OSG aliased
+    // matrix uniforms. Why except vertex? OSG [3.4] does something internally to
+    // convert these for hte VERTEX shader stage only... and if you try to 
+    // use them anyway, they won't work :(
+
+    gl_ModelViewMatrix           = "osg_ModelViewMatrix",
+    gl_ProjectionMatrix          = "osg_ProjectionMatrix",
+    gl_ModelViewProjectionMatrix = "osg_ModelViewProjectionMatrix",
+    gl_NormalMatrix              = "osg_NormalMatrix",
+    gl_FrontColor                = "osg_FrontColor";
+    
+    glMatrixUniforms =
+        "uniform mat4 osg_ModelViewMatrix;\n"
+        "uniform mat4 osg_ModelViewProjectionMatrix;\n"
+        "uniform mat4 osg_ProjectionMatrix;\n"
+        "uniform mat3 osg_NormalMatrix;\n";
+#endif
+
+
+    if ( hasTCS )
     {
-        buf << INDENT "gl_Position = gl_ModelViewProjectionMatrix * vertex; \n";
-    }
+        stages |= ShaderComp::STAGE_TESSCONTROL;
+        std::stringstream buf;
 
-    buf << "} \n";
+        buf << "#version " << tcs_glsl_version << "\n"
+            << "#pragma vp_name VP Tessellation Control Shader (TCS) Main\n"
+            // For gl_MaxPatchVertices
+            << "#extension GL_NV_gpu_shader5 : enable\n";
 
-    std::string str;
-    str = buf.str();
-    osg::Shader* shader = new osg::Shader( osg::Shader::VERTEX, str );
-    shader->setName( "main(vert)" );
-    return shader;
-}
+        buf << glMatrixUniforms << "\n";
 
+        if ( hasVS )
+        {
+              buf << "\n// TCS stage inputs:\n"
+                 << "in " << vertdata << " vp_in [gl_MaxPatchVertices]; \n";
+        }
 
-osg::Shader*
-ShaderFactory::createFragmentShaderMain(const FunctionLocationMap& functions) const
-{
-    FunctionLocationMap::const_iterator i = functions.find( LOCATION_FRAGMENT_COLORING );
-    const OrderedFunctionMap* coloring = i != functions.end() ? &i->second : 0L;
+        // The TES is mandatory.
+        buf << "\n// TCS stage outputs to TES: \n"
+            << "out " << vertdata << " vp_out [gl_MaxPatchVertices]; \n";
 
-    FunctionLocationMap::const_iterator j = functions.find( LOCATION_FRAGMENT_LIGHTING );
-    const OrderedFunctionMap* lighting = j != functions.end() ? &j->second : 0L;
+        // Stage globals.
+        buf << "\n// TCS stage globals \n";
+        for(Variables::const_iterator i = vars.begin(); i != vars.end(); ++i)
+            buf << i->declaration << "; \n";
 
-    FunctionLocationMap::const_iterator k = functions.find( LOCATION_FRAGMENT_OUTPUT );
-    const OrderedFunctionMap* output = k != functions.end() ? &k->second : 0L;
+        // Helper functions:
+        // TODO: move this into its own osg::Shader so it can be shared.
+        buf << "\nvoid VP_LoadVertex(in int index) \n"
+            << "{ \n";
+        
+        // Copy input block to stage globals:
+        for(Variables::const_iterator i = vars.begin(); i != vars.end(); ++i)
+            buf << INDENT << i->name << " = vp_in[index]." << i->name << "; \n";
 
-    std::stringstream buf;
-    buf << "#version " << GLSL_VERSION_STR << "\n"
-        << GLSL_DEFAULT_PRECISION_FLOAT << "\n"
-        << "uniform float " << RANGE << ";\n";
+        buf << "} \n";
+        
+        // Function declares
+        if ( tessControlStage )
+        {
+            buf << "\n// Function declarations:\n";
+            for( OrderedFunctionMap::const_iterator i = tessControlStage->begin(); i != tessControlStage->end(); ++i )
+                buf << "void " << i->second._name << "(); \n";
+        }
 
-    if ( coloring )
-    {
-        for( OrderedFunctionMap::const_iterator i = coloring->begin(); i != coloring->end(); ++i )
+        // Main
+        buf << "\nvoid main(void) \n"
+            << "{ \n"
+            << INDENT "// copy default outputs: \n";
+                
+        // Copy in to globals
+        for(Variables::const_iterator i = vars.begin(); i != vars.end(); ++i)
+            buf << INDENT << i->name << " = vp_in[gl_InvocationID]." << i->name << "; \n";
+
+        // Invoke functions
+        if ( tessControlStage )
         {
-            buf << "void " << i->second._name << "( inout vec4 color ); \n";
+            for( OrderedFunctionMap::const_iterator i = tessControlStage->begin(); i != tessControlStage->end(); ++i )
+                buf << INDENT << i->second._name << "(); \n";
         }
+                
+        // Copy globals to out.
+        for(Variables::const_iterator i = vars.begin(); i != vars.end(); ++i)
+            buf << INDENT << "vp_out[gl_InvocationID]." << i->name << " = " << i->name << "; \n";
+
+        buf << "} \n";
+        
+        std::string str = buf.str();
+        osg::Shader* tcsShader = new osg::Shader(osg::Shader::TESSCONTROL, str);
+        tcsShader->setName("VP TCS");
+        out_shaders.push_back( tcsShader );
     }
 
-    if ( lighting )
+
+    //.................................................................................
+
+
+    if ( hasTES )
     {
-        for( OrderedFunctionMap::const_iterator i = lighting->begin(); i != lighting->end(); ++i )
+        stages |= ShaderComp::STAGE_TESSEVALUATION;
+
+        std::stringstream buf;
+
+        buf << "#version " << tes_glsl_version << "\n"
+            << "#pragma vp_name VP Tessellation Evaluation (TES) Shader MAIN\n";
+
+        buf << glMatrixUniforms << "\n";
+
+        buf << "\n// TES stage inputs (required):\n"
+            << "in " << vertdata << " vp_in []; \n";
+        
+        // Declare stage globals.
+        buf << "\n// TES stage globals: \n";
+        for(Variables::const_iterator i = vars.begin(); i != vars.end(); ++i)
+            buf << i->declaration << "; \n";
+        
+        buf << "\n// TES stage outputs: \n";
+        if ( hasGS )
+            buf << "out " << vertdata << " vp_out; \n";
+        else
+            buf << "out " << fragdata << " vp_out; \n";
+
+        std::set<std::string> types;
+        for(Variables::const_iterator i=vars.begin(); i != vars.end(); ++i)
+            types.insert(i->type);
+
+        for(std::set<std::string>::const_iterator i = types.begin(); i != types.end(); ++i)
+        {
+            buf << *i << " VP_Interpolate3(" << *i << "," << *i << "," << *i << ");\n";
+        }       
+
+        //buf <<
+        //    "\n// TES user-supplied interpolators: \n"
+        //    "float VP_Interpolate3(float,float,float); \n"
+        //    "vec2  VP_Interpolate3(vec2,vec2,vec2); \n"
+        //    "vec3  VP_Interpolate3(vec3,vec3,vec3); \n"
+        //    "vec4  VP_Interpolate3(vec4,vec4,vec4); \n";
+
+#if 0
+        buf <<
+            "\n// TES user-supplied interpolators: \n"
+            "float VP_Interpolate16(float,float,float,float,float,float,float,float,float,float,float,float,float,float,float,float); \n"
+            "vec2  VP_Interpolate16(vec2,vec2,vec2,vec2,vec2,vec2,vec2,vec2,vec2,vec2,vec2,vec2,vec2,vec2,vec2,vec2); \n"
+            "vec3  VP_Interpolate16(vec3,vec3,vec3,vec3,vec3,vec3,vec3,vec3,vec3,vec3,vec3,vec3,vec3,vec3,vec3,vec3); \n"
+            "vec4  VP_Interpolate16(vec4,vec4,vec4,vec4,vec4,vec4,vec4,vec4,vec4,vec4,vec4,vec4,vec4,vec4,vec4,vec4); \n";
+#endif
+
+        if ( tessEvalStage || (viewStage && viewStageInTES) || (clipStage && clipStageInTES) )
+        {
+            buf << "\n// Function declarations:\n";
+            if ( tessEvalStage )
+            {
+                for( OrderedFunctionMap::const_iterator i = tessEvalStage->begin(); i != tessEvalStage->end(); ++i )
+                {
+                    buf << "void " << i->second._name << "(); \n";
+                }
+            }
+
+            if (viewStage && viewStageInTES)
+            {
+                for( OrderedFunctionMap::const_iterator i = viewStage->begin(); i != viewStage->end(); ++i )
+                {
+                    buf << "void " << i->second._name << "(inout vec4); \n";
+                }
+            }
+
+            if (clipStage && clipStageInTES) 
+            {
+                for( OrderedFunctionMap::const_iterator i = clipStage->begin(); i != clipStage->end(); ++i )
+                {
+                    buf << "void " << i->second._name << "(inout vec4); \n";
+                }
+            }
+
+            // Helper functions:
+            buf << "\nvoid VP_LoadVertex(in int index) \n"
+                << "{ \n";
+        
+            // Copy input block to stage globals:
+            for(Variables::const_iterator i = vars.begin(); i != vars.end(); ++i)
+                buf << INDENT << i->name << " = vp_in[index]." << i->name << "; \n";
+
+            buf << "} \n";
+
+            buf << "\nvoid VP_Interpolate3() \n"
+                << "{ \n";            
+            for(Variables::const_iterator i = vars.begin(); i != vars.end(); ++i)
+            {
+                if ( i->interp != "flat" )
+                {
+                    if ( i->arraySize == 0 )
+                    {
+                        buf << INDENT << i->name << " = VP_Interpolate3"
+                            << "( vp_in[0]." << i->name
+                            << ", vp_in[1]." << i->name
+                            << ", vp_in[2]." << i->name << " ); \n";
+                    }
+                    else
+                    {
+                        for(int n=0; n<i->arraySize; ++n)
+                        {
+                            buf << INDENT << i->name << "[" << n << "] = VP_Interpolate3"
+                                << "( vp_in[0]." << i->name << "[" << n << "]"
+                                << ", vp_in[1]." << i->name << "[" << n << "]"
+                                << ", vp_in[2]." << i->name << "[" << n << "] ); \n";
+                        }
+                    }
+                }
+                else
+                {
+                    buf << INDENT << i->name << " = vp_in[0]." << i->name << "; \n";
+                }
+            }
+            buf << "} \n";
+
+            buf << "\nvoid VP_EmitVertex() \n"
+                << "{ \n";
+
+            int space = SPACE_MODEL;
+
+            if ( viewStage && viewStageInTES )
+            {
+                buf << INDENT << "vp_Vertex = " << gl_ModelViewMatrix << " * vp_Vertex; \n"
+                    << INDENT << "vp_Normal = normalize(" << gl_NormalMatrix << " * vp_Normal); \n";
+                space = SPACE_VIEW;
+
+                for( OrderedFunctionMap::const_iterator i = viewStage->begin(); i != viewStage->end(); ++i )
+                {
+                    buf << INDENT << i->second._name << "(vp_Vertex); \n";
+                }
+            }
+
+            if ( clipStage && clipStageInTES )
+            {
+                if ( space == SPACE_MODEL )
+                    buf << INDENT << "vp_Vertex = " << gl_ModelViewProjectionMatrix << " * vp_Vertex; \n"
+                    << INDENT << "vp_Normal = normalize(" << gl_NormalMatrix << " * vp_Normal); \n";
+                else if ( space == SPACE_VIEW )
+                    buf << INDENT << "vp_Vertex = " << gl_ProjectionMatrix << " * vp_Vertex; \n";
+
+                space = SPACE_CLIP;
+
+                for( OrderedFunctionMap::const_iterator i = clipStage->begin(); i != clipStage->end(); ++i )
+                {
+                    buf << INDENT << i->second._name << "(vp_Vertex); \n";
+                }
+            }
+
+            // resolve vertex to its next space, but ONLY if this is the final Vertex Processing stage.
+            if ( !hasGS )
+            {
+                if ( space == SPACE_MODEL )
+                    buf << INDENT << "vp_Vertex = " << gl_ModelViewProjectionMatrix << " * vp_Vertex; \n"
+                        << INDENT << "vp_Normal = normalize(" << gl_NormalMatrix << " * vp_Normal); \n";
+                else if ( space == SPACE_VIEW )
+                    buf << INDENT << "vp_Vertex = " << gl_ProjectionMatrix << " * vp_Vertex; \n";
+            }
+        
+            // Copy globals to output block:
+            for(Variables::const_iterator i = vars.begin(); i != vars.end(); ++i)
+                buf << INDENT << "vp_out." << i->name << " = " << i->name << "; \n";
+
+            buf << INDENT << "gl_Position = vp_Vertex; \n"
+                << "} \n";
+        }
+
+        buf << "\n"
+            << "void main(void) \n"
+            << "{ \n"
+            << INDENT "// copy default outputs: \n";
+        
+        if ( !tessEvalStage )
         {
-            buf << "void " << i->second._name << "( inout vec4 color ); \n";
+            // Copy default input block to output block (auto passthrough on first vert)
+            // NOT SURE WE NEED THIS
+            for(Variables::const_iterator i = vars.begin(); i != vars.end(); ++i)
+                buf << INDENT << "vp_out." << i->name << " = vp_in[0]." << i->name << "; \n";
         }
-    }
 
-    if ( output )
-    {
-        for( OrderedFunctionMap::const_iterator i = output->begin(); i != output->end(); ++i )
+        if ( tessEvalStage )
         {
-            buf << "void " << i->second._name << "( inout vec4 color ); \n";
+            for( OrderedFunctionMap::const_iterator i = tessEvalStage->begin(); i != tessEvalStage->end(); ++i )
+            {
+                buf << INDENT << i->second._name << "(); \n";
+            }
         }
+
+        buf << "} \n";
+        
+        std::string str = buf.str();
+        osg::Shader* tesShader = new osg::Shader(osg::Shader::TESSEVALUATION, str);
+        tesShader->setName("VP TES");
+        out_shaders.push_back( tesShader );
     }
 
-    buf << 
-        "varying vec4 osg_FrontColor; \n"
-        "varying vec3 oe_Normal; \n"
-        "vec3 oe_global_Normal; \n" // stage-global
-        "void main(void) \n"
-        "{ \n"
-        INDENT "vec4 color = osg_FrontColor; \n"
-        INDENT "oe_global_Normal = normalize(oe_Normal); \n";
-
-    int coloringPass = _fragStageOrder == FRAGMENT_STAGE_ORDER_COLORING_LIGHTING ? 0 : 1;
-    int lightingPass = 1-coloringPass;
-
-    for(int pass=0; pass<2; ++pass)
+
+    //.................................................................................
+
+
+    // Build the geometry shader.
+    if ( hasGS )
     {
-        if ( coloring && (pass == coloringPass) )
+        stages |= ShaderComp::STAGE_GEOMETRY;
+
+        std::stringstream buf;
+
+        buf << "#version " << gs_glsl_version << "\n"
+            << "#pragma vp_name VP Geometry Shader Main\n";
+
+        buf << glMatrixUniforms << "\n";
+
+        if ( hasVS || hasTCS || hasTES )
+        {
+            buf << "\n// Geometry stage inputs:\n"
+                << "in " << vertdata << " vp_in []; \n";
+        }        
+
+        // Declare stage globals.
+        buf << "\n// Geometry stage globals: \n";
+        for(Variables::const_iterator i = vars.begin(); i != vars.end(); ++i)
+            buf << i->declaration << "; \n";
+        
+        buf << "\n// Geometry stage outputs: \n"
+            << "out " << fragdata << " vp_out; \n";
+
+        if ( geomStage || (viewStage && viewStageInGS) || (clipStage && clipStageInGS) )
         {
-            for( OrderedFunctionMap::const_iterator i = coloring->begin(); i != coloring->end(); ++i )
+            buf << "\n// Injected function declarations:\n";
+            if ( geomStage )
+            {
+                for( OrderedFunctionMap::const_iterator i = geomStage->begin(); i != geomStage->end(); ++i )
+                {
+                    buf << "void " << i->second._name << "(); \n";
+                }
+            }       
+
+            if ( viewStage && viewStageInGS )
+            {
+                for( OrderedFunctionMap::const_iterator i = viewStage->begin(); i != viewStage->end(); ++i )
+                {
+                    buf << "void " << i->second._name << "(inout vec4); \n";
+                }
+            }
+
+            if ( clipStage && clipStageInGS )
             {
-                insertRangeConditionals( i->second, buf );
-                buf << INDENT << i->second._name << "( color ); \n";
+                for( OrderedFunctionMap::const_iterator i = clipStage->begin(); i != clipStage->end(); ++i )
+                {
+                    buf << "void " << i->second._name << "(inout vec4); \n";
+                }
             }
         }
+        
+        // Build-in helper functions:
+        buf << "\nvoid VP_LoadVertex(in int index) \n"
+            << "{ \n";
+        
+        // Copy input block to stage globals:
+        for(Variables::const_iterator i = vars.begin(); i != vars.end(); ++i)
+            buf << INDENT << i->name << " = vp_in[index]." << i->name << "; \n";
 
-        if ( lighting && (pass == lightingPass) )
+        buf << "} \n";
+
+        buf << "\nvoid VP_EmitModelVertex() \n"
+            << "{ \n";
+        
+        buf << INDENT << "vp_Vertex = gl_Position; \n";
+        int space = SPACE_MODEL;
+        if ( viewStage && viewStageInGS )
         {
-            for( OrderedFunctionMap::const_iterator i = lighting->begin(); i != lighting->end(); ++i )
+            buf << INDENT << "vp_Vertex = " << gl_ModelViewMatrix << " * vp_Vertex;\n"
+                << INDENT << "vp_Normal = normalize(" << gl_NormalMatrix << " * vp_Normal); \n";
+
+            space = SPACE_VIEW;
+
+            for( OrderedFunctionMap::const_iterator i = viewStage->begin(); i != viewStage->end(); ++i )
             {
-                insertRangeConditionals( i->second, buf );
-                buf << INDENT << i->second._name << "( color ); \n";
+                buf << INDENT << i->second._name << "(vp_Vertex); \n";
             }
         }
-    }
 
-    if ( output )
-    {
-        for( OrderedFunctionMap::const_iterator i = output->begin(); i != output->end(); ++i )
+        if ( clipStage && clipStageInGS )
+        {
+            if ( space == SPACE_MODEL )
+            {
+                buf << INDENT << "vp_Vertex = " << gl_ModelViewProjectionMatrix << " * vp_Vertex; \n"
+                    << INDENT << "vp_Normal = normalize(" << gl_NormalMatrix << " * vp_Normal); \n";
+            }
+            else if ( space == SPACE_VIEW )
+            {
+                buf << INDENT << "vp_Vertex = " << gl_ProjectionMatrix << " * vp_Vertex; \n";
+            }            
+
+            space = SPACE_CLIP;
+
+            for( OrderedFunctionMap::const_iterator i = clipStage->begin(); i != clipStage->end(); ++i )
+            {
+                buf << INDENT << i->second._name << "(vp_Vertex); \n";
+            }
+        }
+
+        // resolve vertex to its next space:
+        if ( space == SPACE_MODEL )
+        {
+            buf << INDENT << "vp_Vertex = " << gl_ModelViewProjectionMatrix << " * vp_Vertex; \n"
+                << INDENT << "vp_Normal = normalize(" << gl_NormalMatrix << " * vp_Normal); \n";
+        }
+        else if ( space == SPACE_VIEW )
+        {
+            buf << INDENT << "vp_Vertex = " << gl_ProjectionMatrix << " * vp_Vertex; \n";
+        }
+                
+        // Copy globals to output block:
+        for(Variables::const_iterator i = vars.begin(); i != vars.end(); ++i)
+            buf << INDENT << "vp_out." << i->name << " = " << i->name << "; \n";
+
+        buf << INDENT << "gl_Position = vp_Vertex; \n";
+
+        buf << INDENT << "EmitVertex(); \n"
+            << "} \n";
+        
+
+        buf << "\nvoid VP_EmitViewVertex() \n"
+            << "{ \n";
+        
+        buf << INDENT << "vp_Vertex = gl_Position; \n";
+        space = SPACE_VIEW;
+        if ( viewStage && viewStageInGS )
         {
-            insertRangeConditionals( i->second, buf );
-            buf << INDENT << i->second._name << "( color ); \n";
+            for( OrderedFunctionMap::const_iterator i = viewStage->begin(); i != viewStage->end(); ++i )
+            {
+                buf << INDENT << i->second._name << "(vp_Vertex); \n";
+            }
+        }
+
+        if ( clipStage && clipStageInGS )
+        {
+            buf << INDENT << "vp_Vertex = " << gl_ProjectionMatrix << " * vp_Vertex; \n";
+            space = SPACE_CLIP;
+            for( OrderedFunctionMap::const_iterator i = clipStage->begin(); i != clipStage->end(); ++i )
+            {
+                buf << INDENT << i->second._name << "(vp_Vertex); \n";
+            }
         }
+
+        // resolve vertex to its next space:
+        if ( space == SPACE_VIEW )
+            buf << INDENT << "vp_Vertex = " << gl_ProjectionMatrix << " * vp_Vertex; \n";
+                
+        // Copy globals to output block:
+        for(Variables::const_iterator i = vars.begin(); i != vars.end(); ++i)
+            buf << INDENT << "vp_out." << i->name << " = " << i->name << "; \n";
+
+        buf << INDENT << "gl_Position = vp_Vertex; \n";
+
+        buf << INDENT << "EmitVertex(); \n"
+            << "} \n";
+
+        buf << "\n"
+            << "void main(void) \n"
+            << "{ \n"
+            << INDENT "// copy default outputs: \n";
+        
+        // Copy default input block to output block (auto passthrough on first vert)
+        // NOT SURE WE NEED THIS
+        for(Variables::const_iterator i = vars.begin(); i != vars.end(); ++i)
+            buf << INDENT << "vp_out." << i->name << " = vp_in[0]." << i->name << "; \n";
+
+        if ( geomStage )
+        {
+            for( OrderedFunctionMap::const_iterator i = geomStage->begin(); i != geomStage->end(); ++i )
+            {
+                buf << INDENT << i->second._name << "(); \n";
+            }
+        }
+
+        buf << "} \n";
+
+        std::string str;
+        str = buf.str();
+        osg::Shader* geomShader = new osg::Shader( osg::Shader::GEOMETRY, str );
+        geomShader->setName( "main(geometry)" );
+        out_shaders.push_back( geomShader );
     }
-    else
+    
+
+    //.................................................................................
+
+
+    // Build the Fragment shader.
+    if ( hasFS )
     {
-        // in the absense of any output functions, generate a default output statement
-        // that simply writes to gl_FragColor.
-        buf << INDENT "gl_FragColor = color;\n";
+        stages |= ShaderComp::STAGE_FRAGMENT;
+
+        std::stringstream buf;
+
+        buf << "#version " << fs_glsl_version << "\n"
+            << "#pragma vp_name VP Fragment Shader Main\n"
+            << "#extension GL_ARB_gpu_shader5 : enable \n";
+
+        // no output stage? Use default output
+        if (!outputStage)
+        {
+            buf << "\n// Fragment output\n"
+                << "out vec4 oe_FragColor;\n";
+        }
+
+        buf << "\n// Fragment stage inputs:\n";
+        buf << "in " << fragdata << " vp_in; \n";
+                
+        buf <<
+            "\n// Fragment stage globals:\n";
+
+        // Declare stage globals.
+        for(Variables::const_iterator i = vars.begin(); i != vars.end(); ++i)
+            buf << i->declaration << ";\n";
+
+        if ( coloringStage || lightingStage || outputStage )
+        {
+            buf << "\n// Function declarations:\n";
+        }
+
+        if ( coloringStage )
+        {
+            for( OrderedFunctionMap::const_iterator i = coloringStage->begin(); i != coloringStage->end(); ++i )
+            {
+                buf << "void " << i->second._name << "(inout vec4 color); \n";
+            }
+        }
+
+        if ( lightingStage )
+        {
+            for( OrderedFunctionMap::const_iterator i = lightingStage->begin(); i != lightingStage->end(); ++i )
+            {
+                buf << "void " << i->second._name << "(inout vec4 color); \n";
+            }
+        }
+
+        if ( outputStage )
+        {
+            for( OrderedFunctionMap::const_iterator i = outputStage->begin(); i != outputStage->end(); ++i )
+            {
+                buf << "void " << i->second._name << "(inout vec4 color); \n";
+            }
+        }
+
+        buf << 
+            "\nvoid main(void) \n"
+            "{ \n";
+        
+        // Copy input block to stage globals:
+        for(Variables::const_iterator i = vars.begin(); i != vars.end(); ++i)
+            buf << INDENT << i->name << " = vp_in." << i->name << "; \n";
+
+        buf << INDENT << "vp_Normal = normalize(vp_Normal); \n";
+
+        int coloringPass = _fragStageOrder == FRAGMENT_STAGE_ORDER_COLORING_LIGHTING ? 0 : 1;
+        int lightingPass = 1-coloringPass;
+
+        for(int pass=0; pass<2; ++pass)
+        {
+            if ( coloringStage && (pass == coloringPass) )
+            {
+                for( OrderedFunctionMap::const_iterator i = coloringStage->begin(); i != coloringStage->end(); ++i )
+                {
+                    buf << INDENT << i->second._name << "( vp_Color ); \n";
+                }
+            }
+
+            if ( lightingStage && (pass == lightingPass) )
+            {
+                for( OrderedFunctionMap::const_iterator i = lightingStage->begin(); i != lightingStage->end(); ++i )
+                {
+                    buf << INDENT << i->second._name << "( vp_Color ); \n";
+                }
+            }
+        }
+
+        if ( outputStage )
+        {
+            for( OrderedFunctionMap::const_iterator i = outputStage->begin(); i != outputStage->end(); ++i )
+            {
+                buf << INDENT << i->second._name << "( vp_Color ); \n";
+            }
+        }
+        else
+        {
+            // in the absense of any output functions, generate a default output statement
+            // that simply writes to gl_FragColor.
+            buf << INDENT << "oe_FragColor = vp_Color;\n";
+        }
+        buf << "}\n";
+
+        std::string str;
+        str = buf.str();
+        osg::Shader* shader = new osg::Shader( osg::Shader::FRAGMENT, str );
+        shader->setName( "main(fragment)" );
+        out_shaders.push_back( shader );
     }
-    buf << "}\n";
 
-    std::string str;
-    str = buf.str();
-    osg::Shader* shader = new osg::Shader( osg::Shader::FRAGMENT, str );
-    shader->setName( "main(frag)" );
-    return shader;
+    return stages;
 }
 
 
diff --git a/src/osgEarth/ShaderGenerator b/src/osgEarth/ShaderGenerator
index 3001c1f..d2aba7d 100644
--- a/src/osgEarth/ShaderGenerator
+++ b/src/osgEarth/ShaderGenerator
@@ -26,6 +26,7 @@
 #include <osg/NodeVisitor>
 #include <osg/State>
 #include <osg/Version>
+#include <osg/Drawable>
 #include <sstream>
 #include <set>
 
@@ -166,6 +167,10 @@ namespace osgEarth
         virtual void apply( osg::ProxyNode& );
         virtual void apply( osg::ClipNode& );
 
+#if OSG_VERSION_GREATER_OR_EQUAL(3,3,3)
+        virtual void apply( osg::Drawable& );
+#endif
+
     public: // types not in osg::NodeVisitor
 
         virtual void applyNonCoreNodeIfNecessary( osg::Node& );
@@ -240,6 +245,8 @@ namespace osgEarth
         typedef std::vector<osg::ref_ptr<AcceptCallback> > AcceptCallbackVector;
         AcceptCallbackVector _acceptCallbacks;
 
+        std::set<osg::Drawable*> _drawablesVisited;
+
         bool accept(const osg::StateAttribute* sa) const;
     };
 
diff --git a/src/osgEarth/ShaderGenerator.cpp b/src/osgEarth/ShaderGenerator.cpp
index 9d68dee..25575de 100644
--- a/src/osgEarth/ShaderGenerator.cpp
+++ b/src/osgEarth/ShaderGenerator.cpp
@@ -1,7 +1,7 @@
 
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -102,7 +102,7 @@ struct OSGEarthShaderGenPseudoLoader : public osgDB::ReaderWriter
         this->supportsExtension( SHADERGEN_PL_EXTENSION, "ShaderGen pseudoloader" );
     }
 
-    const char* className()
+    const char* className() const
     {
         return "OSGEarth ShaderGen pseudoloader";
     }
@@ -310,7 +310,8 @@ namespace
 //...........................................................................
 
 ShaderGenerator::GenBuffers::GenBuffers() :
-_version( GLSL_VERSION )
+_version( GLSL_VERSION ),
+_stateSet(0L)
 {
     //nop
 }
@@ -571,12 +572,33 @@ ShaderGenerator::apply( osg::Geode& node )
     }
 }
 
+#if OSG_VERSION_GREATER_OR_EQUAL(3,3,3)
+void
+ShaderGenerator::apply( osg::Drawable& drawable )
+{
+    if ( !_active )
+        return;
+
+    if ( ignore(&drawable) )
+        return;
+
+    if ( _duplicateSharedSubgraphs )
+        duplicateSharedNode(drawable);
+
+    apply( &drawable );
+}
+#endif
 
 void 
 ShaderGenerator::apply( osg::Drawable* drawable )
 {
     if ( drawable )
     {
+        if (_drawablesVisited.find(drawable) != _drawablesVisited.end())
+            return;
+        else
+            _drawablesVisited.insert(drawable);
+
         osg::ref_ptr<osg::StateSet> ss = drawable->getStateSet();
         if ( ss.valid() )
         {
@@ -774,10 +796,11 @@ ShaderGenerator::processText(const osg::StateSet* ss, osg::ref_ptr<osg::StateSet
         "void " FRAGMENT_FUNCTION "(inout vec4 color)\n"
         "{ \n"
         INDENT MEDIUMP "vec4 texel = texture2D(" SAMPLER_TEXT ", " TEX_COORD_TEXT ".xy);\n"
+        //INDENT MEDIUMP "vec4 texel = texture2DLod(" SAMPLER_TEXT ", " TEX_COORD_TEXT ".xy, 0.0);\n"
         INDENT "color.a *= texel.a; \n"
         "}\n";
 
-    vp->setFunction( VERTEX_FUNCTION,   vertSrc, ShaderComp::LOCATION_VERTEX_VIEW, 0.5f );
+    vp->setFunction( VERTEX_FUNCTION,   vertSrc, ShaderComp::LOCATION_VERTEX_MODEL, 0.5f );
     vp->setFunction( FRAGMENT_FUNCTION, fragSrc, ShaderComp::LOCATION_FRAGMENT_COLORING, 0.5f );
     replacement->getOrCreateUniform( SAMPLER_TEXT, osg::Uniform::SAMPLER_2D )->set( 0 );
 
@@ -879,7 +902,7 @@ ShaderGenerator::processGeometry(const osg::StateSet*         original,
 
     if ( needNewStateSet )
     {
-        std::string version = Stringify() << buf._version;
+        std::string version = GLSL_VERSION_STR;
 
         std::string vertHeadSource;
         vertHeadSource = buf._vertHead.str();
@@ -1080,11 +1103,11 @@ ShaderGenerator::apply(osg::TexGen* texgen, int unit, GenBuffers& buf)
 
         case osg::TexGen::SPHERE_MAP:
             buf._vertHead
-                << "varying vec3 oe_Normal;\n";
+                << "varying vec3 vp_Normal;\n";
             buf._vertBody 
                 << INDENT "{\n" // scope it in case there are > 1
                 << INDENT "vec3 view_vec = normalize(vertex_view.xyz/vertex_view.w); \n"
-                << INDENT "vec3 r = reflect(view_vec, oe_Normal);\n"
+                << INDENT "vec3 r = reflect(view_vec, vp_Normal);\n"
                 << INDENT "r.z += 1.0; \n"
                 << INDENT "float m = 2.0 * sqrt(dot(r,r)); \n"
                 << INDENT TEX_COORD << unit << " = vec4(r.x/m + 0.5, r.y/m + 0.5, 0.0, 1.0); \n"
@@ -1093,20 +1116,20 @@ ShaderGenerator::apply(osg::TexGen* texgen, int unit, GenBuffers& buf)
 
         case osg::TexGen::REFLECTION_MAP:
             buf._vertHead
-                << "varying vec3 oe_Normal;\n";
+                << "varying vec3 vp_Normal;\n";
             buf._vertBody
                 << INDENT "{\n"
                 << INDENT "vec3 view_vec = normalize(vertex_view.xyz/vertex_view.w);\n"
-                << INDENT TEX_COORD << unit << " = vec4(reflect(view_vec, oe_Normal), 1.0); \n"
+                << INDENT TEX_COORD << unit << " = vec4(reflect(view_vec, vp_Normal), 1.0); \n"
                 << INDENT "}\n";
             break;
 
         case osg::TexGen::NORMAL_MAP:
             buf._vertHead
-                << "varying vec3 oe_Normal;\n";
+                << "varying vec3 vp_Normal;\n";
             buf._vertBody
                 << INDENT "{\n"
-                << INDENT TEX_COORD << unit << " = vec4(oe_Normal, 1.0); \n"
+                << INDENT TEX_COORD << unit << " = vec4(vp_Normal, 1.0); \n"
                 << INDENT "}\n";
             break;
 
diff --git a/src/osgEarth/ShaderLoader b/src/osgEarth/ShaderLoader
index 97f602c..731e6b6 100644
--- a/src/osgEarth/ShaderLoader
+++ b/src/osgEarth/ShaderLoader
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -22,6 +22,7 @@
 #include <osgEarth/Common>
 #include <osgDB/Options>
 #include <map>
+#include <set>
 
 namespace osgEarth
 {
@@ -79,6 +80,15 @@ namespace osgEarth
             const std::string& pattern,
             const std::string& value);
 
+        /**
+         * Add a file/source to the package. If you only have inline source, just
+         * set the filename to a unique description string.
+         */
+        void add(const std::string& filename, const std::string& inlineSource)
+        {
+            _sources[filename] = inlineSource;
+        }
+
     public:
         typedef std::map<std::string, std::string> SourceMap;
         typedef std::map<std::string, std::string> ReplaceMap;
@@ -86,9 +96,6 @@ namespace osgEarth
 
         const SourceMap& context() const { return _sources; }
 
-        void add(const std::string& filename, const std::string& inlineSource) {
-            _sources[filename] = inlineSource; }
-
 
     protected:        
         SourceMap _sources;
@@ -109,8 +116,8 @@ namespace osgEarth
          * The shader much include #pragma definitions for both its
          * entry point and its location, e.g.:
          *
-         *   #pragma vp_entryPoint "oe_my_shader"
-         *   #pargma vp_location   "VERTEX_VIEW"
+         *   #pragma vp_entryPoint oe_my_shader
+         *   #pargma vp_location   VERTEX_VIEW
          */
         static bool load(
             VirtualProgram*       vp,
@@ -141,6 +148,20 @@ namespace osgEarth
             const std::string&    filename,
             const ShaderPackage&  package,
             const osgDB::Options* dbOptions =0L );
+
+        /**
+         * Utility function that returns the value of #pragma; e.g.,
+         * #pragma vp_something You are here
+         * returns "You are here" (without the quotes).
+         */
+        static std::string getPragmaValue(
+            const std::string& source,
+            const std::string& key);
+
+        static void getAllPragmaValues(
+            const std::string&     source,
+            const std::string&     key,
+            std::set<std::string>& output);
     };
 
 } // namespace osgEarth
diff --git a/src/osgEarth/ShaderLoader.cpp b/src/osgEarth/ShaderLoader.cpp
index b72f2b0..95d419e 100644
--- a/src/osgEarth/ShaderLoader.cpp
+++ b/src/osgEarth/ShaderLoader.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -26,36 +26,70 @@
 
 using namespace osgEarth;
 
-namespace
-{
-    // find the value of a quoted pragma, e.g.:
-    //   #pragma oe_key "value"
-    // returns the string "value" (without the quotes).
-    std::string getQuotedPragmaValue(const std::string& source,
-                                     const std::string& key)
-    {
-        std::string::size_type includePos = source.find("#pragma " + key);
-        if ( includePos == std::string::npos )
-            return "";
 
-        std::string::size_type openQuotePos = source.find('\"', includePos);
-        if ( openQuotePos == std::string::npos )
-            return "";
+typedef std::map<std::string,std::string> StringMap;
 
-        std::string::size_type closeQuotePos = source.find('\"', openQuotePos+1);
-        if ( closeQuotePos == std::string::npos )
-            return "";
 
-        std::string statement = source.substr( includePos, (closeQuotePos-includePos)+1 );
+// find the value of a pragma, e.g.:
+//   #pragma oe_key value
+// returns the string "value" (without the quotes).
+std::string
+ShaderLoader::getPragmaValue(const std::string& source, const std::string& key)
+{
+    std::string token("#pragma " + key);
+    std::string::size_type statementPos = source.find(token);
+    if ( statementPos == std::string::npos )
+        return "";
+
+    // no quotes; parse to newline.
+    std::string::size_type startPos = source.find_first_not_of(" \t", statementPos+token.length());
+    if ( startPos == std::string::npos )
+        return ""; // no whitespace after the pragma key
 
-        std::string value = source.substr( openQuotePos+1, (closeQuotePos-openQuotePos)-1 );
+    std::string::size_type newlinePos = source.find('\n', startPos);
+    if ( newlinePos == std::string::npos )
+        return ""; // new newline found after pragma
 
-        return value;
-    }
+    return trim(source.substr(startPos, newlinePos-startPos));
 }
 
-typedef std::map<std::string,std::string> StringMap;
-
+void
+ShaderLoader::getAllPragmaValues(const std::string&     source,
+                                 const std::string&     key,
+                                 std::set<std::string>& output)
+{
+    std::string token("#pragma " + key);
+    std::string::size_type pragmaPos = 0;
+    while( pragmaPos != std::string::npos )
+    {
+        pragmaPos = source.find(token, pragmaPos);
+        if ( pragmaPos != std::string::npos )
+        {
+            std::string::size_type startPos = source.find_first_not_of(" \t", pragmaPos+token.length());
+            if ( startPos != std::string::npos )
+            {
+                std::string::size_type newlinePos = source.find('\n', startPos);
+                if ( newlinePos != std::string::npos )
+                {
+                    const size_t len = newlinePos - startPos;
+                    if ( len > 0 )
+                    {
+                        output.insert( trim(source.substr(startPos, len)) );
+                    }
+                    pragmaPos = newlinePos;
+                }
+                else
+                {
+                    break;
+                }
+            }
+            else
+            {
+                break;
+            }
+        }
+    }
+}
 
 std::string
 ShaderLoader::load(const std::string&    filename,
@@ -64,13 +98,16 @@ ShaderLoader::load(const std::string&    filename,
 {
     std::string output;
     bool useInlineSource = false;
-    
+
+    URIContext context( dbOptions );
+    URI uri(filename, context);
+
     std::string inlineSource;
-    ShaderPackage::SourceMap::const_iterator source = package._sources.find(filename); //.context().find(filename);
-    if ( source != package._sources.end() ) //.context().end() )
+    ShaderPackage::SourceMap::const_iterator source = package._sources.find(filename);
+    if ( source != package._sources.end() )
         inlineSource = source->second;
 
-    std::string path = osgDB::findDataFile(filename, dbOptions);
+    std::string path = osgDB::findDataFile(uri.full(), dbOptions);
     if ( path.empty() )
     {
         output = inlineSource;
@@ -82,7 +119,7 @@ ShaderLoader::load(const std::string&    filename,
     }
     else
     {
-        std::string externalSource = URI(path).getString(dbOptions);
+        std::string externalSource = URI(path, context).getString(dbOptions);
         if (!externalSource.empty())
         {
             OE_DEBUG << LC << "Loaded external shader " << filename << " from " << path << "\n";
@@ -98,34 +135,34 @@ ShaderLoader::load(const std::string&    filename,
     // replace common tokens:
     osgEarth::replaceIn(output, "$GLSL_VERSION_STR", GLSL_VERSION_STR);
     osgEarth::replaceIn(output, "$GLSL_DEFAULT_PRECISION_FLOAT", GLSL_DEFAULT_PRECISION_FLOAT);
-    
+
     // If we're using inline source, we have to post-process the string.
     if ( useInlineSource )
     {
-        // reinstate preprocessor macros since GCC doesn't like them in the inlines shaders.
-        // The token was inserted in the CMakeModules/ConfigureShaders.cmake.in script.
-        osgEarth::replaceIn(output, "$__HASHTAG__", "#");
+        // Replace tokens inserted in the CMakeModules/ConfigureShaders.cmake.in script.
+        osgEarth::replaceIn(output, "%EOL%",   "\n");
+        osgEarth::replaceIn(output, "%QUOTE%", "\"");
     }
 
     // Process any "#pragma include" statements
     while(true)
     {
-        std::string::size_type includePos = output.find("#pragma include");
-        if ( includePos == std::string::npos )
+        const std::string token("#pragma include");
+        std::string::size_type statementPos = output.find(token);
+        if ( statementPos == std::string::npos )
             break;
 
-        std::string::size_type openQuotePos = output.find('\"', includePos);
-        if ( openQuotePos == std::string::npos )
+        std::string::size_type startPos = output.find_first_not_of(" \t", statementPos+token.length());
+        if ( startPos == std::string::npos )
             break;
 
-        std::string::size_type closeQuotePos = output.find('\"', openQuotePos+1);
-        if ( closeQuotePos == std::string::npos )
+        std::string::size_type endPos = output.find('\n', startPos);
+        if ( endPos == std::string::npos )
             break;
 
-        std::string includeStatement = output.substr( includePos, (closeQuotePos-includePos)+1 );
+        std::string statement( output.substr(statementPos, endPos-statementPos) );
+        std::string fileToInclude( trim(output.substr(startPos, endPos-startPos)) );
 
-        std::string fileToInclude = output.substr( openQuotePos+1, (closeQuotePos-openQuotePos)-1 );
-        
         // load the source of the included file, and append a newline so we
         // don't break the MULTILINE macro if the last line of the include
         // file is a comment.
@@ -133,27 +170,27 @@ ShaderLoader::load(const std::string&    filename,
             << load(fileToInclude, package, dbOptions)
             << "\n";
 
-        osgEarth::replaceIn(output, includeStatement, fileSource);
+        osgEarth::replaceIn(output, statement, fileSource);
     }
 
     // Process any "#pragma define" statements
     while(true)
     {
-        std::string::size_type definePos = output.find("#pragma vp_define");
-        if ( definePos == std::string::npos )
-            break;        
+        const std::string token("#pragma vp_define");
+        std::string::size_type statementPos = output.find(token);
+        if ( statementPos == std::string::npos )
+            break;
 
-        std::string::size_type openQuotePos = output.find('\"', definePos);
-        if ( openQuotePos == std::string::npos )
+        std::string::size_type startPos = output.find_first_not_of(" \t", statementPos+token.length());
+        if ( startPos == std::string::npos )
             break;
 
-        std::string::size_type closeQuotePos = output.find('\"', openQuotePos+1);
-        if ( closeQuotePos == std::string::npos )
+        std::string::size_type endPos = output.find('\n', startPos);
+        if ( endPos == std::string::npos )
             break;
-        
-        std::string defineStatement = output.substr( definePos, (closeQuotePos-definePos)+1 );
 
-        std::string varName = output.substr( openQuotePos+1, (closeQuotePos-openQuotePos)-1 );
+        std::string statement( output.substr(statementPos, endPos-statementPos) );
+        std::string varName( trim(output.substr(startPos, endPos-startPos)) );
 
         ShaderPackage::DefineMap::const_iterator d = package._defines.find( varName );
 
@@ -165,10 +202,10 @@ ShaderLoader::load(const std::string&    filename,
             << (defineIt? "#define " : "#undef ")
             << varName;
 
-        osgEarth::replaceIn( output, defineStatement, newStatement );
+        osgEarth::replaceIn( output, statement, newStatement );
     }
 
-    // Finally, do any replacements.
+    // Finally, process any replacements.
     for(ShaderPackage::ReplaceMap::const_iterator i = package._replaces.begin();
         i != package._replaces.end();
         ++i)
@@ -187,6 +224,9 @@ ShaderLoader::load(const std::string&    filename,
     std::string output;
     bool useInlineSource = false;
 
+    URIContext context( dbOptions );
+    URI uri(filename, context );
+
     std::string path = osgDB::findDataFile(filename, dbOptions);
     if ( path.empty() )
     {
@@ -195,7 +235,7 @@ ShaderLoader::load(const std::string&    filename,
     }
     else
     {
-        std::string externalSource = URI(path).getString(dbOptions);
+        std::string externalSource = URI(path, context).getString(dbOptions);
         if (!externalSource.empty())
         {
             OE_DEBUG << LC << "Loaded external shader " << filename << " from " << path << "\n";
@@ -211,13 +251,13 @@ ShaderLoader::load(const std::string&    filename,
     // replace common tokens:
     osgEarth::replaceIn(output, "$GLSL_VERSION_STR", GLSL_VERSION_STR);
     osgEarth::replaceIn(output, "$GLSL_DEFAULT_PRECISION_FLOAT", GLSL_DEFAULT_PRECISION_FLOAT);
-    
+
     // If we're using inline source, we have to post-process the string.
     if ( useInlineSource )
     {
-        // reinstate preprocessor macros since GCC doesn't like them in the inlines shaders.
-        // The token was inserted in the CMakeModules/ConfigureShaders.cmake.in script.
-        osgEarth::replaceIn(output, "$__HASHTAG__", "#");
+        // Replace tokens inserted in the CMakeModules/ConfigureShaders.cmake.in script.
+        osgEarth::replaceIn(output, "%EOL%",   "\n");
+        osgEarth::replaceIn(output, "%QUOTE%", "\"");
     }
 
     return output;
@@ -241,21 +281,26 @@ ShaderLoader::load(VirtualProgram*       vp,
         OE_WARN << LC << "Failed to load shader source from \"" << filename << "\"\n";
         return false;
     }
-    
-    std::string loc = getQuotedPragmaValue(source, "vp_location");
-    if ( loc.empty() )
-    {
-        OE_WARN << LC << "Illegal: shader \"" << filename << "\" missing required #pragma vp_location\n";
-        return false;
-    }
 
+    // Remove the quotation marks from the source since they are illegal in GLSL
+    replaceIn( source, "\"", " ");
+
+    std::string loc = getPragmaValue(source, "vp_location");
     ShaderComp::FunctionLocation location;
+    bool locationSet = true;
+
     if      ( ciEquals(loc, "vertex_model") )
         location = ShaderComp::LOCATION_VERTEX_MODEL;
     else if ( ciEquals(loc, "vertex_view") )
         location = ShaderComp::LOCATION_VERTEX_VIEW;
     else if ( ciEquals(loc, "vertex_clip") )
         location = ShaderComp::LOCATION_VERTEX_CLIP;
+    else if ( ciEquals(loc, "tess_control") || ciEquals(loc, "tessellation_control") )
+        location = ShaderComp::LOCATION_TESS_CONTROL;
+    else if ( ciEquals(loc, "tess_eval") || ciEquals(loc, "tessellation_eval") || ciEquals(loc, "tessellation_evaluation") || ciEquals(loc, "tess_evaluation") )
+        location = ShaderComp::LOCATION_TESS_EVALUATION;
+    else if ( ciEquals(loc, "vertex_geometry") || ciEquals(loc, "geometry") )
+        location = ShaderComp::LOCATION_GEOMETRY;
     else if ( ciEquals(loc, "fragment" ) )
         location = ShaderComp::LOCATION_FRAGMENT_COLORING;
     else if ( ciEquals(loc, "fragment_coloring") )
@@ -264,18 +309,25 @@ ShaderLoader::load(VirtualProgram*       vp,
         location = ShaderComp::LOCATION_FRAGMENT_LIGHTING;
     else if ( ciEquals(loc, "fragment_output") )
         location = ShaderComp::LOCATION_FRAGMENT_OUTPUT;
-    else 
+    else
     {
-        OE_WARN << LC << "Illegal: shader \"" << filename << "\" has invalid #pragma vp_location \"" << loc << "\"\n";
-        return false;
+        locationSet = false;
     }
 
     // If entry point is set, this is a function; otherwise a simple library.
-    std::string entryPoint = getQuotedPragmaValue(source, "vp_entryPoint");
+    std::string entryPoint = getPragmaValue(source, "vp_entryPoint");
+
+    // order is optional.
+    std::string orderStr = getPragmaValue(source, "vp_order");
+
     if ( !entryPoint.empty() )
     {
-        // order is optional.
-        std::string orderStr = getQuotedPragmaValue(source, "vp_order");
+        if ( !locationSet )
+        {
+            OE_WARN << LC << "Illegal: shader \"" << filename << "\" has invalid #pragma vp_location when vp_entryPoint is set\n";
+            return false;
+        }
+
         float order;
         if ( ciEquals(orderStr, "FLT_MAX") || ciEquals(orderStr, "last") )
             order = FLT_MAX;
@@ -291,13 +343,30 @@ ShaderLoader::load(VirtualProgram*       vp,
     else
     {
         // install as a simple shader.
-        osg::Shader::Type type =
-            location == ShaderComp::LOCATION_VERTEX_MODEL || location == ShaderComp::LOCATION_VERTEX_VIEW || location == ShaderComp::LOCATION_VERTEX_CLIP ? osg::Shader::VERTEX :
-            osg::Shader::FRAGMENT;
+        if ( locationSet )
+        {
+            // If a location is set, install in that location only
+            osg::Shader::Type type =
+                location == ShaderComp::LOCATION_VERTEX_MODEL || location == ShaderComp::LOCATION_VERTEX_VIEW || location == ShaderComp::LOCATION_VERTEX_CLIP ? osg::Shader::VERTEX :
+                osg::Shader::FRAGMENT;
+
+            osg::Shader* shader = new osg::Shader(type, source);
+            shader->setName( filename );
+            vp->setShader( filename, shader );
+        }
 
-        osg::Shader* shader = new osg::Shader(type, source);
-        shader->setName( filename );
-        vp->setShader( filename, shader );
+        else
+        {
+            // If no location was set, install in all stages.
+            osg::Shader::Type types[5] = { osg::Shader::VERTEX, osg::Shader::FRAGMENT, osg::Shader::GEOMETRY, osg::Shader::TESSCONTROL, osg::Shader::TESSEVALUATION };
+            for(int i=0; i<5; ++i)
+            {
+                osg::Shader* shader = new osg::Shader(types[i], source);
+                std::string name = Stringify() << filename + "_" + shader->getTypename();
+                shader->setName( name );
+                vp->setShader( name, shader );
+            }
+        }
     }
 
     return true;
@@ -322,7 +391,7 @@ ShaderLoader::unload(VirtualProgram*       vp,
         return false;
     }
 
-    std::string entryPoint = getQuotedPragmaValue(source, "vp_entryPoint");
+    std::string entryPoint = getPragmaValue(source, "vp_entryPoint");
     if ( !entryPoint.empty() )
     {
         vp->removeShader( entryPoint );
diff --git a/src/osgEarth/ShaderUtils b/src/osgEarth/ShaderUtils
index d5b00c5..4a948d3 100644
--- a/src/osgEarth/ShaderUtils
+++ b/src/osgEarth/ShaderUtils
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -94,6 +94,8 @@ namespace osgEarth
     {
     public:
         static void run(osg::Shader* shader);
+
+        static void applySupportForNoFFP(osg::Shader* shader);
     };
 
     /**
@@ -115,8 +117,8 @@ namespace osgEarth
 
     protected:
         int   _maxLights;
-        bool* _lightEnabled;
-        bool  _lightingEnabled;
+        //bool* _lightEnabled;
+        //bool  _lightingEnabled;
         bool  _dirty;
         bool  _applied;
         bool  _useUpdateTrav;
diff --git a/src/osgEarth/ShaderUtils.cpp b/src/osgEarth/ShaderUtils.cpp
index 48e1ef5..fe37d34 100644
--- a/src/osgEarth/ShaderUtils.cpp
+++ b/src/osgEarth/ShaderUtils.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -23,6 +23,7 @@
 #include <osgEarth/Capabilities>
 #include <osgEarth/CullingUtils>
 #include <osgEarth/URI>
+#include <osgEarth/GLSLChunker>
 #include <osg/ComputeBoundsVisitor>
 #include <osgDB/FileUtils>
 #include <list>
@@ -42,6 +43,8 @@ namespace
 
     typedef std::list<const osg::StateSet*> StateSetStack;
 
+#if 0
+
     static osg::StateAttribute::GLModeValue 
     getModeValue(const StateSetStack& statesetStack, osg::StateAttribute::GLMode mode)
     {
@@ -65,7 +68,9 @@ namespace
         }
         return base_val;
     }
+#endif
     
+#if 0
     static const osg::Light*
     getLightByID(const StateSetStack& statesetStack, int id)
     {
@@ -98,6 +103,7 @@ namespace
         }
         return base_light;
     }
+#endif
     
     static const osg::Material*
     getFrontMaterial(const StateSetStack& statesetStack)
@@ -139,7 +145,7 @@ namespace
 namespace
 {
     // Code borrowed from osg::State.cpp
-    static bool replace(std::string& str, const std::string& original_phrase, const std::string& new_phrase)
+    bool replace(std::string& str, const std::string& original_phrase, const std::string& new_phrase)
     {
         bool replacedStr = false;
         std::string::size_type pos = 0;
@@ -165,26 +171,169 @@ namespace
         return replacedStr;
     }
 
-    static void replaceAndInsertDeclaration(std::string& source, std::string::size_type declPos, const std::string& originalStr, const std::string& newStr, const std::string& declarationPrefix, const std::string& declarationSuffix ="")
+    bool replaceAndInsertDeclaration(std::string& source, std::string::size_type declPos, const std::string& originalStr, const std::string& newStr, const std::string& declarationPrefix, const std::string& declarationSuffix ="")
     {
-        if (replace(source, originalStr, newStr))
+        bool yes = replace(source, originalStr, newStr);
+        if ( yes )
         {
             source.insert(declPos, declarationPrefix + newStr + declarationSuffix + std::string(";\n"));
         }
+        return yes;
+    }
+
+    bool replaceAndInsertLiteral(std::string& source, std::string::size_type declPos, const std::string& originalStr, const std::string& newStr, const std::string& lit)
+    {
+        bool yes = replace(source, originalStr, newStr);
+        if ( yes )
+        {
+            source.insert(declPos, lit);
+        }
+        return yes;
+    }
+
+    int replaceVarying(GLSLChunker::Chunks& chunks, int index, const StringVector& tokens, int offset, const std::string& prefix)
+    {
+        std::stringstream buf;
+        buf << "#pragma vp_varying";
+        if ( !prefix.empty() )
+            buf << " " << prefix;
+
+        for(int i=offset; i<tokens.size(); ++i)
+        {
+            if ( !tokens[i].empty() )
+            {
+                int len = tokens[i].length();
+                if ( tokens[i].at(len-1) == ';' )
+                    buf << " " << tokens[i].substr(0, len-1); // strip semicolon
+                else
+                    buf << " " << tokens[i];
+            }
+        }
+        
+        chunks[index].text = buf.str();
+        chunks[index].type = GLSLChunker::Chunk::TYPE_DIRECTIVE;
+
+        std::stringstream buf2;
+        for(int i=offset; i<tokens.size(); ++i)
+            buf2 << (i==offset?"":" ") << tokens[i];
+
+        GLSLChunker::Chunk newChunk;
+        newChunk.type = GLSLChunker::Chunk::TYPE_STATEMENT;
+        newChunk.text = buf2.str();
+        chunks.insert( chunks.begin()+index, newChunk );
+
+        return index+1;
+    }
+
+    bool replaceVaryings(osg::Shader::Type type, GLSLChunker::Chunks& chunks)
+    {
+        bool madeChanges = false;
+
+        for(int i=0; i<chunks.size(); ++i)
+        {
+            if ( chunks[i].type == GLSLChunker::Chunk::TYPE_STATEMENT )
+            {
+                std::string replacement;
+                /*
+                StringVector tokens;
+                StringTokenizer(chunks[i].text, tokens, " \t\n", "", false, true);
+                */
+                const std::vector<std::string>& tokens = chunks[i].tokens;
+
+                if      ( tokens.size() > 1 && tokens[0] == "out" && type != osg::Shader::FRAGMENT )
+                    i = replaceVarying(chunks, i, tokens, 1, ""), madeChanges = true;
+                else if ( tokens.size() > 1 && tokens[0] == "in" && type != osg::Shader::VERTEX )
+                    i = replaceVarying(chunks, i, tokens, 1, ""), madeChanges = true;
+                else if ( tokens.size() > 2 && tokens[0] == "varying" && tokens[1] == "out" && type != osg::Shader::FRAGMENT )
+                    i = replaceVarying(chunks, i, tokens, 2, ""), madeChanges = true;
+                else if ( tokens.size() > 2 && tokens[0] == "flat" && tokens[1] == "out" && type != osg::Shader::FRAGMENT )
+                    i = replaceVarying(chunks, i, tokens, 2, "flat"), madeChanges = true;
+                else if ( tokens.size() > 2 && tokens[0] == "flat" && tokens[1] == "in" && type != osg::Shader::VERTEX )
+                    i = replaceVarying(chunks, i, tokens, 2, "flat"), madeChanges = true;
+                else if ( tokens.size() > 1 && tokens[0] == "varying" )
+                    i = replaceVarying(chunks, i, tokens, 1, ""), madeChanges = true;
+            }
+        }
+
+        return madeChanges;
+    }
+
+    void applySupportForNoFFPImpl(GLSLChunker::Chunks& chunks)
+    {
+#if !defined(OSG_GL_FIXED_FUNCTION_AVAILABLE)
+
+        // for geometry and tessellation shaders, replace the built-ins with 
+        // osg uniform aliases.
+        const char* lines[4] = {
+            "uniform mat4 osg_ModelViewMatrix;",
+            "uniform mat4 osg_ProjectionMatrix;",
+            "uniform mat4 osg_ModelViewProjectionMatrix;",
+            "uniform mat3 osg_NormalMatrix;"
+        };
+    
+        GLSLChunker chunker;
+
+        for (GLSLChunker::Chunks::iterator chunk = chunks.begin(); chunk != chunks.end(); ++chunk)
+        {
+            if (chunk->type != GLSLChunker::Chunk::TYPE_DIRECTIVE)
+            {
+                for (unsigned line = 0; line < 4; ++line) {
+                    chunk = chunks.insert(chunk, chunker.chunkLine(lines[line]));
+                    ++chunk;
+                }
+                break;
+            }
+        }
+
+        chunker.replace(chunks, "gl_ModelViewMatrix", "osg_ModelViewMatrix");
+        chunker.replace(chunks, "gl_ProjectionMatrix", "osg_ProjectionMatrix");
+        chunker.replace(chunks, "gl_ModelViewProjectionMatrix", "osg_ModelViewProjectionMatrix");
+        chunker.replace(chunks, "gl_NormalMatrix", "osg_NormalMatrix");
+    
+#endif // !defined(OSG_GL_FIXED_FUNCTION_AVAILABLE)
     }
 }
 
 void
-ShaderPreProcessor::run(osg::Shader* shader)
+ShaderPreProcessor::applySupportForNoFFP(osg::Shader* shader)
 {
-    // only runs for non-FFP (GLES, GL3+, etc.)
+    if (!shader)
+        return;
+            
+#if !defined(OSG_GL_FIXED_FUNCTION_AVAILABLE)
+
+    GLSLChunker chunker;
+    GLSLChunker::Chunks chunks;
+    chunker.read(shader->getShaderSource(), chunks);
+
+    applySupportForNoFFPImpl(chunks);
+
+    std::string output;
+    chunker.write(chunks, output);
+    shader->setShaderSource(output);
+
+#endif // !defined(OSG_GL_FIXED_FUNCTION_AVAILABLE)
+}
 
-    if ( s_NO_FFP && shader )
+void
+ShaderPreProcessor::run(osg::Shader* shader)
+{
+    if ( shader )
     {
+        bool dirty = false;
+
+        // only runs for non-FFP (GLES, GL3+, etc.)
         std::string source = shader->getShaderSource();
 
+        // First replace any quotes with spaces. Quotes are illegal.
+        if ( source.find('\"') != std::string::npos )
+        {
+            osgEarth::replaceIn(source, "\"", " ");
+            dirty = true;
+        }
+
         // find the first legal insertion point for replacement declarations. GLSL requires that nothing
-        // precede a "#verson" compiler directive, so we must insert new declarations after it.
+        // precede a "#version" compiler directive, so we must insert new declarations after it.
         std::string::size_type declPos = source.rfind( "#version " );
         if ( declPos != std::string::npos )
         {
@@ -197,27 +346,47 @@ ShaderPreProcessor::run(osg::Shader* shader)
             declPos = 0;
         }
 
+#if !defined(OSG_GL_FIXED_FUNCTION_AVAILABLE)
+
         int maxLights = Registry::capabilities().getMaxLights();
 
         for( int i=0; i<maxLights; ++i )
         {
-            replaceAndInsertDeclaration(
+            if ( replaceAndInsertDeclaration(
                 source, declPos,
                 Stringify() << "gl_LightSource[" << i << "]",
                 Stringify() << "osg_LightSource" << i,
                 Stringify() 
                     << osg_LightSourceParameters::glslDefinition() << "\n"
-                    << "uniform osg_LightSourceParameters " );
+                    << "uniform osg_LightSourceParameters " ) )
+            {
+                dirty = true;
+            }
 
-            replaceAndInsertDeclaration(
+            if ( replaceAndInsertDeclaration(
                 source, declPos,
                 Stringify() << "gl_FrontLightProduct[" << i << "]", 
                 Stringify() << "osg_FrontLightProduct" << i,
                 Stringify()
                     << osg_LightProducts::glslDefinition() << "\n"
-                    << "uniform osg_LightProducts " );
+                    << "uniform osg_LightProducts " ) )
+            {
+                dirty = true;
+            }
         }
+#endif
+
+        // Chunk the shader.
+        GLSLChunker chunker;
+        GLSLChunker::Chunks chunks;
+        chunker.read( source, chunks );
 
+        applySupportForNoFFPImpl(chunks);
+
+        // Replace varyings with directives that the ShaderFactory can interpret
+        // when creating interface blocks.
+        replaceVaryings( shader->getType(), chunks );
+        chunker.write( chunks, source );
         shader->setShaderSource( source );
     }
 }
@@ -405,7 +574,7 @@ UpdateLightingUniformsHelper::~UpdateLightingUniformsHelper()
 void
 UpdateLightingUniformsHelper::cullTraverse( osg::Node* node, osg::NodeVisitor* nv )
 {
-    osgUtil::CullVisitor* cv = Culling::asCullVisitor(nv);
+    osgUtil::CullVisitor* cv = static_cast<osgUtil::CullVisitor*>(nv);
     if ( cv )
     {
         StateSetStack stateSetStack;
diff --git a/src/osgEarth/Shaders.cpp.in b/src/osgEarth/Shaders.cpp.in
index 9b7c70e..5c8d7b9 100644
--- a/src/osgEarth/Shaders.cpp.in
+++ b/src/osgEarth/Shaders.cpp.in
@@ -8,35 +8,35 @@ namespace osgEarth
     {
         // AlphaEffect
         AlphaEffectFragment = "AlphaEffect.frag.glsl";
-        _sources[AlphaEffectFragment] = OE_MULTILINE(@AlphaEffect.frag.glsl@);
+        _sources[AlphaEffectFragment] = "@AlphaEffect.frag.glsl@";
 
 
         // Depth Offset
         DepthOffsetVertex = "DepthOffset.vert.glsl";
-       _sources[DepthOffsetVertex] = OE_MULTILINE(@DepthOffset.vert.glsl@);
+       _sources[DepthOffsetVertex] = "@DepthOffset.vert.glsl@";
 
 
        // Draping
        DrapingVertex = "Draping.vert.glsl";
-       _sources[DrapingVertex] = OE_MULTILINE(@Draping.vert.glsl@);
+       _sources[DrapingVertex] = "@Draping.vert.glsl@";
 
        DrapingFragment = "Draping.frag.glsl";
-       _sources[DrapingFragment] = OE_MULTILINE(@Draping.frag.glsl@);
+       _sources[DrapingFragment] = "@Draping.frag.glsl@";
 
 
         // GPU Clamping
         GPUClampingVertex = "GPUClamping.vert.glsl";
-        _sources[GPUClampingVertex] = OE_MULTILINE(@GPUClamping.vert.glsl@);
+        _sources[GPUClampingVertex] = "@GPUClamping.vert.glsl@";
 
         GPUClampingFragment = "GPUClamping.frag.glsl";
-        _sources[GPUClampingFragment] = OE_MULTILINE(@GPUClamping.frag.glsl@);
+        _sources[GPUClampingFragment] = "@GPUClamping.frag.glsl@";
 
         GPUClampingVertexLib = "GPUClamping.vert.lib.glsl";
-        _sources[GPUClampingVertexLib] = OE_MULTILINE(@GPUClamping.vert.lib.glsl@);
+        _sources[GPUClampingVertexLib] = "@GPUClamping.vert.lib.glsl@";
 
 
         // DrawInstanced
         InstancingVertex = "Instancing.vert.glsl";
-        _sources[InstancingVertex] = OE_MULTILINE(@Instancing.vert.glsl@);
+        _sources[InstancingVertex] = "@Instancing.vert.glsl@";
     }
 };
\ No newline at end of file
diff --git a/src/osgEarth/Shadowing b/src/osgEarth/Shadowing
new file mode 100644
index 0000000..9cbed4a
--- /dev/null
+++ b/src/osgEarth/Shadowing
@@ -0,0 +1,41 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+* Copyright 2016 Pelican Mapping
+* http://osgearth.org
+*
+* osgEarth is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* 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.
+*
+* You should have received a copy of the GNU Lesser General Public License
+* along with this program.  If not, see <http://www.gnu.org/licenses/>
+*/
+#ifndef OSGEARTH_SHADOWING_H
+#define OSGEARTH_SHADOWING_H  1
+
+#include <osgEarth/Common>
+#include <osg/Camera>
+
+namespace osgEarth
+{
+    struct OSGEARTH_EXPORT Shadowing
+    {
+        /** Marks a camera as a shadow map camera */
+        static void setIsShadowCamera(osg::Camera* camera);
+
+        /** Whether a camera is marked as a shadow map camera */
+        static bool isShadowCamera(const osg::Camera* camera);
+    };
+
+}  // namespace osgEarth::Util
+
+#endif // OSGEARTH_SHADOWING_H
diff --git a/src/osgEarth/Shadowing.cpp b/src/osgEarth/Shadowing.cpp
new file mode 100644
index 0000000..bbdd0d6
--- /dev/null
+++ b/src/osgEarth/Shadowing.cpp
@@ -0,0 +1,42 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+* Copyright 2016 Pelican Mapping
+* http://osgearth.org
+*
+* osgEarth is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* 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.
+*
+* You should have received a copy of the GNU Lesser General Public License
+* along with this program.  If not, see <http://www.gnu.org/licenses/>
+*/
+#include <osgEarth/Shadowing>
+#include <osg/ValueObject>
+
+#define LC "[Shadowing] "
+
+using namespace osgEarth;
+
+
+void
+Shadowing::setIsShadowCamera(osg::Camera* camera)
+{
+    camera->setUserValue("oe_isShadowCamera", true);
+}
+
+bool
+Shadowing::isShadowCamera(const osg::Camera* camera)
+{
+    bool is = false;
+    camera->getUserValue("oe_isShadowCamera", is);
+    return is;
+}
diff --git a/src/osgEarth/SharedSARepo b/src/osgEarth/SharedSARepo
index 94e8c40..a6a46c2 100644
--- a/src/osgEarth/SharedSARepo
+++ b/src/osgEarth/SharedSARepo
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarth/SpatialReference b/src/osgEarth/SpatialReference
index 9353346..7be4c30 100644
--- a/src/osgEarth/SpatialReference
+++ b/src/osgEarth/SpatialReference
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -410,6 +410,10 @@ namespace osgEarth
             const std::string& proj4,
             const std::string& name = "" );
 
+		static SpatialReference* createFromUserInput(
+		    const std::string& input,
+            const std::string& name = "" );
+
         static SpatialReference* createCube();
 
 
diff --git a/src/osgEarth/SpatialReference.cpp b/src/osgEarth/SpatialReference.cpp
index 1dfd47f..8e0368c 100644
--- a/src/osgEarth/SpatialReference.cpp
+++ b/src/osgEarth/SpatialReference.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -132,7 +132,7 @@ SpatialReference::createFromPROJ4( const std::string& proj4, const std::string&
 	void* handle = OSRNewSpatialReference( NULL );
     if ( OSRImportFromProj4( handle, proj4.c_str() ) == OGRERR_NONE )
 	{
-        result = new SpatialReference( handle, "PROJ4" );
+        result = new SpatialReference( handle, std::string("PROJ4") );
 	}
 	else 
 	{
@@ -169,12 +169,21 @@ SpatialReference::createFromWKT( const std::string& wkt, const std::string& name
     osg::ref_ptr<SpatialReference> result;
     GDAL_SCOPED_LOCK;
     void* handle = OSRNewSpatialReference( NULL );
-    char buf[4096];
+    char buf[8192];
     char* buf_ptr = &buf[0];
-    strcpy( buf, wkt.c_str() );
+    if (wkt.length() < 8192)
+    {
+        strcpy( buf, wkt.c_str() );
+    }
+    else
+    {
+        OE_WARN << LC << "BUFFER OVERFLOW - INTERNAL ERROR\n";
+        return 0L;
+    }
+
     if ( OSRImportFromWkt( handle, &buf_ptr ) == OGRERR_NONE )
     {
-        result = new SpatialReference( handle, "WKT" );
+        result = new SpatialReference( handle, std::string("WKT") );
         result = result->fixWKT();
     }
     else 
@@ -186,6 +195,24 @@ SpatialReference::createFromWKT( const std::string& wkt, const std::string& name
 }
 
 SpatialReference*
+SpatialReference::createFromUserInput( const std::string& input, const std::string& name )
+{
+    osg::ref_ptr<SpatialReference> result;
+    GDAL_SCOPED_LOCK;
+    void* handle = OSRNewSpatialReference( NULL );
+    if ( OSRSetFromUserInput( handle, input.c_str() ) == OGRERR_NONE )
+    {
+        result = new SpatialReference( handle, std::string("UserInput") );
+    }
+    else 
+    {
+        //OE_WARN << LC << "Unable to create spatial reference from user input: " << input << std::endl;
+        OSRDestroySpatialReference( handle );
+    }
+    return result.release();
+}
+
+SpatialReference*
 SpatialReference::create( const std::string& horiz, const std::string& vert )
 {
     return create( Key(horiz, vert), true );
@@ -276,13 +303,20 @@ SpatialReference::create( const Key& key, bool useCache )
     else if (key.horizLower.find( "epsg:" )  == 0 ||
              key.horizLower.find( "osgeo:" ) == 0 )
     {
-        srs = createFromPROJ4( std::string("+init=") + key.horiz, key.horiz );
+        srs = createFromPROJ4( std::string("+init=") + key.horizLower, key.horiz );
     }
     else if (key.horizLower.find( "projcs" ) == 0 || 
              key.horizLower.find( "geogcs" ) == 0 )
     {
         srs = createFromWKT( key.horiz, key.horiz );
     }
+    else
+    {
+        // Try to set it from the user input.  This will handle things like CRS:84
+        // createFromUserInput will actually handle all valid inputs from GDAL, so we might be able to
+        // simplify this function and just call createFromUserInput.
+        srs = createFromUserInput( key.horiz, key.horiz );
+    }
 
     // bail out if no SRS exists by this point
     if ( srs == 0L )
@@ -380,7 +414,7 @@ SpatialReference::fixWKT()
 /****************************************************************************/
 
 
-SpatialReference::SpatialReference(void*              handle, 
+SpatialReference::SpatialReference(void* handle,
                                    const std::string& init_type) :
 osg::Referenced ( true ),
 _initialized    ( false ),
@@ -397,7 +431,8 @@ _is_contiguous  ( false ),
 _is_user_defined( false ),
 _is_ltp         ( false ),
 _is_plate_carre ( false ),
-_is_spherical_mercator( false )
+_is_spherical_mercator( false ),
+_ellipsoidId(0u)
 {
     // nop
 }
@@ -945,17 +980,12 @@ SpatialReference::createLocalToWorld(const osg::Vec3d& xyz, osg::Matrixd& out_lo
     }
     else
     {
-        // convert MSL to HAE if necessary:
-        osg::Vec3d geodetic;
-        if ( !transform(xyz, getGeodeticSRS(), geodetic) )
-            return false;
-
-        // then to ECEF:
+        // convert to ECEF:
         osg::Vec3d ecef;
-        if ( !transform(geodetic, getGeodeticSRS()->getECEF(), ecef) )
+        if ( !transform(xyz, getECEF(), ecef) )
             return false;
 
-        //out_local2world = ECEF::createLocalToWorld(ecef);        
+        // and create the matrix.
         _ellipsoid->computeLocalToWorldTransformFromXYZ(ecef.x(), ecef.y(), ecef.z(), out_local2world);
     }
     return true;
@@ -1357,7 +1387,6 @@ SpatialReference::transformExtentToMBR(const SpatialReference* to_srs,
     v.push_back( osg::Vec3d(in_out_xmin, in_out_ymax, 0) ); // ul
     v.push_back( osg::Vec3d(in_out_xmax, in_out_ymax, 0) ); // ur
     v.push_back( osg::Vec3d(in_out_xmax, in_out_ymin, 0) ); // lr
-
     if ( transform(v, to_srs) )
     {
         in_out_xmin = std::min( v[0].x(), v[1].x() );
@@ -1601,4 +1630,4 @@ SpatialReference::_init()
     }
 
     _initialized = true;
-}
+}
\ No newline at end of file
diff --git a/src/osgEarth/StateSetCache b/src/osgEarth/StateSetCache
index f0e1f40..b1eac8e 100644
--- a/src/osgEarth/StateSetCache
+++ b/src/osgEarth/StateSetCache
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
@@ -30,7 +30,23 @@
 namespace osgEarth
 {
     /**
-     * Cache for optimizing state set sharing.
+     * Cache for optimizing state set sharing. Running a sharing pass on a node
+     * (with the optimize method, or one of the consolidate methods) will reduce
+     * any duplicate state attribute or state sets down to a single instance.
+     * This can help reduce the number of state changes that occur when the node
+     * is rendered, though this is not guanranteed.
+     *
+     * This class is not thread safe. That means:
+     *
+     * You should ONLY use it on a node that contains nothing in the LIVE scene
+     * graph. It will replace state attributes and state sets on nodes that it finds;
+     * this is illegal if those objects are in use in another thread. So the typical
+     * use case is to run this on a newly-loaded model or on a newly-created node 
+     * graph before adding it to the live graph.
+     *
+     * It's OK for the contents of the cache itself to be present elsewhere, even
+     * in the live scene graph. These will not altered. So for example, you can re-use
+     * the same StateSetCache instance to optimize more than one new graph.
      */
     class OSGEARTH_EXPORT StateSetCache : public osg::Referenced
     {
diff --git a/src/osgEarth/StateSetCache.cpp b/src/osgEarth/StateSetCache.cpp
index 2226765..43a99f0 100644
--- a/src/osgEarth/StateSetCache.cpp
+++ b/src/osgEarth/StateSetCache.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarth/StateSetLOD b/src/osgEarth/StateSetLOD
index c6ba867..342353f 100644
--- a/src/osgEarth/StateSetLOD
+++ b/src/osgEarth/StateSetLOD
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarth/StateSetLOD.cpp b/src/osgEarth/StateSetLOD.cpp
index 321e6d0..c2ff9df 100644
--- a/src/osgEarth/StateSetLOD.cpp
+++ b/src/osgEarth/StateSetLOD.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarth/Status b/src/osgEarth/Status
new file mode 100644
index 0000000..779000f
--- /dev/null
+++ b/src/osgEarth/Status
@@ -0,0 +1,75 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+* Copyright 2016 Pelican Mapping
+* http://osgearth.org
+*
+* osgEarth is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* 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.
+*
+* You should have received a copy of the GNU Lesser General Public License
+* along with this program.  If not, see <http://www.gnu.org/licenses/>
+*/
+
+#ifndef OSGEARTH_STATUS_H
+#define OSGEARTH_STATUS_H 1
+
+#include <osgEarth/Common>
+
+namespace osgEarth
+{
+    /** General purpose status object */
+    class OSGEARTH_EXPORT Status
+    {
+    public:
+        enum Code {
+            NoError,
+            ResourceUnavailable,  // e.g. failure to access a file, URL, database, or other resource
+            ServiceUnavailable,   // e.g. failure to load a plugin, extension, or other module
+            ConfigurationError,   // required data or properties missing
+            AssertionFailure,     // an illegal software state was detected
+            GeneralError          // something else went wrong
+        };
+
+    public:
+        Status() : _code(NoError) { }
+        Status(const Status& rhs) : _code(rhs._code), _source(rhs._source), _msg(rhs._msg) { }
+        Status(const Code& code) : _code(code) { }
+        Status(const std::string& msg) : _code(GeneralError), _msg(msg) { }
+        Status(const Code& code, const std::string& msg) : _code(code), _msg(msg) { }
+        Status(const std::string& source, const std::string& msg) : _code(GeneralError), _source(source), _msg(msg) { }
+        Status(const Code& code, const std::string& source, const std::string& msg) : _code(code), _source(source), _msg(msg) { }
+        bool isOK() const { return _code == NoError; }
+        bool isError() const { return !isOK(); }
+        const Code& code() const { return _code; }
+        const std::string& source() const { return _source; }
+        const std::string& message() const { return _msg; }
+        bool operator == (const Status& rhs) const { return _code == rhs._code && _source.compare(rhs._source) == 0 && _msg.compare(rhs._msg) == 0; }
+        bool operator != (const Status& rhs) const { return !(*this==rhs); }
+        bool const operator ! () const { return isError(); }
+        static Status OK() { return Status(); }
+        static Status Error(const Code& code) { return Status(code); }
+        static Status Error(const std::string& msg) { return Status(msg); }
+        static Status Error(const Code& code, const std::string& msg) { return Status(code, msg); }
+        static Status Error(const std::string& owner, const std::string& msg) { return Status(owner, msg); }
+        static Status Error(const Code& code, const std::string& owner, const std::string& msg) { return Status(code, owner, msg); }
+        std::string toString() const;
+    private:
+        Code _code;
+        std::string _source;
+        std::string _msg;
+    };
+
+    extern OSGEARTH_EXPORT const Status STATUS_OK;
+}
+
+#endif // OSGEARTH_STATUS_H
diff --git a/src/osgEarth/Status.cpp b/src/osgEarth/Status.cpp
new file mode 100644
index 0000000..ca28c46
--- /dev/null
+++ b/src/osgEarth/Status.cpp
@@ -0,0 +1,47 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+ * Copyright 2016 Pelican Mapping
+ * http://osgearth.org
+ *
+ * osgEarth is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ */
+#include <osgEarth/Status>
+#include <osgEarth/StringUtils>
+
+using namespace osgEarth;
+
+#define LC "[Status] "
+
+const osgEarth::Status osgEarth::STATUS_OK;
+
+namespace
+{
+    const std::string m[] = {
+        "No error",
+        "Resource unavailable",
+        "Service unavailable",
+        "Configuration error",
+        "Assertion failure",
+        "Error"
+    };
+}
+
+std::string
+Status::toString() const
+{
+    return Stringify()
+        << ((int)_code < 6 ? m[(int)_code] : "Bad error code")
+        << " : "
+        << message();
+}
diff --git a/src/osgEarth/StringUtils b/src/osgEarth/StringUtils
index 6d4c34f..e2a0681 100644
--- a/src/osgEarth/StringUtils
+++ b/src/osgEarth/StringUtils
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -57,6 +57,11 @@ namespace osgEarth
     extern OSGEARTH_EXPORT std::string trim( const std::string& in );
 
     /**
+     * Trims whitespace from the ends of a string; in-place modification on the string to reduce string copies.
+     */
+    extern OSGEARTH_EXPORT void trim2( std::string& str );
+
+    /**
      * True is "ref" starts with "pattern"
      */
     extern OSGEARTH_EXPORT bool startsWith( 
@@ -119,6 +124,9 @@ namespace osgEarth
     /** Generates a hashed integer for a string (poor man's MD5) */
     extern OSGEARTH_EXPORT unsigned hashString( const std::string& input );
 
+    /** Same as hashString but returns a string value. */
+    extern OSGEARTH_EXPORT std::string hashToString(const std::string& input);
+
     /**
     * Gets the total number of seconds formatted as H:M:S
     */
diff --git a/src/osgEarth/StringUtils.cpp b/src/osgEarth/StringUtils.cpp
index 0ffbcf6..8cc7921 100644
--- a/src/osgEarth/StringUtils.cpp
+++ b/src/osgEarth/StringUtils.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -32,9 +32,9 @@ _trimTokens  ( true )
     addQuotes( quotes );
 }
 
-StringTokenizer::StringTokenizer(const std::string& input, 
+StringTokenizer::StringTokenizer(const std::string& input,
                                  StringVector&      output,
-                                 const std::string& delims, 
+                                 const std::string& delims,
                                  const std::string& quotes,
                                  bool               allowEmpties,
                                  bool               trimTokens ) :
@@ -83,7 +83,7 @@ StringTokenizer::tokenize( const std::string& input, StringVector& output ) cons
 
     for( std::string::const_iterator i = input.begin(); i != input.end(); ++i )
     {
-        char c = *i;    
+        char c = *i;
 
         TokenMap::const_iterator q = _quotes.find( c );
 
@@ -119,9 +119,9 @@ StringTokenizer::tokenize( const std::string& input, StringVector& output ) cons
                 }
                 else
                 {
-                    std::string bufstr;
-                    bufstr = buf.str();
-                    std::string token = _trimTokens ? trim(bufstr) : bufstr;
+                    std::string token = buf.str();
+                    if ( _trimTokens )
+                        trim2( token );
 
                     if ( _allowEmpties || !token.empty() )
                         output.push_back( token );
@@ -134,14 +134,14 @@ StringTokenizer::tokenize( const std::string& input, StringVector& output ) cons
                     buf.str("");
                 }
             }
-        }       
+        }
     }
 
-    std::string bufstr;
-    bufstr = buf.str();
-    std::string last = _trimTokens ? trim(bufstr) : bufstr;
-    if ( !last.empty() )
-        output.push_back( last );
+    std::string bufstr = buf.str();
+    if ( _trimTokens )
+        trim2( bufstr );
+    if ( !bufstr.empty() )
+        output.push_back( bufstr );
 }
 
 //--------------------------------------------------------------------------
@@ -186,10 +186,10 @@ osgEarth::hashString( const std::string& input )
     while(len >= 4)
     {
         unsigned int k = *(unsigned int *)data;
-        k *= m; 
-        k ^= k >> r; 
-        k *= m;     		
-        h *= m; 
+        k *= m;
+        k ^= k >> r;
+        k *= m;
+        h *= m;
         h ^= k;
         data += 4;
         len -= 4;
@@ -210,6 +210,12 @@ osgEarth::hashString( const std::string& input )
     return h;
 }
 
+std::string
+osgEarth::hashToString(const std::string& input)
+{
+    return Stringify() << std::hex << std::setw(8) << std::setfill('0') << hashString(input);
+}
+
 
 /** Parses an HTML color ("#rrggbb" or "#rrggbbaa") into an OSG color. */
 osg::Vec4f
@@ -328,7 +334,7 @@ std::string&
 osgEarth::ciReplaceIn( std::string& s, const std::string& pattern, const std::string& replacement )
 {
     if ( pattern.empty() ) return s;
-    
+
     std::string upperSource = s;
     std::transform( upperSource.begin(), upperSource.end(), upperSource.begin(), (int(*)(int))std::toupper );
 
@@ -352,11 +358,10 @@ osgEarth::ciReplaceIn( std::string& s, const std::string& pattern, const std::st
 * by Rodrigo C F Dias
 * http://www.codeproject.com/KB/stl/stdstringtrim.aspx
 */
-std::string 
-osgEarth::trim( const std::string& in )
+void
+osgEarth::trim2( std::string& str )
 {
-    std::string whitespace (" \t\f\v\n\r");
-    std::string str = in;
+    static const std::string whitespace (" \t\f\v\n\r");
     std::string::size_type pos = str.find_last_not_of( whitespace );
     if(pos != std::string::npos) {
         str.erase(pos + 1);
@@ -364,6 +369,17 @@ osgEarth::trim( const std::string& in )
         if(pos != std::string::npos) str.erase(0, pos);
     }
     else str.erase(str.begin(), str.end());
+}
+
+/**
+* Trims whitespace from the ends of a string, returning a
+* copy of the string with whitespace removed.
+*/
+std::string
+osgEarth::trim( const std::string& in )
+{
+    std::string str = in;
+    trim2( str );
     return str;
 }
 
@@ -418,7 +434,7 @@ osgEarth::prettyPrintSize( double mb )
     {
         buf << (mb / 1024.0) << " GB";
     }
-    else 
+    else
     {
         buf << mb << " MB";
     }
diff --git a/src/osgEarth/TaskService b/src/osgEarth/TaskService
index 9732182..dbf537a 100644
--- a/src/osgEarth/TaskService
+++ b/src/osgEarth/TaskService
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarth/TaskService.cpp b/src/osgEarth/TaskService.cpp
index bfb9739..8e4318c 100644
--- a/src/osgEarth/TaskService.cpp
+++ b/src/osgEarth/TaskService.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -30,7 +30,11 @@ using namespace OpenThreads;
 TaskRequest::TaskRequest( float priority ) :
 osg::Referenced( true ),
 _priority( priority ),
-_state( STATE_IDLE )
+_state( STATE_IDLE ),
+_stamp(0),
+_startTime(0),
+_endTime(0),
+_completedEvent(0L)
 {
     _progress = new ProgressCallback();
 }
@@ -68,8 +72,10 @@ TaskRequest::wasCanceled() const
 TaskRequestQueue::TaskRequestQueue(unsigned int maxSize) :
 osg::Referenced( true ),
 _done( false ),
-_maxSize( maxSize )
+_maxSize( maxSize ),
+_stamp(0)
 {
+    //nop
 }
 
 void
diff --git a/src/osgEarth/Terrain b/src/osgEarth/Terrain
index 5bfd682..260e405 100644
--- a/src/osgEarth/Terrain
+++ b/src/osgEarth/Terrain
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -238,12 +238,12 @@ namespace osgEarth
          *      Terrain callback to add. This will get called whenever tile data changes in
          *      the active terrain graph
          */
-        void addTerrainCallback( TerrainCallback* callback);
+        void addTerrainCallback(TerrainCallback* callback);
 
         /**
          * Removes a terrain callback.
          */
-        void removeTerrainCallback( TerrainCallback* callback );
+        void removeTerrainCallback(TerrainCallback* callback );
         
 
     public:
diff --git a/src/osgEarth/Terrain.cpp b/src/osgEarth/Terrain.cpp
index 0fe1674..21d15f7 100644
--- a/src/osgEarth/Terrain.cpp
+++ b/src/osgEarth/Terrain.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -110,6 +110,18 @@ Terrain::getHeight(osg::Node*              patch,
     if ( !getProfile()->getExtent().contains(x, y) )
         return 0L;
 
+    if (srs && srs->isGeographic())
+    {
+        // perturb polar latitudes slightly to prevent intersection anomaly at the poles
+        if (getSRS()->isGeographic())
+        {
+            if (osg::equivalent(y, 90.0))
+                y -= 1e-7;
+            else if (osg::equivalent(y, -90))
+                y += 1e-7;
+        }
+    }
+
     const osg::EllipsoidModel* em = getSRS()->getEllipsoid();
     double r = std::min( em->getRadiusEquator(), em->getRadiusPolar() );
 
@@ -275,7 +287,9 @@ Terrain::addTerrainCallback( TerrainCallback* cb )
 {
     if ( cb )
     {        
-        Threading::ScopedWriteLock exclusiveLock( _callbacksMutex );
+        removeTerrainCallback( cb );
+
+        Threading::ScopedWriteLock exclusiveLock( _callbacksMutex );        
         _callbacks.push_back( cb );
         ++_callbacksSize; // atomic increment
     }
diff --git a/src/osgEarth/TerrainEffect b/src/osgEarth/TerrainEffect
index 0a20136..6388f6b 100644
--- a/src/osgEarth/TerrainEffect
+++ b/src/osgEarth/TerrainEffect
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarth/TerrainEngineNode b/src/osgEarth/TerrainEngineNode
index c4e6100..58988c4 100644
--- a/src/osgEarth/TerrainEngineNode
+++ b/src/osgEarth/TerrainEngineNode
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -23,33 +23,94 @@
 #include <osgEarth/MapFrame>
 #include <osgEarth/Terrain>
 #include <osgEarth/TerrainEffect>
+#include <osgEarth/TerrainTileModelFactory>
 #include <osgEarth/TerrainTileNode>
+#include <osgEarth/TerrainEngineRequirements>
 #include <osgEarth/TextureCompositor>
 #include <osgEarth/ShaderUtils>
+#include <osgEarth/TilePatchCallback>
+#include <osgEarth/Progress>
 #include <osg/CoordinateSystemNode>
 #include <osg/Geode>
 #include <osg/NodeCallback>
+#include <osgUtil/RenderBin>
 
 #define OSGEARTH_ENV_TERRAIN_ENGINE_DRIVER "OSGEARTH_TERRAIN_ENGINE"
 
+namespace osgUtil {
+    class CullVisitor;
+}
+
 namespace osgEarth
 {
     class TerrainEffect;
+    class VirtualProgram;
 
     /**
-     * Interface for querying terrain engine feature requirements.
+     * Interface for and object that can create a new terrain tile models
      */
-    class TerrainEngineRequirements
+    class /*interface*/ TerrainEngine
     {
     public:
-        virtual bool elevationTexturesRequired() const =0;
-        virtual bool normalTexturesRequired() const =0;
-        virtual bool parentTexturesRequired() const =0;
+        /**
+         * Callback for new node creation.
+         */
+        class NodeCallback : public osg::Referenced
+        {
+        public:
+            virtual void operator()(const TileKey& key, osg::Node* node) =0;
+
+        protected:
+            NodeCallback() { }
+            virtual ~NodeCallback() { }
+        };
 
     public:
-        virtual ~TerrainEngineRequirements() { }
+        /**
+         * Unique ID of this engine.
+         */
+        virtual UID getUID() const =0;
+
+        /**
+         * Creates a new data model for a terrain tile, calling any registered
+         * CreateTileModelCallbacks before returning the new object.
+         *
+         * @param frame Map frame from which to create the new tile model
+         * @param key   Key for which to create the new tile model
+         * @param modelStore Optional interface for accessing other previously
+         *                   created tile models (see TerrainTileModelFactory)
+         * @param progress Optional progress/stats tracking callback
+         */
+        virtual TerrainTileModel* createTileModel(
+            const MapFrame&              frame,
+            const TileKey&               key,
+            ProgressCallback*            progress ) =0;
+
+        
+        /**
+         * Notify the engine of a completed tile node creation, so it can 
+         * activate callbacks. (This might happen in a pager thread.)
+         *
+         * @param key  TileKey corresponding to the new Node
+         * @param node The new terrain node.
+         */
+        virtual void notifyOfTerrainTileNodeCreation(
+            const TileKey& key,
+            osg::Node*     node) =0;
     };
 
+
+
+    /**
+     * A callback that lets you customize the computed range for a terrain tile.
+     * Providing a custom range can let applications better control how paging behaves.
+     */
+    struct ComputeRangeCallback : public osg::Referenced
+    {
+        virtual float operator()(osg::Node* node, osg::NodeVisitor& nv) = 0;
+    };
+
+
     /**
      * TerrainEngineNode is the base class and interface for map engine implementations.
      *
@@ -57,7 +118,7 @@ namespace osgEarth
      * actual geometry representing the Earth.
      */
     class OSGEARTH_EXPORT TerrainEngineNode : public osg::CoordinateSystemNode,
-                                              public TerrainTileNodeBroker,
+                                              public TerrainEngine,
                                               public TerrainEngineRequirements
     {
     public:
@@ -106,22 +167,62 @@ namespace osgEarth
         void requireParentTextures();
 
         /** Access the stateset used to render the terrain. */
-        virtual osg::StateSet* getTerrainStateSet() { return getOrCreateStateSet(); }
+        virtual osg::StateSet* getSurfaceStateSet() { return getOrCreateStateSet(); }
+
+        /** Adds a tile patch callback. */
+        virtual void addTilePatchCallback(TilePatchCallback*);
+
+        /** Removes a tile patch callback. */
+        virtual void removeTilePatchCallback(TilePatchCallback*);
+
+        /** Gets the ComputeRangeCallback for this TerrainEngineNode */
+        ComputeRangeCallback* getComputeRangeCallback() const;
+
+        /** Sets the ComputeRangeCallback for this TerrainEngineNode */
+        void setComputeRangeCallback(ComputeRangeCallback* computeRangeCallback);
+
+        // Request that the terrain tiles be rebuilt.
+        virtual void dirtyTerrain();
+
+
+
+    public: // TerrainEngine
+
+        TerrainTileModel* createTileModel(
+            const MapFrame&              frame,
+            const TileKey&               key,
+            ProgressCallback*            progress );
+
+        void notifyOfTerrainTileNodeCreation(
+            const TileKey& key, 
+            osg::Node*     node);
+
+    public:
+
+        /**
+         * Callback for customizing the TileModel.
+         */
+        class CreateTileModelCallback : public osg::Referenced
+        {
+        public:
+            virtual void onCreateTileModel(
+                TerrainEngineNode* engine,
+                TerrainTileModel*  model) = 0;
+        };
+
+        /**
+         * Adds a TileModel creation callback, so you can add custom data
+         * to the TileModel after it's created.
+         */
+        void addCreateTileModelCallback(CreateTileModelCallback* callback);
+        void removeCreateTileModelCallback(CreateTileModelCallback* callback);
 
-        /** Access the stateset used to render payload data. */
-        virtual osg::StateSet* getPayloadStateSet() { return getOrCreateStateSet(); }
 
     public: // TerrainEngineRequirements
 
         bool normalTexturesRequired() const { return _requireNormalTextures; }
         bool elevationTexturesRequired() const { return _requireElevationTextures; }
         bool parentTexturesRequired() const { return _requireParentTextures; }
-
-    public:
-        // adds a callback that will be fired while the terrain engine is building
-        // a tile node in a background thread.
-        void addTileNodeCallback(TerrainTileNodeCallback* cb);
-        void removeTileNodeCallback(TerrainTileNodeCallback* cb);
             
 
     public: // Runtime properties
@@ -131,7 +232,7 @@ namespace osgEarth
         void setVerticalScale( float value );
 
         /** Gets the scale factor to apply to elevation height values.
-          * #deprecated */
+          * @deprecated */
         float getVerticalScale() const { return _verticalScale; }
 
     public: // deprecated
@@ -141,9 +242,6 @@ namespace osgEarth
 
     protected:
         TerrainEngineNode();
-
-        //TerrainEngineNode( const TerrainEngineNode& rhs, const osg::CopyOp& op =osg::CopyOp::DEEP_COPY_ALL );
-
         virtual ~TerrainEngineNode();
 
     public: // osg::Node overrides
@@ -151,7 +249,10 @@ namespace osgEarth
         virtual void traverse( osg::NodeVisitor& );
 
     protected: // implementation events
+
+        /** @deprecated */
         virtual void onVerticalScaleChanged() { }
+        /** @deprecated */
         virtual void onElevationSamplingRatioChanged() { }
 
     protected:
@@ -165,8 +266,9 @@ namespace osgEarth
         // signals that a redraw is needed because something changed.
         virtual void requestRedraw();
 
-        // Request that the terrain tiles be rebuilt.
-        virtual void dirtyTerrain();
+        // Request the state setup be refreshed because something has changed that requires new
+        // shaders, state, etc.
+        virtual void dirtyState() { }
 
         // allow subclasses direct access for convenience.
         osg::ref_ptr<TextureCompositor> _texCompositor;
@@ -177,11 +279,7 @@ namespace osgEarth
 
         // called by addTileNodeCallback to notify any already-existing nodes
         // of the new callback.
-        virtual void notifyExistingNodes(TerrainTileNodeCallback* cb) { }
-
-    public: // TerrainTileNodeBroker
-
-        void notifyOfTerrainTileNodeCreation(const TileKey& key, osg::Node* node);
+        virtual void notifyExistingNodes(TerrainEngine::NodeCallback* cb) { }
 
     public: // utility
 
@@ -189,8 +287,11 @@ namespace osgEarth
          * Utility function that will return an osg::Node representing the geometry
          * for a tile key. The node is standalone; it has no ability to load children
          * or receive updates.
+         *
+         * TODO: deprecate in favor of a separate utility for creating simple
+         * geometry out of a TerrainTileModel. -gw
          */
-        virtual osg::Node* createTile( const TileKey& key ) =0;
+        virtual osg::Node* createTile(const TileKey& key) =0;
 
     private:
         friend struct TerrainEngineNodeCallbackProxy;
@@ -231,9 +332,21 @@ namespace osgEarth
         typedef std::vector<osg::ref_ptr<TerrainEffect> > TerrainEffectVector;
         TerrainEffectVector effects_;
 
-        typedef std::vector<osg::ref_ptr<TerrainTileNodeCallback> > TerrainTileNodeCallbackVector;
-        TerrainTileNodeCallbackVector _tileNodeCallbacks;
+        typedef std::vector<osg::ref_ptr<TerrainEngine::NodeCallback> > NodeCallbackVector;
+        NodeCallbackVector _tileNodeCallbacks;
         mutable Threading::Mutex _tileNodeCallbacksMutex;
+        
+        typedef std::vector<osg::ref_ptr<CreateTileModelCallback> > CreateTileModelCallbacks;
+        CreateTileModelCallbacks _createTileModelCallbacks;
+        mutable Threading::ReadWriteMutex _createTileModelCallbacksMutex;
+
+        osg::ref_ptr<TerrainTileModelFactory> _tileModelFactory;
+
+        osg::ref_ptr<ComputeRangeCallback> _computeRangeCallback;
+
+    protected:
+
+        TilePatchCallbacks _tilePatchCallbacks;
 
     public:
 
diff --git a/src/osgEarth/TerrainEngineNode.cpp b/src/osgEarth/TerrainEngineNode.cpp
index d359d3e..c41cff8 100644
--- a/src/osgEarth/TerrainEngineNode.cpp
+++ b/src/osgEarth/TerrainEngineNode.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -23,6 +23,8 @@
 #include <osgEarth/TextureCompositor>
 #include <osgEarth/NodeUtils>
 #include <osgEarth/MapModelChange>
+#include <osgEarth/TerrainTileModelFactory>
+#include <osgEarth/TraversalData>
 #include <osgDB/ReadFile>
 #include <osg/CullFace>
 #include <osg/PolygonOffset>
@@ -77,6 +79,7 @@ TerrainEngineNode::addEffect(TerrainEffect* effect)
     {
         effects_.push_back( effect );
         effect->onInstall( this );
+        dirtyState();
     }
 }
 
@@ -90,6 +93,7 @@ TerrainEngineNode::removeEffect(TerrainEffect* effect)
         TerrainEffectVector::iterator i = std::find(effects_.begin(), effects_.end(), effect);
         if ( i != effects_.end() )
             effects_.erase( i );
+        dirtyState();
     }
 }
 
@@ -116,13 +120,13 @@ _initStage               ( INIT_NONE ),
 _dirtyCount              ( 0 ),
 _requireElevationTextures( false ),
 _requireNormalTextures   ( false ),
-_requireParentTextures   ( false )
+_requireParentTextures   ( false ),
+_redrawRequired          ( true )
 {
     // register for event traversals so we can properly reset the dirtyCount
     ADJUST_EVENT_TRAV_COUNT( this, 1 );
 }
 
-
 TerrainEngineNode::~TerrainEngineNode()
 {
     //Remove any callbacks added to the image layers
@@ -192,15 +196,21 @@ TerrainEngineNode::preInitialize( const Map* map, const TerrainOptions& options
     if ( !_map->isGeocentric() )
         this->setEllipsoidModel( NULL );
     
-    // install the proper layer composition technique:
+    // install an object to manage texture image unit usage:
     _texCompositor = new TextureCompositor();
+    std::set<int> offLimits = osgEarth::Registry::instance()->getOffLimitsTextureImageUnits();
+    for(std::set<int>::const_iterator i = offLimits.begin(); i != offLimits.end(); ++i)
+        _texCompositor->setTextureImageUnitOffLimits( *i );
 
     // then register the callback so we can process further map model changes
     _map->addMapCallback( new TerrainEngineNodeCallbackProxy( this ) );
 
-    // enable backface culling
-    osg::StateSet* set = getOrCreateStateSet();
-    set->setMode( GL_CULL_FACE, 1 );
+    // apply render bin if necessary
+    if ( options.binNumber().isSet() )
+    {
+        osg::StateSet* set = getOrCreateStateSet();
+        set->setRenderBinDetails( options.binNumber().get(), "RenderBin" );
+    }
 
     if ( options.enableMercatorFastPath().isSet() )
     {
@@ -208,6 +218,10 @@ TerrainEngineNode::preInitialize( const Map* map, const TerrainOptions& options
             << LC << "Mercator fast path " 
             << (options.enableMercatorFastPath()==true? "enabled" : "DISABLED") << std::endl;
     }
+    
+    // a default factory - this is the object that creates the data model for
+    // each terrain tile.
+    _tileModelFactory = new TerrainTileModelFactory(options);
 
     _initStage = INIT_PREINIT_COMPLETE;
 }
@@ -289,6 +303,57 @@ TerrainEngineNode::onMapModelChanged( const MapModelChange& change )
     requestRedraw();
 }
 
+TerrainTileModel*
+TerrainEngineNode::createTileModel(const MapFrame&   frame,
+                                   const TileKey&    key,
+                                   ProgressCallback* progress)
+{
+    TerrainEngineRequirements* requirements = this;
+
+    // Ask the factory to create a new tile model:
+    osg::ref_ptr<TerrainTileModel> model = _tileModelFactory->createTileModel(
+        frame, 
+        key, 
+        requirements, 
+        progress);
+
+    if ( model.valid() )
+    {
+        // Fire all registered tile model callbacks, so user code can 
+        // add to or otherwise customize the model before it's returned
+        Threading::ScopedReadLock sharedLock(_createTileModelCallbacksMutex);
+        for(CreateTileModelCallbacks::iterator i = _createTileModelCallbacks.begin();
+            i != _createTileModelCallbacks.end();
+            ++i)
+        {
+            i->get()->onCreateTileModel(this, model.get());
+        }
+    }
+    return model.release();
+}
+
+void 
+TerrainEngineNode::addCreateTileModelCallback(CreateTileModelCallback* callback)
+{
+    Threading::ScopedWriteLock exclusiveLock(_createTileModelCallbacksMutex);
+    _createTileModelCallbacks.push_back(callback);
+}
+
+void 
+TerrainEngineNode::removeCreateTileModelCallback(CreateTileModelCallback* callback)
+{
+    Threading::ScopedWriteLock exclusiveLock(_createTileModelCallbacksMutex);
+    for(CreateTileModelCallbacks::iterator i = _createTileModelCallbacks.begin(); i != _createTileModelCallbacks.end(); ++i)
+    {
+        if ( i->get() == callback )
+        {
+            _createTileModelCallbacks.erase( i );
+            break;
+        }
+    }
+}
+
+
 namespace
 {
     Threading::Mutex s_opqlock;
@@ -332,34 +397,39 @@ TerrainEngineNode::traverse( osg::NodeVisitor& nv )
     osg::CoordinateSystemNode::traverse( nv );
 }
 
+//todo: remove?
 void
-TerrainEngineNode::addTileNodeCallback(TerrainTileNodeCallback* cb)
+TerrainEngineNode::notifyOfTerrainTileNodeCreation(const TileKey& key, osg::Node* node)
 {
     Threading::ScopedMutexLock lock(_tileNodeCallbacksMutex);
-    _tileNodeCallbacks.push_back( cb );
-    notifyExistingNodes( cb );
+    for(unsigned i=0; i<_tileNodeCallbacks.size(); ++i)
+    {
+        _tileNodeCallbacks[i]->operator()(key, node);
+    }
 }
 
 void
-TerrainEngineNode::removeTileNodeCallback(TerrainTileNodeCallback* cb)
+TerrainEngineNode::addTilePatchCallback(TilePatchCallback* cb)
 {
-    Threading::ScopedMutexLock lock(_tileNodeCallbacksMutex);
-    for(TerrainTileNodeCallbackVector::iterator i = _tileNodeCallbacks.begin(); i != _tileNodeCallbacks.end(); ++i)
-    {
-        if ( i->get() == cb )
-        {
-            _tileNodeCallbacks.erase( i );
-            break;
-        }
-    }
+    _tilePatchCallbacks.push_back( cb );
 }
 
 void
-TerrainEngineNode::notifyOfTerrainTileNodeCreation(const TileKey& key, osg::Node* node)
+TerrainEngineNode::removeTilePatchCallback(TilePatchCallback* cb)
 {
-    Threading::ScopedMutexLock lock(_tileNodeCallbacksMutex);
-    for(unsigned i=0; i<_tileNodeCallbacks.size(); ++i)
-        _tileNodeCallbacks[i]->operator()(key, node);
+    std::remove(_tilePatchCallbacks.begin(), _tilePatchCallbacks.end(), cb);
+}
+
+ComputeRangeCallback*
+TerrainEngineNode::getComputeRangeCallback() const
+{
+    return _computeRangeCallback.get();
+}
+
+void
+TerrainEngineNode::setComputeRangeCallback(ComputeRangeCallback* computeRangeCallback)
+{
+    _computeRangeCallback = computeRangeCallback;
 }
 
 
diff --git a/src/osgEarth/TerrainEngineRequirements b/src/osgEarth/TerrainEngineRequirements
new file mode 100644
index 0000000..96a31b9
--- /dev/null
+++ b/src/osgEarth/TerrainEngineRequirements
@@ -0,0 +1,39 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+ * Copyright 2008-2014 Pelican Mapping
+ * http://osgearth.org
+ *
+ * osgEarth is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ */
+#ifndef OSGEARTH_TERRAIN_ENGINE_REQUIREMENTS_H
+#define OSGEARTH_TERRAIN_ENGINE_REQUIREMENTS_H 1
+
+namespace osgEarth
+{
+    /**
+     * Interface for querying terrain engine feature requirements.
+     */
+    class TerrainEngineRequirements
+    {
+    public:
+        virtual bool elevationTexturesRequired() const =0;
+        virtual bool normalTexturesRequired() const =0;
+        virtual bool parentTexturesRequired() const =0;
+
+    public:
+        virtual ~TerrainEngineRequirements() { }
+    };
+}
+
+#endif // OSGEARTH_TERRAIN_ENGINE_REQUIREMENTS_H
diff --git a/src/osgEarth/TerrainLayer b/src/osgEarth/TerrainLayer
index 15724ad..de86cf8 100644
--- a/src/osgEarth/TerrainLayer
+++ b/src/osgEarth/TerrainLayer
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -28,6 +28,7 @@
 #include <osgEarth/Profile>
 #include <osgEarth/ThreadingUtils>
 #include <osgEarth/HTTPClient>
+#include <osgEarth/Status>
 
 namespace osgEarth
 {
@@ -128,13 +129,6 @@ namespace osgEarth
         const optional<std::string>& cacheId() const { return _cacheId; }
 
         /**
-         * The format that this MapLayer should use when caching. This can be a mime type
-         * or a file extension.
-         */
-        optional<std::string>& cacheFormat() { return _cacheFormat; }
-        const optional<std::string>& cacheFormat() const { return _cacheFormat; }
-
-        /**
          * Caching policy to use for this layer.
          */
         optional<CachePolicy>& cachePolicy() { return _cachePolicy; }
@@ -187,7 +181,6 @@ namespace osgEarth
         optional<unsigned>          _maxDataLevel;
 
         optional<std::string>       _cacheId;
-        optional<std::string>       _cacheFormat;
         optional<CachePolicy>       _cachePolicy;
         optional<ProxySettings>     _proxySettings;
     };
@@ -223,6 +216,12 @@ namespace osgEarth
 
     public:
 
+        /** Opens the layer and initializes the data source. */
+        const Status& open();
+
+        /** Gets the status of this layer, which will be unset if open() has not been called. */
+        const Status& getStatus() const { return _status; }
+
         /**
          * The options data connected to this layer.
          */
@@ -292,25 +291,21 @@ namespace osgEarth
          */
         virtual void setTargetProfileHint( const Profile* profile );
 
-        /** 
-         * The cache bin for storing data generated by this layer
-         */
-        virtual CacheBin* getCacheBin( const Profile* profile );
-        
         /**
-         * Gets the Cache to be used on this TerrainLayer.
+         * Disable this layer, setting an error status.
          */
-        Cache* getCache() const { return _cache.get(); }
+        void disable(const std::string& msg);
 
         /**
-         * Convenience function to check for cache_only mode
+         * Sets the I/O options to use. This data may include cache information.
          */
-        bool isCacheOnly() const;
-        
+        void setReadOptions(const osgDB::Options* readOptions);
+
         /**
-         * Convenience check for no-cache mode.
+         * Data Extents reported for this layer are copied into output.
+         * Returns true on success, false is there are no extents to report.
          */
-        bool isNoCache() const;
+        bool getDataExtents(DataExtentList& output) const;
 
 
     public: // Layer interface
@@ -324,60 +319,17 @@ namespace osgEarth
          * Metadata about the terrain layer that is stored in the cache, and read
          * when the cache is opened.
          */
-        struct CacheBinMetadata
+        struct OSGEARTH_EXPORT CacheBinMetadata : public osg::Referenced
         {
-            CacheBinMetadata() :
-                _valid(false) { }
-
-            CacheBinMetadata( const CacheBinMetadata& rhs ) :
-                _valid          ( rhs._valid ),
-                _cacheBinId     ( rhs._cacheBinId ),
-                _sourceName     ( rhs._sourceName ),
-                _sourceDriver   ( rhs._sourceDriver ),
-                _sourceTileSize ( rhs._sourceTileSize ),
-                _sourceProfile  ( rhs._sourceProfile ),
-                _cacheProfile   ( rhs._cacheProfile ),   
-                _cacheCreateTime( rhs._cacheCreateTime ) { }
-
-            CacheBinMetadata( const Config& conf )
-            {
-                _valid = !conf.empty();
-
-                conf.getIfSet   ( "cachebin_id",      _cacheBinId );
-                conf.getIfSet   ( "source_name",      _sourceName );
-                conf.getIfSet   ( "source_driver",    _sourceDriver );   
-                conf.getIfSet   ( "source_tile_size", _sourceTileSize );           
-                conf.getObjIfSet( "source_profile",   _sourceProfile );
-                conf.getObjIfSet( "cache_profile",    _cacheProfile ); 
-                conf.getIfSet   ( "cache_create_time", _cacheCreateTime ); 
-                
-                // check for validity. This will reject older caches that don't have
-                // sufficient attribution.
-                if ( _valid )
-                {
-                    if (!conf.hasValue("source_tile_size") ||
-                        !conf.hasChild("source_profile")   ||
-                        !conf.hasChild("cache_profile"))
-                    {
-                        _valid = false;
-                    }
-                }
-            }
-
-            bool isValid() const { return _valid; }
-
-            Config getConfig() const
-            {
-                Config conf( "osgearth_terrainlayer_cachebin" );
-                conf.addIfSet   ( "cachebin_id",       _cacheBinId );
-                conf.addIfSet   ( "source_name",       _sourceName );
-                conf.addIfSet   ( "source_driver",     _sourceDriver );      
-                conf.addIfSet   ( "source_tile_size",  _sourceTileSize );
-                conf.addObjIfSet( "source_profile",    _sourceProfile );
-                conf.addObjIfSet( "cache_profile",     _cacheProfile );
-                conf.addIfSet   ( "cache_create_time", _cacheCreateTime );
-                return conf;
-            }
+            CacheBinMetadata();
+
+            CacheBinMetadata( const CacheBinMetadata& rhs );
+
+            CacheBinMetadata( const Config& conf );
+
+            bool isOK() const { return _valid; }
+
+            Config getConfig() const;
 
             bool                     _valid;
             optional<std::string>    _cacheBinId;
@@ -387,12 +339,18 @@ namespace osgEarth
             optional<ProfileOptions> _sourceProfile;
             optional<ProfileOptions> _cacheProfile;
             optional<TimeStamp>      _cacheCreateTime;
+            DataExtentList           _dataExtents;
         };
 
         /**
          * Access to information about the cache 
          */
-        bool getCacheBinMetadata( const Profile* profile, CacheBinMetadata& output );
+        CacheBinMetadata* getCacheBinMetadata(const Profile* profile);
+
+        /**
+         * Cache Settings for this layer - guaranteed to return an object
+         */
+        CacheSettings* getCacheSettings() const;
 
     protected:
 
@@ -401,15 +359,16 @@ namespace osgEarth
 
         void applyProfileOverrides();
 
-        CacheBin* getCacheBin( const Profile* profile, const std::string& binId );
+        CacheBin* getCacheBin(const Profile* profile);
+
+        /** Subclass can call this to indicate an error. */
+        void setStatus(const Status& value) { _status = value; }
 
     protected:
 
         osg::ref_ptr<const Profile>    _targetProfileHint;
-        mutable bool                   _tileSourceInitAttempted;
-        //bool                           _tileSourceInitFailed;
         unsigned                       _tileSize;  
-        osg::ref_ptr<osgDB::Options>   _dbOptions;
+        osg::ref_ptr<osgDB::Options>   _readOptions;
         osg::ref_ptr<MemCache>         _memCache;
 
         // profile from tile source or cache, before any overrides applied
@@ -418,8 +377,11 @@ namespace osgEarth
         // profile to use
         mutable osg::ref_ptr<const Profile> _profile;
 
-        void setCachePolicy( const CachePolicy& cp );
-        const CachePolicy& getCachePolicy() const;
+        // CTOR initialization; call from subclass.
+        void init();
+
+        // cache key for metadata
+        std::string getMetadataKey(const Profile*) const;
 
     private:
         std::string                    _name;
@@ -430,41 +392,32 @@ namespace osgEarth
         mutable Threading::Mutex       _initTileSourceMutex;
         osg::ref_ptr<TileSource>       _tileSource;
 
-        osg::ref_ptr<Cache>            _cache;
+        std::string                    _cacheId;
         
         // cache policy that may be automatically set by the layer and will 
         // override the runtime options policy if set.
         optional<CachePolicy>          _effectiveCachePolicy;
 
-        // maps profile signature to cache bin pointer.
-        struct CacheBinInfo
-        {
-            osg::ref_ptr<CacheBin>     _bin;
-            optional<CacheBinMetadata> _metadata;
-        };
-        typedef std::map< std::string, CacheBinInfo > CacheBinInfoMap; // indexed by profile signature
+        typedef std::map<std::string, osg::ref_ptr<CacheBinMetadata> > CacheBinMetadataMap;
+        CacheBinMetadataMap _cacheBinMetadata;
 
-        CacheBinInfoMap                _cacheBins;
-        Threading::ReadWriteMutex      _cacheBinsMutex;
+        mutable Threading::Mutex    _mutex;
+
+        mutable osg::ref_ptr<CacheSettings> _cacheSettings;
+
+        bool _openCalled;
 
-        void init();
-        //void applyCacheFormat( CacheBin* bin, const std::string& format );
         virtual void fireCallback( TerrainLayerCallbackMethodPtr method ) =0;
 
         // methods accesible by Map:
         friend class Map;
-        void setDBOptions( const osgDB::Options* dbOptions );
         void initializeCachePolicy( const osgDB::Options* );
         void storeProxySettings( osgDB::Options* );
 
-        /**
-         * Sets the cache to be used on this MapLayer
-         * TODO: is it legal to set this at any time?
-         */
-        void setCache( Cache* cache );
-
         // read the tile source's cache policy hint and apply as necessary
         void refreshTileSourceCachePolicyHint(TileSource*);
+
+        Status _status;
     };
 
     typedef std::vector<osg::ref_ptr<TerrainLayer> > TerrainLayerVector;
diff --git a/src/osgEarth/TerrainLayer.cpp b/src/osgEarth/TerrainLayer.cpp
index 8ac8c7a..507ee1e 100644
--- a/src/osgEarth/TerrainLayer.cpp
+++ b/src/osgEarth/TerrainLayer.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -32,7 +32,7 @@
 using namespace osgEarth;
 using namespace OpenThreads;
 
-#define LC "[TerrainLayer] \"" << getName() << "\": "
+#define LC "[TerrainLayer] Layer \"" << getName() << "\" "
 
 //------------------------------------------------------------------------
 
@@ -95,10 +95,11 @@ TerrainLayerOptions::getConfig( bool isolate ) const
     conf.updateIfSet( "vdatum", _vertDatum );
 
     conf.updateIfSet   ( "cacheid",      _cacheId );
-    conf.updateIfSet   ( "cache_format", _cacheFormat );
-    conf.updateObjIfSet( "cache_policy", _cachePolicy );
     conf.updateObjIfSet( "proxy",        _proxySettings );
 
+    if ( _cachePolicy.isSet() && !_cachePolicy->empty() )
+        conf.updateObjIfSet( "cache_policy", _cachePolicy );
+
     // Merge the TileSource options
     if ( !isolate && driver().isSet() )
         conf.merge( driver()->getConfig() );
@@ -125,7 +126,6 @@ TerrainLayerOptions::fromConfig( const Config& conf )
     conf.getIfSet( "vsrs", _vertDatum );    // back compat
 
     conf.getIfSet   ( "cacheid",      _cacheId );
-    conf.getIfSet   ( "cache_format", _cacheFormat );
     conf.getObjIfSet( "cache_policy", _cachePolicy );
     conf.getObjIfSet( "proxy",        _proxySettings );
 
@@ -148,12 +148,123 @@ TerrainLayerOptions::mergeConfig( const Config& conf )
 
 //------------------------------------------------------------------------
 
+TerrainLayer::CacheBinMetadata::CacheBinMetadata() :
+_valid(false)
+{
+    //nop
+}
+
+TerrainLayer::CacheBinMetadata::CacheBinMetadata(const TerrainLayer::CacheBinMetadata& rhs) :
+_valid          ( rhs._valid ),
+_cacheBinId     ( rhs._cacheBinId ),
+_sourceName     ( rhs._sourceName ),
+_sourceDriver   ( rhs._sourceDriver ),
+_sourceTileSize ( rhs._sourceTileSize ),
+_sourceProfile  ( rhs._sourceProfile ),
+_cacheProfile   ( rhs._cacheProfile ),   
+_cacheCreateTime( rhs._cacheCreateTime )
+{
+    //nop
+}
+
+TerrainLayer::CacheBinMetadata::CacheBinMetadata(const Config& conf)
+{
+    _valid = !conf.empty();
+
+    conf.getIfSet("cachebin_id", _cacheBinId);
+    conf.getIfSet("source_name", _sourceName);
+    conf.getIfSet("source_driver", _sourceDriver);
+    conf.getIfSet("source_tile_size", _sourceTileSize);
+    conf.getObjIfSet("source_profile", _sourceProfile);
+    conf.getObjIfSet("cache_profile", _cacheProfile);
+    conf.getIfSet("cache_create_time", _cacheCreateTime);
+
+    const Config* extentsRoot = conf.child_ptr("extents");
+    if ( extentsRoot )
+    {
+        const ConfigSet& extents = extentsRoot->children();
+
+        for (ConfigSet::const_iterator i = extents.begin(); i != extents.end(); ++i)
+        {
+            std::string srsString;
+            double xmin, ymin, xmax, ymax;
+            optional<unsigned> minLevel, maxLevel;
+        
+            srsString = i->value("srs");
+            xmin = i->value("xmin", 0.0f);
+            ymin = i->value("ymin", 0.0f);
+            xmax = i->value("xmax", 0.0f);
+            ymax = i->value("ymax", 0.0f);
+            i->getIfSet("minlevel", minLevel);
+            i->getIfSet("maxlevel", maxLevel);
+
+            const SpatialReference* srs = SpatialReference::get(srsString);
+            DataExtent e( GeoExtent(srs, xmin,  ymin, xmax, ymax) );
+            if (minLevel.isSet())
+                e.minLevel() = minLevel.get();
+            if (maxLevel.isSet())
+                e.maxLevel() = maxLevel.get();
+
+            _dataExtents.push_back(e);
+        }
+    }
+
+    // check for validity. This will reject older caches that don't have
+    // sufficient attribution.
+    if (_valid)
+    {
+        if (!conf.hasValue("source_tile_size") ||
+            !conf.hasChild("source_profile") ||
+            !conf.hasChild("cache_profile"))
+        {
+            _valid = false;
+        }
+    }
+}
+
+Config 
+TerrainLayer::CacheBinMetadata::getConfig() const
+{
+    Config conf("osgearth_terrainlayer_cachebin");
+    conf.addIfSet("cachebin_id", _cacheBinId);
+    conf.addIfSet("source_name", _sourceName);
+    conf.addIfSet("source_driver", _sourceDriver);
+    conf.addIfSet("source_tile_size", _sourceTileSize);
+    conf.addObjIfSet("source_profile", _sourceProfile);
+    conf.addObjIfSet("cache_profile", _cacheProfile);
+    conf.addIfSet("cache_create_time", _cacheCreateTime);
+
+    if (!_dataExtents.empty())
+    {
+        Config extents;
+        for (DataExtentList::const_iterator i = _dataExtents.begin(); i != _dataExtents.end(); ++i)
+        {
+            Config extent;
+            extent.set("srs", i->getSRS()->getHorizInitString());
+            extent.set("xmin", i->xMin());
+            extent.set("ymin", i->yMin());
+            extent.set("xmax", i->xMax());
+            extent.set("ymax", i->yMax());
+            extent.addIfSet("minlevel", i->minLevel());
+            extent.addIfSet("maxlevel", i->maxLevel());
+            extents.add("extent", extent);
+        }
+        conf.add("extents", extents);
+    }
+
+    return conf;
+}
+
+//------------------------------------------------------------------------
+
 TerrainLayer::TerrainLayer(const TerrainLayerOptions& initOptions,
                            TerrainLayerOptions*       runtimeOptions ) :
 _initOptions   ( initOptions ),
-_runtimeOptions( runtimeOptions )
+_runtimeOptions( runtimeOptions ),
+_openCalled( false ),
+_tileSize( 256 )
 {
-    init();
+    // nop
 }
 
 TerrainLayer::TerrainLayer(const TerrainLayerOptions& initOptions,
@@ -161,36 +272,23 @@ TerrainLayer::TerrainLayer(const TerrainLayerOptions& initOptions,
                            TileSource*                tileSource ) :
 _initOptions   ( initOptions ),
 _runtimeOptions( runtimeOptions ),
-_tileSource    ( tileSource )
+_tileSource    ( tileSource ),
+_openCalled( false ),
+_tileSize( 256 )
 {
-    init();
+    // nop
 }
 
 TerrainLayer::~TerrainLayer()
 {
-    if ( _cache.valid() )
-    {
-        Threading::ScopedWriteLock exclusive( _cacheBinsMutex );
-        for( CacheBinInfoMap::iterator i = _cacheBins.begin(); i != _cacheBins.end(); ++i )
-        {
-            CacheBinInfo& info = i->second;
-            if ( info._bin.valid() )
-            {
-                _cache->removeBin( info._bin.get() );
-            }
-        }
-    }
+    //nop
 }
 
 void
 TerrainLayer::init()
-{
-    _tileSourceInitAttempted = false;
-    _tileSize                = 256;
-    _dbOptions               = Registry::instance()->cloneOrCreateOptions();
-    
-    initializeCachePolicy( _dbOptions.get() );
-    storeProxySettings( _dbOptions.get() );
+{    
+    // intiailize out read-options, which store caching and IO information.
+    setReadOptions(0L);
 
     // Create an L2 mem cache that sits atop the main cache, if necessary.
     // For now: use the same L2 cache size at the driver.
@@ -204,95 +302,166 @@ TerrainLayer::init()
         OE_INFO << LC << "L2 cache size set from environment = " << l2CacheSize << "\n";
     }
 
+    // Env cache-only mode also disables the L2 cache.
+    char const* noCacheEnv = ::getenv( "OSGEARTH_MEMORY_PROFILE" );
+    if ( noCacheEnv )
+    {
+        l2CacheSize = 0;
+    }
+
     // Initialize the l2 cache if it's size is > 0
     if ( l2CacheSize > 0 )
     {
         _memCache = new MemCache( l2CacheSize );
     }
+
+    // create the unique cache ID for the cache bin.
+    std::string cacheId;
+
+    if (_runtimeOptions->cacheId().isSet() && !_runtimeOptions->cacheId()->empty())
+    {
+        // user expliticy set a cacheId in the terrain layer options.
+        // this appears to be a NOP; review for removal -gw
+        cacheId = *_runtimeOptions->cacheId();
+    }
+    else
+    {
+        // system will generate a cacheId.
+        // technically, this is not quite right, we need to remove everything that's
+        // an image layer property and just use the tilesource properties.
+        Config layerConf = _runtimeOptions->getConfig(true);
+        Config driverConf = _runtimeOptions->driver()->getConfig();
+        Config hashConf = driverConf - layerConf;
+
+        // remove cache-control properties before hashing.
+        hashConf.remove("cache_only");
+        hashConf.remove("cache_enabled");
+        hashConf.remove("cache_policy");
+        hashConf.remove("cacheid");
+        hashConf.remove("l2_cache_size");
+
+        // need this, b/c data is vdatum-transformed before caching.
+        if (layerConf.hasValue("vdatum"))
+            hashConf.add("vdatum", layerConf.value("vdatum"));
+
+        unsigned hash = osgEarth::hashString(hashConf.toJSON());
+        cacheId = Stringify() << std::hex << std::setw(8) << std::setfill('0') << hash;
+
+        _runtimeOptions->cacheId().init(cacheId); // set as default value
+    }
 }
 
-void
-TerrainLayer::setCache( Cache* cache )
+const Status&
+TerrainLayer::open()
 {
-    if (_cache.get() != cache && getCachePolicy() != CachePolicy::NO_CACHE )
+    if ( !_openCalled )
     {
-        _cache = cache;
+        CacheSettings* cacheSettings = getCacheSettings(); // guaranteed to return non-null
 
-        // Initialize a cache bin for this layer.
-        if ( _cache.valid() )
+        Threading::ScopedMutexLock lock(_mutex);
+        if (!_openCalled)
         {
-            // create the unique cache ID for the cache bin.
-            std::string cacheId;
-
-            if ( _runtimeOptions->cacheId().isSet() && !_runtimeOptions->cacheId()->empty() )
+            // If you created the layer with a pre-created tile source, it will already by set.
+            if (!_tileSource.valid())
             {
-                // user expliticy set a cacheId in the terrain layer options.
-                // this appears to be a NOP; review for removal -gw
-                cacheId = *_runtimeOptions->cacheId();
+                osg::ref_ptr<TileSource> ts;
+
+                // as long as we're not in cache-only mode, try to create the TileSource.
+                if (cacheSettings->cachePolicy()->isCacheOnly())
+                {
+                    OE_INFO << LC << "Opening in cache-only mode\n";
+                }
+                else
+                {
+                    // Initialize the tile source once and only once.
+                    ts = createTileSource();
+                }
+
+                if ( ts.valid() )
+                {
+                    if (cacheSettings->isCacheEnabled())
+                    {
+                        // read the cache policy hint from the tile source unless user expressly set 
+                        // a policy in the initialization options. In other words, the hint takes
+                        // ultimate priority (even over the Registry override) unless expressly
+                        // overridden in the layer options!
+                        refreshTileSourceCachePolicyHint( ts.get() );
+
+                        // Unless the user has already configured an expiration policy, use the "last modified"
+                        // timestamp of the TileSource to set a minimum valid cache entry timestamp.
+                        CachePolicy& cp = _runtimeOptions->cachePolicy().mutable_value();
+                        if ( !cp.minTime().isSet() && !cp.maxAge().isSet() && ts->getLastModifiedTime() > 0)
+                        {
+                            // The "effective" policy overrides the runtime policy, but it does not get serialized.
+                            _effectiveCachePolicy = cp;
+                            _effectiveCachePolicy->minTime() = ts->getLastModifiedTime();
+                            OE_INFO << LC << "driver says min valid timestamp = " << DateTime(*cp.minTime()).asRFC1123() << "\n";
+                        }
+                    }
+
+                    // All is well - set the tile source.
+                    if ( !_tileSource.valid() )
+                    {
+                        _tileSource = ts.release();
+                    }
+                }
             }
             else
             {
-                // system will generate a cacheId.
-                // technically, this is not quite right, we need to remove everything that's
-                // an image layer property and just use the tilesource properties.
-                Config layerConf  = _runtimeOptions->getConfig( true );
-                Config driverConf = _runtimeOptions->driver()->getConfig();
-                Config hashConf   = driverConf - layerConf;
-
-                // remove cache-control properties before hashing.
-                hashConf.remove( "cache_only" );
-                hashConf.remove( "cache_enabled" );
-                hashConf.remove( "cache_policy" );
-                hashConf.remove( "cacheid" );
-                hashConf.remove( "l2_cache_size" );
-                
-                // need this, b/c data is vdatum-transformed before caching.
-                if ( layerConf.hasValue("vdatum") )
-                    hashConf.add("vdatum", layerConf.value("vdatum"));
-
-                cacheId = Stringify() << std::hex << osgEarth::hashString(hashConf.toJSON());
-
-                _runtimeOptions->cacheId().init( cacheId ); // set as default value
+                // User supplied the tile source, so attempt to get its profile:
+                _profile = _tileSource->getProfile();
+                if (!_profile.valid())
+                {
+                    setStatus( Status::Error(getName(), "Cannot establish profile") );
+                }
             }
+
+            _openCalled = true;
+                        
+            OE_INFO << LC << cacheSettings->toString() << "\n";
         }
-    }
 
-    if ( !_cache.valid() )
-    {
-        _cache = 0L; 
-        setCachePolicy( CachePolicy::NO_CACHE );
     }
+
+    return _status;
+    //return _runtimeOptions->enabled() == true;
 }
 
-void
-TerrainLayer::setCachePolicy( const CachePolicy& cp )
+CacheSettings*
+TerrainLayer::getCacheSettings() const
 {
-    _runtimeOptions->cachePolicy() = cp;
-    _runtimeOptions->cachePolicy()->apply( _dbOptions.get() );
+    if (!_cacheSettings.valid())
+    {
+        Threading::ScopedMutexLock lock(_mutex);
+        if (!_cacheSettings.valid())
+        {
+            // clone the existing one if it exists:
+            CacheSettings* oldSettings = CacheSettings::get(_readOptions.get());
+            _cacheSettings = oldSettings ? new CacheSettings(*oldSettings) : new CacheSettings();
 
-    // if an effective policy was previously set, clear it out
-    _effectiveCachePolicy.unset();
-}
+            // install the effective policy (which comes from the tile source). We don't call
+            // integrateCachePolicy here because we want this to take precedend over the registry's
+            // global overrides.
+            _cacheSettings->cachePolicy()->mergeAndOverride(_effectiveCachePolicy);
 
-const CachePolicy&
-TerrainLayer::getCachePolicy() const
-{
-    // An effective policy, if set, overrides the runtime policy.
-    return
-        _effectiveCachePolicy.isSet() ? _effectiveCachePolicy.get() :
-        _runtimeOptions->cachePolicy().get();
-}
+            // install the layer policy
+            _cacheSettings->integrateCachePolicy(_runtimeOptions->cachePolicy());
 
-bool
-TerrainLayer::isCacheOnly() const
-{
-    return getCachePolicy().usage() == CachePolicy::USAGE_CACHE_ONLY;
-}
+            // if all it well, open and activate a caching bin for this layer.
+            if (_cacheSettings->isCacheEnabled())
+            {
+                CacheBin* bin = _cacheSettings->getCache()->addBin(_runtimeOptions->cacheId().get());
+                if (bin)
+                {
+                    _cacheSettings->setCacheBin(bin);
+                    OE_INFO << LC << "Cache bin is [" << bin->getID() << "]\n";
+                }
+            }
 
-bool
-TerrainLayer::isNoCache() const
-{
-    return getCachePolicy().usage() == CachePolicy::USAGE_NO_CACHE;
+            _cacheSettings->store(_readOptions.get());
+        }
+    }
+    return _cacheSettings.get();
 }
 
 void
@@ -300,104 +469,34 @@ TerrainLayer::setTargetProfileHint( const Profile* profile )
 {
     _targetProfileHint = profile;
 
-    // This will attempt to open and access a cache bin if there
-    // is one. This is important in cache-only mode since we cannot
-    // establish a profile from the tile source.
-    if ( getCachePolicy() != CachePolicy::NO_CACHE )
-    {
-        CacheBinMetadata meta;
-        getCacheBinMetadata( profile, meta );
-    }
-
-    // If the tilesource was already initialized, re-read the 
-    // cache policy hint since it may change due to the target
-    // profile change.
+    // Re-read the  cache policy hint since it may change due to the target profile change.
     refreshTileSourceCachePolicyHint( getTileSource() );
 }
 
 void
 TerrainLayer::refreshTileSourceCachePolicyHint(TileSource* ts)
 {
-    if ( ts && !_initOptions.cachePolicy().isSet() )
+    if ( ts && getCacheSettings() && !_initOptions.cachePolicy().isSet() )
     {
         CachePolicy hint = ts->getCachePolicyHint( _targetProfileHint.get() );
 
         if ( hint.usage().isSetTo(CachePolicy::USAGE_NO_CACHE) )
         {
-            setCachePolicy( hint );
+            getCacheSettings()->cachePolicy() = hint;
             OE_INFO << LC << "Caching disabled (by policy hint)" << std::endl;
         }
     }
 }
 
-TileSource* 
+TileSource*
 TerrainLayer::getTileSource() const
 {
-    if ( !_tileSourceInitAttempted )
-    {
-        // Lock and double check:
-        Threading::ScopedMutexLock lock( _initTileSourceMutex );
-        if ( !_tileSourceInitAttempted )
-        {
-            // Continue with thread-safe initialization.
-            TerrainLayer* this_nc = const_cast<TerrainLayer*>(this);
-
-            osg::ref_ptr<TileSource> ts;
-            if ( !isCacheOnly() )
-            {
-                // Initialize the tile source once and only once.
-                ts = this_nc->createTileSource();
-            }
-
-            if ( ts.valid() )
-            {
-                // read the cache policy hint from the tile source unless user expressly set 
-                // a policy in the initialization options. In other words, the hint takes
-                // ultimate priority (even over the Registry override) unless expressly
-                // overridden in the layer options!
-                this_nc->refreshTileSourceCachePolicyHint( ts.get() );
-
-                // Unless the user has already configured an expiration policy, use the "last modified"
-                // timestamp of the TileSource to set a minimum valid cache entry timestamp.
-                if ( ts )
-                {
-                    CachePolicy& cp = _runtimeOptions->cachePolicy().mutable_value();
-                    if ( !cp.minTime().isSet() && !cp.maxAge().isSet() && ts->getLastModifiedTime() > 0)
-                    {
-                        // The "effective" policy overrides the runtime policy, but it does not
-                        // get serialized.
-                        this_nc->_effectiveCachePolicy = cp;
-                        this_nc->_effectiveCachePolicy->minTime() = ts->getLastModifiedTime();
-                        OE_INFO << LC << "cache min valid time reported by driver = " << DateTime(*cp.minTime()).asRFC1123() << "\n";
-                    }
-                    OE_INFO << LC << "cache policy = " << getCachePolicy().usageString() << std::endl;
-                }
-
-                if ( !_tileSource.valid() )
-                    this_nc->_tileSource = ts.release();
-            }
-
-            // finally, set this whether we succeeded or failed
-            _tileSourceInitAttempted = true;
-        }
-    }
-
     return _tileSource.get();
 }
 
 const Profile*
 TerrainLayer::getProfile() const
 {
-    // NB: in cache-only mode, there IS NO layer profile.
-    if ( !_profile.valid() && !isCacheOnly() )
-    {
-        if ( !_tileSourceInitAttempted )
-        {
-            // Call getTileSource to make sure the TileSource is initialized
-            getTileSource();
-        }
-    }
-    
     return _profile.get();
 }
 
@@ -405,7 +504,7 @@ unsigned
 TerrainLayer::getTileSize() const
 {
     // force tile source initialization (which sets _tileSize)
-    getTileSource();
+    //getTileSource();
     return _tileSize; //ts ? ts->getPixelsPerTile() : _tileSize;
 }
 
@@ -416,171 +515,175 @@ TerrainLayer::isDynamic() const
     return ts ? ts->isDynamic() : false;
 }
 
+std::string
+TerrainLayer::getMetadataKey(const Profile* profile) const
+{
+    if (profile)
+        return Stringify() << profile->getHorizSignature() << "_metadata";
+    else
+        return "_metadata";
+}
+
 CacheBin*
 TerrainLayer::getCacheBin(const Profile* profile)
 {
-    // make sure we've initialized the tile source first.
-    getTileSource();
-
-    if ( getCachePolicy() == CachePolicy::NO_CACHE )
+    if ( !_openCalled )
     {
+        OE_WARN << LC << "Illegal- called getCacheBin() before calling open()\n";
         return 0L;
     }
 
-    // the cache bin ID is the cache ID concatenated with the FULL profile signature.
-    std::string binId = *_runtimeOptions->cacheId() + std::string("_") + profile->getFullSignature();
-
-    return getCacheBin( profile, binId );
-}
-
-CacheBin*
-TerrainLayer::getCacheBin(const Profile* profile, const std::string& binId)
-{
-    // make sure we've initialized the tile source first.
-    TileSource* tileSource = getTileSource();
+    CacheSettings* cacheSettings = getCacheSettings();
+    if (!cacheSettings)
+        return 0L;
 
-    // in no-cache mode, there are no cache bins.
-    if ( getCachePolicy() == CachePolicy::NO_CACHE )
-    {
+    if (cacheSettings->cachePolicy()->isCacheDisabled())
         return 0L;
-    }
 
-    // if cache is not setted, return NULL
-    if (_cache == NULL)
-    {
+    CacheBin* bin = cacheSettings->getCacheBin();
+    if (!bin)
         return 0L;
-    }
 
-    // see if the cache bin already exists and return it if so
-    {
-        Threading::ScopedReadLock shared(_cacheBinsMutex);
-        CacheBinInfoMap::iterator i = _cacheBins.find( binId );
-        if ( i != _cacheBins.end() )
-            return i->second._bin.get();
-    }
+    // does the metadata need initializing?
+    std::string metaKey = getMetadataKey(profile);
 
-    // create/open the cache bin.
-    {
-        Threading::ScopedWriteLock exclusive(_cacheBinsMutex);
+    Threading::ScopedMutexLock lock(_mutex);
 
-        // double-check:
-        CacheBinInfoMap::iterator i = _cacheBins.find( binId );
-        if ( i != _cacheBins.end() )
-            return i->second._bin.get();
+    CacheBinMetadataMap::iterator i = _cacheBinMetadata.find(metaKey);
+    if (i == _cacheBinMetadata.end())
+    {
+        std::string cacheId = _runtimeOptions->cacheId().get();
 
-        // add the new bin:
-        osg::ref_ptr<CacheBin> newBin = _cache->addBin( binId );
+        // read the metadata record from the cache bin:
+        ReadResult rr = bin->readString(metaKey, _readOptions.get());
+            
+        osg::ref_ptr<CacheBinMetadata> meta;
+        bool metadataOK = false;
 
-        // and configure:
-        if ( newBin.valid() )
+        if (rr.succeeded())
         {
-            // attempt to read the cache metadata:
-            CacheBinMetadata meta( newBin->readMetadata() );
+            // Try to parse the metadata record:
+            Config conf;
+            conf.fromJSON(rr.getString());
+            meta = new CacheBinMetadata(conf);
 
-            if ( meta.isValid() ) // cache exists and is valid.
+            if (meta->isOK())
             {
-                // verify that the cache if compatible with the tile source:
-                if ( tileSource && getProfile() )
+                metadataOK = true;
+
+                // verify that the cache if compatible with the open tile source:
+                if ( getTileSource() && getProfile() )
                 {
                     //todo: check the profile too
-                    if ( *meta._sourceDriver != tileSource->getOptions().getDriver() )
+                    if ( meta->_sourceDriver.get() != getTileSource()->getOptions().getDriver() )
                     {                     
                         OE_WARN << LC 
                             << "Layer \"" << getName() << "\" is requesting a \""
-                            << tileSource->getOptions().getDriver() << " cache, but a \""
-                            << *meta._sourceDriver << "\" cache exists at the specified location. "
+                            << getTileSource()->getOptions().getDriver() << "\" cache, but a \""
+                            << meta->_sourceDriver.get() << "\" cache exists at the specified location. "
                             << "The cache will ignored for this layer.\n";
 
-                        setCachePolicy( CachePolicy::NO_CACHE );
+                        cacheSettings->cachePolicy() = CachePolicy::NO_CACHE;
                         return 0L;
                     }
                 }   
 
-                else if ( isCacheOnly() && !_profile.valid() )
+                // if not, see if we're in cache-only mode and still need a profile:
+                else if (cacheSettings->cachePolicy()->isCacheOnly() && !_profile.valid())
                 {
                     // in cacheonly mode, create a profile from the first cache bin accessed
                     // (they SHOULD all be the same...)
-                    _profile = Profile::create( *meta._sourceProfile );
-                    _tileSize = *meta._sourceTileSize;
+                    _profile = Profile::create( meta->_sourceProfile.get() );
+                    _tileSize = meta->_sourceTileSize.get();
                 }
-            }
 
+                bin->setMetadata(meta.get());
+            }
             else
             {
-                // cache does not exist, so try to create it. A valid TileSource is necessary
-                // for this.
-                if ( tileSource && getProfile() )
-                {
-                    // no existing metadata; create some.
-                    meta._cacheBinId      = binId;
-                    meta._sourceName      = this->getName();
-                    meta._sourceDriver    = tileSource->getOptions().getDriver();
-                    meta._sourceTileSize  = getTileSize();
-                    meta._sourceProfile   = getProfile()->toProfileOptions();
-                    meta._cacheProfile    = profile->toProfileOptions();
-                    meta._cacheCreateTime = DateTime().asTimeStamp();
-
-                    // store it in the cache bin.
-                    newBin->writeMetadata( meta.getConfig() );
-                }
-                else if ( isCacheOnly() )
-                {
-                    OE_WARN << LC <<
-                        "Failed to open a cache for layer "
-                        "because cache_only policy is in effect and bin [" << binId << "] "
-                        "could not be located."
-                        << std::endl;
-                    return 0L;
-                }
-                else
-                {
-                    OE_WARN << LC <<
-                        "Failed to create cache bin [" << binId << "] "
-                        "because there is no valid tile source."
-                        << std::endl;
-                    return 0L;
-                }
+                OE_WARN << LC << "Metadata appears to be corrupt.\n";
+            }
+        }
+
+        if (!metadataOK)
+        {
+            // cache metadata does not exist, so try to create it. A valid TileSource is necessary for this.
+            if ( getTileSource() && getProfile() )
+            {
+                meta = new CacheBinMetadata();
+
+                // no existing metadata; create some.
+                meta->_cacheBinId      = cacheId;
+                meta->_sourceName      = this->getName();
+                meta->_sourceDriver    = getTileSource()->getOptions().getDriver();
+                meta->_sourceTileSize  = getTileSize();
+                meta->_sourceProfile   = getProfile()->toProfileOptions();
+                meta->_cacheProfile    = profile->toProfileOptions();
+                meta->_cacheCreateTime = DateTime().asTimeStamp();
+                meta->_dataExtents     = getTileSource()->getDataExtents();
+
+                // store it in the cache bin.
+                std::string data = meta->getConfig().toJSON(false);
+                bin->write(metaKey, new StringObject(data), _readOptions.get());                   
+
+                bin->setMetadata(meta.get());
             }
 
-            // store the bin.
-            CacheBinInfo& newInfo = _cacheBins[binId];
-            newInfo._metadata = meta;
-            newInfo._bin      = newBin.get();
+            else if ( cacheSettings->cachePolicy()->isCacheOnly() )
+            {
+                disable(Stringify() <<
+                    "Failed to open a cache for layer "
+                    "because cache_only policy is in effect and bin [" << cacheId << "] "
+                    "could not be located.");
 
-            OE_INFO << LC <<
-                "Opened cache bin [" << binId << "]" << std::endl;
+                return 0L;
+            }
 
-            // If we loaded a profile from the cache metadata, apply the overrides:
-            applyProfileOverrides();
+            else
+            {
+                OE_WARN << LC <<
+                    "Failed to create cache bin [" << cacheId << "] "
+                    "because there is no valid tile source."
+                    << std::endl;
+
+                cacheSettings->cachePolicy() = CachePolicy::NO_CACHE;
+                return 0L;
+            }
         }
-        else
+
+        // If we loaded a profile from the cache metadata, apply the overrides:
+        applyProfileOverrides();
+
+        if (meta.valid())
         {
-            // bin creation failed, so disable caching for this layer.
-            setCachePolicy( CachePolicy::NO_CACHE );
-            OE_WARN << LC << "Failed to create a cache bin; cache disabled." << std::endl;
+            _cacheBinMetadata[metaKey] = meta.get();
+            OE_DEBUG << LC << "Established metadata for cache bin [" << cacheId << "]" << std::endl;
         }
-
-        return newBin.get(); // not release()
     }
+
+    return bin;
 }
 
-bool
-TerrainLayer::getCacheBinMetadata( const Profile* profile, CacheBinMetadata& output )
+void
+TerrainLayer::disable(const std::string& msg)
 {
-    // the cache bin ID is the cache IF concatenated with the profile signature.
-    std::string binId = *_runtimeOptions->cacheId() + std::string("_") + profile->getFullSignature();
-    CacheBin* bin = getCacheBin( profile );
-    if ( bin )
+    if (!_runtimeOptions->enabled().isSetTo(false))
     {
-        Threading::ScopedReadLock shared(_cacheBinsMutex);
-        CacheBinInfoMap::iterator i = _cacheBins.find( binId );
-        if ( i != _cacheBins.end() )
-        {
-            output = i->second._metadata.value();
-            return true;
-        }
+        _runtimeOptions->enabled() = false;
+        _status = Status::Error(msg);
     }
-    return false;
+}
+
+TerrainLayer::CacheBinMetadata*
+TerrainLayer::getCacheBinMetadata(const Profile* profile)
+{
+    if (!profile)
+        return 0L;
+
+    Threading::ScopedMutexLock lock(_mutex);
+
+    CacheBinMetadataMap::iterator i = _cacheBinMetadata.find(getMetadataKey(profile));
+    return i != _cacheBinMetadata.end() ? i->second.get() : 0L;
 }
 
 TileSource*
@@ -600,26 +703,31 @@ TerrainLayer::createTileSource()
         // This will also set a manual "override" profile if the user provided one.
         if ( _runtimeOptions->driver().isSet() )
         {
-            OE_INFO << LC << "Creating TileSource, driver = \"" << _runtimeOptions->driver()->getDriver() << "\"\n";
+            OE_INFO << LC << "Creating \"" << _runtimeOptions->driver()->getDriver() << "\" driver\n";
             ts = TileSourceFactory::create( *_runtimeOptions->driver() );
             if ( !ts.valid() )
             {
-                OE_WARN << LC << "Failed to create TileSource for driver \"" << _runtimeOptions->driver()->getDriver() << "\"\n";
+                setStatus(Status::Error(Status::ServiceUnavailable, Stringify()<<"Failed to find driver \"" << _runtimeOptions->driver()->getDriver() << "\"\n"));
+                return 0L;
             }
         }
     }
 
+    Status tileSourceStatus;
+
     // Initialize the profile with the context information:
     if ( ts.valid() )
     {
-        // set up the URI options.
-        if ( !_dbOptions.valid() )
+        // add the osgDB options string if it's set.
+        const optional<std::string>& osgOptions = ts->getOptions().osgOptionString();
+        if ( osgOptions.isSet() && !osgOptions->empty() )
         {
-            _dbOptions = Registry::instance()->cloneOrCreateOptions();
-            if ( _cache.valid() )
-                _cache->apply( _dbOptions.get() );
-            _initOptions.cachePolicy()->apply( _dbOptions.get() );
-            URIContext( _runtimeOptions->referrer() ).apply( _dbOptions.get() );
+            std::string s = _readOptions->getOptionString();
+            if ( !s.empty() )
+                s = Stringify() << osgOptions.get() << " " << s;
+            else
+                s = osgOptions.get();
+            _readOptions->setOptionString( s );
         }
 
         // report on a manual override profile:
@@ -629,40 +737,20 @@ TerrainLayer::createTileSource()
         }
 
         // Open the tile source (if it hasn't already been started)
-        TileSource::Status status = ts->getStatus();
-        if ( status != TileSource::STATUS_OK )
+        tileSourceStatus = ts->getStatus();
+        if (!tileSourceStatus.isOK())
         {
-            status = ts->open(TileSource::MODE_READ, _dbOptions.get());
+            tileSourceStatus = ts->open(TileSource::MODE_READ, _readOptions.get());
         }
 
-        if ( status == TileSource::STATUS_OK )
+        if ( tileSourceStatus.isOK() )
         {
             _tileSize = ts->getPixelsPerTile();
-
-#if 0 //debugging 
-            // dump out data extents:
-            if ( ts->getDataExtents().size() > 0 )
-            {
-                OE_INFO << LC << "Data extents reported:" << std::endl;
-                for(DataExtentList::const_iterator i = ts->getDataExtents().begin();
-                    i != ts->getDataExtents().end(); ++i)
-                {
-                    const DataExtent& de = *i;
-                    OE_INFO << "    "
-                        << "X(" << i->xMin() << ", " << i->xMax() << ") "
-                        << "Y(" << i->yMin() << ", " << i->yMax() << ") "
-                        << "Z(" << i->minLevel().get() << ", " << i->maxLevel().get() << ")"
-                        << std::endl;
-                }                
-            }
-#endif
         }
         else
         {
-            OE_WARN << LC << "Could not initialize driver" << std::endl;
+            //OE_WARN << LC << "Driver initialization failed: " << tileSourceStatus.message() << std::endl;
             ts = NULL;
-            //_tileSourceInitFailed = true;
-            _runtimeOptions->enabled() = true;
         }
     }
 
@@ -687,11 +775,23 @@ TerrainLayer::createTileSource()
 
     // Otherwise, force cache-only mode (since there is no tilesource). The layer will try to 
     // establish a profile from the metadata in the cache instead.
-    else if (_cache.valid())
+    else if (getCacheSettings()->isCacheEnabled())
+    {
+        OE_NOTICE << LC << "Failed to create \"" << _runtimeOptions->driver()->getDriver() << "\" driver, but a cache may exist, so falling back on cache-only mode." << std::endl;
+        getCacheSettings()->cachePolicy() = CachePolicy::CACHE_ONLY;
+    }
+
+    // Finally: if we could not open a TileSource, and there's no cache available, 
+    // just disable the layer.
+    else
     {
-        OE_NOTICE << LC << "Could not initialize TileSource " << _name << ", but a cache exists. Setting layer to cache-only mode." << std::endl;
-        setCachePolicy( CachePolicy::CACHE_ONLY );
+        disable(tileSourceStatus.message());
+        setStatus(tileSourceStatus);
     }
+    //if (!ts.valid() && getCacheSettings()->isCacheDisabled())
+    //{
+    //    disable("Could not initialize TileSource and no cache is available");
+    //}
 
     return ts.release();
 }
@@ -768,9 +868,10 @@ bool
 TerrainLayer::isCached(const TileKey& key) const
 {
     // first consult the policy:
-    if ( getCachePolicy() == CachePolicy::NO_CACHE )
+    if (getCacheSettings()->isCacheDisabled())
         return false;
-    else if ( getCachePolicy() == CachePolicy::CACHE_ONLY )
+
+    else if (getCacheSettings()->cachePolicy()->isCacheOnly())
         return true;
 
     // next check for a bin:
@@ -789,38 +890,46 @@ TerrainLayer::setVisible( bool value )
 }
 
 void
-TerrainLayer::setDBOptions( const osgDB::Options* dbOptions )
+TerrainLayer::setReadOptions(const osgDB::Options* readOptions)
 {
-    _dbOptions = Registry::instance()->cloneOrCreateOptions( dbOptions );
-    initializeCachePolicy( dbOptions );
-    storeProxySettings( _dbOptions );
+    // clone the options, or create it not set
+    _readOptions = Registry::cloneOrCreateOptions(readOptions);
+
+    // store HTTP proxy settings in the options:
+    storeProxySettings( _readOptions );
+    
+    // store the referrer for relative-path resolution
+    URIContext( _runtimeOptions->referrer() ).store( _readOptions.get() );
+
+    Threading::ScopedMutexLock lock(_mutex);
+    _cacheSettings = 0L;
+    _cacheBinMetadata.clear();
 }
 
-void
-TerrainLayer::initializeCachePolicy(const osgDB::Options* options)
+bool
+TerrainLayer::getDataExtents(DataExtentList& output) const
 {
-    // Start with the cache policy passed in by the Map.
-    optional<CachePolicy> cp;
-    CachePolicy::fromOptions(options, cp);
+    output.clear();
 
-    // if this layer specifies cache policy info, that will override 
-    // whatever the map passed in:
-    if ( _initOptions.cachePolicy().isSet() )
-        cp->mergeAndOverride( _initOptions.cachePolicy() );
+    // if a tile source is available, get the extents directly from it:
+    if (getTileSource())
+        output = getTileSource()->getDataExtents();
 
-    // finally resolve with global overrides:
-    Registry::instance()->resolveCachePolicy( cp );
+    // otherwise, try the cache. Extents are the same regardless of
+    // profile so just use the first one available:
+    else if (!_cacheBinMetadata.empty())
+        output = _cacheBinMetadata.begin()->second->_dataExtents;
 
-    setCachePolicy( cp.get() );
+    return !output.empty();
 }
 
 void
-TerrainLayer::storeProxySettings(osgDB::Options* opt)
+TerrainLayer::storeProxySettings(osgDB::Options* readOptions)
 {
     //Store the proxy settings in the options structure.
     if (_initOptions.proxySettings().isSet())
     {        
-        _initOptions.proxySettings().get().apply( opt );
+        _initOptions.proxySettings()->apply( readOptions );
     }
 }
 
diff --git a/src/osgEarth/TerrainOptions b/src/osgEarth/TerrainOptions
index b132248..a3db9c2 100644
--- a/src/osgEarth/TerrainOptions
+++ b/src/osgEarth/TerrainOptions
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
@@ -55,15 +55,6 @@ namespace osgEarth
         const optional<float>& verticalOffset() const { return _verticalOffset; }
 
         /**
-         * @deprecated - Use MapOptions::elevationTileSize instead
-         * The sample ratio for height fields. I.e., the terrain engine
-         * will sample heightfield grids at this ratio
-         * Default = 1.0
-         */
-        optional<float>& heightFieldSampleRatio() { return _heightFieldSampleRatio; }
-        const optional<float>& heightFieldSampleRatio() const { return _heightFieldSampleRatio; }
-
-        /**
          * Size of each dimension of each terrain tile, in verts. Ideally this 
          * will be a power of 2 plus 1, i.e.: a number X with that X = (2^Y)+1
          * where Y is an integer >= 1.
@@ -176,10 +167,28 @@ namespace osgEarth
         const optional<unsigned>& minNormalMapLOD() const { return _minNormalMapLOD; }
 
         /**
+         * Whether the terrain engine will be using GPU tessellation shaders.
+         */
+        optional<bool>& gpuTessellation() { return _gpuTessellation; }
+        const optional<bool>& gpuTessellation() const { return _gpuTessellation; }
+
+        /**
          * debugging mode
          */
         optional<bool>& debug() { return _debug; }
         const optional<bool>& debug() const { return _debug; }
+
+        optional<int>& binNumber() { return _binNumber; }
+        const optional<int>& binNumber() const { return _binNumber; }
+
+        /**
+         * Terrain tile expiration
+         */
+        optional<int>& minExpiryFrames() { return _minExpiryFrames; }
+        const optional<int>& minExpiryFrames() const { return _minExpiryFrames; }
+
+        optional<double>& minExpiryTime() { return _minExpiryTime; }
+        const optional<double>& minExpiryTime() const { return _minExpiryTime; }
    
     public:
         virtual Config getConfig() const;
@@ -195,7 +204,6 @@ namespace osgEarth
                     
         optional<float> _verticalScale;
         optional<float> _verticalOffset;
-        optional<float> _heightFieldSampleRatio;
         optional<int>   _tileSize;
         optional<float> _minTileRangeFactor;        
         optional<bool> _combineLayers;
@@ -215,7 +223,11 @@ namespace osgEarth
         optional<unsigned> _primaryTraversalMask;
         optional<unsigned> _secondaryTraversalMask;
         optional<unsigned> _minNormalMapLOD;
+        optional<bool> _gpuTessellation;
         optional<bool> _debug;
+        optional<int> _binNumber;
+        optional<int> _minExpiryFrames;
+        optional<double> _minExpiryTime;
     };
 }
 
diff --git a/src/osgEarth/TerrainOptions.cpp b/src/osgEarth/TerrainOptions.cpp
index 9f5bbc7..71e949b 100644
--- a/src/osgEarth/TerrainOptions.cpp
+++ b/src/osgEarth/TerrainOptions.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -30,8 +30,7 @@ DriverConfigOptions( options ),
 _tileSize( 17 ),
 _verticalScale( 1.0f ),
 _verticalOffset( 0.0f ),
-_heightFieldSampleRatio( 1.0f ),
-_minTileRangeFactor( 6.0 ),
+_minTileRangeFactor( 7.0 ),
 _combineLayers( true ),
 _maxLOD( 23 ),
 _minLOD( 0 ),
@@ -46,7 +45,9 @@ _mercatorFastPath( true ),
 _minFilter( osg::Texture::LINEAR_MIPMAP_LINEAR ),
 _magFilter( osg::Texture::LINEAR),
 _minNormalMapLOD( 0u ),
-_debug( false )
+_gpuTessellation( false ),
+_debug( false ),
+_binNumber( 0 )
 {
     fromConfig( _conf );
 }
@@ -57,15 +58,11 @@ TerrainOptions::getConfig() const
     Config conf = DriverConfigOptions::getConfig();
     conf.key() = "terrain";
     
-    if ( _heightFieldSampleRatio.isSetTo( 0.0f ) )
-        conf.update( "sample_ratio", "auto" );
-    else
-        conf.updateIfSet( "sample_ratio", _heightFieldSampleRatio );
-
     conf.updateIfSet( "tile_size", _tileSize );
     conf.updateIfSet( "vertical_scale", _verticalScale );
     conf.updateIfSet( "vertical_offset", _verticalOffset );
-    conf.updateIfSet( "min_tile_range_factor", _minTileRangeFactor );    
+    conf.updateIfSet( "min_tile_range_factor", _minTileRangeFactor );
+    conf.updateIfSet( "range_factor", _minTileRangeFactor );  
     conf.updateIfSet( "max_lod", _maxLOD );
     conf.updateIfSet( "min_lod", _minLOD );
     conf.updateIfSet( "first_lod", _firstLOD );
@@ -77,7 +74,11 @@ TerrainOptions::getConfig() const
     conf.updateIfSet( "blending", _enableBlending );
     conf.updateIfSet( "mercator_fast_path", _mercatorFastPath );
     conf.updateIfSet( "min_normal_map_lod", _minNormalMapLOD );
+    conf.updateIfSet( "gpu_tessellation", _gpuTessellation );
     conf.updateIfSet( "debug", _debug );
+    conf.updateIfSet( "bin_number", _binNumber );
+    conf.updateIfSet( "min_expiry_time", _minExpiryTime);
+    conf.updateIfSet( "min_expiry_frames", _minExpiryFrames);
 
     //Save the filter settings
 	conf.updateIfSet("mag_filter","LINEAR",                _magFilter,osg::Texture::LINEAR);
@@ -99,15 +100,11 @@ TerrainOptions::getConfig() const
 void
 TerrainOptions::fromConfig( const Config& conf )
 {
-    if ( conf.value("sample_ratio") == "auto" )
-        _heightFieldSampleRatio = 0.0f;
-    else
-        conf.getIfSet( "sample_ratio", _heightFieldSampleRatio );
-
     conf.getIfSet( "tile_size", _tileSize );
     conf.getIfSet( "vertical_scale", _verticalScale );
     conf.getIfSet( "vertical_offset", _verticalOffset );
-    conf.getIfSet( "min_tile_range_factor", _minTileRangeFactor );    
+    conf.getIfSet( "min_tile_range_factor", _minTileRangeFactor );   
+    conf.getIfSet( "range_factor", _minTileRangeFactor );   
     conf.getIfSet( "max_lod", _maxLOD ); conf.getIfSet( "max_level", _maxLOD );
     conf.getIfSet( "min_lod", _minLOD ); conf.getIfSet( "min_level", _minLOD );
     conf.getIfSet( "first_lod", _firstLOD ); conf.getIfSet( "first_level", _firstLOD );
@@ -119,7 +116,11 @@ TerrainOptions::fromConfig( const Config& conf )
     conf.getIfSet( "blending", _enableBlending );
     conf.getIfSet( "mercator_fast_path", _mercatorFastPath );
     conf.getIfSet( "min_normal_map_lod", _minNormalMapLOD );
+    conf.getIfSet( "gpu_tessellation", _gpuTessellation );
     conf.getIfSet( "debug", _debug );
+    conf.getIfSet( "bin_number", _binNumber );
+    conf.getIfSet( "min_expiry_time", _minExpiryTime);
+    conf.getIfSet( "min_expiry_frames", _minExpiryFrames);
 
     //Load the filter settings
 	conf.getIfSet("mag_filter","LINEAR",                _magFilter,osg::Texture::LINEAR);
diff --git a/src/osgEarth/TerrainTileModel b/src/osgEarth/TerrainTileModel
new file mode 100644
index 0000000..27d5c26
--- /dev/null
+++ b/src/osgEarth/TerrainTileModel
@@ -0,0 +1,234 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+ * Copyright 2008-2014 Pelican Mapping
+ * http://osgearth.org
+ *
+ * osgEarth is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ */
+#ifndef OSGEARTH_TERRAIN_TILE_MODEL_H
+#define OSGEARTH_TERRAIN_TILE_MODEL_H 1
+
+#include <osgEarth/Common>
+#include <osgEarth/TileKey>
+#include <osgEarth/ImageLayer>
+#include <osgEarth/Revisioning>
+#include <osgEarth/MapInfo>
+#include <osgEarth/Locators>
+#include <osgEarth/HeightFieldUtils>
+#include <osgEarth/TileKeyDataStore>
+#include <osg/Texture>
+#include <osg/Matrix>
+
+namespace osgEarth
+{
+    class TerrainData : public osg::Referenced
+    {
+    public:
+        enum Type 
+        {
+            TYPE_IMAGE,
+            TYPE_ELEVATION,
+            TYPE_NORMAL,
+            TYPE_MATERIAL,
+            TYPE_VECTOR,
+            TYPE_UNKNOWN
+        };
+
+        void setType(Type type) { _type = type; }
+        const Type& getType() const { return _type; }
+
+    protected:
+        Type _type;
+
+        TerrainData() : _type(TYPE_UNKNOWN) { }
+        virtual ~TerrainData() { }
+    };
+
+
+    class OSGEARTH_EXPORT TerrainRaster : public TerrainData
+    {
+    public:
+        TerrainRaster() : TerrainData() { }
+
+        /** Raster image. */
+        void setImage(osg::Image* image) { _image = image; }
+        osg::Image* getImage() const { return _image.get(); }
+
+        void setLayer(Layer* layer) { _layer = layer; }
+        Layer* getLayer() const { return _layer.get(); }
+
+    protected:
+        virtual ~TerrainRaster() { }
+
+        osg::ref_ptr<osg::Image> _image;
+        osg::ref_ptr<Layer>      _layer;
+    };
+
+
+
+    //...start old stuff
+
+
+    /**
+     * Data model backing an individual layer of a terrain tile.
+     */
+    class OSGEARTH_EXPORT TerrainTileLayerModel : public osg::Referenced
+    {
+    public:
+        /** Name */
+        void setName(const std::string& name) { _name = name; }
+        const std::string& getName() const { return _name; }
+
+        /** Texture to use for rendering this layer */
+        void setTexture(osg::Texture* texture) { _texture = texture; }
+        osg::Texture* getTexture() const { return _texture.get(); }
+
+        /** Texture matrix to scale/bias the texture for the corresponding tile key */
+        void setMatrix(osg::RefMatrixf* matrix) { _matrix = matrix; }
+        osg::RefMatrixf* getMatrix() const { return _matrix.get(); }
+
+    public:
+        TerrainTileLayerModel();
+
+    protected:
+        virtual ~TerrainTileLayerModel() { }
+
+        std::string                   _name;
+        osg::ref_ptr<osg::Texture>    _texture;
+        osg::ref_ptr<osg::RefMatrixf> _matrix;
+    };
+    typedef std::vector< osg::ref_ptr<TerrainTileLayerModel> > TerrainTileLayerModelVector;
+
+    /**
+     * Layer based on an ImageLayer from the map.
+     */
+    class OSGEARTH_EXPORT TerrainTileImageLayerModel : public TerrainTileLayerModel
+    {
+    public:
+        TerrainTileImageLayerModel() : _order(0) { }
+
+    public:
+        /** Source layer */
+        void setImageLayer(ImageLayer* layer) { _layer = layer; }
+        const ImageLayer* getImageLayer() const { return _layer.get(); }
+
+        void setOrder(int order) { _order = order; }
+        int getOrder() const { return _order; }
+
+    protected:
+        virtual ~TerrainTileImageLayerModel() { }
+        osg::ref_ptr<ImageLayer> _layer;
+        int _order;
+    };
+    typedef std::vector< osg::ref_ptr<TerrainTileImageLayerModel> > TerrainTileImageLayerModelVector;
+
+    /**
+     * Layer based on aggregated elevation data.
+     */
+    class OSGEARTH_EXPORT TerrainTileElevationModel : public TerrainTileLayerModel
+    {
+    public:
+        /** Constructor */
+        TerrainTileElevationModel();
+
+        void setHeightField(const osg::HeightField* value) { _heightField = value; }
+        const osg::HeightField* getHeightField() const { return _heightField; }
+
+        /** Minimum height in the tile */
+        void setMinHeight(float value) { _minHeight = value; }
+        float getMinHeight() const { return _minHeight; }
+
+        /** Maximum height in the tile */
+        void setMaxHeight(float value) { _maxHeight = value; }
+        float getMaxHeight() const { return _maxHeight; }
+
+    protected:
+        virtual ~TerrainTileElevationModel() { }
+
+        osg::ref_ptr<const osg::HeightField> _heightField;
+        float _minHeight, _maxHeight;
+    };
+
+    /**
+     * Data model backing an individual terrain tile.
+     */
+    class OSGEARTH_EXPORT TerrainTileModel : public osg::Referenced
+    {
+    public:
+        /** Constructor */
+        TerrainTileModel(
+            const TileKey&  key,
+            const Revision& revision);
+
+        /** Map model revision from which this model was created */
+        const Revision& getRevision() const { return _revision; }
+
+        /** TileKey corresponding to this model */
+        const TileKey& getKey() const { return _key; }
+
+        /** Color layers (rendered one at a time in order) */
+        TerrainTileImageLayerModelVector& colorLayers() { return _colorLayers; }
+        const TerrainTileImageLayerModelVector& colorLayers() const { return _colorLayers; }
+
+        /** Elevation Layer model (one) */
+        osg::ref_ptr<TerrainTileElevationModel>& elevationModel() { return _elevationLayer; }
+        const osg::ref_ptr<TerrainTileElevationModel>& elevationModel() const { return _elevationLayer; }
+
+        /** Normal model (one) */
+        osg::ref_ptr<TerrainTileLayerModel>& normalModel() { return _normalLayer; }
+        const osg::ref_ptr<TerrainTileLayerModel>& normalModel() const { return _normalLayer; }
+
+        /** Shared raster layers (bound for all rendering) */
+        TerrainTileImageLayerModelVector& sharedLayers() { return _sharedLayers; }
+        const TerrainTileImageLayerModelVector& sharedLayers() const { return _sharedLayers; }
+
+        /** Try to find a layer */
+        const TerrainTileImageLayerModel* findColorLayerByUID(const UID& uid) const;
+        const TerrainTileImageLayerModel* findSharedLayerByUID(const UID& uid) const;
+        const TerrainTileImageLayerModel* findSharedLayerByName(const std::string& name) const;
+
+        /** Height field neighborhood surrounding the tile */
+        /** TODO: does this need to be in the model itself? probably not */
+        HeightFieldNeighborhood& heightFields() { return _heightFields; }
+        const HeightFieldNeighborhood& heightFields() const { return _heightFields; }
+
+        /** Whether a tile created from this model requires an update traversal. */
+        void setRequiresUpdateTraverse(bool value) { _requiresUpdateTraverse = value; }
+        bool requiresUpdateTraverse() const { return _requiresUpdateTraverse; }
+
+    public: // convenience getters.
+        osg::Texture* getNormalTexture() const;
+        osg::RefMatrixf* getNormalTextureMatrix() const;
+
+        osg::Texture* getElevationTexture() const;
+        osg::RefMatrixf* getElevationTextureMatrix() const;
+
+    protected:
+        TileKey                                 _key;
+        Revision                                _revision;
+        TerrainTileImageLayerModelVector        _colorLayers;
+        TerrainTileImageLayerModelVector        _sharedLayers;
+        osg::ref_ptr<TerrainTileElevationModel> _elevationLayer;
+        osg::ref_ptr<TerrainTileLayerModel>     _normalLayer;
+        HeightFieldNeighborhood                 _heightFields;
+        bool                                    _requiresUpdateTraverse;
+    };
+
+    /**
+     * Data store that references TerrainTileModel by TileKey.
+     */
+    typedef TileKeyDataStore<const TerrainTileModel> TerrainTileModelStore;
+}
+
+#endif // OSGEARTH_TERRAIN_TILE_MODEL_H
diff --git a/src/osgEarth/TerrainTileModel.cpp b/src/osgEarth/TerrainTileModel.cpp
new file mode 100644
index 0000000..dd9be80
--- /dev/null
+++ b/src/osgEarth/TerrainTileModel.cpp
@@ -0,0 +1,124 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+* Copyright 2008-2014 Pelican Mapping
+* http://osgearth.org
+*
+* osgEarth is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public License
+* along with this program.  If not, see <http://www.gnu.org/licenses/>
+*/
+#include <osgEarth/TerrainTileModel>
+#include <osgEarth/ImageLayer>
+#include <osgEarth/ImageUtils>
+#include <osgEarth/ImageToHeightFieldConverter>
+#include <osgEarth/Registry>
+#include <osg/Texture2D>
+
+using namespace osgEarth;
+
+#undef  LC
+#define LC "[TerrainTileModel] "
+
+//...................................................................
+
+TerrainTileLayerModel::TerrainTileLayerModel()
+{
+}
+
+//...................................................................
+
+TerrainTileElevationModel::TerrainTileElevationModel() :
+_minHeight( FLT_MAX ),
+_maxHeight(-FLT_MAX )
+{
+    //NOP
+}
+
+//...................................................................
+
+TerrainTileModel::TerrainTileModel(const TileKey&  key,
+                                   const Revision& revision) :
+_key                   ( key ),
+_revision              ( revision ),
+_requiresUpdateTraverse( false )
+{
+    //NOP
+}
+
+const TerrainTileImageLayerModel*
+TerrainTileModel::findSharedLayerByName(const std::string& name) const
+{
+    for(TerrainTileImageLayerModelVector::const_iterator i = _sharedLayers.begin();
+        i != _sharedLayers.end();
+        ++i)
+    {
+        if ( i->get()->getName() == name )
+        {
+            return i->get();
+        }
+    }
+    return 0L;
+}
+
+const TerrainTileImageLayerModel*
+TerrainTileModel::findSharedLayerByUID(const UID& uid) const
+{
+    for(TerrainTileImageLayerModelVector::const_iterator i = _sharedLayers.begin();
+        i != _sharedLayers.end();
+        ++i)
+    {
+        if ( i->get()->getImageLayer() && i->get()->getImageLayer()->getUID() == uid )
+        {
+            return i->get();
+        }
+    }
+    return 0L;
+}
+
+const TerrainTileImageLayerModel*
+TerrainTileModel::findColorLayerByUID(const UID& uid) const
+{
+    for(TerrainTileImageLayerModelVector::const_iterator i = _colorLayers.begin();
+        i != _colorLayers.end();
+        ++i)
+    {
+        if ( i->get()->getImageLayer() && i->get()->getImageLayer()->getUID() == uid )
+        {
+            return i->get();
+        }
+    }
+    return 0L;
+}
+
+osg::Texture* 
+TerrainTileModel::getNormalTexture() const
+{
+    return _normalLayer.valid() ? _normalLayer->getTexture() : 0L;
+}
+
+osg::RefMatrixf* 
+TerrainTileModel::getNormalTextureMatrix() const
+{
+    return _normalLayer.valid() ? _normalLayer->getMatrix() : 0L;
+}
+
+osg::Texture* 
+TerrainTileModel::getElevationTexture() const
+{
+    return _elevationLayer.valid() ? _elevationLayer->getTexture() : 0L;
+}
+
+osg::RefMatrixf* 
+TerrainTileModel::getElevationTextureMatrix() const
+{
+    return _elevationLayer.valid() ? _elevationLayer->getMatrix() : 0L;
+}
diff --git a/src/osgEarth/TerrainTileModelFactory b/src/osgEarth/TerrainTileModelFactory
new file mode 100644
index 0000000..a31d083
--- /dev/null
+++ b/src/osgEarth/TerrainTileModelFactory
@@ -0,0 +1,128 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+ * Copyright 2008-2014 Pelican Mapping
+ * http://osgearth.org
+ *
+ * osgEarth is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+#ifndef OSGEARTH_TERRAIN_TILE_MODEL_FACTORY_H
+#define OSGEARTH_TERRAIN_TILE_MODEL_FACTORY_H 1
+
+#include <osgEarth/TerrainTileModel>
+#include <osgEarth/TerrainOptions>
+#include <osgEarth/TerrainEngineRequirements>
+#include <osgEarth/MapFrame>
+#include <osgEarth/Progress>
+
+namespace osgEarth
+{
+    /**
+     * Builds a TerrainTileModel from a map frame.
+     */
+    class OSGEARTH_EXPORT TerrainTileModelFactory : public osg::Referenced
+    {
+    public:
+        /** Constructor */
+        TerrainTileModelFactory(
+            const TerrainOptions& options);
+
+        /**
+         * Creates a tile model and populates it with data from the map.
+         *
+         * @param frame       Map frame from which to read source data
+         * @param key         Tile key for which to create the model
+         * @param modelStore  Access to other tile models; if set, the factory
+         *                    will be able to access parent and neighbor data
+         *                    where appropriate
+         * @param progress    Progress tracking callback
+         */
+        virtual TerrainTileModel* createTileModel(
+            const MapFrame&                  frame,
+            const TileKey&                   key,
+            const TerrainEngineRequirements* requirements,
+            ProgressCallback*                progress);
+
+    protected:
+
+        virtual void addImageLayers(
+            TerrainTileModel*            model,
+            const MapFrame&              frame,
+            const TileKey&               key,
+            ProgressCallback*            progress);
+
+        virtual void addElevation(
+            TerrainTileModel*            model,
+            const MapFrame&              frame,
+            const TileKey&               key,
+            ProgressCallback*            progress);
+
+        virtual void addNormalMap(
+            TerrainTileModel*            model,
+            const MapFrame&              frame,
+            const TileKey&               key,
+            ProgressCallback*            progress);
+
+    protected:
+
+        /** Find a heightfield in the cache, or fetch it from the source. */
+        bool getOrCreateHeightField(
+            const MapFrame&                 frame,
+            const TileKey&                  key,
+            ElevationSamplePolicy           samplePolicy,
+            ElevationInterpolation          interpolation,
+            osg::ref_ptr<osg::HeightField>& out_hf,
+            ProgressCallback*               progress);
+
+        osg::Texture* createImageTexture(
+            osg::Image*       image,
+            const ImageLayer* layer) const;
+
+        osg::Texture* createCoverageTexture(
+            osg::Image*       image,
+            const ImageLayer* layer) const;
+
+        osg::Texture* createElevationTexture(
+            osg::Image* image) const;
+
+        osg::Texture* createNormalTexture(
+            osg::Image* image) const;
+
+        const TerrainOptions& _options;
+        
+
+        /** Key into the height field cache */
+        struct HFCacheKey 
+        {
+            TileKey               _key;
+            Revision              _revision;
+            ElevationSamplePolicy _samplePolicy;
+
+            bool operator < (const HFCacheKey& rhs) const {
+                if ( _key < rhs._key ) return true;
+                if ( rhs._key < _key ) return false;
+                if ( _revision < rhs._revision ) return true;
+                if ( _revision > rhs._revision ) return false;
+                return _samplePolicy < rhs._samplePolicy;
+            }
+        };
+
+        typedef osg::ref_ptr<osg::HeightField> HFCacheValue;
+        typedef LRUCache<HFCacheKey, HFCacheValue> HFCache;
+        HFCache _heightFieldCache;
+        bool    _heightFieldCacheEnabled;
+    };
+}
+
+#endif // OSGEARTH_TERRAIN_TILE_MODEL_FACTORY_H
diff --git a/src/osgEarth/TerrainTileModelFactory.cpp b/src/osgEarth/TerrainTileModelFactory.cpp
new file mode 100644
index 0000000..122558c
--- /dev/null
+++ b/src/osgEarth/TerrainTileModelFactory.cpp
@@ -0,0 +1,399 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+* Copyright 2008-2014 Pelican Mapping
+* http://osgearth.org
+*
+* osgEarth is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public License
+* along with this program.  If not, see <http://www.gnu.org/licenses/>
+*/
+#include <osgEarth/TerrainTileModelFactory>
+#include <osgEarth/Registry>
+#include <osgEarth/ImageUtils>
+#include <osgEarth/ImageToHeightFieldConverter>
+
+#include <osg/Texture2D>
+
+#define LC "[TerrainTileModelFactory] "
+
+using namespace osgEarth;
+
+//.........................................................................
+
+TerrainTileModelFactory::TerrainTileModelFactory(const TerrainOptions& options) :
+_options         ( options ),
+_heightFieldCache( true, 128 )
+{
+    _heightFieldCacheEnabled = (::getenv("OSGEARTH_MEMORY_PROFILE") == 0L);
+}
+
+TerrainTileModel*
+TerrainTileModelFactory::createTileModel(const MapFrame&                  frame,
+                                         const TileKey&                   key,
+                                         const TerrainEngineRequirements* requirements,
+                                         ProgressCallback*                progress)
+{
+    // Make a new model:
+    osg::ref_ptr<TerrainTileModel> model = new TerrainTileModel(
+        key,
+        frame.getRevision() );
+
+    // assemble all the components:
+    addImageLayers( model.get(), frame, key, progress );
+
+    if ( requirements == 0L || requirements->elevationTexturesRequired() )
+    {
+        addElevation( model.get(), frame, key, progress );
+    }
+
+    if ( requirements == 0L || requirements->normalTexturesRequired() )
+    {
+        addNormalMap( model.get(), frame, key, progress );
+    }
+
+    // done.
+    return model.release();
+}
+
+void
+TerrainTileModelFactory::addImageLayers(TerrainTileModel*            model,
+                                        const MapFrame&              frame,
+                                        const TileKey&               key,
+                                        ProgressCallback*            progress)
+{
+    OE_START_TIMER(fetch_image_layers);
+
+    int order = 0;
+
+    for(ImageLayerVector::const_iterator i = frame.imageLayers().begin();
+        i != frame.imageLayers().end();
+        ++i, ++order )
+    {
+        ImageLayer* layer = i->get();
+
+        if ( layer->getEnabled() && layer->isKeyInRange(key) )
+        {
+            // This will only go true if we are requesting a ROOT TILE but we have to
+            // fall back on lower resolution data to create it.
+            bool isFallback = false;
+
+            GeoImage geoImage;
+
+            const Profile* layerProfile = layer->getProfile();
+            
+            // If this is a ROOT tile, we will try to fall back on lower-resolution
+            // data if we can't find something at the optimal LOD.
+            bool isRootKey =
+                (key.getLOD() == 0) || // should never be
+                (key.getLOD()-1 == _options.firstLOD().get() );
+
+            TileSource* tileSource = layer->getTileSource();
+
+            // Only try to get data from the source if it actually intersects the key extent
+            bool hasDataInExtent = true;
+            if ( tileSource && layerProfile )
+            {
+                GeoExtent ext = key.getExtent();
+                if (!layerProfile->getSRS()->isEquivalentTo( ext.getSRS() ))
+                {
+                    ext = layerProfile->clampAndTransformExtent( ext );
+                }
+                hasDataInExtent = tileSource->hasDataInExtent( ext );
+            }
+            
+            // fetch the image from the layer if it's available:
+            if ( hasDataInExtent && layer->isKeyInRange(key) )
+            {
+                geoImage = layer->createImage( key, progress );
+            }
+            
+            if ( geoImage.valid() )
+            {
+                TerrainTileImageLayerModel* layerModel = new TerrainTileImageLayerModel();
+                layerModel->setImageLayer( layer );
+
+                // preserve layer ordering. Without this, layer draw order can get out of whack
+                // if you have a layer that doesn't appear in the model until a higher LOD. Instead
+                // of just getting appended to the draw set, the Order will make sure it gets 
+                // inserted in the correct position according to the map model.
+                layerModel->setOrder( order );
+
+                // made an image. Store as a texture with an identity matrix.
+                osg::Texture* texture;
+                if ( layer->isCoverage() )
+                    texture = createCoverageTexture(geoImage.getImage(), layer);
+                else
+                    texture = createImageTexture(geoImage.getImage(), layer);
+
+                layerModel->setTexture( texture );
+
+
+                if ( layer->isShared() )
+                    model->sharedLayers().push_back( layerModel );
+
+                if ( layer->getVisible() )
+                    model->colorLayers().push_back( layerModel );
+
+                if ( layer->isDynamic() )
+                    model->setRequiresUpdateTraverse( true );
+            }
+        }
+    }
+
+    if (progress)
+        progress->stats()["fetch_imagery_time"] += OE_STOP_TIMER(fetch_image_layers);
+}
+
+
+void
+TerrainTileModelFactory::addElevation(TerrainTileModel*            model,
+                                      const MapFrame&              frame,
+                                      const TileKey&               key,
+                                      ProgressCallback*            progress)
+{    
+    // make an elevation layer.
+    OE_START_TIMER(fetch_elevation);
+
+    const MapInfo& mapInfo = frame.getMapInfo();
+
+    const osgEarth::ElevationInterpolation& interp =
+        frame.getMapOptions().elevationInterpolation().get();
+
+    // Request a heightfield from the map.
+    osg::ref_ptr<osg::HeightField> mainHF;
+
+    if (getOrCreateHeightField(frame, key, SAMPLE_FIRST_VALID, interp, mainHF, progress) && mainHF.valid())
+    {
+        osg::ref_ptr<TerrainTileElevationModel> layerModel = new TerrainTileElevationModel();
+        layerModel->setHeightField( mainHF.get() );
+
+        // pre-calculate the min/max heights:
+        for( unsigned col = 0; col < mainHF->getNumColumns(); ++col )
+        {
+            for( unsigned row = 0; row < mainHF->getNumRows(); ++row )
+            {
+                float h = mainHF->getHeight(col, row);
+                if ( h > layerModel->getMaxHeight() )
+                    layerModel->setMaxHeight( h );
+                if ( h < layerModel->getMinHeight() )
+                    layerModel->setMinHeight( h );
+            }
+        }        
+
+        // needed for normal map generation
+        model->heightFields().setNeighbor(0, 0, mainHF.get());
+
+        // convert the heightfield to a 1-channel 32-bit fp image:
+        ImageToHeightFieldConverter conv;
+        osg::Image* image = conv.convert( mainHF.get(), 32 ); // 32 = GL_FLOAT
+
+        if ( image )
+        {
+            // Made an image, so store this as a texture with no matrix.
+            osg::Texture* texture = createElevationTexture( image );
+            layerModel->setTexture( texture );
+            model->elevationModel() = layerModel.get();
+        }
+    }
+
+    if (progress)
+        progress->stats()["fetch_elevation_time"] += OE_STOP_TIMER(fetch_elevation);
+}
+
+void
+TerrainTileModelFactory::addNormalMap(TerrainTileModel*            model,
+                                      const MapFrame&              frame,
+                                      const TileKey&               key,
+                                      ProgressCallback*            progress)
+{
+    OE_START_TIMER(fetch_normalmap);
+
+    const osgEarth::ElevationInterpolation& interp =
+        frame.getMapOptions().elevationInterpolation().get();
+
+    // Can only generate the normal map if the center heightfield was built:
+    osg::Image* image = HeightFieldUtils::convertToNormalMap(
+        model->heightFields(),
+        key.getProfile()->getSRS() );
+
+    if ( image )
+    {
+        TerrainTileImageLayerModel* layerModel = new TerrainTileImageLayerModel();
+        layerModel->setName( "oe_normal_map" );
+
+        // Made an image, so store this as a texture with no matrix.
+        osg::Texture* texture = createNormalTexture( image );
+        layerModel->setTexture( texture );
+        model->normalModel() = layerModel;
+    }
+
+    if (progress)
+        progress->stats()["fetch_normalmap_time"] += OE_STOP_TIMER(fetch_normalmap);
+}
+
+bool
+TerrainTileModelFactory::getOrCreateHeightField(const MapFrame&                 frame,
+                                                const TileKey&                  key,
+                                                ElevationSamplePolicy           samplePolicy,
+                                                ElevationInterpolation          interpolation,
+                                                osg::ref_ptr<osg::HeightField>& out_hf,
+                                                ProgressCallback*               progress)
+{
+    // check the quick cache.
+    HFCacheKey cachekey;
+    cachekey._key          = key;
+    cachekey._revision     = frame.getRevision();
+    cachekey._samplePolicy = samplePolicy;
+
+    if (progress)
+        progress->stats()["hfcache_try_count"] += 1;
+
+    bool hit = false;
+    HFCache::Record rec;
+    if ( _heightFieldCacheEnabled && _heightFieldCache.get(cachekey, rec) )
+    {
+        out_hf = rec.value().get();
+
+        if (progress)
+        {
+            progress->stats()["hfcache_hit_count"] += 1;
+            progress->stats()["hfcache_hit_rate"] = progress->stats()["hfcache_hit_count"]/progress->stats()["hfcache_try_count"];
+        }
+
+        return true;
+    }
+
+    if ( !out_hf.valid() )
+    {
+        // This sets the elevation tile size; query size for all tiles.
+        out_hf = HeightFieldUtils::createReferenceHeightField(
+            key.getExtent(), 257, 257, true );
+    }
+
+    bool populated = frame.populateHeightField(
+        out_hf,
+        key,
+        true, // convertToHAE
+        progress );
+
+#ifdef TREAT_ALL_ZEROS_AS_MISSING_TILE
+    // check for a real tile with all zeros and treat it the same as non-existant data.
+    if ( populated )
+    {
+        bool isEmpty = true;
+        for(osg::FloatArray::const_iterator f = out_hf->getFloatArray()->begin(); f != out_hf->getFloatArray()->end(); ++f)
+        {
+            if ( (*f) != 0.0f )
+            {
+                isEmpty = false;
+                break;
+            }
+        }
+        if ( isEmpty )
+        {
+            populated = false;
+        }
+    }
+#endif
+
+    if ( populated )
+    {
+        // Treat Plate Carre specially by scaling the height values. (There is no need
+        // to do this with an empty heightfield)
+        const MapInfo& mapInfo = frame.getMapInfo();
+        if ( mapInfo.isPlateCarre() )
+        {
+            HeightFieldUtils::scaleHeightFieldToDegrees( out_hf.get() );
+        }
+
+        // cache it.
+        if (_heightFieldCacheEnabled )
+            _heightFieldCache.insert( cachekey, out_hf.get() );
+    }
+
+    return populated;
+}
+
+osg::Texture*
+TerrainTileModelFactory::createImageTexture(osg::Image*       image,
+                                            const ImageLayer* layer) const
+{
+    osg::Texture2D* tex = new osg::Texture2D( image );
+
+    tex->setWrap( osg::Texture::WRAP_S, osg::Texture::CLAMP_TO_EDGE );
+    tex->setWrap( osg::Texture::WRAP_T, osg::Texture::CLAMP_TO_EDGE );
+    tex->setResizeNonPowerOfTwoHint(false);
+
+    osg::Texture::FilterMode magFilter = 
+        layer ? layer->getImageLayerOptions().magFilter().get() : osg::Texture::LINEAR;
+    osg::Texture::FilterMode minFilter =
+        layer ? layer->getImageLayerOptions().minFilter().get() : osg::Texture::LINEAR;
+
+    tex->setFilter( osg::Texture::MAG_FILTER, magFilter );
+    tex->setFilter( osg::Texture::MIN_FILTER, minFilter );
+    tex->setMaxAnisotropy( 4.0f );
+
+    // Disable mip mapping for npot tiles
+    if (!ImageUtils::isPowerOfTwo( image ) || (!image->isMipmap() && ImageUtils::isCompressed(image)))
+    {
+        tex->setFilter( osg::Texture::MIN_FILTER, osg::Texture::LINEAR );
+    }
+
+    return tex;
+}
+
+osg::Texture*
+TerrainTileModelFactory::createCoverageTexture(osg::Image*       image,
+                                               const ImageLayer* layer) const
+{
+    osg::Texture2D* tex = new osg::Texture2D( image );
+
+    tex->setWrap( osg::Texture::WRAP_S, osg::Texture::CLAMP_TO_EDGE );
+    tex->setWrap( osg::Texture::WRAP_T, osg::Texture::CLAMP_TO_EDGE );
+    tex->setResizeNonPowerOfTwoHint(false);
+
+    tex->setFilter( osg::Texture::MAG_FILTER, osg::Texture::NEAREST );
+    tex->setFilter( osg::Texture::MIN_FILTER, osg::Texture::NEAREST );
+
+    tex->setMaxAnisotropy( 1.0f );
+
+    return tex;
+}
+
+osg::Texture*
+TerrainTileModelFactory::createElevationTexture(osg::Image* image) const
+{
+    osg::Texture2D* tex = new osg::Texture2D( image );
+    tex->setInternalFormat(GL_LUMINANCE32F_ARB);
+    tex->setSourceFormat(GL_LUMINANCE);
+    tex->setFilter( osg::Texture::MAG_FILTER, osg::Texture::LINEAR );
+    tex->setFilter( osg::Texture::MIN_FILTER, osg::Texture::NEAREST );
+    tex->setWrap  ( osg::Texture::WRAP_S,     osg::Texture::CLAMP_TO_EDGE );
+    tex->setWrap  ( osg::Texture::WRAP_T,     osg::Texture::CLAMP_TO_EDGE );
+    tex->setResizeNonPowerOfTwoHint( false );
+    tex->setMaxAnisotropy( 1.0f );
+    return tex;
+}
+
+osg::Texture*
+TerrainTileModelFactory::createNormalTexture(osg::Image* image) const
+{
+    osg::Texture2D* tex = new osg::Texture2D( image );
+    tex->setInternalFormatMode(osg::Texture::USE_IMAGE_DATA_FORMAT);
+    tex->setFilter( osg::Texture::MAG_FILTER, osg::Texture::LINEAR );
+    tex->setFilter( osg::Texture::MIN_FILTER, osg::Texture::LINEAR_MIPMAP_LINEAR );
+    tex->setWrap  ( osg::Texture::WRAP_S,     osg::Texture::CLAMP_TO_EDGE );
+    tex->setWrap  ( osg::Texture::WRAP_T,     osg::Texture::CLAMP_TO_EDGE );
+    tex->setResizeNonPowerOfTwoHint( false );
+    tex->setMaxAnisotropy( 1.0f );
+    return tex;
+}
diff --git a/src/osgEarth/TerrainTileNode b/src/osgEarth/TerrainTileNode
index a6c0d8b..77ea5d7 100644
--- a/src/osgEarth/TerrainTileNode
+++ b/src/osgEarth/TerrainTileNode
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -22,6 +22,7 @@
 
 #include <osgEarth/Common>
 #include <osgEarth/TileKey>
+#include <osgEarth/TerrainTileModel>
 #include <osg/MatrixTransform>
 #include <osg/Texture>
 
@@ -32,56 +33,17 @@ namespace osgEarth
      * This is largely for internal use and subject to change, so
      * be careful relying on the structure of this object.
      */
-    class /*header-only*/ TerrainTileNode // : public osg::MatrixTransform
+    class /*header-only*/ TerrainTileNode
     {
     public:
-        virtual const TileKey& getKey() const =0;
+        const TerrainTileModel* getModel() const { return _model.get(); }
 
-        virtual osg::Texture* getElevationTexture() const =0;
-
-        virtual osg::RefMatrixf* getElevationTextureMatrix() const =0;
-
-        virtual osg::Texture* getNormalTexture() const =0;
-
-        virtual osg::RefMatrixf* getNormalTextureMatrix() const =0;
-
-        virtual osg::Group* getPayloadGroup() const =0;
-
-        virtual osg::Group* getOrCreatePayloadGroup() =0;
+        const TileKey& getKey() const { return _model->getKey(); }
 
     protected:
         virtual ~TerrainTileNode() { }
-    };
-
-    /**
-     * Interface for notification of the creation of TerrainTileNodes by
-     * the terrain engine.
-     */
-    class /*header-only*/ TerrainTileNodeBroker
-    {
-    public:
-        /**
-         * Terrain engine calls this when it finishes creating a single tile node
-         * for a given tile key. (Typically that will happen in a pager thread.)
-         */
-        virtual void notifyOfTerrainTileNodeCreation(const TileKey& key, osg::Node* node) =0;
-
-    public:
-        virtual ~TerrainTileNodeBroker() { }
-    };
-
-    /**
-     * Callback you can install on a TerrainEngineNode to get a first look at
-     * a TerrainTileNode when it's created.
-     */
-    class /*header-only*/ TerrainTileNodeCallback : public osg::Referenced
-    {
-    public:
-        // Careful: runs in a terrain engine background thread.
-        virtual void operator()(const TileKey& key, osg::Node* tileNode) =0;
 
-    protected:
-        virtual ~TerrainTileNodeCallback() { }
+        osg::ref_ptr<TerrainTileModel> _model;
     };
 };
 
diff --git a/src/osgEarth/Tessellator b/src/osgEarth/Tessellator
index ae44390..e7159d7 100644
--- a/src/osgEarth/Tessellator
+++ b/src/osgEarth/Tessellator
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarth/Tessellator.cpp b/src/osgEarth/Tessellator.cpp
index b22d2ab..ab1b470 100644
--- a/src/osgEarth/Tessellator.cpp
+++ b/src/osgEarth/Tessellator.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarth/TextureBufferSerializer.cpp b/src/osgEarth/TextureBufferSerializer.cpp
new file mode 100644
index 0000000..d94ff68
--- /dev/null
+++ b/src/osgEarth/TextureBufferSerializer.cpp
@@ -0,0 +1,37 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+* Copyright 2008-2012 Pelican Mapping
+* http://osgearth.org
+*
+* osgEarth is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* 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.
+*
+* You should have received a copy of the GNU Lesser General Public License
+* along with this program.  If not, see <http://www.gnu.org/licenses/>
+*/
+#include <osg/TextureBuffer>
+#include <osgDB/ObjectWrapper>
+#include <osgDB/InputStream>
+#include <osgDB/OutputStream>
+
+namespace
+{
+    REGISTER_OBJECT_WRAPPER( TextureBuffer,
+                             new osg::TextureBuffer,
+                             osg::TextureBuffer,
+                             "osg::Object osg::StateAttribute osg::Texture osg::TextureBuffer" )
+    {
+        ADD_IMAGE_SERIALIZER( Image, osg::Image, NULL );  // _image
+        ADD_INT_SERIALIZER( TextureWidth, 0 );  // _textureWidth
+    }
+}
diff --git a/src/osgEarth/TextureCompositor b/src/osgEarth/TextureCompositor
index 8cfbec8..3275890 100644
--- a/src/osgEarth/TextureCompositor
+++ b/src/osgEarth/TextureCompositor
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarth/TextureCompositor.cpp b/src/osgEarth/TextureCompositor.cpp
index 90f3549..6fe9318 100755
--- a/src/osgEarth/TextureCompositor.cpp
+++ b/src/osgEarth/TextureCompositor.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarth/ThreadingUtils b/src/osgEarth/ThreadingUtils
index 34230d4..583fc66 100644
--- a/src/osgEarth/ThreadingUtils
+++ b/src/osgEarth/ThreadingUtils
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarth/ThreadingUtils.cpp b/src/osgEarth/ThreadingUtils.cpp
index 8c798c3..a38124e 100644
--- a/src/osgEarth/ThreadingUtils.cpp
+++ b/src/osgEarth/ThreadingUtils.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarth/TileHandler b/src/osgEarth/TileHandler
index 96293b9..5565219 100644
--- a/src/osgEarth/TileHandler
+++ b/src/osgEarth/TileHandler
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarth/TileHandler.cpp b/src/osgEarth/TileHandler.cpp
index edc52fa..ce1c3f0 100644
--- a/src/osgEarth/TileHandler.cpp
+++ b/src/osgEarth/TileHandler.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarth/TileKey b/src/osgEarth/TileKey
index e09500e..0fd04b0 100644
--- a/src/osgEarth/TileKey
+++ b/src/osgEarth/TileKey
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -38,7 +38,7 @@ namespace osgEarth
         /**
          * Constructs an invalid TileKey.
          */
-        TileKey() { }
+        TileKey() : _lod(0), _x(0), _y(0) { }
 
         /**
          * Creates a new TileKey with the given tile xy at the specified level of detail
diff --git a/src/osgEarth/TileKey.cpp b/src/osgEarth/TileKey.cpp
index be2a5b8..d019289 100644
--- a/src/osgEarth/TileKey.cpp
+++ b/src/osgEarth/TileKey.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarth/TileKeyDataStore b/src/osgEarth/TileKeyDataStore
new file mode 100644
index 0000000..dd1538b
--- /dev/null
+++ b/src/osgEarth/TileKeyDataStore
@@ -0,0 +1,40 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+* Copyright 2008-2014 Pelican Mapping
+* http://osgearth.org
+*
+* osgEarth is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public License
+* along with this program.  If not, see <http://www.gnu.org/licenses/>
+*/
+#ifndef OSGEARTH_TILEKEY_DATA_STORE
+#define OSGEARTH_TILEKEY_DATA_STORE 1
+
+#include <osgEarth/TileKey>
+#include <osg/ref_ptr>
+
+namespace osgEarth
+{
+    /**
+     * Interface that provides access to a registry of in-memory
+     * tile nodes managed by a terrain engine.
+     */
+    template<typename T>
+    class /*header-only*/ TileKeyDataStore
+    {
+    public:
+        /** Finds a piece of referenced data in the registry */
+        virtual bool get(const TileKey& key, osg::ref_ptr<T>& out_data) const =0;
+    };
+}
+
+#endif // OSGEARTH_TILEKEY_DATA_STORE
diff --git a/src/osgEarth/TilePatchCallback b/src/osgEarth/TilePatchCallback
new file mode 100644
index 0000000..e785bc0
--- /dev/null
+++ b/src/osgEarth/TilePatchCallback
@@ -0,0 +1,79 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+ * Copyright 2016 Pelican Mapping
+ * http://osgearth.org
+ *
+ * osgEarth is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ */
+#ifndef OSGEARTH_TILE_PATCH_CALLBACK_H
+#define OSGEARTH_TILE_PATCH_CALLBACK_H 1
+
+#include <osgEarth/TileKey>
+#include <vector>
+
+// forward declarations
+namespace osg {
+    class Node;
+    class StateSet;
+}
+namespace osgUtil {
+    class CullVisitor;
+}
+
+namespace osgEarth
+{
+    /**
+     * A "Tile Patch" is a patch of surface geometry that corresponds to a terrain tile.
+     * For an engine that supports patches, this callback will let you install custom
+     * rendering state for a tile patch.
+     */
+    class OSGEARTH_EXPORT TilePatchCallback : public osg::Referenced
+    {
+    public:
+        /**
+         * Cull the patch for a given tile. You must push the passed-in stateset, traverse
+         * the patch, and then pop the stateset yourself. You can of course push any additional
+         * state or cull any additional drawables that you want to.
+         *
+         * @param[in ] nv Cull visitor that is traversing the scene graph
+         * @param[in ] key Tile key of the tile currenting being culled
+         * @param[in ] stateSet StateSet corresponding to the current TileKey; the implementation
+         *             is responsible for pushing/popping this
+         * @param[in ] patch Optional node to traverse if you want to render a tessellation patch.
+         */
+        virtual void cull(
+            osgUtil::CullVisitor* nv, 
+            const TileKey&        key, 
+            osg::StateSet*        stateSet, 
+            osg::Node*            patch) =0;
+
+        /**
+         * Release any resources associated with the provided tile key. The engine will call
+         * this automatically then a tile is removed from the scene.
+         *
+         * @param[in ] key TileKey for which to release resources.
+         */
+        virtual void release(
+            const TileKey& key) { }
+
+    protected:
+        virtual ~TilePatchCallback() { }
+    };
+
+    typedef std::vector< osg::ref_ptr<TilePatchCallback> > TilePatchCallbacks;
+
+
+} // namespace osgEarth
+
+#endif // OSGEARTH_TILE_PATCH_CALLBACK_H
diff --git a/src/osgEarth/TilePatchCallback.cpp b/src/osgEarth/TilePatchCallback.cpp
new file mode 100644
index 0000000..a0eac72
--- /dev/null
+++ b/src/osgEarth/TilePatchCallback.cpp
@@ -0,0 +1,26 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+ * Copyright 2016 Pelican Mapping
+ * http://osgearth.org
+ *
+ * osgEarth is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ */
+#include <osgEarth/TilePatchCallback>
+
+#include <osg/Node>
+#include <osg/StateSet>
+#include <osgUtil/CullVisitor>
+
+using namespace osgEarth;
+
diff --git a/src/osgEarth/TileSource b/src/osgEarth/TileSource
index e670475..5ba9e38 100644
--- a/src/osgEarth/TileSource
+++ b/src/osgEarth/TileSource
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -33,6 +33,8 @@
 #include <osgEarth/Profile>
 #include <osgEarth/ThreadingUtils>
 #include <osgEarth/MemCache>
+#include <osgEarth/Status>
+#include <osgEarth/Containers>
 
 #include <osg/Referenced>
 #include <osg/Object>
@@ -97,6 +99,10 @@ namespace osgEarth
         optional<bool>& coverage() { return _coverage; }
         const optional<bool>& coverage() const { return _coverage; }
 
+        /** osgDB::Options option string to pass through to osgDB reader/writers. */
+        optional<std::string>& osgOptionString() { return _osgOptionString; }
+        const optional<std::string>& osgOptionString() const { return _osgOptionString; }
+
     public:
         /** For backwards-compatibility; use minValidValue() instead 
          *  @deprecated */
@@ -131,13 +137,14 @@ namespace osgEarth
         optional<bool>           _bilinearReprojection;
         optional<unsigned>       _maxDataLevel;
         optional<bool>           _coverage;
+        optional<std::string>    _osgOptionString;
     };
 
 
     /**
      * A collection of tiles that should be considered blacklisted
      */
-    class OSGEARTH_EXPORT TileBlacklist : public virtual osg::Referenced
+    class OSGEARTH_EXPORT TileBlacklist : public osg::Referenced
     {
     public:
         /**
@@ -169,11 +176,6 @@ namespace osgEarth
         bool contains(const TileKey& key) const;
 
         /**
-         *Returns the size of the blacklist
-         */
-        unsigned int size() const;
-
-        /**
          *Reads a TileBlacklist from the given istream
          */
         static TileBlacklist* read(std::istream &in);
@@ -194,9 +196,9 @@ namespace osgEarth
         void write(const std::string &filename) const;
 
     private:
-        typedef std::set<TileKey> BlacklistedTiles;
-        BlacklistedTiles _tiles;
-        mutable osgEarth::Threading::ReadWriteMutex _mutex;
+        //typedef std::set<TileKey> BlacklistedTiles;
+        //BlacklistedTiles _tiles;
+        mutable LRUCache<TileKey, bool> _tiles; // using as a set (value unused)
     };
 
     /**
@@ -219,29 +221,12 @@ namespace osgEarth
         /** When using MODE_WRITE, create the data store if necessary */
         static const Mode MODE_CREATE;
 
-
-        /** Initialization status */
-        struct Status
-        {
-        public:
-            Status() { }
-            Status(const Status& rhs) : _msg(rhs._msg) { }
-            Status(const std::string& msg) : _msg(msg) { }
-            bool isOK() const { return _msg.empty(); }
-            bool isError() const { return !_msg.empty(); }
-            const std::string& message() const { return _msg; }
-            bool operator == (const Status& rhs) const { return _msg.compare(rhs._msg)==0; }
-            bool operator != (const Status& rhs) const { return _msg.compare(rhs._msg)!=0; }
-            static Status Error(const std::string& msg) { return Status(msg); }
-        private:
-            std::string _msg;
-        };
-
-        static Status STATUS_OK;
-
         /** interface name, used by the plugin system. */
         static const char* INTERFACE_NAME;
 
+        //typedef osgEarth::Status Status;
+        //static Status STATUS_OK;
+
     public:
         struct ImageOperation : public osg::Referenced {
             virtual void operator()( osg::ref_ptr<osg::Image>& in_out_image ) =0;
@@ -256,6 +241,13 @@ namespace osgEarth
         TileSource(const TileSourceOptions& options);
 
         /**
+         * Opens the tile source and returns the initial status.
+         */
+        const Status& open(
+            const Mode&           openMode  =MODE_READ,
+            const osgDB::Options* dbOptions =0L);
+
+        /**
          * Gets the status of this tile source.
          */
         const Status& getStatus() const { return _status; }
@@ -433,13 +425,6 @@ namespace osgEarth
             { return CachePolicy::DEFAULT; }
 
         /**
-         * Starts up the tile source.
-         */
-        const Status& open(
-            const Mode&           openMode  =MODE_READ,
-            const osgDB::Options* dbOptions =0L);
-
-        /**
          * The open mode (passed to startup).
          */
         const Mode& getMode() const { return _mode; }
@@ -460,9 +445,8 @@ namespace osgEarth
 
     protected:
 
-
         /**
-         * Initializes the tile source (called by startup)
+         * Initializes the tile source (called by open)
          *
          * The osgEarth engine calls this function to initialize a TileSource using an
          * active osgDB::Options. The method returns a status code indicating whether
@@ -474,7 +458,7 @@ namespace osgEarth
          * The Subclass should override this to report a correct initialization status.
          * The default implementation reports STATUS_OK (for compatibility).
          */
-        virtual Status initialize(const osgDB::Options* dbOptions);
+        virtual Status initialize(const osgDB::Options* readOptions) =0;
 
         /**
          * Creates an image for the given TileKey.
@@ -507,7 +491,7 @@ namespace osgEarth
          * status by returning it from initialize(), but you can call this
          * later, e.g. in the event of an unrecoverable error.
          */
-        void setStatus( Status status );
+        void setStatus(const Status& value) { _status = value; }
 
         /**
          * Accesses the map frame that synchronizes with a map if one is set.
@@ -549,8 +533,9 @@ namespace osgEarth
         Status         _status;
         Mode           _mode;
 
-        void setMap(const Map* map);
-        MapFrame* _frame;
+        bool _openCalled;
+
+        mutable Threading::Mutex _mutex;
     };
 
 
diff --git a/src/osgEarth/TileSource.cpp b/src/osgEarth/TileSource.cpp
index a41f28c..fcdf2b8 100644
--- a/src/osgEarth/TileSource.cpp
+++ b/src/osgEarth/TileSource.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -40,7 +40,8 @@ using namespace osgEarth;
 
 //------------------------------------------------------------------------
 
-TileBlacklist::TileBlacklist()
+TileBlacklist::TileBlacklist() :
+_tiles(true, 1024)
 {
     //NOP
 }
@@ -48,15 +49,13 @@ TileBlacklist::TileBlacklist()
 void
 TileBlacklist::add(const TileKey& key)
 {
-    Threading::ScopedWriteLock lock(_mutex);
-    _tiles.insert(key);
+    _tiles.insert(key, true);
     OE_DEBUG << "Added " << key.str() << " to blacklist" << std::endl;
 }
 
 void
 TileBlacklist::remove(const TileKey& key)
 {
-    Threading::ScopedWriteLock lock(_mutex);
     _tiles.erase(key);
     OE_DEBUG << "Removed " << key.str() << " from blacklist" << std::endl;
 }
@@ -64,7 +63,6 @@ TileBlacklist::remove(const TileKey& key)
 void
 TileBlacklist::clear()
 {
-    Threading::ScopedWriteLock lock(_mutex);
     _tiles.clear();
     OE_DEBUG << "Cleared blacklist" << std::endl;
 }
@@ -72,15 +70,7 @@ TileBlacklist::clear()
 bool
 TileBlacklist::contains(const TileKey& key) const
 {
-    Threading::ScopedReadLock lock(_mutex);
-    return _tiles.find(key) != _tiles.end();
-}
-
-unsigned int
-TileBlacklist::size() const
-{
-    Threading::ScopedReadLock lock(_mutex);
-    return _tiles.size();
+    return _tiles.has(key);
 }
 
 TileBlacklist*
@@ -130,14 +120,21 @@ TileBlacklist::write(const std::string &filename) const
     write(out);
 }
 
+namespace {
+    struct WriteFunctor : public LRUCache<TileKey,bool>::Functor {
+        std::ostream& _out;
+        WriteFunctor(std::ostream& out) : _out(out) { }
+        void operator()(const TileKey& key, const bool& value) {
+            _out << key.getLOD() << ' ' << key.getTileX() << ' ' << key.getTileY() << std::endl;
+        }
+    };
+}
+
 void
 TileBlacklist::write(std::ostream &output) const
 {
-    Threading::ScopedReadLock lock(const_cast<TileBlacklist*>(this)->_mutex);
-    for (BlacklistedTiles::const_iterator itr = _tiles.begin(); itr != _tiles.end(); ++itr)
-    {
-        output << itr->getLOD() << " " << itr->getTileX() << " " << itr->getTileY() << std::endl;
-    }
+    WriteFunctor writer(output);
+    _tiles.iterate(writer);
 }
 
 
@@ -171,6 +168,7 @@ TileSourceOptions::getConfig() const
     conf.updateIfSet( "bilinear_reprojection", _bilinearReprojection );
     conf.updateIfSet( "max_data_level", _maxDataLevel );
     conf.updateIfSet( "coverage", _coverage );
+    conf.updateIfSet( "osg_option_string", _osgOptionString );
     conf.updateObjIfSet( "profile", _profileOptions );
     return conf;
 }
@@ -198,6 +196,7 @@ TileSourceOptions::fromConfig( const Config& conf )
     conf.getIfSet( "bilinear_reprojection", _bilinearReprojection );
     conf.getIfSet( "max_data_level", _maxDataLevel );
     conf.getIfSet( "coverage", _coverage );
+    conf.getIfSet( "osg_option_string", _osgOptionString );
     conf.getObjIfSet( "profile", _profileOptions );
 }
 
@@ -205,7 +204,6 @@ TileSourceOptions::fromConfig( const Config& conf )
 //------------------------------------------------------------------------
 
 // statics
-TileSource::Status TileSource::STATUS_OK = TileSource::Status();
 
 const char* TileSource::INTERFACE_NAME = "osgEarth::TileSource";
 
@@ -218,12 +216,10 @@ TileSource::TileSource(const TileSourceOptions& options) :
 _options( options ),
 _status ( Status::Error("Not initialized") ),
 _mode   ( 0 ),
-_frame  ( 0L )
+_openCalled( false )
 {
     this->setThreadSafeRefUnref( true );
 
-    _frame = new MapFrame();
-
     // Initialize the l2 cache size to the options.
     int l2CacheSize = *options.L2CacheSize();
 
@@ -234,6 +230,13 @@ _frame  ( 0L )
         l2CacheSize = as<int>( std::string(l2env), 0 );
     }
 
+    // Env cache-only mode also disables the L2 cache.
+    char const* noCacheEnv = ::getenv( "OSGEARTH_MEMORY_PROFILE" );
+    if ( noCacheEnv )
+    {
+        l2CacheSize = 0;
+    }
+
     // Initialize the l2 cache if it's size is > 0
     if ( l2CacheSize > 0 )
     {
@@ -268,56 +271,38 @@ TileSource::~TileSource()
     {
         _blacklist->write(_blacklistFilename);
     }
-
-    if ( _frame )
-    {
-        delete _frame;
-    }
-}
-
-void
-TileSource::setStatus( TileSource::Status status )
-{
-    _status = status;
 }
 
-TileSource::Status
-TileSource::initialize(const osgDB::Options* options)
-{
-    // default implementation. Subclasses should override this.
-    return STATUS_OK;
-}
-
-const TileSource::Status&
+const Status&
 TileSource::open(const Mode&           openMode,
                  const osgDB::Options* options)
 {
-    _mode = openMode;
+    if (!_openCalled)
+    {
+        _mode = openMode;
 
-    // Initialize the underlying data store
-    Status status = initialize(options);
+        // Initialize the underlying data store
+        Status status = initialize(options);
 
-    // Check the return status. The TileSource MUST have a valid
-    // Profile after initialization.
-    if ( status == STATUS_OK )
-    {
-        if ( getProfile() != 0L )
+        // Check the return status. The TileSource MUST have a valid
+        // Profile after initialization.
+        if ( status == STATUS_OK )
         {
-            _status = status;
+            if ( getProfile() != 0L )
+            {
+                _status = status;
+            }
+            else 
+            {
+                _status = Status::Error("No profile available");
+            }
         }
-        else 
+        else
         {
-            _status = Status::Error("No profile available");
+            _status = status;
         }
-    }
-    else
-    {
-        _status = status;
-    }
 
-    if ( _status.isError() )
-    {
-        OE_WARN << LC << "Open failed: " << _status.message() << std::endl;
+        _openCalled = true;
     }
 
     return _status;
@@ -339,8 +324,7 @@ const GeoExtent& TileSource::getDataExtentsUnion() const
 {
     if (_dataExtentsUnion.isInvalid() && _dataExtents.size() > 0)
     {
-        static Threading::Mutex s_mutex;
-        Threading::ScopedMutexLock lock(s_mutex);
+        Threading::ScopedMutexLock lock(_mutex);
         {
             if (_dataExtentsUnion.isInvalid() && _dataExtents.size() > 0) // double-check
             {
@@ -356,30 +340,18 @@ const GeoExtent& TileSource::getDataExtentsUnion() const
     return _dataExtentsUnion;
 }
 
-void
-TileSource::setMap(const Map* map)
-{
-    _frame->setMap( map );
-}
-
-MapFrame&
-TileSource::getMapFrame() const
-{
-    return *_frame;
-}
-
 osg::Image*
 TileSource::createImage(const TileKey&        key,
                         ImageOperation*       prepOp, 
                         ProgressCallback*     progress )
 {
-    if ( _status != STATUS_OK )
+    if (getStatus().isError())
         return 0L;
 
     // Try to get it from the memcache fist
     if (_memCache.valid())
     {
-        ReadResult r = _memCache->getOrCreateDefaultBin()->readImage( key.str() );
+        ReadResult r = _memCache->getOrCreateDefaultBin()->readImage(key.str(), 0L);
         if ( r.succeeded() )
             return r.releaseImage();
     }
@@ -392,7 +364,7 @@ TileSource::createImage(const TileKey&        key,
     if ( newImage.valid() && _memCache.valid() )
     {
         // cache it to the memory cache.
-        _memCache->getOrCreateDefaultBin()->write( key.str(), newImage.get() );
+        _memCache->getOrCreateDefaultBin()->write(key.str(), newImage.get(), 0L);
     }
 
     return newImage.release();
@@ -403,13 +375,13 @@ TileSource::createHeightField(const TileKey&        key,
                               HeightFieldOperation* prepOp, 
                               ProgressCallback*     progress )
 {
-    if ( _status != STATUS_OK )
+    if (getStatus().isError())
         return 0L;
 
     // Try to get it from the memcache first:
     if (_memCache.valid())
     {
-        ReadResult r = _memCache->getOrCreateDefaultBin()->readObject( key.str() );
+        ReadResult r = _memCache->getOrCreateDefaultBin()->readObject(key.str(), 0L);
         if ( r.succeeded() )
             return r.release<osg::HeightField>();
     }
@@ -421,7 +393,7 @@ TileSource::createHeightField(const TileKey&        key,
 
     if ( newHF.valid() && _memCache.valid() )
     {
-        _memCache->getOrCreateDefaultBin()->write( key.str(), newHF.get() );
+        _memCache->getOrCreateDefaultBin()->write(key.str(), newHF.get(), 0L);
     }
 
     //TODO: why not just newHF.release()? -gw
@@ -439,7 +411,7 @@ osg::HeightField*
 TileSource::createHeightField(const TileKey&        key,
                               ProgressCallback*     progress)
 {
-    if ( _status != STATUS_OK )
+    if (getStatus().isError())
         return 0L;
 
     osg::ref_ptr<osg::Image> image = createImage(key, progress);
@@ -457,7 +429,7 @@ TileSource::storeHeightField(const TileKey&     key,
                              osg::HeightField*  hf,
                               ProgressCallback* progress)
 {
-    if ( _status != STATUS_OK || hf == 0L )
+    if (getStatus().isError() || hf == 0L )
         return 0L;
 
     ImageToHeightFieldConverter conv;
@@ -472,7 +444,7 @@ TileSource::storeHeightField(const TileKey&     key,
 bool
 TileSource::isOK() const 
 {
-    return _status == STATUS_OK;
+    return _status.isOK();
 }
 
 void
@@ -570,6 +542,9 @@ TileSource::hasData(const osgEarth::TileKey& key) const
 {
     //sematics: "might have data"
 
+    if ( !key.valid() )
+        return false;
+
     // If no data extents are provided, and there's no data level override,
     // return true because there might be data but there's no way to tell.
     if (_dataExtents.size() == 0 && !_options.maxDataLevel().isSet())
@@ -618,6 +593,10 @@ bool
 TileSource::getBestAvailableTileKey(const osgEarth::TileKey& key,
                                     osgEarth::TileKey&       output) const
 {
+    // trivial reject
+    if ( !key.valid() )
+        return false;
+
     // trivial accept: no data extents = not enough info.
     if (_dataExtents.size() == 0)
     {
@@ -643,7 +622,7 @@ TileSource::getBestAvailableTileKey(const osgEarth::TileKey& key,
         if (key.getExtent().intersects( *itr ))
         {
             // check that the extent isn't higher-resolution than our key:
-            if ( !itr->minLevel().isSet() || layerLOD >= itr->minLevel().get() )
+            if ( !itr->minLevel().isSet() || layerLOD >= (int)itr->minLevel().get() )
             {
                 // Got an intersetion; now test the LODs:
                 intersects = true;
@@ -658,7 +637,7 @@ TileSource::getBestAvailableTileKey(const osgEarth::TileKey& key,
 
                 // Is our key at a lower or equal LOD than the max key in this extent?
                 // If so, our key is good.
-                else if ( layerLOD <= itr->maxLevel().get() )
+                else if ( layerLOD <= (int)itr->maxLevel().get() )
                 {
                     output = key;
                     return true;
@@ -690,6 +669,9 @@ TileSource::hasDataForFallback(const osgEarth::TileKey& key) const
 {
     //sematics: might have data.
 
+    if ( !key.valid() )
+        return false;
+
     //If no data extents are provided, just return true
     if (_dataExtents.size() == 0) 
         return true;
@@ -749,68 +731,36 @@ TileSourceFactory::create(const TileSourceOptions& options)
     result = dynamic_cast<TileSource*>( osgDB::readObjectFile( driverExt, dbopt.get() ) );
     if ( !result )
     {
-        OE_WARN << LC << "Failed to load TileSource driver \"" << driver << "\"" << std::endl;
-    }
-
-    OE_DEBUG << LC << "Tile source Profile = " << (result->getProfile() ? result->getProfile()->toString() : "NULL") << std::endl;
-
-    // apply an Override Profile if provided.
-    if ( result && options.profile().isSet() )
-    {
-        const Profile* profile = Profile::create(*options.profile());
-        if ( profile )
-        {
-            result->setProfile( profile );
-        }
-    }
-
-    return result;
-}
-
-#if 0
-ReadWriteTileSource*
-TileSourceFactory::openReadWrite(const TileSourceOptions& options)
-{
-    ReadWriteTileSource* result = 0L;
-
-    std::string driver = options.getDriver();
-    if ( driver.empty() )
-    {
-        OE_WARN << LC << "ILLEGAL- no driver set for tile source" << std::endl;
-        return 0L;
+        OE_INFO << LC << "Failed to load TileSource driver \"" << driver << "\"" << std::endl;
     }
 
-    osg::ref_ptr<osgDB::Options> dbopt = Registry::instance()->cloneOrCreateOptions();
-    dbopt->setPluginData      ( TILESOURCEOPTIONS_TAG,   (void*)&options );
-    dbopt->setPluginStringData( TILESOURCEINTERFACE_TAG, ReadWriteTileSource::INTERFACE_NAME );
-
-    std::string driverExt = std::string( ".osgearth_" ) + driver;
-    result = dynamic_cast<ReadWriteTileSource*>( osgDB::readObjectFile( driverExt, dbopt.get() ) );
-    if ( !result )
+    else
     {
-        OE_WARN << LC << "Failed to load ReadWriteTileSource driver \"" << driver << "\"" << std::endl;
-    }
+        OE_DEBUG << LC << "Tile source Profile = " << (result->getProfile() ? result->getProfile()->toString() : "NULL") << std::endl;
 
-    // apply an Override Profile if provided.
-    if ( result && options.profile().isSet() )
-    {
-        const Profile* profile = Profile::create(*options.profile());
-        if ( profile )
+        // apply an Override Profile if provided.
+        if ( options.profile().isSet() )
         {
-            result->setProfile( profile );
+            const Profile* profile = Profile::create(*options.profile());
+            if ( profile )
+            {
+                result->setProfile( profile );
+            }
         }
     }
 
     return result;
 }
-#endif
+
 
 //------------------------------------------------------------------------
 
 const TileSourceOptions&
 TileSourceDriver::getTileSourceOptions(const osgDB::Options* dbopt ) const
 {
-    return *static_cast<const TileSourceOptions*>( dbopt->getPluginData( TILESOURCE_OPTIONS_TAG ) );
+    static TileSourceOptions s_default;
+    const void* data = dbopt->getPluginData(TILESOURCE_OPTIONS_TAG);
+    return data ? *static_cast<const TileSourceOptions*>(data) : s_default;
 }
 
 const std::string
diff --git a/src/osgEarth/TileVisitor b/src/osgEarth/TileVisitor
index b599c06..7b365c7 100644
--- a/src/osgEarth/TileVisitor
+++ b/src/osgEarth/TileVisitor
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarth/TileVisitor.cpp b/src/osgEarth/TileVisitor.cpp
index dcef395..c1b0f1f 100644
--- a/src/osgEarth/TileVisitor.cpp
+++ b/src/osgEarth/TileVisitor.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -291,11 +291,14 @@ bool TaskList::load( const std::string &filename)
         std::vector< std::string > parts;
         StringTokenizer(line, parts, "," );
 
-
-        _keys.push_back( TileKey(as<unsigned int>(parts[0], 0), 
-            as<unsigned int>(parts[1], 0), 
-            as<unsigned int>(parts[2], 0),
-            _profile ) );
+        if (parts.size() >= 3)
+        {
+            _keys.push_back( TileKey(
+                as<unsigned int>(parts[0], 0u), 
+                as<unsigned int>(parts[1], 0u), 
+                as<unsigned int>(parts[2], 0u),
+                _profile ) );
+        }
     }
 
 
diff --git a/src/osgEarth/TimeControl b/src/osgEarth/TimeControl
index 82dcc76..5dfb7c9 100644
--- a/src/osgEarth/TimeControl
+++ b/src/osgEarth/TimeControl
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarth/TimeControl.cpp b/src/osgEarth/TimeControl.cpp
index 6f594c4..2cd25f3 100644
--- a/src/osgEarth/TimeControl.cpp
+++ b/src/osgEarth/TimeControl.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarth/TraversalData b/src/osgEarth/TraversalData
index 95ace91..16c5356 100644
--- a/src/osgEarth/TraversalData
+++ b/src/osgEarth/TraversalData
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -21,58 +21,82 @@
 
 #include <osgEarth/Common>
 #include <osgEarth/ThreadingUtils>
+//#include <osgEarth/Horizon>
+#include <osgEarth/Containers>
+//#include <osg/Version>
 #include <osg/NodeVisitor>
 #include <osg/observer_ptr>
 #include <map>
 
+// osgEarth node masks for controlling traversals
+#define OSGEARTH_MASK_TERRAIN_SURFACE    0x01
+#define OSGEARTH_MASK_TERRAIN_LAND_COVER 0x02
+#define OSGEARTH_MASK_TERRAIN            (OSGEARTH_MASK_TERRAIN_SURFACE | OSGEARTH_MASK_TERRAIN_LAND_COVER)
+#define OSGEARTH_MASK_MAP_MODEL_GROUP    0x04
+
+
 namespace osgEarth
 {
     class MapNode;
 
-    class TraversalData : public osg::Referenced
+    // internal utility class supporing VisitorData
+    class OSGEARTH_EXPORT TransientUserDataStore
     {
     public:
-        typedef std::map<void*, osg::ref_ptr<osg::Referenced> > UserDataMap;
+        void store(osg::Referenced* owner, const std::string& key, osg::Referenced* data);
 
-        template<typename T> T& getOrCreate(void* key)
-        {
-            UserDataMap::iterator i = _userData.find( key );
-            if ( i != _userData.end() )
-                return *static_cast<T*>( i->second.get() );
-            T* t = new T();
-            _userData[key] = t;
-            return *t;
-        }
+        osg::Referenced* fetch(osg::Referenced* owner, const std::string& key) const;
 
-    public:
-        TraversalData() { }
-        static TraversalData* get(osg::NodeVisitor& nv)
-        {
-            return dynamic_cast<TraversalData*>( nv.getUserData() );
-        }
+        bool exists(osg::Referenced* owner, const std::string& key) const;
 
+        int size() const;
+        
     protected:
-        UserDataMap _userData;
-    };
+        typedef fast_map<std::string, osg::ref_ptr<osg::Referenced> > StringTable;
 
+        struct DataPair {
+            osg::observer_ptr<osg::Referenced> _owner;
+            StringTable                    _data;
+        };
 
-    /**
-     * Per-camera data for MapNode culling traversals.
-     */
-    class OSGEARTH_EXPORT MapNodeCullData : public osg::Referenced
-    {
-    public:
-        MapNodeCullData();
+        typedef fast_map<void*, DataPair> Table;
+
+        Table _table;
+
+        mutable Threading::Mutex _mutex;
+
+        static bool isObserverInvalid(const Table::entry_t&);
 
     public:
-        osg::observer_ptr<class MapNode> _mapNode;
-        osg::ref_ptr<osg::StateSet>      _stateSet;
-        osg::ref_ptr<osg::Uniform>       _windowMatrixUniform;
-        double                           _cameraAltitude;
-        osg::ref_ptr<osg::Uniform>       _cameraAltitudeUniform;
+        static bool unitTest();
+    };
 
-    protected:
-        virtual ~MapNodeCullData() { }
+    struct OSGEARTH_EXPORT VisitorData
+    {
+        static bool isSet(osg::NodeVisitor& nv, const std::string& key);
+
+        struct Install : public osg::NodeCallback
+        {
+            osg::ref_ptr<osg::Referenced> _data;
+            std::string _key;
+
+            Install(const std::string& key) : _key(key) { }
+            Install(const std::string& key, osg::Referenced* data) : _key(key), _data(data) { }
+
+            void operator()(osg::Node* node, osg::NodeVisitor* nv)
+            {
+                VisitorData::store(*nv, _key, _data.get());
+                traverse(node, nv);
+                //VisitorData::clear(*nv, _key);
+            }
+        };
+
+        static bool store(osg::NodeVisitor& nv, const std::string& key, osg::Referenced* object);
+
+        template<typename T> static T* fetch(osg::NodeVisitor& nv, const std::string& key) {
+            return dynamic_cast<T*>( _fetch(nv, key) ); }
+
+        static osg::Referenced* _fetch(osg::NodeVisitor& nv, const std::string& key);
     };
 
 } // namespace osgEarth
diff --git a/src/osgEarth/TraversalData.cpp b/src/osgEarth/TraversalData.cpp
index 0f31324..50d845d 100644
--- a/src/osgEarth/TraversalData.cpp
+++ b/src/osgEarth/TraversalData.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -17,18 +17,122 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>
  */
 #include <osgEarth/TraversalData>
+#include <osgEarth/Registry>
+#include <osg/ValueObject>
 
 using namespace osgEarth;
 
-MapNodeCullData::MapNodeCullData()
+bool
+TransientUserDataStore::isObserverInvalid(const Table::entry_t& p)
 {
-    _stateSet = new osg::StateSet();
+    return p.second._owner.valid() == false;
+}
+
+int
+TransientUserDataStore::size() const
+{
+    return _table.size();
+}
+
+void
+TransientUserDataStore::store(osg::Referenced* owner, const std::string& key, osg::Referenced* data)
+{
+    if ( !owner ) return;
+
+    _mutex.lock();
+
+    // clear out orphaned data:
+    _table.erase( std::remove_if(_table.begin(), _table.end(), isObserverInvalid), _table.end() );
+
+    // insert new data:
+    DataPair& p = _table[owner];
+    p._owner = owner;
+    p._data[key] = data;
+
+    _mutex.unlock();
+}
+
+osg::Referenced*
+TransientUserDataStore::fetch(osg::Referenced* owner, const std::string& key) const
+{
+    if ( !owner )
+        return 0L;
+
+    Threading::ScopedMutexLock lock(_mutex);
+    Table::const_iterator i = _table.find(owner);
+    if ( i == _table.end() || i->second._owner.valid() == false )
+        return 0L;
+
+    StringTable::const_iterator j = i->second._data.find(key);
+    if ( j == i->second._data.end() )
+        return 0L;
+
+    return j->second.get();
+}
+
+bool
+TransientUserDataStore::exists(osg::Referenced* owner, const std::string& key) const
+{
+    if ( !owner )
+        return false;
+
+    Threading::ScopedMutexLock lock(_mutex);
+    Table::const_iterator i = _table.find(owner);
+    if ( i == _table.end() || i->second._owner.valid() == false )
+        return false;
+
+    StringTable::const_iterator j = i->second._data.find(key);
+    return ( j != i->second._data.end() );
+}
+
+bool
+TransientUserDataStore::unitTest()
+{
+  osgEarth::TransientUserDataStore tuds;
+  osg::ref_ptr<osg::Referenced> owner1 = new osg::Referenced;
+  osg::ref_ptr<osg::Referenced> owner2 = new osg::Referenced;
+  osg::ref_ptr<osg::Referenced> owner3 = new osg::Referenced;
+  osg::ref_ptr<osg::Referenced> data1 = new osg::Referenced;
+  osg::ref_ptr<osg::Referenced> data2 = new osg::Referenced;
+  osg::ref_ptr<osg::Referenced> data3 = new osg::Referenced;
+  tuds.store(owner1, "foo", data1);
+  tuds.store(owner1, "foo", data2);
+  tuds.store(owner1, "foo", data1);
+  data1 = NULL;
+  tuds.store(owner1, "foo", data2);
+  data2 = new osg::Referenced;
+  tuds.store(owner1, "foo", data3);
+  tuds.store(owner1, "foo", data2);
+  data1 = new osg::Referenced;
+  owner1 = owner2;
+  tuds.store(owner1, "foo", data3);
+  tuds.store(owner1, "foo", data1);
+  tuds.store(owner3, "foo", data1);
+  owner3 = NULL;
+  tuds.store(owner1, "foo", data2);
+  tuds.store(owner2, "foo", data2);
+  owner1 = owner2 = owner3 = NULL;
+  owner1 = new osg::Referenced;
+  tuds.store(owner1, "foo", data3);
+  return true;
+}
+
+bool
+VisitorData::store(osg::NodeVisitor& nv, const std::string& key, osg::Referenced* data)
+{
+    Registry::instance()->dataStore().store( &nv, key, data );
+    return true;
+}
 
-    _windowMatrixUniform = new osg::Uniform(osg::Uniform::FLOAT_MAT4, "oe_WindowMatrix");
-    _windowMatrixUniform->set( osg::Matrix::identity() );
-    _stateSet->addUniform( _windowMatrixUniform.get() );
+osg::Referenced*
+VisitorData::_fetch(osg::NodeVisitor& nv, const std::string& key)
+{
+    return Registry::instance()->dataStore().fetch( &nv, key );
+}
 
-    _cameraAltitude = 0.0;
-    _cameraAltitudeUniform = new osg::Uniform(osg::Uniform::FLOAT, "oe_CameraAltitude");
-    _stateSet->addUniform( _cameraAltitudeUniform.get() );
+bool
+VisitorData::isSet(osg::NodeVisitor& nv, const std::string& key)
+{
+    return Registry::instance()->dataStore().exists( &nv, key );
 }
+
diff --git a/src/osgEarth/URI b/src/osgEarth/URI
index dd86a24..d886f05 100644
--- a/src/osgEarth/URI
+++ b/src/osgEarth/URI
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -67,7 +67,7 @@ namespace osgEarth
         /** Serializes this context to an Options structure. This is useful when passing context information
             to an osgDB::ReaderWriter that takes a stream as input -- the stream is anonymous, therefore this
             is the preferred way to communicate the context information. */
-        void apply( osgDB::Options* options );
+        void store( osgDB::Options* options );
 
         /** Creates a context from the serialized version in an Options structure (see above) */
         URIContext( const osgDB::Options* options );
@@ -250,7 +250,7 @@ namespace osgEarth
 
     public:
         /** Copier */
-        URI( const URI& rhs ) : _baseURI(rhs._baseURI), _fullURI(rhs._fullURI), _context(rhs._context) { }
+        URI( const URI& rhs );
 
 
     public: // config methods
@@ -259,6 +259,8 @@ namespace osgEarth
         {
             Config conf("uri", base());
             conf.addIfSet("option_string", _optionString);
+            conf.setReferrer( context().referrer() );
+            conf.setIsLocation( true );
             return conf;
         }
 
@@ -273,6 +275,8 @@ namespace osgEarth
         std::string _cacheKey;
         URIContext  _context;
         optional<std::string> _optionString;
+
+        void ctorCacheKey();
     };
     
 
@@ -315,7 +319,7 @@ namespace osgEarth
          * Loads an alias map from an Options.
          */
         static URIAliasMap* from( const osgDB::Options* options ) {
-            return options ? static_cast<URIAliasMap*>(const_cast<osgDB::Options*>(options)->getPluginData("osgEarth::URIAliasMap")) : 0L;
+            return options ? const_cast<URIAliasMap*>(static_cast<const URIAliasMap*>(options->getPluginData("osgEarth::URIAliasMap"))) : 0L;
         }
 
         /**
@@ -369,7 +373,7 @@ namespace osgEarth
             : LRUCache<URI,ReadResult>( threadsafe ) { }
 
         static URIResultCache* from(const osgDB::Options* options) {
-            return options ? static_cast<URIResultCache*>(const_cast<osgDB::Options*>(options)->getPluginData("osgEarth::URIResultCache")) : 0L;
+            return options ? const_cast<URIResultCache*>(static_cast<const URIResultCache*>(options->getPluginData("osgEarth::URIResultCache"))) : 0L;
         }
 
         void apply( osgDB::Options* options ) {
@@ -398,7 +402,7 @@ namespace osgEarth
         }
 
         static URIPostReadCallback* from(const osgDB::Options* options) {
-            return options ? static_cast<URIPostReadCallback*>(const_cast<osgDB::Options*>(options)->getPluginData("osgEarth::URIPostReadCallback")) : 0L;
+            return options ? const_cast<URIPostReadCallback*>(static_cast<const URIPostReadCallback*>(options->getPluginData("osgEarth::URIPostReadCallback"))) : 0L;
         }
     };
 
@@ -410,21 +414,17 @@ namespace osgEarth
     template <> inline
     void Config::addIfSet<URI>( const std::string& key, const optional<URI>& opt ) {
         if ( opt.isSet() ) {
-            add(key, opt->getConfig());
-            //Config conf(key, opt->base());
-            //conf.setReferrer(opt->context().referrer());
-            //add( conf );
+            Config c = opt->getConfig();
+            c.key() = key;
+            add( c );
         }
     }
 
     template<> inline
     void Config::updateIfSet<URI>( const std::string& key, const optional<URI>& opt ) {
         if ( opt.isSet() ) {
-            //remove(key);
-            update(key, opt->getConfig());
-            //Config conf(key, opt->base());
-            //conf.setReferrer(opt->context().referrer());
-            //add( conf );
+            remove(key);
+            add( key, opt->getConfig() );
         }
     }
 
diff --git a/src/osgEarth/URI.cpp b/src/osgEarth/URI.cpp
index e065bb0..9519e01 100644
--- a/src/osgEarth/URI.cpp
+++ b/src/osgEarth/URI.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -117,7 +117,7 @@ URIContext::add( const std::string& sub ) const
 }
 
 void
-URIContext::apply( osgDB::Options* options )
+URIContext::store( osgDB::Options* options )
 {
     if ( options )
     {
@@ -153,10 +153,20 @@ URI::URI()
     //nop
 }
 
+URI::URI(const URI& rhs) :
+_baseURI(rhs._baseURI),
+_fullURI(rhs._fullURI),
+_context(rhs._context),
+_cacheKey(rhs._cacheKey)
+{
+    //nop
+}
+
 URI::URI( const std::string& location )
 {
     _baseURI = location;
     _fullURI = location;
+    ctorCacheKey();
 }
 
 URI::URI( const std::string& location, const URIContext& context )
@@ -164,12 +174,14 @@ URI::URI( const std::string& location, const URIContext& context )
     _context = context;
     _baseURI = location;
     _fullURI = context.getOSGPath( _baseURI );
+    ctorCacheKey();
 }
 
 URI::URI( const char* location )
 {
     _baseURI = std::string(location);
     _fullURI = _baseURI;
+    ctorCacheKey();
 }
 
 URI
@@ -179,9 +191,20 @@ URI::append( const std::string& suffix ) const
     result._baseURI = _baseURI + suffix;
     result._fullURI = _fullURI + suffix;
     result._context = _context;
+    result.ctorCacheKey();
     return result;
 }
 
+void
+URI::ctorCacheKey()
+{
+    std::string temp = Stringify() << std::hex << std::setw(8) << std::setfill('0') << osgEarth::hashString(_fullURI);
+    _cacheKey
+        .append(temp.substr(0, 3)).append("/")
+        .append(temp.substr(3, 3)).append("/")
+        .append(temp.substr(6));
+}
+
 bool
 URI::isRemote() const
 {
@@ -190,35 +213,6 @@ URI::isRemote() const
 
 namespace
 {
-    // extracts a CacheBin from the dboptions; if one cannot be found, fall back on the
-    // default CacheBin of a Cache found in the dboptions; failing that, call back on
-    // the default CacheBin of the registry-wide cache.
-    CacheBin* s_getCacheBin(const osgDB::Options* dbOptions)
-    {
-        const osgDB::Options* o = dbOptions;
-        
-        if ( o == 0L )
-        {
-            o = Registry::instance()->getDefaultOptions();
-        }
-
-        CacheBin* bin = CacheBin::get( o );
-        if ( !bin )
-        {
-            Cache* cache = Cache::get( o );
-            if ( !cache )
-            {
-                cache = Registry::instance()->getCache();
-            }
-
-            if ( cache )
-            {
-                bin = cache->getOrCreateDefaultBin();
-            }
-        }
-        return bin;
-    }
-
     // convert an osgDB::ReaderWriter::ReadResult to an osgEarth::ReadResult
     ReadResult toReadResult( osgDB::ReaderWriter::ReadResult& rr )
     {
@@ -271,7 +265,7 @@ namespace
         }
 
         // no archive; just read it normally
-        std::ifstream input( uri.c_str() );
+        std::ifstream input( uri.c_str(), std::ios::binary );
         if ( input.is_open() )
         {
             input >> std::noskipws;
@@ -296,7 +290,7 @@ namespace
     {
         bool callbackRequestsCaching( URIReadCallback* cb ) const { return !cb || ((cb->cachingSupport() & URIReadCallback::CACHE_OBJECTS) != 0); }
         ReadResult fromCallback( URIReadCallback* cb, const std::string& uri, const osgDB::Options* opt ) { return cb->readObject(uri, opt); }
-        ReadResult fromCache( CacheBin* bin, const std::string& key) { return bin->readObject(key); }
+        ReadResult fromCache( CacheBin* bin, const std::string& key) { return bin->readObject(key, 0L); }
         ReadResult fromHTTP( const std::string& uri, const osgDB::Options* opt, ProgressCallback* p, TimeStamp lastModified )
         {
             HTTPRequest req(uri);            
@@ -313,7 +307,7 @@ namespace
     {
         bool callbackRequestsCaching( URIReadCallback* cb ) const { return !cb || ((cb->cachingSupport() & URIReadCallback::CACHE_NODES) != 0); }
         ReadResult fromCallback( URIReadCallback* cb, const std::string& uri, const osgDB::Options* opt ) { return cb->readNode(uri, opt); }
-        ReadResult fromCache( CacheBin* bin, const std::string& key ) { return bin->readObject(key); }
+        ReadResult fromCache( CacheBin* bin, const std::string& key ) { return bin->readObject(key, 0L); }
         ReadResult fromHTTP( const std::string& uri, const osgDB::Options* opt, ProgressCallback* p, TimeStamp lastModified )
         {
             HTTPRequest req(uri);            
@@ -337,7 +331,7 @@ namespace
             return r;
         }                
         ReadResult fromCache( CacheBin* bin, const std::string& key) { 
-            ReadResult r = bin->readImage(key);
+            ReadResult r = bin->readImage(key, 0L);
             if ( r.getImage() ) r.getImage()->setFileName( key );
             return r;
         }
@@ -362,7 +356,7 @@ namespace
     {
         bool callbackRequestsCaching( URIReadCallback* cb ) const { return !cb || ((cb->cachingSupport() & URIReadCallback::CACHE_STRINGS) != 0); }
         ReadResult fromCallback( URIReadCallback* cb, const std::string& uri, const osgDB::Options* opt ) { return cb->readString(uri, opt); }
-        ReadResult fromCache( CacheBin* bin, const std::string& key) { return bin->readString(key); }
+        ReadResult fromCache( CacheBin* bin, const std::string& key) { return bin->readString(key, 0L); }
         ReadResult fromHTTP( const std::string& uri, const osgDB::Options* opt, ProgressCallback* p, TimeStamp lastModified )
         {
             HTTPRequest req(uri);            
@@ -397,7 +391,7 @@ namespace
             // if we have an option string, incorporate it.
             if ( inputURI.optionString().isSet() )
             {
-                osgDB::Options* newLocalOptions = osg::clone(localOptions.get());
+                osgDB::Options* newLocalOptions = Registry::cloneOrCreateOptions(localOptions.get());
                 newLocalOptions->setOptionString(
                     inputURI.optionString().get() + " " + localOptions->getOptionString());
                 localOptions = newLocalOptions;
@@ -460,18 +454,18 @@ namespace
                 {
                     bool callbackCachingOK = !cb || reader.callbackRequestsCaching(cb);
 
-                    // establish the caching policy.
                     optional<CachePolicy> cp;
-                    CachePolicy::fromOptions(localOptions.get(), cp);
-                    Registry::instance()->resolveCachePolicy( cp );                    
+                    osg::ref_ptr<CacheBin> bin;
 
-                    // get a cache bin if we need it:
-                    CacheBin* bin = 0L;
-                    if ( (cp->usage() != CachePolicy::USAGE_NO_CACHE) && callbackCachingOK )
+                    CacheSettings* cacheSettings = CacheSettings::get(localOptions.get());
+                    if (cacheSettings)
                     {
-                        bin = s_getCacheBin( localOptions.get() );
-                    }                    
-
+                        cp = cacheSettings->cachePolicy();
+                        if (cp->isCacheEnabled() && callbackCachingOK)
+                        {
+                            bin = cacheSettings->getCacheBin(); 
+                        }
+                    }
 
                     bool expired = false;
                     // first try to go to the cache if there is one:
@@ -518,7 +512,8 @@ namespace
                                 {                                    
                                     OE_DEBUG << LC << uri.full() << " not modified, using cached result" << std::endl;
                                     // Touch the cached item to update it's last modified timestamp so it doesn't expire again immediately.
-                                    bin->touch( uri.cacheKey() );
+                                    if (bin)
+                                        bin->touch( uri.cacheKey() );
                                 }
                                 else
                                 {
@@ -528,10 +523,10 @@ namespace
                             }
 
                             // write the result to the cache if possible:
-                            if ( result.succeeded() && !result.isFromCache() && bin && cp->isCacheWriteable() )
+                            if ( result.succeeded() && !result.isFromCache() && bin && cp->isCacheWriteable() && bin )
                             {
                                 OE_DEBUG << LC << "Writing " << uri.cacheKey() << " to cache" << std::endl;
-                                bin->write( uri.cacheKey(), result.getObject(), result.metadata() );
+                                bin->write( uri.cacheKey(), result.getObject(), result.metadata(), remoteOptions );
                             }
                         }
                     }
diff --git a/src/osgEarth/Units b/src/osgEarth/Units
index 7b3bad4..56629cb 100644
--- a/src/osgEarth/Units
+++ b/src/osgEarth/Units
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -157,7 +157,7 @@ namespace osgEarth
         // Maks a new unit definition (SPEED)
         Units( const std::string& name, const std::string& abbr, const Units& distance, const Units& time );
 
-        Units() : _type(TYPE_INVALID) { }
+        Units() : _type(TYPE_INVALID), _toBase(0.0), _distance(0L), _time(0L) { }
 
     private:
 
@@ -180,6 +180,12 @@ namespace osgEarth
         // called by Registry to register system units
         static void registerAll(class Registry* registry);
         friend class Registry;
+
+    public:
+
+        // returns 0 upon success, error code on failure
+        static int unitTest();
+
     };
     
     template<typename T>
@@ -191,12 +197,12 @@ namespace osgEarth
         qualified_double<T>( const T& rhs ) : _value(rhs._value), _units(rhs._units) { }
 
         // parses the qualified number from a parseable string (e.g., "123km")
-        qualified_double<T>(const std::string& parseable, const Units& defaultUnits) {
+        qualified_double<T>(const std::string& parseable, const Units& defaultUnits) : _value(0.0), _units(defaultUnits) {
             Units::parse( parseable, _value, _units, defaultUnits );
         }
 
         // loads the qualified number from an old-school config (e.g., { value="123" units="km" } )
-        qualified_double<T>( const Config& conf, const Units& defaultUnits ) {
+        qualified_double<T>( const Config& conf, const Units& defaultUnits ) : _value(0.0) {
             if ( conf.hasValue("value") ) {
                 _value = conf.value<double>("value", 0.0);
                 if ( !Units::parse( conf.value("units"), _units ) )
diff --git a/src/osgEarth/Units.cpp b/src/osgEarth/Units.cpp
index ba6799b..133e546 100644
--- a/src/osgEarth/Units.cpp
+++ b/src/osgEarth/Units.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -41,7 +41,19 @@ namespace
 
         std::string valueStr, unitsStr;
 
-        std::string::const_iterator i = std::find_if( input.begin(), input.end(), ::isalpha );
+        std::string::const_iterator start = input.begin();
+        
+        // deal with scientific notation by moving the units search point
+        // past the "e+/-" if it exists:
+        std::string::size_type pos = input.find_first_of("eE");
+        if (pos != std::string::npos && 
+            input.length() > (pos+2) &&
+            (input.at(pos+1) == '-' || input.at(pos+1) == '+'))
+        {
+            start = input.begin() + pos + 2;
+        }
+
+        std::string::const_iterator i = std::find_if( start, input.end(), ::isalpha );
         if ( i == input.end() )
         {
             // to units found; use default
@@ -84,7 +96,9 @@ Units::Units( const std::string& name, const std::string& abbr, const Units::Typ
 _name  ( name ),
 _abbr  ( abbr ),
 _type  ( type ),
-_toBase( toBase )
+_toBase( toBase ),
+_distance(0L),
+_time(0L)
 {
     //nop
 }
@@ -93,6 +107,7 @@ Units::Units( const std::string& name, const std::string& abbr, const Units& dis
 _name    ( name ),
 _abbr    ( abbr ),
 _type    ( TYPE_SPEED ),
+_toBase  ( 1.0 ),
 _distance( &distance ),
 _time    ( &time )
 {
@@ -214,3 +229,50 @@ const Units Units::DATA_MILES_PER_HOUR  ( "data miles per hour",     "dm/h", Uni
 const Units Units::KNOTS                ( "nautical miles per hour", "kts",  Units::NAUTICAL_MILES, Units::HOURS );
 
 const Units Units::PIXELS               ( "pixels", "px", Units::TYPE_SCREEN_SIZE, 1.0 );
+
+
+
+int
+Units::unitTest()
+{
+    double value;
+    Units  units;
+
+    // test parsing scientific notation
+    {
+        Units::parse( "123e-003m", value, units, Units::MILES);
+        if ( value != 123e-003 || units != Units::METERS )
+            return 101;
+
+        Units::parse( "123e+003m", value, units, Units::MILES );
+        if ( value != 123e+003 || units != Units::METERS )
+            return 102;
+
+        Units::parse( "123E-003m", value, units, Units::MILES );
+        if ( value != 123E-003 || units != Units::METERS )
+            return 103;
+
+        Units::parse( "123E+003m", value, units, Units::MILES );
+        if ( value != 123E+003 || units != Units::METERS )
+            return 104;
+    }
+
+    // normal parsing
+    {
+        Units::parse( "123m", value, units, Units::MILES );
+        if ( value != 123 || units != Units::METERS )
+            return 201;
+        
+        Units::parse( "123km", value, units, Units::MILES );
+        if ( value != 123 || units != Units::KILOMETERS )
+            return 202;
+        
+        Units::parse( "1.2rad", value, units, Units::DEGREES );
+        if ( value != 1.2 || units != Units::RADIANS )
+            return 203;
+    }
+
+    // add tests as needed
+
+    return 0;
+}
diff --git a/src/osgEarth/Utils b/src/osgEarth/Utils
index 188e255..ed7ee72 100644
--- a/src/osgEarth/Utils
+++ b/src/osgEarth/Utils
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
@@ -174,6 +174,11 @@ namespace osgEarth
         osg::ref_ptr<T> _prototype;
     };
 
+    struct OSGEARTH_EXPORT RenderBinUtils
+    {
+        static unsigned getTotalNumRenderLeaves(osgUtil::RenderBin* bin);
+    };
+
     /**
      * Shim to apply vertex cache optimizations to geometry when it's legal.
      * This is really only here to work around an OSG bug in the VertexAccessOrder
diff --git a/src/osgEarth/Utils.cpp b/src/osgEarth/Utils.cpp
index 579d5b3..eb3582c 100644
--- a/src/osgEarth/Utils.cpp
+++ b/src/osgEarth/Utils.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -45,7 +45,8 @@ void osgEarth::removeEventHandler(osgViewer::View* view, osgGA::GUIEventHandler*
 PixelAutoTransform::PixelAutoTransform() :
 osg::AutoTransform         (),
 _rotateInScreenSpace       ( false ),
-_screenSpaceRotationRadians( 0.0 )
+_screenSpaceRotationRadians( 0.0 ),
+_dirty( true )
 {
     // deactivate culling for the first traversal. We will reactivate it later.
     setCullingActive( false );
@@ -56,11 +57,16 @@ _screenSpaceRotationRadians( 0.0 )
 void
 PixelAutoTransform::accept( osg::NodeVisitor& nv )
 {
+    // optimization - don't bother with mathing if the node is hidden.
+    // (this occurs in Node::accept, which we override here)
+    if ( !nv.validNodeMask(*this) )
+        return;
+
     if ( nv.getVisitorType() == osg::NodeVisitor::CULL_VISITOR )
     {
         // re-activate culling now that the first cull traversal has taken place.
         this->setCullingActive( true );
-        osgUtil::CullVisitor* cv = Culling::asCullVisitor(nv);
+        osgUtil::CullVisitor* cv = dynamic_cast<osgUtil::CullVisitor*>(&nv);
         if ( cv )
         {
             osg::Viewport::value_type width  = _previousWidth;
@@ -449,20 +455,24 @@ GeometryValidator::apply(osg::Geometry& geom)
     for(unsigned i=0; i<arrays.size(); ++i)
     {
         osg::Array* a = arrays[i].get();
-        if ( a == NULL )
-        {
-            OE_NOTICE << LC << "Found a NULL array\n";
-        }
-        else if ( a->getBinding() == a->BIND_OVERALL && a->getNumElements() != 1 )
+        if ( a )
         {
-            OE_NOTICE << LC << "Found an array with BIND_OVERALL and size <> 1\n";
+            if ( a->getBinding() == a->BIND_OVERALL && a->getNumElements() != 1 )
+            {
+                OE_NOTICE << LC << "Found an array with BIND_OVERALL and size <> 1\n";
+            }
+            else if ( a->getBinding() == a->BIND_PER_VERTEX && a->getNumElements() != numVerts )
+            {
+                OE_NOTICE << LC << "Found BIND_PER_VERTEX with wrong number of elements (expecting " << numVerts << "; found " << a->getNumElements() << ")\n";
+            }
+
+            _vbos.insert( a->getVertexBufferObject() );
         }
-        else if ( a->getBinding() == a->BIND_PER_VERTEX && a->getNumElements() != numVerts )
+        else
         {
-            OE_NOTICE << LC << "Found BIND_PER_VERTEX with wrong number of elements (expecting " << numVerts << "; found " << a->getNumElements() << ")\n";
+            OE_NOTICE << LC << "Found a NULL array\n";
         }
 
-        _vbos.insert( a->getVertexBufferObject() );
     }
 
     if ( _vbos.size() != 1 )
@@ -614,3 +624,36 @@ AllocateAndMergeBufferObjectsVisitor::apply(osg::Geode& geode)
     }
     traverse(geode);
 }
+
+
+//------------------------------------------------------------------------
+
+namespace
+{
+    unsigned getTotalNumRenderLeavesInStateGraph(const osgUtil::StateGraph* sg)
+    {
+        unsigned count = sg->_leaves.size();
+        for(osgUtil::StateGraph::ChildList::const_iterator i = sg->_children.begin(); i != sg->_children.end(); ++i)
+            count += getTotalNumRenderLeavesInStateGraph( i->second.get() );
+        return count;
+    }
+}
+
+unsigned
+RenderBinUtils::getTotalNumRenderLeaves(osgUtil::RenderBin* bin)
+{
+    if ( !bin ) return 0u;
+    unsigned count = bin->getRenderLeafList().size();
+
+    for(osgUtil::RenderBin::StateGraphList::const_iterator i = bin->getStateGraphList().begin(); i != bin->getStateGraphList().end(); ++i)
+    {
+        count += getTotalNumRenderLeavesInStateGraph( *i );
+    }
+
+    for(osgUtil::RenderBin::RenderBinList::const_iterator i = bin->getRenderBinList().begin(); i != bin->getRenderBinList().end(); ++i)
+    {
+        count += getTotalNumRenderLeaves( i->second.get() );
+    }
+
+    return count;
+}
diff --git a/src/osgEarth/Version b/src/osgEarth/Version
index 3fa7278..f70e95c 100644
--- a/src/osgEarth/Version
+++ b/src/osgEarth/Version
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
@@ -28,10 +28,11 @@
 extern "C" {
 
 #define OSGEARTH_MAJOR_VERSION    2
-#define OSGEARTH_MINOR_VERSION    7
+#define OSGEARTH_MINOR_VERSION    8
 #define OSGEARTH_PATCH_VERSION    0
 #define OSGEARTH_SOVERSION        0
-#define OSGEARTH_RC_VERSION       0
+#define OSGEARTH_RC_VERSION       1
+#define OSGEARTH_DEVEL_VERSION    0     // 0 = release; >0 = interim devel version
 
 /* Convenience macro that can be used to decide whether a feature is present or not i.e.
  * #if OSGEARTH_MIN_VERSION_REQUIRED(1,4,0)
diff --git a/src/osgEarth/Version.cpp b/src/osgEarth/Version.cpp
index 5aa8f46..be752aa 100644
--- a/src/osgEarth/Version.cpp
+++ b/src/osgEarth/Version.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -28,6 +28,12 @@
 #    define GET_SHA ""
 #endif
 
+#ifdef OSGEARTH_DEVEL_VERSION
+#    define isDevelopmentVersion " DEVELOPMENT "
+#else
+#    define isDevelopmentVersion " "
+#endif
+
 extern "C" {
 
 const char* osgEarthGetVersion()
@@ -38,19 +44,21 @@ const char* osgEarthGetVersion()
     {
         if (OSGEARTH_RC_VERSION == 0 )
         {
-            sprintf(osgearth_version,"%d.%d.%d (%s)",
+            sprintf(osgearth_version,"%d.%d.%d%s(%s)",
                 OSGEARTH_MAJOR_VERSION,
                 OSGEARTH_MINOR_VERSION,
                 OSGEARTH_PATCH_VERSION,
+                isDevelopmentVersion,
                 GET_SHA );
         }
         else
         {
-            sprintf(osgearth_version,"%d.%d.%d RC%d (%s)",
+            sprintf(osgearth_version,"%d.%d.%d RC%d%s(%s)",
                 OSGEARTH_MAJOR_VERSION,
                 OSGEARTH_MINOR_VERSION,
                 OSGEARTH_PATCH_VERSION,
                 OSGEARTH_RC_VERSION,
+                isDevelopmentVersion,
                 GET_SHA );
         }
 
diff --git a/src/osgEarth/VerticalDatum b/src/osgEarth/VerticalDatum
index a4c7cb5..4fd7de0 100644
--- a/src/osgEarth/VerticalDatum
+++ b/src/osgEarth/VerticalDatum
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarth/VerticalDatum.cpp b/src/osgEarth/VerticalDatum.cpp
index 835d013..377a8e1 100644
--- a/src/osgEarth/VerticalDatum.cpp
+++ b/src/osgEarth/VerticalDatum.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -142,8 +142,8 @@ VerticalDatum::transform(const VerticalDatum* from,
     osg::Vec3d sw(extent.west(), extent.south(), 0.0);
     osg::Vec3d ne(extent.east(), extent.north(), 0.0);
     
-    double xstep = abs(extent.east() - extent.west()) / double(cols-1);
-    double ystep = abs(extent.north() - extent.south()) / double(rows-1);
+    double xstep = std::abs(extent.east() - extent.west()) / double(cols-1);
+    double ystep = std::abs(extent.north() - extent.south()) / double(rows-1);
 
     if ( !extent.getSRS()->isGeographic() )
     {
diff --git a/src/osgEarth/Viewpoint b/src/osgEarth/Viewpoint
index 2320c23..0cf065a 100644
--- a/src/osgEarth/Viewpoint
+++ b/src/osgEarth/Viewpoint
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -125,9 +125,6 @@ namespace osgEarth
         /** SRS is WGS84, angles are in degrees, range is in meters. */
 
         /** @deprecated */
-        Viewpoint(double lon, double lat, double heading, double pitch, double range);
-
-        /** @deprecated */
         Viewpoint(const char* name, double lon, double lat, double z, double heading, double pitch, double range);
         
         /** @deprecated */
diff --git a/src/osgEarth/Viewpoint.cpp b/src/osgEarth/Viewpoint.cpp
index 2672ba6..48617e9 100644
--- a/src/osgEarth/Viewpoint.cpp
+++ b/src/osgEarth/Viewpoint.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarth/VirtualProgram b/src/osgEarth/VirtualProgram
index 296c928..797face 100644
--- a/src/osgEarth/VirtualProgram
+++ b/src/osgEarth/VirtualProgram
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
@@ -34,13 +34,17 @@
 #include <string>
 #include <map>
 
-#ifdef OSG_GLES2_AVAILABLE
+#if defined(OSG_GLES2_AVAILABLE)
 #    define GLSL_VERSION                 100
 #    define GLSL_VERSION_STR             "100"
 #    define GLSL_DEFAULT_PRECISION_FLOAT "precision highp float;"
+#elif defined(OSG_GL3_AVAILABLE)
+#    define GLSL_VERSION                 330
+#    define GLSL_VERSION_STR             "330"
+#    define GLSL_DEFAULT_PRECISION_FLOAT ""
 #else
-#    define GLSL_VERSION                 120
-#    define GLSL_VERSION_STR             "120" 
+#    define GLSL_VERSION                 330
+#    define GLSL_VERSION_STR             "330 compatibility" 
 #    define GLSL_DEFAULT_PRECISION_FLOAT ""
 #endif
 
@@ -52,23 +56,35 @@ namespace osgEarth
         enum FunctionLocation
         {
             // vertex is in model space (equivalent to gl_Vertex).
-            LOCATION_VERTEX_MODEL = 0,
+            LOCATION_VERTEX_MODEL,
 
             // vertex is in view(aka eye) coordinates, with the camera at 0,0,0 
             // looking down the -Z axis.
-            LOCATION_VERTEX_VIEW = 1,
+            LOCATION_VERTEX_VIEW,
 
             // vertex is in post-perspective coordinates; [-w..w] along each axis
-            LOCATION_VERTEX_CLIP = 2,
+            LOCATION_VERTEX_CLIP,
+
+            // tessellation control shader; model space
+            LOCATION_TESS_CONTROL,
+
+            // tessellation evalulation shader; model space
+            LOCATION_TESS_EVALUATION,
+
+            // geometry shader; inputs are in model space.
+            LOCATION_GEOMETRY,
 
             // fragment is being colored.
-            LOCATION_FRAGMENT_COLORING = 3,
+            LOCATION_FRAGMENT_COLORING,
 
             // fragment is being lit.
-            LOCATION_FRAGMENT_LIGHTING = 4,
+            LOCATION_FRAGMENT_LIGHTING,
 
             // fragment output is being assigned.
-            LOCATION_FRAGMENT_OUTPUT = 5
+            LOCATION_FRAGMENT_OUTPUT,
+
+            // not defined.
+            LOCATION_UNDEFINED
         };
 
         /**
@@ -104,10 +120,94 @@ namespace osgEarth
 
         // user function sets, categorized by function location.
         typedef std::map<FunctionLocation, OrderedFunctionMap> FunctionLocationMap;
+
+        // Mask values that represents which stages a composed shader contains.
+        enum StageMaskValues
+        {
+            STAGE_VERTEX          = 1 << 0,
+            STAGE_TESSCONTROL     = 1 << 1,
+            STAGE_TESSEVALUATION  = 1 << 2,
+            STAGE_GEOMETRY        = 1 << 3,
+            STAGE_FRAGMENT        = 1 << 4,
+            STAGE_COMPUTE         = 1 << 5
+        };
+        typedef unsigned StageMask;
     }
 
 
     /**
+     * A Shader that can compile into different stages of the program pipeline
+     * depending on which stages are in use. For example, you may designate a
+     * VP component to run in the "VERTEX_CLIP" location. But if a geometry shader
+     * is present, this function must be moved to the end of the GEOMETRY stage
+     * instead. PolyShader supports this. It also preserves the original shader
+     * source in case someone wants to access it via VirtualProgram::getShaders
+     * (for example, to call VP components from an external shader program).
+     */
+    class OSGEARTH_EXPORT PolyShader : public osg::Referenced
+    {
+    public:
+        /** Construct a polyshader */
+        PolyShader();
+
+        /** Construct a polyshader */
+        PolyShader(osg::Shader* shader);
+
+        /** Name of the polyshader */
+        void setName(const std::string& name) { _name = name; }
+        const std::string& getName() const { return _name; }
+
+        /** Nominal stage at which this shader would run */
+        void setLocation(ShaderComp::FunctionLocation loc);
+        ShaderComp::FunctionLocation getLocation() const { return _location; }
+
+        /** Shader source code (unprocessed) */
+        void setShaderSource(const std::string& source);
+        const std::string& getShaderSource() const { return _source; }
+
+        /** Given a mask of all available stages, return the shader that will run
+            this polyshader in the appropriate stage. */
+        osg::Shader* getShader(ShaderComp::StageMask mask) const;
+
+        /** The shader in its named stage. */
+        osg::Shader* getNominalShader() const { return _nominalShader.get(); }
+
+        /** Generates the shaders. */
+        void prepare();
+
+        /** Called from the draw context to resize shader buffers as necessary (OSG) */
+        virtual void resizeGLObjectBuffers(unsigned maxSize);
+
+
+    protected:
+        virtual ~PolyShader() { }
+
+        std::string                  _name;
+        std::string                  _source;
+        ShaderComp::FunctionLocation _location;
+
+        // Originally specified stage for this shader
+        osg::Shader::Type            _nominalType;
+
+        // The shader built for the nominal program stage (nominalType)
+        osg::ref_ptr<osg::Shader>    _nominalShader;
+
+        // Same shader, but set up for injection into a different stage
+        osg::ref_ptr<osg::Shader>    _geomShader;
+        osg::ref_ptr<osg::Shader>    _tessevalShader;
+
+        // shader source before running thru the preprocessor. Keep this around so that
+        // someone can call VirtualProgram::getShaders and have access to code that has
+        // not been set up for ShaderFactory.
+        //std::string                  _originalSource;
+
+        bool                         _dirty;
+    };
+
+    typedef std::vector< osg::ref_ptr<PolyShader> > ProgramKey;
+
+
+    /**
      * VirtualProgram enables GLSL shader composition within osgEarth. It automatically
      * assembles shader functions into a full shader program at run time. You can add
      * or remove functions (injection points) at any time.
@@ -195,6 +295,7 @@ namespace osgEarth
          * the normal operation. You can set this to "false" to "reset" the VP.
          */
         void setInheritShaders( bool value );
+        bool getInheritShaders() const { return _inherit; }
 
     public: 
         /**
@@ -228,7 +329,7 @@ namespace osgEarth
         /**
          * Gets a shader by its ID.
          */
-        osg::Shader* getShader( const std::string& shaderID ) const;
+        PolyShader* getPolyShader( const std::string& shaderID ) const;
 
         /** 
          * Adds a shader to this VP's shader table.
@@ -273,6 +374,10 @@ namespace osgEarth
         /** Sets whether the accept callbacks vary per frame */
         void setAcceptCallbacksVaryPerFrame(bool acceptCallbacksVaryPerFrame);
 
+        /** Inheritance mask */
+        void setMask(unsigned mask) { _mask = mask; }
+        unsigned getMask() const { return _mask; }
+
     public: // StateAttribute
         virtual void compileGLObjects(osg::State& state) const;
         virtual void resizeGLObjectBuffers(unsigned maxSize);
@@ -290,7 +395,7 @@ namespace osgEarth
         {
             ShaderEntry();
             bool accept(const osg::State& state) const;
-            osg::ref_ptr<osg::Shader>                _shader;
+            osg::ref_ptr<PolyShader>                 _shader;
             osg::StateAttribute::OverrideValue       _overrideValue;
             osg::ref_ptr<ShaderComp::AcceptCallback> _accept;
             bool operator < (const ShaderEntry& rhs) const;
@@ -308,7 +413,7 @@ namespace osgEarth
         typedef std::pair< std::string, std::string > AttribAlias;
         typedef std::vector< AttribAlias >            AttribAliasVector;
 
-        typedef osgEarth::fast_map< ShaderVector, ProgramEntry > ProgramMap;
+        typedef osgEarth::fast_map< ProgramKey, ProgramEntry > ProgramMap;
         typedef std::pair< const osg::StateAttribute*, osg::StateAttribute::OverrideValue > AttributePair;
         typedef std::vector< AttributePair > AttrStack;
 
@@ -316,12 +421,23 @@ namespace osgEarth
         /**
          * Populates the output collection with all the osg::Shader objects that
          * are applicable for the given State.
+         * Returns the size of the output collection.
          */
-        static void getShaders(
+        static int getShaders(
+            const osg::State&                         state,
+            std::vector<osg::ref_ptr<osg::Shader> >&  output);
+        
+        /**
+         * Populates the output collection with all the PolyShaders that are applicable
+         * for the given state. Information about the stage mask is not returned (TODO?)
+         * Returns the size of the output collection.
+         */
+        static int getPolyShaders(
             const osg::State&                        state,
-            std::vector<osg::ref_ptr<osg::Shader> >& output);
+            std::vector<osg::ref_ptr<PolyShader> >&  output);
+
+    public: // INTERNAL USE ONLY
 
-    protected:
         // thread-safe functions map getter
         void getFunctions( ShaderComp::FunctionLocationMap& out ) const;
 
@@ -331,19 +447,24 @@ namespace osgEarth
         // thread-safe shader accumulator
         void addShadersToAccumulationMap(VirtualProgram::ShaderMap& accumMap, const osg::State& state) const;
 
-    protected:
+    protected: // serializable members
+
         // holds "template" data that should be installed in every auto-generated
         // Program, like uniform buffer bindings, etc.
         osg::ref_ptr<osg::Program> _template;
 
         unsigned int       _mask;
         AttribBindingList  _attribBindingList;
-        AttribAliasMap     _attribAliases;
 
         // holds the injection points the user has added to this VP.
         // _dataModelMutex protects access to this member.
         ShaderComp::FunctionLocationMap _functions;
 
+        // whether this VP inherits its state
+        bool _inherit;
+
+    protected: // non-serializable members
+
         // holds a map of each named shader installed in this VP.
         // _dataModelMutex protects access to this member.
         ShaderMap _shaderMap;
@@ -352,7 +473,7 @@ namespace osgEarth
         struct ApplyVars
         {
             ShaderMap         accumShaderMap;
-            ShaderVector      keyVector;
+            ProgramKey        programKey;
             AttribBindingList accumAttribBindings;
             AttribAliasMap    accumAttribAliases;
         };
@@ -368,15 +489,12 @@ namespace osgEarth
         mutable Threading::Mutex _programCacheMutex;
 
         mutable optional<bool> _active;
-        bool _inherit;
         bool _inheritSet;
 
         bool _logShaders;
         std::string _logPath;
 
-        // whether to use the "attribute stack memory" feature. default = true.
-        // see below.
-        bool _useStackMemory;
+        AttribAliasMap _attribAliases;
 
         bool _acceptCallbacksVaryPerFrame;
 
@@ -415,7 +533,7 @@ namespace osgEarth
             bool&              acceptCallbacksPresent);
         
         bool readProgramCache(
-            const ShaderVector& vec,
+            const ProgramKey& key,
             unsigned frameNumber,
             osg::ref_ptr<osg::Program>& program);
 
diff --git a/src/osgEarth/VirtualProgram.cpp b/src/osgEarth/VirtualProgram.cpp
index 225c36f..d137f4a 100644
--- a/src/osgEarth/VirtualProgram.cpp
+++ b/src/osgEarth/VirtualProgram.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -136,7 +136,8 @@ namespace
         }
         std::string r;
         r = buf.str();
-        return trim(r);
+        trim2(r);
+        return r;
     }
 
 
@@ -181,14 +182,6 @@ namespace
                     header = line;
                 }
 
-                else if ( tokens[0] == "#pragma")
-                {
-                    // Discards all pragmas, since the double-quotes in them are illegal in at least
-                    // GLSL ES compiler (on Android). We should consider doing this for all GLSL
-                    // since technically quoting characters are not part of the GLSL grammar at all.
-                    continue;
-                }
-
                 else
                 {
                     body << (*line_iter) << "\n";
@@ -265,8 +258,29 @@ namespace
         const osg::Program::UniformBlockBindingList& ubl = templateProgram->getUniformBlockBindingList();
         for( osg::Program::UniformBlockBindingList::const_iterator i = ubl.begin(); i != ubl.end(); ++i )
             program->addBindUniformBlock( i->first, i->second );
+
+        // dont' need unless we're using shader4 ext??
+        program->setParameter( GL_GEOMETRY_VERTICES_OUT_EXT, templateProgram->getParameter(GL_GEOMETRY_VERTICES_OUT_EXT) );
+        program->setParameter( GL_GEOMETRY_INPUT_TYPE_EXT,   templateProgram->getParameter(GL_GEOMETRY_INPUT_TYPE_EXT) );
+        program->setParameter( GL_GEOMETRY_OUTPUT_TYPE_EXT,  templateProgram->getParameter(GL_GEOMETRY_OUTPUT_TYPE_EXT) );
     }
 
+    struct SortByType {
+        bool operator()(osg::Shader* lhs, osg::Shader* rhs) {
+            return (int)lhs->getType() < (int)rhs->getType();
+        }
+    };
+
+    bool shaderInStageMask(osg::Shader* shader, const ShaderComp::StageMask& mask)
+    {
+        if ( shader->getType() == shader->VERTEX && (mask & STAGE_VERTEX) ) return true;
+        if ( shader->getType() == shader->GEOMETRY && (mask & STAGE_GEOMETRY) ) return true;
+        if ( shader->getType() == shader->TESSCONTROL && (mask & STAGE_TESSCONTROL) ) return true;
+        if ( shader->getType() == shader->TESSEVALUATION && (mask & STAGE_TESSEVALUATION) ) return true;
+        if ( shader->getType() == shader->FRAGMENT && (mask & STAGE_FRAGMENT) ) return true;
+        if ( shader->getType() == shader->COMPUTE && (mask & STAGE_COMPUTE) ) return true;
+        return false;
+    }
 
     /**
     * Populates the specified Program with passed-in shaders.
@@ -274,7 +288,8 @@ namespace
     void addShadersToProgram(const VirtualProgram::ShaderVector&      shaders, 
                              const VirtualProgram::AttribBindingList& attribBindings,
                              const VirtualProgram::AttribAliasMap&    attribAliases,
-                             osg::Program*                            program )
+                             osg::Program*                            program,
+                             ShaderComp::StageMask                    stages)
     {
 #ifdef USE_ATTRIB_ALIASES
         // apply any vertex attribute aliases. But first, sort them from longest to shortest 
@@ -306,13 +321,16 @@ namespace
             for( VirtualProgram::ShaderVector::const_iterator i = shaders.begin(); i != shaders.end(); ++i )
             {
                 osg::Shader* s = i->get();
-                if ( s->getType() == osg::Shader::VERTEX )
-                {
-                    parseShaderForMerging( s->getShaderSource(), vertVersion, vertHeaders, vertBody );
-                }
-                else if ( s->getType() == osg::Shader::FRAGMENT )
+                if ( shaderInStageMask(s, stages) )
                 {
-                    parseShaderForMerging( s->getShaderSource(), fragVersion, fragHeaders, fragBody );
+                    if ( s->getType() == osg::Shader::VERTEX )
+                    {
+                        parseShaderForMerging( s->getShaderSource(), vertVersion, vertHeaders, vertBody );
+                    }
+                    else if ( s->getType() == osg::Shader::FRAGMENT )
+                    {
+                        parseShaderForMerging( s->getShaderSource(), fragVersion, fragHeaders, fragBody );
+                    }
                 }
             }
 
@@ -337,7 +355,7 @@ namespace
             fragShaderBuf << fragBodyText << "\n";
             fragBodyText = fragShaderBuf.str();
 
-            // add them to the program.
+            // add them to the program.            
             program->addShader( new osg::Shader(osg::Shader::VERTEX, vertBodyText) );
             program->addShader( new osg::Shader(osg::Shader::FRAGMENT, fragBodyText) );
 
@@ -350,14 +368,34 @@ namespace
         }
         else
         {
-            for( VirtualProgram::ShaderVector::const_iterator i = shaders.begin(); i != shaders.end(); ++i )
+            if ( !s_dumpShaders )
             {
-                program->addShader( i->get() );
-                if ( s_dumpShaders )
+                for( VirtualProgram::ShaderVector::const_iterator i = shaders.begin(); i != shaders.end(); ++i )
                 {
-                    OE_NOTIFY(osg::NOTICE,"")
-                        << "----------\n"
-                        << i->get()->getShaderSource() << std::endl;
+                    if ( shaderInStageMask(i->get(), stages) )
+                    {
+                        program->addShader( i->get() );
+                    }
+                }
+            }
+
+            else
+            {
+                VirtualProgram::ShaderVector copy(shaders);
+                std::sort(copy.begin(), copy.end(), SortByType());
+
+                int c = 1;
+
+                for( VirtualProgram::ShaderVector::const_iterator i = copy.begin(); i != copy.end(); ++i )
+                {
+                    if ( shaderInStageMask(i->get(), stages) )
+                    {
+                        program->addShader( i->get() );
+
+                        OE_NOTIFY(osg::NOTICE,"")
+                            << "--- [ " << (c++) << "/" << shaders.size() << " " << i->get()->getTypename() << " ] ------------------\n\n"
+                            << i->get()->getShaderSource() << std::endl;
+                    }
                 }
             }
         }
@@ -381,13 +419,13 @@ namespace
                                VirtualProgram::AttribBindingList&  accumAttribBindings,
                                VirtualProgram::AttribAliasMap&     accumAttribAliases,
                                osg::Program*                       templateProgram,
-                               VirtualProgram::ShaderVector&       outputKeyVector)
+                               ProgramKey&                         outputKey)
     {
 
 #ifdef DEBUG_ACCUMULATION
 
         // test dump .. function map and shader map should always include identical data.
-        OE_INFO << LC << "====PROGRAM: " << programName << "\n";
+        OE_INFO << LC << "===PROGRAM: " << programName << "\n";
 
         // debug:
         OE_INFO << LC << "====FUNCTIONS:\n";
@@ -420,33 +458,45 @@ namespace
 #endif
 
         // create new MAINs for this function stack.
-        osg::Shader* vertMain = Registry::shaderFactory()->createVertexShaderMain( accumFunctions );
-        osg::Shader* fragMain = Registry::shaderFactory()->createFragmentShaderMain( accumFunctions );
+        VirtualProgram::ShaderVector mains;
+        ShaderComp::StageMask stages = Registry::shaderFactory()->createMains( accumFunctions, accumShaderMap, mains );
 
         // build a new "key vector" now that we've changed the shader map.
         // we call is a key vector because it uniquely identifies this shader program
         // based on its accumlated function set.
         for( VirtualProgram::ShaderMap::iterator i = accumShaderMap.begin(); i != accumShaderMap.end(); ++i )
         {
-            outputKeyVector.push_back( i->data()._shader.get() );
+            outputKey.push_back( i->data()._shader.get() );
         }
 
         // finally, add the mains (AFTER building the key vector .. we don't want or
         // need to mains in the key vector since they are completely derived from the
         // other elements of the key vector.)
-        VirtualProgram::ShaderVector buildVector( outputKeyVector );
-        buildVector.push_back( vertMain );
-        buildVector.push_back( fragMain );
+
+        VirtualProgram::ShaderVector buildVector;
+        buildVector.reserve( accumShaderMap.size() + mains.size() );
+
+        for(ProgramKey::iterator i = outputKey.begin(); i != outputKey.end(); ++i)
+            buildVector.push_back( i->get()->getShader(stages) );
+
+        buildVector.insert( buildVector.end(), mains.begin(), mains.end() );
 
         if ( s_dumpShaders )
         {
-            OE_NOTICE << LC << "\nPROGRAM: " << programName << " =============================\n" << std::endl;
+            if ( !programName.empty() )
+            {
+                OE_NOTICE << LC << "\n\n=== [ Program \"" << programName << "\" ] =============================\n\n" << std::endl;
+            }
+            else
+            {
+                OE_NOTICE << LC << "\n\n=== [ Program (unnamed) ] =============================\n\n" << std::endl;
+            }
         }
 
         // Create the new program.
         osg::Program* program = new osg::Program();
         program->setName( programName );
-        addShadersToProgram( buildVector, accumAttribBindings, accumAttribAliases, program );
+        addShadersToProgram( buildVector, accumAttribBindings, accumAttribAliases, program, stages );
         addTemplateDataToProgram( templateProgram, program );
 
         return program;
@@ -532,7 +582,8 @@ VirtualProgram::ShaderEntry::accept(const osg::State& state) const
 bool
 VirtualProgram::ShaderEntry::operator < (const VirtualProgram::ShaderEntry& rhs) const
 {
-    if ( _shader->compare(*rhs._shader.get()) < 0 ) return true;
+    if ( _shader->getShaderSource().compare(rhs._shader->getShaderSource()) < 0 ) return true;
+    //if ( _shader->compare(*rhs._shader.get()) < 0 ) return true;
     if ( _overrideValue < rhs._overrideValue ) return true;
     if ( _accept.valid() && !rhs._accept.valid() ) return true;
     return false;
@@ -652,7 +703,8 @@ _inherit           ( rhs._inherit ),
 _inheritSet        ( rhs._inheritSet ),
 _logShaders        ( rhs._logShaders ),
 _logPath           ( rhs._logPath ),
-_template          ( osg::clone(rhs._template.get()) )
+_template          ( osg::clone(rhs._template.get()) ),
+_acceptCallbacksVaryPerFrame( rhs._acceptCallbacksVaryPerFrame )
 {    
     // Attribute bindings.
     const osg::Program::AttribBindingList &abl = rhs.getAttribBindingList();
@@ -751,7 +803,11 @@ VirtualProgram::removeBindAttribLocation( const std::string& name )
 void
 VirtualProgram::compileGLObjects(osg::State& state) const
 {
-    this->apply(state);
+    // Don't do this here. compileGLObjects() runs from a pre-compilation visitor,
+    // and the state is not complete enough to create fully formed programs; so
+    // this is not only pointless but can result in shader linkage errors 
+    // (albeit harmless)
+    //this->apply(state);
 }
 
 void
@@ -764,6 +820,20 @@ VirtualProgram::resizeGLObjectBuffers(unsigned maxSize)
         i->second._program->resizeGLObjectBuffers(maxSize);
     }
 
+    // Resize shaders in the PolyShader
+    for( ShaderMap::iterator i = _shaderMap.begin(); i != _shaderMap.end(); ++i )
+    {
+        if (i->data()._shader.valid())
+        {
+            i->data()._shader->resizeGLObjectBuffers(maxSize );
+        }
+    }
+
+    // Resize the buffered_object
+    _apply.resize(maxSize);
+
+    _vpStackMemory._item.resize(maxSize);
+
     _programCacheMutex.unlock();
 }
 
@@ -783,8 +853,8 @@ VirtualProgram::releaseGLObjects(osg::State* state) const
     _programCacheMutex.unlock();
 }
 
-osg::Shader*
-VirtualProgram::getShader( const std::string& shaderID ) const
+PolyShader*
+VirtualProgram::getPolyShader(const std::string& shaderID) const
 {
     Threading::ScopedMutexLock readonly( _dataModelMutex );
     const ShaderEntry* entry = _shaderMap.find( MAKE_SHADER_ID(shaderID) );
@@ -811,9 +881,8 @@ VirtualProgram::setShader(const std::string&                 shaderID,
     // set the name to the ID:
     shader->setName( shaderID );
 
-    // pre-processes the shader's source to include GLES uniforms as necessary
-    // (no-op on non-GLES)
-    ShaderPreProcessor::run( shader );
+    PolyShader* pshader = new PolyShader( shader );
+    pshader->prepare();
 
     // lock the data model and insert the new shader.
     {
@@ -821,7 +890,7 @@ VirtualProgram::setShader(const std::string&                 shaderID,
         //Threading::ScopedWriteLock exclusive( _dataModelMutex );
 
         ShaderEntry& entry = _shaderMap[MAKE_SHADER_ID(shaderID)];
-        entry._shader        = shader;
+        entry._shader        = pshader;
         entry._overrideValue = ov;
         entry._accept        = 0L;
 
@@ -851,9 +920,8 @@ VirtualProgram::setShader(osg::Shader*                       shader,
         setInheritShaders( true );
     }
 
-    // pre-processes the shader's source to include GLES uniforms as necessary
-    // (no-op on non-GLES)
-    ShaderPreProcessor::run( shader );
+    PolyShader* pshader = new PolyShader(shader);
+    pshader->prepare();
 
     // lock the data model while changing it.
     {
@@ -862,7 +930,7 @@ VirtualProgram::setShader(osg::Shader*                       shader,
         checkSharing();
 
         ShaderEntry& entry = _shaderMap[MAKE_SHADER_ID(shader->getName())];
-        entry._shader        = shader;
+        entry._shader        = pshader;
         entry._overrideValue = ov;
         entry._accept        = 0L;
 
@@ -925,15 +993,16 @@ VirtualProgram::setFunction(const std::string&           functionName,
         function._accept = accept;
         ofm.insert( OrderedFunction(ordering, function) );
 
-        // create and add the new shader function.
-        osg::Shader::Type type = (int)location <= (int)LOCATION_VERTEX_CLIP ?
-            osg::Shader::VERTEX : osg::Shader::FRAGMENT;
+        // Remove any quotes in the shader source (illegal)
+        std::string source(shaderSource);
+        osgEarth::replaceIn(source, "\"", " ");
 
-        osg::Shader* shader = new osg::Shader(type, shaderSource);
+        // assemble the poly shader.
+        PolyShader* shader = new PolyShader();
         shader->setName( functionName );
-
-        // pre-processes the shader's source to include GLES uniforms as necessary
-        ShaderPreProcessor::run( shader );
+        shader->setLocation( location );
+        shader->setShaderSource( source );
+        shader->prepare();
 
         ShaderEntry& entry = _shaderMap[MAKE_SHADER_ID(functionName)];
         entry._shader        = shader;
@@ -1037,7 +1106,8 @@ VirtualProgram::apply( osg::State& state ) const
     }
     else if ( !_active.isSet() )
     {
-        _active = Registry::capabilities().supportsGLSL();
+        // cannot use capabilities here; it breaks serialization.
+        _active = true; //Registry::capabilities().supportsGLSL();
     }
     
     const unsigned contextID = state.getContextID();
@@ -1096,7 +1166,7 @@ VirtualProgram::apply( osg::State& state ) const
         local.accumShaderMap.clear();
         local.accumAttribBindings.clear();
         local.accumAttribAliases.clear();
-        local.keyVector.clear();
+        local.programKey.clear();
     
         // If we are inheriting, build the active shader map up to this point
         // (but not including this VP).
@@ -1143,7 +1213,7 @@ VirtualProgram::apply( osg::State& state ) const
         // bindings.)
         for( ShaderMap::iterator i = local.accumShaderMap.begin(); i != local.accumShaderMap.end(); ++i )
         {
-            local.keyVector.push_back( i->data()._shader.get() );
+            local.programKey.push_back( i->data()._shader.get() );
         }
 
         // current frame number, for shader program expiry.
@@ -1152,7 +1222,7 @@ VirtualProgram::apply( osg::State& state ) const
         // look up the program:
         {
             _programCacheMutex.lock();
-            const_cast<VirtualProgram*>(this)->readProgramCache(local.keyVector, frameNumber, program);
+            const_cast<VirtualProgram*>(this)->readProgramCache(local.programKey, frameNumber, program);
             _programCacheMutex.unlock();
         }
 
@@ -1169,10 +1239,10 @@ VirtualProgram::apply( osg::State& state ) const
                 Threading::ScopedMutexLock lock(_programCacheMutex);
 
                 // double-check: look again to negate race conditions
-                const_cast<VirtualProgram*>(this)->readProgramCache(local.keyVector, frameNumber, program);
+                const_cast<VirtualProgram*>(this)->readProgramCache(local.programKey, frameNumber, program);
                 if ( !program.valid() )
                 {
-                    local.keyVector.clear();
+                    local.programKey.clear();
 
                     //OE_NOTICE << LC << "Building new Program for VP " << getName() << std::endl;
 
@@ -1184,7 +1254,7 @@ VirtualProgram::apply( osg::State& state ) const
                         local.accumAttribBindings, 
                         local.accumAttribAliases, 
                         _template.get(),
-                        local.keyVector);
+                        local.programKey);
 
                     if ( _logShaders && program.valid() )
                     {
@@ -1218,7 +1288,7 @@ VirtualProgram::apply( osg::State& state ) const
                     Registry::programSharedRepo()->share( program );
 
                     // finally, put own new program in the cache.
-                    ProgramEntry& pe = _programCache[local.keyVector];
+                    ProgramEntry& pe = _programCache[local.programKey];
                     pe._program = program.get();
                     pe._frameLastUsed = frameNumber;
 
@@ -1341,7 +1411,8 @@ VirtualProgram::removeExpiredProgramsFromCache(osg::State& state, unsigned frame
 }
 
 bool
-VirtualProgram::readProgramCache(const ShaderVector& vec, unsigned frameNumber, osg::ref_ptr<osg::Program>& program)
+VirtualProgram::readProgramCache(const ProgramKey& vec, unsigned frameNumber, osg::ref_ptr<osg::Program>& program)
+//VirtualProgram::readProgramCache(const ShaderVector& vec, unsigned frameNumber, osg::ref_ptr<osg::Program>& program)
 {
     ProgramMap::iterator p = _programCache.find( vec );
     if ( p != _programCache.end() )
@@ -1540,8 +1611,7 @@ VirtualProgram::addShadersToAccumulationMap(VirtualProgram::ShaderMap& accumMap,
     _dataModelMutex.unlock();
 }
 
-
-void
+int
 VirtualProgram::getShaders(const osg::State&                        state,
                            std::vector<osg::ref_ptr<osg::Shader> >& output)
 {
@@ -1555,12 +1625,40 @@ VirtualProgram::getShaders(const osg::State&                        state,
 
     // pre-allocate space:
     output.reserve( shaders.size() );
+    output.clear();
+
+    // copy to output.
+    for(ShaderMap::iterator i = shaders.begin(); i != shaders.end(); ++i)
+    {
+        output.push_back( i->data()._shader->getNominalShader() );
+    }
+
+    return output.size();
+}
+
+int
+VirtualProgram::getPolyShaders(const osg::State&                       state,
+                               std::vector<osg::ref_ptr<PolyShader> >& output)
+{
+    ShaderMap         shaders;
+    AttribBindingList bindings;
+    AttribAliasMap    aliases;
+    bool              acceptCallbacksVary;
+
+    // build the collection:
+    accumulateShaders(state, ~0, shaders, bindings, aliases, acceptCallbacksVary);
+
+    // pre-allocate space:
+    output.reserve( shaders.size() );
+    output.clear();
 
     // copy to output.
     for(ShaderMap::iterator i = shaders.begin(); i != shaders.end(); ++i)
     {
         output.push_back( i->data()._shader.get() );
     }
+
+    return output.size();
 }
 
 void VirtualProgram::setShaderLogging( bool log )
@@ -1583,3 +1681,304 @@ void VirtualProgram::setAcceptCallbacksVaryPerFrame(bool acceptCallbacksVaryPerF
 {
     _acceptCallbacksVaryPerFrame = acceptCallbacksVaryPerFrame;
 }
+
+//.........................................................................
+
+PolyShader::PolyShader() :
+_dirty( true ),
+_location( ShaderComp::LOCATION_UNDEFINED ),
+_nominalType(osg::Shader::VERTEX)
+{
+    //nop
+}
+
+PolyShader::PolyShader(osg::Shader* shader) :
+_location( ShaderComp::LOCATION_UNDEFINED ),
+_nominalShader( shader ),
+_nominalType(osg::Shader::VERTEX)
+{
+    _dirty = shader != 0L;
+    if ( shader )
+    {
+        _name = shader->getName();
+
+        // extract the source before preprocessing:
+        _source = shader->getShaderSource();
+    }
+}
+
+void
+PolyShader::setShaderSource(const std::string& source)
+{
+    _source = source;
+    _dirty = true;
+}
+
+void
+PolyShader::setLocation(ShaderComp::FunctionLocation location)
+{
+    _location = location;
+    _dirty = true;
+}
+
+osg::Shader*
+PolyShader::getShader(ShaderComp::StageMask mask) const
+{
+    if (_location == ShaderComp::LOCATION_VERTEX_VIEW || _location == ShaderComp::LOCATION_VERTEX_CLIP)
+    {
+        OE_DEBUG << "getShader, mask = " << std::hex << mask << ", location = " << _location << "\n";
+        
+        // geometry stage has priority (runs last)
+        if ( mask & ShaderComp::STAGE_GEOMETRY )
+        {
+            OE_DEBUG << "Installing GS for VIEW/CLIP shader!\n";
+            return _geomShader.get();
+        }
+
+        else if ( mask & ShaderComp::STAGE_TESSEVALUATION )
+        {
+            OE_DEBUG << "Installing TES for VIEW/CLIP shader!\n";
+            return _tessevalShader.get();
+        }
+    }
+
+    return _nominalShader.get();
+}
+
+void
+PolyShader::prepare()
+{
+    if ( _dirty )
+    {
+        osg::Shader::Type nominalType;
+        switch( _location )
+        {
+        case ShaderComp::LOCATION_VERTEX_MODEL:
+        case ShaderComp::LOCATION_VERTEX_VIEW:
+        case ShaderComp::LOCATION_VERTEX_CLIP:
+            nominalType = osg::Shader::VERTEX;
+            break;
+        case ShaderComp::LOCATION_TESS_CONTROL:
+            nominalType = osg::Shader::TESSCONTROL;
+            break;
+        case ShaderComp::LOCATION_TESS_EVALUATION:
+            nominalType = osg::Shader::TESSEVALUATION;
+            break;
+        case ShaderComp::LOCATION_GEOMETRY:
+            nominalType = osg::Shader::GEOMETRY;
+            break;
+        case ShaderComp::LOCATION_FRAGMENT_COLORING:
+        case ShaderComp::LOCATION_FRAGMENT_LIGHTING:
+        case ShaderComp::LOCATION_FRAGMENT_OUTPUT:
+            nominalType = osg::Shader::FRAGMENT;
+            break;
+        default:
+            nominalType = osg::Shader::UNDEFINED;
+        }
+
+        if (nominalType != osg::Shader::UNDEFINED )
+        {
+            _nominalShader = new osg::Shader(nominalType, _source);
+            if ( !_name.empty() )
+                _nominalShader->setName(_name);
+        }
+
+        ShaderPreProcessor::run( _nominalShader.get() );
+
+        // for a VERTEX_VIEW or VERTEX_CLIP shader, these might get moved to another stage.
+        if ( _location == ShaderComp::LOCATION_VERTEX_VIEW || _location == ShaderComp::LOCATION_VERTEX_CLIP )
+        {
+            _geomShader = new osg::Shader(osg::Shader::GEOMETRY, _source);
+            if ( !_name.empty() )
+                _geomShader->setName(_name);
+            ShaderPreProcessor::run( _geomShader.get() );
+
+            _tessevalShader = new osg::Shader(osg::Shader::TESSEVALUATION, _source);
+            if ( !_name.empty() )
+                _tessevalShader->setName(_name);
+            ShaderPreProcessor::run( _tessevalShader.get() );
+        }
+    }
+    _dirty = false;
+}
+
+void PolyShader::resizeGLObjectBuffers(unsigned maxSize)
+{
+    if (_nominalShader.valid())
+    {
+        _nominalShader->resizeGLObjectBuffers(maxSize);
+    }
+
+    if (_geomShader.valid())
+    {
+        _geomShader->resizeGLObjectBuffers(maxSize);
+    }
+
+    if (_tessevalShader.valid())
+    {
+        _tessevalShader->resizeGLObjectBuffers(maxSize);
+    }
+}
+
+//.......................................................................
+// SERIALIZERS for VIRTUALPROGRAM
+
+#include <osgDB/ObjectWrapper>
+#include <osgDB/InputStream>
+#include <osgDB/OutputStream>
+
+#define PROGRAM_LIST_FUNC( PROP, TYPE, DATA ) \
+    static bool check##PROP(const osgEarth::VirtualProgram& attr) \
+    { return attr.get##TYPE().size()>0; } \
+    static bool read##PROP(osgDB::InputStream& is, osgEarth::VirtualProgram& attr) { \
+        unsigned int size = is.readSize(); is >> is.BEGIN_BRACKET; \
+        for ( unsigned int i=0; i<size; ++i ) { \
+            std::string key; unsigned int value; \
+            is >> key >> value; attr.add##DATA(key, value); \
+        } \
+        is >> is.END_BRACKET; \
+        return true; \
+    } \
+    static bool write##PROP( osgDB::OutputStream& os, const osgEarth::VirtualProgram& attr ) \
+    { \
+        const osg::Program::TYPE& plist = attr.get##TYPE(); \
+        os.writeSize(plist.size()); os << os.BEGIN_BRACKET << std::endl; \
+        for ( osg::Program::TYPE::const_iterator itr=plist.begin(); \
+              itr!=plist.end(); ++itr ) { \
+            os << itr->first << itr->second << std::endl; \
+        } \
+        os << os.END_BRACKET << std::endl; \
+        return true; \
+    }
+
+PROGRAM_LIST_FUNC( AttribBinding, AttribBindingList, BindAttribLocation );
+//PROGRAM_LIST_FUNC( FragDataBinding, FragDataBindingList, BindFragDataLocation );
+
+// functions
+static bool checkFunctions( const osgEarth::VirtualProgram& attr )
+{
+    osgEarth::ShaderComp::FunctionLocationMap functions;
+    attr.getFunctions(functions);
+
+    unsigned count = 0;
+    for (osgEarth::ShaderComp::FunctionLocationMap::const_iterator loc = functions.begin(); loc != functions.end(); ++loc)
+        count += loc->second.size();
+    return count > 0;
+}
+
+static bool readFunctions( osgDB::InputStream& is, osgEarth::VirtualProgram& attr )
+{
+    unsigned int size = is.readSize();
+    is >> is.BEGIN_BRACKET;
+
+    for ( unsigned int i=0; i<size; ++i )
+    {
+        std::string name;
+        is >> name >> is.BEGIN_BRACKET;
+        OE_DEBUG << "Name = " << name << std::endl;
+        {
+            unsigned location;
+            is >> is.PROPERTY("Location") >> location;
+            OE_DEBUG << "Location = " << location << std::endl;
+
+            float order;
+            is >> is.PROPERTY("Order") >> order;
+            OE_DEBUG << "Order = " << order << std::endl;
+
+            std::string source;
+            is >> is.PROPERTY("Source");
+            unsigned lines = is.readSize();
+            is >> is.BEGIN_BRACKET;
+            {
+                for (unsigned j=0; j<lines; ++j)
+                {
+                    std::string line;
+                    is.readWrappedString(line);
+                    source.append(line); source.append(1, '\n');
+                }
+            }
+            OE_DEBUG << "Source = " << source << std::endl;
+            is >> is.END_BRACKET;
+
+            attr.setFunction(name, source, (osgEarth::ShaderComp::FunctionLocation)location, order);
+        }
+        is >> is.END_BRACKET;
+    }
+    is >> is.END_BRACKET;
+    return true;
+}
+
+static bool writeFunctions( osgDB::OutputStream& os, const osgEarth::VirtualProgram& attr )
+{
+    osgEarth::ShaderComp::FunctionLocationMap functions;
+    attr.getFunctions(functions);
+
+    osgEarth::VirtualProgram::ShaderMap shaders;
+    attr.getShaderMap(shaders);
+    
+    unsigned count = 0;
+    for (osgEarth::ShaderComp::FunctionLocationMap::const_iterator loc = functions.begin(); loc != functions.end(); ++loc)
+        count += loc->second.size();       
+
+    os.writeSize(count);
+    os << os.BEGIN_BRACKET << std::endl;
+    {
+        for (osgEarth::ShaderComp::FunctionLocationMap::const_iterator loc = functions.begin(); loc != functions.end(); ++loc)
+        {
+            const osgEarth::ShaderComp::OrderedFunctionMap& ofm = loc->second;
+            for (osgEarth::ShaderComp::OrderedFunctionMap::const_iterator k = ofm.begin(); k != ofm.end(); ++k)
+            {
+                os << k->second._name << os.BEGIN_BRACKET << std::endl;
+                {
+                    os << os.PROPERTY("Location") << (unsigned)loc->first << std::endl;
+                    os << os.PROPERTY("Order") << k->first << std::endl;
+                    // todo: min/max range?
+
+                    osgEarth::VirtualProgram::ShaderID shaderId = MAKE_SHADER_ID(k->second._name);
+                    const osgEarth::VirtualProgram::ShaderEntry* m = shaders.find(shaderId);
+                    if (m)
+                    {                    
+                        std::vector<std::string> lines;
+                        std::istringstream iss(m->_shader->getShaderSource());
+                        std::string line;
+                        while ( std::getline(iss, line) )
+                            lines.push_back( line );
+
+                        os << os.PROPERTY("Source");
+                        os.writeSize(lines.size());
+                        os << os.BEGIN_BRACKET << std::endl;
+                        {
+                            for (std::vector<std::string>::const_iterator itr = lines.begin(); itr != lines.end(); ++itr)
+                            {
+                                os.writeWrappedString(*itr);
+                                os << std::endl;
+                            }
+                        }
+                        os << os.END_BRACKET << std::endl;
+                    }
+                }
+                os << os.END_BRACKET << std::endl;
+            }
+        }
+    }
+    os << os.END_BRACKET << std::endl;
+
+    return true;
+}
+
+namespace
+{
+    REGISTER_OBJECT_WRAPPER(
+        VirtualProgram,
+        new osgEarth::VirtualProgram,
+        osgEarth::VirtualProgram,
+        "osg::Object osg::StateAttribute osgEarth::VirtualProgram")
+    {
+        ADD_BOOL_SERIALIZER( InheritShaders, true );
+        ADD_UINT_SERIALIZER( Mask, ~0 );
+
+        ADD_USER_SERIALIZER( AttribBinding );
+        //ADD_USER_SERIALIZER( FragDataBinding );
+        ADD_USER_SERIALIZER( Functions );
+    }
+}
diff --git a/src/osgEarth/XmlUtils b/src/osgEarth/XmlUtils
index 0ae38c8..4fd1628 100644
--- a/src/osgEarth/XmlUtils
+++ b/src/osgEarth/XmlUtils
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -95,13 +95,15 @@ namespace osgEarth
 
         void addSubElement(const std::string& tag, const Properties& attrs, const std::string& text);
 
-        virtual Config getConfig() const;
+        virtual Config getConfig(const std::string& sourceURI) const;
 
     public: // XmlNode
         virtual bool isElement() const { return true; }
 
         virtual bool isText() const { return false; }
 
+        virtual bool isInclude() const { return toLower(name) == "xi:include"; }
+
     private:
         std::string name;
         XmlAttributes attrs;
diff --git a/src/osgEarth/XmlUtils.cpp b/src/osgEarth/XmlUtils.cpp
index 86e2b6f..9dff787 100644
--- a/src/osgEarth/XmlUtils.cpp
+++ b/src/osgEarth/XmlUtils.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -49,21 +49,30 @@ XmlElement::XmlElement( const std::string& _name, const XmlAttributes& _attrs )
 
 XmlElement::XmlElement( const Config& conf )
 {
-    name = conf.key();
-
-    if ( !conf.value().empty() )
+    if (!conf.externalRef().empty())
     {
-        children.push_back( new XmlText(conf.value()) );
+        attrs["href"] = conf.externalRef();
+        name = "xi:include";
     }
-
-    for( ConfigSet::const_iterator j = conf.children().begin(); j != conf.children().end(); j++ )
+    else
     {
-        //if ( j->isSimple() )
-        //{
-        //    attrs[j->key()] = j->value();
-        //}
 
-        children.push_back( new XmlElement(*j) );
+        name = conf.key();
+
+        if ( !conf.value().empty() )
+        {
+            children.push_back( new XmlText(conf.value()) );
+        }
+
+        for( ConfigSet::const_iterator j = conf.children().begin(); j != conf.children().end(); j++ )
+        {
+            //if ( j->isSimple() )
+            //{
+            //    attrs[j->key()] = j->value();
+            //}
+
+            children.push_back( new XmlElement(*j) );
+        }
     }
 }
 
@@ -232,26 +241,59 @@ XmlElement::addSubElement(const std::string& tag, const Properties& attrs, const
 }
 
 Config
-XmlElement::getConfig() const
+XmlElement::getConfig(const std::string& referrer) const
 {
-    Config conf( name );
+	if (isInclude())
+	{
+		std::string href = getAttr("href");
 
-    for( XmlAttributes::const_iterator a = attrs.begin(); a != attrs.end(); a++ )
-    {
-        conf.set( a->first, a->second );
-    }
+        if (href.empty())
+        {
+            OE_WARN << "Missing href with xi:include" << std::endl;
+            return Config();
+        }
 
-    for( XmlNodeList::const_iterator c = children.begin(); c != children.end(); c++ )
-    {
-        XmlNode* n = c->get();
-        if ( n->isElement() )
-            conf.add( static_cast<const XmlElement*>(n)->getConfig() );
-    }
+        URIContext uriContext(referrer);
+        URI uri(href, uriContext);
+        std::string fullURI = uri.full();
+        OE_INFO << "Loading href from " << fullURI << std::endl;
 
-    conf.value() = getText();
-        //else 
-        //    conf.value() = trim( static_cast<const XmlText*>(n)->getValue() );
-    return conf;
+        osg::ref_ptr< XmlDocument > doc = XmlDocument::load(fullURI);
+        if (doc && doc->getChildren().size() > 0)
+        {
+            Config conf = static_cast<XmlElement*>(doc->children.front().get())->getConfig( fullURI );
+            conf.setExternalRef( href ); //fullURI );
+            conf.setReferrer( fullURI );
+            return conf;
+        }
+        else
+        {
+            OE_WARN << "Failed to load xi:include from " << fullURI << std::endl;
+            return Config();
+        }        
+	}
+	else
+	{
+		Config conf( name );
+        conf.setReferrer( referrer );
+
+		for( XmlAttributes::const_iterator a = attrs.begin(); a != attrs.end(); a++ )
+		{
+			conf.set( a->first, a->second );
+		}
+
+		for( XmlNodeList::const_iterator c = children.begin(); c != children.end(); c++ )
+		{
+			XmlNode* n = c->get();
+			if ( n->isElement() )
+				conf.add( static_cast<const XmlElement*>(n)->getConfig(referrer) );
+		}
+
+		conf.value() = getText();
+		//else 
+		//    conf.value() = trim( static_cast<const XmlText*>(n)->getValue() );
+		return conf;
+	}
 }
 
 XmlText::XmlText( const std::string& _value )
@@ -318,7 +360,6 @@ namespace
                     attrs[name] = value;
                     attr = attr->Next();
                 }
-
                 //All the element to the stack
                 new_element = new XmlElement( tag, attrs );
                 parent->getChildren().push_back( new_element );
@@ -393,9 +434,12 @@ XmlDocument::load( const URI& uri, const osgDB::Options* dbOptions )
     if ( r.succeeded() )
     {
         std::stringstream buf( r.getString() );
-        result = load( buf );
+        URIContext context( uri.full() );
+        result = load( buf, context );
         if ( result )
+        {
             result->_sourceURI = uri;
+        }
     }
 
     return result;
@@ -441,7 +485,7 @@ XmlDocument::load( std::istream& in, const URIContext& uriContext )
 Config
 XmlDocument::getConfig() const
 {
-    Config conf = XmlElement::getConfig();
+    Config conf = XmlElement::getConfig(_sourceURI.full());
     conf.setReferrer( _sourceURI.full() );
     return conf;
 }
diff --git a/src/osgEarth/optional b/src/osgEarth/optional
index 43b86d0..009f3cf 100644
--- a/src/osgEarth/optional
+++ b/src/osgEarth/optional
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
@@ -33,7 +33,7 @@ namespace osgEarth
         optional() : _set(false), _value(T()), _defaultValue(T()) { }
         optional(T defaultValue) : _set(false), _value(defaultValue), _defaultValue(defaultValue) { }
         optional(T defaultValue, T value) : _set(true), _value(value), _defaultValue(defaultValue) { }
-        optional(const optional<T>& rhs) { (*this)=rhs; }
+        optional(const optional<T>& rhs) { operator=(rhs); }
         virtual ~optional() { }
         optional<T>& operator =(const optional<T>& rhs) { _set=rhs._set; _value=rhs._value; _defaultValue=rhs._defaultValue; return *this; }
         const T& operator =(const T& value) { _set=true; _value=value; return _value; }
@@ -48,6 +48,7 @@ namespace osgEarth
         bool isSetTo(const T& value) const { return _set && _value==value; } // differs from == in that the value must be explicity set
         bool isSet() const { return _set; }
         void unset() { _set = false; _value=_defaultValue; }
+        void clear() { unset(); }
 
         const T& get() const { return _value; }
         const T& value() const { return _value; }
diff --git a/src/osgEarth/tinyxml.h b/src/osgEarth/tinyxml.h
index 0182291..6fb396d 100644
--- a/src/osgEarth/tinyxml.h
+++ b/src/osgEarth/tinyxml.h
@@ -263,7 +263,7 @@ public:
 
 	enum
 	{
-		TIXML_NO_ERROR = 0,
+		TIXML_NoError = 0,
 		TIXML_ERROR,
 		TIXML_ERROR_OPENING_FILE,
 		TIXML_ERROR_PARSING_ELEMENT,
diff --git a/src/osgEarthAnnotation/AnnotationData b/src/osgEarthAnnotation/AnnotationData
index a168785..1ae84dd 100644
--- a/src/osgEarthAnnotation/AnnotationData
+++ b/src/osgEarthAnnotation/AnnotationData
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
@@ -23,20 +23,21 @@
 #define OSGEARTH_ANNOTATION_ANNOTATION_DATA_H 1
 
 #include <osgEarthAnnotation/Common>
-#include <osg/Referenced>
 #include <osgEarth/Viewpoint>
-#include <osgEarth/Decluttering>
+#include <osgEarth/DateTimeRange>
 
 namespace osgEarth { namespace Annotation
 {	
     using namespace osgEarth;
-
+    
     /**
-     * Stores annotation metadata/extra information that can be stored in a node's
-     * UserData container.
+     * Stores annotation metadata/extra information that can be stored
+     * in a UserData slot
+     *
+     * NOTE: This is only here to support the KML loader, and should be
+     * refactored out of here.
      */
-    class OSGEARTHANNO_EXPORT AnnotationData : public osg::Referenced,
-                                               public osgEarth::PriorityProvider
+    class OSGEARTHANNO_EXPORT AnnotationData : public osg::Referenced
     {
     public:
         /**
@@ -75,13 +76,11 @@ namespace osgEarth { namespace Annotation
             return _viewpoint;
         }
 
-    public: // PriorityProvider interface
-
         /**
-         * Priority of the item
-         */
-        void setPriority( float value ) { _priority = value; }
-        float getPriority() const { return _priority; }
+        * DateTime range of the annotation
+        */
+        void setDateTimeRange(const DateTimeRange& value) { _dateTimeRange = value; }
+        const DateTimeRange& getDateTimeRange() const { return _dateTimeRange; }
 
 
     public: // serialization
@@ -93,10 +92,11 @@ namespace osgEarth { namespace Annotation
         virtual ~AnnotationData();
 
     protected:
-        std::string _name;
-        std::string _description;
-        float       _priority;
-        Viewpoint*  _viewpoint;
+        std::string   _name;
+        std::string   _description;
+        float         _priority;
+        Viewpoint*    _viewpoint;
+        DateTimeRange _dateTimeRange;
     };
 
 } } // namespace osgEarth::Annotation
diff --git a/src/osgEarthAnnotation/AnnotationData.cpp b/src/osgEarthAnnotation/AnnotationData.cpp
index 685f85f..a28d03a 100644
--- a/src/osgEarthAnnotation/AnnotationData.cpp
+++ b/src/osgEarthAnnotation/AnnotationData.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
@@ -73,3 +73,4 @@ AnnotationData::getConfig() const
 
     return conf;
 }
+
diff --git a/src/osgEarthAnnotation/AnnotationEditing b/src/osgEarthAnnotation/AnnotationEditing
index d324089..71f3fe4 100644
--- a/src/osgEarthAnnotation/AnnotationEditing
+++ b/src/osgEarthAnnotation/AnnotationEditing
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -21,7 +21,7 @@
 #define OSGEARTHANNO_ANNOTATION_EDITING_H 1
 
 #include <osgEarthAnnotation/Common>
-#include <osgEarthAnnotation/LocalizedNode>
+#include <osgEarthAnnotation/GeoPositionNode>
 #include <osgEarthAnnotation/CircleNode>
 #include <osgEarthAnnotation/EllipseNode>
 #include <osgEarthAnnotation/RectangleNode>
@@ -41,7 +41,7 @@ namespace osgEarth { namespace Annotation
      /**
      * An editor node that allows you to move the position of LocalizedNode annotations    
      */
-    class OSGEARTHANNO_EXPORT LocalizedNodeEditor : public AnnotationEditor
+    class OSGEARTHANNO_EXPORT GeoPositionNodeEditor : public AnnotationEditor
     {
     public:
         /**
@@ -49,9 +49,9 @@ namespace osgEarth { namespace Annotation
          * @param localizedNode
          *        The LocalizedNode to edit
          */
-        LocalizedNodeEditor(LocalizedNode* localizedNode);    
+        GeoPositionNodeEditor(GeoPositionNode* localizedNode);    
         
-        virtual ~LocalizedNodeEditor();    
+        virtual ~GeoPositionNodeEditor();    
 
         virtual void updateDraggers();
 
@@ -60,11 +60,11 @@ namespace osgEarth { namespace Annotation
         void setPosition( const GeoPoint& pos );
 
     protected:
-        osg::ref_ptr< LocalizedNode > _node;
+        osg::ref_ptr< GeoPositionNode > _node;
         Dragger* _dragger;
     };
 
-    class OSGEARTHANNO_EXPORT CircleNodeEditor : public LocalizedNodeEditor
+    class OSGEARTHANNO_EXPORT CircleNodeEditor : public GeoPositionNodeEditor
     {
     public:
         /**
@@ -89,7 +89,7 @@ namespace osgEarth { namespace Annotation
         Dragger* _radiusDragger;
     };
 
-    class OSGEARTHANNO_EXPORT EllipseNodeEditor : public LocalizedNodeEditor
+    class OSGEARTHANNO_EXPORT EllipseNodeEditor : public GeoPositionNodeEditor
     {
     public:
         /**
@@ -107,7 +107,7 @@ namespace osgEarth { namespace Annotation
         Dragger* _minorDragger;
     };
 
-    class OSGEARTHANNO_EXPORT RectangleNodeEditor : public LocalizedNodeEditor
+    class OSGEARTHANNO_EXPORT RectangleNodeEditor : public GeoPositionNodeEditor
     {
     public:
         /**
diff --git a/src/osgEarthAnnotation/AnnotationEditing.cpp b/src/osgEarthAnnotation/AnnotationEditing.cpp
index bc59344..476379a 100644
--- a/src/osgEarthAnnotation/AnnotationEditing.cpp
+++ b/src/osgEarthAnnotation/AnnotationEditing.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
@@ -31,7 +31,7 @@ using namespace osgEarth::Symbology;
 class DraggerCallback : public Dragger::PositionChangedCallback
 {
 public:
-    DraggerCallback(LocalizedNode* node, LocalizedNodeEditor* editor):
+    DraggerCallback(GeoPositionNode* node, GeoPositionNodeEditor* editor):
       _node(node),
       _editor( editor )
       {          
@@ -43,8 +43,8 @@ public:
           _editor->updateDraggers();
       }
 
-      LocalizedNode* _node;
-      LocalizedNodeEditor* _editor;
+      GeoPositionNode* _node;
+      GeoPositionNodeEditor* _editor;
 };
 
 /**********************************************************************/
@@ -58,7 +58,7 @@ osg::Group()
 }
 
 /**********************************************************************/
-LocalizedNodeEditor::LocalizedNodeEditor(LocalizedNode* node):
+GeoPositionNodeEditor::GeoPositionNodeEditor(GeoPositionNode* node):
 _node( node )
 {
     _dragger  = new SphereDragger( _node->getMapNode());  
@@ -67,19 +67,19 @@ _node( node )
     updateDraggers();
 }
 
-LocalizedNodeEditor::~LocalizedNodeEditor()
+GeoPositionNodeEditor::~GeoPositionNodeEditor()
 {    
 }
 
 void
-LocalizedNodeEditor::updateDraggers()
+GeoPositionNodeEditor::updateDraggers()
 {
     GeoPoint pos = _node->getPosition();    
     _dragger->setPosition( pos, false );
 }
 
 void
-LocalizedNodeEditor::setPosition(const GeoPoint& pos)
+GeoPositionNodeEditor::setPosition(const GeoPoint& pos)
 {
     _node->setPosition( pos );
     updateDraggers();
@@ -123,7 +123,7 @@ public:
 
 
 CircleNodeEditor::CircleNodeEditor( CircleNode* node ):
-LocalizedNodeEditor( node ),
+GeoPositionNodeEditor( node ),
 _radiusDragger( 0 ),
 _bearing( osg::DegreesToRadians( 90.0 ) )
 {
@@ -150,16 +150,18 @@ void
 CircleNodeEditor::computeBearing()
 {
     _bearing = osg::DegreesToRadians( 90.0 );
+
     //Get the radius dragger's position
-    if (!_radiusDragger->getMatrix().isIdentity())
+    if ( _radiusDragger->getPosition().isValid() )
     {
         // Get the current location of the center of the circle (in lat/long)
         GeoPoint location = _node->getPosition();
         location.makeGeographic();
 
         // location of the radius dragger (in lat/long)
-        GeoPoint radiusLocation;
-        radiusLocation.fromWorld( location.getSRS(), _radiusDragger->getMatrix().getTrans() );
+        GeoPoint radiusLocation = _radiusDragger->getPosition();
+        if ( !radiusLocation.getSRS()->isGeographic() )
+            radiusLocation = radiusLocation.transform( location.getSRS() );
 
         // calculate the bearing b/w the 
         _bearing = GeoMath::bearing(
@@ -171,7 +173,7 @@ CircleNodeEditor::computeBearing()
 void
 CircleNodeEditor::updateDraggers()
 {
-    LocalizedNodeEditor::updateDraggers();
+    GeoPositionNodeEditor::updateDraggers();
     if (_radiusDragger)
     {
         const osg::EllipsoidModel* em = _node->getMapNode()->getMapSRS()->getEllipsoid();
@@ -179,7 +181,6 @@ CircleNodeEditor::updateDraggers()
         // Get the current location of the center of the circle (in lat/long, absolute Z)
         GeoPoint location = _node->getPosition();   
         location.makeGeographic();
-        //location.makeAbsolute( _node->getMapNode()->getTerrain() );
         
         //Get the radius of the circle in meters
         double r = static_cast<CircleNode*>(_node.get())->getRadius().as(Units::METERS);
@@ -256,7 +257,7 @@ public:
 
 
 EllipseNodeEditor::EllipseNodeEditor( EllipseNode* node ):
-LocalizedNodeEditor( node ),
+GeoPositionNodeEditor( node ),
 _minorDragger( 0 ),
 _majorDragger( 0 )
 {
@@ -280,7 +281,7 @@ EllipseNodeEditor::~EllipseNodeEditor()
 void
 EllipseNodeEditor::updateDraggers()
 {
-    LocalizedNodeEditor::updateDraggers();
+    GeoPositionNodeEditor::updateDraggers();
     if (_majorDragger && _minorDragger)
     {
         const osg::EllipsoidModel* em = _node->getMapNode()->getMap()->getProfile()->getSRS()->getEllipsoid();
@@ -352,7 +353,7 @@ public:
 
 
 RectangleNodeEditor::RectangleNodeEditor( RectangleNode* node ):
-LocalizedNodeEditor( node ),
+GeoPositionNodeEditor( node ),
 _llDragger( 0 ),
 _lrDragger( 0 ),
 _urDragger( 0 ),
@@ -392,7 +393,7 @@ RectangleNodeEditor::~RectangleNodeEditor()
 void
 RectangleNodeEditor::updateDraggers()
 {
-    LocalizedNodeEditor::updateDraggers();    
+    GeoPositionNodeEditor::updateDraggers();    
 
     RectangleNode* rect = static_cast<RectangleNode*>(_node.get());
     
diff --git a/src/osgEarthAnnotation/AnnotationExtension b/src/osgEarthAnnotation/AnnotationExtension
new file mode 100644
index 0000000..6ecc7ca
--- /dev/null
+++ b/src/osgEarthAnnotation/AnnotationExtension
@@ -0,0 +1,61 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+ * Copyright 2016 Pelican Mapping
+ * http://osgearth.org
+ *
+ * osgEarth is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ */
+#ifndef OSGEARTH_ANNOTATION_EXTENSION
+#define OSGEARTH_ANNOTATION_EXTENSION 1
+
+#include "Common"
+#include <osgEarth/Extension>
+#include <osgEarth/MapNode>
+
+namespace osgEarth { namespace Annotation
+{
+    using namespace osgEarth;    
+
+    /**
+     * Extension for loading the splatting effect on demand.
+     */
+    class OSGEARTHANNO_EXPORT AnnotationExtension : public Extension,
+                                                    public ExtensionInterface<MapNode>,
+                                                    public ConfigOptions
+    {
+    public:
+        META_osgEarth_Extension(AnnotationExtension);
+
+        AnnotationExtension(const ConfigOptions& options);
+
+    public: // Extension
+
+        void setDBOptions(const osgDB::Options* readOptions);
+
+        const ConfigOptions& getConfigOptions() const { return *this; }
+
+
+    public: // ExtensionInterface<MapNode>
+
+        bool connect(MapNode* mapNode);
+
+        bool disconnect(MapNode* mapNode);
+
+    private:
+        osg::ref_ptr<const osgDB::Options> _dbo;
+    };
+
+} } // namespace osgEarth::Annotations
+
+#endif // OSGEARTH_ANNOTATION_EXTENSION
diff --git a/src/osgEarthAnnotation/AnnotationExtension.cpp b/src/osgEarthAnnotation/AnnotationExtension.cpp
new file mode 100644
index 0000000..5b7be4e
--- /dev/null
+++ b/src/osgEarthAnnotation/AnnotationExtension.cpp
@@ -0,0 +1,91 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+ * Copyright 2016 Pelican Mapping
+ * http://osgearth.org
+ *
+ * osgEarth is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ */
+#include "AnnotationExtension"
+#include <osgEarthAnnotation/AnnotationRegistry>
+#include <osgEarth/Extension>
+
+#include <osgEarth/MapNode>
+#include <osgDB/FileNameUtils>
+#include <osgDB/ReaderWriter>
+
+using namespace osgEarth;
+using namespace osgEarth::Annotation;
+
+#define LC "[AnnotationExtension] "
+
+//.........................................................................
+
+
+AnnotationExtension::AnnotationExtension(const ConfigOptions& co) :
+ConfigOptions( co )
+{
+    //nop
+}
+
+void
+AnnotationExtension::setDBOptions(const osgDB::Options* dbOptions)
+{
+    _dbo = dbOptions;
+}
+
+bool
+AnnotationExtension::connect(MapNode* mapNode)
+{
+    if ( !mapNode )
+    {
+        OE_WARN << LC << "Illegal: MapNode cannot be null." << std::endl;
+        return false;
+    }
+
+    // decode the Config.
+    osg::Group* annotations = 0L;
+
+    AnnotationRegistry::instance()->create( mapNode, getConfig(), _dbo.get(), annotations );
+
+    if ( annotations )
+    {
+        if ( annotations )
+            annotations->setName("osgEarth::AnnotationExtension");
+
+        mapNode->addChild( annotations );
+    }
+
+    return true;
+}
+
+bool
+AnnotationExtension::disconnect(MapNode* mapNode)
+{
+    if ( mapNode )
+    {
+        for(unsigned i=0; i<mapNode->getNumChildren(); ++i)
+        {
+            if ( mapNode->getChild(i)->getName() == "osgEarth::AnnotationExtension")
+            {
+                mapNode->removeChild(i);
+                break;
+            }
+        }
+    }
+
+    return true;
+}
+
+REGISTER_OSGEARTH_EXTENSION(osgearth_annotations, AnnotationExtension);
+//REGISTER_OSGEARTH_EXTENSION(osgearth_annotation,  AnnotationExtension);
diff --git a/src/osgEarthAnnotation/AnnotationNode b/src/osgEarthAnnotation/AnnotationNode
index d2aab2b..800f123 100644
--- a/src/osgEarthAnnotation/AnnotationNode
+++ b/src/osgEarthAnnotation/AnnotationNode
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
@@ -23,25 +23,19 @@
 #define OSGEARTH_ANNO_ANNOTATION_NODE_H 1
 
 #include <osgEarthAnnotation/Common>
-#include <osgEarthAnnotation/AnnotationData>
-#include <osgEarthAnnotation/Decoration>
 #include <osgEarthSymbology/Style>
 #include <osgEarth/DepthOffset>
 #include <osgEarth/MapNodeObserver>
-#include <osgEarth/Terrain>
-#include <osgEarth/TileKey>
-
+#include <osgEarth/Horizon>
 
 #define META_AnnotationNode(library,name) \
-    META_Node(library,name) \
-    virtual bool accept(Decoration* ds, bool enable) { return ds->apply(*this, enable); }
+    META_Node(library,name)
 
 #define META_AnnotationNodeAbstract(library,name) \
     virtual bool isSameKindAs(const osg::Object* obj) const { return dynamic_cast<const name *>(obj)!=NULL; } \
     virtual const char* className() const { return #name; } \
     virtual const char* libraryName() const { return #library; } \
-    virtual void accept(osg::NodeVisitor& nv) { if (nv.validNodeMask(*this)) { nv.pushOntoNodePath(this); nv.apply(*this); nv.popFromNodePath(); } } \
-    virtual bool accept(Decoration* ds, bool enable) { return ds->apply(*this, enable); }
+    virtual void accept(osg::NodeVisitor& nv) { if (nv.validNodeMask(*this)) { nv.pushOntoNodePath(this); nv.apply(*this); nv.popFromNodePath(); } }
 
 // forward decs
 namespace osgEarth
@@ -65,60 +59,31 @@ namespace osgEarth { namespace Annotation
         META_AnnotationNode(osgEarthAnnotation, AnnotationNode);
 
         /**
-         * Annotation data attached to this annotation node.
-         */
-        virtual void setAnnotationData( AnnotationData* data );
-        AnnotationData* getAnnotationData() const { return _annoData.get(); }
-        AnnotationData* getOrCreateAnnotationData();
-
-        /**
          * Sets the node to "dynamic", i.e. sets up the node so that you can
          * safely change it at runtime.
          */
         virtual void setDynamic( bool value );
 
-        /** 
-         * Gets the attach point for children of this node
-         */
-        virtual osg::Group* getChildAttachPoint();
-
         /**
          * Serialized this annotation node so you can re-create it later
          */
         virtual Config getConfig() const { return Config(); }
 
+    public:
 
-    public: // decoration support
-
-        /**
-         * Installs a decoration on this annotation node.
-         */
-        void installDecoration( const std::string& name, Decoration* ds );
-
-        /**
-         * Uninstalls a decoration on this annotation node.
-         */
-        void uninstallDecoration( const std::string& name );
-
-        /**
-         * Gets the current decoration
-         */
-        const std::string& getDecoration() const;
-
-        /**
-         * Activates a named decoration that was installed previously
-         */
-        virtual void setDecoration( const std::string& name );
-
+        const std::string& getName() const { return osg::Group::getName(); }
+        
         /**
-         * Clears any decoration.
+         * Priority of the item. A negative Priority means "never occlude me".
          */
-        virtual void clearDecoration();
+        virtual void setPriority( float value );
+        float getPriority() const { return _priority; }
 
         /**
-         * Whether this annotation has the specified decoration installed.
+         * Enables or disable automatic horizon culling for geocentric maps
          */
-        bool hasDecoration( const std::string& name ) const;
+        void setHorizonCulling(bool value);
+        bool getHorizonCulling() const;
 
         /**
          * Text associated with this annotation; might be the name, might be actual text
@@ -139,44 +104,20 @@ namespace osgEarth { namespace Annotation
 
         virtual const Style& getStyle() const { return s_emptyStyle; }
 
-
     protected:
 
-        osg::ref_ptr<AnnotationData> _annoData;
-        bool                         _dynamic;
-        bool                         _autoclamp;
-        bool                         _depthAdj;
-        osg::ref_ptr<const AltitudeSymbol> _altitude;
+        bool _dynamic;
+        bool _depthAdj;
 
         DepthOffsetAdapter _doAdapter;
 
-        typedef std::map<std::string, osg::ref_ptr<Decoration> > DecorationMap;
-        DecorationMap _dsMap;
-        Decoration*   _activeDs;
-        std::string   _activeDsName;
-
-
-        bool supportsAutoClamping( const Style& style ) const;
-        
-        /**
-         * Check the altitude symbology (if present) and configure the
-         * automatic mesh clamping if necessary.
-         */
-        virtual void configureForAltitudeMode( const AltitudeMode& mode );
+        float _priority;
 
         /**
          * Apply general style information to the node
          */
-        virtual void applyStyle( const Style&);
-        virtual void applyGeneralSymbology(const Style&);
-        
-        /**
-         * Sets the node to automatically re-clamp its geometry to incoming terrain tiles
-         * as they page in (if applicable).
-         * Note: you usually don't need to call this directly; it is automatically set
-         * based on the symbology. But you can call it to override the automatic setting.
-         */
-        virtual void setCPUAutoClamping( bool value );
+        virtual void applyStyle(const Style&);
+        virtual void applyRenderSymbology(const Style&);
 
         /**
          * Whether to activate depth adjustment.
@@ -190,63 +131,27 @@ namespace osgEarth { namespace Annotation
          */
         void setLightingIfNotSet( bool lighting );
 
-        // utility funcion to make a geopoint absolute height
-        bool makeAbsolute( GeoPoint& mapPoint, osg::Node* patch =0L ) const;
-
         // hidden default ctor
-        AnnotationNode( MapNode* mapNode =0L );
+        AnnotationNode();
 
         // hidden config ctor
-        AnnotationNode( MapNode* mapNode, const Config& conf );
+        AnnotationNode(const Config& conf );
 
         // hidden copy ctor
         AnnotationNode(const AnnotationNode& rhs, const osg::CopyOp& op=osg::CopyOp::DEEP_COPY_ALL) : osg::Group(rhs, op) { }
 
-        osg::ref_ptr< TerrainCallback > _autoClampCallback;
+    protected:
+        
+        osg::ref_ptr<HorizonCullCallback> _horizonCuller;
 
     private:
             
-        osg::observer_ptr<MapNode>   _mapNode;
+        osg::observer_ptr<MapNode> _mapNode;
         static Style s_emptyStyle;
 
-
-    public: // internal methods; do not call directly
-
-        virtual void reclamp( const TileKey& key, osg::Node* tile, const Terrain* terrain ) { }
-
-        virtual ~AnnotationNode();
-    };
-
-    /**
-     * Virtual class for AnnotationNodes with the set/getPosition method
-     */
-    class PositionedAnnotationNode : public AnnotationNode
-    {
     public:
 
-        /**
-         * Sets the map position of the node.
-         * Returns true upon success.
-         */
-        virtual bool setPosition( const GeoPoint& p ) =0;
-
-        /**
-         * Gets the position (in map coordinates) of the node
-         */
-        virtual GeoPoint getPosition() const =0;
-
-    protected:
-
-        PositionedAnnotationNode()
-            : AnnotationNode() { }
-
-        PositionedAnnotationNode(MapNode* mapNode)
-            : AnnotationNode( mapNode ) { }
-
-        PositionedAnnotationNode(MapNode* mapNode, const Config& conf)
-            : AnnotationNode( mapNode, conf ) { }
-        
-        PositionedAnnotationNode(const PositionedAnnotationNode& rhs, const osg::CopyOp& op=osg::CopyOp::DEEP_COPY_ALL) : AnnotationNode(rhs, op) { }
+        virtual ~AnnotationNode();
     };
 
 } } // namespace osgEarth::Annotation
diff --git a/src/osgEarthAnnotation/AnnotationNode.cpp b/src/osgEarthAnnotation/AnnotationNode.cpp
index d5f593f..096f338 100644
--- a/src/osgEarthAnnotation/AnnotationNode.cpp
+++ b/src/osgEarthAnnotation/AnnotationNode.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
@@ -26,88 +26,42 @@
 
 #include <osgEarth/DepthOffset>
 #include <osgEarth/MapNode>
-#include <osgEarth/NodeUtils>
-#include <osgEarth/TerrainEngineNode>
 
 using namespace osgEarth;
 using namespace osgEarth::Annotation;
 
 //-------------------------------------------------------------------
 
-namespace osgEarth { namespace Annotation
-{
-    struct AutoClampCallback : public TerrainCallback
-    {
-        AutoClampCallback( AnnotationNode* annotation):
-        _annotation( annotation )
-        {
-        }
-
-        void onTileAdded( const TileKey& key, osg::Node* tile, TerrainCallbackContext& context )
-        {
-            _annotation->reclamp( key, tile, context.getTerrain() );
-        }
-
-        AnnotationNode* _annotation;
-    };
-}  }
-
-//-------------------------------------------------------------------
-
 Style AnnotationNode::s_emptyStyle;
 
 //-------------------------------------------------------------------
 
-AnnotationNode::AnnotationNode(MapNode* mapNode) :
-_mapNode    ( mapNode ),
+AnnotationNode::AnnotationNode() :
 _dynamic    ( false ),
-_autoclamp  ( false ),
 _depthAdj   ( false ),
-_activeDs   ( 0L )
+_priority   ( 0.0f )
 {
-    //Note: Cannot call setMapNode() here because it's a virtual function.
-    //      Each subclass will be separately responsible at ctor time.
-
     // always blend.
     this->getOrCreateStateSet()->setMode( GL_BLEND, osg::StateAttribute::ON );
     // always draw after the terrain.
     this->getOrCreateStateSet()->setRenderBinDetails( 1, "DepthSortedBin" );
+    
+    _horizonCuller = new HorizonCullCallback();
+    this->addCullCallback( _horizonCuller.get() );
 }
 
-AnnotationNode::AnnotationNode(MapNode* mapNode, const Config& conf) :
-_mapNode    ( mapNode ),
+AnnotationNode::AnnotationNode(const Config& conf) :
 _dynamic    ( false ),
-_autoclamp  ( false ),
 _depthAdj   ( false ),
-_activeDs   ( 0L )
+_priority   ( 0.0f )
 {
-    this->setName( conf.value("name") );
-
-    if ( conf.hasValue("lighting") )
-    {
-        bool lighting = conf.value<bool>("lighting", false);
-        setLightingIfNotSet( lighting );
-    }
-
-    if ( conf.hasValue("backface_culling") )
-    {
-        bool culling = conf.value<bool>("backface_culling", false);
-        getOrCreateStateSet()->setMode( GL_CULL_FACE, (culling?1:0) | osg::StateAttribute::OVERRIDE );
-    }
-
-    if ( conf.hasValue("blending") )
-    {
-        bool blending = conf.value<bool>("blending", false);
-        getOrCreateStateSet()->setMode( GL_BLEND, (blending?1:0) | osg::StateAttribute::OVERRIDE );
-    }
-    else
-    {
-        // blend by default.
-        this->getOrCreateStateSet()->setMode( GL_BLEND, osg::StateAttribute::ON );
-    }
-    
+    this->getOrCreateStateSet()->setMode( GL_BLEND, osg::StateAttribute::ON );
     // always draw after the terrain.
     this->getOrCreateStateSet()->setRenderBinDetails( 1, "DepthSortedBin" );
+    _horizonCuller = new HorizonCullCallback();
+    this->addCullCallback( _horizonCuller.get() );
+
+    this->setName( conf.value("name") );
 }
 
 AnnotationNode::~AnnotationNode()
@@ -122,9 +76,9 @@ AnnotationNode::setLightingIfNotSet( bool lighting )
 
     if ( ss->getMode(GL_LIGHTING) == osg::StateAttribute::INHERIT )
     {
-        this->getOrCreateStateSet()->setMode(
-            GL_LIGHTING,
-            (lighting ? 1 : 0) | osg::StateAttribute::OVERRIDE );
+        this->getOrCreateStateSet()->setMode(GL_LIGHTING,
+            lighting ? osg::StateAttribute::ON | osg::StateAttribute::PROTECTED :
+                       osg::StateAttribute::OFF | osg::StateAttribute::PROTECTED );
     }
 }
 
@@ -133,38 +87,30 @@ AnnotationNode::setMapNode( MapNode* mapNode )
 {
     if ( getMapNode() != mapNode )
     {
-        // relocate the auto-clamping callback, if there is one:
-        osg::ref_ptr<MapNode> oldMapNode = _mapNode.get();
-        if ( oldMapNode.valid() )
-        {
-            if ( _autoClampCallback )
-            {
-                oldMapNode->getTerrain()->removeTerrainCallback( _autoClampCallback.get() );
-                if ( mapNode )
-                    mapNode->getTerrain()->addTerrainCallback( _autoClampCallback.get() );
-            }
-        }		
-
         _mapNode = mapNode;
+        
+        if ( mapNode )
+        {
+            if ( mapNode->isGeocentric() )
+                _horizonCuller->setHorizon( new Horizon(mapNode->getMapSRS()) );
+            else
+                _horizonCuller->setEnabled( false );
+        }
 
 		applyStyle( this->getStyle() );
     }
 }
 
-void
-AnnotationNode::setAnnotationData( AnnotationData* data )
+bool
+AnnotationNode::getHorizonCulling() const
 {
-    _annoData = data;
+    return _horizonCuller->getEnabled();
 }
 
-AnnotationData*
-AnnotationNode::getOrCreateAnnotationData()
+void
+AnnotationNode::setHorizonCulling(bool value)
 {
-    if ( !_annoData.valid() )
-    {
-        setAnnotationData( new AnnotationData() );
-    }
-    return _annoData.get();
+    _horizonCuller->setEnabled( value );
 }
 
 void
@@ -174,50 +120,9 @@ AnnotationNode::setDynamic( bool value )
 }
 
 void
-AnnotationNode::setCPUAutoClamping( bool value )
+AnnotationNode::setPriority(float priority)
 {
-    if ( getMapNode() )
-    {
-        if ( !_autoclamp && value )
-        {
-            setDynamic( true );
-
-            if ( AnnotationSettings::getContinuousClamping() )
-            {
-                _autoClampCallback = new AutoClampCallback( this );
-                getMapNode()->getTerrain()->addTerrainCallback( _autoClampCallback.get() );
-            }
-        }
-        else if ( _autoclamp && !value && _autoClampCallback.valid())
-        {
-            getMapNode()->getTerrain()->removeTerrainCallback( _autoClampCallback );
-            _autoClampCallback = 0;
-        }
-
-        _autoclamp = value;
-        
-        if ( _autoclamp && AnnotationSettings::getApplyDepthOffsetToClampedLines() )
-        {
-            if ( !_depthAdj )
-            {
-                // verify that the geometry if polygon-less:
-                bool wantDepthAdjustment = false;
-                PrimitiveSetTypeCounter counter;
-                this->accept(counter);
-                if ( counter._polygon == 0 && (counter._line > 0 || counter._point > 0) )
-                {
-                    wantDepthAdjustment = true;
-                }
-
-                setDepthAdjustment( wantDepthAdjustment );
-            }
-            else
-            {
-                // update depth adjustment calculation
-                //getOrCreateStateSet()->addUniform( DepthOffsetUtils::createMinOffsetUniform(this) );
-            }
-        }
-    }
+    _priority = priority;
 }
 
 void
@@ -235,168 +140,24 @@ AnnotationNode::setDepthAdjustment( bool enable )
     _depthAdj = enable;
 }
 
-bool
-AnnotationNode::makeAbsolute( GeoPoint& mapPoint, osg::Node* patch ) const
-{
-    // in terrain-clamping mode, force it to HAT=0:
-    if ( _altitude.valid() && (
-        _altitude->clamping() == AltitudeSymbol::CLAMP_TO_TERRAIN || 
-        _altitude->clamping() == AltitudeSymbol::CLAMP_RELATIVE_TO_TERRAIN) )
-    {
-        mapPoint.altitudeMode() = ALTMODE_RELATIVE;
-        //If we're clamping to the terrain
-        if (_altitude->clamping() == AltitudeSymbol::CLAMP_TO_TERRAIN)
-        {
-            mapPoint.z() = 0.0;
-        }
-    }
-
-    // if the point's already absolute and we're not clamping it, nop.
-    if ( mapPoint.altitudeMode() == ALTMODE_ABSOLUTE )
-    {
-        return true;
-    }
-
-    // calculate the absolute Z of the map point.
-    if ( getMapNode() )
-    {
-        // find the terrain height at the map point:
-        double hamsl;
-        if (getMapNode()->getTerrain()->getHeight(patch, mapPoint.getSRS(), mapPoint.x(), mapPoint.y(), &hamsl, 0L))
-        {
-            // apply any scale/offset in the symbology:
-            if ( _altitude.valid() )
-            {
-                if ( _altitude->verticalScale().isSet() )
-                    hamsl *= _altitude->verticalScale()->eval();
-                if ( _altitude->verticalOffset().isSet() )
-                    hamsl += _altitude->verticalOffset()->eval();
-            }
-            mapPoint.z() += hamsl;
-        }
-        mapPoint.altitudeMode() = ALTMODE_ABSOLUTE;
-        return true;
-    }
-
-    return false;
-}
-
-
-void
-AnnotationNode::installDecoration( const std::string& name, Decoration* ds )
-{
-    if ( _activeDs )
-    {
-        clearDecoration();
-    }
-
-    if ( ds == 0L )
-    {
-        _dsMap.erase( name );
-    }
-    else
-    {
-        _dsMap[name] = ds->copyOrClone();
-    }
-}
-
-void
-AnnotationNode::uninstallDecoration( const std::string& name )
-{
-    clearDecoration();
-    _dsMap.erase( name );
-}
-
-const std::string&
-AnnotationNode::getDecoration() const
-{
-    return _activeDsName;
-}
-
 void
-AnnotationNode::setDecoration( const std::string& name )
+AnnotationNode::applyStyle( const Style& style)
 {
-    // already active?
-    if ( _activeDs && _activeDsName == name )
-        return;
-
-    // is a different one active? if so kill it
-    if ( _activeDs )
-        clearDecoration();
+    applyRenderSymbology(style);
 
-    // try to find and enable the new one
-    DecorationMap::iterator i = _dsMap.find(name);
-    if ( i != _dsMap.end() )
+    // default priority if available.
+    const TextSymbol* ts = style.get<TextSymbol>();
+    if (ts)
     {
-        Decoration* ds = i->second.get();
-        if ( ds )
+        if (ts->priority().isSet())
         {
-            if ( this->accept(ds, true) ) 
-            {
-                _activeDs = ds;
-                _activeDsName = name;
-            }
+            _priority = ts->priority()->eval();
         }
     }
 }
 
 void
-AnnotationNode::clearDecoration()
-{
-    if ( _activeDs )
-    {
-        this->accept(_activeDs, false);
-        _activeDs = 0L;
-        _activeDsName = "";
-    }
-}
-
-bool
-AnnotationNode::hasDecoration( const std::string& name ) const
-{
-    return _dsMap.find(name) != _dsMap.end();
-}
-
-osg::Group*
-AnnotationNode::getChildAttachPoint()
-{
-    osg::Transform* t = osgEarth::findTopMostNodeOfType<osg::Transform>(this);
-    return t ? (osg::Group*)t : (osg::Group*)this;
-}
-
-bool
-AnnotationNode::supportsAutoClamping( const Style& style ) const
-{
-    return
-        !style.has<ExtrusionSymbol>()  &&
-        !style.has<InstanceSymbol>()   &&
-        !style.has<MarkerSymbol>()     &&  // backwards-compability
-        style.has<AltitudeSymbol>()    &&
-        (style.get<AltitudeSymbol>()->clamping() == AltitudeSymbol::CLAMP_TO_TERRAIN ||
-         style.get<AltitudeSymbol>()->clamping() == AltitudeSymbol::CLAMP_RELATIVE_TO_TERRAIN);
-}
-
-void
-AnnotationNode::configureForAltitudeMode( const AltitudeMode& mode )
-{
-    setCPUAutoClamping(
-        mode == ALTMODE_RELATIVE ||
-        (_altitude.valid() && _altitude->clamping() == AltitudeSymbol::CLAMP_TO_TERRAIN) );
-}
-
-void
-AnnotationNode::applyStyle( const Style& style)
-{
-    if ( supportsAutoClamping(style) )
-    {
-        _altitude = style.get<AltitudeSymbol>();
-        setCPUAutoClamping( true );
-    }
-    applyGeneralSymbology(style);
-}
-
-void
-AnnotationNode::applyGeneralSymbology(const Style& style)
+AnnotationNode::applyRenderSymbology(const Style& style)
 {
     const RenderSymbol* render = style.get<RenderSymbol>();
     if ( render )
@@ -442,7 +203,7 @@ AnnotationNode::applyGeneralSymbology(const Style& style)
             int binNumber = render->order().isSet() ? (int)render->order()->eval() : ss->getBinNumber();
             std::string binName =
                 render->renderBin().isSet() ? render->renderBin().get() :
-                ss->useRenderBinDetails() ? ss->getBinName() : "RenderBin";
+                ss->useRenderBinDetails() ? ss->getBinName() : "DepthSortedBin";
             ss->setRenderBinDetails(binNumber, binName);
         }
 
@@ -450,5 +211,12 @@ AnnotationNode::applyGeneralSymbology(const Style& style)
         {
             DiscardAlphaFragments().install( getOrCreateStateSet(), render->minAlpha().value() );
         }
+        
+
+        if ( render->transparent() == true )
+        {
+            osg::StateSet* ss = getOrCreateStateSet();
+            ss->setRenderingHint( ss->TRANSPARENT_BIN );
+        }
     }
 }
diff --git a/src/osgEarthAnnotation/AnnotationRegistry b/src/osgEarthAnnotation/AnnotationRegistry
index 1e72670..cae1e08 100644
--- a/src/osgEarthAnnotation/AnnotationRegistry
+++ b/src/osgEarthAnnotation/AnnotationRegistry
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
@@ -27,6 +27,8 @@
 
 namespace osgEarth { namespace Annotation
 {
+    class AnnotationFactory;
+
     /**
      * Singleton registry for annotation node types.
      */
@@ -59,7 +61,7 @@ namespace osgEarth { namespace Annotation
         /**
          * Adds an annotation type to the registry
          */
-        void add( const std::string& key, class AnnotationFactory* factory );
+        void add( const std::string& key, AnnotationFactory* factory );
 
         virtual ~AnnotationRegistry() { }
 
@@ -71,8 +73,7 @@ namespace osgEarth { namespace Annotation
         AnnotationNode* createOne( 
             MapNode*              mapNode, 
             const Config&         conf,
-            const osgDB::Options* dbOptions, 
-            bool                  declutter =false ) const;
+            const osgDB::Options* dbOptions) const;
     };
 
     // Macro used to register new annotation types.
diff --git a/src/osgEarthAnnotation/AnnotationRegistry.cpp b/src/osgEarthAnnotation/AnnotationRegistry.cpp
index 6f29388..74f25c8 100644
--- a/src/osgEarthAnnotation/AnnotationRegistry.cpp
+++ b/src/osgEarthAnnotation/AnnotationRegistry.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
@@ -20,7 +20,7 @@
 * along with this program.  If not, see <http://www.gnu.org/licenses/>
 */
 #include <osgEarthAnnotation/AnnotationRegistry>
-#include <osgEarth/Decluttering>
+#include <osgEarth/ScreenSpaceLayout>
 #include <osgEarth/Registry>
 #include <osgEarth/ObjectIndex>
 
@@ -38,7 +38,6 @@ namespace
         CollectAnnotationNodes() : osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN)
         {
             _group.key() = "annotations";
-            _declutter   = false;
         }
 
         void apply(osg::Node& node)
@@ -50,19 +49,10 @@ namespace
                 _group.add( conf );
             }
 
-            if (!_declutter &&
-                node.getStateSet() &&
-                node.getStateSet()->getRenderBinMode() != osg::StateSet::INHERIT_RENDERBIN_DETAILS &&
-                node.getStateSet()->getBinName() == OSGEARTH_DECLUTTER_BIN )
-            {
-                _declutter = true;
-            }
-
             traverse(node);
         }
 
         Config _group;
-        bool   _declutter;
     };
 }
 
@@ -104,10 +94,8 @@ AnnotationRegistry::create(MapNode*              mapNode,
 {
     bool createdAtLeastOne = false;
 
-    bool declutter = conf.value<bool>("declutter",false) == true;
-
     // first try to parse the top-level config as an annotation:
-    AnnotationNode* top = createOne(mapNode, conf, options, declutter);
+    AnnotationNode* top = createOne(mapNode, conf, options);
     if ( top )
     {
         if ( results == 0L )
@@ -121,7 +109,7 @@ AnnotationRegistry::create(MapNode*              mapNode,
     {
         for( ConfigSet::const_iterator i = conf.children().begin(); i != conf.children().end(); ++i )
         {
-            AnnotationNode* anno = createOne( mapNode, *i, options, declutter );
+            AnnotationNode* anno = createOne( mapNode, *i, options );
             if ( anno )
             {
                 if ( results == 0L )
@@ -139,8 +127,7 @@ AnnotationRegistry::create(MapNode*              mapNode,
 AnnotationNode*
 AnnotationRegistry::createOne(MapNode*              mapNode, 
                               const Config&         conf, 
-                              const osgDB::Options* options, 
-                              bool                  declutterOrthos ) const
+                              const osgDB::Options* options) const
 {
     FactoryMap::const_iterator f = _factories.find( conf.key() );
     if ( f != _factories.end() && f->second != 0L )
@@ -148,13 +135,7 @@ AnnotationRegistry::createOne(MapNode*              mapNode,
         AnnotationNode* anno = f->second->create(mapNode, conf, options);
         if ( anno )
         {
-            if ( declutterOrthos && dynamic_cast<SupportsDecluttering*>(anno) )
-            {
-                Decluttering::setEnabled( anno->getOrCreateStateSet(), true );
-            }
-
             Registry::objectIndex()->tagNode( anno, anno );
-
             return anno;
         }
     }
@@ -169,8 +150,6 @@ AnnotationRegistry::getConfig( osg::Node* graph ) const
     {
         CollectAnnotationNodes visitor;
         graph->accept( visitor );
-        if ( visitor._declutter )
-            visitor._group.set( "declutter", "true" );
         return visitor._group;
     }
     return Config();
diff --git a/src/osgEarthAnnotation/AnnotationSettings b/src/osgEarthAnnotation/AnnotationSettings
index efc7b09..1e75086 100644
--- a/src/osgEarthAnnotation/AnnotationSettings
+++ b/src/osgEarthAnnotation/AnnotationSettings
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthAnnotation/AnnotationSettings.cpp b/src/osgEarthAnnotation/AnnotationSettings.cpp
index 8f7ee6d..5427605 100644
--- a/src/osgEarthAnnotation/AnnotationSettings.cpp
+++ b/src/osgEarthAnnotation/AnnotationSettings.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthAnnotation/AnnotationUtils b/src/osgEarthAnnotation/AnnotationUtils
index 6bf70f2..438146b 100644
--- a/src/osgEarthAnnotation/AnnotationUtils
+++ b/src/osgEarthAnnotation/AnnotationUtils
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
@@ -56,13 +56,24 @@ namespace osgEarth { namespace Annotation
         static osgText::String::Encoding convertTextSymbolEncoding(const TextSymbol::Encoding encoding);
 
         /**
-         * Creates a drawable representing a symbolized text label in
-         * pixel space.
+         * Creates a drawable representing a symbolized text label in pixel space.
+         * The "box" is an alignment box; all positioning and alignment of the text
+         * is relative to this box. For example, if the TextSymbol contains an align
+         * of RIGHT_TOP, that means the text origin is at the upper-right corner of
+         * the box.
          */
         static osg::Drawable* createTextDrawable(
             const std::string& text,
             const TextSymbol*  symbol,
-            const osg::Vec3&   positionOffset );
+            const osg::BoundingBox& alignmentBox);
+        
+        static osg::Drawable* createTextDrawable(
+            const std::string& text,
+            const TextSymbol*  symbol,
+            const osg::Vec3&   pos )
+        {
+            return createTextDrawable(text, symbol, osg::BoundingBox(pos,pos));
+        }
 
         /**
          * Creates the basic geometry to draw an image texture-mapped to
@@ -99,18 +110,6 @@ namespace osgEarth { namespace Annotation
          */
         static bool styleRequiresAlphaBlending( const Style& style );
 
-        /**
-         * Internal - A customized AutoTransform used by the OrthoNode to
-         * support intersections that are compatible with the decluttering engine
-         */
-        struct OrthoNodeAutoTransform : public osg::AutoTransform
-        {
-            /** override */
-            virtual void accept(osg::NodeVisitor& nv);
-
-            bool okToIntersect() const { return !_firstTimeToInitEyePoint; }
-        };
-
         // some geometry creation utilities
         static osg::Drawable* create2DQuad( const osg::BoundingBox& box, float padding, const osg::Vec4& color );
 
@@ -152,8 +151,15 @@ namespace osgEarth { namespace Annotation
             bool sceneClamping;
             bool gpuClamping;
         };
+
         static void getAltitudePolicy( const Style& style, AltitudePolicy& b );
 
+        /**
+         * If the style requests draping or clamping, creates the appropriate parent
+         * group and adds the input node as a child, and returns the new parent.
+         * Otherwise, just returns the input node unchanged.
+         */
+        static osg::Node* installOverlayParent(osg::Node* child, const Style& style);
 
     private:
         AnnotationUtils() { }
diff --git a/src/osgEarthAnnotation/AnnotationUtils.cpp b/src/osgEarthAnnotation/AnnotationUtils.cpp
index 90ddee8..805e9a5 100755
--- a/src/osgEarthAnnotation/AnnotationUtils.cpp
+++ b/src/osgEarthAnnotation/AnnotationUtils.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
@@ -28,6 +28,8 @@
 #include <osgEarth/VirtualProgram>
 #include <osgEarth/Capabilities>
 #include <osgEarth/CullingUtils>
+#include <osgEarth/DrapeableNode>
+#include <osgEarth/ClampableNode>
 
 #include <osgText/Text>
 #include <osg/Depth>
@@ -85,14 +87,13 @@ AnnotationUtils::convertTextSymbolEncoding (const TextSymbol::Encoding encoding)
     return text_encoding;
 }
 
-osg::Drawable* 
+osg::Drawable*
 AnnotationUtils::createTextDrawable(const std::string& text,
                                     const TextSymbol*  symbol,
-                                    const osg::Vec3&   positionOffset )
-                                    
+                                    const osg::BoundingBox& box)
 {
     osgText::Text* t = new osgText::Text();
-    
+
     osgText::String::Encoding text_encoding = osgText::String::ENCODING_UNDEFINED;
     if ( symbol && symbol->encoding().isSet() )
     {
@@ -119,47 +120,114 @@ AnnotationUtils::createTextDrawable(const std::string& text,
             t->setLayout(osgText::TextBase::VERTICAL);
         }
     }
-    if ( symbol && symbol->pixelOffset().isSet() )
+
+    // calculate the text position relative to the alignment box.
+    osg::Vec3f pos;
+
+    osgText::Text::AlignmentType align = osgText::Text::CENTER_CENTER;
+    if ( symbol )
     {
-        t->setPosition( osg::Vec3(
-            positionOffset.x() + symbol->pixelOffset()->x(),
-            positionOffset.y() + symbol->pixelOffset()->y(),
-            positionOffset.z() ) );
+        // they're the same enum, but we need to apply the BBOX offsets.
+        align = (osgText::Text::AlignmentType)symbol->alignment().value();
     }
-    else
+
+    switch( align )
     {
-        t->setPosition( positionOffset );
+    case osgText::Text::LEFT_TOP:
+        pos.x() = box.xMax();
+        pos.y() = box.yMin();
+        break;
+    case osgText::Text::LEFT_CENTER:
+        pos.x() = box.xMax();
+        pos.y() = box.center().y();
+        break;
+    case osgText::Text::LEFT_BOTTOM:
+    case osgText::Text::LEFT_BOTTOM_BASE_LINE:
+    case osgText::Text::LEFT_BASE_LINE:
+        pos.x() = box.xMax();
+        pos.y() = box.yMax();
+        break;
+
+    case osgText::Text::RIGHT_TOP:
+        pos.x() = box.xMin();
+        pos.y() = box.yMin();
+        break;
+    case osgText::Text::RIGHT_CENTER:
+        pos.x() = box.xMin();
+        pos.y() = box.center().y();
+        break;
+    case osgText::Text::RIGHT_BOTTOM:
+    case osgText::Text::RIGHT_BOTTOM_BASE_LINE:
+    case osgText::Text::RIGHT_BASE_LINE:
+        pos.x() = box.xMin();
+        pos.y() = box.yMax();
+        break;
+
+    case osgText::Text::CENTER_TOP:
+        pos.x() = box.center().x();
+        pos.y() = box.yMin();
+        break;
+    case osgText::Text::CENTER_BOTTOM:
+    case osgText::Text::CENTER_BOTTOM_BASE_LINE:
+    case osgText::Text::CENTER_BASE_LINE:
+        pos.x() = box.center().x();
+        pos.y() = box.yMax();
+        break;
+    case osgText::Text::CENTER_CENTER:
+    default:
+        pos = box.center();
+        break;
     }
 
-    t->setAutoRotateToScreen( false );
+    t->setPosition( pos );
+    t->setAlignment( align );
+
+    t->setAutoRotateToScreen(false);
+
+#if OSG_MIN_VERSION_REQUIRED(3,4,0)
+    t->setCullingActive(false);
+#endif
+
     t->setCharacterSizeMode( osgText::Text::OBJECT_COORDS );
-    t->setCharacterSize( symbol && symbol->size().isSet() ? (float)(symbol->size()->eval()) : 16.0f );
+    float size = symbol && symbol->size().isSet() ? (float)(symbol->size()->eval()) : 16.0f;
+    t->setCharacterSize( size );
     t->setColor( symbol && symbol->fill().isSet() ? symbol->fill()->color() : Color::White );
 
     osgText::Font* font = 0L;
     if ( symbol && symbol->font().isSet() )
     {
         font = osgText::readFontFile( *symbol->font() );
-        // mitigates mipmapping issues that cause rendering artifacts for some fonts/placement
-        if ( font )
-          font->setGlyphImageMargin( 2 );
     }
     if ( !font )
         font = Registry::instance()->getDefaultFont();
+
     if ( font )
+    {
         t->setFont( font );
 
-    if ( symbol )
-    {
-        // they're the same enum.
-        osgText::Text::AlignmentType at = (osgText::Text::AlignmentType)symbol->alignment().value();
-        t->setAlignment( at );
+        // mitigates mipmapping issues that cause rendering artifacts for some fonts/placement
+        font->setGlyphImageMargin( 2 );
     }
 
+    t->setFontResolution( size, size );
+    t->setBackdropOffset( (float)t->getFontWidth() / 256.0f, (float)t->getFontHeight() / 256.0f );
+
     if ( symbol && symbol->halo().isSet() )
     {
         t->setBackdropColor( symbol->halo()->color() );
-        t->setBackdropType( osgText::Text::OUTLINE );
+        if ( symbol->haloBackdropType().isSet() )
+        {
+            t->setBackdropType( *symbol->haloBackdropType() );
+        }
+        else
+        {
+            t->setBackdropType( osgText::Text::OUTLINE );
+        }
+
+        if ( symbol->haloImplementation().isSet() )
+        {
+            t->setBackdropImplementation( *symbol->haloImplementation() );
+        }
 
         if ( symbol->haloOffset().isSet() )
         {
@@ -207,7 +275,7 @@ AnnotationUtils::createImageGeometry(osg::Image*       image,
 
     // set up the geoset.
     osg::Geometry* geom = new osg::Geometry();
-    geom->setUseVertexBufferObjects(true);    
+    geom->setUseVertexBufferObjects(true);
     geom->setStateSet(dstate);
 
     float s = scale * image->s();
@@ -266,157 +334,7 @@ AnnotationUtils::createHighlightUniform()
     return u;
 }
 
-//-------------------------------------------------------------------------
-
-// This is identical to osg::AutoTransform::accept, except that we (a) removed
-// code that's not used by OrthoNode, and (b) took out the call to
-// Transform::accept since we don't want to traverse the child graph from
-// this call.
-void
-AnnotationUtils::OrthoNodeAutoTransform::accept(osg::NodeVisitor& nv)
-{
-    if ( nv.validNodeMask(*this) )
-    {
-        if ( nv.getVisitorType() == nv.CULL_VISITOR )
-        {
-            osgUtil::CullVisitor* cv = Culling::asCullVisitor(nv);
-
-            // check for a reference camera for size scaling.
-            osg::Vec3f refCamScale(1,1,1);
-            osg::Camera* cam = cv->getCurrentCamera();
-            if ( cam && cam->isRenderToTextureCamera() )
-            {
-                const osg::Viewport* vp = cam->getViewport();
-                if ( vp )
-                {
-                    osg::Camera* refCam = dynamic_cast<osg::Camera*>(cam->getUserData());
-                    if ( refCam && refCam->getViewport() )
-                    {
-                        refCamScale.set(
-                            vp->width() / refCam->getViewport()->width(),
-                            vp->height() / refCam->getViewport()->height(),
-                            1.0f );
-                    }
-                }
-            }
-
-            osg::Viewport::value_type width = _previousWidth;
-            osg::Viewport::value_type height = _previousHeight;
-
-            osg::Viewport* viewport = cv->getViewport();
-            if (viewport)
-            {
-                width = viewport->width();
-                height = viewport->height();
-            }
-
-            osg::Vec3d eyePoint = cv->getEyeLocal(); 
-            osg::Vec3d localUp = cv->getUpLocal(); 
-            osg::Vec3d position = getPosition();
-
-            const osg::Matrix& projection = *(cv->getProjectionMatrix());
-
-            bool doUpdate = _firstTimeToInitEyePoint;
-            if (!_firstTimeToInitEyePoint)
-            {
-                osg::Vec3d dv = _previousEyePoint-eyePoint;
-                if (dv.length2()>getAutoUpdateEyeMovementTolerance()*(eyePoint-getPosition()).length2())
-                {
-                    doUpdate = true;
-                }
-                osg::Vec3d dupv = _previousLocalUp-localUp;
-                // rotating the camera only affects ROTATE_TO_*
-                if (_autoRotateMode &&
-                    dupv.length2()>getAutoUpdateEyeMovementTolerance())
-                {
-                    doUpdate = true;
-                }
-                else if (width!=_previousWidth || height!=_previousHeight)
-                {
-                    doUpdate = true;
-                }
-                else if (projection != _previousProjection) 
-                {
-                    doUpdate = true;
-                }                
-                else if (position != _previousPosition) 
-                { 
-                    doUpdate = true; 
-                } 
-            }
-            _firstTimeToInitEyePoint = false;
-
-            if (doUpdate)
-            {            
-                if (getAutoScaleToScreen())
-                {
-                    double size = 1.0/cv->pixelSize(getPosition(),0.48f);
-
-                    if (_autoScaleTransitionWidthRatio>0.0)
-                    {
-                        if (_minimumScale>0.0)
-                        {
-                            double j = _minimumScale;
-                            double i = (_maximumScale<DBL_MAX) ? 
-                                _minimumScale+(_maximumScale-_minimumScale)*_autoScaleTransitionWidthRatio :
-                            _minimumScale*(1.0+_autoScaleTransitionWidthRatio);
-                            double c = 1.0/(4.0*(i-j));
-                            double b = 1.0 - 2.0*c*i;
-                            double a = j + b*b / (4.0*c);
-                            double k = -b / (2.0*c);
-
-                            if (size<k) size = _minimumScale;
-                            else if (size<i) size = a + b*size + c*(size*size);
-                        }
-
-                        if (_maximumScale<DBL_MAX)
-                        {
-                            double n = _maximumScale;
-                            double m = (_minimumScale>0.0) ?
-                                _maximumScale+(_minimumScale-_maximumScale)*_autoScaleTransitionWidthRatio :
-                            _maximumScale*(1.0-_autoScaleTransitionWidthRatio);
-                            double c = 1.0 / (4.0*(m-n));
-                            double b = 1.0 - 2.0*c*m;
-                            double a = n + b*b/(4.0*c);
-                            double p = -b / (2.0*c);
-
-                            if (size>p) size = _maximumScale;
-                            else if (size>m) size = a + b*size + c*(size*size);
-                        }        
-                    }
-
-                    setScale(size * refCamScale.x());
-                }
-
-                if (_autoRotateMode==ROTATE_TO_SCREEN)
-                {
-                    osg::Vec3d translation;
-                    osg::Quat rotation;
-                    osg::Vec3d scale;
-                    osg::Quat so;
-
-                    cv->getModelViewMatrix()->decompose( translation, rotation, scale, so );
-
-                    setRotation(rotation.inverse());
-                }
-                // GW: removed other unused auto-rotate modes
-
-                _previousEyePoint = eyePoint;
-                _previousLocalUp = localUp;
-                _previousWidth = width;
-                _previousHeight = height;
-                _previousProjection = projection;
-                _previousPosition = position;
-
-                _matrixDirty = true;
-            }
-        }
-
-        osg::Transform::accept( nv );
-    }
-}
-
-osg::Node* 
+osg::Node*
 AnnotationUtils::createSphere( float r, const osg::Vec4& color, float maxAngle )
 {
     osg::Geometry* geom = new osg::Geometry();
@@ -475,7 +393,7 @@ AnnotationUtils::createSphere( float r, const osg::Vec4& color, float maxAngle )
       return geode;
 }
 
-osg::Node* 
+osg::Node*
 AnnotationUtils::createHemisphere( float r, const osg::Vec4& color, float maxAngle )
 {
     osg::Geometry* geom = new osg::Geometry();
@@ -530,10 +448,10 @@ AnnotationUtils::createHemisphere( float r, const osg::Vec4& color, float maxAng
 
 // constructs an ellipsoidal mesh
 osg::Geometry*
-AnnotationUtils::createEllipsoidGeometry(float xRadius, 
+AnnotationUtils::createEllipsoidGeometry(float xRadius,
                                          float yRadius,
                                          float zRadius,
-                                         const osg::Vec4f& color, 
+                                         const osg::Vec4f& color,
                                          float maxAngle,
                                          float minLat,
                                          float maxLat,
@@ -555,6 +473,7 @@ AnnotationUtils::createEllipsoidGeometry(float xRadius,
     osg::Vec3Array* verts = new osg::Vec3Array();
     verts->reserve( latSegments * lonSegments );
 
+#if 0
     bool genTexCoords = false; // TODO: optional
     osg::Vec2Array* texCoords = 0;
     if (genTexCoords)
@@ -563,6 +482,7 @@ AnnotationUtils::createEllipsoidGeometry(float xRadius,
         texCoords->reserve( latSegments * lonSegments );
         geom->setTexCoordArray( 0, texCoords );
     }
+#endif
 
     osg::Vec3Array* normals = new osg::Vec3Array();
     normals->reserve( latSegments * lonSegments );
@@ -585,24 +505,23 @@ AnnotationUtils::createEllipsoidGeometry(float xRadius,
             float sin_u = sinf(u);
             float cos_v = cosf(v);
             float sin_v = sinf(v);
-            
+
             verts->push_back(osg::Vec3(
                 xRadius * cos_u * cos_v,
                 yRadius * sin_u * cos_v,
                 zRadius * sin_v ));
 
+#if 0
             if (genTexCoords)
             {
                 double s = (lon + 180) / 360.0;
                 double t = (lat + 90.0) / 180.0;
                 texCoords->push_back( osg::Vec2(s, t ) );
             }
+#endif
 
-            if (normals)
-            {
-                normals->push_back( verts->back() );
-                normals->back().normalize();
-            }
+            normals->push_back( verts->back() );
+            normals->back().normalize();
 
             if ( y < latSegments )
             {
@@ -629,11 +548,11 @@ AnnotationUtils::createEllipsoidGeometry(float xRadius,
     return geom;
 }
 
-osg::Node* 
-AnnotationUtils::createEllipsoid(float xRadius, 
+osg::Node*
+AnnotationUtils::createEllipsoid(float xRadius,
                                  float yRadius,
                                  float zRadius,
-                                 const osg::Vec4f& color, 
+                                 const osg::Vec4f& color,
                                  float maxAngle,
                                  float minLat,
                                  float maxLat,
@@ -664,7 +583,7 @@ AnnotationUtils::createEllipsoid(float xRadius,
     return geode;
 }
 
-osg::Node* 
+osg::Node*
 AnnotationUtils::createFullScreenQuad( const osg::Vec4& color )
 {
     osg::Geometry* geom = new osg::Geometry();
@@ -818,7 +737,7 @@ AnnotationUtils::installTwoPassAlpha(osg::Node* node)
 }
 
 
-bool 
+bool
 AnnotationUtils::styleRequiresAlphaBlending( const Style& style )
 {
     if (style.has<PolygonSymbol>() &&
@@ -862,7 +781,7 @@ AnnotationUtils::getAltitudePolicy(const Style& style, AltitudePolicy& out)
         const AltitudeSymbol* alt = style.get<AltitudeSymbol>();
         if ( alt )
         {
-            if (alt->clamping() == AltitudeSymbol::CLAMP_TO_TERRAIN || 
+            if (alt->clamping() == AltitudeSymbol::CLAMP_TO_TERRAIN ||
                 alt->clamping() == AltitudeSymbol::CLAMP_RELATIVE_TO_TERRAIN )
             {
                 out.sceneClamping = alt->technique() == AltitudeSymbol::TECHNIQUE_SCENE;
@@ -880,3 +799,51 @@ AnnotationUtils::getAltitudePolicy(const Style& style, AltitudePolicy& out)
         }
     }
 }
+
+osg::Node*
+AnnotationUtils::installOverlayParent(osg::Node* node, const Style& style)
+{
+    AnnotationUtils::AltitudePolicy ap;
+
+    AnnotationUtils::getAltitudePolicy( style, ap );
+
+    // Draped (projected) geometry
+    if ( ap.draping )
+    {
+        DrapeableNode* drapable = new DrapeableNode();
+        drapable->addChild( node );
+        node = drapable;
+    }
+
+    // gw - not sure whether is makes sense to support this for LocalizedNode
+    // GPU-clamped geometry
+    else if ( ap.gpuClamping )
+    {
+        ClampableNode* clampable = new ClampableNode( 0L );
+        clampable->addChild( node );
+        node = clampable;
+
+        const RenderSymbol* render = style.get<RenderSymbol>();
+        if ( render && render->depthOffset().isSet() )
+        {
+            clampable->setDepthOffsetOptions( *render->depthOffset() );
+        }
+    }
+
+#if 0 // TODO -- constuct a callback instead.
+
+    // scenegraph-clamped geometry
+    else if ( ap.sceneClamping )
+    {
+        // save for later when we need to reclamp the mesh on the CPU
+        _altitude = style.get<AltitudeSymbol>();
+
+        // activate the terrain callback:
+        setCPUAutoClamping( true );
+    }
+
+#endif
+
+    return node;
+}
+
diff --git a/src/osgEarthAnnotation/BboxDrawable b/src/osgEarthAnnotation/BboxDrawable
new file mode 100644
index 0000000..c3abcf1
--- /dev/null
+++ b/src/osgEarthAnnotation/BboxDrawable
@@ -0,0 +1,47 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+* Copyright 2016 Pelican Mapping
+* http://osgearth.org
+*
+* osgEarth is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* 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.
+*
+* You should have received a copy of the GNU Lesser General Public License
+* along with this program.  If not, see <http://www.gnu.org/licenses/>
+*/
+
+#ifndef OSGEARTH_ANNOTATION_BBOXDRAWABLE_H
+#define OSGEARTH_ANNOTATION_BBOXDRAWABLE_H 1
+
+#include <osgEarthSymbology/BBoxSymbol>
+#include <osgEarthAnnotation/Common>
+
+#include <osg/Geometry>
+
+namespace osgEarth { namespace Annotation
+{	
+    /**
+     * Drawable for rendering bounding box around label
+     */
+    class OSGEARTHANNO_EXPORT BboxDrawable : public osg::Geometry
+    {
+
+    public:
+
+        BboxDrawable( const osg::BoundingBox& box, const BBoxSymbol &bboxSymbol );
+
+    };
+
+} } // namespace osgEarth::Annotation
+
+#endif // OSGEARTH_ANNOTATION_BBOXDRAWABLE_H
diff --git a/src/osgEarthAnnotation/BboxDrawable.cpp b/src/osgEarthAnnotation/BboxDrawable.cpp
new file mode 100644
index 0000000..88cc073
--- /dev/null
+++ b/src/osgEarthAnnotation/BboxDrawable.cpp
@@ -0,0 +1,81 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+* Copyright 2016 Pelican Mapping
+* http://osgearth.org
+*
+* osgEarth is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* 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.
+*
+* You should have received a copy of the GNU Lesser General Public License
+* along with this program.  If not, see <http://www.gnu.org/licenses/>
+*/
+#include <osgEarthAnnotation/BboxDrawable>
+#include <osgEarthAnnotation/AnnotationUtils>
+
+#include <osg/LineWidth>
+
+using namespace osgEarth;
+using namespace osgEarth::Annotation;
+
+
+//------------------------------------------------------------------------
+
+BboxDrawable::BboxDrawable( const osg::BoundingBox& box, const BBoxSymbol &bboxSymbol ) :
+osg::Geometry()
+{
+    setUseVertexBufferObjects(true);
+
+    float margin = bboxSymbol.margin().isSet() ? bboxSymbol.margin().value() : 2.f;
+    osg::Vec3Array* v = new osg::Vec3Array();
+    if ( bboxSymbol.geom().isSet() && bboxSymbol.geom().value() == BBoxSymbol::GEOM_BOX_ORIENTED )
+    {
+        float h = box.yMax() - box.yMin() + 2.f * margin;
+        v->push_back( osg::Vec3(box.xMax()+margin+h/2.f, box.yMax()+margin-h/2.f, 0) );
+    }
+    v->push_back( osg::Vec3(box.xMax()+margin, box.yMax()+margin, 0) );
+    v->push_back( osg::Vec3(box.xMin()-margin, box.yMax()+margin, 0) );
+    v->push_back( osg::Vec3(box.xMin()-margin, box.yMin()-margin, 0) );
+    v->push_back( osg::Vec3(box.xMax()+margin, box.yMin()-margin, 0) );
+    setVertexArray(v);
+    if ( v->getVertexBufferObject() )
+        v->getVertexBufferObject()->setUsage(GL_STATIC_DRAW_ARB);
+
+    osg::Vec4Array* c = new osg::Vec4Array();
+    if ( bboxSymbol.fill().isSet() )
+    {
+        c->push_back( bboxSymbol.fill()->color() );
+        addPrimitiveSet( new osg::DrawArrays(GL_POLYGON, 0, v->getNumElements()) );
+    }
+
+    if ( bboxSymbol.border().isSet() )
+    {
+        c->push_back( bboxSymbol.border()->color() );
+        if ( bboxSymbol.border()->width().isSet() )
+            getOrCreateStateSet()->setAttribute( new osg::LineWidth( bboxSymbol.border()->width().value() ));
+        addPrimitiveSet( new osg::DrawArrays(GL_LINE_LOOP, 0, v->getNumElements()) );
+    }
+
+    setColorArray( c );
+    setColorBinding( osg::Geometry::BIND_PER_PRIMITIVE_SET );
+
+    // add the static "isText=true" uniform; this is a hint for the annotation shaders
+    // if they get installed.
+    static osg::ref_ptr<osg::Uniform> s_isTextUniform = new osg::Uniform(osg::Uniform::BOOL, AnnotationUtils::UNIFORM_IS_TEXT());
+    s_isTextUniform->set( false );
+    getOrCreateStateSet()->addUniform( s_isTextUniform.get() );
+
+    // Disable culling since this bounding box will eventually be drawn in screen space.
+#if OSG_MIN_VERSION_REQUIRED(3,4,0)
+    setCullingActive(false);
+#endif
+}
diff --git a/src/osgEarthAnnotation/CMakeLists.txt b/src/osgEarthAnnotation/CMakeLists.txt
index 2b257c3..667b922 100644
--- a/src/osgEarthAnnotation/CMakeLists.txt
+++ b/src/osgEarthAnnotation/CMakeLists.txt
@@ -11,10 +11,12 @@ set(HEADER_PATH ${OSGEARTH_SOURCE_DIR}/include/${LIB_NAME})
 set(LIB_PUBLIC_HEADERS  
     AnnotationSettings
     AnnotationEditing
+    AnnotationExtension
     AnnotationData
     AnnotationNode
     AnnotationRegistry
     AnnotationUtils
+	BboxDrawable
     CircleNode
     Common
     Decoration
@@ -23,14 +25,14 @@ set(LIB_PUBLIC_HEADERS
     Export
     FeatureNode
     FeatureEditing
+    GeoPositionNode
+    GeoPositionNodeAutoScaler
     LocalGeometryNode
     HighlightDecoration
     ImageOverlay
     ImageOverlayEditor
     LabelNode
-    LocalizedNode
     ModelNode
-    OrthoNode
     PlaceNode
     RectangleNode
     ScaleDecoration
@@ -39,26 +41,28 @@ set(LIB_PUBLIC_HEADERS
 
 set(LIB_COMMON_FILES
     AnnotationEditing.cpp
+    AnnotationExtension.cpp
     AnnotationSettings.cpp
     AnnotationData.cpp
     AnnotationNode.cpp
     AnnotationRegistry.cpp
     AnnotationUtils.cpp
+	BboxDrawable.cpp
     CircleNode.cpp
     Decoration.cpp
     Draggers.cpp
     EllipseNode.cpp
     FeatureNode.cpp
     FeatureEditing.cpp
+    GeoPositionNode.cpp
+    GeoPositionNodeAutoScaler.cpp
     LocalGeometryNode.cpp
     HighlightDecoration.cpp
     ImageOverlay.cpp
     ImageOverlayEditor.cpp
     LabelNode.cpp
-    LocalizedNode.cpp
     RectangleNode.cpp
     ModelNode.cpp
-    OrthoNode.cpp
     PlaceNode.cpp
     TrackNode.cpp
 )
diff --git a/src/osgEarthAnnotation/CircleNode b/src/osgEarthAnnotation/CircleNode
index 7bcd31d..9614dac 100644
--- a/src/osgEarthAnnotation/CircleNode
+++ b/src/osgEarthAnnotation/CircleNode
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
@@ -23,7 +23,7 @@
 #ifndef OSGEARTH_ANNOTATION_CIRCLE_NODE_H
 #define OSGEARTH_ANNOTATION_CIRCLE_NODE_H 1
 
-#include <osgEarthAnnotation/LocalizedNode>
+#include <osgEarthAnnotation/LocalGeometryNode>
 #include <osgEarthSymbology/Style>
 #include <osgEarth/MapNode>
 #include <osgEarth/Units>
@@ -36,7 +36,7 @@ namespace osgEarth { namespace Annotation
     /**
      * Circle annotation.
      */
-    class OSGEARTHANNO_EXPORT CircleNode : public LocalizedNode
+    class OSGEARTHANNO_EXPORT CircleNode : public LocalGeometryNode
     {
     public:
         META_AnnotationNode( osgEarthAnnotation, CircleNode );
@@ -94,16 +94,6 @@ namespace osgEarth { namespace Annotation
         void setNumSegments(unsigned int numSegments );
 
         /**
-         * Gets the style of this circle
-         */
-        const Style& getStyle() const;
-
-        /**
-         * Sets the style of this circle
-         */
-        void setStyle( const Style& style );
-
-        /**
          * Gets the start degrees of this (arc) circle
          */
         const Angle& getArcStart(void) const;
@@ -133,10 +123,6 @@ namespace osgEarth { namespace Annotation
          */
         void setPie(const bool& pie);
 
-    public: // LocalizedNode
-
-        osg::MatrixTransform* getTransform() { return _xform.get(); }
-
 
     public: // AnnotationNode overrides
 
@@ -147,17 +133,15 @@ namespace osgEarth { namespace Annotation
         CircleNode() { }
         CircleNode(const CircleNode& rhs, const osg::CopyOp& op) { }
 
-        void rebuild();
+        void rebuildGeometry();
 
-        Style           _style;
-        bool            _draped;
-        unsigned        _numSegments;
-        Distance        _radius;
+        void initCircleNode();
+
+        unsigned       _numSegments;
+        Distance       _radius;
         Angle          _arcStart;
         Angle          _arcEnd;
         bool           _pie;
-
-        osg::ref_ptr<osg::MatrixTransform> _xform;
     };
 
 } } // namespace osgEarth::Annotation
diff --git a/src/osgEarthAnnotation/CircleNode.cpp b/src/osgEarthAnnotation/CircleNode.cpp
index f5401be..7296e3d 100644
--- a/src/osgEarthAnnotation/CircleNode.cpp
+++ b/src/osgEarthAnnotation/CircleNode.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
@@ -22,6 +22,7 @@
 
 #include <osgEarthAnnotation/CircleNode>
 #include <osgEarthAnnotation/AnnotationRegistry>
+#include <osgEarthAnnotation/AnnotationUtils>
 #include <osgEarthFeatures/GeometryCompiler>
 #include <osgEarthSymbology/GeometryFactory>
 #include <osgEarthSymbology/ExtrusionSymbol>
@@ -44,19 +45,26 @@ CircleNode::CircleNode(MapNode*           mapNode,
                        const Angle&       arcEnd,
                        const bool         pie):
 
-LocalizedNode( mapNode, position ),
+LocalGeometryNode(mapNode),
 _radius      ( radius ),
-_style       ( style ),
 _arcStart    ( arcStart ),
 _arcEnd      ( arcEnd ),
 _pie         ( pie ),
 _numSegments ( 0 )
 {
-    _xform = new osg::MatrixTransform();
-    rebuild();
+    initCircleNode();
+    setStyle( style );
+    setPosition( position );
 }
 
 
+void
+CircleNode::initCircleNode()
+{
+    setName("Circle");
+    rebuildGeometry();
+}
+
 const Linear&
 CircleNode::getRadius() const
 {
@@ -69,7 +77,7 @@ CircleNode::setRadius( const Linear& radius )
     if (_radius != radius )
     {
         _radius = radius;
-        rebuild();
+        rebuildGeometry();
     }
 }
 
@@ -85,23 +93,10 @@ CircleNode::setNumSegments(unsigned int numSegments )
     if (_numSegments != numSegments )
     {
         _numSegments = numSegments;
-        rebuild();
+        rebuildGeometry();
     }
 }
 
-const Style&
-CircleNode::getStyle() const
-{
-    return _style;
-}
-
-void
-CircleNode::setStyle( const Style& style )
-{
-    _style = style;
-    rebuild();
-}
-
 const Angle&
 CircleNode::getArcStart(void) const
 {
@@ -112,7 +107,7 @@ void
 CircleNode::setArcStart(const Angle& arcStart)
 {
 	_arcStart = arcStart;
-	rebuild();
+	rebuildGeometry();
 }
 
 const Angle&
@@ -125,7 +120,7 @@ void
 CircleNode::setArcEnd(const Angle& arcEnd)
 {
 	_arcEnd = arcEnd;
-	rebuild();
+	rebuildGeometry();
 }
 
 const bool&
@@ -138,20 +133,12 @@ void
 CircleNode::setPie(const bool& pie)
 {
     _pie = pie;
-    rebuild();
+    rebuildGeometry();
 }
 
 void
-CircleNode::rebuild()
+CircleNode::rebuildGeometry()
 {
-    std::string currentDecoration = getDecoration();
-    clearDecoration();
-
-    // Reset this node.
-    osgEarth::clearChildren( this );
-    osgEarth::clearChildren( _xform.get() );
-    this->addChild( _xform.get() );
-
     // construct a local-origin circle.
     GeometryFactory factory;
     Geometry* geom = NULL;
@@ -163,22 +150,11 @@ CircleNode::rebuild()
     {
         geom = factory.createArc(osg::Vec3d(0,0,0), _radius, _arcStart, _arcEnd, _numSegments, 0L, _pie);
     }
+
     if ( geom )
     {
-        GeometryCompiler compiler;
-        osg::ref_ptr<Feature> feature = new Feature(geom, 0L); //todo: consider the SRS
-        osg::Node* node = compiler.compile( feature.get(), _style, FilterContext(0L) );
-        if ( node )
-        {
-            _xform->addChild( node );
-            this->replaceChild( _xform.get(), applyAltitudePolicy(_xform.get(), _style) );
-        }
-
-        applyGeneralSymbology( _style );
-        setLightingIfNotSet( false );
+        setGeometry( geom );        
     }
-
-    setDecoration( currentDecoration );
 }
 
 
@@ -190,27 +166,22 @@ OSGEARTH_REGISTER_ANNOTATION( circle, osgEarth::Annotation::CircleNode );
 CircleNode::CircleNode(MapNode*              mapNode,
                        const Config&         conf,
                        const osgDB::Options* dbOptions) :
-LocalizedNode( mapNode, conf ),
+LocalGeometryNode( mapNode, conf, dbOptions ),
 _radius      ( 1.0, Units::KILOMETERS ),
 _numSegments ( 0 )
 {
-    _xform = new osg::MatrixTransform();
-
-    conf.getObjIfSet( "radius", _radius );
-    conf.getObjIfSet( "style",  _style );
+    conf.getObjIfSet( "radius",       _radius );
     conf.getIfSet   ( "num_segments", _numSegments );
-
-    rebuild();
+    initCircleNode();
 }
 
 Config
 CircleNode::getConfig() const
 {
-    Config conf = LocalizedNode::getConfig();
+    Config conf = LocalGeometryNode::getConfig();
     conf.key() = "circle";
 
     conf.addObj( "radius", _radius );
-    conf.addObj( "style",  _style );
 
     if ( _numSegments != 0 )
         conf.add( "num_segments", _numSegments );
diff --git a/src/osgEarthAnnotation/Common b/src/osgEarthAnnotation/Common
index a876573..bfb920c 100644
--- a/src/osgEarthAnnotation/Common
+++ b/src/osgEarthAnnotation/Common
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthAnnotation/Decoration b/src/osgEarthAnnotation/Decoration
index e6b4a44..5df1d5e 100644
--- a/src/osgEarthAnnotation/Decoration
+++ b/src/osgEarthAnnotation/Decoration
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
@@ -29,6 +29,7 @@ namespace osgEarth { namespace Annotation
 {	
     using namespace osgEarth;
 
+#if 0
     //-----------------------------------------------------------------------
 
     class OSGEARTHANNO_EXPORT Decoration : public osg::Referenced
@@ -43,8 +44,7 @@ namespace osgEarth { namespace Annotation
 
     public:
         virtual bool apply(class AnnotationNode& node, bool enable);
-        virtual bool apply(class LocalizedNode&  node, bool enable);
-        virtual bool apply(class OrthoNode&      node, bool enable);
+        virtual bool apply(class GeoPositionNode& node, bool enable);
     };
 
     //-----------------------------------------------------------------------
@@ -113,6 +113,7 @@ namespace osgEarth { namespace Annotation
         virtual bool apply(osg::Group* attachPoint, bool enable);
     };
 
+#endif
 
 } } // namespace osgEarth::Annotation
 
diff --git a/src/osgEarthAnnotation/Decoration.cpp b/src/osgEarthAnnotation/Decoration.cpp
index e923685..451e538 100644
--- a/src/osgEarthAnnotation/Decoration.cpp
+++ b/src/osgEarthAnnotation/Decoration.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
@@ -24,14 +24,13 @@
 
 #include <osgEarthAnnotation/AnnotationUtils>
 #include <osgEarthAnnotation/AnnotationNode>
-#include <osgEarthAnnotation/LocalizedNode>
-#include <osgEarthAnnotation/OrthoNode>
+#include <osgEarthAnnotation/GeoPositionNode>
 #include <osgEarthAnnotation/LabelNode>
 #include <osgEarthAnnotation/PlaceNode>
 #include <osgEarthAnnotation/TrackNode>
 
 using namespace osgEarth::Annotation;
-
+#if 0
 //---------------------------------------------------------------------------
 
 void
@@ -56,13 +55,7 @@ Decoration::apply(class AnnotationNode& node, bool enable)
 }
 
 bool
-Decoration::apply(class LocalizedNode& node, bool enable)
-{ 
-    return apply(static_cast<AnnotationNode&>(node), enable);
-}
-
-bool
-Decoration::apply(class OrthoNode& node, bool enable)
+Decoration::apply(class GeoPositionNode& node, bool enable)
 {
     return apply(static_cast<AnnotationNode&>(node), enable);
 }
@@ -110,3 +103,4 @@ InjectionDecoration::apply(osg::Group* ap, bool enable)
     }
     return false;
 }
+#endif
\ No newline at end of file
diff --git a/src/osgEarthAnnotation/Draggers b/src/osgEarthAnnotation/Draggers
index 53d90cc..2079ccc 100644
--- a/src/osgEarthAnnotation/Draggers
+++ b/src/osgEarthAnnotation/Draggers
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
@@ -23,6 +23,7 @@
 #define OSGEARTH_DRAGGERS_H
 
 #include <osgEarthAnnotation/Common>
+#include <osgEarthAnnotation/GeoPositionNode>
 #include <osgEarth/GeoData>
 #include <osgEarth/TileKey>
 #include <osgEarth/MapNodeObserver>
@@ -39,7 +40,12 @@ namespace osgEarth {
 
 namespace osgEarth { namespace Annotation
 {
-    class OSGEARTHANNO_EXPORT Dragger : public osg::MatrixTransform, public MapNodeObserver
+    /**
+     * Dragger is a handle you can use to control things in the scene.
+     * You drag it around with the mouse and it fires PositionChangedCallback's
+     * that you can listen to to repond to.
+     */
+    class OSGEARTHANNO_EXPORT Dragger : public GeoPositionNode
     {
     public:
         /**
@@ -65,62 +71,59 @@ namespace osgEarth { namespace Annotation
         /** dtor */
         virtual ~Dragger();
 
+        /** Sets the map position of the dragger, optionally firing a PositionChanged event. */
+        void setPosition(const osgEarth::GeoPoint& position, bool fireEvents);
+
+        /** Is the user currently dragging? */
         bool getDragging() const;
 
+        /** Is the mouse hovering over this dragger? */
         bool getHovered() const;
 
-        const osgEarth::GeoPoint& getPosition() const;
-
-        void setPosition( const osgEarth::GeoPoint& position, bool fireEvents=true);
-
+        /** Mod key to require to activate the dragget */
         void setModKeyMask(int mask) { _modKeyMask = mask; }
-
         int getModKeyMask() const { return _modKeyMask; }
 
+        /** Drag mode */
         void setDefaultDragMode(const DragMode& mode) { _defaultMode = mode; }
-
         DragMode& getDefaultDragMode() { return _defaultMode; }
 
+        /** Minimum vertical distance for vertical dragging */
         void setVerticalMinimum(double min) { _verticalMinimum = min; }
-
         double getVerticalMinimim() const { return _verticalMinimum; }
-
-
-        void updateTransform(osg::Node* patch = 0);
-
+        
+        /** Runs when the mouse intersects/hovers over the dragger */
         virtual void enter();
 
+        /** Runs when the mouse leaves the dragger */
         virtual void leave();
 
+        /** Sets the main color of the dragger */
         virtual void setColor( const osg::Vec4f& color ) =0;
 
+        /** Sets the color to use when the dragger is entered */
         virtual void setPickColor( const osg::Vec4f& color ) =0;
 
+        /** Add a callback that runs whenever the user moves the dragger */
         void addPositionChangedCallback( PositionChangedCallback* callback );
 
+        /** Remove a callback. */
         void removePositionChangedCallback( PositionChangedCallback* callback );
 
-        virtual void traverse(osg::NodeVisitor& nv);        
-
-        virtual void reclamp( const TileKey& key, osg::Node* tile, const Terrain* terrain );
-
 
-    public: // MapNodeObserver
+    public: // GeoPositionNode
 
-        virtual void setMapNode( MapNode* mapNode );
+        virtual void setPosition(const GeoPoint& point);
 
-        virtual MapNode* getMapNode() { return _mapNode.get(); }
+    public: // osg::Node
 
+        virtual void traverse(osg::NodeVisitor& nv);
 
     protected:
         virtual bool handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa);
         void setHover( bool hovered);
         void firePositionChanged();
-
-        osg::ref_ptr< TerrainCallback > _autoClampCallback;
-
-        osg::observer_ptr< MapNode > _mapNode;
-        osgEarth::GeoPoint _position;
+        
         bool _dragging;
         bool _hovered;
         PositionChangedCallbackList _callbacks;
@@ -161,8 +164,6 @@ namespace osgEarth { namespace Annotation
     protected:
 
         void updateColor();
-
-        osg::MatrixTransform* _scaler;
         osg::ShapeDrawable* _shapeDrawable;
         osg::Vec4f _pickColor;
         osg::Vec4f _color;
diff --git a/src/osgEarthAnnotation/Draggers.cpp b/src/osgEarthAnnotation/Draggers.cpp
index 500ba0a..74de87f 100644
--- a/src/osgEarthAnnotation/Draggers.cpp
+++ b/src/osgEarthAnnotation/Draggers.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
@@ -20,7 +20,11 @@
 * along with this program.  If not, see <http://www.gnu.org/licenses/>
 */
 #include <osgEarthAnnotation/Draggers>
+#include <osgEarthAnnotation/AnnotationUtils>
+#include <osgEarthAnnotation/GeoPositionNodeAutoScaler>
+
 #include <osgEarth/MapNode>
+#include <osgEarth/GeometryClamper>
 #include <osgEarth/IntersectionPicker>
 
 #include <osg/AutoTransform>
@@ -38,25 +42,10 @@
 using namespace osgEarth;
 using namespace osgEarth::Annotation;
 
-struct ClampDraggerCallback : public TerrainCallback
-{
-    ClampDraggerCallback( Dragger* dragger ):
-        _dragger( dragger )
-    {
-        //nop
-    }
-
-    void onTileAdded( const TileKey& key, osg::Node* tile, osgEarth::TerrainCallbackContext& context )
-    {    
-        _dragger->reclamp( key, tile, context.getTerrain() );
-    }
-
-    Dragger* _dragger;
-};
-
 /**********************************************************/
+
 Dragger::Dragger( MapNode* mapNode, int modKeyMask, const DragMode& defaultMode ):
-_position( mapNode->getMapSRS(), 0,0,0, ALTMODE_RELATIVE),
+GeoPositionNode( mapNode ),
 _dragging(false),
 _hovered(false),
 _modKeyMask(modKeyMask),
@@ -66,10 +55,12 @@ _verticalMinimum(0.0)
 {    
     setNumChildrenRequiringEventTraversal( 1 );
 
-    _autoClampCallback = new ClampDraggerCallback( this );
+    //_clampCallback = new ClampDraggerCallback( this );
     _projector = new osgManipulator::LineProjector;
 
-    setMapNode( mapNode );
+    //setMapNode( mapNode );
+
+    this->getOrCreateStateSet()->setRenderBinDetails(50, "DepthSortedBin");
 }
 
 Dragger::~Dragger()
@@ -77,27 +68,6 @@ Dragger::~Dragger()
     setMapNode( 0L );
 }
 
-void
-Dragger::setMapNode( MapNode* mapNode )
-{
-    MapNode* oldMapNode = getMapNode();
-
-    if ( oldMapNode != mapNode )
-    {
-        if ( oldMapNode && _autoClampCallback.valid() )
-        {
-            oldMapNode->getTerrain()->removeTerrainCallback( _autoClampCallback.get() );
-        }
-
-        _mapNode = mapNode;
-
-        if ( _mapNode.valid() && _autoClampCallback.valid() )
-        {            
-            _mapNode->getTerrain()->addTerrainCallback( _autoClampCallback.get() );
-        }
-    }
-}
-
 bool Dragger::getDragging() const
 {
     return _dragging;
@@ -108,47 +78,23 @@ bool Dragger::getHovered() const
     return _hovered;
 }
 
-const GeoPoint& Dragger::getPosition() const
+void Dragger::setPosition(const GeoPoint& position)
 {
-    return _position;
+    Dragger::setPosition( position, true );
 }
 
-void Dragger::setPosition( const GeoPoint& position, bool fireEvents)
+void Dragger::setPosition(const GeoPoint& position, bool fireEvents)
 {
-    if (_position != position)
-    {
-        _position = position;
-        updateTransform();
-
-        if ( fireEvents )
-            firePositionChanged();
-    }
+    GeoPositionNode::setPosition( position );
+    if ( fireEvents )
+        firePositionChanged();
 }
 
 void Dragger::firePositionChanged()
 {
     for( PositionChangedCallbackList::iterator i = _callbacks.begin(); i != _callbacks.end(); i++ )
     {
-        i->get()->onPositionChanged(this, _position);
-    }
-}
-
-void Dragger::updateTransform(osg::Node* patch)
-{
-    if ( getMapNode() )
-    {
-        osg::Matrixd matrix;
-        
-        GeoPoint mapPoint( _position );
-        mapPoint = mapPoint.transform( _mapNode->getMapSRS() );
-        if (!mapPoint.makeAbsolute( getMapNode()->getTerrain() ))
-        {
-            OE_INFO << LC << "Failed to clamp dragger" << std::endl;
-            return;            
-        }
-
-        mapPoint.createLocalToWorld( matrix );
-        setMatrix( matrix );
+        i->get()->onPositionChanged(this, getPosition());
     }
 }
 
@@ -188,7 +134,7 @@ void Dragger::traverse(osg::NodeVisitor& nv)
                 ea->setHandled(true);
         }
     }
-    osg::MatrixTransform::traverse(nv);
+    GeoPositionNode::traverse( nv );
 }
 
 bool Dragger::handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa)
@@ -197,7 +143,7 @@ bool Dragger::handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter&
 
     osgViewer::View* view = dynamic_cast<osgViewer::View*>(&aa);
     if (!view) return false;
-    if (!_mapNode.valid()) return false;
+    if (!getMapNode()) return false;
 
     if (ea.getEventType() == osgGA::GUIEventAdapter::PUSH)
     {
@@ -206,6 +152,8 @@ bool Dragger::handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter&
 
         if ( picker.pick( ea.getX(), ea.getY(), hits ) )
         {
+            const GeoPoint& position = getPosition();
+
             _dragging = true;
 
             //Check for and handle vertical dragging if necessary
@@ -218,11 +166,11 @@ bool Dragger::handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter&
 
               // set movement range
               // TODO: values 0.0 and 300000.0 are rather experimental
-              GeoPoint posStart(_position.getSRS(), _position.x(), _position.y(), 0.0, ALTMODE_ABSOLUTE);
+              GeoPoint posStart(position.getSRS(), position.x(), position.y(), 0.0, ALTMODE_ABSOLUTE);
               osg::Vec3d posStartXYZ;
               posStart.toWorld(posStartXYZ);
 
-              GeoPoint posEnd(_position.getSRS(), _position.x(), _position.y(), 300000.0, ALTMODE_ABSOLUTE);
+              GeoPoint posEnd(position.getSRS(), position.x(), position.y(), 300000.0, ALTMODE_ABSOLUTE);
               osg::Vec3d posEndXYZ;
               posEnd.toWorld(posEndXYZ);
 
@@ -232,6 +180,9 @@ bool Dragger::handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter&
               osgUtil::LineSegmentIntersector::Intersections intersections;
               osg::Node::NodeMask intersectionMask = 0xffffffff;
               osgViewer::View* view = dynamic_cast<osgViewer::View*>(&aa);
+              if ( !view )
+                  return true;
+
               if (view->computeIntersections(ea.getX(),ea.getY(),intersections, intersectionMask))
               {
                   for (osgUtil::LineSegmentIntersector::Intersections::iterator hitr = intersections.begin(); hitr != intersections.end(); ++hitr)
@@ -247,7 +198,7 @@ bool Dragger::handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter&
                           Dragger* dragger = dynamic_cast<Dragger*>(*itr);
                           if (dragger==this)
                           {
-                            draggerFound = true;
+                              draggerFound = true;
                               osg::Camera *rootCamera = view->getCamera();
                               osg::NodePath nodePath = _pointer._hitList.front().first;
                               osg::NodePath::reverse_iterator ritr;
@@ -298,9 +249,11 @@ bool Dragger::handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter&
 
             if (_projector->project(_pointer, _startProjectedPoint)) 
             {
+                const GeoPoint& position = getPosition();
+
                 //Get the absolute mapPoint that they've drug it to.
                 GeoPoint projectedPos;
-                projectedPos.fromWorld(_position.getSRS(), _startProjectedPoint);
+                projectedPos.fromWorld(position.getSRS(), _startProjectedPoint);
 
                 // make sure point is not dragged down below
                 // TODO: think of a better solution / HeightAboveTerrain performance issues?
@@ -308,7 +261,7 @@ bool Dragger::handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter&
                 {
                     //If the current position is relative, we need to convert the absolute world point to relative.
                     //If the point is absolute then just emit the absolute point.
-                    if (_position.altitudeMode() == ALTMODE_RELATIVE)
+                    if (position.altitudeMode() == ALTMODE_RELATIVE)
                     {
                         projectedPos.transformZ(ALTMODE_RELATIVE, getMapNode()->getTerrain());
                     }
@@ -326,16 +279,17 @@ bool Dragger::handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter&
             osg::Vec3d world;
             if ( getMapNode() && getMapNode()->getTerrain()->getWorldCoordsUnderMouse(view, ea.getX(), ea.getY(), world) )
             {
+                const GeoPoint& position = getPosition();
+
                 //Get the absolute mapPoint that they've drug it to.
                 GeoPoint mapPoint;
                 mapPoint.fromWorld( getMapNode()->getMapSRS(), world );
-                //_mapNode->getMap()->worldPointToMapPoint(world, mapPoint);
 
                 //If the current position is relative, we need to convert the absolute world point to relative.
                 //If the point is absolute then just emit the absolute point.
-                if (_position.altitudeMode() == ALTMODE_RELATIVE)
+                if (position.altitudeMode() == ALTMODE_RELATIVE)
                 {
-                    mapPoint.alt() = _position.alt();
+                    mapPoint.alt() = position.alt();
                     mapPoint.altitudeMode() = ALTMODE_RELATIVE;
                 }
 
@@ -380,18 +334,22 @@ void Dragger::setHover( bool hovered)
     }
 }
 
-void Dragger::reclamp( const TileKey& key, osg::Node* tile, const Terrain* terrain )
-{            
-    GeoPoint p;
-    _position.transform( key.getExtent().getSRS(), p );
-    // first verify that the control position intersects the tile:
-    if ( key.getExtent().contains( p.x(), p.y() ) )
+namespace
+{
+    struct DC : public osg::Drawable::DrawCallback
     {
-        updateTransform( tile );
-    }
-}
+        void drawImplementation(osg::RenderInfo& ri, const osg::Drawable* drawable) const {
+            osg::Matrix mvm = ri.getState()->getModelViewMatrix();
+            osg::Matrix pm = ri.getState()->getProjectionMatrix();
+            double l, r, b, t, n, f;
+            pm.getFrustum(l, r, b, t, n, f);            
 
+            ri.getState()->applyModelViewMatrix( new osg::RefMatrix(pm) );            
 
+            drawable->drawImplementation( ri );
+        }
+    };
+}
 
 /**********************************************************/
 
@@ -399,13 +357,14 @@ SphereDragger::SphereDragger(MapNode* mapNode):
 Dragger(mapNode),
 _pickColor(1.0f, 1.0f, 0.0f, 1.0f),
 _color(0.0f, 1.0f, 0.0f, 1.0f),
-_size( 5.0f )
+_size( 5.0 )
 {
     //Disable culling
     setCullingActive( false );
 
     //Build the handle
-    osg::Sphere* shape = new osg::Sphere(osg::Vec3(0,0,0), 1.0f);   
+    osg::Sphere* shape = new osg::Sphere(osg::Vec3(0,0,0), _size);
+
     osg::Geode* geode = new osg::Geode();
     _shapeDrawable = new osg::ShapeDrawable( shape );    
     _shapeDrawable->setDataVariance( osg::Object::DYNAMIC );
@@ -414,15 +373,10 @@ _size( 5.0f )
     geode->getOrCreateStateSet()->setMode(GL_DEPTH_TEST, osg::StateAttribute::OFF);
     geode->getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
 
-    _scaler = new osg::MatrixTransform;
-    _scaler->setMatrix( osg::Matrixd::scale( _size, _size, _size ));
-    _scaler->addChild( geode );
-
-    osg::AutoTransform* at = new osg::AutoTransform;
-    at->setAutoScaleToScreen( true );
-    at->addChild( _scaler );
-    addChild( at );
+    getPositionAttitudeTransform()->addChild( geode );
 
+    this->addCullCallback( new GeoPositionNodeAutoScaler() );
+    
     updateColor();
 }
 
@@ -464,7 +418,9 @@ void SphereDragger::setSize(float size)
     if (_size != size)
     {
         _size = size;
-        _scaler->setMatrix( osg::Matrixd::scale( _size, _size, _size ));
+        _shapeDrawable->setShape( new osg::Sphere(osg::Vec3f(0,0,0), _size) );
+        _shapeDrawable->setColor( _color );
+        //getPositionAttitudeTransform()->setScale(osg::Vec3d(_size,_size,_size));
     }
 }
 
diff --git a/src/osgEarthAnnotation/EllipseNode b/src/osgEarthAnnotation/EllipseNode
index 1e4481c..72e9994 100644
--- a/src/osgEarthAnnotation/EllipseNode
+++ b/src/osgEarthAnnotation/EllipseNode
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
@@ -23,7 +23,7 @@
 #ifndef OSGEARTH_ANNOTATION_ELLIPSE_NODE_H
 #define OSGEARTH_ANNOTATION_ELLIPSE_NODE_H 1
 
-#include <osgEarthAnnotation/LocalizedNode>
+#include <osgEarthAnnotation/LocalGeometryNode>
 #include <osgEarthSymbology/Style>
 #include <osgEarth/Units>
 #include <osgEarth/MapNode>
@@ -36,7 +36,7 @@ namespace osgEarth { namespace Annotation
     /** 
      * Renders an ellipse that can drape on a MapNode terrain.    
      */
-    class OSGEARTHANNO_EXPORT EllipseNode : public LocalizedNode
+    class OSGEARTHANNO_EXPORT EllipseNode : public LocalGeometryNode
     {
     public:
         META_AnnotationNode( osgEarthAnnotation, EllipseNode );
@@ -113,16 +113,6 @@ namespace osgEarth { namespace Annotation
         void setNumSegments(unsigned int numSegments );
 
         /**
-         * Gets the style
-         */
-        const Style& getStyle() const;
-
-        /**
-         * Sets the style
-         */
-        void setStyle( const Style& style );
-
-        /**
          * Gets the start degrees of this (arc) circle
          */
         const Angle& getArcStart(void) const;
@@ -158,18 +148,14 @@ namespace osgEarth { namespace Annotation
         virtual Config getConfig() const;
 
 
-    public: // LocalizedNode
-
-        osg::MatrixTransform* getTransform() { return _xform.get(); }
-
-
     private:
         EllipseNode() { }
         EllipseNode(const EllipseNode& rhs, const osg::CopyOp& op) { }
 
-        void rebuild();
+        void rebuildGeometry();
+
+        void initEllipseNode();
         
-        Style _style;
         Angle _rotationAngle;
         Distance _radiusMajor;
         Distance _radiusMinor;
@@ -177,7 +163,6 @@ namespace osgEarth { namespace Annotation
         Angle _arcEnd;
         bool  _pie;
         unsigned int _numSegments;
-        osg::ref_ptr<osg::MatrixTransform> _xform;
     };
 
 } } // namespace osgEarth::Annotation
diff --git a/src/osgEarthAnnotation/EllipseNode.cpp b/src/osgEarthAnnotation/EllipseNode.cpp
index 96ca915..24c86d1 100644
--- a/src/osgEarthAnnotation/EllipseNode.cpp
+++ b/src/osgEarthAnnotation/EllipseNode.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
@@ -21,6 +21,7 @@
 */
 #include <osgEarthAnnotation/EllipseNode>
 #include <osgEarthAnnotation/AnnotationRegistry>
+#include <osgEarthAnnotation/AnnotationUtils>
 #include <osgEarthFeatures/GeometryCompiler>
 #include <osgEarthSymbology/GeometryFactory>
 #include <osgEarth/DrapeableNode>
@@ -42,31 +43,24 @@ EllipseNode::EllipseNode(MapNode*          mapNode,
                          const Angle&      arcStart,
                          const Angle&      arcEnd,
                          const bool        pie) :
-LocalizedNode ( mapNode, position ),
+LocalGeometryNode( mapNode ),
 _radiusMajor  ( radiusMajor ),
 _radiusMinor  ( radiusMinor ),
 _rotationAngle( rotationAngle ),
-_style        ( style ),
 _arcStart     ( arcStart ),
 _arcEnd       ( arcEnd ),
 _pie          ( pie ),
 _numSegments  ( 0 )
 {
-    _xform = new osg::MatrixTransform();
-    rebuild();
-}
-
-const Style&
-EllipseNode::getStyle() const
-{
-    return _style;
+    initEllipseNode();
+    setStyle( style );
+    setPosition( position );
 }
 
 void
-EllipseNode::setStyle( const Style& style )
+EllipseNode::initEllipseNode()
 {
-    _style = style;
-    rebuild();
+    rebuildGeometry();
 }
 
 unsigned int
@@ -81,7 +75,7 @@ EllipseNode::setNumSegments(unsigned int numSegments )
     if (_numSegments != numSegments )
     {
         _numSegments = numSegments;
-        rebuild();
+        rebuildGeometry();
     }
 }
 
@@ -118,7 +112,7 @@ EllipseNode::setRadii( const Linear& radiusMajor, const Linear& radiusMinor )
     {
         _radiusMajor = radiusMajor;
         _radiusMinor = radiusMinor;
-        rebuild();
+        rebuildGeometry();
     }
 }
 
@@ -134,7 +128,7 @@ EllipseNode::setRotationAngle(const Angular& rotationAngle)
     if (_rotationAngle != rotationAngle)
     {
         _rotationAngle = rotationAngle;
-        rebuild();
+        rebuildGeometry();
     }
 }
 const Angle&
@@ -147,7 +141,7 @@ void
 EllipseNode::setArcStart(const Angle& arcStart)
 {
     _arcStart = arcStart;
-    rebuild();
+    rebuildGeometry();
 }
 
 const Angle&
@@ -160,7 +154,7 @@ void
 EllipseNode::setArcEnd(const Angle& arcEnd)
 {
     _arcEnd = arcEnd;
-    rebuild();
+    rebuildGeometry();
 }
 
 const bool&
@@ -173,23 +167,16 @@ void
 EllipseNode::setPie(const bool& pie)
 {
 	_pie = pie;
-	rebuild();
+	rebuildGeometry();
 }
 
 void
-EllipseNode::rebuild()
+EllipseNode::rebuildGeometry()
 {
-    std::string currentDecoration = getDecoration();
-    clearDecoration();
-
-    //Remove all children from this node
-    osgEarth::clearChildren( this );
-    osgEarth::clearChildren( _xform.get() );
-    this->addChild( _xform.get() );
-
     // construct a local-origin ellipse.
     GeometryFactory factory;
-    Geometry* geom = NULL;
+
+    osg::ref_ptr<Geometry> geom;
 
     if (std::abs(_arcEnd.as(Units::DEGREES) - _arcStart.as(Units::DEGREES)) >= 360.0)
     {
@@ -199,22 +186,10 @@ EllipseNode::rebuild()
     {
         geom = factory.createEllipticalArc(osg::Vec3d(0,0,0), _radiusMajor, _radiusMinor, _rotationAngle, _arcStart, _arcEnd, _numSegments, 0L, _pie);
     }
-    if ( geom )
+    if ( geom.valid() )
     {
-        GeometryCompiler compiler;
-        osg::ref_ptr<Feature> feature = new Feature(geom, 0L); //todo: consider the SRS
-        osg::Node* node = compiler.compile( feature.get(), _style, FilterContext(0L) );
-        if ( node )
-        {
-            _xform->addChild( node );
-            this->replaceChild( _xform.get(), applyAltitudePolicy(_xform.get(), _style) );
-        }
-
-        applyGeneralSymbology( _style );
-        setLightingIfNotSet( false );
+        setGeometry( geom.get() );
     }
-
-    setDecoration( currentDecoration );
 }
 
 
@@ -227,30 +202,26 @@ OSGEARTH_REGISTER_ANNOTATION( ellipse, osgEarth::Annotation::EllipseNode );
 EllipseNode::EllipseNode(MapNode*              mapNode,
                          const Config&         conf,
                          const osgDB::Options* dbOptions) :
-LocalizedNode( mapNode, conf ),
+LocalGeometryNode(mapNode, conf, dbOptions),
 _numSegments ( 0 )
 {
-    _xform = new osg::MatrixTransform();
-
     conf.getObjIfSet( "radius_major", _radiusMajor );
     conf.getObjIfSet( "radius_minor", _radiusMinor );
     conf.getObjIfSet( "rotation", _rotationAngle );
-    conf.getObjIfSet( "style",  _style );
     conf.getIfSet   ( "num_segments", _numSegments );
 
-    rebuild();
+    initEllipseNode();
 }
 
 Config
 EllipseNode::getConfig() const
 {
-    Config conf = LocalizedNode::getConfig();
+    Config conf = LocalGeometryNode::getConfig();
     conf.key() = "ellipse";
 
     conf.addObj( "radius_major", _radiusMajor );
     conf.addObj( "radius_minor", _radiusMinor );
     conf.addObj( "rotation", _rotationAngle );
-    conf.addObj( "style", _style );
 
     if ( _numSegments != 0 )
         conf.add( "num_segments", _numSegments );
diff --git a/src/osgEarthAnnotation/Export b/src/osgEarthAnnotation/Export
index 099f37b..f54cd64 100644
--- a/src/osgEarthAnnotation/Export
+++ b/src/osgEarthAnnotation/Export
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthAnnotation/FeatureEditing b/src/osgEarthAnnotation/FeatureEditing
index b7d560c..22d8f99 100644
--- a/src/osgEarthAnnotation/FeatureEditing
+++ b/src/osgEarthAnnotation/FeatureEditing
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthAnnotation/FeatureEditing.cpp b/src/osgEarthAnnotation/FeatureEditing.cpp
index aaf8f68..5e9db15 100644
--- a/src/osgEarthAnnotation/FeatureEditing.cpp
+++ b/src/osgEarthAnnotation/FeatureEditing.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthAnnotation/FeatureNode b/src/osgEarthAnnotation/FeatureNode
index 5362ab0..22b2f1b 100644
--- a/src/osgEarthAnnotation/FeatureNode
+++ b/src/osgEarthAnnotation/FeatureNode
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
@@ -24,6 +24,7 @@
 
 #include <osgEarthAnnotation/AnnotationNode>
 #include <osgEarth/MapNode>
+#include <osgEarth/GeometryClamper>
 #include <osgEarthSymbology/Style>
 #include <osgEarthFeatures/Feature>
 #include <osgEarthFeatures/GeometryCompiler>
@@ -52,7 +53,8 @@ namespace osgEarth { namespace Annotation
             MapNode* mapNode, 
             Feature* feature,
             const Style& style = Style(),
-            const GeometryCompilerOptions& options = GeometryCompilerOptions() );
+            const GeometryCompilerOptions& options = GeometryCompilerOptions(),
+            StyleSheet* styleSheet = 0);
 
         /**
          * Constructs a new FeatureNode from a FeatureList
@@ -61,14 +63,15 @@ namespace osgEarth { namespace Annotation
             MapNode* mapNode, 
             FeatureList& features,
             const Style& style = Style(),
-            const GeometryCompilerOptions& options = GeometryCompilerOptions() );
+            const GeometryCompilerOptions& options = GeometryCompilerOptions(), 
+            StyleSheet* styleSheet = 0);
 
         virtual ~FeatureNode() { }
 
          /**
          * Gets the list of features
          */
-        FeatureList& getFeatures() { return _features; };
+        FeatureList& getFeatures() { return _features; }
 
         /**
          * Utility that lets you work on this FeatureNode as a single Feature instead of a list
@@ -81,14 +84,14 @@ namespace osgEarth { namespace Annotation
         void setFeature(Feature* feature);
 
         /**
-         * Get whether cluster culling is enabled on this FeatureNode
+         * Gets the StyleSheet for the session.
          */
-        bool getClusterCulling() const;
+        StyleSheet* getStyleSheet() const;
 
-        /*
-         * Sets whether cluster culling is enabled on this FeatureNode.
+        /**
+         * Sets the StyleSheet for the session.
          */
-        void setClusterCulling( bool clusterCulling );
+        void setStyleSheet(StyleSheet* styleSheet);
 
 
         /**
@@ -100,8 +103,6 @@ namespace osgEarth { namespace Annotation
 
     public: // AnnotationNode
 
-        virtual osg::Group* getAttachPoint();
-
         /**
          * Gets the Style for this FeatureNode.
          */
@@ -130,24 +131,28 @@ namespace osgEarth { namespace Annotation
         osg::Polytope                _featurePolytope;
         Style                        _style;
         bool                         _needsRebuild;
-        bool                         _clusterCulling;
         GeoExtent                    _extent;
-        osg::NodeCallback*           _clusterCullingCallback;
+
+        typedef TerrainCallbackAdapter<FeatureNode> ClampCallback;
+        osg::ref_ptr<ClampCallback> _clampCallback;
 
         osg::ref_ptr< osg::Node >    _compiled;
 
+        osg::ref_ptr< StyleSheet >   _styleSheet;
+
         FeatureNode() { }
         FeatureNode(const FeatureNode& rhs, const osg::CopyOp& op) { }
         
-        virtual void reclamp( const TileKey& key, osg::Node* tile, const Terrain* );
+        void clamp(const Terrain* terrain, osg::Node* patch);
 
         void build();
 
-        void updateClusterCulling();
+    public:
 
-        
-    private:
-        void clampMesh( osg::Node* terrainModel );
+        void onTileAdded(
+            const TileKey&          key, 
+            osg::Node*              tile, 
+            TerrainCallbackContext& context);
     };
 
 } } // namespace osgEarth::Annotation
diff --git a/src/osgEarthAnnotation/FeatureNode.cpp b/src/osgEarthAnnotation/FeatureNode.cpp
index b7c28d8..5ff3e5b 100644
--- a/src/osgEarthAnnotation/FeatureNode.cpp
+++ b/src/osgEarthAnnotation/FeatureNode.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
@@ -26,7 +26,6 @@
 
 #include <osgEarthFeatures/GeometryCompiler>
 #include <osgEarthFeatures/GeometryUtils>
-#include <osgEarthFeatures/MeshClamper>
 
 #include <osgEarthSymbology/AltitudeSymbol>
 
@@ -36,6 +35,8 @@
 #include <osgEarth/Utils>
 #include <osgEarth/Registry>
 #include <osgEarth/CullingUtils>
+#include <osgEarth/GeometryClamper>
+#include <osgEarth/TerrainEngineNode>
 
 #include <osg/BoundingSphere>
 #include <osg/Polytope>
@@ -50,61 +51,48 @@ using namespace osgEarth::Symbology;
 
 FeatureNode::FeatureNode(MapNode* mapNode,
                          Feature* feature,
-                         const Style& style,
-                         const GeometryCompilerOptions& options ) :
-AnnotationNode( mapNode ),
-_style        ( style ),
-_options      ( options ),
-_needsRebuild (true),
-_clusterCulling(true),
-_clusterCullingCallback(0)
+                         const Style& in_style,
+                         const GeometryCompilerOptions& options,
+                         StyleSheet* styleSheet) :
+AnnotationNode(),
+_options           ( options ),
+_needsRebuild      ( true ),
+_styleSheet        ( styleSheet )
 {
-    if (_style.empty() && feature->style().isSet())
+    _features.push_back( feature );
+
+    FeatureNode::setMapNode( mapNode );
+
+    Style style = in_style;
+    if (style.empty() && feature->style().isSet())
     {
-        _style = *feature->style();
+        style = *feature->style();
     }
 
-    _features.push_back( feature );
-    build();
+    setStyle( style );
 }
 
-FeatureNode::FeatureNode(MapNode* mapNode, 
+FeatureNode::FeatureNode(MapNode* mapNode,
                          FeatureList& features,
                          const Style& style,
-                         const GeometryCompilerOptions& options):
-AnnotationNode( mapNode ),
-_style        ( style ),
-_options      ( options ),
-_needsRebuild (true),
-_clusterCulling(true),
-_clusterCullingCallback(0)
+                         const GeometryCompilerOptions& options,
+                         StyleSheet* styleSheet):
+AnnotationNode(),
+_options        ( options ),
+_needsRebuild   ( true ),
+_styleSheet     ( styleSheet )
 {
     _features.insert( _features.end(), features.begin(), features.end() );
-    build();
-}
-
-bool
-FeatureNode::getClusterCulling() const
-{
-    return _clusterCulling;
-}
-
-void
-FeatureNode::setClusterCulling( bool clusterCulling)
-{
-    if (_clusterCulling != clusterCulling)
-    {
-        _clusterCulling = clusterCulling;
-        updateClusterCulling();
-    }
+    FeatureNode::setMapNode( mapNode );
+    setStyle( style );
 }
 
-
 void
 FeatureNode::build()
 {
-    // if there's a decoration, clear it out first.
-    this->clearDecoration();
+    if ( !_clampCallback.valid() )
+        _clampCallback = new ClampCallback(this);
+
     _attachPoint = 0L;
 
     // if there is existing geometry, kill it
@@ -120,19 +108,19 @@ FeatureNode::build()
 
     // compilation options.
     GeometryCompilerOptions options = _options;
-    
+
     // figure out what kind of altitude manipulation we need to perform.
     AnnotationUtils::AltitudePolicy ap;
     AnnotationUtils::getAltitudePolicy( style, ap );
 
     // If we're doing auto-clamping on the CPU, shut off compiler map clamping
     // clamping since it would be redundant.
-    // TODO: I think this is OBE now that we have "scene" clamping technique..
     if ( ap.sceneClamping )
     {
         options.ignoreAltitudeSymbol() = true;
     }
 
+
     osg::Node* node = _compiled.get();
     if (_needsRebuild || !_compiled.valid() )
     {
@@ -159,7 +147,7 @@ FeatureNode::build()
 
         // prep the compiler:
         GeometryCompiler compiler( options );
-        Session* session = new Session( getMapNode()->getMap() );
+        Session* session = new Session( getMapNode()->getMap(), _styleSheet.get() );
 
         FilterContext context( session, new FeatureProfile( _extent ), _extent );
 
@@ -175,9 +163,9 @@ FeatureNode::build()
             itr->get()->getWorldBound(getMapNode()->getMapSRS(), bs);
             bounds.expandBy(bs);
         }
+
         // The polytope will ensure we only clamp to intersecting tiles:
         Feature::getWorldBoundingPolytope(bounds, getMapNode()->getMapSRS(), _featurePolytope);
-
     }
 
     if ( node )
@@ -188,15 +176,13 @@ FeatureNode::build()
             node = AnnotationUtils::installTwoPassAlpha( node );
         }
 
-        //OE_NOTICE << GeometryUtils::geometryToGeoJSON( _feature->getGeometry() ) << std::endl;
-
         _attachPoint = new osg::Group();
         _attachPoint->addChild( node );
 
         // Draped (projected) geometry
         if ( ap.draping )
         {
-            DrapeableNode* d = new DrapeableNode( getMapNode() );
+            DrapeableNode* d = new DrapeableNode();
             d->addChild( _attachPoint );
             this->addChild( d );
         }
@@ -215,31 +201,29 @@ FeatureNode::build()
             }
         }
 
-        else 
+        else
         {
             this->addChild( _attachPoint );
 
-            // CPU-clamped geometry?
-            if ( ap.sceneClamping )
-            {
-                // save for later when we need to reclamp the mesh on the CPU
-                _altitude = style.get<AltitudeSymbol>();
-
-                // activate the terrain callback:
-                setCPUAutoClamping( true );
-
-                // set default lighting based on whether we are extruding:
-                setLightingIfNotSet( style.has<ExtrusionSymbol>() );
+            // set default lighting based on whether we are extruding:
+            setLightingIfNotSet( style.has<ExtrusionSymbol>() );
 
-                // do an initial clamp to get started.
-                clampMesh( getMapNode()->getTerrain()->getGraph() );
-            } 
+            applyRenderSymbology( style );
+        }
 
-            applyGeneralSymbology( style );
+        if ( getMapNode()->getTerrain() )
+        {
+            if ( ap.sceneClamping )
+            {
+                getMapNode()->getTerrain()->addTerrainCallback( _clampCallback.get() );
+                clamp( getMapNode()->getTerrain(), getMapNode()->getTerrain()->getGraph() );
+            }
+            else
+            {
+                getMapNode()->getTerrain()->removeTerrainCallback( _clampCallback.get() );
+            }
         }
     }
-
-    updateClusterCulling();
 }
 
 void
@@ -247,7 +231,11 @@ FeatureNode::setMapNode( MapNode* mapNode )
 {
     if ( getMapNode() != mapNode )
     {
+        if (_clampCallback.valid() && getMapNode() && getMapNode()->getTerrain())
+            getMapNode()->getTerrain()->removeTerrainCallback( _clampCallback.get() );
+
         AnnotationNode::setMapNode( mapNode );
+
         _needsRebuild = true;
         build();
     }
@@ -261,25 +249,24 @@ const Style& FeatureNode::getStyle() const
 void
 FeatureNode::setStyle(const Style& style)
 {
-    // Try to compare the styles and see if we can get away with not compiling the geometry again.
-    Style a = _style;
-    Style b = style;
-   
-    // If the only thing that has changed is the AltitudeSymbol, we don't need to worry about rebuilding the entire geometry again.
-    a.remove<AltitudeSymbol>();
-    b.remove<AltitudeSymbol>();
-    if (a.getConfig().toJSON() == b.getConfig().toJSON())
-    {
-        _needsRebuild = false;
-    }
-    else
-    {
-        _needsRebuild = true;
-    }
     _style = style;
+
+    AnnotationNode::setStyle( style );
+
+    _needsRebuild = true;
     build();
 }
 
+StyleSheet* FeatureNode::getStyleSheet() const
+{
+    return _styleSheet;
+}
+
+void FeatureNode::setStyleSheet(StyleSheet* styleSheet)
+{
+    _styleSheet = styleSheet;
+}
+
 Feature* FeatureNode::getFeature()
 {
     if (_features.size() == 1)
@@ -306,90 +293,36 @@ void FeatureNode::init()
     build();
 }
 
-osg::Group*
-FeatureNode::getAttachPoint()
-{
-    if ( !_attachPoint )
-        return 0L;
-
-    // first try to find a transform to go under:
-    osg::Group* xform = osgEarth::findTopMostNodeOfType<osg::Transform>(_attachPoint);
-    if ( xform )
-        return xform;
-
-    // failing that, use the artificial attach group we created.
-    return _attachPoint;
-}
-
-
 // This will be called by AnnotationNode when a new terrain tile comes in.
 void
-FeatureNode::reclamp( const TileKey& key, osg::Node* tile, const Terrain* terrain )
+FeatureNode::onTileAdded(const TileKey&          key,
+                         osg::Node*              tile,
+                         TerrainCallbackContext& context)
 {
-    if ( _featurePolytope.contains( tile->getBound() ) )
+    if ( !tile || _featurePolytope.contains( tile->getBound() ) )
     {
-        clampMesh( tile );
+        clamp( context.getTerrain(), tile );
     }
 }
 
 void
-FeatureNode::clampMesh( osg::Node* terrainModel )
+FeatureNode::clamp(const Terrain* terrain, osg::Node* patch)
 {
-    if ( getMapNode() )
+    if ( terrain && patch )
     {
-        double scale  = 1.0;
-        double offset = 0.0;
-        bool   relative = false;
+        const AltitudeSymbol* alt = getStyle().get<AltitudeSymbol>();
+        bool relative = alt && alt->clamping() == alt->CLAMP_RELATIVE_TO_TERRAIN && alt->technique() == alt->TECHNIQUE_SCENE;
 
-        if (_altitude.valid())
-        {
-            NumericExpression scaleExpr(_altitude->verticalScale().value());
-            NumericExpression offsetExpr(_altitude->verticalOffset().value());
-            scale = scaleExpr.eval();
-            offset = offsetExpr.eval();
-            relative = _altitude->clamping() == AltitudeSymbol::CLAMP_RELATIVE_TO_TERRAIN;
-        }
-
-        MeshClamper clamper( terrainModel, getMapNode()->getMapSRS(), getMapNode()->isGeocentric(), relative, scale, offset );
-        getAttachPoint()->accept( clamper );
+        GeometryClamper clamper;
+        clamper.setTerrainPatch( patch );
+        clamper.setTerrainSRS( terrain->getSRS() );
+        clamper.setPreserveZ( relative );
 
+        this->accept( clamper );
         this->dirtyBound();
     }
 }
 
-void
-FeatureNode::updateClusterCulling()
-{
-    // install a cluster culler.
-    if ( getMapNode()->isGeocentric() && _clusterCulling && !_clusterCullingCallback)
-    {
-        const GeoExtent& ccExtent = _extent;
-        if ( ccExtent.isValid() )
-        {
-            // if the extent is more than 90 degrees, bail
-            GeoExtent geodeticExtent = ccExtent.transform( ccExtent.getSRS()->getGeographicSRS() );
-            if ( geodeticExtent.width() < 90.0 && geodeticExtent.height() < 90.0 )
-            {
-                // get the geocentric tile center:
-                osg::Vec3d tileCenter;
-                ccExtent.getCentroid( tileCenter.x(), tileCenter.y() );
-
-                osg::Vec3d centerECEF;
-                ccExtent.getSRS()->transform( tileCenter, getMapNode()->getMapSRS()->getECEF(), centerECEF );
-                _clusterCullingCallback = ClusterCullingFactory::create2( this, centerECEF );
-                if ( _clusterCullingCallback )
-                    this->addCullCallback( _clusterCullingCallback );
-            }
-        }
-    }
-    else if (!_clusterCulling && _clusterCullingCallback)
-    {
-        this->removeCullCallback( _clusterCullingCallback );
-        _clusterCullingCallback = 0;
-    }
-}
-
-
 //-------------------------------------------------------------------
 
 OSGEARTH_REGISTER_ANNOTATION( feature, osgEarth::Annotation::FeatureNode );
@@ -398,7 +331,7 @@ OSGEARTH_REGISTER_ANNOTATION( feature, osgEarth::Annotation::FeatureNode );
 FeatureNode::FeatureNode(MapNode*              mapNode,
                          const Config&         conf,
                          const osgDB::Options* dbOptions ) :
-AnnotationNode( mapNode, conf )
+AnnotationNode(conf)
 {
     osg::ref_ptr<Geometry> geom;
     if ( conf.hasChild("geometry") )
@@ -408,7 +341,7 @@ AnnotationNode( mapNode, conf )
         if ( !geom.valid() )
             OE_WARN << LC << "Config is missing required 'geometry' element" << std::endl;
     }
-    
+
     osg::ref_ptr<const SpatialReference> srs;
     srs = SpatialReference::create( conf.value("srs"), conf.value("vdatum") );
     if ( !srs.valid() )
@@ -418,6 +351,8 @@ AnnotationNode( mapNode, conf )
 
     conf.getObjIfSet( "style", _style );
 
+    FeatureNode::setMapNode( mapNode );
+
     if ( srs.valid() && geom.valid() )
     {
         Feature* feature = new Feature(geom.get(), srs.get() );
@@ -433,7 +368,6 @@ AnnotationNode( mapNode, conf )
 Config
 FeatureNode::getConfig() const
 {
-    
     Config conf("feature");
 
     if ( !_features.empty() )
diff --git a/src/osgEarthAnnotation/GeoPositionNode b/src/osgEarthAnnotation/GeoPositionNode
new file mode 100644
index 0000000..ee178da
--- /dev/null
+++ b/src/osgEarthAnnotation/GeoPositionNode
@@ -0,0 +1,141 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+* Copyright 2016 Pelican Mapping
+* http://osgearth.org
+*
+* osgEarth is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* 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.
+*
+* You should have received a copy of the GNU Lesser General Public License
+* along with this program.  If not, see <http://www.gnu.org/licenses/>
+*/
+#ifndef OSGEARTH_ANNO_ORTHO_NODE_H
+#define OSGEARTH_ANNO_ORTHO_NODE_H 1
+
+#include <osgEarthAnnotation/AnnotationNode>
+#include <osgEarth/GeoTransform>
+#include <osgEarth/CullingUtils>
+#include <osg/PositionAttitudeTransform>
+
+namespace osgEarth { namespace Annotation
+{	
+    using namespace osgEarth;
+
+    /**
+     * Base class for an annotation node that is anchored to a GeoPoint on the map.
+     * Use getGeoTransform() to control the map position, and getPositionAttitudeTransform()
+     * to control the offsets in the local tangent plane at that location.
+     */
+    class OSGEARTHANNO_EXPORT GeoPositionNode : public AnnotationNode
+    {
+    public:
+        META_AnnotationNode( osgEarthAnnotation, GeoPositionNode );
+
+        /**
+         * Constructs an positional node
+         */
+        GeoPositionNode();
+
+        /**
+         * Constructs a positional with initial with a MapNode
+         */
+        GeoPositionNode(MapNode* mapNode);
+
+        /**
+         * Constructs an positional node that resides at an absolute position on the map
+         * @param mapNode  MapNode used to referenced the ortho node
+         * @param position Starting position
+         */
+        GeoPositionNode(MapNode* mapNode, const GeoPoint& position);
+
+        /** The anchor position */
+        virtual void setPosition(const GeoPoint& pos) { _geoxform->setPosition( pos ); dirty(); }
+        const GeoPoint& getPosition() const           { return _geoxform->getPosition(); }
+
+        /** Local XYZ offset */
+        virtual void setLocalOffset(const osg::Vec3f& pos) { _paxform->setPosition(pos); dirty(); }
+        const osg::Vec3d& getLocalOffset() const           { return _paxform->getPosition(); }
+
+        /** Local rotation */
+        virtual void setLocalRotation(const osg::Quat& rot) { _paxform->setAttitude(rot); dirty(); }
+        const osg::Quat& getLocalRotation() const           { return _paxform->getAttitude(); }
+
+        /** Scale */
+        virtual void setScale(const osg::Vec3f& scale) { _paxform->setScale(scale); dirty(); }
+        const osg::Vec3d& getScale() const             { return _paxform->getScale(); }
+
+        /**
+         * Access to the GeoTransform that positions this node.
+         */
+        GeoTransform* getGeoTransform() const { return _geoxform; }
+
+        /**
+         * Access to the PositionAttitudeTransform for local offsets and rotation
+         */
+        osg::PositionAttitudeTransform* getPositionAttitudeTransform() const { return _paxform; }
+
+        /**
+         * Enables or disables ray based occlusion culling
+         */
+        bool getOcclusionCulling() const;
+        void setOcclusionCulling( bool value );
+
+        /**
+         * Gets or sets the maximum altitude that the occlusion culling takes place.
+         */
+        double getOcclusionCullingMaxAltitude() const;
+        void setOcclusionCullingMaxAltitude( double occlusionCullingMaxAltitude );
+
+        /** Serialize. */
+        Config getConfig() const;
+
+
+    public: // AnnotationNode
+
+        virtual void applyStyle(const Style& style);
+
+    public: // MapNodeObserver
+
+        virtual void setMapNode( MapNode* mapNode );
+
+    protected:
+        /** virtual dtor */
+        virtual ~GeoPositionNode() { }
+
+        /** called when someone calls one of the set functions */
+        virtual void dirty() { }
+
+        virtual void setConfig(const Config&);
+
+    private:
+        GeoTransform*                   _geoxform;
+        osg::PositionAttitudeTransform* _paxform;
+        bool                            _occlusionCullingRequested;
+        optional< double >              _occlusionCullingMaxAltitude;
+        bool                            _horizonCullingRequested;
+
+        osg::ref_ptr< HorizonCullCallback >      _horizonCuller;
+        osg::ref_ptr< OcclusionCullingCallback > _occlusionCuller;
+
+        void init();
+
+    protected:
+        GeoPositionNode(MapNode* mapNode, const Config& conf);
+
+        // required by META_Node, but this object is not cloneable
+        GeoPositionNode(const GeoPositionNode& rhs, const osg::CopyOp& op =osg::CopyOp::DEEP_COPY_ALL);
+    };
+
+} } // namespace osgEarth::Annotation
+
+#endif // OSGEARTH_ANNO_LOCALIZED_NODE_H
diff --git a/src/osgEarthAnnotation/GeoPositionNode.cpp b/src/osgEarthAnnotation/GeoPositionNode.cpp
new file mode 100644
index 0000000..eda0c61
--- /dev/null
+++ b/src/osgEarthAnnotation/GeoPositionNode.cpp
@@ -0,0 +1,307 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+* Copyright 2016 Pelican Mapping
+* http://osgearth.org
+*
+* osgEarth is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* 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.
+*
+* You should have received a copy of the GNU Lesser General Public License
+* along with this program.  If not, see <http://www.gnu.org/licenses/>
+*/
+
+#include <osgEarthAnnotation/GeoPositionNode>
+#include <osgEarthAnnotation/AnnotationUtils>
+#include <osgEarthAnnotation/AnnotationSettings>
+#include <osgEarthSymbology/Color>
+#include <osgEarth/ThreadingUtils>
+#include <osgEarth/CullingUtils>
+#include <osgEarth/MapNode>
+#include <osgEarth/TerrainEngineNode>
+
+#include <osgText/Text>
+#include <osg/ComputeBoundsVisitor>
+#include <osgUtil/IntersectionVisitor>
+#include <osg/OcclusionQueryNode>
+#include <osg/Point>
+#include <osg/Depth>
+#include <osg/Switch>
+
+#define LC "[GeoPositionNode] "
+
+using namespace osgEarth;
+using namespace osgEarth::Annotation;
+
+#define DEFAULT_OCCLUSION_CULLING false
+#define DEFAULT_HORIZON_CULLING true
+
+GeoPositionNode::GeoPositionNode() :
+AnnotationNode(),
+_geoxform(0L),
+_paxform(0L),
+_occlusionCullingRequested( DEFAULT_OCCLUSION_CULLING ),
+_horizonCullingRequested( DEFAULT_HORIZON_CULLING )
+{
+    init();
+}
+
+GeoPositionNode::GeoPositionNode(MapNode* mapNode) :
+AnnotationNode(),
+_geoxform(0L),
+_paxform(0L),
+_occlusionCullingRequested( DEFAULT_OCCLUSION_CULLING ),
+_horizonCullingRequested( DEFAULT_HORIZON_CULLING )
+{
+    init();
+    GeoPositionNode::setMapNode( mapNode );
+}
+
+GeoPositionNode::GeoPositionNode(MapNode* mapNode, const GeoPoint& position ) :
+AnnotationNode(),
+_geoxform(0L),
+_paxform(0L),
+_occlusionCullingRequested( DEFAULT_OCCLUSION_CULLING ),
+_horizonCullingRequested( DEFAULT_HORIZON_CULLING )
+{
+    init();
+    GeoPositionNode::setMapNode( mapNode );
+    _geoxform->setPosition( position );
+}
+
+GeoPositionNode::GeoPositionNode(const GeoPositionNode& rhs, const osg::CopyOp& copy) :
+AnnotationNode(rhs, copy),
+_geoxform(0L),
+_paxform(0L),
+_occlusionCullingRequested( DEFAULT_OCCLUSION_CULLING ),
+_horizonCullingRequested( DEFAULT_HORIZON_CULLING )
+{
+    //nop - UNUSED
+}
+
+void
+GeoPositionNode::init()
+{    
+    _geoxform = new GeoTransform();
+    _geoxform->setAutoRecomputeHeights( true );
+    this->addChild( _geoxform );
+
+    _paxform = new osg::PositionAttitudeTransform();
+    _geoxform->addChild( _paxform );
+    
+    this->getOrCreateStateSet()->setMode( GL_LIGHTING, 0 );
+}
+
+void
+GeoPositionNode::setMapNode( MapNode* mapNode )
+{
+    MapNode* oldMapNode = getMapNode();
+    if ( oldMapNode != mapNode )
+    {
+        AnnotationNode::setMapNode( mapNode );
+
+        bool occlusionCullingRequested = _occlusionCullingRequested;
+        // the occlusion culler depends on the mapnode, so re-initialize it:
+        setOcclusionCulling( false );
+        if ( occlusionCullingRequested )
+        {
+            setOcclusionCulling( true );
+        }
+
+        if ( mapNode )
+            _geoxform->setTerrain( getMapNode()->getTerrain() );
+        else
+            _geoxform->setTerrain( 0L );
+    }
+}
+
+void
+GeoPositionNode::applyStyle(const Style& style)
+{
+    const TextSymbol* text = style.get<TextSymbol>();
+
+    // check for decluttering.
+    if ( text && text->declutter() == false )
+    {
+        setPriority( FLT_MAX );
+    }
+
+
+    // check for occlusion culling
+    if ( text && text->occlusionCull().isSet() )
+    {
+        setOcclusionCulling( *text->occlusionCull() );
+
+        if (text->occlusionCullAltitude().isSet())
+        {
+            setOcclusionCullingMaxAltitude( *text->occlusionCullAltitude() );
+        }
+    }
+
+    const IconSymbol* icon = style.get<IconSymbol>();
+
+    if ( icon && icon->declutter() == false )
+    {
+        setPriority( FLT_MAX );
+    }
+
+    // check for occlusion culling
+    if ( icon && icon->occlusionCull().isSet() )
+    {
+        this->setOcclusionCulling( *icon->occlusionCull() );
+
+        if (icon->occlusionCullAltitude().isSet())
+        {
+            setOcclusionCullingMaxAltitude( *icon->occlusionCullAltitude() );
+        }
+    }
+
+    // up the chain
+    AnnotationNode::applyStyle( style );
+}
+
+bool
+GeoPositionNode::getOcclusionCulling() const
+{
+    return _occlusionCullingRequested;
+}
+
+void
+GeoPositionNode::setOcclusionCulling( bool value )
+{
+    if (_occlusionCullingRequested != value)
+    {
+        _occlusionCullingRequested = value;
+
+        if ( _occlusionCullingRequested )
+        {
+            _occlusionCuller = new OcclusionCullingCallback( _geoxform );
+            _occlusionCuller->setMaxAltitude( getOcclusionCullingMaxAltitude() );
+            addCullCallback( _occlusionCuller.get()  );
+        }
+        else if (_occlusionCuller.valid())
+        {
+            removeCullCallback( _occlusionCuller.get() );
+            _occlusionCuller = 0;
+        }
+    }
+}
+
+double
+GeoPositionNode::getOcclusionCullingMaxAltitude() const
+{
+    if (_occlusionCullingMaxAltitude.isSet())
+    {
+        return *_occlusionCullingMaxAltitude;
+    }
+    return AnnotationSettings::getOcclusionCullingMaxAltitude();
+}
+
+void GeoPositionNode::setOcclusionCullingMaxAltitude( double occlusionCullingMaxAltitude )
+{
+    _occlusionCullingMaxAltitude = occlusionCullingMaxAltitude;
+    if ( _occlusionCuller.valid() )
+    {
+        _occlusionCuller->setMaxAltitude( getOcclusionCullingMaxAltitude() );         
+    }
+}
+
+
+GeoPositionNode::GeoPositionNode(MapNode* mapNode, const Config& conf) :
+AnnotationNode          ( conf ),
+_horizonCullingRequested( true )
+{
+    init();
+    GeoPositionNode::setMapNode( mapNode );
+    setConfig(conf);
+}
+
+void
+GeoPositionNode::setConfig(const Config& conf)
+{
+    //AnnotationNode::setConfig(conf);
+
+    if ( conf.hasChild( "position" ) )
+    {
+        setPosition( GeoPoint(conf.child("position")) );
+    }
+    else
+    {
+        if (conf.hasValue("lat") && conf.hasValue("long"))
+        {
+            setPosition( GeoPoint(SpatialReference::get("wgs84"),
+                conf.value("long", 0.0), conf.value("lat", 0.0)) );
+        }
+    }
+
+    if ( conf.hasChild( "scale" ) )
+    {
+        const Config* c = conf.child_ptr("scale");
+        osg::Vec3f s( c->value("x", 1.0f), c->value("y", 1.0f), c->value("z", 1.0f) );
+        getPositionAttitudeTransform()->setScale( s );
+    }
+
+    if ( conf.hasChild( "local_offset" ) )
+    {
+        const Config* c = conf.child_ptr("local_offset");
+        osg::Vec3d o( c->value("x", 0.0), c->value("y", 0.0), c->value("z", 0.0) );
+        getPositionAttitudeTransform()->setPosition( o );
+    }
+
+    if ( conf.hasChild( "local_rotation" ) )
+    {
+        const Config* c = conf.child_ptr("local_rotation");
+        osg::Quat q( c->value("x", 0.0), c->value("y", 0.0), c->value("z", 0.0), c->value("w", 1.0) );
+        getPositionAttitudeTransform()->setAttitude( q );
+    }
+}
+
+Config
+GeoPositionNode::getConfig() const
+{
+    Config conf = AnnotationNode::getConfig();
+
+    conf.addObj( "position", getGeoTransform()->getPosition() );
+
+    const osg::Vec3d& scale = getPositionAttitudeTransform()->getScale();
+    if ( scale.x() != 1.0f || scale.y() != 1.0f || scale.z() != 1.0f )
+    {
+        Config c( "scale" );
+        c.add( "x", scale.x() );
+        c.add( "y", scale.y() );
+        c.add( "z", scale.z() );
+        conf.add( c );
+    }
+
+    const osg::Vec3d& offset = getPositionAttitudeTransform()->getPosition();
+    if ( offset != osg::Vec3d(0,0,0) )
+    {
+        Config c( "local_offset" );
+        c.set( "x", offset.x() );
+        c.set( "y", offset.y() );
+        c.set( "z", offset.z() );
+        conf.add( c );
+    }
+
+    const osg::Quat& rot = getPositionAttitudeTransform()->getAttitude();
+    if ( !rot.zeroRotation() )
+    {
+        Config c( "local_rotation" );
+        c.set( "x", rot.x() );
+        c.set( "y", rot.y() );
+        c.set( "z", rot.z() );
+        c.set( "w", rot.w() );
+        conf.add( c );
+    }
+
+    return conf;
+}
diff --git a/src/osgEarthAnnotation/GeoPositionNodeAutoScaler b/src/osgEarthAnnotation/GeoPositionNodeAutoScaler
new file mode 100644
index 0000000..822f5f0
--- /dev/null
+++ b/src/osgEarthAnnotation/GeoPositionNodeAutoScaler
@@ -0,0 +1,58 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+* Copyright 2016 Pelican Mapping
+* http://osgearth.org
+*
+* osgEarth is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* 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.
+*
+* You should have received a copy of the GNU Lesser General Public License
+* along with this program.  If not, see <http://www.gnu.org/licenses/>
+*/
+#ifndef OSGEARTH_ANNOTATION_GEO_POSITION_NODE_AUTO_SCALER_H
+#define OSGEARTH_ANNOTATION_GEO_POSITION_NODE_AUTO_SCALER_H 1
+
+#include <osgEarthAnnotation/Common>
+#include <osg/NodeCallback>
+#include <osg/Vec3d>
+
+namespace osgEarth { namespace Annotation
+{
+    /**
+     * A CULL callback you can install on a GeoPositionNode that will
+     * automatically scale the annotation from scene coordinates to 
+     * screen coordinates.
+     *
+     * Important: ONLY install this on a GeoPositionNode, or else you will
+     * get a crash -- it does NO type checking.
+     *
+     * geoPosNode->setCullCallback( new GeoPositionNodeAutoScaler() );
+     */
+    class OSGEARTHANNO_EXPORT GeoPositionNodeAutoScaler : public osg::NodeCallback
+    {
+    public:
+        GeoPositionNodeAutoScaler(const osg::Vec3d& baseScale = osg::Vec3d(1,1,1), double minScale = 0.0, double maxScale = DBL_MAX);
+
+    public: // osg::NodeCallback
+
+        void operator()(osg::Node* node, osg::NodeVisitor* nv);
+
+    protected:
+        osg::Vec3d _baseScale;
+		double _minScale;
+		double _maxScale;
+    };
+
+} } // namespace
+
+#endif //OSGEARTH_ANNOTATION_GEO_POSITION_NODE_AUTO_SCALER_H
diff --git a/src/osgEarthAnnotation/GeoPositionNodeAutoScaler.cpp b/src/osgEarthAnnotation/GeoPositionNodeAutoScaler.cpp
new file mode 100644
index 0000000..4d1085b
--- /dev/null
+++ b/src/osgEarthAnnotation/GeoPositionNodeAutoScaler.cpp
@@ -0,0 +1,53 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+* Copyright 2016 Pelican Mapping
+* http://osgearth.org
+*
+* osgEarth is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* 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.
+*
+* You should have received a copy of the GNU Lesser General Public License
+* along with this program.  If not, see <http://www.gnu.org/licenses/>
+*/
+
+#include <osgEarthAnnotation/GeoPositionNodeAutoScaler>
+#include <osgEarthAnnotation/GeoPositionNode>
+#include <osgUtil/CullVisitor>
+
+#define LC "[GeoPositionNodeAutoScaler] "
+
+using namespace osgEarth;
+using namespace osgEarth::Annotation;
+
+
+GeoPositionNodeAutoScaler::GeoPositionNodeAutoScaler(const osg::Vec3d& baseScale, double minScale, double maxScale) :
+_baseScale( baseScale ),
+_minScale( minScale ),
+_maxScale( maxScale )
+{
+    //nop
+}
+
+void
+GeoPositionNodeAutoScaler::operator()(osg::Node* node, osg::NodeVisitor* nv)
+{
+    GeoPositionNode* geo = static_cast<GeoPositionNode*>(node);
+    osgUtil::CullVisitor* cs = static_cast<osgUtil::CullVisitor*>(nv);
+    double size = 1.0/cs->pixelSize( node->getBound().center(), 0.5f );
+	if (size < _minScale)
+		size = _minScale;
+	else if (size>_maxScale)
+		size = _maxScale;
+    geo->getPositionAttitudeTransform()->setScale( osg::componentMultiply(_baseScale, osg::Vec3d(size,size,size)) );
+    traverse(node, nv);
+}
diff --git a/src/osgEarthAnnotation/HighlightDecoration b/src/osgEarthAnnotation/HighlightDecoration
index 14e4ea0..90a540a 100644
--- a/src/osgEarthAnnotation/HighlightDecoration
+++ b/src/osgEarthAnnotation/HighlightDecoration
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
@@ -29,6 +29,7 @@ namespace osgEarth { namespace Annotation
 {	
     using namespace osgEarth;
 
+#if 0
     /**
      * Decoration technique that highlights the geometry.
      */
@@ -54,6 +55,7 @@ namespace osgEarth { namespace Annotation
         osg::Vec4f                   _color;
         osg::ref_ptr<osg::Uniform>   _colorUniform;
     };
+#endif
 
 } } // namespace osgEarth::Annotation
 
diff --git a/src/osgEarthAnnotation/HighlightDecoration.cpp b/src/osgEarthAnnotation/HighlightDecoration.cpp
index 18d993d..48742b3 100644
--- a/src/osgEarthAnnotation/HighlightDecoration.cpp
+++ b/src/osgEarthAnnotation/HighlightDecoration.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
@@ -20,6 +20,7 @@
 * along with this program.  If not, see <http://www.gnu.org/licenses/>
 */
 
+#if 0
 #include <osgEarthAnnotation/HighlightDecoration>
 #include <osgEarthAnnotation/AnnotationNode>
 #include <osgEarthAnnotation/AnnotationUtils>
@@ -76,7 +77,7 @@ HighlightDecoration::apply(AnnotationNode& node, bool enable)
         if ( enable )
         {
             VirtualProgram* vp = VirtualProgram::getOrCreate( ss );
-            if ( vp->getShader(FRAG_FUNCTION) == 0L )
+            if ( vp->getPolyShader(FRAG_FUNCTION) == 0L )
             {
                 vp->setFunction(FRAG_FUNCTION, fragSource, ShaderComp::LOCATION_FRAGMENT_COLORING, 0.6f);
                 ss->addUniform( _colorUniform.get() );
@@ -91,3 +92,4 @@ HighlightDecoration::apply(AnnotationNode& node, bool enable)
     }
     return _supported;
 }
+#endif
diff --git a/src/osgEarthAnnotation/ImageOverlay b/src/osgEarthAnnotation/ImageOverlay
index 5947c65..3001d6a 100644
--- a/src/osgEarthAnnotation/ImageOverlay
+++ b/src/osgEarthAnnotation/ImageOverlay
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -23,6 +23,7 @@
 #include <osgEarth/GeoData>
 #include <osgEarth/Units>
 #include <osgEarth/URI>
+#include <osgEarth/Terrain>
 
 #include <osg/Group>
 #include <osg/Geometry>
@@ -80,6 +81,11 @@ namespace osgEarth { namespace Annotation
         osg::Vec2d getControlPoint(ControlPoint controlPoint);
         void setControlPoint(ControlPoint controlPoint, double lon_deg, double lat_deg, bool singleVert=false);
 
+        /** When refining the mesh to fit the curtavure of the earth, this is the target resolution of the triangle mesh.
+            Default is 5 degrees */
+        void setGeometryResolution(const Distance& d) { _geometryResolution = d; }
+        const Distance& getGeometryResolution() const { return _geometryResolution; }
+
         struct ImageOverlayCallback : public osg::Referenced
         {
             virtual void onOverlayChanged() {};
@@ -124,7 +130,7 @@ namespace osgEarth { namespace Annotation
 
     public: // AnnotationNode
         
-        virtual void reclamp( const TileKey& key, osg::Node* tile, const Terrain* );
+        //virtual void reclamp( const TileKey& key, osg::Node* tile, const Terrain* );
 
     public: // MapNodeObserver
 
@@ -133,6 +139,14 @@ namespace osgEarth { namespace Annotation
     public: // osg::Node
 
         virtual void traverse(osg::NodeVisitor& nv);
+
+    public:
+        
+        // callback from Terrain whsen new data arrives
+        void onTileAdded(
+            const TileKey&          key, 
+            osg::Node*              tile, 
+            TerrainCallbackContext& context);
         
     private:
         void fireCallback(ImageOverlay::ControlPoint point, const osg::Vec2d& location);
@@ -141,8 +155,6 @@ namespace osgEarth { namespace Annotation
         void init();
         void clampLatitudes();
 
-        void clampMesh( osg::Node* terrainModel );
-
         void updateFilters();
 
 
@@ -158,6 +170,7 @@ namespace osgEarth { namespace Annotation
         osg::MatrixTransform* _transform;
         osg::Geometry* _geometry;
         osg::Texture* _texture;
+        Distance _geometryResolution;
 
         //float _alpha;
         CallbackList _callbacks;
@@ -167,6 +180,10 @@ namespace osgEarth { namespace Annotation
         optional<osg::Texture::FilterMode> _minFilter;
         optional<osg::Texture::FilterMode> _magFilter;
 
+        osg::ref_ptr< TerrainCallbackAdapter<ImageOverlay> > _clampCallback;
+        
+        void clamp(const Terrain* terrain, osg::Node* patch);
+
         ImageOverlay() { }
         ImageOverlay(const ImageOverlay&, const osg::CopyOp&) { }
     };
diff --git a/src/osgEarthAnnotation/ImageOverlay.cpp b/src/osgEarthAnnotation/ImageOverlay.cpp
index 15456b6..f845e47 100644
--- a/src/osgEarthAnnotation/ImageOverlay.cpp
+++ b/src/osgEarthAnnotation/ImageOverlay.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
@@ -23,7 +23,7 @@
 #include <osgEarthAnnotation/AnnotationRegistry>
 #include <osgEarthSymbology/MeshSubdivider>
 #include <osgEarthFeatures/GeometryUtils>
-#include <osgEarthFeatures/MeshClamper>
+#include <osgEarth/GeometryClamper>
 #include <osgEarthFeatures/Feature>
 #include <osgEarth/MapNode>
 #include <osgEarth/NodeUtils>
@@ -55,6 +55,8 @@ namespace
     {
         l.y() = osg::clampBetween( l.y(), -90.0, 90.0);
     }
+
+    static Distance default_geometryResolution(5.0, Units::DEGREES);
 }
 
 //---------------------------------------------------------------------------
@@ -62,7 +64,7 @@ namespace
 OSGEARTH_REGISTER_ANNOTATION( imageoverlay, osgEarth::Annotation::ImageOverlay );
 
 ImageOverlay::ImageOverlay(MapNode* mapNode, const Config& conf, const osgDB::Options* dbOptions) :
-AnnotationNode(mapNode, conf),
+AnnotationNode(conf),
 _lowerLeft    (10, 10),
 _lowerRight   (20, 10),
 _upperRight   (20, 20),
@@ -71,7 +73,8 @@ _dirty        (false),
 _alpha        (1.0f),
 _minFilter    (osg::Texture::LINEAR_MIPMAP_LINEAR),
 _magFilter    (osg::Texture::LINEAR),
-_texture      (0)
+_texture      (0),
+_geometryResolution(default_geometryResolution)
 {
     conf.getIfSet( "url",   _imageURI );
     if ( _imageURI.isSet() )
@@ -115,7 +118,15 @@ _texture      (0)
     conf.getIfSet("min_filter","NEAREST_MIPMAP_LINEAR", _minFilter,osg::Texture::NEAREST_MIPMAP_LINEAR);
     conf.getIfSet("min_filter","NEAREST_MIPMAP_NEAREST",_minFilter,osg::Texture::NEAREST_MIPMAP_NEAREST);
 
+    if (conf.hasValue("geometry_resolution"))
+    {
+        float value; Units units;
+        if (Units::parse(conf.value("geometry_resolution"), value, units, Units::DEGREES))
+            _geometryResolution.set(value, units);
+    }
+
     postCTOR();
+    ImageOverlay::setMapNode( mapNode );
 }
 
 Config
@@ -161,6 +172,11 @@ ImageOverlay::getConfig() const
     conf.updateIfSet("min_filter","NEAREST_MIPMAP_LINEAR", _minFilter,osg::Texture::NEAREST_MIPMAP_LINEAR);
     conf.updateIfSet("min_filter","NEAREST_MIPMAP_NEAREST",_minFilter,osg::Texture::NEAREST_MIPMAP_NEAREST);
 
+    if (_geometryResolution != default_geometryResolution)
+    {
+        conf.update("geometry_resolution", _geometryResolution.asParseableString());
+    }
+
     return conf;
 }
 
@@ -168,7 +184,7 @@ ImageOverlay::getConfig() const
 
 
 ImageOverlay::ImageOverlay(MapNode* mapNode, osg::Image* image) :
-AnnotationNode(mapNode),
+AnnotationNode(),
 _lowerLeft    (10, 10),
 _lowerRight   (20, 10),
 _upperRight   (20, 20),
@@ -178,9 +194,11 @@ _dirty        (false),
 _alpha        (1.0f),
 _minFilter    (osg::Texture::LINEAR_MIPMAP_LINEAR),
 _magFilter    (osg::Texture::LINEAR),
-_texture      (0)
+_texture      (0),
+_geometryResolution(default_geometryResolution)
 {        
     postCTOR();
+    ImageOverlay::setMapNode(mapNode);
 }
 
 void
@@ -192,7 +210,7 @@ ImageOverlay::postCTOR()
     _transform->addChild( _geode );
 
     // place the geometry under a drapeable node so it will project onto the terrain    
-    DrapeableNode* d = new DrapeableNode( getMapNode() );
+    DrapeableNode* d = new DrapeableNode(); // getMapNode() );
     addChild( d );
 
     d->addChild( _transform );
@@ -209,14 +227,16 @@ ImageOverlay::init()
 
     _geode->removeDrawables(0, _geode->getNumDrawables() );
 
+    if ( !_clampCallback.valid() )
+    {
+        _clampCallback = new TerrainCallbackAdapter<ImageOverlay>(this);
+    }
+
     if ( getMapNode() )
     {
-        double height = 0;
         osg::Geometry* geometry = new osg::Geometry();
         geometry->setUseVertexBufferObjects(true);
 
-        const osg::EllipsoidModel* ellipsoid = getMapNode()->getMapSRS()->getEllipsoid();
-
         const SpatialReference* mapSRS = getMapNode()->getMapSRS();
 
         // calculate a bounding polytope in world space (for mesh clamping):
@@ -226,7 +246,7 @@ ImageOverlay::init()
         g->push_back( osg::Vec3d(_lowerRight.x(), _lowerRight.y(), 0) );
         g->push_back( osg::Vec3d(_upperRight.x(), _upperRight.y(), 0) );
         g->push_back( osg::Vec3d(_upperLeft.x(),  _upperLeft.y(),  0) );
-        //_boundingPolytope = f->getWorldBoundingPolytope();
+        
         f->getWorldBoundingPolytope( getMapNode()->getMapSRS(), _boundingPolytope );
 
         // next, convert to world coords and create the geometry:
@@ -289,7 +309,7 @@ ImageOverlay::init()
         if (getMapNode()->getMap()->isGeocentric())
         {
             MeshSubdivider ms(osg::Matrixd::inverse(_transform->getMatrix()), _transform->getMatrix());
-            ms.run(*geometry, osg::DegreesToRadians(5.0), GEOINTERP_RHUMB_LINE);
+            ms.run(*geometry, _geometryResolution.as(Units::RADIANS), GEOINTERP_RHUMB_LINE);
         }
 
         _geode->addDrawable( geometry );
@@ -305,13 +325,16 @@ ImageOverlay::init()
         style.getOrCreate<AltitudeSymbol>()->clamping() = AltitudeSymbol::CLAMP_RELATIVE_TO_TERRAIN;
         applyStyle( style );
         setLightingIfNotSet( false );
-        clampMesh( getMapNode()->getTerrain()->getGraph() );
+        //clampMesh( getMapNode()->getTerrain()->getGraph() );
 
         if ( Registry::capabilities().supportsGLSL() )
         {
             //OE_WARN << LC << "ShaderGen RUNNING" << std::endl;
             Registry::shaderGenerator().run( _geode, "osgEarth.ImageOverlay" );
         }
+
+        getMapNode()->getTerrain()->addTerrainCallback( _clampCallback.get() );
+        clamp( getMapNode()->getTerrain(), getMapNode()->getTerrain()->getGraph() );
     }
 }
 
@@ -328,13 +351,13 @@ ImageOverlay::setMapNode( MapNode* mapNode )
 bool
 ImageOverlay::getDraped() const
 {
-    return static_cast< const DrapeableNode *>( getChild(0))->getDraped();
+    return static_cast< const DrapeableNode *>( getChild(0))->getDrapingEnabled();
 }
 
 void
 ImageOverlay::setDraped( bool draped )
 {
-    static_cast< DrapeableNode *>( getChild(0))->setDraped( draped );
+    static_cast< DrapeableNode *>( getChild(0))->setDrapingEnabled( draped );
 }
 
 osg::Image*
@@ -717,37 +740,27 @@ ImageOverlay::removeCallback( ImageOverlayCallback* cb )
     }    
 }
 
-
 void
-ImageOverlay::reclamp( const TileKey& key, osg::Node* tile, const Terrain* )
+ImageOverlay::clamp(const Terrain* terrain, osg::Node* patch)
 {
-    if ( _boundingPolytope.contains( tile->getBound() ) ) // intersects, actually
+    if ( terrain && patch )
     {
-        clampMesh( tile );
-        OE_DEBUG << LC << "Clamped overlay mesh, tile radius = " << tile->getBound().radius() << std::endl;
+        GeometryClamper clamper;
+        clamper.setTerrainPatch( patch );
+        clamper.setTerrainSRS( terrain->getSRS() );
+
+        this->accept( clamper );
+        this->dirtyBound();
     }
 }
 
 void
-ImageOverlay::clampMesh( osg::Node* terrainModel )
+ImageOverlay::onTileAdded(const TileKey&          key, 
+                          osg::Node*              tile, 
+                          TerrainCallbackContext& context)
 {
-    double scale  = 1.0;
-    double offset = 0.0;
-    bool   relative = false;
-
-    if (_altitude.valid())
+    if ( tile == 0L || _boundingPolytope.contains(tile->getBound()) )
     {
-        if ( _altitude->verticalScale().isSet() )
-            scale = _altitude->verticalScale()->eval();
-
-        if ( _altitude->verticalOffset().isSet() )
-            offset = _altitude->verticalOffset()->eval();
-
-        relative = _altitude->clamping() == AltitudeSymbol::CLAMP_RELATIVE_TO_TERRAIN;
+        clamp( context.getTerrain(), tile );
     }
-
-    MeshClamper clamper( terrainModel, getMapNode()->getMapSRS(), getMapNode()->isGeocentric(), relative, scale, offset );
-    this->accept( clamper );
-
-    this->dirtyBound();
 }
diff --git a/src/osgEarthAnnotation/ImageOverlayEditor b/src/osgEarthAnnotation/ImageOverlayEditor
index 71ce102..8da7fbf 100644
--- a/src/osgEarthAnnotation/ImageOverlayEditor
+++ b/src/osgEarthAnnotation/ImageOverlayEditor
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthAnnotation/ImageOverlayEditor.cpp b/src/osgEarthAnnotation/ImageOverlayEditor.cpp
index 4c35787..45b6dfd 100644
--- a/src/osgEarthAnnotation/ImageOverlayEditor.cpp
+++ b/src/osgEarthAnnotation/ImageOverlayEditor.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
@@ -99,7 +99,8 @@ ImageOverlayEditor::addDragger( ImageOverlay::ControlPoint controlPoint )
     osg::Vec2d location = _overlay->getControlPoint( controlPoint );
     
     SphereDragger* dragger = new SphereDragger(_overlay->getMapNode());
-    dragger->setPosition( GeoPoint( SpatialReference::create( "epsg:4326"), location.x(), location.y()));
+    GeoPoint point( SpatialReference::get("epsg:4326"), location.x(), location.y() );
+    dragger->setPosition( point );
     dragger->addPositionChangedCallback( new ImageOverlayDraggerCallback(_overlay.get(), controlPoint, _singleVert));
     addChild(dragger);
     _draggers[ controlPoint ] = dragger;
diff --git a/src/osgEarthAnnotation/LabelNode b/src/osgEarthAnnotation/LabelNode
index 260ad79..2058ffb 100644
--- a/src/osgEarthAnnotation/LabelNode
+++ b/src/osgEarthAnnotation/LabelNode
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
@@ -23,9 +23,10 @@
 #ifndef OSGEARTH_ANNOTATION_LABEL_NODE_H
 #define OSGEARTH_ANNOTATION_LABEL_NODE_H 1
 
-#include <osgEarthAnnotation/OrthoNode>
+#include <osgEarthAnnotation/GeoPositionNode>
 #include <osgEarthSymbology/Style>
 #include <osgEarth/MapNode>
+#include <osgEarth/ScreenSpaceLayout>
 #include <osg/Geode>
 
 namespace osgEarth { namespace Annotation
@@ -36,7 +37,7 @@ namespace osgEarth { namespace Annotation
     /**
      * Text labeling node.
      */
-    class OSGEARTHANNO_EXPORT LabelNode : public OrthoNode
+    class OSGEARTHANNO_EXPORT LabelNode : public GeoPositionNode
     {
     public:
         META_AnnotationNode( osgEarthAnnotation, LabelNode );
@@ -92,6 +93,9 @@ namespace osgEarth { namespace Annotation
             const Config&         conf,
             const osgDB::Options* dbOptions );
 
+        /**
+         * Destructor
+         */
         virtual ~LabelNode() { }
 
         /**
@@ -111,23 +115,34 @@ namespace osgEarth { namespace Annotation
          */
         void setStyle( const Style& style );
 
-    public: // OrthoNode override
+    public: // GeoPositionNode override
 
-        virtual void setAnnotationData( AnnotationData* data );
+        virtual void setPriority(float value);
 
         virtual void setDynamic( bool value );
 
         virtual Config getConfig() const;
 
+        virtual void dirty();
+
     protected:
         void init(const Style& style);
 
         std::string              _text;
         Style                    _style;
         osg::ref_ptr<osg::Geode> _geode;
+        osg::ref_ptr<ScreenSpaceLayoutData> _dataLayout;
+
+        /** rotation of the label **/
+        float                    _labelRotationRad;
+        bool                     _followFixedCourse;
+        GeoPoint                 _geoPointLoc;
+        GeoPoint                 _geoPointProj;
 
         /** Copy constructor */
-        LabelNode( const LabelNode& rhs, const osg::CopyOp& op =osg::CopyOp::DEEP_COPY_ALL ) : OrthoNode(rhs, op) { }
+        LabelNode(const LabelNode& rhs, const osg::CopyOp& op = osg::CopyOp::DEEP_COPY_ALL);
+
+        void updateLayoutData();
     };
 
 } } // namespace osgEarth::Annotation
diff --git a/src/osgEarthAnnotation/LabelNode.cpp b/src/osgEarthAnnotation/LabelNode.cpp
index 05e586b..9615510 100644
--- a/src/osgEarthAnnotation/LabelNode.cpp
+++ b/src/osgEarthAnnotation/LabelNode.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
@@ -23,9 +23,14 @@
 #include <osgEarthAnnotation/LabelNode>
 #include <osgEarthAnnotation/AnnotationUtils>
 #include <osgEarthAnnotation/AnnotationRegistry>
+#include <osgEarthAnnotation/BboxDrawable>
 #include <osgEarthSymbology/Color>
+#include <osgEarthSymbology/BBoxSymbol>
 #include <osgEarth/Registry>
 #include <osgEarth/ShaderGenerator>
+#include <osgEarth/GeoMath>
+#include <osgEarth/Utils>
+#include <osgEarth/ScreenSpaceLayout>
 #include <osgText/Text>
 #include <osg/Depth>
 #include <osgUtil/IntersectionVisitor>
@@ -45,8 +50,10 @@ LabelNode::LabelNode(MapNode*            mapNode,
                      const std::string&  text,
                      const Style&        style ) :
 
-OrthoNode( mapNode, position ),
-_text    ( text )
+GeoPositionNode( mapNode, position ),
+_text             ( text ),
+_labelRotationRad ( 0. ),
+_followFixedCourse( false )
 {
     init( style );
 }
@@ -56,8 +63,10 @@ LabelNode::LabelNode(MapNode*            mapNode,
                      const std::string&  text,
                      const TextSymbol*   symbol ) :
 
-OrthoNode( mapNode, position ),
-_text    ( text )
+GeoPositionNode( mapNode, position ),
+_text             ( text ),
+_labelRotationRad ( 0. ),
+_followFixedCourse( false )
 {
     Style style;
     style.add( const_cast<TextSymbol*>(symbol) );
@@ -66,8 +75,10 @@ _text    ( text )
 
 LabelNode::LabelNode(const std::string&  text,
                      const Style&        style ) :
-OrthoNode(),
-_text    ( text )
+GeoPositionNode(),
+_text             ( text ),
+_labelRotationRad ( 0. ),
+_followFixedCourse( false )
 {
     init( style );
 }
@@ -75,31 +86,45 @@ _text    ( text )
 LabelNode::LabelNode(MapNode*            mapNode,
                      const GeoPoint&     position,
                      const Style&        style ) :
-OrthoNode( mapNode, position )
+GeoPositionNode   ( mapNode, position ),
+_labelRotationRad ( 0. ),
+_followFixedCourse( false )
 {
     init( style );
 }
 
 LabelNode::LabelNode(MapNode*            mapNode,
                      const Style&        style ) :
-OrthoNode( mapNode, GeoPoint::INVALID )
+GeoPositionNode   ( mapNode, GeoPoint::INVALID ),
+_labelRotationRad ( 0. ),
+_followFixedCourse( false )
 {
     init( style );
 }
 
+LabelNode::LabelNode(const LabelNode& rhs, const osg::CopyOp& op) :
+GeoPositionNode(rhs, op),
+_labelRotationRad(0.),
+_followFixedCourse(false)
+{
+    //nop - unused
+}
+
 void
 LabelNode::init( const Style& style )
 {
+    ScreenSpaceLayout::activate( this->getOrCreateStateSet() );
+
     _geode = new osg::Geode();
 
     // ensure that (0,0,0) is the bounding sphere control/center point.
     // useful for things like horizon culling.
     _geode->setComputeBoundingSphereCallback(new ControlPointCallback());
 
-    getAttachPoint()->addChild( _geode.get() );
+    getPositionAttitudeTransform()->addChild( _geode.get() );
 
     osg::StateSet* stateSet = _geode->getOrCreateStateSet();
-    stateSet->setAttributeAndModes( new osg::Depth(osg::Depth::ALWAYS, 0, 1, false), 1 );
+    stateSet->setAttributeAndModes( new osg::Depth(osg::Depth::ALWAYS, 0, 1, false), 1 );    
 
     setStyle( style );
 }
@@ -116,7 +141,16 @@ LabelNode::setText( const std::string& text )
     osgText::Text* d = dynamic_cast<osgText::Text*>(_geode->getDrawable(0));
     if ( d )
     {
-        d->setText( text );
+        const TextSymbol* symbol = _style.get<TextSymbol>();
+
+        osgText::String::Encoding textEncoding = osgText::String::ENCODING_UNDEFINED;
+        if (symbol && symbol->encoding().isSet())
+        {
+            textEncoding = AnnotationUtils::convertTextSymbolEncoding(symbol->encoding().value());
+        }
+
+        d->setText(text, textEncoding);
+
         d->dirtyDisplayList();
         _text = text;
     }
@@ -130,8 +164,6 @@ LabelNode::setStyle( const Style& style )
         OE_WARN << LC << "Illegal state: cannot change a LabelNode that is not dynamic" << std::endl;
         return;
     }
-    
-    this->clearDecoration();
 
     _geode->removeDrawables( 0, _geode->getNumDrawables() );
 
@@ -142,8 +174,32 @@ LabelNode::setStyle( const Style& style )
     if ( _text.empty() )
         _text = symbol->content()->eval();
 
-    osg::Drawable* t = AnnotationUtils::createTextDrawable( _text, symbol, osg::Vec3(0,0,0) );
-    _geode->addDrawable(t);
+    if ( symbol && symbol->onScreenRotation().isSet() )
+    {
+        _labelRotationRad = osg::DegreesToRadians(symbol->onScreenRotation()->eval());
+    }
+
+    // In case of a label must follow a course on map, we project a point from the position
+    // with the given bearing. Then during culling phase we compute both points on the screen
+    // and then we can deduce the screen rotation
+    // may be optimized...
+    else if ( symbol && symbol->geographicCourse().isSet() )
+    {
+        _followFixedCourse = true;
+        _labelRotationRad = osg::DegreesToRadians ( symbol->geographicCourse()->eval() );
+    }
+
+    osg::Drawable* text = AnnotationUtils::createTextDrawable( _text, symbol, osg::Vec3(0,0,0) );
+
+    const BBoxSymbol* bboxsymbol = _style.get<BBoxSymbol>();
+    if ( bboxsymbol && text )
+    {
+        osg::Drawable* bboxGeom = new BboxDrawable( Utils::getBoundingBox(text), *bboxsymbol );
+        _geode->addDrawable(bboxGeom);
+    }
+
+    _geode->addDrawable(text);
+    _geode->setCullingActive(false);
 
     applyStyle( _style );
 
@@ -153,24 +209,85 @@ LabelNode::setStyle( const Style& style )
         this,
         "osgEarth.LabelNode",
         Registry::stateSetCache() );
+
+    updateLayoutData();
+    dirty();
+}
+
+void
+LabelNode::dirty()
+{
+    GeoPositionNode::dirty();
+    updateLayoutData();
+}
+
+void
+LabelNode::setPriority(float value)
+{
+    GeoPositionNode::setPriority(value);
+    updateLayoutData();
 }
 
 void
-LabelNode::setAnnotationData( AnnotationData* data )
+LabelNode::updateLayoutData()
 {
-    OrthoNode::setAnnotationData( data );
+    if (!_dataLayout.valid())
+    {
+        _dataLayout = new ScreenSpaceLayoutData();
+    }
 
-    // override this method so we can attach the anno data to the drawables.
-    for(unsigned i=0; i<_geode->getNumDrawables(); ++i)
+    // re-apply annotation drawable-level stuff as neccesary.
+    for (unsigned i = 0; i < _geode->getNumDrawables(); ++i)
     {
-        _geode->getDrawable(i)->setUserData( data );
+        _geode->getDrawable(i)->setUserData(_dataLayout.get());
+    }
+    
+    _dataLayout->setPriority(getPriority());
+    
+    GeoPoint location = getPosition();
+    location.makeGeographic();
+    double latRad;
+    double longRad;
+    GeoMath::destination(osg::DegreesToRadians(location.y()),
+        osg::DegreesToRadians(location.x()),
+        _labelRotationRad,
+        2500.,
+        latRad,
+        longRad);
+
+    _geoPointProj.set(osgEarth::SpatialReference::get("wgs84"),
+        osg::RadiansToDegrees(longRad),
+        osg::RadiansToDegrees(latRad),
+        0,
+        osgEarth::ALTMODE_ABSOLUTE);
+
+    _geoPointLoc.set(osgEarth::SpatialReference::get("wgs84"),
+        //location.getSRS(),
+        location.x(),
+        location.y(),
+        0,
+        osgEarth::ALTMODE_ABSOLUTE);
+
+    const TextSymbol* ts = getStyle().get<TextSymbol>();
+    if (ts)
+    {
+        _dataLayout->setPixelOffset(ts->pixelOffset().get());
+        
+        if (_followFixedCourse)
+        {
+            osg::Vec3d p0, p1;
+            _geoPointLoc.toWorld(p0);
+            _geoPointProj.toWorld(p1);
+            _dataLayout->setAnchorPoint(p0);
+            _dataLayout->setProjPoint(p1);
+        }
     }
 }
 
 void
 LabelNode::setDynamic( bool dynamic )
 {
-    OrthoNode::setDynamic( dynamic );
+    GeoPositionNode::setDynamic( dynamic );
 
     osgText::Text* d = dynamic_cast<osgText::Text*>(_geode->getDrawable(0));
     if ( d )
@@ -179,17 +296,17 @@ LabelNode::setDynamic( bool dynamic )
     }    
 }
 
-
-
 //-------------------------------------------------------------------
 
 OSGEARTH_REGISTER_ANNOTATION( label, osgEarth::Annotation::LabelNode );
 
 
-LabelNode::LabelNode(MapNode*               mapNode,
+LabelNode::LabelNode(MapNode*              mapNode,
                      const Config&         conf,
                      const osgDB::Options* dbOptions ) :
-OrthoNode( mapNode, GeoPoint::INVALID )
+GeoPositionNode( mapNode, conf ),
+_labelRotationRad ( 0. ),
+_followFixedCourse( false )
 {
     optional<Style> style;
 
@@ -197,9 +314,6 @@ OrthoNode( mapNode, GeoPoint::INVALID )
     conf.getIfSet   ( "text",  _text );
 
     init( *style );
-
-    if ( conf.hasChild("position") )
-        setPosition( GeoPoint(conf.child("position")) );
 }
 
 Config
@@ -208,7 +322,6 @@ LabelNode::getConfig() const
     Config conf( "label" );
     conf.add   ( "text",   _text );
     conf.addObj( "style",  _style );
-    conf.addObj( "position", getPosition() );
 
     return conf;
 }
diff --git a/src/osgEarthAnnotation/LocalGeometryNode b/src/osgEarthAnnotation/LocalGeometryNode
index 9088a5f..60cb44e 100644
--- a/src/osgEarthAnnotation/LocalGeometryNode
+++ b/src/osgEarthAnnotation/LocalGeometryNode
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
@@ -22,7 +22,7 @@
 #ifndef OSGEARTH_ANNO_LOCAL_GEOMETRY_NODE_H
 #define OSGEARTH_ANNO_LOCAL_GEOMETRY_NODE_H 1
 
-#include <osgEarthAnnotation/LocalizedNode>
+#include <osgEarthAnnotation/GeoPositionNode>
 #include <osgEarth/MapNode>
 #include <osgEarthSymbology/Geometry>
 #include <osgEarthSymbology/Style>
@@ -37,7 +37,7 @@ namespace osgEarth { namespace Annotation
      * is in a local tangent plane that may be positioned somewhere on the 
      * Map's surface.
      */
-    class OSGEARTHANNO_EXPORT LocalGeometryNode : public LocalizedNode
+    class OSGEARTHANNO_EXPORT LocalGeometryNode : public GeoPositionNode
     {
     public:
         /**
@@ -57,6 +57,12 @@ namespace osgEarth { namespace Annotation
             osg::Node*   node, 
             const Style& style  =Style() );
 
+        /**
+         * Construct an LGN connected to a mapnode.
+         */
+        LocalGeometryNode( MapNode* node );
+
+
         virtual ~LocalGeometryNode() { }
 
         /**
@@ -91,6 +97,10 @@ namespace osgEarth { namespace Annotation
 
     public:
 
+        virtual void setMapNode(MapNode*);
+
+    public:
+
         /**
          * Constructs an LGN from a serialized Config.
          */
@@ -101,21 +111,41 @@ namespace osgEarth { namespace Annotation
 
         virtual Config getConfig() const;
 
-    protected: // LocalizedNode
+    public: // osg::Node
 
-        virtual osg::MatrixTransform* getTransform() { return _xform.get(); }
+        virtual osg::BoundingSphere computeBound() const;
+
+    protected: // GeoPositionNode
+
+        virtual void dirty();
 
     protected:
+        LocalGeometryNode();
 
         Style                        _style;
         osg::ref_ptr<osg::Node>      _node;
         osg::ref_ptr<Geometry>       _geom;
-
-        osg::ref_ptr<osg::MatrixTransform> _xform;
+        
+        typedef TerrainCallbackAdapter<LocalGeometryNode> ClampCallback;
+        osg::ref_ptr<ClampCallback> _clampCallback;
+        bool _clampRelative;
+        mutable osg::Polytope _boundingPT;
 
         void initNode();
         void initGeometry(const osgDB::Options*);
         void init(const osgDB::Options*);
+
+        void applyAltitudeSymbology(const Style&);
+
+    public:
+        void onTileAdded(
+            const TileKey&          key, 
+            osg::Node*              tile, 
+            TerrainCallbackContext& context);
+
+        virtual void clampToScene(
+            osg::Node*     tile,
+            const Terrain* terrain);
     };
 
 } } // namespace osgEarth::Annotation
diff --git a/src/osgEarthAnnotation/LocalGeometryNode.cpp b/src/osgEarthAnnotation/LocalGeometryNode.cpp
index 0097c61..d5bbe17 100644
--- a/src/osgEarthAnnotation/LocalGeometryNode.cpp
+++ b/src/osgEarthAnnotation/LocalGeometryNode.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
@@ -22,10 +22,10 @@
 
 #include <osgEarthAnnotation/LocalGeometryNode>
 #include <osgEarthAnnotation/AnnotationRegistry>
+#include <osgEarthAnnotation/AnnotationUtils>
 #include <osgEarthFeatures/GeometryCompiler>
 #include <osgEarthFeatures/GeometryUtils>
-#include <osgEarthFeatures/MeshClamper>
-#include <osgEarth/DrapeableNode>
+#include <osgEarth/GeometryClamper>
 #include <osgEarth/Utils>
 
 #define LC "[GeometryNode] "
@@ -35,14 +35,30 @@ using namespace osgEarth::Annotation;
 using namespace osgEarth::Features;
 
 
+LocalGeometryNode::LocalGeometryNode() :
+GeoPositionNode(),
+_clampRelative(false)
+{
+    //nop - unused
+}
+
+LocalGeometryNode::LocalGeometryNode(MapNode* mapNode) :
+GeoPositionNode(),
+_clampRelative(false)
+{
+    LocalGeometryNode::setMapNode( mapNode );
+    init( 0L );
+}
+
 LocalGeometryNode::LocalGeometryNode(MapNode*     mapNode,
                                      Geometry*    geom,
                                      const Style& style) :
-LocalizedNode( mapNode ),
-_geom        ( geom ),
-_style       ( style )
+GeoPositionNode(),
+_geom    ( geom ),
+_style   ( style ),
+_clampRelative(false)
 {
-    _xform = new osg::MatrixTransform();
+    LocalGeometryNode::setMapNode( mapNode );
     init( 0L );
 }
 
@@ -50,31 +66,39 @@ _style       ( style )
 LocalGeometryNode::LocalGeometryNode(MapNode*     mapNode,
                                      osg::Node*   node,
                                      const Style& style) :
-LocalizedNode( mapNode ),
-_node        ( node ),
-_style       ( style )
+GeoPositionNode(),
+_node    ( node ),
+_style   ( style ),
+_clampRelative(false)
 {
-    _xform = new osg::MatrixTransform();
+    LocalGeometryNode::setMapNode( mapNode );
     init( 0L );
 }
 
+void
+LocalGeometryNode::setMapNode(MapNode* mapNode)
+{
+    if ( mapNode != getMapNode() )
+    {
+        GeoPositionNode::setMapNode( mapNode );
+        init(0L);
+    }
+}
 
 void
 LocalGeometryNode::initNode()
 {
-    // reset
-    osgEarth::clearChildren( this );
-    osgEarth::clearChildren( _xform.get() );
-    this->addChild( _xform.get() );
+    osgEarth::clearChildren( getPositionAttitudeTransform() );
 
     if ( _node.valid() )
     {
-        _xform->addChild( _node );
-        // activate clamping if necessary
-        replaceChild( _xform.get(), applyAltitudePolicy(_xform.get(), _style) );
+        _node = AnnotationUtils::installOverlayParent( _node.get(), _style );
+
+        getPositionAttitudeTransform()->addChild( _node.get() );
+
+        applyRenderSymbology( getStyle() );
 
-        applyGeneralSymbology( _style );
-        setLightingIfNotSet( _style.has<ExtrusionSymbol>() );
+        setLightingIfNotSet( getStyle().has<ExtrusionSymbol>() );
     }
 }
 
@@ -82,37 +106,33 @@ LocalGeometryNode::initNode()
 void
 LocalGeometryNode::initGeometry(const osgDB::Options* dbOptions)
 {
-    // reset
-    osgEarth::clearChildren( this );
-    osgEarth::clearChildren( _xform.get() );
-    this->addChild( _xform.get() );
+    osgEarth::clearChildren( getPositionAttitudeTransform() );
 
     if ( _geom.valid() )
     {
-        Session* session = 0L;
+        osg::ref_ptr<Session> session;
         if ( getMapNode() )
             session = new Session(getMapNode()->getMap(), 0L, 0L, dbOptions);
-        FilterContext cx( session );
-
+        
         GeometryCompiler gc;
-        osg::Node* node = gc.compile( _geom.get(), _style, cx );
-        if ( node )
+        osg::ref_ptr<osg::Node> node = gc.compile( _geom.get(), getStyle(), FilterContext(session) );
+        if ( node.valid() )
         {
-            _xform->addChild( node );
-            // activate clamping if necessary
-            replaceChild( _xform.get(), applyAltitudePolicy(_xform.get(), _style) );
+            node = AnnotationUtils::installOverlayParent( node.get(), getStyle() );
+
+            getPositionAttitudeTransform()->addChild( node.get() );
 
-            applyGeneralSymbology( _style );
+            applyRenderSymbology( getStyle() );
+
+            applyAltitudeSymbology( getStyle() );
         }
     }
 }
 
 
 void 
-LocalGeometryNode::init(const osgDB::Options* options )
-{
-    this->clearDecoration();
-    
+LocalGeometryNode::init(const osgDB::Options* options)
+{    
     if ( _node.valid() )
     {
         initNode();
@@ -149,6 +169,138 @@ LocalGeometryNode::setGeometry( Geometry* geom )
     initGeometry(0L);
 }
 
+void
+LocalGeometryNode::applyAltitudeSymbology(const Style& style)
+{
+    // deal with scene clamping symbology.
+    if ( getMapNode() )
+    {
+        if ( _clampCallback.valid() )
+        {
+            getMapNode()->getTerrain()->removeTerrainCallback( _clampCallback.get() );
+            _clampCallback = 0L;
+        }
+
+        const AltitudeSymbol* alt = style.get<AltitudeSymbol>();
+        if ( alt && alt->technique() == alt->TECHNIQUE_SCENE )
+        {
+            if ( alt->binding() == alt->BINDING_CENTROID )
+            {
+                // centroid scene clamping? let GeoTransform do its thing.
+                getGeoTransform()->setAutoRecomputeHeights( true );
+            }
+
+            else if ( alt->binding() == alt->BINDING_VERTEX )
+            {
+                // per vertex clamping? disable the GeoTransform's clamping and take over.
+                getGeoTransform()->setAutoRecomputeHeights( false );
+
+                if ( !_clampCallback.valid() )
+                {
+                    _clampCallback = new ClampCallback(this);
+                }
+
+                if ( alt->clamping() == alt->CLAMP_TO_TERRAIN )
+                {
+                    _clampRelative = false;
+                    getMapNode()->getTerrain()->addTerrainCallback( _clampCallback.get() );
+                }
+
+                else if ( alt->clamping() == alt->CLAMP_RELATIVE_TO_TERRAIN )
+                {
+                    _clampRelative = true;
+                    getMapNode()->getTerrain()->addTerrainCallback( _clampCallback.get() );
+                }
+            }
+        }
+    }
+}
+
+void
+LocalGeometryNode::onTileAdded(const TileKey&          key, 
+                               osg::Node*              patch, 
+                               TerrainCallbackContext& context)
+{
+    // if key and data intersect then
+    if ( _boundingPT.contains(patch->getBound()) )
+    {    
+        clampToScene( patch, context.getTerrain() );
+        this->dirtyBound();
+    }
+}
+
+void
+LocalGeometryNode::clampToScene(osg::Node* patch, const Terrain* terrain)
+{
+    GeometryClamper clamper;
+
+    clamper.setTerrainPatch( patch );
+    clamper.setTerrainSRS( terrain ? terrain->getSRS() : 0L );
+    clamper.setPreserveZ( _clampRelative );
+    clamper.setOffset( getPosition().alt() );
+
+    this->accept( clamper );
+}
+
+osg::BoundingSphere
+LocalGeometryNode::computeBound() const
+{
+    osg::BoundingSphere bs = AnnotationNode::computeBound();
+    
+    // NOTE: this is the same code found in Feature.cpp. Consolidate?
+
+    _boundingPT.clear();
+
+    // add planes for the four sides of the BS. Normals point inwards.
+    _boundingPT.add( osg::Plane(osg::Vec3d( 1, 0,0), osg::Vec3d(-bs.radius(),0,0)) );
+    _boundingPT.add( osg::Plane(osg::Vec3d(-1, 0,0), osg::Vec3d( bs.radius(),0,0)) );
+    _boundingPT.add( osg::Plane(osg::Vec3d( 0, 1,0), osg::Vec3d(0, -bs.radius(),0)) );
+    _boundingPT.add( osg::Plane(osg::Vec3d( 0,-1,0), osg::Vec3d(0,  bs.radius(),0)) );
+
+    const SpatialReference* srs = getPosition().getSRS();
+    if ( srs )
+    {
+        // for a projected feature, we're done. For a geocentric one, transform the polytope
+        // into world (ECEF) space.
+        if ( srs->isGeographic() && !srs->isPlateCarre() )
+        {
+            const osg::EllipsoidModel* e = srs->getEllipsoid();
+
+            // add a bottom cap, unless the bounds are sufficiently large.
+            double minRad = std::min(e->getRadiusPolar(), e->getRadiusEquator());
+            double maxRad = std::max(e->getRadiusPolar(), e->getRadiusEquator());
+            double zeroOffset = bs.center().length();
+            if ( zeroOffset > minRad * 0.1 )
+            {
+                _boundingPT.add( osg::Plane(osg::Vec3d(0,0,1), osg::Vec3d(0,0,-maxRad+zeroOffset)) );
+            }
+        }
+
+        // transform the clipping planes ito ECEF space
+        GeoPoint refPoint;
+        refPoint.fromWorld( srs, bs.center() );
+
+        osg::Matrix local2world;
+        refPoint.createLocalToWorld( local2world );
+
+        _boundingPT.transform( local2world );
+    }
+
+    return bs;
+}
+
+void
+LocalGeometryNode::dirty()
+{
+    GeoPositionNode::dirty();
+
+    // re-clamp the geometry if necessary.
+    if ( _clampCallback.valid() && getMapNode() )
+    {
+        clampToScene( getMapNode()->getTerrain()->getGraph(), getMapNode()->getTerrain() );
+    }
+}
+
 //-------------------------------------------------------------------
 
 OSGEARTH_REGISTER_ANNOTATION( local_geometry, osgEarth::Annotation::LocalGeometryNode );
@@ -157,38 +309,31 @@ OSGEARTH_REGISTER_ANNOTATION( local_geometry, osgEarth::Annotation::LocalGeometr
 LocalGeometryNode::LocalGeometryNode(MapNode*              mapNode,
                                      const Config&         conf,
                                      const osgDB::Options* dbOptions) :
-LocalizedNode( mapNode, conf )
+GeoPositionNode( mapNode, conf ),
+_clampRelative(false)
 {
-    _xform = new osg::MatrixTransform();
-
     if ( conf.hasChild("geometry") )
     {
         Config geomconf = conf.child("geometry");
         _geom = GeometryUtils::geometryFromWKT( geomconf.value() );
-        if ( _geom.valid() )
-        {
-            conf.getObjIfSet( "style", _style );
-
-            init( dbOptions );
-        }
     }
+
+    conf.getObjIfSet( "style", _style );
+    init( dbOptions );
 }
 
 Config
 LocalGeometryNode::getConfig() const
 {
-    Config conf = LocalizedNode::getConfig();
+    Config conf = GeoPositionNode::getConfig();
     conf.key() = "local_geometry";
 
+    if ( !_style.empty() )
+        conf.addObj( "style", _style );
+
     if ( _geom.valid() )
     {
         conf.add( Config("geometry", GeometryUtils::geometryToWKT(_geom.get())) );
-        if ( !_style.empty() )
-            conf.addObj( "style", _style );
-    }
-    else
-    {
-        OE_WARN << LC << "Cannot serialize GeometryNode because it contains no geometry" << std::endl;
     }
 
     return conf;
diff --git a/src/osgEarthAnnotation/LocalizedNode b/src/osgEarthAnnotation/LocalizedNode
deleted file mode 100644
index f6aac2e..0000000
--- a/src/osgEarthAnnotation/LocalizedNode
+++ /dev/null
@@ -1,159 +0,0 @@
-/* -*-c++-*- */
-/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
-* http://osgearth.org
-*
-* osgEarth is free software; you can redistribute it and/or modify
-* it under the terms of the GNU Lesser General Public License as published by
-* the Free Software Foundation; either version 2 of the License, or
-* (at your option) any later version.
-*
-* 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.
-*
-* You should have received a copy of the GNU Lesser General Public License
-* along with this program.  If not, see <http://www.gnu.org/licenses/>
-*/
-#ifndef OSGEARTH_ANNO_LOCALIZED_NODE_H
-#define OSGEARTH_ANNO_LOCALIZED_NODE_H 1
-
-#include <osgEarthAnnotation/AnnotationNode>
-#include <osgEarth/GeoData>
-#include <osgEarth/Horizon>
-#include <osg/MatrixTransform>
-
-namespace osgEarth { namespace Annotation
-{	
-    using namespace osgEarth;
-
-    /**
-     * Base class for node that is localized at a specific geographic point.
-     *
-     * Don't use this class *directly*. If you are trying to add your own 
-     * osg::Node as an Annotation, use the LocalizedGeometryNode instead.
-     */
-    class OSGEARTHANNO_EXPORT LocalizedNode : public PositionedAnnotationNode
-    {
-    public:
-        META_AnnotationNodeAbstract(osgEarthAnnotation, LocalizedNode);
-
-        /**
-         * Constructs a new LocalizedNode.
-         * @param mapSRS  Spatial reference for position info
-         * @param pos     Initial position of the node (map coords)
-         */
-        LocalizedNode( 
-            MapNode*          mapNode,
-            const GeoPoint&   pos      =GeoPoint::INVALID );
-
-        LocalizedNode(
-            MapNode*          mapNode,
-            const Config&     conf );
-
-
-    public: // PositionedAnnotationNode
-
-        /** Sets the node position */
-        virtual bool setPosition( const GeoPoint& p );
-
-        /** Gets the node position (in map coords) */
-        virtual GeoPoint getPosition() const;
-
-
-    public: // MapNodeObserver
-
-        virtual void setMapNode( MapNode* mapNode );
-
-    public:
-        /**
-         * Sets a "local offset" position - for an ECEF map, this is an offset in 
-         * the local tangent plane of the node that is applied to the geometry.
-         */
-        void setLocalOffset( const osg::Vec3d& offset );
-
-        /**
-         * Gets the local tangent plane -space offset.
-         */
-        const osg::Vec3d& getLocalOffset() const;
-
-        /**
-         * Sets a local rotation - a rotation relative to the local tangent plane
-         * of the geometry.
-         */
-        void setLocalRotation( const osg::Quat& rotation );
-
-        /**
-         * Gets the local tangent plane -space rotation.
-         */
-        const osg::Quat& getLocalRotation() const;
-
-        /**
-         * Local scale factor.
-         */
-        virtual void setScale( const osg::Vec3f& scale );
-        const osg::Vec3f& getScale() const { return _scale; }
-
-        /**
-         * Enables or disable automatic horizon culling
-         */
-        void setHorizonCulling( bool value );
-        bool getHorizonCulling() const;
-
-    public: // AnnotationNode
-
-        virtual Config getConfig() const;
-
-    public: // osg::Node
-
-        virtual osg::BoundingSphere computeBound() const;
-
-    protected:
-
-        /**
-         * The matrix transform that controls this node's position
-         */
-        virtual osg::MatrixTransform* getTransform() =0;
-
-	public:
-        // refreshed the main transform with data from an asbolute point
-        bool updateTransform(const GeoPoint& absPt, osg::Node* patch =0L);
-
-    protected:
-        bool                               _initComplete;
-        GeoPoint                           _mapPosition;
-        osg::Vec3f                         _scale;
-        osg::Vec3d                         _localOffset;
-        osg::Quat                          _localRotation;
-        
-        bool                               _horizonCullingRequested;
-        osg::ref_ptr<HorizonCullCallback>  _horizonCuller;
-
-        friend class Decoration;
-        
-        // re-clamped the vert mesh based on a new terrain tile coming in
-        virtual void reclamp( const TileKey& key, osg::Node* tile, const Terrain* terrain );
-
-        // checks for overlay requirements, and if needed, installs a decorator node above
-        // the passed-in node to facilitate the clamping/draping. The proper usage pattern
-        // is:  node = applyAltitudePolicy(node, style)
-        osg::Node* applyAltitudePolicy( osg::Node* node, const Style& style );
-
-        // hidden copy constructor
-        LocalizedNode() { }
-        LocalizedNode(const LocalizedNode& rhs, const osg::CopyOp& op=osg::CopyOp::DEEP_COPY_ALL) : PositionedAnnotationNode(rhs, op) { }
-        virtual ~LocalizedNode() { }
-
-
-    private:
-
-        void init();
-    };
-
-} } // namespace osgEarth::Annotation
-
-#endif // OSGEARTH_ANNO_LOCALIZED_NODE_H
diff --git a/src/osgEarthAnnotation/LocalizedNode.cpp b/src/osgEarthAnnotation/LocalizedNode.cpp
deleted file mode 100644
index 76deb19..0000000
--- a/src/osgEarthAnnotation/LocalizedNode.cpp
+++ /dev/null
@@ -1,354 +0,0 @@
-/* -*-c++-*- */
-/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
-* http://osgearth.org
-*
-* osgEarth is free software; you can redistribute it and/or modify
-* it under the terms of the GNU Lesser General Public License as published by
-* the Free Software Foundation; either version 2 of the License, or
-* (at your option) any later version.
-*
-* 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.
-*
-* You should have received a copy of the GNU Lesser General Public License
-* along with this program.  If not, see <http://www.gnu.org/licenses/>
-*/
-
-#include <osgEarthAnnotation/LocalizedNode>
-#include <osgEarthAnnotation/AnnotationUtils>
-#include <osgEarth/ClampableNode>
-#include <osgEarth/DrapeableNode>
-#include <osgEarth/CullingUtils>
-#include <osgEarth/MapNode>
-#include <osg/MatrixTransform>
-
-#define LC "[LocalizedNode] "
-
-using namespace osgEarth;
-using namespace osgEarth::Annotation;
-
-
-LocalizedNode::LocalizedNode(MapNode*        mapNode,
-                             const GeoPoint& position) :
-PositionedAnnotationNode( mapNode ),
-_initComplete           ( false ),
-_horizonCullingRequested( true ),
-_scale                  ( 1.0f, 1.0f, 1.0f ),
-_mapPosition            ( position )
-{
-    init();
-}
-
-
-void
-LocalizedNode::init()
-{
-    this->getOrCreateStateSet()->setRenderingHint( osg::StateSet::TRANSPARENT_BIN );    
-    _horizonCuller = new HorizonCullCallback();
-    this->addCullCallback( _horizonCuller.get() );
-}
-
-
-namespace
-{
-    static Threading::Mutex s_initCompleteMutex;
-}
-
-osg::BoundingSphere
-LocalizedNode::computeBound() const
-{
-    if ( !_initComplete )
-    {
-        // perform initialization that cannot happen in the CTOR
-        // (due to possible virtual function calls)
-        Threading::ScopedMutexLock lock(s_initCompleteMutex);
-        if ( !_initComplete )
-        {
-            const_cast<LocalizedNode*>(this)->_initComplete = true;
-            const_cast<LocalizedNode*>(this)->setHorizonCulling( _horizonCullingRequested );
-            const_cast<LocalizedNode*>(this)->setPosition      ( _mapPosition );
-        }
-    }
-    return PositionedAnnotationNode::computeBound();
-}
-
-
-void
-LocalizedNode::setMapNode( MapNode* mapNode )
-{
-    if ( getMapNode() != mapNode )
-    {
-        PositionedAnnotationNode::setMapNode( mapNode );
-
-        // The horizon culler depends on the map node, so reinitialize it:
-        setHorizonCulling( _horizonCullingRequested );
-
-        // re-apply the position since the map has changed
-        setPosition( _mapPosition );
-    }
-}
-
-
-bool
-LocalizedNode::setPosition( const GeoPoint& pos )
-{
-    if ( _initComplete )
-    {
-        if ( getMapNode() )
-        {
-            // first transform the point to the map's SRS:
-            const SpatialReference* mapSRS = getMapNode()->getMapSRS();
-            GeoPoint mapPos = mapSRS ? pos.transform(mapSRS) : pos;
-            if ( !mapPos.isValid() )
-                return false;
-
-            _mapPosition = mapPos;
-        }
-        else
-        {
-            _mapPosition = pos;
-        }
-
-        // make sure the node is set up for auto-z-update if necessary:
-        configureForAltitudeMode( _mapPosition.altitudeMode() );
-
-        // update the node.
-        return updateTransform( _mapPosition );
-    }
-    else
-    {
-        _mapPosition = pos;
-        return true;
-    }
-}
-
-bool
-LocalizedNode::updateTransform( const GeoPoint& p, osg::Node* patch )
-{
-    if ( p.isValid() )
-    {
-        GeoPoint absPos(p);
-        if ( !makeAbsolute(absPos, patch) )
-            return false;
-
-        OE_DEBUG << LC << "Update transforms for position: " << absPos.x() << ", " << absPos.y() << ", " << absPos.z()
-            << std::endl;
-
-        osg::Matrixd local2world;
-        absPos.createLocalToWorld( local2world );
-        
-        // apply the local offsets
-        local2world.preMult( osg::Matrix::translate(_localOffset) );
-
-        getTransform()->setMatrix( 
-            osg::Matrix::scale (_scale)         * 
-            osg::Matrix::rotate(_localRotation) *
-            local2world  );
-    }
-    else
-    {
-        osg::Vec3d absPos = p.vec3d() + _localOffset;
-
-        getTransform()->setMatrix(
-            osg::Matrix::scale    (_scale)         * 
-            osg::Matrix::rotate   (_localRotation) *
-            osg::Matrix::translate(absPos) );
-    }
-    
-
-    dirtyBound();
-
-    return true;
-}
-
-GeoPoint
-LocalizedNode::getPosition() const
-{
-    return _mapPosition;
-}
-
-void
-LocalizedNode::setScale( const osg::Vec3f& scale )
-{
-    _scale = scale;
-    updateTransform( _mapPosition );
-}
-
-void
-LocalizedNode::setLocalOffset( const osg::Vec3d& offset )
-{
-    _localOffset = offset;
-    setPosition( _mapPosition );
-}
-
-const osg::Vec3d&
-LocalizedNode::getLocalOffset() const
-{
-    return _localOffset;
-}
-
-void
-LocalizedNode::setLocalRotation( const osg::Quat& rotation )
-{
-    _localRotation = rotation;
-    setPosition( _mapPosition );
-}
-
-const osg::Quat&
-LocalizedNode::getLocalRotation() const
-{
-    return _localRotation;
-}
-
-void
-LocalizedNode::setHorizonCulling( bool value )
-{
-    _horizonCullingRequested = value;
-
-    if ( _initComplete )
-    {
-        if ( getMapNode() )
-        {
-            _horizonCuller->setHorizon(
-                Horizon(*getMapNode()->getMapSRS()->getEllipsoid()) );
-        }
-
-        _horizonCuller->setEnabled(
-            _horizonCullingRequested &&
-            getMapNode() &&
-            getMapNode()->isGeocentric() );
-    }
-}
-
-void
-LocalizedNode::reclamp( const TileKey& key, osg::Node* tile, const Terrain* terrain )
-{
-    // first verify that the control position intersects the tile:
-    if ( key.getExtent().contains( _mapPosition.x(), _mapPosition.y() ) )
-    {
-        updateTransform(_mapPosition, tile);
-    }
-}
-
-
-osg::Node*
-LocalizedNode::applyAltitudePolicy(osg::Node* node, const Style& style)
-{
-    AnnotationUtils::AltitudePolicy ap;
-    AnnotationUtils::getAltitudePolicy( style, ap );
-
-    // Draped (projected) geometry
-    if ( ap.draping )
-    {
-        DrapeableNode* drapable = new DrapeableNode( getMapNode() );
-        drapable->addChild( node );
-        node = drapable;
-    }
-
-    // gw - not sure whether is makes sense to support this for LocalizedNode
-    // GPU-clamped geometry
-    else if ( ap.gpuClamping )
-    {
-        ClampableNode* clampable = new ClampableNode( getMapNode() );
-        clampable->addChild( node );
-        node = clampable;
-
-        const RenderSymbol* render = style.get<RenderSymbol>();
-        if ( render && render->depthOffset().isSet() )
-        {
-            clampable->setDepthOffsetOptions( *render->depthOffset() );
-        }
-    }
-
-    // scenegraph-clamped geometry
-    else if ( ap.sceneClamping )
-    {
-        // save for later when we need to reclamp the mesh on the CPU
-        _altitude = style.get<AltitudeSymbol>();
-
-        // activate the terrain callback:
-        setCPUAutoClamping( true );
-    }
-
-    return node;
-}
-
-
-//-------------------------------------------------------------------
-
-LocalizedNode::LocalizedNode(MapNode* mapNode, const Config& conf) :
-PositionedAnnotationNode( mapNode, conf ),
-_initComplete           ( false ),
-_horizonCullingRequested( true ),
-_scale                  ( 1.0f, 1.0f, 1.0f )
-{
-    if ( conf.hasChild( "position" ) )
-        setPosition( GeoPoint(conf.child("position")) );
-
-    if ( conf.hasChild( "scale" ) )
-    {
-        const Config* c = conf.child_ptr("scale");
-        osg::Vec3f s( c->value("x", 1.0f), c->value("y", 1.0f), c->value("z", 1.0f) );
-        setScale( s );
-    }
-
-    if ( conf.hasChild( "local_offset" ) )
-    {
-        const Config* c = conf.child_ptr("local_offset");
-        osg::Vec3d o( c->value("x", 0.0), c->value("y", 0.0), c->value("z", 0.0) );
-        setLocalOffset( o );
-    }
-
-    if ( conf.hasChild( "local_rotation" ) )
-    {
-        const Config* c = conf.child_ptr("local_rotation");
-        osg::Quat q( c->value("x", 0.0), c->value("y", 0.0), c->value("z", 0.0), c->value("w", 1.0) );
-        setLocalRotation( q );
-    }
-
-    init();
-}
-
-Config
-LocalizedNode::getConfig() const
-{
-    Config conf = PositionedAnnotationNode::getConfig();
-
-    conf.addObj( "position", getPosition() );
-    
-    if ( _scale.x() != 1.0f || _scale.y() != 1.0f || _scale.z() != 1.0f )
-    {
-        Config c( "scale" );
-        c.add( "x", _scale.x() );
-        c.add( "y", _scale.y() );
-        c.add( "z", _scale.z() );
-        conf.add( c );
-    }
-
-    if ( _localOffset != osg::Vec3d(0,0,0) )
-    {
-        Config c( "local_offset" );
-        c.set( "x", _localOffset.x() );
-        c.set( "y", _localOffset.y() );
-        c.set( "z", _localOffset.z() );
-        conf.add( c );
-    }
-
-    if ( !_localRotation.zeroRotation() )
-    {
-        Config c( "local_rotation" );
-        c.set( "x", _localRotation.x() );
-        c.set( "y", _localRotation.y() );
-        c.set( "z", _localRotation.z() );
-        c.set( "w", _localRotation.w() );
-        conf.add( c );
-    }
-
-    return conf;
-}
diff --git a/src/osgEarthAnnotation/ModelNode b/src/osgEarthAnnotation/ModelNode
index c97aaf3..1886e8f 100644
--- a/src/osgEarthAnnotation/ModelNode
+++ b/src/osgEarthAnnotation/ModelNode
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
@@ -22,7 +22,7 @@
 #ifndef OSGEARTH_ANNO_MODEL_NODE_H
 #define OSGEARTH_ANNO_MODEL_NODE_H 1
 
-#include <osgEarthAnnotation/LocalizedNode>
+#include <osgEarthAnnotation/GeoPositionNode>
 #include <osgEarth/URI>
 #include <osgEarth/CachePolicy>
 #include <osgDB/ReaderWriter>
@@ -36,7 +36,7 @@ namespace osgEarth { namespace Annotation
      * Annotation node that loads a 3D model from a URI and places it
      * at a geo location.
      */
-    class OSGEARTHANNO_EXPORT ModelNode : public LocalizedNode
+    class OSGEARTHANNO_EXPORT ModelNode : public GeoPositionNode
     {
     public:
         /**
@@ -61,7 +61,7 @@ namespace osgEarth { namespace Annotation
 
     public: // LocalizedNode
         
-        virtual void setScale( const osg::Vec3f& scale );
+    //    virtual void setScale( const osg::Vec3f& scale );
 
     public:
 
@@ -76,15 +76,10 @@ namespace osgEarth { namespace Annotation
 
         virtual Config getConfig() const;
 
-    protected: // LocalizedNode
-
-        virtual osg::MatrixTransform* getTransform() { return _xform.get(); }
-
     protected:
 
         Style _style;
         osg::ref_ptr<const osgDB::Options> _dbOptions;
-        osg::ref_ptr<osg::MatrixTransform> _xform;
 
         void init();
 
diff --git a/src/osgEarthAnnotation/ModelNode.cpp b/src/osgEarthAnnotation/ModelNode.cpp
index 28c7718..8e00a4a 100644
--- a/src/osgEarthAnnotation/ModelNode.cpp
+++ b/src/osgEarthAnnotation/ModelNode.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
@@ -22,6 +22,8 @@
 
 #include <osgEarthAnnotation/ModelNode>
 #include <osgEarthAnnotation/AnnotationRegistry>
+#include <osgEarthAnnotation/AnnotationUtils>
+#include <osgEarthAnnotation/GeoPositionNodeAutoScaler>
 #include <osgEarthSymbology/Style>
 #include <osgEarthSymbology/InstanceSymbol>
 #include <osgEarth/AutoScale>
@@ -43,11 +45,10 @@ using namespace osgEarth::Symbology;
 ModelNode::ModelNode(MapNode*              mapNode,
                      const Style&          style,
                      const osgDB::Options* dbOptions ) :
-LocalizedNode( mapNode ),
+GeoPositionNode    ( mapNode, GeoPoint() ),
 _style       ( style ),
 _dbOptions   ( dbOptions )
 {
-    _xform = new osg::MatrixTransform();
     init();
 }
 
@@ -60,32 +61,16 @@ ModelNode::setStyle(const Style& style)
 }
 
 void
-ModelNode::setScale(const osg::Vec3f& scale)
-{
-    osg::StateSet* stateSet = getStateSet();
-    if ( stateSet && stateSet->getBinName() == osgEarth::AUTO_SCALE_BIN )
-    {
-        stateSet->setRenderBinToInherit();
-    }
-    LocalizedNode::setScale( scale );
-}
-
-void
 ModelNode::init()
 {
-    // reset.
-    this->clearDecoration();
-    osgEarth::clearChildren( this );
-    osgEarth::clearChildren( _xform.get() );
-    this->addChild( _xform.get() );
-
-    this->setHorizonCulling(false);
+    osgEarth::clearChildren( getPositionAttitudeTransform() );
 
     osg::ref_ptr<const ModelSymbol> sym = _style.get<ModelSymbol>();
     
     // backwards-compatibility: support for MarkerSymbol (deprecated)
     if ( !sym.valid() && _style.has<MarkerSymbol>() )
     {
+        OE_WARN << LC << "MarkerSymbol is deprecated, please remove it\n";
         osg::ref_ptr<InstanceSymbol> temp = _style.get<MarkerSymbol>()->convertToInstanceSymbol();
         sym = dynamic_cast<const ModelSymbol*>( temp.get() );
     }
@@ -98,9 +83,9 @@ ModelNode::init()
             osg::ref_ptr<osg::Node> node = sym->getModel();
 
             // Try to get a model from URI
-            if (node.valid() == false)
+            if ( !node.valid() )
             {
-                URI uri( sym->url()->eval(), sym->url()->uriContext() );
+                URI uri = sym->url()->evalURI();
 
                 if ( sym->uriAliasMap()->empty() )
                 {
@@ -114,13 +99,13 @@ ModelNode::init()
                     node = uri.getNode( tempOptions.get() );
                 }
 
-                if (node.valid() == false)
+                if ( !node.valid() )
                 {
                     OE_WARN << LC << "No model and failed to load data from " << uri.full() << std::endl;
                 }
             }
 
-            if (node.valid() == true)
+            if ( node.valid() )
             {
                 if ( Registry::capabilities().supportsGLSL() )
                 {
@@ -131,23 +116,34 @@ ModelNode::init()
                         Registry::stateSetCache() );
                 }
 
-                // attach to the transform:
-                _xform->addChild( node );
+                // install clamping/draping if necessary
+                node = AnnotationUtils::installOverlayParent( node.get(), _style );
 
-                // insert a clamping agent if necessary:
-                replaceChild( _xform.get(), applyAltitudePolicy(_xform.get(), _style) );
+                getPositionAttitudeTransform()->addChild( node.get() );
+
+                osg::Vec3d scale(1, 1, 1);
 
                 if ( sym->scale().isSet() )
                 {
                     double s = sym->scale()->eval();
-                    this->setScale( osg::Vec3f(s, s, s) );
+                    scale.set(s, s, s);
                 }
+                if ( sym->scaleX().isSet() )
+                    scale.x() = sym->scaleX()->eval();
+
+                if ( sym->scaleY().isSet() )
+                    scale.y() = sym->scaleY()->eval();
+
+                if ( sym->scaleZ().isSet() )
+                    scale.z() = sym->scaleZ()->eval();
+
+                getPositionAttitudeTransform()->setScale( scale );
 
                 // auto scaling?
                 if ( sym->autoScale() == true )
                 {
-                    this->getOrCreateStateSet()->setRenderBinDetails(0, osgEarth::AUTO_SCALE_BIN );
-                }
+                    this->addCullCallback( new GeoPositionNodeAutoScaler( osg::Vec3d(1,1,1), sym->minAutoScale().value(), sym->maxAutoScale().value() ));
+                } 
 
                 // rotational offsets?
                 if (sym && (sym->heading().isSet() || sym->pitch().isSet() || sym->roll().isSet()) )
@@ -160,10 +156,11 @@ ModelNode::init()
                         osg::DegreesToRadians(heading), osg::Vec3(0,0,1),
                         osg::DegreesToRadians(pitch),   osg::Vec3(1,0,0),
                         osg::DegreesToRadians(roll),    osg::Vec3(0,1,0) );
-                    this->setLocalRotation( rot.getRotate() );
+
+                    getPositionAttitudeTransform()->setAttitude( rot.getRotate() );
                 }
 
-                this->applyGeneralSymbology( _style );
+                this->applyRenderSymbology( _style );
             }
             else
             {
@@ -187,11 +184,9 @@ OSGEARTH_REGISTER_ANNOTATION( model, osgEarth::Annotation::ModelNode );
 
 
 ModelNode::ModelNode(MapNode* mapNode, const Config& conf, const osgDB::Options* dbOptions) :
-LocalizedNode( mapNode, conf ),
+GeoPositionNode    ( mapNode, conf ),
 _dbOptions   ( dbOptions )
 {
-    _xform = new osg::MatrixTransform();
-
     conf.getObjIfSet( "style", _style );
 
     std::string uri = conf.value("url");
@@ -204,7 +199,7 @@ _dbOptions   ( dbOptions )
 Config
 ModelNode::getConfig() const
 {
-    Config conf = LocalizedNode::getConfig();
+    Config conf = GeoPositionNode::getConfig();
     conf.key() = "model";
 
     if ( !_style.empty() )
diff --git a/src/osgEarthAnnotation/OrthoNode b/src/osgEarthAnnotation/OrthoNode
deleted file mode 100644
index 363c212..0000000
--- a/src/osgEarthAnnotation/OrthoNode
+++ /dev/null
@@ -1,158 +0,0 @@
-/* -*-c++-*- */
-/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
-* http://osgearth.org
-*
-* osgEarth is free software; you can redistribute it and/or modify
-* it under the terms of the GNU Lesser General Public License as published by
-* the Free Software Foundation; either version 2 of the License, or
-* (at your option) any later version.
-*
-* 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.
-*
-* You should have received a copy of the GNU Lesser General Public License
-* along with this program.  If not, see <http://www.gnu.org/licenses/>
-*/
-#ifndef OSGEARTH_ANNO_ORTHO_NODE_H
-#define OSGEARTH_ANNO_ORTHO_NODE_H 1
-
-#include <osgEarthAnnotation/AnnotationNode>
-#include <osgEarth/Decluttering>
-#include <osgEarth/SpatialReference>
-#include <osgEarth/Horizon>
-#include <osgEarth/CullingUtils>
-#include <osg/AutoTransform>
-#include <osg/MatrixTransform>
-
-namespace osgEarth { namespace Annotation
-{	
-    using namespace osgEarth;
-
-    /**
-     * Base class for an annotation node that it drawn in screen-space
-     * (as an orthographic overlay)
-     *
-     * Don't use this class directly. Use one of its subclasses instead like
-     * LabelNode or PlaceNode.
-     */
-    class OSGEARTHANNO_EXPORT OrthoNode : public PositionedAnnotationNode, 
-                                          public SupportsDecluttering
-    {
-    public:
-        META_AnnotationNode( osgEarthAnnotation, OrthoNode );
-
-        /**
-         * Constructs an relative-position ortho node
-         */
-        OrthoNode();
-
-        /**
-         * Constructs an ortho node that resides at an absolute position on the map
-         * @param mapNode  MapNode used to referenced the ortho node
-         * @param position Starting position
-         */
-        OrthoNode( 
-            MapNode*        mapNode, 
-            const GeoPoint& position );
-
-        /**
-         * Attaches a child node to the transforms. Use this instead of addChild.
-         */
-        virtual osg::Group* getAttachPoint() { return _attachPoint; }
-
-
-    public: // PositionedAnnotationNode
-
-        /** Sets the node position */
-        virtual bool setPosition( const GeoPoint& pos );
-
-        /** Gets the position (in map coordinates) of the node */
-        virtual GeoPoint getPosition() const;
-
-    public:
-        /**
-         * Sets a "local offset" position - for an ECEF map, this is an offset in 
-         * the local tangent plane of the node that is applied to the geometry.
-         */
-        void setLocalOffset( const osg::Vec3d& offset );
-
-        /**
-         * Gets the local tangent plane -space offset.
-         */
-        const osg::Vec3d& getLocalOffset() const;
-
-        /**
-         * Enables or disable automatic horizon culling for geocentric maps
-         */
-        void setHorizonCulling(bool value);
-        bool getHorizonCulling() const;
-
-        /**
-         * Enables or disables ray based occlusion culling
-         */
-        bool getOcclusionCulling() const;
-        void setOcclusionCulling( bool value );
-
-        /**
-         * Gets or sets the maximum altitude that the occlusion culling takes place.
-         */
-        double getOcclusionCullingMaxAltitude() const;
-        void setOcclusionCullingMaxAltitude( double occlusionCullingMaxAltitude );
-
-    public: // AnnotationNode
-
-        virtual void applyStyle(const Style& style);
-
-    public: // MapNodeObserver
-
-        virtual void setMapNode( MapNode* mapNode );
-
-    public: // osg::Node
-
-        virtual void traverse( osg::NodeVisitor& nv );
-
-        virtual osg::BoundingSphere computeBound() const;
-
-    protected:
-        /** virtual dtor */
-        virtual ~OrthoNode() { }
-
-    private:
-        osg::Switch*                   _switch;
-        osg::Group*                    _oq;
-        osg::AutoTransform*            _autoxform;
-        osg::MatrixTransform*          _matxform;
-        osg::Group*                    _attachPoint;
-        bool                           _occlusionCulling;
-        optional< double >             _occlusionCullingMaxAltitude;
-        GeoPoint                       _mapPosition;
-        osg::Vec3d                     _localOffset;
-        bool                           _horizonCullingRequested;
-
-        osg::ref_ptr< HorizonCullCallback >      _horizonCuller;
-        osg::ref_ptr< OcclusionCullingCallback > _occlusionCuller;
-
-        void init();
-
-        osg::Vec3d adjustOcclusionCullingPoint( const osg::Vec3d& world );
-
-    protected:
-        // required by META_Node, but this object is not cloneable
-        OrthoNode( const OrthoNode& rhs, const osg::CopyOp& op =osg::CopyOp::DEEP_COPY_ALL ) : PositionedAnnotationNode(rhs, op) { }
-
-    private:
-        // autoclamping.
-        virtual void reclamp( const TileKey& key, osg::Node* tile, const Terrain* );
-
-        bool updateTransforms( const GeoPoint& mappos, osg::Node* patch =0L );
-    };
-
-} } // namespace osgEarth::Annotation
-
-#endif // OSGEARTH_ANNO_LOCALIZED_NODE_H
diff --git a/src/osgEarthAnnotation/OrthoNode.cpp b/src/osgEarthAnnotation/OrthoNode.cpp
deleted file mode 100644
index 0c66c5b..0000000
--- a/src/osgEarthAnnotation/OrthoNode.cpp
+++ /dev/null
@@ -1,413 +0,0 @@
-/* -*-c++-*- */
-/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
-* http://osgearth.org
-*
-* osgEarth is free software; you can redistribute it and/or modify
-* it under the terms of the GNU Lesser General Public License as published by
-* the Free Software Foundation; either version 2 of the License, or
-* (at your option) any later version.
-*
-* 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.
-*
-* You should have received a copy of the GNU Lesser General Public License
-* along with this program.  If not, see <http://www.gnu.org/licenses/>
-*/
-
-#include <osgEarthAnnotation/OrthoNode>
-#include <osgEarthAnnotation/AnnotationUtils>
-#include <osgEarthAnnotation/AnnotationSettings>
-#include <osgEarthSymbology/Color>
-#include <osgEarth/ThreadingUtils>
-#include <osgEarth/CullingUtils>
-#include <osgEarth/MapNode>
-#include <osgText/Text>
-#include <osg/ComputeBoundsVisitor>
-#include <osgUtil/IntersectionVisitor>
-#include <osg/OcclusionQueryNode>
-#include <osg/Point>
-#include <osg/Depth>
-#include <osg/Switch>
-
-#define LC "[OrthoNode] "
-
-using namespace osgEarth;
-using namespace osgEarth::Annotation;
-
-
-OrthoNode::OrthoNode(MapNode*        mapNode,
-                     const GeoPoint& position ) :
-
-PositionedAnnotationNode( mapNode ),
-_occlusionCulling       ( false ),
-_horizonCullingRequested( true )
-{
-    init();
-    setPosition( position );
-}
-
-
-OrthoNode::OrthoNode() :
-_occlusionCulling       ( false ),
-_horizonCullingRequested( true )
-{
-    init();
-}
-
-
-void
-OrthoNode::init()
-{
-    _switch = new osg::Switch();
-    this->addChild( _switch );
-
-    _autoxform = new AnnotationUtils::OrthoNodeAutoTransform();
-    _autoxform->setAutoRotateMode( osg::AutoTransform::ROTATE_TO_SCREEN );
-    _autoxform->setAutoScaleToScreen( true );
-    _autoxform->setCullingActive( false ); // for the first pass
-    _switch->addChild( _autoxform );
-
-    _matxform = new osg::MatrixTransform();
-    _switch->addChild( _matxform );
-    _switch->setSingleChildOn( 0 );
-
-    _attachPoint = new osg::Group();
-    _autoxform->addChild( _attachPoint );
-    _matxform->addChild( _attachPoint );
-
-    this->getOrCreateStateSet()->setMode( GL_LIGHTING, 0 );
-
-    // Callback to cull ortho nodes that are not visible over the geocentric horizon
-    _horizonCuller = new HorizonCullCallback();
-    setHorizonCulling( _horizonCullingRequested );
-
-    _attachPoint->addCullCallback( _horizonCuller.get() );
-}
-
-osg::BoundingSphere
-OrthoNode::computeBound() const
-{
-    osg::BoundingSphere bs = PositionedAnnotationNode::computeBound();
-    //OE_NOTICE << "BOUND RADIUS = " << bs.radius() << "\n";
-    return bs;
-}
-
-void
-OrthoNode::traverse( osg::NodeVisitor& nv )
-{
-    osgUtil::CullVisitor* cv = 0L;
-
-    if ( nv.getVisitorType() == osg::NodeVisitor::CULL_VISITOR )
-    {
-        cv = Culling::asCullVisitor(nv);
-
-        // make sure that we're NOT using the AutoTransform if this node is in the decluttering bin;
-        // the decluttering bin automatically manages screen space transformation.
-        bool declutter = cv->getCurrentRenderBin()->getName() == OSGEARTH_DECLUTTER_BIN;
-        if ( declutter && _switch->getValue(0) == 1 )
-        {
-            _switch->setSingleChildOn( 1 );
-        }
-        else if ( !declutter && _switch->getValue(0) == 0 )
-        {
-            _switch->setSingleChildOn( 0 );
-        }
-
-        // If decluttering is enabled, update the auto-transform but not its children.
-        // This is necessary to support picking/selection. An optimization would be to
-        // disable this pass when picking is not in use
-        //if ( !declutter )
-        //{
-        //    static_cast<AnnotationUtils::OrthoNodeAutoTransform*>(_autoxform)->accept( nv, false );
-        //}
-
-        // turn off small feature culling
-        // (note: pretty sure this does nothing here -gw)
-        cv->setSmallFeatureCullingPixelSize(-1.0f);
-
-        AnnotationNode::traverse( nv );
-
-        if ( _autoxform->getCullingActive() == false )
-        {
-            _autoxform->setCullingActive( true );
-            this->dirtyBound();
-        }
-    }
-    
-    // For an intersection visitor, ALWAYS traverse the autoxform instead of the 
-    // matrix transform. The matrix transform is only used in combination with the 
-    // decluttering engine, so it cannot properly support picking of decluttered
-    // objects
-    else if ( 
-        nv.getVisitorType() == osg::NodeVisitor::NODE_VISITOR &&
-        dynamic_cast<osgUtil::IntersectionVisitor*>( &nv ) )
-    {
-        if ( static_cast<AnnotationUtils::OrthoNodeAutoTransform*>(_autoxform)->okToIntersect() )
-        {
-            _autoxform->accept( nv );
-        }
-    }
-
-    else
-    {
-        AnnotationNode::traverse( nv );
-    }
-}
-
-void
-OrthoNode::setMapNode( MapNode* mapNode )
-{
-    MapNode* oldMapNode = getMapNode();
-    if ( oldMapNode != mapNode )
-    {
-        PositionedAnnotationNode::setMapNode( mapNode );
-
-        // the occlusion culler depends on the mapnode, so re-initialize it:
-        if ( _occlusionCulling )
-        {
-            setOcclusionCulling( false );
-            setOcclusionCulling( true );
-        }
-
-        // same goes for the horizon culler:
-        _horizonCuller->setHorizon( Horizon(*mapNode->getMapSRS()->getEllipsoid()) );
-        setHorizonCulling( _horizonCullingRequested );
-
-        // re-apply the position since the map has changed
-        setPosition( getPosition() );
-    }
-}
-
-bool
-OrthoNode::setPosition( const GeoPoint& position )
-{
-    MapNode* mapNode = getMapNode();
-    if ( mapNode )
-    {
-        // first transform the point to the map's SRS:
-        const SpatialReference* mapSRS = mapNode->getMapSRS();
-        GeoPoint mapPos = mapSRS ? position.transform(mapSRS) : position;
-        if ( !mapPos.isValid() )
-            return false;
-
-        _mapPosition = mapPos;
-    }
-    else
-    {
-        _mapPosition = position;
-    }
-
-    // make sure the node is set up for auto-z-update if necessary:
-    configureForAltitudeMode( _mapPosition.altitudeMode() );
-
-    // and update the node.
-    if ( !updateTransforms(_mapPosition) )
-        return false;
-
-    return true;
-}
-
-void
-OrthoNode::applyStyle(const Style& style)
-{
-    // check for decluttering.
-    const TextSymbol* text = style.get<TextSymbol>();
-    if ( text && text->declutter().isSet() )
-    {
-        Decluttering::setEnabled( this->getOrCreateStateSet(), (text->declutter() == true) );
-    }
-
-
-    // check for occlusion culling
-    if ( text && text->occlusionCull().isSet() )
-    {
-        setOcclusionCulling( *text->occlusionCull() );
-
-        if (text->occlusionCullAltitude().isSet())
-        {
-            setOcclusionCullingMaxAltitude( *text->occlusionCullAltitude() );
-        }
-    }
-
-    const IconSymbol* icon = style.get<IconSymbol>();
-    if ( icon && icon->declutter().isSet() )
-    {
-        Decluttering::setEnabled( this->getOrCreateStateSet(), (icon->declutter() == true) );
-    }
-
-    // check for occlusion culling
-    if ( icon && icon->occlusionCull().isSet() )
-    {
-        this->setOcclusionCulling( *icon->occlusionCull() );
-
-        if (icon->occlusionCullAltitude().isSet())
-        {
-            setOcclusionCullingMaxAltitude( *icon->occlusionCullAltitude() );
-        }
-    }
-
-    // up the chain
-    PositionedAnnotationNode::applyStyle( style );
-}
-
-bool
-OrthoNode::updateTransforms( const GeoPoint& p, osg::Node* patch )
-{
-    if ( getMapNode() )
-    {
-        //OE_NOTICE << "updateTransforms" << std::endl;
-        // make sure the point is absolute to terrain
-        GeoPoint absPos(p);
-        if ( !makeAbsolute(absPos, patch) )
-            return false;
-
-        osg::Matrixd local2world;
-        if ( !absPos.createLocalToWorld(local2world) )
-            return false;
-
-        // apply the local tangent plane offset:
-        local2world.preMult( osg::Matrix::translate(_localOffset) );
-
-        // update the xforms:
-        _autoxform->setPosition( local2world.getTrans() );
-        _matxform->setMatrix( local2world );
-        
-        osg::Vec3d world = local2world.getTrans();
-
-        if (_occlusionCuller.valid())
-        {                                
-            _occlusionCuller->setWorld( adjustOcclusionCullingPoint( world ));
-        } 
-    }
-    else
-    {
-        osg::Vec3d absPos = p.vec3d() + _localOffset;
-        _autoxform->setPosition( absPos );
-        _matxform->setMatrix( osg::Matrix::translate(absPos) );
-    }
-
-    dirtyBound();
-    return true;
-}
-
-GeoPoint
-OrthoNode::getPosition() const
-{
-    return _mapPosition;
-}
-
-void
-OrthoNode::setLocalOffset( const osg::Vec3d& offset )
-{
-    _localOffset = offset;
-    setPosition( _mapPosition );
-}
-
-const osg::Vec3d&
-OrthoNode::getLocalOffset() const
-{
-    return _localOffset;
-}
-
-bool
-OrthoNode::getHorizonCulling() const
-{
-    return _horizonCullingRequested;
-}
-
-void
-OrthoNode::setHorizonCulling(bool value)
-{
-    _horizonCullingRequested = value;
-
-    _horizonCuller->setEnabled(
-        _horizonCullingRequested &&
-        getMapNode() &&
-        getMapNode()->isGeocentric() );
-}
-
-osg::Vec3d
-OrthoNode::adjustOcclusionCullingPoint( const osg::Vec3d& world )
-{
-    // Adjust the height by a little bit "up", we can't have the occlusion point sitting right on the ground
-    if ( getMapNode() )
-    {
-        const osg::EllipsoidModel* em = getMapNode()->getMapSRS()->getEllipsoid();
-        osg::Vec3d up = em ? em->computeLocalUpVector( world.x(), world.y(), world.z() ) : osg::Vec3d(0,0,1);
-        osg::Vec3d adjust = up * AnnotationSettings::getOcclusionCullingHeightAdjustment();        
-        return world + adjust;
-    }
-    else
-    {
-        return world;
-    }
-}
-
-bool
-OrthoNode::getOcclusionCulling() const
-{
-    return _occlusionCulling;
-}
-
-void
-OrthoNode::setOcclusionCulling( bool value )
-{
-    if (_occlusionCulling != value)
-    {
-        _occlusionCulling = value;
-
-        if ( _occlusionCulling && getMapNode() )
-        {
-            osg::Vec3d world = _autoxform->getPosition();
-            _occlusionCuller = new OcclusionCullingCallback( getMapNode()->getMapSRS(),  adjustOcclusionCullingPoint(world), getMapNode()->getTerrainEngine() );
-            _occlusionCuller->setMaxAltitude( getOcclusionCullingMaxAltitude() );
-            addCullCallback( _occlusionCuller.get()  );
-        }
-        else
-        {
-            if (_occlusionCulling)
-            {
-                if (_occlusionCuller.valid())
-                {
-                    removeCullCallback( _occlusionCuller.get() );
-                    _occlusionCuller = 0;
-                }
-            }
-        }
-    }
-}
-
-double
-OrthoNode::getOcclusionCullingMaxAltitude() const
-{
-    if (_occlusionCullingMaxAltitude.isSet())
-    {
-        return *_occlusionCullingMaxAltitude;
-    }
-    return AnnotationSettings::getOcclusionCullingMaxAltitude();
-}
-
-void OrthoNode::setOcclusionCullingMaxAltitude( double occlusionCullingMaxAltitude )
-{
-    _occlusionCullingMaxAltitude = occlusionCullingMaxAltitude;
-    if ( _occlusionCuller.valid() )
-    {
-        _occlusionCuller->setMaxAltitude( getOcclusionCullingMaxAltitude() );         
-    }
-}
-
-void
-OrthoNode::reclamp( const TileKey& key, osg::Node* tile, const Terrain* terrain )
-{
-    // first verify that the label position intersects the tile:
-    if ( key.getExtent().contains( _mapPosition.x(), _mapPosition.y() ) )
-    {
-        updateTransforms( _mapPosition, tile );
-    }
-}
diff --git a/src/osgEarthAnnotation/PlaceNode b/src/osgEarthAnnotation/PlaceNode
index afa6905..016d450 100644
--- a/src/osgEarthAnnotation/PlaceNode
+++ b/src/osgEarthAnnotation/PlaceNode
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
@@ -22,8 +22,9 @@
 #ifndef OSGEARTH_ANNOTATION_PLACE_NODE_H
 #define OSGEARTH_ANNOTATION_PLACE_NODE_H 1
 
-#include <osgEarthAnnotation/OrthoNode>
+#include <osgEarthAnnotation/GeoPositionNode>
 #include <osgEarthSymbology/Style>
+#include <osgEarth/ScreenSpaceLayout>
 
 namespace osgEarth { namespace Annotation
 {
@@ -34,7 +35,7 @@ namespace osgEarth { namespace Annotation
      * A PlaceNode combines an 2D icon, a label, support for mouse interaction
      * and a popup control (eventually)
      */
-    class OSGEARTHANNO_EXPORT PlaceNode : public OrthoNode
+    class OSGEARTHANNO_EXPORT PlaceNode : public GeoPositionNode
     {
     public:
         META_AnnotationNode(osgEarthAnnotation, PlaceNode);
@@ -110,31 +111,44 @@ namespace osgEarth { namespace Annotation
         void setStyle( const Style& style );
         const Style& getStyle() const { return _style; }
 
+    public: // GeoPositionNode override
 
-    public: // OrthoNode override
-
-        virtual void setAnnotationData( AnnotationData* data );
-
+        virtual void setPriority( float value );
         virtual void setDynamic( bool value );
 
         virtual Config getConfig() const;
 
+        virtual void dirty();
+
     protected:
 
         virtual ~PlaceNode() { }
-        
-    private:
+
         osg::ref_ptr<osg::Image>           _image;
         std::string                        _text;
         Style                              _style;
         class osg::Geode*                  _geode;
         osg::ref_ptr<const osgDB::Options> _dbOptions;
+        osg::ref_ptr<ScreenSpaceLayoutData> _dataLayout;
+
+        /** rotation of the label **/
+        float                    _labelRotationRad;
+        bool                     _followFixedCourse;
+        GeoPoint                 _geoPointLoc;
+        GeoPoint                 _geoPointProj;
 
         void init();
+        void updateLayoutData();
 
+    public:
         // required by META_Node, but this object is not cloneable
-        PlaceNode() { }
-        PlaceNode(const PlaceNode& rhs, const osg::CopyOp& op =osg::CopyOp::DEEP_COPY_ALL) : OrthoNode(rhs, op) { }
+        PlaceNode();
+
+        void setConfig(const Config& conf);
+
+    private:
+        PlaceNode(const PlaceNode& rhs, const osg::CopyOp& op =osg::CopyOp::DEEP_COPY_ALL) : GeoPositionNode(rhs, op) { }
+
     };
 
 } } // namespace osgEarth::Annotation
diff --git a/src/osgEarthAnnotation/PlaceNode.cpp b/src/osgEarthAnnotation/PlaceNode.cpp
index 2967813..ee4c5c1 100644
--- a/src/osgEarthAnnotation/PlaceNode.cpp
+++ b/src/osgEarthAnnotation/PlaceNode.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
@@ -23,11 +23,14 @@
 #include <osgEarthAnnotation/PlaceNode>
 #include <osgEarthAnnotation/AnnotationUtils>
 #include <osgEarthAnnotation/AnnotationRegistry>
+#include <osgEarthAnnotation/BboxDrawable>
 #include <osgEarthFeatures/BuildTextFilter>
 #include <osgEarthFeatures/LabelSource>
 #include <osgEarth/Utils>
 #include <osgEarth/Registry>
 #include <osgEarth/ShaderGenerator>
+#include <osgEarth/GeoMath>
+#include <osgEarth/ScreenSpaceLayout>
 
 #include <osg/Depth>
 #include <osgText/Text>
@@ -39,6 +42,12 @@ using namespace osgEarth::Annotation;
 using namespace osgEarth::Features;
 using namespace osgEarth::Symbology;
 
+PlaceNode::PlaceNode() :
+_labelRotationRad ( 0. ),
+_followFixedCourse( false )
+{
+    //nop
+}
 
 PlaceNode::PlaceNode(MapNode*           mapNode,
                      const GeoPoint&    position,
@@ -46,11 +55,13 @@ PlaceNode::PlaceNode(MapNode*           mapNode,
                      const std::string& text,
                      const Style&       style ) :
 
-OrthoNode( mapNode, position ),
+GeoPositionNode( mapNode, position ),
 _image   ( image ),
 _text    ( text ),
 _style   ( style ),
-_geode   ( 0L )
+_geode            ( 0L ),
+_labelRotationRad ( 0. ),
+_followFixedCourse( false )
 {
     init();
 }
@@ -60,10 +71,12 @@ PlaceNode::PlaceNode(MapNode*           mapNode,
                      const std::string& text,
                      const Style&       style ) :
 
-OrthoNode( mapNode, position ),
+GeoPositionNode( mapNode, position ),
 _text    ( text ),
 _style   ( style ),
-_geode   ( 0L )
+_geode            ( 0L ),
+_labelRotationRad ( 0. ),
+_followFixedCourse( false )
 {
     init();
 }
@@ -72,9 +85,11 @@ PlaceNode::PlaceNode(MapNode*              mapNode,
                      const GeoPoint&       position,
                      const Style&          style,
                      const osgDB::Options* dbOptions ) :
-OrthoNode ( mapNode, position ),
+GeoPositionNode ( mapNode, position ),
 _style    ( style ),
-_dbOptions( dbOptions )
+_dbOptions        ( dbOptions ),
+_labelRotationRad ( 0. ),
+_followFixedCourse( false )
 {
     init();
 }
@@ -82,9 +97,9 @@ _dbOptions( dbOptions )
 void
 PlaceNode::init()
 {
-    //reset.
-    this->clearDecoration();
-    getAttachPoint()->removeChildren(0, getAttachPoint()->getNumChildren());
+    ScreenSpaceLayout::activate( this->getOrCreateStateSet() );
+
+    osgEarth::clearChildren( getPositionAttitudeTransform() );
 
     _geode = new osg::Geode();
 
@@ -94,10 +109,28 @@ PlaceNode::init()
 
     osg::Drawable* text = 0L;
 
+    const TextSymbol* symbol = _style.get<TextSymbol>();
+
     // If there's no explicit text, look to the text symbol for content.
-    if ( _text.empty() && _style.has<TextSymbol>() )
+    if ( _text.empty() && symbol )
+    {
+        _text = symbol->content()->eval();
+    }
+
+    // Handle the rotation if any
+    if ( symbol && symbol->onScreenRotation().isSet() )
+    {
+        _labelRotationRad = osg::DegreesToRadians(symbol->onScreenRotation()->eval());
+    }
+
+    // In case of a label must follow a course on map, we project a point from the position
+    // with the given bearing. Then during culling phase we compute both points on the screen
+    // and then we can deduce the screen rotation
+    // may be optimized...
+    else if ( symbol && symbol->geographicCourse().isSet() )
     {
-        _text = _style.get<TextSymbol>()->content()->eval();
+        _followFixedCourse = true;
+        _labelRotationRad = osg::DegreesToRadians ( symbol->geographicCourse()->eval() );
     }
 
     osg::ref_ptr<const InstanceSymbol> instance = _style.get<InstanceSymbol>();
@@ -118,7 +151,7 @@ PlaceNode::init()
         {
             if ( icon->url().isSet() )
             {
-                imageURI = URI( icon->url()->eval(), icon->url()->uriContext() );
+                imageURI = icon->url()->evalURI();
             }
             else if (icon->getImage())
             {
@@ -132,6 +165,8 @@ PlaceNode::init()
         }
     }
 
+    osg::BoundingBox imageBox(0,0,0,0,0,0);
+
     // found an image; now format it:
     if ( _image.get() )
     {
@@ -200,28 +235,38 @@ PlaceNode::init()
         if ( imageGeom )
         {
             _geode->addDrawable( imageGeom );
-        }
-
-        text = AnnotationUtils::createTextDrawable(
-            _text,
-            _style.get<TextSymbol>(),
-            osg::Vec3( (offset.x() + (s / 2.0) + 2), offset.y(), 0 ) );
+            imageBox = osgEarth::Utils::getBoundingBox( imageGeom );
+        }    
     }
-    else
+
+    if ( _image.valid() )
     {
-        text = AnnotationUtils::createTextDrawable(
+        TextSymbol* textSymbol = _style.getOrCreate<TextSymbol>();
+        if ( !textSymbol->alignment().isSet() )
+            textSymbol->alignment() = textSymbol->ALIGN_LEFT_CENTER;
+    }
+
+    text = AnnotationUtils::createTextDrawable(
             _text,
             _style.get<TextSymbol>(),
-            osg::Vec3( 0, 0, 0 ) );
+            imageBox );
+
+    const BBoxSymbol* bboxsymbol = _style.get<BBoxSymbol>();
+    if ( bboxsymbol && text )
+    {
+        osg::Drawable* bboxGeom = new BboxDrawable( osgEarth::Utils::getBoundingBox(text), *bboxsymbol );
+        _geode->addDrawable(bboxGeom);
     }
 
     if ( text )
+    {
         _geode->addDrawable( text );
+    }
     
     osg::StateSet* stateSet = _geode->getOrCreateStateSet();
     stateSet->setAttributeAndModes( new osg::Depth(osg::Depth::ALWAYS, 0, 1, false), 1 );
 
-    getAttachPoint()->addChild( _geode );
+    getPositionAttitudeTransform()->addChild( _geode );
 
     // for clamping and occlusion culling    
     //OE_WARN << LC << "PlaceNode::applyStyle: " << _style.getConfig().toJSON(true) << std::endl;
@@ -235,15 +280,83 @@ PlaceNode::init()
         "osgEarth.PlaceNode",
         Registry::stateSetCache() );
 
-    // re-apply annotation drawable-level stuff as neccesary.
-    AnnotationData* ad = getAnnotationData();
-    if ( ad )
-        setAnnotationData( ad );
+    setPriority(getPriority());
 
     if ( _dynamic )
         setDynamic( _dynamic );
+
+    updateLayoutData();
+}
+
+void
+PlaceNode::dirty()
+{
+    GeoPositionNode::dirty();
+    updateLayoutData();
+}
+
+void
+PlaceNode::setPriority(float value)
+{
+    GeoPositionNode::setPriority(value);
+    updateLayoutData();
 }
 
+void
+PlaceNode::updateLayoutData()
+{
+    if (!_dataLayout.valid())
+    {
+        _dataLayout = new ScreenSpaceLayoutData();
+    }
+
+    // re-apply annotation drawable-level stuff as neccesary.
+    for (unsigned i = 0; i < _geode->getNumDrawables(); ++i)
+    {
+        _geode->getDrawable(i)->setUserData(_dataLayout.get());
+    }
+
+    _dataLayout->setPriority(getPriority());    
+    
+    GeoPoint location = getPosition();
+    location.makeGeographic();
+    double latRad;
+    double longRad;
+    GeoMath::destination(osg::DegreesToRadians(location.y()),
+        osg::DegreesToRadians(location.x()),
+        _labelRotationRad,
+        2500.,
+        latRad,
+        longRad);
+
+    _geoPointProj.set(osgEarth::SpatialReference::get("wgs84"),
+        osg::RadiansToDegrees(longRad),
+        osg::RadiansToDegrees(latRad),
+        0,
+        osgEarth::ALTMODE_ABSOLUTE);
+
+    _geoPointLoc.set(osgEarth::SpatialReference::get("wgs84"),
+        //location.getSRS(),
+        location.x(),
+        location.y(),
+        0,
+        osgEarth::ALTMODE_ABSOLUTE);
+
+    const TextSymbol* ts = getStyle().get<TextSymbol>();
+    if (ts)
+    {
+        _dataLayout->setPixelOffset(ts->pixelOffset().get());
+        
+        if (_followFixedCourse)
+        {
+            osg::Vec3d p0, p1;
+            _geoPointLoc.toWorld(p0);
+            _geoPointProj.toWorld(p1);
+            _dataLayout->setAnchorPoint(p0);
+            _dataLayout->setProjPoint(p1);
+        }
+    }
+}
 
 void
 PlaceNode::setText( const std::string& text )
@@ -294,22 +407,9 @@ PlaceNode::setIconImage(osg::Image* image)
 
 
 void
-PlaceNode::setAnnotationData( AnnotationData* data )
-{
-    OrthoNode::setAnnotationData( data );
-
-    // override this method so we can attach the anno data to the drawables.
-    for(unsigned i=0; i<_geode->getNumDrawables(); ++i)
-    {
-        _geode->getDrawable(i)->setUserData( data );
-    }
-}
-
-
-void
 PlaceNode::setDynamic( bool value )
 {
-    OrthoNode::setDynamic( value );
+    GeoPositionNode::setDynamic( value );
     
     for(unsigned i=0; i<_geode->getNumDrawables(); ++i)
     {
@@ -318,8 +418,6 @@ PlaceNode::setDynamic( bool value )
     }
 }
 
-
-
 //-------------------------------------------------------------------
 
 OSGEARTH_REGISTER_ANNOTATION( place, osgEarth::Annotation::PlaceNode );
@@ -328,8 +426,10 @@ OSGEARTH_REGISTER_ANNOTATION( place, osgEarth::Annotation::PlaceNode );
 PlaceNode::PlaceNode(MapNode*              mapNode,
                      const Config&         conf,
                      const osgDB::Options* dbOptions) :
-OrthoNode ( mapNode, conf ),
-_dbOptions( dbOptions )
+GeoPositionNode ( mapNode, conf ),
+_dbOptions( dbOptions ),
+_labelRotationRad ( 0. ),
+_followFixedCourse( false )
 {
     conf.getObjIfSet( "style",  _style );
     conf.getIfSet   ( "text",   _text );
@@ -344,9 +444,26 @@ _dbOptions( dbOptions )
     }
 
     init();
+}
+
+void
+PlaceNode::setConfig(const Config& conf)
+{
+    GeoPositionNode::setConfig(conf);
+
+    conf.getObjIfSet( "style",  _style );
+    conf.getIfSet   ( "text",   _text );
+
+    optional<URI> imageURI;
+    conf.getIfSet( "icon", imageURI );
+    if ( imageURI.isSet() )
+    {
+        _image = imageURI->getImage();
+        if ( _image.valid() )
+            _image->setFileName( imageURI->base() );
+    }
 
-    if ( conf.hasChild("position") )
-        setPosition( GeoPoint(conf.child("position")) );
+    init();
 }
 
 Config
@@ -355,7 +472,6 @@ PlaceNode::getConfig() const
     Config conf( "place" );
     conf.add   ( "text",   _text );
     conf.addObj( "style",  _style );
-    conf.addObj( "position", getPosition() );
     if ( _image.valid() ) {
         if ( !_image->getFileName().empty() )
             conf.add( "icon", _image->getFileName() );
@@ -365,3 +481,45 @@ PlaceNode::getConfig() const
 
     return conf;
 }
+
+
+#undef  LC
+#define LC "[PlaceNode Serializer] "
+
+#include <osgDB/ObjectWrapper>
+#include <osgDB/InputStream>
+#include <osgDB/OutputStream>
+
+namespace
+{
+    // functions
+    static bool checkConfig(const osgEarth::Annotation::PlaceNode& node)
+    {
+        return true;
+    }
+
+    static bool readConfig(osgDB::InputStream& is, osgEarth::Annotation::PlaceNode& node)
+    {
+        std::string json;
+        is >> json;
+        Config conf;
+        conf.fromJSON(json);
+        node.setConfig(conf);
+        return true;
+    }
+
+    static bool writeConfig(osgDB::OutputStream& os, const osgEarth::Annotation::PlaceNode& node)
+    {
+        os << node.getConfig().toJSON(false) << std::endl;
+        return true;
+    }
+
+    REGISTER_OBJECT_WRAPPER(
+        PlaceNode,
+        new osgEarth::Annotation::PlaceNode,
+        osgEarth::Annotation::PlaceNode,
+        "osg::Object osg::Node osg::Group osgEarth::Annotation::AnnotationNode osgEarth::Annotation::GeoPositionNode osgEarth::Annotation::PlaceNode")
+    {
+        ADD_USER_SERIALIZER(Config);
+    }
+}
diff --git a/src/osgEarthAnnotation/RectangleNode b/src/osgEarthAnnotation/RectangleNode
index fefe7f7..ce0e4c6 100644
--- a/src/osgEarthAnnotation/RectangleNode
+++ b/src/osgEarthAnnotation/RectangleNode
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
@@ -23,7 +23,7 @@
 #ifndef OSGEARTH_ANNOTATION_RECTANGLE_NODE_H
 #define OSGEARTH_ANNOTATION_RECTANGLE_NODE_H 1
 
-#include <osgEarthAnnotation/LocalizedNode>
+#include <osgEarthAnnotation/GeoPositionNode>
 #include <osgEarthSymbology/Style>
 #include <osgEarth/MapNode>
 #include <osgEarth/Units>
@@ -36,7 +36,7 @@ namespace osgEarth { namespace Annotation
     /**
      * Rectangle annotation.
      */
-    class OSGEARTHANNO_EXPORT RectangleNode : public LocalizedNode
+    class OSGEARTHANNO_EXPORT RectangleNode : public GeoPositionNode
     {
     public:
         enum Corner
@@ -126,10 +126,6 @@ namespace osgEarth { namespace Annotation
 
         RectangleNode(MapNode* mapNode, const Config& conf, const osgDB::Options* options);
         virtual Config getConfig() const;
-        
-    protected: // LocalizedNode
-
-        virtual osg::MatrixTransform* getTransform() { return _xform.get(); }
 
     private:
         RectangleNode() { }
@@ -140,8 +136,6 @@ namespace osgEarth { namespace Annotation
         Style  _style;
         Linear _width;
         Linear _height;
-
-        osg::ref_ptr<osg::MatrixTransform> _xform;
     };
 
 } } // namespace osgEarth::Annotation
diff --git a/src/osgEarthAnnotation/RectangleNode.cpp b/src/osgEarthAnnotation/RectangleNode.cpp
index 3ac110d..db095aa 100644
--- a/src/osgEarthAnnotation/RectangleNode.cpp
+++ b/src/osgEarthAnnotation/RectangleNode.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
@@ -22,6 +22,7 @@
 
 #include <osgEarthAnnotation/RectangleNode>
 #include <osgEarthAnnotation/AnnotationRegistry>
+#include <osgEarthAnnotation/AnnotationUtils>
 #include <osgEarthFeatures/GeometryCompiler>
 #include <osgEarthSymbology/GeometryFactory>
 #include <osgEarthSymbology/ExtrusionSymbol>
@@ -40,12 +41,11 @@ RectangleNode::RectangleNode(MapNode*          mapNode,
                              const Linear&     width,
                              const Linear&     height,
                              const Style&      style) :
-LocalizedNode( mapNode, position ),
+GeoPositionNode    ( mapNode, position ),
 _width       ( width ),
 _height      ( height ),
 _style       ( style )
 {
-    _xform = new osg::MatrixTransform();
     rebuild();
 }
 
@@ -334,13 +334,7 @@ RectangleNode::setCorner( Corner corner, const GeoPoint& location)
 void
 RectangleNode::rebuild()
 {    
-    std::string currentDecoration = getDecoration();
-    clearDecoration();
-
-    // Reset:
-    osgEarth::clearChildren( this );
-    osgEarth::clearChildren( _xform.get() );
-    this->addChild( _xform.get() );
+    osgEarth::clearChildren( getPositionAttitudeTransform() );
 
     // construct a local-origin circle.
     GeometryFactory factory;    
@@ -348,19 +342,16 @@ RectangleNode::rebuild()
     if ( geom )
     {
         GeometryCompiler compiler;
-        osg::ref_ptr<Feature> feature = new Feature(geom, 0L); //todo: consider the SRS
-        osg::Node* node = compiler.compile( feature.get(), _style, FilterContext(0L) );
+        osg::ref_ptr<osg::Node> node = compiler.compile( geom, _style, FilterContext(0L) );
         if ( node )
         {
-            _xform->addChild( node );
-            replaceChild( _xform.get(), applyAltitudePolicy(_xform.get(), _style) );
+            node = AnnotationUtils::installOverlayParent( node.get(), _style );
+            getPositionAttitudeTransform()->addChild( node.get() );
         }
 
-        applyGeneralSymbology( _style );
+        applyRenderSymbology( _style );
         setLightingIfNotSet( false );
     }
-
-    setDecoration( currentDecoration );
 }
 
 
@@ -373,10 +364,8 @@ OSGEARTH_REGISTER_ANNOTATION( rectangle, osgEarth::Annotation::RectangleNode );
 RectangleNode::RectangleNode(MapNode*              mapNode,
                              const Config&         conf,
                              const osgDB::Options* dbOptions) :
-LocalizedNode( mapNode, conf )
+GeoPositionNode( mapNode, conf )
 {
-    _xform = new osg::MatrixTransform();
-
     conf.getObjIfSet( "width", _width );
     conf.getObjIfSet( "height", _height );
     conf.getObjIfSet( "style",  _style );
@@ -387,7 +376,7 @@ LocalizedNode( mapNode, conf )
 Config
 RectangleNode::getConfig() const
 {
-    Config conf = LocalizedNode::getConfig();
+    Config conf = GeoPositionNode::getConfig();
     conf.key() = "rectangle";
 
     conf.addObj( "width",  _width );
diff --git a/src/osgEarthAnnotation/ScaleDecoration b/src/osgEarthAnnotation/ScaleDecoration
index dbb5e47..839169f 100644
--- a/src/osgEarthAnnotation/ScaleDecoration
+++ b/src/osgEarthAnnotation/ScaleDecoration
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
@@ -29,6 +29,7 @@ namespace osgEarth { namespace Annotation
 {	
     using namespace osgEarth;
 
+#if 0
     /**
      * A decoration technique that scales the annotation.
      */
@@ -46,6 +47,7 @@ namespace osgEarth { namespace Annotation
     protected:
         float _factor;
     };
+#endif
 
 } } // namespace osgEarth::Annotation
 
diff --git a/src/osgEarthAnnotation/TrackNode b/src/osgEarthAnnotation/TrackNode
index 371cdac..a40f6fd 100644
--- a/src/osgEarthAnnotation/TrackNode
+++ b/src/osgEarthAnnotation/TrackNode
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
@@ -22,7 +22,7 @@
 #ifndef OSGEARTH_ANNOTATION_TRACK_NODE_H
 #define OSGEARTH_ANNOTATION_TRACK_NODE_H 1
 
-#include <osgEarthAnnotation/OrthoNode>
+#include <osgEarthAnnotation/GeoPositionNode>
 #include <osgEarthSymbology/Style>
 #include <osgEarth/Containers>
 #include <osg/Image>
@@ -80,7 +80,7 @@ namespace osgEarth { namespace Annotation
      * presumably the entity itself will be responsible for its own absolute
      * positioning (and clamping, if applicable).
      */
-    class OSGEARTHANNO_EXPORT TrackNode : public OrthoNode
+    class OSGEARTHANNO_EXPORT TrackNode : public GeoPositionNode
     {
     public:
         META_AnnotationNode(osgEarthAnnotation, TrackNode);
@@ -135,9 +135,9 @@ namespace osgEarth { namespace Annotation
          */
         osg::Drawable* getDrawable( const std::string& name ) const;
 
-    public: // override
+    public:
 
-        virtual void setAnnotationData( AnnotationData* data );
+        virtual void setPriority(float value);
 
     protected:
 
@@ -156,6 +156,8 @@ namespace osgEarth { namespace Annotation
         TrackNode() { }
         TrackNode(const TrackNode& rhs, const osg::CopyOp& op =osg::CopyOp::DEEP_COPY_ALL) { }
 
+        void updateLayoutData();
+
     };
 
 } } // namespace osgEarth::Annotation
diff --git a/src/osgEarthAnnotation/TrackNode.cpp b/src/osgEarthAnnotation/TrackNode.cpp
index 1c2c10e..3a021c9 100644
--- a/src/osgEarthAnnotation/TrackNode.cpp
+++ b/src/osgEarthAnnotation/TrackNode.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
@@ -25,6 +25,7 @@
 #include <osgEarth/MapNode>
 #include <osgEarth/Registry>
 #include <osgEarth/ShaderGenerator>
+#include <osgEarth/ScreenSpaceLayout>
 #include <osg/Depth>
 #include <osgText/Text>
 
@@ -41,7 +42,7 @@ TrackNode::TrackNode(MapNode*                    mapNode,
                      osg::Image*                 image,
                      const TrackNodeFieldSchema& fieldSchema ) :
 
-OrthoNode   ( mapNode, position )
+GeoPositionNode   ( mapNode, position )
 {
     if ( image )
     {
@@ -57,7 +58,7 @@ TrackNode::TrackNode(MapNode*                    mapNode,
                      const Style&                style,
                      const TrackNodeFieldSchema& fieldSchema ) :
 
-OrthoNode   ( mapNode, position ),
+GeoPositionNode   ( mapNode, position ),
 _style      ( style )
 {
     init( fieldSchema );
@@ -66,6 +67,11 @@ _style      ( style )
 void
 TrackNode::init( const TrackNodeFieldSchema& schema )
 {
+    // tracknodes draw in screen space at their geoposition.
+    ScreenSpaceLayout::activate( this->getOrCreateStateSet() );
+
+    osgEarth::clearChildren( getPositionAttitudeTransform() );
+
     _geode = new osg::Geode();
 
     IconSymbol* icon = _style.get<IconSymbol>();
@@ -84,6 +90,10 @@ TrackNode::init( const TrackNodeFieldSchema& schema )
         if ( imageGeom )
         {
             _geode->addDrawable( imageGeom );
+
+            ScreenSpaceLayoutData* layout = new ScreenSpaceLayoutData();
+            layout->setPriority(getPriority());
+            imageGeom->setUserData(layout);
         }
     }
 
@@ -96,10 +106,15 @@ TrackNode::init( const TrackNodeFieldSchema& schema )
             const TrackNodeField& field = i->second;
             if ( field._symbol.valid() )
             {
+                osg::Vec3 offset(
+                    field._symbol->pixelOffset()->x(),
+                    field._symbol->pixelOffset()->y(),
+                    0.0);
+
                 osg::Drawable* drawable = AnnotationUtils::createTextDrawable( 
                     field._symbol->content()->expr(),   // text
                     field._symbol.get(),                // symbol
-                    osg::Vec3(0,0,0) );                 // offset
+                    offset );                           // offset
 
                 if ( drawable )
                 {
@@ -124,7 +139,7 @@ TrackNode::init( const TrackNodeFieldSchema& schema )
 
     setLightingIfNotSet( false );
 
-    getAttachPoint()->addChild( _geode );
+    getPositionAttitudeTransform()->addChild( _geode );
     
     // generate shaders:
     Registry::shaderGenerator().run(
@@ -134,6 +149,26 @@ TrackNode::init( const TrackNodeFieldSchema& schema )
 }
 
 void
+TrackNode::setPriority(float value)
+{
+    GeoPositionNode::setPriority( value );
+    updateLayoutData();
+}
+
+void
+TrackNode::updateLayoutData()
+{
+    osg::ref_ptr<ScreenSpaceLayoutData> data = new ScreenSpaceLayoutData();
+    data->setPriority(getPriority());
+
+    // re-apply annotation drawable-level stuff as neccesary.
+    for (unsigned i = 0; i<_geode->getNumDrawables(); ++i)
+    {
+        _geode->getDrawable(i)->setUserData(data.get());
+    }
+}
+
+void
 TrackNode::setFieldValue( const std::string& name, const osgText::String& value )
 {
     NamedDrawables::const_iterator i = _namedDrawables.find(name);
@@ -163,12 +198,9 @@ TrackNode::setFieldValue( const std::string& name, const osgText::String& value
 void
 TrackNode::addDrawable( const std::string& name, osg::Drawable* drawable )
 {
-    // attach the annotation data to the drawable:
-    if ( _annoData.valid() )
-        drawable->setUserData( _annoData.get() );
-
     _namedDrawables[name] = drawable;
     _geode->addDrawable( drawable );
+    updateLayoutData();
 }
 
 osg::Drawable*
@@ -177,15 +209,3 @@ TrackNode::getDrawable( const std::string& name ) const
     NamedDrawables::const_iterator i = _namedDrawables.find(name);
     return i != _namedDrawables.end() ? i->second : 0L;
 }
-
-void
-TrackNode::setAnnotationData( AnnotationData* data )
-{
-    OrthoNode::setAnnotationData( data );
-
-    // override this method so we can attach the anno data to the drawables.
-    for(unsigned i=0; i<_geode->getNumDrawables(); ++i)
-    {
-        _geode->getDrawable(i)->setUserData( data );
-    }
-}
diff --git a/src/osgEarthDrivers/CMakeLists.txt b/src/osgEarthDrivers/CMakeLists.txt
index 9c4e18a..85fa291 100644
--- a/src/osgEarthDrivers/CMakeLists.txt
+++ b/src/osgEarthDrivers/CMakeLists.txt
@@ -38,4 +38,4 @@ SUBDIRLIST(PLUGIN_DIRS ${CMAKE_CURRENT_SOURCE_DIR})
 FOREACH(subdir ${PLUGIN_DIRS})
     # MESSAGE("Adding driver ${subdir}")
     ADD_SUBDIRECTORY(${subdir})
-ENDFOREACH()
\ No newline at end of file
+ENDFOREACH()
diff --git a/src/osgEarthDrivers/agglite/AGGLiteOptions b/src/osgEarthDrivers/agglite/AGGLiteOptions
index 76da64f..882d053 100644
--- a/src/osgEarthDrivers/agglite/AGGLiteOptions
+++ b/src/osgEarthDrivers/agglite/AGGLiteOptions
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthDrivers/agglite/AGGLiteRasterizerTileSource.cpp b/src/osgEarthDrivers/agglite/AGGLiteRasterizerTileSource.cpp
index dfcac4c..7566849 100644
--- a/src/osgEarthDrivers/agglite/AGGLiteRasterizerTileSource.cpp
+++ b/src/osgEarthDrivers/agglite/AGGLiteRasterizerTileSource.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -160,6 +160,8 @@ public:
         const GeoExtent&   imageExtent,
         osg::Image*        image )
     {
+        OE_DEBUG << LC << "Rendering " << features.size() << " features for " << imageExtent.toString() << "\n";
+
         // A processing context to use with the filters:
         FilterContext context( session );
         context.setProfile( getFeatureSource()->getFeatureProfile() );
@@ -482,7 +484,7 @@ class AGGLiteRasterizerTileSourceDriver : public TileSourceDriver
     public:
         AGGLiteRasterizerTileSourceDriver() {}
 
-        virtual const char* className()
+        virtual const char* className() const
         {
             return "AGG-Lite feature rasterizer";
         }
diff --git a/src/osgEarthDrivers/arcgis/ArcGISOptions b/src/osgEarthDrivers/arcgis/ArcGISOptions
index e096d4e..d407319 100644
--- a/src/osgEarthDrivers/arcgis/ArcGISOptions
+++ b/src/osgEarthDrivers/arcgis/ArcGISOptions
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthDrivers/arcgis/Extent.h b/src/osgEarthDrivers/arcgis/Extent.h
index 93dbe39..678707f 100644
--- a/src/osgEarthDrivers/arcgis/Extent.h
+++ b/src/osgEarthDrivers/arcgis/Extent.h
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthDrivers/arcgis/MapService.cpp b/src/osgEarthDrivers/arcgis/MapService.cpp
index 2d7bea0..b24c3ec 100644
--- a/src/osgEarthDrivers/arcgis/MapService.cpp
+++ b/src/osgEarthDrivers/arcgis/MapService.cpp
@@ -30,8 +30,13 @@ MapServiceLayer::getName() const {
 
 //===========================================================================
 
-TileInfo::TileInfo()
-: is_valid( false )
+TileInfo::TileInfo() :
+is_valid( false ),
+tile_size(0),
+min_level(0),
+max_level(0),
+num_tiles_wide(0),
+num_tiles_high(0)
 {
     //NOP
 }
diff --git a/src/osgEarthDrivers/arcgis/MapService.h b/src/osgEarthDrivers/arcgis/MapService.h
index 47cf262..e74fd24 100644
--- a/src/osgEarthDrivers/arcgis/MapService.h
+++ b/src/osgEarthDrivers/arcgis/MapService.h
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthDrivers/arcgis/ReaderWriterArcGIS.cpp b/src/osgEarthDrivers/arcgis/ReaderWriterArcGIS.cpp
index 3196cb9..e2d0c05 100644
--- a/src/osgEarthDrivers/arcgis/ReaderWriterArcGIS.cpp
+++ b/src/osgEarthDrivers/arcgis/ReaderWriterArcGIS.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
@@ -136,9 +136,10 @@ public:
         {
 			OE_INFO << LC << "_map_service.init failed: " << _map_service.getError() << std::endl;
 
-            return Status::Error( Stringify()
-                << "[osgearth] [ArcGIS] map service initialization failed: "
-                << _map_service.getError() );
+            return Status::Error(
+                Status::ResourceUnavailable, Stringify()
+                    << "[osgearth] [ArcGIS] map service initialization failed: "
+                    << _map_service.getError() );
         }
 
         _dbOptions = Registry::instance()->cloneOrCreateOptions( dbOptions );        
@@ -268,7 +269,7 @@ public:
         supportsExtension( "osgearth_arcgis", "ArcGIS Server" );
     }
 
-    virtual const char* className()
+    virtual const char* className() const
     {
         return "ArcGIS Server REST ReaderWriter";
     }
diff --git a/src/osgEarthDrivers/arcgis_map_cache/ReaderWriterArcGISMapCache.cpp b/src/osgEarthDrivers/arcgis_map_cache/ReaderWriterArcGISMapCache.cpp
index a4a8035..696ee6b 100644
--- a/src/osgEarthDrivers/arcgis_map_cache/ReaderWriterArcGISMapCache.cpp
+++ b/src/osgEarthDrivers/arcgis_map_cache/ReaderWriterArcGISMapCache.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -129,7 +129,7 @@ class ReaderWriterAGSMapCache : public TileSourceDriver
             supportsExtension( "osgearth_arcgis_map_cache", "ArcGIS Server Map Service Cache" );
         }
 
-        virtual const char* className()
+        virtual const char* className() const
         {
             return "ArcGIS Server Map Service Cache Imagery ReaderWriter";
         }
diff --git a/src/osgEarthDrivers/bing/BingOptions b/src/osgEarthDrivers/bing/BingOptions
index 8770036..83fcea5 100644
--- a/src/osgEarthDrivers/bing/BingOptions
+++ b/src/osgEarthDrivers/bing/BingOptions
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -40,8 +40,8 @@ namespace osgEarth { namespace Drivers
         /**
          * API Key to use to access Bing REST services. Required!
          */
-        optional<std::string>& key() { return _apiKey; }
-        const optional<std::string>& key() const { return _apiKey; }
+        optional<std::string>& apiKey() { return _apiKey; }
+        const optional<std::string>& apiKey() const { return _apiKey; }
 
         /**
          * Imagery set to access. Default is "Aerial".
diff --git a/src/osgEarthDrivers/bing/BingTileSource.cpp b/src/osgEarthDrivers/bing/BingTileSource.cpp
index 3ef5340..95f9911 100644
--- a/src/osgEarthDrivers/bing/BingTileSource.cpp
+++ b/src/osgEarthDrivers/bing/BingTileSource.cpp
@@ -41,11 +41,11 @@ namespace
 }
 
 
-class BingTileSource : public TileSource
+class BingTileSource : public TileSource, public osgEarth::Drivers::BingOptions
 {
 private:
-    osgEarth::Drivers::BingOptions _options;
-    osg::ref_ptr<osgDB::Options>   _dbOptions;
+    //osgEarth::Drivers::BingOptions _options;
+    osg::ref_ptr<const osgDB::Options> _readOptions;
     Random                         _prng;
     bool                           _debugDirect;
     osg::ref_ptr<Geometry>         _geom;
@@ -59,7 +59,8 @@ public:
      */
     BingTileSource(const TileSourceOptions& options) : 
       TileSource   ( options ),
-      _options     ( options ),
+      BingOptions  ( options ),
+      //_options     ( options ),
       _debugDirect ( false ),
       _tileURICache( true, 1024u )
     {
@@ -82,20 +83,18 @@ public:
      */
     Status initialize(const osgDB::Options* dbOptions)
     {
-        // Always apply the NO CACHE policy.  Bing doesn't allow caching of their data.
-        _dbOptions = Registry::instance()->cloneOrCreateOptions(dbOptions);
-        CachePolicy::NO_CACHE.apply( _dbOptions.get() );
+        _readOptions = dbOptions;
 
         // If the user did not include an API key, fail.
-        if ( !_options.key().isSet() )
+        if ( !apiKey().isSet() )
         {
-            return Status::Error("Bing API key is required");
+            return Status::Error(Status::ConfigurationError, "Bing API key is required");
         }
 
         // If the user did not specify an imagery set, default to aerial.
-        if ( !_options.imagerySet().isSet() )
+        if ( !imagerySet().isSet() )
         {
-            _options.imagerySet() = "Aerial";
+            imagerySet() = "Aerial";
         }
 
         // Bing maps profile is spherical mercator with 2x2 tiles are the root.
@@ -111,6 +110,7 @@ public:
     
     /**
      * Tell the terrain engine not to cache tiles form this source.
+     * Always apply the NO CACHE policy.  Bing doesn't allow caching of their data.
      */
     CachePolicy getCachePolicyHint(const Profile*) const
     {
@@ -127,7 +127,7 @@ public:
 
         if (_debugDirect)
         {
-            image = URI(getDirectURI(key)).getImage(_dbOptions.get(), progress);
+            image = URI(getDirectURI(key)).getImage(_readOptions.get(), progress);
         }
 
         else
@@ -149,12 +149,12 @@ public:
             // construct the request URI:
             std::string request = Stringify()
                 << std::setprecision(12)
-                << _options.imageryMetadataAPI().get()     // base REST API
-                << "/"    << _options.imagerySet().get()   // imagery set to use
+                << imageryMetadataAPI().get()     // base REST API
+                << "/"    << imagerySet().get()   // imagery set to use
                 << "/"    << geo.y() << "," << geo.x()     // center point in lat/long
                 << "?zl=" << key.getLOD() + 1              // zoom level
                 << "&o=json"                               // response format
-                << "&key=" << _options.key().get();        // API key
+                << "&key=" << apiKey().get();        // API key
 
             // check the URI cache.
             URI                  location;
@@ -170,10 +170,10 @@ public:
             {
                 unsigned c = ++_apiCount;
                 if ( c % 25 == 0 )
-                    OE_INFO << LC << "API calls = " << c << std::endl;
+                    OE_DEBUG << LC << "API calls = " << c << std::endl;
             
                 // fetch it:
-                ReadResult metadataResult = URI(request).readString(_dbOptions, progress);
+                ReadResult metadataResult = URI(request).readString(_readOptions, progress);
 
                 if ( metadataResult.failed() )
                 {
@@ -290,7 +290,7 @@ public:
         supportsExtension( "osgearth_bing", "Microsoft Bing Driver" );
     }
 
-    virtual const char* className()
+    virtual const char* className() const
     {
         return "Microsoft Bing Driver";
     }
diff --git a/src/osgEarthDrivers/bumpmap/BumpMap.frag.common.glsl b/src/osgEarthDrivers/bumpmap/BumpMap.frag.common.glsl
new file mode 100644
index 0000000..797734f
--- /dev/null
+++ b/src/osgEarthDrivers/bumpmap/BumpMap.frag.common.glsl
@@ -0,0 +1,26 @@
+#pragma vp_define OE_USE_NORMAL_MAP
+
+#ifdef OE_USE_NORMAL_MAP
+
+// normal map version:
+uniform sampler2D oe_tile_normalTex;
+in vec2 oe_normalMapCoords;
+
+float oe_bumpmap_getSlope()
+{
+    vec4 encodedNormal = texture2D(oe_nmap_normalTex, oe_normalMapCoords);
+    vec3 normalTangent = normalize(encodedNormal.xyz*2.0-1.0);
+    return clamp((1.0-normalTangent.z)/0.8, 0.0, 1.0);
+}
+
+#else // OE_USE_NORMAL_MAP
+
+// non- normal map version:
+in float oe_bumpmap_slope;
+
+float oe_bumpmap_getSlope()
+{
+    return oe_bumpmap_slope;
+}
+
+#endif // OE_USE_NORMAL_MAP
diff --git a/src/osgEarthDrivers/bumpmap/BumpMap.frag.progressive.glsl b/src/osgEarthDrivers/bumpmap/BumpMap.frag.progressive.glsl
new file mode 100644
index 0000000..a3d2ee5
--- /dev/null
+++ b/src/osgEarthDrivers/bumpmap/BumpMap.frag.progressive.glsl
@@ -0,0 +1,60 @@
+#version $GLSL_VERSION_STR
+
+#pragma vp_entryPoint oe_bumpmap_fragment
+#pragma vp_location   fragment_coloring
+#pragma vp_order      0.3
+
+#pragma include BumpMap.frag.common.glsl
+
+uniform sampler2D oe_bumpmap_tex;
+uniform float     oe_bumpmap_intensity;
+uniform int       oe_bumpmap_octaves;
+uniform float     oe_bumpmap_maxRange;
+uniform float     oe_bumpmap_slopeFactor;
+
+// framework/stage global
+in vec3 vp_Normal;
+in vec3 oe_UpVectorView;
+
+// from BumpMap.model.vert.glsl
+in vec2 oe_bumpmap_coords;
+flat in mat3 oe_bumpmap_normalMatrix;
+
+// from BumpMap.view.vert.glsl
+in float oe_bumpmap_range;
+
+// Entry point for progressive blended bump maps
+void oe_bumpmap_fragment(inout vec4 color)
+{
+	// sample the bump map
+    const float amplitudeDecay = 1.0; // no decay.
+    float maxLOD = float(oe_bumpmap_octaves)+1.0;
+
+    // starter vector:
+    vec3 bump = vec3(0.0);    
+    float scale = 1.0;
+    float amplitude = 1.0;
+    float limit = oe_bumpmap_range;
+    float range = oe_bumpmap_maxRange;
+    float lastRange = oe_bumpmap_maxRange;
+    for(float lod = 1.0; lod < maxLOD; lod += 1.0, scale *= 2.0, amplitude *= amplitudeDecay)
+    {
+        float fadeIn = 1.0;
+        if ( range <= limit && limit < oe_bumpmap_maxRange )
+            fadeIn = clamp((lastRange-limit)/(lastRange-range), 0.0, 1.0);
+        bump += (texture2D(oe_bumpmap_tex, oe_bumpmap_coords*scale).xyz*2.0-1.0)*amplitude*fadeIn;
+        if ( range <= limit )
+            break;
+        lastRange = range;
+        range = oe_bumpmap_maxRange/exp(lod);
+    }
+
+    // finally, transform into view space and normalize the vector.
+    bump = normalize(oe_bumpmap_normalMatrix*bump);
+    
+    // calculate slope from normal:
+    float slope = mix(1.0, 1.0 - dot(oe_UpVectorView, vp_Normal), oe_bumpmap_slopeFactor);
+
+	// permute the normal with the bump.
+	vp_Normal = normalize(vp_Normal + bump*oe_bumpmap_intensity*slope);
+}
diff --git a/src/osgEarthDrivers/bumpmap/BumpMap.frag.simple.glsl b/src/osgEarthDrivers/bumpmap/BumpMap.frag.simple.glsl
new file mode 100644
index 0000000..a160378
--- /dev/null
+++ b/src/osgEarthDrivers/bumpmap/BumpMap.frag.simple.glsl
@@ -0,0 +1,29 @@
+#version $GLSL_VERSION_STR
+
+#pragma vp_entryPoint oe_bumpmap_fragment
+#pragma vp_location   fragment_coloring
+#pragma vp_order      0.3
+
+#pragma include BumpMap.frag.common.glsl
+
+in vec3 vp_Normal;
+in vec2 oe_bumpmap_coords;
+flat in mat3 oe_bumpmap_normalMatrix;
+in vec3 oe_UpVectorView;
+
+uniform sampler2D oe_bumpmap_tex;
+uniform float     oe_bumpmap_intensity;
+uniform float     oe_bumpmap_slopeFactor;
+
+
+void oe_bumpmap_fragment(inout vec4 color)
+{
+	// sample the bump map
+    vec3 bump = oe_bumpmap_normalMatrix * normalize(texture2D(oe_bumpmap_tex, oe_bumpmap_coords).xyz*2.0-1.0);
+    
+    // calculate slope from normal:
+    float slope = clamp( (1.0-dot(oe_UpVectorView, vp_Normal))*oe_bumpmap_slopeFactor, 0.0, 1.0);
+    
+	// permute the normal with the bump.
+	vp_Normal = normalize(vp_Normal + bump*oe_bumpmap_intensity*slope);
+}
diff --git a/src/osgEarthDrivers/bumpmap/BumpMap.vert.view.glsl b/src/osgEarthDrivers/bumpmap/BumpMap.vert.view.glsl
new file mode 100644
index 0000000..0528203
--- /dev/null
+++ b/src/osgEarthDrivers/bumpmap/BumpMap.vert.view.glsl
@@ -0,0 +1,52 @@
+#version $GLSL_VERSION_STR
+
+#pragma vp_entryPoint oe_bumpmap_vertexView
+#pragma vp_location   vertex_view
+#pragma vp_order      0.5
+
+uniform vec4 oe_tile_key;
+uniform float oe_bumpmap_scale;
+uniform float oe_bumpmap_baseLOD;
+
+out vec4 oe_layer_tilec;
+out vec3 vp_Normal;
+
+out vec2 oe_bumpmap_coords;
+out float oe_bumpmap_range;
+flat out mat3 oe_bumpmap_normalMatrix;
+
+
+vec2 oe_bumpmap_scaleCoords(in vec2 coords, in float targetLOD)
+{
+    float dL = oe_tile_key.z - targetLOD;
+    float factor = exp2(dL);
+    float invFactor = 1.0/factor;
+    vec2 scale = vec2(invFactor);
+    vec2 result = coords * scale;
+
+    // For upsampling we need to calculate an offset as well
+    float upSampleToggle = factor >= 1.0 ? 1.0 : 0.0;
+    {
+        vec2 a = floor(oe_tile_key.xy * invFactor);
+        vec2 b = a * factor;
+        vec2 c = (a+1.0) * factor;
+        vec2 offset = (oe_tile_key.xy-b)/(c-b);
+        result += upSampleToggle * offset;
+    }
+
+    return result;
+}
+
+void oe_bumpmap_vertexView(inout vec4 vertexView)
+{
+    oe_bumpmap_range = -vertexView.z;
+
+    // quantize the scale factor
+    float iscale = float(int(oe_bumpmap_scale));
+
+    // scale sampling coordinates to a target LOD.
+    oe_bumpmap_coords = oe_bumpmap_scaleCoords(oe_layer_tilec.st, floor(oe_bumpmap_baseLOD)) * iscale;
+
+    // propagate normal matrix to fragment stage
+    oe_bumpmap_normalMatrix = gl_NormalMatrix;
+}
diff --git a/src/osgEarthDrivers/bumpmap/BumpMapExtension b/src/osgEarthDrivers/bumpmap/BumpMapExtension
new file mode 100644
index 0000000..f93aafd
--- /dev/null
+++ b/src/osgEarthDrivers/bumpmap/BumpMapExtension
@@ -0,0 +1,75 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+ * Copyright 2016 Pelican Mapping
+ * http://osgearth.org
+ *
+ * osgEarth is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ */
+#ifndef OSGEARTH_BUMPMAP_EXTENSION
+#define OSGEARTH_BUMPMAP_EXTENSION 1
+
+#include "BumpMapOptions"
+#include "BumpMapTerrainEffect"
+#include <osgEarth/Extension>
+#include <osgEarth/MapNode>
+#include <osgEarthUtil/Controls>
+
+namespace osgEarth { namespace BumpMap
+{
+    using namespace osgEarth;
+    using namespace osgEarth::Util::Controls;
+
+    /**
+     * Extension for loading the normal mapping effect on demand.
+     */
+    class BumpMapExtension : public Extension,
+                             public ExtensionInterface<MapNode>,
+                             public BumpMapOptions
+    {
+    public:
+        META_Object(osgearth_ext_BumpMap, BumpMapExtension);
+
+        // CTORs
+        BumpMapExtension();
+        BumpMapExtension(const BumpMapOptions& options);
+
+        // DTOR
+        virtual ~BumpMapExtension();
+
+
+    public: // Extension
+
+        virtual void setDBOptions(const osgDB::Options* dbOptions);
+
+        virtual const ConfigOptions& getConfigOptions() const { return *this; }
+
+
+    public: // ExtensionInterface<MapNode>
+
+        bool connect(MapNode* mapNode);
+
+        bool disconnect(MapNode* mapNode);
+
+
+    protected: // Object
+        BumpMapExtension(const BumpMapExtension& rhs, const osg::CopyOp& op) { }
+
+    private:
+        osg::ref_ptr<const osgDB::Options>   _dbOptions;
+        osg::ref_ptr<BumpMapTerrainEffect>   _effect;
+    };
+
+} } // namespace osgEarth::BumpMap
+
+#endif // OSGEARTH_BUMPMAP_EXTENSION
diff --git a/src/osgEarthDrivers/bumpmap/BumpMapExtension.cpp b/src/osgEarthDrivers/bumpmap/BumpMapExtension.cpp
new file mode 100644
index 0000000..72caaa1
--- /dev/null
+++ b/src/osgEarthDrivers/bumpmap/BumpMapExtension.cpp
@@ -0,0 +1,106 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+ * Copyright 2016 Pelican Mapping
+ * http://osgearth.org
+ *
+ * osgEarth is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ */
+#include "BumpMapExtension"
+#include "BumpMapTerrainEffect"
+
+#include <osgEarth/MapNode>
+#include <osgEarth/TerrainEngineNode>
+
+using namespace osgEarth;
+using namespace osgEarth::BumpMap;
+
+#define LC "[BumpMapExtension] "
+
+
+REGISTER_OSGEARTH_EXTENSION(osgearth_bumpmap, BumpMapExtension);
+REGISTER_OSGEARTH_EXTENSION(osgearth_bump_map, BumpMapExtension);
+
+
+BumpMapExtension::BumpMapExtension()
+{
+    //nop
+}
+
+BumpMapExtension::BumpMapExtension(const BumpMapOptions& options) :
+BumpMapOptions( options )
+{
+    //nop
+}
+
+BumpMapExtension::~BumpMapExtension()
+{
+    //nop
+}
+
+void
+BumpMapExtension::setDBOptions(const osgDB::Options* dbOptions)
+{
+    _dbOptions = dbOptions;
+}
+
+bool
+BumpMapExtension::connect(MapNode* mapNode)
+{
+    if ( !mapNode )
+    {
+        OE_WARN << LC << "Illegal: MapNode cannot be null." << std::endl;
+        return false;
+    }
+    
+    osg::ref_ptr<osg::Image> image = imageURI()->getImage( _dbOptions.get() );
+    if ( !image.valid() )
+    {
+        OE_WARN << LC << "Failed; unable to load normal map image from "
+            << imageURI()->full() << "\n";
+        return false;
+    }
+
+    _effect = new BumpMapTerrainEffect( _dbOptions.get() );
+    _effect->setBumpMapImage( image.get() );
+
+    if (intensity().isSet())
+        _effect->getIntensityUniform()->set( intensity().get() );
+
+    if (scale().isSet())
+        _effect->getScaleUniform()->set( scale().get() );
+
+    if ( octaves().isSet() )
+        _effect->setOctaves( octaves().get() );
+
+    if ( baseLOD().isSet() )
+        _effect->setBaseLOD( baseLOD().get() );
+
+    mapNode->getTerrainEngine()->addEffect( _effect.get() );
+    
+    OE_INFO << LC << "Installed.\n";
+
+    return true;
+}
+
+bool
+BumpMapExtension::disconnect(MapNode* mapNode)
+{
+    if ( mapNode )
+    {
+        mapNode->getTerrainEngine()->removeEffect( _effect.get() );
+    }
+    _effect = 0L;
+    return true;
+}
+
diff --git a/src/osgEarthDrivers/bumpmap/BumpMapOptions b/src/osgEarthDrivers/bumpmap/BumpMapOptions
new file mode 100644
index 0000000..312cf58
--- /dev/null
+++ b/src/osgEarthDrivers/bumpmap/BumpMapOptions
@@ -0,0 +1,118 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+ * Copyright 2016 Pelican Mapping
+ * http://osgearth.org
+ *
+ * osgEarth is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ */
+#ifndef OSGEARTH_DRIVER_BUMPMAP_OPTIONS
+#define OSGEARTH_DRIVER_BUMPMAP_OPTIONS 1
+
+#include <osgEarth/Common>
+#include <osgEarth/URI>
+
+namespace osgEarth { namespace BumpMap
+{
+    using namespace osgEarth;
+
+    /**
+     * Options governing bump mapping of the terrain.
+     * A Bump Map is a repeating normal texture that modifies the
+     * existing normal vector per fragment.
+     */
+    class BumpMapOptions : public DriverConfigOptions // NO EXPORT; header only
+    {
+    public:
+        // bump map texture to load.
+        optional<URI>& imageURI() { return _imageURI; }
+        const optional<URI>& imageURI() const { return _imageURI; }
+
+        // Intensity of normal map effect.
+        optional<float>& intensity() { return _intensity; }
+        const optional<float>& intensity() const { return _intensity; }
+
+        // Scale factor for the normal map texture.
+        optional<float>& scale() { return _scale; }
+        const optional<float>& scale() const { return _scale; }
+
+        /** Number of times to proressively scale and multisample the bump map
+            based on camera range. Default is 1. */
+        optional<int>& octaves() { return _octaves; }
+        const optional<int>& octaves() const { return _octaves; }
+
+        /** Camera range at which to render one octave (outer range). */
+        optional<float>& maxRange() { return _maxRange; }
+        const optional<float>& maxRange() const { return _maxRange; }
+
+        /** LOD at which the bumpmap renders at a scale of 1.0. */
+        optional<unsigned>& baseLOD() { return _baseLOD; }
+        const optional<unsigned>& baseLOD() const { return _baseLOD; }
+
+    public:
+        BumpMapOptions( const ConfigOptions& opt =ConfigOptions() ) : DriverConfigOptions( opt )
+        {
+            setDriver( "bumpmap" );
+
+            // Defaults.
+            _intensity.init( 1.0f );
+            _scale.init    ( 1.0f );
+            _octaves.init  ( 1 );
+            _maxRange.init (25000.0f);
+            _baseLOD.init  ( 13u );
+
+            fromConfig( _conf );
+        }
+
+        virtual ~BumpMapOptions() { }
+
+    public:
+        Config getConfig() const {
+            Config conf = DriverConfigOptions::getConfig();
+            conf.updateIfSet("image",     _imageURI);
+            conf.updateIfSet("intensity", _intensity);
+            conf.updateIfSet("scale",     _scale);
+            conf.updateIfSet("octaves",   _octaves);
+            conf.updateIfSet("max_range", _maxRange);
+            conf.updateIfSet("base_lod",  _baseLOD);
+            return conf;
+        }
+
+    protected:
+        void mergeConfig( const Config& conf ) {
+            DriverConfigOptions::mergeConfig( conf );
+            fromConfig( conf );
+        }
+
+    private:
+        void fromConfig( const Config& conf ) {
+            conf.getIfSet("image",     _imageURI);
+            conf.getIfSet("intensity", _intensity);
+            conf.getIfSet("scale",     _scale);
+            conf.getIfSet("octaves",   _octaves);
+            conf.getIfSet("max_range", _maxRange);
+            conf.getIfSet("base_lod",  _baseLOD);
+        }
+
+        optional<URI>      _imageURI;
+        optional<float>    _intensity;
+        optional<float>    _scale;
+        optional<int>      _octaves;
+        optional<float>    _maxRange;
+        optional<unsigned> _baseLOD;
+    };
+
+} } // namespace osgEarth::BumpMap
+
+#endif // OSGEARTH_DRIVER_BUMPMAP_OPTIONS
+
diff --git a/src/osgEarthDrivers/bumpmap/BumpMapPlugin.cpp b/src/osgEarthDrivers/bumpmap/BumpMapPlugin.cpp
new file mode 100644
index 0000000..65e0aae
--- /dev/null
+++ b/src/osgEarthDrivers/bumpmap/BumpMapPlugin.cpp
@@ -0,0 +1,28 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+ * Copyright 2015 Pelican Mapping
+ * http://osgearth.org
+ *
+ * osgEarth is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ */
+#include "BumpMapOptions"
+#include "BumpMapExtension"
+
+#include <osgDB/ReaderWriter>
+#include <osgDB/Registry>
+#include <osgDB/FileNameUtils>
+
+using namespace osgEarth::BumpMap;
+
+REGISTER_OSGEARTH_EXTENSION(osgearth_bumpmap, BumpMapExtension);
diff --git a/src/osgEarthDrivers/bumpmap/BumpMapShaders b/src/osgEarthDrivers/bumpmap/BumpMapShaders
new file mode 100644
index 0000000..fb4a925
--- /dev/null
+++ b/src/osgEarthDrivers/bumpmap/BumpMapShaders
@@ -0,0 +1,39 @@
+// ***DO NOT EDIT THIS FILE - IT IS AUTOMATICALLY GENERATED BY CMAKE***
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+* Copyright 2008-2012 Pelican Mapping
+* http://osgearth.org
+*
+* osgEarth is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* 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.
+*
+* You should have received a copy of the GNU Lesser General Public License
+* along with this program.  If not, see <http://www.gnu.org/licenses/>
+*/
+#ifndef OSGEARTH_BUMPMAP_SHADERS
+#define OSGEARTH_BUMPMAP_SHADERS 1
+
+#include <osgEarth/ShaderLoader>
+
+namespace osgEarth { namespace BumpMap
+{
+    struct Shaders : public osgEarth::ShaderPackage
+	{
+        Shaders();
+        std::string VertexView;
+        std::string FragmentSimple, FragmentProgressive, FragmentCommon;
+	};
+	
+} } // namespace osgEarth/BumpMap
+
+#endif // OSGEARTH_BUMPMAP_SHADERS
\ No newline at end of file
diff --git a/src/osgEarthDrivers/bumpmap/BumpMapShaders.cpp.in b/src/osgEarthDrivers/bumpmap/BumpMapShaders.cpp.in
new file mode 100644
index 0000000..3d06bfd
--- /dev/null
+++ b/src/osgEarthDrivers/bumpmap/BumpMapShaders.cpp.in
@@ -0,0 +1,19 @@
+/** CMake Template File - compiled into AutoGenShaders.cpp */
+#include <osgEarthDrivers/bumpmap/BumpMapShaders>
+
+using namespace osgEarth::BumpMap;
+
+Shaders::Shaders()
+{
+    VertexView = "BumpMap.vert.view.glsl";
+    _sources[VertexView] = "@BumpMap.vert.view.glsl@";
+
+    FragmentSimple = "BumpMap.frag.simple.glsl";
+    _sources[FragmentSimple] = "@BumpMap.frag.simple.glsl@";
+
+    FragmentProgressive = "BumpMap.frag.progressive.glsl";
+    _sources[FragmentProgressive] = "@BumpMap.frag.progressive.glsl@";
+
+    FragmentCommon = "BumpMap.frag.common.glsl";
+    _sources[FragmentCommon] = "@BumpMap.frag.common.glsl@";
+};
diff --git a/src/osgEarthDrivers/bumpmap/BumpMapTerrainEffect b/src/osgEarthDrivers/bumpmap/BumpMapTerrainEffect
new file mode 100644
index 0000000..af0b6f4
--- /dev/null
+++ b/src/osgEarthDrivers/bumpmap/BumpMapTerrainEffect
@@ -0,0 +1,86 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+* Copyright 2008-2012 Pelican Mapping
+* http://osgearth.org
+*
+* osgEarth is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* 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.
+*
+* You should have received a copy of the GNU Lesser General Public License
+* along with this program.  If not, see <http://www.gnu.org/licenses/>
+*/
+#ifndef OSGEARTH_BumpMap_TERRAIN_EFFECT_H
+#define OSGEARTH_BumpMap_TERRAIN_EFFECT_H
+
+#include <osgEarth/TerrainEffect>
+#include <osgEarth/ImageLayer>
+#include <osg/Image>
+#include <osg/Uniform>
+#include <osg/Texture2D>
+
+using namespace osgEarth;
+
+namespace osgEarth { namespace BumpMap
+{
+    /**
+     * Effect that applies bump mapping to the terrain.
+     */
+    class BumpMapTerrainEffect : public TerrainEffect
+    {
+    public:
+        /** construct a new terrain effect. */
+        BumpMapTerrainEffect(const osgDB::Options* dbOptions);
+
+        /** Sets the image containing the normal offsets. */
+        void setBumpMapImage(osg::Image* image);
+
+        /** Sets the LOD at which the bumpmap renders with native scale */
+        void setBaseLOD(unsigned value) { _baseLOD = value; }
+
+        /** Sets the number of progressive octaves. */
+        void setOctaves(int value) { _octaves = value; }
+
+        /** Sets the range of the first octave. */
+        void setMaxRange(float value) { _maxRange = value; }
+
+        /** UNiform that controls intensity */
+        osg::Uniform* getIntensityUniform() const { return _intensityUniform.get(); }
+
+        /** Uniform that controls scale factor */
+        osg::Uniform* getScaleUniform() const { return _scaleUniform.get(); }
+
+
+    public: // TerrainEffect interface
+
+        void onInstall(TerrainEngineNode* engine);
+
+        void onUninstall(TerrainEngineNode* engine);
+
+
+    protected:
+        virtual ~BumpMapTerrainEffect() { }
+
+        bool  _ok;
+        int   _bumpMapUnit;
+        int   _octaves;
+        float _maxRange;
+        unsigned _baseLOD;
+        osg::ref_ptr<osg::Texture2D> _bumpMapTex;
+        osg::ref_ptr<osg::Uniform>   _bumpMapTexUniform;
+        osg::ref_ptr<osg::Uniform>   _scaleUniform;
+        osg::ref_ptr<osg::Uniform>   _intensityUniform;
+    };
+
+} } // namespace osgEarth::BumpMap
+
+#endif // OSGEARTH_BumpMap_TERRAIN_EFFECT_H
diff --git a/src/osgEarthDrivers/bumpmap/BumpMapTerrainEffect.cpp b/src/osgEarthDrivers/bumpmap/BumpMapTerrainEffect.cpp
new file mode 100644
index 0000000..f34130d
--- /dev/null
+++ b/src/osgEarthDrivers/bumpmap/BumpMapTerrainEffect.cpp
@@ -0,0 +1,146 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+* Copyright 2008-2012 Pelican Mapping
+* http://osgearth.org
+*
+* osgEarth is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* 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.
+*
+* You should have received a copy of the GNU Lesser General Public License
+* along with this program.  If not, see <http://www.gnu.org/licenses/>
+*/
+#include "BumpMapTerrainEffect"
+#include "BumpMapOptions"
+
+#include <osgEarth/Registry>
+#include <osgEarth/Capabilities>
+#include <osgEarth/VirtualProgram>
+#include <osgEarth/TerrainEngineNode>
+#include <osgEarth/TerrainTileNode>
+
+#include "BumpMapShaders"
+
+#define LC "[BumpMap] "
+
+#define BUMP_SAMPLER   "oe_bumpmap_tex"
+
+using namespace osgEarth;
+using namespace osgEarth::BumpMap;
+
+
+BumpMapTerrainEffect::BumpMapTerrainEffect(const osgDB::Options* dbOptions) :
+_ok(true),
+_bumpMapUnit(-1)
+{
+    BumpMapOptions defaults;
+    _octaves = defaults.octaves().get();
+    _maxRange = defaults.maxRange().get();
+    _baseLOD  = defaults.baseLOD().get();
+
+    _scaleUniform     = new osg::Uniform("oe_bumpmap_scale", defaults.scale().get());
+    _intensityUniform = new osg::Uniform("oe_bumpmap_intensity", defaults.intensity().get());
+}
+
+void
+BumpMapTerrainEffect::setBumpMapImage(osg::Image* image)
+{
+    if ( image )
+    {
+        _bumpMapTex = new osg::Texture2D(image);
+        _bumpMapTex->setWrap(osg::Texture::WRAP_S, osg::Texture::REPEAT);
+        _bumpMapTex->setWrap(osg::Texture::WRAP_T, osg::Texture::REPEAT);
+        _bumpMapTex->setFilter(osg::Texture::MIN_FILTER, osg::Texture::LINEAR);
+        _bumpMapTex->setFilter(osg::Texture::MAG_FILTER, osg::Texture::LINEAR);
+        _bumpMapTex->setMaxAnisotropy(1.0f);
+        _bumpMapTex->setUnRefImageDataAfterApply(true);
+        _bumpMapTex->setResizeNonPowerOfTwoHint(false);
+    }
+    else
+    {
+        OE_WARN << LC << "Failed to load the bump map texture\n";
+    }
+}
+
+void
+BumpMapTerrainEffect::onInstall(TerrainEngineNode* engine)
+{
+    if ( engine && _bumpMapTex.valid() )
+    {
+        osg::StateSet* stateset = engine->getSurfaceStateSet();
+
+        // install the NormalMap texture array:
+        if ( engine->getResources()->reserveTextureImageUnit(_bumpMapUnit, "BumpMap") )
+        {
+            // NormalMap sampler
+            _bumpMapTexUniform = stateset->getOrCreateUniform(BUMP_SAMPLER, osg::Uniform::SAMPLER_2D);
+            _bumpMapTexUniform->set( _bumpMapUnit );
+            stateset->setTextureAttribute( _bumpMapUnit, _bumpMapTex.get() );
+
+            // configure shaders
+            VirtualProgram* vp = VirtualProgram::getOrCreate(stateset);
+
+            Shaders package;            
+            package.define( "OE_USE_NORMAL_MAP", false ); //engine->normalTexturesRequired() );
+
+            //package.load( vp, package.VertexModel );
+            package.load( vp, package.VertexView );
+            package.load( vp, _octaves <= 1? package.FragmentSimple : package.FragmentProgressive );
+
+            if ( _octaves > 1 )
+                stateset->addUniform(new osg::Uniform("oe_bumpmap_octaves", _octaves));
+
+            stateset->addUniform(new osg::Uniform("oe_bumpmap_maxRange", _maxRange));
+            stateset->addUniform(new osg::Uniform("oe_bumpmap_slopeFactor", 1.0f));
+            stateset->addUniform(new osg::Uniform("oe_bumpmap_baseLOD", (float)_baseLOD));
+
+            stateset->addUniform( _scaleUniform.get() );
+            stateset->addUniform( _intensityUniform.get() );
+        }
+        else
+        {
+            OE_WARN << LC << "Failed to allocation a texture image unit!\n";
+        }
+    }
+}
+
+
+void
+BumpMapTerrainEffect::onUninstall(TerrainEngineNode* engine)
+{
+    osg::StateSet* stateset = engine->getStateSet();
+    if ( stateset )
+    {
+        if ( _bumpMapTex.valid() )
+        {
+            stateset->removeUniform("oe_bumpmap_maxRange");
+            stateset->removeUniform("oe_bumpmap_octaves");
+            stateset->removeUniform( _scaleUniform.get() );
+            stateset->removeUniform( _intensityUniform.get() );
+            stateset->removeUniform( _bumpMapTexUniform.get() );
+            stateset->removeTextureAttribute( _bumpMapUnit, osg::StateAttribute::TEXTURE );
+        }
+
+        VirtualProgram* vp = VirtualProgram::get(stateset);
+        if ( vp )
+        {
+            Shaders pkg;
+            pkg.unloadAll( vp );
+        }
+    }
+    
+    if ( _bumpMapUnit >= 0 )
+    {
+        engine->getResources()->releaseTextureImageUnit( _bumpMapUnit );
+        _bumpMapUnit = -1;
+    }
+}
diff --git a/src/osgEarthDrivers/bumpmap/CMakeLists.txt b/src/osgEarthDrivers/bumpmap/CMakeLists.txt
new file mode 100644
index 0000000..43340f1
--- /dev/null
+++ b/src/osgEarthDrivers/bumpmap/CMakeLists.txt
@@ -0,0 +1,43 @@
+#
+# bump mapping plugin
+#
+
+set(TARGET_GLSL
+	BumpMap.vert.view.glsl
+    BumpMap.frag.simple.glsl
+    BumpMap.frag.progressive.glsl
+    BumpMap.frag.common.glsl)
+
+set(SHADERS_CPP "${CMAKE_CURRENT_BINARY_DIR}/AutoGenShaders.cpp")
+
+set(TARGET_IN
+    BumpMapShaders.cpp.in)
+
+configure_shaders(
+    BumpMapShaders.cpp.in
+    ${SHADERS_CPP}
+    ${TARGET_GLSL} )
+
+set(TARGET_SRC
+	BumpMapExtension.cpp
+	BumpMapTerrainEffect.cpp
+	${SHADERS_CPP} )
+	
+set(LIB_PUBLIC_HEADERS
+	BumpMapExtension
+	BumpMapOptions
+	BumpMapTerrainEffect)
+	
+set(TARGET_H
+	${LIB_PUBLIC_HEADERS}
+	BumpMapShaders )
+
+
+set(TARGET_COMMON_LIBRARIES ${TARGET_COMMON_LIBRARIES}
+    osgEarthUtil)
+	
+setup_plugin(osgearth_bumpmap)
+
+# to install public driver includes:
+set(LIB_NAME bumpmap)
+
diff --git a/src/osgEarthDrivers/cache_filesystem/FileSystemCache b/src/osgEarthDrivers/cache_filesystem/FileSystemCache
index d9dc8eb..ef202a8 100644
--- a/src/osgEarthDrivers/cache_filesystem/FileSystemCache
+++ b/src/osgEarthDrivers/cache_filesystem/FileSystemCache
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthDrivers/cache_filesystem/FileSystemCache.cpp b/src/osgEarthDrivers/cache_filesystem/FileSystemCache.cpp
index 7e4eb0b..18b1c68 100644
--- a/src/osgEarthDrivers/cache_filesystem/FileSystemCache.cpp
+++ b/src/osgEarthDrivers/cache_filesystem/FileSystemCache.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -38,6 +38,10 @@ using namespace osgEarth::Threading;
 #   include <unistd.h>
 #endif
 
+#define OSG_FORMAT "osgb"
+#define OSG_EXT   ".osgb"
+#define OSG_COMPRESS
+
 namespace
 {
     /** 
@@ -81,15 +85,15 @@ namespace
 
     public: // CacheBin interface
 
-        ReadResult readObject(const std::string& key);
+        ReadResult readObject(const std::string& key, const osgDB::Options* dbo);
 
-        ReadResult readImage(const std::string& key);
+        ReadResult readImage(const std::string& key, const osgDB::Options* dbo);
 
-        ReadResult readNode(const std::string& key);
+        //ReadResult readNode(const std::string& key, const osgDB::Options* dbo);
 
-        ReadResult readString(const std::string& key);
+        ReadResult readString(const std::string& key, const osgDB::Options* dbo);
 
-        bool write(const std::string& key, const osg::Object* object, const Config& meta);
+        bool write(const std::string& key, const osg::Object* object, const Config& meta, const osgDB::Options* dbo);
 
         bool remove(const std::string& key);
 
@@ -103,6 +107,8 @@ namespace
 
         bool writeMetadata( const Config& meta );
 
+        std::string getHashedKey(const std::string&) const;
+
     protected:
         bool purgeDirectory( const std::string& dir );
 
@@ -110,15 +116,15 @@ namespace
 
         bool binValidForWriting(bool silent =false);
 
-        std::string getValidKey(const std::string&);
+        const osgDB::Options* mergeOptions(const osgDB::Options* in);
 
         bool                              _ok;
         bool                              _binPathExists;
         std::string                       _metaPath;       // full path to the bin's metadata file
         std::string                       _binPath;        // full path to the bin's root folder
         osg::ref_ptr<osgDB::ReaderWriter> _rw;
-        osg::ref_ptr<osgDB::Options>      _rwOptions;
-        Threading::ReadWriteMutex         _rwmutex;
+        osg::ref_ptr<osgDB::Options>      _zlibOptions;
+        mutable Threading::Mutex          _mutex;
     };
 
     void writeMeta( const std::string& fullPath, const Config& meta )
@@ -178,7 +184,7 @@ namespace
     void
     FileSystemCache::init()
     {
-        //nop
+        OE_INFO << LC << "Opened a filesystem cache at \"" << _rootPath << "\"\n";
     }
 
     CacheBin*
@@ -205,12 +211,20 @@ namespace
     //------------------------------------------------------------------------
 
     std::string
-    FileSystemCacheBin::getValidKey(const std::string& key)
+    FileSystemCacheBin::getHashedKey(const std::string& key) const
     {
         if ( getHashKeys() )
-            return Stringify() << std::hex << osgEarth::hashString(key);
+        {
+            unsigned hash = osgEarth::hashString(key);
+            unsigned b1 = (hash & 0xfff00000) >> 20;
+            unsigned b2 = (hash & 0x000fff00) >> 8;
+            unsigned b3 = (hash & 0x000000ff);
+            return Stringify() << std::hex << std::setfill('0') << std::setw(3) << b1 << "/" << b2 << "/" << std::setw(2) << b3;
+        }
         else
+        {
             return osgEarth::toLegalFileName(key);
+        }
     }
 
     bool
@@ -276,71 +290,63 @@ namespace
     FileSystemCacheBin::FileSystemCacheBin(const std::string&   binID,
                                            const std::string&   rootPath) :
     CacheBin            ( binID ),
-    _binPathExists      ( false )
+    _binPathExists      ( false ),
+    _ok( true )
     {
         _binPath = osgDB::concatPaths( rootPath, binID );
         _metaPath = osgDB::concatPaths( _binPath, "osgearth_cacheinfo.json" );
 
-        _rw = osgDB::Registry::instance()->getReaderWriterForExtension( "osgb" );
+        _rw = osgDB::Registry::instance()->getReaderWriterForExtension(OSG_FORMAT);
+
+#ifdef OSG_COMPRESS
 #ifdef OSGEARTH_HAVE_ZLIB
-        _rwOptions = Registry::instance()->cloneOrCreateOptions();
-        _rwOptions->setOptionString( "Compressor=zlib" );
+        _zlibOptions = Registry::instance()->cloneOrCreateOptions();
+        _zlibOptions->setPluginStringData("Compressor", "zlib");
 #endif        
+#endif
     }
 
-    ReadResult
-    FileSystemCacheBin::readImage(const std::string& key)
+    const osgDB::Options*
+    FileSystemCacheBin::mergeOptions(const osgDB::Options* dbo)
     {
-        if ( !binValidForReading() ) 
-            return ReadResult(ReadResult::RESULT_NOT_FOUND);
-
-        // mangle "key" into a legal path name
-        URI fileURI( getValidKey(key), _metaPath );
-        std::string path = fileURI.full() + ".osgb";
-
-        if ( !osgDB::fileExists(path) )
-            return ReadResult( ReadResult::RESULT_NOT_FOUND );
-
-        osgEarth::TimeStamp timeStamp = osgEarth::getLastModifiedTime(path);        
-
-        osgDB::ReaderWriter::ReadResult r;
+        if (!dbo)
         {
-            ScopedReadLock sharedLock( _rwmutex );
-            r = _rw->readImage( path, _rwOptions.get() );
-            if ( !r.success() )
-                return ReadResult();
-
-            // read metadata
-            Config meta;
-            std::string metafile = fileURI.full() + ".meta";
-            if ( osgDB::fileExists(metafile) )
-                readMeta( metafile, meta );
-
-            ReadResult rr( r.getImage(), meta );
-            rr.setLastModifiedTime(timeStamp);
-            return rr;            
+            return _zlibOptions.get();
+        }
+        else if (!_zlibOptions.valid())
+        {
+            return dbo;
+        }
+        else
+        {
+            osgDB::Options* merged = Registry::cloneOrCreateOptions(dbo);
+            merged->setPluginStringData("Compressor", "zlib");
+            return merged;
         }
     }
 
     ReadResult
-    FileSystemCacheBin::readObject(const std::string& key)
+    FileSystemCacheBin::readImage(const std::string& key, const osgDB::Options* readOptions)
     {
         if ( !binValidForReading() ) 
             return ReadResult(ReadResult::RESULT_NOT_FOUND);
 
         // mangle "key" into a legal path name
-        URI fileURI( getValidKey(key), _metaPath );
-        std::string path = fileURI.full() + ".osgb";
+        URI fileURI( getHashedKey(key), _metaPath );
+        std::string path = fileURI.full() + OSG_EXT;
 
         if ( !osgDB::fileExists(path) )
             return ReadResult( ReadResult::RESULT_NOT_FOUND );
 
-        osgEarth::TimeStamp timeStamp = osgEarth::getLastModifiedTime(path);
+        osgEarth::TimeStamp timeStamp = osgEarth::getLastModifiedTime(path);     
+
+        osg::ref_ptr<const osgDB::Options> dbo = mergeOptions(readOptions);
 
         osgDB::ReaderWriter::ReadResult r;
         {
-            ScopedReadLock sharedLock( _rwmutex );
-            r = _rw->readObject( path, _rwOptions.get() );
+            ScopedMutexLock lock(_mutex);
+
+            r = _rw->readImage( path, dbo.get() );
             if ( !r.success() )
                 return ReadResult();
 
@@ -350,31 +356,34 @@ namespace
             if ( osgDB::fileExists(metafile) )
                 readMeta( metafile, meta );
 
-            ReadResult rr( r.getObject(), meta );
+            ReadResult rr( r.getImage(), meta );
             rr.setLastModifiedTime(timeStamp);
             return rr;            
         }
     }
 
     ReadResult
-    FileSystemCacheBin::readNode(const std::string& key)
+    FileSystemCacheBin::readObject(const std::string& key, const osgDB::Options* readOptions)
     {
         if ( !binValidForReading() ) 
             return ReadResult(ReadResult::RESULT_NOT_FOUND);
 
         // mangle "key" into a legal path name
-        URI fileURI( getValidKey(key), _metaPath );
-        std::string path = fileURI.full() + ".osgb";
+        URI fileURI( getHashedKey(key), _metaPath );
+        std::string path = fileURI.full() + OSG_EXT;
 
         if ( !osgDB::fileExists(path) )
             return ReadResult( ReadResult::RESULT_NOT_FOUND );
 
         osgEarth::TimeStamp timeStamp = osgEarth::getLastModifiedTime(path);
 
+        osg::ref_ptr<const osgDB::Options> dbo = mergeOptions(readOptions);
+
         osgDB::ReaderWriter::ReadResult r;
         {
-            ScopedReadLock sharedLock( _rwmutex );
-            r = _rw->readNode( path, _rwOptions.get() );
+            ScopedMutexLock lock(_mutex);
+
+            r = _rw->readObject( path, dbo.get() );
             if ( !r.success() )
                 return ReadResult();
 
@@ -384,16 +393,16 @@ namespace
             if ( osgDB::fileExists(metafile) )
                 readMeta( metafile, meta );
 
-            ReadResult rr( r.getNode(), meta );
+            ReadResult rr( r.getObject(), meta );
             rr.setLastModifiedTime(timeStamp);
             return rr;            
         }
     }
 
     ReadResult
-    FileSystemCacheBin::readString(const std::string& key)
+    FileSystemCacheBin::readString(const std::string& key, const osgDB::Options* readOptions)
     {
-        ReadResult r = readObject(key);
+        ReadResult r = readObject(key, readOptions);
         if ( r.succeeded() )
         {
             if ( r.get<StringObject>() )
@@ -408,42 +417,43 @@ namespace
     }
 
     bool
-    FileSystemCacheBin::write( const std::string& key, const osg::Object* object, const Config& meta )
+    FileSystemCacheBin::write(const std::string& key, const osg::Object* object, const Config& meta, const osgDB::Options* writeOptions)
     {
         if ( !binValidForWriting() || !object ) 
             return false;
 
         // convert the key into a legal filename:
-        URI fileURI( getValidKey(key), _metaPath );
+        URI fileURI( getHashedKey(key), _metaPath );
         
         osgDB::ReaderWriter::WriteResult r;
 
         bool objWriteOK = false;
         {
             // prevent cache contention:
-            ScopedWriteLock exclusiveLock( _rwmutex );
+            ScopedMutexLock lock(_mutex);
 
             // make a home for it..
             if ( !osgDB::fileExists( osgDB::getFilePath(fileURI.full()) ) )
                 osgEarth::makeDirectoryForFile( fileURI.full() );
 
+            osg::ref_ptr<const osgDB::Options> dbo = mergeOptions(writeOptions);
 
             if ( dynamic_cast<const osg::Image*>(object) )
             {
-                std::string filename = fileURI.full() + ".osgb";
-                r = _rw->writeImage( *static_cast<const osg::Image*>(object), filename, _rwOptions.get() );
+                std::string filename = fileURI.full() + OSG_EXT;
+                r = _rw->writeImage( *static_cast<const osg::Image*>(object), filename, dbo.get() );
                 objWriteOK = r.success();
             }
             else if ( dynamic_cast<const osg::Node*>(object) )
             {
-                std::string filename = fileURI.full() + ".osgb";
-                r = _rw->writeNode( *static_cast<const osg::Node*>(object), filename, _rwOptions.get() );
+                std::string filename = fileURI.full() + OSG_EXT;
+                r = _rw->writeNode(*static_cast<const osg::Node*>(object), filename, dbo.get());
                 objWriteOK = r.success();
             }
             else
             {
-                std::string filename = fileURI.full() + ".osgb";
-                r = _rw->writeObject( *object, filename );
+                std::string filename = fileURI.full() + OSG_EXT;
+                r = _rw->writeObject(*object, filename, dbo.get());
                 objWriteOK = r.success();
             }
 
@@ -457,7 +467,7 @@ namespace
 
         if ( objWriteOK )
         {
-            OE_DEBUG << LC << "Wrote \"" << key << "\" to cache bin " << getID() << std::endl;
+            OE_DEBUG << LC << "Wrote \"" << key << "\" to cache bin [" << getID() << "] path=" << fileURI.full() << "." << OSG_EXT << std::endl;
         }
         else
         {
@@ -474,8 +484,8 @@ namespace
         if ( !binValidForReading() ) 
             return STATUS_NOT_FOUND;
 
-        URI fileURI( getValidKey(key), _metaPath );
-        std::string path( fileURI.full() + ".osgb" );
+        URI fileURI( getHashedKey(key), _metaPath );
+        std::string path( fileURI.full() + OSG_EXT );
         if ( !osgDB::fileExists(path) )
             return STATUS_NOT_FOUND;
 
@@ -486,8 +496,10 @@ namespace
     FileSystemCacheBin::remove(const std::string& key)
     {
         if ( !binValidForReading() ) return false;
-        URI fileURI( getValidKey(key), _metaPath );
-        std::string path( fileURI.full() + ".osgb" );
+        URI fileURI( getHashedKey(key), _metaPath );
+        std::string path( fileURI.full() + OSG_EXT );
+
+        ScopedMutexLock lock(_mutex);
         return ::unlink( path.c_str() ) == 0;
     }
 
@@ -495,8 +507,10 @@ namespace
     FileSystemCacheBin::touch(const std::string& key)
     {
         if ( !binValidForReading() ) return false;
-        URI fileURI( getValidKey(key), _metaPath );
-        std::string path( fileURI.full() + ".osgb" );
+        URI fileURI( getHashedKey(key), _metaPath );
+        std::string path( fileURI.full() + OSG_EXT );
+
+        ScopedMutexLock lock(_mutex);
         return osgEarth::touchFile( path );
     }
 
@@ -505,6 +519,8 @@ namespace
     {
         if ( !binValidForReading() ) return false;
 
+        ScopedMutexLock lock(_mutex);
+
         bool allOK = true;
         osgDB::DirectoryContents dc = osgDB::getDirectoryContents( dir );
 
@@ -547,7 +563,7 @@ namespace
         if ( !binValidForReading() )
             return false;
 
-        ScopedWriteLock exclusiveLock( _rwmutex );
+        ScopedMutexLock lock(_mutex);
         std::string binDir = osgDB::getFilePath( _metaPath );
         return purgeDirectory( binDir );
     }
@@ -556,11 +572,11 @@ namespace
     FileSystemCacheBin::readMetadata()
     {
         if ( !binValidForReading() ) return Config();
-
-        ScopedReadLock sharedLock( _rwmutex );
         
+        ScopedMutexLock lock(_mutex);
+
         Config conf;
-        conf.fromJSON( URI(_metaPath).getString(_rwOptions.get()) );
+        conf.fromJSON( URI(_metaPath).getString(_zlibOptions.get()) );
 
         return conf;
     }
@@ -569,8 +585,8 @@ namespace
     FileSystemCacheBin::writeMetadata( const Config& conf )
     {
         if ( !binValidForWriting() ) return false;
-
-        ScopedWriteLock exclusiveLock( _rwmutex );
+        
+        ScopedMutexLock lock(_mutex);
 
         std::fstream output( _metaPath.c_str(), std::ios_base::out );
         if ( output.is_open() )
@@ -601,7 +617,7 @@ public:
         supportsExtension( "osgearth_cache_filesystem", "File system cache for osgEarth" );
     }
 
-    virtual const char* className()
+    virtual const char* className() const
     {
         return "File system cache for osgEarth";
     }
diff --git a/src/osgEarthDrivers/cache_leveldb/LevelDBCache b/src/osgEarthDrivers/cache_leveldb/LevelDBCache
index f7e3d42..14490a3 100644
--- a/src/osgEarthDrivers/cache_leveldb/LevelDBCache
+++ b/src/osgEarthDrivers/cache_leveldb/LevelDBCache
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthDrivers/cache_leveldb/LevelDBCache.cpp b/src/osgEarthDrivers/cache_leveldb/LevelDBCache.cpp
index f21e9a0..fa97b30 100644
--- a/src/osgEarthDrivers/cache_leveldb/LevelDBCache.cpp
+++ b/src/osgEarthDrivers/cache_leveldb/LevelDBCache.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -24,6 +24,7 @@
 #include <osgDB/ReaderWriter>
 #include <osgDB/FileUtils>
 #include <osgDB/FileNameUtils>
+#include <osgDB/ObjectWrapper>
 
 #include <sys/stat.h>
 #ifndef _WIN32
@@ -45,6 +46,12 @@ osgEarth::Cache( options ),
 _options       ( options ),
 _active        ( true )
 {
+    // Force OSG to initialize the image wrapper. Failure to do this can result
+    // in a race condition within OSG when the cache is accessed from multiple threads.
+    osgDB::ObjectWrapperManager* owm = osgDB::Registry::instance()->getObjectWrapperManager();
+    owm->findWrapper("osg::Image");
+    owm->findWrapper("osg::HeightField");
+
     if ( _options.rootPath().isSet() )
     {
         _rootPath = URI( *_options.rootPath(), options.referrer() ).full();
@@ -130,7 +137,7 @@ LevelDBCacheImpl::init()
 
     if ( _active )
     {
-        OE_INFO << LC << "Opened DB at " << _rootPath << std::endl;
+        OE_INFO << LC << "Opened a cache at \"" << _rootPath << "\"" << std::endl;
     }
 }
 
diff --git a/src/osgEarthDrivers/cache_leveldb/LevelDBCacheBin b/src/osgEarthDrivers/cache_leveldb/LevelDBCacheBin
index f3405a5..c213317 100644
--- a/src/osgEarthDrivers/cache_leveldb/LevelDBCacheBin
+++ b/src/osgEarthDrivers/cache_leveldb/LevelDBCacheBin
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -43,15 +43,15 @@ namespace osgEarth { namespace Drivers { namespace LevelDBCache
 
     public: // CacheBin interface
 
-        ReadResult readObject(const std::string& key);
+        ReadResult readObject(const std::string& key, const osgDB::Options*);
 
-        ReadResult readImage(const std::string& key);
+        ReadResult readImage(const std::string& key, const osgDB::Options*);
 
-        ReadResult readNode(const std::string& key);
+        ReadResult readNode(const std::string& key, const osgDB::Options*);
 
-        ReadResult readString(const std::string& key);
+        ReadResult readString(const std::string& key, const osgDB::Options*);
 
-        bool write(const std::string& key, const osg::Object* object, const Config& meta);
+        bool write(const std::string& key, const osg::Object* object, const Config& meta, const osgDB::Options*);
 
         bool remove(const std::string& key);
 
@@ -69,6 +69,8 @@ namespace osgEarth { namespace Drivers { namespace LevelDBCache
 
         bool writeMetadata( const Config& meta );
 
+        std::string getHashedKey(const std::string& key) const;
+
         bool purgeOldest(unsigned maxnum);
         
     protected:
@@ -90,25 +92,25 @@ namespace osgEarth { namespace Drivers { namespace LevelDBCache
         
         // adapter base for all the osg read functions...
         struct Reader {
-            osgDB::ReaderWriter* _rw;
-            osgDB::Options*      _op;
-            Reader(osgDB::ReaderWriter* rw, osgDB::Options* op) : _rw(rw), _op(op) { }
+            osgDB::ReaderWriter*   _rw;
+            const osgDB::Options*  _op;
+            Reader(osgDB::ReaderWriter* rw, const osgDB::Options* op) : _rw(rw), _op(op) { }
             virtual osgDB::ReaderWriter::ReadResult read(std::istream& in) const = 0;
             virtual std::string name() const = 0;
         };
 
         struct ImageReader : public Reader {
-            ImageReader(osgDB::ReaderWriter* rw, osgDB::Options* op) : Reader(rw, op) { }
+            ImageReader(osgDB::ReaderWriter* rw, const osgDB::Options* op) : Reader(rw, op) { }
             osgDB::ReaderWriter::ReadResult read(std::istream& in) const { return _rw->readImage(in, _op); }
             std::string name() const { return "ImageReader"; }
         };
         struct NodeReader : public Reader {
-            NodeReader(osgDB::ReaderWriter* rw, osgDB::Options* op) : Reader(rw, op) { }
+            NodeReader(osgDB::ReaderWriter* rw, const osgDB::Options* op) : Reader(rw, op) { }
             osgDB::ReaderWriter::ReadResult read(std::istream& in) const { return _rw->readNode(in, _op); }
             std::string name() const { return "NodeReader"; }
         };
         struct ObjectReader : public Reader {
-            ObjectReader(osgDB::ReaderWriter* rw, osgDB::Options* op) : Reader(rw, op) { }
+            ObjectReader(osgDB::ReaderWriter* rw, const osgDB::Options* op) : Reader(rw, op) { }
             osgDB::ReaderWriter::ReadResult read(std::istream& in) const { return _rw->readObject(in, _op); }
             std::string name() const { return "ObjectReader"; }
         };
@@ -118,22 +120,22 @@ namespace osgEarth { namespace Drivers { namespace LevelDBCache
         void postWrite();
 
         // key generators
-        std::string binDataKeyTuple(const std::string& key);
-        std::string binPhrase();
-        std::string dataKey(const std::string& key);
-        std::string dataKeyFromTuple(const std::string& tuple);
-        std::string dataBegin();
-        std::string dataEnd();
-        std::string metaKey(const std::string& key);
-        std::string metaKeyFromTuple(const std::string& tuple);
-        std::string metaBegin();
-        std::string metaEnd();
-        std::string timeKey(const DateTime& t, const std::string& key);
-        std::string timeBegin();
-        std::string timeEnd();
-        std::string binKey();
-        std::string timeBeginGlobal();
-        std::string timeEndGlobal();
+        std::string binDataKeyTuple(const std::string& key) const;
+        std::string binPhrase() const;
+        std::string dataKey(const std::string& key) const;
+        std::string dataKeyFromTuple(const std::string& tuple) const;
+        std::string dataBegin() const;
+        std::string dataEnd() const;
+        std::string metaKey(const std::string& key) const;
+        std::string metaKeyFromTuple(const std::string& tuple) const;
+        std::string metaBegin() const;
+        std::string metaEnd() const;
+        std::string timeKey(const DateTime& t, const std::string& key) const;
+        std::string timeBegin() const;
+        std::string timeEnd() const;
+        std::string binKey() const;
+        std::string timeBeginGlobal() const;
+        std::string timeEndGlobal() const;
     };
 
 
diff --git a/src/osgEarthDrivers/cache_leveldb/LevelDBCacheBin.cpp b/src/osgEarthDrivers/cache_leveldb/LevelDBCacheBin.cpp
index 779af30..68326fc 100644
--- a/src/osgEarthDrivers/cache_leveldb/LevelDBCacheBin.cpp
+++ b/src/osgEarthDrivers/cache_leveldb/LevelDBCacheBin.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -122,121 +122,127 @@ LevelDBCacheBin::binValidForWriting(bool silent)
     return ok;
 }
 
+std::string
+LevelDBCacheBin::getHashedKey(const std::string& key) const
+{
+    return dataKey(key);
+}
+
 #define SEP std::string("!")
 
 std::string
-LevelDBCacheBin::binPhrase()
+LevelDBCacheBin::binPhrase() const
 {
     return SEP + getID() + SEP;
 }
 
 std::string
-LevelDBCacheBin::binKey()
+LevelDBCacheBin::binKey() const
 {
     return "b" + SEP + getID();
 }
 
 std::string
-LevelDBCacheBin::dataKey(const std::string& key)
+LevelDBCacheBin::dataKey(const std::string& key) const
 {
     return "d" + SEP + binDataKeyTuple(key);
 }
 
 std::string
-LevelDBCacheBin::binDataKeyTuple(const std::string& key)
+LevelDBCacheBin::binDataKeyTuple(const std::string& key) const
 {
     return getID() + SEP + key;
 }
 
 std::string
-LevelDBCacheBin::dataKeyFromTuple(const std::string& tuple)
+LevelDBCacheBin::dataKeyFromTuple(const std::string& tuple) const
 {
     return "d" + SEP + tuple;
 }
 
 std::string
-LevelDBCacheBin::dataBegin()
+LevelDBCacheBin::dataBegin() const
 {
     return "d" + SEP + getID() + SEP;
 }
 
 std::string
-LevelDBCacheBin::dataEnd()
+LevelDBCacheBin::dataEnd() const
 {
     return "d" + SEP + getID() + SEP + "\xff";
 }
 
 std::string
-LevelDBCacheBin::metaKey(const std::string& key)
+LevelDBCacheBin::metaKey(const std::string& key) const
 {
     return "m" + SEP + binDataKeyTuple(key);
 }
 
 std::string
-LevelDBCacheBin::metaKeyFromTuple(const std::string& tuple)
+LevelDBCacheBin::metaKeyFromTuple(const std::string& tuple) const
 {
     return "m" + SEP + tuple;
 }
 
 std::string
-LevelDBCacheBin::metaBegin()
+LevelDBCacheBin::metaBegin() const
 {
     return "m" + SEP + getID() + SEP;
 }
 
 std::string
-LevelDBCacheBin::metaEnd()
+LevelDBCacheBin::metaEnd() const
 {
     return "m" + SEP + getID() + SEP + "\xff";
 }
 
 std::string
-LevelDBCacheBin::timeKey(const DateTime& t, const std::string& key)
+LevelDBCacheBin::timeKey(const DateTime& t, const std::string& key) const
 {
     return "t" + SEP + t.asCompactISO8601() + SEP + getID() + SEP + key;
 }
 
 std::string
-LevelDBCacheBin::timeBegin()
+LevelDBCacheBin::timeBegin() const
 {
     return "t" + SEP + getID() + SEP;
 }
 
 std::string
-LevelDBCacheBin::timeEnd()
+LevelDBCacheBin::timeEnd() const
 {
     return "t" + SEP + getID() + SEP + "\xff";
 }
 
 std::string
-LevelDBCacheBin::timeBeginGlobal()
+LevelDBCacheBin::timeBeginGlobal() const
 {
     return "t" + SEP;
 }
 
 std::string
-LevelDBCacheBin::timeEndGlobal()
+LevelDBCacheBin::timeEndGlobal() const
 {
     return "t" + SEP + "\xff";
 }
 
 ReadResult
-LevelDBCacheBin::readImage(const std::string& key)
+LevelDBCacheBin::readImage(const std::string& key, const osgDB::Options* readOptions)
 {
-    return read(key, ImageReader(_rw.get(), _rwOptions.get()));    
+    return read(key, ImageReader(_rw.get(), readOptions));
 }
 
 ReadResult
-LevelDBCacheBin::readObject(const std::string& key)
+LevelDBCacheBin::readObject(const std::string& key, const osgDB::Options* readOptions)
 {
     //OE_INFO << LC << "Read attempt: " << key << " from " << getID() << std::endl;
-    return read(key, ObjectReader(_rw.get(), _rwOptions.get()));
+    return read(key, ObjectReader(_rw.get(), readOptions));
 }
 
 ReadResult
-LevelDBCacheBin::readNode(const std::string& key)
+LevelDBCacheBin::readNode(const std::string& key, const osgDB::Options* readOptions)
 {
-    return read(key, NodeReader(_rw.get(), _rwOptions.get()));
+    return read(key, NodeReader(_rw.get(), readOptions));
 }
 
 ReadResult
@@ -254,7 +260,7 @@ LevelDBCacheBin::read(const std::string& key, const Reader& reader)
     // first read the metadata record.
     std::string metavalue;
     status = _db->Get( ro, metaKey(key), &metavalue );
-    TimeStamp lastModified;
+    TimeStamp lastModified = (TimeStamp)0;
     if ( status.ok() )
     {        
         decodeMeta(metavalue, metadata);
@@ -310,9 +316,9 @@ LevelDBCacheBin::read(const std::string& key, const Reader& reader)
 }
 
 ReadResult
-LevelDBCacheBin::readString(const std::string& key)
+LevelDBCacheBin::readString(const std::string& key, const osgDB::Options* readOptions)
 {
-    ReadResult r = readObject(key);
+    ReadResult r = readObject(key, readOptions);
     if ( r.succeeded() )
     {
         if ( r.get<StringObject>() )
@@ -327,7 +333,7 @@ LevelDBCacheBin::readString(const std::string& key)
 }
 
 bool
-LevelDBCacheBin::write(const std::string& key, const osg::Object* object, const Config& meta)
+LevelDBCacheBin::write(const std::string& key, const osg::Object* object, const Config& meta, const osgDB::Options* writeOptions)
 {
     if ( !binValidForWriting() || !object ) 
         return false;
@@ -345,7 +351,7 @@ LevelDBCacheBin::write(const std::string& key, const osg::Object* object, const
             OE_WARN << LC << "Internal: tried to write image to " << _rw->className() << "\n";
             return false;
         }
-        r = _rw->writeImage( *static_cast<const osg::Image*>(object), datastream, _rwOptions.get() );
+        r = _rw->writeImage( *static_cast<const osg::Image*>(object), datastream, writeOptions );
         objWriteOK = r.success();
     }
     else if ( dynamic_cast<const osg::Node*>(object) )
@@ -355,7 +361,7 @@ LevelDBCacheBin::write(const std::string& key, const osg::Object* object, const
             OE_WARN << LC << "Internal: tried to write node to " << _rw->className() << "\n";
             return false;
         }
-        r = _rw->writeNode( *static_cast<const osg::Node*>(object), datastream, _rwOptions.get() );
+        r = _rw->writeNode( *static_cast<const osg::Node*>(object), datastream, writeOptions );
         objWriteOK = r.success();
     }
     else
@@ -365,7 +371,7 @@ LevelDBCacheBin::write(const std::string& key, const osg::Object* object, const
             OE_WARN << LC << "Internal: tried to write an object to " << _rw->className() << "\n";
             return false;
         }
-        r = _rw->writeObject( *object, datastream );
+        r = _rw->writeObject( *object, datastream, writeOptions );
         objWriteOK = r.success();
     }
 
diff --git a/src/osgEarthDrivers/cache_leveldb/LevelDBCacheDriver.cpp b/src/osgEarthDrivers/cache_leveldb/LevelDBCacheDriver.cpp
index 6e5b3cd..4765f7c 100644
--- a/src/osgEarthDrivers/cache_leveldb/LevelDBCacheDriver.cpp
+++ b/src/osgEarthDrivers/cache_leveldb/LevelDBCacheDriver.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -38,7 +38,7 @@ namespace osgEarth { namespace Drivers { namespace LevelDBCache
             supportsExtension( "osgearth_cache_leveldb", "leveldb cache for osgEarth" );
         }
 
-        virtual const char* className()
+        virtual const char* className() const
         {
             return "leveldb cache for osgEarth";
         }
diff --git a/src/osgEarthDrivers/cache_leveldb/LevelDBCacheOptions b/src/osgEarthDrivers/cache_leveldb/LevelDBCacheOptions
index 7287595..ef95069 100644
--- a/src/osgEarthDrivers/cache_leveldb/LevelDBCacheOptions
+++ b/src/osgEarthDrivers/cache_leveldb/LevelDBCacheOptions
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthDrivers/cache_leveldb/Tracker b/src/osgEarthDrivers/cache_leveldb/Tracker
index c49bb01..1dd377d 100644
--- a/src/osgEarthDrivers/cache_leveldb/Tracker
+++ b/src/osgEarthDrivers/cache_leveldb/Tracker
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthDrivers/cache_rocksdb/CMakeLists.txt b/src/osgEarthDrivers/cache_rocksdb/CMakeLists.txt
new file mode 100644
index 0000000..10132d5
--- /dev/null
+++ b/src/osgEarthDrivers/cache_rocksdb/CMakeLists.txt
@@ -0,0 +1,30 @@
+IF(ROCKSDB_FOUND)
+
+INCLUDE_DIRECTORIES( ${ROCKSDB_INCLUDE_DIR} )
+
+SET(TARGET_H
+    RocksDBCacheOptions
+    RocksDBCache
+    RocksDBCacheBin
+	Tracker
+)
+SET(TARGET_SRC 
+    RocksDBCache.cpp
+    RocksDBCacheBin.cpp
+    RocksDBCacheDriver.cpp
+)
+
+SET(TARGET_LIBRARIES_VARS ROCKSDB_LIBRARY)
+
+SET(TARGET_EXTERNAL_LIBRARIES ws2_32 winmm rpcrt4)
+
+SETUP_PLUGIN(osgearth_cache_rocksdb)
+
+# to install public driver includes:
+SET(LIB_NAME cache_rocksdb)
+SET(LIB_PUBLIC_HEADERS RocksDBCacheOptions)
+INCLUDE(ModuleInstallOsgEarthDriverIncludes OPTIONAL)
+
+ENDIF(ROCKSDB_FOUND)
+
+
diff --git a/src/osgEarthDrivers/cache_rocksdb/RocksDBCache b/src/osgEarthDrivers/cache_rocksdb/RocksDBCache
new file mode 100644
index 0000000..135a5b1
--- /dev/null
+++ b/src/osgEarthDrivers/cache_rocksdb/RocksDBCache
@@ -0,0 +1,77 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+ * Copyright 2016 Pelican Mapping
+ * http://osgearth.org
+ *
+ * osgEarth is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ */
+#ifndef OSGEARTH_DRIVER_CACHE_ROCKSDB
+#define OSGEARTH_DRIVER_CACHE_ROCKSDB 1
+
+#include "RocksDBCacheOptions"
+#include "Tracker"
+#include <osgEarth/Common>
+#include <osgEarth/Cache>
+#include <rocksdb/db.h>
+
+namespace osgEarth { namespace Drivers { namespace RocksDBCache
+{    
+    /** 
+     * Cache that stores data in a ROCKSDB database in the local filesystem.
+     */
+    class RocksDBCacheImpl : public osgEarth::Cache
+    {
+    public:
+        META_Object( osgEarth, RocksDBCacheImpl );
+        virtual ~RocksDBCacheImpl();
+        RocksDBCacheImpl() { } // unused
+        RocksDBCacheImpl( const RocksDBCacheImpl& rhs, const osg::CopyOp& op ) { } // unused
+
+        /**
+         * Constructs a new rocksdb cache object.
+         * @param options Options structure that comes from a serialized description of 
+         *        the object (see RocksDBCacheOptions)
+         */
+        RocksDBCacheImpl( const osgEarth::CacheOptions& options );
+
+    public: // Cache interface
+
+        osgEarth::CacheBin* addBin( const std::string& binID );
+
+        osgEarth::CacheBin* getOrCreateDefaultBin();
+
+        off_t getApproximateSize() const;
+
+        // Compact the cache, reclaiming space fragmented by removing records
+        bool compact();
+
+        // Clear all records from the cache
+        bool clear();
+
+    protected:
+
+        void init();
+        void open();
+
+        std::string  _rootPath;
+        bool         _active;
+        rocksdb::DB* _db;
+        osg::ref_ptr<Tracker> _tracker;
+        RocksDBCacheOptions _options;
+    };
+
+
+} } } // namespace osgEarth::Drivers::RocksDBCache
+
+#endif // OSGEARTH_DRIVER_CACHE_ROCKSDB
diff --git a/src/osgEarthDrivers/cache_rocksdb/RocksDBCache.cpp b/src/osgEarthDrivers/cache_rocksdb/RocksDBCache.cpp
new file mode 100644
index 0000000..943c224
--- /dev/null
+++ b/src/osgEarthDrivers/cache_rocksdb/RocksDBCache.cpp
@@ -0,0 +1,258 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+ * Copyright 2016 Pelican Mapping
+ * http://osgearth.org
+ *
+ * osgEarth is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ */
+#include "RocksDBCache"
+#include "RocksDBCacheBin"
+#include <osgEarth/URI>
+#include <osgEarth/ThreadingUtils>
+#include <osgDB/Registry>
+#include <osgDB/ReaderWriter>
+#include <osgDB/FileUtils>
+#include <osgDB/FileNameUtils>
+#include <osgDB/ObjectWrapper>
+#include <rocksdb/cache.h>
+#include <rocksdb/filter_policy.h>
+#include <rocksdb/table.h>
+#include <sys/stat.h>
+#ifndef _WIN32
+#   include <unistd.h>
+#endif
+
+#define LC "[RocksDBCache] "
+
+#define OSGEARTH_ENV_CACHE_MAX_SIZE_MB "OSGEARTH_CACHE_MAX_SIZE_MB"
+
+#define ROCKSDB_CACHE_VERSION 1
+
+using namespace osgEarth;
+using namespace osgEarth::Drivers::RocksDBCache;
+
+
+RocksDBCacheImpl::RocksDBCacheImpl( const CacheOptions& options ) :
+osgEarth::Cache( options ),
+_options       ( options ),
+_active        ( true )
+{
+    // Force OSG to initialize the image wrapper. Failure to do this can result
+    // in a race condition within OSG when the cache is accessed from multiple threads.
+    osgDB::ObjectWrapperManager* owm = osgDB::Registry::instance()->getObjectWrapperManager();
+    owm->findWrapper("osg::Image");
+    owm->findWrapper("osg::HeightField");
+
+    if ( _options.rootPath().isSet() )
+    {
+        _rootPath = URI( *_options.rootPath(), options.referrer() ).full();
+    }
+    else
+    {
+        // read the root path from ENV is necessary:
+        const char* cachePath = ::getenv(OSGEARTH_ENV_CACHE_PATH);
+        if ( cachePath )
+        {
+            _rootPath = cachePath;           
+            OE_INFO << LC << "Cache location set from environment: \"" 
+                << cachePath << "\"" << std::endl;
+        }
+    }
+
+    const char* maxsize = ::getenv(OSGEARTH_ENV_CACHE_MAX_SIZE_MB);
+    if ( maxsize )
+    {
+        unsigned mb = as<unsigned>(std::string(maxsize), 0u);
+        if ( mb > 0 )
+        {
+            _options.maxSizeMB() = mb;
+
+            OE_INFO << LC << "Set max cache size from environment: "
+                << (_options.maxSizeMB().value()) << " MB"
+                << std::endl;
+        }
+        else
+        {
+            OE_WARN << LC 
+                << "Env var \"" OSGEARTH_ENV_CACHE_MAX_SIZE_MB "\" set to an invalid value"
+                << std::endl;
+        }
+    }
+
+    _tracker = new Tracker(_options, _rootPath);
+    
+    if ( !_rootPath.empty() )
+    {
+        init();
+    }
+    else
+    {
+        _active = false;
+        OE_WARN << LC << "Illegal: no root path set for cache!" << std::endl;
+    }
+}
+
+RocksDBCacheImpl::~RocksDBCacheImpl()
+{
+    if ( _db )
+    {
+        // problem. This destructor causes a lockup sometimes. Perhaps try
+        // upgrading to a newer version of LDB. In the meantime, that's why it
+        // is commented out
+        //delete _db;
+        _db = 0L;
+    }
+}
+
+void
+RocksDBCacheImpl::init()
+{
+    // ensure there's a folder for the cache.
+    if ( !osgDB::fileExists(_rootPath) )
+    {
+        if (osgDB::makeDirectory(_rootPath) == false)
+        {
+            OE_WARN << LC << "Oh no, failed to create root cache folder \"" << _rootPath << "\""
+                << std::endl;
+            return;
+        }
+    }
+
+    open();
+
+    // Do an initial size check.
+    if ( _db )
+    {
+        _tracker->calcSize();
+    }
+
+    if ( _active )
+    {
+        OE_INFO << LC << "Opened a cache at \"" << _rootPath << "\"" << std::endl;
+    }
+}
+
+// https://github.com/facebook/rocksdb/wiki/RocksDB-Tuning-Guide
+
+void
+RocksDBCacheImpl::open()
+{
+    rocksdb::Options options;
+    options.create_if_missing = true;
+    rocksdb::BlockBasedTableOptions table_options;
+
+    options.stats_dump_period_sec = 30;
+
+	table_options.filter_policy.reset(rocksdb::NewBloomFilterPolicy(10));
+    table_options.block_size = _options.blockSize().value();
+	table_options.block_cache = rocksdb::NewLRUCache(_options.blockCacheSize().value());
+    options.table_factory.reset( NewBlockBasedTableFactory( table_options ) );
+
+	if (_options.logPath().isSet())
+		options.db_log_dir = _options.logPath().value();
+
+	options.write_buffer_size = _options.writeBufferSize().value();
+	options.level0_file_num_compaction_trigger = _options.maxFilesLevel0().value();
+	options.min_write_buffer_number_to_merge = _options.minBuffersToMerge().value();
+
+	options.max_bytes_for_level_base = options.write_buffer_size * options.min_write_buffer_number_to_merge * options.level0_file_num_compaction_trigger;
+	options.target_file_size_base = options.max_bytes_for_level_base / 10;
+
+    rocksdb::Status status;
+        
+    status = rocksdb::DB::Open(options, _rootPath, &_db);
+    if ( status.ok() )
+        return;
+
+    OE_WARN << LC << "Database problem...attempting to repair..." << std::endl;
+    status = rocksdb::RepairDB(_rootPath, options);
+    if ( status.ok() )
+    {
+        status = rocksdb::DB::Open(options, _rootPath, &_db);
+        if ( status.ok() )
+        {
+            OE_WARN << LC << "...repair complete!" << std::endl;
+            return;
+        }
+    }
+
+    OE_WARN << LC << "Failed to open or create cache bin at " << _rootPath << std::endl;
+    if ( _db )
+    {
+        delete _db;
+        _db = 0L;
+        _active = false;
+    }
+}
+
+CacheBin*
+RocksDBCacheImpl::addBin( const std::string& name )
+{
+    return _db ?
+        _bins.getOrCreate(name, new RocksDBCacheBin(name, _db, _tracker.get())) :
+        0L;
+}
+
+CacheBin*
+RocksDBCacheImpl::getOrCreateDefaultBin()
+{    
+    if ( !_db )
+        return 0L;
+
+    static Threading::Mutex s_defaultBinMutex;
+    if ( !_defaultBin.valid() )
+    {
+        Threading::ScopedMutexLock lock( s_defaultBinMutex );
+        if ( !_defaultBin.valid() ) // double-check
+        {
+            _defaultBin = new RocksDBCacheBin("_default", _db, _tracker.get());
+        }
+    }
+    return _defaultBin.get();
+}
+
+off_t
+RocksDBCacheImpl::getApproximateSize() const
+{
+    return _tracker->calcSize();
+}
+
+bool
+RocksDBCacheImpl::compact()
+{
+    if ( !_db )
+        return false;
+
+    _db->CompactRange(0L, 0L);
+
+    return true;
+}
+
+bool
+RocksDBCacheImpl::clear()
+{
+    if ( !_db )
+        return false;
+
+    // No WriteBatch because it doesn't seem to allow compaction to occur
+    // -- need to figure out why someday.
+
+    rocksdb::Iterator* it = _db->NewIterator(rocksdb::ReadOptions());
+    for(it->SeekToFirst(); it->Valid(); it->Next())
+    {
+        _db->Delete(rocksdb::WriteOptions(), it->key());
+    }
+
+    return true;
+}
diff --git a/src/osgEarthDrivers/cache_rocksdb/RocksDBCacheBin b/src/osgEarthDrivers/cache_rocksdb/RocksDBCacheBin
new file mode 100644
index 0000000..6b3ec58
--- /dev/null
+++ b/src/osgEarthDrivers/cache_rocksdb/RocksDBCacheBin
@@ -0,0 +1,144 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+ * Copyright 2016 Pelican Mapping
+ * http://osgearth.org
+ *
+ * osgEarth is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ */
+#ifndef OSGEARTH_DRIVER_CACHE_ROCKSDB_BIN
+#define OSGEARTH_DRIVER_CACHE_ROCKSDB_BIN 1
+
+#include "Tracker"
+#include <osgEarth/Common>
+#include <osgEarth/Cache>
+#include <string>
+#include <rocksdb/db.h>
+
+#define ROCKSDB_CACHE_VERSION 1
+
+namespace osgEarth { namespace Drivers { namespace RocksDBCache
+{
+    using namespace osgEarth;
+
+    /** 
+     * Cache bin implementation for a RocksDBCache.
+    */
+    class RocksDBCacheBin : public osgEarth::CacheBin
+    {
+    public:
+        RocksDBCacheBin(const std::string& name, rocksdb::DB* db, Tracker* tracker);
+
+        virtual ~RocksDBCacheBin();
+
+    public: // CacheBin interface
+
+        ReadResult readObject(const std::string& key, const osgDB::Options* dbo);
+
+        ReadResult readImage(const std::string& key, const osgDB::Options* dbo);
+
+        //ReadResult readNode(const std::string& key);
+
+        ReadResult readString(const std::string& key, const osgDB::Options* dbo);
+
+        bool write(const std::string& key, const osg::Object* object, const Config& meta, const osgDB::Options* dbo);
+
+        bool remove(const std::string& key);
+
+        bool touch(const std::string& key);
+
+        RecordStatus getRecordStatus(const std::string& key);
+
+        bool clear();
+
+        bool compact();
+        
+        unsigned getStorageSize();
+
+        Config readMetadata();
+
+        bool writeMetadata( const Config& meta );
+
+        std::string getHashedKey(const std::string& key) const;
+
+        bool purgeOldest(unsigned maxnum);
+        
+    protected:
+
+        bool binValidForReading(bool silent =true);
+
+        bool binValidForWriting(bool silent =false);
+
+        bool                              _ok;
+        bool                              _binPathExists;
+        std::string                       _metaPath;       // full path to the bin's metadata file
+        std::string                       _binPath;        // full path to the bin's root folder
+        osg::ref_ptr<osgDB::ReaderWriter> _rw;
+        osg::ref_ptr<osgDB::Options>      _rwOptions;
+        Threading::Mutex                  _rwMutex;
+        rocksdb::DB*                      _db;
+        osg::ref_ptr<Tracker>             _tracker;
+        bool                              _debug;
+        
+        // adapter base for all the osg read functions...
+        struct Reader {
+            osgDB::ReaderWriter*  _rw;
+            const osgDB::Options* _op;
+            Reader(osgDB::ReaderWriter* rw, const osgDB::Options* op) : _rw(rw), _op(op) { }
+            virtual osgDB::ReaderWriter::ReadResult read(std::istream& in) const = 0;
+            virtual std::string name() const = 0;
+        };
+
+        struct ImageReader : public Reader {
+            ImageReader(osgDB::ReaderWriter* rw, const osgDB::Options* op) : Reader(rw, op) { }
+            osgDB::ReaderWriter::ReadResult read(std::istream& in) const { return _rw->readImage(in, _op); }
+            std::string name() const { return "ImageReader"; }
+        };
+        struct NodeReader : public Reader {
+            NodeReader(osgDB::ReaderWriter* rw, const osgDB::Options* op) : Reader(rw, op) { }
+            osgDB::ReaderWriter::ReadResult read(std::istream& in) const { return _rw->readNode(in, _op); }
+            std::string name() const { return "NodeReader"; }
+        };
+        struct ObjectReader : public Reader {
+            ObjectReader(osgDB::ReaderWriter* rw, const osgDB::Options* op) : Reader(rw, op) { }
+            osgDB::ReaderWriter::ReadResult read(std::istream& in) const { return _rw->readObject(in, _op); }
+            std::string name() const { return "ObjectReader"; }
+        };
+
+        ReadResult read(const std::string& key, const Reader& reader);
+
+        void postWrite();
+
+        // key generators
+        std::string binDataKeyTuple(const std::string& key) const;
+        std::string binPhrase() const;
+        std::string dataKey(const std::string& key) const;
+        std::string dataKeyFromTuple(const std::string& tuple) const;
+        std::string dataBegin() const;
+        std::string dataEnd() const;
+        std::string metaKey(const std::string& key) const;
+        std::string metaKeyFromTuple(const std::string& tuple) const;
+        std::string metaBegin() const;
+        std::string metaEnd() const;
+        std::string timeKey(const DateTime& t, const std::string& key) const;
+        std::string timeBegin() const;
+        std::string timeEnd() const;
+        std::string binKey() const;
+        std::string timeBeginGlobal() const;
+        std::string timeEndGlobal() const;
+    };
+
+
+} } } // namespace osgEarth::Drivers::RocksDBCache
+
+#endif // OSGEARTH_DRIVER_CACHE_ROCKSDB_BIN
diff --git a/src/osgEarthDrivers/cache_rocksdb/RocksDBCacheBin.cpp b/src/osgEarthDrivers/cache_rocksdb/RocksDBCacheBin.cpp
new file mode 100644
index 0000000..e263fab
--- /dev/null
+++ b/src/osgEarthDrivers/cache_rocksdb/RocksDBCacheBin.cpp
@@ -0,0 +1,688 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+ * Copyright 2016 Pelican Mapping
+ * http://osgearth.org
+ *
+ * osgEarth is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ */
+#include "RocksDBCacheBin"
+#include <osgEarth/Cache>
+#include <osgEarth/Registry>
+#include <osgEarth/Random>
+#include <osgDB/Registry>
+#include <rocksdb/write_batch.h>
+#include <string>
+
+using namespace osgEarth;
+using namespace osgEarth::Threading;
+using namespace osgEarth::Drivers::RocksDBCache;
+
+//------------------------------------------------------------------------
+
+namespace
+{
+    void encodeMeta(const Config& meta, std::string& out)
+    {
+        out = Stringify() << meta.toJSON(false);
+    }
+
+    void decodeMeta(const std::string& in, Config& meta)
+    {
+        std::istringstream inmeta(in);
+        inmeta >> std::noskipws;
+        std::stringstream buf;
+        buf << inmeta.rdbuf();
+        std::string bufStr;
+        bufStr = buf.str();
+        meta.fromJSON( bufStr );
+    }
+
+    void blend(std::string& data, unsigned seed)
+    {
+        osgEarth::Random prng(seed, osgEarth::Random::METHOD_FAST);
+        unsigned paddedSize = data.size();
+        if ( data.size() % 4 > 0 ) paddedSize += 4 - (data.size() % 4);
+        char* buf = new char[paddedSize];
+        memcpy(buf, data.c_str(), data.size());
+        unsigned* ptr = (unsigned*)buf;
+        for(unsigned i=0; i<paddedSize/4; ++i, ++ptr)
+            (*ptr) ^= prng.next(INT_MAX);
+        data = std::string(buf, data.size());
+        delete buf;
+    }
+
+    void unblend(std::string& data, unsigned seed)
+    {
+        blend(data, seed);
+    }
+}
+
+//------------------------------------------------------------------------
+
+#undef  LC
+#define LC "[RocksDBCacheBin] "
+
+#undef  OE_TEST
+#define OE_TEST OE_NOTICE
+
+#define TIME_FIELD "rocksdb.time"
+
+
+RocksDBCacheBin::RocksDBCacheBin(const std::string& binID,
+                                 rocksdb::DB*       db,
+                                 Tracker*           tracker) :
+osgEarth::CacheBin( binID ),
+_db               ( db ),
+_tracker          ( tracker ),
+_debug            ( false )
+{
+    // reader to parse data:
+    _rw = osgDB::Registry::instance()->getReaderWriterForExtension( "osgb" );
+    _rwOptions = osgEarth::Registry::instance()->cloneOrCreateOptions();    
+    
+    if ( ::getenv("OSGEARTH_CACHE_DEBUG") )
+        _debug = true;
+}
+
+RocksDBCacheBin::~RocksDBCacheBin()
+{
+    // nop
+}
+
+bool
+RocksDBCacheBin::binValidForReading(bool silent)
+{
+    bool ok = _db != 0L;
+    if ( !ok && !silent )
+    {
+        OE_WARN << LC << "Failed to locate cache bin (" << getID() << ")" << std::endl;
+    }
+    return ok;
+}
+
+bool
+RocksDBCacheBin::binValidForWriting(bool silent)
+{
+    bool ok = _db != 0L;
+    if ( !ok && !silent )
+    {
+        OE_WARN << LC << "Failed to locate cache bin (" << getID() << ")" << std::endl;
+    }
+    return ok;
+}
+
+std::string
+RocksDBCacheBin::getHashedKey(const std::string& key) const
+{
+    return dataKey(key);
+}
+
+#define SEP std::string("!")
+
+std::string
+RocksDBCacheBin::binPhrase() const
+{
+    return SEP + getID() + SEP;
+}
+
+std::string
+RocksDBCacheBin::binKey() const
+{
+    return "b" + SEP + getID();
+}
+
+std::string
+RocksDBCacheBin::dataKey(const std::string& key) const
+{
+    return "d" + SEP + binDataKeyTuple(key);
+}
+
+std::string
+RocksDBCacheBin::binDataKeyTuple(const std::string& key) const
+{
+    return getID() + SEP + key;
+}
+
+std::string
+RocksDBCacheBin::dataKeyFromTuple(const std::string& tuple) const
+{
+    return "d" + SEP + tuple;
+}
+
+std::string
+RocksDBCacheBin::dataBegin() const
+{
+    return "d" + SEP + getID() + SEP;
+}
+
+std::string
+RocksDBCacheBin::dataEnd() const
+{
+    return "d" + SEP + getID() + SEP + "\xff";
+}
+
+std::string
+RocksDBCacheBin::metaKey(const std::string& key) const
+{
+    return "m" + SEP + binDataKeyTuple(key);
+}
+
+std::string
+RocksDBCacheBin::metaKeyFromTuple(const std::string& tuple) const
+{
+    return "m" + SEP + tuple;
+}
+
+std::string
+RocksDBCacheBin::metaBegin() const
+{
+    return "m" + SEP + getID() + SEP;
+}
+
+std::string
+RocksDBCacheBin::metaEnd() const
+{
+    return "m" + SEP + getID() + SEP + "\xff";
+}
+
+std::string
+RocksDBCacheBin::timeKey(const DateTime& t, const std::string& key) const
+{
+    return "t" + SEP + t.asCompactISO8601() + SEP + getID() + SEP + key;
+}
+
+std::string
+RocksDBCacheBin::timeBegin() const
+{
+    return "t" + SEP + getID() + SEP;
+}
+
+std::string
+RocksDBCacheBin::timeEnd() const
+{
+    return "t" + SEP + getID() + SEP + "\xff";
+}
+
+std::string
+RocksDBCacheBin::timeBeginGlobal() const
+{
+    return "t" + SEP;
+}
+
+std::string
+RocksDBCacheBin::timeEndGlobal() const
+{
+    return "t" + SEP + "\xff";
+}
+
+ReadResult
+RocksDBCacheBin::readImage(const std::string& key, const osgDB::Options* readOptions)
+{
+    return read(key, ImageReader(_rw.get(), readOptions));  
+}
+
+ReadResult
+RocksDBCacheBin::readObject(const std::string& key, const osgDB::Options* readOptions)
+{
+    //OE_INFO << LC << "Read attempt: " << key << " from " << getID() << std::endl;
+    return read(key, ObjectReader(_rw.get(), readOptions));
+}
+
+ReadResult
+RocksDBCacheBin::read(const std::string& key, const Reader& reader)
+{
+    if ( !binValidForReading() ) 
+        return ReadResult(ReadResult::RESULT_NOT_FOUND);
+
+    ++_tracker->reads;
+
+    Config metadata;
+    rocksdb::Status status;
+    rocksdb::ReadOptions ro;
+
+    // first read the metadata record.
+    std::string metavalue;
+    status = _db->Get( ro, metaKey(key), &metavalue );
+    TimeStamp lastModified = (TimeStamp)0;
+    if ( status.ok() )
+    {        
+        decodeMeta(metavalue, metadata);
+        DateTime t( metadata.value(TIME_FIELD));
+        lastModified = t.asTimeStamp();
+    }
+        
+    // next read the data record.
+    std::string datakey = dataKey(key);
+    std::string datavalue;
+    status = _db->Get( ro, datakey, &datavalue );
+    if ( !status.ok() )
+    {
+        // main record not found for some reason.
+        return ReadResult(ReadResult::RESULT_NOT_FOUND);
+    }
+
+    // blend the data string
+    if ( _tracker->seed().isSet() )
+        unblend(datavalue, _tracker->seed().value());
+
+    // finally, decode the OSGB stream into an object.
+    std::istringstream datastream(datavalue);
+    osgDB::ReaderWriter::ReadResult r = reader.read(datastream);
+    if ( !r.success() )
+    {
+        OE_WARN << LC << "Cache read failure!"
+            << "\n reader = " << reader.name()
+            << "\n error detail = " << r.message()
+            << "\n data value = " << datavalue
+            << "\n";
+
+        return ReadResult(ReadResult::RESULT_READER_ERROR);
+    }
+        
+    if ( _debug )
+    {
+        OE_NOTICE << LC << "Bin " << getID() << ": read (" << key << ")\n";
+    }
+
+    // if there's a size limit, we need to 'touch' the record.
+    if ( _tracker->hasSizeLimit() )
+    {
+        // Room for optimization here since we already have the 
+        // meta/time records around.
+        touch( key );
+    }
+
+    ++_tracker->hits;
+    ReadResult rr(r.getObject(), metadata);
+    rr.setLastModifiedTime(lastModified);    
+    return rr;
+}
+
+ReadResult
+RocksDBCacheBin::readString(const std::string& key, const osgDB::Options* readOptions)
+{
+    ReadResult r = readObject(key, readOptions);
+    if ( r.succeeded() )
+    {
+        if ( r.get<StringObject>() )
+            return r;
+        else
+            return ReadResult();
+    }
+    else
+    {
+        return r;
+    }
+}
+
+bool
+RocksDBCacheBin::write(const std::string& key, const osg::Object* object, const Config& meta, const osgDB::Options* writeOptions)
+{
+    if ( !binValidForWriting() || !object ) 
+        return false;
+        
+    osgDB::ReaderWriter::WriteResult r;
+    bool objWriteOK = false;
+
+    std::string       data;
+    std::stringstream datastream;
+
+    if ( dynamic_cast<const osg::Image*>(object) )
+    {
+        if ( (_rw->supportedFeatures() & _rw->FEATURE_WRITE_IMAGE) == 0 )
+        {
+            OE_WARN << LC << "Internal: tried to write image to " << _rw->className() << "\n";
+            return false;
+        }
+        r = _rw->writeImage( *static_cast<const osg::Image*>(object), datastream, writeOptions);
+        objWriteOK = r.success();
+    }
+    else if ( dynamic_cast<const osg::Node*>(object) )
+    {
+        if ( (_rw->supportedFeatures() & _rw->FEATURE_WRITE_NODE) == 0 )
+        {
+            OE_WARN << LC << "Internal: tried to write node to " << _rw->className() << "\n";
+            return false;
+        }
+        r = _rw->writeNode( *static_cast<const osg::Node*>(object), datastream, writeOptions);
+        objWriteOK = r.success();
+    }
+    else
+    {
+        if ( (_rw->supportedFeatures() & _rw->FEATURE_WRITE_OBJECT) == 0 )
+        {
+            OE_WARN << LC << "Internal: tried to write an object to " << _rw->className() << "\n";
+            return false;
+        }
+        r = _rw->writeObject( *object, datastream, writeOptions );
+        objWriteOK = r.success();
+    }
+
+    if (objWriteOK)
+    {
+        DateTime now;
+        rocksdb::WriteBatch batch;
+
+        // write the data:
+        data = datastream.str();
+        if ( _tracker->seed().isSet() )
+            blend(data, _tracker->seed().value());
+        batch.Put( dataKey(key), data );
+
+        // write the timestamp index:
+        batch.Put( timeKey(now, key), binDataKeyTuple(key) );
+
+        // write the metadata:
+        Config metadata(meta);
+        metadata.set( TIME_FIELD, now.asCompactISO8601() );
+        encodeMeta( metadata, data );
+        batch.Put( metaKey(key), data );
+
+        objWriteOK = _db->Write( rocksdb::WriteOptions(), &batch ).ok();
+
+        if ( objWriteOK )
+        {
+            ++_tracker->writes;
+            postWrite();
+            
+            if ( _debug )
+            {
+                OE_NOTICE << LC << "Bin " << getID() << ": wrote (" << key << ")\n";
+            }
+        }
+    }
+
+        
+    if ( !objWriteOK )
+    {
+        OE_WARN << LC << "Bin " << getID() << ": FAILED to write (" << key << "); msg = \"" 
+            << r.message() << "\"\n";
+    }
+
+    return objWriteOK;
+}
+
+void
+RocksDBCacheBin::postWrite()
+{
+    if ( _tracker->hasSizeLimit() )
+    {
+        if ( _tracker->isOverLimit() )
+        {
+            if ( _tracker->isTimeToPurge() )
+            {
+                this->purgeOldest(_tracker->numToPurge());
+
+                if (_debug)
+                {
+                    off_t size = _tracker->calcSize();
+                    OE_NOTICE 
+                        << LC << "Cache size = " << (size/1048576) << " MB; " 
+                        << "Hit ratio = " << (float)_tracker->hits/(float)_tracker->reads << std::endl;
+                }
+            }
+        }
+        else
+        {
+            if ( _tracker->isTimeToCheckSize() )
+            {
+                off_t size = _tracker->calcSize();
+                if ( _debug )
+                {
+                    OE_NOTICE 
+                        << LC << "Cache size = " << (size/1048576) << " MB; " 
+                        << "Hit ratio = " << (float)_tracker->hits/(float)_tracker->reads << std::endl;
+                }
+            }
+        }
+    }
+}
+
+CacheBin::RecordStatus
+RocksDBCacheBin::getRecordStatus(const std::string& key)
+{
+    if ( !binValidForReading() ) 
+        return STATUS_NOT_FOUND;
+
+    rocksdb::Status status;
+    rocksdb::ReadOptions ro;
+
+    // read the metadata record.
+    std::string metavalue;
+    status = _db->Get( ro, metaKey(key), &metavalue );
+    if ( status.ok() )
+    {        
+        return STATUS_OK;
+    }
+    else
+    {
+        return STATUS_NOT_FOUND;
+    }
+}
+
+bool
+RocksDBCacheBin::remove(const std::string& key)
+{
+    if ( !binValidForReading() )
+        return false;
+
+    // first read in the time from the metadata record.
+    std::string metavalue;
+    if ( _db->Get(rocksdb::ReadOptions(), metaKey(key), &metavalue).ok() == false )
+        return false;
+
+    Config metadata;
+    decodeMeta(metavalue, metadata);
+    DateTime t(metadata.value(TIME_FIELD));
+
+    rocksdb::WriteBatch batch;
+    batch.Delete( dataKey(key) );
+    batch.Delete( metaKey(key) );
+    batch.Delete( timeKey(t, key) );
+        
+    rocksdb::Status status = _db->Write(rocksdb::WriteOptions(), &batch);
+    if ( !status.ok() )
+    {
+        OE_WARN << LC << "Failed to remove (" << key << ") from bin " << getID() << std::endl;
+        return false;
+    }
+    else if ( _debug )
+    {
+        OE_NOTICE << LC << "Removed (" << key << ") from bin " << getID() << std::endl;
+    }
+
+    return true;
+}
+
+bool
+RocksDBCacheBin::touch(const std::string& key)
+{    
+    if ( !binValidForWriting() )
+        return false;
+
+    // first read in the time from the metadata record.
+    std::string metavalue;
+    if ( _db->Get(rocksdb::ReadOptions(), metaKey(key), &metavalue).ok() == false )
+        return false;
+
+    Config metadata;
+    decodeMeta(metavalue, metadata);
+    DateTime oldtime(metadata.value(TIME_FIELD));
+        
+    rocksdb::WriteBatch batch;
+
+    // In a transaction, update the metadata record with the current time.
+    std::string newtime = DateTime().asCompactISO8601();
+    metadata.set(TIME_FIELD, newtime);
+    encodeMeta(metadata, metavalue);
+    batch.Put(metaKey(key), metavalue);
+
+    // ...remove the old time index record:
+    batch.Delete( timeKey(oldtime, key) );
+
+    // ...and write a new time index record.
+    batch.Put( timeKey(newtime, key), binDataKeyTuple(key) );
+
+    rocksdb::Status status = _db->Write(rocksdb::WriteOptions(), &batch);
+    if ( !status.ok() )
+    {
+        OE_WARN << LC << "Failed to touch (" << key << ") in bin " << getID() << std::endl;
+    }
+    else if ( _debug )
+    {
+        OE_NOTICE << LC << "Bin " << getID() << ": touch (" << key << ")\n";
+    }
+    return status.ok();
+}
+
+bool
+RocksDBCacheBin::clear()
+{
+    if ( !binValidForWriting() )
+        return false;
+    
+    rocksdb::WriteOptions wo;
+    std::string binphrase = binPhrase();
+    rocksdb::WriteBatch batch;
+    rocksdb::Iterator* i = _db->NewIterator(rocksdb::ReadOptions());
+    for(i->SeekToFirst(); i->Valid(); i->Next())
+    {
+        std::string key = i->key().ToString();
+        if ( key.find(binphrase) != std::string::npos )
+        {
+            _db->Delete( wo, i->key() );
+        }
+    }
+    delete i;
+
+    if ( _debug )
+    {
+        OE_NOTICE << LC << "Cleared bin " << getID() << std::endl;
+    }
+
+    return true;
+}
+
+bool
+RocksDBCacheBin::compact()
+{
+    if ( !binValidForWriting() )
+        return false;
+
+    // This could take a while.
+    _db->CompactRange(0L, 0L);
+
+    return false;
+}
+
+unsigned
+RocksDBCacheBin::getStorageSize()
+{
+    if ( !binValidForReading() )
+        return false;
+
+    //Note: doesn't work..
+    rocksdb::Range ranges[3];
+    uint64_t       sizes[3];
+
+    ranges[0] = rocksdb::Range(dataBegin(), dataEnd());
+    ranges[1] = rocksdb::Range(metaBegin(), metaEnd());
+    ranges[2] = rocksdb::Range(timeBegin(), timeEnd());
+    sizes[0] = sizes[1] = sizes[2] = 0;
+
+    _db->GetApproximateSizes( ranges, 3, sizes );
+    return sizes[0] + sizes[1] + sizes[2];
+}
+
+Config
+RocksDBCacheBin::readMetadata()
+{
+    if ( !binValidForReading() )
+        return Config();
+
+    ScopedMutexLock exclusiveLock( _rwMutex );
+
+    std::string binvalue;
+    rocksdb::Status status = _db->Get(rocksdb::ReadOptions(), binKey(), &binvalue);
+    if ( !status.ok() )
+        return Config();
+
+    Config binMetadata;
+    decodeMeta(binvalue, binMetadata);
+    return binMetadata;
+}
+
+bool
+RocksDBCacheBin::writeMetadata(const Config& conf)
+{
+    if ( !binValidForWriting() )
+        return false;
+
+    ScopedMutexLock exclusiveLock( _rwMutex );
+
+    // inject the cache version
+    Config mutableConf(conf);
+    mutableConf.set("rocksdb.cache_version", ROCKSDB_CACHE_VERSION);
+
+    std::string value;
+    encodeMeta(mutableConf, value);
+
+    if ( _db->Put(rocksdb::WriteOptions(), binKey(), value).ok() == false )
+    {
+        OE_WARN << LC << "Failed to write metadata record for bin (" << getID() << ")" << std::endl;
+        return false;
+    }
+
+    return true;
+}
+
+bool
+RocksDBCacheBin::purgeOldest(unsigned maxnum)
+{
+    if ( !binValidForWriting() )
+        return false;
+
+    rocksdb::Iterator* it = _db->NewIterator(rocksdb::ReadOptions());
+
+    unsigned count = 0;
+    std::string limit = timeEndGlobal();
+
+    // note: this will delete records NOT OF THIS BIN as well!
+    for(it->Seek(timeBeginGlobal());
+        count < maxnum && it->Valid() && it->key().ToString() < limit;
+        it->Next(), ++count )
+    {
+        if ( !it->status().ok() )
+            break;
+
+        std::string tuple = it->value().ToString();
+
+        // doing this in a WriteBatch did not work. The size of the
+        // database would never go down.
+        rocksdb::WriteOptions wo;
+        _db->Delete( wo, dataKeyFromTuple(tuple) );
+        _db->Delete( wo, metaKeyFromTuple(tuple) );
+        _db->Delete( wo, it->key() );
+    }
+
+    delete it;
+
+    if ( _debug )
+    {
+        OE_NOTICE << LC << "Purged " << count << " record(s) for "
+            << (_tracker->calcSize()/1048576) << " MB" << std::endl;
+    }
+
+    return true;
+}
diff --git a/src/osgEarthDrivers/cache_rocksdb/RocksDBCacheDriver.cpp b/src/osgEarthDrivers/cache_rocksdb/RocksDBCacheDriver.cpp
new file mode 100644
index 0000000..33bd1e5
--- /dev/null
+++ b/src/osgEarthDrivers/cache_rocksdb/RocksDBCacheDriver.cpp
@@ -0,0 +1,57 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+ * Copyright 2016 Pelican Mapping
+ * http://osgearth.org
+ *
+ * osgEarth is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ */
+#include "RocksDBCache"
+#include <osgEarth/Cache>
+#include <osgDB/Registry>
+#include <osgDB/FileNameUtils>
+
+namespace osgEarth { namespace Drivers { namespace RocksDBCache
+{
+    /**
+     * This driver defers loading of the source data to the appropriate OSG plugin. You
+     * must explicity set an override profile when using this driver.
+     *
+     * For example, use this driver to load a simple jpeg file; then set the profile to
+     * tell osgEarth its projection.
+     */
+    class RocksDBCacheDriver : public osgEarth::CacheDriver
+    {
+    public:
+        RocksDBCacheDriver()
+        {
+            supportsExtension( "osgearth_cache_rocksdb", "rocksdb cache for osgEarth" );
+        }
+
+        virtual const char* className() const
+        {
+            return "rocksdb cache for osgEarth";
+        }
+
+        virtual ReadResult readObject(const std::string& file_name, const Options* options) const
+        {
+            if ( !acceptsExtension(osgDB::getLowerCaseFileExtension( file_name )))
+                return ReadResult::FILE_NOT_HANDLED;
+
+            return ReadResult( new RocksDBCacheImpl( getCacheOptions(options) ) );
+        }
+    };
+
+    REGISTER_OSGPLUGIN(osgearth_cache_rocksdb, RocksDBCacheDriver);
+
+} } } // namespace osgEarth::Drivers::RocksDBCache
diff --git a/src/osgEarthDrivers/cache_rocksdb/RocksDBCacheOptions b/src/osgEarthDrivers/cache_rocksdb/RocksDBCacheOptions
new file mode 100644
index 0000000..c6f35bd
--- /dev/null
+++ b/src/osgEarthDrivers/cache_rocksdb/RocksDBCacheOptions
@@ -0,0 +1,153 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+ * Copyright 2016 Pelican Mapping
+ * http://osgearth.org
+ *
+ * osgEarth is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ */
+#ifndef OSGEARTH_DRIVER_CACHE_ROCKSDB_OPTIONS
+#define OSGEARTH_DRIVER_CACHE_ROCKSDB_OPTIONS 1
+
+#include <osgEarth/Common>
+#include <osgEarth/Cache>
+#include <string>
+
+namespace osgEarth { namespace Drivers { namespace RocksDBCache
+{
+    using namespace osgEarth;
+    
+    /**
+     * Serializable options for the RocksDBCache.
+     */
+    class RocksDBCacheOptions : public CacheOptions
+    {
+    public:
+        RocksDBCacheOptions( const ConfigOptions& options =ConfigOptions() )
+            : CacheOptions      ( options ),
+              _maxSizeMB        ( 0 ),
+              _sizeCheckPeriod  ( 100 ),
+              _sizePurgePeriod  ( 75 ),
+              _blockSize        ( 262144 ),// 256K
+			  _blockCacheSize   ( 16777216 ), // 16MB
+			  _writeBufferSize  ( 134217728 ), // 128MB
+			  _maxFilesLevel0   ( 10 ),
+			  _minBuffersToMerge( 1 )
+        {
+            setDriver( "RocksDB" );
+            fromConfig( _conf ); 
+        }
+
+        /** dtor */
+        virtual ~RocksDBCacheOptions() { }
+
+    public:
+        /** Folder containing the cache bins. */
+        optional<std::string>& rootPath() { return _path; }
+        const optional<std::string>& rootPath() const { return _path; }
+
+		/** Folder to write RocksDB log files to. */
+		optional<std::string>& logPath() { return _logPath; }
+		const optional<std::string>& logPath() const { return _logPath; }
+
+        /** Maximum size of the cache in megabytes. Note: this is not
+         *  a guarantee - merely a guideline. */
+        optional<unsigned>& maxSizeMB() { return _maxSizeMB; }
+        const optional<unsigned>& maxSizeMB() const { return _maxSizeMB; }
+
+        //--- Advanced options ---
+
+        /** Number of writes between cap checks */
+        optional<unsigned>& sizeCheckPeriod() { return _sizeCheckPeriod; }
+        const optional<unsigned>& sizeCheckPeriod() const { return _sizeCheckPeriod; }
+
+        /** Number of writer between cap purges */
+        optional<unsigned>& sizePurgePeriod() { return _sizePurgePeriod; }
+        const optional<unsigned>& sizePurgePeriod() const { return _sizePurgePeriod; }
+
+        /** RocksDB block size */
+        optional<unsigned>& blockSize() { return _blockSize; }
+        const optional<unsigned>& blockSize() const { return _blockSize; }
+
+		/** RocksDB LRU Cache size */
+		optional<unsigned>& blockCacheSize() { return _blockCacheSize; }
+		const optional<unsigned>& blockCacheSize() const { return _blockCacheSize; }
+
+		/** RocksDB write_buffer_size: size of in-memory data block before being written to disk */
+		optional<unsigned>& writeBufferSize() { return _writeBufferSize; }
+		const optional<unsigned>& writeBufferSize() const { return _writeBufferSize; }
+
+		/** RocksDB level0_file_num_compaction_trigger: number of files in level 0 before a compaction is triggered */
+		optional<unsigned>& maxFilesLevel0() { return _maxFilesLevel0; }
+		const optional<unsigned>& maxFilesLevel0() const { return _maxFilesLevel0; }
+
+		/** RocksDB min_write_buffer_number_to_merge: number of full write buffers needed for level 0 merge */
+		optional<unsigned>& minBuffersToMerge() { return _minBuffersToMerge; }
+		const optional<unsigned>& minBuffersToMerge() const { return _minBuffersToMerge; }
+
+        /** Obfuscation key string */
+        optional<std::string>& key() { return _key; }
+        const optional<std::string>& key() const { return _key; }
+
+    public:
+        virtual Config getConfig() const {
+            Config conf = ConfigOptions::getConfig();
+            conf.addIfSet( "path", _path );
+			conf.addIfSet( "log_path", _logPath );
+            conf.addIfSet( "max_size_mb", _maxSizeMB );
+            conf.addIfSet( "size_check_period", _sizeCheckPeriod );
+            conf.addIfSet( "size_purge_period", _sizePurgePeriod );
+            conf.addIfSet( "block_size", _blockSize );
+			conf.addIfSet( "block_cache_size", _blockCacheSize );
+			conf.addIfSet( "write_buffer_size", _writeBufferSize );
+			conf.addIfSet( "max_files_level0", _maxFilesLevel0 );
+			conf.addIfSet( "min_buffers_to_merge", _minBuffersToMerge );
+            conf.addIfSet( "key", _key );
+            return conf;
+        }
+        virtual void mergeConfig( const Config& conf ) {
+            ConfigOptions::mergeConfig( conf );
+            fromConfig( conf );
+        }
+
+    private:
+        void fromConfig( const Config& conf ) {
+            conf.getIfSet( "path", _path );
+			conf.getIfSet( "log_path", _logPath );
+            conf.getIfSet( "max_size_mb", _maxSizeMB );
+            conf.getIfSet( "size_check_period", _sizeCheckPeriod );
+            conf.getIfSet( "size_purge_period", _sizePurgePeriod );
+            conf.getIfSet( "block_size", _blockSize );
+			conf.getIfSet( "block_cache_size", _blockCacheSize );
+			conf.getIfSet( "write_buffer_size", _writeBufferSize );
+			conf.getIfSet( "max_files_level0", _maxFilesLevel0 );
+			conf.getIfSet( "min_buffers_to_merge", _minBuffersToMerge );
+            conf.getIfSet( "key", _key );
+        }
+
+        optional<std::string> _path;
+		optional<std::string> _logPath;
+        optional<unsigned>    _maxSizeMB;
+        optional<unsigned>    _sizeCheckPeriod;
+        optional<unsigned>    _sizePurgePeriod;
+        optional<unsigned>    _blockSize;
+		optional<unsigned>    _blockCacheSize;
+		optional<unsigned>    _writeBufferSize;
+		optional<unsigned>    _maxFilesLevel0;
+		optional<unsigned>    _minBuffersToMerge;
+        optional<std::string> _key;
+    };
+
+} } } // namespace osgEarth::Drivers::RocksDBCache
+
+#endif // OSGEARTH_DRIVER_CACHE_ROCKSDB_OPTIONS
diff --git a/src/osgEarthDrivers/cache_rocksdb/Tracker b/src/osgEarthDrivers/cache_rocksdb/Tracker
new file mode 100644
index 0000000..0cf183d
--- /dev/null
+++ b/src/osgEarthDrivers/cache_rocksdb/Tracker
@@ -0,0 +1,113 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+ * Copyright 2016 Pelican Mapping
+ * http://osgearth.org
+ *
+ * osgEarth is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ */
+#ifndef OSGEARTH_DRIVER_CACHE_ROCKSDB_TRACKER
+#define OSGEARTH_DRIVER_CACHE_ROCKSDB_TRACKER 1
+
+#include "RocksDBCacheOptions"
+#include <osgEarth/ThreadingUtils>
+#include <osgDB/FileUtils>
+#include <osgDB/FileNameUtils>
+#include <osg/Referenced>
+#include <sys/stat.h>
+#ifndef _WIN32
+#   include <unistd.h>
+#endif
+
+namespace osgEarth { namespace Drivers { namespace RocksDBCache
+{
+    typedef OpenThreads::Atomic unsigned_atomic;
+
+    /**
+     * Tracks usage metrics across a RocksDB cache
+     */
+    class Tracker : public osg::Referenced
+    {
+    public:
+        Tracker(const RocksDBCacheOptions& options,
+                const std::string&         path ) : 
+            _options(options),                 
+            _path(path),
+            _seed(0)
+        {
+            _maxBytes = (off_t)(options.maxSizeMB().get() * 1048576);
+            _size = (::off_t)0;
+
+            if (_options.key().isSet() && !_options.key()->empty())
+            {
+                _seed = osgEarth::hashString(_options.key().value());
+            }
+        }
+        virtual ~Tracker() { }
+
+    public:
+        unsigned_atomic reads;
+        unsigned_atomic hits;
+        unsigned_atomic writes;
+
+        bool hasSizeLimit() const {
+            return _options.maxSizeMB().isSet();
+        }
+
+        bool isOverLimit() const { 
+            return _size > _maxBytes; 
+        }
+
+        bool isTimeToCheckSize() const {
+            return ((unsigned)writes % _options.sizeCheckPeriod().value()) == 0;
+        }
+
+        bool isTimeToPurge() const {
+            unsigned w = (unsigned)writes;
+            return w == 1 || (w % _options.sizePurgePeriod().value()) == 0;
+        }
+
+        unsigned numToPurge() const {
+            return _options.sizePurgePeriod().value();
+        }
+
+        const optional<unsigned>& seed() const {
+            return _seed;
+        }
+
+        ::off_t calcSize()
+        {
+            ::off_t total = 0;
+            osgDB::DirectoryContents dir = osgDB::getDirectoryContents(_path);
+            for(osgDB::DirectoryContents::iterator i = dir.begin(); i != dir.end(); ++i)
+            {
+                std::string path = osgDB::concatPaths(_path, *i);
+                struct stat s;
+                ::stat( path.c_str(), &s );
+                total += s.st_size;
+            }
+            _size = total;
+            return total;
+        }
+
+    private:
+        const std::string         _path;
+        const RocksDBCacheOptions _options;
+        ::off_t                   _maxBytes;
+        ::off_t                   _size;
+        optional<unsigned>        _seed;
+    };
+
+} } } // namespace osgEarth::Drivers::RocksDBCache
+
+#endif // OSGEARTH_DRIVER_CACHE_ROCKSDB_TRACKER
diff --git a/src/osgEarthDrivers/colorramp/ColorRampOptions b/src/osgEarthDrivers/colorramp/ColorRampOptions
index dd042b0..7bdd6cd 100644
--- a/src/osgEarthDrivers/colorramp/ColorRampOptions
+++ b/src/osgEarthDrivers/colorramp/ColorRampOptions
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthDrivers/colorramp/ColorRampTileSource.cpp b/src/osgEarthDrivers/colorramp/ColorRampTileSource.cpp
index 29a938e..852818a 100644
--- a/src/osgEarthDrivers/colorramp/ColorRampTileSource.cpp
+++ b/src/osgEarthDrivers/colorramp/ColorRampTileSource.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -52,14 +52,11 @@ public:
 
         if (!_options.elevationLayer().isSet())
         {
-            return Status::Error("Please specify a heightfield layer for the color ramp");
+            return Status::Error(Status::ConfigurationError, "Please specify a heightfield layer for the color ramp");
         }
         
         _layer = new ElevationLayer(*_options.elevationLayer() );
-        if (!_layer.valid())
-        {
-            return Status::Error("Failed to initialize the Please specify a heightfield layer for the color ramp");
-        }
+        _layer->open();
 
         setProfile(_layer->getProfile());
 
@@ -148,7 +145,7 @@ public:
         supportsExtension( "osgearth_colorramp", "Color ramp driver for osgEarth" );
     }
 
-    virtual const char* className()
+    virtual const char* className() const
     {
         return "ColorRamp Image Driver";
     }
diff --git a/src/osgEarthDrivers/debug/DebugOptions b/src/osgEarthDrivers/debug/DebugOptions
index 3877d26..f8684bd 100644
--- a/src/osgEarthDrivers/debug/DebugOptions
+++ b/src/osgEarthDrivers/debug/DebugOptions
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthDrivers/debug/DebugTileSource.cpp b/src/osgEarthDrivers/debug/DebugTileSource.cpp
index 18109b0..e0d40a3 100644
--- a/src/osgEarthDrivers/debug/DebugTileSource.cpp
+++ b/src/osgEarthDrivers/debug/DebugTileSource.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -153,7 +153,7 @@ class DebugTileSourceDriver : public TileSourceDriver
             supportsExtension( "osgearth_debug", "Debugging driver" );
         }
 
-        virtual const char* className()
+        virtual const char* className() const
         {
             return "Debugging Driver";
         }
diff --git a/src/osgEarthDrivers/detail/CMakeLists.txt b/src/osgEarthDrivers/detail/CMakeLists.txt
new file mode 100644
index 0000000..5e8d0bc
--- /dev/null
+++ b/src/osgEarthDrivers/detail/CMakeLists.txt
@@ -0,0 +1,42 @@
+#
+# Detail texture generator plugin
+#
+
+set(TARGET_GLSL
+	Detail.vert.view.glsl
+    Detail.frag.glsl
+    )
+
+set(SHADERS_CPP "${CMAKE_CURRENT_BINARY_DIR}/AutoGenShaders.cpp")
+
+set(TARGET_IN
+    DetailShaders.cpp.in)
+
+configure_shaders(
+    DetailShaders.cpp.in
+    ${SHADERS_CPP}
+    ${TARGET_GLSL} )
+
+set(TARGET_SRC
+	DetailPlugin.cpp
+	DetailExtension.cpp
+	DetailTerrainEffect.cpp
+	${SHADERS_CPP} )
+	
+set(LIB_PUBLIC_HEADERS
+	DetailExtension
+	DetailOptions
+	DetailTerrainEffect)
+	
+set(TARGET_H
+	${LIB_PUBLIC_HEADERS}
+	DetailShaders
+	)
+
+set(TARGET_COMMON_LIBRARIES ${TARGET_COMMON_LIBRARIES}
+    osgEarthUtil)
+	
+setup_plugin(osgearth_detail)
+
+# to install public driver includes:
+set(LIB_NAME detail)
diff --git a/src/osgEarthDrivers/detail/Detail.frag.glsl b/src/osgEarthDrivers/detail/Detail.frag.glsl
new file mode 100644
index 0000000..106aa5e
--- /dev/null
+++ b/src/osgEarthDrivers/detail/Detail.frag.glsl
@@ -0,0 +1,15 @@
+#version $GLSL_VERSION_STR
+#pragma vp_entryPoint oe_detail_fragment
+#pragma vp_location   fragment_coloring
+#pragma vp_order      1
+                
+uniform sampler2D oe_detail_tex; // uniform of detail texture
+uniform float oe_detail_alpha;   // The detail textures alpha.
+in vec2 detailCoords;            // input from vertex stage
+in float detailIntensity;        // The intensity of the detail effect.
+                
+void oe_detail_fragment(inout vec4 color)
+{
+    vec4 texel = texture(oe_detail_tex, detailCoords);
+    color.rgb = mix(color.rgb, texel.rgb, oe_detail_alpha * detailIntensity);
+}                
\ No newline at end of file
diff --git a/src/osgEarthDrivers/detail/Detail.vert.view.glsl b/src/osgEarthDrivers/detail/Detail.vert.view.glsl
new file mode 100644
index 0000000..af76960
--- /dev/null
+++ b/src/osgEarthDrivers/detail/Detail.vert.view.glsl
@@ -0,0 +1,20 @@
+#version $GLSL_VERSION_STR
+
+#pragma vp_entryPoint oe_detail_vertexView
+#pragma vp_location   vertex_view
+
+uniform float oe_detail_lod;    // uniform of base LOD
+uniform float oe_detail_maxRange;
+uniform float oe_detail_attenDist;
+vec4 oe_layer_tilec;        // stage global - tile coordinates
+out vec2 detailCoords;      // output to fragment stage
+out float detailIntensity;  // output to fragment stage.
+                
+// Terrain SDK function
+vec2 oe_terrain_scaleCoordsToRefLOD(in vec2 tc, in float refLOD);
+               
+void oe_detail_vertexView(inout vec4 VertexView)
+{
+  detailCoords = oe_terrain_scaleCoordsToRefLOD(oe_layer_tilec.st, int(oe_detail_lod));
+  detailIntensity = clamp((oe_detail_maxRange - (-VertexView.z))/oe_detail_attenDist, 0.0, 1.0);
+}
\ No newline at end of file
diff --git a/src/osgEarthDrivers/detail/DetailExtension b/src/osgEarthDrivers/detail/DetailExtension
new file mode 100644
index 0000000..d337f3a
--- /dev/null
+++ b/src/osgEarthDrivers/detail/DetailExtension
@@ -0,0 +1,73 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+ * Copyright 2016 Pelican Mapping
+ * http://osgearth.org
+ *
+ * osgEarth is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ */
+#ifndef OSGEARTH_DETAIL_EXTENSION
+#define OSGEARTH_DETAIL_EXTENSION 1
+
+#include "DetailOptions"
+#include "DetailTerrainEffect"
+#include <osgEarth/Extension>
+#include <osgEarth/MapNode>
+#include <osgEarthUtil/Controls>
+
+namespace osgEarth { namespace Detail
+{
+    using namespace osgEarth;
+    using namespace osgEarth::Util::Controls;
+
+    /**
+     * Extension for loading a detail texture.
+     */
+    class DetailExtension : public Extension,
+                            public ExtensionInterface<MapNode>
+    {
+    public:
+        META_Object(osgearth_detail, DetailExtension);
+
+        // CTORs
+        DetailExtension();
+        DetailExtension(const DetailOptions& options);
+
+        // DTOR
+        virtual ~DetailExtension();
+
+
+    public: // Extension
+
+        void setDBOptions(const osgDB::Options* dbOptions);
+
+
+    public: // ExtensionInterface<MapNode>
+
+        bool connect(MapNode* mapNode);
+
+        bool disconnect(MapNode* mapNode);
+
+
+    protected: // Object
+        DetailExtension(const DetailExtension& rhs, const osg::CopyOp& op) { }
+
+    private:
+        const DetailOptions                 _options;
+        osg::ref_ptr<const osgDB::Options>     _dbOptions;
+        osg::ref_ptr<DetailTerrainEffect>   _effect;
+    };
+
+} } // namespace osgEarth::Detail
+
+#endif // OSGEARTH_DETAIL_EXTENSION
diff --git a/src/osgEarthDrivers/detail/DetailExtension.cpp b/src/osgEarthDrivers/detail/DetailExtension.cpp
new file mode 100644
index 0000000..0d42563
--- /dev/null
+++ b/src/osgEarthDrivers/detail/DetailExtension.cpp
@@ -0,0 +1,79 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+ * Copyright 2016 Pelican Mapping
+ * http://osgearth.org
+ *
+ * osgEarth is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ */
+#include "DetailExtension"
+#include "DetailTerrainEffect"
+#include <osgEarth/TerrainEngineNode>
+
+using namespace osgEarth;
+using namespace osgEarth::Detail;
+
+#define LC "[DetailExtension] "
+
+
+DetailExtension::DetailExtension()
+{
+    //nop
+}
+
+DetailExtension::DetailExtension(const DetailOptions& options) :
+_options( options )
+{
+    //nop
+}
+
+DetailExtension::~DetailExtension()
+{
+    //nop
+}
+
+void
+DetailExtension::setDBOptions(const osgDB::Options* dbOptions)
+{
+    _dbOptions = dbOptions;
+}
+
+bool
+DetailExtension::connect(MapNode* mapNode)
+{
+    if ( !mapNode )
+    {
+        OE_WARN << LC << "Illegal: MapNode cannot be null." << std::endl;
+        return false;
+    }
+
+    _effect = new DetailTerrainEffect( _options );
+
+    mapNode->getTerrainEngine()->addEffect( _effect.get() );
+    
+    OE_INFO << LC << "Installed!\n";
+
+    return true;
+}
+
+bool
+DetailExtension::disconnect(MapNode* mapNode)
+{
+    if ( mapNode )
+    {
+        mapNode->getTerrainEngine()->removeEffect( _effect.get() );
+    }
+    _effect = 0L;
+    return true;
+}
+
diff --git a/src/osgEarthDrivers/detail/DetailOptions b/src/osgEarthDrivers/detail/DetailOptions
new file mode 100644
index 0000000..7904ad1
--- /dev/null
+++ b/src/osgEarthDrivers/detail/DetailOptions
@@ -0,0 +1,101 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+ * Copyright 2016 Pelican Mapping
+ * http://osgearth.org
+ *
+ * osgEarth is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ */
+#ifndef OSGEARTH_DRIVER_DETAIL_OPTIONS
+#define OSGEARTH_DRIVER_DETAIL_OPTIONS 1
+
+#include <osgEarth/Common>
+#include <osgEarth/URI>
+
+namespace osgEarth { namespace Detail
+{
+    using namespace osgEarth;
+
+    class DetailOptions : public DriverConfigOptions // NO EXPORT; header only
+    {
+    public:
+        // The lod that the detail texture is displayed at.
+        optional<unsigned>& lod() { return _lod; }
+        const optional<unsigned>& size() const { return _lod; }
+
+        // detail texture.
+        optional<URI>& imageURI() { return _imageURI; }
+        const optional<URI>& imageURI() const { return _imageURI; }
+
+        // The alpha of the detail texture.
+        optional<float>& alpha() { return _alpha; }
+        const optional<float>& alpha() const { return _alpha; }
+
+        // The max range of the detail texture.
+        optional<float>& maxRange() { return _maxRange; }
+        const optional<float>& maxRange() const { return _maxRange; }
+
+        // The attenutation distance of the detail texture.
+        optional<float>& attenDist() { return _attenDist; }
+        const optional<float>& attenDist() const { return _attenDist; }
+
+    public:
+        DetailOptions( const ConfigOptions& opt =ConfigOptions() ) : DriverConfigOptions( opt )
+        {
+            setDriver( "detail" );
+            _lod.init( 23u );            
+            _alpha.init( 0.5 ); 
+            _maxRange.init(6000.0);
+            _attenDist.init(2000.0f);
+            fromConfig( _conf );
+        }
+
+        virtual ~DetailOptions() { }
+
+    public:
+        Config getConfig() const {
+            Config conf = DriverConfigOptions::getConfig();
+            conf.updateIfSet("image", _imageURI);
+            conf.updateIfSet("lod", _lod);
+            conf.updateIfSet("alpha", _alpha);
+            conf.updateIfSet("max_range", _maxRange);
+            conf.updateIfSet("attenuation", _attenDist);
+            return conf;
+        }
+
+    protected:
+        void mergeConfig( const Config& conf ) {
+            DriverConfigOptions::mergeConfig( conf );
+            fromConfig( conf );
+        }
+
+    private:
+        void fromConfig( const Config& conf ) {
+            conf.getIfSet( "image", _imageURI );
+            conf.getIfSet( "lod", _lod );
+            conf.getIfSet( "alpha", _alpha );
+            conf.getIfSet( "max_range", _maxRange );
+            conf.getIfSet( "attenuation", _attenDist);
+        }
+
+        optional<URI> _imageURI;
+        optional<unsigned int> _lod;
+        optional<float> _alpha;
+        optional<float> _maxRange;
+        optional<float> _attenDist;
+    };
+
+} } // namespace osgEarth::Detail
+
+#endif // OSGEARTH_DRIVER_DETAIL_OPTIONS
+
diff --git a/src/osgEarthDrivers/detail/DetailPlugin.cpp b/src/osgEarthDrivers/detail/DetailPlugin.cpp
new file mode 100644
index 0000000..24bb90b
--- /dev/null
+++ b/src/osgEarthDrivers/detail/DetailPlugin.cpp
@@ -0,0 +1,56 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+ * Copyright 2016 Pelican Mapping
+ * http://osgearth.org
+ *
+ * osgEarth is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ */
+#include "DetailOptions"
+#include "DetailExtension"
+
+#include <osgDB/ReaderWriter>
+#include <osgDB/Registry>
+#include <osgDB/FileNameUtils>
+
+namespace osgEarth { namespace Detail
+{
+    /**
+     * Plugin entry point
+     */
+    class DetailPlugin : public osgDB::ReaderWriter
+    {
+    public: // Plugin stuff
+
+        DetailPlugin() {
+            supportsExtension( "osgearth_detail", "osgEarth Detail Texture Extension" );
+        }
+        
+        const char* className() const {
+            return "osgEarth Detail Texture Extension";
+        }
+
+        virtual ~DetailPlugin() { }
+
+        ReadResult readObject(const std::string& filename, const osgDB::Options* dbOptions) const
+        {
+          if ( !acceptsExtension(osgDB::getLowerCaseFileExtension(filename)) )
+                return ReadResult::FILE_NOT_HANDLED;
+
+          return ReadResult( new DetailExtension(Extension::getConfigOptions(dbOptions)) );
+        }
+    };
+
+    REGISTER_OSGPLUGIN(osgearth_detail, DetailPlugin)
+
+} } // namespace osgEarth::Detail
diff --git a/src/osgEarthDrivers/detail/DetailShaders b/src/osgEarthDrivers/detail/DetailShaders
new file mode 100644
index 0000000..d40b76d
--- /dev/null
+++ b/src/osgEarthDrivers/detail/DetailShaders
@@ -0,0 +1,39 @@
+// ***DO NOT EDIT THIS FILE - IT IS AUTOMATICALLY GENERATED BY CMAKE***
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+* Copyright 2008-2012 Pelican Mapping
+* http://osgearth.org
+*
+* osgEarth is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* 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.
+*
+* You should have received a copy of the GNU Lesser General Public License
+* along with this program.  If not, see <http://www.gnu.org/licenses/>
+*/
+#ifndef OSGEARTH_DETAIL_SHADERS
+#define OSGEARTH_DETAIL_SHADERS 1
+
+#include <osgEarth/ShaderLoader>
+
+namespace osgEarth { namespace Detail
+{
+    struct Shaders : public osgEarth::ShaderPackage
+	{
+        Shaders();
+        std::string VertexView;
+        std::string Fragment;
+	};
+	
+} } // namespace osgEarth/Detail
+
+#endif // OSGEARTH_BUMPMAP_SHADERS
\ No newline at end of file
diff --git a/src/osgEarthDrivers/detail/DetailShaders.cpp.in b/src/osgEarthDrivers/detail/DetailShaders.cpp.in
new file mode 100644
index 0000000..bb4f989
--- /dev/null
+++ b/src/osgEarthDrivers/detail/DetailShaders.cpp.in
@@ -0,0 +1,15 @@
+/** CMake Template File - compiled into AutoGenShaders.cpp */
+#include <osgEarthDrivers/detail/DetailShaders>
+
+#define MULTILINE(...) #__VA_ARGS__
+
+using namespace osgEarth::Detail;
+
+Shaders::Shaders()
+{
+    VertexView = "Detail.vert.view.glsl";
+    _sources[VertexView] = "@Detail.vert.view.glsl@";
+
+    Fragment = "Detail.frag.glsl";
+    _sources[Fragment] = "@Detail.frag.glsl@";
+};
diff --git a/src/osgEarthDrivers/detail/DetailTerrainEffect b/src/osgEarthDrivers/detail/DetailTerrainEffect
new file mode 100644
index 0000000..a3f1f3d
--- /dev/null
+++ b/src/osgEarthDrivers/detail/DetailTerrainEffect
@@ -0,0 +1,62 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+* Copyright 2008-2012 Pelican Mapping
+* http://osgearth.org
+*
+* osgEarth is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* 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.
+*
+* You should have received a copy of the GNU Lesser General Public License
+* along with this program.  If not, see <http://www.gnu.org/licenses/>
+*/
+#ifndef OSGEARTH_DETAIL_TERRAIN_EFFECT_H
+#define OSGEARTH_DETAIL_TERRAIN_EFFECT_H
+
+#include "DetailOptions"
+
+#include <osgEarth/TerrainEffect>
+#include <osg/Uniform>
+#include <osg/Texture2D>
+
+using namespace osgEarth;
+
+namespace osgEarth { namespace Detail
+{
+    /**
+     * Effect that activates a detail texture on the terrain.
+     */
+    class DetailTerrainEffect : public TerrainEffect
+    {
+    public:
+        DetailTerrainEffect(const DetailOptions& options);        
+
+
+    public: // TerrainEffect interface
+
+        void onInstall(TerrainEngineNode* engine);
+
+        void onUninstall(TerrainEngineNode* engine);
+
+
+    protected:
+        virtual ~DetailTerrainEffect() { }
+
+        DetailOptions                _options;
+        int                          _texImageUnit;
+        osg::ref_ptr<osg::Texture>   _tex;
+        osg::ref_ptr<osg::Uniform>   _samplerUniform;
+    };
+
+} } // namespace osgEarth::Detail
+
+#endif // OSGEARTH_DETAIL_TERRAIN_EFFECT_H
diff --git a/src/osgEarthDrivers/detail/DetailTerrainEffect.cpp b/src/osgEarthDrivers/detail/DetailTerrainEffect.cpp
new file mode 100644
index 0000000..e7c41b8
--- /dev/null
+++ b/src/osgEarthDrivers/detail/DetailTerrainEffect.cpp
@@ -0,0 +1,113 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+* Copyright 2008-2012 Pelican Mapping
+* http://osgearth.org
+*
+* osgEarth is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* 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.
+*
+* You should have received a copy of the GNU Lesser General Public License
+* along with this program.  If not, see <http://www.gnu.org/licenses/>
+*/
+#include "DetailTerrainEffect"
+#include "DetailShaders"
+
+#include <osgEarth/Registry>
+#include <osgEarth/Capabilities>
+#include <osgEarth/TerrainEngineNode>
+#include <osgEarth/ImageUtils>
+#include <osgEarthUtil/SimplexNoise>
+
+#define LC "[Detail] "
+
+#define SAMPLER_NAME "oe_detail_tex"
+
+using namespace osgEarth;
+using namespace osgEarth::Detail;
+
+DetailTerrainEffect::DetailTerrainEffect(const DetailOptions& options) :
+_options     ( options ),
+_texImageUnit( -1 )
+{
+}
+
+void
+DetailTerrainEffect::onInstall(TerrainEngineNode* engine)
+{
+    if ( engine )
+    {
+        // Load the image
+        osg::ref_ptr<osg::Image> image = _options.imageURI()->getImage();
+        if ( !image.valid() )
+        {
+            OE_WARN << LC << "Failed; unable to load detail map image from "
+                << _options.imageURI()->full() << "\n";
+            return;
+        }
+
+        // Create the texture
+        _tex = new osg::Texture2D(image.get());
+        _tex->setWrap(osg::Texture::WRAP_S, osg::Texture::REPEAT);
+        _tex->setWrap(osg::Texture::WRAP_T, osg::Texture::REPEAT);
+        _tex->setFilter(osg::Texture::MIN_FILTER, osg::Texture::LINEAR_MIPMAP_LINEAR);
+        _tex->setFilter(osg::Texture::MAG_FILTER, osg::Texture::LINEAR);
+        _tex->setMaxAnisotropy(1.0f);
+        _tex->setUnRefImageDataAfterApply(true);
+        _tex->setResizeNonPowerOfTwoHint(false);
+
+        engine->getResources()->reserveTextureImageUnit(_texImageUnit, "Detail");
+        if ( _texImageUnit >= 0 )
+        {   
+            // Create the uniform for the sampler.
+            osg::StateSet* stateset = engine->getOrCreateStateSet();
+            stateset->setTextureAttribute( _texImageUnit, _tex.get() );
+            stateset->addUniform( new osg::Uniform(SAMPLER_NAME, _texImageUnit) );
+            stateset->addUniform( new osg::Uniform("oe_detail_lod", (float)_options.lod().get()));
+            stateset->addUniform( new osg::Uniform("oe_detail_alpha", _options.alpha().get()));
+            stateset->addUniform( new osg::Uniform("oe_detail_maxRange", _options.maxRange().get()));
+            stateset->addUniform( new osg::Uniform("oe_detail_attenDist", _options.attenDist().get()));
+
+            // configure shaders
+            VirtualProgram* vp = VirtualProgram::getOrCreate(stateset);
+
+            Shaders package;            
+
+            package.load( vp, package.VertexView );
+            package.load( vp, package.Fragment );           
+            
+            OE_INFO << LC << "Detail texture installed!\n";
+        }
+        else
+        {
+            OE_WARN << LC << "No texture image units available; detail disabled.\n";
+        }
+    }
+}
+
+
+void
+DetailTerrainEffect::onUninstall(TerrainEngineNode* engine)
+{
+    if ( engine && _texImageUnit >= 0 )
+    {
+        osg::StateSet* stateset = engine->getStateSet();
+        if ( stateset )
+        {
+            stateset->removeUniform( SAMPLER_NAME );
+            stateset->removeTextureAttribute( _texImageUnit, _tex.get() );
+        }
+
+        engine->getResources()->releaseTextureImageUnit( _texImageUnit );
+        _texImageUnit = -1;
+    }
+}
\ No newline at end of file
diff --git a/src/osgEarthDrivers/earth/CMakeLists.txt b/src/osgEarthDrivers/earth/CMakeLists.txt
index e7fca8c..79fb5f6 100644
--- a/src/osgEarthDrivers/earth/CMakeLists.txt
+++ b/src/osgEarthDrivers/earth/CMakeLists.txt
@@ -2,7 +2,9 @@ OPTION(CURL_IS_STATIC "on if curl is a static lib " ON)
 MARK_AS_ADVANCED(CURL_IS_STATIC)
 
 IF(WIN32)
-    SET(CMAKE_SHARED_LINKER_FLAGS_DEBUG "${CMAKE_SHARED_LINKER_FLAGS_DEBUG} /NODEFAULTLIB:MSVCRT")
+    IF(MSVC)
+        SET(CMAKE_SHARED_LINKER_FLAGS_DEBUG "${CMAKE_SHARED_LINKER_FLAGS_DEBUG} /NODEFAULTLIB:MSVCRT")
+    ENDIF(MSVC)
     IF(CURL_IS_STATIC)
         ADD_DEFINITIONS(-DCURL_STATICLIB)
         SET(TARGET_EXTERNAL_LIBRARIES ws2_32 winmm)
diff --git a/src/osgEarthDrivers/earth/EarthFileSerializer b/src/osgEarthDrivers/earth/EarthFileSerializer
index a8f6453..8f1decf 100644
--- a/src/osgEarthDrivers/earth/EarthFileSerializer
+++ b/src/osgEarthDrivers/earth/EarthFileSerializer
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -29,15 +29,50 @@ namespace osgEarth_osgearth
     class EarthFileSerializer1
     {
     public:
-        MapNode* deserialize( const Config& conf, const std::string& referenceURI ) const;
+        MapNode* deserialize( const Config& conf, const std::string& referrer ) const;
     };
 
     class EarthFileSerializer2
     {
     public:
-        MapNode* deserialize( const Config& conf, const std::string& referenceURI ) const;
+        EarthFileSerializer2();
 
-        Config serialize( MapNode* mapNode ) const;
+        /**
+         * Relative pathnames in the earth file are relative to the earth file itself.
+         * When storing a MapNode, the serializer will rewrite those relative paths
+         * so they are relative to the new save location.
+         *
+         * Set this to false to disable this feature.
+         */
+        void setRewritePaths(bool value) { _rewritePaths = value; }
+
+        /**
+         * By default, when rewriting paths (see above), absolute paths in the earth
+         * file will be skipped (not rewritten). Set this to true to tell the 
+         * serializer to attempt to re-write absolute paths and make then relative
+         * to the new save location.
+         */
+        void setRewriteAbsolutePaths(bool value) { _rewriteAbsolutePaths = value; }
+
+    public:
+        /**
+         * Parse data in a Config structure into a new MapNode.
+         * referrer = the location from which the Config was created; typically this
+         * is the pathname of the .earth file.
+         */
+        osg::Node* deserialize( const Config& conf, const std::string& referrer ) const;
+        
+        /**
+         * Create a Config structure representing a MapNode.
+         * referrer = the location to which the Config will be stored, typically this
+         * is the pathname of the .earth file.
+         */
+        Config serialize( const MapNode* mapNode, const std::string& referrer ) const;
+
+    private:
+
+        bool _rewritePaths;
+        bool _rewriteAbsolutePaths;
     };
 
 } // namespace osgEarth_osgearth
diff --git a/src/osgEarthDrivers/earth/EarthFileSerializer1.cpp b/src/osgEarthDrivers/earth/EarthFileSerializer1.cpp
index 58f5d04..2b98192 100644
--- a/src/osgEarthDrivers/earth/EarthFileSerializer1.cpp
+++ b/src/osgEarthDrivers/earth/EarthFileSerializer1.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthDrivers/earth/EarthFileSerializer2.cpp b/src/osgEarthDrivers/earth/EarthFileSerializer2.cpp
index f08cb9a..8e78184 100644
--- a/src/osgEarthDrivers/earth/EarthFileSerializer2.cpp
+++ b/src/osgEarthDrivers/earth/EarthFileSerializer2.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -20,138 +20,483 @@
 #include <osgEarth/FileUtils>
 #include <osgEarth/MapFrame>
 #include <osgEarth/Extension>
+#include <osgEarth/StringUtils>
+#include <osgEarth/FileUtils>
+#include <osgDB/FileUtils>
+#include <osgDB/FileNameUtils>
+#include <stdio.h>
+#include <ctype.h>
 
 using namespace osgEarth_osgearth;
 using namespace osgEarth;
 
-MapNode*
-EarthFileSerializer2::deserialize( const Config& conf, const std::string& referenceURI ) const
+#undef  LC
+#define LC "[EarthSerializer2] "
+
+static const char * const PATH_SEPARATORS = "/\\";
+static unsigned int PATH_SEPARATORS_LEN = 2;
+
+namespace
 {
-    MapOptions mapOptions( conf.child( "options" ) );
 
-    // legacy: check for name/type in top-level attrs:
-    if ( conf.hasValue( "name" ) || conf.hasValue( "type" ) )
+	class PathIterator
     {
-        Config legacy;
-        if ( conf.hasValue("name") ) legacy.add( "name", conf.value("name") );
-        if ( conf.hasValue("type") ) legacy.add( "type", conf.value("type") );
-        mapOptions.mergeConfig( legacy );
+		public:
+			PathIterator(const std::string & v);
+			bool valid() const { return start!=end; }
+			PathIterator & operator++();
+			std::string operator*();
+
+		protected:
+			std::string::const_iterator end;     ///< End of path string
+			std::string::const_iterator start;   ///< Points to the first char of an element, or ==end() if no more
+			std::string::const_iterator stop;    ///< Points to the separator after 'start', or ==end()
+
+			/// Iterate until 'it' points to something different from a separator
+			std::string::const_iterator skipSeparators(std::string::const_iterator it);
+			std::string::const_iterator next(std::string::const_iterator it);
+    };
+
+	PathIterator::PathIterator(const std::string & v) : end(v.end()), start(v.begin()), stop(v.begin()) { operator++(); }
+
+	PathIterator & PathIterator::operator++()
+	{
+		if (!valid()) return *this;
+			start = skipSeparators(stop);
+		if (start != end) stop = next(start);
+		return *this;
+	}
+	std::string PathIterator::operator*()
+	{
+		if (!valid()) return std::string();
+		return std::string(start, stop);
+	}
+
+	std::string::const_iterator PathIterator::skipSeparators(std::string::const_iterator it)
+	{
+		for (; it!=end && std::find_first_of(it, it+1, PATH_SEPARATORS, PATH_SEPARATORS+PATH_SEPARATORS_LEN) != it+1; ++it) {}
+		return it;
+	}
+
+	std::string::const_iterator PathIterator::next(std::string::const_iterator it)
+	{
+		return std::find_first_of(it, end, PATH_SEPARATORS, PATH_SEPARATORS+PATH_SEPARATORS_LEN);
+	}
+
+    bool isReservedWord(const std::string& k)
+    {
+        return
+            k == "options" ||
+            k == "image" ||
+            k == "elevation" ||
+            k == "heightfield" ||
+            k == "model" ||
+            k == "mask" ||
+            k == "external" ||
+            k == "extensions";
     }
 
-    Map* map = new Map( mapOptions );
+    /**
+     * Looks at each key in a Config and tries to match that key to a shared library name;
+     * loads the shared library associated with the name. This will "pre-load" all the DLLs
+     * associated with extensions in the earth file even if they weren't linked.
+     *
+     * Will also pre-load any expressly indicated shared libraries in the "libraries" element.
+     */
+    void preloadExtensionLibs(const Config& conf)
+    {
+        for(ConfigSet::const_iterator i = conf.children().begin(); i != conf.children().end(); ++i)
+        {
+            const std::string& name = i->key();
 
-    // Yes, MapOptions and MapNodeOptions share the same Config node. Weird but true.
-    MapNodeOptions mapNodeOptions( conf.child( "options" ) );
+            if ( isReservedWord(name) )
+                continue;
 
-    // Read the layers in LAST (otherwise they will not benefit from the cache/profile configuration)
+            if ( !name.empty() )
+            {
+                // Load the extension library if necessary.
+                std::string libName = osgDB::Registry::instance()->createLibraryNameForExtension("osgearth_" + name);
+                osgDB::Registry::LoadStatus status = osgDB::Registry::instance()->loadLibrary(libName);
+                if ( status == osgDB::Registry::LOADED )
+                {
+                    OE_INFO << LC << "Loaded extension lib \"" << libName << "\"\n";
+                }
+                else
+                {
+                    // If it failed to load, try loading an extension from an osgEarth library with the same name.
+                    // Capitalize the name of the extension,.
+                    std::string capName = name;
+                    capName[0] = ::toupper(capName[0]);
+                    std::stringstream buf;
+                    buf << "osgEarth" << capName;
+                    libName = osgDB::Registry::instance()->createLibraryNameForNodeKit(buf.str());
+                    status = osgDB::Registry::instance()->loadLibrary(libName);
+                    if (status == osgDB::Registry::LOADED)
+                    {
+                        OE_INFO << LC << "Loaded extension lib \"" << libName << "\"\n";
+                    }
+                }
+            }
+        }
 
-    // Image layers:
-    ConfigSet images = conf.children( "image" );
-    for( ConfigSet::const_iterator i = images.begin(); i != images.end(); i++ )
+        // Preload any libraries
+        Config libraries = conf.child("libraries");
+        if (!libraries.value().empty())
+        {
+            StringTokenizer izer( ";" );
+            StringVector libs;
+            izer.tokenize( libraries.value(), libs );
+            for (StringVector::iterator itr = libs.begin(); itr != libs.end(); ++itr)
+            {
+                std::string lib = *itr;
+                trim2(lib);
+                std::string libName = osgDB::Registry::instance()->createLibraryNameForNodeKit(lib);
+                osgDB::Registry::LoadStatus status = osgDB::Registry::instance()->loadLibrary(libName);
+                if (status == osgDB::Registry::LOADED)
+                {
+                    OE_INFO << LC << "Loaded library \"" << libName << "\"\n";
+                }
+                else
+                {
+                    OE_WARN << LC << "Failed to load library \"" << libName << "\"\n";
+                }
+            }
+        }        
+    }
+
+    /**
+     * Visits a Config hierarchy and rewrites relative pathnames to be relative to a new referrer.
+     */
+    struct RewritePaths
     {
-        Config layerDriverConf = *i;        
+        bool        _rewriteAbsolutePaths;
+        std::string _newReferrerAbsPath;
+        std::string _newReferrerFolder;
 
-        ImageLayerOptions layerOpt( layerDriverConf );
-        layerOpt.name() = layerDriverConf.value("name");
-        //layerOpt.driver() = TileSourceOptions( layerDriverConf );
+        RewritePaths(const std::string& referrer)
+        {
+            _rewriteAbsolutePaths = false;
+            _newReferrerAbsPath = osgDB::convertFileNameToUnixStyle( osgDB::getRealPath(referrer) );
+            _newReferrerFolder  = osgDB::getFilePath( osgDB::findDataFile(_newReferrerAbsPath) );
+        }
 
-        map->addImageLayer( new ImageLayer(layerOpt) );
-    }
+        /** Whether to make absolute paths into relative paths if possible */
+        void setRewriteAbsolutePaths(bool value)
+        {
+            _rewriteAbsolutePaths = value;
+        }
 
-    // Elevation layers:
-    for( int k=0; k<2; ++k )
-    {
-        std::string tagName = k == 0 ? "elevation" : "heightfield"; // support both :)
+        bool isLocation(const Config& input) const
+        {
+            if ( input.value().empty() )
+                return false;
+
+            if ( input.referrer().empty() )
+                return false;
+
+            return 
+                input.key() == "url"      ||
+                input.key() == "uri"      ||
+                input.key() == "href"     ||
+                input.key() == "filename" ||
+                input.key() == "file"     ||
+                input.key() == "pathname" ||
+                input.key() == "path";
+        }
 
-        ConfigSet heightfields = conf.children( tagName );
-        for( ConfigSet::const_iterator i = heightfields.begin(); i != heightfields.end(); i++ )
+        void apply(Config& input)
         {
-            Config layerDriverConf = *i;            
+            if ( isLocation(input) )
+            {
+                // resolve the absolute path of the input:
+                URI inputURI( input.value(), URIContext(input.referrer()) );
+
+                std::string newValue = resolve(inputURI);
+                if ( newValue != input.value() )
+                {
+                    input.value() = newValue;
+                    input.setReferrer( _newReferrerAbsPath );
+                }
+
+                if ( !input.externalRef().empty() )
+                {
+                    URI xrefURI( input.externalRef(), URIContext(input.referrer()) );
+                    std::string newXRef = resolve(xrefURI);
+                    if ( newXRef != input.externalRef() )
+                    {
+                        input.setExternalRef( newXRef );
+                        input.setReferrer( _newReferrerAbsPath );
+                    }
+                }
+            }
 
-            ElevationLayerOptions layerOpt( layerDriverConf );
-            layerOpt.name() = layerDriverConf.value( "name" );
+            for(ConfigSet::iterator i = input.children().begin(); i != input.children().end(); ++i)
+            {
+                apply( *i );
+            }
+        }
 
-            map->addElevationLayer( new ElevationLayer(layerOpt) );
+        std::string resolve(const URI& inputURI )
+        {
+            std::string inputAbsPath = osgDB::convertFileNameToUnixStyle( inputURI.full() );
+
+            // if the abs paths have different roots, no resolution; use the input.
+            if (osgDB::getPathRoot(inputAbsPath) != osgDB::getPathRoot(_newReferrerFolder))
+            {
+                return inputURI.full();
+            }
+
+            // see whether the file exists (this is how we verify that it's actually a path)
+            //if ( osgDB::fileExists(inputAbsPath) )
+            {
+                if ( !osgDB::isAbsolutePath(inputURI.base()) || _rewriteAbsolutePaths )
+                {
+                    std::string inputNewRelPath = getPathRelative( _newReferrerFolder, inputAbsPath );
+                    
+                    //OE_DEBUG << LC << "\n"
+                    //    "   Rewriting \"" << input.value() << "\" as \"" << inputNewRelPath << "\"\n"
+                    //    "   Absolute = " << inputAbsPath << "\n"
+                    //    "   ReferrerFolder = " << _newReferrerFolder << "\n";
+
+                    return inputNewRelPath;
+                }
+            }
+
+            return inputURI.base();
         }
+
+		std::string getPathRelative(const std::string& from, const std::string& to)
+		{
+			// This implementation is not 100% robust, and should be replaced with C++0x "std::path" as soon as possible.
+
+			// Definition: an "element" is a part between slashes. Ex: "/a/b" has two elements ("a" and "b").
+			// Algorithm:
+			// 1. If paths are neither both absolute nor both relative, then we cannot do anything (we need to make them absolute, but need additionnal info on how to make it). Return.
+			// 2. If both paths are absolute and root isn't the same (for Windows only, as roots are of the type "C:", "D:"), then the operation is impossible. Return.
+			// 3. Iterate over two paths elements until elements are equal
+			// 4. For each remaining element in "from", add ".." to result
+			// 5. For each remaining element in "to", add this element to result
+
+			// 1 & 2
+			const std::string root = osgDB::getPathRoot(from);
+			if (root != osgDB::getPathRoot(to)) {
+				OSG_INFO << "Cannot relativise paths. From=" << from << ", To=" << to << ". Returning 'to' unchanged." << std::endl;
+				//return to;
+				return osgDB::getSimpleFileName(to);
+			}
+
+			// 3
+			PathIterator itFrom(from), itTo(to);
+			// Iterators may point to Windows roots. As we tested they are equal, there is no need to ++itFrom and ++itTo.
+			// However, if we got an Unix root, we must add it to the result.
+			// std::string res(root == "/" ? "/" : "");
+			// Since result is a relative path, even in unix, no need to add / to the result first.
+			std::string res = "";
+			for(; itFrom.valid() && itTo.valid() && *itFrom==*itTo; ++itFrom, ++itTo) {}
+
+			// 4
+			for(; itFrom.valid(); ++itFrom) res += "../";
+
+			// 5
+			for(; itTo.valid(); ++itTo) res += *itTo + "/";
+
+			// Remove trailing slash before returning
+			if (!res.empty() && std::find_first_of(res.rbegin(), res.rbegin()+1, PATH_SEPARATORS, PATH_SEPARATORS+PATH_SEPARATORS_LEN) != res.rbegin()+1)
+			{
+				return res.substr(0, res.length()-1);
+			}
+			return res;
+			}
+    };
+}
+
+//............................................................................
+
+namespace
+{
+    void addImageLayer(const Config& conf, Map* map)
+    {
+        ImageLayerOptions options( conf );
+        options.name() = conf.value("name");
+        ImageLayer* layer = new ImageLayer(options);
+        map->addImageLayer(layer);
+        if (layer->getStatus().isError())
+            OE_WARN << LC << "Layer \"" << layer->getName() << "\" : " << layer->getStatus().toString() << std::endl;
     }
 
-    // Model layers:
-    ConfigSet models = conf.children( "model" );
-    for( ConfigSet::const_iterator i = models.begin(); i != models.end(); i++ )
+    void addElevationLayer(const Config& conf, Map* map)
     {
-        const Config& layerDriverConf = *i;
+        ElevationLayerOptions options( conf );
+        options.name() = conf.value( "name" );
+        ElevationLayer* layer = new ElevationLayer(options);
+        map->addElevationLayer(layer);
+        if (layer->getStatus().isError())
+            OE_WARN << LC << "Layer \"" << layer->getName() << "\" : " << layer->getStatus().toString() << std::endl;
+    }
 
-        ModelLayerOptions layerOpt( layerDriverConf );
-        layerOpt.name() = layerDriverConf.value( "name" );
-        layerOpt.driver() = ModelSourceOptions( layerDriverConf );
+    void addModelLayer(const Config& conf, Map* map)
+    {
+        ModelLayerOptions options( conf );
+        options.name() = conf.value( "name" );
+        options.driver() = ModelSourceOptions( conf );
+        ModelLayer* layer = new ModelLayer(options);
+        map->addModelLayer(layer);
+        if (layer->getStatus().isError())
+            OE_WARN << LC << "Layer \"" << layer->getName() << "\" : " << layer->getStatus().toString() << std::endl;
+    }
 
-        map->addModelLayer( new ModelLayer(layerOpt) );
+    void addMaskLayer(const Config& conf, Map* map)
+    {
+        MaskLayerOptions options(conf);
+        options.name() = conf.value( "name" );
+        options.driver() = MaskSourceOptions(options);
+        MaskLayer* layer = new MaskLayer(options);
+        map->addTerrainMaskLayer(layer);
+        if (layer->getStatus().isError())
+            OE_WARN << LC << "Layer \"" << layer->getName() << "\" : " << layer->getStatus().toString() << std::endl;
     }
 
-    // Mask layer:
-    ConfigSet masks = conf.children( "mask" );
-    for( ConfigSet::const_iterator i = masks.begin(); i != masks.end(); i++ )
+    // support for "special" extension names (convenience and backwards compat)
+    Extension* createSpecialExtension(const Config& conf, MapNode* mapNode)
     {
-        Config maskLayerConf = *i;
+        // special support for the default sky extension:
+        if (conf.key() == "sky" && !conf.hasValue("driver"))
+            return Extension::create("sky_simple", conf);
 
-        MaskLayerOptions options(maskLayerConf);
-        options.name() = maskLayerConf.value( "name" );
-        options.driver() = MaskSourceOptions(options);
+        if (conf.key() == "ocean" && !conf.hasValue("driver"))
+            return Extension::create("ocean_simple", conf);
+
+        return 0L;
+    }
+
+    void addExtension(const Config& conf, MapNode* mapNode)
+    {
+        std::string name = conf.key();
+        Extension* extension = Extension::create( conf.key(), conf );
+        if ( !extension )
+        {
+            name = conf.key() + "_" + conf.value("driver");
+            extension = Extension::create(name, conf);
 
-        map->addTerrainMaskLayer( new MaskLayer(options) );
+            if (!extension)
+                extension = createSpecialExtension(conf, mapNode);
+        }
+
+        if (extension)
+        {
+            mapNode->addExtension(extension);
+        }
+        else
+        {            
+            OE_INFO << LC << "Failed to find an extension for \"" << name << "\"\n";
+        }
     }
+}
+
+EarthFileSerializer2::EarthFileSerializer2() :
+_rewritePaths        ( true ),
+_rewriteAbsolutePaths( false )
+{
+    // nop
+}
+
+
+osg::Node*
+EarthFileSerializer2::deserialize( const Config& conf, const std::string& referrer ) const
+{
+    // First, pre-load any extension DLLs.
+    preloadExtensionLibs(conf);
+    preloadExtensionLibs(conf.child("extensions"));
+    preloadExtensionLibs(conf.child("external"));
+
+    MapOptions mapOptions( conf.child( "options" ) );
 
-    
-    //Add any addition paths specified in the options/osg_file_paths element to the file path.  Useful for pointing osgEarth at resource folders.
-    Config osg_file_paths = conf.child( "options" ).child("osg_file_paths");
-    ConfigSet urls = osg_file_paths.children("url");
-    for (ConfigSet::const_iterator i = urls.begin(); i != urls.end(); i++) 
+    // legacy: check for name/type in top-level attrs:
+    if ( conf.hasValue( "name" ) || conf.hasValue( "type" ) )
     {
-        std::string path = osgEarth::getFullPath( referenceURI, (*i).value());
-        OE_DEBUG << "Adding OSG file path " << path << std::endl;
-        osgDB::Registry::instance()->getDataFilePathList().push_back( path );
+        Config legacy;
+        if ( conf.hasValue("name") ) legacy.add( "name", conf.value("name") );
+        if ( conf.hasValue("type") ) legacy.add( "type", conf.value("type") );
+        mapOptions.mergeConfig( legacy );
     }
 
+    Map* map = new Map( mapOptions );
+
+    // Yes, MapOptions and MapNodeOptions share the same Config node. Weird but true.
+    MapNodeOptions mapNodeOptions( conf.child( "options" ) );
+
+    // Create a map node.
     osg::ref_ptr<MapNode> mapNode = new MapNode( map, mapNodeOptions );
 
-    // External configs. Support both "external" and "extensions" tags.
+    // Read all the elevation layers in FIRST so other layers can access them for things like clamping.
+    for(ConfigSet::const_iterator i = conf.children().begin(); i != conf.children().end(); ++i)
+    {
+        if ( i->key() == "elevation" || i->key() == "heightfield" )
+        {
+            addElevationLayer( *i, map );
+        }
+    }
 
-    Config ext = conf.child( "external" );
-    if ( ext.empty() )
-        ext = conf.child( "extensions" );
 
-    if ( !ext.empty() )
+    // Read the layers in LAST (otherwise they will not benefit from the cache/profile configuration)
+    for(ConfigSet::const_iterator i = conf.children().begin(); i != conf.children().end(); ++i)
     {
-        // save the configuration in case we need to write it back out later
-        mapNode->externalConfig() = ext;
+        if (i->key() == "options" || i->key() == "name" || i->key() == "type" || i->key() == "version")
+        {
+            // nop - handled earlier
+        }
 
-        // locate and install any registered extensions.
-        ConfigSet extensions = ext.children();
-        for(ConfigSet::const_iterator i = extensions.begin(); i != extensions.end(); ++i)
+        else if ( i->key() == "image" )
         {
-            std::string name = i->key();
-            Extension* extension = Extension::create( name, *i );
-            if ( extension )
+            addImageLayer( *i, map );
+        }
+
+        else if ( i->key() == "model" )
+        {
+            addModelLayer( *i, map );
+        }
+
+        else if ( i->key() == "mask" )
+        {
+            addMaskLayer( *i, map );
+        }
+
+        else if ( i->key() == "external" || i->key() == "extensions" )
+        {
+            mapNode->externalConfig() = *i;
+            for(ConfigSet::const_iterator e = i->children().begin(); e != i->children().end(); ++e)
             {
-                mapNode->addExtension( extension );
+                addExtension( *e, mapNode.get() );
             }
         }
+
+        else if ( !isReservedWord(i->key()) ) // plugins/extensions.
+        {
+            addExtension( *i, mapNode.get() );
+        }
     }
 
-    return mapNode.release();
+    // return the topmost parent of the mapnode. It's possible that
+    // an extension added parents!
+    osg::Node* top = mapNode.release();
+
+    while( top->getNumParents() > 0 )
+        top = top->getParent(0);
+
+    return top;
 }
 
 
 Config
-EarthFileSerializer2::serialize( MapNode* input ) const
+EarthFileSerializer2::serialize(const MapNode* input, const std::string& referrer) const
 {
     Config mapConf("map");
     mapConf.set("version", "2");
 
     if ( !input || !input->getMap() )
-        return mapConf;
+        return mapConf; 
 
-    Map* map = input->getMap();
+    const Map* map = input->getMap();
     MapFrame mapf( map, Map::ENTIRE_MODEL );
 
     // the map and node options:
@@ -189,6 +534,17 @@ EarthFileSerializer2::serialize( MapNode* input ) const
         mapConf.add( "model", layerConf );
     }
 
+    typedef std::vector< osg::ref_ptr<Extension> > Extensions;
+    for(Extensions::const_iterator i = input->getExtensions().begin(); i != input->getExtensions().end(); ++i)
+    {
+        Extension* e = i->get();
+        Config conf = e->getConfigOptions().getConfig();
+        if ( !conf.key().empty() )
+        {
+            mapConf.add( conf );
+        }
+    }
+
     Config ext = input->externalConfig();
     if ( !ext.empty() )
     {
@@ -196,5 +552,13 @@ EarthFileSerializer2::serialize( MapNode* input ) const
         mapConf.add( ext );
     }
 
+    // Re-write pathnames in the Config so they are relative to the new referrer.
+    if ( _rewritePaths && !referrer.empty() )
+    {
+        RewritePaths rewritePaths( referrer );
+        rewritePaths.setRewriteAbsolutePaths( _rewriteAbsolutePaths );
+        rewritePaths.apply( mapConf );
+    }
+
     return mapConf;
 }
diff --git a/src/osgEarthDrivers/earth/ReaderWriterOsgEarth.cpp b/src/osgEarthDrivers/earth/ReaderWriterOsgEarth.cpp
index c1e3bbc..7644661 100644
--- a/src/osgEarthDrivers/earth/ReaderWriterOsgEarth.cpp
+++ b/src/osgEarthDrivers/earth/ReaderWriterOsgEarth.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -31,7 +31,7 @@
 using namespace osgEarth_osgearth;
 using namespace osgEarth;
 
-#define LC "[ReaderWriterEarth] "
+#define LC "[Earth Plugin] "
 
 // Macros to determine the filename for dependent libs.
 #define Q2(x) #x
@@ -57,6 +57,18 @@ using namespace osgEarth;
 #   endif
 #endif
 
+
+// OSG OPTIONS
+
+// By default the writer will re-write relative pathnames so they are relative to the new
+// save location. This option will disable that.
+#define EARTH_DO_NOT_REWRITE_PATHS   "DoNotRewritePaths"
+
+// By default the writer will skip absolute paths and leave them as-is. This option will
+// cause the writer to try making absolute paths relative to the new save location.
+#define EARTH_REWRITE_ABSOLUTE_PATHS "RewriteAbsolutePaths"
+
+
 namespace
 {
     void recursiveUniqueKeyMerge(Config& lhs, const Config& rhs)
@@ -90,7 +102,7 @@ class ReaderWriterEarth : public osgDB::ReaderWriter
             osgDB::Registry::instance()->loadLibrary( LIBNAME_UTIL LIBNAME_UTIL_POSTFIX LIBNAME_UTIL_EXTENSION );
         }
 
-        virtual const char* className()
+        virtual const char* className() const
         {
             return "OSG Earth ReaderWriter";
         }
@@ -117,7 +129,12 @@ class ReaderWriterEarth : public osgDB::ReaderWriter
 
             std::ofstream out( fileName.c_str());
             if ( out.is_open() )
-                return writeNode( node, out, options );
+            {
+                osg::ref_ptr<osgDB::Options> myOptions = Registry::instance()->cloneOrCreateOptions(options);
+                URIContext( fileName ).store( myOptions.get() );
+
+                return writeNode( node, out, myOptions.get() );
+            }
 
             return WriteResult::ERROR_IN_WRITING_FILE;            
         }
@@ -128,10 +145,32 @@ class ReaderWriterEarth : public osgDB::ReaderWriter
             MapNode* mapNode = MapNode::findMapNode( searchNode );
             if ( !mapNode )
                 return WriteResult::ERROR_IN_WRITING_FILE; // i.e., no MapNode found in the graph.
+            
+            // decode the context from the options (might be there, might not)
+            URIContext uriContext( options );
 
             // serialize the map node to a generic Config object:
             EarthFileSerializer2 ser;
-            Config conf = ser.serialize( mapNode );
+
+            // check for writer options
+            if ( options )
+            {
+                std::string ostr = osgEarth::toLower(options->getOptionString());
+
+                if ( ostr.find(toLower(EARTH_DO_NOT_REWRITE_PATHS)) != std::string::npos )
+                {
+                    OE_INFO << LC << "path re-writing disabled\n";
+                    ser.setRewritePaths( false );
+                }
+
+                if ( ostr.find(toLower(EARTH_REWRITE_ABSOLUTE_PATHS)) != std::string::npos )
+                {
+                    OE_INFO << LC << "absolute path re-writing enabled\n";
+                    ser.setRewriteAbsolutePaths( true );
+                }
+            }
+
+            Config conf = ser.serialize( mapNode, uriContext.referrer() );
 
             // dump that Config out as XML.
             osg::ref_ptr<XmlDocument> xml = new XmlDocument( conf );
@@ -140,7 +179,7 @@ class ReaderWriterEarth : public osgDB::ReaderWriter
             return WriteResult::FILE_SAVED;
         }
 
-        virtual ReadResult readNode(const std::string& fileName, const osgDB::Options* options) const
+        virtual ReadResult readNode(const std::string& fileName, const osgDB::Options* readOptions) const
         {
             std::string ext = osgDB::getFileExtension( fileName );
             if ( !acceptsExtension( ext ) )
@@ -152,7 +191,7 @@ class ReaderWriterEarth : public osgDB::ReaderWriter
             // osgDB::readNodeFile("server:http://myserver/myearth.earth").  This should only be
             // necessary for the first level as the other files will have a tilekey prepended to them.
             if ((fileName.length() > 7) && (fileName.substr(0, 7) == "server:"))
-                return readNode(fileName.substr(7), options);            
+                return readNode(fileName.substr(7), readOptions);            
 
             if ( fileName == "__globe.earth" )
             {
@@ -164,30 +203,30 @@ class ReaderWriterEarth : public osgDB::ReaderWriter
                 std::string fullFileName = fileName;
                 if ( !osgDB::containsServerAddress( fileName ) )
                 {
-                    fullFileName = osgDB::findDataFile( fileName, options );
+                    fullFileName = osgDB::findDataFile( fileName, readOptions );
                     if (fullFileName.empty()) return ReadResult::FILE_NOT_FOUND;
                 }
 
-                osgEarth::ReadResult r = URI(fullFileName).readString( options );
+                osgEarth::ReadResult r = URI(fullFileName).readString( readOptions );
                 if ( r.failed() )
                     return ReadResult::ERROR_IN_READING_FILE;
 
                 // Since we're now passing off control to the stream, we have to pass along the
                 // reference URI as well..
-                osg::ref_ptr<osgDB::Options> myOptions = Registry::instance()->cloneOrCreateOptions(options);
+                osg::ref_ptr<osgDB::Options> myReadOptions = Registry::instance()->cloneOrCreateOptions(readOptions);
 
-                URIContext( fullFileName ).apply( myOptions.get() );
+                URIContext( fullFileName ).store( myReadOptions.get() );
 
                 std::stringstream in( r.getString() );
-                return readNode( in, myOptions.get() );
+                return readNode( in, myReadOptions.get() );
             }
         }
 
-        virtual ReadResult readNode(std::istream& in, const osgDB::Options* options ) const
+        virtual ReadResult readNode(std::istream& in, const osgDB::Options* readOptions) const
         {
             // pull the URI context from the options structure (since we're reading
             // from an "anonymous" stream here)
-            URIContext uriContext( options ); 
+            URIContext uriContext( readOptions ); 
 
             osg::ref_ptr<XmlDocument> doc = XmlDocument::load( in, uriContext );
             if ( !doc.valid() )
@@ -202,7 +241,8 @@ class ReaderWriterEarth : public osgDB::ReaderWriter
             else if ( docConf.hasChild( "earth" ) )
                 conf = docConf.child( "earth" );
 
-            MapNode* mapNode =0L;
+            osg::ref_ptr<osg::Node> node;
+
             if ( !conf.empty() )
             {
                 // see if we were given a reference URI to use:
@@ -212,7 +252,7 @@ class ReaderWriterEarth : public osgDB::ReaderWriter
                 {
                     OE_INFO << LC << "Detected a version 1.x earth file" << std::endl;
                     EarthFileSerializer1 ser;
-                    mapNode = ser.deserialize( conf, refURI );
+                    node = ser.deserialize( conf, refURI );
                 }
 
                 else
@@ -222,9 +262,9 @@ class ReaderWriterEarth : public osgDB::ReaderWriter
 
                     // attempt to parse a "default options" JSON string:
                     std::string defaultConfStr;
-                    if ( options )
+                    if ( readOptions )
                     {
-                        defaultConfStr = options->getPluginStringData("osgEarth.defaultOptions");
+                        defaultConfStr = readOptions->getPluginStringData("osgEarth.defaultOptions");
                         if ( !defaultConfStr.empty() )
                         {
                             Config optionsConf("options");
@@ -246,11 +286,23 @@ class ReaderWriterEarth : public osgDB::ReaderWriter
                     }
 
                     EarthFileSerializer2 ser;
-                    mapNode = ser.deserialize( conf, refURI );
+                    node = ser.deserialize( conf, refURI );
+                }
+            }
+
+            MapNode* mapNode = MapNode::get(node.get());
+            if (mapNode)
+            {
+                // If the user passed in a cache object, apply it to the map now
+                CacheSettings* cacheSettings = CacheSettings::get(readOptions);
+                if (cacheSettings && cacheSettings->getCache())
+                {
+                    mapNode->getMap()->setCache( cacheSettings->getCache() );
+                    OE_INFO << LC << "Applied user-supplied cache to the Map\n";
                 }
             }
 
-            return ReadResult(mapNode);
+            return ReadResult(node.get());
         }
 };
 
diff --git a/src/osgEarthDrivers/engine_byo/BYOTerrainEngineDriver.cpp b/src/osgEarthDrivers/engine_byo/BYOTerrainEngineDriver.cpp
index 61bdaa9..8356a91 100644
--- a/src/osgEarthDrivers/engine_byo/BYOTerrainEngineDriver.cpp
+++ b/src/osgEarthDrivers/engine_byo/BYOTerrainEngineDriver.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -33,7 +33,7 @@ class osgEarth_BYOTerrainEngineDriver : public osgDB::ReaderWriter
 public:
     osgEarth_BYOTerrainEngineDriver() {}
 
-    virtual const char* className()
+    virtual const char* className() const
     {
         return "osgEarth BYO Terrain Engine";
     }
diff --git a/src/osgEarthDrivers/engine_byo/BYOTerrainEngineNode b/src/osgEarthDrivers/engine_byo/BYOTerrainEngineNode
index d5d1ed3..b31433c 100644
--- a/src/osgEarthDrivers/engine_byo/BYOTerrainEngineNode
+++ b/src/osgEarthDrivers/engine_byo/BYOTerrainEngineNode
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -35,6 +35,8 @@ namespace osgEarth_engine_byo
 
     public: // TerrainEngineNode
 
+        UID getUID() const { return _uid; }
+
         // for standalone tile creation outside of a terrain
         osg::Node* createTile(const TileKey& key) { return 0L; }
 
@@ -46,6 +48,8 @@ namespace osgEarth_engine_byo
     private:
         osgEarth::Drivers::BYOTerrainEngineOptions _terrainOptions;
         BYOTerrainEngineNode( const BYOTerrainEngineNode& rhs, const osg::CopyOp& op =osg::CopyOp::DEEP_COPY_ALL ) { }
+
+        UID _uid;
     };
 
 } // namespace osgEarth_engine_byo
diff --git a/src/osgEarthDrivers/engine_byo/BYOTerrainEngineNode.cpp b/src/osgEarthDrivers/engine_byo/BYOTerrainEngineNode.cpp
index 184a54b..ba213b6 100644
--- a/src/osgEarthDrivers/engine_byo/BYOTerrainEngineNode.cpp
+++ b/src/osgEarthDrivers/engine_byo/BYOTerrainEngineNode.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
@@ -35,7 +35,7 @@ using namespace osgEarth::Drivers;
 BYOTerrainEngineNode::BYOTerrainEngineNode() :
 TerrainEngineNode( )
 {
-    //nop
+    _uid = Registry::instance()->createUID();
 }
 
 BYOTerrainEngineNode::~BYOTerrainEngineNode()
@@ -56,11 +56,7 @@ BYOTerrainEngineNode::preInitialize( const Map* map, const TerrainOptions& optio
     {
         OE_INFO << LC << "Loading terrain from " << myoptions.url()->full() << std::endl;
 
-        // no caching for this terrain.
-        osg::ref_ptr<osgDB::Options> dbOptions = Registry::instance()->cloneOrCreateOptions();
-        CachePolicy::NO_CACHE.apply( dbOptions.get() );
-
-        osg::Node* node = myoptions.url()->getNode( dbOptions.get() );
+        osg::Node* node = myoptions.url()->getNode();
         if ( node )
         {
             if ( myoptions.shaderPolicy() == SHADERPOLICY_GENERATE )
diff --git a/src/osgEarthDrivers/engine_byo/BYOTerrainEngineOptions b/src/osgEarthDrivers/engine_byo/BYOTerrainEngineOptions
index 7d6198b..73ab11e 100644
--- a/src/osgEarthDrivers/engine_byo/BYOTerrainEngineOptions
+++ b/src/osgEarthDrivers/engine_byo/BYOTerrainEngineOptions
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthDrivers/engine_byo/Common b/src/osgEarthDrivers/engine_byo/Common
index faf4a3f..f3431fb 100644
--- a/src/osgEarthDrivers/engine_byo/Common
+++ b/src/osgEarthDrivers/engine_byo/Common
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthDrivers/engine_mp/CMakeLists.txt b/src/osgEarthDrivers/engine_mp/CMakeLists.txt
index 44c0886..bb36a33 100644
--- a/src/osgEarthDrivers/engine_mp/CMakeLists.txt
+++ b/src/osgEarthDrivers/engine_mp/CMakeLists.txt
@@ -4,7 +4,10 @@ SET(TARGET_COMMON_LIBRARIES ${TARGET_COMMON_LIBRARIES} osgEarthSymbology)
 set(TARGET_GLSL
     MPEngine.vert.model.glsl
     MPEngine.vert.view.glsl
-    MPEngine.frag.glsl)
+    MPEngine.frag.glsl
+    MPEngine.NormalMap.vert.glsl
+    MPEngine.NormalMap.frag.glsl
+)
 
 set(TARGET_IN
     MPShaders.cpp.in)
@@ -44,7 +47,6 @@ SET(TARGET_H
     MPShaders
     MPTerrainEngineNode
     MPTerrainEngineOptions
-    QuickReleaseGLObjects
     SingleKeyNodeFactory
     TerrainNode
     TileGroup
diff --git a/src/osgEarthDrivers/engine_mp/Common b/src/osgEarthDrivers/engine_mp/Common
index 0736efc..eddaad2 100644
--- a/src/osgEarthDrivers/engine_mp/Common
+++ b/src/osgEarthDrivers/engine_mp/Common
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthDrivers/engine_mp/DynamicLODScaleCallback b/src/osgEarthDrivers/engine_mp/DynamicLODScaleCallback
index d05eda1..6272d3a 100644
--- a/src/osgEarthDrivers/engine_mp/DynamicLODScaleCallback
+++ b/src/osgEarthDrivers/engine_mp/DynamicLODScaleCallback
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthDrivers/engine_mp/FileLocationCallback b/src/osgEarthDrivers/engine_mp/FileLocationCallback
index eaa6518..0662946 100644
--- a/src/osgEarthDrivers/engine_mp/FileLocationCallback
+++ b/src/osgEarthDrivers/engine_mp/FileLocationCallback
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthDrivers/engine_mp/GeometryPool b/src/osgEarthDrivers/engine_mp/GeometryPool
new file mode 100644
index 0000000..a1f92b7
--- /dev/null
+++ b/src/osgEarthDrivers/engine_mp/GeometryPool
@@ -0,0 +1,92 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+* Copyright 2008-2014 Pelican Mapping
+* http://osgearth.org
+*
+* osgEarth is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public License
+* along with this program.  If not, see <http://www.gnu.org/licenses/>
+*/
+#ifndef OSGEARTH_DRIVERS_MP_TERRAIN_ENGINE_GEOMETRY_POOL
+#define OSGEARTH_DRIVERS_MP_TERRAIN_ENGINE_GEOMETRY_POOL 1
+
+#include "Common"
+#include "MaskGenerator"
+#include "MPTerrainEngineOptions"
+#include <osgEarth/MapInfo>
+#include <osgEarth/TileKey>
+#include <osgEarth/ThreadingUtils>
+#include <osg/Geometry>
+
+namespace osgEarth { namespace Drivers { namespace MPTerrainEngine
+{
+    using namespace osgEarth;
+
+    /**
+     * Pooled geometry manager.
+     * Concept adapted from OSG's osgTerrain::GeometryPool
+     */
+    class GeometryPool : public osg::Referenced
+    {
+    public:
+        GeometryPool(
+            unsigned tileSize,
+            const MPTerrainEngineOptions& options);
+
+    public:
+        /**
+         * Hashtable key for unique (and therefore shareable) geometries.
+         */
+        struct GeometryKey
+        {
+            GeometryKey() : lod(-1) {}
+
+            bool operator < (const GeometryKey& rhs) const
+            {
+                if (lod < rhs.lod) return true;
+                if (lod > rhs.lod) return false;                
+                return (yMin < rhs.yMin);
+            }
+
+            int    lod;
+            double yMin;
+        };
+
+        typedef std::map<GeometryKey, osg::ref_ptr<osg::Geometry> > GeometryMap;
+
+        void getPooledGeometry(
+            const TileKey&               tileKey, 
+            const MapInfo&               mapInfo,
+            osg::ref_ptr<osg::Geometry>& out);
+
+        osg::Geometry* createGeometry(
+            const TileKey& tileKey,
+            const MapInfo& mapInfo,
+            MaskGenerator* maskSet ) const;
+
+    protected:
+        virtual ~GeometryPool() { }
+
+        mutable Threading::Mutex      _geometryMapMutex;
+        GeometryMap                   _geometryMap;
+        unsigned                      _tileSize;
+        const MPTerrainEngineOptions& _options;
+        
+        void createKeyForTileKey(
+            const TileKey& tileKey, 
+            const MapInfo& mapInfo,
+            GeometryKey&   out) const;
+    };
+
+} } } // namespace osgEarth::Drivers::MPTerrainEngine
+
+#endif // OSGEARTH_DRIVERS_MP_TERRAIN_ENGINE_GEOMETRY_POOL
diff --git a/src/osgEarthDrivers/engine_mp/GeometryPool.cpp b/src/osgEarthDrivers/engine_mp/GeometryPool.cpp
new file mode 100644
index 0000000..09f4c73
--- /dev/null
+++ b/src/osgEarthDrivers/engine_mp/GeometryPool.cpp
@@ -0,0 +1,254 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+* Copyright 2008-2014 Pelican Mapping
+* http://osgearth.org
+*
+* osgEarth is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public License
+* along with this program.  If not, see <http://www.gnu.org/licenses/>
+*/
+#include "GeometryPool"
+#include <osgEarth/Locators>
+
+using namespace osgEarth;
+using namespace osgEarth::Drivers::MPTerrainEngine;
+
+#define LC "[GeometryPool] "
+
+
+GeometryPool::GeometryPool(unsigned                      tileSize,
+                           const MPTerrainEngineOptions& options) :
+_tileSize( tileSize ),
+_options ( options )
+{
+    // nop
+}
+
+void
+GeometryPool::getPooledGeometry(const TileKey&               tileKey,
+                                const MapInfo&               mapInfo,
+                                osg::ref_ptr<osg::Geometry>& out)
+{
+    // convert to a unique-geometry key:
+    GeometryKey geomKey;
+    createKeyForTileKey( tileKey, mapInfo, geomKey );
+
+    // Look it up in the pool:
+    Threading::ScopedMutexLock exclusive( _geometryMapMutex );
+    GeometryMap::iterator i = _geometryMap.find( geomKey );
+    if ( i != _geometryMap.end() )
+    {
+        // Found. return it.
+        out = i->second.get();
+    }
+    else
+    {
+        // Not found. Create it.
+        out = createGeometry( tileKey, mapInfo, 0L );
+        _geometryMap[ geomKey ] = out.get();
+        OE_NOTICE << LC << "Geometry pool size = " << _geometryMap.size() << "\n";
+    }
+}
+
+void
+GeometryPool::createKeyForTileKey(const TileKey&             tileKey,
+                                  const MapInfo&             mapInfo,
+                                  GeometryPool::GeometryKey& out) const
+{
+    out.lod  = tileKey.getLOD();
+    out.yMin = mapInfo.isGeocentric()? tileKey.getExtent().yMin() : 0.0;
+}
+
+#define addSkirtDataForIndex(INDEX, HEIGHT) \
+{ \
+    verts->push_back( (*verts)[INDEX] ); \
+    normals->push_back( (*normals)[INDEX] ); \
+    texCoords->push_back( (*texCoords)[INDEX] ); \
+    verts->push_back( (*verts)[INDEX] - ((*normals)[INDEX])*(HEIGHT) ); \
+    normals->push_back( (*normals)[INDEX] ); \
+    texCoords->push_back( (*texCoords)[INDEX] ); \
+}
+
+#define addSkirtTriangles(INDEX0, INDEX1) \
+{ \
+    if ( maskSet == 0L || (!maskSet->isMasked((*texCoords)[INDEX0]) && !maskSet->isMasked((*texCoords)[INDEX1])) ) \
+    { \
+        primSet->addElement((INDEX0));   \
+        primSet->addElement((INDEX0)+1); \
+        primSet->addElement((INDEX1));   \
+        primSet->addElement((INDEX1));   \
+        primSet->addElement((INDEX0)+1); \
+        primSet->addElement((INDEX1)+1); \
+    } \
+}
+
+osg::Geometry*
+GeometryPool::createGeometry(const TileKey& tileKey,
+                             const MapInfo& mapInfo,
+                             MaskGenerator* maskSet) const
+{
+    osg::ref_ptr<GeoLocator> locator = GeoLocator::createForKey( tileKey, mapInfo );
+    
+    // Establish a local reference frame for the tile:
+    osg::Vec3d centerWorld;
+    GeoPoint centroid;
+    tileKey.getExtent().getCentroid( centroid );
+    centroid.toWorld( centerWorld );
+
+    osg::Matrix world2local, local2world;
+    centroid.createWorldToLocal( world2local );
+    local2world.invert( world2local );
+
+    // Attempt to calculate the number of verts in the surface geometry.
+    bool createSkirt = _options.heightFieldSkirtRatio() > 0.0f;
+    unsigned numVertsInSurface = (_tileSize*_tileSize);
+    unsigned numVertsInSkirt = createSkirt ? _tileSize*4u - 4u : 0;
+    unsigned numVerts = numVertsInSurface + numVertsInSkirt;    
+    unsigned numIndiciesInSurface = (_tileSize-1) * (_tileSize-1) * 6;
+    unsigned numIncidesInSkirt    = createSkirt ? (_tileSize-1) * 4 * 6 : 0;
+    
+    // Pre-allocate enought space for all triangles.
+    osg::DrawElements* primSet = numVerts > 0xFFFF ? 
+        (osg::DrawElements*)(new osg::DrawElementsUInt(GL_TRIANGLES)) :
+        (osg::DrawElements*)(new osg::DrawElementsUShort(GL_TRIANGLES));
+
+    primSet->reserveElements(numIndiciesInSurface + numIncidesInSkirt);
+
+    osg::BoundingSphere tileBound;
+
+    // the geometry:
+    osg::Geometry* geom = new osg::Geometry();
+    geom->setUseVertexBufferObjects(true);
+    geom->setUseDisplayList(false);
+
+    geom->addPrimitiveSet( primSet );
+
+    // the vertex locations:
+    osg::Vec3Array* verts = new osg::Vec3Array();
+    verts->reserve( numVerts );
+    geom->setVertexArray( verts );
+
+    // the surface normals (i.e. extrusion vectors)
+    osg::Vec3Array* normals = new osg::Vec3Array();
+    normals->reserve( numVerts );
+    geom->setNormalArray( normals );
+
+    // tex coord is [0..1] across the tile. The 3rd dimension tracks whether the
+    // vert is masked: 0=yes, 1=no
+    osg::Vec3Array* texCoords = new osg::Vec3Array();
+    texCoords->reserve( numVerts );
+    geom->setTexCoordArray( 0, texCoords );
+    
+    for(unsigned row=0; row<_tileSize; ++row)
+    {
+        float ny = (float)row/(float)(_tileSize-1);
+        for(unsigned col=0; col<_tileSize; ++col)
+        {
+            float nx = (float)col/(float)(_tileSize-1);
+
+            osg::Vec3d model;
+            locator->unitToModel(osg::Vec3d(nx, ny, 0.0f), model);
+            osg::Vec3d modelLTP = model*world2local;
+            verts->push_back( modelLTP );
+            tileBound.expandBy( verts->back() );
+
+            // no masking in the geometry pool, so always write a z=1.0 -gw
+            //bool masked = _maskSet.contains(nx, ny);            
+            texCoords->push_back( osg::Vec3f(nx, ny, 1.0f) );
+
+            osg::Vec3d modelPlusOne;
+            locator->unitToModel(osg::Vec3d(nx, ny, 1.0f), modelPlusOne);
+            osg::Vec3f normal = (modelPlusOne*world2local)-modelLTP;
+            normal.normalize();
+            normals->push_back( normal );
+        }
+    }
+
+    // Now tessellate the surface.
+    
+    // TODO: do we really need this??
+    bool swapOrientation = !locator->orientationOpenGL();
+
+    for(unsigned j=0; j<_tileSize-1; ++j)
+    {
+        for(unsigned i=0; i<_tileSize-1; ++i)
+        {
+            int i00;
+            int i01;
+            if (swapOrientation)
+            {
+                i01 = j*_tileSize + i;
+                i00 = i01+_tileSize;
+            }
+            else
+            {
+                i00 = j*_tileSize + i;
+                i01 = i00+_tileSize;
+            }
+
+            int i10 = i00+1;
+            int i11 = i01+1;
+
+            // If the quad does not intersect a mask, tessellate it; otherwise skip it
+            // since the mask generator will take care of it.
+            bool addTris = true;
+            if ( maskSet )
+            {
+                addTris =
+                    !maskSet->isMasked( (*texCoords)[i00] ) &&
+                    !maskSet->isMasked( (*texCoords)[i01] ) &&
+                    !maskSet->isMasked( (*texCoords)[i10] ) &&
+                    !maskSet->isMasked( (*texCoords)[i11] ) &&
+                    !maskSet->containedByQuadAtColRow( i, j, _tileSize );
+            }
+
+            if ( addTris )
+            {
+                primSet->addElement(i01);
+                primSet->addElement(i00);
+                primSet->addElement(i11);
+
+                primSet->addElement(i00);
+                primSet->addElement(i10);
+                primSet->addElement(i11);
+            }
+        }
+    }
+
+    // SKIRTS:
+    // calculate the skirt extrusion height
+    double height = tileBound.radius() * _options.heightFieldSkirtRatio().get();
+        
+    unsigned skirtIndex = verts->size();
+
+    // first, create all the skirt verts, normals, and texcoords.
+    for(int c=0; c<(int)_tileSize-1; ++c)
+        addSkirtDataForIndex( c, height ); //top
+
+    for(int r=0; r<(int)_tileSize-1; ++r)
+        addSkirtDataForIndex( r*_tileSize+(_tileSize-1), height ); //right
+    
+    for(int c=_tileSize-1; c>=0; --c)
+        addSkirtDataForIndex( (_tileSize-1)*_tileSize+c, height ); //bottom
+
+    for(int r=_tileSize-1; r>=0; --r)
+        addSkirtDataForIndex( r*_tileSize, height ); //left
+    
+    // then create the elements indices:
+    int i;
+    for(i=skirtIndex; i<(int)verts->size()-2; i+=2)
+        addSkirtTriangles( i, i+2 );
+
+    addSkirtTriangles( i, skirtIndex );
+
+    return geom;
+}
diff --git a/src/osgEarthDrivers/engine_mp/HeightFieldCache b/src/osgEarthDrivers/engine_mp/HeightFieldCache
index ac4a9d2..27a17d3 100644
--- a/src/osgEarthDrivers/engine_mp/HeightFieldCache
+++ b/src/osgEarthDrivers/engine_mp/HeightFieldCache
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
@@ -88,8 +88,8 @@ namespace osgEarth { namespace Drivers { namespace MPTerrainEngine
         }
 
     private:
+        bool                            _enabled;
         mutable LRUCache<HFKey,HFValue> _cache;
-        int                             _firstLOD;
         int                             _tileSize;
         bool                            _useParentAsReferenceHF;
     };
diff --git a/src/osgEarthDrivers/engine_mp/HeightFieldCache.cpp b/src/osgEarthDrivers/engine_mp/HeightFieldCache.cpp
index d180d89..8cb9e36 100644
--- a/src/osgEarthDrivers/engine_mp/HeightFieldCache.cpp
+++ b/src/osgEarthDrivers/engine_mp/HeightFieldCache.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
@@ -20,6 +20,7 @@
 * along with this program.  If not, see <http://www.gnu.org/licenses/>
 */
 #include "HeightFieldCache"
+#include <cstdlib>
 
 using namespace osgEarth::Drivers::MPTerrainEngine;
 using namespace osgEarth;
@@ -32,6 +33,7 @@ _cache   ( true, 128 ),
 _tileSize( options.tileSize().get() )
 {
     _useParentAsReferenceHF = (options.elevationSmoothing() == true);
+    _enabled = (::getenv("OSGEARTH_MEMORY_PROFILE") == 0L);
 }
 
 
@@ -58,7 +60,7 @@ HeightFieldCache::getOrCreateHeightField(const MapFrame&                 frame,
         progress->stats()["hfcache_try_count"] += 1;
 
     LRUCache<HFKey,HFValue>::Record rec;
-    if ( _cache.get(cachekey, rec) )
+    if ( _enabled && _cache.get(cachekey, rec) )
     {
         // Found it in the cache.
         out_hf         = rec.value()._hf.get();
@@ -129,7 +131,7 @@ HeightFieldCache::getOrCreateHeightField(const MapFrame&                 frame,
         // while the tile's parent expires from the scene graph. In that case the result
         // of this task will be discarded. Therefore we should not cache the result here.
         // This was causing intermittent rare "flat tiles" to appear in the terrain.
-        if ( parent_hf )
+        if ( _enabled && parent_hf )
         {
             // cache it.
             HFValue cacheval;
diff --git a/src/osgEarthDrivers/engine_mp/KeyNodeFactory b/src/osgEarthDrivers/engine_mp/KeyNodeFactory
index 0a9cb6e..3e0a5ff 100644
--- a/src/osgEarthDrivers/engine_mp/KeyNodeFactory
+++ b/src/osgEarthDrivers/engine_mp/KeyNodeFactory
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthDrivers/engine_mp/KeyNodeFactory.cpp b/src/osgEarthDrivers/engine_mp/KeyNodeFactory.cpp
index 3c2cc00..7861c32 100644
--- a/src/osgEarthDrivers/engine_mp/KeyNodeFactory.cpp
+++ b/src/osgEarthDrivers/engine_mp/KeyNodeFactory.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthDrivers/engine_mp/MPEngine.NormalMap.frag.glsl b/src/osgEarthDrivers/engine_mp/MPEngine.NormalMap.frag.glsl
new file mode 100644
index 0000000..632e742
--- /dev/null
+++ b/src/osgEarthDrivers/engine_mp/MPEngine.NormalMap.frag.glsl
@@ -0,0 +1,37 @@
+#version $GLSL_VERSION_STR
+
+#pragma vp_entryPoint oe_mp_NormalMap_fragment
+#pragma vp_location   fragment_coloring
+#pragma vp_order      0.2
+
+uniform sampler2D oe_tile_normalTex;
+
+in vec3 vp_Normal;
+in vec2 oe_normalMapCoords;
+in vec3 oe_normalMapBinormal;
+
+void oe_mp_NormalMap_fragment(inout vec4 color)
+{
+    //const vec3 B = vec3(0,1,0);
+
+    vec4 encodedNormal = texture2D(oe_tile_normalTex, oe_normalMapCoords);
+    vec3 normal        = normalize(encodedNormal.xyz*2.0-1.0);
+
+    //vp_Normal = normalize(oe_mp_NormalMap_TBN * normalTangent);
+
+    vec3 tangent = normalize(cross(oe_normalMapBinormal, vp_Normal));
+
+    vp_Normal = normalize(mat3(tangent, oe_normalMapBinormal, vp_Normal) * normal);
+
+    // visualize curvature gradient:
+    //color.rgb = vec3(0,0,0);
+    //color.r = (encodedNormal.a+1.0)/2.0;
+    //color.b = 1.0-color.r;
+
+    // visualize curvature quantized:
+    //if(encodedNormal.a >= 0.4) color.r = 1.0;
+    //if(encodedNormal.a <= -0.4) color.b = 1.0;
+    
+    // visualize normals:
+    //color.rgb = encodedNormal.xyz;
+}
diff --git a/src/osgEarthDrivers/engine_mp/MPEngine.NormalMap.vert.glsl b/src/osgEarthDrivers/engine_mp/MPEngine.NormalMap.vert.glsl
new file mode 100644
index 0000000..9339346
--- /dev/null
+++ b/src/osgEarthDrivers/engine_mp/MPEngine.NormalMap.vert.glsl
@@ -0,0 +1,23 @@
+#version $GLSL_VERSION_STR
+
+#pragma vp_entryPoint oe_mp_NormalMap_vertex
+#pragma vp_location   vertex_view
+#pragma vp_order      0.5
+
+uniform mat4 oe_tile_normalTexMatrix;
+
+// stage globals
+vec3 vp_Normal;
+vec4 oe_layer_tilec;
+
+out vec2 oe_normalMapCoords;
+out vec3 oe_normalMapBinormal;
+
+void oe_mp_NormalMap_vertex(inout vec4 unused)
+{
+    // calculate the sampling coordinates for the normal texture
+    oe_normalMapCoords = (oe_tile_normalTexMatrix * oe_layer_tilec).st;
+
+    // send the bi-normal vector to the fragment shader.
+    oe_normalMapBinormal = gl_NormalMatrix * vec3(0,1,0);
+}
diff --git a/src/osgEarthDrivers/engine_mp/MPEngine.frag.glsl b/src/osgEarthDrivers/engine_mp/MPEngine.frag.glsl
index d7dbb9c..0e29fb0 100644
--- a/src/osgEarthDrivers/engine_mp/MPEngine.frag.glsl
+++ b/src/osgEarthDrivers/engine_mp/MPEngine.frag.glsl
@@ -1,10 +1,10 @@
 #version $GLSL_VERSION_STR
 $GLSL_DEFAULT_PRECISION_FLOAT
 
-#pragma vp_entryPoint "oe_mp_apply_coloring"
-#pragma vp_location   "fragment_coloring"
-#pragma vp_order      "0.5"
-#pragma vp_define     "MP_USE_BLENDING"
+#pragma vp_entryPoint oe_mp_apply_coloring
+#pragma vp_location   fragment_coloring
+#pragma vp_order      0.5
+#pragma vp_define     MP_USE_BLENDING
 
 uniform bool oe_isPickCamera;
 uniform vec4 oe_terrain_color;
@@ -13,8 +13,8 @@ uniform int oe_layer_uid;
 uniform int oe_layer_order;
 uniform float oe_layer_opacity;
 
-varying vec4 oe_layer_texc;
-varying float oe_layer_rangeOpacity;
+in vec4 oe_layer_texc;
+in float oe_layer_rangeOpacity;
 
 void oe_mp_apply_coloring(inout vec4 color)
 {
@@ -31,7 +31,8 @@ void oe_mp_apply_coloring(inout vec4 color)
     color = texel;
 #endif
 
-    // disable primary coloring for pick cameras.
+    // disable primary coloring for pick cameras. Necessary to support picking of
+    // draped geometry.
     float pick = oe_isPickCamera ? 1.0 : 0.0;
     color = mix(color, vec4(0), pick);
 }
diff --git a/src/osgEarthDrivers/engine_mp/MPEngine.vert.model.glsl b/src/osgEarthDrivers/engine_mp/MPEngine.vert.model.glsl
index ec99ca8..7fcae7c 100644
--- a/src/osgEarthDrivers/engine_mp/MPEngine.vert.model.glsl
+++ b/src/osgEarthDrivers/engine_mp/MPEngine.vert.model.glsl
@@ -1,15 +1,25 @@
 #version $GLSL_VERSION_STR
 $GLSL_DEFAULT_PRECISION_FLOAT
 
-#pragma vp_entryPoint "oe_mp_vertModel"
-#pragma vp_location   "vertex_model"
-#pragma vp_order      "-FLT_MAX"
+#pragma vp_entryPoint oe_mp_vertModel
+#pragma vp_location   vertex_model
+#pragma vp_order      first
 
-varying vec4 oe_layer_texc;
-varying vec4 oe_layer_tilec;
+out vec4 oe_layer_texc;
+out vec4 oe_layer_tilec;
+
+out vec3 oe_UpVectorView;
+out float oe_mp_terrainElev; // internal
+in vec4 oe_terrain_attr;     // internal
 
 void oe_mp_vertModel(inout vec4 vertexModel)
 {
     oe_layer_texc  = gl_MultiTexCoord$MP_PRIMARY_UNIT;
     oe_layer_tilec = gl_MultiTexCoord$MP_SECONDARY_UNIT;
+
+    oe_UpVectorView = gl_NormalMatrix * oe_terrain_attr.xyz;
+
+    // internal variable to support the oe_terrain_getElevation() SDK method
+    // in the fragment shader stage
+    oe_mp_terrainElev = oe_terrain_attr[3];
 }
diff --git a/src/osgEarthDrivers/engine_mp/MPEngine.vert.pooled.glsl b/src/osgEarthDrivers/engine_mp/MPEngine.vert.pooled.glsl
new file mode 100644
index 0000000..6648025
--- /dev/null
+++ b/src/osgEarthDrivers/engine_mp/MPEngine.vert.pooled.glsl
@@ -0,0 +1,24 @@
+#version $GLSL_VERSION_STR
+$GLSL_DEFAULT_PRECISION_FLOAT
+
+uniform mat4 oe_layer_texMatrix;
+varying vec4 oe_layer_texc;
+varying vec4 oe_layer_tilec;
+varying vec3 oe_Normal;
+
+uniform sampler2D oe_tile_elevationTex;
+uniform mat4 oe_tile_elevationTexMatrix;
+
+void oe_mp_pooled_vert(inout vec4 vertexModel)
+{
+    // Texture coordinate for the tile (always 0..1)
+    oe_layer_tilec = gl_MultiTexCoord$MP_PRIMARY_UNIT;
+
+    // Texture coordinate for the color texture (scale,bias)
+    oe_layer_texc = oe_layer_texMatrix * oe_layer_tilec;
+
+    // Sample the elevation texture and move the vertex accordingly.
+    vec4 elevc = oe_tile_elevationTexMatrix * oe_layer_tilec;
+    float elev = texture2D(oe_tile_elevationTex, elevc.st).r;
+    vertexModel.xyz = vertexModel.xyz + oe_Normal*elev;
+}
diff --git a/src/osgEarthDrivers/engine_mp/MPEngine.vert.view.glsl b/src/osgEarthDrivers/engine_mp/MPEngine.vert.view.glsl
index aee7c17..1f2b250 100644
--- a/src/osgEarthDrivers/engine_mp/MPEngine.vert.view.glsl
+++ b/src/osgEarthDrivers/engine_mp/MPEngine.vert.view.glsl
@@ -1,19 +1,19 @@
 #version $GLSL_VERSION_STR
 $GLSL_DEFAULT_PRECISION_FLOAT
 
-#pragma vp_entryPoint "oe_mp_vertView"
-#pragma vp_location   "vertex_view"
-#pragma vp_order      "0.5"
+#pragma vp_entryPoint oe_mp_vertView
+#pragma vp_location   vertex_view
+#pragma vp_order      0.5
 
 uniform float oe_layer_minRange;
 uniform float oe_layer_maxRange;
 uniform float oe_layer_attenuationRange;
 
-varying float oe_layer_rangeOpacity;
+out float oe_layer_rangeOpacity;
 
 void oe_mp_vertView(inout vec4 vertexView)
 {
-    float range = -vertexView.z;
+    float range = max(-vertexView.z, 0.0);
 
     float attenMin    = oe_layer_minRange - oe_layer_attenuationRange;
     float attenMax    = oe_layer_maxRange + oe_layer_attenuationRange;
diff --git a/src/osgEarthDrivers/engine_mp/MPGeometry b/src/osgEarthDrivers/engine_mp/MPGeometry
index 32a02d2..d6da05f 100644
--- a/src/osgEarthDrivers/engine_mp/MPGeometry
+++ b/src/osgEarthDrivers/engine_mp/MPGeometry
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
@@ -50,6 +50,8 @@ namespace osgEarth { namespace Drivers { namespace MPTerrainEngine
             Layer()
             {
                 _texMatUniformID = ~0;
+                _layerID = 0u;
+                _opaque = true;
             }
 
             osgEarth::UID                  _layerID;
@@ -58,7 +60,6 @@ namespace osgEarth { namespace Drivers { namespace MPTerrainEngine
             osg::ref_ptr<osg::Vec2Array>   _texCoords;
             osg::ref_ptr<osg::Texture>     _texParent;
             osg::Matrixf                   _texMatParent; // yes, must be a float matrix
-            float                          _alphaThreshold;
             bool                           _opaque;
 
             // for shared layers only:
@@ -107,6 +108,8 @@ namespace osgEarth { namespace Drivers { namespace MPTerrainEngine
 
         osg::ref_ptr<osg::Texture> _elevTex;
 
+        mutable osg::ref_ptr<osg::PrimitiveSet> _patchTriangles;
+
     public:
         
         // construct a new MPGeometry.
@@ -134,6 +137,13 @@ namespace osgEarth { namespace Drivers { namespace MPTerrainEngine
         // all the code that handles non-fastPath (don't need it) and
         // called into our custom renderPrimitiveSets method.
         void drawImplementation(osg::RenderInfo& renderInfo) const;
+        
+        // override to correctly process GL_PATCHES if necessary
+        bool supports(const osg::PrimitiveFunctor&) const { return true; }
+        void accept(osg::PrimitiveFunctor& functor) const;
+
+        bool supports(const osg::PrimitiveIndexFunctor&) const { return true; }
+        void accept(osg::PrimitiveIndexFunctor& functor) const;
 
         // recalculate the bound for the tile key uniform.
 #if OSG_VERSION_GREATER_THAN(3,3,1)
@@ -144,8 +154,8 @@ namespace osgEarth { namespace Drivers { namespace MPTerrainEngine
 
     public:
         META_Object(osgEarth, MPGeometry);
-        MPGeometry() : osg::Geometry(), _frame(0L) { }
-        MPGeometry(const MPGeometry& rhs, const osg::CopyOp& cop) : osg::Geometry(rhs, cop), _frame(rhs._frame) { }
+        MPGeometry();
+        MPGeometry(const MPGeometry& rhs, const osg::CopyOp& cop);
         virtual ~MPGeometry() { }
     };
 
diff --git a/src/osgEarthDrivers/engine_mp/MPGeometry.cpp b/src/osgEarthDrivers/engine_mp/MPGeometry.cpp
index 50ad265..d408441 100644
--- a/src/osgEarthDrivers/engine_mp/MPGeometry.cpp
+++ b/src/osgEarthDrivers/engine_mp/MPGeometry.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
@@ -37,10 +37,58 @@ using namespace osgEarth;
 #define LC "[MPGeometry] "
 
 
+MPGeometry::MPGeometry() :
+osg::Geometry(),
+_frame(0L),
+_uidUniformNameID(0),
+_birthTimeUniformNameID(0u),
+_orderUniformNameID(0u),
+_opacityUniformNameID(0u),
+_texMatParentUniformNameID(0u),
+_tileKeyUniformNameID(0u),
+_minRangeUniformNameID(0u),
+_maxRangeUniformNameID(0u),
+_imageUnit(0),
+_imageUnitParent(0),
+_elevUnit(0),
+_supportsGLSL(false)
+{
+}
+
+MPGeometry::MPGeometry(const MPGeometry& rhs, const osg::CopyOp& cop) :
+osg::Geometry(rhs, cop),
+_frame(rhs._frame),
+_uidUniformNameID(rhs._uidUniformNameID),
+_birthTimeUniformNameID(rhs._birthTimeUniformNameID),
+_orderUniformNameID(rhs._orderUniformNameID),
+_opacityUniformNameID(rhs._opacityUniformNameID),
+_texMatParentUniformNameID(rhs._texMatParentUniformNameID),
+_tileKeyUniformNameID(rhs._tileKeyUniformNameID),
+_minRangeUniformNameID(rhs._minRangeUniformNameID),
+_maxRangeUniformNameID(rhs._maxRangeUniformNameID),
+_imageUnit(rhs._imageUnit),
+_imageUnitParent(rhs._imageUnitParent),
+_elevUnit(rhs._elevUnit),
+_supportsGLSL(rhs._supportsGLSL)
+{
+}
+
+
 MPGeometry::MPGeometry(const TileKey& key, const MapFrame& frame, int imageUnit) : 
 osg::Geometry    ( ),
 _frame           ( frame ),
-_imageUnit       ( imageUnit )
+_imageUnit       ( imageUnit ),
+_uidUniformNameID(0),
+_birthTimeUniformNameID(0u),
+_orderUniformNameID(0u),
+_opacityUniformNameID(0u),
+_texMatParentUniformNameID(0u),
+_tileKeyUniformNameID(0u),
+_minRangeUniformNameID(0u),
+_maxRangeUniformNameID(0u),
+_imageUnitParent(0),
+_elevUnit(0),
+_supportsGLSL(false)
 {
     _supportsGLSL = Registry::capabilities().supportsGLSL();
 
@@ -141,6 +189,8 @@ MPGeometry::renderPrimitiveSets(osg::State& state,
         uidLocation          = pcp->getUniformLocation( _uidUniformNameID );
         orderLocation        = pcp->getUniformLocation( _orderUniformNameID );
         texMatParentLocation = pcp->getUniformLocation( _texMatParentUniformNameID );
+        minRangeLocation = pcp->getUniformLocation( _minRangeUniformNameID );
+        maxRangeLocation = pcp->getUniformLocation( _maxRangeUniformNameID );
     }
     
     // apply the tilekey uniform once.
@@ -193,13 +243,10 @@ MPGeometry::renderPrimitiveSets(osg::State& state,
 
     // remember whether we applied a parent texture.
     bool usedTexParent = false;
-    bool useMinVisibleRange = false;
-    bool useMaxVisibleRange = false;
 
     if ( _layers.size() > 0 )
     {
         float prev_opacity        = -1.0f;
-        float prev_alphaThreshold = -1.0f;
 
         // first bind any shared layers. We still have to do this even if we are
         // in !renderColor mode b/c these textures could be used by vertex shaders
@@ -234,29 +281,8 @@ MPGeometry::renderPrimitiveSets(osg::State& state,
                         }
                     }
                 }
-
-                // check for min/rax range usage.
-                const ImageLayerOptions& layerOptions = layer._imageLayer->getImageLayerOptions();
-
-                if ( layerOptions.minVisibleRange().isSet() )
-                    useMinVisibleRange = true;
-                if ( layerOptions.maxVisibleRange().isSet() )
-                    useMaxVisibleRange = true;
             }
         }
-
-        // look up the minRange uniform if necessary
-        if ( useMinVisibleRange && pcp )
-        {
-            minRangeLocation = pcp->getUniformLocation( _minRangeUniformNameID );
-        }
-        
-        // look up the maxRange uniform if necessary
-        if ( useMaxVisibleRange && pcp )
-        {
-            maxRangeLocation = pcp->getUniformLocation( _maxRangeUniformNameID );
-        }
-
         if (renderColor)
         {
             // find the first opaque layer, top-down, and start there:
@@ -438,22 +464,13 @@ MPGeometry:: COMPUTE_BOUND() const
         // update the uniform.
         Threading::ScopedMutexLock exclusive(_frameSyncMutex);
         _tileKeyValue.w() = bbox.radius();
-        
-#if 0
-        // make sure everyone's got a vbo.
-        MPGeometry* ncthis = const_cast<MPGeometry*>(this);
 
-        for(std::vector<Layer>::iterator i = _layers.begin(); i != _layers.end(); ++i)
+        // create the patch triangles index if necessary.
+        if ( getNumPrimitiveSets() > 0 && getPrimitiveSet(0)->getMode() == GL_PATCHES )
         {
-            if ( i->_texCoords.valid() && i->_texCoords->getVertexBufferObject() == 0L )
-                i->_texCoords->setVertexBufferObject( ncthis->getVertexArray()->getVertexBufferObject() );
+            _patchTriangles = osg::clone( getPrimitiveSet(0), osg::CopyOp::SHALLOW_COPY );
+            _patchTriangles->setMode( GL_TRIANGLES );
         }
-
-        if ( _tileCoords.valid() && _tileCoords->getVertexBufferObject() == 0L )
-        {
-            _tileCoords->setVertexBufferObject( ncthis->getVertexArray()->getVertexBufferObject() );
-        }
-#endif
     }
     return bbox;
 }
@@ -655,3 +672,25 @@ MPGeometry::drawImplementation(osg::RenderInfo& renderInfo) const
     state.unbindVertexBufferObject();
     state.unbindElementBufferObject();
 }
+
+void
+MPGeometry::accept(osg::PrimitiveIndexFunctor& functor) const
+{
+    osg::Geometry::accept(functor);
+
+    if ( getNumPrimitiveSets() > 0 && getPrimitiveSet(0)->getMode() == GL_PATCHES && _patchTriangles.valid() )
+    {
+        _patchTriangles->accept( functor );
+    }
+}
+
+void
+MPGeometry::accept(osg::PrimitiveFunctor& functor) const
+{
+    osg::Geometry::accept(functor);
+
+    if ( getNumPrimitiveSets() > 0 && getPrimitiveSet(0)->getMode() == GL_PATCHES && _patchTriangles.valid() )
+    {
+        _patchTriangles->accept( functor );
+    }
+}
diff --git a/src/osgEarthDrivers/engine_mp/MPShaders b/src/osgEarthDrivers/engine_mp/MPShaders
index 5cd6c36..dd61c0a 100644
--- a/src/osgEarthDrivers/engine_mp/MPShaders
+++ b/src/osgEarthDrivers/engine_mp/MPShaders
@@ -31,9 +31,11 @@ namespace osgEarth { namespace Drivers { namespace MPTerrainEngine
         
     public:
         std::string
-            VertexModel,
-            VertexView,
-            Fragment;
+            EngineVertexModel,
+            EngineVertexView,
+            EngineFragment,
+            NormalMapVertex,
+            NormalMapFragment;
 	};
 	
 } } } // namespace osgEarth::Drivers::MPTerrainEngine
diff --git a/src/osgEarthDrivers/engine_mp/MPShaders.cpp.in b/src/osgEarthDrivers/engine_mp/MPShaders.cpp.in
index 18e5e7c..383e402 100644
--- a/src/osgEarthDrivers/engine_mp/MPShaders.cpp.in
+++ b/src/osgEarthDrivers/engine_mp/MPShaders.cpp.in
@@ -2,18 +2,22 @@
 
 #include <osgEarthDrivers/engine_mp/MPShaders>
 
-#define MULTILINE(...) #__VA_ARGS__
-
 using namespace osgEarth::Drivers::MPTerrainEngine;
 
 Shaders::Shaders()
 {
-    VertexModel = "MPEngine.vert.model.glsl";
-    _sources[VertexModel] = OE_MULTILINE(@MPEngine.vert.model.glsl@);
+    EngineVertexModel = "MPEngine.vert.model.glsl";
+    _sources[EngineVertexModel] = "@MPEngine.vert.model.glsl@";
+
+    EngineVertexView = "MPEngine.vert.view.glsl";
+    _sources[EngineVertexView] = "@MPEngine.vert.view.glsl@";
+
+    EngineFragment = "MPEngine.frag.glsl";
+    _sources[EngineFragment] = "@MPEngine.frag.glsl@";
 
-    VertexView = "MPEngine.vert.view.glsl";
-    _sources[VertexView] = OE_MULTILINE(@MPEngine.vert.view.glsl@);
+    NormalMapVertex = "MPEngine.NormalMap.vert.glsl";
+    _sources[NormalMapVertex] = "@MPEngine.NormalMap.vert.glsl@";
 
-    Fragment = "MPEngine.frag.glsl";
-    _sources[Fragment] = OE_MULTILINE(@MPEngine.frag.glsl@);
+    NormalMapFragment = "MPEngine.NormalMap.frag.glsl";
+    _sources[NormalMapFragment] = "@MPEngine.NormalMap.frag.glsl@";
 }
diff --git a/src/osgEarthDrivers/engine_mp/MPTerrainEngineDriver.cpp b/src/osgEarthDrivers/engine_mp/MPTerrainEngineDriver.cpp
index 3b4a33e..d2cd67e 100644
--- a/src/osgEarthDrivers/engine_mp/MPTerrainEngineDriver.cpp
+++ b/src/osgEarthDrivers/engine_mp/MPTerrainEngineDriver.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -48,7 +48,7 @@ namespace osgEarth { namespace Drivers { namespace MPTerrainEngine
                 _profiling = as<int>(std::string(p), 1);
         }
 
-        virtual const char* className()
+        virtual const char* className() const
         {
             return "osgEarth MP Terrain Engine";
         }
@@ -146,7 +146,7 @@ namespace osgEarth { namespace Drivers { namespace MPTerrainEngine
                             progress->stats()["http_get_time"] / progress->stats()["http_get_count"];
 
                         OE_NOTICE << "tile: " << tileDef << std::endl;
-                        for(fast_map<std::string,double>::iterator i = progress->stats().begin();
+                        for(ProgressCallback::Stats::iterator i = progress->stats().begin();
                             i != progress->stats().end();
                             ++i)
                         {
diff --git a/src/osgEarthDrivers/engine_mp/MPTerrainEngineNode b/src/osgEarthDrivers/engine_mp/MPTerrainEngineNode
index e51515e..65e13ec 100644
--- a/src/osgEarthDrivers/engine_mp/MPTerrainEngineNode
+++ b/src/osgEarthDrivers/engine_mp/MPTerrainEngineNode
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -25,6 +25,7 @@
 #include <osgEarth/Revisioning>
 #include <osgEarth/ThreadingUtils>
 #include <osgEarth/Containers>
+#include <osgEarth/ResourceReleaser>
 
 #include "MPTerrainEngineOptions"
 #include "KeyNodeFactory"
@@ -73,6 +74,9 @@ namespace osgEarth { namespace Drivers { namespace MPTerrainEngine
         /** Access the stateset used to render payload data. */
         osg::StateSet* getPayloadStateSet();
 
+        /** Install and MP-specific shader library. */
+        bool includeShaderLibrary(VirtualProgram* vp);
+
     public: // internal TerrainEngineNode
 
         virtual void preInitialize( const Map* map, const TerrainOptions& options );
@@ -93,7 +97,6 @@ namespace osgEarth { namespace Drivers { namespace MPTerrainEngine
 
     public: // statics    
         static void registerEngine( MPTerrainEngineNode* engineNode );
-        static void unregisterEngine( UID uid );
         static void getEngineByUID( UID uid, osg::ref_ptr<MPTerrainEngineNode>& output );
 
     public:
@@ -112,7 +115,7 @@ namespace osgEarth { namespace Drivers { namespace MPTerrainEngine
         // override from TerrainEngineNode
         virtual void updateTextureCombining() { updateState(); }
         
-        virtual void notifyExistingNodes(TerrainTileNodeCallback* cb);
+        virtual void notifyExistingNodes(TerrainEngine::NodeCallback* cb);
 
     private:
         void init();
@@ -146,16 +149,17 @@ namespace osgEarth { namespace Drivers { namespace MPTerrainEngine
         bool               _batchUpdateInProgress;
         bool               _refreshRequired;
         bool               _stateUpdateRequired;
-        bool               _rootTilesRegistered;
-        Threading::Mutex   _rootTilesRegisteredMutex;
 
         osg::ref_ptr< ElevationChangedCallback > _elevationCallback;
 
+        osg::ref_ptr<TerrainEngine::NodeCallback> _normalMapInstaller;
+
         MapFrame* _update_mapf; // map frame for the main/update traversal thread
 
         // node registry is shared across all threads.
         osg::ref_ptr<TileNodeRegistry> _liveTiles;      // tiles in the scene graph.
-        osg::ref_ptr<TileNodeRegistry> _deadTiles;        // tiles that used to be in the scene graph.
+        //osg::ref_ptr<TileNodeRegistry> _deadTiles;        // tiles that used to be in the scene graph.
+        osg::ref_ptr<ResourceReleaser> _releaser;
 
         PerThread< osg::ref_ptr<KeyNodeFactory> > _perThreadKeyNodeFactories;
         KeyNodeFactory* getKeyNodeFactory();
@@ -166,8 +170,7 @@ namespace osgEarth { namespace Drivers { namespace MPTerrainEngine
         int        _primaryUnit;
         int        _secondaryUnit;
         int        _elevationTextureUnit;
-
-        osg::Uniform* _verticalScaleUniform;
+        int        _normalMapUnit;
 
         osg::ref_ptr< TileModelFactory > _tileModelFactory;
 
diff --git a/src/osgEarthDrivers/engine_mp/MPTerrainEngineNode.cpp b/src/osgEarthDrivers/engine_mp/MPTerrainEngineNode.cpp
index a750e2a..84c2789 100644
--- a/src/osgEarthDrivers/engine_mp/MPTerrainEngineNode.cpp
+++ b/src/osgEarthDrivers/engine_mp/MPTerrainEngineNode.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
@@ -123,6 +123,55 @@ namespace
         {
         }
     };
+
+#if 0
+    class NormalTexInstaller : public TerrainEngine::NodeCallback
+    {
+    public:
+        NormalTexInstaller(int unit) : _unit(unit) { }
+        
+    public: // TileNodeCallback
+        void operator()(const TileKey& key, osg::Node* node)
+        {
+            TileNode* tile = osgEarth::findTopMostNodeOfType<TileNode>(node);
+            if ( !tile )
+            {
+                OE_WARN << LC << "No tile " << key.str() << "\n";
+                return;
+            }
+
+            if ( !tile->getTileModel() )
+            {
+                OE_WARN << LC << "No tile model available for " << key.str() << "\n";
+                return;
+            }
+            
+            osg::StateSet* ss = node->getOrCreateStateSet();
+            osg::Texture* tex = tile->getTileModel()->getNormalTexture();
+            if ( tex )
+            {
+                ss->setTextureAttribute(_unit, tex);
+            }
+
+            osg::RefMatrixf* mat = tile->getModel()->getNormalTextureMatrix();
+            osg::Matrixf fmat;
+            if ( mat )
+            {
+                fmat = osg::Matrixf(*mat);
+            }
+            else
+            {
+                // special marker indicating that there's no valid normal texture.
+                fmat(0,0) = 0.0f;
+            }
+
+            ss->addUniform(new osg::Uniform("oe_tile_normalTexMatrix", fmat) );
+        }
+
+    private:
+        int _unit;
+    };
+#endif
 }
 
 //---------------------------------------------------------------------------
@@ -146,18 +195,6 @@ MPTerrainEngineNode::registerEngine(MPTerrainEngineNode* engineNode)
     OE_DEBUG << LC << "Registered engine " << engineNode->_uid << std::endl;
 }
 
-void
-MPTerrainEngineNode::unregisterEngine( UID uid )
-{
-    Threading::ScopedWriteLock exclusiveLock( s_engineNodeCacheMutex );
-    EngineNodeCache::iterator k = getEngineNodeCache().find( uid );
-    if (k != getEngineNodeCache().end())
-    {
-        getEngineNodeCache().erase(k);
-        OE_DEBUG << LC << "Unregistered engine " << uid << std::endl;
-    }
-}
-
 // since this method is called in a database pager thread, we use a ref_ptr output
 // parameter to avoid the engine node being destructed between the time we 
 // return it and the time it's accessed; this could happen if the user removed the
@@ -209,6 +246,7 @@ _stateUpdateRequired  ( false )
     // unique ID for this engine:
     _uid = Registry::instance()->createUID();
 
+#ifdef USE_RENDER_BINS
     // Register our render bins protos.
     {
         // Mutex because addRenderBinPrototype isn't thread-safe.
@@ -223,17 +261,26 @@ _stateUpdateRequired  ( false )
         _payloadRenderBinPrototype->setName( Stringify() << "oe.PayloadBin." << _uid );
         osgUtil::RenderBin::addRenderBinPrototype( _payloadRenderBinPrototype->getName(), _payloadRenderBinPrototype.get() );
     }
+#endif
 
     // install an elevation callback so we can update elevation data
     _elevationCallback = new ElevationChangedCallback( this );
+
+    // install the static shader components now.
+    if ( osgEarth::Registry::capabilities().supportsGLSL() )
+    {
+        osg::StateSet* stateset = getOrCreateStateSet();
+        VirtualProgram* vp = VirtualProgram::getOrCreate(stateset);
+        includeShaderLibrary( vp );
+    }
 }
 
 MPTerrainEngineNode::~MPTerrainEngineNode()
 {
-    unregisterEngine( _uid );
-
+#ifdef USE_RENDER_BINS
     osgUtil::RenderBin::removeRenderBinPrototype( _terrainRenderBinPrototype.get() );
     osgUtil::RenderBin::removeRenderBinPrototype( _payloadRenderBinPrototype.get() );
+#endif
 
     if ( _update_mapf )
     {
@@ -241,6 +288,113 @@ MPTerrainEngineNode::~MPTerrainEngineNode()
     }
 }
 
+bool
+MPTerrainEngineNode::includeShaderLibrary(VirtualProgram* vp)
+{
+    static const char* libVS =
+        "#version 330\n"
+        "#pragma vp_name MP Terrain SDK (VS)\n"
+
+        "in vec4 oe_terrain_attr; \n"
+        "uniform vec4 oe_tile_key; \n"
+        "vec3 vp_Normal; \n"
+
+        "float oe_terrain_getElevation(in vec2 uv) \n"
+        "{ \n"
+        "    return oe_terrain_attr[3]; \n"
+        "} \n"
+
+        "float oe_terrain_getElevation() \n"
+        "{ \n"
+        "    return oe_terrain_attr[3]; \n"
+        "} \n"
+
+        "vec4 oe_terrain_getNormalAndCurvature(in vec2 uv) \n"
+        "{ \n"
+        "    return vec4(vp_Normal, 0.0); \n"
+        "} \n"
+
+        "vec2 oe_terrain_scaleCoordsToRefLOD(in vec2 uv, in float refLOD) \n"
+        "{ \n"
+        "    float dL = oe_tile_key.z - refLOD; \n"
+        "    float factor = exp2(dL); \n"
+        "    float invFactor = 1.0/factor; \n"
+        "    vec2 scale = vec2(invFactor); \n"
+        "    vec2 result = uv * scale; \n"
+        "    if ( factor >= 1.0 ) \n"
+        "    { \n"
+        "        vec2 a = floor(oe_tile_key.xy * invFactor); \n"
+        "        vec2 b = a * factor; \n"
+        "        vec2 c = (a+1.0) * factor; \n"
+        "        vec2 offset = (oe_tile_key.xy-b)/(c-b); \n"
+        "        result += offset; \n"
+        "    } \n"
+        "    return result; \n"
+        "} \n";
+
+    static const char* libFS =
+        "#version 330\n"
+        "#pragma vp_name MP Terrain SDK (FS)\n"
+
+        "uniform vec4 oe_tile_key; \n"
+        "vec3 vp_Normal; \n"
+        "in float oe_mp_terrainElev; // internal variable \n"
+
+        "float oe_terrain_getElevation(in vec2 uv) \n"
+        "{ \n"
+        "    return oe_mp_terrainElev; \n"
+        "} \n"
+
+        "float oe_terrain_getElevation() \n"
+        "{ \n"
+        "    return oe_mp_terrainElev; \n"
+        "} \n"
+
+        "vec4 oe_terrain_getNormalAndCurvature(in vec2 uv) \n"
+        "{ \n"
+        "    return vec4(vp_Normal, 0.0); \n"
+        "} \n"
+
+        "vec4 oe_terrain_getNormalAndCurvature() \n"
+        "{ \n"
+        "    return vec4(vp_Normal, 0.0); \n"
+        "} \n"
+
+        "vec2 oe_terrain_scaleCoordsToRefLOD(in vec2 uv, in float refLOD) \n"
+        "{ \n"
+        "    float dL = oe_tile_key.z - refLOD; \n"
+        "    float factor = exp2(dL); \n"
+        "    float invFactor = 1.0/factor; \n"
+        "    vec2 scale = vec2(invFactor); \n"
+        "    vec2 result = uv * scale; \n"
+        "    if ( factor >= 1.0 ) \n"
+        "    { \n"
+        "        vec2 a = floor(oe_tile_key.xy * invFactor); \n"
+        "        vec2 b = a * factor; \n"
+        "        vec2 c = (a+1.0) * factor; \n"
+        "        vec2 offset = (oe_tile_key.xy-b)/(c-b); \n"
+        "        result += offset; \n"
+        "    } \n"
+        "    return result; \n"
+        "} \n";
+
+    if ( vp )
+    {
+        osg::Shader* VS = new osg::Shader(osg::Shader::VERTEX, libVS);
+        VS->setName( "oe_terrain_SDK_mp_VS" );
+        vp->setShader( VS );
+        
+        osg::Shader* FS = new osg::Shader(osg::Shader::FRAGMENT, libFS);
+        FS->setName( "oe_terrain_SDK_mp_FS" );
+        vp->setShader( FS );
+
+        vp->addBindAttribLocation( "oe_terrain_attr",  osg::Drawable::ATTRIBUTE_6 );
+        vp->addBindAttribLocation( "oe_terrain_attr2", osg::Drawable::ATTRIBUTE_7 );
+    }
+
+    return (vp != 0L);
+}
+
 void
 MPTerrainEngineNode::preInitialize( const Map* map, const TerrainOptions& options )
 {
@@ -269,11 +423,9 @@ MPTerrainEngineNode::postInitialize( const Map* map, const TerrainOptions& optio
     _liveTiles->setRevisioningEnabled( _terrainOptions.incrementalUpdate() == true );
     _liveTiles->setMapRevision( _update_mapf->getRevision() );
 
-    // set up a registry for quick release:
-    if ( _terrainOptions.quickReleaseGLObjects() == true )
-    {
-        _deadTiles = new TileNodeRegistry("dead");
-    }
+    // Facility to properly release GL objects
+    _releaser = new ResourceReleaser();
+    this->addChild(_releaser.get());
 
     // reserve GPU resources. Must do this before initializing the model factory.
     if ( _primaryUnit < 0 )
@@ -291,6 +443,14 @@ MPTerrainEngineNode::postInitialize( const Map* map, const TerrainOptions& optio
     // initialize the model factory:
     _tileModelFactory = new TileModelFactory(_liveTiles.get(), _terrainOptions, this);
 
+    // Normal map texture unit
+    if ( _terrainOptions.normalMaps() == true )
+    {
+        this->_requireNormalTextures = true;
+        getResources()->reserveTextureImageUnit( _normalMapUnit, "MP Normal Maps" );
+        _tileModelFactory->setNormalMapUnit( _normalMapUnit );
+    }
+
     // handle an already-established map profile:
     if ( _update_mapf->getProfile() )
     {
@@ -406,17 +566,15 @@ MPTerrainEngineNode::getTerrainStateSet()
 
 namespace
 {
-    struct NotifyExistingNodesOp : public TileNodeRegistry::Operation
+    struct NotifyExistingNodesOp : public TileNodeRegistry::ConstOperation
     {
-        TerrainTileNodeCallback* _cb;
+        TerrainEngine::NodeCallback* _cb;
 
-        NotifyExistingNodesOp(TerrainTileNodeCallback* cb) : _cb(cb) { }
+        NotifyExistingNodesOp(TerrainEngine::NodeCallback* cb) : _cb(cb) { }
 
-        void operator()(TileNodeRegistry::TileNodeMap& tiles)
+        void operator()(const TileNodeRegistry::TileNodeMap& tiles) const
         {
-            //OE_INFO << LC << "Gonna notify " << tiles.size() << " existing nodes...\n";
-
-            for(TileNodeRegistry::TileNodeMap::iterator i = tiles.begin();
+            for(TileNodeRegistry::TileNodeMap::const_iterator i = tiles.begin();
                 i != tiles.end();
                 ++i)
             {
@@ -427,7 +585,7 @@ namespace
 }
 
 void
-MPTerrainEngineNode::notifyExistingNodes(TerrainTileNodeCallback* cb)
+MPTerrainEngineNode::notifyExistingNodes(TerrainEngine::NodeCallback* cb)
 {
     NotifyExistingNodesOp op( cb );
     _liveTiles->run( op );
@@ -456,7 +614,11 @@ MPTerrainEngineNode::dirtyTerrain()
     }
 
     // New terrain
-    _terrain = new TerrainNode( _deadTiles.get() );
+    _terrain = new TerrainNode();
+
+    // Clear out the tile registry:
+    _liveTiles->releaseAll(_releaser.get());
+
 
 #ifdef USE_RENDER_BINS
     _terrain->getOrCreateStateSet()->setRenderBinDetails( 0, _terrainRenderBinPrototype->getName() );
@@ -466,45 +628,46 @@ MPTerrainEngineNode::dirtyTerrain()
 #endif
 
     this->addChild( _terrain );
-
-    // Factory to create the root keys:
-    KeyNodeFactory* factory = getKeyNodeFactory();
-    
     // Build the first level of the terrain.
     // Collect the tile keys comprising the root tiles of the terrain.
-    std::vector< TileKey > keys;
-    _update_mapf->getProfile()->getAllKeysAtLOD( *_terrainOptions.firstLOD(), keys );
+    if ( _update_mapf )
+    {
+        // Factory to create the root keys:
+        KeyNodeFactory* factory = getKeyNodeFactory();
+    
+        std::vector< TileKey > keys;
+        _update_mapf->getProfile()->getAllKeysAtLOD( *_terrainOptions.firstLOD(), keys );
 
-    // create a root node for each root tile key.
-    OE_INFO << LC << "Creating " << keys.size() << " root keys.." << std::endl;
+        // create a root node for each root tile key.
+        OE_INFO << LC << "Creating " << keys.size() << " root keys.." << std::endl;
 
-    TilePagedLOD* root = new TilePagedLOD( _uid, _liveTiles, _deadTiles );
-    _terrain->addChild( root );
+        TilePagedLOD* root = new TilePagedLOD( _uid, _liveTiles, _releaser.get() );
+        root->setRangeFactor(_terrainOptions.minTileRangeFactor().get());
+        _terrain->addChild( root );
 
-    osg::ref_ptr<osgDB::Options> dbOptions = Registry::instance()->cloneOrCreateOptions();
+        osg::ref_ptr<osgDB::Options> dbOptions = Registry::instance()->cloneOrCreateOptions();
 
-    // Accumulate data from low to high resolution when necessary:
-    bool accumulate = true;
+        // Accumulate data from low to high resolution when necessary:
+        bool accumulate = true;
 
-    unsigned child = 0;
-    for( unsigned i=0; i<keys.size(); ++i )
-    {
-        osg::ref_ptr<osg::Node> node = factory->createNode( keys[i], accumulate, true, 0L );
-        if ( node.valid() )
+        unsigned child = 0;
+        for( unsigned i=0; i<keys.size(); ++i )
         {
-            root->addChild( node.get() );
-            root->setRange( child++, 0.0f, FLT_MAX );
-            root->setCenter( node->getBound().center() );
-            root->setNumChildrenThatCannotBeExpired( child );
-        }
-        else
-        {
-            OE_WARN << LC << "Couldn't make tile for root key: " << keys[i].str() << std::endl;
+            osg::ref_ptr<osg::Node> node = factory->createNode( keys[i], accumulate, true, 0L );
+            if ( node.valid() )
+            {
+                root->addChild( node.get() );
+                root->setRange( child++, 0.0f, FLT_MAX );
+                root->setCenter( node->getBound().center() );
+                root->setNumChildrenThatCannotBeExpired( child );
+            }
+            else
+            {
+                OE_WARN << LC << "Couldn't make tile for root key: " << keys[i].str() << std::endl;
+            }
         }
     }
 
-    _rootTilesRegistered = false;
-
     updateState();
 
     // Call the base class
@@ -523,7 +686,7 @@ namespace
                 }
             }
             if ( count > 0 )
-                OE_WARN << LC << "Oh no! " << count << " orphaned tiles in the reg" << std::endl;
+                OE_DEBUG << LC << "Oh no! " << count << " orphaned tiles in the reg" << std::endl;
         }
     };
 }
@@ -534,28 +697,6 @@ MPTerrainEngineNode::traverse(osg::NodeVisitor& nv)
 {
     if ( nv.getVisitorType() == nv.CULL_VISITOR )
     {
-
-#if 0 // believe this is now unnecessary
-
-        // since the root tiles are manually added, the pager never has a chance to 
-        // register the PagedLODs in their children. So we have to do it manually here.
-        if ( !_rootTilesRegistered )
-        {
-            Threading::ScopedMutexLock lock(_rootTilesRegisteredMutex);
-
-            if ( !_rootTilesRegistered )
-            {
-                osgDB::DatabasePager* pager = dynamic_cast<osgDB::DatabasePager*>(nv.getDatabaseRequestHandler());
-                if ( pager )
-                {
-                    //OE_WARN << "Registering plods." << std::endl;
-                    pager->registerPagedLODs( _terrain );
-                    _rootTilesRegistered = true;
-                }
-            }
-        }
-#endif
-
         // Inform the registry of the current frame so that Tiles have access
         // to the information.
         if ( _liveTiles.valid() && nv.getFrameStamp() )
@@ -568,8 +709,9 @@ MPTerrainEngineNode::traverse(osg::NodeVisitor& nv)
     static int c = 0;
     if ( ++c % 60 == 0 )
     {
-        OE_NOTICE << LC << "Live = " << _liveTiles->size() << ", Dead = " << _deadTiles->size() << std::endl;
+        //OE_NOTICE << LC << "Live = " << _liveTiles->size() << ", Dead = " << _deadTiles->size() << std::endl;
         _liveTiles->run( CheckForOrphans() );
+        Registry::instance()->startActivity("MP live tiles", Stringify() << _liveTiles->size());
     }
 #endif
 
@@ -601,9 +743,8 @@ MPTerrainEngineNode::getKeyNodeFactory()
             _tileModelFactory.get(),
             compiler,
             _liveTiles.get(),
-            _deadTiles.get(),
+            _releaser.get(),
             _terrainOptions,
-            _uid,
             this );
     }
 
@@ -659,7 +800,8 @@ MPTerrainEngineNode::createTile( const TileKey& key )
     const osgEarth::ElevationInterpolation& interp = _update_mapf->getMapOptions().elevationInterpolation().get();
 
     // Request a heightfield from the map, falling back on lower resolution tiles
-    osg::ref_ptr<osg::HeightField> hf;    
+    int tileSize = _terrainOptions.tileSize().get();    
+    osg::ref_ptr<osg::HeightField> hf = HeightFieldUtils::createReferenceHeightField( key.getExtent(), tileSize, tileSize );
 
     TileKey sampleKey = key;
     bool populated = false;
@@ -803,7 +945,8 @@ MPTerrainEngineNode::addImageLayer( ImageLayer* layerAdded )
             optional<std::string>& texMatUniformName = layerAdded->shareTexMatUniformName();
             if ( !texMatUniformName.isSet() )
             {
-                texMatUniformName = Stringify() << "oe_layer_" << layerAdded->getUID() << "_texmat";
+                texMatUniformName = Stringify() << "oe_layer_" << layerAdded->getUID() << "_texMatrix";
+                OE_INFO << LC << "Layer \"" << layerAdded->getName() << "\" texmat uniform = \"" << texMatUniformName.get() << "\"\n";
             }
         }
     }
@@ -888,6 +1031,8 @@ MPTerrainEngineNode::updateState()
         }
 
         osg::StateSet* terrainStateSet = getTerrainStateSet();
+        if ( !terrainStateSet )
+            return;
         
         // required for multipass tile rendering to work
         terrainStateSet->setAttributeAndModes(
@@ -905,10 +1050,6 @@ MPTerrainEngineNode::updateState()
             vp->setName( "osgEarth.engine_mp.TerrainNode" );
             terrainStateSet->setAttributeAndModes( vp, osg::StateAttribute::ON );
 
-            // bind the vertex attributes generated by the tile compiler.
-            vp->addBindAttribLocation( "oe_terrain_attr",  osg::Drawable::ATTRIBUTE_6 );
-            vp->addBindAttribLocation( "oe_terrain_attr2", osg::Drawable::ATTRIBUTE_7 );
-
             Shaders package;
 
             package.replace( "$MP_PRIMARY_UNIT",   Stringify() << _primaryUnit );
@@ -916,77 +1057,86 @@ MPTerrainEngineNode::updateState()
 
             package.define( "MP_USE_BLENDING", (_terrainOptions.enableBlending() == true) );
 
-            package.load( vp, package.VertexModel );
-            package.load( vp, package.VertexView );
-            package.load( vp, package.Fragment );
+            package.load( vp, package.EngineVertexModel );
+            package.load( vp, package.EngineVertexView );
+            package.load( vp, package.EngineFragment );
             
+            if ( this->normalTexturesRequired() )
+            {
+                package.load( vp, package.NormalMapVertex );
+                package.load( vp, package.NormalMapFragment );
+
+                terrainStateSet->addUniform( new osg::Uniform("oe_tile_normalTex", _normalMapUnit) );
+            }
 
             // terrain background color; negative means use the vertex color.
             Color terrainColor = _terrainOptions.color().getOrUse( Color(1,1,1,-1) );
             terrainStateSet->addUniform(new osg::Uniform("oe_terrain_color", terrainColor));
 
-            
-            // assemble color filter code snippets.
-            bool haveColorFilters = false;
+            if ( _update_mapf )
             {
-                // Color filter frag function:
-                std::string fs_colorfilters =
-                    "#version " GLSL_VERSION_STR "\n"
-                    GLSL_DEFAULT_PRECISION_FLOAT "\n"
-                    "uniform int oe_layer_uid; \n"
-                    "$COLOR_FILTER_HEAD"
-                    "void oe_mp_apply_filters(inout vec4 color) \n"
-                    "{ \n"
-                        "$COLOR_FILTER_BODY"
-                    "} \n";
-
-                std::stringstream cf_head;
-                std::stringstream cf_body;
-                const char* I = "    ";
-
-                // second, install the per-layer color filter functions AND shared layer bindings.
-                bool ifStarted = false;
-                int numImageLayers = _update_mapf->imageLayers().size();
-                for( int i=0; i<numImageLayers; ++i )
+                // assemble color filter code snippets.
+                bool haveColorFilters = false;
                 {
-                    ImageLayer* layer = _update_mapf->getImageLayerAt(i);
-                    if ( layer->getEnabled() )
+                    // Color filter frag function:
+                    std::string fs_colorfilters =
+                        "#version " GLSL_VERSION_STR "\n"
+                        GLSL_DEFAULT_PRECISION_FLOAT "\n"
+                        "uniform int oe_layer_uid; \n"
+                        "$COLOR_FILTER_HEAD"
+                        "void oe_mp_apply_filters(inout vec4 color) \n"
+                        "{ \n"
+                            "$COLOR_FILTER_BODY"
+                        "} \n";
+
+                    std::stringstream cf_head;
+                    std::stringstream cf_body;
+                    const char* I = "    ";
+
+                    // second, install the per-layer color filter functions AND shared layer bindings.
+                    bool ifStarted = false;
+                    int numImageLayers = _update_mapf->imageLayers().size();
+                    for( int i=0; i<numImageLayers; ++i )
                     {
-                        // install Color Filter function calls:
-                        const ColorFilterChain& chain = layer->getColorFilters();
-                        if ( chain.size() > 0 )
+                        ImageLayer* layer = _update_mapf->getImageLayerAt(i);
+                        if ( layer->getEnabled() )
                         {
-                            haveColorFilters = true;
-                            if ( ifStarted ) cf_body << I << "else if ";
-                            else             cf_body << I << "if ";
-                            cf_body << "(oe_layer_uid == " << layer->getUID() << ") {\n";
-                            for( ColorFilterChain::const_iterator j = chain.begin(); j != chain.end(); ++j )
+                            // install Color Filter function calls:
+                            const ColorFilterChain& chain = layer->getColorFilters();
+                            if ( chain.size() > 0 )
                             {
-                                const ColorFilter* filter = j->get();
-                                cf_head << "void " << filter->getEntryPointFunctionName() << "(inout vec4 color);\n";
-                                cf_body << I << I << filter->getEntryPointFunctionName() << "(color);\n";
-                                filter->install( terrainStateSet );
+                                haveColorFilters = true;
+                                if ( ifStarted ) cf_body << I << "else if ";
+                                else             cf_body << I << "if ";
+                                cf_body << "(oe_layer_uid == " << layer->getUID() << ") {\n";
+                                for( ColorFilterChain::const_iterator j = chain.begin(); j != chain.end(); ++j )
+                                {
+                                    const ColorFilter* filter = j->get();
+                                    cf_head << "void " << filter->getEntryPointFunctionName() << "(inout vec4 color);\n";
+                                    cf_body << I << I << filter->getEntryPointFunctionName() << "(color);\n";
+                                    filter->install( terrainStateSet );
+                                }
+                                cf_body << I << "}\n";
+                                ifStarted = true;
                             }
-                            cf_body << I << "}\n";
-                            ifStarted = true;
                         }
                     }
-                }
 
-                if ( haveColorFilters )
-                {
-                    std::string cf_head_str, cf_body_str;
-                    cf_head_str = cf_head.str();
-                    cf_body_str = cf_body.str();
-
-                    replaceIn( fs_colorfilters, "$COLOR_FILTER_HEAD", cf_head_str );
-                    replaceIn( fs_colorfilters, "$COLOR_FILTER_BODY", cf_body_str );
-
-                    vp->setFunction(
-                        "oe_mp_apply_filters",
-                        fs_colorfilters,
-                        ShaderComp::LOCATION_FRAGMENT_COLORING,
-                        0.5f );
+                    if ( haveColorFilters )
+                    {
+                        std::string cf_head_str, cf_body_str;
+                        cf_head_str = cf_head.str();
+                        cf_body_str = cf_body.str();
+
+                        replaceIn( fs_colorfilters, "$COLOR_FILTER_HEAD", cf_head_str );
+                        replaceIn( fs_colorfilters, "$COLOR_FILTER_BODY", cf_body_str );
+
+                        vp->setFunction(
+                            "oe_mp_apply_filters",
+                            fs_colorfilters,
+                            ShaderComp::LOCATION_FRAGMENT_COLORING,
+                            0.5f );
+                    }
                 }
             }
 
@@ -1043,16 +1193,19 @@ MPTerrainEngineNode::updateState()
                 Registry::objectIndex()->getObjectIDUniformName().c_str(), OSGEARTH_OBJECTID_TERRAIN) );
 
             // assign the uniforms for each shared layer.
-            int numImageLayers = _update_mapf->imageLayers().size();
-            for( int i=0; i<numImageLayers; ++i )
+            if ( _update_mapf )
             {
-                ImageLayer* layer = _update_mapf->getImageLayerAt(i);
-                if ( layer->getEnabled() && layer->isShared() )
+                int numImageLayers = _update_mapf->imageLayers().size();
+                for( int i=0; i<numImageLayers; ++i )
                 {
-                    terrainStateSet->addUniform( new osg::Uniform(
-                        layer->shareTexUniformName()->c_str(),
-                        layer->shareImageUnit().get() ) );
+                    ImageLayer* layer = _update_mapf->getImageLayerAt(i);
+                    if ( layer->getEnabled() && layer->isShared() )
+                    {
+                        terrainStateSet->addUniform( new osg::Uniform(
+                            layer->shareTexUniformName()->c_str(),
+                            layer->shareImageUnit().get() ) );
                         
+                    }
                 }
             }
         }
diff --git a/src/osgEarthDrivers/engine_mp/MPTerrainEngineOptions b/src/osgEarthDrivers/engine_mp/MPTerrainEngineOptions
index ff1455c..540de85 100644
--- a/src/osgEarthDrivers/engine_mp/MPTerrainEngineOptions
+++ b/src/osgEarthDrivers/engine_mp/MPTerrainEngineOptions
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -42,7 +42,9 @@ namespace osgEarth { namespace Drivers { namespace MPTerrainEngine
             _tilePixelSize     ( 256 ),
             _color             ( Color::White ),
             _incrementalUpdate ( false ),
-            _smoothing         ( false )
+            _smoothing         ( false ),
+            _normalMaps        ( false ),
+            _adaptivePolarRangeFactor( false )
          {
             setDriver( "mp" );
             fromConfig( _conf );
@@ -87,6 +89,18 @@ namespace osgEarth { namespace Drivers { namespace MPTerrainEngine
         optional<bool>& elevationSmoothing() { return _smoothing; }
         const optional<bool>& elevationSmoothing() const { return _smoothing; }
 
+        /** Whether to generate normal maps from elevation data. */
+        optional<bool>& normalMaps() { return _normalMaps; }
+        const optional<bool>& normalMaps() const { return _normalMaps; }
+
+        /**
+         * Whether to automatically adjust(reduce) the minTileRangeFactor with increase in
+         * latitude. This prevents overtessellation in the polar regions. Only works with
+         * a geocentric map. Defaults to false.
+         */
+        optional<bool>& adaptivePolarRangeFactor() { return _adaptivePolarRangeFactor; }
+        const optional<bool>& adaptivePolarRangeFactor() const { return _adaptivePolarRangeFactor; }
+
     public:
 
         /** @deprecated */
@@ -105,6 +119,8 @@ namespace osgEarth { namespace Drivers { namespace MPTerrainEngine
             conf.updateIfSet( "color", _color );
             conf.updateIfSet( "incremental_update", _incrementalUpdate );
             conf.updateIfSet( "elevation_smoothing", _smoothing );
+            conf.updateIfSet( "normal_maps", _normalMaps );
+            conf.updateIfSet( "adaptive_polar_range_factor", _adaptivePolarRangeFactor);
 
             return conf;
         }
@@ -126,6 +142,8 @@ namespace osgEarth { namespace Drivers { namespace MPTerrainEngine
             conf.getIfSet( "color", _color );
             conf.getIfSet( "incremental_update", _incrementalUpdate );
             conf.getIfSet( "elevation_smoothing", _smoothing );
+            conf.getIfSet( "normal_maps", _normalMaps );
+            conf.getIfSet( "adaptive_polar_range_factor", _adaptivePolarRangeFactor);
        }
 
         optional<float>               _skirtRatio;
@@ -137,6 +155,8 @@ namespace osgEarth { namespace Drivers { namespace MPTerrainEngine
         optional<Color>               _color;
         optional<bool>                _incrementalUpdate;
         optional<bool>                _smoothing;
+        optional<bool>                _normalMaps;
+        optional<bool>                _adaptivePolarRangeFactor;
     };
 
 } } } // namespace osgEarth::Drivers::MPTerrainEngine
diff --git a/src/osgEarthDrivers/engine_mp/MaskGenerator b/src/osgEarthDrivers/engine_mp/MaskGenerator
new file mode 100644
index 0000000..75a779c
--- /dev/null
+++ b/src/osgEarthDrivers/engine_mp/MaskGenerator
@@ -0,0 +1,81 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+* Copyright 2008-2014 Pelican Mapping
+* http://osgearth.org
+*
+* osgEarth is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public License
+* along with this program.  If not, see <http://www.gnu.org/licenses/>
+*/
+#ifndef OSGEARTH_DRIVERS_MP_MASK_GENERATOR
+#define OSGEARTH_DRIVERS_MP_MASK_GENERATOR 1
+
+#include "Common"
+#include <osgEarth/TileKey>
+#include <osg/Geometry>
+
+namespace osgEarth { namespace Drivers { namespace MPTerrainEngine
+{
+    using namespace osgEarth;
+
+    /**
+     * Record that stores the data for a single masking region.
+     */
+    struct MaskRecord
+    {
+        osg::ref_ptr<osg::Vec3dArray> _boundary;
+        osg::Vec3d                    _ndcMin, _ndcMax;
+        osg::Geometry*                _geom;
+        osg::ref_ptr<osg::Vec3Array>  _internal;
+
+        MaskRecord(osg::Vec3dArray* boundary, osg::Vec3d& ndcMin, osg::Vec3d& ndcMax, osg::Geometry* geom) 
+            : _boundary(boundary), _ndcMin(ndcMin), _ndcMax(ndcMax), _geom(geom), _internal(new osg::Vec3Array()) { }
+    };
+
+    typedef std::vector<MaskRecord> MaskRecordVector;
+
+
+    /**
+     * Creates geometry for the part of a tile containing mask data.
+     */
+    class MaskGenerator
+    {
+    public:
+        MaskGenerator(const TileKey& key);
+
+        /** whether a texcoord indicates that the corresponding vert is masked. */
+        bool isMasked(const osg::Vec3f& texCoord) const
+        {
+            return texCoord.z() == 0.0f;
+        }
+
+        /** whether the masking geometry contains a unit location. */
+        bool contains(float nx, float ny) const
+        {
+            // Placeholder for now.
+            return false;
+        }
+
+        bool containedByQuadAtColRow(int col, int row, int tileSize) const
+        {
+            // Placeholder for now.
+            return false;
+        }
+
+    protected:
+        const TileKey    _key;
+        MaskRecordVector _maskRecords;
+    };
+
+} } } // namespace osgEarth::Drivers::MPTerrainEngine
+
+#endif // OSGEARTH_DRIVERS_MP_MASK_GENERATOR
diff --git a/src/osgEarthDrivers/engine_mp/MaskGenerator.cpp b/src/osgEarthDrivers/engine_mp/MaskGenerator.cpp
new file mode 100644
index 0000000..c0d20fe
--- /dev/null
+++ b/src/osgEarthDrivers/engine_mp/MaskGenerator.cpp
@@ -0,0 +1,29 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+* Copyright 2008-2014 Pelican Mapping
+* http://osgearth.org
+*
+* osgEarth is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public License
+* along with this program.  If not, see <http://www.gnu.org/licenses/>
+*/
+#include "MaskGenerator"
+
+using namespace osgEarth::Drivers::MPTerrainEngine;
+
+#define LC "[MaskGenerator] "
+
+MaskGenerator::MaskGenerator(const TileKey& key) :
+_key( key )
+{
+    //NOP
+}
diff --git a/src/osgEarthDrivers/engine_mp/QuickReleaseGLObjects b/src/osgEarthDrivers/engine_mp/QuickReleaseGLObjects
deleted file mode 100644
index 7b5150e..0000000
--- a/src/osgEarthDrivers/engine_mp/QuickReleaseGLObjects
+++ /dev/null
@@ -1,94 +0,0 @@
-/* -*-c++-*- */
-/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
-* http://osgearth.org
-*
-* osgEarth is free software; you can redistribute it and/or modify
-* it under the terms of the GNU Lesser General Public License as published by
-* the Free Software Foundation; either version 2 of the License, or
-* (at your option) any later version.
-*
-* 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.
-*
-* You should have received a copy of the GNU Lesser General Public License
-* along with this program.  If not, see <http://www.gnu.org/licenses/>
-*/
-#ifndef OSGEARTH_DRIVERS_MP_TERRAIN_ENGINE_QUICK_RELEASE_GL_OBJECTS
-#define OSGEARTH_DRIVERS_MP_TERRAIN_ENGINE_QUICK_RELEASE_GL_OBJECTS 1
-
-#include "Common"
-#include "TileNodeRegistry"
-#include <osg/Camera>
-
-namespace osgEarth { namespace Drivers { namespace MPTerrainEngine
-{
-    /**
-     * A draw callback to calls another, nested draw callback.
-     */
-    struct NestingDrawCallback : public osg::Camera::DrawCallback
-    {
-        NestingDrawCallback( osg::Camera::DrawCallback* next ) : _next(next) { }
-
-        virtual void operator()( osg::RenderInfo& renderInfo ) const
-        {
-            dispatch( renderInfo );
-        }
-
-        void dispatch( osg::RenderInfo& renderInfo ) const
-        {
-            if ( _next )
-                _next->operator ()( renderInfo );
-        }
-
-        osg::ref_ptr<osg::Camera::DrawCallback> _next;
-    };
-
-
-    // a simple draw callback, to be installed on a Camera, that immediately releases the
-    // GL memory associated with a dead tile (instead of wating for OSG to do it in the
-    // future).
-    struct QuickReleaseGLObjects : public NestingDrawCallback
-    {
-        struct ReleaseOperation : public TileNodeRegistry::Operation
-        {
-            osg::State* _state;
-            ReleaseOperation( osg::State* state ) : _state(state) { }
-            void operator()( TileNodeRegistry::TileNodeMap& tiles )
-            {
-                unsigned size = tiles.size();
-                for( TileNodeRegistry::TileNodeMap::iterator i = tiles.begin(); i != tiles.end(); ++i )
-                {
-                    i->second.get()->releaseGLObjects( _state );
-                }
-                tiles.clear();
-                OE_DEBUG << "Quick-released " << size << " tiles" << std::endl;
-            }
-        };
-
-        QuickReleaseGLObjects( TileNodeRegistry* tiles, osg::Camera::DrawCallback* nextCB) 
-            : NestingDrawCallback( nextCB ), _tilesToRelease(tiles) { }
-
-        // from DrawCallback
-        void operator()( osg::RenderInfo& renderInfo ) const
-        {
-            dispatch( renderInfo );
-
-            if ( !_tilesToRelease->empty() )
-            {
-                ReleaseOperation op(renderInfo.getState());
-                _tilesToRelease->run( op );
-            }
-        }
-
-        osg::ref_ptr<TileNodeRegistry> _tilesToRelease;
-    };
-
-} } } // namespace
-
-#endif // OSGEARTH_DRIVERS_MP_TERRAIN_ENGINE_QUICK_RELEASE_GL_OBJECTS
diff --git a/src/osgEarthDrivers/engine_mp/RenderBindings b/src/osgEarthDrivers/engine_mp/RenderBindings
new file mode 100644
index 0000000..c1ef017
--- /dev/null
+++ b/src/osgEarthDrivers/engine_mp/RenderBindings
@@ -0,0 +1,70 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+ * Copyright 2008-2014 Pelican Mapping
+ * http://osgearth.org
+ *
+ * osgEarth is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ */
+#ifndef OSGEARTH_DRIVERS_MP_RENDER_BINDINGS_H
+#define OSGEARTH_DRIVERS_MP_RENDER_BINDINGS_H 1
+
+#include "Common"
+
+namespace osgEarth { namespace Drivers { namespace MPTerrainEngine
+{
+    class SamplerBinding
+    {
+    public:
+        SamplerBinding() : _unit(-1) { }
+
+        int& unit() { return _unit; }
+        const int& unit() const { return _unit; }
+
+        std::string& samplerName() { return _samplerName; }
+        const std::string& samplerName() const { return _samplerName; }
+
+        std::string& matrixName() { return _matrixName; }
+        const std::string& matrixName() const { return _matrixName; }
+
+    private:
+        int         _unit;
+        std::string _samplerName;
+        std::string _matrixName;
+    };
+
+    class RenderBindings
+    {
+    public:
+        SamplerBinding& color() { return _colorBinding; }
+        const SamplerBinding& color() const { return _colorBinding; }
+
+        SamplerBinding& parentColor() { return _parentColorBinding; }
+        const SamplerBinding& parentColor() const { return _parentColorBinding; }
+
+        SamplerBinding& elevation() { return _elevationBinding; }
+        const SamplerBinding& elevation() const { return _elevationBinding; }
+
+        SamplerBinding& parentElevation() { return _parentElevationBinding; }
+        const SamplerBinding& parentElevation() const { return _parentElevationBinding; }
+
+    private:
+        SamplerBinding _colorBinding;
+        SamplerBinding _parentColorBinding;
+        SamplerBinding _elevationBinding;
+        SamplerBinding _parentElevationBinding;
+    };
+
+} } } // namespace osgEarth::Drivers::MPTerrainEngine
+
+#endif // OSGEARTH_DRIVERS_MP_RENDER_BINDINGS_H
\ No newline at end of file
diff --git a/src/osgEarthDrivers/engine_mp/SingleKeyNodeFactory b/src/osgEarthDrivers/engine_mp/SingleKeyNodeFactory
index c9ab6d7..f677943 100644
--- a/src/osgEarthDrivers/engine_mp/SingleKeyNodeFactory
+++ b/src/osgEarthDrivers/engine_mp/SingleKeyNodeFactory
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
@@ -30,6 +30,8 @@
 #include "TileNodeRegistry"
 #include <osgEarth/Map>
 #include <osgEarth/Progress>
+#include <osgEarth/TerrainEngineNode>
+#include <osgEarth/ResourceReleaser>
 
 using namespace osgEarth;
 
@@ -43,10 +45,9 @@ namespace osgEarth { namespace Drivers { namespace MPTerrainEngine
             TileModelFactory*                   modelFactory,
             TileModelCompiler*                  modelCompiler,
             TileNodeRegistry*                   liveTiles,
-            TileNodeRegistry*                   deadTiles,
+            ResourceReleaser*                   releaser,
             const MPTerrainEngineOptions&       options,
-            UID                                 engineUID,
-            TerrainTileNodeBroker*              tileNodeBroker );
+            TerrainEngine*                      terrainEngine );
 
         /** dtor */
         virtual ~SingleKeyNodeFactory() { }
@@ -80,11 +81,9 @@ namespace osgEarth { namespace Drivers { namespace MPTerrainEngine
         osg::ref_ptr<TileModelFactory>      _modelFactory;
         osg::ref_ptr<TileModelCompiler>     _modelCompiler;
         osg::ref_ptr<TileNodeRegistry>      _liveTiles;
-        osg::ref_ptr<TileNodeRegistry>      _deadTiles;
+        osg::ref_ptr<ResourceReleaser>      _releaser;
         const MPTerrainEngineOptions&       _options;
-        UID                                 _engineUID;
-        TerrainTileNodeBroker*              _tileNodeBroker;
-        bool                                _debug;
+        TerrainEngine*                      _engine;
 
         unsigned getMinimumRequiredLevel();
     };
diff --git a/src/osgEarthDrivers/engine_mp/SingleKeyNodeFactory.cpp b/src/osgEarthDrivers/engine_mp/SingleKeyNodeFactory.cpp
index bdc069f..25bf2bf 100644
--- a/src/osgEarthDrivers/engine_mp/SingleKeyNodeFactory.cpp
+++ b/src/osgEarthDrivers/engine_mp/SingleKeyNodeFactory.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
@@ -38,87 +38,24 @@ using namespace osgEarth;
 
 #define LC "[SingleKeyNodeFactory] "
 
-namespace
-{
-    /**
-     * Culling callback for terrain tiles.
-     *
-     * It performs a horizon-visibility test against the highest four corners of
-     * the tile's bounding box.
-
-     * This is an alternative to the old cluster culling callback.
-     */
-    struct HorizonTileCuller : public osg::NodeCallback
-    {
-        Horizon    _horizonPrototype;
-        osg::Vec3d _points[4];
-
-        HorizonTileCuller(const SpatialReference* srs, const osg::BoundingBox& bbox, const osg::Matrix& m)
-        {
-            _horizonPrototype.setEllipsoid(*srs->getEllipsoid());
-
-            // Adjust the horizon ellipsoid based on the minimum Z value of the tile;
-            // necessary because a tile that's below the ellipsoid (ocean floor, e.g.)
-            // may be visible even if it doesn't pass the horizon-cone test. In such
-            // cases we need a more conservative ellipsoid.
-            double zMin = bbox.corner(0).z();
-            if ( zMin < 0.0 )
-            {
-                _horizonPrototype.setEllipsoid(osg::EllipsoidModel(
-                    srs->getEllipsoid()->getRadiusEquator() + zMin,
-                    srs->getEllipsoid()->getRadiusPolar()   + zMin));
-            }
-            
-
-            // consider the uppermost 4 points of the tile-aligned bounding box.
-            // (the last four corners of the bbox are the "zmax" corners.)
-            for(unsigned i=0; i<4; ++i)
-            {
-                _points[i] = bbox.corner(4+i) * m;
-            }
-        }
-
-        void operator()(osg::Node* node, osg::NodeVisitor* nv)
-        {
-            // Clone the horizon object to support multiple cull threads
-            // (since we call setEye with the current node visitor eye point)
-            Horizon horizon(_horizonPrototype);
-
-            // Since each terrain tile has an aboslute reference frame, 
-            // there is no need to transform the eyepoint:
-            horizon.setEye(nv->getViewPoint()); // * osg::computeLocalToWorld(nv->getNodePath()));
-            
-            for(unsigned i=0; i<4; ++i)
-            {                   
-                if ( !horizon.occludes(_points[i]) )
-                {
-                    traverse(node, nv);
-                    break;
-                }
-            }
-        }
-    };
-}
 
 
 SingleKeyNodeFactory::SingleKeyNodeFactory(const Map*                    map,
                                            TileModelFactory*             modelFactory,
                                            TileModelCompiler*            modelCompiler,
                                            TileNodeRegistry*             liveTiles,
-                                           TileNodeRegistry*             deadTiles,
+                                           ResourceReleaser*             releaser,
                                            const MPTerrainEngineOptions& options,
-                                           UID                           engineUID,
-                                           TerrainTileNodeBroker*        tileNodeBroker ) :
+                                           TerrainEngine*                engine ) :
 _frame           ( map ),
 _modelFactory    ( modelFactory ),
 _modelCompiler   ( modelCompiler ),
 _liveTiles       ( liveTiles ),
-_deadTiles       ( deadTiles ),
+_releaser        ( releaser ),
 _options         ( options ),
-_engineUID       ( engineUID ),
-_tileNodeBroker  ( tileNodeBroker )
+_engine          ( engine )
 {
-    _debug = _options.debug() == true;
+    //nop
 }
 
 unsigned
@@ -164,7 +101,6 @@ SingleKeyNodeFactory::createTile(TileModel*        model,
 #else
     // compile the model into a node:
     TileNode* tileNode = _modelCompiler->compile(model, _frame, progress);
-    tileNode->setEngineUID( _engineUID );
 #endif
 
     // see if this tile might have children.
@@ -177,11 +113,30 @@ SingleKeyNodeFactory::createTile(TileModel*        model,
     if ( prepareForChildren )
     {
         osg::BoundingSphere bs = tileNode->getBound();
-        TilePagedLOD* plod = new TilePagedLOD( _engineUID, _liveTiles, _deadTiles );
+        TilePagedLOD* plod = new TilePagedLOD( _engine->getUID(), _liveTiles.get(), _releaser.get() );
         plod->setCenter  ( bs.center() );
         plod->addChild   ( tileNode );
-        plod->setFileName( 1, Stringify() << tileNode->getKey().str() << "." << _engineUID << ".osgearth_engine_mp_tile" );
-        plod->setDebug   ( _debug );
+        plod->setFileName( 1, Stringify() << tileNode->getKey().str() << "." << _engine->getUID() << ".osgearth_engine_mp_tile" );
+        
+        double rangeFactor = _options.minTileRangeFactor().get();
+        if (_options.adaptivePolarRangeFactor() == true)
+        {
+            double lat = model->_tileKey.getExtent().yMin() < 0 ? -model->_tileKey.getExtent().yMax() : model->_tileKey.getExtent().yMin();
+            double latRad = osg::DegreesToRadians(lat);
+            rangeFactor -= (rangeFactor - 1.0)*sin(latRad)*sin(latRad);
+        }
+        plod->setRangeFactor(rangeFactor);
+
+        // Setup expiration.
+        if (_options.minExpiryFrames().isSet())
+        {
+            plod->setMinimumExpiryFrames(1, *_options.minExpiryFrames());
+        }
+        
+        if (_options.minExpiryTime().isSet())
+        {         
+            plod->setMinimumExpiryTime(1, *_options.minExpiryTime());
+        }      
 
         if ( _options.rangeMode().value() == osg::LOD::DISTANCE_FROM_EYE_POINT )
         {
@@ -213,7 +168,8 @@ SingleKeyNodeFactory::createTile(TileModel*        model,
                 radius = (ur - ll).length() / 2.0;
             }
           
-            float minRange = (float)(radius * _options.minTileRangeFactor().value());
+            //float minRange = (float)(radius * _options.minTileRangeFactor().value());
+            float minRange = radius;
 
             plod->setRange( 0, minRange, FLT_MAX );
             plod->setRange( 1, 0, minRange );
@@ -250,8 +206,6 @@ SingleKeyNodeFactory::createTile(TileModel*        model,
         // this one rejects back-facing tiles:
         if ( _frame.getMapInfo().isGeocentric() && _options.clusterCulling() == true )
         {
-
-#if 1
             osg::HeightField* hf =
                 model->_elevationData.getHeightField();
 
@@ -259,14 +213,6 @@ SingleKeyNodeFactory::createTile(TileModel*        model,
                 hf,
                 tileNode->getKey().getProfile()->getSRS()->getEllipsoid(),
                 *_options.verticalScale() ) );
-#else
-            // This works, but isn't quite as tight at the cluster culler.
-            // Re-evaluate down the road.
-            result->addCullCallback( new HorizonTileCuller(
-                _frame.getMapInfo().getSRS(),
-                tileNode->getTerrainBoundingBox(),
-                tileNode->getMatrix(), tileNode->getKey() ) );
-#endif
         }
     }
     else
@@ -352,7 +298,7 @@ SingleKeyNodeFactory::createNode(const TileKey&    key,
     {
         if ( _options.incrementalUpdate() == true )
         {
-            quad = new TileGroup(key, _engineUID, _liveTiles.get(), _deadTiles.get());
+            quad = new TileGroup(key, _engine->getUID(), _liveTiles.get(), _releaser.get());
         }
         else
         {
@@ -362,7 +308,7 @@ SingleKeyNodeFactory::createNode(const TileKey&    key,
         for( unsigned q=0; q<4; ++q )
         {
             osg::ref_ptr<osg::Node> tile = createTile(model[q].get(), setupChildren, progress);
-            _tileNodeBroker->notifyOfTerrainTileNodeCreation( model[q]->_tileKey, tile.get() );
+            _engine->notifyOfTerrainTileNodeCreation( model[q]->_tileKey, tile.get() );
             quad->addChild( tile.get() );
         }
     }
diff --git a/src/osgEarthDrivers/engine_mp/SurfaceNode b/src/osgEarthDrivers/engine_mp/SurfaceNode
new file mode 100644
index 0000000..a0312a5
--- /dev/null
+++ b/src/osgEarthDrivers/engine_mp/SurfaceNode
@@ -0,0 +1,53 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+* Copyright 2008-2014 Pelican Mapping
+* http://osgearth.org
+*
+* osgEarth is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public License
+* along with this program.  If not, see <http://www.gnu.org/licenses/>
+*/
+#ifndef OSGEARTH_DRIVERS_MP_SURFACE_NODE
+#define OSGEARTH_DRIVERS_MP_SURFACE_NODE 1
+
+#include "Common"
+#include <osg/MatrixTransform>
+#include <osg/BoundingBox>
+
+namespace osgEarth { namespace Drivers { namespace MPTerrainEngine
+{
+    using namespace osgEarth;
+
+    /**
+     * SurfaceNode holds the geometry of the terrain surface.
+     */
+    class SurfaceNode : public osg::MatrixTransform
+    {
+    public:
+        SurfaceNode() { }
+
+        void setEngineUID(const UID& uid) { _engineUID = uid; }
+        const UID& getEngineUID() const { return _engineUID; }
+
+        void setBoundingBox(const osg::BoundingBox& bbox) { _bbox = bbox; }
+        const osg::BoundingBox& getBoundingBox() const { return _bbox; }
+
+    protected:
+        virtual ~SurfaceNode() { }
+
+        osg::BoundingBox _bbox;
+        UID              _engineUID;
+    };
+
+} } } // namespace osgEarth::Drivers::MPTerrainEngine
+
+#endif // OSGEARTH_DRIVERS_MP_SURFACE_NODE
diff --git a/src/osgEarthDrivers/engine_mp/SurfaceNode.cpp b/src/osgEarthDrivers/engine_mp/SurfaceNode.cpp
new file mode 100644
index 0000000..e69de29
diff --git a/src/osgEarthDrivers/engine_mp/SurfaceNodeFactory b/src/osgEarthDrivers/engine_mp/SurfaceNodeFactory
new file mode 100644
index 0000000..6839720
--- /dev/null
+++ b/src/osgEarthDrivers/engine_mp/SurfaceNodeFactory
@@ -0,0 +1,130 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+* Copyright 2008-2014 Pelican Mapping
+* http://osgearth.org
+*
+* osgEarth is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public License
+* along with this program.  If not, see <http://www.gnu.org/licenses/>
+*/
+#ifndef OSGEARTH_DRIVERS_MP_SURFACE_NODE_FACTORY
+#define OSGEARTH_DRIVERS_MP_SURFACE_NODE_FACTORY 1
+
+#include "Common"
+#include "SurfaceNode"
+#include "MPTerrainEngineOptions"
+#include "MaskGenerator"
+#include "GeometryPool"
+#include "TileDrawable"
+#include "RenderBindings"
+#include "MPGeometry"
+#include <osg/Geode>
+
+// forward declares
+namespace osgEarth {
+    class MapFrame;
+    class TerrainTileModel;
+    class ProgressCallback;
+}
+
+namespace osgEarth { namespace Drivers { namespace MPTerrainEngine
+{
+    using namespace osgEarth;
+    class MPGeometry;
+
+    /**
+     * Interface for an object that can build a SurfaceNode from a
+     * TerrainTileModel.
+     */
+    class SurfaceNodeFactory : public osg::Referenced
+    {
+    public:
+        SurfaceNodeFactory(
+            const TerrainTileModel*       model,
+            const MapFrame&               frame,
+            const RenderBindings&         bindings,
+            GeometryPool*                 geometryPool,
+            unsigned                      tileSize,
+            const MPTerrainEngineOptions& options);
+
+        /**
+         * Uses a TerrainTileModel to build a new SurfaceNode from data
+         * in a MapFrame.
+         */
+        virtual SurfaceNode* createSurfaceNode();
+
+    protected:
+        /** Creates a new empty surface mesh in the context. */
+        void addSurfaceMesh();
+
+        /** Adds a skirt mesh to the existing geometry */
+        void addSkirtMesh();
+
+        /** Sets up the MP geometry with the color layers to render. */
+        void installColorLayers();
+
+        /** Adds a surface and mesh skirt from the geometry pool.
+            Will not work with masked tiles. */
+        void addSharedMeshes();
+        
+    protected:
+        /** Convert unit [0..1] to world coords. */
+        osg::Vec3d unitToWorld(const osg::Vec3d& input) const;
+
+        /** Convert unit [0..1] to tile local tangent plane coords. */
+        osg::Vec3d unitToLocal(const osg::Vec3d& input) const;
+
+        /** Whether the vertex at the corresponding index is marked for masking. */
+        bool vertIsMasked(unsigned index) const;
+
+        /** Allocates a new DrawElements based on the size of the geometry. */
+        osg::DrawElements* newDrawElements(GLenum mode) const;
+
+        void addSkirtDataForIndex(
+            unsigned index,
+            float    skirtHeight );
+
+        void addSkirtTriangles(
+            unsigned index0,
+            unsigned index1,
+            osg::DrawElements* elements);
+
+        /** Computes a bounding box to use for the new surface node, taking into
+            account things like elevation textures */
+        osg::BoundingBox computeBoundingBox() const;
+
+    protected:
+        const TerrainTileModel*       _model;
+        const MapFrame&               _frame;
+        osg::ref_ptr<GeoLocator>      _locator;
+        osg::Matrix                   _world2local, _local2world;
+        const MPTerrainEngineOptions& _options;
+        unsigned                      _tileSize;
+        MaskGenerator                 _maskSet;
+        osg::ref_ptr<osg::Geode>      _geode;
+        osg::ref_ptr<TileDrawable>    _tileDrawable;
+        osg::ref_ptr<MPGeometry>      _surfaceGeom;
+        osg::DrawElements*            _surfacePrimSet;
+        osg::Vec3Array*               _verts;
+        osg::Vec3Array*               _normals;
+        osg::Vec3Array*               _texCoords;
+        bool                          _requireUInt;
+        bool                          _createSkirt;
+        unsigned                      _numVerts;
+        osg::BoundingSphere           _tileBound;
+        const RenderBindings          _bindings;
+        osg::ref_ptr<GeometryPool>    _geometryPool;
+    };
+
+} } } // namespace osgEarth::Drivers::MPTerrainEngine
+
+#endif // OSGEARTH_DRIVERS_MP_SURFACE_NODE_FACTORY
diff --git a/src/osgEarthDrivers/engine_mp/SurfaceNodeFactory.cpp b/src/osgEarthDrivers/engine_mp/SurfaceNodeFactory.cpp
new file mode 100644
index 0000000..4aa7412
--- /dev/null
+++ b/src/osgEarthDrivers/engine_mp/SurfaceNodeFactory.cpp
@@ -0,0 +1,344 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+* Copyright 2008-2014 Pelican Mapping
+* http://osgearth.org
+*
+* osgEarth is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public License
+* along with this program.  If not, see <http://www.gnu.org/licenses/>
+*/
+#include "SurfaceNodeFactory"
+#include "MPGeometry"
+#include <osg/ComputeBoundsVisitor>
+
+using namespace osgEarth::Drivers::MPTerrainEngine;
+
+#define LC "[SurfaceNodeFactory] "
+
+
+SurfaceNodeFactory::SurfaceNodeFactory(const TerrainTileModel*       model,
+                                       const MapFrame&               frame,
+                                       const RenderBindings&         bindings,
+                                       GeometryPool*                 geometryPool,
+                                       unsigned                      tileSize,
+                                       const MPTerrainEngineOptions& options) :
+_model       ( model ),
+_frame       ( frame ),
+_bindings    ( bindings ),
+_geometryPool( geometryPool ),
+_tileSize    ( tileSize ),
+_options     ( options ),
+_requireUInt ( false ),
+_maskSet     ( model->getKey() )
+{
+    // Create a locator for transforming coordinates between unit [0..1]
+    // and world coordinates:
+    _locator = GeoLocator::createForKey(
+        _model->getKey(),
+        _frame.getMapInfo());
+    
+    // Establish a local reference frame for the tile:
+    osg::Vec3d centerWorld;
+    GeoPoint centroid;
+    _model->getKey().getExtent().getCentroid(centroid);
+    centroid.toWorld(centerWorld);
+    osg::Matrix world2local;
+    centroid.createWorldToLocal(_world2local);
+    _local2world.invert(_world2local);
+
+    // Tile size:
+    _tileSize = 17;
+
+    // Attempt to calculate the number of verts in the surface geometry.
+    _createSkirt = _options.heightFieldSkirtRatio() > 0.0f;
+    unsigned numVertsInSkirt = _createSkirt ? _tileSize*4u - 4u : 0;
+    _numVerts = (_tileSize*_tileSize) + numVertsInSkirt;
+    
+    unsigned numIndiciesInSurface = (_tileSize-1) * (_tileSize-1) * 6;
+    unsigned numIncidesInSkirt   = _createSkirt ? (_tileSize-1) * 4 * 6 : 0;
+    
+    // Pre-allocate enought space for all triangles.
+    _surfacePrimSet = newDrawElements(GL_TRIANGLES);
+    _surfacePrimSet->reserveElements(numIndiciesInSurface + numIncidesInSkirt);
+}
+
+SurfaceNode*
+SurfaceNodeFactory::createSurfaceNode()
+{
+    _geode = new osg::Geode();
+
+    if ( _geometryPool.valid() )
+    {
+        osg::ref_ptr<osg::Geometry> geom;
+        _geometryPool->getPooledGeometry( _model->getKey(), _frame.getMapInfo(), geom );
+
+        TileDrawable* drawable = new TileDrawable(
+            _model->getKey(),
+            _frame,
+            _bindings,
+            geom.get() );
+        
+        for(TerrainTileImageLayerModelVector::const_iterator i = _model->colorLayers().begin();
+            i != _model->colorLayers().end();
+            ++i)
+        {
+            TileDrawable::Layer r;
+            r._tex = i->get()->getTexture();
+            r._texMatrix = i->get()->getMatrix();
+            r._imageLayer = i->get()->getImageLayer();
+            r._layerID = r._imageLayer ? r._imageLayer->getUID() : -1;
+            drawable->_layers.push_back(r);
+        }
+
+        _geode->addDrawable( drawable );
+    }
+    else
+    {
+        addSurfaceMesh();
+        addSkirtMesh();
+        installColorLayers();
+        _geode->addDrawable( _surfaceGeom.get() );
+    }
+    
+    _geode->getDrawable(0)->setInitialBound( computeBoundingBox() );
+
+    SurfaceNode* node = new SurfaceNode();
+    node->setMatrix( _local2world );
+    node->addChild( _geode.get() );
+
+    return node;
+}
+
+void
+SurfaceNodeFactory::addSurfaceMesh()
+{
+    _tileBound.init();
+
+    // the geometry:
+    _surfaceGeom = new MPGeometry( _model->getKey(), _frame, 0 );
+    _geode->addDrawable( _surfaceGeom );
+
+    // the vertex locations:
+    _verts = new osg::Vec3Array();
+    _verts->reserve( _numVerts );
+    _surfaceGeom->setVertexArray( _verts );
+
+    // the surface normals (i.e. extrusion vectors)
+    _normals = new osg::Vec3Array();
+    _normals->reserve( _numVerts );
+    _surfaceGeom->setNormalArray( _normals );
+
+    // tex coord is [0..1] across the tile. The 3rd dimension tracks whether the
+    // vert is masked: 0=yes, 1=no
+    _texCoords = new osg::Vec3Array();
+    _texCoords->reserve( _numVerts );
+    _surfaceGeom->setTexCoordArray( 0, _texCoords );
+
+    for(unsigned row=0; row<_tileSize; ++row)
+    {
+        float ny = (float)row/(float)(_tileSize-1);
+        for(unsigned col=0; col<_tileSize; ++col)
+        {
+            float nx = (float)col/(float)(_tileSize-1);
+
+            osg::Vec3d model;
+            _locator->unitToModel(osg::Vec3d(nx, ny, 0.0f), model);
+            osg::Vec3d modelLTP = model*_world2local;
+            _verts->push_back( modelLTP );
+            _tileBound.expandBy( _verts->back() );
+
+            bool masked = _maskSet.contains(nx, ny);            
+            _texCoords->push_back( osg::Vec3f(nx, ny, masked? 0.0f : 1.0f) );
+
+            osg::Vec3d modelPlusOne;
+            _locator->unitToModel(osg::Vec3d(nx, ny, 1.0f), modelPlusOne);
+            osg::Vec3f normal = (modelPlusOne*_world2local)-modelLTP;
+            normal.normalize();
+            _normals->push_back( normal );
+        }
+    }
+
+    // Now tessellate the surface.
+
+     // Put it first so it can "early-z" the skirts.
+    _surfaceGeom->insertPrimitiveSet(0, _surfacePrimSet);
+    
+    // TODO: do we really need this??
+    bool swapOrientation = !_locator->orientationOpenGL();
+
+    for(unsigned j=0; j<_tileSize-1; ++j)
+    {
+        for(unsigned i=0; i<_tileSize-1; ++i)
+        {
+            int i00;
+            int i01;
+            if (swapOrientation)
+            {
+                i01 = j*_tileSize + i;
+                i00 = i01+_tileSize;
+            }
+            else
+            {
+                i00 = j*_tileSize + i;
+                i01 = i00+_tileSize;
+            }
+
+            int i10 = i00+1;
+            int i11 = i01+1;
+
+            // If the quad does not intersect a mask, tessellate it; otherwise skip it
+            // since the mask generator will take care of it.
+            if (!vertIsMasked(i00) && !vertIsMasked(i01) &&
+                !vertIsMasked(i10) && !vertIsMasked(i11) &&
+                !_maskSet.containedByQuadAtColRow(i, j, _tileSize) )
+            {
+                _surfacePrimSet->addElement(i01);
+                _surfacePrimSet->addElement(i00);
+                _surfacePrimSet->addElement(i11);
+
+                _surfacePrimSet->addElement(i00);
+                _surfacePrimSet->addElement(i10);
+                _surfacePrimSet->addElement(i11);
+            }
+        }
+    }
+}
+
+void
+SurfaceNodeFactory::addSkirtDataForIndex(unsigned index,
+                                         float    skirtHeight)
+{
+    _verts->push_back( (*_verts)[index] );
+    _normals->push_back( (*_normals)[index] );
+    _texCoords->push_back( (*_texCoords)[index] );
+
+    _verts->push_back( (*_verts)[index] - ((*_normals)[index])*skirtHeight );
+    _normals->push_back( (*_normals)[index] );
+    _texCoords->push_back( (*_texCoords)[index] );
+}
+
+void
+SurfaceNodeFactory::addSkirtTriangles(unsigned           index0,
+                                      unsigned           index1,
+                                      osg::DrawElements* elements)
+{
+    if ( !vertIsMasked(index0) && !vertIsMasked(index1) )
+    {
+        elements->addElement(index0);
+        elements->addElement(index0+1);
+        elements->addElement(index1);
+
+        elements->addElement(index1);
+        elements->addElement(index0+1);
+        elements->addElement(index1+1);
+    }
+}
+
+void
+SurfaceNodeFactory::addSkirtMesh()
+{
+    // calculate the skirt extrusion height
+    double height = _tileBound.radius() * _options.heightFieldSkirtRatio().get();
+        
+    unsigned skirtIndex = _verts->size();
+
+    // first, create all the skirt verts, normals, and texcoords.
+    for(int c=0; c<(int)_tileSize-1; ++c)
+        addSkirtDataForIndex( c, height ); //top
+
+    for(int r=0; r<(int)_tileSize-1; ++r)
+        addSkirtDataForIndex( r*_tileSize+(_tileSize-1), height ); //right
+    
+    for(int c=_tileSize-1; c>=0; --c)
+        addSkirtDataForIndex( (_tileSize-1)*_tileSize+c, height ); //bottom
+
+    for(int r=_tileSize-1; r>=0; --r)
+        addSkirtDataForIndex( r*_tileSize, height ); //left
+    
+    // then create the elements indices:
+    int i;
+    for(i=skirtIndex; i<(int)_verts->size()-2; i+=2)
+        addSkirtTriangles( i, i+2, _surfacePrimSet );
+
+    addSkirtTriangles( i, skirtIndex, _surfacePrimSet );
+}
+
+void
+SurfaceNodeFactory::installColorLayers()
+{
+    for(TerrainTileImageLayerModelVector::const_iterator i = _model->colorLayers().begin();
+        i != _model->colorLayers().end();
+        ++i)
+    {
+        MPGeometry::Layer r;
+        r._tex = i->get()->getTexture();
+        r._texMatrix = i->get()->getMatrix();
+        r._imageLayer = i->get()->getImageLayer();
+        r._layerID = r._imageLayer ? r._imageLayer->getUID() : -1;
+        _surfaceGeom->_layers.push_back(r);
+    }
+}
+
+osg::BoundingBox
+SurfaceNodeFactory::computeBoundingBox() const
+{
+    osg::ComputeBoundsVisitor cbv;
+    _geode->accept( cbv );
+
+    if ( _model->elevationModel().valid() )
+    {
+        if ( _model->elevationModel()->getMaxHeight() > cbv.getBoundingBox().zMax() )
+        {
+            cbv.getBoundingBox().zMax() = _model->elevationModel()->getMaxHeight();
+        }
+        if ( _model->elevationModel()->getMinHeight() < cbv.getBoundingBox().zMin() )
+        {
+            cbv.getBoundingBox().zMin() = _model->elevationModel()->getMinHeight();
+        }
+    } 
+
+    return cbv.getBoundingBox();
+}
+
+osg::Vec3d 
+SurfaceNodeFactory::unitToWorld(const osg::Vec3d& input) const
+{
+    osg::Vec3d model;
+    _locator->unitToModel( input, model );
+    return model;
+}
+
+osg::Vec3d 
+SurfaceNodeFactory::unitToLocal(const osg::Vec3d& input) const
+{
+    osg::Vec3d model;
+    _locator->unitToModel( input, model );
+    return model * _world2local;
+}
+
+bool
+SurfaceNodeFactory::vertIsMasked(unsigned index) const
+{
+    return
+        _texCoords && 
+        _texCoords->size() > index &&
+        (*_texCoords)[index].z() == 0.0f;
+}
+
+osg::DrawElements*
+SurfaceNodeFactory::newDrawElements(GLenum mode) const
+{
+    if ( _requireUInt )
+        return new osg::DrawElementsUInt(mode);
+    else
+        return new osg::DrawElementsUShort(mode);
+}
diff --git a/src/osgEarthDrivers/engine_mp/TerrainNode b/src/osgEarthDrivers/engine_mp/TerrainNode
index 51d3fab..3900482 100644
--- a/src/osgEarthDrivers/engine_mp/TerrainNode
+++ b/src/osgEarthDrivers/engine_mp/TerrainNode
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
@@ -37,24 +37,11 @@ namespace osgEarth { namespace Drivers { namespace MPTerrainEngine
     class TerrainNode : public osg::Group
     {
     public:
-
-        /**
-         * Constructs a new terrain node.
-         * @param[in ] deadTiles If non-NULL, the terrain node will active GL object
-         *             quick-release and use this registry to track dead tiles.
-         */
-        TerrainNode( TileNodeRegistry* deadTiles );
-
-    public: // osg::Node
-
-        virtual void traverse( osg::NodeVisitor &nv );
+        TerrainNode();
 
     protected:
 
         virtual ~TerrainNode() { }
-
-        osg::ref_ptr<TileNodeRegistry> _tilesToQuickRelease;
-        bool _quickReleaseCallbackInstalled;
     };
 
 } } } // namespace osgEarth::Drivers::MPTerrainEngine
diff --git a/src/osgEarthDrivers/engine_mp/TerrainNode.cpp b/src/osgEarthDrivers/engine_mp/TerrainNode.cpp
index 61c7617..0966ac2 100644
--- a/src/osgEarthDrivers/engine_mp/TerrainNode.cpp
+++ b/src/osgEarthDrivers/engine_mp/TerrainNode.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
@@ -20,70 +20,14 @@
 * along with this program.  If not, see <http://www.gnu.org/licenses/>
 */
 #include "TerrainNode"
-#include "QuickReleaseGLObjects"
-
-#include <osgEarth/Registry>
-#include <osgEarth/Map>
-#include <osgEarth/NodeUtils>
-#include <osgEarth/ThreadingUtils>
-
-#include <osg/NodeCallback>
-#include <osg/NodeVisitor>
-#include <osg/Node>
-#include <osgGA/EventVisitor>
 
 using namespace osgEarth::Drivers::MPTerrainEngine;
-using namespace osgEarth;
-using namespace OpenThreads;
 
 #define LC "[TerrainNode] "
 
 //----------------------------------------------------------------------------
 
-TerrainNode::TerrainNode(TileNodeRegistry* removedTiles ) :
-_tilesToQuickRelease            ( removedTiles ),
-_quickReleaseCallbackInstalled  ( false )
-{
-    // tick the update count to install the quick release callback:
-    if ( _tilesToQuickRelease.valid() )
-    {
-        ADJUST_UPDATE_TRAV_COUNT( this, 1 );
-    }
-}
-
-
-void
-TerrainNode::traverse( osg::NodeVisitor &nv )
+TerrainNode::TerrainNode()
 {
-    if ( nv.getVisitorType() == nv.UPDATE_VISITOR )
-    {
-        // if the terrain engine requested "quick release", install the quick release
-        // draw callback now.
-        if ( !_quickReleaseCallbackInstalled && _tilesToQuickRelease.valid() )
-        {
-            osg::Camera* cam = findFirstParentOfType<osg::Camera>( this );
-            if ( cam )
-            {
-                // get the installed PDC so we can nest them:
-                osg::Camera::DrawCallback* cbToNest = cam->getPostDrawCallback();
-
-                // if it's another QR callback, we'll just replace it.
-                QuickReleaseGLObjects* previousQR = dynamic_cast<QuickReleaseGLObjects*>(cbToNest);
-                if ( previousQR )
-                    cbToNest = previousQR->_next.get();
-
-                cam->setPostDrawCallback( new QuickReleaseGLObjects(
-                    _tilesToQuickRelease.get(),
-                    cbToNest ) );
-
-                _quickReleaseCallbackInstalled = true;
-                OE_INFO << LC << "Quick release enabled" << std::endl;
-
-                // knock down the trav count set in the constructor.
-                ADJUST_UPDATE_TRAV_COUNT( this, -1 );
-            }
-        }
-    }
-
-    osg::Group::traverse( nv );
+    //nop
 }
diff --git a/src/osgEarthDrivers/engine_mp/TileDrawable b/src/osgEarthDrivers/engine_mp/TileDrawable
new file mode 100644
index 0000000..a8d1651
--- /dev/null
+++ b/src/osgEarthDrivers/engine_mp/TileDrawable
@@ -0,0 +1,156 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+* Copyright 2008-2014 Pelican Mapping
+* http://osgearth.org
+*
+* osgEarth is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public License
+* along with this program.  If not, see <http://www.gnu.org/licenses/>
+*/
+#ifndef OSGEARTH_DRIVERS_MP_TERRAIN_ENGINE_TILE_DRAWABLE
+#define OSGEARTH_DRIVERS_MP_TERRAIN_ENGINE_TILE_DRAWABLE 1
+
+#include "Common"
+#include "TileNode"
+#include "TileNodeRegistry"
+#include "RenderBindings"
+
+#include <osg/Geometry>
+#include <osg/buffered_value>
+#include <osgEarth/Map>
+#include <osgEarth/MapFrame>
+
+using namespace osgEarth;
+
+namespace osgEarth { namespace Drivers { namespace MPTerrainEngine
+{
+    /**
+     * A Geometry that will draw its primitive sets multiple time,
+     * once for each configured "layer". For rendering multipass
+     * data from a single cull.
+     */
+    class TileDrawable : public osg::Drawable
+    {
+    public:
+        /**
+         * Per-tile attribution for use with the MPGeometry.
+         */
+        struct Layer
+        {
+            Layer()
+            {
+                _texMatrixUniformID = ~0;
+                _parentTexMatrixUniformID = ~0;
+            }
+
+            osgEarth::UID                   _layerID;
+            osg::ref_ptr<const ImageLayer>  _imageLayer;
+
+            osg::ref_ptr<osg::Texture>      _tex;
+            osg::ref_ptr<osg::RefMatrixf>   _texMatrix;
+            unsigned                        _texMatrixUniformID;
+
+            osg::ref_ptr<osg::Texture>      _parentTex;
+            osg::ref_ptr<osg::RefMatrixf>   _parentTexMatrix;
+            unsigned                        _parentTexMatrixUniformID;
+
+            float                           _alphaThreshold;
+            bool                            _opaque;
+
+            // in support of std::find
+            inline bool operator == (const osgEarth::UID& rhs) const {
+                return _layerID == rhs;
+            }
+        };
+
+    public:
+        mutable MapFrame           _frame;
+        mutable std::vector<Layer> _layers;
+        mutable Threading::Mutex   _frameSyncMutex;
+
+        // uniform name IDs.
+        unsigned _uidUniformNameID;
+        unsigned _birthTimeUniformNameID;
+        unsigned _orderUniformNameID;
+        unsigned _opacityUniformNameID;
+        unsigned _tileKeyUniformNameID;
+        unsigned _texMatrixUniformNameID;
+        unsigned _parentTexMatrixUniformNameID;
+
+        // Data stored for each graphics context:
+        struct PerContextData {
+            PerContextData() : birthTime(-1.0f), lastFrame(0) { }
+            float    birthTime;
+            unsigned lastFrame;
+        };
+        mutable osg::buffered_object<PerContextData> _pcd;
+
+
+        mutable osg::Vec4f _tileKeyValue;
+
+        //int _imageUnit;          // image unit for primary texture
+        //int _imageUnitParent;    // image unit for secondary (parent) texture
+        //int _elevUnit;           // image unit for elevation texture
+        RenderBindings _bindings;
+
+        bool _supportsGLSL;
+
+        // underlying geometry, possible shared between this tile and other.
+        osg::ref_ptr<osg::Geometry> _geom;
+
+    public:
+        
+        // construct a new TileDrawable that fronts an osg::Geometry
+        TileDrawable(
+            const TileKey&        key,
+            const MapFrame&       frame,
+            const RenderBindings& bindings,
+            osg::Geometry*        geometry);
+
+        void drawVertexArraysImplementation(osg::RenderInfo& renderInfo) const;
+
+        void drawPrimitivesImplementation(osg::RenderInfo& renderInfo) const;
+
+        // validate the geometry is OK.
+        void validate();
+
+    public: // osg::Geometry overrides
+
+        // override so we can properly release the GL buffer objects
+        // that are not tracked by the Geometry itself but rather are
+        // stored in the LayerRenderData.
+        void releaseGLObjects(osg::State* state) const;
+        void resizeGLObjectBuffers(unsigned maxSize);
+        void compileGLObjects(osg::RenderInfo& renderInfo) const;
+
+        // this is copied mostly from osg::Geometry, but we've removed 
+        // all the code that handles non-fastPath (don't need it) and
+        // called into our custom renderPrimitiveSets method.
+        void drawImplementation(osg::RenderInfo& renderInfo) const;
+        
+        // recalculate the bound for the tile key uniform.
+#if OSG_VERSION_GREATER_THAN(3,3,1)
+        osg::BoundingBox computeBoundingBox() const;
+#else
+        osg::BoundingBox computeBound() const;
+#endif
+
+    public:
+        META_Object(osgEarth, TileDrawable);
+        TileDrawable() : osg::Drawable(), _frame(0L) { }
+        TileDrawable(const TileDrawable& rhs, const osg::CopyOp& cop) : osg::Drawable(rhs, cop), _frame(rhs._frame) { }
+        virtual ~TileDrawable() { }
+    };
+
+} } } // namespace osgEarth::Drivers::MPTerrainEngine
+
+#endif // OSGEARTH_DRIVERS_MP_TERRAIN_ENGINE_MPGEOMETRY
diff --git a/src/osgEarthDrivers/engine_mp/TileDrawable.cpp b/src/osgEarthDrivers/engine_mp/TileDrawable.cpp
new file mode 100644
index 0000000..a526c60
--- /dev/null
+++ b/src/osgEarthDrivers/engine_mp/TileDrawable.cpp
@@ -0,0 +1,534 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+* Copyright 2008-2014 Pelican Mapping
+* http://osgearth.org
+*
+* osgEarth is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public License
+* along with this program.  If not, see <http://www.gnu.org/licenses/>
+*/
+#include "TileDrawable"
+
+#include <osg/Version>
+#include <osgUtil/MeshOptimizers>
+#include <iterator>
+#include <osgEarth/Registry>
+#include <osgEarth/Capabilities>
+
+#include <osgUtil/IncrementalCompileOperation>
+
+using namespace osg;
+using namespace osgEarth::Drivers::MPTerrainEngine;
+using namespace osgEarth;
+
+#define LC "[TileDrawable] "
+
+
+TileDrawable::TileDrawable(const TileKey&        key, 
+                           const MapFrame&       frame,
+                           const RenderBindings& bindings,
+                           osg::Geometry*        geometry) :
+osg::Drawable( ),
+_frame       ( frame ),
+_bindings    ( bindings ),
+_geom        ( geometry )
+{
+    setUseVertexBufferObjects( true );
+    setUseDisplayList( false );
+
+    _supportsGLSL = Registry::capabilities().supportsGLSL();
+
+    unsigned tw, th;
+    key.getProfile()->getNumTiles(key.getLOD(), tw, th);
+    _tileKeyValue.set( key.getTileX(), th-key.getTileY()-1.0f, key.getLOD(), -1.0f );
+
+    // establish uniform name IDs.
+    _tileKeyUniformNameID      = osg::Uniform::getNameID( "oe_tile_key" );
+    _birthTimeUniformNameID    = osg::Uniform::getNameID( "oe_tile_birthtime" );
+    _uidUniformNameID          = osg::Uniform::getNameID( "oe_layer_uid" );
+    _orderUniformNameID        = osg::Uniform::getNameID( "oe_layer_order" );
+    _opacityUniformNameID      = osg::Uniform::getNameID( "oe_layer_opacity" );
+
+    _texMatrixUniformNameID    = osg::Uniform::getNameID( "oe_layer_texMatrix" );
+}
+
+
+void
+TileDrawable::drawPrimitivesImplementation(osg::RenderInfo& renderInfo) const
+{
+#if 0
+    // check the map frame to see if it's up to date
+    if ( _frame.needsSync() )
+    {
+        // this lock protects a MapFrame sync when we have multiple DRAW threads.
+        Threading::ScopedMutexLock exclusive( _frameSyncMutex );
+
+        if ( _frame.needsSync() && _frame.sync() ) // always double check
+        {
+            // This should only happen is the layer ordering changes;
+            // If layers are added or removed, the Tile gets rebuilt and
+            // the point is moot.
+            std::vector<Layer> reordered;
+            const ImageLayerVector& layers = _frame.imageLayers();
+            reordered.reserve( layers.size() );
+            for( ImageLayerVector::const_iterator i = layers.begin(); i != layers.end(); ++i )
+            {
+                std::vector<Layer>::iterator j = std::find( _layers.begin(), _layers.end(), i->get()->getUID() );
+                if ( j != _layers.end() )
+                    reordered.push_back( *j );
+            }
+            _layers.swap( reordered );
+        }
+    }
+#endif
+
+    unsigned layersDrawn = 0;
+
+    // access the GL extensions interface for the current GC:
+    const osg::Program::PerContextProgram* pcp = 0L;
+    osg::ref_ptr<osg::GL2Extensions> ext;
+    unsigned contextID;
+    osg::State& state = *renderInfo.getState();
+
+    //unsigned f = state.getFrameStamp()?state.getFrameStamp()->getFrameNumber():0;
+    //OE_WARN << LC << "frame="<<f<<"\n";
+
+    if (_supportsGLSL)
+    {
+        contextID = state.getContextID();
+        ext = osg::GL2Extensions::Get( contextID, true );
+        pcp = state.getLastAppliedProgramObject();
+    }
+
+    // cannot store these in the object since there could be multiple GCs (and multiple
+    // PerContextPrograms) at large
+    GLint tileKeyLocation       = -1;
+    GLint birthTimeLocation     = -1;
+    GLint opacityLocation       = -1;
+    GLint uidLocation           = -1;
+    GLint orderLocation         = -1;
+    GLint texMatrixLocation     = -1;
+
+    // The PCP can change (especially in a VirtualProgram environment). So we do need to
+    // requery the uni locations each time unfortunately. TODO: explore optimizations.
+    if ( pcp )
+    {
+        tileKeyLocation      = pcp->getUniformLocation( _tileKeyUniformNameID );
+        birthTimeLocation    = pcp->getUniformLocation( _birthTimeUniformNameID );
+        opacityLocation      = pcp->getUniformLocation( _opacityUniformNameID );
+        uidLocation          = pcp->getUniformLocation( _uidUniformNameID );
+        orderLocation        = pcp->getUniformLocation( _orderUniformNameID );
+        texMatrixLocation    = pcp->getUniformLocation( _texMatrixUniformNameID );
+    }
+    
+    // apply the tilekey uniform once.
+    if ( tileKeyLocation >= 0 )
+    {
+        ext->glUniform4fv( tileKeyLocation, 1, _tileKeyValue.ptr() );
+    }
+
+    // set the "birth time" - i.e. the time this tile last entered the scene in the current GC.
+    if ( birthTimeLocation >= 0 )
+    {
+        PerContextData& pcd = _pcd[contextID];
+        if ( pcd.birthTime < 0.0f )
+        {
+            const osg::FrameStamp* stamp = state.getFrameStamp();
+            if ( stamp )
+            {
+                pcd.birthTime = stamp->getReferenceTime();
+            }
+        }
+        ext->glUniform1f( birthTimeLocation, pcd.birthTime );
+    }
+
+//#ifndef OSG_GLES2_AVAILABLE
+//    if ( renderColor )
+//    {
+//        // emit a default terrain color since we're not binding a color array:
+//        glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
+//    }
+//#endif
+
+    float prevOpacity = -1.0f;
+
+    for(std::vector<Layer>::const_iterator i = _layers.begin(); i != _layers.end(); ++i)
+    {
+        const ImageLayer* imageLayer = i->_imageLayer.get();
+        if ( imageLayer->getVisible() && imageLayer->getOpacity() > 0.0f )
+        {
+            // bind the proper unit:
+            state.setActiveTextureUnit( _bindings.color().unit() );
+
+            // bind the color texture:
+            if ( i->_tex.valid() )
+                i->_tex->apply( state );  
+            else
+                OE_WARN << LC << "NO texture!\n";
+
+            // apply the color texture matrix uniform:
+            if ( i->_texMatrix.valid() )
+                ext->glUniformMatrix4fv( texMatrixLocation, 1, GL_FALSE, i->_texMatrix->ptr() );
+            else
+                OE_WARN << LC << "NO tex matrix!\n";
+            
+            // apply uniform values:
+            if ( pcp )
+            {
+                // apply opacity:
+                if ( opacityLocation >= 0 )
+                {
+                    float opacity = imageLayer->getOpacity();
+                    if ( opacity != prevOpacity )
+                    {
+                        ext->glUniform1f( opacityLocation, (GLfloat)opacity );
+                        prevOpacity = opacity;
+                    }
+                }
+
+                // assign the layer UID:
+                if ( uidLocation >= 0 )
+                {
+                    ext->glUniform1i( uidLocation, (GLint)imageLayer->getUID() );
+                }
+
+                // assign the layer order:
+                if ( orderLocation >= 0 )
+                {
+                    ext->glUniform1i( orderLocation, (GLint)layersDrawn );
+                }
+
+                // draw the primitive sets.
+                for(unsigned p=0; p != _geom->getPrimitiveSetList().size(); ++p)
+                {
+                    const osg::PrimitiveSet* primSet = _geom->getPrimitiveSet(p);
+                    if ( primSet )
+                    {
+                        primSet->draw(state, true);
+                    }
+                    else
+                    {
+                        OE_WARN << LC << "Strange, TileDrawable had a 0L primset" << std::endl;
+                    }
+                }
+
+                ++layersDrawn;
+            }
+        }
+    }
+
+    // Draw when there are no textures:
+    if ( layersDrawn == 0 )
+    {
+        if ( opacityLocation >= 0 )
+            ext->glUniform1f( opacityLocation, (GLfloat)1.0f );
+        if ( uidLocation >= 0 )
+            ext->glUniform1i( uidLocation, (GLint)-1 );
+        if ( orderLocation >= 0 )
+            ext->glUniform1i( orderLocation, (GLint)0 );
+        
+        for(unsigned p=0; p != _geom->getPrimitiveSetList().size(); ++p)
+        {
+            const osg::PrimitiveSet* primSet = _geom->getPrimitiveSet(p);
+            if ( primSet )
+            {
+                primSet->draw(state, true);
+            }
+            else
+            {
+                OE_WARN << LC << "INTERNAL: TileDrawable had a 0L primset" << std::endl;
+            }
+        }
+    }
+}
+
+
+#if OSG_VERSION_GREATER_OR_EQUAL(3,3,2)
+#    define COMPUTE_BOUND computeBoundingBox
+#else
+#    define COMPUTE_BOUND computeBound
+#endif
+
+#if OSG_VERSION_GREATER_OR_EQUAL(3,1,8)
+#   define GET_ARRAY(a) (a)
+#else
+#   define GET_ARRAY(a) (a).array
+#endif
+
+osg::BoundingBox
+TileDrawable:: COMPUTE_BOUND() const
+{
+    //osg::BoundingBox bbox = osg::Drawable:: COMPUTE_BOUND ();
+    osg::BoundingBox bbox = _geom->computeBound();
+    {
+        // update the uniform.
+        Threading::ScopedMutexLock exclusive(_frameSyncMutex);
+        _tileKeyValue.w() = bbox.radius();
+    }
+    return bbox;
+}
+
+
+void 
+TileDrawable::releaseGLObjects(osg::State* state) const
+{
+    osg::Drawable::releaseGLObjects( state );
+
+    if ( _geom.valid() )
+    {
+        _geom->releaseGLObjects( state );
+    }
+
+    for(std::vector<Layer>::const_iterator i = _layers.begin(); i != _layers.end(); ++i)
+    {
+        if ( i->_tex.valid() )
+        {
+            i->_tex->releaseGLObjects( state );
+        }
+    }
+}
+
+
+void
+TileDrawable::resizeGLObjectBuffers(unsigned maxSize)
+{
+    osg::Drawable::resizeGLObjectBuffers( maxSize );
+
+    if ( _geom.valid() )
+    {
+        _geom->resizeGLObjectBuffers( maxSize );
+    }
+
+    if ( _pcd.size() < maxSize )
+    {
+        _pcd.resize(maxSize);
+    }
+}
+
+
+void 
+TileDrawable::compileGLObjects(osg::RenderInfo& renderInfo) const
+{
+    osg::Drawable::compileGLObjects( renderInfo );
+
+    osg::State& state = *renderInfo.getState();
+    unsigned contextID = state.getContextID();
+    GLBufferObject::Extensions* extensions = GLBufferObject::getExtensions(contextID, true);
+    if (!extensions)
+        return;
+
+    for(std::vector<Layer>::iterator i = _layers.begin(); i != _layers.end(); ++i)
+    {
+        if ( i->_tex.valid() )
+            i->_tex->apply( state );
+    }
+
+    if ( _geom.valid() )
+    {
+        _geom->compileGLObjects( renderInfo );
+    }
+
+    // unbind the BufferObjects
+    //extensions->glBindBuffer(GL_ARRAY_BUFFER_ARB,0);
+    //extensions->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER_ARB,0);
+}
+
+void
+TileDrawable::drawImplementation(osg::RenderInfo& renderInfo) const
+{
+    State& state = *renderInfo.getState();
+    bool checkForGLErrors = state.getCheckForGLErrors() == osg::State::ONCE_PER_ATTRIBUTE;
+    if ( checkForGLErrors ) state.checkGLErrors("start of TileDrawable::drawImplementation()");
+
+#if OSG_MIN_VERSION_REQUIRED(3,3,1)
+    _geom->drawVertexArraysImplementation( renderInfo );
+#else
+    drawVertexArraysImplementation( renderInfo );
+#endif
+
+    drawPrimitivesImplementation( renderInfo );
+
+    if ( checkForGLErrors ) state.checkGLErrors("end of TileDrawable::drawImplementation()");
+    
+    // unbind the VBO's if any are used.
+    state.unbindVertexBufferObject();
+    state.unbindElementBufferObject();
+}
+
+
+#if OSG_MIN_VERSION_REQUIRED(3,1,8)
+void
+TileDrawable::drawVertexArraysImplementation(osg::RenderInfo& renderInfo) const
+{
+    if ( !_geom.valid() )
+        return;
+
+    State& state = *renderInfo.getState();
+
+    bool handleVertexAttributes = !_geom->getVertexAttribArrayList().empty();
+
+    ArrayDispatchers& arrayDispatchers = state.getArrayDispatchers();
+
+    arrayDispatchers.reset();
+    arrayDispatchers.setUseVertexAttribAlias(state.getUseVertexAttributeAliasing());
+
+    arrayDispatchers.activateNormalArray(_geom->getNormalArray());
+    arrayDispatchers.activateColorArray(_geom->getColorArray());
+    arrayDispatchers.activateSecondaryColorArray(_geom->getSecondaryColorArray());
+    arrayDispatchers.activateFogCoordArray(_geom->getFogCoordArray());
+
+    if (handleVertexAttributes)
+    {
+        for(unsigned int unit=0;unit<_geom->getVertexAttribArrayList().size();++unit)
+        {
+            arrayDispatchers.activateVertexAttribArray(unit, _geom->getVertexAttribArray(unit));
+        }
+    }
+
+    // dispatch any attributes that are bound overall
+    arrayDispatchers.dispatch(osg::Array::BIND_OVERALL,0);
+
+    state.lazyDisablingOfVertexAttributes();
+
+    // set up arrays
+    if( _geom->getVertexArray() )
+        state.setVertexPointer(_geom->getVertexArray());
+
+    if (_geom->getNormalArray() && _geom->getNormalArray()->getBinding()==osg::Array::BIND_PER_VERTEX)
+        state.setNormalPointer(_geom->getNormalArray());
+
+    if (_geom->getColorArray() && _geom->getColorArray()->getBinding()==osg::Array::BIND_PER_VERTEX)
+        state.setColorPointer(_geom->getColorArray());
+
+    if (_geom->getSecondaryColorArray() && _geom->getSecondaryColorArray()->getBinding()==osg::Array::BIND_PER_VERTEX)
+        state.setSecondaryColorPointer(_geom->getSecondaryColorArray());
+
+    if (_geom->getFogCoordArray() && _geom->getFogCoordArray()->getBinding()==osg::Array::BIND_PER_VERTEX)
+        state.setFogCoordPointer(_geom->getFogCoordArray());
+
+    for(unsigned int unit=0;unit<_geom->getTexCoordArrayList().size();++unit)
+    {
+        const Array* array = _geom->getTexCoordArray(unit);
+        if (array)
+        {
+            state.setTexCoordPointer(unit,array);
+        }
+    }
+
+    if ( handleVertexAttributes )
+    {
+        for(unsigned int index = 0; index < _geom->getVertexAttribArrayList().size(); ++index)
+        {
+            const Array* array = _geom->getVertexAttribArray(index);
+            if (array && array->getBinding()==osg::Array::BIND_PER_VERTEX)
+            {
+                if (array->getPreserveDataType())
+                {
+                    GLenum dataType = array->getDataType();
+                    if (dataType==GL_FLOAT) state.setVertexAttribPointer( index, array );
+                    else if (dataType==GL_DOUBLE) state.setVertexAttribLPointer( index, array );
+                    else state.setVertexAttribIPointer( index, array );
+                }
+                else
+                {
+                    state.setVertexAttribPointer( index, array );
+                }
+            }
+        }
+    }
+
+    state.applyDisablingOfVertexAttributes();
+}
+
+#else
+
+void
+TileDrawable::drawVertexArraysImplementation(osg::RenderInfo& renderInfo) const
+{
+    State& state = *renderInfo.getState();
+    bool handleVertexAttributes = !_vertexAttribList.empty();
+
+    ArrayDispatchers& arrayDispatchers = state.getArrayDispatchers();
+
+    arrayDispatchers.reset();
+    arrayDispatchers.setUseVertexAttribAlias(useFastPath && state.getUseVertexAttributeAliasing());
+    arrayDispatchers.setUseGLBeginEndAdapter(!useFastPath);
+
+    arrayDispatchers.activateNormalArray(_normalData.binding, _normalData.array.get(), _normalData.indices.get());
+    arrayDispatchers.activateColorArray(_colorData.binding, _colorData.array.get(), _colorData.indices.get());
+    arrayDispatchers.activateSecondaryColorArray(_secondaryColorData.binding, _secondaryColorData.array.get(), _secondaryColorData.indices.get());
+    arrayDispatchers.activateFogCoordArray(_fogCoordData.binding, _fogCoordData.array.get(), _fogCoordData.indices.get());
+
+    if (handleVertexAttributes)
+    {
+        for(unsigned int unit=0;unit<_vertexAttribList.size();++unit)
+        {
+            arrayDispatchers.activateVertexAttribArray(_vertexAttribList[unit].binding, unit, _vertexAttribList[unit].array.get(), _vertexAttribList[unit].indices.get());
+        }
+    }
+
+    // dispatch any attributes that are bound overall
+    arrayDispatchers.dispatch(BIND_OVERALL,0);
+
+    state.lazyDisablingOfVertexAttributes();
+
+    if (useFastPath)
+    {
+        // set up arrays
+        if( _vertexData.array.valid() )
+            state.setVertexPointer(_vertexData.array.get());
+
+        if (_normalData.binding==BIND_PER_VERTEX && _normalData.array.valid())
+            state.setNormalPointer(_normalData.array.get());
+
+        if (_colorData.binding==BIND_PER_VERTEX && _colorData.array.valid())
+            state.setColorPointer(_colorData.array.get());
+
+        if (_secondaryColorData.binding==BIND_PER_VERTEX && _secondaryColorData.array.valid())
+            state.setSecondaryColorPointer(_secondaryColorData.array.get());
+
+        if (_fogCoordData.binding==BIND_PER_VERTEX && _fogCoordData.array.valid())
+            state.setFogCoordPointer(_fogCoordData.array.get());
+
+        for(unsigned int unit=0;unit<_texCoordList.size();++unit)
+        {
+            const Array* array = _texCoordList[unit].array.get();
+            if (array) state.setTexCoordPointer(unit,array);
+        }
+
+        if( handleVertexAttributes )
+        {
+            for(unsigned int index = 0; index < _vertexAttribList.size(); ++index )
+            {
+                const Array* array = _vertexAttribList[index].array.get();
+                const AttributeBinding ab = _vertexAttribList[index].binding;
+                if( ab == BIND_PER_VERTEX && array )
+                {
+                    state.setVertexAttribPointer( index, array, _vertexAttribList[index].normalize );
+                }
+            }
+        }
+    }
+    else
+    {
+        for(unsigned int unit=0;unit<_texCoordList.size();++unit)
+        {
+            arrayDispatchers.activateTexCoordArray(BIND_PER_VERTEX, unit, _texCoordList[unit].array.get(), _texCoordList[unit].indices.get());
+        }
+
+        arrayDispatchers.activateVertexArray(BIND_PER_VERTEX, _vertexData.array.get(), _vertexData.indices.get());
+    }
+
+    state.applyDisablingOfVertexAttributes();
+}
+
+#endif
\ No newline at end of file
diff --git a/src/osgEarthDrivers/engine_mp/TileGroup b/src/osgEarthDrivers/engine_mp/TileGroup
index c466c5a..2d3527d 100644
--- a/src/osgEarthDrivers/engine_mp/TileGroup
+++ b/src/osgEarthDrivers/engine_mp/TileGroup
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
@@ -27,6 +27,7 @@
 #include "TileNodeRegistry"
 #include <osg/Group>
 #include <osgEarth/ThreadingUtils>
+#include <osgEarth/ResourceReleaser>
 
 namespace osgEarth { namespace Drivers { namespace MPTerrainEngine
 {
@@ -44,7 +45,7 @@ namespace osgEarth { namespace Drivers { namespace MPTerrainEngine
         TileGroup(const TileKey&    key, 
                   const UID&        engineUID,
                   TileNodeRegistry* live,
-                  TileNodeRegistry* dead);
+                  ResourceReleaser* releaser);
 
         const UID& getEngineUID() const { return _engineUID; }
 
@@ -66,7 +67,7 @@ namespace osgEarth { namespace Drivers { namespace MPTerrainEngine
         UID                            _engineUID;
         TileKey                        _key;
         osg::ref_ptr<TileNodeRegistry> _live;
-        osg::ref_ptr<TileNodeRegistry> _dead;
+        osg::ref_ptr<ResourceReleaser> _releaser;
     };
 
 } } } // namespace osgEarth::Drivers::MPTerrainEngine
diff --git a/src/osgEarthDrivers/engine_mp/TileGroup.cpp b/src/osgEarthDrivers/engine_mp/TileGroup.cpp
index d94174f..76c68ed 100644
--- a/src/osgEarthDrivers/engine_mp/TileGroup.cpp
+++ b/src/osgEarthDrivers/engine_mp/TileGroup.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
@@ -73,11 +73,11 @@ namespace
 TileGroup::TileGroup(const TileKey&    key, 
                      const UID&        engineUID,
                      TileNodeRegistry* live,
-                     TileNodeRegistry* dead) :
+                     ResourceReleaser* releaser) :
 _key      ( key ),
 _engineUID( engineUID ),
 _live     ( live ),
-_dead     ( dead )
+_releaser ( releaser )
 {
     this->setName( key.str() );
 }
@@ -135,7 +135,10 @@ TileGroup::applyUpdate(osg::Node* node)
                 oldTileNode = plod->getTileNode();
                 plod->setTileNode( newTileNode );
                 if ( _live.valid() )
-                    _live->move( oldTileNode.get(), _dead.get() );
+                {
+                    _live->remove(oldTileNode.get());
+                    _releaser->push(oldTileNode.get());
+                }
             }
             else
             {
@@ -149,11 +152,16 @@ TileGroup::applyUpdate(osg::Node* node)
 
                 this->setChild( i, newTileNode );
                 if ( _live.valid() )
-                    _live->move( oldTileNode.get(), _dead.get() );
+                {
+                    _live->remove(oldTileNode.get());
+                    _releaser->push(oldTileNode.get());
+                }
             }
 
             if ( _live.valid() )
+            {
                 _live->add( newTileNode );
+            }
         }
     }
 
diff --git a/src/osgEarthDrivers/engine_mp/TileGroupFactory b/src/osgEarthDrivers/engine_mp/TileGroupFactory
new file mode 100644
index 0000000..f778771
--- /dev/null
+++ b/src/osgEarthDrivers/engine_mp/TileGroupFactory
@@ -0,0 +1,100 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+* Copyright 2008-2014 Pelican Mapping
+* http://osgearth.org
+*
+* osgEarth is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public License
+* along with this program.  If not, see <http://www.gnu.org/licenses/>
+*/
+#ifndef OSGEARTH_DRIVERS_MP_TILE_GROUP_FACTORY
+#define OSGEARTH_DRIVERS_MP_TILE_GROUP_FACTORY 1
+
+#include "Common"
+#include "GeometryPool"
+#include "TileNode"
+#include "TileNodeRegistry"
+#include "MPTerrainEngineOptions"
+#include "RenderBindings"
+
+#include <osgEarth/TerrainTileModel>
+#include <osgEarth/MapFrame>
+#include <osgEarth/Progress>
+
+using namespace osgEarth;
+
+namespace osgEarth {
+    class TerrainEngine;
+}
+
+namespace osgEarth { namespace Drivers { namespace MPTerrainEngine
+{    
+    class TileGroupFactory : public osg::Referenced
+    {
+    public:
+        TileGroupFactory(
+            const Map*                          map,
+            TerrainEngine*                      engine,
+            GeometryPool*                       geometryPool,
+            TileNodeRegistry*                   liveTiles,
+            TileNodeRegistry*                   deadTiles,
+            const RenderBindings&               renderBindings,
+            const MPTerrainEngineOptions&       options);
+
+
+        /**
+         * Creates a TileGroup corresponding to the TileKey.
+         *
+         * @param key           TileKey for which to create a new node
+         * @param accumulate    Whether to accumulate data from parent tiles if necessary
+         * @param setupChildren When true, build and include the necessary structures to
+         *                      page in subtiles if and when necessary. If false, you just get
+         *                      the tile alone with no paging support.
+         * @param progress      Callback for cancelation and progress reporting
+         */
+        osg::Node* createTileGroup(
+            const TileKey&    key, 
+            bool              accumulate,
+            bool              setupChildren,
+            ProgressCallback* progress );
+
+    protected:
+
+        virtual ~TileGroupFactory() { }
+
+        /** Creates the graph representing a single tile within the group. */
+        TileNode* createTileNodeGraph(
+            TerrainTileModel* model,
+            bool              setupChildrenIfNecessary,
+            ProgressCallback* progress);
+
+        /** Creates the TileNode, the parent of the terrain surface and subtile pager */
+        TileNode* createTileNode(
+            TerrainTileModel* model,
+            ProgressCallback* progress);
+
+    protected:
+
+        MapFrame                              _frame;
+        osg::ref_ptr<TileNodeRegistry>        _liveTiles;
+        osg::ref_ptr<TileNodeRegistry>        _deadTiles;
+        const MPTerrainEngineOptions&         _options;
+        const RenderBindings&                 _renderBindings;
+        TerrainEngine*                        _terrainEngine;
+        GeometryPool*                         _geometryPool;
+
+        unsigned getMinimumRequiredLevel();
+    };
+
+} } } // namespace osgEarth::Drivers::MPTerrainEngine
+
+#endif // OSGEARTH_DRIVERS_MP_TILE_GROUP_FACTORY
diff --git a/src/osgEarthDrivers/engine_mp/TileGroupFactory.cpp b/src/osgEarthDrivers/engine_mp/TileGroupFactory.cpp
new file mode 100644
index 0000000..19546c5
--- /dev/null
+++ b/src/osgEarthDrivers/engine_mp/TileGroupFactory.cpp
@@ -0,0 +1,383 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+* Copyright 2008-2014 Pelican Mapping
+* http://osgearth.org
+*
+* osgEarth is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public License
+* along with this program.  If not, see <http://www.gnu.org/licenses/>
+*/
+#include "TileGroupFactory"
+#include "FileLocationCallback"
+#include "TilePagedLOD"
+#include "TileGroup"
+#include "SurfaceNodeFactory"
+
+#include <osgEarth/GeoData>
+#include <osgEarth/Registry>
+#include <osgEarth/HeightFieldUtils>
+#include <osgEarth/Progress>
+#include <osgEarth/Containers>
+#include <osgEarth/TerrainEngineNode>
+
+#include <osgUtil/CullVisitor>
+
+using namespace osgEarth::Drivers::MPTerrainEngine;
+using namespace osgEarth;
+
+#define LC "[TileGroupFactory] "
+
+//..............................................................
+
+namespace
+{
+    // Cull callback that uses a tight bounding box around the surface node.
+    struct SurfaceNodeCullCallback : public osg::NodeCallback
+    {
+        void operator()(osg::Node* node, osg::NodeVisitor* nv)
+        {
+            osgUtil::CullVisitor* cv = static_cast<osgUtil::CullVisitor*>(nv);
+            if ( !cv->isCulled(static_cast<SurfaceNode*>(node)->getBoundingBox()) )
+                traverse(node, nv);
+        }
+    };
+}
+
+//..............................................................
+
+
+TileGroupFactory::TileGroupFactory(const Map*                    map,
+                                   TerrainEngine*                terrainEngine,
+                                   GeometryPool*                 geometryPool,
+                                   TileNodeRegistry*             liveTiles,
+                                   TileNodeRegistry*             deadTiles,
+                                   const RenderBindings&         renderBindings,
+                                   const MPTerrainEngineOptions& options) :
+_frame         ( map ),
+_terrainEngine ( terrainEngine ),
+_geometryPool  ( geometryPool ),
+_liveTiles     ( liveTiles ),
+_deadTiles     ( deadTiles ),
+_renderBindings( renderBindings ),
+_options       ( options )
+{
+    //NOP
+}
+
+unsigned
+TileGroupFactory::getMinimumRequiredLevel()
+{
+    // highest required level in the map:
+    unsigned minLevel = _frame.getHighestMinLevel();
+
+    return _options.minLOD().isSet() ?
+        std::max( _options.minLOD().value(), minLevel ) :
+        minLevel;
+}
+
+TileNode*
+TileGroupFactory::createTileNode(TerrainTileModel* model,
+                                 ProgressCallback* progress)
+{
+    TileNode* tileNode = new TileNode(model);
+    
+    for(TerrainTileImageLayerModelVector::const_iterator i = model->colorLayers().begin();
+        i != model->colorLayers().end();
+        ++i)
+    {
+        const TerrainTileLayerModel* layer = i->get();
+
+        if ( layer->getTexture() )
+        {
+            osg::StateSet* stateSet = tileNode->getOrCreateStateSet();
+
+            stateSet->setTextureAttribute(
+                _renderBindings.color().unit(),
+                layer->getTexture() );
+
+            // (note: sampler uniform is set at the top level by the engine)
+        }
+
+        if ( layer->getMatrix() )
+        {
+            osg::StateSet* stateSet = tileNode->getOrCreateStateSet();
+
+            stateSet->addUniform( new osg::Uniform(
+                _renderBindings.color().matrixName().c_str(),
+                *(layer->getMatrix())) );
+        }
+    }
+
+    if ( model->elevationModel() )
+    {
+        const TerrainTileElevationModel* em = model->elevationModel();
+        
+        if ( em->getTexture() )
+        {
+            osg::StateSet* stateSet = tileNode->getOrCreateStateSet();
+
+            stateSet->setTextureAttribute(
+                _renderBindings.elevation().unit(),
+                em->getTexture() );
+
+            osg::Matrixf elevMatrix;
+            if ( em->getMatrix() )
+                elevMatrix = *(em->getMatrix());
+
+            stateSet->addUniform( new osg::Uniform(
+                _renderBindings.elevation().matrixName().c_str(),
+                elevMatrix ));
+
+            // (note: sampler uniform is set at the top level by the engine)
+        }
+    }
+    
+    for(TerrainTileImageLayerModelVector::const_iterator i = model->sharedLayers().begin();
+        i != model->sharedLayers().end();
+        ++i)
+    {
+        const TerrainTileImageLayerModel* layerModel = i->get();
+        
+        const ImageLayer* imageLayer = layerModel->getImageLayer();
+        if ( imageLayer )
+        {
+            if ( layerModel->getTexture() )
+            {
+                osg::StateSet* stateSet = tileNode->getOrCreateStateSet();
+
+                stateSet->setTextureAttribute(
+                    imageLayer->shareImageUnit().get(),
+                    layerModel->getTexture() );
+                
+                //TODO: don't really need this if we set it up in the Engine 
+                //  once at the top level when adding the layer.
+                stateSet->addUniform( new osg::Uniform(
+                    imageLayer->shareSamplerName()->c_str(),
+                    imageLayer->shareImageUnit().get() ));
+            }
+
+            if ( layerModel->getMatrix() )
+            {
+                osg::StateSet* stateSet = tileNode->getOrCreateStateSet();
+
+                stateSet->addUniform( new osg::Uniform(
+                    imageLayer->shareMatrixName()->c_str(),
+                    *(layerModel->getMatrix())) );
+            }
+        }
+    }
+
+    return tileNode;
+}
+
+TileNode*
+TileGroupFactory::createTileNodeGraph(TerrainTileModel* model,
+                                      bool              setupChildrenIfNecessary,
+                                      ProgressCallback* progress)
+{
+    // TODO: fix this
+    const unsigned tileSize = 17;
+
+    // Build the surface node.
+    SurfaceNodeFactory factory(model, _frame, _renderBindings, _geometryPool, tileSize, _options);
+    SurfaceNode* surfaceNode = factory.createSurfaceNode();
+
+    surfaceNode->setEngineUID( _terrainEngine->getUID() );
+
+    // see if this tile might have children.
+    bool prepareForChildren =
+        setupChildrenIfNecessary &&
+        model->getKey().getLOD() < *_options.maxLOD();
+    
+    // Build the Tile Node that will hold all the textures and texture matrices.
+    TileNode* tileNode = createTileNode(
+        model,
+        progress );
+
+    // Build the paging node that will load subtiles, if necessary:
+    if ( prepareForChildren )
+    {
+        osg::BoundingSphere bs = surfaceNode->getBound();
+        TilePagedLOD* plod = new TilePagedLOD( _terrainEngine->getUID(), _liveTiles, _deadTiles );
+        plod->setCenter  ( bs.center() );
+        plod->addChild   ( surfaceNode );
+        plod->setFileName( 1, Stringify() 
+            << model->getKey().str()
+            << "." << _terrainEngine->getUID()
+            << ".osgearth_engine_mp_tile" );
+
+        if ( _options.rangeMode().value() == osg::LOD::DISTANCE_FROM_EYE_POINT )
+        {
+            //Compute the min range based on the 2D size of the tile
+            GeoExtent extent = model->getKey().getExtent();
+            GeoPoint lowerLeft(extent.getSRS(), extent.xMin(), extent.yMin(), 0.0, ALTMODE_ABSOLUTE);
+            GeoPoint upperRight(extent.getSRS(), extent.xMax(), extent.yMax(), 0.0, ALTMODE_ABSOLUTE);
+            osg::Vec3d ll, ur;
+            lowerLeft.toWorld( ll );
+            upperRight.toWorld( ur );
+            double radius = (ur - ll).length() / 2.0;
+            float minRange = (float)(radius * _options.minTileRangeFactor().value());
+
+            plod->setRange( 0, minRange, FLT_MAX );
+            plod->setRange( 1, 0, minRange );
+            plod->setRangeMode( osg::LOD::DISTANCE_FROM_EYE_POINT );
+        }
+        else
+        {
+            plod->setRange( 0, 0.0f, _options.tilePixelSize().value() );
+            plod->setRange( 1, _options.tilePixelSize().value(), FLT_MAX );
+            plod->setRangeMode( osg::LOD::PIXEL_SIZE_ON_SCREEN );
+        }
+        
+#if 0 // TODO: reinstate this!
+
+        // Install a tile-aligned bounding box in the pager node itself so we can do
+        // visibility testing before paging in subtiles.
+        plod->setChildBoundingBoxAndMatrix(
+            1,
+            surfaceNode->getTerrainBoundingBox(),
+            surfaceNode->getLocalToWorldMatrix() );
+#endif
+
+#if USE_FILELOCATIONCALLBACK
+        osgDB::Options* options = plod->getOrCreateDBOptions();
+        options->setFileLocationCallback( new FileLocationCallback() );
+#endif
+        
+        tileNode->addChild( plod );
+
+        // Install a callback to reject back-facing tiles.
+        if ( _frame.getMapInfo().isGeocentric() && _options.clusterCulling() == true )
+        {
+            const osg::HeightField* heightField = model->elevationModel()->getHeightField();
+            if ( heightField )
+            {
+                tileNode->addCullCallback( HeightFieldUtils::createClusterCullingCallback(
+                    heightField,
+                    tileNode->getKey().getProfile()->getSRS()->getEllipsoid(),
+                    *_options.verticalScale() ) );
+            }
+        }
+    }
+    else
+    {
+        tileNode->addChild( surfaceNode );
+    }
+
+    return tileNode;
+}
+
+
+osg::Node*
+TileGroupFactory::createTileGroup(const TileKey&    parentKey, 
+                                  bool              accumulate,
+                                  bool              setupChildren,
+                                  ProgressCallback* progress )
+{
+    if ( progress && progress->isCanceled() )
+        return 0L;
+
+    _frame.sync();
+    
+    OE_START_TIMER(create_model);
+
+    osg::ref_ptr<TerrainTileModel> model[4];
+    for(unsigned q=0; q<4; ++q)
+    {
+        if ( progress && progress->isCanceled() )
+            return 0L;
+        
+        TileKey quadrantKey = parentKey.createChildKey(q);
+
+        // assemble a new tile model for this child.
+        model[q] = _terrainEngine->createTileModel(
+            _frame,
+            quadrantKey,
+            _liveTiles.get(),
+            progress );
+
+        // if any one of the TileModel creations fail, we will be unable to build
+        // this quadtile. So goodbye.
+        if ( !model[q].valid() )
+        {
+            OE_DEBUG << LC << "Bailed on key " << parentKey.str() << " due to a NULL quadrant model." << std::endl;
+            return 0L;
+        }
+    }
+
+    if (progress)
+        progress->stats()["create_tilemodel_time"] += OE_STOP_TIMER(create_model);
+
+    // See whether we can make a new tile family from the four models.
+    bool makeGroup;
+
+    // If this is a request for a root tile, make it no matter what.
+    if ( parentKey.getLOD() == 0 || (parentKey.getLOD()-1) == _options.firstLOD().value() )
+    {
+        makeGroup = true;
+    }
+
+    // If there's a minimum LOD set, and we haven't reached it yet, make the tile.
+    else if ( parentKey.getLOD() <= getMinimumRequiredLevel() )
+    {
+        makeGroup = true;
+    }
+
+    // Otherwise, only make the tile if at least one quadrant has REAL data
+    // (not fallback data).
+    else
+    {
+        makeGroup = false;
+        for(unsigned q=0; q<4; ++q)
+        {
+            if ( model[q]->containsNewData() )
+            {
+                makeGroup = true;
+                break;
+            }
+        }
+    }
+    
+    if ( progress && progress->isCanceled() )
+        return 0L;
+
+    OE_START_TIMER(compile_tile);
+
+    osg::ref_ptr<TileGroup> tileGroup;
+
+    if ( makeGroup )
+    {
+        tileGroup = new TileGroup();
+
+        for( unsigned q=0; q<4; ++q )
+        {
+            // create the new node:
+            osg::ref_ptr<TileNode> tileGraph = createTileNodeGraph(
+                model[q].get(),
+                setupChildren,
+                progress);
+
+            // notify the engine so it can fire callbacks, etc.
+            _terrainEngine->notifyOfTerrainTileNodeCreation(
+                model[q]->getKey(),
+                tileGraph.get() );
+
+            // welcome to the family.
+            tileGroup->addChild( tileGraph.get() );
+        }
+    }
+
+    if (progress)
+        progress->stats()["compile_tilemodel_time"] += OE_STOP_TIMER(compile_tile);
+
+    return tileGroup.release();
+}
diff --git a/src/osgEarthDrivers/engine_mp/TileModel b/src/osgEarthDrivers/engine_mp/TileModel
index cf80348..29084bc 100644
--- a/src/osgEarthDrivers/engine_mp/TileModel
+++ b/src/osgEarthDrivers/engine_mp/TileModel
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
@@ -124,7 +124,7 @@ namespace osgEarth { namespace Drivers { namespace MPTerrainEngine
         class NormalData
         {
         public:
-            NormalData() : _fallbackData(true) { }
+            NormalData() : _fallbackData(true), _unit(0) { }
             NormalData(const NormalData& rhs);
 
             virtual ~NormalData() { }
@@ -158,11 +158,17 @@ namespace osgEarth { namespace Drivers { namespace MPTerrainEngine
                 return _neighbors;
             }
 
+            int getUnit() const
+            {
+                return _unit;
+            }
+
         public:
             osg::ref_ptr<osg::HeightField> _hf;
             osg::ref_ptr<GeoLocator>       _locator;
             bool                           _fallbackData;
             osg::ref_ptr<osg::HeightField> _parent;
+            int                            _unit;
 
             HeightFieldNeighborhood _neighbors;
         };
@@ -171,7 +177,7 @@ namespace osgEarth { namespace Drivers { namespace MPTerrainEngine
         class ColorData
         {
         public:
-            ColorData() : _fallbackData(true) { }
+            ColorData() : _fallbackData(true), _order(0), _hasAlpha(false) { }
 
             /** Copy ctor - shallow */
             ColorData(const ColorData& rhs);
@@ -185,9 +191,6 @@ namespace osgEarth { namespace Drivers { namespace MPTerrainEngine
                 osg::Image*                 image,
                 GeoLocator*                 locator,
                 bool                        fallbackData =false );
-    
-            void resizeGLObjectBuffers(unsigned maxSize);
-            void releaseGLObjects(osg::State* state) const;
 
 
             osgEarth::UID getUID() const {
@@ -291,7 +294,6 @@ namespace osgEarth { namespace Drivers { namespace MPTerrainEngine
         ColorDataByUID               _colorData;
         ElevationData                _elevationData;
         NormalData                   _normalData;
-        float                        _sampleRatio;
         osg::ref_ptr<osg::Texture>   _elevationTexture;
         osg::ref_ptr<osg::Texture>   _normalTexture;
         bool                         _useParentData;
diff --git a/src/osgEarthDrivers/engine_mp/TileModel.cpp b/src/osgEarthDrivers/engine_mp/TileModel.cpp
index 2dc2a8b..5cb12d4 100644
--- a/src/osgEarthDrivers/engine_mp/TileModel.cpp
+++ b/src/osgEarthDrivers/engine_mp/TileModel.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
@@ -129,7 +129,8 @@ TileModel::NormalData::NormalData(osg::HeightField* hf,
                                   bool              fallbackData) :
 _hf          ( hf ),
 _locator     ( locator ),
-_fallbackData( fallbackData )
+_fallbackData( fallbackData ),
+_unit        ( -1 )
 {
     _neighbors._center = hf;
 }
@@ -138,7 +139,8 @@ TileModel::NormalData::NormalData(const TileModel::NormalData& rhs) :
 _hf          ( rhs._hf.get() ),
 _locator     ( rhs._locator.get() ),
 _fallbackData( rhs._fallbackData ),
-_parent      ( rhs._parent )
+_parent      ( rhs._parent ),
+_unit        ( rhs._unit )
 {
     _neighbors._center = rhs._neighbors._center.get();
     for(unsigned i=0; i<8; ++i)
@@ -204,11 +206,15 @@ _fallbackData( fallbackData )
         _texture = tex;
     }
 
-
+    // First check the unref globel policy:
     const optional<bool>& unRefPolicy = Registry::instance()->unRefImageDataAfterApply();
     if ( unRefPolicy.isSet() )
         _texture->setUnRefImageDataAfterApply( unRefPolicy.get() );
 
+    // dynamic layer? Need to keep it around
+    if ( layer->isDynamic() )
+        _texture->setUnRefImageDataAfterApply( false );
+
     _texture->setWrap( osg::Texture::WRAP_S, osg::Texture::CLAMP_TO_EDGE );
     _texture->setWrap( osg::Texture::WRAP_T, osg::Texture::CLAMP_TO_EDGE );
     _texture->setResizeNonPowerOfTwoHint(false);
@@ -234,7 +240,7 @@ _fallbackData( fallbackData )
         }    
     }
 
-    _hasAlpha = image && ImageUtils::hasTransparency(image);
+    _hasAlpha = ImageUtils::hasTransparency(image);
 
     layer->applyTextureCompressionMode( _texture.get() );    
 }
@@ -250,24 +256,6 @@ _hasAlpha    ( rhs._hasAlpha )
     //nop
 }
 
-void
-TileModel::ColorData::resizeGLObjectBuffers(unsigned maxSize)
-{
-    if ( _texture.valid() )
-    {
-        _texture->resizeGLObjectBuffers( maxSize );
-    }
-}
-
-void
-TileModel::ColorData::releaseGLObjects(osg::State* state) const
-{
-    if ( _texture.valid() && _texture->referenceCount() == 1 )
-    {
-        _texture->releaseGLObjects( state );
-    }
-}
-
 //------------------------------------------------------------------
 
 TileModel::TileModel(const TileModel& rhs) :
@@ -277,7 +265,6 @@ _tileKey         ( rhs._tileKey ),
 _tileLocator     ( rhs._tileLocator.get() ),
 _colorData       ( rhs._colorData ),
 _elevationData   ( rhs._elevationData ),
-_sampleRatio     ( rhs._sampleRatio ),
 _parentStateSet  ( rhs._parentStateSet ),
 _useParentData   ( rhs._useParentData )
 {
@@ -409,22 +396,32 @@ TileModel::generateNormalTexture()
     _normalTexture->setUnRefImageDataAfterApply( false );
 }
 
+
 void
 TileModel::resizeGLObjectBuffers(unsigned maxSize)
 {
     for(ColorDataByUID::iterator i = _colorData.begin(); i != _colorData.end(); ++i )
-        i->second.resizeGLObjectBuffers( maxSize );
+    {
+        if (i->second.getTexture())
+            i->second.getTexture()->resizeGLObjectBuffers(maxSize);
+    }    
 }
 
 void
 TileModel::releaseGLObjects(osg::State* state) const
 {
-    for(ColorDataByUID::const_iterator i = _colorData.begin(); i != _colorData.end(); ++i )
-        i->second.releaseGLObjects( state );
+    unsigned count=0;
+
+    for (ColorDataByUID::const_iterator i = _colorData.begin(); i != _colorData.end(); ++i)
+    {
+        if (i->second.getTexture() && i->second.getTexture()->referenceCount() == 1)
+            i->second.getTexture()->releaseGLObjects(state), ++count;
+    }
 
     if (_normalTexture.valid() && _normalTexture->referenceCount() == 1)
-        _normalTexture->releaseGLObjects(state);
+        _normalTexture->releaseGLObjects(state), ++count;
 
     if (_elevationTexture.valid() && _elevationTexture->referenceCount() == 1)
-        _elevationTexture->releaseGLObjects(state);
+        _elevationTexture->releaseGLObjects(state), ++count;
+
 }
diff --git a/src/osgEarthDrivers/engine_mp/TileModelCompiler b/src/osgEarthDrivers/engine_mp/TileModelCompiler
index bf2af7a..5267831 100644
--- a/src/osgEarthDrivers/engine_mp/TileModelCompiler
+++ b/src/osgEarthDrivers/engine_mp/TileModelCompiler
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthDrivers/engine_mp/TileModelCompiler.cpp b/src/osgEarthDrivers/engine_mp/TileModelCompiler.cpp
index cb8aa06..da9a94c 100644
--- a/src/osgEarthDrivers/engine_mp/TileModelCompiler.cpp
+++ b/src/osgEarthDrivers/engine_mp/TileModelCompiler.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
@@ -141,6 +141,14 @@ namespace
             ownsTileCoords   = false;
             stitchTileCoords = 0L;
             installParentData = false;
+            usePatches       = false;
+            numVerticesInSkirt = 0;
+            numVerticesInSurface = 0;
+            numRows = 0;
+            numCols = 0;
+            originalNumRows = 0;
+            originalNumCols = 0;
+            useUInt = false;
         }
 
         osg::Matrixd local2world, world2local;
@@ -167,12 +175,12 @@ namespace
         osg::ref_ptr<osg::Vec2Array> stitchTileCoords;
 
         // surface data:
-        osg::Geode*                   surfaceGeode;
-        MPGeometry*                   surface;
-        osg::Vec3Array*               surfaceVerts;
-        osg::Vec3Array*               normals;
-        osg::Vec4Array*               surfaceAttribs;
-        osg::Vec4Array*               surfaceAttribs2;
+        osg::ref_ptr<osg::Geode>      surfaceGeode;
+        osg::ref_ptr<MPGeometry>      surface;
+        osg::ref_ptr<osg::Vec3Array>  surfaceVerts;
+        osg::ref_ptr<osg::Vec3Array>  normals;
+        osg::ref_ptr<osg::Vec4Array>  surfaceAttribs;
+        osg::ref_ptr<osg::Vec4Array>  surfaceAttribs2;
         unsigned                      numVerticesInSurface;
         osg::ref_ptr<osg::FloatArray> elevations;
         Indices                       indices;
@@ -196,6 +204,8 @@ namespace
         MaskRecordVector         maskRecords;
         //MPGeometry*              stitchGeom;
 
+        bool                     usePatches;
+
         bool useUInt;
         osg::DrawElements* newDrawElements(GLenum mode) {
             osg::DrawElements* de = 0L;
@@ -248,7 +258,7 @@ namespace
 
             if (x_match && y_match)
             {
-                MPGeometry* stitchGeom = new MPGeometry( d.model->_tileKey, d.frame, d.textureImageUnit );
+                osg::ref_ptr<MPGeometry> stitchGeom = new MPGeometry( d.model->_tileKey, d.frame, d.textureImageUnit );
                 stitchGeom->setName("stitchGeom");
                 d.maskRecords.push_back( MaskRecord(boundary, min_ndc, max_ndc, stitchGeom) );
             }
@@ -870,8 +880,8 @@ namespace
                 // Add mask bounds as a triangulation constraint
 
                 osg::ref_ptr<osgUtil::DelaunayConstraint> newdc=new osgUtil::DelaunayConstraint;
-                osg::Vec3Array* maskConstraint = new osg::Vec3Array();
-                newdc->setVertexArray(maskConstraint);
+                osg::ref_ptr<osg::Vec3Array> maskConstraint = new osg::Vec3Array();
+                newdc->setVertexArray(maskConstraint.get());
 
                 //Crop the mask to the stitching poly (for case where mask crosses tile edge)
                 osg::ref_ptr<Geometry> maskCrop;
@@ -886,7 +896,7 @@ namespace
 
                     if (part->getType() == Geometry::TYPE_POLYGON)
                     {
-                        osg::Vec3Array* partVerts = part->toVec3Array();
+                        osg::ref_ptr<osg::Vec3Array> partVerts = part->createVec3Array();
                         maskConstraint->insert(maskConstraint->end(), partVerts->begin(), partVerts->end());
                         newdc->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::LINE_LOOP, maskConstraint->size() - partVerts->size(), partVerts->size()));
                     }
@@ -1026,8 +1036,8 @@ namespace
             }
 
             // Create array to hold vertex normals
-            osg::Vec3Array *norms=new osg::Vec3Array;
-            trig->setOutputNormalArray(norms);
+            osg::ref_ptr<osg::Vec3Array> norms = new osg::Vec3Array;
+            trig->setOutputNormalArray(norms.get());
 
 
             // Triangulate vertices and remove triangles that lie within the contraint loop
@@ -1041,15 +1051,33 @@ namespace
 
             MaskRecordVector::iterator mr = d.maskRecords.begin();
             // Set up new arrays to hold final vertices and normals
-            osg::Geometry* stitch_geom = (*mr)._geom;
-            osg::Vec3Array* stitch_verts = new osg::Vec3Array();
+            osg::ref_ptr<osg::Geometry> stitch_geom = (*mr)._geom;
+
+            osg::ref_ptr<osg::Vec3Array> stitch_verts = new osg::Vec3Array();
             stitch_verts->reserve(trig->getInputPointArray()->size());
             stitch_geom->setVertexArray(stitch_verts);
-            osg::Vec3Array* stitch_norms = new osg::Vec3Array(trig->getInputPointArray()->size());
+
+            osg::ref_ptr<osg::Vec3Array> stitch_norms = new osg::Vec3Array(trig->getInputPointArray()->size());
             stitch_geom->setNormalArray( stitch_norms );
             stitch_geom->setNormalBinding( osg::Geometry::BIND_PER_VERTEX );
 
 
+            // vertex attribution
+            // for each vertex, a vec4 containing a unit extrusion vector in [0..2] and the raw elevation in [3]
+            osg::ref_ptr<osg::Vec4Array> surfaceAttribs = new osg::Vec4Array();
+            surfaceAttribs->reserve( trig->getInputPointArray()->size() );
+            stitch_geom->setVertexAttribArray( osg::Drawable::ATTRIBUTE_6, surfaceAttribs );
+            stitch_geom->setVertexAttribBinding( osg::Drawable::ATTRIBUTE_6, osg::Geometry::BIND_PER_VERTEX );
+            stitch_geom->setVertexAttribNormalize( osg::Drawable::ATTRIBUTE_6, false );
+
+            // for each vertex, index 0 holds the interpolated elevation from the lower lod (for morphing)
+            osg::ref_ptr<osg::Vec4Array> surfaceAttribs2 = new osg::Vec4Array();
+            surfaceAttribs2->reserve( trig->getInputPointArray()->size() );
+            stitch_geom->setVertexAttribArray( osg::Drawable::ATTRIBUTE_7, surfaceAttribs2 );
+            stitch_geom->setVertexAttribBinding( osg::Drawable::ATTRIBUTE_7, osg::Geometry::BIND_PER_VERTEX );
+            stitch_geom->setVertexAttribNormalize( osg::Drawable::ATTRIBUTE_7, false );
+
+
             //Initialize tex coords
             if ( d.renderLayers.size() > 0 )
             {
@@ -1072,6 +1100,7 @@ namespace
                 stitch_verts->push_back(model);
 
                 // calc normals
+                osg::Vec3d local_zero(*it);
                 osg::Vec3d local_one(*it);
                 local_one.z() += 1.0;
                 osg::Vec3d model_one;
@@ -1080,6 +1109,49 @@ namespace
                 model_one.normalize();
                 (*stitch_norms)[++norm_i] = model_one;
 
+
+                // calculate and set vertext attributes for newly created mask geometry
+                osg::Vec3d model_up;
+                d.model->_tileLocator->unitToModel(local_one, model_up);
+                model_up = (model_up*d.world2local) - local_zero;
+                model_up.normalize();
+                (*d.normals).push_back(model_up);
+
+                // Calculate and store the "old height", i.e the height value from
+                // the parent LOD.
+                float heightValue = 0.0;
+                d.model->_elevationData.getHeight( local_zero, d.model->_tileLocator, heightValue, INTERP_TRIANGULATE );
+
+                float     oldHeightValue = heightValue;
+                osg::Vec3 oldNormal;
+
+                // This only works if the tile size is an odd number in both directions.
+                if (d.model->_tileKey.getLOD() > 0 && (d.numCols&1) && (d.numRows&1) && d.parentModel.valid())
+                {
+                    d.parentModel->_elevationData.getHeight( local_zero, d.model->_tileLocator.get(), oldHeightValue, INTERP_TRIANGULATE );
+                    d.parentModel->_elevationData.getNormal( local_zero, d.model->_tileLocator.get(), oldNormal, INTERP_TRIANGULATE );
+                }
+                else
+                {
+                    d.model->_elevationData.getNormal(local_zero, d.model->_tileLocator.get(), oldNormal, INTERP_TRIANGULATE );
+                }
+
+                // first attribute set has the unit extrusion vector and the
+                // raw height value.
+                (*surfaceAttribs).push_back( osg::Vec4f(
+                    model_up.x(),
+                    model_up.y(),
+                    model_up.z(),
+                    heightValue) );
+
+                // second attribute set has the old height value in "w"
+                (*surfaceAttribs2).push_back( osg::Vec4f(
+                    oldNormal.x(),
+                    oldNormal.y(),
+                    oldNormal.z(),
+                    oldHeightValue ) );
+
+
                 // set up text coords
                 if (d.renderLayers.size() > 0)
                 {
@@ -1102,7 +1174,7 @@ namespace
 
 
             // Get triangles from triangulator and add as primative set to the geometry
-            osg::DrawElementsUInt* tris = trig->getTriangles();
+            osg::ref_ptr<osg::DrawElementsUInt> tris = trig->getTriangles();
             if ( tris && tris->getNumIndices() >= 3 )
             {
                 stitch_geom->addPrimitiveSet(tris);
@@ -1141,7 +1213,11 @@ namespace
         }
 
         // Use the existing DrawElements on the surface so we merge the skirts and the surface together.
-        osg::ref_ptr<osg::DrawElements> elements = dynamic_cast< osg::DrawElements* >(d.surface->getPrimitiveSet(0));
+        osg::ref_ptr<osg::DrawElements> elements;
+        if ( d.surface->getNumPrimitiveSets() > 0 )
+        {
+            elements = dynamic_cast< osg::DrawElements* >(d.surface->getPrimitiveSet(0));
+        }
         if (!elements)
         {
             OE_WARN << LC << "Couldn't find existing DrawElements" << std::endl;
@@ -1388,7 +1464,8 @@ namespace
 
         unsigned numSurfaceNormals = d.numRows * d.numCols;
 
-        osg::DrawElements* elements = d.newDrawElements(GL_TRIANGLES);
+        GLenum mode = d.usePatches ? GL_PATCHES : GL_TRIANGLES;
+        osg::ref_ptr<osg::DrawElements> elements = d.newDrawElements(mode);
         elements->reserveElements((d.numRows-1) * (d.numCols-1) * 6);
 
         if ( recalcNormals )
@@ -2099,6 +2176,7 @@ TileModelCompiler::compile(TileModel*        model,
     d.parentModel = model->getParentTileModel();
     d.heightScale = *_options.verticalScale();
     d.heightOffset = *_options.verticalOffset();
+    d.usePatches = *_options.gpuTessellation();
 
     // A Geode/Geometry for the surface:
     d.surface = new MPGeometry( d.model->_tileKey, d.frame, _textureImageUnit );
diff --git a/src/osgEarthDrivers/engine_mp/TileModelFactory b/src/osgEarthDrivers/engine_mp/TileModelFactory
index 1370e4c..2fade69 100644
--- a/src/osgEarthDrivers/engine_mp/TileModelFactory
+++ b/src/osgEarthDrivers/engine_mp/TileModelFactory
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
@@ -66,6 +66,8 @@ namespace osgEarth { namespace Drivers { namespace MPTerrainEngine
             osg::ref_ptr<TileModel>& out_model,     // output or NULL upon failure
             ProgressCallback*        progress);     // progess tracking
 
+        void setNormalMapUnit(int unit) { _normalMapUnit = unit; }
+
     private:        
 
         osg::ref_ptr<TileNodeRegistry> _liveTiles;
@@ -73,6 +75,7 @@ namespace osgEarth { namespace Drivers { namespace MPTerrainEngine
         TerrainEngineRequirements*     _terrainReqs;
         osg::ref_ptr<HeightFieldCache> _meshHFCache;
         osg::ref_ptr<HeightFieldCache> _normalHFCache;
+        int                            _normalMapUnit;
         bool                           _debug;
         
         void buildElevation(
diff --git a/src/osgEarthDrivers/engine_mp/TileModelFactory.cpp b/src/osgEarthDrivers/engine_mp/TileModelFactory.cpp
index 763c57a..c279ad3 100644
--- a/src/osgEarthDrivers/engine_mp/TileModelFactory.cpp
+++ b/src/osgEarthDrivers/engine_mp/TileModelFactory.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
@@ -214,7 +214,8 @@ TileModelFactory::TileModelFactory(TileNodeRegistry*             liveTiles,
                                    TerrainEngineRequirements*    terrainReqs) :
 _liveTiles     ( liveTiles ),
 _terrainOptions( terrainOptions ),
-_terrainReqs   ( terrainReqs )
+_terrainReqs   ( terrainReqs ),
+_normalMapUnit ( 0 )
 {
     _meshHFCache = new HeightFieldCache( terrainOptions );
 
@@ -394,6 +395,8 @@ TileModelFactory::buildNormalMap(const TileKey&    key,
                     hf,
                     GeoLocator::createForKey( key, mapInfo ),
                     isFallback );
+
+                model->_normalData._unit = _normalMapUnit;
             }
         }
     }
@@ -408,6 +411,8 @@ TileModelFactory::buildNormalMap(const TileKey&    key,
             hf,
             GeoLocator::createForKey( key, mapInfo ),
             false );
+
+        model->_normalData._unit = _normalMapUnit;
     }
 
     if ( isFallback && parentModel.valid() )
diff --git a/src/osgEarthDrivers/engine_mp/TileNode b/src/osgEarthDrivers/engine_mp/TileNode
index 032bfb5..4a5febb 100644
--- a/src/osgEarthDrivers/engine_mp/TileNode
+++ b/src/osgEarthDrivers/engine_mp/TileNode
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
@@ -48,10 +48,6 @@ namespace osgEarth { namespace Drivers { namespace MPTerrainEngine
 
         osg::RefMatrixf* getNormalTextureMatrix() const;
 
-        osg::Group* getPayloadGroup() const;
-
-        osg::Group* getOrCreatePayloadGroup();
-
 
     public:
         /**
@@ -60,11 +56,6 @@ namespace osgEarth { namespace Drivers { namespace MPTerrainEngine
         TileNode(const TileKey& key, TileModel* model, const osg::Matrixd& matrix);
 
         /**
-         * Assigned the UID of the engine that created this tile.
-         */
-        void setEngineUID(UID uid) { _engineUID = uid; }
-
-        /**
          * True if this is a valid tile node.
          * Subclass may override (see InvalidTileNode)
          */
@@ -129,7 +120,6 @@ namespace osgEarth { namespace Drivers { namespace MPTerrainEngine
         virtual ~TileNode() { }
 
         TileKey                            _key;
-        UID                                _engineUID;
         osg::ref_ptr<TileModel>            _model;
         unsigned                           _lastTraversalFrame;
         Revision                           _maprevision;
@@ -138,7 +128,6 @@ namespace osgEarth { namespace Drivers { namespace MPTerrainEngine
         osg::ref_ptr<osg::RefMatrixf>      _elevTexMat;
         osg::ref_ptr<osg::RefMatrixf>      _normalTexMat;
         osg::BoundingBox                   _terrainBBox;
-        osg::ref_ptr<osg::Group>           _payload;
     };
 
 
diff --git a/src/osgEarthDrivers/engine_mp/TileNode.cpp b/src/osgEarthDrivers/engine_mp/TileNode.cpp
index b167654..22fe872 100644
--- a/src/osgEarthDrivers/engine_mp/TileNode.cpp
+++ b/src/osgEarthDrivers/engine_mp/TileNode.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
@@ -69,10 +69,9 @@ _outOfDate         ( false )
 
             _elevTexMat = new osg::RefMatrixf( osg::Matrixf(elevMatrix) );
             
-            // just stick this here for now.
-            // TODO: use the proper unit binding.
             osg::StateSet* stateSet = getOrCreateStateSet();
 
+            // TEMPORARY.
             stateSet->setTextureAttribute(
                 2,
                 _model->_elevationTexture.get() );
@@ -101,6 +100,15 @@ _outOfDate         ( false )
             normalMatrix.postMult( samplingScaleBias );
 
             _normalTexMat = new osg::RefMatrixf(normalMatrix);
+            
+            osg::StateSet* stateSet = getOrCreateStateSet();
+
+            stateSet->setTextureAttribute(
+                model->_normalData.getUnit(),
+                model->_normalTexture.get() );
+
+            stateSet->addUniform( new osg::Uniform(
+                "oe_tile_normalTexMatrix", *_normalTexMat.get() ) );
         }
     }
 }
@@ -139,29 +147,6 @@ TileNode::setLastTraversalFrame(unsigned frame)
     _lastTraversalFrame = frame;
 }
 
-osg::Group*
-TileNode::getPayloadGroup() const
-{
-    return _payload.get();
-}
-
-osg::Group*
-TileNode::getOrCreatePayloadGroup()
-{
-    if ( !_payload.valid() )
-    {
-        osg::StateSet* stateSet = new osg::StateSet();
-        std::string binName = Stringify() << "oe.PayloadBin." << _engineUID;
-        stateSet->setRenderBinDetails(1, binName);
-        stateSet->setNestRenderBins( false );
-
-        _payload = new osg::Group();
-        _payload->setStateSet( stateSet );
-        this->addChild( _payload.get() );
-    }
-    return _payload.get();
-}
-
 void
 TileNode::traverse( osg::NodeVisitor& nv )
 {
diff --git a/src/osgEarthDrivers/engine_mp/TileNodeRegistry b/src/osgEarthDrivers/engine_mp/TileNodeRegistry
index 7d78469..37e22d7 100644
--- a/src/osgEarthDrivers/engine_mp/TileNodeRegistry
+++ b/src/osgEarthDrivers/engine_mp/TileNodeRegistry
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
@@ -26,8 +26,10 @@
 #include "TileNode"
 #include <osgEarth/Revisioning>
 #include <osgEarth/ThreadingUtils>
+#include <osgEarth/ResourceReleaser>
 #include <OpenThreads/Atomic>
 #include <map>
+#include <set>
 
 namespace osgEarth { namespace Drivers { namespace MPTerrainEngine
 {
@@ -96,15 +98,9 @@ namespace osgEarth { namespace Drivers { namespace MPTerrainEngine
         /** Adds a tile to the registry */
         void add( TileNode* tile );
 
-        /** Adds several tiles to the registry */
-        //void add( const TileNodeVector& tiles );
-
         /** Removes a tile */
         void remove( TileNode* tile );
 
-        /** Moves a tile from this registry to another registry */
-        void move( TileNode* tile, TileNodeRegistry* destination );
-
         /** Finds a tile in the registry */
         bool get( const TileKey& key, osg::ref_ptr<TileNode>& out_tile );
 
@@ -113,9 +109,6 @@ namespace osgEarth { namespace Drivers { namespace MPTerrainEngine
 
         /** Whether there are tiles in this registry (snapshot in time) */
         bool empty() const;
-
-        /** Runs an operation against the exclusively locked tile set. */
-        void run( Operation& op );
         
         /** Runs an operation against the read-locked tile set. */
         void run( const ConstOperation& op ) const;
@@ -123,10 +116,8 @@ namespace osgEarth { namespace Drivers { namespace MPTerrainEngine
         /** Number of tiles in the registry. */
         unsigned size() const { return _tiles.size(); }
 
-        /** Tells the registry to listen for the TileNode for the specific key
-            to arrive, and upon its arrival, notifies the waiter. After notifying
-            the waiter, it removes the listen request. */
-        void listenFor(const TileKey& keyToWaitFor, TileNode* waiter);
+        /** Empty the registry, releasing all tiles. */
+        void releaseAll(ResourceReleaser*);
 
     protected:
 
@@ -135,11 +126,20 @@ namespace osgEarth { namespace Drivers { namespace MPTerrainEngine
         std::string                       _name;
         TileNodeMap                       _tiles;
         OpenThreads::Atomic               _frameNumber;
-        mutable Threading::ReadWriteMutex _tilesMutex;
+        mutable Threading::Mutex          _tilesMutex;
 
-        typedef std::vector<TileKey> TileKeyVector;
-        typedef std::map<TileKey, TileKeyVector> Notifications;
+        typedef std::set<TileKey> TileKeySet;
+        typedef std::map<TileKey, TileKeySet> Notifications;
         Notifications _notifications;
+
+    private:
+        /** Tells the registry to listen for the TileNode for the specific key
+            to arrive, and upon its arrival, notifies the waiter. After notifying
+            the waiter, it removes the listen request. (assumes lock held) */
+        void startListeningFor(const TileKey& keyToWaitFor, TileNode* waiter);
+
+        /** Removes a listen request set by startListeningFor (assumes lock held) */
+        void stopListeningFor(const TileKey& keyToWairFor, TileNode* waiter);
     };
 
 } } } // namespace osgEarth::Drivers::MPTerrainEngine
diff --git a/src/osgEarthDrivers/engine_mp/TileNodeRegistry.cpp b/src/osgEarthDrivers/engine_mp/TileNodeRegistry.cpp
index 82f94ec..a1654cf 100644
--- a/src/osgEarthDrivers/engine_mp/TileNodeRegistry.cpp
+++ b/src/osgEarthDrivers/engine_mp/TileNodeRegistry.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
@@ -56,7 +56,7 @@ TileNodeRegistry::setMapRevision(const Revision& rev,
     {
         if ( _maprev != rev || setToDirty )
         {
-            Threading::ScopedWriteLock exclusive( _tilesMutex );
+            Threading::ScopedMutexLock exclusive( _tilesMutex );
 
             if ( _maprev != rev || setToDirty )
             {
@@ -81,7 +81,7 @@ TileNodeRegistry::setDirty(const GeoExtent& extent,
                            unsigned         minLevel,
                            unsigned         maxLevel)
 {
-    Threading::ScopedWriteLock exclusive( _tilesMutex );
+    Threading::ScopedMutexLock exclusive( _tilesMutex );
     
     bool checkSRS = false;
     for( TileNodeMap::iterator i = _tiles.begin(); i != _tiles.end(); ++i )
@@ -102,7 +102,7 @@ TileNodeRegistry::add( TileNode* tile )
 {
     if ( tile )
     {
-        Threading::ScopedWriteLock exclusive( _tilesMutex );
+        Threading::ScopedMutexLock exclusive( _tilesMutex );
         _tiles[ tile->getKey() ] = tile;
         if ( _revisioningEnabled )
             tile->setMapRevision( _maprev );
@@ -113,27 +113,29 @@ TileNodeRegistry::add( TileNode* tile )
         Notifications::iterator i = _notifications.find(tile->getKey());
         if ( i != _notifications.end() )
         {
-            TileKeyVector& waiters = i->second;
-            for(unsigned j=0; j<waiters.size(); )
+            TileKeySet& waiters = i->second;
+
+            for (TileKeySet::iterator j = waiters.begin(); j != waiters.end(); ++j)
             {
-                TileKey& waiter = waiters[j];
+                const TileKey& waiter = *j;
                 TileNodeMap::iterator k = _tiles.find(waiter);
                 if ( k != _tiles.end() )
                 {
+                    // notify the listener:
                     k->second->notifyOfArrival( tile );
-                    waiter = waiters.back();
-                    waiters.resize( waiters.size()-1 );
-                }
-                else
-                {
-                    ++j;
                 }
             }
-            if ( waiters.size() == 0 )
-            {
-                _notifications.erase( i );
-            }
+
+            // clear the wait list for this tile.
+            // if there were waiters whose keys weren't found in the registry,
+            // they should not have been there anyway!
+            _notifications.erase(i);
         }
+
+        // Listen for east and south neighbors of the new tile:
+        const TileKey& key = tile->getTileNode()->getKey();
+        startListeningFor( key.createNeighborKey(1, 0), tile->getTileNode() );
+        startListeningFor( key.createNeighborKey(0, 1), tile->getTileNode() );
     }
 }
 
@@ -142,23 +144,14 @@ TileNodeRegistry::remove( TileNode* tile )
 {
     if ( tile )
     {
-        Threading::ScopedWriteLock exclusive( _tilesMutex );
+        Threading::ScopedMutexLock exclusive( _tilesMutex );
         _tiles.erase( tile->getKey() );
         OE_TEST << LC << _name << ": tiles=" << _tiles.size() << std::endl;
-    }
-}
-
-
-void
-TileNodeRegistry::move(TileNode* tile, TileNodeRegistry* destination)
-{
-    if ( tile )
-    {
-        // ref just in case remove() is the last reference
-        osg::ref_ptr<TileNode> tileSafe = tile;
-        remove( tile );
-        if ( destination )
-            destination->add( tileSafe.get() );
+        
+        // remove neighbor listeners:
+        const TileKey& key = tile->getTileNode()->getKey();
+        stopListeningFor( key.createNeighborKey(1, 0), tile->getTileNode() );
+        stopListeningFor( key.createNeighborKey(0, 1), tile->getTileNode() );
     }
 }
 
@@ -166,10 +159,10 @@ TileNodeRegistry::move(TileNode* tile, TileNodeRegistry* destination)
 bool
 TileNodeRegistry::get( const TileKey& key, osg::ref_ptr<TileNode>& out_tile )
 {
-    Threading::ScopedReadLock shared( _tilesMutex );
+    Threading::ScopedMutexLock shared( _tilesMutex );
 
     TileNodeMap::iterator i = _tiles.find(key);
-    if ( i != _tiles.end() )
+    if ( i != _tiles.end() && i->second.valid() )
     {
         out_tile = i->second.get();
         return true;
@@ -181,7 +174,7 @@ TileNodeRegistry::get( const TileKey& key, osg::ref_ptr<TileNode>& out_tile )
 bool
 TileNodeRegistry::take( const TileKey& key, osg::ref_ptr<TileNode>& out_tile )
 {
-    Threading::ScopedWriteLock exclusive( _tilesMutex );
+    Threading::ScopedMutexLock exclusive( _tilesMutex );
 
     TileNodeMap::iterator i = _tiles.find(key);
     if ( i != _tiles.end() )
@@ -194,24 +187,11 @@ TileNodeRegistry::take( const TileKey& key, osg::ref_ptr<TileNode>& out_tile )
     return false;
 }
 
-
-void
-TileNodeRegistry::run( TileNodeRegistry::Operation& op )
-{
-    Threading::ScopedWriteLock lock( _tilesMutex );
-    unsigned size = _tiles.size();
-    op.operator()( _tiles );
-    if ( size != _tiles.size() )
-        OE_TEST << LC << _name << ": tiles=" << _tiles.size() << std::endl;
-}
-
-
 void
 TileNodeRegistry::run( const TileNodeRegistry::ConstOperation& op ) const
 {
-    Threading::ScopedReadLock lock( _tilesMutex );
+    Threading::ScopedMutexLock lock( _tilesMutex );
     op.operator()( _tiles );
-    OE_TEST << LC << _name << ": tiles=" << _tiles.size() << std::endl;
 }
 
 
@@ -223,9 +203,11 @@ TileNodeRegistry::empty() const
 }
 
 void
-TileNodeRegistry::listenFor(const TileKey& tileToWaitFor, TileNode* waiter)
+TileNodeRegistry::startListeningFor(const TileKey& tileToWaitFor, TileNode* waiter)
 {
-    Threading::ScopedWriteLock lock( _tilesMutex );
+    //Threading::ScopedMutexLock lock( _tilesMutex );
+    // ASSUME EXCLUSIVE LOCK
+
     TileNodeMap::iterator i = _tiles.find( tileToWaitFor );
     if ( i != _tiles.end() )
     {
@@ -237,6 +219,45 @@ TileNodeRegistry::listenFor(const TileKey& tileToWaitFor, TileNode* waiter)
     else
     {
         OE_DEBUG << LC << waiter->getKey().str() << " listened for " << tileToWaitFor.str() << ".\n";
-        _notifications[tileToWaitFor].push_back( waiter->getKey() );
+        _notifications[tileToWaitFor].insert( waiter->getKey() );
+    }
+}
+
+void
+TileNodeRegistry::stopListeningFor(const TileKey& tileToWaitFor, TileNode* waiter)
+{
+    //Threading::ScopedMutexLock lock( _tilesMutex );
+    // ASSUME EXCLUSIVE LOCK
+
+    Notifications::iterator i = _notifications.find(tileToWaitFor);
+    if (i != _notifications.end())
+    {
+        // remove the waiter from this set:
+        i->second.erase(waiter->getKey());
+
+        // if the set is now empty, remove the set entirely
+        if (i->second.empty())
+        {
+            _notifications.erase(i);
+        }
     }
 }
+
+void
+TileNodeRegistry::releaseAll(ResourceReleaser* releaser)
+{
+    ResourceReleaser::ObjectList objects;
+    {
+        Threading::ScopedMutexLock exclusive(_tilesMutex);
+
+        for (TileNodeMap::iterator i = _tiles.begin(); i != _tiles.end(); ++i)
+        {
+            objects.push_back(i->second.get());
+        }
+
+        _tiles.clear();
+        _notifications.clear();
+    }
+
+    releaser->push(objects);
+}
\ No newline at end of file
diff --git a/src/osgEarthDrivers/engine_mp/TilePagedLOD b/src/osgEarthDrivers/engine_mp/TilePagedLOD
index 2842192..52e5479 100644
--- a/src/osgEarthDrivers/engine_mp/TilePagedLOD
+++ b/src/osgEarthDrivers/engine_mp/TilePagedLOD
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
@@ -27,6 +27,7 @@
 #include <osg/PagedLOD>
 #include <osgEarth/ThreadingUtils>
 #include <osgEarth/Progress>
+#include <osgEarth/ResourceReleaser>
 
 using namespace osgEarth;
 
@@ -42,7 +43,7 @@ namespace osgEarth { namespace Drivers { namespace MPTerrainEngine
         TilePagedLOD(
             const UID&        engineUID,
             TileNodeRegistry* liveTiles,
-            TileNodeRegistry* deadTiles);
+            ResourceReleaser* releaser);
 
         /**
          * Sets a bounding box and localization matrix that will allow
@@ -62,6 +63,8 @@ namespace osgEarth { namespace Drivers { namespace MPTerrainEngine
 
         void setDebug(bool value) { _debug = value; }
 
+        void setRangeFactor(double f) { _rangeFactor = f; }
+
     public: // osg::Group
 
         /** called by the OSG DatabasePager when a paging result is ready. */
@@ -79,11 +82,12 @@ namespace osgEarth { namespace Drivers { namespace MPTerrainEngine
 
     private:
         osg::ref_ptr<TileNodeRegistry> _live;
-        osg::ref_ptr<TileNodeRegistry> _dead;
+        osg::ref_ptr<ResourceReleaser> _releaser;
         UID                            _engineUID;
         Threading::Mutex               _updateMutex;
         std::vector<osg::BoundingBox>  _childBBoxes;
         std::vector<osg::Matrix>       _childBBoxMatrices;
+        optional<double>               _rangeFactor;
 
         struct MyProgressCallback : public ProgressCallback
         {
diff --git a/src/osgEarthDrivers/engine_mp/TilePagedLOD.cpp b/src/osgEarthDrivers/engine_mp/TilePagedLOD.cpp
index 61f57f0..3aeb724 100644
--- a/src/osgEarthDrivers/engine_mp/TilePagedLOD.cpp
+++ b/src/osgEarthDrivers/engine_mp/TilePagedLOD.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
@@ -21,6 +21,7 @@
 */
 #include "TilePagedLOD"
 #include "TileNodeRegistry"
+#include "MPTerrainEngineNode"
 #include <osg/Version>
 #include <osgEarth/Registry>
 #include <osgEarth/CullingUtils>
@@ -34,6 +35,10 @@ using namespace osgEarth;
 //#define OE_TEST OE_INFO
 #define OE_TEST OE_NULL
 
+// whether a camera with an ABSOLUTE_RF_INHERIT_VIEWPOINT reference frame can trigger tile subdivision.
+// NOTE: this causes issues with some of the RTT cameras like GPU clamping and draping.
+//#define INHERIT_VIEWPOINT_CAMERAS_CANNOT_SUBDIVIDE 1
+
 namespace
 {
     // traverses a node graph and moves any TileNodes from the LIVE
@@ -41,11 +46,12 @@ namespace
     struct ExpirationCollector : public osg::NodeVisitor
     {
         TileNodeRegistry* _live;
-        TileNodeRegistry* _dead;
+        ResourceReleaser* _releaser;
         unsigned          _count;
+        ResourceReleaser::ObjectList _toRelease;
 
-        ExpirationCollector(TileNodeRegistry* live, TileNodeRegistry* dead)
-            : _live(live), _dead(dead), _count(0)
+        ExpirationCollector(TileNodeRegistry* live)
+            : _live(live), _count(0)
         {
             // set up to traverse the entire subgraph, ignoring node masks.
             setTraversalMode( TRAVERSE_ALL_CHILDREN );
@@ -57,7 +63,9 @@ namespace
             TileNode* tn = dynamic_cast<TileNode*>( &node );
             if ( tn && _live )
             {
-                _live->move( tn, _dead );
+                _toRelease.push_back( tn );
+                _live->remove( tn );
+                //_live->move( tn, _dead );
                 _count++;
                 //OE_NOTICE << "Expired " << tn->getKey().str() << std::endl;
             }
@@ -100,11 +108,11 @@ TilePagedLOD::MyProgressCallback::update(unsigned frame)
 
 TilePagedLOD::TilePagedLOD(const UID&        engineUID,
                            TileNodeRegistry* live,
-                           TileNodeRegistry* dead) :
+                           ResourceReleaser* releaser) :
 osg::PagedLOD(),
 _engineUID( engineUID ),
 _live     ( live ),
-_dead     ( dead ),
+_releaser ( releaser ),
 _debug    ( false )
 {
     if ( live )
@@ -123,8 +131,9 @@ TilePagedLOD::~TilePagedLOD()
     // need this here b/c it's possible for addChild() to get called from
     // a pager dispatch even after the PLOD in question has been "expired"
     // so we still need to process the live/dead list.
-    ExpirationCollector collector( _live.get(), _dead.get() );
+    ExpirationCollector collector( _live.get() );
     this->accept( collector );
+    _releaser->push( collector._toRelease );
 }
 
 osgDB::Options*
@@ -187,11 +196,6 @@ TilePagedLOD::addChild(osg::Node* node)
         if ( tilenode && _live.get() )
         {
             _live->add( tilenode );
-
-            // Listen for out east and south neighbors.
-            const TileKey& key = tilenode->getKey();
-            _live->listenFor( key.createNeighborKey(1, 0), tilenode );
-            _live->listenFor( key.createNeighborKey(0, 1), tilenode );
         }
 
         return osg::PagedLOD::addChild( node );
@@ -231,25 +235,43 @@ TilePagedLOD::traverse(osg::NodeVisitor& nv)
             break;
         case(osg::NodeVisitor::TRAVERSE_ACTIVE_CHILDREN):
         {
-            float required_range = 0;
-            if (_rangeMode==DISTANCE_FROM_EYE_POINT)
-            {
-                required_range = nv.getDistanceToViewPoint(getCenter(),true);
-            }
-            else
+            osg::ref_ptr<MPTerrainEngineNode> engine;
+            MPTerrainEngineNode::getEngineByUID( _engineUID, engine );
+            if (!engine.valid())
+                return;
+
+            // Compute the required range.
+            float required_range = -1.0;
+            if (engine->getComputeRangeCallback())
+            {                
+                required_range = (*engine->getComputeRangeCallback())(this, nv);
+            }            
+
+            // If we don't have a callback or it return a negative number fallback on the original calculation.
+            if (required_range < 0.0)
             {
-                osg::CullStack* cullStack = dynamic_cast<osg::CullStack*>(&nv);
-                if (cullStack && cullStack->getLODScale()>0.0f)
+                if (_rangeMode==DISTANCE_FROM_EYE_POINT)
                 {
-                    required_range = cullStack->clampedPixelSize(getBound()) / cullStack->getLODScale();
+                    required_range = nv.getDistanceToViewPoint(getCenter(),true);
+
+                    if (_rangeFactor.isSet())
+                        required_range /= _rangeFactor.get();
                 }
                 else
                 {
-                    // fallback to selecting the highest res tile by
-                    // finding out the max range
-                    for(unsigned int i=0;i<_rangeList.size();++i)
+                    osg::CullStack* cullStack = dynamic_cast<osg::CullStack*>(&nv);
+                    if (cullStack && cullStack->getLODScale()>0.0f)
                     {
-                        required_range = osg::maximum(required_range,_rangeList[i].first);
+                        required_range = cullStack->clampedPixelSize(getBound()) / cullStack->getLODScale();
+                    }
+                    else
+                    {
+                        // fallback to selecting the highest res tile by
+                        // finding out the max range
+                        for(unsigned int i=0;i<_rangeList.size();++i)
+                        {
+                            required_range = osg::maximum(required_range,_rangeList[i].first);
+                        }
                     }
                 }
             }
@@ -278,6 +300,16 @@ TilePagedLOD::traverse(osg::NodeVisitor& nv)
                 }
             }
 
+#ifdef INHERIT_VIEWPOINT_CAMERAS_CANNOT_SUBDIVIDE
+            // Prevents an INHERIT_VIEWPOINT camera from invoking tile subdivision
+            if (needToLoadChild)
+            {
+                osgUtil::CullVisitor* cv = dynamic_cast<osgUtil::CullVisitor*>(&nv);
+                if ( cv && cv->getCurrentCamera() && cv->getCurrentCamera()->getReferenceFrame() == osg::Camera::ABSOLUTE_RF_INHERIT_VIEWPOINT )
+                    needToLoadChild = false;
+            }
+#endif
+
             if (needToLoadChild)
             {
                 unsigned int numChildren = _children.size();
@@ -381,8 +413,9 @@ TilePagedLOD::removeExpiredChildren(double         expiryTime,
             osg::Node* nodeToRemove = _children[cindex].get();
             removedChildren.push_back(nodeToRemove);
 
-            ExpirationCollector collector( _live.get(), _dead.get() );
+            ExpirationCollector collector( _live.get() );
             nodeToRemove->accept( collector );
+            _releaser->push( collector._toRelease );
 
             if ( _debug )
             {
diff --git a/src/osgEarthDrivers/engine_rex/CMakeLists.txt b/src/osgEarthDrivers/engine_rex/CMakeLists.txt
new file mode 100644
index 0000000..5a40c99
--- /dev/null
+++ b/src/osgEarthDrivers/engine_rex/CMakeLists.txt
@@ -0,0 +1,69 @@
+
+SET(TARGET_COMMON_LIBRARIES ${TARGET_COMMON_LIBRARIES} osgEarthSymbology)
+
+set(TARGET_GLSL
+    RexEngine.vert.glsl
+    RexEngine.vert.view.glsl
+    RexEngine.tcs.glsl
+    RexEngine.tes.glsl
+    RexEngine.gs.glsl
+    RexEngine.frag.glsl
+    RexEngine.NormalMap.vert.glsl
+    RexEngine.NormalMap.frag.glsl
+    RexEngine.Morphing.vert.glsl
+    RexEngine.SDK.vert.glsl)
+
+set(TARGET_IN
+    Shaders.cpp.in)
+
+set(SHADERS_CPP "${CMAKE_CURRENT_BINARY_DIR}/AutoGenShaders.cpp")
+
+configure_shaders(
+    Shaders.cpp.in
+    ${SHADERS_CPP}
+    ${TARGET_GLSL} )
+
+SET(TARGET_SRC
+    GeometryPool.cpp
+    RexTerrainEngineNode.cpp
+    RexTerrainEngineDriver.cpp
+    LoadTileData.cpp
+    MaskGenerator.cpp
+    MPTexture.cpp
+	SelectionInfo.cpp
+    SurfaceNode.cpp
+	TileDrawable.cpp
+    EngineContext.cpp
+    TileNode.cpp
+    TileNodeRegistry.cpp
+    Loader.cpp
+    Unloader.cpp
+    ${SHADERS_CPP}
+)
+
+SET(TARGET_H
+    Common
+    GeometryPool
+    Shaders
+    RexTerrainEngineNode
+    RexTerrainEngineOptions
+    LoadTileData
+    MaskGenerator
+    MPTexture
+    RenderBindings
+    SurfaceNode
+	TileDrawable
+    EngineContext
+    TileNode
+    TileNodeRegistry
+    Loader
+    Unloader
+	SelectionInfo
+)
+
+setup_plugin(osgearth_engine_rex)
+
+# to install public driver includes:
+SET(LIB_NAME engine_rex)
+SET(LIB_PUBLIC_HEADERS ${TARGET_H})
+INCLUDE(ModuleInstallOsgEarthDriverIncludes OPTIONAL)
diff --git a/src/osgEarthDrivers/engine_rex/Common b/src/osgEarthDrivers/engine_rex/Common
new file mode 100644
index 0000000..da6b740
--- /dev/null
+++ b/src/osgEarthDrivers/engine_rex/Common
@@ -0,0 +1,24 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+ * Copyright 2008-2014 Pelican Mapping
+ * http://osgearth.org
+ *
+ * osgEarth is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ */
+#ifndef OSGEARTH_DRIVERS_REX_TERRAIN_ENGINE_COMMON_H
+#define OSGEARTH_DRIVERS_REX_TERRAIN_ENGINE_COMMON_H 1
+
+#include <osgEarth/Common>
+
+#endif // OSGEARTH_DRIVERS_REX_TERRAIN_ENGINE_COMMON_H
diff --git a/src/osgEarthDrivers/engine_rex/ElevationTextureUtils b/src/osgEarthDrivers/engine_rex/ElevationTextureUtils
new file mode 100644
index 0000000..ff2499e
--- /dev/null
+++ b/src/osgEarthDrivers/engine_rex/ElevationTextureUtils
@@ -0,0 +1,73 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+ * Copyright 2008-2014 Pelican Mapping
+ * http://osgearth.org
+ *
+ * osgEarth is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ */
+#ifndef OSGEARTH_DRIVERS_REX_ELEVATION_TEXTURE_UTILS_H
+#define OSGEARTH_DRIVERS_REX_ELEVATION_TEXTURE_UTILS_H 1
+
+#include <osg/Matrix>
+#include <osgEarth/ImageUtils>
+
+namespace osg
+{
+    class Texture;
+    class Image;
+}
+namespace osgEarth
+{
+    class TileKey;
+}
+
+namespace osgEarth { namespace Drivers { namespace RexTerrainEngine
+{
+    class ElevationImageReader
+    {
+    public:
+        ElevationImageReader(const osg::Image* image, const osg::Matrix& matrixScaleBias);
+        ElevationImageReader(const osg::Image* image);
+
+        bool valid(void) const {return _valid;}
+
+        int startCol(void) const {return _startCol;}
+        int startRow(void) const {return _startRow;}
+
+        int endCol(void) const {return _endCol;}
+        int endRow(void) const {return _endRow;}
+
+        float elevationN(float s, float t);
+
+        float elevation(int col, int row) const
+        {
+            return _pixelReader(col, row).r();
+        }
+    private:
+        ImageUtils::PixelReader _pixelReader;
+        bool _valid;
+
+        int _startCol, _startRow;
+        int _endCol, _endRow;
+
+        void init(const osg::Image* image, const osg::Matrix& matrixScaleBias);
+    };
+
+    class ElevationTexureUtils
+    {
+    public:
+        static bool findExtrema(osg::Texture* elevationTex, const osg::Matrix& matrixScaleBias, const TileKey& tileKey, osg::Vec2f& output);
+    };
+}}}
+#endif
diff --git a/src/osgEarthDrivers/engine_rex/ElevationTextureUtils.cpp b/src/osgEarthDrivers/engine_rex/ElevationTextureUtils.cpp
new file mode 100644
index 0000000..fe10ad1
--- /dev/null
+++ b/src/osgEarthDrivers/engine_rex/ElevationTextureUtils.cpp
@@ -0,0 +1,119 @@
+#include "ElevationTextureUtils"
+
+#include <osgEarth/ImageUtils>
+#include <osgEarth/TileKey>
+
+#include <osg/Texture>
+
+#include <numeric>
+
+using namespace osgEarth::Drivers::RexTerrainEngine;
+using namespace osgEarth;
+
+#define LC "[ElevationTexureUtils] "
+
+ElevationImageReader::ElevationImageReader(const osg::Image* image)
+: _pixelReader(image)
+{
+    init(image, osg::Matrixf::identity());
+}
+
+
+ElevationImageReader::ElevationImageReader(const osg::Image* image, const osg::Matrix& matrixScaleBias)
+: _pixelReader(image)
+{
+    init(image, matrixScaleBias);
+}
+
+void
+ElevationImageReader::init(const osg::Image* image, const osg::Matrix& matrixScaleBias)
+{
+    double s_offset = matrixScaleBias(3,0) * (double)image->s();
+    double t_offset = matrixScaleBias(3,1) * (double)image->t();
+    double s_span   = matrixScaleBias(0,0) * (double)image->s();
+    double t_span   = matrixScaleBias(1,1) * (double)image->t();
+
+    // if the window is smaller than one pixel, forget it.
+    if ( s_span < 4.0 || t_span < 4.0 )
+    {
+        _valid = false;
+        return;
+    }
+
+    // starting column and row:
+    _startCol = osg::clampAbove( ((int)s_offset)-1, 0 );
+    _startRow = osg::clampAbove( ((int)t_offset)-1, 0 );
+
+    // ending column and row
+    _endCol = osg::clampBelow( _startCol + ((int)s_span) + 1, image->s()-1 );
+    _endRow = osg::clampBelow( _startRow + ((int)t_span) + 1, image->t()-1 );
+
+    OE_DEBUG << LC << std::dec 
+        << "scale=" << s_offset << ", " << t_offset
+        << "; span = " << s_span << ", " << t_span
+        << "; c0=" << startCol() << ", r0=" << startRow() << "; c1=" << endCol() << ", r1=" << endRow() << "\n";
+
+    _valid = true;
+}
+
+float
+ElevationImageReader::elevationN(float s, float t)
+{
+    int col = startCol() + (endCol()-startCol())*s;
+    int row = startRow() + (endRow()-startRow())*t;
+    return elevation(col, row);
+}
+
+bool
+ElevationTexureUtils::findExtrema(osg::Texture* elevationTexture, const osg::Matrix& matrixScaleBias, const TileKey& tileKey, osg::Vec2f& extrema)
+{
+    if (elevationTexture==0)
+    {
+        OE_DEBUG << LC << "findExtrema ERROR!! Elevation Texture is NULL"<<std::endl;
+        return false;
+    }
+    // Searches a texture image (using a texture matrix) for the min and max elevation values.
+    extrema.set( FLT_MAX, -FLT_MAX );
+
+    osg::Image* image = elevationTexture->getImage(0);
+    if ( image )
+    {
+        ElevationImageReader reader(image, matrixScaleBias);
+
+        if (reader.valid()==false)
+        {
+            OE_DEBUG << LC << "findExtrema ERROR!! Elevation Texture extents too small"<<std::endl;
+            return false;
+        }
+
+        OE_DEBUG << LC << "findExtrema: "<<tileKey.str()<<std::endl;
+
+        for(int col=reader.startCol(); col <= reader.endCol(); ++col)
+        {
+            for(int row=reader.startRow(); row <= reader.endRow(); ++row)
+            {
+                float elevation = reader.elevation(col, row);
+                if ( elevation < extrema[0] ) extrema[0] = elevation;
+                if ( elevation > extrema[1] ) extrema[1] = elevation;
+            }
+        }
+
+        if ( extrema[0] > extrema[1] )
+        {
+            OE_WARN << LC << "findExtrema ERROR!! (" << tileKey.str() << ") c0=" << reader.startCol() 
+                                                                    << ", r0=" << reader.startRow() 
+                                                                    << "; c1=" << reader.endCol() 
+                                                                    << ", r1=" << reader.endRow() 
+                                                                    << ", s=" << image->s() 
+                                                                    << ", t=" << image->t() << "\n";
+        }
+    }
+    else
+    {
+        OE_WARN << LC << "findExtrema ERROR!! (" << tileKey.str() << ") no tex image available\n";
+    }
+
+    OE_DEBUG << LC <<tileKey.getLOD()<< " Extrema Min: "<<extrema[0]<<" Max: "<<extrema[1]<<std::endl;
+
+    return extrema[0] <= extrema[1];
+}
\ No newline at end of file
diff --git a/src/osgEarthDrivers/engine_rex/EngineContext b/src/osgEarthDrivers/engine_rex/EngineContext
new file mode 100644
index 0000000..02a2e4d
--- /dev/null
+++ b/src/osgEarthDrivers/engine_rex/EngineContext
@@ -0,0 +1,135 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+* Copyright 2008-2014 Pelican Mapping
+* http://osgearth.org
+*
+* osgEarth is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public License
+* along with this program.  If not, see <http://www.gnu.org/licenses/>
+*/
+#ifndef OSGEARTH_DRIVERS_REX_TILE_GROUP_FACTORY
+#define OSGEARTH_DRIVERS_REX_TILE_GROUP_FACTORY 1
+
+#include "Common"
+#include "GeometryPool"
+#include "Loader"
+#include "Unloader"
+#include "TileNode"
+#include "TileNodeRegistry"
+#include "RexTerrainEngineOptions"
+#include "RenderBindings"
+
+#include <osgEarth/TerrainTileModel>
+#include <osgEarth/MapFrame>
+#include <osgEarth/Progress>
+#include <osgEarth/TerrainEngineNode>
+
+#include <osgUtil/CullVisitor>
+
+using namespace osgEarth;
+
+#define ENGINE_CONTEXT_TAG "osgEarth::Rex::EngineContext"
+
+namespace osgEarth {
+    class TerrainEngine;
+}
+
+namespace osgEarth { namespace Drivers { namespace RexTerrainEngine
+{
+    class SelectionInfo;
+
+    class EngineContext : public osg::Referenced
+    {
+    public:
+        EngineContext(
+            const Map*                          map,
+            TerrainEngineNode*                  engine,
+            GeometryPool*                       geometryPool,
+            Loader*                             loader,
+            Unloader*                           unloader,
+            TileNodeRegistry*                   liveTiles,
+            const RenderBindings&               renderBindings,
+            const RexTerrainEngineOptions&      options,
+            const SelectionInfo&                selectionInfo,
+            TilePatchCallbacks&                 tilePatchCallbacks);
+        
+        Loader* getLoader() const { return _loader; }
+
+        Unloader* getUnloader() const { return _unloader; }
+
+        const RenderBindings& getRenderBindings() const { return _renderBindings; }
+
+        GeometryPool* getGeometryPool() const { return _geometryPool; }
+
+        const MapFrame& getMapFrame();
+
+        TerrainEngineNode* getEngine() const { return _terrainEngine; }
+
+        TileNodeRegistry* liveTiles() const { return _liveTiles.get(); }
+
+        const SelectionInfo& getSelectionInfo() const { return _selectionInfo; }
+
+        const RexTerrainEngineOptions& getOptions() const { return _options; }
+
+        ProgressCallback* progress() const { return _progress.get(); }
+
+        void startCull(osgUtil::CullVisitor* cv);
+
+        void endCull(osgUtil::CullVisitor* cv);
+
+        double getElapsedCullTime() const;
+
+        bool maxLiveTilesExceeded() const;
+
+        osg::Uniform* getOrCreateMatrixUniform(const std::string& name, const osg::Matrixf& m);
+
+        void unloadChildrenOf(const TileNode*);
+
+        double getExpirationRange2() const { return _expirationRange2; }
+
+        void invokeTilePatchCallbacks(
+            osgUtil::CullVisitor* cv,
+            const TileKey&        tileKey,
+            osg::StateSet*        tileStateSet,
+            osg::Node*            tilePatch);
+        
+        osg::ref_ptr<osg::StateSet>           _surfaceSS;
+
+    protected:
+
+        virtual ~EngineContext() { }
+
+    public:
+
+        MapFrame                              _frame;
+        osg::ref_ptr<TileNodeRegistry>        _liveTiles;
+        const RexTerrainEngineOptions&        _options;
+        const RenderBindings&                 _renderBindings;
+        TerrainEngineNode*                    _terrainEngine;
+        GeometryPool*                         _geometryPool;
+        Loader*                               _loader;
+        Unloader*                             _unloader;
+        const SelectionInfo&                  _selectionInfo;
+        osg::Timer_t                          _tick;
+        int                                   _tilesLastCull;
+        osg::ref_ptr<ProgressCallback>        _progress;
+        TilePatchCallbacks&                   _tilePatchCallbacks;        
+        std::vector<TileKey>                  _tilesWithChildrenToUnload;
+        double                                _expirationRange2;
+
+        typedef std::map<osg::Vec4f, osg::ref_ptr<osg::Uniform> > MatrixUniformMap;
+        MatrixUniformMap _matrixUniforms;
+    };
+
+} } } // namespace osgEarth::Drivers::RexTerrainEngine
+
+#endif // OSGEARTH_DRIVERS_REX_TILE_GROUP_FACTORY
diff --git a/src/osgEarthDrivers/engine_rex/EngineContext.cpp b/src/osgEarthDrivers/engine_rex/EngineContext.cpp
new file mode 100644
index 0000000..9238dfb
--- /dev/null
+++ b/src/osgEarthDrivers/engine_rex/EngineContext.cpp
@@ -0,0 +1,232 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+* Copyright 2008-2014 Pelican Mapping
+* http://osgearth.org
+*
+* osgEarth is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public License
+* along with this program.  If not, see <http://www.gnu.org/licenses/>
+*/
+#include "EngineContext"
+#include "TileNodeRegistry"
+#include <osgEarth/TraversalData>
+#include <osgEarth/CullingUtils>
+#include <osgEarth/Registry>
+
+using namespace osgEarth::Drivers::RexTerrainEngine;
+using namespace osgEarth;
+
+#define LC "[EngineContext] "
+
+//#define PROFILE 1
+
+//..............................................................
+
+
+EngineContext::EngineContext(const Map*                     map,
+                             TerrainEngineNode*             terrainEngine,
+                             GeometryPool*                  geometryPool,
+                             Loader*                        loader,
+                             Unloader*                      unloader,
+                             TileNodeRegistry*              liveTiles,
+                             const RenderBindings&          renderBindings,
+                             const RexTerrainEngineOptions& options,
+                             const SelectionInfo&           selectionInfo,
+                             TilePatchCallbacks&            tilePatchCallbacks) :
+_frame         ( map ),
+_terrainEngine ( terrainEngine ),
+_geometryPool  ( geometryPool ),
+_loader        ( loader ),
+_unloader      ( unloader ),
+_liveTiles     ( liveTiles ),
+_renderBindings( renderBindings ),
+_options       ( options ),
+_selectionInfo ( selectionInfo ),
+_tilePatchCallbacks( tilePatchCallbacks ),
+_tick(0),
+_tilesLastCull(0)
+{
+    _expirationRange2 = _options.expirationRange().get() * _options.expirationRange().get();
+}
+
+const MapFrame& EngineContext::getMapFrame()
+{
+    if (_frame.needsSync())
+        _frame.sync();
+
+    return _frame;
+}
+
+void
+EngineContext::unloadChildrenOf(const TileNode* tile)
+{
+   _tilesWithChildrenToUnload.push_back( tile->getTileKey() );
+   OE_INFO << LC << "Unload children of: " << tile->getTileKey().str() << "\n";
+}
+
+void
+EngineContext::startCull(osgUtil::CullVisitor* cv)
+{
+    _tick = osg::Timer::instance()->tick();
+    _tilesLastCull = _liveTiles->size();
+
+#ifdef PROFILE
+    _progress = new ProgressCallback();
+#endif
+}
+
+double
+EngineContext::getElapsedCullTime() const
+{
+    osg::Timer_t now = osg::Timer::instance()->tick();
+    return osg::Timer::instance()->delta_s(_tick, now);
+}
+
+namespace
+{
+    struct Scanner : public TileNodeRegistry::ConstOperation
+    {
+        enum Policy {
+            POLICY_FIND_ALL,
+            POLICY_FIND_SOME,
+            POLICY_FIND_ONE
+        };
+
+        std::vector<TileKey>& _keys;
+        const osg::FrameStamp* _stamp;
+        Policy _policy;
+
+        Scanner(std::vector<TileKey>& keys, const osg::FrameStamp* stamp) : _keys(keys), _stamp(stamp)
+        {
+            _policy = POLICY_FIND_ALL;
+        }
+
+        void operator()(const TileNodeRegistry::TileNodeMap& tiles) const
+        {
+            if ( tiles.empty() ) return;
+            unsigned f = _stamp->getFrameNumber(), s = tiles.size();
+
+            switch (_policy)
+            {
+                case POLICY_FIND_ALL:
+                {
+                    for (TileNodeRegistry::TileNodeMap::const_iterator i = tiles.begin(); i != tiles.end(); ++i)
+                    {
+                        const TileNode* tile = i->second.tile.get();
+                        if (tile->areSubTilesDormant(_stamp))
+                            _keys.push_back(i->first);
+                    }
+                }
+                break;
+
+                case POLICY_FIND_ONE:
+                {
+                    const TileNode* tile = tiles.at(f%s);
+                    if (tile->areSubTilesDormant(_stamp))
+                    {
+                        _keys.push_back(tile->getTileKey());
+                    }
+                }
+                break;
+
+                default:
+                case POLICY_FIND_SOME:
+                {
+                    for(unsigned i=0; i<4; ++i) {
+                        const TileNode* tile = tiles.at((f+i)%s);
+                        if ( tile->areSubTilesDormant(_stamp) )
+                            _keys.push_back( tile->getTileKey() );
+                    }
+                }
+            }
+        }
+    };
+}
+
+void
+EngineContext::endCull(osgUtil::CullVisitor* cv)
+{
+    if ( progress() )
+    {
+        double tms = 1000.0 * getElapsedCullTime();
+
+        OE_NOTICE << "Stats:\n";
+        double totalCull = getElapsedCullTime();
+        OE_NOTICE << "  TOTAL TIME = " << tms << " ms ... live tiles = " << _liveTiles->size() << std::endl;
+        for(ProgressCallback::Stats::const_iterator i = _progress->stats().begin(); i != _progress->stats().end(); ++i)
+        { 
+            if ( osgEarth::endsWith(i->first, "_count") )
+            {
+                OE_NOTICE << "    " << i->first << " = " << (int)i->second << std::endl;
+            }
+            else
+            {
+                OE_NOTICE << "    " << i->first << " = " << std::setprecision(5) << (1000.0*i->second) << " ms (" << 
+                    std::setprecision(2) << 100.0*i->second/totalCull << "%)" << std::endl;
+            }
+        }
+    }  
+
+#if 0 // render bin printout
+    Config c = CullDebugger().dumpRenderBin(cv->getCurrentRenderBin());
+    OE_NOTICE << c.toJSON(true) << std::endl << std::endl;
+#endif
+
+    Scanner scanner(_tilesWithChildrenToUnload, cv->getFrameStamp());
+    _liveTiles->run( scanner );
+
+    if ( !_tilesWithChildrenToUnload.empty() )
+    {        
+        getUnloader()->unloadChildren( _tilesWithChildrenToUnload );
+        _tilesWithChildrenToUnload.clear();
+    }
+
+    Registry::instance()->startActivity("REX live tiles", Stringify()<<_liveTiles->size());
+}
+
+bool
+EngineContext::maxLiveTilesExceeded() const
+{
+    return _liveTiles->size() > _options.expirationThreshold().get();
+}
+
+osg::Uniform*
+EngineContext::getOrCreateMatrixUniform(const std::string& name, const osg::Matrixf& m)
+{
+    // Unique key for this uniform include the scale, the x/y bias, and the name ID.
+    osg::Vec4f key(m(0,0),m(3,0),m(3,1),(float)osg::Uniform::getNameID(name));
+
+    MatrixUniformMap::iterator i = _matrixUniforms.find(key);
+    if ( i != _matrixUniforms.end() )
+    {
+        return i->second.get();
+    }
+    
+    osg::Uniform* u = new osg::Uniform(name.c_str(), m);
+    _matrixUniforms[key] = u;
+
+    return u;
+}
+
+void
+EngineContext::invokeTilePatchCallbacks(osgUtil::CullVisitor* cv,
+                                        const TileKey&        tileKey,
+                                        osg::StateSet*        tileStateSet,
+                                        osg::Node*            tilePatch)
+{
+    for(TilePatchCallbacks::iterator i = _tilePatchCallbacks.begin();
+        i != _tilePatchCallbacks.end();
+        ++i)
+    {
+        i->get()->cull(cv, tileKey, tileStateSet, tilePatch);
+    }
+}
diff --git a/src/osgEarthDrivers/engine_rex/GeometryPool b/src/osgEarthDrivers/engine_rex/GeometryPool
new file mode 100644
index 0000000..22196b4
--- /dev/null
+++ b/src/osgEarthDrivers/engine_rex/GeometryPool
@@ -0,0 +1,138 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+* Copyright 2008-2014 Pelican Mapping
+* http://osgearth.org
+*
+* osgEarth is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public License
+* along with this program.  If not, see <http://www.gnu.org/licenses/>
+*/
+#ifndef OSGEARTH_DRIVERS_REX_TERRAIN_ENGINE_GEOMETRY_POOL
+#define OSGEARTH_DRIVERS_REX_TERRAIN_ENGINE_GEOMETRY_POOL 1
+
+#include "Common"
+#include "MaskGenerator"
+#include "RexTerrainEngineOptions"
+#include <osgEarth/MapInfo>
+#include <osgEarth/TileKey>
+#include <osgEarth/ThreadingUtils>
+#include <osgEarth/ResourceReleaser>
+#include <osg/Geometry>
+
+namespace osgEarth { namespace Drivers { namespace RexTerrainEngine
+{
+    using namespace osgEarth;
+
+    /**
+     * Pool of terrain tile geometries.
+     *
+     * In a geocentric map, every tile at a particular LOD and a particular latitudinal
+     * (north-south) extent shares exactly the same geometry; each tile is just shifted
+     * and rotated differently. Therefore we can use the same Geometry for all tiles that
+     * share the same LOD and same min/max latitude in a geocentric map. In a projected
+     * map, all tiles at a given LOD share the same geometry regardless of extent, so eve
+     * more sharing is possible.
+     *
+     * This object creates and returns geometries based on TileKeys, sharing instances
+     * whenever possible. Concept adapted from OSG's osgTerrain::GeometryPool.
+     */
+    class GeometryPool : public osg::Group
+    {
+    public:
+        /** Construct the geometry pool */
+        GeometryPool(const RexTerrainEngineOptions& options);
+
+        /** Sets an object to release unused GL resources */
+        void setReleaser(ResourceReleaser* releaser);
+
+    public:
+        /**
+         * Hashtable key for unique (and therefore shareable) geometries.
+         */
+        struct GeometryKey
+        {
+            GeometryKey() :
+                lod(-1),
+                yMin(0.0),
+                patch(false),
+                size(0u)
+                {
+                }
+
+            bool operator < (const GeometryKey& rhs) const
+            {
+                if (lod < rhs.lod) return true;
+                if (lod > rhs.lod) return false;
+                if (yMin < rhs.yMin) return true;
+                if (yMin > rhs.yMin) return false;
+                if (size < rhs.size) return true;
+                if (size > rhs.size) return false;
+                return patch == false && rhs.patch == true;
+            }
+
+            int      lod;
+            double   yMin;
+            bool     patch;
+            unsigned size;
+        };
+
+        typedef std::map<GeometryKey, osg::ref_ptr<osg::Geometry> > GeometryMap;
+
+        /**
+         * Gets the Geometry associated with a tile key, creating a new one if
+         * necessary and storing it in the pool.
+         */
+        void getPooledGeometry(
+            const TileKey&               tileKey,
+            const MapInfo&               mapInfo,
+            osg::ref_ptr<osg::Geometry>& out,
+            MaskGenerator*               maskSet=0L);
+
+        /**
+         * The number of elements (incides) in the terrain skirt, if applicable
+         */
+        int getNumSkirtElements() const;
+
+    public: // osg::Node
+
+        /** Perform an update traversal to check for unused resources. */
+        void traverse(osg::NodeVisitor& nv);
+
+    protected:
+        virtual ~GeometryPool() { }
+
+        mutable Threading::Mutex       _geometryMapMutex;
+        GeometryMap                    _geometryMap;
+        unsigned                       _tileSize;
+        const RexTerrainEngineOptions& _options; 
+        osg::ref_ptr<ResourceReleaser> _releaser;
+
+        mutable osg::ref_ptr<osg::Vec3Array> _sharedTexCoords;
+        
+        void createKeyForTileKey(
+            const TileKey& tileKey, 
+            unsigned       size,
+            const MapInfo& mapInfo,
+            GeometryKey&   out) const;
+
+        osg::Geometry* createGeometry(
+            const TileKey& tileKey,
+            const MapInfo& mapInfo,
+            MaskGenerator* maskSet ) const;
+
+        bool _enabled;
+        bool _debug;
+    };
+
+} } } // namespace osgEarth::Drivers::RexTerrainEngine
+
+#endif // OSGEARTH_DRIVERS_REX_TERRAIN_ENGINE_GEOMETRY_POOL
diff --git a/src/osgEarthDrivers/engine_rex/GeometryPool.cpp b/src/osgEarthDrivers/engine_rex/GeometryPool.cpp
new file mode 100644
index 0000000..9f5978c
--- /dev/null
+++ b/src/osgEarthDrivers/engine_rex/GeometryPool.cpp
@@ -0,0 +1,421 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+* Copyright 2008-2014 Pelican Mapping
+* http://osgearth.org
+*
+* osgEarth is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public License
+* along with this program.  If not, see <http://www.gnu.org/licenses/>
+*/
+#include "GeometryPool"
+#include <osgEarth/Locators>
+#include <osg/Point>
+#include <cstdlib> // for getenv
+
+using namespace osgEarth;
+using namespace osgEarth::Drivers::RexTerrainEngine;
+
+#define LC "[GeometryPool] "
+
+// TODO: experiment with sharing a single texture coordinate array 
+//// across all shared geometries.
+/// JB:  Disabled to fix issues with ATI.
+//#define SHARE_TEX_COORDS 1
+
+
+GeometryPool::GeometryPool(const RexTerrainEngineOptions& options) :
+_options ( options ),
+_enabled ( true ),
+_debug   ( false )
+{
+    // sign up for the update traversal so we can prune unused pool objects.
+    setNumChildrenRequiringUpdateTraversal(1u);
+
+    _tileSize = _options.tileSize().get();
+
+    // activate debugging mode
+    if ( getenv("OSGEARTH_DEBUG_REX_GEOMETRY_POOL") != 0L )
+    {
+        _debug = true;
+    }
+
+    if ( ::getenv("OSGEARTH_REX_NO_POOL") )
+    {
+        _enabled = false;
+        OE_INFO << LC << "Geometry pool disabled (environment)" << std::endl;
+    }
+
+    //if ( ::getenv( "OSGEARTH_MEMORY_PROFILE" ) )
+    //{
+    //    _enabled = false;
+    //    OE_INFO << LC << "Geometry pool disabled (memory profile mode)" << std::endl;
+    //}
+}
+
+void
+GeometryPool::getPooledGeometry(const TileKey&               tileKey,
+                                const MapInfo&               mapInfo,
+                                osg::ref_ptr<osg::Geometry>& out,
+                                MaskGenerator*               maskSet)
+{
+    // convert to a unique-geometry key:
+    GeometryKey geomKey;
+    createKeyForTileKey( tileKey, _tileSize, mapInfo, geomKey );
+
+    if ( _enabled )
+    {
+        // Look it up in the pool:
+        Threading::ScopedMutexLock exclusive( _geometryMapMutex );
+
+        bool masking = maskSet && maskSet->hasMasks();
+
+        GeometryMap::iterator i = _geometryMap.find( geomKey );
+        if ( !masking && i != _geometryMap.end() )
+        {
+            // Found. return it.
+            out = i->second.get();
+        }
+        else
+        {
+            // Not found. Create it.
+            out = createGeometry( tileKey, mapInfo, maskSet );
+
+            if (!masking)
+                _geometryMap[ geomKey ] = out.get();
+
+            if ( _debug )
+            {
+                OE_NOTICE << LC << "Geometry pool size = " << _geometryMap.size() << "\n";
+            }
+        }
+    }
+
+    else
+    {
+        out = createGeometry( tileKey, mapInfo, maskSet );
+    }
+}
+
+void
+GeometryPool::createKeyForTileKey(const TileKey&             tileKey,
+                                  unsigned                   size,
+                                  const MapInfo&             mapInfo,
+                                  GeometryPool::GeometryKey& out) const
+{
+    out.lod  = tileKey.getLOD();
+    out.yMin = mapInfo.isGeocentric()? tileKey.getExtent().yMin() : 0.0;
+    out.size = size;
+}
+
+int
+GeometryPool::getNumSkirtElements() const
+{
+    return _options.heightFieldSkirtRatio().get() > 0.0 ? (_tileSize-1) * 4 * 6 : 0;
+}
+
+namespace
+{
+    int getMorphNeighborIndexOffset(unsigned col, unsigned row, int rowSize)
+    {
+        if ( (col & 0x1)==1 && (row & 0x1)==1 ) return rowSize+2;
+        if ( (row & 0x1)==1 )                   return rowSize+1;
+        if ( (col & 0x1)==1 )                   return 2;
+        return 1;            
+    }
+}
+
+#define addSkirtDataForIndex(INDEX, HEIGHT) \
+{ \
+    verts->push_back( (*verts)[INDEX] ); \
+    normals->push_back( (*normals)[INDEX] ); \
+    texCoords->push_back( (*texCoords)[INDEX] ); \
+    if ( neighbors ) neighbors->push_back( (*neighbors)[INDEX] ); \
+    verts->push_back( (*verts)[INDEX] - ((*normals)[INDEX])*(HEIGHT) ); \
+    normals->push_back( (*normals)[INDEX] ); \
+    texCoords->push_back( (*texCoords)[INDEX] ); \
+    if ( neighbors ) neighbors->push_back( (*neighbors)[INDEX] - ((*normals)[INDEX])*(HEIGHT) ); \
+}
+
+#define addSkirtTriangles(INDEX0, INDEX1) \
+{ \
+    if ( maskSet == 0L || (!maskSet->isMasked((*texCoords)[INDEX0]) && !maskSet->isMasked((*texCoords)[INDEX1])) ) \
+    { \
+        primSet->addElement((INDEX0));   \
+        primSet->addElement((INDEX0)+1); \
+        primSet->addElement((INDEX1));   \
+        primSet->addElement((INDEX1));   \
+        primSet->addElement((INDEX0)+1); \
+        primSet->addElement((INDEX1)+1); \
+    } \
+}
+
+osg::Geometry*
+GeometryPool::createGeometry(const TileKey& tileKey,
+                             const MapInfo& mapInfo,
+                             MaskGenerator* maskSet) const
+{    
+    // Establish a local reference frame for the tile:
+    osg::Vec3d centerWorld;
+    GeoPoint centroid;
+    tileKey.getExtent().getCentroid( centroid );
+    centroid.toWorld( centerWorld );
+
+    osg::Matrix world2local, local2world;
+    centroid.createWorldToLocal( world2local );
+    local2world.invert( world2local );
+
+    // Attempt to calculate the number of verts in the surface geometry.
+    bool createSkirt = _options.heightFieldSkirtRatio() > 0.0f;
+
+    unsigned numVertsInSurface    = (_tileSize*_tileSize);
+    unsigned numVertsInSkirt      = createSkirt ? _tileSize*4u - 4u : 0;
+    unsigned numVerts             = numVertsInSurface + numVertsInSkirt;    
+    unsigned numIndiciesInSurface = (_tileSize-1) * (_tileSize-1) * 6;
+    unsigned numIncidesInSkirt    = getNumSkirtElements();
+    
+    GLenum mode = (_options.gpuTessellation() == true) ? GL_PATCHES : GL_TRIANGLES;
+
+    // Pre-allocate enough space for all triangles.
+    osg::DrawElements* primSet = new osg::DrawElementsUShort(mode);
+
+    primSet->reserveElements(numIndiciesInSurface + numIncidesInSkirt);
+
+    osg::BoundingSphere tileBound;
+
+    // the geometry:
+    osg::Geometry* geom = new osg::Geometry();
+    geom->setUseVertexBufferObjects(true);
+    geom->setUseDisplayList(false);
+
+    geom->addPrimitiveSet( primSet );
+
+    // the vertex locations:
+    osg::Vec3Array* verts = new osg::Vec3Array();
+    verts->reserve( numVerts );
+    geom->setVertexArray( verts );
+
+    // the surface normals (i.e. extrusion vectors)
+    osg::Vec3Array* normals = new osg::Vec3Array();
+    normals->reserve( numVerts );
+    geom->setNormalArray( normals );
+    geom->setNormalBinding( geom->BIND_PER_VERTEX );
+
+    osg::Vec3Array* neighbors = 0L;
+    if ( _options.morphTerrain() == true )
+    {
+        // neighbor positions (for morphing)
+        neighbors = new osg::Vec3Array();
+        neighbors->reserve( numVerts );
+        geom->setTexCoordArray( 1, neighbors );
+    }
+
+    // tex coord is [0..1] across the tile. The 3rd dimension tracks whether the
+    // vert is masked: 0=yes, 1=no
+#ifdef SHARE_TEX_COORDS
+    bool populateTexCoords = false;
+    if ( !_sharedTexCoords.valid() )
+    {
+        _sharedTexCoords = new osg::Vec3Array();
+        _sharedTexCoords->reserve( numVerts );
+        populateTexCoords = true;
+    }    
+    osg::Vec3Array* texCoords = _sharedTexCoords.get();
+#else
+    bool populateTexCoords = true;
+    osg::Vec3Array* texCoords = new osg::Vec3Array();
+    texCoords->reserve( numVerts );
+#endif
+
+    geom->setTexCoordArray( 0, texCoords );
+    
+    float delta = 1.0/(_tileSize-1);
+    osg::Vec3d tdelta(delta,0,0);
+    tdelta.normalize();
+    osg::Vec3d vZero(0,0,0);
+
+    osg::ref_ptr<GeoLocator> locator = GeoLocator::createForKey( tileKey, mapInfo );
+
+    for(unsigned row=0; row<_tileSize; ++row)
+    {
+        float ny = (float)row/(float)(_tileSize-1);
+        for(unsigned col=0; col<_tileSize; ++col)
+        {
+            float nx = (float)col/(float)(_tileSize-1);
+
+            osg::Vec3d model;
+            locator->unitToModel(osg::Vec3d(nx, ny, 0.0f), model);
+            osg::Vec3d modelLTP = model*world2local;
+            verts->push_back( modelLTP );
+            tileBound.expandBy( verts->back() );
+
+            if ( populateTexCoords )
+            {
+                // if masked then set textCoord z-value to 0.0
+                float marker = maskSet ? maskSet->getMarker(nx, ny) : MASK_MARKER_NORMAL;
+                texCoords->push_back( osg::Vec3f(nx, ny, marker) );
+            }
+
+            osg::Vec3d modelPlusOne;
+            locator->unitToModel(osg::Vec3d(nx, ny, 1.0f), modelPlusOne);
+            osg::Vec3d normal = (modelPlusOne*world2local)-modelLTP;                
+            normal.normalize();
+            normals->push_back( normal );
+
+            // neighbor:
+            if ( neighbors )
+            {
+                osg::Vec3d modelNeighborLTP = (*verts)[verts->size() - getMorphNeighborIndexOffset(col, row, _tileSize)];
+                neighbors->push_back(modelNeighborLTP);
+            }
+        }
+    }
+
+    // Now tessellate the surface.
+    
+    // TODO: do we really need this??
+    bool swapOrientation = !locator->orientationOpenGL();
+
+    for(unsigned j=0; j<_tileSize-1; ++j)
+    {
+        for(unsigned i=0; i<_tileSize-1; ++i)
+        {
+            int i00;
+            int i01;
+            if (swapOrientation)
+            {
+                i01 = j*_tileSize + i;
+                i00 = i01+_tileSize;
+            }
+            else
+            {
+                i00 = j*_tileSize + i;
+                i01 = i00+_tileSize;
+            }
+
+            int i10 = i00+1;
+            int i11 = i01+1;
+
+            // skip any triangles that have a discarded vertex:
+            bool discard = maskSet && (
+                maskSet->isMasked( (*texCoords)[i00] ) ||
+                maskSet->isMasked( (*texCoords)[i11] )
+            );
+
+            if ( !discard )
+            {
+                discard = maskSet && maskSet->isMasked( (*texCoords)[i01] );
+                if ( !discard )
+                {
+                    primSet->addElement(i01);
+                    primSet->addElement(i00);
+                    primSet->addElement(i11);
+                }
+            
+                discard = maskSet && maskSet->isMasked( (*texCoords)[i10] );
+                if ( !discard )
+                {
+                    primSet->addElement(i00);
+                    primSet->addElement(i10);
+                    primSet->addElement(i11);
+                }
+            }
+        }
+    }
+
+    if ( createSkirt )
+    {
+        // SKIRTS:
+        // calculate the skirt extrusion height
+        double height = tileBound.radius() * _options.heightFieldSkirtRatio().get();
+        
+        unsigned skirtIndex = verts->size();
+
+        // first, create all the skirt verts, normals, and texcoords.
+        for(int c=0; c<(int)_tileSize-1; ++c)
+            addSkirtDataForIndex( c, height ); //top
+
+        for(int r=0; r<(int)_tileSize-1; ++r)
+            addSkirtDataForIndex( r*_tileSize+(_tileSize-1), height ); //right
+    
+        for(int c=_tileSize-1; c>=0; --c)
+            addSkirtDataForIndex( (_tileSize-1)*_tileSize+c, height ); //bottom
+
+        for(int r=_tileSize-1; r>=0; --r)
+            addSkirtDataForIndex( r*_tileSize, height ); //left
+    
+        // then create the elements indices:
+        int i;
+        for(i=skirtIndex; i<(int)verts->size()-2; i+=2)
+            addSkirtTriangles( i, i+2 );
+
+        addSkirtTriangles( i, skirtIndex );
+    }
+
+    // create mask geometry
+    if (maskSet)
+    {
+        osg::ref_ptr<osg::DrawElementsUInt> maskPrim = maskSet->createMaskPrimitives(mapInfo, verts, texCoords, normals, neighbors);
+        if (maskPrim)
+            geom->addPrimitiveSet( maskPrim );
+    }
+
+    return geom;
+}
+
+
+void
+GeometryPool::setReleaser(ResourceReleaser* releaser)
+{
+    if (_releaser.valid())
+        ADJUST_UPDATE_TRAV_COUNT(this, -1);
+
+    _releaser = releaser;
+
+    if (_releaser.valid())
+        ADJUST_UPDATE_TRAV_COUNT(this, +1);
+}
+
+
+void
+GeometryPool::traverse(osg::NodeVisitor& nv)
+{
+    if (nv.getVisitorType() == nv.UPDATE_VISITOR && _releaser.valid() && _enabled)
+    {
+        // look for usused pool objects and push them to the resource releaser.
+        ResourceReleaser::ObjectList objects;
+        {
+            Threading::ScopedMutexLock exclusive( _geometryMapMutex );
+
+            std::vector<GeometryKey> keys;
+
+            for (GeometryMap::iterator i = _geometryMap.begin(); i != _geometryMap.end(); ++i)
+            {
+                if (i->second.get()->referenceCount() == 1)
+                {
+                    keys.push_back(i->first);
+                    objects.push_back(i->second.get());
+                }
+            }
+            for (std::vector<GeometryKey>::iterator key = keys.begin(); key != keys.end(); ++key)
+            {
+                _geometryMap.erase(*key);
+            }
+        }
+
+        if (!objects.empty())
+        {
+            _releaser->push(objects);
+        }
+    }
+
+    osg::Group::traverse(nv);
+}
diff --git a/src/osgEarthDrivers/engine_rex/LoadTileData b/src/osgEarthDrivers/engine_rex/LoadTileData
new file mode 100644
index 0000000..e02a316
--- /dev/null
+++ b/src/osgEarthDrivers/engine_rex/LoadTileData
@@ -0,0 +1,51 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+* Copyright 2008-2014 Pelican Mapping
+* http://osgearth.org
+*
+* osgEarth is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public License
+* along with this program.  If not, see <http://www.gnu.org/licenses/>
+*/
+#ifndef OSGEARTH_REX_LOAD_TILE_DATA
+#define OSGEARTH_REX_LOAD_TILE_DATA 1
+
+#include "Common"
+#include "Loader"
+#include "RenderBindings"
+#include "TileNode"
+#include "EngineContext"
+
+namespace osgEarth { namespace Drivers { namespace RexTerrainEngine
+{    
+    class LoadTileData : public Loader::Request
+    {
+    public:
+        LoadTileData(TileNode* tilenode, EngineContext* factory);
+
+    public: // Loader::Request
+
+        /** Fetches the data for the tile node. */
+        void invoke();
+
+        /** Applies the fetched data to the tile node (scene-graph safe) */
+        void apply(const osg::FrameStamp*);
+
+    protected:
+        osg::observer_ptr<TileNode>    _tilenode;
+        EngineContext*              _context;
+        osg::ref_ptr<TerrainTileModel> _model;
+    };
+
+} } } // namespace osgEarth::Drivers::RexTerrainEngine
+
+#endif // OSGEARTH_REX_LOAD_TILE_DATA
diff --git a/src/osgEarthDrivers/engine_rex/LoadTileData.cpp b/src/osgEarthDrivers/engine_rex/LoadTileData.cpp
new file mode 100644
index 0000000..fe3aace
--- /dev/null
+++ b/src/osgEarthDrivers/engine_rex/LoadTileData.cpp
@@ -0,0 +1,268 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+* Copyright 2008-2014 Pelican Mapping
+* http://osgearth.org
+*
+* osgEarth is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public License
+* along with this program.  If not, see <http://www.gnu.org/licenses/>
+*/
+#include "LoadTileData"
+#include "MPTexture"
+#include <osgEarth/TerrainEngineNode>
+#include <osgEarth/Terrain>
+#include <osgEarth/Registry>
+#include <osg/NodeVisitor>
+
+using namespace osgEarth::Drivers::RexTerrainEngine;
+using namespace osgEarth;
+
+#define LC "[LoadTileData] "
+
+namespace
+{
+    // Visitor that recalculates the sampler inheritance matrices in a graph.
+    struct UpdateInheritance : public osg::NodeVisitor
+    {
+        UpdateInheritance(EngineContext* context, Loader::Request::ChangeSet& changeSet)
+            : _context(context),
+              _changeSet(changeSet)
+        {
+            setTraversalMode( TRAVERSE_ALL_CHILDREN );
+        }
+
+        void apply(osg::Group& node)
+        {
+            TileNode* tilenode = dynamic_cast<TileNode*>(&node);
+            if ( tilenode )
+            {
+                if ( tilenode->inheritState( _context ) )
+                {
+                    // return true = changes occurred.
+                    _changeSet.push_back( tilenode );
+                }
+            }
+
+            traverse(node);
+        }
+
+        Loader::Request::ChangeSet& _changeSet;
+        EngineContext*              _context;
+    };
+}
+
+//............................................................................
+
+
+LoadTileData::LoadTileData(TileNode* tilenode, EngineContext* context) :
+_tilenode(tilenode),
+_context(context)
+{
+    //nop
+}
+
+namespace
+{
+    void applyDefaultUnRefPolicy(osg::Texture* tex)
+    {
+        const optional<bool>& unRefPolicy = Registry::instance()->unRefImageDataAfterApply();
+        tex->setUnRefImageDataAfterApply( unRefPolicy.get() );
+    }
+}
+
+
+// invoke runs in the background pager thread.
+void
+LoadTileData::invoke()
+{
+    osg::ref_ptr<TileNode> tilenode;
+    if ( _tilenode.lock(tilenode) )
+    {
+        osg::ref_ptr<ProgressCallback> progress; // = new ProgressCallback();
+
+        // Assemble all the components necessary to display this tile
+        _model = _context->getEngine()->createTileModel(
+            _context->getMapFrame(),
+            tilenode->getTileKey(),
+            progress ); // progress
+
+        // Prep the stateset for merging (and for GL pre-compile).
+        if ( _model.valid() )
+        {
+#if 0
+            if ( progress.valid() )
+            {
+                int count = (int)progress->stats("http_get_count");
+                if ( count > 0 )
+                {
+                    double t = (progress->stats("http_get_time")*1000.0);
+                    OE_NOTICE << LC << tilenode->getTileKey().str()
+                        << " : http_get_time = " << t << " ms, "
+                        << " : http_get_count = " << count << ", avg = " << (t/count) << std::endl;
+                }
+            }
+#endif
+
+            const RenderBindings& bindings = _context->getRenderBindings();
+
+            osg::StateSet* stateSet = getStateSet();
+
+            // Insert all the color layers into a new MPTexture state attribute,
+            // which exists to facilitate GL pre-compilation.
+            if ( _model->colorLayers().size() > 0 )
+            {
+                const SamplerBinding* colorBinding = SamplerBinding::findUsage(bindings, SamplerBinding::COLOR);
+                if ( colorBinding )
+                {
+                    osg::ref_ptr<MPTexture> mptex = new MPTexture();
+
+                    for(TerrainTileImageLayerModelVector::iterator i = _model->colorLayers().begin();
+                        i != _model->colorLayers().end();
+                        ++i)
+                    {
+                        TerrainTileImageLayerModel* layerModel = i->get();
+                        if ( layerModel && layerModel->getTexture() )
+                        {
+                            applyDefaultUnRefPolicy( layerModel->getTexture() );
+                            mptex->setLayer( layerModel->getImageLayer(), layerModel->getTexture(), layerModel->getOrder() );
+                        }
+                    }
+
+                    if ( !mptex->getPasses().empty() )
+                    {
+                        stateSet->setTextureAttribute(
+                            colorBinding->unit(),
+                            mptex );
+                    }
+                }
+            }
+
+            // Insert the elevation texture and an identity matrix:
+            if ( _model->elevationModel().valid() && _model->elevationModel()->getTexture())
+            {
+                const SamplerBinding* binding = SamplerBinding::findUsage(bindings, SamplerBinding::ELEVATION);
+                if ( binding )
+                {                
+                    applyDefaultUnRefPolicy( _model->elevationModel()->getTexture() );
+
+                    stateSet->setTextureAttribute(
+                        binding->unit(),
+                        _model->elevationModel()->getTexture() );
+
+                    stateSet->removeUniform(binding->matrixName());
+
+                    stateSet->addUniform( _context->getOrCreateMatrixUniform(
+                        binding->matrixName(),
+                        osg::Matrixf::identity() ) );    
+                }
+            }
+            
+            // Insert the normal texture and an identity matrix:
+            if ( _model->normalModel().valid() && _model->normalModel()->getTexture() )
+            {
+                const SamplerBinding* binding = SamplerBinding::findUsage(bindings, SamplerBinding::NORMAL);
+                if ( binding )
+                {
+                    //TODO: if we subload the normal texture later on, we will need to change unref to false.
+                    applyDefaultUnRefPolicy( _model->normalModel()->getTexture() );
+
+                    stateSet->setTextureAttribute(
+                        binding->unit(),
+                        _model->normalModel()->getTexture() );
+
+                    stateSet->removeUniform(binding->matrixName());
+
+                    stateSet->addUniform( _context->getOrCreateMatrixUniform(
+                        binding->matrixName(),
+                        osg::Matrixf::identity() ) );
+                }
+            }
+
+            // Process any shared image layers, each of which should have its
+            // own sampler binding point
+            for(TerrainTileImageLayerModelVector::iterator i = _model->sharedLayers().begin();
+                i != _model->sharedLayers().end();
+                ++i)
+            {
+                TerrainTileImageLayerModel* layerModel = i->get();
+                if ( layerModel->getTexture() )
+                {
+                    const SamplerBinding* binding = SamplerBinding::findUID(bindings, layerModel->getImageLayer()->getUID());
+                    if ( binding )
+                    {
+                        applyDefaultUnRefPolicy( layerModel->getTexture() );
+
+                        stateSet->setTextureAttribute(
+                            binding->unit(),
+                            layerModel->getTexture() );
+
+                        stateSet->removeUniform(binding->matrixName());
+
+                        stateSet->addUniform( _context->getOrCreateMatrixUniform(
+                            binding->matrixName(),
+                            osg::Matrixf::identity() ) );
+                    }
+                }
+            }
+        }
+    }
+}
+
+
+// apply() runs in the update traversal and can safely alter the scene graph
+void
+LoadTileData::apply(const osg::FrameStamp* stamp)
+{
+    if ( _model.valid() )
+    {
+        osg::ref_ptr<TileNode> tilenode;
+        if ( _tilenode.lock(tilenode) )
+        {
+            const RenderBindings& bindings      = _context->getRenderBindings();
+            const SelectionInfo&  selectionInfo = _context->getSelectionInfo();
+            const MapInfo&        mapInfo       = _context->getMapFrame().getMapInfo();
+
+            const SamplerBinding* color = SamplerBinding::findUsage(bindings, SamplerBinding::COLOR);
+
+            // Find the mptexture, and then remove it since it was only in the state set for ICO compilation.
+            osg::ref_ptr<MPTexture> mptex = dynamic_cast<MPTexture*>(
+                getStateSet()->getTextureAttribute( color->unit(), osg::StateAttribute::TEXTURE) );
+
+            if ( mptex.valid() )
+            {
+                getStateSet()->removeTextureAttribute( color->unit(), mptex.get() );
+            }
+
+            // Merge our prepped stateset into the live one.
+            tilenode->mergeStateSet( getStateSet(), mptex.get(), bindings);
+
+            // Update existing inheritance matrices as necessary.
+            UpdateInheritance update( _context, getChangeSet() );
+            tilenode->accept( update );
+
+            // Mark as complete. TODO: per-data requests will do something different.
+            tilenode->setDirty( false );
+
+            // Notify listeners that we've added a tile.
+            _context->getEngine()->getTerrain()->notifyTileAdded( _key, tilenode );
+
+            OE_DEBUG << LC << "apply " << _model->getKey().str() << "\n";
+
+            // Delete the model immediately
+            _model = 0L;
+        }
+        else
+        {
+            OE_DEBUG << LC << "LoadTileData failed; TileNode disappeared\n";
+        }
+    }
+}
diff --git a/src/osgEarthDrivers/engine_rex/Loader b/src/osgEarthDrivers/engine_rex/Loader
new file mode 100644
index 0000000..be16849
--- /dev/null
+++ b/src/osgEarthDrivers/engine_rex/Loader
@@ -0,0 +1,227 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+ * Copyright 2008-2014 Pelican Mapping
+ * http://osgearth.org
+ *
+ * osgEarth is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ */
+#ifndef OSGEARTH_REX_LOADER
+#define OSGEARTH_REX_LOADER 1
+
+#include "Common"
+
+#include <osgEarth/IOTypes>
+#include <osgEarth/ThreadingUtils>
+#include <osgEarth/TileKey>
+
+#include <osg/ref_ptr>
+#include <osg/Group>
+
+#include <osgDB/Options>
+#include <set>
+
+namespace osgEarth {
+    class TerrainEngine;
+}
+
+namespace osgEarth { namespace Drivers { namespace RexTerrainEngine
+{
+    class TileNodeRegistry; // for UnloaderGroup
+
+
+    /** Interface for a utility to satifies loading requests. */
+    class Loader
+    {
+    public:
+        class Handler;
+
+        class Request : public osg::Referenced
+        {
+        public:
+            typedef std::vector<osg::Node*> ChangeSet;
+
+        public:
+            Request();
+
+            /** Name the request */
+            void setName(const std::string& name) { _name = name; }
+            const std::string& getName() const { return _name; }
+
+            /** TileKey associated with this request */
+            void setTileKey(const TileKey& key) { _key = key; }
+            const TileKey& getTileKey() const { return _key; }
+
+            /** Invoke the operation - not safe to alter the graph */
+            virtual void invoke() { }
+
+            /** Apply the results of the invoke operation - runs safely in update stage */
+            virtual void apply(const osg::FrameStamp*) { }
+
+            /** Request apply() should call this to mark a node as "changed" */
+            void addToChangeSet(osg::Node* Node);
+            
+            /** Loader calls this to process and reset the change set */
+            ChangeSet& getChangeSet() { return _nodesChanged; }
+
+            bool operator()(const Request& lhs, const Request& rhs) const {
+                return lhs._uid < rhs._uid;
+            }
+
+            UID getUID() const { return _uid; }
+
+            /** Access the stateset that holds optional GL-compilable objects. */
+            osg::StateSet* getStateSet();
+
+            void setFrameNumber(unsigned fn) { _lastFrameSubmitted = fn; }
+            unsigned getLastFrameSubmitted() const { return _lastFrameSubmitted; }
+
+            enum State {
+                IDLE,
+                RUNNING,
+                MERGING,
+                FINISHED
+            };
+
+            void setState(State value) {
+                _state = value;
+                if ( _state == IDLE )
+                    _loadCount = 0;
+            }
+
+            bool isIdle() const { return _state == IDLE; }
+            bool isRunning() const { return _state == RUNNING; }
+            bool isMerging() const { return _state == MERGING; }
+            bool isFinished() const { return _state == FINISHED; }
+
+            UID                           _uid;
+            std::string                   _name;
+            TileKey                       _key;
+            State                         _state;
+            float                         _priority;
+            osg::ref_ptr<osg::Referenced> _internalHandle;
+            unsigned                      _lastFrameSubmitted;
+            osg::Timer_t                  _lastTick;
+            osg::ref_ptr<osg::StateSet>   _stateSet;
+            mutable Threading::Mutex      _lock;
+            int                           _loadCount;
+
+            void lock() { _lock.lock(); }
+            void unlock() { _lock.unlock(); }
+
+            ChangeSet                     _nodesChanged;
+        };
+
+        class Handler : public osg::Referenced
+        {
+        public:
+            virtual void operator()(Request* request) =0;
+        };
+
+        /** Start or continue loading a request. */
+        virtual bool load(Loader::Request* req, float priority, osg::NodeVisitor& nv) =0;
+
+        /** Clear out all pending requests. */
+        virtual void clear() =0;
+    };
+
+
+    class LoaderGroup : public osg::Group, public Loader
+    {
+    public: // Loader
+        void setFrameStamp(const osg::FrameStamp* fs) { _frameStamp = fs; }
+        const osg::FrameStamp* getFrameStamp() const { return _frameStamp.get(); }
+
+    protected:
+        osg::ref_ptr<const osg::FrameStamp> _frameStamp;
+    };
+
+
+    /** Loader that immediately invokes and applies synchronously. */
+    class SimpleLoader : public LoaderGroup
+    {
+    public:
+        SimpleLoader();
+
+    public: // Loader
+        bool load(Loader::Request* req, float priority, osg::NodeVisitor& nv);
+
+        void clear();
+    };
+
+
+    /** Loader that uses the OSG database pager to run requests in the background. */
+    class PagerLoader : public LoaderGroup
+    {
+    public:
+        PagerLoader(TerrainEngine* engine); //UID engineUID);
+
+        /** Sets the maximum number of requests to merge per frame. 0=infinity */
+        void setMergesPerFrame(int);
+
+    public: // Loader
+
+        /** Asks the loader to begin or continue loading something.
+            Returns true if a NEW request was scheduled; false if an existing request was updated. */
+        bool load(Loader::Request* req, float priority, osg::NodeVisitor& nv);
+
+        /** Cancel all pending requests. */
+        void clear();
+
+    public: // osg::Group
+
+        bool addChild(osg::Node*);
+
+        void traverse(osg::NodeVisitor& nv);
+
+    public:
+
+        /** Internal method to invoke a request that was previously queued with load(). */
+        Request* invokeAndRelease(UID requestUID);
+
+        /** Returns the tilekey associated with the request (or TileKey::INVALID if none) */
+        TileKey getTileKeyForRequest(UID requestUID) const;
+
+    protected:
+        
+        void processChangeSet(Loader::Request* req);
+
+        typedef std::map<UID, osg::ref_ptr<Loader::Request> > Requests;
+
+        typedef osg::ref_ptr<Loader::Request> RefRequest;
+
+        struct SortRequest {
+            bool operator()(const RefRequest& lhs, const RefRequest& rhs) const {
+                return lhs->_priority > rhs->_priority;
+            }
+        };
+
+        //typedef std::set<RefRequest, SortRequest> MergeQueue;
+        typedef std::multiset<RefRequest, SortRequest> MergeQueue;
+
+        UID              _engineUID;
+        osg::NodePath    _myNodePath;
+        Requests         _requests;
+        MergeQueue       _mergeQueue;  
+        osg::Timer_t     _checkpoint;
+        int              _mergesPerFrame;
+        unsigned         _frameNumber;
+
+        osg::ref_ptr<osgDB::Options> _dboptions;
+        mutable Threading::Mutex     _requestsMutex;
+    };
+
+} } }
+
+
+#endif // OSGEARTH_REX_LOADER
diff --git a/src/osgEarthDrivers/engine_rex/Loader.cpp b/src/osgEarthDrivers/engine_rex/Loader.cpp
new file mode 100644
index 0000000..2064786
--- /dev/null
+++ b/src/osgEarthDrivers/engine_rex/Loader.cpp
@@ -0,0 +1,483 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+ * Copyright 2008-2014 Pelican Mapping
+ * http://osgearth.org
+ *
+ * osgEarth is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ */
+#include "Loader"
+#include "RexTerrainEngineNode"
+
+#include <osgEarth/Registry>
+#include <osgDB/FileNameUtils>
+#include <osgDB/FileUtils>
+#include <osgDB/Registry>
+#include <osgDB/ReaderWriter>
+
+#include <string>
+
+#define REPORT_ACTIVITY true
+
+using namespace osgEarth::Drivers::RexTerrainEngine;
+
+
+Loader::Request::Request()
+{
+    _uid = osgEarth::Registry::instance()->createUID();
+    _state = IDLE;
+    _loadCount = 0;
+    _priority = 0;
+    _lastFrameSubmitted = 0;
+    _lastTick = 0;
+}
+
+osg::StateSet*
+Loader::Request::getStateSet()
+{
+    if ( !_stateSet.valid() )
+    {
+        _stateSet = new osg::StateSet();
+        _stateSet->setDataVariance( osg::Object::DYNAMIC );
+    }
+    return _stateSet.get();
+}
+
+void
+Loader::Request::addToChangeSet(osg::Node* node)
+{
+    if ( node )
+    {
+        _nodesChanged.push_back( node );
+    }
+}
+
+//...............................................
+
+#undef  LC
+#define LC "[SimpleLoader] "
+
+SimpleLoader::SimpleLoader()
+{
+}
+
+bool
+SimpleLoader::load(Loader::Request* request, float priority, osg::NodeVisitor& nv)
+{
+    if ( request )
+    {
+        // take a reference, which will cause an unref after load.
+        osg::ref_ptr<Request> r = request;
+
+        //OE_INFO << LC << "Request invoke : UID = " << request->getUID() << "\n";
+        request->invoke();
+        
+        //OE_INFO << LC << "Request apply : UID = " << request->getUID() << "\n";
+        request->apply( nv.getFrameStamp() );
+    }
+    return request != 0L;
+}
+
+void
+SimpleLoader::clear()
+{
+    // nop.
+}
+
+//...............................................
+
+#undef  LC
+#define LC "[PagerLoader.FileLocationCallback] "
+
+namespace
+{ 
+    class FileLocationCallback : public osgDB::FileLocationCallback
+    {
+    public:
+        FileLocationCallback() { }
+
+        /** dtor */
+        virtual ~FileLocationCallback() { }
+
+        Location fileLocation(const std::string& filename, const osgDB::Options* dboptions)
+        {
+            Location result = REMOTE_FILE;
+
+            osgEarth::UID requestUID, engineUID;
+
+            sscanf(filename.c_str(), "%d.%d", &requestUID, &engineUID);
+
+            osg::ref_ptr<RexTerrainEngineNode> engine;
+            RexTerrainEngineNode::getEngineByUID( (UID)engineUID, engine );
+
+            if ( engine.valid() )
+            {
+                PagerLoader* loader = dynamic_cast<PagerLoader*>( engine->getLoader() );
+                if ( loader )
+                {
+                    TileKey key = loader->getTileKeyForRequest(requestUID);
+
+                    MapFrame frame(engine->getMap());
+                    if ( frame.isCached(key) )
+                    {
+                        result = LOCAL_FILE;
+                    }
+                }
+
+                //OE_NOTICE << "key=" << key.str() << " : " << (result==LOCAL_FILE?"local":"remote") << "\n";
+            }
+
+            return result;
+        }
+
+        bool useFileCache() const { return false; }
+    };
+}
+
+//...............................................
+
+#undef  LC
+#define LC "[PagerLoader] "
+
+namespace
+{
+    struct RequestResultNode : public osg::Node
+    {
+        RequestResultNode(Loader::Request* request)
+            : _request(request)
+        {
+            // Do this so the pager/ICO can find and pre-compile GL objects that are
+            // attached to the stateset.
+            if ( _request.valid() )
+            {
+                // TODO: for some reason pre-compiling is causing texture flashing issues 
+                // with things like classification maps when using --ico. Figure out why.
+                setStateSet( _request->getStateSet() );
+            }
+        }
+
+        Loader::Request* getRequest() const { return _request.get(); }
+
+        osg::ref_ptr<Loader::Request> _request;
+    };
+}
+
+
+PagerLoader::PagerLoader(TerrainEngine* engine) :
+_engineUID     ( engine->getUID() ),
+_checkpoint    ( (osg::Timer_t)0 ),
+_mergesPerFrame( 0 ),
+_frameNumber   ( 0 )
+{
+    _myNodePath.push_back( this );
+
+    _dboptions = new osgDB::Options();
+    _dboptions->setFileLocationCallback( new FileLocationCallback() );
+}
+
+void
+PagerLoader::setMergesPerFrame(int value)
+{
+    _mergesPerFrame = std::max(value, 0);
+    this->setNumChildrenRequiringUpdateTraversal( 1 );
+}
+
+bool
+PagerLoader::load(Loader::Request* request, float priority, osg::NodeVisitor& nv)
+{
+    // check that the request is not already completed but unmerged:
+    //if ( request && !request->isMerging() && nv.getDatabaseRequestHandler() )
+    if ( request && !request->isMerging() && !request->isFinished() && nv.getDatabaseRequestHandler() )
+    {
+        //OE_INFO << LC << "load (" << request->getTileKey().str() << ")" << std::endl;
+
+        unsigned fn = 0;
+        if ( nv.getFrameStamp() )
+        {
+            fn = nv.getFrameStamp()->getFrameNumber();
+            request->setFrameNumber( fn );
+        }
+
+        bool addToRequestSet = false;
+
+        // lock the request since multiple cull traversals might hit this function.
+        request->lock();
+        {
+            request->setState(Request::RUNNING);
+
+            // remember the last tick at which this request was submitted
+            request->_lastTick = osg::Timer::instance()->tick();
+
+            // update the priority
+            request->_priority = priority;
+
+            // timestamp it
+            request->setFrameNumber( fn );
+
+            // incremenet the load count.
+            request->_loadCount++;
+
+            // if this is the first load request since idle, we need to remember this request.
+            addToRequestSet = (request->_loadCount == 1);
+        }
+        request->unlock();
+
+        char filename[64];
+        sprintf(filename, "%u.%u.osgearth_rex_loader", request->_uid, _engineUID);
+        //std::string filename = Stringify() << request->_uid << "." << _engineUID << ".osgearth_rex_loader";
+
+        // scale from LOD to 0..1 range, more or less
+        // TODO: need to balance this with normal PagedLOD priority setup
+        //float scaledPriority = priority / 20.0f;
+
+        nv.getDatabaseRequestHandler()->requestNodeFile(
+            filename,
+            _myNodePath,
+            priority,
+            nv.getFrameStamp(),
+            request->_internalHandle,
+            _dboptions.get() );
+
+        // remember the request:
+        if ( true ) // addToRequestSet // Not sure whether we need to keep doing this in order keep it sorted -- check it out.
+        {
+            Threading::ScopedMutexLock lock( _requestsMutex );
+            _requests[request->getUID()] = request;
+        }
+
+        return true;
+    }
+    return false;
+}
+
+void
+PagerLoader::clear()
+{
+    // Set a time checkpoint for invalidating old requests.
+    _checkpoint = osg::Timer::instance()->tick();
+}
+
+void
+PagerLoader::traverse(osg::NodeVisitor& nv)
+{
+    // only called when _mergesPerFrame > 0
+    if ( nv.getVisitorType() == nv.UPDATE_VISITOR )
+    {
+        if ( nv.getFrameStamp() )
+        {
+            setFrameStamp(nv.getFrameStamp());
+        }
+
+        int count;
+        for(count=0; count < _mergesPerFrame && !_mergeQueue.empty(); ++count)
+        {
+            Request* req = _mergeQueue.begin()->get();
+            if ( req && req->_lastTick >= _checkpoint )
+            {
+                OE_START_TIMER(req_apply);
+                req->apply( getFrameStamp() );
+                double s = OE_STOP_TIMER(req_apply);
+
+                req->setState(Request::FINISHED);
+            }
+
+            _mergeQueue.erase( _mergeQueue.begin() );
+        }
+
+        // cull finished requests.
+        {
+            Threading::ScopedMutexLock lock( _requestsMutex );
+
+            unsigned fn = 0;
+            if ( nv.getFrameStamp() )
+                fn = nv.getFrameStamp()->getFrameNumber();
+
+            // Purge expired requests.
+            for(Requests::iterator i = _requests.begin(); i != _requests.end(); )
+            {
+                Request* req = i->second.get();
+
+                if ( req->isFinished() )
+                {
+                    //OE_INFO << LC << req->getName() << "(" << i->second->getUID() << ") finished." << std::endl; 
+                    req->setState( Request::IDLE );
+                    if ( REPORT_ACTIVITY )
+                        Registry::instance()->endActivity( req->getName() );
+                    _requests.erase( i++ );
+                }
+
+                else if ( !req->isMerging() && (fn - req->getLastFrameSubmitted() > 2) )
+                {
+                    //OE_INFO << LC << req->getName() << "(" << i->second->getUID() << ") died waiting after " << fn-req->getLastFrameSubmitted() << " frames" << std::endl; 
+                    req->setState( Request::IDLE );
+                    if ( REPORT_ACTIVITY )
+                        Registry::instance()->endActivity( req->getName() );
+                    _requests.erase( i++ );
+                }
+
+                else // still valid.
+                {
+                    ++i;
+                }
+            }
+
+            //OE_NOTICE << LC << "PagerLoader: requests=" << _requests.size() << "; mergeQueue=" << _mergeQueue.size() << std::endl;
+        }
+    }
+
+    LoaderGroup::traverse( nv );
+}
+
+
+bool
+PagerLoader::addChild(osg::Node* node)
+{
+    osg::ref_ptr<RequestResultNode> result = dynamic_cast<RequestResultNode*>(node);
+    if ( result.valid() )
+    {
+        Request* req = result->getRequest();
+        if ( req )
+        {
+            if ( req->_lastTick >= _checkpoint )
+            {
+                if ( _mergesPerFrame > 0 )
+                {
+                    _mergeQueue.insert( req );
+                    req->setState( Request::MERGING );
+                }
+                else
+                {
+                    req->apply( getFrameStamp() );
+                    req->setState( Request::FINISHED );
+                    if ( REPORT_ACTIVITY )
+                        Registry::instance()->endActivity( req->getName() );
+                }
+            }                
+
+            else
+            {
+                req->setState( Request::FINISHED );
+                if ( REPORT_ACTIVITY )
+                    Registry::instance()->endActivity( req->getName() );
+            }
+        }
+    }
+
+    else
+    {
+        //OE_WARN << LC << "Internal error: illegal node type in addchild" << std::endl;
+    }
+    return true;
+}
+
+TileKey
+PagerLoader::getTileKeyForRequest(UID requestUID) const
+{
+    Threading::ScopedMutexLock lock( _requestsMutex );
+    Requests::const_iterator i = _requests.find( requestUID );
+    if ( i != _requests.end() )
+    {
+        return i->second->getTileKey();
+    }
+
+    return TileKey::INVALID;
+}
+
+Loader::Request*
+PagerLoader::invokeAndRelease(UID requestUID)
+{
+    osg::ref_ptr<Request> request;
+    {
+        Threading::ScopedMutexLock lock( _requestsMutex );
+        Requests::iterator i = _requests.find( requestUID );
+        if ( i != _requests.end() )
+        {
+            request = i->second.get();
+        }
+    }
+
+    if ( request.valid() )
+    {
+        if ( REPORT_ACTIVITY )
+            Registry::instance()->startActivity( request->getName() );
+
+        request->invoke();
+    }
+
+    else
+    {
+        // If request is NULL, that means that the Pager dispatched a request that 
+        // has already died on the vine.
+        //OE_WARN << LC << "Internal: invokeAndRelease (" << requestUID << ") not found." << std::endl;
+    }
+
+    return request.release();
+}
+
+
+
+namespace osgEarth { namespace Drivers { namespace RexTerrainEngine
+{
+    using namespace osgEarth;
+
+    /** Registry Plugin Agent. */
+    struct PagerLoaderAgent : public osgDB::ReaderWriter
+    {
+        PagerLoaderAgent()
+        {
+            //nop
+        }
+
+        virtual const char* className() const
+        {
+            return "osgEarth REX Loader Agent";
+        }
+
+        virtual bool acceptsExtension(const std::string& extension) const
+        {
+            return osgDB::equalCaseInsensitive( extension, "osgearth_rex_loader" );
+        }
+
+        ReadResult readNode(const std::string& uri, const osgDB::Options* dboptions) const
+        {
+            std::string ext = osgDB::getFileExtension(uri);
+            if ( acceptsExtension(ext) )
+            {
+                // parse the tile key and engine ID:
+                std::string requestdef = osgDB::getNameLessExtension(uri);
+                unsigned requestUID, engineUID;
+                sscanf(requestdef.c_str(), "%u.%u", &requestUID, &engineUID);
+
+                // find the appropriate engine:
+                osg::ref_ptr<RexTerrainEngineNode> engineNode;
+                RexTerrainEngineNode::getEngineByUID( (UID)engineUID, engineNode );
+                if ( engineNode.valid() )
+                {
+                    PagerLoader* loader = dynamic_cast<PagerLoader*>(engineNode->getLoader());
+                    if ( loader )
+                    {
+                        Loader::Request* req = loader->invokeAndRelease( requestUID );
+                        return new RequestResultNode(req);
+                    }
+                }
+                return ReadResult::FILE_NOT_FOUND;
+            }
+            else
+            {
+                return ReadResult::FILE_NOT_HANDLED;
+            }
+        };
+    };
+    REGISTER_OSGPLUGIN(osgearth_rex_loader, PagerLoaderAgent);
+
+} } } // namespace osgEarth::Drivers::RexTerrainEngine
diff --git a/src/osgEarthDrivers/engine_rex/MPTexture b/src/osgEarthDrivers/engine_rex/MPTexture
new file mode 100644
index 0000000..111b361
--- /dev/null
+++ b/src/osgEarthDrivers/engine_rex/MPTexture
@@ -0,0 +1,106 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+* Copyright 2008-2014 Pelican Mapping
+* http://osgearth.org
+*
+* osgEarth is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public License
+* along with this program.  If not, see <http://www.gnu.org/licenses/>
+*/
+#ifndef OSGEARTH_REX_MPTEXTURE
+#define OSGEARTH_REX_MPTEXTURE 1
+
+#include "Common"
+#include <osg/Texture2D>
+#include <osgEarth/ImageLayer>
+
+using namespace osgEarth;
+
+namespace osgEarth { namespace Drivers { namespace RexTerrainEngine
+{
+    /**
+     * MPTexture is a multipass texture attribute that holds one or more Texture2D
+     * objects each with associated texture matrix.
+     *
+     * We don't actually store it in the TileNode's stateSet. The reason it is a 
+     * StateAttribute (and subclassed from Texture2D) is so that OSG's GL object
+     * pre-compile visitors will find it and process it.
+     */
+    class MPTexture : public osg::Texture2D
+    {
+    public:
+        /** A single color layer pass. */
+        struct Pass
+        {
+            Pass() : _ownsTexture(false), _order(0) { }
+
+            Pass(const Pass& rhs) {
+                _layer = rhs._layer.get();
+                _order = rhs._order;
+                _texture = rhs._texture.get();
+                _textureMatrix = rhs._textureMatrix;
+                _ownsTexture = false; //rhs._ownsTexture;
+                _parentTexture = rhs._parentTexture.get();
+                _parentTextureMatrix = rhs._parentTextureMatrix;
+            }
+
+            osg::ref_ptr<const ImageLayer> _layer;          // source image layer
+            int                            _order;          // rendering order
+            osg::ref_ptr<osg::Texture>     _texture;        // texture object
+            osg::Matrixf                   _textureMatrix;  // scale bias matrix for inherited textures.
+            bool                           _ownsTexture;    // whether this key/pass owns this texture.
+
+            osg::ref_ptr<osg::Texture>     _parentTexture;
+            osg::Matrixf                   _parentTextureMatrix;
+        };
+
+        typedef std::vector<Pass> Passes;
+
+    public:
+        /** ctor */
+        MPTexture();
+
+        /** Sets or adds an image layer and associated texture object as a pass. */
+        void setLayer(const ImageLayer* layer, osg::Texture* tex, int order);
+
+        /** Passes to be drawn for this object. */
+        const Passes& getPasses() const { return _passes; }
+
+        /** Merge the contents of "rhs" into this object. */
+        void merge(MPTexture* rhs);
+
+        /** Inherit pass information from another MPTexture with scale/bias information. */
+        void inheritState(MPTexture* parent, const osg::Matrixf& scaleBias);
+
+    public: // osg::Texture
+
+        // override an nullify apply; functionality happens manually in TileDrawable
+        void apply(osg::State& state) const { }
+
+        // support GL pre-compilation, etc.
+        void compileGLObjects(osg::State& state) const;
+        void resizeGLObjectBuffers(unsigned int maxSize);
+        void releaseGLObjects(osg::State* state=0) const;
+
+    protected:
+        virtual ~MPTexture() { }
+
+        Passes _passes;
+        
+    private:
+        /** copy ctor - disabled */
+        MPTexture(const MPTexture& rhs) { }
+    };
+
+} } } // namespace osgEarth::Drivers::RexTerrainEngine
+
+#endif // OSGEARTH_REX_MPTEXTURE
diff --git a/src/osgEarthDrivers/engine_rex/MPTexture.cpp b/src/osgEarthDrivers/engine_rex/MPTexture.cpp
new file mode 100644
index 0000000..b378e9d
--- /dev/null
+++ b/src/osgEarthDrivers/engine_rex/MPTexture.cpp
@@ -0,0 +1,171 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+* Copyright 2008-2014 Pelican Mapping
+* http://osgearth.org
+*
+* osgEarth is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public License
+* along with this program.  If not, see <http://www.gnu.org/licenses/>
+*/
+#include "MPTexture"
+
+using namespace osgEarth::Drivers::RexTerrainEngine;
+using namespace osgEarth;
+
+#define LC "[MPTexture] "
+
+MPTexture::MPTexture() :
+osg::Texture2D()
+{
+    //nop
+}
+
+void
+MPTexture::setLayer(const ImageLayer* layer, osg::Texture* tex, int order)
+{
+    Passes::iterator insertionPoint = _passes.end();
+
+    // If the layer already exists as a pass, update it
+    for(Passes::iterator pass = _passes.begin(); pass != _passes.end(); ++pass)
+    {
+        if ( pass->_layer.get() == layer )
+        {
+            pass->_texture = tex;
+            pass->_ownsTexture = true;
+            pass->_textureMatrix = osg::Matrixf::identity();
+            return;
+        }
+        else if ( order < pass->_order )
+        {
+            insertionPoint = pass;
+        }            
+    }
+
+    // Layer didn't already exist; add it (in the proper order)
+    Pass& pass = *_passes.insert( insertionPoint, Pass() );
+    pass._layer   = layer;
+    pass._texture = tex;
+    pass._parentTexture = tex;
+    pass._order   = order;
+    pass._ownsTexture = true;
+}
+
+void
+MPTexture::merge(MPTexture* rhs)
+{
+    if ( rhs )
+    {
+        for(Passes::const_iterator pass = rhs->getPasses().begin(); pass != rhs->getPasses().end(); ++pass)
+        {
+            setLayer( pass->_layer.get(), pass->_texture.get(), pass->_order );
+        }
+    }
+}
+
+void
+MPTexture::inheritState(MPTexture* parent, const osg::Matrixf& scaleBias)
+{
+    if ( parent )
+    {
+        // First time around, copy the parent's data in whole, and then scale/bias
+        // the texture matrix to the appropriate quadrant
+        if ( _passes.empty() )
+        {
+            // copy it:
+            _passes = parent->getPasses();
+
+            for(Passes::iterator pass = _passes.begin(); pass != _passes.end(); ++pass)
+            {
+                // scale and bias the texture matrix; then the new parent texture just
+                // points to the main texture until the main texture gets replaced later.
+                pass->_textureMatrix.preMult( scaleBias );
+                pass->_parentTexture = pass->_texture.get();
+                pass->_parentTextureMatrix = pass->_textureMatrix;
+                pass->_ownsTexture = false;
+            }
+        }
+
+        // If this object already has data, recalculate the sub-matrixing on all
+        // existing textures and parent-textures:
+        else
+        {
+            for(Passes::const_iterator parentPass = parent->getPasses().begin(); parentPass != parent->getPasses().end(); ++parentPass)
+            {
+                for(Passes::iterator pass = _passes.begin(); pass != _passes.end(); ++pass)
+                {
+                    if ( parentPass->_layer.get() == pass->_layer.get())
+                    {
+                        // If the texture matrix is non-identity, that means we are inheriting from another tile.
+                        // In this case, re-copy from the parent (in case it changed) and recalculate the
+                        // texture matrix.
+                        if ( !pass->_textureMatrix.isIdentity() )
+                        {
+                            pass->_texture = parentPass->_texture.get();
+                            pass->_textureMatrix = parentPass->_textureMatrix;
+                            pass->_textureMatrix.preMult( scaleBias );
+                        }
+                        
+                        // Update the parent texture always.
+                        if ( parentPass->_texture.valid() )
+                        {
+                            pass->_parentTexture = parentPass->_texture.get();
+                            pass->_parentTextureMatrix = parentPass->_textureMatrix;
+                            pass->_parentTextureMatrix.preMult( scaleBias );
+                        }
+                        else
+                        {
+                            pass->_parentTexture = pass->_texture.get();
+                            pass->_parentTextureMatrix = pass->_textureMatrix;
+                        }
+                    }
+                }
+            }
+        }
+    }
+}
+
+void 
+MPTexture::compileGLObjects(osg::State& state) const
+{
+    for(Passes::const_iterator pass = _passes.begin(); pass != _passes.end(); ++pass)
+    {
+        if ( pass->_texture.valid() ) //&& pass->_ownsTexture )
+        {
+            pass->_texture->apply(state);
+        }
+    }
+}
+
+void
+MPTexture::resizeGLObjectBuffers(unsigned int maxSize)
+{
+    for(Passes::const_iterator pass = _passes.begin(); pass != _passes.end(); ++pass)
+    {
+        if ( pass->_texture.valid() && pass->_ownsTexture )
+        {
+            pass->_texture->resizeGLObjectBuffers(maxSize);
+        }
+    }
+}
+
+void
+MPTexture::releaseGLObjects(osg::State* state) const
+{
+    for(Passes::const_iterator pass = _passes.begin(); pass != _passes.end(); ++pass)
+    {
+        // check the refcount since textures are shared across MPTexture instances.
+        if ( pass->_texture.valid() && pass->_texture->referenceCount() == 1 )
+        {
+            pass->_texture->releaseGLObjects(state);
+        }
+    }
+}
diff --git a/src/osgEarthDrivers/engine_rex/MaskGenerator b/src/osgEarthDrivers/engine_rex/MaskGenerator
new file mode 100644
index 0000000..fad96a8
--- /dev/null
+++ b/src/osgEarthDrivers/engine_rex/MaskGenerator
@@ -0,0 +1,102 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+* Copyright 2008-2014 Pelican Mapping
+* http://osgearth.org
+*
+* osgEarth is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public License
+* along with this program.  If not, see <http://www.gnu.org/licenses/>
+*/
+#ifndef OSGEARTH_DRIVERS_REX_MASK_GENERATOR
+#define OSGEARTH_DRIVERS_REX_MASK_GENERATOR 1
+
+#include "Common"
+#include <osgEarth/MapFrame>
+#include <osgEarth/TileKey>
+#include <osg/Geometry>
+
+#define MASK_MARKER_DISCARD  0.0f    // do not draw
+#define MASK_MARKER_NORMAL   1.0f    // normal vertex
+#define MASK_MARKER_SKIRT    2.0f    // not subject to morphing
+#define MASK_MARKER_BOUNDARY 3.0f    // not subject to elevation texture
+
+namespace osgEarth { namespace Drivers { namespace RexTerrainEngine
+{
+    using namespace osgEarth;
+
+    /**
+     * Record that stores the data for a single masking region.
+     */
+    struct MaskRecord
+    {
+        osg::ref_ptr<osg::Vec3dArray> _boundary;
+        osg::Vec3d                    _ndcMin, _ndcMax;
+        osg::Geometry*                _geom;
+        osg::ref_ptr<osg::Vec3Array>  _internal;
+
+        MaskRecord(osg::Vec3dArray* boundary, osg::Vec3d& ndcMin, osg::Vec3d& ndcMax, osg::Geometry* geom) 
+            : _boundary(boundary), _ndcMin(ndcMin), _ndcMax(ndcMax), _geom(geom), _internal(new osg::Vec3Array()) { }
+    };
+
+    typedef std::vector<MaskRecord> MaskRecordVector;
+
+
+    /**
+     * Creates geometry for the part of a tile containing mask data.
+     */
+    class MaskGenerator : public osg::Referenced
+    {
+    public:
+        MaskGenerator(const TileKey& key, unsigned tileSize, const MapFrame& mapFrame);
+
+
+        bool hasMasks() const
+        {
+            return _maskRecords.size() > 0;
+        }
+
+        /** whether a texcoord indicates that the corresponding vert is masked. */
+        bool isMasked(const osg::Vec3f& texCoord) const
+        {
+            return texCoord.z() == MASK_MARKER_DISCARD;
+        }
+
+        /** whether the masking geometry contains a unit location. */
+        /*  0.0 - contains                                         */
+        /*  1.0 - does not contain                                 */
+        /*  2.0 - does not contain but is a tile vert on the outer */
+        /*        masking skirt boundary                           */
+        float getMarker(float nx, float ny) const;
+
+        bool containedByQuadAtColRow(int col, int row, int tileSize) const
+        {
+            // Placeholder for now.
+            return false;
+        }
+
+        void getMinMax(osg::Vec3d& min, osg::Vec3d& max);
+
+        osg::DrawElementsUInt* createMaskPrimitives(const MapInfo& mapInfo, osg::Vec3Array* verts, osg::Vec3Array* texCoords,  osg::Vec3Array* normals, osg::Vec3Array* neighbors);
+
+    protected:
+        void setupMaskRecord(const MapFrame& mapFrame, osg::Vec3dArray* boundary);
+
+    protected:
+        const TileKey    _key;
+        unsigned _tileSize;
+        MaskRecordVector _maskRecords;
+        osg::Vec3d _ndcMin, _ndcMax;
+    };
+
+} } } // namespace osgEarth::Drivers::RexTerrainEngine
+
+#endif // OSGEARTH_DRIVERS_REX_MASK_GENERATOR
diff --git a/src/osgEarthDrivers/engine_rex/MaskGenerator.cpp b/src/osgEarthDrivers/engine_rex/MaskGenerator.cpp
new file mode 100644
index 0000000..51ff8c5
--- /dev/null
+++ b/src/osgEarthDrivers/engine_rex/MaskGenerator.cpp
@@ -0,0 +1,532 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+* Copyright 2008-2014 Pelican Mapping
+* http://osgearth.org
+*
+* osgEarth is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public License
+* along with this program.  If not, see <http://www.gnu.org/licenses/>
+*/
+#include "MaskGenerator"
+
+#include <osgEarth/Locators>
+#include <osgEarthSymbology/Geometry>
+
+#include <osgUtil/DelaunayTriangulator>
+
+
+using namespace osgEarth::Drivers::RexTerrainEngine;
+using namespace osgEarth::Symbology;
+
+
+#define LC "[MaskGenerator] "
+
+#define MATCH_TOLERANCE 0.000001
+
+
+MaskGenerator::MaskGenerator(const TileKey& key, unsigned tileSize, const MapFrame& mapFrame) :
+_key( key ), _tileSize(tileSize)
+{
+    const osgEarth::MaskLayerVector maskLayers = mapFrame.terrainMaskLayers();
+    for(MaskLayerVector::const_iterator it = maskLayers.begin();
+        it != maskLayers.end(); 
+        ++it)
+    {
+        MaskLayer* layer = it->get();
+        if ( layer->getMinLevel() <= key.getLevelOfDetail() )
+        {
+            setupMaskRecord( mapFrame, layer->getOrCreateMaskBoundary( 1.0, key.getExtent().getSRS(), (ProgressCallback*)0L ) );
+        }
+    }
+}
+
+void
+MaskGenerator::setupMaskRecord(const MapFrame& mapFrame, osg::Vec3dArray* boundary)
+{
+    osg::ref_ptr<osgEarth::GeoLocator> geoLocator = GeoLocator::createForKey(_key, mapFrame.getMapInfo());
+    if (geoLocator->getCoordinateSystemType() == GeoLocator::GEOCENTRIC)
+        geoLocator = geoLocator->getGeographicFromGeocentric();
+
+    if ( boundary )
+    {
+        osg::Vec3d min, max;
+        min = max = boundary->front();
+
+        for (osg::Vec3dArray::iterator it = boundary->begin(); it != boundary->end(); ++it)
+        {
+            if (it->x() < min.x())
+            min.x() = it->x();
+
+            if (it->y() < min.y())
+            min.y() = it->y();
+
+            if (it->x() > max.x())
+            max.x() = it->x();
+
+            if (it->y() > max.y())
+            max.y() = it->y();
+        }
+
+        osg::Vec3d min_ndc, max_ndc;
+        geoLocator->modelToUnit(min, min_ndc);
+        geoLocator->modelToUnit(max, max_ndc);
+
+        bool x_match = ((min_ndc.x() >= 0.0 && max_ndc.x() <= 1.0) ||
+                        (min_ndc.x() <= 0.0 && max_ndc.x() > 0.0) ||
+                        (min_ndc.x() < 1.0 && max_ndc.x() >= 1.0));
+
+        bool y_match = ((min_ndc.y() >= 0.0 && max_ndc.y() <= 1.0) ||
+                        (min_ndc.y() <= 0.0 && max_ndc.y() > 0.0) ||
+                        (min_ndc.y() < 1.0 && max_ndc.y() >= 1.0));
+
+        if (x_match && y_match)
+        {
+            if (_maskRecords.size() == 0)
+            {
+                _ndcMin = min_ndc;
+                _ndcMax = max_ndc;
+            }
+            else
+            {
+                if (min_ndc.x() < _ndcMin.x()) _ndcMin.x() = min_ndc.x();
+                if (min_ndc.y() < _ndcMin.y()) _ndcMin.y() = min_ndc.y();
+                if (max_ndc.x() > _ndcMax.x()) _ndcMax.x() = max_ndc.x();
+                if (max_ndc.y() > _ndcMax.y()) _ndcMax.y() = max_ndc.y();
+            }
+
+            _maskRecords.push_back( MaskRecord(boundary, min_ndc, max_ndc, 0L) );
+        }
+    }
+}
+
+osg::DrawElementsUInt*
+MaskGenerator::createMaskPrimitives(const MapInfo& mapInfo, osg::Vec3Array* verts, osg::Vec3Array* texCoords, osg::Vec3Array* normals, osg::Vec3Array* neighbors)
+{
+    if (_maskRecords.size() <= 0)
+      return 0L;
+
+    osg::ref_ptr<osgEarth::GeoLocator> geoLocator = GeoLocator::createForKey(_key, mapInfo);
+    if (geoLocator->getCoordinateSystemType() == GeoLocator::GEOCENTRIC)
+        geoLocator = geoLocator->getGeographicFromGeocentric();
+
+    GeoPoint centroid;
+    _key.getExtent().getCentroid( centroid );
+
+    osg::Matrix world2local, local2world;
+    centroid.createWorldToLocal( world2local );
+    local2world.invert( world2local );
+
+    osg::ref_ptr<osgUtil::DelaunayTriangulator> trig=new osgUtil::DelaunayTriangulator();
+
+    std::vector<osg::ref_ptr<osgUtil::DelaunayConstraint> > alldcs;
+
+    osg::ref_ptr<osg::Vec3Array> coordsArray = new osg::Vec3Array;
+
+    double minndcx = _maskRecords[0]._ndcMin.x();
+    double minndcy = _maskRecords[0]._ndcMin.y();
+    double maxndcx = _maskRecords[0]._ndcMax.x();
+    double maxndcy = _maskRecords[0]._ndcMax.y();
+    for (int mrs = 1; mrs < _maskRecords.size(); ++mrs)
+    {
+        if ( _maskRecords[mrs]._ndcMin.x()< minndcx)
+        {
+            minndcx = _maskRecords[mrs]._ndcMin.x();
+        }
+        if ( _maskRecords[mrs]._ndcMin.y()< minndcy)
+        {
+            minndcy = _maskRecords[mrs]._ndcMin.y();
+        }
+        if ( _maskRecords[mrs]._ndcMax.x()> maxndcx)
+        {
+            maxndcx = _maskRecords[mrs]._ndcMax.x();
+        }
+        if ( _maskRecords[mrs]._ndcMax.y()> maxndcy)
+        {
+            maxndcy = _maskRecords[mrs]._ndcMax.y();
+        }			
+    }
+
+    int min_i = (int)floor(minndcx * (double)(_tileSize-1));
+    if (min_i < 0) min_i = 0;
+    if (min_i >= (int)_tileSize) min_i = _tileSize - 1;
+
+    int min_j = (int)floor(minndcy * (double)(_tileSize-1));
+    if (min_j < 0) min_j = 0;
+    if (min_j >= (int)_tileSize) min_j = _tileSize - 1;
+
+    int max_i = (int)ceil(maxndcx * (double)(_tileSize-1));
+    if (max_i < 0) max_i = 0;
+    if (max_i >= (int)_tileSize) max_i = _tileSize - 1;
+
+    int max_j = (int)ceil(maxndcy * (double)(_tileSize-1));
+    if (max_j < 0) max_j = 0;
+    if (max_j >= (int)_tileSize) max_j = _tileSize - 1;
+
+    if (min_i >= 0 && max_i >= 0 && min_j >= 0 && max_j >= 0)
+    {
+        int num_i = max_i - min_i + 1;
+        int num_j = max_j - min_j + 1;
+
+        osg::ref_ptr<Polygon> maskSkirtPoly = new Polygon();
+        maskSkirtPoly->resize(num_i * 2 + num_j * 2 - 4);
+
+        for (int i = 0; i < num_i; i++)
+        {
+            {
+                osg::Vec3d ndc( ((double)(i + min_i))/(double)(_tileSize-1), ((double)min_j)/(double)(_tileSize-1), 0.0);
+                (*maskSkirtPoly)[i] = ndc;
+            }
+
+            {
+                osg::Vec3d ndc( ((double)(i + min_i))/(double)(_tileSize-1), ((double)max_j)/(double)(_tileSize-1), 0.0);
+                (*maskSkirtPoly)[i + (2 * num_i + num_j - 3) - 2 * i] = ndc;
+            }
+        }
+        for (int j = 0; j < num_j - 2; j++)
+        {
+            {
+                osg::Vec3d ndc( ((double)max_i)/(double)(_tileSize-1), ((double)(min_j + j + 1))/(double)(_tileSize-1), 0.0);
+                (*maskSkirtPoly)[j + num_i] = ndc;
+            }
+
+            {
+                osg::Vec3d ndc( ((double)min_i)/(double)(_tileSize-1), ((double)(min_j + j + 1))/(double)(_tileSize-1), 0.0);
+                (*maskSkirtPoly)[j + (2 * num_i + 2 * num_j - 5) - 2 * j] = ndc;
+            }
+        }
+
+        for (int j = 0; j < num_j; j++)
+        {
+            for (int i = 0; i < num_i; i++)
+            {
+                {
+                    osg::Vec3d ndc( ((double)(i + min_i))/(double)(_tileSize-1), ((double)(j+min_j))/(double)(_tileSize-1), 0.0);
+                    coordsArray->push_back(ndc) ;
+                }						
+            }
+        }
+
+
+        //
+        osg::ref_ptr<osg::Vec3dArray> boundaryVerts = new osg::Vec3dArray;
+
+        // Use delaunay triangulation for stitching:
+        for (MaskRecordVector::iterator mr = _maskRecords.begin();mr != _maskRecords.end();mr++)
+        {
+            //Create local polygon representing mask
+            osg::ref_ptr<Polygon> maskPoly = new Polygon();
+            for (osg::Vec3dArray::iterator it = (*mr)._boundary->begin(); it != (*mr)._boundary->end(); ++it)
+            {
+                osg::Vec3d local;
+                geoLocator->convertModelToLocal(*it, local);
+                maskPoly->push_back(local);
+            }
+
+            // Add mask bounds as a triangulation constraint
+            osg::ref_ptr<osgUtil::DelaunayConstraint> newdc=new osgUtil::DelaunayConstraint;
+            osg::Vec3Array* maskConstraint = new osg::Vec3Array();
+            newdc->setVertexArray(maskConstraint);
+
+            //Crop the mask to the stitching poly (for case where mask crosses tile edge)
+            osg::ref_ptr<Geometry> maskCrop;
+            maskPoly->crop(maskSkirtPoly.get(), maskCrop);
+
+            GeometryIterator i( maskCrop.get(), false );
+            while( i.hasMore() )
+            {
+                Geometry* part = i.next();
+                if (!part)
+                    continue;
+
+                if (part->getType() == Geometry::TYPE_POLYGON)
+                {
+                    osg::ref_ptr<osg::Vec3Array> partVerts = part->createVec3Array();
+                    maskConstraint->insert(maskConstraint->end(), partVerts->begin(), partVerts->end());
+                    newdc->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::LINE_LOOP, maskConstraint->size() - partVerts->size(), partVerts->size()));
+                }
+            }
+
+            // Cropping strips z-values so need reassign
+            std::vector<int> isZSet;
+            for (osg::Vec3Array::iterator it = maskConstraint->begin(); it != maskConstraint->end(); ++it)
+            {
+                int zSet = 0;
+
+                //Look for verts that belong to the original mask skirt polygon
+                for (Polygon::iterator mit = maskSkirtPoly->begin(); mit != maskSkirtPoly->end(); ++mit)
+                {
+                    if (osg::absolute((*mit).x() - (*it).x()) < MATCH_TOLERANCE && osg::absolute((*mit).y() - (*it).y()) < MATCH_TOLERANCE)
+                    {
+                        //(*it).z() = (*mit).z();
+                        zSet += 1;
+
+                        // Remove duplicate point from coordsArray to avoid duplicate point warnings
+                        osg::Vec3Array::iterator caIt;
+                        for (caIt = coordsArray->begin(); caIt != coordsArray->end(); ++caIt)
+                        {
+                            if (osg::absolute((*caIt).x() - (*it).x()) < MATCH_TOLERANCE && osg::absolute((*caIt).y() - (*it).y()) < MATCH_TOLERANCE)
+                                break;
+                        }
+                        if (caIt != coordsArray->end())
+                            coordsArray->erase(caIt);
+
+                        break;
+                    }
+                }
+
+                //Look for verts that belong to the mask polygon
+                for (Polygon::iterator mit = maskPoly->begin(); mit != maskPoly->end(); ++mit)
+                {
+                    if (osg::absolute((*mit).x() - (*it).x()) < MATCH_TOLERANCE && osg::absolute((*mit).y() - (*it).y()) < MATCH_TOLERANCE)
+                    {
+                        (*it).z() = (*mit).z();
+                        zSet += 2;
+
+                        boundaryVerts->push_back((*it));
+                        break;
+                    }
+                }
+
+                isZSet.push_back(zSet);
+            }
+
+            //Any mask skirt verts that are still unset are newly created verts where the skirt
+            //meets the mask. Find the mask segment the point lies along and calculate the
+            //appropriate z value for the point.
+            int count = 0;
+            for (osg::Vec3Array::iterator it = maskConstraint->begin(); it != maskConstraint->end(); ++it)
+            {
+                //If the z-value was set from a mask vertex there is no need to change it.  If
+                //it was set from a vertex from the stitching polygon it may need overriden if
+                //the vertex lies along a mask edge.  Or if it is unset, it will need to be set.
+                //if (isZSet[count] < 2)
+                if (!isZSet[count])
+                {
+                    osg::Vec3d p2 = *it;
+                    double closestZ = 0.0;
+                    double closestRatio = DBL_MAX;
+                    for (Polygon::iterator mit = maskPoly->begin(); mit != maskPoly->end(); ++mit)
+                    {
+                        osg::Vec3d p1 = *mit;
+                        osg::Vec3d p3 = mit == --maskPoly->end() ? maskPoly->front() : (*(mit + 1));
+
+                        //Truncated vales to compensate for accuracy issues
+                        double p1x = ((int)(p1.x() * 1000000)) / 1000000.0L;
+                        double p3x = ((int)(p3.x() * 1000000)) / 1000000.0L;
+                        double p2x = ((int)(p2.x() * 1000000)) / 1000000.0L;
+
+                        double p1y = ((int)(p1.y() * 1000000)) / 1000000.0L;
+                        double p3y = ((int)(p3.y() * 1000000)) / 1000000.0L;
+                        double p2y = ((int)(p2.y() * 1000000)) / 1000000.0L;
+
+                        if ((p1x < p3x ? p2x >= p1x && p2x <= p3x : p2x >= p3x && p2x <= p1x) &&
+                            (p1y < p3y ? p2y >= p1y && p2y <= p3y : p2y >= p3y && p2y <= p1y))
+                        {
+                            double l1 =(osg::Vec2d(p2.x(), p2.y()) - osg::Vec2d(p1.x(), p1.y())).length();
+                            double lt = (osg::Vec2d(p3.x(), p3.y()) - osg::Vec2d(p1.x(), p1.y())).length();
+                            double zmag = p3.z() - p1.z();
+
+                            double foundZ = (l1 / lt) * zmag + p1.z();
+
+                            double mRatio = 1.0;
+                            if (osg::absolute(p1x - p3x) < MATCH_TOLERANCE)
+                            {
+                                if (osg::absolute(p1x-p2x) < MATCH_TOLERANCE)
+                                    mRatio = 0.0;
+                            }
+                            else
+                            {
+                                double m1 = p1x == p2x ? 0.0 : (p2y - p1y) / (p2x - p1x);
+                                double m2 = p1x == p3x ? 0.0 : (p3y - p1y) / (p3x - p1x);
+                                mRatio = m2 == 0.0 ? m1 : osg::absolute(1.0L - m1 / m2);
+                            }
+
+                            if (mRatio < 0.01)
+                            {
+                                (*it).z() = foundZ;
+                                isZSet[count] = 2;
+
+                                boundaryVerts->push_back((*it));
+                                break;
+                            }
+                            else if (mRatio < closestRatio)
+                            {
+                                closestRatio = mRatio;
+                                closestZ = foundZ;
+                            }
+                        }
+                    }
+
+                    if (!isZSet[count] && closestRatio < DBL_MAX)
+                    {
+                        (*it).z() = closestZ;
+                        isZSet[count] = 2;
+
+                        boundaryVerts->push_back((*it));
+                    }
+                }
+
+                if (!isZSet[count])
+                    OE_WARN << LC << "Z-value not set for mask constraint vertex" << std::endl;
+
+                count++;
+            }
+
+            alldcs.push_back(newdc);
+        }
+
+        trig->setInputPointArray(coordsArray.get());
+
+        for (int dcnum =0; dcnum < alldcs.size();dcnum++)
+        {
+            trig->addInputConstraint(alldcs[dcnum].get());
+        }
+
+        // Create array to hold vertex normals
+        osg::Vec3Array *norms=new osg::Vec3Array;
+        trig->setOutputNormalArray(norms);
+
+
+        // Triangulate vertices and remove triangles that lie within the contraint loop
+        trig->triangulate();
+        for (int dcnum =0; dcnum < alldcs.size();dcnum++)
+        {
+            trig->removeInternalTriangles(alldcs[dcnum].get());
+        }
+
+        verts->reserve(verts->size() + trig->getInputPointArray()->size());
+        texCoords->reserve(texCoords->size() + trig->getInputPointArray()->size());
+        normals->reserve(normals->size() + trig->getInputPointArray()->size());
+        if ( neighbors )
+            neighbors->reserve(neighbors->size() + trig->getInputPointArray()->size()); 
+
+        // Iterate through point to convert to model coords, calculate normals, and set up tex coords
+        osg::ref_ptr<GeoLocator> locator = GeoLocator::createForKey( _key, mapInfo );
+
+        //int norm_i = -1;
+        unsigned vertsOffset = verts->size();
+
+        for (osg::Vec3Array::iterator it = trig->getInputPointArray()->begin(); it != trig->getInputPointArray()->end(); ++it)
+        {
+            // check to see if point is a part of the original mask boundary
+            bool isBoundary = false;
+            for (osg::Vec3dArray::iterator bit = boundaryVerts->begin(); bit != boundaryVerts->end(); ++bit)
+            {
+                if (osg::absolute((*bit).x() - (*it).x()) < MATCH_TOLERANCE && osg::absolute((*bit).y() - (*it).y()) < MATCH_TOLERANCE)
+                {
+                    isBoundary = true;
+                    break;
+                }
+            }
+
+            // get model coords
+            osg::Vec3d model;
+            locator->unitToModel(osg::Vec3d(it->x(), it->y(), 0.0f), model);
+            model = model * world2local;
+
+            // calc normals
+            osg::Vec3d modelPlusOne;
+            locator->unitToModel(osg::Vec3d(it->x(), it->y(), 1.0f), modelPlusOne);
+            osg::Vec3d normal = (modelPlusOne*world2local)-model;                
+            normal.normalize();
+            normals->push_back( normal );
+
+            // set elevation if this is a point along the mask boundary
+            if (isBoundary)
+                model += normal*it->z();
+
+            verts->push_back(model);
+
+            // use same vert for neighbor to prevent morphing
+            if ( neighbors )
+                neighbors->push_back( model );  
+
+            // set up text coords
+            texCoords->push_back( osg::Vec3f(it->x(), it->y(), isBoundary ? MASK_MARKER_BOUNDARY : MASK_MARKER_SKIRT) );
+        }
+
+        // Get triangles from triangulator and add as primative set to the geometry
+        osg::DrawElementsUInt* tris = trig->getTriangles();
+        if ( tris && tris->getNumIndices() >= 3 )
+        {
+            osg::ref_ptr<osg::DrawElementsUInt> elems = new osg::DrawElementsUInt(tris->getMode());
+            elems->reserve(tris->size());
+
+            const osg::MixinVector<GLuint> ins = tris->asVector();
+            for (osg::MixinVector<GLuint>::const_iterator it = ins.begin(); it != ins.end(); ++it)
+            {
+                elems->push_back((*it) + vertsOffset);
+            }
+
+            return elems.release();
+        }
+    }
+
+    return 0L;
+}
+
+void
+MaskGenerator::getMinMax(osg::Vec3d& min, osg::Vec3d& max)
+{
+    if (_maskRecords.size() > 0)
+    {
+        min.x() = _maskRecords[0]._ndcMin.x();
+        min.y() = _maskRecords[0]._ndcMin.y();
+        min.z() = _maskRecords[0]._ndcMin.z();
+
+        max.x() = _maskRecords[0]._ndcMax.x();
+        max.y() = _maskRecords[0]._ndcMax.y();
+        max.z() = _maskRecords[0]._ndcMax.z();
+
+        for (MaskRecordVector::const_iterator it = _maskRecords.begin(); it != _maskRecords.end(); ++it)
+        {
+            if (it->_ndcMin.x() < min.x()) min.x() = it->_ndcMin.x();
+            if (it->_ndcMin.y() < min.y()) min.y() = it->_ndcMin.y();
+            if (it->_ndcMin.z() < min.z()) min.z() = it->_ndcMin.z();
+
+            if (it->_ndcMax.x() > max.x()) max.x() = it->_ndcMax.x();
+            if (it->_ndcMax.y() > max.y()) max.y() = it->_ndcMax.y();
+            if (it->_ndcMax.z() > max.z()) max.z() = it->_ndcMax.z();
+        }
+    }
+}
+
+float
+MaskGenerator::getMarker(float nx, float ny) const
+{
+    float marker = 1.0f; // 1.0 == does not contain
+
+    if (_maskRecords.size() > 0)
+    {
+        int min_i = (int)floor(_ndcMin.x() * (double)(_tileSize-1));
+        int min_j = (int)floor(_ndcMin.y() * (double)(_tileSize-1));
+        int max_i = (int)ceil(_ndcMax.x() * (double)(_tileSize-1));
+        int max_j = (int)ceil(_ndcMax.y() * (double)(_tileSize-1));
+
+        int i = nx * (double)(_tileSize-1);
+        int j = ny * (double)(_tileSize-1);
+
+        if (i > min_i && i < max_i && j > min_j && j < max_j)
+        {
+            marker = MASK_MARKER_DISCARD; // contained by mask
+        }
+        else if ((i == min_i && j >= min_j && j <= max_j) ||
+                 (i == max_i && j >= min_j && j <= max_j) ||
+                 (j == min_j && i >= min_i && i <= max_i) ||
+                 (j == max_j && i >= min_i && i <= max_i))
+        {
+            marker = MASK_MARKER_SKIRT; // tile vert on outer mask skirt boundary
+        }
+    }
+
+    return marker;
+}
\ No newline at end of file
diff --git a/src/osgEarthDrivers/engine_rex/ProxyGeometry b/src/osgEarthDrivers/engine_rex/ProxyGeometry
new file mode 100644
index 0000000..6a83be8
--- /dev/null
+++ b/src/osgEarthDrivers/engine_rex/ProxyGeometry
@@ -0,0 +1,75 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+* Copyright 2008-2014 Pelican Mapping
+* http://osgearth.org
+*
+* osgEarth is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public License
+* along with this program.  If not, see <http://www.gnu.org/licenses/>
+*/
+#ifndef OSGEARTH_DRIVERS_REX_TERRAIN_PROXY_GEOMETRY
+#define OSGEARTH_DRIVERS_REX_TERRAIN_PROXY_GEOMETRY 1
+
+#include "Common"
+
+#include <osg/Geometry>
+#include <osg/Matrix>
+
+#include <osgEarth/TileKey>
+
+namespace osgEarth
+{
+    class MapInfo;
+}
+
+namespace osgEarth { namespace Drivers { namespace RexTerrainEngine
+{
+    class IndexPool
+    {
+    public:
+        osg::DrawElements* getOrCreate(unsigned tileSize, bool swapOrientation);
+    private:
+        typedef std::map<unsigned, osg::ref_ptr<osg::DrawElements> > MapTileSizeToIndices;
+        MapTileSizeToIndices _mapIndices;
+    };
+
+    class ProxyGeometry : public osg::Geometry
+    {
+    public:
+        ProxyGeometry(const TileKey& key, const MapInfo& mapInfo, unsigned tileSize, const osg::Texture* elevationTexture);
+
+        const osg::Texture* getElevationTexture(void) const;
+
+        void accept(osg::PrimitiveFunctor& f) const ;
+        void accept(osg::PrimitiveIndexFunctor& f) const;
+
+    private:
+        void constructXReferenceFrame(void);
+        void constructEmptyGeometry(void);
+
+        void build(void);
+        void buildIfNecessary(void) const;
+        
+        void makeVertices(void);
+    private:
+        const TileKey  _key;
+        const unsigned _tileSize;
+        osg::ref_ptr<GeoLocator> _locator;
+
+        const osg::Texture* _elevationTexture;
+        osg::Matrix   _world2local;
+        osg::Matrix   _local2world;
+        static IndexPool _indexPool;
+    };
+
+} } } // namespace osgEarth::Drivers::RexTerrainEngine
+#endif
diff --git a/src/osgEarthDrivers/engine_rex/ProxyGeometry.cpp b/src/osgEarthDrivers/engine_rex/ProxyGeometry.cpp
new file mode 100644
index 0000000..51bf799
--- /dev/null
+++ b/src/osgEarthDrivers/engine_rex/ProxyGeometry.cpp
@@ -0,0 +1,234 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+* Copyright 2008-2014 Pelican Mapping
+* http://osgearth.org
+*
+* osgEarth is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public License
+* along with this program.  If not, see <http://www.gnu.org/licenses/>
+*/
+#include "ProxyGeometry"
+#include "ElevationTextureUtils"
+
+#include <osgEarth/Locators>
+#include <osgEarth/QuadTree>
+#include <osg/KdTree>
+
+using namespace osg;
+using namespace osgEarth::Drivers::RexTerrainEngine;
+using namespace osgEarth;
+
+#define OSGEARTH_REX_PROXY_GEOMETRY_DEBUG 0
+
+#define LC "[ProxyGeometry] "
+
+IndexPool ProxyGeometry::_indexPool;
+namespace 
+{
+    unsigned getNumberOfVerts(unsigned tileSize)
+    {
+        return (tileSize*tileSize);    
+    }
+
+    unsigned getNumberOfIndices(unsigned tileSize)
+    {
+        return (tileSize-1) * (tileSize-1) * 6;
+    }
+
+    unsigned getNumTriangles(unsigned tileSize)
+    {
+        return (tileSize-1)*(tileSize-1)*2;
+    }
+
+    void tessellate(osg::DrawElements* primSet, unsigned tileSize, bool swapOrientation)
+    {
+        int i00;
+        int i01;
+        for(unsigned j=0; j<tileSize-1; ++j)
+        {
+            for(unsigned i=0; i<tileSize-1; ++i)
+            {
+                if (swapOrientation)
+                {
+                    i01 = j*tileSize + i;
+                    i00 = i01+tileSize;
+                }
+                else
+                {
+                    i00 = j*tileSize + i;
+                    i01 = i00+tileSize;
+                }
+
+                int i10 = i00+1;
+                int i11 = i01+1;
+
+                primSet->addElement(i01);
+                primSet->addElement(i00);
+                primSet->addElement(i11);
+
+                primSet->addElement(i00);
+                primSet->addElement(i10);
+                primSet->addElement(i11);
+            }
+        }
+        primSet->dirty();
+    }
+}
+
+DrawElements* IndexPool::getOrCreate(unsigned tileSize, bool swapOrientation)
+{
+    MapTileSizeToIndices::const_iterator it = _mapIndices.find(tileSize);
+    if (it!=_mapIndices.end())
+    {
+        return it->second.get();
+    }
+
+    OE_INFO << LC <<" Constructing Indices for TileSize: "<<tileSize<<std::endl;
+
+    // Pre-allocate enough space for all triangles.
+    osg::DrawElements* primSet = new osg::DrawElementsUShort(GL_TRIANGLES);
+    primSet->reserveElements(getNumberOfIndices(tileSize));
+    _mapIndices.insert(std::make_pair(tileSize, primSet));
+    tessellate(primSet, tileSize, swapOrientation);
+
+    return primSet;
+}
+
+void
+ProxyGeometry::constructXReferenceFrame()
+{
+    // Establish a local reference frame for the tile:
+    osg::Vec3d centerWorld;
+    GeoPoint centroid;
+    _key.getExtent().getCentroid( centroid );
+    centroid.toWorld( centerWorld );
+
+    centroid.createWorldToLocal( _world2local );
+    _local2world.invert( _world2local );
+}
+
+void
+ProxyGeometry::constructEmptyGeometry()
+{
+    // the geometry:
+    osg::Geometry* geom = this;
+
+    // Pre-allocate enough space for all triangles.
+    osg::DrawElements* primSet = _indexPool.getOrCreate(_tileSize, !_locator->orientationOpenGL());
+    geom->addPrimitiveSet(primSet);
+
+#if OSGEARTH_REX_PROXY_GEOMETRY_DEBUG
+    geom->setUseVertexBufferObjects(true);
+#endif
+    geom->setUseDisplayList(false);
+
+    // the vertex locations:
+    osg::Vec3Array* verts = new osg::Vec3Array();
+    verts->reserve( getNumberOfVerts(_tileSize) );
+    geom->setVertexArray( verts );
+}
+
+ProxyGeometry::ProxyGeometry(const TileKey& key, const MapInfo& mapInfo, unsigned tileSize, const osg::Texture* elevationTexture) : 
+    _key(key), 
+    //_tileSize( 32 ), // temporary
+    _tileSize(elevationTexture->getImage(0)->s()),
+    _elevationTexture(elevationTexture)
+{
+    _locator = GeoLocator::createForKey( _key, mapInfo );
+}
+
+const osg::Texture*
+ProxyGeometry::getElevationTexture(void) const
+{
+    return _elevationTexture;
+}
+
+void
+ProxyGeometry::build(void)
+{
+    constructEmptyGeometry();    
+    constructXReferenceFrame();
+    OE_START_TIMER(b1);
+    makeVertices();
+    double t1 = OE_STOP_TIMER(b1);
+
+    QuadTree* quadTree = new QuadTree();
+    QuadTree::BuildOptions options;
+    options._maxNumLevels = 10;    // PPP: Auto compute an estimate?
+    options._targetNumTrianglesPerLeaf = 16*16;    // PPP: Auto compute an estimate?
+    options._numTriangles = getNumTriangles(_tileSize);
+    quadTree->build(options, this);
+    this->setShape(quadTree);
+
+
+    OE_INFO << LC << "Built proxy: "<<_key.str()<<", t=" << t1*1000 << " ms\n";
+}
+
+void
+ProxyGeometry::buildIfNecessary(void) const
+{
+    if (getVertexArray()==0)
+    {
+        ProxyGeometry* pNonConst = const_cast<ProxyGeometry*>(this);
+        pNonConst->build();
+    }   
+}
+
+void
+ProxyGeometry::accept(osg::PrimitiveFunctor& f) const 
+{
+    buildIfNecessary();
+    osg::Geometry::accept(f);
+}
+
+void
+ProxyGeometry::accept(osg::PrimitiveIndexFunctor& f) const
+{
+    buildIfNecessary();
+    osg::Geometry::accept(f);
+}
+
+void
+ProxyGeometry::makeVertices()
+{
+    //assert(_elevationTexture && _elevationTexture->getImage(0));
+    ElevationImageReader elevationImageReader(_elevationTexture->getImage(0));
+    if (elevationImageReader.valid()==false)
+    {
+        OE_DEBUG << LC << "Error: Cannot use elevation texture. Window too small!!"<<std::endl;
+        return;
+    }
+
+    osg::Vec3Array* verts   = static_cast<osg::Vec3Array*>(this->getVertexArray());
+
+    for(unsigned row=0; row<_tileSize; ++row)
+    {
+        float ny = (float)row/(float)(_tileSize-1);
+        for(unsigned col=0; col<_tileSize; ++col)
+        {
+            float nx = (float)col/(float)(_tileSize-1);
+
+            osg::Vec3d model;
+            _locator->unitToModel(osg::Vec3d(nx, ny, 0.0f), model);
+            osg::Vec3d modelLTP = model*_world2local;
+
+            osg::Vec3d modelPlusOne;
+            _locator->unitToModel(osg::Vec3d(nx, ny, 1.0f), modelPlusOne);
+            osg::Vec3d normal = (modelPlusOne*_world2local)-modelLTP;
+            normal.normalize();
+
+            //modelLTP = modelLTP + normal*elevationImageReader.elevationN(nx,ny);
+            verts->push_back( modelLTP);
+        }
+    }
+    verts->dirty();
+}
diff --git a/src/osgEarthDrivers/engine_rex/ProxySurfaceNode b/src/osgEarthDrivers/engine_rex/ProxySurfaceNode
new file mode 100644
index 0000000..4a4f216
--- /dev/null
+++ b/src/osgEarthDrivers/engine_rex/ProxySurfaceNode
@@ -0,0 +1,58 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+* Copyright 2008-2014 Pelican Mapping
+* http://osgearth.org
+*
+* osgEarth is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public License
+* along with this program.  If not, see <http://www.gnu.org/licenses/>
+*/
+#ifndef OSGEARTH_DRIVERS_REX_PROXY_SURFACE_NODE
+#define OSGEARTH_DRIVERS_REX_PROXY_SURFACE_NODE 1
+
+#include "Common"
+#include "ProxyGeometry"
+
+#include <osgEarth/TileKey>
+
+#include <osg/Vec3>
+#include <osg/MatrixTransform>
+#include <vector>
+
+namespace osgEarth
+{
+    class MapInfo;
+}
+
+namespace osgEarth { namespace Drivers { namespace RexTerrainEngine
+{
+    typedef std::vector<osg::Vec3> VectorPoints;
+    /**
+     * SurfaceNode holds the proxy (physics) geometry of the terrain surface.
+     */
+    class ProxySurfaceNode : public osg::MatrixTransform
+    {
+    public:
+        ProxySurfaceNode(const TileKey& key, const MapInfo& mapInfo, unsigned tileSize, const osg::Texture* pTexture);
+
+    protected:
+        virtual ~ProxySurfaceNode() { }
+
+        // container for proxy geometry
+        osg::ref_ptr<osg::Geode>   _proxySurfaceGeode;
+
+        // proxy geometry used for intersections, bounds, etc.
+        osg::ref_ptr<ProxyGeometry> _proxyGeom;
+    };
+} } } // namespace osgEarth::Drivers::RexTerrainEngine
+
+#endif // OSGEARTH_DRIVERS_REX_SURFACE_NODE
diff --git a/src/osgEarthDrivers/engine_rex/ProxySurfaceNode.cpp b/src/osgEarthDrivers/engine_rex/ProxySurfaceNode.cpp
new file mode 100644
index 0000000..b05ae97
--- /dev/null
+++ b/src/osgEarthDrivers/engine_rex/ProxySurfaceNode.cpp
@@ -0,0 +1,55 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+* Copyright 2008-2014 Pelican Mapping
+* http://osgearth.org
+*
+* osgEarth is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public License
+* along with this program.  If not, see <http://www.gnu.org/licenses/>
+*/
+#include "ProxySurfaceNode"
+#include "GeometryPool"
+
+#include <osgEarth/TileKey>
+
+#include <osg/Geode>
+
+#include <osg/Geometry>
+
+#include <numeric>
+
+using namespace osgEarth::Drivers::RexTerrainEngine;
+using namespace osgEarth;
+
+#define LC "[ProxySurfaceNode] "
+
+//..............................................................
+
+ProxySurfaceNode::ProxySurfaceNode(const TileKey& tilekey, const MapInfo& mapInfo, unsigned tileSize, const osg::Texture* pTexture)
+{
+    _proxyGeom = new ProxyGeometry(tilekey, mapInfo, tileSize, pTexture);
+
+    _proxySurfaceGeode = new osg::Geode();
+    _proxySurfaceGeode->addDrawable( _proxyGeom );
+
+    // Create the final node.
+    addChild( _proxySurfaceGeode.get() );
+
+    // Establish a local reference frame for the tile:
+    osg::Vec3d centerWorld;
+    GeoPoint centroid;
+    tilekey.getExtent().getCentroid(centroid);
+    centroid.toWorld(centerWorld);
+    osg::Matrix local2world;
+    centroid.createLocalToWorld( local2world );
+    setMatrix( local2world );
+}
diff --git a/src/osgEarthDrivers/engine_rex/RenderBindings b/src/osgEarthDrivers/engine_rex/RenderBindings
new file mode 100644
index 0000000..6b13d48
--- /dev/null
+++ b/src/osgEarthDrivers/engine_rex/RenderBindings
@@ -0,0 +1,97 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+ * Copyright 2008-2014 Pelican Mapping
+ * http://osgearth.org
+ *
+ * osgEarth is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ */
+#ifndef OSGEARTH_DRIVERS_REX_RENDER_BINDINGS_H
+#define OSGEARTH_DRIVERS_REX_RENDER_BINDINGS_H 1
+
+#include "Common"
+#include <osgEarth/Common>
+#include <osgEarth/optional>
+#include <vector>
+
+namespace osgEarth { namespace Drivers { namespace RexTerrainEngine
+{
+    class SamplerBinding
+    {
+    public:
+        enum Usage
+        {
+            COLOR,
+            ELEVATION,
+            NORMAL,
+            MATERIAL,
+            COLOR_PARENT
+        };
+
+    public:
+        SamplerBinding() : _unit(-1) { }
+
+        /** Optional UID of the source (usually a layer) to which this binding applies */
+        optional<osgEarth::UID>& sourceUID()             { return _sourceUID; }
+        const optional<osgEarth::UID>& sourceUID() const { return _sourceUID; }
+
+        /** Optional usage hint */
+        optional<Usage>& usage()             { return _usage; }
+        const optional<Usage>& usage() const { return _usage; }
+
+        /** Texture image unit of the sampler */
+        int& unit() { return _unit; }
+        const int& unit() const { return _unit; }
+
+        /** Uniform name of the sampler */
+        std::string& samplerName() { return _samplerName; }
+        const std::string& samplerName() const { return _samplerName; }
+
+        /** Uniform name of the sampler matrix */
+        std::string& matrixName() { return _matrixName; }
+        const std::string& matrixName() const { return _matrixName; }
+
+    public:
+        bool isActive() const { return _unit >= 0; }
+
+    private:
+        optional<UID>   _sourceUID;
+        optional<Usage> _usage;
+        int             _unit;
+        std::string     _samplerName;
+        std::string     _matrixName;
+
+    public:
+        static const SamplerBinding* findUsage(const std::vector<SamplerBinding>& v, Usage usage) {
+            for(int i=0; i<v.size(); ++i) {
+                if ( v[i].usage().isSetTo(usage) )
+                    return &v[i];
+            }
+            return 0L;
+        }
+        
+        static const SamplerBinding* findUID(const std::vector<SamplerBinding>& v, UID uid) {
+            for(int i=0; i<v.size(); ++i) {
+                if ( v[i].sourceUID().isSetTo(uid) )
+                    return &v[i];
+            }
+            return 0L;
+        }
+    };
+
+    typedef std::vector<SamplerBinding> RenderBindings;
+
+
+} } } // namespace osgEarth::Drivers::RexTerrainEngine
+
+#endif // OSGEARTH_DRIVERS_REX_RENDER_BINDINGS_H
diff --git a/src/osgEarthDrivers/engine_rex/RexEngine.Morphing.vert.glsl b/src/osgEarthDrivers/engine_rex/RexEngine.Morphing.vert.glsl
new file mode 100644
index 0000000..a2f5b77
--- /dev/null
+++ b/src/osgEarthDrivers/engine_rex/RexEngine.Morphing.vert.glsl
@@ -0,0 +1,87 @@
+#version $GLSL_VERSION_STR
+
+#pragma vp_name       REX Engine - Morphing
+#pragma vp_entryPoint oe_rexEngine_morph
+#pragma vp_location   vertex_model
+#pragma vp_order      0.5
+#pragma vp_define     OE_REX_VERTEX_MORPHING
+
+// stage
+vec3 vp_Normal; // up vector
+
+vec4 oe_layer_texc;
+vec4 oe_layer_tilec;
+
+out float oe_rex_morphFactor;
+
+uniform sampler2D oe_tile_elevationTex;
+uniform mat4      oe_tile_elevationTexMatrix;
+uniform vec2	  oe_tile_morph;
+uniform float     oe_tile_size;
+uniform vec4	  oe_tile_key;
+
+// SDK functions:
+float oe_terrain_getElevation(in vec2 uv);
+
+// Vertex Markers:
+#define MASK_MARKER_DISCARD  0.0
+#define MASK_MARKER_NORMAL   1.0
+#define MASK_MARKER_SKIRT    2.0
+#define MASK_MARKER_BOUNDARY 3.0
+
+
+// Morphs a vertex using a neighbor.
+void oe_rex_MorphVertex(inout vec3 position, inout vec2 uv, in vec3 neighborPosition)
+{
+   float halfSize        = (0.5*oe_tile_size)-0.5;
+   float twoOverHalfSize = 2.0/(oe_tile_size-1.0);
+   
+   vec2 fractionalPart = fract(uv * halfSize) * twoOverHalfSize;
+   uv = clamp(uv - (fractionalPart * oe_rex_morphFactor), 0.0, 1.0);
+   //uv = clamp(uv, 0, 1);
+
+   vec3 morphVector = neighborPosition.xyz - position.xyz;
+   position.xyz = position.xyz + morphVector*oe_rex_morphFactor;
+}
+
+
+// Compute a morphing factor based on model-space inputs:
+float oe_rex_ComputeMorphFactor(in vec4 position, in vec3 up)
+{
+    // Find the "would be" position of the vertex (the position the vertex would
+    // assume with no morphing)
+	vec4 wouldBePosition = position;
+
+	#ifdef OE_REX_VERTEX_MORPHING
+        float elev = oe_terrain_getElevation( oe_layer_tilec.st );
+		wouldBePosition.xyz += up*elev;
+	#endif
+
+    vec4 wouldBePositionView = gl_ModelViewMatrix * wouldBePosition;
+    
+    float fDistanceToEye = length(wouldBePositionView.xyz); // or just -z.
+	float fMorphLerpK  = 1.0f - clamp( oe_tile_morph[0] - fDistanceToEye * oe_tile_morph[1], 0.0, 1.0 );
+    return fMorphLerpK;
+}
+
+
+void oe_rexEngine_morph(inout vec4 vertexModel)
+{    
+    // compute the morphing factor to send down the pipe.
+    // we need this even if vertex-morphing is off since we use it for 
+    // other things (like image blending)
+    if (oe_layer_tilec.z == MASK_MARKER_NORMAL)
+    {
+        oe_rex_morphFactor = oe_rex_ComputeMorphFactor(vertexModel, vp_Normal);    
+
+#ifdef OE_REX_VERTEX_MORPHING
+        vec3 neighborVertexModel = gl_MultiTexCoord1.xyz;
+        oe_rex_MorphVertex(vertexModel.xyz, oe_layer_tilec.st, neighborVertexModel.xyz);
+#endif
+    }
+    else
+    {
+        oe_rex_morphFactor = 0.0;
+    }
+}
+
diff --git a/src/osgEarthDrivers/engine_rex/RexEngine.NormalMap.frag.glsl b/src/osgEarthDrivers/engine_rex/RexEngine.NormalMap.frag.glsl
new file mode 100644
index 0000000..70dadfe
--- /dev/null
+++ b/src/osgEarthDrivers/engine_rex/RexEngine.NormalMap.frag.glsl
@@ -0,0 +1,37 @@
+#version $GLSL_VERSION_STR
+
+#pragma vp_entryPoint oe_normalMapFragment
+#pragma vp_location   fragment_coloring
+#pragma vp_order      0.2
+
+// import terrain SDK
+vec4 oe_terrain_getNormalAndCurvature(in vec2);
+
+uniform sampler2D oe_tile_normalTex;
+
+in vec3 vp_Normal;
+in vec3 oe_UpVectorView;
+in vec2 oe_normalMapCoords;
+in vec3 oe_normalMapBinormal;
+
+void oe_normalMapFragment(inout vec4 color)
+{
+    vec4 encodedNormal = oe_terrain_getNormalAndCurvature(oe_normalMapCoords);
+    //vec4 encodedNormal = texture2D(oe_tile_normalTex, oe_normalMapCoords);
+    vec3 normal = normalize(encodedNormal.xyz*2.0-1.0);
+
+    vec3 tangent = normalize(cross(oe_normalMapBinormal, oe_UpVectorView));
+    vp_Normal = normalize( mat3(tangent, oe_normalMapBinormal, oe_UpVectorView) * normal );
+
+    // visualize curvature gradient:
+    //color.rgb = vec3(0,0,0);
+    //color.r = (encodedNormal.a+1.0)/2.0;
+    //color.b = 1.0-color.r;
+
+    // visualize curvature quantized:
+    //if(encodedNormal.a >= 0.4) color.r = 1.0;
+    //if(encodedNormal.a <= -0.4) color.b = 1.0;
+    
+    // visualize normals:
+    //color.rgb = encodedNormal.xyz;
+}
diff --git a/src/osgEarthDrivers/engine_rex/RexEngine.NormalMap.vert.glsl b/src/osgEarthDrivers/engine_rex/RexEngine.NormalMap.vert.glsl
new file mode 100644
index 0000000..95552c3
--- /dev/null
+++ b/src/osgEarthDrivers/engine_rex/RexEngine.NormalMap.vert.glsl
@@ -0,0 +1,22 @@
+#version $GLSL_VERSION_STR
+
+#pragma vp_entryPoint oe_normalMapVertex
+#pragma vp_location   vertex_view
+#pragma vp_order      0.5
+
+uniform mat4 oe_tile_normalTexMatrix;
+
+// stage globals
+vec4 oe_layer_tilec;
+
+out vec2 oe_normalMapCoords;
+out vec3 oe_normalMapBinormal;
+
+void oe_normalMapVertex(inout vec4 unused)
+{
+    // calculate the sampling coordinates for the normal texture
+    oe_normalMapCoords = (oe_tile_normalTexMatrix * oe_layer_tilec).st;
+
+    // send the bi-normal to the fragment shader
+    oe_normalMapBinormal = gl_NormalMatrix * vec3(0,1,0);
+}
diff --git a/src/osgEarthDrivers/engine_rex/RexEngine.SDK.vert.glsl b/src/osgEarthDrivers/engine_rex/RexEngine.SDK.vert.glsl
new file mode 100644
index 0000000..751c90e
--- /dev/null
+++ b/src/osgEarthDrivers/engine_rex/RexEngine.SDK.vert.glsl
@@ -0,0 +1,79 @@
+#version 330
+#pragma vp_name Rex Terrain SDK
+
+/**
+ * SDK functions for the Rex engine.
+ * Declare and call these from any shader that runs on the terrain.
+ */
+
+// uniforms from terrain engine
+uniform sampler2D oe_tile_elevationTex;
+uniform mat4 oe_tile_elevationTexMatrix;
+uniform vec2 oe_tile_elevTexelCoeff;
+
+uniform sampler2D oe_tile_normalTex;
+uniform mat4 oe_tile_normalTexMatrix;
+
+uniform vec4 oe_tile_key;
+
+// Stage global
+vec4 oe_layer_tilec;
+
+
+/**
+ * Sample the elevation data at a UV tile coordinate.
+ */
+float oe_terrain_getElevation(in vec2 uv)
+{
+    // Texel-level scale and bias allow us to sample the elevation texture
+    // on texel center instead of edge.
+    vec2 elevc = uv
+        * oe_tile_elevTexelCoeff.x * oe_tile_elevationTexMatrix[0][0]     // scale
+        + oe_tile_elevTexelCoeff.x * oe_tile_elevationTexMatrix[3].st     // bias
+        + oe_tile_elevTexelCoeff.y;                                      
+
+    return texture(oe_tile_elevationTex, elevc).r;
+}
+
+/**
+ * Read the elevation at the build-in tile coordinates (convenience)
+ */
+float oe_terrain_getElevation()
+{
+    return oe_terrain_getElevation(oe_layer_tilec.st);
+}
+
+/**
+ * Read the normal vector and curvature at resolved UV tile coordinates.
+ */
+vec4 oe_terrain_getNormalAndCurvature(in vec2 uv_scaledBiased)
+{
+    return texture(oe_tile_normalTex, uv_scaledBiased);
+}
+
+vec4 oe_terrain_getNormalAndCurvature()
+{
+    vec2 uv_scaledBiased = oe_layer_tilec.st * oe_tile_normalTexMatrix[0][0] + oe_tile_normalTexMatrix[3].st;
+    return texture(oe_tile_normalTex, uv_scaledBiased);
+}
+
+/**
+ * Scales repeating texture coordinate such that they are [0..1]
+ * at a specific reference tile LOD. 
+ */
+vec2 oe_terrain_scaleCoordsToRefLOD(in vec2 tc, in float refLOD)
+{
+    float dL = oe_tile_key.z - refLOD;
+    float factor = exp2(dL);
+    float invFactor = 1.0/factor;
+    vec2 result = tc * vec2(invFactor);
+
+    vec2 a = floor(oe_tile_key.xy * invFactor);
+    vec2 b = a * factor;
+    vec2 c = b + factor;
+
+    float m = floor(clamp(factor,0.0,1.0)); // if factor>=1.0
+    result += m*(oe_tile_key.xy-b)/(c-b);
+
+    return result;
+}
diff --git a/src/osgEarthDrivers/engine_rex/RexEngine.frag.glsl b/src/osgEarthDrivers/engine_rex/RexEngine.frag.glsl
new file mode 100644
index 0000000..e6071c8
--- /dev/null
+++ b/src/osgEarthDrivers/engine_rex/RexEngine.frag.glsl
@@ -0,0 +1,84 @@
+#version 330
+
+#pragma vp_name       REX Engine - Fragment
+#pragma vp_entryPoint oe_rexEngine_frag
+#pragma vp_location   fragment_coloring
+#pragma vp_order      0.5
+#pragma vp_define     OE_REX_GL_BLENDING
+#pragma vp_define     OE_REX_MORPH_IMAGERY
+
+uniform bool      oe_isPickCamera;
+uniform sampler2D oe_layer_tex;
+uniform int       oe_layer_uid;
+uniform int       oe_layer_order;
+uniform float     oe_layer_opacity;
+
+#ifdef OE_REX_MORPH_IMAGERY
+uniform sampler2D oe_layer_texParent;
+uniform float oe_layer_texParentExists;
+in vec4 oe_layer_texcParent;
+in float oe_rex_morphFactor;
+#endif
+
+in vec4 oe_layer_texc;
+
+in float oe_layer_rangeOpacity;
+
+void oe_rexEngine_frag(inout vec4 color)
+{
+    float applyImagery = oe_layer_uid >= 0 ? 1.0 : 0.0;
+    
+	vec4 texelSelf = texture(oe_layer_tex, oe_layer_texc.st);
+
+#ifdef OE_REX_MORPH_IMAGERY
+
+    // sample the parent texture:
+	vec4 texelParent = texture(oe_layer_texParent, oe_layer_texcParent.st);
+
+    // if the parent texture does not exist, use the current texture with alpha=0 as the parent
+    // so we can "fade in" an image layer that starts at LOD > 0:
+    texelParent = mix( vec4(texelSelf.rgb, 0.0), texelParent, oe_layer_texParentExists );
+
+    // Resolve the final texel color:
+	vec4 texel = mix(texelSelf, texelParent, oe_rex_morphFactor);
+
+    // Decide whether to use the texel or the incoming color:
+	texel = mix(color, texel, applyImagery);
+
+#else
+
+    // No morphing, just use the incoming color or texture:
+    vec4 texel = mix(color, texelSelf, applyImagery);
+
+#endif
+
+    // Integrate layer opacity into the texture:
+    texel.a = mix(texel.a, texel.a*oe_layer_opacity*oe_layer_rangeOpacity, applyImagery);
+
+    float firstLayer = (applyImagery == 1.0 && oe_layer_order == 0) ? 1.0 : 0.0;
+
+#ifdef OE_REX_GL_BLENDING
+    
+    // Blend RGB with the incoming color:
+    //color.rgb = texel.rgb*texel.a + color.rgb*(1.0-texel.a);
+
+    // If this is a first image layer, use the max alpha; otherwise just leave it
+    // to GL blending
+    if (firstLayer == 1.0) {
+        color.rgb = texel.rgb*texel.a + color.rgb*(1.0-texel.a);
+        color.a = max(color.a, texel.a);
+    }
+    else color = texel;
+
+#else
+
+    // No blending? The output is just the texel value.
+    color = texel;
+
+#endif
+
+    // disable primary coloring for pick cameras. Necessary to support picking of
+    // draped geometry.
+    float pick = oe_isPickCamera ? 1.0 : 0.0;
+    color = mix(color, vec4(0), pick);
+}
diff --git a/src/osgEarthDrivers/engine_rex/RexEngine.gs.glsl b/src/osgEarthDrivers/engine_rex/RexEngine.gs.glsl
new file mode 100644
index 0000000..c0de328
--- /dev/null
+++ b/src/osgEarthDrivers/engine_rex/RexEngine.gs.glsl
@@ -0,0 +1,43 @@
+#version $GLSL_VERSION_STR
+
+
+#if 0 // currently unused - triangle discard implemented on CPU instead
+
+#pragma vp_name       REX Engine - GS
+#pragma vp_entryPoint oe_rexEngine_gs
+#pragma vp_location   geometry
+
+// Vertex Markers:
+#define MASK_MARKER_DISCARD  0.0
+#define MASK_MARKER_NORMAL   1.0
+#define MASK_MARKER_SKIRT    2.0
+#define MASK_MARKER_BOUNDARY 3.0
+
+layout(triangles)      in;
+layout(triangle_strip) out;
+layout(max_vertices=3) out;
+
+void VP_LoadVertex(in int);
+void VP_EmitModelVertex();
+
+in vec4 oe_layer_tilec;
+
+void oe_rexEngine_gs(void)
+{
+    for(int i=0; i < 3; ++i )
+    {
+        VP_LoadVertex(i);
+        if ( oe_layer_tilec.z == MASK_MARKER_DISCARD )
+            return;
+    }
+
+    for(int i=0; i < 3; ++i )
+    {
+        VP_LoadVertex(i);
+        gl_Position = gl_in[i].gl_Position;
+        VP_EmitModelVertex();
+    }
+    EndPrimitive();
+}
+
+#endif
diff --git a/src/osgEarthDrivers/engine_rex/RexEngine.tcs.glsl b/src/osgEarthDrivers/engine_rex/RexEngine.tcs.glsl
new file mode 100644
index 0000000..4ee0135
--- /dev/null
+++ b/src/osgEarthDrivers/engine_rex/RexEngine.tcs.glsl
@@ -0,0 +1,3 @@
+#version $GLSL_VERSION_STR
+
+}
diff --git a/src/osgEarthDrivers/engine_rex/RexEngine.tes.glsl b/src/osgEarthDrivers/engine_rex/RexEngine.tes.glsl
new file mode 100644
index 0000000..0fde065
--- /dev/null
+++ b/src/osgEarthDrivers/engine_rex/RexEngine.tes.glsl
@@ -0,0 +1,10 @@
+#version 400
+
+#pragma vp_name       REX Engine - TES
+#pragma vp_entryPoint oe_rexEngine_tes
+#pragma vp_location   tess_eval
+
+void oe_rexEngine_tes(void)
+{
+    //todo
+}
diff --git a/src/osgEarthDrivers/engine_rex/RexEngine.vert.glsl b/src/osgEarthDrivers/engine_rex/RexEngine.vert.glsl
new file mode 100644
index 0000000..1ad78ab
--- /dev/null
+++ b/src/osgEarthDrivers/engine_rex/RexEngine.vert.glsl
@@ -0,0 +1,35 @@
+#version $GLSL_VERSION_STR
+
+#pragma vp_name       REX Engine - Vertex
+#pragma vp_entryPoint oe_rexEngine_vert
+#pragma vp_location   vertex_model
+#pragma vp_order      0.0
+
+// uniforms
+uniform vec4 oe_terrain_color;
+
+// outputs
+out vec4 vp_Color;
+out vec3 vp_Normal;
+
+out vec4 oe_layer_texc;
+out vec4 oe_layer_tilec;
+out vec3 oe_UpVectorView;
+
+out float oe_rex_morphFactor;
+
+void oe_rexEngine_vert(inout vec4 vertexModel)
+{
+    // Texture coordinate for the tile (always 0..1)
+    oe_layer_tilec = gl_MultiTexCoord0;
+
+    // Color of the underlying map geometry (untextured)
+    vp_Color = oe_terrain_color;
+	
+    // "up" vector at this vertex in view space, which we will later
+    // need in order to elevate the terrain
+	oe_UpVectorView = normalize(gl_NormalMatrix*vp_Normal);
+
+    // initialize:
+    oe_rex_morphFactor = 0.0;
+}
diff --git a/src/osgEarthDrivers/engine_rex/RexEngine.vert.view.glsl b/src/osgEarthDrivers/engine_rex/RexEngine.vert.view.glsl
new file mode 100644
index 0000000..dff05f0
--- /dev/null
+++ b/src/osgEarthDrivers/engine_rex/RexEngine.vert.view.glsl
@@ -0,0 +1,65 @@
+#version $GLSL_VERSION_STR
+
+#pragma vp_name       REX Engine - Vertex/View
+#pragma vp_entryPoint oe_rex_elevateVertexAndSetTexCoords
+#pragma vp_location   vertex_view
+#pragma vp_order      0.4
+
+// Stage globals
+vec4 oe_layer_tilec;
+vec4 oe_layer_texc;
+vec4 oe_layer_texcParent;
+vec3 oe_UpVectorView;
+
+vec4 vp_Color;
+
+uniform mat4 oe_layer_texMatrix;
+uniform mat4 oe_layer_texParentMatrix;
+
+uniform float oe_layer_minRange;
+uniform float oe_layer_maxRange;
+uniform float oe_layer_attenuationRange;
+
+// SDK functions:
+float oe_terrain_getElevation(in vec2 uv);
+
+out float oe_layer_rangeOpacity;
+
+// Vertex Markers:
+#define MASK_MARKER_DISCARD  0.0
+#define MASK_MARKER_NORMAL   1.0
+#define MASK_MARKER_SKIRT    2.0
+#define MASK_MARKER_BOUNDARY 3.0
+
+void oe_rex_elevateVertexAndSetTexCoords(inout vec4 vertexView)
+{
+    float elev = 
+        oe_layer_tilec.z == MASK_MARKER_BOUNDARY || oe_layer_tilec.z == MASK_MARKER_DISCARD ? 0.0f
+        : oe_terrain_getElevation( oe_layer_tilec.st );
+
+    vertexView.xyz += oe_UpVectorView * elev;
+
+#if 0
+    // calculate the texture coordinates:
+    oe_layer_texc       = oe_layer_texMatrix       * oe_layer_tilec;
+	oe_layer_texcParent = oe_layer_texParentMatrix * oe_layer_tilec;
+#else
+    // faster (MAD)
+	oe_layer_texc.xy	   = oe_layer_tilec.xy*oe_layer_texMatrix[0][0] + oe_layer_texMatrix[3].xy;
+    oe_layer_texc.zw       = oe_layer_tilec.zw;
+    oe_layer_texcParent.xy = oe_layer_tilec.xy*oe_layer_texParentMatrix[0][0] + oe_layer_texParentMatrix[3].xy;
+    oe_layer_texcParent.zw = oe_layer_tilec.zw;
+#endif
+
+   float range = max(-vertexView.z, 0.0);
+
+   float attenMin    = oe_layer_minRange - oe_layer_attenuationRange;
+   float attenMax    = oe_layer_maxRange + oe_layer_attenuationRange;
+
+   oe_layer_rangeOpacity =
+       oe_layer_minRange >= oe_layer_maxRange                   ? 1.0 :
+       range >= oe_layer_minRange && range < oe_layer_maxRange  ? 1.0 :
+       range < oe_layer_minRange                                ? clamp((range-attenMin)/oe_layer_attenuationRange, 0.0, 1.0) :
+       range > oe_layer_maxRange                                ? clamp((attenMax-range)/oe_layer_attenuationRange, 0.0, 1.0) :
+       0.0;
+}
diff --git a/src/osgEarthDrivers/engine_rex/RexTerrainEngineDriver.cpp b/src/osgEarthDrivers/engine_rex/RexTerrainEngineDriver.cpp
new file mode 100644
index 0000000..2625b97
--- /dev/null
+++ b/src/osgEarthDrivers/engine_rex/RexTerrainEngineDriver.cpp
@@ -0,0 +1,72 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+ * Copyright 2008-2014 Pelican Mapping
+ * http://osgearth.org
+ *
+ * osgEarth is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ */
+#include "RexTerrainEngineNode"
+#include "RexTerrainEngineOptions"
+#include "TileNode"
+#include <osgEarth/Registry>
+#include <osgEarth/Progress>
+#include <osgEarth/Utils>
+#include <osgDB/FileNameUtils>
+#include <osgDB/FileUtils>
+#include <osgDB/Registry>
+#include <string>
+#include <sstream>
+
+#define LC "[engine_rex] "
+
+namespace osgEarth { namespace Drivers { namespace RexTerrainEngine
+{
+    /**
+     * osgEarth driver for the Rex terrain engine.
+     */
+    class RexTerrainEngineDriver : public osgDB::ReaderWriter
+    {
+    public:
+        RexTerrainEngineDriver()
+        {
+            //nop
+        }
+
+        virtual const char* className() const
+        {
+            return "osgEarth Rex Terrain Engine";
+        }
+
+        virtual bool acceptsExtension(const std::string& extension) const
+        {
+            return osgDB::equalCaseInsensitive( extension, "osgearth_engine_rex" );
+        }
+
+        virtual ReadResult readObject(const std::string& uri, const Options* options) const
+        {
+            if ( "osgearth_engine_rex" == osgDB::getFileExtension( uri ) )
+            {
+                OE_INFO << LC << "Activated!" << std::endl;
+                return ReadResult( new RexTerrainEngineNode() );
+            }
+            else
+            {
+                return ReadResult::FILE_NOT_HANDLED;
+            }
+        }    
+    };
+
+    REGISTER_OSGPLUGIN(osgearth_engine_rex, RexTerrainEngineDriver);
+
+} } } // namespace osgEarth::Drivers::RexTerrainEngine
diff --git a/src/osgEarthDrivers/engine_rex/RexTerrainEngineNode b/src/osgEarthDrivers/engine_rex/RexTerrainEngineNode
new file mode 100644
index 0000000..e5cd0fe
--- /dev/null
+++ b/src/osgEarthDrivers/engine_rex/RexTerrainEngineNode
@@ -0,0 +1,192 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+ * Copyright 2008-2014 Pelican Mapping
+ * http://osgearth.org
+ *
+ * osgEarth is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ */
+#ifndef OSGEARTH_DRIVERS_REX_TERRAIN_ENGINE_ENGINE_NODE_H
+#define OSGEARTH_DRIVERS_REX_TERRAIN_ENGINE_ENGINE_NODE_H 1
+
+#include <osgEarth/TerrainEngineNode>
+#include <osgEarth/TextureCompositor>
+#include <osgEarth/Map>
+#include <osgEarth/Revisioning>
+#include <osgEarth/ThreadingUtils>
+#include <osgEarth/Containers>
+#include <osgEarth/ResourceReleaser>
+
+#include "RexTerrainEngineOptions"
+#include "EngineContext"
+#include "TileNodeRegistry"
+#include "RenderBindings"
+#include "GeometryPool"
+#include "Loader"
+#include "Unloader"
+#include "SelectionInfo"
+
+#include <osg/Geode>
+#include <osg/NodeCallback>
+#include <osg/Uniform>
+#include <osg/Timer>
+
+using namespace osgEarth;
+
+namespace osgEarth { namespace Drivers { namespace RexTerrainEngine
+{
+    class SelectionInfo;
+
+    class RexTerrainEngineNode : public TerrainEngineNode
+    {
+    public:
+        RexTerrainEngineNode();
+        META_Node(osgEarth,RexTerrainEngineNode);
+        virtual ~RexTerrainEngineNode();
+
+    public: // TerrainEngineNode
+
+        // for standalone tile creation outside of a terrain
+        osg::Node* createTile(const TileKey& key);
+        
+        // when incremental update is enabled, forces regeneration of tiles
+        // in the given region.
+        void invalidateRegion(
+            const GeoExtent& extent,
+            unsigned         minLevel,
+            unsigned         maxLevel);
+
+        /** Get the stateset used to render the terrain surface. */
+        osg::StateSet* getSurfaceStateSet();
+
+    public: // internal TerrainEngineNode
+
+        virtual void preInitialize( const Map* map, const TerrainOptions& options );
+        virtual void postInitialize( const Map* map, const TerrainOptions& options );
+        virtual const TerrainOptions& getTerrainOptions() const { return _terrainOptions; }
+        virtual osg::BoundingSphere computeBound() const;
+
+    public: // osg::Node
+
+        void traverse(osg::NodeVisitor& nv);
+
+    public: // MapCallback adapter functions
+
+        void onMapInfoEstablished( const MapInfo& mapInfo ); // not virtual!
+        void onMapModelChanged( const MapModelChange& change ); // not virtual!
+
+        UID getUID() const;
+
+    public: // statics    
+        static void registerEngine( RexTerrainEngineNode* engineNode );
+        static void getEngineByUID( UID uid, osg::ref_ptr<RexTerrainEngineNode>& output );
+
+        /** Access to the asychronous data loader */
+        Loader* getLoader() { return _loader.get(); }
+
+    public:
+        class ElevationChangedCallback : public ElevationLayerCallback
+        {
+        public:
+            ElevationChangedCallback( RexTerrainEngineNode* terrain );
+
+           virtual void onVisibleChanged( TerrainLayer* layer );
+
+            RexTerrainEngineNode* _terrain;
+            friend class RexTerrainEngineNode;
+        };
+
+    protected:
+        // override from TerrainEngineNode
+        virtual void updateTextureCombining() { updateState(); }
+        
+        // override from TerrainEngineNode
+        virtual void dirtyTerrain();
+
+        // override from TerrainEngineNode
+        virtual void dirtyState();
+
+    private:
+        void init();
+        void syncMapModel();
+
+        // Reloads all the tiles in the terrain due to a data model change
+        void refresh(bool force =false);
+
+        void addImageLayer( ImageLayer* layer );
+        void addElevationLayer( ElevationLayer* layer );
+
+        void removeImageLayer( ImageLayer* layerRemoved );
+        void removeElevationLayer( ElevationLayer* layerRemoved );
+        void toggleElevationLayer( ElevationLayer* layer );
+
+        void moveImageLayer( unsigned int oldIndex, unsigned int newIndex );
+        void moveElevationLayer( unsigned int oldIndex, unsigned int newIndex );
+        
+        void updateState(); 
+
+        void setupRenderBindings();
+
+
+
+        /**
+         * Utility function to compute the heightfield sample size required to match the vertices at the highest level of detail in rex
+         * if a tile key was requested at the given level of detail.
+         */
+        unsigned int computeSampleSize(unsigned int levelOfDetail);
+
+
+    private:
+        RexTerrainEngineOptions _terrainOptions;
+
+        UID                _uid;
+        bool               _batchUpdateInProgress;
+        bool               _refreshRequired;
+        bool               _stateUpdateRequired;
+
+        osg::ref_ptr<ElevationChangedCallback> _elevationCallback;
+
+        MapFrame* _update_mapf; // map frame for the main/update traversal thread
+
+        // node registry is shared across all threads.
+        osg::ref_ptr<TileNodeRegistry> _liveTiles;      // tiles in the scene graph.
+        osg::ref_ptr<ResourceReleaser> _releaser;
+
+        PerThread< osg::ref_ptr<EngineContext> > _perThreadTileGroupFactories;
+        EngineContext* getEngineContext();
+
+        osg::Timer _timer;
+        unsigned   _tileCount;
+        double     _tileCreationTime;
+        RenderBindings _renderBindings;
+        osg::ref_ptr<GeometryPool> _geometryPool;
+        osg::ref_ptr<LoaderGroup>  _loader;
+        osg::ref_ptr<UnloaderGroup> _unloader;
+        
+        osg::ref_ptr<osg::Group> _terrain;
+
+        Threading::Mutex _renderBinMutex;
+        osg::ref_ptr<osgUtil::RenderBin> _surfaceRenderBinPrototype;
+
+        RexTerrainEngineNode( const RexTerrainEngineNode& rhs, const osg::CopyOp& op =osg::CopyOp::DEEP_COPY_ALL ) { }
+
+        SelectionInfo _selectionInfo;
+        void buildSelectionInfo(void);
+        void destroySelectionInfo(void);
+
+        osg::ref_ptr<osg::StateSet> _surfaceSS;
+    };
+
+} } } // namespace osgEarth::Drivers::RexTerrainEngine
+
+#endif // OSGEARTH_DRIVERS_REX_TERRAIN_ENGINE_ENGINE_NODE_H
diff --git a/src/osgEarthDrivers/engine_rex/RexTerrainEngineNode.cpp b/src/osgEarthDrivers/engine_rex/RexTerrainEngineNode.cpp
new file mode 100644
index 0000000..b8832ac
--- /dev/null
+++ b/src/osgEarthDrivers/engine_rex/RexTerrainEngineNode.cpp
@@ -0,0 +1,1070 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+* Copyright 2008-2014 Pelican Mapping
+* http://osgearth.org
+*
+* osgEarth is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public License
+* along with this program.  If not, see <http://www.gnu.org/licenses/>
+*/
+#include "RexTerrainEngineNode"
+#include "Shaders"
+#include "SelectionInfo"
+
+#include <osgEarth/HeightFieldUtils>
+#include <osgEarth/ImageUtils>
+#include <osgEarth/Registry>
+#include <osgEarth/Capabilities>
+#include <osgEarth/VirtualProgram>
+#include <osgEarth/ShaderFactory>
+#include <osgEarth/MapModelChange>
+#include <osgEarth/Progress>
+#include <osgEarth/ShaderLoader>
+#include <osgEarth/Utils>
+#include <osgEarth/ObjectIndex>
+#include <osgEarth/TraversalData>
+
+#include <osg/Version>
+#include <osg/BlendFunc>
+#include <osg/Depth>
+#include <osgUtil/RenderBin>
+
+#if OSG_VERSION_GREATER_OR_EQUAL(3,1,8)
+#   define HAVE_OSG_PATCH_PARAMETER
+#   include <osg/PatchParameter>
+#endif
+
+#include <cstdlib> // for getenv
+
+#define LC "[RexTerrainEngineNode] "
+
+using namespace osgEarth::Drivers::RexTerrainEngine;
+using namespace osgEarth;
+
+//------------------------------------------------------------------------
+
+namespace
+{
+    // adapter that lets RexTerrainEngineNode listen to Map events
+    struct RexTerrainEngineNodeMapCallbackProxy : public MapCallback
+    {
+        RexTerrainEngineNodeMapCallbackProxy(RexTerrainEngineNode* node) : _node(node) { }
+        osg::observer_ptr<RexTerrainEngineNode> _node;
+
+        void onMapInfoEstablished( const MapInfo& mapInfo ) {
+            osg::ref_ptr<RexTerrainEngineNode> node;
+            if ( _node.lock(node) )
+                node->onMapInfoEstablished( mapInfo );
+        }
+
+        void onMapModelChanged( const MapModelChange& change ) {
+            osg::ref_ptr<RexTerrainEngineNode> node;
+            if ( _node.lock(node) )
+                node->onMapModelChanged( change );
+        }
+    };
+}
+
+//---------------------------------------------------------------------------
+
+static Threading::ReadWriteMutex s_engineNodeCacheMutex;
+//Caches the engines that have been created
+typedef std::map<UID, osg::observer_ptr<RexTerrainEngineNode> > EngineNodeCache;
+
+static
+EngineNodeCache& getEngineNodeCache()
+{
+    static EngineNodeCache s_cache;
+    return s_cache;
+}
+
+void
+RexTerrainEngineNode::registerEngine(RexTerrainEngineNode* engineNode)
+{
+    Threading::ScopedWriteLock exclusiveLock( s_engineNodeCacheMutex );
+    getEngineNodeCache()[engineNode->_uid] = engineNode;
+    OE_DEBUG << LC << "Registered engine " << engineNode->_uid << std::endl;
+}
+
+// since this method is called in a database pager thread, we use a ref_ptr output
+// parameter to avoid the engine node being destructed between the time we 
+// return it and the time it's accessed; this could happen if the user removed the
+// MapNode from the scene during paging.
+void
+RexTerrainEngineNode::getEngineByUID( UID uid, osg::ref_ptr<RexTerrainEngineNode>& output )
+{
+    Threading::ScopedReadLock sharedLock( s_engineNodeCacheMutex );
+    EngineNodeCache::const_iterator k = getEngineNodeCache().find( uid );
+    if (k != getEngineNodeCache().end())
+        output = k->second.get();
+}
+
+UID
+RexTerrainEngineNode::getUID() const
+{
+    return _uid;
+}
+
+//------------------------------------------------------------------------
+
+RexTerrainEngineNode::ElevationChangedCallback::ElevationChangedCallback( RexTerrainEngineNode* terrain ):
+_terrain( terrain )
+{
+    //nop
+}
+
+void
+RexTerrainEngineNode::ElevationChangedCallback::onVisibleChanged( TerrainLayer* layer )
+{
+    _terrain->refresh(true); // true => force a dirty
+}
+
+//------------------------------------------------------------------------
+
+RexTerrainEngineNode::RexTerrainEngineNode() :
+TerrainEngineNode     ( ),
+_terrain              ( 0L ),
+_update_mapf          ( 0L ),
+_tileCount            ( 0 ),
+_tileCreationTime     ( 0.0 ),
+_batchUpdateInProgress( false ),
+_refreshRequired      ( false ),
+_stateUpdateRequired  ( false )
+{
+    // unique ID for this engine:
+    _uid = Registry::instance()->createUID();
+
+    // always require elevation.
+    _requireElevationTextures = true;
+
+    // install an elevation callback so we can update elevation data
+    _elevationCallback = new ElevationChangedCallback( this );
+
+    // static shaders.
+    if ( Registry::capabilities().supportsGLSL() )
+    {
+        osg::StateSet* stateset = getOrCreateStateSet();
+        VirtualProgram* vp = VirtualProgram::getOrCreate(stateset);
+        Shaders package;
+        package.load(vp, package.SDK);
+    }
+
+    _surfaceSS = new osg::StateSet();
+}
+
+RexTerrainEngineNode::~RexTerrainEngineNode()
+{
+    if ( _update_mapf )
+    {
+        delete _update_mapf;
+    }
+    destroySelectionInfo();
+}
+
+void
+RexTerrainEngineNode::preInitialize( const Map* map, const TerrainOptions& options )
+{
+    // Force the mercator fast path off, since REX does not support it yet.
+    TerrainOptions myOptions = options;
+    myOptions.enableMercatorFastPath() = false;
+
+    TerrainEngineNode::preInitialize( map, myOptions );
+}
+
+void
+RexTerrainEngineNode::postInitialize( const Map* map, const TerrainOptions& options )
+{
+    // Force the mercator fast path off, since REX does not support it yet.
+    TerrainOptions myOptions = options;
+    myOptions.enableMercatorFastPath() = false;
+
+    TerrainEngineNode::postInitialize( map, myOptions );
+
+    // Initialize the map frames. We need one for the update thread and one for the
+    // cull thread. Someday we can detect whether these are actually the same thread
+    // (depends on the viewer's threading mode).
+    _update_mapf = new MapFrame( map, Map::ENTIRE_MODEL );
+
+    // merge in the custom options:
+    _terrainOptions.merge( myOptions );
+
+    // morphing imagery LODs requires we bind parent textures to their own unit.
+    if ( _terrainOptions.morphImagery() == true )
+    {
+        _requireParentTextures = true;
+    }
+
+    // Terrain morphing doesn't work in projected maps:
+    if (map->getSRS()->isProjected())
+    {
+        _terrainOptions.morphTerrain() = false;
+    }
+
+    // if the envvar for tile expiration is set, overide the options setting
+    const char* val = ::getenv("OSGEARTH_EXPIRATION_THRESHOLD");
+    if ( val )
+    {
+        _terrainOptions.expirationThreshold() = as<unsigned>(val, _terrainOptions.expirationThreshold().get());
+        OE_INFO << LC << "Expiration threshold set by env var = " << _terrainOptions.expirationThreshold().get() << "\n";
+    }
+
+    // if the envvar for hires prioritization is set, override the options setting
+    const char* hiresFirst = ::getenv("OSGEARTH_HIGH_RES_FIRST");
+    if ( hiresFirst )
+    {
+        _terrainOptions.highResolutionFirst() = true;
+    }
+
+    // check for normal map generation (required for lighting).
+    if ( _terrainOptions.normalMaps() == true )
+    {
+        this->_requireNormalTextures = true;
+    }
+
+    // A shared registry for tile nodes in the scene graph. Enable revision tracking
+    // if requested in the options. Revision tracking lets the registry notify all
+    // live tiles of the current map revision so they can inrementally update
+    // themselves if necessary.
+    _liveTiles = new TileNodeRegistry("live");
+    _liveTiles->setMapRevision( _update_mapf->getRevision() );
+
+    // A resource releaser that will call releaseGLObjects() on expired objects.
+    _releaser = new ResourceReleaser();
+    this->addChild(_releaser.get());
+
+    // A shared geometry pool.
+    _geometryPool = new GeometryPool( _terrainOptions );
+    _geometryPool->setReleaser( _releaser.get());
+    this->addChild( _geometryPool.get() );
+
+    // Make a tile loader
+    PagerLoader* loader = new PagerLoader( this );
+    loader->setMergesPerFrame( _terrainOptions.mergesPerFrame().get() );
+    _loader = loader;
+    this->addChild( _loader.get() );
+
+    // Make a tile unloader
+    _unloader = new UnloaderGroup( _liveTiles.get() );
+    _unloader->setThreshold( _terrainOptions.expirationThreshold().get() );
+    _unloader->setReleaser(_releaser.get());
+    this->addChild( _unloader.get() );
+    
+    // handle an already-established map profile:
+    MapInfo mapInfo( map );
+    if ( _update_mapf->getProfile() )
+    {
+        // NOTE: this will initialize the map with the startup layers
+        onMapInfoEstablished( mapInfo );
+    }
+
+    // install a layer callback for processing further map actions:
+    map->addMapCallback( new RexTerrainEngineNodeMapCallbackProxy(this) );
+
+    // Prime with existing layers:
+    _batchUpdateInProgress = true;
+
+    ElevationLayerVector elevationLayers;
+    map->getElevationLayers( elevationLayers );
+    for( ElevationLayerVector::const_iterator i = elevationLayers.begin(); i != elevationLayers.end(); ++i )
+        addElevationLayer( i->get() );
+
+    ImageLayerVector imageLayers;
+    map->getImageLayers( imageLayers );
+    for( ImageLayerVector::iterator i = imageLayers.begin(); i != imageLayers.end(); ++i )
+        addImageLayer( i->get() );
+
+    _batchUpdateInProgress = false;
+
+    // set up the initial shaders
+    updateState();
+
+    // register this instance to the osgDB plugin can find it.
+    registerEngine( this );
+
+    // now that we have a map, set up to recompute the bounds
+    dirtyBound();
+}
+
+
+osg::BoundingSphere
+RexTerrainEngineNode::computeBound() const
+{
+    return TerrainEngineNode::computeBound();
+}
+
+void
+RexTerrainEngineNode::invalidateRegion(const GeoExtent& extent,
+                                       unsigned         minLevel,
+                                       unsigned         maxLevel)
+{
+    if ( _liveTiles.valid() )
+    {
+        GeoExtent extentLocal = extent;
+
+        if ( !extent.getSRS()->isEquivalentTo(this->getMap()->getSRS()) )
+        {
+            extent.transform(this->getMap()->getSRS(), extentLocal);
+        }
+        
+        _liveTiles->setDirty(extentLocal, minLevel, maxLevel);
+    }
+}
+
+void
+RexTerrainEngineNode::refresh(bool forceDirty)
+{
+    if ( _batchUpdateInProgress )
+    {
+        _refreshRequired = true;
+    }
+    else
+    {
+        dirtyTerrain();
+
+        _refreshRequired = false;
+    }
+}
+
+void
+RexTerrainEngineNode::onMapInfoEstablished( const MapInfo& mapInfo )
+{
+    dirtyTerrain();
+}
+
+osg::StateSet*
+RexTerrainEngineNode::getSurfaceStateSet()
+{
+    return _surfaceSS.get();
+}
+
+void
+RexTerrainEngineNode::setupRenderBindings()
+{
+    _renderBindings.push_back( SamplerBinding() );
+    SamplerBinding& color = _renderBindings.back();
+    color.usage()       = SamplerBinding::COLOR;
+    color.samplerName() = "oe_layer_tex";
+    color.matrixName()  = "oe_layer_texMatrix";
+    this->getResources()->reserveTextureImageUnit( color.unit(), "Terrain Color" );
+
+    _renderBindings.push_back( SamplerBinding() );
+    SamplerBinding& elevation = _renderBindings.back();
+    elevation.usage()       = SamplerBinding::ELEVATION;
+    elevation.samplerName() = "oe_tile_elevationTex";
+    elevation.matrixName()  = "oe_tile_elevationTexMatrix";
+    this->getResources()->reserveTextureImageUnit( elevation.unit(), "Terrain Elevation" );
+
+    _renderBindings.push_back( SamplerBinding() );
+    SamplerBinding& normal = _renderBindings.back();
+    normal.usage()       = SamplerBinding::NORMAL;
+    normal.samplerName() = "oe_tile_normalTex";
+    normal.matrixName()  = "oe_tile_normalTexMatrix";
+    this->getResources()->reserveTextureImageUnit( normal.unit(), "Terrain Normals" );
+
+    _renderBindings.push_back( SamplerBinding() );
+    SamplerBinding& colorParent = _renderBindings.back();
+    colorParent.usage()       = SamplerBinding::COLOR_PARENT;
+    colorParent.samplerName() = "oe_layer_texParent";
+    colorParent.matrixName()  = "oe_layer_texParentMatrix";
+    this->getResources()->reserveTextureImageUnit( colorParent.unit(), "Terrain Color (Parent)" );
+}
+
+void RexTerrainEngineNode::destroySelectionInfo()
+{
+    //if (_selectionInfo)
+    //{
+    //    delete _selectionInfo; _selectionInfo = 0;
+    //}
+}
+
+void RexTerrainEngineNode::buildSelectionInfo()
+{
+//    _selectionInfo = new SelectionInfo;
+}
+
+void
+RexTerrainEngineNode::dirtyTerrain()
+{
+    //TODO: scrub the geometry pool?
+
+    // clear the loader:
+    _loader->clear();
+
+    if ( _terrain )
+    {
+        this->removeChild( _terrain );
+    }
+
+    // New terrain
+    _terrain = new osg::Group();
+    this->addChild( _terrain );
+
+    // are we LOD blending?
+    bool setupParentData = 
+        _terrainOptions.morphImagery() == true || // gw: redundant?
+        this->parentTexturesRequired();
+    
+    // reserve GPU unit for the main color texture:
+    if ( _renderBindings.empty() )
+    {
+        setupRenderBindings();
+    }
+
+    // Calculate the LOD morphing parameters:
+    double averageRadius = 0.5*(
+        _update_mapf->getMapInfo().getSRS()->getEllipsoid()->getRadiusEquator() +
+        _update_mapf->getMapInfo().getSRS()->getEllipsoid()->getRadiusPolar());
+
+    double farLOD = 
+        _terrainOptions.minTileRangeFactor().get() *
+        3.214 * averageRadius;
+
+    _selectionInfo.initialize(
+        0u, // always zero, not the terrain options firstLOD
+        std::min( _terrainOptions.maxLOD().get(), 19u ),
+        _terrainOptions.tileSize().get(),
+        farLOD );
+
+    // clear out the tile registry:
+    if ( _liveTiles.valid() )
+    {
+        _liveTiles->releaseAll(_releaser.get());
+    }
+
+    // Factory to create the root keys:
+    EngineContext* context = getEngineContext();
+
+    // Build the first level of the terrain.
+    // Collect the tile keys comprising the root tiles of the terrain.
+    std::vector<TileKey> keys;
+    _update_mapf->getProfile()->getAllKeysAtLOD( *_terrainOptions.firstLOD(), keys );
+
+    // create a root node for each root tile key.
+    OE_INFO << LC << "Creating " << keys.size() << " root keys.." << std::endl;
+
+    unsigned child = 0;
+    for( unsigned i=0; i<keys.size(); ++i )
+    {
+        TileNode* tileNode = new TileNode();
+        if (context->getOptions().minExpiryFrames().isSet())
+        {
+            tileNode->setMinimumExpiryFrames( *context->getOptions().minExpiryFrames() );
+        }
+        if (context->getOptions().minExpiryTime().isSet())
+        {         
+            tileNode->setMinimumExpiryTime( *context->getOptions().minExpiryTime() );
+        }
+                
+        // Next, build the surface geometry for the node.
+        tileNode->create( keys[i], context );
+
+        _terrain->addChild( tileNode );
+    }
+
+    updateState();
+
+    // Call the base class
+    TerrainEngineNode::dirtyTerrain();
+}
+
+namespace
+{
+    // debugging
+    struct CheckForOrphans : public TileNodeRegistry::ConstOperation {
+        void operator()( const TileNodeRegistry::TileNodeMap& tiles ) const {
+            unsigned count = 0;
+            for(TileNodeRegistry::TileNodeMap::const_iterator i = tiles.begin(); i != tiles.end(); ++i ) {
+                if ( i->second.tile->referenceCount() == 1 ) {
+                    count++;
+                }
+            }
+            if ( count > 0 )
+                OE_WARN << LC << "Oh no! " << count << " orphaned tiles in the reg" << std::endl;
+        }
+    };
+}
+
+
+void
+RexTerrainEngineNode::dirtyState()
+{
+    // TODO: perhaps defer this until the next update traversal so we don't 
+    // reinitialize the state multiple times unnecessarily. 
+    updateState();
+}
+
+
+void
+RexTerrainEngineNode::traverse(osg::NodeVisitor& nv)
+{
+    if ( nv.getVisitorType() == nv.CULL_VISITOR )
+    {
+        // Inform the registry of the current frame so that Tiles have access
+        // to the information.
+        if ( _liveTiles.valid() && nv.getFrameStamp() )
+        {
+            _liveTiles->setTraversalFrame( nv.getFrameStamp()->getFrameNumber() );
+        }
+    }
+
+#if 0
+    static int c = 0;
+    if ( ++c % 60 == 0 )
+    {
+        OE_NOTICE << LC << "Live = " << _liveTiles->size() << ", Dead = " << _deadTiles->size() << std::endl;
+        _liveTiles->run( CheckForOrphans() );
+    }
+#endif
+    
+    if ( nv.getVisitorType() == nv.CULL_VISITOR && _loader.valid() ) // ensures that postInitialize has run
+    {
+        VisitorData::store(nv, ENGINE_CONTEXT_TAG, this->getEngineContext());
+        // Pass the tile creation context to the traversal.
+        //osg::ref_ptr<osg::Referenced> data = nv.getUserData();
+        //nv.setUserData( this->getEngineContext() );
+
+        osgUtil::CullVisitor* cv = static_cast<osgUtil::CullVisitor*>(&nv);
+
+        this->getEngineContext()->_surfaceSS = _surfaceSS.get();
+
+        this->getEngineContext()->startCull( cv );
+        TerrainEngineNode::traverse( nv );
+        this->getEngineContext()->endCull( cv );
+
+        //if ( data.valid() )
+        //    nv.setUserData( data.get() );
+    }
+
+    else
+    {
+        TerrainEngineNode::traverse( nv );
+    }
+}
+
+
+EngineContext*
+RexTerrainEngineNode::getEngineContext()
+{
+    osg::ref_ptr<EngineContext>& context = _perThreadTileGroupFactories.get(); // thread-safe get
+    if ( !context.valid() )
+    {
+        // initialize a key node factory.
+        context = new EngineContext(
+            getMap(),
+            this, // engine
+            _geometryPool.get(),
+            _loader.get(),
+            _unloader.get(),
+            _liveTiles.get(),
+            _renderBindings,
+            _terrainOptions,
+            _selectionInfo,
+            _tilePatchCallbacks);
+    }
+
+    return context.get();
+}
+
+unsigned int
+RexTerrainEngineNode::computeSampleSize(unsigned int levelOfDetail)
+{    
+    unsigned maxLevel = std::min( *_terrainOptions.maxLOD(), 19u ); // beyond LOD 19 or 20, morphing starts to lose precision.
+    unsigned int meshSize = *_terrainOptions.tileSize();
+
+    unsigned int sampleSize = meshSize;
+    int level = maxLevel; // make sure it's signed for the loop below to work
+
+    while( level >= 0 && levelOfDetail != level)
+    {
+        sampleSize = sampleSize * 2 - 1;
+        level--;
+    }
+
+    return sampleSize;    
+}
+
+osg::Vec3d getWorld( const GeoHeightField& geoHF, unsigned int c, unsigned int r)
+{
+    double x = geoHF.getExtent().xMin() + (double)c * geoHF.getXInterval();
+    double y = geoHF.getExtent().yMin() + (double)r * geoHF.getYInterval();
+    double h = geoHF.getHeightField()->getHeight(c,r);
+
+    osg::Vec3d world;
+    GeoPoint point(geoHF.getExtent().getSRS(), x, y, h );
+    point.toWorld( world );    
+    return world;
+}
+
+osg::Node* renderHeightField(const GeoHeightField& geoHF)
+{
+    osg::MatrixTransform* mt = new osg::MatrixTransform;
+
+    GeoPoint centroid;
+    geoHF.getExtent().getCentroid(centroid);
+
+    osg::Matrix world2local, local2world;
+    centroid.createWorldToLocal( world2local );
+    local2world.invert( world2local );
+
+    mt->setMatrix( local2world );
+
+    osg::Geometry* geometry = new osg::Geometry;
+    osg::Geode* geode = new osg::Geode;
+    geode->addDrawable( geometry );
+    mt->addChild( geode );
+
+    osg::Vec3Array* verts = new osg::Vec3Array;
+    geometry->setVertexArray( verts );
+
+    for (unsigned int c = 0; c < geoHF.getHeightField()->getNumColumns() - 1; c++)
+    {
+        for (unsigned int r = 0; r < geoHF.getHeightField()->getNumRows() - 1; r++)
+        {
+            // Add two triangles 
+            verts->push_back( getWorld( geoHF, c,     r    ) * world2local );
+            verts->push_back( getWorld( geoHF, c + 1, r    ) * world2local );
+            verts->push_back( getWorld( geoHF, c + 1, r + 1) * world2local );
+
+            verts->push_back( getWorld( geoHF, c,     r    ) * world2local );
+            verts->push_back( getWorld( geoHF, c + 1, r + 1) * world2local );
+            verts->push_back( getWorld( geoHF, c,     r + 1) * world2local );
+        }
+    }
+    geode->setCullingActive(false);
+    mt->setCullingActive(false);
+
+    geometry->addPrimitiveSet(new osg::DrawArrays(GL_TRIANGLES, 0, verts->size()));      
+
+    osg::Vec4ubArray* colors = new osg::Vec4ubArray();
+    colors->push_back(osg::Vec4ub(255,0,0,255));
+    geometry->setColorArray(colors, osg::Array::BIND_OVERALL);
+    mt->getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
+    mt->getOrCreateStateSet()->setRenderBinDetails(99, "RenderBin");        
+
+    return mt;
+}
+
+
+osg::Node*
+RexTerrainEngineNode::createTile( const TileKey& key )
+{
+     // Compute the sample size to use for the key's level of detail that will line up exactly with the tile size of the highest level of subdivision of the rex engine.
+    unsigned int sampleSize = computeSampleSize( key.getLevelOfDetail() );    
+    OE_INFO << LC << "Computed a sample size of " << sampleSize << " for lod " << key.getLevelOfDetail() << std::endl;
+
+    TileKey sampleKey = key;
+
+    // ALWAYS use 257x257 b/c that is what rex always uses.
+    osg::ref_ptr< osg::HeightField > out_hf = HeightFieldUtils::createReferenceHeightField(
+            key.getExtent(), 257, 257, true );
+
+    sampleKey = key;
+
+    bool populated = false;
+    while (!populated)
+    {
+        populated = _update_mapf->populateHeightField(
+            out_hf,
+            sampleKey,
+            true, // convertToHAE
+            0 );
+
+        if (!populated)
+        {
+            // Fallback on the parent
+            sampleKey = sampleKey.createParentKey();
+            if (!sampleKey.valid())
+            {
+                return 0;
+            }
+        }
+    }
+
+    // cannot happen (says coverity; see loop above), so commenting this out -gw
+#if 0
+    if (!populated)
+    {
+        // We have no heightfield so just create a reference heightfield.
+        out_hf = HeightFieldUtils::createReferenceHeightField( key.getExtent(), 257, 257);
+        sampleKey = key;
+    }
+#endif
+
+    GeoHeightField geoHF( out_hf.get(), sampleKey.getExtent() );    
+    if (sampleKey != key)
+    {   
+        geoHF = geoHF.createSubSample( key.getExtent(), sampleSize, sampleSize, osgEarth::INTERP_BILINEAR);         
+    }
+
+    // We should now have a heightfield that matches up exactly with the requested key at the appropriate resolution.
+    // Turn it into triangles.
+    return renderHeightField( geoHF );      
+}
+
+
+void
+RexTerrainEngineNode::onMapModelChanged( const MapModelChange& change )
+{
+    if ( change.getAction() == MapModelChange::BEGIN_BATCH_UPDATE )
+    {
+        _batchUpdateInProgress = true;
+    }
+
+    else if ( change.getAction() == MapModelChange::END_BATCH_UPDATE )
+    {
+        _batchUpdateInProgress = false;
+
+        if ( _refreshRequired )
+            refresh();
+
+        if ( _stateUpdateRequired )
+            updateState();
+    }
+
+    else
+    {
+        // update the thread-safe map model copy:
+        if ( _update_mapf->sync() )
+        {
+            _liveTiles->setMapRevision( _update_mapf->getRevision() );
+        }
+
+        // dispatch the change handler
+        if ( change.getLayer() )
+        {
+            // then apply the actual change:
+            switch( change.getAction() )
+            {
+            case MapModelChange::ADD_IMAGE_LAYER:
+                addImageLayer( change.getImageLayer() );
+                break;
+            case MapModelChange::REMOVE_IMAGE_LAYER:
+                removeImageLayer( change.getImageLayer() );
+                break;
+            case MapModelChange::ADD_ELEVATION_LAYER:
+                addElevationLayer( change.getElevationLayer() );
+                break;
+            case MapModelChange::REMOVE_ELEVATION_LAYER:
+                removeElevationLayer( change.getElevationLayer() );
+                break;
+            case MapModelChange::MOVE_IMAGE_LAYER:
+                moveImageLayer( change.getFirstIndex(), change.getSecondIndex() );
+                break;
+            case MapModelChange::MOVE_ELEVATION_LAYER:
+                moveElevationLayer( change.getFirstIndex(), change.getSecondIndex() );
+                break;
+            case MapModelChange::TOGGLE_ELEVATION_LAYER:
+                toggleElevationLayer( change.getElevationLayer() );
+                break;
+            case MapModelChange::ADD_MODEL_LAYER:
+            case MapModelChange::REMOVE_MODEL_LAYER:
+            case MapModelChange::MOVE_MODEL_LAYER:
+            default: 
+                break;
+            }
+        }
+    }
+}
+
+
+void
+RexTerrainEngineNode::addImageLayer( ImageLayer* layerAdded )
+{
+    if ( layerAdded && layerAdded->getEnabled() )
+    {
+        // for a shared layer, allocate a shared image unit if necessary.
+        if ( layerAdded->isShared() )
+        {
+            optional<int>& unit = layerAdded->shareImageUnit();
+            if ( !unit.isSet() )
+            {
+                int temp;
+                if ( getResources()->reserveTextureImageUnit(temp) )
+                {
+                    layerAdded->shareImageUnit() = temp;
+                    OE_INFO << LC << "Image unit " << temp << " assigned to shared layer " << layerAdded->getName() << std::endl;
+                }
+                else
+                {
+                    OE_WARN << LC << "Insufficient GPU image units to share layer " << layerAdded->getName() << std::endl;
+                }
+            }
+
+            // Build a sampler binding for the layer.
+            if ( unit.isSet() )
+            {
+                _renderBindings.push_back( SamplerBinding() );
+                SamplerBinding& binding = _renderBindings.back();
+
+                //binding.usage()     = binding.MATERIAL; // ?... not COLOR at least
+                binding.sourceUID() = layerAdded->getUID();
+                binding.unit()      = unit.get();
+
+                binding.samplerName() = layerAdded->shareTexUniformName().get();
+                binding.matrixName()  = layerAdded->shareTexMatUniformName().get();
+
+                OE_INFO << LC 
+                    << " .. Sampler=\"" << binding.samplerName() << "\", "
+                    << "Matrix=\"" << binding.matrixName() << ", "
+                    << "unit=" << binding.unit() << "\n";                
+            }
+        }
+    }
+
+    refresh();
+}
+
+
+void
+RexTerrainEngineNode::removeImageLayer( ImageLayer* layerRemoved )
+{
+    if ( layerRemoved )
+    {
+        // for a shared layer, release the shared image unit.
+        if ( layerRemoved->getEnabled() && layerRemoved->isShared() )
+        {
+            if ( layerRemoved->shareImageUnit().isSet() )
+            {
+                getResources()->releaseTextureImageUnit( *layerRemoved->shareImageUnit() );
+                layerRemoved->shareImageUnit().unset();
+            }
+
+            //TODO: remove the sampler/matrix uniforms
+        }
+    }
+
+    refresh();
+}
+
+void
+RexTerrainEngineNode::moveImageLayer( unsigned int oldIndex, unsigned int newIndex )
+{
+    updateState();
+}
+
+void
+RexTerrainEngineNode::addElevationLayer( ElevationLayer* layer )
+{
+    if ( layer == 0L || layer->getEnabled() == false )
+        return;
+
+    layer->addCallback( _elevationCallback.get() );
+
+    refresh();
+}
+
+void
+RexTerrainEngineNode::removeElevationLayer( ElevationLayer* layerRemoved )
+{
+    if ( layerRemoved->getEnabled() == false )
+        return;
+
+    layerRemoved->removeCallback( _elevationCallback.get() );
+
+    refresh();
+}
+
+void
+RexTerrainEngineNode::moveElevationLayer( unsigned int oldIndex, unsigned int newIndex )
+{
+    refresh();
+}
+
+void
+RexTerrainEngineNode::toggleElevationLayer( ElevationLayer* layer )
+{
+    refresh();
+}
+
+// Generates the main shader code for rendering the terrain.
+void
+RexTerrainEngineNode::updateState()
+{
+    if ( _batchUpdateInProgress )
+    {
+        _stateUpdateRequired = true;
+    }
+    else
+    {
+        osg::StateSet* terrainStateSet   = _terrain->getOrCreateStateSet();   // everything
+        osg::StateSet* surfaceStateSet   = getSurfaceStateSet();    // just the surface
+        
+        terrainStateSet->setRenderBinDetails(0, "SORT_FRONT_TO_BACK");
+        
+        // required for multipass tile rendering to work
+        surfaceStateSet->setAttributeAndModes(
+            new osg::Depth(osg::Depth::LEQUAL, 0, 1, true) );
+
+        // activate standard mix blending.
+        terrainStateSet->setAttributeAndModes( 
+            new osg::BlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA),
+            osg::StateAttribute::ON );
+
+        // install patch param if we are tessellation on the GPU.
+        if ( _terrainOptions.gpuTessellation() == true )
+        {
+            #ifdef HAVE_PATCH_PARAMETER
+              terrainStateSet->setAttributeAndModes( new osg::PatchParameter(3) );
+            #endif
+        }
+
+        // install shaders, if we're using them.
+        if ( Registry::capabilities().supportsGLSL() )
+        {
+            Shaders package;
+
+            VirtualProgram* terrainVP = VirtualProgram::getOrCreate(terrainStateSet);
+            terrainVP->setName( "Rex Terrain" );
+            package.load(terrainVP, package.ENGINE_VERT_MODEL);
+            
+            surfaceStateSet->addUniform(new osg::Uniform("oe_terrain_color", _terrainOptions.color().get()));
+
+            bool useBlending = _terrainOptions.enableBlending().get();
+            package.define("OE_REX_GL_BLENDING", useBlending);
+
+            bool morphImagery = _terrainOptions.morphImagery().get();
+            package.define("OE_REX_MORPH_IMAGERY", morphImagery);
+
+            // Funtions that affect only the terrain surface:
+            VirtualProgram* surfaceVP = VirtualProgram::getOrCreate(surfaceStateSet);
+            surfaceVP->setName("Rex Surface");
+
+            // Functions that affect the terrain surface only:
+            package.load(surfaceVP, package.ENGINE_VERT_VIEW);
+            package.load(surfaceVP, package.ENGINE_FRAG);
+
+            // Normal mapping shaders:
+            if ( this->normalTexturesRequired() )
+            {
+                package.load(surfaceVP, package.NORMAL_MAP_VERT);
+                package.load(surfaceVP, package.NORMAL_MAP_FRAG);
+            }
+
+            // Morphing?
+            if (_terrainOptions.morphTerrain() == true ||
+                _terrainOptions.morphImagery() == true)
+            {
+                package.define("OE_REX_VERTEX_MORPHING", (_terrainOptions.morphTerrain() == true));
+                package.load(surfaceVP, package.MORPHING_VERT);
+            }
+
+            // assemble color filter code snippets.
+            bool haveColorFilters = false;
+            {
+                // Color filter frag function:
+                std::string fs_colorfilters =
+                    "#version " GLSL_VERSION_STR "\n"
+                    GLSL_DEFAULT_PRECISION_FLOAT "\n"
+                    "uniform int oe_layer_uid; \n"
+                    "$COLOR_FILTER_HEAD"
+                    "void oe_rexEngine_applyFilters(inout vec4 color) \n"
+                    "{ \n"
+                        "$COLOR_FILTER_BODY"
+                    "} \n";
+
+                std::stringstream cf_head;
+                std::stringstream cf_body;
+                const char* I = "    ";
+
+                // second, install the per-layer color filter functions AND shared layer bindings.
+                bool ifStarted = false;
+                int numImageLayers = _update_mapf->imageLayers().size();
+                for( int i=0; i<numImageLayers; ++i )
+                {
+                    ImageLayer* layer = _update_mapf->getImageLayerAt(i);
+                    if ( layer->getEnabled() )
+                    {
+                        // install Color Filter function calls:
+                        const ColorFilterChain& chain = layer->getColorFilters();
+                        if ( chain.size() > 0 )
+                        {
+                            haveColorFilters = true;
+                            if ( ifStarted ) cf_body << I << "else if ";
+                            else             cf_body << I << "if ";
+                            cf_body << "(oe_layer_uid == " << layer->getUID() << ") {\n";
+                            for( ColorFilterChain::const_iterator j = chain.begin(); j != chain.end(); ++j )
+                            {
+                                const ColorFilter* filter = j->get();
+                                cf_head << "void " << filter->getEntryPointFunctionName() << "(inout vec4 color);\n";
+                                cf_body << I << I << filter->getEntryPointFunctionName() << "(color);\n";
+                                filter->install( surfaceStateSet );
+                            }
+                            cf_body << I << "}\n";
+                            ifStarted = true;
+                        }
+                    }
+                }
+
+                if ( haveColorFilters )
+                {
+                    std::string cf_head_str, cf_body_str;
+                    cf_head_str = cf_head.str();
+                    cf_body_str = cf_body.str();
+
+                    replaceIn( fs_colorfilters, "$COLOR_FILTER_HEAD", cf_head_str );
+                    replaceIn( fs_colorfilters, "$COLOR_FILTER_BODY", cf_body_str );
+
+                    surfaceVP->setFunction(
+                        "oe_rexEngine_applyFilters",
+                        fs_colorfilters,
+                        ShaderComp::LOCATION_FRAGMENT_COLORING,
+                        0.6 );
+                }
+            }
+
+            // Apply uniforms for sampler bindings:
+            OE_DEBUG << LC << "Render Bindings:\n";
+            for(RenderBindings::const_iterator b = _renderBindings.begin(); b != _renderBindings.end(); ++b)
+            {
+                osg::Image* empty = ImageUtils::createEmptyImage(1,1);
+                osg::ref_ptr<osg::Texture2D> tex = new osg::Texture2D(empty);
+
+                if ( b->isActive() )
+                {
+                    terrainStateSet->addUniform( new osg::Uniform(b->samplerName().c_str(), b->unit()) );
+                    OE_DEBUG << LC << " > Bound \"" << b->samplerName() << "\" to unit " << b->unit() << "\n";
+                    terrainStateSet->setTextureAttribute(b->unit(), tex.get());
+                }
+
+            }
+
+            // uniform that controls per-layer opacity
+            terrainStateSet->addUniform( new osg::Uniform("oe_layer_opacity", 1.0f) );
+
+            // uniform that conveys the layer UID to the shaders; necessary
+            // for per-layer branching (like color filters)
+            // UID -1 => no image layer (no texture)
+            terrainStateSet->addUniform( new osg::Uniform("oe_layer_uid", (int)-1 ) );
+
+            // uniform that conveys the render order, since the shaders
+            // need to know which is the first layer in order to blend properly
+            terrainStateSet->addUniform( new osg::Uniform("oe_layer_order", (int)0) );
+
+            // default min/max range uniforms. (max < min means ranges are disabled)
+            terrainStateSet->addUniform( new osg::Uniform("oe_layer_minRange", 0.0f) );
+            terrainStateSet->addUniform( new osg::Uniform("oe_layer_maxRange", -1.0f) );
+            terrainStateSet->addUniform( new osg::Uniform("oe_layer_attenuationRange", _terrainOptions.attentuationDistance().get()) );
+            
+            terrainStateSet->getOrCreateUniform(
+                "oe_min_tile_range_factor",
+                osg::Uniform::FLOAT)->set( *_terrainOptions.minTileRangeFactor() );
+
+            terrainStateSet->addUniform(new osg::Uniform("oe_tile_size", (float)_terrainOptions.tileSize().get()));
+
+            // special object ID that denotes the terrain surface.
+            surfaceStateSet->addUniform( new osg::Uniform(
+                Registry::objectIndex()->getObjectIDUniformName().c_str(), OSGEARTH_OBJECTID_TERRAIN) );
+        }
+
+        _stateUpdateRequired = false;
+    }
+}
diff --git a/src/osgEarthDrivers/engine_rex/RexTerrainEngineOptions b/src/osgEarthDrivers/engine_rex/RexTerrainEngineOptions
new file mode 100644
index 0000000..20c135f
--- /dev/null
+++ b/src/osgEarthDrivers/engine_rex/RexTerrainEngineOptions
@@ -0,0 +1,163 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+ * Copyright 2008-2014 Pelican Mapping
+ * http://osgearth.org
+ *
+ * osgEarth is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ */
+#ifndef OSGEARTH_DRIVERS_REX_TERRAIN_ENGINE_OPTIONS
+#define OSGEARTH_DRIVERS_REX_TERRAIN_ENGINE_OPTIONS 1
+
+#include <osgEarth/Common>
+#include <osgEarth/TerrainOptions>
+#include <osgEarthSymbology/Color>
+#include <osg/LOD>
+
+namespace osgEarth { namespace Drivers { namespace RexTerrainEngine
+{
+    using namespace osgEarth;
+    using namespace osgEarth::Symbology;
+
+    /**
+     * Options for configuring the Rex Engine driver.
+     */
+    class RexTerrainEngineOptions : public TerrainOptions // NO EXPORT (header-only)
+    {
+    public:
+        RexTerrainEngineOptions( const ConfigOptions& options =ConfigOptions() ) : TerrainOptions( options ),
+            _skirtRatio             ( 0.0f ),
+            _color                  ( Color::White ),
+            //_quickRelease           ( false ),
+            _expirationThreshold    ( 300 ),
+            _progressive            ( false ),
+            _highResolutionFirst    ( true ),
+            _normalMaps             ( true ),
+            _morphTerrain           ( true ),
+            _morphImagery           ( true ),
+            _mergesPerFrame         ( 20 ),
+            _expirationRange        ( 0 )
+        {
+            setDriver( "rex" );
+            fromConfig( _conf );
+
+            // override.
+            enableMercatorFastPath().init( false );
+        }
+
+        /** dtor */
+        virtual ~RexTerrainEngineOptions() { }
+
+    public:
+        /** Ratio of terrain tile skirt height to tile radius */
+        optional<float>& heightFieldSkirtRatio() { return _skirtRatio; }
+        const optional<float>& heightFieldSkirtRatio() const { return _skirtRatio; }
+
+        /** The color of the globe surface where no images are applied */
+        optional<Color>& color() { return _color; }
+        const optional<Color>& color() const { return _color; }
+
+#if 0
+        /** Whether to run a post-render process that releases GL objects as quickly as
+          * possible, freeing up memory faster */
+        optional<bool>& quickReleaseGLObjects() { return _quickRelease; }
+        const optional<bool>& quickReleaseGLObjects() const { return _quickRelease; }
+#endif
+
+        /** Minimum distance at which tiles will page out of memory once loaded */
+        optional<float>& expirationRange() { return _expirationRange; }
+        const optional<float>& expirationRange() const { return _expirationRange; }
+
+        /** Number of terrain tiles to keep in memory before expiring usused tiles. */
+        optional<unsigned>& expirationThreshold() { return _expirationThreshold; }
+        const optional<unsigned>& expirationThreshold() const { return _expirationThreshold; }
+
+        /** Whether to finish loading a tile's data before subdividing */
+        optional<bool>& progressive() { return _progressive; }
+        const optional<bool>& progressive() const { return _progressive; }
+
+        /** Whether to load higher-resolution data first. */
+        optional<bool>& highResolutionFirst() { return _highResolutionFirst; }
+        const optional<bool>& highResolutionFirst() const { return _highResolutionFirst; } 
+
+        /** Whether to generate normal map textures. Default is true. */
+        optional<bool>& normalMaps() { return _normalMaps; }
+        const optional<bool>& normalMaps() const { return _normalMaps; }
+
+        /** Whether to morph terrain data between terrain tile LODs. */
+        optional<bool>& morphTerrain() { return _morphTerrain; }
+        const optional<bool>& morphTerrain() const { return _morphTerrain; }
+
+        /** Whether to morph imagery between terrain tile LODs. */
+        optional<bool>& morphImagery() { return _morphImagery; }
+        const optional<bool>& morphImagery() const { return _morphImagery; }
+
+        /** Maximum number of tile data merges permitted per frame. 0 = infinity. */
+        optional<int>& mergesPerFrame() { return _mergesPerFrame; }
+        const optional<int>& mergesPerFrame() const { return _mergesPerFrame; }
+
+
+    protected:
+        virtual Config getConfig() const {
+            Config conf = TerrainOptions::getConfig();
+            conf.updateIfSet( "skirt_ratio", _skirtRatio );
+            conf.updateIfSet( "color", _color );
+            conf.updateIfSet( "quick_release_gl_objects", _quickRelease );
+            conf.updateIfSet( "expiration_range", _expirationRange );
+            conf.updateIfSet( "expiration_threshold", _expirationThreshold );
+            conf.updateIfSet( "progressive", _progressive );
+            conf.updateIfSet( "high_resolution_first", _highResolutionFirst );
+            conf.updateIfSet( "normal_maps", _normalMaps );
+            conf.updateIfSet( "morph_terrain", _morphTerrain );
+            conf.updateIfSet( "morph_imagery", _morphImagery );
+            conf.updateIfSet( "merges_per_frame", _mergesPerFrame );
+
+            return conf;
+        }
+
+        virtual void mergeConfig( const Config& conf ) {
+            TerrainOptions::mergeConfig( conf );
+            fromConfig( conf );
+        }
+
+    private:
+        void fromConfig( const Config& conf ) {
+            conf.getIfSet( "skirt_ratio", _skirtRatio );
+            conf.getIfSet( "color", _color );
+            conf.getIfSet( "quick_release_gl_objects", _quickRelease );
+            conf.getIfSet( "expiration_range", _expirationRange );
+            conf.getIfSet( "expiration_threshold", _expirationThreshold );
+            conf.getIfSet( "progressive", _progressive );
+            conf.getIfSet( "high_resolution_first", _highResolutionFirst );
+            conf.getIfSet( "normal_maps", _normalMaps );
+            conf.getIfSet( "morph_terrain", _morphTerrain );
+            conf.getIfSet( "morph_imagery", _morphImagery );
+            conf.getIfSet( "merges_per_frame", _mergesPerFrame );
+        }
+
+        optional<float>    _skirtRatio;
+        optional<Color>    _color;
+        optional<bool>     _quickRelease;
+        optional<float>    _expirationRange;
+        optional<unsigned> _expirationThreshold;
+        optional<bool>     _progressive;
+        optional<bool>     _highResolutionFirst;
+        optional<bool>     _normalMaps;
+        optional<bool>     _morphTerrain;
+        optional<bool>     _morphImagery;
+        optional<int>      _mergesPerFrame;
+    };
+
+} } } // namespace osgEarth::Drivers::RexTerrainEngine
+
+#endif // OSGEARTH_DRIVERS_REX_TERRAIN_ENGINE_OPTIONS
diff --git a/src/osgEarthDrivers/engine_rex/SelectionInfo b/src/osgEarthDrivers/engine_rex/SelectionInfo
new file mode 100644
index 0000000..431f86e
--- /dev/null
+++ b/src/osgEarthDrivers/engine_rex/SelectionInfo
@@ -0,0 +1,77 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+* Copyright 2008-2014 Pelican Mapping
+* http://osgearth.org
+*
+* osgEarth is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public License
+* along with this program.  If not, see <http://www.gnu.org/licenses/>
+*/
+#ifndef OSGEARTH_DRIVERS_REX_TERRAIN_ENGINE_SELECTION_INFO
+#define OSGEARTH_DRIVERS_REX_TERRAIN_ENGINE_SELECTION_INFO 1
+
+#include "Common"
+#include <vector>
+
+
+namespace osgEarth { namespace Drivers { namespace RexTerrainEngine
+{
+    struct VisParameters
+    {
+        double _visibilityRange;
+        double _visibilityRange2;
+        double _fMorphStart;
+        double _fMorphEnd;
+    };
+    class SelectionInfo
+    {
+    public:
+        SelectionInfo() : _numLods(0), _uiFirstLOD(0) { }
+
+        bool initialized(void) const;
+        void initialize(unsigned uiFirstLOD, unsigned uiMaxLod, unsigned uiTileSize, double fLodFar);
+
+        unsigned numLods(void) const;
+
+        // Dimensions of the skeleton grid in X
+        unsigned gridDimX(void) const;
+
+        // Dimensions of the skeleton grid in Y
+        unsigned gridDimY(void) const;
+
+        // Morph start ratio
+        static double   morphStartRatio(void);
+
+        // LOD at which morphing should start
+        static unsigned lodForMorphing(bool isProjected);
+
+        VisParameters visParameters(unsigned lod) const;
+    private:
+        unsigned                        _numLods;
+        std::pair<unsigned, unsigned>   _uiGridDimensions; 
+        std::vector<VisParameters>      _vecVisParams;
+        unsigned                        _uiFirstLOD;
+
+        static const double             _fMorphStartRatio; 
+
+        // This is the lod at which morphing should start (used by shader)
+        static const unsigned           _uiLODForMorphingRoundEarth;
+        
+        // This is used to determine _numLods given a fLodFar during initialize
+        // initialize. This is the distance beyond which further lods (and 
+        // hence VisParameters) are not generated
+        static const double             _fLodLowerBound;
+    };
+}
+}
+}
+#endif
diff --git a/src/osgEarthDrivers/engine_rex/SelectionInfo.cpp b/src/osgEarthDrivers/engine_rex/SelectionInfo.cpp
new file mode 100644
index 0000000..76560ce
--- /dev/null
+++ b/src/osgEarthDrivers/engine_rex/SelectionInfo.cpp
@@ -0,0 +1,120 @@
+#include "SelectionInfo"
+#include "SurfaceNode"
+#include "RexTerrainEngineOptions"
+
+using namespace osgEarth::Drivers::RexTerrainEngine;
+using namespace osgEarth;
+
+#define LC "[SelectionInfo] "
+
+const unsigned SelectionInfo::_uiLODForMorphingRoundEarth = 0;
+const double   SelectionInfo::_fLodLowerBound   = 12.0;
+const double   SelectionInfo::_fMorphStartRatio = 0.66;
+
+unsigned SelectionInfo::lodForMorphing(bool isProjected)
+{
+    return (isProjected) ? 0 : _uiLODForMorphingRoundEarth;
+}
+
+double SelectionInfo::morphStartRatio(void) 
+{
+    return _fMorphStartRatio;
+}
+
+unsigned SelectionInfo::numLods(void) const
+{
+    return _numLods;
+}
+
+unsigned SelectionInfo::gridDimX(void) const
+{
+    return _uiGridDimensions.first;
+}
+
+unsigned SelectionInfo::gridDimY(void) const
+{
+    return _uiGridDimensions.second;
+}
+
+VisParameters SelectionInfo::visParameters(unsigned lod) const
+{
+    if (lod-_uiFirstLOD>=_vecVisParams.size())
+    {
+        // note, this can happen if firstLOD() is set
+        OE_DEBUG << LC <<"Index out of bounds"<<std::endl;
+        return VisParameters();
+    }
+    return _vecVisParams[lod-_uiFirstLOD];
+}
+
+bool SelectionInfo::initialized(void) const
+{
+    return _vecVisParams.size()>0;
+}
+
+void SelectionInfo::initialize(unsigned uiFirstLOD, unsigned uiMaxLod, unsigned uiTileSize, double fLodFar)
+{
+    if (initialized())
+    {
+        OE_INFO << LC <<"Error: Selection Information already initialized"<<std::endl;
+        return;
+    }
+
+    if (fLodFar<0)
+    {
+        OE_INFO << LC <<"Error: Invalid fLodFar hint"<<std::endl;
+        return;
+    }
+    if (uiFirstLOD>uiMaxLod)
+    {
+        OE_INFO << LC <<"Error: Inconsistent First and Max LODs"<<std::endl;
+        return;
+    }
+    _uiGridDimensions.first  = uiTileSize;
+    _uiGridDimensions.second = uiTileSize;
+
+    _uiFirstLOD = uiFirstLOD;
+
+    double fLodNear = 0;
+    float fRatio = 1.0;
+
+    unsigned currLOD = _uiFirstLOD;
+    while(currLOD<=uiMaxLod)
+    {
+        double fVisibility = fLodNear + fRatio*(fLodFar-fLodNear);
+        if (fVisibility<_fLodLowerBound)
+        {
+            break;
+        }
+        fRatio*= 0.5;
+        ++currLOD;
+    }
+
+    _numLods = currLOD-_uiFirstLOD;
+
+    fLodNear = 0;
+    fRatio = 1.0;
+    _vecVisParams.resize(_numLods);
+    for( int i = 0; i < (int)_numLods; ++i )
+    {
+        _vecVisParams[i]._visibilityRange = fLodNear + fRatio*(fLodFar-fLodNear);
+        _vecVisParams[i]._visibilityRange2 = _vecVisParams[i]._visibilityRange * _vecVisParams[i]._visibilityRange;
+        fRatio *= 0.5;
+    }
+
+    double fPrevPos = fLodNear;
+    for (int i=(int)(_numLods-1); i>=0; --i)
+    {
+        _vecVisParams[i]._fMorphEnd   = _vecVisParams[i]._visibilityRange;
+        _vecVisParams[i]._fMorphStart = fPrevPos + (_vecVisParams[i]._fMorphEnd - fPrevPos) * _fMorphStartRatio;
+
+        fPrevPos = _vecVisParams[i]._fMorphStart;
+    }
+    for( int i = 0; i < (int)_numLods; ++i ) 
+    {
+        OE_DEBUG << "LOD[" << i+_uiFirstLOD<<"] = "<<_vecVisParams[i]._visibilityRange
+                 <<" Start: "<<_vecVisParams[i]._fMorphStart
+                 <<" End  : "<<_vecVisParams[i]._fMorphEnd
+                 <<std::endl;
+    }
+}
\ No newline at end of file
diff --git a/src/osgEarthDrivers/engine_rex/Shaders b/src/osgEarthDrivers/engine_rex/Shaders
new file mode 100644
index 0000000..07d38bc
--- /dev/null
+++ b/src/osgEarthDrivers/engine_rex/Shaders
@@ -0,0 +1,39 @@
+// ***DO NOT EDIT THIS FILE - IT IS AUTOMATICALLY GENERATED BY CMAKE***
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+* Copyright 2008-2012 Pelican Mapping
+* http://osgearth.org
+*
+* osgEarth is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public License
+* along with this program.  If not, see <http://www.gnu.org/licenses/>
+*/
+#include <osgEarth/ShaderLoader>
+
+namespace osgEarth { namespace Drivers { namespace RexTerrainEngine
+{
+    struct Shaders : public ShaderPackage
+	{
+        Shaders();
+
+        std::string
+            ENGINE_VERT_MODEL,
+            ENGINE_VERT_VIEW,
+            ENGINE_FRAG,
+            ENGINE_GEOM,
+            NORMAL_MAP_VERT,
+            NORMAL_MAP_FRAG,
+            MORPHING_VERT,
+            SDK;
+	};
+	
+} } } // namespace osgEarth::Drivers::RexTerrainEngine
diff --git a/src/osgEarthDrivers/engine_rex/Shaders.cpp.in b/src/osgEarthDrivers/engine_rex/Shaders.cpp.in
new file mode 100644
index 0000000..ad3fa04
--- /dev/null
+++ b/src/osgEarthDrivers/engine_rex/Shaders.cpp.in
@@ -0,0 +1,32 @@
+// ***DO NOT EDIT THIS FILE - IT IS AUTOMATICALLY GENERATED BY CMAKE***
+
+#include <osgEarthDrivers/engine_rex/Shaders>
+
+using namespace osgEarth::Drivers::RexTerrainEngine;
+
+Shaders::Shaders()
+{
+    ENGINE_VERT_MODEL = "RexEngine.vert.glsl";
+    _sources[ENGINE_VERT_MODEL] = "@RexEngine.vert.glsl@";
+
+    MORPHING_VERT = "RexEngine.Morphing.vert.glsl";
+    _sources[MORPHING_VERT] = "@RexEngine.Morphing.vert.glsl@";
+
+    ENGINE_VERT_VIEW = "RexEngine.vert.view.glsl";
+    _sources[ENGINE_VERT_VIEW] = "@RexEngine.vert.view.glsl@";
+
+    ENGINE_FRAG = "RexEngine.frag.glsl";
+    _sources[ENGINE_FRAG] = "@RexEngine.frag.glsl@";
+
+    NORMAL_MAP_VERT = "RexEngine.NormalMap.vert.glsl";
+    _sources[NORMAL_MAP_VERT] = "@RexEngine.NormalMap.vert.glsl@";
+
+    NORMAL_MAP_FRAG = "RexEngine.NormalMap.frag.glsl";
+    _sources[NORMAL_MAP_FRAG] = "@RexEngine.NormalMap.frag.glsl@";
+
+    ENGINE_GEOM = "RexEngine.gs.glsl";
+    _sources[ENGINE_GEOM] = "@RexEngine.gs.glsl@";
+
+    SDK = "RexEngine.SDK.vert.glsl";
+    _sources[SDK] = "@RexEngine.SDK.vert.glsl@";
+}
diff --git a/src/osgEarthDrivers/engine_rex/SurfaceNode b/src/osgEarthDrivers/engine_rex/SurfaceNode
new file mode 100644
index 0000000..0f53209
--- /dev/null
+++ b/src/osgEarthDrivers/engine_rex/SurfaceNode
@@ -0,0 +1,124 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+* Copyright 2008-2014 Pelican Mapping
+* http://osgearth.org
+*
+* osgEarth is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public License
+* along with this program.  If not, see <http://www.gnu.org/licenses/>
+*/
+#ifndef OSGEARTH_DRIVERS_REX_SURFACE_NODE
+#define OSGEARTH_DRIVERS_REX_SURFACE_NODE 1
+
+#include "Common"
+#include "GeometryPool"
+#include "RenderBindings"
+#include "TileDrawable"
+
+#include <osgEarth/MapInfo>
+#include <osgEarth/Horizon>
+#include <osg/MatrixTransform>
+#include <osg/BoundingBox>
+#include <osg/Drawable>
+#include <osg/Geode>
+#include <osgText/Text>
+#include <osgUtil/CullVisitor>
+#include <vector>
+
+namespace osgEarth { namespace Drivers { namespace RexTerrainEngine
+{
+    using namespace osgEarth;
+
+    /**
+     * Like cluster culling
+     */
+    struct HorizonTileCuller
+    {
+        osg::Vec3d  _points[4];
+        osg::ref_ptr<Horizon> _horizon;
+
+        void set(const SpatialReference* srs, const osg::Matrix& local2world, const osg::BoundingBox& bbox);
+
+        bool isVisible(const osg::Vec3d& from) const;
+    };
+
+
+    /**
+     * SurfaceNode holds the geometry of the terrain surface.
+     */
+    class SurfaceNode : public osg::MatrixTransform
+    {
+    public:
+        SurfaceNode(
+            const TileKey&        tilekey,
+            const MapInfo&        mapinfo,
+            const RenderBindings& bindings,
+            TileDrawable*         drawable);
+
+        void setElevationRaster(const osg::Image* raster, const osg::Matrixf& scaleBias);
+        const osg::Image* getElevationRaster() const;
+        const osg::Matrixf& getElevationMatrix() const;
+
+        const osg::BoundingBox& getAlignedBoundingBox() const;
+        
+        TileDrawable* getDrawable() const { return _drawable.get(); }
+
+        inline bool isVisible(osgUtil::CullVisitor* cv) const {
+            return _horizonCuller.isVisible(cv->getViewPointLocal());
+        }
+        
+        // A box can have 4 children. 
+        // Returns true if any child box intersects the sphere of radius centered around point
+        inline bool anyChildBoxIntersectsSphere(const osg::Vec3& point, float radiusSquared, float lodScale) {
+            double X = radiusSquared / (lodScale*lodScale);
+            for(int c=0; c<4; ++c) {
+                for(int j=0; j<8; ++j) {
+                    if ( (_childrenCorners[c][j]-point).length2() < X )
+                        return true;
+                }
+            }
+            return false;
+        }
+
+        void setDebugText(const std::string& strText);
+
+    protected:
+        virtual ~SurfaceNode() { }
+
+        TileKey                    _tileKey;
+        osg::BoundingBox           _bbox;
+        osg::ref_ptr<TileDrawable> _drawable;
+        osg::ref_ptr<osg::Geode>   _surfaceGeode;
+
+        osg::ref_ptr<osg::Geode>    _debugGeode;
+        osg::ref_ptr<osgText::Text> _debugText;
+        static const bool           _enableDebugNodes;
+        
+        HorizonTileCuller           _horizonCuller;        
+
+        typedef osg::Vec3 VectorPoints[8];
+
+
+        void addDebugNode(const osg::BoundingBox& box);
+        void removeDebugNode(void);
+
+        VectorPoints _worldCorners;
+
+        typedef VectorPoints (ChildrenCorners) [4];
+        ChildrenCorners _childrenCorners;
+
+        //osg::ref_ptr<osg::RefMatrix> _matrix;
+    };
+
+} } } // namespace osgEarth::Drivers::RexTerrainEngine
+
+#endif // OSGEARTH_DRIVERS_REX_SURFACE_NODE
diff --git a/src/osgEarthDrivers/engine_rex/SurfaceNode.cpp b/src/osgEarthDrivers/engine_rex/SurfaceNode.cpp
new file mode 100644
index 0000000..b2c4591
--- /dev/null
+++ b/src/osgEarthDrivers/engine_rex/SurfaceNode.cpp
@@ -0,0 +1,418 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+* Copyright 2008-2014 Pelican Mapping
+* http://osgearth.org
+*
+* osgEarth is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public License
+* along with this program.  If not, see <http://www.gnu.org/licenses/>
+*/
+#include "SurfaceNode"
+#include "GeometryPool"
+#include "TileDrawable"
+
+#include <osgEarth/TileKey>
+#include <osgEarth/Registry>
+#include <osgEarth/Horizon>
+#include <osgEarth/ImageUtils>
+
+#include <osg/CullStack>
+#include <osg/Geode>
+
+#include <osg/Geometry>
+#include <osg/TriangleFunctor>
+#include <osgText/Text>
+#include <osg/CullStack>
+#include <osgUtil/CullVisitor>
+
+#include <numeric>
+
+using namespace osgEarth::Drivers::RexTerrainEngine;
+using namespace osgEarth;
+
+#define LC "[SurfaceNode] "
+
+//..............................................................
+
+namespace
+{    
+    osg::Geode* makeBBox(const osg::BoundingBox& bbox, const TileKey& key)
+    {        
+        osg::Geode* geode = new osg::Geode();
+        std::string sizeStr = "(empty)";
+        float zpos = 0.0f;
+
+        if ( bbox.valid() )
+        {
+            osg::Geometry* geom = new osg::Geometry();
+            geom->setName("bbox");
+        
+            osg::Vec3Array* v = new osg::Vec3Array();
+            for(int i=0; i<8; ++i)
+                v->push_back(bbox.corner(i));
+            geom->setVertexArray(v);
+
+            osg::DrawElementsUByte* de = new osg::DrawElementsUByte(GL_LINES);
+
+#if 1
+            // bottom:
+            de->push_back(0); de->push_back(1);
+            de->push_back(1); de->push_back(3);
+            de->push_back(3); de->push_back(2);
+            de->push_back(2); de->push_back(0);
+#endif
+#if 1
+            // top:
+            de->push_back(4); de->push_back(5);
+            de->push_back(5); de->push_back(7);
+            de->push_back(7); de->push_back(6);
+            de->push_back(6); de->push_back(4);
+#endif
+#if 0
+            // corners:
+            de->push_back(0); de->push_back(4);
+            de->push_back(1); de->push_back(5);
+            de->push_back(3); de->push_back(7);
+            de->push_back(2); de->push_back(6);
+#endif
+            geom->addPrimitiveSet(de);
+
+            osg::Vec4Array* c= new osg::Vec4Array();
+            c->push_back(osg::Vec4(1,0,0,1));
+            geom->setColorArray(c);
+            geom->setColorBinding(geom->BIND_OVERALL);
+
+            geode->addDrawable(geom);
+
+            sizeStr = Stringify() << key.str() << "\nmax="<<bbox.zMax()<<"\nmin="<<bbox.zMin()<<"\n";
+            zpos = bbox.zMax();
+        }
+
+        osgText::Text* textDrawable = new osgText::Text();
+        textDrawable->setDataVariance(osg::Object::DYNAMIC);
+        textDrawable->setText( sizeStr );
+        textDrawable->setFont( osgEarth::Registry::instance()->getDefaultFont() );
+        textDrawable->setCharacterSizeMode(textDrawable->SCREEN_COORDS);
+        textDrawable->setCharacterSize(32.0f);
+        textDrawable->setAlignment(textDrawable->CENTER_BOTTOM);
+        textDrawable->setColor(osg::Vec4(1,1,1,1));
+        textDrawable->setBackdropColor(osg::Vec4(0,0,0,1));
+        textDrawable->setBackdropType(textDrawable->OUTLINE);
+        textDrawable->setPosition(osg::Vec3(0,0,zpos));
+        textDrawable->setAutoRotateToScreen(true);
+        geode->addDrawable(textDrawable);
+
+        geode->getOrCreateStateSet()->setAttributeAndModes(new osg::Program(),0);
+        geode->getOrCreateStateSet()->setMode(GL_LIGHTING,0);
+        geode->getOrCreateStateSet()->setRenderBinDetails(INT_MAX, "DepthSortedBin");
+
+        return geode;
+    }
+
+    osg::Geode* makeSphere(const osg::BoundingSphere& bs)
+    {
+        osg::Geometry* geom = new osg::Geometry();
+        geom->setUseVertexBufferObjects(true);
+
+        float r = bs.radius();
+
+        osg::Vec3Array* v = new osg::Vec3Array();
+        v->reserve(6);
+        v->push_back(osg::Vec3(0, 0, r)); // top
+        v->push_back(osg::Vec3(0, 0, -r)); // bottom
+        v->push_back(osg::Vec3(-r, 0, 0)); // left
+        v->push_back(osg::Vec3(r, 0, 0)); // right
+        v->push_back(osg::Vec3(0, r, 0)); // back
+        v->push_back(osg::Vec3(0, -r, 0)); // front
+        geom->setVertexArray(v);
+
+        osg::DrawElementsUByte* b = new osg::DrawElementsUByte(GL_LINE_STRIP);
+        b->reserve(24);
+        b->push_back(0); b->push_back(3); b->push_back(4);
+        b->push_back(0); b->push_back(4); b->push_back(2);
+        b->push_back(0); b->push_back(2); b->push_back(5);
+        b->push_back(0); b->push_back(5); b->push_back(3);
+        b->push_back(1); b->push_back(3); b->push_back(5);
+        b->push_back(1); b->push_back(4); b->push_back(3);
+        b->push_back(1); b->push_back(2); b->push_back(4);
+        b->push_back(1); b->push_back(5); b->push_back(2);
+        geom->addPrimitiveSet(b);
+
+        osg::Vec3Array* n = new osg::Vec3Array();
+        n->reserve(6);
+        n->push_back(osg::Vec3(0, 0, 1));
+        n->push_back(osg::Vec3(0, 0, -1));
+        n->push_back(osg::Vec3(-1, 0, 0));
+        n->push_back(osg::Vec3(1, 0, 0));
+        n->push_back(osg::Vec3(0, 1, 0));
+        n->push_back(osg::Vec3(0, -1, 0));
+        geom->setNormalArray(n);
+        geom->setNormalBinding(osg::Geometry::BIND_PER_VERTEX);
+
+        //MeshSubdivider ms;
+        //ms.run(*geom, osg::DegreesToRadians(maxAngle), GEOINTERP_GREAT_CIRCLE);
+
+        osg::Vec4Array* c = new osg::Vec4Array(1);
+        (*c)[0].set(1,1,0,1);
+        geom->setColorArray(c);
+        geom->setColorBinding(osg::Geometry::BIND_OVERALL);
+
+        osg::Geode* geode = new osg::Geode();
+        geode->addDrawable(geom);
+
+        return geode;
+    }
+}
+
+//..............................................................
+
+void
+HorizonTileCuller::set(const SpatialReference* srs, 
+                       const osg::Matrix&      local2world,
+                       const osg::BoundingBox& bbox)
+{
+    if (!_horizon.valid() && srs->isGeographic())
+    {
+        _horizon = new Horizon();
+    }
+
+    if (_horizon.valid())
+    {
+        _horizon->setEllipsoid(*srs->getEllipsoid());
+        //_radiusPolar = srs->getEllipsoid()->getRadiusPolar();
+        //_radiusEquator = srs->getEllipsoid()->getRadiusEquator();
+        //_local2world = local2world;
+
+        // Adjust the horizon ellipsoid based on the minimum Z value of the tile;
+        // necessary because a tile that's below the ellipsoid (ocean floor, e.g.)
+        // may be visible even if it doesn't pass the horizon-cone test. In such
+        // cases we need a more conservative ellipsoid.
+        double zMin = (double)std::min( bbox.corner(0).z(), 0.0f );
+        zMin = std::max(zMin, -25000.0); // approx the lowest point on earth * 2
+        _horizon->setEllipsoid( osg::EllipsoidModel(
+            srs->getEllipsoid()->getRadiusEquator() + zMin, 
+            srs->getEllipsoid()->getRadiusPolar() + zMin) );
+
+        // consider the uppermost 4 points of the tile-aligned bounding box.
+        // (the last four corners of the bbox are the "zmax" corners.)
+        for(unsigned i=0; i<4; ++i)
+        {
+            _points[i] = bbox.corner(4+i) * local2world;
+        }
+
+        //_bs.set(bbox.center() * _local2world, bbox.radius());
+    }
+}
+
+bool
+HorizonTileCuller::isVisible(const osg::Vec3d& from) const
+{
+    if (!_horizon.valid())
+        return true;
+
+    // alternate method (slower)
+    //return _horizon->isVisible(from, _bs.center(), _bs.radius());
+
+    for (unsigned i = 0; i < 4; ++i)
+        if (_horizon->isVisible(from, _points[i], 0.0))
+            return true;
+
+    return false;
+}
+
+//..............................................................
+
+
+const bool SurfaceNode::_enableDebugNodes = ::getenv("OSGEARTH_MP_DEBUG") != 0L;
+
+SurfaceNode::SurfaceNode(const TileKey&        tilekey,
+                         const MapInfo&        mapinfo,
+                         const RenderBindings& bindings,
+                         TileDrawable*         drawable)
+{
+    _tileKey = tilekey;
+
+    _drawable = drawable;
+
+    _surfaceGeode = new osg::Geode();
+    _surfaceGeode->addDrawable( drawable );
+    
+    // Create the final node.
+    addChild( _surfaceGeode.get() );
+
+    // Establish a local reference frame for the tile:
+    GeoPoint centroid;
+    tilekey.getExtent().getCentroid(centroid);
+
+    osg::Matrix local2world;
+    centroid.createLocalToWorld( local2world );
+    setMatrix( local2world );
+    
+    // Initialize the cached bounding box.
+    setElevationRaster( 0L, osg::Matrixf::identity() );
+}
+
+void
+SurfaceNode::setElevationRaster(const osg::Image*   raster,
+                                const osg::Matrixf& scaleBias)
+{
+    if ( !_drawable.valid() )
+        return;
+
+    // communicate the raster to the drawable:
+    if ( raster )
+    {
+        _drawable->setElevationRaster( raster, scaleBias );
+    }
+
+    // next compute the bounding box in local space:
+#if OSG_VERSION_GREATER_OR_EQUAL(3,3,2)
+    const osg::BoundingBox& box = _drawable->getBoundingBox();
+#else
+    const osg::BoundingBox& box = _drawable->getBound();
+#endif
+
+    // Compute the medians of each potential child node:
+
+    osg::Vec3 minZMedians[4];
+    osg::Vec3 maxZMedians[4];
+
+    minZMedians[0] = (box.corner(0)+box.corner(1))*0.5;
+    minZMedians[1] = (box.corner(1)+box.corner(3))*0.5;
+    minZMedians[2] = (box.corner(3)+box.corner(2))*0.5;
+    minZMedians[3] = (box.corner(0)+box.corner(2))*0.5;
+                                  
+    maxZMedians[0] = (box.corner(4)+box.corner(5))*0.5;
+    maxZMedians[1] = (box.corner(5)+box.corner(7))*0.5;
+    maxZMedians[2] = (box.corner(7)+box.corner(6))*0.5;
+    maxZMedians[3] = (box.corner(4)+box.corner(6))*0.5;
+                                  
+    // Child 0 corners
+    _childrenCorners[0][0] =  box.corner(0);
+    _childrenCorners[0][1] =  minZMedians[0];
+    _childrenCorners[0][2] =  minZMedians[3];
+    _childrenCorners[0][3] = (minZMedians[0]+minZMedians[2])*0.5;
+
+    _childrenCorners[0][4] =  box.corner(4);
+    _childrenCorners[0][5] =  maxZMedians[0];
+    _childrenCorners[0][6] =  maxZMedians[3];
+    _childrenCorners[0][7] = (maxZMedians[0]+maxZMedians[2])*0.5;
+
+    // Child 1 corners
+    _childrenCorners[1][0] =  minZMedians[0];
+    _childrenCorners[1][1] =  box.corner(1);
+    _childrenCorners[1][2] = (minZMedians[0]+minZMedians[2])*0.5;
+    _childrenCorners[1][3] =  minZMedians[1];
+                     
+    _childrenCorners[1][4] =  maxZMedians[0];
+    _childrenCorners[1][5] =  box.corner(5);
+    _childrenCorners[1][6] = (maxZMedians[0]+maxZMedians[2])*0.5;
+    _childrenCorners[1][7] =  maxZMedians[1];
+
+    // Child 2 corners
+    _childrenCorners[2][0] =  minZMedians[3];
+    _childrenCorners[2][1] = (minZMedians[0]+minZMedians[2])*0.5;
+    _childrenCorners[2][2] =  box.corner(2);
+    _childrenCorners[2][3] =  minZMedians[2];
+                     
+    _childrenCorners[2][4] =  maxZMedians[3];
+    _childrenCorners[2][5] = (maxZMedians[0]+maxZMedians[2])*0.5;
+    _childrenCorners[2][6] =  box.corner(6);
+    _childrenCorners[2][7] =  maxZMedians[2]; 
+
+    // Child 3 corners
+    _childrenCorners[3][0] = (minZMedians[0]+minZMedians[2])*0.5;
+    _childrenCorners[3][1] =  minZMedians[1];
+    _childrenCorners[3][2] =  minZMedians[2];
+    _childrenCorners[3][3] =  box.corner(3);
+                     
+    _childrenCorners[3][4] = (maxZMedians[0]+maxZMedians[2])*0.5;
+    _childrenCorners[3][5] =  maxZMedians[1];
+    _childrenCorners[3][6] =  maxZMedians[2];
+    _childrenCorners[3][7] =  box.corner(7);
+
+    // Transform the child corners to world space
+    
+    const osg::Matrix& local2world = getMatrix();
+    for(int i=0; i<4; ++i)
+    {
+        VectorPoints& childCorners = _childrenCorners[i];
+         for(int j=0; j<8; ++j)
+         {
+             osg::Vec3& corner = childCorners[j];
+             corner = corner*local2world;
+         }
+    }
+
+    if( _enableDebugNodes )
+    {
+        removeDebugNode();
+        addDebugNode(box);
+    }
+
+    // Update the horizon culler.
+    _horizonCuller.set( _tileKey.getProfile()->getSRS(), getMatrix(), box );
+
+    // need this?
+    dirtyBound();
+}
+
+const osg::Image*
+SurfaceNode::getElevationRaster() const
+{
+    return _drawable->getElevationRaster();
+}
+
+const osg::Matrixf&
+SurfaceNode::getElevationMatrix() const
+{
+    return _drawable->getElevationMatrix();
+};
+
+void
+SurfaceNode::addDebugNode(const osg::BoundingBox& box)
+{
+    _debugText = 0;
+    _debugGeode = makeBBox(box, _tileKey);
+    //_debugGeode = makeSphere(this->getBound());
+    addChild( _debugGeode.get() );
+}
+
+void
+SurfaceNode::removeDebugNode(void)
+{
+    _debugText = 0;
+    if ( _debugGeode.valid() )
+    {
+        removeChild( _debugGeode.get() );
+    }
+}
+
+void
+SurfaceNode::setDebugText(const std::string& strText)
+{
+    if (_debugText.valid()==false)
+    {
+        return;
+    }
+    _debugText->setText(strText);
+}
+
+const osg::BoundingBox&
+SurfaceNode::getAlignedBoundingBox() const
+{
+#if OSG_VERSION_GREATER_OR_EQUAL(3,3,2)
+    return _drawable->getBoundingBox();
+#else
+    return _drawable->getBound();
+#endif
+}
diff --git a/src/osgEarthDrivers/engine_rex/TileDrawable b/src/osgEarthDrivers/engine_rex/TileDrawable
new file mode 100644
index 0000000..e4d8543
--- /dev/null
+++ b/src/osgEarthDrivers/engine_rex/TileDrawable
@@ -0,0 +1,166 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+* Copyright 2008-2014 Pelican Mapping
+* http://osgearth.org
+*
+* osgEarth is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public License
+* along with this program.  If not, see <http://www.gnu.org/licenses/>
+*/
+#ifndef OSGEARTH_DRIVERS_REX_TERRAIN_ENGINE_TILE_DRAWABLE
+#define OSGEARTH_DRIVERS_REX_TERRAIN_ENGINE_TILE_DRAWABLE 1
+
+#include "Common"
+#include "TileNode"
+#include "TileNodeRegistry"
+#include "RenderBindings"
+#include "MPTexture"
+
+#include <osg/Geometry>
+#include <osg/buffered_value>
+#include <osgEarth/Map>
+#include <osgEarth/MapFrame>
+
+using namespace osgEarth;
+
+namespace osgEarth { namespace Drivers { namespace RexTerrainEngine
+{
+    /**
+     * A Geometry that will draw its primitive sets multiple time,
+     * once for each configured "layer". For rendering multipass
+     * data from a single cull.
+     */
+    class TileDrawable : public osg::Drawable
+    {
+    public:
+        // uniform name IDs.
+        unsigned _uidUniformNameID;
+        unsigned _orderUniformNameID;
+        unsigned _opacityUniformNameID;
+        unsigned _texMatrixUniformNameID;
+        unsigned _texMatrixParentUniformNameID;
+        unsigned _texParentExistsUniformNameID;
+        unsigned _minRangeUniformNameID;
+        unsigned _maxRangeUniformNameID;
+
+        // Data stored for each graphics context:
+        struct PerContextData {
+            PerContextData() : birthTime(-1.0f), lastFrame(0) { }
+            float    birthTime;
+            unsigned lastFrame;
+        };
+        mutable osg::buffered_object<PerContextData> _pcd;
+
+        mutable osg::Vec4f _tileMorphCValue;
+        mutable osg::Vec4f _tileGridDimsValue;
+        mutable osg::Vec4f _tileExtentsValue;
+        RenderBindings _bindings;
+
+        bool _supportsGLSL;
+
+        // underlying geometry, possible shared between this tile and other.
+        osg::ref_ptr<osg::Geometry> _geom;
+
+        // tile dimensions
+        int _tileSize;
+
+        bool _drawPatch;
+
+        osg::ref_ptr<MPTexture> _mptex;
+
+        int _textureImageUnit;
+        int _textureParentImageUnit;
+
+        const TileKey _key;
+
+        osg::ref_ptr<const osg::Image> _elevationRaster;
+        osg::Matrixf                   _elevationScaleBias;
+
+        int _skirtSize;
+
+        float* _heightCache;
+
+    public:
+        
+        // construct a new TileDrawable that fronts an osg::Geometry
+        TileDrawable(
+            const TileKey&        key,
+            const RenderBindings& bindings,
+            osg::Geometry*        geometry,
+            int                   tileSize,
+            int                   skirtSize);
+
+        // whether to draw this as a multi-image geometry or as a tesselation patch.
+        void setDrawAsPatches(bool value) { _drawPatch = value; }
+
+        /** Sets the multipass texture to use when rendering geometry. */
+        void setMPTexture(MPTexture* tex) { _mptex = tex; }
+
+    public:
+
+        void drawVertexArraysImplementation(osg::RenderInfo& renderInfo) const;
+
+        void drawPrimitivesImplementation(osg::RenderInfo& renderInfo) const;
+
+        void drawPatches(osg::RenderInfo& renderInfo) const;
+
+        void drawSurface(osg::RenderInfo& renderInfo, bool renderColor) const;
+
+        // validate the geometry is OK.
+        void validate();
+
+        // Sets the elevation raster for this tile
+        void setElevationRaster(const osg::Image* image, const osg::Matrixf& scaleBias);
+        const osg::Image* getElevationRaster() const;
+        const osg::Matrixf& getElevationMatrix() const;
+
+    public: // osg::Geometry overrides
+
+        // override so we can properly release the GL buffer objects
+        // that are not tracked by the Geometry itself but rather are
+        // stored in the LayerRenderData.
+        void releaseGLObjects(osg::State* state) const;
+        void resizeGLObjectBuffers(unsigned maxSize);
+        void compileGLObjects(osg::RenderInfo& renderInfo) const;
+
+        // this is copied mostly from osg::Geometry, but we've removed 
+        // all the code that handles non-fastPath (don't need it) and
+        // called into our custom renderPrimitiveSets method.
+        void drawImplementation(osg::RenderInfo& renderInfo) const;
+
+    public: // osg::Drawable overrides
+
+        // These methods defer functors (like stats collection) to the underlying
+        // (possibly shared) geometry instance.
+        bool supports(const osg::Drawable::AttributeFunctor& f) const { return true; }
+        void accept(osg::Drawable::AttributeFunctor& f) { if ( _geom.valid() ) _geom->accept(f); }
+
+        bool supports(const osg::Drawable::ConstAttributeFunctor& f) const { return true; }
+        void accept(osg::Drawable::ConstAttributeFunctor& f) const { if ( _geom.valid() ) _geom->accept(f); }
+
+        bool supports(const osg::PrimitiveFunctor& f) const { return true; }
+        void accept(osg::PrimitiveFunctor& f) const;
+        
+        /** indexed functor is NOT supported since we need to apply elevation dynamically */
+        bool supports(const osg::PrimitiveIndexFunctor& f) const { return false; }
+
+    public:
+        META_Object(osgEarth, TileDrawable);
+        TileDrawable() : osg::Drawable(){}
+        TileDrawable(const TileDrawable& rhs, const osg::CopyOp& cop) : osg::Drawable(rhs, cop) {}
+
+        virtual ~TileDrawable();
+    };
+
+} } } // namespace osgEarth::Drivers::RexTerrainEngine
+
+#endif // OSGEARTH_DRIVERS_REX_TERRAIN_ENGINE_RexGEOMETRY
diff --git a/src/osgEarthDrivers/engine_rex/TileDrawable.cpp b/src/osgEarthDrivers/engine_rex/TileDrawable.cpp
new file mode 100644
index 0000000..9fd63f5
--- /dev/null
+++ b/src/osgEarthDrivers/engine_rex/TileDrawable.cpp
@@ -0,0 +1,689 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+* Copyright 2008-2014 Pelican Mapping
+* http://osgearth.org
+*
+* osgEarth is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public License
+* along with this program.  If not, see <http://www.gnu.org/licenses/>
+*/
+#include "TileDrawable"
+#include "MPTexture"
+
+#include <osg/Version>
+#include <osgUtil/MeshOptimizers>
+#include <iterator>
+#include <osgEarth/Registry>
+#include <osgEarth/Capabilities>
+#include <osgEarth/ImageUtils>
+
+using namespace osg;
+using namespace osgEarth::Drivers::RexTerrainEngine;
+using namespace osgEarth;
+
+#define LC "[TileDrawable] "
+
+
+static Threading::Mutex _profMutex;
+static unsigned s_frame = 0;
+static unsigned s_draws = 0;
+static unsigned s_functors = 0;
+
+
+TileDrawable::TileDrawable(const TileKey&        key,
+                           const RenderBindings& bindings,
+                           osg::Geometry*        geometry,
+                           int                   tileSize,
+                           int                   skirtSize) :
+osg::Drawable( ),
+_key         ( key ),
+_bindings    ( bindings ),
+_geom        ( geometry ),
+_tileSize    ( tileSize ),
+_drawPatch   ( false ),
+_skirtSize   ( skirtSize )
+{
+    this->setDataVariance( DYNAMIC );
+
+    if (_geom.valid())
+        _geom->setDataVariance( DYNAMIC );
+
+    this->setName( key.str() );
+
+    setUseVertexBufferObjects( true );
+    setUseDisplayList( false );
+
+    _supportsGLSL = Registry::capabilities().supportsGLSL();
+
+    // establish uniform name IDs.
+    _uidUniformNameID             = osg::Uniform::getNameID( "oe_layer_uid" );
+    _orderUniformNameID           = osg::Uniform::getNameID( "oe_layer_order" );
+    _opacityUniformNameID         = osg::Uniform::getNameID( "oe_layer_opacity" );
+    _texMatrixUniformNameID       = osg::Uniform::getNameID( "oe_layer_texMatrix" );
+    _texMatrixParentUniformNameID = osg::Uniform::getNameID( "oe_layer_texParentMatrix" );
+    _texParentExistsUniformNameID = osg::Uniform::getNameID( "oe_layer_texParentExists" );
+    _minRangeUniformNameID        = osg::Uniform::getNameID( "oe_layer_minRange" );
+    _maxRangeUniformNameID        = osg::Uniform::getNameID( "oe_layer_maxRange" );
+
+    _textureImageUnit       = SamplerBinding::findUsage(bindings, SamplerBinding::COLOR)->unit();
+    _textureParentImageUnit = SamplerBinding::findUsage(bindings, SamplerBinding::COLOR_PARENT)->unit();
+    
+    int tileSize2 = tileSize*tileSize;
+    _heightCache = new float[ tileSize2 ];
+    for(int i=0; i<tileSize2; ++i)
+        _heightCache[i] = 0.0f;    
+}
+
+TileDrawable::~TileDrawable()
+{
+    delete [] _heightCache;
+}
+
+void
+TileDrawable::drawPrimitivesImplementation(osg::RenderInfo& renderInfo) const
+{
+    if ( _drawPatch )
+    {
+        drawPatches( renderInfo );
+    }
+    else
+    {
+        const osg::Camera* camera = renderInfo.getCurrentCamera();
+
+        bool renderColor =
+            //(camera->getRenderOrder() != osg::Camera::PRE_RENDER) ||
+            ((camera->getClearMask() & GL_COLOR_BUFFER_BIT) != 0L);
+
+        drawSurface( renderInfo, renderColor );
+    }
+}
+
+
+void
+TileDrawable::drawPatches(osg::RenderInfo& renderInfo) const
+{
+    if  (!_geom.valid() || _geom->getNumPrimitiveSets() < 1 )
+        return;
+
+    osg::State& state = *renderInfo.getState(); 
+    
+    const osg::DrawElementsUShort* de = static_cast<osg::DrawElementsUShort*>(_geom->getPrimitiveSet(0));
+    osg::GLBufferObject* ebo = de->getOrCreateGLBufferObject(state.getContextID());
+    state.bindElementBufferObject(ebo);
+    if (ebo)
+        glDrawElements(GL_PATCHES, de->size()-_skirtSize, GL_UNSIGNED_SHORT, (const GLvoid *)(ebo->getOffset(de->getBufferIndex())));
+    else
+        glDrawElements(GL_PATCHES, de->size()-_skirtSize, GL_UNSIGNED_SHORT, &de->front());
+}
+
+
+void
+TileDrawable::drawSurface(osg::RenderInfo& renderInfo, bool renderColor) const
+{
+    unsigned layersDrawn = 0;
+
+    osg::State& state = *renderInfo.getState();    
+
+    // access the GL extensions interface for the current GC:
+    const osg::Program::PerContextProgram* pcp = 0L;
+
+#if OSG_MIN_VERSION_REQUIRED(3,3,3)
+	osg::ref_ptr<osg::GLExtensions> ext;
+#else
+    osg::ref_ptr<osg::GL2Extensions> ext;
+#endif
+    unsigned contextID;
+
+    if (_supportsGLSL)
+    {
+        contextID = state.getContextID();
+#if OSG_MIN_VERSION_REQUIRED(3,3,3)
+		ext = osg::GLExtensions::Get(contextID, true);
+#else   
+		ext = osg::GL2Extensions::Get( contextID, true );
+#endif
+        pcp = state.getLastAppliedProgramObject();
+    }
+
+    // safely latch
+    if ( !_geom.valid() || _geom->getNumPrimitiveSets() < 1 )
+        return;
+
+    // cannot store these in the object since there could be multiple GCs (and multiple
+    // PerContextPrograms) at large
+    GLint opacityLocation            = -1;
+    GLint uidLocation                = -1;
+    GLint orderLocation              = -1;
+    GLint texMatrixLocation          = -1;
+    GLint texMatrixParentLocation    = -1;
+    GLint texParentExistsLocation    = -1;
+    GLint minRangeLocation           = -1;
+    GLint maxRangeLocation           = -1;
+
+    // The PCP can change (especially in a VirtualProgram environment). So we do need to
+    // requery the uni locations each time unfortunately. TODO: explore optimizations.
+    if ( pcp )
+    {
+        opacityLocation             = pcp->getUniformLocation( _opacityUniformNameID );
+        uidLocation                 = pcp->getUniformLocation( _uidUniformNameID );
+        orderLocation               = pcp->getUniformLocation( _orderUniformNameID );
+        texMatrixLocation           = pcp->getUniformLocation( _texMatrixUniformNameID );
+        texMatrixParentLocation     = pcp->getUniformLocation( _texMatrixParentUniformNameID );
+        texParentExistsLocation     = pcp->getUniformLocation( _texParentExistsUniformNameID );
+        minRangeLocation            = pcp->getUniformLocation( _minRangeUniformNameID );
+        maxRangeLocation            = pcp->getUniformLocation( _maxRangeUniformNameID );
+    }
+
+    float prevOpacity = -1.0f;
+    if ( renderColor && _mptex.valid() && !_mptex->getPasses().empty() )
+    {
+        float prevOpacity = -1.0f;
+
+        // in FFP mode, we need to enable the GL mode for texturing:
+        if ( !pcp )
+            state.applyMode(GL_TEXTURE_2D, true);
+
+        optional<bool> texParentExists_lastValue;
+
+        for(MPTexture::Passes::const_iterator p = _mptex->getPasses().begin();
+            p != _mptex->getPasses().end();
+            ++p)
+        {
+            const MPTexture::Pass& pass = *p;
+
+            if ( pass._layer->getVisible() && pass._layer->getOpacity() > 0.1 )
+            {
+                // Apply the texture.
+                state.setActiveTextureUnit( _textureImageUnit );
+                const osg::StateAttribute* lastTex = state.getLastAppliedTextureAttribute(_textureImageUnit, osg::StateAttribute::TEXTURE);
+                if ( lastTex != pass._texture.get() )
+                    pass._texture->apply( state );
+
+                // Apply the texture matrix.
+                ext->glUniformMatrix4fv( texMatrixLocation, 1, GL_FALSE, pass._textureMatrix.ptr() );
+
+                bool texParentExists = pass._parentTexture.valid();
+                if ( texParentExists )
+                {
+                    // Apply the parent texture.
+                    state.setActiveTextureUnit( _textureParentImageUnit );
+                    const osg::StateAttribute* lastTex = state.getLastAppliedTextureAttribute(_textureParentImageUnit, osg::StateAttribute::TEXTURE);
+                    if ( lastTex != pass._parentTexture.get() )
+                        pass._parentTexture->apply( state );
+
+                    // Apply the parent texture matrix.
+                    ext->glUniformMatrix4fv( texMatrixParentLocation, 1, GL_FALSE, pass._parentTextureMatrix.ptr() );
+                }
+
+                if ( !texParentExists_lastValue.isSetTo(texParentExists) )
+                {
+                    texParentExists_lastValue = texParentExists;
+                    ext->glUniform1f( texParentExistsLocation, texParentExists? 1.0f : 0.0f );
+                }
+
+                // Order uniform (TODO: evaluate whether we still need this)
+                if ( orderLocation >= 0 )
+                {
+                    ext->glUniform1i( orderLocation, (GLint)layersDrawn );
+                }
+
+                // assign the layer UID:
+                if ( uidLocation >= 0 )
+                {
+                    ext->glUniform1i( uidLocation, (GLint)pass._layer->getUID() );
+                }
+
+                // apply opacity:
+                if ( opacityLocation >= 0 )
+                {
+                    float opacity = pass._layer->getOpacity();
+                    if ( opacity != prevOpacity )
+                    {
+                        ext->glUniform1f( opacityLocation, (GLfloat)opacity );
+                        prevOpacity = opacity;
+                    }
+                }         
+
+                // Apply the min/max range
+                float minRange = pass._layer->getImageLayerOptions().minVisibleRange().getOrUse(0.0);
+                float maxRange = pass._layer->getImageLayerOptions().maxVisibleRange().getOrUse(-1.0);
+                ext->glUniform1f( minRangeLocation, minRange );
+                ext->glUniform1f( maxRangeLocation, maxRange );
+
+                for (unsigned i=0; i < _geom->getNumPrimitiveSets(); i++)
+                    _geom->getPrimitiveSet(i)->draw(state, true);
+
+                ++layersDrawn;
+            }
+        }
+    }
+
+    // No mptex or no layers in the mptex? Draw simple.
+    if ( layersDrawn == 0 )
+    {
+        if ( opacityLocation >= 0 )
+            ext->glUniform1f( opacityLocation, (GLfloat)1.0f );
+
+        if ( uidLocation >= 0 )
+            ext->glUniform1i( uidLocation, (GLint)-1 );
+
+        if ( orderLocation >= 0 )
+            ext->glUniform1i( orderLocation, (GLint)0 );
+
+        if ( renderColor )
+        {
+            for (unsigned i=0; i < _geom->getNumPrimitiveSets(); i++)
+            {
+                _geom->getPrimitiveSet(i)->draw(state, true);
+            }
+        }
+        else
+        {
+            // draw the surface w/o the skirt:
+            const osg::DrawElementsUShort* de = static_cast<osg::DrawElementsUShort*>(_geom->getPrimitiveSet(0));
+            osg::GLBufferObject* ebo = de->getOrCreateGLBufferObject(state.getContextID());
+            state.bindElementBufferObject(ebo);
+            glDrawElements(GL_TRIANGLES, de->size()-_skirtSize, GL_UNSIGNED_SHORT, (const GLvoid *)(ebo->getOffset(de->getBufferIndex())));
+        
+            // draw the remaining primsets normally
+            for (unsigned i=1; i < _geom->getNumPrimitiveSets(); i++)
+            {
+                _geom->getPrimitiveSet(i)->draw(state, true);
+            }
+        }
+    }
+
+}
+
+void
+TileDrawable::setElevationRaster(const osg::Image*   image,
+                                 const osg::Matrixf& scaleBias)
+{
+    _elevationRaster = image;
+    _elevationScaleBias = scaleBias;
+
+    if (osg::equivalent(0.0f, _elevationScaleBias(0,0)) ||
+        osg::equivalent(0.0f, _elevationScaleBias(1,1)))
+    {
+        OE_WARN << "("<<_key.str()<<") precision error\n";
+    }
+
+    if ( _elevationRaster.valid() )
+    {
+        const osg::Vec3Array& verts   = *static_cast<osg::Vec3Array*>(_geom->getVertexArray());
+        const osg::Vec3Array& normals = *static_cast<osg::Vec3Array*>(_geom->getNormalArray());
+
+        //OE_INFO << LC << _key.str() << " - rebuilding height cache" << std::endl;
+
+        ImageUtils::PixelReader elevation(_elevationRaster.get());
+        elevation.setBilinear(true);
+
+        float
+            scaleU = _elevationScaleBias(0,0),
+            scaleV = _elevationScaleBias(1,1),
+            biasU  = _elevationScaleBias(3,0),
+            biasV  = _elevationScaleBias(3,1);
+
+        if ( osg::equivalent(scaleU, 0.0f) || osg::equivalent(scaleV, 0.0f) )
+        {
+            OE_WARN << LC << "Precision loss in tile " << _key.str() << "\n";
+        }
+    
+        for(int t=0; t<_tileSize; ++t)
+        {
+            float v = (float)t / (float)(_tileSize-1);
+            v = v*scaleV + biasV;
+
+            for(int s=0; s<_tileSize; ++s)
+            {
+                float u = (float)s / (float)(_tileSize-1);
+                u = u*scaleU + biasU;
+                _heightCache[t*_tileSize+s] = elevation(u, v).r();
+            }
+        }
+    }
+
+    dirtyBound();
+}
+
+const osg::Image*
+TileDrawable::getElevationRaster() const
+{
+    return _elevationRaster.get();
+}
+
+const osg::Matrixf&
+TileDrawable::getElevationMatrix() const
+{
+    return _elevationScaleBias;
+}
+
+// Functor supplies triangles to things like IntersectionVisitor, ComputeBoundsVisitor, etc.
+void
+TileDrawable::accept(osg::PrimitiveFunctor& f) const
+{
+    const osg::Vec3Array& verts   = *static_cast<osg::Vec3Array*>(_geom->getVertexArray());
+    const osg::Vec3Array& normals = *static_cast<osg::Vec3Array*>(_geom->getNormalArray());
+        
+#if 1 // triangles (OSG-stats-friendly)
+
+    //TODO: improve by caching the entire Vec3f, not just the height.
+
+    f.begin(GL_TRIANGLES);
+    for(int t=0; t<_tileSize-1; ++t)
+    {
+        for(int s=0; s<_tileSize-1; ++s)
+        {
+            int i00 = t*_tileSize + s;
+            int i10 = i00 + 1;
+            int i01 = i00 + _tileSize;
+            int i11 = i01 + 1;
+            
+            osg::Vec3d v01 = verts[i01] + normals[i01] * _heightCache[i01];
+            osg::Vec3d v10 = verts[i10] + normals[i10] * _heightCache[i10];
+
+            f.vertex( verts[i00] + normals[i00] * _heightCache[i00] );
+            f.vertex( v01 );
+            f.vertex( v10 );
+            
+            f.vertex( v10 );
+            f.vertex( v01 );
+            f.vertex( verts[i11] + normals[i11] * _heightCache[i11] );
+        }
+    }
+    f.end();
+
+#else
+    // triangle-strips (faster? but not stats-friendly; will cause the OSG stats
+    // to report _tileSize-1 primitive sets per TileDrawable even though there
+    // is only one.
+
+    for(int t=0; t<_tileSize-1; ++t)
+    {
+        f.begin( GL_TRIANGLE_STRIP );
+
+        for(int s=0; s<_tileSize; ++s)
+        {
+            int i = t*_tileSize + s;
+            f.vertex( verts[i] + normals[i] * _heightCache[i] );
+
+            i += _tileSize;
+            f.vertex( verts[i] + normals[i] * _heightCache[i] );
+        }
+
+        f.end();
+    }
+
+#endif
+}
+
+void 
+TileDrawable::releaseGLObjects(osg::State* state) const
+{
+    osg::Drawable::releaseGLObjects( state );
+
+    if ( _geom.valid() )
+    {
+        _geom->releaseGLObjects( state );
+    }
+}
+
+
+void
+TileDrawable::resizeGLObjectBuffers(unsigned maxSize)
+{
+    osg::Drawable::resizeGLObjectBuffers( maxSize );
+
+    if ( _geom.valid() )
+    {
+        _geom->resizeGLObjectBuffers( maxSize );
+    }
+
+    if ( _pcd.size() < maxSize )
+    {
+        _pcd.resize(maxSize);
+    }
+}
+
+
+void 
+TileDrawable::compileGLObjects(osg::RenderInfo& renderInfo) const
+{
+    osg::Drawable::compileGLObjects( renderInfo );
+
+    if ( _geom.valid() )
+    {
+        _geom->compileGLObjects( renderInfo );
+    }
+
+    // unbind the BufferObjects
+    //extensions->glBindBuffer(GL_ARRAY_BUFFER_ARB,0);
+    //extensions->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER_ARB,0);
+}
+
+
+#if OSG_VERSION_GREATER_OR_EQUAL(3,1,8)
+#   define GET_ARRAY(a) (a)
+#else
+#   define GET_ARRAY(a) (a).array
+#endif
+
+
+void
+TileDrawable::drawImplementation(osg::RenderInfo& renderInfo) const
+{
+    State& state = *renderInfo.getState();
+    //bool checkForGLErrors = state.getCheckForGLErrors() == osg::State::ONCE_PER_ATTRIBUTE;
+    //if ( checkForGLErrors ) state.checkGLErrors("start of TileDrawable::drawImplementation()");
+
+#if 0
+    const osg::FrameStamp* fs = state.getFrameStamp();
+    if ( fs )
+    {
+        Threading::ScopedMutexLock lock(_profMutex);
+        if ( s_frame != fs->getFrameNumber() )
+        {
+            OE_NOTICE << "Frame " << s_frame << " : draws = " << s_draws << ", functors = " << s_functors << std::endl;
+            s_draws = 0;
+            s_functors = 0;
+            s_frame = fs->getFrameNumber();
+        }
+        s_draws++;
+    }
+#endif
+
+
+#if OSG_MIN_VERSION_REQUIRED(3,3,1)
+    _geom->drawVertexArraysImplementation( renderInfo );
+#else
+    drawVertexArraysImplementation( renderInfo );
+#endif
+
+    drawPrimitivesImplementation( renderInfo );
+
+    //if ( checkForGLErrors ) state.checkGLErrors("end of TileDrawable::drawImplementation()");
+    
+    // unbind the VBO's if any are used.
+    state.unbindVertexBufferObject();
+    state.unbindElementBufferObject();
+}
+
+
+#if OSG_MIN_VERSION_REQUIRED(3,1,8)
+void
+TileDrawable::drawVertexArraysImplementation(osg::RenderInfo& renderInfo) const
+{
+    if ( !_geom.valid() )
+        return;
+
+    State& state = *renderInfo.getState();
+
+    bool handleVertexAttributes = !_geom->getVertexAttribArrayList().empty();
+
+    ArrayDispatchers& arrayDispatchers = state.getArrayDispatchers();
+
+    arrayDispatchers.reset();
+    arrayDispatchers.setUseVertexAttribAlias(state.getUseVertexAttributeAliasing());
+
+    arrayDispatchers.activateNormalArray(_geom->getNormalArray());
+    //arrayDispatchers.activateColorArray(_geom->getColorArray());
+    //arrayDispatchers.activateSecondaryColorArray(_geom->getSecondaryColorArray());
+    //arrayDispatchers.activateFogCoordArray(_geom->getFogCoordArray());
+
+    if (handleVertexAttributes)
+    {
+        for(unsigned int unit=0;unit<_geom->getVertexAttribArrayList().size();++unit)
+        {
+            arrayDispatchers.activateVertexAttribArray(unit, _geom->getVertexAttribArray(unit));
+        }
+    }
+
+    // dispatch any attributes that are bound overall
+    arrayDispatchers.dispatch(osg::Array::BIND_OVERALL,0);
+
+    state.lazyDisablingOfVertexAttributes();
+
+    // set up arrays
+    if( _geom->getVertexArray() )
+        state.setVertexPointer(_geom->getVertexArray());
+
+    if (_geom->getNormalArray() && _geom->getNormalArray()->getBinding()==osg::Array::BIND_PER_VERTEX)
+        state.setNormalPointer(_geom->getNormalArray());
+
+    //if (_geom->getColorArray() && _geom->getColorArray()->getBinding()==osg::Array::BIND_PER_VERTEX)
+    //    state.setColorPointer(_geom->getColorArray());
+
+    //if (_geom->getSecondaryColorArray() && _geom->getSecondaryColorArray()->getBinding()==osg::Array::BIND_PER_VERTEX)
+    //    state.setSecondaryColorPointer(_geom->getSecondaryColorArray());
+
+    //if (_geom->getFogCoordArray() && _geom->getFogCoordArray()->getBinding()==osg::Array::BIND_PER_VERTEX)
+    //    state.setFogCoordPointer(_geom->getFogCoordArray());
+
+    for(unsigned int unit=0;unit<_geom->getTexCoordArrayList().size();++unit)
+    {
+        const Array* array = _geom->getTexCoordArray(unit);
+        if (array)
+        {
+            state.setTexCoordPointer(unit,array);
+        }
+    }
+
+    if ( handleVertexAttributes )
+    {
+        for(unsigned int index = 0; index < _geom->getVertexAttribArrayList().size(); ++index)
+        {
+            const Array* array = _geom->getVertexAttribArray(index);
+            if (array && array->getBinding()==osg::Array::BIND_PER_VERTEX)
+            {
+                if (array->getPreserveDataType())
+                {
+                    GLenum dataType = array->getDataType();
+                    if (dataType==GL_FLOAT) state.setVertexAttribPointer( index, array );
+                    else if (dataType==GL_DOUBLE) state.setVertexAttribLPointer( index, array );
+                    else state.setVertexAttribIPointer( index, array );
+                }
+                else
+                {
+                    state.setVertexAttribPointer( index, array );
+                }
+            }
+        }
+    }
+    
+    state.applyDisablingOfVertexAttributes();
+}
+
+#else
+
+void
+TileDrawable::drawVertexArraysImplementation(osg::RenderInfo& renderInfo) const
+{
+    State& state = *renderInfo.getState();
+    bool handleVertexAttributes = !_geom->getVertexAttribArrayList().empty();
+    //bool handleVertexAttributes = !_vertexAttribList.empty();
+
+    ArrayDispatchers& arrayDispatchers = state.getArrayDispatchers();
+
+    arrayDispatchers.reset();
+    arrayDispatchers.setUseVertexAttribAlias(state.getUseVertexAttributeAliasing());
+    arrayDispatchers.setUseGLBeginEndAdapter(false);
+
+    arrayDispatchers.activateNormalArray(_geom->getNormalBinding(), _geom->getNormalArray(), _geom->getNormalIndices());
+    arrayDispatchers.activateColorArray(_geom->getColorBinding(), _geom->getColorArray(), _geom->getColorIndices());
+    arrayDispatchers.activateSecondaryColorArray(_geom->getSecondaryColorBinding(), _geom->getSecondaryColorArray(), _geom->getSecondaryColorIndices());
+    arrayDispatchers.activateFogCoordArray(_geom->getFogCoordBinding(), _geom->getFogCoordArray(), _geom->getFogCoordIndices());
+
+    if (handleVertexAttributes)
+    {
+        for(unsigned int unit=0;unit < _geom->getVertexAttribArrayList().size();++unit)
+        {
+            const osg::Geometry::ArrayData& val = _geom->getVertexAttribArrayList()[unit];
+            arrayDispatchers.activateVertexAttribArray(val.binding, unit, val.array.get(), val.indices.get());
+        }
+    }
+
+    // dispatch any attributes that are bound overall
+    arrayDispatchers.dispatch(_geom->BIND_OVERALL, 0);
+
+    state.lazyDisablingOfVertexAttributes();
+
+    // set up arrays
+    if( _geom->getVertexArray() )
+        state.setVertexPointer(_geom->getVertexArray()); //_vertexData.array.get());
+
+    if (_geom->getNormalBinding()==_geom->BIND_PER_VERTEX && _geom->getNormalArray())
+        state.setNormalPointer(_geom->getNormalArray());
+
+    if (_geom->getColorBinding()==_geom->BIND_PER_VERTEX && _geom->getColorArray())
+        state.setColorPointer(_geom->getColorArray());
+
+    if (_geom->getSecondaryColorBinding()==_geom->BIND_PER_VERTEX && _geom->getSecondaryColorArray())
+        state.setSecondaryColorPointer(_geom->getSecondaryColorArray());
+
+    if (_geom->getFogCoordBinding()==_geom->BIND_PER_VERTEX && _geom->getFogCoordArray())
+        state.setFogCoordPointer(_geom->getFogCoordArray());
+    
+    for(unsigned int unit=0;unit<_geom->getTexCoordArrayList().size();++unit)
+    {
+        const Array* array = _geom->getTexCoordArray(unit);
+        if (array)
+        {
+            state.setTexCoordPointer(unit,array);
+        }
+    }
+    
+    if ( handleVertexAttributes )
+    {
+        for(unsigned int index = 0; index < _geom->getVertexAttribArrayList().size(); ++index)
+        {
+            const osg::Array* array = _geom->getVertexAttribArray(index);
+            if ( array && _geom->getVertexAttribBinding(index) == _geom->BIND_PER_VERTEX )
+            {
+                if (array->getPreserveDataType())
+                {
+                    GLenum dataType = array->getDataType();
+                    if (dataType==GL_FLOAT) state.setVertexAttribPointer( index, array, GL_FALSE );
+                    else if (dataType==GL_DOUBLE) state.setVertexAttribLPointer( index, array );
+                    else state.setVertexAttribIPointer( index, array );
+                }
+                else
+                {
+                    state.setVertexAttribPointer( index, array, GL_FALSE );
+                }
+            }
+        }
+    }
+
+    state.applyDisablingOfVertexAttributes();
+}
+
+#endif
diff --git a/src/osgEarthDrivers/engine_rex/TileNode b/src/osgEarthDrivers/engine_rex/TileNode
new file mode 100644
index 0000000..26efb51
--- /dev/null
+++ b/src/osgEarthDrivers/engine_rex/TileNode
@@ -0,0 +1,175 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+* Copyright 2008-2014 Pelican Mapping
+* http://osgearth.org
+*
+* osgEarth is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public License
+* along with this program.  If not, see <http://www.gnu.org/licenses/>
+*/
+#ifndef OSGEARTH_DRIVERS_REX_TERRAIN_ENGINE_TILE_NODE
+#define OSGEARTH_DRIVERS_REX_TERRAIN_ENGINE_TILE_NODE 1
+
+#include "Common"
+#include "RenderBindings"
+#include "Loader"
+#include "MaskGenerator"
+#include "MPTexture"
+#include "ProxySurfaceNode"
+
+#include <OpenThreads/Atomic>
+#include <osgEarth/TerrainTileNode>
+#include <vector>
+
+namespace osg {
+    class CullStack;
+}
+namespace osgUtil {
+    class CullVisitor;
+}
+
+namespace osgEarth { namespace Drivers { namespace RexTerrainEngine
+{
+    class EngineContext;
+    class SurfaceNode;
+    class ProxySurfaceNode;
+    class SelectionInfo;
+
+    /**
+     * TileNode represents a single tile. TileNode has 5 children:
+     * one SurfaceNode that renders the actual tile content under a MatrixTransform;
+     * and four TileNodes representing the LOD+1 quadtree tiles under this tile.
+     */
+    class TileNode : public osg::Group
+    {
+    public:
+        TileNode();
+
+        /** TileKey of the key representing the data in this node. */
+        const TileKey& getTileKey() const { return _key; }
+
+        /** Sets the map revision that this tile should be using. */
+        void setMapRevision(Revision rev) { } // nyi - check for need
+
+        /** Tells this tile that it needs to request data. */
+        void setDirty(bool value);
+
+        /** Creates the geometry and state for this tilenode. */
+        void create(const TileKey& key, EngineContext* context);
+
+        /** Whether this node has enough data to traverse. */
+        bool isReadyToTraverse() const;
+
+        /** Whether the tile is expired; i.e. has not been visited in some time. */
+        bool isDormant(const osg::FrameStamp*) const;
+
+        /** Whether all the subtiles are this tile are dormant (have not been visited recently) */
+        bool areSubTilesDormant(const osg::FrameStamp*) const;
+
+        /** Removed any sub tiles from the scene graph. Please call from a safe thread only (update) */
+        void removeSubTiles();
+
+        /** Whether the tile drawables are visible */
+        bool isVisible(osg::CullStack* cs) const;
+
+        /** Load (or continue loading) content for the tiles in this quad. */
+        void load(osg::NodeVisitor& nv);
+
+        /** Notifies this tile that another tile has come into existence. */
+        void notifyOfArrival(TileNode* that) { } // nyi - todo
+
+        /** Set inheritance matrices as necessary. Return true is changed were made. */
+        bool inheritState(EngineContext* context);
+
+        /** Returns the tile's parent; convenience function */
+        TileNode* getParentTile() { return dynamic_cast<TileNode*>(getParent(0)); }
+        
+        /** merge in new stuff from a state set. */
+        void mergeStateSet(osg::StateSet* stateSet, MPTexture* mptex, const RenderBindings& bindings);
+
+        /** Access to the multipass texture attribute */
+        MPTexture* getMPTexture() const { return _mptex.get(); }
+
+        /** Elevation data for this node along with its scale/bias matrix; needed for bounding box */
+        void setElevationRaster(const osg::Image* image, const osg::Matrixf& matrix);
+        const osg::Image* getElevationRaster() const;
+        const osg::Matrixf& getElevationMatrix() const;
+
+        // access to subtiles
+        TileNode* getSubTile(unsigned i) { return static_cast<TileNode*>(_children[i].get()); }
+        const TileNode* getSubTile(unsigned i) const { return static_cast<TileNode*>(_children[i].get()); }
+
+        double getMinimumExpiryTime() const { return _minExpiryTime; }
+        void setMinimumExpiryTime(double minExpiryTime) { _minExpiryTime = minExpiryTime; }
+        
+        unsigned int getMinimumExpiryFrames() const { return _minExpiryFrames; }
+        void setMinimumExpiryFrames(unsigned int minExpiryFrames) { _minExpiryFrames = minExpiryFrames; }
+
+
+    public: // osg::Node
+
+        osg::BoundingSphere computeBound() const;
+
+        void traverse(osg::NodeVisitor& nv);
+
+        void releaseGLObjects(osg::State* state) const;
+
+    protected:
+        TileKey                            _key;
+        osg::ref_ptr<SurfaceNode>          _surface;
+        osg::ref_ptr<SurfaceNode>          _patch;
+        osg::ref_ptr<Loader::Request>      _loadRequest;
+        osg::ref_ptr<Loader::Request>      _expireRequest;
+        Threading::Mutex                   _mutex;
+        bool                               _dirty;
+        OpenThreads::Atomic                _lastTraversalFrame;
+        double                             _lastTraversalTime;
+        OpenThreads::Atomic                _lastAcceptSurfaceFrame;
+        unsigned                           _count;
+        osg::ref_ptr<MPTexture>            _mptex;
+        osg::ref_ptr<osg::StateSet>        _payloadStateSet;
+        bool                               _childrenReady;
+        unsigned int                       _minExpiryFrames;
+        double                             _minExpiryTime;
+
+    private:
+
+        void createChildren(EngineContext* context);
+
+        /** Returns false if the Surface node fails visiblity test */
+        bool cull(osgUtil::CullVisitor* cv);
+
+        bool accept_cull(osgUtil::CullVisitor* cv);
+
+        bool cull_stealth(osgUtil::CullVisitor* cv);
+
+        bool accept_cull_stealth(osgUtil::CullVisitor* cv);
+
+        // returns true if any surface geometry was added (visible).
+        bool acceptSurface(osgUtil::CullVisitor* nv, EngineContext*);
+
+        bool shouldSubDivide(osgUtil::CullVisitor* cv, const SelectionInfo& selectionInfo);
+
+        void createPayloadStateSet(EngineContext*);
+
+        void updateTileUniforms(const SelectionInfo& selectionInfo);
+
+        osg::ref_ptr<osg::Uniform> _tileKeyUniform;
+        osg::ref_ptr<osg::Uniform> _tileMorphUniform;
+        osg::ref_ptr<osg::Uniform> _tileGridDimsUniform;
+    };
+
+    typedef std::vector< osg::ref_ptr<TileNode> > TileNodeVector;
+
+} } } // namespace osgEarth::Drivers::RexTerrainEngine
+
+#endif // OSGEARTH_DRIVERS_REX_TERRAIN_ENGINE_TILE_NODE
diff --git a/src/osgEarthDrivers/engine_rex/TileNode.cpp b/src/osgEarthDrivers/engine_rex/TileNode.cpp
new file mode 100644
index 0000000..f38376b
--- /dev/null
+++ b/src/osgEarthDrivers/engine_rex/TileNode.cpp
@@ -0,0 +1,732 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+* Copyright 2008-2014 Pelican Mapping
+* http://osgearth.org
+*
+* osgEarth is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public License
+* along with this program.  If not, see <http://www.gnu.org/licenses/>
+*/
+#include "TileNode"
+#include "SurfaceNode"
+#include "ProxySurfaceNode"
+#include "EngineContext"
+#include "Loader"
+#include "LoadTileData"
+#include "SelectionInfo"
+#include "ElevationTextureUtils"
+
+#include <osgEarth/CullingUtils>
+#include <osgEarth/ImageUtils>
+#include <osgEarth/TraversalData>
+#include <osgEarth/Shadowing>
+#include <osgEarth/Utils>
+#include <osgEarth/TraversalData>
+
+#include <osg/Uniform>
+#include <osg/ComputeBoundsVisitor>
+#include <osg/ValueObject>
+
+using namespace osgEarth::Drivers::RexTerrainEngine;
+using namespace osgEarth;
+
+#define OSGEARTH_TILE_NODE_PROXY_GEOMETRY_DEBUG 0
+
+// Whether to check the child nodes for culling before traversing them.
+// This could prevent premature Loader requests, but it increases cull time.
+//#define VISIBILITY_PRECHECK
+
+#define LC "[TileNode] "
+
+#define REPORT(name,timer) if(context->progress()) { \
+    context->progress()->stats()[name] += OE_GET_TIMER(timer); }
+
+namespace
+{
+    // Scale and bias matrices, one for each TileKey quadrant.
+    const osg::Matrixf scaleBias[4] =
+    {
+        osg::Matrixf(0.5f,0,0,0, 0,0.5f,0,0, 0,0,1.0f,0, 0.0f,0.5f,0,1.0f),
+        osg::Matrixf(0.5f,0,0,0, 0,0.5f,0,0, 0,0,1.0f,0, 0.5f,0.5f,0,1.0f),
+        osg::Matrixf(0.5f,0,0,0, 0,0.5f,0,0, 0,0,1.0f,0, 0.0f,0.0f,0,1.0f),
+        osg::Matrixf(0.5f,0,0,0, 0,0.5f,0,0, 0,0,1.0f,0, 0.5f,0.0f,0,1.0f)
+    };
+}
+
+TileNode::TileNode() : 
+_dirty        ( false ),
+_childrenReady( false ),
+_minExpiryTime( 0.0 ),
+_minExpiryFrames( 0 ),
+_lastTraversalTime(0.0),
+_lastTraversalFrame(0.0)
+{
+    osg::StateSet* stateSet = getOrCreateStateSet();
+
+    // The StateSet must have a dynamic data variance since we plan to alter it
+    // as new data becomes available.
+    stateSet->setDataVariance(osg::Object::DYNAMIC);
+
+    _count = 0;
+}
+
+void
+TileNode::create(const TileKey& key, EngineContext* context)
+{
+    if (!context)
+        return;
+
+    _key = key;
+
+    // Create mask records
+    osg::ref_ptr<MaskGenerator> masks = new MaskGenerator(key, context->getOptions().tileSize().get(), context->getMapFrame());
+
+    // Get a shared geometry from the pool that corresponds to this tile key:
+    osg::ref_ptr<osg::Geometry> geom;
+    context->getGeometryPool()->getPooledGeometry(key, context->getMapFrame().getMapInfo(), geom, masks.get());
+
+
+    // Create the drawable for the terrain surface:
+    TileDrawable* surfaceDrawable = new TileDrawable(
+        key, 
+        context->getRenderBindings(), 
+        geom.get(),
+        context->getOptions().tileSize().get(),
+        context->getGeometryPool()->getNumSkirtElements() );
+
+    surfaceDrawable->setDrawAsPatches(false);
+
+    // Create the node to house the tile drawable:
+    _surface = new SurfaceNode(
+        key,
+        context->getMapFrame().getMapInfo(),
+        context->getRenderBindings(),
+        surfaceDrawable );
+
+    // Create a drawable for "patch" geometry, which is rendered as GL patches, not triangles.
+    // Patch geometry can be used to place land cover or render other tile-specific data.
+    TileDrawable* patchDrawable = new TileDrawable(
+        key, 
+        context->getRenderBindings(),
+        geom.get(),
+        context->getOptions().tileSize().get(),
+        context->getGeometryPool()->getNumSkirtElements() );
+    
+    patchDrawable->setDrawAsPatches(true);
+
+    // And a node to house that as well:
+    _patch = new SurfaceNode(
+        key,
+        context->getMapFrame().getMapInfo(),
+        context->getRenderBindings(),
+        patchDrawable );
+
+    // initialize all the per-tile uniforms the shaders will need:
+    createPayloadStateSet(context);
+
+    updateTileUniforms(context->getSelectionInfo());
+
+    // Set up a data container for multipass layer rendering:
+    _mptex = new MPTexture();
+    surfaceDrawable->setMPTexture( _mptex.get() );
+
+    // need to recompute the bounds after adding payload:
+    dirtyBound();
+
+    // signal the tile to start loading data:
+    setDirty( true );
+
+    // register me.
+    context->liveTiles()->add( this );
+}
+
+osg::BoundingSphere
+TileNode::computeBound() const
+{
+    return _surface.valid() ? _surface->computeBound() : osg::BoundingSphere();
+}
+
+bool
+TileNode::isDormant(const osg::FrameStamp* fs) const
+{
+    const unsigned minMinExpiryFrames = 3u;
+
+    bool dormant = 
+           fs &&
+           fs->getFrameNumber() - _lastTraversalFrame > std::max(_minExpiryFrames, minMinExpiryFrames) &&
+           fs->getReferenceTime() - _lastTraversalTime > _minExpiryTime;
+    return dormant;
+}
+
+void
+TileNode::setElevationRaster(const osg::Image* image, const osg::Matrixf& matrix)
+{
+    if ( _surface.valid() )
+        _surface->setElevationRaster( image, matrix );
+
+    if ( _patch.valid() )
+        _patch->setElevationRaster( image, matrix );
+}
+
+const osg::Image*
+TileNode::getElevationRaster() const
+{
+    return _surface->getElevationRaster();
+}
+
+const osg::Matrixf&
+TileNode::getElevationMatrix() const
+{
+    return _surface->getElevationMatrix();
+}
+
+void
+TileNode::createPayloadStateSet(EngineContext* context)
+{
+    _payloadStateSet = new osg::StateSet();
+
+    // Install the tile key uniform.
+    _tileKeyUniform = new osg::Uniform("oe_tile_key", osg::Vec4f(0,0,0,0));
+    _payloadStateSet->addUniform( _tileKeyUniform.get() );
+
+    _tileMorphUniform = new osg::Uniform("oe_tile_morph", osg::Vec2f(0,0));
+    _payloadStateSet->addUniform( _tileMorphUniform.get() );
+}
+
+void
+TileNode::updateTileUniforms(const SelectionInfo& selectionInfo)
+{
+    //assert(_surface.valid());
+    // update the tile key uniform
+    const osg::BoundingBox& bbox = _surface->getAlignedBoundingBox();
+    float width = std::max( (bbox.xMax()-bbox.xMin()), (bbox.yMax()-bbox.yMin()) );
+
+    unsigned tw, th;
+    _key.getProfile()->getNumTiles(_key.getLOD(), tw, th);
+
+    _tileKeyUniform->set(osg::Vec4f(_key.getTileX(), th-_key.getTileY()-1.0f, _key.getLOD(), width));
+
+    // update the morph constants
+
+    float start = (float)selectionInfo.visParameters(_key.getLOD())._fMorphStart;
+    float end   = (float)selectionInfo.visParameters(_key.getLOD())._fMorphEnd;
+
+    float one_by_end_minus_start = end - start;
+    one_by_end_minus_start = 1.0f/one_by_end_minus_start;
+    osg::Vec2f morphConstants( end * one_by_end_minus_start, one_by_end_minus_start );
+    _tileMorphUniform->set( morphConstants );
+
+    const osg::Image* er = getElevationRaster();
+    if ( er )
+    {
+        // pre-calculate texel-sampling scale and bias coefficients that allow us to sample
+        // elevation textures on texel-center instead of edge:
+        float size = (float)er->s();
+        osg::Vec2f elevTexelOffsets( (size-1.0f)/size, 0.5/size );
+        getOrCreateStateSet()->getOrCreateUniform("oe_tile_elevTexelCoeff", osg::Uniform::FLOAT_VEC2)->set(elevTexelOffsets);
+    }
+}
+
+bool
+TileNode::isReadyToTraverse() const
+{
+    // Later, we might replace this if the tile isn't immediately created at cull time.
+    return true;
+}
+
+void
+TileNode::setDirty(bool value)
+{
+    _dirty = value;
+}
+
+void
+TileNode::releaseGLObjects(osg::State* state) const
+{
+    OE_DEBUG << LC << "Tile " << _key.str() << " : Release GL objects\n";
+
+    if ( getStateSet() )
+        getStateSet()->releaseGLObjects(state);
+    if ( _payloadStateSet.valid() )
+        _payloadStateSet->releaseGLObjects(state);
+    if ( _surface.valid() )
+        _surface->releaseGLObjects(state);
+    if ( _patch.valid() )
+        _patch->releaseGLObjects(state);
+    if ( _mptex.valid() )
+        _mptex->releaseGLObjects(state);
+
+    osg::Group::releaseGLObjects(state);
+}
+
+bool
+TileNode::shouldSubDivide(osgUtil::CullVisitor* cv, const SelectionInfo& selectionInfo)
+{
+    unsigned currLOD = _key.getLOD();
+    if (currLOD < selectionInfo.numLods() && currLOD != selectionInfo.numLods()-1)
+    {
+        return _surface->anyChildBoxIntersectsSphere(
+            cv->getViewPointLocal(), 
+            (float)selectionInfo.visParameters(currLOD+1)._visibilityRange2,
+            cv->getLODScale());
+    }
+    return false;
+}
+
+
+bool
+TileNode::isVisible(osg::CullStack* stack) const
+{
+#ifdef VISIBILITY_PRECHECK
+    return _surface->isVisible( stack );
+#else
+    return true;
+#endif
+}
+
+bool
+TileNode::cull_stealth(osgUtil::CullVisitor* cv)
+{
+    bool visible = false;
+
+    EngineContext* context = VisitorData::fetch<EngineContext>(*cv, ENGINE_CONTEXT_TAG);
+
+    // Shows all culled tiles, good for testing culling
+    unsigned frame = cv->getFrameStamp()->getFrameNumber();
+
+    if ( frame - _lastAcceptSurfaceFrame < 2u )
+    {
+        acceptSurface( cv, context );
+    }
+
+    else if ( _childrenReady )
+    {
+        for(int i=0; i<4; ++i)
+        {
+            getSubTile(i)->accept_cull_stealth( cv );
+        }
+    }
+
+    return visible;
+}
+
+bool
+TileNode::cull(osgUtil::CullVisitor* cv)
+{
+    EngineContext* context = VisitorData::fetch<EngineContext>(*cv, ENGINE_CONTEXT_TAG);
+    const SelectionInfo& selectionInfo = context->getSelectionInfo();
+
+    // Horizon check the surface first:
+    if ( !_surface->isVisible(cv) )
+    {
+        return false;
+    }
+    
+    // determine whether we can and should subdivide to a higher resolution:
+    bool childrenInRange = shouldSubDivide(cv, selectionInfo);
+
+    // whether it is OK to create child TileNodes is necessary.
+    bool canCreateChildren = childrenInRange;
+
+    // whether it is OK to load data if necessary.
+    bool canLoadData = true;
+
+    // whether to accept the current surface node and not the children.
+    bool canAcceptSurface = false;
+    
+    // Don't create children in progressive mode until content is in place
+    if ( _dirty && context->getOptions().progressive() == true )
+    {
+        canCreateChildren = false;
+    }
+    
+    // If this is an inherit-viewpoint camera, we don't need it to invoke subdivision
+    // because we want only the tiles loaded by the true viewpoint.
+    const osg::Camera* cam = cv->getCurrentCamera();
+    if ( cam && cam->getReferenceFrame() == osg::Camera::ABSOLUTE_RF_INHERIT_VIEWPOINT )
+    {
+        canCreateChildren = false;
+        canLoadData       = false;
+    }
+
+    if (childrenInRange)
+    {
+        // We are in range of the child nodes. Either draw them or load them.
+
+        // If the children don't exist, create them and inherit the parent's data.
+        if ( !_childrenReady && canCreateChildren )
+        {
+            _mutex.lock();
+
+            if ( !_childrenReady )
+            {
+                OE_START_TIMER(createChildren);
+                createChildren( context );
+                REPORT("TileNode::createChildren", createChildren);
+                _childrenReady = true;
+
+                // This means that you cannot start loading data immediately; must wait a frame.
+                canLoadData = false;
+            }
+
+            _mutex.unlock();
+        }
+
+        // If all are ready, traverse them now.
+        if ( _childrenReady )
+        {
+            for(int i=0; i<4; ++i)
+            {
+                getSubTile(i)->accept_cull(cv);
+            }
+
+            // if we traversed all children, but they all return "not visible",
+            // that means it's a horizon-culled tile anyway and we don't need
+            // to add any drawables.
+        }
+
+        // If we don't traverse the children, traverse this node's payload.
+        else
+        {
+            canAcceptSurface = true;
+        }
+    }
+
+    // If children are outside camera range, draw the payload and expire the children.
+    else
+    {
+        canAcceptSurface = true;
+    }
+
+    // accept this surface if necessary.
+    if ( canAcceptSurface )
+    {
+        acceptSurface( cv, context );
+        _lastAcceptSurfaceFrame.exchange( cv->getFrameStamp()->getFrameNumber() );
+    }
+
+       
+    // Run any patch callbacks.
+    context->invokeTilePatchCallbacks( cv, getTileKey(), _payloadStateSet.get(), _patch.get() );
+
+    // If this tile is marked dirty, try loading data.
+    if ( _dirty && canLoadData )
+    {
+        load( *cv );
+    }
+
+    return true;
+}
+
+bool
+TileNode::acceptSurface(osgUtil::CullVisitor* cv, EngineContext* context)
+{
+    OE_START_TIMER(acceptSurface);
+
+    // The reason we push the top-leel surface SS for every node is because
+    // of the patch callbacks. Instead of doing this we need a way to put
+    // patch traversals in their own top-level bin...
+
+    cv->pushStateSet( context->_surfaceSS.get() );
+    cv->pushStateSet( _payloadStateSet.get() );
+    _surface->accept( *cv );
+    cv->popStateSet();
+    cv->popStateSet();
+
+    REPORT("TileNode::acceptSurface", acceptSurface);
+
+    return true; //visible;
+}
+
+bool
+TileNode::accept_cull(osgUtil::CullVisitor* cv)
+{
+    bool visible = false;
+    
+    if (cv)
+    {
+        // update the timestamp so this tile doesn't become dormant.
+        _lastTraversalFrame.exchange( cv->getFrameStamp()->getFrameNumber() );
+        _lastTraversalTime = cv->getFrameStamp()->getReferenceTime();
+
+        if ( !cv->isCulled(*this) )
+        {
+            cv->pushStateSet( getStateSet() );
+
+            visible = cull( cv );
+
+            cv->popStateSet();
+        }
+    }
+
+    return visible;
+}
+
+bool
+TileNode::accept_cull_stealth(osgUtil::CullVisitor* cv)
+{
+    bool visible = false;
+    
+    if (cv)
+    {
+        cv->pushStateSet( getStateSet() );
+
+        visible = cull_stealth( cv );
+
+        cv->popStateSet();
+    }
+
+    return visible;
+}
+
+void
+TileNode::traverse(osg::NodeVisitor& nv)
+{
+    // Cull only:
+    if ( nv.getVisitorType() == nv.CULL_VISITOR )
+    {
+        osgUtil::CullVisitor* cv = dynamic_cast<osgUtil::CullVisitor*>(&nv);
+
+        if (VisitorData::isSet(nv, "osgEarth.Stealth"))
+        {
+            accept_cull_stealth( cv );
+        }
+        else
+        {
+            accept_cull( cv );
+        }
+    }
+
+    // Everything else: update, GL compile, intersection, compute bound, etc.
+    else
+    {
+        // If there are child nodes, traverse them:
+        int numChildren = getNumChildren();
+        if ( numChildren > 0 )
+        {
+            for(int i=0; i<numChildren; ++i)
+            {
+                _children[i]->accept( nv );
+            }
+        }
+
+        // Otherwise traverse the surface.
+        // TODO: in what situations should we traverse the landcover as well? GL compile?
+        else 
+        {
+            _surface->accept( nv );
+        }
+    }
+}
+
+void
+TileNode::createChildren(EngineContext* context)
+{
+    // NOTE: Ensure that _mutex is locked before calling this fucntion!
+
+    // Create the four child nodes.
+    for(unsigned quadrant=0; quadrant<4; ++quadrant)
+    {
+        TileNode* node = new TileNode();
+        if (context->getOptions().minExpiryFrames().isSet())
+        {
+            node->setMinimumExpiryFrames( *context->getOptions().minExpiryFrames() );
+        }
+        if (context->getOptions().minExpiryTime().isSet())
+        {         
+            node->setMinimumExpiryTime( *context->getOptions().minExpiryTime() );
+        }
+
+        // Build the surface geometry:
+        node->create( getTileKey().createChildKey(quadrant), context );
+
+        // Add to the scene graph.
+        addChild( node );
+
+        // Inherit the samplers with new scale/bias information.
+        node->inheritState( context );
+    }
+}
+
+bool
+TileNode::inheritState(EngineContext* context)
+{
+    // Find the parent node. It will only be null if this is a "first LOD" tile.
+    TileNode* parent = getNumParents() > 0 ? dynamic_cast<TileNode*>(getParent(0)) : 0L;
+
+    bool changesMade = false;
+
+    // which quadrant is this tile in?
+    unsigned quadrant = getTileKey().getQuadrant();
+
+    // default inheritance of the elevation data for bounding purposes:
+    osg::ref_ptr<const osg::Image> elevRaster;
+    osg::Matrixf                   elevMatrix;
+    if ( parent )
+    {
+        elevRaster = parent->getElevationRaster();
+        elevMatrix = parent->getElevationMatrix();
+        elevMatrix.preMult( scaleBias[quadrant] );
+    }
+
+    // Find all the sampler matrix uniforms and scale/bias them to the current quadrant.
+    // This will inherit textures and use the proper sub-quadrant until new data arrives (later).
+    for( RenderBindings::const_iterator binding = context->getRenderBindings().begin(); binding != context->getRenderBindings().end(); ++binding )
+    {
+        if ( binding->usage().isSetTo(binding->COLOR) )
+        {
+            if ( parent && parent->getStateSet() )
+            {
+                MPTexture* parentMPTex = parent->getMPTexture();
+                _mptex->inheritState( parentMPTex, scaleBias[quadrant] );
+                changesMade = true;
+            }
+        }
+
+        else if ( binding->usage().isSetTo(binding->COLOR_PARENT) )
+        {
+            //nop -- this is handled as part of the COLOR binding
+        }
+
+        else
+        {
+            osg::StateAttribute* sa = getStateSet()->getTextureAttribute(binding->unit(), osg::StateAttribute::TEXTURE);        
+
+            // If the attribute isn't present, that means we are inheriting it from above.
+            // So construct a new scale/bias matrix.
+            if ( sa == 0L )
+            {
+                osg::Matrixf matrix;
+
+                // Find the parent's matrix and scale/bias it to this quadrant:
+                if ( parent && parent->getStateSet() )
+                {
+                    const osg::Uniform* matrixUniform = parent->getStateSet()->getUniform( binding->matrixName() );
+                    if ( matrixUniform )
+                    {
+                        matrixUniform->get( matrix );
+                        matrix.preMult( scaleBias[quadrant] );
+                    }
+                }
+
+                // Add a new uniform with the scale/bias'd matrix:
+                osg::StateSet* stateSet = getOrCreateStateSet();
+                stateSet->removeUniform( binding->matrixName() );
+                stateSet->addUniform( context->getOrCreateMatrixUniform(binding->matrixName(), matrix) );
+                changesMade = true;
+            }
+
+            // If this is elevation data, record the new raster so we can apply it to the node.
+            else if ( binding->usage().isSetTo(binding->ELEVATION) )
+            {
+                osg::Texture* t = static_cast<osg::Texture*>(sa);
+                elevRaster = t->getImage(0);
+                elevMatrix = osg::Matrixf::identity();
+            }
+        }
+    }
+
+    // If we found one, communicate it to the node and its children.
+    if (elevRaster.valid())
+    {
+        if (elevRaster.get() != getElevationRaster() || elevMatrix != getElevationMatrix() )
+        {
+            setElevationRaster( elevRaster.get(), elevMatrix );
+            changesMade = true;
+        }
+    }
+
+    // finally, update the uniforms for terrain morphing
+    updateTileUniforms( context->getSelectionInfo() );
+
+    if ( !changesMade )
+    {
+        OE_INFO << LC << _key.str() << ", good, no changes :)\n";
+    }
+    else
+    {
+        dirtyBound();
+    }
+
+    return changesMade;
+}
+
+void
+TileNode::mergeStateSet(osg::StateSet* stateSet, MPTexture* mptex, const RenderBindings& bindings)
+{
+    _mptex->merge( mptex );    
+    getStateSet()->merge(*stateSet);
+}
+
+void
+TileNode::load(osg::NodeVisitor& nv)
+{
+    // Access the context:
+    EngineContext* context = VisitorData::fetch<EngineContext>(nv, ENGINE_CONTEXT_TAG);
+
+    // Create a new load request on demand:
+    if ( !_loadRequest.valid() )
+    {
+        Threading::ScopedMutexLock lock(_mutex);
+        if ( !_loadRequest.valid() )
+        {
+            _loadRequest = new LoadTileData( this, context );
+            _loadRequest->setName( _key.str() );
+            _loadRequest->setTileKey( _key );
+        }
+    }
+
+    
+    // Construct the load PRIORITY: 0=lowest, 1=highest.
+    
+    const SelectionInfo& si = context->getSelectionInfo();
+    int lod     = getTileKey().getLOD();
+    int numLods = si.numLods();
+    
+    // LOD priority is in the range [0..numLods]
+    float lodPriority = (float)lod;
+    if ( context->getOptions().highResolutionFirst() == false )
+        lodPriority = (float)(numLods - lod);
+
+    float distance = nv.getDistanceToViewPoint(getBound().center(), true);
+
+    // dist priority uis in the range [0..1]
+    float distPriority = 1.0 - distance/si.visParameters(0)._visibilityRange;
+
+    // add thenm together, and you get tiles sorted first by lodPriority (because of
+    // the biggest range), and second by distance.
+    float priority = lodPriority + distPriority;
+
+    // normalize the composite priority to [0..1].
+    priority /= (float)(numLods+1);
+
+    // Submit to the loader.
+    context->getLoader()->load( _loadRequest.get(), priority, nv );
+}
+
+bool
+TileNode::areSubTilesDormant(const osg::FrameStamp* fs) const
+{
+    return
+        getNumChildren() >= 4           &&
+        getSubTile(0)->isDormant( fs )  &&
+        getSubTile(1)->isDormant( fs )  &&
+        getSubTile(2)->isDormant( fs )  &&
+        getSubTile(3)->isDormant( fs );
+}
+
+void
+TileNode::removeSubTiles()
+{
+    _childrenReady = false;
+    this->removeChildren(0, this->getNumChildren());
+}
diff --git a/src/osgEarthDrivers/engine_rex/TileNodeRegistry b/src/osgEarthDrivers/engine_rex/TileNodeRegistry
new file mode 100644
index 0000000..62e8344
--- /dev/null
+++ b/src/osgEarthDrivers/engine_rex/TileNodeRegistry
@@ -0,0 +1,239 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+* Copyright 2008-2014 Pelican Mapping
+* http://osgearth.org
+*
+* osgEarth is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public License
+* along with this program.  If not, see <http://www.gnu.org/licenses/>
+*/
+#ifndef OSGEARTH_DRIVERS_REX_TERRAIN_ENGINE_TILE_NODE_REGISTRY
+#define OSGEARTH_DRIVERS_REX_TERRAIN_ENGINE_TILE_NODE_REGISTRY 1
+
+#include "Common"
+#include "TileNode"
+#include <osgEarth/Revisioning>
+#include <osgEarth/ThreadingUtils>
+//#include <osgEarth/TerrainEngineNode>
+#include <osgEarth/ResourceReleaser>
+#include <OpenThreads/Atomic>
+#include <osgUtil/RenderBin>
+#include <map>
+
+namespace osgEarth { namespace Drivers { namespace RexTerrainEngine
+{
+    using namespace osgEarth;
+
+    struct RandomAccessTileMap
+    {
+        struct Entry {
+            osg::ref_ptr<TileNode> tile;
+            unsigned index;
+        };
+
+        typedef std::map<TileKey, Entry> Table;
+        Table _table;
+
+        typedef Table::iterator iterator;
+        typedef Table::const_iterator const_iterator;
+
+        typedef std::vector<Entry*> Vector;
+        Vector _vector;
+
+        iterator begin()             { return _table.begin(); }
+        const_iterator begin() const { return _table.begin(); }
+        iterator end()               { return _table.end(); }
+        const_iterator end() const   { return _table.end(); }
+
+        void insert(const TileKey& key, TileNode* data) {
+            Entry& e = _table[key];
+            e.tile = data;
+            e.index = _vector.size();
+            _vector.push_back( &e );
+        }
+
+        void erase(const TileKey& key) {
+            iterator i = _table.find(key);
+            if ( i != _table.end() ) {
+                unsigned s = _vector.size()-1;
+                _vector[i->second.index] = _vector[s];
+                _vector[i->second.index]->index = i->second.index;
+                _vector.resize( s );
+                _table.erase( i );
+            }
+        }
+
+        const TileNode* find(const TileKey& key) const {
+            const_iterator i = _table.find(key);
+            return i != _table.end() ? i->second.tile.get() : 0L;
+        }
+
+        TileNode* find(const TileKey& key) {
+            const_iterator i = _table.find(key);
+            return i != _table.end() ? i->second.tile.get() : 0L;
+        }
+
+        unsigned size() const {
+            return _vector.size();
+        }
+
+        bool empty() const {
+            return size() == 0u;
+        }
+
+        TileNode* at(unsigned index) {
+            return _vector[index]->tile.get();
+        }
+
+        const TileNode* at(unsigned index) const {
+            return _vector[index]->tile.get();
+        }
+
+        void clear() {
+            _table.clear();
+            _vector.clear();
+        }
+    };
+
+    /**
+     * Holds a reference to each tile created by the driver.
+     */
+    class TileNodeRegistry : public osg::Referenced
+    {
+    public:
+        typedef RandomAccessTileMap TileNodeMap;
+
+        // Prototype for a locked tileset operation (see run)
+        struct Operation {
+            virtual void operator()(TileNodeMap& tiles) =0;
+        };
+        struct ConstOperation {
+            virtual void operator()(const TileNodeMap& tiles) const =0;
+        };
+
+        // Operation that runs when another node enters the registry.
+        struct DeferredOperation {
+            virtual void operator()(TileNode* requestingNode, TileNode* expectedNode) const =0;
+        };
+
+    public:
+        TileNodeRegistry( const std::string& name );
+
+        /* Enabled revisioning on TileNodes, to support incremental update. */
+        void setRevisioningEnabled(bool value);
+
+        /**
+         * Sets the revision of the map model - the registry will assign this
+         * to TileNodes added with add().
+         *
+         * @param rev        Revision of map
+         * @param setToDirty In addition to update the revision, immediately set
+         *                   all tiles to dirty as well, effectively forcing an
+         *                   update.
+         */
+        void setMapRevision( const Revision& rev, bool setToDirty =false );
+
+        /** Map revision that the reg will assign to new tiles. */
+        const Revision& getMapRevision() const { return _maprev; }
+
+        /**
+         * Marks all tiles intersecting the extent as dirty. If incremental
+         * update is enabled, they will automatically reload.
+         *
+         * NOTE: Input extent SRS must match the terrain's SRS exactly.
+         *       The method does not check.
+         */
+        void setDirty(const GeoExtent& extent, unsigned minLevel, unsigned maxLevel);
+
+        /**
+         * Sets the current cull traversal frame number so that tiles have
+         * access to the information. Atomic.
+         */
+        void setTraversalFrame(unsigned frame) { _frameNumber.exchange(frame); }
+
+        unsigned getTraversalFrame() const { return _frameNumber; }
+
+        virtual ~TileNodeRegistry() { }
+
+        /** Adds a tile to the registry */
+        void add( TileNode* tile );
+
+        /** Adds several tiles to the registry */
+        void add( const TileNodeVector& tiles );
+
+        /** Removes a tile */
+        void remove( TileNode* tile );
+
+        /** Clears all tiles from the registry */
+        //void clear();
+
+        /** Moves a tile from this registry to another registry */
+        //void move( TileNode* tile, TileNodeRegistry* destination );
+
+        /** Moves all tiles to another registry. */
+        //void moveAll(TileNodeRegistry* destinataion);
+
+        /** Finds a tile in the registry */
+        bool get( const TileKey& key, osg::ref_ptr<TileNode>& out_tile );
+
+        /** Finds a tile in the registry and then removes it. */
+        bool take( const TileKey& key, osg::ref_ptr<TileNode>& out_tile );
+
+        /** Whether there are tiles in this registry (snapshot in time) */
+        bool empty() const;
+
+        /** Runs an operation against the exclusively locked tile set. */
+        void run( Operation& op );
+        
+        /** Runs an operation against the read-locked tile set. */
+        void run( const ConstOperation& op ) const;
+
+        /** Number of tiles in the registry. */
+        unsigned size() const { return _tiles.size(); }
+
+        /** Tells the registry to listen for the TileNode for the specific key
+            to arrive, and upon its arrival, notifies the waiter. After notifying
+            the waiter, it removes the listen request. */
+        void listenFor(const TileKey& keyToWaitFor, TileNode* waiter);
+
+        /** Take an arbitrary node from the registry. */
+        TileNode* takeAny();
+
+        /** Empty the registry, releasing all tiles. */
+        void releaseAll(ResourceReleaser*);
+
+    protected:
+
+        bool                              _revisioningEnabled;
+        Revision                          _maprev;
+        std::string                       _name;
+        TileNodeMap                       _tiles;
+        OpenThreads::Atomic               _frameNumber;
+        mutable Threading::ReadWriteMutex _tilesMutex;
+
+        //typedef std::vector<TileKey> TileKeyVector;
+        typedef fast_set<TileKey> TileKeySet;
+        typedef std::map<TileKey, TileKeySet> TileKeyOneToMany;
+
+        TileKeyOneToMany _notifiers;
+
+    private:
+
+        /** adds a tile node, assuming the write-lock has been taken by the caller and
+            that node is not NULL */
+        void addSafely(TileNode* node);
+        void removeSafely(const TileKey& key);
+    };
+
+} } } // namespace osgEarth::Drivers::MPTerrainEngine
+
+#endif // OSGEARTH_DRIVERS_REX_TERRAIN_ENGINE_TILE_NODE_REGISTRY
diff --git a/src/osgEarthDrivers/engine_rex/TileNodeRegistry.cpp b/src/osgEarthDrivers/engine_rex/TileNodeRegistry.cpp
new file mode 100644
index 0000000..0e6d122
--- /dev/null
+++ b/src/osgEarthDrivers/engine_rex/TileNodeRegistry.cpp
@@ -0,0 +1,278 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+* Copyright 2008-2014 Pelican Mapping
+* http://osgearth.org
+*
+* osgEarth is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public License
+* along with this program.  If not, see <http://www.gnu.org/licenses/>
+*/
+#include "TileNodeRegistry"
+
+using namespace osgEarth::Drivers::RexTerrainEngine;
+using namespace osgEarth;
+
+#define LC "[TileNodeRegistry] "
+
+#define OE_TEST OE_NULL
+//#define OE_TEST OE_INFO
+
+
+//----------------------------------------------------------------------------
+
+TileNodeRegistry::TileNodeRegistry(const std::string& name) :
+_name              ( name ),
+_revisioningEnabled( false ),
+_frameNumber       ( 0u )
+{
+    //nop
+}
+
+
+void
+TileNodeRegistry::setRevisioningEnabled(bool value)
+{
+    _revisioningEnabled = value;
+}
+
+
+void
+TileNodeRegistry::setMapRevision(const Revision& rev,
+                                 bool            setToDirty)
+{
+    if ( _revisioningEnabled )
+    {
+        if ( _maprev != rev || setToDirty )
+        {
+            Threading::ScopedWriteLock exclusive( _tilesMutex );
+
+            if ( _maprev != rev || setToDirty )
+            {
+                _maprev = rev;
+
+                for( TileNodeMap::iterator i = _tiles.begin(); i != _tiles.end(); ++i )
+                {
+                    i->second.tile->setMapRevision( _maprev );
+                    if ( setToDirty )
+                    {
+                        i->second.tile->setDirty( true );
+                    }
+                }
+            }
+        }
+    }
+}
+
+
+//NOTE: this method assumes the input extent is the same SRS as
+// the terrain profile SRS.
+void
+TileNodeRegistry::setDirty(const GeoExtent& extent,
+                           unsigned         minLevel,
+                           unsigned         maxLevel)
+{
+    Threading::ScopedWriteLock exclusive( _tilesMutex );
+    
+    bool checkSRS = false;
+    for( TileNodeMap::iterator i = _tiles.begin(); i != _tiles.end(); ++i )
+    {
+        const TileKey& key = i->first;
+        if (minLevel <= key.getLOD() && 
+            maxLevel >= key.getLOD() &&
+            extent.intersects(i->first.getExtent(), checkSRS) )
+        {
+            i->second.tile->setDirty( true );
+        }
+    }
+}
+
+void
+TileNodeRegistry::addSafely(TileNode* tile)
+{
+    _tiles.insert( tile->getTileKey(), tile );
+    //_tiles[ tile->getTileKey() ] = tile;
+    if ( _revisioningEnabled )
+        tile->setMapRevision( _maprev );
+
+    // check for tiles that are waiting on this tile, and notify them!
+    TileKeyOneToMany::iterator notifier = _notifiers.find( tile->getTileKey() );
+    if ( notifier != _notifiers.end() )
+    {
+        TileKeySet& listeners = notifier->second;
+
+        for(TileKeySet::iterator listener = listeners.begin(); listener != listeners.end(); ++listener)
+        {
+            TileNode* listenerTile = _tiles.find( *listener );
+            if ( listenerTile )
+            {
+                listenerTile->notifyOfArrival( tile );
+            }
+        }
+        _notifiers.erase( notifier );
+    }
+
+    OE_TEST << LC << _name 
+        << ": tiles=" << _tiles.size()
+        << ", notifiers=" << _notifiers.size()
+        << std::endl;
+}
+
+void
+TileNodeRegistry::removeSafely(const TileKey& key)
+{
+    _tiles.erase( key );
+
+    for(TileKeyOneToMany::iterator i = _notifiers.begin(); i != _notifiers.end(); )
+    {
+        i->second.erase( key );
+
+        if ( i->second.size() == 0 )
+            _notifiers.erase( i++ ); // http://stackoverflow.com/a/8234813/4218920
+        else
+            ++i;
+    }
+}
+
+void
+TileNodeRegistry::add( TileNode* tile )
+{
+    if ( tile )
+    {
+        Threading::ScopedWriteLock exclusive( _tilesMutex );
+        addSafely( tile );
+    }
+}
+
+void
+TileNodeRegistry::add( const TileNodeVector& tiles )
+{
+    if ( tiles.size() > 0 )
+    {
+        Threading::ScopedWriteLock exclusive( _tilesMutex );
+        for( TileNodeVector::const_iterator i = tiles.begin(); i != tiles.end(); ++i )
+        {
+            if ( i->valid() )
+                addSafely( i->get() );
+        }
+        OE_TEST << LC << _name << ": tiles=" << _tiles.size() << std::endl;
+    }
+}
+
+void
+TileNodeRegistry::remove( TileNode* tile )
+{
+    if ( tile )
+    {
+        Threading::ScopedWriteLock exclusive( _tilesMutex );
+        removeSafely( tile->getTileKey() );
+    }
+}
+  
+
+bool
+TileNodeRegistry::get( const TileKey& key, osg::ref_ptr<TileNode>& out_tile )
+{
+    Threading::ScopedReadLock shared( _tilesMutex );
+
+    out_tile = _tiles.find(key);
+    return out_tile.valid();
+}
+
+
+bool
+TileNodeRegistry::take( const TileKey& key, osg::ref_ptr<TileNode>& out_tile )
+{
+    Threading::ScopedWriteLock exclusive( _tilesMutex );
+
+    out_tile = _tiles.find(key);
+    if ( out_tile.valid() )
+    {
+        removeSafely( key );
+    }
+    return out_tile.valid();
+}
+
+
+void
+TileNodeRegistry::run( TileNodeRegistry::Operation& op )
+{
+    Threading::ScopedWriteLock lock( _tilesMutex );
+    unsigned size = _tiles.size();
+    op.operator()( _tiles );
+    if ( size != _tiles.size() )
+        OE_TEST << LC << _name << ": tiles=" << _tiles.size() << std::endl;
+}
+
+
+void
+TileNodeRegistry::run( const TileNodeRegistry::ConstOperation& op ) const
+{
+    Threading::ScopedReadLock lock( _tilesMutex );
+    op.operator()( _tiles );
+    OE_TEST << LC << _name << ": tiles=" << _tiles.size() << std::endl;
+}
+
+
+bool
+TileNodeRegistry::empty() const
+{
+    // don't bother mutex-protecteding this.
+    return _tiles.empty();
+}
+
+void
+TileNodeRegistry::listenFor(const TileKey& tileToWaitFor, TileNode* waiter)
+{
+    Threading::ScopedWriteLock lock( _tilesMutex );
+    TileNode* tile = _tiles.find( tileToWaitFor );
+    if ( tile )
+    {
+        OE_DEBUG << LC << waiter->getTileKey().str() << " listened for " << tileToWaitFor.str()
+            << ", but it was already in the repo.\n";
+
+        waiter->notifyOfArrival( tile );
+    }
+    else
+    {
+        OE_DEBUG << LC << waiter->getTileKey().str() << " listened for " << tileToWaitFor.str() << ".\n";
+        //_notifications[tileToWaitFor].push_back( waiter->getKey() );
+        _notifiers[tileToWaitFor].insert( waiter->getTileKey() );
+    }
+}
+        
+TileNode*
+TileNodeRegistry::takeAny()
+{
+    Threading::ScopedWriteLock exclusive( _tilesMutex );
+    osg::ref_ptr<TileNode> tile = _tiles.begin()->second.tile.get();
+    removeSafely( tile->getTileKey() );
+    return tile.release();
+}
+
+void
+TileNodeRegistry::releaseAll(ResourceReleaser* releaser)
+{
+    ResourceReleaser::ObjectList objects;
+    {
+        Threading::ScopedWriteLock exclusive(_tilesMutex);
+
+        for (TileNodeMap::iterator i = _tiles.begin(); i != _tiles.end(); ++i)
+        {
+            objects.push_back(i->second.tile.get());
+        }
+
+        _tiles.clear();
+        _notifiers.clear();
+    }
+
+    releaser->push(objects);
+}
\ No newline at end of file
diff --git a/src/osgEarthDrivers/engine_rex/Unloader b/src/osgEarthDrivers/engine_rex/Unloader
new file mode 100644
index 0000000..919d8f8
--- /dev/null
+++ b/src/osgEarthDrivers/engine_rex/Unloader
@@ -0,0 +1,73 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+ * Copyright 2008-2014 Pelican Mapping
+ * http://osgearth.org
+ *
+ * osgEarth is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ */
+#ifndef OSGEARTH_REX_UNLOADER
+#define OSGEARTH_REX_UNLOADER 1
+
+#include "Common"
+
+#include <osgEarth/ThreadingUtils>
+#include <osgEarth/TileKey>
+#include <osgEarth/ResourceReleaser>
+
+#include <osg/Group>
+
+
+namespace osgEarth { namespace Drivers { namespace RexTerrainEngine
+{
+    class TileNodeRegistry; // for UnloaderGroup
+
+
+    /** Pure interface class for a tile unloader. */
+    class Unloader
+    {
+    public:
+        virtual void unloadChildren(const std::vector<TileKey>& keys) =0;
+    };
+
+    /** Group-based tile unloader. */
+    class UnloaderGroup : public osg::Group, public Unloader
+    {
+    public:
+        UnloaderGroup(TileNodeRegistry* tiles);
+
+        /** Sets the key count at which unloading will begin */
+        void setThreshold(int t) { _threshold = t; }
+
+        /** Service that will release GL objects on unloaded nodes. */
+        void setReleaser(ResourceReleaser* releaser) { _releaser = releaser; }
+
+    public: // Unloader
+
+        void unloadChildren(const std::vector<TileKey>& keys);
+
+    public: // osg::Node
+        void traverse(osg::NodeVisitor& nv);
+
+    protected:
+        int                            _threshold;
+        std::vector<TileKey>           _parentKeys;
+        TileNodeRegistry*              _tiles;
+        osg::ref_ptr<ResourceReleaser> _releaser;
+        mutable Threading::Mutex       _mutex;
+    };
+
+} } } // namespace osgEarth::Drivers::RexTerrainEngine
+
+
+#endif // OSGEARTH_REX_UNLOADER
diff --git a/src/osgEarthDrivers/engine_rex/Unloader.cpp b/src/osgEarthDrivers/engine_rex/Unloader.cpp
new file mode 100644
index 0000000..32b9863
--- /dev/null
+++ b/src/osgEarthDrivers/engine_rex/Unloader.cpp
@@ -0,0 +1,124 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+ * Copyright 2008-2014 Pelican Mapping
+ * http://osgearth.org
+ *
+ * osgEarth is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ */
+#include "Unloader"
+#include "TileNode"
+#include "TileNodeRegistry"
+
+using namespace osgEarth::Drivers::RexTerrainEngine;
+
+
+//........................................................................
+
+namespace
+{
+    // traverses a node graph and moves any TileNodes from the LIVE
+    // registry to the DEAD registry.
+    struct ExpirationCollector : public osg::NodeVisitor
+    {
+        TileNodeRegistry*      _tiles;
+        unsigned               _count;
+
+        ResourceReleaser::ObjectList _nodes;
+
+        ExpirationCollector(TileNodeRegistry* tiles)
+            : _tiles(tiles), _count(0)
+        {
+            // set up to traverse the entire subgraph, ignoring node masks.
+            setTraversalMode( TRAVERSE_ALL_CHILDREN );
+            setNodeMaskOverride( ~0 );
+        }
+
+        void apply(osg::Node& node)
+        {
+            // Make sure the tile is still dormat before releasing it
+            TileNode* tn = dynamic_cast<TileNode*>( &node );
+            if ( tn )
+            {
+                _nodes.push_back(tn);
+                _tiles->remove( tn );
+                _count++;
+            }
+            traverse(node);
+        }
+    };
+}
+
+//........................................................................
+
+
+#undef  LC
+#define LC "[UnloaderGroup] "
+
+UnloaderGroup::UnloaderGroup(TileNodeRegistry* tiles) :
+_tiles(tiles),
+_threshold( INT_MAX )
+{
+    this->setNumChildrenRequiringUpdateTraversal( 1u );
+}
+
+void
+UnloaderGroup::unloadChildren(const std::vector<TileKey>& keys)
+{
+    _mutex.lock();
+    for(std::vector<TileKey>::const_iterator i = keys.begin(); i != keys.end(); ++i)
+        _parentKeys.push_back( *i );
+    _mutex.unlock();
+}
+
+void
+UnloaderGroup::traverse(osg::NodeVisitor& nv)
+{
+    if ( nv.getVisitorType() == nv.UPDATE_VISITOR )
+    {
+        if ( _parentKeys.size() > _threshold )
+        {
+            unsigned unloaded=0, notFound=0, notDormant=0;
+            Threading::ScopedMutexLock lock( _mutex );
+            for(std::vector<TileKey>::const_iterator parentKey = _parentKeys.begin(); parentKey != _parentKeys.end(); ++parentKey)
+            {
+                osg::ref_ptr<TileNode> parentNode;
+                if ( _tiles->get(*parentKey, parentNode) )
+                {
+                    // re-check for dormancy in case something has changed
+                    if ( parentNode->areSubTilesDormant(nv.getFrameStamp()) )
+                    {
+                        // find and move all tiles to be unloaded to the dead pile.
+                        ExpirationCollector collector( _tiles );
+                        for(unsigned i=0; i<parentNode->getNumChildren(); ++i)
+                            parentNode->getSubTile(i)->accept( collector );
+                        unloaded += collector._count;
+
+                        // submit all collected nodes for GL resource release:
+                        if (!collector._nodes.empty() && _releaser.valid())
+                            _releaser->push(collector._nodes);
+
+                        parentNode->removeSubTiles();
+                    }
+                    else notDormant++;
+                }
+                else notFound++;
+            }
+
+            //OE_NOTICE << LC << "Total=" << _parentKeys.size() << "; threshold=" << _threshold << "; unloaded=" << unloaded << "; notDormant=" << notDormant << "; notFound=" << notFound << "; live=" << _live->size() << "\n";
+            _parentKeys.clear();
+        }
+    }
+    osg::Group::traverse( nv );
+}
+
diff --git a/src/osgEarthDrivers/fastdxt/CMakeLists.txt b/src/osgEarthDrivers/fastdxt/CMakeLists.txt
index 132aa0b..ce231bd 100644
--- a/src/osgEarthDrivers/fastdxt/CMakeLists.txt
+++ b/src/osgEarthDrivers/fastdxt/CMakeLists.txt
@@ -5,7 +5,9 @@ OPTION(CURL_IS_STATIC "on if curl is a static lib " ON)
 MARK_AS_ADVANCED(CURL_IS_STATIC)
 
 IF(WIN32)
-    SET(CMAKE_SHARED_LINKER_FLAGS_DEBUG "${CMAKE_SHARED_LINKER_FLAGS_DEBUG} /NODEFAULTLIB:MSVCRT")
+    IF(MSVC)
+        SET(CMAKE_SHARED_LINKER_FLAGS_DEBUG "${CMAKE_SHARED_LINKER_FLAGS_DEBUG} /NODEFAULTLIB:MSVCRT")
+    ENDIF(MSVC)
     IF(CURL_IS_STATIC)
         ADD_DEFINITIONS(-DCURL_STATICLIB)
         SET(TARGET_EXTERNAL_LIBRARIES ws2_32 winmm)
@@ -36,4 +38,4 @@ ENDIF()
 
 SETUP_PLUGIN(fastdxt)
 
-ENDIF(ENABLE_FASTDXT)
\ No newline at end of file
+ENDIF(ENABLE_FASTDXT)
diff --git a/src/osgEarthDrivers/feature_elevation/FeatureElevationOptions b/src/osgEarthDrivers/feature_elevation/FeatureElevationOptions
index 619e1fd..0f2ade8 100644
--- a/src/osgEarthDrivers/feature_elevation/FeatureElevationOptions
+++ b/src/osgEarthDrivers/feature_elevation/FeatureElevationOptions
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -37,6 +37,10 @@ namespace osgEarth { namespace Drivers
         optional<std::string>& attr() { return _attr; }
         const optional<std::string>& attr() const { return _attr; }
 
+        /** vertical offset for flattening from the elevation value in the feature source */
+        optional<double>& offset() { return _offset; }
+        const optional<double>& offset() const { return _offset; }
+
         /** Feature source from which to read the feature data */
         optional<FeatureSourceOptions>& featureOptions() { return _featureOptions; }
         const optional<FeatureSourceOptions>& featureOptions() const { return _featureOptions; }
@@ -45,7 +49,8 @@ namespace osgEarth { namespace Drivers
 
         FeatureElevationOptions( const TileSourceOptions& options =TileSourceOptions() ) :
             TileSourceOptions( options ),
-            _attr( "ELEVATION" )
+            _attr( "ELEVATION" ),
+            _offset( -0.1 )
         {
             setDriver( "feature_elevation" );
             fromConfig( _conf );
@@ -60,6 +65,7 @@ namespace osgEarth { namespace Drivers
             Config conf = TileSourceOptions::getConfig();
             conf.updateIfSet( "attr", _attr );
             conf.updateObjIfSet( "features", _featureOptions );
+            conf.updateIfSet( "offset", _offset );
 
             return conf;
         }
@@ -71,6 +77,7 @@ namespace osgEarth { namespace Drivers
 
         void fromConfig( const Config& conf ) {
             conf.getIfSet( "attr", _attr );
+            conf.getIfSet( "offset", _offset );
 
             if ( conf.hasChild("features") )
                 _featureOptions->merge( conf.child("features") );
@@ -78,6 +85,7 @@ namespace osgEarth { namespace Drivers
 
         optional<FeatureSourceOptions>  _featureOptions;
         optional<std::string>           _attr;
+        optional<double>                _offset;
     };
 
 } } // namespace osgEarth::Drivers
diff --git a/src/osgEarthDrivers/feature_elevation/ReaderWriterFeatureElevation.cpp b/src/osgEarthDrivers/feature_elevation/ReaderWriterFeatureElevation.cpp
index 9f0c091..a0cc694 100644
--- a/src/osgEarthDrivers/feature_elevation/ReaderWriterFeatureElevation.cpp
+++ b/src/osgEarthDrivers/feature_elevation/ReaderWriterFeatureElevation.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
@@ -48,6 +48,8 @@ using namespace std;
 using namespace osgEarth;
 using namespace osgEarth::Drivers;
 
+#include <osgEarth/Profiler>
+
 
 class FeatureElevationTileSource : public TileSource
 {
@@ -55,99 +57,68 @@ public:
     FeatureElevationTileSource( const TileSourceOptions& options ) :
       TileSource( options ),
       _options(options),
-      _maxDataLevel(30)
+      _maxDataLevel(23),
+      _offset(-0.1)
     {
+        _offset = _options.offset().getOrUse(_offset);
     }
 
     virtual ~FeatureElevationTileSource() { }
 
 
-    Status initialize( const osgDB::Options* dbOptions )
+    Status initialize(const osgDB::Options* readOptions)
     {
         Cache* cache = 0;
 
-        _dbOptions = Registry::instance()->cloneOrCreateOptions( dbOptions );
-
-        if ( _dbOptions.valid() )
-        {
-            // Set up a Custom caching bin for this TileSource
-            cache = Cache::get( _dbOptions.get() );
-            if ( cache )
-            {
-                Config optionsConf = _options.getConfig();
-
-                std::string binId = Stringify() << std::hex << hashString(optionsConf.toJSON());
-                _cacheBin = cache->addBin( binId );
-
-                if ( _cacheBin.valid() )
-                {
-                    _cacheBin->apply( _dbOptions.get() );
-                }
-            }
-        }
-
-
         if ( !_options.featureOptions().isSet() )
         {
-            return Status::Error( Stringify() << LC << "Illegal: feature source is required" );
+            return Status::Error(Status::ConfigurationError, "Feature source is required" );
         }
     
+        // create the driver:
         _features = FeatureSourceFactory::create( _options.featureOptions().value() );
         if ( !_features.valid() )
         {
-            return Status::Error( Stringify() << "Illegal: no valid feature source provided");
+            return Status::Error(Status::ServiceUnavailable, "Cannot find feature driver \"" + _options.featureOptions()->getDriver() + "\"");
         }
 
-        //if ( _features->getGeometryType() != osgEarth::Symbology::Geometry::TYPE_POLYGON )
-        //{
-        //    Status::Error( Stringify() << "Illegal: only polygon features are currently supported");
-        //    return false;
-        //}
-
-        _features->initialize( _dbOptions );
-
-        // populate feature list
-        osg::ref_ptr<FeatureCursor> cursor = _features->createFeatureCursor();
-        while ( cursor.valid() && cursor->hasMore() )
+        // open the feature source:
+        const Status& fstatus = _features->open(readOptions);
+        if (fstatus.isError())
         {
-            Feature* f = cursor->nextFeature();
-            if ( f && f->getGeometry() )
-                _featureList.push_back(f);
+            return fstatus;
         }
 
         if (_features->getFeatureProfile())
         {
-            if (getProfile() && !getProfile()->getSRS()->isEquivalentTo(_features->getFeatureProfile()->getSRS()))
+			if (getProfile() && !getProfile()->getSRS()->isEquivalentTo(_features->getFeatureProfile()->getSRS()))
+            {
                 OE_WARN << LC << "Specified profile does not match feature profile, ignoring specified profile." << std::endl;
+            }
 
             _extents = _features->getFeatureProfile()->getExtent();
 
-            const Profile* profile = Profile::create(
-                _extents.getSRS(),
-                _extents.bounds().xMin(),
-                _extents.bounds().yMin(),
-                _extents.bounds().xMax(),
-                _extents.bounds().yMax());
+			// If you didn't specify a profile (hint, you should have), use the feature profile.
+			if ( !getProfile() )
+			{
+                OE_WARN << LC << "No profile specified; falling back on feature profile." << std::endl;
 
-            setProfile( profile );
-        }
-        else if (getProfile())
-        {
-            _extents = getProfile()->getExtent();
-        }
-        else
-        {
-            return Status::Error( Stringify() << "Failed to establish a profile for " <<  this->getName() );
-        }
+				const Profile* profile = Profile::create(
+					_extents.getSRS(),
+					_extents.bounds().xMin(),
+					_extents.bounds().yMin(),
+					_extents.bounds().xMax(),
+					_extents.bounds().yMax());
 
-        getDataExtents().push_back( DataExtent(_extents, 0, _maxDataLevel) );
+				setProfile( profile );
+			}
+        }
 
         return STATUS_OK;
     }
 
 
-    osg::Image* createImage( const TileKey&        key,
-                             ProgressCallback*     progress)
+    osg::Image* createImage(const TileKey& key, ProgressCallback* progress)
     {
         return 0L;
     }
@@ -162,60 +133,121 @@ public:
             return NULL;
         }
 
-        int tileSize = _options.tileSize().value();
+        int tileSize = _options.tileSize().value();        
 
-        //Allocate the heightfield
-        osg::ref_ptr<osg::HeightField> hf = new osg::HeightField;
-        hf->allocate(tileSize, tileSize);
-        for (unsigned int i = 0; i < hf->getHeightList().size(); ++i) hf->getHeightList()[i] = NO_DATA_VALUE;
-
-        if (intersects(key))
+	    if (intersects(key))
         {
             //Get the extents of the tile
             double xmin, ymin, xmax, ymax;
             key.getExtent().getBounds(xmin, ymin, xmax, ymax);
 
-            // Iterate over the output heightfield and sample the data that was read into it.
-            double dx = (xmax - xmin) / (tileSize-1);
-            double dy = (ymax - ymin) / (tileSize-1);
+            const SpatialReference* featureSRS = _features->getFeatureProfile()->getSRS();
+            GeoExtent extentInFeatureSRS = key.getExtent().transform( featureSRS );
+
+            const SpatialReference* keySRS = key.getProfile()->getSRS();
+            
+            // populate feature list
+            // assemble a spatial query. It helps if your features have a spatial index.
+            Query query;
+            query.bounds() = extentInFeatureSRS.bounds();
 
-            for (int c = 0; c < tileSize; ++c)
+		    FeatureList featureList;
+            osg::ref_ptr<FeatureCursor> cursor = _features->createFeatureCursor(query);
+            while ( cursor.valid() && cursor->hasMore() )
             {
-                double geoX = xmin + (dx * (double)c);
-                for (int r = 0; r < tileSize; ++r)
-                {
-                    double geoY = ymin + (dy * (double)r);
-
-                    float h = NO_DATA_VALUE;
-
-
-                    for (FeatureList::iterator f = _featureList.begin(); f != _featureList.end(); ++f)
-                    {
-                        osgEarth::Symbology::Polygon* p = dynamic_cast<osgEarth::Symbology::Polygon*>((*f)->getGeometry());
-
-                        if (!p)
-                        {
-                            OE_WARN << LC << "NOT A POLYGON" << std::endl;
-                        }
-                        else
-                        {
-                            GeoPoint geo(key.getProfile()->getSRS(), geoX, geoY);
-                            if (!key.getProfile()->getSRS()->isEquivalentTo(getProfile()->getSRS()))
-                                geo.transform(getProfile()->getSRS());
-                            
-                            if (p->contains2D(geo.x(), geo.y()))
-                            {
-                                h = (*f)->getDouble(_options.attr().value());
-                                break;
-                            }
-                        }
-                    }
-
-                    hf->setHeight(c, r, h);
-                }
+                Feature* f = cursor->nextFeature();
+                if ( f && f->getGeometry() )
+                    featureList.push_back(f);
             }
+
+            // We now have a feature list in feature SRS.
+
+            bool transformRequired = !keySRS->isHorizEquivalentTo(featureSRS);
+		    
+			if (!featureList.empty())
+			{
+                //Only allocate the heightfield if we actually intersect any features.
+                osg::ref_ptr<osg::HeightField> hf = new osg::HeightField;
+                hf->allocate(tileSize, tileSize);
+                for (unsigned int i = 0; i < hf->getHeightList().size(); ++i) hf->getHeightList()[i] = NO_DATA_VALUE;
+
+				// Iterate over the output heightfield and sample the data that was read into it.
+				double dx = (xmax - xmin) / (tileSize-1);
+				double dy = (ymax - ymin) / (tileSize-1);
+
+				for (int c = 0; c < tileSize; ++c)
+				{
+					double geoX = xmin + (dx * (double)c);
+					for (int r = 0; r < tileSize; ++r)
+					{
+						double geoY = ymin + (dy * (double)r);
+
+						float h = NO_DATA_VALUE;
+
+						for (FeatureList::iterator f = featureList.begin(); f != featureList.end(); ++f)
+						{
+							osgEarth::Symbology::Polygon* boundary = dynamic_cast<osgEarth::Symbology::Polygon*>((*f)->getGeometry());
+
+							if (!boundary)
+							{
+								OE_WARN << LC << "NOT A POLYGON" << std::endl;
+							}
+							else
+							{
+								GeoPoint geo(keySRS, geoX, geoY, 0.0, ALTMODE_ABSOLUTE);
+
+                                if ( transformRequired )
+                                    geo = geo.transform(featureSRS);
+
+								if ( boundary->contains2D(geo.x(), geo.y()) )
+								{
+                                    h = (*f)->getDouble(_options.attr().value());
+
+                                    if ( keySRS->isGeographic() )
+                                    {                              
+                                        // for a round earth, must adjust the final elevation accounting for the
+                                        // curvature of the earth; so we have to adjust it in the feature boundary's
+                                        // local tangent plane.
+                                        Bounds bounds = boundary->getBounds();
+                                        GeoPoint anchor( featureSRS, bounds.center().x(), bounds.center().y(), h, ALTMODE_ABSOLUTE );
+                                        if ( transformRequired )
+                                            anchor = anchor.transform(keySRS);
+
+                                        // For transforming between ECEF and local tangent plane:
+                                        osg::Matrix localToWorld, worldToLocal;
+                                        anchor.createLocalToWorld(localToWorld);
+                                        worldToLocal.invert( localToWorld );
+
+                                        // Get the ECEF location of the anchor point:
+                                        osg::Vec3d ecef;
+                                        geo.toWorld( ecef );
+
+                                        // Move it into Local Tangent Plane coordinates:
+                                        osg::Vec3d local = ecef * worldToLocal;
+
+                                        // Reset the Z to zero, since the LTP is centered on the "h" elevation:
+                                        local.z() = 0.0;
+
+                                        // Back into ECEF:
+                                        ecef = local * localToWorld;
+
+                                        // And back into lat/long/alt:
+                                        geo.fromWorld( geo.getSRS(), ecef);
+
+                                        h = geo.z();
+                                    }
+									break;
+								}
+							}
+						}
+
+						hf->setHeight(c, r, h + _offset);
+					}
+				}
+                return hf.release();
+			}	
         }
-        return hf.release();
+        return 0;        
     }
 
 
@@ -230,14 +262,11 @@ private:
     GeoExtent _extents;
 
     const FeatureElevationOptions _options;
-
     osg::ref_ptr<FeatureSource> _features;
-    FeatureList _featureList;
-
-    osg::ref_ptr< CacheBin > _cacheBin;
-    osg::ref_ptr< osgDB::Options > _dbOptions;
 
     unsigned int _maxDataLevel;
+
+    double _offset;
 };
 
 
@@ -246,7 +275,7 @@ class ReaderWriterFeatureElevationTile : public TileSourceDriver
 public:
     ReaderWriterFeatureElevationTile() {}
 
-    virtual const char* className()
+    virtual const char* className() const
     {
         return "Feature Elevation Tile Reader";
     }
diff --git a/src/osgEarthDrivers/feature_mapnikvectortiles/CMakeLists.txt b/src/osgEarthDrivers/feature_mapnikvectortiles/CMakeLists.txt
new file mode 100644
index 0000000..05c0fdc
--- /dev/null
+++ b/src/osgEarthDrivers/feature_mapnikvectortiles/CMakeLists.txt
@@ -0,0 +1,25 @@
+FIND_PACKAGE(Protobuf)
+
+IF(SQLITE3_FOUND AND PROTOBUF_FOUND AND PROTOBUF_PROTOC_EXECUTABLE)
+
+INCLUDE_DIRECTORIES( ${SQLITE3_INCLUDE_DIR} ${CMAKE_CURRENT_BINARY_DIR})
+
+SET(TARGET_SRC
+    FeatureSourceMVT.cpp    
+)
+
+SET(TARGET_H
+    MVTFeatureOptions
+)
+
+SET(TARGET_COMMON_LIBRARIES ${TARGET_COMMON_LIBRARIES} osgEarthFeatures osgEarthSymbology osgEarthUtil)
+SET(TARGET_LIBRARIES_VARS SQLITE3_LIBRARY)
+SETUP_PLUGIN(osgearth_feature_mapnikvectortiles)
+
+
+# to install public driver includes:
+SET(LIB_NAME feature_mapnikvectortiles)
+SET(LIB_PUBLIC_HEADERS ${TARGET_H})
+INCLUDE(ModuleInstallOsgEarthDriverIncludes OPTIONAL)
+
+ENDIF()
diff --git a/src/osgEarthDrivers/feature_mapnikvectortiles/FeatureSourceMVT.cpp b/src/osgEarthDrivers/feature_mapnikvectortiles/FeatureSourceMVT.cpp
new file mode 100644
index 0000000..eeb0f80
--- /dev/null
+++ b/src/osgEarthDrivers/feature_mapnikvectortiles/FeatureSourceMVT.cpp
@@ -0,0 +1,315 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+ * Copyright 2008-2014 Pelican Mapping
+ * http://osgearth.org
+ *
+ * osgEarth is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ */
+#include "MVTFeatureOptions"
+
+#include <osgEarth/Registry>
+#include <osgEarth/FileUtils>
+#include <osgEarth/GeoData>
+#include <osgEarthFeatures/FeatureSource>
+#include <osgEarthFeatures/MVT>
+#include <osgEarthFeatures/Filter>
+#include <osg/Notify>
+#include <osgDB/FileNameUtils>
+#include <osgDB/FileUtils>
+#include <list>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sqlite3.h>
+
+
+#define LC "[MVT FeatureSource] "
+
+using namespace osgEarth;
+using namespace osgEarth::Features;
+using namespace osgEarth::Drivers;
+
+
+class MVTFeatureSource : public FeatureSource
+{
+public:
+    MVTFeatureSource(const MVTFeatureOptions& options ) :
+      FeatureSource( options ),
+      _options     ( options ),
+      _minLevel(0),
+      _maxLevel(14),
+      _database(0L)
+    {
+        _compressor = osgDB::Registry::instance()->getObjectWrapperManager()->findCompressor("zlib");
+        if (!_compressor.valid())
+        {
+           OE_WARN << LC << "Failed to get zlib compressor" << std::endl;
+        }
+    }
+
+    /** Destruct the object, cleaning up and OGR handles. */
+    virtual ~MVTFeatureSource()
+    {               
+        //nop
+    }
+
+    FeatureCursor* createFeatureCursor( const Symbology::Query& query )
+    {
+        if (!query.tileKey().isSet())
+        {
+            OE_WARN << LC << "No tile key in query; no features will be returned\n";
+            return 0L;
+        }
+
+        TileKey key = *query.tileKey();
+
+        int z = key.getLevelOfDetail();
+        int tileX = key.getTileX();
+        int tileY = key.getTileY();
+
+        unsigned int numRows, numCols;
+        key.getProfile()->getNumTiles(key.getLevelOfDetail(), numCols, numRows);
+        tileY  = numRows - tileY - 1;
+
+        //Get the image
+        sqlite3_stmt* select = NULL;
+        std::string queryStr = "SELECT tile_data from tiles where zoom_level = ? AND tile_column = ? AND tile_row = ?";
+        int rc = sqlite3_prepare_v2( _database, queryStr.c_str(), -1, &select, 0L );
+        if ( rc != SQLITE_OK )
+        {
+            OE_WARN << LC << "Failed to prepare SQL: " << queryStr << "; " << sqlite3_errmsg(_database) << std::endl;
+            return NULL;
+        }
+
+        bool valid = true;        
+
+        sqlite3_bind_int( select, 1, z );
+        sqlite3_bind_int( select, 2, tileX );
+        sqlite3_bind_int( select, 3, tileY );
+
+        rc = sqlite3_step( select );
+
+        FeatureList features;
+
+        if ( rc == SQLITE_ROW)
+        {                     
+            // the pointer returned from _blob gets freed internally by sqlite, supposedly
+            const char* data = (const char*)sqlite3_column_blob( select, 0 );
+            int dataLen = sqlite3_column_bytes( select, 0 );
+            std::string dataBuffer( data, dataLen );
+            std::stringstream in(dataBuffer);
+            MVT::read(in, key, features);
+        }
+        else
+        {
+            OE_DEBUG << LC << "SQL QUERY failed for " << queryStr << ": " << std::endl;
+            valid = false;
+        }
+
+        sqlite3_finalize( select );
+
+        // apply filters before returning.
+        applyFilters( features, query.tileKey()->getExtent() );
+
+        // If we have any features and we have an fid attribute, override the fid of the features
+        if (_options.fidAttribute().isSet())
+        {
+            for (FeatureList::iterator itr = features.begin(); itr != features.end(); ++itr)
+            {
+                std::string attr = itr->get()->getString(_options.fidAttribute().get());                
+                FeatureID fid = as<long>(attr, 0);
+                itr->get()->setFID( fid );
+            }
+        }
+
+        if (!features.empty())
+        {
+            //OE_NOTICE << "Returning " << features.size() << " features" << std::endl;
+            return new FeatureListCursor(features);
+        }
+
+        return 0;
+    }
+
+    /**
+    * Gets the Feature with the given FID
+    * @returns
+    *     The Feature with the given FID or NULL if not found.
+    */
+    virtual Feature* getFeature( FeatureID fid )
+    {
+        return 0;
+    }
+
+    virtual bool isWritable() const
+    {
+        return false;
+    }
+
+    virtual const FeatureSchema& getSchema() const
+    {
+        //TODO:  Populate the schema from the DescribeFeatureType call
+        return _schema;
+    }
+
+    virtual osgEarth::Symbology::Geometry::Type getGeometryType() const
+    {
+        return Geometry::TYPE_UNKNOWN;
+    }
+
+    bool getMetaData(const std::string& key, std::string& value)
+    {
+        //get the metadata
+        sqlite3_stmt* select = NULL;
+        std::string query = "SELECT value from metadata where name = ?";
+        int rc = sqlite3_prepare_v2( _database, query.c_str(), -1, &select, 0L );
+        if ( rc != SQLITE_OK )
+        {
+            OE_WARN << LC << "Failed to prepare SQL: " << query << "; " << sqlite3_errmsg(_database) << std::endl;
+            return false;
+        }
+
+
+        bool valid = true;
+        std::string keyStr = std::string( key );
+        rc = sqlite3_bind_text( select, 1, keyStr.c_str(), keyStr.length(), SQLITE_STATIC );
+        if (rc != SQLITE_OK )
+        {
+            OE_WARN << LC << "Failed to bind text: " << query << "; " << sqlite3_errmsg(_database) << std::endl;
+            return false;
+        }
+
+        rc = sqlite3_step( select );
+        if ( rc == SQLITE_ROW)
+        {                     
+            value = (char*)sqlite3_column_text( select, 0 );
+        }
+        else
+        {
+            OE_DEBUG << LC << "SQL QUERY failed for " << query << ": " << std::endl;
+            valid = false;
+        }
+
+        sqlite3_finalize( select );
+        return valid;
+    }
+
+    void computeLevels()
+    {        
+
+        osg::Timer_t startTime = osg::Timer::instance()->tick();
+        sqlite3_stmt* select = NULL;
+        std::string query = "SELECT min(zoom_level), max(zoom_level) from tiles";
+        int rc = sqlite3_prepare_v2( _database, query.c_str(), -1, &select, 0L );
+        if ( rc != SQLITE_OK )
+        {
+            OE_WARN << LC << "Failed to prepare SQL: " << query << "; " << sqlite3_errmsg(_database) << std::endl;
+        }
+
+        rc = sqlite3_step( select );
+        if ( rc == SQLITE_ROW)
+        {                     
+            _minLevel = sqlite3_column_int( select, 0 );
+            _maxLevel = sqlite3_column_int( select, 1 );
+            OE_DEBUG << LC << "Min=" << _minLevel << " Max=" << _maxLevel << std::endl;
+        }
+        else
+        {
+            OE_DEBUG << LC << "SQL QUERY failed for " << query << ": " << std::endl;
+        }        
+        sqlite3_finalize( select );        
+        osg::Timer_t endTime = osg::Timer::instance()->tick();
+        OE_DEBUG << LC << "Computing levels took " << osg::Timer::instance()->delta_s(startTime, endTime ) << " s" << std::endl;
+    }
+
+protected:
+    //override
+    Status initialize(const osgDB::Options* readOptions)
+    {
+        _dbOptions = Registry::cloneOrCreateOptions(readOptions);
+        std::string fullFilename = _options.url()->full();
+
+        int rc = sqlite3_open_v2( fullFilename.c_str(), &_database, SQLITE_OPEN_READONLY, 0L );
+        if ( rc != 0 )
+        {          
+            return Status::Error(Status::ResourceUnavailable, Stringify() << "Failed to open database, " << sqlite3_errmsg(_database));
+        }
+
+        setFeatureProfile(createFeatureProfile());
+
+        return Status::OK();
+    }
+
+private:
+    const FeatureProfile* createFeatureProfile()
+    {
+        const osgEarth::Profile* profile = osgEarth::Registry::instance()->getSphericalMercatorProfile();
+        FeatureProfile* result = new FeatureProfile(profile->getExtent());
+        result->setTiled(true);
+        std::string minLevelStr, maxLevelStr;
+        if (getMetaData("minzoom", minLevelStr) && getMetaData("maxzoom", maxLevelStr))
+        {
+            _minLevel = as<int>(minLevelStr, 0);
+            _maxLevel = as<int>(maxLevelStr, 0);
+            OE_NOTICE << LC << "Got levels from metadata " << _minLevel << ", " << _maxLevel << std::endl;
+        }
+        else
+        {            
+            computeLevels();
+            OE_NOTICE << LC << "Got levels from database " << _minLevel << ", " << _maxLevel << std::endl;
+        }
+
+
+        result->setFirstLevel(_minLevel);
+        result->setMaxLevel(_maxLevel);
+        result->setProfile(profile);
+        result->geoInterp() = osgEarth::GEOINTERP_GREAT_CIRCLE;
+        return result;
+    }
+
+
+private:
+    const MVTFeatureOptions         _options;    
+    FeatureSchema                   _schema;
+    osg::ref_ptr<osgDB::Options>    _dbOptions;    
+    osg::ref_ptr<osgDB::BaseCompressor> _compressor;
+    sqlite3* _database;
+    unsigned int _minLevel;
+    unsigned int _maxLevel;
+};
+
+
+class MVTFeatureSourceFactory : public FeatureSourceDriver
+{
+public:
+    MVTFeatureSourceFactory()
+    {
+        supportsExtension( "osgearth_feature_mapnikvectortiles", "Mapnik Vector Tiles feature driver for osgEarth" );
+    }
+
+    virtual const char* className() const
+    {
+        return "Mapnik Vector Tiles Feature Reader";
+    }
+
+    virtual ReadResult readObject(const std::string& file_name, const Options* options) const
+    {
+        if ( !acceptsExtension(osgDB::getLowerCaseFileExtension( file_name )))
+            return ReadResult::FILE_NOT_HANDLED;
+
+        return ReadResult( new MVTFeatureSource( getFeatureSourceOptions(options) ) );
+    }
+};
+
+REGISTER_OSGPLUGIN(osgearth_feature_mapnikvectortiles, MVTFeatureSourceFactory)
+
diff --git a/src/osgEarthDrivers/feature_mapnikvectortiles/MVTFeatureOptions b/src/osgEarthDrivers/feature_mapnikvectortiles/MVTFeatureOptions
new file mode 100644
index 0000000..357086c
--- /dev/null
+++ b/src/osgEarthDrivers/feature_mapnikvectortiles/MVTFeatureOptions
@@ -0,0 +1,76 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+ * Copyright 2008-2014 Pelican Mapping
+ * http://osgearth.org
+ *
+ * osgEarth is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ */
+#ifndef OSGEARTH_DRIVER_MVT_FEATURE_SOURCE_OPTIONS
+#define OSGEARTH_DRIVER_MVT_FEATURE_SOURCE_OPTIONS 1
+
+#include <osgEarth/Common>
+#include <osgEarth/URI>
+#include <osgEarthFeatures/FeatureSource>
+
+namespace osgEarth { namespace Drivers
+{
+    using namespace osgEarth;
+    using namespace osgEarth::Features;
+
+    /**
+     * Options for the TFS feature driver.
+     */
+    class MVTFeatureOptions : public FeatureSourceOptions // NO EXPORT; header only
+    {
+    public:
+        /** Base URL of the TFS service */
+        optional<URI>& url() { return _url; }
+        const optional<URI>& url() const { return _url; }
+
+    public:
+        MVTFeatureOptions( const ConfigOptions& opt =ConfigOptions() ) :
+          FeatureSourceOptions( opt )
+          {
+            setDriver( "mapnikvectortiles" );            
+            fromConfig( _conf );
+        }
+
+        virtual ~MVTFeatureOptions() { }
+
+    public:
+        Config getConfig() const {
+            Config conf = FeatureSourceOptions::getConfig();
+            conf.updateIfSet( "url", _url ); 
+            return conf;
+        }
+
+    protected:
+        void mergeConfig( const Config& conf ) {
+            FeatureSourceOptions::mergeConfig( conf );
+            fromConfig( conf );
+        }
+
+    private:
+        void fromConfig( const Config& conf ) {
+            conf.getIfSet( "url", _url );
+        }
+
+        optional<URI>         _url;        
+        optional<std::string> _format;
+    };
+
+} } // namespace osgEarth::Drivers
+
+#endif // OSGEARTH_DRIVER_MVT_FEATURE_SOURCE_OPTIONS
+
diff --git a/src/osgEarthDrivers/feature_ogr/FeatureCursorOGR b/src/osgEarthDrivers/feature_ogr/FeatureCursorOGR
index 91b682d..5def968 100644
--- a/src/osgEarthDrivers/feature_ogr/FeatureCursorOGR
+++ b/src/osgEarthDrivers/feature_ogr/FeatureCursorOGR
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -75,6 +75,7 @@ private:
     std::queue< osg::ref_ptr<Feature> > _queue;
     osg::ref_ptr<Feature>               _lastFeatureReturned;
     const FeatureFilterList&            _filters;
+    bool                                _resultSetEndReached;
 
 private:
     void readChunk();    
diff --git a/src/osgEarthDrivers/feature_ogr/FeatureCursorOGR.cpp b/src/osgEarthDrivers/feature_ogr/FeatureCursorOGR.cpp
index aeab6db..30e93e5 100644
--- a/src/osgEarthDrivers/feature_ogr/FeatureCursorOGR.cpp
+++ b/src/osgEarthDrivers/feature_ogr/FeatureCursorOGR.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -20,6 +20,7 @@
 #include <osgEarthFeatures/OgrUtils>
 #include <osgEarthFeatures/Feature>
 #include <osgEarth/Registry>
+#include <osg/Math>
 #include <algorithm>
 
 #define LC "[FeatureCursorOGR] "
@@ -42,16 +43,22 @@ namespace
     }
 
     /**
-     * Checks to see if all points in the Geometry are valid.
+     * Checks to see if all points in the Geometry are valid, and makes minor repairs
+     * if necessary. Returns false if the geometry cannot be validated.
      */
-    inline bool isGeometryValid( Geometry* geometry )
+    inline bool validateGeometry( Geometry* geometry )
     {        
         if (!geometry) return false;
 
         if (!geometry->isValid()) return false;
 
-        for (Geometry::const_iterator i = geometry->begin(); i != geometry->end(); ++i)
+        for (Geometry::iterator i = geometry->begin(); i != geometry->end(); ++i)
         {
+            // a "NaN" Z value is automatically changed to zero:
+            if (osg::isNaN(i->z()))
+                i->z() = 0.0;
+
+            // then we test for a valid point.
             if (!isPointValid( *i ))
             {
                 return false;
@@ -76,6 +83,7 @@ _spatialFilter    ( 0L ),
 _query            ( query ),
 _chunkSize        ( 500 ),
 _nextHandleToQueue( 0L ),
+_resultSetEndReached(false),
 _profile          ( profile ),
 _filters          ( filters )
 {
@@ -89,17 +97,18 @@ _filters          ( filters )
         std::string driverName = OGR_Dr_GetName( OGR_DS_GetDriver( dsHandle ) );             
         // Quote the layer name if it is a shapefile, so we can handle any weird filenames like those with spaces or hyphens.
         // Or quote any layers containing spaces for PostgreSQL
-        if (driverName == "ESRI Shapefile" || from.find(" ") != std::string::npos)
-        {                        
+        if (driverName == "ESRI Shapefile" || driverName == "VRT" ||
+            from.find(" ") != std::string::npos)
+        {
             std::string delim = "\"";
-            from = delim + from + delim;                    
+            from = delim + from + delim;
         }
 
-        if ( query.expression().isSet() )
+        if ( _query.expression().isSet() )
         {
             // build the SQL: allow the Query to include either a full SQL statement or
             // just the WHERE clause.
-            expr = query.expression().value();
+            expr = _query.expression().value();
 
             // if the expression is just a where clause, expand it into a complete SQL expression.
             std::string temp = osgEarth::toLower(expr);
@@ -121,9 +130,9 @@ _filters          ( filters )
         }
 
         //Include the order by clause if it's set
-        if (query.orderby().isSet())
+        if (_query.orderby().isSet())
         {                     
-            std::string orderby = query.orderby().value();
+            std::string orderby = _query.orderby().value();
             
             std::string temp = osgEarth::toLower(orderby);
 
@@ -138,15 +147,22 @@ _filters          ( filters )
             expr += (" " + orderby );
         }
 
+        // if the tilekey is set, convert it to feature profile coords
+        if ( _query.tileKey().isSet() && !_query.bounds().isSet() && profile )
+        {
+            GeoExtent localEx = _query.tileKey()->getExtent().transform( profile->getSRS() );
+            _query.bounds() = localEx.bounds();
+        }
+
         // if there's a spatial extent in the query, build the spatial filter:
-        if ( query.bounds().isSet() )
+        if ( _query.bounds().isSet() )
         {
             OGRGeometryH ring = OGR_G_CreateGeometry( wkbLinearRing );
-            OGR_G_AddPoint(ring, query.bounds()->xMin(), query.bounds()->yMin(), 0 );
-            OGR_G_AddPoint(ring, query.bounds()->xMin(), query.bounds()->yMax(), 0 );
-            OGR_G_AddPoint(ring, query.bounds()->xMax(), query.bounds()->yMax(), 0 );
-            OGR_G_AddPoint(ring, query.bounds()->xMax(), query.bounds()->yMin(), 0 );
-            OGR_G_AddPoint(ring, query.bounds()->xMin(), query.bounds()->yMin(), 0 );
+            OGR_G_AddPoint(ring, _query.bounds()->xMin(), _query.bounds()->yMin(), 0 );
+            OGR_G_AddPoint(ring, _query.bounds()->xMin(), _query.bounds()->yMax(), 0 );
+            OGR_G_AddPoint(ring, _query.bounds()->xMax(), _query.bounds()->yMax(), 0 );
+            OGR_G_AddPoint(ring, _query.bounds()->xMax(), _query.bounds()->yMin(), 0 );
+            OGR_G_AddPoint(ring, _query.bounds()->xMin(), _query.bounds()->yMin(), 0 );
 
             _spatialFilter = OGR_G_CreateGeometry( wkbPolygon );
             OGR_G_AddGeometryDirectly( _spatialFilter, ring ); 
@@ -186,7 +202,7 @@ FeatureCursorOGR::~FeatureCursorOGR()
 bool
 FeatureCursorOGR::hasMore() const
 {
-    return _resultSetHandle && ( _queue.size() > 0 || _nextHandleToQueue != 0L );
+    return _resultSetHandle && _queue.size() > 0;
 }
 
 Feature*
@@ -195,7 +211,7 @@ FeatureCursorOGR::nextFeature()
     if ( !hasMore() )
         return 0L;
 
-    if ( _queue.size() == 0 && _nextHandleToQueue )
+    if ( _queue.size() == 1u )
         readChunk();
 
     // do this in order to hold a reference to the feature we return, so the caller
@@ -207,7 +223,6 @@ FeatureCursorOGR::nextFeature()
     return _lastFeatureReturned.get();
 }
 
-
 // reads a chunk of features into a memory cache; do this for performance
 // and to avoid needing the OGR Mutex every time
 void
@@ -216,86 +231,57 @@ FeatureCursorOGR::readChunk()
     if ( !_resultSetHandle )
         return;
     
-    FeatureList preProcessList;
-    
     OGR_SCOPED_LOCK;
 
-    if ( _nextHandleToQueue )
+    while( _queue.size() < _chunkSize && !_resultSetEndReached )
     {
-        osg::ref_ptr<Feature> f = OgrUtils::createFeature( _nextHandleToQueue, _profile.get() );
-        if ( f.valid() && !_source->isBlacklisted(f->getFID()) )
+        FeatureList filterList;
+        while( filterList.size() < _chunkSize && !_resultSetEndReached )
         {
-            if ( isGeometryValid( f->getGeometry() ) )
+            OGRFeatureH handle = OGR_L_GetNextFeature( _resultSetHandle );
+            if ( handle )
             {
-                _queue.push( f );
+                osg::ref_ptr<Feature> feature = OgrUtils::createFeature( handle, _profile.get() );
 
-                if ( _filters.size() > 0 )
+                if (feature.valid() &&
+                    !_source->isBlacklisted( feature->getFID() ) &&
+                    validateGeometry( feature->getGeometry() ))
                 {
-                    preProcessList.push_back( f.release() );
+                    filterList.push_back( feature.release() );
                 }
+                OGR_F_Destroy( handle );
             }
             else
             {
-                OE_DEBUG << LC << "Skipping feature with invalid geometry: " << f->getGeoJSON() << std::endl;
+                _resultSetEndReached = true;
             }
         }
-        OGR_F_Destroy( _nextHandleToQueue );
-        _nextHandleToQueue = 0L;
-    }
 
-    unsigned handlesToQueue = _chunkSize - _queue.size();
-    bool resultSetEndReached = false;
-
-    for( unsigned i=0; i<handlesToQueue; i++ )
-    {
-        OGRFeatureH handle = OGR_L_GetNextFeature( _resultSetHandle );
-        if ( handle )
+        // preprocess the features using the filter list:
+        if ( !_filters.empty() )
         {
-            osg::ref_ptr<Feature> f = OgrUtils::createFeature( handle, _profile.get() );
-            if ( f.valid() && !_source->isBlacklisted(f->getFID()) )
+            FilterContext cx;
+            cx.setProfile( _profile.get() );
+            if (_query.bounds().isSet())
             {
-                if (isGeometryValid( f->getGeometry() ) )
-                {
-                    _queue.push( f );
+                cx.extent() = GeoExtent(_profile->getSRS(), _query.bounds().get());
+            }
+            else
+            {
+                cx.extent() = _profile->getExtent();
+            }
 
-                    if ( _filters.size() > 0 )
-                    {
-                        preProcessList.push_back( f.release() );
-                    }
-                }
-                else
-                {
-                    OE_DEBUG << LC << "Skipping feature with invalid geometry: " << f->getGeoJSON() << std::endl;
-                }
-            }            
-            OGR_F_Destroy( handle );
-        }
-        else
-        {
-            resultSetEndReached = true;
-            break;
+            for( FeatureFilterList::const_iterator i = _filters.begin(); i != _filters.end(); ++i )
+            {
+                FeatureFilter* filter = i->get();
+                cx = filter->push( filterList, cx );
+            }
         }
-    }
 
-    // preprocess the features using the filter list:
-    if ( preProcessList.size() > 0 )
-    {
-        FilterContext cx;
-        cx.setProfile( _profile.get() );
-
-        for( FeatureFilterList::const_iterator i = _filters.begin(); i != _filters.end(); ++i )
+        for(FeatureList::const_iterator i = filterList.begin(); i != filterList.end(); ++i)
         {
-            FeatureFilter* filter = i->get();
-            cx = filter->push( preProcessList, cx );
+            _queue.push( i->get() );
         }
     }
-
-    // read one more for "more" detection:
-    if (!resultSetEndReached)
-        _nextHandleToQueue = OGR_L_GetNextFeature( _resultSetHandle );
-    else
-        _nextHandleToQueue = 0L;
-
-    //OE_NOTICE << "read " << _queue.size() << " features ... " << std::endl;
 }
 
diff --git a/src/osgEarthDrivers/feature_ogr/FeatureSourceOGR.cpp b/src/osgEarthDrivers/feature_ogr/FeatureSourceOGR.cpp
index 3a5826f..a52c405 100644
--- a/src/osgEarthDrivers/feature_ogr/FeatureSourceOGR.cpp
+++ b/src/osgEarthDrivers/feature_ogr/FeatureSourceOGR.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -74,7 +74,8 @@ public:
       _options( options ),
       _featureCount(-1),
       _needsSync(false),
-      _writable(false)
+      _writable(false),
+      _geometryType(Geometry::TYPE_UNKNOWN)
     {
         //nop
     }
@@ -108,35 +109,41 @@ public:
     }
 
     //override
-    void initialize( const osgDB::Options* dbOptions )
+    Status initialize(const osgDB::Options* dbOptions)
     {
+        // Data source at a URL?
         if ( _options.url().isSet() )
         {
             _source = _options.url()->full();
-            if (osgEarth::endsWith(_source, ".zip", false) ||
-                _source.find(".zip/") != std::string::npos)
+
+            // ..inside a zip file?
+            if (osgEarth::endsWith(_source, ".zip", false) || _source.find(".zip/") != std::string::npos)
             {
                 _source = Stringify() << "/vsizip/" << _source;
             }
         }
+
+        // ..or database connection?
         else if ( _options.connection().isSet() )
         {
             _source = _options.connection().value();
         }
         
-        // establish the geometry:
+        // ..or inline geometry?
         _geometry = 
             _options.geometry().valid()       ? _options.geometry().get() :
             _options.geometryConfig().isSet() ? parseGeometry( *_options.geometryConfig() ) :
             _options.geometryUrl().isSet()    ? parseGeometryUrl( *_options.geometryUrl(), dbOptions ) :
             0L;
-    }
 
-    /** Called once at startup to create the profile for this feature set. Successful profile
-        creation implies that the datasource opened succesfully. */
-    const FeatureProfile* createFeatureProfile()
-    {
-        FeatureProfile* result = 0L;
+        // If nothing was set, we're done
+        if (_source.empty() && !_geometry.valid())
+        {
+            return Status::Error(Status::ConfigurationError, "No URL, connection, or inline geometry provided");
+        }
+
+        // Try to open the datasource and establish a feature profile.        
+        FeatureProfile* featureProfile = 0L;
 
         // see if we have a custom profile.
         osg::ref_ptr<const Profile> profile;
@@ -152,7 +159,6 @@ public:
             GeoExtent ex;
             if ( profile.valid() )
             {                
-                //ex = profile->getExtent();
                 ex = GeoExtent(profile->getSRS(), _geometry->getBounds());
             }
 
@@ -161,163 +167,163 @@ public:
                 // default to WGS84 Lat/Long
                 ex = osgEarth::Registry::instance()->getGlobalGeodeticProfile()->getExtent();
             }
-            result = new FeatureProfile( ex );
+
+            featureProfile = new FeatureProfile( ex );
         }
 
         else if ( !_source.empty() )
         {
-            // otherwise, assume we're loading from the URL:
+            // otherwise, assume we're loading from the URL/connection:
             OGR_SCOPED_LOCK;
 
             // load up the driver, defaulting to shapefile if unspecified.
             std::string driverName = _options.ogrDriver().value();
             if ( driverName.empty() )
                 driverName = "ESRI Shapefile";
+
             _ogrDriverHandle = OGRGetDriverByName( driverName.c_str() );
 
             // attempt to open the dataset:
             int openMode = _options.openWrite().isSet() && _options.openWrite().value() ? 1 : 0;
 
-            _dsHandle = OGROpen( _source.c_str(), openMode, &_ogrDriverHandle );
-            if ( _dsHandle )
-            {
-                if (openMode == 1) _writable = true;
+            _dsHandle = OGROpenShared( _source.c_str(), openMode, &_ogrDriverHandle );
+            if ( !_dsHandle )
+                return Status::Error(Status::ResourceUnavailable, Stringify() << "Failed to open \"" << _source << "\"");
+
+            if (openMode == 1)
+                _writable = true;
                 
-                _layerHandle = openLayer(_dsHandle, _options.layer().value());
+            // Open a specific layer within the data source, if applicable:
+            _layerHandle = openLayer(_dsHandle, _options.layer().value());
+            if ( !_layerHandle )
+                return Status::Error(Status::ResourceUnavailable, Stringify() << "Failed to open layer \"" << _options.layer().get() << "\" from \"" << _source << "\"");
 
-                if ( _layerHandle )
-                {                                     
-                    GeoExtent extent;
 
-                    // if the user provided a profile, user that:
-                    if ( profile.valid() )
-                    {
-                        result = new FeatureProfile( profile->getExtent() );
-                    }
+            // if the user provided a profile, use that:
+            if ( profile.valid() )
+            {
+                featureProfile = new FeatureProfile( profile->getExtent() );
+            }
 
-                    else
-                    {
-                        // extract the SRS and Extent:                
-                        OGRSpatialReferenceH srHandle = OGR_L_GetSpatialRef( _layerHandle );
-                        if ( srHandle )
-                        {
-                            osg::ref_ptr<SpatialReference> srs = SpatialReference::createFromHandle( srHandle, false );
-                            if ( srs.valid() )
-                            {
-                                // extract the full extent of the layer:
-                                OGREnvelope env;
-                                if ( OGR_L_GetExtent( _layerHandle, &env, 1 ) == OGRERR_NONE )
-                                {
-                                    GeoExtent extent( srs.get(), env.MinX, env.MinY, env.MaxX, env.MaxY );
-                                    if ( extent.isValid() )
-                                    {                                    
-                                        // got enough info to make the profile!
-                                        result = new FeatureProfile( extent );
-                                    }
-                                    else
-                                    {
-                                        OE_WARN << LC << "Extent returned from OGR was invalid.\n";
-                                    }
-                                }
-                            }
-                        }
-                    }
+            // otherwise extract one from the layer:
+            else
+            {
+                // extract the SRS and Extent:                
+                OGRSpatialReferenceH srHandle = OGR_L_GetSpatialRef( _layerHandle );
+                if (!srHandle)
+                    return Status::Error(Status::ResourceUnavailable, Stringify() << "No spatial reference found in \"" << _source << "\"");
+
+                osg::ref_ptr<SpatialReference> srs = SpatialReference::createFromHandle( srHandle, false );
+                if (!srs.valid())
+                    return Status::Error(Status::ResourceUnavailable, Stringify() << "Unrecognized SRS found in \"" << _source << "\"");
+
+                // extract the full extent of the layer:
+                OGREnvelope env;
+                if ( OGR_L_GetExtent( _layerHandle, &env, 1 ) != OGRERR_NONE )
+                    return Status::Error(Status::ResourceUnavailable, Stringify() << "Invalid extent returned from \"" << _source << "\"");
+
+                GeoExtent extent( srs.get(), env.MinX, env.MinY, env.MaxX, env.MaxY );
+                if ( !extent.isValid() )
+                    return Status::Error(Status::ResourceUnavailable, Stringify() << "Invalid extent returned from \"" << _source << "\"");
+
+                // Made it!
+                featureProfile = new FeatureProfile(extent);
+            }
 
-                    // assuming we successfully opened the layer, build a spatial index if requested.
-                    if ( _options.buildSpatialIndex() == true )
-                    {
-                        if ( (_options.forceRebuildSpatialIndex() == true) || (OGR_L_TestCapability(_layerHandle, OLCFastSpatialFilter) == 0) )
-                        {
-                            OE_INFO << LC << "Building spatial index for " << getName() << std::endl;
-                            std::stringstream buf;
-                            const char* name = OGR_FD_GetName( OGR_L_GetLayerDefn( _layerHandle ) );
-                            buf << "CREATE SPATIAL INDEX ON " << name;
-                            std::string bufStr;
-                            bufStr = buf.str();
-                            OE_DEBUG << LC << "SQL: " << bufStr << std::endl;
-                            OGR_DS_ExecuteSQL( _dsHandle, bufStr.c_str(), 0L, 0L );
-                        }
-                        else
-                        {
-                            OE_INFO << LC << "Use existing spatial index for " << getName() << std::endl;
-                        }
-                    }
 
-                    //Get the feature count
-                    _featureCount = OGR_L_GetFeatureCount( _layerHandle, 1 );
+            // assuming we successfully opened the layer, build a spatial index if requested.
+            if ( _options.buildSpatialIndex() == true )
+            {
+                if ( (_options.forceRebuildSpatialIndex() == true) || (OGR_L_TestCapability(_layerHandle, OLCFastSpatialFilter) == 0) )
+                {
+                    OE_INFO << LC << "Building spatial index for " << getName() << std::endl;
+                    std::stringstream buf;
+                    const char* name = OGR_FD_GetName( OGR_L_GetLayerDefn( _layerHandle ) );
+                    buf << "CREATE SPATIAL INDEX ON " << name;
+                    std::string bufStr;
+                    bufStr = buf.str();
+                    OE_DEBUG << LC << "SQL: " << bufStr << std::endl;
+                    OGR_DS_ExecuteSQL( _dsHandle, bufStr.c_str(), 0L, 0L );
+                }
+                else
+                {
+                    OE_INFO << LC << "Use existing spatial index for " << getName() << std::endl;
+                }
+            }
 
-                    initSchema();
 
-                    OGRwkbGeometryType wkbType = OGR_FD_GetGeomType( OGR_L_GetLayerDefn( _layerHandle ) );
-                    if (
-                        wkbType == wkbPolygon ||
-                        wkbType == wkbPolygon25D )
-                    {
-                        _geometryType = Geometry::TYPE_POLYGON;
-                    }
-                    else if (
-                        wkbType == wkbLineString ||
-                        wkbType == wkbLineString25D )
-                    {
-                        _geometryType = Geometry::TYPE_LINESTRING;
-                    }
-                    else if (
-                        wkbType == wkbLinearRing )
-                    {
-                        _geometryType = Geometry::TYPE_RING;
-                    }
-                    else if ( 
-                        wkbType == wkbPoint ||
-                        wkbType == wkbPoint25D )
-                    {
-                        _geometryType = Geometry::TYPE_POINTSET;
-                    }
-                    else if (
-                        wkbType == wkbGeometryCollection ||
-                        wkbType == wkbGeometryCollection25D ||
-                        wkbType == wkbMultiPoint ||
-                        wkbType == wkbMultiPoint25D ||
-                        wkbType == wkbMultiLineString ||
-                        wkbType == wkbMultiLineString25D ||
-                        wkbType == wkbMultiPolygon ||
-                        wkbType == wkbMultiPolygon25D )
-                    {
-                        _geometryType = Geometry::TYPE_MULTI;
-                    }
-                }
+            //Get the feature count
+            _featureCount = OGR_L_GetFeatureCount( _layerHandle, 1 );
+
+            // establish the feature schema:
+            initSchema();
+
+            // establish the geometry type for this feature layer:
+            OGRwkbGeometryType wkbType = OGR_FD_GetGeomType( OGR_L_GetLayerDefn( _layerHandle ) );
+            if (
+                wkbType == wkbPolygon ||
+                wkbType == wkbPolygon25D )
+            {
+                _geometryType = Geometry::TYPE_POLYGON;
             }
-            else
+            else if (
+                wkbType == wkbLineString ||
+                wkbType == wkbLineString25D )
             {
-                OE_INFO << LC << "failed to open dataset at \"" << _source << "\" error " << CPLGetLastErrorMsg() << std::endl;
+                _geometryType = Geometry::TYPE_LINESTRING;
+            }
+            else if (
+                wkbType == wkbLinearRing )
+            {
+                _geometryType = Geometry::TYPE_RING;
+            }
+            else if ( 
+                wkbType == wkbPoint ||
+                wkbType == wkbPoint25D )
+            {
+                _geometryType = Geometry::TYPE_POINTSET;
+            }
+            else if (
+                wkbType == wkbGeometryCollection ||
+                wkbType == wkbGeometryCollection25D ||
+                wkbType == wkbMultiPoint ||
+                wkbType == wkbMultiPoint25D ||
+                wkbType == wkbMultiLineString ||
+                wkbType == wkbMultiLineString25D ||
+                wkbType == wkbMultiPolygon ||
+                wkbType == wkbMultiPolygon25D )
+            {
+                _geometryType = Geometry::TYPE_MULTI;
             }
-        }
-        else
-        {
-            OE_INFO << LC 
-                << "Feature Source: no valid source data available" << std::endl;
         }
 
-        if ( result )
+        // finally, if we're establish a profile, set it for this source.
+        if ( featureProfile )
         {
             if ( _options.geoInterp().isSet() )
             {
-                result->geoInterp() = _options.geoInterp().get();
+                featureProfile->geoInterp() = _options.geoInterp().get();
             }
+            setFeatureProfile(featureProfile);
         }
 
-        return result;
-    }
+        else
+        {
+            return Status::Error(Status::ResourceUnavailable, "Failed to establish a valid feature profile");
+        }
 
+        return Status::OK();
+    }
 
     //override
-    FeatureCursor* createFeatureCursor( const Symbology::Query& query )
+    FeatureCursor* createFeatureCursor(const Symbology::Query& query)
     {
         if ( _geometry.valid() )
         {
             return new GeometryFeatureCursor(
                 _geometry.get(),
                 getFeatureProfile(),
-                _options.filters() );
+                getFilters() );
         }
         else
         {
@@ -346,7 +352,7 @@ public:
                     this,
                     getFeatureProfile(),
                     query,
-                    _options.filters() );
+                    getFilters() );
             }
             else
             {
@@ -389,7 +395,7 @@ public:
     {
         Feature* result = NULL;
 
-        if ( !isBlacklisted(fid) )
+        if ( _layerHandle && !isBlacklisted(fid) )
         {
             OGR_SCOPED_LOCK;
             OGRFeatureH handle = OGR_L_GetFeature( _layerHandle, fid);
@@ -546,7 +552,7 @@ public:
         supportsExtension( "osgearth_feature_ogr", "OGR feature driver for osgEarth" );
     }
 
-    virtual const char* className()
+    virtual const char* className() const
     {
         return "OGR Feature Reader";
     }
diff --git a/src/osgEarthDrivers/feature_ogr/OGRFeatureOptions b/src/osgEarthDrivers/feature_ogr/OGRFeatureOptions
index 1b42972..b3fbd37 100644
--- a/src/osgEarthDrivers/feature_ogr/OGRFeatureOptions
+++ b/src/osgEarthDrivers/feature_ogr/OGRFeatureOptions
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthDrivers/feature_raster/FeatureSourceRaster.cpp b/src/osgEarthDrivers/feature_raster/FeatureSourceRaster.cpp
index e798faa..93d7753 100644
--- a/src/osgEarthDrivers/feature_raster/FeatureSourceRaster.cpp
+++ b/src/osgEarthDrivers/feature_raster/FeatureSourceRaster.cpp
@@ -49,34 +49,9 @@ public:
         //nop
     }
 
-    //override
-    void initialize( const osgDB::Options* dbOptions )
-    {
-        _dbOptions = dbOptions ? osg::clone(dbOptions) : 0L;
-    }
-
-
-    /** Called once at startup to create the profile for this feature set. Successful profile
-        creation implies that the datasource opened succesfully. */
-    const FeatureProfile* createFeatureProfile()
-    {
-        const Profile* wgs84 = Registry::instance()->getGlobalGeodeticProfile();
-        //GeoExtent extent(wgs84->getSRS(), -180, -90, 0, 90);
-        GeoExtent extent(wgs84->getSRS(), -180, -90, 180, 90);
-        FeatureProfile* profile = new FeatureProfile( extent );
-        profile->setProfile( Profile::create("wgs84", extent.xMin(), extent.yMin(), extent.xMax(), extent.yMax(), "", 1, 1) );
-        unsigned int level = *_options.level();
-        profile->setFirstLevel(level);
-        profile->setMaxLevel(level);
-        profile->setTiled(true);
-        return profile;
-    }
-
     FeatureCursor* createFeatureCursor( const Symbology::Query& query )
     {
-        unsigned w, h;
-        query.tileKey()->getProfile()->getNumTiles( query.tileKey()->getLevelOfDetail(), w, h );      
-        TileKey key = TileKey(query.tileKey()->getLevelOfDetail(), query.tileKey()->getTileX(), h - query.tileKey()->getTileY() -1, query.tileKey()->getProfile() );
+        TileKey key = *query.tileKey();
 
 #if 0
         // Debug
@@ -208,6 +183,27 @@ public:
         return Geometry::TYPE_UNKNOWN;
     }
 
+protected:
+
+    //override
+    Status initialize(const osgDB::Options* readOptions)
+    {
+        _dbOptions = Registry::cloneOrCreateOptions(readOptions);
+        
+        // Establish the feature profile.
+        const Profile* wgs84 = Registry::instance()->getGlobalGeodeticProfile();
+        GeoExtent extent(wgs84->getSRS(), -180, -90, 180, 90);
+
+        FeatureProfile* profile = new FeatureProfile( extent );
+        profile->setProfile( Profile::create("wgs84", extent.xMin(), extent.yMin(), extent.xMax(), extent.yMax(), "", 1, 1) );
+        unsigned int level = _options.level().get();
+        profile->setFirstLevel(level);
+        profile->setMaxLevel(level);
+        profile->setTiled(true);
+
+        setFeatureProfile(profile);
+        return Status::OK();
+    }
 
 
 private:
@@ -225,7 +221,7 @@ public:
         supportsExtension( "osgearth_feature_raster", "Raster feature driver for osgEarth" );
     }
 
-    virtual const char* className()
+    virtual const char* className() const
     {
         return "Raster Feature Reader";
     }
diff --git a/src/osgEarthDrivers/feature_tfs/FeatureSourceTFS.cpp b/src/osgEarthDrivers/feature_tfs/FeatureSourceTFS.cpp
index a9859e1..f1f5631 100644
--- a/src/osgEarthDrivers/feature_tfs/FeatureSourceTFS.cpp
+++ b/src/osgEarthDrivers/feature_tfs/FeatureSourceTFS.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -25,6 +25,7 @@
 #include <osgEarthFeatures/Filter>
 #include <osgEarthFeatures/BufferFilter>
 #include <osgEarthFeatures/ScaleFilter>
+#include <osgEarthFeatures/MVT>
 #include <osgEarthFeatures/OgrUtils>
 #include <osgEarthUtil/TFS>
 #include <osg/Notify>
@@ -70,117 +71,117 @@ public:
     }
 
     //override
-    void initialize( const osgDB::Options* dbOptions )
-    {
-        _dbOptions = dbOptions ? osg::clone(dbOptions) : 0L;
-        if ( _dbOptions.valid() )
-        {
-            // Set up a Custom caching bin for this source:
-            Cache* cache = Cache::get( _dbOptions.get() );
-            if ( cache )
-            {
-                Config optionsConf = _options.getConfig();
-
-                std::string binId = Stringify() << std::hex << hashString(optionsConf.toJSON()) << "_tfs";
-                _cacheBin = cache->addBin( binId );
-                if ( _cacheBin.valid() )
-                {                
-                    // write a metadata record just for reference purposes.. we don't actually use it
-                    Config metadata = _cacheBin->readMetadata();
-                    if ( metadata.empty() )
-                    {
-                        _cacheBin->writeMetadata( optionsConf );
-                    }
+    Status initialize(const osgDB::Options* readOptions)
+    { 
+        // make a local copy of the read options.
+        _readOptions = Registry::cloneOrCreateOptions(readOptions);
+
+        FeatureProfile* fp = 0L;
+
+        // Try to read the TFS metadata:
+        _layerValid = TFSReaderWriter::read(_options.url().get(), _readOptions.get(), _layer);
 
-                    if ( _cacheBin.valid() )
-                    {
-                        _cacheBin->apply( _dbOptions.get() );
-                    }
-                }
-                else
-                {
-                    OE_INFO << LC << "Failed to open cache bin \"" << binId << "\"\n";
-                }
-            }
-        }     
-        _layerValid = TFSReaderWriter::read(_options.url().get(), _dbOptions.get(), _layer);
         if (_layerValid)
         {
             OE_INFO << LC <<  "Read layer TFS " << _layer.getTitle() << " " << _layer.getAbstract() << " " << _layer.getFirstLevel() << " " << _layer.getMaxLevel() << " " << _layer.getExtent().toString() << std::endl;
-        }
-    }
 
-
-    /** Called once at startup to create the profile for this feature set. Successful profile
-        creation implies that the datasource opened succesfully. */
-    const FeatureProfile* createFeatureProfile()
-    {
-        FeatureProfile* result = NULL;
-        if (_layerValid)
+            fp = new FeatureProfile(_layer.getExtent());
+            fp->setTiled( true );
+            fp->setFirstLevel( _layer.getFirstLevel());
+            fp->setMaxLevel( _layer.getMaxLevel());
+            fp->setProfile( osgEarth::Profile::create(_layer.getSRS(), _layer.getExtent().xMin(), _layer.getExtent().yMin(), _layer.getExtent().xMax(), _layer.getExtent().yMax(), 1, 1) );
+            if ( _options.geoInterp().isSet() )
+                fp->geoInterp() = _options.geoInterp().get();
+        }
+        else
         {
-            result = new FeatureProfile(_layer.getExtent());
-            result->setTiled( true );
-            result->setFirstLevel( _layer.getFirstLevel());
-            result->setMaxLevel( _layer.getMaxLevel());
-            result->setProfile( osgEarth::Profile::create(_layer.getSRS(), _layer.getExtent().xMin(), _layer.getExtent().yMin(), _layer.getExtent().xMax(), _layer.getExtent().yMax(), 1, 1) );
+            // Try to get the results from the settings instead
+            if ( !_options.profile().isSet())
+            {
+                return Status::Error(Status::ConfigurationError, "TFS driver requires an explicit profile");
+            }
+
+            if (!_options.minLevel().isSet() || !_options.maxLevel().isSet())
+            {
+                return Status::Error(Status::ConfigurationError, "TFS driver requires a min and max level");
+            }
+           
+            osg::ref_ptr<const Profile> profile = Profile::create( *_options.profile() );    
+
+            fp = new FeatureProfile(profile->getExtent());
+            fp->setTiled( true );
+            fp->setFirstLevel( *_options.minLevel() );
+            fp->setMaxLevel( *_options.maxLevel() );
+            fp->setProfile( profile );
             if ( _options.geoInterp().isSet() )
-                result->geoInterp() = _options.geoInterp().get();
+                fp->geoInterp() = _options.geoInterp().get();
         }
-        return result;        
-    }
 
+        setFeatureProfile(fp);
 
-    bool getFeatures( const std::string& buffer, const std::string& mimeType, FeatureList& features )
-    {        
-        // find the right driver for the given mime type
-        OGR_SCOPED_LOCK;
-                
-        // find the right driver for the given mime type
-        OGRSFDriverH ogrDriver =
-            isJSON(mimeType) ? OGRGetDriverByName( "GeoJSON" ) :
-            isGML(mimeType)  ? OGRGetDriverByName( "GML" ) :
-            0L;
+        return Status::OK();
+    }
 
-        // fail if we can't find an appropriate OGR driver:
-        if ( !ogrDriver )
-        {
-            OE_WARN << LC << "Error reading TFS response; cannot grok content-type \"" << mimeType << "\""
-                << std::endl;
-            return false;
-        }
 
-        OGRDataSourceH ds = OGROpen( buffer.c_str(), FALSE, &ogrDriver );
-        
-        if ( !ds )
+    bool getFeatures( const std::string& buffer, const TileKey& key, const std::string& mimeType, FeatureList& features )
+    {            
+        if (mimeType == "application/x-protobuf" || mimeType == "binary/octet-stream")
         {
-            OE_WARN << LC << "Error reading TFS response" << std::endl;
-            return false;
+            std::stringstream in(buffer);
+            return MVT::read(in, key, features);
         }
+        else
+        {            
+            // find the right driver for the given mime type
+            OGR_SCOPED_LOCK;
+
+            // find the right driver for the given mime type
+            OGRSFDriverH ogrDriver =
+                isJSON(mimeType) ? OGRGetDriverByName( "GeoJSON" ) :
+                isGML(mimeType)  ? OGRGetDriverByName( "GML" ) :
+                0L;
+
+            // fail if we can't find an appropriate OGR driver:
+            if ( !ogrDriver )
+            {
+                OE_WARN << LC << "Error reading TFS response; cannot grok content-type \"" << mimeType << "\""
+                    << std::endl;
+                return false;
+            }
 
-        // read the feature data.
-        OGRLayerH layer = OGR_DS_GetLayer(ds, 0);
-        if ( layer )
-        {
-            const SpatialReference* srs = _layer.getSRS();
+            OGRDataSourceH ds = OGROpen( buffer.c_str(), FALSE, &ogrDriver );
+
+            if ( !ds )
+            {
+                OE_WARN << LC << "Error reading TFS response" << std::endl;
+                return false;
+            }
 
-            OGR_L_ResetReading(layer);                                
-            OGRFeatureH feat_handle;
-            while ((feat_handle = OGR_L_GetNextFeature( layer )) != NULL)
+            // read the feature data.
+            OGRLayerH layer = OGR_DS_GetLayer(ds, 0);
+            if ( layer )
             {
-                if ( feat_handle )
+                const SpatialReference* srs = _layer.getSRS();
+
+                OGR_L_ResetReading(layer);                                
+                OGRFeatureH feat_handle;
+                while ((feat_handle = OGR_L_GetNextFeature( layer )) != NULL)
                 {
-                    osg::ref_ptr<Feature> f = OgrUtils::createFeature( feat_handle, getFeatureProfile() );
-                    if ( f.valid() && !isBlacklisted(f->getFID()) )
+                    if ( feat_handle )
                     {
-                        features.push_back( f.release() );
+                        osg::ref_ptr<Feature> f = OgrUtils::createFeature( feat_handle, getFeatureProfile() );
+                        if ( f.valid() && !isBlacklisted(f->getFID()) )
+                        {
+                            features.push_back( f.release() );
+                        }
+                        OGR_F_Destroy( feat_handle );
                     }
-                    OGR_F_Destroy( feat_handle );
                 }
             }
-        }
 
-        // Destroy the datasource
-        OGR_DS_Destroy( ds );
+            // Destroy the datasource
+            OGR_DS_Destroy( ds );
+        }
         
         return true;
     }
@@ -239,25 +240,27 @@ public:
             unsigned int tileY = key.getTileY();
             unsigned int level = key.getLevelOfDetail();
             
-#if 0
-            unsigned int numRows, numCols;
-            key.getProfile()->getNumTiles(key.getLevelOfDetail(), numCols, numRows);
-            tileY  = numRows - tileY - 1;
-#endif
-            
+            // TFS follows the same protocol as TMS, with the origin in the lower left of the profile.
+            // osgEarth TileKeys are upper left origin, so we need to invert the tilekey to request the correct key.            
+            if (_options.invertY() == false)
+            {                
+                unsigned int numRows, numCols;
+                key.getProfile()->getNumTiles(key.getLevelOfDetail(), numCols, numRows);
+                tileY  = numRows - tileY - 1;            
+            }
+
             std::stringstream buf;
             std::string path = osgDB::getFilePath(_options.url()->full());
             buf << path << "/" << level << "/"
                                << tileX << "/"
                                << tileY
                                << "." << _options.format().get();            
-            OE_DEBUG << "TFS url " << buf.str() << std::endl;
             return buf.str();
         }
         return "";                       
     }
 
-    FeatureCursor* createFeatureCursor( const Symbology::Query& query )
+    FeatureCursor* createFeatureCursor(const Symbology::Query& query)
     {
         FeatureCursor* result = 0L;
 
@@ -272,7 +275,7 @@ public:
         URI uri(url);
 
         // read the data:
-        ReadResult r = uri.readString( _dbOptions.get() );
+        ReadResult r = uri.readString( _readOptions.get() );
 
         const std::string& buffer = r.getString();
         const Config&      meta   = r.metadata();
@@ -289,8 +292,9 @@ public:
             {
                 if (_options.format().value() == "json") mimeType = "json";
                 else if (_options.format().value().compare("gml") == 0) mimeType = "text/xml";
+                else if (_options.format().value().compare("pbf") == 0) mimeType = "application/x-protobuf";
             }
-            dataOK = getFeatures( buffer, mimeType, features );
+            dataOK = getFeatures( buffer, *query.tileKey(), mimeType, features );
         }
 
         if ( dataOK )
@@ -299,15 +303,16 @@ public:
         }
 
         //If we have any filters, process them here before the cursor is created
-        if (!_options.filters().empty())
+        if (!getFilters().empty())
         {
             // preprocess the features using the filter list:
             if ( features.size() > 0 )
             {
                 FilterContext cx;
                 cx.setProfile( getFeatureProfile() );
+                cx.extent() = query.tileKey()->getExtent();
 
-                for( FeatureFilterList::const_iterator i = _options.filters().begin(); i != _options.filters().end(); ++i )
+                for( FeatureFilterList::const_iterator i = getFilters().begin(); i != getFilters().end(); ++i )
                 {
                     FeatureFilter* filter = i->get();
                     cx = filter->push( features, cx );
@@ -315,6 +320,17 @@ public:
             }
         }
 
+        // If we have any features and we have an fid attribute, override the fid of the features
+        if (_options.fidAttribute().isSet())
+        {
+            for (FeatureList::iterator itr = features.begin(); itr != features.end(); ++itr)
+            {
+                std::string attr = itr->get()->getString(_options.fidAttribute().get());                
+                FeatureID fid = as<long>(attr, 0);
+                itr->get()->setFID( fid );
+            }
+        }
+
         //result = new FeatureListCursor(features);
         result = dataOK ? new FeatureListCursor( features ) : 0L;
 
@@ -357,7 +373,7 @@ private:
     const TFSFeatureOptions         _options;    
     FeatureSchema                   _schema;
     osg::ref_ptr<CacheBin>          _cacheBin;
-    osg::ref_ptr<osgDB::Options>    _dbOptions;    
+    osg::ref_ptr<osgDB::Options>    _readOptions;    
     TFSLayer                        _layer;
     bool                            _layerValid;
 };
@@ -371,7 +387,7 @@ public:
         supportsExtension( "osgearth_feature_tfs", "TFS feature driver for osgEarth" );
     }
 
-    virtual const char* className()
+    virtual const char* className() const
     {
         return "TFS Feature Reader";
     }
diff --git a/src/osgEarthDrivers/feature_tfs/TFSFeatureOptions b/src/osgEarthDrivers/feature_tfs/TFSFeatureOptions
index 7a912d3..f9c1c3c 100644
--- a/src/osgEarthDrivers/feature_tfs/TFSFeatureOptions
+++ b/src/osgEarthDrivers/feature_tfs/TFSFeatureOptions
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -42,6 +42,15 @@ namespace osgEarth { namespace Drivers
         optional<std::string>& format() { return _format; }
         const optional<std::string>& format() const { return _format; }        
 
+        optional<bool>& invertY() { return _invertY; }
+        const optional<bool>& invertY() const { return _invertY; }
+
+        optional<int>& minLevel() { return _minLevel; }
+        const optional<int>& minLevel() const { return _minLevel; }
+
+        optional<int>& maxLevel() { return _maxLevel; }
+        const optional<int>& maxLevel() const { return _maxLevel; }
+
     public:
         TFSFeatureOptions( const ConfigOptions& opt =ConfigOptions() ) :
           FeatureSourceOptions( opt ),
@@ -57,7 +66,10 @@ namespace osgEarth { namespace Drivers
         Config getConfig() const {
             Config conf = FeatureSourceOptions::getConfig();
             conf.updateIfSet( "url", _url ); 
-            conf.updateIfSet( "format", _format );            
+            conf.updateIfSet( "format", _format );
+            conf.updateIfSet( "invert_y", _invertY);
+            conf.updateIfSet( "min_level", _minLevel);
+            conf.updateIfSet( "max_level", _maxLevel);
             return conf;
         }
 
@@ -71,10 +83,16 @@ namespace osgEarth { namespace Drivers
         void fromConfig( const Config& conf ) {
             conf.getIfSet( "url", _url );
             conf.getIfSet( "format", _format );
+            conf.getIfSet( "invert_y", _invertY );
+            conf.getIfSet( "min_level", _minLevel);
+            conf.getIfSet( "max_level", _maxLevel);
         }
 
         optional<URI>         _url;        
         optional<std::string> _format;
+        optional<bool>        _invertY;
+        optional<int>         _minLevel;
+        optional<int>         _maxLevel;
     };
 
 } } // namespace osgEarth::Drivers
diff --git a/src/osgEarthDrivers/feature_wfs/FeatureSourceWFS.cpp b/src/osgEarthDrivers/feature_wfs/FeatureSourceWFS.cpp
index d30775f..d8c8687 100644
--- a/src/osgEarthDrivers/feature_wfs/FeatureSourceWFS.cpp
+++ b/src/osgEarthDrivers/feature_wfs/FeatureSourceWFS.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -70,37 +70,17 @@ public:
     }
 
     //override
-    void initialize( const osgDB::Options* dbOptions )
+    Status initialize(const osgDB::Options* readOptions)
     {
-        _dbOptions = dbOptions ? osg::clone(dbOptions) : 0L;
-        if ( _dbOptions.valid() )
-        {
-            // Set up a Custom caching bin for this source:
-            Cache* cache = Cache::get( _dbOptions.get() );
-            if ( cache )
-            {
-                Config optionsConf = _options.getConfig();
-
-                std::string binId = Stringify() << std::hex << hashString(optionsConf.toJSON()) << "_wfs";
-                _cacheBin = cache->addBin( binId );
-                _cacheBin->setHashKeys(true);
-                
-                // write a metadata record just for reference purposes.. we don't actually use it
-                Config metadata = _cacheBin->readMetadata();
-                if ( metadata.empty() )
-                {
-                    _cacheBin->writeMetadata( optionsConf );
-                }
+        // initialize the base class
+        //FeatureSource::initialize(readOptions);
 
-                if ( _cacheBin.valid() )
-                {
-                    _cacheBin->apply( _dbOptions.get() );
-                }
-            }
-        }
+        // store a reference to the read options so we can pass them along to
+        // later requests.
+        _readOptions = readOptions;
 
+        // parse the WFS capabilities URL
         std::string capUrl;
-
         if ( _options.url().isSet() )
         {
             char sep = _options.url()->full().find_first_of('?') == std::string::npos? '?' : '&';
@@ -111,87 +91,66 @@ public:
                 "SERVICE=WFS&VERSION=1.0.0&REQUEST=GetCapabilities";
         }        
 
-        _capabilities = WFSCapabilitiesReader::read( capUrl, _dbOptions.get() );
+        // read the WFS capabilities:
+        _capabilities = WFSCapabilitiesReader::read( capUrl, _readOptions.get() );
         if ( !_capabilities.valid() )
         {
-            OE_WARN << "[osgEarth::WFS] Unable to read WFS GetCapabilities." << std::endl;
-            //return;
+            return Status::Error(Status::ResourceUnavailable, Stringify()<<"Failed to read WFS GetCapabilities from \"" << capUrl << "\"");
         }
         else
         {
             OE_INFO << "[osgEarth::WFS] Got capabilities from " << capUrl << std::endl;
         }
-    }
-
-    void saveResponse(const std::string buffer, const std::string& filename)
-    {
-        std::ofstream fout;
-        fout.open(filename.c_str(), std::ios::out | std::ios::binary);        
-        fout.write(buffer.c_str(), buffer.size());        
-        fout.close();
-    }
 
+        // establish a feature profile
+        FeatureProfile* fp = 0L;
 
-    /** Called once at startup to create the profile for this feature set. Successful profile
-        creation implies that the datasource opened succesfully. */
-    const FeatureProfile* createFeatureProfile()
-    {
-        if ( !_featureProfile.valid() )
+        //Find the feature type by name
+        osg::ref_ptr< WFSFeatureType > featureType = _capabilities->getFeatureTypeByName( _options.typeName().get() );
+        if (featureType.valid())
         {
-            static Threading::Mutex s_mutex;
-            Threading::ScopedMutexLock lock(s_mutex);
-            
-            if ( !_featureProfile.valid() )
+            if (featureType->getExtent().isValid())
             {
-                FeatureProfile* result = 0L;
-
-                if (_capabilities.valid())
-                {
-                    //Find the feature type by name
-                    osg::ref_ptr< WFSFeatureType > featureType = _capabilities->getFeatureTypeByName( _options.typeName().get() );
-                    if (featureType.valid())
-                    {
-                        if (featureType->getExtent().isValid())
-                        {
-                            result = new FeatureProfile(featureType->getExtent());
-
-                            bool disableTiling = _options.disableTiling().isSet() && *_options.disableTiling();
-
-                            if (featureType->getTiled() && !disableTiling)
-                            {                        
-                                result->setTiled( true );
-                                result->setFirstLevel( featureType->getFirstLevel() );
-                                result->setMaxLevel( featureType->getMaxLevel() );
-                                result->setProfile( osgEarth::Profile::create(osgEarth::SpatialReference::create("epsg:4326"), featureType->getExtent().xMin(), featureType->getExtent().yMin(), featureType->getExtent().xMax(), featureType->getExtent().yMax(), 1, 1) );
-                            }
-                        }
-                    }
-                }
-
-                if (!result)
-                {
-                    result = new FeatureProfile(GeoExtent(SpatialReference::create( "epsg:4326" ), -180, -90, 180, 90));
+                fp = new FeatureProfile(featureType->getExtent());
+
+                bool disableTiling = _options.disableTiling().isSetTo(true);
+
+                if (featureType->getTiled() && !disableTiling)
+                {                        
+                    fp->setTiled( true );
+                    fp->setFirstLevel( featureType->getFirstLevel() );
+                    fp->setMaxLevel( featureType->getMaxLevel() );
+                    fp->setProfile(osgEarth::Profile::create(
+                        osgEarth::SpatialReference::create("epsg:4326"), 
+                        featureType->getExtent().xMin(), featureType->getExtent().yMin(), 
+                        featureType->getExtent().xMax(), featureType->getExtent().yMax(), 
+                        1, 1) );
                 }
-                
-                _featureProfile = result;
             }
         }
 
-        if ( _featureProfile.valid() && _options.geoInterp().isSet() )
+        // if nothing else, fall back on a global geodetic feature profile.
+        if ( !fp )
         {
-            _featureProfile->geoInterp() = _options.geoInterp().get();
+            fp = new FeatureProfile(GeoExtent(SpatialReference::create( "epsg:4326" ), -180, -90, 180, 90));
         }
+             
+        if (_options.geoInterp().isSet())
+        {
+            fp->geoInterp() = _options.geoInterp().get();
+        }
+
+        setFeatureProfile( fp );
 
-        return _featureProfile.get();
+        return Status::OK();
     }
 
-    FeatureProfile* getFeatureProfile()
+    void saveResponse(const std::string buffer, const std::string& filename)
     {
-        if ( !_featureProfile.valid() )
-        {
-            createFeatureProfile();
-        }
-        return _featureProfile.get();
+        std::ofstream fout;
+        fout.open(filename.c_str(), std::ios::out | std::ios::binary);        
+        fout.write(buffer.c_str(), buffer.size());        
+        fout.close();
     }
 
     bool getFeatures( const std::string& buffer, const std::string& mimeType, FeatureList& features )
@@ -328,11 +287,12 @@ public:
             unsigned int tileX = query.tileKey().get().getTileX();
             unsigned int tileY = query.tileKey().get().getTileY();
             unsigned int level = query.tileKey().get().getLevelOfDetail();
-#if 0
+            
+            // Tiled WFS follows the same protocol as TMS, with the origin in the lower left of the profile.
+            // osgEarth TileKeys are upper left origin, so we need to invert the tilekey to request the correct key.
             unsigned int numRows, numCols;
             query.tileKey().get().getProfile()->getNumTiles(level, numCols, numRows);
             tileY  = numRows - tileY - 1;
-#endif
 
             buf << "&Z=" << level << 
                    "&X=" << tileX <<
@@ -366,7 +326,7 @@ public:
         URI uri(url);
 
         // read the data:
-        ReadResult r = uri.readString( _dbOptions.get() );
+        ReadResult r = uri.readString( _readOptions.get() );
 
         const std::string& buffer = r.getString();
         const Config&      meta   = r.metadata();
@@ -387,7 +347,7 @@ public:
         }
 
         //If we have any filters, process them here before the cursor is created
-        if (!_options.filters().empty())
+        if (!getFilters().empty())
         {
             // preprocess the features using the filter list:
             if ( features.size() > 0 )
@@ -395,7 +355,7 @@ public:
                 FilterContext cx;
                 cx.setProfile( getFeatureProfile() );
 
-                for( FeatureFilterList::const_iterator i = _options.filters().begin(); i != _options.filters().end(); ++i )
+                for( FeatureFilterList::const_iterator i = getFilters().begin(); i != getFilters().end(); ++i )
                 {
                     FeatureFilter* filter = i->get();
                     cx = filter->push( features, cx );
@@ -403,6 +363,17 @@ public:
             }
         }
 
+        // If we have any features and we have an fid attribute, override the fid of the features
+        if (_options.fidAttribute().isSet())
+        {
+            for (FeatureList::iterator itr = features.begin(); itr != features.end(); ++itr)
+            {
+                std::string attr = itr->get()->getString(_options.fidAttribute().get());                
+                FeatureID fid = as<long>(attr, 0);
+                itr->get()->setFID( fid );
+            }
+        }
+
         //result = new FeatureListCursor(features);
         result = dataOK ? new FeatureListCursor( features ) : 0L;
 
@@ -442,12 +413,11 @@ public:
 
 
 private:
-    const WFSFeatureOptions         _options;  
-    osg::ref_ptr< WFSCapabilities > _capabilities;
-    osg::ref_ptr< FeatureProfile >  _featureProfile;
-    FeatureSchema                   _schema;
-    osg::ref_ptr<CacheBin>          _cacheBin;
-    osg::ref_ptr<osgDB::Options>    _dbOptions;    
+    const WFSFeatureOptions            _options;  
+    osg::ref_ptr< WFSCapabilities >    _capabilities;
+    osg::ref_ptr< FeatureProfile >     _featureProfile;
+    FeatureSchema                      _schema;
+    osg::ref_ptr<const osgDB::Options> _readOptions;
 };
 
 
@@ -459,17 +429,17 @@ public:
         supportsExtension( "osgearth_feature_wfs", "WFS feature driver for osgEarth" );
     }
 
-    virtual const char* className()
+    virtual const char* className() const
     {
         return "WFS Feature Reader";
     }
 
-    virtual ReadResult readObject(const std::string& file_name, const Options* options) const
+    virtual ReadResult readObject(const std::string& file_name, const osgDB::Options* readOptions) const
     {
         if ( !acceptsExtension(osgDB::getLowerCaseFileExtension( file_name )))
             return ReadResult::FILE_NOT_HANDLED;
 
-        return ReadResult( new WFSFeatureSource( getFeatureSourceOptions(options) ) );
+        return ReadResult( new WFSFeatureSource( getFeatureSourceOptions(readOptions) ) );
     }
 };
 
diff --git a/src/osgEarthDrivers/feature_wfs/WFSFeatureOptions b/src/osgEarthDrivers/feature_wfs/WFSFeatureOptions
index d1483cb..acc639e 100644
--- a/src/osgEarthDrivers/feature_wfs/WFSFeatureOptions
+++ b/src/osgEarthDrivers/feature_wfs/WFSFeatureOptions
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthDrivers/featurefilter_intersect/CMakeLists.txt b/src/osgEarthDrivers/featurefilter_intersect/CMakeLists.txt
new file mode 100644
index 0000000..4b58cc8
--- /dev/null
+++ b/src/osgEarthDrivers/featurefilter_intersect/CMakeLists.txt
@@ -0,0 +1,15 @@
+SET(TARGET_SRC
+    IntersectFeatureFilter.cpp    
+)
+
+SET(TARGET_H   	
+    IntersectFeatureFilterOptions
+)
+
+SET(TARGET_COMMON_LIBRARIES ${TARGET_COMMON_LIBRARIES} osgEarthFeatures osgEarthSymbology)
+SETUP_PLUGIN(osgearth_featurefilter_intersect)
+
+# to install public driver includes:
+SET(LIB_NAME featurefilter_intersect)
+SET(LIB_PUBLIC_HEADERS ${TARGET_H})
+INCLUDE(ModuleInstallOsgEarthDriverIncludes OPTIONAL)
diff --git a/src/osgEarthDrivers/featurefilter_intersect/IntersectFeatureFilter.cpp b/src/osgEarthDrivers/featurefilter_intersect/IntersectFeatureFilter.cpp
new file mode 100644
index 0000000..0799998
--- /dev/null
+++ b/src/osgEarthDrivers/featurefilter_intersect/IntersectFeatureFilter.cpp
@@ -0,0 +1,196 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+ * Copyright 2008-2014 Pelican Mapping
+ * http://osgearth.org
+ *
+ * osgEarth is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ */
+#include "IntersectFeatureFilterOptions"
+
+#include <osgEarthFeatures/Filter>
+
+#include <osgDB/FileNameUtils>
+#include <osgDB/FileUtils>
+#include <osgEarth/Registry>
+#include <osgEarth/ImageUtils>
+#include <osgEarthFeatures/FeatureSource>
+#include <osgEarthSymbology/Geometry>
+
+#define LC "[Intersect FeatureFilter] "
+
+using namespace osgEarth;
+using namespace osgEarth::Features;
+using namespace osgEarth::Drivers;
+using namespace osgEarth::Symbology;
+
+
+
+class IntersectFeatureFilter : public FeatureFilter, public IntersectFeatureFilterOptions
+{
+private:
+    osg::ref_ptr< FeatureSource > _featureSource;
+
+public:
+    IntersectFeatureFilter(const ConfigOptions& options)
+        : FeatureFilter(), IntersectFeatureFilterOptions(options)
+    {
+    }
+
+public: // FeatureFilter
+
+    Status initialize(const osgDB::Options* readOptions)
+    {
+        // Load the feature source containing the intersection geometry.
+        _featureSource = FeatureSourceFactory::create( features().get() );
+        if ( !_featureSource.valid() )
+            return Status::Error(Status::ServiceUnavailable, Stringify()<< "Failed to create feature driver \"" << features()->getDriver() << "\"");
+
+        const Status& s = _featureSource->open(readOptions);
+        if (s.isError())
+            return s;
+
+        return Status::OK();
+    }
+
+    /**
+     * Gets all the features that intersect the extent
+     */
+    void getFeatures(const GeoExtent& extent, FeatureList& features)
+    {
+        GeoExtent localExtent = extent.transform( _featureSource->getFeatureProfile()->getSRS() );
+        Query query;
+        query.bounds() = localExtent.bounds();
+        if (localExtent.intersects( _featureSource->getFeatureProfile()->getExtent()))
+        {
+            osg::ref_ptr< FeatureCursor > cursor = _featureSource->createFeatureCursor( query );
+            if (cursor)
+            {
+                cursor->fill( features );
+            }
+        }     
+    }
+
+    FilterContext push(FeatureList& input, FilterContext& context)
+    {
+        if (_featureSource.valid())
+        {
+            // Get any features that intersect this query.
+            FeatureList boundaries;
+            getFeatures(context.extent().get(), boundaries );
+            
+            
+            // The list of output features
+            FeatureList output;
+
+            if (boundaries.empty())
+            {
+                // No intersecting features.  If contains is false, then just the output to the input.
+                if (contains() == false)
+                {
+                    output = input;
+                }
+            }
+            else
+            {
+                // Transform the boundaries into the coordinate system of the features
+                for (FeatureList::iterator itr = boundaries.begin(); itr != boundaries.end(); ++itr)
+                {
+                    itr->get()->transform( context.profile()->getSRS() );
+                }
+
+                for(FeatureList::const_iterator f = input.begin(); f != input.end(); ++f)
+                {
+                    Feature* feature = f->get();
+                    if ( feature && feature->getGeometry() )
+                    {
+                        osg::Vec2d c = feature->getGeometry()->getBounds().center2d();
+
+                        if ( contains() == true )
+                        {
+                            // coarsest:
+                            if (_featureSource->getFeatureProfile()->getExtent().contains(GeoPoint(feature->getSRS(), c.x(), c.y())))
+                            {
+                                for (FeatureList::iterator itr = boundaries.begin(); itr != boundaries.end(); ++itr)
+                                {
+                                    Ring* ring = dynamic_cast< Ring*>(itr->get()->getGeometry());
+                                    if (ring && ring->contains2D(c.x(), c.y()))
+                                    {
+                                        output.push_back( feature );
+                                    }
+                                }                        
+                            }
+                        }
+
+                        else
+                        {    
+                            bool contained = false;
+
+                            // coarsest:
+                            if (_featureSource->getFeatureProfile()->getExtent().contains(GeoPoint(feature->getSRS(), c.x(), c.y())))
+                            {
+                                for (FeatureList::iterator itr = boundaries.begin(); itr != boundaries.end(); ++itr)
+                                {
+                                    Ring* ring = dynamic_cast< Ring*>(itr->get()->getGeometry());
+                                    if (ring && ring->contains2D(c.x(), c.y()))
+                                    {                             
+                                        contained = true;
+                                        break;
+                                    }
+                                }
+                            }
+                            if ( !contained )
+                            {
+                                output.push_back( feature );
+                            }
+                        }
+                    }
+                }
+            }
+
+            OE_INFO << LC << "Allowed " << output.size() << " out of " << input.size() << " features\n";
+
+            input = output;
+        }
+
+        return context;
+    }
+};
+
+
+class IntersectFeatureFilterPlugin : public FeatureFilterDriver
+{
+public:
+    IntersectFeatureFilterPlugin() : FeatureFilterDriver()
+    {
+        this->supportsExtension("osgearth_featurefilter_intersect", className() );
+    }
+    
+    const char* className() const
+    {
+        return "IntersectFeatureFilterPlugin";
+    }
+
+    ReadResult readObject(const std::string& file_name, const Options* options) const
+    {
+        if ( !acceptsExtension(osgDB::getLowerCaseFileExtension( file_name )))
+            return ReadResult::FILE_NOT_HANDLED;
+
+        return new IntersectFeatureFilter( getConfigOptions(options) );
+    }
+};
+
+REGISTER_OSGPLUGIN(osgearth_featurefilter_intersect, IntersectFeatureFilterPlugin);
+
+//OSGEARTH_REGISTER_SIMPLE_FEATUREFILTER(intersect, IntersectFeatureFilter);
+
diff --git a/src/osgEarthDrivers/featurefilter_intersect/IntersectFeatureFilterOptions b/src/osgEarthDrivers/featurefilter_intersect/IntersectFeatureFilterOptions
new file mode 100644
index 0000000..85d147d
--- /dev/null
+++ b/src/osgEarthDrivers/featurefilter_intersect/IntersectFeatureFilterOptions
@@ -0,0 +1,78 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+ * Copyright 2008-2014 Pelican Mapping
+ * http://osgearth.org
+ *
+ * osgEarth is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ */
+#ifndef OSGEARTH_DRIVER_INTERSECT_FEATUREFILTER_OPTIONS
+#define OSGEARTH_DRIVER_INTERSECT_FEATUREFILTER_OPTIONS 1
+
+#include <osgEarth/Common>
+#include <osgEarthFeatures/FeatureSource>
+
+namespace osgEarth { namespace Drivers
+{
+    using namespace osgEarth;
+    using namespace osgEarth::Features;
+
+    /**
+     * Options for the Raster feature driver.
+     */
+    class IntersectFeatureFilterOptions : public ConfigOptions // NO EXPORT; header only
+    {
+    public:
+        IntersectFeatureFilterOptions( const ConfigOptions& opt =ConfigOptions() ) : ConfigOptions( opt )
+        {
+            _conf.set("driver", "intersect");
+            _contains.init( true );
+            fromConfig( _conf );
+        }
+
+        /** Features to load and use as boundary geometries */
+        optional<FeatureSourceOptions>& features() { return _features; }
+        const optional<FeatureSourceOptions>& features() const { return _features; }
+
+        /** If true (the default), accept features whose centroids are contained in the boundaries */
+        optional<bool>& contains() { return _contains; }
+        const optional<bool>& contains() const { return _contains; }
+
+    public:
+        Config getConfig() const {
+            Config conf = ConfigOptions::getConfig();
+            conf.key() = "intersect";
+            conf.addObjIfSet( "features", _features );
+            conf.addIfSet   ( "contains", _contains );
+            return conf;
+        }
+
+    protected:
+        void mergeConfig( const Config& conf ) {
+            ConfigOptions::mergeConfig( conf );
+            fromConfig( conf );
+        }
+
+    private:
+        void fromConfig( const Config& conf ) {
+            conf.getObjIfSet( "features", _features );
+            conf.getIfSet   ( "contains", _contains );
+        }
+
+        optional<FeatureSourceOptions> _features;
+        optional<bool>                 _contains;
+    };
+
+} } // namespace osgEarth::Drivers
+
+#endif // OSGEARTH_DRIVER_INTERSECT_FEATUREFILTER_OPTIONS
diff --git a/src/osgEarthDrivers/featurefilter_join/CMakeLists.txt b/src/osgEarthDrivers/featurefilter_join/CMakeLists.txt
new file mode 100644
index 0000000..aef7b71
--- /dev/null
+++ b/src/osgEarthDrivers/featurefilter_join/CMakeLists.txt
@@ -0,0 +1,15 @@
+SET(TARGET_SRC
+    JoinFeatureFilter.cpp    
+)
+
+SET(TARGET_H   	
+    JoinFeatureFilterOptions
+)
+
+SET(TARGET_COMMON_LIBRARIES ${TARGET_COMMON_LIBRARIES} osgEarthFeatures osgEarthSymbology)
+SETUP_PLUGIN(osgearth_featurefilter_join)
+
+# to install public driver includes:
+SET(LIB_NAME featurefilter_join)
+SET(LIB_PUBLIC_HEADERS ${TARGET_H})
+INCLUDE(ModuleInstallOsgEarthDriverIncludes OPTIONAL)
diff --git a/src/osgEarthDrivers/featurefilter_join/JoinFeatureFilter.cpp b/src/osgEarthDrivers/featurefilter_join/JoinFeatureFilter.cpp
new file mode 100644
index 0000000..9d7123a
--- /dev/null
+++ b/src/osgEarthDrivers/featurefilter_join/JoinFeatureFilter.cpp
@@ -0,0 +1,160 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+ * Copyright 2008-2014 Pelican Mapping
+ * http://osgearth.org
+ *
+ * osgEarth is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ */
+#include "JoinFeatureFilterOptions"
+
+#include <osgEarthFeatures/Filter>
+
+#include <osgDB/FileNameUtils>
+#include <osgDB/FileUtils>
+#include <osgEarth/Registry>
+#include <osgEarth/ImageUtils>
+#include <osgEarthFeatures/FeatureSource>
+#include <osgEarthSymbology/Geometry>
+
+#define LC "[Intersect FeatureFilter] "
+
+using namespace osgEarth;
+using namespace osgEarth::Features;
+using namespace osgEarth::Drivers;
+using namespace osgEarth::Symbology;
+
+
+
+class JoinFeatureFilter : public FeatureFilter, public JoinFeatureFilterOptions
+{
+private:
+    osg::ref_ptr< FeatureSource > _featureSource;
+
+public:
+    JoinFeatureFilter(const ConfigOptions& options)
+        : FeatureFilter(), JoinFeatureFilterOptions(options)
+    {
+    }
+
+public: // FeatureFilter
+
+    Status initialize(const osgDB::Options* readOptions)
+    {
+        // Load the feature source containing the intersection geometry.
+        _featureSource = FeatureSourceFactory::create( features().get() );
+        if ( !_featureSource.valid() )
+            return Status::Error(Status::ServiceUnavailable, Stringify() << "Failed to create feature driver \"" << features()->getDriver() << "\"");
+
+        const Status& fs = _featureSource->open(readOptions);
+        if (fs.isError())
+            return fs;
+
+        return Status::OK();
+    }
+
+    /**
+     * Gets all the features that intersect the extent
+     */
+    void getFeatures(const GeoExtent& extent, FeatureList& features)
+    {
+        GeoExtent localExtent = extent.transform( _featureSource->getFeatureProfile()->getSRS() );
+        Query query;
+        query.bounds() = localExtent.bounds();
+        if (localExtent.intersects( _featureSource->getFeatureProfile()->getExtent()))
+        {
+            osg::ref_ptr< FeatureCursor > cursor = _featureSource->createFeatureCursor( query );
+            if (cursor)
+            {
+                cursor->fill( features );
+            }
+        }     
+    }
+
+    FilterContext push(FeatureList& input, FilterContext& context)
+    {
+        if (_featureSource.valid())
+        {
+            // Get any features that intersect this query.
+            FeatureList boundaries;
+            getFeatures(context.extent().get(), boundaries );
+
+            if (!boundaries.empty())
+            {
+                // Transform the boundaries into the coordinate system of the features
+                for (FeatureList::iterator itr = boundaries.begin(); itr != boundaries.end(); ++itr)
+                {
+                    itr->get()->transform( context.profile()->getSRS() );
+                }
+
+                for(FeatureList::const_iterator f = input.begin(); f != input.end(); ++f)
+                {
+                    Feature* feature = f->get();
+                    if ( feature && feature->getGeometry() )
+                    {
+                        osg::Vec2d c = feature->getGeometry()->getBounds().center2d();
+                       
+                        if (_featureSource->getFeatureProfile()->getExtent().contains(GeoPoint(feature->getSRS(), c.x(), c.y())))
+                        {
+                            for (FeatureList::iterator itr = boundaries.begin(); itr != boundaries.end(); ++itr)
+                            {
+                                //if (ring && ring->contains2D(c.x(), c.y()))
+                                if (itr->get()->getGeometry()->intersects( feature->getGeometry() ) )
+                                {
+                                    // Copy the attributes in the boundary to the feature
+                                    for (AttributeTable::const_iterator attrItr = itr->get()->getAttrs().begin();
+                                         attrItr != itr->get()->getAttrs().end();
+                                         attrItr++)
+                                    {
+                                        feature->set( attrItr->first, attrItr->second );
+                                    }
+                                    break;
+                                }
+                            }                        
+                        }
+                    }
+                }
+            }
+        }
+
+        return context;
+    }
+};
+
+
+class JoinFeatureFilterPlugin : public FeatureFilterDriver
+{
+public:
+    JoinFeatureFilterPlugin() : FeatureFilterDriver()
+    {
+        this->supportsExtension("osgearth_featurefilter_join", className() );
+    }
+    
+    const char* className() const
+    {
+        return "JoinFeatureFilterPlugin";
+    }
+
+    ReadResult readObject(const std::string& file_name, const Options* options) const
+    {
+        if ( !acceptsExtension(osgDB::getLowerCaseFileExtension( file_name )))
+            return ReadResult::FILE_NOT_HANDLED;
+
+        return new JoinFeatureFilter( getConfigOptions(options) );
+    }
+};
+
+REGISTER_OSGPLUGIN(osgearth_featurefilter_join, JoinFeatureFilterPlugin);
+
+//OSGEARTH_REGISTER_SIMPLE_FEATUREFILTER(intersect, IntersectFeatureFilter);
+
diff --git a/src/osgEarthDrivers/featurefilter_join/JoinFeatureFilterOptions b/src/osgEarthDrivers/featurefilter_join/JoinFeatureFilterOptions
new file mode 100644
index 0000000..72da461
--- /dev/null
+++ b/src/osgEarthDrivers/featurefilter_join/JoinFeatureFilterOptions
@@ -0,0 +1,67 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+ * Copyright 2008-2014 Pelican Mapping
+ * http://osgearth.org
+ *
+ * osgEarth is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ */
+#ifndef OSGEARTH_DRIVER_JOIN_FEATUREFILTER_OPTIONS
+#define OSGEARTH_DRIVER_JOIN_FEATUREFILTER_OPTIONS 1
+
+#include <osgEarth/Common>
+#include <osgEarthFeatures/FeatureSource>
+
+namespace osgEarth { namespace Drivers
+{
+    using namespace osgEarth;
+    using namespace osgEarth::Features;
+
+    class JoinFeatureFilterOptions : public ConfigOptions // NO EXPORT; header only
+    {
+    public:
+        JoinFeatureFilterOptions( const ConfigOptions& opt =ConfigOptions() ) : ConfigOptions( opt )
+        {
+            _conf.set("driver", "join");            
+            fromConfig( _conf );
+        }
+
+        /** Features to load and use as boundary geometries */
+        optional<FeatureSourceOptions>& features() { return _features; }
+        const optional<FeatureSourceOptions>& features() const { return _features; }
+
+    public:
+        Config getConfig() const {
+            Config conf = ConfigOptions::getConfig();
+            conf.key() = "join";
+            conf.addObjIfSet( "features", _features );
+            return conf;
+        }
+
+    protected:
+        void mergeConfig( const Config& conf ) {
+            ConfigOptions::mergeConfig( conf );
+            fromConfig( conf );
+        }
+
+    private:
+        void fromConfig( const Config& conf ) {
+            conf.getObjIfSet( "features", _features );
+        }
+
+        optional<FeatureSourceOptions> _features;
+    };
+
+} } // namespace osgEarth::Drivers
+
+#endif // OSGEARTH_DRIVER_JOIN_FEATUREFILTER_OPTIONS
diff --git a/src/osgEarthDrivers/gdal/GDALOptions b/src/osgEarthDrivers/gdal/GDALOptions
index 1fd3583..73d9e8c 100644
--- a/src/osgEarthDrivers/gdal/GDALOptions
+++ b/src/osgEarthDrivers/gdal/GDALOptions
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthDrivers/gdal/ReaderWriterGDAL.cpp b/src/osgEarthDrivers/gdal/ReaderWriterGDAL.cpp
index ebc0fd2..ff0fb44 100644
--- a/src/osgEarthDrivers/gdal/ReaderWriterGDAL.cpp
+++ b/src/osgEarthDrivers/gdal/ReaderWriterGDAL.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
@@ -51,11 +51,11 @@
 // From easyrgb.com
 float Hue_2_RGB( float v1, float v2, float vH )
 {
-   if ( vH < 0 ) vH += 1;
-   if ( vH > 1 ) vH -= 1;
-   if ( ( 6 * vH ) < 1 ) return ( v1 + ( v2 - v1 ) * 6 * vH );
-   if ( ( 2 * vH ) < 1 ) return ( v2 );
-   if ( ( 3 * vH ) < 2 ) return ( v1 + ( v2 - v1 ) * ( ( 2 / 3 ) - vH ) * 6 );
+   if ( vH < 0.0f ) vH += 1.0f;
+   if ( vH > 1.0f ) vH -= 1.0f;
+   if ( ( 6.0f * vH ) < 1.0f ) return ( v1 + ( v2 - v1 ) * 6.0f * vH );
+   if ( ( 2.0f * vH ) < 1.0f ) return ( v2 );
+   if ( ( 3.0f * vH ) < 2.0f ) return ( v1 + ( v2 - v1 ) * ( ( 2.0f / 3.0f ) - vH ) * 6.0f );
    return ( v1 );
 }
 
@@ -676,27 +676,17 @@ public:
     {
         GDAL_SCOPED_LOCK;
 
-        Cache* cache = 0;
-
         _dbOptions = Registry::instance()->cloneOrCreateOptions( dbOptions );
-
-        if ( _dbOptions.valid() )
-        {
-            // Set up a Custom caching bin for this TileSource
-            cache = Cache::get( _dbOptions.get() );
-            if ( cache )
-            {
-                Config optionsConf = _options.getConfig();
-
-                std::string binId = Stringify() << std::hex << hashString(optionsConf.toJSON());
-                _cacheBin = cache->addBin( binId );
-
-                if ( _cacheBin.valid() )
-                {
-                    _cacheBin->apply( _dbOptions.get() );
-                }
-            }
-        }
+        //if ( _dbOptions.valid() )
+        //{
+        //    // Set up a custom cache bin
+        //    CacheManager* cacheManager = CacheManager::get(dbOptions);
+        //    if (cacheManager && cacheManager->getCache())
+        //    {
+        //        std::string binId = Stringify() << std::hex << hashString(_options.getConfig().toJSON());
+        //        _cacheBin = cacheManager->getCache()->addBin(binId);
+        //    }
+        //}
 
         // Is a valid external GDAL dataset specified ?
         bool useExternalDataset = false;
@@ -713,7 +703,7 @@ public:
             (!_options.url().isSet() || _options.url()->empty()) &&
             (!_options.connection().isSet() || _options.connection()->empty()) )
         {
-            return Status::Error( "No URL, directory, or connection string specified" );
+            return Status::Error(Status::ConfigurationError, "No URL, directory, or connection string specified" );
         }
 
         // source connection:
@@ -752,7 +742,7 @@ public:
 
                 getFiles(source, exts, blackExts, files);
 
-                OE_INFO << LC << "Driver found " << files.size() << " files:" << std::endl;
+                OE_INFO << LC << "Identified " << files.size() << " files:" << std::endl;
                 for (unsigned int i = 0; i < files.size(); ++i)
                 {
                     OE_INFO << LC << INDENT << files[i] << std::endl;
@@ -766,7 +756,7 @@ public:
 
             if (files.empty())
             {
-                return Status::Error( "Could not find any valid input." );
+                return Status::Error( Status::ResourceUnavailable, "Could not find any valid input." );
             }
 
             //If we found more than one file, try to combine them into a single logical dataset
@@ -780,7 +770,7 @@ public:
                 //Try to load the VRT file from the cache so we don't have to build it each time.
                 if (_cacheBin.valid())
                 {                
-                    ReadResult result = _cacheBin->readString( vrtKey);
+                    ReadResult result = _cacheBin->readString( vrtKey, 0L);
                     if (result.succeeded())
                     {
                         _srcDS = (GDALDataset*)GDALOpen(result.getString().c_str(), GA_ReadOnly );
@@ -810,8 +800,10 @@ public:
 
                             if (vrtDriver)
                             {
-                                vrtDriver->CreateCopy(vrtFile.c_str(), _srcDS, 0, 0, 0, 0 );
-
+                                if ( vrtDriver->CreateCopy(vrtFile.c_str(), _srcDS, 0, 0, 0, 0 ) == NULL )
+                                {
+                                    OE_WARN << LC << INDENT << "Faile to create copy" << std::endl;
+                                }
 
                                 //We created the temp file, now read the contents back
                                 std::ifstream input( vrtFile.c_str() );
@@ -822,7 +814,7 @@ public:
                                     buf << input.rdbuf();
                                     std::string vrtContents = buf.str();
                                     osg::ref_ptr< StringObject > strObject = new StringObject( vrtContents );
-                                    _cacheBin->write( vrtKey, strObject.get() );
+                                    _cacheBin->write(vrtKey, strObject.get(), 0L);
                                 }
                             }
                             if (osgDB::fileExists( vrtFile ) )
@@ -865,7 +857,7 @@ public:
 
                 if (!_srcDS)
                 {
-                    return Status::Error( Stringify() << "Failed to open dataset " << files[0] );
+                    return Status::Error( Status::ResourceUnavailable, Stringify() << "Failed to open " << files[0] );
                 }
             }
         }
@@ -935,7 +927,7 @@ public:
 
             if ( !src_srs.valid() )
             {
-                return Status::Error( Stringify()
+                return Status::Error( Status::ResourceUnavailable, Stringify()
                     << "Dataset has no spatial reference information (" << source << ")" );
             }
         }
@@ -979,7 +971,7 @@ public:
             profile = Profile::create(src_srs.get(), -180.0, -90.0, 180.0, 90.0, 2u, 1u);
             if ( !profile )
             {
-                return Status::Error( Stringify()
+                return Status::Error( Status::ResourceUnavailable, Stringify()
                     << "Cannot create geographic Profile from dataset's spatial reference information: " << src_srs->getName() );
             }
         }
@@ -1045,7 +1037,10 @@ public:
             _warpedDS->GetGeoTransform(_geotransform);
         }
 
-        GDALInvGeoTransform(_geotransform, _invtransform);
+        if ( GDALInvGeoTransform(_geotransform, _invtransform) == 0 )
+        {
+            OE_WARN << LC << INDENT << "_geotransform not invertible" << std::endl;
+        }
 
         double minX, minY, maxX, maxY;
 
@@ -1232,9 +1227,9 @@ public:
 
                     var_1 = 2 * L - var_2;
 
-                    R = Hue_2_RGB( var_1, var_2, H + ( 1 / 3 ) );
+                    R = Hue_2_RGB( var_1, var_2, H + ( 1.0f / 3.0f ) );
                     G = Hue_2_RGB( var_1, var_2, H );
-                    B = Hue_2_RGB( var_1, var_2, H - ( 1 / 3 ) );
+                    B = Hue_2_RGB( var_1, var_2, H - ( 1.0f / 3.0f ) );
                 }
                 color.r() = static_cast<unsigned char>(R*255.0f);
                 color.g() = static_cast<unsigned char>(G*255.0f);
@@ -1509,23 +1504,33 @@ public:
                     image->allocateImage( tileSize, tileSize, 1, GL_LUMINANCE, glDataType );
                     image->setInternalTextureFormat( internalFormat );
                     ImageUtils::markAsUnNormalized( image, true );
+                    memset(image->data(), 0, image->getImageSizeInBytes());
+                
+                    ImageUtils::PixelWriter write(image); 
                     
-                    // coverage data; one channel data that is not subject to interpolated values
-                    int xbytes = target_width *  gdalSampleSize;
-                    int ybytes = target_height * gdalSampleSize;
-                    unsigned char* data = new unsigned char[xbytes * ybytes];
+                    // initialize all coverage texels to NODATA. -gw
                     osg::Vec4 temp;
+                    temp.r() = NO_DATA_VALUE;
+
+                    for(int s=0; s<image->s(); ++s) {
+                        for(int t=0; t<image->t(); ++t) {
+                            write(temp, s, t);
+                        }
+                    }
+                    
+                    // coverage data; one channel data that is not subject to interpolated values
+                    unsigned char* data = new unsigned char[target_width * target_height * gdalSampleSize];
+                    memset(data, 0, target_width * target_height * gdalSampleSize);
+
 
                     int success;
                     float nodata = bandGray->GetNoDataValue(&success);
                     if ( !success )
                         nodata = getOptions().noDataValue().get();
 
-                    CPLErr err = bandGray->RasterIO(GF_Read, off_x, off_y, width, height, data, target_width, target_height, gdalDataType, 1, 0);
+                    CPLErr err = bandGray->RasterIO(GF_Read, off_x, off_y, width, height, data, target_width, target_height, gdalDataType, 0, 0);
                     if ( err == CE_None )
                     {
-                        ImageUtils::PixelWriter write(image);
-
                         // copy from data to image.
                         for (int src_row = 0, dst_row = tile_offset_top; src_row < target_height; src_row++, dst_row++)
                         {
@@ -1644,14 +1649,23 @@ public:
                     image->allocateImage(tileSize, tileSize, 1, GL_LUMINANCE, GL_FLOAT);
                     image->setInternalTextureFormat(GL_LUMINANCE32F_ARB);
                     ImageUtils::markAsUnNormalized(image, true);
+
+                    // initialize all coverage texels to NODATA. -gw
+                    osg::Vec4 temp;
+                    temp.r() = NO_DATA_VALUE;
+                    ImageUtils::PixelWriter write(image);
+                    for(int s=0; s<image->s(); ++s) {
+                        for(int t=0; t<image->t(); ++t) {
+                            write(temp, s, t);
+                        }
+                    }
                 }
                 else
                 {
                     image->allocateImage(tileSize, tileSize, 1, pixelFormat, GL_UNSIGNED_BYTE);
+                    memset(image->data(), 0, image->getImageSizeInBytes());
                 }
 
-                memset(image->data(), 0, image->getImageSizeInBytes());
-
                 bandPalette->RasterIO(GF_Read, off_x, off_y, width, height, palette, target_width, target_height, GDT_Byte, 0, 0);
 
                 ImageUtils::PixelWriter write(image);
@@ -1708,10 +1722,6 @@ public:
                 return NULL;
             }
         }
-        else
-        {
-            OE_NOTICE << LC << key.str() << " does not intersect " << _options.url()->full() << std::endl;
-        }
 
         return image.release();
     }
@@ -1902,23 +1912,68 @@ public:
                 band = _warpedDS->GetRasterBand(1);
             }
 
-            double dx = (xmax - xmin) / (tileSize-1);
-            double dy = (ymax - ymin) / (tileSize-1);
-
+            if (_options.interpolation() == INTERP_NEAREST)
+            {
+                double colMin, colMax;
+                double rowMin, rowMax;
+                geoToPixel( xmin, ymin, colMin, rowMax );
+                geoToPixel( xmax, ymax, colMax, rowMin );
+                std::vector<float> buffer(tileSize * tileSize, NO_DATA_VALUE);
+
+                int iColMin = floor(colMin);
+                int iColMax = ceil(colMax);
+                int iRowMin = floor(rowMin);
+                int iRowMax = ceil(rowMax);
+                int iNumCols = iColMax - iColMin + 1;
+                int iNumRows = iRowMax - iRowMin + 1;
+
+                int iWinColMin = max(0, iColMin);
+                int iWinColMax = min(_warpedDS->GetRasterXSize()-1, iColMax);
+                int iWinRowMin = max(0, iRowMin);
+                int iWinRowMax = min(_warpedDS->GetRasterYSize()-1, iRowMax);
+                int iNumWinCols = iWinColMax - iWinColMin + 1;
+                int iNumWinRows = iWinRowMax - iWinRowMin + 1;
+
+                int iBufColMin = osg::round((iWinColMin - iColMin) / double(iNumCols - 1) * (tileSize - 1));
+                int iBufColMax = osg::round((iWinColMax - iColMin) / double(iNumCols - 1) * (tileSize - 1));
+                int iBufRowMin = osg::round((iWinRowMin - iRowMin) / double(iNumRows - 1) * (tileSize - 1));
+                int iBufRowMax = osg::round((iWinRowMax - iRowMin) / double(iNumRows - 1) * (tileSize - 1));
+                int iNumBufCols = iBufColMax - iBufColMin + 1;
+                int iNumBufRows = iBufRowMax - iBufRowMin + 1;
+
+                int startOffset = iBufRowMin * tileSize + iBufColMin;
+                int lineSpace = tileSize * sizeof(float);
+
+                band->RasterIO(GF_Read, iWinColMin, iWinRowMin, iNumWinCols, iNumWinRows, &buffer[startOffset], iNumBufCols, iNumBufRows, GDT_Float32, 0, lineSpace);
+
+                for (int r = 0, ir = tileSize - 1; r < tileSize; ++r, --ir)
+                {
+                    for (int c = 0; c < tileSize; ++c)
+                    {
+                        hf->setHeight(c, ir, buffer[r * tileSize + c]);
+                    }
+                }
+            }
+            else
+            {
+                double dx = (xmax - xmin) / (tileSize-1);
+                double dy = (ymax - ymin) / (tileSize-1);
                 for (int r = 0; r < tileSize; ++r)
                 {
                     double geoY = ymin + (dy * (double)r);
-                for (int c = 0; c < tileSize; ++c)
-                {
-                    double geoX = xmin + (dx * (double)c);
-                    float h = getInterpolatedValue(band, geoX, geoY);
-                    hf->setHeight(c, r, h);
+                    for (int c = 0; c < tileSize; ++c)
+                    {
+                        double geoX = xmin + (dx * (double)c);
+                        float h = getInterpolatedValue(band, geoX, geoY);
+                        hf->setHeight(c, r, h);
+                    }
                 }
             }
         }
         else
         {
-            for (unsigned int i = 0; i < hf->getHeightList().size(); ++i) hf->getHeightList()[i] = NO_DATA_VALUE;
+            std::vector<float>& heightList = hf->getHeightList();
+            std::fill(heightList.begin(), heightList.end(), NO_DATA_VALUE);
         }
         return hf.release();
     }
@@ -2246,7 +2301,7 @@ class ReaderWriterGDALTile : public TileSourceDriver
 public:
     ReaderWriterGDALTile() {}
 
-    virtual const char* className()
+    virtual const char* className() const
     {
         return "GDAL Tile Reader";
     }
diff --git a/src/osgEarthDrivers/kml/CMakeLists.txt b/src/osgEarthDrivers/kml/CMakeLists.txt
index cb35253..9d937f7 100644
--- a/src/osgEarthDrivers/kml/CMakeLists.txt
+++ b/src/osgEarthDrivers/kml/CMakeLists.txt
@@ -2,7 +2,9 @@ OPTION(CURL_IS_STATIC "on if curl is a static lib " ON)
 MARK_AS_ADVANCED(CURL_IS_STATIC)
 
 IF(WIN32)
-    SET(CMAKE_SHARED_LINKER_FLAGS_DEBUG "${CMAKE_SHARED_LINKER_FLAGS_DEBUG} /NODEFAULTLIB:MSVCRT")
+    IF(MSVC)
+        SET(CMAKE_SHARED_LINKER_FLAGS_DEBUG "${CMAKE_SHARED_LINKER_FLAGS_DEBUG} /NODEFAULTLIB:MSVCRT")
+    ENDIF(MSVC)
     IF(CURL_IS_STATIC)
         ADD_DEFINITIONS(-DCURL_STATICLIB)
         SET(TARGET_EXTERNAL_LIBRARIES ws2_32 winmm)
@@ -16,12 +18,6 @@ set(TARGET_COMMON_LIBRARIES ${TARGET_COMMON_LIBRARIES}
     osgEarthAnnotation
 )
 
-IF( MINIZIP_FOUND )
-    SET(TARGET_LIBRARIES_VARS ZLIB_LIBRARY MINIZIP_LIBRARY )
-    INCLUDE_DIRECTORIES( ${ZLIB_INCLUDE_DIR} ${MINIZIP_INCLUDE_DIR} )
-    ADD_DEFINITIONS(-DOSGEARTH_HAVE_ZLIB -DOSGEARTH_HAVE_MINIZIP )
-ENDIF( MINIZIP_FOUND )
-
 SET(TARGET_H
     KML
     KMLOptions
diff --git a/src/osgEarthDrivers/kml/KML b/src/osgEarthDrivers/kml/KML
index 28783a0..79a43e6 100644
--- a/src/osgEarthDrivers/kml/KML
+++ b/src/osgEarthDrivers/kml/KML
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -24,6 +24,7 @@
 #include <osgEarth/Registry>
 #include <osgDB/ReaderWriter>
 #include <osgDB/FileNameUtils>
+#include <osgDB/Registry>
 #include "KMLOptions"
 
 namespace osgEarth { namespace Drivers
@@ -45,6 +46,21 @@ namespace osgEarth { namespace Drivers
                                const osgDB::Options* dbOptions, 
                                const KMLOptions&     kmlOptions)
         {
+            // ensure the library is loaded.
+            osgDB::Registry::instance()->addArchiveExtension( "kmz" );
+            if ( osgDB::getLowerCaseFileExtension(uri.full()) == "kmz" )
+            {
+                OE_INFO << "[KML] Preloading KML plugin\n";
+                std::string libName = osgDB::Registry::instance()->createLibraryNameForExtension("kml");
+                osgDB::Registry::LoadStatus status = osgDB::Registry::instance()->loadLibrary(libName);
+                if ( status == osgDB::Registry::NOT_LOADED )
+                {
+                    OE_WARN << "[KML] FAILED!\n";
+                }
+                URI newURI( uri.full() + "/doc.kml", uri.context() );
+                return load( newURI, mapNode, dbOptions, kmlOptions );
+            }
+
             if ( !mapNode ) {
                 OE_WARN << "[KML] " << "MapNode instance required" << std::endl;
                 return 0L;
@@ -53,12 +69,6 @@ namespace osgEarth { namespace Drivers
             options->setPluginData( "osgEarth::MapNode",    mapNode );
             options->setPluginData( "osgEarth::KMLOptions", (void*)&kmlOptions );
 
-            // for a KMZ archive over HTTP, we need to go through OSG's archive management system
-            if ( osgDB::containsServerAddress(uri.full()) && osgDB::getLowerCaseFileExtension(uri.full()) == "kmz" )
-            {
-                return osgDB::readNodeFile( uri.full() + "/.kml", options.get() );
-            }
-
             return uri.getNode( options.get() );
         }
 
diff --git a/src/osgEarthDrivers/kml/KMLOptions b/src/osgEarthDrivers/kml/KMLOptions
index 4b45a22..af3d465 100644
--- a/src/osgEarthDrivers/kml/KMLOptions
+++ b/src/osgEarthDrivers/kml/KMLOptions
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthDrivers/kml/KMLReader b/src/osgEarthDrivers/kml/KMLReader
index 103169a..46ff4a4 100644
--- a/src/osgEarthDrivers/kml/KMLReader
+++ b/src/osgEarthDrivers/kml/KMLReader
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthDrivers/kml/KMLReader.cpp b/src/osgEarthDrivers/kml/KMLReader.cpp
index b50dc41..43211cd 100644
--- a/src/osgEarthDrivers/kml/KMLReader.cpp
+++ b/src/osgEarthDrivers/kml/KMLReader.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -23,7 +23,7 @@
 #include <osgEarth/Capabilities>
 #include <osgEarth/XmlUtils>
 #include <osgEarth/VirtualProgram>
-#include <osgEarth/Decluttering>
+#include <osgEarth/ScreenSpaceLayout>
 #include <stack>
 #include <iterator>
 
@@ -103,10 +103,10 @@ KMLReader::read( xml_document<>& doc, const osgDB::Options* dbOptions )
     if ( cx._options == 0L )
         cx._options = &blankOptions;
 
-    if ( cx._options->iconAndLabelGroup().valid() && cx._options->declutter() == true )
-    {
-        Decluttering::setEnabled( cx._options->iconAndLabelGroup()->getOrCreateStateSet(), true );
-    }
+    //if ( cx._options->iconAndLabelGroup().valid() && cx._options->declutter() == true )
+    //{
+    //    Decluttering::setEnabled( cx._options->iconAndLabelGroup()->getOrCreateStateSet(), true );
+    //}
 
     //const Config* top = conf.hasChild("kml" ) ? conf.child_ptr("kml") : &conf;
 	xml_node<> *top = doc.first_node("kml", 0, false);
diff --git a/src/osgEarthDrivers/kml/KML_Common b/src/osgEarthDrivers/kml/KML_Common
index 028349f..46d826d 100644
--- a/src/osgEarthDrivers/kml/KML_Common
+++ b/src/osgEarthDrivers/kml/KML_Common
@@ -1,7 +1,7 @@
 
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -108,12 +108,15 @@ namespace osgEarth_kml
 				else
 				{
 					link = node->first_node("url", 0, false);
-					std::string url = getValue(link, "href");
-					if (url.empty())
-					{
-						url = link->value();
-					}
-					return url;
+                    if (link)
+                    {
+					    std::string url = getValue(link, "href");
+					    if (url.empty())
+					    {
+    						url = link->value();
+					    }
+					    return url;
+                    }
 				}
 			}
 			return "";
diff --git a/src/osgEarthDrivers/kml/KML_Container b/src/osgEarthDrivers/kml/KML_Container
index 3a83001..2dc9cb7 100644
--- a/src/osgEarthDrivers/kml/KML_Container
+++ b/src/osgEarthDrivers/kml/KML_Container
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthDrivers/kml/KML_Document b/src/osgEarthDrivers/kml/KML_Document
index 7596a6d..7611e7c 100644
--- a/src/osgEarthDrivers/kml/KML_Document
+++ b/src/osgEarthDrivers/kml/KML_Document
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthDrivers/kml/KML_Document.cpp b/src/osgEarthDrivers/kml/KML_Document.cpp
index ad80a70..796d090 100644
--- a/src/osgEarthDrivers/kml/KML_Document.cpp
+++ b/src/osgEarthDrivers/kml/KML_Document.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthDrivers/kml/KML_Feature b/src/osgEarthDrivers/kml/KML_Feature
index 1842c0b..2ced86c 100644
--- a/src/osgEarthDrivers/kml/KML_Feature
+++ b/src/osgEarthDrivers/kml/KML_Feature
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthDrivers/kml/KML_Feature.cpp b/src/osgEarthDrivers/kml/KML_Feature.cpp
index 70c6d7d..56afa70 100644
--- a/src/osgEarthDrivers/kml/KML_Feature.cpp
+++ b/src/osgEarthDrivers/kml/KML_Feature.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -80,16 +80,33 @@ KML_Feature::build( xml_node<>* node, KMLContext& cx, osg::Node* working )
             anno->setViewpoint( vp );
         }
 
+        xml_node<>* timespan = node->first_node("timespan", 0, false);
+        if ( timespan )
+        {
+            DateTimeRange range;
+
+            std::string begin = getValue(timespan, "begin");
+            if ( !begin.empty() )
+            {
+                range.begin() = DateTime(begin);
+            }
+
+            std::string end = getValue(timespan, "end");
+            if ( !end.empty() )
+            {
+                range.end() = DateTime(end);
+            }
+
+            anno->setDateTimeRange( range );
+        }
+
         xml_node<>* extdata = node->first_node("extendeddata", 0, false);
         if ( extdata )
         {
             xml_node<>* data = extdata->first_node("data", 0, false);
             if ( data )
             {
-			    for (xml_node<>* n = data->first_node(); n; n = n->next_sibling())
-			    {
-    				working->setUserValue(getValue(n, "name"), getValue(n, "value"));
-			    }
+                working->setUserValue(getValue(data, "name"), getValue(data, "value"));			    
             }
         }
     }
diff --git a/src/osgEarthDrivers/kml/KML_Folder b/src/osgEarthDrivers/kml/KML_Folder
index dc1621d..6c91142 100644
--- a/src/osgEarthDrivers/kml/KML_Folder
+++ b/src/osgEarthDrivers/kml/KML_Folder
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthDrivers/kml/KML_Folder.cpp b/src/osgEarthDrivers/kml/KML_Folder.cpp
index e248bd9..7ca967c 100644
--- a/src/osgEarthDrivers/kml/KML_Folder.cpp
+++ b/src/osgEarthDrivers/kml/KML_Folder.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthDrivers/kml/KML_Geometry b/src/osgEarthDrivers/kml/KML_Geometry
index ac274bd..8964075 100644
--- a/src/osgEarthDrivers/kml/KML_Geometry
+++ b/src/osgEarthDrivers/kml/KML_Geometry
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthDrivers/kml/KML_Geometry.cpp b/src/osgEarthDrivers/kml/KML_Geometry.cpp
index f57a436..78dd880 100644
--- a/src/osgEarthDrivers/kml/KML_Geometry.cpp
+++ b/src/osgEarthDrivers/kml/KML_Geometry.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -73,14 +73,11 @@ KML_Geometry::buildChild( xml_node<>* node, KMLContext& cx, Style& style)
         KML_MultiGeometry g;
         g.parseCoords(node, cx);
         _geom = g._geom.get();
-        g.parseStyle(node, cx, style);
         
         for( xml_node<>* n = node->first_node(); n; n = n->next_sibling())
         {
-            Style subStyle = style;
             KML_Geometry subGeom;
-            subGeom.parseStyle( n, cx, subStyle );
-            subGeom.buildChild( n, cx, style );
+            subGeom.buildChild( n, cx, style ); //use single style for all subgeometries
             if ( subGeom._geom.valid() )
                 dynamic_cast<MultiGeometry*>(g._geom.get())->getComponents().push_back( subGeom._geom.get() );
         }
@@ -131,6 +128,7 @@ KML_Geometry::parseStyle( xml_node<>* node, KMLContext& cx, Style& style )
         am = "clampToGround"; // default.
 
     bool isPoly = _geom.valid() && _geom->getComponentType() == Geometry::TYPE_POLYGON;
+    bool isLine = _geom.valid() && _geom->getComponentType() == Geometry::TYPE_LINESTRING;
 
     // Resolve the correct altitude symbol. CLAMP_TO_TERRAIN is the default, but the
     // technique will depend on the geometry's type and setup.
@@ -147,7 +145,7 @@ KML_Geometry::parseStyle( xml_node<>* node, KMLContext& cx, Style& style )
 
     double maxElevation = -DBL_MAX;
 
-    if ( isPoly )
+    //if ( isPoly ) //compute maxElevation also for line strings for extrusion height
     {
         bool first = true;
         double e = 0.0;
@@ -189,6 +187,10 @@ KML_Geometry::parseStyle( xml_node<>* node, KMLContext& cx, Style& style )
         {
             alt->technique() = alt->TECHNIQUE_DRAPE;
         }
+        else if ( isLine)
+        {
+            alt->technique() = alt->TECHNIQUE_DRAPE; // or could be GPU.
+        }
         else // line or point
         {
             alt->technique() = alt->TECHNIQUE_SCENE;
diff --git a/src/osgEarthDrivers/kml/KML_GroundOverlay b/src/osgEarthDrivers/kml/KML_GroundOverlay
index e4cafa8..9b4e937 100644
--- a/src/osgEarthDrivers/kml/KML_GroundOverlay
+++ b/src/osgEarthDrivers/kml/KML_GroundOverlay
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthDrivers/kml/KML_GroundOverlay.cpp b/src/osgEarthDrivers/kml/KML_GroundOverlay.cpp
index 85a8405..c7ce76e 100644
--- a/src/osgEarthDrivers/kml/KML_GroundOverlay.cpp
+++ b/src/osgEarthDrivers/kml/KML_GroundOverlay.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthDrivers/kml/KML_IconStyle b/src/osgEarthDrivers/kml/KML_IconStyle
index 01e15c8..17367cf 100644
--- a/src/osgEarthDrivers/kml/KML_IconStyle
+++ b/src/osgEarthDrivers/kml/KML_IconStyle
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthDrivers/kml/KML_IconStyle.cpp b/src/osgEarthDrivers/kml/KML_IconStyle.cpp
index c197552..12cb2a0 100644
--- a/src/osgEarthDrivers/kml/KML_IconStyle.cpp
+++ b/src/osgEarthDrivers/kml/KML_IconStyle.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -40,7 +40,9 @@ KML_IconStyle::scan( xml_node<>* node, Style& style, KMLContext& cx )
 
         if ( !iconHref.empty() )
         {
-            icon->url() = StringExpression( iconHref, URIContext(cx._referrer) );
+            // We set a literal here to avoid filenames with spaces being evaluated.
+            icon->url()->setLiteral(iconHref);
+            icon->url()->setURIContext(URIContext(cx._referrer));
         }
 			
         // see: https://developers.google.com/kml/documentation/kmlreference#headingdiagram
@@ -52,6 +54,12 @@ KML_IconStyle::scan( xml_node<>* node, Style& style, KMLContext& cx )
 
 		std::string scale = getValue(node, "scale");
         if ( !scale.empty() )
-            icon->scale() = NumericExpression( scale );
+        {
+            icon->scale() = NumericExpression(NumericExpression( scale ).eval() * finalScale);
+        }
+        else
+        {
+            icon->scale() = NumericExpression(finalScale);
+        }
     }
 }
diff --git a/src/osgEarthDrivers/kml/KML_LabelStyle b/src/osgEarthDrivers/kml/KML_LabelStyle
index 850010d..78b19c7 100644
--- a/src/osgEarthDrivers/kml/KML_LabelStyle
+++ b/src/osgEarthDrivers/kml/KML_LabelStyle
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthDrivers/kml/KML_LabelStyle.cpp b/src/osgEarthDrivers/kml/KML_LabelStyle.cpp
index c2ce119..2c17b03 100644
--- a/src/osgEarthDrivers/kml/KML_LabelStyle.cpp
+++ b/src/osgEarthDrivers/kml/KML_LabelStyle.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthDrivers/kml/KML_LineString b/src/osgEarthDrivers/kml/KML_LineString
index 62aef5e..710979c 100644
--- a/src/osgEarthDrivers/kml/KML_LineString
+++ b/src/osgEarthDrivers/kml/KML_LineString
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthDrivers/kml/KML_LineString.cpp b/src/osgEarthDrivers/kml/KML_LineString.cpp
index ce61ad0..a31a888 100644
--- a/src/osgEarthDrivers/kml/KML_LineString.cpp
+++ b/src/osgEarthDrivers/kml/KML_LineString.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthDrivers/kml/KML_LineStyle b/src/osgEarthDrivers/kml/KML_LineStyle
index c135ccf..5a7989d 100644
--- a/src/osgEarthDrivers/kml/KML_LineStyle
+++ b/src/osgEarthDrivers/kml/KML_LineStyle
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthDrivers/kml/KML_LineStyle.cpp b/src/osgEarthDrivers/kml/KML_LineStyle.cpp
index caa583e..5857a6a 100644
--- a/src/osgEarthDrivers/kml/KML_LineStyle.cpp
+++ b/src/osgEarthDrivers/kml/KML_LineStyle.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -35,6 +35,11 @@ KML_LineStyle::scan( xml_node<>* node, Style& style, KMLContext& cx )
         if ( !width.empty() )
         {
             line->stroke()->width() = as<float>( width, 1.0f );
+
+            if ( line->stroke()->width() == 0.0f )
+            {
+                line->stroke()->width() = 1.0f;
+            }
         }
     }
 }
diff --git a/src/osgEarthDrivers/kml/KML_LinearRing b/src/osgEarthDrivers/kml/KML_LinearRing
index a14fed9..fab9ce4 100644
--- a/src/osgEarthDrivers/kml/KML_LinearRing
+++ b/src/osgEarthDrivers/kml/KML_LinearRing
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthDrivers/kml/KML_LinearRing.cpp b/src/osgEarthDrivers/kml/KML_LinearRing.cpp
index cd51d74..81009f6 100644
--- a/src/osgEarthDrivers/kml/KML_LinearRing.cpp
+++ b/src/osgEarthDrivers/kml/KML_LinearRing.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthDrivers/kml/KML_Model b/src/osgEarthDrivers/kml/KML_Model
index 098c8d7..a8860a6 100644
--- a/src/osgEarthDrivers/kml/KML_Model
+++ b/src/osgEarthDrivers/kml/KML_Model
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthDrivers/kml/KML_Model.cpp b/src/osgEarthDrivers/kml/KML_Model.cpp
index fadebc9..a82b634 100644
--- a/src/osgEarthDrivers/kml/KML_Model.cpp
+++ b/src/osgEarthDrivers/kml/KML_Model.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthDrivers/kml/KML_MultiGeometry b/src/osgEarthDrivers/kml/KML_MultiGeometry
index 6d33509..38f29b4 100644
--- a/src/osgEarthDrivers/kml/KML_MultiGeometry
+++ b/src/osgEarthDrivers/kml/KML_MultiGeometry
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthDrivers/kml/KML_MultiGeometry.cpp b/src/osgEarthDrivers/kml/KML_MultiGeometry.cpp
index 5f75d82..c97fe06 100644
--- a/src/osgEarthDrivers/kml/KML_MultiGeometry.cpp
+++ b/src/osgEarthDrivers/kml/KML_MultiGeometry.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthDrivers/kml/KML_NetworkLink.cpp b/src/osgEarthDrivers/kml/KML_NetworkLink.cpp
index 5aaadf1..71d2b9c 100644
--- a/src/osgEarthDrivers/kml/KML_NetworkLink.cpp
+++ b/src/osgEarthDrivers/kml/KML_NetworkLink.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -37,6 +37,11 @@ KML_NetworkLink::build( xml_node<>* node, KMLContext& cx )
 
     // parse the link:
     std::string href = KMLUtils::parseLink(node);
+    
+    if ( !href.empty())
+    {
+        href = URIContext(cx._referrer).getOSGPath(href);
+    }
 
     // "open" determines whether to load it immediately
     bool open = as<bool>(getValue(node, "open"), false);
diff --git a/src/osgEarthDrivers/kml/KML_NetworkLinkControl b/src/osgEarthDrivers/kml/KML_NetworkLinkControl
index ac2d6ba..e1ad719 100644
--- a/src/osgEarthDrivers/kml/KML_NetworkLinkControl
+++ b/src/osgEarthDrivers/kml/KML_NetworkLinkControl
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthDrivers/kml/KML_NetworkLinkControl.cpp b/src/osgEarthDrivers/kml/KML_NetworkLinkControl.cpp
index 6e04eae..4be8aa7 100644
--- a/src/osgEarthDrivers/kml/KML_NetworkLinkControl.cpp
+++ b/src/osgEarthDrivers/kml/KML_NetworkLinkControl.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthDrivers/kml/KML_Object b/src/osgEarthDrivers/kml/KML_Object
index 7272d16..4247164 100644
--- a/src/osgEarthDrivers/kml/KML_Object
+++ b/src/osgEarthDrivers/kml/KML_Object
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthDrivers/kml/KML_Object.cpp b/src/osgEarthDrivers/kml/KML_Object.cpp
index b3ea4cf..1f46b6f 100644
--- a/src/osgEarthDrivers/kml/KML_Object.cpp
+++ b/src/osgEarthDrivers/kml/KML_Object.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthDrivers/kml/KML_Overlay b/src/osgEarthDrivers/kml/KML_Overlay
index 6a00ce4..0c0aec1 100644
--- a/src/osgEarthDrivers/kml/KML_Overlay
+++ b/src/osgEarthDrivers/kml/KML_Overlay
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthDrivers/kml/KML_Overlay.cpp b/src/osgEarthDrivers/kml/KML_Overlay.cpp
index 50158f8..ea92106 100644
--- a/src/osgEarthDrivers/kml/KML_Overlay.cpp
+++ b/src/osgEarthDrivers/kml/KML_Overlay.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthDrivers/kml/KML_PhotoOverlay b/src/osgEarthDrivers/kml/KML_PhotoOverlay
index 791888f..55b35b0 100644
--- a/src/osgEarthDrivers/kml/KML_PhotoOverlay
+++ b/src/osgEarthDrivers/kml/KML_PhotoOverlay
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthDrivers/kml/KML_PhotoOverlay.cpp b/src/osgEarthDrivers/kml/KML_PhotoOverlay.cpp
index 734e3a3..09b49ad 100644
--- a/src/osgEarthDrivers/kml/KML_PhotoOverlay.cpp
+++ b/src/osgEarthDrivers/kml/KML_PhotoOverlay.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthDrivers/kml/KML_Placemark.cpp b/src/osgEarthDrivers/kml/KML_Placemark.cpp
index 90b3d38..11e56f0 100644
--- a/src/osgEarthDrivers/kml/KML_Placemark.cpp
+++ b/src/osgEarthDrivers/kml/KML_Placemark.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -24,8 +24,8 @@
 #include <osgEarthAnnotation/PlaceNode>
 #include <osgEarthAnnotation/LabelNode>
 #include <osgEarthAnnotation/ModelNode>
-#include <osgEarthAnnotation/LocalGeometryNode>
-#include <osgEarth/Decluttering>
+#include <osgEarth/ObjectIndex>
+#include <osgEarth/Registry>
 
 #include <osg/Depth>
 #include <osgDB/WriteFile>
@@ -87,13 +87,27 @@ KML_Placemark::build( xml_node<>* node, KMLContext& cx )
 
                 GeoPoint position(cx._srs.get(), geom->getBounds().center(), altMode);
 
-                bool isPoly = geom->getComponentType() == Geometry::TYPE_POLYGON;
-                bool isPoint = geom->getComponentType() == Geometry::TYPE_POINTSET;
-
                 // check for symbols.
-                ModelSymbol*    model = style.get<ModelSymbol>();
-                IconSymbol*     icon  = style.get<IconSymbol>();
-                TextSymbol*     text  = style.get<TextSymbol>();
+                ModelSymbol* model = style.get<ModelSymbol>();
+                IconSymbol*  icon  = style.get<IconSymbol>();
+                TextSymbol*  text  = style.get<TextSymbol>();
+
+                // for a single point placemark, apply the default icon and text symbols
+                // if none are specified in the KML.
+                if (geom->getTotalPointCount() == 1)
+                {
+                    if (!model && !icon && cx._options->defaultIconSymbol().valid())
+                    {
+                        icon = cx._options->defaultIconSymbol().get();
+                        style.add(icon);
+                    }
+
+                    if (!text && cx._options->defaultTextSymbol().valid())
+                    {
+                        text = cx._options->defaultTextSymbol().get();
+                        style.add(text);
+                    }
+                }
 
                 // the annotation name:
                 std::string name = getValue(node, "name");
@@ -105,14 +119,6 @@ KML_Placemark::build( xml_node<>* node, KMLContext& cx )
                 // one coordinate? It's a place marker or a label.
                 if ( (model || icon || text) && geom->getTotalPointCount() == 1 )
                 {
-                    // load up the default icon if there we don't have one.
-                    if ( !model && !icon )
-                    {
-                        icon = cx._options->defaultIconSymbol().get();
-                        if ( icon )
-                            style.add( icon );
-                    }
-
                     // if there's a model, render that - models do NOT get labels.
                     if ( model )
                     {
@@ -123,13 +129,13 @@ KML_Placemark::build( xml_node<>* node, KMLContext& cx )
                         if ( cx._options->modelScale() != 1.0f )
                         {
                             float s = *cx._options->modelScale();
-                            node->setScale( osg::Vec3f(s,s,s) );
+                            node->getPositionAttitudeTransform()->setScale(osg::Vec3d(s,s,s));
                         }
 
                         // model local tangent plane rotation:
                         if ( !cx._options->modelRotation()->zeroRotation() )
                         {
-                            node->setLocalRotation( *cx._options->modelRotation() );
+                            node->getPositionAttitudeTransform()->setAttitude( *cx._options->modelRotation() );
                         }
 
                         modelNode = node;
@@ -138,13 +144,7 @@ KML_Placemark::build( xml_node<>* node, KMLContext& cx )
                     // is there a label?
                     else if ( !name.empty() )
                     {
-                        if ( !text && cx._options->defaultTextSymbol().valid() )
-                        {
-                            text = cx._options->defaultTextSymbol().get();
-                            style.addSymbol( text );
-
-                        }
-                        else
+                        if ( !text )
                         {
                             text = style.getOrCreate<TextSymbol>();
                             text->encoding() = TextSymbol::ENCODING_UTF8;
@@ -168,8 +168,6 @@ KML_Placemark::build( xml_node<>* node, KMLContext& cx )
                 // multiple coords? feature:
                 if ( geom->getTotalPointCount() > 1 )
                 {
-                    ExtrusionSymbol* extruded = style.get<ExtrusionSymbol>();
-
                     // Remove symbols that we have already processed so the geometry
                     // compiler doesn't get confused.
                     if ( model )
@@ -183,6 +181,21 @@ KML_Placemark::build( xml_node<>* node, KMLContext& cx )
                     featureNode = new FeatureNode( cx._mapNode, feature );
                 }
 
+                if ( iconNode )
+                {
+                    Registry::objectIndex()->tagNode( iconNode, iconNode );
+                }
+
+                if ( modelNode )
+                {
+                    Registry::objectIndex()->tagNode( modelNode, modelNode );
+                }
+
+                if ( featureNode )
+                {
+                    Registry::objectIndex()->tagNode( featureNode, featureNode );
+                }
+
 
                 // assemble the results:
                 if ( (iconNode || modelNode) && featureNode )
@@ -196,11 +209,6 @@ KML_Placemark::build( xml_node<>* node, KMLContext& cx )
 
                     cx._groupStack.top()->addChild( group );
 
-                    if ( iconNode && cx._options->declutter() == true )
-                    {
-                        Decluttering::setEnabled( iconNode->getOrCreateStateSet(), true );
-                    }
-
                     if ( iconNode )
                         KML_Feature::build( node, cx, iconNode );
                     if ( modelNode )
@@ -220,10 +228,6 @@ KML_Placemark::build( xml_node<>* node, KMLContext& cx )
                         else
                         {
                             cx._groupStack.top()->addChild( iconNode );
-                            if ( cx._options->declutter() == true )
-                            {
-                                Decluttering::setEnabled( iconNode->getOrCreateStateSet(), true );
-                            }
                         }
                         KML_Feature::build( node, cx, iconNode );
                     }
diff --git a/src/osgEarthDrivers/kml/KML_Point b/src/osgEarthDrivers/kml/KML_Point
index 3b4879f..e893f77 100644
--- a/src/osgEarthDrivers/kml/KML_Point
+++ b/src/osgEarthDrivers/kml/KML_Point
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthDrivers/kml/KML_Point.cpp b/src/osgEarthDrivers/kml/KML_Point.cpp
index 5199208..cac6681 100644
--- a/src/osgEarthDrivers/kml/KML_Point.cpp
+++ b/src/osgEarthDrivers/kml/KML_Point.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthDrivers/kml/KML_PolyStyle b/src/osgEarthDrivers/kml/KML_PolyStyle
index d6e68c8..12f4019 100644
--- a/src/osgEarthDrivers/kml/KML_PolyStyle
+++ b/src/osgEarthDrivers/kml/KML_PolyStyle
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthDrivers/kml/KML_PolyStyle.cpp b/src/osgEarthDrivers/kml/KML_PolyStyle.cpp
index 2d7b8de..9b9657a 100644
--- a/src/osgEarthDrivers/kml/KML_PolyStyle.cpp
+++ b/src/osgEarthDrivers/kml/KML_PolyStyle.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthDrivers/kml/KML_Polygon b/src/osgEarthDrivers/kml/KML_Polygon
index acd7c4a..d58eb8b 100644
--- a/src/osgEarthDrivers/kml/KML_Polygon
+++ b/src/osgEarthDrivers/kml/KML_Polygon
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthDrivers/kml/KML_Polygon.cpp b/src/osgEarthDrivers/kml/KML_Polygon.cpp
index e095773..f7019c9 100644
--- a/src/osgEarthDrivers/kml/KML_Polygon.cpp
+++ b/src/osgEarthDrivers/kml/KML_Polygon.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -49,7 +49,7 @@ KML_Polygon::parseCoords( xml_node<>* node, KMLContext& cx )
             outer.parseCoords( outerRing, cx );
             if ( outer._geom.valid() )
             {
-                dynamic_cast<Ring*>(outer._geom.get())->rewind( Ring::ORIENTATION_CCW );
+                static_cast<Ring*>(outer._geom.get())->rewind( Ring::ORIENTATION_CCW );
                 poly->reserve( outer._geom->size() );
                 std::copy( outer._geom->begin(), outer._geom->end(), std::back_inserter(*poly) );
             }
@@ -65,7 +65,7 @@ KML_Polygon::parseCoords( xml_node<>* node, KMLContext& cx )
 				if ( inner._geom.valid() )
 				{
 					Geometry* innerGeom = inner._geom.get();
-					dynamic_cast<Ring*>(innerGeom)->rewind( Ring::ORIENTATION_CW );
+					static_cast<Ring*>(innerGeom)->rewind( Ring::ORIENTATION_CW );
 					poly->getHoles().push_back( dynamic_cast<Ring*>(innerGeom) );
 				}
 			}
diff --git a/src/osgEarthDrivers/kml/KML_Root b/src/osgEarthDrivers/kml/KML_Root
index 5721ad6..638af3d 100644
--- a/src/osgEarthDrivers/kml/KML_Root
+++ b/src/osgEarthDrivers/kml/KML_Root
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthDrivers/kml/KML_Root.cpp b/src/osgEarthDrivers/kml/KML_Root.cpp
index cfcaeef..916f0e7 100644
--- a/src/osgEarthDrivers/kml/KML_Root.cpp
+++ b/src/osgEarthDrivers/kml/KML_Root.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthDrivers/kml/KML_Schema b/src/osgEarthDrivers/kml/KML_Schema
index 8eb3fa6..784f4ff 100644
--- a/src/osgEarthDrivers/kml/KML_Schema
+++ b/src/osgEarthDrivers/kml/KML_Schema
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthDrivers/kml/KML_Schema.cpp b/src/osgEarthDrivers/kml/KML_Schema.cpp
index f5b9d18..6db28b5 100644
--- a/src/osgEarthDrivers/kml/KML_Schema.cpp
+++ b/src/osgEarthDrivers/kml/KML_Schema.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthDrivers/kml/KML_ScreenOverlay b/src/osgEarthDrivers/kml/KML_ScreenOverlay
index 2eccf41..fbcf304 100644
--- a/src/osgEarthDrivers/kml/KML_ScreenOverlay
+++ b/src/osgEarthDrivers/kml/KML_ScreenOverlay
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthDrivers/kml/KML_ScreenOverlay.cpp b/src/osgEarthDrivers/kml/KML_ScreenOverlay.cpp
index 012f2db..4dcb050 100644
--- a/src/osgEarthDrivers/kml/KML_ScreenOverlay.cpp
+++ b/src/osgEarthDrivers/kml/KML_ScreenOverlay.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthDrivers/kml/KML_Style b/src/osgEarthDrivers/kml/KML_Style
index 8c46dfb..b024177 100644
--- a/src/osgEarthDrivers/kml/KML_Style
+++ b/src/osgEarthDrivers/kml/KML_Style
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthDrivers/kml/KML_Style.cpp b/src/osgEarthDrivers/kml/KML_Style.cpp
index bbe9472..94a035b 100644
--- a/src/osgEarthDrivers/kml/KML_Style.cpp
+++ b/src/osgEarthDrivers/kml/KML_Style.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthDrivers/kml/KML_StyleMap b/src/osgEarthDrivers/kml/KML_StyleMap
index a03103b..0400b14 100644
--- a/src/osgEarthDrivers/kml/KML_StyleMap
+++ b/src/osgEarthDrivers/kml/KML_StyleMap
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthDrivers/kml/KML_StyleMap.cpp b/src/osgEarthDrivers/kml/KML_StyleMap.cpp
index 9a1847f..f4fe767 100644
--- a/src/osgEarthDrivers/kml/KML_StyleMap.cpp
+++ b/src/osgEarthDrivers/kml/KML_StyleMap.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthDrivers/kml/KML_StyleSelector b/src/osgEarthDrivers/kml/KML_StyleSelector
index 8523bda..7d01f97 100644
--- a/src/osgEarthDrivers/kml/KML_StyleSelector
+++ b/src/osgEarthDrivers/kml/KML_StyleSelector
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthDrivers/kml/KMZArchive b/src/osgEarthDrivers/kml/KMZArchive
index bd4bb6d..ab1a524 100644
--- a/src/osgEarthDrivers/kml/KMZArchive
+++ b/src/osgEarthDrivers/kml/KMZArchive
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -19,22 +19,15 @@
 #ifndef OSGEARTH_DRIVER_KML_KMZ_ARCHIVE
 #define OSGEARTH_DRIVER_KML_KMZ_ARCHIVE 1
 
-#ifdef OSGEARTH_HAVE_MINIZIP
-#    define SUPPORT_KMZ 1
-#endif
-
-#ifdef SUPPORT_KMZ
-
 #include <osgDB/Archive>
 #include <osgEarth/URI>
-#include "unzip.h"  // minizip
 
 using namespace osgEarth;
 
 
 struct KMZArchive : public osgDB::Archive
 {
-    KMZArchive( const URI& archiveURI );
+    KMZArchive(const URI& archiveURI, const Options* options);
 
     virtual ~KMZArchive();
 
@@ -45,7 +38,7 @@ struct KMZArchive : public osgDB::Archive
     std::string getArchiveFileName() const;
 
     /** Get the file name which represents the master file recorded in the Archive.*/
-    std::string getMasterFileName() const ;
+    std::string getMasterFileName() const;
 
     /** return true if file exists in archive.*/
     bool fileExists(const std::string& filename) const;
@@ -82,14 +75,11 @@ struct KMZArchive : public osgDB::Archive
 
 private:
     URI            _archiveURI;
-    unzFile        _uf;
-    void*          _buf;
-    unsigned       _bufsize;
+
+    osg::ref_ptr<osgDB::Archive> _zip;
 
     bool isAcceptable(const std::string& filename, const osgDB::Options* options) const;
 };
 
 
-#endif // SUPPORT_KMZ
-
 #endif // OSGEARTH_DRIVER_KML_KMZ_ARCHIVE
diff --git a/src/osgEarthDrivers/kml/KMZArchive.cpp b/src/osgEarthDrivers/kml/KMZArchive.cpp
index a9d90cd..33a0f62 100644
--- a/src/osgEarthDrivers/kml/KMZArchive.cpp
+++ b/src/osgEarthDrivers/kml/KMZArchive.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -17,7 +17,6 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>
  */
 #include "KMZArchive"
-#ifdef SUPPORT_KMZ
 
 #include <osgDB/ReaderWriter>
 #include <osgDB/FileNameUtils>
@@ -25,6 +24,7 @@
 #include <osgEarth/HTTPClient>
 #include <osgEarth/Registry>
 #include <osgEarth/ThreadingUtils>
+#include <fstream>
 
 #define LC "[KMZArchive] "
 
@@ -69,10 +69,8 @@ namespace
 
 //------------------------------------------------------------------------
 
-KMZArchive::KMZArchive( const URI& archiveURI ) :
-_archiveURI( archiveURI ),
-_buf( 0L ),
-_bufsize( 1024000 )
+KMZArchive::KMZArchive(const URI& archiveURI, const osgDB::Options* dbOptions) :
+_archiveURI( archiveURI )
 {
     supportsExtension( "kmz", "KMZ" );
 
@@ -83,20 +81,51 @@ _bufsize( 1024000 )
         localURI = downloadToCache( archiveURI );
     }
 
-    _uf = unzOpen( localURI.full().c_str() );
-    _buf = (void*)new char[_bufsize];
+    osg::ref_ptr<osgDB::ReaderWriter> zipRW = osgDB::Registry::instance()->getReaderWriterForExtension("zip");
+    if ( zipRW.valid() )
+    {
+        std::ifstream fin(localURI.full().c_str(), std::ios::binary|std::ios::in);
+        if ( fin.is_open() )
+        {
+            //std::string str(
+            //    (std::istreambuf_iterator<char>(fin)),
+            //    std::istreambuf_iterator<char>());
+
+            //std::istringstream in(str);
+
+            ReadResult r = zipRW->openArchive( fin, dbOptions );
+            if ( r.success() )
+            {
+                _zip = r.takeArchive();
+            }
+            else
+            {
+                OE_WARN << LC << "Failed to open archive at \"" << localURI.full() << "\"\n";
+                OE_WARN << LC << "Message = " << r.message() << "\n";
+            }
+        }
+        else
+        {
+            OE_WARN << LC << "Failed to read archive from \"" << localURI.full() << "\"\n";
+        }
+    }
+    else
+    {
+        OE_WARN << LC << "Failed to locate OSG ZIP plugin\n";
+    }
 }
 
 KMZArchive::~KMZArchive()
 {
-    if ( _buf )
-        delete [] _buf;
 }
 
 void 
 KMZArchive::close()
 {
-    _uf = 0;
+    if ( _zip.valid() )
+    {
+        _zip->close();
+    }
 }
 
 /** Get the file name which represents the archived file.*/
@@ -117,22 +146,21 @@ KMZArchive::getMasterFileName() const
 bool
 KMZArchive::fileExists(const std::string& filename) const
 {
-    //todo
-    return false;
+    return _zip.valid() ? _zip->fileExists(filename) : false;
 }
 
 /** return type of file. */
 osgDB::FileType
 KMZArchive::getFileType(const std::string& filename) const
 {
-    return osgDB::REGULAR_FILE;
+    return _zip.valid() ? _zip->getFileType(filename) : osgDB::REGULAR_FILE;
 }
 
 /** Get the full list of file names available in the archive.*/
 bool 
 KMZArchive::getFileNames(FileNameList& fileNames) const
 {
-    return false;
+    return _zip.valid() ? _zip->getFileNames(fileNames) : false;
 }
 
 /** return the contents of a directory.
@@ -140,195 +168,23 @@ KMZArchive::getFileNames(FileNameList& fileNames) const
 osgDB::DirectoryContents 
 KMZArchive::getDirectoryContents(const std::string& dirName) const
 {
-    return osgDB::DirectoryContents();
-}
-
-/** reads a file from the archive into an io buffer. */
-bool 
-KMZArchive::readToBuffer( const std::string& fileInZip, std::ostream& iobuf ) const
-{
-    // help from:
-    // http://bytes.com/topic/c/answers/764381-reading-contents-zip-files
-
-
-    //OE_INFO << LC << "Attempting to read \"" << fileInZip << "\" from \"" << _archiveURI.base() << "\"" << std::endl;
-
-
-    int err = UNZ_OK;
-    unz_file_info file_info;
-    char filename_inzip[2048];
-    bool got_file_info = false;
-
-    if ( _uf == 0 )
-    {
-        OE_WARN << LC << "Archive is not open." << std::endl;
-        return false;
-    }
-
-    if ( fileInZip == ".kml" )
-    {
-        // special case; first try the master file (doc.kml), then failing that, look
-        // for the first KML file in the archive.
-        if ( unzLocateFile( _uf, "doc.kml", 0 ) != 0 )
-        {
-            if ( unzGoToFirstFile( _uf ) != UNZ_OK )
-            {
-                OE_WARN << LC << "Archive is empty" << std::endl;
-                return false;
-            }
-
-            while( err == UNZ_OK )
-            {
-                if ( unzGetCurrentFileInfo( _uf, &file_info, filename_inzip, sizeof(filename_inzip), 0L, 0, 0L, 0) )
-                {
-                    OE_WARN << LC << "Error with zipfile " << _archiveURI.base() << std::endl;
-                    return false;
-                }
-
-                got_file_info = true;
-                std::string lc = osgEarth::toLower( std::string(filename_inzip) );
-                if ( endsWith( lc, ".kml" ) )
-                {
-                    break;
-                }
-
-                err = unzGoToNextFile( _uf );
-            }
-
-            if ( err != UNZ_OK )
-            {
-                OE_WARN << LC << "No KML file found in archive" << std::endl;
-                return false;
-            }
-        }
-    }
-
-    else if ( unzLocateFile( _uf, fileInZip.c_str(), 0 ) )
-    {
-        OE_WARN << LC << "Failed to locate '" << fileInZip << "' in '" << _archiveURI.base() << "'" << std::endl;
-        return false;
-    }
-
-    if ( !got_file_info )
-    {
-        if ( unzGetCurrentFileInfo( _uf, &file_info, filename_inzip, sizeof(filename_inzip), 0L, 0, 0L, 0) )
-        {
-            OE_WARN << LC << "Error with zipfile " << _archiveURI.base() << std::endl;
-            return false;
-        }
-    }
-
-    err = unzOpenCurrentFilePassword( _uf, 0L );
-    if ( err != UNZ_OK )
-    {
-        OE_WARN << LC << "unzOpenCurrentFilePassword failed" << std::endl;
-        return false;
-    }
-
-    do
-    {
-        err = unzReadCurrentFile( _uf, _buf, _bufsize );
-        if ( err < 0 )
-        {
-            OE_WARN << LC << "Error in unzReadCurrentFile" << std::endl;
-            break;
-        }
-        if ( err > 0 )
-        {
-            for( unsigned i=0; i<(unsigned)err; ++i )
-            {
-                iobuf.put( *(((char*)_buf)+i) );
-            }
-        }
-    }
-    while( err > 0 );
-
-    err = unzCloseCurrentFile( _uf );
-    if ( err != UNZ_OK )
-    {
-        //ignore it...
-    }
-
-    return true;
-}
-
-bool
-KMZArchive::isAcceptable(const std::string& filename, const osgDB::Options* options) const
-{
-    if (!options ||
-        options->getDatabasePathList().size() == 0 ||
-        options->getDatabasePathList()[0] != _archiveURI.full() )
-    {
-        //OE_INFO << "Rejected: " << filename << std::endl;
-        return false;
-    }
-    return true;
+    return _zip.valid() ? _zip->getDirectoryContents(dirName) : osgDB::DirectoryContents();
 }
 
 osgDB::ReaderWriter::ReadResult
 KMZArchive::readImage(const std::string& filename, const osgDB::Options* options) const
 {
-    if ( isAcceptable(filename, options) )
-    {
-        osgDB::ReaderWriter* rw = osgDB::Registry::instance()->getReaderWriterForExtension(
-            osgDB::getLowerCaseFileExtension( filename ) );
-        if ( rw )
-        {
-            std::stringstream iobuf;
-            if ( readToBuffer( filename, iobuf ) )
-            {
-                osg::ref_ptr<osgDB::Options> myOptions = Registry::instance()->cloneOrCreateOptions(options);
-                URIContext(*_archiveURI).add(filename).apply( myOptions.get() );
-                return rw->readImage( iobuf, myOptions.get() );
-            }
-            else return ReadResult::ERROR_IN_READING_FILE;
-        }
-    }
-    return ReadResult::FILE_NOT_HANDLED;
+    return _zip.valid() ? _zip->readImage(filename, options) : ReadResult::FILE_NOT_HANDLED;
 }
 
 osgDB::ReaderWriter::ReadResult
 KMZArchive::readNode(const std::string& filename, const osgDB::Options* options) const
 {
-    if ( isAcceptable(filename, options) )
-    {
-        osgDB::ReaderWriter* rw = osgDB::Registry::instance()->getReaderWriterForExtension(
-            osgDB::getLowerCaseFileExtension( filename ) );
-        if ( rw )
-        {
-            std::stringstream iobuf;
-            if ( readToBuffer( filename, iobuf ) )
-            {
-                osg::ref_ptr<osgDB::Options> myOptions = Registry::instance()->cloneOrCreateOptions(options);
-                URIContext(*_archiveURI).add(filename).apply( myOptions.get() );
-                return rw->readNode( iobuf, myOptions.get() );
-            }
-            else return ReadResult::ERROR_IN_READING_FILE;
-        }
-    }
-    return ReadResult::FILE_NOT_HANDLED;
+    return _zip.valid() ? _zip->readNode(filename, options) : ReadResult::FILE_NOT_HANDLED;
 }
 
 osgDB::ReaderWriter::ReadResult
 KMZArchive::readObject(const std::string& filename, const osgDB::Options* options) const
 {
-    if ( isAcceptable(filename, options) )
-    {
-        osgDB::ReaderWriter* rw = osgDB::Registry::instance()->getReaderWriterForExtension(
-            osgDB::getLowerCaseFileExtension( filename ) );
-        if ( rw )
-        {
-            std::stringstream iobuf;
-            if ( readToBuffer( filename, iobuf ) )
-            {
-                osg::ref_ptr<osgDB::Options> myOptions = Registry::instance()->cloneOrCreateOptions(options);
-                URIContext(*_archiveURI).add(filename).apply( myOptions.get() );
-                return rw->readObject( iobuf, myOptions.get() );
-            }
-            else return ReadResult::ERROR_IN_READING_FILE;
-        }
-    }
-    return ReadResult::FILE_NOT_HANDLED;
+    return _zip.valid() ? _zip->readObject(filename, options) : ReadResult::FILE_NOT_HANDLED;
 }
-
-#endif // SUPPORT_KMZ
diff --git a/src/osgEarthDrivers/kml/ReaderWriterKML.cpp b/src/osgEarthDrivers/kml/ReaderWriterKML.cpp
index c277326..2ff1bd0 100644
--- a/src/osgEarthDrivers/kml/ReaderWriterKML.cpp
+++ b/src/osgEarthDrivers/kml/ReaderWriterKML.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -43,10 +43,11 @@ struct ReaderWriterKML : public osgDB::ReaderWriter
     ReaderWriterKML()
     {
         supportsExtension( "kml", "KML" );
-
-#ifdef SUPPORT_KMZ
         supportsExtension( "kmz", "KMZ" );
-#endif // SUPPORT_KMZ
+        osgDB::Registry::instance()->addArchiveExtension("kmz");
+
+        // Not supported for archives:
+        //osgDB::Registry::instance()->addFileExtensionAlias("kmz", "zip"); 
     }
 
     osgDB::ReaderWriter::ReadResult readObject(const std::string& url, const osgDB::Options* options) const
@@ -67,13 +68,14 @@ struct ReaderWriterKML : public osgDB::ReaderWriter
 
         if ( ext == "kmz" )
         {
-            return URI(url + "/.kml").readNode( dbOptions ).releaseNode();
+            // redirect to the archive.
+            return URI(url + "/doc.kml").readNode(dbOptions).releaseNode();
         }
         else
         {
             // propagate the source URI along to the stream reader
             osg::ref_ptr<osgDB::Options> myOptions = Registry::instance()->cloneOrCreateOptions(dbOptions);
-            URIContext(url).apply( myOptions.get() );
+            URIContext(url).store( myOptions.get() );
             return readNode( URIStream(url), myOptions.get() );
         }
     }
@@ -99,24 +101,15 @@ struct ReaderWriterKML : public osgDB::ReaderWriter
         return ReadResult(node);
     }
 
-#ifdef SUPPORT_KMZ
-
-    osgDB::ReaderWriter::ReadResult openArchive( const std::string& url, ArchiveStatus status, unsigned int dummy, const osgDB::Options* options =0L ) const
+    osgDB::ReaderWriter::ReadResult openArchive(const std::string& url, ArchiveStatus status, unsigned blockSizeHint, const osgDB::Options* options =0L) const
     {
-        // Find the archive for this thread. We store one KMZ archive instance per thread 
-        // so that the minizip library can work in parallel
-        osg::ref_ptr<KMZArchive>& kmz = const_cast<ReaderWriterKML*>(this)->_archive.get();
-        if ( !kmz.valid() )
-            kmz = new KMZArchive( URI(url) );
-
-        return ReadResult( kmz.release() );
+        if ( osgDB::getLowerCaseFileExtension(url) == "kmz" )
+        {
+            OE_NOTICE << LC << "Opening KMZ archive at \"" << url << "\"\n";
+            return new KMZArchive( URI(url), options );
+        }
+        else return ReadResult::FILE_NOT_HANDLED;
     }
-
-private:
-
-    PerThread< osg::ref_ptr<KMZArchive> > _archive;
-
-#endif // SUPPORT_KMZ
 };
 
 REGISTER_OSGPLUGIN( kml, ReaderWriterKML )
diff --git a/src/osgEarthDrivers/kml/rapidxml_ext.hpp b/src/osgEarthDrivers/kml/rapidxml_ext.hpp
index 2e6250b..c1fc433 100644
--- a/src/osgEarthDrivers/kml/rapidxml_ext.hpp
+++ b/src/osgEarthDrivers/kml/rapidxml_ext.hpp
@@ -33,8 +33,19 @@ inline std::string getChildValue(xml_node<>* node, const std::string& key)
 		xml_node<>* child = node->first_node(key.c_str(), 0, false);
 		if (child)
 		{
-			return child->value();
-		}
+            if (child->value_size() > 0)
+            {
+                return child->value();
+            }
+            else //Try to read CDATA node
+            {
+                child = child->first_node();
+                if (child)
+                {
+                    return child->value();
+                }
+            }
+		}                
 	}
 	return "";
 }
diff --git a/src/osgEarthDrivers/label_annotation/AnnotationLabelSource.cpp b/src/osgEarthDrivers/label_annotation/AnnotationLabelSource.cpp
index 116506d..c06ce73 100644
--- a/src/osgEarthDrivers/label_annotation/AnnotationLabelSource.cpp
+++ b/src/osgEarthDrivers/label_annotation/AnnotationLabelSource.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -61,6 +61,8 @@ public:
         StringExpression  textContentExpr ( text ? *text->content()  : StringExpression() );
         NumericExpression textPriorityExpr( text ? *text->priority() : NumericExpression() );
         NumericExpression textSizeExpr    ( text ? *text->size()     : NumericExpression() );
+        NumericExpression textRotationExpr( text ? *text->onScreenRotation() : NumericExpression() );
+        NumericExpression textCourseExpr  ( text ? *text->geographicCourse() : NumericExpression() );
         StringExpression  iconUrlExpr     ( icon ? *icon->url()      : StringExpression() );
         NumericExpression iconScaleExpr   ( icon ? *icon->scale()    : NumericExpression() );
         NumericExpression iconHeadingExpr ( icon ? *icon->heading()  : NumericExpression() );
@@ -102,6 +104,12 @@ public:
 
                 if ( text->size().isSet() )
                     tempStyle.get<TextSymbol>()->size()->setLiteral( feature->eval(textSizeExpr, &context) );
+
+                if ( text->onScreenRotation().isSet() )
+                    tempStyle.get<TextSymbol>()->onScreenRotation()->setLiteral( feature->eval(textRotationExpr, &context) );
+
+                if ( text->geographicCourse().isSet() )
+                    tempStyle.get<TextSymbol>()->geographicCourse()->setLiteral( feature->eval(textCourseExpr, &context) );
             }
 
             if ( icon )
@@ -133,10 +141,6 @@ public:
             }
         }
 
-        // Note to self: need to change this to support picking later. -gw
-        //VirtualProgram* vp = VirtualProgram::getOrCreate(group->getOrCreateStateSet());
-        //vp->setInheritShaders( false );
-
         return group;
     }
 
@@ -147,16 +151,25 @@ public:
                              NumericExpression& priorityExpr )
     {
         osg::Vec3d center = feature->getGeometry()->getBounds().center();
-        GeoPoint point(feature->getSRS(), center.x(), center.y());
 
-        //LabelNode* node = new LabelNode(0L, point, style);
-        PlaceNode* node = new PlaceNode(0L, point, style, context.getDBOptions());
+        AltitudeMode mode = ALTMODE_ABSOLUTE;        
 
+        const AltitudeSymbol* alt = style.getSymbol<AltitudeSymbol>();
+        if (alt &&
+           (alt->clamping() == AltitudeSymbol::CLAMP_TO_TERRAIN || alt->clamping() == AltitudeSymbol::CLAMP_RELATIVE_TO_TERRAIN) &&
+           alt->technique() == AltitudeSymbol::TECHNIQUE_SCENE)
+        {
+            mode = ALTMODE_RELATIVE;
+        }                              
+
+        GeoPoint point(feature->getSRS(), center.x(), center.y(), center.z(), mode);        
+
+        PlaceNode* node = new PlaceNode(0L, point, style, context.getDBOptions());
+        
         if ( !priorityExpr.empty() )
         {
-            AnnotationData* data = new AnnotationData();
-            data->setPriority( feature->eval(priorityExpr, &context) );
-            node->setAnnotationData( data );
+            float val = feature->eval(priorityExpr, &context);
+            node->setPriority( val >= 0.0f ? val : FLT_MAX );
         }
 
         return node;
@@ -174,7 +187,7 @@ public:
         supportsExtension( "osgearth_label_annotation", "osgEarth annotation label plugin" );
     }
 
-    virtual const char* className()
+    virtual const char* className() const
     {
         return "osgEarth Annotation Label Plugin";
     }
diff --git a/src/osgEarthDrivers/mapinspector/CMakeLists.txt b/src/osgEarthDrivers/mapinspector/CMakeLists.txt
new file mode 100644
index 0000000..1bc4420
--- /dev/null
+++ b/src/osgEarthDrivers/mapinspector/CMakeLists.txt
@@ -0,0 +1,26 @@
+#
+# MapInspector Extension
+#
+
+SET(TARGET_SRC
+	MapInspectorExtension.cpp
+	MapInspectorUI.cpp)
+	
+SET(LIB_PUBLIC_HEADERS
+	MapInspectorExtension
+	MapInspectorUI)
+	
+SET(TARGET_H
+	${LIB_PUBLIC_HEADERS} )
+
+SET(TARGET_COMMON_LIBRARIES ${TARGET_COMMON_LIBRARIES}
+    osgEarthUtil
+	osgEarthFeatures
+	osgEarthSymbology)
+	
+SETUP_PLUGIN(osgearth_mapinspector)
+
+SET(LIB_NAME mapinspector)
+
+INCLUDE(ModuleInstallOsgEarthPluginIncludes OPTIONAL)
+
diff --git a/src/osgEarthDrivers/mapinspector/MapInspectorExtension b/src/osgEarthDrivers/mapinspector/MapInspectorExtension
new file mode 100644
index 0000000..1197627
--- /dev/null
+++ b/src/osgEarthDrivers/mapinspector/MapInspectorExtension
@@ -0,0 +1,84 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+ * Copyright 2016 Pelican Mapping
+ * http://osgearth.org
+ *
+ * osgEarth is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ */
+#ifndef OSGEARTH_MAPINSPECTOR_EXTENSION
+#define OSGEARTH_MAPINSPECTOR_EXTENSION 1
+
+#include <osgEarth/Extension>
+#include <osgEarth/MapNode>
+#include <osgEarth/MapCallback>
+#include <osgEarthUtil/Controls>
+
+namespace osgEarth { namespace MapInspector
+{
+    using namespace osgEarth;
+    using namespace osgEarth::Util::Controls;
+
+    /**
+     * Displays visual metadata about the visible layers in a map.
+     */
+    class MapInspectorExtension : public Extension,
+                                  public ExtensionInterface<MapNode>,
+                                  public ExtensionInterface<Control>,
+                                  public MapCallback
+    {
+    public:
+        META_Object(osgearth_ext_MapInspector, MapInspectorExtension);
+
+        // CTORs
+        MapInspectorExtension();
+        MapInspectorExtension(const ConfigOptions& options);
+
+        // DTOR
+        virtual ~MapInspectorExtension();
+
+
+    public: // ExtensionInterface<MapNode>
+
+        bool connect(MapNode* mapNode);
+
+        bool disconnect(MapNode* mapNode);
+
+
+    public: // ExtensionInterface<Control>
+
+        bool connect(Control* control);
+
+        bool disconnect(Control* control);
+
+        
+    public: // MapCallback
+
+        void onMapModelChanged(const MapModelChange& change);
+
+
+    protected: // Object
+
+        MapInspectorExtension(const MapInspectorExtension& rhs, const osg::CopyOp& op) { }
+
+
+    private:
+        osg::observer_ptr<MapNode> _mapNode;
+        osg::ref_ptr<Control>      _ui;
+
+        void ctor();
+    };
+
+} } // namespace osgEarth::MapInspector
+
+#endif // OSGEARTH_MAPINSPECTOR_EXTENSION
diff --git a/src/osgEarthDrivers/mapinspector/MapInspectorExtension.cpp b/src/osgEarthDrivers/mapinspector/MapInspectorExtension.cpp
new file mode 100644
index 0000000..07ab4d8
--- /dev/null
+++ b/src/osgEarthDrivers/mapinspector/MapInspectorExtension.cpp
@@ -0,0 +1,116 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+ * Copyright 2016 Pelican Mapping
+ * http://osgearth.org
+ *
+ * osgEarth is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ */
+#include "MapInspectorExtension"
+#include "MapInspectorUI"
+
+#include <osgEarthFeatures/FeatureSource>
+#include <osgEarthDrivers/feature_ogr/OGRFeatureOptions>
+#include <osgEarthAnnotation/FeatureNode>
+#include <osgEarthSymbology/Style>
+
+using namespace osgEarth;
+using namespace osgEarth::Util;
+using namespace osgEarth::Util::Controls;
+using namespace osgEarth::MapInspector;
+
+#define LC "[MapInspector] "
+
+
+REGISTER_OSGEARTH_EXTENSION(osgearth_mapinspector, MapInspectorExtension)
+
+
+MapInspectorExtension::MapInspectorExtension()
+{
+    ctor();
+}
+
+MapInspectorExtension::MapInspectorExtension(const ConfigOptions& options)
+{
+    ctor();
+}
+
+MapInspectorExtension::~MapInspectorExtension()
+{
+    // nop
+}
+
+void
+MapInspectorExtension::ctor()
+{
+    OE_INFO << LC << "loaded\n";
+    _ui = new MapInspectorUI();
+}
+
+
+void 
+MapInspectorExtension::onMapModelChanged(const MapModelChange& change)
+{
+    osg::ref_ptr<MapNode> mapNode;
+    _mapNode.lock(mapNode);
+    static_cast<MapInspectorUI*>(_ui.get())->reinit(mapNode.get());
+}
+
+bool
+MapInspectorExtension::connect(MapNode* mapNode)
+{
+    OE_INFO << LC << "connected\n";
+    if ( mapNode )
+    {
+        _mapNode = mapNode;
+        _mapNode->getMap()->addMapCallback(this);
+        static_cast<MapInspectorUI*>(_ui.get())->reinit(mapNode);
+    }
+    
+    return true;
+}
+
+bool
+MapInspectorExtension::disconnect(MapNode* mapNode)
+{
+    OE_INFO << LC << "disconnected\n";
+
+    if ( mapNode )
+        mapNode->getMap()->removeMapCallback(this);
+
+    static_cast<MapInspectorUI*>(_ui.get())->reinit(0L);
+    return true;
+}
+
+bool
+MapInspectorExtension::connect(Control* control)
+{
+    Container* container = dynamic_cast<Container*>(control);
+    if ( container && _ui.valid() )
+    {
+        container->addControl( _ui.get() );
+    }
+
+    return true;
+}
+
+bool
+MapInspectorExtension::disconnect(Control* control)
+{
+    Container* container = dynamic_cast<Container*>(control);
+    if ( container && _ui.valid() )
+    {
+        container->removeChild( _ui.get() );
+    }
+    return true;
+}
diff --git a/src/osgEarthDrivers/mapinspector/MapInspectorUI b/src/osgEarthDrivers/mapinspector/MapInspectorUI
new file mode 100644
index 0000000..5ec9311
--- /dev/null
+++ b/src/osgEarthDrivers/mapinspector/MapInspectorUI
@@ -0,0 +1,49 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+ * Copyright 2016 Pelican Mapping
+ * http://osgearth.org
+ *
+ * osgEarth is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ */
+#ifndef OSGEARTH_MAPINSPECTOR_UI
+#define OSGEARTH_MAPINSPECTOR_UI 1
+
+#include <osgEarth/MapCallback>
+#include <osgEarth/MapNode>
+#include <osgEarthUtil/Controls>
+#include <osg/View>
+
+namespace osgEarth { namespace MapInspector
+{
+    using namespace osgEarth;
+
+    class MapInspectorUI : public osgEarth::Util::Controls::Grid
+    {
+    public:
+        /** create UI */
+        MapInspectorUI();
+
+        /** rebuild everything */
+        void reinit(MapNode* mapNode);
+
+    private:
+        osg::ref_ptr<osg::Group>    _annos;
+
+        void addTerrainLayer(class TerrainLayer* layer, MapNode* mapNode);
+        void addModelLayer  (class ModelLayer*   layer, MapNode* mapNode);
+    };
+
+} } // namespace
+
+#endif // OSGEARTH_MAPINSPECTOR_UI
\ No newline at end of file
diff --git a/src/osgEarthDrivers/mapinspector/MapInspectorUI.cpp b/src/osgEarthDrivers/mapinspector/MapInspectorUI.cpp
new file mode 100644
index 0000000..b6748ad
--- /dev/null
+++ b/src/osgEarthDrivers/mapinspector/MapInspectorUI.cpp
@@ -0,0 +1,162 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+ * Copyright 2016 Pelican Mapping
+ * http://osgearth.org
+ *
+ * osgEarth is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ */
+#include "MapInspectorUI"
+#include <osgEarth/GeoData>
+#include <osgEarthAnnotation/FeatureNode>
+#include <osgEarthAnnotation/LabelNode>
+#include <osgEarthFeatures/Feature>
+#include <osgEarthSymbology/Style>
+#include <osgEarthSymbology/Geometry>
+
+using namespace osgEarth;
+using namespace osgEarth::Annotation;
+using namespace osgEarth::Features;
+using namespace osgEarth::Symbology;
+using namespace osgEarth::MapInspector;
+
+namespace ui = osgEarth::Util::Controls;
+
+#define LC "[MapInspectorUI] "
+
+MapInspectorUI::MapInspectorUI()
+{
+    //nop
+}
+
+void
+MapInspectorUI::reinit(MapNode* mapNode)
+{
+    if ( !_annos.valid() )
+        _annos = new osg::Group();
+
+    _annos->removeChildren(0, _annos->getNumChildren());
+
+    this->clearControls();
+
+    if ( mapNode )
+    {
+        // install annotation group as neccesary
+        if (_annos->getNumParents() == 0 || _annos->getParent(0) != mapNode)
+        {
+            if ( _annos->getNumParents() > 0 )
+            {
+                _annos->getParent(0)->removeChild(_annos.get());
+            }
+            mapNode->addChild( _annos.get() );
+        }
+        
+        Map* map = mapNode->getMap();
+
+        for(int i=0; i<map->getNumElevationLayers(); ++i)
+        {
+            ElevationLayer* layer = map->getElevationLayerAt(i);
+            addTerrainLayer( layer, mapNode );
+        }
+
+        for(int i=0; i<map->getNumImageLayers(); ++i)
+        {
+            ImageLayer* layer = map->getImageLayerAt(i);
+            addTerrainLayer( layer, mapNode );
+        }
+
+        for(int i=0; i<map->getNumModelLayers(); ++i)
+        {
+            ModelLayer* layer = map->getModelLayerAt(i);
+            addModelLayer( layer, mapNode );
+        }
+    }
+    else
+    {
+        OE_INFO << LC << "MapNode is null\n";
+    }
+}
+
+void
+MapInspectorUI::addTerrainLayer(TerrainLayer* layer,
+                                MapNode*      mapNode)
+{
+    const Color colors[6] = {
+        Color::White,
+        Color::Yellow,
+        Color::Cyan,
+        Color::Lime,
+        Color::Red,
+        Color::Magenta
+    };
+    Color color = colors[(int)layer->getUID()%6];
+
+    osg::ref_ptr<MultiGeometry> collection = new MultiGeometry();
+
+    DataExtentList exlist;
+    if (layer->getDataExtents(exlist))
+    {
+        for(DataExtentList::const_iterator i = exlist.begin(); i != exlist.end(); ++i)
+        {
+            const DataExtent& e = *i;
+            Polygon* p = new Polygon();
+            p->push_back( e.xMin(), e.yMin() );
+            p->push_back( e.xMax(), e.yMin() );
+            p->push_back( e.xMax(), e.yMax() );
+            p->push_back( e.xMin(), e.yMax() );
+            collection->add( p );
+        }
+
+        // poly:
+        {
+            Style style;
+            style.getOrCreate<LineSymbol>()->stroke()->color() = color;
+            style.getOrCreate<LineSymbol>()->stroke()->width() = 2;
+            style.getOrCreate<AltitudeSymbol>()->clamping() = AltitudeSymbol::CLAMP_TO_TERRAIN;
+            style.getOrCreate<AltitudeSymbol>()->technique() = AltitudeSymbol::TECHNIQUE_DRAPE;
+            style.getOrCreate<RenderSymbol>()->lighting() = false;
+
+            Feature* feature = new Feature(collection.get(), layer->getProfile()->getSRS(), style);
+            FeatureNode* node = new FeatureNode( mapNode, feature );
+            _annos->addChild( node );
+        }
+
+        // label:
+        std::string text = 
+            !layer->getName().empty()? layer->getName() :
+            Stringify() << "Layer " << layer->getUID();
+
+        {
+            Style style;
+            TextSymbol* ts = style.getOrCreate<TextSymbol>();
+            ts->halo()->color().set(0,0,0,1);
+            ts->declutter() = true;
+            ts->alignment() = TextSymbol::ALIGN_CENTER_CENTER;
+        
+            osg::Vec2d center = collection->getBounds().center2d();
+            GeoPoint position(layer->getProfile()->getSRS(), center.x(), center.y(), 0.0, ALTMODE_ABSOLUTE);
+
+            LabelNode* label = new LabelNode(mapNode, position, text, style);
+            _annos->addChild( label );
+        }
+
+        unsigned r = this->getNumRows();
+        setControl(0, r, new ui::LabelControl(text, color));
+    }
+}
+
+void
+MapInspectorUI::addModelLayer(ModelLayer* layer,
+                              MapNode*    mapNode)
+{
+}
diff --git a/src/osgEarthDrivers/mask_feature/FeatureMaskOptions b/src/osgEarthDrivers/mask_feature/FeatureMaskOptions
index 24a17b6..f252501 100644
--- a/src/osgEarthDrivers/mask_feature/FeatureMaskOptions
+++ b/src/osgEarthDrivers/mask_feature/FeatureMaskOptions
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthDrivers/mask_feature/FeatureMaskSource.cpp b/src/osgEarthDrivers/mask_feature/FeatureMaskSource.cpp
index 1664c84..87828ac 100644
--- a/src/osgEarthDrivers/mask_feature/FeatureMaskSource.cpp
+++ b/src/osgEarthDrivers/mask_feature/FeatureMaskSource.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -58,28 +58,28 @@ public:
         }
     }
 
-    const MaskSourceOptions& getOptions() const { return _options; }
+    const MaskSourceOptions& getOptions() const { 
+        return _options; 
+    }
 
     //override
-    void initialize(const osgDB::Options* dbOptions)
+    Status initialize(const osgDB::Options* readOptions)
     {
-        MaskSource::initialize( dbOptions );
+        if (!_features.valid())
+            return Status::Error(LC, "No feature source available");
 
-        if ( _features.valid() )
-        {
-            _features->initialize( dbOptions );
-        } 
-        else
-        {
-            OE_WARN << LC << "No FeatureSource; nothing will be rendered (" << getName() << ")" << std::endl;
-        }
+        const Status& fstatus = _features->open(readOptions);
+        if (fstatus.isError())
+            return fstatus;
+
+        return Status::OK();
     }
 
     osg::Vec3dArray* createBoundary(const SpatialReference* srs, ProgressCallback* progress)
     {
-        if ( _failed )
+        if (getStatus().isError())
             return 0L;
-
+        
         if ( _features.valid() )
         {
             if ( _features->getFeatureProfile() )
@@ -102,20 +102,20 @@ public:
                             cx = xform.push(featureList, cx);
                         }
 
-                        return f->getGeometry()->toVec3dArray();
+                        return f->getGeometry()->createVec3dArray();
                     }
                 }
             }
             else
             {
-                OE_WARN << LC << "Failed to create boundary; feature source has no SRS" << std::endl;
-                _failed = true;
+                setStatus(Status::Error("Failed to create boundary"));
+                OE_WARN << LC << getStatus().message() << std::endl;
             }
         }
         else
         {
-            OE_WARN << LC << "Unable to create boundary; invalid feature source" << std::endl;
-            _failed = true;
+            setStatus(Status::Error("Failed to create boundary"));
+            OE_WARN << LC << getStatus().message() << std::endl;
         }
         return 0L;
     }
@@ -136,7 +136,7 @@ public:
         supportsExtension( "osgearth_mask_feature", "osgEarth feature mask plugin" );
     }
 
-    virtual const char* className()
+    virtual const char* className() const
     {
         return "osgEarth Feature Mask Plugin";
     }
diff --git a/src/osgEarthDrivers/mbtiles/MBTilesPlugin.cpp b/src/osgEarthDrivers/mbtiles/MBTilesPlugin.cpp
index a941bae..d5b604a 100644
--- a/src/osgEarthDrivers/mbtiles/MBTilesPlugin.cpp
+++ b/src/osgEarthDrivers/mbtiles/MBTilesPlugin.cpp
@@ -40,7 +40,7 @@ namespace osgEarth { namespace Drivers { namespace MBTiles
             supportsExtension( "osgearth_mbtiles", "MBTiles tile driver" );
         }
 
-        virtual const char* className()
+        virtual const char* className() const
         {
             return "MBTiles Driver";
         }
diff --git a/src/osgEarthDrivers/mbtiles/MBTilesTileSource.cpp b/src/osgEarthDrivers/mbtiles/MBTilesTileSource.cpp
index 8b17959..c55eb76 100644
--- a/src/osgEarthDrivers/mbtiles/MBTilesTileSource.cpp
+++ b/src/osgEarthDrivers/mbtiles/MBTilesTileSource.cpp
@@ -68,7 +68,7 @@ _forceRGB ( false )
     //nop
 }
 
-TileSource::Status
+Status
 MBTilesTileSource::initialize(const osgDB::Options* dbOptions)
 {    
     _dbOptions = Registry::instance()->cloneOrCreateOptions( dbOptions );    
@@ -82,7 +82,7 @@ MBTilesTileSource::initialize(const osgDB::Options* dbOptions)
     {
         // For a NEW database, the profile MUST be set prior to initialization.
         if ( getProfile() == 0L )
-            return Status::Error("Cannot create database; required Profile is missing");
+            return Status::Error(Status::ConfigurationError, "Cannot create database; required Profile is missing");
 
         // For a NEW database the format is required.
         if ( _options.format().isSet() )
@@ -90,11 +90,11 @@ MBTilesTileSource::initialize(const osgDB::Options* dbOptions)
             _tileFormat = _options.format().value();
             _rw = getReaderWriter( _tileFormat );
             if ( !_rw.valid() )
-                return Status::Error("No plugin to load format \"" + _tileFormat + "\"");
+                return Status::Error(Status::ServiceUnavailable, "No plugin to load format \"" + _tileFormat + "\"");
         }
         else
         {
-            return Status::Error("Cannot create database; required format is missing");
+            return Status::Error(Status::ConfigurationError, "Cannot create database; required format is missing");
         }
 
         OE_INFO << LC << "Database does not exist; attempting to create it." << std::endl;
@@ -109,7 +109,7 @@ MBTilesTileSource::initialize(const osgDB::Options* dbOptions)
     int rc = sqlite3_open_v2( fullFilename.c_str(), &_database, flags, 0L );
     if ( rc != 0 )
     {                        
-        return Status::Error( Stringify()
+        return Status::Error( Status::ResourceUnavailable, Stringify()
             << "Database \"" << fullFilename << "\": " << sqlite3_errmsg(_database) );
     }
     
@@ -136,11 +136,33 @@ MBTilesTileSource::initialize(const osgDB::Options* dbOptions)
                 OE_INFO << LC << "Data will be compressed (zlib)" << std::endl;
             }
         }
+
+        // If we have some data extents at this point, write the bounds to the metadata.
+        if (getDataExtents().size() > 0)
+        {
+            // Get the union of all the extents
+            GeoExtent e(getDataExtents()[0]);
+            for (unsigned int i = 1; i < getDataExtents().size(); i++)
+            {
+                e.expandToInclude(getDataExtents()[i]);
+            }
+
+            // Convert the bounds to wgs84
+            GeoExtent bounds = e.transform(osgEarth::SpatialReference::get("wgs84"));
+            std::stringstream boundsStr;
+            boundsStr << bounds.xMin() << "," << bounds.yMin() << "," << bounds.xMax() << "," << bounds.yMax();
+            putMetaData("bounds", boundsStr.str());
+        }
     }
 
     // If the database pre-existed, read in the information from the metadata.
     else // !isNewDatabase
     {
+        if ( _options.computeLevels() == true )
+        {
+            computeLevels();
+        }
+
         std::string profileStr;
         getMetaData( "profile", profileStr );
 
@@ -162,11 +184,11 @@ MBTilesTileSource::initialize(const osgDB::Options* dbOptions)
 
         // By this point, we require a valid tile format.
         if ( _tileFormat.empty() )
-            return Status::Error("Required format not in metadata, nor specified in the options.");
+            return Status::Error(Status::ConfigurationError, "Required format not in metadata, nor specified in the options.");
 
         _rw = getReaderWriter( _tileFormat );
         if ( !_rw.valid() )
-            return Status::Error("No plugin to load format \"" + _tileFormat + "\"");
+            return Status::Error(Status::ServiceUnavailable, "No plugin to load format \"" + _tileFormat + "\"");
 
         // check for compression.
         std::string compression;
@@ -175,32 +197,10 @@ MBTilesTileSource::initialize(const osgDB::Options* dbOptions)
         {
             _compressor = osgDB::Registry::instance()->getObjectWrapperManager()->findCompressor(compression);
             if ( !_compressor.valid() )
-                return Status::Error("Cannot find compressor \"" + compression + "\"");
+                return Status::Error(Status::ServiceUnavailable, "Cannot find compressor \"" + compression + "\"");
             else
                 OE_INFO << LC << "Data is compressed (" << compression << ")" << std::endl;
-        }
-
-        // Check for bounds and populate DataExtents.
-        std::string boundsStr;
-        if ( getMetaData("bounds", boundsStr) )
-        {
-            std::vector<std::string> tokens;
-            StringTokenizer(",").tokenize(boundsStr, tokens);
-            if (tokens.size() == 4)
-            {
-                GeoExtent extent(
-                    osgEarth::SpatialReference::get("wgs84"),
-                    osgEarth::as<double>(tokens[0], 0.0),
-                    osgEarth::as<double>(tokens[3], 0.0), // south
-                    osgEarth::as<double>(tokens[2], 0.0), // east
-                    osgEarth::as<double>(tokens[1], 0.0)  // north
-                    );
-
-                this->getDataExtents().push_back(DataExtent(extent));
-
-                OE_INFO << LC << "Bounds = " << extent.toString() << std::endl;
-            }
-        }
+        }        
 
         // Set the profile
         const Profile* profile = getProfile();
@@ -224,7 +224,8 @@ MBTilesTileSource::initialize(const osgDB::Options* dbOptions)
                     return Status::Error( Stringify() << "Profile not recognized: " << profileStr );
                 }
             }
-            else
+            
+            if (!profile)
             {
                 // Spherical mercator is the MBTiles default.
                 profile = osgEarth::Registry::instance()->getSphericalMercatorProfile();
@@ -234,10 +235,32 @@ MBTilesTileSource::initialize(const osgDB::Options* dbOptions)
             OE_INFO << LC << "Profile = " << profileStr << std::endl;
         }
 
-        if ( _options.computeLevels() == true )
+        // Check for bounds and populate DataExtents.
+        std::string boundsStr;
+        if ( getMetaData("bounds", boundsStr) )
         {
-            computeLevels();
+            std::vector<std::string> tokens;
+            StringTokenizer(",").tokenize(boundsStr, tokens);
+            if (tokens.size() == 4)
+            {
+                GeoExtent extent(
+                    osgEarth::SpatialReference::get("wgs84"),
+                    osgEarth::as<double>(tokens[0], 0.0),
+                    osgEarth::as<double>(tokens[1], 0.0), // south
+                    osgEarth::as<double>(tokens[2], 0.0), // east
+                    osgEarth::as<double>(tokens[3], 0.0)  // north
+                    );
+
+                this->getDataExtents().push_back(DataExtent(extent, _minLevel, _maxLevel));
+
+                OE_INFO << LC << "Bounds = " << extent.toString() << std::endl;
+            }
+        }
+        else
+        {
+            this->getDataExtents().push_back(DataExtent(getProfile()->getExtent(), _minLevel, _maxLevel));
         }
+
     }
 
     // do we require RGB? for jpeg?
@@ -337,7 +360,7 @@ MBTilesTileSource::createImage(const TileKey&    key,
         if ( valid )
         {
             std::istringstream inputStream(dataBuffer);
-            osgDB::ReaderWriter::ReadResult rr = _rw->readImage( inputStream );
+            osgDB::ReaderWriter::ReadResult rr = _rw->readImage( inputStream, _dbOptions.get() );
             if (rr.validImage())
             {
                 result = rr.takeImage();                
@@ -370,11 +393,11 @@ MBTilesTileSource::storeImage(const TileKey&    key,
     if ( _forceRGB && ImageUtils::hasAlphaChannel(image) )
     {
         osg::ref_ptr<osg::Image> rgb = ImageUtils::convertToRGB8(image);
-        wr = _rw->writeImage(*(rgb.get()), buf);
+        wr = _rw->writeImage(*(rgb.get()), buf, _dbOptions.get());
     }
     else
     {
-        wr = _rw->writeImage(*image, buf);
+        wr = _rw->writeImage(*image, buf, _dbOptions.get());
     }
 
     if ( wr.error() )
@@ -413,7 +436,7 @@ MBTilesTileSource::storeImage(const TileKey&    key,
     if ( rc != SQLITE_OK )
     {
         OE_WARN << LC << "Failed to prepare SQL: " << query << "; " << sqlite3_errmsg(_database) << std::endl;
-        return NULL;
+        return false;
     }
 
     // bind parameters:
diff --git a/src/osgEarthDrivers/model_feature_geom/FeatureGeomModelOptions b/src/osgEarthDrivers/model_feature_geom/FeatureGeomModelOptions
index 27053a9..3f54f44 100644
--- a/src/osgEarthDrivers/model_feature_geom/FeatureGeomModelOptions
+++ b/src/osgEarthDrivers/model_feature_geom/FeatureGeomModelOptions
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthDrivers/model_feature_geom/FeatureGeomModelSource.cpp b/src/osgEarthDrivers/model_feature_geom/FeatureGeomModelSource.cpp
index cd26ee7..cde82ab 100644
--- a/src/osgEarthDrivers/model_feature_geom/FeatureGeomModelSource.cpp
+++ b/src/osgEarthDrivers/model_feature_geom/FeatureGeomModelSource.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -35,6 +35,8 @@ using namespace osgEarth::Drivers;
 
 //------------------------------------------------------------------------
 
+#define LC "[FeatureGeomModelSource] "
+
 namespace
 {
     //------------------------------------------------------------------------
@@ -54,14 +56,9 @@ namespace
 
     public: // FeatureModelSource
 
-        void initialize( const osgDB::Options* dbOptions )
-        {
-            FeatureModelSource::initialize( dbOptions );
-        }
-
         FeatureNodeFactory* createFeatureNodeFactory()
         {
-            return new GeomFeatureNodeFactory( _options.compilerOptions() );
+            return new GeomFeatureNodeFactory(_options.compilerOptions());
         }
 
     private:
@@ -80,7 +77,7 @@ public:
         supportsExtension( "osgearth_model_feature_geom", "osgEarth feature geom plugin" );
     }
 
-    virtual const char* className()
+    virtual const char* className() const
     {
         return "osgEarth Feature Geom Model Plugin";
     }
diff --git a/src/osgEarthDrivers/model_feature_stencil/FeatureStencilModelSource.cpp b/src/osgEarthDrivers/model_feature_stencil/FeatureStencilModelSource.cpp
deleted file mode 100644
index a836259..0000000
--- a/src/osgEarthDrivers/model_feature_stencil/FeatureStencilModelSource.cpp
+++ /dev/null
@@ -1,380 +0,0 @@
-/* -*-c++-*- */
-/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
- * http://osgearth.org
- *
- * osgEarth is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>
- */
-
-#include <osgEarth/Registry>
-#include <osgEarth/Map>
-#include <osgEarthFeatures/FeatureModelSource>
-#include <osgEarthFeatures/FeatureSource>
-#include <osgEarthFeatures/AltitudeFilter>
-#include <osgEarthFeatures/BufferFilter>
-#include <osgEarthFeatures/TransformFilter>
-#include <osgEarthFeatures/ResampleFilter>
-#include <osgEarthFeatures/ConvertTypeFilter>
-#include <osgEarthFeatures/ExtrudeGeometryFilter>
-#include <osgEarthSymbology/StencilVolumeNode>
-#include <osgEarthSymbology/Style>
-#include <osg/Notify>
-#include <osg/MatrixTransform>
-#include <osg/ClusterCullingCallback>
-#include <osg/Geode>
-#include <osg/Projection>
-#include <osgUtil/Tessellator>
-#include <osg/MatrixTransform>
-#include <osgDB/FileNameUtils>
-#include <OpenThreads/Mutex>
-#include <OpenThreads/ScopedLock>
-
-#include "FeatureStencilModelOptions"
-
-using namespace osgEarth;
-using namespace osgEarth::Features;
-using namespace osgEarth::Symbology;
-using namespace osgEarth::Drivers;
-using namespace OpenThreads;
-
-#define LC "[FeatureStencilModelSource] "
-
-#define RENDER_BIN_START 100
-#define MAX_NUM_STYLES   100
-#define OFF_PROTECTED osg::StateAttribute::OFF | osg::StateAttribute::PROTECTED
-
-namespace
-{
-    /** Creates a full-screen quad to fill in the colors on the stencil volume. */
-    osg::Node* createColorNode( const osg::Vec4f& color )
-    {
-        // make a full screen quad:
-        osg::Geometry* quad = new osg::Geometry();
-        quad->setUseVertexBufferObjects(true);
-
-        osg::Vec3Array* verts = new osg::Vec3Array(4);
-        (*verts)[0].set( 0, 1, 0 );
-        (*verts)[1].set( 0, 0, 0 );
-        (*verts)[2].set( 1, 0, 0 );
-        (*verts)[3].set( 1, 1, 0 );
-        quad->setVertexArray( verts );
-        if ( verts->getVertexBufferObject() )
-            verts->getVertexBufferObject()->setUsage(GL_STATIC_DRAW_ARB);
-
-        quad->addPrimitiveSet( new osg::DrawArrays( osg::PrimitiveSet::QUADS, 0, 4 ) );
-        osg::Vec4Array* colors = new osg::Vec4Array(1);
-        (*colors)[0] = color;
-        quad->setColorArray( colors );
-        quad->setColorBinding( osg::Geometry::BIND_OVERALL );
-        osg::Geode* quad_geode = new osg::Geode();
-        quad_geode->addDrawable( quad );
-
-        osg::StateSet* quad_ss = quad->getOrCreateStateSet();
-        quad_ss->setMode( GL_CULL_FACE, OFF_PROTECTED );
-        quad_ss->setMode( GL_DEPTH_TEST, OFF_PROTECTED );
-        quad_ss->setMode( GL_LIGHTING, OFF_PROTECTED );
-        osg::MatrixTransform* abs = new osg::MatrixTransform();
-        abs->setReferenceFrame( osg::Transform::ABSOLUTE_RF );
-        abs->setMatrix( osg::Matrix::identity() );
-        abs->addChild( quad_geode );
-
-        osg::Projection* proj = new osg::Projection();
-        proj->setMatrix( osg::Matrix::ortho(0, 1, 0, 1, 0, -1) );
-        proj->addChild( abs );
-
-        proj->getOrCreateStateSet()->setMode( GL_BLEND, 1 );    
-
-        return proj;
-    }
-
-    struct BuildData // : public osg::Referenced
-    {
-        //BuildData() { }
-        BuildData( int renderBinStart ) : _renderBin( renderBinStart ) { }
-
-        typedef std::pair<std::string, osg::ref_ptr<StencilVolumeNode> > StyleGroup;
-        int                       _renderBin;
-        Threading::ReadWriteMutex _mutex;
-        std::vector<StyleGroup>   _styleGroups;  // NOTE: DO NOT ACCESS without a mutex!
-
-
-        bool getStyleNode( const std::string& styleName, StencilVolumeNode*& out_svn, bool useLock )
-        {
-            if ( useLock )
-            {
-                Threading::ScopedReadLock lock( _mutex );
-                return getStyleNodeWithoutLocking( styleName, out_svn );
-            }
-            else
-            {
-                return getStyleNodeWithoutLocking( styleName, out_svn );
-            }
-        }
-
-    private:
-        bool getStyleNodeWithoutLocking( const std::string& styleName, StencilVolumeNode*& out_svn )
-        {
-            for(std::vector<StyleGroup>::iterator i = _styleGroups.begin(); i != _styleGroups.end(); ++i )
-            {
-                if( i->first == styleName )
-                {
-                    out_svn = i->second.get();
-                    return true;
-                }
-            }
-            return false;
-        }
-    };
-
-    class StencilVolumeNodeFactory : public FeatureNodeFactory
-    {
-    protected:
-        const FeatureStencilModelOptions _options;
-        int                              _renderBinStart;
-        BuildData                        _buildData;
-
-    public:
-        StencilVolumeNodeFactory( const FeatureStencilModelOptions& options, int renderBinStart )
-            : _options(options),
-              _buildData( renderBinStart )
-        { }
-
-        //override
-        bool createOrUpdateNode(
-            FeatureCursor*            cursor,
-            const Style&              style,
-            const FilterContext&      context,
-            osg::ref_ptr<osg::Node>&  node )
-        {
-            const MapInfo& mi = context.getSession()->getMapInfo();
-            
-            // A processing context to use locally
-            FilterContext cx = context;
-
-            // make a working copy of the feature data.
-            FeatureList featureList;
-            cursor->fill( featureList );
-
-            // establish the extrusion distance for the stencil volumes
-            double extrusionDistance = 1;
-            double densificationThreshold = 1.0;
-            if ( _options.extrusionDistance().isSet() )
-            {
-                extrusionDistance = *_options.extrusionDistance();
-            }
-            else
-            {
-                if ( mi.isGeocentric() )
-                    extrusionDistance = 300000.0; // meters geocentric
-                else if ( mi.getProfile()->getSRS()->isGeographic() )
-                    extrusionDistance = 5.0; // degrees-as-meters
-                else
-                    extrusionDistance = 12000.0; // meters
-            }
-
-            densificationThreshold = *_options.densificationThreshold();
-
-            // Scan the geometry to see if it includes line data, since that will require buffering:
-            bool hasLines = style.has<LineSymbol>() && !style.has<PolygonSymbol>();
-
-            // If the geometry is lines, we need to buffer them before they will work with stenciling
-            if ( hasLines )
-            {
-                const LineSymbol* line = style.getSymbol<LineSymbol>();
-                if (line)
-                {
-                    BufferFilter buffer;
-                    buffer.distance() = 0.5 * line->stroke()->width().value();
-                    buffer.capStyle() = line->stroke()->lineCap().value();
-                    cx = buffer.push( featureList, cx );
-                }
-            }
-
-            // Extrude and cap the geometry in both directions to build a stencil volume:
-
-            Style bs;
-            bs.getOrCreate<AltitudeSymbol>()->verticalOffset() = -extrusionDistance;
-            bs.getOrCreate<ExtrusionSymbol>()->height() = extrusionDistance * 2.0;
-            
-            AltitudeFilter alt;
-            alt.setPropertiesFromStyle( bs );
-            cx = alt.push( featureList, cx );
-
-            ExtrudeGeometryFilter extrude;
-            extrude.setStyle( bs );
-            extrude.setMakeStencilVolume( true );
-            osg::Node* volumes = extrude.push( featureList, cx );           
-
-            if ( volumes )
-            {
-                // Apply an LOD if required:
-                if ( _options.minRange().isSet() || _options.maxRange().isSet() )
-                {
-                    osg::LOD* lod = new osg::LOD();
-                    lod->addChild( volumes, _options.minRange().value(), _options.maxRange().value() );
-                    volumes = lod;
-                }
-
-                // Add the volumes to the appropriate style group.
-                osg::Group* styleGroup = getOrCreateStyleGroup( style, cx.getSession() );
-                StencilVolumeNode* svNode = dynamic_cast<StencilVolumeNode*>( styleGroup );
-                if ( svNode )
-                    svNode->addVolumes( volumes );
-                else
-                    styleGroup->addChild( volumes );
-            }
-
-            node = 0L; // always return null, since we added our geom to the style group.
-            return volumes != 0L;
-        }
-
-        //override
-        osg::Group* getOrCreateStyleGroup( const Style& style, Session* session )
-        {
-            if ( _options.showVolumes() == true )
-            {
-                return new osg::Group();
-            }
-            else
-            {
-                StencilVolumeNode* styleNode = 0L;
-                if ( !_buildData.getStyleNode(style.getName(), styleNode, true) )
-                {
-                    // did not find; write-lock it and try again (double-check pattern)
-                    Threading::ScopedWriteLock exclusiveLock( _buildData._mutex );
-
-                    if ( !_buildData.getStyleNode(style.getName(), styleNode, false) )
-                    {
-                        OE_INFO << LC << "Create style group \"" << style.getName() << "\"" << std::endl;
-
-                        styleNode = new StencilVolumeNode( *_options.mask(), *_options.inverted() );
-
-                        if ( _options.mask() == false )
-                        {
-                            osg::Vec4f maskColor = osg::Vec4(1,1,0,1);
-
-                            if (/*hasLines &&*/ style.getSymbol<LineSymbol>())
-                            {
-                                const LineSymbol* line = style.getSymbol<LineSymbol>();
-                                maskColor = line->stroke()->color();
-                            } 
-                            else
-                            {
-                                const PolygonSymbol* poly = style.getSymbol<PolygonSymbol>();
-                                if (poly)
-                                    maskColor = poly->fill()->color();
-                            }
-                            styleNode->addChild( createColorNode(maskColor) );
-                            
-                            osg::StateSet* ss = styleNode->getOrCreateStateSet();
-
-                            ss->setMode( GL_LIGHTING, _options.enableLighting() == true?
-                                 osg::StateAttribute::ON | osg::StateAttribute::PROTECTED :
-                                 osg::StateAttribute::OFF | osg::StateAttribute::PROTECTED );
-                        }
-
-                        _buildData._renderBin = styleNode->setBaseRenderBin( _buildData._renderBin );
-                        _buildData._styleGroups.push_back( BuildData::StyleGroup(style.getName(), styleNode) );
-                    }
-                }
-
-                return styleNode;
-            }
-        }
-    };
-
-
-    class FeatureStencilModelSource : public FeatureModelSource
-    {
-    public:
-        FeatureStencilModelSource( const ModelSourceOptions& options, int renderBinStart ) :
-            FeatureModelSource( options ),
-            _options( options ),
-            _renderBinStart( renderBinStart )
-        {
-            // make sure we have stencil bits. Note, this only works before
-            // a viewer gets created. You may need to allocate stencil bits
-            // yourself if you make this object after realizing a viewer.
-            if ( osg::DisplaySettings::instance()->getMinimumNumStencilBits() < 8 )
-            {
-                osg::DisplaySettings::instance()->setMinimumNumStencilBits( 8 );
-            }
-        }
-        
-    public: // FeatureModelSource
-
-        virtual const FeatureModelSourceOptions& getFeatureModelOptions() const
-        {
-            return _options;
-        }
-
-        void initialize( const osgDB::Options* dbOptions )
-        {
-            FeatureModelSource::initialize( dbOptions );
-        }
-
-        FeatureNodeFactory* createFeatureNodeFactory()
-        {
-            return new StencilVolumeNodeFactory( _options, _renderBinStart );
-        }
-
-    protected:
-        int _renderBinStart;
-        const FeatureStencilModelOptions _options;
-    };
-}
-
-
-class FeatureStencilModelSourceDriver : public ModelSourceDriver
-{
-public:
-    FeatureStencilModelSourceDriver() :
-        _renderBinStart( RENDER_BIN_START )
-    {
-        supportsExtension( "osgearth_model_feature_stencil", "osgEarth feature stencil plugin" );
-    }
-
-    virtual const char* className()
-    {
-        return "osgEarth Feature Stencil Model Plugin";
-    }
-
-    FeatureStencilModelSource* create( const Options* options )
-    {
-        ScopedLock<Mutex> lock( _createMutex );
-
-        FeatureStencilModelSource* obj = new FeatureStencilModelSource( 
-            getModelSourceOptions(options), 
-            _renderBinStart );
-
-        _renderBinStart += MAX_NUM_STYLES*4;
-
-        return obj;
-    }
-
-    virtual ReadResult readObject(const std::string& file_name, const Options* options) const
-    {
-        if ( !acceptsExtension(osgDB::getLowerCaseFileExtension( file_name )))
-            return ReadResult::FILE_NOT_HANDLED;
-
-        FeatureStencilModelSourceDriver* nonConstThis = const_cast<FeatureStencilModelSourceDriver*>(this);
-        return nonConstThis->create( options );
-    }
-
-protected:
-    Mutex _createMutex;
-    int _renderBinStart;
-};
-
-REGISTER_OSGPLUGIN(osgearth_model_feature_stencil, FeatureStencilModelSourceDriver)
diff --git a/src/osgEarthDrivers/model_simple/SimpleModelOptions b/src/osgEarthDrivers/model_simple/SimpleModelOptions
index 38317b5..891acda 100644
--- a/src/osgEarthDrivers/model_simple/SimpleModelOptions
+++ b/src/osgEarthDrivers/model_simple/SimpleModelOptions
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthDrivers/model_simple/SimpleModelSource.cpp b/src/osgEarthDrivers/model_simple/SimpleModelSource.cpp
index ac8c4e5..3d870e6 100644
--- a/src/osgEarthDrivers/model_simple/SimpleModelSource.cpp
+++ b/src/osgEarthDrivers/model_simple/SimpleModelSource.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -141,10 +141,11 @@ public:
         : ModelSource( options ), _options(options) { }
 
     //override
-    void initialize( const osgDB::Options* dbOptions )
+    Status initialize( const osgDB::Options* dbOptions )
     {
         _dbOptions = dbOptions;
-        ModelSource::initialize( dbOptions );
+        //ModelSource::initialize( dbOptions );
+        return Status::OK();
     }
 
     // override
@@ -172,7 +173,7 @@ public:
             // Only load the model if it's not paged or we don't have a location set.
             if (!usePagedLOD || !_options.location().isSet())
             {
-                result = _options.url()->getNode( localDBOptions.get(), progress );                
+                result = _options.url()->getNode( localDBOptions.get(), progress );
             }
         }
 
@@ -309,7 +310,7 @@ public:
         supportsExtension( "osgearth_model_simple", "osgEarth simple model plugin" );
     }
 
-    virtual const char* className()
+    virtual const char* className() const
     {
         return "osgEarth Simple Model Plugin";
     }
diff --git a/src/osgEarthDrivers/monitor/CMakeLists.txt b/src/osgEarthDrivers/monitor/CMakeLists.txt
new file mode 100644
index 0000000..11f9238
--- /dev/null
+++ b/src/osgEarthDrivers/monitor/CMakeLists.txt
@@ -0,0 +1,28 @@
+#
+# Monitor Extension
+#
+
+SET(TARGET_SRC
+	MonitorPlugin.cpp
+	MonitorExtension.cpp
+	MonitorUI.cpp)
+	
+SET(LIB_PUBLIC_HEADERS
+	MonitorExtension
+	MonitorUI)
+	
+SET(TARGET_H
+	${LIB_PUBLIC_HEADERS} )
+
+SET(TARGET_COMMON_LIBRARIES ${TARGET_COMMON_LIBRARIES}
+    osgEarthUtil
+    osgEarthFeatures
+    osgEarthSymbology
+    osgEarthAnnotation)
+	
+SETUP_PLUGIN(osgearth_monitor)
+
+SET(LIB_NAME monitor)
+
+INCLUDE(ModuleInstallOsgEarthPluginIncludes OPTIONAL)
+
diff --git a/src/osgEarthDrivers/monitor/MonitorExtension b/src/osgEarthDrivers/monitor/MonitorExtension
new file mode 100644
index 0000000..55acbc0
--- /dev/null
+++ b/src/osgEarthDrivers/monitor/MonitorExtension
@@ -0,0 +1,82 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+ * Copyright 2016 Pelican Mapping
+ * http://osgearth.org
+ *
+ * osgEarth is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ */
+#ifndef OSGEARTH_MONITOR_EXTENSION
+#define OSGEARTH_MONITOR_EXTENSION 1
+
+#include <osgEarth/Extension>
+#include <osgEarth/MapNode>
+#include <osgEarth/MapCallback>
+#include <osgEarthUtil/Controls>
+
+#include "MonitorUI"
+
+namespace osgEarth { namespace Monitor
+{
+    using namespace osgEarth;
+    using namespace osgEarth::Util::Controls;
+
+    /**
+     * Displays visual metadata about the visible layers in a map.
+     */
+    class MonitorExtension : public Extension,
+                             public ExtensionInterface<MapNode>,
+                             public ExtensionInterface<Control>
+    {
+    public:
+        META_Object(osgearth_ext_Monitor, MonitorExtension);
+
+        // CTORs
+        MonitorExtension();
+        MonitorExtension(const ConfigOptions& options);
+
+        // DTOR
+        virtual ~MonitorExtension();
+        
+        void frame(const osg::FrameStamp*);
+
+
+    public: // ExtensionInterface<MapNode>
+
+        bool connect(MapNode* mapNode);
+
+        bool disconnect(MapNode* mapNode);
+
+
+    public: // ExtensionInterface<Control>
+
+        bool connect(Control* control);
+
+        bool disconnect(Control* control);
+
+
+    protected: // Object
+
+        MonitorExtension(const MonitorExtension& rhs, const osg::CopyOp& op) { }
+
+
+    private:
+        osg::observer_ptr<MapNode> _mapNode;
+        osg::ref_ptr<MonitorUI>      _ui;
+
+        void ctor();
+    };
+
+} } // namespace osgEarth::Monitor
+
+#endif // OSGEARTH_MONITOR_EXTENSION
diff --git a/src/osgEarthDrivers/monitor/MonitorExtension.cpp b/src/osgEarthDrivers/monitor/MonitorExtension.cpp
new file mode 100644
index 0000000..f0a33ee
--- /dev/null
+++ b/src/osgEarthDrivers/monitor/MonitorExtension.cpp
@@ -0,0 +1,127 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+ * Copyright 2016 Pelican Mapping
+ * http://osgearth.org
+ *
+ * osgEarth is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ */
+#include "MonitorExtension"
+#include "MonitorUI"
+
+#include <osgEarthFeatures/FeatureSource>
+#include <osgEarthDrivers/feature_ogr/OGRFeatureOptions>
+#include <osgEarthAnnotation/FeatureNode>
+#include <osgEarthSymbology/Style>
+
+#include <osgGA/GUIEventHandler>
+
+using namespace osgEarth;
+using namespace osgEarth::Util;
+using namespace osgEarth::Util::Controls;
+using namespace osgEarth::Monitor;
+
+#define LC "[Monitor] "
+
+namespace
+{
+    struct EventFrame : public osgGA::GUIEventHandler
+    {
+        EventFrame(MonitorExtension* ext) : _ext(ext) { }
+
+        bool handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa)
+        {
+            if (ea.getEventType() == ea.FRAME)
+            {
+                _ext->frame(aa.asView()->getFrameStamp());
+            }
+            return false;
+        }
+
+        MonitorExtension* _ext;
+    };
+}
+
+MonitorExtension::MonitorExtension()
+{
+    ctor();
+}
+
+MonitorExtension::MonitorExtension(const ConfigOptions& options)
+{
+    ctor();
+}
+
+MonitorExtension::~MonitorExtension()
+{
+    // nop
+}
+
+void
+MonitorExtension::ctor()
+{
+    OE_INFO << LC << "loaded\n";
+    _ui = new MonitorUI();
+}
+
+
+bool
+MonitorExtension::connect(MapNode* mapNode)
+{
+    OE_INFO << LC << "connected\n";
+    if ( mapNode )
+    {
+        _mapNode = mapNode;
+        _mapNode->addEventCallback(new EventFrame(this));
+    }
+    
+    return true;
+}
+
+bool
+MonitorExtension::disconnect(MapNode* mapNode)
+{
+    OE_INFO << LC << "disconnected\n";
+
+    return true;
+}
+
+bool
+MonitorExtension::connect(Control* control)
+{
+    Container* container = dynamic_cast<Container*>(control);
+    if ( container && _ui.valid() )
+    {
+        container->addControl( _ui.get() );
+    }
+
+    return true;
+}
+
+bool
+MonitorExtension::disconnect(Control* control)
+{
+    Container* container = dynamic_cast<Container*>(control);
+    if ( container && _ui.valid() )
+    {
+        container->removeChild( _ui.get() );
+    }
+    return true;
+}
+
+void
+MonitorExtension::frame(const osg::FrameStamp* fs)
+{
+    if (_ui.valid())
+        _ui->update(fs);
+}
\ No newline at end of file
diff --git a/src/osgEarthDrivers/monitor/MonitorPlugin.cpp b/src/osgEarthDrivers/monitor/MonitorPlugin.cpp
new file mode 100644
index 0000000..391caa0
--- /dev/null
+++ b/src/osgEarthDrivers/monitor/MonitorPlugin.cpp
@@ -0,0 +1,55 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+ * Copyright 2016 Pelican Mapping
+ * http://osgearth.org
+ *
+ * osgEarth is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ */
+#include "MonitorExtension"
+
+#include <osgDB/ReaderWriter>
+#include <osgDB/Registry>
+#include <osgDB/FileNameUtils>
+
+namespace osgEarth { namespace Monitor
+{
+    /**
+     * Plugin entry point
+     */
+    class MonitorPlugin : public osgDB::ReaderWriter
+    {
+    public: // Plugin stuff
+
+        MonitorPlugin() {
+            supportsExtension( "osgearth_monitor", "osgEarth Monitor Extension" );
+        }
+        
+        const char* className() const {
+            return "osgEarth Monitor Extension";
+        }
+
+        virtual ~MonitorPlugin() { }
+
+        ReadResult readObject(const std::string& filename, const osgDB::Options* dbOptions) const
+        {
+          if ( !acceptsExtension(osgDB::getLowerCaseFileExtension(filename)) )
+                return ReadResult::FILE_NOT_HANDLED;
+
+          return ReadResult( new MonitorExtension(Extension::getConfigOptions(dbOptions)) );
+        }
+    };
+
+    REGISTER_OSGPLUGIN(osgearth_monitor, MonitorPlugin)
+
+} } // namespace osgEarth::Monitor
diff --git a/src/osgEarthDrivers/monitor/MonitorUI b/src/osgEarthDrivers/monitor/MonitorUI
new file mode 100644
index 0000000..64d4775
--- /dev/null
+++ b/src/osgEarthDrivers/monitor/MonitorUI
@@ -0,0 +1,46 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+ * Copyright 2016 Pelican Mapping
+ * http://osgearth.org
+ *
+ * osgEarth is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ */
+#ifndef OSGEARTH_Monitor_UI
+#define OSGEARTH_Monitor_UI 1
+
+#include <osgEarth/MapCallback>
+#include <osgEarth/MapNode>
+#include <osgEarthUtil/Controls>
+#include <osg/View>
+
+namespace osgEarth { namespace Monitor
+{
+    using namespace osgEarth;
+    namespace ui = osgEarth::Util::Controls;
+
+    class MonitorUI : public osgEarth::Util::Controls::Grid
+    {
+    public:
+        /** create UI */
+        MonitorUI();
+
+        void update(const osg::FrameStamp*);
+
+    private:
+        osg::ref_ptr<ui::LabelControl> _pb, _ws, _ppb;
+    };
+
+} } // namespace
+
+#endif // OSGEARTH_Monitor_UI
\ No newline at end of file
diff --git a/src/osgEarthDrivers/monitor/MonitorUI.cpp b/src/osgEarthDrivers/monitor/MonitorUI.cpp
new file mode 100644
index 0000000..1df2537
--- /dev/null
+++ b/src/osgEarthDrivers/monitor/MonitorUI.cpp
@@ -0,0 +1,69 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+ * Copyright 2016 Pelican Mapping
+ * http://osgearth.org
+ *
+ * osgEarth is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ */
+#include "MonitorUI"
+#include <osgEarth/Memory>
+#include <osgEarth/Registry>
+
+using namespace osgEarth::Monitor;
+using namespace osgEarth;
+using namespace osgEarth::Util;
+
+namespace ui = osgEarth::Util::Controls;
+
+#define LC "[MonitorUI] "
+
+MonitorUI::MonitorUI()
+{
+    this->setHorizAlign(ALIGN_RIGHT);
+    this->setVertAlign(ALIGN_BOTTOM);
+
+    int r=0;
+
+    this->setControl(0, r, new ui::LabelControl("Physical RAM:"));
+    _ws = new ui::LabelControl();
+    _ws->setHorizAlign(ALIGN_RIGHT);
+    this->setControl(1, r, _ws.get());
+    ++r;
+
+    this->setControl(0, r, new ui::LabelControl("Total RAM:"));
+    _pb = new ui::LabelControl();
+    _pb->setHorizAlign(ALIGN_RIGHT);
+    this->setControl(1, r, _pb.get());
+    ++r;
+
+    this->setControl(0, r, new ui::LabelControl("Peak RAM:"));
+    _ppb = new ui::LabelControl();
+    _ppb->setHorizAlign(ALIGN_RIGHT);
+    this->setControl(1, r, _ppb.get());
+    ++r;
+}
+
+void
+MonitorUI::update(const osg::FrameStamp* fs)
+{
+    if (fs && fs->getFrameNumber() % 15 == 0)
+    {
+        _ws->setText(Stringify() << (Memory::getProcessPhysicalUsage() / 1048576) << " M");
+        _pb->setText(Stringify() << (Memory::getProcessPrivateUsage() / 1048576) << " M");
+        _ppb->setText(Stringify() << (Memory::getProcessPeakPrivateUsage() / 1048576) << " M");
+
+        //Registry::instance()->startActivity("Current Mem", Stringify() <<  (bytes / 1048576) << " M");
+        //Registry::instance()->startActivity("Peak Mem", Stringify() << (Memory::getProcessPeakUsage() / 1048576) << " M");
+    }
+}
diff --git a/src/osgEarthDrivers/noise/CMakeLists.txt b/src/osgEarthDrivers/noise/CMakeLists.txt
new file mode 100644
index 0000000..0f877c9
--- /dev/null
+++ b/src/osgEarthDrivers/noise/CMakeLists.txt
@@ -0,0 +1,24 @@
+#
+# Noise generator plugin
+#
+
+set(TARGET_SRC
+	NoiseExtension.cpp
+	NoiseTerrainEffect.cpp
+	${SHADERS_CPP} )
+	
+set(LIB_PUBLIC_HEADERS
+	NoiseExtension
+	NoiseOptions
+	NoiseTerrainEffect)
+	
+set(TARGET_H
+	${LIB_PUBLIC_HEADERS} )
+
+set(TARGET_COMMON_LIBRARIES ${TARGET_COMMON_LIBRARIES}
+    osgEarthUtil)
+	
+setup_plugin(osgearth_noise)
+
+# to install public driver includes:
+set(LIB_NAME noise)
diff --git a/src/osgEarthDrivers/noise/NoiseExtension b/src/osgEarthDrivers/noise/NoiseExtension
new file mode 100644
index 0000000..0b572d1
--- /dev/null
+++ b/src/osgEarthDrivers/noise/NoiseExtension
@@ -0,0 +1,74 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+ * Copyright 2016 Pelican Mapping
+ * http://osgearth.org
+ *
+ * osgEarth is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ */
+#ifndef OSGEARTH_NOISE_EXTENSION
+#define OSGEARTH_NOISE_EXTENSION 1
+
+#include "NoiseOptions"
+#include "NoiseTerrainEffect"
+#include <osgEarth/Extension>
+#include <osgEarth/MapNode>
+#include <osgEarthUtil/Controls>
+
+namespace osgEarth { namespace Noise
+{
+    using namespace osgEarth;
+    using namespace osgEarth::Util::Controls;
+
+    /**
+     * Extension for loading the normal mapping effect on demand.
+     */
+    class NoiseExtension : public Extension,
+                           public ExtensionInterface<MapNode>,
+                           public NoiseOptions
+    {
+    public:
+        META_Object(osgearth_ext_normalmap, NoiseExtension);
+
+        // CTORs
+        NoiseExtension();
+        NoiseExtension(const NoiseOptions& options);
+
+        // DTOR
+        virtual ~NoiseExtension();
+
+
+    public: // Extension
+
+        virtual void setDBOptions(const osgDB::Options* dbOptions);
+
+        virtual const ConfigOptions& getConfigOptions() const { return *this; }
+
+    public: // ExtensionInterface<MapNode>
+
+        bool connect(MapNode* mapNode);
+
+        bool disconnect(MapNode* mapNode);
+
+
+    protected: // Object
+        NoiseExtension(const NoiseExtension& rhs, const osg::CopyOp& op) { }
+
+    private:
+        osg::ref_ptr<const osgDB::Options> _dbOptions;
+        osg::ref_ptr<NoiseTerrainEffect>   _effect;
+    };
+
+} } // namespace osgEarth::Noise
+
+#endif // OSGEARTH_NOISE_EXTENSION
diff --git a/src/osgEarthDrivers/noise/NoiseExtension.cpp b/src/osgEarthDrivers/noise/NoiseExtension.cpp
new file mode 100644
index 0000000..935bffd
--- /dev/null
+++ b/src/osgEarthDrivers/noise/NoiseExtension.cpp
@@ -0,0 +1,80 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+ * Copyright 2016 Pelican Mapping
+ * http://osgearth.org
+ *
+ * osgEarth is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ */
+#include "NoiseExtension"
+#include "NoiseTerrainEffect"
+#include <osgEarth/TerrainEngineNode>
+
+using namespace osgEarth;
+using namespace osgEarth::Noise;
+
+#define LC "[NoiseExtension] "
+
+
+REGISTER_OSGEARTH_EXTENSION( osgearth_noise, NoiseExtension )
+
+
+NoiseExtension::NoiseExtension()
+{
+    //nop
+}
+
+NoiseExtension::NoiseExtension(const NoiseOptions& options) :
+NoiseOptions( options )
+{
+    //nop
+}
+
+NoiseExtension::~NoiseExtension()
+{
+    //nop
+}
+
+void
+NoiseExtension::setDBOptions(const osgDB::Options* dbOptions)
+{
+    _dbOptions = dbOptions;
+}
+
+bool
+NoiseExtension::connect(MapNode* mapNode)
+{
+    if ( !mapNode )
+    {
+        OE_WARN << LC << "Illegal: MapNode cannot be null." << std::endl;
+        return false;
+    }
+
+    _effect = new NoiseTerrainEffect( *this );
+
+    mapNode->getTerrainEngine()->addEffect( _effect.get() );
+    
+    return true;
+}
+
+bool
+NoiseExtension::disconnect(MapNode* mapNode)
+{
+    if ( mapNode )
+    {
+        mapNode->getTerrainEngine()->removeEffect( _effect.get() );
+    }
+    _effect = 0L;
+    return true;
+}
+
diff --git a/src/osgEarthDrivers/noise/NoiseOptions b/src/osgEarthDrivers/noise/NoiseOptions
new file mode 100644
index 0000000..5c7c0e5
--- /dev/null
+++ b/src/osgEarthDrivers/noise/NoiseOptions
@@ -0,0 +1,82 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+ * Copyright 2016 Pelican Mapping
+ * http://osgearth.org
+ *
+ * osgEarth is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ */
+#ifndef OSGEARTH_DRIVER_NOISE_OPTIONS
+#define OSGEARTH_DRIVER_NOISE_OPTIONS 1
+
+#include <osgEarth/Common>
+#include <osgEarth/URI>
+
+namespace osgEarth { namespace Noise
+{
+    using namespace osgEarth;
+
+    /**
+     * Options governing the terrain noise texture.
+     */
+    class NoiseOptions : public DriverConfigOptions // NO EXPORT; header only
+    {
+    public:
+        /** Size of the noise texture in the U and V dimensions. Default = 1024. */
+        optional<unsigned>& size() { return _size; }
+        const optional<unsigned>& size() const { return _size; }
+
+        /** Number of channels of noise to make (1-4) default = 1. */
+        optional<unsigned>& numChannels() { return _numChannels; }
+        const optional<unsigned>& numChannels() const { return _numChannels; }
+
+
+    public:
+        NoiseOptions( const ConfigOptions& opt =ConfigOptions() ) : DriverConfigOptions( opt )
+        {
+            setDriver( "noise" );
+            _size.init( 1024u );
+            _numChannels.init( 1u );
+            fromConfig( _conf );
+        }
+
+        virtual ~NoiseOptions() { }
+
+    public:
+        Config getConfig() const {
+            Config conf = DriverConfigOptions::getConfig();
+            conf.addIfSet( "size", _size );
+            conf.addIfSet( "num_channels", _numChannels );
+            return conf;
+        }
+
+    protected:
+        void mergeConfig( const Config& conf ) {
+            DriverConfigOptions::mergeConfig( conf );
+            fromConfig( conf );
+        }
+
+    private:
+        void fromConfig( const Config& conf ) {
+            conf.getIfSet( "size", _size );
+            conf.getIfSet( "num_channels", _numChannels );
+        }
+
+        optional<unsigned> _size;
+        optional<unsigned> _numChannels;
+    };
+
+} } // namespace osgEarth::Noise
+
+#endif // OSGEARTH_DRIVER_NOISE_OPTIONS
+
diff --git a/src/osgEarthDrivers/noise/NoiseTerrainEffect b/src/osgEarthDrivers/noise/NoiseTerrainEffect
new file mode 100644
index 0000000..50a0bf1
--- /dev/null
+++ b/src/osgEarthDrivers/noise/NoiseTerrainEffect
@@ -0,0 +1,65 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+* Copyright 2008-2012 Pelican Mapping
+* http://osgearth.org
+*
+* osgEarth is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* 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.
+*
+* You should have received a copy of the GNU Lesser General Public License
+* along with this program.  If not, see <http://www.gnu.org/licenses/>
+*/
+#ifndef OSGEARTH_NOISE_TERRAIN_EFFECT_H
+#define OSGEARTH_NOISE_TERRAIN_EFFECT_H
+
+#include "NoiseOptions"
+
+#include <osgEarth/TerrainEffect>
+#include <osg/Uniform>
+#include <osg/Texture2D>
+
+using namespace osgEarth;
+
+namespace osgEarth { namespace Noise
+{
+    /**
+     * Effect that activates a multi-resolution noise texture on the terrain.
+     */
+    class NoiseTerrainEffect : public TerrainEffect
+    {
+    public:
+        /** construct a new terrain effect. */
+        NoiseTerrainEffect(const NoiseOptions& options);        
+
+
+    public: // TerrainEffect interface
+
+        void onInstall(TerrainEngineNode* engine);
+
+        void onUninstall(TerrainEngineNode* engine);
+
+
+    protected:
+        virtual ~NoiseTerrainEffect() { }
+
+        osg::Texture* createNoiseTexture() const;
+
+        NoiseOptions                 _options;
+        int                          _texImageUnit;
+        osg::ref_ptr<osg::Texture>   _tex;
+        osg::ref_ptr<osg::Uniform>   _samplerUniform;
+    };
+
+} } // namespace osgEarth::Noise
+
+#endif // OSGEARTH_NOISE_TERRAIN_EFFECT_H
diff --git a/src/osgEarthDrivers/noise/NoiseTerrainEffect.cpp b/src/osgEarthDrivers/noise/NoiseTerrainEffect.cpp
new file mode 100644
index 0000000..c891a60
--- /dev/null
+++ b/src/osgEarthDrivers/noise/NoiseTerrainEffect.cpp
@@ -0,0 +1,167 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+* Copyright 2008-2012 Pelican Mapping
+* http://osgearth.org
+*
+* osgEarth is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* 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.
+*
+* You should have received a copy of the GNU Lesser General Public License
+* along with this program.  If not, see <http://www.gnu.org/licenses/>
+*/
+#include "NoiseTerrainEffect"
+
+#include <osgEarth/Registry>
+#include <osgEarth/Capabilities>
+#include <osgEarth/TerrainEngineNode>
+#include <osgEarth/ImageUtils>
+#include <osgEarthUtil/SimplexNoise>
+
+#include <osgDB/WriteFile>
+
+#define LC "[Noise] "
+
+#define SAMPLER_NAME "oe_noise_tex"
+//#define MATRIX_NAME  "oe_nmap_normalTexMatrix"
+
+using namespace osgEarth;
+using namespace osgEarth::Noise;
+
+NoiseTerrainEffect::NoiseTerrainEffect(const NoiseOptions& options) :
+_options     ( options ),
+_texImageUnit( -1 )
+{
+    _tex = createNoiseTexture();
+}
+
+void
+NoiseTerrainEffect::onInstall(TerrainEngineNode* engine)
+{
+    if ( engine )
+    {
+        engine->getResources()->reserveTextureImageUnit(_texImageUnit, "Noise");
+        if ( _texImageUnit >= 0 )
+        {        
+            osg::StateSet* stateset = engine->getOrCreateStateSet();
+            stateset->setTextureAttribute( _texImageUnit, _tex.get() );
+            stateset->addUniform( new osg::Uniform(SAMPLER_NAME, _texImageUnit) );
+            OE_INFO << LC << "Noise generator installed!\n";
+        }
+        else
+        {
+            OE_WARN << LC << "No texture image units available; noise disabled.\n";
+        }
+    }
+}
+
+
+void
+NoiseTerrainEffect::onUninstall(TerrainEngineNode* engine)
+{
+    if ( engine && _texImageUnit >= 0 )
+    {
+        osg::StateSet* stateset = engine->getStateSet();
+        if ( stateset )
+        {
+            stateset->removeUniform( SAMPLER_NAME );
+            stateset->removeTextureAttribute( _texImageUnit, _tex.get() );
+        }
+
+        engine->getResources()->releaseTextureImageUnit( _texImageUnit );
+        _texImageUnit = -1;
+    }
+}
+
+
+osg::Texture*
+NoiseTerrainEffect::createNoiseTexture() const
+{
+    const int size  = (int)osg::clampBetween(_options.size().get(), 1u, 16384u);
+    const int chans = (int)osg::clampBetween(_options.numChannels().get(), 1u, 4u);
+
+    GLenum type = chans > 2 ? GL_RGBA : GL_LUMINANCE;
+    
+    osg::Image* image = new osg::Image();
+    image->allocateImage(size, size, 1, type, GL_UNSIGNED_BYTE);
+
+    // 0 = rocky mountains..
+    // 1 = warping...
+    const float F[4] = { 4.0f, 16.0f, 4.0f, 8.0f };
+    const float P[4] = { 0.8f,  0.6f, 0.8f, 0.9f };
+    const float L[4] = { 2.2f,  1.7f, 3.0f, 4.0f };
+    
+    for(int k=0; k<chans; ++k)
+    {
+        // Configure the noise function:
+        osgEarth::Util::SimplexNoise noise;
+        noise.setNormalize( true );
+        noise.setRange( 0.0, 1.0 );
+        noise.setFrequency( F[k] );
+        noise.setPersistence( P[k] );
+        noise.setLacunarity( L[k] );
+        noise.setOctaves( 8 );
+
+        float nmin = 10.0f;
+        float nmax = -10.0f;
+
+        // write repeating noise to the image:
+        ImageUtils::PixelReader read ( image );
+        ImageUtils::PixelWriter write( image );
+        for(int t=0; t<size; ++t)
+        {
+            double rt = (double)t/size;
+            for(int s=0; s<size; ++s)
+            {
+                double rs = (double)s/(double)size;
+
+                double n = noise.getTiledValue(rs, rt);
+
+                n = osg::clampBetween(n, 0.0, 1.0);
+
+                if ( n < nmin ) nmin = n;
+                if ( n > nmax ) nmax = n;
+                osg::Vec4f v = read(s, t);
+                v[k] = n;
+                write(v, s, t);
+            }
+        }
+   
+        // histogram stretch to [0..1]
+        for(int x=0; x<size*size; ++x)
+        {
+            int s = x%size, t = x/size;
+            osg::Vec4f v = read(s, t);
+            v[k] = osg::clampBetween((v[k]-nmin)/(nmax-nmin), 0.0f, 1.0f);
+            write(v, s, t);
+        }
+
+        //OE_INFO << LC << "Noise: MIN = " << nmin << "; MAX = " << nmax << "\n";
+    }
+
+#if 0
+    std::string filename("noise.png");
+    osgDB::writeImageFile(*image, filename);
+    OE_NOTICE << LC << "Wrote noise texture to " << filename << "\n";
+#endif
+
+    // make a texture:
+    osg::Texture2D* tex = new osg::Texture2D( image );
+    tex->setWrap(tex->WRAP_S, tex->REPEAT);
+    tex->setWrap(tex->WRAP_T, tex->REPEAT);
+    tex->setFilter(tex->MIN_FILTER, tex->LINEAR_MIPMAP_LINEAR);
+    tex->setFilter(tex->MAG_FILTER, tex->LINEAR);
+    tex->setMaxAnisotropy( 4.0f );
+    tex->setUnRefImageDataAfterApply( true );
+
+    return tex;
+}
diff --git a/src/osgEarthDrivers/ocean_simple/CMakeLists.txt b/src/osgEarthDrivers/ocean_simple/CMakeLists.txt
index 298b512..08b162c 100644
--- a/src/osgEarthDrivers/ocean_simple/CMakeLists.txt
+++ b/src/osgEarthDrivers/ocean_simple/CMakeLists.txt
@@ -1,13 +1,30 @@
 
-SET(TARGET_SRC ElevationProxyImageLayer.cpp
-               SimpleOceanDriver.cpp
-               SimpleOceanNode.cpp
+set(TARGET_GLSL
+    SimpleOcean.VS.glsl
+    SimpleOcean.FS.glsl)
+
+set(TARGET_IN
+    Shaders.cpp.in)
+
+set(SHADERS_CPP "${CMAKE_CURRENT_BINARY_DIR}/AutoGenShaders.cpp")
+
+configure_shaders(
+    Shaders.cpp.in
+    ${SHADERS_CPP}
+    ${TARGET_GLSL} )
+
+SET(TARGET_SRC
+    ElevationProxyImageLayer.cpp
+    SimpleOceanDriver.cpp
+    SimpleOceanNode.cpp
+    ${SHADERS_CPP}
 )
                
-SET(TARGET_H   ElevationProxyImageLayer
-               SimpleOceanOptions
-               SimpleOceanNode
-               SimpleOceanShaders
+SET(TARGET_H   
+    ElevationProxyImageLayer
+    SimpleOceanOptions
+    SimpleOceanNode
+    SimpleOceanShaders
 )
 
 SET(TARGET_COMMON_LIBRARIES ${TARGET_COMMON_LIBRARIES}
diff --git a/src/osgEarthDrivers/ocean_simple/ElevationProxyImageLayer b/src/osgEarthDrivers/ocean_simple/ElevationProxyImageLayer
index ea917a6..f53fe1c 100644
--- a/src/osgEarthDrivers/ocean_simple/ElevationProxyImageLayer
+++ b/src/osgEarthDrivers/ocean_simple/ElevationProxyImageLayer
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -23,7 +23,7 @@
 #include <osgEarth/ImageLayer>
 #include <osgEarth/ThreadingUtils>
 
-namespace osgEarth { namespace Drivers { namespace SimpleOcean
+namespace osgEarth { namespace SimpleOcean
 {
     using namespace osgEarth;
 
@@ -60,6 +60,6 @@ namespace osgEarth { namespace Drivers { namespace SimpleOcean
         Threading::Mutex _mapfMutex;
     };
 
-} } } // namespace osgEarth::Drivers::SimpleOcean
+} } // namespace osgEarth::SimpleOcean
 
 #endif // OSGEARTH_DRIVER_SIMPLE_OCEAN_ELEV_PROXY_IMAGE_LAYER
diff --git a/src/osgEarthDrivers/ocean_simple/ElevationProxyImageLayer.cpp b/src/osgEarthDrivers/ocean_simple/ElevationProxyImageLayer.cpp
index fb1891c..f3d26cb 100644
--- a/src/osgEarthDrivers/ocean_simple/ElevationProxyImageLayer.cpp
+++ b/src/osgEarthDrivers/ocean_simple/ElevationProxyImageLayer.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -18,8 +18,10 @@
  */
 #include "ElevationProxyImageLayer"
 
+#include <osgEarth/HeightFieldUtils>
+
 using namespace osgEarth;
-using namespace osgEarth::Drivers::SimpleOcean;
+using namespace osgEarth::SimpleOcean;
 
 #define LC "[ElevationProxyImageLayer] "
 
@@ -62,7 +64,7 @@ ElevationProxyImageLayer::createImage(const TileKey& key, ProgressCallback* prog
         }
     }
 
-    osg::ref_ptr<osg::HeightField> hf;
+    osg::ref_ptr<osg::HeightField> hf = HeightFieldUtils::createReferenceHeightField(key.getExtent(), 257,257, true );
 
     if ( _mapf.populateHeightField(hf, key, true, 0L) )
     {
diff --git a/src/osgEarthDrivers/ocean_simple/Shaders.cpp.in b/src/osgEarthDrivers/ocean_simple/Shaders.cpp.in
new file mode 100644
index 0000000..014f3cd
--- /dev/null
+++ b/src/osgEarthDrivers/ocean_simple/Shaders.cpp.in
@@ -0,0 +1,14 @@
+// ***DO NOT EDIT THIS FILE - IT IS AUTOMATICALLY GENERATED BY CMAKE***
+
+#include <osgEarthDrivers/ocean_simple/SimpleOceanShaders>
+
+using namespace osgEarth::SimpleOcean;
+
+Shaders::Shaders()
+{    
+    VERT_MODEL = "SimpleOcean.VS.glsl";
+    _sources[VERT_MODEL] = "@SimpleOcean.VS.glsl@";
+
+    FRAG = "SimpleOcean.FS.glsl";
+    _sources[FRAG] = "@SimpleOcean.FS.glsl@";
+}
diff --git a/src/osgEarthDrivers/ocean_simple/SimpleOcean.FS.glsl b/src/osgEarthDrivers/ocean_simple/SimpleOcean.FS.glsl
new file mode 100644
index 0000000..d713651
--- /dev/null
+++ b/src/osgEarthDrivers/ocean_simple/SimpleOcean.FS.glsl
@@ -0,0 +1,114 @@
+#version $GLSL_VERSION_STR
+
+#pragma vp_name       SimpleOcean Proxy FS
+#pragma vp_entryPoint oe_ocean_fragment
+#pragma vp_location   fragment_coloring
+#pragma vp_order      0.6
+#pragma vp_define     USE_OCEAN_MASK
+
+// clamps a value to the vmin/vmax range, then re-maps it to the r0/r1 range:
+float ocean_remap( float val, float vmin, float vmax, float r0, float r1 )  
+{  
+    float vr = (clamp(val, vmin, vmax)-vmin)/(vmax-vmin);  
+    return r0 + vr * (r1-r0);  
+}  
+
+// uniforms
+uniform bool ocean_has_surface_tex;           // whether there's a surface texture
+uniform sampler2D ocean_surface_tex;          // surface texture
+uniform float ocean_seaLevel;                 // sea level offset
+uniform float ocean_lowFeather;               // offset from sea level at which to start feathering out
+uniform float ocean_highFeather;              // offset from sea level at which to stop feathering out
+uniform vec4  ocean_baseColor;                // base ocean color before processing
+uniform float ocean_max_range;                // maximum visible distance of the ocean
+uniform float ocean_fade_range;               // distance over which to fade in the ocean
+uniform float oe_ocean_alpha;                 // The ocean alpha
+
+// inputs from vertex stage
+in float ocean_v_msl;                    // elevation (MSL) of camera
+in float ocean_v_range;                  // distance from camera to current vertex
+in float ocean_v_enorm;                  // normalized terrain height at vertex [0..1]
+in vec4 ocean_surface_tex_coord;         // surface texture coords
+
+
+#ifdef USE_OCEAN_MASK
+
+uniform sampler2D ocean_data;
+in vec4 ocean_mask_tex_coord;
+
+// Ocean mask version:
+void oe_ocean_fragment(inout vec4 color)  
+{  
+    color = ocean_baseColor;  
+
+    // amplify the range's effect on alpha when the camera elevation gets low
+    float rangeFactor = ocean_remap( ocean_v_msl, -10000.0, 10000.0, 10.0, 1.0 );  
+
+    // affect alpha based on the distance from the camera
+    float rangeEffect = ocean_remap( 
+       ocean_v_range, 
+       ocean_max_range - ocean_fade_range, ocean_max_range * rangeFactor, 
+       1.0, 0.0);  
+
+    // start with the surface texture.
+    if (ocean_has_surface_tex)  
+    {  
+        float a1 = texture(ocean_surface_tex, ocean_surface_tex_coord.xy).r;  
+        float a2 = -texture(ocean_surface_tex, ocean_surface_tex_coord.zw).r;  
+        const float contrast = 1.0;
+        float brightness = 1.0 + 0.5*(a1+a2);
+        color = clamp(((color-0.5)*contrast + 0.5) * brightness, 0.0, 1.0);
+        color.a = ocean_baseColor.a; 
+        color.a = max(color.a, ocean_baseColor.a);
+    }  
+
+    // effect of the terrain mask [0..1] in the alpha component.
+    float maskEffect = texture(ocean_data, ocean_mask_tex_coord.xy).a;  
+
+    // color it
+    color = vec4( color.rgb, maskEffect * rangeEffect * color.a * oe_ocean_alpha );  
+
+    //"    color = vec4( 1, 0, 0, 1 );   // debugging
+}
+
+#else
+
+// Proxy layer version:
+void oe_ocean_fragment(inout vec4 color)  
+{  
+    color = ocean_baseColor;  
+
+    // amplify the range's effect on alpha when the camera elevation gets low
+    float rangeFactor = ocean_remap( ocean_v_msl, -10000.0, 10000.0, 10.0, 1.0 );  
+
+    // affect alpha based on the distance from the camera
+    float rangeEffect = ocean_remap( 
+        ocean_v_range, 
+        ocean_max_range - ocean_fade_range, ocean_max_range * rangeFactor, 
+        1.0, 0.0);  
+
+    // start with the surface texture.
+    if (ocean_has_surface_tex)  
+    {  
+        float a1 = texture(ocean_surface_tex, ocean_surface_tex_coord.xy).r;  
+        float a2 = -texture(ocean_surface_tex, ocean_surface_tex_coord.zw).r;  
+        const float contrast = 1.0;
+        float brightness = 1.0 + 0.5*(a1+a2);
+        color = clamp(((color-0.5)*contrast + 0.5) * brightness, 0.0, 1.0);
+        color.a = ocean_baseColor.a; 
+        color.a = max(color.a, ocean_baseColor.a);
+    }  
+
+    // un-normalize the heightfield data
+    float terrainHeight = (ocean_v_enorm * 65535.0) - 32768.0;  
+
+    // heightfield's effect on alpha [0..1]
+    float terrainEffect = ocean_remap( terrainHeight, ocean_seaLevel+ocean_lowFeather, ocean_seaLevel+ocean_highFeather, 1.0, 0.0 );   
+
+    // color it
+    color = vec4( color.rgb, terrainEffect * rangeEffect * oe_ocean_alpha * color.a );  
+
+    //     color = vec4( 1, 0, 0, 1 );   // debugging
+}
+
+#endif
diff --git a/src/osgEarthDrivers/ocean_simple/SimpleOcean.VS.glsl b/src/osgEarthDrivers/ocean_simple/SimpleOcean.VS.glsl
new file mode 100644
index 0000000..e58d977
--- /dev/null
+++ b/src/osgEarthDrivers/ocean_simple/SimpleOcean.VS.glsl
@@ -0,0 +1,102 @@
+#version $GLSL_VERSION_STR
+
+#pragma vp_name       SimpleOcean with Proxy VS
+#pragma vp_entryPoint oe_ocean_vertex
+#pragma vp_location   vertex_view
+#pragma vp_define     USE_OCEAN_MASK
+
+// convert an ecef coordinate to lon/lat (low precision)
+vec2 ocean_xyz_to_spherical(in vec3 xyz)  
+{  
+    float r = length(xyz);  
+    float lat = acos(xyz.z/r);  
+    float lon = atan(xyz.y, xyz.x);  
+    return vec2(lon,lat);  
+}  
+
+// uniforms
+uniform mat4 osg_ViewMatrixInverse;  
+uniform float osg_FrameTime;  
+uniform sampler2D ocean_data;                 // heightfield encoded into 16 bit texture
+uniform float ocean_seaLevel;                 // sea level offset
+uniform sampler2D ocean_surface_tex;          // surface texture
+uniform bool ocean_has_surface_tex;           // whether there's a surface texture
+
+// outputs to fragment stage
+out vec4 ocean_surface_tex_coord;  
+out float ocean_v_msl;                      // elevation (MSL) of camera
+out float ocean_v_range;                    // distance from camera to current vertex
+out float ocean_v_enorm;                    // normalized terrain height at vertex [0..1]
+
+// stage global
+vec3 vp_Normal;
+
+
+#ifdef USE_OCEAN_MASK
+out vec4 ocean_mask_tex_coord;
+
+// Ocean mask version:
+void oe_ocean_vertex(inout vec4 VertexMODEL)  
+{  
+    // adjust our vert for the sea level - extrude along the normal vector 
+    // (this must be done in modelview space to preserve precision)
+    vec4 mvVertex = VertexMODEL;  
+    vec3 mvNormal = gl_NormalMatrix * gl_Normal;  
+    vec4 mvVertex2 = vec4(mvVertex.xyz + (mvNormal * ocean_seaLevel), mvVertex.w );  
+
+    VertexMODEL = mvVertex2;  
+
+    // ocean mask texture coordinate:
+    ocean_mask_tex_coord = gl_MultiTexCoord0;  
+
+    // send interpolated params to the fs:
+    vec4 eye = osg_ViewMatrixInverse * vec4(0,0,0,1);  
+
+    // height of camera above sea level:
+    ocean_v_msl = length(eye.xyz/eye.w) - 6378137.0 + ocean_seaLevel;  
+
+    // disatnce to camera:
+    ocean_v_range = ocean_v_msl;  
+
+    // scale the texture mapping to something reasonable:
+    vec4 worldVertex = osg_ViewMatrixInverse * mvVertex;  
+    vec2 lonlat = ocean_xyz_to_spherical( worldVertex.xyz/worldVertex.w );  
+    ocean_surface_tex_coord.xy = lonlat/0.0005;
+    ocean_surface_tex_coord.zw = ocean_surface_tex_coord.xy;  
+    ocean_surface_tex_coord.w -= mod(0.1*osg_FrameTime,25.0)/25.0; 
+}
+
+#else
+
+// Proxy layer version:
+void oe_ocean_vertex(inout vec4 VertexVIEW)  
+{  
+    // adjust our vert for the sea level - extrude along the normal vector 
+    // (this must be done in view space to preserve precision)
+    vec4 mvVertex = VertexVIEW;  
+    vec3 mvNormal = vp_Normal;  
+    vec4 mvVertex2 = vec4(mvVertex.xyz + (mvNormal * ocean_seaLevel), mvVertex.w );  
+
+    VertexVIEW = mvVertex2;  
+
+    // read normalized [0..1] elevation data from the height texture:
+    ocean_v_enorm = texture2D( ocean_data, gl_MultiTexCoord0.st ).r;  
+
+    // send interpolated params to the fs:
+    vec4 eye = osg_ViewMatrixInverse * vec4(0,0,0,1);  
+
+    // height of camera above sea level:
+    ocean_v_msl = length(eye.xyz/eye.w) - 6378137.0 + ocean_seaLevel;  
+
+    // disatnce to camera:
+    ocean_v_range = ocean_v_msl;  
+
+    // scale the texture mapping to something reasonable:
+    vec4 worldVertex = osg_ViewMatrixInverse * mvVertex;  
+    vec2 lonlat = ocean_xyz_to_spherical( worldVertex.xyz/worldVertex.w );  
+    ocean_surface_tex_coord.xy = lonlat/0.0005;
+    ocean_surface_tex_coord.zw = ocean_surface_tex_coord.xy;  
+    ocean_surface_tex_coord.w -= mod(0.1*osg_FrameTime,25.0)/25.0; 
+ }
+
+#endif
diff --git a/src/osgEarthDrivers/ocean_simple/SimpleOceanDriver.cpp b/src/osgEarthDrivers/ocean_simple/SimpleOceanDriver.cpp
index 2364300..ee1a9e4 100644
--- a/src/osgEarthDrivers/ocean_simple/SimpleOceanDriver.cpp
+++ b/src/osgEarthDrivers/ocean_simple/SimpleOceanDriver.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -22,46 +22,146 @@
 #include <osgDB/FileUtils>
 
 #include "SimpleOceanNode"
+#include "SimpleOceanOptions"
+#include <osgEarthUtil/Controls>
 
 #undef  LC
-#define LC "[SimpleOceanDriver] "
+#define LC "[SimpleOceanExtension] "
 
 using namespace osgEarth;
 using namespace osgEarth::Util;
+namespace ui = osgEarth::Util::Controls;
 
-namespace osgEarth { namespace Drivers { namespace SimpleOcean
+namespace osgEarth { namespace SimpleOcean
 {
-    struct SimpleOceanDriver : public OceanDriver
+    /**
+     * Extension that lets you load a SimpleOcean from an earth file.
+     */
+    class SimpleOceanExtension : public Extension,
+                                 public ExtensionInterface<MapNode>,
+                                 public ExtensionInterface<ui::Control>,
+                                 public SimpleOceanOptions,
+                                 public OceanNodeFactory
     {
-        SimpleOceanDriver()
+    public:
+        META_Object(osgearth_ocean_simple, SimpleOceanExtension);
+
+        SimpleOceanExtension() { }
+
+        SimpleOceanExtension(const ConfigOptions& options) :
+            SimpleOceanOptions(options) { }
+
+    public: // ExtensionInterface<MapNode>
+
+        bool connect(MapNode* mapNode)
         {
-            supportsExtension( "osgearth_ocean_simple", "Simple Ocean" );
+            _oceanNode = createOceanNode(mapNode);
+            mapNode->addChild(_oceanNode.get());
+            return true;
         }
 
-        ReadResult readObject(const std::string& url, const Options* options) const
+        bool disconnect(MapNode* mapNode)
         {
-            return readNode( url, options );
+            if (mapNode && _oceanNode.valid())
+                mapNode->removeChild(_oceanNode.get());
+            return true;
         }
 
-        ReadResult readNode(const std::string& url, const Options* options) const
-        {
-            std::string ext = osgDB::getLowerCaseFileExtension(url);
-            if ( !acceptsExtension(ext) )
-                return ReadResult::FILE_NOT_HANDLED;
+    public: // ExtensionInterface<Control>
 
-            MapNode*           mapNode( getMapNode(options) );
-            SimpleOceanOptions oceanOptions( getOceanOptions(options) );
+        bool connect(ui::Control* control);
 
-            if ( !mapNode )
-            {
-                OE_WARN << LC << "Internal error - no MapNode marshalled" << std::endl;
-                return ReadResult::ERROR_IN_READING_FILE;
-            }
+        bool disconnect(ui::Control* control) {
+            return true;
+        }
+
+    public: // OCeanNodeFactory
 
-            return new SimpleOceanNode( oceanOptions, mapNode );
+        OceanNode* createOceanNode(MapNode* mapNode) {
+            return new SimpleOceanNode(*this, mapNode);
         }
+
+    protected:
+        SimpleOceanExtension(const SimpleOceanExtension& rhs, const osg::CopyOp& op) { }
+
+        virtual ~SimpleOceanExtension() { }
+
+        osg::ref_ptr<OceanNode> _oceanNode;
     };
 
-    REGISTER_OSGPLUGIN( osgearth_ocean_simple, SimpleOceanDriver )
+    REGISTER_OSGEARTH_EXTENSION(osgearth_ocean_simple, SimpleOceanExtension);
+
+} } // namespace osgEarth::Drivers::SimpleOcean
+
+
+
+
+
+using namespace osgEarth::SimpleOcean;
+
+namespace
+{
+    struct ChangeSeaLevel : public ui::ControlEventHandler
+    {
+        ChangeSeaLevel( OceanNode* ocean ) : _ocean(ocean) { }
+        OceanNode* _ocean;
+        virtual void onValueChanged( ui::Control* control, float value )
+        {
+            _ocean->setSeaLevel( value );
+        }
+    };
+
+    struct ChangeSeaAlpha : public ui::ControlEventHandler
+    {
+        ChangeSeaAlpha( OceanNode* ocean ) : _ocean(ocean) { }
+        OceanNode* _ocean;
+        virtual void onValueChanged( ui::Control* control, float value )
+        {
+            _ocean->setAlpha( value );
+        }
+    };
+}
+
+bool
+SimpleOceanExtension::connect(ui::Control* control)
+{
+    ui::Container* container = dynamic_cast<ui::Container*>(control);
+    if (container && _oceanNode.valid())
+    {
+        ui::VBox* main = new ui::VBox();
+
+        ui::HBox* sealLevelBox = main->addControl(new ui::HBox());
+        sealLevelBox->setChildVertAlign( ui::Control::ALIGN_CENTER );
+        sealLevelBox->setChildSpacing( 10 );
+        sealLevelBox->setHorizFill( true );
+
+        sealLevelBox->addControl( new ui::LabelControl("Sea Level: ", 16) );
+
+        ui::HSliderControl* mslSlider = sealLevelBox->addControl(new ui::HSliderControl( -250.0f, 250.0f, 0.0f ));
+        mslSlider->setBackColor( Color::Gray );
+        mslSlider->setHeight( 12 );
+        mslSlider->setHorizFill( true, 200 );
+        mslSlider->addEventHandler( new ChangeSeaLevel(_oceanNode.get()) );
+
+        ui::HBox* alphaBox = main->addControl(new ui::HBox());
+        alphaBox->setChildVertAlign( ui::Control::ALIGN_CENTER );
+        alphaBox->setChildSpacing( 10 );
+        alphaBox->setHorizFill( true );
+    
+        alphaBox->addControl( new ui::LabelControl("Sea Alpha: ", 16) );
+
+        ui::HSliderControl* alphaSlider = alphaBox->addControl(new ui::HSliderControl( 0.0, 1.0, 1.0));
+        alphaSlider->setBackColor( Color::Gray );
+        alphaSlider->setHeight( 12 );
+        alphaSlider->setHorizFill( true, 200 );
+        alphaSlider->addEventHandler( new ChangeSeaAlpha(_oceanNode.get()) );
+
+        container->addControl(main);
+    }
+    else
+    {
+        OE_WARN << LC << "Ocean node is unavailable; cannot create the UI.\n";
+    }
 
-} } } // namespace osgEarth::Drivers::SimpleOcean
+    return true;
+}
\ No newline at end of file
diff --git a/src/osgEarthDrivers/ocean_simple/SimpleOceanNode b/src/osgEarthDrivers/ocean_simple/SimpleOceanNode
index d37497f..22e861c 100644
--- a/src/osgEarthDrivers/ocean_simple/SimpleOceanNode
+++ b/src/osgEarthDrivers/ocean_simple/SimpleOceanNode
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -29,7 +29,7 @@ namespace osg {
     class Uniform;
 }
 
-namespace osgEarth { namespace Drivers { namespace SimpleOcean
+namespace osgEarth { namespace SimpleOcean
 {
     using namespace osgEarth;
     using namespace osgEarth::Util;
@@ -37,7 +37,8 @@ namespace osgEarth { namespace Drivers { namespace SimpleOcean
     /**
      * Node tha renders an ocean surface over a MapNode.
      */
-    class SimpleOceanNode : public OceanNode
+    class SimpleOceanNode : public OceanNode,
+                            public SimpleOceanOptions
     {
     public:
         /**
@@ -48,25 +49,30 @@ namespace osgEarth { namespace Drivers { namespace SimpleOcean
             const SimpleOceanOptions& options,
             MapNode*                  mapNode);
 
+        // if you change any of the SimpleOceanOptions, call this to apply them.
+        void dirty() { applyOptions();  }
+
     protected: // OceanNode
 
         void onSetSeaLevel();
 
+        void onSetAlpha();
+
         virtual ~SimpleOceanNode() { }
 
     private:
 
         osg::observer_ptr<MapNode> _parentMapNode;
-        SimpleOceanOptions         _options;
         osg::ref_ptr<osg::Uniform> _seaLevel, _lowFeather, _highFeather;
         osg::ref_ptr<osg::Uniform> _maxRange, _fadeRange;
         osg::ref_ptr<osg::Uniform> _baseColor;
+        osg::ref_ptr<osg::Uniform> _alphaUniform;
 
         void rebuild();
 
         void applyOptions();
     };
 
-} } } // namespace osgEarth::Drivers::SimpleOcean
+} } // namespace osgEarth::Drivers::SimpleOcean
 
 #endif // OSGEARTH_DRIVER_SIMPLE_OCEAN_NODE
diff --git a/src/osgEarthDrivers/ocean_simple/SimpleOceanNode.cpp b/src/osgEarthDrivers/ocean_simple/SimpleOceanNode.cpp
index c1ab3de..7e4c81c 100644
--- a/src/osgEarthDrivers/ocean_simple/SimpleOceanNode.cpp
+++ b/src/osgEarthDrivers/ocean_simple/SimpleOceanNode.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -35,7 +35,7 @@
 
 using namespace osgEarth;
 using namespace osgEarth::Util;
-using namespace osgEarth::Drivers::SimpleOcean;
+using namespace osgEarth::SimpleOcean;
 using namespace osgEarth::Drivers::MPTerrainEngine;
 
 namespace
@@ -47,14 +47,17 @@ namespace
         static const double twoPI = 2.0*osg::PI;
 
         osg::Image* image = new osg::Image();
-        image->allocateImage(SIR, SIR, 1, GL_RGBA, GL_UNSIGNED_BYTE);
+        image->allocateImage(SIR, SIR, 1, GL_LUMINANCE, GL_UNSIGNED_BYTE);
 
         SimplexNoise noise;
         noise.setFrequency(SIR*512.0);
         noise.setOctaves(16);
-        noise.setRange(1.0, 2.6);
+        noise.setRange(0.0, 1.0);
+
+        double n0=DBL_MAX, n1=-DBL_MAX;
 
         ImageUtils::PixelWriter write(image);
+
         for(int s=0; s<image->s(); ++s)
         {
             for(int t=0; t<image->t(); ++t)
@@ -62,20 +65,19 @@ namespace
                 double a = (double)s / (double)image->s();
                 double b = (double)t / (double)image->t();
 
-                // trick to create tiled noise (2 ortho circles)
-                // http://www.gamedev.net/blog/33/entry-2138456-seamless-noise/
+                double n = noise.getTiledValue(a, b);
 
-                double x = cos(a*twoPI)/twoPI;
-                double y = cos(b*twoPI)/twoPI;
-                double z = sin(a*twoPI)/twoPI;
-                double w = sin(b*twoPI)/twoPI;
+                //write( osg::Vec4(0.25*n, 0.3*n, 0.35*n, 0.5), s, t );
 
-                double n = noise.getValue(x, y, z, w);
+                write( osg::Vec4(n,n,n,n), s, t );
 
-                write( osg::Vec4(0.25*n, 0.3*n, 0.35*n, 1.0), s, t );
+                if (n<n0) n0=n;
+                if (n>n1) n1=n;
             }
         }
 
+        OE_DEBUG << "Min = " << n0 << ", Max = " << n1 << "\n";
+
         return image;
     }
 }
@@ -85,9 +87,9 @@ namespace
 
 SimpleOceanNode::SimpleOceanNode(const SimpleOceanOptions& options,
                                  MapNode*                  mapNode) :
-OceanNode     ( options ),
-_parentMapNode( mapNode ),
-_options      ( options )
+OceanNode(options),
+SimpleOceanOptions(options),
+_parentMapNode(mapNode)
 {
     // set the node mask so that our custom EarthManipulator will NOT find this node.
     setNodeMask( 0xFFFFFFFE );
@@ -101,15 +103,16 @@ SimpleOceanNode::rebuild()
 {
     this->removeChildren( 0, this->getNumChildren() );
 
-    if ( _parentMapNode.valid() )
+    osg::ref_ptr<MapNode> mapNode;
+    if (_parentMapNode.lock(mapNode))
     {
-        const MapOptions&     parentMapOptions     = _parentMapNode->getMap()->getMapOptions();
-        const MapNodeOptions& parentMapNodeOptions = _parentMapNode->getMapNodeOptions();
+        const MapOptions&     parentMapOptions     = mapNode->getMap()->getMapOptions();
+        const MapNodeOptions& parentMapNodeOptions = mapNode->getMapNodeOptions();
 
         // set up the map to "match" the parent map:
         MapOptions mo;
         mo.coordSysType() = parentMapOptions.coordSysType();
-        mo.profile()      = _parentMapNode->getMap()->getProfile()->toProfileOptions();
+        mo.profile()      = mapNode->getMap()->getProfile()->toProfileOptions();
 
         // new data model for the ocean:
         Map* oceanMap = new Map( mo );
@@ -121,14 +124,14 @@ SimpleOceanNode::rebuild()
 
         MPTerrainEngineOptions mpoptions;
         mpoptions.heightFieldSkirtRatio() = 0.0;      // don't want to see skirts
-        mpoptions.minLOD() = _options.maxLOD().get(); // weird, I know
+        mpoptions.minLOD() = maxLOD().get(); // weird, I know
 
         // so we can the surface from underwater:
         mpoptions.clusterCulling() = false;       // want to see underwater
 
         mpoptions.enableBlending() = true;        // gotsta blend with the main node
 
-        mpoptions.color() = _options.baseColor().get();
+        mpoptions.color() = baseColor().get();
 
         mno.setTerrainOptions( mpoptions );
 
@@ -136,22 +139,22 @@ SimpleOceanNode::rebuild()
         MapNode* oceanMapNode = new MapNode( oceanMap, mno );
 
         // if the caller requested a mask layer, install that now.
-        if ( _options.maskLayer().isSet() )
+        if ( maskLayer().isSet() )
         {
-            if ( !_options.maskLayer()->maxLevel().isSet() )
+            if ( !maskLayer()->maxLevel().isSet() )
             {
                 // set the max subdivision level if it's not already specified in the 
                 // mask layer options:
-                _options.maskLayer()->maxLevel() = *_options.maxLOD();
+                maskLayer()->maxLevel() = maxLOD().get();
             }
 
             // make sure the mask is shared (so we can access it from our shader)
             // and invisible (so we can't see it)
-            _options.maskLayer()->shared() = true;
-            _options.maskLayer()->visible() = false;
+            maskLayer()->shared() = true;
+            maskLayer()->visible() = false;
 
-            ImageLayer* maskLayer = new ImageLayer( "ocean-mask", *_options.maskLayer() );
-            oceanMap->addImageLayer( maskLayer );
+            ImageLayer* layer = new ImageLayer("ocean-mask", maskLayer().get());
+            oceanMap->addImageLayer( layer );
         }
 
         // otherwise, install a "proxy layer" that will use the elevation data in the map
@@ -163,8 +166,7 @@ SimpleOceanNode::rebuild()
             // parent map and turns them into encoded images for our shader to use.
             ImageLayerOptions epo( "ocean-proxy" );
             epo.cachePolicy() = CachePolicy::NO_CACHE;
-            //epo.maxLevel() = *_options.maxLOD();
-            oceanMap->addImageLayer( new ElevationProxyImageLayer(_parentMapNode->getMap(), epo) );
+            oceanMap->addImageLayer( new ElevationProxyImageLayer(mapNode->getMap(), epo) );
         }
 
         this->addChild( oceanMapNode );
@@ -175,13 +177,17 @@ SimpleOceanNode::rebuild()
         // install the shaders on the ocean map node.
         VirtualProgram* vp = VirtualProgram::getOrCreate( ss );
         vp->setName( "osgEarth SimpleOcean" );
+        
+        Shaders shaders;
+        shaders.define("USE_OCEAN_MASK", maskLayer().isSet());
+        shaders.loadAll(vp, 0L);
 
-        // use the appropriate shader for the active technique:
-        std::string vertSource = _options.maskLayer().isSet() ? source_vertMask : source_vertProxy;
-        std::string fragSource = _options.maskLayer().isSet() ? source_fragMask : source_fragProxy;
+        //// use the appropriate shader for the active technique:
+        //std::string vertSource = maskLayer().isSet() ? source_vertMask : source_vertProxy;
+        //std::string fragSource = maskLayer().isSet() ? source_fragMask : source_fragProxy;
 
-        vp->setFunction( "oe_ocean_vertex",   vertSource, ShaderComp::LOCATION_VERTEX_VIEW );
-        vp->setFunction( "oe_ocean_fragment", fragSource, ShaderComp::LOCATION_FRAGMENT_COLORING, 0.6f );
+        //vp->setFunction( "oe_ocean_vertex",   vertSource, ShaderComp::LOCATION_VERTEX_VIEW );
+        //vp->setFunction( "oe_ocean_fragment", fragSource, ShaderComp::LOCATION_FRAGMENT_COLORING, 0.6f );
 
         // install the slot attribute(s)
         ss->getOrCreateUniform( "ocean_data", osg::Uniform::SAMPLER_2D )->set( 0 );
@@ -206,17 +212,19 @@ SimpleOceanNode::rebuild()
         _fadeRange = new osg::Uniform(osg::Uniform::FLOAT, "ocean_fade_range");
         ss->addUniform( _fadeRange.get() );
 
-        // trick to mitigate z-fighting..
+        _alphaUniform = new osg::Uniform(osg::Uniform::FLOAT, "oe_ocean_alpha");
+        ss->addUniform( _alphaUniform.get() );
+
+        // disable depth writes.
         ss->setAttributeAndModes( new osg::Depth(osg::Depth::LEQUAL, 0.0, 1.0, false) );
-        ss->setRenderBinDetails( 15, "RenderBin" );
 
         // load up a surface texture
         osg::ref_ptr<osg::Image> surfaceImage;
         ss->getOrCreateUniform( "ocean_has_surface_tex", osg::Uniform::BOOL )->set( false );
-        if ( _options.textureURI().isSet() )
+        if ( textureURI().isSet() )
         {
             //TODO: enable cache support here?
-            surfaceImage = _options.textureURI()->getImage();
+            surfaceImage = textureURI()->getImage();
         }
 
         if ( !surfaceImage.valid() )
@@ -245,11 +253,11 @@ SimpleOceanNode::rebuild()
 
         // Material.
         osg::Material* m = new osg::Material();
-        m->setAmbient(m->FRONT_AND_BACK, osg::Vec4(0,0,0,1));
+        m->setAmbient(m->FRONT_AND_BACK, osg::Vec4(.5,.5,.5,1));
         m->setDiffuse(m->FRONT_AND_BACK, osg::Vec4(1,1,1,1));
-        m->setSpecular(m->FRONT_AND_BACK, osg::Vec4(0.1,0.1,0.1,1));
+        m->setSpecular(m->FRONT_AND_BACK, osg::Vec4(0.2,0.2,0.2,1));
         m->setEmission(m->FRONT_AND_BACK, osg::Vec4(0,0,0,1));
-        m->setShininess(m->FRONT_AND_BACK, 32.0);
+        m->setShininess(m->FRONT_AND_BACK, 40.0);
         ss->setAttributeAndModes(m, osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE );
 
         // force apply options:
@@ -260,14 +268,17 @@ SimpleOceanNode::rebuild()
 void
 SimpleOceanNode::applyOptions()
 {
-    setSeaLevel( *_options.seaLevel() );
-
-    _lowFeather->set( *_options.lowFeatherOffset() );
-    _highFeather->set( *_options.highFeatherOffset() );
-    _baseColor->set( *_options.baseColor() );
-    _maxRange->set( *_options.maxRange() );
-    _fadeRange->set( *_options.fadeRange() );
-
+    if (_seaLevel.valid())
+    {
+        setSeaLevel(seaLevel().get());
+        _lowFeather->set(lowFeatherOffset().get());
+        _highFeather->set(highFeatherOffset().get());
+        _baseColor->set(baseColor().get());
+        _maxRange->set(maxRange().get());
+        _fadeRange->set(fadeRange().get());
+        _alphaUniform->set(getAlpha());
+        this->getOrCreateStateSet()->setRenderBinDetails(renderBinNumber().get(), "DepthSortedBin");
+    }
 }
 
 void
@@ -275,3 +286,9 @@ SimpleOceanNode::onSetSeaLevel()
 {
     _seaLevel->set( getSeaLevel() );
 }
+
+void
+SimpleOceanNode::onSetAlpha()
+{
+    _alphaUniform->set(getAlpha());
+}
diff --git a/src/osgEarthDrivers/ocean_simple/SimpleOceanOptions b/src/osgEarthDrivers/ocean_simple/SimpleOceanOptions
index 2822b0e..54aa90c 100644
--- a/src/osgEarthDrivers/ocean_simple/SimpleOceanOptions
+++ b/src/osgEarthDrivers/ocean_simple/SimpleOceanOptions
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -26,7 +26,7 @@
 #include <osgEarth/Registry>
 #include <osgEarthSymbology/Color>
 
-namespace osgEarth { namespace Drivers { namespace SimpleOcean
+namespace osgEarth { namespace SimpleOcean
 {
     using namespace osgEarth;
     using namespace osgEarth::Util;
@@ -72,6 +72,11 @@ namespace osgEarth { namespace Drivers { namespace SimpleOcean
         optional<URI>& textureURI() { return _textureURI; }
         const optional<URI>& textureURI() const { return _textureURI; }
 
+        /** Render bin number to assign to the ocean (in DepthSortedBin) */
+        optional<int>& renderBinNumber() { return _renderBinNumber; }
+        const optional<int>& renderBinNumber() const { return _renderBinNumber; }
+
+
         /** Image layer configuration for an optional "ocean mask" layer.
          *  This is an image layer that encodes areas of land versus ocean in the
          *  alpha channel of the image. The mapping is: [0...1] => [land...ocean] */
@@ -87,7 +92,8 @@ namespace osgEarth { namespace Drivers { namespace SimpleOcean
               _maxRange         ( 1000000.0f ),
               _fadeRange        ( 125000.0f ),
               _maxLOD           ( 20 ),
-              _baseColor        ( osg::Vec4(0.2, 0.3, 0.5, 0.8) )
+              _baseColor        ( Color("#1c6ba0ef") ),
+              _renderBinNumber  ( 12 )
         {
             mergeConfig( _conf );
         }
@@ -107,6 +113,7 @@ namespace osgEarth { namespace Drivers { namespace SimpleOcean
             conf.updateIfSet("base_color",          _baseColor );
             conf.updateIfSet("texture_url",         _textureURI );
             conf.updateObjIfSet("mask_layer",       _maskLayerOptions );
+            conf.updateIfSet("render_bin_number",   _renderBinNumber);
             return conf;
         }
 
@@ -127,6 +134,7 @@ namespace osgEarth { namespace Drivers { namespace SimpleOcean
             conf.getIfSet("base_color",          _baseColor );
             conf.getIfSet("texture_url",         _textureURI );
             conf.getObjIfSet("mask_layer",       _maskLayerOptions );
+            conf.getIfSet("render_bin_number",   _renderBinNumber);
         }
 
     private:
@@ -139,8 +147,9 @@ namespace osgEarth { namespace Drivers { namespace SimpleOcean
         optional<Color>             _baseColor;
         optional<URI>               _textureURI;
         optional<ImageLayerOptions> _maskLayerOptions;
+        optional<int>               _renderBinNumber;
     };
 
-} } } // namespace osgEarth::Drivers::SimpleOcean
+} } // namespace osgEarth::SimpleOcean
 
 #endif // OSGEARTH_DRIVER_SIMPLE_OCEAN
diff --git a/src/osgEarthDrivers/ocean_simple/SimpleOceanShaders b/src/osgEarthDrivers/ocean_simple/SimpleOceanShaders
index f00fc62..e1d21d8 100644
--- a/src/osgEarthDrivers/ocean_simple/SimpleOceanShaders
+++ b/src/osgEarthDrivers/ocean_simple/SimpleOceanShaders
@@ -1,273 +1,30 @@
+// ***DO NOT EDIT THIS FILE - IT IS AUTOMATICALLY GENERATED BY CMAKE***
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
- * http://osgearth.org
- *
- * osgEarth is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>
- */
-#ifndef OSGEARTH_DRIVER_SIMPLE_OCEAN_SHADERS
-#define OSGEARTH_DRIVER_SIMPLE_OCEAN_SHADERS 1
-
-#include <osgEarth/VirtualProgram>
-
-namespace
+* Copyright 2008-2012 Pelican Mapping
+* http://osgearth.org
+*
+* osgEarth is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public License
+* along with this program.  If not, see <http://www.gnu.org/licenses/>
+*/
+#include <osgEarth/ShaderLoader>
+
+namespace osgEarth { namespace SimpleOcean
 {
-    static char source_vertProxy[] =
-        "#version " GLSL_VERSION_STR "\n"
-        GLSL_DEFAULT_PRECISION_FLOAT "\n"
-
-        "vec2 ocean_xyz_to_spherical(in vec3 xyz) \n"
-        "{ \n"
-        "    float r = length(xyz); \n"
-        "    float lat = acos(xyz.z/r); \n"
-        "    float lon = atan(xyz.y, xyz.x); \n"
-        "    return vec2(lon,lat); \n"
-        "} \n"
-
-        "uniform mat4 osg_ViewMatrixInverse; \n"
-        "uniform mat4 osg_ViewMatrix; \n"
-        "uniform float osg_FrameTime; \n"
-        "uniform sampler2D ocean_data; \n"                 // heightfield encoded into 16 bit texture
-        "uniform float ocean_seaLevel; \n"                 // sea level offset
-
-        "varying vec4 osg_FrontColor; \n"
-        "varying vec4 ocean_surface_tex_coord; \n"
-        "varying float ocean_v_msl; \n"                    // elevation (MSL) of camera
-        "varying float ocean_v_range; \n"                  // distance from camera to current vertex
-        "varying float ocean_v_enorm; \n"                  // normalized terrain height at vertex [0..1]
-
-        "varying vec3 oe_Normal; \n" 
-        "uniform sampler2D ocean_surface_tex; \n"        // surface texture
-        "uniform bool ocean_has_surface_tex; \n"         // whether there's a surface texture
-
-        "void oe_ocean_vertex(inout vec4 VertexVIEW) \n"
-        "{ \n"
-        "   osg_FrontColor = gl_Color; \n"
-
-        // adjust our vert for the sea level - extrude along the normal vector 
-        // (this must be done in view space to preserve precision)
-        "   vec4 mvVertex = VertexVIEW; \n"
-        "   vec3 mvNormal = oe_Normal; \n"
-        "   vec4 mvVertex2 = vec4(mvVertex.xyz + (mvNormal * ocean_seaLevel), mvVertex.w ); \n"
-
-        "   VertexVIEW = mvVertex2; \n"
-
-        // read normalized [0..1] elevation data from the height texture:
-        "   ocean_v_enorm = texture2D( ocean_data, gl_MultiTexCoord0.st ).r; \n"
-
-        // send interpolated params to the fs:
-        "   vec4 eye = osg_ViewMatrixInverse * vec4(0,0,0,1); \n"
-
-        // height of camera above sea level:
-        "   ocean_v_msl = length(eye.xyz/eye.w) - 6378137.0 + ocean_seaLevel; \n"
-
-        // disatnce to camera:
-        "   ocean_v_range = ocean_v_msl; \n"
-
-        // scale the texture mapping to something reasonable:
-        "   vec4 worldVertex = osg_ViewMatrixInverse * mvVertex; \n"
-        "   vec2 lonlat = ocean_xyz_to_spherical( worldVertex.xyz/worldVertex.w ); \n"
-        "   ocean_surface_tex_coord.xy = lonlat / 0.0005; \n"
-        "   ocean_surface_tex_coord.zw = ocean_surface_tex_coord.xy; \n"
-        "   ocean_surface_tex_coord.w -= mod(0.1*osg_FrameTime,25.0)/25.0;\n"
-
-        // fake waves:
-        "   if (ocean_has_surface_tex) { \n"
-        "       vec4 t0 = texture2D(ocean_surface_tex, ocean_surface_tex_coord.xy); \n"
-        "       vec4 t1 = texture2D(ocean_surface_tex, ocean_surface_tex_coord.zw); \n"
-        "       oe_Normal = normalize((3.0*t0.rgb*t1.rgb)*2.0-1.0); \n"
-        "   } \n"
-        "} \n";
-
-
-    char source_fragProxy[] = 
-        "#version " GLSL_VERSION_STR "\n"
-        GLSL_DEFAULT_PRECISION_FLOAT "\n"
-
-        // clamps a value to the vmin/vmax range, then re-maps it to the r0/r1 range:
-        "float ocean_remap( float val, float vmin, float vmax, float r0, float r1 ) \n"
-        "{ \n"
-        "    float vr = (clamp(val, vmin, vmax)-vmin)/(vmax-vmin); \n"
-        "    return r0 + vr * (r1-r0); \n"
-        "} \n"
-
-        "varying float ocean_v_msl; \n"                  // elevation (MSL) of camera
-        "varying float ocean_v_range; \n"                // distance from camera to current vertex
-        "varying float ocean_v_enorm; \n"                // normalized terrain height at vertex [0..1]
-        "varying vec4 ocean_surface_tex_coord; \n"       // surface texture coords
-
-        "uniform bool ocean_has_surface_tex; \n"         // whether there's a surface texture
-        "uniform sampler2D ocean_surface_tex; \n"        // surface texture
-        "uniform float ocean_seaLevel; \n"               // sea level offset
-        "uniform float ocean_lowFeather; \n"             // offset from sea level at which to start feathering out
-        "uniform float ocean_highFeather; \n"            // offset from sea level at which to stop feathering out
-        "uniform vec4  ocean_baseColor; \n"              // base ocean color before processing
-
-        "uniform float ocean_max_range; \n"              // maximum visible distance of the ocean
-        "uniform float ocean_fade_range; \n"             // distance over which to fade in the ocean
-
-        "void oe_ocean_fragment(inout vec4 color) \n"
-        "{ \n"
-        "    color = ocean_baseColor; \n"
-
-        // amplify the range's effect on alpha when the camera elevation gets low
-        "    float rangeFactor = ocean_remap( ocean_v_msl, -10000.0, 10000.0, 10.0, 1.0 ); \n"
-
-        // affect alpha based on the distance from the camera
-        "    float rangeEffect = ocean_remap(\n"
-        "       ocean_v_range,\n"
-        "       ocean_max_range - ocean_fade_range, ocean_max_range * rangeFactor,\n"
-        "       1.0, 0.0); \n"
-
-        // start with the surface texture.
-        "    if (ocean_has_surface_tex) \n"
-        "    { \n"
-        "        vec4 texel1 = texture2D(ocean_surface_tex, ocean_surface_tex_coord.xy); \n"
-        "        vec4 texel2 = texture2D(ocean_surface_tex, ocean_surface_tex_coord.zw); \n"
-        "        vec4 texel  = vec4(texel1.rgb*texel2.rgb, texel2.a); \n"
-        "        vec4 nearColor = vec4(mix(color.rgb, texel.rgb, texel.a), color.a); \n"
-        "        color = mix(color, nearColor, rangeEffect); \n"
-        "    } \n"
-
-        // un-normalize the heightfield data
-        "    float terrainHeight = (ocean_v_enorm * 65535.0) - 32768.0; \n"
-
-        // heightfield's effect on alpha [0..1]
-        "    float terrainEffect = ocean_remap( terrainHeight, ocean_seaLevel+ocean_lowFeather, ocean_seaLevel+ocean_highFeather, 1.0, 0.0 ); \n" 
-
-        // color it
-        "    color = vec4( color.rgb, terrainEffect * rangeEffect ); \n" //* color.a ); \n"
-
-        //"    color = vec4( 1, 0, 0, 1 ); \n" // debugging
-        "} \n";
-
-
-
-    char source_vertMask[] =
-        "#version " GLSL_VERSION_STR "\n"
-        GLSL_DEFAULT_PRECISION_FLOAT "\n"
-
-        "vec2 ocean_xyz_to_spherical(in vec3 xyz) \n"
-        "{ \n"
-        "    float r = length(xyz); \n"
-        "    float lat = acos(xyz.z/r); \n"
-        "    float lon = atan(xyz.y, xyz.x); \n"
-        "    return vec2(lon,lat); \n"
-        "} \n"
-
-        "uniform mat4 osg_ViewMatrixInverse; \n"
-        "uniform float osg_FrameTime; \n"
-        "uniform float ocean_seaLevel; \n"
-        "varying vec4 osg_FrontColor; \n"
-        "varying vec4 ocean_mask_tex_coord; \n"
-        "varying vec4 ocean_surface_tex_coord; \n"
-        "varying float ocean_v_msl; \n"
-        "varying float ocean_v_range; \n"
-
-        "void oe_ocean_vertex(inout vec4 VertexMODEL) \n"
-        "{ \n"
-        "   osg_FrontColor = gl_Color; \n"
-
-        // adjust our vert for the sea level - extrude along the normal vector 
-        // (this must be done in modelview space to preserve precision)
-        "   vec4 mvVertex = VertexMODEL; \n"
-        "   vec3 mvNormal = gl_NormalMatrix * gl_Normal; \n"
-        "   vec4 mvVertex2 = vec4(mvVertex.xyz + (mvNormal * ocean_seaLevel), mvVertex.w ); \n"
-
-        "   VertexMODEL = mvVertex2; \n"
-        //"   gl_Position = gl_ProjectionMatrix * mvVertex2; \n"
-
-        // ocean mask texture coordinate:
-        "   ocean_mask_tex_coord = gl_MultiTexCoord0; \n"
-
-        // send interpolated params to the fs:
-        "   vec4 eye = osg_ViewMatrixInverse * vec4(0,0,0,1); \n"
-
-        // height of camera above sea level:
-        "   ocean_v_msl = length(eye.xyz/eye.w) - 6378137.0 + ocean_seaLevel; \n"
-
-        // disatnce to camera:
-        "   ocean_v_range = ocean_v_msl; \n"
-
-        // scale the texture mapping to something reasonable:
-        "   vec4 worldVertex = osg_ViewMatrixInverse * mvVertex; \n"
-        "   vec2 lonlat = ocean_xyz_to_spherical( worldVertex.xyz/worldVertex.w ); \n"
-        "   ocean_surface_tex_coord.xy = lonlat / 0.0005; \n"
-        "   ocean_surface_tex_coord.zw = ocean_surface_tex_coord.xy; \n"
-        "   ocean_surface_tex_coord.x += mod(osg_FrameTime,100.0)/100.0;\n"
-        //"   ocean_surface_tex_coord.w -= mod(osg_FrameTime,50.0)/50.0;\n"
-        "} \n";
-
-
-    char source_fragMask[] = 
-
-        "#version " GLSL_VERSION_STR "\n"
-        GLSL_DEFAULT_PRECISION_FLOAT "\n"
-
-        // clamps a value to the vmin/vmax range, then re-maps it to the r0/r1 range:
-        "float ocean_remap( float val, float vmin, float vmax, float r0, float r1 ) \n"
-        "{ \n"
-        "    float vr = (clamp(val, vmin, vmax)-vmin)/(vmax-vmin); \n"
-        "    return r0 + vr * (r1-r0); \n"
-        "} \n"
-
-        "varying float ocean_v_msl; \n"                  // elevation (MSL) of camera
-        "varying float ocean_v_range; \n"                // distance from camera to current vertex
-        "varying vec4 ocean_mask_tex_coord; \n"          // tex coord for the mask texture
-        "varying vec4 ocean_surface_tex_coord; \n"       // surface texture coords
-
-        "uniform sampler2D ocean_data; \n"               // ocean mask texture
-        "uniform bool ocean_has_surface_tex; \n"         // whether there's a surface texture
-        "uniform sampler2D ocean_surface_tex; \n"        // surface texture
-
-        "uniform float ocean_seaLevel; \n"               // sea level offset
-        "uniform vec4 ocean_baseColor; \n"               // base ocean color before processing
-
-        "uniform float ocean_max_range; \n"              // maximum visible distance of the ocean
-        "uniform float ocean_fade_range; \n"             // distance over which to fade in the ocean
-
-        "void oe_ocean_fragment(inout vec4 color) \n"
-        "{ \n"
-        "    color = ocean_baseColor; \n"
-
-        // amplify the range's effect on alpha when the camera elevation gets low
-        "    float rangeFactor = ocean_remap( ocean_v_msl, -10000.0, 10000.0, 10.0, 1.0 ); \n"
-
-        // affect alpha based on the distance from the camera
-        "    float rangeEffect = ocean_remap(\n"
-        "       ocean_v_range,\n"
-        "       ocean_max_range - ocean_fade_range, ocean_max_range * rangeFactor,\n"
-        "       1.0, 0.0); \n"
-
-        // start with the surface texture.
-        "    if (ocean_has_surface_tex) \n"
-        "    { \n"
-        "        vec4 texel1 = texture2D(ocean_surface_tex, ocean_surface_tex_coord.xy); \n"
-        "        vec4 texel2 = texture2D(ocean_surface_tex, ocean_surface_tex_coord.zw); \n"
-        "        vec4 texel  = vec4(texel1.rgb*texel2.rgb, texel2.a); \n"
-        "        vec4 nearColor = vec4(mix(color.rgb, texel.rgb, texel.a), color.a); \n"
-        "        color = mix(color, nearColor, rangeEffect); \n"
-        "    } \n"
-
-        // effect of the terrain mask [0..1] in the alpha component.
-        "    float maskEffect = texture2D(ocean_data, ocean_mask_tex_coord.xy).a; \n"
-
-        // color it
-        "    color = vec4( color.rgb, maskEffect * rangeEffect * color.a ); \n"
-
-        //"    color = vec4( 1, 0, 0, 1 ); \n" // debugging
-        "} \n";
-}
-
-#endif // OSGEARTH_DRIVER_SIMPLE_OCEAN_SHADERS
+    struct Shaders : public ShaderPackage
+	{
+        Shaders();
+        std::string VERT_MODEL, FRAG;
+	};
+	
+} } // namespace osgEarth::SimpleOcean
diff --git a/src/osgEarthDrivers/ocean_triton/CMakeLists.txt b/src/osgEarthDrivers/ocean_triton/CMakeLists.txt
index c4a3ac6..a26afa0 100644
--- a/src/osgEarthDrivers/ocean_triton/CMakeLists.txt
+++ b/src/osgEarthDrivers/ocean_triton/CMakeLists.txt
@@ -1,24 +1,17 @@
 IF(TRITON_FOUND)
 
 SET(TARGET_SRC TritonDriver.cpp
-               TritonNode.cpp
-               TritonContext.cpp
-               TritonDrawable.cpp
 )
                
-SET(TARGET_H   TritonNode
-               TritonOptions
-               TritonContext
-               TritonDrawable
+SET(TARGET_H 
 )
 
 INCLUDE_DIRECTORIES( 
-    ${TRITON_INCLUDE_DIR}
 )
 
 SET(TARGET_COMMON_LIBRARIES ${TARGET_COMMON_LIBRARIES}
-	${TRITON_LIBRARY}
     osgEarthUtil
+    osgEarthTriton
 )
 
 SETUP_PLUGIN(osgearth_ocean_triton)
@@ -26,8 +19,6 @@ SETUP_PLUGIN(osgearth_ocean_triton)
 # to install public driver includes:
 SET(LIB_NAME ocean_triton)
 
-SET(LIB_PUBLIC_HEADERS TritonOptions)
-
 INCLUDE(ModuleInstallOsgEarthDriverIncludes OPTIONAL)
 
-ENDIF(TRITON_FOUND)
\ No newline at end of file
+ENDIF(TRITON_FOUND)
diff --git a/src/osgEarthDrivers/ocean_triton/TritonContext b/src/osgEarthDrivers/ocean_triton/TritonContext
deleted file mode 100644
index 2a44977..0000000
--- a/src/osgEarthDrivers/ocean_triton/TritonContext
+++ /dev/null
@@ -1,85 +0,0 @@
-/* -*-c++-*- */
-/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
- * http://osgearth.org
- *
- * osgEarth is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>
- */
-#ifndef OSGEARTH_TRITON_CONTEXT_H
-#define OSGEARTH_TRITON_CONTEXT_H
-
-#include "TritonOptions"
-#include <osg/Referenced>
-#include <osg/Light>
-#include <osgEarth/ThreadingUtils>
-
-namespace osgEarth {
-    class SpatialReference;
-}
-
-namespace Triton {
-    class ResourceLoader;
-    class Environment;
-    class Ocean;
-}
-
-namespace osgEarth { namespace Triton
-{
-    /**
-     * Contains all the Triton SDK handles.
-     */
-    class TritonContext : public osg::Referenced
-    {
-    public:
-        TritonContext(const TritonOptions& options);
-
-        /** Sets the spatial reference system of the map */
-        void setSRS(const osgEarth::SpatialReference* srs);
-
-    public: // accessors
-
-        bool ready() const { return _initAttempted && !_initFailed; }
-
-        /** Spatial reference of the map */
-        const osgEarth::SpatialReference* getSRS() const { return _srs.get(); }
-
-        void initialize(osg::RenderInfo& renderInfo);
-
-        void update(double simTime);
-
-        ::Triton::Environment* getEnvironment() { return _environment; }
-        ::Triton::Ocean* getOcean() { return _ocean; }
-
-    protected:
-
-        virtual ~TritonContext();
-
-
-    private:
-        TritonOptions    _options;
-
-        bool             _initAttempted;
-        bool             _initFailed;
-        Threading::Mutex _initMutex;
-
-        osg::ref_ptr<const osgEarth::SpatialReference> _srs;
-
-        ::Triton::ResourceLoader* _resourceLoader;
-        ::Triton::Environment*    _environment;
-        ::Triton::Ocean*          _ocean;
-    };
-
-} } // namespace osgEarth::Triton
-
-#endif // OSGEARTH_TRITON_CONTEXT_H
\ No newline at end of file
diff --git a/src/osgEarthDrivers/ocean_triton/TritonContext.cpp b/src/osgEarthDrivers/ocean_triton/TritonContext.cpp
deleted file mode 100644
index 58e79e3..0000000
--- a/src/osgEarthDrivers/ocean_triton/TritonContext.cpp
+++ /dev/null
@@ -1,141 +0,0 @@
-/* -*-c++-*- */
-/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
- * http://osgearth.org
- *
- * osgEarth is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>
- */
-#include <Triton.h>
-#include "TritonContext"
-#include <osg/GLExtensions>
-#include <osgEarth/SpatialReference>
-
-#define LC "[TritonContext] "
-
-using namespace osgEarth::Triton;
-
-
-TritonContext::TritonContext(const TritonOptions& options) :
-_options              ( options ),
-_initAttempted        ( false ),
-_initFailed           ( false ),
-_resourceLoader       ( 0L ),
-_environment          ( 0L ),
-_ocean                ( 0L )
-{
-    //nop
-}
-
-void
-TritonContext::setSRS(const osgEarth::SpatialReference* srs)
-{
-    _srs = srs;
-}
-
-void
-TritonContext::initialize(osg::RenderInfo& renderInfo)
-{
-    if ( !_initAttempted && !_initFailed )
-    {
-        // lock/double-check:
-        Threading::ScopedMutexLock excl(_initMutex);
-        if ( !_initAttempted && !_initFailed )
-        {
-            _initAttempted = true;
-
-            _resourceLoader = new ::Triton::ResourceLoader(
-                _options.resourcePath()->c_str() );
-
-            _environment = new ::Triton::Environment();
-
-            _environment->SetLicenseCode(
-                _options.user()->c_str(),
-                _options.licenseCode()->c_str() );
-
-            // "WGS84" is used to represent any ellipsoid.
-            ::Triton::CoordinateSystem cs =
-                _srs->isGeographic() ? ::Triton::WGS84_ZUP :
-                ::Triton::FLAT_ZUP;
-
-            // Set the ellipsoid to match the one in our map's SRS.
-            if ( _srs->isGeographic() )
-            {
-                const osg::EllipsoidModel* ellipsoid = _srs->getEllipsoid();
-                
-                std::string eqRadius = Stringify() << ellipsoid->getRadiusEquator();
-                std::string poRadius = Stringify() << ellipsoid->getRadiusPolar();
-
-                _environment->SetConfigOption( "equatorial-earth-radius-meters", eqRadius.c_str() );
-                _environment->SetConfigOption( "polar-earth-radius-meters",      poRadius.c_str() );
-            }
-
-            float openGLVersion = osg::getGLVersionNumber();
-            enum ::Triton::Renderer tritonOpenGlVersion = ::Triton::OPENGL_2_0;
-            if( openGLVersion == 4.1 )
-                tritonOpenGlVersion = ::Triton::OPENGL_4_1;
-            else if( openGLVersion == 4.0 )
-                tritonOpenGlVersion = ::Triton::OPENGL_4_0;
-            else if( openGLVersion == 3.2 )
-                tritonOpenGlVersion = ::Triton::OPENGL_3_2;
-
-            ::Triton::EnvironmentError err = _environment->Initialize(
-                cs,
-                tritonOpenGlVersion,
-                _resourceLoader );
-
-            if ( err == ::Triton::SUCCEEDED )
-            {
-                ::Triton::WindFetch wf;
-                wf.SetWind( 10.0, 0.0 );
-                _environment->AddWindFetch( wf );
-
-                _ocean = ::Triton::Ocean::Create(
-                    _environment, 
-                    ::Triton::JONSWAP );
-            }
-
-            if ( _ocean )
-            {
-                OE_INFO << LC << "Triton initialized OK!" << std::endl;
-            }
-            else
-            {
-                _initFailed = true;
-                OE_WARN << LC << "Triton initialization failed" << std::endl;
-            }
-        }
-    }
-}
-
-void
-TritonContext::update(double simTime)
-{
-    if ( _ocean )
-    {
-        // fmod requires b/c CUDA is limited to single-precision values
-        _ocean->UpdateSimulation( fmod(simTime, 86400.0) );
-    }
-}
-
-TritonContext::~TritonContext()
-{
-    if ( _ocean )
-        delete _ocean;
-
-    if ( _environment )
-        delete _environment;
-
-    if ( _resourceLoader )
-        delete _resourceLoader;
-}
diff --git a/src/osgEarthDrivers/ocean_triton/TritonDrawable b/src/osgEarthDrivers/ocean_triton/TritonDrawable
deleted file mode 100644
index 313cc88..0000000
--- a/src/osgEarthDrivers/ocean_triton/TritonDrawable
+++ /dev/null
@@ -1,85 +0,0 @@
-/* -*-c++-*- */
-/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
- * http://osgearth.org
- *
- * osgEarth is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>
- */
-#ifndef OSGEARTH_TRITON_DRAWABLE_H
-#define OSGEARTH_TRITON_DRAWABLE_H
-
-#include <osg/Drawable>
-#include <osg/RenderInfo>
-#include <osg/TextureCubeMap>
-#include <osg/Version>
-#include <osg/Texture2D>
-
-#include <osgEarth/MapNode>
-#include <osgEarth/Terrain>
-#include <osgEarth/NativeProgramAdapter>
-
-const unsigned int TRITON_OCEAN_MASK = 0x4; // 0100
-
-namespace osgEarth { namespace Triton
-{
-    class TritonContext;
-
-    /**
-     * Custom drawable for rendering the Triton ocean effects
-     */
-    class TritonDrawable : public osg::Drawable
-    {
-    public:
-        TritonDrawable(osgEarth::MapNode* mapNode=NULL, TritonContext* TRITON =0L);
-        META_Object(Triton, TritonDrawable);
-     
-    public: // osg::Drawable
-
-        // custom draw (called with an active GC)
-        void drawImplementation(osg::RenderInfo& ri) const;
-        
-        void setupHeightMap(osgEarth::MapNode* mapNode);
-
-#if OSG_VERSION_GREATER_THAN(3,3,1)
-        osg::BoundingBox computeBoundingBox() const
-#else
-        osg::BoundingBox computeBound() const
-#endif
-            { return osg::BoundingBox(); }
-            
-        void SetPlanarReflectionMap(osg::Texture2D* map) {_planarReflectionMap = map;};
-        void SetPlanarReflectionProjection(osg::RefMatrix * proj) {_planarReflectionProjection = proj;};
-
-    protected:
-        virtual ~TritonDrawable() { }
-
-        osg::observer_ptr<TritonContext>  _TRITON;
-        osg::observer_ptr<osgEarth::MapNode> _mapNode;
-        osg::ref_ptr<osg::TextureCubeMap> _cubeMap;
-        osg::BoundingBox                  _bbox;
-        osg::ref_ptr<osg::Texture2D> _heightMap;
-        osg::ref_ptr<osg::Camera> _heightCamera;
-        osg::observer_ptr<osgEarth::TerrainCallback> _terrainChangedCallback;
-        
-        osg::ref_ptr< osg::Texture2D >       _planarReflectionMap;
-        osg::ref_ptr< osg::RefMatrix >       _planarReflectionProjection;
-
-        mutable osg::buffered_object<osgEarth::NativeProgramAdapterCollection> _adapters;
-        
-        TritonDrawable(const TritonDrawable& copy, const osg::CopyOp& op=osg::CopyOp::SHALLOW_COPY) { }
-    };
-
-} } // namespace osgEarth::Triton
-
-#endif // OSGEARTH_TRITON_DRAWABLE_H
diff --git a/src/osgEarthDrivers/ocean_triton/TritonDrawable.cpp b/src/osgEarthDrivers/ocean_triton/TritonDrawable.cpp
deleted file mode 100644
index f63df95..0000000
--- a/src/osgEarthDrivers/ocean_triton/TritonDrawable.cpp
+++ /dev/null
@@ -1,558 +0,0 @@
-/* -*-c++-*- */
-/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
- * http://osgearth.org
- *
- * osgEarth is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>
- */
-#include <Triton.h>
-
-#include "TritonDrawable"
-#include "TritonContext"
-#include <osg/MatrixTransform>
-#include <osgEarth/SpatialReference>
-#include <osgEarth/VirtualProgram>
-
-#undef  LC
-#define LC "[TritonDrawable] "
-
-//#define DEBUG_HEIGHTMAP
-
-//#define USE_HEIGHT_MAP
-
-using namespace osgEarth::Triton;
-
-namespace
-{
-#ifdef DEBUG_HEIGHTMAP
-    osg::Node*
-    makeFrustumFromCamera( osg::Camera* camera )
-    {
-        osg::Matrixd proj;
-        osg::Matrixd mv;
-        if (camera)
-        {
-            proj = camera->getProjectionMatrix();
-            mv = camera->getViewMatrix();
-        }
-        else
-        {
-            proj.makePerspective( 30., 1., 1., 10. );
-            // leave mv as identity
-        }
-
-        double near=0.0, far=0.0;
-        double left=0.0, right=0.0, bottom=0.0, top=0.0;
-        double fovy=0.0, aspectRatio=0.0;
-        double nLeft=0.0, nRight=0.0, nBottom=0.0, nTop=0.0;
-        double fLeft=0.0, fRight=0.0, fBottom=0.0, fTop=0.0;
-
-        osg::Geode* geode = new osg::Geode;
-
-        if( proj.getPerspective(fovy, aspectRatio, near, far) )
-        {
-            near = proj(3,2) / (proj(2,2)-1.0);
-            far = proj(3,2) / (1.0+proj(2,2));
-
-            nLeft = near * (proj(2,0)-1.0) / proj(0,0);
-            nRight = near * (1.0+proj(2,0)) / proj(0,0);
-            nTop = near * (1.0+proj(2,1)) / proj(1,1);
-            nBottom = near * (proj(2,1)-1.0) / proj(1,1);
-
-            fLeft = far * (proj(2,0)-1.0) / proj(0,0);
-            fRight = far * (1.0+proj(2,0)) / proj(0,0);
-            fTop = far * (1.0+proj(2,1)) / proj(1,1);
-            fBottom = far * (proj(2,1)-1.0) / proj(1,1);
-
-            osg::Vec3Array* v = new osg::Vec3Array;
-            v->resize( 9 );
-            (*v)[0].set( 0., 0., 0. );
-
-            (*v)[1].set( nLeft, nBottom, -near );
-            (*v)[2].set( nRight, nBottom, -near );
-            (*v)[3].set( nRight, nTop, -near );
-            (*v)[4].set( nLeft, nTop, -near );
-            (*v)[5].set( fLeft, fBottom, -far );
-            (*v)[6].set( fRight, fBottom, -far );
-            (*v)[7].set( fRight, fTop, -far );
-            (*v)[8].set( fLeft, fTop, -far );
-
-            osg::Geometry* geom = new osg::Geometry;
-            geom->setVertexArray( v );
-
-            GLushort idxLines[8] = {
-                0, 5, 0, 6, 0, 7, 0, 8 };
-            GLushort idxLoops0[4] = {
-                1, 2, 3, 4 };
-            GLushort idxLoops1[4] = {
-                5, 6, 7, 8 };
-            geom->addPrimitiveSet( new osg::DrawElementsUShort( osg::PrimitiveSet::LINES, 8, idxLines ) );
-            geom->addPrimitiveSet( new osg::DrawElementsUShort( osg::PrimitiveSet::LINE_LOOP, 4, idxLoops0 ) );
-            geom->addPrimitiveSet( new osg::DrawElementsUShort( osg::PrimitiveSet::LINE_LOOP, 4, idxLoops1 ) );
-
-            geode->addDrawable( geom );
-        }
-        else if(proj.getOrtho( left, right, bottom, top, near, far) )
-        {
-            nLeft = left;//near * (proj(2,0)-1.0) / proj(0,0);
-            nRight = right;//near * (1.0+proj(2,0)) / proj(0,0);
-            nTop = top;//near * (1.0+proj(2,1)) / proj(1,1);
-            nBottom = bottom;//near * (proj(2,1)-1.0) / proj(1,1);
-
-            fLeft = left;//far * (proj(2,0)-1.0) / proj(0,0);
-            fRight = right;//far * (1.0+proj(2,0)) / proj(0,0);
-            fTop = top;//far * (1.0+proj(2,1)) / proj(1,1);
-            fBottom = bottom;//far * (proj(2,1)-1.0) / proj(1,1);
-
-            osg::Vec3Array* v = new osg::Vec3Array;
-            v->resize( 9 );
-            (*v)[0].set( 0., 0., 0. );
-
-            (*v)[1].set( nLeft, nBottom, -near );
-            (*v)[2].set( nRight, nBottom, -near );
-            (*v)[3].set( nRight, nTop, -near );
-            (*v)[4].set( nLeft, nTop, -near );
-            (*v)[5].set( fLeft, fBottom, -far );
-            (*v)[6].set( fRight, fBottom, -far );
-            (*v)[7].set( fRight, fTop, -far );
-            (*v)[8].set( fLeft, fTop, -far );
-
-            osg::Geometry* geom = new osg::Geometry;
-            geom->setVertexArray( v );
-
-            GLushort idxLines[8] = {
-                1, 5, 2, 6, 3, 7, 4, 8 };
-            GLushort idxLoops0[4] = {
-                1, 2, 3, 4 };
-            GLushort idxLoops1[4] = {
-                5, 6, 7, 8 };
-            geom->addPrimitiveSet( new osg::DrawElementsUShort( osg::PrimitiveSet::LINES, 8, idxLines ) );
-            geom->addPrimitiveSet( new osg::DrawElementsUShort( osg::PrimitiveSet::LINE_LOOP, 4, idxLoops0 ) );
-            geom->addPrimitiveSet( new osg::DrawElementsUShort( osg::PrimitiveSet::LINE_LOOP, 4, idxLoops1 ) );
-
-            geode->addDrawable( geom );
-        }
-
-        geode->getOrCreateStateSet()->setMode( GL_LIGHTING, osg::StateAttribute::OFF );
-
-
-
-        osg::MatrixTransform* mt = new osg::MatrixTransform;
-        osg::Matrixd mvi = osg::Matrixd::inverse( mv );
-        mt->setMatrix( mvi );
-        mt->addChild( geode );
-
-        return mt;
-    }
-
-    osg::Camera *
-    CreateTextureQuadOverlay( osg::Texture * texture, float x, float y, float w, float h )
-    {
-        osg::Camera * camera = new osg::Camera;
-
-        // set up the background color and clear mask.
-        camera->setClearMask( GL_DEPTH_BUFFER_BIT );
-
-        // set viewport
-        camera->setProjectionMatrixAsOrtho2D( 0, 1, 0, 1 );
-        camera->setViewMatrix( osg::Matrix::identity() );
-        camera->setReferenceFrame( osg::Transform::ABSOLUTE_RF );
-
-        osg::Geode * geode = new osg::Geode();
-        camera->addChild( geode );
-    /*
-        osg::Geometry * background = osg::createTexturedQuadGeometry( osg::Vec3( x,y,0 ),osg::Vec3( w,0,0 ), osg::Vec3( 0,h,0 ) );
-        geode->addDrawable( background );
-
-        osg::Vec4Array* colors = new osg::Vec4Array;
-        colors->push_back( osg::Vec4( 1,1,0,0.3 ) );
-        background->setColorArray( colors );
-        background->setColorBinding( osg::Geometry::BIND_OVERALL );
-        background->getOrCreateStateSet()->setMode( GL_BLEND, osg::StateAttribute::ON );
-        background->getOrCreateStateSet()->setMode( GL_DEPTH_TEST, osg::StateAttribute::OFF );
-    */
-        osg::Geometry * quad = osg::createTexturedQuadGeometry( osg::Vec3( x,y,0 ),osg::Vec3( w,0,0 ), osg::Vec3( 0,h,0 ) );
-        geode->addDrawable( quad );
-        quad->getOrCreateStateSet()->setTextureAttributeAndModes( 0, texture, osg::StateAttribute::ON );
-        quad->getOrCreateStateSet()->setMode( GL_BLEND, osg::StateAttribute::ON );
-        quad->getOrCreateStateSet()->setMode( GL_LIGHTING, osg::StateAttribute::OFF );
-        quad->getOrCreateStateSet()->setMode( GL_DEPTH_TEST, osg::StateAttribute::OFF );
-
-
-        // set the camera to render after the main camera.
-        camera->setRenderOrder(osg::Camera::POST_RENDER);
-
-        return camera;
-    }
-#endif /* DEBUG_HEIGHTMAP */
-
-
-    struct PassHeightMapToTritonCallback : public osg::Camera::DrawCallback
-    {
-        PassHeightMapToTritonCallback(TritonContext* triton) : _TRITON(triton), _enable(false), _id(0) { _ptrEnable = const_cast<bool*> (&_enable); };
-        virtual void operator()( osg::RenderInfo& renderInfo ) const
-        {
-            if( _enable )
-            {
-                *_ptrEnable = false; // cannot directly change _enable because of const
-
-                //osg::notify( osg::ALWAYS ) << "passing heightmap to Triton" << std::endl;
-                if(_TRITON->ready())
-                    _TRITON->getEnvironment()->SetHeightMap((::Triton::TextureHandle)_id,_heightMapMatrix);
-            }
-        }
-
-        unsigned int _frameNumber;
-        bool _enable;
-        bool* _ptrEnable;
-        int _id;
-        ::Triton::Matrix4 _heightMapMatrix;
-
-    private:
-        osg::observer_ptr<TritonContext>  _TRITON;
-    };
-
-
-    class OceanTerrainChangedCallback : public osgEarth::TerrainCallback
-    {
-    public:
-        OceanTerrainChangedCallback(TritonContext* triton, osgEarth::MapNode* mapNode, osg::Camera* heightCam, osg::Texture2D* heightMap )
-          : _TRITON(triton),
-            _mapNode(mapNode),
-            _heightCam(heightCam),
-            _heightMap(heightMap)
-        {
-        }
-
-        virtual void onTileAdded(const osgEarth::TileKey& tileKey, osg::Node* terrain, osgEarth::TerrainCallbackContext& context)
-        {
-            if ( !_TRITON->ready() )
-                return;
-
-            osg::Vec3d eye, center, up;
-            _viewMatrix.getLookAt(eye, center, up);
-            double fovyDEG=0.0, aspectRatio=0.0, zNear=0.0, zFar=0.0;
-            _projectionMatrix.getPerspective(fovyDEG, aspectRatio,zNear,zFar);
-
-            // aspect_ratio = tan( HFOV/2 ) / tan( VFOV/2 )
-            // tan( HFOV/2 ) = tan( VFOV/2 ) * aspect_ratio
-            // HFOV/2 = atan( tan( VFOV/2 ) * aspect_ratio )
-            // HFOV = 2.0 * atan( tan( VFOV/2 ) * aspect_ratio )
-            double fovxDEG = osg::RadiansToDegrees( 2.0 * atan( tan(osg::DegreesToRadians(fovyDEG))/2.0 * aspectRatio ));
-
-            double eyeLat=0.0, eyeLon=0.0, eyeHeight=0.0;
-            _mapNode->getMap()->getSRS()->getEllipsoid()->convertXYZToLatLongHeight(eye.x(), eye.y(), eye.z(), eyeLat, eyeLon, eyeHeight);
-            double clampedEyeX=0.0, clampedEyeY=0.0,clampedEyeZ=0.0;
-            _mapNode->getMap()->getSRS()->getEllipsoid()->convertLatLongHeightToXYZ(eyeLat, eyeLon, 0.0, clampedEyeX, clampedEyeY, clampedEyeZ);
-            osg::Vec3 mslEye(clampedEyeX,clampedEyeY,clampedEyeZ);
-            double lookAtLat=0.0, lookAtLon=0.0, lookAtHeight=0.0;
-            _mapNode->getMap()->getSRS()->getEllipsoid()->convertXYZToLatLongHeight(center.x(), center.y(), center.z(), lookAtLat, lookAtLon, lookAtHeight);
-
-            // Calculate the distance to the horizon from the eyepoint
-            double eyeLen = eye.length();
-            double radE = mslEye.length();
-            double hmax = radE + 8848.0;
-            double hmin = radE - 12262.0;
-            double hasl = osg::maximum(0.1, eyeLen - radE);
-            double radius = eyeLen - hasl;
-            double horizonDistance = osg::minimum(radE, sqrt( 2.0*radius*hasl + hasl*hasl ));
-
-            osg::Vec3d heightCamEye(eye);
-
-            double near = osg::maximum(1.0, heightCamEye.length() - hmax);
-            double far = osg::maximum(10.0, heightCamEye.length() - hmin + radE);
-            //osg::notify( osg::ALWAYS ) << "near = " << near << "; far = " << far << std::endl;
-
-            _heightCam->setProjectionMatrix(osg::Matrix::ortho(-horizonDistance,horizonDistance,-horizonDistance,horizonDistance,near,far) );
-            _heightCam->setViewMatrixAsLookAt( heightCamEye, osg::Vec3d(0.0,0.0,0.0), osg::Vec3d(0.0,0.0,1.0));
-
-            const osg::Matrixd bias(0.5, 0.0, 0.0, 0.0,
-                                    0.0, 0.5, 0.0, 0.0,
-                                    0.0, 0.0, 0.5, 0.0,
-                                    0.5, 0.5, 0.5, 1.0);
-
-            osg::Matrix hMM = _heightCam->getViewMatrix() * _heightCam->getProjectionMatrix() * bias;
-            ::Triton::Matrix4 heightMapMatrix(hMM(0,0),hMM(0,1),hMM(0,2),hMM(0,3),
-                                              hMM(1,0),hMM(1,1),hMM(1,2),hMM(1,3),
-                                              hMM(2,0),hMM(2,1),hMM(2,2),hMM(2,3),
-                                              hMM(3,0),hMM(3,1),hMM(3,2),hMM(3,3));
-
-            //unsigned int contextID = _viewer->getCamera()->getGraphicsContext()->getState()->getContextID();
-            _texObj = _heightMap->getTextureObject(_contextID);
-            //osg::notify( osg::ALWAYS ) << "_contextID " << _contextID << std::endl;
-
-            if(_texObj)
-            {
-                PassHeightMapToTritonCallback* cb = dynamic_cast<PassHeightMapToTritonCallback*>(_heightCam->getFinalDrawCallback());
-                if( cb )
-                {
-                    cb->_enable = true;
-                    cb->_id = _texObj->id();
-                    cb->_heightMapMatrix = heightMapMatrix;
-                }
-            }
-    #ifdef DEBUG_HEIGHTMAP
-            _mapNode->getParent(0)->removeChild(0 ,1);
-            _mapNode->getParent(0)->insertChild(0, makeFrustumFromCamera(_heightCam));
-    #endif /* DEBUG_HEIGHTMAP */
-
-        }
-
-        void setViewMatrix(const osg::Matrix& viewMatrix) { _viewMatrix = viewMatrix; };
-        void setProjectionMatrix(const osg::Matrix& projectionMatrix) { _projectionMatrix = projectionMatrix; };
-        void setContextID(unsigned int contextID) {_contextID = contextID;}
-
-    private:
-        osg::observer_ptr<TritonContext> _TRITON;
-        osg::observer_ptr<osgEarth::MapNode> _mapNode;
-        osg::Camera* _heightCam;
-        osg::Texture2D* _heightMap;
-        osg::Texture::TextureObject* _texObj;
-        osg::Matrix _viewMatrix, _projectionMatrix;
-        unsigned int _contextID;
-    };
-
-
-    const char* vertexShader =
-        "#version " GLSL_VERSION_STR "\n"
-        GLSL_DEFAULT_PRECISION_FLOAT "\n"
-
-        "attribute vec4 oe_terrain_attr; \n"
-        "varying float oe_triton_height;\n"
-
-        "void setupContour(inout vec4 VertexModel) \n"
-        "{ \n"
-        "    oe_triton_height = oe_terrain_attr[3]; \n"
-        "} \n";
-
-    // The fragment shader simply takes the texture index that we generated
-    // in the vertex shader and does a texture lookup. In this case we're
-    // just wholesale replacing the color, so if the map had any existing
-    // imagery, this will overwrite it.
-
-    const char* fragmentShader =
-        "#version " GLSL_VERSION_STR "\n"
-        GLSL_DEFAULT_PRECISION_FLOAT "\n"
-
-        "varying float oe_triton_height;\n"
-
-        "void colorContour( inout vec4 color ) \n"
-        "{ \n"
-#ifdef DEBUG_HEIGHTMAP
-          // Map to black = -500m, white = +500m
-          "   float nHeight = clamp(oe_triton_height / 1000.0 + 0.5, 0.0, 1.0);\n"
-#else
-          "   float nHeight = oe_triton_height;\n"
-#endif
-        "    color = vec4( nHeight, 0.0, 0.0, 1.0 ); \n"
-        "} \n";
-}
-
-
-TritonDrawable::TritonDrawable(osgEarth::MapNode* mapNode, TritonContext* TRITON) :
-_TRITON(TRITON),
-_mapNode(mapNode)
-{
-    // call this to ensure draw() gets called every frame.
-    setSupportsDisplayList( false );
-    setUseVertexBufferObjects( false );
-
-    // dynamic variance prevents update/cull overlap when drawing this
-    setDataVariance( osg::Object::DYNAMIC );
-
-    this->getOrCreateStateSet()->setRenderingHint( osg::StateSet::TRANSPARENT_BIN );
-    this->getOrCreateStateSet()->setRenderBinDetails( 97, "RenderBin" );
-}
-
-void
-TritonDrawable::drawImplementation(osg::RenderInfo& renderInfo) const
-{
-    osg::State* state = renderInfo.getState();
-
-    state->disableAllVertexArrays();
-
-    _TRITON->initialize( renderInfo );
-    if ( !_TRITON->ready() )
-        return;
-
-#ifdef USE_HEIGHT_MAP
-    if( !_terrainChangedCallback.valid())
-        const_cast< TritonDrawable *>( this )->setupHeightMap(_mapNode.get());
-#endif
-
-    ::Triton::Environment* environment = _TRITON->getEnvironment();
-
-    osgEarth::NativeProgramAdapterCollection& adapters = _adapters[ state->getContextID() ];
-    if ( adapters.empty() )
-    {
-        adapters.push_back( new osgEarth::NativeProgramAdapter(state, (GLint)_TRITON->getOcean()->GetShaderObject(::Triton::GOD_RAYS)) );
-        adapters.push_back( new osgEarth::NativeProgramAdapter(state, (GLint)_TRITON->getOcean()->GetShaderObject(::Triton::SPRAY_PARTICLES)) );
-        adapters.push_back( new osgEarth::NativeProgramAdapter(state, (GLint)_TRITON->getOcean()->GetShaderObject(::Triton::WAKE_SPRAY_PARTICLES)) );
-        adapters.push_back( new osgEarth::NativeProgramAdapter(state, (GLint)_TRITON->getOcean()->GetShaderObject(::Triton::WATER_DECALS)) );
-        adapters.push_back( new osgEarth::NativeProgramAdapter(state, (GLint)_TRITON->getOcean()->GetShaderObject(::Triton::WATER_SURFACE)) );
-        adapters.push_back( new osgEarth::NativeProgramAdapter(state, (GLint)_TRITON->getOcean()->GetShaderObject(::Triton::WATER_SURFACE_PATCH)) );
-    }
-    adapters.apply( state );
-
-    // Pass the final view and projection matrices into Triton.
-    if ( environment )
-    {
-        environment->SetCameraMatrix( state->getModelViewMatrix().ptr() );
-        environment->SetProjectionMatrix( state->getProjectionMatrix().ptr() );
-    }
-
-    if(_terrainChangedCallback.valid())
-    {
-        OceanTerrainChangedCallback* c = static_cast<OceanTerrainChangedCallback*>(_terrainChangedCallback.get());
-        c->setViewMatrix( renderInfo.getView()->getCamera()->getViewMatrix() );
-        c->setProjectionMatrix(renderInfo.getView()->getCamera()->getProjectionMatrix() );
-        c->setContextID(renderInfo.getView()->getCamera()->getGraphicsContext()->getState()->getContextID() );
-    }
-
-    state->dirtyAllVertexArrays();
-
-    // Now light and draw the ocean:
-    if ( environment )
-    {
-        // The sun position is roughly where it is in our skybox texture:
-
-        // Since this is a simple example we will just assume that Sun is the light from View light source
-        // TODO: fix this...
-        osg::Light* light = renderInfo.getView() ? renderInfo.getView()->getLight() : NULL;
-
-        // This is the light attached to View so there are no transformations above..
-        // But in general case you would need to accumulate all transforms above the light into this matrix
-        osg::Matrix lightLocalToWorldMatrix = osg::Matrix::identity();
-
-        // If you don't know where the sun lightsource is attached and don't know its local to world matrix you may use
-        // following elaborate scheme to grab the light source while drawing Triton ocean:
-        // - Install cull callback to catch CullVisitor and record pointer to its associated RenderStage
-        //   I was hoping RenderStage can be found from renderInfo in drawImplementation but I didn't figure how ...
-        // - When TritonDrawable::drawImplementation is called all lights will be already applied to OpenGL
-        //   then just find proper infinite directional light by scanning renderStage->PositionalStateContainer.
-        // - Note that we canot scan for the lights inside cull because they may not be traversed before Triton drawable
-        // - When you found interesting ligt source that can work as Sun, read its modelview matrix and lighting params
-        //   Multiply light position by ( modelview * inverse camera view ) and pass this to Triton with lighting colors
-
-        if ( light && light->getPosition().w() == 0 )
-        {
-            osg::Vec4 ambient = light->getAmbient();
-            osg::Vec4 diffuse = light->getDiffuse();
-            osg::Vec4 position = light->getPosition();
-
-            // Compute light position/direction in the world
-            position = position * lightLocalToWorldMatrix;
-
-            // Diffuse direction and color
-            environment->SetDirectionalLight(
-                ::Triton::Vector3( position[0], position[1], position[2] ),
-                ::Triton::Vector3( diffuse[0],  diffuse[1],  diffuse[2] ) );
-
-            // Ambient color based on the zenith color in the cube map
-            environment->SetAmbientLight(
-                ::Triton::Vector3( ambient[0], ambient[1], ambient[2] ) );
-        }
-
-        // Build transform from our cube map orientation space to native Triton orientation
-        // See worldToCubeMap function used in SkyBox to orient sky texture so that sky is up and earth is down
-        osg::Matrix m = osg::Matrix::rotate( osg::PI_2, osg::X_AXIS ); // = worldToCubeMap
-
-        ::Triton::Matrix3 transformFromYUpToZUpCubeMapCoords(
-            m(0,0), m(0,1), m(0,2),
-            m(1,0), m(1,1), m(1,2),
-            m(2,0), m(2,1), m(2,2) );
-
-        // Grab the cube map from our sky box and give it to Triton to use as an _environment map
-        // GLenum texture = renderInfo.getState()->getLastAppliedTextureAttribute( _stage, osg::StateAttribute::TEXTURE );
-        if ( _cubeMap.valid() )
-        {
-            environment->SetEnvironmentMap(
-                (::Triton::TextureHandle)_cubeMap->getTextureObject( state->getContextID() )->id(), transformFromYUpToZUpCubeMapCoords );
-
-            if( _planarReflectionMap.valid() && _planarReflectionProjection.valid() )
-            {
-                osg::Matrix & p = *_planarReflectionProjection;
-
-                ::Triton::Matrix3 planarProjection( p(0,0), p(0,1), p(0,2),
-                                                    p(1,0), p(1,1), p(1,2),
-                                                    p(2,0), p(2,1), p(2,2) );
-
-                environment->SetPlanarReflectionMap( (::Triton::TextureHandle)
-                                                      _planarReflectionMap->getTextureObject( state->getContextID() )->id(),
-                                                      planarProjection, 0.125  );
-            }
-        }
-
-        // Draw the ocean for the current time sample
-        if ( _TRITON->getOcean() )
-        {
-            _TRITON->getOcean()->Draw( renderInfo.getView()->getFrameStamp()->getSimulationTime() );
-        }
-    }
-
-    state->dirtyAllVertexArrays();
-}
-
-void TritonDrawable::setupHeightMap(osgEarth::MapNode* mapNode)
-{
-    int textureUnit = 0;
-    int textureSize = 1024;
-    // Create our height map texture
-    _heightMap = new osg::Texture2D;
-    _heightMap->setTextureSize(textureSize, textureSize);
-    _heightMap->setInternalFormat(GL_LUMINANCE32F_ARB);
-    _heightMap->setSourceFormat(GL_LUMINANCE);
-    _heightMap->setFilter(osg::Texture2D::MIN_FILTER, osg::Texture2D::LINEAR);
-    _heightMap->setFilter(osg::Texture2D::MAG_FILTER, osg::Texture2D::LINEAR);
-
-    // Create its camera and render to it
-    _heightCamera = new osg::Camera;
-    _heightCamera->setReferenceFrame(osg::Transform::ABSOLUTE_RF);
-    _heightCamera->setClearMask(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
-    _heightCamera->setClearColor(osg::Vec4(-1000.0, -1000.0, -1000.0, 1.0f));
-    _heightCamera->setViewport(0, 0, textureSize, textureSize);
-    _heightCamera->setRenderOrder(osg::Camera::PRE_RENDER);
-    _heightCamera->setRenderTargetImplementation( osg::Camera::FRAME_BUFFER_OBJECT );
-    _heightCamera->attach(osg::Camera::COLOR_BUFFER, _heightMap);
-    _heightCamera->setCullMask( ~TRITON_OCEAN_MASK );
-    _heightCamera->setAllowEventFocus(false);
-    _heightCamera->setFinalDrawCallback(new PassHeightMapToTritonCallback(_TRITON.get()));
-
-    // Install the shaders. We also bind osgEarth's elevation data attribute, which the
-    // terrain engine automatically generates at the specified location.
-    osgEarth::VirtualProgram* heightProgram = new osgEarth::VirtualProgram();
-    heightProgram->setFunction( "setupContour", vertexShader,   osgEarth::ShaderComp::LOCATION_VERTEX_MODEL);
-    heightProgram->setFunction( "colorContour", fragmentShader, osgEarth::ShaderComp::LOCATION_FRAGMENT_COLORING);//, -1.0 );
-    heightProgram->addBindAttribLocation( "oe_terrain_attr", osg::Drawable::ATTRIBUTE_6 );
-
-    osg::StateSet *stateSet = _heightCamera->getOrCreateStateSet();
-    stateSet->setAttributeAndModes(heightProgram, osg::StateAttribute::ON);// | osg::StateAttribute::OVERRIDE);
-    stateSet->setMode(GL_LIGHTING, osg::StateAttribute::OFF);// | osg::StateAttribute::OVERRIDE);
-
-
-    if( mapNode && _heightCamera )
-    {
-        _heightCamera->addChild( mapNode->getTerrainEngine() );
-        _terrainChangedCallback = new OceanTerrainChangedCallback( _TRITON.get(), mapNode, _heightCamera.get(), _heightMap.get());
-        mapNode->getTerrain()->addTerrainCallback( _terrainChangedCallback.get() );
-    }
-
-    osg::Group* root = osgEarth::findTopMostNodeOfType<osg::Group>(mapNode);
-    root->addChild(_heightCamera);
-
-#ifdef DEBUG_HEIGHTMAP
-    mapNode->getParent(0)->addChild(CreateTextureQuadOverlay(_heightMap, 0.65, 0.05, 0.3, 0.3));
-    mapNode->getParent(0)->insertChild(0, makeFrustumFromCamera(_heightCamera));
-#endif /* DEBUG_HEIGHTMAP */
-}
\ No newline at end of file
diff --git a/src/osgEarthDrivers/ocean_triton/TritonDriver.cpp b/src/osgEarthDrivers/ocean_triton/TritonDriver.cpp
index 6c3eaf2..12dc25f 100644
--- a/src/osgEarthDrivers/ocean_triton/TritonDriver.cpp
+++ b/src/osgEarthDrivers/ocean_triton/TritonDriver.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -25,7 +25,8 @@
 #include <osgEarth/ThreadingUtils>
 #include <osgEarthUtil/Ocean>
 
-#include "TritonNode"
+#include <osgEarthTriton/TritonOptions>
+#include <osgEarthTriton/TritonNode>
 
 #undef  LC
 #define LC "[TritonDriver] "
@@ -34,60 +35,59 @@
 
 namespace osgEarth { namespace Triton
 {
-    class TritonDriver : public osgEarth::Util::OceanDriver
+    using namespace osgEarth;
+    using namespace osgEarth::Util;
+
+    /**
+     * Extension that lets you load a SimpleOcean from an earth file.
+     */
+    class TritonExtension : public Extension,
+                            public ExtensionInterface<MapNode>,
+                            public TritonOptions,
+                            public OceanNodeFactory
     {
     public:
-        TritonDriver()
+        META_Object(osgearth_ocean_triton, TritonExtension);
+
+        TritonExtension() { }
+
+        TritonExtension(const ConfigOptions& options) :
+            TritonOptions(options) { }
+
+    public: // Extension
+
+        const ConfigOptions& getConfigOptions() const { return *this; }
+
+    public: // ExtensionInterface<MapNode>
+
+        bool connect(MapNode* mapNode)
         {
-            supportsExtension(
-                "osgearth_ocean_triton",
-                "osgEarth Triton Ocean plugin" );
+            _oceanNode = createOceanNode(mapNode);
+            mapNode->addChild(_oceanNode.get());
+            return true;
         }
 
-        const char* className()
+        bool disconnect(MapNode* mapNode)
         {
-            return "osgEarth Triton Ocean plugin";
+            if (mapNode && _oceanNode.valid())
+                mapNode->removeChild(_oceanNode.get());
+            return true;
         }
 
-        ReadResult readNode(const std::string& file_name, const Options* options) const
-        {
-            if ( !acceptsExtension(osgDB::getLowerCaseFileExtension( file_name )))
-                return ReadResult::FILE_NOT_HANDLED;
-
-            TritonOptions tritonOptions = getOceanOptions(options);
-
-            // if the Resource Path isn't set, attempt to set it from 
-            // the SL environment variable.
-            if ( !tritonOptions.resourcePath().isSet() )
-            {
-                const char* ev = ::getenv("TRITON_PATH");
-                if ( ev )
-                {
-                    tritonOptions.resourcePath() = osgDB::concatPaths(
-                        std::string(ev),
-                        "Resources" );
-
-                    OE_INFO << LC 
-                        << "Setting resource path to << " << tritonOptions.resourcePath().get()
-                        << std::endl;
-                }
-                else
-                {
-                    OE_WARN << LC
-                        << "No resource path! Triton might not initialize properly. "
-                        << "Consider setting the TRITON_PATH environment variable."
-                        << std::endl;
-                }
-            }
-
-            osgEarth::MapNode* mapNode = getMapNode(options);
-            return new TritonNode( mapNode, tritonOptions );
+    public: // OceanNodeFactory
+
+        OceanNode* createOceanNode(MapNode* mapNode) {
+            return new TritonNode(mapNode, *this);
         }
 
     protected:
-        virtual ~TritonDriver() { }
+        TritonExtension(const TritonExtension& rhs, const osg::CopyOp& op) { }
+
+        virtual ~TritonExtension() { }
+
+        osg::ref_ptr<OceanNode> _oceanNode;
     };
 
-    REGISTER_OSGPLUGIN(osgearth_ocean_triton, TritonDriver)
+    REGISTER_OSGEARTH_EXTENSION(osgearth_ocean_triton, TritonExtension);
 
-} } // namespace osgEarth::Triton
+} } // namespace osgEarth::Drivers::Triton
diff --git a/src/osgEarthDrivers/ocean_triton/TritonNode b/src/osgEarthDrivers/ocean_triton/TritonNode
deleted file mode 100644
index 3c662c3..0000000
--- a/src/osgEarthDrivers/ocean_triton/TritonNode
+++ /dev/null
@@ -1,61 +0,0 @@
-/* -*-c++-*- */
-/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
- * http://osgearth.org
- *
- * osgEarth is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>
- */
-#ifndef OSGEARTH_TRITON_NODE
-#define OSGEARTH_TRITON_NODE 1
-
-#include "TritonOptions"
-#include <osgEarthUtil/Ocean>
-#include <osgEarth/MapNode>
-#include <osg/Drawable>
-
-namespace osgEarth { namespace Triton
-{
-    class TritonContext;
-
-    /**
-     * Node that roots the Triton adapter.
-     */
-    class TritonNode : public osgEarth::Util::OceanNode
-    {
-    public:
-        TritonNode(
-            osgEarth::MapNode*   mapNode,
-            const TritonOptions& options );
-
-    protected: // OceanNode
-
-        void onSetSeaLevel();
-
-    public: // osg::Node
-
-        osg::BoundingSphere computeBound() const;
-
-        void traverse(osg::NodeVisitor&);
-
-    protected:
-        virtual ~TritonNode();
-
-        osg::ref_ptr<TritonContext> _TRITON;
-        TritonOptions               _options;
-        osg::Drawable*              _drawable;
-    };
-
-} } // namespace osgEarth::Triton
-
-#endif // OSGEARTH_TRITON_NODE
diff --git a/src/osgEarthDrivers/ocean_triton/TritonNode.cpp b/src/osgEarthDrivers/ocean_triton/TritonNode.cpp
deleted file mode 100644
index 99d38a7..0000000
--- a/src/osgEarthDrivers/ocean_triton/TritonNode.cpp
+++ /dev/null
@@ -1,84 +0,0 @@
-/* -*-c++-*- */
-/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
- * http://osgearth.org
- *
- * osgEarth is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>
- */
-
-#include <Triton.h>
-#include "TritonNode"
-#include "TritonContext"
-#include "TritonDrawable"
-#include <osgEarth/CullingUtils>
-
-#define LC "[TritonNode] "
-
-using namespace osgEarth::Triton;
-
-TritonNode::TritonNode(osgEarth::MapNode*   mapNode,
-                       const TritonOptions& options) :
-OceanNode( options ),
-_options ( options )
-{
-    const osgEarth::Map* map = mapNode->getMap();
-    if ( map )
-        setSRS( map->getSRS() );
-
-    _TRITON = new TritonContext( options );
-
-    if ( map )
-        _TRITON->setSRS( map->getSRS() );
-
-    TritonDrawable* tritonDrawable = new TritonDrawable(mapNode,_TRITON);
-    _drawable = tritonDrawable;
-    osg::Geode* geode = new osg::Geode();
-    geode->addDrawable( _drawable );
-    geode->setNodeMask( TRITON_OCEAN_MASK );
-
-    this->addChild( geode );
-
-    this->setNumChildrenRequiringUpdateTraversal(1);
-}
-
-TritonNode::~TritonNode()
-{
-    //nop
-}
-
-void
-TritonNode::onSetSeaLevel()
-{
-    if ( _TRITON->ready() )
-    {
-        _TRITON->getEnvironment()->SetSeaLevel( getSeaLevel() );
-    }
-    dirtyBound();
-}
-
-osg::BoundingSphere
-TritonNode::computeBound() const
-{
-    return osg::BoundingSphere();
-}
-
-void
-TritonNode::traverse(osg::NodeVisitor& nv)
-{
-    if ( nv.getVisitorType() == nv.UPDATE_VISITOR && _TRITON->ready() )
-    {
-        _TRITON->update(nv.getFrameStamp()->getSimulationTime());
-    }
-    osgEarth::Util::OceanNode::traverse(nv);
-}
diff --git a/src/osgEarthDrivers/ocean_triton/TritonOptions b/src/osgEarthDrivers/ocean_triton/TritonOptions
deleted file mode 100644
index 68d0531..0000000
--- a/src/osgEarthDrivers/ocean_triton/TritonOptions
+++ /dev/null
@@ -1,83 +0,0 @@
-/* -*-c++-*- */
-/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
- * http://osgearth.org
- *
- * osgEarth is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>
- */
-#ifndef OSGEARTH_TRITON_OPTIONS
-#define OSGEARTH_TRITON_OPTIONS 1
-
-#include <osgEarthUtil/Ocean>
-
-namespace osgEarth { namespace Triton
-{
-    /**
-     * Options for controlling the ocean surface node.
-     */
-    class /*header-only*/ TritonOptions : public osgEarth::Util::OceanOptions
-    {
-    public:
-        TritonOptions(const osgEarth::Util::OceanOptions& conf = osgEarth::Util::OceanOptions()) :
-            osgEarth::Util::OceanOptions( conf )
-        {
-            setDriver( "triton" );
-            fromConfig( _conf );
-        }
-
-        virtual ~TritonOptions() { }
-
-        /* User name for license activation */
-        osgEarth::optional<std::string>& user() { return _user; }
-        const osgEarth::optional<std::string>& user() const { return _user; }
-
-        /* License code string */
-        osgEarth::optional<std::string>& licenseCode() { return _licenseCode; }
-        const osgEarth::optional<std::string>& licenseCode() const { return _licenseCode; }
-
-        /* SilverLining resource path */
-        osgEarth::optional<std::string>& resourcePath() { return _resourcePath; }
-        const osgEarth::optional<std::string>& resourcePath() const { return _resourcePath; }
-
-    public:
-        osgEarth::Config getConfig() const {
-            osgEarth::Config conf = osgEarth::Util::OceanOptions::newConfig();
-            conf.addIfSet("user", _user);
-            conf.addIfSet("license_code", _licenseCode);
-            conf.addIfSet("resource_path", _resourcePath);
-            return conf;
-        }
-
-    protected:
-        void mergeConfig( const osgEarth::Config& conf ) {
-            osgEarth::Util::OceanOptions::mergeConfig( conf );
-            fromConfig( conf );
-        }
-
-    private:
-        void fromConfig( const osgEarth::Config& conf ) {
-            conf.getIfSet("user", _user);
-            conf.getIfSet("license_code", _licenseCode);
-            conf.getIfSet("resource_path", _resourcePath);
-        }
-
-    private:
-        osgEarth::optional<std::string> _user;
-        osgEarth::optional<std::string> _licenseCode;
-        osgEarth::optional<std::string> _resourcePath;
-    };
-
-} } // namespace osgEarth::Triton
-
-#endif // OSGEARTH_TRITON_OPTIONS
diff --git a/src/osgEarthDrivers/osg/OSGOptions b/src/osgEarthDrivers/osg/OSGOptions
index 9dd2846..a1d03a5 100644
--- a/src/osgEarthDrivers/osg/OSGOptions
+++ b/src/osgEarthDrivers/osg/OSGOptions
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthDrivers/osg/OSGTileSource.cpp b/src/osgEarthDrivers/osg/OSGTileSource.cpp
index 3f176ab..ce6b88b 100644
--- a/src/osgEarthDrivers/osg/OSGTileSource.cpp
+++ b/src/osgEarthDrivers/osg/OSGTileSource.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -72,7 +72,7 @@ public:
 
         if ( !getProfile() )
         {
-            return Status::Error( "An explicit profile definition is required by the OSG driver." );
+            return Status::Error( Status::ConfigurationError, "An explicit profile definition is required by the OSG driver." );
         }
 
         osg::ref_ptr<osg::Image> image;
@@ -88,7 +88,7 @@ public:
 
         if ( !image.valid() )
         {
-            return Status::Error( Stringify() <<  "Faild to load data from \"" << _options.url()->full() << "\"" );
+            return Status::Error( Status::ResourceUnavailable, Stringify() <<  "Faild to load data from \"" << _options.url()->full() << "\"" );
         }
 
         // calculate and store the maximum LOD for which to return data
@@ -178,7 +178,7 @@ public:
         supportsExtension( "osgearth_osg", "OSG image driver for osgEarth" );
     }
 
-    virtual const char* className()
+    virtual const char* className() const
     {
         return "OSG Image Driver";
     }
diff --git a/src/osgEarthDrivers/quadkey/QuadKeyOptions b/src/osgEarthDrivers/quadkey/QuadKeyOptions
index fdf3879..952bdb3 100644
--- a/src/osgEarthDrivers/quadkey/QuadKeyOptions
+++ b/src/osgEarthDrivers/quadkey/QuadKeyOptions
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthDrivers/quadkey/ReaderWriterQuadKey.cpp b/src/osgEarthDrivers/quadkey/ReaderWriterQuadKey.cpp
index 8f8d910..1be6cf6 100644
--- a/src/osgEarthDrivers/quadkey/ReaderWriterQuadKey.cpp
+++ b/src/osgEarthDrivers/quadkey/ReaderWriterQuadKey.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
@@ -50,7 +50,7 @@ class QuadKeySource : public TileSource
 {
 public:
     QuadKeySource(const TileSourceOptions& options) : 
-      TileSource(options), _options(options), _rotate_iter(0u)
+        TileSource(options), _options(options), _rotate_iter(0u), _rotateStart(0), _rotateEnd(0)
     {
         //nop
     }
@@ -63,7 +63,7 @@ public:
         URI uri = _options.url().value();
         if ( uri.empty() )
         {
-            return Status::Error( "Fail: driver requires a valid \"url\" property" );
+            return Status::Error( Status::ConfigurationError, "Fail: driver requires a valid \"url\" property" );
         }
 
         // The quadkey driver always uses spherical mercator.
@@ -182,7 +182,7 @@ public:
         supportsExtension( "osgearth_quadkey", "QuadKey Driver" );
     }
 
-    virtual const char* className()
+    virtual const char* className() const
     {
         return "QuadKey Driver";
     }
diff --git a/src/osgEarthDrivers/refresh/ReaderWriterRefresh.cpp b/src/osgEarthDrivers/refresh/ReaderWriterRefresh.cpp
index f7ae050..20145dd 100644
--- a/src/osgEarthDrivers/refresh/ReaderWriterRefresh.cpp
+++ b/src/osgEarthDrivers/refresh/ReaderWriterRefresh.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
@@ -233,7 +233,7 @@ public:
         supportsExtension( "osgearth_refresh", "Refresh" );
     }
 
-    virtual const char* className()
+    virtual const char* className() const
     {
         return "ReaderWriterRefresh";
     }
diff --git a/src/osgEarthDrivers/refresh/RefreshOptions b/src/osgEarthDrivers/refresh/RefreshOptions
index ec33e90..0871b2e 100644
--- a/src/osgEarthDrivers/refresh/RefreshOptions
+++ b/src/osgEarthDrivers/refresh/RefreshOptions
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthDrivers/script_engine_duktape/CMakeLists.txt b/src/osgEarthDrivers/script_engine_duktape/CMakeLists.txt
index 72d853d..b8385d4 100644
--- a/src/osgEarthDrivers/script_engine_duktape/CMakeLists.txt
+++ b/src/osgEarthDrivers/script_engine_duktape/CMakeLists.txt
@@ -20,6 +20,7 @@ ELSE(WITH_EXTERNAL_DUKTAPE)
 
     SET(TARGET_H
         duktape.h
+        duk_config.h
         DuktapeEngine
 		JSGeometry
     )
diff --git a/src/osgEarthDrivers/script_engine_duktape/DuktapeEngine b/src/osgEarthDrivers/script_engine_duktape/DuktapeEngine
index e663089..75a73f0 100644
--- a/src/osgEarthDrivers/script_engine_duktape/DuktapeEngine
+++ b/src/osgEarthDrivers/script_engine_duktape/DuktapeEngine
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -58,8 +58,9 @@ namespace osgEarth { namespace Drivers { namespace Duktape
         {
             Context();
             ~Context();
-            void initialize(const ScriptEngineOptions&);
+            void initialize(const ScriptEngineOptions&, bool);
             duk_context* _ctx;
+            osg::observer_ptr<const Feature> _feature;
         };
 
         PerThread<Context> _contexts;
diff --git a/src/osgEarthDrivers/script_engine_duktape/DuktapeEngine.cpp b/src/osgEarthDrivers/script_engine_duktape/DuktapeEngine.cpp
index 804747c..5eab418 100644
--- a/src/osgEarthDrivers/script_engine_duktape/DuktapeEngine.cpp
+++ b/src/osgEarthDrivers/script_engine_duktape/DuktapeEngine.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -136,30 +136,64 @@ namespace
 namespace
 {
     // Create a "feature" object in the global namespace.
-    void setFeature(duk_context* ctx, Feature const* feature)
+    void setFeature(duk_context* ctx, Feature const* feature, bool complete)
     {
-        std::string geojson = feature->getGeoJSON();
-        
-        duk_push_global_object(ctx);                         // [global]
-        duk_push_string(ctx, geojson.c_str());               // [global, json]
-        duk_json_decode(ctx, -1);                            // [global, feature]
-        duk_push_pointer(ctx, (void*)feature);               // [global, feature, ptr]
-        duk_put_prop_string(ctx, -2, "__ptr");               // [global, feature]
-        duk_put_prop_string(ctx, -2, "feature");             // [global]
+        duk_push_global_object(ctx);                             // [global]
 
-        // add the save() function and the "attributes" alias.
-        duk_eval_string_noresult(ctx,
-            "feature.save = function() {"
-            "    oe_duk_save_feature(this.__ptr);"
-            "} ");
+        // Complete profile: properties, geometry, and API bindings.
+        if ( complete )
+        {
+            std::string geojson = feature->getGeoJSON();
+            duk_push_string(ctx, geojson.c_str());               // [global, json]
+            duk_json_decode(ctx, -1);                            // [global, feature]
+            duk_push_pointer(ctx, (void*)feature);               // [global, feature, ptr]
+            duk_put_prop_string(ctx, -2, "__ptr");               // [global, feature]
+            duk_put_prop_string(ctx, -2, "feature");             // [global]
+
+            // add the save() function and the "attributes" alias.
+            duk_eval_string_noresult(ctx,
+                "feature.save = function() {"
+                "    oe_duk_save_feature(this.__ptr);"
+                "} ");
+
+            duk_eval_string_noresult(ctx,
+                "Object.defineProperty(feature, 'attributes', {get:function() {return feature.properties;}});");
+
+            GeometryAPI::bindToFeature(ctx);
+        }
 
-        duk_eval_string_noresult(ctx,
-            "Object.defineProperty(feature, 'attributes', {get:function() {return feature.properties;}});");
+        // Minimal profile: ID and properties only. MUCH faster!
+        else
+        {
+            duk_idx_t feature_i = duk_push_object(ctx);
+            {
+                duk_push_int(ctx, feature->getFID());
+                duk_put_prop_string(ctx, feature_i, "id");
 
-        GeometryAPI::bindToFeature(ctx);
+                duk_idx_t props_i = duk_push_object(ctx);
+                {
+                    const AttributeTable& attrs = feature->getAttrs();
+                    for(AttributeTable::const_iterator a = attrs.begin(); a != attrs.end(); ++a)
+                    {
+                        AttributeType type = a->second.first;
+                        switch(type) {
+                        case ATTRTYPE_DOUBLE: duk_push_number (ctx, a->second.getDouble()); break;
+                        case ATTRTYPE_INT:    duk_push_int    (ctx, a->second.getInt()); break;
+                        case ATTRTYPE_BOOL:   duk_push_boolean(ctx, a->second.getBool()); break;
+                        case ATTRTYPE_STRING:
+                        default:              duk_push_string (ctx, a->second.getString().c_str()); break;
+                        }
+                        duk_put_prop_string(ctx, props_i, a->first.c_str());
+                    }
+                }
+                duk_put_prop_string(ctx, feature_i, "properties");
+            }
+            duk_put_prop_string(ctx, -2, "feature");
+        }
 
         duk_pop(ctx); 
     }
+    
 }
 
 //............................................................................
@@ -170,7 +204,7 @@ DuktapeEngine::Context::Context()
 }
 
 void
-DuktapeEngine::Context::initialize(const ScriptEngineOptions& options)
+DuktapeEngine::Context::initialize(const ScriptEngineOptions& options, bool complete)
 {
     if ( _ctx == 0L )
     {
@@ -193,14 +227,17 @@ DuktapeEngine::Context::initialize(const ScriptEngineOptions& options)
         duk_push_global_object( _ctx );
 
         // Add global log function.
-        duk_push_c_function( _ctx, log, DUK_VARARGS );
-        duk_put_prop_string( _ctx, -2, "log" );
+        duk_push_c_function( _ctx, log, DUK_VARARGS ); // [global, function]
+        duk_put_prop_string( _ctx, -2, "log" );        // [global]
 
-        // feature.save() callback
-        duk_push_c_function(_ctx, oe_duk_save_feature, 1/*numargs*/); // [global, function]
-        duk_put_prop_string(_ctx, -2, "oe_duk_save_feature");         // [global]
+        if ( complete )
+        {
+            // feature.save() callback
+            duk_push_c_function(_ctx, oe_duk_save_feature, 1/*numargs*/); // [global, function]
+            duk_put_prop_string(_ctx, -2, "oe_duk_save_feature");         // [global]
 
-        GeometryAPI::install(_ctx);
+            GeometryAPI::install(_ctx);
+        }
 
         duk_pop(_ctx); // []
     }
@@ -236,28 +273,34 @@ DuktapeEngine::run(const std::string&   code,
 {
     if (code.empty())
         return ScriptResult(EMPTY_STRING, false, "Script is empty.");
+        
+    bool complete = (getProfile() == "full");
 
 #ifdef MAXIMUM_ISOLATION
     // brand new context every time
     Context c;
-    c.initialize( _options );
+    c.initialize( _options, complete );
     duk_context* ctx = c._ctx;
 #else
     // cache the Context on a per-thread basis
     Context& c = _contexts.get();
-    c.initialize( _options );
+    c.initialize( _options, complete );
     duk_context* ctx = c._ctx;
 #endif
 
-	if(feature) {
-		// encode the feature in the global object and push a
-        // native pointer:
-		setFeature(ctx, feature);
+	if ( feature && feature != c._feature.get() )
+    {
+		// encode the feature in the global object and push a native pointer:
+		setFeature(ctx, feature, complete);
 	}
 
+    // remember the feature so we don't re-create it if not necessary
+    c._feature = feature;
+
     // run the script. On error, the top of stack will hold the error
     // message instead of the return value.
     std::string resultString;
+
     bool ok = (duk_peval_string(ctx, code.c_str()) == 0); // [ "result" ]
     const char* resultVal = duk_to_string(ctx, -1);
     if ( resultVal )
@@ -265,7 +308,7 @@ DuktapeEngine::run(const std::string&   code,
 
     if ( !ok )
     {
-        OE_WARN << LC << "Error: source =\n" << code << std::endl;
+        OE_WARN << LC << "Error: source =" << std::endl << code << std::endl;
     }
 
     // pop the return value:
diff --git a/src/osgEarthDrivers/script_engine_duktape/JSGeometry b/src/osgEarthDrivers/script_engine_duktape/JSGeometry
index 95f5fdc..6ddd66d 100644
--- a/src/osgEarthDrivers/script_engine_duktape/JSGeometry
+++ b/src/osgEarthDrivers/script_engine_duktape/JSGeometry
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -136,6 +136,8 @@ namespace osgEarth { namespace Drivers { namespace Duktape
             duk_put_prop_string(ctx, -2, "xmax");
             duk_push_number(ctx, b.yMax());
             duk_put_prop_string(ctx, -2, "ymax");
+            duk_push_number(ctx, b.area2d());
+            duk_put_prop_string(ctx, -2, "area");
 
             return 1;
         }
diff --git a/src/osgEarthDrivers/script_engine_duktape/Plugin.cpp b/src/osgEarthDrivers/script_engine_duktape/Plugin.cpp
index 49217be..7772cd9 100644
--- a/src/osgEarthDrivers/script_engine_duktape/Plugin.cpp
+++ b/src/osgEarthDrivers/script_engine_duktape/Plugin.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -39,7 +39,7 @@ namespace osgEarth { namespace Drivers { namespace Duktape
                 "osgearth_scriptengine_javascript", "osgEarth Duktape JavaScript Engine" );
         }
 
-        const char* className()
+        const char* className() const
         {
             return "osgEarth Duktape JavaScript Engine";
         }
@@ -49,7 +49,7 @@ namespace osgEarth { namespace Drivers { namespace Duktape
           if ( !acceptsExtension(osgDB::getLowerCaseFileExtension(filename)) )
                 return ReadResult::FILE_NOT_HANDLED;
 
-          OE_INFO << LC << "Loaded duktape JavaScript engine" << std::endl;
+          OE_DEBUG << LC << "Loaded duktape JavaScript engine" << std::endl;
           return ReadResult( new DuktapeEngine(getScriptEngineOptions(dbOptions)) );
         }
     };
diff --git a/src/osgEarthDrivers/script_engine_duktape/duk_config.h b/src/osgEarthDrivers/script_engine_duktape/duk_config.h
new file mode 100644
index 0000000..64c10ea
--- /dev/null
+++ b/src/osgEarthDrivers/script_engine_duktape/duk_config.h
@@ -0,0 +1,3643 @@
+/*
+ *  duk_config.h configuration header generated by genconfig.py.
+ *
+ *  Git commit: cad6f595382a0cc1a7e4207794ade5be11b3e397
+ *  Git describe: v1.4.0
+ *  Git branch: master
+ *
+ *  Supported platforms:
+ *      - Mac OSX, iPhone, Darwin
+ *      - OpenBSD
+ *      - Generic BSD
+ *      - Atari ST TOS
+ *      - AmigaOS
+ *      - Windows
+ *      - Flashplayer (Crossbridge)
+ *      - QNX
+ *      - TI-Nspire
+ *      - Emscripten
+ *      - Linux
+ *      - Solaris
+ *      - Generic POSIX
+ *      - Cygwin
+ *      - Generic UNIX
+ *      - Generic fallback
+ *
+ *  Supported architectures:
+ *      - x86
+ *      - x64
+ *      - x32
+ *      - ARM 32-bit
+ *      - ARM 64-bit
+ *      - MIPS 32-bit
+ *      - MIPS 64-bit
+ *      - PowerPC 32-bit
+ *      - PowerPC 64-bit
+ *      - SPARC 32-bit
+ *      - SPARC 64-bit
+ *      - SuperH
+ *      - Motorola 68k
+ *      - Emscripten
+ *      - Generic
+ *
+ *  Supported compilers:
+ *      - Clang
+ *      - GCC
+ *      - MSVC
+ *      - Emscripten
+ *      - TinyC
+ *      - VBCC
+ *      - Bruce's C compiler
+ *      - Generic
+ *
+ */
+
+#if !defined(DUK_CONFIG_H_INCLUDED)
+#define DUK_CONFIG_H_INCLUDED
+
+/*
+ *  Intermediate helper defines
+ */
+
+/* DLL build detection */
+#if defined(DUK_OPT_DLL_BUILD)
+#define DUK_F_DLL_BUILD
+#elif defined(DUK_OPT_NO_DLL_BUILD)
+#undef DUK_F_DLL_BUILD
+#else
+/* not configured for DLL build */
+#undef DUK_F_DLL_BUILD
+#endif
+
+/* Apple OSX, iOS */
+#if defined(__APPLE__)
+#define DUK_F_APPLE
+#endif
+
+/* OpenBSD */
+#if defined(__OpenBSD__) || defined(__OpenBSD)
+#define DUK_F_OPENBSD
+#endif
+
+/* NetBSD */
+#if defined(__NetBSD__) || defined(__NetBSD)
+#define DUK_F_NETBSD
+#endif
+
+/* FreeBSD */
+#if defined(__FreeBSD__) || defined(__FreeBSD)
+#define DUK_F_FREEBSD
+#endif
+
+/* BSD variant */
+#if defined(DUK_F_FREEBSD) || defined(DUK_F_NETBSD) || defined(DUK_F_OPENBSD) || \
+    defined(__bsdi__) || defined(__DragonFly__)
+#define DUK_F_BSD
+#endif
+
+/* Atari ST TOS.  __TOS__ defined by PureC.  No platform define in VBCC
+ * apparently, so to use with VBCC user must define __TOS__ manually.
+  */
+#if defined(__TOS__)
+#define DUK_F_TOS
+#endif
+
+/* Motorola 68K.  Not defined by VBCC, so user must define one of these
+ * manually when using VBCC.
+ */
+#if defined(__m68k__) || defined(M68000) || defined(__MC68K__)
+#define DUK_F_M68K
+#endif
+
+/* AmigaOS.  Neither AMIGA nor __amigaos__ is defined on VBCC, so user must
+ * define 'AMIGA' manually when using VBCC.
+ */
+#if defined(AMIGA) || defined(__amigaos__)
+#define DUK_F_AMIGAOS
+#endif
+
+/* PowerPC */
+#if defined(__powerpc) || defined(__powerpc__) || defined(__PPC__)
+#define DUK_F_PPC
+#if defined(__PPC64__) || defined(__LP64__) || defined(_LP64)
+#define DUK_F_PPC64
+#else
+#define DUK_F_PPC32
+#endif
+#endif
+
+/* Windows, both 32-bit and 64-bit */
+#if defined(_WIN32) || defined(WIN32) || defined(_WIN64) || defined(WIN64) || \
+    defined(__WIN32__) || defined(__TOS_WIN__) || defined(__WINDOWS__)
+#define DUK_F_WINDOWS
+#if defined(_WIN64) || defined(WIN64)
+#define DUK_F_WIN64
+#else
+#define DUK_F_WIN32
+#endif
+#endif
+
+/* Flash player (e.g. Crossbridge) */
+#if defined(__FLASHPLAYER__)
+#define DUK_F_FLASHPLAYER
+#endif
+
+/* QNX */
+#if defined(__QNX__)
+#define DUK_F_QNX
+#endif
+
+/* TI-Nspire (using Ndless) */
+#if defined(_TINSPIRE)
+#define DUK_F_TINSPIRE
+#endif
+
+/* Emscripten (provided explicitly by user), improve if possible */
+#if defined(EMSCRIPTEN)
+#define DUK_F_EMSCRIPTEN
+#endif
+
+/* BCC (Bruce's C compiler): this is a "torture target" for compilation */
+#if defined(__BCC__) || defined(__BCC_VERSION__)
+#define DUK_F_BCC
+#endif
+
+/* Linux */
+#if defined(__linux) || defined(__linux__) || defined(linux)
+#define DUK_F_LINUX
+#endif
+
+/* illumos / Solaris */
+#if defined(__sun) && defined(__SVR4)
+#define DUK_F_SUN
+#endif
+
+/* POSIX */
+#if defined(__posix)
+#define DUK_F_POSIX
+#endif
+
+/* Cygwin */
+#if defined(__CYGWIN__)
+#define DUK_F_CYGWIN
+#endif
+
+/* Generic Unix (includes Cygwin) */
+#if defined(__unix) || defined(__unix__) || defined(unix) || \
+    defined(DUK_F_LINUX) || defined(DUK_F_BSD)
+#define DUK_F_UNIX
+#endif
+
+/* stdint.h not available */
+#if defined(DUK_F_WINDOWS) && defined(_MSC_VER)
+#if (_MSC_VER < 1700)
+/* VS2012+ has stdint.h, < VS2012 does not (but it's available for download). */
+#define DUK_F_NO_STDINT_H
+#endif
+#endif
+#if !defined(DUK_F_NO_STDINT_H) && (defined(DUK_F_TOS) || defined(DUK_F_BCC))
+#define DUK_F_NO_STDINT_H
+#endif
+
+/* C++ */
+#undef DUK_F_CPP
+#if defined(__cplusplus)
+#define DUK_F_CPP
+#endif
+
+/* Intel x86 (32-bit), x64 (64-bit) or x32 (64-bit but 32-bit pointers),
+ * define only one of DUK_F_X86, DUK_F_X64, DUK_F_X32.
+ * https://sites.google.com/site/x32abi/
+ */
+#if defined(__amd64__) || defined(__amd64) || \
+    defined(__x86_64__) || defined(__x86_64) || \
+    defined(_M_X64) || defined(_M_AMD64)
+#if defined(__ILP32__) || defined(_ILP32)
+#define DUK_F_X32
+#else
+#define DUK_F_X64
+#endif
+#elif defined(i386) || defined(__i386) || defined(__i386__) || \
+      defined(__i486__) || defined(__i586__) || defined(__i686__) || \
+      defined(__IA32__) || defined(_M_IX86) || defined(__X86__) || \
+      defined(_X86_) || defined(__THW_INTEL__) || defined(__I86__)
+#if defined(__LP64__) || defined(_LP64)
+/* This should not really happen, but would indicate x64. */
+#define DUK_F_X64
+#else
+#define DUK_F_X86
+#endif
+#endif
+
+/* ARM */
+#if defined(__arm__) || defined(__thumb__) || defined(_ARM) || defined(_M_ARM)
+#define DUK_F_ARM
+#if defined(__LP64__) || defined(_LP64) || defined(__arm64) || defined(__arm64__)
+#define DUK_F_ARM64
+#else
+#define DUK_F_ARM32
+#endif
+#endif
+
+/* MIPS.  Related defines: __MIPSEB__, __MIPSEL__, __mips_isa_rev, __LP64__ */
+#if defined(__mips__) || defined(mips) || defined(_MIPS_ISA) || \
+    defined(_R3000) || defined(_R4000) || defined(_R5900) || \
+    defined(_MIPS_ISA_MIPS1) || defined(_MIPS_ISA_MIPS2) || \
+    defined(_MIPS_ISA_MIPS3) || defined(_MIPS_ISA_MIPS4) || \
+    defined(__mips) || defined(__MIPS__)
+#define DUK_F_MIPS
+#if defined(__LP64__) || defined(_LP64) || defined(__mips64) || \
+    defined(__mips64__) || defined(__mips_n64)
+#define DUK_F_MIPS64
+#else
+#define DUK_F_MIPS32
+#endif
+#endif
+
+/* SPARC */
+#if defined(sparc) || defined(__sparc) || defined(__sparc__)
+#define DUK_F_SPARC
+#if defined(__LP64__) || defined(_LP64)
+#define DUK_F_SPARC64
+#else
+#define DUK_F_SPARC32
+#endif
+#endif
+
+/* SuperH */
+#if defined(__sh__) || \
+    defined(__sh1__) || defined(__SH1__) || \
+    defined(__sh2__) || defined(__SH2__) || \
+    defined(__sh3__) || defined(__SH3__) || \
+    defined(__sh4__) || defined(__SH4__) || \
+    defined(__sh5__) || defined(__SH5__)
+#define DUK_F_SUPERH
+#endif
+
+/* Clang */
+#if defined(__clang__)
+#define DUK_F_CLANG
+#endif
+
+/* C99 or above */
+#undef DUK_F_C99
+#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
+#define DUK_F_C99
+#endif
+
+/* C++11 or above */
+#undef DUK_F_CPP11
+#if defined(__cplusplus) && (__cplusplus >= 201103L)
+#define DUK_F_CPP11
+#endif
+
+/* GCC.  Clang also defines __GNUC__ so don't detect GCC if using Clang. */
+#if defined(__GNUC__) && !defined(__clang__) && !defined(DUK_F_CLANG)
+#define DUK_F_GCC
+#if defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__GNUC_PATCHLEVEL__)
+/* Convenience, e.g. gcc 4.5.1 == 40501; http://stackoverflow.com/questions/6031819/emulating-gccs-builtin-unreachable */
+#define DUK_F_GCC_VERSION  (__GNUC__ * 10000L + __GNUC_MINOR__ * 100L + __GNUC_PATCHLEVEL__)
+#else
+#error cannot figure out gcc version
+#endif
+#endif
+
+/* MinGW.  Also GCC flags (DUK_F_GCC) are enabled now. */
+#if defined(__MINGW32__) || defined(__MINGW64__)
+#define DUK_F_MINGW
+#endif
+
+/* MSVC */
+#if defined(_MSC_VER)
+/* MSVC preprocessor defines: http://msdn.microsoft.com/en-us/library/b0084kay.aspx
+ * _MSC_FULL_VER includes the build number, but it has at least two formats, see e.g.
+ * BOOST_MSVC_FULL_VER in http://www.boost.org/doc/libs/1_52_0/boost/config/compiler/visualc.hpp
+ */
+#define DUK_F_MSVC
+#if defined(_MSC_FULL_VER)
+#if (_MSC_FULL_VER > 100000000)
+#define DUK_F_MSVC_FULL_VER _MSC_FULL_VER
+#else
+#define DUK_F_MSCV_FULL_VER (_MSC_FULL_VER * 10)
+#endif
+#endif
+#endif  /* _MSC_VER */
+
+/* TinyC */
+#if defined(__TINYC__)
+/* http://bellard.org/tcc/tcc-doc.html#SEC9 */
+#define DUK_F_TINYC
+#endif
+
+/* VBCC */
+#if defined(__VBCC__)
+#define DUK_F_VBCC
+#endif
+
+/*
+ *  Platform autodetection
+ */
+
+/* Workaround for older C++ compilers before including <inttypes.h>,
+ * see e.g.: https://sourceware.org/bugzilla/show_bug.cgi?id=15366
+ */
+#if defined(__cplusplus) && !defined(__STDC_LIMIT_MACROS)
+#define __STDC_LIMIT_MACROS
+#endif
+#if defined(__cplusplus) && !defined(__STDC_CONSTANT_MACROS)
+#define __STDC_CONSTANT_MACROS
+#endif
+
+#if defined(DUK_F_APPLE)
+/* --- Mac OSX, iPhone, Darwin --- */
+#define DUK_USE_DATE_NOW_GETTIMEOFDAY
+#define DUK_USE_DATE_TZO_GMTIME_R
+#define DUK_USE_DATE_PRS_STRPTIME
+#define DUK_USE_DATE_FMT_STRFTIME
+#include <TargetConditionals.h>
+#include <architecture/byte_order.h>
+#include <sys/param.h>
+#include <sys/time.h>
+#include <time.h>
+
+/* http://stackoverflow.com/questions/5919996/how-to-detect-reliably-mac-os-x-ios-linux-windows-in-c-preprocessor */
+#if TARGET_IPHONE_SIMULATOR
+#define DUK_USE_OS_STRING "iphone-sim"
+#elif TARGET_OS_IPHONE
+#define DUK_USE_OS_STRING "iphone"
+#elif TARGET_OS_MAC
+#define DUK_USE_OS_STRING "ios"
+#else
+#define DUK_USE_OS_STRING "ios-unknown"
+#endif
+
+/* Use _setjmp() on Apple by default, see GH-55. */
+#define DUK_USE_UNDERSCORE_SETJMP
+#define DUK_SETJMP(jb)        _setjmp((jb))
+#define DUK_LONGJMP(jb)       _longjmp((jb), 1)
+#elif defined(DUK_F_OPENBSD)
+/* --- OpenBSD --- */
+/* http://www.monkey.org/openbsd/archive/ports/0401/msg00089.html */
+#define DUK_USE_DATE_NOW_GETTIMEOFDAY
+#define DUK_USE_DATE_TZO_GMTIME_R
+#define DUK_USE_DATE_PRS_STRPTIME
+#define DUK_USE_DATE_FMT_STRFTIME
+#include <sys/types.h>
+#include <sys/endian.h>
+#include <sys/param.h>
+#include <sys/time.h>
+#include <time.h>
+
+#define DUK_USE_OS_STRING  "openbsd"
+#elif defined(DUK_F_BSD)
+/* --- Generic BSD --- */
+#define DUK_USE_DATE_NOW_GETTIMEOFDAY
+#define DUK_USE_DATE_TZO_GMTIME_R
+#define DUK_USE_DATE_PRS_STRPTIME
+#define DUK_USE_DATE_FMT_STRFTIME
+#include <sys/types.h>
+#include <sys/endian.h>
+#include <sys/param.h>
+#include <sys/time.h>
+#include <time.h>
+
+#define DUK_USE_OS_STRING  "bsd"
+#elif defined(DUK_F_TOS)
+/* --- Atari ST TOS --- */
+#define DUK_USE_DATE_NOW_TIME
+#define DUK_USE_DATE_TZO_GMTIME
+/* no parsing (not an error) */
+#define DUK_USE_DATE_FMT_STRFTIME
+#include <time.h>
+
+#define DUK_USE_OS_STRING  "tos"
+
+/* TOS on M68K is always big endian. */
+#if !defined(DUK_USE_BYTEORDER) && defined(DUK_F_M68K)
+#define DUK_USE_BYTEORDER 3
+#endif
+#elif defined(DUK_F_AMIGAOS)
+/* --- AmigaOS --- */
+#if defined(DUK_F_M68K)
+/* AmigaOS on M68k */
+#define DUK_USE_DATE_NOW_TIME
+#define DUK_USE_DATE_TZO_GMTIME
+/* no parsing (not an error) */
+#define DUK_USE_DATE_FMT_STRFTIME
+#include <time.h>
+#elif defined(DUK_F_PPC)
+#define DUK_USE_DATE_NOW_GETTIMEOFDAY
+#define DUK_USE_DATE_TZO_GMTIME_R
+#define DUK_USE_DATE_PRS_STRPTIME
+#define DUK_USE_DATE_FMT_STRFTIME
+#include <time.h>
+#ifndef UINTPTR_MAX
+#define UINTPTR_MAX UINT_MAX
+#endif
+#else
+#error AmigaOS but not M68K/PPC, not supported now
+#endif
+
+#define DUK_USE_OS_STRING "amigaos"
+
+/* AmigaOS on M68K or PPC is always big endian. */
+#if !defined(DUK_USE_BYTEORDER) && (defined(DUK_F_M68K) || defined(DUK_F_PPC))
+#define DUK_USE_BYTEORDER 3
+#endif
+#elif defined(DUK_F_WINDOWS)
+/* --- Windows --- */
+/* Initial fix: disable secure CRT related warnings when compiling Duktape
+ * itself (must be defined before including Windows headers).  Don't define
+ * for user code including duktape.h.
+ */
+#if defined(DUK_COMPILING_DUKTAPE) && !defined(_CRT_SECURE_NO_WARNINGS)
+#define _CRT_SECURE_NO_WARNINGS
+#endif
+
+/* Windows 32-bit and 64-bit are currently the same. */
+/* MSVC does not have sys/param.h */
+#define DUK_USE_DATE_NOW_WINDOWS
+#define DUK_USE_DATE_TZO_WINDOWS
+/* Note: PRS and FMT are intentionally left undefined for now.  This means
+ * there is no platform specific date parsing/formatting but there is still
+ * the ISO 8601 standard format.
+ */
+#if defined(DUK_COMPILING_DUKTAPE)
+/* Only include when compiling Duktape to avoid polluting application build
+ * with a lot of unnecessary defines.
+ */
+#include <windows.h>
+#endif
+
+#define DUK_USE_OS_STRING "windows"
+
+/* On Windows, assume we're little endian.  Even Itanium which has a
+ * configurable endianness runs little endian in Windows.
+ */
+#if !defined(DUK_USE_BYTEORDER)
+#define DUK_USE_BYTEORDER 1
+#endif
+#elif defined(DUK_F_FLASHPLAYER)
+/* --- Flashplayer (Crossbridge) --- */
+#define DUK_USE_DATE_NOW_GETTIMEOFDAY
+#define DUK_USE_DATE_TZO_GMTIME_R
+#define DUK_USE_DATE_PRS_STRPTIME
+#define DUK_USE_DATE_FMT_STRFTIME
+#include <endian.h>
+#include <sys/param.h>
+#include <sys/time.h>
+#include <time.h>
+
+#define DUK_USE_OS_STRING "flashplayer"
+
+#if !defined(DUK_USE_BYTEORDER) && defined(DUK_F_FLASHPLAYER)
+#define DUK_USE_BYTEORDER 1
+#endif
+#elif defined(DUK_F_QNX)
+/* --- QNX --- */
+#if defined(DUK_F_QNX) && defined(DUK_COMPILING_DUKTAPE)
+/* See: /opt/qnx650/target/qnx6/usr/include/sys/platform.h */
+#define _XOPEN_SOURCE    600
+#define _POSIX_C_SOURCE  200112L
+#endif
+
+#define DUK_USE_DATE_NOW_GETTIMEOFDAY
+#define DUK_USE_DATE_TZO_GMTIME_R
+#define DUK_USE_DATE_PRS_STRPTIME
+#define DUK_USE_DATE_FMT_STRFTIME
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/time.h>
+#include <time.h>
+
+#define DUK_USE_OS_STRING "qnx"
+#elif defined(DUK_F_TINSPIRE)
+/* --- TI-Nspire --- */
+#define DUK_USE_DATE_NOW_GETTIMEOFDAY
+#define DUK_USE_DATE_TZO_GMTIME_R
+#define DUK_USE_DATE_PRS_STRPTIME
+#define DUK_USE_DATE_FMT_STRFTIME
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/time.h>
+#include <time.h>
+
+#define DUK_USE_OS_STRING "tinspire"
+#elif defined(DUK_F_EMSCRIPTEN)
+/* --- Emscripten --- */
+#if defined(DUK_COMPILING_DUKTAPE)
+#ifndef _POSIX_C_SOURCE
+#define _POSIX_C_SOURCE  200809L
+#endif
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE      /* e.g. getdate_r */
+#endif
+#ifndef _XOPEN_SOURCE
+#define _XOPEN_SOURCE    /* e.g. strptime */
+#endif
+#endif  /* DUK_COMPILING_DUKTAPE */
+
+#include <sys/types.h>
+#if defined(DUK_F_BCC)
+/* no endian.h */
+#else
+#include <endian.h>
+#endif  /* DUK_F_BCC */
+#include <sys/param.h>
+#include <sys/time.h>
+#include <time.h>
+#include <stdint.h>
+
+#define DUK_USE_DATE_NOW_GETTIMEOFDAY
+#define DUK_USE_DATE_TZO_GMTIME_R
+#define DUK_USE_DATE_PRS_STRPTIME
+#define DUK_USE_DATE_FMT_STRFTIME
+
+#define DUK_USE_OS_STRING "emscripten"
+#elif defined(DUK_F_LINUX)
+/* --- Linux --- */
+#if defined(DUK_COMPILING_DUKTAPE)
+#ifndef _POSIX_C_SOURCE
+#define _POSIX_C_SOURCE  200809L
+#endif
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE      /* e.g. getdate_r */
+#endif
+#ifndef _XOPEN_SOURCE
+#define _XOPEN_SOURCE    /* e.g. strptime */
+#endif
+#endif  /* DUK_COMPILING_DUKTAPE */
+
+#include <sys/types.h>
+#if defined(DUK_F_BCC)
+/* no endian.h or stdint.h */
+#else
+#include <endian.h>
+#include <stdint.h>
+#endif  /* DUK_F_BCC */
+#include <sys/param.h>
+#include <sys/time.h>
+#include <time.h>
+
+#define DUK_USE_DATE_NOW_GETTIMEOFDAY
+#define DUK_USE_DATE_TZO_GMTIME_R
+#define DUK_USE_DATE_PRS_STRPTIME
+#define DUK_USE_DATE_FMT_STRFTIME
+
+#define DUK_USE_OS_STRING "linux"
+#elif defined(DUK_F_SUN)
+/* --- Solaris --- */
+#define DUK_USE_DATE_NOW_GETTIMEOFDAY
+#define DUK_USE_DATE_TZO_GMTIME_R
+#define DUK_USE_DATE_PRS_STRPTIME
+#define DUK_USE_DATE_FMT_STRFTIME
+
+#include <sys/types.h>
+#include <ast/endian.h>
+#include <sys/param.h>
+#include <sys/time.h>
+#include <time.h>
+
+#define DUK_USE_OS_STRING "solaris"
+#elif defined(DUK_F_POSIX)
+/* --- Generic POSIX --- */
+#define DUK_USE_DATE_NOW_GETTIMEOFDAY
+#define DUK_USE_DATE_TZO_GMTIME_R
+#define DUK_USE_DATE_PRS_STRPTIME
+#define DUK_USE_DATE_FMT_STRFTIME
+#include <sys/types.h>
+#include <endian.h>
+#include <sys/param.h>
+#include <sys/time.h>
+#include <time.h>
+
+#define DUK_USE_OS_STRING "posix"
+#elif defined(DUK_F_CYGWIN)
+/* --- Cygwin --- */
+/* don't use strptime() for now */
+#define DUK_USE_DATE_NOW_GETTIMEOFDAY
+#define DUK_USE_DATE_TZO_GMTIME_R
+#define DUK_USE_DATE_FMT_STRFTIME
+#include <sys/types.h>
+#include <endian.h>
+#include <sys/param.h>
+#include <sys/time.h>
+#include <time.h>
+
+#define DUK_USE_UNDERSCORE_SETJMP
+#define DUK_SETJMP(jb)        _setjmp((jb))
+#define DUK_LONGJMP(jb)       _longjmp((jb), 1)
+
+#define DUK_USE_OS_STRING "windows"
+#elif defined(DUK_F_UNIX)
+/* --- Generic UNIX --- */
+#define DUK_USE_DATE_NOW_GETTIMEOFDAY
+#define DUK_USE_DATE_TZO_GMTIME_R
+#define DUK_USE_DATE_PRS_STRPTIME
+#define DUK_USE_DATE_FMT_STRFTIME
+#include <time.h>
+#include <sys/time.h>
+#define DUK_USE_OS_STRING "unknown"
+#else
+/* --- Generic fallback --- */
+/* The most portable current time provider is time(), but it only has a
+ * one second resolution.
+ */
+#define DUK_USE_DATE_NOW_TIME
+
+/* The most portable way to figure out local time offset is gmtime(),
+ * but it's not thread safe so use with caution.
+ */
+#define DUK_USE_DATE_TZO_GMTIME
+
+/* Avoid custom date parsing and formatting for portability. */
+#undef DUK_USE_DATE_PRS_STRPTIME
+#undef DUK_USE_DATE_FMT_STRFTIME
+
+/* Rely on C89 headers only; time.h must be here. */
+#include <time.h>
+
+#define DUK_USE_OS_STRING "unknown"
+#endif  /* autodetect platform */
+
+/* Shared includes: C89 */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>  /* varargs */
+#include <setjmp.h>
+#include <stddef.h>  /* e.g. ptrdiff_t */
+#include <math.h>
+#include <limits.h>
+
+/* date.h is omitted, and included per platform */
+
+/* Shared includes: stdint.h is C99 */
+#if defined(DUK_F_NO_STDINT_H)
+/* stdint.h not available */
+#else
+/* Technically C99 (C++11) but found in many systems.  On some systems
+ * __STDC_LIMIT_MACROS and __STDC_CONSTANT_MACROS must be defined before
+ * including stdint.h (see above).
+ */
+#include <stdint.h>
+#endif
+
+#if defined(DUK_F_CPP)
+#include <exception>  /* std::exception */
+#endif
+
+/*
+ *  Architecture autodetection
+ */
+
+#if defined(DUK_F_X86)
+/* --- x86 --- */
+#define DUK_USE_ARCH_STRING "x86"
+#if !defined(DUK_USE_BYTEORDER)
+#define DUK_USE_BYTEORDER 1
+#endif
+/* XXX: This is technically not guaranteed because it's possible to configure
+ * an x86 to require aligned accesses with Alignment Check (AC) flag.
+ */
+#if !defined(DUK_USE_ALIGN_BY)
+#define DUK_USE_ALIGN_BY 1
+#endif
+#define DUK_USE_PACKED_TVAL
+#define DUK_F_PACKED_TVAL_PROVIDED
+#elif defined(DUK_F_X64)
+/* --- x64 --- */
+#define DUK_USE_ARCH_STRING "x64"
+#if !defined(DUK_USE_BYTEORDER)
+#define DUK_USE_BYTEORDER 1
+#endif
+/* XXX: This is technically not guaranteed because it's possible to configure
+ * an x86 to require aligned accesses with Alignment Check (AC) flag.
+ */
+#if !defined(DUK_USE_ALIGN_BY)
+#define DUK_USE_ALIGN_BY 1
+#endif
+#undef DUK_USE_PACKED_TVAL
+#define DUK_F_PACKED_TVAL_PROVIDED
+#elif defined(DUK_F_X32)
+/* --- x32 --- */
+#define DUK_USE_ARCH_STRING "x32"
+#if !defined(DUK_USE_BYTEORDER)
+#define DUK_USE_BYTEORDER 1
+#endif
+/* XXX: This is technically not guaranteed because it's possible to configure
+ * an x86 to require aligned accesses with Alignment Check (AC) flag.
+ */
+#if !defined(DUK_USE_ALIGN_BY)
+#define DUK_USE_ALIGN_BY 1
+#endif
+#define DUK_USE_PACKED_TVAL
+#define DUK_F_PACKED_TVAL_PROVIDED
+#elif defined(DUK_F_ARM32)
+/* --- ARM 32-bit --- */
+#define DUK_USE_ARCH_STRING "arm32"
+/* Byte order varies, so rely on autodetect. */
+#if !defined(DUK_USE_ALIGN_BY)
+#define DUK_USE_ALIGN_BY 4
+#endif
+#define DUK_USE_PACKED_TVAL
+#define DUK_F_PACKED_TVAL_PROVIDED
+#elif defined(DUK_F_ARM64)
+/* --- ARM 64-bit --- */
+#define DUK_USE_ARCH_STRING "arm64"
+/* Byte order varies, so rely on autodetect. */
+#if !defined(DUK_USE_ALIGN_BY)
+#define DUK_USE_ALIGN_BY 8
+#endif
+#undef DUK_USE_PACKED_TVAL
+#define DUK_F_PACKED_TVAL_PROVIDED
+#elif defined(DUK_F_MIPS32)
+/* --- MIPS 32-bit --- */
+#define DUK_USE_ARCH_STRING "mips32"
+/* MIPS byte order varies so rely on autodetection. */
+/* Based on 'make checkalign' there are no alignment requirements on
+ * Linux MIPS except for doubles, which need align by 4.  Alignment
+ * requirements vary based on target though.
+ */
+#if !defined(DUK_USE_ALIGN_BY)
+#define DUK_USE_ALIGN_BY 4
+#endif
+#define DUK_USE_PACKED_TVAL
+#define DUK_F_PACKED_TVAL_PROVIDED
+#elif defined(DUK_F_MIPS64)
+/* --- MIPS 64-bit --- */
+#define DUK_USE_ARCH_STRING "mips64"
+/* MIPS byte order varies so rely on autodetection. */
+/* Good default is a bit arbitrary because alignment requirements
+ * depend on target.  See https://github.com/svaarala/duktape/issues/102.
+ */
+#if !defined(DUK_USE_ALIGN_BY)
+#define DUK_USE_ALIGN_BY 8
+#endif
+#undef DUK_USE_PACKED_TVAL
+#define DUK_F_PACKED_TVAL_PROVIDED
+#elif defined(DUK_F_PPC32)
+/* --- PowerPC 32-bit --- */
+#define DUK_USE_ARCH_STRING "ppc32"
+#if !defined(DUK_USE_BYTEORDER)
+#define DUK_USE_BYTEORDER 3
+#endif
+#if !defined(DUK_USE_ALIGN_BY)
+#define DUK_USE_ALIGN_BY 8
+#endif
+#define DUK_USE_PACKED_TVAL
+#define DUK_F_PACKED_TVAL_PROVIDED
+#elif defined(DUK_F_PPC64)
+/* --- PowerPC 64-bit --- */
+#define DUK_USE_ARCH_STRING "ppc64"
+#if !defined(DUK_USE_BYTEORDER)
+#define DUK_USE_BYTEORDER 3
+#endif
+#if !defined(DUK_USE_ALIGN_BY)
+#define DUK_USE_ALIGN_BY 8
+#endif
+#undef DUK_USE_PACKED_TVAL
+#define DUK_F_PACKED_TVAL_PROVIDED
+#elif defined(DUK_F_SPARC32)
+/* --- SPARC 32-bit --- */
+#define DUK_USE_ARCH_STRING "sparc32"
+/* SPARC byte order varies so rely on autodetection. */
+#if !defined(DUK_USE_ALIGN_BY)
+#define DUK_USE_ALIGN_BY 8
+#endif
+#define DUK_USE_PACKED_TVAL
+#define DUK_F_PACKED_TVAL_PROVIDED
+#elif defined(DUK_F_SPARC64)
+/* --- SPARC 64-bit --- */
+#define DUK_USE_ARCH_STRING "sparc64"
+/* SPARC byte order varies so rely on autodetection. */
+#if !defined(DUK_USE_ALIGN_BY)
+#define DUK_USE_ALIGN_BY 8
+#endif
+#undef DUK_USE_PACKED_TVAL
+#define DUK_F_PACKED_TVAL_PROVIDED
+#elif defined(DUK_F_SUPERH)
+/* --- SuperH --- */
+#define DUK_USE_ARCH_STRING "sh"
+/* Byte order varies, rely on autodetection. */
+/* Based on 'make checkalign' there are no alignment requirements on
+ * Linux SH4, but align by 4 is probably a good basic default.
+ */
+#if !defined(DUK_USE_ALIGN_BY)
+#define DUK_USE_ALIGN_BY 4
+#endif
+#define DUK_USE_PACKED_TVAL
+#define DUK_F_PACKED_TVAL_PROVIDED
+#elif defined(DUK_F_M68K)
+/* --- Motorola 68k --- */
+#define DUK_USE_ARCH_STRING "m68k"
+#if !defined(DUK_USE_BYTEORDER)
+#define DUK_USE_BYTEORDER 3
+#endif
+#if !defined(DUK_USE_ALIGN_BY)
+#define DUK_USE_ALIGN_BY 8
+#endif
+#define DUK_USE_PACKED_TVAL
+#define DUK_F_PACKED_TVAL_PROVIDED
+#elif defined(DUK_F_EMSCRIPTEN)
+/* --- Emscripten --- */
+#define DUK_USE_ARCH_STRING "emscripten"
+#if !defined(DUK_USE_BYTEORDER)
+#define DUK_USE_BYTEORDER 1
+#endif
+#if !defined(DUK_USE_ALIGN_BY)
+#define DUK_USE_ALIGN_BY 8
+#endif
+#undef DUK_USE_PACKED_TVAL
+#define DUK_F_PACKED_TVAL_PROVIDED
+#else
+/* --- Generic --- */
+/* These are necessary wild guesses. */
+#define DUK_USE_ARCH_STRING "generic"
+/* Rely on autodetection for byte order, alignment, and packed tval. */
+#endif  /* autodetect architecture */
+
+/*
+ *  Compiler autodetection
+ */
+
+#if defined(DUK_F_CLANG)
+/* --- Clang --- */
+#if defined(DUK_F_C99) || defined(DUK_F_CPP11)
+/* C99 / C++11 and above: rely on va_copy() which is required. */
+#define DUK_VA_COPY(dest,src) va_copy(dest,src)
+#else
+/* Clang: assume we have __va_copy() in non-C99 mode. */
+#define DUK_VA_COPY(dest,src) __va_copy(dest,src)
+#endif
+
+#define DUK_NORETURN(decl)  decl __attribute__((noreturn))
+
+#if defined(__clang__) && defined(__has_builtin)
+#if __has_builtin(__builtin_unreachable)
+#define DUK_UNREACHABLE()  do { __builtin_unreachable(); } while (0)
+#endif
+#endif
+
+#define DUK_USE_BRANCH_HINTS
+#define DUK_LIKELY(x)    __builtin_expect((x), 1)
+#define DUK_UNLIKELY(x)  __builtin_expect((x), 0)
+
+#if defined(DUK_F_C99) || defined(DUK_F_CPP11)
+#define DUK_NOINLINE        __attribute__((noinline))
+#define DUK_INLINE          inline
+#define DUK_ALWAYS_INLINE   inline __attribute__((always_inline))
+#endif
+
+#if defined(DUK_F_DLL_BUILD) && defined(DUK_F_WINDOWS)
+/* MSVC dllexport/dllimport: appropriate __declspec depends on whether we're
+ * compiling Duktape or the application.
+ */
+#if defined(DUK_COMPILING_DUKTAPE)
+#define DUK_EXTERNAL_DECL  extern __declspec(dllexport)
+#define DUK_EXTERNAL       __declspec(dllexport)
+#else
+#define DUK_EXTERNAL_DECL  extern __declspec(dllimport)
+#define DUK_EXTERNAL       should_not_happen
+#endif
+#if defined(DUK_SINGLE_FILE)
+#define DUK_INTERNAL_DECL  static
+#define DUK_INTERNAL       static
+#else
+#define DUK_INTERNAL_DECL  extern
+#define DUK_INTERNAL       /*empty*/
+#endif
+#define DUK_LOCAL_DECL     static
+#define DUK_LOCAL          static
+
+#else
+#define DUK_EXTERNAL_DECL  __attribute__ ((visibility("default"))) extern
+#define DUK_EXTERNAL       __attribute__ ((visibility("default")))
+#if defined(DUK_SINGLE_FILE)
+#define DUK_INTERNAL_DECL  static
+#define DUK_INTERNAL       static
+#else
+#define DUK_INTERNAL_DECL  __attribute__ ((visibility("hidden"))) extern
+#define DUK_INTERNAL       __attribute__ ((visibility("hidden")))
+#endif
+#define DUK_LOCAL_DECL     static
+#define DUK_LOCAL          static
+#endif
+
+#if defined(DUK_F_CPP)
+#define DUK_USE_COMPILER_STRING "clang"
+#else
+#define DUK_USE_COMPILER_STRING "clang"
+#endif
+
+#undef DUK_USE_VARIADIC_MACROS
+#if defined(DUK_F_C99) || defined(DUK_F_CPP11)
+#define DUK_USE_VARIADIC_MACROS
+#endif
+
+#undef DUK_USE_FLEX_C99
+#undef DUK_USE_FLEX_ZEROSIZE
+#undef DUK_USE_FLEX_ONESIZE
+#if defined(DUK_F_C99)
+#define DUK_USE_FLEX_C99
+#else
+#define DUK_USE_FLEX_ZEROSIZE
+#endif
+
+#undef DUK_USE_GCC_PRAGMAS
+#define DUK_USE_PACK_CLANG_ATTR
+#define DUK_F_VARIADIC_MACROS_PROVIDED
+#elif defined(DUK_F_GCC)
+/* --- GCC --- */
+#if defined(DUK_F_C99) || defined(DUK_F_CPP11)
+/* C99 / C++11 and above: rely on va_copy() which is required. */
+#define DUK_VA_COPY(dest,src) va_copy(dest,src)
+#else
+/* GCC: assume we have __va_copy() in non-C99 mode. */
+#define DUK_VA_COPY(dest,src) __va_copy(dest,src)
+#endif
+
+#if defined(DUK_F_GCC_VERSION) && (DUK_F_GCC_VERSION >= 20500L)
+/* since gcc-2.5 */
+#define DUK_NORETURN(decl)  decl __attribute__((noreturn))
+#endif
+
+#if defined(DUK_F_GCC_VERSION) && (DUK_F_GCC_VERSION >= 40500L)
+/* since gcc-4.5 */
+#define DUK_UNREACHABLE()  do { __builtin_unreachable(); } while (0)
+#endif
+
+#define DUK_USE_BRANCH_HINTS
+#if defined(DUK_F_GCC_VERSION) && (DUK_F_GCC_VERSION >= 40500L)
+/* GCC: test not very accurate; enable only in relatively recent builds
+ * because of bugs in gcc-4.4 (http://lists.debian.org/debian-gcc/2010/04/msg00000.html)
+ */
+#define DUK_LIKELY(x)    __builtin_expect((x), 1)
+#define DUK_UNLIKELY(x)  __builtin_expect((x), 0)
+#endif
+
+#if (defined(DUK_F_C99) || defined(DUK_F_CPP11)) && \
+    defined(DUK_F_GCC_VERSION) && (DUK_F_GCC_VERSION >= 30101)
+#define DUK_NOINLINE        __attribute__((noinline))
+#define DUK_INLINE          inline
+#define DUK_ALWAYS_INLINE   inline __attribute__((always_inline))
+#endif
+
+#if defined(DUK_F_DLL_BUILD) && defined(DUK_F_WINDOWS)
+/* MSVC dllexport/dllimport: appropriate __declspec depends on whether we're
+ * compiling Duktape or the application.
+ */
+#if defined(DUK_COMPILING_DUKTAPE)
+#define DUK_EXTERNAL_DECL  extern __declspec(dllexport)
+#define DUK_EXTERNAL       __declspec(dllexport)
+#else
+#define DUK_EXTERNAL_DECL  extern __declspec(dllimport)
+#define DUK_EXTERNAL       should_not_happen
+#endif
+#if defined(DUK_SINGLE_FILE)
+#define DUK_INTERNAL_DECL  static
+#define DUK_INTERNAL       static
+#else
+#define DUK_INTERNAL_DECL  extern
+#define DUK_INTERNAL       /*empty*/
+#endif
+#define DUK_LOCAL_DECL     static
+#define DUK_LOCAL          static
+
+#elif defined(DUK_F_GCC_VERSION) && (DUK_F_GCC_VERSION >= 40000)
+#define DUK_EXTERNAL_DECL  __attribute__ ((visibility("default"))) extern
+#define DUK_EXTERNAL       __attribute__ ((visibility("default")))
+#if defined(DUK_SINGLE_FILE)
+#define DUK_INTERNAL_DECL  static
+#define DUK_INTERNAL       static
+#else
+#define DUK_INTERNAL_DECL  __attribute__ ((visibility("hidden"))) extern
+#define DUK_INTERNAL       __attribute__ ((visibility("hidden")))
+#endif
+#define DUK_LOCAL_DECL     static
+#define DUK_LOCAL          static
+#endif
+
+#if defined(DUK_F_MINGW)
+#if defined(DUK_F_CPP)
+#define DUK_USE_COMPILER_STRING "mingw++"
+#else
+#define DUK_USE_COMPILER_STRING "mingw"
+#endif
+#else
+#if defined(DUK_F_CPP)
+#define DUK_USE_COMPILER_STRING "g++"
+#else
+#define DUK_USE_COMPILER_STRING "gcc"
+#endif
+#endif
+
+#undef DUK_USE_VARIADIC_MACROS
+#if defined(DUK_F_C99) || (defined(DUK_F_CPP11) && defined(__GNUC__))
+#define DUK_USE_VARIADIC_MACROS
+#endif
+
+#undef DUK_USE_FLEX_C99
+#undef DUK_USE_FLEX_ZEROSIZE
+#undef DUK_USE_FLEX_ONESIZE
+#if defined(DUK_F_C99)
+#define DUK_USE_FLEX_C99
+#else
+#define DUK_USE_FLEX_ZEROSIZE
+#endif
+
+#if defined(DUK_F_GCC_VERSION) && (DUK_F_GCC_VERSION >= 40600)
+#define DUK_USE_GCC_PRAGMAS
+#else
+#undef DUK_USE_GCC_PRAGMAS
+#endif
+
+#define DUK_USE_PACK_GCC_ATTR
+#define DUK_F_VARIADIC_MACROS_PROVIDED
+#elif defined(DUK_F_MSVC)
+/* --- MSVC --- */
+/* http://msdn.microsoft.com/en-us/library/aa235362(VS.60).aspx */
+#define DUK_NORETURN(decl)  __declspec(noreturn) decl
+
+/* XXX: DUK_UNREACHABLE for msvc? */
+
+#undef DUK_USE_BRANCH_HINTS
+
+/* XXX: DUK_LIKELY, DUK_UNLIKELY for msvc? */
+/* XXX: DUK_NOINLINE, DUK_INLINE, DUK_ALWAYS_INLINE for msvc? */
+
+#if defined(DUK_F_DLL_BUILD) && defined(DUK_F_WINDOWS)
+/* MSVC dllexport/dllimport: appropriate __declspec depends on whether we're
+ * compiling Duktape or the application.
+ */
+#if defined(DUK_COMPILING_DUKTAPE)
+#define DUK_EXTERNAL_DECL  extern __declspec(dllexport)
+#define DUK_EXTERNAL       __declspec(dllexport)
+#else
+#define DUK_EXTERNAL_DECL  extern __declspec(dllimport)
+#define DUK_EXTERNAL       should_not_happen
+#endif
+#if defined(DUK_SINGLE_FILE)
+#define DUK_INTERNAL_DECL  static
+#define DUK_INTERNAL       static
+#else
+#define DUK_INTERNAL_DECL  extern
+#define DUK_INTERNAL       /*empty*/
+#endif
+#define DUK_LOCAL_DECL     static
+#define DUK_LOCAL          static
+
+#endif
+
+#if defined(DUK_F_CPP)
+#define DUK_USE_COMPILER_STRING "msvc++"
+#else
+#define DUK_USE_COMPILER_STRING "msvc"
+#endif
+
+#undef DUK_USE_VARIADIC_MACROS
+#if defined(DUK_F_C99)
+#define DUK_USE_VARIADIC_MACROS
+#elif defined(_MSC_VER) && (_MSC_VER >= 1400)
+/* VS2005+ should have variadic macros even when they're not C99. */
+#define DUK_USE_VARIADIC_MACROS
+#endif
+
+#undef DUK_USE_FLEX_C99
+#undef DUK_USE_FLEX_ZEROSIZE
+#undef DUK_USE_FLEX_ONESIZE
+#if defined(DUK_F_C99)
+#define DUK_USE_FLEX_C99
+#else
+#define DUK_USE_FLEX_ZEROSIZE
+#endif
+
+#undef DUK_USE_GCC_PRAGMAS
+
+#define DUK_USE_PACK_MSVC_PRAGMA
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1900)
+#define DUK_SNPRINTF     snprintf
+#define DUK_VSNPRINTF    vsnprintf
+#else
+/* (v)snprintf() is missing before MSVC 2015.  Note that _(v)snprintf() does
+ * NOT NUL terminate on truncation, but Duktape code never assumes that.
+ * http://stackoverflow.com/questions/2915672/snprintf-and-visual-studio-2010
+ */
+#define DUK_SNPRINTF     _snprintf
+#define DUK_VSNPRINTF    _vsnprintf
+#endif
+#define DUK_F_VARIADIC_MACROS_PROVIDED
+#elif defined(DUK_F_EMSCRIPTEN)
+/* --- Emscripten --- */
+#define DUK_NORETURN(decl)  decl __attribute__((noreturn))
+
+#if defined(__clang__) && defined(__has_builtin)
+#if __has_builtin(__builtin_unreachable)
+#define DUK_UNREACHABLE()  do { __builtin_unreachable(); } while (0)
+#endif
+#endif
+
+#define DUK_USE_BRANCH_HINTS
+#define DUK_LIKELY(x)    __builtin_expect((x), 1)
+#define DUK_UNLIKELY(x)  __builtin_expect((x), 0)
+
+#if defined(DUK_F_C99) || defined(DUK_F_CPP11)
+#define DUK_NOINLINE        __attribute__((noinline))
+#define DUK_INLINE          inline
+#define DUK_ALWAYS_INLINE   inline __attribute__((always_inline))
+#endif
+
+#define DUK_EXTERNAL_DECL  __attribute__ ((visibility("default"))) extern
+#define DUK_EXTERNAL       __attribute__ ((visibility("default")))
+#if defined(DUK_SINGLE_FILE)
+#define DUK_INTERNAL_DECL  static
+#define DUK_INTERNAL       static
+#else
+#define DUK_INTERNAL_DECL  __attribute__ ((visibility("hidden"))) extern
+#define DUK_INTERNAL       __attribute__ ((visibility("hidden")))
+#endif
+#define DUK_LOCAL_DECL     static
+#define DUK_LOCAL          static
+
+#define DUK_USE_COMPILER_STRING "emscripten"
+
+#undef DUK_USE_VARIADIC_MACROS
+#if defined(DUK_F_C99) || defined(DUK_F_CPP11)
+#define DUK_USE_VARIADIC_MACROS
+#endif
+
+#undef DUK_USE_FLEX_C99
+#undef DUK_USE_FLEX_ZEROSIZE
+#undef DUK_USE_FLEX_ONESIZE
+#if defined(DUK_F_C99)
+#define DUK_USE_FLEX_C99
+#else
+#define DUK_USE_FLEX_ZEROSIZE
+#endif
+
+#undef DUK_USE_GCC_PRAGMAS
+#define DUK_USE_PACK_CLANG_ATTR
+#define DUK_F_VARIADIC_MACROS_PROVIDED
+#elif defined(DUK_F_TINYC)
+/* --- TinyC --- */
+#undef DUK_USE_BRANCH_HINTS
+
+#if defined(DUK_F_CPP)
+#define DUK_USE_COMPILER_STRING "tinyc++"
+#else
+#define DUK_USE_COMPILER_STRING "tinyc"
+#endif
+
+/* http://bellard.org/tcc/tcc-doc.html#SEC7 */
+#define DUK_USE_VARIADIC_MACROS
+
+/* Most portable, wastes space */
+#define DUK_USE_FLEX_ONESIZE
+
+/* Most portable, potentially wastes space */
+#define DUK_USE_PACK_DUMMY_MEMBER
+#define DUK_F_VARIADIC_MACROS_PROVIDED
+#elif defined(DUK_F_VBCC)
+/* --- VBCC --- */
+#undef DUK_USE_BRANCH_HINTS
+
+#if defined(DUK_F_CPP)
+#define DUK_USE_COMPILER_STRING "vbcc-c++"
+#else
+#define DUK_USE_COMPILER_STRING "vbcc"
+#endif
+
+#undef DUK_USE_VARIADIC_MACROS
+#if defined(DUK_F_C99) || defined(DUK_F_CPP11)
+#define DUK_USE_VARIADIC_MACROS
+#endif
+
+#define DUK_USE_FLEX_ZEROSIZE
+#define DUK_USE_PACK_DUMMY_MEMBER
+#define DUK_F_VARIADIC_MACROS_PROVIDED
+#elif defined(DUK_F_BCC)
+/* --- Bruce's C compiler --- */
+#undef DUK_USE_BRANCH_HINTS
+
+#if defined(DUK_F_CPP)
+#define DUK_USE_COMPILER_STRING "bcc++"
+#else
+#define DUK_USE_COMPILER_STRING "bcc"
+#endif
+
+/* XXX */
+#undef DUK_USE_VARIADIC_MACROS
+
+/* Most portable, wastes space */
+#define DUK_USE_FLEX_ONESIZE
+
+/* Most portable, potentially wastes space */
+#define DUK_USE_PACK_DUMMY_MEMBER
+
+/* BCC, assume we're on x86. */
+#if !defined(DUK_USE_BYTEORDER)
+#define DUK_USE_BYTEORDER 1
+#endif
+#define DUK_F_VARIADIC_MACROS_PROVIDED
+#else
+/* --- Generic --- */
+#undef DUK_USE_BRANCH_HINTS
+
+#if defined(DUK_F_CPP)
+#define DUK_USE_COMPILER_STRING "generic-c++"
+#else
+#define DUK_USE_COMPILER_STRING "generic"
+#endif
+
+#undef DUK_USE_VARIADIC_MACROS
+#if defined(DUK_F_C99) || defined(DUK_F_CPP11)
+#define DUK_USE_VARIADIC_MACROS
+#endif
+
+/* Most portable, wastes space */
+#define DUK_USE_FLEX_ONESIZE
+
+/* Most portable, potentially wastes space */
+#define DUK_USE_PACK_DUMMY_MEMBER
+#define DUK_F_VARIADIC_MACROS_PROVIDED
+#endif  /* autodetect compiler */
+
+/* uclibc */
+#if defined(__UCLIBC__)
+#define DUK_F_UCLIBC
+#endif
+
+/*
+ *  Wrapper typedefs and constants for integer types, also sanity check types.
+ *
+ *  C99 typedefs are quite good but not always available, and we want to avoid
+ *  forcibly redefining the C99 typedefs.  So, there are Duktape wrappers for
+ *  all C99 typedefs and Duktape code should only use these typedefs.  Type
+ *  detection when C99 is not supported is best effort and may end up detecting
+ *  some types incorrectly.
+ *
+ *  Pointer sizes are a portability problem: pointers to different types may
+ *  have a different size and function pointers are very difficult to manage
+ *  portably.
+ *
+ *  http://en.wikipedia.org/wiki/C_data_types#Fixed-width_integer_types
+ *
+ *  Note: there's an interesting corner case when trying to define minimum
+ *  signed integer value constants which leads to the current workaround of
+ *  defining e.g. -0x80000000 as (-0x7fffffffL - 1L).  See doc/code-issues.txt
+ *  for a longer discussion.
+ *
+ *  Note: avoid typecasts and computations in macro integer constants as they
+ *  can then no longer be used in macro relational expressions (such as
+ *  #if DUK_SIZE_MAX < 0xffffffffUL).  There is internal code which relies on
+ *  being able to compare DUK_SIZE_MAX against a limit.
+ */
+
+/* XXX: add feature options to force basic types from outside? */
+
+#if !defined(INT_MAX)
+#error INT_MAX not defined
+#endif
+
+/* Check that architecture is two's complement, standard C allows e.g.
+ * INT_MIN to be -2**31+1 (instead of -2**31).
+ */
+#if defined(INT_MAX) && defined(INT_MIN)
+#if INT_MAX != -(INT_MIN + 1)
+#error platform does not seem complement of two
+#endif
+#else
+#error cannot check complement of two
+#endif
+
+/* Pointer size determination based on __WORDSIZE or architecture when
+ * that's not available.
+ */
+#if defined(DUK_F_X86) || defined(DUK_F_X32) || \
+    defined(DUK_F_M68K) || defined(DUK_F_PPC32) || \
+    defined(DUK_F_BCC) || \
+    (defined(__WORDSIZE) && (__WORDSIZE == 32))
+#define DUK_F_32BIT_PTRS
+#elif defined(DUK_F_X64) || \
+      (defined(__WORDSIZE) && (__WORDSIZE == 64))
+#define DUK_F_64BIT_PTRS
+#else
+/* not sure, not needed with C99 anyway */
+#endif
+
+/* Intermediate define for 'have inttypes.h' */
+#undef DUK_F_HAVE_INTTYPES
+#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && \
+    !(defined(DUK_F_AMIGAOS) && defined(DUK_F_VBCC))
+/* vbcc + AmigaOS has C99 but no inttypes.h */
+#define DUK_F_HAVE_INTTYPES
+#elif defined(__cplusplus) && (__cplusplus >= 201103L)
+/* C++11 apparently ratified stdint.h */
+#define DUK_F_HAVE_INTTYPES
+#endif
+
+/* Basic integer typedefs and limits, preferably from inttypes.h, otherwise
+ * through automatic detection.
+ */
+#if defined(DUK_F_HAVE_INTTYPES)
+/* C99 or compatible */
+
+#define DUK_F_HAVE_64BIT
+#include <inttypes.h>
+
+typedef uint8_t duk_uint8_t;
+typedef int8_t duk_int8_t;
+typedef uint16_t duk_uint16_t;
+typedef int16_t duk_int16_t;
+typedef uint32_t duk_uint32_t;
+typedef int32_t duk_int32_t;
+typedef uint64_t duk_uint64_t;
+typedef int64_t duk_int64_t;
+typedef uint_least8_t duk_uint_least8_t;
+typedef int_least8_t duk_int_least8_t;
+typedef uint_least16_t duk_uint_least16_t;
+typedef int_least16_t duk_int_least16_t;
+typedef uint_least32_t duk_uint_least32_t;
+typedef int_least32_t duk_int_least32_t;
+typedef uint_least64_t duk_uint_least64_t;
+typedef int_least64_t duk_int_least64_t;
+typedef uint_fast8_t duk_uint_fast8_t;
+typedef int_fast8_t duk_int_fast8_t;
+typedef uint_fast16_t duk_uint_fast16_t;
+typedef int_fast16_t duk_int_fast16_t;
+typedef uint_fast32_t duk_uint_fast32_t;
+typedef int_fast32_t duk_int_fast32_t;
+typedef uint_fast64_t duk_uint_fast64_t;
+typedef int_fast64_t duk_int_fast64_t;
+typedef uintptr_t duk_uintptr_t;
+typedef intptr_t duk_intptr_t;
+typedef uintmax_t duk_uintmax_t;
+typedef intmax_t duk_intmax_t;
+
+#define DUK_UINT8_MIN         0
+#define DUK_UINT8_MAX         UINT8_MAX
+#define DUK_INT8_MIN          INT8_MIN
+#define DUK_INT8_MAX          INT8_MAX
+#define DUK_UINT_LEAST8_MIN   0
+#define DUK_UINT_LEAST8_MAX   UINT_LEAST8_MAX
+#define DUK_INT_LEAST8_MIN    INT_LEAST8_MIN
+#define DUK_INT_LEAST8_MAX    INT_LEAST8_MAX
+#define DUK_UINT_FAST8_MIN    0
+#define DUK_UINT_FAST8_MAX    UINT_FAST8_MAX
+#define DUK_INT_FAST8_MIN     INT_FAST8_MIN
+#define DUK_INT_FAST8_MAX     INT_FAST8_MAX
+#define DUK_UINT16_MIN        0
+#define DUK_UINT16_MAX        UINT16_MAX
+#define DUK_INT16_MIN         INT16_MIN
+#define DUK_INT16_MAX         INT16_MAX
+#define DUK_UINT_LEAST16_MIN  0
+#define DUK_UINT_LEAST16_MAX  UINT_LEAST16_MAX
+#define DUK_INT_LEAST16_MIN   INT_LEAST16_MIN
+#define DUK_INT_LEAST16_MAX   INT_LEAST16_MAX
+#define DUK_UINT_FAST16_MIN   0
+#define DUK_UINT_FAST16_MAX   UINT_FAST16_MAX
+#define DUK_INT_FAST16_MIN    INT_FAST16_MIN
+#define DUK_INT_FAST16_MAX    INT_FAST16_MAX
+#define DUK_UINT32_MIN        0
+#define DUK_UINT32_MAX        UINT32_MAX
+#define DUK_INT32_MIN         INT32_MIN
+#define DUK_INT32_MAX         INT32_MAX
+#define DUK_UINT_LEAST32_MIN  0
+#define DUK_UINT_LEAST32_MAX  UINT_LEAST32_MAX
+#define DUK_INT_LEAST32_MIN   INT_LEAST32_MIN
+#define DUK_INT_LEAST32_MAX   INT_LEAST32_MAX
+#define DUK_UINT_FAST32_MIN   0
+#define DUK_UINT_FAST32_MAX   UINT_FAST32_MAX
+#define DUK_INT_FAST32_MIN    INT_FAST32_MIN
+#define DUK_INT_FAST32_MAX    INT_FAST32_MAX
+#define DUK_UINT64_MIN        0
+#define DUK_UINT64_MAX        UINT64_MAX
+#define DUK_INT64_MIN         INT64_MIN
+#define DUK_INT64_MAX         INT64_MAX
+#define DUK_UINT_LEAST64_MIN  0
+#define DUK_UINT_LEAST64_MAX  UINT_LEAST64_MAX
+#define DUK_INT_LEAST64_MIN   INT_LEAST64_MIN
+#define DUK_INT_LEAST64_MAX   INT_LEAST64_MAX
+#define DUK_UINT_FAST64_MIN   0
+#define DUK_UINT_FAST64_MAX   UINT_FAST64_MAX
+#define DUK_INT_FAST64_MIN    INT_FAST64_MIN
+#define DUK_INT_FAST64_MAX    INT_FAST64_MAX
+
+#define DUK_UINTPTR_MIN       0
+#define DUK_UINTPTR_MAX       UINTPTR_MAX
+#define DUK_INTPTR_MIN        INTPTR_MIN
+#define DUK_INTPTR_MAX        INTPTR_MAX
+
+#define DUK_UINTMAX_MIN       0
+#define DUK_UINTMAX_MAX       UINTMAX_MAX
+#define DUK_INTMAX_MIN        INTMAX_MIN
+#define DUK_INTMAX_MAX        INTMAX_MAX
+
+#define DUK_SIZE_MIN          0
+#define DUK_SIZE_MAX          SIZE_MAX
+#undef DUK_SIZE_MAX_COMPUTED
+
+#else  /* C99 types */
+
+/* When C99 types are not available, we use heuristic detection to get
+ * the basic 8, 16, 32, and (possibly) 64 bit types.  The fast/least
+ * types are then assumed to be exactly the same for now: these could
+ * be improved per platform but C99 types are very often now available.
+ * 64-bit types are not available on all platforms; this is OK at least
+ * on 32-bit platforms.
+ *
+ * This detection code is necessarily a bit hacky and can provide typedefs
+ * and defines that won't work correctly on some exotic platform.
+ */
+
+#if (defined(CHAR_BIT) && (CHAR_BIT == 8)) || \
+    (defined(UCHAR_MAX) && (UCHAR_MAX == 255))
+typedef unsigned char duk_uint8_t;
+typedef signed char duk_int8_t;
+#else
+#error cannot detect 8-bit type
+#endif
+
+#if defined(USHRT_MAX) && (USHRT_MAX == 65535UL)
+typedef unsigned short duk_uint16_t;
+typedef signed short duk_int16_t;
+#elif defined(UINT_MAX) && (UINT_MAX == 65535UL)
+/* On some platforms int is 16-bit but long is 32-bit (e.g. PureC) */
+typedef unsigned int duk_uint16_t;
+typedef signed int duk_int16_t;
+#else
+#error cannot detect 16-bit type
+#endif
+
+#if defined(UINT_MAX) && (UINT_MAX == 4294967295UL)
+typedef unsigned int duk_uint32_t;
+typedef signed int duk_int32_t;
+#elif defined(ULONG_MAX) && (ULONG_MAX == 4294967295UL)
+/* On some platforms int is 16-bit but long is 32-bit (e.g. PureC) */
+typedef unsigned long duk_uint32_t;
+typedef signed long duk_int32_t;
+#else
+#error cannot detect 32-bit type
+#endif
+
+/* 64-bit type detection is a bit tricky.
+ *
+ * ULLONG_MAX is a standard define.  __LONG_LONG_MAX__ and __ULONG_LONG_MAX__
+ * are used by at least GCC (even if system headers don't provide ULLONG_MAX).
+ * Some GCC variants may provide __LONG_LONG_MAX__ but not __ULONG_LONG_MAX__.
+ *
+ * ULL / LL constants are rejected / warned about by some compilers, even if
+ * the compiler has a 64-bit type and the compiler/system headers provide an
+ * unsupported constant (ULL/LL)!  Try to avoid using ULL / LL constants.
+ * As a side effect we can only check that e.g. ULONG_MAX is larger than 32
+ * bits but can't be sure it is exactly 64 bits.  Self tests will catch such
+ * cases.
+ */
+#undef DUK_F_HAVE_64BIT
+#if !defined(DUK_F_HAVE_64BIT) && defined(ULONG_MAX)
+#if (ULONG_MAX > 4294967295UL)
+#define DUK_F_HAVE_64BIT
+typedef unsigned long duk_uint64_t;
+typedef signed long duk_int64_t;
+#endif
+#endif
+#if !defined(DUK_F_HAVE_64BIT) && defined(ULLONG_MAX)
+#if (ULLONG_MAX > 4294967295UL)
+#define DUK_F_HAVE_64BIT
+typedef unsigned long long duk_uint64_t;
+typedef signed long long duk_int64_t;
+#endif
+#endif
+#if !defined(DUK_F_HAVE_64BIT) && defined(__ULONG_LONG_MAX__)
+#if (__ULONG_LONG_MAX__ > 4294967295UL)
+#define DUK_F_HAVE_64BIT
+typedef unsigned long long duk_uint64_t;
+typedef signed long long duk_int64_t;
+#endif
+#endif
+#if !defined(DUK_F_HAVE_64BIT) && defined(__LONG_LONG_MAX__)
+#if (__LONG_LONG_MAX__ > 2147483647L)
+#define DUK_F_HAVE_64BIT
+typedef unsigned long long duk_uint64_t;
+typedef signed long long duk_int64_t;
+#endif
+#endif
+#if !defined(DUK_F_HAVE_64BIT) && \
+    (defined(DUK_F_MINGW) || defined(DUK_F_MSVC))
+/* Both MinGW and MSVC have a 64-bit type. */
+#define DUK_F_HAVE_64BIT
+typedef unsigned long duk_uint64_t;
+typedef signed long duk_int64_t;
+#endif
+#if !defined(DUK_F_HAVE_64BIT)
+/* cannot detect 64-bit type, not always needed so don't error */
+#endif
+
+typedef duk_uint8_t duk_uint_least8_t;
+typedef duk_int8_t duk_int_least8_t;
+typedef duk_uint16_t duk_uint_least16_t;
+typedef duk_int16_t duk_int_least16_t;
+typedef duk_uint32_t duk_uint_least32_t;
+typedef duk_int32_t duk_int_least32_t;
+typedef duk_uint8_t duk_uint_fast8_t;
+typedef duk_int8_t duk_int_fast8_t;
+typedef duk_uint16_t duk_uint_fast16_t;
+typedef duk_int16_t duk_int_fast16_t;
+typedef duk_uint32_t duk_uint_fast32_t;
+typedef duk_int32_t duk_int_fast32_t;
+#if defined(DUK_F_HAVE_64BIT)
+typedef duk_uint64_t duk_uint_least64_t;
+typedef duk_int64_t duk_int_least64_t;
+typedef duk_uint64_t duk_uint_fast64_t;
+typedef duk_int64_t duk_int_fast64_t;
+#endif
+#if defined(DUK_F_HAVE_64BIT)
+typedef duk_uint64_t duk_uintmax_t;
+typedef duk_int64_t duk_intmax_t;
+#else
+typedef duk_uint32_t duk_uintmax_t;
+typedef duk_int32_t duk_intmax_t;
+#endif
+
+/* Note: the funny looking computations for signed minimum 16-bit, 32-bit, and
+ * 64-bit values are intentional as the obvious forms (e.g. -0x80000000L) are
+ * -not- portable.  See code-issues.txt for a detailed discussion.
+ */
+#define DUK_UINT8_MIN         0UL
+#define DUK_UINT8_MAX         0xffUL
+#define DUK_INT8_MIN          (-0x80L)
+#define DUK_INT8_MAX          0x7fL
+#define DUK_UINT_LEAST8_MIN   0UL
+#define DUK_UINT_LEAST8_MAX   0xffUL
+#define DUK_INT_LEAST8_MIN    (-0x80L)
+#define DUK_INT_LEAST8_MAX    0x7fL
+#define DUK_UINT_FAST8_MIN    0UL
+#define DUK_UINT_FAST8_MAX    0xffUL
+#define DUK_INT_FAST8_MIN     (-0x80L)
+#define DUK_INT_FAST8_MAX     0x7fL
+#define DUK_UINT16_MIN        0UL
+#define DUK_UINT16_MAX        0xffffUL
+#define DUK_INT16_MIN         (-0x7fffL - 1L)
+#define DUK_INT16_MAX         0x7fffL
+#define DUK_UINT_LEAST16_MIN  0UL
+#define DUK_UINT_LEAST16_MAX  0xffffUL
+#define DUK_INT_LEAST16_MIN   (-0x7fffL - 1L)
+#define DUK_INT_LEAST16_MAX   0x7fffL
+#define DUK_UINT_FAST16_MIN   0UL
+#define DUK_UINT_FAST16_MAX   0xffffUL
+#define DUK_INT_FAST16_MIN    (-0x7fffL - 1L)
+#define DUK_INT_FAST16_MAX    0x7fffL
+#define DUK_UINT32_MIN        0UL
+#define DUK_UINT32_MAX        0xffffffffUL
+#define DUK_INT32_MIN         (-0x7fffffffL - 1L)
+#define DUK_INT32_MAX         0x7fffffffL
+#define DUK_UINT_LEAST32_MIN  0UL
+#define DUK_UINT_LEAST32_MAX  0xffffffffUL
+#define DUK_INT_LEAST32_MIN   (-0x7fffffffL - 1L)
+#define DUK_INT_LEAST32_MAX   0x7fffffffL
+#define DUK_UINT_FAST32_MIN   0UL
+#define DUK_UINT_FAST32_MAX   0xffffffffUL
+#define DUK_INT_FAST32_MIN    (-0x7fffffffL - 1L)
+#define DUK_INT_FAST32_MAX    0x7fffffffL
+
+/* 64-bit constants.  Since LL / ULL constants are not always available,
+ * use computed values.  These values can't be used in preprocessor
+ * comparisons; flag them as such.
+ */
+#if defined(DUK_F_HAVE_64BIT)
+#define DUK_UINT64_MIN        ((duk_uint64_t) 0)
+#define DUK_UINT64_MAX        ((duk_uint64_t) -1)
+#define DUK_INT64_MIN         ((duk_int64_t) (~(DUK_UINT64_MAX >> 1)))
+#define DUK_INT64_MAX         ((duk_int64_t) (DUK_UINT64_MAX >> 1))
+#define DUK_UINT_LEAST64_MIN  DUK_UINT64_MIN
+#define DUK_UINT_LEAST64_MAX  DUK_UINT64_MAX
+#define DUK_INT_LEAST64_MIN   DUK_INT64_MIN
+#define DUK_INT_LEAST64_MAX   DUK_INT64_MAX
+#define DUK_UINT_FAST64_MIN   DUK_UINT64_MIN
+#define DUK_UINT_FAST64_MAX   DUK_UINT64_MAX
+#define DUK_INT_FAST64_MIN    DUK_INT64_MIN
+#define DUK_INT_FAST64_MAX    DUK_INT64_MAX
+#define DUK_UINT64_MIN_COMPUTED
+#define DUK_UINT64_MAX_COMPUTED
+#define DUK_INT64_MIN_COMPUTED
+#define DUK_INT64_MAX_COMPUTED
+#define DUK_UINT_LEAST64_MIN_COMPUTED
+#define DUK_UINT_LEAST64_MAX_COMPUTED
+#define DUK_INT_LEAST64_MIN_COMPUTED
+#define DUK_INT_LEAST64_MAX_COMPUTED
+#define DUK_UINT_FAST64_MIN_COMPUTED
+#define DUK_UINT_FAST64_MAX_COMPUTED
+#define DUK_INT_FAST64_MIN_COMPUTED
+#define DUK_INT_FAST64_MAX_COMPUTED
+#endif
+
+#if defined(DUK_F_HAVE_64BIT)
+#define DUK_UINTMAX_MIN       DUK_UINT64_MIN
+#define DUK_UINTMAX_MAX       DUK_UINT64_MAX
+#define DUK_INTMAX_MIN        DUK_INT64_MIN
+#define DUK_INTMAX_MAX        DUK_INT64_MAX
+#define DUK_UINTMAX_MIN_COMPUTED
+#define DUK_UINTMAX_MAX_COMPUTED
+#define DUK_INTMAX_MIN_COMPUTED
+#define DUK_INTMAX_MAX_COMPUTED
+#else
+#define DUK_UINTMAX_MIN       0UL
+#define DUK_UINTMAX_MAX       0xffffffffUL
+#define DUK_INTMAX_MIN        (-0x7fffffffL - 1L)
+#define DUK_INTMAX_MAX        0x7fffffffL
+#endif
+
+/* This detection is not very reliable. */
+#if defined(DUK_F_32BIT_PTRS)
+typedef duk_int32_t duk_intptr_t;
+typedef duk_uint32_t duk_uintptr_t;
+#define DUK_UINTPTR_MIN       DUK_UINT32_MIN
+#define DUK_UINTPTR_MAX       DUK_UINT32_MAX
+#define DUK_INTPTR_MIN        DUK_INT32_MIN
+#define DUK_INTPTR_MAX        DUK_INT32_MAX
+#elif defined(DUK_F_64BIT_PTRS) && defined(DUK_F_HAVE_64BIT)
+typedef duk_int64_t duk_intptr_t;
+typedef duk_uint64_t duk_uintptr_t;
+#define DUK_UINTPTR_MIN       DUK_UINT64_MIN
+#define DUK_UINTPTR_MAX       DUK_UINT64_MAX
+#define DUK_INTPTR_MIN        DUK_INT64_MIN
+#define DUK_INTPTR_MAX        DUK_INT64_MAX
+#define DUK_UINTPTR_MIN_COMPUTED
+#define DUK_UINTPTR_MAX_COMPUTED
+#define DUK_INTPTR_MIN_COMPUTED
+#define DUK_INTPTR_MAX_COMPUTED
+#else
+#error cannot determine intptr type
+#endif
+
+/* SIZE_MAX may be missing so use an approximate value for it. */
+#undef DUK_SIZE_MAX_COMPUTED
+#if !defined(SIZE_MAX)
+#define DUK_SIZE_MAX_COMPUTED
+#define SIZE_MAX              ((size_t) (-1))
+#endif
+#define DUK_SIZE_MIN          0
+#define DUK_SIZE_MAX          SIZE_MAX
+
+#endif  /* C99 types */
+
+/* A few types are assumed to always exist. */
+typedef size_t duk_size_t;
+typedef ptrdiff_t duk_ptrdiff_t;
+
+/* The best type for an "all around int" in Duktape internals is "at least
+ * 32 bit signed integer" which is most convenient.  Same for unsigned type.
+ * Prefer 'int' when large enough, as it is almost always a convenient type.
+ */
+#if defined(UINT_MAX) && (UINT_MAX >= 0xffffffffUL)
+typedef int duk_int_t;
+typedef unsigned int duk_uint_t;
+#define DUK_INT_MIN           INT_MIN
+#define DUK_INT_MAX           INT_MAX
+#define DUK_UINT_MIN          0
+#define DUK_UINT_MAX          UINT_MAX
+#else
+typedef duk_int_fast32_t duk_int_t;
+typedef duk_uint_fast32_t duk_uint_t;
+#define DUK_INT_MIN           DUK_INT_FAST32_MIN
+#define DUK_INT_MAX           DUK_INT_FAST32_MAX
+#define DUK_UINT_MIN          DUK_UINT_FAST32_MIN
+#define DUK_UINT_MAX          DUK_UINT_FAST32_MAX
+#endif
+
+/* Same as 'duk_int_t' but guaranteed to be a 'fast' variant if this
+ * distinction matters for the CPU.  These types are used mainly in the
+ * executor where it might really matter.
+ */
+typedef duk_int_fast32_t duk_int_fast_t;
+typedef duk_uint_fast32_t duk_uint_fast_t;
+#define DUK_INT_FAST_MIN      DUK_INT_FAST32_MIN
+#define DUK_INT_FAST_MAX      DUK_INT_FAST32_MAX
+#define DUK_UINT_FAST_MIN     DUK_UINT_FAST32_MIN
+#define DUK_UINT_FAST_MAX     DUK_UINT_FAST32_MAX
+
+/* Small integers (16 bits or more) can fall back to the 'int' type, but
+ * have a typedef so they are marked "small" explicitly.
+ */
+typedef int duk_small_int_t;
+typedef unsigned int duk_small_uint_t;
+#define DUK_SMALL_INT_MIN     INT_MIN
+#define DUK_SMALL_INT_MAX     INT_MAX
+#define DUK_SMALL_UINT_MIN    0
+#define DUK_SMALL_UINT_MAX    UINT_MAX
+
+/* Fast variants of small integers, again for really fast paths like the
+ * executor.
+ */
+typedef duk_int_fast16_t duk_small_int_fast_t;
+typedef duk_uint_fast16_t duk_small_uint_fast_t;
+#define DUK_SMALL_INT_FAST_MIN    DUK_INT_FAST16_MIN
+#define DUK_SMALL_INT_FAST_MAX    DUK_INT_FAST16_MAX
+#define DUK_SMALL_UINT_FAST_MIN   DUK_UINT_FAST16_MIN
+#define DUK_SMALL_UINT_FAST_MAX   DUK_UINT_FAST16_MAX
+
+/* Boolean values are represented with the platform 'int'. */
+typedef duk_small_int_t duk_bool_t;
+#define DUK_BOOL_MIN              DUK_SMALL_INT_MIN
+#define DUK_BOOL_MAX              DUK_SMALL_INT_MAX
+
+/* Index values must have at least 32-bit signed range. */
+typedef duk_int_t duk_idx_t;
+#define DUK_IDX_MIN               DUK_INT_MIN
+#define DUK_IDX_MAX               DUK_INT_MAX
+
+/* Unsigned index variant. */
+typedef duk_uint_t duk_uidx_t;
+#define DUK_UIDX_MIN              DUK_UINT_MIN
+#define DUK_UIDX_MAX              DUK_UINT_MAX
+
+/* Array index values, could be exact 32 bits.
+ * Currently no need for signed duk_arridx_t.
+ */
+typedef duk_uint_t duk_uarridx_t;
+#define DUK_UARRIDX_MIN           DUK_UINT_MIN
+#define DUK_UARRIDX_MAX           DUK_UINT_MAX
+
+/* Duktape/C function return value, platform int is enough for now to
+ * represent 0, 1, or negative error code.  Must be compatible with
+ * assigning truth values (e.g. duk_ret_t rc = (foo == bar);).
+ */
+typedef duk_small_int_t duk_ret_t;
+#define DUK_RET_MIN               DUK_SMALL_INT_MIN
+#define DUK_RET_MAX               DUK_SMALL_INT_MAX
+
+/* Error codes are represented with platform int.  High bits are used
+ * for flags and such, so 32 bits are needed.
+ */
+typedef duk_int_t duk_errcode_t;
+#define DUK_ERRCODE_MIN           DUK_INT_MIN
+#define DUK_ERRCODE_MAX           DUK_INT_MAX
+
+/* Codepoint type.  Must be 32 bits or more because it is used also for
+ * internal codepoints.  The type is signed because negative codepoints
+ * are used as internal markers (e.g. to mark EOF or missing argument).
+ * (X)UTF-8/CESU-8 encode/decode take and return an unsigned variant to
+ * ensure duk_uint32_t casts back and forth nicely.  Almost everything
+ * else uses the signed one.
+ */
+typedef duk_int_t duk_codepoint_t;
+typedef duk_uint_t duk_ucodepoint_t;
+#define DUK_CODEPOINT_MIN         DUK_INT_MIN
+#define DUK_CODEPOINT_MAX         DUK_INT_MAX
+#define DUK_UCODEPOINT_MIN        DUK_UINT_MIN
+#define DUK_UCODEPOINT_MAX        DUK_UINT_MAX
+
+/* IEEE float/double typedef. */
+typedef float duk_float_t;
+typedef double duk_double_t;
+
+/* We're generally assuming that we're working on a platform with a 32-bit
+ * address space.  If DUK_SIZE_MAX is a typecast value (which is necessary
+ * if SIZE_MAX is missing), the check must be avoided because the
+ * preprocessor can't do a comparison.
+ */
+#if !defined(DUK_SIZE_MAX)
+#error DUK_SIZE_MAX is undefined, probably missing SIZE_MAX
+#elif !defined(DUK_SIZE_MAX_COMPUTED)
+#if DUK_SIZE_MAX < 0xffffffffUL
+/* On some systems SIZE_MAX can be smaller than max unsigned 32-bit value
+ * which seems incorrect if size_t is (at least) an unsigned 32-bit type.
+ * However, it doesn't seem useful to error out compilation if this is the
+ * case.
+ */
+#endif
+#endif
+
+/* Type for public API calls. */
+typedef struct duk_hthread duk_context;
+
+/* Check whether we should use 64-bit integers or not.
+ *
+ * Quite incomplete now.  Use 64-bit types if detected (C99 or other detection)
+ * unless they are known to be unreliable.  For instance, 64-bit types are
+ * available on VBCC but seem to misbehave.
+ */
+#if defined(DUK_F_HAVE_64BIT) && !defined(DUK_F_VBCC)
+#define DUK_USE_64BIT_OPS
+#else
+#undef DUK_USE_64BIT_OPS
+#endif
+
+/*
+ *  Fill-ins for platform, architecture, and compiler
+ */
+
+#if !defined(DUK_SETJMP)
+#define DUK_USE_SETJMP
+#define DUK_SETJMP(jb)        setjmp((jb))
+#define DUK_LONGJMP(jb)       longjmp((jb), 1)
+#endif
+
+typedef FILE duk_file;
+#if !defined(DUK_STDIN)
+#define DUK_STDIN       stdin
+#endif
+#if !defined(DUK_STDOUT)
+#define DUK_STDOUT      stdout
+#endif
+#if !defined(DUK_STDERR)
+#define DUK_STDERR      stderr
+#endif
+
+/* Special naming to avoid conflict with e.g. DUK_FREE() in duk_heap.h
+ * (which is unfortunately named).  May sometimes need replacement, e.g.
+ * some compilers don't handle zero length or NULL correctly in realloc().
+ */
+#if !defined(DUK_ANSI_MALLOC)
+#define DUK_ANSI_MALLOC      malloc
+#endif
+#if !defined(DUK_ANSI_REALLOC)
+#define DUK_ANSI_REALLOC     realloc
+#endif
+#if !defined(DUK_ANSI_CALLOC)
+#define DUK_ANSI_CALLOC      calloc
+#endif
+#if !defined(DUK_ANSI_FREE)
+#define DUK_ANSI_FREE        free
+#endif
+
+/* ANSI C (various versions) and some implementations require that the
+ * pointer arguments to memset(), memcpy(), and memmove() be valid values
+ * even when byte size is 0 (even a NULL pointer is considered invalid in
+ * this context).  Zero-size operations as such are allowed, as long as their
+ * pointer arguments point to a valid memory area.  The DUK_MEMSET(),
+ * DUK_MEMCPY(), and DUK_MEMMOVE() macros require this same behavior, i.e.:
+ * (1) pointers must be valid and non-NULL, (2) zero size must otherwise be
+ * allowed.  If these are not fulfilled, a macro wrapper is needed.
+ *
+ *   http://stackoverflow.com/questions/5243012/is-it-guaranteed-to-be-safe-to-perform-memcpy0-0-0
+ *   http://lists.cs.uiuc.edu/pipermail/llvmdev/2007-October/011065.html
+ *
+ * Not sure what's the required behavior when a pointer points just past the
+ * end of a buffer, which often happens in practice (e.g. zero size memmoves).
+ * For example, if allocation size is 3, the following pointer would not
+ * technically point to a valid memory byte:
+ *
+ *   <-- alloc -->
+ *   | 0 | 1 | 2 | .....
+ *                 ^-- p=3, points after last valid byte (2)
+ */
+#if !defined(DUK_MEMCPY)
+#if defined(DUK_F_UCLIBC)
+/* Old uclibcs have a broken memcpy so use memmove instead (this is overly wide
+ * now on purpose): http://lists.uclibc.org/pipermail/uclibc-cvs/2008-October/025511.html
+ */
+#define DUK_MEMCPY       memmove
+#else
+#define DUK_MEMCPY       memcpy
+#endif
+#endif
+#if !defined(DUK_MEMMOVE)
+#define DUK_MEMMOVE      memmove
+#endif
+#if !defined(DUK_MEMCMP)
+#define DUK_MEMCMP       memcmp
+#endif
+#if !defined(DUK_MEMSET)
+#define DUK_MEMSET       memset
+#endif
+#if !defined(DUK_STRLEN)
+#define DUK_STRLEN       strlen
+#endif
+#if !defined(DUK_STRCMP)
+#define DUK_STRCMP       strcmp
+#endif
+#if !defined(DUK_STRNCMP)
+#define DUK_STRNCMP      strncmp
+#endif
+#if !defined(DUK_PRINTF)
+#define DUK_PRINTF       printf
+#endif
+#if !defined(DUK_FPRINTF)
+#define DUK_FPRINTF      fprintf
+#endif
+#if !defined(DUK_SPRINTF)
+#define DUK_SPRINTF      sprintf
+#endif
+#if !defined(DUK_SNPRINTF)
+/* snprintf() is technically not part of C89 but usually available. */
+#define DUK_SNPRINTF     snprintf
+#endif
+#if !defined(DUK_VSPRINTF)
+#define DUK_VSPRINTF     vsprintf
+#endif
+#if !defined(DUK_VSNPRINTF)
+/* vsnprintf() is technically not part of C89 but usually available. */
+#define DUK_VSNPRINTF    vsnprintf
+#endif
+#if !defined(DUK_SSCANF)
+#define DUK_SSCANF       sscanf
+#endif
+#if !defined(DUK_VSSCANF)
+#define DUK_VSSCANF      vsscanf
+#endif
+#if !defined(DUK_FOPEN)
+#define DUK_FOPEN        fopen
+#endif
+#if !defined(DUK_FCLOSE)
+#define DUK_FCLOSE       fclose
+#endif
+#if !defined(DUK_FREAD)
+#define DUK_FREAD        fread
+#endif
+#if !defined(DUK_FWRITE)
+#define DUK_FWRITE       fwrite
+#endif
+#if !defined(DUK_FSEEK)
+#define DUK_FSEEK        fseek
+#endif
+#if !defined(DUK_FTELL)
+#define DUK_FTELL        ftell
+#endif
+#if !defined(DUK_FFLUSH)
+#define DUK_FFLUSH       fflush
+#endif
+#if !defined(DUK_FPUTC)
+#define DUK_FPUTC        fputc
+#endif
+#if !defined(DUK_MEMZERO)
+#define DUK_MEMZERO(p,n) DUK_MEMSET((p), 0, (n))
+#endif
+#if !defined(DUK_ABORT)
+#define DUK_ABORT        abort
+#endif
+#if !defined(DUK_EXIT)
+#define DUK_EXIT         exit
+#endif
+
+#if !defined(DUK_DOUBLE_2TO32)
+#define DUK_DOUBLE_2TO32     4294967296.0
+#endif
+#if !defined(DUK_DOUBLE_2TO31)
+#define DUK_DOUBLE_2TO31     2147483648.0
+#endif
+
+#if !defined(DUK_DOUBLE_INFINITY)
+#undef DUK_USE_COMPUTED_INFINITY
+#if defined(DUK_F_GCC_VERSION) && (DUK_F_GCC_VERSION < 40600)
+/* GCC older than 4.6: avoid overflow warnings related to using INFINITY */
+#define DUK_DOUBLE_INFINITY  (__builtin_inf())
+#elif defined(INFINITY)
+#define DUK_DOUBLE_INFINITY  ((double) INFINITY)
+#elif !defined(DUK_F_VBCC) && !defined(DUK_F_MSVC) && !defined(DUK_F_BCC)
+#define DUK_DOUBLE_INFINITY  (1.0 / 0.0)
+#else
+/* In VBCC (1.0 / 0.0) results in a warning and 0.0 instead of infinity.
+ * Use a computed infinity (initialized when a heap is created at the
+ * latest).
+ */
+#define DUK_USE_COMPUTED_INFINITY
+#define DUK_DOUBLE_INFINITY  duk_computed_infinity
+#endif
+#endif
+
+#if !defined(DUK_DOUBLE_NAN)
+#undef DUK_USE_COMPUTED_NAN
+#if defined(NAN)
+#define DUK_DOUBLE_NAN       NAN
+#elif !defined(DUK_F_VBCC) && !defined(DUK_F_MSVC) && !defined(DUK_F_BCC)
+#define DUK_DOUBLE_NAN       (0.0 / 0.0)
+#else
+/* In VBCC (0.0 / 0.0) results in a warning and 0.0 instead of NaN.
+ * In MSVC (VS2010 Express) (0.0 / 0.0) results in a compile error.
+ * Use a computed NaN (initialized when a heap is created at the
+ * latest).
+ */
+#define DUK_USE_COMPUTED_NAN
+#define DUK_DOUBLE_NAN       duk_computed_nan
+#endif
+#endif
+
+/* Many platforms are missing fpclassify() and friends, so use replacements
+ * if necessary.  The replacement constants (FP_NAN etc) can be anything but
+ * match Linux constants now.
+ */
+#undef DUK_USE_REPL_FPCLASSIFY
+#undef DUK_USE_REPL_SIGNBIT
+#undef DUK_USE_REPL_ISFINITE
+#undef DUK_USE_REPL_ISNAN
+#undef DUK_USE_REPL_ISINF
+
+/* Complex condition broken into separate parts. */
+#undef DUK_F_USE_REPL_ALL
+#if !(defined(FP_NAN) && defined(FP_INFINITE) && defined(FP_ZERO) && \
+      defined(FP_SUBNORMAL) && defined(FP_NORMAL))
+/* Missing some obvious constants. */
+#define DUK_F_USE_REPL_ALL
+#elif defined(DUK_F_AMIGAOS) && defined(DUK_F_VBCC)
+/* VBCC is missing the built-ins even in C99 mode (perhaps a header issue) */
+#define DUK_F_USE_REPL_ALL
+#elif defined(DUK_F_FREEBSD) && defined(DUK_F_CLANG)
+/* Placeholder fix for (detection is wider than necessary):
+ * http://llvm.org/bugs/show_bug.cgi?id=17788
+ */
+#define DUK_F_USE_REPL_ALL
+#elif defined(DUK_F_UCLIBC)
+/* At least some uclibc versions have broken floating point math.  For
+ * example, fpclassify() can incorrectly classify certain NaN formats.
+ * To be safe, use replacements.
+ */
+#define DUK_F_USE_REPL_ALL
+#endif
+
+#if defined(DUK_F_USE_REPL_ALL)
+#define DUK_USE_REPL_FPCLASSIFY
+#define DUK_USE_REPL_SIGNBIT
+#define DUK_USE_REPL_ISFINITE
+#define DUK_USE_REPL_ISNAN
+#define DUK_USE_REPL_ISINF
+#define DUK_FPCLASSIFY       duk_repl_fpclassify
+#define DUK_SIGNBIT          duk_repl_signbit
+#define DUK_ISFINITE         duk_repl_isfinite
+#define DUK_ISNAN            duk_repl_isnan
+#define DUK_ISINF            duk_repl_isinf
+#define DUK_FP_NAN           0
+#define DUK_FP_INFINITE      1
+#define DUK_FP_ZERO          2
+#define DUK_FP_SUBNORMAL     3
+#define DUK_FP_NORMAL        4
+#else
+#define DUK_FPCLASSIFY       fpclassify
+#define DUK_SIGNBIT          signbit
+#define DUK_ISFINITE         isfinite
+#define DUK_ISNAN            isnan
+#define DUK_ISINF            isinf
+#define DUK_FP_NAN           FP_NAN
+#define DUK_FP_INFINITE      FP_INFINITE
+#define DUK_FP_ZERO          FP_ZERO
+#define DUK_FP_SUBNORMAL     FP_SUBNORMAL
+#define DUK_FP_NORMAL        FP_NORMAL
+#endif
+
+#if defined(DUK_F_USE_REPL_ALL)
+#undef DUK_F_USE_REPL_ALL
+#endif
+
+/* Some math functions are C99 only.  This is also an issue with some
+ * embedded environments using uclibc where uclibc has been configured
+ * not to provide some functions.  For now, use replacements whenever
+ * using uclibc.
+ */
+#undef DUK_USE_MATH_FMIN
+#undef DUK_USE_MATH_FMAX
+#undef DUK_USE_MATH_ROUND
+#if defined(DUK_F_UCLIBC)
+/* uclibc may be missing these */
+#elif defined(DUK_F_AMIGAOS) && defined(DUK_F_VBCC)
+/* vbcc + AmigaOS may be missing these */
+#elif !defined(DUK_F_C99) && !defined(DUK_F_CPP11)
+/* build is not C99 or C++11, play it safe */
+#else
+/* C99 or C++11, no known issues */
+#define DUK_USE_MATH_FMIN
+#define DUK_USE_MATH_FMAX
+#define DUK_USE_MATH_ROUND
+#endif
+
+/* These functions don't currently need replacement but are wrapped for
+ * completeness.  Because these are used as function pointers, they need
+ * to be defined as concrete C functions (not macros).
+ */
+#if !defined(DUK_FABS)
+#define DUK_FABS             fabs
+#endif
+#if !defined(DUK_FMIN)
+#define DUK_FMIN             fmin
+#endif
+#if !defined(DUK_FMAX)
+#define DUK_FMAX             fmax
+#endif
+#if !defined(DUK_FLOOR)
+#define DUK_FLOOR            floor
+#endif
+#if !defined(DUK_CEIL)
+#define DUK_CEIL             ceil
+#endif
+#if !defined(DUK_FMOD)
+#define DUK_FMOD             fmod
+#endif
+#if !defined(DUK_POW)
+#define DUK_POW              pow
+#endif
+#if !defined(DUK_ACOS)
+#define DUK_ACOS             acos
+#endif
+#if !defined(DUK_ASIN)
+#define DUK_ASIN             asin
+#endif
+#if !defined(DUK_ATAN)
+#define DUK_ATAN             atan
+#endif
+#if !defined(DUK_ATAN2)
+#define DUK_ATAN2            atan2
+#endif
+#if !defined(DUK_SIN)
+#define DUK_SIN              sin
+#endif
+#if !defined(DUK_COS)
+#define DUK_COS              cos
+#endif
+#if !defined(DUK_TAN)
+#define DUK_TAN              tan
+#endif
+#if !defined(DUK_EXP)
+#define DUK_EXP              exp
+#endif
+#if !defined(DUK_LOG)
+#define DUK_LOG              log
+#endif
+#if !defined(DUK_SQRT)
+#define DUK_SQRT             sqrt
+#endif
+
+/* NetBSD 6.0 x86 (at least) has a few problems with pow() semantics,
+ * see test-bug-netbsd-math-pow.js.  Use NetBSD specific workaround.
+ * (This might be a wider problem; if so, generalize the define name.)
+ */
+#undef DUK_USE_POW_NETBSD_WORKAROUND
+#if defined(DUK_F_NETBSD)
+#define DUK_USE_POW_NETBSD_WORKAROUND
+#endif
+
+/* Rely as little as possible on compiler behavior for NaN comparison,
+ * signed zero handling, etc.  Currently never activated but may be needed
+ * for broken compilers.
+ */
+#undef DUK_USE_PARANOID_MATH
+
+/* There was a curious bug where test-bi-date-canceling.js would fail e.g.
+ * on 64-bit Ubuntu, gcc-4.8.1, -m32, and no -std=c99.  Some date computations
+ * using doubles would be optimized which then broke some corner case tests.
+ * The problem goes away by adding 'volatile' to the datetime computations.
+ * Not sure what the actual triggering conditions are, but using this on
+ * non-C99 systems solves the known issues and has relatively little cost
+ * on other platforms.
+ */
+#undef DUK_USE_PARANOID_DATE_COMPUTATION
+#if !defined(DUK_F_C99)
+#define DUK_USE_PARANOID_DATE_COMPUTATION
+#endif
+
+/*
+ *  Byte order and double memory layout detection
+ *
+ *  Endianness detection is a major portability hassle because the macros
+ *  and headers are not standardized.  There's even variance across UNIX
+ *  platforms.  Even with "standard" headers, details like underscore count
+ *  varies between platforms, e.g. both __BYTE_ORDER and _BYTE_ORDER are used
+ *  (Crossbridge has a single underscore, for instance).
+ *
+ *  The checks below are structured with this in mind: several approaches are
+ *  used, and at the end we check if any of them worked.  This allows generic
+ *  approaches to be tried first, and platform/compiler specific hacks tried
+ *  last.  As a last resort, the user can force a specific endianness, as it's
+ *  not likely that automatic detection will work on the most exotic platforms.
+ *
+ *  Duktape supports little and big endian machines.  There's also support
+ *  for a hybrid used by some ARM machines where integers are little endian
+ *  but IEEE double values use a mixed order (12345678 -> 43218765).  This
+ *  byte order for doubles is referred to as "mixed endian".
+ */
+
+/* For custom platforms allow user to define byteorder explicitly.
+ * Since endianness headers are not standardized, this is a useful
+ * workaround for custom platforms for which endianness detection
+ * is not directly supported.  Perhaps custom hardware is used and
+ * user cannot submit upstream patches.
+ */
+#if defined(DUK_OPT_FORCE_BYTEORDER)
+#undef DUK_USE_BYTEORDER
+#if (DUK_OPT_FORCE_BYTEORDER == 1)
+#define DUK_USE_BYTEORDER 1
+#elif (DUK_OPT_FORCE_BYTEORDER == 2)
+#define DUK_USE_BYTEORDER 2
+#elif (DUK_OPT_FORCE_BYTEORDER == 3)
+#define DUK_USE_BYTEORDER 3
+#else
+#error invalid DUK_OPT_FORCE_BYTEORDER value
+#endif
+#endif  /* DUK_OPT_FORCE_BYTEORDER */
+
+/* GCC and Clang provide endianness defines as built-in predefines, with
+ * leading and trailing double underscores (e.g. __BYTE_ORDER__).  See
+ * output of "make gccpredefs" and "make clangpredefs".  Clang doesn't
+ * seem to provide __FLOAT_WORD_ORDER__; assume not mixed endian for clang.
+ * http://gcc.gnu.org/onlinedocs/cpp/Common-Predefined-Macros.html
+ */
+#if !defined(DUK_USE_BYTEORDER) && defined(__BYTE_ORDER__)
+#if defined(__ORDER_LITTLE_ENDIAN__) && (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
+#if defined(__FLOAT_WORD_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) && (__FLOAT_WORD_ORDER__ == __ORDER_LITTLE_ENDIAN__)
+#define DUK_USE_BYTEORDER 1
+#elif defined(__FLOAT_WORD_ORDER__) && defined(__ORDER_BIG_ENDIAN__) && (__FLOAT_WORD_ORDER__ == __ORDER_BIG_ENDIAN__)
+#define DUK_USE_BYTEORDER 2
+#elif !defined(__FLOAT_WORD_ORDER__)
+/* Float word order not known, assume not a hybrid. */
+#define DUK_USE_BYTEORDER 1
+#else
+/* Byte order is little endian but cannot determine IEEE double word order. */
+#endif  /* float word order */
+#elif defined(__ORDER_BIG_ENDIAN__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)
+#if defined(__FLOAT_WORD_ORDER__) && defined(__ORDER_BIG_ENDIAN__) && (__FLOAT_WORD_ORDER__ == __ORDER_BIG_ENDIAN__)
+#define DUK_USE_BYTEORDER 3
+#elif !defined(__FLOAT_WORD_ORDER__)
+/* Float word order not known, assume not a hybrid. */
+#define DUK_USE_BYTEORDER 3
+#else
+/* Byte order is big endian but cannot determine IEEE double word order. */
+#endif  /* float word order */
+#else
+/* Cannot determine byte order; __ORDER_PDP_ENDIAN__ is related to 32-bit
+ * integer ordering and is not relevant.
+ */
+#endif  /* integer byte order */
+#endif  /* !defined(DUK_USE_BYTEORDER) && defined(__BYTE_ORDER__) */
+
+/* More or less standard endianness predefines provided by header files.
+ * The ARM hybrid case is detected by assuming that __FLOAT_WORD_ORDER
+ * will be big endian, see: http://lists.mysql.com/internals/443.
+ * On some platforms some defines may be present with an empty value which
+ * causes comparisons to fail: https://github.com/svaarala/duktape/issues/453.
+ */
+#if !defined(DUK_USE_BYTEORDER)
+#if defined(__BYTE_ORDER) && defined(__LITTLE_ENDIAN) && (__BYTE_ORDER == __LITTLE_ENDIAN) || \
+    defined(_BYTE_ORDER) && defined(_LITTLE_ENDIAN) && (_BYTE_ORDER == _LITTLE_ENDIAN) || \
+    defined(__LITTLE_ENDIAN__)
+#if defined(__FLOAT_WORD_ORDER) && defined(__LITTLE_ENDIAN) && (__FLOAT_WORD_ORDER == __LITTLE_ENDIAN) || \
+    defined(_FLOAT_WORD_ORDER) && defined(_LITTLE_ENDIAN) && (_FLOAT_WORD_ORDER == _LITTLE_ENDIAN)
+#define DUK_USE_BYTEORDER 1
+#elif defined(__FLOAT_WORD_ORDER) && defined(__BIG_ENDIAN) && (__FLOAT_WORD_ORDER == __BIG_ENDIAN) || \
+      defined(_FLOAT_WORD_ORDER) && defined(_BIG_ENDIAN) && (_FLOAT_WORD_ORDER == _BIG_ENDIAN)
+#define DUK_USE_BYTEORDER 2
+#elif !defined(__FLOAT_WORD_ORDER) && !defined(_FLOAT_WORD_ORDER)
+/* Float word order not known, assume not a hybrid. */
+#define DUK_USE_BYTEORDER 1
+#else
+/* Byte order is little endian but cannot determine IEEE double word order. */
+#endif  /* float word order */
+#elif defined(__BYTE_ORDER) && defined(__BIG_ENDIAN) && (__BYTE_ORDER == __BIG_ENDIAN) || \
+      defined(_BYTE_ORDER) && defined(_BIG_ENDIAN) && (_BYTE_ORDER == _BIG_ENDIAN) || \
+      defined(__BIG_ENDIAN__)
+#if defined(__FLOAT_WORD_ORDER) && defined(__BIG_ENDIAN) && (__FLOAT_WORD_ORDER == __BIG_ENDIAN) || \
+    defined(_FLOAT_WORD_ORDER) && defined(_BIG_ENDIAN) && (_FLOAT_WORD_ORDER == _BIG_ENDIAN)
+#define DUK_USE_BYTEORDER 3
+#elif !defined(__FLOAT_WORD_ORDER) && !defined(_FLOAT_WORD_ORDER)
+/* Float word order not known, assume not a hybrid. */
+#define DUK_USE_BYTEORDER 3
+#else
+/* Byte order is big endian but cannot determine IEEE double word order. */
+#endif  /* float word order */
+#else
+/* Cannot determine byte order. */
+#endif  /* integer byte order */
+#endif  /* !defined(DUK_USE_BYTEORDER) */
+
+/* QNX gcc cross compiler seems to define e.g. __LITTLEENDIAN__ or __BIGENDIAN__:
+ *  $ /opt/qnx650/host/linux/x86/usr/bin/i486-pc-nto-qnx6.5.0-gcc -dM -E - </dev/null | grep -ni endian
+ *  67:#define __LITTLEENDIAN__ 1
+ *  $ /opt/qnx650/host/linux/x86/usr/bin/mips-unknown-nto-qnx6.5.0-gcc -dM -E - </dev/null | grep -ni endian
+ *  81:#define __BIGENDIAN__ 1
+ *  $ /opt/qnx650/host/linux/x86/usr/bin/arm-unknown-nto-qnx6.5.0-gcc -dM -E - </dev/null | grep -ni endian
+ *  70:#define __LITTLEENDIAN__ 1
+ */
+#if !defined(DUK_USE_BYTEORDER)
+#if defined(__LITTLEENDIAN__)
+#define DUK_USE_BYTEORDER 1
+#elif defined(__BIGENDIAN__)
+#define DUK_USE_BYTEORDER 3
+#endif
+#endif
+
+/*
+ *  Alignment requirement and support for unaligned accesses
+ *
+ *  Assume unaligned accesses are not supported unless specifically allowed
+ *  in the target platform.  Some platforms may support unaligned accesses
+ *  but alignment to 4 or 8 may still be desirable.
+ */
+
+/* If not provided, use safe default for alignment. */
+#if !defined(DUK_USE_ALIGN_BY)
+#define DUK_USE_ALIGN_BY 8
+#endif
+
+/* User forced alignment to 4 or 8. */
+#if defined(DUK_OPT_FORCE_ALIGN)
+#undef DUK_USE_ALIGN_BY
+#if (DUK_OPT_FORCE_ALIGN == 4)
+#define DUK_USE_ALIGN_BY 4
+#elif (DUK_OPT_FORCE_ALIGN == 8)
+#define DUK_USE_ALIGN_BY 8
+#else
+#error invalid DUK_OPT_FORCE_ALIGN value
+#endif
+#endif
+
+/* Compiler specific hackery needed to force struct size to match aligment,
+ * see e.g. duk_hbuffer.h.
+ *
+ * http://stackoverflow.com/questions/11130109/c-struct-size-alignment
+ * http://stackoverflow.com/questions/10951039/specifying-64-bit-alignment
+ */
+#if !(defined(DUK_USE_PACK_MSVC_PRAGMA) || defined(DUK_USE_PACK_GCC_ATTR) || \
+      defined(DUK_USE_PACK_CLANG_ATTR) || defined(DUK_USE_PACK_DUMMY_MEMBER))
+#define DUK_USE_PACK_DUMMY_MEMBER
+#endif
+
+#if !defined(DUK_VA_COPY)
+/* We need va_copy() which is defined in C99 / C++11, so an awkward
+ * replacement is needed for pre-C99 / pre-C++11 environments.  This
+ * will quite likely need portability hacks for some non-C99
+ * environments.
+ */
+#if defined(DUK_F_C99) || defined(DUK_F_CPP11)
+/* C99 / C++11 and above: rely on va_copy() which is required.
+ * Omit parenthesis on macro right side on purpose to minimize differences
+ * to direct use.
+ */
+#define DUK_VA_COPY(dest,src) va_copy(dest,src)
+#else
+/* Pre-C99: va_list type is implementation dependent.  This replacement
+ * assumes it is a plain value so that a simple assignment will work.
+ * This is not the case on all platforms (it may be a single-array element,
+ * for instance).
+ */
+#define DUK_VA_COPY(dest,src) do { (dest) = (src); } while (0)
+#endif
+#endif
+
+#if !defined(DUK_MACRO_STRINGIFY)
+/* Macro hackery to convert e.g. __LINE__ to a string without formatting,
+ * see: http://stackoverflow.com/questions/240353/convert-a-preprocessor-token-to-a-string
+ */
+#define DUK_MACRO_STRINGIFY_HELPER(x)  #x
+#define DUK_MACRO_STRINGIFY(x)  DUK_MACRO_STRINGIFY_HELPER(x)
+#endif
+
+#if !defined(DUK_CAUSE_SEGFAULT)
+/* This is optionally used by panic handling to cause the program to segfault
+ * (instead of e.g. abort()) on panic.  Valgrind will then indicate the C
+ * call stack leading to the panic.
+ */
+#define DUK_CAUSE_SEGFAULT()  do { *((volatile duk_uint32_t *) NULL) = (duk_uint32_t) 0xdeadbeefUL; } while (0)
+#endif
+#if !defined(DUK_UNREF)
+/* Macro for suppressing warnings for potentially unreferenced variables.
+ * The variables can be actually unreferenced or unreferenced in some
+ * specific cases only; for instance, if a variable is only debug printed,
+ * it is unreferenced when debug printing is disabled.
+ */
+#define DUK_UNREF(x)  do { (void) (x); } while (0)
+#endif
+#if !defined(DUK_NORETURN)
+#define DUK_NORETURN(decl)  decl
+#endif
+#if !defined(DUK_UNREACHABLE)
+/* Don't know how to declare unreachable point, so don't do it; this
+ * may cause some spurious compilation warnings (e.g. "variable used
+ * uninitialized").
+ */
+#define DUK_UNREACHABLE()  do { } while (0)
+#endif
+#if !defined(DUK_LOSE_CONST)
+/* Convert any input pointer into a "void *", losing a const qualifier.
+ * This is not fully portable because casting through duk_uintptr_t may
+ * not work on all architectures (e.g. those with long, segmented pointers).
+ */
+#define DUK_LOSE_CONST(src) ((void *) (duk_uintptr_t) (src))
+#endif
+
+#if !defined(DUK_LIKELY)
+#define DUK_LIKELY(x)    (x)
+#endif
+#if !defined(DUK_UNLIKELY)
+#define DUK_UNLIKELY(x)  (x)
+#endif
+
+#if !defined(DUK_NOINLINE)
+#define DUK_NOINLINE       /*nop*/
+#endif
+#if !defined(DUK_INLINE)
+#define DUK_INLINE         /*nop*/
+#endif
+#if !defined(DUK_ALWAYS_INLINE)
+#define DUK_ALWAYS_INLINE  /*nop*/
+#endif
+
+#if !defined(DUK_EXTERNAL_DECL)
+#define DUK_EXTERNAL_DECL  extern
+#endif
+#if !defined(DUK_EXTERNAL)
+#define DUK_EXTERNAL       /*empty*/
+#endif
+#if !defined(DUK_INTERNAL_DECL)
+#if defined(DUK_SINGLE_FILE)
+#define DUK_INTERNAL_DECL  static
+#else
+#define DUK_INTERNAL_DECL  extern
+#endif
+#endif
+#if !defined(DUK_INTERNAL)
+#if defined(DUK_SINGLE_FILE)
+#define DUK_INTERNAL       static
+#else
+#define DUK_INTERNAL       /*empty*/
+#endif
+#endif
+#if !defined(DUK_LOCAL_DECL)
+#define DUK_LOCAL_DECL     static
+#endif
+#if !defined(DUK_LOCAL)
+#define DUK_LOCAL          static
+#endif
+
+#if !defined(DUK_FILE_MACRO)
+#define DUK_FILE_MACRO  __FILE__
+#endif
+#if !defined(DUK_LINE_MACRO)
+#define DUK_LINE_MACRO  __LINE__
+#endif
+#if !defined(DUK_FUNC_MACRO)
+#if defined(DUK_F_C99) || defined(DUK_F_CPP11)
+#define DUK_FUNC_MACRO  __func__
+#elif defined(__FUNCTION__)
+#define DUK_FUNC_MACRO  __FUNCTION__
+#else
+#define DUK_FUNC_MACRO  "unknown"
+#endif
+#endif
+
+#if !defined(DUK_BSWAP32)
+#define DUK_BSWAP32(x) \
+	((((duk_uint32_t) (x)) >> 24) | \
+	 ((((duk_uint32_t) (x)) >> 8) & 0xff00UL) | \
+	 ((((duk_uint32_t) (x)) << 8) & 0xff0000UL) | \
+	 (((duk_uint32_t) (x)) << 24))
+#endif
+#if !defined(DUK_BSWAP16)
+#define DUK_BSWAP16(x) \
+	((duk_uint16_t) (x) >> 8) | \
+	((duk_uint16_t) (x) << 8)
+#endif
+
+/* Explicit marker needed; may be 'defined', 'undefined, 'or 'not provided'. */
+#if !defined(DUK_F_VARIADIC_MACROS_PROVIDED)
+#undef DUK_USE_VARIADIC_MACROS
+#if defined(DUK_F_C99) || defined(DUK_F_CPP11)
+#define DUK_USE_VARIADIC_MACROS
+#endif
+#endif
+
+#if !(defined(DUK_USE_FLEX_C99) || defined(DUK_USE_FLEX_ZEROSIZE) || defined(DUK_USE_FLEX_ONESIZE))
+#if defined(DUK_F_C99)
+#define DUK_USE_FLEX_C99
+#else
+#define DUK_USE_FLEX_ZEROSIZE  /* Not standard but common enough */
+#endif
+#endif
+
+#if !(defined(DUK_USE_PACK_GCC_ATTR) || defined(DUK_USE_PACK_CLANG_ATTR) || \
+      defined(DUK_USE_PACK_MSVC_PRAGMA) || defined(DUK_USE_PACK_DUMMY_MEMBER))
+#define DUK_USE_PACK_DUMMY_MEMBER
+#endif
+
+#if 0  /* not defined by default */
+#undef DUK_USE_GCC_PRAGMAS
+#endif
+
+/* Workaround for GH-323: avoid inlining control when compiling from
+ * multiple sources, as it causes compiler portability trouble.
+ */
+#if !defined(DUK_SINGLE_FILE)
+#undef DUK_NOINLINE
+#undef DUK_INLINE
+#undef DUK_ALWAYS_INLINE
+#define DUK_NOINLINE       /*nop*/
+#define DUK_INLINE         /*nop*/
+#define DUK_ALWAYS_INLINE  /*nop*/
+#endif
+
+/*
+ *  Check whether or not a packed duk_tval representation is possible.
+ *  What's basically required is that pointers are 32-bit values
+ *  (sizeof(void *) == 4).  Best effort check, not always accurate.
+ *  If guess goes wrong, crashes may result; self tests also verify
+ *  the guess.
+ */
+
+/* Explicit marker needed; may be 'defined', 'undefined, 'or 'not provided'. */
+#if !defined(DUK_F_PACKED_TVAL_PROVIDED)
+#undef DUK_F_PACKED_TVAL_POSSIBLE
+
+/* Strict C99 case: DUK_UINTPTR_MAX (= UINTPTR_MAX) should be very reliable */
+#if !defined(DUK_F_PACKED_TVAL_POSSIBLE) && defined(DUK_UINTPTR_MAX)
+#if (DUK_UINTPTR_MAX <= 0xffffffffUL)
+#define DUK_F_PACKED_TVAL_POSSIBLE
+#endif
+#endif
+
+/* Non-C99 case, still relying on DUK_UINTPTR_MAX, as long as it is not a computed value */
+#if !defined(DUK_F_PACKED_TVAL_POSSIBLE) && defined(DUK_UINTPTR_MAX) && !defined(DUK_UINTPTR_MAX_COMPUTED)
+#if (DUK_UINTPTR_MAX <= 0xffffffffUL)
+#define DUK_F_PACKED_TVAL_POSSIBLE
+#endif
+#endif
+
+/* DUK_SIZE_MAX (= SIZE_MAX) is often reliable */
+#if !defined(DUK_F_PACKED_TVAL_POSSIBLE) && defined(DUK_SIZE_MAX) && !defined(DUK_SIZE_MAX_COMPUTED)
+#if (DUK_SIZE_MAX <= 0xffffffffUL)
+#define DUK_F_PACKED_TVAL_POSSIBLE
+#endif
+#endif
+
+#undef DUK_USE_PACKED_TVAL
+#if defined(DUK_F_PACKED_TVAL_POSSIBLE)
+#define DUK_USE_PACKED_TVAL
+#endif
+
+#undef DUK_F_PACKED_TVAL_POSSIBLE
+#endif  /* DUK_F_PACKED_TVAL_PROVIDED */
+
+/* Feature option forcing. */
+#if defined(DUK_OPT_NO_PACKED_TVAL)
+#undef DUK_USE_PACKED_TVAL
+#elif defined(DUK_OPT_PACKED_TVAL)
+#undef DUK_USE_PACKED_TVAL
+#define DUK_USE_PACKED_TVAL
+#endif
+/* Object property allocation layout has implications for memory and code
+ * footprint and generated code size/speed.  The best layout also depends
+ * on whether the platform has alignment requirements or benefits from
+ * having mostly aligned accesses.
+ */
+#undef DUK_USE_HOBJECT_LAYOUT_1
+#undef DUK_USE_HOBJECT_LAYOUT_2
+#undef DUK_USE_HOBJECT_LAYOUT_3
+#if (DUK_USE_ALIGN_BY == 1)
+/* On platforms without any alignment issues, layout 1 is preferable
+ * because it compiles to slightly less code and provides direct access
+ * to property keys.
+ */
+#define DUK_USE_HOBJECT_LAYOUT_1
+#else
+/* On other platforms use layout 2, which requires some padding but
+ * is a bit more natural than layout 3 in ordering the entries.  Layout
+ * 3 is currently not used.
+ */
+#define DUK_USE_HOBJECT_LAYOUT_2
+#endif
+
+/* GCC/clang inaccurate math would break compliance and probably duk_tval,
+ * so refuse to compile.  Relax this if -ffast-math is tested to work.
+ */
+#if defined(__FAST_MATH__)
+#error __FAST_MATH__ defined, refusing to compile
+#endif
+
+/*
+ *  Feature option handling
+ */
+
+#if !defined(DUK_USE_ALIGN_BY)
+#if defined(DUK_OPT_FORCE_ALIGN)
+#define DUK_USE_ALIGN_BY DUK_OPT_FORCE_ALIGN
+#else
+#define DUK_USE_ALIGN_BY 8
+#endif
+#endif
+
+#if defined(DUK_OPT_ASSERTIONS)
+#define DUK_USE_ASSERTIONS
+#elif defined(DUK_OPT_NO_ASSERTIONS)
+#undef DUK_USE_ASSERTIONS
+#else
+#undef DUK_USE_ASSERTIONS
+#endif
+
+#if defined(DUK_OPT_AUGMENT_ERRORS)
+#define DUK_USE_AUGMENT_ERROR_CREATE
+#elif defined(DUK_OPT_NO_AUGMENT_ERRORS)
+#undef DUK_USE_AUGMENT_ERROR_CREATE
+#else
+#define DUK_USE_AUGMENT_ERROR_CREATE
+#endif
+
+#if defined(DUK_OPT_AUGMENT_ERRORS)
+#define DUK_USE_AUGMENT_ERROR_THROW
+#elif defined(DUK_OPT_NO_AUGMENT_ERRORS)
+#undef DUK_USE_AUGMENT_ERROR_THROW
+#else
+#define DUK_USE_AUGMENT_ERROR_THROW
+#endif
+
+#if defined(DUK_OPT_BROWSER_LIKE)
+#define DUK_USE_BROWSER_LIKE
+#elif defined(DUK_OPT_NO_BROWSER_LIKE)
+#undef DUK_USE_BROWSER_LIKE
+#else
+#define DUK_USE_BROWSER_LIKE
+#endif
+
+#if defined(DUK_OPT_BUFFEROBJECT_SUPPORT)
+#define DUK_USE_BUFFEROBJECT_SUPPORT
+#elif defined(DUK_OPT_NO_BUFFEROBJECT_SUPPORT)
+#undef DUK_USE_BUFFEROBJECT_SUPPORT
+#else
+#define DUK_USE_BUFFEROBJECT_SUPPORT
+#endif
+
+#if defined(DUK_OPT_BUFLEN16)
+#define DUK_USE_BUFLEN16
+#elif defined(DUK_OPT_NO_BUFLEN16)
+#undef DUK_USE_BUFLEN16
+#else
+#undef DUK_USE_BUFLEN16
+#endif
+
+#if defined(DUK_OPT_BYTECODE_DUMP_SUPPORT)
+#define DUK_USE_BYTECODE_DUMP_SUPPORT
+#elif defined(DUK_OPT_NO_BYTECODE_DUMP_SUPPORT)
+#undef DUK_USE_BYTECODE_DUMP_SUPPORT
+#else
+#define DUK_USE_BYTECODE_DUMP_SUPPORT
+#endif
+
+#if defined(DUK_OPT_COMMONJS_MODULES)
+#define DUK_USE_COMMONJS_MODULES
+#elif defined(DUK_OPT_NO_COMMONJS_MODULES)
+#undef DUK_USE_COMMONJS_MODULES
+#else
+#define DUK_USE_COMMONJS_MODULES
+#endif
+
+#if defined(DUK_OPT_CPP_EXCEPTIONS)
+#define DUK_USE_CPP_EXCEPTIONS
+#elif defined(DUK_OPT_NO_CPP_EXCEPTIONS)
+#undef DUK_USE_CPP_EXCEPTIONS
+#else
+#undef DUK_USE_CPP_EXCEPTIONS
+#endif
+
+#if defined(DUK_OPT_DATAPTR16)
+#define DUK_USE_DATAPTR16
+#elif defined(DUK_OPT_NO_DATAPTR16)
+#undef DUK_USE_DATAPTR16
+#else
+#undef DUK_USE_DATAPTR16
+#endif
+
+#if defined(DUK_OPT_DATAPTR_DEC16)
+#define DUK_USE_DATAPTR_DEC16(udata,ptr) DUK_OPT_DATAPTR_DEC16((udata),(ptr))
+#else
+#undef DUK_USE_DATAPTR_DEC16
+#endif
+
+#if defined(DUK_OPT_DATAPTR_ENC16)
+#define DUK_USE_DATAPTR_ENC16(udata,ptr) DUK_OPT_DATAPTR_ENC16((udata),(ptr))
+#else
+#undef DUK_USE_DATAPTR_ENC16
+#endif
+
+#if defined(DUK_OPT_DDDPRINT)
+#define DUK_USE_DDDPRINT
+#elif defined(DUK_OPT_NO_DDDPRINT)
+#undef DUK_USE_DDDPRINT
+#else
+#undef DUK_USE_DDDPRINT
+#endif
+
+#if defined(DUK_OPT_DDPRINT)
+#define DUK_USE_DDPRINT
+#elif defined(DUK_OPT_NO_DDPRINT)
+#undef DUK_USE_DDPRINT
+#else
+#undef DUK_USE_DDPRINT
+#endif
+
+#if defined(DUK_OPT_DEBUG)
+#define DUK_USE_DEBUG
+#elif defined(DUK_OPT_NO_DEBUG)
+#undef DUK_USE_DEBUG
+#else
+#undef DUK_USE_DEBUG
+#endif
+
+#if defined(DUK_OPT_DEBUGGER_DUMPHEAP)
+#define DUK_USE_DEBUGGER_DUMPHEAP
+#elif defined(DUK_OPT_NO_DEBUGGER_DUMPHEAP)
+#undef DUK_USE_DEBUGGER_DUMPHEAP
+#else
+#undef DUK_USE_DEBUGGER_DUMPHEAP
+#endif
+
+#if defined(DUK_OPT_DEBUGGER_FWD_LOGGING)
+#define DUK_USE_DEBUGGER_FWD_LOGGING
+#elif defined(DUK_OPT_NO_DEBUGGER_FWD_LOGGING)
+#undef DUK_USE_DEBUGGER_FWD_LOGGING
+#else
+#undef DUK_USE_DEBUGGER_FWD_LOGGING
+#endif
+
+#if defined(DUK_OPT_DEBUGGER_FWD_PRINTALERT)
+#define DUK_USE_DEBUGGER_FWD_PRINTALERT
+#elif defined(DUK_OPT_NO_DEBUGGER_FWD_PRINTALERT)
+#undef DUK_USE_DEBUGGER_FWD_PRINTALERT
+#else
+#undef DUK_USE_DEBUGGER_FWD_PRINTALERT
+#endif
+
+#if defined(DUK_OPT_DEBUGGER_PAUSE_UNCAUGHT)
+#define DUK_USE_DEBUGGER_PAUSE_UNCAUGHT
+#elif defined(DUK_OPT_NO_DEBUGGER_PAUSE_UNCAUGHT)
+#undef DUK_USE_DEBUGGER_PAUSE_UNCAUGHT
+#else
+#undef DUK_USE_DEBUGGER_PAUSE_UNCAUGHT
+#endif
+
+#if defined(DUK_OPT_DEBUGGER_SUPPORT)
+#define DUK_USE_DEBUGGER_SUPPORT
+#elif defined(DUK_OPT_NO_DEBUGGER_SUPPORT)
+#undef DUK_USE_DEBUGGER_SUPPORT
+#else
+#undef DUK_USE_DEBUGGER_SUPPORT
+#endif
+
+#if defined(DUK_OPT_DEBUGGER_THROW_NOTIFY)
+#define DUK_USE_DEBUGGER_THROW_NOTIFY
+#elif defined(DUK_OPT_NO_DEBUGGER_THROW_NOTIFY)
+#undef DUK_USE_DEBUGGER_THROW_NOTIFY
+#else
+#define DUK_USE_DEBUGGER_THROW_NOTIFY
+#endif
+
+#if defined(DUK_OPT_DEBUGGER_TRANSPORT_TORTURE)
+#define DUK_USE_DEBUGGER_TRANSPORT_TORTURE
+#elif defined(DUK_OPT_NO_DEBUGGER_TRANSPORT_TORTURE)
+#undef DUK_USE_DEBUGGER_TRANSPORT_TORTURE
+#else
+#undef DUK_USE_DEBUGGER_TRANSPORT_TORTURE
+#endif
+
+#if defined(DUK_OPT_DEBUG_BUFSIZE)
+#define DUK_USE_DEBUG_BUFSIZE DUK_OPT_DEBUG_BUFSIZE
+#else
+#define DUK_USE_DEBUG_BUFSIZE 65536L
+#endif
+
+#if defined(DUK_OPT_REFERENCE_COUNTING)
+#define DUK_USE_DOUBLE_LINKED_HEAP
+#elif defined(DUK_OPT_NO_REFERENCE_COUNTING)
+#undef DUK_USE_DOUBLE_LINKED_HEAP
+#else
+#define DUK_USE_DOUBLE_LINKED_HEAP
+#endif
+
+#if defined(DUK_OPT_DPRINT)
+#define DUK_USE_DPRINT
+#elif defined(DUK_OPT_NO_DPRINT)
+#undef DUK_USE_DPRINT
+#else
+#undef DUK_USE_DPRINT
+#endif
+
+#if defined(DUK_OPT_DPRINT_COLORS)
+#define DUK_USE_DPRINT_COLORS
+#elif defined(DUK_OPT_NO_DPRINT_COLORS)
+#undef DUK_USE_DPRINT_COLORS
+#else
+#undef DUK_USE_DPRINT_COLORS
+#endif
+
+#if defined(DUK_OPT_DPRINT_RDTSC)
+#define DUK_USE_DPRINT_RDTSC
+#elif defined(DUK_OPT_NO_DPRINT_RDTSC)
+#undef DUK_USE_DPRINT_RDTSC
+#else
+#undef DUK_USE_DPRINT_RDTSC
+#endif
+
+#if defined(DUK_OPT_AUGMENT_ERRORS)
+#define DUK_USE_ERRCREATE
+#elif defined(DUK_OPT_NO_AUGMENT_ERRORS)
+#undef DUK_USE_ERRCREATE
+#else
+#define DUK_USE_ERRCREATE
+#endif
+
+#if defined(DUK_OPT_AUGMENT_ERRORS)
+#define DUK_USE_ERRTHROW
+#elif defined(DUK_OPT_NO_AUGMENT_ERRORS)
+#undef DUK_USE_ERRTHROW
+#else
+#define DUK_USE_ERRTHROW
+#endif
+
+#if defined(DUK_OPT_ES6_OBJECT_PROTO_PROPERTY)
+#define DUK_USE_ES6_OBJECT_PROTO_PROPERTY
+#elif defined(DUK_OPT_NO_ES6_OBJECT_PROTO_PROPERTY)
+#undef DUK_USE_ES6_OBJECT_PROTO_PROPERTY
+#else
+#define DUK_USE_ES6_OBJECT_PROTO_PROPERTY
+#endif
+
+#if defined(DUK_OPT_ES6_OBJECT_SETPROTOTYPEOF)
+#define DUK_USE_ES6_OBJECT_SETPROTOTYPEOF
+#elif defined(DUK_OPT_NO_ES6_OBJECT_SETPROTOTYPEOF)
+#undef DUK_USE_ES6_OBJECT_SETPROTOTYPEOF
+#else
+#define DUK_USE_ES6_OBJECT_SETPROTOTYPEOF
+#endif
+
+#if defined(DUK_OPT_ES6_PROXY)
+#define DUK_USE_ES6_PROXY
+#elif defined(DUK_OPT_NO_ES6_PROXY)
+#undef DUK_USE_ES6_PROXY
+#else
+#define DUK_USE_ES6_PROXY
+#endif
+
+#undef DUK_USE_EXEC_INDIRECT_BOUND_CHECK
+#if defined(DUK_OPT_DEBUG) || defined(DUK_OPT_ASSERTIONS)
+/* Enabled with debug/assertions just so that any issues can be caught. */
+#define DUK_USE_EXEC_INDIRECT_BOUND_CHECK
+#endif
+
+#undef DUK_USE_EXEC_TIMEOUT_CHECK
+#if defined(DUK_OPT_EXEC_TIMEOUT_CHECK)
+#define DUK_USE_EXEC_TIMEOUT_CHECK(udata)  DUK_OPT_EXEC_TIMEOUT_CHECK((udata))
+#endif
+
+#undef DUK_USE_EXTSTR_FREE
+#if defined(DUK_OPT_EXTERNAL_STRINGS) && defined(DUK_OPT_EXTSTR_FREE)
+#define DUK_USE_EXTSTR_FREE(udata,ptr) DUK_OPT_EXTSTR_FREE((udata), (ptr))
+#endif
+
+#undef DUK_USE_EXTSTR_INTERN_CHECK
+#if defined(DUK_OPT_EXTERNAL_STRINGS) && defined(DUK_OPT_EXTSTR_INTERN_CHECK)
+#define DUK_USE_EXTSTR_INTERN_CHECK(udata,ptr,len) DUK_OPT_EXTSTR_INTERN_CHECK((udata), (ptr), (len))
+#endif
+
+/* Support for 48-bit signed integer duk_tval with transparent semantics. */
+#undef DUK_USE_FASTINT
+#if defined(DUK_OPT_FASTINT)
+#if !defined(DUK_F_HAVE_64BIT)
+#error DUK_OPT_FASTINT requires 64-bit integer type support at the moment
+#endif
+#define DUK_USE_FASTINT
+#endif
+
+#if defined(DUK_OPT_FILE_IO)
+#define DUK_USE_FILE_IO
+#elif defined(DUK_OPT_NO_FILE_IO)
+#undef DUK_USE_FILE_IO
+#else
+#define DUK_USE_FILE_IO
+#endif
+
+#if defined(DUK_OPT_FUNCPTR16)
+#define DUK_USE_FUNCPTR16
+#elif defined(DUK_OPT_NO_FUNCPTR16)
+#undef DUK_USE_FUNCPTR16
+#else
+#undef DUK_USE_FUNCPTR16
+#endif
+
+#if defined(DUK_OPT_FUNCPTR_DEC16)
+#define DUK_USE_FUNCPTR_DEC16(udata,ptr) DUK_OPT_FUNCPTR_DEC16((udata),(ptr))
+#else
+#undef DUK_USE_FUNCPTR_DEC16
+#endif
+
+#if defined(DUK_OPT_FUNCPTR_ENC16)
+#define DUK_USE_FUNCPTR_ENC16(udata,ptr) DUK_OPT_FUNCPTR_ENC16((udata),(ptr))
+#else
+#undef DUK_USE_FUNCPTR_ENC16
+#endif
+
+#if defined(DUK_OPT_GC_TORTURE)
+#define DUK_USE_GC_TORTURE
+#elif defined(DUK_OPT_NO_GC_TORTURE)
+#undef DUK_USE_GC_TORTURE
+#else
+#undef DUK_USE_GC_TORTURE
+#endif
+
+#if defined(DUK_OPT_HEAPPTR16)
+#define DUK_USE_HEAPPTR16
+#elif defined(DUK_OPT_NO_HEAPPTR16)
+#undef DUK_USE_HEAPPTR16
+#else
+#undef DUK_USE_HEAPPTR16
+#endif
+
+#if defined(DUK_OPT_HEAPPTR_DEC16)
+#define DUK_USE_HEAPPTR_DEC16(udata,ptr) DUK_OPT_HEAPPTR_DEC16((udata),(ptr))
+#else
+#undef DUK_USE_HEAPPTR_DEC16
+#endif
+
+#if defined(DUK_OPT_HEAPPTR_ENC16)
+#define DUK_USE_HEAPPTR_ENC16(udata,ptr) DUK_OPT_HEAPPTR_ENC16((udata),(ptr))
+#else
+#undef DUK_USE_HEAPPTR_ENC16
+#endif
+
+/* For now, hash part is dropped if and only if 16-bit object fields are used. */
+#define DUK_USE_HOBJECT_HASH_PART
+#if defined(DUK_OPT_OBJSIZES16)
+#undef DUK_USE_HOBJECT_HASH_PART
+#endif
+
+#if defined(DUK_OPT_EXTERNAL_STRINGS)
+#define DUK_USE_HSTRING_EXTDATA
+#elif defined(DUK_OPT_NO_EXTERNAL_STRINGS)
+#undef DUK_USE_HSTRING_EXTDATA
+#else
+#undef DUK_USE_HSTRING_EXTDATA
+#endif
+
+#if defined(DUK_OPT_INTERRUPT_COUNTER)
+#define DUK_USE_INTERRUPT_COUNTER
+#elif defined(DUK_OPT_NO_INTERRUPT_COUNTER)
+#undef DUK_USE_INTERRUPT_COUNTER
+#else
+#undef DUK_USE_INTERRUPT_COUNTER
+#endif
+
+#if defined(DUK_OPT_JC)
+#define DUK_USE_JC
+#elif defined(DUK_OPT_NO_JC)
+#undef DUK_USE_JC
+#else
+#define DUK_USE_JC
+#endif
+
+#if defined(DUK_OPT_JSON_STRINGIFY_FASTPATH)
+#define DUK_USE_JSON_STRINGIFY_FASTPATH
+#elif defined(DUK_OPT_NO_JSON_STRINGIFY_FASTPATH)
+#undef DUK_USE_JSON_STRINGIFY_FASTPATH
+#else
+#undef DUK_USE_JSON_STRINGIFY_FASTPATH
+#endif
+
+#if defined(DUK_OPT_JX)
+#define DUK_USE_JX
+#elif defined(DUK_OPT_NO_JX)
+#undef DUK_USE_JX
+#else
+#define DUK_USE_JX
+#endif
+
+#if defined(DUK_OPT_LIGHTFUNC_BUILTINS)
+#define DUK_USE_LIGHTFUNC_BUILTINS
+#elif defined(DUK_OPT_NO_LIGHTFUNC_BUILTINS)
+#undef DUK_USE_LIGHTFUNC_BUILTINS
+#else
+#undef DUK_USE_LIGHTFUNC_BUILTINS
+#endif
+
+#if defined(DUK_OPT_MARK_AND_SWEEP)
+#define DUK_USE_MARK_AND_SWEEP
+#elif defined(DUK_OPT_NO_MARK_AND_SWEEP)
+#undef DUK_USE_MARK_AND_SWEEP
+#else
+#define DUK_USE_MARK_AND_SWEEP
+#endif
+
+#if defined(DUK_OPT_MS_STRINGTABLE_RESIZE)
+#define DUK_USE_MS_STRINGTABLE_RESIZE
+#elif defined(DUK_OPT_NO_MS_STRINGTABLE_RESIZE)
+#undef DUK_USE_MS_STRINGTABLE_RESIZE
+#else
+#define DUK_USE_MS_STRINGTABLE_RESIZE
+#endif
+
+#if defined(DUK_OPT_NONSTD_ARRAY_CONCAT_TRAILER)
+#define DUK_USE_NONSTD_ARRAY_CONCAT_TRAILER
+#elif defined(DUK_OPT_NO_NONSTD_ARRAY_CONCAT_TRAILER)
+#undef DUK_USE_NONSTD_ARRAY_CONCAT_TRAILER
+#else
+#define DUK_USE_NONSTD_ARRAY_CONCAT_TRAILER
+#endif
+
+#if defined(DUK_OPT_NONSTD_ARRAY_MAP_TRAILER)
+#define DUK_USE_NONSTD_ARRAY_MAP_TRAILER
+#elif defined(DUK_OPT_NO_NONSTD_ARRAY_MAP_TRAILER)
+#undef DUK_USE_NONSTD_ARRAY_MAP_TRAILER
+#else
+#define DUK_USE_NONSTD_ARRAY_MAP_TRAILER
+#endif
+
+#if defined(DUK_OPT_NONSTD_ARRAY_SPLICE_DELCOUNT)
+#define DUK_USE_NONSTD_ARRAY_SPLICE_DELCOUNT
+#elif defined(DUK_OPT_NO_NONSTD_ARRAY_SPLICE_DELCOUNT)
+#undef DUK_USE_NONSTD_ARRAY_SPLICE_DELCOUNT
+#else
+#define DUK_USE_NONSTD_ARRAY_SPLICE_DELCOUNT
+#endif
+
+#if defined(DUK_OPT_NONSTD_FUNC_CALLER_PROPERTY)
+#define DUK_USE_NONSTD_FUNC_CALLER_PROPERTY
+#elif defined(DUK_OPT_NO_NONSTD_FUNC_CALLER_PROPERTY)
+#undef DUK_USE_NONSTD_FUNC_CALLER_PROPERTY
+#else
+#undef DUK_USE_NONSTD_FUNC_CALLER_PROPERTY
+#endif
+
+#if defined(DUK_OPT_NONSTD_FUNC_SOURCE_PROPERTY)
+#define DUK_USE_NONSTD_FUNC_SOURCE_PROPERTY
+#elif defined(DUK_OPT_NO_NONSTD_FUNC_SOURCE_PROPERTY)
+#undef DUK_USE_NONSTD_FUNC_SOURCE_PROPERTY
+#else
+#undef DUK_USE_NONSTD_FUNC_SOURCE_PROPERTY
+#endif
+
+#if defined(DUK_OPT_NONSTD_FUNC_STMT)
+#define DUK_USE_NONSTD_FUNC_STMT
+#elif defined(DUK_OPT_NO_NONSTD_FUNC_STMT)
+#undef DUK_USE_NONSTD_FUNC_STMT
+#else
+#define DUK_USE_NONSTD_FUNC_STMT
+#endif
+
+#if defined(DUK_OPT_NONSTD_ACCESSOR_KEY_ARGUMENT)
+#define DUK_USE_NONSTD_GETTER_KEY_ARGUMENT
+#elif defined(DUK_OPT_NO_NONSTD_ACCESSOR_KEY_ARGUMENT)
+#undef DUK_USE_NONSTD_GETTER_KEY_ARGUMENT
+#else
+#define DUK_USE_NONSTD_GETTER_KEY_ARGUMENT
+#endif
+
+#if defined(DUK_OPT_NONSTD_JSON_ESC_U2028_U2029)
+#define DUK_USE_NONSTD_JSON_ESC_U2028_U2029
+#elif defined(DUK_OPT_NO_NONSTD_JSON_ESC_U2028_U2029)
+#undef DUK_USE_NONSTD_JSON_ESC_U2028_U2029
+#else
+#define DUK_USE_NONSTD_JSON_ESC_U2028_U2029
+#endif
+
+#if defined(DUK_OPT_NONSTD_REGEXP_DOLLAR_ESCAPE)
+#define DUK_USE_NONSTD_REGEXP_DOLLAR_ESCAPE
+#elif defined(DUK_OPT_NO_NONSTD_REGEXP_DOLLAR_ESCAPE)
+#undef DUK_USE_NONSTD_REGEXP_DOLLAR_ESCAPE
+#else
+#define DUK_USE_NONSTD_REGEXP_DOLLAR_ESCAPE
+#endif
+
+#if defined(DUK_OPT_NONSTD_ACCESSOR_KEY_ARGUMENT)
+#define DUK_USE_NONSTD_SETTER_KEY_ARGUMENT
+#elif defined(DUK_OPT_NO_NONSTD_ACCESSOR_KEY_ARGUMENT)
+#undef DUK_USE_NONSTD_SETTER_KEY_ARGUMENT
+#else
+#define DUK_USE_NONSTD_SETTER_KEY_ARGUMENT
+#endif
+
+#if defined(DUK_OPT_NONSTD_STRING_FROMCHARCODE_32BIT)
+#define DUK_USE_NONSTD_STRING_FROMCHARCODE_32BIT
+#elif defined(DUK_OPT_NO_NONSTD_STRING_FROMCHARCODE_32BIT)
+#undef DUK_USE_NONSTD_STRING_FROMCHARCODE_32BIT
+#else
+#define DUK_USE_NONSTD_STRING_FROMCHARCODE_32BIT
+#endif
+
+#if defined(DUK_OPT_OBJSIZES16)
+#define DUK_USE_OBJSIZES16
+#elif defined(DUK_OPT_NO_OBJSIZES16)
+#undef DUK_USE_OBJSIZES16
+#else
+#undef DUK_USE_OBJSIZES16
+#endif
+
+#if defined(DUK_OPT_OCTAL_SUPPORT)
+#define DUK_USE_OCTAL_SUPPORT
+#elif defined(DUK_OPT_NO_OCTAL_SUPPORT)
+#undef DUK_USE_OCTAL_SUPPORT
+#else
+#define DUK_USE_OCTAL_SUPPORT
+#endif
+
+#if defined(DUK_OPT_PACKED_TVAL)
+#define DUK_USE_PACKED_TVAL
+#elif defined(DUK_OPT_NO_PACKED_TVAL)
+#undef DUK_USE_PACKED_TVAL
+#else
+#undef DUK_USE_PACKED_TVAL
+#endif
+
+#undef DUK_USE_PANIC_ABORT
+#if !defined(DUK_OPT_SEGFAULT_ON_PANIC)
+#define DUK_USE_PANIC_ABORT
+#endif
+
+#undef DUK_USE_PANIC_HANDLER
+#if defined(DUK_OPT_PANIC_HANDLER)
+#define DUK_USE_PANIC_HANDLER(code,msg) DUK_OPT_PANIC_HANDLER((code),(msg))
+#endif
+
+#undef DUK_USE_PANIC_SEGFAULT
+#if defined(DUK_OPT_SEGFAULT_ON_PANIC)
+#define DUK_USE_PANIC_SEGFAULT
+#endif
+
+#if defined(DUK_OPT_PARANOID_ERRORS)
+#define DUK_USE_PARANOID_ERRORS
+#elif defined(DUK_OPT_NO_PARANOID_ERRORS)
+#undef DUK_USE_PARANOID_ERRORS
+#else
+#undef DUK_USE_PARANOID_ERRORS
+#endif
+
+#if defined(DUK_OPT_PC2LINE)
+#define DUK_USE_PC2LINE
+#elif defined(DUK_OPT_NO_PC2LINE)
+#undef DUK_USE_PC2LINE
+#else
+#define DUK_USE_PC2LINE
+#endif
+
+#if defined(DUK_OPT_REFCOUNT16)
+#define DUK_USE_REFCOUNT16
+#elif defined(DUK_OPT_NO_REFCOUNT16)
+#undef DUK_USE_REFCOUNT16
+#else
+#undef DUK_USE_REFCOUNT16
+#endif
+
+#if defined(DUK_OPT_REFERENCE_COUNTING)
+#define DUK_USE_REFERENCE_COUNTING
+#elif defined(DUK_OPT_NO_REFERENCE_COUNTING)
+#undef DUK_USE_REFERENCE_COUNTING
+#else
+#define DUK_USE_REFERENCE_COUNTING
+#endif
+
+#if defined(DUK_OPT_REGEXP_CANON_WORKAROUND)
+#define DUK_USE_REGEXP_CANON_WORKAROUND
+#elif defined(DUK_OPT_NO_REGEXP_CANON_WORKAROUND)
+#undef DUK_USE_REGEXP_CANON_WORKAROUND
+#else
+#undef DUK_USE_REGEXP_CANON_WORKAROUND
+#endif
+
+#if defined(DUK_OPT_REGEXP_SUPPORT)
+#define DUK_USE_REGEXP_SUPPORT
+#elif defined(DUK_OPT_NO_REGEXP_SUPPORT)
+#undef DUK_USE_REGEXP_SUPPORT
+#else
+#define DUK_USE_REGEXP_SUPPORT
+#endif
+
+#if defined(DUK_OPT_SECTION_B)
+#define DUK_USE_SECTION_B
+#elif defined(DUK_OPT_NO_SECTION_B)
+#undef DUK_USE_SECTION_B
+#else
+#define DUK_USE_SECTION_B
+#endif
+
+#if defined(DUK_OPT_SELF_TESTS)
+#define DUK_USE_SELF_TESTS
+#elif defined(DUK_OPT_NO_SELF_TESTS)
+#undef DUK_USE_SELF_TESTS
+#else
+#undef DUK_USE_SELF_TESTS
+#endif
+
+#if defined(DUK_OPT_SETJMP)
+#define DUK_USE_SETJMP
+#elif defined(DUK_OPT_NO_SETJMP)
+#undef DUK_USE_SETJMP
+#else
+#define DUK_USE_SETJMP
+#endif
+
+#if defined(DUK_OPT_SHUFFLE_TORTURE)
+#define DUK_USE_SHUFFLE_TORTURE
+#elif defined(DUK_OPT_NO_SHUFFLE_TORTURE)
+#undef DUK_USE_SHUFFLE_TORTURE
+#else
+#undef DUK_USE_SHUFFLE_TORTURE
+#endif
+
+#if defined(DUK_OPT_SIGSETJMP)
+#define DUK_USE_SIGSETJMP
+#elif defined(DUK_OPT_NO_SIGSETJMP)
+#undef DUK_USE_SIGSETJMP
+#else
+#undef DUK_USE_SIGSETJMP
+#endif
+
+#if defined(DUK_OPT_SOURCE_NONBMP)
+#define DUK_USE_SOURCE_NONBMP
+#elif defined(DUK_OPT_NO_SOURCE_NONBMP)
+#undef DUK_USE_SOURCE_NONBMP
+#else
+#define DUK_USE_SOURCE_NONBMP
+#endif
+
+#if defined(DUK_OPT_STRHASH16)
+#define DUK_USE_STRHASH16
+#elif defined(DUK_OPT_NO_STRHASH16)
+#undef DUK_USE_STRHASH16
+#else
+#undef DUK_USE_STRHASH16
+#endif
+
+#if defined(DUK_OPT_STRICT_DECL)
+#define DUK_USE_STRICT_DECL
+#elif defined(DUK_OPT_NO_STRICT_DECL)
+#undef DUK_USE_STRICT_DECL
+#else
+#define DUK_USE_STRICT_DECL
+#endif
+
+#if defined(DUK_OPT_STRICT_UTF8_SOURCE)
+#define DUK_USE_STRICT_UTF8_SOURCE
+#elif defined(DUK_OPT_NO_STRICT_UTF8_SOURCE)
+#undef DUK_USE_STRICT_UTF8_SOURCE
+#else
+#undef DUK_USE_STRICT_UTF8_SOURCE
+#endif
+
+#if defined(DUK_OPT_STRLEN16)
+#define DUK_USE_STRLEN16
+#elif defined(DUK_OPT_NO_STRLEN16)
+#undef DUK_USE_STRLEN16
+#else
+#undef DUK_USE_STRLEN16
+#endif
+
+#undef DUK_USE_STRTAB_CHAIN
+#if defined(DUK_OPT_STRTAB_CHAIN) && defined(DUK_OPT_STRTAB_CHAIN_SIZE)
+#define DUK_USE_STRTAB_CHAIN
+#endif
+
+#undef DUK_USE_STRTAB_CHAIN_SIZE
+#if defined(DUK_OPT_STRTAB_CHAIN) && defined(DUK_OPT_STRTAB_CHAIN_SIZE)
+/* Low memory algorithm: separate chaining using arrays, fixed size hash */
+#define DUK_USE_STRTAB_CHAIN_SIZE  DUK_OPT_STRTAB_CHAIN_SIZE
+#endif
+
+#undef DUK_USE_STRTAB_PROBE
+#if !(defined(DUK_OPT_STRTAB_CHAIN) && defined(DUK_OPT_STRTAB_CHAIN_SIZE))
+#define DUK_USE_STRTAB_PROBE
+#endif
+
+#if defined(DUK_OPT_NONSTD_FUNC_CALLER_PROPERTY)
+#undef DUK_USE_TAILCALL
+#else
+#define DUK_USE_TAILCALL
+#endif
+
+#if defined(DUK_OPT_TARGET_INFO)
+#define DUK_USE_TARGET_INFO DUK_OPT_TARGET_INFO
+#else
+#define DUK_USE_TARGET_INFO "unknown"
+#endif
+
+#if defined(DUK_OPT_NO_AUGMENT_ERRORS)
+#undef DUK_USE_TRACEBACKS
+#elif defined(DUK_OPT_NO_TRACEBACKS)
+#undef DUK_USE_TRACEBACKS
+#else
+#define DUK_USE_TRACEBACKS
+#endif
+
+#if defined(DUK_OPT_TRACEBACK_DEPTH)
+#define DUK_USE_TRACEBACK_DEPTH  DUK_OPT_TRACEBACK_DEPTH
+#else
+#define DUK_USE_TRACEBACK_DEPTH  10
+#endif
+
+#if defined(DUK_OPT_UNDERSCORE_SETJMP)
+#define DUK_USE_UNDERSCORE_SETJMP
+#elif defined(DUK_OPT_NO_UNDERSCORE_SETJMP)
+#undef DUK_USE_UNDERSCORE_SETJMP
+#else
+#undef DUK_USE_UNDERSCORE_SETJMP
+#endif
+
+#if defined(DUK_OPT_DECLARE)
+#define DUK_USE_USER_DECLARE() DUK_OPT_DECLARE
+#else
+#define DUK_USE_USER_DECLARE() /* no user declarations */
+#endif
+
+/* User provided InitJS. */
+#undef DUK_USE_USER_INITJS
+#if defined(DUK_OPT_USER_INITJS)
+#define DUK_USE_USER_INITJS (DUK_OPT_USER_INITJS)
+#endif
+
+#if defined(DUK_OPT_VERBOSE_ERRORS)
+#define DUK_USE_VERBOSE_ERRORS
+#elif defined(DUK_OPT_NO_VERBOSE_ERRORS)
+#undef DUK_USE_VERBOSE_ERRORS
+#else
+#define DUK_USE_VERBOSE_ERRORS
+#endif
+
+#if defined(DUK_OPT_VOLUNTARY_GC)
+#define DUK_USE_VOLUNTARY_GC
+#elif defined(DUK_OPT_NO_VOLUNTARY_GC)
+#undef DUK_USE_VOLUNTARY_GC
+#else
+#define DUK_USE_VOLUNTARY_GC
+#endif
+
+#if defined(DUK_OPT_ZERO_BUFFER_DATA)
+#define DUK_USE_ZERO_BUFFER_DATA
+#elif defined(DUK_OPT_NO_ZERO_BUFFER_DATA)
+#undef DUK_USE_ZERO_BUFFER_DATA
+#else
+#define DUK_USE_ZERO_BUFFER_DATA
+#endif
+
+/*
+ *  Autogenerated defaults
+ */
+
+#define DUK_USE_AVOID_PLATFORM_FUNCPTRS
+#define DUK_USE_BASE64_FASTPATH
+#define DUK_USE_BUILTIN_INITJS
+#define DUK_USE_COMPILER_RECLIMIT 2500
+#undef DUK_USE_DATE_FORMAT_STRING
+#undef DUK_USE_DATE_GET_LOCAL_TZOFFSET
+#undef DUK_USE_DATE_GET_NOW
+#undef DUK_USE_DATE_PARSE_STRING
+#undef DUK_USE_DATE_PRS_GETDATE
+#define DUK_USE_ESBC_LIMITS
+#define DUK_USE_ESBC_MAX_BYTES 2147418112L
+#define DUK_USE_ESBC_MAX_LINENUMBER 2147418112L
+#undef DUK_USE_EXEC_FUN_LOCAL
+#undef DUK_USE_EXPLICIT_NULL_INIT
+#define DUK_USE_FAST_REFCOUNT_DEFAULT
+#define DUK_USE_HEX_FASTPATH
+#undef DUK_USE_INTERRUPT_DEBUG_FIXUP
+#define DUK_USE_JSON_DECNUMBER_FASTPATH
+#define DUK_USE_JSON_DECSTRING_FASTPATH
+#define DUK_USE_JSON_DEC_RECLIMIT 1000
+#define DUK_USE_JSON_EATWHITE_FASTPATH
+#define DUK_USE_JSON_ENC_RECLIMIT 1000
+#define DUK_USE_JSON_QUOTESTRING_FASTPATH
+#define DUK_USE_LEXER_SLIDING_WINDOW
+#undef DUK_USE_MARKANDSWEEP_FINALIZER_TORTURE
+#define DUK_USE_MARK_AND_SWEEP_RECLIMIT 256
+#define DUK_USE_MATH_BUILTIN
+#define DUK_USE_NATIVE_CALL_RECLIMIT 1000
+#undef DUK_USE_PANIC_EXIT
+#undef DUK_USE_PREFER_SIZE
+#define DUK_USE_PROVIDE_DEFAULT_ALLOC_FUNCTIONS
+#undef DUK_USE_REFZERO_FINALIZER_TORTURE
+#define DUK_USE_REGEXP_COMPILER_RECLIMIT 10000
+#define DUK_USE_REGEXP_EXECUTOR_RECLIMIT 10000
+#undef DUK_USE_STRHASH_DENSE
+#define DUK_USE_STRHASH_SKIP_SHIFT 5
+#undef DUK_USE_VALSTACK_UNSAFE
+#define DUK_USE_VERBOSE_EXECUTOR_ERRORS
+
+/*
+ *  Alternative customization header
+ *
+ *  If you want to modify the final DUK_USE_xxx flags directly (without
+ *  using the available DUK_OPT_xxx flags), define DUK_OPT_HAVE_CUSTOM_H
+ *  and tweak the final flags there.
+ */
+
+#if defined(DUK_OPT_HAVE_CUSTOM_H)
+#include "duk_custom.h"
+#endif
+
+/*
+ *  You may add overriding #define/#undef directives below for
+ *  customization.  You of course cannot un-#include or un-typedef
+ *  anything; these require direct changes above.
+ */
+
+/* __OVERRIDE_DEFINES__ */
+
+/*
+ *  Date provider selection
+ *
+ *  User may define DUK_USE_DATE_GET_NOW() etc directly, in which case we'll
+ *  rely on an external provider.  If this is not done, revert to previous
+ *  behavior and use Unix/Windows built-in provider.
+ */
+
+#if defined(DUK_COMPILING_DUKTAPE)
+
+#if defined(DUK_USE_DATE_GET_NOW)
+/* External provider already defined. */
+#elif defined(DUK_USE_DATE_NOW_GETTIMEOFDAY)
+#define DUK_USE_DATE_GET_NOW(ctx)            duk_bi_date_get_now_gettimeofday((ctx))
+#elif defined(DUK_USE_DATE_NOW_TIME)
+#define DUK_USE_DATE_GET_NOW(ctx)            duk_bi_date_get_now_time((ctx))
+#elif defined(DUK_USE_DATE_NOW_WINDOWS)
+#define DUK_USE_DATE_GET_NOW(ctx)            duk_bi_date_get_now_windows((ctx))
+#else
+#error no provider for DUK_USE_DATE_GET_NOW()
+#endif
+
+#if defined(DUK_USE_DATE_GET_LOCAL_TZOFFSET)
+/* External provider already defined. */
+#elif defined(DUK_USE_DATE_TZO_GMTIME_R) || defined(DUK_USE_DATE_TZO_GMTIME)
+#define DUK_USE_DATE_GET_LOCAL_TZOFFSET(d)   duk_bi_date_get_local_tzoffset_gmtime((d))
+#elif defined(DUK_USE_DATE_TZO_WINDOWS)
+#define DUK_USE_DATE_GET_LOCAL_TZOFFSET(d)   duk_bi_date_get_local_tzoffset_windows((d))
+#else
+#error no provider for DUK_USE_DATE_GET_LOCAL_TZOFFSET()
+#endif
+
+#if defined(DUK_USE_DATE_PARSE_STRING)
+/* External provider already defined. */
+#elif defined(DUK_USE_DATE_PRS_STRPTIME)
+#define DUK_USE_DATE_PARSE_STRING(ctx,str)   duk_bi_date_parse_string_strptime((ctx), (str))
+#elif defined(DUK_USE_DATE_PRS_GETDATE)
+#define DUK_USE_DATE_PARSE_STRING(ctx,str)   duk_bi_date_parse_string_getdate((ctx), (str))
+#else
+/* No provider for DUK_USE_DATE_PARSE_STRING(), fall back to ISO 8601 only. */
+#endif
+
+#if defined(DUK_USE_DATE_FORMAT_STRING)
+/* External provider already defined. */
+#elif defined(DUK_USE_DATE_FMT_STRFTIME)
+#define DUK_USE_DATE_FORMAT_STRING(ctx,parts,tzoffset,flags) \
+	duk_bi_date_format_parts_strftime((ctx), (parts), (tzoffset), (flags))
+#else
+/* No provider for DUK_USE_DATE_FORMAT_STRING(), fall back to ISO 8601 only. */
+#endif
+
+#endif  /* DUK_COMPILING_DUKTAPE */
+
+/*
+ *  Checks for config option consistency (DUK_USE_xxx)
+ */
+
+#if defined(DUK_USE_32BIT_PTRS)
+#error unsupported config option used (option has been removed): DUK_USE_32BIT_PTRS
+#endif
+#if defined(DUK_USE_ALIGN_4)
+#error unsupported config option used (option has been removed): DUK_USE_ALIGN_4
+#endif
+#if defined(DUK_USE_ALIGN_8)
+#error unsupported config option used (option has been removed): DUK_USE_ALIGN_8
+#endif
+#if defined(DUK_USE_BYTEORDER_FORCED)
+#error unsupported config option used (option has been removed): DUK_USE_BYTEORDER_FORCED
+#endif
+#if defined(DUK_USE_DATAPTR_DEC16) && !defined(DUK_USE_DATAPTR16)
+#error config option DUK_USE_DATAPTR_DEC16 requires option DUK_USE_DATAPTR16 (which is missing)
+#endif
+#if defined(DUK_USE_DATAPTR_ENC16) && !defined(DUK_USE_DATAPTR16)
+#error config option DUK_USE_DATAPTR_ENC16 requires option DUK_USE_DATAPTR16 (which is missing)
+#endif
+#if defined(DUK_USE_DEBUGGER_SUPPORT) && !defined(DUK_USE_INTERRUPT_COUNTER)
+#error config option DUK_USE_DEBUGGER_SUPPORT requires option DUK_USE_INTERRUPT_COUNTER (which is missing)
+#endif
+#if defined(DUK_USE_DEEP_C_STACK)
+#error unsupported config option used (option has been removed): DUK_USE_DEEP_C_STACK
+#endif
+#if defined(DUK_USE_DOUBLE_BE)
+#error unsupported config option used (option has been removed): DUK_USE_DOUBLE_BE
+#endif
+#if defined(DUK_USE_DOUBLE_BE) && defined(DUK_USE_DOUBLE_LE)
+#error config option DUK_USE_DOUBLE_BE conflicts with option DUK_USE_DOUBLE_LE (which is also defined)
+#endif
+#if defined(DUK_USE_DOUBLE_BE) && defined(DUK_USE_DOUBLE_ME)
+#error config option DUK_USE_DOUBLE_BE conflicts with option DUK_USE_DOUBLE_ME (which is also defined)
+#endif
+#if defined(DUK_USE_DOUBLE_LE)
+#error unsupported config option used (option has been removed): DUK_USE_DOUBLE_LE
+#endif
+#if defined(DUK_USE_DOUBLE_LE) && defined(DUK_USE_DOUBLE_BE)
+#error config option DUK_USE_DOUBLE_LE conflicts with option DUK_USE_DOUBLE_BE (which is also defined)
+#endif
+#if defined(DUK_USE_DOUBLE_LE) && defined(DUK_USE_DOUBLE_ME)
+#error config option DUK_USE_DOUBLE_LE conflicts with option DUK_USE_DOUBLE_ME (which is also defined)
+#endif
+#if defined(DUK_USE_DOUBLE_ME)
+#error unsupported config option used (option has been removed): DUK_USE_DOUBLE_ME
+#endif
+#if defined(DUK_USE_DOUBLE_ME) && defined(DUK_USE_DOUBLE_LE)
+#error config option DUK_USE_DOUBLE_ME conflicts with option DUK_USE_DOUBLE_LE (which is also defined)
+#endif
+#if defined(DUK_USE_DOUBLE_ME) && defined(DUK_USE_DOUBLE_BE)
+#error config option DUK_USE_DOUBLE_ME conflicts with option DUK_USE_DOUBLE_BE (which is also defined)
+#endif
+#if defined(DUK_USE_DPRINT) && !defined(DUK_USE_DEBUG)
+#error config option DUK_USE_DPRINT requires option DUK_USE_DEBUG (which is missing)
+#endif
+#if defined(DUK_USE_ESBC_MAX_BYTES) && !defined(DUK_USE_ESBC_LIMITS)
+#error config option DUK_USE_ESBC_MAX_BYTES requires option DUK_USE_ESBC_LIMITS (which is missing)
+#endif
+#if defined(DUK_USE_ESBC_MAX_LINENUMBER) && !defined(DUK_USE_ESBC_LIMITS)
+#error config option DUK_USE_ESBC_MAX_LINENUMBER requires option DUK_USE_ESBC_LIMITS (which is missing)
+#endif
+#if defined(DUK_USE_EXEC_TIMEOUT_CHECK) && !defined(DUK_USE_INTERRUPT_COUNTER)
+#error config option DUK_USE_EXEC_TIMEOUT_CHECK requires option DUK_USE_INTERRUPT_COUNTER (which is missing)
+#endif
+#if defined(DUK_USE_EXTSTR_FREE) && !defined(DUK_USE_HSTRING_EXTDATA)
+#error config option DUK_USE_EXTSTR_FREE requires option DUK_USE_HSTRING_EXTDATA (which is missing)
+#endif
+#if defined(DUK_USE_EXTSTR_INTERN_CHECK) && !defined(DUK_USE_HSTRING_EXTDATA)
+#error config option DUK_USE_EXTSTR_INTERN_CHECK requires option DUK_USE_HSTRING_EXTDATA (which is missing)
+#endif
+#if defined(DUK_USE_FULL_TVAL)
+#error unsupported config option used (option has been removed): DUK_USE_FULL_TVAL
+#endif
+#if defined(DUK_USE_FUNCPTR_DEC16) && !defined(DUK_USE_FUNCPTR16)
+#error config option DUK_USE_FUNCPTR_DEC16 requires option DUK_USE_FUNCPTR16 (which is missing)
+#endif
+#if defined(DUK_USE_FUNCPTR_ENC16) && !defined(DUK_USE_FUNCPTR16)
+#error config option DUK_USE_FUNCPTR_ENC16 requires option DUK_USE_FUNCPTR16 (which is missing)
+#endif
+#if defined(DUK_USE_HASHBYTES_UNALIGNED_U32_ACCESS)
+#error unsupported config option used (option has been removed): DUK_USE_HASHBYTES_UNALIGNED_U32_ACCESS
+#endif
+#if defined(DUK_USE_HEAPPTR16) && defined(DUK_USE_DEBUG)
+#error config option DUK_USE_HEAPPTR16 conflicts with option DUK_USE_DEBUG (which is also defined)
+#endif
+#if defined(DUK_USE_HEAPPTR_DEC16) && !defined(DUK_USE_HEAPPTR16)
+#error config option DUK_USE_HEAPPTR_DEC16 requires option DUK_USE_HEAPPTR16 (which is missing)
+#endif
+#if defined(DUK_USE_HEAPPTR_ENC16) && !defined(DUK_USE_HEAPPTR16)
+#error config option DUK_USE_HEAPPTR_ENC16 requires option DUK_USE_HEAPPTR16 (which is missing)
+#endif
+#if defined(DUK_USE_INTEGER_BE)
+#error unsupported config option used (option has been removed): DUK_USE_INTEGER_BE
+#endif
+#if defined(DUK_USE_INTEGER_BE) && defined(DUK_USE_INTEGER_LE)
+#error config option DUK_USE_INTEGER_BE conflicts with option DUK_USE_INTEGER_LE (which is also defined)
+#endif
+#if defined(DUK_USE_INTEGER_BE) && defined(DUK_USE_INTEGER_ME)
+#error config option DUK_USE_INTEGER_BE conflicts with option DUK_USE_INTEGER_ME (which is also defined)
+#endif
+#if defined(DUK_USE_INTEGER_LE)
+#error unsupported config option used (option has been removed): DUK_USE_INTEGER_LE
+#endif
+#if defined(DUK_USE_INTEGER_LE) && defined(DUK_USE_INTEGER_BE)
+#error config option DUK_USE_INTEGER_LE conflicts with option DUK_USE_INTEGER_BE (which is also defined)
+#endif
+#if defined(DUK_USE_INTEGER_LE) && defined(DUK_USE_INTEGER_ME)
+#error config option DUK_USE_INTEGER_LE conflicts with option DUK_USE_INTEGER_ME (which is also defined)
+#endif
+#if defined(DUK_USE_INTEGER_ME)
+#error unsupported config option used (option has been removed): DUK_USE_INTEGER_ME
+#endif
+#if defined(DUK_USE_INTEGER_ME) && defined(DUK_USE_INTEGER_LE)
+#error config option DUK_USE_INTEGER_ME conflicts with option DUK_USE_INTEGER_LE (which is also defined)
+#endif
+#if defined(DUK_USE_INTEGER_ME) && defined(DUK_USE_INTEGER_BE)
+#error config option DUK_USE_INTEGER_ME conflicts with option DUK_USE_INTEGER_BE (which is also defined)
+#endif
+#if defined(DUK_USE_NO_DOUBLE_ALIASING_SELFTEST)
+#error unsupported config option used (option has been removed): DUK_USE_NO_DOUBLE_ALIASING_SELFTEST
+#endif
+#if defined(DUK_USE_PACKED_TVAL_POSSIBLE)
+#error unsupported config option used (option has been removed): DUK_USE_PACKED_TVAL_POSSIBLE
+#endif
+#if defined(DUK_USE_RDTSC)
+#error unsupported config option used (option has been removed): DUK_USE_RDTSC
+#endif
+#if defined(DUK_USE_STRTAB_CHAIN_SIZE) && !defined(DUK_USE_STRTAB_CHAIN)
+#error config option DUK_USE_STRTAB_CHAIN_SIZE requires option DUK_USE_STRTAB_CHAIN (which is missing)
+#endif
+#if defined(DUK_USE_TAILCALL) && defined(DUK_USE_NONSTD_FUNC_CALLER_PROPERTY)
+#error config option DUK_USE_TAILCALL conflicts with option DUK_USE_NONSTD_FUNC_CALLER_PROPERTY (which is also defined)
+#endif
+#if defined(DUK_USE_UNALIGNED_ACCESSES_POSSIBLE)
+#error unsupported config option used (option has been removed): DUK_USE_UNALIGNED_ACCESSES_POSSIBLE
+#endif
+
+#if defined(DUK_USE_CPP_EXCEPTIONS) && !defined(__cplusplus)
+#error DUK_USE_CPP_EXCEPTIONS enabled but not compiling with a C++ compiler
+#endif
+
+/*
+ *  Convert DUK_USE_BYTEORDER, from whatever source, into currently used
+ *  internal defines.  If detection failed, #error out.
+ */
+
+#if defined(DUK_USE_BYTEORDER)
+#if (DUK_USE_BYTEORDER == 1)
+#define DUK_USE_INTEGER_LE
+#define DUK_USE_DOUBLE_LE
+#elif (DUK_USE_BYTEORDER == 2)
+#define DUK_USE_INTEGER_LE  /* integer endianness is little on purpose */
+#define DUK_USE_DOUBLE_ME
+#elif (DUK_USE_BYTEORDER == 3)
+#define DUK_USE_INTEGER_BE
+#define DUK_USE_DOUBLE_BE
+#else
+#error unsupported: byte order invalid
+#endif  /* byte order */
+#else
+#error unsupported: byte order detection failed
+#endif  /* defined(DUK_USE_BYTEORDER) */
+
+#endif  /* DUK_CONFIG_H_INCLUDED */
diff --git a/src/osgEarthDrivers/script_engine_duktape/duktape.c b/src/osgEarthDrivers/script_engine_duktape/duktape.c
index a3a0d7e..dc62df8 100644
--- a/src/osgEarthDrivers/script_engine_duktape/duktape.c
+++ b/src/osgEarthDrivers/script_engine_duktape/duktape.c
@@ -1,8 +1,10 @@
 /*
- *  Single file autogenerated distributable for Duktape 0.11.0.
- *  Git commit 621b545c474dd7a3def7aefed0557b1a825a4578 (v0.10.0-827-g621b545).
+ *  Single source autogenerated distributable for Duktape 1.4.0.
  *
- *  See Duktape AUTHORS.txt and LICENSE.txt for copyright and
+ *  Git commit cad6f595382a0cc1a7e4207794ade5be11b3e397 (v1.4.0).
+ *  Git branch master.
+ *
+ *  See Duktape AUTHORS.rst and LICENSE.txt for copyright and
  *  licensing information.
  */
 
@@ -14,7 +16,7 @@
 *
 *  (http://opensource.org/licenses/MIT)
 *
-*  Copyright (c) 2013-2014 by Duktape authors (see AUTHORS.txt)
+*  Copyright (c) 2013-2016 by Duktape authors (see AUTHORS.rst)
 *
 *  Permission is hereby granted, free of charge, to any person obtaining a copy
 *  of this software and associated documentation files (the "Software"), to deal
@@ -33,9 +35,8 @@
 *  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.
-*
 */
-/* AUTHORS.txt */
+/* AUTHORS.rst */
 /*
 *  ===============
 *  Duktape authors
@@ -54,18 +55,24 @@
 *  Please include an e-mail address, a link to your GitHub profile, or something
 *  similar to allow your contribution to be identified accurately.
 *
-*  The following people have contributed code and agreed to irrevocably license
-*  their contributions under the Duktape ``LICENSE.txt`` (in order of appearance):
+*  The following people have contributed code, website contents, or Wiki contents,
+*  and agreed to irrevocably license their contributions under the Duktape
+*  ``LICENSE.txt`` (in order of appearance):
 *
 *  * Sami Vaarala <sami.vaarala at iki.fi>
 *  * Niki Dobrev
 *  * Andreas \u00d6man <andreas at lonelycoder.com>
+*  * L\u00e1szl\u00f3 Lang\u00f3 <llango.u-szeged at partner.samsung.com>
+*  * Legimet <legimet.calc at gmail.com>
+*  * Karl Skomski <karl at skomski.com>
+*  * Bruce Pascoe <fatcerberus1 at gmail.com>
+*  * Ren\u00e9 Hollander <rene at rene8888.at>
 *
 *  Other contributions
 *  ===================
 *
 *  The following people have contributed something other than code (e.g. reported
-*  bugs, provided ideas, etc; in order of appearance):
+*  bugs, provided ideas, etc; roughly in order of appearance):
 *
 *  * Greg Burns
 *  * Anthony Rabine
@@ -81,7 +88,25 @@
 *  * Rajaran Gaunker (https://github.com/zimbabao)
 *  * Andreas \u00d6man
 *  * Doug Sanden
+*  * Josh Engebretson (https://github.com/JoshEngebretson)
 *  * Remo Eichenberger (https://github.com/remoe)
+*  * Mamod Mehyar (https://github.com/mamod)
+*  * David Demelier (https://github.com/markand)
+*  * Tim Caswell (https://github.com/creationix)
+*  * Mitchell Blank Jr (https://github.com/mitchblank)
+*  * https://github.com/yushli
+*  * Seo Sanghyeon (https://github.com/sanxiyn)
+*  * Han ChoongWoo (https://github.com/tunz)
+*  * Joshua Peek (https://github.com/josh)
+*  * Bruce E. Pascoe (https://github.com/fatcerberus)
+*  * https://github.com/Kelledin
+*  * https://github.com/sstruchtrup
+*  * Michael Drake (https://github.com/tlsa)
+*  * https://github.com/chris-y
+*  * Laurent Zubiaur (https://github.com/lzubiaur)
+*
+*  If you are accidentally missing from this list, send me an e-mail
+*  (``sami.vaarala at iki.fi``) and I'll fix the omission.
 */
 #line 1 "duk_internal.h"
 /*
@@ -113,7 +138,7 @@
 
 /*
  *  User declarations, e.g. prototypes for user functions used by Duktape
- *  macros.  Concretely, if DUK_OPT_PANIC_HANDLER is used and the macro
+ *  macros.  Concretely, if DUK_USE_PANIC_HANDLER is used and the macro
  *  value calls a user function, it needs to be declared for Duktape
  *  compilation to avoid warnings.
  */
@@ -133,24 +158,32 @@ DUK_USE_USER_DECLARE()
 #ifndef DUK_REPLACEMENTS_H_INCLUDED
 #define DUK_REPLACEMENTS_H_INCLUDED
 
-#ifdef DUK_USE_REPL_FPCLASSIFY
-int duk_repl_fpclassify(double x);
+#if defined(DUK_USE_COMPUTED_INFINITY)
+DUK_INTERNAL_DECL double duk_computed_infinity;
+#endif
+
+#if defined(DUK_USE_COMPUTED_NAN)
+DUK_INTERNAL_DECL double duk_computed_nan;
 #endif
 
-#ifdef DUK_USE_REPL_SIGNBIT
-int duk_repl_signbit(double x);
+#if defined(DUK_USE_REPL_FPCLASSIFY)
+DUK_INTERNAL_DECL int duk_repl_fpclassify(double x);
 #endif
 
-#ifdef DUK_USE_REPL_ISFINITE
-int duk_repl_isfinite(double x);
+#if defined(DUK_USE_REPL_SIGNBIT)
+DUK_INTERNAL_DECL int duk_repl_signbit(double x);
 #endif
 
-#ifdef DUK_USE_REPL_ISNAN
-int duk_repl_isnan(double x);
+#if defined(DUK_USE_REPL_ISFINITE)
+DUK_INTERNAL_DECL int duk_repl_isfinite(double x);
 #endif
 
-#ifdef DUK_USE_REPL_ISINF
-int duk_repl_isinf(double x);
+#if defined(DUK_USE_REPL_ISNAN)
+DUK_INTERNAL_DECL int duk_repl_isnan(double x);
+#endif
+
+#if defined(DUK_USE_REPL_ISINF)
+DUK_INTERNAL_DECL int duk_repl_isinf(double x);
 #endif
 
 #endif  /* DUK_REPLACEMENTS_H_INCLUDED */
@@ -168,12 +201,38 @@ int duk_repl_isinf(double x);
 #ifndef DUK_JMPBUF_H_INCLUDED
 #define DUK_JMPBUF_H_INCLUDED
 
+#if !defined(DUK_USE_CPP_EXCEPTIONS)
 struct duk_jmpbuf {
+#if defined(DUK_USE_SETJMP) || defined(DUK_USE_UNDERSCORE_SETJMP)
 	jmp_buf jb;
+#elif defined(DUK_USE_SIGSETJMP)
+	sigjmp_buf jb;
+#else
+#error internal error, no long control transfer provider
+#endif
 };
+#endif
 
 #endif  /* DUK_JMPBUF_H_INCLUDED */
+#line 1 "duk_exception.h"
+/*
+ *  Exception for Duktape internal throws when C++ exceptions are used
+ *  for long control transfers.
+ *
+ *  Doesn't inherit from any exception base class to minimize the chance
+ *  that user code would accidentally catch this exception.
+ */
 
+#ifndef DUK_EXCEPTION_H_INCLUDED
+#define DUK_EXCEPTION_H_INCLUDED
+
+#if defined(DUK_USE_CPP_EXCEPTIONS)
+class duk_internal_exception {
+	/* intentionally empty */
+};
+#endif
+
+#endif  /* DUK_EXCEPTION_H_INCLUDED */
 #line 1 "duk_forwdecl.h"
 /*
  *  Forward declarations for all Duktape structures.
@@ -186,30 +245,39 @@ struct duk_jmpbuf {
  *  Forward declarations
  */
 
+#if defined(DUK_USE_CPP_EXCEPTIONS)
+class duk_internal_exception;
+#else
 struct duk_jmpbuf;
+#endif
 
 /* duk_tval intentionally skipped */
 struct duk_heaphdr;
 struct duk_heaphdr_string;
 struct duk_hstring;
+struct duk_hstring_external;
 struct duk_hobject;
 struct duk_hcompiledfunction;
 struct duk_hnativefunction;
 struct duk_hthread;
+struct duk_hbufferobject;
 struct duk_hbuffer;
 struct duk_hbuffer_fixed;
 struct duk_hbuffer_dynamic;
+struct duk_hbuffer_external;
 
 struct duk_propaccessor;
 union duk_propvalue;
 struct duk_propdesc;
 
 struct duk_heap;
+struct duk_breakpoint;
 
 struct duk_activation;
 struct duk_catcher;
 struct duk_strcache;
 struct duk_ljstate;
+struct duk_strtab_entry;
 
 #ifdef DUK_USE_DEBUG
 struct duk_fixedbuffer;
@@ -217,11 +285,13 @@ struct duk_fixedbuffer;
 
 struct duk_bitdecoder_ctx;
 struct duk_bitencoder_ctx;
+struct duk_bufwriter_ctx;
 
 struct duk_token;
 struct duk_re_token;
 struct duk_lexer_point;
 struct duk_lexer_ctx;
+struct duk_lexer_codepoint;
 
 struct duk_compiler_instr;
 struct duk_compiler_func;
@@ -230,30 +300,39 @@ struct duk_compiler_ctx;
 struct duk_re_matcher_ctx;
 struct duk_re_compiler_ctx;
 
+#if defined(DUK_USE_CPP_EXCEPTIONS)
+/* no typedef */
+#else
 typedef struct duk_jmpbuf duk_jmpbuf;
+#endif
 
 /* duk_tval intentionally skipped */
 typedef struct duk_heaphdr duk_heaphdr;
 typedef struct duk_heaphdr_string duk_heaphdr_string;
 typedef struct duk_hstring duk_hstring;
+typedef struct duk_hstring_external duk_hstring_external;
 typedef struct duk_hobject duk_hobject;
 typedef struct duk_hcompiledfunction duk_hcompiledfunction;
 typedef struct duk_hnativefunction duk_hnativefunction;
+typedef struct duk_hbufferobject duk_hbufferobject;
 typedef struct duk_hthread duk_hthread;
 typedef struct duk_hbuffer duk_hbuffer;
 typedef struct duk_hbuffer_fixed duk_hbuffer_fixed;
 typedef struct duk_hbuffer_dynamic duk_hbuffer_dynamic;
+typedef struct duk_hbuffer_external duk_hbuffer_external;
 
 typedef struct duk_propaccessor duk_propaccessor;
 typedef union duk_propvalue duk_propvalue;
 typedef struct duk_propdesc duk_propdesc;
- 
+
 typedef struct duk_heap duk_heap;
+typedef struct duk_breakpoint duk_breakpoint;
 
 typedef struct duk_activation duk_activation;
 typedef struct duk_catcher duk_catcher;
 typedef struct duk_strcache duk_strcache;
 typedef struct duk_ljstate duk_ljstate;
+typedef struct duk_strtab_entry duk_strtab_entry;
 
 #ifdef DUK_USE_DEBUG
 typedef struct duk_fixedbuffer duk_fixedbuffer;
@@ -261,11 +340,13 @@ typedef struct duk_fixedbuffer duk_fixedbuffer;
 
 typedef struct duk_bitdecoder_ctx duk_bitdecoder_ctx;
 typedef struct duk_bitencoder_ctx duk_bitencoder_ctx;
+typedef struct duk_bufwriter_ctx duk_bufwriter_ctx;
 
 typedef struct duk_token duk_token;
 typedef struct duk_re_token duk_re_token;
 typedef struct duk_lexer_point duk_lexer_point;
 typedef struct duk_lexer_ctx duk_lexer_ctx;
+typedef struct duk_lexer_codepoint duk_lexer_codepoint;
 
 typedef struct duk_compiler_instr duk_compiler_instr;
 typedef struct duk_compiler_func duk_compiler_func;
@@ -273,7 +354,7 @@ typedef struct duk_compiler_ctx duk_compiler_ctx;
 
 typedef struct duk_re_matcher_ctx duk_re_matcher_ctx;
 typedef struct duk_re_compiler_ctx duk_re_compiler_ctx;
-	
+
 #endif  /* DUK_FORWDECL_H_INCLUDED */
 #line 1 "duk_builtins.h"
 /*
@@ -284,347 +365,427 @@ typedef struct duk_re_compiler_ctx duk_re_compiler_ctx;
 #define DUK_BUILTINS_H_INCLUDED
 
 #if defined(DUK_USE_DOUBLE_LE)
-extern const duk_uint8_t duk_strings_data[];
+#if !defined(DUK_SINGLE_FILE)
+DUK_INTERNAL_DECL const duk_uint8_t duk_strings_data[2624];
+#endif  /* !DUK_SINGLE_FILE */
 
-#define DUK_STRDATA_DATA_LENGTH                                       1931
+#define DUK_STRDATA_DATA_LENGTH                                       2624
 #define DUK_STRDATA_MAX_STRLEN                                        24
 
 #define DUK_STRIDX_UC_LOGGER                                          0                              /* 'Logger' */
 #define DUK_STRIDX_UC_THREAD                                          1                              /* 'Thread' */
 #define DUK_STRIDX_UC_POINTER                                         2                              /* 'Pointer' */
-#define DUK_STRIDX_UC_BUFFER                                          3                              /* 'Buffer' */
-#define DUK_STRIDX_DEC_ENV                                            4                              /* 'DecEnv' */
-#define DUK_STRIDX_OBJ_ENV                                            5                              /* 'ObjEnv' */
-#define DUK_STRIDX_EMPTY_STRING                                       6                              /* '' */
-#define DUK_STRIDX_GLOBAL                                             7                              /* 'global' */
-#define DUK_STRIDX_UC_ARGUMENTS                                       8                              /* 'Arguments' */
-#define DUK_STRIDX_JSON                                               9                              /* 'JSON' */
-#define DUK_STRIDX_MATH                                               10                             /* 'Math' */
-#define DUK_STRIDX_UC_ERROR                                           11                             /* 'Error' */
-#define DUK_STRIDX_REG_EXP                                            12                             /* 'RegExp' */
-#define DUK_STRIDX_DATE                                               13                             /* 'Date' */
-#define DUK_STRIDX_UC_NUMBER                                          14                             /* 'Number' */
-#define DUK_STRIDX_UC_BOOLEAN                                         15                             /* 'Boolean' */
-#define DUK_STRIDX_UC_STRING                                          16                             /* 'String' */
-#define DUK_STRIDX_ARRAY                                              17                             /* 'Array' */
-#define DUK_STRIDX_UC_FUNCTION                                        18                             /* 'Function' */
-#define DUK_STRIDX_UC_OBJECT                                          19                             /* 'Object' */
-#define DUK_STRIDX_UC_NULL                                            20                             /* 'Null' */
-#define DUK_STRIDX_UC_UNDEFINED                                       21                             /* 'Undefined' */
-#define DUK_STRIDX_JSON_EXT_FUNCTION2                                 22                             /* '{_func:true}' */
-#define DUK_STRIDX_JSON_EXT_FUNCTION1                                 23                             /* '{"_func":true}' */
-#define DUK_STRIDX_JSON_EXT_NEGINF                                    24                             /* '{"_ninf":true}' */
-#define DUK_STRIDX_JSON_EXT_POSINF                                    25                             /* '{"_inf":true}' */
-#define DUK_STRIDX_JSON_EXT_NAN                                       26                             /* '{"_nan":true}' */
-#define DUK_STRIDX_JSON_EXT_UNDEFINED                                 27                             /* '{"_undef":true}' */
-#define DUK_STRIDX_TO_LOG_STRING                                      28                             /* 'toLogString' */
-#define DUK_STRIDX_CLOG                                               29                             /* 'clog' */
-#define DUK_STRIDX_LC_L                                               30                             /* 'l' */
-#define DUK_STRIDX_LC_N                                               31                             /* 'n' */
-#define DUK_STRIDX_LC_FATAL                                           32                             /* 'fatal' */
-#define DUK_STRIDX_LC_ERROR                                           33                             /* 'error' */
-#define DUK_STRIDX_LC_WARN                                            34                             /* 'warn' */
-#define DUK_STRIDX_LC_DEBUG                                           35                             /* 'debug' */
-#define DUK_STRIDX_LC_TRACE                                           36                             /* 'trace' */
-#define DUK_STRIDX_RAW                                                37                             /* 'raw' */
-#define DUK_STRIDX_FMT                                                38                             /* 'fmt' */
-#define DUK_STRIDX_CURRENT                                            39                             /* 'current' */
-#define DUK_STRIDX_RESUME                                             40                             /* 'resume' */
-#define DUK_STRIDX_COMPACT                                            41                             /* 'compact' */
-#define DUK_STRIDX_JC                                                 42                             /* 'jc' */
-#define DUK_STRIDX_JX                                                 43                             /* 'jx' */
-#define DUK_STRIDX_BASE64                                             44                             /* 'base64' */
-#define DUK_STRIDX_HEX                                                45                             /* 'hex' */
-#define DUK_STRIDX_DEC                                                46                             /* 'dec' */
-#define DUK_STRIDX_ENC                                                47                             /* 'enc' */
-#define DUK_STRIDX_FIN                                                48                             /* 'fin' */
-#define DUK_STRIDX_GC                                                 49                             /* 'gc' */
-#define DUK_STRIDX_ACT                                                50                             /* 'act' */
-#define DUK_STRIDX_LC_INFO                                            51                             /* 'info' */
-#define DUK_STRIDX_VERSION                                            52                             /* 'version' */
-#define DUK_STRIDX_ENV                                                53                             /* 'env' */
-#define DUK_STRIDX_MOD_LOADED                                         54                             /* 'modLoaded' */
-#define DUK_STRIDX_MOD_SEARCH                                         55                             /* 'modSearch' */
-#define DUK_STRIDX_ERR_THROW                                          56                             /* 'errThrow' */
-#define DUK_STRIDX_ERR_CREATE                                         57                             /* 'errCreate' */
-#define DUK_STRIDX_COMPILE                                            58                             /* 'compile' */
-#define DUK_STRIDX_INT_REGBASE                                        59                             /* '\x00regbase' */
-#define DUK_STRIDX_INT_THREAD                                         60                             /* '\x00thread' */
-#define DUK_STRIDX_INT_HANDLER                                        61                             /* '\x00handler' */
-#define DUK_STRIDX_INT_FINALIZER                                      62                             /* '\x00finalizer' */
-#define DUK_STRIDX_INT_CALLEE                                         63                             /* '\x00callee' */
-#define DUK_STRIDX_INT_MAP                                            64                             /* '\x00map' */
-#define DUK_STRIDX_INT_ARGS                                           65                             /* '\x00args' */
-#define DUK_STRIDX_INT_THIS                                           66                             /* '\x00this' */
-#define DUK_STRIDX_INT_PC2LINE                                        67                             /* '\x00pc2line' */
-#define DUK_STRIDX_INT_SOURCE                                         68                             /* '\x00source' */
-#define DUK_STRIDX_INT_VARENV                                         69                             /* '\x00varenv' */
-#define DUK_STRIDX_INT_LEXENV                                         70                             /* '\x00lexenv' */
-#define DUK_STRIDX_INT_VARMAP                                         71                             /* '\x00varmap' */
-#define DUK_STRIDX_INT_FORMALS                                        72                             /* '\x00formals' */
-#define DUK_STRIDX_INT_BYTECODE                                       73                             /* '\x00bytecode' */
-#define DUK_STRIDX_INT_NEXT                                           74                             /* '\x00next' */
-#define DUK_STRIDX_INT_TARGET                                         75                             /* '\x00target' */
-#define DUK_STRIDX_INT_VALUE                                          76                             /* '\x00value' */
-#define DUK_STRIDX_LC_POINTER                                         77                             /* 'pointer' */
-#define DUK_STRIDX_LC_BUFFER                                          78                             /* 'buffer' */
-#define DUK_STRIDX_TRACEDATA                                          79                             /* 'tracedata' */
-#define DUK_STRIDX_LINE_NUMBER                                        80                             /* 'lineNumber' */
-#define DUK_STRIDX_FILE_NAME                                          81                             /* 'fileName' */
-#define DUK_STRIDX_PC                                                 82                             /* 'pc' */
-#define DUK_STRIDX_STACK                                              83                             /* 'stack' */
-#define DUK_STRIDX_THROW_TYPE_ERROR                                   84                             /* 'ThrowTypeError' */
-#define DUK_STRIDX_DUKTAPE                                            85                             /* 'Duktape' */
-#define DUK_STRIDX_ID                                                 86                             /* 'id' */
-#define DUK_STRIDX_REQUIRE                                            87                             /* 'require' */
-#define DUK_STRIDX___PROTO__                                          88                             /* '__proto__' */
-#define DUK_STRIDX_SET_PROTOTYPE_OF                                   89                             /* 'setPrototypeOf' */
-#define DUK_STRIDX_OWN_KEYS                                           90                             /* 'ownKeys' */
-#define DUK_STRIDX_ENUMERATE                                          91                             /* 'enumerate' */
-#define DUK_STRIDX_DELETE_PROPERTY                                    92                             /* 'deleteProperty' */
-#define DUK_STRIDX_HAS                                                93                             /* 'has' */
-#define DUK_STRIDX_PROXY                                              94                             /* 'Proxy' */
-#define DUK_STRIDX_CALLEE                                             95                             /* 'callee' */
-#define DUK_STRIDX_INVALID_DATE                                       96                             /* 'Invalid Date' */
-#define DUK_STRIDX_BRACKETED_ELLIPSIS                                 97                             /* '[...]' */
-#define DUK_STRIDX_NEWLINE_TAB                                        98                             /* '\n\t' */
-#define DUK_STRIDX_SPACE                                              99                             /* ' ' */
-#define DUK_STRIDX_COMMA                                              100                            /* ',' */
-#define DUK_STRIDX_MINUS_ZERO                                         101                            /* '-0' */
-#define DUK_STRIDX_PLUS_ZERO                                          102                            /* '+0' */
-#define DUK_STRIDX_ZERO                                               103                            /* '0' */
-#define DUK_STRIDX_MINUS_INFINITY                                     104                            /* '-Infinity' */
-#define DUK_STRIDX_PLUS_INFINITY                                      105                            /* '+Infinity' */
-#define DUK_STRIDX_INFINITY                                           106                            /* 'Infinity' */
-#define DUK_STRIDX_LC_OBJECT                                          107                            /* 'object' */
-#define DUK_STRIDX_LC_STRING                                          108                            /* 'string' */
-#define DUK_STRIDX_LC_NUMBER                                          109                            /* 'number' */
-#define DUK_STRIDX_LC_BOOLEAN                                         110                            /* 'boolean' */
-#define DUK_STRIDX_LC_UNDEFINED                                       111                            /* 'undefined' */
-#define DUK_STRIDX_STRINGIFY                                          112                            /* 'stringify' */
-#define DUK_STRIDX_TAN                                                113                            /* 'tan' */
-#define DUK_STRIDX_SQRT                                               114                            /* 'sqrt' */
-#define DUK_STRIDX_SIN                                                115                            /* 'sin' */
-#define DUK_STRIDX_ROUND                                              116                            /* 'round' */
-#define DUK_STRIDX_RANDOM                                             117                            /* 'random' */
-#define DUK_STRIDX_POW                                                118                            /* 'pow' */
-#define DUK_STRIDX_MIN                                                119                            /* 'min' */
-#define DUK_STRIDX_MAX                                                120                            /* 'max' */
-#define DUK_STRIDX_LOG                                                121                            /* 'log' */
-#define DUK_STRIDX_FLOOR                                              122                            /* 'floor' */
-#define DUK_STRIDX_EXP                                                123                            /* 'exp' */
-#define DUK_STRIDX_COS                                                124                            /* 'cos' */
-#define DUK_STRIDX_CEIL                                               125                            /* 'ceil' */
-#define DUK_STRIDX_ATAN2                                              126                            /* 'atan2' */
-#define DUK_STRIDX_ATAN                                               127                            /* 'atan' */
-#define DUK_STRIDX_ASIN                                               128                            /* 'asin' */
-#define DUK_STRIDX_ACOS                                               129                            /* 'acos' */
-#define DUK_STRIDX_ABS                                                130                            /* 'abs' */
-#define DUK_STRIDX_SQRT2                                              131                            /* 'SQRT2' */
-#define DUK_STRIDX_SQRT1_2                                            132                            /* 'SQRT1_2' */
-#define DUK_STRIDX_PI                                                 133                            /* 'PI' */
-#define DUK_STRIDX_LOG10E                                             134                            /* 'LOG10E' */
-#define DUK_STRIDX_LOG2E                                              135                            /* 'LOG2E' */
-#define DUK_STRIDX_LN2                                                136                            /* 'LN2' */
-#define DUK_STRIDX_LN10                                               137                            /* 'LN10' */
-#define DUK_STRIDX_E                                                  138                            /* 'E' */
-#define DUK_STRIDX_MESSAGE                                            139                            /* 'message' */
-#define DUK_STRIDX_NAME                                               140                            /* 'name' */
-#define DUK_STRIDX_INPUT                                              141                            /* 'input' */
-#define DUK_STRIDX_INDEX                                              142                            /* 'index' */
-#define DUK_STRIDX_ESCAPED_EMPTY_REGEXP                               143                            /* '(?:)' */
-#define DUK_STRIDX_LAST_INDEX                                         144                            /* 'lastIndex' */
-#define DUK_STRIDX_MULTILINE                                          145                            /* 'multiline' */
-#define DUK_STRIDX_IGNORE_CASE                                        146                            /* 'ignoreCase' */
-#define DUK_STRIDX_SOURCE                                             147                            /* 'source' */
-#define DUK_STRIDX_TEST                                               148                            /* 'test' */
-#define DUK_STRIDX_EXEC                                               149                            /* 'exec' */
-#define DUK_STRIDX_TO_GMT_STRING                                      150                            /* 'toGMTString' */
-#define DUK_STRIDX_SET_YEAR                                           151                            /* 'setYear' */
-#define DUK_STRIDX_GET_YEAR                                           152                            /* 'getYear' */
-#define DUK_STRIDX_TO_JSON                                            153                            /* 'toJSON' */
-#define DUK_STRIDX_TO_ISO_STRING                                      154                            /* 'toISOString' */
-#define DUK_STRIDX_TO_UTC_STRING                                      155                            /* 'toUTCString' */
-#define DUK_STRIDX_SET_UTC_FULL_YEAR                                  156                            /* 'setUTCFullYear' */
-#define DUK_STRIDX_SET_FULL_YEAR                                      157                            /* 'setFullYear' */
-#define DUK_STRIDX_SET_UTC_MONTH                                      158                            /* 'setUTCMonth' */
-#define DUK_STRIDX_SET_MONTH                                          159                            /* 'setMonth' */
-#define DUK_STRIDX_SET_UTC_DATE                                       160                            /* 'setUTCDate' */
-#define DUK_STRIDX_SET_DATE                                           161                            /* 'setDate' */
-#define DUK_STRIDX_SET_UTC_HOURS                                      162                            /* 'setUTCHours' */
-#define DUK_STRIDX_SET_HOURS                                          163                            /* 'setHours' */
-#define DUK_STRIDX_SET_UTC_MINUTES                                    164                            /* 'setUTCMinutes' */
-#define DUK_STRIDX_SET_MINUTES                                        165                            /* 'setMinutes' */
-#define DUK_STRIDX_SET_UTC_SECONDS                                    166                            /* 'setUTCSeconds' */
-#define DUK_STRIDX_SET_SECONDS                                        167                            /* 'setSeconds' */
-#define DUK_STRIDX_SET_UTC_MILLISECONDS                               168                            /* 'setUTCMilliseconds' */
-#define DUK_STRIDX_SET_MILLISECONDS                                   169                            /* 'setMilliseconds' */
-#define DUK_STRIDX_SET_TIME                                           170                            /* 'setTime' */
-#define DUK_STRIDX_GET_TIMEZONE_OFFSET                                171                            /* 'getTimezoneOffset' */
-#define DUK_STRIDX_GET_UTC_MILLISECONDS                               172                            /* 'getUTCMilliseconds' */
-#define DUK_STRIDX_GET_MILLISECONDS                                   173                            /* 'getMilliseconds' */
-#define DUK_STRIDX_GET_UTC_SECONDS                                    174                            /* 'getUTCSeconds' */
-#define DUK_STRIDX_GET_SECONDS                                        175                            /* 'getSeconds' */
-#define DUK_STRIDX_GET_UTC_MINUTES                                    176                            /* 'getUTCMinutes' */
-#define DUK_STRIDX_GET_MINUTES                                        177                            /* 'getMinutes' */
-#define DUK_STRIDX_GET_UTC_HOURS                                      178                            /* 'getUTCHours' */
-#define DUK_STRIDX_GET_HOURS                                          179                            /* 'getHours' */
-#define DUK_STRIDX_GET_UTC_DAY                                        180                            /* 'getUTCDay' */
-#define DUK_STRIDX_GET_DAY                                            181                            /* 'getDay' */
-#define DUK_STRIDX_GET_UTC_DATE                                       182                            /* 'getUTCDate' */
-#define DUK_STRIDX_GET_DATE                                           183                            /* 'getDate' */
-#define DUK_STRIDX_GET_UTC_MONTH                                      184                            /* 'getUTCMonth' */
-#define DUK_STRIDX_GET_MONTH                                          185                            /* 'getMonth' */
-#define DUK_STRIDX_GET_UTC_FULL_YEAR                                  186                            /* 'getUTCFullYear' */
-#define DUK_STRIDX_GET_FULL_YEAR                                      187                            /* 'getFullYear' */
-#define DUK_STRIDX_GET_TIME                                           188                            /* 'getTime' */
-#define DUK_STRIDX_TO_LOCALE_TIME_STRING                              189                            /* 'toLocaleTimeString' */
-#define DUK_STRIDX_TO_LOCALE_DATE_STRING                              190                            /* 'toLocaleDateString' */
-#define DUK_STRIDX_TO_TIME_STRING                                     191                            /* 'toTimeString' */
-#define DUK_STRIDX_TO_DATE_STRING                                     192                            /* 'toDateString' */
-#define DUK_STRIDX_NOW                                                193                            /* 'now' */
-#define DUK_STRIDX_UTC                                                194                            /* 'UTC' */
-#define DUK_STRIDX_PARSE                                              195                            /* 'parse' */
-#define DUK_STRIDX_TO_PRECISION                                       196                            /* 'toPrecision' */
-#define DUK_STRIDX_TO_EXPONENTIAL                                     197                            /* 'toExponential' */
-#define DUK_STRIDX_TO_FIXED                                           198                            /* 'toFixed' */
-#define DUK_STRIDX_POSITIVE_INFINITY                                  199                            /* 'POSITIVE_INFINITY' */
-#define DUK_STRIDX_NEGATIVE_INFINITY                                  200                            /* 'NEGATIVE_INFINITY' */
-#define DUK_STRIDX_NAN                                                201                            /* 'NaN' */
-#define DUK_STRIDX_MIN_VALUE                                          202                            /* 'MIN_VALUE' */
-#define DUK_STRIDX_MAX_VALUE                                          203                            /* 'MAX_VALUE' */
-#define DUK_STRIDX_SUBSTR                                             204                            /* 'substr' */
-#define DUK_STRIDX_TRIM                                               205                            /* 'trim' */
-#define DUK_STRIDX_TO_LOCALE_UPPER_CASE                               206                            /* 'toLocaleUpperCase' */
-#define DUK_STRIDX_TO_UPPER_CASE                                      207                            /* 'toUpperCase' */
-#define DUK_STRIDX_TO_LOCALE_LOWER_CASE                               208                            /* 'toLocaleLowerCase' */
-#define DUK_STRIDX_TO_LOWER_CASE                                      209                            /* 'toLowerCase' */
-#define DUK_STRIDX_SUBSTRING                                          210                            /* 'substring' */
-#define DUK_STRIDX_SPLIT                                              211                            /* 'split' */
-#define DUK_STRIDX_SEARCH                                             212                            /* 'search' */
-#define DUK_STRIDX_REPLACE                                            213                            /* 'replace' */
-#define DUK_STRIDX_MATCH                                              214                            /* 'match' */
-#define DUK_STRIDX_LOCALE_COMPARE                                     215                            /* 'localeCompare' */
-#define DUK_STRIDX_CHAR_CODE_AT                                       216                            /* 'charCodeAt' */
-#define DUK_STRIDX_CHAR_AT                                            217                            /* 'charAt' */
-#define DUK_STRIDX_FROM_CHAR_CODE                                     218                            /* 'fromCharCode' */
-#define DUK_STRIDX_REDUCE_RIGHT                                       219                            /* 'reduceRight' */
-#define DUK_STRIDX_REDUCE                                             220                            /* 'reduce' */
-#define DUK_STRIDX_FILTER                                             221                            /* 'filter' */
-#define DUK_STRIDX_MAP                                                222                            /* 'map' */
-#define DUK_STRIDX_FOR_EACH                                           223                            /* 'forEach' */
-#define DUK_STRIDX_SOME                                               224                            /* 'some' */
-#define DUK_STRIDX_EVERY                                              225                            /* 'every' */
-#define DUK_STRIDX_LAST_INDEX_OF                                      226                            /* 'lastIndexOf' */
-#define DUK_STRIDX_INDEX_OF                                           227                            /* 'indexOf' */
-#define DUK_STRIDX_UNSHIFT                                            228                            /* 'unshift' */
-#define DUK_STRIDX_SPLICE                                             229                            /* 'splice' */
-#define DUK_STRIDX_SORT                                               230                            /* 'sort' */
-#define DUK_STRIDX_SLICE                                              231                            /* 'slice' */
-#define DUK_STRIDX_SHIFT                                              232                            /* 'shift' */
-#define DUK_STRIDX_REVERSE                                            233                            /* 'reverse' */
-#define DUK_STRIDX_PUSH                                               234                            /* 'push' */
-#define DUK_STRIDX_POP                                                235                            /* 'pop' */
-#define DUK_STRIDX_JOIN                                               236                            /* 'join' */
-#define DUK_STRIDX_CONCAT                                             237                            /* 'concat' */
-#define DUK_STRIDX_IS_ARRAY                                           238                            /* 'isArray' */
-#define DUK_STRIDX_LC_ARGUMENTS                                       239                            /* 'arguments' */
-#define DUK_STRIDX_CALLER                                             240                            /* 'caller' */
-#define DUK_STRIDX_BIND                                               241                            /* 'bind' */
-#define DUK_STRIDX_CALL                                               242                            /* 'call' */
-#define DUK_STRIDX_APPLY                                              243                            /* 'apply' */
-#define DUK_STRIDX_PROPERTY_IS_ENUMERABLE                             244                            /* 'propertyIsEnumerable' */
-#define DUK_STRIDX_IS_PROTOTYPE_OF                                    245                            /* 'isPrototypeOf' */
-#define DUK_STRIDX_HAS_OWN_PROPERTY                                   246                            /* 'hasOwnProperty' */
-#define DUK_STRIDX_VALUE_OF                                           247                            /* 'valueOf' */
-#define DUK_STRIDX_TO_LOCALE_STRING                                   248                            /* 'toLocaleString' */
-#define DUK_STRIDX_TO_STRING                                          249                            /* 'toString' */
-#define DUK_STRIDX_CONSTRUCTOR                                        250                            /* 'constructor' */
-#define DUK_STRIDX_SET                                                251                            /* 'set' */
-#define DUK_STRIDX_GET                                                252                            /* 'get' */
-#define DUK_STRIDX_ENUMERABLE                                         253                            /* 'enumerable' */
-#define DUK_STRIDX_CONFIGURABLE                                       254                            /* 'configurable' */
-#define DUK_STRIDX_WRITABLE                                           255                            /* 'writable' */
-#define DUK_STRIDX_VALUE                                              256                            /* 'value' */
-#define DUK_STRIDX_KEYS                                               257                            /* 'keys' */
-#define DUK_STRIDX_IS_EXTENSIBLE                                      258                            /* 'isExtensible' */
-#define DUK_STRIDX_IS_FROZEN                                          259                            /* 'isFrozen' */
-#define DUK_STRIDX_IS_SEALED                                          260                            /* 'isSealed' */
-#define DUK_STRIDX_PREVENT_EXTENSIONS                                 261                            /* 'preventExtensions' */
-#define DUK_STRIDX_FREEZE                                             262                            /* 'freeze' */
-#define DUK_STRIDX_SEAL                                               263                            /* 'seal' */
-#define DUK_STRIDX_DEFINE_PROPERTIES                                  264                            /* 'defineProperties' */
-#define DUK_STRIDX_DEFINE_PROPERTY                                    265                            /* 'defineProperty' */
-#define DUK_STRIDX_CREATE                                             266                            /* 'create' */
-#define DUK_STRIDX_GET_OWN_PROPERTY_NAMES                             267                            /* 'getOwnPropertyNames' */
-#define DUK_STRIDX_GET_OWN_PROPERTY_DESCRIPTOR                        268                            /* 'getOwnPropertyDescriptor' */
-#define DUK_STRIDX_GET_PROTOTYPE_OF                                   269                            /* 'getPrototypeOf' */
-#define DUK_STRIDX_PROTOTYPE                                          270                            /* 'prototype' */
-#define DUK_STRIDX_LENGTH                                             271                            /* 'length' */
-#define DUK_STRIDX_ALERT                                              272                            /* 'alert' */
-#define DUK_STRIDX_PRINT                                              273                            /* 'print' */
-#define DUK_STRIDX_UNESCAPE                                           274                            /* 'unescape' */
-#define DUK_STRIDX_ESCAPE                                             275                            /* 'escape' */
-#define DUK_STRIDX_ENCODE_URI_COMPONENT                               276                            /* 'encodeURIComponent' */
-#define DUK_STRIDX_ENCODE_URI                                         277                            /* 'encodeURI' */
-#define DUK_STRIDX_DECODE_URI_COMPONENT                               278                            /* 'decodeURIComponent' */
-#define DUK_STRIDX_DECODE_URI                                         279                            /* 'decodeURI' */
-#define DUK_STRIDX_IS_FINITE                                          280                            /* 'isFinite' */
-#define DUK_STRIDX_IS_NAN                                             281                            /* 'isNaN' */
-#define DUK_STRIDX_PARSE_FLOAT                                        282                            /* 'parseFloat' */
-#define DUK_STRIDX_PARSE_INT                                          283                            /* 'parseInt' */
-#define DUK_STRIDX_EVAL                                               284                            /* 'eval' */
-#define DUK_STRIDX_URI_ERROR                                          285                            /* 'URIError' */
-#define DUK_STRIDX_TYPE_ERROR                                         286                            /* 'TypeError' */
-#define DUK_STRIDX_SYNTAX_ERROR                                       287                            /* 'SyntaxError' */
-#define DUK_STRIDX_REFERENCE_ERROR                                    288                            /* 'ReferenceError' */
-#define DUK_STRIDX_RANGE_ERROR                                        289                            /* 'RangeError' */
-#define DUK_STRIDX_EVAL_ERROR                                         290                            /* 'EvalError' */
-#define DUK_STRIDX_BREAK                                              291                            /* 'break' */
-#define DUK_STRIDX_CASE                                               292                            /* 'case' */
-#define DUK_STRIDX_CATCH                                              293                            /* 'catch' */
-#define DUK_STRIDX_CONTINUE                                           294                            /* 'continue' */
-#define DUK_STRIDX_DEBUGGER                                           295                            /* 'debugger' */
-#define DUK_STRIDX_DEFAULT                                            296                            /* 'default' */
-#define DUK_STRIDX_DELETE                                             297                            /* 'delete' */
-#define DUK_STRIDX_DO                                                 298                            /* 'do' */
-#define DUK_STRIDX_ELSE                                               299                            /* 'else' */
-#define DUK_STRIDX_FINALLY                                            300                            /* 'finally' */
-#define DUK_STRIDX_FOR                                                301                            /* 'for' */
-#define DUK_STRIDX_LC_FUNCTION                                        302                            /* 'function' */
-#define DUK_STRIDX_IF                                                 303                            /* 'if' */
-#define DUK_STRIDX_IN                                                 304                            /* 'in' */
-#define DUK_STRIDX_INSTANCEOF                                         305                            /* 'instanceof' */
-#define DUK_STRIDX_NEW                                                306                            /* 'new' */
-#define DUK_STRIDX_RETURN                                             307                            /* 'return' */
-#define DUK_STRIDX_SWITCH                                             308                            /* 'switch' */
-#define DUK_STRIDX_THIS                                               309                            /* 'this' */
-#define DUK_STRIDX_THROW                                              310                            /* 'throw' */
-#define DUK_STRIDX_TRY                                                311                            /* 'try' */
-#define DUK_STRIDX_TYPEOF                                             312                            /* 'typeof' */
-#define DUK_STRIDX_VAR                                                313                            /* 'var' */
-#define DUK_STRIDX_VOID                                               314                            /* 'void' */
-#define DUK_STRIDX_WHILE                                              315                            /* 'while' */
-#define DUK_STRIDX_WITH                                               316                            /* 'with' */
-#define DUK_STRIDX_CLASS                                              317                            /* 'class' */
-#define DUK_STRIDX_CONST                                              318                            /* 'const' */
-#define DUK_STRIDX_ENUM                                               319                            /* 'enum' */
-#define DUK_STRIDX_EXPORT                                             320                            /* 'export' */
-#define DUK_STRIDX_EXTENDS                                            321                            /* 'extends' */
-#define DUK_STRIDX_IMPORT                                             322                            /* 'import' */
-#define DUK_STRIDX_SUPER                                              323                            /* 'super' */
-#define DUK_STRIDX_LC_NULL                                            324                            /* 'null' */
-#define DUK_STRIDX_TRUE                                               325                            /* 'true' */
-#define DUK_STRIDX_FALSE                                              326                            /* 'false' */
-#define DUK_STRIDX_IMPLEMENTS                                         327                            /* 'implements' */
-#define DUK_STRIDX_INTERFACE                                          328                            /* 'interface' */
-#define DUK_STRIDX_LET                                                329                            /* 'let' */
-#define DUK_STRIDX_PACKAGE                                            330                            /* 'package' */
-#define DUK_STRIDX_PRIVATE                                            331                            /* 'private' */
-#define DUK_STRIDX_PROTECTED                                          332                            /* 'protected' */
-#define DUK_STRIDX_PUBLIC                                             333                            /* 'public' */
-#define DUK_STRIDX_STATIC                                             334                            /* 'static' */
-#define DUK_STRIDX_YIELD                                              335                            /* 'yield' */
+#define DUK_STRIDX_DEC_ENV                                            3                              /* 'DecEnv' */
+#define DUK_STRIDX_OBJ_ENV                                            4                              /* 'ObjEnv' */
+#define DUK_STRIDX_FLOAT64_ARRAY                                      5                              /* 'Float64Array' */
+#define DUK_STRIDX_FLOAT32_ARRAY                                      6                              /* 'Float32Array' */
+#define DUK_STRIDX_UINT32_ARRAY                                       7                              /* 'Uint32Array' */
+#define DUK_STRIDX_INT32_ARRAY                                        8                              /* 'Int32Array' */
+#define DUK_STRIDX_UINT16_ARRAY                                       9                              /* 'Uint16Array' */
+#define DUK_STRIDX_INT16_ARRAY                                        10                             /* 'Int16Array' */
+#define DUK_STRIDX_UINT8_CLAMPED_ARRAY                                11                             /* 'Uint8ClampedArray' */
+#define DUK_STRIDX_UINT8_ARRAY                                        12                             /* 'Uint8Array' */
+#define DUK_STRIDX_INT8_ARRAY                                         13                             /* 'Int8Array' */
+#define DUK_STRIDX_DATA_VIEW                                          14                             /* 'DataView' */
+#define DUK_STRIDX_ARRAY_BUFFER                                       15                             /* 'ArrayBuffer' */
+#define DUK_STRIDX_UC_BUFFER                                          16                             /* 'Buffer' */
+#define DUK_STRIDX_EMPTY_STRING                                       17                             /* '' */
+#define DUK_STRIDX_GLOBAL                                             18                             /* 'global' */
+#define DUK_STRIDX_UC_ARGUMENTS                                       19                             /* 'Arguments' */
+#define DUK_STRIDX_JSON                                               20                             /* 'JSON' */
+#define DUK_STRIDX_MATH                                               21                             /* 'Math' */
+#define DUK_STRIDX_UC_ERROR                                           22                             /* 'Error' */
+#define DUK_STRIDX_REG_EXP                                            23                             /* 'RegExp' */
+#define DUK_STRIDX_DATE                                               24                             /* 'Date' */
+#define DUK_STRIDX_UC_NUMBER                                          25                             /* 'Number' */
+#define DUK_STRIDX_UC_BOOLEAN                                         26                             /* 'Boolean' */
+#define DUK_STRIDX_UC_STRING                                          27                             /* 'String' */
+#define DUK_STRIDX_ARRAY                                              28                             /* 'Array' */
+#define DUK_STRIDX_UC_FUNCTION                                        29                             /* 'Function' */
+#define DUK_STRIDX_UC_OBJECT                                          30                             /* 'Object' */
+#define DUK_STRIDX_UC_NULL                                            31                             /* 'Null' */
+#define DUK_STRIDX_UC_UNDEFINED                                       32                             /* 'Undefined' */
+#define DUK_STRIDX_JSON_EXT_FUNCTION2                                 33                             /* '{_func:true}' */
+#define DUK_STRIDX_JSON_EXT_FUNCTION1                                 34                             /* '{"_func":true}' */
+#define DUK_STRIDX_JSON_EXT_NEGINF                                    35                             /* '{"_ninf":true}' */
+#define DUK_STRIDX_JSON_EXT_POSINF                                    36                             /* '{"_inf":true}' */
+#define DUK_STRIDX_JSON_EXT_NAN                                       37                             /* '{"_nan":true}' */
+#define DUK_STRIDX_JSON_EXT_UNDEFINED                                 38                             /* '{"_undef":true}' */
+#define DUK_STRIDX_TO_LOG_STRING                                      39                             /* 'toLogString' */
+#define DUK_STRIDX_CLOG                                               40                             /* 'clog' */
+#define DUK_STRIDX_LC_L                                               41                             /* 'l' */
+#define DUK_STRIDX_LC_N                                               42                             /* 'n' */
+#define DUK_STRIDX_LC_FATAL                                           43                             /* 'fatal' */
+#define DUK_STRIDX_LC_ERROR                                           44                             /* 'error' */
+#define DUK_STRIDX_LC_WARN                                            45                             /* 'warn' */
+#define DUK_STRIDX_LC_DEBUG                                           46                             /* 'debug' */
+#define DUK_STRIDX_LC_TRACE                                           47                             /* 'trace' */
+#define DUK_STRIDX_RAW                                                48                             /* 'raw' */
+#define DUK_STRIDX_FMT                                                49                             /* 'fmt' */
+#define DUK_STRIDX_CURRENT                                            50                             /* 'current' */
+#define DUK_STRIDX_RESUME                                             51                             /* 'resume' */
+#define DUK_STRIDX_COMPACT                                            52                             /* 'compact' */
+#define DUK_STRIDX_JC                                                 53                             /* 'jc' */
+#define DUK_STRIDX_JX                                                 54                             /* 'jx' */
+#define DUK_STRIDX_BASE64                                             55                             /* 'base64' */
+#define DUK_STRIDX_HEX                                                56                             /* 'hex' */
+#define DUK_STRIDX_DEC                                                57                             /* 'dec' */
+#define DUK_STRIDX_ENC                                                58                             /* 'enc' */
+#define DUK_STRIDX_FIN                                                59                             /* 'fin' */
+#define DUK_STRIDX_GC                                                 60                             /* 'gc' */
+#define DUK_STRIDX_ACT                                                61                             /* 'act' */
+#define DUK_STRIDX_LC_INFO                                            62                             /* 'info' */
+#define DUK_STRIDX_VERSION                                            63                             /* 'version' */
+#define DUK_STRIDX_ENV                                                64                             /* 'env' */
+#define DUK_STRIDX_MOD_LOADED                                         65                             /* 'modLoaded' */
+#define DUK_STRIDX_MOD_SEARCH                                         66                             /* 'modSearch' */
+#define DUK_STRIDX_ERR_THROW                                          67                             /* 'errThrow' */
+#define DUK_STRIDX_ERR_CREATE                                         68                             /* 'errCreate' */
+#define DUK_STRIDX_COMPILE                                            69                             /* 'compile' */
+#define DUK_STRIDX_INT_REGBASE                                        70                             /* '\x00Regbase' */
+#define DUK_STRIDX_INT_THREAD                                         71                             /* '\x00Thread' */
+#define DUK_STRIDX_INT_HANDLER                                        72                             /* '\x00Handler' */
+#define DUK_STRIDX_INT_FINALIZER                                      73                             /* '\x00Finalizer' */
+#define DUK_STRIDX_INT_CALLEE                                         74                             /* '\x00Callee' */
+#define DUK_STRIDX_INT_MAP                                            75                             /* '\x00Map' */
+#define DUK_STRIDX_INT_ARGS                                           76                             /* '\x00Args' */
+#define DUK_STRIDX_INT_THIS                                           77                             /* '\x00This' */
+#define DUK_STRIDX_INT_PC2LINE                                        78                             /* '\x00Pc2line' */
+#define DUK_STRIDX_INT_SOURCE                                         79                             /* '\x00Source' */
+#define DUK_STRIDX_INT_VARENV                                         80                             /* '\x00Varenv' */
+#define DUK_STRIDX_INT_LEXENV                                         81                             /* '\x00Lexenv' */
+#define DUK_STRIDX_INT_VARMAP                                         82                             /* '\x00Varmap' */
+#define DUK_STRIDX_INT_FORMALS                                        83                             /* '\x00Formals' */
+#define DUK_STRIDX_INT_BYTECODE                                       84                             /* '\x00Bytecode' */
+#define DUK_STRIDX_INT_NEXT                                           85                             /* '\x00Next' */
+#define DUK_STRIDX_INT_TARGET                                         86                             /* '\x00Target' */
+#define DUK_STRIDX_INT_VALUE                                          87                             /* '\x00Value' */
+#define DUK_STRIDX_LC_POINTER                                         88                             /* 'pointer' */
+#define DUK_STRIDX_INT_TRACEDATA                                      89                             /* '\x00Tracedata' */
+#define DUK_STRIDX_LINE_NUMBER                                        90                             /* 'lineNumber' */
+#define DUK_STRIDX_FILE_NAME                                          91                             /* 'fileName' */
+#define DUK_STRIDX_PC                                                 92                             /* 'pc' */
+#define DUK_STRIDX_STACK                                              93                             /* 'stack' */
+#define DUK_STRIDX_THROW_TYPE_ERROR                                   94                             /* 'ThrowTypeError' */
+#define DUK_STRIDX_DUKTAPE                                            95                             /* 'Duktape' */
+#define DUK_STRIDX_SET_FLOAT64                                        96                             /* 'setFloat64' */
+#define DUK_STRIDX_SET_FLOAT32                                        97                             /* 'setFloat32' */
+#define DUK_STRIDX_SET_UINT32                                         98                             /* 'setUint32' */
+#define DUK_STRIDX_SET_INT32                                          99                             /* 'setInt32' */
+#define DUK_STRIDX_SET_UINT16                                         100                            /* 'setUint16' */
+#define DUK_STRIDX_SET_INT16                                          101                            /* 'setInt16' */
+#define DUK_STRIDX_SET_UINT8                                          102                            /* 'setUint8' */
+#define DUK_STRIDX_SET_INT8                                           103                            /* 'setInt8' */
+#define DUK_STRIDX_GET_FLOAT64                                        104                            /* 'getFloat64' */
+#define DUK_STRIDX_GET_FLOAT32                                        105                            /* 'getFloat32' */
+#define DUK_STRIDX_GET_UINT32                                         106                            /* 'getUint32' */
+#define DUK_STRIDX_GET_INT32                                          107                            /* 'getInt32' */
+#define DUK_STRIDX_GET_UINT16                                         108                            /* 'getUint16' */
+#define DUK_STRIDX_GET_INT16                                          109                            /* 'getInt16' */
+#define DUK_STRIDX_GET_UINT8                                          110                            /* 'getUint8' */
+#define DUK_STRIDX_GET_INT8                                           111                            /* 'getInt8' */
+#define DUK_STRIDX_SUBARRAY                                           112                            /* 'subarray' */
+#define DUK_STRIDX_BYTES_PER_ELEMENT                                  113                            /* 'BYTES_PER_ELEMENT' */
+#define DUK_STRIDX_BYTE_OFFSET                                        114                            /* 'byteOffset' */
+#define DUK_STRIDX_LC_BUFFER                                          115                            /* 'buffer' */
+#define DUK_STRIDX_IS_VIEW                                            116                            /* 'isView' */
+#define DUK_STRIDX_DATA                                               117                            /* 'data' */
+#define DUK_STRIDX_TYPE                                               118                            /* 'type' */
+#define DUK_STRIDX_WRITE_INT_BE                                       119                            /* 'writeIntBE' */
+#define DUK_STRIDX_WRITE_INT_LE                                       120                            /* 'writeIntLE' */
+#define DUK_STRIDX_WRITE_UINT_BE                                      121                            /* 'writeUIntBE' */
+#define DUK_STRIDX_WRITE_UINT_LE                                      122                            /* 'writeUIntLE' */
+#define DUK_STRIDX_WRITE_DOUBLE_BE                                    123                            /* 'writeDoubleBE' */
+#define DUK_STRIDX_WRITE_DOUBLE_LE                                    124                            /* 'writeDoubleLE' */
+#define DUK_STRIDX_WRITE_FLOAT_BE                                     125                            /* 'writeFloatBE' */
+#define DUK_STRIDX_WRITE_FLOAT_LE                                     126                            /* 'writeFloatLE' */
+#define DUK_STRIDX_WRITE_INT32_BE                                     127                            /* 'writeInt32BE' */
+#define DUK_STRIDX_WRITE_INT32_LE                                     128                            /* 'writeInt32LE' */
+#define DUK_STRIDX_WRITE_UINT32_BE                                    129                            /* 'writeUInt32BE' */
+#define DUK_STRIDX_WRITE_UINT32_LE                                    130                            /* 'writeUInt32LE' */
+#define DUK_STRIDX_WRITE_INT16_BE                                     131                            /* 'writeInt16BE' */
+#define DUK_STRIDX_WRITE_INT16_LE                                     132                            /* 'writeInt16LE' */
+#define DUK_STRIDX_WRITE_UINT16_BE                                    133                            /* 'writeUInt16BE' */
+#define DUK_STRIDX_WRITE_UINT16_LE                                    134                            /* 'writeUInt16LE' */
+#define DUK_STRIDX_WRITE_INT8                                         135                            /* 'writeInt8' */
+#define DUK_STRIDX_WRITE_UINT8                                        136                            /* 'writeUInt8' */
+#define DUK_STRIDX_READ_INT_BE                                        137                            /* 'readIntBE' */
+#define DUK_STRIDX_READ_INT_LE                                        138                            /* 'readIntLE' */
+#define DUK_STRIDX_READ_UINT_BE                                       139                            /* 'readUIntBE' */
+#define DUK_STRIDX_READ_UINT_LE                                       140                            /* 'readUIntLE' */
+#define DUK_STRIDX_READ_DOUBLE_BE                                     141                            /* 'readDoubleBE' */
+#define DUK_STRIDX_READ_DOUBLE_LE                                     142                            /* 'readDoubleLE' */
+#define DUK_STRIDX_READ_FLOAT_BE                                      143                            /* 'readFloatBE' */
+#define DUK_STRIDX_READ_FLOAT_LE                                      144                            /* 'readFloatLE' */
+#define DUK_STRIDX_READ_INT32_BE                                      145                            /* 'readInt32BE' */
+#define DUK_STRIDX_READ_INT32_LE                                      146                            /* 'readInt32LE' */
+#define DUK_STRIDX_READ_UINT32_BE                                     147                            /* 'readUInt32BE' */
+#define DUK_STRIDX_READ_UINT32_LE                                     148                            /* 'readUInt32LE' */
+#define DUK_STRIDX_READ_INT16_BE                                      149                            /* 'readInt16BE' */
+#define DUK_STRIDX_READ_INT16_LE                                      150                            /* 'readInt16LE' */
+#define DUK_STRIDX_READ_UINT16_BE                                     151                            /* 'readUInt16BE' */
+#define DUK_STRIDX_READ_UINT16_LE                                     152                            /* 'readUInt16LE' */
+#define DUK_STRIDX_READ_INT8                                          153                            /* 'readInt8' */
+#define DUK_STRIDX_READ_UINT8                                         154                            /* 'readUInt8' */
+#define DUK_STRIDX_COPY                                               155                            /* 'copy' */
+#define DUK_STRIDX_EQUALS                                             156                            /* 'equals' */
+#define DUK_STRIDX_FILL                                               157                            /* 'fill' */
+#define DUK_STRIDX_WRITE                                              158                            /* 'write' */
+#define DUK_STRIDX_COMPARE                                            159                            /* 'compare' */
+#define DUK_STRIDX_BYTE_LENGTH                                        160                            /* 'byteLength' */
+#define DUK_STRIDX_IS_BUFFER                                          161                            /* 'isBuffer' */
+#define DUK_STRIDX_IS_ENCODING                                        162                            /* 'isEncoding' */
+#define DUK_STRIDX_EXPORTS                                            163                            /* 'exports' */
+#define DUK_STRIDX_ID                                                 164                            /* 'id' */
+#define DUK_STRIDX_REQUIRE                                            165                            /* 'require' */
+#define DUK_STRIDX___PROTO__                                          166                            /* '__proto__' */
+#define DUK_STRIDX_SET_PROTOTYPE_OF                                   167                            /* 'setPrototypeOf' */
+#define DUK_STRIDX_OWN_KEYS                                           168                            /* 'ownKeys' */
+#define DUK_STRIDX_ENUMERATE                                          169                            /* 'enumerate' */
+#define DUK_STRIDX_DELETE_PROPERTY                                    170                            /* 'deleteProperty' */
+#define DUK_STRIDX_HAS                                                171                            /* 'has' */
+#define DUK_STRIDX_PROXY                                              172                            /* 'Proxy' */
+#define DUK_STRIDX_CALLEE                                             173                            /* 'callee' */
+#define DUK_STRIDX_INVALID_DATE                                       174                            /* 'Invalid Date' */
+#define DUK_STRIDX_BRACKETED_ELLIPSIS                                 175                            /* '[...]' */
+#define DUK_STRIDX_NEWLINE_TAB                                        176                            /* '\n\t' */
+#define DUK_STRIDX_SPACE                                              177                            /* ' ' */
+#define DUK_STRIDX_COMMA                                              178                            /* ',' */
+#define DUK_STRIDX_MINUS_ZERO                                         179                            /* '-0' */
+#define DUK_STRIDX_PLUS_ZERO                                          180                            /* '+0' */
+#define DUK_STRIDX_ZERO                                               181                            /* '0' */
+#define DUK_STRIDX_MINUS_INFINITY                                     182                            /* '-Infinity' */
+#define DUK_STRIDX_PLUS_INFINITY                                      183                            /* '+Infinity' */
+#define DUK_STRIDX_INFINITY                                           184                            /* 'Infinity' */
+#define DUK_STRIDX_LC_OBJECT                                          185                            /* 'object' */
+#define DUK_STRIDX_LC_STRING                                          186                            /* 'string' */
+#define DUK_STRIDX_LC_NUMBER                                          187                            /* 'number' */
+#define DUK_STRIDX_LC_BOOLEAN                                         188                            /* 'boolean' */
+#define DUK_STRIDX_LC_UNDEFINED                                       189                            /* 'undefined' */
+#define DUK_STRIDX_STRINGIFY                                          190                            /* 'stringify' */
+#define DUK_STRIDX_TAN                                                191                            /* 'tan' */
+#define DUK_STRIDX_SQRT                                               192                            /* 'sqrt' */
+#define DUK_STRIDX_SIN                                                193                            /* 'sin' */
+#define DUK_STRIDX_ROUND                                              194                            /* 'round' */
+#define DUK_STRIDX_RANDOM                                             195                            /* 'random' */
+#define DUK_STRIDX_POW                                                196                            /* 'pow' */
+#define DUK_STRIDX_MIN                                                197                            /* 'min' */
+#define DUK_STRIDX_MAX                                                198                            /* 'max' */
+#define DUK_STRIDX_LOG                                                199                            /* 'log' */
+#define DUK_STRIDX_FLOOR                                              200                            /* 'floor' */
+#define DUK_STRIDX_EXP                                                201                            /* 'exp' */
+#define DUK_STRIDX_COS                                                202                            /* 'cos' */
+#define DUK_STRIDX_CEIL                                               203                            /* 'ceil' */
+#define DUK_STRIDX_ATAN2                                              204                            /* 'atan2' */
+#define DUK_STRIDX_ATAN                                               205                            /* 'atan' */
+#define DUK_STRIDX_ASIN                                               206                            /* 'asin' */
+#define DUK_STRIDX_ACOS                                               207                            /* 'acos' */
+#define DUK_STRIDX_ABS                                                208                            /* 'abs' */
+#define DUK_STRIDX_SQRT2                                              209                            /* 'SQRT2' */
+#define DUK_STRIDX_SQRT1_2                                            210                            /* 'SQRT1_2' */
+#define DUK_STRIDX_PI                                                 211                            /* 'PI' */
+#define DUK_STRIDX_LOG10E                                             212                            /* 'LOG10E' */
+#define DUK_STRIDX_LOG2E                                              213                            /* 'LOG2E' */
+#define DUK_STRIDX_LN2                                                214                            /* 'LN2' */
+#define DUK_STRIDX_LN10                                               215                            /* 'LN10' */
+#define DUK_STRIDX_E                                                  216                            /* 'E' */
+#define DUK_STRIDX_MESSAGE                                            217                            /* 'message' */
+#define DUK_STRIDX_NAME                                               218                            /* 'name' */
+#define DUK_STRIDX_INPUT                                              219                            /* 'input' */
+#define DUK_STRIDX_INDEX                                              220                            /* 'index' */
+#define DUK_STRIDX_ESCAPED_EMPTY_REGEXP                               221                            /* '(?:)' */
+#define DUK_STRIDX_LAST_INDEX                                         222                            /* 'lastIndex' */
+#define DUK_STRIDX_MULTILINE                                          223                            /* 'multiline' */
+#define DUK_STRIDX_IGNORE_CASE                                        224                            /* 'ignoreCase' */
+#define DUK_STRIDX_SOURCE                                             225                            /* 'source' */
+#define DUK_STRIDX_TEST                                               226                            /* 'test' */
+#define DUK_STRIDX_EXEC                                               227                            /* 'exec' */
+#define DUK_STRIDX_TO_GMT_STRING                                      228                            /* 'toGMTString' */
+#define DUK_STRIDX_SET_YEAR                                           229                            /* 'setYear' */
+#define DUK_STRIDX_GET_YEAR                                           230                            /* 'getYear' */
+#define DUK_STRIDX_TO_JSON                                            231                            /* 'toJSON' */
+#define DUK_STRIDX_TO_ISO_STRING                                      232                            /* 'toISOString' */
+#define DUK_STRIDX_TO_UTC_STRING                                      233                            /* 'toUTCString' */
+#define DUK_STRIDX_SET_UTC_FULL_YEAR                                  234                            /* 'setUTCFullYear' */
+#define DUK_STRIDX_SET_FULL_YEAR                                      235                            /* 'setFullYear' */
+#define DUK_STRIDX_SET_UTC_MONTH                                      236                            /* 'setUTCMonth' */
+#define DUK_STRIDX_SET_MONTH                                          237                            /* 'setMonth' */
+#define DUK_STRIDX_SET_UTC_DATE                                       238                            /* 'setUTCDate' */
+#define DUK_STRIDX_SET_DATE                                           239                            /* 'setDate' */
+#define DUK_STRIDX_SET_UTC_HOURS                                      240                            /* 'setUTCHours' */
+#define DUK_STRIDX_SET_HOURS                                          241                            /* 'setHours' */
+#define DUK_STRIDX_SET_UTC_MINUTES                                    242                            /* 'setUTCMinutes' */
+#define DUK_STRIDX_SET_MINUTES                                        243                            /* 'setMinutes' */
+#define DUK_STRIDX_SET_UTC_SECONDS                                    244                            /* 'setUTCSeconds' */
+#define DUK_STRIDX_SET_SECONDS                                        245                            /* 'setSeconds' */
+#define DUK_STRIDX_SET_UTC_MILLISECONDS                               246                            /* 'setUTCMilliseconds' */
+#define DUK_STRIDX_SET_MILLISECONDS                                   247                            /* 'setMilliseconds' */
+#define DUK_STRIDX_SET_TIME                                           248                            /* 'setTime' */
+#define DUK_STRIDX_GET_TIMEZONE_OFFSET                                249                            /* 'getTimezoneOffset' */
+#define DUK_STRIDX_GET_UTC_MILLISECONDS                               250                            /* 'getUTCMilliseconds' */
+#define DUK_STRIDX_GET_MILLISECONDS                                   251                            /* 'getMilliseconds' */
+#define DUK_STRIDX_GET_UTC_SECONDS                                    252                            /* 'getUTCSeconds' */
+#define DUK_STRIDX_GET_SECONDS                                        253                            /* 'getSeconds' */
+#define DUK_STRIDX_GET_UTC_MINUTES                                    254                            /* 'getUTCMinutes' */
+#define DUK_STRIDX_GET_MINUTES                                        255                            /* 'getMinutes' */
+#define DUK_STRIDX_GET_UTC_HOURS                                      256                            /* 'getUTCHours' */
+#define DUK_STRIDX_GET_HOURS                                          257                            /* 'getHours' */
+#define DUK_STRIDX_GET_UTC_DAY                                        258                            /* 'getUTCDay' */
+#define DUK_STRIDX_GET_DAY                                            259                            /* 'getDay' */
+#define DUK_STRIDX_GET_UTC_DATE                                       260                            /* 'getUTCDate' */
+#define DUK_STRIDX_GET_DATE                                           261                            /* 'getDate' */
+#define DUK_STRIDX_GET_UTC_MONTH                                      262                            /* 'getUTCMonth' */
+#define DUK_STRIDX_GET_MONTH                                          263                            /* 'getMonth' */
+#define DUK_STRIDX_GET_UTC_FULL_YEAR                                  264                            /* 'getUTCFullYear' */
+#define DUK_STRIDX_GET_FULL_YEAR                                      265                            /* 'getFullYear' */
+#define DUK_STRIDX_GET_TIME                                           266                            /* 'getTime' */
+#define DUK_STRIDX_TO_LOCALE_TIME_STRING                              267                            /* 'toLocaleTimeString' */
+#define DUK_STRIDX_TO_LOCALE_DATE_STRING                              268                            /* 'toLocaleDateString' */
+#define DUK_STRIDX_TO_TIME_STRING                                     269                            /* 'toTimeString' */
+#define DUK_STRIDX_TO_DATE_STRING                                     270                            /* 'toDateString' */
+#define DUK_STRIDX_NOW                                                271                            /* 'now' */
+#define DUK_STRIDX_UTC                                                272                            /* 'UTC' */
+#define DUK_STRIDX_PARSE                                              273                            /* 'parse' */
+#define DUK_STRIDX_TO_PRECISION                                       274                            /* 'toPrecision' */
+#define DUK_STRIDX_TO_EXPONENTIAL                                     275                            /* 'toExponential' */
+#define DUK_STRIDX_TO_FIXED                                           276                            /* 'toFixed' */
+#define DUK_STRIDX_POSITIVE_INFINITY                                  277                            /* 'POSITIVE_INFINITY' */
+#define DUK_STRIDX_NEGATIVE_INFINITY                                  278                            /* 'NEGATIVE_INFINITY' */
+#define DUK_STRIDX_NAN                                                279                            /* 'NaN' */
+#define DUK_STRIDX_MIN_VALUE                                          280                            /* 'MIN_VALUE' */
+#define DUK_STRIDX_MAX_VALUE                                          281                            /* 'MAX_VALUE' */
+#define DUK_STRIDX_SUBSTR                                             282                            /* 'substr' */
+#define DUK_STRIDX_TRIM                                               283                            /* 'trim' */
+#define DUK_STRIDX_TO_LOCALE_UPPER_CASE                               284                            /* 'toLocaleUpperCase' */
+#define DUK_STRIDX_TO_UPPER_CASE                                      285                            /* 'toUpperCase' */
+#define DUK_STRIDX_TO_LOCALE_LOWER_CASE                               286                            /* 'toLocaleLowerCase' */
+#define DUK_STRIDX_TO_LOWER_CASE                                      287                            /* 'toLowerCase' */
+#define DUK_STRIDX_SUBSTRING                                          288                            /* 'substring' */
+#define DUK_STRIDX_SPLIT                                              289                            /* 'split' */
+#define DUK_STRIDX_SEARCH                                             290                            /* 'search' */
+#define DUK_STRIDX_REPLACE                                            291                            /* 'replace' */
+#define DUK_STRIDX_MATCH                                              292                            /* 'match' */
+#define DUK_STRIDX_LOCALE_COMPARE                                     293                            /* 'localeCompare' */
+#define DUK_STRIDX_CHAR_CODE_AT                                       294                            /* 'charCodeAt' */
+#define DUK_STRIDX_CHAR_AT                                            295                            /* 'charAt' */
+#define DUK_STRIDX_FROM_CHAR_CODE                                     296                            /* 'fromCharCode' */
+#define DUK_STRIDX_REDUCE_RIGHT                                       297                            /* 'reduceRight' */
+#define DUK_STRIDX_REDUCE                                             298                            /* 'reduce' */
+#define DUK_STRIDX_FILTER                                             299                            /* 'filter' */
+#define DUK_STRIDX_MAP                                                300                            /* 'map' */
+#define DUK_STRIDX_FOR_EACH                                           301                            /* 'forEach' */
+#define DUK_STRIDX_SOME                                               302                            /* 'some' */
+#define DUK_STRIDX_EVERY                                              303                            /* 'every' */
+#define DUK_STRIDX_LAST_INDEX_OF                                      304                            /* 'lastIndexOf' */
+#define DUK_STRIDX_INDEX_OF                                           305                            /* 'indexOf' */
+#define DUK_STRIDX_UNSHIFT                                            306                            /* 'unshift' */
+#define DUK_STRIDX_SPLICE                                             307                            /* 'splice' */
+#define DUK_STRIDX_SORT                                               308                            /* 'sort' */
+#define DUK_STRIDX_SLICE                                              309                            /* 'slice' */
+#define DUK_STRIDX_SHIFT                                              310                            /* 'shift' */
+#define DUK_STRIDX_REVERSE                                            311                            /* 'reverse' */
+#define DUK_STRIDX_PUSH                                               312                            /* 'push' */
+#define DUK_STRIDX_POP                                                313                            /* 'pop' */
+#define DUK_STRIDX_JOIN                                               314                            /* 'join' */
+#define DUK_STRIDX_CONCAT                                             315                            /* 'concat' */
+#define DUK_STRIDX_IS_ARRAY                                           316                            /* 'isArray' */
+#define DUK_STRIDX_LC_ARGUMENTS                                       317                            /* 'arguments' */
+#define DUK_STRIDX_CALLER                                             318                            /* 'caller' */
+#define DUK_STRIDX_BIND                                               319                            /* 'bind' */
+#define DUK_STRIDX_CALL                                               320                            /* 'call' */
+#define DUK_STRIDX_APPLY                                              321                            /* 'apply' */
+#define DUK_STRIDX_PROPERTY_IS_ENUMERABLE                             322                            /* 'propertyIsEnumerable' */
+#define DUK_STRIDX_IS_PROTOTYPE_OF                                    323                            /* 'isPrototypeOf' */
+#define DUK_STRIDX_HAS_OWN_PROPERTY                                   324                            /* 'hasOwnProperty' */
+#define DUK_STRIDX_VALUE_OF                                           325                            /* 'valueOf' */
+#define DUK_STRIDX_TO_LOCALE_STRING                                   326                            /* 'toLocaleString' */
+#define DUK_STRIDX_TO_STRING                                          327                            /* 'toString' */
+#define DUK_STRIDX_CONSTRUCTOR                                        328                            /* 'constructor' */
+#define DUK_STRIDX_SET                                                329                            /* 'set' */
+#define DUK_STRIDX_GET                                                330                            /* 'get' */
+#define DUK_STRIDX_ENUMERABLE                                         331                            /* 'enumerable' */
+#define DUK_STRIDX_CONFIGURABLE                                       332                            /* 'configurable' */
+#define DUK_STRIDX_WRITABLE                                           333                            /* 'writable' */
+#define DUK_STRIDX_VALUE                                              334                            /* 'value' */
+#define DUK_STRIDX_KEYS                                               335                            /* 'keys' */
+#define DUK_STRIDX_IS_EXTENSIBLE                                      336                            /* 'isExtensible' */
+#define DUK_STRIDX_IS_FROZEN                                          337                            /* 'isFrozen' */
+#define DUK_STRIDX_IS_SEALED                                          338                            /* 'isSealed' */
+#define DUK_STRIDX_PREVENT_EXTENSIONS                                 339                            /* 'preventExtensions' */
+#define DUK_STRIDX_FREEZE                                             340                            /* 'freeze' */
+#define DUK_STRIDX_SEAL                                               341                            /* 'seal' */
+#define DUK_STRIDX_DEFINE_PROPERTIES                                  342                            /* 'defineProperties' */
+#define DUK_STRIDX_DEFINE_PROPERTY                                    343                            /* 'defineProperty' */
+#define DUK_STRIDX_CREATE                                             344                            /* 'create' */
+#define DUK_STRIDX_GET_OWN_PROPERTY_NAMES                             345                            /* 'getOwnPropertyNames' */
+#define DUK_STRIDX_GET_OWN_PROPERTY_DESCRIPTOR                        346                            /* 'getOwnPropertyDescriptor' */
+#define DUK_STRIDX_GET_PROTOTYPE_OF                                   347                            /* 'getPrototypeOf' */
+#define DUK_STRIDX_PROTOTYPE                                          348                            /* 'prototype' */
+#define DUK_STRIDX_LENGTH                                             349                            /* 'length' */
+#define DUK_STRIDX_ALERT                                              350                            /* 'alert' */
+#define DUK_STRIDX_PRINT                                              351                            /* 'print' */
+#define DUK_STRIDX_UNESCAPE                                           352                            /* 'unescape' */
+#define DUK_STRIDX_ESCAPE                                             353                            /* 'escape' */
+#define DUK_STRIDX_ENCODE_URI_COMPONENT                               354                            /* 'encodeURIComponent' */
+#define DUK_STRIDX_ENCODE_URI                                         355                            /* 'encodeURI' */
+#define DUK_STRIDX_DECODE_URI_COMPONENT                               356                            /* 'decodeURIComponent' */
+#define DUK_STRIDX_DECODE_URI                                         357                            /* 'decodeURI' */
+#define DUK_STRIDX_IS_FINITE                                          358                            /* 'isFinite' */
+#define DUK_STRIDX_IS_NAN                                             359                            /* 'isNaN' */
+#define DUK_STRIDX_PARSE_FLOAT                                        360                            /* 'parseFloat' */
+#define DUK_STRIDX_PARSE_INT                                          361                            /* 'parseInt' */
+#define DUK_STRIDX_EVAL                                               362                            /* 'eval' */
+#define DUK_STRIDX_URI_ERROR                                          363                            /* 'URIError' */
+#define DUK_STRIDX_TYPE_ERROR                                         364                            /* 'TypeError' */
+#define DUK_STRIDX_SYNTAX_ERROR                                       365                            /* 'SyntaxError' */
+#define DUK_STRIDX_REFERENCE_ERROR                                    366                            /* 'ReferenceError' */
+#define DUK_STRIDX_RANGE_ERROR                                        367                            /* 'RangeError' */
+#define DUK_STRIDX_EVAL_ERROR                                         368                            /* 'EvalError' */
+#define DUK_STRIDX_BREAK                                              369                            /* 'break' */
+#define DUK_STRIDX_CASE                                               370                            /* 'case' */
+#define DUK_STRIDX_CATCH                                              371                            /* 'catch' */
+#define DUK_STRIDX_CONTINUE                                           372                            /* 'continue' */
+#define DUK_STRIDX_DEBUGGER                                           373                            /* 'debugger' */
+#define DUK_STRIDX_DEFAULT                                            374                            /* 'default' */
+#define DUK_STRIDX_DELETE                                             375                            /* 'delete' */
+#define DUK_STRIDX_DO                                                 376                            /* 'do' */
+#define DUK_STRIDX_ELSE                                               377                            /* 'else' */
+#define DUK_STRIDX_FINALLY                                            378                            /* 'finally' */
+#define DUK_STRIDX_FOR                                                379                            /* 'for' */
+#define DUK_STRIDX_LC_FUNCTION                                        380                            /* 'function' */
+#define DUK_STRIDX_IF                                                 381                            /* 'if' */
+#define DUK_STRIDX_IN                                                 382                            /* 'in' */
+#define DUK_STRIDX_INSTANCEOF                                         383                            /* 'instanceof' */
+#define DUK_STRIDX_NEW                                                384                            /* 'new' */
+#define DUK_STRIDX_RETURN                                             385                            /* 'return' */
+#define DUK_STRIDX_SWITCH                                             386                            /* 'switch' */
+#define DUK_STRIDX_THIS                                               387                            /* 'this' */
+#define DUK_STRIDX_THROW                                              388                            /* 'throw' */
+#define DUK_STRIDX_TRY                                                389                            /* 'try' */
+#define DUK_STRIDX_TYPEOF                                             390                            /* 'typeof' */
+#define DUK_STRIDX_VAR                                                391                            /* 'var' */
+#define DUK_STRIDX_CONST                                              392                            /* 'const' */
+#define DUK_STRIDX_VOID                                               393                            /* 'void' */
+#define DUK_STRIDX_WHILE                                              394                            /* 'while' */
+#define DUK_STRIDX_WITH                                               395                            /* 'with' */
+#define DUK_STRIDX_CLASS                                              396                            /* 'class' */
+#define DUK_STRIDX_ENUM                                               397                            /* 'enum' */
+#define DUK_STRIDX_EXPORT                                             398                            /* 'export' */
+#define DUK_STRIDX_EXTENDS                                            399                            /* 'extends' */
+#define DUK_STRIDX_IMPORT                                             400                            /* 'import' */
+#define DUK_STRIDX_SUPER                                              401                            /* 'super' */
+#define DUK_STRIDX_LC_NULL                                            402                            /* 'null' */
+#define DUK_STRIDX_TRUE                                               403                            /* 'true' */
+#define DUK_STRIDX_FALSE                                              404                            /* 'false' */
+#define DUK_STRIDX_IMPLEMENTS                                         405                            /* 'implements' */
+#define DUK_STRIDX_INTERFACE                                          406                            /* 'interface' */
+#define DUK_STRIDX_LET                                                407                            /* 'let' */
+#define DUK_STRIDX_PACKAGE                                            408                            /* 'package' */
+#define DUK_STRIDX_PRIVATE                                            409                            /* 'private' */
+#define DUK_STRIDX_PROTECTED                                          410                            /* 'protected' */
+#define DUK_STRIDX_PUBLIC                                             411                            /* 'public' */
+#define DUK_STRIDX_STATIC                                             412                            /* 'static' */
+#define DUK_STRIDX_YIELD                                              413                            /* 'yield' */
 
 #define DUK_HEAP_STRING_UC_LOGGER(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_LOGGER)
 #define DUK_HTHREAD_STRING_UC_LOGGER(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_LOGGER)
@@ -632,12 +793,34 @@ extern const duk_uint8_t duk_strings_data[];
 #define DUK_HTHREAD_STRING_UC_THREAD(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_THREAD)
 #define DUK_HEAP_STRING_UC_POINTER(heap)                              DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_POINTER)
 #define DUK_HTHREAD_STRING_UC_POINTER(thr)                            DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_POINTER)
-#define DUK_HEAP_STRING_UC_BUFFER(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_BUFFER)
-#define DUK_HTHREAD_STRING_UC_BUFFER(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_BUFFER)
 #define DUK_HEAP_STRING_DEC_ENV(heap)                                 DUK_HEAP_GET_STRING((heap),DUK_STRIDX_DEC_ENV)
 #define DUK_HTHREAD_STRING_DEC_ENV(thr)                               DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_DEC_ENV)
 #define DUK_HEAP_STRING_OBJ_ENV(heap)                                 DUK_HEAP_GET_STRING((heap),DUK_STRIDX_OBJ_ENV)
 #define DUK_HTHREAD_STRING_OBJ_ENV(thr)                               DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_OBJ_ENV)
+#define DUK_HEAP_STRING_FLOAT64_ARRAY(heap)                           DUK_HEAP_GET_STRING((heap),DUK_STRIDX_FLOAT64_ARRAY)
+#define DUK_HTHREAD_STRING_FLOAT64_ARRAY(thr)                         DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_FLOAT64_ARRAY)
+#define DUK_HEAP_STRING_FLOAT32_ARRAY(heap)                           DUK_HEAP_GET_STRING((heap),DUK_STRIDX_FLOAT32_ARRAY)
+#define DUK_HTHREAD_STRING_FLOAT32_ARRAY(thr)                         DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_FLOAT32_ARRAY)
+#define DUK_HEAP_STRING_UINT32_ARRAY(heap)                            DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UINT32_ARRAY)
+#define DUK_HTHREAD_STRING_UINT32_ARRAY(thr)                          DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UINT32_ARRAY)
+#define DUK_HEAP_STRING_INT32_ARRAY(heap)                             DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT32_ARRAY)
+#define DUK_HTHREAD_STRING_INT32_ARRAY(thr)                           DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT32_ARRAY)
+#define DUK_HEAP_STRING_UINT16_ARRAY(heap)                            DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UINT16_ARRAY)
+#define DUK_HTHREAD_STRING_UINT16_ARRAY(thr)                          DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UINT16_ARRAY)
+#define DUK_HEAP_STRING_INT16_ARRAY(heap)                             DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT16_ARRAY)
+#define DUK_HTHREAD_STRING_INT16_ARRAY(thr)                           DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT16_ARRAY)
+#define DUK_HEAP_STRING_UINT8_CLAMPED_ARRAY(heap)                     DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UINT8_CLAMPED_ARRAY)
+#define DUK_HTHREAD_STRING_UINT8_CLAMPED_ARRAY(thr)                   DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UINT8_CLAMPED_ARRAY)
+#define DUK_HEAP_STRING_UINT8_ARRAY(heap)                             DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UINT8_ARRAY)
+#define DUK_HTHREAD_STRING_UINT8_ARRAY(thr)                           DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UINT8_ARRAY)
+#define DUK_HEAP_STRING_INT8_ARRAY(heap)                              DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT8_ARRAY)
+#define DUK_HTHREAD_STRING_INT8_ARRAY(thr)                            DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT8_ARRAY)
+#define DUK_HEAP_STRING_DATA_VIEW(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_DATA_VIEW)
+#define DUK_HTHREAD_STRING_DATA_VIEW(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_DATA_VIEW)
+#define DUK_HEAP_STRING_ARRAY_BUFFER(heap)                            DUK_HEAP_GET_STRING((heap),DUK_STRIDX_ARRAY_BUFFER)
+#define DUK_HTHREAD_STRING_ARRAY_BUFFER(thr)                          DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_ARRAY_BUFFER)
+#define DUK_HEAP_STRING_UC_BUFFER(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_BUFFER)
+#define DUK_HTHREAD_STRING_UC_BUFFER(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_BUFFER)
 #define DUK_HEAP_STRING_EMPTY_STRING(heap)                            DUK_HEAP_GET_STRING((heap),DUK_STRIDX_EMPTY_STRING)
 #define DUK_HTHREAD_STRING_EMPTY_STRING(thr)                          DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_EMPTY_STRING)
 #define DUK_HEAP_STRING_GLOBAL(heap)                                  DUK_HEAP_GET_STRING((heap),DUK_STRIDX_GLOBAL)
@@ -782,10 +965,8 @@ extern const duk_uint8_t duk_strings_data[];
 #define DUK_HTHREAD_STRING_INT_VALUE(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_VALUE)
 #define DUK_HEAP_STRING_LC_POINTER(heap)                              DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_POINTER)
 #define DUK_HTHREAD_STRING_LC_POINTER(thr)                            DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_POINTER)
-#define DUK_HEAP_STRING_LC_BUFFER(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_BUFFER)
-#define DUK_HTHREAD_STRING_LC_BUFFER(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_BUFFER)
-#define DUK_HEAP_STRING_TRACEDATA(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_TRACEDATA)
-#define DUK_HTHREAD_STRING_TRACEDATA(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_TRACEDATA)
+#define DUK_HEAP_STRING_INT_TRACEDATA(heap)                           DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_TRACEDATA)
+#define DUK_HTHREAD_STRING_INT_TRACEDATA(thr)                         DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_TRACEDATA)
 #define DUK_HEAP_STRING_LINE_NUMBER(heap)                             DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LINE_NUMBER)
 #define DUK_HTHREAD_STRING_LINE_NUMBER(thr)                           DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LINE_NUMBER)
 #define DUK_HEAP_STRING_FILE_NAME(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_FILE_NAME)
@@ -798,6 +979,142 @@ extern const duk_uint8_t duk_strings_data[];
 #define DUK_HTHREAD_STRING_THROW_TYPE_ERROR(thr)                      DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_THROW_TYPE_ERROR)
 #define DUK_HEAP_STRING_DUKTAPE(heap)                                 DUK_HEAP_GET_STRING((heap),DUK_STRIDX_DUKTAPE)
 #define DUK_HTHREAD_STRING_DUKTAPE(thr)                               DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_DUKTAPE)
+#define DUK_HEAP_STRING_SET_FLOAT64(heap)                             DUK_HEAP_GET_STRING((heap),DUK_STRIDX_SET_FLOAT64)
+#define DUK_HTHREAD_STRING_SET_FLOAT64(thr)                           DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_SET_FLOAT64)
+#define DUK_HEAP_STRING_SET_FLOAT32(heap)                             DUK_HEAP_GET_STRING((heap),DUK_STRIDX_SET_FLOAT32)
+#define DUK_HTHREAD_STRING_SET_FLOAT32(thr)                           DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_SET_FLOAT32)
+#define DUK_HEAP_STRING_SET_UINT32(heap)                              DUK_HEAP_GET_STRING((heap),DUK_STRIDX_SET_UINT32)
+#define DUK_HTHREAD_STRING_SET_UINT32(thr)                            DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_SET_UINT32)
+#define DUK_HEAP_STRING_SET_INT32(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_SET_INT32)
+#define DUK_HTHREAD_STRING_SET_INT32(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_SET_INT32)
+#define DUK_HEAP_STRING_SET_UINT16(heap)                              DUK_HEAP_GET_STRING((heap),DUK_STRIDX_SET_UINT16)
+#define DUK_HTHREAD_STRING_SET_UINT16(thr)                            DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_SET_UINT16)
+#define DUK_HEAP_STRING_SET_INT16(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_SET_INT16)
+#define DUK_HTHREAD_STRING_SET_INT16(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_SET_INT16)
+#define DUK_HEAP_STRING_SET_UINT8(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_SET_UINT8)
+#define DUK_HTHREAD_STRING_SET_UINT8(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_SET_UINT8)
+#define DUK_HEAP_STRING_SET_INT8(heap)                                DUK_HEAP_GET_STRING((heap),DUK_STRIDX_SET_INT8)
+#define DUK_HTHREAD_STRING_SET_INT8(thr)                              DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_SET_INT8)
+#define DUK_HEAP_STRING_GET_FLOAT64(heap)                             DUK_HEAP_GET_STRING((heap),DUK_STRIDX_GET_FLOAT64)
+#define DUK_HTHREAD_STRING_GET_FLOAT64(thr)                           DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_GET_FLOAT64)
+#define DUK_HEAP_STRING_GET_FLOAT32(heap)                             DUK_HEAP_GET_STRING((heap),DUK_STRIDX_GET_FLOAT32)
+#define DUK_HTHREAD_STRING_GET_FLOAT32(thr)                           DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_GET_FLOAT32)
+#define DUK_HEAP_STRING_GET_UINT32(heap)                              DUK_HEAP_GET_STRING((heap),DUK_STRIDX_GET_UINT32)
+#define DUK_HTHREAD_STRING_GET_UINT32(thr)                            DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_GET_UINT32)
+#define DUK_HEAP_STRING_GET_INT32(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_GET_INT32)
+#define DUK_HTHREAD_STRING_GET_INT32(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_GET_INT32)
+#define DUK_HEAP_STRING_GET_UINT16(heap)                              DUK_HEAP_GET_STRING((heap),DUK_STRIDX_GET_UINT16)
+#define DUK_HTHREAD_STRING_GET_UINT16(thr)                            DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_GET_UINT16)
+#define DUK_HEAP_STRING_GET_INT16(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_GET_INT16)
+#define DUK_HTHREAD_STRING_GET_INT16(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_GET_INT16)
+#define DUK_HEAP_STRING_GET_UINT8(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_GET_UINT8)
+#define DUK_HTHREAD_STRING_GET_UINT8(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_GET_UINT8)
+#define DUK_HEAP_STRING_GET_INT8(heap)                                DUK_HEAP_GET_STRING((heap),DUK_STRIDX_GET_INT8)
+#define DUK_HTHREAD_STRING_GET_INT8(thr)                              DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_GET_INT8)
+#define DUK_HEAP_STRING_SUBARRAY(heap)                                DUK_HEAP_GET_STRING((heap),DUK_STRIDX_SUBARRAY)
+#define DUK_HTHREAD_STRING_SUBARRAY(thr)                              DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_SUBARRAY)
+#define DUK_HEAP_STRING_BYTES_PER_ELEMENT(heap)                       DUK_HEAP_GET_STRING((heap),DUK_STRIDX_BYTES_PER_ELEMENT)
+#define DUK_HTHREAD_STRING_BYTES_PER_ELEMENT(thr)                     DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_BYTES_PER_ELEMENT)
+#define DUK_HEAP_STRING_BYTE_OFFSET(heap)                             DUK_HEAP_GET_STRING((heap),DUK_STRIDX_BYTE_OFFSET)
+#define DUK_HTHREAD_STRING_BYTE_OFFSET(thr)                           DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_BYTE_OFFSET)
+#define DUK_HEAP_STRING_LC_BUFFER(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_BUFFER)
+#define DUK_HTHREAD_STRING_LC_BUFFER(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_BUFFER)
+#define DUK_HEAP_STRING_IS_VIEW(heap)                                 DUK_HEAP_GET_STRING((heap),DUK_STRIDX_IS_VIEW)
+#define DUK_HTHREAD_STRING_IS_VIEW(thr)                               DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_IS_VIEW)
+#define DUK_HEAP_STRING_DATA(heap)                                    DUK_HEAP_GET_STRING((heap),DUK_STRIDX_DATA)
+#define DUK_HTHREAD_STRING_DATA(thr)                                  DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_DATA)
+#define DUK_HEAP_STRING_TYPE(heap)                                    DUK_HEAP_GET_STRING((heap),DUK_STRIDX_TYPE)
+#define DUK_HTHREAD_STRING_TYPE(thr)                                  DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_TYPE)
+#define DUK_HEAP_STRING_WRITE_INT_BE(heap)                            DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WRITE_INT_BE)
+#define DUK_HTHREAD_STRING_WRITE_INT_BE(thr)                          DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WRITE_INT_BE)
+#define DUK_HEAP_STRING_WRITE_INT_LE(heap)                            DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WRITE_INT_LE)
+#define DUK_HTHREAD_STRING_WRITE_INT_LE(thr)                          DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WRITE_INT_LE)
+#define DUK_HEAP_STRING_WRITE_UINT_BE(heap)                           DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WRITE_UINT_BE)
+#define DUK_HTHREAD_STRING_WRITE_UINT_BE(thr)                         DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WRITE_UINT_BE)
+#define DUK_HEAP_STRING_WRITE_UINT_LE(heap)                           DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WRITE_UINT_LE)
+#define DUK_HTHREAD_STRING_WRITE_UINT_LE(thr)                         DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WRITE_UINT_LE)
+#define DUK_HEAP_STRING_WRITE_DOUBLE_BE(heap)                         DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WRITE_DOUBLE_BE)
+#define DUK_HTHREAD_STRING_WRITE_DOUBLE_BE(thr)                       DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WRITE_DOUBLE_BE)
+#define DUK_HEAP_STRING_WRITE_DOUBLE_LE(heap)                         DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WRITE_DOUBLE_LE)
+#define DUK_HTHREAD_STRING_WRITE_DOUBLE_LE(thr)                       DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WRITE_DOUBLE_LE)
+#define DUK_HEAP_STRING_WRITE_FLOAT_BE(heap)                          DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WRITE_FLOAT_BE)
+#define DUK_HTHREAD_STRING_WRITE_FLOAT_BE(thr)                        DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WRITE_FLOAT_BE)
+#define DUK_HEAP_STRING_WRITE_FLOAT_LE(heap)                          DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WRITE_FLOAT_LE)
+#define DUK_HTHREAD_STRING_WRITE_FLOAT_LE(thr)                        DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WRITE_FLOAT_LE)
+#define DUK_HEAP_STRING_WRITE_INT32_BE(heap)                          DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WRITE_INT32_BE)
+#define DUK_HTHREAD_STRING_WRITE_INT32_BE(thr)                        DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WRITE_INT32_BE)
+#define DUK_HEAP_STRING_WRITE_INT32_LE(heap)                          DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WRITE_INT32_LE)
+#define DUK_HTHREAD_STRING_WRITE_INT32_LE(thr)                        DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WRITE_INT32_LE)
+#define DUK_HEAP_STRING_WRITE_UINT32_BE(heap)                         DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WRITE_UINT32_BE)
+#define DUK_HTHREAD_STRING_WRITE_UINT32_BE(thr)                       DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WRITE_UINT32_BE)
+#define DUK_HEAP_STRING_WRITE_UINT32_LE(heap)                         DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WRITE_UINT32_LE)
+#define DUK_HTHREAD_STRING_WRITE_UINT32_LE(thr)                       DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WRITE_UINT32_LE)
+#define DUK_HEAP_STRING_WRITE_INT16_BE(heap)                          DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WRITE_INT16_BE)
+#define DUK_HTHREAD_STRING_WRITE_INT16_BE(thr)                        DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WRITE_INT16_BE)
+#define DUK_HEAP_STRING_WRITE_INT16_LE(heap)                          DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WRITE_INT16_LE)
+#define DUK_HTHREAD_STRING_WRITE_INT16_LE(thr)                        DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WRITE_INT16_LE)
+#define DUK_HEAP_STRING_WRITE_UINT16_BE(heap)                         DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WRITE_UINT16_BE)
+#define DUK_HTHREAD_STRING_WRITE_UINT16_BE(thr)                       DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WRITE_UINT16_BE)
+#define DUK_HEAP_STRING_WRITE_UINT16_LE(heap)                         DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WRITE_UINT16_LE)
+#define DUK_HTHREAD_STRING_WRITE_UINT16_LE(thr)                       DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WRITE_UINT16_LE)
+#define DUK_HEAP_STRING_WRITE_INT8(heap)                              DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WRITE_INT8)
+#define DUK_HTHREAD_STRING_WRITE_INT8(thr)                            DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WRITE_INT8)
+#define DUK_HEAP_STRING_WRITE_UINT8(heap)                             DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WRITE_UINT8)
+#define DUK_HTHREAD_STRING_WRITE_UINT8(thr)                           DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WRITE_UINT8)
+#define DUK_HEAP_STRING_READ_INT_BE(heap)                             DUK_HEAP_GET_STRING((heap),DUK_STRIDX_READ_INT_BE)
+#define DUK_HTHREAD_STRING_READ_INT_BE(thr)                           DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_READ_INT_BE)
+#define DUK_HEAP_STRING_READ_INT_LE(heap)                             DUK_HEAP_GET_STRING((heap),DUK_STRIDX_READ_INT_LE)
+#define DUK_HTHREAD_STRING_READ_INT_LE(thr)                           DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_READ_INT_LE)
+#define DUK_HEAP_STRING_READ_UINT_BE(heap)                            DUK_HEAP_GET_STRING((heap),DUK_STRIDX_READ_UINT_BE)
+#define DUK_HTHREAD_STRING_READ_UINT_BE(thr)                          DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_READ_UINT_BE)
+#define DUK_HEAP_STRING_READ_UINT_LE(heap)                            DUK_HEAP_GET_STRING((heap),DUK_STRIDX_READ_UINT_LE)
+#define DUK_HTHREAD_STRING_READ_UINT_LE(thr)                          DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_READ_UINT_LE)
+#define DUK_HEAP_STRING_READ_DOUBLE_BE(heap)                          DUK_HEAP_GET_STRING((heap),DUK_STRIDX_READ_DOUBLE_BE)
+#define DUK_HTHREAD_STRING_READ_DOUBLE_BE(thr)                        DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_READ_DOUBLE_BE)
+#define DUK_HEAP_STRING_READ_DOUBLE_LE(heap)                          DUK_HEAP_GET_STRING((heap),DUK_STRIDX_READ_DOUBLE_LE)
+#define DUK_HTHREAD_STRING_READ_DOUBLE_LE(thr)                        DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_READ_DOUBLE_LE)
+#define DUK_HEAP_STRING_READ_FLOAT_BE(heap)                           DUK_HEAP_GET_STRING((heap),DUK_STRIDX_READ_FLOAT_BE)
+#define DUK_HTHREAD_STRING_READ_FLOAT_BE(thr)                         DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_READ_FLOAT_BE)
+#define DUK_HEAP_STRING_READ_FLOAT_LE(heap)                           DUK_HEAP_GET_STRING((heap),DUK_STRIDX_READ_FLOAT_LE)
+#define DUK_HTHREAD_STRING_READ_FLOAT_LE(thr)                         DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_READ_FLOAT_LE)
+#define DUK_HEAP_STRING_READ_INT32_BE(heap)                           DUK_HEAP_GET_STRING((heap),DUK_STRIDX_READ_INT32_BE)
+#define DUK_HTHREAD_STRING_READ_INT32_BE(thr)                         DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_READ_INT32_BE)
+#define DUK_HEAP_STRING_READ_INT32_LE(heap)                           DUK_HEAP_GET_STRING((heap),DUK_STRIDX_READ_INT32_LE)
+#define DUK_HTHREAD_STRING_READ_INT32_LE(thr)                         DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_READ_INT32_LE)
+#define DUK_HEAP_STRING_READ_UINT32_BE(heap)                          DUK_HEAP_GET_STRING((heap),DUK_STRIDX_READ_UINT32_BE)
+#define DUK_HTHREAD_STRING_READ_UINT32_BE(thr)                        DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_READ_UINT32_BE)
+#define DUK_HEAP_STRING_READ_UINT32_LE(heap)                          DUK_HEAP_GET_STRING((heap),DUK_STRIDX_READ_UINT32_LE)
+#define DUK_HTHREAD_STRING_READ_UINT32_LE(thr)                        DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_READ_UINT32_LE)
+#define DUK_HEAP_STRING_READ_INT16_BE(heap)                           DUK_HEAP_GET_STRING((heap),DUK_STRIDX_READ_INT16_BE)
+#define DUK_HTHREAD_STRING_READ_INT16_BE(thr)                         DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_READ_INT16_BE)
+#define DUK_HEAP_STRING_READ_INT16_LE(heap)                           DUK_HEAP_GET_STRING((heap),DUK_STRIDX_READ_INT16_LE)
+#define DUK_HTHREAD_STRING_READ_INT16_LE(thr)                         DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_READ_INT16_LE)
+#define DUK_HEAP_STRING_READ_UINT16_BE(heap)                          DUK_HEAP_GET_STRING((heap),DUK_STRIDX_READ_UINT16_BE)
+#define DUK_HTHREAD_STRING_READ_UINT16_BE(thr)                        DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_READ_UINT16_BE)
+#define DUK_HEAP_STRING_READ_UINT16_LE(heap)                          DUK_HEAP_GET_STRING((heap),DUK_STRIDX_READ_UINT16_LE)
+#define DUK_HTHREAD_STRING_READ_UINT16_LE(thr)                        DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_READ_UINT16_LE)
+#define DUK_HEAP_STRING_READ_INT8(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_READ_INT8)
+#define DUK_HTHREAD_STRING_READ_INT8(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_READ_INT8)
+#define DUK_HEAP_STRING_READ_UINT8(heap)                              DUK_HEAP_GET_STRING((heap),DUK_STRIDX_READ_UINT8)
+#define DUK_HTHREAD_STRING_READ_UINT8(thr)                            DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_READ_UINT8)
+#define DUK_HEAP_STRING_COPY(heap)                                    DUK_HEAP_GET_STRING((heap),DUK_STRIDX_COPY)
+#define DUK_HTHREAD_STRING_COPY(thr)                                  DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_COPY)
+#define DUK_HEAP_STRING_EQUALS(heap)                                  DUK_HEAP_GET_STRING((heap),DUK_STRIDX_EQUALS)
+#define DUK_HTHREAD_STRING_EQUALS(thr)                                DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_EQUALS)
+#define DUK_HEAP_STRING_FILL(heap)                                    DUK_HEAP_GET_STRING((heap),DUK_STRIDX_FILL)
+#define DUK_HTHREAD_STRING_FILL(thr)                                  DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_FILL)
+#define DUK_HEAP_STRING_WRITE(heap)                                   DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WRITE)
+#define DUK_HTHREAD_STRING_WRITE(thr)                                 DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WRITE)
+#define DUK_HEAP_STRING_COMPARE(heap)                                 DUK_HEAP_GET_STRING((heap),DUK_STRIDX_COMPARE)
+#define DUK_HTHREAD_STRING_COMPARE(thr)                               DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_COMPARE)
+#define DUK_HEAP_STRING_BYTE_LENGTH(heap)                             DUK_HEAP_GET_STRING((heap),DUK_STRIDX_BYTE_LENGTH)
+#define DUK_HTHREAD_STRING_BYTE_LENGTH(thr)                           DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_BYTE_LENGTH)
+#define DUK_HEAP_STRING_IS_BUFFER(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_IS_BUFFER)
+#define DUK_HTHREAD_STRING_IS_BUFFER(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_IS_BUFFER)
+#define DUK_HEAP_STRING_IS_ENCODING(heap)                             DUK_HEAP_GET_STRING((heap),DUK_STRIDX_IS_ENCODING)
+#define DUK_HTHREAD_STRING_IS_ENCODING(thr)                           DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_IS_ENCODING)
+#define DUK_HEAP_STRING_EXPORTS(heap)                                 DUK_HEAP_GET_STRING((heap),DUK_STRIDX_EXPORTS)
+#define DUK_HTHREAD_STRING_EXPORTS(thr)                               DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_EXPORTS)
 #define DUK_HEAP_STRING_ID(heap)                                      DUK_HEAP_GET_STRING((heap),DUK_STRIDX_ID)
 #define DUK_HTHREAD_STRING_ID(thr)                                    DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_ID)
 #define DUK_HEAP_STRING_REQUIRE(heap)                                 DUK_HEAP_GET_STRING((heap),DUK_STRIDX_REQUIRE)
@@ -1254,6 +1571,8 @@ extern const duk_uint8_t duk_strings_data[];
 #define DUK_HTHREAD_STRING_TYPEOF(thr)                                DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_TYPEOF)
 #define DUK_HEAP_STRING_VAR(heap)                                     DUK_HEAP_GET_STRING((heap),DUK_STRIDX_VAR)
 #define DUK_HTHREAD_STRING_VAR(thr)                                   DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_VAR)
+#define DUK_HEAP_STRING_CONST(heap)                                   DUK_HEAP_GET_STRING((heap),DUK_STRIDX_CONST)
+#define DUK_HTHREAD_STRING_CONST(thr)                                 DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_CONST)
 #define DUK_HEAP_STRING_VOID(heap)                                    DUK_HEAP_GET_STRING((heap),DUK_STRIDX_VOID)
 #define DUK_HTHREAD_STRING_VOID(thr)                                  DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_VOID)
 #define DUK_HEAP_STRING_WHILE(heap)                                   DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WHILE)
@@ -1262,8 +1581,6 @@ extern const duk_uint8_t duk_strings_data[];
 #define DUK_HTHREAD_STRING_WITH(thr)                                  DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WITH)
 #define DUK_HEAP_STRING_CLASS(heap)                                   DUK_HEAP_GET_STRING((heap),DUK_STRIDX_CLASS)
 #define DUK_HTHREAD_STRING_CLASS(thr)                                 DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_CLASS)
-#define DUK_HEAP_STRING_CONST(heap)                                   DUK_HEAP_GET_STRING((heap),DUK_STRIDX_CONST)
-#define DUK_HTHREAD_STRING_CONST(thr)                                 DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_CONST)
 #define DUK_HEAP_STRING_ENUM(heap)                                    DUK_HEAP_GET_STRING((heap),DUK_STRIDX_ENUM)
 #define DUK_HTHREAD_STRING_ENUM(thr)                                  DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_ENUM)
 #define DUK_HEAP_STRING_EXPORT(heap)                                  DUK_HEAP_GET_STRING((heap),DUK_STRIDX_EXPORT)
@@ -1299,19 +1616,21 @@ extern const duk_uint8_t duk_strings_data[];
 #define DUK_HEAP_STRING_YIELD(heap)                                   DUK_HEAP_GET_STRING((heap),DUK_STRIDX_YIELD)
 #define DUK_HTHREAD_STRING_YIELD(thr)                                 DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_YIELD)
 
-#define DUK_HEAP_NUM_STRINGS                                          336
+#define DUK_HEAP_NUM_STRINGS                                          414
 
-#define DUK_STRIDX_START_RESERVED                                     291
-#define DUK_STRIDX_START_STRICT_RESERVED                              327
-#define DUK_STRIDX_END_RESERVED                                       336                            /* exclusive endpoint */
+#define DUK_STRIDX_START_RESERVED                                     369
+#define DUK_STRIDX_START_STRICT_RESERVED                              405
+#define DUK_STRIDX_END_RESERVED                                       414                            /* exclusive endpoint */
 
-extern const duk_c_function duk_bi_native_functions[];
-extern const duk_uint8_t duk_builtins_data[];
+#if !defined(DUK_SINGLE_FILE)
+DUK_INTERNAL_DECL const duk_c_function duk_bi_native_functions[149];
+DUK_INTERNAL_DECL const duk_uint8_t duk_builtins_data[1955];
 #ifdef DUK_USE_BUILTIN_INITJS
-extern const duk_uint8_t duk_initjs_data[];
+DUK_INTERNAL_DECL const duk_uint8_t duk_initjs_data[187];
 #endif  /* DUK_USE_BUILTIN_INITJS */
+#endif  /* !DUK_SINGLE_FILE */
 
-#define DUK_BUILTINS_DATA_LENGTH                                      1336
+#define DUK_BUILTINS_DATA_LENGTH                                      1955
 #ifdef DUK_USE_BUILTIN_INITJS
 #define DUK_BUILTIN_INITJS_DATA_LENGTH                                187
 #endif  /* DUK_USE_BUILTIN_INITJS */
@@ -1362,351 +1681,456 @@ extern const duk_uint8_t duk_initjs_data[];
 #define DUK_BIDX_LOGGER_CONSTRUCTOR                                   43
 #define DUK_BIDX_LOGGER_PROTOTYPE                                     44
 #define DUK_BIDX_DOUBLE_ERROR                                         45
-
-#define DUK_NUM_BUILTINS                                              46
+#define DUK_BIDX_ARRAYBUFFER_CONSTRUCTOR                              46
+#define DUK_BIDX_ARRAYBUFFER_PROTOTYPE                                47
+#define DUK_BIDX_DATAVIEW_CONSTRUCTOR                                 48
+#define DUK_BIDX_DATAVIEW_PROTOTYPE                                   49
+#define DUK_BIDX_TYPEDARRAY_PROTOTYPE                                 50
+#define DUK_BIDX_INT8ARRAY_CONSTRUCTOR                                51
+#define DUK_BIDX_INT8ARRAY_PROTOTYPE                                  52
+#define DUK_BIDX_UINT8ARRAY_CONSTRUCTOR                               53
+#define DUK_BIDX_UINT8ARRAY_PROTOTYPE                                 54
+#define DUK_BIDX_UINT8CLAMPEDARRAY_CONSTRUCTOR                        55
+#define DUK_BIDX_UINT8CLAMPEDARRAY_PROTOTYPE                          56
+#define DUK_BIDX_INT16ARRAY_CONSTRUCTOR                               57
+#define DUK_BIDX_INT16ARRAY_PROTOTYPE                                 58
+#define DUK_BIDX_UINT16ARRAY_CONSTRUCTOR                              59
+#define DUK_BIDX_UINT16ARRAY_PROTOTYPE                                60
+#define DUK_BIDX_INT32ARRAY_CONSTRUCTOR                               61
+#define DUK_BIDX_INT32ARRAY_PROTOTYPE                                 62
+#define DUK_BIDX_UINT32ARRAY_CONSTRUCTOR                              63
+#define DUK_BIDX_UINT32ARRAY_PROTOTYPE                                64
+#define DUK_BIDX_FLOAT32ARRAY_CONSTRUCTOR                             65
+#define DUK_BIDX_FLOAT32ARRAY_PROTOTYPE                               66
+#define DUK_BIDX_FLOAT64ARRAY_CONSTRUCTOR                             67
+#define DUK_BIDX_FLOAT64ARRAY_PROTOTYPE                               68
+#define DUK_BIDX_NODEJS_BUFFER_CONSTRUCTOR                            69
+#define DUK_BIDX_NODEJS_BUFFER_PROTOTYPE                              70
+
+#define DUK_NUM_BUILTINS                                              71
 
 #elif defined(DUK_USE_DOUBLE_BE)
-extern const duk_uint8_t duk_strings_data[];
+#if !defined(DUK_SINGLE_FILE)
+DUK_INTERNAL_DECL const duk_uint8_t duk_strings_data[2624];
+#endif  /* !DUK_SINGLE_FILE */
 
-#define DUK_STRDATA_DATA_LENGTH                                       1931
+#define DUK_STRDATA_DATA_LENGTH                                       2624
 #define DUK_STRDATA_MAX_STRLEN                                        24
 
 #define DUK_STRIDX_UC_LOGGER                                          0                              /* 'Logger' */
 #define DUK_STRIDX_UC_THREAD                                          1                              /* 'Thread' */
 #define DUK_STRIDX_UC_POINTER                                         2                              /* 'Pointer' */
-#define DUK_STRIDX_UC_BUFFER                                          3                              /* 'Buffer' */
-#define DUK_STRIDX_DEC_ENV                                            4                              /* 'DecEnv' */
-#define DUK_STRIDX_OBJ_ENV                                            5                              /* 'ObjEnv' */
-#define DUK_STRIDX_EMPTY_STRING                                       6                              /* '' */
-#define DUK_STRIDX_GLOBAL                                             7                              /* 'global' */
-#define DUK_STRIDX_UC_ARGUMENTS                                       8                              /* 'Arguments' */
-#define DUK_STRIDX_JSON                                               9                              /* 'JSON' */
-#define DUK_STRIDX_MATH                                               10                             /* 'Math' */
-#define DUK_STRIDX_UC_ERROR                                           11                             /* 'Error' */
-#define DUK_STRIDX_REG_EXP                                            12                             /* 'RegExp' */
-#define DUK_STRIDX_DATE                                               13                             /* 'Date' */
-#define DUK_STRIDX_UC_NUMBER                                          14                             /* 'Number' */
-#define DUK_STRIDX_UC_BOOLEAN                                         15                             /* 'Boolean' */
-#define DUK_STRIDX_UC_STRING                                          16                             /* 'String' */
-#define DUK_STRIDX_ARRAY                                              17                             /* 'Array' */
-#define DUK_STRIDX_UC_FUNCTION                                        18                             /* 'Function' */
-#define DUK_STRIDX_UC_OBJECT                                          19                             /* 'Object' */
-#define DUK_STRIDX_UC_NULL                                            20                             /* 'Null' */
-#define DUK_STRIDX_UC_UNDEFINED                                       21                             /* 'Undefined' */
-#define DUK_STRIDX_JSON_EXT_FUNCTION2                                 22                             /* '{_func:true}' */
-#define DUK_STRIDX_JSON_EXT_FUNCTION1                                 23                             /* '{"_func":true}' */
-#define DUK_STRIDX_JSON_EXT_NEGINF                                    24                             /* '{"_ninf":true}' */
-#define DUK_STRIDX_JSON_EXT_POSINF                                    25                             /* '{"_inf":true}' */
-#define DUK_STRIDX_JSON_EXT_NAN                                       26                             /* '{"_nan":true}' */
-#define DUK_STRIDX_JSON_EXT_UNDEFINED                                 27                             /* '{"_undef":true}' */
-#define DUK_STRIDX_TO_LOG_STRING                                      28                             /* 'toLogString' */
-#define DUK_STRIDX_CLOG                                               29                             /* 'clog' */
-#define DUK_STRIDX_LC_L                                               30                             /* 'l' */
-#define DUK_STRIDX_LC_N                                               31                             /* 'n' */
-#define DUK_STRIDX_LC_FATAL                                           32                             /* 'fatal' */
-#define DUK_STRIDX_LC_ERROR                                           33                             /* 'error' */
-#define DUK_STRIDX_LC_WARN                                            34                             /* 'warn' */
-#define DUK_STRIDX_LC_DEBUG                                           35                             /* 'debug' */
-#define DUK_STRIDX_LC_TRACE                                           36                             /* 'trace' */
-#define DUK_STRIDX_RAW                                                37                             /* 'raw' */
-#define DUK_STRIDX_FMT                                                38                             /* 'fmt' */
-#define DUK_STRIDX_CURRENT                                            39                             /* 'current' */
-#define DUK_STRIDX_RESUME                                             40                             /* 'resume' */
-#define DUK_STRIDX_COMPACT                                            41                             /* 'compact' */
-#define DUK_STRIDX_JC                                                 42                             /* 'jc' */
-#define DUK_STRIDX_JX                                                 43                             /* 'jx' */
-#define DUK_STRIDX_BASE64                                             44                             /* 'base64' */
-#define DUK_STRIDX_HEX                                                45                             /* 'hex' */
-#define DUK_STRIDX_DEC                                                46                             /* 'dec' */
-#define DUK_STRIDX_ENC                                                47                             /* 'enc' */
-#define DUK_STRIDX_FIN                                                48                             /* 'fin' */
-#define DUK_STRIDX_GC                                                 49                             /* 'gc' */
-#define DUK_STRIDX_ACT                                                50                             /* 'act' */
-#define DUK_STRIDX_LC_INFO                                            51                             /* 'info' */
-#define DUK_STRIDX_VERSION                                            52                             /* 'version' */
-#define DUK_STRIDX_ENV                                                53                             /* 'env' */
-#define DUK_STRIDX_MOD_LOADED                                         54                             /* 'modLoaded' */
-#define DUK_STRIDX_MOD_SEARCH                                         55                             /* 'modSearch' */
-#define DUK_STRIDX_ERR_THROW                                          56                             /* 'errThrow' */
-#define DUK_STRIDX_ERR_CREATE                                         57                             /* 'errCreate' */
-#define DUK_STRIDX_COMPILE                                            58                             /* 'compile' */
-#define DUK_STRIDX_INT_REGBASE                                        59                             /* '\x00regbase' */
-#define DUK_STRIDX_INT_THREAD                                         60                             /* '\x00thread' */
-#define DUK_STRIDX_INT_HANDLER                                        61                             /* '\x00handler' */
-#define DUK_STRIDX_INT_FINALIZER                                      62                             /* '\x00finalizer' */
-#define DUK_STRIDX_INT_CALLEE                                         63                             /* '\x00callee' */
-#define DUK_STRIDX_INT_MAP                                            64                             /* '\x00map' */
-#define DUK_STRIDX_INT_ARGS                                           65                             /* '\x00args' */
-#define DUK_STRIDX_INT_THIS                                           66                             /* '\x00this' */
-#define DUK_STRIDX_INT_PC2LINE                                        67                             /* '\x00pc2line' */
-#define DUK_STRIDX_INT_SOURCE                                         68                             /* '\x00source' */
-#define DUK_STRIDX_INT_VARENV                                         69                             /* '\x00varenv' */
-#define DUK_STRIDX_INT_LEXENV                                         70                             /* '\x00lexenv' */
-#define DUK_STRIDX_INT_VARMAP                                         71                             /* '\x00varmap' */
-#define DUK_STRIDX_INT_FORMALS                                        72                             /* '\x00formals' */
-#define DUK_STRIDX_INT_BYTECODE                                       73                             /* '\x00bytecode' */
-#define DUK_STRIDX_INT_NEXT                                           74                             /* '\x00next' */
-#define DUK_STRIDX_INT_TARGET                                         75                             /* '\x00target' */
-#define DUK_STRIDX_INT_VALUE                                          76                             /* '\x00value' */
-#define DUK_STRIDX_LC_POINTER                                         77                             /* 'pointer' */
-#define DUK_STRIDX_LC_BUFFER                                          78                             /* 'buffer' */
-#define DUK_STRIDX_TRACEDATA                                          79                             /* 'tracedata' */
-#define DUK_STRIDX_LINE_NUMBER                                        80                             /* 'lineNumber' */
-#define DUK_STRIDX_FILE_NAME                                          81                             /* 'fileName' */
-#define DUK_STRIDX_PC                                                 82                             /* 'pc' */
-#define DUK_STRIDX_STACK                                              83                             /* 'stack' */
-#define DUK_STRIDX_THROW_TYPE_ERROR                                   84                             /* 'ThrowTypeError' */
-#define DUK_STRIDX_DUKTAPE                                            85                             /* 'Duktape' */
-#define DUK_STRIDX_ID                                                 86                             /* 'id' */
-#define DUK_STRIDX_REQUIRE                                            87                             /* 'require' */
-#define DUK_STRIDX___PROTO__                                          88                             /* '__proto__' */
-#define DUK_STRIDX_SET_PROTOTYPE_OF                                   89                             /* 'setPrototypeOf' */
-#define DUK_STRIDX_OWN_KEYS                                           90                             /* 'ownKeys' */
-#define DUK_STRIDX_ENUMERATE                                          91                             /* 'enumerate' */
-#define DUK_STRIDX_DELETE_PROPERTY                                    92                             /* 'deleteProperty' */
-#define DUK_STRIDX_HAS                                                93                             /* 'has' */
-#define DUK_STRIDX_PROXY                                              94                             /* 'Proxy' */
-#define DUK_STRIDX_CALLEE                                             95                             /* 'callee' */
-#define DUK_STRIDX_INVALID_DATE                                       96                             /* 'Invalid Date' */
-#define DUK_STRIDX_BRACKETED_ELLIPSIS                                 97                             /* '[...]' */
-#define DUK_STRIDX_NEWLINE_TAB                                        98                             /* '\n\t' */
-#define DUK_STRIDX_SPACE                                              99                             /* ' ' */
-#define DUK_STRIDX_COMMA                                              100                            /* ',' */
-#define DUK_STRIDX_MINUS_ZERO                                         101                            /* '-0' */
-#define DUK_STRIDX_PLUS_ZERO                                          102                            /* '+0' */
-#define DUK_STRIDX_ZERO                                               103                            /* '0' */
-#define DUK_STRIDX_MINUS_INFINITY                                     104                            /* '-Infinity' */
-#define DUK_STRIDX_PLUS_INFINITY                                      105                            /* '+Infinity' */
-#define DUK_STRIDX_INFINITY                                           106                            /* 'Infinity' */
-#define DUK_STRIDX_LC_OBJECT                                          107                            /* 'object' */
-#define DUK_STRIDX_LC_STRING                                          108                            /* 'string' */
-#define DUK_STRIDX_LC_NUMBER                                          109                            /* 'number' */
-#define DUK_STRIDX_LC_BOOLEAN                                         110                            /* 'boolean' */
-#define DUK_STRIDX_LC_UNDEFINED                                       111                            /* 'undefined' */
-#define DUK_STRIDX_STRINGIFY                                          112                            /* 'stringify' */
-#define DUK_STRIDX_TAN                                                113                            /* 'tan' */
-#define DUK_STRIDX_SQRT                                               114                            /* 'sqrt' */
-#define DUK_STRIDX_SIN                                                115                            /* 'sin' */
-#define DUK_STRIDX_ROUND                                              116                            /* 'round' */
-#define DUK_STRIDX_RANDOM                                             117                            /* 'random' */
-#define DUK_STRIDX_POW                                                118                            /* 'pow' */
-#define DUK_STRIDX_MIN                                                119                            /* 'min' */
-#define DUK_STRIDX_MAX                                                120                            /* 'max' */
-#define DUK_STRIDX_LOG                                                121                            /* 'log' */
-#define DUK_STRIDX_FLOOR                                              122                            /* 'floor' */
-#define DUK_STRIDX_EXP                                                123                            /* 'exp' */
-#define DUK_STRIDX_COS                                                124                            /* 'cos' */
-#define DUK_STRIDX_CEIL                                               125                            /* 'ceil' */
-#define DUK_STRIDX_ATAN2                                              126                            /* 'atan2' */
-#define DUK_STRIDX_ATAN                                               127                            /* 'atan' */
-#define DUK_STRIDX_ASIN                                               128                            /* 'asin' */
-#define DUK_STRIDX_ACOS                                               129                            /* 'acos' */
-#define DUK_STRIDX_ABS                                                130                            /* 'abs' */
-#define DUK_STRIDX_SQRT2                                              131                            /* 'SQRT2' */
-#define DUK_STRIDX_SQRT1_2                                            132                            /* 'SQRT1_2' */
-#define DUK_STRIDX_PI                                                 133                            /* 'PI' */
-#define DUK_STRIDX_LOG10E                                             134                            /* 'LOG10E' */
-#define DUK_STRIDX_LOG2E                                              135                            /* 'LOG2E' */
-#define DUK_STRIDX_LN2                                                136                            /* 'LN2' */
-#define DUK_STRIDX_LN10                                               137                            /* 'LN10' */
-#define DUK_STRIDX_E                                                  138                            /* 'E' */
-#define DUK_STRIDX_MESSAGE                                            139                            /* 'message' */
-#define DUK_STRIDX_NAME                                               140                            /* 'name' */
-#define DUK_STRIDX_INPUT                                              141                            /* 'input' */
-#define DUK_STRIDX_INDEX                                              142                            /* 'index' */
-#define DUK_STRIDX_ESCAPED_EMPTY_REGEXP                               143                            /* '(?:)' */
-#define DUK_STRIDX_LAST_INDEX                                         144                            /* 'lastIndex' */
-#define DUK_STRIDX_MULTILINE                                          145                            /* 'multiline' */
-#define DUK_STRIDX_IGNORE_CASE                                        146                            /* 'ignoreCase' */
-#define DUK_STRIDX_SOURCE                                             147                            /* 'source' */
-#define DUK_STRIDX_TEST                                               148                            /* 'test' */
-#define DUK_STRIDX_EXEC                                               149                            /* 'exec' */
-#define DUK_STRIDX_TO_GMT_STRING                                      150                            /* 'toGMTString' */
-#define DUK_STRIDX_SET_YEAR                                           151                            /* 'setYear' */
-#define DUK_STRIDX_GET_YEAR                                           152                            /* 'getYear' */
-#define DUK_STRIDX_TO_JSON                                            153                            /* 'toJSON' */
-#define DUK_STRIDX_TO_ISO_STRING                                      154                            /* 'toISOString' */
-#define DUK_STRIDX_TO_UTC_STRING                                      155                            /* 'toUTCString' */
-#define DUK_STRIDX_SET_UTC_FULL_YEAR                                  156                            /* 'setUTCFullYear' */
-#define DUK_STRIDX_SET_FULL_YEAR                                      157                            /* 'setFullYear' */
-#define DUK_STRIDX_SET_UTC_MONTH                                      158                            /* 'setUTCMonth' */
-#define DUK_STRIDX_SET_MONTH                                          159                            /* 'setMonth' */
-#define DUK_STRIDX_SET_UTC_DATE                                       160                            /* 'setUTCDate' */
-#define DUK_STRIDX_SET_DATE                                           161                            /* 'setDate' */
-#define DUK_STRIDX_SET_UTC_HOURS                                      162                            /* 'setUTCHours' */
-#define DUK_STRIDX_SET_HOURS                                          163                            /* 'setHours' */
-#define DUK_STRIDX_SET_UTC_MINUTES                                    164                            /* 'setUTCMinutes' */
-#define DUK_STRIDX_SET_MINUTES                                        165                            /* 'setMinutes' */
-#define DUK_STRIDX_SET_UTC_SECONDS                                    166                            /* 'setUTCSeconds' */
-#define DUK_STRIDX_SET_SECONDS                                        167                            /* 'setSeconds' */
-#define DUK_STRIDX_SET_UTC_MILLISECONDS                               168                            /* 'setUTCMilliseconds' */
-#define DUK_STRIDX_SET_MILLISECONDS                                   169                            /* 'setMilliseconds' */
-#define DUK_STRIDX_SET_TIME                                           170                            /* 'setTime' */
-#define DUK_STRIDX_GET_TIMEZONE_OFFSET                                171                            /* 'getTimezoneOffset' */
-#define DUK_STRIDX_GET_UTC_MILLISECONDS                               172                            /* 'getUTCMilliseconds' */
-#define DUK_STRIDX_GET_MILLISECONDS                                   173                            /* 'getMilliseconds' */
-#define DUK_STRIDX_GET_UTC_SECONDS                                    174                            /* 'getUTCSeconds' */
-#define DUK_STRIDX_GET_SECONDS                                        175                            /* 'getSeconds' */
-#define DUK_STRIDX_GET_UTC_MINUTES                                    176                            /* 'getUTCMinutes' */
-#define DUK_STRIDX_GET_MINUTES                                        177                            /* 'getMinutes' */
-#define DUK_STRIDX_GET_UTC_HOURS                                      178                            /* 'getUTCHours' */
-#define DUK_STRIDX_GET_HOURS                                          179                            /* 'getHours' */
-#define DUK_STRIDX_GET_UTC_DAY                                        180                            /* 'getUTCDay' */
-#define DUK_STRIDX_GET_DAY                                            181                            /* 'getDay' */
-#define DUK_STRIDX_GET_UTC_DATE                                       182                            /* 'getUTCDate' */
-#define DUK_STRIDX_GET_DATE                                           183                            /* 'getDate' */
-#define DUK_STRIDX_GET_UTC_MONTH                                      184                            /* 'getUTCMonth' */
-#define DUK_STRIDX_GET_MONTH                                          185                            /* 'getMonth' */
-#define DUK_STRIDX_GET_UTC_FULL_YEAR                                  186                            /* 'getUTCFullYear' */
-#define DUK_STRIDX_GET_FULL_YEAR                                      187                            /* 'getFullYear' */
-#define DUK_STRIDX_GET_TIME                                           188                            /* 'getTime' */
-#define DUK_STRIDX_TO_LOCALE_TIME_STRING                              189                            /* 'toLocaleTimeString' */
-#define DUK_STRIDX_TO_LOCALE_DATE_STRING                              190                            /* 'toLocaleDateString' */
-#define DUK_STRIDX_TO_TIME_STRING                                     191                            /* 'toTimeString' */
-#define DUK_STRIDX_TO_DATE_STRING                                     192                            /* 'toDateString' */
-#define DUK_STRIDX_NOW                                                193                            /* 'now' */
-#define DUK_STRIDX_UTC                                                194                            /* 'UTC' */
-#define DUK_STRIDX_PARSE                                              195                            /* 'parse' */
-#define DUK_STRIDX_TO_PRECISION                                       196                            /* 'toPrecision' */
-#define DUK_STRIDX_TO_EXPONENTIAL                                     197                            /* 'toExponential' */
-#define DUK_STRIDX_TO_FIXED                                           198                            /* 'toFixed' */
-#define DUK_STRIDX_POSITIVE_INFINITY                                  199                            /* 'POSITIVE_INFINITY' */
-#define DUK_STRIDX_NEGATIVE_INFINITY                                  200                            /* 'NEGATIVE_INFINITY' */
-#define DUK_STRIDX_NAN                                                201                            /* 'NaN' */
-#define DUK_STRIDX_MIN_VALUE                                          202                            /* 'MIN_VALUE' */
-#define DUK_STRIDX_MAX_VALUE                                          203                            /* 'MAX_VALUE' */
-#define DUK_STRIDX_SUBSTR                                             204                            /* 'substr' */
-#define DUK_STRIDX_TRIM                                               205                            /* 'trim' */
-#define DUK_STRIDX_TO_LOCALE_UPPER_CASE                               206                            /* 'toLocaleUpperCase' */
-#define DUK_STRIDX_TO_UPPER_CASE                                      207                            /* 'toUpperCase' */
-#define DUK_STRIDX_TO_LOCALE_LOWER_CASE                               208                            /* 'toLocaleLowerCase' */
-#define DUK_STRIDX_TO_LOWER_CASE                                      209                            /* 'toLowerCase' */
-#define DUK_STRIDX_SUBSTRING                                          210                            /* 'substring' */
-#define DUK_STRIDX_SPLIT                                              211                            /* 'split' */
-#define DUK_STRIDX_SEARCH                                             212                            /* 'search' */
-#define DUK_STRIDX_REPLACE                                            213                            /* 'replace' */
-#define DUK_STRIDX_MATCH                                              214                            /* 'match' */
-#define DUK_STRIDX_LOCALE_COMPARE                                     215                            /* 'localeCompare' */
-#define DUK_STRIDX_CHAR_CODE_AT                                       216                            /* 'charCodeAt' */
-#define DUK_STRIDX_CHAR_AT                                            217                            /* 'charAt' */
-#define DUK_STRIDX_FROM_CHAR_CODE                                     218                            /* 'fromCharCode' */
-#define DUK_STRIDX_REDUCE_RIGHT                                       219                            /* 'reduceRight' */
-#define DUK_STRIDX_REDUCE                                             220                            /* 'reduce' */
-#define DUK_STRIDX_FILTER                                             221                            /* 'filter' */
-#define DUK_STRIDX_MAP                                                222                            /* 'map' */
-#define DUK_STRIDX_FOR_EACH                                           223                            /* 'forEach' */
-#define DUK_STRIDX_SOME                                               224                            /* 'some' */
-#define DUK_STRIDX_EVERY                                              225                            /* 'every' */
-#define DUK_STRIDX_LAST_INDEX_OF                                      226                            /* 'lastIndexOf' */
-#define DUK_STRIDX_INDEX_OF                                           227                            /* 'indexOf' */
-#define DUK_STRIDX_UNSHIFT                                            228                            /* 'unshift' */
-#define DUK_STRIDX_SPLICE                                             229                            /* 'splice' */
-#define DUK_STRIDX_SORT                                               230                            /* 'sort' */
-#define DUK_STRIDX_SLICE                                              231                            /* 'slice' */
-#define DUK_STRIDX_SHIFT                                              232                            /* 'shift' */
-#define DUK_STRIDX_REVERSE                                            233                            /* 'reverse' */
-#define DUK_STRIDX_PUSH                                               234                            /* 'push' */
-#define DUK_STRIDX_POP                                                235                            /* 'pop' */
-#define DUK_STRIDX_JOIN                                               236                            /* 'join' */
-#define DUK_STRIDX_CONCAT                                             237                            /* 'concat' */
-#define DUK_STRIDX_IS_ARRAY                                           238                            /* 'isArray' */
-#define DUK_STRIDX_LC_ARGUMENTS                                       239                            /* 'arguments' */
-#define DUK_STRIDX_CALLER                                             240                            /* 'caller' */
-#define DUK_STRIDX_BIND                                               241                            /* 'bind' */
-#define DUK_STRIDX_CALL                                               242                            /* 'call' */
-#define DUK_STRIDX_APPLY                                              243                            /* 'apply' */
-#define DUK_STRIDX_PROPERTY_IS_ENUMERABLE                             244                            /* 'propertyIsEnumerable' */
-#define DUK_STRIDX_IS_PROTOTYPE_OF                                    245                            /* 'isPrototypeOf' */
-#define DUK_STRIDX_HAS_OWN_PROPERTY                                   246                            /* 'hasOwnProperty' */
-#define DUK_STRIDX_VALUE_OF                                           247                            /* 'valueOf' */
-#define DUK_STRIDX_TO_LOCALE_STRING                                   248                            /* 'toLocaleString' */
-#define DUK_STRIDX_TO_STRING                                          249                            /* 'toString' */
-#define DUK_STRIDX_CONSTRUCTOR                                        250                            /* 'constructor' */
-#define DUK_STRIDX_SET                                                251                            /* 'set' */
-#define DUK_STRIDX_GET                                                252                            /* 'get' */
-#define DUK_STRIDX_ENUMERABLE                                         253                            /* 'enumerable' */
-#define DUK_STRIDX_CONFIGURABLE                                       254                            /* 'configurable' */
-#define DUK_STRIDX_WRITABLE                                           255                            /* 'writable' */
-#define DUK_STRIDX_VALUE                                              256                            /* 'value' */
-#define DUK_STRIDX_KEYS                                               257                            /* 'keys' */
-#define DUK_STRIDX_IS_EXTENSIBLE                                      258                            /* 'isExtensible' */
-#define DUK_STRIDX_IS_FROZEN                                          259                            /* 'isFrozen' */
-#define DUK_STRIDX_IS_SEALED                                          260                            /* 'isSealed' */
-#define DUK_STRIDX_PREVENT_EXTENSIONS                                 261                            /* 'preventExtensions' */
-#define DUK_STRIDX_FREEZE                                             262                            /* 'freeze' */
-#define DUK_STRIDX_SEAL                                               263                            /* 'seal' */
-#define DUK_STRIDX_DEFINE_PROPERTIES                                  264                            /* 'defineProperties' */
-#define DUK_STRIDX_DEFINE_PROPERTY                                    265                            /* 'defineProperty' */
-#define DUK_STRIDX_CREATE                                             266                            /* 'create' */
-#define DUK_STRIDX_GET_OWN_PROPERTY_NAMES                             267                            /* 'getOwnPropertyNames' */
-#define DUK_STRIDX_GET_OWN_PROPERTY_DESCRIPTOR                        268                            /* 'getOwnPropertyDescriptor' */
-#define DUK_STRIDX_GET_PROTOTYPE_OF                                   269                            /* 'getPrototypeOf' */
-#define DUK_STRIDX_PROTOTYPE                                          270                            /* 'prototype' */
-#define DUK_STRIDX_LENGTH                                             271                            /* 'length' */
-#define DUK_STRIDX_ALERT                                              272                            /* 'alert' */
-#define DUK_STRIDX_PRINT                                              273                            /* 'print' */
-#define DUK_STRIDX_UNESCAPE                                           274                            /* 'unescape' */
-#define DUK_STRIDX_ESCAPE                                             275                            /* 'escape' */
-#define DUK_STRIDX_ENCODE_URI_COMPONENT                               276                            /* 'encodeURIComponent' */
-#define DUK_STRIDX_ENCODE_URI                                         277                            /* 'encodeURI' */
-#define DUK_STRIDX_DECODE_URI_COMPONENT                               278                            /* 'decodeURIComponent' */
-#define DUK_STRIDX_DECODE_URI                                         279                            /* 'decodeURI' */
-#define DUK_STRIDX_IS_FINITE                                          280                            /* 'isFinite' */
-#define DUK_STRIDX_IS_NAN                                             281                            /* 'isNaN' */
-#define DUK_STRIDX_PARSE_FLOAT                                        282                            /* 'parseFloat' */
-#define DUK_STRIDX_PARSE_INT                                          283                            /* 'parseInt' */
-#define DUK_STRIDX_EVAL                                               284                            /* 'eval' */
-#define DUK_STRIDX_URI_ERROR                                          285                            /* 'URIError' */
-#define DUK_STRIDX_TYPE_ERROR                                         286                            /* 'TypeError' */
-#define DUK_STRIDX_SYNTAX_ERROR                                       287                            /* 'SyntaxError' */
-#define DUK_STRIDX_REFERENCE_ERROR                                    288                            /* 'ReferenceError' */
-#define DUK_STRIDX_RANGE_ERROR                                        289                            /* 'RangeError' */
-#define DUK_STRIDX_EVAL_ERROR                                         290                            /* 'EvalError' */
-#define DUK_STRIDX_BREAK                                              291                            /* 'break' */
-#define DUK_STRIDX_CASE                                               292                            /* 'case' */
-#define DUK_STRIDX_CATCH                                              293                            /* 'catch' */
-#define DUK_STRIDX_CONTINUE                                           294                            /* 'continue' */
-#define DUK_STRIDX_DEBUGGER                                           295                            /* 'debugger' */
-#define DUK_STRIDX_DEFAULT                                            296                            /* 'default' */
-#define DUK_STRIDX_DELETE                                             297                            /* 'delete' */
-#define DUK_STRIDX_DO                                                 298                            /* 'do' */
-#define DUK_STRIDX_ELSE                                               299                            /* 'else' */
-#define DUK_STRIDX_FINALLY                                            300                            /* 'finally' */
-#define DUK_STRIDX_FOR                                                301                            /* 'for' */
-#define DUK_STRIDX_LC_FUNCTION                                        302                            /* 'function' */
-#define DUK_STRIDX_IF                                                 303                            /* 'if' */
-#define DUK_STRIDX_IN                                                 304                            /* 'in' */
-#define DUK_STRIDX_INSTANCEOF                                         305                            /* 'instanceof' */
-#define DUK_STRIDX_NEW                                                306                            /* 'new' */
-#define DUK_STRIDX_RETURN                                             307                            /* 'return' */
-#define DUK_STRIDX_SWITCH                                             308                            /* 'switch' */
-#define DUK_STRIDX_THIS                                               309                            /* 'this' */
-#define DUK_STRIDX_THROW                                              310                            /* 'throw' */
-#define DUK_STRIDX_TRY                                                311                            /* 'try' */
-#define DUK_STRIDX_TYPEOF                                             312                            /* 'typeof' */
-#define DUK_STRIDX_VAR                                                313                            /* 'var' */
-#define DUK_STRIDX_VOID                                               314                            /* 'void' */
-#define DUK_STRIDX_WHILE                                              315                            /* 'while' */
-#define DUK_STRIDX_WITH                                               316                            /* 'with' */
-#define DUK_STRIDX_CLASS                                              317                            /* 'class' */
-#define DUK_STRIDX_CONST                                              318                            /* 'const' */
-#define DUK_STRIDX_ENUM                                               319                            /* 'enum' */
-#define DUK_STRIDX_EXPORT                                             320                            /* 'export' */
-#define DUK_STRIDX_EXTENDS                                            321                            /* 'extends' */
-#define DUK_STRIDX_IMPORT                                             322                            /* 'import' */
-#define DUK_STRIDX_SUPER                                              323                            /* 'super' */
-#define DUK_STRIDX_LC_NULL                                            324                            /* 'null' */
-#define DUK_STRIDX_TRUE                                               325                            /* 'true' */
-#define DUK_STRIDX_FALSE                                              326                            /* 'false' */
-#define DUK_STRIDX_IMPLEMENTS                                         327                            /* 'implements' */
-#define DUK_STRIDX_INTERFACE                                          328                            /* 'interface' */
-#define DUK_STRIDX_LET                                                329                            /* 'let' */
-#define DUK_STRIDX_PACKAGE                                            330                            /* 'package' */
-#define DUK_STRIDX_PRIVATE                                            331                            /* 'private' */
-#define DUK_STRIDX_PROTECTED                                          332                            /* 'protected' */
-#define DUK_STRIDX_PUBLIC                                             333                            /* 'public' */
-#define DUK_STRIDX_STATIC                                             334                            /* 'static' */
-#define DUK_STRIDX_YIELD                                              335                            /* 'yield' */
+#define DUK_STRIDX_DEC_ENV                                            3                              /* 'DecEnv' */
+#define DUK_STRIDX_OBJ_ENV                                            4                              /* 'ObjEnv' */
+#define DUK_STRIDX_FLOAT64_ARRAY                                      5                              /* 'Float64Array' */
+#define DUK_STRIDX_FLOAT32_ARRAY                                      6                              /* 'Float32Array' */
+#define DUK_STRIDX_UINT32_ARRAY                                       7                              /* 'Uint32Array' */
+#define DUK_STRIDX_INT32_ARRAY                                        8                              /* 'Int32Array' */
+#define DUK_STRIDX_UINT16_ARRAY                                       9                              /* 'Uint16Array' */
+#define DUK_STRIDX_INT16_ARRAY                                        10                             /* 'Int16Array' */
+#define DUK_STRIDX_UINT8_CLAMPED_ARRAY                                11                             /* 'Uint8ClampedArray' */
+#define DUK_STRIDX_UINT8_ARRAY                                        12                             /* 'Uint8Array' */
+#define DUK_STRIDX_INT8_ARRAY                                         13                             /* 'Int8Array' */
+#define DUK_STRIDX_DATA_VIEW                                          14                             /* 'DataView' */
+#define DUK_STRIDX_ARRAY_BUFFER                                       15                             /* 'ArrayBuffer' */
+#define DUK_STRIDX_UC_BUFFER                                          16                             /* 'Buffer' */
+#define DUK_STRIDX_EMPTY_STRING                                       17                             /* '' */
+#define DUK_STRIDX_GLOBAL                                             18                             /* 'global' */
+#define DUK_STRIDX_UC_ARGUMENTS                                       19                             /* 'Arguments' */
+#define DUK_STRIDX_JSON                                               20                             /* 'JSON' */
+#define DUK_STRIDX_MATH                                               21                             /* 'Math' */
+#define DUK_STRIDX_UC_ERROR                                           22                             /* 'Error' */
+#define DUK_STRIDX_REG_EXP                                            23                             /* 'RegExp' */
+#define DUK_STRIDX_DATE                                               24                             /* 'Date' */
+#define DUK_STRIDX_UC_NUMBER                                          25                             /* 'Number' */
+#define DUK_STRIDX_UC_BOOLEAN                                         26                             /* 'Boolean' */
+#define DUK_STRIDX_UC_STRING                                          27                             /* 'String' */
+#define DUK_STRIDX_ARRAY                                              28                             /* 'Array' */
+#define DUK_STRIDX_UC_FUNCTION                                        29                             /* 'Function' */
+#define DUK_STRIDX_UC_OBJECT                                          30                             /* 'Object' */
+#define DUK_STRIDX_UC_NULL                                            31                             /* 'Null' */
+#define DUK_STRIDX_UC_UNDEFINED                                       32                             /* 'Undefined' */
+#define DUK_STRIDX_JSON_EXT_FUNCTION2                                 33                             /* '{_func:true}' */
+#define DUK_STRIDX_JSON_EXT_FUNCTION1                                 34                             /* '{"_func":true}' */
+#define DUK_STRIDX_JSON_EXT_NEGINF                                    35                             /* '{"_ninf":true}' */
+#define DUK_STRIDX_JSON_EXT_POSINF                                    36                             /* '{"_inf":true}' */
+#define DUK_STRIDX_JSON_EXT_NAN                                       37                             /* '{"_nan":true}' */
+#define DUK_STRIDX_JSON_EXT_UNDEFINED                                 38                             /* '{"_undef":true}' */
+#define DUK_STRIDX_TO_LOG_STRING                                      39                             /* 'toLogString' */
+#define DUK_STRIDX_CLOG                                               40                             /* 'clog' */
+#define DUK_STRIDX_LC_L                                               41                             /* 'l' */
+#define DUK_STRIDX_LC_N                                               42                             /* 'n' */
+#define DUK_STRIDX_LC_FATAL                                           43                             /* 'fatal' */
+#define DUK_STRIDX_LC_ERROR                                           44                             /* 'error' */
+#define DUK_STRIDX_LC_WARN                                            45                             /* 'warn' */
+#define DUK_STRIDX_LC_DEBUG                                           46                             /* 'debug' */
+#define DUK_STRIDX_LC_TRACE                                           47                             /* 'trace' */
+#define DUK_STRIDX_RAW                                                48                             /* 'raw' */
+#define DUK_STRIDX_FMT                                                49                             /* 'fmt' */
+#define DUK_STRIDX_CURRENT                                            50                             /* 'current' */
+#define DUK_STRIDX_RESUME                                             51                             /* 'resume' */
+#define DUK_STRIDX_COMPACT                                            52                             /* 'compact' */
+#define DUK_STRIDX_JC                                                 53                             /* 'jc' */
+#define DUK_STRIDX_JX                                                 54                             /* 'jx' */
+#define DUK_STRIDX_BASE64                                             55                             /* 'base64' */
+#define DUK_STRIDX_HEX                                                56                             /* 'hex' */
+#define DUK_STRIDX_DEC                                                57                             /* 'dec' */
+#define DUK_STRIDX_ENC                                                58                             /* 'enc' */
+#define DUK_STRIDX_FIN                                                59                             /* 'fin' */
+#define DUK_STRIDX_GC                                                 60                             /* 'gc' */
+#define DUK_STRIDX_ACT                                                61                             /* 'act' */
+#define DUK_STRIDX_LC_INFO                                            62                             /* 'info' */
+#define DUK_STRIDX_VERSION                                            63                             /* 'version' */
+#define DUK_STRIDX_ENV                                                64                             /* 'env' */
+#define DUK_STRIDX_MOD_LOADED                                         65                             /* 'modLoaded' */
+#define DUK_STRIDX_MOD_SEARCH                                         66                             /* 'modSearch' */
+#define DUK_STRIDX_ERR_THROW                                          67                             /* 'errThrow' */
+#define DUK_STRIDX_ERR_CREATE                                         68                             /* 'errCreate' */
+#define DUK_STRIDX_COMPILE                                            69                             /* 'compile' */
+#define DUK_STRIDX_INT_REGBASE                                        70                             /* '\x00Regbase' */
+#define DUK_STRIDX_INT_THREAD                                         71                             /* '\x00Thread' */
+#define DUK_STRIDX_INT_HANDLER                                        72                             /* '\x00Handler' */
+#define DUK_STRIDX_INT_FINALIZER                                      73                             /* '\x00Finalizer' */
+#define DUK_STRIDX_INT_CALLEE                                         74                             /* '\x00Callee' */
+#define DUK_STRIDX_INT_MAP                                            75                             /* '\x00Map' */
+#define DUK_STRIDX_INT_ARGS                                           76                             /* '\x00Args' */
+#define DUK_STRIDX_INT_THIS                                           77                             /* '\x00This' */
+#define DUK_STRIDX_INT_PC2LINE                                        78                             /* '\x00Pc2line' */
+#define DUK_STRIDX_INT_SOURCE                                         79                             /* '\x00Source' */
+#define DUK_STRIDX_INT_VARENV                                         80                             /* '\x00Varenv' */
+#define DUK_STRIDX_INT_LEXENV                                         81                             /* '\x00Lexenv' */
+#define DUK_STRIDX_INT_VARMAP                                         82                             /* '\x00Varmap' */
+#define DUK_STRIDX_INT_FORMALS                                        83                             /* '\x00Formals' */
+#define DUK_STRIDX_INT_BYTECODE                                       84                             /* '\x00Bytecode' */
+#define DUK_STRIDX_INT_NEXT                                           85                             /* '\x00Next' */
+#define DUK_STRIDX_INT_TARGET                                         86                             /* '\x00Target' */
+#define DUK_STRIDX_INT_VALUE                                          87                             /* '\x00Value' */
+#define DUK_STRIDX_LC_POINTER                                         88                             /* 'pointer' */
+#define DUK_STRIDX_INT_TRACEDATA                                      89                             /* '\x00Tracedata' */
+#define DUK_STRIDX_LINE_NUMBER                                        90                             /* 'lineNumber' */
+#define DUK_STRIDX_FILE_NAME                                          91                             /* 'fileName' */
+#define DUK_STRIDX_PC                                                 92                             /* 'pc' */
+#define DUK_STRIDX_STACK                                              93                             /* 'stack' */
+#define DUK_STRIDX_THROW_TYPE_ERROR                                   94                             /* 'ThrowTypeError' */
+#define DUK_STRIDX_DUKTAPE                                            95                             /* 'Duktape' */
+#define DUK_STRIDX_SET_FLOAT64                                        96                             /* 'setFloat64' */
+#define DUK_STRIDX_SET_FLOAT32                                        97                             /* 'setFloat32' */
+#define DUK_STRIDX_SET_UINT32                                         98                             /* 'setUint32' */
+#define DUK_STRIDX_SET_INT32                                          99                             /* 'setInt32' */
+#define DUK_STRIDX_SET_UINT16                                         100                            /* 'setUint16' */
+#define DUK_STRIDX_SET_INT16                                          101                            /* 'setInt16' */
+#define DUK_STRIDX_SET_UINT8                                          102                            /* 'setUint8' */
+#define DUK_STRIDX_SET_INT8                                           103                            /* 'setInt8' */
+#define DUK_STRIDX_GET_FLOAT64                                        104                            /* 'getFloat64' */
+#define DUK_STRIDX_GET_FLOAT32                                        105                            /* 'getFloat32' */
+#define DUK_STRIDX_GET_UINT32                                         106                            /* 'getUint32' */
+#define DUK_STRIDX_GET_INT32                                          107                            /* 'getInt32' */
+#define DUK_STRIDX_GET_UINT16                                         108                            /* 'getUint16' */
+#define DUK_STRIDX_GET_INT16                                          109                            /* 'getInt16' */
+#define DUK_STRIDX_GET_UINT8                                          110                            /* 'getUint8' */
+#define DUK_STRIDX_GET_INT8                                           111                            /* 'getInt8' */
+#define DUK_STRIDX_SUBARRAY                                           112                            /* 'subarray' */
+#define DUK_STRIDX_BYTES_PER_ELEMENT                                  113                            /* 'BYTES_PER_ELEMENT' */
+#define DUK_STRIDX_BYTE_OFFSET                                        114                            /* 'byteOffset' */
+#define DUK_STRIDX_LC_BUFFER                                          115                            /* 'buffer' */
+#define DUK_STRIDX_IS_VIEW                                            116                            /* 'isView' */
+#define DUK_STRIDX_DATA                                               117                            /* 'data' */
+#define DUK_STRIDX_TYPE                                               118                            /* 'type' */
+#define DUK_STRIDX_WRITE_INT_BE                                       119                            /* 'writeIntBE' */
+#define DUK_STRIDX_WRITE_INT_LE                                       120                            /* 'writeIntLE' */
+#define DUK_STRIDX_WRITE_UINT_BE                                      121                            /* 'writeUIntBE' */
+#define DUK_STRIDX_WRITE_UINT_LE                                      122                            /* 'writeUIntLE' */
+#define DUK_STRIDX_WRITE_DOUBLE_BE                                    123                            /* 'writeDoubleBE' */
+#define DUK_STRIDX_WRITE_DOUBLE_LE                                    124                            /* 'writeDoubleLE' */
+#define DUK_STRIDX_WRITE_FLOAT_BE                                     125                            /* 'writeFloatBE' */
+#define DUK_STRIDX_WRITE_FLOAT_LE                                     126                            /* 'writeFloatLE' */
+#define DUK_STRIDX_WRITE_INT32_BE                                     127                            /* 'writeInt32BE' */
+#define DUK_STRIDX_WRITE_INT32_LE                                     128                            /* 'writeInt32LE' */
+#define DUK_STRIDX_WRITE_UINT32_BE                                    129                            /* 'writeUInt32BE' */
+#define DUK_STRIDX_WRITE_UINT32_LE                                    130                            /* 'writeUInt32LE' */
+#define DUK_STRIDX_WRITE_INT16_BE                                     131                            /* 'writeInt16BE' */
+#define DUK_STRIDX_WRITE_INT16_LE                                     132                            /* 'writeInt16LE' */
+#define DUK_STRIDX_WRITE_UINT16_BE                                    133                            /* 'writeUInt16BE' */
+#define DUK_STRIDX_WRITE_UINT16_LE                                    134                            /* 'writeUInt16LE' */
+#define DUK_STRIDX_WRITE_INT8                                         135                            /* 'writeInt8' */
+#define DUK_STRIDX_WRITE_UINT8                                        136                            /* 'writeUInt8' */
+#define DUK_STRIDX_READ_INT_BE                                        137                            /* 'readIntBE' */
+#define DUK_STRIDX_READ_INT_LE                                        138                            /* 'readIntLE' */
+#define DUK_STRIDX_READ_UINT_BE                                       139                            /* 'readUIntBE' */
+#define DUK_STRIDX_READ_UINT_LE                                       140                            /* 'readUIntLE' */
+#define DUK_STRIDX_READ_DOUBLE_BE                                     141                            /* 'readDoubleBE' */
+#define DUK_STRIDX_READ_DOUBLE_LE                                     142                            /* 'readDoubleLE' */
+#define DUK_STRIDX_READ_FLOAT_BE                                      143                            /* 'readFloatBE' */
+#define DUK_STRIDX_READ_FLOAT_LE                                      144                            /* 'readFloatLE' */
+#define DUK_STRIDX_READ_INT32_BE                                      145                            /* 'readInt32BE' */
+#define DUK_STRIDX_READ_INT32_LE                                      146                            /* 'readInt32LE' */
+#define DUK_STRIDX_READ_UINT32_BE                                     147                            /* 'readUInt32BE' */
+#define DUK_STRIDX_READ_UINT32_LE                                     148                            /* 'readUInt32LE' */
+#define DUK_STRIDX_READ_INT16_BE                                      149                            /* 'readInt16BE' */
+#define DUK_STRIDX_READ_INT16_LE                                      150                            /* 'readInt16LE' */
+#define DUK_STRIDX_READ_UINT16_BE                                     151                            /* 'readUInt16BE' */
+#define DUK_STRIDX_READ_UINT16_LE                                     152                            /* 'readUInt16LE' */
+#define DUK_STRIDX_READ_INT8                                          153                            /* 'readInt8' */
+#define DUK_STRIDX_READ_UINT8                                         154                            /* 'readUInt8' */
+#define DUK_STRIDX_COPY                                               155                            /* 'copy' */
+#define DUK_STRIDX_EQUALS                                             156                            /* 'equals' */
+#define DUK_STRIDX_FILL                                               157                            /* 'fill' */
+#define DUK_STRIDX_WRITE                                              158                            /* 'write' */
+#define DUK_STRIDX_COMPARE                                            159                            /* 'compare' */
+#define DUK_STRIDX_BYTE_LENGTH                                        160                            /* 'byteLength' */
+#define DUK_STRIDX_IS_BUFFER                                          161                            /* 'isBuffer' */
+#define DUK_STRIDX_IS_ENCODING                                        162                            /* 'isEncoding' */
+#define DUK_STRIDX_EXPORTS                                            163                            /* 'exports' */
+#define DUK_STRIDX_ID                                                 164                            /* 'id' */
+#define DUK_STRIDX_REQUIRE                                            165                            /* 'require' */
+#define DUK_STRIDX___PROTO__                                          166                            /* '__proto__' */
+#define DUK_STRIDX_SET_PROTOTYPE_OF                                   167                            /* 'setPrototypeOf' */
+#define DUK_STRIDX_OWN_KEYS                                           168                            /* 'ownKeys' */
+#define DUK_STRIDX_ENUMERATE                                          169                            /* 'enumerate' */
+#define DUK_STRIDX_DELETE_PROPERTY                                    170                            /* 'deleteProperty' */
+#define DUK_STRIDX_HAS                                                171                            /* 'has' */
+#define DUK_STRIDX_PROXY                                              172                            /* 'Proxy' */
+#define DUK_STRIDX_CALLEE                                             173                            /* 'callee' */
+#define DUK_STRIDX_INVALID_DATE                                       174                            /* 'Invalid Date' */
+#define DUK_STRIDX_BRACKETED_ELLIPSIS                                 175                            /* '[...]' */
+#define DUK_STRIDX_NEWLINE_TAB                                        176                            /* '\n\t' */
+#define DUK_STRIDX_SPACE                                              177                            /* ' ' */
+#define DUK_STRIDX_COMMA                                              178                            /* ',' */
+#define DUK_STRIDX_MINUS_ZERO                                         179                            /* '-0' */
+#define DUK_STRIDX_PLUS_ZERO                                          180                            /* '+0' */
+#define DUK_STRIDX_ZERO                                               181                            /* '0' */
+#define DUK_STRIDX_MINUS_INFINITY                                     182                            /* '-Infinity' */
+#define DUK_STRIDX_PLUS_INFINITY                                      183                            /* '+Infinity' */
+#define DUK_STRIDX_INFINITY                                           184                            /* 'Infinity' */
+#define DUK_STRIDX_LC_OBJECT                                          185                            /* 'object' */
+#define DUK_STRIDX_LC_STRING                                          186                            /* 'string' */
+#define DUK_STRIDX_LC_NUMBER                                          187                            /* 'number' */
+#define DUK_STRIDX_LC_BOOLEAN                                         188                            /* 'boolean' */
+#define DUK_STRIDX_LC_UNDEFINED                                       189                            /* 'undefined' */
+#define DUK_STRIDX_STRINGIFY                                          190                            /* 'stringify' */
+#define DUK_STRIDX_TAN                                                191                            /* 'tan' */
+#define DUK_STRIDX_SQRT                                               192                            /* 'sqrt' */
+#define DUK_STRIDX_SIN                                                193                            /* 'sin' */
+#define DUK_STRIDX_ROUND                                              194                            /* 'round' */
+#define DUK_STRIDX_RANDOM                                             195                            /* 'random' */
+#define DUK_STRIDX_POW                                                196                            /* 'pow' */
+#define DUK_STRIDX_MIN                                                197                            /* 'min' */
+#define DUK_STRIDX_MAX                                                198                            /* 'max' */
+#define DUK_STRIDX_LOG                                                199                            /* 'log' */
+#define DUK_STRIDX_FLOOR                                              200                            /* 'floor' */
+#define DUK_STRIDX_EXP                                                201                            /* 'exp' */
+#define DUK_STRIDX_COS                                                202                            /* 'cos' */
+#define DUK_STRIDX_CEIL                                               203                            /* 'ceil' */
+#define DUK_STRIDX_ATAN2                                              204                            /* 'atan2' */
+#define DUK_STRIDX_ATAN                                               205                            /* 'atan' */
+#define DUK_STRIDX_ASIN                                               206                            /* 'asin' */
+#define DUK_STRIDX_ACOS                                               207                            /* 'acos' */
+#define DUK_STRIDX_ABS                                                208                            /* 'abs' */
+#define DUK_STRIDX_SQRT2                                              209                            /* 'SQRT2' */
+#define DUK_STRIDX_SQRT1_2                                            210                            /* 'SQRT1_2' */
+#define DUK_STRIDX_PI                                                 211                            /* 'PI' */
+#define DUK_STRIDX_LOG10E                                             212                            /* 'LOG10E' */
+#define DUK_STRIDX_LOG2E                                              213                            /* 'LOG2E' */
+#define DUK_STRIDX_LN2                                                214                            /* 'LN2' */
+#define DUK_STRIDX_LN10                                               215                            /* 'LN10' */
+#define DUK_STRIDX_E                                                  216                            /* 'E' */
+#define DUK_STRIDX_MESSAGE                                            217                            /* 'message' */
+#define DUK_STRIDX_NAME                                               218                            /* 'name' */
+#define DUK_STRIDX_INPUT                                              219                            /* 'input' */
+#define DUK_STRIDX_INDEX                                              220                            /* 'index' */
+#define DUK_STRIDX_ESCAPED_EMPTY_REGEXP                               221                            /* '(?:)' */
+#define DUK_STRIDX_LAST_INDEX                                         222                            /* 'lastIndex' */
+#define DUK_STRIDX_MULTILINE                                          223                            /* 'multiline' */
+#define DUK_STRIDX_IGNORE_CASE                                        224                            /* 'ignoreCase' */
+#define DUK_STRIDX_SOURCE                                             225                            /* 'source' */
+#define DUK_STRIDX_TEST                                               226                            /* 'test' */
+#define DUK_STRIDX_EXEC                                               227                            /* 'exec' */
+#define DUK_STRIDX_TO_GMT_STRING                                      228                            /* 'toGMTString' */
+#define DUK_STRIDX_SET_YEAR                                           229                            /* 'setYear' */
+#define DUK_STRIDX_GET_YEAR                                           230                            /* 'getYear' */
+#define DUK_STRIDX_TO_JSON                                            231                            /* 'toJSON' */
+#define DUK_STRIDX_TO_ISO_STRING                                      232                            /* 'toISOString' */
+#define DUK_STRIDX_TO_UTC_STRING                                      233                            /* 'toUTCString' */
+#define DUK_STRIDX_SET_UTC_FULL_YEAR                                  234                            /* 'setUTCFullYear' */
+#define DUK_STRIDX_SET_FULL_YEAR                                      235                            /* 'setFullYear' */
+#define DUK_STRIDX_SET_UTC_MONTH                                      236                            /* 'setUTCMonth' */
+#define DUK_STRIDX_SET_MONTH                                          237                            /* 'setMonth' */
+#define DUK_STRIDX_SET_UTC_DATE                                       238                            /* 'setUTCDate' */
+#define DUK_STRIDX_SET_DATE                                           239                            /* 'setDate' */
+#define DUK_STRIDX_SET_UTC_HOURS                                      240                            /* 'setUTCHours' */
+#define DUK_STRIDX_SET_HOURS                                          241                            /* 'setHours' */
+#define DUK_STRIDX_SET_UTC_MINUTES                                    242                            /* 'setUTCMinutes' */
+#define DUK_STRIDX_SET_MINUTES                                        243                            /* 'setMinutes' */
+#define DUK_STRIDX_SET_UTC_SECONDS                                    244                            /* 'setUTCSeconds' */
+#define DUK_STRIDX_SET_SECONDS                                        245                            /* 'setSeconds' */
+#define DUK_STRIDX_SET_UTC_MILLISECONDS                               246                            /* 'setUTCMilliseconds' */
+#define DUK_STRIDX_SET_MILLISECONDS                                   247                            /* 'setMilliseconds' */
+#define DUK_STRIDX_SET_TIME                                           248                            /* 'setTime' */
+#define DUK_STRIDX_GET_TIMEZONE_OFFSET                                249                            /* 'getTimezoneOffset' */
+#define DUK_STRIDX_GET_UTC_MILLISECONDS                               250                            /* 'getUTCMilliseconds' */
+#define DUK_STRIDX_GET_MILLISECONDS                                   251                            /* 'getMilliseconds' */
+#define DUK_STRIDX_GET_UTC_SECONDS                                    252                            /* 'getUTCSeconds' */
+#define DUK_STRIDX_GET_SECONDS                                        253                            /* 'getSeconds' */
+#define DUK_STRIDX_GET_UTC_MINUTES                                    254                            /* 'getUTCMinutes' */
+#define DUK_STRIDX_GET_MINUTES                                        255                            /* 'getMinutes' */
+#define DUK_STRIDX_GET_UTC_HOURS                                      256                            /* 'getUTCHours' */
+#define DUK_STRIDX_GET_HOURS                                          257                            /* 'getHours' */
+#define DUK_STRIDX_GET_UTC_DAY                                        258                            /* 'getUTCDay' */
+#define DUK_STRIDX_GET_DAY                                            259                            /* 'getDay' */
+#define DUK_STRIDX_GET_UTC_DATE                                       260                            /* 'getUTCDate' */
+#define DUK_STRIDX_GET_DATE                                           261                            /* 'getDate' */
+#define DUK_STRIDX_GET_UTC_MONTH                                      262                            /* 'getUTCMonth' */
+#define DUK_STRIDX_GET_MONTH                                          263                            /* 'getMonth' */
+#define DUK_STRIDX_GET_UTC_FULL_YEAR                                  264                            /* 'getUTCFullYear' */
+#define DUK_STRIDX_GET_FULL_YEAR                                      265                            /* 'getFullYear' */
+#define DUK_STRIDX_GET_TIME                                           266                            /* 'getTime' */
+#define DUK_STRIDX_TO_LOCALE_TIME_STRING                              267                            /* 'toLocaleTimeString' */
+#define DUK_STRIDX_TO_LOCALE_DATE_STRING                              268                            /* 'toLocaleDateString' */
+#define DUK_STRIDX_TO_TIME_STRING                                     269                            /* 'toTimeString' */
+#define DUK_STRIDX_TO_DATE_STRING                                     270                            /* 'toDateString' */
+#define DUK_STRIDX_NOW                                                271                            /* 'now' */
+#define DUK_STRIDX_UTC                                                272                            /* 'UTC' */
+#define DUK_STRIDX_PARSE                                              273                            /* 'parse' */
+#define DUK_STRIDX_TO_PRECISION                                       274                            /* 'toPrecision' */
+#define DUK_STRIDX_TO_EXPONENTIAL                                     275                            /* 'toExponential' */
+#define DUK_STRIDX_TO_FIXED                                           276                            /* 'toFixed' */
+#define DUK_STRIDX_POSITIVE_INFINITY                                  277                            /* 'POSITIVE_INFINITY' */
+#define DUK_STRIDX_NEGATIVE_INFINITY                                  278                            /* 'NEGATIVE_INFINITY' */
+#define DUK_STRIDX_NAN                                                279                            /* 'NaN' */
+#define DUK_STRIDX_MIN_VALUE                                          280                            /* 'MIN_VALUE' */
+#define DUK_STRIDX_MAX_VALUE                                          281                            /* 'MAX_VALUE' */
+#define DUK_STRIDX_SUBSTR                                             282                            /* 'substr' */
+#define DUK_STRIDX_TRIM                                               283                            /* 'trim' */
+#define DUK_STRIDX_TO_LOCALE_UPPER_CASE                               284                            /* 'toLocaleUpperCase' */
+#define DUK_STRIDX_TO_UPPER_CASE                                      285                            /* 'toUpperCase' */
+#define DUK_STRIDX_TO_LOCALE_LOWER_CASE                               286                            /* 'toLocaleLowerCase' */
+#define DUK_STRIDX_TO_LOWER_CASE                                      287                            /* 'toLowerCase' */
+#define DUK_STRIDX_SUBSTRING                                          288                            /* 'substring' */
+#define DUK_STRIDX_SPLIT                                              289                            /* 'split' */
+#define DUK_STRIDX_SEARCH                                             290                            /* 'search' */
+#define DUK_STRIDX_REPLACE                                            291                            /* 'replace' */
+#define DUK_STRIDX_MATCH                                              292                            /* 'match' */
+#define DUK_STRIDX_LOCALE_COMPARE                                     293                            /* 'localeCompare' */
+#define DUK_STRIDX_CHAR_CODE_AT                                       294                            /* 'charCodeAt' */
+#define DUK_STRIDX_CHAR_AT                                            295                            /* 'charAt' */
+#define DUK_STRIDX_FROM_CHAR_CODE                                     296                            /* 'fromCharCode' */
+#define DUK_STRIDX_REDUCE_RIGHT                                       297                            /* 'reduceRight' */
+#define DUK_STRIDX_REDUCE                                             298                            /* 'reduce' */
+#define DUK_STRIDX_FILTER                                             299                            /* 'filter' */
+#define DUK_STRIDX_MAP                                                300                            /* 'map' */
+#define DUK_STRIDX_FOR_EACH                                           301                            /* 'forEach' */
+#define DUK_STRIDX_SOME                                               302                            /* 'some' */
+#define DUK_STRIDX_EVERY                                              303                            /* 'every' */
+#define DUK_STRIDX_LAST_INDEX_OF                                      304                            /* 'lastIndexOf' */
+#define DUK_STRIDX_INDEX_OF                                           305                            /* 'indexOf' */
+#define DUK_STRIDX_UNSHIFT                                            306                            /* 'unshift' */
+#define DUK_STRIDX_SPLICE                                             307                            /* 'splice' */
+#define DUK_STRIDX_SORT                                               308                            /* 'sort' */
+#define DUK_STRIDX_SLICE                                              309                            /* 'slice' */
+#define DUK_STRIDX_SHIFT                                              310                            /* 'shift' */
+#define DUK_STRIDX_REVERSE                                            311                            /* 'reverse' */
+#define DUK_STRIDX_PUSH                                               312                            /* 'push' */
+#define DUK_STRIDX_POP                                                313                            /* 'pop' */
+#define DUK_STRIDX_JOIN                                               314                            /* 'join' */
+#define DUK_STRIDX_CONCAT                                             315                            /* 'concat' */
+#define DUK_STRIDX_IS_ARRAY                                           316                            /* 'isArray' */
+#define DUK_STRIDX_LC_ARGUMENTS                                       317                            /* 'arguments' */
+#define DUK_STRIDX_CALLER                                             318                            /* 'caller' */
+#define DUK_STRIDX_BIND                                               319                            /* 'bind' */
+#define DUK_STRIDX_CALL                                               320                            /* 'call' */
+#define DUK_STRIDX_APPLY                                              321                            /* 'apply' */
+#define DUK_STRIDX_PROPERTY_IS_ENUMERABLE                             322                            /* 'propertyIsEnumerable' */
+#define DUK_STRIDX_IS_PROTOTYPE_OF                                    323                            /* 'isPrototypeOf' */
+#define DUK_STRIDX_HAS_OWN_PROPERTY                                   324                            /* 'hasOwnProperty' */
+#define DUK_STRIDX_VALUE_OF                                           325                            /* 'valueOf' */
+#define DUK_STRIDX_TO_LOCALE_STRING                                   326                            /* 'toLocaleString' */
+#define DUK_STRIDX_TO_STRING                                          327                            /* 'toString' */
+#define DUK_STRIDX_CONSTRUCTOR                                        328                            /* 'constructor' */
+#define DUK_STRIDX_SET                                                329                            /* 'set' */
+#define DUK_STRIDX_GET                                                330                            /* 'get' */
+#define DUK_STRIDX_ENUMERABLE                                         331                            /* 'enumerable' */
+#define DUK_STRIDX_CONFIGURABLE                                       332                            /* 'configurable' */
+#define DUK_STRIDX_WRITABLE                                           333                            /* 'writable' */
+#define DUK_STRIDX_VALUE                                              334                            /* 'value' */
+#define DUK_STRIDX_KEYS                                               335                            /* 'keys' */
+#define DUK_STRIDX_IS_EXTENSIBLE                                      336                            /* 'isExtensible' */
+#define DUK_STRIDX_IS_FROZEN                                          337                            /* 'isFrozen' */
+#define DUK_STRIDX_IS_SEALED                                          338                            /* 'isSealed' */
+#define DUK_STRIDX_PREVENT_EXTENSIONS                                 339                            /* 'preventExtensions' */
+#define DUK_STRIDX_FREEZE                                             340                            /* 'freeze' */
+#define DUK_STRIDX_SEAL                                               341                            /* 'seal' */
+#define DUK_STRIDX_DEFINE_PROPERTIES                                  342                            /* 'defineProperties' */
+#define DUK_STRIDX_DEFINE_PROPERTY                                    343                            /* 'defineProperty' */
+#define DUK_STRIDX_CREATE                                             344                            /* 'create' */
+#define DUK_STRIDX_GET_OWN_PROPERTY_NAMES                             345                            /* 'getOwnPropertyNames' */
+#define DUK_STRIDX_GET_OWN_PROPERTY_DESCRIPTOR                        346                            /* 'getOwnPropertyDescriptor' */
+#define DUK_STRIDX_GET_PROTOTYPE_OF                                   347                            /* 'getPrototypeOf' */
+#define DUK_STRIDX_PROTOTYPE                                          348                            /* 'prototype' */
+#define DUK_STRIDX_LENGTH                                             349                            /* 'length' */
+#define DUK_STRIDX_ALERT                                              350                            /* 'alert' */
+#define DUK_STRIDX_PRINT                                              351                            /* 'print' */
+#define DUK_STRIDX_UNESCAPE                                           352                            /* 'unescape' */
+#define DUK_STRIDX_ESCAPE                                             353                            /* 'escape' */
+#define DUK_STRIDX_ENCODE_URI_COMPONENT                               354                            /* 'encodeURIComponent' */
+#define DUK_STRIDX_ENCODE_URI                                         355                            /* 'encodeURI' */
+#define DUK_STRIDX_DECODE_URI_COMPONENT                               356                            /* 'decodeURIComponent' */
+#define DUK_STRIDX_DECODE_URI                                         357                            /* 'decodeURI' */
+#define DUK_STRIDX_IS_FINITE                                          358                            /* 'isFinite' */
+#define DUK_STRIDX_IS_NAN                                             359                            /* 'isNaN' */
+#define DUK_STRIDX_PARSE_FLOAT                                        360                            /* 'parseFloat' */
+#define DUK_STRIDX_PARSE_INT                                          361                            /* 'parseInt' */
+#define DUK_STRIDX_EVAL                                               362                            /* 'eval' */
+#define DUK_STRIDX_URI_ERROR                                          363                            /* 'URIError' */
+#define DUK_STRIDX_TYPE_ERROR                                         364                            /* 'TypeError' */
+#define DUK_STRIDX_SYNTAX_ERROR                                       365                            /* 'SyntaxError' */
+#define DUK_STRIDX_REFERENCE_ERROR                                    366                            /* 'ReferenceError' */
+#define DUK_STRIDX_RANGE_ERROR                                        367                            /* 'RangeError' */
+#define DUK_STRIDX_EVAL_ERROR                                         368                            /* 'EvalError' */
+#define DUK_STRIDX_BREAK                                              369                            /* 'break' */
+#define DUK_STRIDX_CASE                                               370                            /* 'case' */
+#define DUK_STRIDX_CATCH                                              371                            /* 'catch' */
+#define DUK_STRIDX_CONTINUE                                           372                            /* 'continue' */
+#define DUK_STRIDX_DEBUGGER                                           373                            /* 'debugger' */
+#define DUK_STRIDX_DEFAULT                                            374                            /* 'default' */
+#define DUK_STRIDX_DELETE                                             375                            /* 'delete' */
+#define DUK_STRIDX_DO                                                 376                            /* 'do' */
+#define DUK_STRIDX_ELSE                                               377                            /* 'else' */
+#define DUK_STRIDX_FINALLY                                            378                            /* 'finally' */
+#define DUK_STRIDX_FOR                                                379                            /* 'for' */
+#define DUK_STRIDX_LC_FUNCTION                                        380                            /* 'function' */
+#define DUK_STRIDX_IF                                                 381                            /* 'if' */
+#define DUK_STRIDX_IN                                                 382                            /* 'in' */
+#define DUK_STRIDX_INSTANCEOF                                         383                            /* 'instanceof' */
+#define DUK_STRIDX_NEW                                                384                            /* 'new' */
+#define DUK_STRIDX_RETURN                                             385                            /* 'return' */
+#define DUK_STRIDX_SWITCH                                             386                            /* 'switch' */
+#define DUK_STRIDX_THIS                                               387                            /* 'this' */
+#define DUK_STRIDX_THROW                                              388                            /* 'throw' */
+#define DUK_STRIDX_TRY                                                389                            /* 'try' */
+#define DUK_STRIDX_TYPEOF                                             390                            /* 'typeof' */
+#define DUK_STRIDX_VAR                                                391                            /* 'var' */
+#define DUK_STRIDX_CONST                                              392                            /* 'const' */
+#define DUK_STRIDX_VOID                                               393                            /* 'void' */
+#define DUK_STRIDX_WHILE                                              394                            /* 'while' */
+#define DUK_STRIDX_WITH                                               395                            /* 'with' */
+#define DUK_STRIDX_CLASS                                              396                            /* 'class' */
+#define DUK_STRIDX_ENUM                                               397                            /* 'enum' */
+#define DUK_STRIDX_EXPORT                                             398                            /* 'export' */
+#define DUK_STRIDX_EXTENDS                                            399                            /* 'extends' */
+#define DUK_STRIDX_IMPORT                                             400                            /* 'import' */
+#define DUK_STRIDX_SUPER                                              401                            /* 'super' */
+#define DUK_STRIDX_LC_NULL                                            402                            /* 'null' */
+#define DUK_STRIDX_TRUE                                               403                            /* 'true' */
+#define DUK_STRIDX_FALSE                                              404                            /* 'false' */
+#define DUK_STRIDX_IMPLEMENTS                                         405                            /* 'implements' */
+#define DUK_STRIDX_INTERFACE                                          406                            /* 'interface' */
+#define DUK_STRIDX_LET                                                407                            /* 'let' */
+#define DUK_STRIDX_PACKAGE                                            408                            /* 'package' */
+#define DUK_STRIDX_PRIVATE                                            409                            /* 'private' */
+#define DUK_STRIDX_PROTECTED                                          410                            /* 'protected' */
+#define DUK_STRIDX_PUBLIC                                             411                            /* 'public' */
+#define DUK_STRIDX_STATIC                                             412                            /* 'static' */
+#define DUK_STRIDX_YIELD                                              413                            /* 'yield' */
 
 #define DUK_HEAP_STRING_UC_LOGGER(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_LOGGER)
 #define DUK_HTHREAD_STRING_UC_LOGGER(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_LOGGER)
@@ -1714,12 +2138,34 @@ extern const duk_uint8_t duk_strings_data[];
 #define DUK_HTHREAD_STRING_UC_THREAD(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_THREAD)
 #define DUK_HEAP_STRING_UC_POINTER(heap)                              DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_POINTER)
 #define DUK_HTHREAD_STRING_UC_POINTER(thr)                            DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_POINTER)
-#define DUK_HEAP_STRING_UC_BUFFER(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_BUFFER)
-#define DUK_HTHREAD_STRING_UC_BUFFER(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_BUFFER)
 #define DUK_HEAP_STRING_DEC_ENV(heap)                                 DUK_HEAP_GET_STRING((heap),DUK_STRIDX_DEC_ENV)
 #define DUK_HTHREAD_STRING_DEC_ENV(thr)                               DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_DEC_ENV)
 #define DUK_HEAP_STRING_OBJ_ENV(heap)                                 DUK_HEAP_GET_STRING((heap),DUK_STRIDX_OBJ_ENV)
 #define DUK_HTHREAD_STRING_OBJ_ENV(thr)                               DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_OBJ_ENV)
+#define DUK_HEAP_STRING_FLOAT64_ARRAY(heap)                           DUK_HEAP_GET_STRING((heap),DUK_STRIDX_FLOAT64_ARRAY)
+#define DUK_HTHREAD_STRING_FLOAT64_ARRAY(thr)                         DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_FLOAT64_ARRAY)
+#define DUK_HEAP_STRING_FLOAT32_ARRAY(heap)                           DUK_HEAP_GET_STRING((heap),DUK_STRIDX_FLOAT32_ARRAY)
+#define DUK_HTHREAD_STRING_FLOAT32_ARRAY(thr)                         DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_FLOAT32_ARRAY)
+#define DUK_HEAP_STRING_UINT32_ARRAY(heap)                            DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UINT32_ARRAY)
+#define DUK_HTHREAD_STRING_UINT32_ARRAY(thr)                          DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UINT32_ARRAY)
+#define DUK_HEAP_STRING_INT32_ARRAY(heap)                             DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT32_ARRAY)
+#define DUK_HTHREAD_STRING_INT32_ARRAY(thr)                           DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT32_ARRAY)
+#define DUK_HEAP_STRING_UINT16_ARRAY(heap)                            DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UINT16_ARRAY)
+#define DUK_HTHREAD_STRING_UINT16_ARRAY(thr)                          DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UINT16_ARRAY)
+#define DUK_HEAP_STRING_INT16_ARRAY(heap)                             DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT16_ARRAY)
+#define DUK_HTHREAD_STRING_INT16_ARRAY(thr)                           DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT16_ARRAY)
+#define DUK_HEAP_STRING_UINT8_CLAMPED_ARRAY(heap)                     DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UINT8_CLAMPED_ARRAY)
+#define DUK_HTHREAD_STRING_UINT8_CLAMPED_ARRAY(thr)                   DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UINT8_CLAMPED_ARRAY)
+#define DUK_HEAP_STRING_UINT8_ARRAY(heap)                             DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UINT8_ARRAY)
+#define DUK_HTHREAD_STRING_UINT8_ARRAY(thr)                           DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UINT8_ARRAY)
+#define DUK_HEAP_STRING_INT8_ARRAY(heap)                              DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT8_ARRAY)
+#define DUK_HTHREAD_STRING_INT8_ARRAY(thr)                            DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT8_ARRAY)
+#define DUK_HEAP_STRING_DATA_VIEW(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_DATA_VIEW)
+#define DUK_HTHREAD_STRING_DATA_VIEW(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_DATA_VIEW)
+#define DUK_HEAP_STRING_ARRAY_BUFFER(heap)                            DUK_HEAP_GET_STRING((heap),DUK_STRIDX_ARRAY_BUFFER)
+#define DUK_HTHREAD_STRING_ARRAY_BUFFER(thr)                          DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_ARRAY_BUFFER)
+#define DUK_HEAP_STRING_UC_BUFFER(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_BUFFER)
+#define DUK_HTHREAD_STRING_UC_BUFFER(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_BUFFER)
 #define DUK_HEAP_STRING_EMPTY_STRING(heap)                            DUK_HEAP_GET_STRING((heap),DUK_STRIDX_EMPTY_STRING)
 #define DUK_HTHREAD_STRING_EMPTY_STRING(thr)                          DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_EMPTY_STRING)
 #define DUK_HEAP_STRING_GLOBAL(heap)                                  DUK_HEAP_GET_STRING((heap),DUK_STRIDX_GLOBAL)
@@ -1864,10 +2310,8 @@ extern const duk_uint8_t duk_strings_data[];
 #define DUK_HTHREAD_STRING_INT_VALUE(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_VALUE)
 #define DUK_HEAP_STRING_LC_POINTER(heap)                              DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_POINTER)
 #define DUK_HTHREAD_STRING_LC_POINTER(thr)                            DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_POINTER)
-#define DUK_HEAP_STRING_LC_BUFFER(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_BUFFER)
-#define DUK_HTHREAD_STRING_LC_BUFFER(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_BUFFER)
-#define DUK_HEAP_STRING_TRACEDATA(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_TRACEDATA)
-#define DUK_HTHREAD_STRING_TRACEDATA(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_TRACEDATA)
+#define DUK_HEAP_STRING_INT_TRACEDATA(heap)                           DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_TRACEDATA)
+#define DUK_HTHREAD_STRING_INT_TRACEDATA(thr)                         DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_TRACEDATA)
 #define DUK_HEAP_STRING_LINE_NUMBER(heap)                             DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LINE_NUMBER)
 #define DUK_HTHREAD_STRING_LINE_NUMBER(thr)                           DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LINE_NUMBER)
 #define DUK_HEAP_STRING_FILE_NAME(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_FILE_NAME)
@@ -1880,6 +2324,142 @@ extern const duk_uint8_t duk_strings_data[];
 #define DUK_HTHREAD_STRING_THROW_TYPE_ERROR(thr)                      DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_THROW_TYPE_ERROR)
 #define DUK_HEAP_STRING_DUKTAPE(heap)                                 DUK_HEAP_GET_STRING((heap),DUK_STRIDX_DUKTAPE)
 #define DUK_HTHREAD_STRING_DUKTAPE(thr)                               DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_DUKTAPE)
+#define DUK_HEAP_STRING_SET_FLOAT64(heap)                             DUK_HEAP_GET_STRING((heap),DUK_STRIDX_SET_FLOAT64)
+#define DUK_HTHREAD_STRING_SET_FLOAT64(thr)                           DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_SET_FLOAT64)
+#define DUK_HEAP_STRING_SET_FLOAT32(heap)                             DUK_HEAP_GET_STRING((heap),DUK_STRIDX_SET_FLOAT32)
+#define DUK_HTHREAD_STRING_SET_FLOAT32(thr)                           DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_SET_FLOAT32)
+#define DUK_HEAP_STRING_SET_UINT32(heap)                              DUK_HEAP_GET_STRING((heap),DUK_STRIDX_SET_UINT32)
+#define DUK_HTHREAD_STRING_SET_UINT32(thr)                            DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_SET_UINT32)
+#define DUK_HEAP_STRING_SET_INT32(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_SET_INT32)
+#define DUK_HTHREAD_STRING_SET_INT32(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_SET_INT32)
+#define DUK_HEAP_STRING_SET_UINT16(heap)                              DUK_HEAP_GET_STRING((heap),DUK_STRIDX_SET_UINT16)
+#define DUK_HTHREAD_STRING_SET_UINT16(thr)                            DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_SET_UINT16)
+#define DUK_HEAP_STRING_SET_INT16(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_SET_INT16)
+#define DUK_HTHREAD_STRING_SET_INT16(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_SET_INT16)
+#define DUK_HEAP_STRING_SET_UINT8(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_SET_UINT8)
+#define DUK_HTHREAD_STRING_SET_UINT8(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_SET_UINT8)
+#define DUK_HEAP_STRING_SET_INT8(heap)                                DUK_HEAP_GET_STRING((heap),DUK_STRIDX_SET_INT8)
+#define DUK_HTHREAD_STRING_SET_INT8(thr)                              DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_SET_INT8)
+#define DUK_HEAP_STRING_GET_FLOAT64(heap)                             DUK_HEAP_GET_STRING((heap),DUK_STRIDX_GET_FLOAT64)
+#define DUK_HTHREAD_STRING_GET_FLOAT64(thr)                           DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_GET_FLOAT64)
+#define DUK_HEAP_STRING_GET_FLOAT32(heap)                             DUK_HEAP_GET_STRING((heap),DUK_STRIDX_GET_FLOAT32)
+#define DUK_HTHREAD_STRING_GET_FLOAT32(thr)                           DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_GET_FLOAT32)
+#define DUK_HEAP_STRING_GET_UINT32(heap)                              DUK_HEAP_GET_STRING((heap),DUK_STRIDX_GET_UINT32)
+#define DUK_HTHREAD_STRING_GET_UINT32(thr)                            DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_GET_UINT32)
+#define DUK_HEAP_STRING_GET_INT32(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_GET_INT32)
+#define DUK_HTHREAD_STRING_GET_INT32(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_GET_INT32)
+#define DUK_HEAP_STRING_GET_UINT16(heap)                              DUK_HEAP_GET_STRING((heap),DUK_STRIDX_GET_UINT16)
+#define DUK_HTHREAD_STRING_GET_UINT16(thr)                            DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_GET_UINT16)
+#define DUK_HEAP_STRING_GET_INT16(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_GET_INT16)
+#define DUK_HTHREAD_STRING_GET_INT16(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_GET_INT16)
+#define DUK_HEAP_STRING_GET_UINT8(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_GET_UINT8)
+#define DUK_HTHREAD_STRING_GET_UINT8(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_GET_UINT8)
+#define DUK_HEAP_STRING_GET_INT8(heap)                                DUK_HEAP_GET_STRING((heap),DUK_STRIDX_GET_INT8)
+#define DUK_HTHREAD_STRING_GET_INT8(thr)                              DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_GET_INT8)
+#define DUK_HEAP_STRING_SUBARRAY(heap)                                DUK_HEAP_GET_STRING((heap),DUK_STRIDX_SUBARRAY)
+#define DUK_HTHREAD_STRING_SUBARRAY(thr)                              DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_SUBARRAY)
+#define DUK_HEAP_STRING_BYTES_PER_ELEMENT(heap)                       DUK_HEAP_GET_STRING((heap),DUK_STRIDX_BYTES_PER_ELEMENT)
+#define DUK_HTHREAD_STRING_BYTES_PER_ELEMENT(thr)                     DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_BYTES_PER_ELEMENT)
+#define DUK_HEAP_STRING_BYTE_OFFSET(heap)                             DUK_HEAP_GET_STRING((heap),DUK_STRIDX_BYTE_OFFSET)
+#define DUK_HTHREAD_STRING_BYTE_OFFSET(thr)                           DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_BYTE_OFFSET)
+#define DUK_HEAP_STRING_LC_BUFFER(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_BUFFER)
+#define DUK_HTHREAD_STRING_LC_BUFFER(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_BUFFER)
+#define DUK_HEAP_STRING_IS_VIEW(heap)                                 DUK_HEAP_GET_STRING((heap),DUK_STRIDX_IS_VIEW)
+#define DUK_HTHREAD_STRING_IS_VIEW(thr)                               DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_IS_VIEW)
+#define DUK_HEAP_STRING_DATA(heap)                                    DUK_HEAP_GET_STRING((heap),DUK_STRIDX_DATA)
+#define DUK_HTHREAD_STRING_DATA(thr)                                  DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_DATA)
+#define DUK_HEAP_STRING_TYPE(heap)                                    DUK_HEAP_GET_STRING((heap),DUK_STRIDX_TYPE)
+#define DUK_HTHREAD_STRING_TYPE(thr)                                  DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_TYPE)
+#define DUK_HEAP_STRING_WRITE_INT_BE(heap)                            DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WRITE_INT_BE)
+#define DUK_HTHREAD_STRING_WRITE_INT_BE(thr)                          DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WRITE_INT_BE)
+#define DUK_HEAP_STRING_WRITE_INT_LE(heap)                            DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WRITE_INT_LE)
+#define DUK_HTHREAD_STRING_WRITE_INT_LE(thr)                          DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WRITE_INT_LE)
+#define DUK_HEAP_STRING_WRITE_UINT_BE(heap)                           DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WRITE_UINT_BE)
+#define DUK_HTHREAD_STRING_WRITE_UINT_BE(thr)                         DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WRITE_UINT_BE)
+#define DUK_HEAP_STRING_WRITE_UINT_LE(heap)                           DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WRITE_UINT_LE)
+#define DUK_HTHREAD_STRING_WRITE_UINT_LE(thr)                         DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WRITE_UINT_LE)
+#define DUK_HEAP_STRING_WRITE_DOUBLE_BE(heap)                         DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WRITE_DOUBLE_BE)
+#define DUK_HTHREAD_STRING_WRITE_DOUBLE_BE(thr)                       DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WRITE_DOUBLE_BE)
+#define DUK_HEAP_STRING_WRITE_DOUBLE_LE(heap)                         DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WRITE_DOUBLE_LE)
+#define DUK_HTHREAD_STRING_WRITE_DOUBLE_LE(thr)                       DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WRITE_DOUBLE_LE)
+#define DUK_HEAP_STRING_WRITE_FLOAT_BE(heap)                          DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WRITE_FLOAT_BE)
+#define DUK_HTHREAD_STRING_WRITE_FLOAT_BE(thr)                        DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WRITE_FLOAT_BE)
+#define DUK_HEAP_STRING_WRITE_FLOAT_LE(heap)                          DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WRITE_FLOAT_LE)
+#define DUK_HTHREAD_STRING_WRITE_FLOAT_LE(thr)                        DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WRITE_FLOAT_LE)
+#define DUK_HEAP_STRING_WRITE_INT32_BE(heap)                          DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WRITE_INT32_BE)
+#define DUK_HTHREAD_STRING_WRITE_INT32_BE(thr)                        DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WRITE_INT32_BE)
+#define DUK_HEAP_STRING_WRITE_INT32_LE(heap)                          DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WRITE_INT32_LE)
+#define DUK_HTHREAD_STRING_WRITE_INT32_LE(thr)                        DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WRITE_INT32_LE)
+#define DUK_HEAP_STRING_WRITE_UINT32_BE(heap)                         DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WRITE_UINT32_BE)
+#define DUK_HTHREAD_STRING_WRITE_UINT32_BE(thr)                       DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WRITE_UINT32_BE)
+#define DUK_HEAP_STRING_WRITE_UINT32_LE(heap)                         DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WRITE_UINT32_LE)
+#define DUK_HTHREAD_STRING_WRITE_UINT32_LE(thr)                       DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WRITE_UINT32_LE)
+#define DUK_HEAP_STRING_WRITE_INT16_BE(heap)                          DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WRITE_INT16_BE)
+#define DUK_HTHREAD_STRING_WRITE_INT16_BE(thr)                        DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WRITE_INT16_BE)
+#define DUK_HEAP_STRING_WRITE_INT16_LE(heap)                          DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WRITE_INT16_LE)
+#define DUK_HTHREAD_STRING_WRITE_INT16_LE(thr)                        DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WRITE_INT16_LE)
+#define DUK_HEAP_STRING_WRITE_UINT16_BE(heap)                         DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WRITE_UINT16_BE)
+#define DUK_HTHREAD_STRING_WRITE_UINT16_BE(thr)                       DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WRITE_UINT16_BE)
+#define DUK_HEAP_STRING_WRITE_UINT16_LE(heap)                         DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WRITE_UINT16_LE)
+#define DUK_HTHREAD_STRING_WRITE_UINT16_LE(thr)                       DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WRITE_UINT16_LE)
+#define DUK_HEAP_STRING_WRITE_INT8(heap)                              DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WRITE_INT8)
+#define DUK_HTHREAD_STRING_WRITE_INT8(thr)                            DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WRITE_INT8)
+#define DUK_HEAP_STRING_WRITE_UINT8(heap)                             DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WRITE_UINT8)
+#define DUK_HTHREAD_STRING_WRITE_UINT8(thr)                           DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WRITE_UINT8)
+#define DUK_HEAP_STRING_READ_INT_BE(heap)                             DUK_HEAP_GET_STRING((heap),DUK_STRIDX_READ_INT_BE)
+#define DUK_HTHREAD_STRING_READ_INT_BE(thr)                           DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_READ_INT_BE)
+#define DUK_HEAP_STRING_READ_INT_LE(heap)                             DUK_HEAP_GET_STRING((heap),DUK_STRIDX_READ_INT_LE)
+#define DUK_HTHREAD_STRING_READ_INT_LE(thr)                           DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_READ_INT_LE)
+#define DUK_HEAP_STRING_READ_UINT_BE(heap)                            DUK_HEAP_GET_STRING((heap),DUK_STRIDX_READ_UINT_BE)
+#define DUK_HTHREAD_STRING_READ_UINT_BE(thr)                          DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_READ_UINT_BE)
+#define DUK_HEAP_STRING_READ_UINT_LE(heap)                            DUK_HEAP_GET_STRING((heap),DUK_STRIDX_READ_UINT_LE)
+#define DUK_HTHREAD_STRING_READ_UINT_LE(thr)                          DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_READ_UINT_LE)
+#define DUK_HEAP_STRING_READ_DOUBLE_BE(heap)                          DUK_HEAP_GET_STRING((heap),DUK_STRIDX_READ_DOUBLE_BE)
+#define DUK_HTHREAD_STRING_READ_DOUBLE_BE(thr)                        DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_READ_DOUBLE_BE)
+#define DUK_HEAP_STRING_READ_DOUBLE_LE(heap)                          DUK_HEAP_GET_STRING((heap),DUK_STRIDX_READ_DOUBLE_LE)
+#define DUK_HTHREAD_STRING_READ_DOUBLE_LE(thr)                        DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_READ_DOUBLE_LE)
+#define DUK_HEAP_STRING_READ_FLOAT_BE(heap)                           DUK_HEAP_GET_STRING((heap),DUK_STRIDX_READ_FLOAT_BE)
+#define DUK_HTHREAD_STRING_READ_FLOAT_BE(thr)                         DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_READ_FLOAT_BE)
+#define DUK_HEAP_STRING_READ_FLOAT_LE(heap)                           DUK_HEAP_GET_STRING((heap),DUK_STRIDX_READ_FLOAT_LE)
+#define DUK_HTHREAD_STRING_READ_FLOAT_LE(thr)                         DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_READ_FLOAT_LE)
+#define DUK_HEAP_STRING_READ_INT32_BE(heap)                           DUK_HEAP_GET_STRING((heap),DUK_STRIDX_READ_INT32_BE)
+#define DUK_HTHREAD_STRING_READ_INT32_BE(thr)                         DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_READ_INT32_BE)
+#define DUK_HEAP_STRING_READ_INT32_LE(heap)                           DUK_HEAP_GET_STRING((heap),DUK_STRIDX_READ_INT32_LE)
+#define DUK_HTHREAD_STRING_READ_INT32_LE(thr)                         DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_READ_INT32_LE)
+#define DUK_HEAP_STRING_READ_UINT32_BE(heap)                          DUK_HEAP_GET_STRING((heap),DUK_STRIDX_READ_UINT32_BE)
+#define DUK_HTHREAD_STRING_READ_UINT32_BE(thr)                        DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_READ_UINT32_BE)
+#define DUK_HEAP_STRING_READ_UINT32_LE(heap)                          DUK_HEAP_GET_STRING((heap),DUK_STRIDX_READ_UINT32_LE)
+#define DUK_HTHREAD_STRING_READ_UINT32_LE(thr)                        DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_READ_UINT32_LE)
+#define DUK_HEAP_STRING_READ_INT16_BE(heap)                           DUK_HEAP_GET_STRING((heap),DUK_STRIDX_READ_INT16_BE)
+#define DUK_HTHREAD_STRING_READ_INT16_BE(thr)                         DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_READ_INT16_BE)
+#define DUK_HEAP_STRING_READ_INT16_LE(heap)                           DUK_HEAP_GET_STRING((heap),DUK_STRIDX_READ_INT16_LE)
+#define DUK_HTHREAD_STRING_READ_INT16_LE(thr)                         DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_READ_INT16_LE)
+#define DUK_HEAP_STRING_READ_UINT16_BE(heap)                          DUK_HEAP_GET_STRING((heap),DUK_STRIDX_READ_UINT16_BE)
+#define DUK_HTHREAD_STRING_READ_UINT16_BE(thr)                        DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_READ_UINT16_BE)
+#define DUK_HEAP_STRING_READ_UINT16_LE(heap)                          DUK_HEAP_GET_STRING((heap),DUK_STRIDX_READ_UINT16_LE)
+#define DUK_HTHREAD_STRING_READ_UINT16_LE(thr)                        DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_READ_UINT16_LE)
+#define DUK_HEAP_STRING_READ_INT8(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_READ_INT8)
+#define DUK_HTHREAD_STRING_READ_INT8(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_READ_INT8)
+#define DUK_HEAP_STRING_READ_UINT8(heap)                              DUK_HEAP_GET_STRING((heap),DUK_STRIDX_READ_UINT8)
+#define DUK_HTHREAD_STRING_READ_UINT8(thr)                            DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_READ_UINT8)
+#define DUK_HEAP_STRING_COPY(heap)                                    DUK_HEAP_GET_STRING((heap),DUK_STRIDX_COPY)
+#define DUK_HTHREAD_STRING_COPY(thr)                                  DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_COPY)
+#define DUK_HEAP_STRING_EQUALS(heap)                                  DUK_HEAP_GET_STRING((heap),DUK_STRIDX_EQUALS)
+#define DUK_HTHREAD_STRING_EQUALS(thr)                                DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_EQUALS)
+#define DUK_HEAP_STRING_FILL(heap)                                    DUK_HEAP_GET_STRING((heap),DUK_STRIDX_FILL)
+#define DUK_HTHREAD_STRING_FILL(thr)                                  DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_FILL)
+#define DUK_HEAP_STRING_WRITE(heap)                                   DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WRITE)
+#define DUK_HTHREAD_STRING_WRITE(thr)                                 DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WRITE)
+#define DUK_HEAP_STRING_COMPARE(heap)                                 DUK_HEAP_GET_STRING((heap),DUK_STRIDX_COMPARE)
+#define DUK_HTHREAD_STRING_COMPARE(thr)                               DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_COMPARE)
+#define DUK_HEAP_STRING_BYTE_LENGTH(heap)                             DUK_HEAP_GET_STRING((heap),DUK_STRIDX_BYTE_LENGTH)
+#define DUK_HTHREAD_STRING_BYTE_LENGTH(thr)                           DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_BYTE_LENGTH)
+#define DUK_HEAP_STRING_IS_BUFFER(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_IS_BUFFER)
+#define DUK_HTHREAD_STRING_IS_BUFFER(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_IS_BUFFER)
+#define DUK_HEAP_STRING_IS_ENCODING(heap)                             DUK_HEAP_GET_STRING((heap),DUK_STRIDX_IS_ENCODING)
+#define DUK_HTHREAD_STRING_IS_ENCODING(thr)                           DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_IS_ENCODING)
+#define DUK_HEAP_STRING_EXPORTS(heap)                                 DUK_HEAP_GET_STRING((heap),DUK_STRIDX_EXPORTS)
+#define DUK_HTHREAD_STRING_EXPORTS(thr)                               DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_EXPORTS)
 #define DUK_HEAP_STRING_ID(heap)                                      DUK_HEAP_GET_STRING((heap),DUK_STRIDX_ID)
 #define DUK_HTHREAD_STRING_ID(thr)                                    DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_ID)
 #define DUK_HEAP_STRING_REQUIRE(heap)                                 DUK_HEAP_GET_STRING((heap),DUK_STRIDX_REQUIRE)
@@ -2336,6 +2916,8 @@ extern const duk_uint8_t duk_strings_data[];
 #define DUK_HTHREAD_STRING_TYPEOF(thr)                                DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_TYPEOF)
 #define DUK_HEAP_STRING_VAR(heap)                                     DUK_HEAP_GET_STRING((heap),DUK_STRIDX_VAR)
 #define DUK_HTHREAD_STRING_VAR(thr)                                   DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_VAR)
+#define DUK_HEAP_STRING_CONST(heap)                                   DUK_HEAP_GET_STRING((heap),DUK_STRIDX_CONST)
+#define DUK_HTHREAD_STRING_CONST(thr)                                 DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_CONST)
 #define DUK_HEAP_STRING_VOID(heap)                                    DUK_HEAP_GET_STRING((heap),DUK_STRIDX_VOID)
 #define DUK_HTHREAD_STRING_VOID(thr)                                  DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_VOID)
 #define DUK_HEAP_STRING_WHILE(heap)                                   DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WHILE)
@@ -2344,8 +2926,6 @@ extern const duk_uint8_t duk_strings_data[];
 #define DUK_HTHREAD_STRING_WITH(thr)                                  DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WITH)
 #define DUK_HEAP_STRING_CLASS(heap)                                   DUK_HEAP_GET_STRING((heap),DUK_STRIDX_CLASS)
 #define DUK_HTHREAD_STRING_CLASS(thr)                                 DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_CLASS)
-#define DUK_HEAP_STRING_CONST(heap)                                   DUK_HEAP_GET_STRING((heap),DUK_STRIDX_CONST)
-#define DUK_HTHREAD_STRING_CONST(thr)                                 DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_CONST)
 #define DUK_HEAP_STRING_ENUM(heap)                                    DUK_HEAP_GET_STRING((heap),DUK_STRIDX_ENUM)
 #define DUK_HTHREAD_STRING_ENUM(thr)                                  DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_ENUM)
 #define DUK_HEAP_STRING_EXPORT(heap)                                  DUK_HEAP_GET_STRING((heap),DUK_STRIDX_EXPORT)
@@ -2381,19 +2961,21 @@ extern const duk_uint8_t duk_strings_data[];
 #define DUK_HEAP_STRING_YIELD(heap)                                   DUK_HEAP_GET_STRING((heap),DUK_STRIDX_YIELD)
 #define DUK_HTHREAD_STRING_YIELD(thr)                                 DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_YIELD)
 
-#define DUK_HEAP_NUM_STRINGS                                          336
+#define DUK_HEAP_NUM_STRINGS                                          414
 
-#define DUK_STRIDX_START_RESERVED                                     291
-#define DUK_STRIDX_START_STRICT_RESERVED                              327
-#define DUK_STRIDX_END_RESERVED                                       336                            /* exclusive endpoint */
+#define DUK_STRIDX_START_RESERVED                                     369
+#define DUK_STRIDX_START_STRICT_RESERVED                              405
+#define DUK_STRIDX_END_RESERVED                                       414                            /* exclusive endpoint */
 
-extern const duk_c_function duk_bi_native_functions[];
-extern const duk_uint8_t duk_builtins_data[];
+#if !defined(DUK_SINGLE_FILE)
+DUK_INTERNAL_DECL const duk_c_function duk_bi_native_functions[149];
+DUK_INTERNAL_DECL const duk_uint8_t duk_builtins_data[1955];
 #ifdef DUK_USE_BUILTIN_INITJS
-extern const duk_uint8_t duk_initjs_data[];
+DUK_INTERNAL_DECL const duk_uint8_t duk_initjs_data[187];
 #endif  /* DUK_USE_BUILTIN_INITJS */
+#endif  /* !DUK_SINGLE_FILE */
 
-#define DUK_BUILTINS_DATA_LENGTH                                      1336
+#define DUK_BUILTINS_DATA_LENGTH                                      1955
 #ifdef DUK_USE_BUILTIN_INITJS
 #define DUK_BUILTIN_INITJS_DATA_LENGTH                                187
 #endif  /* DUK_USE_BUILTIN_INITJS */
@@ -2444,351 +3026,456 @@ extern const duk_uint8_t duk_initjs_data[];
 #define DUK_BIDX_LOGGER_CONSTRUCTOR                                   43
 #define DUK_BIDX_LOGGER_PROTOTYPE                                     44
 #define DUK_BIDX_DOUBLE_ERROR                                         45
-
-#define DUK_NUM_BUILTINS                                              46
+#define DUK_BIDX_ARRAYBUFFER_CONSTRUCTOR                              46
+#define DUK_BIDX_ARRAYBUFFER_PROTOTYPE                                47
+#define DUK_BIDX_DATAVIEW_CONSTRUCTOR                                 48
+#define DUK_BIDX_DATAVIEW_PROTOTYPE                                   49
+#define DUK_BIDX_TYPEDARRAY_PROTOTYPE                                 50
+#define DUK_BIDX_INT8ARRAY_CONSTRUCTOR                                51
+#define DUK_BIDX_INT8ARRAY_PROTOTYPE                                  52
+#define DUK_BIDX_UINT8ARRAY_CONSTRUCTOR                               53
+#define DUK_BIDX_UINT8ARRAY_PROTOTYPE                                 54
+#define DUK_BIDX_UINT8CLAMPEDARRAY_CONSTRUCTOR                        55
+#define DUK_BIDX_UINT8CLAMPEDARRAY_PROTOTYPE                          56
+#define DUK_BIDX_INT16ARRAY_CONSTRUCTOR                               57
+#define DUK_BIDX_INT16ARRAY_PROTOTYPE                                 58
+#define DUK_BIDX_UINT16ARRAY_CONSTRUCTOR                              59
+#define DUK_BIDX_UINT16ARRAY_PROTOTYPE                                60
+#define DUK_BIDX_INT32ARRAY_CONSTRUCTOR                               61
+#define DUK_BIDX_INT32ARRAY_PROTOTYPE                                 62
+#define DUK_BIDX_UINT32ARRAY_CONSTRUCTOR                              63
+#define DUK_BIDX_UINT32ARRAY_PROTOTYPE                                64
+#define DUK_BIDX_FLOAT32ARRAY_CONSTRUCTOR                             65
+#define DUK_BIDX_FLOAT32ARRAY_PROTOTYPE                               66
+#define DUK_BIDX_FLOAT64ARRAY_CONSTRUCTOR                             67
+#define DUK_BIDX_FLOAT64ARRAY_PROTOTYPE                               68
+#define DUK_BIDX_NODEJS_BUFFER_CONSTRUCTOR                            69
+#define DUK_BIDX_NODEJS_BUFFER_PROTOTYPE                              70
+
+#define DUK_NUM_BUILTINS                                              71
 
 #elif defined(DUK_USE_DOUBLE_ME)
-extern const duk_uint8_t duk_strings_data[];
+#if !defined(DUK_SINGLE_FILE)
+DUK_INTERNAL_DECL const duk_uint8_t duk_strings_data[2624];
+#endif  /* !DUK_SINGLE_FILE */
 
-#define DUK_STRDATA_DATA_LENGTH                                       1931
+#define DUK_STRDATA_DATA_LENGTH                                       2624
 #define DUK_STRDATA_MAX_STRLEN                                        24
 
 #define DUK_STRIDX_UC_LOGGER                                          0                              /* 'Logger' */
 #define DUK_STRIDX_UC_THREAD                                          1                              /* 'Thread' */
 #define DUK_STRIDX_UC_POINTER                                         2                              /* 'Pointer' */
-#define DUK_STRIDX_UC_BUFFER                                          3                              /* 'Buffer' */
-#define DUK_STRIDX_DEC_ENV                                            4                              /* 'DecEnv' */
-#define DUK_STRIDX_OBJ_ENV                                            5                              /* 'ObjEnv' */
-#define DUK_STRIDX_EMPTY_STRING                                       6                              /* '' */
-#define DUK_STRIDX_GLOBAL                                             7                              /* 'global' */
-#define DUK_STRIDX_UC_ARGUMENTS                                       8                              /* 'Arguments' */
-#define DUK_STRIDX_JSON                                               9                              /* 'JSON' */
-#define DUK_STRIDX_MATH                                               10                             /* 'Math' */
-#define DUK_STRIDX_UC_ERROR                                           11                             /* 'Error' */
-#define DUK_STRIDX_REG_EXP                                            12                             /* 'RegExp' */
-#define DUK_STRIDX_DATE                                               13                             /* 'Date' */
-#define DUK_STRIDX_UC_NUMBER                                          14                             /* 'Number' */
-#define DUK_STRIDX_UC_BOOLEAN                                         15                             /* 'Boolean' */
-#define DUK_STRIDX_UC_STRING                                          16                             /* 'String' */
-#define DUK_STRIDX_ARRAY                                              17                             /* 'Array' */
-#define DUK_STRIDX_UC_FUNCTION                                        18                             /* 'Function' */
-#define DUK_STRIDX_UC_OBJECT                                          19                             /* 'Object' */
-#define DUK_STRIDX_UC_NULL                                            20                             /* 'Null' */
-#define DUK_STRIDX_UC_UNDEFINED                                       21                             /* 'Undefined' */
-#define DUK_STRIDX_JSON_EXT_FUNCTION2                                 22                             /* '{_func:true}' */
-#define DUK_STRIDX_JSON_EXT_FUNCTION1                                 23                             /* '{"_func":true}' */
-#define DUK_STRIDX_JSON_EXT_NEGINF                                    24                             /* '{"_ninf":true}' */
-#define DUK_STRIDX_JSON_EXT_POSINF                                    25                             /* '{"_inf":true}' */
-#define DUK_STRIDX_JSON_EXT_NAN                                       26                             /* '{"_nan":true}' */
-#define DUK_STRIDX_JSON_EXT_UNDEFINED                                 27                             /* '{"_undef":true}' */
-#define DUK_STRIDX_TO_LOG_STRING                                      28                             /* 'toLogString' */
-#define DUK_STRIDX_CLOG                                               29                             /* 'clog' */
-#define DUK_STRIDX_LC_L                                               30                             /* 'l' */
-#define DUK_STRIDX_LC_N                                               31                             /* 'n' */
-#define DUK_STRIDX_LC_FATAL                                           32                             /* 'fatal' */
-#define DUK_STRIDX_LC_ERROR                                           33                             /* 'error' */
-#define DUK_STRIDX_LC_WARN                                            34                             /* 'warn' */
-#define DUK_STRIDX_LC_DEBUG                                           35                             /* 'debug' */
-#define DUK_STRIDX_LC_TRACE                                           36                             /* 'trace' */
-#define DUK_STRIDX_RAW                                                37                             /* 'raw' */
-#define DUK_STRIDX_FMT                                                38                             /* 'fmt' */
-#define DUK_STRIDX_CURRENT                                            39                             /* 'current' */
-#define DUK_STRIDX_RESUME                                             40                             /* 'resume' */
-#define DUK_STRIDX_COMPACT                                            41                             /* 'compact' */
-#define DUK_STRIDX_JC                                                 42                             /* 'jc' */
-#define DUK_STRIDX_JX                                                 43                             /* 'jx' */
-#define DUK_STRIDX_BASE64                                             44                             /* 'base64' */
-#define DUK_STRIDX_HEX                                                45                             /* 'hex' */
-#define DUK_STRIDX_DEC                                                46                             /* 'dec' */
-#define DUK_STRIDX_ENC                                                47                             /* 'enc' */
-#define DUK_STRIDX_FIN                                                48                             /* 'fin' */
-#define DUK_STRIDX_GC                                                 49                             /* 'gc' */
-#define DUK_STRIDX_ACT                                                50                             /* 'act' */
-#define DUK_STRIDX_LC_INFO                                            51                             /* 'info' */
-#define DUK_STRIDX_VERSION                                            52                             /* 'version' */
-#define DUK_STRIDX_ENV                                                53                             /* 'env' */
-#define DUK_STRIDX_MOD_LOADED                                         54                             /* 'modLoaded' */
-#define DUK_STRIDX_MOD_SEARCH                                         55                             /* 'modSearch' */
-#define DUK_STRIDX_ERR_THROW                                          56                             /* 'errThrow' */
-#define DUK_STRIDX_ERR_CREATE                                         57                             /* 'errCreate' */
-#define DUK_STRIDX_COMPILE                                            58                             /* 'compile' */
-#define DUK_STRIDX_INT_REGBASE                                        59                             /* '\x00regbase' */
-#define DUK_STRIDX_INT_THREAD                                         60                             /* '\x00thread' */
-#define DUK_STRIDX_INT_HANDLER                                        61                             /* '\x00handler' */
-#define DUK_STRIDX_INT_FINALIZER                                      62                             /* '\x00finalizer' */
-#define DUK_STRIDX_INT_CALLEE                                         63                             /* '\x00callee' */
-#define DUK_STRIDX_INT_MAP                                            64                             /* '\x00map' */
-#define DUK_STRIDX_INT_ARGS                                           65                             /* '\x00args' */
-#define DUK_STRIDX_INT_THIS                                           66                             /* '\x00this' */
-#define DUK_STRIDX_INT_PC2LINE                                        67                             /* '\x00pc2line' */
-#define DUK_STRIDX_INT_SOURCE                                         68                             /* '\x00source' */
-#define DUK_STRIDX_INT_VARENV                                         69                             /* '\x00varenv' */
-#define DUK_STRIDX_INT_LEXENV                                         70                             /* '\x00lexenv' */
-#define DUK_STRIDX_INT_VARMAP                                         71                             /* '\x00varmap' */
-#define DUK_STRIDX_INT_FORMALS                                        72                             /* '\x00formals' */
-#define DUK_STRIDX_INT_BYTECODE                                       73                             /* '\x00bytecode' */
-#define DUK_STRIDX_INT_NEXT                                           74                             /* '\x00next' */
-#define DUK_STRIDX_INT_TARGET                                         75                             /* '\x00target' */
-#define DUK_STRIDX_INT_VALUE                                          76                             /* '\x00value' */
-#define DUK_STRIDX_LC_POINTER                                         77                             /* 'pointer' */
-#define DUK_STRIDX_LC_BUFFER                                          78                             /* 'buffer' */
-#define DUK_STRIDX_TRACEDATA                                          79                             /* 'tracedata' */
-#define DUK_STRIDX_LINE_NUMBER                                        80                             /* 'lineNumber' */
-#define DUK_STRIDX_FILE_NAME                                          81                             /* 'fileName' */
-#define DUK_STRIDX_PC                                                 82                             /* 'pc' */
-#define DUK_STRIDX_STACK                                              83                             /* 'stack' */
-#define DUK_STRIDX_THROW_TYPE_ERROR                                   84                             /* 'ThrowTypeError' */
-#define DUK_STRIDX_DUKTAPE                                            85                             /* 'Duktape' */
-#define DUK_STRIDX_ID                                                 86                             /* 'id' */
-#define DUK_STRIDX_REQUIRE                                            87                             /* 'require' */
-#define DUK_STRIDX___PROTO__                                          88                             /* '__proto__' */
-#define DUK_STRIDX_SET_PROTOTYPE_OF                                   89                             /* 'setPrototypeOf' */
-#define DUK_STRIDX_OWN_KEYS                                           90                             /* 'ownKeys' */
-#define DUK_STRIDX_ENUMERATE                                          91                             /* 'enumerate' */
-#define DUK_STRIDX_DELETE_PROPERTY                                    92                             /* 'deleteProperty' */
-#define DUK_STRIDX_HAS                                                93                             /* 'has' */
-#define DUK_STRIDX_PROXY                                              94                             /* 'Proxy' */
-#define DUK_STRIDX_CALLEE                                             95                             /* 'callee' */
-#define DUK_STRIDX_INVALID_DATE                                       96                             /* 'Invalid Date' */
-#define DUK_STRIDX_BRACKETED_ELLIPSIS                                 97                             /* '[...]' */
-#define DUK_STRIDX_NEWLINE_TAB                                        98                             /* '\n\t' */
-#define DUK_STRIDX_SPACE                                              99                             /* ' ' */
-#define DUK_STRIDX_COMMA                                              100                            /* ',' */
-#define DUK_STRIDX_MINUS_ZERO                                         101                            /* '-0' */
-#define DUK_STRIDX_PLUS_ZERO                                          102                            /* '+0' */
-#define DUK_STRIDX_ZERO                                               103                            /* '0' */
-#define DUK_STRIDX_MINUS_INFINITY                                     104                            /* '-Infinity' */
-#define DUK_STRIDX_PLUS_INFINITY                                      105                            /* '+Infinity' */
-#define DUK_STRIDX_INFINITY                                           106                            /* 'Infinity' */
-#define DUK_STRIDX_LC_OBJECT                                          107                            /* 'object' */
-#define DUK_STRIDX_LC_STRING                                          108                            /* 'string' */
-#define DUK_STRIDX_LC_NUMBER                                          109                            /* 'number' */
-#define DUK_STRIDX_LC_BOOLEAN                                         110                            /* 'boolean' */
-#define DUK_STRIDX_LC_UNDEFINED                                       111                            /* 'undefined' */
-#define DUK_STRIDX_STRINGIFY                                          112                            /* 'stringify' */
-#define DUK_STRIDX_TAN                                                113                            /* 'tan' */
-#define DUK_STRIDX_SQRT                                               114                            /* 'sqrt' */
-#define DUK_STRIDX_SIN                                                115                            /* 'sin' */
-#define DUK_STRIDX_ROUND                                              116                            /* 'round' */
-#define DUK_STRIDX_RANDOM                                             117                            /* 'random' */
-#define DUK_STRIDX_POW                                                118                            /* 'pow' */
-#define DUK_STRIDX_MIN                                                119                            /* 'min' */
-#define DUK_STRIDX_MAX                                                120                            /* 'max' */
-#define DUK_STRIDX_LOG                                                121                            /* 'log' */
-#define DUK_STRIDX_FLOOR                                              122                            /* 'floor' */
-#define DUK_STRIDX_EXP                                                123                            /* 'exp' */
-#define DUK_STRIDX_COS                                                124                            /* 'cos' */
-#define DUK_STRIDX_CEIL                                               125                            /* 'ceil' */
-#define DUK_STRIDX_ATAN2                                              126                            /* 'atan2' */
-#define DUK_STRIDX_ATAN                                               127                            /* 'atan' */
-#define DUK_STRIDX_ASIN                                               128                            /* 'asin' */
-#define DUK_STRIDX_ACOS                                               129                            /* 'acos' */
-#define DUK_STRIDX_ABS                                                130                            /* 'abs' */
-#define DUK_STRIDX_SQRT2                                              131                            /* 'SQRT2' */
-#define DUK_STRIDX_SQRT1_2                                            132                            /* 'SQRT1_2' */
-#define DUK_STRIDX_PI                                                 133                            /* 'PI' */
-#define DUK_STRIDX_LOG10E                                             134                            /* 'LOG10E' */
-#define DUK_STRIDX_LOG2E                                              135                            /* 'LOG2E' */
-#define DUK_STRIDX_LN2                                                136                            /* 'LN2' */
-#define DUK_STRIDX_LN10                                               137                            /* 'LN10' */
-#define DUK_STRIDX_E                                                  138                            /* 'E' */
-#define DUK_STRIDX_MESSAGE                                            139                            /* 'message' */
-#define DUK_STRIDX_NAME                                               140                            /* 'name' */
-#define DUK_STRIDX_INPUT                                              141                            /* 'input' */
-#define DUK_STRIDX_INDEX                                              142                            /* 'index' */
-#define DUK_STRIDX_ESCAPED_EMPTY_REGEXP                               143                            /* '(?:)' */
-#define DUK_STRIDX_LAST_INDEX                                         144                            /* 'lastIndex' */
-#define DUK_STRIDX_MULTILINE                                          145                            /* 'multiline' */
-#define DUK_STRIDX_IGNORE_CASE                                        146                            /* 'ignoreCase' */
-#define DUK_STRIDX_SOURCE                                             147                            /* 'source' */
-#define DUK_STRIDX_TEST                                               148                            /* 'test' */
-#define DUK_STRIDX_EXEC                                               149                            /* 'exec' */
-#define DUK_STRIDX_TO_GMT_STRING                                      150                            /* 'toGMTString' */
-#define DUK_STRIDX_SET_YEAR                                           151                            /* 'setYear' */
-#define DUK_STRIDX_GET_YEAR                                           152                            /* 'getYear' */
-#define DUK_STRIDX_TO_JSON                                            153                            /* 'toJSON' */
-#define DUK_STRIDX_TO_ISO_STRING                                      154                            /* 'toISOString' */
-#define DUK_STRIDX_TO_UTC_STRING                                      155                            /* 'toUTCString' */
-#define DUK_STRIDX_SET_UTC_FULL_YEAR                                  156                            /* 'setUTCFullYear' */
-#define DUK_STRIDX_SET_FULL_YEAR                                      157                            /* 'setFullYear' */
-#define DUK_STRIDX_SET_UTC_MONTH                                      158                            /* 'setUTCMonth' */
-#define DUK_STRIDX_SET_MONTH                                          159                            /* 'setMonth' */
-#define DUK_STRIDX_SET_UTC_DATE                                       160                            /* 'setUTCDate' */
-#define DUK_STRIDX_SET_DATE                                           161                            /* 'setDate' */
-#define DUK_STRIDX_SET_UTC_HOURS                                      162                            /* 'setUTCHours' */
-#define DUK_STRIDX_SET_HOURS                                          163                            /* 'setHours' */
-#define DUK_STRIDX_SET_UTC_MINUTES                                    164                            /* 'setUTCMinutes' */
-#define DUK_STRIDX_SET_MINUTES                                        165                            /* 'setMinutes' */
-#define DUK_STRIDX_SET_UTC_SECONDS                                    166                            /* 'setUTCSeconds' */
-#define DUK_STRIDX_SET_SECONDS                                        167                            /* 'setSeconds' */
-#define DUK_STRIDX_SET_UTC_MILLISECONDS                               168                            /* 'setUTCMilliseconds' */
-#define DUK_STRIDX_SET_MILLISECONDS                                   169                            /* 'setMilliseconds' */
-#define DUK_STRIDX_SET_TIME                                           170                            /* 'setTime' */
-#define DUK_STRIDX_GET_TIMEZONE_OFFSET                                171                            /* 'getTimezoneOffset' */
-#define DUK_STRIDX_GET_UTC_MILLISECONDS                               172                            /* 'getUTCMilliseconds' */
-#define DUK_STRIDX_GET_MILLISECONDS                                   173                            /* 'getMilliseconds' */
-#define DUK_STRIDX_GET_UTC_SECONDS                                    174                            /* 'getUTCSeconds' */
-#define DUK_STRIDX_GET_SECONDS                                        175                            /* 'getSeconds' */
-#define DUK_STRIDX_GET_UTC_MINUTES                                    176                            /* 'getUTCMinutes' */
-#define DUK_STRIDX_GET_MINUTES                                        177                            /* 'getMinutes' */
-#define DUK_STRIDX_GET_UTC_HOURS                                      178                            /* 'getUTCHours' */
-#define DUK_STRIDX_GET_HOURS                                          179                            /* 'getHours' */
-#define DUK_STRIDX_GET_UTC_DAY                                        180                            /* 'getUTCDay' */
-#define DUK_STRIDX_GET_DAY                                            181                            /* 'getDay' */
-#define DUK_STRIDX_GET_UTC_DATE                                       182                            /* 'getUTCDate' */
-#define DUK_STRIDX_GET_DATE                                           183                            /* 'getDate' */
-#define DUK_STRIDX_GET_UTC_MONTH                                      184                            /* 'getUTCMonth' */
-#define DUK_STRIDX_GET_MONTH                                          185                            /* 'getMonth' */
-#define DUK_STRIDX_GET_UTC_FULL_YEAR                                  186                            /* 'getUTCFullYear' */
-#define DUK_STRIDX_GET_FULL_YEAR                                      187                            /* 'getFullYear' */
-#define DUK_STRIDX_GET_TIME                                           188                            /* 'getTime' */
-#define DUK_STRIDX_TO_LOCALE_TIME_STRING                              189                            /* 'toLocaleTimeString' */
-#define DUK_STRIDX_TO_LOCALE_DATE_STRING                              190                            /* 'toLocaleDateString' */
-#define DUK_STRIDX_TO_TIME_STRING                                     191                            /* 'toTimeString' */
-#define DUK_STRIDX_TO_DATE_STRING                                     192                            /* 'toDateString' */
-#define DUK_STRIDX_NOW                                                193                            /* 'now' */
-#define DUK_STRIDX_UTC                                                194                            /* 'UTC' */
-#define DUK_STRIDX_PARSE                                              195                            /* 'parse' */
-#define DUK_STRIDX_TO_PRECISION                                       196                            /* 'toPrecision' */
-#define DUK_STRIDX_TO_EXPONENTIAL                                     197                            /* 'toExponential' */
-#define DUK_STRIDX_TO_FIXED                                           198                            /* 'toFixed' */
-#define DUK_STRIDX_POSITIVE_INFINITY                                  199                            /* 'POSITIVE_INFINITY' */
-#define DUK_STRIDX_NEGATIVE_INFINITY                                  200                            /* 'NEGATIVE_INFINITY' */
-#define DUK_STRIDX_NAN                                                201                            /* 'NaN' */
-#define DUK_STRIDX_MIN_VALUE                                          202                            /* 'MIN_VALUE' */
-#define DUK_STRIDX_MAX_VALUE                                          203                            /* 'MAX_VALUE' */
-#define DUK_STRIDX_SUBSTR                                             204                            /* 'substr' */
-#define DUK_STRIDX_TRIM                                               205                            /* 'trim' */
-#define DUK_STRIDX_TO_LOCALE_UPPER_CASE                               206                            /* 'toLocaleUpperCase' */
-#define DUK_STRIDX_TO_UPPER_CASE                                      207                            /* 'toUpperCase' */
-#define DUK_STRIDX_TO_LOCALE_LOWER_CASE                               208                            /* 'toLocaleLowerCase' */
-#define DUK_STRIDX_TO_LOWER_CASE                                      209                            /* 'toLowerCase' */
-#define DUK_STRIDX_SUBSTRING                                          210                            /* 'substring' */
-#define DUK_STRIDX_SPLIT                                              211                            /* 'split' */
-#define DUK_STRIDX_SEARCH                                             212                            /* 'search' */
-#define DUK_STRIDX_REPLACE                                            213                            /* 'replace' */
-#define DUK_STRIDX_MATCH                                              214                            /* 'match' */
-#define DUK_STRIDX_LOCALE_COMPARE                                     215                            /* 'localeCompare' */
-#define DUK_STRIDX_CHAR_CODE_AT                                       216                            /* 'charCodeAt' */
-#define DUK_STRIDX_CHAR_AT                                            217                            /* 'charAt' */
-#define DUK_STRIDX_FROM_CHAR_CODE                                     218                            /* 'fromCharCode' */
-#define DUK_STRIDX_REDUCE_RIGHT                                       219                            /* 'reduceRight' */
-#define DUK_STRIDX_REDUCE                                             220                            /* 'reduce' */
-#define DUK_STRIDX_FILTER                                             221                            /* 'filter' */
-#define DUK_STRIDX_MAP                                                222                            /* 'map' */
-#define DUK_STRIDX_FOR_EACH                                           223                            /* 'forEach' */
-#define DUK_STRIDX_SOME                                               224                            /* 'some' */
-#define DUK_STRIDX_EVERY                                              225                            /* 'every' */
-#define DUK_STRIDX_LAST_INDEX_OF                                      226                            /* 'lastIndexOf' */
-#define DUK_STRIDX_INDEX_OF                                           227                            /* 'indexOf' */
-#define DUK_STRIDX_UNSHIFT                                            228                            /* 'unshift' */
-#define DUK_STRIDX_SPLICE                                             229                            /* 'splice' */
-#define DUK_STRIDX_SORT                                               230                            /* 'sort' */
-#define DUK_STRIDX_SLICE                                              231                            /* 'slice' */
-#define DUK_STRIDX_SHIFT                                              232                            /* 'shift' */
-#define DUK_STRIDX_REVERSE                                            233                            /* 'reverse' */
-#define DUK_STRIDX_PUSH                                               234                            /* 'push' */
-#define DUK_STRIDX_POP                                                235                            /* 'pop' */
-#define DUK_STRIDX_JOIN                                               236                            /* 'join' */
-#define DUK_STRIDX_CONCAT                                             237                            /* 'concat' */
-#define DUK_STRIDX_IS_ARRAY                                           238                            /* 'isArray' */
-#define DUK_STRIDX_LC_ARGUMENTS                                       239                            /* 'arguments' */
-#define DUK_STRIDX_CALLER                                             240                            /* 'caller' */
-#define DUK_STRIDX_BIND                                               241                            /* 'bind' */
-#define DUK_STRIDX_CALL                                               242                            /* 'call' */
-#define DUK_STRIDX_APPLY                                              243                            /* 'apply' */
-#define DUK_STRIDX_PROPERTY_IS_ENUMERABLE                             244                            /* 'propertyIsEnumerable' */
-#define DUK_STRIDX_IS_PROTOTYPE_OF                                    245                            /* 'isPrototypeOf' */
-#define DUK_STRIDX_HAS_OWN_PROPERTY                                   246                            /* 'hasOwnProperty' */
-#define DUK_STRIDX_VALUE_OF                                           247                            /* 'valueOf' */
-#define DUK_STRIDX_TO_LOCALE_STRING                                   248                            /* 'toLocaleString' */
-#define DUK_STRIDX_TO_STRING                                          249                            /* 'toString' */
-#define DUK_STRIDX_CONSTRUCTOR                                        250                            /* 'constructor' */
-#define DUK_STRIDX_SET                                                251                            /* 'set' */
-#define DUK_STRIDX_GET                                                252                            /* 'get' */
-#define DUK_STRIDX_ENUMERABLE                                         253                            /* 'enumerable' */
-#define DUK_STRIDX_CONFIGURABLE                                       254                            /* 'configurable' */
-#define DUK_STRIDX_WRITABLE                                           255                            /* 'writable' */
-#define DUK_STRIDX_VALUE                                              256                            /* 'value' */
-#define DUK_STRIDX_KEYS                                               257                            /* 'keys' */
-#define DUK_STRIDX_IS_EXTENSIBLE                                      258                            /* 'isExtensible' */
-#define DUK_STRIDX_IS_FROZEN                                          259                            /* 'isFrozen' */
-#define DUK_STRIDX_IS_SEALED                                          260                            /* 'isSealed' */
-#define DUK_STRIDX_PREVENT_EXTENSIONS                                 261                            /* 'preventExtensions' */
-#define DUK_STRIDX_FREEZE                                             262                            /* 'freeze' */
-#define DUK_STRIDX_SEAL                                               263                            /* 'seal' */
-#define DUK_STRIDX_DEFINE_PROPERTIES                                  264                            /* 'defineProperties' */
-#define DUK_STRIDX_DEFINE_PROPERTY                                    265                            /* 'defineProperty' */
-#define DUK_STRIDX_CREATE                                             266                            /* 'create' */
-#define DUK_STRIDX_GET_OWN_PROPERTY_NAMES                             267                            /* 'getOwnPropertyNames' */
-#define DUK_STRIDX_GET_OWN_PROPERTY_DESCRIPTOR                        268                            /* 'getOwnPropertyDescriptor' */
-#define DUK_STRIDX_GET_PROTOTYPE_OF                                   269                            /* 'getPrototypeOf' */
-#define DUK_STRIDX_PROTOTYPE                                          270                            /* 'prototype' */
-#define DUK_STRIDX_LENGTH                                             271                            /* 'length' */
-#define DUK_STRIDX_ALERT                                              272                            /* 'alert' */
-#define DUK_STRIDX_PRINT                                              273                            /* 'print' */
-#define DUK_STRIDX_UNESCAPE                                           274                            /* 'unescape' */
-#define DUK_STRIDX_ESCAPE                                             275                            /* 'escape' */
-#define DUK_STRIDX_ENCODE_URI_COMPONENT                               276                            /* 'encodeURIComponent' */
-#define DUK_STRIDX_ENCODE_URI                                         277                            /* 'encodeURI' */
-#define DUK_STRIDX_DECODE_URI_COMPONENT                               278                            /* 'decodeURIComponent' */
-#define DUK_STRIDX_DECODE_URI                                         279                            /* 'decodeURI' */
-#define DUK_STRIDX_IS_FINITE                                          280                            /* 'isFinite' */
-#define DUK_STRIDX_IS_NAN                                             281                            /* 'isNaN' */
-#define DUK_STRIDX_PARSE_FLOAT                                        282                            /* 'parseFloat' */
-#define DUK_STRIDX_PARSE_INT                                          283                            /* 'parseInt' */
-#define DUK_STRIDX_EVAL                                               284                            /* 'eval' */
-#define DUK_STRIDX_URI_ERROR                                          285                            /* 'URIError' */
-#define DUK_STRIDX_TYPE_ERROR                                         286                            /* 'TypeError' */
-#define DUK_STRIDX_SYNTAX_ERROR                                       287                            /* 'SyntaxError' */
-#define DUK_STRIDX_REFERENCE_ERROR                                    288                            /* 'ReferenceError' */
-#define DUK_STRIDX_RANGE_ERROR                                        289                            /* 'RangeError' */
-#define DUK_STRIDX_EVAL_ERROR                                         290                            /* 'EvalError' */
-#define DUK_STRIDX_BREAK                                              291                            /* 'break' */
-#define DUK_STRIDX_CASE                                               292                            /* 'case' */
-#define DUK_STRIDX_CATCH                                              293                            /* 'catch' */
-#define DUK_STRIDX_CONTINUE                                           294                            /* 'continue' */
-#define DUK_STRIDX_DEBUGGER                                           295                            /* 'debugger' */
-#define DUK_STRIDX_DEFAULT                                            296                            /* 'default' */
-#define DUK_STRIDX_DELETE                                             297                            /* 'delete' */
-#define DUK_STRIDX_DO                                                 298                            /* 'do' */
-#define DUK_STRIDX_ELSE                                               299                            /* 'else' */
-#define DUK_STRIDX_FINALLY                                            300                            /* 'finally' */
-#define DUK_STRIDX_FOR                                                301                            /* 'for' */
-#define DUK_STRIDX_LC_FUNCTION                                        302                            /* 'function' */
-#define DUK_STRIDX_IF                                                 303                            /* 'if' */
-#define DUK_STRIDX_IN                                                 304                            /* 'in' */
-#define DUK_STRIDX_INSTANCEOF                                         305                            /* 'instanceof' */
-#define DUK_STRIDX_NEW                                                306                            /* 'new' */
-#define DUK_STRIDX_RETURN                                             307                            /* 'return' */
-#define DUK_STRIDX_SWITCH                                             308                            /* 'switch' */
-#define DUK_STRIDX_THIS                                               309                            /* 'this' */
-#define DUK_STRIDX_THROW                                              310                            /* 'throw' */
-#define DUK_STRIDX_TRY                                                311                            /* 'try' */
-#define DUK_STRIDX_TYPEOF                                             312                            /* 'typeof' */
-#define DUK_STRIDX_VAR                                                313                            /* 'var' */
-#define DUK_STRIDX_VOID                                               314                            /* 'void' */
-#define DUK_STRIDX_WHILE                                              315                            /* 'while' */
-#define DUK_STRIDX_WITH                                               316                            /* 'with' */
-#define DUK_STRIDX_CLASS                                              317                            /* 'class' */
-#define DUK_STRIDX_CONST                                              318                            /* 'const' */
-#define DUK_STRIDX_ENUM                                               319                            /* 'enum' */
-#define DUK_STRIDX_EXPORT                                             320                            /* 'export' */
-#define DUK_STRIDX_EXTENDS                                            321                            /* 'extends' */
-#define DUK_STRIDX_IMPORT                                             322                            /* 'import' */
-#define DUK_STRIDX_SUPER                                              323                            /* 'super' */
-#define DUK_STRIDX_LC_NULL                                            324                            /* 'null' */
-#define DUK_STRIDX_TRUE                                               325                            /* 'true' */
-#define DUK_STRIDX_FALSE                                              326                            /* 'false' */
-#define DUK_STRIDX_IMPLEMENTS                                         327                            /* 'implements' */
-#define DUK_STRIDX_INTERFACE                                          328                            /* 'interface' */
-#define DUK_STRIDX_LET                                                329                            /* 'let' */
-#define DUK_STRIDX_PACKAGE                                            330                            /* 'package' */
-#define DUK_STRIDX_PRIVATE                                            331                            /* 'private' */
-#define DUK_STRIDX_PROTECTED                                          332                            /* 'protected' */
-#define DUK_STRIDX_PUBLIC                                             333                            /* 'public' */
-#define DUK_STRIDX_STATIC                                             334                            /* 'static' */
-#define DUK_STRIDX_YIELD                                              335                            /* 'yield' */
+#define DUK_STRIDX_DEC_ENV                                            3                              /* 'DecEnv' */
+#define DUK_STRIDX_OBJ_ENV                                            4                              /* 'ObjEnv' */
+#define DUK_STRIDX_FLOAT64_ARRAY                                      5                              /* 'Float64Array' */
+#define DUK_STRIDX_FLOAT32_ARRAY                                      6                              /* 'Float32Array' */
+#define DUK_STRIDX_UINT32_ARRAY                                       7                              /* 'Uint32Array' */
+#define DUK_STRIDX_INT32_ARRAY                                        8                              /* 'Int32Array' */
+#define DUK_STRIDX_UINT16_ARRAY                                       9                              /* 'Uint16Array' */
+#define DUK_STRIDX_INT16_ARRAY                                        10                             /* 'Int16Array' */
+#define DUK_STRIDX_UINT8_CLAMPED_ARRAY                                11                             /* 'Uint8ClampedArray' */
+#define DUK_STRIDX_UINT8_ARRAY                                        12                             /* 'Uint8Array' */
+#define DUK_STRIDX_INT8_ARRAY                                         13                             /* 'Int8Array' */
+#define DUK_STRIDX_DATA_VIEW                                          14                             /* 'DataView' */
+#define DUK_STRIDX_ARRAY_BUFFER                                       15                             /* 'ArrayBuffer' */
+#define DUK_STRIDX_UC_BUFFER                                          16                             /* 'Buffer' */
+#define DUK_STRIDX_EMPTY_STRING                                       17                             /* '' */
+#define DUK_STRIDX_GLOBAL                                             18                             /* 'global' */
+#define DUK_STRIDX_UC_ARGUMENTS                                       19                             /* 'Arguments' */
+#define DUK_STRIDX_JSON                                               20                             /* 'JSON' */
+#define DUK_STRIDX_MATH                                               21                             /* 'Math' */
+#define DUK_STRIDX_UC_ERROR                                           22                             /* 'Error' */
+#define DUK_STRIDX_REG_EXP                                            23                             /* 'RegExp' */
+#define DUK_STRIDX_DATE                                               24                             /* 'Date' */
+#define DUK_STRIDX_UC_NUMBER                                          25                             /* 'Number' */
+#define DUK_STRIDX_UC_BOOLEAN                                         26                             /* 'Boolean' */
+#define DUK_STRIDX_UC_STRING                                          27                             /* 'String' */
+#define DUK_STRIDX_ARRAY                                              28                             /* 'Array' */
+#define DUK_STRIDX_UC_FUNCTION                                        29                             /* 'Function' */
+#define DUK_STRIDX_UC_OBJECT                                          30                             /* 'Object' */
+#define DUK_STRIDX_UC_NULL                                            31                             /* 'Null' */
+#define DUK_STRIDX_UC_UNDEFINED                                       32                             /* 'Undefined' */
+#define DUK_STRIDX_JSON_EXT_FUNCTION2                                 33                             /* '{_func:true}' */
+#define DUK_STRIDX_JSON_EXT_FUNCTION1                                 34                             /* '{"_func":true}' */
+#define DUK_STRIDX_JSON_EXT_NEGINF                                    35                             /* '{"_ninf":true}' */
+#define DUK_STRIDX_JSON_EXT_POSINF                                    36                             /* '{"_inf":true}' */
+#define DUK_STRIDX_JSON_EXT_NAN                                       37                             /* '{"_nan":true}' */
+#define DUK_STRIDX_JSON_EXT_UNDEFINED                                 38                             /* '{"_undef":true}' */
+#define DUK_STRIDX_TO_LOG_STRING                                      39                             /* 'toLogString' */
+#define DUK_STRIDX_CLOG                                               40                             /* 'clog' */
+#define DUK_STRIDX_LC_L                                               41                             /* 'l' */
+#define DUK_STRIDX_LC_N                                               42                             /* 'n' */
+#define DUK_STRIDX_LC_FATAL                                           43                             /* 'fatal' */
+#define DUK_STRIDX_LC_ERROR                                           44                             /* 'error' */
+#define DUK_STRIDX_LC_WARN                                            45                             /* 'warn' */
+#define DUK_STRIDX_LC_DEBUG                                           46                             /* 'debug' */
+#define DUK_STRIDX_LC_TRACE                                           47                             /* 'trace' */
+#define DUK_STRIDX_RAW                                                48                             /* 'raw' */
+#define DUK_STRIDX_FMT                                                49                             /* 'fmt' */
+#define DUK_STRIDX_CURRENT                                            50                             /* 'current' */
+#define DUK_STRIDX_RESUME                                             51                             /* 'resume' */
+#define DUK_STRIDX_COMPACT                                            52                             /* 'compact' */
+#define DUK_STRIDX_JC                                                 53                             /* 'jc' */
+#define DUK_STRIDX_JX                                                 54                             /* 'jx' */
+#define DUK_STRIDX_BASE64                                             55                             /* 'base64' */
+#define DUK_STRIDX_HEX                                                56                             /* 'hex' */
+#define DUK_STRIDX_DEC                                                57                             /* 'dec' */
+#define DUK_STRIDX_ENC                                                58                             /* 'enc' */
+#define DUK_STRIDX_FIN                                                59                             /* 'fin' */
+#define DUK_STRIDX_GC                                                 60                             /* 'gc' */
+#define DUK_STRIDX_ACT                                                61                             /* 'act' */
+#define DUK_STRIDX_LC_INFO                                            62                             /* 'info' */
+#define DUK_STRIDX_VERSION                                            63                             /* 'version' */
+#define DUK_STRIDX_ENV                                                64                             /* 'env' */
+#define DUK_STRIDX_MOD_LOADED                                         65                             /* 'modLoaded' */
+#define DUK_STRIDX_MOD_SEARCH                                         66                             /* 'modSearch' */
+#define DUK_STRIDX_ERR_THROW                                          67                             /* 'errThrow' */
+#define DUK_STRIDX_ERR_CREATE                                         68                             /* 'errCreate' */
+#define DUK_STRIDX_COMPILE                                            69                             /* 'compile' */
+#define DUK_STRIDX_INT_REGBASE                                        70                             /* '\x00Regbase' */
+#define DUK_STRIDX_INT_THREAD                                         71                             /* '\x00Thread' */
+#define DUK_STRIDX_INT_HANDLER                                        72                             /* '\x00Handler' */
+#define DUK_STRIDX_INT_FINALIZER                                      73                             /* '\x00Finalizer' */
+#define DUK_STRIDX_INT_CALLEE                                         74                             /* '\x00Callee' */
+#define DUK_STRIDX_INT_MAP                                            75                             /* '\x00Map' */
+#define DUK_STRIDX_INT_ARGS                                           76                             /* '\x00Args' */
+#define DUK_STRIDX_INT_THIS                                           77                             /* '\x00This' */
+#define DUK_STRIDX_INT_PC2LINE                                        78                             /* '\x00Pc2line' */
+#define DUK_STRIDX_INT_SOURCE                                         79                             /* '\x00Source' */
+#define DUK_STRIDX_INT_VARENV                                         80                             /* '\x00Varenv' */
+#define DUK_STRIDX_INT_LEXENV                                         81                             /* '\x00Lexenv' */
+#define DUK_STRIDX_INT_VARMAP                                         82                             /* '\x00Varmap' */
+#define DUK_STRIDX_INT_FORMALS                                        83                             /* '\x00Formals' */
+#define DUK_STRIDX_INT_BYTECODE                                       84                             /* '\x00Bytecode' */
+#define DUK_STRIDX_INT_NEXT                                           85                             /* '\x00Next' */
+#define DUK_STRIDX_INT_TARGET                                         86                             /* '\x00Target' */
+#define DUK_STRIDX_INT_VALUE                                          87                             /* '\x00Value' */
+#define DUK_STRIDX_LC_POINTER                                         88                             /* 'pointer' */
+#define DUK_STRIDX_INT_TRACEDATA                                      89                             /* '\x00Tracedata' */
+#define DUK_STRIDX_LINE_NUMBER                                        90                             /* 'lineNumber' */
+#define DUK_STRIDX_FILE_NAME                                          91                             /* 'fileName' */
+#define DUK_STRIDX_PC                                                 92                             /* 'pc' */
+#define DUK_STRIDX_STACK                                              93                             /* 'stack' */
+#define DUK_STRIDX_THROW_TYPE_ERROR                                   94                             /* 'ThrowTypeError' */
+#define DUK_STRIDX_DUKTAPE                                            95                             /* 'Duktape' */
+#define DUK_STRIDX_SET_FLOAT64                                        96                             /* 'setFloat64' */
+#define DUK_STRIDX_SET_FLOAT32                                        97                             /* 'setFloat32' */
+#define DUK_STRIDX_SET_UINT32                                         98                             /* 'setUint32' */
+#define DUK_STRIDX_SET_INT32                                          99                             /* 'setInt32' */
+#define DUK_STRIDX_SET_UINT16                                         100                            /* 'setUint16' */
+#define DUK_STRIDX_SET_INT16                                          101                            /* 'setInt16' */
+#define DUK_STRIDX_SET_UINT8                                          102                            /* 'setUint8' */
+#define DUK_STRIDX_SET_INT8                                           103                            /* 'setInt8' */
+#define DUK_STRIDX_GET_FLOAT64                                        104                            /* 'getFloat64' */
+#define DUK_STRIDX_GET_FLOAT32                                        105                            /* 'getFloat32' */
+#define DUK_STRIDX_GET_UINT32                                         106                            /* 'getUint32' */
+#define DUK_STRIDX_GET_INT32                                          107                            /* 'getInt32' */
+#define DUK_STRIDX_GET_UINT16                                         108                            /* 'getUint16' */
+#define DUK_STRIDX_GET_INT16                                          109                            /* 'getInt16' */
+#define DUK_STRIDX_GET_UINT8                                          110                            /* 'getUint8' */
+#define DUK_STRIDX_GET_INT8                                           111                            /* 'getInt8' */
+#define DUK_STRIDX_SUBARRAY                                           112                            /* 'subarray' */
+#define DUK_STRIDX_BYTES_PER_ELEMENT                                  113                            /* 'BYTES_PER_ELEMENT' */
+#define DUK_STRIDX_BYTE_OFFSET                                        114                            /* 'byteOffset' */
+#define DUK_STRIDX_LC_BUFFER                                          115                            /* 'buffer' */
+#define DUK_STRIDX_IS_VIEW                                            116                            /* 'isView' */
+#define DUK_STRIDX_DATA                                               117                            /* 'data' */
+#define DUK_STRIDX_TYPE                                               118                            /* 'type' */
+#define DUK_STRIDX_WRITE_INT_BE                                       119                            /* 'writeIntBE' */
+#define DUK_STRIDX_WRITE_INT_LE                                       120                            /* 'writeIntLE' */
+#define DUK_STRIDX_WRITE_UINT_BE                                      121                            /* 'writeUIntBE' */
+#define DUK_STRIDX_WRITE_UINT_LE                                      122                            /* 'writeUIntLE' */
+#define DUK_STRIDX_WRITE_DOUBLE_BE                                    123                            /* 'writeDoubleBE' */
+#define DUK_STRIDX_WRITE_DOUBLE_LE                                    124                            /* 'writeDoubleLE' */
+#define DUK_STRIDX_WRITE_FLOAT_BE                                     125                            /* 'writeFloatBE' */
+#define DUK_STRIDX_WRITE_FLOAT_LE                                     126                            /* 'writeFloatLE' */
+#define DUK_STRIDX_WRITE_INT32_BE                                     127                            /* 'writeInt32BE' */
+#define DUK_STRIDX_WRITE_INT32_LE                                     128                            /* 'writeInt32LE' */
+#define DUK_STRIDX_WRITE_UINT32_BE                                    129                            /* 'writeUInt32BE' */
+#define DUK_STRIDX_WRITE_UINT32_LE                                    130                            /* 'writeUInt32LE' */
+#define DUK_STRIDX_WRITE_INT16_BE                                     131                            /* 'writeInt16BE' */
+#define DUK_STRIDX_WRITE_INT16_LE                                     132                            /* 'writeInt16LE' */
+#define DUK_STRIDX_WRITE_UINT16_BE                                    133                            /* 'writeUInt16BE' */
+#define DUK_STRIDX_WRITE_UINT16_LE                                    134                            /* 'writeUInt16LE' */
+#define DUK_STRIDX_WRITE_INT8                                         135                            /* 'writeInt8' */
+#define DUK_STRIDX_WRITE_UINT8                                        136                            /* 'writeUInt8' */
+#define DUK_STRIDX_READ_INT_BE                                        137                            /* 'readIntBE' */
+#define DUK_STRIDX_READ_INT_LE                                        138                            /* 'readIntLE' */
+#define DUK_STRIDX_READ_UINT_BE                                       139                            /* 'readUIntBE' */
+#define DUK_STRIDX_READ_UINT_LE                                       140                            /* 'readUIntLE' */
+#define DUK_STRIDX_READ_DOUBLE_BE                                     141                            /* 'readDoubleBE' */
+#define DUK_STRIDX_READ_DOUBLE_LE                                     142                            /* 'readDoubleLE' */
+#define DUK_STRIDX_READ_FLOAT_BE                                      143                            /* 'readFloatBE' */
+#define DUK_STRIDX_READ_FLOAT_LE                                      144                            /* 'readFloatLE' */
+#define DUK_STRIDX_READ_INT32_BE                                      145                            /* 'readInt32BE' */
+#define DUK_STRIDX_READ_INT32_LE                                      146                            /* 'readInt32LE' */
+#define DUK_STRIDX_READ_UINT32_BE                                     147                            /* 'readUInt32BE' */
+#define DUK_STRIDX_READ_UINT32_LE                                     148                            /* 'readUInt32LE' */
+#define DUK_STRIDX_READ_INT16_BE                                      149                            /* 'readInt16BE' */
+#define DUK_STRIDX_READ_INT16_LE                                      150                            /* 'readInt16LE' */
+#define DUK_STRIDX_READ_UINT16_BE                                     151                            /* 'readUInt16BE' */
+#define DUK_STRIDX_READ_UINT16_LE                                     152                            /* 'readUInt16LE' */
+#define DUK_STRIDX_READ_INT8                                          153                            /* 'readInt8' */
+#define DUK_STRIDX_READ_UINT8                                         154                            /* 'readUInt8' */
+#define DUK_STRIDX_COPY                                               155                            /* 'copy' */
+#define DUK_STRIDX_EQUALS                                             156                            /* 'equals' */
+#define DUK_STRIDX_FILL                                               157                            /* 'fill' */
+#define DUK_STRIDX_WRITE                                              158                            /* 'write' */
+#define DUK_STRIDX_COMPARE                                            159                            /* 'compare' */
+#define DUK_STRIDX_BYTE_LENGTH                                        160                            /* 'byteLength' */
+#define DUK_STRIDX_IS_BUFFER                                          161                            /* 'isBuffer' */
+#define DUK_STRIDX_IS_ENCODING                                        162                            /* 'isEncoding' */
+#define DUK_STRIDX_EXPORTS                                            163                            /* 'exports' */
+#define DUK_STRIDX_ID                                                 164                            /* 'id' */
+#define DUK_STRIDX_REQUIRE                                            165                            /* 'require' */
+#define DUK_STRIDX___PROTO__                                          166                            /* '__proto__' */
+#define DUK_STRIDX_SET_PROTOTYPE_OF                                   167                            /* 'setPrototypeOf' */
+#define DUK_STRIDX_OWN_KEYS                                           168                            /* 'ownKeys' */
+#define DUK_STRIDX_ENUMERATE                                          169                            /* 'enumerate' */
+#define DUK_STRIDX_DELETE_PROPERTY                                    170                            /* 'deleteProperty' */
+#define DUK_STRIDX_HAS                                                171                            /* 'has' */
+#define DUK_STRIDX_PROXY                                              172                            /* 'Proxy' */
+#define DUK_STRIDX_CALLEE                                             173                            /* 'callee' */
+#define DUK_STRIDX_INVALID_DATE                                       174                            /* 'Invalid Date' */
+#define DUK_STRIDX_BRACKETED_ELLIPSIS                                 175                            /* '[...]' */
+#define DUK_STRIDX_NEWLINE_TAB                                        176                            /* '\n\t' */
+#define DUK_STRIDX_SPACE                                              177                            /* ' ' */
+#define DUK_STRIDX_COMMA                                              178                            /* ',' */
+#define DUK_STRIDX_MINUS_ZERO                                         179                            /* '-0' */
+#define DUK_STRIDX_PLUS_ZERO                                          180                            /* '+0' */
+#define DUK_STRIDX_ZERO                                               181                            /* '0' */
+#define DUK_STRIDX_MINUS_INFINITY                                     182                            /* '-Infinity' */
+#define DUK_STRIDX_PLUS_INFINITY                                      183                            /* '+Infinity' */
+#define DUK_STRIDX_INFINITY                                           184                            /* 'Infinity' */
+#define DUK_STRIDX_LC_OBJECT                                          185                            /* 'object' */
+#define DUK_STRIDX_LC_STRING                                          186                            /* 'string' */
+#define DUK_STRIDX_LC_NUMBER                                          187                            /* 'number' */
+#define DUK_STRIDX_LC_BOOLEAN                                         188                            /* 'boolean' */
+#define DUK_STRIDX_LC_UNDEFINED                                       189                            /* 'undefined' */
+#define DUK_STRIDX_STRINGIFY                                          190                            /* 'stringify' */
+#define DUK_STRIDX_TAN                                                191                            /* 'tan' */
+#define DUK_STRIDX_SQRT                                               192                            /* 'sqrt' */
+#define DUK_STRIDX_SIN                                                193                            /* 'sin' */
+#define DUK_STRIDX_ROUND                                              194                            /* 'round' */
+#define DUK_STRIDX_RANDOM                                             195                            /* 'random' */
+#define DUK_STRIDX_POW                                                196                            /* 'pow' */
+#define DUK_STRIDX_MIN                                                197                            /* 'min' */
+#define DUK_STRIDX_MAX                                                198                            /* 'max' */
+#define DUK_STRIDX_LOG                                                199                            /* 'log' */
+#define DUK_STRIDX_FLOOR                                              200                            /* 'floor' */
+#define DUK_STRIDX_EXP                                                201                            /* 'exp' */
+#define DUK_STRIDX_COS                                                202                            /* 'cos' */
+#define DUK_STRIDX_CEIL                                               203                            /* 'ceil' */
+#define DUK_STRIDX_ATAN2                                              204                            /* 'atan2' */
+#define DUK_STRIDX_ATAN                                               205                            /* 'atan' */
+#define DUK_STRIDX_ASIN                                               206                            /* 'asin' */
+#define DUK_STRIDX_ACOS                                               207                            /* 'acos' */
+#define DUK_STRIDX_ABS                                                208                            /* 'abs' */
+#define DUK_STRIDX_SQRT2                                              209                            /* 'SQRT2' */
+#define DUK_STRIDX_SQRT1_2                                            210                            /* 'SQRT1_2' */
+#define DUK_STRIDX_PI                                                 211                            /* 'PI' */
+#define DUK_STRIDX_LOG10E                                             212                            /* 'LOG10E' */
+#define DUK_STRIDX_LOG2E                                              213                            /* 'LOG2E' */
+#define DUK_STRIDX_LN2                                                214                            /* 'LN2' */
+#define DUK_STRIDX_LN10                                               215                            /* 'LN10' */
+#define DUK_STRIDX_E                                                  216                            /* 'E' */
+#define DUK_STRIDX_MESSAGE                                            217                            /* 'message' */
+#define DUK_STRIDX_NAME                                               218                            /* 'name' */
+#define DUK_STRIDX_INPUT                                              219                            /* 'input' */
+#define DUK_STRIDX_INDEX                                              220                            /* 'index' */
+#define DUK_STRIDX_ESCAPED_EMPTY_REGEXP                               221                            /* '(?:)' */
+#define DUK_STRIDX_LAST_INDEX                                         222                            /* 'lastIndex' */
+#define DUK_STRIDX_MULTILINE                                          223                            /* 'multiline' */
+#define DUK_STRIDX_IGNORE_CASE                                        224                            /* 'ignoreCase' */
+#define DUK_STRIDX_SOURCE                                             225                            /* 'source' */
+#define DUK_STRIDX_TEST                                               226                            /* 'test' */
+#define DUK_STRIDX_EXEC                                               227                            /* 'exec' */
+#define DUK_STRIDX_TO_GMT_STRING                                      228                            /* 'toGMTString' */
+#define DUK_STRIDX_SET_YEAR                                           229                            /* 'setYear' */
+#define DUK_STRIDX_GET_YEAR                                           230                            /* 'getYear' */
+#define DUK_STRIDX_TO_JSON                                            231                            /* 'toJSON' */
+#define DUK_STRIDX_TO_ISO_STRING                                      232                            /* 'toISOString' */
+#define DUK_STRIDX_TO_UTC_STRING                                      233                            /* 'toUTCString' */
+#define DUK_STRIDX_SET_UTC_FULL_YEAR                                  234                            /* 'setUTCFullYear' */
+#define DUK_STRIDX_SET_FULL_YEAR                                      235                            /* 'setFullYear' */
+#define DUK_STRIDX_SET_UTC_MONTH                                      236                            /* 'setUTCMonth' */
+#define DUK_STRIDX_SET_MONTH                                          237                            /* 'setMonth' */
+#define DUK_STRIDX_SET_UTC_DATE                                       238                            /* 'setUTCDate' */
+#define DUK_STRIDX_SET_DATE                                           239                            /* 'setDate' */
+#define DUK_STRIDX_SET_UTC_HOURS                                      240                            /* 'setUTCHours' */
+#define DUK_STRIDX_SET_HOURS                                          241                            /* 'setHours' */
+#define DUK_STRIDX_SET_UTC_MINUTES                                    242                            /* 'setUTCMinutes' */
+#define DUK_STRIDX_SET_MINUTES                                        243                            /* 'setMinutes' */
+#define DUK_STRIDX_SET_UTC_SECONDS                                    244                            /* 'setUTCSeconds' */
+#define DUK_STRIDX_SET_SECONDS                                        245                            /* 'setSeconds' */
+#define DUK_STRIDX_SET_UTC_MILLISECONDS                               246                            /* 'setUTCMilliseconds' */
+#define DUK_STRIDX_SET_MILLISECONDS                                   247                            /* 'setMilliseconds' */
+#define DUK_STRIDX_SET_TIME                                           248                            /* 'setTime' */
+#define DUK_STRIDX_GET_TIMEZONE_OFFSET                                249                            /* 'getTimezoneOffset' */
+#define DUK_STRIDX_GET_UTC_MILLISECONDS                               250                            /* 'getUTCMilliseconds' */
+#define DUK_STRIDX_GET_MILLISECONDS                                   251                            /* 'getMilliseconds' */
+#define DUK_STRIDX_GET_UTC_SECONDS                                    252                            /* 'getUTCSeconds' */
+#define DUK_STRIDX_GET_SECONDS                                        253                            /* 'getSeconds' */
+#define DUK_STRIDX_GET_UTC_MINUTES                                    254                            /* 'getUTCMinutes' */
+#define DUK_STRIDX_GET_MINUTES                                        255                            /* 'getMinutes' */
+#define DUK_STRIDX_GET_UTC_HOURS                                      256                            /* 'getUTCHours' */
+#define DUK_STRIDX_GET_HOURS                                          257                            /* 'getHours' */
+#define DUK_STRIDX_GET_UTC_DAY                                        258                            /* 'getUTCDay' */
+#define DUK_STRIDX_GET_DAY                                            259                            /* 'getDay' */
+#define DUK_STRIDX_GET_UTC_DATE                                       260                            /* 'getUTCDate' */
+#define DUK_STRIDX_GET_DATE                                           261                            /* 'getDate' */
+#define DUK_STRIDX_GET_UTC_MONTH                                      262                            /* 'getUTCMonth' */
+#define DUK_STRIDX_GET_MONTH                                          263                            /* 'getMonth' */
+#define DUK_STRIDX_GET_UTC_FULL_YEAR                                  264                            /* 'getUTCFullYear' */
+#define DUK_STRIDX_GET_FULL_YEAR                                      265                            /* 'getFullYear' */
+#define DUK_STRIDX_GET_TIME                                           266                            /* 'getTime' */
+#define DUK_STRIDX_TO_LOCALE_TIME_STRING                              267                            /* 'toLocaleTimeString' */
+#define DUK_STRIDX_TO_LOCALE_DATE_STRING                              268                            /* 'toLocaleDateString' */
+#define DUK_STRIDX_TO_TIME_STRING                                     269                            /* 'toTimeString' */
+#define DUK_STRIDX_TO_DATE_STRING                                     270                            /* 'toDateString' */
+#define DUK_STRIDX_NOW                                                271                            /* 'now' */
+#define DUK_STRIDX_UTC                                                272                            /* 'UTC' */
+#define DUK_STRIDX_PARSE                                              273                            /* 'parse' */
+#define DUK_STRIDX_TO_PRECISION                                       274                            /* 'toPrecision' */
+#define DUK_STRIDX_TO_EXPONENTIAL                                     275                            /* 'toExponential' */
+#define DUK_STRIDX_TO_FIXED                                           276                            /* 'toFixed' */
+#define DUK_STRIDX_POSITIVE_INFINITY                                  277                            /* 'POSITIVE_INFINITY' */
+#define DUK_STRIDX_NEGATIVE_INFINITY                                  278                            /* 'NEGATIVE_INFINITY' */
+#define DUK_STRIDX_NAN                                                279                            /* 'NaN' */
+#define DUK_STRIDX_MIN_VALUE                                          280                            /* 'MIN_VALUE' */
+#define DUK_STRIDX_MAX_VALUE                                          281                            /* 'MAX_VALUE' */
+#define DUK_STRIDX_SUBSTR                                             282                            /* 'substr' */
+#define DUK_STRIDX_TRIM                                               283                            /* 'trim' */
+#define DUK_STRIDX_TO_LOCALE_UPPER_CASE                               284                            /* 'toLocaleUpperCase' */
+#define DUK_STRIDX_TO_UPPER_CASE                                      285                            /* 'toUpperCase' */
+#define DUK_STRIDX_TO_LOCALE_LOWER_CASE                               286                            /* 'toLocaleLowerCase' */
+#define DUK_STRIDX_TO_LOWER_CASE                                      287                            /* 'toLowerCase' */
+#define DUK_STRIDX_SUBSTRING                                          288                            /* 'substring' */
+#define DUK_STRIDX_SPLIT                                              289                            /* 'split' */
+#define DUK_STRIDX_SEARCH                                             290                            /* 'search' */
+#define DUK_STRIDX_REPLACE                                            291                            /* 'replace' */
+#define DUK_STRIDX_MATCH                                              292                            /* 'match' */
+#define DUK_STRIDX_LOCALE_COMPARE                                     293                            /* 'localeCompare' */
+#define DUK_STRIDX_CHAR_CODE_AT                                       294                            /* 'charCodeAt' */
+#define DUK_STRIDX_CHAR_AT                                            295                            /* 'charAt' */
+#define DUK_STRIDX_FROM_CHAR_CODE                                     296                            /* 'fromCharCode' */
+#define DUK_STRIDX_REDUCE_RIGHT                                       297                            /* 'reduceRight' */
+#define DUK_STRIDX_REDUCE                                             298                            /* 'reduce' */
+#define DUK_STRIDX_FILTER                                             299                            /* 'filter' */
+#define DUK_STRIDX_MAP                                                300                            /* 'map' */
+#define DUK_STRIDX_FOR_EACH                                           301                            /* 'forEach' */
+#define DUK_STRIDX_SOME                                               302                            /* 'some' */
+#define DUK_STRIDX_EVERY                                              303                            /* 'every' */
+#define DUK_STRIDX_LAST_INDEX_OF                                      304                            /* 'lastIndexOf' */
+#define DUK_STRIDX_INDEX_OF                                           305                            /* 'indexOf' */
+#define DUK_STRIDX_UNSHIFT                                            306                            /* 'unshift' */
+#define DUK_STRIDX_SPLICE                                             307                            /* 'splice' */
+#define DUK_STRIDX_SORT                                               308                            /* 'sort' */
+#define DUK_STRIDX_SLICE                                              309                            /* 'slice' */
+#define DUK_STRIDX_SHIFT                                              310                            /* 'shift' */
+#define DUK_STRIDX_REVERSE                                            311                            /* 'reverse' */
+#define DUK_STRIDX_PUSH                                               312                            /* 'push' */
+#define DUK_STRIDX_POP                                                313                            /* 'pop' */
+#define DUK_STRIDX_JOIN                                               314                            /* 'join' */
+#define DUK_STRIDX_CONCAT                                             315                            /* 'concat' */
+#define DUK_STRIDX_IS_ARRAY                                           316                            /* 'isArray' */
+#define DUK_STRIDX_LC_ARGUMENTS                                       317                            /* 'arguments' */
+#define DUK_STRIDX_CALLER                                             318                            /* 'caller' */
+#define DUK_STRIDX_BIND                                               319                            /* 'bind' */
+#define DUK_STRIDX_CALL                                               320                            /* 'call' */
+#define DUK_STRIDX_APPLY                                              321                            /* 'apply' */
+#define DUK_STRIDX_PROPERTY_IS_ENUMERABLE                             322                            /* 'propertyIsEnumerable' */
+#define DUK_STRIDX_IS_PROTOTYPE_OF                                    323                            /* 'isPrototypeOf' */
+#define DUK_STRIDX_HAS_OWN_PROPERTY                                   324                            /* 'hasOwnProperty' */
+#define DUK_STRIDX_VALUE_OF                                           325                            /* 'valueOf' */
+#define DUK_STRIDX_TO_LOCALE_STRING                                   326                            /* 'toLocaleString' */
+#define DUK_STRIDX_TO_STRING                                          327                            /* 'toString' */
+#define DUK_STRIDX_CONSTRUCTOR                                        328                            /* 'constructor' */
+#define DUK_STRIDX_SET                                                329                            /* 'set' */
+#define DUK_STRIDX_GET                                                330                            /* 'get' */
+#define DUK_STRIDX_ENUMERABLE                                         331                            /* 'enumerable' */
+#define DUK_STRIDX_CONFIGURABLE                                       332                            /* 'configurable' */
+#define DUK_STRIDX_WRITABLE                                           333                            /* 'writable' */
+#define DUK_STRIDX_VALUE                                              334                            /* 'value' */
+#define DUK_STRIDX_KEYS                                               335                            /* 'keys' */
+#define DUK_STRIDX_IS_EXTENSIBLE                                      336                            /* 'isExtensible' */
+#define DUK_STRIDX_IS_FROZEN                                          337                            /* 'isFrozen' */
+#define DUK_STRIDX_IS_SEALED                                          338                            /* 'isSealed' */
+#define DUK_STRIDX_PREVENT_EXTENSIONS                                 339                            /* 'preventExtensions' */
+#define DUK_STRIDX_FREEZE                                             340                            /* 'freeze' */
+#define DUK_STRIDX_SEAL                                               341                            /* 'seal' */
+#define DUK_STRIDX_DEFINE_PROPERTIES                                  342                            /* 'defineProperties' */
+#define DUK_STRIDX_DEFINE_PROPERTY                                    343                            /* 'defineProperty' */
+#define DUK_STRIDX_CREATE                                             344                            /* 'create' */
+#define DUK_STRIDX_GET_OWN_PROPERTY_NAMES                             345                            /* 'getOwnPropertyNames' */
+#define DUK_STRIDX_GET_OWN_PROPERTY_DESCRIPTOR                        346                            /* 'getOwnPropertyDescriptor' */
+#define DUK_STRIDX_GET_PROTOTYPE_OF                                   347                            /* 'getPrototypeOf' */
+#define DUK_STRIDX_PROTOTYPE                                          348                            /* 'prototype' */
+#define DUK_STRIDX_LENGTH                                             349                            /* 'length' */
+#define DUK_STRIDX_ALERT                                              350                            /* 'alert' */
+#define DUK_STRIDX_PRINT                                              351                            /* 'print' */
+#define DUK_STRIDX_UNESCAPE                                           352                            /* 'unescape' */
+#define DUK_STRIDX_ESCAPE                                             353                            /* 'escape' */
+#define DUK_STRIDX_ENCODE_URI_COMPONENT                               354                            /* 'encodeURIComponent' */
+#define DUK_STRIDX_ENCODE_URI                                         355                            /* 'encodeURI' */
+#define DUK_STRIDX_DECODE_URI_COMPONENT                               356                            /* 'decodeURIComponent' */
+#define DUK_STRIDX_DECODE_URI                                         357                            /* 'decodeURI' */
+#define DUK_STRIDX_IS_FINITE                                          358                            /* 'isFinite' */
+#define DUK_STRIDX_IS_NAN                                             359                            /* 'isNaN' */
+#define DUK_STRIDX_PARSE_FLOAT                                        360                            /* 'parseFloat' */
+#define DUK_STRIDX_PARSE_INT                                          361                            /* 'parseInt' */
+#define DUK_STRIDX_EVAL                                               362                            /* 'eval' */
+#define DUK_STRIDX_URI_ERROR                                          363                            /* 'URIError' */
+#define DUK_STRIDX_TYPE_ERROR                                         364                            /* 'TypeError' */
+#define DUK_STRIDX_SYNTAX_ERROR                                       365                            /* 'SyntaxError' */
+#define DUK_STRIDX_REFERENCE_ERROR                                    366                            /* 'ReferenceError' */
+#define DUK_STRIDX_RANGE_ERROR                                        367                            /* 'RangeError' */
+#define DUK_STRIDX_EVAL_ERROR                                         368                            /* 'EvalError' */
+#define DUK_STRIDX_BREAK                                              369                            /* 'break' */
+#define DUK_STRIDX_CASE                                               370                            /* 'case' */
+#define DUK_STRIDX_CATCH                                              371                            /* 'catch' */
+#define DUK_STRIDX_CONTINUE                                           372                            /* 'continue' */
+#define DUK_STRIDX_DEBUGGER                                           373                            /* 'debugger' */
+#define DUK_STRIDX_DEFAULT                                            374                            /* 'default' */
+#define DUK_STRIDX_DELETE                                             375                            /* 'delete' */
+#define DUK_STRIDX_DO                                                 376                            /* 'do' */
+#define DUK_STRIDX_ELSE                                               377                            /* 'else' */
+#define DUK_STRIDX_FINALLY                                            378                            /* 'finally' */
+#define DUK_STRIDX_FOR                                                379                            /* 'for' */
+#define DUK_STRIDX_LC_FUNCTION                                        380                            /* 'function' */
+#define DUK_STRIDX_IF                                                 381                            /* 'if' */
+#define DUK_STRIDX_IN                                                 382                            /* 'in' */
+#define DUK_STRIDX_INSTANCEOF                                         383                            /* 'instanceof' */
+#define DUK_STRIDX_NEW                                                384                            /* 'new' */
+#define DUK_STRIDX_RETURN                                             385                            /* 'return' */
+#define DUK_STRIDX_SWITCH                                             386                            /* 'switch' */
+#define DUK_STRIDX_THIS                                               387                            /* 'this' */
+#define DUK_STRIDX_THROW                                              388                            /* 'throw' */
+#define DUK_STRIDX_TRY                                                389                            /* 'try' */
+#define DUK_STRIDX_TYPEOF                                             390                            /* 'typeof' */
+#define DUK_STRIDX_VAR                                                391                            /* 'var' */
+#define DUK_STRIDX_CONST                                              392                            /* 'const' */
+#define DUK_STRIDX_VOID                                               393                            /* 'void' */
+#define DUK_STRIDX_WHILE                                              394                            /* 'while' */
+#define DUK_STRIDX_WITH                                               395                            /* 'with' */
+#define DUK_STRIDX_CLASS                                              396                            /* 'class' */
+#define DUK_STRIDX_ENUM                                               397                            /* 'enum' */
+#define DUK_STRIDX_EXPORT                                             398                            /* 'export' */
+#define DUK_STRIDX_EXTENDS                                            399                            /* 'extends' */
+#define DUK_STRIDX_IMPORT                                             400                            /* 'import' */
+#define DUK_STRIDX_SUPER                                              401                            /* 'super' */
+#define DUK_STRIDX_LC_NULL                                            402                            /* 'null' */
+#define DUK_STRIDX_TRUE                                               403                            /* 'true' */
+#define DUK_STRIDX_FALSE                                              404                            /* 'false' */
+#define DUK_STRIDX_IMPLEMENTS                                         405                            /* 'implements' */
+#define DUK_STRIDX_INTERFACE                                          406                            /* 'interface' */
+#define DUK_STRIDX_LET                                                407                            /* 'let' */
+#define DUK_STRIDX_PACKAGE                                            408                            /* 'package' */
+#define DUK_STRIDX_PRIVATE                                            409                            /* 'private' */
+#define DUK_STRIDX_PROTECTED                                          410                            /* 'protected' */
+#define DUK_STRIDX_PUBLIC                                             411                            /* 'public' */
+#define DUK_STRIDX_STATIC                                             412                            /* 'static' */
+#define DUK_STRIDX_YIELD                                              413                            /* 'yield' */
 
 #define DUK_HEAP_STRING_UC_LOGGER(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_LOGGER)
 #define DUK_HTHREAD_STRING_UC_LOGGER(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_LOGGER)
@@ -2796,12 +3483,34 @@ extern const duk_uint8_t duk_strings_data[];
 #define DUK_HTHREAD_STRING_UC_THREAD(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_THREAD)
 #define DUK_HEAP_STRING_UC_POINTER(heap)                              DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_POINTER)
 #define DUK_HTHREAD_STRING_UC_POINTER(thr)                            DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_POINTER)
-#define DUK_HEAP_STRING_UC_BUFFER(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_BUFFER)
-#define DUK_HTHREAD_STRING_UC_BUFFER(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_BUFFER)
 #define DUK_HEAP_STRING_DEC_ENV(heap)                                 DUK_HEAP_GET_STRING((heap),DUK_STRIDX_DEC_ENV)
 #define DUK_HTHREAD_STRING_DEC_ENV(thr)                               DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_DEC_ENV)
 #define DUK_HEAP_STRING_OBJ_ENV(heap)                                 DUK_HEAP_GET_STRING((heap),DUK_STRIDX_OBJ_ENV)
 #define DUK_HTHREAD_STRING_OBJ_ENV(thr)                               DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_OBJ_ENV)
+#define DUK_HEAP_STRING_FLOAT64_ARRAY(heap)                           DUK_HEAP_GET_STRING((heap),DUK_STRIDX_FLOAT64_ARRAY)
+#define DUK_HTHREAD_STRING_FLOAT64_ARRAY(thr)                         DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_FLOAT64_ARRAY)
+#define DUK_HEAP_STRING_FLOAT32_ARRAY(heap)                           DUK_HEAP_GET_STRING((heap),DUK_STRIDX_FLOAT32_ARRAY)
+#define DUK_HTHREAD_STRING_FLOAT32_ARRAY(thr)                         DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_FLOAT32_ARRAY)
+#define DUK_HEAP_STRING_UINT32_ARRAY(heap)                            DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UINT32_ARRAY)
+#define DUK_HTHREAD_STRING_UINT32_ARRAY(thr)                          DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UINT32_ARRAY)
+#define DUK_HEAP_STRING_INT32_ARRAY(heap)                             DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT32_ARRAY)
+#define DUK_HTHREAD_STRING_INT32_ARRAY(thr)                           DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT32_ARRAY)
+#define DUK_HEAP_STRING_UINT16_ARRAY(heap)                            DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UINT16_ARRAY)
+#define DUK_HTHREAD_STRING_UINT16_ARRAY(thr)                          DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UINT16_ARRAY)
+#define DUK_HEAP_STRING_INT16_ARRAY(heap)                             DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT16_ARRAY)
+#define DUK_HTHREAD_STRING_INT16_ARRAY(thr)                           DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT16_ARRAY)
+#define DUK_HEAP_STRING_UINT8_CLAMPED_ARRAY(heap)                     DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UINT8_CLAMPED_ARRAY)
+#define DUK_HTHREAD_STRING_UINT8_CLAMPED_ARRAY(thr)                   DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UINT8_CLAMPED_ARRAY)
+#define DUK_HEAP_STRING_UINT8_ARRAY(heap)                             DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UINT8_ARRAY)
+#define DUK_HTHREAD_STRING_UINT8_ARRAY(thr)                           DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UINT8_ARRAY)
+#define DUK_HEAP_STRING_INT8_ARRAY(heap)                              DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT8_ARRAY)
+#define DUK_HTHREAD_STRING_INT8_ARRAY(thr)                            DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT8_ARRAY)
+#define DUK_HEAP_STRING_DATA_VIEW(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_DATA_VIEW)
+#define DUK_HTHREAD_STRING_DATA_VIEW(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_DATA_VIEW)
+#define DUK_HEAP_STRING_ARRAY_BUFFER(heap)                            DUK_HEAP_GET_STRING((heap),DUK_STRIDX_ARRAY_BUFFER)
+#define DUK_HTHREAD_STRING_ARRAY_BUFFER(thr)                          DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_ARRAY_BUFFER)
+#define DUK_HEAP_STRING_UC_BUFFER(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_BUFFER)
+#define DUK_HTHREAD_STRING_UC_BUFFER(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_BUFFER)
 #define DUK_HEAP_STRING_EMPTY_STRING(heap)                            DUK_HEAP_GET_STRING((heap),DUK_STRIDX_EMPTY_STRING)
 #define DUK_HTHREAD_STRING_EMPTY_STRING(thr)                          DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_EMPTY_STRING)
 #define DUK_HEAP_STRING_GLOBAL(heap)                                  DUK_HEAP_GET_STRING((heap),DUK_STRIDX_GLOBAL)
@@ -2946,10 +3655,8 @@ extern const duk_uint8_t duk_strings_data[];
 #define DUK_HTHREAD_STRING_INT_VALUE(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_VALUE)
 #define DUK_HEAP_STRING_LC_POINTER(heap)                              DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_POINTER)
 #define DUK_HTHREAD_STRING_LC_POINTER(thr)                            DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_POINTER)
-#define DUK_HEAP_STRING_LC_BUFFER(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_BUFFER)
-#define DUK_HTHREAD_STRING_LC_BUFFER(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_BUFFER)
-#define DUK_HEAP_STRING_TRACEDATA(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_TRACEDATA)
-#define DUK_HTHREAD_STRING_TRACEDATA(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_TRACEDATA)
+#define DUK_HEAP_STRING_INT_TRACEDATA(heap)                           DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_TRACEDATA)
+#define DUK_HTHREAD_STRING_INT_TRACEDATA(thr)                         DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_TRACEDATA)
 #define DUK_HEAP_STRING_LINE_NUMBER(heap)                             DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LINE_NUMBER)
 #define DUK_HTHREAD_STRING_LINE_NUMBER(thr)                           DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LINE_NUMBER)
 #define DUK_HEAP_STRING_FILE_NAME(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_FILE_NAME)
@@ -2962,6 +3669,142 @@ extern const duk_uint8_t duk_strings_data[];
 #define DUK_HTHREAD_STRING_THROW_TYPE_ERROR(thr)                      DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_THROW_TYPE_ERROR)
 #define DUK_HEAP_STRING_DUKTAPE(heap)                                 DUK_HEAP_GET_STRING((heap),DUK_STRIDX_DUKTAPE)
 #define DUK_HTHREAD_STRING_DUKTAPE(thr)                               DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_DUKTAPE)
+#define DUK_HEAP_STRING_SET_FLOAT64(heap)                             DUK_HEAP_GET_STRING((heap),DUK_STRIDX_SET_FLOAT64)
+#define DUK_HTHREAD_STRING_SET_FLOAT64(thr)                           DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_SET_FLOAT64)
+#define DUK_HEAP_STRING_SET_FLOAT32(heap)                             DUK_HEAP_GET_STRING((heap),DUK_STRIDX_SET_FLOAT32)
+#define DUK_HTHREAD_STRING_SET_FLOAT32(thr)                           DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_SET_FLOAT32)
+#define DUK_HEAP_STRING_SET_UINT32(heap)                              DUK_HEAP_GET_STRING((heap),DUK_STRIDX_SET_UINT32)
+#define DUK_HTHREAD_STRING_SET_UINT32(thr)                            DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_SET_UINT32)
+#define DUK_HEAP_STRING_SET_INT32(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_SET_INT32)
+#define DUK_HTHREAD_STRING_SET_INT32(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_SET_INT32)
+#define DUK_HEAP_STRING_SET_UINT16(heap)                              DUK_HEAP_GET_STRING((heap),DUK_STRIDX_SET_UINT16)
+#define DUK_HTHREAD_STRING_SET_UINT16(thr)                            DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_SET_UINT16)
+#define DUK_HEAP_STRING_SET_INT16(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_SET_INT16)
+#define DUK_HTHREAD_STRING_SET_INT16(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_SET_INT16)
+#define DUK_HEAP_STRING_SET_UINT8(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_SET_UINT8)
+#define DUK_HTHREAD_STRING_SET_UINT8(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_SET_UINT8)
+#define DUK_HEAP_STRING_SET_INT8(heap)                                DUK_HEAP_GET_STRING((heap),DUK_STRIDX_SET_INT8)
+#define DUK_HTHREAD_STRING_SET_INT8(thr)                              DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_SET_INT8)
+#define DUK_HEAP_STRING_GET_FLOAT64(heap)                             DUK_HEAP_GET_STRING((heap),DUK_STRIDX_GET_FLOAT64)
+#define DUK_HTHREAD_STRING_GET_FLOAT64(thr)                           DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_GET_FLOAT64)
+#define DUK_HEAP_STRING_GET_FLOAT32(heap)                             DUK_HEAP_GET_STRING((heap),DUK_STRIDX_GET_FLOAT32)
+#define DUK_HTHREAD_STRING_GET_FLOAT32(thr)                           DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_GET_FLOAT32)
+#define DUK_HEAP_STRING_GET_UINT32(heap)                              DUK_HEAP_GET_STRING((heap),DUK_STRIDX_GET_UINT32)
+#define DUK_HTHREAD_STRING_GET_UINT32(thr)                            DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_GET_UINT32)
+#define DUK_HEAP_STRING_GET_INT32(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_GET_INT32)
+#define DUK_HTHREAD_STRING_GET_INT32(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_GET_INT32)
+#define DUK_HEAP_STRING_GET_UINT16(heap)                              DUK_HEAP_GET_STRING((heap),DUK_STRIDX_GET_UINT16)
+#define DUK_HTHREAD_STRING_GET_UINT16(thr)                            DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_GET_UINT16)
+#define DUK_HEAP_STRING_GET_INT16(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_GET_INT16)
+#define DUK_HTHREAD_STRING_GET_INT16(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_GET_INT16)
+#define DUK_HEAP_STRING_GET_UINT8(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_GET_UINT8)
+#define DUK_HTHREAD_STRING_GET_UINT8(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_GET_UINT8)
+#define DUK_HEAP_STRING_GET_INT8(heap)                                DUK_HEAP_GET_STRING((heap),DUK_STRIDX_GET_INT8)
+#define DUK_HTHREAD_STRING_GET_INT8(thr)                              DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_GET_INT8)
+#define DUK_HEAP_STRING_SUBARRAY(heap)                                DUK_HEAP_GET_STRING((heap),DUK_STRIDX_SUBARRAY)
+#define DUK_HTHREAD_STRING_SUBARRAY(thr)                              DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_SUBARRAY)
+#define DUK_HEAP_STRING_BYTES_PER_ELEMENT(heap)                       DUK_HEAP_GET_STRING((heap),DUK_STRIDX_BYTES_PER_ELEMENT)
+#define DUK_HTHREAD_STRING_BYTES_PER_ELEMENT(thr)                     DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_BYTES_PER_ELEMENT)
+#define DUK_HEAP_STRING_BYTE_OFFSET(heap)                             DUK_HEAP_GET_STRING((heap),DUK_STRIDX_BYTE_OFFSET)
+#define DUK_HTHREAD_STRING_BYTE_OFFSET(thr)                           DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_BYTE_OFFSET)
+#define DUK_HEAP_STRING_LC_BUFFER(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_BUFFER)
+#define DUK_HTHREAD_STRING_LC_BUFFER(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_BUFFER)
+#define DUK_HEAP_STRING_IS_VIEW(heap)                                 DUK_HEAP_GET_STRING((heap),DUK_STRIDX_IS_VIEW)
+#define DUK_HTHREAD_STRING_IS_VIEW(thr)                               DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_IS_VIEW)
+#define DUK_HEAP_STRING_DATA(heap)                                    DUK_HEAP_GET_STRING((heap),DUK_STRIDX_DATA)
+#define DUK_HTHREAD_STRING_DATA(thr)                                  DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_DATA)
+#define DUK_HEAP_STRING_TYPE(heap)                                    DUK_HEAP_GET_STRING((heap),DUK_STRIDX_TYPE)
+#define DUK_HTHREAD_STRING_TYPE(thr)                                  DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_TYPE)
+#define DUK_HEAP_STRING_WRITE_INT_BE(heap)                            DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WRITE_INT_BE)
+#define DUK_HTHREAD_STRING_WRITE_INT_BE(thr)                          DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WRITE_INT_BE)
+#define DUK_HEAP_STRING_WRITE_INT_LE(heap)                            DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WRITE_INT_LE)
+#define DUK_HTHREAD_STRING_WRITE_INT_LE(thr)                          DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WRITE_INT_LE)
+#define DUK_HEAP_STRING_WRITE_UINT_BE(heap)                           DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WRITE_UINT_BE)
+#define DUK_HTHREAD_STRING_WRITE_UINT_BE(thr)                         DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WRITE_UINT_BE)
+#define DUK_HEAP_STRING_WRITE_UINT_LE(heap)                           DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WRITE_UINT_LE)
+#define DUK_HTHREAD_STRING_WRITE_UINT_LE(thr)                         DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WRITE_UINT_LE)
+#define DUK_HEAP_STRING_WRITE_DOUBLE_BE(heap)                         DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WRITE_DOUBLE_BE)
+#define DUK_HTHREAD_STRING_WRITE_DOUBLE_BE(thr)                       DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WRITE_DOUBLE_BE)
+#define DUK_HEAP_STRING_WRITE_DOUBLE_LE(heap)                         DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WRITE_DOUBLE_LE)
+#define DUK_HTHREAD_STRING_WRITE_DOUBLE_LE(thr)                       DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WRITE_DOUBLE_LE)
+#define DUK_HEAP_STRING_WRITE_FLOAT_BE(heap)                          DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WRITE_FLOAT_BE)
+#define DUK_HTHREAD_STRING_WRITE_FLOAT_BE(thr)                        DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WRITE_FLOAT_BE)
+#define DUK_HEAP_STRING_WRITE_FLOAT_LE(heap)                          DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WRITE_FLOAT_LE)
+#define DUK_HTHREAD_STRING_WRITE_FLOAT_LE(thr)                        DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WRITE_FLOAT_LE)
+#define DUK_HEAP_STRING_WRITE_INT32_BE(heap)                          DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WRITE_INT32_BE)
+#define DUK_HTHREAD_STRING_WRITE_INT32_BE(thr)                        DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WRITE_INT32_BE)
+#define DUK_HEAP_STRING_WRITE_INT32_LE(heap)                          DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WRITE_INT32_LE)
+#define DUK_HTHREAD_STRING_WRITE_INT32_LE(thr)                        DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WRITE_INT32_LE)
+#define DUK_HEAP_STRING_WRITE_UINT32_BE(heap)                         DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WRITE_UINT32_BE)
+#define DUK_HTHREAD_STRING_WRITE_UINT32_BE(thr)                       DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WRITE_UINT32_BE)
+#define DUK_HEAP_STRING_WRITE_UINT32_LE(heap)                         DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WRITE_UINT32_LE)
+#define DUK_HTHREAD_STRING_WRITE_UINT32_LE(thr)                       DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WRITE_UINT32_LE)
+#define DUK_HEAP_STRING_WRITE_INT16_BE(heap)                          DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WRITE_INT16_BE)
+#define DUK_HTHREAD_STRING_WRITE_INT16_BE(thr)                        DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WRITE_INT16_BE)
+#define DUK_HEAP_STRING_WRITE_INT16_LE(heap)                          DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WRITE_INT16_LE)
+#define DUK_HTHREAD_STRING_WRITE_INT16_LE(thr)                        DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WRITE_INT16_LE)
+#define DUK_HEAP_STRING_WRITE_UINT16_BE(heap)                         DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WRITE_UINT16_BE)
+#define DUK_HTHREAD_STRING_WRITE_UINT16_BE(thr)                       DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WRITE_UINT16_BE)
+#define DUK_HEAP_STRING_WRITE_UINT16_LE(heap)                         DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WRITE_UINT16_LE)
+#define DUK_HTHREAD_STRING_WRITE_UINT16_LE(thr)                       DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WRITE_UINT16_LE)
+#define DUK_HEAP_STRING_WRITE_INT8(heap)                              DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WRITE_INT8)
+#define DUK_HTHREAD_STRING_WRITE_INT8(thr)                            DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WRITE_INT8)
+#define DUK_HEAP_STRING_WRITE_UINT8(heap)                             DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WRITE_UINT8)
+#define DUK_HTHREAD_STRING_WRITE_UINT8(thr)                           DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WRITE_UINT8)
+#define DUK_HEAP_STRING_READ_INT_BE(heap)                             DUK_HEAP_GET_STRING((heap),DUK_STRIDX_READ_INT_BE)
+#define DUK_HTHREAD_STRING_READ_INT_BE(thr)                           DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_READ_INT_BE)
+#define DUK_HEAP_STRING_READ_INT_LE(heap)                             DUK_HEAP_GET_STRING((heap),DUK_STRIDX_READ_INT_LE)
+#define DUK_HTHREAD_STRING_READ_INT_LE(thr)                           DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_READ_INT_LE)
+#define DUK_HEAP_STRING_READ_UINT_BE(heap)                            DUK_HEAP_GET_STRING((heap),DUK_STRIDX_READ_UINT_BE)
+#define DUK_HTHREAD_STRING_READ_UINT_BE(thr)                          DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_READ_UINT_BE)
+#define DUK_HEAP_STRING_READ_UINT_LE(heap)                            DUK_HEAP_GET_STRING((heap),DUK_STRIDX_READ_UINT_LE)
+#define DUK_HTHREAD_STRING_READ_UINT_LE(thr)                          DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_READ_UINT_LE)
+#define DUK_HEAP_STRING_READ_DOUBLE_BE(heap)                          DUK_HEAP_GET_STRING((heap),DUK_STRIDX_READ_DOUBLE_BE)
+#define DUK_HTHREAD_STRING_READ_DOUBLE_BE(thr)                        DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_READ_DOUBLE_BE)
+#define DUK_HEAP_STRING_READ_DOUBLE_LE(heap)                          DUK_HEAP_GET_STRING((heap),DUK_STRIDX_READ_DOUBLE_LE)
+#define DUK_HTHREAD_STRING_READ_DOUBLE_LE(thr)                        DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_READ_DOUBLE_LE)
+#define DUK_HEAP_STRING_READ_FLOAT_BE(heap)                           DUK_HEAP_GET_STRING((heap),DUK_STRIDX_READ_FLOAT_BE)
+#define DUK_HTHREAD_STRING_READ_FLOAT_BE(thr)                         DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_READ_FLOAT_BE)
+#define DUK_HEAP_STRING_READ_FLOAT_LE(heap)                           DUK_HEAP_GET_STRING((heap),DUK_STRIDX_READ_FLOAT_LE)
+#define DUK_HTHREAD_STRING_READ_FLOAT_LE(thr)                         DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_READ_FLOAT_LE)
+#define DUK_HEAP_STRING_READ_INT32_BE(heap)                           DUK_HEAP_GET_STRING((heap),DUK_STRIDX_READ_INT32_BE)
+#define DUK_HTHREAD_STRING_READ_INT32_BE(thr)                         DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_READ_INT32_BE)
+#define DUK_HEAP_STRING_READ_INT32_LE(heap)                           DUK_HEAP_GET_STRING((heap),DUK_STRIDX_READ_INT32_LE)
+#define DUK_HTHREAD_STRING_READ_INT32_LE(thr)                         DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_READ_INT32_LE)
+#define DUK_HEAP_STRING_READ_UINT32_BE(heap)                          DUK_HEAP_GET_STRING((heap),DUK_STRIDX_READ_UINT32_BE)
+#define DUK_HTHREAD_STRING_READ_UINT32_BE(thr)                        DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_READ_UINT32_BE)
+#define DUK_HEAP_STRING_READ_UINT32_LE(heap)                          DUK_HEAP_GET_STRING((heap),DUK_STRIDX_READ_UINT32_LE)
+#define DUK_HTHREAD_STRING_READ_UINT32_LE(thr)                        DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_READ_UINT32_LE)
+#define DUK_HEAP_STRING_READ_INT16_BE(heap)                           DUK_HEAP_GET_STRING((heap),DUK_STRIDX_READ_INT16_BE)
+#define DUK_HTHREAD_STRING_READ_INT16_BE(thr)                         DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_READ_INT16_BE)
+#define DUK_HEAP_STRING_READ_INT16_LE(heap)                           DUK_HEAP_GET_STRING((heap),DUK_STRIDX_READ_INT16_LE)
+#define DUK_HTHREAD_STRING_READ_INT16_LE(thr)                         DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_READ_INT16_LE)
+#define DUK_HEAP_STRING_READ_UINT16_BE(heap)                          DUK_HEAP_GET_STRING((heap),DUK_STRIDX_READ_UINT16_BE)
+#define DUK_HTHREAD_STRING_READ_UINT16_BE(thr)                        DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_READ_UINT16_BE)
+#define DUK_HEAP_STRING_READ_UINT16_LE(heap)                          DUK_HEAP_GET_STRING((heap),DUK_STRIDX_READ_UINT16_LE)
+#define DUK_HTHREAD_STRING_READ_UINT16_LE(thr)                        DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_READ_UINT16_LE)
+#define DUK_HEAP_STRING_READ_INT8(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_READ_INT8)
+#define DUK_HTHREAD_STRING_READ_INT8(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_READ_INT8)
+#define DUK_HEAP_STRING_READ_UINT8(heap)                              DUK_HEAP_GET_STRING((heap),DUK_STRIDX_READ_UINT8)
+#define DUK_HTHREAD_STRING_READ_UINT8(thr)                            DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_READ_UINT8)
+#define DUK_HEAP_STRING_COPY(heap)                                    DUK_HEAP_GET_STRING((heap),DUK_STRIDX_COPY)
+#define DUK_HTHREAD_STRING_COPY(thr)                                  DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_COPY)
+#define DUK_HEAP_STRING_EQUALS(heap)                                  DUK_HEAP_GET_STRING((heap),DUK_STRIDX_EQUALS)
+#define DUK_HTHREAD_STRING_EQUALS(thr)                                DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_EQUALS)
+#define DUK_HEAP_STRING_FILL(heap)                                    DUK_HEAP_GET_STRING((heap),DUK_STRIDX_FILL)
+#define DUK_HTHREAD_STRING_FILL(thr)                                  DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_FILL)
+#define DUK_HEAP_STRING_WRITE(heap)                                   DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WRITE)
+#define DUK_HTHREAD_STRING_WRITE(thr)                                 DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WRITE)
+#define DUK_HEAP_STRING_COMPARE(heap)                                 DUK_HEAP_GET_STRING((heap),DUK_STRIDX_COMPARE)
+#define DUK_HTHREAD_STRING_COMPARE(thr)                               DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_COMPARE)
+#define DUK_HEAP_STRING_BYTE_LENGTH(heap)                             DUK_HEAP_GET_STRING((heap),DUK_STRIDX_BYTE_LENGTH)
+#define DUK_HTHREAD_STRING_BYTE_LENGTH(thr)                           DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_BYTE_LENGTH)
+#define DUK_HEAP_STRING_IS_BUFFER(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_IS_BUFFER)
+#define DUK_HTHREAD_STRING_IS_BUFFER(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_IS_BUFFER)
+#define DUK_HEAP_STRING_IS_ENCODING(heap)                             DUK_HEAP_GET_STRING((heap),DUK_STRIDX_IS_ENCODING)
+#define DUK_HTHREAD_STRING_IS_ENCODING(thr)                           DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_IS_ENCODING)
+#define DUK_HEAP_STRING_EXPORTS(heap)                                 DUK_HEAP_GET_STRING((heap),DUK_STRIDX_EXPORTS)
+#define DUK_HTHREAD_STRING_EXPORTS(thr)                               DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_EXPORTS)
 #define DUK_HEAP_STRING_ID(heap)                                      DUK_HEAP_GET_STRING((heap),DUK_STRIDX_ID)
 #define DUK_HTHREAD_STRING_ID(thr)                                    DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_ID)
 #define DUK_HEAP_STRING_REQUIRE(heap)                                 DUK_HEAP_GET_STRING((heap),DUK_STRIDX_REQUIRE)
@@ -3418,6 +4261,8 @@ extern const duk_uint8_t duk_strings_data[];
 #define DUK_HTHREAD_STRING_TYPEOF(thr)                                DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_TYPEOF)
 #define DUK_HEAP_STRING_VAR(heap)                                     DUK_HEAP_GET_STRING((heap),DUK_STRIDX_VAR)
 #define DUK_HTHREAD_STRING_VAR(thr)                                   DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_VAR)
+#define DUK_HEAP_STRING_CONST(heap)                                   DUK_HEAP_GET_STRING((heap),DUK_STRIDX_CONST)
+#define DUK_HTHREAD_STRING_CONST(thr)                                 DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_CONST)
 #define DUK_HEAP_STRING_VOID(heap)                                    DUK_HEAP_GET_STRING((heap),DUK_STRIDX_VOID)
 #define DUK_HTHREAD_STRING_VOID(thr)                                  DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_VOID)
 #define DUK_HEAP_STRING_WHILE(heap)                                   DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WHILE)
@@ -3426,8 +4271,6 @@ extern const duk_uint8_t duk_strings_data[];
 #define DUK_HTHREAD_STRING_WITH(thr)                                  DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WITH)
 #define DUK_HEAP_STRING_CLASS(heap)                                   DUK_HEAP_GET_STRING((heap),DUK_STRIDX_CLASS)
 #define DUK_HTHREAD_STRING_CLASS(thr)                                 DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_CLASS)
-#define DUK_HEAP_STRING_CONST(heap)                                   DUK_HEAP_GET_STRING((heap),DUK_STRIDX_CONST)
-#define DUK_HTHREAD_STRING_CONST(thr)                                 DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_CONST)
 #define DUK_HEAP_STRING_ENUM(heap)                                    DUK_HEAP_GET_STRING((heap),DUK_STRIDX_ENUM)
 #define DUK_HTHREAD_STRING_ENUM(thr)                                  DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_ENUM)
 #define DUK_HEAP_STRING_EXPORT(heap)                                  DUK_HEAP_GET_STRING((heap),DUK_STRIDX_EXPORT)
@@ -3463,19 +4306,21 @@ extern const duk_uint8_t duk_strings_data[];
 #define DUK_HEAP_STRING_YIELD(heap)                                   DUK_HEAP_GET_STRING((heap),DUK_STRIDX_YIELD)
 #define DUK_HTHREAD_STRING_YIELD(thr)                                 DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_YIELD)
 
-#define DUK_HEAP_NUM_STRINGS                                          336
+#define DUK_HEAP_NUM_STRINGS                                          414
 
-#define DUK_STRIDX_START_RESERVED                                     291
-#define DUK_STRIDX_START_STRICT_RESERVED                              327
-#define DUK_STRIDX_END_RESERVED                                       336                            /* exclusive endpoint */
+#define DUK_STRIDX_START_RESERVED                                     369
+#define DUK_STRIDX_START_STRICT_RESERVED                              405
+#define DUK_STRIDX_END_RESERVED                                       414                            /* exclusive endpoint */
 
-extern const duk_c_function duk_bi_native_functions[];
-extern const duk_uint8_t duk_builtins_data[];
+#if !defined(DUK_SINGLE_FILE)
+DUK_INTERNAL_DECL const duk_c_function duk_bi_native_functions[149];
+DUK_INTERNAL_DECL const duk_uint8_t duk_builtins_data[1955];
 #ifdef DUK_USE_BUILTIN_INITJS
-extern const duk_uint8_t duk_initjs_data[];
+DUK_INTERNAL_DECL const duk_uint8_t duk_initjs_data[187];
 #endif  /* DUK_USE_BUILTIN_INITJS */
+#endif  /* !DUK_SINGLE_FILE */
 
-#define DUK_BUILTINS_DATA_LENGTH                                      1336
+#define DUK_BUILTINS_DATA_LENGTH                                      1955
 #ifdef DUK_USE_BUILTIN_INITJS
 #define DUK_BUILTIN_INITJS_DATA_LENGTH                                187
 #endif  /* DUK_USE_BUILTIN_INITJS */
@@ -3526,18 +4371,574 @@ extern const duk_uint8_t duk_initjs_data[];
 #define DUK_BIDX_LOGGER_CONSTRUCTOR                                   43
 #define DUK_BIDX_LOGGER_PROTOTYPE                                     44
 #define DUK_BIDX_DOUBLE_ERROR                                         45
-
-#define DUK_NUM_BUILTINS                                              46
+#define DUK_BIDX_ARRAYBUFFER_CONSTRUCTOR                              46
+#define DUK_BIDX_ARRAYBUFFER_PROTOTYPE                                47
+#define DUK_BIDX_DATAVIEW_CONSTRUCTOR                                 48
+#define DUK_BIDX_DATAVIEW_PROTOTYPE                                   49
+#define DUK_BIDX_TYPEDARRAY_PROTOTYPE                                 50
+#define DUK_BIDX_INT8ARRAY_CONSTRUCTOR                                51
+#define DUK_BIDX_INT8ARRAY_PROTOTYPE                                  52
+#define DUK_BIDX_UINT8ARRAY_CONSTRUCTOR                               53
+#define DUK_BIDX_UINT8ARRAY_PROTOTYPE                                 54
+#define DUK_BIDX_UINT8CLAMPEDARRAY_CONSTRUCTOR                        55
+#define DUK_BIDX_UINT8CLAMPEDARRAY_PROTOTYPE                          56
+#define DUK_BIDX_INT16ARRAY_CONSTRUCTOR                               57
+#define DUK_BIDX_INT16ARRAY_PROTOTYPE                                 58
+#define DUK_BIDX_UINT16ARRAY_CONSTRUCTOR                              59
+#define DUK_BIDX_UINT16ARRAY_PROTOTYPE                                60
+#define DUK_BIDX_INT32ARRAY_CONSTRUCTOR                               61
+#define DUK_BIDX_INT32ARRAY_PROTOTYPE                                 62
+#define DUK_BIDX_UINT32ARRAY_CONSTRUCTOR                              63
+#define DUK_BIDX_UINT32ARRAY_PROTOTYPE                                64
+#define DUK_BIDX_FLOAT32ARRAY_CONSTRUCTOR                             65
+#define DUK_BIDX_FLOAT32ARRAY_PROTOTYPE                               66
+#define DUK_BIDX_FLOAT64ARRAY_CONSTRUCTOR                             67
+#define DUK_BIDX_FLOAT64ARRAY_PROTOTYPE                               68
+#define DUK_BIDX_NODEJS_BUFFER_CONSTRUCTOR                            69
+#define DUK_BIDX_NODEJS_BUFFER_PROTOTYPE                              70
+
+#define DUK_NUM_BUILTINS                                              71
 
 #else
 #error invalid endianness defines
 #endif
 #endif  /* DUK_BUILTINS_H_INCLUDED */
-#line 50 "duk_internal.h"
+#line 51 "duk_internal.h"
+
+#line 1 "duk_util.h"
+/*
+ *  Utilities
+ */
+
+#ifndef DUK_UTIL_H_INCLUDED
+#define DUK_UTIL_H_INCLUDED
+
+#define DUK_UTIL_MIN_HASH_PRIME  17  /* must match genhashsizes.py */
+
+#define DUK_UTIL_GET_HASH_PROBE_STEP(hash)  (duk_util_probe_steps[(hash) & 0x1f])
 
+/*
+ *  Endian conversion
+ */
+
+#if defined(DUK_USE_INTEGER_LE)
+#define DUK_HTON32(x) DUK_BSWAP32((x))
+#define DUK_NTOH32(x) DUK_BSWAP32((x))
+#define DUK_HTON16(x) DUK_BSWAP16((x))
+#define DUK_NTOH16(x) DUK_BSWAP16((x))
+#elif defined(DUK_USE_INTEGER_BE)
+#define DUK_HTON32(x) (x)
+#define DUK_NTOH32(x) (x)
+#define DUK_HTON16(x) (x)
+#define DUK_NTOH16(x) (x)
+#else
+#error internal error, endianness defines broken
+#endif
+
+/*
+ *  Bitstream decoder
+ */
+
+struct duk_bitdecoder_ctx {
+	const duk_uint8_t *data;
+	duk_size_t offset;
+	duk_size_t length;
+	duk_uint32_t currval;
+	duk_small_int_t currbits;
+};
+
+/*
+ *  Bitstream encoder
+ */
+
+struct duk_bitencoder_ctx {
+	duk_uint8_t *data;
+	duk_size_t offset;
+	duk_size_t length;
+	duk_uint32_t currval;
+	duk_small_int_t currbits;
+	duk_small_int_t truncated;
+};
+
+/*
+ *  Raw write/read macros for big endian, unaligned basic values.
+ *  Caller ensures there's enough space.  The macros update the pointer
+ *  argument automatically on resizes.  The idiom seems a bit odd, but
+ *  leads to compact code.
+ */
+
+#define DUK_RAW_WRITE_U8(ptr,val)  do { \
+		*(ptr)++ = (duk_uint8_t) (val); \
+	} while (0)
+#define DUK_RAW_WRITE_U16_BE(ptr,val) duk_raw_write_u16_be(&(ptr), (duk_uint16_t) (val))
+#define DUK_RAW_WRITE_U32_BE(ptr,val) duk_raw_write_u32_be(&(ptr), (duk_uint32_t) (val))
+#define DUK_RAW_WRITE_DOUBLE_BE(ptr,val) duk_raw_write_double_be(&(ptr), (duk_double_t) (val))
+#define DUK_RAW_WRITE_XUTF8(ptr,val)  do { \
+		/* 'ptr' is evaluated both as LHS and RHS. */ \
+		duk_uint8_t *duk__ptr; \
+		duk_small_int_t duk__len; \
+		duk__ptr = (duk_uint8_t *) (ptr); \
+		duk__len = duk_unicode_encode_xutf8((duk_ucodepoint_t) (val), duk__ptr); \
+		duk__ptr += duk__len; \
+		(ptr) = duk__ptr; \
+	} while (0)
+#define DUK_RAW_WRITE_CESU8(ptr,val)  do { \
+		/* 'ptr' is evaluated both as LHS and RHS. */ \
+		duk_uint8_t *duk__ptr; \
+		duk_small_int_t duk__len; \
+		duk__ptr = (duk_uint8_t *) (ptr); \
+		duk__len = duk_unicode_encode_cesu8((duk_ucodepoint_t) (val), duk__ptr); \
+		duk__ptr += duk__len; \
+		(ptr) = duk__ptr; \
+	} while (0)
+
+#define DUK_RAW_READ_U8(ptr) ((duk_uint8_t) (*(ptr)++))
+#define DUK_RAW_READ_U16_BE(ptr) duk_raw_read_u16_be(&(ptr));
+#define DUK_RAW_READ_U32_BE(ptr) duk_raw_read_u32_be(&(ptr));
+#define DUK_RAW_READ_DOUBLE_BE(ptr) duk_raw_read_double_be(&(ptr));
+
+/*
+ *  Buffer writer (dynamic buffer only)
+ *
+ *  Helper for writing to a dynamic buffer with a concept of a "spare" area
+ *  to reduce resizes.  You can ensure there is enough space beforehand and
+ *  then write for a while without further checks, relying on a stable data
+ *  pointer.  Spare handling is automatic so call sites only indicate how
+ *  much data they need right now.
+ *
+ *  There are several ways to write using bufwriter.  The best approach
+ *  depends mainly on how much performance matters over code footprint.
+ *  The key issues are (1) ensuring there is space and (2) keeping the
+ *  pointers consistent.  Fast code should ensure space for multiple writes
+ *  with one ensure call.  Fastest inner loop code can temporarily borrow
+ *  the 'p' pointer but must write it back eventually.
+ *
+ *  Be careful to ensure all macro arguments (other than static pointers like
+ *  'thr' and 'bw_ctx') are evaluated exactly once, using temporaries if
+ *  necessary (if that's not possible, there should be a note near the macro).
+ *  Buffer write arguments often contain arithmetic etc so this is
+ *  particularly important here.
+ */
+
+/* XXX: Migrate bufwriter and other read/write helpers to its own header? */
+
+struct duk_bufwriter_ctx {
+	duk_uint8_t *p;
+	duk_uint8_t *p_base;
+	duk_uint8_t *p_limit;
+	duk_hbuffer_dynamic *buf;
+};
+
+#define DUK_BW_SPARE_ADD           64
+#define DUK_BW_SPARE_SHIFT         4    /* 2^4 -> 1/16 = 6.25% spare */
+
+/* Initialization and finalization (compaction), converting to other types. */
+
+#define DUK_BW_INIT_PUSHBUF(thr,bw_ctx,sz) do { \
+		duk_bw_init_pushbuf((thr), (bw_ctx), (sz)); \
+	} while (0)
+#define DUK_BW_INIT_WITHBUF(thr,bw_ctx,buf) do { \
+		duk_bw_init((thr), (bw_ctx), (buf)); \
+	} while (0)
+#define DUK_BW_COMPACT(thr,bw_ctx) do { \
+		/* Make underlying buffer compact to match DUK_BW_GET_SIZE(). */ \
+		duk_bw_compact((thr), (bw_ctx)); \
+	} while (0)
+#define DUK_BW_PUSH_AS_STRING(thr,bw_ctx) do { \
+		duk_push_lstring((duk_context *) (thr), \
+		                 (const char *) (bw_ctx)->p_base, \
+		                 (duk_size_t) ((bw_ctx)->p - (bw_ctx)->p_base)); \
+	} while (0)
+/* Pointers may be NULL for a while when 'buf' size is zero and before any
+ * ENSURE calls have been made.  Once an ENSURE has been made, the pointers
+ * are required to be non-NULL so that it's always valid to use memcpy() and
+ * memmove(), even for zero size.
+ */
+#define DUK_BW_ASSERT_VALID_EXPR(thr,bw_ctx) \
+	DUK_ASSERT_EXPR((bw_ctx) != NULL && \
+	                (bw_ctx)->buf != NULL && \
+			((DUK_HBUFFER_DYNAMIC_GET_SIZE((bw_ctx)->buf) == 0) || \
+				((bw_ctx)->p != NULL && \
+		                 (bw_ctx)->p_base != NULL && \
+		                 (bw_ctx)->p_limit != NULL && \
+		                 (bw_ctx)->p_limit >= (bw_ctx)->p_base && \
+		                 (bw_ctx)->p >= (bw_ctx)->p_base && \
+		                 (bw_ctx)->p <= (bw_ctx)->p_limit)))
+#define DUK_BW_ASSERT_VALID(thr,bw_ctx) do { \
+		DUK_BW_ASSERT_VALID_EXPR((thr), (bw_ctx)); \
+	} while (0)
+
+/* Working with the pointer and current size. */
+
+#define DUK_BW_GET_PTR(thr,bw_ctx) \
+	((bw_ctx)->p)
+#define DUK_BW_SET_PTR(thr,bw_ctx,ptr) do { \
+		(bw_ctx)->p = (ptr); \
+	} while (0)
+#define DUK_BW_ADD_PTR(thr,bw_ctx,delta) do { \
+		(bw_ctx)->p += (delta); \
+	} while (0)
+#define DUK_BW_GET_BASEPTR(thr,bw_ctx) \
+	((bw_ctx)->p_base)
+#define DUK_BW_GET_LIMITPTR(thr,bw_ctx) \
+	((bw_ctx)->p_limit)
+#define DUK_BW_GET_SIZE(thr,bw_ctx) \
+	((duk_size_t) ((bw_ctx)->p - (bw_ctx)->p_base))
+#define DUK_BW_SET_SIZE(thr,bw_ctx,sz) do { \
+		DUK_ASSERT((duk_size_t) (sz) <= (duk_size_t) ((bw_ctx)->p - (bw_ctx)->p_base)); \
+		(bw_ctx)->p = (bw_ctx)->p_base + (sz); \
+	} while (0)
+#define DUK_BW_RESET_SIZE(thr,bw_ctx) do { \
+		/* Reset to zero size, keep current limit. */ \
+		(bw_ctx)->p = (bw_ctx)->p_base; \
+	} while (0)
+#define DUK_BW_GET_BUFFER(thr,bw_ctx) \
+	((bw_ctx)->buf)
+
+/* Ensuring (reserving) space. */
+
+#define DUK_BW_ENSURE(thr,bw_ctx,sz) do { \
+		duk_size_t duk__sz, duk__space; \
+		DUK_BW_ASSERT_VALID((thr), (bw_ctx)); \
+		duk__sz = (sz); \
+		duk__space = (duk_size_t) ((bw_ctx)->p_limit - (bw_ctx)->p); \
+		if (duk__space < duk__sz) { \
+			(void) duk_bw_resize((thr), (bw_ctx), duk__sz); \
+		} \
+	} while (0)
+/* NOTE: Multiple evaluation of 'ptr' in this macro. */
+/* XXX: Rework to use an always-inline function? */
+#define DUK_BW_ENSURE_RAW(thr,bw_ctx,sz,ptr) \
+	(((duk_size_t) ((bw_ctx)->p_limit - (ptr)) >= (sz)) ? \
+	 (ptr) : \
+	 ((bw_ctx)->p = (ptr), duk_bw_resize((thr),(bw_ctx),(sz))))
+#define DUK_BW_ENSURE_GETPTR(thr,bw_ctx,sz) \
+	DUK_BW_ENSURE_RAW((thr), (bw_ctx), (sz), (bw_ctx)->p)
+#define DUK_BW_ASSERT_SPACE_EXPR(thr,bw_ctx,sz) \
+	(DUK_BW_ASSERT_VALID_EXPR((thr), (bw_ctx)), \
+	 DUK_ASSERT_EXPR((duk_size_t) ((bw_ctx)->p_limit - (bw_ctx)->p) >= (duk_size_t) (sz)))
+#define DUK_BW_ASSERT_SPACE(thr,bw_ctx,sz) do { \
+		DUK_BW_ASSERT_SPACE_EXPR((thr), (bw_ctx), (sz)); \
+	} while (0)
+
+/* Miscellaneous. */
+
+#define DUK_BW_SETPTR_AND_COMPACT(thr,bw_ctx,ptr) do { \
+		(bw_ctx)->p = (ptr); \
+		duk_bw_compact((thr), (bw_ctx)); \
+	} while (0)
+
+/* Fast write calls which assume you control the spare beforehand.
+ * Multibyte write variants exist and use a temporary write pointer
+ * because byte writes alias with anything: with a stored pointer
+ * explicit pointer load/stores get generated (e.g. gcc -Os).
+ */
+
+#define DUK_BW_WRITE_RAW_U8(thr,bw_ctx,val) do { \
+		DUK_BW_ASSERT_SPACE((thr), (bw_ctx), 1); \
+		*(bw_ctx)->p++ = (duk_uint8_t) (val); \
+	} while (0)
+#define DUK_BW_WRITE_RAW_U8_2(thr,bw_ctx,val1,val2) do { \
+		duk_uint8_t *duk__p; \
+		DUK_BW_ASSERT_SPACE((thr), (bw_ctx), 2); \
+		duk__p = (bw_ctx)->p; \
+		*duk__p++ = (duk_uint8_t) (val1); \
+		*duk__p++ = (duk_uint8_t) (val2); \
+		(bw_ctx)->p = duk__p; \
+	} while (0)
+#define DUK_BW_WRITE_RAW_U8_3(thr,bw_ctx,val1,val2,val3) do { \
+		duk_uint8_t *duk__p; \
+		DUK_BW_ASSERT_SPACE((thr), (bw_ctx), 3); \
+		duk__p = (bw_ctx)->p; \
+		*duk__p++ = (duk_uint8_t) (val1); \
+		*duk__p++ = (duk_uint8_t) (val2); \
+		*duk__p++ = (duk_uint8_t) (val3); \
+		(bw_ctx)->p = duk__p; \
+	} while (0)
+#define DUK_BW_WRITE_RAW_U8_4(thr,bw_ctx,val1,val2,val3,val4) do { \
+		duk_uint8_t *duk__p; \
+		DUK_BW_ASSERT_SPACE((thr), (bw_ctx), 4); \
+		duk__p = (bw_ctx)->p; \
+		*duk__p++ = (duk_uint8_t) (val1); \
+		*duk__p++ = (duk_uint8_t) (val2); \
+		*duk__p++ = (duk_uint8_t) (val3); \
+		*duk__p++ = (duk_uint8_t) (val4); \
+		(bw_ctx)->p = duk__p; \
+	} while (0)
+#define DUK_BW_WRITE_RAW_U8_5(thr,bw_ctx,val1,val2,val3,val4,val5) do { \
+		duk_uint8_t *duk__p; \
+		DUK_BW_ASSERT_SPACE((thr), (bw_ctx), 5); \
+		duk__p = (bw_ctx)->p; \
+		*duk__p++ = (duk_uint8_t) (val1); \
+		*duk__p++ = (duk_uint8_t) (val2); \
+		*duk__p++ = (duk_uint8_t) (val3); \
+		*duk__p++ = (duk_uint8_t) (val4); \
+		*duk__p++ = (duk_uint8_t) (val5); \
+		(bw_ctx)->p = duk__p; \
+	} while (0)
+#define DUK_BW_WRITE_RAW_U8_6(thr,bw_ctx,val1,val2,val3,val4,val5,val6) do { \
+		duk_uint8_t *duk__p; \
+		DUK_BW_ASSERT_SPACE((thr), (bw_ctx), 6); \
+		duk__p = (bw_ctx)->p; \
+		*duk__p++ = (duk_uint8_t) (val1); \
+		*duk__p++ = (duk_uint8_t) (val2); \
+		*duk__p++ = (duk_uint8_t) (val3); \
+		*duk__p++ = (duk_uint8_t) (val4); \
+		*duk__p++ = (duk_uint8_t) (val5); \
+		*duk__p++ = (duk_uint8_t) (val6); \
+		(bw_ctx)->p = duk__p; \
+	} while (0)
+#define DUK_BW_WRITE_RAW_XUTF8(thr,bw_ctx,cp) do { \
+		duk_ucodepoint_t duk__cp; \
+		duk_small_int_t duk__enc_len; \
+		duk__cp = (cp); \
+		DUK_BW_ASSERT_SPACE((thr), (bw_ctx), duk_unicode_get_xutf8_length(duk__cp)); \
+		duk__enc_len = duk_unicode_encode_xutf8(duk__cp, (bw_ctx)->p); \
+		(bw_ctx)->p += duk__enc_len; \
+	} while (0)
+#define DUK_BW_WRITE_RAW_CESU8(thr,bw_ctx,cp) do { \
+		duk_ucodepoint_t duk__cp; \
+		duk_small_int_t duk__enc_len; \
+		duk__cp = (duk_ucodepoint_t) (cp); \
+		DUK_BW_ASSERT_SPACE((thr), (bw_ctx), duk_unicode_get_cesu8_length(duk__cp)); \
+		duk__enc_len = duk_unicode_encode_cesu8(duk__cp, (bw_ctx)->p); \
+		(bw_ctx)->p += duk__enc_len; \
+	} while (0)
+/* XXX: add temporary duk__p pointer here too; sharing */
+#define DUK_BW_WRITE_RAW_BYTES(thr,bw_ctx,valptr,valsz) do { \
+		const void *duk__valptr; \
+		duk_size_t duk__valsz; \
+		duk__valptr = (const void *) (valptr); \
+		duk__valsz = (duk_size_t) (valsz); \
+		DUK_MEMCPY((void *) ((bw_ctx)->p), duk__valptr, duk__valsz); \
+		(bw_ctx)->p += duk__valsz; \
+	} while (0)
+#define DUK_BW_WRITE_RAW_CSTRING(thr,bw_ctx,val) do { \
+		const duk_uint8_t *duk__val; \
+		duk_size_t duk__val_len; \
+		duk__val = (const duk_uint8_t *) (val); \
+		duk__val_len = DUK_STRLEN((const char *) duk__val); \
+		DUK_MEMCPY((void *) ((bw_ctx)->p), (const void *) duk__val, duk__val_len); \
+		(bw_ctx)->p += duk__val_len; \
+	} while (0)
+#define DUK_BW_WRITE_RAW_HSTRING(thr,bw_ctx,val) do { \
+		duk_size_t duk__val_len; \
+		duk__val_len = DUK_HSTRING_GET_BYTELEN((val)); \
+		DUK_MEMCPY((void *) ((bw_ctx)->p), (const void *) DUK_HSTRING_GET_DATA((val)), duk__val_len); \
+		(bw_ctx)->p += duk__val_len; \
+	} while (0)
+#define DUK_BW_WRITE_RAW_HBUFFER(thr,bw_ctx,val) do { \
+		duk_size_t duk__val_len; \
+		duk__val_len = DUK_HBUFFER_GET_SIZE((val)); \
+		DUK_MEMCPY((void *) ((bw_ctx)->p), (const void *) DUK_HBUFFER_GET_DATA_PTR((thr)->heap, (val)), duk__val_len); \
+		(bw_ctx)->p += duk__val_len; \
+	} while (0)
+#define DUK_BW_WRITE_RAW_HBUFFER_FIXED(thr,bw_ctx,val) do { \
+		duk_size_t duk__val_len; \
+		duk__val_len = DUK_HBUFFER_FIXED_GET_SIZE((val)); \
+		DUK_MEMCPY((void *) ((bw_ctx)->p), (const void *) DUK_HBUFFER_FIXED_GET_DATA_PTR((thr)->heap, (val)), duk__val_len); \
+		(bw_ctx)->p += duk__val_len; \
+	} while (0)
+#define DUK_BW_WRITE_RAW_HBUFFER_DYNAMIC(thr,bw_ctx,val) do { \
+		duk_size_t duk__val_len; \
+		duk__val_len = DUK_HBUFFER_DYNAMIC_GET_SIZE((val)); \
+		DUK_MEMCPY((void *) ((bw_ctx)->p), (const void *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR((thr)->heap, (val)), duk__val_len); \
+		(bw_ctx)->p += duk__val_len; \
+	} while (0)
+
+/* Append bytes from a slice already in the buffer. */
+#define DUK_BW_WRITE_RAW_SLICE(thr,bw,dst_off,dst_len) \
+	duk_bw_write_raw_slice((thr), (bw), (dst_off), (dst_len))
+
+/* Insert bytes in the middle of the buffer from an external buffer. */
+#define DUK_BW_INSERT_RAW_BYTES(thr,bw,dst_off,buf,len) \
+	duk_bw_insert_raw_bytes((thr), (bw), (dst_off), (buf), (len))
+
+/* Insert bytes in the middle of the buffer from a slice already
+ * in the buffer.  Source offset is interpreted "before" the operation.
+ */
+#define DUK_BW_INSERT_RAW_SLICE(thr,bw,dst_off,src_off,len) \
+	duk_bw_insert_raw_slice((thr), (bw), (dst_off), (src_off), (len))
+
+/* Insert a reserved area somewhere in the buffer; caller fills it.
+ * Evaluates to a (duk_uint_t *) pointing to the start of the reserved
+ * area for convenience.
+ */
+#define DUK_BW_INSERT_RAW_AREA(thr,bw,off,len) \
+	duk_bw_insert_raw_area((thr), (bw), (off), (len))
+
+/* Remove a slice from inside buffer. */
+#define DUK_BW_REMOVE_RAW_SLICE(thr,bw,off,len) \
+	duk_bw_remove_raw_slice((thr), (bw), (off), (len))
+
+/* Safe write calls which will ensure space first. */
+
+#define DUK_BW_WRITE_ENSURE_U8(thr,bw_ctx,val) do { \
+		DUK_BW_ENSURE((thr), (bw_ctx), 1); \
+		DUK_BW_WRITE_RAW_U8((thr), (bw_ctx), (val)); \
+	} while (0)
+#define DUK_BW_WRITE_ENSURE_U8_2(thr,bw_ctx,val1,val2) do { \
+		DUK_BW_ENSURE((thr), (bw_ctx), 2); \
+		DUK_BW_WRITE_RAW_U8_2((thr), (bw_ctx), (val1), (val2)); \
+	} while (0)
+#define DUK_BW_WRITE_ENSURE_U8_3(thr,bw_ctx,val1,val2,val3) do { \
+		DUK_BW_ENSURE((thr), (bw_ctx), 3); \
+		DUK_BW_WRITE_RAW_U8_3((thr), (bw_ctx), (val1), (val2), (val3)); \
+	} while (0)
+#define DUK_BW_WRITE_ENSURE_U8_4(thr,bw_ctx,val1,val2,val3,val4) do { \
+		DUK_BW_ENSURE((thr), (bw_ctx), 4); \
+		DUK_BW_WRITE_RAW_U8_4((thr), (bw_ctx), (val1), (val2), (val3), (val4)); \
+	} while (0)
+#define DUK_BW_WRITE_ENSURE_U8_5(thr,bw_ctx,val1,val2,val3,val4,val5) do { \
+		DUK_BW_ENSURE((thr), (bw_ctx), 5); \
+		DUK_BW_WRITE_RAW_U8_5((thr), (bw_ctx), (val1), (val2), (val3), (val4), (val5)); \
+	} while (0)
+#define DUK_BW_WRITE_ENSURE_U8_6(thr,bw_ctx,val1,val2,val3,val4,val5,val6) do { \
+		DUK_BW_ENSURE((thr), (bw_ctx), 6); \
+		DUK_BW_WRITE_RAW_U8_6((thr), (bw_ctx), (val1), (val2), (val3), (val4), (val5), (val6)); \
+	} while (0)
+#define DUK_BW_WRITE_ENSURE_XUTF8(thr,bw_ctx,cp) do { \
+		DUK_BW_ENSURE((thr), (bw_ctx), DUK_UNICODE_MAX_XUTF8_LENGTH); \
+		DUK_BW_WRITE_RAW_XUTF8((thr), (bw_ctx), (cp)); \
+	} while (0)
+#define DUK_BW_WRITE_ENSURE_CESU8(thr,bw_ctx,cp) do { \
+		DUK_BW_ENSURE((thr), (bw_ctx), DUK_UNICODE_MAX_CESU8_LENGTH); \
+		DUK_BW_WRITE_RAW_CESU8((thr), (bw_ctx), (cp)); \
+	} while (0)
+/* XXX: add temporary duk__p pointer here too; sharing */
+#define DUK_BW_WRITE_ENSURE_BYTES(thr,bw_ctx,valptr,valsz) do { \
+		const void *duk__valptr; \
+		duk_size_t duk__valsz; \
+		duk__valptr = (const void *) (valptr); \
+		duk__valsz = (duk_size_t) (valsz); \
+		DUK_BW_ENSURE((thr), (bw_ctx), duk__valsz); \
+		DUK_MEMCPY((void *) ((bw_ctx)->p), duk__valptr, duk__valsz); \
+		(bw_ctx)->p += duk__valsz; \
+	} while (0)
+#define DUK_BW_WRITE_ENSURE_CSTRING(thr,bw_ctx,val) do { \
+		const duk_uint8_t *duk__val; \
+		duk_size_t duk__val_len; \
+		duk__val = (const duk_uint8_t *) (val); \
+		duk__val_len = DUK_STRLEN((const char *) duk__val); \
+		DUK_BW_ENSURE((thr), (bw_ctx), duk__val_len); \
+		DUK_MEMCPY((void *) ((bw_ctx)->p), (const void *) duk__val, duk__val_len); \
+		(bw_ctx)->p += duk__val_len; \
+	} while (0)
+#define DUK_BW_WRITE_ENSURE_HSTRING(thr,bw_ctx,val) do { \
+		duk_size_t duk__val_len; \
+		duk__val_len = DUK_HSTRING_GET_BYTELEN((val)); \
+		DUK_BW_ENSURE((thr), (bw_ctx), duk__val_len); \
+		DUK_MEMCPY((void *) ((bw_ctx)->p), (const void *) DUK_HSTRING_GET_DATA((val)), duk__val_len); \
+		(bw_ctx)->p += duk__val_len; \
+	} while (0)
+#define DUK_BW_WRITE_ENSURE_HBUFFER(thr,bw_ctx,val) do { \
+		duk_size_t duk__val_len; \
+		duk__val_len = DUK_HBUFFER_GET_SIZE((val)); \
+		DUK_BW_ENSURE((thr), (bw_ctx), duk__val_len); \
+		DUK_MEMCPY((void *) ((bw_ctx)->p), (const void *) DUK_HBUFFER_GET_DATA_PTR((thr)->heap, (val)), duk__val_len); \
+		(bw_ctx)->p += duk__val_len; \
+	} while (0)
+#define DUK_BW_WRITE_ENSURE_HBUFFER_FIXED(thr,bw_ctx,val) do { \
+		duk_size_t duk__val_len; \
+		duk__val_len = DUK_HBUFFER_FIXED_GET_SIZE((val)); \
+		DUK_BW_ENSURE((thr), (bw_ctx), duk__val_len); \
+		DUK_MEMCPY((void *) ((bw_ctx)->p), (const void *) DUK_HBUFFER_FIXED_GET_DATA_PTR((thr)->heap, (val)), duk__val_len); \
+		(bw_ctx)->p += duk__val_len; \
+	} while (0)
+#define DUK_BW_WRITE_ENSURE_HBUFFER_DYNAMIC(thr,bw_ctx,val) do { \
+		duk_size_t duk__val_len; \
+		duk__val_len = DUK_HBUFFER_DYNAMIC_GET_SIZE((val)); \
+		DUK_BW_ENSURE((thr), (bw_ctx), duk__val_len); \
+		DUK_MEMCPY((void *) ((bw_ctx)->p), (const void *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR((thr)->heap, (val)), duk__val_len); \
+		(bw_ctx)->p += duk__val_len; \
+	} while (0)
+
+#define DUK_BW_WRITE_ENSURE_SLICE(thr,bw,dst_off,dst_len) \
+	duk_bw_write_ensure_slice((thr), (bw), (dst_off), (dst_len))
+#define DUK_BW_INSERT_ENSURE_BYTES(thr,bw,dst_off,buf,len) \
+	duk_bw_insert_ensure_bytes((thr), (bw), (dst_off), (buf), (len))
+#define DUK_BW_INSERT_ENSURE_SLICE(thr,bw,dst_off,src_off,len) \
+	duk_bw_insert_ensure_slice((thr), (bw), (dst_off), (src_off), (len))
+#define DUK_BW_INSERT_ENSURE_AREA(thr,bw,off,len) \
+	/* Evaluates to (duk_uint8_t *) pointing to start of area. */ \
+	duk_bw_insert_ensure_area((thr), (bw), (off), (len))
+#define DUK_BW_REMOVE_ENSURE_SLICE(thr,bw,off,len) \
+	/* No difference between raw/ensure because the buffer shrinks. */ \
+	DUK_BW_REMOVE_RAW_SLICE((thr), (bw), (off), (len))
+
+/*
+ *  Externs and prototypes
+ */
+
+#if !defined(DUK_SINGLE_FILE)
+DUK_INTERNAL_DECL const duk_uint8_t duk_lc_digits[36];
+DUK_INTERNAL_DECL const duk_uint8_t duk_uc_nybbles[16];
+DUK_INTERNAL_DECL const duk_int8_t duk_hex_dectab[256];
+#if defined(DUK_USE_HEX_FASTPATH)
+DUK_INTERNAL_DECL const duk_int16_t duk_hex_dectab_shift4[256];
+DUK_INTERNAL_DECL const duk_uint16_t duk_hex_enctab[256];
+#endif
+#if defined(DUK_USE_BASE64_FASTPATH)
+DUK_INTERNAL_DECL const duk_uint8_t duk_base64_enctab[64];
+DUK_INTERNAL_DECL const duk_int8_t duk_base64_dectab[256];
+#endif
+#endif  /* !DUK_SINGLE_FILE */
+
+/* Note: assumes that duk_util_probe_steps size is 32 */
+#if defined(DUK_USE_HOBJECT_HASH_PART) || defined(DUK_USE_STRTAB_PROBE)
+#if !defined(DUK_SINGLE_FILE)
+DUK_INTERNAL_DECL duk_uint8_t duk_util_probe_steps[32];
+#endif  /* !DUK_SINGLE_FILE */
+#endif
+
+#if defined(DUK_USE_STRHASH_DENSE)
+DUK_INTERNAL_DECL duk_uint32_t duk_util_hashbytes(const duk_uint8_t *data, duk_size_t len, duk_uint32_t seed);
+#endif
+
+#if defined(DUK_USE_HOBJECT_HASH_PART) || defined(DUK_USE_STRTAB_PROBE)
+DUK_INTERNAL_DECL duk_uint32_t duk_util_get_hash_prime(duk_uint32_t size);
+#endif
+
+DUK_INTERNAL_DECL duk_int32_t duk_bd_decode(duk_bitdecoder_ctx *ctx, duk_small_int_t bits);
+DUK_INTERNAL_DECL duk_small_int_t duk_bd_decode_flag(duk_bitdecoder_ctx *ctx);
+DUK_INTERNAL_DECL duk_int32_t duk_bd_decode_flagged(duk_bitdecoder_ctx *ctx, duk_small_int_t bits, duk_int32_t def_value);
+
+DUK_INTERNAL_DECL void duk_be_encode(duk_bitencoder_ctx *ctx, duk_uint32_t data, duk_small_int_t bits);
+DUK_INTERNAL_DECL void duk_be_finish(duk_bitencoder_ctx *ctx);
+
+DUK_INTERNAL_DECL duk_uint32_t duk_util_tinyrandom_get_bits(duk_hthread *thr, duk_small_int_t n);
+DUK_INTERNAL_DECL duk_double_t duk_util_tinyrandom_get_double(duk_hthread *thr);
+
+DUK_INTERNAL_DECL void duk_bw_init(duk_hthread *thr, duk_bufwriter_ctx *bw_ctx, duk_hbuffer_dynamic *h_buf);
+DUK_INTERNAL_DECL void duk_bw_init_pushbuf(duk_hthread *thr, duk_bufwriter_ctx *bw_ctx, duk_size_t buf_size);
+DUK_INTERNAL_DECL duk_uint8_t *duk_bw_resize(duk_hthread *thr, duk_bufwriter_ctx *bw_ctx, duk_size_t sz);
+DUK_INTERNAL_DECL void duk_bw_compact(duk_hthread *thr, duk_bufwriter_ctx *bw_ctx);
+DUK_INTERNAL_DECL void duk_bw_write_raw_slice(duk_hthread *thr, duk_bufwriter_ctx *bw, duk_size_t src_off, duk_size_t len);
+DUK_INTERNAL_DECL void duk_bw_write_ensure_slice(duk_hthread *thr, duk_bufwriter_ctx *bw, duk_size_t src_off, duk_size_t len);
+DUK_INTERNAL_DECL void duk_bw_insert_raw_bytes(duk_hthread *thr, duk_bufwriter_ctx *bw, duk_size_t dst_off, const duk_uint8_t *buf, duk_size_t len);
+DUK_INTERNAL_DECL void duk_bw_insert_ensure_bytes(duk_hthread *thr, duk_bufwriter_ctx *bw, duk_size_t dst_off, const duk_uint8_t *buf, duk_size_t len);
+DUK_INTERNAL_DECL void duk_bw_insert_raw_slice(duk_hthread *thr, duk_bufwriter_ctx *bw, duk_size_t dst_off, duk_size_t src_off, duk_size_t len);
+DUK_INTERNAL_DECL void duk_bw_insert_ensure_slice(duk_hthread *thr, duk_bufwriter_ctx *bw, duk_size_t dst_off, duk_size_t src_off, duk_size_t len);
+DUK_INTERNAL_DECL duk_uint8_t *duk_bw_insert_raw_area(duk_hthread *thr, duk_bufwriter_ctx *bw, duk_size_t off, duk_size_t len);
+DUK_INTERNAL_DECL duk_uint8_t *duk_bw_insert_ensure_area(duk_hthread *thr, duk_bufwriter_ctx *bw, duk_size_t off, duk_size_t len);
+DUK_INTERNAL_DECL void duk_bw_remove_raw_slice(duk_hthread *thr, duk_bufwriter_ctx *bw, duk_size_t off, duk_size_t len);
+/* No duk_bw_remove_ensure_slice(), functionality would be identical. */
+
+DUK_INTERNAL_DECL duk_uint16_t duk_raw_read_u16_be(duk_uint8_t **p);
+DUK_INTERNAL_DECL duk_uint32_t duk_raw_read_u32_be(duk_uint8_t **p);
+DUK_INTERNAL_DECL duk_double_t duk_raw_read_double_be(duk_uint8_t **p);
+DUK_INTERNAL_DECL void duk_raw_write_u16_be(duk_uint8_t **p, duk_uint16_t val);
+DUK_INTERNAL_DECL void duk_raw_write_u32_be(duk_uint8_t **p, duk_uint32_t val);
+DUK_INTERNAL_DECL void duk_raw_write_double_be(duk_uint8_t **p, duk_double_t val);
+
+#if defined(DUK_USE_DEBUGGER_SUPPORT)  /* For now only needed by the debugger. */
+DUK_INTERNAL void duk_byteswap_bytes(duk_uint8_t *p, duk_small_uint_t len);
+#endif
+
+#endif  /* DUK_UTIL_H_INCLUDED */
 #line 1 "duk_strings.h"
 /*
- *  Shared error messages: externs and macros
+ *  Shared error messages: declarations and macros
  *
  *  Error messages are accessed through macros with fine-grained, explicit
  *  error message distinctions.  Concrete error messages are selected by the
@@ -3568,84 +4969,90 @@ extern const duk_uint8_t duk_initjs_data[];
 #define DUK_STR_NOT_WRITABLE duk_str_not_writable
 #define DUK_STR_NOT_CONFIGURABLE duk_str_not_configurable
 
-extern const char *duk_str_internal_error;
-extern const char *duk_str_invalid_count;
-extern const char *duk_str_invalid_call_args;
-extern const char *duk_str_not_constructable;
-extern const char *duk_str_not_callable;
-extern const char *duk_str_not_extensible;
-extern const char *duk_str_not_writable;
-extern const char *duk_str_not_configurable;
-
-#define DUK_STR_INVALID_INDEX duk_str_invalid_index
+#if !defined(DUK_SINGLE_FILE)
+DUK_INTERNAL_DECL const char *duk_str_internal_error;
+DUK_INTERNAL_DECL const char *duk_str_invalid_count;
+DUK_INTERNAL_DECL const char *duk_str_invalid_call_args;
+DUK_INTERNAL_DECL const char *duk_str_not_constructable;
+DUK_INTERNAL_DECL const char *duk_str_not_callable;
+DUK_INTERNAL_DECL const char *duk_str_not_extensible;
+DUK_INTERNAL_DECL const char *duk_str_not_writable;
+DUK_INTERNAL_DECL const char *duk_str_not_configurable;
+#endif  /* !DUK_SINGLE_FILE */
+
+#define DUK_STR_INVALID_CONTEXT duk_str_invalid_context
+#define DUK_STR_INVALID_INDEX duk_str_invalid_call_args
 #define DUK_STR_PUSH_BEYOND_ALLOC_STACK duk_str_push_beyond_alloc_stack
-#define DUK_STR_SRC_STACK_NOT_ENOUGH duk_str_src_stack_not_enough
-#define DUK_STR_NOT_UNDEFINED duk_str_not_undefined
-#define DUK_STR_NOT_NULL duk_str_not_null
-#define DUK_STR_NOT_BOOLEAN duk_str_not_boolean
-#define DUK_STR_NOT_NUMBER duk_str_not_number
-#define DUK_STR_NOT_STRING duk_str_not_string
-#define DUK_STR_NOT_POINTER duk_str_not_pointer
-#define DUK_STR_NOT_BUFFER duk_str_not_buffer
-#define DUK_STR_NOT_OBJECT duk_str_not_object
+#define DUK_STR_NOT_UNDEFINED duk_str_unexpected_type
+#define DUK_STR_NOT_NULL duk_str_unexpected_type
+#define DUK_STR_NOT_BOOLEAN duk_str_unexpected_type
+#define DUK_STR_NOT_NUMBER duk_str_unexpected_type
+#define DUK_STR_NOT_STRING duk_str_unexpected_type
+#define DUK_STR_NOT_OBJECT duk_str_unexpected_type
+#define DUK_STR_NOT_POINTER duk_str_unexpected_type
+#define DUK_STR_NOT_BUFFER duk_str_not_buffer  /* still in use with verbose messages */
 #define DUK_STR_UNEXPECTED_TYPE duk_str_unexpected_type
-#define DUK_STR_NOT_THREAD duk_str_not_thread
-#define DUK_STR_NOT_COMPILEDFUNCTION duk_str_not_compiledfunction
-#define DUK_STR_NOT_NATIVEFUNCTION duk_str_not_nativefunction
-#define DUK_STR_NOT_C_FUNCTION duk_str_not_c_function
+#define DUK_STR_NOT_THREAD duk_str_unexpected_type
+#define DUK_STR_NOT_COMPILEDFUNCTION duk_str_unexpected_type
+#define DUK_STR_NOT_NATIVEFUNCTION duk_str_unexpected_type
+#define DUK_STR_NOT_C_FUNCTION duk_str_unexpected_type
+#define DUK_STR_NOT_FUNCTION duk_str_unexpected_type
+#define DUK_STR_NOT_REGEXP duk_str_unexpected_type
 #define DUK_STR_DEFAULTVALUE_COERCE_FAILED duk_str_defaultvalue_coerce_failed
 #define DUK_STR_NUMBER_OUTSIDE_RANGE duk_str_number_outside_range
 #define DUK_STR_NOT_OBJECT_COERCIBLE duk_str_not_object_coercible
 #define DUK_STR_STRING_TOO_LONG duk_str_string_too_long
 #define DUK_STR_BUFFER_TOO_LONG duk_str_buffer_too_long
 #define DUK_STR_SPRINTF_TOO_LONG duk_str_sprintf_too_long
-#define DUK_STR_OBJECT_ALLOC_FAILED duk_str_object_alloc_failed
-#define DUK_STR_THREAD_ALLOC_FAILED duk_str_thread_alloc_failed
-#define DUK_STR_FUNC_ALLOC_FAILED duk_str_func_alloc_failed
-#define DUK_STR_BUFFER_ALLOC_FAILED duk_str_buffer_alloc_failed
+#define DUK_STR_ALLOC_FAILED duk_str_alloc_failed
 #define DUK_STR_POP_TOO_MANY duk_str_pop_too_many
-
-extern const char *duk_str_invalid_index;
-extern const char *duk_str_push_beyond_alloc_stack;
-extern const char *duk_str_src_stack_not_enough;
-extern const char *duk_str_not_undefined;
-extern const char *duk_str_not_null;
-extern const char *duk_str_not_boolean;
-extern const char *duk_str_not_number;
-extern const char *duk_str_not_string;
-extern const char *duk_str_not_pointer;
-extern const char *duk_str_not_buffer;
-extern const char *duk_str_not_object;
-extern const char *duk_str_unexpected_type;
-extern const char *duk_str_not_thread;
-extern const char *duk_str_not_compiledfunction;
-extern const char *duk_str_not_nativefunction;
-extern const char *duk_str_not_c_function;
-extern const char *duk_str_defaultvalue_coerce_failed;
-extern const char *duk_str_number_outside_range;
-extern const char *duk_str_not_object_coercible;
-extern const char *duk_str_string_too_long;
-extern const char *duk_str_buffer_too_long;
-extern const char *duk_str_sprintf_too_long;
-extern const char *duk_str_object_alloc_failed;
-extern const char *duk_str_thread_alloc_failed;
-extern const char *duk_str_func_alloc_failed;
-extern const char *duk_str_buffer_alloc_failed;
-extern const char *duk_str_pop_too_many;
+#define DUK_STR_WRONG_BUFFER_TYPE duk_str_wrong_buffer_type
+#define DUK_STR_FAILED_TO_EXTEND_VALSTACK duk_str_failed_to_extend_valstack
+#define DUK_STR_ENCODE_FAILED duk_str_encode_failed
+#define DUK_STR_DECODE_FAILED duk_str_decode_failed
+#define DUK_STR_NO_SOURCECODE duk_str_no_sourcecode
+#define DUK_STR_CONCAT_RESULT_TOO_LONG duk_str_concat_result_too_long
+#define DUK_STR_UNIMPLEMENTED duk_str_unimplemented
+#define DUK_STR_UNSUPPORTED duk_str_unsupported
+#define DUK_STR_ARRAY_LENGTH_OVER_2G duk_str_array_length_over_2g
+
+#if !defined(DUK_SINGLE_FILE)
+DUK_INTERNAL_DECL const char *duk_str_invalid_context;
+DUK_INTERNAL_DECL const char *duk_str_push_beyond_alloc_stack;
+DUK_INTERNAL_DECL const char *duk_str_not_buffer;
+DUK_INTERNAL_DECL const char *duk_str_unexpected_type;
+DUK_INTERNAL_DECL const char *duk_str_defaultvalue_coerce_failed;
+DUK_INTERNAL_DECL const char *duk_str_number_outside_range;
+DUK_INTERNAL_DECL const char *duk_str_not_object_coercible;
+DUK_INTERNAL_DECL const char *duk_str_string_too_long;
+DUK_INTERNAL_DECL const char *duk_str_buffer_too_long;
+DUK_INTERNAL_DECL const char *duk_str_sprintf_too_long;
+DUK_INTERNAL_DECL const char *duk_str_alloc_failed;
+DUK_INTERNAL_DECL const char *duk_str_pop_too_many;
+DUK_INTERNAL_DECL const char *duk_str_wrong_buffer_type;
+DUK_INTERNAL_DECL const char *duk_str_failed_to_extend_valstack;
+DUK_INTERNAL_DECL const char *duk_str_encode_failed;
+DUK_INTERNAL_DECL const char *duk_str_decode_failed;
+DUK_INTERNAL_DECL const char *duk_str_no_sourcecode;
+DUK_INTERNAL_DECL const char *duk_str_concat_result_too_long;
+DUK_INTERNAL_DECL const char *duk_str_unimplemented;
+DUK_INTERNAL_DECL const char *duk_str_unsupported;
+DUK_INTERNAL_DECL const char *duk_str_array_length_over_2g;
+#endif  /* !DUK_SINGLE_FILE */
 
 #define DUK_STR_FMT_PTR duk_str_fmt_ptr
-#define DUK_STR_INVALID_JSON duk_str_invalid_json
-#define DUK_STR_INVALID_NUMBER duk_str_invalid_number
+#define DUK_STR_FMT_INVALID_JSON duk_str_fmt_invalid_json
 #define DUK_STR_JSONDEC_RECLIMIT duk_str_jsondec_reclimit
 #define DUK_STR_JSONENC_RECLIMIT duk_str_jsonenc_reclimit
 #define DUK_STR_CYCLIC_INPUT duk_str_cyclic_input
 
-extern const char *duk_str_fmt_ptr;
-extern const char *duk_str_invalid_json;
-extern const char *duk_str_invalid_number;
-extern const char *duk_str_jsondec_reclimit;
-extern const char *duk_str_jsonenc_reclimit;
-extern const char *duk_str_cyclic_input;
+#if !defined(DUK_SINGLE_FILE)
+DUK_INTERNAL_DECL const char *duk_str_fmt_ptr;
+DUK_INTERNAL_DECL const char *duk_str_fmt_invalid_json;
+DUK_INTERNAL_DECL const char *duk_str_jsondec_reclimit;
+DUK_INTERNAL_DECL const char *duk_str_jsonenc_reclimit;
+DUK_INTERNAL_DECL const char *duk_str_cyclic_input;
+#endif  /* !DUK_SINGLE_FILE */
 
 #define DUK_STR_PROXY_REVOKED duk_str_proxy_revoked
 #define DUK_STR_OBJECT_RESIZE_FAILED duk_str_object_resize_failed
@@ -3660,18 +5067,20 @@ extern const char *duk_str_cyclic_input;
 #define DUK_STR_INVALID_DESCRIPTOR duk_str_invalid_descriptor
 #define DUK_STR_PROPERTY_IS_VIRTUAL duk_str_property_is_virtual
 
-extern const char *duk_str_proxy_revoked;
-extern const char *duk_str_object_resize_failed;
-extern const char *duk_str_invalid_base;
-extern const char *duk_str_strict_caller_read;
-extern const char *duk_str_proxy_rejected;
-extern const char *duk_str_invalid_array_length;
-extern const char *duk_str_array_length_write_failed;
-extern const char *duk_str_array_length_not_writable;
-extern const char *duk_str_setter_undefined;
-extern const char *duk_str_redefine_virt_prop;
-extern const char *duk_str_invalid_descriptor;
-extern const char *duk_str_property_is_virtual;
+#if !defined(DUK_SINGLE_FILE)
+DUK_INTERNAL_DECL const char *duk_str_proxy_revoked;
+DUK_INTERNAL_DECL const char *duk_str_object_resize_failed;
+DUK_INTERNAL_DECL const char *duk_str_invalid_base;
+DUK_INTERNAL_DECL const char *duk_str_strict_caller_read;
+DUK_INTERNAL_DECL const char *duk_str_proxy_rejected;
+DUK_INTERNAL_DECL const char *duk_str_invalid_array_length;
+DUK_INTERNAL_DECL const char *duk_str_array_length_write_failed;
+DUK_INTERNAL_DECL const char *duk_str_array_length_not_writable;
+DUK_INTERNAL_DECL const char *duk_str_setter_undefined;
+DUK_INTERNAL_DECL const char *duk_str_redefine_virt_prop;
+DUK_INTERNAL_DECL const char *duk_str_invalid_descriptor;
+DUK_INTERNAL_DECL const char *duk_str_property_is_virtual;
+#endif  /* !DUK_SINGLE_FILE */
 
 #define DUK_STR_PARSE_ERROR duk_str_parse_error
 #define DUK_STR_DUPLICATE_LABEL duk_str_duplicate_label
@@ -3689,6 +5098,7 @@ extern const char *duk_str_property_is_virtual;
 #define DUK_STR_INVALID_BREAK_CONT_LABEL duk_str_invalid_break_cont_label
 #define DUK_STR_INVALID_RETURN duk_str_invalid_return
 #define DUK_STR_INVALID_TRY duk_str_invalid_try
+#define DUK_STR_INVALID_THROW duk_str_invalid_throw
 #define DUK_STR_WITH_IN_STRICT_MODE duk_str_with_in_strict_mode
 #define DUK_STR_FUNC_STMT_NOT_ALLOWED duk_str_func_stmt_not_allowed
 #define DUK_STR_UNTERMINATED_STMT duk_str_unterminated_stmt
@@ -3697,35 +5107,68 @@ extern const char *duk_str_property_is_virtual;
 #define DUK_STR_INVALID_GETSET_NAME duk_str_invalid_getset_name
 #define DUK_STR_FUNC_NAME_REQUIRED duk_str_func_name_required
 
-extern const char *duk_str_parse_error;
-extern const char *duk_str_duplicate_label;
-extern const char *duk_str_invalid_label;
-extern const char *duk_str_invalid_array_literal;
-extern const char *duk_str_invalid_object_literal;
-extern const char *duk_str_invalid_var_declaration;
-extern const char *duk_str_cannot_delete_identifier;
-extern const char *duk_str_invalid_expression;
-extern const char *duk_str_invalid_lvalue;
-extern const char *duk_str_expected_identifier;
-extern const char *duk_str_empty_expr_not_allowed;
-extern const char *duk_str_invalid_for;
-extern const char *duk_str_invalid_switch;
-extern const char *duk_str_invalid_break_cont_label;
-extern const char *duk_str_invalid_return;
-extern const char *duk_str_invalid_try;
-extern const char *duk_str_with_in_strict_mode;
-extern const char *duk_str_func_stmt_not_allowed;
-extern const char *duk_str_unterminated_stmt;
-extern const char *duk_str_invalid_arg_name;
-extern const char *duk_str_invalid_func_name;
-extern const char *duk_str_invalid_getset_name;
-extern const char *duk_str_func_name_required;
+#if !defined(DUK_SINGLE_FILE)
+DUK_INTERNAL_DECL const char *duk_str_parse_error;
+DUK_INTERNAL_DECL const char *duk_str_duplicate_label;
+DUK_INTERNAL_DECL const char *duk_str_invalid_label;
+DUK_INTERNAL_DECL const char *duk_str_invalid_array_literal;
+DUK_INTERNAL_DECL const char *duk_str_invalid_object_literal;
+DUK_INTERNAL_DECL const char *duk_str_invalid_var_declaration;
+DUK_INTERNAL_DECL const char *duk_str_cannot_delete_identifier;
+DUK_INTERNAL_DECL const char *duk_str_invalid_expression;
+DUK_INTERNAL_DECL const char *duk_str_invalid_lvalue;
+DUK_INTERNAL_DECL const char *duk_str_expected_identifier;
+DUK_INTERNAL_DECL const char *duk_str_empty_expr_not_allowed;
+DUK_INTERNAL_DECL const char *duk_str_invalid_for;
+DUK_INTERNAL_DECL const char *duk_str_invalid_switch;
+DUK_INTERNAL_DECL const char *duk_str_invalid_break_cont_label;
+DUK_INTERNAL_DECL const char *duk_str_invalid_return;
+DUK_INTERNAL_DECL const char *duk_str_invalid_try;
+DUK_INTERNAL_DECL const char *duk_str_invalid_throw;
+DUK_INTERNAL_DECL const char *duk_str_with_in_strict_mode;
+DUK_INTERNAL_DECL const char *duk_str_func_stmt_not_allowed;
+DUK_INTERNAL_DECL const char *duk_str_unterminated_stmt;
+DUK_INTERNAL_DECL const char *duk_str_invalid_arg_name;
+DUK_INTERNAL_DECL const char *duk_str_invalid_func_name;
+DUK_INTERNAL_DECL const char *duk_str_invalid_getset_name;
+DUK_INTERNAL_DECL const char *duk_str_func_name_required;
+#endif  /* !DUK_SINGLE_FILE */
 
 #define DUK_STR_INTERNAL_ERROR_EXEC_LONGJMP duk_str_internal_error_exec_longjmp
 
-extern const char *duk_str_internal_error_exec_longjmp;
+#if !defined(DUK_SINGLE_FILE)
+DUK_INTERNAL_DECL const char *duk_str_internal_error_exec_longjmp;
+#endif  /* !DUK_SINGLE_FILE */
+
+#define DUK_STR_INVALID_QUANTIFIER_NO_ATOM duk_str_invalid_quantifier_no_atom
+#define DUK_STR_INVALID_QUANTIFIER_VALUES duk_str_invalid_quantifier_values
+#define DUK_STR_QUANTIFIER_TOO_MANY_COPIES duk_str_quantifier_too_many_copies
+#define DUK_STR_UNEXPECTED_CLOSING_PAREN duk_str_unexpected_closing_paren
+#define DUK_STR_UNEXPECTED_END_OF_PATTERN duk_str_unexpected_end_of_pattern
+#define DUK_STR_UNEXPECTED_REGEXP_TOKEN duk_str_unexpected_regexp_token
+#define DUK_STR_INVALID_REGEXP_FLAGS duk_str_invalid_regexp_flags
+#define DUK_STR_INVALID_BACKREFS duk_str_invalid_backrefs
+#define DUK_STR_REGEXP_BACKTRACK_FAILED duk_str_regexp_backtrack_failed
+#define DUK_STR_REGEXP_ADVANCE_FAILED duk_str_regexp_advance_failed
+#define DUK_STR_REGEXP_INTERNAL_ERROR duk_str_regexp_internal_error
+
+#if !defined(DUK_SINGLE_FILE)
+DUK_INTERNAL_DECL const char *duk_str_invalid_quantifier_no_atom;
+DUK_INTERNAL_DECL const char *duk_str_invalid_quantifier_values;
+DUK_INTERNAL_DECL const char *duk_str_quantifier_too_many_copies;
+DUK_INTERNAL_DECL const char *duk_str_unexpected_closing_paren;
+DUK_INTERNAL_DECL const char *duk_str_unexpected_end_of_pattern;
+DUK_INTERNAL_DECL const char *duk_str_unexpected_regexp_token;
+DUK_INTERNAL_DECL const char *duk_str_invalid_regexp_flags;
+DUK_INTERNAL_DECL const char *duk_str_invalid_backrefs;
+DUK_INTERNAL_DECL const char *duk_str_regexp_backtrack_failed;
+DUK_INTERNAL_DECL const char *duk_str_regexp_advance_failed;
+DUK_INTERNAL_DECL const char *duk_str_regexp_internal_error;
+#endif  /* !DUK_SINGLE_FILE */
 
 #define DUK_STR_VALSTACK_LIMIT duk_str_valstack_limit
+#define DUK_STR_CALLSTACK_LIMIT duk_str_callstack_limit
+#define DUK_STR_CATCHSTACK_LIMIT duk_str_catchstack_limit
 #define DUK_STR_OBJECT_PROPERTY_LIMIT duk_str_object_property_limit
 #define DUK_STR_PROTOTYPE_CHAIN_LIMIT duk_str_prototype_chain_limit
 #define DUK_STR_BOUND_CHAIN_LIMIT duk_str_bound_chain_limit
@@ -3736,18 +5179,36 @@ extern const char *duk_str_internal_error_exec_longjmp;
 #define DUK_STR_TEMP_LIMIT duk_str_temp_limit
 #define DUK_STR_CONST_LIMIT duk_str_const_limit
 #define DUK_STR_FUNC_LIMIT duk_str_func_limit
-
-extern const char *duk_str_valstack_limit;
-extern const char *duk_str_object_property_limit;
-extern const char *duk_str_prototype_chain_limit;
-extern const char *duk_str_bound_chain_limit;
-extern const char *duk_str_c_callstack_limit;
-extern const char *duk_str_compiler_recursion_limit;
-extern const char *duk_str_bytecode_limit;
-extern const char *duk_str_reg_limit;
-extern const char *duk_str_temp_limit;
-extern const char *duk_str_const_limit;
-extern const char *duk_str_func_limit;
+#define DUK_STR_REGEXP_COMPILER_RECURSION_LIMIT duk_str_regexp_compiler_recursion_limit
+#define DUK_STR_REGEXP_EXECUTOR_RECURSION_LIMIT duk_str_regexp_executor_recursion_limit
+#define DUK_STR_REGEXP_EXECUTOR_STEP_LIMIT duk_str_regexp_executor_step_limit
+
+#if !defined(DUK_SINGLE_FILE)
+DUK_INTERNAL_DECL const char *duk_str_valstack_limit;
+DUK_INTERNAL_DECL const char *duk_str_callstack_limit;
+DUK_INTERNAL_DECL const char *duk_str_catchstack_limit;
+DUK_INTERNAL_DECL const char *duk_str_object_property_limit;
+DUK_INTERNAL_DECL const char *duk_str_prototype_chain_limit;
+DUK_INTERNAL_DECL const char *duk_str_bound_chain_limit;
+DUK_INTERNAL_DECL const char *duk_str_c_callstack_limit;
+DUK_INTERNAL_DECL const char *duk_str_compiler_recursion_limit;
+DUK_INTERNAL_DECL const char *duk_str_bytecode_limit;
+DUK_INTERNAL_DECL const char *duk_str_reg_limit;
+DUK_INTERNAL_DECL const char *duk_str_temp_limit;
+DUK_INTERNAL_DECL const char *duk_str_const_limit;
+DUK_INTERNAL_DECL const char *duk_str_func_limit;
+DUK_INTERNAL_DECL const char *duk_str_regexp_compiler_recursion_limit;
+DUK_INTERNAL_DECL const char *duk_str_regexp_executor_recursion_limit;
+DUK_INTERNAL_DECL const char *duk_str_regexp_executor_step_limit;
+#endif  /* !DUK_SINGLE_FILE */
+
+#define DUK_STR_ANON duk_str_anon
+#define DUK_STR_REALLOC_FAILED duk_str_realloc_failed
+
+#if !defined(DUK_SINGLE_FILE)
+DUK_INTERNAL_DECL const char *duk_str_anon;
+DUK_INTERNAL_DECL const char *duk_str_realloc_failed;
+#endif  /* !DUK_SINGLE_FILE */
 
 #endif  /* DUK_ERRMSG_H_INCLUDED */
 #line 1 "duk_js_bytecode.h"
@@ -3780,7 +5241,7 @@ extern const char *duk_str_func_limit;
  *
  *  Note: macro naming is a bit misleading, e.g. "ABC" in macro name but
  *  the field layout is logically "CBA".
- */ 
+ */
 
 typedef duk_uint32_t duk_instr_t;
 
@@ -3791,6 +5252,7 @@ typedef duk_uint32_t duk_instr_t;
 #define DUK_DEC_BC(x)               (((x) >> 14) & 0x3ffffUL)
 #define DUK_DEC_ABC(x)              (((x) >> 6) & 0x3ffffffUL)
 
+#define DUK_ENC_OP(op)              ((duk_instr_t) (op))
 #define DUK_ENC_OP_ABC(op,abc)      ((duk_instr_t) ( \
                                         (((duk_instr_t) (abc)) << 6) | \
                                         ((duk_instr_t) (op)) \
@@ -3827,7 +5289,7 @@ typedef duk_uint32_t duk_instr_t;
 #define DUK_BC_EXTRAOP_MIN          DUK_BC_A_MIN
 #define DUK_BC_EXTRAOP_MAX          DUK_BC_A_MAX
 
-#define DUK_OP_LDREG                0 
+#define DUK_OP_LDREG                0
 #define DUK_OP_STREG                1
 #define DUK_OP_LDCONST              2
 #define DUK_OP_LDINT                3
@@ -3864,47 +5326,48 @@ typedef duk_uint32_t duk_instr_t;
 #define DUK_OP_BASL                 34
 #define DUK_OP_BLSR                 35
 #define DUK_OP_BASR                 36
-#define DUK_OP_BNOT                 37
-#define DUK_OP_LNOT                 38
-#define DUK_OP_EQ                   39
-#define DUK_OP_NEQ                  40
-#define DUK_OP_SEQ                  41
-#define DUK_OP_SNEQ                 42
-#define DUK_OP_GT                   43
-#define DUK_OP_GE                   44
-#define DUK_OP_LT                   45
-#define DUK_OP_LE                   46
-#define DUK_OP_IF                   47
-#define DUK_OP_INSTOF               48
-#define DUK_OP_IN                   49
-#define DUK_OP_JUMP                 50
-#define DUK_OP_RETURN               51
-#define DUK_OP_CALL                 52
-#define DUK_OP_CALLI                53
-#define DUK_OP_LABEL                54
-#define DUK_OP_ENDLABEL             55
-#define DUK_OP_BREAK                56
-#define DUK_OP_CONTINUE             57
-#define DUK_OP_TRYCATCH             58
-#define DUK_OP_UNUSED59             59
-#define DUK_OP_UNUSED60             60
-#define DUK_OP_UNUSED61             61
-#define DUK_OP_EXTRA                62
-#define DUK_OP_INVALID              63
+#define DUK_OP_EQ                   37
+#define DUK_OP_NEQ                  38
+#define DUK_OP_SEQ                  39
+#define DUK_OP_SNEQ                 40
+#define DUK_OP_GT                   41
+#define DUK_OP_GE                   42
+#define DUK_OP_LT                   43
+#define DUK_OP_LE                   44
+#define DUK_OP_IF                   45
+#define DUK_OP_JUMP                 46
+#define DUK_OP_RETURN               47
+#define DUK_OP_CALL                 48
+#define DUK_OP_CALLI                49
+#define DUK_OP_TRYCATCH             50
+#define DUK_OP_EXTRA                51
+#define DUK_OP_PREINCR              52  /* pre/post opcode values have constraints, */
+#define DUK_OP_PREDECR              53  /* see duk_js_executor.c */
+#define DUK_OP_POSTINCR             54
+#define DUK_OP_POSTDECR             55
+#define DUK_OP_PREINCV              56
+#define DUK_OP_PREDECV              57
+#define DUK_OP_POSTINCV             58
+#define DUK_OP_POSTDECV             59
+#define DUK_OP_PREINCP              60
+#define DUK_OP_PREDECP              61
+#define DUK_OP_POSTINCP             62
+#define DUK_OP_POSTDECP             63
+#define DUK_OP_NONE                 64  /* dummy value used as marker */
 
 /* DUK_OP_EXTRA, sub-operation in A */
 #define DUK_EXTRAOP_NOP             0
-#define DUK_EXTRAOP_LDTHIS          1
-#define DUK_EXTRAOP_LDUNDEF         2
-#define DUK_EXTRAOP_LDNULL          3
-#define DUK_EXTRAOP_LDTRUE          4
-#define DUK_EXTRAOP_LDFALSE         5
-#define DUK_EXTRAOP_NEWOBJ          6
-#define DUK_EXTRAOP_NEWARR          7
-#define DUK_EXTRAOP_SETALEN         8
-#define DUK_EXTRAOP_TYPEOF          9
-#define DUK_EXTRAOP_TYPEOFID        10
-#define DUK_EXTRAOP_TONUM           11
+#define DUK_EXTRAOP_INVALID         1
+#define DUK_EXTRAOP_LDTHIS          2
+#define DUK_EXTRAOP_LDUNDEF         3
+#define DUK_EXTRAOP_LDNULL          4
+#define DUK_EXTRAOP_LDTRUE          5
+#define DUK_EXTRAOP_LDFALSE         6
+#define DUK_EXTRAOP_NEWOBJ          7
+#define DUK_EXTRAOP_NEWARR          8
+#define DUK_EXTRAOP_SETALEN         9
+#define DUK_EXTRAOP_TYPEOF          10
+#define DUK_EXTRAOP_TYPEOFID        11
 #define DUK_EXTRAOP_INITENUM        12
 #define DUK_EXTRAOP_NEXTENUM        13
 #define DUK_EXTRAOP_INITSET         14
@@ -3918,14 +5381,15 @@ typedef duk_uint32_t duk_instr_t;
 #define DUK_EXTRAOP_INVLHS          22
 #define DUK_EXTRAOP_UNM             23
 #define DUK_EXTRAOP_UNP             24
-#define DUK_EXTRAOP_INC             25
-#define DUK_EXTRAOP_DEC             26
-
-/* DUK_OP_EXTRA for debugging */
-#define DUK_EXTRAOP_DUMPREG         128
-#define DUK_EXTRAOP_DUMPREGS        129
-#define DUK_EXTRAOP_DUMPTHREAD      130
-#define DUK_EXTRAOP_LOGMARK         131
+#define DUK_EXTRAOP_DEBUGGER        25
+#define DUK_EXTRAOP_BREAK           26
+#define DUK_EXTRAOP_CONTINUE        27
+#define DUK_EXTRAOP_BNOT            28
+#define DUK_EXTRAOP_LNOT            29
+#define DUK_EXTRAOP_INSTOF          30
+#define DUK_EXTRAOP_IN              31
+#define DUK_EXTRAOP_LABEL           32
+#define DUK_EXTRAOP_ENDLABEL        33
 
 /* DUK_OP_CALL flags in A */
 #define DUK_BC_CALL_FLAG_TAILCALL           (1 << 0)
@@ -3938,8 +5402,7 @@ typedef duk_uint32_t duk_instr_t;
 #define DUK_BC_TRYCATCH_FLAG_WITH_BINDING   (1 << 3)
 
 /* DUK_OP_RETURN flags in A */
-#define DUK_BC_RETURN_FLAG_FAST             (1 << 0)
-#define DUK_BC_RETURN_FLAG_HAVE_RETVAL      (1 << 1)
+#define DUK_BC_RETURN_FLAG_HAVE_RETVAL      (1 << 0)
 
 /* DUK_OP_DECLVAR flags in A; bottom bits are reserved for propdesc flags (DUK_PROPDESC_FLAG_XXX) */
 #define DUK_BC_DECLVAR_FLAG_UNDEF_VALUE     (1 << 4)  /* use 'undefined' for value automatically */
@@ -3954,7 +5417,6 @@ typedef duk_uint32_t duk_instr_t;
 #define DUK_BC_JUMP_BIAS            (1L << 25)
 
 #endif  /* DUK_JS_BYTECODE_H_INCLUDED */
-
 #line 1 "duk_lexer.h"
 /*
  *  Lexer defines.
@@ -3988,149 +5450,146 @@ typedef void (*duk_re_range_callback)(void *user, duk_codepoint_t r1, duk_codepo
 
 #define DUK_LEXER_SETPOINT(ctx,pt)    duk_lexer_setpoint((ctx), (pt))
 
-#define DUK_LEXER_GETPOINT(ctx,pt)    do { (pt)->offset = (ctx)->offsets[0]; \
-                                           (pt)->line = (ctx)->lines[0]; } while (0)
+#define DUK_LEXER_GETPOINT(ctx,pt)    do { (pt)->offset = (ctx)->window[0].offset; \
+                                           (pt)->line = (ctx)->window[0].line; } while (0)
 
 /* currently 6 characters of lookup are actually needed (duk_lexer.c) */
-#define DUK_LEXER_WINDOW_SIZE                     8
+#define DUK_LEXER_WINDOW_SIZE                     6
+#if defined(DUK_USE_LEXER_SLIDING_WINDOW)
+#define DUK_LEXER_BUFFER_SIZE                     64
+#endif
 
 #define DUK_TOK_MINVAL                            0
 
 /* returned after EOF (infinite amount) */
 #define DUK_TOK_EOF                               0
 
-/* line terminator or multi-line comment with internal lineterm (E5 Sections 7.3, 7.4) */
-#define DUK_TOK_LINETERM                          1
-
-/* single-line comment or multi-line comment without internal lineterm (E5 Section 7.4) */
-#define DUK_TOK_COMMENT                           2
-
 /* identifier names (E5 Section 7.6) */
-#define DUK_TOK_IDENTIFIER                        3
+#define DUK_TOK_IDENTIFIER                        1
 
 /* reserved words: keywords */
-#define DUK_TOK_START_RESERVED                    4
-#define DUK_TOK_BREAK                             4
-#define DUK_TOK_CASE                              5
-#define DUK_TOK_CATCH                             6
-#define DUK_TOK_CONTINUE                          7
-#define DUK_TOK_DEBUGGER                          8
-#define DUK_TOK_DEFAULT                           9
-#define DUK_TOK_DELETE                            10
-#define DUK_TOK_DO                                11
-#define DUK_TOK_ELSE                              12
-#define DUK_TOK_FINALLY                           13
-#define DUK_TOK_FOR                               14
-#define DUK_TOK_FUNCTION                          15
-#define DUK_TOK_IF                                16
-#define DUK_TOK_IN                                17
-#define DUK_TOK_INSTANCEOF                        18
-#define DUK_TOK_NEW                               19
-#define DUK_TOK_RETURN                            20
-#define DUK_TOK_SWITCH                            21
-#define DUK_TOK_THIS                              22
-#define DUK_TOK_THROW                             23
-#define DUK_TOK_TRY                               24
-#define DUK_TOK_TYPEOF                            25
-#define DUK_TOK_VAR                               26
-#define DUK_TOK_VOID                              27
-#define DUK_TOK_WHILE                             28
-#define DUK_TOK_WITH                              29
+#define DUK_TOK_START_RESERVED                    2
+#define DUK_TOK_BREAK                             2
+#define DUK_TOK_CASE                              3
+#define DUK_TOK_CATCH                             4
+#define DUK_TOK_CONTINUE                          5
+#define DUK_TOK_DEBUGGER                          6
+#define DUK_TOK_DEFAULT                           7
+#define DUK_TOK_DELETE                            8
+#define DUK_TOK_DO                                9
+#define DUK_TOK_ELSE                              10
+#define DUK_TOK_FINALLY                           11
+#define DUK_TOK_FOR                               12
+#define DUK_TOK_FUNCTION                          13
+#define DUK_TOK_IF                                14
+#define DUK_TOK_IN                                15
+#define DUK_TOK_INSTANCEOF                        16
+#define DUK_TOK_NEW                               17
+#define DUK_TOK_RETURN                            18
+#define DUK_TOK_SWITCH                            19
+#define DUK_TOK_THIS                              20
+#define DUK_TOK_THROW                             21
+#define DUK_TOK_TRY                               22
+#define DUK_TOK_TYPEOF                            23
+#define DUK_TOK_VAR                               24
+#define DUK_TOK_CONST                             25
+#define DUK_TOK_VOID                              26
+#define DUK_TOK_WHILE                             27
+#define DUK_TOK_WITH                              28
 
 /* reserved words: future reserved words */
-#define DUK_TOK_CLASS                             30
-#define DUK_TOK_CONST                             31
-#define DUK_TOK_ENUM                              32
-#define DUK_TOK_EXPORT                            33
-#define DUK_TOK_EXTENDS                           34
-#define DUK_TOK_IMPORT                            35
-#define DUK_TOK_SUPER                             36
+#define DUK_TOK_CLASS                             29
+#define DUK_TOK_ENUM                              30
+#define DUK_TOK_EXPORT                            31
+#define DUK_TOK_EXTENDS                           32
+#define DUK_TOK_IMPORT                            33
+#define DUK_TOK_SUPER                             34
 
 /* "null", "true", and "false" are always reserved words.
  * Note that "get" and "set" are not!
  */
-#define DUK_TOK_NULL                              37
-#define DUK_TOK_TRUE                              38
-#define DUK_TOK_FALSE                             39
+#define DUK_TOK_NULL                              35
+#define DUK_TOK_TRUE                              36
+#define DUK_TOK_FALSE                             37
 
 /* reserved words: additional future reserved words in strict mode */
-#define DUK_TOK_START_STRICT_RESERVED             40  /* inclusive */
-#define DUK_TOK_IMPLEMENTS                        40
-#define DUK_TOK_INTERFACE                         41
-#define DUK_TOK_LET                               42
-#define DUK_TOK_PACKAGE                           43
-#define DUK_TOK_PRIVATE                           44
-#define DUK_TOK_PROTECTED                         45
-#define DUK_TOK_PUBLIC                            46
-#define DUK_TOK_STATIC                            47
-#define DUK_TOK_YIELD                             48
-
-#define DUK_TOK_END_RESERVED                      49  /* exclusive */
+#define DUK_TOK_START_STRICT_RESERVED             38  /* inclusive */
+#define DUK_TOK_IMPLEMENTS                        38
+#define DUK_TOK_INTERFACE                         39
+#define DUK_TOK_LET                               40
+#define DUK_TOK_PACKAGE                           41
+#define DUK_TOK_PRIVATE                           42
+#define DUK_TOK_PROTECTED                         43
+#define DUK_TOK_PUBLIC                            44
+#define DUK_TOK_STATIC                            45
+#define DUK_TOK_YIELD                             46
+
+#define DUK_TOK_END_RESERVED                      47  /* exclusive */
 
 /* "get" and "set" are tokens but NOT ReservedWords.  They are currently
  * parsed and identifiers and these defines are actually now unused.
  */
-#define DUK_TOK_GET                               49
-#define DUK_TOK_SET                               50
+#define DUK_TOK_GET                               47
+#define DUK_TOK_SET                               48
 
 /* punctuators (unlike the spec, also includes "/" and "/=") */
-#define DUK_TOK_LCURLY                            51
-#define DUK_TOK_RCURLY                            52
-#define DUK_TOK_LBRACKET                          53
-#define DUK_TOK_RBRACKET                          54
-#define DUK_TOK_LPAREN                            55
-#define DUK_TOK_RPAREN                            56
-#define DUK_TOK_PERIOD                            57
-#define DUK_TOK_SEMICOLON                         58
-#define DUK_TOK_COMMA                             59
-#define DUK_TOK_LT                                60
-#define DUK_TOK_GT                                61
-#define DUK_TOK_LE                                62
-#define DUK_TOK_GE                                63
-#define DUK_TOK_EQ                                64
-#define DUK_TOK_NEQ                               65
-#define DUK_TOK_SEQ                               66
-#define DUK_TOK_SNEQ                              67
-#define DUK_TOK_ADD                               68
-#define DUK_TOK_SUB                               69
-#define DUK_TOK_MUL                               70
-#define DUK_TOK_DIV                               71
-#define DUK_TOK_MOD                               72
-#define DUK_TOK_INCREMENT                         73
-#define DUK_TOK_DECREMENT                         74
-#define DUK_TOK_ALSHIFT                           75  /* named "arithmetic" because result is signed */
-#define DUK_TOK_ARSHIFT                           76
-#define DUK_TOK_RSHIFT                            77
-#define DUK_TOK_BAND                              78
-#define DUK_TOK_BOR                               79
-#define DUK_TOK_BXOR                              80
-#define DUK_TOK_LNOT                              81
-#define DUK_TOK_BNOT                              82
-#define DUK_TOK_LAND                              83
-#define DUK_TOK_LOR                               84
-#define DUK_TOK_QUESTION                          85
-#define DUK_TOK_COLON                             86
-#define DUK_TOK_EQUALSIGN                         87
-#define DUK_TOK_ADD_EQ                            88
-#define DUK_TOK_SUB_EQ                            89
-#define DUK_TOK_MUL_EQ                            90
-#define DUK_TOK_DIV_EQ                            91
-#define DUK_TOK_MOD_EQ                            92
-#define DUK_TOK_ALSHIFT_EQ                        93
-#define DUK_TOK_ARSHIFT_EQ                        94
-#define DUK_TOK_RSHIFT_EQ                         95
-#define DUK_TOK_BAND_EQ                           96
-#define DUK_TOK_BOR_EQ                            97
-#define DUK_TOK_BXOR_EQ                           98
+#define DUK_TOK_LCURLY                            49
+#define DUK_TOK_RCURLY                            50
+#define DUK_TOK_LBRACKET                          51
+#define DUK_TOK_RBRACKET                          52
+#define DUK_TOK_LPAREN                            53
+#define DUK_TOK_RPAREN                            54
+#define DUK_TOK_PERIOD                            55
+#define DUK_TOK_SEMICOLON                         56
+#define DUK_TOK_COMMA                             57
+#define DUK_TOK_LT                                58
+#define DUK_TOK_GT                                59
+#define DUK_TOK_LE                                60
+#define DUK_TOK_GE                                61
+#define DUK_TOK_EQ                                62
+#define DUK_TOK_NEQ                               63
+#define DUK_TOK_SEQ                               64
+#define DUK_TOK_SNEQ                              65
+#define DUK_TOK_ADD                               66
+#define DUK_TOK_SUB                               67
+#define DUK_TOK_MUL                               68
+#define DUK_TOK_DIV                               69
+#define DUK_TOK_MOD                               70
+#define DUK_TOK_INCREMENT                         71
+#define DUK_TOK_DECREMENT                         72
+#define DUK_TOK_ALSHIFT                           73  /* named "arithmetic" because result is signed */
+#define DUK_TOK_ARSHIFT                           74
+#define DUK_TOK_RSHIFT                            75
+#define DUK_TOK_BAND                              76
+#define DUK_TOK_BOR                               77
+#define DUK_TOK_BXOR                              78
+#define DUK_TOK_LNOT                              79
+#define DUK_TOK_BNOT                              80
+#define DUK_TOK_LAND                              81
+#define DUK_TOK_LOR                               82
+#define DUK_TOK_QUESTION                          83
+#define DUK_TOK_COLON                             84
+#define DUK_TOK_EQUALSIGN                         85
+#define DUK_TOK_ADD_EQ                            86
+#define DUK_TOK_SUB_EQ                            87
+#define DUK_TOK_MUL_EQ                            88
+#define DUK_TOK_DIV_EQ                            89
+#define DUK_TOK_MOD_EQ                            90
+#define DUK_TOK_ALSHIFT_EQ                        91
+#define DUK_TOK_ARSHIFT_EQ                        92
+#define DUK_TOK_RSHIFT_EQ                         93
+#define DUK_TOK_BAND_EQ                           94
+#define DUK_TOK_BOR_EQ                            95
+#define DUK_TOK_BXOR_EQ                           96
 
 /* literals (E5 Section 7.8), except null, true, false, which are treated
  * like reserved words (above).
  */
-#define DUK_TOK_NUMBER                            99
-#define DUK_TOK_STRING                            100
-#define DUK_TOK_REGEXP                            101
+#define DUK_TOK_NUMBER                            97
+#define DUK_TOK_STRING                            98
+#define DUK_TOK_REGEXP                            99
 
-#define DUK_TOK_MAXVAL                            101  /* inclusive */
+#define DUK_TOK_MAXVAL                            99  /* inclusive */
 
 /* Convert heap string index to a token (reserved words) */
 #define DUK_STRIDX_TO_TOK(x)                        ((x) - DUK_STRIDX_START_RESERVED + DUK_TOK_START_RESERVED)
@@ -4302,20 +5761,21 @@ typedef void (*duk_re_range_callback)(void *user, duk_codepoint_t r1, duk_codepo
 #define DUK_RETOK_ATOM_START_CHARCLASS_INVERTED    21
 #define DUK_RETOK_ATOM_END_GROUP                   22
 
-/* constants for duk_lexer_ctx.buf */
-#define DUK_LEXER_TEMP_BUF_INITIAL                 64
+/* Constants for duk_lexer_ctx.buf. */
 #define DUK_LEXER_TEMP_BUF_LIMIT                   256
 
-/* A token value.  Can be memcpy()'d, but note that slot1/slot2 values are on the valstack. */
+/* A token value.  Can be memcpy()'d, but note that slot1/slot2 values are on the valstack.
+ * Some fields (like num, str1, str2) are only valid for specific token types and may have
+ * stale values otherwise.
+ */
 struct duk_token {
 	duk_small_int_t t;            /* token type (with reserved word identification) */
 	duk_small_int_t t_nores;      /* token type (with reserved words as DUK_TOK_IDENTIFER) */
 	duk_double_t num;             /* numeric value of token */
 	duk_hstring *str1;            /* string 1 of token (borrowed, stored to ctx->slot1_idx) */
-	duk_hstring *str2;            /* string 2 of token (borrowed, stored to ctx->slot1_idx) */
+	duk_hstring *str2;            /* string 2 of token (borrowed, stored to ctx->slot2_idx) */
 	duk_size_t start_offset;      /* start byte offset of token in lexer input */
 	duk_int_t start_line;         /* start line of token (first char) */
-	duk_int_t end_line;           /* end line of token (char after last token char) */
 	duk_int_t num_escapes;        /* number of escapes and line continuations (for directive prologue) */
 	duk_bool_t lineterm;          /* token was preceded by a lineterm */
 	duk_bool_t allow_auto_semi;   /* token allows automatic semicolon insertion (eof or preceded by newline) */
@@ -4338,22 +5798,34 @@ struct duk_lexer_point {
 	duk_int_t line;
 };
 
+/* Lexer codepoint with additional info like offset/line number */
+struct duk_lexer_codepoint {
+	duk_codepoint_t codepoint;
+	duk_size_t offset;
+	duk_int_t line;
+};
+
 /* Lexer context.  Same context is used for Ecmascript and Regexp parsing. */
 struct duk_lexer_ctx {
+#if defined(DUK_USE_LEXER_SLIDING_WINDOW)
+	duk_lexer_codepoint *window; /* unicode code points, window[0] is always next, points to 'buffer' */
+	duk_lexer_codepoint buffer[DUK_LEXER_BUFFER_SIZE];
+#else
+	duk_lexer_codepoint window[DUK_LEXER_WINDOW_SIZE]; /* unicode code points, window[0] is always next */
+#endif
+
 	duk_hthread *thr;                              /* thread; minimizes argument passing */
 
 	const duk_uint8_t *input;                      /* input string (may be a user pointer) */
 	duk_size_t input_length;                       /* input byte length */
 	duk_size_t input_offset;                       /* input offset for window leading edge (not window[0]) */
-
-	duk_codepoint_t window[DUK_LEXER_WINDOW_SIZE]; /* window of unicode code points */
-	duk_size_t offsets[DUK_LEXER_WINDOW_SIZE];     /* input byte offset for each char */
-	duk_int_t lines[DUK_LEXER_WINDOW_SIZE];        /* input lines for each char */
 	duk_int_t input_line;                          /* input linenumber at input_offset (not window[0]), init to 1 */
+
 	duk_idx_t slot1_idx;                           /* valstack slot for 1st token value */
 	duk_idx_t slot2_idx;                           /* valstack slot for 2nd token value */
 	duk_idx_t buf_idx;                             /* valstack slot for temp buffer */
-	duk_hbuffer_dynamic *buf;                      /* temp accumulation buffer (on valstack) */
+	duk_hbuffer_dynamic *buf;                      /* temp accumulation buffer */
+	duk_bufwriter_ctx bw;                          /* bufwriter for temp accumulation */
 
 	duk_int_t token_count;                         /* number of tokens parsed */
 	duk_int_t token_limit;                         /* maximum token count before error (sanity backstop) */
@@ -4363,17 +5835,18 @@ struct duk_lexer_ctx {
  *  Prototypes
  */
 
-void duk_lexer_initctx(duk_lexer_ctx *lex_ctx);
+DUK_INTERNAL_DECL void duk_lexer_initctx(duk_lexer_ctx *lex_ctx);
 
-void duk_lexer_setpoint(duk_lexer_ctx *lex_ctx, duk_lexer_point *pt);
+DUK_INTERNAL_DECL void duk_lexer_setpoint(duk_lexer_ctx *lex_ctx, duk_lexer_point *pt);
 
+DUK_INTERNAL_DECL
 void duk_lexer_parse_js_input_element(duk_lexer_ctx *lex_ctx,
                                       duk_token *out_token,
                                       duk_bool_t strict_mode,
                                       duk_bool_t regexp_mode);
 #ifdef DUK_USE_REGEXP_SUPPORT
-void duk_lexer_parse_re_token(duk_lexer_ctx *lex_ctx, duk_re_token *out_token);
-void duk_lexer_parse_re_ranges(duk_lexer_ctx *lex_ctx, duk_re_range_callback gen_range, void *userdata);
+DUK_INTERNAL_DECL void duk_lexer_parse_re_token(duk_lexer_ctx *lex_ctx, duk_re_token *out_token);
+DUK_INTERNAL_DECL void duk_lexer_parse_re_ranges(duk_lexer_ctx *lex_ctx, duk_re_range_callback gen_range, void *userdata);
 #endif  /* DUK_USE_REGEXP_SUPPORT */
 
 #endif  /* DUK_LEXER_H_INCLUDED */
@@ -4386,11 +5859,6 @@ void duk_lexer_parse_re_ranges(duk_lexer_ctx *lex_ctx, duk_re_range_callback gen
 #define DUK_JS_COMPILER_H_INCLUDED
 
 /* ecmascript compiler limits */
-#if defined(DUK_USE_DEEP_C_STACK)
-#define DUK_COMPILER_RECURSION_LIMIT       2500L
-#else
-#define DUK_COMPILER_RECURSION_LIMIT       50L
-#endif
 #define DUK_COMPILER_TOKEN_LIMIT           100000000L  /* 1e8: protects against deeply nested inner functions */
 
 /* maximum loopcount for peephole optimization */
@@ -4410,8 +5878,9 @@ void duk_lexer_parse_re_ranges(duk_lexer_ctx *lex_ctx, duk_re_range_callback gen
 #define DUK_IVAL_NONE          0   /* no value */
 #define DUK_IVAL_PLAIN         1   /* register, constant, or value */
 #define DUK_IVAL_ARITH         2   /* binary arithmetic; DUK_OP_ADD, DUK_OP_EQ, other binary ops */
-#define DUK_IVAL_PROP          3   /* property access */
-#define DUK_IVAL_VAR           4   /* variable access */
+#define DUK_IVAL_ARITH_EXTRAOP 3   /* binary arithmetic using extraops; DUK_EXTRAOP_INSTOF etc */
+#define DUK_IVAL_PROP          4   /* property access */
+#define DUK_IVAL_VAR           5   /* variable access */
 
 #define DUK_ISPEC_NONE         0   /* no value */
 #define DUK_ISPEC_VALUE        1   /* value resides in 'valstack_idx' */
@@ -4442,7 +5911,7 @@ typedef struct {
 
 	/* XXX: can be optimized for smaller footprint esp. on 32-bit environments */
 	duk_small_uint_t t;          /* DUK_IVAL_XXX */
-	duk_small_uint_t op;         /* bytecode opcode for binary ops */
+	duk_small_uint_t op;         /* bytecode opcode (or extraop) for binary ops */
 	duk_ispec x1;
 	duk_ispec x2;
 } duk_ivalue;
@@ -4495,8 +5964,10 @@ struct duk_compiler_func {
 	 * platforms (e.g. if int is 32 bits and pointers are 64 bits).
 	 */
 
+	duk_bufwriter_ctx bw_code;          /* bufwriter for code */
+
 	duk_hstring *h_name;                /* function name (borrowed reference), ends up in _name */
-	duk_hbuffer_dynamic *h_code;        /* C array of duk_compiler_instr */
+	/* h_code: held in bw_code */
 	duk_hobject *h_consts;              /* array */
 	duk_hobject *h_funcs;               /* array of function templates: [func1, offset1, line1, func2, offset2, line2]
 	                                     * offset/line points to closing brace to allow skipping on pass 2
@@ -4507,11 +5978,11 @@ struct duk_compiler_func {
 	                                     */
 	duk_hobject *h_labelnames;          /* array of active label names */
 	duk_hbuffer_dynamic *h_labelinfos;  /* C array of duk_labelinfo */
-	duk_hobject *h_argnames;            /* array of formal argument names (-> _formals) */
+	duk_hobject *h_argnames;            /* array of formal argument names (-> _Formals) */
 	duk_hobject *h_varmap;              /* variable map for pass 2 (identifier -> register number or null (unmapped)) */
 
 	/* value stack indices for tracking objects */
-	duk_idx_t code_idx;
+	/* code_idx: not needed */
 	duk_idx_t consts_idx;
 	duk_idx_t funcs_idx;
 	duk_idx_t decls_idx;
@@ -4545,6 +6016,10 @@ struct duk_compiler_func {
 	duk_int_t fnum_next;                /* inner function numbering */
 	duk_int_t num_formals;              /* number of formal arguments */
 	duk_reg_t reg_stmt_value;           /* register for writing value of 'non-empty' statements (global or eval code), -1 is marker */
+#if defined(DUK_USE_DEBUGGER_SUPPORT)
+	duk_int_t min_line;                 /* XXX: typing (duk_hcompiledfunction has duk_uint32_t) */
+	duk_int_t max_line;
+#endif
 
 	/* status booleans */
 	duk_bool_t is_function;             /* is an actual function (not global/eval code) */
@@ -4553,7 +6028,7 @@ struct duk_compiler_func {
 	duk_bool_t is_setget;               /* is a setter/getter */
 	duk_bool_t is_decl;                 /* is a function declaration (as opposed to function expression) */
 	duk_bool_t is_strict;               /* function is strict */
-	duk_bool_t is_notail;               /* function must not be tailcalled */
+	duk_bool_t is_notail;               /* function must not be tail called */
 	duk_bool_t in_directive_prologue;   /* parsing in "directive prologue", recognize directives */
 	duk_bool_t in_scanning;             /* parsing in "scanning" phase (first pass) */
 	duk_bool_t may_direct_eval;         /* function may call direct eval */
@@ -4585,6 +6060,9 @@ struct duk_compiler_ctx {
 	duk_int_t recursion_depth;
 	duk_int_t recursion_limit;
 
+	/* code emission temporary */
+	duk_int_t emit_jumpslot_pc;
+
 	/* current function being compiled (embedded instead of pointer for more compact access) */
 	duk_compiler_func curr_func;
 };
@@ -4593,11 +6071,11 @@ struct duk_compiler_ctx {
  *  Prototypes
  */
 
-#define DUK_JS_COMPILE_FLAG_EVAL      (1 << 0)  /* source is eval code (not program) */
+#define DUK_JS_COMPILE_FLAG_EVAL      (1 << 0)  /* source is eval code (not global) */
 #define DUK_JS_COMPILE_FLAG_STRICT    (1 << 1)  /* strict outer context */
 #define DUK_JS_COMPILE_FLAG_FUNCEXPR  (1 << 2)  /* source is a function expression (used for Function constructor) */
 
-void duk_js_compile(duk_hthread *thr, const duk_uint8_t *src_buffer, duk_size_t src_length, duk_small_uint_t flags);
+DUK_INTERNAL_DECL void duk_js_compile(duk_hthread *thr, const duk_uint8_t *src_buffer, duk_size_t src_length, duk_small_uint_t flags);
 
 #endif  /* DUK_JS_COMPILER_H_INCLUDED */
 #line 1 "duk_regexp.h"
@@ -4612,19 +6090,9 @@ void duk_js_compile(duk_hthread *thr, const duk_uint8_t *src_buffer, duk_size_t
 #define DUK_RE_MAX_ATOM_COPIES             1000
 
 /* regexp compilation limits */
-#if defined(DUK_USE_DEEP_C_STACK)
-#define DUK_RE_COMPILE_RECURSION_LIMIT     1000
-#else
-#define DUK_RE_COMPILE_RECURSION_LIMIT     100
-#endif
 #define DUK_RE_COMPILE_TOKEN_LIMIT         100000000L   /* 1e8 */
 
 /* regexp execution limits */
-#if defined(DUK_USE_DEEP_C_STACK)
-#define DUK_RE_EXECUTE_RECURSION_LIMIT     1000
-#else
-#define DUK_RE_EXECUTE_RECURSION_LIMIT     100
-#endif
 #define DUK_RE_EXECUTE_STEPS_LIMIT         1000000000L  /* 1e9 */
 
 /* regexp opcodes */
@@ -4657,11 +6125,11 @@ struct duk_re_matcher_ctx {
 	duk_hthread *thr;
 
 	duk_uint32_t re_flags;
-	duk_uint8_t *input;
-	duk_uint8_t *input_end;
-	duk_uint8_t *bytecode;
-	duk_uint8_t *bytecode_end;
-	duk_uint8_t **saved;		/* allocated from valstack (fixed buffer) */
+	const duk_uint8_t *input;
+	const duk_uint8_t *input_end;
+	const duk_uint8_t *bytecode;
+	const duk_uint8_t *bytecode_end;
+	const duk_uint8_t **saved;  /* allocated from valstack (fixed buffer) */
 	duk_uint32_t nsaved;
 	duk_uint32_t recursion_depth;
 	duk_uint32_t recursion_limit;
@@ -4675,25 +6143,24 @@ struct duk_re_compiler_ctx {
 	duk_uint32_t re_flags;
 	duk_lexer_ctx lex;
 	duk_re_token curr_token;
-	duk_hbuffer_dynamic *buf;
+	duk_bufwriter_ctx bw;
 	duk_uint32_t captures;  /* highest capture number emitted so far (used as: ++captures) */
 	duk_uint32_t highest_backref;
 	duk_uint32_t recursion_depth;
 	duk_uint32_t recursion_limit;
-	duk_uint32_t nranges;	/* internal temporary value, used for char classes */
+	duk_uint32_t nranges;  /* internal temporary value, used for char classes */
 };
 
 /*
  *  Prototypes
  */
 
-void duk_regexp_compile(duk_hthread *thr);
-void duk_regexp_create_instance(duk_hthread *thr);
-void duk_regexp_match(duk_hthread *thr);
-void duk_regexp_match_force_global(duk_hthread *thr);  /* hacky helper for String.prototype.split() */
+DUK_INTERNAL_DECL void duk_regexp_compile(duk_hthread *thr);
+DUK_INTERNAL_DECL void duk_regexp_create_instance(duk_hthread *thr);
+DUK_INTERNAL_DECL void duk_regexp_match(duk_hthread *thr);
+DUK_INTERNAL_DECL void duk_regexp_match_force_global(duk_hthread *thr);  /* hacky helper for String.prototype.split() */
 
 #endif  /* DUK_REGEXP_H_INCLUDED */
-
 #line 1 "duk_tval.h"
 /*
  *  Tagged type definition (duk_tval) and accessor macros.
@@ -4708,7 +6175,7 @@ void duk_regexp_match_force_global(duk_hthread *thr);  /* hacky helper for Strin
  *
  *  Selecting the tagged type format involves many trade-offs (memory
  *  use, size and performance of generated code, portability, etc),
- *  see doc/types.txt for a detailed discussion (especially of how the
+ *  see doc/types.rst for a detailed discussion (especially of how the
  *  IEEE double format is used to pack tagged values).
  *
  *  NB: because macro arguments are often expressions, macros should
@@ -4730,52 +6197,29 @@ void duk_regexp_match_force_global(duk_hthread *thr);  /* hacky helper for Strin
  *  Packed 8-byte representation
  */
 
-/* sanity */
-#if !defined(DUK_USE_PACKED_TVAL_POSSIBLE)
-#error packed representation not supported
-#endif
-
 /* use duk_double_union as duk_tval directly */
 typedef union duk_double_union duk_tval;
 
 /* tags */
 #define DUK_TAG_NORMALIZED_NAN    0x7ff8UL   /* the NaN variant we use */
 /* avoid tag 0xfff0, no risk of confusion with negative infinity */
-#define DUK_TAG_UNDEFINED         0xfff1UL   /* embed: 0 or 1 (normal or unused) */
-#define DUK_TAG_NULL              0xfff2UL   /* embed: nothing */
-#define DUK_TAG_BOOLEAN           0xfff3UL   /* embed: 0 or 1 (false or true) */
+#if defined(DUK_USE_FASTINT)
+#define DUK_TAG_FASTINT           0xfff1UL   /* embed: integer value */
+#endif
+#define DUK_TAG_UNUSED            0xfff2UL   /* marker; not actual tagged value */
+#define DUK_TAG_UNDEFINED         0xfff3UL   /* embed: nothing */
+#define DUK_TAG_NULL              0xfff4UL   /* embed: nothing */
+#define DUK_TAG_BOOLEAN           0xfff5UL   /* embed: 0 or 1 (false or true) */
 /* DUK_TAG_NUMBER would logically go here, but it has multiple 'tags' */
-#define DUK_TAG_POINTER           0xfff4UL   /* embed: void ptr */
-#define DUK_TAG_STRING            0xfff5UL   /* embed: duk_hstring ptr */
-#define DUK_TAG_OBJECT            0xfff6UL   /* embed: duk_hobject ptr */
-#define DUK_TAG_BUFFER            0xfff7UL   /* embed: duk_hbuffer ptr */
+#define DUK_TAG_POINTER           0xfff6UL   /* embed: void ptr */
+#define DUK_TAG_LIGHTFUNC         0xfff7UL   /* embed: func ptr */
+#define DUK_TAG_STRING            0xfff8UL   /* embed: duk_hstring ptr */
+#define DUK_TAG_OBJECT            0xfff9UL   /* embed: duk_hobject ptr */
+#define DUK_TAG_BUFFER            0xfffaUL   /* embed: duk_hbuffer ptr */
 
 /* for convenience */
-#define DUK_XTAG_UNDEFINED_ACTUAL 0xfff10000UL
-#define DUK_XTAG_UNDEFINED_UNUSED 0xfff10001UL
-#define DUK_XTAG_NULL             0xfff20000UL
-#define DUK_XTAG_BOOLEAN_FALSE    0xfff30000UL
-#define DUK_XTAG_BOOLEAN_TRUE     0xfff30001UL
-
-#define DUK__TVAL_SET_UNDEFINED_ACTUAL_FULL(v)      DUK_DBLUNION_SET_HIGH32_ZERO_LOW32((v), DUK_XTAG_UNDEFINED_ACTUAL)
-#define DUK__TVAL_SET_UNDEFINED_ACTUAL_NOTFULL(v)   DUK_DBLUNION_SET_HIGH32((v), DUK_XTAG_UNDEFINED_ACTUAL)
-#define DUK__TVAL_SET_UNDEFINED_UNUSED_FULL(v)      DUK_DBLUNION_SET_HIGH32_ZERO_LOW32((v), DUK_XTAG_UNDEFINED_UNUSED)
-#define DUK__TVAL_SET_UNDEFINED_UNUSED_NOTFULL(v)   DUK_DBLUNION_SET_HIGH32((v), DUK_XTAG_UNDEFINED_UNUSED)
-
-/* Note: 16-bit initializer suffices (unlike for undefined/boolean) */
-#define DUK__TVAL_SET_NULL_FULL(v)     DUK_DBLUNION_SET_HIGH32_ZERO_LOW32((v), DUK_XTAG_NULL)
-#define DUK__TVAL_SET_NULL_NOTFULL(v)  do { \
-		(v)->us[DUK_DBL_IDX_US0] = (duk_uint16_t) DUK_TAG_NULL; \
-	} while (0)
-
-#define DUK__TVAL_SET_BOOLEAN_FULL(v,val)    DUK_DBLUNION_SET_HIGH32_ZERO_LOW32((v), (((duk_uint32_t) DUK_TAG_BOOLEAN) << 16) | ((duk_uint32_t) val))
-#define DUK__TVAL_SET_BOOLEAN_NOTFULL(v,val) DUK_DBLUNION_SET_HIGH32((v), (((duk_uint32_t) DUK_TAG_BOOLEAN) << 16) | ((duk_uint32_t) (val)))
-
-/* assumes that caller has normalized a possible NaN value of 'val', otherwise trouble ahead;
- * no notfull variant
- */
-#define DUK__TVAL_SET_NUMBER_FULL(v,val)     DUK_DBLUNION_SET_DOUBLE((v), (val))
-#define DUK__TVAL_SET_NUMBER_NOTFULL(v,val)  DUK_DBLUNION_SET_DOUBLE((v), (val))
+#define DUK_XTAG_BOOLEAN_FALSE    0xfff50000UL
+#define DUK_XTAG_BOOLEAN_TRUE     0xfff50001UL
 
 /* two casts to avoid gcc warning: "warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]" */
 #ifdef DUK_USE_64BIT_OPS
@@ -4795,33 +6239,137 @@ typedef union duk_double_union duk_tval;
 	} while (0)
 #endif  /* DUK_USE_64BIT_OPS */
 
-/* select actual setters */
-#ifdef DUK_USE_FULL_TVAL
-#define DUK_TVAL_SET_UNDEFINED_ACTUAL(v)    DUK__TVAL_SET_UNDEFINED_ACTUAL_FULL((v))
-#define DUK_TVAL_SET_UNDEFINED_UNUSED(v)    DUK__TVAL_SET_UNDEFINED_UNUSED_FULL((v))
-#define DUK_TVAL_SET_NULL(v)                DUK__TVAL_SET_NULL_FULL((v))
-#define DUK_TVAL_SET_BOOLEAN(v,i)           DUK__TVAL_SET_BOOLEAN_FULL((v),(i))
-#define DUK_TVAL_SET_NUMBER(v,d)            DUK__TVAL_SET_NUMBER_FULL((v),(d))
-#define DUK_TVAL_SET_NAN(v)                 DUK__TVAL_SET_NAN_FULL((v))
+#ifdef DUK_USE_64BIT_OPS
+/* Double casting for pointer to avoid gcc warning (cast from pointer to integer of different size) */
+#ifdef DUK_USE_DOUBLE_ME
+#define DUK__TVAL_SET_LIGHTFUNC(v,fp,flags)  do { \
+		(v)->ull[DUK_DBL_IDX_ULL0] = (((duk_uint64_t) DUK_TAG_LIGHTFUNC) << 16) | \
+		                             ((duk_uint64_t) (flags)) | \
+		                             (((duk_uint64_t) (duk_uint32_t) (fp)) << 32); \
+	} while (0)
 #else
-#define DUK_TVAL_SET_UNDEFINED_ACTUAL(v)    DUK__TVAL_SET_UNDEFINED_ACTUAL_NOTFULL((v))
-#define DUK_TVAL_SET_UNDEFINED_UNUSED(v)    DUK__TVAL_SET_UNDEFINED_UNUSED_NOTFULL((v))
-#define DUK_TVAL_SET_NULL(v)                DUK__TVAL_SET_NULL_NOTFULL((v))
-#define DUK_TVAL_SET_BOOLEAN(v,i)           DUK__TVAL_SET_BOOLEAN_NOTFULL((v),(i))
-#define DUK_TVAL_SET_NUMBER(v,d)            DUK__TVAL_SET_NUMBER_NOTFULL((v),(d))
-#define DUK_TVAL_SET_NAN(v)                 DUK__TVAL_SET_NAN_NOTFULL((v))
+#define DUK__TVAL_SET_LIGHTFUNC(v,fp,flags)  do { \
+		(v)->ull[DUK_DBL_IDX_ULL0] = (((duk_uint64_t) DUK_TAG_LIGHTFUNC) << 48) | \
+		                             (((duk_uint64_t) (flags)) << 32) | \
+		                             ((duk_uint64_t) (duk_uint32_t) (fp)); \
+	} while (0)
 #endif
+#else  /* DUK_USE_64BIT_OPS */
+#define DUK__TVAL_SET_LIGHTFUNC(v,fp,flags)  do { \
+		(v)->ui[DUK_DBL_IDX_UI0] = (((duk_uint32_t) DUK_TAG_LIGHTFUNC) << 16) | ((duk_uint32_t) (flags)); \
+		(v)->ui[DUK_DBL_IDX_UI1] = (duk_uint32_t) (fp); \
+	} while (0)
+#endif  /* DUK_USE_64BIT_OPS */
 
-#define DUK_TVAL_SET_STRING(v,h)            DUK__TVAL_SET_TAGGEDPOINTER((v),(h),DUK_TAG_STRING)
-#define DUK_TVAL_SET_OBJECT(v,h)            DUK__TVAL_SET_TAGGEDPOINTER((v),(h),DUK_TAG_OBJECT)
-#define DUK_TVAL_SET_BUFFER(v,h)            DUK__TVAL_SET_TAGGEDPOINTER((v),(h),DUK_TAG_BUFFER)
-#define DUK_TVAL_SET_POINTER(v,p)           DUK__TVAL_SET_TAGGEDPOINTER((v),(p),DUK_TAG_POINTER)
+#if defined(DUK_USE_FASTINT)
+/* Note: masking is done for 'i' to deal with negative numbers correctly */
+#ifdef DUK_USE_DOUBLE_ME
+#define DUK__TVAL_SET_FASTINT(v,i)  do { \
+		(v)->ui[DUK_DBL_IDX_UI0] = ((duk_uint32_t) DUK_TAG_FASTINT) << 16 | (((duk_uint32_t) ((i) >> 32)) & 0x0000ffffUL); \
+		(v)->ui[DUK_DBL_IDX_UI1] = (duk_uint32_t) (i); \
+	} while (0)
+#define DUK__TVAL_SET_FASTINT_U32(v,i)  do { \
+		(v)->ui[DUK_DBL_IDX_UI0] = ((duk_uint32_t) DUK_TAG_FASTINT) << 16; \
+		(v)->ui[DUK_DBL_IDX_UI1] = (duk_uint32_t) (i); \
+	} while (0)
+#else
+#define DUK__TVAL_SET_FASTINT(v,i)  do { \
+		(v)->ull[DUK_DBL_IDX_ULL0] = (((duk_uint64_t) DUK_TAG_FASTINT) << 48) | (((duk_uint64_t) (i)) & 0x0000ffffffffffffULL); \
+	} while (0)
+#define DUK__TVAL_SET_FASTINT_U32(v,i)  do { \
+		(v)->ull[DUK_DBL_IDX_ULL0] = (((duk_uint64_t) DUK_TAG_FASTINT) << 48) | (duk_uint64_t) (i); \
+	} while (0)
+#endif
+
+#define DUK__TVAL_SET_FASTINT_I32(v,i)  do { \
+		duk_int64_t duk__tmp = (duk_int64_t) (i); \
+		DUK_TVAL_SET_FASTINT((v), duk__tmp); \
+	} while (0)
+
+/* XXX: clumsy sign extend and masking of 16 topmost bits */
+#ifdef DUK_USE_DOUBLE_ME
+#define DUK__TVAL_GET_FASTINT(v)      (((duk_int64_t) ((((duk_uint64_t) (v)->ui[DUK_DBL_IDX_UI0]) << 32) | ((duk_uint64_t) (v)->ui[DUK_DBL_IDX_UI1]))) << 16 >> 16)
+#else
+#define DUK__TVAL_GET_FASTINT(v)      ((((duk_int64_t) (v)->ull[DUK_DBL_IDX_ULL0]) << 16) >> 16)
+#endif
+#define DUK__TVAL_GET_FASTINT_U32(v)  ((v)->ui[DUK_DBL_IDX_UI1])
+#define DUK__TVAL_GET_FASTINT_I32(v)  ((duk_int32_t) (v)->ui[DUK_DBL_IDX_UI1])
+#endif  /* DUK_USE_FASTINT */
+
+#define DUK_TVAL_SET_UNDEFINED(v)  do { \
+		(v)->us[DUK_DBL_IDX_US0] = (duk_uint16_t) DUK_TAG_UNDEFINED; \
+	} while (0)
+#define DUK_TVAL_SET_UNUSED(v)  do { \
+		(v)->us[DUK_DBL_IDX_US0] = (duk_uint16_t) DUK_TAG_UNUSED; \
+	} while (0)
+#define DUK_TVAL_SET_NULL(v)  do { \
+		(v)->us[DUK_DBL_IDX_US0] = (duk_uint16_t) DUK_TAG_NULL; \
+	} while (0)
+
+#define DUK_TVAL_SET_BOOLEAN(v,val)         DUK_DBLUNION_SET_HIGH32((v), (((duk_uint32_t) DUK_TAG_BOOLEAN) << 16) | ((duk_uint32_t) (val)))
+
+#define DUK_TVAL_SET_NAN(v)                 DUK_DBLUNION_SET_NAN_FULL((v))
+
+/* Assumes that caller has normalized NaNs, otherwise trouble ahead. */
+#if defined(DUK_USE_FASTINT)
+#define DUK_TVAL_SET_DOUBLE(v,d)  do { \
+		duk_double_t duk__dblval; \
+		duk__dblval = (d); \
+		DUK_ASSERT_DOUBLE_IS_NORMALIZED(duk__dblval); \
+		DUK_DBLUNION_SET_DOUBLE((v), duk__dblval); \
+	} while (0)
+#define DUK_TVAL_SET_FASTINT(v,i)           DUK__TVAL_SET_FASTINT((v), (i))
+#define DUK_TVAL_SET_FASTINT_I32(v,i)       DUK__TVAL_SET_FASTINT_I32((v), (i))
+#define DUK_TVAL_SET_FASTINT_U32(v,i)       DUK__TVAL_SET_FASTINT_U32((v), (i))
+#define DUK_TVAL_SET_NUMBER_CHKFAST(v,d)    duk_tval_set_number_chkfast((v), (d))
+#define DUK_TVAL_SET_NUMBER(v,d)            DUK_TVAL_SET_DOUBLE((v), (d))
+#define DUK_TVAL_CHKFAST_INPLACE(v)  do { \
+		duk_tval *duk__tv; \
+		duk_double_t duk__d; \
+		duk__tv = (v); \
+		if (DUK_TVAL_IS_DOUBLE(duk__tv)) { \
+			duk__d = DUK_TVAL_GET_DOUBLE(duk__tv); \
+			DUK_TVAL_SET_NUMBER_CHKFAST(duk__tv, duk__d); \
+		} \
+	} while (0)
+#else
+#define DUK_TVAL_SET_DOUBLE(v,d)  do { \
+		duk_double_t duk__dblval; \
+		duk__dblval = (d); \
+		DUK_ASSERT_DOUBLE_IS_NORMALIZED(duk__dblval); \
+		DUK_DBLUNION_SET_DOUBLE((v), duk__dblval); \
+	} while (0)
+#define DUK_TVAL_SET_NUMBER_CHKFAST(v,d)    DUK_TVAL_SET_DOUBLE((v), (d))
+#define DUK_TVAL_SET_NUMBER(v,d)            DUK_TVAL_SET_DOUBLE((v), (d))
+#define DUK_TVAL_CHKFAST_INPLACE(v)  do { } while (0)
+#endif
+
+#define DUK_TVAL_SET_LIGHTFUNC(v,fp,flags)  DUK__TVAL_SET_LIGHTFUNC((v), (fp), (flags))
+#define DUK_TVAL_SET_STRING(v,h)            DUK__TVAL_SET_TAGGEDPOINTER((v), (h), DUK_TAG_STRING)
+#define DUK_TVAL_SET_OBJECT(v,h)            DUK__TVAL_SET_TAGGEDPOINTER((v), (h), DUK_TAG_OBJECT)
+#define DUK_TVAL_SET_BUFFER(v,h)            DUK__TVAL_SET_TAGGEDPOINTER((v), (h), DUK_TAG_BUFFER)
+#define DUK_TVAL_SET_POINTER(v,p)           DUK__TVAL_SET_TAGGEDPOINTER((v), (p), DUK_TAG_POINTER)
 
 #define DUK_TVAL_SET_TVAL(v,x)              do { *(v) = *(x); } while (0)
 
 /* getters */
 #define DUK_TVAL_GET_BOOLEAN(v)             ((int) (v)->us[DUK_DBL_IDX_US1])
+#if defined(DUK_USE_FASTINT)
+#define DUK_TVAL_GET_DOUBLE(v)              ((v)->d)
+#define DUK_TVAL_GET_FASTINT(v)             DUK__TVAL_GET_FASTINT((v))
+#define DUK_TVAL_GET_FASTINT_U32(v)         DUK__TVAL_GET_FASTINT_U32((v))
+#define DUK_TVAL_GET_FASTINT_I32(v)         DUK__TVAL_GET_FASTINT_I32((v))
+#define DUK_TVAL_GET_NUMBER(v)              duk_tval_get_number_packed((v))
+#else
 #define DUK_TVAL_GET_NUMBER(v)              ((v)->d)
+#define DUK_TVAL_GET_DOUBLE(v)              ((v)->d)
+#endif
+#define DUK_TVAL_GET_LIGHTFUNC(v,out_fp,out_flags)  do { \
+		(out_flags) = (v)->ui[DUK_DBL_IDX_UI0] & 0xffffUL; \
+		(out_fp) = (duk_c_function) (v)->ui[DUK_DBL_IDX_UI1]; \
+	} while (0)
+#define DUK_TVAL_GET_LIGHTFUNC_FUNCPTR(v)   ((duk_c_function) ((v)->ui[DUK_DBL_IDX_UI1]))
+#define DUK_TVAL_GET_LIGHTFUNC_FLAGS(v)     (((int) (v)->ui[DUK_DBL_IDX_UI0]) & 0xffffUL)
 #define DUK_TVAL_GET_STRING(v)              ((duk_hstring *) (v)->vp[DUK_DBL_IDX_VP1])
 #define DUK_TVAL_GET_OBJECT(v)              ((duk_hobject *) (v)->vp[DUK_DBL_IDX_VP1])
 #define DUK_TVAL_GET_BUFFER(v)              ((duk_hbuffer *) (v)->vp[DUK_DBL_IDX_VP1])
@@ -4832,21 +6380,33 @@ typedef union duk_double_union duk_tval;
 #define DUK_TVAL_GET_TAG(v)                 ((duk_small_uint_t) (v)->us[DUK_DBL_IDX_US0])
 
 #define DUK_TVAL_IS_UNDEFINED(v)            (DUK_TVAL_GET_TAG((v)) == DUK_TAG_UNDEFINED)
-#define DUK_TVAL_IS_UNDEFINED_ACTUAL(v)     ((v)->ui[DUK_DBL_IDX_UI0] == DUK_XTAG_UNDEFINED_ACTUAL)
-#define DUK_TVAL_IS_UNDEFINED_UNUSED(v)     ((v)->ui[DUK_DBL_IDX_UI0] == DUK_XTAG_UNDEFINED_UNUSED)
+#define DUK_TVAL_IS_UNUSED(v)               (DUK_TVAL_GET_TAG((v)) == DUK_TAG_UNUSED)
 #define DUK_TVAL_IS_NULL(v)                 (DUK_TVAL_GET_TAG((v)) == DUK_TAG_NULL)
 #define DUK_TVAL_IS_BOOLEAN(v)              (DUK_TVAL_GET_TAG((v)) == DUK_TAG_BOOLEAN)
 #define DUK_TVAL_IS_BOOLEAN_TRUE(v)         ((v)->ui[DUK_DBL_IDX_UI0] == DUK_XTAG_BOOLEAN_TRUE)
 #define DUK_TVAL_IS_BOOLEAN_FALSE(v)        ((v)->ui[DUK_DBL_IDX_UI0] == DUK_XTAG_BOOLEAN_FALSE)
+#define DUK_TVAL_IS_LIGHTFUNC(v)            (DUK_TVAL_GET_TAG((v)) == DUK_TAG_LIGHTFUNC)
 #define DUK_TVAL_IS_STRING(v)               (DUK_TVAL_GET_TAG((v)) == DUK_TAG_STRING)
 #define DUK_TVAL_IS_OBJECT(v)               (DUK_TVAL_GET_TAG((v)) == DUK_TAG_OBJECT)
 #define DUK_TVAL_IS_BUFFER(v)               (DUK_TVAL_GET_TAG((v)) == DUK_TAG_BUFFER)
 #define DUK_TVAL_IS_POINTER(v)              (DUK_TVAL_GET_TAG((v)) == DUK_TAG_POINTER)
+#if defined(DUK_USE_FASTINT)
 /* 0xfff0 is -Infinity */
+#define DUK_TVAL_IS_DOUBLE(v)               (DUK_TVAL_GET_TAG((v)) <= 0xfff0UL)
+#define DUK_TVAL_IS_FASTINT(v)              (DUK_TVAL_GET_TAG((v)) == DUK_TAG_FASTINT)
+#define DUK_TVAL_IS_NUMBER(v)               (DUK_TVAL_GET_TAG((v)) <= 0xfff1UL)
+#else
 #define DUK_TVAL_IS_NUMBER(v)               (DUK_TVAL_GET_TAG((v)) <= 0xfff0UL)
+#define DUK_TVAL_IS_DOUBLE(v)               DUK_TVAL_IS_NUMBER((v))
+#endif
 
+/* This is performance critical because it appears in every DECREF. */
 #define DUK_TVAL_IS_HEAP_ALLOCATED(v)       (DUK_TVAL_GET_TAG((v)) >= DUK_TAG_STRING)
 
+#if defined(DUK_USE_FASTINT)
+DUK_INTERNAL_DECL duk_double_t duk_tval_get_number_packed(duk_tval *tv);
+#endif
+
 #else  /* DUK_USE_PACKED_TVAL */
 /* ======================================================================== */
 
@@ -4854,17 +6414,25 @@ typedef union duk_double_union duk_tval;
  *  Portable 12-byte representation
  */
 
-#ifdef DUK_USE_FULL_TVAL
-#error no 'full' tagged values in 12-byte representation
-#endif
+/* Note: not initializing all bytes is normally not an issue: Duktape won't
+ * read or use the uninitialized bytes so valgrind won't issue warnings.
+ * In some special cases a harmless valgrind warning may be issued though.
+ * For example, the DumpHeap debugger command writes out a compiled function's
+ * 'data' area as is, including any uninitialized bytes, which causes a
+ * valgrind warning.
+ */
 
 typedef struct duk_tval_struct duk_tval;
 
 struct duk_tval_struct {
 	duk_small_uint_t t;
+	duk_small_uint_t v_extra;
 	union {
 		duk_double_t d;
 		duk_small_int_t i;
+#if defined(DUK_USE_FASTINT)
+		duk_int64_t fi;  /* if present, forces 16-byte duk_tval */
+#endif
 		void *voidptr;
 		duk_hstring *hstring;
 		duk_hobject *hobject;
@@ -4873,17 +6441,23 @@ struct duk_tval_struct {
 		duk_hthread *hthread;
 		duk_hbuffer *hbuffer;
 		duk_heaphdr *heaphdr;
+		duk_c_function lightfunc;
 	} v;
 };
 
 #define DUK__TAG_NUMBER               0  /* not exposed */
-#define DUK_TAG_UNDEFINED             1
-#define DUK_TAG_NULL                  2
-#define DUK_TAG_BOOLEAN               3
-#define DUK_TAG_POINTER               4
-#define DUK_TAG_STRING                5
-#define DUK_TAG_OBJECT                6
-#define DUK_TAG_BUFFER                7
+#if defined(DUK_USE_FASTINT)
+#define DUK_TAG_FASTINT               1
+#endif
+#define DUK_TAG_UNDEFINED             2
+#define DUK_TAG_NULL                  3
+#define DUK_TAG_BOOLEAN               4
+#define DUK_TAG_POINTER               5
+#define DUK_TAG_LIGHTFUNC             6
+#define DUK_TAG_UNUSED                7  /* marker; not actual tagged type */
+#define DUK_TAG_STRING                8  /* first heap allocated, match bit boundary */
+#define DUK_TAG_OBJECT                9
+#define DUK_TAG_BUFFER                10
 
 /* DUK__TAG_NUMBER is intentionally first, as it is the default clause in code
  * to support the 8-byte representation.  Further, it is a non-heap-allocated
@@ -4892,14 +6466,12 @@ struct duk_tval_struct {
  */
 
 /* setters */
-#define DUK_TVAL_SET_UNDEFINED_ACTUAL(tv)  do { \
+#define DUK_TVAL_SET_UNDEFINED(tv)  do { \
 		(tv)->t = DUK_TAG_UNDEFINED; \
-		(tv)->v.i = 0; \
 	} while (0)
 
-#define DUK_TVAL_SET_UNDEFINED_UNUSED(tv)  do { \
-		(tv)->t = DUK_TAG_UNDEFINED; \
-		(tv)->v.i = 1; \
+#define DUK_TVAL_SET_UNUSED(tv)  do { \
+		(tv)->t = DUK_TAG_UNUSED; \
 	} while (0)
 
 #define DUK_TVAL_SET_NULL(tv)  do { \
@@ -4911,10 +6483,58 @@ struct duk_tval_struct {
 		(tv)->v.i = (val); \
 	} while (0)
 
+#if defined(DUK_USE_FASTINT)
+#define DUK_TVAL_SET_DOUBLE(tv,val)  do { \
+		(tv)->t = DUK__TAG_NUMBER; \
+		(tv)->v.d = (val); \
+	} while (0)
+#define DUK_TVAL_SET_FASTINT(tv,val)  do { \
+		(tv)->t = DUK_TAG_FASTINT; \
+		(tv)->v.fi = (val); \
+	} while (0)
+#define DUK_TVAL_SET_FASTINT_U32(tv,val)  do { \
+		(tv)->t = DUK_TAG_FASTINT; \
+		(tv)->v.fi = (duk_int64_t) (val); \
+	} while (0)
+#define DUK_TVAL_SET_FASTINT_I32(tv,val)  do { \
+		(tv)->t = DUK_TAG_FASTINT; \
+		(tv)->v.fi = (duk_int64_t) (val); \
+	} while (0)
+#define DUK_TVAL_SET_NUMBER_CHKFAST(tv,d) \
+	duk_tval_set_number_chkfast((tv), (d))
+#define DUK_TVAL_SET_NUMBER(tv,val) \
+	DUK_TVAL_SET_DOUBLE((tv), (val))
+#define DUK_TVAL_CHKFAST_INPLACE(v)  do { \
+		duk_tval *duk__tv; \
+		duk_double_t duk__d; \
+		duk__tv = (v); \
+		if (DUK_TVAL_IS_DOUBLE(duk__tv)) { \
+			duk__d = DUK_TVAL_GET_DOUBLE(duk__tv); \
+			DUK_TVAL_SET_NUMBER_CHKFAST(duk__tv, duk__d); \
+		} \
+	} while (0)
+#else
 #define DUK_TVAL_SET_NUMBER(tv,val)  do { \
 		(tv)->t = DUK__TAG_NUMBER; \
 		(tv)->v.d = (val); \
 	} while (0)
+#define DUK_TVAL_SET_NUMBER_CHKFAST(tv,d) \
+	DUK_TVAL_SET_NUMBER((tv), (d))
+#define DUK_TVAL_SET_DOUBLE(v,d) \
+	DUK_TVAL_SET_NUMBER((tv), (d))
+#define DUK_TVAL_CHKFAST_INPLACE(v)  do { } while (0)
+#endif  /* DUK_USE_FASTINT */
+
+#define DUK_TVAL_SET_POINTER(tv,hptr)  do { \
+		(tv)->t = DUK_TAG_POINTER; \
+		(tv)->v.voidptr = (hptr); \
+	} while (0)
+
+#define DUK_TVAL_SET_LIGHTFUNC(tv,fp,flags)  do { \
+		(tv)->t = DUK_TAG_LIGHTFUNC; \
+		(tv)->v_extra = (flags); \
+		(tv)->v.lightfunc = (duk_c_function) (fp); \
+	} while (0)
 
 #define DUK_TVAL_SET_STRING(tv,hptr)  do { \
 		(tv)->t = DUK_TAG_STRING; \
@@ -4931,44 +6551,87 @@ struct duk_tval_struct {
 		(tv)->v.hbuffer = (hptr); \
 	} while (0)
 
-#define DUK_TVAL_SET_POINTER(tv,hptr)  do { \
-		(tv)->t = DUK_TAG_POINTER; \
-		(tv)->v.voidptr = (hptr); \
-	} while (0)
-
 #define DUK_TVAL_SET_NAN(tv)  do { \
 		/* in non-packed representation we don't care about which NaN is used */ \
 		(tv)->t = DUK__TAG_NUMBER; \
 		(tv)->v.d = DUK_DOUBLE_NAN; \
 	} while (0)
 
-#define DUK_TVAL_SET_TVAL(v,x)              do { *(v) = *(x); } while (0)
+#define DUK_TVAL_SET_TVAL(v,x)             do { *(v) = *(x); } while (0)
 
 /* getters */
 #define DUK_TVAL_GET_BOOLEAN(tv)           ((tv)->v.i)
+#if defined(DUK_USE_FASTINT)
+#define DUK_TVAL_GET_DOUBLE(tv)            ((tv)->v.d)
+#define DUK_TVAL_GET_FASTINT(tv)           ((tv)->v.fi)
+#define DUK_TVAL_GET_FASTINT_U32(tv)       ((duk_uint32_t) ((tv)->v.fi))
+#define DUK_TVAL_GET_FASTINT_I32(tv)       ((duk_int32_t) ((tv)->v.fi))
+#if 0
+#define DUK_TVAL_GET_NUMBER(tv)            (DUK_TVAL_IS_FASTINT((tv)) ? \
+                                               (duk_double_t) DUK_TVAL_GET_FASTINT((tv)) : \
+                                               DUK_TVAL_GET_DOUBLE((tv)))
+#define DUK_TVAL_GET_NUMBER(tv)            duk_tval_get_number_unpacked((tv))
+#else
+/* This seems reasonable overall. */
+#define DUK_TVAL_GET_NUMBER(tv)            (DUK_TVAL_IS_FASTINT((tv)) ? \
+                                               duk_tval_get_number_unpacked_fastint((tv)) : \
+                                               DUK_TVAL_GET_DOUBLE((tv)))
+#endif
+#else
 #define DUK_TVAL_GET_NUMBER(tv)            ((tv)->v.d)
+#define DUK_TVAL_GET_DOUBLE(tv)            ((tv)->v.d)
+#endif  /* DUK_USE_FASTINT */
+#define DUK_TVAL_GET_POINTER(tv)           ((tv)->v.voidptr)
+#define DUK_TVAL_GET_LIGHTFUNC(tv,out_fp,out_flags)  do { \
+		(out_flags) = (duk_uint32_t) (tv)->v_extra; \
+		(out_fp) = (tv)->v.lightfunc; \
+	} while (0)
+#define DUK_TVAL_GET_LIGHTFUNC_FUNCPTR(tv) ((tv)->v.lightfunc)
+#define DUK_TVAL_GET_LIGHTFUNC_FLAGS(tv)   ((duk_uint32_t) ((tv)->v_extra))
 #define DUK_TVAL_GET_STRING(tv)            ((tv)->v.hstring)
 #define DUK_TVAL_GET_OBJECT(tv)            ((tv)->v.hobject)
 #define DUK_TVAL_GET_BUFFER(tv)            ((tv)->v.hbuffer)
-#define DUK_TVAL_GET_POINTER(tv)           ((tv)->v.voidptr)
 #define DUK_TVAL_GET_HEAPHDR(tv)           ((tv)->v.heaphdr)
 
 /* decoding */
 #define DUK_TVAL_GET_TAG(tv)               ((tv)->t)
-#define DUK_TVAL_IS_NUMBER(tv)             ((tv)->t == DUK__TAG_NUMBER)
 #define DUK_TVAL_IS_UNDEFINED(tv)          ((tv)->t == DUK_TAG_UNDEFINED)
-#define DUK_TVAL_IS_UNDEFINED_ACTUAL(tv)   (((tv)->t == DUK_TAG_UNDEFINED) && ((tv)->v.i == 0))
-#define DUK_TVAL_IS_UNDEFINED_UNUSED(tv)   (((tv)->t == DUK_TAG_UNDEFINED) && ((tv)->v.i != 0))
+#define DUK_TVAL_IS_UNUSED(tv)             ((tv)->t == DUK_TAG_UNUSED)
 #define DUK_TVAL_IS_NULL(tv)               ((tv)->t == DUK_TAG_NULL)
 #define DUK_TVAL_IS_BOOLEAN(tv)            ((tv)->t == DUK_TAG_BOOLEAN)
 #define DUK_TVAL_IS_BOOLEAN_TRUE(tv)       (((tv)->t == DUK_TAG_BOOLEAN) && ((tv)->v.i != 0))
 #define DUK_TVAL_IS_BOOLEAN_FALSE(tv)      (((tv)->t == DUK_TAG_BOOLEAN) && ((tv)->v.i == 0))
+#if defined(DUK_USE_FASTINT)
+#define DUK_TVAL_IS_DOUBLE(tv)             ((tv)->t == DUK__TAG_NUMBER)
+#define DUK_TVAL_IS_FASTINT(tv)            ((tv)->t == DUK_TAG_FASTINT)
+#define DUK_TVAL_IS_NUMBER(tv)             ((tv)->t == DUK__TAG_NUMBER || \
+                                            (tv)->t == DUK_TAG_FASTINT)
+#else
+#define DUK_TVAL_IS_NUMBER(tv)             ((tv)->t == DUK__TAG_NUMBER)
+#define DUK_TVAL_IS_DOUBLE(v)              DUK_TVAL_IS_NUMBER((v))
+#endif  /* DUK_USE_FASTINT */
+#define DUK_TVAL_IS_POINTER(tv)            ((tv)->t == DUK_TAG_POINTER)
+#define DUK_TVAL_IS_LIGHTFUNC(tv)          ((tv)->t == DUK_TAG_LIGHTFUNC)
 #define DUK_TVAL_IS_STRING(tv)             ((tv)->t == DUK_TAG_STRING)
 #define DUK_TVAL_IS_OBJECT(tv)             ((tv)->t == DUK_TAG_OBJECT)
 #define DUK_TVAL_IS_BUFFER(tv)             ((tv)->t == DUK_TAG_BUFFER)
-#define DUK_TVAL_IS_POINTER(tv)            ((tv)->t == DUK_TAG_POINTER)
 
+/* This is performance critical because it's needed for every DECREF.
+ * Take advantage of the fact that the first heap allocated tag is 8,
+ * so that bit 3 is set for all heap allocated tags (and never set for
+ * non-heap-allocated tags).
+ */
+#if 0
 #define DUK_TVAL_IS_HEAP_ALLOCATED(tv)     ((tv)->t >= DUK_TAG_STRING)
+#endif
+#define DUK_TVAL_IS_HEAP_ALLOCATED(tv)     ((tv)->t & 0x08)
+
+#if defined(DUK_USE_FASTINT)
+#if 0
+DUK_INTERNAL_DECL duk_double_t duk_tval_get_number_unpacked(duk_tval *tv);
+#endif
+DUK_INTERNAL_DECL duk_double_t duk_tval_get_number_unpacked_fastint(duk_tval *tv);
+#endif
 
 #endif  /* DUK_USE_PACKED_TVAL */
 
@@ -4979,6 +6642,34 @@ struct duk_tval_struct {
 #define DUK_TVAL_SET_BOOLEAN_TRUE(v)        DUK_TVAL_SET_BOOLEAN(v, 1)
 #define DUK_TVAL_SET_BOOLEAN_FALSE(v)       DUK_TVAL_SET_BOOLEAN(v, 0)
 
+/* Lightfunc flags packing and unpacking. */
+/* Sign extend: 0x0000##00 -> 0x##000000 -> sign extend to 0xssssss## */
+#define DUK_LFUNC_FLAGS_GET_MAGIC(lf_flags) \
+	((((duk_int32_t) (lf_flags)) << 16) >> 24)
+#define DUK_LFUNC_FLAGS_GET_LENGTH(lf_flags) \
+	(((lf_flags) >> 4) & 0x0f)
+#define DUK_LFUNC_FLAGS_GET_NARGS(lf_flags) \
+	((lf_flags) & 0x0f)
+#define DUK_LFUNC_FLAGS_PACK(magic,length,nargs) \
+	(((magic) & 0xff) << 8) | ((length) << 4) | (nargs)
+
+#define DUK_LFUNC_NARGS_VARARGS             0x0f   /* varargs marker */
+#define DUK_LFUNC_NARGS_MIN                 0x00
+#define DUK_LFUNC_NARGS_MAX                 0x0e   /* max, excl. varargs marker */
+#define DUK_LFUNC_LENGTH_MIN                0x00
+#define DUK_LFUNC_LENGTH_MAX                0x0f
+#define DUK_LFUNC_MAGIC_MIN                 (-0x80)
+#define DUK_LFUNC_MAGIC_MAX                 0x7f
+
+/* fastint constants etc */
+#if defined(DUK_USE_FASTINT)
+#define DUK_FASTINT_MIN           (-0x800000000000LL)
+#define DUK_FASTINT_MAX           0x7fffffffffffLL
+#define DUK_FASTINT_BITS          48
+
+DUK_INTERNAL_DECL void duk_tval_set_number_chkfast(duk_tval *tv, duk_double_t x);
+#endif
+
 #endif  /* DUK_TVAL_H_INCLUDED */
 #line 1 "duk_heaphdr.h"
 /*
@@ -5010,21 +6701,59 @@ struct duk_tval_struct {
 
 struct duk_heaphdr {
 	duk_uint32_t h_flags;
+
 #if defined(DUK_USE_REFERENCE_COUNTING)
+#if defined(DUK_USE_REFCOUNT16)
+	duk_uint16_t h_refcount16;
+#else
 	duk_size_t h_refcount;
 #endif
+#endif
+
+#if defined(DUK_USE_HEAPPTR16)
+	duk_uint16_t h_next16;
+#else
 	duk_heaphdr *h_next;
+#endif
+
 #if defined(DUK_USE_DOUBLE_LINKED_HEAP)
 	/* refcounting requires direct heap frees, which in turn requires a dual linked heap */
+#if defined(DUK_USE_HEAPPTR16)
+	duk_uint16_t h_prev16;
+#else
 	duk_heaphdr *h_prev;
 #endif
+#endif
+
+	/* When DUK_USE_HEAPPTR16 (and DUK_USE_REFCOUNT16) is in use, the
+	 * struct won't align nicely to 4 bytes.  This 16-bit extra field
+	 * is added to make the alignment clean; the field can be used by
+	 * heap objects when 16-bit packing is used.  This field is now
+	 * conditional to DUK_USE_HEAPPTR16 only, but it is intended to be
+	 * used with DUK_USE_REFCOUNT16 and DUK_USE_DOUBLE_LINKED_HEAP;
+	 * this only matter to low memory environments anyway.
+	 */
+#if defined(DUK_USE_HEAPPTR16)
+	duk_uint16_t h_extra16;
+#endif
 };
 
 struct duk_heaphdr_string {
+	/* 16 bits would be enough for shared heaphdr flags and duk_hstring
+	 * flags.  The initial parts of duk_heaphdr_string and duk_heaphdr
+	 * must match so changing the flags field size here would be quite
+	 * awkward.  However, to minimize struct size, we can pack at least
+	 * 16 bits of duk_hstring data into the flags field.
+	 */
 	duk_uint32_t h_flags;
+
 #if defined(DUK_USE_REFERENCE_COUNTING)
+#if defined(DUK_USE_REFCOUNT16)
+	duk_uint16_t h_refcount16;
+#else
 	duk_size_t h_refcount;
 #endif
+#endif
 };
 
 #define DUK_HEAPHDR_FLAGS_TYPE_MASK      0x00000003UL
@@ -5050,23 +6779,50 @@ struct duk_heaphdr_string {
 #define DUK_HTYPE_BUFFER                 3
 #define DUK_HTYPE_MAX                    3
 
-#define DUK_HEAPHDR_GET_NEXT(h)       ((h)->h_next)
-#define DUK_HEAPHDR_SET_NEXT(h,val)   do { \
+#if defined(DUK_USE_HEAPPTR16)
+#define DUK_HEAPHDR_GET_NEXT(heap,h) \
+	((duk_heaphdr *) DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, (h)->h_next16))
+#define DUK_HEAPHDR_SET_NEXT(heap,h,val)   do { \
+		(h)->h_next16 = DUK_USE_HEAPPTR_ENC16((heap)->heap_udata, (void *) val); \
+	} while (0)
+#else
+#define DUK_HEAPHDR_GET_NEXT(heap,h)  ((h)->h_next)
+#define DUK_HEAPHDR_SET_NEXT(heap,h,val)   do { \
 		(h)->h_next = (val); \
 	} while (0)
+#endif
 
 #if defined(DUK_USE_DOUBLE_LINKED_HEAP)
-#define DUK_HEAPHDR_GET_PREV(h)       ((h)->h_prev)
-#define DUK_HEAPHDR_SET_PREV(h,val)   do { \
+#if defined(DUK_USE_HEAPPTR16)
+#define DUK_HEAPHDR_GET_PREV(heap,h) \
+	((duk_heaphdr *) DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, (h)->h_prev16))
+#define DUK_HEAPHDR_SET_PREV(heap,h,val)   do { \
+		(h)->h_prev16 = DUK_USE_HEAPPTR_ENC16((heap)->heap_udata, (void *) (val)); \
+	} while (0)
+#else
+#define DUK_HEAPHDR_GET_PREV(heap,h)       ((h)->h_prev)
+#define DUK_HEAPHDR_SET_PREV(heap,h,val)   do { \
 		(h)->h_prev = (val); \
 	} while (0)
 #endif
+#endif
 
 #if defined(DUK_USE_REFERENCE_COUNTING)
+#if defined(DUK_USE_REFCOUNT16)
+#define DUK_HEAPHDR_GET_REFCOUNT(h)   ((h)->h_refcount16)
+#define DUK_HEAPHDR_SET_REFCOUNT(h,val)  do { \
+		(h)->h_refcount16 = (val); \
+	} while (0)
+#define DUK_HEAPHDR_PREINC_REFCOUNT(h)  (++(h)->h_refcount16)  /* result: updated refcount */
+#define DUK_HEAPHDR_PREDEC_REFCOUNT(h)  (--(h)->h_refcount16)  /* result: updated refcount */
+#else
 #define DUK_HEAPHDR_GET_REFCOUNT(h)   ((h)->h_refcount)
 #define DUK_HEAPHDR_SET_REFCOUNT(h,val)  do { \
 		(h)->h_refcount = (val); \
 	} while (0)
+#define DUK_HEAPHDR_PREINC_REFCOUNT(h)  (++(h)->h_refcount)  /* result: updated refcount */
+#define DUK_HEAPHDR_PREDEC_REFCOUNT(h)  (--(h)->h_refcount)  /* result: updated refcount */
+#endif
 #else
 /* refcount macros not defined without refcounting, caller must #ifdef now */
 #endif  /* DUK_USE_REFERENCE_COUNTING */
@@ -5076,6 +6832,8 @@ struct duk_heaphdr_string {
  *  involved in the macros below.
  */
 
+#define DUK_HEAPHDR_GET_FLAGS_RAW(h)  ((h)->h_flags)
+
 #define DUK_HEAPHDR_GET_FLAGS(h)      ((h)->h_flags & DUK_HEAPHDR_FLAGS_FLAG_MASK)
 #define DUK_HEAPHDR_SET_FLAGS(h,val)  do { \
 		(h)->h_flags = ((h)->h_flags & ~(DUK_HEAPHDR_FLAGS_FLAG_MASK)) | (val); \
@@ -5136,12 +6894,12 @@ struct duk_heaphdr_string {
 /* init pointer fields to null */
 #if defined(DUK_USE_DOUBLE_LINKED_HEAP)
 #define DUK_HEAPHDR_INIT_NULLS(h)       do { \
-		(h)->h_next = NULL; \
+		DUK_HEAPHDR_SET_NEXT((h), (void *) NULL); \
+		DUK_HEAPHDR_SET_PREV((h), (void *) NULL); \
 	} while (0)
 #else
 #define DUK_HEAPHDR_INIT_NULLS(h)       do { \
-		(h)->h_next = NULL; \
-		(h)->h_prev = NULL; \
+		DUK_HEAPHDR_SET_NEXT((h), (void *) NULL); \
 	} while (0)
 #endif
 
@@ -5160,43 +6918,447 @@ struct duk_heaphdr_string {
 
 #if defined(DUK_USE_REFERENCE_COUNTING)
 
-#define DUK_TVAL_INCREF(thr,tv)                duk_heap_tval_incref((tv))
-#define DUK_TVAL_DECREF(thr,tv)                duk_heap_tval_decref((thr),(tv))
-#define DUK__HEAPHDR_INCREF(thr,h)             duk_heap_heaphdr_incref((h))
-#define DUK__HEAPHDR_DECREF(thr,h)             duk_heap_heaphdr_decref((thr),(h))
-#define DUK_HEAPHDR_INCREF(thr,h)              DUK__HEAPHDR_INCREF((thr),(duk_heaphdr *) (h))
-#define DUK_HEAPHDR_DECREF(thr,h)              DUK__HEAPHDR_DECREF((thr),(duk_heaphdr *) (h))
-#define DUK_HSTRING_INCREF(thr,h)              DUK__HEAPHDR_INCREF((thr),(duk_heaphdr *) (h))
-#define DUK_HSTRING_DECREF(thr,h)              DUK__HEAPHDR_DECREF((thr),(duk_heaphdr *) (h))
-#define DUK_HOBJECT_INCREF(thr,h)              DUK__HEAPHDR_INCREF((thr),(duk_heaphdr *) (h))
-#define DUK_HOBJECT_DECREF(thr,h)              DUK__HEAPHDR_DECREF((thr),(duk_heaphdr *) (h))
-#define DUK_HBUFFER_INCREF(thr,h)              DUK__HEAPHDR_INCREF((thr),(duk_heaphdr *) (h))
-#define DUK_HBUFFER_DECREF(thr,h)              DUK__HEAPHDR_DECREF((thr),(duk_heaphdr *) (h))
-#define DUK_HCOMPILEDFUNCTION_INCREF(thr,h)    DUK__HEAPHDR_INCREF((thr),(duk_heaphdr *) &(h)->obj)
-#define DUK_HCOMPILEDFUNCTION_DECREF(thr,h)    DUK__HEAPHDR_DECREF((thr),(duk_heaphdr *) &(h)->obj)
-#define DUK_HNATIVEFUNCTION_INCREF(thr,h)      DUK__HEAPHDR_INCREF((thr),(duk_heaphdr *) &(h)->obj)
-#define DUK_HNATIVEFUNCTION_DECREF(thr,h)      DUK__HEAPHDR_DECREF((thr),(duk_heaphdr *) &(h)->obj)
-#define DUK_HTHREAD_INCREF(thr,h)              DUK__HEAPHDR_INCREF((thr),(duk_heaphdr *) &(h)->obj)
-#define DUK_HTHREAD_DECREF(thr,h)              DUK__HEAPHDR_DECREF((thr),(duk_heaphdr *) &(h)->obj)
+/* Fast variants, inline refcount operations except for refzero handling.
+ * Can be used explicitly when speed is always more important than size.
+ * For a good compiler and a single file build, these are basically the
+ * same as a forced inline.
+ */
+#define DUK_TVAL_INCREF_FAST(thr,tv) do { \
+		duk_tval *duk__tv = (tv); \
+		DUK_ASSERT(duk__tv != NULL); \
+		if (DUK_TVAL_IS_HEAP_ALLOCATED(duk__tv)) { \
+			duk_heaphdr *duk__h = DUK_TVAL_GET_HEAPHDR(duk__tv); \
+			DUK_ASSERT(duk__h != NULL); \
+			DUK_ASSERT(DUK_HEAPHDR_HTYPE_VALID(duk__h)); \
+			DUK_HEAPHDR_PREINC_REFCOUNT(duk__h); \
+		} \
+	} while (0)
+#define DUK_TVAL_DECREF_FAST(thr,tv) do { \
+		duk_tval *duk__tv = (tv); \
+		DUK_ASSERT(duk__tv != NULL); \
+		if (DUK_TVAL_IS_HEAP_ALLOCATED(duk__tv)) { \
+			duk_heaphdr *duk__h = DUK_TVAL_GET_HEAPHDR(duk__tv); \
+			DUK_ASSERT(duk__h != NULL); \
+			DUK_ASSERT(DUK_HEAPHDR_HTYPE_VALID(duk__h)); \
+			DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT(duk__h) > 0); \
+			if (DUK_HEAPHDR_PREDEC_REFCOUNT(duk__h) == 0) { \
+				duk_heaphdr_refzero((thr), duk__h); \
+			} \
+		} \
+	} while (0)
+#define DUK_HEAPHDR_INCREF_FAST(thr,h) do { \
+		duk_heaphdr *duk__h = (duk_heaphdr *) (h); \
+		DUK_ASSERT(duk__h != NULL); \
+		DUK_ASSERT(DUK_HEAPHDR_HTYPE_VALID(duk__h)); \
+		DUK_HEAPHDR_PREINC_REFCOUNT(duk__h); \
+	} while (0)
+#define DUK_HEAPHDR_DECREF_FAST(thr,h) do { \
+		duk_heaphdr *duk__h = (duk_heaphdr *) (h); \
+		DUK_ASSERT(duk__h != NULL); \
+		DUK_ASSERT(DUK_HEAPHDR_HTYPE_VALID(duk__h)); \
+		DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT(duk__h) > 0); \
+		if (DUK_HEAPHDR_PREDEC_REFCOUNT(duk__h) == 0) { \
+			duk_heaphdr_refzero((thr), duk__h); \
+		} \
+	} while (0)
+
+/* Slow variants, call to a helper to reduce code size.
+ * Can be used explicitly when size is always more important than speed.
+ */
+#define DUK_TVAL_INCREF_SLOW(thr,tv) do { \
+		duk_tval_incref((tv)); \
+	} while (0)
+#define DUK_TVAL_DECREF_SLOW(thr,tv) do { \
+		duk_tval_decref((thr), (tv)); \
+	} while (0)
+#define DUK_HEAPHDR_INCREF_SLOW(thr,h) do { \
+		duk_heaphdr_incref((duk_heaphdr *) (h)); \
+	} while (0)
+#define DUK_HEAPHDR_DECREF_SLOW(thr,h) do { \
+		duk_heaphdr_decref((thr), (duk_heaphdr *) (h)); \
+	} while (0)
+
+/* Default variants.  Selection depends on speed/size preference.
+ * Concretely: with gcc 4.8.1 -Os x64 the difference in final binary
+ * is about +1kB for _FAST variants.
+ */
+#if defined(DUK_USE_FAST_REFCOUNT_DEFAULT)
+#define DUK_TVAL_INCREF(thr,tv)                DUK_TVAL_INCREF_FAST((thr),(tv))
+#define DUK_TVAL_DECREF(thr,tv)                DUK_TVAL_DECREF_FAST((thr),(tv))
+#define DUK_HEAPHDR_INCREF(thr,h)              DUK_HEAPHDR_INCREF_FAST((thr),(h))
+#define DUK_HEAPHDR_DECREF(thr,h)              DUK_HEAPHDR_DECREF_FAST((thr),(h))
+#else
+#define DUK_TVAL_INCREF(thr,tv)                DUK_TVAL_INCREF_SLOW((thr),(tv))
+#define DUK_TVAL_DECREF(thr,tv)                DUK_TVAL_DECREF_SLOW((thr),(tv))
+#define DUK_HEAPHDR_INCREF(thr,h)              DUK_HEAPHDR_INCREF_SLOW((thr),(h))
+#define DUK_HEAPHDR_DECREF(thr,h)              DUK_HEAPHDR_DECREF_SLOW((thr),(h))
+#endif
+
+/* Casting convenience. */
+#define DUK_HSTRING_INCREF(thr,h)              DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) (h))
+#define DUK_HSTRING_DECREF(thr,h)              DUK_HEAPHDR_DECREF((thr),(duk_heaphdr *) (h))
+#define DUK_HOBJECT_INCREF(thr,h)              DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) (h))
+#define DUK_HOBJECT_DECREF(thr,h)              DUK_HEAPHDR_DECREF((thr),(duk_heaphdr *) (h))
+#define DUK_HBUFFER_INCREF(thr,h)              DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) (h))
+#define DUK_HBUFFER_DECREF(thr,h)              DUK_HEAPHDR_DECREF((thr),(duk_heaphdr *) (h))
+#define DUK_HCOMPILEDFUNCTION_INCREF(thr,h)    DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) &(h)->obj)
+#define DUK_HCOMPILEDFUNCTION_DECREF(thr,h)    DUK_HEAPHDR_DECREF((thr),(duk_heaphdr *) &(h)->obj)
+#define DUK_HNATIVEFUNCTION_INCREF(thr,h)      DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) &(h)->obj)
+#define DUK_HNATIVEFUNCTION_DECREF(thr,h)      DUK_HEAPHDR_DECREF((thr),(duk_heaphdr *) &(h)->obj)
+#define DUK_HBUFFEROBJECT_INCREF(thr,h)        DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) &(h)->obj)
+#define DUK_HBUFFEROBJECT_DECREF(thr,h)        DUK_HEAPHDR_DECREF((thr),(duk_heaphdr *) &(h)->obj)
+#define DUK_HTHREAD_INCREF(thr,h)              DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) &(h)->obj)
+#define DUK_HTHREAD_DECREF(thr,h)              DUK_HEAPHDR_DECREF((thr),(duk_heaphdr *) &(h)->obj)
+
+/* Convenience for some situations; the above macros don't allow NULLs
+ * for performance reasons.
+ */
+#define DUK_HOBJECT_INCREF_ALLOWNULL(thr,h) do { \
+		if ((h) != NULL) { \
+			DUK_HEAPHDR_INCREF((thr), (duk_heaphdr *) (h)); \
+		} \
+	} while (0)
+#define DUK_HOBJECT_DECREF_ALLOWNULL(thr,h) do { \
+		if ((h) != NULL) { \
+			DUK_HEAPHDR_DECREF((thr), (duk_heaphdr *) (h)); \
+		} \
+	} while (0)
+
+/*
+ *  Macros to set a duk_tval and update refcount of the target (decref the
+ *  old value and incref the new value if necessary).  This is both performance
+ *  and footprint critical; any changes made should be measured for size/speed.
+ */
+
+#define DUK_TVAL_SET_UNDEFINED_UPDREF_ALT0(thr,tvptr_dst) do { \
+		duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
+		DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
+		DUK_TVAL_SET_UNDEFINED(tv__dst); \
+		DUK_TVAL_DECREF((thr), &tv__tmp);  /* side effects */ \
+	} while (0)
+
+#define DUK_TVAL_SET_UNUSED_UPDREF_ALT0(thr,tvptr_dst) do { \
+		duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
+		DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
+		DUK_TVAL_SET_UNUSED(tv__dst); \
+		DUK_TVAL_DECREF((thr), &tv__tmp);  /* side effects */ \
+	} while (0)
+
+#define DUK_TVAL_SET_NULL_UPDREF_ALT0(thr,tvptr_dst) do { \
+		duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
+		DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
+		DUK_TVAL_SET_NULL(tv__dst); \
+		DUK_TVAL_DECREF((thr), &tv__tmp);  /* side effects */ \
+	} while (0)
+
+#define DUK_TVAL_SET_BOOLEAN_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
+		duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
+		DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
+		DUK_TVAL_SET_BOOLEAN(tv__dst, (newval)); \
+		DUK_TVAL_DECREF((thr), &tv__tmp);  /* side effects */ \
+	} while (0)
+
+#define DUK_TVAL_SET_NUMBER_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
+		duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
+		DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
+		DUK_TVAL_SET_NUMBER(tv__dst, (newval)); \
+		DUK_TVAL_DECREF((thr), &tv__tmp);  /* side effects */ \
+	} while (0)
+#define DUK_TVAL_SET_NUMBER_CHKFAST_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
+		duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
+		DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
+		DUK_TVAL_SET_NUMBER_CHKFAST(tv__dst, (newval)); \
+		DUK_TVAL_DECREF((thr), &tv__tmp);  /* side effects */ \
+	} while (0)
+#define DUK_TVAL_SET_DOUBLE_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
+		duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
+		DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
+		DUK_TVAL_SET_DOUBLE(tv__dst, (newval)); \
+		DUK_TVAL_DECREF((thr), &tv__tmp);  /* side effects */ \
+	} while (0)
+#define DUK_TVAL_SET_NAN_UPDREF_ALT0(thr,tvptr_dst) do { \
+		duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
+		DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
+		DUK_TVAL_SET_NAN(tv__dst); \
+		DUK_TVAL_DECREF((thr), &tv__tmp);  /* side effects */ \
+	} while (0)
+#if defined(DUK_USE_FASTINT)
+#define DUK_TVAL_SET_FASTINT_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
+		duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
+		DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
+		DUK_TVAL_SET_FASTINT(tv__dst, (newval)); \
+		DUK_TVAL_DECREF((thr), &tv__tmp);  /* side effects */ \
+	} while (0)
+#define DUK_TVAL_SET_FASTINT_I32_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
+		duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
+		DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
+		DUK_TVAL_SET_FASTINT_I32(tv__dst, (newval)); \
+		DUK_TVAL_DECREF((thr), &tv__tmp);  /* side effects */ \
+	} while (0)
+#define DUK_TVAL_SET_FASTINT_U32_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
+		duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
+		DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
+		DUK_TVAL_SET_FASTINT_U32(tv__dst, (newval)); \
+		DUK_TVAL_DECREF((thr), &tv__tmp);  /* side effects */ \
+	} while (0)
+#endif  /* DUK_USE_FASTINT */
+
+#define DUK_TVAL_SET_LIGHTFUNC_UPDREF_ALT0(thr,tvptr_dst,lf_v,lf_fp,lf_flags) do { \
+		duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
+		DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
+		DUK_TVAL_SET_LIGHTFUNC(tv__dst, (lf_v), (lf_fp), (lf_flags)); \
+		DUK_TVAL_DECREF((thr), &tv__tmp);  /* side effects */ \
+	} while (0)
+
+#define DUK_TVAL_SET_STRING_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
+		duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
+		DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
+		DUK_TVAL_SET_STRING(tv__dst, (newval)); \
+		DUK_HSTRING_INCREF((thr), (newval)); \
+		DUK_TVAL_DECREF((thr), &tv__tmp);  /* side effects */ \
+	} while (0)
+
+#define DUK_TVAL_SET_OBJECT_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
+		duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
+		DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
+		DUK_TVAL_SET_OBJECT(tv__dst, (newval)); \
+		DUK_HOBJECT_INCREF((thr), (newval)); \
+		DUK_TVAL_DECREF((thr), &tv__tmp);  /* side effects */ \
+	} while (0)
+
+#define DUK_TVAL_SET_BUFFER_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
+		duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
+		DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
+		DUK_TVAL_SET_BUFFER(tv__dst, (newval)); \
+		DUK_HBUFFER_INCREF((thr), (newval)); \
+		DUK_TVAL_DECREF((thr), &tv__tmp);  /* side effects */ \
+	} while (0)
+
+#define DUK_TVAL_SET_POINTER_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
+		duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
+		DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
+		DUK_TVAL_SET_POINTER(tv__dst, (newval)); \
+		DUK_TVAL_DECREF((thr), &tv__tmp);  /* side effects */ \
+	} while (0)
+
+/* DUK_TVAL_SET_TVAL_UPDREF() is used a lot in executor, property lookups,
+ * etc, so it's very important for performance.  Measure when changing.
+ *
+ * NOTE: the source and destination duk_tval pointers may be the same, and
+ * the macros MUST deal with that correctly.
+ */
+
+/* Original idiom used, minimal code size. */
+#define DUK_TVAL_SET_TVAL_UPDREF_ALT0(thr,tvptr_dst,tvptr_src) do { \
+		duk_tval *tv__dst, *tv__src; duk_tval tv__tmp; \
+		tv__dst = (tvptr_dst); tv__src = (tvptr_src); \
+		DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
+		DUK_TVAL_SET_TVAL(tv__dst, tv__src); \
+		DUK_TVAL_INCREF((thr), tv__src); \
+		DUK_TVAL_DECREF((thr), &tv__tmp);  /* side effects */ \
+	} while (0)
+
+/* Faster alternative: avoid making a temporary copy of tvptr_dst and use
+ * fast incref/decref macros.
+ */
+#define DUK_TVAL_SET_TVAL_UPDREF_ALT1(thr,tvptr_dst,tvptr_src) do { \
+		duk_tval *tv__dst, *tv__src; duk_heaphdr *h__obj; \
+		tv__dst = (tvptr_dst); tv__src = (tvptr_src); \
+		DUK_TVAL_INCREF_FAST((thr), tv__src); \
+		if (DUK_TVAL_IS_HEAP_ALLOCATED(tv__dst)) { \
+			h__obj = DUK_TVAL_GET_HEAPHDR(tv__dst); \
+			DUK_ASSERT(h__obj != NULL); \
+			DUK_TVAL_SET_TVAL(tv__dst, tv__src); \
+			DUK_HEAPHDR_DECREF_FAST((thr), h__obj);  /* side effects */ \
+		} else { \
+			DUK_TVAL_SET_TVAL(tv__dst, tv__src); \
+		} \
+	} while (0)
+
+/* XXX: no optimized variants yet */
+#define DUK_TVAL_SET_UNDEFINED_UPDREF         DUK_TVAL_SET_UNDEFINED_UPDREF_ALT0
+#define DUK_TVAL_SET_UNUSED_UPDREF            DUK_TVAL_SET_UNUSED_UPDREF_ALT0
+#define DUK_TVAL_SET_NULL_UPDREF              DUK_TVAL_SET_NULL_UPDREF_ALT0
+#define DUK_TVAL_SET_BOOLEAN_UPDREF           DUK_TVAL_SET_BOOLEAN_UPDREF_ALT0
+#define DUK_TVAL_SET_NUMBER_UPDREF            DUK_TVAL_SET_NUMBER_UPDREF_ALT0
+#define DUK_TVAL_SET_NUMBER_CHKFAST_UPDREF    DUK_TVAL_SET_NUMBER_CHKFAST_UPDREF_ALT0
+#define DUK_TVAL_SET_DOUBLE_UPDREF            DUK_TVAL_SET_DOUBLE_UPDREF_ALT0
+#define DUK_TVAL_SET_NAN_UPDREF               DUK_TVAL_SET_NAN_UPDREF_ALT0
+#if defined(DUK_USE_FASTINT)
+#define DUK_TVAL_SET_FASTINT_UPDREF           DUK_TVAL_SET_FASTINT_UPDREF_ALT0
+#define DUK_TVAL_SET_FASTINT_I32_UPDREF       DUK_TVAL_SET_FASTINT_I32_UPDREF_ALT0
+#define DUK_TVAL_SET_FASTINT_U32_UPDREF       DUK_TVAL_SET_FASTINT_U32_UPDREF_ALT0
+#endif  /* DUK_USE_FASTINT */
+#define DUK_TVAL_SET_LIGHTFUNC_UPDREF         DUK_TVAL_SET_LIGHTFUNC_UPDREF_ALT0
+#define DUK_TVAL_SET_STRING_UPDREF            DUK_TVAL_SET_STRING_UPDREF_ALT0
+#define DUK_TVAL_SET_OBJECT_UPDREF            DUK_TVAL_SET_OBJECT_UPDREF_ALT0
+#define DUK_TVAL_SET_BUFFER_UPDREF            DUK_TVAL_SET_BUFFER_UPDREF_ALT0
+#define DUK_TVAL_SET_POINTER_UPDREF           DUK_TVAL_SET_POINTER_UPDREF_ALT0
+
+#if defined(DUK_USE_FAST_REFCOUNT_DEFAULT)
+/* Optimized for speed. */
+#define DUK_TVAL_SET_TVAL_UPDREF              DUK_TVAL_SET_TVAL_UPDREF_ALT1
+#define DUK_TVAL_SET_TVAL_UPDREF_FAST         DUK_TVAL_SET_TVAL_UPDREF_ALT1
+#define DUK_TVAL_SET_TVAL_UPDREF_SLOW         DUK_TVAL_SET_TVAL_UPDREF_ALT0
+#else
+/* Optimized for size. */
+#define DUK_TVAL_SET_TVAL_UPDREF              DUK_TVAL_SET_TVAL_UPDREF_ALT0
+#define DUK_TVAL_SET_TVAL_UPDREF_FAST         DUK_TVAL_SET_TVAL_UPDREF_ALT0
+#define DUK_TVAL_SET_TVAL_UPDREF_SLOW         DUK_TVAL_SET_TVAL_UPDREF_ALT0
+#endif
 
 #else  /* DUK_USE_REFERENCE_COUNTING */
 
-#define DUK_TVAL_INCREF(thr,v)                 /* nop */
-#define DUK_TVAL_DECREF(thr,v)                 /* nop */
-#define DUK_HEAPHDR_INCREF(thr,h)              /* nop */
-#define DUK_HEAPHDR_DECREF(thr,h)              /* nop */
-#define DUK_HSTRING_INCREF(thr,h)              /* nop */
-#define DUK_HSTRING_DECREF(thr,h)              /* nop */
-#define DUK_HOBJECT_INCREF(thr,h)              /* nop */
-#define DUK_HOBJECT_DECREF(thr,h)              /* nop */
-#define DUK_HBUFFER_INCREF(thr,h)              /* nop */
-#define DUK_HBUFFER_DECREF(thr,h)              /* nop */
-#define DUK_HCOMPILEDFUNCTION_INCREF(thr,h)    /* nop */
-#define DUK_HCOMPILEDFUNCTION_DECREF(thr,h)    /* nop */
-#define DUK_HNATIVEFUNCTION_INCREF(thr,h)      /* nop */
-#define DUK_HNATIVEFUNCTION_DECREF(thr,h)      /* nop */
-#define DUK_HTHREAD_INCREF(thr,h)              /* nop */
-#define DUK_HTHREAD_DECREF(thr,h)              /* nop */
+#define DUK_TVAL_INCREF_FAST(thr,v)            do {} while (0) /* nop */
+#define DUK_TVAL_DECREF_FAST(thr,v)            do {} while (0) /* nop */
+#define DUK_TVAL_INCREF_SLOW(thr,v)            do {} while (0) /* nop */
+#define DUK_TVAL_DECREF_SLOW(thr,v)            do {} while (0) /* nop */
+#define DUK_TVAL_INCREF(thr,v)                 do {} while (0) /* nop */
+#define DUK_TVAL_DECREF(thr,v)                 do {} while (0) /* nop */
+#define DUK_HEAPHDR_INCREF_FAST(thr,h)         do {} while (0) /* nop */
+#define DUK_HEAPHDR_DECREF_FAST(thr,h)         do {} while (0) /* nop */
+#define DUK_HEAPHDR_INCREF_SLOW(thr,h)         do {} while (0) /* nop */
+#define DUK_HEAPHDR_DECREF_SLOW(thr,h)         do {} while (0) /* nop */
+#define DUK_HEAPHDR_INCREF(thr,h)              do {} while (0) /* nop */
+#define DUK_HEAPHDR_DECREF(thr,h)              do {} while (0) /* nop */
+#define DUK_HSTRING_INCREF(thr,h)              do {} while (0) /* nop */
+#define DUK_HSTRING_DECREF(thr,h)              do {} while (0) /* nop */
+#define DUK_HOBJECT_INCREF(thr,h)              do {} while (0) /* nop */
+#define DUK_HOBJECT_DECREF(thr,h)              do {} while (0) /* nop */
+#define DUK_HBUFFER_INCREF(thr,h)              do {} while (0) /* nop */
+#define DUK_HBUFFER_DECREF(thr,h)              do {} while (0) /* nop */
+#define DUK_HCOMPILEDFUNCTION_INCREF(thr,h)    do {} while (0) /* nop */
+#define DUK_HCOMPILEDFUNCTION_DECREF(thr,h)    do {} while (0) /* nop */
+#define DUK_HNATIVEFUNCTION_INCREF(thr,h)      do {} while (0) /* nop */
+#define DUK_HNATIVEFUNCTION_DECREF(thr,h)      do {} while (0) /* nop */
+#define DUK_HBUFFEROBJECT_INCREF(thr,h)        do {} while (0) /* nop */
+#define DUK_HBUFFEROBJECT_DECREF(thr,h)        do {} while (0) /* nop */
+#define DUK_HTHREAD_INCREF(thr,h)              do {} while (0) /* nop */
+#define DUK_HTHREAD_DECREF(thr,h)              do {} while (0) /* nop */
+#define DUK_HOBJECT_INCREF_ALLOWNULL(thr,h)    do {} while (0) /* nop */
+#define DUK_HOBJECT_DECREF_ALLOWNULL(thr,h)    do {} while (0) /* nop */
+
+#define DUK_TVAL_SET_UNDEFINED_UPDREF_ALT0(thr,tvptr_dst) do { \
+		duk_tval *tv__dst; tv__dst = (tvptr_dst); \
+		DUK_TVAL_SET_UNDEFINED(tv__dst); \
+		DUK_UNREF((thr)); \
+	} while (0)
+
+#define DUK_TVAL_SET_UNUSED_UPDREF_ALT0(thr,tvptr_dst) do { \
+		duk_tval *tv__dst; tv__dst = (tvptr_dst); \
+		DUK_TVAL_SET_UNUSED(tv__dst); \
+		DUK_UNREF((thr)); \
+	} while (0)
+
+#define DUK_TVAL_SET_NULL_UPDREF_ALT0(thr,tvptr_dst) do { \
+		duk_tval *tv__dst; tv__dst = (tvptr_dst); \
+		DUK_TVAL_SET_NULL(tv__dst); \
+		DUK_UNREF((thr)); \
+	} while (0)
+
+#define DUK_TVAL_SET_BOOLEAN_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
+		duk_tval *tv__dst; tv__dst = (tvptr_dst); \
+		DUK_TVAL_SET_BOOLEAN(tv__dst, (newval)); \
+		DUK_UNREF((thr)); \
+	} while (0)
+
+#define DUK_TVAL_SET_NUMBER_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
+		duk_tval *tv__dst; tv__dst = (tvptr_dst); \
+		DUK_TVAL_SET_NUMBER(tv__dst, (newval)); \
+		DUK_UNREF((thr)); \
+	} while (0)
+#define DUK_TVAL_SET_NUMBER_CHKFAST_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
+		duk_tval *tv__dst; tv__dst = (tvptr_dst); \
+		DUK_TVAL_SET_NUMBER_CHKFAST(tv__dst, (newval)); \
+		DUK_UNREF((thr)); \
+	} while (0)
+#define DUK_TVAL_SET_DOUBLE_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
+		duk_tval *tv__dst; tv__dst = (tvptr_dst); \
+		DUK_TVAL_SET_DOUBLE(tv__dst, (newval)); \
+		DUK_UNREF((thr)); \
+	} while (0)
+#define DUK_TVAL_SET_NAN_UPDREF_ALT0(thr,tvptr_dst) do { \
+		duk_tval *tv__dst; tv__dst = (tvptr_dst); \
+		DUK_TVAL_SET_NAN(tv__dst); \
+		DUK_UNREF((thr)); \
+	} while (0)
+#if defined(DUK_USE_FASTINT)
+#define DUK_TVAL_SET_FASTINT_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
+		duk_tval *tv__dst; tv__dst = (tvptr_dst); \
+		DUK_TVAL_SET_FASTINT(tv__dst, (newval)); \
+		DUK_UNREF((thr)); \
+	} while (0)
+#define DUK_TVAL_SET_FASTINT_I32_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
+		duk_tval *tv__dst; tv__dst = (tvptr_dst); \
+		DUK_TVAL_SET_FASTINT_I32(tv__dst, (newval)); \
+		DUK_UNREF((thr)); \
+	} while (0)
+#define DUK_TVAL_SET_FASTINT_U32_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
+		duk_tval *tv__dst; tv__dst = (tvptr_dst); \
+		DUK_TVAL_SET_FASTINT_U32(tv__dst, (newval)); \
+		DUK_UNREF((thr)); \
+	} while (0)
+#endif  /* DUK_USE_FASTINT */
+
+#define DUK_TVAL_SET_LIGHTFUNC_UPDREF_ALT0(thr,tvptr_dst,lf_v,lf_fp,lf_flags) do { \
+		duk_tval *tv__dst; tv__dst = (tvptr_dst); \
+		DUK_TVAL_SET_LIGHTFUNC(tv__dst, (lf_v), (lf_fp), (lf_flags)); \
+		DUK_UNREF((thr)); \
+	} while (0)
+
+#define DUK_TVAL_SET_STRING_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
+		duk_tval *tv__dst; tv__dst = (tvptr_dst); \
+		DUK_TVAL_SET_STRING(tv__dst, (newval)); \
+		DUK_UNREF((thr)); \
+	} while (0)
+
+#define DUK_TVAL_SET_OBJECT_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
+		duk_tval *tv__dst; tv__dst = (tvptr_dst); \
+		DUK_TVAL_SET_OBJECT(tv__dst, (newval)); \
+		DUK_UNREF((thr)); \
+	} while (0)
+
+#define DUK_TVAL_SET_BUFFER_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
+		duk_tval *tv__dst; tv__dst = (tvptr_dst); \
+		DUK_TVAL_SET_BUFFER(tv__dst, (newval)); \
+		DUK_UNREF((thr)); \
+	} while (0)
+
+#define DUK_TVAL_SET_POINTER_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
+		duk_tval *tv__dst; tv__dst = (tvptr_dst); \
+		DUK_TVAL_SET_POINTER(tv__dst, (newval)); \
+		DUK_UNREF((thr)); \
+	} while (0)
+
+#define DUK_TVAL_SET_TVAL_UPDREF_ALT0(thr,tvptr_dst,tvptr_src) do { \
+		duk_tval *tv__dst, *tv__src; \
+		tv__dst = (tvptr_dst); tv__src = (tvptr_src); \
+		DUK_TVAL_SET_TVAL(tv__dst, tv__src); \
+		DUK_UNREF((thr)); \
+	} while (0)
+
+#define DUK_TVAL_SET_UNDEFINED_UPDREF         DUK_TVAL_SET_UNDEFINED_UPDREF_ALT0
+#define DUK_TVAL_SET_UNUSED_UPDREF            DUK_TVAL_SET_UNUSED_UPDREF_ALT0
+#define DUK_TVAL_SET_NULL_UPDREF              DUK_TVAL_SET_NULL_UPDREF_ALT0
+#define DUK_TVAL_SET_BOOLEAN_UPDREF           DUK_TVAL_SET_BOOLEAN_UPDREF_ALT0
+#define DUK_TVAL_SET_NUMBER_UPDREF            DUK_TVAL_SET_NUMBER_UPDREF_ALT0
+#define DUK_TVAL_SET_NUMBER_CHKFAST_UPDREF    DUK_TVAL_SET_NUMBER_CHKFAST_UPDREF_ALT0
+#define DUK_TVAL_SET_DOUBLE_UPDREF            DUK_TVAL_SET_DOUBLE_UPDREF_ALT0
+#define DUK_TVAL_SET_NAN_UPDREF               DUK_TVAL_SET_NAN_UPDREF_ALT0
+#if defined(DUK_USE_FASTINT)
+#define DUK_TVAL_SET_FASTINT_UPDREF           DUK_TVAL_SET_FASTINT_UPDREF_ALT0
+#define DUK_TVAL_SET_FASTINT_I32_UPDREF       DUK_TVAL_SET_FASTINT_I32_UPDREF_ALT0
+#define DUK_TVAL_SET_FASTINT_U32_UPDREF       DUK_TVAL_SET_FASTINT_U32_UPDREF_ALT0
+#endif  /* DUK_USE_FASTINT */
+#define DUK_TVAL_SET_LIGHTFUNC_UPDREF         DUK_TVAL_SET_LIGHTFUNC_UPDREF_ALT0
+#define DUK_TVAL_SET_STRING_UPDREF            DUK_TVAL_SET_STRING_UPDREF_ALT0
+#define DUK_TVAL_SET_OBJECT_UPDREF            DUK_TVAL_SET_OBJECT_UPDREF_ALT0
+#define DUK_TVAL_SET_BUFFER_UPDREF            DUK_TVAL_SET_BUFFER_UPDREF_ALT0
+#define DUK_TVAL_SET_POINTER_UPDREF           DUK_TVAL_SET_POINTER_UPDREF_ALT0
+
+#define DUK_TVAL_SET_TVAL_UPDREF              DUK_TVAL_SET_TVAL_UPDREF_ALT0
+#define DUK_TVAL_SET_TVAL_UPDREF_FAST         DUK_TVAL_SET_TVAL_UPDREF_ALT0
+#define DUK_TVAL_SET_TVAL_UPDREF_SLOW         DUK_TVAL_SET_TVAL_UPDREF_ALT0
 
 #endif  /* DUK_USE_REFERENCE_COUNTING */
 
@@ -5219,25 +7381,55 @@ struct duk_heaphdr_string {
  */
 #define DUK_ERRCODE_FLAG_NOBLAME_FILELINE  (1L << 24)
 
+/* Valstack resize flags */
+#define DUK_VSRESIZE_FLAG_SHRINK           (1 << 0)
+#define DUK_VSRESIZE_FLAG_COMPACT          (1 << 1)
+#define DUK_VSRESIZE_FLAG_THROW            (1 << 2)
+
 /* Current convention is to use duk_size_t for value stack sizes and global indices,
  * and duk_idx_t for local frame indices.
  */
-duk_bool_t duk_check_valstack_resize(duk_context *ctx, duk_size_t min_new_size, duk_bool_t allow_shrink);
-void duk_require_valstack_resize(duk_context *ctx, duk_size_t min_new_size, duk_bool_t allow_shrink);
+DUK_INTERNAL_DECL
+duk_bool_t duk_valstack_resize_raw(duk_context *ctx,
+                                   duk_size_t min_new_size,
+                                   duk_small_uint_t flags);
 
-duk_tval *duk_get_tval(duk_context *ctx, duk_idx_t index);
-duk_tval *duk_require_tval(duk_context *ctx, duk_idx_t index);
-void duk_push_tval(duk_context *ctx, duk_tval *tv);
+#if defined(DUK_USE_VERBOSE_ERRORS) && defined(DUK_USE_PARANOID_ERRORS)
+DUK_INTERNAL_DECL const char *duk_get_type_name(duk_context *ctx, duk_idx_t index);
+#endif
+
+DUK_INTERNAL_DECL duk_tval *duk_get_tval(duk_context *ctx, duk_idx_t index);
+DUK_INTERNAL_DECL duk_tval *duk_require_tval(duk_context *ctx, duk_idx_t index);
+DUK_INTERNAL_DECL void duk_push_tval(duk_context *ctx, duk_tval *tv);
+
+/* Push the current 'this' binding; throw TypeError if binding is not object
+ * coercible (CheckObjectCoercible).
+ */
+DUK_INTERNAL_DECL void duk_push_this_check_object_coercible(duk_context *ctx);
+
+/* duk_push_this() + CheckObjectCoercible() + duk_to_object() */
+DUK_INTERNAL_DECL duk_hobject *duk_push_this_coercible_to_object(duk_context *ctx);
+
+/* duk_push_this() + CheckObjectCoercible() + duk_to_string() */
+DUK_INTERNAL_DECL duk_hstring *duk_push_this_coercible_to_string(duk_context *ctx);
+
+/* Get a borrowed duk_tval pointer to the current 'this' binding.  Caller must
+ * make sure there's an active callstack entry.  Note that the returned pointer
+ * is unstable with regards to side effects.
+ */
+DUK_INTERNAL_DECL duk_tval *duk_get_borrowed_this_tval(duk_context *ctx);
 
-void duk_push_this_check_object_coercible(duk_context *ctx);   /* push the current 'this' binding; throw TypeError
-                                                                * if binding is not object coercible (CheckObjectCoercible).
-                                                                */
-duk_hobject *duk_push_this_coercible_to_object(duk_context *ctx);       /* duk_push_this() + CheckObjectCoercible() + duk_to_object() */
-duk_hstring *duk_push_this_coercible_to_string(duk_context *ctx);       /* duk_push_this() + CheckObjectCoercible() + duk_to_string() */
+/* XXX: add fastint support? */
+#define duk_push_u64(ctx,val) \
+	duk_push_number((ctx), (duk_double_t) (val))
+#define duk_push_i64(ctx,val) \
+	duk_push_number((ctx), (duk_double_t) (val))
 
-/* duk_push_uint() is guaranteed to support at least unsigned 32-bit range */
+/* duk_push_(u)int() is guaranteed to support at least (un)signed 32-bit range */
 #define duk_push_u32(ctx,val) \
 	duk_push_uint((ctx), (duk_uint_t) (val))
+#define duk_push_i32(ctx,val) \
+	duk_push_int((ctx), (duk_int_t) (val))
 
 /* sometimes stack and array indices need to go on the stack */
 #define duk_push_idx(ctx,val) \
@@ -5247,88 +7439,105 @@ duk_hstring *duk_push_this_coercible_to_string(duk_context *ctx);       /* duk_p
 #define duk_push_size_t(ctx,val) \
 	duk_push_uint((ctx), (duk_uint_t) (val))  /* XXX: assumed to fit for now */
 
-/* internal helper for looking up a tagged type */
-#define  DUK_GETTAGGED_FLAG_ALLOW_NULL  (1L << 24)
-#define  DUK_GETTAGGED_FLAG_CHECK_CLASS (1L << 25)
-#define  DUK_GETTAGGED_CLASS_SHIFT      16
-
-duk_heaphdr *duk_get_tagged_heaphdr_raw(duk_context *ctx, duk_idx_t index, duk_uint_t flags_and_tag);
-
-duk_hstring *duk_get_hstring(duk_context *ctx, duk_idx_t index);
-duk_hobject *duk_get_hobject(duk_context *ctx, duk_idx_t index);
-duk_hbuffer *duk_get_hbuffer(duk_context *ctx, duk_idx_t index);
-duk_hthread *duk_get_hthread(duk_context *ctx, duk_idx_t index);
-duk_hcompiledfunction *duk_get_hcompiledfunction(duk_context *ctx, duk_idx_t index);
-duk_hnativefunction *duk_get_hnativefunction(duk_context *ctx, duk_idx_t index);
-
-#define duk_get_hobject_with_class(ctx,index,classnum) \
-	((duk_hobject *) duk_get_tagged_heaphdr_raw((ctx), (index), \
-		DUK_TAG_OBJECT | DUK_GETTAGGED_FLAG_ALLOW_NULL | \
-		DUK_GETTAGGED_FLAG_CHECK_CLASS | ((classnum) << DUK_GETTAGGED_CLASS_SHIFT)))
-
-void *duk_get_voidptr(duk_context *ctx, duk_idx_t index);
-
-duk_hstring *duk_to_hstring(duk_context *ctx, duk_idx_t index);
-duk_int_t duk_to_int_clamped_raw(duk_context *ctx, duk_idx_t index, duk_int_t minval, duk_int_t maxval, duk_bool_t *out_clamped);  /* out_clamped=NULL, RangeError if outside range */
-duk_int_t duk_to_int_clamped(duk_context *ctx, duk_idx_t index, duk_int_t minval, duk_int_t maxval);
-duk_int_t duk_to_int_check_range(duk_context *ctx, duk_idx_t index, duk_int_t minval, duk_int_t maxval);
-
-duk_hstring *duk_require_hstring(duk_context *ctx, duk_idx_t index);
-duk_hobject *duk_require_hobject(duk_context *ctx, duk_idx_t index);
-duk_hbuffer *duk_require_hbuffer(duk_context *ctx, duk_idx_t index);
-duk_hthread *duk_require_hthread(duk_context *ctx, duk_idx_t index);
-duk_hcompiledfunction *duk_require_hcompiledfunction(duk_context *ctx, duk_idx_t index);
-duk_hnativefunction *duk_require_hnativefunction(duk_context *ctx, duk_idx_t index);
-
-#define duk_require_hobject_with_class(ctx,index,classnum) \
-	((duk_hobject *) duk_get_tagged_heaphdr_raw((ctx), (index), \
-		DUK_TAG_OBJECT | \
-		DUK_GETTAGGED_FLAG_CHECK_CLASS | ((classnum) << DUK_GETTAGGED_CLASS_SHIFT)))
-
-void duk_push_unused(duk_context *ctx);
-void duk_push_hstring(duk_context *ctx, duk_hstring *h);
-void duk_push_hstring_stridx(duk_context *ctx, duk_small_int_t stridx);
-void duk_push_hobject(duk_context *ctx, duk_hobject *h);
-void duk_push_hbuffer(duk_context *ctx, duk_hbuffer *h);
+DUK_INTERNAL_DECL duk_hstring *duk_get_hstring(duk_context *ctx, duk_idx_t index);
+DUK_INTERNAL_DECL duk_hobject *duk_get_hobject(duk_context *ctx, duk_idx_t index);
+DUK_INTERNAL_DECL duk_hbuffer *duk_get_hbuffer(duk_context *ctx, duk_idx_t index);
+DUK_INTERNAL_DECL duk_hthread *duk_get_hthread(duk_context *ctx, duk_idx_t index);
+DUK_INTERNAL_DECL duk_hcompiledfunction *duk_get_hcompiledfunction(duk_context *ctx, duk_idx_t index);
+DUK_INTERNAL_DECL duk_hnativefunction *duk_get_hnativefunction(duk_context *ctx, duk_idx_t index);
+
+DUK_INTERNAL_DECL duk_hobject *duk_get_hobject_with_class(duk_context *ctx, duk_idx_t index, duk_small_uint_t classnum);
+
+#if 0  /* This would be pointless: unexpected type and lightfunc would both return NULL */
+DUK_INTERNAL_DECL duk_hobject *duk_get_hobject_or_lfunc(duk_context *ctx, duk_idx_t index);
+#endif
+DUK_INTERNAL_DECL duk_hobject *duk_get_hobject_or_lfunc_coerce(duk_context *ctx, duk_idx_t index);
+
+#if 0  /*unused*/
+DUK_INTERNAL_DECL void *duk_get_voidptr(duk_context *ctx, duk_idx_t index);
+#endif
+
+DUK_INTERNAL_DECL duk_hstring *duk_to_hstring(duk_context *ctx, duk_idx_t index);
+#if defined(DUK_USE_DEBUGGER_SUPPORT)  /* only needed by debugger for now */
+DUK_INTERNAL_DECL duk_hstring *duk_safe_to_hstring(duk_context *ctx, duk_idx_t index);
+#endif
+DUK_INTERNAL_DECL void duk_to_object_class_string_top(duk_context *ctx);
+#if !defined(DUK_USE_PARANOID_ERRORS)
+DUK_INTERNAL_DECL void duk_push_hobject_class_string(duk_context *ctx, duk_hobject *h);
+#endif
+
+DUK_INTERNAL_DECL duk_int_t duk_to_int_clamped_raw(duk_context *ctx, duk_idx_t index, duk_int_t minval, duk_int_t maxval, duk_bool_t *out_clamped);  /* out_clamped=NULL, RangeError if outside range */
+DUK_INTERNAL_DECL duk_int_t duk_to_int_clamped(duk_context *ctx, duk_idx_t index, duk_int_t minval, duk_int_t maxval);
+DUK_INTERNAL_DECL duk_int_t duk_to_int_check_range(duk_context *ctx, duk_idx_t index, duk_int_t minval, duk_int_t maxval);
+#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
+DUK_INTERNAL_DECL duk_uint8_t duk_to_uint8clamped(duk_context *ctx, duk_idx_t index);
+#endif
+
+DUK_INTERNAL_DECL duk_hstring *duk_require_hstring(duk_context *ctx, duk_idx_t index);
+DUK_INTERNAL_DECL duk_hobject *duk_require_hobject(duk_context *ctx, duk_idx_t index);
+DUK_INTERNAL_DECL duk_hbuffer *duk_require_hbuffer(duk_context *ctx, duk_idx_t index);
+DUK_INTERNAL_DECL duk_hthread *duk_require_hthread(duk_context *ctx, duk_idx_t index);
+DUK_INTERNAL_DECL duk_hcompiledfunction *duk_require_hcompiledfunction(duk_context *ctx, duk_idx_t index);
+DUK_INTERNAL_DECL duk_hnativefunction *duk_require_hnativefunction(duk_context *ctx, duk_idx_t index);
+
+DUK_INTERNAL_DECL duk_hobject *duk_require_hobject_with_class(duk_context *ctx, duk_idx_t index, duk_small_uint_t classnum);
+
+DUK_INTERNAL_DECL duk_hobject *duk_require_hobject_or_lfunc(duk_context *ctx, duk_idx_t index);
+DUK_INTERNAL_DECL duk_hobject *duk_require_hobject_or_lfunc_coerce(duk_context *ctx, duk_idx_t index);
+
+DUK_INTERNAL_DECL void duk_push_hstring(duk_context *ctx, duk_hstring *h);
+DUK_INTERNAL_DECL void duk_push_hstring_stridx(duk_context *ctx, duk_small_int_t stridx);
+DUK_INTERNAL_DECL void duk_push_hobject(duk_context *ctx, duk_hobject *h);
+DUK_INTERNAL_DECL void duk_push_hbuffer(duk_context *ctx, duk_hbuffer *h);
 #define duk_push_hthread(ctx,h) \
 	duk_push_hobject((ctx), (duk_hobject *) (h))
 #define duk_push_hcompiledfunction(ctx,h) \
 	duk_push_hobject((ctx), (duk_hobject *) (h))
 #define duk_push_hnativefunction(ctx,h) \
 	duk_push_hobject((ctx), (duk_hobject *) (h))
-void duk_push_hobject_bidx(duk_context *ctx, duk_small_int_t builtin_idx);
-duk_idx_t duk_push_object_helper(duk_context *ctx, duk_uint_t hobject_flags_and_class, duk_small_int_t prototype_bidx);
-duk_idx_t duk_push_object_helper_proto(duk_context *ctx, duk_uint_t hobject_flags_and_class, duk_hobject *proto);
-duk_idx_t duk_push_object_internal(duk_context *ctx);
-duk_idx_t duk_push_compiledfunction(duk_context *ctx);
-void duk_push_c_function_noexotic(duk_context *ctx, duk_c_function func, duk_int_t nargs);
-void duk_push_c_function_noconstruct_noexotic(duk_context *ctx, duk_c_function func, duk_int_t nargs);
-
-duk_bool_t duk_get_prop_stridx(duk_context *ctx, duk_idx_t obj_index, duk_small_int_t stridx);     /* [] -> [val] */
-duk_bool_t duk_put_prop_stridx(duk_context *ctx, duk_idx_t obj_index, duk_small_int_t stridx);     /* [val] -> [] */
-duk_bool_t duk_del_prop_stridx(duk_context *ctx, duk_idx_t obj_index, duk_small_int_t stridx);     /* [] -> [] */
-duk_bool_t duk_has_prop_stridx(duk_context *ctx, duk_idx_t obj_index, duk_small_int_t stridx);     /* [] -> [] */
-
-duk_bool_t duk_get_prop_stridx_boolean(duk_context *ctx, duk_idx_t obj_index, duk_small_int_t stridx, duk_bool_t *out_has_prop);  /* [] -> [] */
-
-void duk_def_prop(duk_context *ctx, duk_idx_t obj_index, duk_small_uint_t desc_flags);  /* [key val] -> [] */
-void duk_def_prop_index(duk_context *ctx, duk_idx_t obj_index, duk_uarridx_t arr_index, duk_small_uint_t desc_flags);  /* [val] -> [] */
-void duk_def_prop_stridx(duk_context *ctx, duk_idx_t obj_index, duk_small_int_t stridx, duk_small_uint_t desc_flags);  /* [val] -> [] */
-void duk_def_prop_stridx_builtin(duk_context *ctx, duk_idx_t obj_index, duk_small_int_t stridx, duk_small_int_t builtin_idx, duk_small_uint_t desc_flags);  /* [] -> [] */
-void duk_def_prop_stridx_thrower(duk_context *ctx, duk_idx_t obj_index, duk_small_int_t stridx, duk_small_uint_t desc_flags);  /* [] -> [] */
+DUK_INTERNAL_DECL void duk_push_hobject_bidx(duk_context *ctx, duk_small_int_t builtin_idx);
+DUK_INTERNAL_DECL duk_idx_t duk_push_object_helper(duk_context *ctx, duk_uint_t hobject_flags_and_class, duk_small_int_t prototype_bidx);
+DUK_INTERNAL_DECL duk_idx_t duk_push_object_helper_proto(duk_context *ctx, duk_uint_t hobject_flags_and_class, duk_hobject *proto);
+DUK_INTERNAL_DECL duk_idx_t duk_push_object_internal(duk_context *ctx);
+DUK_INTERNAL_DECL duk_idx_t duk_push_compiledfunction(duk_context *ctx);
+DUK_INTERNAL_DECL void duk_push_c_function_noexotic(duk_context *ctx, duk_c_function func, duk_int_t nargs);
+DUK_INTERNAL_DECL void duk_push_c_function_noconstruct_noexotic(duk_context *ctx, duk_c_function func, duk_int_t nargs);
+
+DUK_INTERNAL_DECL void duk_push_string_funcptr(duk_context *ctx, duk_uint8_t *ptr, duk_size_t sz);
+DUK_INTERNAL_DECL void duk_push_lightfunc_name(duk_context *ctx, duk_tval *tv);
+DUK_INTERNAL_DECL void duk_push_lightfunc_tostring(duk_context *ctx, duk_tval *tv);
+DUK_INTERNAL_DECL duk_hbufferobject *duk_push_bufferobject_raw(duk_context *ctx, duk_uint_t hobject_flags_and_class, duk_small_int_t prototype_bidx);
+
+#if !defined(DUK_USE_PARANOID_ERRORS)
+DUK_INTERNAL_DECL const char *duk_push_string_readable(duk_context *ctx, duk_idx_t index);
+DUK_INTERNAL_DECL const char *duk_push_string_tval_readable(duk_context *ctx, duk_tval *tv);
+#endif
+
+DUK_INTERNAL_DECL duk_bool_t duk_get_prop_stridx(duk_context *ctx, duk_idx_t obj_index, duk_small_int_t stridx);     /* [] -> [val] */
+DUK_INTERNAL_DECL duk_bool_t duk_put_prop_stridx(duk_context *ctx, duk_idx_t obj_index, duk_small_int_t stridx);     /* [val] -> [] */
+DUK_INTERNAL_DECL duk_bool_t duk_del_prop_stridx(duk_context *ctx, duk_idx_t obj_index, duk_small_int_t stridx);     /* [] -> [] */
+DUK_INTERNAL_DECL duk_bool_t duk_has_prop_stridx(duk_context *ctx, duk_idx_t obj_index, duk_small_int_t stridx);     /* [] -> [] */
+
+DUK_INTERNAL_DECL duk_bool_t duk_get_prop_stridx_boolean(duk_context *ctx, duk_idx_t obj_index, duk_small_int_t stridx, duk_bool_t *out_has_prop);  /* [] -> [] */
+
+DUK_INTERNAL_DECL void duk_xdef_prop(duk_context *ctx, duk_idx_t obj_index, duk_small_uint_t desc_flags);  /* [key val] -> [] */
+DUK_INTERNAL_DECL void duk_xdef_prop_index(duk_context *ctx, duk_idx_t obj_index, duk_uarridx_t arr_index, duk_small_uint_t desc_flags);  /* [val] -> [] */
+DUK_INTERNAL_DECL void duk_xdef_prop_stridx(duk_context *ctx, duk_idx_t obj_index, duk_small_int_t stridx, duk_small_uint_t desc_flags);  /* [val] -> [] */
+DUK_INTERNAL_DECL void duk_xdef_prop_stridx_builtin(duk_context *ctx, duk_idx_t obj_index, duk_small_int_t stridx, duk_small_int_t builtin_idx, duk_small_uint_t desc_flags);  /* [] -> [] */
+DUK_INTERNAL_DECL void duk_xdef_prop_stridx_thrower(duk_context *ctx, duk_idx_t obj_index, duk_small_int_t stridx, duk_small_uint_t desc_flags);  /* [] -> [] */
 
 /* These are macros for now, but could be separate functions to reduce code
  * footprint (check call site count before refactoring).
  */
-#define duk_def_prop_wec(ctx,obj_index) \
-	duk_def_prop((ctx), (obj_index), DUK_PROPDESC_FLAGS_WEC)
-#define duk_def_prop_index_wec(ctx,obj_index,arr_index) \
-	duk_def_prop_index((ctx), (obj_index), (arr_index), DUK_PROPDESC_FLAGS_WEC)
-#define duk_def_prop_stridx_wec(ctx,obj_index,stridx) \
-	duk_def_prop_stridx((ctx), (obj_index), (stridx), DUK_PROPDESC_FLAGS_WEC)
+#define duk_xdef_prop_wec(ctx,obj_index) \
+	duk_xdef_prop((ctx), (obj_index), DUK_PROPDESC_FLAGS_WEC)
+#define duk_xdef_prop_index_wec(ctx,obj_index,arr_index) \
+	duk_xdef_prop_index((ctx), (obj_index), (arr_index), DUK_PROPDESC_FLAGS_WEC)
+#define duk_xdef_prop_stridx_wec(ctx,obj_index,stridx) \
+	duk_xdef_prop_stridx((ctx), (obj_index), (stridx), DUK_PROPDESC_FLAGS_WEC)
 
 /* Set object 'length'. */
-void duk_set_length(duk_context *ctx, duk_idx_t index, duk_size_t length);
+DUK_INTERNAL_DECL void duk_set_length(duk_context *ctx, duk_idx_t index, duk_size_t length);
 
 #endif  /* DUK_API_INTERNAL_H_INCLUDED */
 #line 1 "duk_hstring.h"
@@ -5359,7 +7568,12 @@ void duk_set_length(duk_context *ctx, duk_idx_t index, duk_size_t length);
  * This limit should be eliminated on 64-bit platforms (and increased
  * closer to maximum support on 32-bit platforms).
  */
+
+#if defined(DUK_USE_STRLEN16)
+#define DUK_HSTRING_MAX_BYTELEN                     (0x0000ffffUL)
+#else
 #define DUK_HSTRING_MAX_BYTELEN                     (0x7fffffffUL)
+#endif
 
 /* XXX: could add flags for "is valid CESU-8" (Ecmascript compatible strings),
  * "is valid UTF-8", "is valid extended UTF-8" (internal strings are not,
@@ -5372,33 +7586,77 @@ void duk_set_length(duk_context *ctx, duk_idx_t index, duk_size_t length);
 #define DUK_HSTRING_FLAG_RESERVED_WORD              DUK_HEAPHDR_USER_FLAG(2)  /* string is a reserved word (non-strict) */
 #define DUK_HSTRING_FLAG_STRICT_RESERVED_WORD       DUK_HEAPHDR_USER_FLAG(3)  /* string is a reserved word (strict) */
 #define DUK_HSTRING_FLAG_EVAL_OR_ARGUMENTS          DUK_HEAPHDR_USER_FLAG(4)  /* string is 'eval' or 'arguments' */
+#define DUK_HSTRING_FLAG_EXTDATA                    DUK_HEAPHDR_USER_FLAG(5)  /* string data is external (duk_hstring_external) */
 
 #define DUK_HSTRING_HAS_ARRIDX(x)                   DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_ARRIDX)
 #define DUK_HSTRING_HAS_INTERNAL(x)                 DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_INTERNAL)
 #define DUK_HSTRING_HAS_RESERVED_WORD(x)            DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_RESERVED_WORD)
 #define DUK_HSTRING_HAS_STRICT_RESERVED_WORD(x)     DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_STRICT_RESERVED_WORD)
 #define DUK_HSTRING_HAS_EVAL_OR_ARGUMENTS(x)        DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_EVAL_OR_ARGUMENTS)
+#define DUK_HSTRING_HAS_EXTDATA(x)                  DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_EXTDATA)
 
 #define DUK_HSTRING_SET_ARRIDX(x)                   DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_ARRIDX)
 #define DUK_HSTRING_SET_INTERNAL(x)                 DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_INTERNAL)
 #define DUK_HSTRING_SET_RESERVED_WORD(x)            DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_RESERVED_WORD)
 #define DUK_HSTRING_SET_STRICT_RESERVED_WORD(x)     DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_STRICT_RESERVED_WORD)
 #define DUK_HSTRING_SET_EVAL_OR_ARGUMENTS(x)        DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_EVAL_OR_ARGUMENTS)
+#define DUK_HSTRING_SET_EXTDATA(x)                  DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_EXTDATA)
 
 #define DUK_HSTRING_CLEAR_ARRIDX(x)                 DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_ARRIDX)
 #define DUK_HSTRING_CLEAR_INTERNAL(x)               DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_INTERNAL)
 #define DUK_HSTRING_CLEAR_RESERVED_WORD(x)          DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_RESERVED_WORD)
 #define DUK_HSTRING_CLEAR_STRICT_RESERVED_WORD(x)   DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_STRICT_RESERVED_WORD)
 #define DUK_HSTRING_CLEAR_EVAL_OR_ARGUMENTS(x)      DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_EVAL_OR_ARGUMENTS)
+#define DUK_HSTRING_CLEAR_EXTDATA(x)                DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_EXTDATA)
 
-#define DUK_HSTRING_IS_ASCII(x)                     ((x)->blen == (x)->clen)
-#define DUK_HSTRING_IS_EMPTY(x)                     ((x)->blen == 0)
+#define DUK_HSTRING_IS_ASCII(x)                     (DUK_HSTRING_GET_BYTELEN((x)) == DUK_HSTRING_GET_CHARLEN((x)))
+#define DUK_HSTRING_IS_EMPTY(x)                     (DUK_HSTRING_GET_BYTELEN((x)) == 0)
 
+#if defined(DUK_USE_STRHASH16)
+#define DUK_HSTRING_GET_HASH(x)                     ((x)->hdr.h_flags >> 16)
+#define DUK_HSTRING_SET_HASH(x,v) do { \
+		(x)->hdr.h_flags = ((x)->hdr.h_flags & 0x0000ffffUL) | ((v) << 16); \
+	} while (0)
+#else
 #define DUK_HSTRING_GET_HASH(x)                     ((x)->hash)
+#define DUK_HSTRING_SET_HASH(x,v) do { \
+		(x)->hash = (v); \
+	} while (0)
+#endif
+
+#if defined(DUK_USE_STRLEN16)
+#define DUK_HSTRING_GET_BYTELEN(x)                  ((x)->blen16)
+#define DUK_HSTRING_SET_BYTELEN(x,v) do { \
+		(x)->blen16 = (v); \
+	} while (0)
+#define DUK_HSTRING_GET_CHARLEN(x)                  ((x)->clen16)
+#define DUK_HSTRING_SET_CHARLEN(x,v) do { \
+		(x)->clen16 = (v); \
+	} while (0)
+#else
 #define DUK_HSTRING_GET_BYTELEN(x)                  ((x)->blen)
+#define DUK_HSTRING_SET_BYTELEN(x,v) do { \
+		(x)->blen = (v); \
+	} while (0)
 #define DUK_HSTRING_GET_CHARLEN(x)                  ((x)->clen)
-#define DUK_HSTRING_GET_DATA(x)                     ((duk_uint8_t *) ((x) + 1))
-#define DUK_HSTRING_GET_DATA_END(x)                 (((duk_uint8_t *) ((x) + 1)) + ((x)->blen))
+#define DUK_HSTRING_SET_CHARLEN(x,v) do { \
+		(x)->clen = (v); \
+	} while (0)
+#endif
+
+#if defined(DUK_USE_HSTRING_EXTDATA)
+#define DUK_HSTRING_GET_EXTDATA(x) \
+	((x)->extdata)
+#define DUK_HSTRING_GET_DATA(x) \
+	(DUK_HSTRING_HAS_EXTDATA((x)) ? \
+		DUK_HSTRING_GET_EXTDATA((duk_hstring_external *) (x)) : ((const duk_uint8_t *) ((x) + 1)))
+#else
+#define DUK_HSTRING_GET_DATA(x) \
+	((const duk_uint8_t *) ((x) + 1))
+#endif
+
+#define DUK_HSTRING_GET_DATA_END(x) \
+	(DUK_HSTRING_GET_DATA((x)) + (x)->blen)
 
 /* marker value; in E5 2^32-1 is not a valid array index (2^32-2 is highest valid) */
 #define DUK_HSTRING_NO_ARRAY_INDEX  (0xffffffffUL)
@@ -5418,8 +7676,10 @@ void duk_set_length(duk_context *ctx, duk_idx_t index, duk_size_t length);
  */
 
 struct duk_hstring {
-	/* smaller heaphdr than for other objects, because strings are held
-	 * in string intern table which requires no link pointers.
+	/* Smaller heaphdr than for other objects, because strings are held
+	 * in string intern table which requires no link pointers.  Much of
+	 * the 32-bit flags field is unused by flags, so we can stuff a 16-bit
+	 * field in there.
 	 */
 	duk_heaphdr_string hdr;
 
@@ -5427,9 +7687,26 @@ struct duk_hstring {
 	 * shared heap header.  Good hashing needs more hash bits though.
 	 */
 
-	duk_uint32_t hash;         /* string hash */
-	duk_uint32_t blen;         /* length in bytes (not counting NUL term) */
-	duk_uint32_t clen;         /* length in codepoints (must be E5 compatible) */
+	/* string hash */
+#if defined(DUK_USE_STRHASH16)
+	/* If 16-bit hash is in use, stuff it into duk_heaphdr_string flags. */
+#else
+	duk_uint32_t hash;
+#endif
+
+	/* length in bytes (not counting NUL term) */
+#if defined(DUK_USE_STRLEN16)
+	duk_uint16_t blen16;
+#else
+	duk_uint32_t blen;
+#endif
+
+	/* length in codepoints (must be E5 compatible) */
+#if defined(DUK_USE_STRLEN16)
+	duk_uint16_t clen16;
+#else
+	duk_uint32_t clen;
+#endif
 
 	/*
 	 *  String value of 'blen+1' bytes follows (+1 for NUL termination
@@ -5439,14 +7716,26 @@ struct duk_hstring {
 	 */
 };
 
+/* The external string struct is defined even when the feature is inactive. */
+struct duk_hstring_external {
+	duk_hstring str;
+
+	/*
+	 *  For an external string, the NUL-terminated string data is stored
+	 *  externally.  The user must guarantee that data behind this pointer
+	 *  doesn't change while it's used.
+	 */
+
+	const duk_uint8_t *extdata;
+};
+
 /*
  *  Prototypes
  */
 
-duk_ucodepoint_t duk_hstring_char_code_at_raw(duk_hthread *thr, duk_hstring *h, duk_uint_t pos);
+DUK_INTERNAL_DECL duk_ucodepoint_t duk_hstring_char_code_at_raw(duk_hthread *thr, duk_hstring *h, duk_uint_t pos);
 
 #endif  /* DUK_HSTRING_H_INCLUDED */
-
 #line 1 "duk_hobject.h"
 /*
  *  Heap object representation.
@@ -5471,7 +7760,7 @@ duk_ucodepoint_t duk_hstring_char_code_at_raw(duk_hthread *thr, duk_hstring *h,
  *       abandoned and moved to the 'entry part'.
  *
  *    3. An optional 'hash part' is used to optimize lookups of the entry
- *       part; it is used only for objects with sufficiently many properties 
+ *       part; it is used only for objects with sufficiently many properties
  *       and can be abandoned without loss of information.
  *
  *  These three conceptual parts are stored in a single memory allocated area.
@@ -5488,21 +7777,20 @@ duk_ucodepoint_t duk_hstring_char_code_at_raw(duk_hthread *thr, duk_hstring *h,
 #define DUK_HOBJECT_FLAG_BOUND                 DUK_HEAPHDR_USER_FLAG(2)   /* object established using Function.prototype.bind() */
 #define DUK_HOBJECT_FLAG_COMPILEDFUNCTION      DUK_HEAPHDR_USER_FLAG(4)   /* object is a compiled function (duk_hcompiledfunction) */
 #define DUK_HOBJECT_FLAG_NATIVEFUNCTION        DUK_HEAPHDR_USER_FLAG(5)   /* object is a native function (duk_hnativefunction) */
-#define DUK_HOBJECT_FLAG_THREAD                DUK_HEAPHDR_USER_FLAG(6)   /* object is a thread (duk_hthread) */
-#define DUK_HOBJECT_FLAG_ARRAY_PART            DUK_HEAPHDR_USER_FLAG(7)   /* object has an array part (a_size may still be 0) */
-#define DUK_HOBJECT_FLAG_STRICT                DUK_HEAPHDR_USER_FLAG(8)   /* function: function object is strict */
-#define DUK_HOBJECT_FLAG_NOTAIL                DUK_HEAPHDR_USER_FLAG(9)   /* function: function must not be tailcalled */
-#define DUK_HOBJECT_FLAG_NEWENV                DUK_HEAPHDR_USER_FLAG(10)  /* function: create new environment when called (see duk_hcompiledfunction) */
-#define DUK_HOBJECT_FLAG_NAMEBINDING           DUK_HEAPHDR_USER_FLAG(11)  /* function: create binding for func name (function templates only, used for named function expressions) */
-#define DUK_HOBJECT_FLAG_CREATEARGS            DUK_HEAPHDR_USER_FLAG(12)  /* function: create an arguments object on function call */
-#define DUK_HOBJECT_FLAG_ENVRECCLOSED          DUK_HEAPHDR_USER_FLAG(13)  /* envrec: (declarative) record is closed */
-#define DUK_HOBJECT_FLAG_EXOTIC_ARRAY          DUK_HEAPHDR_USER_FLAG(14)  /* 'Array' object, array length and index exotic behavior */
-#define DUK_HOBJECT_FLAG_EXOTIC_STRINGOBJ      DUK_HEAPHDR_USER_FLAG(15)  /* 'String' object, array index exotic behavior */
-#define DUK_HOBJECT_FLAG_EXOTIC_ARGUMENTS      DUK_HEAPHDR_USER_FLAG(16)  /* 'Arguments' object and has arguments exotic behavior (non-strict callee) */
-#define DUK_HOBJECT_FLAG_EXOTIC_DUKFUNC        DUK_HEAPHDR_USER_FLAG(17)  /* Duktape/C (nativefunction) object, exotic 'length' */
-#define DUK_HOBJECT_FLAG_EXOTIC_BUFFEROBJ      DUK_HEAPHDR_USER_FLAG(18)  /* 'Buffer' object, array index exotic behavior, virtual 'length' */
+#define DUK_HOBJECT_FLAG_BUFFEROBJECT          DUK_HEAPHDR_USER_FLAG(6)   /* object is a buffer object (duk_hbufferobject) (always exotic) */
+#define DUK_HOBJECT_FLAG_THREAD                DUK_HEAPHDR_USER_FLAG(7)   /* object is a thread (duk_hthread) */
+#define DUK_HOBJECT_FLAG_ARRAY_PART            DUK_HEAPHDR_USER_FLAG(8)   /* object has an array part (a_size may still be 0) */
+#define DUK_HOBJECT_FLAG_STRICT                DUK_HEAPHDR_USER_FLAG(9)   /* function: function object is strict */
+#define DUK_HOBJECT_FLAG_NOTAIL                DUK_HEAPHDR_USER_FLAG(10)  /* function: function must not be tail called */
+#define DUK_HOBJECT_FLAG_NEWENV                DUK_HEAPHDR_USER_FLAG(11)  /* function: create new environment when called (see duk_hcompiledfunction) */
+#define DUK_HOBJECT_FLAG_NAMEBINDING           DUK_HEAPHDR_USER_FLAG(12)  /* function: create binding for func name (function templates only, used for named function expressions) */
+#define DUK_HOBJECT_FLAG_CREATEARGS            DUK_HEAPHDR_USER_FLAG(13)  /* function: create an arguments object on function call */
+#define DUK_HOBJECT_FLAG_ENVRECCLOSED          DUK_HEAPHDR_USER_FLAG(14)  /* envrec: (declarative) record is closed */
+#define DUK_HOBJECT_FLAG_EXOTIC_ARRAY          DUK_HEAPHDR_USER_FLAG(15)  /* 'Array' object, array length and index exotic behavior */
+#define DUK_HOBJECT_FLAG_EXOTIC_STRINGOBJ      DUK_HEAPHDR_USER_FLAG(16)  /* 'String' object, array index exotic behavior */
+#define DUK_HOBJECT_FLAG_EXOTIC_ARGUMENTS      DUK_HEAPHDR_USER_FLAG(17)  /* 'Arguments' object and has arguments exotic behavior (non-strict callee) */
+#define DUK_HOBJECT_FLAG_EXOTIC_DUKFUNC        DUK_HEAPHDR_USER_FLAG(18)  /* Duktape/C (nativefunction) object, exotic 'length' */
 #define DUK_HOBJECT_FLAG_EXOTIC_PROXYOBJ       DUK_HEAPHDR_USER_FLAG(19)  /* 'Proxy' object */
-/* bit 20 unused */
 
 #define DUK_HOBJECT_FLAG_CLASS_BASE            DUK_HEAPHDR_USER_FLAG_NUMBER(21)
 #define DUK_HOBJECT_FLAG_CLASS_BITS            5
@@ -5512,6 +7800,9 @@ duk_ucodepoint_t duk_hstring_char_code_at_raw(duk_hthread *thr, duk_hstring *h,
 #define DUK_HOBJECT_SET_CLASS_NUMBER(h,v)      \
 	DUK_HEAPHDR_SET_FLAG_RANGE(&(h)->hdr, DUK_HOBJECT_FLAG_CLASS_BASE, DUK_HOBJECT_FLAG_CLASS_BITS, (v))
 
+#define DUK_HOBJECT_GET_CLASS_MASK(h)          \
+	(1UL << DUK_HEAPHDR_GET_FLAG_RANGE(&(h)->hdr, DUK_HOBJECT_FLAG_CLASS_BASE, DUK_HOBJECT_FLAG_CLASS_BITS))
+
 /* Macro for creating flag initializer from a class number.
  * Unsigned type cast is needed to avoid warnings about coercing
  * a signed integer to an unsigned one; the largest class values
@@ -5536,9 +7827,68 @@ duk_ucodepoint_t duk_hstring_char_code_at_raw(duk_hthread *thr, duk_hstring *h,
 #define DUK_HOBJECT_CLASS_GLOBAL               13
 #define DUK_HOBJECT_CLASS_OBJENV               14  /* custom */
 #define DUK_HOBJECT_CLASS_DECENV               15  /* custom */
-#define DUK_HOBJECT_CLASS_BUFFER               16  /* custom */
+#define DUK_HOBJECT_CLASS_BUFFER               16  /* custom; implies DUK_HOBJECT_IS_BUFFEROBJECT */
 #define DUK_HOBJECT_CLASS_POINTER              17  /* custom */
-#define DUK_HOBJECT_CLASS_THREAD               18  /* custom */
+#define DUK_HOBJECT_CLASS_THREAD               18  /* custom; implies DUK_HOBJECT_IS_THREAD */
+#define DUK_HOBJECT_CLASS_ARRAYBUFFER          19  /* implies DUK_HOBJECT_IS_BUFFEROBJECT */
+#define DUK_HOBJECT_CLASS_DATAVIEW             20
+#define DUK_HOBJECT_CLASS_INT8ARRAY            21
+#define DUK_HOBJECT_CLASS_UINT8ARRAY           22
+#define DUK_HOBJECT_CLASS_UINT8CLAMPEDARRAY    23
+#define DUK_HOBJECT_CLASS_INT16ARRAY           24
+#define DUK_HOBJECT_CLASS_UINT16ARRAY          25
+#define DUK_HOBJECT_CLASS_INT32ARRAY           26
+#define DUK_HOBJECT_CLASS_UINT32ARRAY          27
+#define DUK_HOBJECT_CLASS_FLOAT32ARRAY         28
+#define DUK_HOBJECT_CLASS_FLOAT64ARRAY         29
+#define DUK_HOBJECT_CLASS_MAX                  29
+
+/* class masks */
+#define DUK_HOBJECT_CMASK_ALL                  ((1UL << (DUK_HOBJECT_CLASS_MAX + 1)) - 1UL)
+#define DUK_HOBJECT_CMASK_UNUSED               (1UL << DUK_HOBJECT_CLASS_UNUSED)
+#define DUK_HOBJECT_CMASK_ARGUMENTS            (1UL << DUK_HOBJECT_CLASS_ARGUMENTS)
+#define DUK_HOBJECT_CMASK_ARRAY                (1UL << DUK_HOBJECT_CLASS_ARRAY)
+#define DUK_HOBJECT_CMASK_BOOLEAN              (1UL << DUK_HOBJECT_CLASS_BOOLEAN)
+#define DUK_HOBJECT_CMASK_DATE                 (1UL << DUK_HOBJECT_CLASS_DATE)
+#define DUK_HOBJECT_CMASK_ERROR                (1UL << DUK_HOBJECT_CLASS_ERROR)
+#define DUK_HOBJECT_CMASK_FUNCTION             (1UL << DUK_HOBJECT_CLASS_FUNCTION)
+#define DUK_HOBJECT_CMASK_JSON                 (1UL << DUK_HOBJECT_CLASS_JSON)
+#define DUK_HOBJECT_CMASK_MATH                 (1UL << DUK_HOBJECT_CLASS_MATH)
+#define DUK_HOBJECT_CMASK_NUMBER               (1UL << DUK_HOBJECT_CLASS_NUMBER)
+#define DUK_HOBJECT_CMASK_OBJECT               (1UL << DUK_HOBJECT_CLASS_OBJECT)
+#define DUK_HOBJECT_CMASK_REGEXP               (1UL << DUK_HOBJECT_CLASS_REGEXP)
+#define DUK_HOBJECT_CMASK_STRING               (1UL << DUK_HOBJECT_CLASS_STRING)
+#define DUK_HOBJECT_CMASK_GLOBAL               (1UL << DUK_HOBJECT_CLASS_GLOBAL)
+#define DUK_HOBJECT_CMASK_OBJENV               (1UL << DUK_HOBJECT_CLASS_OBJENV)
+#define DUK_HOBJECT_CMASK_DECENV               (1UL << DUK_HOBJECT_CLASS_DECENV)
+#define DUK_HOBJECT_CMASK_BUFFER               (1UL << DUK_HOBJECT_CLASS_BUFFER)
+#define DUK_HOBJECT_CMASK_POINTER              (1UL << DUK_HOBJECT_CLASS_POINTER)
+#define DUK_HOBJECT_CMASK_THREAD               (1UL << DUK_HOBJECT_CLASS_THREAD)
+#define DUK_HOBJECT_CMASK_ARRAYBUFFER          (1UL << DUK_HOBJECT_CLASS_ARRAYBUFFER)
+#define DUK_HOBJECT_CMASK_DATAVIEW             (1UL << DUK_HOBJECT_CLASS_DATAVIEW)
+#define DUK_HOBJECT_CMASK_INT8ARRAY            (1UL << DUK_HOBJECT_CLASS_INT8ARRAY)
+#define DUK_HOBJECT_CMASK_UINT8ARRAY           (1UL << DUK_HOBJECT_CLASS_UINT8ARRAY)
+#define DUK_HOBJECT_CMASK_UINT8CLAMPEDARRAY    (1UL << DUK_HOBJECT_CLASS_UINT8CLAMPEDARRAY)
+#define DUK_HOBJECT_CMASK_INT16ARRAY           (1UL << DUK_HOBJECT_CLASS_INT16ARRAY)
+#define DUK_HOBJECT_CMASK_UINT16ARRAY          (1UL << DUK_HOBJECT_CLASS_UINT16ARRAY)
+#define DUK_HOBJECT_CMASK_INT32ARRAY           (1UL << DUK_HOBJECT_CLASS_INT32ARRAY)
+#define DUK_HOBJECT_CMASK_UINT32ARRAY          (1UL << DUK_HOBJECT_CLASS_UINT32ARRAY)
+#define DUK_HOBJECT_CMASK_FLOAT32ARRAY         (1UL << DUK_HOBJECT_CLASS_FLOAT32ARRAY)
+#define DUK_HOBJECT_CMASK_FLOAT64ARRAY         (1UL << DUK_HOBJECT_CLASS_FLOAT64ARRAY)
+
+#define DUK_HOBJECT_CMASK_ALL_BUFFEROBJECTS \
+	(DUK_HOBJECT_CMASK_BUFFER | \
+	 DUK_HOBJECT_CMASK_ARRAYBUFFER | \
+	 DUK_HOBJECT_CMASK_DATAVIEW | \
+	 DUK_HOBJECT_CMASK_INT8ARRAY | \
+	 DUK_HOBJECT_CMASK_UINT8ARRAY | \
+	 DUK_HOBJECT_CMASK_UINT8CLAMPEDARRAY | \
+	 DUK_HOBJECT_CMASK_INT16ARRAY | \
+	 DUK_HOBJECT_CMASK_UINT16ARRAY | \
+	 DUK_HOBJECT_CMASK_INT32ARRAY | \
+	 DUK_HOBJECT_CMASK_UINT32ARRAY | \
+	 DUK_HOBJECT_CMASK_FLOAT32ARRAY | \
+	 DUK_HOBJECT_CMASK_FLOAT64ARRAY)
 
 #define DUK_HOBJECT_IS_OBJENV(h)               (DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_OBJENV)
 #define DUK_HOBJECT_IS_DECENV(h)               (DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_DECENV)
@@ -5546,6 +7896,7 @@ duk_ucodepoint_t duk_hstring_char_code_at_raw(duk_hthread *thr, duk_hstring *h,
 #define DUK_HOBJECT_IS_ARRAY(h)                (DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_ARRAY)
 #define DUK_HOBJECT_IS_COMPILEDFUNCTION(h)     DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_COMPILEDFUNCTION)
 #define DUK_HOBJECT_IS_NATIVEFUNCTION(h)       DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NATIVEFUNCTION)
+#define DUK_HOBJECT_IS_BUFFEROBJECT(h)         DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_BUFFEROBJECT)
 #define DUK_HOBJECT_IS_THREAD(h)               DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_THREAD)
 
 #define DUK_HOBJECT_IS_NONBOUND_FUNCTION(h)    DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, \
@@ -5567,7 +7918,7 @@ duk_ucodepoint_t duk_hstring_char_code_at_raw(duk_hthread *thr, duk_hstring *h,
                                                 DUK_HOBJECT_FLAG_EXOTIC_ARGUMENTS | \
                                                 DUK_HOBJECT_FLAG_EXOTIC_STRINGOBJ | \
                                                 DUK_HOBJECT_FLAG_EXOTIC_DUKFUNC | \
-                                                DUK_HOBJECT_FLAG_EXOTIC_BUFFEROBJ | \
+                                                DUK_HOBJECT_FLAG_BUFFEROBJECT | \
                                                 DUK_HOBJECT_FLAG_EXOTIC_PROXYOBJ)
 
 #define DUK_HOBJECT_HAS_EXOTIC_BEHAVIOR(h)     DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_EXOTIC_BEHAVIOR_FLAGS)
@@ -5577,6 +7928,7 @@ duk_ucodepoint_t duk_hstring_char_code_at_raw(duk_hthread *thr, duk_hstring *h,
 #define DUK_HOBJECT_HAS_BOUND(h)               DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_BOUND)
 #define DUK_HOBJECT_HAS_COMPILEDFUNCTION(h)    DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_COMPILEDFUNCTION)
 #define DUK_HOBJECT_HAS_NATIVEFUNCTION(h)      DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NATIVEFUNCTION)
+#define DUK_HOBJECT_HAS_BUFFEROBJECT(h)        DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_BUFFEROBJECT)
 #define DUK_HOBJECT_HAS_THREAD(h)              DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_THREAD)
 #define DUK_HOBJECT_HAS_ARRAY_PART(h)          DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_ARRAY_PART)
 #define DUK_HOBJECT_HAS_STRICT(h)              DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_STRICT)
@@ -5589,7 +7941,6 @@ duk_ucodepoint_t duk_hstring_char_code_at_raw(duk_hthread *thr, duk_hstring *h,
 #define DUK_HOBJECT_HAS_EXOTIC_STRINGOBJ(h)    DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_STRINGOBJ)
 #define DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(h)    DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_ARGUMENTS)
 #define DUK_HOBJECT_HAS_EXOTIC_DUKFUNC(h)      DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_DUKFUNC)
-#define DUK_HOBJECT_HAS_EXOTIC_BUFFEROBJ(h)    DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_BUFFEROBJ)
 #define DUK_HOBJECT_HAS_EXOTIC_PROXYOBJ(h)     DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_PROXYOBJ)
 
 #define DUK_HOBJECT_SET_EXTENSIBLE(h)          DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXTENSIBLE)
@@ -5597,6 +7948,7 @@ duk_ucodepoint_t duk_hstring_char_code_at_raw(duk_hthread *thr, duk_hstring *h,
 #define DUK_HOBJECT_SET_BOUND(h)               DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_BOUND)
 #define DUK_HOBJECT_SET_COMPILEDFUNCTION(h)    DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_COMPILEDFUNCTION)
 #define DUK_HOBJECT_SET_NATIVEFUNCTION(h)      DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NATIVEFUNCTION)
+#define DUK_HOBJECT_SET_BUFFEROBJECT(h)        DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_BUFFEROBJECT)
 #define DUK_HOBJECT_SET_THREAD(h)              DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_THREAD)
 #define DUK_HOBJECT_SET_ARRAY_PART(h)          DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_ARRAY_PART)
 #define DUK_HOBJECT_SET_STRICT(h)              DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_STRICT)
@@ -5609,7 +7961,6 @@ duk_ucodepoint_t duk_hstring_char_code_at_raw(duk_hthread *thr, duk_hstring *h,
 #define DUK_HOBJECT_SET_EXOTIC_STRINGOBJ(h)    DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_STRINGOBJ)
 #define DUK_HOBJECT_SET_EXOTIC_ARGUMENTS(h)    DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_ARGUMENTS)
 #define DUK_HOBJECT_SET_EXOTIC_DUKFUNC(h)      DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_DUKFUNC)
-#define DUK_HOBJECT_SET_EXOTIC_BUFFEROBJ(h)    DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_BUFFEROBJ)
 #define DUK_HOBJECT_SET_EXOTIC_PROXYOBJ(h)     DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_PROXYOBJ)
 
 #define DUK_HOBJECT_CLEAR_EXTENSIBLE(h)        DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXTENSIBLE)
@@ -5617,6 +7968,7 @@ duk_ucodepoint_t duk_hstring_char_code_at_raw(duk_hthread *thr, duk_hstring *h,
 #define DUK_HOBJECT_CLEAR_BOUND(h)             DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_BOUND)
 #define DUK_HOBJECT_CLEAR_COMPILEDFUNCTION(h)  DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_COMPILEDFUNCTION)
 #define DUK_HOBJECT_CLEAR_NATIVEFUNCTION(h)    DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NATIVEFUNCTION)
+#define DUK_HOBJECT_CLEAR_BUFFEROBJECT(h)      DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_BUFFEROBJECT)
 #define DUK_HOBJECT_CLEAR_THREAD(h)            DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_THREAD)
 #define DUK_HOBJECT_CLEAR_ARRAY_PART(h)        DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_ARRAY_PART)
 #define DUK_HOBJECT_CLEAR_STRICT(h)            DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_STRICT)
@@ -5629,7 +7981,6 @@ duk_ucodepoint_t duk_hstring_char_code_at_raw(duk_hthread *thr, duk_hstring *h,
 #define DUK_HOBJECT_CLEAR_EXOTIC_STRINGOBJ(h)  DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_STRINGOBJ)
 #define DUK_HOBJECT_CLEAR_EXOTIC_ARGUMENTS(h)  DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_ARGUMENTS)
 #define DUK_HOBJECT_CLEAR_EXOTIC_DUKFUNC(h)    DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_DUKFUNC)
-#define DUK_HOBJECT_CLEAR_EXOTIC_BUFFEROBJ(h)  DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_BUFFEROBJ)
 #define DUK_HOBJECT_CLEAR_EXOTIC_PROXYOBJ(h)   DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_PROXYOBJ)
 
 /* flags used for property attributes in duk_propdesc and packed flags */
@@ -5663,34 +8014,73 @@ duk_ucodepoint_t duk_hstring_char_code_at_raw(duk_hthread *thr, duk_hstring *h,
                                                  DUK_PROPDESC_FLAG_CONFIGURABLE)
 
 /*
- *  Macros to access the 'p' allocation.
+ *  Macro for object validity check
+ *
+ *  Assert for currently guaranteed relations between flags, for instance.
+ */
+
+#define DUK_ASSERT_HOBJECT_VALID(h) do { \
+		DUK_ASSERT((h) != NULL); \
+		DUK_ASSERT(!DUK_HOBJECT_IS_CALLABLE((h)) || \
+		           DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_FUNCTION); \
+		DUK_ASSERT(!DUK_HOBJECT_IS_BUFFEROBJECT((h)) || \
+		           (DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_BUFFER || \
+		            DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_ARRAYBUFFER || \
+		            DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_DATAVIEW || \
+		            DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_INT8ARRAY || \
+		            DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_UINT8ARRAY || \
+		            DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_UINT8CLAMPEDARRAY || \
+		            DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_INT16ARRAY || \
+		            DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_UINT16ARRAY || \
+		            DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_INT32ARRAY || \
+		            DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_UINT32ARRAY || \
+		            DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_FLOAT32ARRAY || \
+		            DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_FLOAT64ARRAY)); \
+	} while (0)
+
+/*
+ *  Macros to access the 'props' allocation.
  */
 
+#if defined(DUK_USE_HEAPPTR16)
+#define DUK_HOBJECT_GET_PROPS(heap,h) \
+	((duk_uint8_t *) DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, ((duk_heaphdr *) (h))->h_extra16))
+#define DUK_HOBJECT_SET_PROPS(heap,h,x) do { \
+		((duk_heaphdr *) (h))->h_extra16 = DUK_USE_HEAPPTR_ENC16((heap)->heap_udata, (void *) (x)); \
+	} while (0)
+#else
+#define DUK_HOBJECT_GET_PROPS(heap,h) \
+	((h)->props)
+#define DUK_HOBJECT_SET_PROPS(heap,h,x) do { \
+		(h)->props = (duk_uint8_t *) (x); \
+	} while (0)
+#endif
+
 #if defined(DUK_USE_HOBJECT_LAYOUT_1)
 /* LAYOUT 1 */
-#define DUK_HOBJECT_E_GET_KEY_BASE(h)           \
-	((duk_hstring **) ( \
-		(h)->p \
+#define DUK_HOBJECT_E_GET_KEY_BASE(heap,h) \
+	((duk_hstring **) (void *) ( \
+		DUK_HOBJECT_GET_PROPS((heap), (h)) \
 	))
-#define DUK_HOBJECT_E_GET_VALUE_BASE(h)         \
-	((duk_propvalue *) ( \
-		(h)->p + \
-			(h)->e_size * sizeof(duk_hstring *) \
+#define DUK_HOBJECT_E_GET_VALUE_BASE(heap,h) \
+	((duk_propvalue *) (void *) ( \
+		DUK_HOBJECT_GET_PROPS((heap), (h)) + \
+			DUK_HOBJECT_GET_ESIZE((h)) * sizeof(duk_hstring *) \
 	))
-#define DUK_HOBJECT_E_GET_FLAGS_BASE(h)         \
-	((duk_uint8_t *) ( \
-		(h)->p + (h)->e_size * (sizeof(duk_hstring *) + sizeof(duk_propvalue)) \
+#define DUK_HOBJECT_E_GET_FLAGS_BASE(heap,h) \
+	((duk_uint8_t *) (void *) ( \
+		DUK_HOBJECT_GET_PROPS((heap), (h)) + DUK_HOBJECT_GET_ESIZE((h)) * (sizeof(duk_hstring *) + sizeof(duk_propvalue)) \
 	))
-#define DUK_HOBJECT_A_GET_BASE(h)               \
-	((duk_tval *) ( \
-		(h)->p + \
-			(h)->e_size * (sizeof(duk_hstring *) + sizeof(duk_propvalue) + sizeof(duk_uint8_t)) \
+#define DUK_HOBJECT_A_GET_BASE(heap,h) \
+	((duk_tval *) (void *) ( \
+		DUK_HOBJECT_GET_PROPS((heap), (h)) + \
+			DUK_HOBJECT_GET_ESIZE((h)) * (sizeof(duk_hstring *) + sizeof(duk_propvalue) + sizeof(duk_uint8_t)) \
 	))
-#define DUK_HOBJECT_H_GET_BASE(h)               \
-	((duk_uint32_t *) ( \
-		(h)->p + \
-			(h)->e_size * (sizeof(duk_hstring *) + sizeof(duk_propvalue) + sizeof(duk_uint8_t)) + \
-			(h)->a_size * sizeof(duk_tval) \
+#define DUK_HOBJECT_H_GET_BASE(heap,h) \
+	((duk_uint32_t *) (void *) ( \
+		DUK_HOBJECT_GET_PROPS((heap), (h)) + \
+			DUK_HOBJECT_GET_ESIZE((h)) * (sizeof(duk_hstring *) + sizeof(duk_propvalue) + sizeof(duk_uint8_t)) + \
+			DUK_HOBJECT_GET_ASIZE((h)) * sizeof(duk_tval) \
 	))
 #define DUK_HOBJECT_P_COMPUTE_SIZE(n_ent,n_arr,n_hash) \
 	( \
@@ -5699,46 +8089,48 @@ duk_ucodepoint_t duk_hstring_char_code_at_raw(duk_hthread *thr, duk_hstring *h,
 		(n_hash) * sizeof(duk_uint32_t) \
 	)
 #define DUK_HOBJECT_P_SET_REALLOC_PTRS(p_base,set_e_k,set_e_pv,set_e_f,set_a,set_h,n_ent,n_arr,n_hash)  do { \
-		(set_e_k) = (duk_hstring **) (p_base); \
-		(set_e_pv) = (duk_propvalue *) ((set_e_k) + (n_ent)); \
-		(set_e_f) = (duk_uint8_t *) ((set_e_pv) + (n_ent)); \
-		(set_a) = (duk_tval *) ((set_e_f) + (n_ent)); \
-		(set_h) = (duk_uint32_t *) ((set_a) + (n_arr)); \
+		(set_e_k) = (duk_hstring **) (void *) (p_base); \
+		(set_e_pv) = (duk_propvalue *) (void *) ((set_e_k) + (n_ent)); \
+		(set_e_f) = (duk_uint8_t *) (void *) ((set_e_pv) + (n_ent)); \
+		(set_a) = (duk_tval *) (void *) ((set_e_f) + (n_ent)); \
+		(set_h) = (duk_uint32_t *) (void *) ((set_a) + (n_arr)); \
 	} while (0)
 #elif defined(DUK_USE_HOBJECT_LAYOUT_2)
 /* LAYOUT 2 */
-#if defined(DUK_USE_ALIGN_4)
+#if (DUK_USE_ALIGN_BY == 4)
 #define DUK_HOBJECT_E_FLAG_PADDING(e_sz) ((4 - (e_sz)) & 0x03)
-#elif defined(DUK_USE_ALIGN_8)
+#elif (DUK_USE_ALIGN_BY == 8)
 #define DUK_HOBJECT_E_FLAG_PADDING(e_sz) ((8 - (e_sz)) & 0x07)
-#else
+#elif (DUK_USE_ALIGN_BY == 1)
 #define DUK_HOBJECT_E_FLAG_PADDING(e_sz) 0
+#else
+#error invalid DUK_USE_ALIGN_BY
 #endif
-#define DUK_HOBJECT_E_GET_KEY_BASE(h)           \
-	((duk_hstring **) ( \
-		(h)->p + \
-			(h)->e_size * sizeof(duk_propvalue) \
+#define DUK_HOBJECT_E_GET_KEY_BASE(heap,h) \
+	((duk_hstring **) (void *) ( \
+		DUK_HOBJECT_GET_PROPS((heap), (h)) + \
+			DUK_HOBJECT_GET_ESIZE((h)) * sizeof(duk_propvalue) \
 	))
-#define DUK_HOBJECT_E_GET_VALUE_BASE(h)         \
-	((duk_propvalue *) ( \
-		(h)->p \
+#define DUK_HOBJECT_E_GET_VALUE_BASE(heap,h) \
+	((duk_propvalue *) (void *) ( \
+		DUK_HOBJECT_GET_PROPS((heap), (h)) \
 	))
-#define DUK_HOBJECT_E_GET_FLAGS_BASE(h)         \
-	((duk_uint8_t *) ( \
-		(h)->p + (h)->e_size * (sizeof(duk_hstring *) + sizeof(duk_propvalue)) \
+#define DUK_HOBJECT_E_GET_FLAGS_BASE(heap,h) \
+	((duk_uint8_t *) (void *) ( \
+		DUK_HOBJECT_GET_PROPS((heap), (h)) + DUK_HOBJECT_GET_ESIZE((h)) * (sizeof(duk_hstring *) + sizeof(duk_propvalue)) \
 	))
-#define DUK_HOBJECT_A_GET_BASE(h)               \
-	((duk_tval *) ( \
-		(h)->p + \
-			(h)->e_size * (sizeof(duk_hstring *) + sizeof(duk_propvalue) + sizeof(duk_uint8_t)) + \
-			DUK_HOBJECT_E_FLAG_PADDING((h)->e_size) \
+#define DUK_HOBJECT_A_GET_BASE(heap,h) \
+	((duk_tval *) (void *) ( \
+		DUK_HOBJECT_GET_PROPS((heap), (h)) + \
+			DUK_HOBJECT_GET_ESIZE((h)) * (sizeof(duk_hstring *) + sizeof(duk_propvalue) + sizeof(duk_uint8_t)) + \
+			DUK_HOBJECT_E_FLAG_PADDING(DUK_HOBJECT_GET_ESIZE((h))) \
 	))
-#define DUK_HOBJECT_H_GET_BASE(h)               \
-	((duk_uint32_t *) ( \
-		(h)->p + \
-			(h)->e_size * (sizeof(duk_hstring *) + sizeof(duk_propvalue) + sizeof(duk_uint8_t)) + \
-			DUK_HOBJECT_E_FLAG_PADDING((h)->e_size) + \
-			(h)->a_size * sizeof(duk_tval) \
+#define DUK_HOBJECT_H_GET_BASE(heap,h) \
+	((duk_uint32_t *) (void *) ( \
+		DUK_HOBJECT_GET_PROPS((heap), (h)) + \
+			DUK_HOBJECT_GET_ESIZE((h)) * (sizeof(duk_hstring *) + sizeof(duk_propvalue) + sizeof(duk_uint8_t)) + \
+			DUK_HOBJECT_E_FLAG_PADDING(DUK_HOBJECT_GET_ESIZE((h))) + \
+			DUK_HOBJECT_GET_ASIZE((h)) * sizeof(duk_tval) \
 	))
 #define DUK_HOBJECT_P_COMPUTE_SIZE(n_ent,n_arr,n_hash) \
 	( \
@@ -5748,43 +8140,43 @@ duk_ucodepoint_t duk_hstring_char_code_at_raw(duk_hthread *thr, duk_hstring *h,
 		(n_hash) * sizeof(duk_uint32_t) \
 	)
 #define DUK_HOBJECT_P_SET_REALLOC_PTRS(p_base,set_e_k,set_e_pv,set_e_f,set_a,set_h,n_ent,n_arr,n_hash)  do { \
-		(set_e_pv) = (duk_propvalue *) (p_base); \
-		(set_e_k) = (duk_hstring **) ((set_e_pv) + (n_ent)); \
-		(set_e_f) = (duk_uint8_t *) ((set_e_k) + (n_ent)); \
-		(set_a) = (duk_tval *) (((duk_uint8_t *) (set_e_f)) + \
-		                        sizeof(duk_uint8_t) * (n_ent) + \
-		                        DUK_HOBJECT_E_FLAG_PADDING((n_ent))); \
-		(set_h) = (duk_uint32_t *) ((set_a) + (n_arr)); \
+		(set_e_pv) = (duk_propvalue *) (void *) (p_base); \
+		(set_e_k) = (duk_hstring **) (void *) ((set_e_pv) + (n_ent)); \
+		(set_e_f) = (duk_uint8_t *) (void *) ((set_e_k) + (n_ent)); \
+		(set_a) = (duk_tval *) (void *) (((duk_uint8_t *) (set_e_f)) + \
+		                                 sizeof(duk_uint8_t) * (n_ent) + \
+		                                 DUK_HOBJECT_E_FLAG_PADDING((n_ent))); \
+		(set_h) = (duk_uint32_t *) (void *) ((set_a) + (n_arr)); \
 	} while (0)
 #elif defined(DUK_USE_HOBJECT_LAYOUT_3)
 /* LAYOUT 3 */
-#define DUK_HOBJECT_E_GET_KEY_BASE(h)           \
-	((duk_hstring **) ( \
-		(h)->p + \
-			(h)->e_size * sizeof(duk_propvalue) + \
-			(h)->a_size * sizeof(duk_tval) \
+#define DUK_HOBJECT_E_GET_KEY_BASE(heap,h) \
+	((duk_hstring **) (void *) ( \
+		DUK_HOBJECT_GET_PROPS((heap), (h)) + \
+			DUK_HOBJECT_GET_ESIZE((h)) * sizeof(duk_propvalue) + \
+			DUK_HOBJECT_GET_ASIZE((h)) * sizeof(duk_tval) \
 	))
-#define DUK_HOBJECT_E_GET_VALUE_BASE(h)         \
-	((duk_propvalue *) ( \
-		(h)->p \
+#define DUK_HOBJECT_E_GET_VALUE_BASE(heap,h) \
+	((duk_propvalue *) (void *) ( \
+		DUK_HOBJECT_GET_PROPS((heap), (h)) \
 	))
-#define DUK_HOBJECT_E_GET_FLAGS_BASE(h)         \
-	((duk_uint8_t *) ( \
-		(h)->p + \
-			(h)->e_size * (sizeof(duk_propvalue) + sizeof(duk_hstring *)) + \
-			(h)->a_size * sizeof(duk_tval) + \
-			(h)->h_size * sizeof(duk_uint32_t) \
+#define DUK_HOBJECT_E_GET_FLAGS_BASE(heap,h) \
+	((duk_uint8_t *) (void *) ( \
+		DUK_HOBJECT_GET_PROPS((heap), (h)) + \
+			DUK_HOBJECT_GET_ESIZE((h)) * (sizeof(duk_propvalue) + sizeof(duk_hstring *)) + \
+			DUK_HOBJECT_GET_ASIZE((h)) * sizeof(duk_tval) + \
+			DUK_HOBJECT_GET_HSIZE((h)) * sizeof(duk_uint32_t) \
 	))
-#define DUK_HOBJECT_A_GET_BASE(h)               \
-	((duk_tval *) ( \
-		(h)->p + \
-			(h)->e_size * sizeof(duk_propvalue) \
+#define DUK_HOBJECT_A_GET_BASE(heap,h) \
+	((duk_tval *) (void *) ( \
+		DUK_HOBJECT_GET_PROPS((heap), (h)) + \
+			DUK_HOBJECT_GET_ESIZE((h)) * sizeof(duk_propvalue) \
 	))
-#define DUK_HOBJECT_H_GET_BASE(h)               \
-	((duk_uint32_t *) ( \
-		(h)->p + \
-			(h)->e_size * (sizeof(duk_propvalue) + sizeof(duk_hstring *)) + \
-			(h)->a_size * sizeof(duk_tval) \
+#define DUK_HOBJECT_H_GET_BASE(heap,h) \
+	((duk_uint32_t *) (void *) ( \
+		DUK_HOBJECT_GET_PROPS((heap), (h)) + \
+			DUK_HOBJECT_GET_ESIZE((h)) * (sizeof(duk_propvalue) + sizeof(duk_hstring *)) + \
+			DUK_HOBJECT_GET_ASIZE((h)) * sizeof(duk_tval) \
 	))
 #define DUK_HOBJECT_P_COMPUTE_SIZE(n_ent,n_arr,n_hash) \
 	( \
@@ -5793,83 +8185,85 @@ duk_ucodepoint_t duk_hstring_char_code_at_raw(duk_hthread *thr, duk_hstring *h,
 		(n_hash) * sizeof(duk_uint32_t) \
 	)
 #define DUK_HOBJECT_P_SET_REALLOC_PTRS(p_base,set_e_k,set_e_pv,set_e_f,set_a,set_h,n_ent,n_arr,n_hash)  do { \
-		(set_e_pv) = (duk_propvalue *) (p_base); \
-		(set_a) = (duk_tval *) ((set_e_pv) + (n_ent)); \
-		(set_e_k) = (duk_hstring **) ((set_a) + (n_arr)); \
-		(set_h) = (duk_uint32_t *) ((set_e_k) + (n_ent)); \
-		(set_e_f) = (duk_uint8_t *) ((set_h) + (n_hash)); \
+		(set_e_pv) = (duk_propvalue *) (void *) (p_base); \
+		(set_a) = (duk_tval *) (void *) ((set_e_pv) + (n_ent)); \
+		(set_e_k) = (duk_hstring **) (void *) ((set_a) + (n_arr)); \
+		(set_h) = (duk_uint32_t *) (void *) ((set_e_k) + (n_ent)); \
+		(set_e_f) = (duk_uint8_t *) (void *) ((set_h) + (n_hash)); \
 	} while (0)
 #else
 #error invalid hobject layout defines
 #endif  /* hobject property layout */
 
-#define DUK_HOBJECT_E_ALLOC_SIZE(h) DUK_HOBJECT_P_COMPUTE_SIZE((h)->e_size, (h)->a_size, (h)->h_size)
-
-#define DUK_HOBJECT_E_GET_KEY(h,i)              (DUK_HOBJECT_E_GET_KEY_BASE((h))[(i)])
-#define DUK_HOBJECT_E_GET_KEY_PTR(h,i)          (&DUK_HOBJECT_E_GET_KEY_BASE((h))[(i)])
-#define DUK_HOBJECT_E_GET_VALUE(h,i)            (DUK_HOBJECT_E_GET_VALUE_BASE((h))[(i)])
-#define DUK_HOBJECT_E_GET_VALUE_PTR(h,i)        (&DUK_HOBJECT_E_GET_VALUE_BASE((h))[(i)])
-#define DUK_HOBJECT_E_GET_VALUE_TVAL(h,i)       (DUK_HOBJECT_E_GET_VALUE((h),(i)).v)
-#define DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(h,i)   (&DUK_HOBJECT_E_GET_VALUE((h),(i)).v)
-#define DUK_HOBJECT_E_GET_VALUE_GETTER(h,i)     (DUK_HOBJECT_E_GET_VALUE((h),(i)).a.get)
-#define DUK_HOBJECT_E_GET_VALUE_GETTER_PTR(h,i) (&DUK_HOBJECT_E_GET_VALUE((h),(i)).a.get)
-#define DUK_HOBJECT_E_GET_VALUE_SETTER(h,i)     (DUK_HOBJECT_E_GET_VALUE((h),(i)).a.set)
-#define DUK_HOBJECT_E_GET_VALUE_SETTER_PTR(h,i) (&DUK_HOBJECT_E_GET_VALUE((h),(i)).a.set)
-#define DUK_HOBJECT_E_GET_FLAGS(h,i)            (DUK_HOBJECT_E_GET_FLAGS_BASE((h))[(i)])
-#define DUK_HOBJECT_E_GET_FLAGS_PTR(h,i)        (&DUK_HOBJECT_E_GET_FLAGS_BASE((h))[(i)])
-#define DUK_HOBJECT_A_GET_VALUE(h,i)            (DUK_HOBJECT_A_GET_BASE((h))[(i)])
-#define DUK_HOBJECT_A_GET_VALUE_PTR(h,i)        (&DUK_HOBJECT_A_GET_BASE((h))[(i)])
-#define DUK_HOBJECT_H_GET_INDEX(h,i)            (DUK_HOBJECT_H_GET_BASE((h))[(i)])
-#define DUK_HOBJECT_H_GET_INDEX_PTR(h,i)        (&DUK_HOBJECT_H_GET_BASE((h))[(i)])
-
-#define DUK_HOBJECT_E_SET_KEY(h,i,k)  do { \
-		DUK_HOBJECT_E_GET_KEY((h),(i)) = (k); \
+#define DUK_HOBJECT_E_ALLOC_SIZE(h) \
+	DUK_HOBJECT_P_COMPUTE_SIZE(DUK_HOBJECT_GET_ESIZE((h)), DUK_HOBJECT_GET_ASIZE((h)), DUK_HOBJECT_GET_HSIZE((h)))
+
+#define DUK_HOBJECT_E_GET_KEY(heap,h,i)              (DUK_HOBJECT_E_GET_KEY_BASE((heap), (h))[(i)])
+#define DUK_HOBJECT_E_GET_KEY_PTR(heap,h,i)          (&DUK_HOBJECT_E_GET_KEY_BASE((heap), (h))[(i)])
+#define DUK_HOBJECT_E_GET_VALUE(heap,h,i)            (DUK_HOBJECT_E_GET_VALUE_BASE((heap), (h))[(i)])
+#define DUK_HOBJECT_E_GET_VALUE_PTR(heap,h,i)        (&DUK_HOBJECT_E_GET_VALUE_BASE((heap), (h))[(i)])
+#define DUK_HOBJECT_E_GET_VALUE_TVAL(heap,h,i)       (DUK_HOBJECT_E_GET_VALUE((heap), (h), (i)).v)
+#define DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(heap,h,i)   (&DUK_HOBJECT_E_GET_VALUE((heap), (h), (i)).v)
+#define DUK_HOBJECT_E_GET_VALUE_GETTER(heap,h,i)     (DUK_HOBJECT_E_GET_VALUE((heap), (h), (i)).a.get)
+#define DUK_HOBJECT_E_GET_VALUE_GETTER_PTR(heap,h,i) (&DUK_HOBJECT_E_GET_VALUE((heap), (h), (i)).a.get)
+#define DUK_HOBJECT_E_GET_VALUE_SETTER(heap,h,i)     (DUK_HOBJECT_E_GET_VALUE((heap), (h), (i)).a.set)
+#define DUK_HOBJECT_E_GET_VALUE_SETTER_PTR(heap,h,i) (&DUK_HOBJECT_E_GET_VALUE((heap), (h), (i)).a.set)
+#define DUK_HOBJECT_E_GET_FLAGS(heap,h,i)            (DUK_HOBJECT_E_GET_FLAGS_BASE((heap), (h))[(i)])
+#define DUK_HOBJECT_E_GET_FLAGS_PTR(heap,h,i)        (&DUK_HOBJECT_E_GET_FLAGS_BASE((heap), (h))[(i)])
+#define DUK_HOBJECT_A_GET_VALUE(heap,h,i)            (DUK_HOBJECT_A_GET_BASE((heap), (h))[(i)])
+#define DUK_HOBJECT_A_GET_VALUE_PTR(heap,h,i)        (&DUK_HOBJECT_A_GET_BASE((heap), (h))[(i)])
+#define DUK_HOBJECT_H_GET_INDEX(heap,h,i)            (DUK_HOBJECT_H_GET_BASE((heap), (h))[(i)])
+#define DUK_HOBJECT_H_GET_INDEX_PTR(heap,h,i)        (&DUK_HOBJECT_H_GET_BASE((heap), (h))[(i)])
+
+#define DUK_HOBJECT_E_SET_KEY(heap,h,i,k)  do { \
+		DUK_HOBJECT_E_GET_KEY((heap), (h), (i)) = (k); \
 	} while (0)
-#define DUK_HOBJECT_E_SET_VALUE(h,i,v)  do { \
-		DUK_HOBJECT_E_GET_VALUE((h),(i)) = (v); \
+#define DUK_HOBJECT_E_SET_VALUE(heap,h,i,v)  do { \
+		DUK_HOBJECT_E_GET_VALUE((heap), (h), (i)) = (v); \
 	} while (0)
-#define DUK_HOBJECT_E_SET_VALUE_TVAL(h,i,v)  do { \
-		DUK_HOBJECT_E_GET_VALUE((h),(i)).v = (v); \
+#define DUK_HOBJECT_E_SET_VALUE_TVAL(heap,h,i,v)  do { \
+		DUK_HOBJECT_E_GET_VALUE((heap), (h), (i)).v = (v); \
 	} while (0)
-#define DUK_HOBJECT_E_SET_VALUE_GETTER(h,i,v)  do { \
-		DUK_HOBJECT_E_GET_VALUE((h),(i)).a.get = (v); \
+#define DUK_HOBJECT_E_SET_VALUE_GETTER(heap,h,i,v)  do { \
+		DUK_HOBJECT_E_GET_VALUE((heap), (h), (i)).a.get = (v); \
 	} while (0)
-#define DUK_HOBJECT_E_SET_VALUE_SETTER(h,i,v)  do { \
-		DUK_HOBJECT_E_GET_VALUE((h),(i)).a.set = (v); \
+#define DUK_HOBJECT_E_SET_VALUE_SETTER(heap,h,i,v)  do { \
+		DUK_HOBJECT_E_GET_VALUE((heap), (h), (i)).a.set = (v); \
 	} while (0)
-#define DUK_HOBJECT_E_SET_FLAGS(h,i,f)  do { \
-		DUK_HOBJECT_E_GET_FLAGS((h),(i)) = (f); \
+#define DUK_HOBJECT_E_SET_FLAGS(heap,h,i,f)  do { \
+		DUK_HOBJECT_E_GET_FLAGS((heap), (h), (i)) = (duk_uint8_t) (f); \
 	} while (0)
-#define DUK_HOBJECT_A_SET_VALUE(h,i,v)  do { \
-		DUK_HOBJECT_A_GET_VALUE((h),(i)) = (v); \
+#define DUK_HOBJECT_A_SET_VALUE(heap,h,i,v)  do { \
+		DUK_HOBJECT_A_GET_VALUE((heap), (h), (i)) = (v); \
 	} while (0)
-#define DUK_HOBJECT_A_SET_VALUE_TVAL(h,i,v)  DUK_HOBJECT_A_SET_VALUE((h),(i),(v))  /* alias for above */
-#define DUK_HOBJECT_H_SET_INDEX(h,i,v)  do { \
-		DUK_HOBJECT_H_GET_INDEX((h),(i)) = (v); \
+#define DUK_HOBJECT_A_SET_VALUE_TVAL(heap,h,i,v) \
+	DUK_HOBJECT_A_SET_VALUE((heap), (h), (i), (v))  /* alias for above */
+#define DUK_HOBJECT_H_SET_INDEX(heap,h,i,v)  do { \
+		DUK_HOBJECT_H_GET_INDEX((heap), (h), (i)) = (v); \
 	} while (0)
 
-#define DUK_HOBJECT_E_SET_FLAG_BITS(h,i,mask)  do { \
-		DUK_HOBJECT_E_GET_FLAGS_BASE((h))[(i)] |= (mask); \
+#define DUK_HOBJECT_E_SET_FLAG_BITS(heap,h,i,mask)  do { \
+		DUK_HOBJECT_E_GET_FLAGS_BASE((heap), (h))[(i)] |= (mask); \
 	} while (0)
 
-#define DUK_HOBJECT_E_CLEAR_FLAG_BITS(h,i,mask)  do { \
-		DUK_HOBJECT_E_GET_FLAGS_BASE((h))[(i)] &= ~(mask); \
+#define DUK_HOBJECT_E_CLEAR_FLAG_BITS(heap,h,i,mask)  do { \
+		DUK_HOBJECT_E_GET_FLAGS_BASE((heap), (h))[(i)] &= ~(mask); \
 	} while (0)
 
-#define DUK_HOBJECT_E_SLOT_IS_WRITABLE(h,i)     ((DUK_HOBJECT_E_GET_FLAGS((h),(i)) & DUK_PROPDESC_FLAG_WRITABLE) != 0)
-#define DUK_HOBJECT_E_SLOT_IS_ENUMERABLE(h,i)   ((DUK_HOBJECT_E_GET_FLAGS((h),(i)) & DUK_PROPDESC_FLAG_ENUMERABLE) != 0)
-#define DUK_HOBJECT_E_SLOT_IS_CONFIGURABLE(h,i) ((DUK_HOBJECT_E_GET_FLAGS((h),(i)) & DUK_PROPDESC_FLAG_CONFIGURABLE) != 0)
-#define DUK_HOBJECT_E_SLOT_IS_ACCESSOR(h,i)     ((DUK_HOBJECT_E_GET_FLAGS((h),(i)) & DUK_PROPDESC_FLAG_ACCESSOR) != 0)
+#define DUK_HOBJECT_E_SLOT_IS_WRITABLE(heap,h,i)     ((DUK_HOBJECT_E_GET_FLAGS((heap), (h), (i)) & DUK_PROPDESC_FLAG_WRITABLE) != 0)
+#define DUK_HOBJECT_E_SLOT_IS_ENUMERABLE(heap,h,i)   ((DUK_HOBJECT_E_GET_FLAGS((heap), (h), (i)) & DUK_PROPDESC_FLAG_ENUMERABLE) != 0)
+#define DUK_HOBJECT_E_SLOT_IS_CONFIGURABLE(heap,h,i) ((DUK_HOBJECT_E_GET_FLAGS((heap), (h), (i)) & DUK_PROPDESC_FLAG_CONFIGURABLE) != 0)
+#define DUK_HOBJECT_E_SLOT_IS_ACCESSOR(heap,h,i)     ((DUK_HOBJECT_E_GET_FLAGS((heap), (h), (i)) & DUK_PROPDESC_FLAG_ACCESSOR) != 0)
 
-#define DUK_HOBJECT_E_SLOT_SET_WRITABLE(h,i)        DUK_HOBJECT_E_SET_FLAG_BITS((h),(i),DUK_PROPDESC_FLAG_WRITABLE)
-#define DUK_HOBJECT_E_SLOT_SET_ENUMERABLE(h,i)      DUK_HOBJECT_E_SET_FLAG_BITS((h),(i),DUK_PROPDESC_FLAG_ENUMERABLE)
-#define DUK_HOBJECT_E_SLOT_SET_CONFIGURABLE(h,i)    DUK_HOBJECT_E_SET_FLAG_BITS((h),(i),DUK_PROPDESC_FLAG_CONFIGURABLE)
-#define DUK_HOBJECT_E_SLOT_SET_ACCESSOR(h,i)        DUK_HOBJECT_E_SET_FLAG_BITS((h),(i),DUK_PROPDESC_FLAG_ACCESSOR)
+#define DUK_HOBJECT_E_SLOT_SET_WRITABLE(heap,h,i)        DUK_HOBJECT_E_SET_FLAG_BITS((heap), (h), (i),DUK_PROPDESC_FLAG_WRITABLE)
+#define DUK_HOBJECT_E_SLOT_SET_ENUMERABLE(heap,h,i)      DUK_HOBJECT_E_SET_FLAG_BITS((heap), (h), (i),DUK_PROPDESC_FLAG_ENUMERABLE)
+#define DUK_HOBJECT_E_SLOT_SET_CONFIGURABLE(heap,h,i)    DUK_HOBJECT_E_SET_FLAG_BITS((heap), (h), (i),DUK_PROPDESC_FLAG_CONFIGURABLE)
+#define DUK_HOBJECT_E_SLOT_SET_ACCESSOR(heap,h,i)        DUK_HOBJECT_E_SET_FLAG_BITS((heap), (h), (i),DUK_PROPDESC_FLAG_ACCESSOR)
 
-#define DUK_HOBJECT_E_SLOT_CLEAR_WRITABLE(h,i)      DUK_HOBJECT_E_CLEAR_FLAG_BITS((h),(i),DUK_PROPDESC_FLAG_WRITABLE)
-#define DUK_HOBJECT_E_SLOT_CLEAR_ENUMERABLE(h,i)    DUK_HOBJECT_E_CLEAR_FLAG_BITS((h),(i),DUK_PROPDESC_FLAG_ENUMERABLE)
-#define DUK_HOBJECT_E_SLOT_CLEAR_CONFIGURABLE(h,i)  DUK_HOBJECT_E_CLEAR_FLAG_BITS((h),(i),DUK_PROPDESC_FLAG_CONFIGURABLE)
-#define DUK_HOBJECT_E_SLOT_CLEAR_ACCESSOR(h,i)      DUK_HOBJECT_E_CLEAR_FLAG_BITS((h),(i),DUK_PROPDESC_FLAG_ACCESSOR)
+#define DUK_HOBJECT_E_SLOT_CLEAR_WRITABLE(heap,h,i)      DUK_HOBJECT_E_CLEAR_FLAG_BITS((heap), (h), (i),DUK_PROPDESC_FLAG_WRITABLE)
+#define DUK_HOBJECT_E_SLOT_CLEAR_ENUMERABLE(heap,h,i)    DUK_HOBJECT_E_CLEAR_FLAG_BITS((heap), (h), (i),DUK_PROPDESC_FLAG_ENUMERABLE)
+#define DUK_HOBJECT_E_SLOT_CLEAR_CONFIGURABLE(heap,h,i)  DUK_HOBJECT_E_CLEAR_FLAG_BITS((heap), (h), (i),DUK_PROPDESC_FLAG_CONFIGURABLE)
+#define DUK_HOBJECT_E_SLOT_CLEAR_ACCESSOR(heap,h,i)      DUK_HOBJECT_E_CLEAR_FLAG_BITS((heap), (h), (i),DUK_PROPDESC_FLAG_ACCESSOR)
 
 #define DUK_PROPDESC_IS_WRITABLE(p)             (((p)->flags & DUK_PROPDESC_FLAG_WRITABLE) != 0)
 #define DUK_PROPDESC_IS_ENUMERABLE(p)           (((p)->flags & DUK_PROPDESC_FLAG_ENUMERABLE) != 0)
@@ -5880,6 +8274,42 @@ duk_ucodepoint_t duk_hstring_char_code_at_raw(duk_hthread *thr, duk_hstring *h,
 #define DUK_HOBJECT_HASHIDX_DELETED             0xfffffffeUL
 
 /*
+ *  Macros for accessing size fields
+ */
+
+#if defined(DUK_USE_OBJSIZES16)
+#define DUK_HOBJECT_GET_ESIZE(h) ((h)->e_size16)
+#define DUK_HOBJECT_SET_ESIZE(h,v) do { (h)->e_size16 = (v); } while (0)
+#define DUK_HOBJECT_GET_ENEXT(h) ((h)->e_next16)
+#define DUK_HOBJECT_SET_ENEXT(h,v) do { (h)->e_next16 = (v); } while (0)
+#define DUK_HOBJECT_POSTINC_ENEXT(h) ((h)->e_next16++)
+#define DUK_HOBJECT_GET_ASIZE(h) ((h)->a_size16)
+#define DUK_HOBJECT_SET_ASIZE(h,v) do { (h)->a_size16 = (v); } while (0)
+#if defined(DUK_USE_HOBJECT_HASH_PART)
+#define DUK_HOBJECT_GET_HSIZE(h) ((h)->h_size16)
+#define DUK_HOBJECT_SET_HSIZE(h,v) do { (h)->h_size16 = (v); } while (0)
+#else
+#define DUK_HOBJECT_GET_HSIZE(h) 0
+#define DUK_HOBJECT_SET_HSIZE(h,v) do { DUK_ASSERT((v) == 0); } while (0)
+#endif
+#else
+#define DUK_HOBJECT_GET_ESIZE(h) ((h)->e_size)
+#define DUK_HOBJECT_SET_ESIZE(h,v) do { (h)->e_size = (v); } while (0)
+#define DUK_HOBJECT_GET_ENEXT(h) ((h)->e_next)
+#define DUK_HOBJECT_SET_ENEXT(h,v) do { (h)->e_next = (v); } while (0)
+#define DUK_HOBJECT_POSTINC_ENEXT(h) ((h)->e_next++)
+#define DUK_HOBJECT_GET_ASIZE(h) ((h)->a_size)
+#define DUK_HOBJECT_SET_ASIZE(h,v) do { (h)->a_size = (v); } while (0)
+#if defined(DUK_USE_HOBJECT_HASH_PART)
+#define DUK_HOBJECT_GET_HSIZE(h) ((h)->h_size)
+#define DUK_HOBJECT_SET_HSIZE(h,v) do { (h)->h_size = (v); } while (0)
+#else
+#define DUK_HOBJECT_GET_HSIZE(h) 0
+#define DUK_HOBJECT_SET_HSIZE(h,v) do { DUK_ASSERT((v) == 0); } while (0)
+#endif
+#endif
+
+/*
  *  Misc
  */
 
@@ -5906,21 +8336,24 @@ duk_ucodepoint_t duk_hstring_char_code_at_raw(duk_hthread *thr, duk_hstring *h,
 
 /*
  *  Macros for property handling
- */		
-
-/* note: this updates refcounts */
-#define DUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr,h,p)       duk_hobject_set_prototype((thr),(h),(p))
-
-/*
- *  Macros for Ecmascript built-in semantics
  */
 
-#define DUK_HOBJECT_OBJECT_SEAL(thr,obj)                duk_hobject_object_seal_freeze_helper((thr),(obj),0)
-#define DUK_HOBJECT_OBJECT_FREEZE(htr,obj)              duk_hobject_object_seal_freeze_helper((thr),(obj),1)
-#define DUK_HOBJECT_OBJECT_IS_SEALED(obj)               duk_hobject_object_is_sealed_frozen_helper((obj),0)
-#define DUK_HOBJECT_OBJECT_IS_FROZEN(obj)               duk_hobject_object_is_sealed_frozen_helper((obj),1)
-#define DUK_HOBJECT_OBJECT_PREVENT_EXTENSIONS(vm,obj)   DUK_HOBJECT_CLEAR_EXTENSIBLE((obj))
-#define DUK_HOBJECT_OBJECT_IS_EXTENSIBLE(vm,obj)        DUK_HOBJECT_HAS_EXTENSIBLE((obj))
+#if defined(DUK_USE_HEAPPTR16)
+#define DUK_HOBJECT_GET_PROTOTYPE(heap,h) \
+	((duk_hobject *) DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, (h)->prototype16))
+#define DUK_HOBJECT_SET_PROTOTYPE(heap,h,x) do { \
+		(h)->prototype16 = DUK_USE_HEAPPTR_ENC16((heap)->heap_udata, (void *) (x)); \
+	} while (0)
+#else
+#define DUK_HOBJECT_GET_PROTOTYPE(heap,h) \
+	((h)->prototype)
+#define DUK_HOBJECT_SET_PROTOTYPE(heap,h,x) do { \
+		(h)->prototype = (x); \
+	} while (0)
+#endif
+
+/* note: this updates refcounts */
+#define DUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr,h,p)       duk_hobject_set_prototype_updref((thr), (h), (p))
 
 /*
  *  Resizing and hash behavior
@@ -5932,7 +8365,11 @@ duk_ucodepoint_t duk_hstring_char_code_at_raw(duk_hthread *thr, duk_hstring *h,
  * Also, we use negative array/entry table indices to indicate 'not found',
  * so anything above 0x80000000 will cause trouble now.
  */
+#if defined(DUK_USE_OBJSIZES16)
+#define DUK_HOBJECT_MAX_PROPERTIES       0x0000ffffUL
+#else
 #define DUK_HOBJECT_MAX_PROPERTIES       0x7fffffffUL   /* 2**31-1 ~= 2G properties */
+#endif
 
 /* higher value conserves memory; also note that linear scan is cache friendly */
 #define DUK_HOBJECT_E_USE_HASH_LIMIT     32
@@ -5948,12 +8385,14 @@ duk_ucodepoint_t duk_hstring_char_code_at_raw(duk_hthread *thr, duk_hstring *h,
 #define DUK_HOBJECT_A_ABANDON_LIMIT      2  /* 25%, i.e. less than 25% used -> abandon */
 
 /* internal align target for props allocation, must be 2*n for some n */
-#if defined(DUK_USE_ALIGN_4)
+#if (DUK_USE_ALIGN_BY == 4)
 #define DUK_HOBJECT_ALIGN_TARGET         4
-#elif defined(DUK_USE_ALIGN_8)
+#elif (DUK_USE_ALIGN_BY == 8)
 #define DUK_HOBJECT_ALIGN_TARGET         8
-#else
+#elif (DUK_USE_ALIGN_BY == 1)
 #define DUK_HOBJECT_ALIGN_TARGET         1
+#else
+#error invalid DUK_USE_ALIGN_BY
 #endif
 
 /* controls for minimum entry part growth */
@@ -5987,6 +8426,10 @@ struct duk_propaccessor {
 };
 
 union duk_propvalue {
+	/* The get/set pointers could be 16-bit pointer compressed but it
+	 * would make no difference on 32-bit platforms because duk_tval is
+	 * 8 bytes or more anyway.
+	 */
 	duk_tval v;
 	duk_propaccessor a;
 };
@@ -5998,56 +8441,56 @@ struct duk_propdesc {
 	duk_hobject *set;
 
 	/* for updating (all are set to < 0 for virtual properties) */
-	duk_int_t e_idx;	/* prop index in 'entry part', < 0 if not there */
-	duk_int_t h_idx;	/* prop index in 'hash part', < 0 if not there */
-	duk_int_t a_idx;	/* prop index in 'array part', < 0 if not there */
+	duk_int_t e_idx;  /* prop index in 'entry part', < 0 if not there */
+	duk_int_t h_idx;  /* prop index in 'hash part', < 0 if not there */
+	duk_int_t a_idx;  /* prop index in 'array part', < 0 if not there */
 };
 
 struct duk_hobject {
 	duk_heaphdr hdr;
 
 	/*
-	 *  'p' contains {key,value,flags} entries, optional array entries, and an
-	 *  optional hash lookup table for non-array entries in a single 'sliced'
+	 *  'props' contains {key,value,flags} entries, optional array entries, and
+	 *  an optional hash lookup table for non-array entries in a single 'sliced'
 	 *  allocation.  There are several layout options, which differ slightly in
 	 *  generated code size/speed and alignment/padding; duk_features.h selects
 	 *  the layout used.
 	 *
 	 *  Layout 1 (DUK_USE_HOBJECT_LAYOUT_1):
 	 *
-	 *    e_size * sizeof(duk_hstring *)         bytes of   entry keys (e_used gc reachable)
-	 *    e_size * sizeof(duk_propvalue)         bytes of   entry values (e_used gc reachable)
-	 *    e_size * sizeof(duk_uint8_t)           bytes of   entry flags (e_used gc reachable)
+	 *    e_size * sizeof(duk_hstring *)         bytes of   entry keys (e_next gc reachable)
+	 *    e_size * sizeof(duk_propvalue)         bytes of   entry values (e_next gc reachable)
+	 *    e_size * sizeof(duk_uint8_t)           bytes of   entry flags (e_next gc reachable)
 	 *    a_size * sizeof(duk_tval)              bytes of   (opt) array values (plain only) (all gc reachable)
 	 *    h_size * sizeof(duk_uint32_t)          bytes of   (opt) hash indexes to entries (e_size),
 	 *                                                      0xffffffffUL = unused, 0xfffffffeUL = deleted
 	 *
 	 *  Layout 2 (DUK_USE_HOBJECT_LAYOUT_2):
 	 *
-	 *    e_size * sizeof(duk_propvalue)         bytes of   entry values (e_used gc reachable)
-	 *    e_size * sizeof(duk_hstring *)         bytes of   entry keys (e_used gc reachable)
-	 *    e_size * sizeof(duk_uint8_t) + pad     bytes of   entry flags (e_used gc reachable)
+	 *    e_size * sizeof(duk_propvalue)         bytes of   entry values (e_next gc reachable)
+	 *    e_size * sizeof(duk_hstring *)         bytes of   entry keys (e_next gc reachable)
+	 *    e_size * sizeof(duk_uint8_t) + pad     bytes of   entry flags (e_next gc reachable)
 	 *    a_size * sizeof(duk_tval)              bytes of   (opt) array values (plain only) (all gc reachable)
 	 *    h_size * sizeof(duk_uint32_t)          bytes of   (opt) hash indexes to entries (e_size),
 	 *                                                      0xffffffffUL = unused, 0xfffffffeUL = deleted
 	 *
 	 *  Layout 3 (DUK_USE_HOBJECT_LAYOUT_3):
 	 *
-	 *    e_size * sizeof(duk_propvalue)         bytes of   entry values (e_used gc reachable)
+	 *    e_size * sizeof(duk_propvalue)         bytes of   entry values (e_next gc reachable)
 	 *    a_size * sizeof(duk_tval)              bytes of   (opt) array values (plain only) (all gc reachable)
-	 *    e_size * sizeof(duk_hstring *)         bytes of   entry keys (e_used gc reachable)
+	 *    e_size * sizeof(duk_hstring *)         bytes of   entry keys (e_next gc reachable)
 	 *    h_size * sizeof(duk_uint32_t)          bytes of   (opt) hash indexes to entries (e_size),
 	 *                                                      0xffffffffUL = unused, 0xfffffffeUL = deleted
-	 *    e_size * sizeof(duk_uint8_t)           bytes of   entry flags (e_used gc reachable)
+	 *    e_size * sizeof(duk_uint8_t)           bytes of   entry flags (e_next gc reachable)
 	 *
-	 *  In layout 1, the 'e_used' count is rounded to 4 or 8 on platforms
+	 *  In layout 1, the 'e_next' count is rounded to 4 or 8 on platforms
 	 *  requiring 4 or 8 byte alignment.  This ensures proper alignment
 	 *  for the entries, at the cost of memory footprint.  However, it's
 	 *  probably preferable to use another layout on such platforms instead.
 	 *
 	 *  In layout 2, the key and value parts are swapped to avoid padding
 	 *  the key array on platforms requiring alignment by 8.  The flags part
-	 *  is padded to get alignment for array entries.  The 'e_used' count does
+	 *  is padded to get alignment for array entries.  The 'e_next' count does
 	 *  not need to be rounded as in layout 1.
 	 *
 	 *  In layout 3, entry values and array values are always aligned properly,
@@ -6067,100 +8510,150 @@ struct duk_hobject {
 	 *  skimps on flags size (which would be followed by 3 bytes of padding in
 	 *  most architectures if entries were placed in a struct).
 	 *
-	 *  'p' also contains internal properties distinguished with a non-BMP
-	 *  prefix.  Often used properties should be placed early in 'p' whenever
+	 *  'props' also contains internal properties distinguished with a non-BMP
+	 *  prefix.  Often used properties should be placed early in 'props' whenever
 	 *  possible to make accessing them as fast a possible.
 	 */
 
-	duk_uint8_t *p;
-	duk_uint32_t e_size;
-	duk_uint32_t e_used;
-	duk_uint32_t a_size;
-	duk_uint32_t h_size;
+#if defined(DUK_USE_HEAPPTR16)
+	/* Located in duk_heaphdr h_extra16.  Subclasses of duk_hobject (like
+	 * duk_hcompiledfunction) are not free to use h_extra16 for this reason.
+	 */
+#else
+	duk_uint8_t *props;
+#endif
 
 	/* prototype: the only internal property lifted outside 'e' as it is so central */
+#if defined(DUK_USE_HEAPPTR16)
+	duk_uint16_t prototype16;
+#else
 	duk_hobject *prototype;
+#endif
+
+#if defined(DUK_USE_OBJSIZES16)
+	duk_uint16_t e_size16;
+	duk_uint16_t e_next16;
+	duk_uint16_t a_size16;
+#if defined(DUK_USE_HOBJECT_HASH_PART)
+	duk_uint16_t h_size16;
+#endif
+#else
+	duk_uint32_t e_size;  /* entry part size */
+	duk_uint32_t e_next;  /* index for next new key ([0,e_next[ are gc reachable) */
+	duk_uint32_t a_size;  /* array part size (entirely gc reachable) */
+#if defined(DUK_USE_HOBJECT_HASH_PART)
+	duk_uint32_t h_size;  /* hash part size or 0 if unused */
+#endif
+#endif
 };
 
 /*
  *  Exposed data
  */
 
-extern duk_uint8_t duk_class_number_to_stridx[32];
+#if !defined(DUK_SINGLE_FILE)
+DUK_INTERNAL_DECL duk_uint8_t duk_class_number_to_stridx[32];
+#endif  /* !DUK_SINGLE_FILE */
 
 /*
  *  Prototypes
  */
 
 /* alloc and init */
-duk_hobject *duk_hobject_alloc(duk_heap *heap, duk_uint_t hobject_flags);
-duk_hobject *duk_hobject_alloc_checked(duk_hthread *thr, duk_uint_t hobject_flags);
-duk_hcompiledfunction *duk_hcompiledfunction_alloc(duk_heap *heap, duk_uint_t hobject_flags);
-duk_hnativefunction *duk_hnativefunction_alloc(duk_heap *heap, duk_uint_t hobject_flags);
-duk_hthread *duk_hthread_alloc(duk_heap *heap, duk_uint_t hobject_flags);
+DUK_INTERNAL_DECL duk_hobject *duk_hobject_alloc(duk_heap *heap, duk_uint_t hobject_flags);
+#if 0  /* unused */
+DUK_INTERNAL_DECL duk_hobject *duk_hobject_alloc_checked(duk_hthread *thr, duk_uint_t hobject_flags);
+#endif
+DUK_INTERNAL_DECL duk_hcompiledfunction *duk_hcompiledfunction_alloc(duk_heap *heap, duk_uint_t hobject_flags);
+DUK_INTERNAL_DECL duk_hnativefunction *duk_hnativefunction_alloc(duk_heap *heap, duk_uint_t hobject_flags);
+DUK_INTERNAL duk_hbufferobject *duk_hbufferobject_alloc(duk_heap *heap, duk_uint_t hobject_flags);
+DUK_INTERNAL_DECL duk_hthread *duk_hthread_alloc(duk_heap *heap, duk_uint_t hobject_flags);
 
 /* low-level property functions */
-void duk_hobject_find_existing_entry(duk_hobject *obj, duk_hstring *key, duk_int_t *e_idx, duk_int_t *h_idx);
-duk_tval *duk_hobject_find_existing_entry_tval_ptr(duk_hobject *obj, duk_hstring *key);
-duk_tval *duk_hobject_find_existing_entry_tval_ptr_and_attrs(duk_hobject *obj, duk_hstring *key, duk_int_t *out_attrs);
-duk_tval *duk_hobject_find_existing_array_entry_tval_ptr(duk_hobject *obj, duk_uarridx_t i);
+DUK_INTERNAL_DECL void duk_hobject_find_existing_entry(duk_heap *heap, duk_hobject *obj, duk_hstring *key, duk_int_t *e_idx, duk_int_t *h_idx);
+DUK_INTERNAL_DECL duk_tval *duk_hobject_find_existing_entry_tval_ptr(duk_heap *heap, duk_hobject *obj, duk_hstring *key);
+DUK_INTERNAL_DECL duk_tval *duk_hobject_find_existing_entry_tval_ptr_and_attrs(duk_heap *heap, duk_hobject *obj, duk_hstring *key, duk_int_t *out_attrs);
+DUK_INTERNAL_DECL duk_tval *duk_hobject_find_existing_array_entry_tval_ptr(duk_heap *heap, duk_hobject *obj, duk_uarridx_t i);
+
+/* XXX: when optimizing for guaranteed property slots, use a guaranteed
+ * slot for internal value; this call can then access it directly.
+ */
+#define duk_hobject_get_internal_value_tval_ptr(heap,obj) \
+	duk_hobject_find_existing_entry_tval_ptr((heap), (obj), DUK_HEAP_STRING_INT_VALUE((heap)))
 
 /* core property functions */
-duk_bool_t duk_hobject_getprop(duk_hthread *thr, duk_tval *tv_obj, duk_tval *tv_key);
-duk_bool_t duk_hobject_putprop(duk_hthread *thr, duk_tval *tv_obj, duk_tval *tv_key, duk_tval *tv_val, duk_bool_t throw_flag);
-duk_bool_t duk_hobject_delprop(duk_hthread *thr, duk_tval *tv_obj, duk_tval *tv_key, duk_bool_t throw_flag);
-duk_bool_t duk_hobject_hasprop(duk_hthread *thr, duk_tval *tv_obj, duk_tval *tv_key);
+DUK_INTERNAL_DECL duk_bool_t duk_hobject_getprop(duk_hthread *thr, duk_tval *tv_obj, duk_tval *tv_key);
+DUK_INTERNAL_DECL duk_bool_t duk_hobject_putprop(duk_hthread *thr, duk_tval *tv_obj, duk_tval *tv_key, duk_tval *tv_val, duk_bool_t throw_flag);
+DUK_INTERNAL_DECL duk_bool_t duk_hobject_delprop(duk_hthread *thr, duk_tval *tv_obj, duk_tval *tv_key, duk_bool_t throw_flag);
+DUK_INTERNAL_DECL duk_bool_t duk_hobject_hasprop(duk_hthread *thr, duk_tval *tv_obj, duk_tval *tv_key);
 
 /* internal property functions */
-duk_bool_t duk_hobject_delprop_raw(duk_hthread *thr, duk_hobject *obj, duk_hstring *key, duk_bool_t throw_flag);
-duk_bool_t duk_hobject_hasprop_raw(duk_hthread *thr, duk_hobject *obj, duk_hstring *key);
-void duk_hobject_define_property_internal(duk_hthread *thr, duk_hobject *obj, duk_hstring *key, duk_small_uint_t flags);
-void duk_hobject_define_property_internal_arridx(duk_hthread *thr, duk_hobject *obj, duk_uarridx_t arr_idx, duk_small_uint_t flags);
-void duk_hobject_define_accessor_internal(duk_hthread *thr, duk_hobject *obj, duk_hstring *key, duk_hobject *getter, duk_hobject *setter, duk_small_uint_t propflags);
-void duk_hobject_set_length(duk_hthread *thr, duk_hobject *obj, duk_uint32_t length);  /* XXX: duk_uarridx_t? */
-void duk_hobject_set_length_zero(duk_hthread *thr, duk_hobject *obj);
-duk_uint32_t duk_hobject_get_length(duk_hthread *thr, duk_hobject *obj);  /* XXX: duk_uarridx_t? */
+#define DUK_DELPROP_FLAG_THROW  (1 << 0)
+#define DUK_DELPROP_FLAG_FORCE  (1 << 1)
+DUK_INTERNAL_DECL duk_bool_t duk_hobject_delprop_raw(duk_hthread *thr, duk_hobject *obj, duk_hstring *key, duk_small_uint_t flags);
+DUK_INTERNAL_DECL duk_bool_t duk_hobject_hasprop_raw(duk_hthread *thr, duk_hobject *obj, duk_hstring *key);
+DUK_INTERNAL_DECL void duk_hobject_define_property_internal(duk_hthread *thr, duk_hobject *obj, duk_hstring *key, duk_small_uint_t flags);
+DUK_INTERNAL_DECL void duk_hobject_define_property_internal_arridx(duk_hthread *thr, duk_hobject *obj, duk_uarridx_t arr_idx, duk_small_uint_t flags);
+DUK_INTERNAL_DECL void duk_hobject_define_accessor_internal(duk_hthread *thr, duk_hobject *obj, duk_hstring *key, duk_hobject *getter, duk_hobject *setter, duk_small_uint_t propflags);
+DUK_INTERNAL_DECL void duk_hobject_set_length(duk_hthread *thr, duk_hobject *obj, duk_uint32_t length);  /* XXX: duk_uarridx_t? */
+DUK_INTERNAL_DECL void duk_hobject_set_length_zero(duk_hthread *thr, duk_hobject *obj);
+DUK_INTERNAL_DECL duk_uint32_t duk_hobject_get_length(duk_hthread *thr, duk_hobject *obj);  /* XXX: duk_uarridx_t? */
+
+/* helpers for defineProperty() and defineProperties() */
+DUK_INTERNAL_DECL
+void duk_hobject_prepare_property_descriptor(duk_context *ctx,
+                                             duk_idx_t idx_in,
+                                             duk_uint_t *out_defprop_flags,
+                                             duk_idx_t *out_idx_value,
+                                             duk_hobject **out_getter,
+                                             duk_hobject **out_setter);
+DUK_INTERNAL_DECL
+void duk_hobject_define_property_helper(duk_context *ctx,
+                                        duk_uint_t defprop_flags,
+                                        duk_hobject *obj,
+                                        duk_hstring *key,
+                                        duk_idx_t idx_value,
+                                        duk_hobject *get,
+                                        duk_hobject *set);
 
 /* Object built-in methods */
-duk_ret_t duk_hobject_object_define_property(duk_context *ctx);
-duk_ret_t duk_hobject_object_define_properties(duk_context *ctx);
-duk_ret_t duk_hobject_object_get_own_property_descriptor(duk_context *ctx);
-void duk_hobject_object_seal_freeze_helper(duk_hthread *thr, duk_hobject *obj, duk_bool_t is_freeze);
-duk_bool_t duk_hobject_object_is_sealed_frozen_helper(duk_hobject *obj, duk_bool_t is_frozen);
-duk_bool_t duk_hobject_object_ownprop_helper(duk_context *ctx, duk_small_uint_t required_desc_flags);
+DUK_INTERNAL_DECL duk_ret_t duk_hobject_object_get_own_property_descriptor(duk_context *ctx);
+DUK_INTERNAL_DECL void duk_hobject_object_seal_freeze_helper(duk_hthread *thr, duk_hobject *obj, duk_bool_t is_freeze);
+DUK_INTERNAL_DECL duk_bool_t duk_hobject_object_is_sealed_frozen_helper(duk_hthread *thr, duk_hobject *obj, duk_bool_t is_frozen);
+DUK_INTERNAL_DECL duk_bool_t duk_hobject_object_ownprop_helper(duk_context *ctx, duk_small_uint_t required_desc_flags);
 
 /* internal properties */
-duk_bool_t duk_hobject_get_internal_value(duk_heap *heap, duk_hobject *obj, duk_tval *tv);
-duk_hstring *duk_hobject_get_internal_value_string(duk_heap *heap, duk_hobject *obj);
-duk_hbuffer *duk_hobject_get_internal_value_buffer(duk_heap *heap, duk_hobject *obj);
-	
+DUK_INTERNAL_DECL duk_bool_t duk_hobject_get_internal_value(duk_heap *heap, duk_hobject *obj, duk_tval *tv);
+DUK_INTERNAL_DECL duk_hstring *duk_hobject_get_internal_value_string(duk_heap *heap, duk_hobject *obj);
+
 /* hobject management functions */
-void duk_hobject_compact_props(duk_hthread *thr, duk_hobject *obj);
+DUK_INTERNAL_DECL void duk_hobject_compact_props(duk_hthread *thr, duk_hobject *obj);
 
 /* ES6 proxy */
 #if defined(DUK_USE_ES6_PROXY)
-duk_bool_t duk_hobject_proxy_check(duk_hthread *thr, duk_hobject *obj, duk_hobject **out_target, duk_hobject **out_handler);
+DUK_INTERNAL_DECL duk_bool_t duk_hobject_proxy_check(duk_hthread *thr, duk_hobject *obj, duk_hobject **out_target, duk_hobject **out_handler);
+DUK_INTERNAL_DECL duk_hobject *duk_hobject_resolve_proxy_target(duk_hthread *thr, duk_hobject *obj);
 #endif
 
 /* enumeration */
-void duk_hobject_enumerator_create(duk_context *ctx, duk_small_uint_t enum_flags);
-duk_ret_t duk_hobject_get_enumerated_keys(duk_context *ctx, duk_small_uint_t enum_flags);
-duk_bool_t duk_hobject_enumerator_next(duk_context *ctx, duk_bool_t get_value);
+DUK_INTERNAL_DECL void duk_hobject_enumerator_create(duk_context *ctx, duk_small_uint_t enum_flags);
+DUK_INTERNAL_DECL duk_ret_t duk_hobject_get_enumerated_keys(duk_context *ctx, duk_small_uint_t enum_flags);
+DUK_INTERNAL_DECL duk_bool_t duk_hobject_enumerator_next(duk_context *ctx, duk_bool_t get_value);
 
 /* macros */
-void duk_hobject_set_prototype(duk_hthread *thr, duk_hobject *h, duk_hobject *p);
+DUK_INTERNAL_DECL void duk_hobject_set_prototype_updref(duk_hthread *thr, duk_hobject *h, duk_hobject *p);
 
 /* finalization */
-void duk_hobject_run_finalizer(duk_hthread *thr, duk_hobject *obj);
+DUK_INTERNAL_DECL void duk_hobject_run_finalizer(duk_hthread *thr, duk_hobject *obj);
 
 /* pc2line */
 #if defined(DUK_USE_PC2LINE)
-void duk_hobject_pc2line_pack(duk_hthread *thr, duk_compiler_instr *instrs, duk_uint_fast32_t length);
-duk_uint_fast32_t duk_hobject_pc2line_query(duk_context *ctx, duk_idx_t idx_func, duk_uint_fast32_t pc);
+DUK_INTERNAL_DECL void duk_hobject_pc2line_pack(duk_hthread *thr, duk_compiler_instr *instrs, duk_uint_fast32_t length);
+DUK_INTERNAL_DECL duk_uint_fast32_t duk_hobject_pc2line_query(duk_context *ctx, duk_idx_t idx_func, duk_uint_fast32_t pc);
 #endif
 
-/* misc */	
-duk_bool_t duk_hobject_prototype_chain_contains(duk_hthread *thr, duk_hobject *h, duk_hobject *p);
+/* misc */
+DUK_INTERNAL_DECL duk_bool_t duk_hobject_prototype_chain_contains(duk_hthread *thr, duk_hobject *h, duk_hobject *p, duk_bool_t ignore_loop);
 
 #endif  /* DUK_HOBJECT_H_INCLUDED */
 #line 1 "duk_hcompiledfunction.h"
@@ -6175,67 +8668,108 @@ duk_bool_t duk_hobject_prototype_chain_contains(duk_hthread *thr, duk_hobject *h
 #define DUK_HCOMPILEDFUNCTION_H_INCLUDED
 
 /*
+ *  Field accessor macros
+ */
+
+/* XXX: casts could be improved, especially for GET/SET DATA */
+
+#if defined(DUK_USE_HEAPPTR16)
+#define DUK_HCOMPILEDFUNCTION_GET_DATA(heap,h) \
+	((duk_hbuffer_fixed *) (void *) DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, (h)->data16))
+#define DUK_HCOMPILEDFUNCTION_SET_DATA(heap,h,v) do { \
+		(h)->data16 = DUK_USE_HEAPPTR_ENC16((heap)->heap_udata, (void *) (v)); \
+	} while (0)
+#define DUK_HCOMPILEDFUNCTION_GET_FUNCS(heap,h)  \
+	((duk_hobject **) (void *) (DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, (h)->funcs16)))
+#define DUK_HCOMPILEDFUNCTION_SET_FUNCS(heap,h,v)  do { \
+		(h)->funcs16 = DUK_USE_HEAPPTR_ENC16((heap)->heap_udata, (void *) (v)); \
+	} while (0)
+#define DUK_HCOMPILEDFUNCTION_GET_BYTECODE(heap,h)  \
+	((duk_instr_t *) (void *) (DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, (h)->bytecode16)))
+#define DUK_HCOMPILEDFUNCTION_SET_BYTECODE(heap,h,v)  do { \
+		(h)->bytecode16 = DUK_USE_HEAPPTR_ENC16((heap)->heap_udata, (void *) (v)); \
+	} while (0)
+#else
+#define DUK_HCOMPILEDFUNCTION_GET_DATA(heap,h) \
+	((duk_hbuffer_fixed *) (void *) (h)->data)
+#define DUK_HCOMPILEDFUNCTION_SET_DATA(heap,h,v) do { \
+		(h)->data = (duk_hbuffer *) (v); \
+	} while (0)
+#define DUK_HCOMPILEDFUNCTION_GET_FUNCS(heap,h)  \
+	((h)->funcs)
+#define DUK_HCOMPILEDFUNCTION_SET_FUNCS(heap,h,v)  do { \
+		(h)->funcs = (v); \
+	} while (0)
+#define DUK_HCOMPILEDFUNCTION_GET_BYTECODE(heap,h)  \
+	((h)->bytecode)
+#define DUK_HCOMPILEDFUNCTION_SET_BYTECODE(heap,h,v)  do { \
+		(h)->bytecode = (v); \
+	} while (0)
+#endif
+
+/*
  *  Accessor macros for function specific data areas
  */
 
 /* Note: assumes 'data' is always a fixed buffer */
-#define DUK_HCOMPILEDFUNCTION_GET_BUFFER_BASE(h)  \
-	DUK_HBUFFER_FIXED_GET_DATA_PTR((duk_hbuffer_fixed *) (h)->data)
+#define DUK_HCOMPILEDFUNCTION_GET_BUFFER_BASE(heap,h)  \
+	DUK_HBUFFER_FIXED_GET_DATA_PTR((heap), DUK_HCOMPILEDFUNCTION_GET_DATA((heap), (h)))
 
-#define DUK_HCOMPILEDFUNCTION_GET_CONSTS_BASE(h)  \
-	((duk_tval *) DUK_HCOMPILEDFUNCTION_GET_BUFFER_BASE((h)))
+#define DUK_HCOMPILEDFUNCTION_GET_CONSTS_BASE(heap,h)  \
+	((duk_tval *) (void *) DUK_HCOMPILEDFUNCTION_GET_BUFFER_BASE((heap), (h)))
 
-#define DUK_HCOMPILEDFUNCTION_GET_FUNCS_BASE(h)  \
-	((h)->funcs)
+#define DUK_HCOMPILEDFUNCTION_GET_FUNCS_BASE(heap,h)  \
+	DUK_HCOMPILEDFUNCTION_GET_FUNCS((heap), (h))
 
-#define DUK_HCOMPILEDFUNCTION_GET_CODE_BASE(h)  \
-	((h)->bytecode)
+#define DUK_HCOMPILEDFUNCTION_GET_CODE_BASE(heap,h)  \
+	DUK_HCOMPILEDFUNCTION_GET_BYTECODE((heap), (h))
 
-#define DUK_HCOMPILEDFUNCTION_GET_CONSTS_END(h)  \
-	((duk_tval *) DUK_HCOMPILEDFUNCTION_GET_FUNCS_BASE((h)))
+#define DUK_HCOMPILEDFUNCTION_GET_CONSTS_END(heap,h)  \
+	((duk_tval *) (void *) DUK_HCOMPILEDFUNCTION_GET_FUNCS((heap), (h)))
 
-#define DUK_HCOMPILEDFUNCTION_GET_FUNCS_END(h)  \
-	((duk_hobject **) DUK_HCOMPILEDFUNCTION_GET_CODE_BASE((h)))
+#define DUK_HCOMPILEDFUNCTION_GET_FUNCS_END(heap,h)  \
+	((duk_hobject **) (void *) DUK_HCOMPILEDFUNCTION_GET_BYTECODE((heap), (h)))
 
-#define DUK_HCOMPILEDFUNCTION_GET_CODE_END(h)  \
-	((duk_instr_t *) (DUK_HBUFFER_FIXED_GET_DATA_PTR((duk_hbuffer_fixed *) (h)->data) + \
-	                DUK_HBUFFER_GET_SIZE((h)->data)))
+/* XXX: double evaluation of DUK_HCOMPILEDFUNCTION_GET_DATA() */
+#define DUK_HCOMPILEDFUNCTION_GET_CODE_END(heap,h)  \
+	((duk_instr_t *) (void *) (DUK_HBUFFER_FIXED_GET_DATA_PTR((heap), DUK_HCOMPILEDFUNCTION_GET_DATA((heap), (h))) + \
+	                DUK_HBUFFER_GET_SIZE((duk_hbuffer *) DUK_HCOMPILEDFUNCTION_GET_DATA((heap), h))))
 
-#define DUK_HCOMPILEDFUNCTION_GET_CONSTS_SIZE(h)  \
+#define DUK_HCOMPILEDFUNCTION_GET_CONSTS_SIZE(heap,h)  \
 	( \
 	 (duk_size_t) \
 	 ( \
-	   ((duk_uint8_t *) DUK_HCOMPILEDFUNCTION_GET_CONSTS_END((h))) - \
-	   ((duk_uint8_t *) DUK_HCOMPILEDFUNCTION_GET_CONSTS_BASE((h))) \
+	   ((const duk_uint8_t *) DUK_HCOMPILEDFUNCTION_GET_CONSTS_END((heap), (h))) - \
+	   ((const duk_uint8_t *) DUK_HCOMPILEDFUNCTION_GET_CONSTS_BASE((heap), (h))) \
 	 ) \
 	)
 
-#define DUK_HCOMPILEDFUNCTION_GET_FUNCS_SIZE(h)  \
+#define DUK_HCOMPILEDFUNCTION_GET_FUNCS_SIZE(heap,h)  \
 	( \
 	 (duk_size_t) \
 	 ( \
-	   ((duk_uint8_t *) DUK_HCOMPILEDFUNCTION_GET_FUNCS_END((h))) - \
-	   ((duk_uint8_t *) DUK_HCOMPILEDFUNCTION_GET_FUNCS_BASE((h))) \
+	   ((const duk_uint8_t *) DUK_HCOMPILEDFUNCTION_GET_FUNCS_END((heap), (h))) - \
+	   ((const duk_uint8_t *) DUK_HCOMPILEDFUNCTION_GET_FUNCS_BASE((heap), (h))) \
 	 ) \
 	)
 
-#define DUK_HCOMPILEDFUNCTION_GET_CODE_SIZE(h)  \
+#define DUK_HCOMPILEDFUNCTION_GET_CODE_SIZE(heap,h)  \
 	( \
 	 (duk_size_t) \
 	 ( \
-	   ((duk_uint8_t *) DUK_HCOMPILEDFUNCTION_GET_CODE_END((h))) - \
-	   ((duk_uint8_t *) DUK_HCOMPILEDFUNCTION_GET_CODE_BASE((h))) \
+	   ((const duk_uint8_t *) DUK_HCOMPILEDFUNCTION_GET_CODE_END((heap),(h))) - \
+	   ((const duk_uint8_t *) DUK_HCOMPILEDFUNCTION_GET_CODE_BASE((heap),(h))) \
 	 ) \
 	)
 
-#define DUK_HCOMPILEDFUNCTION_GET_CONSTS_COUNT(h)  \
-	((duk_size_t) (DUK_HCOMPILEDFUNCTION_GET_CONSTS_SIZE((h)) / sizeof(duk_tval)))
+#define DUK_HCOMPILEDFUNCTION_GET_CONSTS_COUNT(heap,h)  \
+	((duk_size_t) (DUK_HCOMPILEDFUNCTION_GET_CONSTS_SIZE((heap), (h)) / sizeof(duk_tval)))
 
-#define DUK_HCOMPILEDFUNCTION_GET_FUNCS_COUNT(h)  \
-	((duk_size_t) (DUK_HCOMPILEDFUNCTION_GET_FUNCS_SIZE((h)) / sizeof(duk_hobject *)))
+#define DUK_HCOMPILEDFUNCTION_GET_FUNCS_COUNT(heap,h)  \
+	((duk_size_t) (DUK_HCOMPILEDFUNCTION_GET_FUNCS_SIZE((heap), (h)) / sizeof(duk_hobject *)))
 
-#define DUK_HCOMPILEDFUNCTION_GET_CODE_COUNT(h)  \
-	((duk_size_t) (DUK_HCOMPILEDFUNCTION_GET_CODE_SIZE((h)) / sizeof(duk_instr_t)))
+#define DUK_HCOMPILEDFUNCTION_GET_CODE_COUNT(heap,h)  \
+	((duk_size_t) (DUK_HCOMPILEDFUNCTION_GET_CODE_SIZE((heap), (h)) / sizeof(duk_instr_t)))
 
 
 /*
@@ -6267,11 +8801,27 @@ struct duk_hcompiledfunction {
 	 *  to the 'data' element.
 	 */
 
-	duk_hbuffer *data;    /* data area, fixed allocation, stable data ptrs */
+	/* Data area, fixed allocation, stable data ptrs. */
+#if defined(DUK_USE_HEAPPTR16)
+	duk_uint16_t data16;
+#else
+	duk_hbuffer *data;
+#endif
 
-	/* no need for constants pointer */
+	/* No need for constants pointer (= same as data).
+	 *
+	 * When using 16-bit packing alignment to 4 is nice.  'funcs' will be
+	 * 4-byte aligned because 'constants' are duk_tvals.  For now the
+	 * inner function pointers are not compressed, so that 'bytecode' will
+	 * also be 4-byte aligned.
+	 */
+#if defined(DUK_USE_HEAPPTR16)
+	duk_uint16_t funcs16;
+	duk_uint16_t bytecode16;
+#else
 	duk_hobject **funcs;
 	duk_instr_t *bytecode;
+#endif
 
 	/*
 	 *  'nregs' registers are allocated on function entry, at most 'nargs'
@@ -6288,7 +8838,7 @@ struct duk_hcompiledfunction {
 	 *  must be the same for the duration of the function execution and
 	 *  the register cannot be used for anything else.
 	 *
-	 *  When looking up variables by name, the '_varmap' map is used.
+	 *  When looking up variables by name, the '_Varmap' map is used.
 	 *  When an activation closes, registers mapped to arguments are
 	 *  copied into the environment record based on the same map.  The
 	 *  reverse map (from register to variable) is not currently needed
@@ -6307,12 +8857,12 @@ struct duk_hcompiledfunction {
 	 *  Function templates:
 	 *
 	 *    {
-	 *      _varmap: { "arg1": 0, "arg2": 1, "varname": 2 },
-	 *      _formals: [ "arg1", "arg2" ],
-	 *      _name: "func",    // declaration, named function expressions
-	 *      _source: "function func(arg1, arg2) { ... }",
-	 *      _pc2line: <debug info for pc-to-line mapping>,
-	 *      _filename: <debug info for creating nice errors>
+	 *      name: "func",    // declaration, named function expressions
+	 *      fileName: <debug info for creating nice errors>
+	 *      _Varmap: { "arg1": 0, "arg2": 1, "varname": 2 },
+	 *      _Formals: [ "arg1", "arg2" ],
+	 *      _Source: "function func(arg1, arg2) { ... }",
+	 *      _Pc2line: <debug info for pc-to-line mapping>,
 	 *    }
 	 *
 	 *  Function instances:
@@ -6322,19 +8872,27 @@ struct duk_hcompiledfunction {
 	 *      prototype: { constructor: <func> },
 	 *      caller: <thrower>,
 	 *      arguments: <thrower>,
-	 *      _varmap: { "arg1": 0, "arg2": 1, "varname": 2 },
-	 *      _formals: [ "arg1", "arg2" ],
-	 *      _name: "func",    // declaration, named function expressions
-	 *      _source: "function func(arg1, arg2) { ... }",
-	 *      _pc2line: <debug info for pc-to-line mapping>,
-	 *      _filename: <debug info for creating nice errors>
-	 *      _varenv: <variable environment of closure>,
-	 *      _lexenv: <lexical environment of closure (if differs from _varenv)>
+	 *      name: "func",    // declaration, named function expressions
+	 *      fileName: <debug info for creating nice errors>
+	 *      _Varmap: { "arg1": 0, "arg2": 1, "varname": 2 },
+	 *      _Formals: [ "arg1", "arg2" ],
+	 *      _Source: "function func(arg1, arg2) { ... }",
+	 *      _Pc2line: <debug info for pc-to-line mapping>,
+	 *      _Varenv: <variable environment of closure>,
+	 *      _Lexenv: <lexical environment of closure (if differs from _Varenv)>
 	 *    }
 	 *
 	 *  More detailed description of these properties can be found
 	 *  in the documentation.
 	 */
+
+#if defined(DUK_USE_DEBUGGER_SUPPORT)
+	/* Line number range for function.  Needed during debugging to
+	 * determine active breakpoints.
+	 */
+	duk_uint32_t start_line;
+	duk_uint32_t end_line;
+#endif
 };
 
 #endif  /* DUK_HCOMPILEDFUNCTION_H_INCLUDED */
@@ -6371,6 +8929,140 @@ struct duk_hnativefunction {
 };
 
 #endif  /* DUK_HNATIVEFUNCTION_H_INCLUDED */
+#line 1 "duk_hbufferobject.h"
+/*
+ *  Heap Buffer object representation.  Used for all Buffer variants.
+ */
+
+#ifndef DUK_HBUFFEROBJECT_H_INCLUDED
+#define DUK_HBUFFEROBJECT_H_INCLUDED
+
+/* All element accessors are host endian now (driven by TypedArray spec). */
+#define DUK_HBUFFEROBJECT_ELEM_UINT8           0
+#define DUK_HBUFFEROBJECT_ELEM_UINT8CLAMPED    1
+#define DUK_HBUFFEROBJECT_ELEM_INT8            2
+#define DUK_HBUFFEROBJECT_ELEM_UINT16          3
+#define DUK_HBUFFEROBJECT_ELEM_INT16           4
+#define DUK_HBUFFEROBJECT_ELEM_UINT32          5
+#define DUK_HBUFFEROBJECT_ELEM_INT32           6
+#define DUK_HBUFFEROBJECT_ELEM_FLOAT32         7
+#define DUK_HBUFFEROBJECT_ELEM_FLOAT64         8
+#define DUK_HBUFFEROBJECT_ELEM_MAX             8
+
+#define DUK_ASSERT_HBUFFEROBJECT_VALID(h) do { \
+		DUK_ASSERT((h) != NULL); \
+		DUK_ASSERT((h)->shift <= 3); \
+		DUK_ASSERT((h)->elem_type <= DUK_HBUFFEROBJECT_ELEM_MAX); \
+		DUK_ASSERT(((h)->shift == 0 && (h)->elem_type == DUK_HBUFFEROBJECT_ELEM_UINT8) || \
+		           ((h)->shift == 0 && (h)->elem_type == DUK_HBUFFEROBJECT_ELEM_UINT8CLAMPED) || \
+		           ((h)->shift == 0 && (h)->elem_type == DUK_HBUFFEROBJECT_ELEM_INT8) || \
+		           ((h)->shift == 1 && (h)->elem_type == DUK_HBUFFEROBJECT_ELEM_UINT16) || \
+		           ((h)->shift == 1 && (h)->elem_type == DUK_HBUFFEROBJECT_ELEM_INT16) || \
+		           ((h)->shift == 2 && (h)->elem_type == DUK_HBUFFEROBJECT_ELEM_UINT32) || \
+		           ((h)->shift == 2 && (h)->elem_type == DUK_HBUFFEROBJECT_ELEM_INT32) || \
+		           ((h)->shift == 2 && (h)->elem_type == DUK_HBUFFEROBJECT_ELEM_FLOAT32) || \
+		           ((h)->shift == 3 && (h)->elem_type == DUK_HBUFFEROBJECT_ELEM_FLOAT64)); \
+		DUK_ASSERT((h)->is_view == 0 || (h)->is_view == 1); \
+		DUK_ASSERT(DUK_HOBJECT_IS_BUFFEROBJECT((duk_hobject *) (h))); \
+		if ((h)->buf == NULL) { \
+			DUK_ASSERT((h)->offset == 0); \
+			DUK_ASSERT((h)->length == 0); \
+		} else { \
+			/* No assertions for offset or length; in particular, \
+			 * it's OK for length to be longer than underlying \
+			 * buffer.  Just ensure they don't wrap when added. \
+			 */ \
+			DUK_ASSERT((h)->offset + (h)->length >= (h)->offset); \
+		} \
+	} while (0)
+
+/* Get the current data pointer (caller must ensure buf != NULL) as a
+ * duk_uint8_t ptr.
+ */
+#define DUK_HBUFFEROBJECT_GET_SLICE_BASE(heap,h) \
+	(DUK_ASSERT_EXPR((h) != NULL), DUK_ASSERT_EXPR((h)->buf != NULL), \
+	(((duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR((heap), (h)->buf)) + (h)->offset))
+
+/* True if slice is full, i.e. offset is zero and length covers the entire
+ * buffer.  This status may change independently of the duk_hbufferobject if
+ * the underlying buffer is dynamic and changes without the hbufferobject
+ * being changed.
+ */
+#define DUK_HBUFFEROBJECT_FULL_SLICE(h) \
+	(DUK_ASSERT_EXPR((h) != NULL), DUK_ASSERT_EXPR((h)->buf != NULL), \
+	((h)->offset == 0 && (h)->length == DUK_HBUFFER_GET_SIZE((h)->buf)))
+
+/* Validate that the whole slice [0,length[ is contained in the underlying
+ * buffer.  Caller must ensure 'buf' != NULL.
+ */
+#define DUK_HBUFFEROBJECT_VALID_SLICE(h) \
+	(DUK_ASSERT_EXPR((h) != NULL), DUK_ASSERT_EXPR((h)->buf != NULL), \
+	((h)->offset + (h)->length <= DUK_HBUFFER_GET_SIZE((h)->buf)))
+
+/* Validate byte read/write for virtual 'offset', i.e. check that the
+ * offset, taking into account h->offset, is within the underlying
+ * buffer size.  This is a safety check which is needed to ensure
+ * that even a misconfigured duk_hbufferobject never causes memory
+ * unsafe behavior (e.g. if an underlying dynamic buffer changes
+ * after being setup).  Caller must ensure 'buf' != NULL.
+ */
+#define DUK_HBUFFEROBJECT_VALID_BYTEOFFSET_INCL(h,off) \
+	(DUK_ASSERT_EXPR((h) != NULL), DUK_ASSERT_EXPR((h)->buf != NULL), \
+	((h)->offset + (off) < DUK_HBUFFER_GET_SIZE((h)->buf)))
+
+#define DUK_HBUFFEROBJECT_VALID_BYTEOFFSET_EXCL(h,off) \
+	(DUK_ASSERT_EXPR((h) != NULL), DUK_ASSERT_EXPR((h)->buf != NULL), \
+	((h)->offset + (off) <= DUK_HBUFFER_GET_SIZE((h)->buf)))
+
+/* Clamp an input byte length (already assumed to be within the nominal
+ * duk_hbufferobject 'length') to the current dynamic buffer limits to
+ * yield a byte length limit that's safe for memory accesses.  This value
+ * can be invalidated by any side effect because it may trigger a user
+ * callback that resizes the underlying buffer.
+ */
+#define DUK_HBUFFEROBJECT_CLAMP_BYTELENGTH(h,len) \
+	(DUK_ASSERT_EXPR((h) != NULL), \
+	duk_hbufferobject_clamp_bytelength((h), (len)))
+
+struct duk_hbufferobject {
+	/* Shared object part. */
+	duk_hobject obj;
+
+	/* Underlying buffer (refcounted), may be NULL. */
+	duk_hbuffer *buf;
+
+	/* Slice and accessor information.
+	 *
+	 * Because the underlying buffer may be dynamic, these may be
+	 * invalidated by the buffer being modified so that both offset
+	 * and length should be validated before every access.  Behavior
+	 * when the underlying buffer has changed doesn't need to be clean:
+	 * virtual 'length' doesn't need to be affected, reads can return
+	 * zero/NaN, and writes can be ignored.
+	 *
+	 * Note that a data pointer cannot be precomputed because 'buf' may
+	 * be dynamic and its pointer unstable.
+	 */
+
+	duk_uint_t offset;       /* byte offset to buf */
+	duk_uint_t length;       /* byte index limit for element access, exclusive */
+	duk_uint8_t shift;       /* element size shift:
+	                          *   0 = u8/i8
+	                          *   1 = u16/i16
+	                          *   2 = u32/i32/float
+	                          *   3 = double
+	                          */
+	duk_uint8_t elem_type;   /* element type */
+	duk_uint8_t is_view;
+};
+
+#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
+DUK_INTERNAL_DECL duk_uint_t duk_hbufferobject_clamp_bytelength(duk_hbufferobject *h_bufobj, duk_uint_t len);
+#endif
+DUK_INTERNAL_DECL void duk_hbufferobject_push_validated_read(duk_context *ctx, duk_hbufferobject *h_bufobj, duk_uint8_t *p, duk_small_uint_t elem_size);
+DUK_INTERNAL_DECL void duk_hbufferobject_validated_write(duk_context *ctx, duk_hbufferobject *h_bufobj, duk_uint8_t *p, duk_small_uint_t elem_size);
+
+#endif  /* DUK_HBUFFEROBJECT_H_INCLUDED */
 #line 1 "duk_hthread.h"
 /*
  *  Heap thread object representation.
@@ -6422,11 +9114,14 @@ struct duk_hnativefunction {
  *  Activation defines
  */
 
-#define DUK_ACT_FLAG_STRICT          (1 << 0)  /* function executes in strict mode */
-#define DUK_ACT_FLAG_TAILCALLED      (1 << 1)  /* activation has tailcalled one or more times */
-#define DUK_ACT_FLAG_CONSTRUCT       (1 << 2)  /* function executes as a constructor (called via "new") */
-#define DUK_ACT_FLAG_PREVENT_YIELD   (1 << 3)  /* activation prevents yield (native call or "new") */
-#define DUK_ACT_FLAG_DIRECT_EVAL     (1 << 4)  /* activation is a direct eval call */
+#define DUK_ACT_FLAG_STRICT             (1 << 0)  /* function executes in strict mode */
+#define DUK_ACT_FLAG_TAILCALLED         (1 << 1)  /* activation has tail called one or more times */
+#define DUK_ACT_FLAG_CONSTRUCT          (1 << 2)  /* function executes as a constructor (called via "new") */
+#define DUK_ACT_FLAG_PREVENT_YIELD      (1 << 3)  /* activation prevents yield (native call or "new") */
+#define DUK_ACT_FLAG_DIRECT_EVAL        (1 << 4)  /* activation is a direct eval call */
+#define DUK_ACT_FLAG_BREAKPOINT_ACTIVE  (1 << 5)  /* activation has active breakpoint(s) */
+
+#define DUK_ACT_GET_FUNC(act)        ((act)->func)
 
 /*
  *  Flags for __FILE__ / __LINE__ registered into tracedata
@@ -6492,7 +9187,13 @@ struct duk_hnativefunction {
  *  Thread defines
  */
 
-#define DUK_HTHREAD_GET_STRING(thr,idx)          ((thr)->strs[(idx)])
+#if defined(DUK_USE_HEAPPTR16)
+#define DUK_HTHREAD_GET_STRING(thr,idx) \
+	((duk_hstring *) DUK_USE_HEAPPTR_DEC16((thr)->heap->heap_udata, (thr)->strs16[(idx)]))
+#else
+#define DUK_HTHREAD_GET_STRING(thr,idx) \
+	((thr)->strs[(idx)])
+#endif
 
 #define DUK_HTHREAD_GET_CURRENT_ACTIVATION(thr)  (&(thr)->callstack[(thr)->callstack_top - 1])
 
@@ -6503,13 +9204,56 @@ struct duk_hnativefunction {
 #define DUK_HTHREAD_STATE_YIELDED      4   /* thread has yielded */
 #define DUK_HTHREAD_STATE_TERMINATED   5   /* thread has terminated */
 
+/* Executor interrupt default interval when nothing else requires a
+ * smaller value.  The default interval must be small enough to allow
+ * for reasonable execution timeout checking but large enough to keep
+ * impact on execution performance low.
+ */
+#if defined(DUK_USE_INTERRUPT_COUNTER)
+#define DUK_HTHREAD_INTCTR_DEFAULT     (256L * 1024L)
+#endif
+
+/*
+ *  Assert context is valid: non-NULL pointer, fields look sane.
+ *
+ *  This is used by public API call entrypoints to catch invalid 'ctx' pointers
+ *  as early as possible; invalid 'ctx' pointers cause very odd and difficult to
+ *  diagnose behavior so it's worth checking even when the check is not 100%.
+ */
+
+#if defined(DUK_USE_PREFER_SIZE)
+#define DUK_ASSERT_CTX_VSSIZE(ctx)  /*nop*/
+#else
+#define DUK_ASSERT_CTX_VSSIZE(ctx) \
+	DUK_ASSERT((duk_size_t) (((duk_hthread *) (ctx))->valstack_end - ((duk_hthread *) (ctx))->valstack) == \
+		((duk_hthread *) (ctx))->valstack_size)
+#endif
+#define DUK_ASSERT_CTX_VALID(ctx) do { \
+		DUK_ASSERT((ctx) != NULL); \
+		DUK_ASSERT(DUK_HEAPHDR_GET_TYPE((duk_heaphdr *) (ctx)) == DUK_HTYPE_OBJECT); \
+		DUK_ASSERT(DUK_HOBJECT_IS_THREAD((duk_hobject *) (ctx))); \
+		DUK_ASSERT(((duk_hthread *) (ctx))->unused1 == 0); \
+		DUK_ASSERT(((duk_hthread *) (ctx))->unused2 == 0); \
+		DUK_ASSERT(((duk_hthread *) (ctx))->valstack != NULL); \
+		DUK_ASSERT(((duk_hthread *) (ctx))->valstack_end >= ((duk_hthread *) (ctx))->valstack); \
+		DUK_ASSERT(((duk_hthread *) (ctx))->valstack_top >= ((duk_hthread *) (ctx))->valstack); \
+		DUK_ASSERT(((duk_hthread *) (ctx))->valstack_top >= ((duk_hthread *) (ctx))->valstack_bottom); \
+		DUK_ASSERT(((duk_hthread *) (ctx))->valstack_end >= ((duk_hthread *) (ctx))->valstack_top); \
+		DUK_ASSERT_CTX_VSSIZE((ctx)); \
+	} while (0)
+
 /*
  *  Struct defines
  */
 
-/* Note: it's nice if size is 2^N (now 32 bytes on 32 bit without 'caller' property) */
+/* XXX: for a memory-code tradeoff, remove 'func' and make it's access either a function
+ * or a macro.  This would make the activation 32 bytes long on 32-bit platforms again.
+ */
+
+/* Note: it's nice if size is 2^N (at least for 32-bit platforms). */
 struct duk_activation {
-	duk_hobject *func;      /* function being executed; for bound function calls, this is the final, real function */
+	duk_tval tv_func;       /* borrowed: full duk_tval for function being executed; for lightfuncs */
+	duk_hobject *func;      /* borrowed: function being executed; for bound function calls, this is the final, real function, NULL for lightfuncs */
 	duk_hobject *var_env;   /* current variable environment (may be NULL if delayed) */
 	duk_hobject *lex_env;   /* current lexical environment (may be NULL if delayed) */
 #ifdef DUK_USE_NONSTD_FUNC_CALLER_PROPERTY
@@ -6519,8 +9263,11 @@ struct duk_activation {
 	duk_hobject *prev_caller;
 #endif
 
+	duk_instr_t *curr_pc;   /* next instruction to execute (points to 'func' bytecode, stable pointer), NULL for native calls */
+#if defined(DUK_USE_DEBUGGER_SUPPORT)
+	duk_uint32_t prev_line; /* needed for stepping */
+#endif
 	duk_small_uint_t flags;
-	duk_uint32_t pc;        /* next instruction to execute */
 
 	/* idx_bottom and idx_retval are only used for book-keeping of
 	 * Ecmascript-initiated calls, to allow returning to an Ecmascript
@@ -6553,75 +9300,89 @@ struct duk_activation {
 	 * (calling) valstack.  This works for everything except tail
 	 * calls, which must not "cumulate" valstack temps.
 	 */
-
-#if defined(DUK_USE_32BIT_PTRS) && !defined(DUK_USE_NONSTD_FUNC_CALLER_PROPERTY)
-	/* Minor optimization: pad structure to 2^N size on 32-bit platforms. */
-	duk_int_t unused1;  /* pad to 2^N */
-#endif
 };
 
 /* Note: it's nice if size is 2^N (not 4x4 = 16 bytes on 32 bit) */
 struct duk_catcher {
 	duk_hstring *h_varname;         /* borrowed reference to catch variable name (or NULL if none) */
 	                                /* (reference is valid as long activation exists) */
+	duk_instr_t *pc_base;           /* resume execution from pc_base or pc_base+1 (points to 'func' bytecode, stable pointer) */
 	duk_size_t callstack_index;     /* callstack index of related activation */
 	duk_size_t idx_base;            /* idx_base and idx_base+1 get completion value and type */
-	duk_uint32_t pc_base;           /* resume execution from pc_base or pc_base+1 */
 	duk_uint32_t flags;             /* type and control flags, label number */
 };
 
 struct duk_hthread {
-	/* shared object part */
+	/* Shared object part */
 	duk_hobject obj;
 
-	/* backpointers */
+	/* Pointer to bytecode executor's 'curr_pc' variable.  Used to copy
+	 * the current PC back into the topmost activation when activation
+	 * state is about to change (or "syncing" is otherwise needed).  This
+	 * is rather awkward but important for performance, see execution.rst.
+	 */
+	duk_instr_t **ptr_curr_pc;
+
+	/* Backpointers. */
 	duk_heap *heap;
 
-	/* current strictness flag: affects API calls */
+	/* Current strictness flag: affects API calls. */
 	duk_uint8_t strict;
+
+	/* Thread state. */
 	duk_uint8_t state;
 	duk_uint8_t unused1;
 	duk_uint8_t unused2;
 
-	/* sanity limits */
+	/* Sanity limits for stack sizes. */
 	duk_size_t valstack_max;
 	duk_size_t callstack_max;
 	duk_size_t catchstack_max;
 
-	/* XXX: valstack, callstack, and catchstack are currently assumed
+	/* XXX: Valstack, callstack, and catchstack are currently assumed
 	 * to have non-NULL pointers.  Relaxing this would not lead to big
 	 * benefits (except perhaps for terminated threads).
 	 */
 
-	/* value stack: these are expressed as pointers for faster stack manipulation */
-	duk_tval *valstack;			/* start of valstack allocation */
-	duk_tval *valstack_end;			/* end of valstack allocation (exclusive) */
-	duk_tval *valstack_bottom;		/* bottom of current frame */
-	duk_tval *valstack_top;			/* top of current frame (exclusive) */
+	/* Value stack: these are expressed as pointers for faster stack manipulation.
+	 * [valstack,valstack_top[ is GC-reachable, [valstack_top,valstack_end[ is
+	 * not GC-reachable but kept initialized as 'undefined'.
+	 */
+	duk_tval *valstack;                     /* start of valstack allocation */
+	duk_tval *valstack_end;                 /* end of valstack allocation (exclusive) */
+	duk_tval *valstack_bottom;              /* bottom of current frame */
+	duk_tval *valstack_top;                 /* top of current frame (exclusive) */
+#if !defined(DUK_USE_PREFER_SIZE)
+	duk_size_t valstack_size;               /* cached: valstack_end - valstack (in entries, not bytes) */
+#endif
 
-	/* call stack */
+	/* Call stack.  [0,callstack_top[ is GC reachable. */
 	duk_activation *callstack;
-	duk_size_t callstack_size;		/* allocation size */
-	duk_size_t callstack_top;		/* next to use, highest used is top - 1 */
-	duk_size_t callstack_preventcount;	/* number of activation records in callstack preventing a yield */
+	duk_size_t callstack_size;              /* allocation size */
+	duk_size_t callstack_top;               /* next to use, highest used is top - 1 */
+	duk_size_t callstack_preventcount;      /* number of activation records in callstack preventing a yield */
 
-	/* catch stack */
+	/* Catch stack.  [0,catchstack_top[ is GC reachable. */
 	duk_catcher *catchstack;
-	duk_size_t catchstack_size;		/* allocation size */
-	duk_size_t catchstack_top;		/* next to use, highest used is top - 1 */
+	duk_size_t catchstack_size;             /* allocation size */
+	duk_size_t catchstack_top;              /* next to use, highest used is top - 1 */
 
-	/* yield/resume book-keeping */
-	duk_hthread *resumer;			/* who resumed us (if any) */
+	/* Yield/resume book-keeping. */
+	duk_hthread *resumer;                   /* who resumed us (if any) */
 
-#ifdef DUK_USE_INTERRUPT_COUNTER
+	/* Current compiler state (if any), used for augmenting SyntaxErrors. */
+	duk_compiler_ctx *compile_ctx;
+
+#if defined(DUK_USE_INTERRUPT_COUNTER)
 	/* Interrupt counter for triggering a slow path check for execution
-	 * timeout, debugger interaction such as breakpoints, etc.  This is
-	 * actually a value copied from the heap structure into the current
-	 * thread to be more convenient for the bytecode executor inner loop.
-	 * The final value is copied back to the heap structure on a thread
-	 * switch by DUK_HEAP_SWITCH_THREAD().
+	 * timeout, debugger interaction such as breakpoints, etc.  The value
+	 * is valid for the current running thread, and both the init and
+	 * counter values are copied whenever a thread switch occurs.  It's
+	 * important for the counter to be conveniently accessible for the
+	 * bytecode executor inner loop for performance reasons.
 	 */
-	duk_int_t interrupt_counter;
+	duk_int_t interrupt_counter;    /* countdown state */
+	duk_int_t interrupt_init;       /* start value for current countdown */
 #endif
 
 	/* Builtin-objects; may or may not be shared with other threads,
@@ -6633,30 +9394,41 @@ struct duk_hthread {
 	 */
 	duk_hobject *builtins[DUK_NUM_BUILTINS];
 
-	/* convenience copies from heap/vm for faster access */
-	duk_hstring **strs;			/* (from duk_heap) */
+	/* Convenience copies from heap/vm for faster access. */
+#if defined(DUK_USE_HEAPPTR16)
+	duk_uint16_t *strs16;
+#else
+	duk_hstring **strs;
+#endif
 };
 
 /*
  *  Prototypes
  */
 
-void duk_hthread_copy_builtin_objects(duk_hthread *thr_from, duk_hthread *thr_to);
-void duk_hthread_create_builtin_objects(duk_hthread *thr);
-duk_bool_t duk_hthread_init_stacks(duk_heap *heap, duk_hthread *thr);
-void duk_hthread_terminate(duk_hthread *thr);
+DUK_INTERNAL_DECL void duk_hthread_copy_builtin_objects(duk_hthread *thr_from, duk_hthread *thr_to);
+DUK_INTERNAL_DECL void duk_hthread_create_builtin_objects(duk_hthread *thr);
+DUK_INTERNAL_DECL duk_bool_t duk_hthread_init_stacks(duk_heap *heap, duk_hthread *thr);
+DUK_INTERNAL_DECL void duk_hthread_terminate(duk_hthread *thr);
 
-void duk_hthread_callstack_grow(duk_hthread *thr);
-void duk_hthread_callstack_shrink_check(duk_hthread *thr);
-void duk_hthread_callstack_unwind(duk_hthread *thr, duk_size_t new_top);
-void duk_hthread_catchstack_grow(duk_hthread *thr);
-void duk_hthread_catchstack_shrink_check(duk_hthread *thr);
-void duk_hthread_catchstack_unwind(duk_hthread *thr, duk_size_t new_top);
+DUK_INTERNAL_DECL void duk_hthread_callstack_grow(duk_hthread *thr);
+DUK_INTERNAL_DECL void duk_hthread_callstack_shrink_check(duk_hthread *thr);
+DUK_INTERNAL_DECL void duk_hthread_callstack_unwind(duk_hthread *thr, duk_size_t new_top);
+DUK_INTERNAL_DECL void duk_hthread_catchstack_grow(duk_hthread *thr);
+DUK_INTERNAL_DECL void duk_hthread_catchstack_shrink_check(duk_hthread *thr);
+DUK_INTERNAL_DECL void duk_hthread_catchstack_unwind(duk_hthread *thr, duk_size_t new_top);
 
-duk_activation *duk_hthread_get_current_activation(duk_hthread *thr);
-void *duk_hthread_get_valstack_ptr(void *ud);  /* indirect allocs */
-void *duk_hthread_get_callstack_ptr(void *ud);  /* indirect allocs */
-void *duk_hthread_get_catchstack_ptr(void *ud);  /* indirect allocs */
+DUK_INTERNAL_DECL duk_activation *duk_hthread_get_current_activation(duk_hthread *thr);
+DUK_INTERNAL_DECL void *duk_hthread_get_valstack_ptr(duk_heap *heap, void *ud);  /* indirect allocs */
+DUK_INTERNAL_DECL void *duk_hthread_get_callstack_ptr(duk_heap *heap, void *ud);  /* indirect allocs */
+DUK_INTERNAL_DECL void *duk_hthread_get_catchstack_ptr(duk_heap *heap, void *ud);  /* indirect allocs */
+
+#if defined(DUK_USE_DEBUGGER_SUPPORT)
+DUK_INTERNAL_DECL duk_uint_fast32_t duk_hthread_get_act_curr_pc(duk_hthread *thr, duk_activation *act);
+#endif
+DUK_INTERNAL_DECL duk_uint_fast32_t duk_hthread_get_act_prev_pc(duk_hthread *thr, duk_activation *act);
+DUK_INTERNAL_DECL void duk_hthread_sync_currpc(duk_hthread *thr);
+DUK_INTERNAL_DECL void duk_hthread_sync_and_null_currpc(duk_hthread *thr);
 
 #endif  /* DUK_HTHREAD_H_INCLUDED */
 #line 1 "duk_hbuffer.h"
@@ -6674,59 +9446,174 @@ void *duk_hthread_get_catchstack_ptr(void *ud);  /* indirect allocs */
 #ifndef DUK_HBUFFER_H_INCLUDED
 #define DUK_HBUFFER_H_INCLUDED
 
-/* Impose a maximum buffer length for now.  Restricted artificially to
- * ensure resize computations or adding a heap header length won't
- * overflow size_t.  The limit should be synchronized with
- * DUK_HSTRING_MAX_BYTELEN.
+/*
+ *  Flags
+ *
+ *  Fixed buffer:     0
+ *  Dynamic buffer:   DUK_HBUFFER_FLAG_DYNAMIC
+ *  External buffer:  DUK_HBUFFER_FLAG_DYNAMIC | DUK_HBUFFER_FLAG_EXTERNAL
  */
-#define DUK_HBUFFER_MAX_BYTELEN                   (0x7fffffffUL)
 
-#define DUK_HBUFFER_FLAG_DYNAMIC                  DUK_HEAPHDR_USER_FLAG(0)  /* buffer is resizable */
+#define DUK_HBUFFER_FLAG_DYNAMIC                  DUK_HEAPHDR_USER_FLAG(0)    /* buffer is behind a pointer, dynamic or external */
+#define DUK_HBUFFER_FLAG_EXTERNAL                 DUK_HEAPHDR_USER_FLAG(1)    /* buffer pointer is to an externally allocated buffer */
 
 #define DUK_HBUFFER_HAS_DYNAMIC(x)                DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HBUFFER_FLAG_DYNAMIC)
+#define DUK_HBUFFER_HAS_EXTERNAL(x)               DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HBUFFER_FLAG_EXTERNAL)
 
 #define DUK_HBUFFER_SET_DYNAMIC(x)                DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HBUFFER_FLAG_DYNAMIC)
+#define DUK_HBUFFER_SET_EXTERNAL(x)               DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HBUFFER_FLAG_EXTERNAL)
 
 #define DUK_HBUFFER_CLEAR_DYNAMIC(x)              DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HBUFFER_FLAG_DYNAMIC)
+#define DUK_HBUFFER_CLEAR_EXTERNAL(x)             DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HBUFFER_FLAG_EXTERNAL)
 
-#define DUK_HBUFFER_FIXED_GET_DATA_PTR(x)         ((duk_uint8_t *) (((duk_hbuffer_fixed *) (x)) + 1))
-#define DUK_HBUFFER_FIXED_GET_SIZE(x)             ((x)->u.s.size)
+/*
+ *  Misc defines
+ */
+
+/* Impose a maximum buffer length for now.  Restricted artificially to
+ * ensure resize computations or adding a heap header length won't
+ * overflow size_t and that a signed duk_int_t can hold a buffer
+ * length.  The limit should be synchronized with DUK_HSTRING_MAX_BYTELEN.
+ */
 
-#define DUK_HBUFFER_DYNAMIC_GET_ALLOC_SIZE(x)     ((x)->usable_size)
-#define DUK_HBUFFER_DYNAMIC_GET_USABLE_SIZE(x)    ((x)->usable_size)
-#define DUK_HBUFFER_DYNAMIC_GET_SPARE_SIZE(x)     ((x)->usable_size - (x)->size)
-#define DUK_HBUFFER_DYNAMIC_GET_CURR_DATA_PTR(x)  ((x)->curr_alloc)
+#if defined(DUK_USE_BUFLEN16)
+#define DUK_HBUFFER_MAX_BYTELEN                   (0x0000ffffUL)
+#else
+/* Intentionally not 0x7fffffffUL; at least JSON code expects that
+ * 2*len + 2 fits in 32 bits.
+ */
+#define DUK_HBUFFER_MAX_BYTELEN                   (0x7ffffffeUL)
+#endif
 
-/* gets the actual buffer contents which matches the current allocation size
- * (may be NULL for zero size dynamic buffer)
+/*
+ *  Field access
  */
-#define DUK_HBUFFER_GET_DATA_PTR(x)  ( \
-	DUK_HBUFFER_HAS_DYNAMIC((x)) ? \
-		DUK_HBUFFER_DYNAMIC_GET_CURR_DATA_PTR((duk_hbuffer_dynamic *) (x)) : \
-		DUK_HBUFFER_FIXED_GET_DATA_PTR((duk_hbuffer_fixed *) (x)) \
-	)
 
-/* gets the current user visible size, without accounting for a dynamic
+/* Get/set the current user visible size, without accounting for a dynamic
  * buffer's "spare" (= usable size).
  */
-#define DUK_HBUFFER_GET_SIZE(x)         ((x)->size)
+#if defined(DUK_USE_BUFLEN16)
+/* size stored in duk_heaphdr unused flag bits */
+#define DUK_HBUFFER_GET_SIZE(x)     ((x)->hdr.h_flags >> 16)
+#define DUK_HBUFFER_SET_SIZE(x,v)   do { \
+		(x)->hdr.h_flags = ((x)->hdr.h_flags & 0x0000ffffUL) | ((v) << 16); \
+	} while (0)
+#define DUK_HBUFFER_ADD_SIZE(x,dv)  do { \
+		(x)->hdr.h_flags += ((dv) << 16); \
+	} while (0)
+#define DUK_HBUFFER_SUB_SIZE(x,dv)  do { \
+		(x)->hdr.h_flags -= ((dv) << 16); \
+	} while (0)
+#else
+#define DUK_HBUFFER_GET_SIZE(x)     (((duk_hbuffer *) (x))->size)
+#define DUK_HBUFFER_SET_SIZE(x,v)   do { \
+		((duk_hbuffer *) (x))->size = (v); \
+	} while (0)
+#define DUK_HBUFFER_ADD_SIZE(x,dv)  do { \
+		(x)->size += (dv); \
+	} while (0)
+#define DUK_HBUFFER_SUB_SIZE(x,dv)  do { \
+		(x)->size -= (dv); \
+	} while (0)
+#endif
+
+#define DUK_HBUFFER_FIXED_GET_SIZE(x)       DUK_HBUFFER_GET_SIZE((duk_hbuffer *) (x))
+#define DUK_HBUFFER_FIXED_SET_SIZE(x,v)     DUK_HBUFFER_SET_SIZE((duk_hbuffer *) (x))
+
+#define DUK_HBUFFER_DYNAMIC_GET_SIZE(x)     DUK_HBUFFER_GET_SIZE((duk_hbuffer *) (x))
+#define DUK_HBUFFER_DYNAMIC_SET_SIZE(x,v)   DUK_HBUFFER_SET_SIZE((duk_hbuffer *) (x), (v))
+#define DUK_HBUFFER_DYNAMIC_ADD_SIZE(x,dv)  DUK_HBUFFER_ADD_SIZE((duk_hbuffer *) (x), (dv))
+#define DUK_HBUFFER_DYNAMIC_SUB_SIZE(x,dv)  DUK_HBUFFER_SUB_SIZE((duk_hbuffer *) (x), (dv))
+
+#define DUK_HBUFFER_EXTERNAL_GET_SIZE(x)    DUK_HBUFFER_GET_SIZE((duk_hbuffer *) (x))
+#define DUK_HBUFFER_EXTERNAL_SET_SIZE(x,v)  DUK_HBUFFER_SET_SIZE((duk_hbuffer *) (x), (v))
 
-#define DUK_HBUFFER_SET_SIZE(x,val)  do { \
-		(x)->size = (val); \
+#define DUK_HBUFFER_FIXED_GET_DATA_PTR(heap,x)    ((duk_uint8_t *) (((duk_hbuffer_fixed *) (x)) + 1))
+
+#if defined(DUK_USE_HEAPPTR16)
+#define DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(heap,x) \
+	((void *) DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, ((duk_heaphdr *) (x))->h_extra16))
+#define DUK_HBUFFER_DYNAMIC_SET_DATA_PTR(heap,x,v)     do { \
+		((duk_heaphdr *) (x))->h_extra16 = DUK_USE_HEAPPTR_ENC16((heap)->heap_udata, (void *) (v)); \
+	} while (0)
+#define DUK_HBUFFER_DYNAMIC_SET_DATA_PTR_NULL(heap,x)  do { \
+		((duk_heaphdr *) (x))->h_extra16 = 0;  /* assume 0 <=> NULL */ \
+	} while (0)
+#else
+#define DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(heap,x)       ((x)->curr_alloc)
+#define DUK_HBUFFER_DYNAMIC_SET_DATA_PTR(heap,x,v)     do { \
+		(x)->curr_alloc = (void *) (v); \
+	} while (0)
+#define DUK_HBUFFER_DYNAMIC_SET_DATA_PTR_NULL(heap,x)  do { \
+		(x)->curr_alloc = (void *) NULL; \
 	} while (0)
+#endif
 
-/* growth parameters */
-#define DUK_HBUFFER_SPARE_ADD      16
-#define DUK_HBUFFER_SPARE_DIVISOR  16   /* 2^4 -> 1/16 = 6.25% spare */
+/* No pointer compression because pointer is potentially outside of
+ * Duktape heap.
+ */
+#if defined(DUK_USE_HEAPPTR16)
+#define DUK_HBUFFER_EXTERNAL_GET_DATA_PTR(heap,x) \
+	((void *) (x)->curr_alloc)
+#define DUK_HBUFFER_EXTERNAL_SET_DATA_PTR(heap,x,v)     do { \
+		(x)->curr_alloc = (void *) (v); \
+	} while (0)
+#define DUK_HBUFFER_EXTERNAL_SET_DATA_PTR_NULL(heap,x)  do { \
+		(x)->curr_alloc = (void *) NULL; \
+	} while (0)
+#else
+#define DUK_HBUFFER_EXTERNAL_GET_DATA_PTR(heap,x) \
+	((void *) (x)->curr_alloc)
+#define DUK_HBUFFER_EXTERNAL_SET_DATA_PTR(heap,x,v)     do { \
+		(x)->curr_alloc = (void *) (v); \
+	} while (0)
+#define DUK_HBUFFER_EXTERNAL_SET_DATA_PTR_NULL(heap,x)  do { \
+		(x)->curr_alloc = (void *) NULL; \
+	} while (0)
+#endif
 
+/* Get a pointer to the current buffer contents (matching current allocation
+ * size).  May be NULL for zero size dynamic/external buffer.
+ */
+#if defined(DUK_USE_HEAPPTR16)
+#define DUK_HBUFFER_GET_DATA_PTR(heap,x)  ( \
+	DUK_HBUFFER_HAS_DYNAMIC((x)) ? \
+		( \
+			DUK_HBUFFER_HAS_EXTERNAL((x)) ? \
+				DUK_HBUFFER_EXTERNAL_GET_DATA_PTR((heap), (duk_hbuffer_external *) (x)) : \
+				DUK_HBUFFER_DYNAMIC_GET_DATA_PTR((heap), (duk_hbuffer_dynamic *) (x)) \
+		) : \
+		DUK_HBUFFER_FIXED_GET_DATA_PTR((heap), (duk_hbuffer_fixed *) (x)) \
+	)
+#else
+/* Without heap pointer compression duk_hbuffer_dynamic and duk_hbuffer_external
+ * have the same layout so checking for fixed vs. dynamic (or external) is enough.
+ */
+#define DUK_HBUFFER_GET_DATA_PTR(heap,x)  ( \
+	DUK_HBUFFER_HAS_DYNAMIC((x)) ? \
+		DUK_HBUFFER_DYNAMIC_GET_DATA_PTR((heap), (duk_hbuffer_dynamic *) (x)) : \
+		DUK_HBUFFER_FIXED_GET_DATA_PTR((heap), (duk_hbuffer_fixed *) (x)) \
+	)
+#endif
+
+/*
+ *  Structs
+ */
+
+/* Shared prefix for all buffer types. */
 struct duk_hbuffer {
 	duk_heaphdr hdr;
 
-	/* it's not strictly necessary to track the current size, but
+	/* It's not strictly necessary to track the current size, but
 	 * it is useful for writing robust native code.
 	 */
 
-	duk_size_t size;  /* current size (not counting a dynamic buffer's "spare") */
+	/* Current size (not counting a dynamic buffer's "spare"). */
+#if defined(DUK_USE_BUFLEN16)
+	/* Stored in duk_heaphdr unused flags. */
+#else
+	duk_size_t size;
+#endif
 
 	/*
 	 *  Data following the header depends on the DUK_HBUFFER_FLAG_DYNAMIC
@@ -6741,6 +9628,11 @@ struct duk_hbuffer {
 	 *    - a "void *" pointing to the current allocation
 	 *    - a duk_size_t indicating the full allocated size (always >= 'size')
 	 *
+	 *  If DUK_HBUFFER_FLAG_EXTERNAL is set, the buffer has been allocated
+	 *  by user code, so that Duktape won't be able to resize it and won't
+	 *  free it.  This allows buffers to point to e.g. an externally
+	 *  allocated structure such as a frame buffer.
+	 *
 	 *  Unlike strings, no terminator byte (NUL) is guaranteed after the
 	 *  data.  This would be convenient, but would pad aligned user buffers
 	 *  unnecessarily upwards in size.  For instance, if user code requested
@@ -6749,7 +9641,10 @@ struct duk_hbuffer {
 	 */
 };
 
-#if defined(DUK_USE_ALIGN_8) && defined(DUK_USE_PACK_MSVC_PRAGMA)
+/* Fixed buffer; data follows struct, with proper alignment guaranteed by
+ * struct size.
+ */
+#if (DUK_USE_ALIGN_BY == 8) && defined(DUK_USE_PACK_MSVC_PRAGMA)
 #pragma pack(push, 8)
 #endif
 struct duk_hbuffer_fixed {
@@ -6762,14 +9657,20 @@ struct duk_hbuffer_fixed {
 	union {
 		struct {
 			duk_heaphdr hdr;
+#if defined(DUK_USE_BUFLEN16)
+			/* Stored in duk_heaphdr unused flags. */
+#else
 			duk_size_t size;
+#endif
 		} s;
-#if defined(DUK_USE_ALIGN_4)
+#if (DUK_USE_ALIGN_BY == 4)
 		duk_uint32_t dummy_for_align4;
-#elif defined(DUK_USE_ALIGN_8)
-		duk_uint64_t dummy_for_align8;
-#else
+#elif (DUK_USE_ALIGN_BY == 8)
+		duk_double_t dummy_for_align8;
+#elif (DUK_USE_ALIGN_BY == 1)
 		/* no extra padding */
+#else
+#error invalid DUK_USE_ALIGN_BY
 #endif
 	} u;
 
@@ -6786,27 +9687,38 @@ struct duk_hbuffer_fixed {
 	 *  dynamic buffer).
 	 */
 }
-#if defined(DUK_USE_ALIGN_8) && defined(DUK_USE_PACK_GCC_ATTR)
+#if (DUK_USE_ALIGN_BY == 8) && defined(DUK_USE_PACK_GCC_ATTR)
 __attribute__ ((aligned (8)))
-#elif defined(DUK_USE_ALIGN_8) && defined(DUK_USE_PACK_CLANG_ATTR)
+#elif (DUK_USE_ALIGN_BY == 8) && defined(DUK_USE_PACK_CLANG_ATTR)
 __attribute__ ((aligned (8)))
 #endif
 ;
-#if defined(DUK_USE_ALIGN_8) && defined(DUK_USE_PACK_MSVC_PRAGMA)
+#if (DUK_USE_ALIGN_BY == 8) && defined(DUK_USE_PACK_MSVC_PRAGMA)
 #pragma pack(pop)
 #endif
 
+/* Dynamic buffer with 'curr_alloc' pointing to a dynamic area allocated using
+ * heap allocation primitives.  Also used for external buffers when low memory
+ * options are not used.
+ */
 struct duk_hbuffer_dynamic {
 	duk_heaphdr hdr;
+
+#if defined(DUK_USE_BUFLEN16)
+	/* Stored in duk_heaphdr unused flags. */
+#else
 	duk_size_t size;
+#endif
 
-	void *curr_alloc;  /* may be NULL if usable_size == 0 */
-	duk_size_t usable_size;
+#if defined(DUK_USE_HEAPPTR16)
+	/* Stored in duk_heaphdr h_extra16. */
+#else
+	void *curr_alloc;  /* may be NULL if alloc_size == 0 */
+#endif
 
 	/*
-	 *  Allocation size for 'curr_alloc' is usable_size directly.
-	 *  There is no automatic NUL terminator for buffers (see above
-	 *  for rationale).
+	 *  Allocation size for 'curr_alloc' is alloc_size.  There is no
+	 *  automatic NUL terminator for buffers (see above for rationale).
 	 *
 	 *  'curr_alloc' is explicitly allocated with heap allocation
 	 *  primitives and will thus always have alignment suitable for
@@ -6814,33 +9726,35 @@ struct duk_hbuffer_dynamic {
 	 */
 };
 
+/* External buffer with 'curr_alloc' managed by user code and pointing to an
+ * arbitrary address.  When heap pointer compression is not used, this struct
+ * has the same layout as duk_hbuffer_dynamic.
+ */
+struct duk_hbuffer_external {
+	duk_heaphdr hdr;
+
+#if defined(DUK_USE_BUFLEN16)
+	/* Stored in duk_heaphdr unused flags. */
+#else
+	duk_size_t size;
+#endif
+
+	/* Cannot be compressed as a heap pointer because may point to
+	 * an arbitrary address.
+	 */
+	void *curr_alloc;  /* may be NULL if alloc_size == 0 */
+};
+
 /*
  *  Prototypes
  */
 
-duk_hbuffer *duk_hbuffer_alloc(duk_heap *heap, duk_size_t size, duk_bool_t dynamic);
-void *duk_hbuffer_get_dynalloc_ptr(void *ud);  /* indirect allocs */
+DUK_INTERNAL_DECL duk_hbuffer *duk_hbuffer_alloc(duk_heap *heap, duk_size_t size, duk_small_uint_t flags, void **out_bufdata);
+DUK_INTERNAL_DECL void *duk_hbuffer_get_dynalloc_ptr(duk_heap *heap, void *ud);  /* indirect allocs */
 
 /* dynamic buffer ops */
-void duk_hbuffer_resize(duk_hthread *thr, duk_hbuffer_dynamic *buf, duk_size_t new_size, duk_size_t new_usable_size);
-void duk_hbuffer_reset(duk_hthread *thr, duk_hbuffer_dynamic *buf);
-void duk_hbuffer_compact(duk_hthread *thr, duk_hbuffer_dynamic *buf);
-void duk_hbuffer_append_bytes(duk_hthread *thr, duk_hbuffer_dynamic *buf, duk_uint8_t *data, duk_size_t length);
-void duk_hbuffer_append_byte(duk_hthread *thr, duk_hbuffer_dynamic *buf, duk_uint8_t byte);
-duk_size_t duk_hbuffer_append_cstring(duk_hthread *thr, duk_hbuffer_dynamic *buf, const char *str);
-duk_size_t duk_hbuffer_append_hstring(duk_hthread *thr, duk_hbuffer_dynamic *buf, duk_hstring *str);
-duk_size_t duk_hbuffer_append_xutf8(duk_hthread *thr, duk_hbuffer_dynamic *buf, duk_ucodepoint_t codepoint);
-duk_size_t duk_hbuffer_append_cesu8(duk_hthread *thr, duk_hbuffer_dynamic *buf, duk_ucodepoint_t codepoint);
-void duk_hbuffer_append_native_u32(duk_hthread *thr, duk_hbuffer_dynamic *buf, duk_uint32_t val);
-void duk_hbuffer_insert_bytes(duk_hthread *thr, duk_hbuffer_dynamic *buf, duk_size_t offset, duk_uint8_t *data, duk_size_t length);
-void duk_hbuffer_insert_byte(duk_hthread *thr, duk_hbuffer_dynamic *buf, duk_size_t offset, duk_uint8_t byte);
-duk_size_t duk_hbuffer_insert_cstring(duk_hthread *thr, duk_hbuffer_dynamic *buf, duk_size_t offset, const char *str);
-duk_size_t duk_hbuffer_insert_hstring(duk_hthread *thr, duk_hbuffer_dynamic *buf, duk_size_t offset, duk_hstring *str);
-duk_size_t duk_hbuffer_insert_xutf8(duk_hthread *thr, duk_hbuffer_dynamic *buf, duk_size_t offset, duk_ucodepoint_t codepoint);
-duk_size_t duk_hbuffer_insert_cesu8(duk_hthread *thr, duk_hbuffer_dynamic *buf, duk_size_t offset, duk_ucodepoint_t codepoint);
-void duk_hbuffer_remove_slice(duk_hthread *thr, duk_hbuffer_dynamic *buf, duk_size_t offset, duk_size_t length);
-void duk_hbuffer_insert_slice(duk_hthread *thr, duk_hbuffer_dynamic *buf, duk_size_t dst_offset, duk_size_t src_offset, duk_size_t length);
-void duk_hbuffer_append_slice(duk_hthread *thr, duk_hbuffer_dynamic *buf, duk_size_t src_offset, duk_size_t length);
+DUK_INTERNAL_DECL void duk_hbuffer_resize(duk_hthread *thr, duk_hbuffer_dynamic *buf, duk_size_t new_size);
+DUK_INTERNAL_DECL void duk_hbuffer_reset(duk_hthread *thr, duk_hbuffer_dynamic *buf);
 
 #endif  /* DUK_HBUFFER_H_INCLUDED */
 #line 1 "duk_heap.h"
@@ -6864,6 +9778,8 @@ void duk_hbuffer_append_slice(duk_hthread *thr, duk_hbuffer_dynamic *buf, duk_si
 #define DUK_HEAP_FLAG_MARKANDSWEEP_RECLIMIT_REACHED            (1 << 1)  /* mark-and-sweep marking reached a recursion limit and must use multi-pass marking */
 #define DUK_HEAP_FLAG_REFZERO_FREE_RUNNING                     (1 << 2)  /* refcount code is processing refzero list */
 #define DUK_HEAP_FLAG_ERRHANDLER_RUNNING                       (1 << 3)  /* an error handler (user callback to augment/replace error) is running */
+#define DUK_HEAP_FLAG_INTERRUPT_RUNNING                        (1 << 4)  /* executor interrupt running (used to avoid nested interrupts) */
+#define DUK_HEAP_FLAG_FINALIZER_NORESCUE                       (1 << 5)  /* heap destruction ongoing, finalizer rescue no longer possible */
 
 #define DUK__HEAP_HAS_FLAGS(heap,bits)               ((heap)->flags & (bits))
 #define DUK__HEAP_SET_FLAGS(heap,bits)  do { \
@@ -6877,32 +9793,35 @@ void duk_hbuffer_append_slice(duk_hthread *thr, duk_hbuffer_dynamic *buf, duk_si
 #define DUK_HEAP_HAS_MARKANDSWEEP_RECLIMIT_REACHED(heap)   DUK__HEAP_HAS_FLAGS((heap), DUK_HEAP_FLAG_MARKANDSWEEP_RECLIMIT_REACHED)
 #define DUK_HEAP_HAS_REFZERO_FREE_RUNNING(heap)            DUK__HEAP_HAS_FLAGS((heap), DUK_HEAP_FLAG_REFZERO_FREE_RUNNING)
 #define DUK_HEAP_HAS_ERRHANDLER_RUNNING(heap)              DUK__HEAP_HAS_FLAGS((heap), DUK_HEAP_FLAG_ERRHANDLER_RUNNING)
+#define DUK_HEAP_HAS_INTERRUPT_RUNNING(heap)               DUK__HEAP_HAS_FLAGS((heap), DUK_HEAP_FLAG_INTERRUPT_RUNNING)
+#define DUK_HEAP_HAS_FINALIZER_NORESCUE(heap)              DUK__HEAP_HAS_FLAGS((heap), DUK_HEAP_FLAG_FINALIZER_NORESCUE)
 
 #define DUK_HEAP_SET_MARKANDSWEEP_RUNNING(heap)            DUK__HEAP_SET_FLAGS((heap), DUK_HEAP_FLAG_MARKANDSWEEP_RUNNING)
 #define DUK_HEAP_SET_MARKANDSWEEP_RECLIMIT_REACHED(heap)   DUK__HEAP_SET_FLAGS((heap), DUK_HEAP_FLAG_MARKANDSWEEP_RECLIMIT_REACHED)
 #define DUK_HEAP_SET_REFZERO_FREE_RUNNING(heap)            DUK__HEAP_SET_FLAGS((heap), DUK_HEAP_FLAG_REFZERO_FREE_RUNNING)
 #define DUK_HEAP_SET_ERRHANDLER_RUNNING(heap)              DUK__HEAP_SET_FLAGS((heap), DUK_HEAP_FLAG_ERRHANDLER_RUNNING)
+#define DUK_HEAP_SET_INTERRUPT_RUNNING(heap)               DUK__HEAP_SET_FLAGS((heap), DUK_HEAP_FLAG_INTERRUPT_RUNNING)
+#define DUK_HEAP_SET_FINALIZER_NORESCUE(heap)              DUK__HEAP_SET_FLAGS((heap), DUK_HEAP_FLAG_FINALIZER_NORESCUE)
 
 #define DUK_HEAP_CLEAR_MARKANDSWEEP_RUNNING(heap)          DUK__HEAP_CLEAR_FLAGS((heap), DUK_HEAP_FLAG_MARKANDSWEEP_RUNNING)
 #define DUK_HEAP_CLEAR_MARKANDSWEEP_RECLIMIT_REACHED(heap) DUK__HEAP_CLEAR_FLAGS((heap), DUK_HEAP_FLAG_MARKANDSWEEP_RECLIMIT_REACHED)
 #define DUK_HEAP_CLEAR_REFZERO_FREE_RUNNING(heap)          DUK__HEAP_CLEAR_FLAGS((heap), DUK_HEAP_FLAG_REFZERO_FREE_RUNNING)
 #define DUK_HEAP_CLEAR_ERRHANDLER_RUNNING(heap)            DUK__HEAP_CLEAR_FLAGS((heap), DUK_HEAP_FLAG_ERRHANDLER_RUNNING)
+#define DUK_HEAP_CLEAR_INTERRUPT_RUNNING(heap)             DUK__HEAP_CLEAR_FLAGS((heap), DUK_HEAP_FLAG_INTERRUPT_RUNNING)
+#define DUK_HEAP_CLEAR_FINALIZER_NORESCUE(heap)            DUK__HEAP_CLEAR_FLAGS((heap), DUK_HEAP_FLAG_FINALIZER_NORESCUE)
 
 /*
  *  Longjmp types, also double as identifying continuation type for a rethrow (in 'finally')
  */
 
 #define DUK_LJ_TYPE_UNKNOWN      0    /* unused */
-#define DUK_LJ_TYPE_RETURN       1    /* value1 -> return value */
-#define DUK_LJ_TYPE_THROW        2    /* value1 -> error object */
-#define DUK_LJ_TYPE_BREAK        3    /* value1 -> label number */
-#define DUK_LJ_TYPE_CONTINUE     4    /* value1 -> label number */
-#define DUK_LJ_TYPE_YIELD        5    /* value1 -> yield value, iserror -> error / normal */
-#define DUK_LJ_TYPE_RESUME       6    /* value1 -> resume value, value2 -> resumee thread, iserror -> error/normal */
-#define DUK_LJ_TYPE_NORMAL       7    /* pseudo-type to indicate a normal continuation (for 'finally' rethrowing) */
-
-/* dummy non-zero value to be used as an argument for longjmp(), see man longjmp */
-#define DUK_LONGJMP_DUMMY_VALUE  1
+#define DUK_LJ_TYPE_THROW        1    /* value1 -> error object */
+#define DUK_LJ_TYPE_YIELD        2    /* value1 -> yield value, iserror -> error / normal */
+#define DUK_LJ_TYPE_RESUME       3    /* value1 -> resume value, value2 -> resumee thread, iserror -> error/normal */
+#define DUK_LJ_TYPE_BREAK        4    /* value1 -> label number, pseudo-type to indicate a break continuation (for ENDFIN) */
+#define DUK_LJ_TYPE_CONTINUE     5    /* value1 -> label number, pseudo-type to indicate a continue continuation (for ENDFIN) */
+#define DUK_LJ_TYPE_RETURN       6    /* value1 -> return value, pseudo-type to indicate a return continuation (for ENDFIN) */
+#define DUK_LJ_TYPE_NORMAL       7    /* no value, pseudo-type to indicate a normal continuation (for ENDFIN) */
 
 /*
  *  Mark-and-sweep flags
@@ -6914,8 +9833,9 @@ void duk_hbuffer_append_slice(duk_hthread *thr, duk_hbuffer_dynamic *buf, duk_si
 
 #define DUK_MS_FLAG_EMERGENCY                (1 << 0)   /* emergency mode: try extra hard */
 #define DUK_MS_FLAG_NO_STRINGTABLE_RESIZE    (1 << 1)   /* don't resize stringtable (but may sweep it); needed during stringtable resize */
-#define DUK_MS_FLAG_NO_FINALIZERS            (1 << 2)   /* don't run finalizers (which may have arbitrary side effects) */
-#define DUK_MS_FLAG_NO_OBJECT_COMPACTION     (1 << 3)   /* don't compact objects; needed during object property allocation resize */
+#define DUK_MS_FLAG_NO_OBJECT_COMPACTION     (1 << 2)   /* don't compact objects; needed during object property allocation resize */
+#define DUK_MS_FLAG_NO_FINALIZERS            (1 << 3)   /* don't run finalizers; leave finalizable objects in finalize_list for next round */
+#define DUK_MS_FLAG_SKIP_FINALIZERS          (1 << 4)   /* don't run finalizers; queue finalizable objects back to heap_allocated */
 
 /*
  *  Thread switching
@@ -6925,7 +9845,7 @@ void duk_hbuffer_append_slice(duk_hthread *thr, duk_hbuffer_dynamic *buf, duk_si
  *  happens e.g. in call handling.
  */
 
-#ifdef DUK_USE_INTERRUPT_COUNTER
+#if defined(DUK_USE_INTERRUPT_COUNTER)
 #define DUK_HEAP_SWITCH_THREAD(heap,newthr)  duk_heap_switch_thread((heap), (newthr))
 #else
 #define DUK_HEAP_SWITCH_THREAD(heap,newthr)  do { \
@@ -6937,31 +9857,6 @@ void duk_hbuffer_append_slice(duk_hthread *thr, duk_hbuffer_dynamic *buf, duk_si
  *  Other heap related defines
  */
 
-/* Maximum duk_handle_call / duk_handle_safe_call depth.  Note that this
- * does not limit bytecode executor internal call depth at all (e.g.
- * for Ecmascript-to-Ecmascript calls, thread yields/resumes, etc).
- * There is a separate callstack depth limit for threads.
- */
-
-#if defined(DUK_USE_DEEP_C_STACK)
-#define DUK_HEAP_DEFAULT_CALL_RECURSION_LIMIT             1000  /* assuming 0.5 kB between calls, about 500kB of stack */ 
-#else
-#define DUK_HEAP_DEFAULT_CALL_RECURSION_LIMIT             60    /* assuming 0.5 kB between calls, about 30kB of stack */ 
-#endif
-
-/* Mark-and-sweep C recursion depth for marking phase; if reached,
- * mark object as a TEMPROOT and use multi-pass marking.
- */
-#if defined(DUK_USE_MARK_AND_SWEEP)
-#if defined(DUK_USE_GC_TORTURE)
-#define DUK_HEAP_MARK_AND_SWEEP_RECURSION_LIMIT   3
-#elif defined(DUK_USE_DEEP_C_STACK)
-#define DUK_HEAP_MARK_AND_SWEEP_RECURSION_LIMIT   256
-#else
-#define DUK_HEAP_MARK_AND_SWEEP_RECURSION_LIMIT   32
-#endif
-#endif
-
 /* Mark-and-sweep interval is relative to combined count of objects and
  * strings kept in the heap during the latest mark-and-sweep pass.
  * Fixed point .8 multiplier and .0 adder.  Trigger count (interval) is
@@ -6993,14 +9888,6 @@ void duk_hbuffer_append_slice(duk_hthread *thr, duk_hbuffer_dynamic *buf, duk_si
 /* helper to insert a (non-string) heap object into heap allocated list */
 #define DUK_HEAP_INSERT_INTO_HEAP_ALLOCATED(heap,hdr)     duk_heap_insert_into_heap_allocated((heap),(hdr))
 
-/* Executor interrupt default interval when nothing else requires a
- * smaller value.  The default interval must be small enough to allow
- * for reasonable execution timeout checking.
- */
-#ifdef DUK_USE_INTERRUPT_COUNTER
-#define DUK_HEAP_INTCTR_DEFAULT                           (256L * 1024L)
-#endif
-
 /*
  *  Stringtable
  */
@@ -7019,29 +9906,38 @@ void duk_hbuffer_append_slice(duk_hthread *thr, duk_hbuffer_dynamic *buf, duk_si
 #define DUK_STRTAB_U32_MAX_STRLEN          10               /* 4'294'967'295 */
 #define DUK_STRTAB_HIGHEST_32BIT_PRIME     0xfffffffbUL
 
-/* probe sequence */
+/* probe sequence (open addressing) */
 #define DUK_STRTAB_HASH_INITIAL(hash,h_size)    ((hash) % (h_size))
 #define DUK_STRTAB_HASH_PROBE_STEP(hash)        DUK_UTIL_GET_HASH_PROBE_STEP((hash))
 
+/* fixed top level hashtable size (separate chaining) */
+#define DUK_STRTAB_CHAIN_SIZE              DUK_USE_STRTAB_CHAIN_SIZE
+
 /*
  *  Built-in strings
  */
 
 /* heap string indices are autogenerated in duk_strings.h */
-#define DUK_HEAP_GET_STRING(heap,idx)  ((heap)->strs[(idx)])
+#if defined(DUK_USE_HEAPPTR16)
+#define DUK_HEAP_GET_STRING(heap,idx) \
+	((duk_hstring *) DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, (heap)->strs16[(idx)]))
+#else
+#define DUK_HEAP_GET_STRING(heap,idx) \
+	((heap)->strs[(idx)])
+#endif
 
 /*
  *  Raw memory calls: relative to heap, but no GC interaction
  */
 
 #define DUK_ALLOC_RAW(heap,size) \
-	((heap)->alloc_func((heap)->alloc_udata, (size)))
+	((heap)->alloc_func((heap)->heap_udata, (size)))
 
 #define DUK_REALLOC_RAW(heap,ptr,newsize) \
-	((heap)->realloc_func((heap)->alloc_udata, (ptr), (newsize)))
+	((heap)->realloc_func((heap)->heap_udata, (void *) (ptr), (newsize)))
 
 #define DUK_FREE_RAW(heap,ptr) \
-	((heap)->free_func((heap)->alloc_udata, (ptr)))
+	((heap)->free_func((heap)->heap_udata, (void *) (ptr)))
 
 /*
  *  Memory calls: relative to heap, GC interaction, but no error throwing.
@@ -7055,9 +9951,9 @@ void duk_hbuffer_append_slice(duk_hthread *thr, duk_hbuffer_dynamic *buf, duk_si
  *
  *    - DUK_FREE() is required to ignore NULL and any other possible return
  *      value of a zero-sized alloc/realloc (same as ANSI C free()).
- * 
- *    - There is no DUK_REALLOC_ZEROED (and checked variant) because we don't
- *      assume to know the old size.  Caller must zero the reallocated memory.
+ *
+ *    - There is no DUK_REALLOC_ZEROED because we don't assume to know the
+ *      old size.  Caller must zero the reallocated memory.
  *
  *    - DUK_REALLOC_INDIRECT() must be used when a mark-and-sweep triggered
  *      by an allocation failure might invalidate the original 'ptr', thus
@@ -7072,7 +9968,7 @@ void duk_hbuffer_append_slice(duk_hthread *thr, duk_hbuffer_dynamic *buf, duk_si
  */
 
 /* callback for indirect reallocs, request for current pointer */
-typedef void *(*duk_mem_getptr)(void *ud);
+typedef void *(*duk_mem_getptr)(duk_heap *heap, void *ud);
 
 #define DUK_ALLOC(heap,size)                            duk_heap_mem_alloc((heap), (size))
 #define DUK_ALLOC_ZEROED(heap,size)                     duk_heap_mem_alloc_zeroed((heap), (size))
@@ -7081,26 +9977,6 @@ typedef void *(*duk_mem_getptr)(void *ud);
 #define DUK_FREE(heap,ptr)                              duk_heap_mem_free((heap), (ptr))
 
 /*
- *  Memory calls: relative to a thread, GC interaction, throw error on alloc failure
- */
-
-/* XXX: add __func__; use DUK_FUNC_MACRO because __func__ is not always available */
-
-#ifdef DUK_USE_VERBOSE_ERRORS
-#define DUK_ALLOC_CHECKED(thr,size)                     duk_heap_mem_alloc_checked((thr), (size), DUK_FILE_MACRO, DUK_LINE_MACRO)
-#define DUK_ALLOC_CHECKED_ZEROED(thr,size)              duk_heap_mem_alloc_checked_zeroed((thr), (size), DUK_FILE_MACRO, DUK_LINE_MACRO)
-#define DUK_REALLOC_CHECKED(thr,ptr,newsize)            duk_heap_mem_realloc_checked((thr), (ptr), (newsize), DUK_FILE_MACRO, DUK_LINE_MACRO)
-#define DUK_REALLOC_INDIRECT_CHECKED(thr,cb,ud,newsize) duk_heap_mem_realloc_indirect_checked((thr), (cb), (ud), (newsize), DUK_FILE_MACRO, DUK_LINE_MACRO)
-#define DUK_FREE_CHECKED(thr,ptr)                       duk_heap_mem_free((thr)->heap, (ptr))  /* must not fail */
-#else
-#define DUK_ALLOC_CHECKED(thr,size)                     duk_heap_mem_alloc_checked((thr), (size))
-#define DUK_ALLOC_CHECKED_ZEROED(thr,size)              duk_heap_mem_alloc_checked_zeroed((thr), (size))
-#define DUK_REALLOC_CHECKED(thr,ptr,newsize)            duk_heap_mem_realloc_checked((thr), (ptr), (newsize))
-#define DUK_REALLOC_INDIRECT_CHECKED(thr,cb,ud,newsize) duk_heap_mem_realloc_indirect_checked((thr), (cb), (ud), (newsize))
-#define DUK_FREE_CHECKED(thr,ptr)                       duk_heap_mem_free((thr)->heap, (ptr))  /* must not fail */
-#endif
-
-/*
  *  Memory constants
  */
 
@@ -7116,6 +9992,56 @@ typedef void *(*duk_mem_getptr)(void *ud);
                                                               */
 
 /*
+ *  Debugger support
+ */
+
+/* Maximum number of breakpoints.  Only breakpoints that are set are
+ * consulted so increasing this has no performance impact.
+ */
+#define DUK_HEAP_MAX_BREAKPOINTS          16
+
+/* Opcode interval for a Date-based status/peek rate limit check.  Only
+ * relevant when debugger is attached.  Requesting a timestamp may be a
+ * slow operation on some platforms so this shouldn't be too low.  On the
+ * other hand a high value makes Duktape react to a pause request slowly.
+ */
+#define DUK_HEAP_DBG_RATELIMIT_OPCODES    4000
+
+/* Milliseconds between status notify and transport peeks. */
+#define DUK_HEAP_DBG_RATELIMIT_MILLISECS  200
+
+/* Step types */
+#define DUK_STEP_TYPE_NONE  0
+#define DUK_STEP_TYPE_INTO  1
+#define DUK_STEP_TYPE_OVER  2
+#define DUK_STEP_TYPE_OUT   3
+
+struct duk_breakpoint {
+	duk_hstring *filename;
+	duk_uint32_t line;
+};
+
+#if defined(DUK_USE_DEBUGGER_SUPPORT)
+#define DUK_HEAP_IS_DEBUGGER_ATTACHED(heap) ((heap)->dbg_read_cb != NULL)
+#define DUK_HEAP_CLEAR_STEP_STATE(heap) do { \
+		(heap)->dbg_step_type = DUK_STEP_TYPE_NONE; \
+		(heap)->dbg_step_thread = NULL; \
+		(heap)->dbg_step_csindex = 0; \
+		(heap)->dbg_step_startline = 0; \
+	} while (0)
+#define DUK_HEAP_SET_PAUSED(heap) do { \
+		(heap)->dbg_paused = 1; \
+		(heap)->dbg_state_dirty = 1; \
+		DUK_HEAP_CLEAR_STEP_STATE((heap)); \
+	} while (0)
+#define DUK_HEAP_CLEAR_PAUSED(heap) do { \
+		(heap)->dbg_paused = 0; \
+		(heap)->dbg_state_dirty = 1; \
+		DUK_HEAP_CLEAR_STEP_STATE((heap)); \
+	} while (0)
+#endif  /* DUK_USE_DEBUGGER_SUPPORT */
+
+/*
  *  String cache should ideally be at duk_hthread level, but that would
  *  cause string finalization to slow down relative to the number of
  *  threads; string finalization must check the string cache for "weak"
@@ -7136,7 +10062,9 @@ struct duk_strcache {
  */
 
 struct duk_ljstate {
+#if !defined(DUK_USE_CPP_EXCEPTIONS)
 	duk_jmpbuf *jmpbuf_ptr;   /* current setjmp() catchpoint */
+#endif
 	duk_small_uint_t type;    /* longjmp type */
 	duk_bool_t iserror;       /* isError flag for yield */
 	duk_tval value1;          /* 1st related value (type specific) */
@@ -7144,17 +10072,50 @@ struct duk_ljstate {
 };
 
 /*
+ *  Stringtable entry for fixed size stringtable
+ */
+
+struct duk_strtab_entry {
+#if defined(DUK_USE_HEAPPTR16)
+	/* A 16-bit listlen makes sense with 16-bit heap pointers: there
+	 * won't be space for 64k strings anyway.
+	 */
+	duk_uint16_t listlen;  /* if 0, 'str16' used, if > 0, 'strlist16' used */
+	union {
+		duk_uint16_t strlist16;
+		duk_uint16_t str16;
+	} u;
+#else
+	duk_size_t listlen;  /* if 0, 'str' used, if > 0, 'strlist' used */
+	union {
+		duk_hstring **strlist;
+		duk_hstring *str;
+	} u;
+#endif
+};
+
+/*
  *  Main heap structure
  */
 
 struct duk_heap {
 	duk_small_uint_t flags;
 
-	/* allocator functions */
+	/* Allocator functions. */
 	duk_alloc_function alloc_func;
 	duk_realloc_function realloc_func;
 	duk_free_function free_func;
-	void *alloc_udata;
+
+	/* Heap udata, used for allocator functions but also for other heap
+	 * level callbacks like pointer compression, etc.
+	 */
+	void *heap_udata;
+
+	/* Precomputed pointers when using 16-bit heap pointer packing. */
+#if defined(DUK_USE_HEAPPTR16)
+	duk_uint16_t heapptr_null16;
+	duk_uint16_t heapptr_deleted16;
+#endif
 
 	/* Fatal error handling, called e.g. when a longjmp() is needed but
 	 * lj.jmpbuf_ptr is NULL.  fatal_func must never return; it's not
@@ -7170,14 +10131,14 @@ struct duk_heap {
 	 * "finalized"; avoids recursive C calls when refcounts go to zero in a
 	 * chain of objects.
 	 */
-#ifdef DUK_USE_REFERENCE_COUNTING
+#if defined(DUK_USE_REFERENCE_COUNTING)
 	duk_heaphdr *refzero_list;
 	duk_heaphdr *refzero_list_tail;
 #endif
 
-#ifdef DUK_USE_MARK_AND_SWEEP
+#if defined(DUK_USE_MARK_AND_SWEEP)
 	/* mark-and-sweep control */
-#ifdef DUK_USE_VOLUNTARY_GC
+#if defined(DUK_USE_VOLUNTARY_GC)
 	duk_int_t mark_and_sweep_trigger_counter;
 #endif
 	duk_int_t mark_and_sweep_recursion_depth;
@@ -7199,14 +10160,11 @@ struct duk_heap {
 	duk_hthread *heap_thread;
 
 	/* current thread */
-	duk_hthread *curr_thread;	/* currently running thread */
+	duk_hthread *curr_thread;  /* currently running thread */
 
 	/* heap level "stash" object (e.g., various reachability roots) */
 	duk_hobject *heap_object;
 
-	/* heap level temporary log formatting buffer */
-	duk_hbuffer_dynamic *log_buffer;
-
 	/* duk_handle_call / duk_handle_safe_call recursion depth limiting */
 	duk_int_t call_recursion_depth;
 	duk_int_t call_recursion_limit;
@@ -7217,16 +10175,69 @@ struct duk_heap {
 	/* rnd_state for duk_util_tinyrandom.c */
 	duk_uint32_t rnd_state;
 
-	/* interrupt counter */
-#ifdef DUK_USE_INTERRUPT_COUNTER
-	duk_int_t interrupt_init;     /* start value for current countdown */
-	duk_int_t interrupt_counter;  /* countdown state (mirrored in current thread state) */
+	/* For manual debugging: instruction count based on executor and
+	 * interrupt counter book-keeping.  Inspect debug logs to see how
+	 * they match up.
+	 */
+#if defined(DUK_USE_INTERRUPT_COUNTER) && defined(DUK_USE_DEBUG)
+	duk_int_t inst_count_exec;
+	duk_int_t inst_count_interrupt;
+#endif
+
+	/* debugger */
+
+#if defined(DUK_USE_DEBUGGER_SUPPORT)
+	/* callbacks and udata; dbg_read_cb != NULL is used to indicate attached state */
+	duk_debug_read_function dbg_read_cb;                /* required, NULL implies detached */
+	duk_debug_write_function dbg_write_cb;              /* required */
+	duk_debug_peek_function dbg_peek_cb;
+	duk_debug_read_flush_function dbg_read_flush_cb;
+	duk_debug_write_flush_function dbg_write_flush_cb;
+	duk_debug_detached_function dbg_detached_cb;
+	void *dbg_udata;
+
+	/* debugger state, only relevant when attached */
+	duk_bool_t dbg_processing;              /* currently processing messages or breakpoints: don't enter message processing recursively (e.g. no breakpoints when processing debugger eval) */
+	duk_bool_t dbg_paused;                  /* currently paused: talk with debug client until step/resume */
+	duk_bool_t dbg_state_dirty;             /* resend state next time executor is about to run */
+	duk_bool_t dbg_force_restart;           /* force executor restart to recheck breakpoints; used to handle function returns (see GH-303) */
+	duk_bool_t dbg_detaching;               /* debugger detaching; used to avoid calling detach handler recursively */
+	duk_small_uint_t dbg_step_type;         /* step type: none, step into, step over, step out */
+	duk_hthread *dbg_step_thread;           /* borrowed; NULL if no step state (NULLed in unwind) */
+	duk_size_t dbg_step_csindex;            /* callstack index */
+	duk_uint32_t dbg_step_startline;        /* starting line number */
+	duk_breakpoint dbg_breakpoints[DUK_HEAP_MAX_BREAKPOINTS];  /* breakpoints: [0,breakpoint_count[ gc reachable */
+	duk_small_uint_t dbg_breakpoint_count;
+	duk_breakpoint *dbg_breakpoints_active[DUK_HEAP_MAX_BREAKPOINTS + 1];  /* currently active breakpoints: NULL term, borrowed pointers */
+	/* XXX: make active breakpoints actual copies instead of pointers? */
+
+	/* These are for rate limiting Status notifications and transport peeking. */
+	duk_uint32_t dbg_exec_counter;          /* cumulative opcode execution count (overflows are OK) */
+	duk_uint32_t dbg_last_counter;          /* value of dbg_exec_counter when we last did a Date-based check */
+	duk_double_t dbg_last_time;             /* time when status/peek was last done (Date-based rate limit) */
+
+	/* Used to support single-byte stream lookahead. */
+	duk_bool_t dbg_have_next_byte;
+	duk_uint8_t dbg_next_byte;
 #endif
 
 	/* string intern table (weak refs) */
-	duk_hstring **st;
+#if defined(DUK_USE_STRTAB_PROBE)
+#if defined(DUK_USE_HEAPPTR16)
+	duk_uint16_t *strtable16;
+#else
+	duk_hstring **strtable;
+#endif
 	duk_uint32_t st_size;     /* alloc size in elements */
 	duk_uint32_t st_used;     /* used elements (includes DELETED) */
+#endif
+
+	/* XXX: static alloc is OK until separate chaining stringtable
+	 * resizing is implemented.
+	 */
+#if defined(DUK_USE_STRTAB_CHAIN)
+	duk_strtab_entry strtable[DUK_STRTAB_CHAIN_SIZE];
+#endif
 
 	/* string access cache (codepoint offset -> byte offset) for fast string
 	 * character looping; 'weak' reference which needs special handling in GC.
@@ -7234,84 +10245,209 @@ struct duk_heap {
 	duk_strcache strcache[DUK_HEAP_STRCACHE_SIZE];
 
 	/* built-in strings */
+#if defined(DUK_USE_HEAPPTR16)
+	duk_uint16_t strs16[DUK_HEAP_NUM_STRINGS];
+#else
 	duk_hstring *strs[DUK_HEAP_NUM_STRINGS];
+#endif
 };
 
 /*
  *  Prototypes
  */
 
+DUK_INTERNAL_DECL
 duk_heap *duk_heap_alloc(duk_alloc_function alloc_func,
                          duk_realloc_function realloc_func,
                          duk_free_function free_func,
-                         void *alloc_udata,
+                         void *heap_udata,
                          duk_fatal_function fatal_func);
-void duk_heap_free(duk_heap *heap);
-void duk_heap_free_heaphdr_raw(duk_heap *heap, duk_heaphdr *hdr);
+DUK_INTERNAL_DECL void duk_heap_free(duk_heap *heap);
+DUK_INTERNAL_DECL void duk_free_hobject_inner(duk_heap *heap, duk_hobject *h);
+DUK_INTERNAL_DECL void duk_free_hbuffer_inner(duk_heap *heap, duk_hbuffer *h);
+DUK_INTERNAL_DECL void duk_free_hstring_inner(duk_heap *heap, duk_hstring *h);
+DUK_INTERNAL_DECL void duk_heap_free_heaphdr_raw(duk_heap *heap, duk_heaphdr *hdr);
 
-void duk_heap_insert_into_heap_allocated(duk_heap *heap, duk_heaphdr *hdr);
+DUK_INTERNAL_DECL void duk_heap_insert_into_heap_allocated(duk_heap *heap, duk_heaphdr *hdr);
 #if defined(DUK_USE_DOUBLE_LINKED_HEAP) && defined(DUK_USE_REFERENCE_COUNTING)
-void duk_heap_remove_any_from_heap_allocated(duk_heap *heap, duk_heaphdr *hdr);
+DUK_INTERNAL_DECL void duk_heap_remove_any_from_heap_allocated(duk_heap *heap, duk_heaphdr *hdr);
 #endif
-#ifdef DUK_USE_INTERRUPT_COUNTER
-void duk_heap_switch_thread(duk_heap *heap, duk_hthread *new_thr);
+#if defined(DUK_USE_INTERRUPT_COUNTER)
+DUK_INTERNAL_DECL void duk_heap_switch_thread(duk_heap *heap, duk_hthread *new_thr);
 #endif
 
-duk_hstring *duk_heap_string_lookup(duk_heap *heap, duk_uint8_t *str, duk_uint32_t blen);
-duk_hstring *duk_heap_string_intern(duk_heap *heap, duk_uint8_t *str, duk_uint32_t blen);
-duk_hstring *duk_heap_string_intern_checked(duk_hthread *thr, duk_uint8_t *str, duk_uint32_t len);
-duk_hstring *duk_heap_string_lookup_u32(duk_heap *heap, duk_uint32_t val);
-duk_hstring *duk_heap_string_intern_u32(duk_heap *heap, duk_uint32_t val);
-duk_hstring *duk_heap_string_intern_u32_checked(duk_hthread *thr, duk_uint32_t val);
-void duk_heap_string_remove(duk_heap *heap, duk_hstring *h);
+#if 0  /*unused*/
+DUK_INTERNAL_DECL duk_hstring *duk_heap_string_lookup(duk_heap *heap, const duk_uint8_t *str, duk_uint32_t blen);
+#endif
+DUK_INTERNAL_DECL duk_hstring *duk_heap_string_intern(duk_heap *heap, const duk_uint8_t *str, duk_uint32_t blen);
+DUK_INTERNAL_DECL duk_hstring *duk_heap_string_intern_checked(duk_hthread *thr, const duk_uint8_t *str, duk_uint32_t len);
+#if 0  /*unused*/
+DUK_INTERNAL_DECL duk_hstring *duk_heap_string_lookup_u32(duk_heap *heap, duk_uint32_t val);
+#endif
+DUK_INTERNAL_DECL duk_hstring *duk_heap_string_intern_u32(duk_heap *heap, duk_uint32_t val);
+DUK_INTERNAL_DECL duk_hstring *duk_heap_string_intern_u32_checked(duk_hthread *thr, duk_uint32_t val);
+#if defined(DUK_USE_REFERENCE_COUNTING)
+DUK_INTERNAL_DECL void duk_heap_string_remove(duk_heap *heap, duk_hstring *h);
+#endif
 #if defined(DUK_USE_MARK_AND_SWEEP) && defined(DUK_USE_MS_STRINGTABLE_RESIZE)
-void duk_heap_force_stringtable_resize(duk_heap *heap);
+DUK_INTERNAL_DECL void duk_heap_force_strtab_resize(duk_heap *heap);
 #endif
-
-void duk_heap_strcache_string_remove(duk_heap *heap, duk_hstring *h);
-duk_uint_fast32_t duk_heap_strcache_offset_char2byte(duk_hthread *thr, duk_hstring *h, duk_uint_fast32_t char_offset);
-
-#ifdef DUK_USE_PROVIDE_DEFAULT_ALLOC_FUNCTIONS
-void *duk_default_alloc_function(void *udata, duk_size_t size);
-void *duk_default_realloc_function(void *udata, void *ptr, duk_size_t newsize);
-void duk_default_free_function(void *udata, void *ptr);
+DUK_INTERNAL void duk_heap_free_strtab(duk_heap *heap);
+#if defined(DUK_USE_DEBUG)
+DUK_INTERNAL void duk_heap_dump_strtab(duk_heap *heap);
 #endif
 
-void *duk_heap_mem_alloc(duk_heap *heap, duk_size_t size);
-void *duk_heap_mem_alloc_zeroed(duk_heap *heap, duk_size_t size);
-void *duk_heap_mem_realloc(duk_heap *heap, void *ptr, duk_size_t newsize);
-void *duk_heap_mem_realloc_indirect(duk_heap *heap, duk_mem_getptr cb, void *ud, duk_size_t newsize);
-void duk_heap_mem_free(duk_heap *heap, void *ptr);
 
-#ifdef DUK_USE_VERBOSE_ERRORS
-void *duk_heap_mem_alloc_checked(duk_hthread *thr, duk_size_t size, const char *filename, duk_int_t line);
-void *duk_heap_mem_alloc_checked_zeroed(duk_hthread *thr, duk_size_t size, const char *filename, duk_int_t line);
-void *duk_heap_mem_realloc_checked(duk_hthread *thr, void *ptr, duk_size_t newsize, const char *filename, duk_int_t line);
-void *duk_heap_mem_realloc_indirect_checked(duk_hthread *thr, duk_mem_getptr cb, void *ud, duk_size_t newsize, const char *filename, duk_int_t line);
-#else
-void *duk_heap_mem_alloc_checked(duk_hthread *thr, duk_size_t size);
-void *duk_heap_mem_alloc_checked_zeroed(duk_hthread *thr, duk_size_t size);
-void *duk_heap_mem_realloc_checked(duk_hthread *thr, void *ptr, duk_size_t newsize);
-void *duk_heap_mem_realloc_indirect_checked(duk_hthread *thr, duk_mem_getptr cb, void *ud, duk_size_t newsize);
+DUK_INTERNAL_DECL void duk_heap_strcache_string_remove(duk_heap *heap, duk_hstring *h);
+DUK_INTERNAL_DECL duk_uint_fast32_t duk_heap_strcache_offset_char2byte(duk_hthread *thr, duk_hstring *h, duk_uint_fast32_t char_offset);
+
+#if defined(DUK_USE_PROVIDE_DEFAULT_ALLOC_FUNCTIONS)
+DUK_INTERNAL_DECL void *duk_default_alloc_function(void *udata, duk_size_t size);
+DUK_INTERNAL_DECL void *duk_default_realloc_function(void *udata, void *ptr, duk_size_t newsize);
+DUK_INTERNAL_DECL void duk_default_free_function(void *udata, void *ptr);
 #endif
 
+DUK_INTERNAL_DECL void *duk_heap_mem_alloc(duk_heap *heap, duk_size_t size);
+DUK_INTERNAL_DECL void *duk_heap_mem_alloc_zeroed(duk_heap *heap, duk_size_t size);
+DUK_INTERNAL_DECL void *duk_heap_mem_realloc(duk_heap *heap, void *ptr, duk_size_t newsize);
+DUK_INTERNAL_DECL void *duk_heap_mem_realloc_indirect(duk_heap *heap, duk_mem_getptr cb, void *ud, duk_size_t newsize);
+DUK_INTERNAL_DECL void duk_heap_mem_free(duk_heap *heap, void *ptr);
+
 #ifdef DUK_USE_REFERENCE_COUNTING
-void duk_heap_tval_incref(duk_tval *tv);
-void duk_heap_tval_decref(duk_hthread *thr, duk_tval *tv);
-void duk_heap_heaphdr_incref(duk_heaphdr *h);
-void duk_heap_heaphdr_decref(duk_hthread *thr, duk_heaphdr *h);
-void duk_heap_refcount_finalize_heaphdr(duk_hthread *thr, duk_heaphdr *hdr);
+#if !defined(DUK_USE_FAST_REFCOUNT_DEFAULT)
+DUK_INTERNAL_DECL void duk_tval_incref(duk_tval *tv);
+#endif
+#if 0  /* unused */
+DUK_INTERNAL_DECL void duk_tval_incref_allownull(duk_tval *tv);
+#endif
+DUK_INTERNAL_DECL void duk_tval_decref(duk_hthread *thr, duk_tval *tv);
+#if 0  /* unused */
+DUK_INTERNAL_DECL void duk_tval_decref_allownull(duk_hthread *thr, duk_tval *tv);
+#endif
+#if !defined(DUK_USE_FAST_REFCOUNT_DEFAULT)
+DUK_INTERNAL_DECL void duk_heaphdr_incref(duk_heaphdr *h);
+#endif
+#if 0  /* unused */
+DUK_INTERNAL_DECL void duk_heaphdr_incref_allownull(duk_heaphdr *h);
+#endif
+DUK_INTERNAL_DECL void duk_heaphdr_decref(duk_hthread *thr, duk_heaphdr *h);
+DUK_INTERNAL_DECL void duk_heaphdr_decref_allownull(duk_hthread *thr, duk_heaphdr *h);
+DUK_INTERNAL_DECL void duk_heaphdr_refzero(duk_hthread *thr, duk_heaphdr *h);
+DUK_INTERNAL_DECL void duk_heaphdr_refcount_finalize(duk_hthread *thr, duk_heaphdr *hdr);
 #else
 /* no refcounting */
 #endif
 
-#ifdef DUK_USE_MARK_AND_SWEEP
-duk_bool_t duk_heap_mark_and_sweep(duk_heap *heap, duk_small_uint_t flags);
+#if defined(DUK_USE_MARK_AND_SWEEP)
+DUK_INTERNAL_DECL duk_bool_t duk_heap_mark_and_sweep(duk_heap *heap, duk_small_uint_t flags);
 #endif
 
-duk_uint32_t duk_heap_hashstring(duk_heap *heap, duk_uint8_t *str, duk_size_t len);
+DUK_INTERNAL_DECL duk_uint32_t duk_heap_hashstring(duk_heap *heap, const duk_uint8_t *str, duk_size_t len);
 
 #endif  /* DUK_HEAP_H_INCLUDED */
+#line 1 "duk_debugger.h"
+#ifndef DUK_DEBUGGER_H_INCLUDED
+#define DUK_DEBUGGER_H_INCLUDED
+
+/* Debugger protocol version is defined in the public API header. */
+
+#define DUK_DBG_MARKER_EOM        0x00
+#define DUK_DBG_MARKER_REQUEST    0x01
+#define DUK_DBG_MARKER_REPLY      0x02
+#define DUK_DBG_MARKER_ERROR      0x03
+#define DUK_DBG_MARKER_NOTIFY     0x04
+
+#define DUK_DBG_ERR_UNKNOWN       0x00
+#define DUK_DBG_ERR_UNSUPPORTED   0x01
+#define DUK_DBG_ERR_TOOMANY       0x02
+#define DUK_DBG_ERR_NOTFOUND      0x03
+
+/* Initiated by Duktape */
+#define DUK_DBG_CMD_STATUS        0x01
+#define DUK_DBG_CMD_PRINT         0x02
+#define DUK_DBG_CMD_ALERT         0x03
+#define DUK_DBG_CMD_LOG           0x04
+#define DUK_DBG_CMD_THROW         0x05
+#define DUK_DBG_CMD_DETACHING     0x06
+
+/* Initiated by debug client */
+#define DUK_DBG_CMD_BASICINFO     0x10
+#define DUK_DBG_CMD_TRIGGERSTATUS 0x11
+#define DUK_DBG_CMD_PAUSE         0x12
+#define DUK_DBG_CMD_RESUME        0x13
+#define DUK_DBG_CMD_STEPINTO      0x14
+#define DUK_DBG_CMD_STEPOVER      0x15
+#define DUK_DBG_CMD_STEPOUT       0x16
+#define DUK_DBG_CMD_LISTBREAK     0x17
+#define DUK_DBG_CMD_ADDBREAK      0x18
+#define DUK_DBG_CMD_DELBREAK      0x19
+#define DUK_DBG_CMD_GETVAR        0x1a
+#define DUK_DBG_CMD_PUTVAR        0x1b
+#define DUK_DBG_CMD_GETCALLSTACK  0x1c
+#define DUK_DBG_CMD_GETLOCALS     0x1d
+#define DUK_DBG_CMD_EVAL          0x1e
+#define DUK_DBG_CMD_DETACH        0x1f
+#define DUK_DBG_CMD_DUMPHEAP      0x20
+#define DUK_DBG_CMD_GETBYTECODE   0x21
+
+#if defined(DUK_USE_DEBUGGER_SUPPORT)
+DUK_INTERNAL_DECL void duk_debug_do_detach(duk_heap *heap);
+
+DUK_INTERNAL_DECL duk_bool_t duk_debug_read_peek(duk_hthread *thr);
+DUK_INTERNAL_DECL void duk_debug_write_flush(duk_hthread *thr);
+
+DUK_INTERNAL_DECL void duk_debug_skip_bytes(duk_hthread *thr, duk_size_t length);
+DUK_INTERNAL_DECL void duk_debug_skip_byte(duk_hthread *thr);
+
+DUK_INTERNAL_DECL void duk_debug_read_bytes(duk_hthread *thr, duk_uint8_t *data, duk_size_t length);
+DUK_INTERNAL_DECL duk_uint8_t duk_debug_read_byte(duk_hthread *thr);
+DUK_INTERNAL_DECL duk_int32_t duk_debug_read_int(duk_hthread *thr);
+DUK_INTERNAL_DECL duk_hstring *duk_debug_read_hstring(duk_hthread *thr);
+/* XXX: exposed duk_debug_read_pointer */
+/* XXX: exposed duk_debug_read_buffer */
+/* XXX: exposed duk_debug_read_hbuffer */
+DUK_INTERNAL_DECL void duk_debug_read_tval(duk_hthread *thr);
+
+DUK_INTERNAL_DECL void duk_debug_write_bytes(duk_hthread *thr, const duk_uint8_t *data, duk_size_t length);
+DUK_INTERNAL_DECL void duk_debug_write_byte(duk_hthread *thr, duk_uint8_t x);
+DUK_INTERNAL_DECL void duk_debug_write_unused(duk_hthread *thr);
+DUK_INTERNAL_DECL void duk_debug_write_undefined(duk_hthread *thr);
+DUK_INTERNAL_DECL void duk_debug_write_int(duk_hthread *thr, duk_int32_t x);
+DUK_INTERNAL_DECL void duk_debug_write_uint(duk_hthread *thr, duk_uint32_t x);
+DUK_INTERNAL_DECL void duk_debug_write_string(duk_hthread *thr, const char *data, duk_size_t length);
+DUK_INTERNAL_DECL void duk_debug_write_cstring(duk_hthread *thr, const char *data);
+DUK_INTERNAL_DECL void duk_debug_write_hstring(duk_hthread *thr, duk_hstring *h);
+DUK_INTERNAL_DECL void duk_debug_write_buffer(duk_hthread *thr, const char *data, duk_size_t length);
+DUK_INTERNAL_DECL void duk_debug_write_hbuffer(duk_hthread *thr, duk_hbuffer *h);
+DUK_INTERNAL_DECL void duk_debug_write_pointer(duk_hthread *thr, void *ptr);
+#if defined(DUK_USE_DEBUGGER_DUMPHEAP)
+DUK_INTERNAL_DECL void duk_debug_write_heapptr(duk_hthread *thr, duk_heaphdr *h);
+#endif
+DUK_INTERNAL_DECL void duk_debug_write_hobject(duk_hthread *thr, duk_hobject *obj);
+DUK_INTERNAL_DECL void duk_debug_write_tval(duk_hthread *thr, duk_tval *tv);
+
+#if 0  /* unused */
+DUK_INTERNAL_DECL void duk_debug_write_request(duk_hthread *thr, duk_small_uint_t command);
+#endif
+DUK_INTERNAL_DECL void duk_debug_write_reply(duk_hthread *thr);
+DUK_INTERNAL_DECL void duk_debug_write_error_eom(duk_hthread *thr, duk_small_uint_t err_code, const char *msg);
+DUK_INTERNAL_DECL void duk_debug_write_notify(duk_hthread *thr, duk_small_uint_t command);
+DUK_INTERNAL_DECL void duk_debug_write_eom(duk_hthread *thr);
+
+DUK_INTERNAL_DECL duk_uint_fast32_t duk_debug_curr_line(duk_hthread *thr);
+DUK_INTERNAL_DECL void duk_debug_send_status(duk_hthread *thr);
+#if defined(DUK_USE_DEBUGGER_THROW_NOTIFY)
+DUK_INTERNAL_DECL void duk_debug_send_throw(duk_hthread *thr, duk_bool_t fatal);
+#endif
+
+DUK_INTERNAL_DECL void duk_debug_halt_execution(duk_hthread *thr, duk_bool_t use_prev_pc);
+DUK_INTERNAL_DECL duk_bool_t duk_debug_process_messages(duk_hthread *thr, duk_bool_t no_block);
+
+DUK_INTERNAL_DECL duk_small_int_t duk_debug_add_breakpoint(duk_hthread *thr, duk_hstring *filename, duk_uint32_t line);
+DUK_INTERNAL_DECL duk_bool_t duk_debug_remove_breakpoint(duk_hthread *thr, duk_small_uint_t breakpoint_index);
+#endif
+
+#endif  /* DUK_DEBUGGER_H_INCLUDED */
 #line 1 "duk_debug.h"
 /*
  *  Debugging macros, DUK_DPRINT() and its variants in particular.
@@ -7413,52 +10549,17 @@ duk_uint32_t duk_heap_hashstring(duk_heap *heap, duk_uint8_t *str, duk_size_t le
 #ifdef DUK_USE_DDPRINT
 #define DUK_DDPRINT  DUK__DEBUG_STASH(DUK_LEVEL_DDEBUG), (void) duk_debug_log  /* args go here in parens */
 #else
-#define DUK_DDPRINT  0 && 
+#define DUK_DDPRINT  0 && /* args */
 #endif
 
 #ifdef DUK_USE_DDDPRINT
 #define DUK_DDDPRINT  DUK__DEBUG_STASH(DUK_LEVEL_DDDEBUG), (void) duk_debug_log  /* args go here in parens */
 #else
-#define DUK_DDDPRINT  0 && 
+#define DUK_DDDPRINT  0 && /* args */
 #endif
 
 #endif  /* DUK_USE_VARIADIC_MACROS */
 
-/* object dumpers */
-
-#define DUK_DEBUG_DUMP_HEAP(x)               duk_debug_dump_heap((x))
-#define DUK_DEBUG_DUMP_HSTRING(x)            /* XXX: unimplemented */
-#define DUK_DEBUG_DUMP_HOBJECT(x)            duk_debug_dump_hobject((x))
-#define DUK_DEBUG_DUMP_HCOMPILEDFUNCTION(x)  /* XXX: unimplemented */
-#define DUK_DEBUG_DUMP_HNATIVEFUNCTION(x)    /* XXX: unimplemented */
-#define DUK_DEBUG_DUMP_HTHREAD(thr)          duk_debug_dump_hobject((duk_hobject *) (thr))
-#define DUK_DEBUG_DUMP_CALLSTACK(thr)        duk_debug_dump_callstack((thr))
-#define DUK_DEBUG_DUMP_ACTIVATION(thr,act)   duk_debug_dump_activation((thr),(act))
-
-/* summary macros */
-
-#define DUK_DEBUG_SUMMARY_INIT()  do { \
-		DUK_MEMZERO(duk_debug_summary_buf, sizeof(duk_debug_summary_buf)); \
-		duk_debug_summary_idx = 0; \
-	} while (0)
-
-#define DUK_DEBUG_SUMMARY_CHAR(ch)  do { \
-		duk_debug_summary_buf[duk_debug_summary_idx++] = (ch); \
-		if ((duk_size_t) duk_debug_summary_idx >= (duk_size_t) (sizeof(duk_debug_summary_buf) - 1)) { \
-			duk_debug_summary_buf[duk_debug_summary_idx++] = (char) 0; \
-			DUK_DPRINT("    %s", (const char *) duk_debug_summary_buf); \
-			DUK_DEBUG_SUMMARY_INIT(); \
-		} \
-	} while (0)
-
-#define DUK_DEBUG_SUMMARY_FINISH()  do { \
-		if (duk_debug_summary_idx > 0) { \
-			duk_debug_summary_buf[duk_debug_summary_idx++] = (char) 0; \
-			DUK_DPRINT("    %s", (const char *) duk_debug_summary_buf); \
-			DUK_DEBUG_SUMMARY_INIT(); \
-		} \
-	} while (0)
-
 #else  /* DUK_USE_DEBUG */
 
 /*
@@ -7478,22 +10579,11 @@ duk_uint32_t duk_heap_hashstring(duk_heap *heap, duk_uint8_t *str, duk_size_t le
 #else  /* DUK_USE_VARIADIC_MACROS */
 
 #define DUK_DPRINT    0 && /* args go here as a comma expression in parens */
-#define DUK_DDPRINT   0 && 
-#define DUK_DDDPRINT  0 && 
+#define DUK_DDPRINT   0 && /* args */
+#define DUK_DDDPRINT  0 && /* args */
 
 #endif  /* DUK_USE_VARIADIC_MACROS */
 
-#define DUK_DEBUG_DUMP_HEAP(x)
-#define DUK_DEBUG_DUMP_HSTRING(x)
-#define DUK_DEBUG_DUMP_HOBJECT(x)
-#define DUK_DEBUG_DUMP_HCOMPILEDFUNCTION(x)
-#define DUK_DEBUG_DUMP_HNATIVEFUNCTION(x)
-#define DUK_DEBUG_DUMP_HTHREAD(x)
-
-#define DUK_DEBUG_SUMMARY_INIT()
-#define DUK_DEBUG_SUMMARY_CHAR(ch)
-#define DUK_DEBUG_SUMMARY_FINISH()
-
 #endif  /* DUK_USE_DEBUG */
 
 /*
@@ -7514,38 +10604,32 @@ struct duk_fixedbuffer {
  */
 
 #ifdef DUK_USE_DEBUG
-duk_int_t duk_debug_vsnprintf(char *str, duk_size_t size, const char *format, va_list ap);
-duk_int_t duk_debug_snprintf(char *str, duk_size_t size, const char *format, ...);
-void duk_debug_format_funcptr(char *buf, duk_size_t buf_size, duk_uint8_t *fptr, duk_size_t fptr_size);
+DUK_INTERNAL_DECL duk_int_t duk_debug_vsnprintf(char *str, duk_size_t size, const char *format, va_list ap);
+#if 0  /*unused*/
+DUK_INTERNAL_DECL duk_int_t duk_debug_snprintf(char *str, duk_size_t size, const char *format, ...);
+#endif
+DUK_INTERNAL_DECL void duk_debug_format_funcptr(char *buf, duk_size_t buf_size, duk_uint8_t *fptr, duk_size_t fptr_size);
 
 #ifdef DUK_USE_VARIADIC_MACROS
-void duk_debug_log(duk_small_int_t level, const char *file, duk_int_t line, const char *func, char *fmt, ...);
+DUK_INTERNAL_DECL void duk_debug_log(duk_small_int_t level, const char *file, duk_int_t line, const char *func, const char *fmt, ...);
 #else  /* DUK_USE_VARIADIC_MACROS */
 /* parameter passing, not thread safe */
 #define DUK_DEBUG_STASH_SIZE  128
-extern char duk_debug_file_stash[DUK_DEBUG_STASH_SIZE];
-extern char duk_debug_line_stash[DUK_DEBUG_STASH_SIZE];
-extern char duk_debug_func_stash[DUK_DEBUG_STASH_SIZE];
-extern duk_small_int_t duk_debug_level_stash;
-extern void duk_debug_log(char *fmt, ...);
+#if !defined(DUK_SINGLE_FILE)
+DUK_INTERNAL_DECL char duk_debug_file_stash[DUK_DEBUG_STASH_SIZE];
+DUK_INTERNAL_DECL char duk_debug_line_stash[DUK_DEBUG_STASH_SIZE];
+DUK_INTERNAL_DECL char duk_debug_func_stash[DUK_DEBUG_STASH_SIZE];
+DUK_INTERNAL_DECL duk_small_int_t duk_debug_level_stash;
+#endif
+DUK_INTERNAL_DECL void duk_debug_log(const char *fmt, ...);
 #endif  /* DUK_USE_VARIADIC_MACROS */
 
-void duk_fb_put_bytes(duk_fixedbuffer *fb, duk_uint8_t *buffer, duk_size_t length);
-void duk_fb_put_byte(duk_fixedbuffer *fb, duk_uint8_t x);
-void duk_fb_put_cstring(duk_fixedbuffer *fb, const char *x);
-void duk_fb_sprintf(duk_fixedbuffer *fb, const char *fmt, ...);
-duk_bool_t duk_fb_is_full(duk_fixedbuffer *fb);
-
-void duk_debug_dump_heap(duk_heap *heap);
-void duk_debug_heap_graphviz(duk_heap *heap);
-void duk_debug_dump_hobject(duk_hobject *obj);
-void duk_debug_dump_hthread(duk_hthread *thr);
-void duk_debug_dump_callstack(duk_hthread *thr);
-void duk_debug_dump_activation(duk_hthread *thr, duk_activation *act);
-
-#define DUK_DEBUG_SUMMARY_BUF_SIZE  76
-extern char duk_debug_summary_buf[DUK_DEBUG_SUMMARY_BUF_SIZE];
-extern duk_int_t duk_debug_summary_idx;
+DUK_INTERNAL_DECL void duk_fb_put_bytes(duk_fixedbuffer *fb, const duk_uint8_t *buffer, duk_size_t length);
+DUK_INTERNAL_DECL void duk_fb_put_byte(duk_fixedbuffer *fb, duk_uint8_t x);
+DUK_INTERNAL_DECL void duk_fb_put_cstring(duk_fixedbuffer *fb, const char *x);
+DUK_INTERNAL_DECL void duk_fb_sprintf(duk_fixedbuffer *fb, const char *fmt, ...);
+DUK_INTERNAL_DECL void duk_fb_put_funcptr(duk_fixedbuffer *fb, duk_uint8_t *fptr, duk_size_t fptr_size);
+DUK_INTERNAL_DECL duk_bool_t duk_fb_is_full(duk_fixedbuffer *fb);
 
 #endif  /* DUK_USE_DEBUG */
 
@@ -7584,7 +10668,7 @@ extern duk_int_t duk_debug_summary_idx;
  *  Normal error is thrown with a longjmp() through the current setjmp()
  *  catchpoint record in the duk_heap.  The 'curr_thread' of the duk_heap
  *  identifies the throwing thread.
- * 
+ *
  *  Error formatting is not always necessary but there are no separate calls
  *  (to minimize code size).  Error object creation will consume a considerable
  *  amount of time, compared to which formatting is probably trivial.  Note
@@ -7598,9 +10682,9 @@ extern duk_int_t duk_debug_summary_idx;
  *  fall back to awkward hacks.
  */
 
-#ifdef DUK_USE_VERBOSE_ERRORS
+#if defined(DUK_USE_VERBOSE_ERRORS)
 
-#ifdef DUK_USE_VARIADIC_MACROS
+#if defined(DUK_USE_VARIADIC_MACROS)
 
 /* __VA_ARGS__ has comma issues for empty lists, so we mandate at least 1 argument for '...' (format string) */
 #define DUK_ERROR(thr,err,...)                    duk_err_handle_error(DUK_FILE_MACRO, (duk_int_t) DUK_LINE_MACRO, (thr), (err), __VA_ARGS__)
@@ -7613,16 +10697,16 @@ extern duk_int_t duk_debug_summary_idx;
  */
 
 #define DUK_ERROR  \
-	duk_err_file_stash = (const char *) DUK_FILE_MACRO, \
-	duk_err_line_stash = (duk_int_t) DUK_LINE_MACRO, \
-	(void) duk_err_handle_error_stash  /* arguments follow */
+	(void) (duk_err_file_stash = (const char *) DUK_FILE_MACRO, \
+	        duk_err_line_stash = (duk_int_t) DUK_LINE_MACRO, \
+	        duk_err_handle_error_stash)  /* arguments follow */
 #define DUK_ERROR_RAW                             duk_err_handle_error
 
 #endif  /* DUK_USE_VARIADIC_MACROS */
 
 #else  /* DUK_USE_VERBOSE_ERRORS */
 
-#ifdef DUK_USE_VARIADIC_MACROS
+#if defined(DUK_USE_VARIADIC_MACROS)
 
 #define DUK_ERROR(thr,err,...)                    duk_err_handle_error((thr), (err))
 #define DUK_ERROR_RAW(file,line,thr,err,...)      duk_err_handle_error((thr), (err))
@@ -7651,7 +10735,7 @@ extern duk_int_t duk_debug_summary_idx;
  *  Panic error
  *
  *  Panic errors are not relative to either a heap or a thread, and cause
- *  DUK_PANIC() macro to be invoked.  Unlesa a user provides DUK_OPT_PANIC_HANDLER,
+ *  DUK_PANIC() macro to be invoked.  Unless a user provides DUK_USE_PANIC_HANDLER,
  *  DUK_PANIC() calls a helper which prints out the error and causes a process
  *  exit.
  *
@@ -7674,7 +10758,7 @@ extern duk_int_t duk_debug_summary_idx;
  *  Assert macro: failure causes panic.
  */
 
-#ifdef DUK_USE_ASSERTIONS
+#if defined(DUK_USE_ASSERTIONS)
 
 /* the message should be a compile time constant without formatting (less risk);
  * we don't care about assertion text size because they're not used in production
@@ -7688,16 +10772,32 @@ extern duk_int_t duk_debug_summary_idx;
 	} \
 	} while (0)
 
+/* Assertion compatible inside a comma expression, evaluates to void.
+ * Currently not compatible with DUK_USE_PANIC_HANDLER() which may have
+ * a statement block.
+ */
+#if defined(DUK_USE_PANIC_HANDLER)
+/* XXX: resolve macro definition issue or call through a helper function? */
+#define DUK_ASSERT_EXPR(x)  ((void) 0)
+#else
+#define DUK_ASSERT_EXPR(x) \
+	((void) ((x) ? 0 : (DUK_PANIC(DUK_ERR_ASSERTION_ERROR, \
+				"assertion failed: " #x \
+				" (" DUK_FILE_MACRO ":" DUK_MACRO_STRINGIFY(DUK_LINE_MACRO) ")"), 0)))
+#endif
+
 #else  /* DUK_USE_ASSERTIONS */
 
-#define DUK_ASSERT(x)  do { /* assertion omitted */ } while(0)
+#define DUK_ASSERT(x)  do { /* assertion omitted */ } while (0)
+
+#define DUK_ASSERT_EXPR(x)  ((void) 0)
 
 #endif  /* DUK_USE_ASSERTIONS */
 
 /* this variant is used when an assert would generate a compile warning by
  * being always true (e.g. >= 0 comparison for an unsigned value
  */
-#define DUK_ASSERT_DISABLE(x)  do { /* assertion disabled */ } while(0)
+#define DUK_ASSERT_DISABLE(x)  do { /* assertion disabled */ } while (0)
 
 /*
  *  Assertion helpers
@@ -7721,9 +10821,9 @@ extern duk_int_t duk_debug_summary_idx;
 
 #if defined(DUK_USE_ASSERTIONS) && defined(DUK_USE_PACKED_TVAL)
 #define DUK_ASSERT_DOUBLE_IS_NORMALIZED(dval)  do { \
-		duk_double_union assert_tmp_du; \
-		assert_tmp_du.d = (dval); \
-		DUK_ASSERT(DUK_DBLUNION_IS_NORMALIZED(&assert_tmp_du)); \
+		duk_double_union duk__assert_tmp_du; \
+		duk__assert_tmp_du.d = (dval); \
+		DUK_ASSERT(DUK_DBLUNION_IS_NORMALIZED(&duk__assert_tmp_du)); \
 	} while (0)
 #else
 #define DUK_ASSERT_DOUBLE_IS_NORMALIZED(dval)  /* nop */
@@ -7738,8 +10838,8 @@ extern duk_int_t duk_debug_summary_idx;
  */
 
 #define DUK_VALSTACK_ASSERT_EXTRA  5  /* this is added to checks to allow for Duktape
-                                        * API calls in addition to function's own use
-                                        */
+                                       * API calls in addition to function's own use
+                                       */
 #if defined(DUK_USE_ASSERTIONS)
 #define DUK_ASSERT_VALSTACK_SPACE(thr,n)   do { \
 		DUK_ASSERT((thr) != NULL); \
@@ -7750,119 +10850,114 @@ extern duk_int_t duk_debug_summary_idx;
 #endif
 
 /*
+ *  Error throwing helpers
+ *
+ *  The goal is to provide verbose and configurable error messages.  Call
+ *  sites should be clean in source code and compile to a small footprint.
+ *  Small footprint is also useful for performance because small cold paths
+ *  reduce code cache pressure.
+ */
+
+#if defined(DUK_USE_VERBOSE_ERRORS)
+#if defined(DUK_USE_PARANOID_ERRORS)
+/* Verbose but paranoid errors. */
+
+#define DUK_ERROR_REQUIRE_TYPE_INDEX(thr,index,expectname,lowmemstr) do { \
+		duk_err_require_type_index(DUK_FILE_MACRO, (duk_int_t) DUK_LINE_MACRO, (thr), (index), (expectname)); \
+	} while (0)
+#else
+/* Verbose errors with key/value summaries. */
+
+#define DUK_ERROR_REQUIRE_TYPE_INDEX(thr,index,expectname,lowmemstr) do { \
+		duk_err_require_type_index(DUK_FILE_MACRO, (duk_int_t) DUK_LINE_MACRO, (thr), (index), (expectname)); \
+	} while (0)
+#endif
+#define DUK_ERROR_API_INDEX(thr,index) do { \
+		duk_err_api_index(DUK_FILE_MACRO, (duk_int_t) DUK_LINE_MACRO, (thr), (index)); \
+	} while (0)
+#define DUK_ERROR_API(thr,msg) do { \
+		duk_err_api(DUK_FILE_MACRO, (duk_int_t) DUK_LINE_MACRO, (thr), (msg)); \
+	} while (0)
+#else
+/* Non-verbose errors for low memory targets. */
+
+#define DUK_ERROR_REQUIRE_TYPE_INDEX(thr,index,expectname,lowmemstr) do { \
+		duk_err_require_type_index(DUK_FILE_MACRO, (duk_int_t) DUK_LINE_MACRO, (thr), (lowmemstr)); \
+	} while (0)
+#define DUK_ERROR_API_INDEX(thr,index) do { \
+		duk_err_api_index(DUK_FILE_MACRO, (duk_int_t) DUK_LINE_MACRO, (thr)); \
+	} while (0)
+#define DUK_ERROR_API(thr,msg) do { \
+		duk_err_api(DUK_FILE_MACRO, (duk_int_t) DUK_LINE_MACRO, (thr), (msg)); \
+	} while (0)
+#endif
+
+/*
  *  Prototypes
  */
 
-#ifdef DUK_USE_VERBOSE_ERRORS
-#ifdef DUK_USE_VARIADIC_MACROS
-DUK_NORETURN(void duk_err_handle_error(const char *filename, duk_int_t line, duk_hthread *thr, duk_errcode_t code, const char *fmt, ...));
+#if defined(DUK_USE_VERBOSE_ERRORS)
+#if defined(DUK_USE_VARIADIC_MACROS)
+DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_handle_error(const char *filename, duk_int_t line, duk_hthread *thr, duk_errcode_t code, const char *fmt, ...));
 #else  /* DUK_USE_VARIADIC_MACROS */
-extern const char *duk_err_file_stash;
-extern duk_int_t duk_err_line_stash;
-DUK_NORETURN(void duk_err_handle_error(const char *filename, duk_int_t line, duk_hthread *thr, duk_errcode_t code, const char *fmt, ...));
-DUK_NORETURN(void duk_err_handle_error_stash(duk_hthread *thr, duk_errcode_t code, const char *fmt, ...));
+#if !defined(DUK_SINGLE_FILE)
+DUK_INTERNAL_DECL const char *duk_err_file_stash;
+DUK_INTERNAL_DECL duk_int_t duk_err_line_stash;
+#endif  /* !DUK_SINGLE_FILE */
+DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_handle_error(const char *filename, duk_int_t line, duk_hthread *thr, duk_errcode_t code, const char *fmt, ...));
+DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_handle_error_stash(duk_hthread *thr, duk_errcode_t code, const char *fmt, ...));
 #endif  /* DUK_USE_VARIADIC_MACROS */
 #else  /* DUK_USE_VERBOSE_ERRORS */
-#ifdef DUK_USE_VARIADIC_MACROS
-DUK_NORETURN(void duk_err_handle_error(duk_hthread *thr, duk_errcode_t code));
+#if defined(DUK_USE_VARIADIC_MACROS)
+DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_handle_error(duk_hthread *thr, duk_errcode_t code));
 #else  /* DUK_USE_VARIADIC_MACROS */
-DUK_NORETURN(void duk_err_handle_error_nonverbose1(duk_hthread *thr, duk_errcode_t code, const char *fmt, ...));
-DUK_NORETURN(void duk_err_handle_error_nonverbose2(const char *filename, duk_int_t line, duk_hthread *thr, duk_errcode_t code, const char *fmt, ...));
+DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_handle_error_nonverbose1(duk_hthread *thr, duk_errcode_t code, const char *fmt, ...));
+DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_handle_error_nonverbose2(const char *filename, duk_int_t line, duk_hthread *thr, duk_errcode_t code, const char *fmt, ...));
 #endif  /* DUK_USE_VARIADIC_MACROS */
 #endif  /* DUK_USE_VERBOSE_ERRORS */
 
-#ifdef DUK_USE_VERBOSE_ERRORS
-DUK_NORETURN(void duk_err_create_and_throw(duk_hthread *thr, duk_errcode_t code, const char *msg, const char *filename, duk_int_t line));
+#if defined(DUK_USE_VERBOSE_ERRORS)
+DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_create_and_throw(duk_hthread *thr, duk_errcode_t code, const char *msg, const char *filename, duk_int_t line));
 #else
-DUK_NORETURN(void duk_err_create_and_throw(duk_hthread *thr, duk_errcode_t code));
+DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_create_and_throw(duk_hthread *thr, duk_errcode_t code));
 #endif
 
-DUK_NORETURN(void duk_error_throw_from_negative_rc(duk_hthread *thr, duk_ret_t rc));
+DUK_NORETURN(DUK_INTERNAL_DECL void duk_error_throw_from_negative_rc(duk_hthread *thr, duk_ret_t rc));
 
 #if defined(DUK_USE_AUGMENT_ERROR_CREATE)
-void duk_err_augment_error_create(duk_hthread *thr, duk_hthread *thr_callstack, const char *filename, duk_int_t line, duk_bool_t noblame_fileline);
+DUK_INTERNAL_DECL void duk_err_augment_error_create(duk_hthread *thr, duk_hthread *thr_callstack, const char *filename, duk_int_t line, duk_bool_t noblame_fileline);
 #endif
 #if defined(DUK_USE_AUGMENT_ERROR_THROW)
-void duk_err_augment_error_throw(duk_hthread *thr);
+DUK_INTERNAL_DECL void duk_err_augment_error_throw(duk_hthread *thr);
+#endif
+
+#if defined(DUK_USE_VERBOSE_ERRORS)
+#if defined(DUK_USE_PARANOID_ERRORS)
+DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_require_type_index(const char *filename, duk_int_t linenumber, duk_hthread *thr, duk_idx_t index, const char *expect_name));
+#else
+DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_require_type_index(const char *filename, duk_int_t linenumber, duk_hthread *thr, duk_idx_t index, const char *expect_name));
+#endif
+DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_api_index(const char *filename, duk_int_t linenumber, duk_hthread *thr, duk_idx_t index));
+DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_api(const char *filename, duk_int_t linenumber, duk_hthread *thr, const char *message));
+#else
+DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_require_type_index(const char *filename, duk_int_t linenumber, duk_hthread *thr, const char *error_msg));
+DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_api_index(const char *filename, duk_int_t linenumber, duk_hthread *thr));
+DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_api(const char *filename, duk_int_t linenumber, duk_hthread *thr, const char *message));
 #endif
 
-DUK_NORETURN(void duk_err_longjmp(duk_hthread *thr));
+DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_longjmp(duk_hthread *thr));
 
-DUK_NORETURN(void duk_default_fatal_handler(duk_context *ctx, duk_errcode_t code, const char *msg));
+DUK_NORETURN(DUK_INTERNAL_DECL void duk_default_fatal_handler(duk_context *ctx, duk_errcode_t code, const char *msg));
 
 #if !defined(DUK_USE_PANIC_HANDLER)
-DUK_NORETURN(void duk_default_panic_handler(duk_errcode_t code, const char *msg));
+DUK_NORETURN(DUK_INTERNAL_DECL void duk_default_panic_handler(duk_errcode_t code, const char *msg));
 #endif
 
-void duk_err_setup_heap_ljstate(duk_hthread *thr, duk_small_int_t lj_type);
+DUK_INTERNAL_DECL void duk_err_setup_heap_ljstate(duk_hthread *thr, duk_small_int_t lj_type);
 
-duk_hobject *duk_error_prototype_from_code(duk_hthread *thr, duk_errcode_t err_code);
+DUK_INTERNAL_DECL duk_hobject *duk_error_prototype_from_code(duk_hthread *thr, duk_errcode_t err_code);
 
 #endif  /* DUK_ERROR_H_INCLUDED */
-#line 1 "duk_util.h"
-/*
- *  Utilities
- */
-
-#ifndef DUK_UTIL_H_INCLUDED
-#define DUK_UTIL_H_INCLUDED
-
-#define DUK_UTIL_MIN_HASH_PRIME  17  /* must match genhashsizes.py */
-
-#define DUK_UTIL_GET_HASH_PROBE_STEP(hash)  (duk_util_probe_steps[(hash) & 0x1f])
-
-/*
- *  Bitstream decoder
- */
-
-struct duk_bitdecoder_ctx {
-	const duk_uint8_t *data;
-	duk_size_t offset;
-	duk_size_t length;
-	duk_uint32_t currval;
-	duk_small_int_t currbits;
-};
-
-/*
- *  Bitstream encoder
- */
-
-struct duk_bitencoder_ctx {
-	duk_uint8_t *data;
-	duk_size_t offset;
-	duk_size_t length;
-	duk_uint32_t currval;
-	duk_small_int_t currbits;
-	duk_small_int_t truncated;
-};
-
-/*
- *  Externs and prototypes
- */
-
-extern duk_uint8_t duk_lc_digits[36];
-extern duk_uint8_t duk_uc_nybbles[16];
-extern duk_int8_t duk_hex_dectab[256];
-
-/* Note: assumes that duk_util_probe_steps size is 32 */
-extern duk_uint8_t duk_util_probe_steps[32];
-
-duk_uint32_t duk_util_hashbytes(duk_uint8_t *data, duk_size_t len, duk_uint32_t seed);
-
-duk_uint32_t duk_util_get_hash_prime(duk_uint32_t size);
-
-duk_int32_t duk_bd_decode(duk_bitdecoder_ctx *ctx, duk_small_int_t bits);
-duk_small_int_t duk_bd_decode_flag(duk_bitdecoder_ctx *ctx);
-duk_int32_t duk_bd_decode_flagged(duk_bitdecoder_ctx *ctx, duk_small_int_t bits, duk_int32_t def_value);
-
-void duk_be_encode(duk_bitencoder_ctx *ctx, duk_uint32_t data, duk_small_int_t bits);
-void duk_be_finish(duk_bitencoder_ctx *ctx);
-
-duk_uint32_t duk_util_tinyrandom_get_bits(duk_hthread *thr, duk_small_int_t n);
-duk_double_t duk_util_tinyrandom_get_double(duk_hthread *thr);
-
-#endif  /* DUK_UTIL_H_INCLUDED */
-
 #line 1 "duk_unicode.h"
 /*
  *  Unicode helpers
@@ -7875,8 +10970,10 @@ duk_double_t duk_util_tinyrandom_get_double(duk_hthread *thr);
  *  UTF-8 / XUTF-8 / CESU-8 constants
  */
 
-#define DUK_UNICODE_MAX_XUTF8_LENGTH   7   /* up to 36 bit codepoints */
-#define DUK_UNICODE_MAX_CESU8_LENGTH   6   /* all codepoints up to U+10FFFF */
+#define DUK_UNICODE_MAX_XUTF8_LENGTH      7   /* up to 36 bit codepoints */
+#define DUK_UNICODE_MAX_XUTF8_BMP_LENGTH  3   /* all codepoints up to U+FFFF */
+#define DUK_UNICODE_MAX_CESU8_LENGTH      6   /* all codepoints up to U+10FFFF */
+#define DUK_UNICODE_MAX_CESU8_BMP_LENGTH  3   /* all codepoints up to U+FFFF */
 
 /*
  *  Useful Unicode codepoints
@@ -8038,13 +11135,13 @@ duk_double_t duk_util_tinyrandom_get_double(duk_hthread *thr);
  *  Automatically generated by extract_chars.py, do not edit!
  */
 
-extern const duk_uint8_t duk_unicode_ids_noa[797];
+extern const duk_uint8_t duk_unicode_ids_noa[791];
 #else
 /*
  *  Automatically generated by extract_chars.py, do not edit!
  */
 
-extern const duk_uint8_t duk_unicode_ids_noabmp[614];
+extern const duk_uint8_t duk_unicode_ids_noabmp[611];
 #endif
 
 #ifdef DUK_USE_SOURCE_NONBMP
@@ -8082,40 +11179,52 @@ extern const duk_uint8_t duk_unicode_idp_m_ids_noabmp[348];
 extern const duk_uint8_t duk_unicode_caseconv_uc[1288];
 extern const duk_uint8_t duk_unicode_caseconv_lc[616];
 
+#if defined(DUK_USE_REGEXP_CANON_WORKAROUND)
+/*
+ *  Automatically generated by extract_caseconv.py, do not edit!
+ */
+
+extern const duk_uint16_t duk_unicode_re_canon_lookup[65536];
+#endif
+
 /*
  *  Extern
  */
 
 /* duk_unicode_support.c */
-extern duk_uint8_t duk_unicode_xutf8_markers[7];
-extern duk_uint16_t duk_unicode_re_ranges_digit[2];
-extern duk_uint16_t duk_unicode_re_ranges_white[22];
-extern duk_uint16_t duk_unicode_re_ranges_wordchar[8];
-extern duk_uint16_t duk_unicode_re_ranges_not_digit[4];
-extern duk_uint16_t duk_unicode_re_ranges_not_white[24];
-extern duk_uint16_t duk_unicode_re_ranges_not_wordchar[10];
+#if !defined(DUK_SINGLE_FILE)
+DUK_INTERNAL_DECL duk_uint8_t duk_unicode_xutf8_markers[7];
+DUK_INTERNAL_DECL duk_uint16_t duk_unicode_re_ranges_digit[2];
+DUK_INTERNAL_DECL duk_uint16_t duk_unicode_re_ranges_white[22];
+DUK_INTERNAL_DECL duk_uint16_t duk_unicode_re_ranges_wordchar[8];
+DUK_INTERNAL_DECL duk_uint16_t duk_unicode_re_ranges_not_digit[4];
+DUK_INTERNAL_DECL duk_uint16_t duk_unicode_re_ranges_not_white[24];
+DUK_INTERNAL_DECL duk_uint16_t duk_unicode_re_ranges_not_wordchar[10];
+#endif  /* !DUK_SINGLE_FILE */
 
 /*
  *  Prototypes
  */
 
-duk_small_int_t duk_unicode_get_xutf8_length(duk_ucodepoint_t cp);
-duk_small_int_t duk_unicode_encode_xutf8(duk_ucodepoint_t cp, duk_uint8_t *out);
-duk_small_int_t duk_unicode_encode_cesu8(duk_ucodepoint_t cp, duk_uint8_t *out);
-duk_small_int_t duk_unicode_decode_xutf8(duk_hthread *thr, duk_uint8_t **ptr, duk_uint8_t *ptr_start, duk_uint8_t *ptr_end, duk_ucodepoint_t *out_cp);
-duk_ucodepoint_t duk_unicode_decode_xutf8_checked(duk_hthread *thr, duk_uint8_t **ptr, duk_uint8_t *ptr_start, duk_uint8_t *ptr_end);
-duk_size_t duk_unicode_unvalidated_utf8_length(duk_uint8_t *data, duk_size_t blen);
-duk_small_int_t duk_unicode_is_whitespace(duk_codepoint_t cp);
-duk_small_int_t duk_unicode_is_line_terminator(duk_codepoint_t cp);
-duk_small_int_t duk_unicode_is_identifier_start(duk_codepoint_t cp);
-duk_small_int_t duk_unicode_is_identifier_part(duk_codepoint_t cp);
-duk_small_int_t duk_unicode_is_letter(duk_codepoint_t cp);
-void duk_unicode_case_convert_string(duk_hthread *thr, duk_bool_t uppercase);
-duk_codepoint_t duk_unicode_re_canonicalize_char(duk_hthread *thr, duk_codepoint_t cp);
-duk_small_int_t duk_unicode_re_is_wordchar(duk_codepoint_t cp);
+DUK_INTERNAL_DECL duk_small_int_t duk_unicode_get_xutf8_length(duk_ucodepoint_t cp);
+#if defined(DUK_USE_ASSERTIONS)
+DUK_INTERNAL_DECL duk_small_int_t duk_unicode_get_cesu8_length(duk_ucodepoint_t cp);
+#endif
+DUK_INTERNAL_DECL duk_small_int_t duk_unicode_encode_xutf8(duk_ucodepoint_t cp, duk_uint8_t *out);
+DUK_INTERNAL_DECL duk_small_int_t duk_unicode_encode_cesu8(duk_ucodepoint_t cp, duk_uint8_t *out);
+DUK_INTERNAL_DECL duk_small_int_t duk_unicode_decode_xutf8(duk_hthread *thr, const duk_uint8_t **ptr, const duk_uint8_t *ptr_start, const duk_uint8_t *ptr_end, duk_ucodepoint_t *out_cp);
+DUK_INTERNAL_DECL duk_ucodepoint_t duk_unicode_decode_xutf8_checked(duk_hthread *thr, const duk_uint8_t **ptr, const duk_uint8_t *ptr_start, const duk_uint8_t *ptr_end);
+DUK_INTERNAL_DECL duk_size_t duk_unicode_unvalidated_utf8_length(const duk_uint8_t *data, duk_size_t blen);
+DUK_INTERNAL_DECL duk_small_int_t duk_unicode_is_whitespace(duk_codepoint_t cp);
+DUK_INTERNAL_DECL duk_small_int_t duk_unicode_is_line_terminator(duk_codepoint_t cp);
+DUK_INTERNAL_DECL duk_small_int_t duk_unicode_is_identifier_start(duk_codepoint_t cp);
+DUK_INTERNAL_DECL duk_small_int_t duk_unicode_is_identifier_part(duk_codepoint_t cp);
+DUK_INTERNAL_DECL duk_small_int_t duk_unicode_is_letter(duk_codepoint_t cp);
+DUK_INTERNAL_DECL void duk_unicode_case_convert_string(duk_hthread *thr, duk_bool_t uppercase);
+DUK_INTERNAL_DECL duk_codepoint_t duk_unicode_re_canonicalize_char(duk_hthread *thr, duk_codepoint_t cp);
+DUK_INTERNAL_DECL duk_small_int_t duk_unicode_re_is_wordchar(duk_codepoint_t cp);
 
 #endif  /* DUK_UNICODE_H_INCLUDED */
-
 #line 1 "duk_json.h"
 /*
  *  Defines for JSON, especially duk_bi_json.c.
@@ -8124,20 +11233,11 @@ duk_small_int_t duk_unicode_re_is_wordchar(duk_codepoint_t cp);
 #ifndef DUK_JSON_H_INCLUDED
 #define DUK_JSON_H_INCLUDED
 
-/* Object/array recursion limit (to protect C stack) */
-#if defined(DUK_USE_DEEP_C_STACK)
-#define DUK_JSON_ENC_RECURSION_LIMIT          1000
-#define DUK_JSON_DEC_RECURSION_LIMIT          1000
-#else
-#define DUK_JSON_ENC_RECURSION_LIMIT          100
-#define DUK_JSON_DEC_RECURSION_LIMIT          100
-#endif
-
 /* Encoding/decoding flags */
-#define DUK_JSON_FLAG_ASCII_ONLY          (1 << 0)  /* escape any non-ASCII characters */
-#define DUK_JSON_FLAG_AVOID_KEY_QUOTES    (1 << 1)  /* avoid key quotes when key is an ASCII Identifier */
-#define DUK_JSON_FLAG_EXT_CUSTOM          (1 << 2)  /* extended types: custom encoding */
-#define DUK_JSON_FLAG_EXT_COMPATIBLE      (1 << 3)  /* extended types: compatible encoding */
+#define DUK_JSON_FLAG_ASCII_ONLY              (1 << 0)  /* escape any non-ASCII characters */
+#define DUK_JSON_FLAG_AVOID_KEY_QUOTES        (1 << 1)  /* avoid key quotes when key is an ASCII Identifier */
+#define DUK_JSON_FLAG_EXT_CUSTOM              (1 << 2)  /* extended types: custom encoding */
+#define DUK_JSON_FLAG_EXT_COMPATIBLE          (1 << 3)  /* extended types: compatible encoding */
 
 /* How much stack to require on entry to object/array encode */
 #define DUK_JSON_ENC_REQSTACK                 32
@@ -8145,13 +11245,15 @@ duk_small_int_t duk_unicode_re_is_wordchar(duk_codepoint_t cp);
 /* How much stack to require on entry to object/array decode */
 #define DUK_JSON_DEC_REQSTACK                 32
 
+/* How large a loop detection stack to use */
+#define DUK_JSON_ENC_LOOPARRAY                64
+
 /* Encoding state.  Heap object references are all borrowed. */
 typedef struct {
 	duk_hthread *thr;
-	duk_hbuffer_dynamic *h_buf;
+	duk_bufwriter_ctx bw;        /* output bufwriter */
 	duk_hobject *h_replacer;     /* replacer function */
 	duk_hstring *h_gap;          /* gap (if empty string, NULL) */
-	duk_hstring *h_indent;       /* current indent (if gap is NULL, this is NULL) */
 	duk_idx_t idx_proplist;      /* explicit PropertyList */
 	duk_idx_t idx_loop;          /* valstack index of loop detection object */
 	duk_small_uint_t flags;
@@ -8160,6 +11262,7 @@ typedef struct {
 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
 	duk_small_uint_t flag_ext_custom;
 	duk_small_uint_t flag_ext_compatible;
+	duk_small_uint_t flag_ext_custom_or_compatible;
 #endif
 	duk_int_t recursion_depth;
 	duk_int_t recursion_limit;
@@ -8171,17 +11274,20 @@ typedef struct {
 	duk_small_uint_t stridx_custom_posinf;
 	duk_small_uint_t stridx_custom_function;
 #endif
+	duk_hobject *visiting[DUK_JSON_ENC_LOOPARRAY];  /* indexed by recursion_depth */
 } duk_json_enc_ctx;
 
 typedef struct {
 	duk_hthread *thr;
-	duk_uint8_t *p;
-	duk_uint8_t *p_end;
+	const duk_uint8_t *p;
+	const duk_uint8_t *p_start;
+	const duk_uint8_t *p_end;
 	duk_idx_t idx_reviver;
 	duk_small_uint_t flags;
 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
 	duk_small_uint_t flag_ext_custom;
 	duk_small_uint_t flag_ext_compatible;
+	duk_small_uint_t flag_ext_custom_or_compatible;
 #endif
 	duk_int_t recursion_depth;
 	duk_int_t recursion_limit;
@@ -8197,12 +11303,11 @@ typedef struct {
 #define DUK_JS_H_INCLUDED
 
 /* Flags for call handling. */
-#define DUK_CALL_FLAG_PROTECTED              (1 << 0)  /* duk_handle_call: call is protected */
-#define DUK_CALL_FLAG_IGNORE_RECLIMIT        (1 << 1)  /* duk_handle_call: call ignores C recursion limit (for errhandler calls) */
-#define DUK_CALL_FLAG_CONSTRUCTOR_CALL       (1 << 2)  /* duk_handle_call: constructor call (i.e. called as 'new Foo()') */
-#define DUK_CALL_FLAG_IS_RESUME              (1 << 3)  /* duk_handle_ecma_call_setup: setup for a resume() */
-#define DUK_CALL_FLAG_IS_TAILCALL            (1 << 4)  /* duk_handle_ecma_call_setup: setup for a tailcall */
-#define DUK_CALL_FLAG_DIRECT_EVAL            (1 << 5)  /* call is a direct eval call */
+#define DUK_CALL_FLAG_IGNORE_RECLIMIT        (1 << 0)  /* duk_handle_call_xxx: call ignores C recursion limit (for errhandler calls) */
+#define DUK_CALL_FLAG_CONSTRUCTOR_CALL       (1 << 1)  /* duk_handle_call_xxx: constructor call (i.e. called as 'new Foo()') */
+#define DUK_CALL_FLAG_IS_RESUME              (1 << 2)  /* duk_handle_ecma_call_setup: setup for a resume() */
+#define DUK_CALL_FLAG_IS_TAILCALL            (1 << 3)  /* duk_handle_ecma_call_setup: setup for a tail call */
+#define DUK_CALL_FLAG_DIRECT_EVAL            (1 << 4)  /* call is a direct eval call */
 
 /* Flags for duk_js_equals_helper(). */
 #define DUK_EQUALS_FLAG_SAMEVALUE            (1 << 0)  /* use SameValue instead of non-strict equality */
@@ -8213,24 +11318,25 @@ typedef struct {
 #define DUK_COMPARE_FLAG_NEGATE              (1 << 1)  /* negate result */
 
 /* conversions, coercions, comparison, etc */
-duk_bool_t duk_js_toboolean(duk_tval *tv);
-duk_double_t duk_js_tonumber(duk_hthread *thr, duk_tval *tv);
-duk_double_t duk_js_tointeger_number(duk_double_t x);
-duk_double_t duk_js_tointeger(duk_hthread *thr, duk_tval *tv);
-duk_uint32_t duk_js_touint32_number(duk_double_t x);
-duk_uint32_t duk_js_touint32(duk_hthread *thr, duk_tval *tv);
-duk_int32_t duk_js_toint32_number(duk_double_t x);
-duk_int32_t duk_js_toint32(duk_hthread *thr, duk_tval *tv);
-duk_uint16_t duk_js_touint16_number(duk_double_t x);
-duk_uint16_t duk_js_touint16(duk_hthread *thr, duk_tval *tv);
-duk_small_int_t duk_js_to_arrayindex_raw_string(duk_uint8_t *str, duk_uint32_t blen, duk_uarridx_t *out_idx);
-duk_uarridx_t duk_js_to_arrayindex_string_helper(duk_hstring *h);
-duk_bool_t duk_js_equals_helper(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_y, duk_small_int_t flags);
-duk_small_int_t duk_js_string_compare(duk_hstring *h1, duk_hstring *h2);
-duk_bool_t duk_js_compare_helper(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_y, duk_small_int_t flags);
-duk_bool_t duk_js_instanceof(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_y);
-duk_bool_t duk_js_in(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_y);
-duk_hstring *duk_js_typeof(duk_hthread *thr, duk_tval *tv_x);
+DUK_INTERNAL_DECL duk_bool_t duk_js_toboolean(duk_tval *tv);
+DUK_INTERNAL_DECL duk_double_t duk_js_tonumber(duk_hthread *thr, duk_tval *tv);
+DUK_INTERNAL_DECL duk_double_t duk_js_tointeger_number(duk_double_t x);
+DUK_INTERNAL_DECL duk_double_t duk_js_tointeger(duk_hthread *thr, duk_tval *tv);
+DUK_INTERNAL_DECL duk_uint32_t duk_js_touint32(duk_hthread *thr, duk_tval *tv);
+DUK_INTERNAL_DECL duk_int32_t duk_js_toint32(duk_hthread *thr, duk_tval *tv);
+DUK_INTERNAL_DECL duk_uint16_t duk_js_touint16(duk_hthread *thr, duk_tval *tv);
+DUK_INTERNAL_DECL duk_small_int_t duk_js_to_arrayindex_raw_string(const duk_uint8_t *str, duk_uint32_t blen, duk_uarridx_t *out_idx);
+DUK_INTERNAL_DECL duk_uarridx_t duk_js_to_arrayindex_string_helper(duk_hstring *h);
+DUK_INTERNAL_DECL duk_bool_t duk_js_equals_helper(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_y, duk_small_int_t flags);
+DUK_INTERNAL_DECL duk_small_int_t duk_js_data_compare(const duk_uint8_t *buf1, const duk_uint8_t *buf2, duk_size_t len1, duk_size_t len2);
+DUK_INTERNAL_DECL duk_small_int_t duk_js_string_compare(duk_hstring *h1, duk_hstring *h2);
+#if 0  /* unused */
+DUK_INTERNAL_DECL duk_small_int_t duk_js_buffer_compare(duk_heap *heap, duk_hbuffer *h1, duk_hbuffer *h2);
+#endif
+DUK_INTERNAL_DECL duk_bool_t duk_js_compare_helper(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_y, duk_small_int_t flags);
+DUK_INTERNAL_DECL duk_bool_t duk_js_instanceof(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_y);
+DUK_INTERNAL_DECL duk_bool_t duk_js_in(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_y);
+DUK_INTERNAL_DECL duk_hstring *duk_js_typeof(duk_hthread *thr, duk_tval *tv_x);
 
 #define duk_js_equals(thr,tv_x,tv_y) \
 	duk_js_equals_helper((thr), (tv_x), (tv_y), 0)
@@ -8256,28 +11362,35 @@ duk_hstring *duk_js_typeof(duk_hthread *thr, duk_tval *tv_x);
 	duk_js_compare_helper((thr), (tv_x), (tv_y), DUK_COMPARE_FLAG_EVAL_LEFT_FIRST | DUK_COMPARE_FLAG_NEGATE)
 
 /* identifiers and environment handling */
-duk_bool_t duk_js_getvar_envrec(duk_hthread *thr, duk_hobject *env, duk_hstring *name, duk_bool_t throw_flag);
-duk_bool_t duk_js_getvar_activation(duk_hthread *thr, duk_activation *act, duk_hstring *name, duk_bool_t throw_flag);
-void duk_js_putvar_envrec(duk_hthread *thr, duk_hobject *env, duk_hstring *name, duk_tval *val, duk_bool_t strict);
-void duk_js_putvar_activation(duk_hthread *thr, duk_activation *act, duk_hstring *name, duk_tval *val, duk_bool_t strict);
-duk_bool_t duk_js_delvar_envrec(duk_hthread *thr, duk_hobject *env, duk_hstring *name);
-duk_bool_t duk_js_delvar_activation(duk_hthread *thr, duk_activation *act, duk_hstring *name);
-duk_bool_t duk_js_declvar_activation(duk_hthread *thr, duk_activation *act, duk_hstring *name, duk_tval *val, duk_small_int_t prop_flags, duk_bool_t is_func_decl);
-void duk_js_init_activation_environment_records_delayed(duk_hthread *thr, duk_activation *act);
-void duk_js_close_environment_record(duk_hthread *thr, duk_hobject *env, duk_hobject *func, duk_size_t regbase);
-duk_hobject *duk_create_activation_environment_record(duk_hthread *thr, duk_hobject *func, duk_size_t idx_bottom);
+#if 0  /*unused*/
+DUK_INTERNAL duk_bool_t duk_js_hasvar_envrec(duk_hthread *thr, duk_hobject *env, duk_hstring *name);
+#endif
+DUK_INTERNAL_DECL duk_bool_t duk_js_getvar_envrec(duk_hthread *thr, duk_hobject *env, duk_hstring *name, duk_bool_t throw_flag);
+DUK_INTERNAL_DECL duk_bool_t duk_js_getvar_activation(duk_hthread *thr, duk_activation *act, duk_hstring *name, duk_bool_t throw_flag);
+DUK_INTERNAL_DECL void duk_js_putvar_envrec(duk_hthread *thr, duk_hobject *env, duk_hstring *name, duk_tval *val, duk_bool_t strict);
+DUK_INTERNAL_DECL void duk_js_putvar_activation(duk_hthread *thr, duk_activation *act, duk_hstring *name, duk_tval *val, duk_bool_t strict);
+#if 0  /*unused*/
+DUK_INTERNAL_DECL duk_bool_t duk_js_delvar_envrec(duk_hthread *thr, duk_hobject *env, duk_hstring *name);
+#endif
+DUK_INTERNAL_DECL duk_bool_t duk_js_delvar_activation(duk_hthread *thr, duk_activation *act, duk_hstring *name);
+DUK_INTERNAL_DECL duk_bool_t duk_js_declvar_activation(duk_hthread *thr, duk_activation *act, duk_hstring *name, duk_tval *val, duk_small_int_t prop_flags, duk_bool_t is_func_decl);
+DUK_INTERNAL_DECL void duk_js_init_activation_environment_records_delayed(duk_hthread *thr, duk_activation *act);
+DUK_INTERNAL_DECL void duk_js_close_environment_record(duk_hthread *thr, duk_hobject *env, duk_hobject *func, duk_size_t regbase);
+DUK_INTERNAL_DECL duk_hobject *duk_create_activation_environment_record(duk_hthread *thr, duk_hobject *func, duk_size_t idx_bottom);
+DUK_INTERNAL_DECL
 void duk_js_push_closure(duk_hthread *thr,
                          duk_hcompiledfunction *fun_temp,
                          duk_hobject *outer_var_env,
                          duk_hobject *outer_lex_env);
 
 /* call handling */
-duk_int_t duk_handle_call(duk_hthread *thr, duk_idx_t num_stack_args, duk_small_uint_t call_flags);
-duk_int_t duk_handle_safe_call(duk_hthread *thr, duk_safe_call_function func, duk_idx_t num_stack_args, duk_idx_t num_stack_res);
-void duk_handle_ecma_call_setup(duk_hthread *thr, duk_idx_t num_stack_args, duk_small_uint_t call_flags);
+DUK_INTERNAL_DECL duk_int_t duk_handle_call_protected(duk_hthread *thr, duk_idx_t num_stack_args, duk_small_uint_t call_flags);
+DUK_INTERNAL_DECL void duk_handle_call_unprotected(duk_hthread *thr, duk_idx_t num_stack_args, duk_small_uint_t call_flags);
+DUK_INTERNAL_DECL duk_int_t duk_handle_safe_call(duk_hthread *thr, duk_safe_call_function func, duk_idx_t num_stack_args, duk_idx_t num_stack_res);
+DUK_INTERNAL_DECL duk_bool_t duk_handle_ecma_call_setup(duk_hthread *thr, duk_idx_t num_stack_args, duk_small_uint_t call_flags);
 
 /* bytecode execution */
-void duk_js_execute_bytecode(duk_hthread *entry_thread);
+DUK_INTERNAL_DECL void duk_js_execute_bytecode(duk_hthread *exec_thr);
 
 #endif  /* DUK_JS_H_INCLUDED */
 #line 1 "duk_numconv.h"
@@ -8367,11 +11480,10 @@ void duk_js_execute_bytecode(duk_hthread *entry_thread);
  *  Prototypes
  */
 
-void duk_numconv_stringify(duk_context *ctx, duk_small_int_t radix, duk_small_int_t digits, duk_small_uint_t flags);
-void duk_numconv_parse(duk_context *ctx, duk_small_int_t radix, duk_small_uint_t flags);
+DUK_INTERNAL_DECL void duk_numconv_stringify(duk_context *ctx, duk_small_int_t radix, duk_small_int_t digits, duk_small_uint_t flags);
+DUK_INTERNAL_DECL void duk_numconv_parse(duk_context *ctx, duk_small_int_t radix, duk_small_uint_t flags);
 
 #endif  /* DUK_NUMCONV_H_INCLUDED */
-
 #line 1 "duk_bi_protos.h"
 /*
  *  Prototypes for all built-in functions.
@@ -8388,184 +11500,232 @@ void duk_numconv_parse(duk_context *ctx, duk_small_int_t radix, duk_small_uint_t
  */
 #define  DUK_BI_DATE_ISO8601_BUFSIZE  48
 
-/* Buffer size for "short log message" which use a heap-level pre-allocated
- * dynamic buffer to reduce memory churn.
- */
-#define  DUK_BI_LOGGER_SHORT_MSG_LIMIT  256
-
 /* Maximum length of CommonJS module identifier to resolve.  Length includes
  * both current module ID, requested (possibly relative) module ID, and a
  * slash in between.
  */
 #define  DUK_BI_COMMONJS_MODULE_ID_LIMIT  256
 
-duk_ret_t duk_bi_array_constructor(duk_context *ctx);
-duk_ret_t duk_bi_array_constructor_is_array(duk_context *ctx);
-duk_ret_t duk_bi_array_prototype_to_string(duk_context *ctx);
-duk_ret_t duk_bi_array_prototype_concat(duk_context *ctx);
-duk_ret_t duk_bi_array_prototype_join_shared(duk_context *ctx);
-duk_ret_t duk_bi_array_prototype_pop(duk_context *ctx);
-duk_ret_t duk_bi_array_prototype_push(duk_context *ctx);
-duk_ret_t duk_bi_array_prototype_reverse(duk_context *ctx);
-duk_ret_t duk_bi_array_prototype_shift(duk_context *ctx);
-duk_ret_t duk_bi_array_prototype_slice(duk_context *ctx);
-duk_ret_t duk_bi_array_prototype_sort(duk_context *ctx);
-duk_ret_t duk_bi_array_prototype_splice(duk_context *ctx);
-duk_ret_t duk_bi_array_prototype_unshift(duk_context *ctx);
-duk_ret_t duk_bi_array_prototype_indexof_shared(duk_context *ctx);
-duk_ret_t duk_bi_array_prototype_iter_shared(duk_context *ctx);
-duk_ret_t duk_bi_array_prototype_reduce_shared(duk_context *ctx);
-
-duk_ret_t duk_bi_boolean_constructor(duk_context *ctx);
-duk_ret_t duk_bi_boolean_prototype_tostring_shared(duk_context *ctx);
-
-duk_ret_t duk_bi_buffer_constructor(duk_context *ctx);
-duk_ret_t duk_bi_buffer_prototype_tostring_shared(duk_context *ctx);
-
-duk_ret_t duk_bi_date_constructor(duk_context *ctx);
-duk_ret_t duk_bi_date_constructor_parse(duk_context *ctx);
-duk_ret_t duk_bi_date_constructor_utc(duk_context *ctx);
-duk_ret_t duk_bi_date_constructor_now(duk_context *ctx);
-duk_ret_t duk_bi_date_prototype_tostring_shared(duk_context *ctx);
-duk_ret_t duk_bi_date_prototype_value_of(duk_context *ctx);
-duk_ret_t duk_bi_date_prototype_to_json(duk_context *ctx);
-duk_ret_t duk_bi_date_prototype_get_shared(duk_context *ctx);
-duk_ret_t duk_bi_date_prototype_get_time(duk_context *ctx);
-duk_ret_t duk_bi_date_prototype_get_timezone_offset(duk_context *ctx);
-duk_ret_t duk_bi_date_prototype_set_shared(duk_context *ctx);
-duk_ret_t duk_bi_date_prototype_set_time(duk_context *ctx);
+DUK_INTERNAL_DECL duk_ret_t duk_bi_array_constructor(duk_context *ctx);
+DUK_INTERNAL_DECL duk_ret_t duk_bi_array_constructor_is_array(duk_context *ctx);
+DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_to_string(duk_context *ctx);
+DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_concat(duk_context *ctx);
+DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_join_shared(duk_context *ctx);
+DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_pop(duk_context *ctx);
+DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_push(duk_context *ctx);
+DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_reverse(duk_context *ctx);
+DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_shift(duk_context *ctx);
+DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_slice(duk_context *ctx);
+DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_sort(duk_context *ctx);
+DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_splice(duk_context *ctx);
+DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_unshift(duk_context *ctx);
+DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_indexof_shared(duk_context *ctx);
+DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_iter_shared(duk_context *ctx);
+DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_reduce_shared(duk_context *ctx);
+
+DUK_INTERNAL_DECL duk_ret_t duk_bi_boolean_constructor(duk_context *ctx);
+DUK_INTERNAL_DECL duk_ret_t duk_bi_boolean_prototype_tostring_shared(duk_context *ctx);
+
+/* XXX: naming is inconsistent with other builtins, "prototype" not used as
+ * part of function name.
+ */
+DUK_INTERNAL_DECL duk_ret_t duk_bi_buffer_constructor(duk_context *ctx);
+DUK_INTERNAL_DECL duk_ret_t duk_bi_buffer_prototype_tostring_shared(duk_context *ctx);
+DUK_INTERNAL_DECL duk_ret_t duk_bi_buffer_readfield(duk_context *ctx);
+DUK_INTERNAL_DECL duk_ret_t duk_bi_buffer_writefield(duk_context *ctx);
+DUK_INTERNAL_DECL duk_ret_t duk_bi_buffer_compare_shared(duk_context *ctx);
+DUK_INTERNAL_DECL duk_ret_t duk_bi_buffer_slice_shared(duk_context *ctx);
+DUK_INTERNAL_DECL duk_ret_t duk_bi_arraybuffer_constructor(duk_context *ctx);
+DUK_INTERNAL_DECL duk_ret_t duk_bi_arraybuffer_isview(duk_context *ctx);
+DUK_INTERNAL_DECL duk_ret_t duk_bi_dataview_constructor(duk_context *ctx);
+DUK_INTERNAL_DECL duk_ret_t duk_bi_typedarray_constructor(duk_context *ctx);
+DUK_INTERNAL_DECL duk_ret_t duk_bi_typedarray_set(duk_context *ctx);
+DUK_INTERNAL_DECL duk_ret_t duk_bi_nodejs_buffer_constructor(duk_context *ctx);
+DUK_INTERNAL_DECL duk_ret_t duk_bi_nodejs_buffer_concat(duk_context *ctx);
+DUK_INTERNAL_DECL duk_ret_t duk_bi_nodejs_buffer_is_encoding(duk_context *ctx);
+DUK_INTERNAL_DECL duk_ret_t duk_bi_nodejs_buffer_is_buffer(duk_context *ctx);
+DUK_INTERNAL_DECL duk_ret_t duk_bi_nodejs_buffer_byte_length(duk_context *ctx);
+DUK_INTERNAL_DECL duk_ret_t duk_bi_nodejs_buffer_tostring(duk_context *ctx);
+DUK_INTERNAL_DECL duk_ret_t duk_bi_nodejs_buffer_tojson(duk_context *ctx);
+DUK_INTERNAL_DECL duk_ret_t duk_bi_nodejs_buffer_fill(duk_context *ctx);
+DUK_INTERNAL_DECL duk_ret_t duk_bi_nodejs_buffer_copy(duk_context *ctx);
+DUK_INTERNAL_DECL duk_ret_t duk_bi_nodejs_buffer_write(duk_context *ctx);
+
+DUK_INTERNAL_DECL duk_ret_t duk_bi_date_constructor(duk_context *ctx);
+DUK_INTERNAL_DECL duk_ret_t duk_bi_date_constructor_parse(duk_context *ctx);
+DUK_INTERNAL_DECL duk_ret_t duk_bi_date_constructor_utc(duk_context *ctx);
+DUK_INTERNAL_DECL duk_ret_t duk_bi_date_constructor_now(duk_context *ctx);
+DUK_INTERNAL_DECL duk_ret_t duk_bi_date_prototype_tostring_shared(duk_context *ctx);
+DUK_INTERNAL_DECL duk_ret_t duk_bi_date_prototype_value_of(duk_context *ctx);
+DUK_INTERNAL_DECL duk_ret_t duk_bi_date_prototype_to_json(duk_context *ctx);
+DUK_INTERNAL_DECL duk_ret_t duk_bi_date_prototype_get_shared(duk_context *ctx);
+DUK_INTERNAL_DECL duk_ret_t duk_bi_date_prototype_get_timezone_offset(duk_context *ctx);
+DUK_INTERNAL_DECL duk_ret_t duk_bi_date_prototype_set_shared(duk_context *ctx);
+DUK_INTERNAL_DECL duk_ret_t duk_bi_date_prototype_set_time(duk_context *ctx);
 /* Helpers exposed for internal use */
-duk_double_t duk_bi_date_get_now(duk_context *ctx);
-void duk_bi_date_format_timeval(duk_double_t timeval, duk_uint8_t *out_buf);
-
-duk_ret_t duk_bi_duktape_object_info(duk_context *ctx);
-duk_ret_t duk_bi_duktape_object_act(duk_context *ctx);
-duk_ret_t duk_bi_duktape_object_gc(duk_context *ctx);
-duk_ret_t duk_bi_duktape_object_fin(duk_context *ctx);
-duk_ret_t duk_bi_duktape_object_enc(duk_context *ctx);
-duk_ret_t duk_bi_duktape_object_dec(duk_context *ctx);
-duk_ret_t duk_bi_duktape_object_compact(duk_context *ctx);
-
-duk_ret_t duk_bi_error_constructor_shared(duk_context *ctx);
-duk_ret_t duk_bi_error_prototype_to_string(duk_context *ctx);
-duk_ret_t duk_bi_error_prototype_stack_getter(duk_context *ctx);
-duk_ret_t duk_bi_error_prototype_filename_getter(duk_context *ctx);
-duk_ret_t duk_bi_error_prototype_linenumber_getter(duk_context *ctx);
-duk_ret_t duk_bi_error_prototype_stack_getter(duk_context *ctx);
-duk_ret_t duk_bi_error_prototype_nop_setter(duk_context *ctx);
-
-duk_ret_t duk_bi_function_constructor(duk_context *ctx);
-duk_ret_t duk_bi_function_prototype(duk_context *ctx);
-duk_ret_t duk_bi_function_prototype_to_string(duk_context *ctx);
-duk_ret_t duk_bi_function_prototype_apply(duk_context *ctx);
-duk_ret_t duk_bi_function_prototype_call(duk_context *ctx);
-duk_ret_t duk_bi_function_prototype_bind(duk_context *ctx);
-
-duk_ret_t duk_bi_global_object_eval(duk_context *ctx);
-duk_ret_t duk_bi_global_object_parse_int(duk_context *ctx);
-duk_ret_t duk_bi_global_object_parse_float(duk_context *ctx);
-duk_ret_t duk_bi_global_object_is_nan(duk_context *ctx);
-duk_ret_t duk_bi_global_object_is_finite(duk_context *ctx);
-duk_ret_t duk_bi_global_object_decode_uri(duk_context *ctx);
-duk_ret_t duk_bi_global_object_decode_uri_component(duk_context *ctx);
-duk_ret_t duk_bi_global_object_encode_uri(duk_context *ctx);
-duk_ret_t duk_bi_global_object_encode_uri_component(duk_context *ctx);
-duk_ret_t duk_bi_global_object_escape(duk_context *ctx);
-duk_ret_t duk_bi_global_object_unescape(duk_context *ctx);
-duk_ret_t duk_bi_global_object_print(duk_context *ctx);
-duk_ret_t duk_bi_global_object_alert(duk_context *ctx);
-duk_ret_t duk_bi_global_object_require(duk_context *ctx);
-
+DUK_INTERNAL_DECL void duk_bi_date_timeval_to_parts(duk_double_t d, duk_int_t *parts, duk_double_t *dparts, duk_small_uint_t flags);
+DUK_INTERNAL_DECL duk_double_t duk_bi_date_get_timeval_from_dparts(duk_double_t *dparts, duk_small_uint_t flags);
+DUK_INTERNAL_DECL void duk_bi_date_format_timeval(duk_double_t timeval, duk_uint8_t *out_buf);
+DUK_INTERNAL_DECL duk_bool_t duk_bi_date_is_leap_year(duk_int_t year);
+DUK_INTERNAL_DECL duk_bool_t duk_bi_date_timeval_in_valid_range(duk_double_t x);
+DUK_INTERNAL_DECL duk_bool_t duk_bi_date_year_in_valid_range(duk_double_t year);
+DUK_INTERNAL_DECL duk_bool_t duk_bi_date_timeval_in_leeway_range(duk_double_t x);
+/* Built-in providers */
+#if defined(DUK_USE_DATE_NOW_GETTIMEOFDAY)
+DUK_INTERNAL_DECL duk_double_t duk_bi_date_get_now_gettimeofday(duk_context *ctx);
+#endif
+#if defined(DUK_USE_DATE_NOW_TIME)
+DUK_INTERNAL_DECL duk_double_t duk_bi_date_get_now_time(duk_context *ctx);
+#endif
+#if defined(DUK_USE_DATE_NOW_WINDOWS)
+DUK_INTERNAL_DECL duk_double_t duk_bi_date_get_now_windows(duk_context *ctx);
+#endif
+#if defined(DUK_USE_DATE_TZO_GMTIME_R) || defined(DUK_USE_DATE_TZO_GMTIME)
+DUK_INTERNAL_DECL duk_int_t duk_bi_date_get_local_tzoffset_gmtime(duk_double_t d);
+#endif
+#if defined(DUK_USE_DATE_TZO_WINDOWS)
+DUK_INTERNAL_DECL duk_int_t duk_bi_date_get_local_tzoffset_windows(duk_double_t d);
+#endif
+#if defined(DUK_USE_DATE_PRS_STRPTIME)
+DUK_INTERNAL_DECL duk_bool_t duk_bi_date_parse_string_strptime(duk_context *ctx, const char *str);
+#endif
+#if defined(DUK_USE_DATE_PRS_GETDATE)
+DUK_INTERNAL_DECL duk_bool_t duk_bi_date_parse_string_getdate(duk_context *ctx, const char *str);
+#endif
+#if defined(DUK_USE_DATE_FMT_STRFTIME)
+DUK_INTERNAL_DECL duk_bool_t duk_bi_date_format_parts_strftime(duk_context *ctx, duk_int_t *parts, duk_int_t tzoffset, duk_small_uint_t flags);
+#endif
+
+DUK_INTERNAL_DECL duk_ret_t duk_bi_duktape_object_info(duk_context *ctx);
+DUK_INTERNAL_DECL duk_ret_t duk_bi_duktape_object_act(duk_context *ctx);
+DUK_INTERNAL_DECL duk_ret_t duk_bi_duktape_object_gc(duk_context *ctx);
+DUK_INTERNAL_DECL duk_ret_t duk_bi_duktape_object_fin(duk_context *ctx);
+DUK_INTERNAL_DECL duk_ret_t duk_bi_duktape_object_enc(duk_context *ctx);
+DUK_INTERNAL_DECL duk_ret_t duk_bi_duktape_object_dec(duk_context *ctx);
+DUK_INTERNAL_DECL duk_ret_t duk_bi_duktape_object_compact(duk_context *ctx);
+
+DUK_INTERNAL_DECL duk_ret_t duk_bi_error_constructor_shared(duk_context *ctx);
+DUK_INTERNAL_DECL duk_ret_t duk_bi_error_prototype_to_string(duk_context *ctx);
+DUK_INTERNAL_DECL duk_ret_t duk_bi_error_prototype_stack_getter(duk_context *ctx);
+DUK_INTERNAL_DECL duk_ret_t duk_bi_error_prototype_filename_getter(duk_context *ctx);
+DUK_INTERNAL_DECL duk_ret_t duk_bi_error_prototype_linenumber_getter(duk_context *ctx);
+DUK_INTERNAL_DECL duk_ret_t duk_bi_error_prototype_stack_setter(duk_context *ctx);
+DUK_INTERNAL_DECL duk_ret_t duk_bi_error_prototype_filename_setter(duk_context *ctx);
+DUK_INTERNAL_DECL duk_ret_t duk_bi_error_prototype_linenumber_setter(duk_context *ctx);
+
+DUK_INTERNAL_DECL duk_ret_t duk_bi_function_constructor(duk_context *ctx);
+DUK_INTERNAL_DECL duk_ret_t duk_bi_function_prototype(duk_context *ctx);
+DUK_INTERNAL_DECL duk_ret_t duk_bi_function_prototype_to_string(duk_context *ctx);
+DUK_INTERNAL_DECL duk_ret_t duk_bi_function_prototype_apply(duk_context *ctx);
+DUK_INTERNAL_DECL duk_ret_t duk_bi_function_prototype_call(duk_context *ctx);
+DUK_INTERNAL_DECL duk_ret_t duk_bi_function_prototype_bind(duk_context *ctx);
+
+DUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_eval(duk_context *ctx);
+DUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_parse_int(duk_context *ctx);
+DUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_parse_float(duk_context *ctx);
+DUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_is_nan(duk_context *ctx);
+DUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_is_finite(duk_context *ctx);
+DUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_decode_uri(duk_context *ctx);
+DUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_decode_uri_component(duk_context *ctx);
+DUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_encode_uri(duk_context *ctx);
+DUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_encode_uri_component(duk_context *ctx);
+DUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_escape(duk_context *ctx);
+DUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_unescape(duk_context *ctx);
+DUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_print_helper(duk_context *ctx);
+DUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_require(duk_context *ctx);
+
+DUK_INTERNAL_DECL
 void duk_bi_json_parse_helper(duk_context *ctx,
                               duk_idx_t idx_value,
                               duk_idx_t idx_reviver,
                               duk_small_uint_t flags);
+DUK_INTERNAL_DECL
 void duk_bi_json_stringify_helper(duk_context *ctx,
                                   duk_idx_t idx_value,
                                   duk_idx_t idx_replacer,
                                   duk_idx_t idx_space,
                                   duk_small_uint_t flags);
-duk_ret_t duk_bi_json_object_parse(duk_context *ctx);
-duk_ret_t duk_bi_json_object_stringify(duk_context *ctx);
-
-duk_ret_t duk_bi_math_object_onearg_shared(duk_context *ctx);
-duk_ret_t duk_bi_math_object_twoarg_shared(duk_context *ctx);
-duk_ret_t duk_bi_math_object_max(duk_context *ctx);
-duk_ret_t duk_bi_math_object_min(duk_context *ctx);
-duk_ret_t duk_bi_math_object_random(duk_context *ctx);
-
-duk_ret_t duk_bi_number_constructor(duk_context *ctx);
-duk_ret_t duk_bi_number_prototype_to_string(duk_context *ctx);
-duk_ret_t duk_bi_number_prototype_to_locale_string(duk_context *ctx);
-duk_ret_t duk_bi_number_prototype_value_of(duk_context *ctx);
-duk_ret_t duk_bi_number_prototype_to_fixed(duk_context *ctx);
-duk_ret_t duk_bi_number_prototype_to_exponential(duk_context *ctx);
-duk_ret_t duk_bi_number_prototype_to_precision(duk_context *ctx);
-
-duk_ret_t duk_bi_object_getprototype_shared(duk_context *ctx);
-duk_ret_t duk_bi_object_setprototype_shared(duk_context *ctx);
-duk_ret_t duk_bi_object_constructor(duk_context *ctx);
-duk_ret_t duk_bi_object_constructor_get_own_property_descriptor(duk_context *ctx);
-duk_ret_t duk_bi_object_constructor_create(duk_context *ctx);
-duk_ret_t duk_bi_object_constructor_define_property(duk_context *ctx);
-duk_ret_t duk_bi_object_constructor_define_properties(duk_context *ctx);
-duk_ret_t duk_bi_object_constructor_seal_freeze_shared(duk_context *ctx);
-duk_ret_t duk_bi_object_constructor_prevent_extensions(duk_context *ctx);
-duk_ret_t duk_bi_object_constructor_is_sealed_frozen_shared(duk_context *ctx);
-duk_ret_t duk_bi_object_constructor_is_extensible(duk_context *ctx);
-duk_ret_t duk_bi_object_constructor_keys_shared(duk_context *ctx);
-duk_ret_t duk_bi_object_prototype_to_string(duk_context *ctx);
-duk_ret_t duk_bi_object_prototype_to_locale_string(duk_context *ctx);
-duk_ret_t duk_bi_object_prototype_value_of(duk_context *ctx);
-duk_ret_t duk_bi_object_prototype_has_own_property(duk_context *ctx);
-duk_ret_t duk_bi_object_prototype_is_prototype_of(duk_context *ctx);
-duk_ret_t duk_bi_object_prototype_property_is_enumerable(duk_context *ctx);
-
-duk_ret_t duk_bi_pointer_constructor(duk_context *ctx);
-duk_ret_t duk_bi_pointer_prototype_tostring_shared(duk_context *ctx);
-
-duk_ret_t duk_bi_regexp_constructor(duk_context *ctx);
-duk_ret_t duk_bi_regexp_prototype_exec(duk_context *ctx);
-duk_ret_t duk_bi_regexp_prototype_test(duk_context *ctx);
-duk_ret_t duk_bi_regexp_prototype_to_string(duk_context *ctx);
-
-duk_ret_t duk_bi_string_constructor(duk_context *ctx);
-duk_ret_t duk_bi_string_constructor_from_char_code(duk_context *ctx);
-duk_ret_t duk_bi_string_prototype_to_string(duk_context *ctx);
-duk_ret_t duk_bi_string_prototype_value_of(duk_context *ctx);
-duk_ret_t duk_bi_string_prototype_char_at(duk_context *ctx);
-duk_ret_t duk_bi_string_prototype_char_code_at(duk_context *ctx);
-duk_ret_t duk_bi_string_prototype_concat(duk_context *ctx);
-duk_ret_t duk_bi_string_prototype_indexof_shared(duk_context *ctx);
-duk_ret_t duk_bi_string_prototype_locale_compare(duk_context *ctx);
-duk_ret_t duk_bi_string_prototype_match(duk_context *ctx);
-duk_ret_t duk_bi_string_prototype_replace(duk_context *ctx);
-duk_ret_t duk_bi_string_prototype_search(duk_context *ctx);
-duk_ret_t duk_bi_string_prototype_slice(duk_context *ctx);
-duk_ret_t duk_bi_string_prototype_split(duk_context *ctx);
-duk_ret_t duk_bi_string_prototype_substring(duk_context *ctx);
-duk_ret_t duk_bi_string_prototype_caseconv_shared(duk_context *ctx);
-duk_ret_t duk_bi_string_prototype_trim(duk_context *ctx);
-#ifdef DUK_USE_SECTION_B
-duk_ret_t duk_bi_string_prototype_substr(duk_context *ctx);
-#endif
-
-duk_ret_t duk_bi_proxy_constructor(duk_context *ctx);
+DUK_INTERNAL_DECL duk_ret_t duk_bi_json_object_parse(duk_context *ctx);
+DUK_INTERNAL_DECL duk_ret_t duk_bi_json_object_stringify(duk_context *ctx);
+
+DUK_INTERNAL_DECL duk_ret_t duk_bi_math_object_onearg_shared(duk_context *ctx);
+DUK_INTERNAL_DECL duk_ret_t duk_bi_math_object_twoarg_shared(duk_context *ctx);
+DUK_INTERNAL_DECL duk_ret_t duk_bi_math_object_max(duk_context *ctx);
+DUK_INTERNAL_DECL duk_ret_t duk_bi_math_object_min(duk_context *ctx);
+DUK_INTERNAL_DECL duk_ret_t duk_bi_math_object_random(duk_context *ctx);
+
+DUK_INTERNAL_DECL duk_ret_t duk_bi_number_constructor(duk_context *ctx);
+DUK_INTERNAL_DECL duk_ret_t duk_bi_number_prototype_to_string(duk_context *ctx);
+DUK_INTERNAL_DECL duk_ret_t duk_bi_number_prototype_to_locale_string(duk_context *ctx);
+DUK_INTERNAL_DECL duk_ret_t duk_bi_number_prototype_value_of(duk_context *ctx);
+DUK_INTERNAL_DECL duk_ret_t duk_bi_number_prototype_to_fixed(duk_context *ctx);
+DUK_INTERNAL_DECL duk_ret_t duk_bi_number_prototype_to_exponential(duk_context *ctx);
+DUK_INTERNAL_DECL duk_ret_t duk_bi_number_prototype_to_precision(duk_context *ctx);
+
+DUK_INTERNAL_DECL duk_ret_t duk_bi_object_getprototype_shared(duk_context *ctx);
+DUK_INTERNAL_DECL duk_ret_t duk_bi_object_setprototype_shared(duk_context *ctx);
+DUK_INTERNAL_DECL duk_ret_t duk_bi_object_constructor(duk_context *ctx);
+DUK_INTERNAL_DECL duk_ret_t duk_bi_object_constructor_get_own_property_descriptor(duk_context *ctx);
+DUK_INTERNAL_DECL duk_ret_t duk_bi_object_constructor_create(duk_context *ctx);
+DUK_INTERNAL_DECL duk_ret_t duk_bi_object_constructor_define_property(duk_context *ctx);
+DUK_INTERNAL_DECL duk_ret_t duk_bi_object_constructor_define_properties(duk_context *ctx);
+DUK_INTERNAL_DECL duk_ret_t duk_bi_object_constructor_seal_freeze_shared(duk_context *ctx);
+DUK_INTERNAL_DECL duk_ret_t duk_bi_object_constructor_prevent_extensions(duk_context *ctx);
+DUK_INTERNAL_DECL duk_ret_t duk_bi_object_constructor_is_sealed_frozen_shared(duk_context *ctx);
+DUK_INTERNAL_DECL duk_ret_t duk_bi_object_constructor_is_extensible(duk_context *ctx);
+DUK_INTERNAL_DECL duk_ret_t duk_bi_object_constructor_keys_shared(duk_context *ctx);
+DUK_INTERNAL_DECL duk_ret_t duk_bi_object_prototype_to_string(duk_context *ctx);
+DUK_INTERNAL_DECL duk_ret_t duk_bi_object_prototype_to_locale_string(duk_context *ctx);
+DUK_INTERNAL_DECL duk_ret_t duk_bi_object_prototype_value_of(duk_context *ctx);
+DUK_INTERNAL_DECL duk_ret_t duk_bi_object_prototype_has_own_property(duk_context *ctx);
+DUK_INTERNAL_DECL duk_ret_t duk_bi_object_prototype_is_prototype_of(duk_context *ctx);
+DUK_INTERNAL_DECL duk_ret_t duk_bi_object_prototype_property_is_enumerable(duk_context *ctx);
+
+DUK_INTERNAL_DECL duk_ret_t duk_bi_pointer_constructor(duk_context *ctx);
+DUK_INTERNAL_DECL duk_ret_t duk_bi_pointer_prototype_tostring_shared(duk_context *ctx);
+
+DUK_INTERNAL_DECL duk_ret_t duk_bi_regexp_constructor(duk_context *ctx);
+DUK_INTERNAL_DECL duk_ret_t duk_bi_regexp_prototype_exec(duk_context *ctx);
+DUK_INTERNAL_DECL duk_ret_t duk_bi_regexp_prototype_test(duk_context *ctx);
+DUK_INTERNAL_DECL duk_ret_t duk_bi_regexp_prototype_to_string(duk_context *ctx);
+
+DUK_INTERNAL_DECL duk_ret_t duk_bi_string_constructor(duk_context *ctx);
+DUK_INTERNAL_DECL duk_ret_t duk_bi_string_constructor_from_char_code(duk_context *ctx);
+DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_to_string(duk_context *ctx);
+DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_char_at(duk_context *ctx);
+DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_char_code_at(duk_context *ctx);
+DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_concat(duk_context *ctx);
+DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_indexof_shared(duk_context *ctx);
+DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_locale_compare(duk_context *ctx);
+DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_match(duk_context *ctx);
+DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_replace(duk_context *ctx);
+DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_search(duk_context *ctx);
+DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_slice(duk_context *ctx);
+DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_split(duk_context *ctx);
+DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_substring(duk_context *ctx);
+DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_caseconv_shared(duk_context *ctx);
+DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_trim(duk_context *ctx);
+/* Note: present even if DUK_USE_SECTION_B undefined given because genbuiltins.py
+ * will point to it.
+ */
+DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_substr(duk_context *ctx);
+
+DUK_INTERNAL_DECL duk_ret_t duk_bi_proxy_constructor(duk_context *ctx);
 #if 0  /* unimplemented now */
-duk_ret_t duk_bi_proxy_constructor_revocable(duk_context *ctx);
+DUK_INTERNAL_DECL duk_ret_t duk_bi_proxy_constructor_revocable(duk_context *ctx);
 #endif
 
-duk_ret_t duk_bi_thread_constructor(duk_context *ctx);
-duk_ret_t duk_bi_thread_resume(duk_context *ctx);
-duk_ret_t duk_bi_thread_yield(duk_context *ctx);
-duk_ret_t duk_bi_thread_current(duk_context *ctx);
+DUK_INTERNAL_DECL duk_ret_t duk_bi_thread_constructor(duk_context *ctx);
+DUK_INTERNAL_DECL duk_ret_t duk_bi_thread_resume(duk_context *ctx);
+DUK_INTERNAL_DECL duk_ret_t duk_bi_thread_yield(duk_context *ctx);
+DUK_INTERNAL_DECL duk_ret_t duk_bi_thread_current(duk_context *ctx);
 
-duk_ret_t duk_bi_logger_constructor(duk_context *ctx);
-duk_ret_t duk_bi_logger_prototype_fmt(duk_context *ctx);
-duk_ret_t duk_bi_logger_prototype_raw(duk_context *ctx);
-duk_ret_t duk_bi_logger_prototype_log_shared(duk_context *ctx);
+DUK_INTERNAL_DECL duk_ret_t duk_bi_logger_constructor(duk_context *ctx);
+DUK_INTERNAL_DECL duk_ret_t duk_bi_logger_prototype_fmt(duk_context *ctx);
+DUK_INTERNAL_DECL duk_ret_t duk_bi_logger_prototype_raw(duk_context *ctx);
+DUK_INTERNAL_DECL duk_ret_t duk_bi_logger_prototype_log_shared(duk_context *ctx);
 
-duk_ret_t duk_bi_type_error_thrower(duk_context *ctx);
+DUK_INTERNAL_DECL duk_ret_t duk_bi_type_error_thrower(duk_context *ctx);
 
 #endif  /* DUK_BUILTIN_PROTOS_H_INCLUDED */
 #line 1 "duk_selftest.h"
@@ -8576,500 +11736,6977 @@ duk_ret_t duk_bi_type_error_thrower(duk_context *ctx);
 #ifndef DUK_SELFTEST_H_INCLUDED
 #define DUK_SELFTEST_H_INCLUDED
 
-void duk_selftest_run_tests(void);
+#if defined(DUK_USE_SELF_TESTS)
+DUK_INTERNAL_DECL void duk_selftest_run_tests(void);
+#endif
 
 #endif  /* DUK_SELFTEST_H_INCLUDED */
-#line 75 "duk_internal.h"
+#line 78 "duk_internal.h"
 
 #endif  /* DUK_INTERNAL_H_INCLUDED */
-#line 1 "duk_alloc_default.c"
+#line 1 "duk_strings.c"
 /*
- *  Default allocation functions.
+ *  Shared error message strings
  *
- *  Assumes behavior such as malloc allowing zero size, yielding
- *  a NULL or a unique pointer which is a no-op for free.
+ *  To minimize code footprint, try to share error messages inside Duktape
+ *  code.  Modern compilers will do this automatically anyway, this is mostly
+ *  for older compilers.
  */
 
 /* include removed: duk_internal.h */
 
-void *duk_default_alloc_function(void *udata, duk_size_t size) {
-	void *res;
-	DUK_UNREF(udata);
-	res = DUK_ANSI_MALLOC(size);
-	DUK_DDD(DUK_DDDPRINT("default alloc function: %lu -> %p",
-	                     (unsigned long) size, (void *) res));
-	return res;
-}
-
-void *duk_default_realloc_function(void *udata, void *ptr, duk_size_t newsize) {
-	void *res;
-	DUK_UNREF(udata);
-	res = DUK_ANSI_REALLOC(ptr, newsize);
-	DUK_DDD(DUK_DDDPRINT("default realloc function: %p %lu -> %p",
-	                     (void *) ptr, (unsigned long) newsize, (void *) res));
-	return res;
-}
-
-void duk_default_free_function(void *udata, void *ptr) {
-	DUK_DDD(DUK_DDDPRINT("default free function: %p", (void *) ptr));
-	DUK_UNREF(udata);
-	DUK_ANSI_FREE(ptr);
-}
-#line 1 "duk_alloc_torture.c"
-/*
- *  Torture allocation functions.
- *
- *  Provides various debugging features:
- *
- *    - Wraps allocations with "buffer zones" which are checked on free
- *    - Overwrites freed memory with garbage (not zero)
- *    - Debug prints memory usage info after every alloc/realloc/free
- *
- *  Can be left out of a standard compilation.
- */
+/* Mostly API and built-in method related */
+DUK_INTERNAL const char *duk_str_internal_error = "internal error";
+DUK_INTERNAL const char *duk_str_invalid_count = "invalid count";
+DUK_INTERNAL const char *duk_str_invalid_call_args = "invalid call args";
+DUK_INTERNAL const char *duk_str_not_constructable = "not constructable";
+DUK_INTERNAL const char *duk_str_not_callable = "not callable";
+DUK_INTERNAL const char *duk_str_not_extensible = "not extensible";
+DUK_INTERNAL const char *duk_str_not_writable = "not writable";
+DUK_INTERNAL const char *duk_str_not_configurable = "not configurable";
+
+DUK_INTERNAL const char *duk_str_invalid_context = "invalid context";
+DUK_INTERNAL const char *duk_str_push_beyond_alloc_stack = "attempt to push beyond currently allocated stack";
+DUK_INTERNAL const char *duk_str_not_buffer = "not buffer";  /* still in use with verbose messages */
+DUK_INTERNAL const char *duk_str_unexpected_type = "unexpected type";
+DUK_INTERNAL const char *duk_str_defaultvalue_coerce_failed = "[[DefaultValue]] coerce failed";
+DUK_INTERNAL const char *duk_str_number_outside_range = "number outside range";
+DUK_INTERNAL const char *duk_str_not_object_coercible = "not object coercible";
+DUK_INTERNAL const char *duk_str_string_too_long = "string too long";
+DUK_INTERNAL const char *duk_str_buffer_too_long = "buffer too long";
+DUK_INTERNAL const char *duk_str_sprintf_too_long = "sprintf message too long";
+DUK_INTERNAL const char *duk_str_alloc_failed = "alloc failed";
+DUK_INTERNAL const char *duk_str_pop_too_many = "attempt to pop too many entries";
+DUK_INTERNAL const char *duk_str_wrong_buffer_type = "wrong buffer type";
+DUK_INTERNAL const char *duk_str_failed_to_extend_valstack = "failed to extend valstack";
+DUK_INTERNAL const char *duk_str_encode_failed = "encode failed";
+DUK_INTERNAL const char *duk_str_decode_failed = "decode failed";
+DUK_INTERNAL const char *duk_str_no_sourcecode = "no sourcecode";
+DUK_INTERNAL const char *duk_str_concat_result_too_long = "concat result too long";
+DUK_INTERNAL const char *duk_str_unimplemented = "unimplemented";
+DUK_INTERNAL const char *duk_str_unsupported = "unsupported";
+DUK_INTERNAL const char *duk_str_array_length_over_2g = "array length over 2G";
 
-/* include removed: duk_internal.h */
+/* JSON */
+DUK_INTERNAL const char *duk_str_fmt_ptr = "%p";
+DUK_INTERNAL const char *duk_str_fmt_invalid_json = "invalid json (at offset %ld)";
+DUK_INTERNAL const char *duk_str_jsondec_reclimit = "json decode recursion limit";
+DUK_INTERNAL const char *duk_str_jsonenc_reclimit = "json encode recursion limit";
+DUK_INTERNAL const char *duk_str_cyclic_input = "cyclic input";
 
-/* FIXME: unimplemented */
+/* Object property access */
+DUK_INTERNAL const char *duk_str_proxy_revoked = "proxy revoked";
+DUK_INTERNAL const char *duk_str_object_resize_failed = "object resize failed";
+DUK_INTERNAL const char *duk_str_invalid_base = "invalid base value";
+DUK_INTERNAL const char *duk_str_strict_caller_read = "attempt to read strict 'caller'";
+DUK_INTERNAL const char *duk_str_proxy_rejected = "proxy rejected";
+DUK_INTERNAL const char *duk_str_invalid_array_length = "invalid array length";
+DUK_INTERNAL const char *duk_str_array_length_write_failed = "array length write failed";
+DUK_INTERNAL const char *duk_str_array_length_not_writable = "array length non-writable";
+DUK_INTERNAL const char *duk_str_setter_undefined = "setter undefined";
+DUK_INTERNAL const char *duk_str_redefine_virt_prop = "attempt to redefine virtual property";
+DUK_INTERNAL const char *duk_str_invalid_descriptor = "invalid descriptor";
+DUK_INTERNAL const char *duk_str_property_is_virtual = "property is virtual";
 
-void *duk_torture_alloc_function(void *udata, duk_size_t size) {
-	void *res;
-	DUK_UNREF(udata);
-	res = DUK_ANSI_MALLOC(size);
-	DUK_DDD(DUK_DDDPRINT("torture alloc function: %lu -> %p",
-	                     (unsigned long) size, (void *) res));
-	return res;
-}
+/* Compiler */
+DUK_INTERNAL const char *duk_str_parse_error = "parse error";
+DUK_INTERNAL const char *duk_str_duplicate_label = "duplicate label";
+DUK_INTERNAL const char *duk_str_invalid_label = "invalid label";
+DUK_INTERNAL const char *duk_str_invalid_array_literal = "invalid array literal";
+DUK_INTERNAL const char *duk_str_invalid_object_literal = "invalid object literal";
+DUK_INTERNAL const char *duk_str_invalid_var_declaration = "invalid variable declaration";
+DUK_INTERNAL const char *duk_str_cannot_delete_identifier = "cannot delete identifier";
+DUK_INTERNAL const char *duk_str_invalid_expression = "invalid expression";
+DUK_INTERNAL const char *duk_str_invalid_lvalue = "invalid lvalue";
+DUK_INTERNAL const char *duk_str_expected_identifier = "expected identifier";
+DUK_INTERNAL const char *duk_str_empty_expr_not_allowed = "empty expression not allowed";
+DUK_INTERNAL const char *duk_str_invalid_for = "invalid for statement";
+DUK_INTERNAL const char *duk_str_invalid_switch = "invalid switch statement";
+DUK_INTERNAL const char *duk_str_invalid_break_cont_label = "invalid break/continue label";
+DUK_INTERNAL const char *duk_str_invalid_return = "invalid return";
+DUK_INTERNAL const char *duk_str_invalid_try = "invalid try";
+DUK_INTERNAL const char *duk_str_invalid_throw = "invalid throw";
+DUK_INTERNAL const char *duk_str_with_in_strict_mode = "with in strict mode";
+DUK_INTERNAL const char *duk_str_func_stmt_not_allowed = "function statement not allowed";
+DUK_INTERNAL const char *duk_str_unterminated_stmt = "unterminated statement";
+DUK_INTERNAL const char *duk_str_invalid_arg_name = "invalid argument name";
+DUK_INTERNAL const char *duk_str_invalid_func_name = "invalid function name";
+DUK_INTERNAL const char *duk_str_invalid_getset_name = "invalid getter/setter name";
+DUK_INTERNAL const char *duk_str_func_name_required = "function name required";
 
-void *duk_torture_realloc_function(void *udata, void *ptr, duk_size_t newsize) {
-	void *res;
-	DUK_UNREF(udata);
-	res = DUK_ANSI_REALLOC(ptr, newsize);
-	DUK_DDD(DUK_DDDPRINT("torture realloc function: %p %lu -> %p",
-	                     (void *) ptr, (unsigned long) newsize, (void *) res));
-	return res;
-}
+/* Executor */
+DUK_INTERNAL const char *duk_str_internal_error_exec_longjmp = "internal error in bytecode executor longjmp handler";
+
+/* Regexp */
+DUK_INTERNAL const char *duk_str_invalid_quantifier_no_atom = "quantifier without preceding atom";
+DUK_INTERNAL const char *duk_str_invalid_quantifier_values = "quantifier values invalid (qmin > qmax)";
+DUK_INTERNAL const char *duk_str_quantifier_too_many_copies = "quantifier expansion requires too many atom copies";
+DUK_INTERNAL const char *duk_str_unexpected_closing_paren = "unexpected closing parenthesis";
+DUK_INTERNAL const char *duk_str_unexpected_end_of_pattern = "unexpected end of pattern";
+DUK_INTERNAL const char *duk_str_unexpected_regexp_token = "unexpected token in regexp";
+DUK_INTERNAL const char *duk_str_invalid_regexp_flags = "invalid regexp flags";
+DUK_INTERNAL const char *duk_str_invalid_backrefs = "invalid backreference(s)";
+DUK_INTERNAL const char *duk_str_regexp_backtrack_failed = "regexp backtrack failed";
+DUK_INTERNAL const char *duk_str_regexp_advance_failed = "regexp advance failed";
+DUK_INTERNAL const char *duk_str_regexp_internal_error = "regexp internal error";
 
-void duk_torture_free_function(void *udata, void *ptr) {
-	DUK_DDD(DUK_DDDPRINT("torture free function: %p", (void *) ptr));
-	DUK_UNREF(udata);
-	DUK_ANSI_FREE(ptr);
-}
-#line 1 "duk_api.c"
+/* Limits */
+DUK_INTERNAL const char *duk_str_valstack_limit = "valstack limit";
+DUK_INTERNAL const char *duk_str_callstack_limit = "callstack limit";
+DUK_INTERNAL const char *duk_str_catchstack_limit = "catchstack limit";
+DUK_INTERNAL const char *duk_str_object_property_limit = "object property limit";
+DUK_INTERNAL const char *duk_str_prototype_chain_limit = "prototype chain limit";
+DUK_INTERNAL const char *duk_str_bound_chain_limit = "function call bound chain limit";
+DUK_INTERNAL const char *duk_str_c_callstack_limit = "C call stack depth limit";
+DUK_INTERNAL const char *duk_str_compiler_recursion_limit = "compiler recursion limit";
+DUK_INTERNAL const char *duk_str_bytecode_limit = "bytecode limit";
+DUK_INTERNAL const char *duk_str_reg_limit = "register limit";
+DUK_INTERNAL const char *duk_str_temp_limit = "temp limit";
+DUK_INTERNAL const char *duk_str_const_limit = "const limit";
+DUK_INTERNAL const char *duk_str_func_limit = "function limit";
+DUK_INTERNAL const char *duk_str_regexp_compiler_recursion_limit = "regexp compiler recursion limit";
+DUK_INTERNAL const char *duk_str_regexp_executor_recursion_limit = "regexp executor recursion limit";
+DUK_INTERNAL const char *duk_str_regexp_executor_step_limit = "regexp step limit";
+
+/* Misc */
+DUK_INTERNAL const char *duk_str_anon = "anon";
+DUK_INTERNAL const char *duk_str_realloc_failed = "realloc failed";
+#line 1 "duk_debug_macros.c"
 /*
- *  API calls not falling into other categories.
- *
- *  Also contains internal functions (such as duk_get_tval()), defined
- *  in duk_api_internal.h, with semantics similar to the public API.
+ *  Debugging macro calls.
  */
 
-/* XXX: repetition of stack pre-checks -> helper or macro or inline */
-/* XXX: shared api error strings, and perhaps even throw code for rare cases? */
-
 /* include removed: duk_internal.h */
 
-/*
- *  Global state for working around missing variadic macros
- */
-
-#ifndef DUK_USE_VARIADIC_MACROS
-const char *duk_api_global_filename = NULL;
-duk_int_t duk_api_global_line = 0;
-#endif
+#ifdef DUK_USE_DEBUG
 
 /*
- *  Helpers
+ *  Debugging enabled
  */
 
-static duk_int_t duk__api_coerce_d2i(duk_double_t d) {
-	duk_small_int_t c;
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
 
-	/*
-	 *  Special cases like NaN and +/- Infinity are handled explicitly
-	 *  because a plain C coercion from double to int handles these cases
-	 *  in undesirable ways.  For instance, NaN may coerce to INT_MIN
-	 *  (not zero), and INT_MAX + 1 may coerce to INT_MIN (not INT_MAX).
-	 *
-	 *  This double-to-int coercion differs from ToInteger() because it
-	 *  has a finite range (ToInteger() allows e.g. +/- Infinity).  It
-	 *  also differs from ToInt32() because the INT_MIN/INT_MAX clamping
-	 *  depends on the size of the int type on the platform.  In particular,
-	 *  on platforms with a 64-bit int type, the full range is allowed.
-	 */
+#define DUK__DEBUG_BUFSIZE  DUK_USE_DEBUG_BUFSIZE
+DUK_LOCAL char duk__debug_buf[DUK__DEBUG_BUFSIZE];
 
-	c = (duk_small_int_t) DUK_FPCLASSIFY(d);
-	if (c == DUK_FP_NAN) {
-		return 0;
-	} else if (d < (duk_double_t) DUK_INT_MIN) {
-		/* covers -Infinity */
-		return DUK_INT_MIN;
-	} else if (d > (duk_double_t) DUK_INT_MAX) {
-		/* covers +Infinity */
-		return DUK_INT_MAX;
-	} else {
-		/* coerce towards zero */
-		return (duk_int_t) d;
+DUK_LOCAL const char *duk__get_level_string(duk_small_int_t level) {
+	switch ((int) level) {
+	case DUK_LEVEL_DEBUG:
+		return "D";
+	case DUK_LEVEL_DDEBUG:
+		return "DD";
+	case DUK_LEVEL_DDDEBUG:
+		return "DDD";
 	}
+	return "???";
 }
 
-static duk_uint_t duk__api_coerce_d2ui(duk_double_t d) {
-	duk_small_int_t c;
+#ifdef DUK_USE_DPRINT_COLORS
 
-	/* Same as above but for unsigned int range. */
+/* http://en.wikipedia.org/wiki/ANSI_escape_code */
+#define DUK__TERM_REVERSE  "\x1b[7m"
+#define DUK__TERM_BRIGHT   "\x1b[1m"
+#define DUK__TERM_RESET    "\x1b[0m"
+#define DUK__TERM_BLUE     "\x1b[34m"
+#define DUK__TERM_RED      "\x1b[31m"
 
-	c = (duk_small_int_t) DUK_FPCLASSIFY(d);
-	if (c == DUK_FP_NAN) {
-		return 0;
-	} else if (d < 0.0) {
-		/* covers -Infinity */
-		return (duk_uint_t) 0;
-	} else if (d > (duk_double_t) DUK_UINT_MAX) {
-		/* covers +Infinity */
-		return (duk_uint_t) DUK_UINT_MAX;
-	} else {
-		/* coerce towards zero */
-		return (duk_uint_t) d;
-	}
+DUK_LOCAL const char *duk__get_term_1(duk_small_int_t level) {
+	DUK_UNREF(level);
+	return (const char *) DUK__TERM_RED;
 }
 
-/*
- *  Stack index validation/normalization and getting a stack duk_tval ptr.
- *
- *  These are called by many API entrypoints so the implementations must be
- *  fast and "inlined".
- *
- *  There's some repetition because of this; keep the functions in sync.
- */
-
-duk_idx_t duk_normalize_index(duk_context *ctx, duk_idx_t index) {
-	duk_hthread *thr = (duk_hthread *) ctx;
-	duk_idx_t vs_size;
-
-	DUK_ASSERT(ctx != NULL);
-	DUK_ASSERT(DUK_INVALID_INDEX < 0);
-
-	/* Care must be taken to avoid pointer wrapping in the index
-	 * validation.  For instance, on a 32-bit platform with 8-byte
-	 * duk_tval the index 0x20000000UL would wrap the memory space
-	 * once.
-	 */
-
-	/* Assume value stack sizes (in elements) fits into duk_idx_t. */
-	vs_size = (duk_idx_t) (thr->valstack_top - thr->valstack_bottom);
-	DUK_ASSERT(vs_size >= 0);
-
-	if (index < 0) {
-		index = vs_size + index;
-		if (DUK_UNLIKELY(index < 0)) {
-			/* Also catches index == DUK_INVALID_INDEX: vs_size >= 0
-			 * so that vs_size + DUK_INVALID_INDEX cannot underflow
-			 * and will always be negative.
-			 */
-			return DUK_INVALID_INDEX;
-		}
-	} else {
-		/* since index non-negative */
-		DUK_ASSERT(index != DUK_INVALID_INDEX);
-
-		if (DUK_UNLIKELY(index >= vs_size)) {
-			return DUK_INVALID_INDEX;
-		}
+DUK_LOCAL const char *duk__get_term_2(duk_small_int_t level) {
+	switch ((int) level) {
+	case DUK_LEVEL_DEBUG:
+		return (const char *) (DUK__TERM_RESET DUK__TERM_BRIGHT);
+	case DUK_LEVEL_DDEBUG:
+		return (const char *) (DUK__TERM_RESET);
+	case DUK_LEVEL_DDDEBUG:
+		return (const char *) (DUK__TERM_RESET DUK__TERM_BLUE);
 	}
-
-	DUK_ASSERT(index >= 0 && index < vs_size);
-	return index;
+	return (const char *) DUK__TERM_RESET;
 }
 
-duk_idx_t duk_require_normalize_index(duk_context *ctx, duk_idx_t index) {
-	duk_hthread *thr = (duk_hthread *) ctx;
-	duk_idx_t vs_size;
-
-	DUK_ASSERT(ctx != NULL);
-	DUK_ASSERT(DUK_INVALID_INDEX < 0);
-
-	vs_size = (duk_idx_t) (thr->valstack_top - thr->valstack_bottom);
-	DUK_ASSERT(vs_size >= 0);
-
-	if (index < 0) {
-		index = vs_size + index;
-		if (DUK_UNLIKELY(index < 0)) {
-			goto invalid_index;
-		}
-	} else {
-		DUK_ASSERT(index != DUK_INVALID_INDEX);
-		if (DUK_UNLIKELY(index >= vs_size)) {
-			goto invalid_index;
-		}
-	}
-
-	DUK_ASSERT(index >= 0 && index < vs_size);
-	return index;
-
- invalid_index:
-	DUK_ERROR(thr, DUK_ERR_API_ERROR, DUK_STR_INVALID_INDEX);
-	return 0;  /* unreachable */
+DUK_LOCAL const char *duk__get_term_3(duk_small_int_t level) {
+	DUK_UNREF(level);
+	return (const char *) DUK__TERM_RESET;
 }
 
-duk_tval *duk_get_tval(duk_context *ctx, duk_idx_t index) {
-	duk_hthread *thr = (duk_hthread *) ctx;
-	duk_idx_t vs_size;
-
-	DUK_ASSERT(ctx != NULL);
-	DUK_ASSERT(DUK_INVALID_INDEX < 0);
-
-	vs_size = (duk_idx_t) (thr->valstack_top - thr->valstack_bottom);
-	DUK_ASSERT(vs_size >= 0);
-
-	if (index < 0) {
-		index = vs_size + index;
-		if (DUK_UNLIKELY(index < 0)) {
-			return NULL;
-		}
-	} else {
-		DUK_ASSERT(index != DUK_INVALID_INDEX);
-		if (DUK_UNLIKELY(index >= vs_size)) {
-			return NULL;
-		}
-	}
+#else
 
-	DUK_ASSERT(index >= 0 && index < vs_size);
-	return thr->valstack_bottom + index;
+DUK_LOCAL const char *duk__get_term_1(duk_small_int_t level) {
+	DUK_UNREF(level);
+	return (const char *) "";
 }
 
-duk_tval *duk_require_tval(duk_context *ctx, duk_idx_t index) {
-	duk_hthread *thr = (duk_hthread *) ctx;
-	duk_idx_t vs_size;
-
-	DUK_ASSERT(ctx != NULL);
-	DUK_ASSERT(DUK_INVALID_INDEX < 0);
-
-	vs_size = (duk_idx_t) (thr->valstack_top - thr->valstack_bottom);
-	DUK_ASSERT(vs_size >= 0);
-
-	if (index < 0) {
-		index = vs_size + index;
-		if (DUK_UNLIKELY(index < 0)) {
-			goto invalid_index;
-		}
-	} else {
-		DUK_ASSERT(index != DUK_INVALID_INDEX);
-		if (DUK_UNLIKELY(index >= vs_size)) {
-			goto invalid_index;
-		}
-	}
-
-	DUK_ASSERT(index >= 0 && index < vs_size);
-	return thr->valstack_bottom + index;
-
- invalid_index:
-	DUK_ERROR(thr, DUK_ERR_API_ERROR, DUK_STR_INVALID_INDEX);
-	return NULL;
+DUK_LOCAL const char *duk__get_term_2(duk_small_int_t level) {
+	DUK_UNREF(level);
+	return (const char *) "";
 }
 
-/* Non-critical. */
-duk_bool_t duk_is_valid_index(duk_context *ctx, duk_idx_t index) {
-	DUK_ASSERT(DUK_INVALID_INDEX < 0);
-	return (duk_normalize_index(ctx, index) >= 0);
+DUK_LOCAL const char *duk__get_term_3(duk_small_int_t level) {
+	DUK_UNREF(level);
+	return (const char *) "";
 }
 
-/* Non-critical. */
-void duk_require_valid_index(duk_context *ctx, duk_idx_t index) {
-	duk_hthread *thr = (duk_hthread *) ctx;
+#endif  /* DUK_USE_DPRINT_COLORS */
 
-	DUK_ASSERT(ctx != NULL);
-	DUK_ASSERT(DUK_INVALID_INDEX < 0);
+#ifdef DUK_USE_VARIADIC_MACROS
 
-	if (duk_normalize_index(ctx, index) < 0) {
-		DUK_ERROR(thr, DUK_ERR_API_ERROR, DUK_STR_INVALID_INDEX);
-	}
-}
+DUK_INTERNAL void duk_debug_log(duk_small_int_t level, const char *file, duk_int_t line, const char *func, const char *fmt, ...) {
+	va_list ap;
 
-/*
- *  Value stack top handling
- */
+	va_start(ap, fmt);
 
-duk_idx_t duk_get_top(duk_context *ctx) {
-	duk_hthread *thr = (duk_hthread *) ctx;
+	DUK_MEMZERO((void *) duk__debug_buf, (size_t) DUK__DEBUG_BUFSIZE);
+	duk_debug_vsnprintf(duk__debug_buf, DUK__DEBUG_BUFSIZE - 1, fmt, ap);
 
-	DUK_ASSERT(ctx != NULL);
+	DUK_FPRINTF(DUK_STDERR, "%s[%s] %s:%ld (%s):%s %s%s\n",
+	            (const char *) duk__get_term_1(level),
+	            (const char *) duk__get_level_string(level),
+	            (const char *) file,
+	            (long) line,
+	            (const char *) func,
+	            (const char *) duk__get_term_2(level),
+	            (const char *) duk__debug_buf,
+	            (const char *) duk__get_term_3(level));
+	DUK_FFLUSH(DUK_STDERR);
 
-	return (duk_idx_t) (thr->valstack_top - thr->valstack_bottom);
+	va_end(ap);
 }
 
-/* set stack top within currently allocated range, but don't reallocate */
-void duk_set_top(duk_context *ctx, duk_idx_t index) {
-	duk_hthread *thr = (duk_hthread *) ctx;
-	duk_idx_t vs_size;
-	duk_idx_t vs_limit;
-	duk_idx_t count;
-	duk_tval tv_tmp;
-	duk_tval *tv;
-
-	DUK_ASSERT(ctx != NULL);
-	DUK_ASSERT(DUK_INVALID_INDEX < 0);
-
-	vs_size = (duk_idx_t) (thr->valstack_top - thr->valstack_bottom);
-	vs_limit = (duk_idx_t) (thr->valstack_end - thr->valstack_bottom);
-
-	if (index < 0) {
-		/* Negative indices are always within allocated stack but
-		 * must not go below zero index.
-		 */
-		index = vs_size + index;
-		if (index < 0) {
-			/* Also catches index == DUK_INVALID_INDEX. */
-			goto invalid_index;
-		}
-	} else {
-		/* Positive index can be higher than valstack top but must
-		 * not go above allocated stack (equality is OK).
-		 */
-		if (index > vs_limit) {
-			goto invalid_index;
-		}
-	}
-	DUK_ASSERT(index >= 0 && index <= vs_limit);
-
-	if (index >= vs_size) {
-		/* Stack size increases or stays the same.  Fill the new
-		 * entries (if any) with undefined.  No pointer stability
-		 * issues here so we can use a running pointer.
-		 */
-
-		tv = thr->valstack_top;
-		count = index - vs_size;
-		DUK_ASSERT(count >= 0);
-		while (count > 0) {
-			/* no need to decref previous or new value */
-			count--;
-			DUK_ASSERT(DUK_TVAL_IS_UNDEFINED_UNUSED(tv));
-			DUK_TVAL_SET_UNDEFINED_ACTUAL(tv);
-			tv++;
-		}
-		thr->valstack_top = tv;
-	} else {
-		/* Stack size decreases, DECREF entries which are above the
-		 * new top.  Each DECREF potentially invalidates valstack
-		 * pointers, so don't hold on to pointers.  The valstack top
-		 * must also be updated on every loop in case a GC is triggered.
-		 */
-
-		/* XXX: Here it would be useful to have a DECREF macro which
-		 * doesn't need a NULL check, and does refzero queueing without
-		 * running the refzero algorithm.  There would be no pointer
-		 * instability in this case, and code could be inlined.  After
-		 * the loop, one call to refzero would be needed.
-		 */
+#else  /* DUK_USE_VARIADIC_MACROS */
 
-		count = vs_size - index;
-		DUK_ASSERT(count > 0);
+DUK_INTERNAL char duk_debug_file_stash[DUK_DEBUG_STASH_SIZE];
+DUK_INTERNAL char duk_debug_line_stash[DUK_DEBUG_STASH_SIZE];
+DUK_INTERNAL char duk_debug_func_stash[DUK_DEBUG_STASH_SIZE];
+DUK_INTERNAL duk_small_int_t duk_debug_level_stash;
 
-		while (count > 0) {
-			count--;
-			tv = --thr->valstack_top;  /* tv -> value just before prev top value */
-			DUK_ASSERT(tv >= thr->valstack_bottom);
-			DUK_TVAL_SET_TVAL(&tv_tmp, tv);
-			DUK_TVAL_SET_UNDEFINED_UNUSED(tv);
-			DUK_TVAL_DECREF(thr, &tv_tmp);  /* side effects */
-		}
-	}
-	return;
+DUK_INTERNAL void duk_debug_log(const char *fmt, ...) {
+	va_list ap;
+	duk_small_int_t level = duk_debug_level_stash;
 
- invalid_index:
-	DUK_ERROR(thr, DUK_ERR_API_ERROR, DUK_STR_INVALID_INDEX);
-}
+	va_start(ap, fmt);
 
-duk_idx_t duk_get_top_index(duk_context *ctx) {
-	duk_hthread *thr = (duk_hthread *) ctx;
-	duk_idx_t ret;
+	DUK_MEMZERO((void *) duk__debug_buf, (size_t) DUK__DEBUG_BUFSIZE);
+	duk_debug_vsnprintf(duk__debug_buf, DUK__DEBUG_BUFSIZE - 1, fmt, ap);
 
-	DUK_ASSERT(ctx != NULL);
+	DUK_FPRINTF(DUK_STDERR, "%s[%s] %s:%s (%s):%s %s%s\n",
+	            (const char *) duk__get_term_1(level),
+	            (const char *) duk__get_level_string(duk_debug_level_stash),
+	            (const char *) duk_debug_file_stash,
+	            (const char *) duk_debug_line_stash,
+	            (const char *) duk_debug_func_stash,
+	            (const char *) duk__get_term_2(level),
+	            (const char *) duk__debug_buf,
+	            (const char *) duk__get_term_3(level));
+	DUK_FFLUSH(DUK_STDERR);
 
-	ret = ((duk_idx_t) (thr->valstack_top - thr->valstack_bottom)) - 1;
-	if (DUK_UNLIKELY(ret < 0)) {
-		/* Return invalid index; if caller uses this without checking
-		 * in another API call, the index won't map to a valid stack
-		 * entry.
-		 */
-		return DUK_INVALID_INDEX;
-	}
-	return ret;
+	va_end(ap);
 }
 
-duk_idx_t duk_require_top_index(duk_context *ctx) {
-	duk_hthread *thr = (duk_hthread *) ctx;
-	duk_idx_t ret;
-
-	DUK_ASSERT(ctx != NULL);
+#endif  /* DUK_USE_VARIADIC_MACROS */
 
-	ret = ((duk_idx_t) (thr->valstack_top - thr->valstack_bottom)) - 1;
-	if (DUK_UNLIKELY(ret < 0)) {
-		DUK_ERROR(thr, DUK_ERR_API_ERROR, DUK_STR_INVALID_INDEX);
-	}
-	return ret;
-}
+#else  /* DUK_USE_DEBUG */
 
 /*
- *  Value stack resizing.
- *
- *  This resizing happens above the current "top": the value stack can be
- *  grown or shrunk, but the "top" is not affected.  The value stack cannot
- *  be resized to a size below the current "top".
- *
- *  The low level reallocation primitive must carefully recompute all value
- *  stack pointers, and must also work if ALL pointers are NULL.  The resize
- *  is quite tricky because the valstack realloc may cause a mark-and-sweep,
- *  which may run finalizers.  Running finalizers may resize the valstack
- *  recursively (the same value stack we're working on).  So, after realloc
- *  returns, we know that the valstack "top" should still be the same (there
- *  should not be live values above the "top"), but its underlying size and
- *  pointer may have changed.
+ *  Debugging disabled
  */
 
-/* XXX: perhaps refactor this to allow caller to specify some parameters, or
- * at least a 'compact' flag which skips any spare or round-up .. useful for
- * emergency gc.
+#endif  /* DUK_USE_DEBUG */
+#line 1 "duk_builtins.c"
+/*
+ *  Automatically generated by genbuiltins.py, do not edit!
  */
 
-static duk_bool_t duk__resize_valstack(duk_context *ctx, duk_size_t new_size) {
-	duk_hthread *thr = (duk_hthread *) ctx;
-	duk_ptrdiff_t old_bottom_offset;
-	duk_ptrdiff_t old_top_offset;
-	duk_ptrdiff_t old_end_offset_post;
-#ifdef DUK_USE_DEBUG
-	duk_ptrdiff_t old_end_offset_pre;
-	duk_tval *old_valstack_pre;
-	duk_tval *old_valstack_post;
-#endif
-	duk_tval *new_valstack;
-	duk_tval *p;
-	duk_size_t new_alloc_size;
-
-	DUK_ASSERT(ctx != NULL);
-	DUK_ASSERT(thr != NULL);
-	DUK_ASSERT(thr->valstack_bottom >= thr->valstack);
-	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
-	DUK_ASSERT(thr->valstack_end >= thr->valstack_top);
-	DUK_ASSERT((duk_size_t) (thr->valstack_top - thr->valstack) <= new_size);  /* can't resize below 'top' */
+/* include removed: duk_internal.h */
 
-	/* get pointer offsets for tweaking below */
-	old_bottom_offset = (((duk_uint8_t *) thr->valstack_bottom) - ((duk_uint8_t *) thr->valstack));
-	old_top_offset = (((duk_uint8_t *) thr->valstack_top) - ((duk_uint8_t *) thr->valstack));
-#ifdef DUK_USE_DEBUG
-	old_end_offset_pre = (((duk_uint8_t *) thr->valstack_end) - ((duk_uint8_t *) thr->valstack));  /* not very useful, used for debugging */
-	old_valstack_pre = thr->valstack;
-#endif
+#if defined(DUK_USE_DOUBLE_LE)
+DUK_INTERNAL const duk_uint8_t duk_strings_data[2624] = {
+55,86,227,24,145,55,102,120,144,3,63,94,228,54,100,137,186,50,11,164,109,
+77,215,5,61,35,106,206,149,110,4,254,219,237,58,8,196,24,103,74,183,2,127,
+103,246,93,4,98,12,47,180,67,103,246,127,101,208,70,32,194,186,134,207,236,
+254,203,160,140,65,133,246,136,108,254,199,237,186,8,196,24,87,80,217,253,
+143,219,116,17,136,49,30,209,13,159,220,116,75,3,30,65,244,17,136,48,174,
+209,13,159,220,116,17,136,48,158,161,179,251,142,130,49,6,17,209,130,96,
+237,80,75,47,160,140,65,142,134,133,41,34,110,134,133,41,34,3,25,110,8,22,
+158,130,38,163,8,217,200,158,76,156,210,117,128,153,203,210,70,46,137,187,
+18,27,164,187,201,209,130,100,55,91,70,4,145,63,66,231,44,128,105,187,41,
+197,13,49,122,8,196,24,71,75,70,138,104,115,77,215,5,36,20,201,214,209,107,
+79,104,209,144,168,105,6,207,251,209,104,209,125,212,227,66,127,235,191,
+239,232,180,90,52,95,69,247,83,141,9,255,174,255,191,162,211,80,210,253,23,
+221,78,52,39,254,183,254,254,139,72,105,126,139,238,167,26,19,255,91,255,
+127,69,166,129,191,69,247,83,141,9,255,175,255,191,162,213,26,50,23,232,
+190,234,113,161,63,245,115,119,86,227,118,83,138,26,98,9,110,48,86,22,148,
+160,152,22,82,70,46,137,44,8,180,163,32,104,98,206,32,17,7,16,88,101,100,
+206,42,70,36,108,205,18,74,140,33,196,230,60,2,152,146,33,38,230,8,36,79,
+182,251,65,156,151,24,200,33,145,162,25,80,209,24,67,0,166,68,52,174,61,73,
+25,33,205,25,27,84,177,195,234,220,1,144,105,99,135,217,16,17,17,208,72,
+199,179,60,93,100,146,49,232,162,64,76,135,19,152,244,44,136,223,98,67,4,
+18,33,247,217,158,36,0,209,190,156,13,26,201,21,111,165,67,64,180,100,145,
+62,250,32,45,100,33,55,214,1,229,223,65,19,72,187,236,206,137,35,125,120,
+190,201,104,105,15,190,201,212,136,136,125,246,160,137,27,83,239,171,37,
+200,218,159,125,168,34,192,61,27,233,93,22,1,114,78,250,28,76,130,112,200,
+93,245,164,188,207,190,204,17,49,38,109,246,160,93,8,119,185,13,153,34,173,
+246,113,0,136,48,76,10,90,26,78,182,140,9,34,130,161,100,235,64,194,9,226,
+44,166,1,41,221,153,226,235,118,120,121,58,72,197,209,63,71,69,76,15,34,
+164,73,244,171,112,39,246,223,104,169,18,125,42,220,9,253,159,217,38,68,
+159,104,134,207,236,254,201,18,36,250,134,207,236,254,201,50,36,251,68,54,
+127,99,246,200,145,39,212,54,127,99,246,200,145,39,218,33,179,251,131,200,
+147,234,27,63,184,81,137,62,149,110,4,254,219,237,20,98,79,165,91,129,63,
+179,251,36,152,147,237,16,217,253,159,217,32,196,159,80,217,253,159,217,36,
+196,159,104,134,207,236,126,217,6,36,250,134,207,236,126,217,6,36,251,68,
+54,127,112,115,18,125,67,103,247,8,149,2,8,196,24,143,131,137,146,90,121,
+35,162,44,140,35,102,160,226,100,235,138,89,18,102,13,10,82,68,200,151,106,
+130,88,131,4,192,73,225,228,85,162,137,147,168,108,252,18,42,209,68,201,
+212,54,126,89,23,104,162,100,245,17,230,207,193,34,237,20,76,158,162,60,
+217,249,100,109,162,137,147,163,117,2,178,120,36,109,162,137,147,163,117,2,
+178,121,100,101,162,137,147,165,91,129,63,4,140,180,81,50,116,171,112,39,
+229,145,150,138,38,78,161,179,251,63,178,240,72,203,69,19,39,80,217,253,
+159,217,121,100,109,162,137,147,212,71,155,63,179,251,47,4,141,180,81,50,
+122,136,243,103,246,127,101,229,145,150,138,38,78,161,179,251,31,182,240,
+72,203,69,19,39,80,217,253,143,219,121,100,109,162,137,147,212,71,155,63,
+177,251,111,4,141,180,81,50,122,136,243,103,246,63,109,229,145,54,138,38,
+78,161,179,251,133,90,40,153,61,68,121,179,251,132,196,128,31,80,217,248,
+36,76,72,1,245,13,159,150,69,68,128,31,168,143,54,126,9,21,18,0,126,162,60,
+217,249,100,100,72,1,244,110,160,86,79,4,140,137,0,62,141,212,10,201,229,
+145,113,32,7,210,173,192,159,130,69,196,128,31,74,183,2,126,89,23,18,0,125,
+67,103,246,127,101,224,145,113,32,7,212,54,127,103,246,94,89,25,18,0,126,
+162,60,217,253,159,217,120,36,100,72,1,250,136,243,103,246,127,101,229,145,
+113,32,7,212,54,127,99,246,222,9,23,18,0,125,67,103,246,63,109,229,145,145,
+32,7,234,35,205,159,216,253,183,130,70,68,128,31,168,143,54,127,99,246,222,
+89,17,18,0,125,67,103,247,9,137,0,63,81,30,108,254,224,130,115,240,98,66,
+128,92,136,84,45,101,180,81,50,28,78,99,193,18,40,56,153,58,178,52,211,58,
+17,46,134,133,41,34,164,75,164,104,156,52,52,199,37,222,232,206,66,64,207,
+18,66,136,137,19,173,62,46,155,181,167,72,147,235,226,233,186,120,121,58,
+226,157,214,111,84,76,73,36,109,24,72,130,100,112,200,178,76,157,124,92,
+242,70,120,25,193,34,245,241,117,240,97,1,107,33,25,212,54,160,90,7,244,29,
+24,38,66,254,223,215,125,119,215,126,232,190,43,226,67,244,1,250,193,125,
+111,216,11,234,254,192,63,96,159,173,234,26,84,53,19,194,126,175,168,105,
+80,212,79,8,234,26,84,53,19,193,156,20,144,83,52,167,20,52,198,109,24,18,
+68,225,115,150,64,53,52,104,200,84,52,131,76,167,20,52,200,46,7,48,52,146,
+132,102,57,33,165,139,168,209,154,32,104,220,193,189,214,27,16,209,176,23,
+26,220,98,149,110,116,70,75,188,98,116,136,34,33,101,4,192,223,178,32,38,6,
+144,18,67,72,1,58,67,0,100,95,74,17,159,217,31,210,132,103,246,58,251,33,
+121,232,55,150,227,125,143,216,16,190,91,141,246,68,31,150,223,178,39,150,
+223,177,251,0,244,135,97,37,32,24,132,104,24,66,161,175,164,202,134,140,
+151,39,212,125,255,221,125,74,86,9,79,168,104,201,116,178,139,154,22,134,
+145,72,51,93,18,116,64,145,13,39,82,34,33,38,73,76,132,185,4,185,187,198,
+100,229,233,197,13,49,228,73,247,4,4,78,98,79,184,32,34,105,187,201,147,
+154,185,187,200,147,165,233,197,13,50,230,239,82,98,151,167,20,52,206,145,
+39,234,76,69,245,22,190,224,128,138,228,73,244,180,90,251,130,2,43,145,39,
+234,76,76,243,155,51,162,68,159,88,230,204,234,145,39,234,76,67,240,38,67,
+200,147,232,193,50,46,68,159,169,49,31,206,164,100,137,18,125,59,169,25,54,
+68,159,169,49,51,200,109,38,73,42,68,159,88,134,210,100,147,100,73,250,147,
+20,188,65,57,163,146,164,73,246,68,19,154,57,74,68,159,169,49,51,200,90,
+209,34,9,205,28,159,34,79,172,66,214,137,16,78,104,228,121,18,125,154,24,
+72,152,147,236,208,194,101,205,39,92,82,200,147,145,137,63,82,98,103,144,
+181,162,68,19,154,57,60,196,159,88,133,173,18,32,156,209,201,166,36,253,73,
+138,94,32,156,209,201,70,36,251,34,9,205,28,154,98,79,212,152,153,228,54,
+147,36,148,98,79,172,67,105,50,73,102,36,253,73,136,254,117,35,36,24,147,
+233,221,72,201,38,36,253,73,136,126,6,12,98,79,163,6,20,98,79,212,152,135,
+224,76,135,49,39,209,130,100,89,137,63,82,98,103,156,217,157,6,36,250,199,
+54,103,113,137,63,82,98,47,168,181,247,4,4,86,98,79,165,162,215,220,16,17,
+57,137,62,205,12,36,166,238,173,194,2,201,217,161,132,236,167,20,52,210,
+155,186,183,8,11,39,70,9,147,178,156,80,211,50,110,236,208,194,118,83,138,
+26,102,77,221,24,38,78,202,113,67,76,54,186,195,245,38,34,188,17,145,23,55,
+117,241,32,145,36,57,173,155,186,75,189,205,35,102,128,44,243,119,74,139,
+144,113,243,221,36,77,21,38,144,210,161,168,158,35,230,144,192,154,42,77,
+33,165,67,81,60,15,173,7,90,159,49,13,213,64,186,17,62,96,47,170,129,116,
+33,165,64,202,113,36,226,134,70,110,234,220,32,44,157,163,222,72,244,64,
+145,23,55,118,143,121,35,209,2,68,140,221,213,184,64,89,58,183,88,145,232,
+129,34,46,110,234,221,98,71,162,4,136,153,80,50,156,80,211,22,79,90,38,105,
+16,17,17,207,18,61,96,17,10,192,76,71,106,220,32,44,157,19,152,240,68,138,
+17,193,30,137,195,39,65,51,8,224,143,65,54,22,46,103,68,112,71,162,112,200,
+184,144,116,17,59,20,24,243,52,72,58,8,134,42,23,50,68,108,3,206,87,71,164,
+0,142,73,57,132,41,42,72,225,107,4,167,212,52,100,191,92,83,161,163,37,250,
+226,158,141,145,208,89,154,79,90,4,66,73,209,153,100,180,8,133,145,208,89,
+158,36,169,35,34,17,244,145,198,247,60,137,114,26,97,57,162,4,206,137,116,
+17,136,48,144,68,212,97,27,57,24,64,90,201,18,5,13,25,4,5,172,160,123,215,
+138,62,46,121,35,60,117,18,233,27,70,18,32,10,200,212,75,175,139,166,233,
+225,228,235,138,227,130,93,117,155,215,197,207,36,103,131,212,11,161,58,
+226,186,110,234,220,32,44,157,148,226,134,153,19,119,101,56,161,166,88,156,
+217,78,52,20,221,17,200,147,25,137,53,17,180,97,34,0,172,140,19,154,84,26,
+145,0,86,68,90,40,152,2,178,22,160,93,8,69,19,18,98,37,210,94,100,108,144,
+21,145,8,151,75,23,100,141,66,37,217,16,11,32,226,248,146,164,108,250,75,
+204,141,146,28,217,24,177,33,50,66,72,128,92,6,66,161,164,235,226,231,146,
+51,65,36,225,144,168,105,58,248,185,228,140,240,97,68,128,153,38,98,79,174,
+179,122,248,185,228,140,241,214,129,132,150,12,73,245,214,111,95,23,60,145,
+158,58,50,72,81,67,230,232,184,196,159,95,23,77,211,195,201,215,21,47,139,
+166,233,225,228,50,200,211,76,229,2,201,25,149,241,67,102,138,52,146,16,30,
+67,18,66,3,201,34,52,78,25,61,72,160,94,115,30,230,145,179,73,26,39,12,158,
+164,81,33,144,78,25,61,72,160,94,115,30,230,145,179,72,200,39,12,158,164,
+80,132,75,165,67,81,50,21,18,235,65,214,169,224,140,137,210,173,192,154,30,
+8,200,157,67,102,66,84,11,71,169,20,19,209,139,162,158,207,15,39,73,24,186,
+43,236,176,217,130,253,36,98,232,187,177,33,73,18,52,68,233,35,23,69,93,
+136,26,98,116,145,139,162,158,146,160,95,73,24,186,37,12,72,5,16,64,145,10,
+32,76,71,64,156,217,161,180,34,6,64,208,198,36,78,50,20,20,92,204,50,44,
+147,32,134,226,17,114,33,202,134,129,107,192,202,232,160,180,104,166,135,
+52,72,40,144,213,33,178,152,26,34,56,163,105,44,104,146,116,139,77,43,34,
+98,57,38,116,72,179,60,93,97,206,56,52,240,242,56,163,168,34,81,57,178,153,
+42,228,12,182,58,22,66,89,19,57,68,176,74,68,35,104,195,18,239,116,102,114,
+94,100,104,228,100,49,238,140,203,42,60,145,35,104,181,146,113,161,10,80,
+46,68,82,24,245,145,132,108,228,148,54,100,137,64,34,13,100,153,222,1,40,6,
+33,223,20,84,19,34,95,23,76,130,153,6,103,208,43,64,141,41,130,104,17,112,
+130,44,96,
+};
+
+/* to convert a heap stridx to a token number, subtract
+ * DUK_STRIDX_START_RESERVED and add DUK_TOK_START_RESERVED.
+ */
+
+/* native functions: 149 */
+DUK_INTERNAL const duk_c_function duk_bi_native_functions[149] = {
+	duk_bi_array_constructor,
+	duk_bi_array_constructor_is_array,
+	duk_bi_array_prototype_concat,
+	duk_bi_array_prototype_indexof_shared,
+	duk_bi_array_prototype_iter_shared,
+	duk_bi_array_prototype_join_shared,
+	duk_bi_array_prototype_pop,
+	duk_bi_array_prototype_push,
+	duk_bi_array_prototype_reduce_shared,
+	duk_bi_array_prototype_reverse,
+	duk_bi_array_prototype_shift,
+	duk_bi_array_prototype_slice,
+	duk_bi_array_prototype_sort,
+	duk_bi_array_prototype_splice,
+	duk_bi_array_prototype_to_string,
+	duk_bi_array_prototype_unshift,
+	duk_bi_arraybuffer_constructor,
+	duk_bi_arraybuffer_isview,
+	duk_bi_boolean_constructor,
+	duk_bi_boolean_prototype_tostring_shared,
+	duk_bi_buffer_compare_shared,
+	duk_bi_buffer_constructor,
+	duk_bi_buffer_prototype_tostring_shared,
+	duk_bi_buffer_readfield,
+	duk_bi_buffer_slice_shared,
+	duk_bi_buffer_writefield,
+	duk_bi_dataview_constructor,
+	duk_bi_date_constructor,
+	duk_bi_date_constructor_now,
+	duk_bi_date_constructor_parse,
+	duk_bi_date_constructor_utc,
+	duk_bi_date_prototype_get_shared,
+	duk_bi_date_prototype_get_timezone_offset,
+	duk_bi_date_prototype_set_shared,
+	duk_bi_date_prototype_set_time,
+	duk_bi_date_prototype_to_json,
+	duk_bi_date_prototype_tostring_shared,
+	duk_bi_date_prototype_value_of,
+	duk_bi_duktape_object_act,
+	duk_bi_duktape_object_compact,
+	duk_bi_duktape_object_dec,
+	duk_bi_duktape_object_enc,
+	duk_bi_duktape_object_fin,
+	duk_bi_duktape_object_gc,
+	duk_bi_duktape_object_info,
+	duk_bi_error_constructor_shared,
+	duk_bi_error_prototype_filename_getter,
+	duk_bi_error_prototype_filename_setter,
+	duk_bi_error_prototype_linenumber_getter,
+	duk_bi_error_prototype_linenumber_setter,
+	duk_bi_error_prototype_stack_getter,
+	duk_bi_error_prototype_stack_setter,
+	duk_bi_error_prototype_to_string,
+	duk_bi_function_constructor,
+	duk_bi_function_prototype,
+	duk_bi_function_prototype_apply,
+	duk_bi_function_prototype_bind,
+	duk_bi_function_prototype_call,
+	duk_bi_function_prototype_to_string,
+	duk_bi_global_object_decode_uri,
+	duk_bi_global_object_decode_uri_component,
+	duk_bi_global_object_encode_uri,
+	duk_bi_global_object_encode_uri_component,
+	duk_bi_global_object_escape,
+	duk_bi_global_object_eval,
+	duk_bi_global_object_is_finite,
+	duk_bi_global_object_is_nan,
+	duk_bi_global_object_parse_float,
+	duk_bi_global_object_parse_int,
+	duk_bi_global_object_print_helper,
+	duk_bi_global_object_require,
+	duk_bi_global_object_unescape,
+	duk_bi_json_object_parse,
+	duk_bi_json_object_stringify,
+	duk_bi_logger_constructor,
+	duk_bi_logger_prototype_fmt,
+	duk_bi_logger_prototype_log_shared,
+	duk_bi_logger_prototype_raw,
+	duk_bi_math_object_max,
+	duk_bi_math_object_min,
+	duk_bi_math_object_onearg_shared,
+	duk_bi_math_object_random,
+	duk_bi_math_object_twoarg_shared,
+	duk_bi_nodejs_buffer_byte_length,
+	duk_bi_nodejs_buffer_concat,
+	duk_bi_nodejs_buffer_constructor,
+	duk_bi_nodejs_buffer_copy,
+	duk_bi_nodejs_buffer_fill,
+	duk_bi_nodejs_buffer_is_buffer,
+	duk_bi_nodejs_buffer_is_encoding,
+	duk_bi_nodejs_buffer_tojson,
+	duk_bi_nodejs_buffer_tostring,
+	duk_bi_nodejs_buffer_write,
+	duk_bi_number_constructor,
+	duk_bi_number_prototype_to_exponential,
+	duk_bi_number_prototype_to_fixed,
+	duk_bi_number_prototype_to_locale_string,
+	duk_bi_number_prototype_to_precision,
+	duk_bi_number_prototype_to_string,
+	duk_bi_number_prototype_value_of,
+	duk_bi_object_constructor,
+	duk_bi_object_constructor_create,
+	duk_bi_object_constructor_define_properties,
+	duk_bi_object_constructor_define_property,
+	duk_bi_object_constructor_get_own_property_descriptor,
+	duk_bi_object_constructor_is_extensible,
+	duk_bi_object_constructor_is_sealed_frozen_shared,
+	duk_bi_object_constructor_keys_shared,
+	duk_bi_object_constructor_prevent_extensions,
+	duk_bi_object_constructor_seal_freeze_shared,
+	duk_bi_object_getprototype_shared,
+	duk_bi_object_prototype_has_own_property,
+	duk_bi_object_prototype_is_prototype_of,
+	duk_bi_object_prototype_property_is_enumerable,
+	duk_bi_object_prototype_to_locale_string,
+	duk_bi_object_prototype_to_string,
+	duk_bi_object_prototype_value_of,
+	duk_bi_object_setprototype_shared,
+	duk_bi_pointer_constructor,
+	duk_bi_pointer_prototype_tostring_shared,
+	duk_bi_proxy_constructor,
+	duk_bi_regexp_constructor,
+	duk_bi_regexp_prototype_exec,
+	duk_bi_regexp_prototype_test,
+	duk_bi_regexp_prototype_to_string,
+	duk_bi_string_constructor,
+	duk_bi_string_constructor_from_char_code,
+	duk_bi_string_prototype_caseconv_shared,
+	duk_bi_string_prototype_char_at,
+	duk_bi_string_prototype_char_code_at,
+	duk_bi_string_prototype_concat,
+	duk_bi_string_prototype_indexof_shared,
+	duk_bi_string_prototype_locale_compare,
+	duk_bi_string_prototype_match,
+	duk_bi_string_prototype_replace,
+	duk_bi_string_prototype_search,
+	duk_bi_string_prototype_slice,
+	duk_bi_string_prototype_split,
+	duk_bi_string_prototype_substr,
+	duk_bi_string_prototype_substring,
+	duk_bi_string_prototype_to_string,
+	duk_bi_string_prototype_trim,
+	duk_bi_thread_constructor,
+	duk_bi_thread_current,
+	duk_bi_thread_resume,
+	duk_bi_thread_yield,
+	duk_bi_type_error_thrower,
+	duk_bi_typedarray_constructor,
+	duk_bi_typedarray_set,
+};
+
+DUK_INTERNAL const duk_uint8_t duk_builtins_data[1955] = {
+105,195,75,32,121,40,105,53,14,252,104,54,8,131,72,0,115,225,65,165,244,55,
+243,6,145,32,210,24,210,186,25,249,35,120,216,99,226,13,79,33,116,177,164,
+180,44,192,4,202,52,150,220,24,0,169,70,146,219,123,0,23,40,210,91,110,96,
+3,37,26,75,109,172,0,108,163,73,109,177,128,14,148,105,45,181,176,1,242,
+144,56,209,36,94,6,167,133,98,80,211,28,1,250,67,72,168,67,232,13,46,192,
+47,162,52,165,0,62,80,163,72,128,61,40,107,26,7,37,20,53,201,131,88,0,66,
+134,185,48,98,80,215,38,11,96,0,138,26,228,193,76,0,69,67,92,152,37,128,6,
+168,107,147,4,48,1,165,13,114,96,118,0,44,161,174,76,12,192,7,148,53,201,
+129,88,1,26,134,165,80,130,80,31,255,241,69,224,0,0,0,0,0,0,124,63,174,32,
+0,0,0,0,0,0,120,63,175,98,7,140,16,116,194,7,12,48,108,196,6,140,80,100,
+198,6,12,112,92,200,5,140,149,192,202,91,204,181,184,204,91,76,213,176,206,
+90,204,240,84,208,5,13,9,124,210,43,13,24,64,226,131,205,112,56,216,3,77,
+152,48,218,130,205,184,40,220,130,77,216,32,222,129,205,248,24,224,129,78,
+25,214,164,2,90,81,17,104,67,37,157,8,150,100,18,89,78,201,100,60,37,140,
+244,150,35,226,88,79,201,96,71,37,125,20,122,188,138,62,0,2,165,70,39,255,
+255,193,43,67,0,0,80,127,192,58,182,220,80,0,21,59,170,64,0,107,77,8,172,
+181,146,176,202,138,187,59,42,204,200,170,182,146,168,218,80,0,26,155,97,
+42,77,68,168,181,20,0,6,160,210,74,123,89,64,0,127,255,4,10,153,219,157,70,
+163,185,130,140,228,10,43,160,40,141,228,161,184,18,132,226,64,161,127,128,
+0,63,225,1,109,74,8,137,71,58,5,4,221,20,3,147,233,249,193,240,80,255,192,
+6,120,2,64,127,195,0,173,28,56,20,96,80,128,0,206,192,143,167,64,164,156,
+131,2,112,14,125,55,9,4,216,40,19,80,180,77,3,9,51,13,94,153,7,159,76,64,
+207,192,0,102,0,103,255,255,242,240,67,73,112,33,168,0,12,180,16,212,0,10,
+88,8,106,0,7,43,4,53,0,4,149,4,31,128,0,202,66,15,255,255,194,137,254,0,50,
+135,227,224,127,196,2,87,132,17,82,143,24,10,44,96,36,240,4,147,64,146,119,
+4,125,49,131,52,152,65,154,128,0,201,97,9,36,133,36,142,25,18,40,114,77,98,
+17,33,137,68,130,45,17,247,240,71,159,193,29,127,8,0,12,113,252,32,0,49,
+184,208,70,162,144,20,95,240,0,7,252,80,37,120,193,81,196,194,0,3,69,19,0,
+81,191,197,140,192,255,255,255,255,255,255,239,127,140,64,1,0,0,0,0,0,0,0,
+139,192,0,0,0,0,0,0,248,127,138,192,0,0,0,0,0,0,240,127,139,64,0,0,0,0,0,0,
+240,255,0,31,241,128,149,224,0,0,0,0,0,0,0,0,13,71,98,37,25,128,148,86,48,
+69,23,201,19,94,36,73,132,129,71,255,0,56,136,233,34,3,223,208,241,192,3,
+254,56,18,188,128,0,0,0,0,0,15,135,251,104,228,128,135,18,4,0,6,26,72,16,0,
+42,49,32,64,0,225,132,129,0,4,133,146,4,0,21,210,72,16,0,103,65,32,64,1,
+220,228,100,162,146,130,20,74,8,72,248,64,2,33,3,225,0,9,131,143,132,0,42,
+12,62,16,0,184,40,248,64,3,32,131,225,0,13,129,143,132,0,58,4,62,16,0,248,
+8,248,64,4,32,3,225,0,17,127,143,132,0,73,252,62,16,1,55,232,248,64,5,31,
+131,225,0,21,125,143,132,0,89,244,62,16,1,119,201,0,31,4,68,123,144,148,0,
+97,236,66,80,1,151,169,10,248,0,211,208,133,124,0,109,230,66,254,0,56,242,
+33,127,0,29,120,144,207,128,15,60,8,103,192,7,221,228,37,0,32,119,16,148,0,
+133,218,66,190,0,68,236,33,95,0,35,117,144,191,128,18,58,136,95,192,9,92,
+195,225,0,38,114,144,148,0,156,41,31,224,0,15,249,1,138,144,65,192,2,22,0,
+88,16,46,24,77,208,148,103,4,102,252,102,244,128,0,0,0,0,0,0,0,0,220,111,
+68,113,61,146,142,248,0,164,255,128,0,63,228,133,109,16,89,178,65,18,235,
+153,25,150,220,184,188,180,230,6,32,209,205,0,20,175,240,0,39,252,160,77,
+162,184,54,72,34,0,82,255,192,0,159,242,193,54,138,222,217,32,136,1,76,255,
+0,2,127,204,4,218,43,115,100,130,32,5,55,252,0,9,255,52,19,104,173,173,146,
+8,128,20,239,240,0,39,252,224,77,162,182,54,72,34,0,83,255,192,0,159,243,
+193,54,138,214,217,32,136,0,255,255,33,177,1,165,92,82,44,42,252,21,1,175,
+0,89,86,214,238,197,172,9,1,173,3,188,231,235,249,8,187,152,253,171,3,250,
+8,173,149,28,87,220,253,169,0,59,148,152,85,239,47,108,253,167,0,96,181,17,
+83,236,132,37,1,165,3,52,237,253,154,122,131,152,253,163,3,52,237,253,154,
+122,131,216,253,38,130,129,25,234,5,0,1,103,40,20,0,9,154,160,80,0,54,98,
+146,25,106,5,0,4,101,40,20,0,21,146,160,80,0,102,66,129,64,1,216,234,5,0,8,
+99,39,47,49,83,215,152,138,73,0,1,97,168,129,132,160,80,0,150,10,129,64,2,
+152,10,5,0,11,95,168,20,0,48,31,255,224,5,17,72,66,249,37,129,127,255,0,0,
+191,255,128,0,63,255,197,31,192,0,0,0,0,0,80,196,64,8,26,112,17,169,0,154,
+80,1,171,28,124,88,65,233,49,7,133,100,29,149,15,14,138,71,135,37,3,195,66,
+114,5,77,252,0,243,178,40,25,200,48,101,30,0,127,210,128,0,85,31,192,0,31,
+244,224,5,71,22,8,0,13,20,88,1,85,127,0,0,127,212,128,21,29,220,32,0,52,87,
+112,5,89,252,0,1,255,86,16,166,64,0,0,0,0,0,0,2,0,170,72,38,29,219,247,16,
+49,75,32,193,52,130,244,193,225,114,96,248,0,8,249,48,124,0,8,90,152,62,0,
+6,44,76,31,0,4,21,166,15,128,2,147,255,252,38,212,16,184,155,250,226,217,
+150,47,46,91,249,54,96,139,229,229,203,127,36,26,119,32,203,203,150,254,72,
+52,97,221,147,102,157,217,192,10,191,248,0,157,4,72,15,250,224,1,154,140,
+36,0,8,43,31,224,0,15,251,0,16,55,139,164,0,192,220,46,144,2,3,104,186,64,
+12,77,130,233,0,33,53,139,164,0,200,212,46,144,2,35,72,186,64,8,205,2,233,
+0,36,51,140,180,0,192,204,50,208,2,3,40,203,64,12,76,131,45,0,33,49,140,
+180,0,200,196,50,208,2,35,8,203,64,8,204,3,45,0,36,7,255,248,1,82,101,16,
+112,24,72,0,8,86,159,193,56,192,0,0,0,0,0,0,240,63,1,151,246,96,0,21,183,
+240,78,48,0,0,0,0,0,0,60,15,192,101,253,168,0,5,113,252,19,140,0,0,0,0,0,0,
+15,3,240,25,127,110,0,1,93,127,4,227,0,0,0,0,0,0,0,1,0,6,95,220,128,0,87,
+159,193,56,192,0,0,0,0,0,0,0,64,1,151,247,96,0,21,247,240,78,48,0,0,0,0,0,
+0,4,16,0,101,253,232,0,5,129,252,19,140,0,0,0,0,0,0,1,4,0,25,127,126,0,1,
+97,127,4,227,0,0,0,0,0,0,0,65,0,6,95,224,128,0,88,159,193,56,192,0,0,0,0,0,
+0,32,64,1,151,248,96,0,22,55,240,5,157,170,33,68,178,69,10,193,20,10,104,
+79,138,36,0,12,31,248,160,88,154,23,66,100,93,32,2,9,129,116,128,0,165,197,
+210,0,18,150,23,72,0,138,84,93,32,3,41,65,116,128,1,36,197,210,0,20,146,23,
+72,0,146,68,93,32,3,73,1,116,128,1,163,197,210,0,22,142,23,72,0,34,52,93,
+32,1,136,193,118,128,2,162,197,218,0,26,138,23,104,0,170,36,93,160,3,168,
+129,150,33,198,90,0,32,134,25,104,0,10,20,101,160,1,40,65,150,128,8,160,
+198,90,0,50,130,25,104,0,18,4,101,160,1,72,1,150,128,9,31,198,90,0,52,126,
+25,104,0,25,244,101,160,1,103,193,150,128,2,30,198,90,0,24,122,25,136,0,41,
+228,102,32,1,167,129,152,128,10,157,198,98,0,59,71,91,99,157,104,9,213,118,
+39,5,8,159,20,40,0,10,109,90,19,81,132,39,151,32,
+};
+#ifdef DUK_USE_BUILTIN_INITJS
+DUK_INTERNAL const duk_uint8_t duk_initjs_data[187] = {
+40,102,117,110,99,116,105,111,110,40,100,44,97,41,123,102,117,110,99,116,
+105,111,110,32,98,40,97,44,98,44,99,41,123,79,98,106,101,99,116,46,100,101,
+102,105,110,101,80,114,111,112,101,114,116,121,40,97,44,98,44,123,118,97,
+108,117,101,58,99,44,119,114,105,116,97,98,108,101,58,33,48,44,101,110,117,
+109,101,114,97,98,108,101,58,33,49,44,99,111,110,102,105,103,117,114,97,98,
+108,101,58,33,48,125,41,125,98,40,97,46,76,111,103,103,101,114,44,34,99,
+108,111,103,34,44,110,101,119,32,97,46,76,111,103,103,101,114,40,34,67,34,
+41,41,59,98,40,97,44,34,109,111,100,76,111,97,100,101,100,34,44,123,125,41,
+125,41,40,116,104,105,115,44,68,117,107,116,97,112,101,41,59,10,0,
+};
+#endif  /* DUK_USE_BUILTIN_INITJS */
+#elif defined(DUK_USE_DOUBLE_BE)
+DUK_INTERNAL const duk_uint8_t duk_strings_data[2624] = {
+55,86,227,24,145,55,102,120,144,3,63,94,228,54,100,137,186,50,11,164,109,
+77,215,5,61,35,106,206,149,110,4,254,219,237,58,8,196,24,103,74,183,2,127,
+103,246,93,4,98,12,47,180,67,103,246,127,101,208,70,32,194,186,134,207,236,
+254,203,160,140,65,133,246,136,108,254,199,237,186,8,196,24,87,80,217,253,
+143,219,116,17,136,49,30,209,13,159,220,116,75,3,30,65,244,17,136,48,174,
+209,13,159,220,116,17,136,48,158,161,179,251,142,130,49,6,17,209,130,96,
+237,80,75,47,160,140,65,142,134,133,41,34,110,134,133,41,34,3,25,110,8,22,
+158,130,38,163,8,217,200,158,76,156,210,117,128,153,203,210,70,46,137,187,
+18,27,164,187,201,209,130,100,55,91,70,4,145,63,66,231,44,128,105,187,41,
+197,13,49,122,8,196,24,71,75,70,138,104,115,77,215,5,36,20,201,214,209,107,
+79,104,209,144,168,105,6,207,251,209,104,209,125,212,227,66,127,235,191,
+239,232,180,90,52,95,69,247,83,141,9,255,174,255,191,162,211,80,210,253,23,
+221,78,52,39,254,183,254,254,139,72,105,126,139,238,167,26,19,255,91,255,
+127,69,166,129,191,69,247,83,141,9,255,175,255,191,162,213,26,50,23,232,
+190,234,113,161,63,245,115,119,86,227,118,83,138,26,98,9,110,48,86,22,148,
+160,152,22,82,70,46,137,44,8,180,163,32,104,98,206,32,17,7,16,88,101,100,
+206,42,70,36,108,205,18,74,140,33,196,230,60,2,152,146,33,38,230,8,36,79,
+182,251,65,156,151,24,200,33,145,162,25,80,209,24,67,0,166,68,52,174,61,73,
+25,33,205,25,27,84,177,195,234,220,1,144,105,99,135,217,16,17,17,208,72,
+199,179,60,93,100,146,49,232,162,64,76,135,19,152,244,44,136,223,98,67,4,
+18,33,247,217,158,36,0,209,190,156,13,26,201,21,111,165,67,64,180,100,145,
+62,250,32,45,100,33,55,214,1,229,223,65,19,72,187,236,206,137,35,125,120,
+190,201,104,105,15,190,201,212,136,136,125,246,160,137,27,83,239,171,37,
+200,218,159,125,168,34,192,61,27,233,93,22,1,114,78,250,28,76,130,112,200,
+93,245,164,188,207,190,204,17,49,38,109,246,160,93,8,119,185,13,153,34,173,
+246,113,0,136,48,76,10,90,26,78,182,140,9,34,130,161,100,235,64,194,9,226,
+44,166,1,41,221,153,226,235,118,120,121,58,72,197,209,63,71,69,76,15,34,
+164,73,244,171,112,39,246,223,104,169,18,125,42,220,9,253,159,217,38,68,
+159,104,134,207,236,254,201,18,36,250,134,207,236,254,201,50,36,251,68,54,
+127,99,246,200,145,39,212,54,127,99,246,200,145,39,218,33,179,251,131,200,
+147,234,27,63,184,81,137,62,149,110,4,254,219,237,20,98,79,165,91,129,63,
+179,251,36,152,147,237,16,217,253,159,217,32,196,159,80,217,253,159,217,36,
+196,159,104,134,207,236,126,217,6,36,250,134,207,236,126,217,6,36,251,68,
+54,127,112,115,18,125,67,103,247,8,149,2,8,196,24,143,131,137,146,90,121,
+35,162,44,140,35,102,160,226,100,235,138,89,18,102,13,10,82,68,200,151,106,
+130,88,131,4,192,73,225,228,85,162,137,147,168,108,252,18,42,209,68,201,
+212,54,126,89,23,104,162,100,245,17,230,207,193,34,237,20,76,158,162,60,
+217,249,100,109,162,137,147,163,117,2,178,120,36,109,162,137,147,163,117,2,
+178,121,100,101,162,137,147,165,91,129,63,4,140,180,81,50,116,171,112,39,
+229,145,150,138,38,78,161,179,251,63,178,240,72,203,69,19,39,80,217,253,
+159,217,121,100,109,162,137,147,212,71,155,63,179,251,47,4,141,180,81,50,
+122,136,243,103,246,127,101,229,145,150,138,38,78,161,179,251,31,182,240,
+72,203,69,19,39,80,217,253,143,219,121,100,109,162,137,147,212,71,155,63,
+177,251,111,4,141,180,81,50,122,136,243,103,246,63,109,229,145,54,138,38,
+78,161,179,251,133,90,40,153,61,68,121,179,251,132,196,128,31,80,217,248,
+36,76,72,1,245,13,159,150,69,68,128,31,168,143,54,126,9,21,18,0,126,162,60,
+217,249,100,100,72,1,244,110,160,86,79,4,140,137,0,62,141,212,10,201,229,
+145,113,32,7,210,173,192,159,130,69,196,128,31,74,183,2,126,89,23,18,0,125,
+67,103,246,127,101,224,145,113,32,7,212,54,127,103,246,94,89,25,18,0,126,
+162,60,217,253,159,217,120,36,100,72,1,250,136,243,103,246,127,101,229,145,
+113,32,7,212,54,127,99,246,222,9,23,18,0,125,67,103,246,63,109,229,145,145,
+32,7,234,35,205,159,216,253,183,130,70,68,128,31,168,143,54,127,99,246,222,
+89,17,18,0,125,67,103,247,9,137,0,63,81,30,108,254,224,130,115,240,98,66,
+128,92,136,84,45,101,180,81,50,28,78,99,193,18,40,56,153,58,178,52,211,58,
+17,46,134,133,41,34,164,75,164,104,156,52,52,199,37,222,232,206,66,64,207,
+18,66,136,137,19,173,62,46,155,181,167,72,147,235,226,233,186,120,121,58,
+226,157,214,111,84,76,73,36,109,24,72,130,100,112,200,178,76,157,124,92,
+242,70,120,25,193,34,245,241,117,240,97,1,107,33,25,212,54,160,90,7,244,29,
+24,38,66,254,223,215,125,119,215,126,232,190,43,226,67,244,1,250,193,125,
+111,216,11,234,254,192,63,96,159,173,234,26,84,53,19,194,126,175,168,105,
+80,212,79,8,234,26,84,53,19,193,156,20,144,83,52,167,20,52,198,109,24,18,
+68,225,115,150,64,53,52,104,200,84,52,131,76,167,20,52,200,46,7,48,52,146,
+132,102,57,33,165,139,168,209,154,32,104,220,193,189,214,27,16,209,176,23,
+26,220,98,149,110,116,70,75,188,98,116,136,34,33,101,4,192,223,178,32,38,6,
+144,18,67,72,1,58,67,0,100,95,74,17,159,217,31,210,132,103,246,58,251,33,
+121,232,55,150,227,125,143,216,16,190,91,141,246,68,31,150,223,178,39,150,
+223,177,251,0,244,135,97,37,32,24,132,104,24,66,161,175,164,202,134,140,
+151,39,212,125,255,221,125,74,86,9,79,168,104,201,116,178,139,154,22,134,
+145,72,51,93,18,116,64,145,13,39,82,34,33,38,73,76,132,185,4,185,187,198,
+100,229,233,197,13,49,228,73,247,4,4,78,98,79,184,32,34,105,187,201,147,
+154,185,187,200,147,165,233,197,13,50,230,239,82,98,151,167,20,52,206,145,
+39,234,76,69,245,22,190,224,128,138,228,73,244,180,90,251,130,2,43,145,39,
+234,76,76,243,155,51,162,68,159,88,230,204,234,145,39,234,76,67,240,38,67,
+200,147,232,193,50,46,68,159,169,49,31,206,164,100,137,18,125,59,169,25,54,
+68,159,169,49,51,200,109,38,73,42,68,159,88,134,210,100,147,100,73,250,147,
+20,188,65,57,163,146,164,73,246,68,19,154,57,74,68,159,169,49,51,200,90,
+209,34,9,205,28,159,34,79,172,66,214,137,16,78,104,228,121,18,125,154,24,
+72,152,147,236,208,194,101,205,39,92,82,200,147,145,137,63,82,98,103,144,
+181,162,68,19,154,57,60,196,159,88,133,173,18,32,156,209,201,166,36,253,73,
+138,94,32,156,209,201,70,36,251,34,9,205,28,154,98,79,212,152,153,228,54,
+147,36,148,98,79,172,67,105,50,73,102,36,253,73,136,254,117,35,36,24,147,
+233,221,72,201,38,36,253,73,136,126,6,12,98,79,163,6,20,98,79,212,152,135,
+224,76,135,49,39,209,130,100,89,137,63,82,98,103,156,217,157,6,36,250,199,
+54,103,113,137,63,82,98,47,168,181,247,4,4,86,98,79,165,162,215,220,16,17,
+57,137,62,205,12,36,166,238,173,194,2,201,217,161,132,236,167,20,52,210,
+155,186,183,8,11,39,70,9,147,178,156,80,211,50,110,236,208,194,118,83,138,
+26,102,77,221,24,38,78,202,113,67,76,54,186,195,245,38,34,188,17,145,23,55,
+117,241,32,145,36,57,173,155,186,75,189,205,35,102,128,44,243,119,74,139,
+144,113,243,221,36,77,21,38,144,210,161,168,158,35,230,144,192,154,42,77,
+33,165,67,81,60,15,173,7,90,159,49,13,213,64,186,17,62,96,47,170,129,116,
+33,165,64,202,113,36,226,134,70,110,234,220,32,44,157,163,222,72,244,64,
+145,23,55,118,143,121,35,209,2,68,140,221,213,184,64,89,58,183,88,145,232,
+129,34,46,110,234,221,98,71,162,4,136,153,80,50,156,80,211,22,79,90,38,105,
+16,17,17,207,18,61,96,17,10,192,76,71,106,220,32,44,157,19,152,240,68,138,
+17,193,30,137,195,39,65,51,8,224,143,65,54,22,46,103,68,112,71,162,112,200,
+184,144,116,17,59,20,24,243,52,72,58,8,134,42,23,50,68,108,3,206,87,71,164,
+0,142,73,57,132,41,42,72,225,107,4,167,212,52,100,191,92,83,161,163,37,250,
+226,158,141,145,208,89,154,79,90,4,66,73,209,153,100,180,8,133,145,208,89,
+158,36,169,35,34,17,244,145,198,247,60,137,114,26,97,57,162,4,206,137,116,
+17,136,48,144,68,212,97,27,57,24,64,90,201,18,5,13,25,4,5,172,160,123,215,
+138,62,46,121,35,60,117,18,233,27,70,18,32,10,200,212,75,175,139,166,233,
+225,228,235,138,227,130,93,117,155,215,197,207,36,103,131,212,11,161,58,
+226,186,110,234,220,32,44,157,148,226,134,153,19,119,101,56,161,166,88,156,
+217,78,52,20,221,17,200,147,25,137,53,17,180,97,34,0,172,140,19,154,84,26,
+145,0,86,68,90,40,152,2,178,22,160,93,8,69,19,18,98,37,210,94,100,108,144,
+21,145,8,151,75,23,100,141,66,37,217,16,11,32,226,248,146,164,108,250,75,
+204,141,146,28,217,24,177,33,50,66,72,128,92,6,66,161,164,235,226,231,146,
+51,65,36,225,144,168,105,58,248,185,228,140,240,97,68,128,153,38,98,79,174,
+179,122,248,185,228,140,241,214,129,132,150,12,73,245,214,111,95,23,60,145,
+158,58,50,72,81,67,230,232,184,196,159,95,23,77,211,195,201,215,21,47,139,
+166,233,225,228,50,200,211,76,229,2,201,25,149,241,67,102,138,52,146,16,30,
+67,18,66,3,201,34,52,78,25,61,72,160,94,115,30,230,145,179,73,26,39,12,158,
+164,81,33,144,78,25,61,72,160,94,115,30,230,145,179,72,200,39,12,158,164,
+80,132,75,165,67,81,50,21,18,235,65,214,169,224,140,137,210,173,192,154,30,
+8,200,157,67,102,66,84,11,71,169,20,19,209,139,162,158,207,15,39,73,24,186,
+43,236,176,217,130,253,36,98,232,187,177,33,73,18,52,68,233,35,23,69,93,
+136,26,98,116,145,139,162,158,146,160,95,73,24,186,37,12,72,5,16,64,145,10,
+32,76,71,64,156,217,161,180,34,6,64,208,198,36,78,50,20,20,92,204,50,44,
+147,32,134,226,17,114,33,202,134,129,107,192,202,232,160,180,104,166,135,
+52,72,40,144,213,33,178,152,26,34,56,163,105,44,104,146,116,139,77,43,34,
+98,57,38,116,72,179,60,93,97,206,56,52,240,242,56,163,168,34,81,57,178,153,
+42,228,12,182,58,22,66,89,19,57,68,176,74,68,35,104,195,18,239,116,102,114,
+94,100,104,228,100,49,238,140,203,42,60,145,35,104,181,146,113,161,10,80,
+46,68,82,24,245,145,132,108,228,148,54,100,137,64,34,13,100,153,222,1,40,6,
+33,223,20,84,19,34,95,23,76,130,153,6,103,208,43,64,141,41,130,104,17,112,
+130,44,96,
+};
+
+/* to convert a heap stridx to a token number, subtract
+ * DUK_STRIDX_START_RESERVED and add DUK_TOK_START_RESERVED.
+ */
+
+/* native functions: 149 */
+DUK_INTERNAL const duk_c_function duk_bi_native_functions[149] = {
+	duk_bi_array_constructor,
+	duk_bi_array_constructor_is_array,
+	duk_bi_array_prototype_concat,
+	duk_bi_array_prototype_indexof_shared,
+	duk_bi_array_prototype_iter_shared,
+	duk_bi_array_prototype_join_shared,
+	duk_bi_array_prototype_pop,
+	duk_bi_array_prototype_push,
+	duk_bi_array_prototype_reduce_shared,
+	duk_bi_array_prototype_reverse,
+	duk_bi_array_prototype_shift,
+	duk_bi_array_prototype_slice,
+	duk_bi_array_prototype_sort,
+	duk_bi_array_prototype_splice,
+	duk_bi_array_prototype_to_string,
+	duk_bi_array_prototype_unshift,
+	duk_bi_arraybuffer_constructor,
+	duk_bi_arraybuffer_isview,
+	duk_bi_boolean_constructor,
+	duk_bi_boolean_prototype_tostring_shared,
+	duk_bi_buffer_compare_shared,
+	duk_bi_buffer_constructor,
+	duk_bi_buffer_prototype_tostring_shared,
+	duk_bi_buffer_readfield,
+	duk_bi_buffer_slice_shared,
+	duk_bi_buffer_writefield,
+	duk_bi_dataview_constructor,
+	duk_bi_date_constructor,
+	duk_bi_date_constructor_now,
+	duk_bi_date_constructor_parse,
+	duk_bi_date_constructor_utc,
+	duk_bi_date_prototype_get_shared,
+	duk_bi_date_prototype_get_timezone_offset,
+	duk_bi_date_prototype_set_shared,
+	duk_bi_date_prototype_set_time,
+	duk_bi_date_prototype_to_json,
+	duk_bi_date_prototype_tostring_shared,
+	duk_bi_date_prototype_value_of,
+	duk_bi_duktape_object_act,
+	duk_bi_duktape_object_compact,
+	duk_bi_duktape_object_dec,
+	duk_bi_duktape_object_enc,
+	duk_bi_duktape_object_fin,
+	duk_bi_duktape_object_gc,
+	duk_bi_duktape_object_info,
+	duk_bi_error_constructor_shared,
+	duk_bi_error_prototype_filename_getter,
+	duk_bi_error_prototype_filename_setter,
+	duk_bi_error_prototype_linenumber_getter,
+	duk_bi_error_prototype_linenumber_setter,
+	duk_bi_error_prototype_stack_getter,
+	duk_bi_error_prototype_stack_setter,
+	duk_bi_error_prototype_to_string,
+	duk_bi_function_constructor,
+	duk_bi_function_prototype,
+	duk_bi_function_prototype_apply,
+	duk_bi_function_prototype_bind,
+	duk_bi_function_prototype_call,
+	duk_bi_function_prototype_to_string,
+	duk_bi_global_object_decode_uri,
+	duk_bi_global_object_decode_uri_component,
+	duk_bi_global_object_encode_uri,
+	duk_bi_global_object_encode_uri_component,
+	duk_bi_global_object_escape,
+	duk_bi_global_object_eval,
+	duk_bi_global_object_is_finite,
+	duk_bi_global_object_is_nan,
+	duk_bi_global_object_parse_float,
+	duk_bi_global_object_parse_int,
+	duk_bi_global_object_print_helper,
+	duk_bi_global_object_require,
+	duk_bi_global_object_unescape,
+	duk_bi_json_object_parse,
+	duk_bi_json_object_stringify,
+	duk_bi_logger_constructor,
+	duk_bi_logger_prototype_fmt,
+	duk_bi_logger_prototype_log_shared,
+	duk_bi_logger_prototype_raw,
+	duk_bi_math_object_max,
+	duk_bi_math_object_min,
+	duk_bi_math_object_onearg_shared,
+	duk_bi_math_object_random,
+	duk_bi_math_object_twoarg_shared,
+	duk_bi_nodejs_buffer_byte_length,
+	duk_bi_nodejs_buffer_concat,
+	duk_bi_nodejs_buffer_constructor,
+	duk_bi_nodejs_buffer_copy,
+	duk_bi_nodejs_buffer_fill,
+	duk_bi_nodejs_buffer_is_buffer,
+	duk_bi_nodejs_buffer_is_encoding,
+	duk_bi_nodejs_buffer_tojson,
+	duk_bi_nodejs_buffer_tostring,
+	duk_bi_nodejs_buffer_write,
+	duk_bi_number_constructor,
+	duk_bi_number_prototype_to_exponential,
+	duk_bi_number_prototype_to_fixed,
+	duk_bi_number_prototype_to_locale_string,
+	duk_bi_number_prototype_to_precision,
+	duk_bi_number_prototype_to_string,
+	duk_bi_number_prototype_value_of,
+	duk_bi_object_constructor,
+	duk_bi_object_constructor_create,
+	duk_bi_object_constructor_define_properties,
+	duk_bi_object_constructor_define_property,
+	duk_bi_object_constructor_get_own_property_descriptor,
+	duk_bi_object_constructor_is_extensible,
+	duk_bi_object_constructor_is_sealed_frozen_shared,
+	duk_bi_object_constructor_keys_shared,
+	duk_bi_object_constructor_prevent_extensions,
+	duk_bi_object_constructor_seal_freeze_shared,
+	duk_bi_object_getprototype_shared,
+	duk_bi_object_prototype_has_own_property,
+	duk_bi_object_prototype_is_prototype_of,
+	duk_bi_object_prototype_property_is_enumerable,
+	duk_bi_object_prototype_to_locale_string,
+	duk_bi_object_prototype_to_string,
+	duk_bi_object_prototype_value_of,
+	duk_bi_object_setprototype_shared,
+	duk_bi_pointer_constructor,
+	duk_bi_pointer_prototype_tostring_shared,
+	duk_bi_proxy_constructor,
+	duk_bi_regexp_constructor,
+	duk_bi_regexp_prototype_exec,
+	duk_bi_regexp_prototype_test,
+	duk_bi_regexp_prototype_to_string,
+	duk_bi_string_constructor,
+	duk_bi_string_constructor_from_char_code,
+	duk_bi_string_prototype_caseconv_shared,
+	duk_bi_string_prototype_char_at,
+	duk_bi_string_prototype_char_code_at,
+	duk_bi_string_prototype_concat,
+	duk_bi_string_prototype_indexof_shared,
+	duk_bi_string_prototype_locale_compare,
+	duk_bi_string_prototype_match,
+	duk_bi_string_prototype_replace,
+	duk_bi_string_prototype_search,
+	duk_bi_string_prototype_slice,
+	duk_bi_string_prototype_split,
+	duk_bi_string_prototype_substr,
+	duk_bi_string_prototype_substring,
+	duk_bi_string_prototype_to_string,
+	duk_bi_string_prototype_trim,
+	duk_bi_thread_constructor,
+	duk_bi_thread_current,
+	duk_bi_thread_resume,
+	duk_bi_thread_yield,
+	duk_bi_type_error_thrower,
+	duk_bi_typedarray_constructor,
+	duk_bi_typedarray_set,
+};
+
+DUK_INTERNAL const duk_uint8_t duk_builtins_data[1955] = {
+105,195,75,32,121,40,105,53,14,252,104,54,8,131,72,0,115,225,65,165,244,55,
+243,6,145,32,210,24,210,186,25,249,35,120,216,99,226,13,79,33,116,177,164,
+180,44,192,4,202,52,150,220,24,0,169,70,146,219,123,0,23,40,210,91,110,96,
+3,37,26,75,109,172,0,108,163,73,109,177,128,14,148,105,45,181,176,1,242,
+144,56,209,36,94,6,167,133,98,80,211,28,1,250,67,72,168,67,232,13,46,192,
+47,162,52,165,0,62,80,163,72,128,61,40,107,26,7,37,20,53,201,131,88,0,66,
+134,185,48,98,80,215,38,11,96,0,138,26,228,193,76,0,69,67,92,152,37,128,6,
+168,107,147,4,48,1,165,13,114,96,118,0,44,161,174,76,12,192,7,148,53,201,
+129,88,1,26,134,165,80,130,80,31,255,241,69,224,63,252,0,0,0,0,0,0,46,32,
+63,248,0,0,0,0,0,0,47,98,7,140,16,116,194,7,12,48,108,196,6,140,80,100,198,
+6,12,112,92,200,5,140,149,192,202,91,204,181,184,204,91,76,213,176,206,90,
+204,240,84,208,5,13,9,124,210,43,13,24,64,226,131,205,112,56,216,3,77,152,
+48,218,130,205,184,40,220,130,77,216,32,222,129,205,248,24,224,129,78,25,
+214,164,2,90,81,17,104,67,37,157,8,150,100,18,89,78,201,100,60,37,140,244,
+150,35,226,88,79,201,96,71,37,125,20,122,188,138,62,0,2,165,70,39,255,255,
+193,43,67,0,0,80,127,192,58,182,220,80,0,21,59,170,64,0,107,77,8,172,181,
+146,176,202,138,187,59,42,204,200,170,182,146,168,218,80,0,26,155,97,42,77,
+68,168,181,20,0,6,160,210,74,123,89,64,0,127,255,4,10,153,219,157,70,163,
+185,130,140,228,10,43,160,40,141,228,161,184,18,132,226,64,161,127,128,0,
+63,225,1,109,74,8,137,71,58,5,4,221,20,3,147,233,249,193,240,80,255,192,6,
+120,2,64,127,195,0,173,28,56,20,96,80,128,0,206,192,143,167,64,164,156,131,
+2,112,14,125,55,9,4,216,40,19,80,180,77,3,9,51,13,94,153,7,159,76,64,207,
+192,0,102,0,103,255,255,242,240,67,73,112,33,168,0,12,180,16,212,0,10,88,8,
+106,0,7,43,4,53,0,4,149,4,31,128,0,202,66,15,255,255,194,137,254,0,50,135,
+227,224,127,196,2,87,132,17,82,143,24,10,44,96,36,240,4,147,64,146,119,4,
+125,49,131,52,152,65,154,128,0,201,97,9,36,133,36,142,25,18,40,114,77,98,
+17,33,137,68,130,45,17,247,240,71,159,193,29,127,8,0,12,113,252,32,0,49,
+184,208,70,162,144,20,95,240,0,7,252,80,37,120,193,81,196,194,0,3,69,19,0,
+81,191,197,140,192,127,239,255,255,255,255,255,255,140,64,0,0,0,0,0,0,0,1,
+139,192,127,248,0,0,0,0,0,0,138,192,127,240,0,0,0,0,0,0,139,64,255,240,0,0,
+0,0,0,0,0,31,241,128,149,224,0,0,0,0,0,0,0,0,13,71,98,37,25,128,148,86,48,
+69,23,201,19,94,36,73,132,129,71,255,0,56,136,233,34,3,223,208,241,192,3,
+254,56,18,188,135,255,128,0,0,0,0,0,11,104,228,128,135,18,4,0,6,26,72,16,0,
+42,49,32,64,0,225,132,129,0,4,133,146,4,0,21,210,72,16,0,103,65,32,64,1,
+220,228,100,162,146,130,20,74,8,72,248,64,2,33,3,225,0,9,131,143,132,0,42,
+12,62,16,0,184,40,248,64,3,32,131,225,0,13,129,143,132,0,58,4,62,16,0,248,
+8,248,64,4,32,3,225,0,17,127,143,132,0,73,252,62,16,1,55,232,248,64,5,31,
+131,225,0,21,125,143,132,0,89,244,62,16,1,119,201,0,31,4,68,123,144,148,0,
+97,236,66,80,1,151,169,10,248,0,211,208,133,124,0,109,230,66,254,0,56,242,
+33,127,0,29,120,144,207,128,15,60,8,103,192,7,221,228,37,0,32,119,16,148,0,
+133,218,66,190,0,68,236,33,95,0,35,117,144,191,128,18,58,136,95,192,9,92,
+195,225,0,38,114,144,148,0,156,41,31,224,0,15,249,1,138,144,65,192,2,22,0,
+88,16,46,24,77,208,148,103,4,102,252,102,244,128,0,0,0,0,0,0,0,0,220,111,
+68,113,61,146,142,248,0,164,255,128,0,63,228,133,109,16,89,178,65,18,235,
+153,25,150,220,184,188,180,230,6,32,209,205,0,20,175,240,0,39,252,160,77,
+162,184,54,72,34,0,82,255,192,0,159,242,193,54,138,222,217,32,136,1,76,255,
+0,2,127,204,4,218,43,115,100,130,32,5,55,252,0,9,255,52,19,104,173,173,146,
+8,128,20,239,240,0,39,252,224,77,162,182,54,72,34,0,83,255,192,0,159,243,
+193,54,138,214,217,32,136,0,255,255,33,177,1,0,22,252,42,44,81,93,165,175,
+1,0,9,174,198,238,213,84,89,173,0,255,152,185,11,251,232,231,189,171,0,255,
+220,85,29,148,174,11,249,169,0,255,111,45,236,84,155,148,57,167,1,0,36,135,
+237,81,16,180,97,165,0,255,154,130,121,153,252,239,53,163,0,255,218,130,
+121,153,252,239,53,38,130,129,25,234,5,0,1,103,40,20,0,9,154,160,80,0,54,
+98,146,25,106,5,0,4,101,40,20,0,21,146,160,80,0,102,66,129,64,1,216,234,5,
+0,8,99,39,47,49,83,215,152,138,73,0,1,97,168,129,132,160,80,0,150,10,129,
+64,2,152,10,5,0,11,95,168,20,0,48,31,255,224,5,17,72,66,249,37,129,127,255,
+0,0,191,255,128,0,63,255,197,31,192,64,196,80,0,0,0,0,0,8,26,112,17,169,0,
+154,80,1,171,28,124,88,65,233,49,7,133,100,29,149,15,14,138,71,135,37,3,
+195,66,114,5,77,252,0,243,178,40,25,200,48,101,30,0,127,210,128,0,85,31,
+192,0,31,244,224,5,71,22,8,0,13,20,88,1,85,127,0,0,127,212,128,21,29,220,
+32,0,52,87,112,5,89,252,0,1,255,86,16,166,66,0,0,0,0,0,0,0,0,170,72,38,29,
+219,247,16,49,75,32,193,52,130,244,193,225,114,96,248,0,8,249,48,124,0,8,
+90,152,62,0,6,44,76,31,0,4,21,166,15,128,2,147,255,252,38,212,16,184,155,
+250,226,217,150,47,46,91,249,54,96,139,229,229,203,127,36,26,119,32,203,
+203,150,254,72,52,97,221,147,102,157,217,192,10,191,248,0,157,4,72,15,250,
+224,1,154,140,36,0,8,43,31,224,0,15,251,0,16,55,139,164,0,192,220,46,144,2,
+3,104,186,64,12,77,130,233,0,33,53,139,164,0,200,212,46,144,2,35,72,186,64,
+8,205,2,233,0,36,51,140,180,0,192,204,50,208,2,3,40,203,64,12,76,131,45,0,
+33,49,140,180,0,200,196,50,208,2,35,8,203,64,8,204,3,45,0,36,7,255,248,1,
+82,101,16,112,24,72,0,8,86,159,193,56,192,63,240,0,0,0,0,0,0,1,151,246,96,
+0,21,183,240,78,48,15,252,0,0,0,0,0,0,0,101,253,168,0,5,113,252,19,140,3,
+255,0,0,0,0,0,0,0,25,127,110,0,1,93,127,4,227,1,0,0,0,0,0,0,0,0,6,95,220,
+128,0,87,159,193,56,192,64,0,0,0,0,0,0,0,1,151,247,96,0,21,247,240,78,48,
+16,4,0,0,0,0,0,0,0,101,253,232,0,5,129,252,19,140,4,1,0,0,0,0,0,0,0,25,127,
+126,0,1,97,127,4,227,1,0,64,0,0,0,0,0,0,6,95,224,128,0,88,159,193,56,192,
+64,32,0,0,0,0,0,0,1,151,248,96,0,22,55,240,5,157,170,33,68,178,69,10,193,
+20,10,104,79,138,36,0,12,31,248,160,88,154,23,66,100,93,32,2,9,129,116,128,
+0,165,197,210,0,18,150,23,72,0,138,84,93,32,3,41,65,116,128,1,36,197,210,0,
+20,146,23,72,0,146,68,93,32,3,73,1,116,128,1,163,197,210,0,22,142,23,72,0,
+34,52,93,32,1,136,193,118,128,2,162,197,218,0,26,138,23,104,0,170,36,93,
+160,3,168,129,150,33,198,90,0,32,134,25,104,0,10,20,101,160,1,40,65,150,
+128,8,160,198,90,0,50,130,25,104,0,18,4,101,160,1,72,1,150,128,9,31,198,90,
+0,52,126,25,104,0,25,244,101,160,1,103,193,150,128,2,30,198,90,0,24,122,25,
+136,0,41,228,102,32,1,167,129,152,128,10,157,198,98,0,59,71,91,99,157,104,
+9,213,118,39,5,8,159,20,40,0,10,109,90,19,81,132,39,151,32,
+};
+#ifdef DUK_USE_BUILTIN_INITJS
+DUK_INTERNAL const duk_uint8_t duk_initjs_data[187] = {
+40,102,117,110,99,116,105,111,110,40,100,44,97,41,123,102,117,110,99,116,
+105,111,110,32,98,40,97,44,98,44,99,41,123,79,98,106,101,99,116,46,100,101,
+102,105,110,101,80,114,111,112,101,114,116,121,40,97,44,98,44,123,118,97,
+108,117,101,58,99,44,119,114,105,116,97,98,108,101,58,33,48,44,101,110,117,
+109,101,114,97,98,108,101,58,33,49,44,99,111,110,102,105,103,117,114,97,98,
+108,101,58,33,48,125,41,125,98,40,97,46,76,111,103,103,101,114,44,34,99,
+108,111,103,34,44,110,101,119,32,97,46,76,111,103,103,101,114,40,34,67,34,
+41,41,59,98,40,97,44,34,109,111,100,76,111,97,100,101,100,34,44,123,125,41,
+125,41,40,116,104,105,115,44,68,117,107,116,97,112,101,41,59,10,0,
+};
+#endif  /* DUK_USE_BUILTIN_INITJS */
+#elif defined(DUK_USE_DOUBLE_ME)
+DUK_INTERNAL const duk_uint8_t duk_strings_data[2624] = {
+55,86,227,24,145,55,102,120,144,3,63,94,228,54,100,137,186,50,11,164,109,
+77,215,5,61,35,106,206,149,110,4,254,219,237,58,8,196,24,103,74,183,2,127,
+103,246,93,4,98,12,47,180,67,103,246,127,101,208,70,32,194,186,134,207,236,
+254,203,160,140,65,133,246,136,108,254,199,237,186,8,196,24,87,80,217,253,
+143,219,116,17,136,49,30,209,13,159,220,116,75,3,30,65,244,17,136,48,174,
+209,13,159,220,116,17,136,48,158,161,179,251,142,130,49,6,17,209,130,96,
+237,80,75,47,160,140,65,142,134,133,41,34,110,134,133,41,34,3,25,110,8,22,
+158,130,38,163,8,217,200,158,76,156,210,117,128,153,203,210,70,46,137,187,
+18,27,164,187,201,209,130,100,55,91,70,4,145,63,66,231,44,128,105,187,41,
+197,13,49,122,8,196,24,71,75,70,138,104,115,77,215,5,36,20,201,214,209,107,
+79,104,209,144,168,105,6,207,251,209,104,209,125,212,227,66,127,235,191,
+239,232,180,90,52,95,69,247,83,141,9,255,174,255,191,162,211,80,210,253,23,
+221,78,52,39,254,183,254,254,139,72,105,126,139,238,167,26,19,255,91,255,
+127,69,166,129,191,69,247,83,141,9,255,175,255,191,162,213,26,50,23,232,
+190,234,113,161,63,245,115,119,86,227,118,83,138,26,98,9,110,48,86,22,148,
+160,152,22,82,70,46,137,44,8,180,163,32,104,98,206,32,17,7,16,88,101,100,
+206,42,70,36,108,205,18,74,140,33,196,230,60,2,152,146,33,38,230,8,36,79,
+182,251,65,156,151,24,200,33,145,162,25,80,209,24,67,0,166,68,52,174,61,73,
+25,33,205,25,27,84,177,195,234,220,1,144,105,99,135,217,16,17,17,208,72,
+199,179,60,93,100,146,49,232,162,64,76,135,19,152,244,44,136,223,98,67,4,
+18,33,247,217,158,36,0,209,190,156,13,26,201,21,111,165,67,64,180,100,145,
+62,250,32,45,100,33,55,214,1,229,223,65,19,72,187,236,206,137,35,125,120,
+190,201,104,105,15,190,201,212,136,136,125,246,160,137,27,83,239,171,37,
+200,218,159,125,168,34,192,61,27,233,93,22,1,114,78,250,28,76,130,112,200,
+93,245,164,188,207,190,204,17,49,38,109,246,160,93,8,119,185,13,153,34,173,
+246,113,0,136,48,76,10,90,26,78,182,140,9,34,130,161,100,235,64,194,9,226,
+44,166,1,41,221,153,226,235,118,120,121,58,72,197,209,63,71,69,76,15,34,
+164,73,244,171,112,39,246,223,104,169,18,125,42,220,9,253,159,217,38,68,
+159,104,134,207,236,254,201,18,36,250,134,207,236,254,201,50,36,251,68,54,
+127,99,246,200,145,39,212,54,127,99,246,200,145,39,218,33,179,251,131,200,
+147,234,27,63,184,81,137,62,149,110,4,254,219,237,20,98,79,165,91,129,63,
+179,251,36,152,147,237,16,217,253,159,217,32,196,159,80,217,253,159,217,36,
+196,159,104,134,207,236,126,217,6,36,250,134,207,236,126,217,6,36,251,68,
+54,127,112,115,18,125,67,103,247,8,149,2,8,196,24,143,131,137,146,90,121,
+35,162,44,140,35,102,160,226,100,235,138,89,18,102,13,10,82,68,200,151,106,
+130,88,131,4,192,73,225,228,85,162,137,147,168,108,252,18,42,209,68,201,
+212,54,126,89,23,104,162,100,245,17,230,207,193,34,237,20,76,158,162,60,
+217,249,100,109,162,137,147,163,117,2,178,120,36,109,162,137,147,163,117,2,
+178,121,100,101,162,137,147,165,91,129,63,4,140,180,81,50,116,171,112,39,
+229,145,150,138,38,78,161,179,251,63,178,240,72,203,69,19,39,80,217,253,
+159,217,121,100,109,162,137,147,212,71,155,63,179,251,47,4,141,180,81,50,
+122,136,243,103,246,127,101,229,145,150,138,38,78,161,179,251,31,182,240,
+72,203,69,19,39,80,217,253,143,219,121,100,109,162,137,147,212,71,155,63,
+177,251,111,4,141,180,81,50,122,136,243,103,246,63,109,229,145,54,138,38,
+78,161,179,251,133,90,40,153,61,68,121,179,251,132,196,128,31,80,217,248,
+36,76,72,1,245,13,159,150,69,68,128,31,168,143,54,126,9,21,18,0,126,162,60,
+217,249,100,100,72,1,244,110,160,86,79,4,140,137,0,62,141,212,10,201,229,
+145,113,32,7,210,173,192,159,130,69,196,128,31,74,183,2,126,89,23,18,0,125,
+67,103,246,127,101,224,145,113,32,7,212,54,127,103,246,94,89,25,18,0,126,
+162,60,217,253,159,217,120,36,100,72,1,250,136,243,103,246,127,101,229,145,
+113,32,7,212,54,127,99,246,222,9,23,18,0,125,67,103,246,63,109,229,145,145,
+32,7,234,35,205,159,216,253,183,130,70,68,128,31,168,143,54,127,99,246,222,
+89,17,18,0,125,67,103,247,9,137,0,63,81,30,108,254,224,130,115,240,98,66,
+128,92,136,84,45,101,180,81,50,28,78,99,193,18,40,56,153,58,178,52,211,58,
+17,46,134,133,41,34,164,75,164,104,156,52,52,199,37,222,232,206,66,64,207,
+18,66,136,137,19,173,62,46,155,181,167,72,147,235,226,233,186,120,121,58,
+226,157,214,111,84,76,73,36,109,24,72,130,100,112,200,178,76,157,124,92,
+242,70,120,25,193,34,245,241,117,240,97,1,107,33,25,212,54,160,90,7,244,29,
+24,38,66,254,223,215,125,119,215,126,232,190,43,226,67,244,1,250,193,125,
+111,216,11,234,254,192,63,96,159,173,234,26,84,53,19,194,126,175,168,105,
+80,212,79,8,234,26,84,53,19,193,156,20,144,83,52,167,20,52,198,109,24,18,
+68,225,115,150,64,53,52,104,200,84,52,131,76,167,20,52,200,46,7,48,52,146,
+132,102,57,33,165,139,168,209,154,32,104,220,193,189,214,27,16,209,176,23,
+26,220,98,149,110,116,70,75,188,98,116,136,34,33,101,4,192,223,178,32,38,6,
+144,18,67,72,1,58,67,0,100,95,74,17,159,217,31,210,132,103,246,58,251,33,
+121,232,55,150,227,125,143,216,16,190,91,141,246,68,31,150,223,178,39,150,
+223,177,251,0,244,135,97,37,32,24,132,104,24,66,161,175,164,202,134,140,
+151,39,212,125,255,221,125,74,86,9,79,168,104,201,116,178,139,154,22,134,
+145,72,51,93,18,116,64,145,13,39,82,34,33,38,73,76,132,185,4,185,187,198,
+100,229,233,197,13,49,228,73,247,4,4,78,98,79,184,32,34,105,187,201,147,
+154,185,187,200,147,165,233,197,13,50,230,239,82,98,151,167,20,52,206,145,
+39,234,76,69,245,22,190,224,128,138,228,73,244,180,90,251,130,2,43,145,39,
+234,76,76,243,155,51,162,68,159,88,230,204,234,145,39,234,76,67,240,38,67,
+200,147,232,193,50,46,68,159,169,49,31,206,164,100,137,18,125,59,169,25,54,
+68,159,169,49,51,200,109,38,73,42,68,159,88,134,210,100,147,100,73,250,147,
+20,188,65,57,163,146,164,73,246,68,19,154,57,74,68,159,169,49,51,200,90,
+209,34,9,205,28,159,34,79,172,66,214,137,16,78,104,228,121,18,125,154,24,
+72,152,147,236,208,194,101,205,39,92,82,200,147,145,137,63,82,98,103,144,
+181,162,68,19,154,57,60,196,159,88,133,173,18,32,156,209,201,166,36,253,73,
+138,94,32,156,209,201,70,36,251,34,9,205,28,154,98,79,212,152,153,228,54,
+147,36,148,98,79,172,67,105,50,73,102,36,253,73,136,254,117,35,36,24,147,
+233,221,72,201,38,36,253,73,136,126,6,12,98,79,163,6,20,98,79,212,152,135,
+224,76,135,49,39,209,130,100,89,137,63,82,98,103,156,217,157,6,36,250,199,
+54,103,113,137,63,82,98,47,168,181,247,4,4,86,98,79,165,162,215,220,16,17,
+57,137,62,205,12,36,166,238,173,194,2,201,217,161,132,236,167,20,52,210,
+155,186,183,8,11,39,70,9,147,178,156,80,211,50,110,236,208,194,118,83,138,
+26,102,77,221,24,38,78,202,113,67,76,54,186,195,245,38,34,188,17,145,23,55,
+117,241,32,145,36,57,173,155,186,75,189,205,35,102,128,44,243,119,74,139,
+144,113,243,221,36,77,21,38,144,210,161,168,158,35,230,144,192,154,42,77,
+33,165,67,81,60,15,173,7,90,159,49,13,213,64,186,17,62,96,47,170,129,116,
+33,165,64,202,113,36,226,134,70,110,234,220,32,44,157,163,222,72,244,64,
+145,23,55,118,143,121,35,209,2,68,140,221,213,184,64,89,58,183,88,145,232,
+129,34,46,110,234,221,98,71,162,4,136,153,80,50,156,80,211,22,79,90,38,105,
+16,17,17,207,18,61,96,17,10,192,76,71,106,220,32,44,157,19,152,240,68,138,
+17,193,30,137,195,39,65,51,8,224,143,65,54,22,46,103,68,112,71,162,112,200,
+184,144,116,17,59,20,24,243,52,72,58,8,134,42,23,50,68,108,3,206,87,71,164,
+0,142,73,57,132,41,42,72,225,107,4,167,212,52,100,191,92,83,161,163,37,250,
+226,158,141,145,208,89,154,79,90,4,66,73,209,153,100,180,8,133,145,208,89,
+158,36,169,35,34,17,244,145,198,247,60,137,114,26,97,57,162,4,206,137,116,
+17,136,48,144,68,212,97,27,57,24,64,90,201,18,5,13,25,4,5,172,160,123,215,
+138,62,46,121,35,60,117,18,233,27,70,18,32,10,200,212,75,175,139,166,233,
+225,228,235,138,227,130,93,117,155,215,197,207,36,103,131,212,11,161,58,
+226,186,110,234,220,32,44,157,148,226,134,153,19,119,101,56,161,166,88,156,
+217,78,52,20,221,17,200,147,25,137,53,17,180,97,34,0,172,140,19,154,84,26,
+145,0,86,68,90,40,152,2,178,22,160,93,8,69,19,18,98,37,210,94,100,108,144,
+21,145,8,151,75,23,100,141,66,37,217,16,11,32,226,248,146,164,108,250,75,
+204,141,146,28,217,24,177,33,50,66,72,128,92,6,66,161,164,235,226,231,146,
+51,65,36,225,144,168,105,58,248,185,228,140,240,97,68,128,153,38,98,79,174,
+179,122,248,185,228,140,241,214,129,132,150,12,73,245,214,111,95,23,60,145,
+158,58,50,72,81,67,230,232,184,196,159,95,23,77,211,195,201,215,21,47,139,
+166,233,225,228,50,200,211,76,229,2,201,25,149,241,67,102,138,52,146,16,30,
+67,18,66,3,201,34,52,78,25,61,72,160,94,115,30,230,145,179,73,26,39,12,158,
+164,81,33,144,78,25,61,72,160,94,115,30,230,145,179,72,200,39,12,158,164,
+80,132,75,165,67,81,50,21,18,235,65,214,169,224,140,137,210,173,192,154,30,
+8,200,157,67,102,66,84,11,71,169,20,19,209,139,162,158,207,15,39,73,24,186,
+43,236,176,217,130,253,36,98,232,187,177,33,73,18,52,68,233,35,23,69,93,
+136,26,98,116,145,139,162,158,146,160,95,73,24,186,37,12,72,5,16,64,145,10,
+32,76,71,64,156,217,161,180,34,6,64,208,198,36,78,50,20,20,92,204,50,44,
+147,32,134,226,17,114,33,202,134,129,107,192,202,232,160,180,104,166,135,
+52,72,40,144,213,33,178,152,26,34,56,163,105,44,104,146,116,139,77,43,34,
+98,57,38,116,72,179,60,93,97,206,56,52,240,242,56,163,168,34,81,57,178,153,
+42,228,12,182,58,22,66,89,19,57,68,176,74,68,35,104,195,18,239,116,102,114,
+94,100,104,228,100,49,238,140,203,42,60,145,35,104,181,146,113,161,10,80,
+46,68,82,24,245,145,132,108,228,148,54,100,137,64,34,13,100,153,222,1,40,6,
+33,223,20,84,19,34,95,23,76,130,153,6,103,208,43,64,141,41,130,104,17,112,
+130,44,96,
+};
+
+/* to convert a heap stridx to a token number, subtract
+ * DUK_STRIDX_START_RESERVED and add DUK_TOK_START_RESERVED.
+ */
+
+/* native functions: 149 */
+DUK_INTERNAL const duk_c_function duk_bi_native_functions[149] = {
+	duk_bi_array_constructor,
+	duk_bi_array_constructor_is_array,
+	duk_bi_array_prototype_concat,
+	duk_bi_array_prototype_indexof_shared,
+	duk_bi_array_prototype_iter_shared,
+	duk_bi_array_prototype_join_shared,
+	duk_bi_array_prototype_pop,
+	duk_bi_array_prototype_push,
+	duk_bi_array_prototype_reduce_shared,
+	duk_bi_array_prototype_reverse,
+	duk_bi_array_prototype_shift,
+	duk_bi_array_prototype_slice,
+	duk_bi_array_prototype_sort,
+	duk_bi_array_prototype_splice,
+	duk_bi_array_prototype_to_string,
+	duk_bi_array_prototype_unshift,
+	duk_bi_arraybuffer_constructor,
+	duk_bi_arraybuffer_isview,
+	duk_bi_boolean_constructor,
+	duk_bi_boolean_prototype_tostring_shared,
+	duk_bi_buffer_compare_shared,
+	duk_bi_buffer_constructor,
+	duk_bi_buffer_prototype_tostring_shared,
+	duk_bi_buffer_readfield,
+	duk_bi_buffer_slice_shared,
+	duk_bi_buffer_writefield,
+	duk_bi_dataview_constructor,
+	duk_bi_date_constructor,
+	duk_bi_date_constructor_now,
+	duk_bi_date_constructor_parse,
+	duk_bi_date_constructor_utc,
+	duk_bi_date_prototype_get_shared,
+	duk_bi_date_prototype_get_timezone_offset,
+	duk_bi_date_prototype_set_shared,
+	duk_bi_date_prototype_set_time,
+	duk_bi_date_prototype_to_json,
+	duk_bi_date_prototype_tostring_shared,
+	duk_bi_date_prototype_value_of,
+	duk_bi_duktape_object_act,
+	duk_bi_duktape_object_compact,
+	duk_bi_duktape_object_dec,
+	duk_bi_duktape_object_enc,
+	duk_bi_duktape_object_fin,
+	duk_bi_duktape_object_gc,
+	duk_bi_duktape_object_info,
+	duk_bi_error_constructor_shared,
+	duk_bi_error_prototype_filename_getter,
+	duk_bi_error_prototype_filename_setter,
+	duk_bi_error_prototype_linenumber_getter,
+	duk_bi_error_prototype_linenumber_setter,
+	duk_bi_error_prototype_stack_getter,
+	duk_bi_error_prototype_stack_setter,
+	duk_bi_error_prototype_to_string,
+	duk_bi_function_constructor,
+	duk_bi_function_prototype,
+	duk_bi_function_prototype_apply,
+	duk_bi_function_prototype_bind,
+	duk_bi_function_prototype_call,
+	duk_bi_function_prototype_to_string,
+	duk_bi_global_object_decode_uri,
+	duk_bi_global_object_decode_uri_component,
+	duk_bi_global_object_encode_uri,
+	duk_bi_global_object_encode_uri_component,
+	duk_bi_global_object_escape,
+	duk_bi_global_object_eval,
+	duk_bi_global_object_is_finite,
+	duk_bi_global_object_is_nan,
+	duk_bi_global_object_parse_float,
+	duk_bi_global_object_parse_int,
+	duk_bi_global_object_print_helper,
+	duk_bi_global_object_require,
+	duk_bi_global_object_unescape,
+	duk_bi_json_object_parse,
+	duk_bi_json_object_stringify,
+	duk_bi_logger_constructor,
+	duk_bi_logger_prototype_fmt,
+	duk_bi_logger_prototype_log_shared,
+	duk_bi_logger_prototype_raw,
+	duk_bi_math_object_max,
+	duk_bi_math_object_min,
+	duk_bi_math_object_onearg_shared,
+	duk_bi_math_object_random,
+	duk_bi_math_object_twoarg_shared,
+	duk_bi_nodejs_buffer_byte_length,
+	duk_bi_nodejs_buffer_concat,
+	duk_bi_nodejs_buffer_constructor,
+	duk_bi_nodejs_buffer_copy,
+	duk_bi_nodejs_buffer_fill,
+	duk_bi_nodejs_buffer_is_buffer,
+	duk_bi_nodejs_buffer_is_encoding,
+	duk_bi_nodejs_buffer_tojson,
+	duk_bi_nodejs_buffer_tostring,
+	duk_bi_nodejs_buffer_write,
+	duk_bi_number_constructor,
+	duk_bi_number_prototype_to_exponential,
+	duk_bi_number_prototype_to_fixed,
+	duk_bi_number_prototype_to_locale_string,
+	duk_bi_number_prototype_to_precision,
+	duk_bi_number_prototype_to_string,
+	duk_bi_number_prototype_value_of,
+	duk_bi_object_constructor,
+	duk_bi_object_constructor_create,
+	duk_bi_object_constructor_define_properties,
+	duk_bi_object_constructor_define_property,
+	duk_bi_object_constructor_get_own_property_descriptor,
+	duk_bi_object_constructor_is_extensible,
+	duk_bi_object_constructor_is_sealed_frozen_shared,
+	duk_bi_object_constructor_keys_shared,
+	duk_bi_object_constructor_prevent_extensions,
+	duk_bi_object_constructor_seal_freeze_shared,
+	duk_bi_object_getprototype_shared,
+	duk_bi_object_prototype_has_own_property,
+	duk_bi_object_prototype_is_prototype_of,
+	duk_bi_object_prototype_property_is_enumerable,
+	duk_bi_object_prototype_to_locale_string,
+	duk_bi_object_prototype_to_string,
+	duk_bi_object_prototype_value_of,
+	duk_bi_object_setprototype_shared,
+	duk_bi_pointer_constructor,
+	duk_bi_pointer_prototype_tostring_shared,
+	duk_bi_proxy_constructor,
+	duk_bi_regexp_constructor,
+	duk_bi_regexp_prototype_exec,
+	duk_bi_regexp_prototype_test,
+	duk_bi_regexp_prototype_to_string,
+	duk_bi_string_constructor,
+	duk_bi_string_constructor_from_char_code,
+	duk_bi_string_prototype_caseconv_shared,
+	duk_bi_string_prototype_char_at,
+	duk_bi_string_prototype_char_code_at,
+	duk_bi_string_prototype_concat,
+	duk_bi_string_prototype_indexof_shared,
+	duk_bi_string_prototype_locale_compare,
+	duk_bi_string_prototype_match,
+	duk_bi_string_prototype_replace,
+	duk_bi_string_prototype_search,
+	duk_bi_string_prototype_slice,
+	duk_bi_string_prototype_split,
+	duk_bi_string_prototype_substr,
+	duk_bi_string_prototype_substring,
+	duk_bi_string_prototype_to_string,
+	duk_bi_string_prototype_trim,
+	duk_bi_thread_constructor,
+	duk_bi_thread_current,
+	duk_bi_thread_resume,
+	duk_bi_thread_yield,
+	duk_bi_type_error_thrower,
+	duk_bi_typedarray_constructor,
+	duk_bi_typedarray_set,
+};
+
+DUK_INTERNAL const duk_uint8_t duk_builtins_data[1955] = {
+105,195,75,32,121,40,105,53,14,252,104,54,8,131,72,0,115,225,65,165,244,55,
+243,6,145,32,210,24,210,186,25,249,35,120,216,99,226,13,79,33,116,177,164,
+180,44,192,4,202,52,150,220,24,0,169,70,146,219,123,0,23,40,210,91,110,96,
+3,37,26,75,109,172,0,108,163,73,109,177,128,14,148,105,45,181,176,1,242,
+144,56,209,36,94,6,167,133,98,80,211,28,1,250,67,72,168,67,232,13,46,192,
+47,162,52,165,0,62,80,163,72,128,61,40,107,26,7,37,20,53,201,131,88,0,66,
+134,185,48,98,80,215,38,11,96,0,138,26,228,193,76,0,69,67,92,152,37,128,6,
+168,107,147,4,48,1,165,13,114,96,118,0,44,161,174,76,12,192,7,148,53,201,
+129,88,1,26,134,165,80,130,80,31,255,241,69,224,0,0,124,63,128,0,0,0,46,32,
+0,0,120,63,128,0,0,0,47,98,7,140,16,116,194,7,12,48,108,196,6,140,80,100,
+198,6,12,112,92,200,5,140,149,192,202,91,204,181,184,204,91,76,213,176,206,
+90,204,240,84,208,5,13,9,124,210,43,13,24,64,226,131,205,112,56,216,3,77,
+152,48,218,130,205,184,40,220,130,77,216,32,222,129,205,248,24,224,129,78,
+25,214,164,2,90,81,17,104,67,37,157,8,150,100,18,89,78,201,100,60,37,140,
+244,150,35,226,88,79,201,96,71,37,125,20,122,188,138,62,0,2,165,70,39,255,
+255,193,43,67,0,0,80,127,192,58,182,220,80,0,21,59,170,64,0,107,77,8,172,
+181,146,176,202,138,187,59,42,204,200,170,182,146,168,218,80,0,26,155,97,
+42,77,68,168,181,20,0,6,160,210,74,123,89,64,0,127,255,4,10,153,219,157,70,
+163,185,130,140,228,10,43,160,40,141,228,161,184,18,132,226,64,161,127,128,
+0,63,225,1,109,74,8,137,71,58,5,4,221,20,3,147,233,249,193,240,80,255,192,
+6,120,2,64,127,195,0,173,28,56,20,96,80,128,0,206,192,143,167,64,164,156,
+131,2,112,14,125,55,9,4,216,40,19,80,180,77,3,9,51,13,94,153,7,159,76,64,
+207,192,0,102,0,103,255,255,242,240,67,73,112,33,168,0,12,180,16,212,0,10,
+88,8,106,0,7,43,4,53,0,4,149,4,31,128,0,202,66,15,255,255,194,137,254,0,50,
+135,227,224,127,196,2,87,132,17,82,143,24,10,44,96,36,240,4,147,64,146,119,
+4,125,49,131,52,152,65,154,128,0,201,97,9,36,133,36,142,25,18,40,114,77,98,
+17,33,137,68,130,45,17,247,240,71,159,193,29,127,8,0,12,113,252,32,0,49,
+184,208,70,162,144,20,95,240,0,7,252,80,37,120,193,81,196,194,0,3,69,19,0,
+81,191,197,140,192,255,255,239,127,255,255,255,255,140,64,0,0,0,0,1,0,0,0,
+139,192,0,0,248,127,0,0,0,0,138,192,0,0,240,127,0,0,0,0,139,64,0,0,240,255,
+0,0,0,0,0,31,241,128,149,224,0,0,0,0,0,0,0,0,13,71,98,37,25,128,148,86,48,
+69,23,201,19,94,36,73,132,129,71,255,0,56,136,233,34,3,223,208,241,192,3,
+254,56,18,188,128,0,15,135,240,0,0,0,11,104,228,128,135,18,4,0,6,26,72,16,
+0,42,49,32,64,0,225,132,129,0,4,133,146,4,0,21,210,72,16,0,103,65,32,64,1,
+220,228,100,162,146,130,20,74,8,72,248,64,2,33,3,225,0,9,131,143,132,0,42,
+12,62,16,0,184,40,248,64,3,32,131,225,0,13,129,143,132,0,58,4,62,16,0,248,
+8,248,64,4,32,3,225,0,17,127,143,132,0,73,252,62,16,1,55,232,248,64,5,31,
+131,225,0,21,125,143,132,0,89,244,62,16,1,119,201,0,31,4,68,123,144,148,0,
+97,236,66,80,1,151,169,10,248,0,211,208,133,124,0,109,230,66,254,0,56,242,
+33,127,0,29,120,144,207,128,15,60,8,103,192,7,221,228,37,0,32,119,16,148,0,
+133,218,66,190,0,68,236,33,95,0,35,117,144,191,128,18,58,136,95,192,9,92,
+195,225,0,38,114,144,148,0,156,41,31,224,0,15,249,1,138,144,65,192,2,22,0,
+88,16,46,24,77,208,148,103,4,102,252,102,244,128,0,0,0,0,0,0,0,0,220,111,
+68,113,61,146,142,248,0,164,255,128,0,63,228,133,109,16,89,178,65,18,235,
+153,25,150,220,184,188,180,230,6,32,209,205,0,20,175,240,0,39,252,160,77,
+162,184,54,72,34,0,82,255,192,0,159,242,193,54,138,222,217,32,136,1,76,255,
+0,2,127,204,4,218,43,115,100,130,32,5,55,252,0,9,255,52,19,104,173,173,146,
+8,128,20,239,240,0,39,252,224,77,162,182,54,72,34,0,83,255,192,0,159,243,
+193,54,138,214,217,32,136,0,255,255,33,177,0,42,252,21,1,165,92,82,45,175,
+2,197,172,9,0,89,86,214,237,173,1,8,187,152,255,188,231,235,249,171,1,28,
+87,220,255,250,8,173,149,169,1,239,47,108,252,59,148,152,85,167,3,236,132,
+37,0,96,181,17,81,165,2,122,131,152,255,52,237,253,153,163,2,122,131,216,
+255,52,237,253,153,38,130,129,25,234,5,0,1,103,40,20,0,9,154,160,80,0,54,
+98,146,25,106,5,0,4,101,40,20,0,21,146,160,80,0,102,66,129,64,1,216,234,5,
+0,8,99,39,47,49,83,215,152,138,73,0,1,97,168,129,132,160,80,0,150,10,129,
+64,2,152,10,5,0,11,95,168,20,0,48,31,255,224,5,17,72,66,249,37,129,127,255,
+0,0,191,255,128,0,63,255,197,31,192,0,80,196,64,0,0,0,0,8,26,112,17,169,0,
+154,80,1,171,28,124,88,65,233,49,7,133,100,29,149,15,14,138,71,135,37,3,
+195,66,114,5,77,252,0,243,178,40,25,200,48,101,30,0,127,210,128,0,85,31,
+192,0,31,244,224,5,71,22,8,0,13,20,88,1,85,127,0,0,127,212,128,21,29,220,
+32,0,52,87,112,5,89,252,0,1,255,86,16,166,64,0,0,2,0,0,0,0,0,170,72,38,29,
+219,247,16,49,75,32,193,52,130,244,193,225,114,96,248,0,8,249,48,124,0,8,
+90,152,62,0,6,44,76,31,0,4,21,166,15,128,2,147,255,252,38,212,16,184,155,
+250,226,217,150,47,46,91,249,54,96,139,229,229,203,127,36,26,119,32,203,
+203,150,254,72,52,97,221,147,102,157,217,192,10,191,248,0,157,4,72,15,250,
+224,1,154,140,36,0,8,43,31,224,0,15,251,0,16,55,139,164,0,192,220,46,144,2,
+3,104,186,64,12,77,130,233,0,33,53,139,164,0,200,212,46,144,2,35,72,186,64,
+8,205,2,233,0,36,51,140,180,0,192,204,50,208,2,3,40,203,64,12,76,131,45,0,
+33,49,140,180,0,200,196,50,208,2,35,8,203,64,8,204,3,45,0,36,7,255,248,1,
+82,101,16,112,24,72,0,8,86,159,193,56,192,0,0,240,63,0,0,0,0,1,151,246,96,
+0,21,183,240,78,48,0,0,60,15,192,0,0,0,0,101,253,168,0,5,113,252,19,140,0,
+0,15,3,240,0,0,0,0,25,127,110,0,1,93,127,4,227,0,0,0,1,0,0,0,0,0,6,95,220,
+128,0,87,159,193,56,192,0,0,0,64,0,0,0,0,1,151,247,96,0,21,247,240,78,48,0,
+0,4,16,0,0,0,0,0,101,253,232,0,5,129,252,19,140,0,0,1,4,0,0,0,0,0,25,127,
+126,0,1,97,127,4,227,0,0,0,65,0,0,0,0,0,6,95,224,128,0,88,159,193,56,192,0,
+0,32,64,0,0,0,0,1,151,248,96,0,22,55,240,5,157,170,33,68,178,69,10,193,20,
+10,104,79,138,36,0,12,31,248,160,88,154,23,66,100,93,32,2,9,129,116,128,0,
+165,197,210,0,18,150,23,72,0,138,84,93,32,3,41,65,116,128,1,36,197,210,0,
+20,146,23,72,0,146,68,93,32,3,73,1,116,128,1,163,197,210,0,22,142,23,72,0,
+34,52,93,32,1,136,193,118,128,2,162,197,218,0,26,138,23,104,0,170,36,93,
+160,3,168,129,150,33,198,90,0,32,134,25,104,0,10,20,101,160,1,40,65,150,
+128,8,160,198,90,0,50,130,25,104,0,18,4,101,160,1,72,1,150,128,9,31,198,90,
+0,52,126,25,104,0,25,244,101,160,1,103,193,150,128,2,30,198,90,0,24,122,25,
+136,0,41,228,102,32,1,167,129,152,128,10,157,198,98,0,59,71,91,99,157,104,
+9,213,118,39,5,8,159,20,40,0,10,109,90,19,81,132,39,151,32,
+};
+#ifdef DUK_USE_BUILTIN_INITJS
+DUK_INTERNAL const duk_uint8_t duk_initjs_data[187] = {
+40,102,117,110,99,116,105,111,110,40,100,44,97,41,123,102,117,110,99,116,
+105,111,110,32,98,40,97,44,98,44,99,41,123,79,98,106,101,99,116,46,100,101,
+102,105,110,101,80,114,111,112,101,114,116,121,40,97,44,98,44,123,118,97,
+108,117,101,58,99,44,119,114,105,116,97,98,108,101,58,33,48,44,101,110,117,
+109,101,114,97,98,108,101,58,33,49,44,99,111,110,102,105,103,117,114,97,98,
+108,101,58,33,48,125,41,125,98,40,97,46,76,111,103,103,101,114,44,34,99,
+108,111,103,34,44,110,101,119,32,97,46,76,111,103,103,101,114,40,34,67,34,
+41,41,59,98,40,97,44,34,109,111,100,76,111,97,100,101,100,34,44,123,125,41,
+125,41,40,116,104,105,115,44,68,117,107,116,97,112,101,41,59,10,0,
+};
+#endif  /* DUK_USE_BUILTIN_INITJS */
+#else
+#error invalid endianness defines
+#endif
+#line 1 "duk_error_macros.c"
+/*
+ *  Error, fatal, and panic handling.
+ */
+
+/* include removed: duk_internal.h */
+
+#define DUK__ERRFMT_BUFSIZE  256  /* size for formatting buffers */
+
+#if defined(DUK_USE_VERBOSE_ERRORS)
+
+#if defined(DUK_USE_VARIADIC_MACROS)
+DUK_INTERNAL void duk_err_handle_error(const char *filename, duk_int_t line, duk_hthread *thr, duk_errcode_t code, const char *fmt, ...) {
+	va_list ap;
+	char msg[DUK__ERRFMT_BUFSIZE];
+	va_start(ap, fmt);
+	(void) DUK_VSNPRINTF(msg, sizeof(msg), fmt, ap);
+	msg[sizeof(msg) - 1] = (char) 0;
+	duk_err_create_and_throw(thr, code, msg, filename, line);
+	va_end(ap);  /* dead code, but ensures portability (see Linux man page notes) */
+}
+#else  /* DUK_USE_VARIADIC_MACROS */
+DUK_INTERNAL const char *duk_err_file_stash = NULL;
+DUK_INTERNAL duk_int_t duk_err_line_stash = 0;
+
+DUK_NORETURN(DUK_LOCAL_DECL void duk__handle_error(const char *filename, duk_int_t line, duk_hthread *thr, duk_errcode_t code, const char *fmt, va_list ap));
+
+DUK_LOCAL void duk__handle_error(const char *filename, duk_int_t line, duk_hthread *thr, duk_errcode_t code, const char *fmt, va_list ap) {
+	char msg[DUK__ERRFMT_BUFSIZE];
+	(void) DUK_VSNPRINTF(msg, sizeof(msg), fmt, ap);
+	msg[sizeof(msg) - 1] = (char) 0;
+	duk_err_create_and_throw(thr, code, msg, filename, line);
+}
+
+DUK_INTERNAL void duk_err_handle_error(const char *filename, duk_int_t line, duk_hthread *thr, duk_errcode_t code, const char *fmt, ...) {
+	va_list ap;
+	va_start(ap, fmt);
+	duk__handle_error(filename, line, thr, code, fmt, ap);
+	va_end(ap);  /* dead code */
+}
+
+DUK_INTERNAL void duk_err_handle_error_stash(duk_hthread *thr, duk_errcode_t code, const char *fmt, ...) {
+	va_list ap;
+	va_start(ap, fmt);
+	duk__handle_error(duk_err_file_stash, duk_err_line_stash, thr, code, fmt, ap);
+	va_end(ap);  /* dead code */
+}
+#endif  /* DUK_USE_VARIADIC_MACROS */
+
+#else  /* DUK_USE_VERBOSE_ERRORS */
+
+#if defined(DUK_USE_VARIADIC_MACROS)
+DUK_INTERNAL void duk_err_handle_error(duk_hthread *thr, duk_errcode_t code) {
+	duk_err_create_and_throw(thr, code);
+}
+
+#else  /* DUK_USE_VARIADIC_MACROS */
+DUK_INTERNAL void duk_err_handle_error_nonverbose1(duk_hthread *thr, duk_errcode_t code, const char *fmt, ...) {
+	DUK_UNREF(fmt);
+	duk_err_create_and_throw(thr, code);
+}
+
+DUK_INTERNAL void duk_err_handle_error_nonverbose2(const char *filename, duk_int_t line, duk_hthread *thr, duk_errcode_t code, const char *fmt, ...) {
+	DUK_UNREF(filename);
+	DUK_UNREF(line);
+	DUK_UNREF(fmt);
+	duk_err_create_and_throw(thr, code);
+}
+#endif  /* DUK_USE_VARIADIC_MACROS */
+
+#endif  /* DUK_USE_VERBOSE_ERRORS */
+
+/*
+ *  Error throwing helpers
+ */
+
+#if defined(DUK_USE_VERBOSE_ERRORS)
+#if defined(DUK_USE_PARANOID_ERRORS)
+DUK_INTERNAL void duk_err_require_type_index(const char *filename, duk_int_t linenumber, duk_hthread *thr, duk_idx_t index, const char *expect_name) {
+	DUK_ERROR_RAW(filename, linenumber, thr, DUK_ERR_TYPE_ERROR, "%s required, found %s (stack index %ld)",
+	              expect_name, duk_get_type_name((duk_context *) thr, index), (long) index);
+}
+#else
+DUK_INTERNAL void duk_err_require_type_index(const char *filename, duk_int_t linenumber, duk_hthread *thr, duk_idx_t index, const char *expect_name) {
+	DUK_ERROR_RAW(filename, linenumber, thr, DUK_ERR_TYPE_ERROR, "%s required, found %s (stack index %ld)",
+	              expect_name, duk_push_string_readable((duk_context *) thr, index), (long) index);
+}
+#endif
+DUK_INTERNAL void duk_err_api_index(const char *filename, duk_int_t linenumber, duk_hthread *thr, duk_idx_t index) {
+	DUK_ERROR_RAW(filename, linenumber, thr, DUK_ERR_API_ERROR, "invalid stack index %ld", (long) (index));
+}
+DUK_INTERNAL void duk_err_api(const char *filename, duk_int_t linenumber, duk_hthread *thr, const char *message) {
+	DUK_ERROR_RAW(filename, linenumber, thr, DUK_ERR_API_ERROR, message);
+}
+#else
+DUK_INTERNAL void duk_err_require_type_index(const char *filename, duk_int_t linenumber, duk_hthread *thr, const char *message) {
+	DUK_UNREF(filename); DUK_UNREF(linenumber); DUK_UNREF(message);
+	DUK_ERROR_RAW(filename, linenumber, thr, DUK_ERR_TYPE_ERROR, message);
+}
+DUK_INTERNAL void duk_err_api_index(const char *filename, duk_int_t linenumber, duk_hthread *thr) {
+	DUK_UNREF(filename); DUK_UNREF(linenumber);
+	DUK_ERROR(thr, DUK_ERR_API_ERROR, DUK_STR_INVALID_INDEX);
+}
+DUK_INTERNAL void duk_err_api(const char *filename, duk_int_t linenumber, duk_hthread *thr, const char *message) {
+	DUK_UNREF(filename); DUK_UNREF(linenumber); DUK_UNREF(message);
+	DUK_ERROR_RAW(filename, linenumber, thr, DUK_ERR_API_ERROR, message);
+}
+#endif
+
+/*
+ *  Default fatal error handler
+ */
+
+DUK_INTERNAL void duk_default_fatal_handler(duk_context *ctx, duk_errcode_t code, const char *msg) {
+	DUK_UNREF(ctx);
+#if defined(DUK_USE_FILE_IO)
+	DUK_FPRINTF(DUK_STDERR, "FATAL %ld: %s\n", (long) code, (const char *) (msg ? msg : "null"));
+	DUK_FFLUSH(DUK_STDERR);
+#else
+	/* omit print */
+#endif
+	DUK_D(DUK_DPRINT("default fatal handler called, code %ld -> calling DUK_PANIC()", (long) code));
+	DUK_PANIC(code, msg);
+	DUK_UNREACHABLE();
+}
+
+/*
+ *  Default panic handler
+ */
+
+#if !defined(DUK_USE_PANIC_HANDLER)
+DUK_INTERNAL void duk_default_panic_handler(duk_errcode_t code, const char *msg) {
+#if defined(DUK_USE_FILE_IO)
+	DUK_FPRINTF(DUK_STDERR, "PANIC %ld: %s ("
+#if defined(DUK_USE_PANIC_ABORT)
+	            "calling abort"
+#elif defined(DUK_USE_PANIC_EXIT)
+	            "calling exit"
+#elif defined(DUK_USE_PANIC_SEGFAULT)
+	            "segfaulting on purpose"
+#else
+#error no DUK_USE_PANIC_xxx macro defined
+#endif
+	            ")\n", (long) code, (const char *) (msg ? msg : "null"));
+	DUK_FFLUSH(DUK_STDERR);
+#else
+	/* omit print */
+	DUK_UNREF(code);
+	DUK_UNREF(msg);
+#endif
+
+#if defined(DUK_USE_PANIC_ABORT)
+	DUK_ABORT();
+#elif defined(DUK_USE_PANIC_EXIT)
+	DUK_EXIT(-1);
+#elif defined(DUK_USE_PANIC_SEGFAULT)
+	/* exit() afterwards to satisfy "noreturn" */
+	DUK_CAUSE_SEGFAULT();  /* SCANBUILD: "Dereference of null pointer", normal */
+	DUK_EXIT(-1);
+#else
+#error no DUK_USE_PANIC_xxx macro defined
+#endif
+
+	DUK_UNREACHABLE();
+}
+#endif  /* !DUK_USE_PANIC_HANDLER */
+
+#undef DUK__ERRFMT_BUFSIZE
+#line 1 "duk_unicode_support.c"
+/*
+ *  Various Unicode help functions for character classification predicates,
+ *  case conversion, decoding, etc.
+ */
+
+/* include removed: duk_internal.h */
+
+/*
+ *  XUTF-8 and CESU-8 encoding/decoding
+ */
+
+DUK_INTERNAL duk_small_int_t duk_unicode_get_xutf8_length(duk_ucodepoint_t cp) {
+	duk_uint_fast32_t x = (duk_uint_fast32_t) cp;
+	if (x < 0x80UL) {
+		/* 7 bits */
+		return 1;
+	} else if (x < 0x800UL) {
+		/* 11 bits */
+		return 2;
+	} else if (x < 0x10000UL) {
+		/* 16 bits */
+		return 3;
+	} else if (x < 0x200000UL) {
+		/* 21 bits */
+		return 4;
+	} else if (x < 0x4000000UL) {
+		/* 26 bits */
+		return 5;
+	} else if (x < (duk_ucodepoint_t) 0x80000000UL) {
+		/* 31 bits */
+		return 6;
+	} else {
+		/* 36 bits */
+		return 7;
+	}
+}
+
+#if defined(DUK_USE_ASSERTIONS)
+DUK_INTERNAL duk_small_int_t duk_unicode_get_cesu8_length(duk_ucodepoint_t cp) {
+	duk_uint_fast32_t x = (duk_uint_fast32_t) cp;
+	if (x < 0x80UL) {
+		/* 7 bits */
+		return 1;
+	} else if (x < 0x800UL) {
+		/* 11 bits */
+		return 2;
+	} else if (x < 0x10000UL) {
+		/* 16 bits */
+		return 3;
+	} else {
+		/* Encoded as surrogate pair, each encoding to 3 bytes for
+		 * 6 bytes total.  Codepoints above U+10FFFF encode as 6 bytes
+		 * too, see duk_unicode_encode_cesu8().
+		  */
+		return 3 + 3;
+	}
+}
+#endif  /* DUK_USE_ASSERTIONS */
+
+DUK_INTERNAL duk_uint8_t duk_unicode_xutf8_markers[7] = {
+	0x00, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe
+};
+
+/* Encode to extended UTF-8; 'out' must have space for at least
+ * DUK_UNICODE_MAX_XUTF8_LENGTH bytes.  Allows encoding of any
+ * 32-bit (unsigned) codepoint.
+ */
+DUK_INTERNAL duk_small_int_t duk_unicode_encode_xutf8(duk_ucodepoint_t cp, duk_uint8_t *out) {
+	duk_uint_fast32_t x = (duk_uint_fast32_t) cp;
+	duk_small_int_t len;
+	duk_uint8_t marker;
+	duk_small_int_t i;
+
+	len = duk_unicode_get_xutf8_length(cp);
+	DUK_ASSERT(len > 0);
+
+	marker = duk_unicode_xutf8_markers[len - 1];  /* 64-bit OK because always >= 0 */
+
+	i = len;
+	DUK_ASSERT(i > 0);
+	do {
+		i--;
+		if (i > 0) {
+			out[i] = (duk_uint8_t) (0x80 + (x & 0x3f));
+			x >>= 6;
+		} else {
+			/* Note: masking of 'x' is not necessary because of
+			 * range check and shifting -> no bits overlapping
+			 * the marker should be set.
+			 */
+			out[0] = (duk_uint8_t) (marker + x);
+		}
+	} while (i > 0);
+
+	return len;
+}
+
+/* Encode to CESU-8; 'out' must have space for at least
+ * DUK_UNICODE_MAX_CESU8_LENGTH bytes; codepoints above U+10FFFF
+ * will encode to garbage but won't overwrite the output buffer.
+ */
+DUK_INTERNAL duk_small_int_t duk_unicode_encode_cesu8(duk_ucodepoint_t cp, duk_uint8_t *out) {
+	duk_uint_fast32_t x = (duk_uint_fast32_t) cp;
+	duk_small_int_t len;
+
+	if (x < 0x80UL) {
+		out[0] = (duk_uint8_t) x;
+		len = 1;
+	} else if (x < 0x800UL) {
+		out[0] = (duk_uint8_t) (0xc0 + ((x >> 6) & 0x1f));
+		out[1] = (duk_uint8_t) (0x80 + (x & 0x3f));
+		len = 2;
+	} else if (x < 0x10000UL) {
+		/* surrogate pairs get encoded here */
+		out[0] = (duk_uint8_t) (0xe0 + ((x >> 12) & 0x0f));
+		out[1] = (duk_uint8_t) (0x80 + ((x >> 6) & 0x3f));
+		out[2] = (duk_uint8_t) (0x80 + (x & 0x3f));
+		len = 3;
+	} else {
+		/*
+		 *  Unicode codepoints above U+FFFF are encoded as surrogate
+		 *  pairs here.  This ensures that all CESU-8 codepoints are
+		 *  16-bit values as expected in Ecmascript.  The surrogate
+		 *  pairs always get a 3-byte encoding (each) in CESU-8.
+		 *  See: http://en.wikipedia.org/wiki/Surrogate_pair
+		 *
+		 *  20-bit codepoint, 10 bits (A and B) per surrogate pair:
+		 *
+		 *    x = 0b00000000 0000AAAA AAAAAABB BBBBBBBB
+		 *  sp1 = 0b110110AA AAAAAAAA  (0xd800 + ((x >> 10) & 0x3ff))
+		 *  sp2 = 0b110111BB BBBBBBBB  (0xdc00 + (x & 0x3ff))
+		 *
+		 *  Encoded into CESU-8:
+		 *
+		 *  sp1 -> 0b11101101  (0xe0 + ((sp1 >> 12) & 0x0f))
+		 *      -> 0b1010AAAA  (0x80 + ((sp1 >> 6) & 0x3f))
+		 *      -> 0b10AAAAAA  (0x80 + (sp1 & 0x3f))
+		 *  sp2 -> 0b11101101  (0xe0 + ((sp2 >> 12) & 0x0f))
+		 *      -> 0b1011BBBB  (0x80 + ((sp2 >> 6) & 0x3f))
+		 *      -> 0b10BBBBBB  (0x80 + (sp2 & 0x3f))
+		 *
+		 *  Note that 0x10000 must be subtracted first.  The code below
+		 *  avoids the sp1, sp2 temporaries which saves around 20 bytes
+		 *  of code.
+		 */
+
+		x -= 0x10000UL;
+
+		out[0] = (duk_uint8_t) (0xed);
+		out[1] = (duk_uint8_t) (0xa0 + ((x >> 16) & 0x0f));
+		out[2] = (duk_uint8_t) (0x80 + ((x >> 10) & 0x3f));
+		out[3] = (duk_uint8_t) (0xed);
+		out[4] = (duk_uint8_t) (0xb0 + ((x >> 6) & 0x0f));
+		out[5] = (duk_uint8_t) (0x80 + (x & 0x3f));
+		len = 6;
+	}
+
+	return len;
+}
+
+/* Decode helper.  Return zero on error. */
+DUK_INTERNAL duk_small_int_t duk_unicode_decode_xutf8(duk_hthread *thr, const duk_uint8_t **ptr, const duk_uint8_t *ptr_start, const duk_uint8_t *ptr_end, duk_ucodepoint_t *out_cp) {
+	const duk_uint8_t *p;
+	duk_uint32_t res;
+	duk_uint_fast8_t ch;
+	duk_small_int_t n;
+
+	DUK_UNREF(thr);
+
+	p = *ptr;
+	if (p < ptr_start || p >= ptr_end) {
+		goto fail;
+	}
+
+	/*
+	 *  UTF-8 decoder which accepts longer than standard byte sequences.
+	 *  This allows full 32-bit code points to be used.
+	 */
+
+	ch = (duk_uint_fast8_t) (*p++);
+	if (ch < 0x80) {
+		/* 0xxx xxxx   [7 bits] */
+		res = (duk_uint32_t) (ch & 0x7f);
+		n = 0;
+	} else if (ch < 0xc0) {
+		/* 10xx xxxx -> invalid */
+		goto fail;
+	} else if (ch < 0xe0) {
+		/* 110x xxxx   10xx xxxx   [11 bits] */
+		res = (duk_uint32_t) (ch & 0x1f);
+		n = 1;
+	} else if (ch < 0xf0) {
+		/* 1110 xxxx   10xx xxxx   10xx xxxx   [16 bits] */
+		res = (duk_uint32_t) (ch & 0x0f);
+		n = 2;
+	} else if (ch < 0xf8) {
+		/* 1111 0xxx   10xx xxxx   10xx xxxx   10xx xxxx   [21 bits] */
+		res = (duk_uint32_t) (ch & 0x07);
+		n = 3;
+	} else if (ch < 0xfc) {
+		/* 1111 10xx   10xx xxxx   10xx xxxx   10xx xxxx   10xx xxxx   [26 bits] */
+		res = (duk_uint32_t) (ch & 0x03);
+		n = 4;
+	} else if (ch < 0xfe) {
+		/* 1111 110x   10xx xxxx   10xx xxxx   10xx xxxx   10xx xxxx   10xx xxxx   [31 bits] */
+		res = (duk_uint32_t) (ch & 0x01);
+		n = 5;
+	} else if (ch < 0xff) {
+		/* 1111 1110   10xx xxxx   10xx xxxx   10xx xxxx   10xx xxxx   10xx xxxx   10xx xxxx   [36 bits] */
+		res = (duk_uint32_t) (0);
+		n = 6;
+	} else {
+		/* 8-byte format could be:
+		 * 1111 1111   10xx xxxx   10xx xxxx   10xx xxxx   10xx xxxx   10xx xxxx   10xx xxxx   10xx xxxx   [41 bits]
+		 *
+		 * However, this format would not have a zero bit following the
+		 * leading one bits and would not allow 0xFF to be used as an
+		 * "invalid xutf-8" marker for internal keys.  Further, 8-byte
+		 * encodings (up to 41 bit code points) are not currently needed.
+		 */
+		goto fail;
+	}
+
+	DUK_ASSERT(p >= ptr_start);  /* verified at beginning */
+	if (p + n > ptr_end) {
+		/* check pointer at end */
+		goto fail;
+	}
+
+	while (n > 0) {
+		DUK_ASSERT(p >= ptr_start && p < ptr_end);
+		res = res << 6;
+		res += (duk_uint32_t) ((*p++) & 0x3f);
+		n--;
+	}
+
+	*ptr = p;
+	*out_cp = res;
+	return 1;
+
+ fail:
+	return 0;
+}
+
+/* used by e.g. duk_regexp_executor.c, string built-ins */
+DUK_INTERNAL duk_ucodepoint_t duk_unicode_decode_xutf8_checked(duk_hthread *thr, const duk_uint8_t **ptr, const duk_uint8_t *ptr_start, const duk_uint8_t *ptr_end) {
+	duk_ucodepoint_t cp;
+
+	if (duk_unicode_decode_xutf8(thr, ptr, ptr_start, ptr_end, &cp)) {
+		return cp;
+	}
+	DUK_ERROR(thr, DUK_ERR_INTERNAL_ERROR, "utf-8 decode failed");
+	DUK_UNREACHABLE();
+	return 0;
+}
+
+/* Compute (extended) utf-8 length without codepoint encoding validation,
+ * used for string interning.
+ *
+ * NOTE: This algorithm is performance critical, more so than string hashing
+ * in some cases.  It is needed when interning a string and needs to scan
+ * every byte of the string with no skipping.  Having an ASCII fast path
+ * is useful if possible in the algorithm.  The current algorithms were
+ * chosen from several variants, based on x64 gcc -O2 testing.  See:
+ * https://github.com/svaarala/duktape/pull/422
+ */
+
+#if defined(DUK_USE_PREFER_SIZE)
+/* Small variant; roughly 150 bytes smaller than the fast variant. */
+DUK_INTERNAL duk_size_t duk_unicode_unvalidated_utf8_length(const duk_uint8_t *data, duk_size_t blen) {
+	const duk_uint8_t *p;
+	const duk_uint8_t *p_end;
+	duk_size_t ncont;
+	duk_size_t clen;
+
+	p = data;
+	p_end = data + blen;
+	ncont = 0;
+	while (p != p_end) {
+		duk_uint8_t x;
+		x = *p++;
+		if (DUK_UNLIKELY(x >= 0x80 && x <= 0xbf)) {
+			ncont++;
+		}
+	}
+
+	DUK_ASSERT(ncont <= blen);
+	clen = blen - ncont;
+	DUK_ASSERT(clen <= blen);
+	return clen;
+}
+#else  /* DUK_USE_PREFER_SIZE */
+/* This seems like a good overall approach.  Fast path for ASCII in 4 byte
+ * blocks.
+ */
+DUK_INTERNAL duk_size_t duk_unicode_unvalidated_utf8_length(const duk_uint8_t *data, duk_size_t blen) {
+	const duk_uint8_t *p;
+	const duk_uint8_t *p_end;
+	const duk_uint32_t *p32_end;
+	const duk_uint32_t *p32;
+	duk_size_t ncont;
+	duk_size_t clen;
+
+	ncont = 0;  /* number of continuation (non-initial) bytes in [0x80,0xbf] */
+	p = data;
+	p_end = data + blen;
+	if (blen < 16) {
+		goto skip_fastpath;
+	}
+
+	/* Align 'p' to 4; the input data may have arbitrary alignment.
+	 * End of string check not needed because blen >= 16.
+	 */
+	while (((duk_uintptr_t) (const void *) p) & 0x03) {
+		duk_uint8_t x;
+		x = *p++;
+		if (DUK_UNLIKELY(x >= 0x80 && x <= 0xbf)) {
+			ncont++;
+		}
+	}
+
+	/* Full, aligned 4-byte reads. */
+	p32_end = (const duk_uint32_t *) (const void *) (p + ((duk_size_t) (p_end - p) & (duk_size_t) (~0x03)));
+	p32 = (const duk_uint32_t *) (const void *) p;
+	while (p32 != (const duk_uint32_t *) p32_end) {
+		duk_uint32_t x;
+		x = *p32++;
+		if (DUK_LIKELY((x & 0x80808080UL) == 0)) {
+			;  /* ASCII fast path */
+		} else {
+			/* Flip highest bit of each byte which changes
+			 * the bit pattern 10xxxxxx into 00xxxxxx which
+			 * allows an easy bit mask test.
+			 */
+			x ^= 0x80808080UL;
+			if (DUK_UNLIKELY(!(x & 0xc0000000UL))) {
+				ncont++;
+			}
+			if (DUK_UNLIKELY(!(x & 0x00c00000UL))) {
+				ncont++;
+			}
+			if (DUK_UNLIKELY(!(x & 0x0000c000UL))) {
+				ncont++;
+			}
+			if (DUK_UNLIKELY(!(x & 0x000000c0UL))) {
+				ncont++;
+			}
+		}
+	}
+	p = (const duk_uint8_t *) p32;
+	/* Fall through to handle the rest. */
+
+ skip_fastpath:
+	while (p != p_end) {
+		duk_uint8_t x;
+		x = *p++;
+		if (DUK_UNLIKELY(x >= 0x80 && x <= 0xbf)) {
+			ncont++;
+		}
+	}
+
+	DUK_ASSERT(ncont <= blen);
+	clen = blen - ncont;
+	DUK_ASSERT(clen <= blen);
+	return clen;
+}
+#endif  /* DUK_USE_PREFER_SIZE */
+
+/*
+ *  Unicode range matcher
+ *
+ *  Matches a codepoint against a packed bitstream of character ranges.
+ *  Used for slow path Unicode matching.
+ */
+
+/* Must match src/extract_chars.py, generate_match_table3(). */
+DUK_LOCAL duk_uint32_t duk__uni_decode_value(duk_bitdecoder_ctx *bd_ctx) {
+	duk_uint32_t t;
+
+	t = (duk_uint32_t) duk_bd_decode(bd_ctx, 4);
+	if (t <= 0x0eU) {
+		return t;
+	}
+	t = (duk_uint32_t) duk_bd_decode(bd_ctx, 8);
+	if (t <= 0xfdU) {
+		return t + 0x0f;
+	}
+	if (t == 0xfeU) {
+		t = (duk_uint32_t) duk_bd_decode(bd_ctx, 12);
+		return t + 0x0fU + 0xfeU;
+	} else {
+		t = (duk_uint32_t) duk_bd_decode(bd_ctx, 24);
+		return t + 0x0fU + 0xfeU + 0x1000UL;
+	}
+}
+
+DUK_LOCAL duk_small_int_t duk__uni_range_match(const duk_uint8_t *unitab, duk_size_t unilen, duk_codepoint_t cp) {
+	duk_bitdecoder_ctx bd_ctx;
+	duk_codepoint_t prev_re;
+
+	DUK_MEMZERO(&bd_ctx, sizeof(bd_ctx));
+	bd_ctx.data = (const duk_uint8_t *) unitab;
+	bd_ctx.length = (duk_size_t) unilen;
+
+	prev_re = 0;
+	for (;;) {
+		duk_codepoint_t r1, r2;
+		r1 = (duk_codepoint_t) duk__uni_decode_value(&bd_ctx);
+		if (r1 == 0) {
+			break;
+		}
+		r2 = (duk_codepoint_t) duk__uni_decode_value(&bd_ctx);
+
+		r1 = prev_re + r1;
+		r2 = r1 + r2;
+		prev_re = r2;
+
+		/* [r1,r2] is the range */
+
+		DUK_DDD(DUK_DDDPRINT("duk__uni_range_match: cp=%06lx range=[0x%06lx,0x%06lx]",
+		                     (unsigned long) cp, (unsigned long) r1, (unsigned long) r2));
+		if (cp >= r1 && cp <= r2) {
+			return 1;
+		}
+	}
+
+	return 0;
+}
+
+/*
+ *  "WhiteSpace" production check.
+ */
+
+DUK_INTERNAL duk_small_int_t duk_unicode_is_whitespace(duk_codepoint_t cp) {
+	/*
+	 *  E5 Section 7.2 specifies six characters specifically as
+	 *  white space:
+	 *
+	 *    0009;<control>;Cc;0;S;;;;;N;CHARACTER TABULATION;;;;
+	 *    000B;<control>;Cc;0;S;;;;;N;LINE TABULATION;;;;
+	 *    000C;<control>;Cc;0;WS;;;;;N;FORM FEED (FF);;;;
+	 *    0020;SPACE;Zs;0;WS;;;;;N;;;;;
+	 *    00A0;NO-BREAK SPACE;Zs;0;CS;<noBreak> 0020;;;;N;NON-BREAKING SPACE;;;;
+	 *    FEFF;ZERO WIDTH NO-BREAK SPACE;Cf;0;BN;;;;;N;BYTE ORDER MARK;;;;
+	 *
+	 *  It also specifies any Unicode category 'Zs' characters as white
+	 *  space.  These can be extracted with the "src/extract_chars.py" script.
+	 *  Current result:
+	 *
+	 *    RAW OUTPUT:
+	 *    ===========
+	 *    0020;SPACE;Zs;0;WS;;;;;N;;;;;
+	 *    00A0;NO-BREAK SPACE;Zs;0;CS;<noBreak> 0020;;;;N;NON-BREAKING SPACE;;;;
+	 *    1680;OGHAM SPACE MARK;Zs;0;WS;;;;;N;;;;;
+	 *    180E;MONGOLIAN VOWEL SEPARATOR;Zs;0;WS;;;;;N;;;;;
+	 *    2000;EN QUAD;Zs;0;WS;2002;;;;N;;;;;
+	 *    2001;EM QUAD;Zs;0;WS;2003;;;;N;;;;;
+	 *    2002;EN SPACE;Zs;0;WS;<compat> 0020;;;;N;;;;;
+	 *    2003;EM SPACE;Zs;0;WS;<compat> 0020;;;;N;;;;;
+	 *    2004;THREE-PER-EM SPACE;Zs;0;WS;<compat> 0020;;;;N;;;;;
+	 *    2005;FOUR-PER-EM SPACE;Zs;0;WS;<compat> 0020;;;;N;;;;;
+	 *    2006;SIX-PER-EM SPACE;Zs;0;WS;<compat> 0020;;;;N;;;;;
+	 *    2007;FIGURE SPACE;Zs;0;WS;<noBreak> 0020;;;;N;;;;;
+	 *    2008;PUNCTUATION SPACE;Zs;0;WS;<compat> 0020;;;;N;;;;;
+	 *    2009;THIN SPACE;Zs;0;WS;<compat> 0020;;;;N;;;;;
+	 *    200A;HAIR SPACE;Zs;0;WS;<compat> 0020;;;;N;;;;;
+	 *    202F;NARROW NO-BREAK SPACE;Zs;0;CS;<noBreak> 0020;;;;N;;;;;
+	 *    205F;MEDIUM MATHEMATICAL SPACE;Zs;0;WS;<compat> 0020;;;;N;;;;;
+	 *    3000;IDEOGRAPHIC SPACE;Zs;0;WS;<wide> 0020;;;;N;;;;;
+	 *
+	 *    RANGES:
+	 *    =======
+	 *    0x0020
+	 *    0x00a0
+	 *    0x1680
+	 *    0x180e
+	 *    0x2000 ... 0x200a
+	 *    0x202f
+	 *    0x205f
+	 *    0x3000
+	 *
+	 *  A manual decoder (below) is probably most compact for this.
+	 */
+
+	duk_uint_fast8_t lo;
+	duk_uint_fast32_t hi;
+
+	/* cp == -1 (EOF) never matches and causes return value 0 */
+
+	lo = (duk_uint_fast8_t) (cp & 0xff);
+	hi = (duk_uint_fast32_t) (cp >> 8);  /* does not fit into an uchar */
+
+	if (hi == 0x0000UL) {
+		if (lo == 0x09U || lo == 0x0bU || lo == 0x0cU ||
+		    lo == 0x20U || lo == 0xa0U) {
+			return 1;
+		}
+	} else if (hi == 0x0020UL) {
+		if (lo <= 0x0aU || lo == 0x2fU || lo == 0x5fU) {
+			return 1;
+		}
+	} else if (cp == 0x1680L || cp == 0x180eL || cp == 0x3000L ||
+	           cp == 0xfeffL) {
+		return 1;
+	}
+
+	return 0;
+}
+
+/*
+ *  "LineTerminator" production check.
+ */
+
+DUK_INTERNAL duk_small_int_t duk_unicode_is_line_terminator(duk_codepoint_t cp) {
+	/*
+	 *  E5 Section 7.3
+	 *
+	 *  A LineTerminatorSequence essentially merges <CR> <LF> sequences
+	 *  into a single line terminator.  This must be handled by the caller.
+	 */
+
+	if (cp == 0x000aL || cp == 0x000dL || cp == 0x2028L ||
+	    cp == 0x2029L) {
+		return 1;
+	}
+
+	return 0;
+}
+
+/*
+ *  "IdentifierStart" production check.
+ */
+
+DUK_INTERNAL duk_small_int_t duk_unicode_is_identifier_start(duk_codepoint_t cp) {
+	/*
+	 *  E5 Section 7.6:
+	 *
+	 *    IdentifierStart:
+	 *      UnicodeLetter
+	 *      $
+	 *      _
+	 *      \ UnicodeEscapeSequence
+	 *
+	 *  IdentifierStart production has one multi-character production:
+	 *
+	 *    \ UnicodeEscapeSequence
+	 *
+	 *  The '\' character is -not- matched by this function.  Rather, the caller
+	 *  should decode the escape and then call this function to check whether the
+	 *  decoded character is acceptable (see discussion in E5 Section 7.6).
+	 *
+	 *  The "UnicodeLetter" alternative of the production allows letters
+	 *  from various Unicode categories.  These can be extracted with the
+	 *  "src/extract_chars.py" script.
+	 *
+	 *  Because the result has hundreds of Unicode codepoint ranges, matching
+	 *  for any values >= 0x80 are done using a very slow range-by-range scan
+	 *  and a packed range format.
+	 *
+	 *  The ASCII portion (codepoints 0x00 ... 0x7f) is fast-pathed below because
+	 *  it matters the most.  The ASCII related ranges of IdentifierStart are:
+	 *
+	 *    0x0041 ... 0x005a     ['A' ... 'Z']
+	 *    0x0061 ... 0x007a     ['a' ... 'z']
+	 *    0x0024                ['$']
+	 *    0x005f                ['_']
+	 */
+
+	/* ASCII (and EOF) fast path -- quick accept and reject */
+	if (cp <= 0x7fL) {
+		if ((cp >= 'a' && cp <= 'z') ||
+		    (cp >= 'A' && cp <= 'Z') ||
+		    cp == '_' || cp == '$') {
+			return 1;
+		}
+		return 0;
+	}
+
+	/* Non-ASCII slow path (range-by-range linear comparison), very slow */
+
+#ifdef DUK_USE_SOURCE_NONBMP
+	if (duk__uni_range_match(duk_unicode_ids_noa,
+	                         (duk_size_t) sizeof(duk_unicode_ids_noa),
+	                         (duk_codepoint_t) cp)) {
+		return 1;
+	}
+	return 0;
+#else
+	if (cp < 0x10000L) {
+		if (duk__uni_range_match(duk_unicode_ids_noabmp,
+		                         sizeof(duk_unicode_ids_noabmp),
+		                         (duk_codepoint_t) cp)) {
+			return 1;
+		}
+		return 0;
+	} else {
+		/* without explicit non-BMP support, assume non-BMP characters
+		 * are always accepted as identifier characters.
+		 */
+		return 1;
+	}
+#endif
+}
+
+/*
+ *  "IdentifierPart" production check.
+ */
+
+DUK_INTERNAL duk_small_int_t duk_unicode_is_identifier_part(duk_codepoint_t cp) {
+	/*
+	 *  E5 Section 7.6:
+	 *
+	 *    IdentifierPart:
+	 *      IdentifierStart
+	 *      UnicodeCombiningMark
+	 *      UnicodeDigit
+	 *      UnicodeConnectorPunctuation
+	 *      <ZWNJ>  [U+200C]
+	 *      <ZWJ>   [U+200D]
+	 *
+	 *  IdentifierPart production has one multi-character production
+	 *  as part of its IdentifierStart alternative.  The '\' character
+	 *  of an escape sequence is not matched here, see discussion in
+	 *  duk_unicode_is_identifier_start().
+	 *
+	 *  To match non-ASCII characters (codepoints >= 0x80), a very slow
+	 *  linear range-by-range scan is used.  The codepoint is first compared
+	 *  to the IdentifierStart ranges, and if it doesn't match, then to a
+	 *  set consisting of code points in IdentifierPart but not in
+	 *  IdentifierStart.  This is done to keep the unicode range data small,
+	 *  at the expense of speed.
+	 *
+	 *  The ASCII fast path consists of:
+	 *
+	 *    0x0030 ... 0x0039     ['0' ... '9', UnicodeDigit]
+	 *    0x0041 ... 0x005a     ['A' ... 'Z', IdentifierStart]
+	 *    0x0061 ... 0x007a     ['a' ... 'z', IdentifierStart]
+	 *    0x0024                ['$', IdentifierStart]
+	 *    0x005f                ['_', IdentifierStart and
+	 *                                UnicodeConnectorPunctuation]
+	 *
+	 *  UnicodeCombiningMark has no code points <= 0x7f.
+	 *
+	 *  The matching code reuses the "identifier start" tables, and then
+	 *  consults a separate range set for characters in "identifier part"
+	 *  but not in "identifier start".  These can be extracted with the
+	 *  "src/extract_chars.py" script.
+	 *
+	 *  UnicodeCombiningMark -> categories Mn, Mc
+	 *  UnicodeDigit -> categories Nd
+	 *  UnicodeConnectorPunctuation -> categories Pc
+	 */
+
+	/* ASCII (and EOF) fast path -- quick accept and reject */
+	if (cp <= 0x7fL) {
+		if ((cp >= 'a' && cp <= 'z') ||
+		    (cp >= 'A' && cp <= 'Z') ||
+		    (cp >= '0' && cp <= '9') ||
+		    cp == '_' || cp == '$') {
+			return 1;
+		}
+		return 0;
+	}
+
+	/* Non-ASCII slow path (range-by-range linear comparison), very slow */
+
+#ifdef DUK_USE_SOURCE_NONBMP
+	if (duk__uni_range_match(duk_unicode_ids_noa,
+	                         sizeof(duk_unicode_ids_noa),
+	                         (duk_codepoint_t) cp) ||
+	    duk__uni_range_match(duk_unicode_idp_m_ids_noa,
+	                         sizeof(duk_unicode_idp_m_ids_noa),
+	                         (duk_codepoint_t) cp)) {
+		return 1;
+	}
+	return 0;
+#else
+	if (cp < 0x10000L) {
+		if (duk__uni_range_match(duk_unicode_ids_noabmp,
+		                         sizeof(duk_unicode_ids_noabmp),
+		                         (duk_codepoint_t) cp) ||
+		    duk__uni_range_match(duk_unicode_idp_m_ids_noabmp,
+		                         sizeof(duk_unicode_idp_m_ids_noabmp),
+		                         (duk_codepoint_t) cp)) {
+			return 1;
+		}
+		return 0;
+	} else {
+		/* without explicit non-BMP support, assume non-BMP characters
+		 * are always accepted as identifier characters.
+		 */
+		return 1;
+	}
+#endif
+}
+
+/*
+ *  Unicode letter check.
+ */
+
+DUK_INTERNAL duk_small_int_t duk_unicode_is_letter(duk_codepoint_t cp) {
+	/*
+	 *  Unicode letter is now taken to be the categories:
+	 *
+	 *    Lu, Ll, Lt, Lm, Lo
+	 *
+	 *  (Not sure if this is exactly correct.)
+	 *
+	 *  The ASCII fast path consists of:
+	 *
+	 *    0x0041 ... 0x005a     ['A' ... 'Z']
+	 *    0x0061 ... 0x007a     ['a' ... 'z']
+	 */
+
+	/* ASCII (and EOF) fast path -- quick accept and reject */
+	if (cp <= 0x7fL) {
+		if ((cp >= 'a' && cp <= 'z') ||
+		    (cp >= 'A' && cp <= 'Z')) {
+			return 1;
+		}
+		return 0;
+	}
+
+	/* Non-ASCII slow path (range-by-range linear comparison), very slow */
+
+#ifdef DUK_USE_SOURCE_NONBMP
+	if (duk__uni_range_match(duk_unicode_ids_noa,
+	                         sizeof(duk_unicode_ids_noa),
+	                         (duk_codepoint_t) cp) &&
+	    !duk__uni_range_match(duk_unicode_ids_m_let_noa,
+	                          sizeof(duk_unicode_ids_m_let_noa),
+	                          (duk_codepoint_t) cp)) {
+		return 1;
+	}
+	return 0;
+#else
+	if (cp < 0x10000L) {
+		if (duk__uni_range_match(duk_unicode_ids_noabmp,
+		                         sizeof(duk_unicode_ids_noabmp),
+		                         (duk_codepoint_t) cp) &&
+		    !duk__uni_range_match(duk_unicode_ids_m_let_noabmp,
+		                          sizeof(duk_unicode_ids_m_let_noabmp),
+		                          (duk_codepoint_t) cp)) {
+			return 1;
+		}
+		return 0;
+	} else {
+		/* without explicit non-BMP support, assume non-BMP characters
+		 * are always accepted as letters.
+		 */
+		return 1;
+	}
+#endif
+}
+
+/*
+ *  Complex case conversion helper which decodes a bit-packed conversion
+ *  control stream generated by unicode/extract_caseconv.py.  The conversion
+ *  is very slow because it runs through the conversion data in a linear
+ *  fashion to save space (which is why ASCII characters have a special
+ *  fast path before arriving here).
+ *
+ *  The particular bit counts etc have been determined experimentally to
+ *  be small but still sufficient, and must match the Python script
+ *  (src/extract_caseconv.py).
+ *
+ *  The return value is the case converted codepoint or -1 if the conversion
+ *  results in multiple characters (this is useful for regexp Canonicalization
+ *  operation).  If 'buf' is not NULL, the result codepoint(s) are also
+ *  appended to the hbuffer.
+ *
+ *  Context and locale specific rules must be checked before consulting
+ *  this function.
+ */
+
+DUK_LOCAL
+duk_codepoint_t duk__slow_case_conversion(duk_hthread *thr,
+                                          duk_bufwriter_ctx *bw,
+                                          duk_codepoint_t cp,
+                                          duk_bitdecoder_ctx *bd_ctx) {
+	duk_small_int_t skip = 0;
+	duk_small_int_t n;
+	duk_small_int_t t;
+	duk_small_int_t count;
+	duk_codepoint_t tmp_cp;
+	duk_codepoint_t start_i;
+	duk_codepoint_t start_o;
+
+	DUK_UNREF(thr);
+	DUK_ASSERT(bd_ctx != NULL);
+
+	DUK_DDD(DUK_DDDPRINT("slow case conversion for codepoint: %ld", (long) cp));
+
+	/* range conversion with a "skip" */
+	DUK_DDD(DUK_DDDPRINT("checking ranges"));
+	for (;;) {
+		skip++;
+		n = (duk_small_int_t) duk_bd_decode(bd_ctx, 6);
+		if (n == 0x3f) {
+			/* end marker */
+			break;
+		}
+		DUK_DDD(DUK_DDDPRINT("skip=%ld, n=%ld", (long) skip, (long) n));
+
+		while (n--) {
+			start_i = (duk_codepoint_t) duk_bd_decode(bd_ctx, 16);
+			start_o = (duk_codepoint_t) duk_bd_decode(bd_ctx, 16);
+			count = (duk_small_int_t) duk_bd_decode(bd_ctx, 7);
+			DUK_DDD(DUK_DDDPRINT("range: start_i=%ld, start_o=%ld, count=%ld, skip=%ld",
+			                     (long) start_i, (long) start_o, (long) count, (long) skip));
+
+			if (cp >= start_i) {
+				tmp_cp = cp - start_i;  /* always >= 0 */
+				if (tmp_cp < (duk_codepoint_t) count * (duk_codepoint_t) skip &&
+				    (tmp_cp % (duk_codepoint_t) skip) == 0) {
+					DUK_DDD(DUK_DDDPRINT("range matches input codepoint"));
+					cp = start_o + tmp_cp;
+					goto single;
+				}
+			}
+		}
+	}
+
+	/* 1:1 conversion */
+	n = (duk_small_int_t) duk_bd_decode(bd_ctx, 6);
+	DUK_DDD(DUK_DDDPRINT("checking 1:1 conversions (count %ld)", (long) n));
+	while (n--) {
+		start_i = (duk_codepoint_t) duk_bd_decode(bd_ctx, 16);
+		start_o = (duk_codepoint_t) duk_bd_decode(bd_ctx, 16);
+		DUK_DDD(DUK_DDDPRINT("1:1 conversion %ld -> %ld", (long) start_i, (long) start_o));
+		if (cp == start_i) {
+			DUK_DDD(DUK_DDDPRINT("1:1 matches input codepoint"));
+			cp = start_o;
+			goto single;
+		}
+	}
+
+	/* complex, multicharacter conversion */
+	n = (duk_small_int_t) duk_bd_decode(bd_ctx, 7);
+	DUK_DDD(DUK_DDDPRINT("checking 1:n conversions (count %ld)", (long) n));
+	while (n--) {
+		start_i = (duk_codepoint_t) duk_bd_decode(bd_ctx, 16);
+		t = (duk_small_int_t) duk_bd_decode(bd_ctx, 2);
+		DUK_DDD(DUK_DDDPRINT("1:n conversion %ld -> %ld chars", (long) start_i, (long) t));
+		if (cp == start_i) {
+			DUK_DDD(DUK_DDDPRINT("1:n matches input codepoint"));
+			if (bw != NULL) {
+				while (t--) {
+					tmp_cp = (duk_codepoint_t) duk_bd_decode(bd_ctx, 16);
+					DUK_BW_WRITE_RAW_XUTF8(thr, bw, (duk_ucodepoint_t) tmp_cp);
+				}
+			}
+			return -1;
+		} else {
+			while (t--) {
+				(void) duk_bd_decode(bd_ctx, 16);
+			}
+		}
+	}
+
+	/* default: no change */
+	DUK_DDD(DUK_DDDPRINT("no rule matches, output is same as input"));
+	/* fall through */
+
+ single:
+	if (bw != NULL) {
+		DUK_BW_WRITE_RAW_XUTF8(thr, bw, (duk_ucodepoint_t) cp);
+	}
+	return cp;
+}
+
+/*
+ *  Case conversion helper, with context/local sensitivity.
+ *  For proper case conversion, one needs to know the character
+ *  and the preceding and following characters, as well as
+ *  locale/language.
+ */
+
+/* XXX: add 'language' argument when locale/language sensitive rule
+ * support added.
+ */
+DUK_LOCAL
+duk_codepoint_t duk__case_transform_helper(duk_hthread *thr,
+                                           duk_bufwriter_ctx *bw,
+                                           duk_codepoint_t cp,
+                                           duk_codepoint_t prev,
+                                           duk_codepoint_t next,
+                                           duk_bool_t uppercase) {
+	duk_bitdecoder_ctx bd_ctx;
+
+	/* fast path for ASCII */
+	if (cp < 0x80L) {
+		/* XXX: there are language sensitive rules for the ASCII range.
+		 * If/when language/locale support is implemented, they need to
+		 * be implemented here for the fast path.  There are no context
+		 * sensitive rules for ASCII range.
+		 */
+
+		if (uppercase) {
+			if (cp >= 'a' && cp <= 'z') {
+				cp = cp - 'a' + 'A';
+			}
+		} else {
+			if (cp >= 'A' && cp <= 'Z') {
+				cp = cp - 'A' + 'a';
+			}
+		}
+
+		if (bw != NULL) {
+			DUK_BW_WRITE_RAW_U8(thr, bw, (duk_uint8_t) cp);
+		}
+		return cp;
+	}
+
+	/* context and locale specific rules which cannot currently be represented
+	 * in the caseconv bitstream: hardcoded rules in C
+	 */
+	if (uppercase) {
+		/* XXX: turkish / azeri */
+	} else {
+		/*
+		 *  Final sigma context specific rule.  This is a rather tricky
+		 *  rule and this handling is probably not 100% correct now.
+		 *  The rule is not locale/language specific so it is supported.
+		 */
+
+		if (cp == 0x03a3L &&    /* U+03A3 = GREEK CAPITAL LETTER SIGMA */
+		    duk_unicode_is_letter(prev) &&        /* prev exists and is not a letter */
+		    !duk_unicode_is_letter(next)) {       /* next does not exist or next is not a letter */
+			/* Capital sigma occurred at "end of word", lowercase to
+			 * U+03C2 = GREEK SMALL LETTER FINAL SIGMA.  Otherwise
+			 * fall through and let the normal rules lowercase it to
+			 * U+03C3 = GREEK SMALL LETTER SIGMA.
+			 */
+			cp = 0x03c2L;
+			goto singlechar;
+		}
+
+		/* XXX: lithuanian not implemented */
+		/* XXX: lithuanian, explicit dot rules */
+		/* XXX: turkish / azeri, lowercase rules */
+	}
+
+	/* 1:1 or special conversions, but not locale/context specific: script generated rules */
+	DUK_MEMZERO(&bd_ctx, sizeof(bd_ctx));
+	if (uppercase) {
+		bd_ctx.data = (const duk_uint8_t *) duk_unicode_caseconv_uc;
+		bd_ctx.length = (duk_size_t) sizeof(duk_unicode_caseconv_uc);
+	} else {
+		bd_ctx.data = (const duk_uint8_t *) duk_unicode_caseconv_lc;
+		bd_ctx.length = (duk_size_t) sizeof(duk_unicode_caseconv_lc);
+	}
+	return duk__slow_case_conversion(thr, bw, cp, &bd_ctx);
+
+ singlechar:
+	if (bw != NULL) {
+		DUK_BW_WRITE_RAW_XUTF8(thr, bw, (duk_ucodepoint_t) cp);
+	}
+	return cp;
+
+ /* unused now, not needed until Turkish/Azeri */
+#if 0
+ nochar:
+	return -1;
+#endif
+}
+
+/*
+ *  Replace valstack top with case converted version.
+ */
+
+DUK_INTERNAL void duk_unicode_case_convert_string(duk_hthread *thr, duk_small_int_t uppercase) {
+	duk_context *ctx = (duk_context *) thr;
+	duk_hstring *h_input;
+	duk_bufwriter_ctx bw_alloc;
+	duk_bufwriter_ctx *bw;
+	const duk_uint8_t *p, *p_start, *p_end;
+	duk_codepoint_t prev, curr, next;
+
+	h_input = duk_require_hstring(ctx, -1);
+	DUK_ASSERT(h_input != NULL);
+
+	bw = &bw_alloc;
+	DUK_BW_INIT_PUSHBUF(thr, bw, DUK_HSTRING_GET_BYTELEN(h_input));
+
+	/* [ ... input buffer ] */
+
+	p_start = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_input);
+	p_end = p_start + DUK_HSTRING_GET_BYTELEN(h_input);
+	p = p_start;
+
+	prev = -1; DUK_UNREF(prev);
+	curr = -1;
+	next = -1;
+	for (;;) {
+		prev = curr;
+		curr = next;
+		next = -1;
+		if (p < p_end) {
+			next = (int) duk_unicode_decode_xutf8_checked(thr, &p, p_start, p_end);
+		} else {
+			/* end of input and last char has been processed */
+			if (curr < 0) {
+				break;
+			}
+		}
+
+		/* on first round, skip */
+		if (curr >= 0) {
+			/* XXX: could add a fast path to process chunks of input codepoints,
+			 * but relative benefit would be quite small.
+			 */
+
+			/* Ensure space for maximum multi-character result; estimate is overkill. */
+			DUK_BW_ENSURE(thr, bw, 8 * DUK_UNICODE_MAX_XUTF8_LENGTH);
+
+			duk__case_transform_helper(thr,
+			                           bw,
+			                           (duk_codepoint_t) curr,
+			                           prev,
+			                           next,
+			                           uppercase);
+		}
+	}
+
+	DUK_BW_COMPACT(thr, bw);
+	duk_to_string(ctx, -1);  /* invalidates h_buf pointer */
+	duk_remove(ctx, -2);
+}
+
+#ifdef DUK_USE_REGEXP_SUPPORT
+
+/*
+ *  Canonicalize() abstract operation needed for canonicalization of individual
+ *  codepoints during regexp compilation and execution, see E5 Section 15.10.2.8.
+ *  Note that codepoints are canonicalized one character at a time, so no context
+ *  specific rules can apply.  Locale specific rules can apply, though.
+ */
+
+DUK_INTERNAL duk_codepoint_t duk_unicode_re_canonicalize_char(duk_hthread *thr, duk_codepoint_t cp) {
+#if defined(DUK_USE_REGEXP_CANON_WORKAROUND)
+	/* Fast canonicalization lookup at the cost of 128kB footprint. */
+	DUK_ASSERT(cp >= 0);
+	DUK_UNREF(thr);
+	if (DUK_LIKELY(cp < 0x10000L)) {
+		return (duk_codepoint_t) duk_unicode_re_canon_lookup[cp];
+	}
+	return cp;
+#else  /* DUK_USE_REGEXP_CANON_WORKAROUND */
+	duk_codepoint_t y;
+
+	y = duk__case_transform_helper(thr,
+	                               NULL,    /* NULL is allowed, no output */
+	                               cp,      /* curr char */
+	                               -1,      /* prev char */
+	                               -1,      /* next char */
+	                               1);      /* uppercase */
+
+	if ((y < 0) || (cp >= 0x80 && y < 0x80)) {
+		/* multiple codepoint conversion or non-ASCII mapped to ASCII
+		 * --> leave as is.
+		 */
+		return cp;
+	}
+
+	return y;
+#endif  /* DUK_USE_REGEXP_CANON_WORKAROUND */
+}
+
+/*
+ *  E5 Section 15.10.2.6 "IsWordChar" abstract operation.  Assume
+ *  x < 0 for characters read outside the string.
+ */
+
+DUK_INTERNAL duk_small_int_t duk_unicode_re_is_wordchar(duk_codepoint_t x) {
+	/*
+	 *  Note: the description in E5 Section 15.10.2.6 has a typo, it
+	 *  contains 'A' twice and lacks 'a'; the intent is [0-9a-zA-Z_].
+	 */
+	if ((x >= '0' && x <= '9') ||
+	    (x >= 'a' && x <= 'z') ||
+	    (x >= 'A' && x <= 'Z') ||
+	    (x == '_')) {
+		return 1;
+	}
+	return 0;
+}
+
+/*
+ *  Regexp range tables
+ */
+
+/* exposed because lexer needs these too */
+DUK_INTERNAL duk_uint16_t duk_unicode_re_ranges_digit[2] = {
+	(duk_uint16_t) 0x0030UL, (duk_uint16_t) 0x0039UL,
+};
+DUK_INTERNAL duk_uint16_t duk_unicode_re_ranges_white[22] = {
+	(duk_uint16_t) 0x0009UL, (duk_uint16_t) 0x000DUL,
+	(duk_uint16_t) 0x0020UL, (duk_uint16_t) 0x0020UL,
+	(duk_uint16_t) 0x00A0UL, (duk_uint16_t) 0x00A0UL,
+	(duk_uint16_t) 0x1680UL, (duk_uint16_t) 0x1680UL,
+	(duk_uint16_t) 0x180EUL, (duk_uint16_t) 0x180EUL,
+	(duk_uint16_t) 0x2000UL, (duk_uint16_t) 0x200AUL,
+	(duk_uint16_t) 0x2028UL, (duk_uint16_t) 0x2029UL,
+	(duk_uint16_t) 0x202FUL, (duk_uint16_t) 0x202FUL,
+	(duk_uint16_t) 0x205FUL, (duk_uint16_t) 0x205FUL,
+	(duk_uint16_t) 0x3000UL, (duk_uint16_t) 0x3000UL,
+	(duk_uint16_t) 0xFEFFUL, (duk_uint16_t) 0xFEFFUL,
+};
+DUK_INTERNAL duk_uint16_t duk_unicode_re_ranges_wordchar[8] = {
+	(duk_uint16_t) 0x0030UL, (duk_uint16_t) 0x0039UL,
+	(duk_uint16_t) 0x0041UL, (duk_uint16_t) 0x005AUL,
+	(duk_uint16_t) 0x005FUL, (duk_uint16_t) 0x005FUL,
+	(duk_uint16_t) 0x0061UL, (duk_uint16_t) 0x007AUL,
+};
+DUK_INTERNAL duk_uint16_t duk_unicode_re_ranges_not_digit[4] = {
+	(duk_uint16_t) 0x0000UL, (duk_uint16_t) 0x002FUL,
+	(duk_uint16_t) 0x003AUL, (duk_uint16_t) 0xFFFFUL,
+};
+DUK_INTERNAL duk_uint16_t duk_unicode_re_ranges_not_white[24] = {
+	(duk_uint16_t) 0x0000UL, (duk_uint16_t) 0x0008UL,
+	(duk_uint16_t) 0x000EUL, (duk_uint16_t) 0x001FUL,
+	(duk_uint16_t) 0x0021UL, (duk_uint16_t) 0x009FUL,
+	(duk_uint16_t) 0x00A1UL, (duk_uint16_t) 0x167FUL,
+	(duk_uint16_t) 0x1681UL, (duk_uint16_t) 0x180DUL,
+	(duk_uint16_t) 0x180FUL, (duk_uint16_t) 0x1FFFUL,
+	(duk_uint16_t) 0x200BUL, (duk_uint16_t) 0x2027UL,
+	(duk_uint16_t) 0x202AUL, (duk_uint16_t) 0x202EUL,
+	(duk_uint16_t) 0x2030UL, (duk_uint16_t) 0x205EUL,
+	(duk_uint16_t) 0x2060UL, (duk_uint16_t) 0x2FFFUL,
+	(duk_uint16_t) 0x3001UL, (duk_uint16_t) 0xFEFEUL,
+	(duk_uint16_t) 0xFF00UL, (duk_uint16_t) 0xFFFFUL,
+};
+DUK_INTERNAL duk_uint16_t duk_unicode_re_ranges_not_wordchar[10] = {
+	(duk_uint16_t) 0x0000UL, (duk_uint16_t) 0x002FUL,
+	(duk_uint16_t) 0x003AUL, (duk_uint16_t) 0x0040UL,
+	(duk_uint16_t) 0x005BUL, (duk_uint16_t) 0x005EUL,
+	(duk_uint16_t) 0x0060UL, (duk_uint16_t) 0x0060UL,
+	(duk_uint16_t) 0x007BUL, (duk_uint16_t) 0xFFFFUL,
+};
+
+#endif  /* DUK_USE_REGEXP_SUPPORT */
+#line 1 "duk_util_misc.c"
+/*
+ *  Misc util stuff
+ */
+
+/* include removed: duk_internal.h */
+
+/*
+ *  Lowercase digits for radix values 2 to 36.  Also doubles as lowercase
+ *  hex nybble table.
+ */
+
+DUK_INTERNAL const duk_uint8_t duk_lc_digits[36] = {
+	DUK_ASC_0, DUK_ASC_1, DUK_ASC_2, DUK_ASC_3,
+	DUK_ASC_4, DUK_ASC_5, DUK_ASC_6, DUK_ASC_7,
+	DUK_ASC_8, DUK_ASC_9, DUK_ASC_LC_A, DUK_ASC_LC_B,
+	DUK_ASC_LC_C, DUK_ASC_LC_D, DUK_ASC_LC_E, DUK_ASC_LC_F,
+	DUK_ASC_LC_G, DUK_ASC_LC_H, DUK_ASC_LC_I, DUK_ASC_LC_J,
+	DUK_ASC_LC_K, DUK_ASC_LC_L, DUK_ASC_LC_M, DUK_ASC_LC_N,
+	DUK_ASC_LC_O, DUK_ASC_LC_P, DUK_ASC_LC_Q, DUK_ASC_LC_R,
+	DUK_ASC_LC_S, DUK_ASC_LC_T, DUK_ASC_LC_U, DUK_ASC_LC_V,
+	DUK_ASC_LC_W, DUK_ASC_LC_X, DUK_ASC_LC_Y, DUK_ASC_LC_Z
+};
+
+DUK_INTERNAL const duk_uint8_t duk_uc_nybbles[16] = {
+	DUK_ASC_0, DUK_ASC_1, DUK_ASC_2, DUK_ASC_3,
+	DUK_ASC_4, DUK_ASC_5, DUK_ASC_6, DUK_ASC_7,
+	DUK_ASC_8, DUK_ASC_9, DUK_ASC_UC_A, DUK_ASC_UC_B,
+	DUK_ASC_UC_C, DUK_ASC_UC_D, DUK_ASC_UC_E, DUK_ASC_UC_F
+};
+
+/*
+ *  Table for hex decoding ASCII hex digits
+ */
+
+DUK_INTERNAL const duk_int8_t duk_hex_dectab[256] = {
+	/* -1 if invalid */
+	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* 0x00-0x0f */
+	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* 0x10-0x1f */
+	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* 0x20-0x2f */
+	 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, -1, -1, -1, -1, -1, -1,  /* 0x30-0x3f */
+	-1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* 0x40-0x4f */
+	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* 0x50-0x5f */
+	-1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* 0x60-0x6f */
+	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* 0x70-0x7f */
+	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* 0x80-0x8f */
+	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* 0x90-0x9f */
+	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* 0xa0-0xaf */
+	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* 0xb0-0xbf */
+	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* 0xc0-0xcf */
+	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* 0xd0-0xdf */
+	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* 0xe0-0xef */
+	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1   /* 0xf0-0xff */
+};
+
+#if defined(DUK_USE_HEX_FASTPATH)
+/* Preshifted << 4.  Must use 16-bit entry to allow negative value signaling. */
+DUK_INTERNAL const duk_int16_t duk_hex_dectab_shift4[256] = {
+	  -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,  /* 0x00-0x0f */
+	  -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,  /* 0x10-0x1f */
+	  -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,  /* 0x20-0x2f */
+	0x00, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80, 0x90,   -1,   -1,   -1,   -1,   -1,   -1,  /* 0x30-0x3f */
+	  -1, 0xa0, 0xb0, 0xc0, 0xd0, 0xe0, 0xf0,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,  /* 0x40-0x4f */
+	  -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,  /* 0x50-0x5f */
+	  -1, 0xa0, 0xb0, 0xc0, 0xd0, 0xe0, 0xf0,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,  /* 0x60-0x6f */
+	  -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,  /* 0x70-0x7f */
+	  -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,  /* 0x80-0x8f */
+	  -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,  /* 0x90-0x9f */
+	  -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,  /* 0xa0-0xaf */
+	  -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,  /* 0xb0-0xbf */
+	  -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,  /* 0xc0-0xcf */
+	  -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,  /* 0xd0-0xdf */
+	  -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,  /* 0xe0-0xef */
+	  -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1   /* 0xf0-0xff */
+};
+#endif
+
+/*
+ *  Table for hex encoding bytes
+ */
+
+#if defined(DUK_USE_HEX_FASTPATH)
+/* Lookup to encode one byte directly into 2 characters:
+ *
+ *   def genhextab(bswap):
+ *       for i in xrange(256):
+ *           t = chr(i).encode('hex')
+ *           if bswap:
+ *               t = t[1] + t[0]
+ *           print('0x' + t.encode('hex') + 'U')
+ *   print('big endian'); genhextab(False)
+ *   print('little endian'); genhextab(True)
+*/
+DUK_INTERNAL const duk_uint16_t duk_hex_enctab[256] = {
+#if defined(DUK_USE_INTEGER_BE)
+	0x3030U, 0x3031U, 0x3032U, 0x3033U, 0x3034U, 0x3035U, 0x3036U, 0x3037U,
+	0x3038U, 0x3039U, 0x3061U, 0x3062U, 0x3063U, 0x3064U, 0x3065U, 0x3066U,
+	0x3130U, 0x3131U, 0x3132U, 0x3133U, 0x3134U, 0x3135U, 0x3136U, 0x3137U,
+	0x3138U, 0x3139U, 0x3161U, 0x3162U, 0x3163U, 0x3164U, 0x3165U, 0x3166U,
+	0x3230U, 0x3231U, 0x3232U, 0x3233U, 0x3234U, 0x3235U, 0x3236U, 0x3237U,
+	0x3238U, 0x3239U, 0x3261U, 0x3262U, 0x3263U, 0x3264U, 0x3265U, 0x3266U,
+	0x3330U, 0x3331U, 0x3332U, 0x3333U, 0x3334U, 0x3335U, 0x3336U, 0x3337U,
+	0x3338U, 0x3339U, 0x3361U, 0x3362U, 0x3363U, 0x3364U, 0x3365U, 0x3366U,
+	0x3430U, 0x3431U, 0x3432U, 0x3433U, 0x3434U, 0x3435U, 0x3436U, 0x3437U,
+	0x3438U, 0x3439U, 0x3461U, 0x3462U, 0x3463U, 0x3464U, 0x3465U, 0x3466U,
+	0x3530U, 0x3531U, 0x3532U, 0x3533U, 0x3534U, 0x3535U, 0x3536U, 0x3537U,
+	0x3538U, 0x3539U, 0x3561U, 0x3562U, 0x3563U, 0x3564U, 0x3565U, 0x3566U,
+	0x3630U, 0x3631U, 0x3632U, 0x3633U, 0x3634U, 0x3635U, 0x3636U, 0x3637U,
+	0x3638U, 0x3639U, 0x3661U, 0x3662U, 0x3663U, 0x3664U, 0x3665U, 0x3666U,
+	0x3730U, 0x3731U, 0x3732U, 0x3733U, 0x3734U, 0x3735U, 0x3736U, 0x3737U,
+	0x3738U, 0x3739U, 0x3761U, 0x3762U, 0x3763U, 0x3764U, 0x3765U, 0x3766U,
+	0x3830U, 0x3831U, 0x3832U, 0x3833U, 0x3834U, 0x3835U, 0x3836U, 0x3837U,
+	0x3838U, 0x3839U, 0x3861U, 0x3862U, 0x3863U, 0x3864U, 0x3865U, 0x3866U,
+	0x3930U, 0x3931U, 0x3932U, 0x3933U, 0x3934U, 0x3935U, 0x3936U, 0x3937U,
+	0x3938U, 0x3939U, 0x3961U, 0x3962U, 0x3963U, 0x3964U, 0x3965U, 0x3966U,
+	0x6130U, 0x6131U, 0x6132U, 0x6133U, 0x6134U, 0x6135U, 0x6136U, 0x6137U,
+	0x6138U, 0x6139U, 0x6161U, 0x6162U, 0x6163U, 0x6164U, 0x6165U, 0x6166U,
+	0x6230U, 0x6231U, 0x6232U, 0x6233U, 0x6234U, 0x6235U, 0x6236U, 0x6237U,
+	0x6238U, 0x6239U, 0x6261U, 0x6262U, 0x6263U, 0x6264U, 0x6265U, 0x6266U,
+	0x6330U, 0x6331U, 0x6332U, 0x6333U, 0x6334U, 0x6335U, 0x6336U, 0x6337U,
+	0x6338U, 0x6339U, 0x6361U, 0x6362U, 0x6363U, 0x6364U, 0x6365U, 0x6366U,
+	0x6430U, 0x6431U, 0x6432U, 0x6433U, 0x6434U, 0x6435U, 0x6436U, 0x6437U,
+	0x6438U, 0x6439U, 0x6461U, 0x6462U, 0x6463U, 0x6464U, 0x6465U, 0x6466U,
+	0x6530U, 0x6531U, 0x6532U, 0x6533U, 0x6534U, 0x6535U, 0x6536U, 0x6537U,
+	0x6538U, 0x6539U, 0x6561U, 0x6562U, 0x6563U, 0x6564U, 0x6565U, 0x6566U,
+	0x6630U, 0x6631U, 0x6632U, 0x6633U, 0x6634U, 0x6635U, 0x6636U, 0x6637U,
+	0x6638U, 0x6639U, 0x6661U, 0x6662U, 0x6663U, 0x6664U, 0x6665U, 0x6666U
+#else  /* DUK_USE_INTEGER_BE */
+	0x3030U, 0x3130U, 0x3230U, 0x3330U, 0x3430U, 0x3530U, 0x3630U, 0x3730U,
+	0x3830U, 0x3930U, 0x6130U, 0x6230U, 0x6330U, 0x6430U, 0x6530U, 0x6630U,
+	0x3031U, 0x3131U, 0x3231U, 0x3331U, 0x3431U, 0x3531U, 0x3631U, 0x3731U,
+	0x3831U, 0x3931U, 0x6131U, 0x6231U, 0x6331U, 0x6431U, 0x6531U, 0x6631U,
+	0x3032U, 0x3132U, 0x3232U, 0x3332U, 0x3432U, 0x3532U, 0x3632U, 0x3732U,
+	0x3832U, 0x3932U, 0x6132U, 0x6232U, 0x6332U, 0x6432U, 0x6532U, 0x6632U,
+	0x3033U, 0x3133U, 0x3233U, 0x3333U, 0x3433U, 0x3533U, 0x3633U, 0x3733U,
+	0x3833U, 0x3933U, 0x6133U, 0x6233U, 0x6333U, 0x6433U, 0x6533U, 0x6633U,
+	0x3034U, 0x3134U, 0x3234U, 0x3334U, 0x3434U, 0x3534U, 0x3634U, 0x3734U,
+	0x3834U, 0x3934U, 0x6134U, 0x6234U, 0x6334U, 0x6434U, 0x6534U, 0x6634U,
+	0x3035U, 0x3135U, 0x3235U, 0x3335U, 0x3435U, 0x3535U, 0x3635U, 0x3735U,
+	0x3835U, 0x3935U, 0x6135U, 0x6235U, 0x6335U, 0x6435U, 0x6535U, 0x6635U,
+	0x3036U, 0x3136U, 0x3236U, 0x3336U, 0x3436U, 0x3536U, 0x3636U, 0x3736U,
+	0x3836U, 0x3936U, 0x6136U, 0x6236U, 0x6336U, 0x6436U, 0x6536U, 0x6636U,
+	0x3037U, 0x3137U, 0x3237U, 0x3337U, 0x3437U, 0x3537U, 0x3637U, 0x3737U,
+	0x3837U, 0x3937U, 0x6137U, 0x6237U, 0x6337U, 0x6437U, 0x6537U, 0x6637U,
+	0x3038U, 0x3138U, 0x3238U, 0x3338U, 0x3438U, 0x3538U, 0x3638U, 0x3738U,
+	0x3838U, 0x3938U, 0x6138U, 0x6238U, 0x6338U, 0x6438U, 0x6538U, 0x6638U,
+	0x3039U, 0x3139U, 0x3239U, 0x3339U, 0x3439U, 0x3539U, 0x3639U, 0x3739U,
+	0x3839U, 0x3939U, 0x6139U, 0x6239U, 0x6339U, 0x6439U, 0x6539U, 0x6639U,
+	0x3061U, 0x3161U, 0x3261U, 0x3361U, 0x3461U, 0x3561U, 0x3661U, 0x3761U,
+	0x3861U, 0x3961U, 0x6161U, 0x6261U, 0x6361U, 0x6461U, 0x6561U, 0x6661U,
+	0x3062U, 0x3162U, 0x3262U, 0x3362U, 0x3462U, 0x3562U, 0x3662U, 0x3762U,
+	0x3862U, 0x3962U, 0x6162U, 0x6262U, 0x6362U, 0x6462U, 0x6562U, 0x6662U,
+	0x3063U, 0x3163U, 0x3263U, 0x3363U, 0x3463U, 0x3563U, 0x3663U, 0x3763U,
+	0x3863U, 0x3963U, 0x6163U, 0x6263U, 0x6363U, 0x6463U, 0x6563U, 0x6663U,
+	0x3064U, 0x3164U, 0x3264U, 0x3364U, 0x3464U, 0x3564U, 0x3664U, 0x3764U,
+	0x3864U, 0x3964U, 0x6164U, 0x6264U, 0x6364U, 0x6464U, 0x6564U, 0x6664U,
+	0x3065U, 0x3165U, 0x3265U, 0x3365U, 0x3465U, 0x3565U, 0x3665U, 0x3765U,
+	0x3865U, 0x3965U, 0x6165U, 0x6265U, 0x6365U, 0x6465U, 0x6565U, 0x6665U,
+	0x3066U, 0x3166U, 0x3266U, 0x3366U, 0x3466U, 0x3566U, 0x3666U, 0x3766U,
+	0x3866U, 0x3966U, 0x6166U, 0x6266U, 0x6366U, 0x6466U, 0x6566U, 0x6666U
+#endif  /* DUK_USE_INTEGER_BE */
+};
+#endif  /* DUK_USE_HEX_FASTPATH */
+
+/*
+ *  Table for base-64 encoding
+ */
+
+#if defined(DUK_USE_BASE64_FASTPATH)
+DUK_INTERNAL const duk_uint8_t duk_base64_enctab[64] = {
+	0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50,  /* A...P */
+	0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66,  /* Q...f */
+	0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76,  /* g...v */
+	0x77, 0x78, 0x79, 0x7a, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x2b, 0x2f   /* w.../ */
+};
+#endif  /* DUK_USE_BASE64_FASTPATH */
+
+/*
+ *  Table for base-64 decoding
+ */
+
+#if defined(DUK_USE_BASE64_FASTPATH)
+DUK_INTERNAL const duk_int8_t duk_base64_dectab[256] = {
+	/* -1 = error, -2 = allowed whitespace, -3 = padding ('='), 0...63 decoded bytes */
+	-1, -1, -1, -1, -1, -1, -1, -1, -1, -2, -2, -1, -1, -2, -1, -1,  /* 0x00...0x0f */
+	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* 0x10...0x1f */
+	-2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63,  /* 0x20...0x2f */
+	52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -3, -1, -1,  /* 0x30...0x3f */
+	-1,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14,  /* 0x40...0x4f */
+	15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1,  /* 0x50...0x5f */
+	-1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,  /* 0x60...0x6f */
+	41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1,  /* 0x70...0x7f */
+	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* 0x80...0x8f */
+	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* 0x90...0x9f */
+	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* 0xa0...0xaf */
+	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* 0xb0...0xbf */
+	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* 0xc0...0xcf */
+	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* 0xd0...0xdf */
+	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* 0xe0...0xef */
+	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1   /* 0xf0...0xff */
+};
+#endif  /* DUK_USE_BASE64_FASTPATH */
+
+/*
+ *  Arbitrary byteswap for potentially unaligned values
+ *
+ *  Used to byteswap pointers e.g. in debugger code.
+ */
+
+#if defined(DUK_USE_DEBUGGER_SUPPORT)  /* For now only needed by the debugger. */
+DUK_INTERNAL void duk_byteswap_bytes(duk_uint8_t *p, duk_small_uint_t len) {
+	duk_uint8_t tmp;
+	duk_uint8_t *q = p + len - 1;
+
+	while (p - q < 0) {
+		tmp = *p;
+		*p = *q;
+		*q = tmp;
+		p++;
+		q--;
+	}
+}
+#endif
+#line 1 "duk_util_hashprime.c"
+/*
+ *  Round a number upwards to a prime (not usually the nearest one).
+ *
+ *  Uses a table of successive 32-bit primes whose ratio is roughly
+ *  constant.  This keeps the relative upwards 'rounding error' bounded
+ *  and the data size small.  A simple 'predict-correct' compression is
+ *  used to compress primes to one byte per prime.  See genhashsizes.py
+ *  for details.
+ *
+ *  The minimum prime returned here must be coordinated with the possible
+ *  probe sequence steps in duk_hobject and duk_heap stringtable.
+ */
+
+/* include removed: duk_internal.h */
+
+/* Awkward inclusion condition: drop out of compilation if not needed by any
+ * call site: object hash part or probing stringtable.
+ */
+#if defined(DUK_USE_HOBJECT_HASH_PART) || defined(DUK_USE_STRTAB_PROBE)
+
+/* hash size ratio goal, must match genhashsizes.py */
+#define DUK__HASH_SIZE_RATIO   1177  /* floor(1.15 * (1 << 10)) */
+
+/* prediction corrections for prime list (see genhashsizes.py) */
+DUK_LOCAL const duk_int8_t duk__hash_size_corrections[] = {
+	17,  /* minimum prime */
+	4, 3, 4, 1, 4, 1, 1, 2, 2, 2, 2, 1, 6, 6, 9, 5, 1, 2, 2, 5, 1, 3, 3, 3,
+	5, 4, 4, 2, 4, 8, 3, 4, 23, 2, 4, 7, 8, 11, 2, 12, 15, 10, 1, 1, 5, 1, 5,
+	8, 9, 17, 14, 10, 7, 5, 2, 46, 21, 1, 9, 9, 4, 4, 10, 23, 36, 6, 20, 29,
+	18, 6, 19, 21, 16, 11, 5, 5, 48, 9, 1, 39, 14, 8, 4, 29, 9, 1, 15, 48, 12,
+	22, 6, 15, 27, 4, 2, 17, 28, 8, 9, 4, 5, 8, 3, 3, 8, 37, 11, 15, 8, 30,
+	43, 6, 33, 41, 5, 20, 32, 41, 38, 24, 77, 14, 19, 11, 4, 35, 18, 19, 41,
+	10, 23, 16, 9, 2,
+	-1
+};
+
+/* probe steps (see genhashsizes.py), currently assumed to be 32 entries long
+ * (DUK_UTIL_GET_HASH_PROBE_STEP macro).
+ */
+DUK_INTERNAL duk_uint8_t duk_util_probe_steps[32] = {
+	2, 3, 5, 7, 11, 13, 19, 31, 41, 47, 59, 67, 73, 79, 89, 101, 103, 107,
+	109, 127, 137, 139, 149, 157, 163, 167, 173, 181, 191, 193, 197, 199
+};
+
+DUK_INTERNAL duk_uint32_t duk_util_get_hash_prime(duk_uint32_t size) {
+	const duk_int8_t *p = duk__hash_size_corrections;
+	duk_uint32_t curr;
+
+	curr = (duk_uint32_t) *p++;
+	for (;;) {
+		duk_small_int_t t = (duk_small_int_t) *p++;
+		if (t < 0) {
+			/* may happen if size is very close to 2^32-1 */
+			break;
+		}
+
+		/* prediction: portable variant using doubles if 64-bit values not available */
+#ifdef DUK_USE_64BIT_OPS
+		curr = (duk_uint32_t) ((((duk_uint64_t) curr) * ((duk_uint64_t) DUK__HASH_SIZE_RATIO)) >> 10);
+#else
+		/* 32-bit x 11-bit = 43-bit, fits accurately into a double */
+		curr = (duk_uint32_t) DUK_FLOOR(((double) curr) * ((double) DUK__HASH_SIZE_RATIO) / 1024.0);
+#endif
+
+		/* correction */
+		curr += t;
+
+		DUK_DDD(DUK_DDDPRINT("size=%ld, curr=%ld", (long) size, (long) curr));
+
+		if (curr >= size) {
+			return curr;
+		}
+	}
+	return 0;
+}
+
+#endif  /* DUK_USE_HOBJECT_HASH_PART || DUK_USE_STRTAB_PROBE */
+#line 1 "duk_hobject_class.c"
+/*
+ *  Hobject Ecmascript [[Class]].
+ */
+
+/* include removed: duk_internal.h */
+
+#if (DUK_STRIDX_UC_ARGUMENTS > 255)
+#error constant too large
+#endif
+#if (DUK_STRIDX_ARRAY > 255)
+#error constant too large
+#endif
+#if (DUK_STRIDX_UC_BOOLEAN > 255)
+#error constant too large
+#endif
+#if (DUK_STRIDX_DATE > 255)
+#error constant too large
+#endif
+#if (DUK_STRIDX_UC_ERROR > 255)
+#error constant too large
+#endif
+#if (DUK_STRIDX_UC_FUNCTION > 255)
+#error constant too large
+#endif
+#if (DUK_STRIDX_JSON > 255)
+#error constant too large
+#endif
+#if (DUK_STRIDX_MATH > 255)
+#error constant too large
+#endif
+#if (DUK_STRIDX_UC_NUMBER > 255)
+#error constant too large
+#endif
+#if (DUK_STRIDX_UC_OBJECT > 255)
+#error constant too large
+#endif
+#if (DUK_STRIDX_REG_EXP > 255)
+#error constant too large
+#endif
+#if (DUK_STRIDX_UC_STRING > 255)
+#error constant too large
+#endif
+#if (DUK_STRIDX_GLOBAL > 255)
+#error constant too large
+#endif
+#if (DUK_STRIDX_OBJ_ENV > 255)
+#error constant too large
+#endif
+#if (DUK_STRIDX_DEC_ENV > 255)
+#error constant too large
+#endif
+#if (DUK_STRIDX_UC_BUFFER > 255)
+#error constant too large
+#endif
+#if (DUK_STRIDX_UC_POINTER > 255)
+#error constant too large
+#endif
+#if (DUK_STRIDX_UC_THREAD > 255)
+#error constant too large
+#endif
+#if (DUK_STRIDX_ARRAY_BUFFER > 255)
+#error constant too large
+#endif
+#if (DUK_STRIDX_DATA_VIEW > 255)
+#error constant too large
+#endif
+#if (DUK_STRIDX_INT8_ARRAY > 255)
+#error constant too large
+#endif
+#if (DUK_STRIDX_UINT8_ARRAY > 255)
+#error constant too large
+#endif
+#if (DUK_STRIDX_UINT8_CLAMPED_ARRAY > 255)
+#error constant too large
+#endif
+#if (DUK_STRIDX_INT16_ARRAY > 255)
+#error constant too large
+#endif
+#if (DUK_STRIDX_UINT16_ARRAY > 255)
+#error constant too large
+#endif
+#if (DUK_STRIDX_INT32_ARRAY > 255)
+#error constant too large
+#endif
+#if (DUK_STRIDX_UINT32_ARRAY > 255)
+#error constant too large
+#endif
+#if (DUK_STRIDX_FLOAT32_ARRAY > 255)
+#error constant too large
+#endif
+#if (DUK_STRIDX_FLOAT64_ARRAY > 255)
+#error constant too large
+#endif
+#if (DUK_STRIDX_EMPTY_STRING > 255)
+#error constant too large
+#endif
+
+/* Note: assumes that these string indexes are 8-bit, genstrings.py must ensure that */
+DUK_INTERNAL duk_uint8_t duk_class_number_to_stridx[32] = {
+	DUK_STRIDX_EMPTY_STRING,  /* UNUSED, intentionally empty */
+	DUK_STRIDX_UC_ARGUMENTS,
+	DUK_STRIDX_ARRAY,
+	DUK_STRIDX_UC_BOOLEAN,
+	DUK_STRIDX_DATE,
+	DUK_STRIDX_UC_ERROR,
+	DUK_STRIDX_UC_FUNCTION,
+	DUK_STRIDX_JSON,
+	DUK_STRIDX_MATH,
+	DUK_STRIDX_UC_NUMBER,
+	DUK_STRIDX_UC_OBJECT,
+	DUK_STRIDX_REG_EXP,
+	DUK_STRIDX_UC_STRING,
+	DUK_STRIDX_GLOBAL,
+	DUK_STRIDX_OBJ_ENV,
+	DUK_STRIDX_DEC_ENV,
+	DUK_STRIDX_UC_BUFFER,
+	DUK_STRIDX_UC_POINTER,
+	DUK_STRIDX_UC_THREAD,
+	DUK_STRIDX_ARRAY_BUFFER,
+	DUK_STRIDX_DATA_VIEW,
+	DUK_STRIDX_INT8_ARRAY,
+	DUK_STRIDX_UINT8_ARRAY,
+	DUK_STRIDX_UINT8_CLAMPED_ARRAY,
+	DUK_STRIDX_INT16_ARRAY,
+	DUK_STRIDX_UINT16_ARRAY,
+	DUK_STRIDX_INT32_ARRAY,
+	DUK_STRIDX_UINT32_ARRAY,
+	DUK_STRIDX_FLOAT32_ARRAY,
+	DUK_STRIDX_FLOAT64_ARRAY,
+	DUK_STRIDX_EMPTY_STRING,  /* UNUSED, intentionally empty */
+	DUK_STRIDX_EMPTY_STRING,  /* UNUSED, intentionally empty */
+};
+#line 1 "duk_alloc_default.c"
+/*
+ *  Default allocation functions.
+ *
+ *  Assumes behavior such as malloc allowing zero size, yielding
+ *  a NULL or a unique pointer which is a no-op for free.
+ */
+
+/* include removed: duk_internal.h */
+
+DUK_INTERNAL void *duk_default_alloc_function(void *udata, duk_size_t size) {
+	void *res;
+	DUK_UNREF(udata);
+	res = DUK_ANSI_MALLOC(size);
+	DUK_DDD(DUK_DDDPRINT("default alloc function: %lu -> %p",
+	                     (unsigned long) size, (void *) res));
+	return res;
+}
+
+DUK_INTERNAL void *duk_default_realloc_function(void *udata, void *ptr, duk_size_t newsize) {
+	void *res;
+	DUK_UNREF(udata);
+	res = DUK_ANSI_REALLOC(ptr, newsize);
+	DUK_DDD(DUK_DDDPRINT("default realloc function: %p %lu -> %p",
+	                     (void *) ptr, (unsigned long) newsize, (void *) res));
+	return res;
+}
+
+DUK_INTERNAL void duk_default_free_function(void *udata, void *ptr) {
+	DUK_DDD(DUK_DDDPRINT("default free function: %p", (void *) ptr));
+	DUK_UNREF(udata);
+	DUK_ANSI_FREE(ptr);
+}
+#line 1 "duk_api_buffer.c"
+/*
+ *  Buffer
+ */
+
+/* include removed: duk_internal.h */
+
+DUK_EXTERNAL void *duk_resize_buffer(duk_context *ctx, duk_idx_t index, duk_size_t new_size) {
+	duk_hthread *thr = (duk_hthread *) ctx;
+	duk_hbuffer_dynamic *h;
+
+	DUK_ASSERT_CTX_VALID(ctx);
+
+	h = (duk_hbuffer_dynamic *) duk_require_hbuffer(ctx, index);
+	DUK_ASSERT(h != NULL);
+
+	if (!(DUK_HBUFFER_HAS_DYNAMIC(h) && !DUK_HBUFFER_HAS_EXTERNAL(h))) {
+		DUK_ERROR(thr, DUK_ERR_TYPE_ERROR, DUK_STR_WRONG_BUFFER_TYPE);
+	}
+
+	/* maximum size check is handled by callee */
+	duk_hbuffer_resize(thr, h, new_size);
+
+	return DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(thr->heap, h);
+}
+
+DUK_EXTERNAL void *duk_steal_buffer(duk_context *ctx, duk_idx_t index, duk_size_t *out_size) {
+	duk_hthread *thr = (duk_hthread *) ctx;
+	duk_hbuffer_dynamic *h;
+	void *ptr;
+	duk_size_t sz;
+
+	DUK_ASSERT(ctx != NULL);
+
+	h = (duk_hbuffer_dynamic *) duk_require_hbuffer(ctx, index);
+	DUK_ASSERT(h != NULL);
+
+	if (!(DUK_HBUFFER_HAS_DYNAMIC(h) && !DUK_HBUFFER_HAS_EXTERNAL(h))) {
+		DUK_ERROR(thr, DUK_ERR_TYPE_ERROR, DUK_STR_WRONG_BUFFER_TYPE);
+	}
+
+	/* Forget the previous allocation, setting size to 0 and alloc to
+	 * NULL.  Caller is responsible for freeing the previous allocation.
+	 * Getting the allocation and clearing it is done in the same API
+	 * call to avoid any chance of a realloc.
+	 */
+	ptr = DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(thr->heap, h);
+	sz = DUK_HBUFFER_DYNAMIC_GET_SIZE(h);
+	if (out_size) {
+		*out_size = sz;
+	}
+	DUK_HBUFFER_DYNAMIC_SET_DATA_PTR_NULL(thr->heap, h);
+	DUK_HBUFFER_DYNAMIC_SET_SIZE(h, 0);
+
+	return ptr;
+}
+
+DUK_EXTERNAL void duk_config_buffer(duk_context *ctx, duk_idx_t index, void *ptr, duk_size_t len) {
+	duk_hthread *thr = (duk_hthread *) ctx;
+	duk_hbuffer_external *h;
+
+	DUK_ASSERT(ctx != NULL);
+
+	h = (duk_hbuffer_external *) duk_require_hbuffer(ctx, index);
+	DUK_ASSERT(h != NULL);
+
+	if (!DUK_HBUFFER_HAS_EXTERNAL(h)) {
+		DUK_ERROR(thr, DUK_ERR_TYPE_ERROR, DUK_STR_WRONG_BUFFER_TYPE);
+	}
+	DUK_ASSERT(DUK_HBUFFER_HAS_DYNAMIC(h));
+
+	DUK_HBUFFER_EXTERNAL_SET_DATA_PTR(thr->heap, h, ptr);
+	DUK_HBUFFER_EXTERNAL_SET_SIZE(h, len);
+}
+#line 1 "duk_api_bytecode.c"
+/*
+ *  Bytecode dump/load
+ *
+ *  The bytecode load primitive is more important performance-wise than the
+ *  dump primitive.
+ *
+ *  Unlike most Duktape API calls, bytecode dump/load is not guaranteed to be
+ *  memory safe for invalid arguments - caller beware!  There's little point
+ *  in trying to achieve memory safety unless bytecode instructions are also
+ *  validated which is not easy to do with indirect register references etc.
+ */
+
+/* include removed: duk_internal.h */
+
+#if defined(DUK_USE_BYTECODE_DUMP_SUPPORT)
+
+#define DUK__SER_MARKER  0xff
+#define DUK__SER_VERSION 0x00
+#define DUK__SER_STRING  0x00
+#define DUK__SER_NUMBER  0x01
+#define DUK__BYTECODE_INITIAL_ALLOC 256
+
+/*
+ *  Dump/load helpers, xxx_raw() helpers do no buffer checks
+ */
+
+DUK_LOCAL duk_uint8_t *duk__load_string_raw(duk_context *ctx, duk_uint8_t *p) {
+	duk_uint32_t len;
+
+	len = DUK_RAW_READ_U32_BE(p);
+	duk_push_lstring(ctx, (const char *) p, len);
+	p += len;
+	return p;
+}
+
+DUK_LOCAL duk_uint8_t *duk__load_buffer_raw(duk_context *ctx, duk_uint8_t *p) {
+	duk_uint32_t len;
+	duk_uint8_t *buf;
+
+	len = DUK_RAW_READ_U32_BE(p);
+	buf = (duk_uint8_t *) duk_push_fixed_buffer(ctx, (duk_size_t) len);
+	DUK_ASSERT(buf != NULL);
+	DUK_MEMCPY((void *) buf, (const void *) p, (size_t) len);
+	p += len;
+	return p;
+}
+
+DUK_LOCAL duk_uint8_t *duk__dump_hstring_raw(duk_uint8_t *p, duk_hstring *h) {
+	duk_size_t len;
+	duk_uint32_t tmp32;
+
+	DUK_ASSERT(h != NULL);
+
+	len = DUK_HSTRING_GET_BYTELEN(h);
+	DUK_ASSERT(len <= 0xffffffffUL);  /* string limits */
+	tmp32 = (duk_uint32_t) len;
+	DUK_RAW_WRITE_U32_BE(p, tmp32);
+	DUK_MEMCPY((void *) p,
+	           (const void *) DUK_HSTRING_GET_DATA(h),
+	           len);
+	p += len;
+	return p;
+}
+
+DUK_LOCAL duk_uint8_t *duk__dump_hbuffer_raw(duk_hthread *thr, duk_uint8_t *p, duk_hbuffer *h) {
+	duk_size_t len;
+	duk_uint32_t tmp32;
+
+	DUK_ASSERT(thr != NULL);
+	DUK_ASSERT(h != NULL);
+	DUK_UNREF(thr);
+
+	len = DUK_HBUFFER_GET_SIZE(h);
+	DUK_ASSERT(len <= 0xffffffffUL);  /* buffer limits */
+	tmp32 = (duk_uint32_t) len;
+	DUK_RAW_WRITE_U32_BE(p, tmp32);
+	DUK_MEMCPY((void *) p,
+	           (const void *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h),
+	           len);
+	p += len;
+	return p;
+}
+
+DUK_LOCAL duk_uint8_t *duk__dump_string_prop(duk_hthread *thr, duk_uint8_t *p, duk_bufwriter_ctx *bw_ctx, duk_hobject *func, duk_small_uint_t stridx) {
+	duk_hstring *h_str;
+	duk_tval *tv;
+
+	tv = duk_hobject_find_existing_entry_tval_ptr(thr->heap, (duk_hobject *) func, DUK_HTHREAD_GET_STRING(thr, stridx));
+	if (tv != NULL && DUK_TVAL_IS_STRING(tv)) {
+		h_str = DUK_TVAL_GET_STRING(tv);
+		DUK_ASSERT(h_str != NULL);
+	} else {
+		h_str = DUK_HTHREAD_STRING_EMPTY_STRING(thr);
+		DUK_ASSERT(h_str != NULL);
+	}
+	DUK_ASSERT(DUK_HSTRING_MAX_BYTELEN <= 0x7fffffffUL);  /* ensures no overflow */
+	p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 4 + DUK_HSTRING_GET_BYTELEN(h_str), p);
+	p = duk__dump_hstring_raw(p, h_str);
+	return p;
+}
+
+DUK_LOCAL duk_uint8_t *duk__dump_buffer_prop(duk_hthread *thr, duk_uint8_t *p, duk_bufwriter_ctx *bw_ctx, duk_hobject *func, duk_small_uint_t stridx) {
+	duk_tval *tv;
+
+	tv = duk_hobject_find_existing_entry_tval_ptr(thr->heap, (duk_hobject *) func, DUK_HTHREAD_GET_STRING(thr, stridx));
+	if (tv != NULL && DUK_TVAL_IS_BUFFER(tv)) {
+		duk_hbuffer *h_buf;
+		h_buf = DUK_TVAL_GET_BUFFER(tv);
+		DUK_ASSERT(h_buf != NULL);
+		DUK_ASSERT(DUK_HBUFFER_MAX_BYTELEN <= 0x7fffffffUL);  /* ensures no overflow */
+		p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 4 + DUK_HBUFFER_GET_SIZE(h_buf), p);
+		p = duk__dump_hbuffer_raw(thr, p, h_buf);
+	} else {
+		p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 4, p);
+		DUK_RAW_WRITE_U32_BE(p, 0);
+	}
+	return p;
+}
+
+DUK_LOCAL duk_uint8_t *duk__dump_uint32_prop(duk_hthread *thr, duk_uint8_t *p, duk_bufwriter_ctx *bw_ctx, duk_hobject *func, duk_small_uint_t stridx, duk_uint32_t def_value) {
+	duk_tval *tv;
+	duk_uint32_t val;
+
+	tv = duk_hobject_find_existing_entry_tval_ptr(thr->heap, (duk_hobject *) func, DUK_HTHREAD_GET_STRING(thr, stridx));
+	if (tv != NULL && DUK_TVAL_IS_NUMBER(tv)) {
+		val = (duk_uint32_t) DUK_TVAL_GET_NUMBER(tv);
+	} else {
+		val = def_value;
+	}
+	p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 4, p);
+	DUK_RAW_WRITE_U32_BE(p, val);
+	return p;
+}
+
+DUK_LOCAL duk_uint8_t *duk__dump_varmap(duk_hthread *thr, duk_uint8_t *p, duk_bufwriter_ctx *bw_ctx, duk_hobject *func) {
+	duk_tval *tv;
+
+	tv = duk_hobject_find_existing_entry_tval_ptr(thr->heap, (duk_hobject *) func, DUK_HTHREAD_STRING_INT_VARMAP(thr));
+	if (tv != NULL && DUK_TVAL_IS_OBJECT(tv)) {
+		duk_hobject *h;
+		duk_uint_fast32_t i;
+
+		h = DUK_TVAL_GET_OBJECT(tv);
+		DUK_ASSERT(h != NULL);
+
+		/* We know _Varmap only has own properties so walk property
+		 * table directly.  We also know _Varmap is dense and all
+		 * values are numbers; assert for these.  GC and finalizers
+		 * shouldn't affect _Varmap so side effects should be fine.
+		 */
+		for (i = 0; i < (duk_uint_fast32_t) DUK_HOBJECT_GET_ENEXT(h); i++) {
+			duk_hstring *key;
+			duk_tval *tv_val;
+			duk_uint32_t val;
+
+			key = DUK_HOBJECT_E_GET_KEY(thr->heap, h, i);
+			DUK_ASSERT(key != NULL);  /* _Varmap is dense */
+			DUK_ASSERT(!DUK_HOBJECT_E_SLOT_IS_ACCESSOR(thr->heap, h, i));
+			tv_val = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, h, i);
+			DUK_ASSERT(tv_val != NULL);
+			DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv_val));  /* known to be number; in fact an integer */
+#if defined(DUK_USE_FASTINT)
+			DUK_ASSERT(DUK_TVAL_IS_FASTINT(tv_val));
+			DUK_ASSERT(DUK_TVAL_GET_FASTINT(tv_val) == (duk_int64_t) DUK_TVAL_GET_FASTINT_U32(tv_val));  /* known to be 32-bit */
+			val = DUK_TVAL_GET_FASTINT_U32(tv_val);
+#else
+			val = (duk_uint32_t) DUK_TVAL_GET_NUMBER(tv_val);
+#endif
+
+			DUK_ASSERT(DUK_HSTRING_MAX_BYTELEN <= 0x7fffffffUL);  /* ensures no overflow */
+			p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 4 + DUK_HSTRING_GET_BYTELEN(key) + 4, p);
+			p = duk__dump_hstring_raw(p, key);
+			DUK_RAW_WRITE_U32_BE(p, val);
+		}
+	}
+	p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 4, p);
+	DUK_RAW_WRITE_U32_BE(p, 0);  /* end of _Varmap */
+	return p;
+}
+
+DUK_LOCAL duk_uint8_t *duk__dump_formals(duk_hthread *thr, duk_uint8_t *p, duk_bufwriter_ctx *bw_ctx, duk_hobject *func) {
+	duk_tval *tv;
+
+	tv = duk_hobject_find_existing_entry_tval_ptr(thr->heap, (duk_hobject *) func, DUK_HTHREAD_STRING_INT_FORMALS(thr));
+	if (tv != NULL && DUK_TVAL_IS_OBJECT(tv)) {
+		duk_hobject *h;
+		duk_uint_fast32_t i;
+
+		h = DUK_TVAL_GET_OBJECT(tv);
+		DUK_ASSERT(h != NULL);
+
+		/* We know _Formals is dense and all entries will be in the
+		 * array part.  GC and finalizers shouldn't affect _Formals
+		 * so side effects should be fine.
+		 */
+		for (i = 0; i < (duk_uint_fast32_t) DUK_HOBJECT_GET_ASIZE(h); i++) {
+			duk_tval *tv_val;
+			duk_hstring *varname;
+
+			tv_val = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, h, i);
+			DUK_ASSERT(tv_val != NULL);
+			if (DUK_TVAL_IS_STRING(tv_val)) {
+				/* Array is dense and contains only strings, but ASIZE may
+				 * be larger than used part and there are UNUSED entries.
+				 */
+				varname = DUK_TVAL_GET_STRING(tv_val);
+				DUK_ASSERT(varname != NULL);
+
+				DUK_ASSERT(DUK_HSTRING_MAX_BYTELEN <= 0x7fffffffUL);  /* ensures no overflow */
+				p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 4 + DUK_HSTRING_GET_BYTELEN(varname), p);
+				p = duk__dump_hstring_raw(p, varname);
+			}
+		}
+	}
+	p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 4, p);
+	DUK_RAW_WRITE_U32_BE(p, 0);  /* end of _Formals */
+	return p;
+}
+
+static duk_uint8_t *duk__dump_func(duk_context *ctx, duk_hcompiledfunction *func, duk_bufwriter_ctx *bw_ctx, duk_uint8_t *p) {
+	duk_hthread *thr;
+	duk_tval *tv, *tv_end;
+	duk_instr_t *ins, *ins_end;
+	duk_hobject **fn, **fn_end;
+	duk_hstring *h_str;
+	duk_uint32_t count_instr;
+	duk_uint32_t tmp32;
+	duk_uint16_t tmp16;
+	duk_double_t d;
+
+	thr = (duk_hthread *) ctx;
+	DUK_UNREF(ctx);
+	DUK_UNREF(thr);
+
+	DUK_DD(DUK_DDPRINT("dumping function %p to %p: "
+	                   "consts=[%p,%p[ (%ld bytes, %ld items), "
+	                   "funcs=[%p,%p[ (%ld bytes, %ld items), "
+	                   "code=[%p,%p[ (%ld bytes, %ld items)",
+	                   (void *) func,
+	                   (void *) p,
+	                   (void *) DUK_HCOMPILEDFUNCTION_GET_CONSTS_BASE(thr->heap, func),
+	                   (void *) DUK_HCOMPILEDFUNCTION_GET_CONSTS_END(thr->heap, func),
+	                   (long) DUK_HCOMPILEDFUNCTION_GET_CONSTS_SIZE(thr->heap, func),
+	                   (long) DUK_HCOMPILEDFUNCTION_GET_CONSTS_COUNT(thr->heap, func),
+	                   (void *) DUK_HCOMPILEDFUNCTION_GET_FUNCS_BASE(thr->heap, func),
+	                   (void *) DUK_HCOMPILEDFUNCTION_GET_FUNCS_END(thr->heap, func),
+	                   (long) DUK_HCOMPILEDFUNCTION_GET_FUNCS_SIZE(thr->heap, func),
+	                   (long) DUK_HCOMPILEDFUNCTION_GET_FUNCS_COUNT(thr->heap, func),
+	                   (void *) DUK_HCOMPILEDFUNCTION_GET_CODE_BASE(thr->heap, func),
+	                   (void *) DUK_HCOMPILEDFUNCTION_GET_CODE_END(thr->heap, func),
+	                   (long) DUK_HCOMPILEDFUNCTION_GET_CODE_SIZE(thr->heap, func),
+	                   (long) DUK_HCOMPILEDFUNCTION_GET_CODE_COUNT(thr->heap, func)));
+
+	DUK_ASSERT(DUK_USE_ESBC_MAX_BYTES <= 0x7fffffffUL);  /* ensures no overflow */
+	count_instr = (duk_uint32_t) DUK_HCOMPILEDFUNCTION_GET_CODE_COUNT(thr->heap, func);
+	p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 3 * 4 + 2 * 2 + 3 * 4 + count_instr * 4, p);
+
+	/* Fixed header info. */
+	tmp32 = count_instr;
+	DUK_RAW_WRITE_U32_BE(p, tmp32);
+	tmp32 = (duk_uint32_t) DUK_HCOMPILEDFUNCTION_GET_CONSTS_COUNT(thr->heap, func);
+	DUK_RAW_WRITE_U32_BE(p, tmp32);
+	tmp32 = (duk_uint32_t) DUK_HCOMPILEDFUNCTION_GET_FUNCS_COUNT(thr->heap, func);
+	DUK_RAW_WRITE_U32_BE(p, tmp32);
+	tmp16 = func->nregs;
+	DUK_RAW_WRITE_U16_BE(p, tmp16);
+	tmp16 = func->nargs;
+	DUK_RAW_WRITE_U16_BE(p, tmp16);
+#if defined(DUK_USE_DEBUGGER_SUPPORT)
+	tmp32 = func->start_line;
+	DUK_RAW_WRITE_U32_BE(p, tmp32);
+	tmp32 = func->end_line;
+	DUK_RAW_WRITE_U32_BE(p, tmp32);
+#else
+	DUK_RAW_WRITE_U32_BE(p, 0);
+	DUK_RAW_WRITE_U32_BE(p, 0);
+#endif
+	tmp32 = ((duk_heaphdr *) func)->h_flags & DUK_HEAPHDR_FLAGS_FLAG_MASK;
+	DUK_RAW_WRITE_U32_BE(p, tmp32);
+
+	/* Bytecode instructions: endian conversion needed unless
+	 * platform is big endian.
+	 */
+	ins = DUK_HCOMPILEDFUNCTION_GET_CODE_BASE(thr->heap, func);
+	ins_end = DUK_HCOMPILEDFUNCTION_GET_CODE_END(thr->heap, func);
+	DUK_ASSERT((duk_size_t) (ins_end - ins) == (duk_size_t) count_instr);
+#if defined(DUK_USE_INTEGER_BE)
+	DUK_MEMCPY((void *) p, (const void *) ins, (size_t) (ins_end - ins));
+	p += (size_t) (ins_end - ins);
+#else
+	while (ins != ins_end) {
+		tmp32 = (duk_uint32_t) (*ins);
+		DUK_RAW_WRITE_U32_BE(p, tmp32);
+		ins++;
+	}
+#endif
+
+	/* Constants: variable size encoding. */
+	tv = DUK_HCOMPILEDFUNCTION_GET_CONSTS_BASE(thr->heap, func);
+	tv_end = DUK_HCOMPILEDFUNCTION_GET_CONSTS_END(thr->heap, func);
+	while (tv != tv_end) {
+		/* constants are strings or numbers now */
+		DUK_ASSERT(DUK_TVAL_IS_STRING(tv) ||
+		           DUK_TVAL_IS_NUMBER(tv));
+
+		if (DUK_TVAL_IS_STRING(tv)) {
+			h_str = DUK_TVAL_GET_STRING(tv);
+			DUK_ASSERT(h_str != NULL);
+			DUK_ASSERT(DUK_HSTRING_MAX_BYTELEN <= 0x7fffffffUL);  /* ensures no overflow */
+			p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 1 + 4 + DUK_HSTRING_GET_BYTELEN(h_str), p),
+			*p++ = DUK__SER_STRING;
+			p = duk__dump_hstring_raw(p, h_str);
+		} else {
+			DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));
+			p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 1 + 8, p);
+			*p++ = DUK__SER_NUMBER;
+			d = DUK_TVAL_GET_NUMBER(tv);
+			DUK_RAW_WRITE_DOUBLE_BE(p, d);
+		}
+		tv++;
+	}
+
+	/* Inner functions recursively. */
+	fn = (duk_hobject **) DUK_HCOMPILEDFUNCTION_GET_FUNCS_BASE(thr->heap, func);
+	fn_end = (duk_hobject **) DUK_HCOMPILEDFUNCTION_GET_FUNCS_END(thr->heap, func);
+	while (fn != fn_end) {
+		/* XXX: This causes recursion up to inner function depth
+		 * which is normally not an issue, e.g. mark-and-sweep uses
+		 * a recursion limiter to avoid C stack issues.  Avoiding
+		 * this would mean some sort of a work list or just refusing
+		 * to serialize deep functions.
+		 */
+		DUK_ASSERT(DUK_HOBJECT_IS_COMPILEDFUNCTION(*fn));
+		p = duk__dump_func(ctx, (duk_hcompiledfunction *) *fn, bw_ctx, p);
+		fn++;
+	}
+
+	/* Object extra properties.
+	 *
+	 * There are some difference between function templates and functions.
+	 * For example, function templates don't have .length and nargs is
+	 * normally used to instantiate the functions.
+	 */
+
+	p = duk__dump_uint32_prop(thr, p, bw_ctx, (duk_hobject *) func, DUK_STRIDX_LENGTH, (duk_uint32_t) func->nargs);
+	p = duk__dump_string_prop(thr, p, bw_ctx, (duk_hobject *) func, DUK_STRIDX_NAME);
+	p = duk__dump_string_prop(thr, p, bw_ctx, (duk_hobject *) func, DUK_STRIDX_FILE_NAME);
+	p = duk__dump_buffer_prop(thr, p, bw_ctx, (duk_hobject *) func, DUK_STRIDX_INT_PC2LINE);
+	p = duk__dump_varmap(thr, p, bw_ctx, (duk_hobject *) func);
+	p = duk__dump_formals(thr, p, bw_ctx, (duk_hobject *) func);
+
+	DUK_DD(DUK_DDPRINT("serialized function %p -> final pointer %p", (void *) func, (void *) p));
+
+	return p;
+}
+
+/* Load a function from bytecode.  The function object returned here must
+ * match what is created by duk_js_push_closure() with respect to its flags,
+ * properties, etc.
+ *
+ * NOTE: there are intentionally no input buffer length / bound checks.
+ * Adding them would be easy but wouldn't ensure memory safety as untrusted
+ * or broken bytecode is unsafe during execution unless the opcodes themselves
+ * are validated (which is quite complex, especially for indirect opcodes).
+ */
+
+#define DUK__ASSERT_LEFT(n) do { \
+		DUK_ASSERT((duk_size_t) (p_end - p) >= (duk_size_t) (n)); \
+	} while (0)
+
+static duk_uint8_t *duk__load_func(duk_context *ctx, duk_uint8_t *p, duk_uint8_t *p_end) {
+	duk_hthread *thr;
+	duk_hcompiledfunction *h_fun;
+	duk_hbuffer *h_data;
+	duk_size_t data_size;
+	duk_uint32_t count_instr, count_const, count_funcs;
+	duk_uint32_t n;
+	duk_uint32_t tmp32;
+	duk_small_uint_t const_type;
+	duk_uint8_t *fun_data;
+	duk_uint8_t *q;
+	duk_idx_t idx_base;
+	duk_tval *tv1;
+	duk_uarridx_t arr_idx;
+
+	/* XXX: There's some overlap with duk_js_closure() here, but
+	 * seems difficult to share code.  Ensure that the final function
+	 * looks the same as created by duk_js_closure().
+	 */
+
+	DUK_ASSERT(ctx != NULL);
+	thr = (duk_hthread *) ctx;
+
+	DUK_DD(DUK_DDPRINT("loading function, p=%p, p_end=%p", (void *) p, (void *) p_end));
+
+	DUK__ASSERT_LEFT(3 * 4);
+	count_instr = DUK_RAW_READ_U32_BE(p);
+	count_const = DUK_RAW_READ_U32_BE(p);
+	count_funcs = DUK_RAW_READ_U32_BE(p);
+
+	data_size = sizeof(duk_tval) * count_const +
+	            sizeof(duk_hobject *) * count_funcs +
+	            sizeof(duk_instr_t) * count_instr;
+
+	DUK_DD(DUK_DDPRINT("instr=%ld, const=%ld, funcs=%ld, data_size=%ld",
+	                   (long) count_instr, (long) count_const,
+	                   (long) count_const, (long) data_size));
+
+	/* Value stack is used to ensure reachability of constants and
+	 * inner functions being loaded.  Require enough space to handle
+	 * large functions correctly.
+	 */
+	duk_require_stack(ctx, 2 + count_const + count_funcs);
+	idx_base = duk_get_top(ctx);
+
+	/* Push function object, init flags etc.  This must match
+	 * duk_js_push_closure() quite carefully.
+	 */
+	duk_push_compiledfunction(ctx);
+	h_fun = duk_get_hcompiledfunction(ctx, -1);
+	DUK_ASSERT(h_fun != NULL);
+	DUK_ASSERT(DUK_HOBJECT_IS_COMPILEDFUNCTION((duk_hobject *) h_fun));
+	DUK_ASSERT(DUK_HCOMPILEDFUNCTION_GET_DATA(thr->heap, h_fun) == NULL);
+	DUK_ASSERT(DUK_HCOMPILEDFUNCTION_GET_FUNCS(thr->heap, h_fun) == NULL);
+	DUK_ASSERT(DUK_HCOMPILEDFUNCTION_GET_BYTECODE(thr->heap, h_fun) == NULL);
+
+	h_fun->nregs = DUK_RAW_READ_U16_BE(p);
+	h_fun->nargs = DUK_RAW_READ_U16_BE(p);
+#if defined(DUK_USE_DEBUGGER_SUPPORT)
+	h_fun->start_line = DUK_RAW_READ_U32_BE(p);
+	h_fun->end_line = DUK_RAW_READ_U32_BE(p);
+#else
+	p += 8;  /* skip line info */
+#endif
+
+	/* duk_hcompiledfunction flags; quite version specific */
+	tmp32 = DUK_RAW_READ_U32_BE(p);
+	DUK_HEAPHDR_SET_FLAGS((duk_heaphdr *) h_fun, tmp32);
+
+	/* standard prototype */
+	DUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr, &h_fun->obj, thr->builtins[DUK_BIDX_FUNCTION_PROTOTYPE]);
+
+	/* assert just a few critical flags */
+	DUK_ASSERT(DUK_HEAPHDR_GET_TYPE((duk_heaphdr *) h_fun) == DUK_HTYPE_OBJECT);
+	DUK_ASSERT(!DUK_HOBJECT_HAS_BOUND(&h_fun->obj));
+	DUK_ASSERT(DUK_HOBJECT_HAS_COMPILEDFUNCTION(&h_fun->obj));
+	DUK_ASSERT(!DUK_HOBJECT_HAS_NATIVEFUNCTION(&h_fun->obj));
+	DUK_ASSERT(!DUK_HOBJECT_HAS_THREAD(&h_fun->obj));
+	DUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_ARRAY(&h_fun->obj));
+	DUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_STRINGOBJ(&h_fun->obj));
+	DUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(&h_fun->obj));
+
+	/* Create function 'data' buffer but don't attach it yet. */
+	fun_data = (duk_uint8_t *) duk_push_fixed_buffer(ctx, data_size);
+	DUK_ASSERT(fun_data != NULL);
+
+	/* Load bytecode instructions. */
+	DUK_ASSERT(sizeof(duk_instr_t) == 4);
+	DUK__ASSERT_LEFT(count_instr * sizeof(duk_instr_t));
+#if defined(DUK_USE_INTEGER_BE)
+	q = fun_data + sizeof(duk_tval) * count_const + sizeof(duk_hobject *) * count_funcs;
+	DUK_MEMCPY((void *) q,
+	           (const void *) p,
+	           sizeof(duk_instr_t) * count_instr);
+	p += sizeof(duk_instr_t) * count_instr;
+#else
+	q = fun_data + sizeof(duk_tval) * count_const + sizeof(duk_hobject *) * count_funcs;
+	for (n = count_instr; n > 0; n--) {
+		*((duk_instr_t *) (void *) q) = DUK_RAW_READ_U32_BE(p);
+		q += sizeof(duk_instr_t);
+	}
+#endif
+
+	/* Load constants onto value stack but don't yet copy to buffer. */
+	for (n = count_const; n > 0; n--) {
+		DUK__ASSERT_LEFT(1);
+		const_type = DUK_RAW_READ_U8(p);
+		switch (const_type) {
+		case DUK__SER_STRING: {
+			p = duk__load_string_raw(ctx, p);
+			break;
+		}
+		case DUK__SER_NUMBER: {
+			/* Important to do a fastint check so that constants are
+			 * properly read back as fastints.
+			 */
+			duk_tval tv_tmp;
+			duk_double_t val;
+			DUK__ASSERT_LEFT(8);
+			val = DUK_RAW_READ_DOUBLE_BE(p);
+			DUK_TVAL_SET_NUMBER_CHKFAST(&tv_tmp, val);
+			duk_push_tval(ctx, &tv_tmp);
+			break;
+		}
+		default: {
+			goto format_error;
+		}
+		}
+	}
+
+	/* Load inner functions to value stack, but don't yet copy to buffer. */
+	for (n = count_funcs; n > 0; n--) {
+		p = duk__load_func(ctx, p, p_end);
+		if (p == NULL) {
+			goto format_error;
+		}
+	}
+
+	/* With constants and inner functions on value stack, we can now
+	 * atomically finish the function 'data' buffer, bump refcounts,
+	 * etc.
+	 *
+	 * Here we take advantage of the value stack being just a duk_tval
+	 * array: we can just memcpy() the constants as long as we incref
+	 * them afterwards.
+	 */
+
+	h_data = (duk_hbuffer *) duk_get_hbuffer(ctx, idx_base + 1);
+	DUK_ASSERT(h_data != NULL);
+	DUK_ASSERT(!DUK_HBUFFER_HAS_DYNAMIC(h_data));
+	DUK_HCOMPILEDFUNCTION_SET_DATA(thr->heap, h_fun, h_data);
+	DUK_HBUFFER_INCREF(thr, h_data);
+
+	tv1 = duk_get_tval(ctx, idx_base + 2);  /* may be NULL if no constants or inner funcs */
+	DUK_ASSERT((count_const == 0 && count_funcs == 0) || tv1 != NULL);
+
+	q = fun_data;
+	if (count_const > 0) {
+		/* Explicit zero size check to avoid NULL 'tv1'. */
+		DUK_MEMCPY((void *) q, (const void *) tv1, sizeof(duk_tval) * count_const);
+		for (n = count_const; n > 0; n--) {
+			DUK_TVAL_INCREF_FAST(thr, (duk_tval *) (void *) q);  /* no side effects */
+			q += sizeof(duk_tval);
+		}
+		tv1 += count_const;
+	}
+
+	DUK_HCOMPILEDFUNCTION_SET_FUNCS(thr->heap, h_fun, (duk_hobject **) (void *) q);
+	for (n = count_funcs; n > 0; n--) {
+		duk_hobject *h_obj;
+
+		DUK_ASSERT(DUK_TVAL_IS_OBJECT(tv1));
+		h_obj = DUK_TVAL_GET_OBJECT(tv1);
+		DUK_ASSERT(h_obj != NULL);
+		tv1++;
+		DUK_HOBJECT_INCREF(thr, h_obj);
+
+		*((duk_hobject **) (void *) q) = h_obj;
+		q += sizeof(duk_hobject *);
+	}
+
+	DUK_HCOMPILEDFUNCTION_SET_BYTECODE(thr->heap, h_fun, (duk_instr_t *) (void *) q);
+
+	/* The function object is now reachable and refcounts are fine,
+	 * so we can pop off all the temporaries.
+	 */
+	DUK_DDD(DUK_DDDPRINT("function is reachable, reset top; func: %!iT", duk_get_tval(ctx, idx_base)));
+	duk_set_top(ctx, idx_base + 1);
+
+	/* Setup function properties. */
+	tmp32 = DUK_RAW_READ_U32_BE(p);
+	duk_push_u32(ctx, tmp32);
+	duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_LENGTH, DUK_PROPDESC_FLAGS_NONE);
+
+	p = duk__load_string_raw(ctx, p);
+	if (DUK_HOBJECT_HAS_NAMEBINDING((duk_hobject *) h_fun)) {
+		/* Original function instance/template had NAMEBINDING.
+		 * Must create a lexical environment on loading to allow
+		 * recursive functions like 'function foo() { foo(); }'.
+		 */
+		duk_hobject *proto;
+
+		proto = thr->builtins[DUK_BIDX_GLOBAL_ENV];
+		(void) duk_push_object_helper_proto(ctx,
+		                                    DUK_HOBJECT_FLAG_EXTENSIBLE |
+		                                    DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_DECENV),
+		                                    proto);
+		duk_dup(ctx, -2);                                 /* -> [ func funcname env funcname ] */
+		duk_dup(ctx, idx_base);                           /* -> [ func funcname env funcname func ] */
+		duk_xdef_prop(ctx, -3, DUK_PROPDESC_FLAGS_NONE);  /* -> [ func funcname env ] */
+		duk_xdef_prop_stridx(ctx, idx_base, DUK_STRIDX_INT_LEXENV, DUK_PROPDESC_FLAGS_WC);
+		/* since closure has NEWENV, never define DUK_STRIDX_INT_VARENV, as it
+		 * will be ignored anyway
+		 */
+	}
+	duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_NAME, DUK_PROPDESC_FLAGS_NONE);
+
+	p = duk__load_string_raw(ctx, p);
+	duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_FILE_NAME, DUK_PROPDESC_FLAGS_WC);
+
+	duk_push_object(ctx);
+	duk_dup(ctx, -2);
+	duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_CONSTRUCTOR, DUK_PROPDESC_FLAGS_WC);  /* func.prototype.constructor = func */
+	duk_compact(ctx, -1);
+	duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_PROTOTYPE, DUK_PROPDESC_FLAGS_W);
+
+	p = duk__load_buffer_raw(ctx, p);
+	duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_INT_PC2LINE, DUK_PROPDESC_FLAGS_WC);
+
+	duk_push_object(ctx);  /* _Varmap */
+	for (;;) {
+		/* XXX: awkward */
+		p = duk__load_string_raw(ctx, p);
+		if (duk_get_length(ctx, -1) == 0) {
+			duk_pop(ctx);
+			break;
+		}
+		tmp32 = DUK_RAW_READ_U32_BE(p);
+		duk_push_u32(ctx, tmp32);
+		duk_put_prop(ctx, -3);
+	}
+	duk_compact(ctx, -1);
+	duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_INT_VARMAP, DUK_PROPDESC_FLAGS_NONE);
+
+	duk_push_array(ctx);  /* _Formals */
+	for (arr_idx = 0; ; arr_idx++) {
+		/* XXX: awkward */
+		p = duk__load_string_raw(ctx, p);
+		if (duk_get_length(ctx, -1) == 0) {
+			duk_pop(ctx);
+			break;
+		}
+		duk_put_prop_index(ctx, -2, arr_idx);
+	}
+	duk_compact(ctx, -1);
+	duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_INT_FORMALS, DUK_PROPDESC_FLAGS_NONE);
+
+	/* Return with final function pushed on stack top. */
+	DUK_DD(DUK_DDPRINT("final loaded function: %!iT", duk_get_tval(ctx, -1)));
+	DUK_ASSERT_TOP(ctx, idx_base + 1);
+	return p;
+
+ format_error:
+	return NULL;
+}
+
+DUK_EXTERNAL void duk_dump_function(duk_context *ctx) {
+	duk_hthread *thr;
+	duk_hcompiledfunction *func;
+	duk_bufwriter_ctx bw_ctx_alloc;
+	duk_bufwriter_ctx *bw_ctx = &bw_ctx_alloc;
+	duk_uint8_t *p;
+
+	DUK_ASSERT(ctx != NULL);
+	thr = (duk_hthread *) ctx;
+
+	/* Bound functions don't have all properties so we'd either need to
+	 * lookup the non-bound target function or reject bound functions.
+	 * For now, bound functions are rejected.
+	 */
+	func = duk_require_hcompiledfunction(ctx, -1);
+	DUK_ASSERT(func != NULL);
+	DUK_ASSERT(!DUK_HOBJECT_HAS_BOUND(&func->obj));
+
+	/* Estimating the result size beforehand would be costly, so
+	 * start with a reasonable size and extend as needed.
+	 */
+	DUK_BW_INIT_PUSHBUF(thr, bw_ctx, DUK__BYTECODE_INITIAL_ALLOC);
+	p = DUK_BW_GET_PTR(thr, bw_ctx);
+	*p++ = DUK__SER_MARKER;
+	*p++ = DUK__SER_VERSION;
+	p = duk__dump_func(ctx, func, bw_ctx, p);
+	DUK_BW_SET_PTR(thr, bw_ctx, p);
+	DUK_BW_COMPACT(thr, bw_ctx);
+
+	DUK_DD(DUK_DDPRINT("serialized result: %!T", duk_get_tval(ctx, -1)));
+
+	duk_remove(ctx, -2);  /* [ ... func buf ] -> [ ... buf ] */
+}
+
+DUK_EXTERNAL void duk_load_function(duk_context *ctx) {
+	duk_hthread *thr;
+	duk_uint8_t *p_buf, *p, *p_end;
+	duk_size_t sz;
+
+	DUK_ASSERT(ctx != NULL);
+	thr = (duk_hthread *) ctx;
+	DUK_UNREF(ctx);
+
+	p_buf = (duk_uint8_t *) duk_require_buffer(ctx, -1, &sz);
+	DUK_ASSERT(p_buf != NULL);
+
+	/* The caller is responsible for being sure that bytecode being loaded
+	 * is valid and trusted.  Invalid bytecode can cause memory unsafe
+	 * behavior directly during loading or later during bytecode execution
+	 * (instruction validation would be quite complex to implement).
+	 *
+	 * This signature check is the only sanity check for detecting
+	 * accidental invalid inputs.  The initial 0xFF byte ensures no
+	 * ordinary string will be accepted by accident.
+	 */
+	p = p_buf;
+	p_end = p_buf + sz;
+	if (sz < 2 || p[0] != DUK__SER_MARKER || p[1] != DUK__SER_VERSION) {
+		goto format_error;
+	}
+	p += 2;
+
+	p = duk__load_func(ctx, p, p_end);
+	if (p == NULL) {
+		goto format_error;
+	}
+
+	duk_remove(ctx, -2);  /* [ ... buf func ] -> [ ... func ] */
+	return;
+
+ format_error:
+	DUK_ERROR(thr, DUK_ERR_TYPE_ERROR, DUK_STR_DECODE_FAILED);
+}
+
+#undef DUK__SER_MARKER
+#undef DUK__SER_VERSION
+#undef DUK__SER_STRING
+#undef DUK__SER_NUMBER
+#undef DUK__BYTECODE_INITIAL_ALLOC
+
+#else  /* DUK_USE_BYTECODE_DUMP_SUPPORT */
+
+DUK_EXTERNAL void duk_dump_function(duk_context *ctx) {
+	DUK_ERROR((duk_hthread *) ctx, DUK_ERR_ERROR, DUK_STR_UNSUPPORTED);
+}
+
+DUK_EXTERNAL void duk_load_function(duk_context *ctx) {
+	DUK_ERROR((duk_hthread *) ctx, DUK_ERR_ERROR, DUK_STR_UNSUPPORTED);
+}
+
+#endif  /* DUK_USE_BYTECODE_DUMP_SUPPORT */
+#line 1 "duk_api_call.c"
+/*
+ *  Calls.
+ *
+ *  Protected variants should avoid ever throwing an error.
+ */
+
+/* include removed: duk_internal.h */
+
+/* Prepare value stack for a method call through an object property.
+ * May currently throw an error e.g. when getting the property.
+ */
+DUK_LOCAL void duk__call_prop_prep_stack(duk_context *ctx, duk_idx_t normalized_obj_index, duk_idx_t nargs) {
+	DUK_ASSERT_CTX_VALID(ctx);
+
+	DUK_DDD(DUK_DDDPRINT("duk__call_prop_prep_stack, normalized_obj_index=%ld, nargs=%ld, stacktop=%ld",
+	                     (long) normalized_obj_index, (long) nargs, (long) duk_get_top(ctx)));
+
+	/* [... key arg1 ... argN] */
+
+	/* duplicate key */
+	duk_dup(ctx, -nargs - 1);  /* Note: -nargs alone would fail for nargs == 0, this is OK */
+	duk_get_prop(ctx, normalized_obj_index);
+
+	DUK_DDD(DUK_DDDPRINT("func: %!T", (duk_tval *) duk_get_tval(ctx, -1)));
+
+	/* [... key arg1 ... argN func] */
+
+	duk_replace(ctx, -nargs - 2);
+
+	/* [... func arg1 ... argN] */
+
+	duk_dup(ctx, normalized_obj_index);
+	duk_insert(ctx, -nargs - 1);
+
+	/* [... func this arg1 ... argN] */
+}
+
+DUK_EXTERNAL void duk_call(duk_context *ctx, duk_idx_t nargs) {
+	duk_hthread *thr = (duk_hthread *) ctx;
+	duk_small_uint_t call_flags;
+	duk_idx_t idx_func;
+
+	DUK_ASSERT_CTX_VALID(ctx);
+	DUK_ASSERT(thr != NULL);
+
+	idx_func = duk_get_top(ctx) - nargs - 1;
+	if (idx_func < 0 || nargs < 0) {
+		/* note that we can't reliably pop anything here */
+		DUK_ERROR(thr, DUK_ERR_API_ERROR, DUK_STR_INVALID_CALL_ARGS);
+	}
+
+	/* XXX: awkward; we assume there is space for this, overwrite
+	 * directly instead?
+	 */
+	duk_push_undefined(ctx);
+	duk_insert(ctx, idx_func + 1);
+
+	call_flags = 0;  /* not protected, respect reclimit, not constructor */
+
+	duk_handle_call_unprotected(thr,           /* thread */
+	                            nargs,         /* num_stack_args */
+	                            call_flags);   /* call_flags */
+}
+
+DUK_EXTERNAL void duk_call_method(duk_context *ctx, duk_idx_t nargs) {
+	duk_hthread *thr = (duk_hthread *) ctx;
+	duk_small_uint_t call_flags;
+	duk_idx_t idx_func;
+
+	DUK_ASSERT_CTX_VALID(ctx);
+	DUK_ASSERT(thr != NULL);
+
+	idx_func = duk_get_top(ctx) - nargs - 2;  /* must work for nargs <= 0 */
+	if (idx_func < 0 || nargs < 0) {
+		/* note that we can't reliably pop anything here */
+		DUK_ERROR(thr, DUK_ERR_API_ERROR, DUK_STR_INVALID_CALL_ARGS);
+	}
+
+	call_flags = 0;  /* not protected, respect reclimit, not constructor */
+
+	duk_handle_call_unprotected(thr,           /* thread */
+	                            nargs,         /* num_stack_args */
+	                            call_flags);   /* call_flags */
+}
+
+DUK_EXTERNAL void duk_call_prop(duk_context *ctx, duk_idx_t obj_index, duk_idx_t nargs) {
+	/*
+	 *  XXX: if duk_handle_call() took values through indices, this could be
+	 *  made much more sensible.  However, duk_handle_call() needs to fudge
+	 *  the 'this' and 'func' values to handle bound function chains, which
+	 *  is now done "in-place", so this is not a trivial change.
+	 */
+
+	DUK_ASSERT_CTX_VALID(ctx);
+
+	obj_index = duk_require_normalize_index(ctx, obj_index);  /* make absolute */
+
+	duk__call_prop_prep_stack(ctx, obj_index, nargs);
+
+	duk_call_method(ctx, nargs);
+}
+
+DUK_EXTERNAL duk_int_t duk_pcall(duk_context *ctx, duk_idx_t nargs) {
+	duk_hthread *thr = (duk_hthread *) ctx;
+	duk_small_uint_t call_flags;
+	duk_idx_t idx_func;
+	duk_int_t rc;
+
+	DUK_ASSERT_CTX_VALID(ctx);
+	DUK_ASSERT(thr != NULL);
+
+	idx_func = duk_get_top(ctx) - nargs - 1;  /* must work for nargs <= 0 */
+	if (idx_func < 0 || nargs < 0) {
+		/* We can't reliably pop anything here because the stack input
+		 * shape is incorrect.  So we throw an error; if the caller has
+		 * no catch point for this, a fatal error will occur.  Another
+		 * alternative would be to just return an error.  But then the
+		 * stack would be in an unknown state which might cause some
+		 * very hard to diagnose problems later on.  Also note that even
+		 * if we did not throw an error here, the underlying call handler
+		 * might STILL throw an out-of-memory error or some other internal
+		 * fatal error.
+		 */
+		DUK_ERROR(thr, DUK_ERR_API_ERROR, DUK_STR_INVALID_CALL_ARGS);
+		return DUK_EXEC_ERROR;  /* unreachable */
+	}
+
+	/* awkward; we assume there is space for this */
+	duk_push_undefined(ctx);
+	duk_insert(ctx, idx_func + 1);
+
+	call_flags = 0;  /* respect reclimit, not constructor */
+
+	rc = duk_handle_call_protected(thr,           /* thread */
+	                               nargs,         /* num_stack_args */
+	                               call_flags);   /* call_flags */
+
+	return rc;
+}
+
+DUK_EXTERNAL duk_int_t duk_pcall_method(duk_context *ctx, duk_idx_t nargs) {
+	duk_hthread *thr = (duk_hthread *) ctx;
+	duk_small_uint_t call_flags;
+	duk_idx_t idx_func;
+	duk_int_t rc;
+
+	DUK_ASSERT_CTX_VALID(ctx);
+	DUK_ASSERT(thr != NULL);
+
+	idx_func = duk_get_top(ctx) - nargs - 2;  /* must work for nargs <= 0 */
+	if (idx_func < 0 || nargs < 0) {
+		/* See comments in duk_pcall(). */
+		DUK_ERROR(thr, DUK_ERR_API_ERROR, DUK_STR_INVALID_CALL_ARGS);
+		return DUK_EXEC_ERROR;  /* unreachable */
+	}
+
+	call_flags = 0;  /* respect reclimit, not constructor */
+
+	rc = duk_handle_call_protected(thr,           /* thread */
+	                               nargs,         /* num_stack_args */
+	                               call_flags);   /* call_flags */
+
+	return rc;
+}
+
+DUK_LOCAL duk_ret_t duk__pcall_prop_raw(duk_context *ctx) {
+	duk_idx_t obj_index;
+	duk_idx_t nargs;
+
+	/* Get the original arguments.  Note that obj_index may be a relative
+	 * index so the stack must have the same top when we use it.
+	 */
+
+	DUK_ASSERT_CTX_VALID(ctx);
+
+	obj_index = (duk_idx_t) duk_get_int(ctx, -2);
+	nargs = (duk_idx_t) duk_get_int(ctx, -1);
+	duk_pop_2(ctx);
+
+	obj_index = duk_require_normalize_index(ctx, obj_index);  /* make absolute */
+	duk__call_prop_prep_stack(ctx, obj_index, nargs);
+	duk_call_method(ctx, nargs);
+	return 1;
+}
+
+DUK_EXTERNAL duk_int_t duk_pcall_prop(duk_context *ctx, duk_idx_t obj_index, duk_idx_t nargs) {
+	/*
+	 *  Must be careful to catch errors related to value stack manipulation
+	 *  and property lookup, not just the call itself.
+	 */
+
+	DUK_ASSERT_CTX_VALID(ctx);
+
+	duk_push_idx(ctx, obj_index);
+	duk_push_idx(ctx, nargs);
+
+	/* Inputs: explicit arguments (nargs), +1 for key, +2 for obj_index/nargs passing.
+	 * If the value stack does not contain enough args, an error is thrown; this matches
+	 * behavior of the other protected call API functions.
+	 */
+	return duk_safe_call(ctx, duk__pcall_prop_raw, nargs + 1 + 2 /*nargs*/, 1 /*nrets*/);
+}
+
+DUK_EXTERNAL duk_int_t duk_safe_call(duk_context *ctx, duk_safe_call_function func, duk_idx_t nargs, duk_idx_t nrets) {
+	duk_hthread *thr = (duk_hthread *) ctx;
+	duk_int_t rc;
+
+	DUK_ASSERT_CTX_VALID(ctx);
+	DUK_ASSERT(thr != NULL);
+
+	if (duk_get_top(ctx) < nargs || nrets < 0) {
+		/* See comments in duk_pcall(). */
+		DUK_ERROR(thr, DUK_ERR_API_ERROR, DUK_STR_INVALID_CALL_ARGS);
+		return DUK_EXEC_ERROR;  /* unreachable */
+	}
+
+	rc = duk_handle_safe_call(thr,           /* thread */
+	                          func,          /* func */
+	                          nargs,         /* num_stack_args */
+	                          nrets);        /* num_stack_res */
+
+	return rc;
+}
+
+DUK_EXTERNAL void duk_new(duk_context *ctx, duk_idx_t nargs) {
+	/*
+	 *  There are two [[Construct]] operations in the specification:
+	 *
+	 *    - E5 Section 13.2.2: for Function objects
+	 *    - E5 Section 15.3.4.5.2: for "bound" Function objects
+	 *
+	 *  The chain of bound functions is resolved in Section 15.3.4.5.2,
+	 *  with arguments "piling up" until the [[Construct]] internal
+	 *  method is called on the final, actual Function object.  Note
+	 *  that the "prototype" property is looked up *only* from the
+	 *  final object, *before* calling the constructor.
+	 *
+	 *  Currently we follow the bound function chain here to get the
+	 *  "prototype" property value from the final, non-bound function.
+	 *  However, we let duk_handle_call() handle the argument "piling"
+	 *  when the constructor is called.  The bound function chain is
+	 *  thus now processed twice.
+	 *
+	 *  When constructing new Array instances, an unnecessary object is
+	 *  created and discarded now: the standard [[Construct]] creates an
+	 *  object, and calls the Array constructor.  The Array constructor
+	 *  returns an Array instance, which is used as the result value for
+	 *  the "new" operation; the object created before the Array constructor
+	 *  call is discarded.
+	 *
+	 *  This would be easy to fix, e.g. by knowing that the Array constructor
+	 *  will always create a replacement object and skip creating the fallback
+	 *  object in that case.
+	 *
+	 *  Note: functions called via "new" need to know they are called as a
+	 *  constructor.  For instance, built-in constructors behave differently
+	 *  depending on how they are called.
+	 */
+
+	/* XXX: merge this with duk_js_call.c, as this function implements
+	 * core semantics (or perhaps merge the two files altogether).
+	 */
+
+	duk_hthread *thr = (duk_hthread *) ctx;
+	duk_hobject *proto;
+	duk_hobject *cons;
+	duk_hobject *fallback;
+	duk_idx_t idx_cons;
+	duk_small_uint_t call_flags;
+
+	DUK_ASSERT_CTX_VALID(ctx);
+
+	/* [... constructor arg1 ... argN] */
+
+	idx_cons = duk_require_normalize_index(ctx, -nargs - 1);
+
+	DUK_DDD(DUK_DDDPRINT("top=%ld, nargs=%ld, idx_cons=%ld",
+	                     (long) duk_get_top(ctx), (long) nargs, (long) idx_cons));
+
+	/* XXX: code duplication */
+
+	/*
+	 *  Figure out the final, non-bound constructor, to get "prototype"
+	 *  property.
+	 */
+
+	duk_dup(ctx, idx_cons);
+	for (;;) {
+		cons = duk_get_hobject(ctx, -1);
+		if (cons == NULL || !DUK_HOBJECT_HAS_CONSTRUCTABLE(cons)) {
+			/* Checking constructability from anything else than the
+			 * initial constructor is not strictly necessary, but a
+			 * nice sanity check.
+			 */
+			goto not_constructable;
+		}
+		if (!DUK_HOBJECT_HAS_BOUND(cons)) {
+			break;
+		}
+		duk_get_prop_stridx(ctx, -1, DUK_STRIDX_INT_TARGET);  /* -> [... cons target] */
+		duk_remove(ctx, -2);                                  /* -> [... target] */
+	}
+	DUK_ASSERT(cons != NULL && !DUK_HOBJECT_HAS_BOUND(cons));
+
+	/* [... constructor arg1 ... argN final_cons] */
+
+	/*
+	 *  Create "fallback" object to be used as the object instance,
+	 *  unless the constructor returns a replacement value.
+	 *  Its internal prototype needs to be set based on "prototype"
+	 *  property of the constructor.
+	 */
+
+	duk_push_object(ctx);  /* class Object, extensible */
+
+	/* [... constructor arg1 ... argN final_cons fallback] */
+
+	duk_get_prop_stridx(ctx, -2, DUK_STRIDX_PROTOTYPE);
+	proto = duk_get_hobject(ctx, -1);
+	if (!proto) {
+		DUK_DDD(DUK_DDDPRINT("constructor has no 'prototype' property, or value not an object "
+		                     "-> leave standard Object prototype as fallback prototype"));
+	} else {
+		DUK_DDD(DUK_DDDPRINT("constructor has 'prototype' property with object value "
+		                     "-> set fallback prototype to that value: %!iO", (duk_heaphdr *) proto));
+		fallback = duk_get_hobject(ctx, -2);
+		DUK_ASSERT(fallback != NULL);
+		DUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr, fallback, proto);
+	}
+	duk_pop(ctx);
+
+	/* [... constructor arg1 ... argN final_cons fallback] */
+
+	/*
+	 *  Manipulate callstack for the call.
+	 */
+
+	duk_dup_top(ctx);
+	duk_insert(ctx, idx_cons + 1);  /* use fallback as 'this' value */
+	duk_insert(ctx, idx_cons);      /* also stash it before constructor,
+	                                 * in case we need it (as the fallback value)
+	                                 */
+	duk_pop(ctx);                   /* pop final_cons */
+
+
+	/* [... fallback constructor fallback(this) arg1 ... argN];
+	 * Note: idx_cons points to first 'fallback', not 'constructor'.
+	 */
+
+	DUK_DDD(DUK_DDDPRINT("before call, idx_cons+1 (constructor) -> %!T, idx_cons+2 (fallback/this) -> %!T, "
+	                     "nargs=%ld, top=%ld",
+	                     (duk_tval *) duk_get_tval(ctx, idx_cons + 1),
+	                     (duk_tval *) duk_get_tval(ctx, idx_cons + 2),
+	                     (long) nargs,
+	                     (long) duk_get_top(ctx)));
+
+	/*
+	 *  Call the constructor function (called in "constructor mode").
+	 */
+
+	call_flags = DUK_CALL_FLAG_CONSTRUCTOR_CALL;  /* not protected, respect reclimit, is a constructor call */
+
+	duk_handle_call_unprotected(thr,           /* thread */
+	                            nargs,         /* num_stack_args */
+	                            call_flags);   /* call_flags */
+
+	/* [... fallback retval] */
+
+	DUK_DDD(DUK_DDDPRINT("constructor call finished, fallback=%!iT, retval=%!iT",
+	                     (duk_tval *) duk_get_tval(ctx, -2),
+	                     (duk_tval *) duk_get_tval(ctx, -1)));
+
+	/*
+	 *  Determine whether to use the constructor return value as the created
+	 *  object instance or not.
+	 */
+
+	if (duk_is_object(ctx, -1)) {
+		duk_remove(ctx, -2);
+	} else {
+		duk_pop(ctx);
+	}
+
+	/*
+	 *  Augment created errors upon creation (not when they are thrown or
+	 *  rethrown).  __FILE__ and __LINE__ are not desirable here; the call
+	 *  stack reflects the caller which is correct.
+	 */
+
+#ifdef DUK_USE_AUGMENT_ERROR_CREATE
+	duk_hthread_sync_currpc(thr);
+	duk_err_augment_error_create(thr, thr, NULL, 0, 1 /*noblame_fileline*/);
+#endif
+
+	/* [... retval] */
+
+	return;
+
+ not_constructable:
+	DUK_ERROR(thr, DUK_ERR_TYPE_ERROR, DUK_STR_NOT_CONSTRUCTABLE);
+}
+
+DUK_LOCAL duk_ret_t duk__pnew_helper(duk_context *ctx) {
+	duk_uint_t nargs;
+
+	nargs = duk_to_uint(ctx, -1);
+	duk_pop(ctx);
+
+	duk_new(ctx, nargs);
+	return 1;
+}
+
+DUK_EXTERNAL duk_int_t duk_pnew(duk_context *ctx, duk_idx_t nargs) {
+	duk_int_t rc;
+
+	DUK_ASSERT_CTX_VALID(ctx);
+
+	/* For now, just use duk_safe_call() to wrap duk_new().  We can't
+	 * simply use a protected duk_handle_call() because there's post
+	 * processing which might throw.  It should be possible to ensure
+	 * the post processing never throws (except in internal errors and
+	 * out of memory etc which are always allowed) and then remove this
+	 * wrapper.
+	 */
+
+	duk_push_uint(ctx, nargs);
+	rc = duk_safe_call(ctx, duk__pnew_helper, nargs + 2 /*nargs*/, 1 /*nrets*/);
+	return rc;
+}
+
+DUK_EXTERNAL duk_bool_t duk_is_constructor_call(duk_context *ctx) {
+	duk_hthread *thr = (duk_hthread *) ctx;
+	duk_activation *act;
+
+	DUK_ASSERT_CTX_VALID(ctx);
+	DUK_ASSERT(thr != NULL);
+	DUK_ASSERT_DISABLE(thr->callstack_top >= 0);
+
+	act = duk_hthread_get_current_activation(thr);
+	DUK_ASSERT(act != NULL);  /* because callstack_top > 0 */
+	return ((act->flags & DUK_ACT_FLAG_CONSTRUCT) != 0 ? 1 : 0);
+}
+
+DUK_EXTERNAL duk_bool_t duk_is_strict_call(duk_context *ctx) {
+	duk_hthread *thr = (duk_hthread *) ctx;
+	duk_activation *act;
+
+	/* For user code this could just return 1 (strict) always
+	 * because all Duktape/C functions are considered strict,
+	 * and strict is also the default when nothing is running.
+	 * However, Duktape may call this function internally when
+	 * the current activation is an Ecmascript function, so
+	 * this cannot be replaced by a 'return 1' without fixing
+	 * the internal call sites.
+	 */
+
+	DUK_ASSERT_CTX_VALID(ctx);
+	DUK_ASSERT(thr != NULL);
+	DUK_ASSERT_DISABLE(thr->callstack_top >= 0);
+
+	act = duk_hthread_get_current_activation(thr);
+	if (act == NULL) {
+		/* Strict by default. */
+		return 1;
+	}
+	return ((act->flags & DUK_ACT_FLAG_STRICT) != 0 ? 1 : 0);
+}
+
+/*
+ *  Duktape/C function magic
+ */
+
+DUK_EXTERNAL duk_int_t duk_get_current_magic(duk_context *ctx) {
+	duk_hthread *thr = (duk_hthread *) ctx;
+	duk_activation *act;
+	duk_hobject *func;
+
+	DUK_ASSERT_CTX_VALID(ctx);
+	DUK_ASSERT(thr != NULL);
+	DUK_ASSERT_DISABLE(thr->callstack_top >= 0);
+
+	act = duk_hthread_get_current_activation(thr);
+	if (act) {
+		func = DUK_ACT_GET_FUNC(act);
+		if (!func) {
+			duk_tval *tv = &act->tv_func;
+			duk_small_uint_t lf_flags;
+			lf_flags = DUK_TVAL_GET_LIGHTFUNC_FLAGS(tv);
+			return (duk_int_t) DUK_LFUNC_FLAGS_GET_MAGIC(lf_flags);
+		}
+		DUK_ASSERT(func != NULL);
+
+		if (DUK_HOBJECT_IS_NATIVEFUNCTION(func)) {
+			duk_hnativefunction *nf = (duk_hnativefunction *) func;
+			return (duk_int_t) nf->magic;
+		}
+	}
+	return 0;
+}
+
+DUK_EXTERNAL duk_int_t duk_get_magic(duk_context *ctx, duk_idx_t index) {
+	duk_hthread *thr = (duk_hthread *) ctx;
+	duk_tval *tv;
+	duk_hobject *h;
+
+	DUK_ASSERT_CTX_VALID(ctx);
+
+	tv = duk_require_tval(ctx, index);
+	if (DUK_TVAL_IS_OBJECT(tv)) {
+		h = DUK_TVAL_GET_OBJECT(tv);
+		DUK_ASSERT(h != NULL);
+		if (!DUK_HOBJECT_HAS_NATIVEFUNCTION(h)) {
+			goto type_error;
+		}
+		return (duk_int_t) ((duk_hnativefunction *) h)->magic;
+	} else if (DUK_TVAL_IS_LIGHTFUNC(tv)) {
+		duk_small_uint_t lf_flags = DUK_TVAL_GET_LIGHTFUNC_FLAGS(tv);
+		return (duk_int_t) DUK_LFUNC_FLAGS_GET_MAGIC(lf_flags);
+	}
+
+	/* fall through */
+ type_error:
+	DUK_ERROR(thr, DUK_ERR_TYPE_ERROR, DUK_STR_UNEXPECTED_TYPE);
+	return 0;
+}
+
+DUK_EXTERNAL void duk_set_magic(duk_context *ctx, duk_idx_t index, duk_int_t magic) {
+	duk_hnativefunction *nf;
+
+	DUK_ASSERT_CTX_VALID(ctx);
+
+	nf = duk_require_hnativefunction(ctx, index);
+	DUK_ASSERT(nf != NULL);
+	nf->magic = (duk_int16_t) magic;
+}
+#line 1 "duk_api_codec.c"
+/*
+ *  Encoding and decoding basic formats: hex, base64.
+ *
+ *  These are in-place operations which may allow an optimized implementation.
+ *
+ *  Base-64: https://tools.ietf.org/html/rfc4648#section-4
+ */
+
+/* include removed: duk_internal.h */
+
+/* Shared handling for encode/decode argument.  Fast path handling for
+ * buffer and string values because they're the most common.  In particular,
+ * avoid creating a temporary string or buffer when possible.
+ */
+DUK_LOCAL const duk_uint8_t *duk__prep_codec_arg(duk_context *ctx, duk_idx_t index, duk_size_t *out_len) {
+	DUK_ASSERT(duk_is_valid_index(ctx, index));  /* checked by caller */
+	if (duk_is_buffer(ctx, index)) {
+		return (const duk_uint8_t *) duk_get_buffer(ctx, index, out_len);
+	} else {
+		return (const duk_uint8_t *) duk_to_lstring(ctx, index, out_len);
+	}
+}
+
+#if defined(DUK_USE_BASE64_FASTPATH)
+DUK_LOCAL void duk__base64_encode_helper(const duk_uint8_t *src, duk_size_t srclen, duk_uint8_t *dst) {
+	duk_uint_t t;
+	duk_size_t n_full, n_full3, n_final;
+	const duk_uint8_t *src_end_fast;
+
+	n_full = srclen / 3;  /* full 3-byte -> 4-char conversions */
+	n_full3 = n_full * 3;
+	n_final = srclen - n_full3;
+	DUK_ASSERT_DISABLE(n_final >= 0);
+	DUK_ASSERT(n_final <= 2);
+
+	src_end_fast = src + n_full3;
+	while (DUK_UNLIKELY(src != src_end_fast)) {
+		t = (duk_uint_t) (*src++);
+		t = (t << 8) + (duk_uint_t) (*src++);
+		t = (t << 8) + (duk_uint_t) (*src++);
+
+		*dst++ = duk_base64_enctab[t >> 18];
+		*dst++ = duk_base64_enctab[(t >> 12) & 0x3f];
+		*dst++ = duk_base64_enctab[(t >> 6) & 0x3f];
+		*dst++ = duk_base64_enctab[t & 0x3f];
+
+#if 0  /* Tested: not faster on x64 */
+		/* aaaaaabb bbbbcccc ccdddddd */
+		dst[0] = duk_base64_enctab[(src[0] >> 2) & 0x3f];
+		dst[1] = duk_base64_enctab[((src[0] << 4) & 0x30) | ((src[1] >> 4) & 0x0f)];
+		dst[2] = duk_base64_enctab[((src[1] << 2) & 0x3f) | ((src[2] >> 6) & 0x03)];
+		dst[3] = duk_base64_enctab[src[2] & 0x3f];
+		src += 3; dst += 4;
+#endif
+	}
+
+	switch (n_final) {
+	/* case 0: nop */
+	case 1: {
+		/* XX== */
+		t = (duk_uint_t) (*src++);
+		*dst++ = duk_base64_enctab[t >> 2];           /* XXXXXX-- */
+		*dst++ = duk_base64_enctab[(t << 4) & 0x3f];  /* ------XX */
+		*dst++ = DUK_ASC_EQUALS;
+		*dst++ = DUK_ASC_EQUALS;
+		break;
+	}
+	case 2: {
+		/* XXX= */
+		t = (duk_uint_t) (*src++);
+		t = (t << 8) + (duk_uint_t) (*src++);
+		*dst++ = duk_base64_enctab[t >> 10];          /* XXXXXX-- -------- */
+		*dst++ = duk_base64_enctab[(t >> 4) & 0x3f];  /* ------XX XXXX---- */
+		*dst++ = duk_base64_enctab[(t << 2) & 0x3f];  /* -------- ----XXXX */
+		*dst++ = DUK_ASC_EQUALS;
+		break;
+	}
+	}
+}
+#else  /* DUK_USE_BASE64_FASTPATH */
+DUK_LOCAL void duk__base64_encode_helper(const duk_uint8_t *src, duk_size_t srclen, duk_uint8_t *dst) {
+	duk_small_uint_t i, snip;
+	duk_uint_t t;
+	duk_uint_fast8_t x, y;
+	const duk_uint8_t *src_end;
+
+	src_end = src + srclen;
+
+	while (src < src_end) {
+		/* read 3 bytes into 't', padded by zero */
+		snip = 4;
+		t = 0;
+		for (i = 0; i < 3; i++) {
+			t = t << 8;
+			if (src >= src_end) {
+				snip--;
+			} else {
+				t += (duk_uint_t) (*src++);
+			}
+		}
+
+		/*
+		 *  Missing bytes    snip     base64 example
+		 *    0               4         XXXX
+		 *    1               3         XXX=
+		 *    2               2         XX==
+		 */
+
+		DUK_ASSERT(snip >= 2 && snip <= 4);
+
+		for (i = 0; i < 4; i++) {
+			x = (duk_uint_fast8_t) ((t >> 18) & 0x3f);
+			t = t << 6;
+
+			/* A straightforward 64-byte lookup would be faster
+			 * and cleaner, but this is shorter.
+			 */
+			if (i >= snip) {
+				y = '=';
+			} else if (x <= 25) {
+				y = x + 'A';
+			} else if (x <= 51) {
+				y = x - 26 + 'a';
+			} else if (x <= 61) {
+				y = x - 52 + '0';
+			} else if (x == 62) {
+				y = '+';
+			} else {
+				y = '/';
+			}
+
+			*dst++ = (duk_uint8_t) y;
+		}
+	}
+}
+#endif  /* DUK_USE_BASE64_FASTPATH */
+
+#if defined(DUK_USE_BASE64_FASTPATH)
+DUK_LOCAL duk_bool_t duk__base64_decode_helper(const duk_uint8_t *src, duk_size_t srclen, duk_uint8_t *dst, duk_uint8_t **out_dst_final) {
+	duk_int_t x;
+	duk_int_t t;
+	duk_small_uint_t n_equal;
+	duk_small_uint_t n_chars;
+	const duk_uint8_t *src_end;
+	const duk_uint8_t *src_end_safe;
+
+	src_end = src + srclen;
+	src_end_safe = src_end - 4;  /* if 'src < src_end_safe', safe to read 4 bytes */
+
+	/* Innermost fast path processes 4 valid base-64 characters at a time
+	 * but bails out on whitespace, padding chars ('=') and invalid chars.
+	 * Once the slow path segment has been processed, we return to the
+	 * inner fast path again.  This handles e.g. base64 with newlines
+	 * reasonably well because the majority of a line is in the fast path.
+	 */
+	for (;;) {
+		/* Fast path, handle units with just actual encoding characters. */
+
+		while (src <= src_end_safe) {
+			/* The lookup byte is intentionally sign extended to (at least)
+			 * 32 bits and then ORed.  This ensures that is at least 1 byte
+			 * is negative, the highest bit of 't' will be set at the end
+			 * and we don't need to check every byte.
+			 */
+			DUK_DDD(DUK_DDDPRINT("fast loop: src=%p, src_end_safe=%p, src_end=%p",
+			                     (const void *) src, (const void *) src_end_safe, (const void *) src_end));
+
+			t = (duk_int_t) duk_base64_dectab[*src++];
+			t = (t << 6) | (duk_int_t) duk_base64_dectab[*src++];
+			t = (t << 6) | (duk_int_t) duk_base64_dectab[*src++];
+			t = (t << 6) | (duk_int_t) duk_base64_dectab[*src++];
+
+			if (DUK_UNLIKELY(t < 0)) {
+				DUK_DDD(DUK_DDDPRINT("fast loop unit was not clean, process one slow path unit"));
+				src -= 4;
+				break;
+			}
+
+			DUK_ASSERT(t <= 0xffffffL);
+			DUK_ASSERT((t >> 24) == 0);
+			*dst++ = (duk_uint8_t) (t >> 16);
+			*dst++ = (duk_uint8_t) ((t >> 8) & 0xff);
+			*dst++ = (duk_uint8_t) (t & 0xff);
+		}
+
+		/* Handle one slow path unit (or finish if we're done). */
+
+		n_equal = 0;
+		n_chars = 0;
+		t = 0;
+		for (;;) {
+			DUK_DDD(DUK_DDDPRINT("slow loop: src=%p, src_end=%p, n_chars=%ld, n_equal=%ld, t=%ld",
+			                     (const void *) src, (const void *) src_end, (long) n_chars, (long) n_equal, (long) t));
+
+			if (DUK_UNLIKELY(src >= src_end)) {
+				goto done;  /* two level break */
+			}
+
+			x = duk_base64_dectab[*src++];
+			if (DUK_UNLIKELY(x < 0)) {
+				if (x == -2) {
+					continue;  /* allowed ascii whitespace */
+				} else if (x == -3) {
+					n_equal++;
+					t <<= 6;
+				} else {
+					DUK_ASSERT(x == -1);
+					goto error;
+				}
+			} else {
+				DUK_ASSERT(x >= 0 && x <= 63);
+				if (n_equal > 0) {
+					/* Don't allow actual chars after equal sign. */
+					goto error;
+				}
+				t = (t << 6) + x;
+			}
+
+			if (DUK_UNLIKELY(n_chars == 3)) {
+				/* Emit 3 bytes and backtrack if there was padding.  There's
+				 * always space for the whole 3 bytes so no check needed.
+				 */
+				DUK_ASSERT(t <= 0xffffffL);
+				DUK_ASSERT((t >> 24) == 0);
+				*dst++ = (duk_uint8_t) (t >> 16);
+				*dst++ = (duk_uint8_t) ((t >> 8) & 0xff);
+				*dst++ = (duk_uint8_t) (t & 0xff);
+
+				if (DUK_UNLIKELY(n_equal > 0)) {
+					DUK_ASSERT(n_equal <= 4);
+
+					/* There may be whitespace between the equal signs. */
+					if (n_equal == 1) {
+						/* XXX= */
+						dst -= 1;
+					} else if (n_equal == 2) {
+						/* XX== */
+						dst -= 2;
+					} else {
+						goto error;  /* invalid padding */
+					}
+
+					/* Continue parsing after padding, allows concatenated,
+					 * padded base64.
+					 */
+				}
+				break;  /* back to fast loop */
+			} else {
+				n_chars++;
+			}
+		}
+	}
+ done:
+	DUK_DDD(DUK_DDDPRINT("done; src=%p, src_end=%p, n_chars=%ld",
+	                     (const void *) src, (const void *) src_end, (long) n_chars));
+
+	DUK_ASSERT(src == src_end);
+
+	if (n_chars != 0) {
+		/* Here we'd have the option of decoding unpadded base64
+		 * (e.g. "xxxxyy" instead of "xxxxyy==".  Currently not
+		 * accepted.
+		 */
+		goto error;
+	}
+
+	*out_dst_final = dst;
+	return 1;
+
+ error:
+	return 0;
+}
+#else  /* DUK_USE_BASE64_FASTPATH */
+DUK_LOCAL duk_bool_t duk__base64_decode_helper(const duk_uint8_t *src, duk_size_t srclen, duk_uint8_t *dst, duk_uint8_t **out_dst_final) {
+	duk_uint_t t;
+	duk_uint_fast8_t x, y;
+	duk_small_uint_t group_idx;
+	duk_small_uint_t n_equal;
+	const duk_uint8_t *src_end;
+
+	src_end = src + srclen;
+	t = 0;
+	group_idx = 0;
+	n_equal = 0;
+
+	while (src < src_end) {
+		x = *src++;
+
+		if (x >= 'A' && x <= 'Z') {
+			y = x - 'A' + 0;
+		} else if (x >= 'a' && x <= 'z') {
+			y = x - 'a' + 26;
+		} else if (x >= '0' && x <= '9') {
+			y = x - '0' + 52;
+		} else if (x == '+') {
+			y = 62;
+		} else if (x == '/') {
+			y = 63;
+		} else if (x == '=') {
+			/* We don't check the zero padding bytes here right now
+			 * (that they're actually zero).  This seems to be common
+			 * behavior for base-64 decoders.
+			 */
+
+			n_equal++;
+			t <<= 6;  /* shift in zeroes */
+			goto skip_add;
+		} else if (x == 0x09 || x == 0x0a || x == 0x0d || x == 0x20) {
+			/* allow basic ASCII whitespace */
+			continue;
+		} else {
+			goto error;
+		}
+
+		if (n_equal > 0) {
+			/* Don't allow mixed padding and actual chars. */
+			goto error;
+		}
+		t = (t << 6) + y;
+	 skip_add:
+
+		if (group_idx == 3) {
+			/* output 3 bytes from 't' */
+			*dst++ = (duk_uint8_t) ((t >> 16) & 0xff);
+			*dst++ = (duk_uint8_t) ((t >> 8) & 0xff);
+			*dst++ = (duk_uint8_t) (t & 0xff);
+
+			if (DUK_UNLIKELY(n_equal > 0)) {
+				/* Backtrack. */
+				DUK_ASSERT(n_equal <= 4);
+				if (n_equal == 1) {
+					dst -= 1;
+				} else if (n_equal == 2) {
+					dst -= 2;
+				} else {
+					goto error;  /* invalid padding */
+				}
+
+				/* Here we can choose either to end parsing and ignore
+				 * whatever follows, or to continue parsing in case
+				 * multiple (possibly padded) base64 strings have been
+				 * concatenated.  Currently, keep on parsing.
+				 */
+				n_equal = 0;
+			}
+
+			t = 0;
+			group_idx = 0;
+		} else {
+			group_idx++;
+		}
+	}
+
+	if (group_idx != 0) {
+		/* Here we'd have the option of decoding unpadded base64
+		 * (e.g. "xxxxyy" instead of "xxxxyy==".  Currently not
+		 * accepted.
+		 */
+		goto error;
+	}
+
+	*out_dst_final = dst;
+	return 1;
+
+ error:
+	return 0;
+}
+#endif  /* DUK_USE_BASE64_FASTPATH */
+
+DUK_EXTERNAL const char *duk_base64_encode(duk_context *ctx, duk_idx_t index) {
+	duk_hthread *thr = (duk_hthread *) ctx;
+	const duk_uint8_t *src;
+	duk_size_t srclen;
+	duk_size_t dstlen;
+	duk_uint8_t *dst;
+	const char *ret;
+
+	DUK_ASSERT_CTX_VALID(ctx);
+
+	/* XXX: optimize for string inputs: no need to coerce to a buffer
+	 * which makes a copy of the input.
+	 */
+
+	index = duk_require_normalize_index(ctx, index);
+	src = duk__prep_codec_arg(ctx, index, &srclen);
+	/* Note: for srclen=0, src may be NULL */
+
+	/* Computation must not wrap; this limit works for 32-bit size_t:
+	 * >>> srclen = 3221225469
+	 * >>> '%x' % ((srclen + 2) / 3 * 4)
+	 * 'fffffffc'
+	 */
+	if (srclen > 3221225469UL) {
+		goto type_error;
+	}
+	dstlen = (srclen + 2) / 3 * 4;
+	dst = (duk_uint8_t *) duk_push_fixed_buffer(ctx, dstlen);
+
+	duk__base64_encode_helper((const duk_uint8_t *) src, srclen, dst);
+
+	ret = duk_to_string(ctx, -1);
+	duk_replace(ctx, index);
+	return ret;
+
+ type_error:
+	DUK_ERROR(thr, DUK_ERR_TYPE_ERROR, DUK_STR_ENCODE_FAILED);
+	return NULL;  /* never here */
+}
+
+DUK_EXTERNAL void duk_base64_decode(duk_context *ctx, duk_idx_t index) {
+	duk_hthread *thr = (duk_hthread *) ctx;
+	const duk_uint8_t *src;
+	duk_size_t srclen;
+	duk_size_t dstlen;
+	duk_uint8_t *dst;
+	duk_uint8_t *dst_final;
+	duk_bool_t retval;
+
+	DUK_ASSERT_CTX_VALID(ctx);
+
+	/* XXX: optimize for buffer inputs: no need to coerce to a string
+	 * which causes an unnecessary interning.
+	 */
+
+	index = duk_require_normalize_index(ctx, index);
+	src = duk__prep_codec_arg(ctx, index, &srclen);
+
+	/* Computation must not wrap, only srclen + 3 is at risk of
+	 * wrapping because after that the number gets smaller.
+	 * This limit works for 32-bit size_t:
+	 * 0x100000000 - 3 - 1 = 4294967292
+	 */
+	if (srclen > 4294967292UL) {
+		goto type_error;
+	}
+	dstlen = (srclen + 3) / 4 * 3;  /* upper limit, assuming no whitespace etc */
+	dst = (duk_uint8_t *) duk_push_dynamic_buffer(ctx, dstlen);
+	/* Note: for dstlen=0, dst may be NULL */
+
+	retval = duk__base64_decode_helper((const duk_uint8_t *) src, srclen, dst, &dst_final);
+	if (!retval) {
+		goto type_error;
+	}
+
+	/* XXX: convert to fixed buffer? */
+	(void) duk_resize_buffer(ctx, -1, (duk_size_t) (dst_final - dst));
+	duk_replace(ctx, index);
+	return;
+
+ type_error:
+	DUK_ERROR(thr, DUK_ERR_TYPE_ERROR, DUK_STR_DECODE_FAILED);
+}
+
+DUK_EXTERNAL const char *duk_hex_encode(duk_context *ctx, duk_idx_t index) {
+	const duk_uint8_t *inp;
+	duk_size_t len;
+	duk_size_t i;
+	duk_uint8_t *buf;
+	const char *ret;
+#if defined(DUK_USE_HEX_FASTPATH)
+	duk_size_t len_safe;
+	duk_uint16_t *p16;
+#endif
+
+	DUK_ASSERT_CTX_VALID(ctx);
+
+	index = duk_require_normalize_index(ctx, index);
+	inp = duk__prep_codec_arg(ctx, index, &len);
+	DUK_ASSERT(inp != NULL || len == 0);
+
+	/* Fixed buffer, no zeroing because we'll fill all the data. */
+	buf = (duk_uint8_t *) duk_push_buffer_raw(ctx, len * 2, DUK_BUF_FLAG_NOZERO /*flags*/);
+	DUK_ASSERT(buf != NULL);
+
+#if defined(DUK_USE_HEX_FASTPATH)
+	DUK_ASSERT((((duk_uintptr_t) buf) & 0x01U) == 0);   /* pointer is aligned, guaranteed for fixed buffer */
+	p16 = (duk_uint16_t *) (void *) buf;
+	len_safe = len & ~0x03U;
+	for (i = 0; i < len_safe; i += 4) {
+		p16[0] = duk_hex_enctab[inp[i]];
+		p16[1] = duk_hex_enctab[inp[i + 1]];
+		p16[2] = duk_hex_enctab[inp[i + 2]];
+		p16[3] = duk_hex_enctab[inp[i + 3]];
+		p16 += 4;
+	}
+	for (; i < len; i++) {
+		*p16++ = duk_hex_enctab[inp[i]];
+	}
+#else  /* DUK_USE_HEX_FASTPATH */
+	for (i = 0; i < len; i++) {
+		duk_small_uint_t t;
+		t = (duk_small_uint_t) inp[i];
+		buf[i*2 + 0] = duk_lc_digits[t >> 4];
+		buf[i*2 + 1] = duk_lc_digits[t & 0x0f];
+	}
+#endif  /* DUK_USE_HEX_FASTPATH */
+
+	/* XXX: Using a string return value forces a string intern which is
+	 * not always necessary.  As a rough performance measure, hex encode
+	 * time for tests/perf/test-hex-encode.js dropped from ~35s to ~15s
+	 * without string coercion.  Change to returning a buffer and let the
+	 * caller coerce to string if necessary?
+	 */
+
+	ret = duk_to_string(ctx, -1);
+	duk_replace(ctx, index);
+	return ret;
+}
+
+DUK_EXTERNAL void duk_hex_decode(duk_context *ctx, duk_idx_t index) {
+	duk_hthread *thr = (duk_hthread *) ctx;
+	const duk_uint8_t *inp;
+	duk_size_t len;
+	duk_size_t i;
+	duk_int_t t;
+	duk_uint8_t *buf;
+#if defined(DUK_USE_HEX_FASTPATH)
+	duk_int_t chk;
+	duk_uint8_t *p;
+	duk_size_t len_safe;
+#endif
+
+	DUK_ASSERT_CTX_VALID(ctx);
+
+	index = duk_require_normalize_index(ctx, index);
+	inp = duk__prep_codec_arg(ctx, index, &len);
+	DUK_ASSERT(inp != NULL || len == 0);
+
+	if (len & 0x01) {
+		goto type_error;
+	}
+
+	/* Fixed buffer, no zeroing because we'll fill all the data. */
+	buf = (duk_uint8_t *) duk_push_buffer_raw(ctx, len / 2, DUK_BUF_FLAG_NOZERO /*flags*/);
+	DUK_ASSERT(buf != NULL);
+
+#if defined(DUK_USE_HEX_FASTPATH)
+	p = buf;
+	len_safe = len & ~0x07U;
+	for (i = 0; i < len_safe; i += 8) {
+		t = ((duk_int_t) duk_hex_dectab_shift4[inp[i]]) |
+		    ((duk_int_t) duk_hex_dectab[inp[i + 1]]);
+		chk = t;
+		p[0] = (duk_uint8_t) t;
+		t = ((duk_int_t) duk_hex_dectab_shift4[inp[i + 2]]) |
+		    ((duk_int_t) duk_hex_dectab[inp[i + 3]]);
+		chk |= t;
+		p[1] = (duk_uint8_t) t;
+		t = ((duk_int_t) duk_hex_dectab_shift4[inp[i + 4]]) |
+		    ((duk_int_t) duk_hex_dectab[inp[i + 5]]);
+		chk |= t;
+		p[2] = (duk_uint8_t) t;
+		t = ((duk_int_t) duk_hex_dectab_shift4[inp[i + 6]]) |
+		    ((duk_int_t) duk_hex_dectab[inp[i + 7]]);
+		chk |= t;
+		p[3] = (duk_uint8_t) t;
+		p += 4;
+
+		/* Check if any lookup above had a negative result. */
+		if (DUK_UNLIKELY(chk < 0)) {
+			goto type_error;
+		}
+	}
+	for (; i < len; i += 2) {
+		t = (((duk_int_t) duk_hex_dectab[inp[i]]) << 4) |
+		    ((duk_int_t) duk_hex_dectab[inp[i + 1]]);
+		if (DUK_UNLIKELY(t < 0)) {
+			goto type_error;
+		}
+		*p++ = (duk_uint8_t) t;
+	}
+#else  /* DUK_USE_HEX_FASTPATH */
+	for (i = 0; i < len; i += 2) {
+		/* For invalid characters the value -1 gets extended to
+		 * at least 16 bits.  If either nybble is invalid, the
+		 * resulting 't' will be < 0.
+		 */
+		t = (((duk_int_t) duk_hex_dectab[inp[i]]) << 4) |
+		    ((duk_int_t) duk_hex_dectab[inp[i + 1]]);
+		if (DUK_UNLIKELY(t < 0)) {
+			goto type_error;
+		}
+		buf[i >> 1] = (duk_uint8_t) t;
+	}
+#endif  /* DUK_USE_HEX_FASTPATH */
+
+	duk_replace(ctx, index);
+	return;
+
+ type_error:
+	DUK_ERROR(thr, DUK_ERR_TYPE_ERROR, DUK_STR_DECODE_FAILED);
+}
+
+DUK_EXTERNAL const char *duk_json_encode(duk_context *ctx, duk_idx_t index) {
+#ifdef DUK_USE_ASSERTIONS
+	duk_idx_t top_at_entry;
+#endif
+	const char *ret;
+
+	DUK_ASSERT_CTX_VALID(ctx);
+#ifdef DUK_USE_ASSERTIONS
+	top_at_entry = duk_get_top(ctx);
+#endif
+
+	index = duk_require_normalize_index(ctx, index);
+	duk_bi_json_stringify_helper(ctx,
+	                             index /*idx_value*/,
+	                             DUK_INVALID_INDEX /*idx_replacer*/,
+	                             DUK_INVALID_INDEX /*idx_space*/,
+	                             0 /*flags*/);
+	DUK_ASSERT(duk_is_string(ctx, -1));
+	duk_replace(ctx, index);
+	ret = duk_get_string(ctx, index);
+
+	DUK_ASSERT(duk_get_top(ctx) == top_at_entry);
+
+	return ret;
+}
+
+DUK_EXTERNAL void duk_json_decode(duk_context *ctx, duk_idx_t index) {
+#ifdef DUK_USE_ASSERTIONS
+	duk_idx_t top_at_entry;
+#endif
+
+	DUK_ASSERT_CTX_VALID(ctx);
+#ifdef DUK_USE_ASSERTIONS
+	top_at_entry = duk_get_top(ctx);
+#endif
+
+	index = duk_require_normalize_index(ctx, index);
+	duk_bi_json_parse_helper(ctx,
+	                         index /*idx_value*/,
+	                         DUK_INVALID_INDEX /*idx_reviver*/,
+	                         0 /*flags*/);
+	duk_replace(ctx, index);
+
+	DUK_ASSERT(duk_get_top(ctx) == top_at_entry);
+}
+#line 1 "duk_api_compile.c"
+/*
+ *  Compilation and evaluation
+ */
+
+/* include removed: duk_internal.h */
+
+typedef struct duk__compile_raw_args duk__compile_raw_args;
+struct duk__compile_raw_args {
+	duk_size_t src_length;  /* should be first on 64-bit platforms */
+	const duk_uint8_t *src_buffer;
+	duk_uint_t flags;
+};
+
+/* Eval is just a wrapper now. */
+DUK_EXTERNAL duk_int_t duk_eval_raw(duk_context *ctx, const char *src_buffer, duk_size_t src_length, duk_uint_t flags) {
+	duk_uint_t comp_flags;
+	duk_int_t rc;
+
+	DUK_ASSERT_CTX_VALID(ctx);
+
+	/* Note: strictness is *not* inherited from the current Duktape/C.
+	 * This would be confusing because the current strictness state
+	 * depends on whether we're running inside a Duktape/C activation
+	 * (= strict mode) or outside of any activation (= non-strict mode).
+	 * See tests/api/test-eval-strictness.c for more discussion.
+	 */
+
+	/* [ ... source? filename ] (depends on flags) */
+
+	comp_flags = flags;
+	comp_flags |= DUK_COMPILE_EVAL;
+	rc = duk_compile_raw(ctx, src_buffer, src_length, comp_flags);  /* may be safe, or non-safe depending on flags */
+
+	/* [ ... closure/error ] */
+
+	if (rc != DUK_EXEC_SUCCESS) {
+		rc = DUK_EXEC_ERROR;
+		goto got_rc;
+	}
+
+	duk_push_global_object(ctx);  /* explicit 'this' binding, see GH-164 */
+
+	if (flags & DUK_COMPILE_SAFE) {
+		rc = duk_pcall_method(ctx, 0);
+	} else {
+		duk_call_method(ctx, 0);
+		rc = DUK_EXEC_SUCCESS;
+	}
+
+	/* [ ... result/error ] */
+
+ got_rc:
+	if (flags & DUK_COMPILE_NORESULT) {
+		duk_pop(ctx);
+	}
+
+	return rc;
+}
+
+/* Helper which can be called both directly and with duk_safe_call(). */
+DUK_LOCAL duk_ret_t duk__do_compile(duk_context *ctx) {
+	duk_hthread *thr = (duk_hthread *) ctx;
+	duk__compile_raw_args *comp_args;
+	duk_uint_t flags;
+	duk_small_uint_t comp_flags;
+	duk_hcompiledfunction *h_templ;
+
+	DUK_ASSERT_CTX_VALID(ctx);
+
+	/* Note: strictness is not inherited from the current Duktape/C
+	 * context.  Otherwise it would not be possible to compile
+	 * non-strict code inside a Duktape/C activation (which is
+	 * always strict now).  See tests/api/test-eval-strictness.c
+	 * for discussion.
+	 */
+
+	/* [ ... source? filename &comp_args ] (depends on flags) */
+
+	comp_args = (duk__compile_raw_args *) duk_require_pointer(ctx, -1);
+	flags = comp_args->flags;
+	duk_pop(ctx);
+
+	/* [ ... source? filename ] */
+
+	if (!comp_args->src_buffer) {
+		duk_hstring *h_sourcecode;
+
+		h_sourcecode = duk_get_hstring(ctx, -2);
+		if ((flags & DUK_COMPILE_NOSOURCE) ||  /* args incorrect */
+		    (h_sourcecode == NULL)) {          /* e.g. duk_push_string_file_raw() pushed undefined */
+			/* XXX: when this error is caused by a nonexistent
+			 * file given to duk_peval_file() or similar, the
+			 * error message is not the best possible.
+			 */
+			DUK_ERROR_API(thr, DUK_STR_NO_SOURCECODE);
+		}
+		DUK_ASSERT(h_sourcecode != NULL);
+		comp_args->src_buffer = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_sourcecode);
+		comp_args->src_length = (duk_size_t) DUK_HSTRING_GET_BYTELEN(h_sourcecode);
+	}
+	DUK_ASSERT(comp_args->src_buffer != NULL);
+
+	/* XXX: unnecessary translation of flags */
+	comp_flags = 0;
+	if (flags & DUK_COMPILE_EVAL) {
+		comp_flags |= DUK_JS_COMPILE_FLAG_EVAL;
+	}
+	if (flags & DUK_COMPILE_FUNCTION) {
+		comp_flags |= DUK_JS_COMPILE_FLAG_EVAL |
+		              DUK_JS_COMPILE_FLAG_FUNCEXPR;
+	}
+	if (flags & DUK_COMPILE_STRICT) {
+		comp_flags |= DUK_JS_COMPILE_FLAG_STRICT;
+	}
+
+	/* [ ... source? filename ] */
+
+	duk_js_compile(thr, comp_args->src_buffer, comp_args->src_length, comp_flags);
+
+	/* [ ... source? func_template ] */
+
+	if (flags & DUK_COMPILE_NOSOURCE) {
+		;
+	} else {
+		duk_remove(ctx, -2);
+	}
+
+	/* [ ... func_template ] */
+
+	h_templ = (duk_hcompiledfunction *) duk_get_hobject(ctx, -1);
+	DUK_ASSERT(h_templ != NULL);
+	duk_js_push_closure(thr,
+	                   h_templ,
+	                   thr->builtins[DUK_BIDX_GLOBAL_ENV],
+	                   thr->builtins[DUK_BIDX_GLOBAL_ENV]);
+	duk_remove(ctx, -2);   /* -> [ ... closure ] */
+
+	/* [ ... closure ] */
+
+	return 1;
+}
+
+DUK_EXTERNAL duk_int_t duk_compile_raw(duk_context *ctx, const char *src_buffer, duk_size_t src_length, duk_uint_t flags) {
+	duk__compile_raw_args comp_args_alloc;
+	duk__compile_raw_args *comp_args = &comp_args_alloc;
+
+	DUK_ASSERT_CTX_VALID(ctx);
+
+	if ((flags & DUK_COMPILE_STRLEN) && (src_buffer != NULL)) {
+		/* String length is computed here to avoid multiple evaluation
+		 * of a macro argument in the calling side.
+		 */
+		src_length = DUK_STRLEN(src_buffer);
+	}
+
+	comp_args->src_buffer = (const duk_uint8_t *) src_buffer;
+	comp_args->src_length = src_length;
+	comp_args->flags = flags;
+	duk_push_pointer(ctx, (void *) comp_args);
+
+	/* [ ... source? filename &comp_args ] (depends on flags) */
+
+	if (flags & DUK_COMPILE_SAFE) {
+		duk_int_t rc;
+		duk_int_t nargs;
+		duk_int_t nrets = 1;
+
+		/* Arguments are either: [ filename &comp_args ] or [ source filename &comp_args ] */
+		nargs = (flags & DUK_COMPILE_NOSOURCE) ? 2 : 3;
+		rc = duk_safe_call(ctx, duk__do_compile, nargs, nrets);
+
+		/* [ ... closure ] */
+		return rc;
+	}
+
+	(void) duk__do_compile(ctx);
+
+	/* [ ... closure ] */
+	return DUK_EXEC_SUCCESS;
+}
+#line 1 "duk_api_debug.c"
+/*
+ *  Debugging related API calls
+ */
+
+/* include removed: duk_internal.h */
+
+DUK_EXTERNAL void duk_push_context_dump(duk_context *ctx) {
+	duk_idx_t idx;
+	duk_idx_t top;
+
+	DUK_ASSERT_CTX_VALID(ctx);
+
+	/* We don't duk_require_stack() here now, but rely on the caller having
+	 * enough space.
+	 */
+
+	top = duk_get_top(ctx);
+	duk_push_array(ctx);
+	for (idx = 0; idx < top; idx++) {
+		duk_dup(ctx, idx);
+		duk_put_prop_index(ctx, -2, idx);
+	}
+
+	/* XXX: conversion errors should not propagate outwards.
+	 * Perhaps values need to be coerced individually?
+	 */
+	duk_bi_json_stringify_helper(ctx,
+	                             duk_get_top_index(ctx),  /*idx_value*/
+	                             DUK_INVALID_INDEX,  /*idx_replacer*/
+	                             DUK_INVALID_INDEX,  /*idx_space*/
+	                             DUK_JSON_FLAG_EXT_CUSTOM |
+	                             DUK_JSON_FLAG_ASCII_ONLY |
+	                             DUK_JSON_FLAG_AVOID_KEY_QUOTES /*flags*/);
+
+	duk_push_sprintf(ctx, "ctx: top=%ld, stack=%s", (long) top, (const char *) duk_safe_to_string(ctx, -1));
+	duk_replace(ctx, -3);  /* [ ... arr jsonx(arr) res ] -> [ ... res jsonx(arr) ] */
+	duk_pop(ctx);
+	DUK_ASSERT(duk_is_string(ctx, -1));
+}
+
+#if defined(DUK_USE_DEBUGGER_SUPPORT)
+
+DUK_EXTERNAL void duk_debugger_attach(duk_context *ctx,
+                                      duk_debug_read_function read_cb,
+                                      duk_debug_write_function write_cb,
+                                      duk_debug_peek_function peek_cb,
+                                      duk_debug_read_flush_function read_flush_cb,
+                                      duk_debug_write_flush_function write_flush_cb,
+                                      duk_debug_detached_function detached_cb,
+                                      void *udata) {
+	duk_hthread *thr = (duk_hthread *) ctx;
+	duk_heap *heap;
+	const char *str;
+	duk_size_t len;
+
+	/* XXX: should there be an error or an automatic detach if
+	 * already attached?
+	 */
+
+	DUK_ASSERT_CTX_VALID(ctx);
+	DUK_ASSERT(read_cb != NULL);
+	DUK_ASSERT(write_cb != NULL);
+	/* Other callbacks are optional. */
+
+	heap = thr->heap;
+	heap->dbg_read_cb = read_cb;
+	heap->dbg_write_cb = write_cb;
+	heap->dbg_peek_cb = peek_cb;
+	heap->dbg_read_flush_cb = read_flush_cb;
+	heap->dbg_write_flush_cb = write_flush_cb;
+	heap->dbg_detached_cb = detached_cb;
+	heap->dbg_udata = udata;
+	heap->dbg_have_next_byte = 0;
+
+	/* Start in paused state. */
+	heap->dbg_processing = 0;
+	heap->dbg_paused = 1;
+	heap->dbg_state_dirty = 1;
+	heap->dbg_force_restart = 0;
+	heap->dbg_step_type = 0;
+	heap->dbg_step_thread = NULL;
+	heap->dbg_step_csindex = 0;
+	heap->dbg_step_startline = 0;
+	heap->dbg_exec_counter = 0;
+	heap->dbg_last_counter = 0;
+	heap->dbg_last_time = 0.0;
+
+	/* Send version identification and flush right afterwards.  Note that
+	 * we must write raw, unframed bytes here.
+	 */
+	duk_push_sprintf(ctx, "%ld %ld %s %s\n",
+	                 (long) DUK_DEBUG_PROTOCOL_VERSION,
+	                 (long) DUK_VERSION,
+	                 (const char *) DUK_GIT_DESCRIBE,
+	                 (const char *) DUK_USE_TARGET_INFO);
+	str = duk_get_lstring(ctx, -1, &len);
+	DUK_ASSERT(str != NULL);
+	duk_debug_write_bytes(thr, (const duk_uint8_t *) str, len);
+	duk_debug_write_flush(thr);
+	duk_pop(ctx);
+}
+
+DUK_EXTERNAL void duk_debugger_detach(duk_context *ctx) {
+	duk_hthread *thr;
+
+	DUK_ASSERT_CTX_VALID(ctx);
+	thr = (duk_hthread *) ctx;
+	DUK_ASSERT(thr != NULL);
+	DUK_ASSERT(thr->heap != NULL);
+
+	/* Can be called multiple times with no harm. */
+	duk_debug_do_detach(thr->heap);
+}
+
+DUK_EXTERNAL void duk_debugger_cooperate(duk_context *ctx) {
+	duk_hthread *thr;
+	duk_bool_t processed_messages;
+
+	DUK_ASSERT_CTX_VALID(ctx);
+	thr = (duk_hthread *) ctx;
+	DUK_ASSERT(thr != NULL);
+	DUK_ASSERT(thr->heap != NULL);
+
+	if (!DUK_HEAP_IS_DEBUGGER_ATTACHED(thr->heap)) {
+		return;
+	}
+	if (thr->callstack_top > 0 || thr->heap->dbg_processing) {
+		/* Calling duk_debugger_cooperate() while Duktape is being
+		 * called into is not supported.  This is not a 100% check
+		 * but prevents any damage in most cases.
+		 */
+		return;
+	}
+
+	thr->heap->dbg_processing = 1;
+	processed_messages = duk_debug_process_messages(thr, 1 /*no_block*/);
+	thr->heap->dbg_processing = 0;
+	DUK_UNREF(processed_messages);
+}
+
+#else  /* DUK_USE_DEBUGGER_SUPPORT */
+
+DUK_EXTERNAL void duk_debugger_attach(duk_context *ctx,
+                                      duk_debug_read_function read_cb,
+                                      duk_debug_write_function write_cb,
+                                      duk_debug_peek_function peek_cb,
+                                      duk_debug_read_flush_function read_flush_cb,
+                                      duk_debug_write_flush_function write_flush_cb,
+                                      duk_debug_detached_function detached_cb,
+                                      void *udata) {
+	DUK_ASSERT_CTX_VALID(ctx);
+	DUK_UNREF(read_cb);
+	DUK_UNREF(write_cb);
+	DUK_UNREF(peek_cb);
+	DUK_UNREF(read_flush_cb);
+	DUK_UNREF(write_flush_cb);
+	DUK_UNREF(detached_cb);
+	DUK_UNREF(udata);
+	DUK_ERROR_API((duk_hthread *) ctx, "no debugger support");
+}
+
+DUK_EXTERNAL void duk_debugger_detach(duk_context *ctx) {
+	DUK_ASSERT_CTX_VALID(ctx);
+	DUK_ERROR_API((duk_hthread *) ctx, "no debugger support");
+}
+
+DUK_EXTERNAL void duk_debugger_cooperate(duk_context *ctx) {
+	/* nop */
+	DUK_ASSERT_CTX_VALID(ctx);
+	DUK_UNREF(ctx);
+}
+
+#endif  /* DUK_USE_DEBUGGER_SUPPORT */
+#line 1 "duk_api_heap.c"
+/*
+ *  Heap creation and destruction
+ */
+
+/* include removed: duk_internal.h */
+
+DUK_EXTERNAL
+duk_context *duk_create_heap(duk_alloc_function alloc_func,
+                             duk_realloc_function realloc_func,
+                             duk_free_function free_func,
+                             void *heap_udata,
+                             duk_fatal_function fatal_handler) {
+	duk_heap *heap = NULL;
+	duk_context *ctx;
+
+	/* Assume that either all memory funcs are NULL or non-NULL, mixed
+	 * cases will now be unsafe.
+	 */
+
+	/* XXX: just assert non-NULL values here and make caller arguments
+	 * do the defaulting to the default implementations (smaller code)?
+	 */
+
+	if (!alloc_func) {
+		DUK_ASSERT(realloc_func == NULL);
+		DUK_ASSERT(free_func == NULL);
+		alloc_func = duk_default_alloc_function;
+		realloc_func = duk_default_realloc_function;
+		free_func = duk_default_free_function;
+	} else {
+		DUK_ASSERT(realloc_func != NULL);
+		DUK_ASSERT(free_func != NULL);
+	}
+
+	if (!fatal_handler) {
+		fatal_handler = duk_default_fatal_handler;
+	}
+
+	DUK_ASSERT(alloc_func != NULL);
+	DUK_ASSERT(realloc_func != NULL);
+	DUK_ASSERT(free_func != NULL);
+	DUK_ASSERT(fatal_handler != NULL);
+
+	heap = duk_heap_alloc(alloc_func, realloc_func, free_func, heap_udata, fatal_handler);
+	if (!heap) {
+		return NULL;
+	}
+	ctx = (duk_context *) heap->heap_thread;
+	DUK_ASSERT(ctx != NULL);
+	DUK_ASSERT(((duk_hthread *) ctx)->heap != NULL);
+	return ctx;
+}
+
+DUK_EXTERNAL void duk_destroy_heap(duk_context *ctx) {
+	duk_hthread *thr = (duk_hthread *) ctx;
+	duk_heap *heap;
+
+	if (!ctx) {
+		return;
+	}
+	heap = thr->heap;
+	DUK_ASSERT(heap != NULL);
+
+	duk_heap_free(heap);
+}
+
+/* XXX: better place for this */
+DUK_EXTERNAL void duk_set_global_object(duk_context *ctx) {
+	duk_hthread *thr = (duk_hthread *) ctx;
+	duk_hobject *h_glob;
+	duk_hobject *h_prev_glob;
+	duk_hobject *h_env;
+	duk_hobject *h_prev_env;
+
+	DUK_D(DUK_DPRINT("replace global object with: %!T", duk_get_tval(ctx, -1)));
+
+	h_glob = duk_require_hobject(ctx, -1);
+	DUK_ASSERT(h_glob != NULL);
+
+	/*
+	 *  Replace global object.
+	 */
+
+	h_prev_glob = thr->builtins[DUK_BIDX_GLOBAL];
+	DUK_UNREF(h_prev_glob);
+	thr->builtins[DUK_BIDX_GLOBAL] = h_glob;
+	DUK_HOBJECT_INCREF(thr, h_glob);
+	DUK_HOBJECT_DECREF_ALLOWNULL(thr, h_prev_glob);  /* side effects, in theory (referenced by global env) */
+
+	/*
+	 *  Replace lexical environment for global scope
+	 *
+	 *  Create a new object environment for the global lexical scope.
+	 *  We can't just reset the _Target property of the current one,
+	 *  because the lexical scope is shared by other threads with the
+	 *  same (initial) built-ins.
+	 */
+
+	(void) duk_push_object_helper(ctx,
+	                              DUK_HOBJECT_FLAG_EXTENSIBLE |
+	                              DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_OBJENV),
+	                              -1);  /* no prototype, updated below */
+
+	duk_dup(ctx, -2);
+	duk_dup(ctx, -3);
+
+	/* [ ... new_glob new_env new_glob new_glob ] */
+
+	duk_xdef_prop_stridx(thr, -3, DUK_STRIDX_INT_TARGET, DUK_PROPDESC_FLAGS_NONE);
+	duk_xdef_prop_stridx(thr, -2, DUK_STRIDX_INT_THIS, DUK_PROPDESC_FLAGS_NONE);
+
+	/* [ ... new_glob new_env ] */
+
+	h_env = duk_get_hobject(ctx, -1);
+	DUK_ASSERT(h_env != NULL);
+
+	h_prev_env = thr->builtins[DUK_BIDX_GLOBAL_ENV];
+	thr->builtins[DUK_BIDX_GLOBAL_ENV] = h_env;
+	DUK_HOBJECT_INCREF(thr, h_env);
+	DUK_HOBJECT_DECREF_ALLOWNULL(thr, h_prev_env);  /* side effects */
+	DUK_UNREF(h_env);  /* without refcounts */
+	DUK_UNREF(h_prev_env);
+
+	/* [ ... new_glob new_env ] */
+
+	duk_pop_2(ctx);
+
+	/* [ ... ] */
+}
+#line 1 "duk_api_logging.c"
+/*
+ *  Logging
+ *
+ *  Current logging primitive is a sprintf-style log which is convenient
+ *  for most C code.  Another useful primitive would be to log N arguments
+ *  from value stack (like the Ecmascript binding does).
+ */
+
+/* include removed: duk_internal.h */
+
+DUK_EXTERNAL void duk_log_va(duk_context *ctx, duk_int_t level, const char *fmt, va_list ap) {
+	/* stridx_logfunc[] must be static to allow initializer with old compilers like BCC */
+	static const duk_uint16_t stridx_logfunc[6] = {
+		DUK_STRIDX_LC_TRACE, DUK_STRIDX_LC_DEBUG, DUK_STRIDX_LC_INFO,
+		DUK_STRIDX_LC_WARN, DUK_STRIDX_LC_ERROR, DUK_STRIDX_LC_FATAL
+	};
+
+	DUK_ASSERT_CTX_VALID(ctx);
+
+	if (level < 0) {
+		level = 0;
+	} else if (level > (int) (sizeof(stridx_logfunc) / sizeof(duk_uint16_t)) - 1) {
+		level = (int) (sizeof(stridx_logfunc) / sizeof(duk_uint16_t)) - 1;
+	}
+
+	duk_push_hobject_bidx(ctx, DUK_BIDX_LOGGER_CONSTRUCTOR);
+	duk_get_prop_stridx(ctx, -1, DUK_STRIDX_CLOG);
+	duk_get_prop_stridx(ctx, -1, stridx_logfunc[level]);
+	duk_dup(ctx, -2);
+
+	/* [ ... Logger clog logfunc clog ] */
+
+	duk_push_vsprintf(ctx, fmt, ap);
+
+	/* [ ... Logger clog logfunc clog(=this) msg ] */
+
+	duk_call_method(ctx, 1 /*nargs*/);
+
+	/* [ ... Logger clog res ] */
+
+	duk_pop_3(ctx);
+}
+
+DUK_EXTERNAL void duk_log(duk_context *ctx, duk_int_t level, const char *fmt, ...) {
+	va_list ap;
+
+	DUK_ASSERT_CTX_VALID(ctx);
+
+	va_start(ap, fmt);
+	duk_log_va(ctx, level, fmt, ap);
+	va_end(ap);
+}
+#line 1 "duk_api_memory.c"
+/*
+ *  Memory calls.
+ */
+
+/* include removed: duk_internal.h */
+
+DUK_EXTERNAL void *duk_alloc_raw(duk_context *ctx, duk_size_t size) {
+	duk_hthread *thr = (duk_hthread *) ctx;
+
+	DUK_ASSERT_CTX_VALID(ctx);
+
+	return DUK_ALLOC_RAW(thr->heap, size);
+}
+
+DUK_EXTERNAL void duk_free_raw(duk_context *ctx, void *ptr) {
+	duk_hthread *thr = (duk_hthread *) ctx;
+
+	DUK_ASSERT_CTX_VALID(ctx);
+
+	DUK_FREE_RAW(thr->heap, ptr);
+}
+
+DUK_EXTERNAL void *duk_realloc_raw(duk_context *ctx, void *ptr, duk_size_t size) {
+	duk_hthread *thr = (duk_hthread *) ctx;
+
+	DUK_ASSERT_CTX_VALID(ctx);
+
+	return DUK_REALLOC_RAW(thr->heap, ptr, size);
+}
+
+DUK_EXTERNAL void *duk_alloc(duk_context *ctx, duk_size_t size) {
+	duk_hthread *thr = (duk_hthread *) ctx;
+
+	DUK_ASSERT_CTX_VALID(ctx);
+
+	return DUK_ALLOC(thr->heap, size);
+}
+
+DUK_EXTERNAL void duk_free(duk_context *ctx, void *ptr) {
+	duk_hthread *thr = (duk_hthread *) ctx;
+
+	DUK_ASSERT_CTX_VALID(ctx);
+
+	DUK_FREE(thr->heap, ptr);
+}
+
+DUK_EXTERNAL void *duk_realloc(duk_context *ctx, void *ptr, duk_size_t size) {
+	duk_hthread *thr = (duk_hthread *) ctx;
+
+	DUK_ASSERT_CTX_VALID(ctx);
+
+	/*
+	 *  Note: since this is an exposed API call, there should be
+	 *  no way a mark-and-sweep could have a side effect on the
+	 *  memory allocation behind 'ptr'; the pointer should never
+	 *  be something that Duktape wants to change.
+	 *
+	 *  Thus, no need to use DUK_REALLOC_INDIRECT (and we don't
+	 *  have the storage location here anyway).
+	 */
+
+	return DUK_REALLOC(thr->heap, ptr, size);
+}
+
+DUK_EXTERNAL void duk_get_memory_functions(duk_context *ctx, duk_memory_functions *out_funcs) {
+	duk_hthread *thr = (duk_hthread *) ctx;
+	duk_heap *heap;
+
+	DUK_ASSERT_CTX_VALID(ctx);
+	DUK_ASSERT(out_funcs != NULL);
+	DUK_ASSERT(thr != NULL);
+	DUK_ASSERT(thr->heap != NULL);
+
+	heap = thr->heap;
+	out_funcs->alloc_func = heap->alloc_func;
+	out_funcs->realloc_func = heap->realloc_func;
+	out_funcs->free_func = heap->free_func;
+	out_funcs->udata = heap->heap_udata;
+}
+
+DUK_EXTERNAL void duk_gc(duk_context *ctx, duk_uint_t flags) {
+#ifdef DUK_USE_MARK_AND_SWEEP
+	duk_hthread *thr = (duk_hthread *) ctx;
+	duk_heap *heap;
+
+	DUK_UNREF(flags);
+
+	/* NULL accepted */
+	if (!ctx) {
+		return;
+	}
+	DUK_ASSERT_CTX_VALID(ctx);
+	heap = thr->heap;
+	DUK_ASSERT(heap != NULL);
+
+	DUK_D(DUK_DPRINT("mark-and-sweep requested by application"));
+	duk_heap_mark_and_sweep(heap, 0);
+#else
+	DUK_D(DUK_DPRINT("mark-and-sweep requested by application but mark-and-sweep not enabled, ignoring"));
+	DUK_UNREF(ctx);
+	DUK_UNREF(flags);
+#endif
+}
+#line 1 "duk_api_object.c"
+/*
+ *  Object handling: property access and other support functions.
+ */
+
+/* include removed: duk_internal.h */
+
+/*
+ *  Property handling
+ *
+ *  The API exposes only the most common property handling functions.
+ *  The caller can invoke Ecmascript built-ins for full control (e.g.
+ *  defineProperty, getOwnPropertyDescriptor).
+ */
+
+DUK_EXTERNAL duk_bool_t duk_get_prop(duk_context *ctx, duk_idx_t obj_index) {
+	duk_hthread *thr = (duk_hthread *) ctx;
+	duk_tval *tv_obj;
+	duk_tval *tv_key;
+	duk_bool_t rc;
+
+	DUK_ASSERT_CTX_VALID(ctx);
+
+	/* Note: copying tv_obj and tv_key to locals to shield against a valstack
+	 * resize is not necessary for a property get right now.
+	 */
+
+	tv_obj = duk_require_tval(ctx, obj_index);
+	tv_key = duk_require_tval(ctx, -1);
+
+	rc = duk_hobject_getprop(thr, tv_obj, tv_key);
+	DUK_ASSERT(rc == 0 || rc == 1);
+	/* a value is left on stack regardless of rc */
+
+	duk_remove(ctx, -2);  /* remove key */
+	return rc;  /* 1 if property found, 0 otherwise */
+}
+
+DUK_EXTERNAL duk_bool_t duk_get_prop_string(duk_context *ctx, duk_idx_t obj_index, const char *key) {
+	DUK_ASSERT_CTX_VALID(ctx);
+	DUK_ASSERT(key != NULL);
+
+	obj_index = duk_require_normalize_index(ctx, obj_index);
+	duk_push_string(ctx, key);
+	return duk_get_prop(ctx, obj_index);
+}
+
+DUK_EXTERNAL duk_bool_t duk_get_prop_index(duk_context *ctx, duk_idx_t obj_index, duk_uarridx_t arr_index) {
+	DUK_ASSERT_CTX_VALID(ctx);
+
+	obj_index = duk_require_normalize_index(ctx, obj_index);
+	duk_push_uarridx(ctx, arr_index);
+	return duk_get_prop(ctx, obj_index);
+}
+
+DUK_INTERNAL duk_bool_t duk_get_prop_stridx(duk_context *ctx, duk_idx_t obj_index, duk_small_int_t stridx) {
+	duk_hthread *thr = (duk_hthread *) ctx;
+
+	DUK_ASSERT_CTX_VALID(ctx);
+	DUK_ASSERT_DISABLE(stridx >= 0);
+	DUK_ASSERT(stridx < DUK_HEAP_NUM_STRINGS);
+
+	obj_index = duk_require_normalize_index(ctx, obj_index);
+	duk_push_hstring(ctx, DUK_HTHREAD_GET_STRING(thr, stridx));
+	return duk_get_prop(ctx, obj_index);
+}
+
+DUK_INTERNAL duk_bool_t duk_get_prop_stridx_boolean(duk_context *ctx, duk_idx_t obj_index, duk_small_int_t stridx, duk_bool_t *out_has_prop) {
+	duk_bool_t rc;
+
+	DUK_ASSERT_CTX_VALID(ctx);
+	DUK_ASSERT_DISABLE(stridx >= 0);
+	DUK_ASSERT(stridx < DUK_HEAP_NUM_STRINGS);
+
+	rc = duk_get_prop_stridx(ctx, obj_index, stridx);
+	if (out_has_prop) {
+		*out_has_prop = rc;
+	}
+	rc = duk_to_boolean(ctx, -1);
+	DUK_ASSERT(rc == 0 || rc == 1);
+	duk_pop(ctx);
+	return rc;
+}
+
+DUK_EXTERNAL duk_bool_t duk_put_prop(duk_context *ctx, duk_idx_t obj_index) {
+	duk_hthread *thr = (duk_hthread *) ctx;
+	duk_tval *tv_obj;
+	duk_tval *tv_key;
+	duk_tval *tv_val;
+	duk_small_int_t throw_flag;
+	duk_bool_t rc;
+
+	DUK_ASSERT_CTX_VALID(ctx);
+
+	/* Note: copying tv_obj and tv_key to locals to shield against a valstack
+	 * resize is not necessary for a property put right now (putprop protects
+	 * against it internally).
+	 */
+
+	tv_obj = duk_require_tval(ctx, obj_index);
+	tv_key = duk_require_tval(ctx, -2);
+	tv_val = duk_require_tval(ctx, -1);
+	throw_flag = duk_is_strict_call(ctx);
+
+	rc = duk_hobject_putprop(thr, tv_obj, tv_key, tv_val, throw_flag);
+	DUK_ASSERT(rc == 0 || rc == 1);
+
+	duk_pop_2(ctx);  /* remove key and value */
+	return rc;  /* 1 if property found, 0 otherwise */
+}
+
+DUK_EXTERNAL duk_bool_t duk_put_prop_string(duk_context *ctx, duk_idx_t obj_index, const char *key) {
+	DUK_ASSERT_CTX_VALID(ctx);
+	DUK_ASSERT(key != NULL);
+
+	obj_index = duk_require_normalize_index(ctx, obj_index);
+	duk_push_string(ctx, key);
+	duk_swap_top(ctx, -2);  /* [val key] -> [key val] */
+	return duk_put_prop(ctx, obj_index);
+}
+
+DUK_EXTERNAL duk_bool_t duk_put_prop_index(duk_context *ctx, duk_idx_t obj_index, duk_uarridx_t arr_index) {
+	DUK_ASSERT_CTX_VALID(ctx);
+
+	obj_index = duk_require_normalize_index(ctx, obj_index);
+	duk_push_uarridx(ctx, arr_index);
+	duk_swap_top(ctx, -2);  /* [val key] -> [key val] */
+	return duk_put_prop(ctx, obj_index);
+}
+
+DUK_INTERNAL duk_bool_t duk_put_prop_stridx(duk_context *ctx, duk_idx_t obj_index, duk_small_int_t stridx) {
+	duk_hthread *thr = (duk_hthread *) ctx;
+
+	DUK_ASSERT_CTX_VALID(ctx);
+	DUK_ASSERT_DISABLE(stridx >= 0);
+	DUK_ASSERT(stridx < DUK_HEAP_NUM_STRINGS);
+
+	obj_index = duk_require_normalize_index(ctx, obj_index);
+	duk_push_hstring(ctx, DUK_HTHREAD_GET_STRING(thr, stridx));
+	duk_swap_top(ctx, -2);  /* [val key] -> [key val] */
+	return duk_put_prop(ctx, obj_index);
+}
+
+DUK_EXTERNAL duk_bool_t duk_del_prop(duk_context *ctx, duk_idx_t obj_index) {
+	duk_hthread *thr = (duk_hthread *) ctx;
+	duk_tval *tv_obj;
+	duk_tval *tv_key;
+	duk_small_int_t throw_flag;
+	duk_bool_t rc;
+
+	DUK_ASSERT_CTX_VALID(ctx);
+
+	/* Note: copying tv_obj and tv_key to locals to shield against a valstack
+	 * resize is not necessary for a property delete right now.
+	 */
+
+	tv_obj = duk_require_tval(ctx, obj_index);
+	tv_key = duk_require_tval(ctx, -1);
+	throw_flag = duk_is_strict_call(ctx);
+
+	rc = duk_hobject_delprop(thr, tv_obj, tv_key, throw_flag);
+	DUK_ASSERT(rc == 0 || rc == 1);
+
+	duk_pop(ctx);  /* remove key */
+	return rc;
+}
+
+DUK_EXTERNAL duk_bool_t duk_del_prop_string(duk_context *ctx, duk_idx_t obj_index, const char *key) {
+	DUK_ASSERT_CTX_VALID(ctx);
+	DUK_ASSERT(key != NULL);
+
+	obj_index = duk_require_normalize_index(ctx, obj_index);
+	duk_push_string(ctx, key);
+	return duk_del_prop(ctx, obj_index);
+}
+
+DUK_EXTERNAL duk_bool_t duk_del_prop_index(duk_context *ctx, duk_idx_t obj_index, duk_uarridx_t arr_index) {
+	DUK_ASSERT_CTX_VALID(ctx);
+
+	obj_index = duk_require_normalize_index(ctx, obj_index);
+	duk_push_uarridx(ctx, arr_index);
+	return duk_del_prop(ctx, obj_index);
+}
+
+DUK_INTERNAL duk_bool_t duk_del_prop_stridx(duk_context *ctx, duk_idx_t obj_index, duk_small_int_t stridx) {
+	duk_hthread *thr = (duk_hthread *) ctx;
+
+	DUK_ASSERT_CTX_VALID(ctx);
+	DUK_ASSERT_DISABLE(stridx >= 0);
+	DUK_ASSERT(stridx < DUK_HEAP_NUM_STRINGS);
+
+	obj_index = duk_require_normalize_index(ctx, obj_index);
+	duk_push_hstring(ctx, DUK_HTHREAD_GET_STRING(thr, stridx));
+	return duk_del_prop(ctx, obj_index);
+}
+
+DUK_EXTERNAL duk_bool_t duk_has_prop(duk_context *ctx, duk_idx_t obj_index) {
+	duk_hthread *thr = (duk_hthread *) ctx;
+	duk_tval *tv_obj;
+	duk_tval *tv_key;
+	duk_bool_t rc;
+
+	DUK_ASSERT_CTX_VALID(ctx);
+
+	/* Note: copying tv_obj and tv_key to locals to shield against a valstack
+	 * resize is not necessary for a property existence check right now.
+	 */
+
+	tv_obj = duk_require_tval(ctx, obj_index);
+	tv_key = duk_require_tval(ctx, -1);
+
+	rc = duk_hobject_hasprop(thr, tv_obj, tv_key);
+	DUK_ASSERT(rc == 0 || rc == 1);
+
+	duk_pop(ctx);  /* remove key */
+	return rc;  /* 1 if property found, 0 otherwise */
+}
+
+DUK_EXTERNAL duk_bool_t duk_has_prop_string(duk_context *ctx, duk_idx_t obj_index, const char *key) {
+	DUK_ASSERT_CTX_VALID(ctx);
+	DUK_ASSERT(key != NULL);
+
+	obj_index = duk_require_normalize_index(ctx, obj_index);
+	duk_push_string(ctx, key);
+	return duk_has_prop(ctx, obj_index);
+}
+
+DUK_EXTERNAL duk_bool_t duk_has_prop_index(duk_context *ctx, duk_idx_t obj_index, duk_uarridx_t arr_index) {
+	DUK_ASSERT_CTX_VALID(ctx);
+
+	obj_index = duk_require_normalize_index(ctx, obj_index);
+	duk_push_uarridx(ctx, arr_index);
+	return duk_has_prop(ctx, obj_index);
+}
+
+DUK_INTERNAL duk_bool_t duk_has_prop_stridx(duk_context *ctx, duk_idx_t obj_index, duk_small_int_t stridx) {
+	duk_hthread *thr = (duk_hthread *) ctx;
+
+	DUK_ASSERT_CTX_VALID(ctx);
+	DUK_ASSERT_DISABLE(stridx >= 0);
+	DUK_ASSERT(stridx < DUK_HEAP_NUM_STRINGS);
+
+	obj_index = duk_require_normalize_index(ctx, obj_index);
+	duk_push_hstring(ctx, DUK_HTHREAD_GET_STRING(thr, stridx));
+	return duk_has_prop(ctx, obj_index);
+}
+
+/* Define own property without inheritance looks and such.  This differs from
+ * [[DefineOwnProperty]] because special behaviors (like Array 'length') are
+ * not invoked by this method.  The caller must be careful to invoke any such
+ * behaviors if necessary.
+ */
+DUK_INTERNAL void duk_xdef_prop(duk_context *ctx, duk_idx_t obj_index, duk_small_uint_t desc_flags) {
+	duk_hthread *thr = (duk_hthread *) ctx;
+	duk_hobject *obj;
+	duk_hstring *key;
+
+	DUK_ASSERT_CTX_VALID(ctx);
+
+	obj = duk_require_hobject(ctx, obj_index);
+	DUK_ASSERT(obj != NULL);
+	key = duk_to_hstring(ctx, -2);
+	DUK_ASSERT(key != NULL);
+	DUK_ASSERT(duk_require_tval(ctx, -1) != NULL);
+
+	duk_hobject_define_property_internal(thr, obj, key, desc_flags);
+
+	duk_pop(ctx);  /* pop key */
+}
+
+DUK_INTERNAL void duk_xdef_prop_index(duk_context *ctx, duk_idx_t obj_index, duk_uarridx_t arr_index, duk_small_uint_t desc_flags) {
+	duk_hthread *thr = (duk_hthread *) ctx;
+	duk_hobject *obj;
+
+	DUK_ASSERT_CTX_VALID(ctx);
+
+	obj = duk_require_hobject(ctx, obj_index);
+	DUK_ASSERT(obj != NULL);
+
+	duk_hobject_define_property_internal_arridx(thr, obj, arr_index, desc_flags);
+	/* value popped by call */
+}
+
+DUK_INTERNAL void duk_xdef_prop_stridx(duk_context *ctx, duk_idx_t obj_index, duk_small_int_t stridx, duk_small_uint_t desc_flags) {
+	duk_hthread *thr = (duk_hthread *) ctx;
+	duk_hobject *obj;
+	duk_hstring *key;
+
+	DUK_ASSERT_CTX_VALID(ctx);
+	DUK_ASSERT_DISABLE(stridx >= 0);
+	DUK_ASSERT(stridx < DUK_HEAP_NUM_STRINGS);
+
+	obj = duk_require_hobject(ctx, obj_index);
+	DUK_ASSERT(obj != NULL);
+	key = DUK_HTHREAD_GET_STRING(thr, stridx);
+	DUK_ASSERT(key != NULL);
+	DUK_ASSERT(duk_require_tval(ctx, -1) != NULL);
+
+	duk_hobject_define_property_internal(thr, obj, key, desc_flags);
+	/* value popped by call */
+}
+
+DUK_INTERNAL void duk_xdef_prop_stridx_builtin(duk_context *ctx, duk_idx_t obj_index, duk_small_int_t stridx, duk_small_int_t builtin_idx, duk_small_uint_t desc_flags) {
+	duk_hthread *thr = (duk_hthread *) ctx;
+	duk_hobject *obj;
+	duk_hstring *key;
+
+	DUK_ASSERT_CTX_VALID(ctx);
+	DUK_ASSERT_DISABLE(stridx >= 0);
+	DUK_ASSERT(stridx < DUK_HEAP_NUM_STRINGS);
+	DUK_ASSERT_DISABLE(builtin_idx >= 0);
+	DUK_ASSERT(builtin_idx < DUK_NUM_BUILTINS);
+
+	obj = duk_require_hobject(ctx, obj_index);
+	DUK_ASSERT(obj != NULL);
+	key = DUK_HTHREAD_GET_STRING(thr, stridx);
+	DUK_ASSERT(key != NULL);
+
+	duk_push_hobject(ctx, thr->builtins[builtin_idx]);
+	duk_hobject_define_property_internal(thr, obj, key, desc_flags);
+	/* value popped by call */
+}
+
+/* This is a rare property helper; it sets the global thrower (E5 Section 13.2.3)
+ * setter/getter into an object property.  This is needed by the 'arguments'
+ * object creation code, function instance creation code, and Function.prototype.bind().
+ */
+
+DUK_INTERNAL void duk_xdef_prop_stridx_thrower(duk_context *ctx, duk_idx_t obj_index, duk_small_int_t stridx, duk_small_uint_t desc_flags) {
+	duk_hthread *thr = (duk_hthread *) ctx;
+	duk_hobject *obj = duk_require_hobject(ctx, obj_index);
+	duk_hobject *thrower = thr->builtins[DUK_BIDX_TYPE_ERROR_THROWER];
+	duk_hobject_define_accessor_internal(thr, obj, DUK_HTHREAD_GET_STRING(thr, stridx), thrower, thrower, desc_flags);
+}
+
+/* Object.defineProperty() equivalent C binding. */
+DUK_EXTERNAL void duk_def_prop(duk_context *ctx, duk_idx_t obj_index, duk_uint_t flags) {
+	duk_hthread *thr = (duk_hthread *) ctx;
+	duk_idx_t idx_base;
+	duk_hobject *obj;
+	duk_hstring *key;
+	duk_idx_t idx_value;
+	duk_hobject *get;
+	duk_hobject *set;
+	duk_uint_t is_data_desc;
+	duk_uint_t is_acc_desc;
+
+	DUK_ASSERT_CTX_VALID(ctx);
+
+	obj = duk_require_hobject(ctx, obj_index);
+
+	is_data_desc = flags & (DUK_DEFPROP_HAVE_VALUE | DUK_DEFPROP_HAVE_WRITABLE);
+	is_acc_desc = flags & (DUK_DEFPROP_HAVE_GETTER | DUK_DEFPROP_HAVE_SETTER);
+	if (is_data_desc && is_acc_desc) {
+		/* "Have" flags must not be conflicting so that they would
+		 * apply to both a plain property and an accessor at the same
+		 * time.
+		 */
+		goto fail_invalid_desc;
+	}
+
+	idx_base = duk_get_top_index(ctx);
+	if (flags & DUK_DEFPROP_HAVE_SETTER) {
+		duk_require_type_mask(ctx, idx_base, DUK_TYPE_MASK_UNDEFINED |
+		                                     DUK_TYPE_MASK_OBJECT |
+		                                     DUK_TYPE_MASK_LIGHTFUNC);
+		set = duk_get_hobject_or_lfunc_coerce(ctx, idx_base);
+		if (set != NULL && !DUK_HOBJECT_IS_CALLABLE(set)) {
+			goto fail_not_callable;
+		}
+		idx_base--;
+	} else {
+		set = NULL;
+	}
+	if (flags & DUK_DEFPROP_HAVE_GETTER) {
+		duk_require_type_mask(ctx, idx_base, DUK_TYPE_MASK_UNDEFINED |
+		                                     DUK_TYPE_MASK_OBJECT |
+		                                     DUK_TYPE_MASK_LIGHTFUNC);
+		get = duk_get_hobject_or_lfunc_coerce(ctx, idx_base);
+		if (get != NULL && !DUK_HOBJECT_IS_CALLABLE(get)) {
+			goto fail_not_callable;
+		}
+		idx_base--;
+	} else {
+		get = NULL;
+	}
+	if (flags & DUK_DEFPROP_HAVE_VALUE) {
+		idx_value = idx_base;
+		idx_base--;
+	} else {
+		idx_value = (duk_idx_t) -1;
+	}
+	key = duk_require_hstring(ctx, idx_base);
+
+	duk_require_valid_index(ctx, idx_base);
+
+	duk_hobject_define_property_helper(ctx,
+	                                   flags /*defprop_flags*/,
+	                                   obj,
+	                                   key,
+	                                   idx_value,
+	                                   get,
+	                                   set);
+
+	/* Clean up stack */
+
+	duk_set_top(ctx, idx_base);
+
+	/* [ ... obj ... ] */
+
+	return;
+
+ fail_invalid_desc:
+	DUK_ERROR(thr, DUK_ERR_TYPE_ERROR, DUK_STR_INVALID_DESCRIPTOR);
+	return;
+
+ fail_not_callable:
+	DUK_ERROR(thr, DUK_ERR_TYPE_ERROR, DUK_STR_NOT_CALLABLE);
+	return;
+}
+
+/*
+ *  Object related
+ *
+ *  Note: seal() and freeze() are accessible through Ecmascript bindings,
+ *  and are not exposed through the API.
+ */
+
+DUK_EXTERNAL void duk_compact(duk_context *ctx, duk_idx_t obj_index) {
+	duk_hthread *thr = (duk_hthread *) ctx;
+	duk_hobject *obj;
+
+	DUK_ASSERT_CTX_VALID(ctx);
+
+	obj = duk_get_hobject(ctx, obj_index);
+	if (obj) {
+		/* Note: this may fail, caller should protect the call if necessary */
+		duk_hobject_compact_props(thr, obj);
+	}
+}
+
+/* XXX: the duk_hobject_enum.c stack APIs should be reworked */
+
+DUK_EXTERNAL void duk_enum(duk_context *ctx, duk_idx_t obj_index, duk_uint_t enum_flags) {
+	DUK_ASSERT_CTX_VALID(ctx);
+
+	duk_dup(ctx, obj_index);
+	duk_require_hobject_or_lfunc_coerce(ctx, -1);
+	duk_hobject_enumerator_create(ctx, enum_flags);   /* [target] -> [enum] */
+}
+
+DUK_EXTERNAL duk_bool_t duk_next(duk_context *ctx, duk_idx_t enum_index, duk_bool_t get_value) {
+	DUK_ASSERT_CTX_VALID(ctx);
+
+	duk_require_hobject(ctx, enum_index);
+	duk_dup(ctx, enum_index);
+	return duk_hobject_enumerator_next(ctx, get_value);
+}
+
+/*
+ *  Helpers for writing multiple properties
+ */
+
+DUK_EXTERNAL void duk_put_function_list(duk_context *ctx, duk_idx_t obj_index, const duk_function_list_entry *funcs) {
+	const duk_function_list_entry *ent = funcs;
+
+	DUK_ASSERT_CTX_VALID(ctx);
+
+	obj_index = duk_require_normalize_index(ctx, obj_index);
+	if (ent != NULL) {
+		while (ent->key != NULL) {
+			duk_push_c_function(ctx, ent->value, ent->nargs);
+			duk_put_prop_string(ctx, obj_index, ent->key);
+			ent++;
+		}
+	}
+}
+
+DUK_EXTERNAL void duk_put_number_list(duk_context *ctx, duk_idx_t obj_index, const duk_number_list_entry *numbers) {
+	const duk_number_list_entry *ent = numbers;
+
+	DUK_ASSERT_CTX_VALID(ctx);
+
+	obj_index = duk_require_normalize_index(ctx, obj_index);
+	if (ent != NULL) {
+		while (ent->key != NULL) {
+			duk_push_number(ctx, ent->value);
+			duk_put_prop_string(ctx, obj_index, ent->key);
+			ent++;
+		}
+	}
+}
+
+/*
+ *  Shortcut for accessing global object properties
+ */
+
+DUK_EXTERNAL duk_bool_t duk_get_global_string(duk_context *ctx, const char *key) {
+	duk_hthread *thr = (duk_hthread *) ctx;
+	duk_bool_t ret;
+
+	DUK_ASSERT_CTX_VALID(ctx);
+	DUK_ASSERT(thr->builtins[DUK_BIDX_GLOBAL] != NULL);
+
+	/* XXX: direct implementation */
+
+	duk_push_hobject(ctx, thr->builtins[DUK_BIDX_GLOBAL]);
+	ret = duk_get_prop_string(ctx, -1, key);
+	duk_remove(ctx, -2);
+	return ret;
+}
+
+DUK_EXTERNAL duk_bool_t duk_put_global_string(duk_context *ctx, const char *key) {
+	duk_hthread *thr = (duk_hthread *) ctx;
+	duk_bool_t ret;
+
+	DUK_ASSERT_CTX_VALID(ctx);
+	DUK_ASSERT(thr->builtins[DUK_BIDX_GLOBAL] != NULL);
+
+	/* XXX: direct implementation */
+
+	duk_push_hobject(ctx, thr->builtins[DUK_BIDX_GLOBAL]);
+	duk_insert(ctx, -2);
+	ret = duk_put_prop_string(ctx, -2, key);  /* [ ... global val ] -> [ ... global ] */
+	duk_pop(ctx);
+	return ret;
+}
+
+/*
+ *  Object prototype
+ */
+
+DUK_EXTERNAL void duk_get_prototype(duk_context *ctx, duk_idx_t index) {
+	duk_hthread *thr = (duk_hthread *) ctx;
+	duk_hobject *obj;
+	duk_hobject *proto;
+
+	DUK_ASSERT_CTX_VALID(ctx);
+	DUK_UNREF(thr);
+
+	obj = duk_require_hobject(ctx, index);
+	DUK_ASSERT(obj != NULL);
+
+	/* XXX: shared helper for duk_push_hobject_or_undefined()? */
+	proto = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, obj);
+	if (proto) {
+		duk_push_hobject(ctx, proto);
+	} else {
+		duk_push_undefined(ctx);
+	}
+}
+
+DUK_EXTERNAL void duk_set_prototype(duk_context *ctx, duk_idx_t index) {
+	duk_hthread *thr = (duk_hthread *) ctx;
+	duk_hobject *obj;
+	duk_hobject *proto;
+
+	DUK_ASSERT_CTX_VALID(ctx);
+
+	obj = duk_require_hobject(ctx, index);
+	DUK_ASSERT(obj != NULL);
+	duk_require_type_mask(ctx, -1, DUK_TYPE_MASK_UNDEFINED |
+	                               DUK_TYPE_MASK_OBJECT);
+	proto = duk_get_hobject(ctx, -1);
+	/* proto can also be NULL here (allowed explicitly) */
+
+	DUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr, obj, proto);
+
+	duk_pop(ctx);
+}
+
+/*
+ *  Object finalizer
+ */
+
+/* XXX: these could be implemented as macros calling an internal function
+ * directly.
+ * XXX: same issue as with Duktape.fin: there's no way to delete the property
+ * now (just set it to undefined).
+ */
+DUK_EXTERNAL void duk_get_finalizer(duk_context *ctx, duk_idx_t index) {
+	DUK_ASSERT_CTX_VALID(ctx);
+
+	duk_get_prop_stridx(ctx, index, DUK_STRIDX_INT_FINALIZER);
+}
+
+DUK_EXTERNAL void duk_set_finalizer(duk_context *ctx, duk_idx_t index) {
+	DUK_ASSERT_CTX_VALID(ctx);
+
+	duk_put_prop_stridx(ctx, index, DUK_STRIDX_INT_FINALIZER);
+}
+#line 1 "duk_api_stack.c"
+/*
+ *  API calls related to general value stack manipulation: resizing the value
+ *  stack, pushing and popping values, type checking and reading values,
+ *  coercing values, etc.
+ *
+ *  Also contains internal functions (such as duk_get_tval()), defined
+ *  in duk_api_internal.h, with semantics similar to the public API.
+ */
+
+/* XXX: repetition of stack pre-checks -> helper or macro or inline */
+/* XXX: shared api error strings, and perhaps even throw code for rare cases? */
+
+/* include removed: duk_internal.h */
+
+/*
+ *  Forward declarations
+ */
+
+DUK_LOCAL_DECL duk_idx_t duk__push_c_function_raw(duk_context *ctx, duk_c_function func, duk_idx_t nargs, duk_uint_t flags);
+
+/*
+ *  Global state for working around missing variadic macros
+ */
+
+#ifndef DUK_USE_VARIADIC_MACROS
+DUK_EXTERNAL const char *duk_api_global_filename = NULL;
+DUK_EXTERNAL duk_int_t duk_api_global_line = 0;
+#endif
+
+/*
+ *  Misc helpers
+ */
+
+/* Check that there's room to push one value. */
+#if defined(DUK_USE_VALSTACK_UNSAFE)
+/* Faster but value stack overruns are memory unsafe. */
+#define DUK__CHECK_SPACE() do { \
+		DUK_ASSERT(!(thr->valstack_top >= thr->valstack_end)); \
+	} while (0)
+#else
+#define DUK__CHECK_SPACE() do { \
+		if (DUK_UNLIKELY(thr->valstack_top >= thr->valstack_end)) { \
+			DUK_ERROR_API(thr, DUK_STR_PUSH_BEYOND_ALLOC_STACK); \
+		} \
+	} while (0)
+#endif
+
+DUK_LOCAL_DECL duk_heaphdr *duk__get_tagged_heaphdr_raw(duk_context *ctx, duk_idx_t index, duk_uint_t tag);
+
+DUK_LOCAL duk_int_t duk__api_coerce_d2i(duk_context *ctx, duk_idx_t index, duk_bool_t require) {
+	duk_hthread *thr;
+	duk_tval *tv;
+	duk_small_int_t c;
+	duk_double_t d;
+
+	thr = (duk_hthread *) ctx;
+
+	tv = duk_get_tval(ctx, index);
+	if (tv == NULL) {
+		goto error_notnumber;
+	}
+
+	/*
+	 *  Special cases like NaN and +/- Infinity are handled explicitly
+	 *  because a plain C coercion from double to int handles these cases
+	 *  in undesirable ways.  For instance, NaN may coerce to INT_MIN
+	 *  (not zero), and INT_MAX + 1 may coerce to INT_MIN (not INT_MAX).
+	 *
+	 *  This double-to-int coercion differs from ToInteger() because it
+	 *  has a finite range (ToInteger() allows e.g. +/- Infinity).  It
+	 *  also differs from ToInt32() because the INT_MIN/INT_MAX clamping
+	 *  depends on the size of the int type on the platform.  In particular,
+	 *  on platforms with a 64-bit int type, the full range is allowed.
+	 */
+
+#if defined(DUK_USE_FASTINT)
+	if (DUK_TVAL_IS_FASTINT(tv)) {
+		duk_int64_t t = DUK_TVAL_GET_FASTINT(tv);
+#if (DUK_INT_MAX <= 0x7fffffffL)
+		/* Clamping only necessary for 32-bit ints. */
+		if (t < DUK_INT_MIN) {
+			t = DUK_INT_MIN;
+		} else if (t > DUK_INT_MAX) {
+			t = DUK_INT_MAX;
+		}
+#endif
+		return (duk_int_t) t;
+	}
+#endif
+
+	if (DUK_TVAL_IS_NUMBER(tv)) {
+		d = DUK_TVAL_GET_NUMBER(tv);
+		c = (duk_small_int_t) DUK_FPCLASSIFY(d);
+		if (c == DUK_FP_NAN) {
+			return 0;
+		} else if (d < (duk_double_t) DUK_INT_MIN) {
+			/* covers -Infinity */
+			return DUK_INT_MIN;
+		} else if (d > (duk_double_t) DUK_INT_MAX) {
+			/* covers +Infinity */
+			return DUK_INT_MAX;
+		} else {
+			/* coerce towards zero */
+			return (duk_int_t) d;
+		}
+	}
+
+ error_notnumber:
+
+	if (require) {
+		DUK_ERROR_REQUIRE_TYPE_INDEX(thr, index, "number", DUK_STR_NOT_NUMBER);
+		/* not reachable */
+	}
+	return 0;
+}
+
+DUK_LOCAL duk_uint_t duk__api_coerce_d2ui(duk_context *ctx, duk_idx_t index, duk_bool_t require) {
+	duk_hthread *thr;
+	duk_tval *tv;
+	duk_small_int_t c;
+	duk_double_t d;
+
+	/* Same as above but for unsigned int range. */
+
+	thr = (duk_hthread *) ctx;
+
+	tv = duk_get_tval(ctx, index);
+	if (tv == NULL) {
+		goto error_notnumber;
+	}
+
+#if defined(DUK_USE_FASTINT)
+	if (DUK_TVAL_IS_FASTINT(tv)) {
+		duk_int64_t t = DUK_TVAL_GET_FASTINT(tv);
+		if (t < 0) {
+			t = 0;
+		}
+#if (DUK_UINT_MAX <= 0xffffffffUL)
+		/* Clamping only necessary for 32-bit ints. */
+		else if (t > DUK_UINT_MAX) {
+			t = DUK_UINT_MAX;
+		}
+#endif
+		return (duk_uint_t) t;
+	}
+#endif
+
+	if (DUK_TVAL_IS_NUMBER(tv)) {
+		d = DUK_TVAL_GET_NUMBER(tv);
+		c = (duk_small_int_t) DUK_FPCLASSIFY(d);
+		if (c == DUK_FP_NAN) {
+			return 0;
+		} else if (d < 0.0) {
+			/* covers -Infinity */
+			return (duk_uint_t) 0;
+		} else if (d > (duk_double_t) DUK_UINT_MAX) {
+			/* covers +Infinity */
+			return (duk_uint_t) DUK_UINT_MAX;
+		} else {
+			/* coerce towards zero */
+			return (duk_uint_t) d;
+		}
+	}
+
+ error_notnumber:
+
+	if (require) {
+		DUK_ERROR_REQUIRE_TYPE_INDEX(thr, index, "number", DUK_STR_NOT_NUMBER);
+		/* not reachable */
+	}
+	return 0;
+}
+
+/*
+ *  Stack index validation/normalization and getting a stack duk_tval ptr.
+ *
+ *  These are called by many API entrypoints so the implementations must be
+ *  fast and "inlined".
+ *
+ *  There's some repetition because of this; keep the functions in sync.
+ */
+
+DUK_EXTERNAL duk_idx_t duk_normalize_index(duk_context *ctx, duk_idx_t index) {
+	duk_hthread *thr = (duk_hthread *) ctx;
+	duk_uidx_t vs_size;
+	duk_uidx_t uindex;
+
+	DUK_ASSERT_CTX_VALID(ctx);
+	DUK_ASSERT(DUK_INVALID_INDEX < 0);
+
+	/* Care must be taken to avoid pointer wrapping in the index
+	 * validation.  For instance, on a 32-bit platform with 8-byte
+	 * duk_tval the index 0x20000000UL would wrap the memory space
+	 * once.
+	 */
+
+	/* Assume value stack sizes (in elements) fits into duk_idx_t. */
+	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
+	vs_size = (duk_uidx_t) (thr->valstack_top - thr->valstack_bottom);
+	DUK_ASSERT_DISABLE(vs_size >= 0);  /* unsigned */
+
+	if (index < 0) {
+		uindex = vs_size + (duk_uidx_t) index;
+	} else {
+		/* since index non-negative */
+		DUK_ASSERT(index != DUK_INVALID_INDEX);
+		uindex = (duk_uidx_t) index;
+	}
+
+	/* DUK_INVALID_INDEX won't be accepted as a valid index. */
+	DUK_ASSERT(vs_size + (duk_uidx_t) DUK_INVALID_INDEX >= vs_size);
+
+	if (DUK_LIKELY(uindex < vs_size)) {
+		return (duk_idx_t) uindex;
+	}
+	return DUK_INVALID_INDEX;
+}
+
+DUK_EXTERNAL duk_idx_t duk_require_normalize_index(duk_context *ctx, duk_idx_t index) {
+	duk_hthread *thr = (duk_hthread *) ctx;
+	duk_uidx_t vs_size;
+	duk_uidx_t uindex;
+
+	DUK_ASSERT_CTX_VALID(ctx);
+	DUK_ASSERT(DUK_INVALID_INDEX < 0);
+
+	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
+	vs_size = (duk_uidx_t) (thr->valstack_top - thr->valstack_bottom);
+	DUK_ASSERT_DISABLE(vs_size >= 0);  /* unsigned */
+
+	if (index < 0) {
+		uindex = vs_size + (duk_uidx_t) index;
+	} else {
+		DUK_ASSERT(index != DUK_INVALID_INDEX);
+		uindex = (duk_uidx_t) index;
+	}
+
+	/* DUK_INVALID_INDEX won't be accepted as a valid index. */
+	DUK_ASSERT(vs_size + (duk_uidx_t) DUK_INVALID_INDEX >= vs_size);
+
+	if (DUK_LIKELY(uindex < vs_size)) {
+		return (duk_idx_t) uindex;
+	}
+	DUK_ERROR_API_INDEX(thr, index);
+	return 0;  /* unreachable */
+}
+
+DUK_INTERNAL duk_tval *duk_get_tval(duk_context *ctx, duk_idx_t index) {
+	duk_hthread *thr = (duk_hthread *) ctx;
+	duk_uidx_t vs_size;
+	duk_uidx_t uindex;
+
+	DUK_ASSERT_CTX_VALID(ctx);
+	DUK_ASSERT(DUK_INVALID_INDEX < 0);
+
+	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
+	vs_size = (duk_uidx_t) (thr->valstack_top - thr->valstack_bottom);
+	DUK_ASSERT_DISABLE(vs_size >= 0);  /* unsigned */
+
+	if (index < 0) {
+		uindex = vs_size + (duk_uidx_t) index;
+	} else {
+		DUK_ASSERT(index != DUK_INVALID_INDEX);
+		uindex = (duk_uidx_t) index;
+	}
+
+	/* DUK_INVALID_INDEX won't be accepted as a valid index. */
+	DUK_ASSERT(vs_size + (duk_uidx_t) DUK_INVALID_INDEX >= vs_size);
+
+	if (DUK_LIKELY(uindex < vs_size)) {
+		return thr->valstack_bottom + uindex;
+	}
+	return NULL;
+}
+
+DUK_INTERNAL duk_tval *duk_require_tval(duk_context *ctx, duk_idx_t index) {
+	duk_hthread *thr = (duk_hthread *) ctx;
+	duk_uidx_t vs_size;
+	duk_uidx_t uindex;
+
+	DUK_ASSERT_CTX_VALID(ctx);
+	DUK_ASSERT(DUK_INVALID_INDEX < 0);
+
+	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
+	vs_size = (duk_uidx_t) (thr->valstack_top - thr->valstack_bottom);
+	DUK_ASSERT_DISABLE(vs_size >= 0);  /* unsigned */
+
+	/* Use unsigned arithmetic to optimize comparison. */
+	if (index < 0) {
+		uindex = vs_size + (duk_uidx_t) index;
+	} else {
+		DUK_ASSERT(index != DUK_INVALID_INDEX);
+		uindex = (duk_uidx_t) index;
+	}
+
+	/* DUK_INVALID_INDEX won't be accepted as a valid index. */
+	DUK_ASSERT(vs_size + (duk_uidx_t) DUK_INVALID_INDEX >= vs_size);
+
+	if (DUK_LIKELY(uindex < vs_size)) {
+		return thr->valstack_bottom + uindex;
+	}
+	DUK_ERROR_API_INDEX(thr, index);
+	return NULL;
+}
+
+/* Non-critical. */
+DUK_EXTERNAL duk_bool_t duk_is_valid_index(duk_context *ctx, duk_idx_t index) {
+	DUK_ASSERT_CTX_VALID(ctx);
+	DUK_ASSERT(DUK_INVALID_INDEX < 0);
+
+	return (duk_normalize_index(ctx, index) >= 0);
+}
+
+/* Non-critical. */
+DUK_EXTERNAL void duk_require_valid_index(duk_context *ctx, duk_idx_t index) {
+	duk_hthread *thr = (duk_hthread *) ctx;
+
+	DUK_ASSERT_CTX_VALID(ctx);
+	DUK_ASSERT(DUK_INVALID_INDEX < 0);
+
+	if (duk_normalize_index(ctx, index) < 0) {
+		DUK_ERROR_API_INDEX(thr, index);
+		return;  /* unreachable */
+	}
+}
+
+/*
+ *  Value stack top handling
+ */
+
+DUK_EXTERNAL duk_idx_t duk_get_top(duk_context *ctx) {
+	duk_hthread *thr = (duk_hthread *) ctx;
+
+	DUK_ASSERT_CTX_VALID(ctx);
+
+	return (duk_idx_t) (thr->valstack_top - thr->valstack_bottom);
+}
+
+/* Set stack top within currently allocated range, but don't reallocate.
+ * This is performance critical especially for call handling, so whenever
+ * changing, profile and look at generated code.
+ */
+DUK_EXTERNAL void duk_set_top(duk_context *ctx, duk_idx_t index) {
+	duk_hthread *thr = (duk_hthread *) ctx;
+	duk_uidx_t vs_size;
+	duk_uidx_t vs_limit;
+	duk_uidx_t uindex;
+	duk_tval *tv;
+
+	DUK_ASSERT_CTX_VALID(ctx);
+	DUK_ASSERT(DUK_INVALID_INDEX < 0);
+
+	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
+	DUK_ASSERT(thr->valstack_end >= thr->valstack_bottom);
+	vs_size = (duk_uidx_t) (thr->valstack_top - thr->valstack_bottom);
+	vs_limit = (duk_uidx_t) (thr->valstack_end - thr->valstack_bottom);
+
+	if (index < 0) {
+		/* Negative indices are always within allocated stack but
+		 * must not go below zero index.
+		 */
+		uindex = vs_size + (duk_uidx_t) index;
+	} else {
+		/* Positive index can be higher than valstack top but must
+		 * not go above allocated stack (equality is OK).
+		 */
+		uindex = (duk_uidx_t) index;
+	}
+
+	/* DUK_INVALID_INDEX won't be accepted as a valid index. */
+	DUK_ASSERT(vs_size + (duk_uidx_t) DUK_INVALID_INDEX >= vs_size);
+	DUK_ASSERT(vs_size + (duk_uidx_t) DUK_INVALID_INDEX >= vs_limit);
+
+#if defined(DUK_USE_VALSTACK_UNSAFE)
+	DUK_ASSERT(uindex <= vs_limit);
+	DUK_UNREF(vs_limit);
+#else
+	if (DUK_UNLIKELY(uindex > vs_limit)) {
+		DUK_ERROR_API_INDEX(thr, index);
+		return;  /* unreachable */
+	}
+#endif
+	DUK_ASSERT(uindex <= vs_limit);
+
+	/* Handle change in value stack top.  Respect value stack
+	 * initialization policy: 'undefined' above top.  Note that
+	 * DECREF may cause a side effect that reallocates valstack,
+	 * so must relookup after DECREF.
+	 */
+
+	if (uindex >= vs_size) {
+		/* Stack size increases or stays the same. */
+#if defined(DUK_USE_ASSERTIONS)
+		duk_uidx_t count;
+
+		count = uindex - vs_size;
+		while (count != 0) {
+			count--;
+			tv = thr->valstack_top + count;
+			DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(tv));
+		}
+#endif
+		thr->valstack_top = thr->valstack_bottom + uindex;
+	} else {
+		/* Stack size decreases. */
+#if defined(DUK_USE_REFERENCE_COUNTING)
+		duk_uidx_t count;
+
+		count = vs_size - uindex;
+		DUK_ASSERT(count > 0);
+		while (count > 0) {
+			count--;
+			tv = --thr->valstack_top;  /* tv -> value just before prev top value; must relookup */
+			DUK_ASSERT(tv >= thr->valstack_bottom);
+			DUK_TVAL_SET_UNDEFINED_UPDREF(thr, tv);  /* side effects */
+		}
+#else  /* DUK_USE_REFERENCE_COUNTING */
+		duk_uidx_t count;
+		duk_tval *tv_end;
+
+		count = vs_size - uindex;
+		tv = thr->valstack_top;
+		tv_end = tv - count;
+		DUK_ASSERT(tv > tv_end);
+		do {
+			tv--;
+			DUK_TVAL_SET_UNDEFINED(tv);
+		} while (tv != tv_end);
+		thr->valstack_top = tv_end;
+#endif  /* DUK_USE_REFERENCE_COUNTING */
+	}
+}
+
+DUK_EXTERNAL duk_idx_t duk_get_top_index(duk_context *ctx) {
+	duk_hthread *thr = (duk_hthread *) ctx;
+	duk_idx_t ret;
+
+	DUK_ASSERT_CTX_VALID(ctx);
+
+	ret = ((duk_idx_t) (thr->valstack_top - thr->valstack_bottom)) - 1;
+	if (DUK_UNLIKELY(ret < 0)) {
+		/* Return invalid index; if caller uses this without checking
+		 * in another API call, the index won't map to a valid stack
+		 * entry.
+		 */
+		return DUK_INVALID_INDEX;
+	}
+	return ret;
+}
+
+DUK_EXTERNAL duk_idx_t duk_require_top_index(duk_context *ctx) {
+	duk_hthread *thr = (duk_hthread *) ctx;
+	duk_idx_t ret;
+
+	DUK_ASSERT_CTX_VALID(ctx);
+
+	ret = ((duk_idx_t) (thr->valstack_top - thr->valstack_bottom)) - 1;
+	if (DUK_UNLIKELY(ret < 0)) {
+		DUK_ERROR_API_INDEX(thr, -1);
+		return 0;  /* unreachable */
+	}
+	return ret;
+}
+
+/*
+ *  Value stack resizing.
+ *
+ *  This resizing happens above the current "top": the value stack can be
+ *  grown or shrunk, but the "top" is not affected.  The value stack cannot
+ *  be resized to a size below the current "top".
+ *
+ *  The low level reallocation primitive must carefully recompute all value
+ *  stack pointers, and must also work if ALL pointers are NULL.  The resize
+ *  is quite tricky because the valstack realloc may cause a mark-and-sweep,
+ *  which may run finalizers.  Running finalizers may resize the valstack
+ *  recursively (the same value stack we're working on).  So, after realloc
+ *  returns, we know that the valstack "top" should still be the same (there
+ *  should not be live values above the "top"), but its underlying size and
+ *  pointer may have changed.
+ */
+
+/* XXX: perhaps refactor this to allow caller to specify some parameters, or
+ * at least a 'compact' flag which skips any spare or round-up .. useful for
+ * emergency gc.
+ */
+
+DUK_LOCAL duk_bool_t duk__resize_valstack(duk_context *ctx, duk_size_t new_size) {
+	duk_hthread *thr = (duk_hthread *) ctx;
+	duk_ptrdiff_t old_bottom_offset;
+	duk_ptrdiff_t old_top_offset;
+	duk_ptrdiff_t old_end_offset_post;
+#ifdef DUK_USE_DEBUG
+	duk_ptrdiff_t old_end_offset_pre;
+	duk_tval *old_valstack_pre;
+	duk_tval *old_valstack_post;
+#endif
+	duk_tval *new_valstack;
+	duk_size_t new_alloc_size;
+	duk_tval *p;
+
+	DUK_ASSERT_CTX_VALID(ctx);
+	DUK_ASSERT(thr != NULL);
+	DUK_ASSERT(thr->valstack_bottom >= thr->valstack);
+	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
+	DUK_ASSERT(thr->valstack_end >= thr->valstack_top);
+	DUK_ASSERT((duk_size_t) (thr->valstack_top - thr->valstack) <= new_size);  /* can't resize below 'top' */
+	DUK_ASSERT(new_size <= thr->valstack_max);  /* valstack limit caller has check, prevents wrapping */
+	DUK_ASSERT(new_size <= DUK_SIZE_MAX / sizeof(duk_tval));  /* specific assert for wrapping */
+
+	/* get pointer offsets for tweaking below */
+	old_bottom_offset = (((duk_uint8_t *) thr->valstack_bottom) - ((duk_uint8_t *) thr->valstack));
+	old_top_offset = (((duk_uint8_t *) thr->valstack_top) - ((duk_uint8_t *) thr->valstack));
+#ifdef DUK_USE_DEBUG
+	old_end_offset_pre = (((duk_uint8_t *) thr->valstack_end) - ((duk_uint8_t *) thr->valstack));  /* not very useful, used for debugging */
+	old_valstack_pre = thr->valstack;
+#endif
 
 	/* Allocate a new valstack.
 	 *
 	 * Note: cannot use a plain DUK_REALLOC() because a mark-and-sweep may
 	 * invalidate the original thr->valstack base pointer inside the realloc
-	 * process.  See doc/memory-management.txt.
+	 * process.  See doc/memory-management.rst.
 	 */
 
-	new_alloc_size = sizeof(duk_tval) * new_size;  /* FIXME: wrap check */
+	new_alloc_size = sizeof(duk_tval) * new_size;
 	new_valstack = (duk_tval *) DUK_REALLOC_INDIRECT(thr->heap, duk_hthread_get_valstack_ptr, (void *) thr, new_alloc_size);
 	if (!new_valstack) {
+		/* Because new_size != 0, if condition doesn't need to be
+		 * (new_valstack != NULL || new_size == 0).
+		 */
+		DUK_ASSERT(new_size != 0);
 		DUK_D(DUK_DPRINT("failed to resize valstack to %lu entries (%lu bytes)",
 		                 (unsigned long) new_size, (unsigned long) new_alloc_size));
 		return 0;
@@ -9088,7 +18725,7 @@ static duk_bool_t duk__resize_valstack(duk_context *ctx, duk_size_t new_size) {
 	 *     because mark-and-sweep must adhere to a strict stack policy.
 	 *     In other words, logical bottom and top MUST NOT have changed.
 	 *   - All values above the top are unreachable but are initialized
-	 *     to UNDEFINED_UNUSED, up to the post-realloc valstack_end.
+	 *     to UNDEFINED, up to the post-realloc valstack_end.
 	 *   - 'old_end_offset' must be computed after realloc to be correct.
 	 */
 
@@ -9102,8 +18739,11 @@ static duk_bool_t duk__resize_valstack(duk_context *ctx, duk_size_t new_size) {
 #endif
 	thr->valstack = new_valstack;
 	thr->valstack_end = new_valstack + new_size;
-	thr->valstack_bottom = (duk_tval *) ((duk_uint8_t *) new_valstack + old_bottom_offset);
-	thr->valstack_top = (duk_tval *) ((duk_uint8_t *) new_valstack + old_top_offset);
+#if !defined(DUK_USE_PREFER_SIZE)
+	thr->valstack_size = new_size;
+#endif
+	thr->valstack_bottom = (duk_tval *) (void *) ((duk_uint8_t *) new_valstack + old_bottom_offset);
+	thr->valstack_top = (duk_tval *) (void *) ((duk_uint8_t *) new_valstack + old_top_offset);
 
 	DUK_ASSERT(thr->valstack_bottom >= thr->valstack);
 	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
@@ -9132,51 +18772,58 @@ static duk_bool_t duk__resize_valstack(duk_context *ctx, duk_size_t new_size) {
 	                   (void *) thr->valstack, (void *) thr->valstack_end,
 	                   (void *) thr->valstack_bottom, (void *) thr->valstack_top));
 
-	/* init newly allocated slots (only) */
-	p = (duk_tval *) ((duk_uint8_t *) thr->valstack + old_end_offset_post);
+	/* Init newly allocated slots (only). */
+	p = (duk_tval *) (void *) ((duk_uint8_t *) thr->valstack + old_end_offset_post);
 	while (p < thr->valstack_end) {
-		/* never executed if new size is smaller */
-		DUK_TVAL_SET_UNDEFINED_UNUSED(p);
+		/* Never executed if new size is smaller. */
+		DUK_TVAL_SET_UNDEFINED(p);
 		p++;
 	}
 
-	/* assertion check: we maintain elements above top in known state */
-#ifdef DUK_USE_ASSERTIONS
+	/* Assert for value stack initialization policy. */
+#if defined(DUK_USE_ASSERTIONS)
 	p = thr->valstack_top;
 	while (p < thr->valstack_end) {
-		/* everything above old valstack top should be preinitialized now */
-		DUK_ASSERT(DUK_TVAL_IS_UNDEFINED_UNUSED(p));
+		DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(p));
 		p++;
 	}
 #endif
+
 	return 1;
 }
 
-static duk_bool_t duk__check_valstack_resize_helper(duk_context *ctx,
-                                                    duk_size_t min_new_size,
-                                                    duk_bool_t shrink_flag,
-                                                    duk_bool_t compact_flag,
-                                                    duk_bool_t throw_flag) {
+DUK_INTERNAL
+duk_bool_t duk_valstack_resize_raw(duk_context *ctx,
+                                   duk_size_t min_new_size,
+                                   duk_small_uint_t flags) {
 	duk_hthread *thr = (duk_hthread *) ctx;
 	duk_size_t old_size;
 	duk_size_t new_size;
 	duk_bool_t is_shrink = 0;
+	duk_small_uint_t shrink_flag = (flags & DUK_VSRESIZE_FLAG_SHRINK);
+	duk_small_uint_t compact_flag = (flags & DUK_VSRESIZE_FLAG_COMPACT);
+	duk_small_uint_t throw_flag = (flags & DUK_VSRESIZE_FLAG_THROW);
 
 	DUK_DDD(DUK_DDDPRINT("check valstack resize: min_new_size=%lu, curr_size=%ld, curr_top=%ld, "
-	                     "curr_bottom=%ld, shrink=%ld, compact=%ld, throw=%ld",
+	                     "curr_bottom=%ld, shrink=%d, compact=%d, throw=%d",
 	                     (unsigned long) min_new_size,
 	                     (long) (thr->valstack_end - thr->valstack),
 	                     (long) (thr->valstack_top - thr->valstack),
 	                     (long) (thr->valstack_bottom - thr->valstack),
-	                     (long) shrink_flag, (long) compact_flag, (long) throw_flag));
+	                     (int) shrink_flag, (int) compact_flag, (int) throw_flag));
 
-	DUK_ASSERT(ctx != NULL);
+	DUK_ASSERT_CTX_VALID(ctx);
 	DUK_ASSERT(thr != NULL);
 	DUK_ASSERT(thr->valstack_bottom >= thr->valstack);
 	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
 	DUK_ASSERT(thr->valstack_end >= thr->valstack_top);
 
+#if defined(DUK_USE_PREFER_SIZE)
 	old_size = (duk_size_t) (thr->valstack_end - thr->valstack);
+#else
+	DUK_ASSERT((duk_size_t) (thr->valstack_end - thr->valstack) == thr->valstack_size);
+	old_size = thr->valstack_size;
+#endif
 
 	if (min_new_size <= old_size) {
 		is_shrink = 1;
@@ -9203,9 +18850,9 @@ static duk_bool_t duk__check_valstack_resize_helper(duk_context *ctx,
 	                   (unsigned long) old_size, (unsigned long) new_size,
 	                   (unsigned long) min_new_size));
 
-	if (new_size >= thr->valstack_max) {
+	if (new_size > thr->valstack_max) {
 		/* Note: may be triggered even if minimal new_size would not reach the limit,
-		 * plan limit accordingly (taking DUK_VALSTACK_GROW_STEP into account.
+		 * plan limit accordingly (taking DUK_VALSTACK_GROW_STEP into account).
 		 */
 		if (throw_flag) {
 			DUK_ERROR(thr, DUK_ERR_RANGE_ERROR, DUK_STR_VALSTACK_LIMIT);
@@ -9219,9 +18866,11 @@ static duk_bool_t duk__check_valstack_resize_helper(duk_context *ctx,
 	 *  the allocation of the new valstack.  If the mark-and-sweep needs
 	 *  to use our thread for something, it may cause *the same valstack*
 	 *  to be resized recursively.  This happens e.g. when mark-and-sweep
-	 *  finalizers are called.
+	 *  finalizers are called.  This is taken into account carefully in
+	 *  duk__resize_valstack().
 	 *
-	 *  This is taken into account carefully in duk__resize_valstack().
+	 *  'new_size' is known to be <= valstack_max, which ensures that
+	 *  size_t and pointer arithmetic won't wrap in duk__resize_valstack().
 	 */
 
 	if (!duk__resize_valstack(ctx, new_size)) {
@@ -9233,7 +18882,7 @@ static duk_bool_t duk__check_valstack_resize_helper(duk_context *ctx,
 		DUK_DD(DUK_DDPRINT("valstack resize failed"));
 
 		if (throw_flag) {
-			DUK_ERROR(thr, DUK_ERR_ALLOC_ERROR, "failed to extend valstack");
+			DUK_ERROR(thr, DUK_ERR_ALLOC_ERROR, DUK_STR_FAILED_TO_EXTEND_VALSTACK);
 		} else {
 			return 0;
 		}
@@ -9243,29 +18892,11 @@ static duk_bool_t duk__check_valstack_resize_helper(duk_context *ctx,
 	return 1;
 }
 
-#if 0  /* XXX: unused */
-duk_bool_t duk_check_valstack_resize(duk_context *ctx, duk_size_t min_new_size, duk_bool_t allow_shrink) {
-	return duk__check_valstack_resize_helper(ctx,
-	                                         min_new_size,  /* min_new_size */
-	                                         allow_shrink,  /* shrink_flag */
-	                                         0,             /* compact flag */
-	                                         0);            /* throw flag */
-}
-#endif
-
-void duk_require_valstack_resize(duk_context *ctx, duk_size_t min_new_size, duk_bool_t allow_shrink) {
-	(void) duk__check_valstack_resize_helper(ctx,
-	                                         min_new_size,  /* min_new_size */
-	                                         allow_shrink,  /* shrink_flag */
-	                                         0,             /* compact flag */
-	                                         1);            /* throw flag */
-}
-
-duk_bool_t duk_check_stack(duk_context *ctx, duk_idx_t extra) {
+DUK_EXTERNAL duk_bool_t duk_check_stack(duk_context *ctx, duk_idx_t extra) {
 	duk_hthread *thr = (duk_hthread *) ctx;
 	duk_size_t min_new_size;
 
-	DUK_ASSERT(ctx != NULL);
+	DUK_ASSERT_CTX_VALID(ctx);
 	DUK_ASSERT(thr != NULL);
 
 	if (DUK_UNLIKELY(extra < 0)) {
@@ -9276,18 +18907,18 @@ duk_bool_t duk_check_stack(duk_context *ctx, duk_idx_t extra) {
 	}
 
 	min_new_size = (thr->valstack_top - thr->valstack) + extra + DUK_VALSTACK_INTERNAL_EXTRA;
-	return duk__check_valstack_resize_helper(ctx,
-	                                         min_new_size,  /* min_new_size */
-	                                         0,             /* shrink_flag */
-	                                         0,             /* compact flag */
-	                                         0);            /* throw flag */
+	return duk_valstack_resize_raw(ctx,
+	                               min_new_size,         /* min_new_size */
+	                               0 /* no shrink */ |   /* flags */
+	                               0 /* no compact */ |
+	                               0 /* no throw */);
 }
 
-void duk_require_stack(duk_context *ctx, duk_idx_t extra) {
+DUK_EXTERNAL void duk_require_stack(duk_context *ctx, duk_idx_t extra) {
 	duk_hthread *thr = (duk_hthread *) ctx;
 	duk_size_t min_new_size;
 
-	DUK_ASSERT(ctx != NULL);
+	DUK_ASSERT_CTX_VALID(ctx);
 	DUK_ASSERT(thr != NULL);
 
 	if (DUK_UNLIKELY(extra < 0)) {
@@ -9298,17 +18929,17 @@ void duk_require_stack(duk_context *ctx, duk_idx_t extra) {
 	}
 
 	min_new_size = (thr->valstack_top - thr->valstack) + extra + DUK_VALSTACK_INTERNAL_EXTRA;
-	(void) duk__check_valstack_resize_helper(ctx,
-	                                         min_new_size,  /* min_new_size */
-	                                         0,             /* shrink_flag */
-	                                         0,             /* compact flag */
-	                                         1);            /* throw flag */
+	(void) duk_valstack_resize_raw(ctx,
+	                               min_new_size,  /* min_new_size */
+	                               0 /* no shrink */ |   /* flags */
+	                               0 /* no compact */ |
+	                               DUK_VSRESIZE_FLAG_THROW);
 }
 
-duk_bool_t duk_check_stack_top(duk_context *ctx, duk_idx_t top) {
+DUK_EXTERNAL duk_bool_t duk_check_stack_top(duk_context *ctx, duk_idx_t top) {
 	duk_size_t min_new_size;
 
-	DUK_ASSERT(ctx != NULL);
+	DUK_ASSERT_CTX_VALID(ctx);
 
 	if (DUK_UNLIKELY(top < 0)) {
 		/* Clamping to zero makes the API more robust to calling code
@@ -9318,17 +18949,17 @@ duk_bool_t duk_check_stack_top(duk_context *ctx, duk_idx_t top) {
 	}
 
 	min_new_size = top + DUK_VALSTACK_INTERNAL_EXTRA;
-	return duk__check_valstack_resize_helper(ctx,
-	                                         min_new_size,  /* min_new_size */
-	                                         0,             /* shrink_flag */
-	                                         0,             /* compact flag */
-	                                         0);            /* throw flag */
+	return duk_valstack_resize_raw(ctx,
+	                               min_new_size,  /* min_new_size */
+	                               0 /* no shrink */ |   /* flags */
+	                               0 /* no compact */ |
+	                               0 /* no throw */);
 }
 
-void duk_require_stack_top(duk_context *ctx, duk_idx_t top) {
+DUK_EXTERNAL void duk_require_stack_top(duk_context *ctx, duk_idx_t top) {
 	duk_size_t min_new_size;
 
-	DUK_ASSERT(ctx != NULL);
+	DUK_ASSERT_CTX_VALID(ctx);
 
 	if (DUK_UNLIKELY(top < 0)) {
 		/* Clamping to zero makes the API more robust to calling code
@@ -9338,23 +18969,23 @@ void duk_require_stack_top(duk_context *ctx, duk_idx_t top) {
 	}
 
 	min_new_size = top + DUK_VALSTACK_INTERNAL_EXTRA;
-	(void) duk__check_valstack_resize_helper(ctx,
-	                                         min_new_size,  /* min_new_size */
-	                                         0,             /* shrink_flag */
-	                                         0,             /* compact flag */
-	                                         1);            /* throw flag */
+	(void) duk_valstack_resize_raw(ctx,
+	                               min_new_size,  /* min_new_size */
+	                               0 /* no shrink */ |   /* flags */
+	                               0 /* no compact */ |
+	                               DUK_VSRESIZE_FLAG_THROW);
 }
 
 /*
  *  Basic stack manipulation: swap, dup, insert, replace, etc
  */
 
-void duk_swap(duk_context *ctx, duk_idx_t index1, duk_idx_t index2) {
+DUK_EXTERNAL void duk_swap(duk_context *ctx, duk_idx_t index1, duk_idx_t index2) {
 	duk_tval *tv1;
 	duk_tval *tv2;
 	duk_tval tv_tmp;
 
-	DUK_ASSERT(ctx != NULL);
+	DUK_ASSERT_CTX_VALID(ctx);
 
 	tv1 = duk_require_tval(ctx, index1);
 	DUK_ASSERT(tv1 != NULL);
@@ -9367,36 +18998,57 @@ void duk_swap(duk_context *ctx, duk_idx_t index1, duk_idx_t index2) {
 	DUK_TVAL_SET_TVAL(tv2, &tv_tmp);
 }
 
-void duk_swap_top(duk_context *ctx, duk_idx_t index) {
-	DUK_ASSERT(ctx != NULL);
+DUK_EXTERNAL void duk_swap_top(duk_context *ctx, duk_idx_t index) {
+	DUK_ASSERT_CTX_VALID(ctx);
 
 	duk_swap(ctx, index, -1);
 }
 
-void duk_dup(duk_context *ctx, duk_idx_t from_index) {
-	duk_tval *tv;
-
-	DUK_ASSERT(ctx != NULL);
+DUK_EXTERNAL void duk_dup(duk_context *ctx, duk_idx_t from_index) {
+	duk_hthread *thr;
+	duk_tval *tv_from;
+	duk_tval *tv_to;
 
-	tv = duk_require_tval(ctx, from_index);
-	DUK_ASSERT(tv != NULL);
+	DUK_ASSERT_CTX_VALID(ctx);
+	thr = (duk_hthread *) ctx;
+	DUK__CHECK_SPACE();
 
-	duk_push_tval(ctx, tv);
+	tv_from = duk_require_tval(ctx, from_index);
+	tv_to = thr->valstack_top++;
+	DUK_ASSERT(tv_from != NULL);
+	DUK_ASSERT(tv_to != NULL);
+	DUK_TVAL_SET_TVAL(tv_to, tv_from);
+	DUK_TVAL_INCREF(thr, tv_to);  /* no side effects */
 }
 
-void duk_dup_top(duk_context *ctx) {
-	DUK_ASSERT(ctx != NULL);
+DUK_EXTERNAL void duk_dup_top(duk_context *ctx) {
+	duk_hthread *thr;
+	duk_tval *tv_from;
+	duk_tval *tv_to;
 
-	duk_dup(ctx, -1);
+	DUK_ASSERT_CTX_VALID(ctx);
+	thr = (duk_hthread *) ctx;
+	DUK__CHECK_SPACE();
+
+	if (thr->valstack_top - thr->valstack_bottom <= 0) {
+		DUK_ERROR_API_INDEX(thr, -1);
+		return;  /* unreachable */
+	}
+	tv_from = thr->valstack_top - 1;
+	tv_to = thr->valstack_top++;
+	DUK_ASSERT(tv_from != NULL);
+	DUK_ASSERT(tv_to != NULL);
+	DUK_TVAL_SET_TVAL(tv_to, tv_from);
+	DUK_TVAL_INCREF(thr, tv_to);  /* no side effects */
 }
 
-void duk_insert(duk_context *ctx, duk_idx_t to_index) {
+DUK_EXTERNAL void duk_insert(duk_context *ctx, duk_idx_t to_index) {
 	duk_tval *p;
 	duk_tval *q;
 	duk_tval tv_tmp;
 	duk_size_t nbytes;
 
-	DUK_ASSERT(ctx != NULL);
+	DUK_ASSERT_CTX_VALID(ctx);
 
 	p = duk_require_tval(ctx, to_index);
 	DUK_ASSERT(p != NULL);
@@ -9421,7 +19073,7 @@ void duk_insert(duk_context *ctx, duk_idx_t to_index) {
 	if (nbytes > 0) {
 		DUK_TVAL_SET_TVAL(&tv_tmp, q);
 		DUK_ASSERT(nbytes > 0);
-		DUK_MEMMOVE((void *) (p + 1), (void *) p, nbytes);
+		DUK_MEMMOVE((void *) (p + 1), (const void *) p, (size_t) nbytes);
 		DUK_TVAL_SET_TVAL(p, &tv_tmp);
 	} else {
 		/* nop: insert top to top */
@@ -9430,13 +19082,13 @@ void duk_insert(duk_context *ctx, duk_idx_t to_index) {
 	}
 }
 
-void duk_replace(duk_context *ctx, duk_idx_t to_index) {
+DUK_EXTERNAL void duk_replace(duk_context *ctx, duk_idx_t to_index) {
 	duk_hthread *thr = (duk_hthread *) ctx;
 	duk_tval *tv1;
 	duk_tval *tv2;
 	duk_tval tv_tmp;
 
-	DUK_ASSERT(ctx != NULL);
+	DUK_ASSERT_CTX_VALID(ctx);
 
 	tv1 = duk_require_tval(ctx, -1);
 	DUK_ASSERT(tv1 != NULL);
@@ -9446,21 +19098,20 @@ void duk_replace(duk_context *ctx, duk_idx_t to_index) {
 	/* For tv1 == tv2, both pointing to stack top, the end result
 	 * is same as duk_pop(ctx).
 	 */
-
 	DUK_TVAL_SET_TVAL(&tv_tmp, tv2);
 	DUK_TVAL_SET_TVAL(tv2, tv1);
-	DUK_TVAL_SET_UNDEFINED_UNUSED(tv1);
+	DUK_TVAL_SET_UNDEFINED(tv1);
 	thr->valstack_top--;
 	DUK_TVAL_DECREF(thr, &tv_tmp);  /* side effects */
 }
 
-void duk_copy(duk_context *ctx, duk_idx_t from_index, duk_idx_t to_index) {
+DUK_EXTERNAL void duk_copy(duk_context *ctx, duk_idx_t from_index, duk_idx_t to_index) {
 	duk_hthread *thr = (duk_hthread *) ctx;
 	duk_tval *tv1;
 	duk_tval *tv2;
-	duk_tval tv_tmp;
 
-	DUK_ASSERT(ctx != NULL);
+	DUK_ASSERT_CTX_VALID(ctx);
+	DUK_UNREF(thr);  /* w/o refcounting */
 
 	tv1 = duk_require_tval(ctx, from_index);
 	DUK_ASSERT(tv1 != NULL);
@@ -9468,14 +19119,10 @@ void duk_copy(duk_context *ctx, duk_idx_t from_index, duk_idx_t to_index) {
 	DUK_ASSERT(tv2 != NULL);
 
 	/* For tv1 == tv2, this is a no-op (no explicit check needed). */
-
-	DUK_TVAL_SET_TVAL(&tv_tmp, tv2);
-	DUK_TVAL_SET_TVAL(tv2, tv1);
-	DUK_TVAL_INCREF(thr, tv2);  /* no side effects */
-	DUK_TVAL_DECREF(thr, &tv_tmp);  /* side effects */
+	DUK_TVAL_SET_TVAL_UPDREF(thr, tv2, tv1);  /* side effects */
 }
 
-void duk_remove(duk_context *ctx, duk_idx_t index) {
+DUK_EXTERNAL void duk_remove(duk_context *ctx, duk_idx_t index) {
 	duk_hthread *thr = (duk_hthread *) ctx;
 	duk_tval *p;
 	duk_tval *q;
@@ -9484,7 +19131,7 @@ void duk_remove(duk_context *ctx, duk_idx_t index) {
 #endif
 	duk_size_t nbytes;
 
-	DUK_ASSERT(ctx != NULL);
+	DUK_ASSERT_CTX_VALID(ctx);
 
 	p = duk_require_tval(ctx, index);
 	DUK_ASSERT(p != NULL);
@@ -9505,9 +19152,9 @@ void duk_remove(duk_context *ctx, duk_idx_t index) {
 #endif
 
 	nbytes = (duk_size_t) (((duk_uint8_t *) q) - ((duk_uint8_t *) p));  /* Note: 'q' is top-1 */
-	DUK_MEMMOVE(p, p + 1, nbytes);  /* zero size not an issue: pointers are valid */
+	DUK_MEMMOVE((void *) p, (const void *) (p + 1), (size_t) nbytes);  /* zero size not an issue: pointers are valid */
 
-	DUK_TVAL_SET_UNDEFINED_UNUSED(q);
+	DUK_TVAL_SET_UNDEFINED(q);
 	thr->valstack_top--;
 
 #ifdef DUK_USE_REFERENCE_COUNTING
@@ -9519,44 +19166,72 @@ void duk_remove(duk_context *ctx, duk_idx_t index) {
  *  Stack slice primitives
  */
 
-void duk_xmove(duk_context *ctx, duk_context *from_ctx, duk_idx_t count) {
-	duk_hthread *thr = (duk_hthread *) ctx;
+DUK_EXTERNAL void duk_xcopymove_raw(duk_context *to_ctx, duk_context *from_ctx, duk_idx_t count, duk_bool_t is_copy) {
+	duk_hthread *to_thr = (duk_hthread *) to_ctx;
 	duk_hthread *from_thr = (duk_hthread *) from_ctx;
 	void *src;
 	duk_size_t nbytes;
 	duk_tval *p;
+	duk_tval *q;
 
-	DUK_ASSERT(ctx != NULL);
+	/* XXX: several pointer comparison issues here */
+
+	DUK_ASSERT_CTX_VALID(to_ctx);
+	DUK_ASSERT_CTX_VALID(from_ctx);
+	DUK_ASSERT(to_ctx != NULL);
 	DUK_ASSERT(from_ctx != NULL);
 
-	if (count < 0) {
-		DUK_ERROR(thr, DUK_ERR_API_ERROR, DUK_STR_INVALID_COUNT);
+	if (to_ctx == from_ctx) {
+		DUK_ERROR_API(to_thr, DUK_STR_INVALID_CONTEXT);
+		return;
+	}
+	if ((count < 0) ||
+	    (count > (duk_idx_t) to_thr->valstack_max)) {
+		/* Maximum value check ensures 'nbytes' won't wrap below. */
+		DUK_ERROR_API(to_thr, DUK_STR_INVALID_COUNT);
 		return;
 	}
 
-	nbytes = sizeof(duk_tval) * count;  /* FIXME: wrap check */
+	nbytes = sizeof(duk_tval) * count;
 	if (nbytes == 0) {
 		return;
 	}
-	DUK_ASSERT(thr->valstack_top <= thr->valstack_end);
-	if ((duk_size_t) ((duk_uint8_t *) thr->valstack_end - (duk_uint8_t *) thr->valstack_top) < nbytes) {
-		DUK_ERROR(thr, DUK_ERR_API_ERROR, DUK_STR_PUSH_BEYOND_ALLOC_STACK);
+	DUK_ASSERT(to_thr->valstack_top <= to_thr->valstack_end);
+	if ((duk_size_t) ((duk_uint8_t *) to_thr->valstack_end - (duk_uint8_t *) to_thr->valstack_top) < nbytes) {
+		DUK_ERROR_API(to_thr, DUK_STR_PUSH_BEYOND_ALLOC_STACK);
 	}
 	src = (void *) ((duk_uint8_t *) from_thr->valstack_top - nbytes);
 	if (src < (void *) from_thr->valstack_bottom) {
-		DUK_ERROR(thr, DUK_ERR_API_ERROR, DUK_STR_SRC_STACK_NOT_ENOUGH);
+		DUK_ERROR_API(to_thr, DUK_STR_INVALID_COUNT);
 	}
 
-	/* copy values (no overlap even if ctx == from_ctx) */
+	/* copy values (no overlap even if to_ctx == from_ctx; that's not
+	 * allowed now anyway)
+	 */
 	DUK_ASSERT(nbytes > 0);
-	DUK_MEMCPY((void *) thr->valstack_top, src, nbytes);
+	DUK_MEMCPY((void *) to_thr->valstack_top, (const void *) src, (size_t) nbytes);
 
-	/* incref them */
-	p = thr->valstack_top;
-	thr->valstack_top = (duk_tval *) (((duk_uint8_t *) thr->valstack_top) + nbytes);
-	while (p < thr->valstack_top) {
-		DUK_TVAL_INCREF(thr, p);  /* no side effects */
-		p++;
+	p = to_thr->valstack_top;
+	to_thr->valstack_top = (duk_tval *) (void *) (((duk_uint8_t *) p) + nbytes);
+
+	if (is_copy) {
+		/* Incref copies, keep originals. */
+		q = to_thr->valstack_top;
+		while (p < q) {
+			DUK_TVAL_INCREF(to_thr, p);  /* no side effects */
+			p++;
+		}
+	} else {
+		/* No net refcount change. */
+		p = from_thr->valstack_top;
+		q = (duk_tval *) (void *) (((duk_uint8_t *) p) - nbytes);
+		from_thr->valstack_top = q;
+
+		while (p > q) {
+			p--;
+			DUK_TVAL_SET_UNDEFINED(p);
+			/* XXX: fast primitive to set a bunch of values to UNDEFINED */
+		}
 	}
 }
 
@@ -9564,39 +19239,39 @@ void duk_xmove(duk_context *ctx, duk_context *from_ctx, duk_idx_t count) {
  *  Get/require
  */
 
-void duk_require_undefined(duk_context *ctx, duk_idx_t index) {
+DUK_EXTERNAL void duk_require_undefined(duk_context *ctx, duk_idx_t index) {
 	duk_hthread *thr = (duk_hthread *) ctx;
 	duk_tval *tv;
 
-	DUK_ASSERT(ctx != NULL);
+	DUK_ASSERT_CTX_VALID(ctx);
 
 	tv = duk_get_tval(ctx, index);
 	if (tv && DUK_TVAL_IS_UNDEFINED(tv)) {
-		/* Note: accept both 'actual' and 'unused' undefined */
 		return;
 	}
-	DUK_ERROR(thr, DUK_ERR_TYPE_ERROR, DUK_STR_NOT_UNDEFINED);
+	DUK_ERROR_REQUIRE_TYPE_INDEX(thr, index, "undefined", DUK_STR_NOT_UNDEFINED);
+	return;  /* not reachable */
 }
 
-void duk_require_null(duk_context *ctx, duk_idx_t index) {
+DUK_EXTERNAL void duk_require_null(duk_context *ctx, duk_idx_t index) {
 	duk_hthread *thr = (duk_hthread *) ctx;
 	duk_tval *tv;
 
-	DUK_ASSERT(ctx != NULL);
+	DUK_ASSERT_CTX_VALID(ctx);
 
 	tv = duk_get_tval(ctx, index);
 	if (tv && DUK_TVAL_IS_NULL(tv)) {
 		return;
 	}
-	DUK_ERROR(thr, DUK_ERR_TYPE_ERROR, DUK_STR_NOT_NULL);
+	DUK_ERROR_REQUIRE_TYPE_INDEX(thr, index, "null", DUK_STR_NOT_NULL);
 	return;  /* not reachable */
 }
 
-duk_bool_t duk_get_boolean(duk_context *ctx, duk_idx_t index) {
+DUK_EXTERNAL duk_bool_t duk_get_boolean(duk_context *ctx, duk_idx_t index) {
 	duk_bool_t ret = 0;  /* default: false */
 	duk_tval *tv;
 
-	DUK_ASSERT(ctx != NULL);
+	DUK_ASSERT_CTX_VALID(ctx);
 
 	tv = duk_get_tval(ctx, index);
 	if (tv && DUK_TVAL_IS_BOOLEAN(tv)) {
@@ -9607,11 +19282,11 @@ duk_bool_t duk_get_boolean(duk_context *ctx, duk_idx_t index) {
 	return ret;
 }
 
-duk_bool_t duk_require_boolean(duk_context *ctx, duk_idx_t index) {
+DUK_EXTERNAL duk_bool_t duk_require_boolean(duk_context *ctx, duk_idx_t index) {
 	duk_hthread *thr = (duk_hthread *) ctx;
 	duk_tval *tv;
 
-	DUK_ASSERT(ctx != NULL);
+	DUK_ASSERT_CTX_VALID(ctx);
 
 	tv = duk_get_tval(ctx, index);
 	if (tv && DUK_TVAL_IS_BOOLEAN(tv)) {
@@ -9619,16 +19294,15 @@ duk_bool_t duk_require_boolean(duk_context *ctx, duk_idx_t index) {
 		DUK_ASSERT(ret == 0 || ret == 1);
 		return ret;
 	}
-
-	DUK_ERROR(thr, DUK_ERR_TYPE_ERROR, DUK_STR_NOT_BOOLEAN);
+	DUK_ERROR_REQUIRE_TYPE_INDEX(thr, index, "boolean", DUK_STR_NOT_BOOLEAN);
 	return 0;  /* not reachable */
 }
 
-duk_double_t duk_get_number(duk_context *ctx, duk_idx_t index) {
+DUK_EXTERNAL duk_double_t duk_get_number(duk_context *ctx, duk_idx_t index) {
 	duk_double_union ret;
 	duk_tval *tv;
 
-	DUK_ASSERT(ctx != NULL);
+	DUK_ASSERT_CTX_VALID(ctx);
 
 	ret.d = DUK_DOUBLE_NAN;  /* default: NaN */
 	tv = duk_get_tval(ctx, index);
@@ -9645,11 +19319,11 @@ duk_double_t duk_get_number(duk_context *ctx, duk_idx_t index) {
 	return ret.d;
 }
 
-duk_double_t duk_require_number(duk_context *ctx, duk_idx_t index) {
+DUK_EXTERNAL duk_double_t duk_require_number(duk_context *ctx, duk_idx_t index) {
 	duk_hthread *thr = (duk_hthread *) ctx;
 	duk_tval *tv;
 
-	DUK_ASSERT(ctx != NULL);
+	DUK_ASSERT_CTX_VALID(ctx);
 
 	tv = duk_get_tval(ctx, index);
 	if (tv && DUK_TVAL_IS_NUMBER(tv)) {
@@ -9664,36 +19338,39 @@ duk_double_t duk_require_number(duk_context *ctx, duk_idx_t index) {
 		DUK_DBLUNION_NORMALIZE_NAN_CHECK(&ret);
 		return ret.d;
 	}
-
-	DUK_ERROR(thr, DUK_ERR_TYPE_ERROR, DUK_STR_NOT_NUMBER);
+	DUK_ERROR_REQUIRE_TYPE_INDEX(thr, index, "number", DUK_STR_NOT_NUMBER);
 	return DUK_DOUBLE_NAN;  /* not reachable */
 }
 
-duk_int_t duk_get_int(duk_context *ctx, duk_idx_t index) {
+DUK_EXTERNAL duk_int_t duk_get_int(duk_context *ctx, duk_idx_t index) {
 	/* Custom coercion for API */
-	return (duk_int_t) duk__api_coerce_d2i(duk_get_number(ctx, index));
+	DUK_ASSERT_CTX_VALID(ctx);
+	return (duk_int_t) duk__api_coerce_d2i(ctx, index, 0 /*require*/);
 }
 
-duk_uint_t duk_get_uint(duk_context *ctx, duk_idx_t index) {
+DUK_EXTERNAL duk_uint_t duk_get_uint(duk_context *ctx, duk_idx_t index) {
 	/* Custom coercion for API */
-	return (duk_uint_t) duk__api_coerce_d2ui(duk_get_number(ctx, index));
+	DUK_ASSERT_CTX_VALID(ctx);
+	return (duk_uint_t) duk__api_coerce_d2ui(ctx, index, 0 /*require*/);
 }
 
-duk_int_t duk_require_int(duk_context *ctx, duk_idx_t index) {
+DUK_EXTERNAL duk_int_t duk_require_int(duk_context *ctx, duk_idx_t index) {
 	/* Custom coercion for API */
-	return (duk_int_t) duk__api_coerce_d2i(duk_require_number(ctx, index));
+	DUK_ASSERT_CTX_VALID(ctx);
+	return (duk_int_t) duk__api_coerce_d2i(ctx, index, 1 /*require*/);
 }
 
-duk_uint_t duk_require_uint(duk_context *ctx, duk_idx_t index) {
+DUK_EXTERNAL duk_uint_t duk_require_uint(duk_context *ctx, duk_idx_t index) {
 	/* Custom coercion for API */
-	return (duk_uint_t) duk__api_coerce_d2ui(duk_require_number(ctx, index));
+	DUK_ASSERT_CTX_VALID(ctx);
+	return (duk_uint_t) duk__api_coerce_d2ui(ctx, index, 1 /*require*/);
 }
 
-const char *duk_get_lstring(duk_context *ctx, duk_idx_t index, duk_size_t *out_len) {
+DUK_EXTERNAL const char *duk_get_lstring(duk_context *ctx, duk_idx_t index, duk_size_t *out_len) {
 	const char *ret;
 	duk_tval *tv;
 
-	DUK_ASSERT(ctx != NULL);
+	DUK_ASSERT_CTX_VALID(ctx);
 
 	/* default: NULL, length 0 */
 	ret = NULL;
@@ -9717,11 +19394,11 @@ const char *duk_get_lstring(duk_context *ctx, duk_idx_t index, duk_size_t *out_l
 	return ret;
 }
 
-const char *duk_require_lstring(duk_context *ctx, duk_idx_t index, duk_size_t *out_len) {
+DUK_EXTERNAL const char *duk_require_lstring(duk_context *ctx, duk_idx_t index, duk_size_t *out_len) {
 	duk_hthread *thr = (duk_hthread *) ctx;
 	const char *ret;
 
-	DUK_ASSERT(ctx != NULL);
+	DUK_ASSERT_CTX_VALID(ctx);
 
 	/* Note: this check relies on the fact that even a zero-size string
 	 * has a non-NULL pointer.
@@ -9730,27 +19407,26 @@ const char *duk_require_lstring(duk_context *ctx, duk_idx_t index, duk_size_t *o
 	if (ret) {
 		return ret;
 	}
-
-	DUK_ERROR(thr, DUK_ERR_TYPE_ERROR, DUK_STR_NOT_STRING);
+	DUK_ERROR_REQUIRE_TYPE_INDEX(thr, index, "string", DUK_STR_NOT_STRING);
 	return NULL;  /* not reachable */
 }
 
-const char *duk_get_string(duk_context *ctx, duk_idx_t index) {
-	DUK_ASSERT(ctx != NULL);
+DUK_EXTERNAL const char *duk_get_string(duk_context *ctx, duk_idx_t index) {
+	DUK_ASSERT_CTX_VALID(ctx);
 
 	return duk_get_lstring(ctx, index, NULL);
 }
 
-const char *duk_require_string(duk_context *ctx, duk_idx_t index) {
-	DUK_ASSERT(ctx != NULL);
+DUK_EXTERNAL const char *duk_require_string(duk_context *ctx, duk_idx_t index) {
+	DUK_ASSERT_CTX_VALID(ctx);
 
 	return duk_require_lstring(ctx, index, NULL);
 }
 
-void *duk_get_pointer(duk_context *ctx, duk_idx_t index) {
+DUK_EXTERNAL void *duk_get_pointer(duk_context *ctx, duk_idx_t index) {
 	duk_tval *tv;
 
-	DUK_ASSERT(ctx != NULL);
+	DUK_ASSERT_CTX_VALID(ctx);
 
 	tv = duk_get_tval(ctx, index);
 	if (tv && DUK_TVAL_IS_POINTER(tv)) {
@@ -9761,11 +19437,11 @@ void *duk_get_pointer(duk_context *ctx, duk_idx_t index) {
 	return NULL;
 }
 
-void *duk_require_pointer(duk_context *ctx, duk_idx_t index) {
+DUK_EXTERNAL void *duk_require_pointer(duk_context *ctx, duk_idx_t index) {
 	duk_hthread *thr = (duk_hthread *) ctx;
 	duk_tval *tv;
 
-	DUK_ASSERT(ctx != NULL);
+	DUK_ASSERT_CTX_VALID(ctx);
 
 	/* Note: here we must be wary of the fact that a pointer may be
 	 * valid and be a NULL.
@@ -9775,16 +19451,15 @@ void *duk_require_pointer(duk_context *ctx, duk_idx_t index) {
 		void *p = DUK_TVAL_GET_POINTER(tv);  /* may be NULL */
 		return (void *) p;
 	}
-
-	DUK_ERROR(thr, DUK_ERR_TYPE_ERROR, DUK_STR_NOT_POINTER);
+	DUK_ERROR_REQUIRE_TYPE_INDEX(thr, index, "pointer", DUK_STR_NOT_POINTER);
 	return NULL;  /* not reachable */
 }
 
-/* XXX: unused */
-void *duk_get_voidptr(duk_context *ctx, duk_idx_t index) {
+#if 0  /*unused*/
+DUK_INTERNAL void *duk_get_voidptr(duk_context *ctx, duk_idx_t index) {
 	duk_tval *tv;
 
-	DUK_ASSERT(ctx != NULL);
+	DUK_ASSERT_CTX_VALID(ctx);
 
 	tv = duk_get_tval(ctx, index);
 	if (tv && DUK_TVAL_IS_HEAP_ALLOCATED(tv)) {
@@ -9795,11 +19470,14 @@ void *duk_get_voidptr(duk_context *ctx, duk_idx_t index) {
 
 	return NULL;
 }
+#endif
 
-void *duk_get_buffer(duk_context *ctx, duk_idx_t index, duk_size_t *out_size) {
+DUK_LOCAL void *duk__get_buffer_helper(duk_context *ctx, duk_idx_t index, duk_size_t *out_size, duk_bool_t throw_flag) {
+	duk_hthread *thr = (duk_hthread *) ctx;
 	duk_tval *tv;
 
-	DUK_ASSERT(ctx != NULL);
+	DUK_ASSERT_CTX_VALID(ctx);
+	DUK_UNREF(thr);
 
 	if (out_size != NULL) {
 		*out_size = 0;
@@ -9812,170 +19490,202 @@ void *duk_get_buffer(duk_context *ctx, duk_idx_t index, duk_size_t *out_size) {
 		if (out_size) {
 			*out_size = DUK_HBUFFER_GET_SIZE(h);
 		}
-		return (void *) DUK_HBUFFER_GET_DATA_PTR(h);  /* may be NULL (but only if size is 0) */
+		return (void *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h);  /* may be NULL (but only if size is 0) */
 	}
 
+	if (throw_flag) {
+		DUK_ERROR_REQUIRE_TYPE_INDEX(thr, index, "buffer", DUK_STR_NOT_BUFFER);
+	}
 	return NULL;
 }
 
-void *duk_require_buffer(duk_context *ctx, duk_idx_t index, duk_size_t *out_size) {
+DUK_EXTERNAL void *duk_get_buffer(duk_context *ctx, duk_idx_t index, duk_size_t *out_size) {
+	return duk__get_buffer_helper(ctx, index, out_size, 0 /*throw_flag*/);
+}
+
+DUK_EXTERNAL void *duk_require_buffer(duk_context *ctx, duk_idx_t index, duk_size_t *out_size) {
+	return duk__get_buffer_helper(ctx, index, out_size, 1 /*throw_flag*/);
+}
+
+DUK_LOCAL void *duk__get_buffer_data_helper(duk_context *ctx, duk_idx_t index, duk_size_t *out_size, duk_bool_t throw_flag) {
 	duk_hthread *thr = (duk_hthread *) ctx;
 	duk_tval *tv;
 
-	DUK_ASSERT(ctx != NULL);
+	DUK_ASSERT_CTX_VALID(ctx);
+	DUK_UNREF(thr);
 
 	if (out_size != NULL) {
 		*out_size = 0;
 	}
 
-	/* Note: here we must be wary of the fact that a data pointer may
-	 * be a NULL for a zero-size buffer.
-	 */
-	
 	tv = duk_get_tval(ctx, index);
-	if (tv && DUK_TVAL_IS_BUFFER(tv)) {
+	if (tv == NULL) {
+		goto fail;
+	}
+
+	if (DUK_TVAL_IS_BUFFER(tv)) {
 		duk_hbuffer *h = DUK_TVAL_GET_BUFFER(tv);
 		DUK_ASSERT(h != NULL);
 		if (out_size) {
 			*out_size = DUK_HBUFFER_GET_SIZE(h);
 		}
-		return (void *) DUK_HBUFFER_GET_DATA_PTR(h);  /* may be NULL (but only if size is 0) */
+		return (void *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h);  /* may be NULL (but only if size is 0) */
+	} else if (DUK_TVAL_IS_OBJECT(tv)) {
+		duk_hobject *h = DUK_TVAL_GET_OBJECT(tv);
+		DUK_ASSERT(h != NULL);
+		if (DUK_HOBJECT_IS_BUFFEROBJECT(h)) {
+			/* XXX: this is probably a useful shared helper: for a
+			 * duk_hbufferobject, get a validated buffer pointer/length.
+			 */
+			duk_hbufferobject *h_bufobj = (duk_hbufferobject *) h;
+			DUK_ASSERT_HBUFFEROBJECT_VALID(h_bufobj);
+
+			if (h_bufobj->buf != NULL &&
+			    DUK_HBUFFEROBJECT_VALID_SLICE(h_bufobj)) {
+				duk_uint8_t *p;
+
+				p = (duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h_bufobj->buf);
+				if (out_size != NULL) {
+					*out_size = (duk_size_t) h_bufobj->length;
+				}
+				return (void *) (p + h_bufobj->offset);
+			}
+			/* if slice not fully valid, treat as error */
+		}
 	}
 
-	DUK_ERROR(thr, DUK_ERR_TYPE_ERROR, DUK_STR_NOT_BUFFER);
-	return NULL;  /* not reachable */
+ fail:
+	if (throw_flag) {
+		DUK_ERROR_REQUIRE_TYPE_INDEX(thr, index, "buffer", DUK_STR_NOT_BUFFER);
+	}
+	return NULL;
+}
+
+DUK_EXTERNAL void *duk_get_buffer_data(duk_context *ctx, duk_idx_t index, duk_size_t *out_size) {
+	return duk__get_buffer_data_helper(ctx, index, out_size, 0 /*throw_flag*/);
 }
 
-/* Raw helper for getting a value from the stack, checking its tag, and possible its object class.
- * The tag cannot be a number because numbers don't have an internal tag in the packed representation.
+DUK_EXTERNAL void *duk_require_buffer_data(duk_context *ctx, duk_idx_t index, duk_size_t *out_size) {
+	return duk__get_buffer_data_helper(ctx, index, out_size, 1 /*throw_flag*/);
+}
+
+/* Raw helper for getting a value from the stack, checking its tag.
+ * The tag cannot be a number because numbers don't have an internal
+ * tag in the packed representation.
  */
-duk_heaphdr *duk_get_tagged_heaphdr_raw(duk_context *ctx, duk_idx_t index, duk_uint_t flags_and_tag) {
-	duk_hthread *thr = (duk_hthread *) ctx;
+
+DUK_LOCAL duk_heaphdr *duk__get_tagged_heaphdr_raw(duk_context *ctx, duk_idx_t index, duk_uint_t tag) {
 	duk_tval *tv;
-	duk_small_uint_t tag = flags_and_tag & 0xffffU;  /* tags can be up to 16 bits */
 
-	DUK_ASSERT(ctx != NULL);
+	DUK_ASSERT_CTX_VALID(ctx);
 
 	tv = duk_get_tval(ctx, index);
 	if (tv && (DUK_TVAL_GET_TAG(tv) == tag)) {
 		duk_heaphdr *ret;
-
-		/* Note: tag comparison in general doesn't work for numbers,
-		 * but it does work for everything else (heap objects here).
-		 */
 		ret = DUK_TVAL_GET_HEAPHDR(tv);
 		DUK_ASSERT(ret != NULL);  /* tagged null pointers should never occur */
-
-		/* If class check has been requested, tag must also be DUK_TAG_OBJECT.
-		 * This allows us to just check the class check flag without checking
-		 * the tag also.
-		 */
-		DUK_ASSERT((flags_and_tag & DUK_GETTAGGED_FLAG_CHECK_CLASS) == 0 ||
-		           tag == DUK_TAG_OBJECT);
-
-		if ((flags_and_tag & DUK_GETTAGGED_FLAG_CHECK_CLASS) == 0 ||  /* no class check */
-		    (duk_int_t) DUK_HOBJECT_GET_CLASS_NUMBER((duk_hobject *) ret) ==  /* or class check matches */
-		        (duk_int_t) ((flags_and_tag >> DUK_GETTAGGED_CLASS_SHIFT) & 0xff)) {
-			return ret;
-		}
-	}
-
-	if (flags_and_tag & DUK_GETTAGGED_FLAG_ALLOW_NULL) {
-		return (duk_heaphdr *) NULL;
+		return ret;
 	}
 
-	/* Formatting the tag number here is not very useful: the tag value
-	 * is Duktape internal (not the same as DUK_TYPE_xxx) and even depends
-	 * on the duk_tval layout.  If anything, add a human readable type here.
-	 */
-	DUK_ERROR(thr, DUK_ERR_TYPE_ERROR, DUK_STR_UNEXPECTED_TYPE);
-	return NULL;  /* not reachable */
+	return (duk_heaphdr *) NULL;
 }
 
-duk_hstring *duk_get_hstring(duk_context *ctx, duk_idx_t index) {
-	return (duk_hstring *) duk_get_tagged_heaphdr_raw(ctx, index, DUK_TAG_STRING | DUK_GETTAGGED_FLAG_ALLOW_NULL);
+DUK_INTERNAL duk_hstring *duk_get_hstring(duk_context *ctx, duk_idx_t index) {
+	return (duk_hstring *) duk__get_tagged_heaphdr_raw(ctx, index, DUK_TAG_STRING);
 }
 
-duk_hstring *duk_require_hstring(duk_context *ctx, duk_idx_t index) {
-	return (duk_hstring *) duk_get_tagged_heaphdr_raw(ctx, index, DUK_TAG_STRING);
+DUK_INTERNAL duk_hstring *duk_require_hstring(duk_context *ctx, duk_idx_t index) {
+	duk_heaphdr *h;
+	h = duk__get_tagged_heaphdr_raw(ctx, index, DUK_TAG_STRING);
+	if (h == NULL) {
+		DUK_ERROR_REQUIRE_TYPE_INDEX(ctx, index, "string", DUK_STR_NOT_STRING);
+	}
+	return (duk_hstring *) h;
 }
 
-duk_hobject *duk_get_hobject(duk_context *ctx, duk_idx_t index) {
-	return (duk_hobject *) duk_get_tagged_heaphdr_raw(ctx, index, DUK_TAG_OBJECT | DUK_GETTAGGED_FLAG_ALLOW_NULL);
+DUK_INTERNAL duk_hobject *duk_get_hobject(duk_context *ctx, duk_idx_t index) {
+	return (duk_hobject *) duk__get_tagged_heaphdr_raw(ctx, index, DUK_TAG_OBJECT);
 }
 
-duk_hobject *duk_require_hobject(duk_context *ctx, duk_idx_t index) {
-	return (duk_hobject *) duk_get_tagged_heaphdr_raw(ctx, index, DUK_TAG_OBJECT);
+DUK_INTERNAL duk_hobject *duk_require_hobject(duk_context *ctx, duk_idx_t index) {
+	duk_heaphdr *h;
+	h = duk__get_tagged_heaphdr_raw(ctx, index, DUK_TAG_OBJECT);
+	if (h == NULL) {
+		DUK_ERROR_REQUIRE_TYPE_INDEX(ctx, index, "object", DUK_STR_NOT_OBJECT);
+	}
+	return (duk_hobject *) h;
 }
 
-duk_hbuffer *duk_get_hbuffer(duk_context *ctx, duk_idx_t index) {
-	return (duk_hbuffer *) duk_get_tagged_heaphdr_raw(ctx, index, DUK_TAG_BUFFER | DUK_GETTAGGED_FLAG_ALLOW_NULL);
+DUK_INTERNAL duk_hbuffer *duk_get_hbuffer(duk_context *ctx, duk_idx_t index) {
+	return (duk_hbuffer *) duk__get_tagged_heaphdr_raw(ctx, index, DUK_TAG_BUFFER);
 }
 
-duk_hbuffer *duk_require_hbuffer(duk_context *ctx, duk_idx_t index) {
-	return (duk_hbuffer *) duk_get_tagged_heaphdr_raw(ctx, index, DUK_TAG_BUFFER);
+DUK_INTERNAL duk_hbuffer *duk_require_hbuffer(duk_context *ctx, duk_idx_t index) {
+	duk_heaphdr *h;
+	h = duk__get_tagged_heaphdr_raw(ctx, index, DUK_TAG_BUFFER);
+	if (h == NULL) {
+		DUK_ERROR_REQUIRE_TYPE_INDEX(ctx, index, "buffer", DUK_STR_NOT_BUFFER);
+	}
+	return (duk_hbuffer *) h;
 }
 
-duk_hthread *duk_get_hthread(duk_context *ctx, duk_idx_t index) {
-	duk_hobject *h = (duk_hobject *) duk_get_tagged_heaphdr_raw(ctx, index, DUK_TAG_OBJECT | DUK_GETTAGGED_FLAG_ALLOW_NULL);
+DUK_INTERNAL duk_hthread *duk_get_hthread(duk_context *ctx, duk_idx_t index) {
+	duk_hobject *h = (duk_hobject *) duk__get_tagged_heaphdr_raw(ctx, index, DUK_TAG_OBJECT);
 	if (h != NULL && !DUK_HOBJECT_IS_THREAD(h)) {
 		h = NULL;
 	}
 	return (duk_hthread *) h;
 }
 
-duk_hthread *duk_require_hthread(duk_context *ctx, duk_idx_t index) {
+DUK_INTERNAL duk_hthread *duk_require_hthread(duk_context *ctx, duk_idx_t index) {
 	duk_hthread *thr = (duk_hthread *) ctx;
-	duk_hobject *h = (duk_hobject *) duk_get_tagged_heaphdr_raw(ctx, index, DUK_TAG_OBJECT);
-	DUK_ASSERT(h != NULL);
-	if (!DUK_HOBJECT_IS_THREAD(h)) {
-		DUK_ERROR(thr, DUK_ERR_TYPE_ERROR, DUK_STR_NOT_THREAD);
+	duk_hobject *h = (duk_hobject *) duk__get_tagged_heaphdr_raw(ctx, index, DUK_TAG_OBJECT);
+	if (!(h != NULL && DUK_HOBJECT_IS_THREAD(h))) {
+		DUK_ERROR_REQUIRE_TYPE_INDEX(thr, index, "thread", DUK_STR_NOT_THREAD);
 	}
 	return (duk_hthread *) h;
 }
 
-duk_hcompiledfunction *duk_get_hcompiledfunction(duk_context *ctx, duk_idx_t index) {
-	duk_hobject *h = (duk_hobject *) duk_get_tagged_heaphdr_raw(ctx, index, DUK_TAG_OBJECT | DUK_GETTAGGED_FLAG_ALLOW_NULL);
+DUK_INTERNAL duk_hcompiledfunction *duk_get_hcompiledfunction(duk_context *ctx, duk_idx_t index) {
+	duk_hobject *h = (duk_hobject *) duk__get_tagged_heaphdr_raw(ctx, index, DUK_TAG_OBJECT);
 	if (h != NULL && !DUK_HOBJECT_IS_COMPILEDFUNCTION(h)) {
 		h = NULL;
 	}
 	return (duk_hcompiledfunction *) h;
 }
 
-duk_hcompiledfunction *duk_require_hcompiledfunction(duk_context *ctx, duk_idx_t index) {
+DUK_INTERNAL duk_hcompiledfunction *duk_require_hcompiledfunction(duk_context *ctx, duk_idx_t index) {
 	duk_hthread *thr = (duk_hthread *) ctx;
-	duk_hobject *h = (duk_hobject *) duk_get_tagged_heaphdr_raw(ctx, index, DUK_TAG_OBJECT);
-	DUK_ASSERT(h != NULL);
-	if (!DUK_HOBJECT_IS_COMPILEDFUNCTION(h)) {
-		DUK_ERROR(thr, DUK_ERR_TYPE_ERROR, DUK_STR_NOT_COMPILEDFUNCTION);
+	duk_hobject *h = (duk_hobject *) duk__get_tagged_heaphdr_raw(ctx, index, DUK_TAG_OBJECT);
+	if (!(h != NULL && DUK_HOBJECT_IS_COMPILEDFUNCTION(h))) {
+		DUK_ERROR_REQUIRE_TYPE_INDEX(thr, index, "compiledfunction", DUK_STR_NOT_COMPILEDFUNCTION);
 	}
 	return (duk_hcompiledfunction *) h;
 }
 
-duk_hnativefunction *duk_get_hnativefunction(duk_context *ctx, duk_idx_t index) {
-	duk_hobject *h = (duk_hobject *) duk_get_tagged_heaphdr_raw(ctx, index, DUK_TAG_OBJECT | DUK_GETTAGGED_FLAG_ALLOW_NULL);
+DUK_INTERNAL duk_hnativefunction *duk_get_hnativefunction(duk_context *ctx, duk_idx_t index) {
+	duk_hobject *h = (duk_hobject *) duk__get_tagged_heaphdr_raw(ctx, index, DUK_TAG_OBJECT);
 	if (h != NULL && !DUK_HOBJECT_IS_NATIVEFUNCTION(h)) {
 		h = NULL;
 	}
 	return (duk_hnativefunction *) h;
 }
 
-duk_hnativefunction *duk_require_hnativefunction(duk_context *ctx, duk_idx_t index) {
+DUK_INTERNAL duk_hnativefunction *duk_require_hnativefunction(duk_context *ctx, duk_idx_t index) {
 	duk_hthread *thr = (duk_hthread *) ctx;
-	duk_hobject *h = (duk_hobject *) duk_get_tagged_heaphdr_raw(ctx, index, DUK_TAG_OBJECT);
-	DUK_ASSERT(h != NULL);
-	if (!DUK_HOBJECT_IS_NATIVEFUNCTION(h)) {
-		DUK_ERROR(thr, DUK_ERR_TYPE_ERROR, DUK_STR_NOT_NATIVEFUNCTION);
+	duk_hobject *h = (duk_hobject *) duk__get_tagged_heaphdr_raw(ctx, index, DUK_TAG_OBJECT);
+	if (!(h != NULL && DUK_HOBJECT_IS_NATIVEFUNCTION(h))) {
+		DUK_ERROR_REQUIRE_TYPE_INDEX(thr, index, "nativefunction", DUK_STR_NOT_NATIVEFUNCTION);
 	}
 	return (duk_hnativefunction *) h;
 }
 
-duk_c_function duk_get_c_function(duk_context *ctx, duk_idx_t index) {
+DUK_EXTERNAL duk_c_function duk_get_c_function(duk_context *ctx, duk_idx_t index) {
 	duk_tval *tv;
 	duk_hobject *h;
 	duk_hnativefunction *f;
 
-	DUK_ASSERT(ctx != NULL);
+	DUK_ASSERT_CTX_VALID(ctx);
 
 	tv = duk_get_tval(ctx, index);
 	if (!tv) {
@@ -9986,7 +19696,7 @@ duk_c_function duk_get_c_function(duk_context *ctx, duk_idx_t index) {
 	}
 	h = DUK_TVAL_GET_OBJECT(tv);
 	DUK_ASSERT(h != NULL);
-	
+
 	if (!DUK_HOBJECT_IS_NATIVEFUNCTION(h)) {
 		return NULL;
 	}
@@ -9996,29 +19706,181 @@ duk_c_function duk_get_c_function(duk_context *ctx, duk_idx_t index) {
 	return f->func;
 }
 
-duk_c_function duk_require_c_function(duk_context *ctx, duk_idx_t index) {
+DUK_EXTERNAL duk_c_function duk_require_c_function(duk_context *ctx, duk_idx_t index) {
 	duk_hthread *thr = (duk_hthread *) ctx;
 	duk_c_function ret;
 
+	DUK_ASSERT_CTX_VALID(ctx);
+
 	ret = duk_get_c_function(ctx, index);
 	if (!ret) {
-		DUK_ERROR(thr, DUK_ERR_TYPE_ERROR, DUK_STR_NOT_C_FUNCTION);
+		DUK_ERROR_REQUIRE_TYPE_INDEX(thr, index, "nativefunction", DUK_STR_NOT_NATIVEFUNCTION);
 	}
 	return ret;
 }
 
-duk_context *duk_get_context(duk_context *ctx, duk_idx_t index) {
+DUK_EXTERNAL void duk_require_function(duk_context *ctx, duk_idx_t index) {
+	if (!duk_is_function(ctx, index)) {
+		DUK_ERROR_REQUIRE_TYPE_INDEX((duk_hthread *) ctx, index, "function", DUK_STR_NOT_FUNCTION);
+	}
+}
+
+DUK_EXTERNAL duk_context *duk_get_context(duk_context *ctx, duk_idx_t index) {
+	DUK_ASSERT_CTX_VALID(ctx);
+
 	return (duk_context *) duk_get_hthread(ctx, index);
 }
 
-duk_context *duk_require_context(duk_context *ctx, duk_idx_t index) {
+DUK_EXTERNAL duk_context *duk_require_context(duk_context *ctx, duk_idx_t index) {
+	DUK_ASSERT_CTX_VALID(ctx);
+
 	return (duk_context *) duk_require_hthread(ctx, index);
 }
 
-duk_size_t duk_get_length(duk_context *ctx, duk_idx_t index) {
+DUK_EXTERNAL void *duk_get_heapptr(duk_context *ctx, duk_idx_t index) {
 	duk_tval *tv;
+	void *ret;
 
-	DUK_ASSERT(ctx != NULL);
+	DUK_ASSERT_CTX_VALID(ctx);
+
+	tv = duk_get_tval(ctx, index);
+	if (tv && DUK_TVAL_IS_HEAP_ALLOCATED(tv)) {
+		ret = (void *) DUK_TVAL_GET_HEAPHDR(tv);
+		DUK_ASSERT(ret != NULL);
+		return ret;
+	}
+
+	return (void *) NULL;
+}
+
+DUK_EXTERNAL void *duk_require_heapptr(duk_context *ctx, duk_idx_t index) {
+	duk_hthread *thr = (duk_hthread *) ctx;
+	duk_tval *tv;
+	void *ret;
+
+	DUK_ASSERT_CTX_VALID(ctx);
+
+	tv = duk_require_tval(ctx, index);
+	DUK_ASSERT(tv != NULL);
+	if (DUK_TVAL_IS_HEAP_ALLOCATED(tv)) {
+		ret = (void *) DUK_TVAL_GET_HEAPHDR(tv);
+		DUK_ASSERT(ret != NULL);
+		return ret;
+	}
+
+	DUK_ERROR_REQUIRE_TYPE_INDEX(thr, index, "heapobject", DUK_STR_UNEXPECTED_TYPE);
+	return (void *) NULL;  /* not reachable */
+}
+
+#if 0
+/* This would be pointless: we'd return NULL for both lightfuncs and
+ * unexpected types.
+ */
+duk_hobject *duk_get_hobject_or_lfunc(duk_context *ctx, duk_idx_t index) {
+}
+#endif
+
+/* Useful for internal call sites where we either expect an object (function)
+ * or a lightfunc.  Accepts an object (returned as is) or a lightfunc (coerced
+ * to an object).  Return value is NULL if value is neither an object nor a
+ * lightfunc.
+ */
+DUK_INTERNAL duk_hobject *duk_get_hobject_or_lfunc_coerce(duk_context *ctx, duk_idx_t index) {
+	duk_tval *tv;
+
+	DUK_ASSERT_CTX_VALID(ctx);
+
+	tv = duk_require_tval(ctx, index);
+	DUK_ASSERT(tv != NULL);
+	if (DUK_TVAL_IS_OBJECT(tv)) {
+		return DUK_TVAL_GET_OBJECT(tv);
+	} else if (DUK_TVAL_IS_LIGHTFUNC(tv)) {
+		duk_to_object(ctx, index);
+		return duk_require_hobject(ctx, index);
+	}
+
+	return NULL;
+}
+
+/* Useful for internal call sites where we either expect an object (function)
+ * or a lightfunc.  Returns NULL for a lightfunc.
+ */
+DUK_INTERNAL duk_hobject *duk_require_hobject_or_lfunc(duk_context *ctx, duk_idx_t index) {
+	duk_hthread *thr = (duk_hthread *) ctx;
+	duk_tval *tv;
+
+	DUK_ASSERT_CTX_VALID(ctx);
+
+	tv = duk_require_tval(ctx, index);
+	DUK_ASSERT(tv != NULL);
+	if (DUK_TVAL_IS_OBJECT(tv)) {
+		return DUK_TVAL_GET_OBJECT(tv);
+	} else if (DUK_TVAL_IS_LIGHTFUNC(tv)) {
+		return NULL;
+	}
+	DUK_ERROR_REQUIRE_TYPE_INDEX(thr, index, "object", DUK_STR_NOT_OBJECT);
+	return NULL;  /* not reachable */
+}
+
+/* Useful for internal call sites where we either expect an object (function)
+ * or a lightfunc.  Accepts an object (returned as is) or a lightfunc (coerced
+ * to an object).  Return value is never NULL.
+ */
+DUK_INTERNAL duk_hobject *duk_require_hobject_or_lfunc_coerce(duk_context *ctx, duk_idx_t index) {
+	duk_hthread *thr = (duk_hthread *) ctx;
+	duk_tval *tv;
+
+	DUK_ASSERT_CTX_VALID(ctx);
+
+	tv = duk_require_tval(ctx, index);
+	if (DUK_TVAL_IS_OBJECT(tv)) {
+		return DUK_TVAL_GET_OBJECT(tv);
+	} else if (DUK_TVAL_IS_LIGHTFUNC(tv)) {
+		duk_to_object(ctx, index);
+		return duk_require_hobject(ctx, index);
+	}
+	DUK_ERROR_REQUIRE_TYPE_INDEX(thr, index, "object", DUK_STR_NOT_OBJECT);
+	return NULL;  /* not reachable */
+}
+
+DUK_INTERNAL duk_hobject *duk_get_hobject_with_class(duk_context *ctx, duk_idx_t index, duk_small_uint_t classnum) {
+	duk_hobject *h;
+
+	DUK_ASSERT_CTX_VALID(ctx);
+	DUK_ASSERT_DISABLE(classnum >= 0);  /* unsigned */
+	DUK_ASSERT(classnum <= DUK_HOBJECT_CLASS_MAX);
+
+	h = (duk_hobject *) duk__get_tagged_heaphdr_raw(ctx, index, DUK_TAG_OBJECT);
+	if (h != NULL && DUK_HOBJECT_GET_CLASS_NUMBER(h) != classnum) {
+		h = NULL;
+	}
+	return h;
+}
+
+DUK_INTERNAL duk_hobject *duk_require_hobject_with_class(duk_context *ctx, duk_idx_t index, duk_small_uint_t classnum) {
+	duk_hthread *thr;
+	duk_hobject *h;
+
+	DUK_ASSERT_CTX_VALID(ctx);
+	DUK_ASSERT_DISABLE(classnum >= 0);  /* unsigned */
+	DUK_ASSERT(classnum <= DUK_HOBJECT_CLASS_MAX);
+	thr = (duk_hthread *) ctx;
+
+	h = (duk_hobject *) duk__get_tagged_heaphdr_raw(ctx, index, DUK_TAG_OBJECT);
+	if (!(h != NULL && DUK_HOBJECT_GET_CLASS_NUMBER(h) == classnum)) {
+		duk_hstring *h_class;
+		h_class = DUK_HTHREAD_GET_STRING(thr, DUK_HOBJECT_CLASS_NUMBER_TO_STRIDX(classnum));
+		DUK_UNREF(h_class);
+
+		DUK_ERROR_REQUIRE_TYPE_INDEX(thr, index, (const char *) DUK_HSTRING_GET_DATA(h_class), DUK_STR_UNEXPECTED_TYPE);
+	}
+	return h;
+}
+
+DUK_EXTERNAL duk_size_t duk_get_length(duk_context *ctx, duk_idx_t index) {
+	duk_tval *tv;
+
+	DUK_ASSERT_CTX_VALID(ctx);
 
 	tv = duk_get_tval(ctx, index);
 	if (!tv) {
@@ -10046,8 +19908,17 @@ duk_size_t duk_get_length(duk_context *ctx, duk_idx_t index) {
 		DUK_ASSERT(h != NULL);
 		return (duk_size_t) DUK_HBUFFER_GET_SIZE(h);
 	}
+	case DUK_TAG_LIGHTFUNC: {
+		duk_small_uint_t lf_flags;
+		lf_flags = DUK_TVAL_GET_LIGHTFUNC_FLAGS(tv);
+		return (duk_size_t) DUK_LFUNC_FLAGS_GET_LENGTH(lf_flags);
+	}
+#if defined(DUK_USE_FASTINT)
+	case DUK_TAG_FASTINT:
+#endif
 	default:
 		/* number */
+		DUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv));
 		DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));
 		return 0;
 	}
@@ -10055,11 +19926,11 @@ duk_size_t duk_get_length(duk_context *ctx, duk_idx_t index) {
 	DUK_UNREACHABLE();
 }
 
-void duk_set_length(duk_context *ctx, duk_idx_t index, duk_size_t length) {
+DUK_INTERNAL void duk_set_length(duk_context *ctx, duk_idx_t index, duk_size_t length) {
 	duk_hthread *thr = (duk_hthread *) ctx;
 	duk_hobject *h;
 
-	DUK_ASSERT(ctx != NULL);
+	DUK_ASSERT_CTX_VALID(ctx);
 
 	h = duk_get_hobject(ctx, index);
 	if (!h) {
@@ -10079,7 +19950,7 @@ void duk_set_length(duk_context *ctx, duk_idx_t index, duk_size_t length) {
 
 /* E5 Section 8.12.8 */
 
-static duk_bool_t duk__defaultvalue_coerce_attempt(duk_context *ctx, duk_idx_t index, duk_small_int_t func_stridx) {
+DUK_LOCAL duk_bool_t duk__defaultvalue_coerce_attempt(duk_context *ctx, duk_idx_t index, duk_small_int_t func_stridx) {
 	if (duk_get_prop_stridx(ctx, index, func_stridx)) {
 		/* [ ... func ] */
 		if (duk_is_callable(ctx, -1)) {
@@ -10096,28 +19967,23 @@ static duk_bool_t duk__defaultvalue_coerce_attempt(duk_context *ctx, duk_idx_t i
 	return 0;
 }
 
-void duk_to_defaultvalue(duk_context *ctx, duk_idx_t index, duk_int_t hint) {
+DUK_EXTERNAL void duk_to_defaultvalue(duk_context *ctx, duk_idx_t index, duk_int_t hint) {
 	duk_hthread *thr = (duk_hthread *) ctx;
 	duk_hobject *obj;
 	/* inline initializer for coercers[] is not allowed by old compilers like BCC */
 	duk_small_int_t coercers[2];
 
-	DUK_ASSERT(ctx != NULL);
+	DUK_ASSERT_CTX_VALID(ctx);
 	DUK_ASSERT(thr != NULL);
 
 	coercers[0] = DUK_STRIDX_VALUE_OF;
 	coercers[1] = DUK_STRIDX_TO_STRING;
 
 	index = duk_require_normalize_index(ctx, index);
-
-	if (!duk_is_object(ctx, index)) {
-		DUK_ERROR(thr, DUK_ERR_TYPE_ERROR, DUK_STR_NOT_OBJECT);
-	}
-	obj = duk_get_hobject(ctx, index);
-	DUK_ASSERT(obj != NULL);
+	obj = duk_require_hobject_or_lfunc(ctx, index);
 
 	if (hint == DUK_HINT_NONE) {
-		if (DUK_HOBJECT_GET_CLASS_NUMBER(obj) == DUK_HOBJECT_CLASS_DATE) {
+		if (obj != NULL && DUK_HOBJECT_GET_CLASS_NUMBER(obj) == DUK_HOBJECT_CLASS_DATE) {
 			hint = DUK_HINT_STRING;
 		} else {
 			hint = DUK_HINT_NUMBER;
@@ -10140,65 +20006,52 @@ void duk_to_defaultvalue(duk_context *ctx, duk_idx_t index, duk_int_t hint) {
 	DUK_ERROR(thr, DUK_ERR_TYPE_ERROR, DUK_STR_DEFAULTVALUE_COERCE_FAILED);
 }
 
-void duk_to_undefined(duk_context *ctx, duk_idx_t index) {
+DUK_EXTERNAL void duk_to_undefined(duk_context *ctx, duk_idx_t index) {
 	duk_hthread *thr = (duk_hthread *) ctx;
 	duk_tval *tv;
-	duk_tval tv_tmp;
 
-	DUK_ASSERT(ctx != NULL);
+	DUK_ASSERT_CTX_VALID(ctx);
 	DUK_UNREF(thr);
 
 	tv = duk_require_tval(ctx, index);
 	DUK_ASSERT(tv != NULL);
-	DUK_TVAL_SET_TVAL(&tv_tmp, tv);
-	DUK_TVAL_SET_UNDEFINED_ACTUAL(tv);  /* no need to incref */
-	DUK_TVAL_DECREF(thr, &tv_tmp);  /* side effects */
+	DUK_TVAL_SET_UNDEFINED_UPDREF(thr, tv);  /* side effects */
 }
 
-void duk_to_null(duk_context *ctx, duk_idx_t index) {
+DUK_EXTERNAL void duk_to_null(duk_context *ctx, duk_idx_t index) {
 	duk_hthread *thr = (duk_hthread *) ctx;
 	duk_tval *tv;
-	duk_tval tv_tmp;
 
-	DUK_ASSERT(ctx != NULL);
+	DUK_ASSERT_CTX_VALID(ctx);
 	DUK_UNREF(thr);
 
 	tv = duk_require_tval(ctx, index);
 	DUK_ASSERT(tv != NULL);
-	DUK_TVAL_SET_TVAL(&tv_tmp, tv);
-	DUK_TVAL_SET_NULL(tv);  /* no need to incref */
-	DUK_TVAL_DECREF(thr, &tv_tmp);  /* side effects */
+	DUK_TVAL_SET_NULL_UPDREF(thr, tv);  /* side effects */
 }
 
 /* E5 Section 9.1 */
-void duk_to_primitive(duk_context *ctx, duk_idx_t index, duk_int_t hint) {
-	duk_tval *tv;
-
-	DUK_ASSERT(ctx != NULL);
+DUK_EXTERNAL void duk_to_primitive(duk_context *ctx, duk_idx_t index, duk_int_t hint) {
+	DUK_ASSERT_CTX_VALID(ctx);
 	DUK_ASSERT(hint == DUK_HINT_NONE || hint == DUK_HINT_NUMBER || hint == DUK_HINT_STRING);
 
 	index = duk_require_normalize_index(ctx, index);
 
-	tv = duk_require_tval(ctx, index);
-	DUK_ASSERT(tv != NULL);
-
-	if (DUK_TVAL_GET_TAG(tv) != DUK_TAG_OBJECT) {
+	if (!duk_check_type_mask(ctx, index, DUK_TYPE_MASK_OBJECT |
+	                                     DUK_TYPE_MASK_LIGHTFUNC)) {
 		/* everything except object stay as is */
 		return;
 	}
-	DUK_ASSERT(DUK_TVAL_IS_OBJECT(tv));
-
 	duk_to_defaultvalue(ctx, index, hint);
 }
 
 /* E5 Section 9.2 */
-duk_bool_t duk_to_boolean(duk_context *ctx, duk_idx_t index) {
+DUK_EXTERNAL duk_bool_t duk_to_boolean(duk_context *ctx, duk_idx_t index) {
 	duk_hthread *thr = (duk_hthread *) ctx;
 	duk_tval *tv;
-	duk_tval tv_tmp;
 	duk_bool_t val;
 
-	DUK_ASSERT(ctx != NULL);
+	DUK_ASSERT_CTX_VALID(ctx);
 	DUK_UNREF(thr);
 
 	index = duk_require_normalize_index(ctx, index);
@@ -10211,29 +20064,25 @@ duk_bool_t duk_to_boolean(duk_context *ctx, duk_idx_t index) {
 
 	/* Note: no need to re-lookup tv, conversion is side effect free */
 	DUK_ASSERT(tv != NULL);
-	DUK_TVAL_SET_TVAL(&tv_tmp, tv);
-	DUK_TVAL_SET_BOOLEAN(tv, val);  /* no need to incref */
-	DUK_TVAL_DECREF(thr, &tv_tmp);  /* side effects */
+	DUK_TVAL_SET_BOOLEAN_UPDREF(thr, tv, val);  /* side effects */
 	return val;
 }
 
-duk_double_t duk_to_number(duk_context *ctx, duk_idx_t index) {
+DUK_EXTERNAL duk_double_t duk_to_number(duk_context *ctx, duk_idx_t index) {
 	duk_hthread *thr = (duk_hthread *) ctx;
 	duk_tval *tv;
-	duk_tval tv_tmp;
 	duk_double_t d;
 
-	DUK_ASSERT(ctx != NULL);
+	DUK_ASSERT_CTX_VALID(ctx);
 
 	tv = duk_require_tval(ctx, index);
 	DUK_ASSERT(tv != NULL);
+	/* XXX: fastint? */
 	d = duk_js_tonumber(thr, tv);
 
 	/* Note: need to re-lookup because ToNumber() may have side effects */
 	tv = duk_require_tval(ctx, index);
-	DUK_TVAL_SET_TVAL(&tv_tmp, tv);
-	DUK_TVAL_SET_NUMBER(tv, d);  /* no need to incref */
-	DUK_TVAL_DECREF(thr, &tv_tmp);  /* side effects */
+	DUK_TVAL_SET_NUMBER_UPDREF(thr, tv, d);  /* side effects */
 	return d;
 }
 
@@ -10243,114 +20092,163 @@ duk_double_t duk_to_number(duk_context *ctx, duk_idx_t index) {
 
 typedef duk_double_t (*duk__toint_coercer)(duk_hthread *thr, duk_tval *tv);
 
-duk_double_t duk__to_int_uint_helper(duk_context *ctx, duk_idx_t index, duk__toint_coercer coerce_func) {
+DUK_LOCAL duk_double_t duk__to_int_uint_helper(duk_context *ctx, duk_idx_t index, duk__toint_coercer coerce_func) {
 	duk_hthread *thr = (duk_hthread *) ctx;
 	duk_tval *tv;
-	duk_tval tv_tmp;
 	duk_double_t d;
 
-	DUK_ASSERT(ctx != NULL);
+	DUK_ASSERT_CTX_VALID(ctx);
 
 	tv = duk_require_tval(ctx, index);
 	DUK_ASSERT(tv != NULL);
 	d = coerce_func(thr, tv);
 
+	/* XXX: fastint? */
+
 	/* Relookup in case coerce_func() has side effects, e.g. ends up coercing an object */
 	tv = duk_require_tval(ctx, index);
-	DUK_TVAL_SET_TVAL(&tv_tmp, tv);
-	DUK_TVAL_SET_NUMBER(tv, d);  /* no need to incref */
-	DUK_TVAL_DECREF(thr, &tv_tmp);  /* side effects */
+	DUK_TVAL_SET_NUMBER_UPDREF(thr, tv, d);  /* side effects */
 	return d;
 }
 
-duk_int_t duk_to_int(duk_context *ctx, duk_idx_t index) {
+DUK_EXTERNAL duk_int_t duk_to_int(duk_context *ctx, duk_idx_t index) {
 	/* Value coercion (in stack): ToInteger(), E5 Section 9.4
 	 * API return value coercion: custom
 	 */
-	return (duk_int_t) duk__api_coerce_d2i(duk__to_int_uint_helper(ctx, index, duk_js_tointeger));
+	DUK_ASSERT_CTX_VALID(ctx);
+	(void) duk__to_int_uint_helper(ctx, index, duk_js_tointeger);
+	return (duk_int_t) duk__api_coerce_d2i(ctx, index, 0 /*require*/);
 }
 
-duk_uint_t duk_to_uint(duk_context *ctx, duk_idx_t index) {
+DUK_EXTERNAL duk_uint_t duk_to_uint(duk_context *ctx, duk_idx_t index) {
 	/* Value coercion (in stack): ToInteger(), E5 Section 9.4
 	 * API return value coercion: custom
 	 */
-	return (duk_uint_t) duk__api_coerce_d2ui(duk__to_int_uint_helper(ctx, index, duk_js_tointeger));
+	DUK_ASSERT_CTX_VALID(ctx);
+	(void) duk__to_int_uint_helper(ctx, index, duk_js_tointeger);
+	return (duk_uint_t) duk__api_coerce_d2ui(ctx, index, 0 /*require*/);
 }
 
-duk_int32_t duk_to_int32(duk_context *ctx, duk_idx_t index) {
+DUK_EXTERNAL duk_int32_t duk_to_int32(duk_context *ctx, duk_idx_t index) {
 	duk_hthread *thr = (duk_hthread *) ctx;
 	duk_tval *tv;
-	duk_tval tv_tmp;
 	duk_int32_t ret;
 
-	DUK_ASSERT(ctx != NULL);
+	DUK_ASSERT_CTX_VALID(ctx);
 
 	tv = duk_require_tval(ctx, index);
 	DUK_ASSERT(tv != NULL);
 	ret = duk_js_toint32(thr, tv);
 
-	/* XXX: avoid double coercion with fastints */
 	/* Relookup in case coerce_func() has side effects, e.g. ends up coercing an object */
 	tv = duk_require_tval(ctx, index);
-	DUK_TVAL_SET_TVAL(&tv_tmp, tv);
-	DUK_TVAL_SET_NUMBER(tv, (duk_double_t) ret);  /* no need to incref */
-	DUK_TVAL_DECREF(thr, &tv_tmp);  /* side effects */
+#if defined(DUK_USE_FASTINT)
+	DUK_TVAL_SET_FASTINT_I32_UPDREF(thr, tv, ret);  /* side effects */
 	return ret;
+#else
+	DUK_TVAL_SET_NUMBER_UPDREF(thr, tv, (duk_double_t) ret);  /* side effects */
+	return ret;
+#endif
 }
 
-duk_uint32_t duk_to_uint32(duk_context *ctx, duk_idx_t index) {
+DUK_EXTERNAL duk_uint32_t duk_to_uint32(duk_context *ctx, duk_idx_t index) {
 	duk_hthread *thr = (duk_hthread *) ctx;
 	duk_tval *tv;
-	duk_tval tv_tmp;
 	duk_uint32_t ret;
 
-	DUK_ASSERT(ctx != NULL);
+	DUK_ASSERT_CTX_VALID(ctx);
 
 	tv = duk_require_tval(ctx, index);
 	DUK_ASSERT(tv != NULL);
 	ret = duk_js_touint32(thr, tv);
 
-	/* XXX: avoid double coercion with fastints */
 	/* Relookup in case coerce_func() has side effects, e.g. ends up coercing an object */
 	tv = duk_require_tval(ctx, index);
-	DUK_TVAL_SET_TVAL(&tv_tmp, tv);
-	DUK_TVAL_SET_NUMBER(tv, (duk_double_t) ret);  /* no need to incref */
-	DUK_TVAL_DECREF(thr, &tv_tmp);  /* side effects */
+#if defined(DUK_USE_FASTINT)
+	DUK_TVAL_SET_FASTINT_U32_UPDREF(thr, tv, ret);  /* side effects */
+	return ret;
+#else
+	DUK_TVAL_SET_NUMBER_UPDREF(thr, tv, (duk_double_t) ret);  /* side effects */
+#endif
 	return ret;
 }
 
-duk_uint16_t duk_to_uint16(duk_context *ctx, duk_idx_t index) {
+DUK_EXTERNAL duk_uint16_t duk_to_uint16(duk_context *ctx, duk_idx_t index) {
 	duk_hthread *thr = (duk_hthread *) ctx;
 	duk_tval *tv;
-	duk_tval tv_tmp;
 	duk_uint16_t ret;
 
-	DUK_ASSERT(ctx != NULL);
+	DUK_ASSERT_CTX_VALID(ctx);
 
 	tv = duk_require_tval(ctx, index);
 	DUK_ASSERT(tv != NULL);
 	ret = duk_js_touint16(thr, tv);
 
-	/* XXX: avoid double coercion with fastints */
 	/* Relookup in case coerce_func() has side effects, e.g. ends up coercing an object */
 	tv = duk_require_tval(ctx, index);
-	DUK_TVAL_SET_TVAL(&tv_tmp, tv);
-	DUK_TVAL_SET_NUMBER(tv, (duk_double_t) ret);  /* no need to incref */
-	DUK_TVAL_DECREF(thr, &tv_tmp);  /* side effects */
+#if defined(DUK_USE_FASTINT)
+	DUK_TVAL_SET_FASTINT_U32_UPDREF(thr, tv, ret);  /* side effects */
+	return ret;
+#else
+	DUK_TVAL_SET_NUMBER_UPDREF(thr, tv, (duk_double_t) ret);  /* side effects */
+#endif
+	return ret;
+}
+
+#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
+/* Special coercion for Uint8ClampedArray. */
+DUK_INTERNAL duk_uint8_t duk_to_uint8clamped(duk_context *ctx, duk_idx_t index) {
+	duk_double_t d;
+	duk_double_t t;
+	duk_uint8_t ret;
+
+	/* XXX: Simplify this algorithm, should be possible to come up with
+	 * a shorter and faster algorithm by inspecting IEEE representation
+	 * directly.
+	 */
+
+	d = duk_to_number(ctx, index);
+	if (d <= 0.0) {
+		return 0;
+	} else if (d >= 255) {
+		return 255;
+	} else if (DUK_ISNAN(d)) {
+		/* Avoid NaN-to-integer coercion as it is compiler specific. */
+		return 0;
+	}
+
+	t = d - DUK_FLOOR(d);
+	if (t == 0.5) {
+		/* Exact halfway, round to even. */
+		ret = (duk_uint8_t) d;
+		ret = (ret + 1) & 0xfe;  /* Example: d=3.5, t=0.5 -> ret = (3 + 1) & 0xfe = 4 & 0xfe = 4
+		                          * Example: d=4.5, t=0.5 -> ret = (4 + 1) & 0xfe = 5 & 0xfe = 4
+		                          */
+	} else {
+		/* Not halfway, round to nearest. */
+		ret = (duk_uint8_t) (d + 0.5);
+	}
 	return ret;
 }
+#endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
+
+DUK_EXTERNAL const char *duk_to_lstring(duk_context *ctx, duk_idx_t index, duk_size_t *out_len) {
+	DUK_ASSERT_CTX_VALID(ctx);
 
-const char *duk_to_lstring(duk_context *ctx, duk_idx_t index, duk_size_t *out_len) {
 	(void) duk_to_string(ctx, index);
 	return duk_require_lstring(ctx, index, out_len);
 }
 
-static duk_ret_t duk__safe_to_string_raw(duk_context *ctx) {
+DUK_LOCAL duk_ret_t duk__safe_to_string_raw(duk_context *ctx) {
+	DUK_ASSERT_CTX_VALID(ctx);
+
 	duk_to_string(ctx, -1);
 	return 1;
 }
 
-const char *duk_safe_to_lstring(duk_context *ctx, duk_idx_t index, duk_size_t *out_len) {
+DUK_EXTERNAL const char *duk_safe_to_lstring(duk_context *ctx, duk_idx_t index, duk_size_t *out_len) {
+	DUK_ASSERT_CTX_VALID(ctx);
+
 	index = duk_require_normalize_index(ctx, index);
 
 	/* We intentionally ignore the duk_safe_call() return value and only
@@ -10374,37 +20272,113 @@ const char *duk_safe_to_lstring(duk_context *ctx, duk_idx_t index, duk_size_t *o
 		;
 	}
 	DUK_ASSERT(duk_is_string(ctx, -1));
+	DUK_ASSERT(duk_get_string(ctx, -1) != NULL);
 
 	duk_replace(ctx, index);
-	return duk_require_lstring(ctx, index, out_len);
+	return duk_get_lstring(ctx, index, out_len);
+}
+
+#if defined(DUK_USE_DEBUGGER_SUPPORT)  /* only needed by debugger for now */
+DUK_EXTERNAL duk_hstring *duk_safe_to_hstring(duk_context *ctx, duk_idx_t index) {
+	(void) duk_safe_to_string(ctx, index);
+	DUK_ASSERT(duk_is_string(ctx, index));
+	DUK_ASSERT(duk_get_hstring(ctx, index) != NULL);
+	return duk_get_hstring(ctx, index);
+}
+#endif
+
+/* Coerce top into Object.prototype.toString() output. */
+DUK_INTERNAL void duk_to_object_class_string_top(duk_context *ctx) {
+	duk_hthread *thr;
+	duk_uint_t typemask;
+	duk_hstring *h_strclass;
+
+	DUK_ASSERT_CTX_VALID(ctx);
+	thr = (duk_hthread *) ctx;
+
+	typemask = duk_get_type_mask(ctx, -1);
+	if (typemask & DUK_TYPE_MASK_UNDEFINED) {
+		h_strclass = DUK_HTHREAD_STRING_UC_UNDEFINED(thr);
+	} else if (typemask & DUK_TYPE_MASK_NULL) {
+		h_strclass = DUK_HTHREAD_STRING_UC_NULL(thr);
+	} else {
+		duk_hobject *h_obj;
+
+		duk_to_object(ctx, -1);
+		h_obj = duk_get_hobject(ctx, -1);
+		DUK_ASSERT(h_obj != NULL);
+
+		h_strclass = DUK_HOBJECT_GET_CLASS_STRING(thr->heap, h_obj);
+	}
+	DUK_ASSERT(h_strclass != NULL);
+
+	duk_pop(ctx);
+	duk_push_sprintf(ctx, "[object %s]", (const char *) DUK_HSTRING_GET_DATA(h_strclass));
+}
+
+#if !defined(DUK_USE_PARANOID_ERRORS)
+DUK_INTERNAL void duk_push_hobject_class_string(duk_context *ctx, duk_hobject *h) {
+	duk_hthread *thr;
+	duk_hstring *h_strclass;
+
+	DUK_ASSERT_CTX_VALID(ctx);
+	DUK_ASSERT(h != NULL);
+	thr = (duk_hthread *) ctx;
+
+	h_strclass = DUK_HOBJECT_GET_CLASS_STRING(thr->heap, h);
+	DUK_ASSERT(h_strclass != NULL);
+	duk_push_sprintf(ctx, "[object %s]", (const char *) DUK_HSTRING_GET_DATA(h_strclass));
 }
+#endif  /* !DUK_USE_PARANOID_ERRORS */
 
 /* XXX: other variants like uint, u32 etc */
-duk_int_t duk_to_int_clamped_raw(duk_context *ctx, duk_idx_t index, duk_int_t minval, duk_int_t maxval, duk_bool_t *out_clamped) {
+DUK_INTERNAL duk_int_t duk_to_int_clamped_raw(duk_context *ctx, duk_idx_t index, duk_int_t minval, duk_int_t maxval, duk_bool_t *out_clamped) {
 	duk_hthread *thr = (duk_hthread *) ctx;
 	duk_tval *tv;
 	duk_tval tv_tmp;
-	duk_double_t d;
+	duk_double_t d, dmin, dmax;
+	duk_int_t res;
 	duk_bool_t clamped = 0;
 
-	DUK_ASSERT(ctx != NULL);
+	DUK_ASSERT_CTX_VALID(ctx);
 
 	tv = duk_require_tval(ctx, index);
 	DUK_ASSERT(tv != NULL);
 	d = duk_js_tointeger(thr, tv);  /* E5 Section 9.4, ToInteger() */
 
-	if (d < (duk_double_t) minval) {
+	dmin = (duk_double_t) minval;
+	dmax = (duk_double_t) maxval;
+
+	if (d < dmin) {
 		clamped = 1;
-		d = (duk_double_t) minval;
-	} else if (d > (duk_double_t) maxval) {
+		res = minval;
+		d = dmin;
+	} else if (d > dmax) {
 		clamped = 1;
-		d = (duk_double_t) maxval;
+		res = maxval;
+		d = dmax;
+	} else {
+		res = (duk_int_t) d;
 	}
+	/* 'd' and 'res' agree here */
 
-	/* relookup in case duk_js_tointeger() ends up e.g. coercing an object */
+	/* Relookup in case duk_js_tointeger() ends up e.g. coercing an object. */
 	tv = duk_require_tval(ctx, index);
 	DUK_TVAL_SET_TVAL(&tv_tmp, tv);
+#if defined(DUK_USE_FASTINT)
+#if (DUK_INT_MAX <= 0x7fffffffL)
+	DUK_TVAL_SET_FASTINT_I32(tv, res);
+#else
+	/* Clamping needed if duk_int_t is 64 bits. */
+	if (res >= DUK_FASTINT_MIN && res <= DUK_FASTINT_MAX) {
+		DUK_TVAL_SET_FASTINT(tv, res);
+	} else {
+		DUK_TVAL_SET_NUMBER(tv, d);
+	}
+#endif
+#else
 	DUK_TVAL_SET_NUMBER(tv, d);  /* no need to incref */
+#endif
 	DUK_TVAL_DECREF(thr, &tv_tmp);  /* side effects */
 
 	if (out_clamped) {
@@ -10416,22 +20390,24 @@ duk_int_t duk_to_int_clamped_raw(duk_context *ctx, duk_idx_t index, duk_int_t mi
 		}
 	}
 
-	return (duk_int_t) d;
+	return res;
 }
 
-duk_int_t duk_to_int_clamped(duk_context *ctx, duk_idx_t index, duk_idx_t minval, duk_idx_t maxval) {
+DUK_INTERNAL duk_int_t duk_to_int_clamped(duk_context *ctx, duk_idx_t index, duk_idx_t minval, duk_idx_t maxval) {
 	duk_bool_t dummy;
 	return duk_to_int_clamped_raw(ctx, index, minval, maxval, &dummy);
 }
 
-duk_int_t duk_to_int_check_range(duk_context *ctx, duk_idx_t index, duk_int_t minval, duk_int_t maxval) {
+DUK_INTERNAL duk_int_t duk_to_int_check_range(duk_context *ctx, duk_idx_t index, duk_int_t minval, duk_int_t maxval) {
 	return duk_to_int_clamped_raw(ctx, index, minval, maxval, NULL);  /* out_clamped==NULL -> RangeError if outside range */
 }
 
-const char *duk_to_string(duk_context *ctx, duk_idx_t index) {
+DUK_EXTERNAL const char *duk_to_string(duk_context *ctx, duk_idx_t index) {
+	duk_hthread *thr = (duk_hthread *) ctx;
 	duk_tval *tv;
 
-	DUK_ASSERT(ctx != NULL);
+	DUK_ASSERT_CTX_VALID(ctx);
+	DUK_UNREF(thr);
 
 	index = duk_require_normalize_index(ctx, index);
 
@@ -10470,7 +20446,7 @@ const char *duk_to_string(duk_context *ctx, duk_idx_t index) {
 
 		DUK_ASSERT(h != NULL);
 		duk_push_lstring(ctx,
-		                 (const char *) DUK_HBUFFER_GET_DATA_PTR(h),
+		                 (const char *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h),
 		                 (duk_size_t) DUK_HBUFFER_GET_SIZE(h));
 		break;
 	}
@@ -10487,8 +20463,17 @@ const char *duk_to_string(duk_context *ctx, duk_idx_t index) {
 		}
 		break;
 	}
+	case DUK_TAG_LIGHTFUNC: {
+		/* Should match Function.prototype.toString() */
+		duk_push_lightfunc_tostring(ctx, tv);
+		break;
+	}
+#if defined(DUK_USE_FASTINT)
+	case DUK_TAG_FASTINT:
+#endif
 	default: {
 		/* number */
+		DUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv));
 		DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));
 		duk_push_tval(ctx, tv);
 		duk_numconv_stringify(ctx,
@@ -10505,57 +20490,67 @@ const char *duk_to_string(duk_context *ctx, duk_idx_t index) {
 	return duk_require_string(ctx, index);
 }
 
-duk_hstring *duk_to_hstring(duk_context *ctx, duk_idx_t index) {
+DUK_INTERNAL duk_hstring *duk_to_hstring(duk_context *ctx, duk_idx_t index) {
 	duk_hstring *ret;
-	DUK_ASSERT(ctx != NULL);
+	DUK_ASSERT_CTX_VALID(ctx);
 	duk_to_string(ctx, index);
 	ret = duk_get_hstring(ctx, index);
 	DUK_ASSERT(ret != NULL);
 	return ret;
 }
 
-static void *duk__to_buffer_raw(duk_context *ctx, duk_idx_t index, duk_size_t *out_size, duk_small_int_t buf_dynamic, duk_small_int_t buf_dontcare) {
+DUK_EXTERNAL void *duk_to_buffer_raw(duk_context *ctx, duk_idx_t index, duk_size_t *out_size, duk_uint_t mode) {
+	duk_hthread *thr = (duk_hthread *) ctx;
 	duk_hbuffer *h_buf;
 	const duk_uint8_t *src_data;
 	duk_size_t src_size;
 	duk_uint8_t *dst_data;
 
+	DUK_ASSERT_CTX_VALID(ctx);
+	DUK_UNREF(thr);
+
 	index = duk_require_normalize_index(ctx, index);
 
 	h_buf = duk_get_hbuffer(ctx, index);
 	if (h_buf != NULL) {
-		/* Buffer is kept as is: note that fixed/dynamic nature of
-		 * the buffer is not changed.
+		/* Buffer is kept as is, with the fixed/dynamic nature of the
+		 * buffer only changed if requested.  An external buffer
+		 * is converted into a non-external dynamic buffer in a
+		 * duk_to_dynamic_buffer() call.
 		 */
-		duk_small_int_t tmp;
+		duk_uint_t tmp;
+		duk_uint8_t *tmp_ptr;
 
-		src_data = (const duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(h_buf);
+		tmp_ptr = (duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h_buf);
+		src_data = (const duk_uint8_t *) tmp_ptr;
 		src_size = DUK_HBUFFER_GET_SIZE(h_buf);
 
-		tmp = (DUK_HBUFFER_HAS_DYNAMIC(h_buf) ? 1 : 0);
-		if (((tmp ^ buf_dynamic) == 0) || buf_dontcare) {
+		tmp = (DUK_HBUFFER_HAS_DYNAMIC(h_buf) ? DUK_BUF_MODE_DYNAMIC : DUK_BUF_MODE_FIXED);
+		if ((tmp == mode && !DUK_HBUFFER_HAS_EXTERNAL(h_buf)) ||
+		    mode == DUK_BUF_MODE_DONTCARE) {
 			/* Note: src_data may be NULL if input is a zero-size
 			 * dynamic buffer.
 			 */
-			dst_data = (duk_uint8_t *) src_data;
+			dst_data = tmp_ptr;
 			goto skip_copy;
 		}
 	} else {
 		/* Non-buffer value is first ToString() coerced, then converted
-		 * to a fixed size buffer.
+		 * to a buffer (fixed buffer is used unless a dynamic buffer is
+		 * explicitly requested).
 		 */
 
 		src_data = (const duk_uint8_t *) duk_to_lstring(ctx, index, &src_size);
 	}
 
-	dst_data = duk_push_buffer(ctx, src_size, buf_dynamic);
+	dst_data = (duk_uint8_t *) duk_push_buffer(ctx, src_size, (mode == DUK_BUF_MODE_DYNAMIC) /*dynamic*/);
 	if (DUK_LIKELY(src_size > 0)) {
 		/* When src_size == 0, src_data may be NULL (if source
 		 * buffer is dynamic), and dst_data may be NULL (if
 		 * target buffer is dynamic).  Avoid zero-size memcpy()
 		 * with an invalid pointer.
 		 */
-		DUK_MEMCPY(dst_data, src_data, src_size);
+		DUK_MEMCPY((void *) dst_data, (const void *) src_data, (size_t) src_size);
 	}
 	duk_replace(ctx, index);
  skip_copy:
@@ -10566,23 +20561,11 @@ static void *duk__to_buffer_raw(duk_context *ctx, duk_idx_t index, duk_size_t *o
 	return dst_data;
 }
 
-void *duk_to_buffer(duk_context *ctx, duk_idx_t index, duk_size_t *out_size) {
-	return duk__to_buffer_raw(ctx, index, out_size, 0 /*buf_dynamic*/, 1 /*buf_dontcare*/);
-}
-
-void *duk_to_fixed_buffer(duk_context *ctx, duk_idx_t index, duk_size_t *out_size) {
-	return duk__to_buffer_raw(ctx, index, out_size, 0 /*buf_dynamic*/, 0 /*buf_dontcare*/);
-}
-
-void *duk_to_dynamic_buffer(duk_context *ctx, duk_idx_t index, duk_size_t *out_size) {
-	return duk__to_buffer_raw(ctx, index, out_size, 1 /*buf_dynamic*/, 0 /*buf_dontcare*/);
-}
-
-void *duk_to_pointer(duk_context *ctx, duk_idx_t index) {
+DUK_EXTERNAL void *duk_to_pointer(duk_context *ctx, duk_idx_t index) {
 	duk_tval *tv;
 	void *res;
 
-	DUK_ASSERT(ctx != NULL);
+	DUK_ASSERT_CTX_VALID(ctx);
 
 	index = duk_require_normalize_index(ctx, index);
 
@@ -10606,8 +20589,20 @@ void *duk_to_pointer(duk_context *ctx, duk_idx_t index) {
 		 */
 		res = (void *) DUK_TVAL_GET_HEAPHDR(tv);
 		break;
+	case DUK_TAG_LIGHTFUNC:
+		/* Function pointers do not always cast correctly to void *
+		 * (depends on memory and segmentation model for instance),
+		 * so they coerce to NULL.
+		 */
+		res = NULL;
+		break;
+#if defined(DUK_USE_FASTINT)
+	case DUK_TAG_FASTINT:
+#endif
 	default:
 		/* number */
+		DUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv));
+		DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));
 		res = NULL;
 		break;
 	}
@@ -10617,13 +20612,13 @@ void *duk_to_pointer(duk_context *ctx, duk_idx_t index) {
 	return res;
 }
 
-void duk_to_object(duk_context *ctx, duk_idx_t index) {
+DUK_EXTERNAL void duk_to_object(duk_context *ctx, duk_idx_t index) {
 	duk_hthread *thr = (duk_hthread *) ctx;
 	duk_tval *tv;
-	duk_uint_t shared_flags = 0;   /* shared flags for a subset of types */
-	duk_small_int_t shared_proto = 0;
+	duk_uint_t flags = 0;   /* shared flags for a subset of types */
+	duk_small_int_t proto = 0;
 
-	DUK_ASSERT(ctx != NULL);
+	DUK_ASSERT_CTX_VALID(ctx);
 
 	index = duk_require_normalize_index(ctx, index);
 
@@ -10637,16 +20632,16 @@ void duk_to_object(duk_context *ctx, duk_idx_t index) {
 		break;
 	}
 	case DUK_TAG_BOOLEAN: {
-		shared_flags = DUK_HOBJECT_FLAG_EXTENSIBLE |
-		               DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_BOOLEAN);
-		shared_proto = DUK_BIDX_BOOLEAN_PROTOTYPE;
+		flags = DUK_HOBJECT_FLAG_EXTENSIBLE |
+		        DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_BOOLEAN);
+		proto = DUK_BIDX_BOOLEAN_PROTOTYPE;
 		goto create_object;
 	}
 	case DUK_TAG_STRING: {
-		shared_flags = DUK_HOBJECT_FLAG_EXTENSIBLE |
-		               DUK_HOBJECT_FLAG_EXOTIC_STRINGOBJ |
-		               DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_STRING);
-		shared_proto = DUK_BIDX_STRING_PROTOTYPE;
+		flags = DUK_HOBJECT_FLAG_EXTENSIBLE |
+		        DUK_HOBJECT_FLAG_EXOTIC_STRINGOBJ |
+		        DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_STRING);
+		proto = DUK_BIDX_STRING_PROTOTYPE;
 		goto create_object;
 	}
 	case DUK_TAG_OBJECT: {
@@ -10654,40 +20649,119 @@ void duk_to_object(duk_context *ctx, duk_idx_t index) {
 		break;
 	}
 	case DUK_TAG_BUFFER: {
-		shared_flags = DUK_HOBJECT_FLAG_EXTENSIBLE |
-		               DUK_HOBJECT_FLAG_EXOTIC_BUFFEROBJ |
-		               DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_BUFFER);
-		shared_proto = DUK_BIDX_BUFFER_PROTOTYPE;
-		goto create_object;
+		/* A plain buffer coerces to a Duktape.Buffer because it's the
+		 * object counterpart of the plain buffer value.  But it might
+		 * still make more sense to produce an ArrayBuffer here?
+		 */
+
+		duk_hbufferobject *h_bufobj;
+		duk_hbuffer *h_val;
+
+		h_val = DUK_TVAL_GET_BUFFER(tv);
+		DUK_ASSERT(h_val != NULL);
+
+		h_bufobj = duk_push_bufferobject_raw(ctx,
+		                                     DUK_HOBJECT_FLAG_EXTENSIBLE |
+		                                     DUK_HOBJECT_FLAG_BUFFEROBJECT |
+		                                     DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_BUFFER),
+		                                     DUK_BIDX_BUFFER_PROTOTYPE);
+		DUK_ASSERT(h_bufobj != NULL);
+		DUK_ASSERT(DUK_HOBJECT_HAS_EXTENSIBLE((duk_hobject *) h_bufobj));
+		DUK_ASSERT(DUK_HOBJECT_IS_BUFFEROBJECT((duk_hobject *) h_bufobj));
+
+		h_bufobj->buf = h_val;
+		DUK_HBUFFER_INCREF(thr, h_val);
+		DUK_ASSERT(h_bufobj->offset == 0);
+		h_bufobj->length = (duk_uint_t) DUK_HBUFFER_GET_SIZE(h_val);
+		DUK_ASSERT(h_bufobj->shift == 0);
+		DUK_ASSERT(h_bufobj->elem_type == DUK_HBUFFEROBJECT_ELEM_UINT8);
+
+		DUK_ASSERT_HBUFFEROBJECT_VALID(h_bufobj);
+		goto replace_value;
 	}
 	case DUK_TAG_POINTER: {
-		shared_flags = DUK_HOBJECT_FLAG_EXTENSIBLE |
-		               DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_POINTER);
-		shared_proto = DUK_BIDX_POINTER_PROTOTYPE;
+		flags = DUK_HOBJECT_FLAG_EXTENSIBLE |
+		        DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_POINTER);
+		proto = DUK_BIDX_POINTER_PROTOTYPE;
 		goto create_object;
 	}
+	case DUK_TAG_LIGHTFUNC: {
+		/* Lightfunc coerces to a Function instance with concrete
+		 * properties.  Since 'length' is virtual for Duktape/C
+		 * functions, don't need to define that.
+		 *
+		 * The result is made extensible to mimic what happens to
+		 * strings:
+		 *   > Object.isExtensible(Object('foo'))
+		 *   true
+		 */
+		duk_small_uint_t lf_flags;
+		duk_idx_t nargs;
+		duk_small_uint_t lf_len;
+		duk_c_function func;
+		duk_hnativefunction *nf;
+
+		DUK_TVAL_GET_LIGHTFUNC(tv, func, lf_flags);
+
+		nargs = (duk_idx_t) DUK_LFUNC_FLAGS_GET_NARGS(lf_flags);
+		if (nargs == DUK_LFUNC_NARGS_VARARGS) {
+			nargs = (duk_idx_t) DUK_VARARGS;
+		}
+		flags = DUK_HOBJECT_FLAG_EXTENSIBLE |
+		        DUK_HOBJECT_FLAG_CONSTRUCTABLE |
+		        DUK_HOBJECT_FLAG_NATIVEFUNCTION |
+	                DUK_HOBJECT_FLAG_NEWENV |
+	                DUK_HOBJECT_FLAG_STRICT |
+	                DUK_HOBJECT_FLAG_NOTAIL |
+			/* DUK_HOBJECT_FLAG_EXOTIC_DUKFUNC: omitted here intentionally */
+	                DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_FUNCTION);
+		(void) duk__push_c_function_raw(ctx, func, nargs, flags);
+
+		lf_len = DUK_LFUNC_FLAGS_GET_LENGTH(lf_flags);
+		if ((duk_idx_t) lf_len != nargs) {
+			/* Explicit length is only needed if it differs from 'nargs'. */
+			duk_push_int(ctx, (duk_int_t) lf_len);
+			duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_LENGTH, DUK_PROPDESC_FLAGS_NONE);
+		}
+		duk_push_lightfunc_name(ctx, tv);
+		duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_NAME, DUK_PROPDESC_FLAGS_NONE);
+
+		nf = duk_get_hnativefunction(ctx, -1);
+		DUK_ASSERT(nf != NULL);
+		nf->magic = (duk_int16_t) DUK_LFUNC_FLAGS_GET_MAGIC(lf_flags);
+
+		/* Enable DUKFUNC exotic behavior once properties are set up. */
+		DUK_HOBJECT_SET_EXOTIC_DUKFUNC((duk_hobject *) nf);
+		goto replace_value;
+	}
+#if defined(DUK_USE_FASTINT)
+	case DUK_TAG_FASTINT:
+#endif
 	default: {
-		shared_flags = DUK_HOBJECT_FLAG_EXTENSIBLE |
+		DUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv));
+		DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));
+		flags = DUK_HOBJECT_FLAG_EXTENSIBLE |
 		               DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_NUMBER);
-		shared_proto = DUK_BIDX_NUMBER_PROTOTYPE;
+		proto = DUK_BIDX_NUMBER_PROTOTYPE;
 		goto create_object;
 	}
 	}
 	return;
 
  create_object:
-	(void) duk_push_object_helper(ctx, shared_flags, shared_proto);
+	(void) duk_push_object_helper(ctx, flags, proto);
 
 	/* Note: Boolean prototype's internal value property is not writable,
-	 * but duk_def_prop_stridx() disregards the write protection.  Boolean
+	 * but duk_xdef_prop_stridx() disregards the write protection.  Boolean
 	 * instances are immutable.
 	 *
 	 * String and buffer special behaviors are already enabled which is not
 	 * ideal, but a write to the internal value is not affected by them.
 	 */
 	duk_dup(ctx, index);
-	duk_def_prop_stridx(ctx, -2, DUK_STRIDX_INT_VALUE, DUK_PROPDESC_FLAGS_NONE);
+	duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_INT_VALUE, DUK_PROPDESC_FLAGS_NONE);
 
+ replace_value:
 	duk_replace(ctx, index);
 }
 
@@ -10695,7 +20769,7 @@ void duk_to_object(duk_context *ctx, duk_idx_t index) {
  *  Type checking
  */
 
-static duk_bool_t duk__tag_check(duk_context *ctx, duk_idx_t index, duk_small_uint_t tag) {
+DUK_LOCAL duk_bool_t duk__tag_check(duk_context *ctx, duk_idx_t index, duk_small_uint_t tag) {
 	duk_tval *tv;
 
 	tv = duk_get_tval(ctx, index);
@@ -10705,10 +20779,10 @@ static duk_bool_t duk__tag_check(duk_context *ctx, duk_idx_t index, duk_small_ui
 	return (DUK_TVAL_GET_TAG(tv) == tag);
 }
 
-static duk_bool_t duk__obj_flag_any_default_false(duk_context *ctx, duk_idx_t index, duk_uint_t flag_mask) {
+DUK_LOCAL duk_bool_t duk__obj_flag_any_default_false(duk_context *ctx, duk_idx_t index, duk_uint_t flag_mask) {
 	duk_hobject *obj;
 
-	DUK_ASSERT(ctx != NULL);
+	DUK_ASSERT_CTX_VALID(ctx);
 
 	obj = duk_get_hobject(ctx, index);
 	if (obj) {
@@ -10717,9 +20791,11 @@ static duk_bool_t duk__obj_flag_any_default_false(duk_context *ctx, duk_idx_t in
 	return 0;
 }
 
-duk_int_t duk_get_type(duk_context *ctx, duk_idx_t index) {
+DUK_EXTERNAL duk_int_t duk_get_type(duk_context *ctx, duk_idx_t index) {
 	duk_tval *tv;
 
+	DUK_ASSERT_CTX_VALID(ctx);
+
 	tv = duk_get_tval(ctx, index);
 	if (!tv) {
 		return DUK_TYPE_NONE;
@@ -10739,21 +20815,56 @@ duk_int_t duk_get_type(duk_context *ctx, duk_idx_t index) {
 		return DUK_TYPE_BUFFER;
 	case DUK_TAG_POINTER:
 		return DUK_TYPE_POINTER;
+	case DUK_TAG_LIGHTFUNC:
+		return DUK_TYPE_LIGHTFUNC;
+#if defined(DUK_USE_FASTINT)
+	case DUK_TAG_FASTINT:
+#endif
 	default:
 		/* Note: number has no explicit tag (in 8-byte representation) */
+		DUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv));
 		DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));
 		return DUK_TYPE_NUMBER;
 	}
 	DUK_UNREACHABLE();
 }
 
-duk_bool_t duk_check_type(duk_context *ctx, duk_idx_t index, duk_int_t type) {
+#if defined(DUK_USE_VERBOSE_ERRORS) && defined(DUK_USE_PARANOID_ERRORS)
+DUK_LOCAL const char *duk__type_names[] = {
+	"none",
+	"undefined",
+	"null",
+	"boolean",
+	"number",
+	"string",
+	"object",
+	"buffer",
+	"pointer",
+	"lightfunc"
+};
+
+DUK_INTERNAL const char *duk_get_type_name(duk_context *ctx, duk_idx_t index) {
+	duk_int_t type_tag;
+
+	type_tag = duk_get_type(ctx, index);
+	DUK_ASSERT(type_tag >= DUK_TYPE_MIN && type_tag <= DUK_TYPE_MAX);
+	DUK_ASSERT(DUK_TYPE_MIN == 0 && sizeof(duk__type_names) / sizeof(const char *) == DUK_TYPE_MAX + 1);
+
+	return duk__type_names[type_tag];
+}
+#endif
+
+DUK_EXTERNAL duk_bool_t duk_check_type(duk_context *ctx, duk_idx_t index, duk_int_t type) {
+	DUK_ASSERT_CTX_VALID(ctx);
+
 	return (duk_get_type(ctx, index) == type) ? 1 : 0;
 }
 
-duk_uint_t duk_get_type_mask(duk_context *ctx, duk_idx_t index) {
+DUK_EXTERNAL duk_uint_t duk_get_type_mask(duk_context *ctx, duk_idx_t index) {
 	duk_tval *tv;
 
+	DUK_ASSERT_CTX_VALID(ctx);
+
 	tv = duk_get_tval(ctx, index);
 	if (!tv) {
 		return DUK_TYPE_MASK_NONE;
@@ -10773,17 +20884,25 @@ duk_uint_t duk_get_type_mask(duk_context *ctx, duk_idx_t index) {
 		return DUK_TYPE_MASK_BUFFER;
 	case DUK_TAG_POINTER:
 		return DUK_TYPE_MASK_POINTER;
+	case DUK_TAG_LIGHTFUNC:
+		return DUK_TYPE_MASK_LIGHTFUNC;
+#if defined(DUK_USE_FASTINT)
+	case DUK_TAG_FASTINT:
+#endif
 	default:
 		/* Note: number has no explicit tag (in 8-byte representation) */
+		DUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv));
 		DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));
 		return DUK_TYPE_MASK_NUMBER;
 	}
 	DUK_UNREACHABLE();
 }
 
-duk_bool_t duk_check_type_mask(duk_context *ctx, duk_idx_t index, duk_uint_t mask) {
+DUK_EXTERNAL duk_bool_t duk_check_type_mask(duk_context *ctx, duk_idx_t index, duk_uint_t mask) {
 	duk_hthread *thr = (duk_hthread *) ctx;
-	DUK_ASSERT(ctx != NULL);
+
+	DUK_ASSERT_CTX_VALID(ctx);
+
 	if (duk_get_type_mask(ctx, index) & mask) {
 		return 1;
 	}
@@ -10794,20 +20913,22 @@ duk_bool_t duk_check_type_mask(duk_context *ctx, duk_idx_t index, duk_uint_t mas
 	return 0;
 }
 
-duk_bool_t duk_is_undefined(duk_context *ctx, duk_idx_t index) {
-	DUK_ASSERT(ctx != NULL);
+DUK_EXTERNAL duk_bool_t duk_is_undefined(duk_context *ctx, duk_idx_t index) {
+	DUK_ASSERT_CTX_VALID(ctx);
 	return duk__tag_check(ctx, index, DUK_TAG_UNDEFINED);
 }
 
-duk_bool_t duk_is_null(duk_context *ctx, duk_idx_t index) {
-	DUK_ASSERT(ctx != NULL);
+DUK_EXTERNAL duk_bool_t duk_is_null(duk_context *ctx, duk_idx_t index) {
+	DUK_ASSERT_CTX_VALID(ctx);
 	return duk__tag_check(ctx, index, DUK_TAG_NULL);
 }
 
-duk_bool_t duk_is_null_or_undefined(duk_context *ctx, duk_idx_t index) {
+DUK_EXTERNAL duk_bool_t duk_is_null_or_undefined(duk_context *ctx, duk_idx_t index) {
 	duk_tval *tv;
 	duk_small_uint_t tag;
 
+	DUK_ASSERT_CTX_VALID(ctx);
+
 	tv = duk_get_tval(ctx, index);
 	if (!tv) {
 		return 0;
@@ -10816,15 +20937,15 @@ duk_bool_t duk_is_null_or_undefined(duk_context *ctx, duk_idx_t index) {
 	return (tag == DUK_TAG_UNDEFINED) || (tag == DUK_TAG_NULL);
 }
 
-duk_bool_t duk_is_boolean(duk_context *ctx, duk_idx_t index) {
-	DUK_ASSERT(ctx != NULL);
+DUK_EXTERNAL duk_bool_t duk_is_boolean(duk_context *ctx, duk_idx_t index) {
+	DUK_ASSERT_CTX_VALID(ctx);
 	return duk__tag_check(ctx, index, DUK_TAG_BOOLEAN);
 }
 
-duk_bool_t duk_is_number(duk_context *ctx, duk_idx_t index) {
+DUK_EXTERNAL duk_bool_t duk_is_number(duk_context *ctx, duk_idx_t index) {
 	duk_tval *tv;
 
-	DUK_ASSERT(ctx != NULL);
+	DUK_ASSERT_CTX_VALID(ctx);
 
 	/*
 	 *  Number is special because it doesn't have a specific
@@ -10840,7 +20961,7 @@ duk_bool_t duk_is_number(duk_context *ctx, duk_idx_t index) {
 	return DUK_TVAL_IS_NUMBER(tv);
 }
 
-duk_bool_t duk_is_nan(duk_context *ctx, duk_idx_t index) {
+DUK_EXTERNAL duk_bool_t duk_is_nan(duk_context *ctx, duk_idx_t index) {
 	/* XXX: This will now return false for non-numbers, even though they would
 	 * coerce to NaN (as a general rule).  In particular, duk_get_number()
 	 * returns a NaN for non-numbers, so should this function also return
@@ -10849,6 +20970,8 @@ duk_bool_t duk_is_nan(duk_context *ctx, duk_idx_t index) {
 
 	duk_tval *tv;
 
+	DUK_ASSERT_CTX_VALID(ctx);
+
 	tv = duk_get_tval(ctx, index);
 	if (!tv || !DUK_TVAL_IS_NUMBER(tv)) {
 		return 0;
@@ -10856,30 +20979,35 @@ duk_bool_t duk_is_nan(duk_context *ctx, duk_idx_t index) {
 	return DUK_ISNAN(DUK_TVAL_GET_NUMBER(tv));
 }
 
-duk_bool_t duk_is_string(duk_context *ctx, duk_idx_t index) {
-	DUK_ASSERT(ctx != NULL);
+DUK_EXTERNAL duk_bool_t duk_is_string(duk_context *ctx, duk_idx_t index) {
+	DUK_ASSERT_CTX_VALID(ctx);
 	return duk__tag_check(ctx, index, DUK_TAG_STRING);
 }
 
-duk_bool_t duk_is_object(duk_context *ctx, duk_idx_t index) {
-	DUK_ASSERT(ctx != NULL);
+DUK_EXTERNAL duk_bool_t duk_is_object(duk_context *ctx, duk_idx_t index) {
+	DUK_ASSERT_CTX_VALID(ctx);
 	return duk__tag_check(ctx, index, DUK_TAG_OBJECT);
 }
 
-duk_bool_t duk_is_buffer(duk_context *ctx, duk_idx_t index) {
-	DUK_ASSERT(ctx != NULL);
+DUK_EXTERNAL duk_bool_t duk_is_buffer(duk_context *ctx, duk_idx_t index) {
+	DUK_ASSERT_CTX_VALID(ctx);
 	return duk__tag_check(ctx, index, DUK_TAG_BUFFER);
 }
 
-duk_bool_t duk_is_pointer(duk_context *ctx, duk_idx_t index) {
-	DUK_ASSERT(ctx != NULL);
+DUK_EXTERNAL duk_bool_t duk_is_pointer(duk_context *ctx, duk_idx_t index) {
+	DUK_ASSERT_CTX_VALID(ctx);
 	return duk__tag_check(ctx, index, DUK_TAG_POINTER);
 }
 
-duk_bool_t duk_is_array(duk_context *ctx, duk_idx_t index) {
+DUK_EXTERNAL duk_bool_t duk_is_lightfunc(duk_context *ctx, duk_idx_t index) {
+	DUK_ASSERT_CTX_VALID(ctx);
+	return duk__tag_check(ctx, index, DUK_TAG_LIGHTFUNC);
+}
+
+DUK_EXTERNAL duk_bool_t duk_is_array(duk_context *ctx, duk_idx_t index) {
 	duk_hobject *obj;
 
-	DUK_ASSERT(ctx != NULL);
+	DUK_ASSERT_CTX_VALID(ctx);
 
 	obj = duk_get_hobject(ctx, index);
 	if (obj) {
@@ -10888,7 +21016,15 @@ duk_bool_t duk_is_array(duk_context *ctx, duk_idx_t index) {
 	return 0;
 }
 
-duk_bool_t duk_is_function(duk_context *ctx, duk_idx_t index) {
+DUK_EXTERNAL duk_bool_t duk_is_function(duk_context *ctx, duk_idx_t index) {
+	duk_tval *tv;
+
+	DUK_ASSERT_CTX_VALID(ctx);
+
+	tv = duk_get_tval(ctx, index);
+	if (tv && DUK_TVAL_IS_LIGHTFUNC(tv)) {
+		return 1;
+	}
 	return duk__obj_flag_any_default_false(ctx,
 	                                       index,
 	                                       DUK_HOBJECT_FLAG_COMPILEDFUNCTION |
@@ -10896,165 +21032,301 @@ duk_bool_t duk_is_function(duk_context *ctx, duk_idx_t index) {
 	                                       DUK_HOBJECT_FLAG_BOUND);
 }
 
-duk_bool_t duk_is_c_function(duk_context *ctx, duk_idx_t index) {
+DUK_EXTERNAL duk_bool_t duk_is_c_function(duk_context *ctx, duk_idx_t index) {
+	DUK_ASSERT_CTX_VALID(ctx);
 	return duk__obj_flag_any_default_false(ctx,
 	                                       index,
 	                                       DUK_HOBJECT_FLAG_NATIVEFUNCTION);
 }
 
-duk_bool_t duk_is_ecmascript_function(duk_context *ctx, duk_idx_t index) {
+DUK_EXTERNAL duk_bool_t duk_is_ecmascript_function(duk_context *ctx, duk_idx_t index) {
+	DUK_ASSERT_CTX_VALID(ctx);
 	return duk__obj_flag_any_default_false(ctx,
 	                                       index,
 	                                       DUK_HOBJECT_FLAG_COMPILEDFUNCTION);
 }
 
-duk_bool_t duk_is_bound_function(duk_context *ctx, duk_idx_t index) {
+DUK_EXTERNAL duk_bool_t duk_is_bound_function(duk_context *ctx, duk_idx_t index) {
+	DUK_ASSERT_CTX_VALID(ctx);
 	return duk__obj_flag_any_default_false(ctx,
 	                                       index,
 	                                       DUK_HOBJECT_FLAG_BOUND);
 }
 
-duk_bool_t duk_is_thread(duk_context *ctx, duk_idx_t index) {
+DUK_EXTERNAL duk_bool_t duk_is_thread(duk_context *ctx, duk_idx_t index) {
+	DUK_ASSERT_CTX_VALID(ctx);
 	return duk__obj_flag_any_default_false(ctx,
 	                                       index,
 	                                       DUK_HOBJECT_FLAG_THREAD);
 }
 
-duk_bool_t duk_is_callable(duk_context *ctx, duk_idx_t index) {
-	/* XXX: currently same as duk_is_function() */
-	return duk__obj_flag_any_default_false(ctx,
-	                                       index,
-	                                       DUK_HOBJECT_FLAG_COMPILEDFUNCTION |
-	                                       DUK_HOBJECT_FLAG_NATIVEFUNCTION |
-	                                       DUK_HOBJECT_FLAG_BOUND);
+DUK_EXTERNAL duk_bool_t duk_is_fixed_buffer(duk_context *ctx, duk_idx_t index) {
+	duk_tval *tv;
+
+	DUK_ASSERT_CTX_VALID(ctx);
+
+	tv = duk_get_tval(ctx, index);
+	if (tv && DUK_TVAL_IS_BUFFER(tv)) {
+		duk_hbuffer *h = DUK_TVAL_GET_BUFFER(tv);
+		DUK_ASSERT(h != NULL);
+		return (DUK_HBUFFER_HAS_DYNAMIC(h) ? 0 : 1);
+	}
+	return 0;
 }
 
-duk_bool_t duk_is_dynamic(duk_context *ctx, duk_idx_t index) {
+DUK_EXTERNAL duk_bool_t duk_is_dynamic_buffer(duk_context *ctx, duk_idx_t index) {
 	duk_tval *tv;
 
-	DUK_ASSERT(ctx != NULL);
+	DUK_ASSERT_CTX_VALID(ctx);
 
 	tv = duk_get_tval(ctx, index);
-	if (DUK_TVAL_IS_BUFFER(tv)) {
+	if (tv && DUK_TVAL_IS_BUFFER(tv)) {
 		duk_hbuffer *h = DUK_TVAL_GET_BUFFER(tv);
 		DUK_ASSERT(h != NULL);
-		return (DUK_HBUFFER_HAS_DYNAMIC(h) ? 1 : 0);
+		return (DUK_HBUFFER_HAS_DYNAMIC(h) && !DUK_HBUFFER_HAS_EXTERNAL(h) ? 1 : 0);
 	}
 	return 0;
 }
 
-duk_bool_t duk_is_fixed(duk_context *ctx, duk_idx_t index) {
+DUK_EXTERNAL duk_bool_t duk_is_external_buffer(duk_context *ctx, duk_idx_t index) {
 	duk_tval *tv;
 
-	DUK_ASSERT(ctx != NULL);
+	DUK_ASSERT_CTX_VALID(ctx);
 
 	tv = duk_get_tval(ctx, index);
-	if (DUK_TVAL_IS_BUFFER(tv)) {
+	if (tv && DUK_TVAL_IS_BUFFER(tv)) {
 		duk_hbuffer *h = DUK_TVAL_GET_BUFFER(tv);
 		DUK_ASSERT(h != NULL);
-		return (DUK_HBUFFER_HAS_DYNAMIC(h) ? 0 : 1);
+		return (DUK_HBUFFER_HAS_DYNAMIC(h) && DUK_HBUFFER_HAS_EXTERNAL(h) ? 1 : 0);
 	}
 	return 0;
 }
 
-/* XXX: make macro in API */
-duk_bool_t duk_is_primitive(duk_context *ctx, duk_idx_t index) {
-	return !duk_is_object(ctx, index);
+DUK_EXTERNAL duk_errcode_t duk_get_error_code(duk_context *ctx, duk_idx_t index) {
+	duk_hthread *thr = (duk_hthread *) ctx;
+	duk_hobject *h;
+	duk_uint_t sanity;
+
+	DUK_ASSERT_CTX_VALID(ctx);
+
+	h = duk_get_hobject(ctx, index);
+
+	sanity = DUK_HOBJECT_PROTOTYPE_CHAIN_SANITY;
+	do {
+		if (!h) {
+			return DUK_ERR_NONE;
+		}
+		if (h == thr->builtins[DUK_BIDX_EVAL_ERROR_PROTOTYPE]) {
+			return DUK_ERR_EVAL_ERROR;
+		}
+		if (h == thr->builtins[DUK_BIDX_RANGE_ERROR_PROTOTYPE]) {
+			return DUK_ERR_RANGE_ERROR;
+		}
+		if (h == thr->builtins[DUK_BIDX_REFERENCE_ERROR_PROTOTYPE]) {
+			return DUK_ERR_REFERENCE_ERROR;
+		}
+		if (h == thr->builtins[DUK_BIDX_SYNTAX_ERROR_PROTOTYPE]) {
+			return DUK_ERR_SYNTAX_ERROR;
+		}
+		if (h == thr->builtins[DUK_BIDX_TYPE_ERROR_PROTOTYPE]) {
+			return DUK_ERR_TYPE_ERROR;
+		}
+		if (h == thr->builtins[DUK_BIDX_URI_ERROR_PROTOTYPE]) {
+			return DUK_ERR_URI_ERROR;
+		}
+		if (h == thr->builtins[DUK_BIDX_ERROR_PROTOTYPE]) {
+			return DUK_ERR_ERROR;
+		}
+
+		h = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h);
+	} while (--sanity > 0);
+
+	return DUK_ERR_NONE;
 }
 
 /*
  *  Pushers
  */
 
-void duk_push_tval(duk_context *ctx, duk_tval *tv) {
-	duk_hthread *thr = (duk_hthread *) ctx;
+DUK_INTERNAL void duk_push_tval(duk_context *ctx, duk_tval *tv) {
+	duk_hthread *thr;
 	duk_tval *tv_slot;
 
-	DUK_ASSERT(ctx != NULL);
+	DUK_ASSERT_CTX_VALID(ctx);
 	DUK_ASSERT(tv != NULL);
+	thr = (duk_hthread *) ctx;
+	DUK__CHECK_SPACE();
+	tv_slot = thr->valstack_top++;
+	DUK_TVAL_SET_TVAL(tv_slot, tv);
+	DUK_TVAL_INCREF(thr, tv);  /* no side effects */
+}
 
-	if (thr->valstack_top >= thr->valstack_end) {
-		DUK_ERROR(thr, DUK_ERR_API_ERROR, DUK_STR_PUSH_BEYOND_ALLOC_STACK);
-	}
+DUK_EXTERNAL void duk_push_undefined(duk_context *ctx) {
+	duk_hthread *thr;
 
-	tv_slot = thr->valstack_top;
-	DUK_TVAL_SET_TVAL(tv_slot, tv);
-	DUK_TVAL_INCREF(thr, tv);
+	DUK_ASSERT_CTX_VALID(ctx);
+	thr = (duk_hthread *) ctx;
+	DUK__CHECK_SPACE();
+
+	/* Because value stack init policy is 'undefined above top',
+	 * we don't need to write, just assert.
+	 */
 	thr->valstack_top++;
+	DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(thr->valstack_top - 1));
 }
 
-void duk_push_unused(duk_context *ctx) {
-	duk_tval tv;
-	DUK_ASSERT(ctx != NULL);
-	DUK_TVAL_SET_UNDEFINED_ACTUAL(&tv);
-	duk_push_tval(ctx, &tv);
-}
+DUK_EXTERNAL void duk_push_null(duk_context *ctx) {
+	duk_hthread *thr;
+	duk_tval *tv_slot;
 
-void duk_push_undefined(duk_context *ctx) {
-	duk_tval tv;
-	DUK_ASSERT(ctx != NULL);
-	DUK_TVAL_SET_UNDEFINED_ACTUAL(&tv);  /* XXX: heap constant would be nice */
-	duk_push_tval(ctx, &tv);
+	DUK_ASSERT_CTX_VALID(ctx);
+	thr = (duk_hthread *) ctx;
+	DUK__CHECK_SPACE();
+	tv_slot = thr->valstack_top++;
+	DUK_TVAL_SET_NULL(tv_slot);
 }
 
-void duk_push_null(duk_context *ctx) {
-	duk_tval tv;
-	DUK_ASSERT(ctx != NULL);
-	DUK_TVAL_SET_NULL(&tv);  /* XXX: heap constant would be nice */
-	duk_push_tval(ctx, &tv);
-}
+DUK_EXTERNAL void duk_push_boolean(duk_context *ctx, duk_bool_t val) {
+	duk_hthread *thr;
+	duk_tval *tv_slot;
+	duk_small_int_t b;
 
-void duk_push_boolean(duk_context *ctx, duk_bool_t val) {
-	duk_tval tv;
-	duk_small_int_t b = (val ? 1 : 0);  /* ensure value is 1 or 0 (not other non-zero) */
-	DUK_ASSERT(ctx != NULL);
-	DUK_TVAL_SET_BOOLEAN(&tv, b);
-	duk_push_tval(ctx, &tv);
+	DUK_ASSERT_CTX_VALID(ctx);
+	thr = (duk_hthread *) ctx;
+	DUK__CHECK_SPACE();
+	b = (val ? 1 : 0);  /* ensure value is 1 or 0 (not other non-zero) */
+	tv_slot = thr->valstack_top++;
+	DUK_TVAL_SET_BOOLEAN(tv_slot, b);
 }
 
-void duk_push_true(duk_context *ctx) {
-	duk_push_boolean(ctx, 1);
+DUK_EXTERNAL void duk_push_true(duk_context *ctx) {
+	duk_hthread *thr;
+	duk_tval *tv_slot;
+
+	DUK_ASSERT_CTX_VALID(ctx);
+	thr = (duk_hthread *) ctx;
+	DUK__CHECK_SPACE();
+	tv_slot = thr->valstack_top++;
+	DUK_TVAL_SET_BOOLEAN_TRUE(tv_slot);
 }
 
-void duk_push_false(duk_context *ctx) {
-	duk_push_boolean(ctx, 0);
+DUK_EXTERNAL void duk_push_false(duk_context *ctx) {
+	duk_hthread *thr;
+	duk_tval *tv_slot;
+
+	DUK_ASSERT_CTX_VALID(ctx);
+	thr = (duk_hthread *) ctx;
+	DUK__CHECK_SPACE();
+	tv_slot = thr->valstack_top++;
+	DUK_TVAL_SET_BOOLEAN_FALSE(tv_slot);
 }
 
-void duk_push_number(duk_context *ctx, duk_double_t val) {
-	duk_tval tv;
+/* normalize NaN which may not match our canonical internal NaN */
+DUK_EXTERNAL void duk_push_number(duk_context *ctx, duk_double_t val) {
+	duk_hthread *thr;
+	duk_tval *tv_slot;
 	duk_double_union du;
-	DUK_ASSERT(ctx != NULL);
 
-	/* normalize NaN which may not match our canonical internal NaN */
+	DUK_ASSERT_CTX_VALID(ctx);
+	thr = (duk_hthread *) ctx;
+	DUK__CHECK_SPACE();
 	du.d = val;
 	DUK_DBLUNION_NORMALIZE_NAN_CHECK(&du);
-
-	DUK_TVAL_SET_NUMBER(&tv, du.d);
-	duk_push_tval(ctx, &tv);
+	tv_slot = thr->valstack_top++;
+	DUK_TVAL_SET_NUMBER(tv_slot, du.d);
 }
 
-void duk_push_int(duk_context *ctx, duk_int_t val) {
-	duk_push_number(ctx, (duk_double_t) val);
+DUK_EXTERNAL void duk_push_int(duk_context *ctx, duk_int_t val) {
+#if defined(DUK_USE_FASTINT)
+	duk_hthread *thr;
+	duk_tval *tv_slot;
+
+	DUK_ASSERT_CTX_VALID(ctx);
+	thr = (duk_hthread *) ctx;
+	DUK__CHECK_SPACE();
+	tv_slot = thr->valstack_top++;
+#if DUK_INT_MAX <= 0x7fffffffL
+	DUK_TVAL_SET_FASTINT_I32(tv_slot, (duk_int32_t) val);
+#else
+	if (val >= DUK_FASTINT_MIN && val <= DUK_FASTINT_MAX) {
+		DUK_TVAL_SET_FASTINT(tv_slot, (duk_int64_t) val);
+	} else {
+		duk_double_t = (duk_double_t) val;
+		DUK_TVAL_SET_NUMBER(tv_slot, d);
+	}
+#endif
+#else  /* DUK_USE_FASTINT */
+	duk_hthread *thr;
+	duk_tval *tv_slot;
+	duk_double_t d;
+
+	DUK_ASSERT_CTX_VALID(ctx);
+	thr = (duk_hthread *) ctx;
+	DUK__CHECK_SPACE();
+	d = (duk_double_t) val;
+	tv_slot = thr->valstack_top++;
+	DUK_TVAL_SET_NUMBER(tv_slot, d);
+#endif  /* DUK_USE_FASTINT */
 }
 
-void duk_push_uint(duk_context *ctx, duk_uint_t val) {
-	duk_push_number(ctx, (duk_double_t) val);
+DUK_EXTERNAL void duk_push_uint(duk_context *ctx, duk_uint_t val) {
+#if defined(DUK_USE_FASTINT)
+	duk_hthread *thr;
+	duk_tval *tv_slot;
+
+	DUK_ASSERT_CTX_VALID(ctx);
+	thr = (duk_hthread *) ctx;
+	DUK__CHECK_SPACE();
+	tv_slot = thr->valstack_top++;
+#if DUK_UINT_MAX <= 0xffffffffUL
+	DUK_TVAL_SET_FASTINT_U32(tv_slot, (duk_uint32_t) val);
+#else
+	if (val <= DUK_FASTINT_MAX) {  /* val is unsigned so >= 0 */
+		/* XXX: take advantage of val being unsigned, no need to mask */
+		DUK_TVAL_SET_FASTINT(tv_slot, (duk_int64_t) val);
+	} else {
+		duk_double_t = (duk_double_t) val;
+		DUK_TVAL_SET_NUMBER(tv_slot, d);
+	}
+#endif
+#else  /* DUK_USE_FASTINT */
+	duk_hthread *thr;
+	duk_tval *tv_slot;
+	duk_double_t d;
+
+	DUK_ASSERT_CTX_VALID(ctx);
+	thr = (duk_hthread *) ctx;
+	DUK__CHECK_SPACE();
+	d = (duk_double_t) val;
+	tv_slot = thr->valstack_top++;
+	DUK_TVAL_SET_NUMBER(tv_slot, d);
+#endif  /* DUK_USE_FASTINT */
 }
 
-void duk_push_nan(duk_context *ctx) {
-	duk_push_number(ctx, DUK_DOUBLE_NAN);
+DUK_EXTERNAL void duk_push_nan(duk_context *ctx) {
+	duk_hthread *thr;
+	duk_tval *tv_slot;
+	duk_double_union du;
+
+	DUK_ASSERT_CTX_VALID(ctx);
+	thr = (duk_hthread *) ctx;
+	DUK__CHECK_SPACE();
+	DUK_DBLUNION_SET_NAN(&du);
+	DUK_ASSERT(DUK_DBLUNION_IS_NORMALIZED(&du));
+	tv_slot = thr->valstack_top++;
+	DUK_TVAL_SET_NUMBER(tv_slot, du.d);
 }
 
-const char *duk_push_lstring(duk_context *ctx, const char *str, duk_size_t len) {
+DUK_EXTERNAL const char *duk_push_lstring(duk_context *ctx, const char *str, duk_size_t len) {
 	duk_hthread *thr = (duk_hthread *) ctx;
 	duk_hstring *h;
 	duk_tval *tv_slot;
 
-	DUK_ASSERT(ctx != NULL);
+	DUK_ASSERT_CTX_VALID(ctx);
 
 	/* check stack before interning (avoid hanging temp) */
 	if (thr->valstack_top >= thr->valstack_end) {
-		DUK_ERROR(thr, DUK_ERR_API_ERROR, DUK_STR_PUSH_BEYOND_ALLOC_STACK);
+		DUK_ERROR_API(thr, DUK_STR_PUSH_BEYOND_ALLOC_STACK);
 	}
 
 	/* NULL with zero length represents an empty string; NULL with higher
@@ -11071,19 +21343,18 @@ const char *duk_push_lstring(duk_context *ctx, const char *str, duk_size_t len)
 		DUK_ERROR(thr, DUK_ERR_RANGE_ERROR, DUK_STR_STRING_TOO_LONG);
 	}
 
-	h = duk_heap_string_intern_checked(thr, (duk_uint8_t *) str, (duk_uint32_t) len);
+	h = duk_heap_string_intern_checked(thr, (const duk_uint8_t *) str, (duk_uint32_t) len);
 	DUK_ASSERT(h != NULL);
 
-	tv_slot = thr->valstack_top;
+	tv_slot = thr->valstack_top++;
 	DUK_TVAL_SET_STRING(tv_slot, h);
-	DUK_HSTRING_INCREF(thr, h);
-	thr->valstack_top++;
+	DUK_HSTRING_INCREF(thr, h);  /* no side effects */
 
 	return (const char *) DUK_HSTRING_GET_DATA(h);
 }
 
-const char *duk_push_string(duk_context *ctx, const char *str) {
-	DUK_ASSERT(ctx != NULL);
+DUK_EXTERNAL const char *duk_push_string(duk_context *ctx, const char *str) {
+	DUK_ASSERT_CTX_VALID(ctx);
 
 	if (str) {
 		return duk_push_lstring(ctx, str, DUK_STRLEN(str));
@@ -11098,13 +21369,14 @@ const char *duk_push_string(duk_context *ctx, const char *str) {
  * relocate to another file because this is potentially platform
  * dependent.
  */
-const char *duk_push_string_file(duk_context *ctx, const char *path) {
+DUK_EXTERNAL const char *duk_push_string_file_raw(duk_context *ctx, const char *path, duk_uint_t flags) {
 	duk_hthread *thr = (duk_hthread *) ctx;
 	duk_file *f = NULL;
 	char *buf;
 	long sz;  /* ANSI C typing */
 
-	DUK_ASSERT(ctx != NULL);
+	DUK_ASSERT_CTX_VALID(ctx);
+
 	if (!path) {
 		goto fail;
 	}
@@ -11135,124 +21407,154 @@ const char *duk_push_string_file(duk_context *ctx, const char *path) {
 	if (f) {
 		DUK_FCLOSE(f);
 	}
-	/* XXX: string not shared because it is conditional */
-	DUK_ERROR(thr, DUK_ERR_TYPE_ERROR, "read file error");
+
+	if (flags != 0) {
+		DUK_ASSERT(flags == DUK_STRING_PUSH_SAFE);  /* only flag now */
+		duk_push_undefined(ctx);
+	} else {
+		/* XXX: string not shared because it is conditional */
+		DUK_ERROR(thr, DUK_ERR_TYPE_ERROR, "read file error");
+	}
 	return NULL;
 }
 #else
-const char *duk_push_string_file(duk_context *ctx, const char *path) {
+DUK_EXTERNAL const char *duk_push_string_file_raw(duk_context *ctx, const char *path, duk_uint_t flags) {
 	duk_hthread *thr = (duk_hthread *) ctx;
-	DUK_ASSERT(ctx != NULL);
+	DUK_ASSERT_CTX_VALID(ctx);
 	DUK_UNREF(path);
-	/* XXX: string not shared because it is conditional */
-	DUK_ERROR(thr, DUK_ERR_TYPE_ERROR, "file I/O disabled");
+
+	if (flags != 0) {
+		DUK_ASSERT(flags == DUK_STRING_PUSH_SAFE);  /* only flag now */
+		duk_push_undefined(ctx);
+	} else {
+		/* XXX: string not shared because it is conditional */
+		DUK_ERROR(thr, DUK_ERR_TYPE_ERROR, "file I/O disabled");
+	}
 	return NULL;
 }
 #endif  /* DUK_USE_FILE_IO */
 
-void duk_push_pointer(duk_context *ctx, void *val) {
-	duk_tval tv;
-	DUK_ASSERT(ctx != NULL);
+DUK_EXTERNAL void duk_push_pointer(duk_context *ctx, void *val) {
+	duk_hthread *thr;
+	duk_tval *tv_slot;
 
-	DUK_TVAL_SET_POINTER(&tv, val);
-	duk_push_tval(ctx, &tv);
+	DUK_ASSERT_CTX_VALID(ctx);
+	thr = (duk_hthread *) ctx;
+	DUK__CHECK_SPACE();
+	tv_slot = thr->valstack_top++;
+	DUK_TVAL_SET_POINTER(tv_slot, val);
 }
 
-#define DUK__PUSH_THIS_FLAG_CHECK_COERC  (1 << 0)
-#define DUK__PUSH_THIS_FLAG_TO_OBJECT    (1 << 1)
-#define DUK__PUSH_THIS_FLAG_TO_STRING    (1 << 2)
-
-static void duk__push_this_helper(duk_context *ctx, duk_small_uint_t flags) {
-	duk_hthread *thr = (duk_hthread *) ctx;
+DUK_LOCAL void duk__push_this_helper(duk_context *ctx, duk_small_uint_t check_object_coercible) {
+	duk_hthread *thr;
+	duk_tval *tv_slot;
 
-	DUK_ASSERT(thr != NULL);
-	DUK_ASSERT(ctx != NULL);
+	DUK_ASSERT_CTX_VALID(ctx);
 	DUK_ASSERT_DISABLE(thr->callstack_top >= 0);  /* avoid warning (unsigned) */
+	thr = (duk_hthread *) ctx;
 	DUK_ASSERT(thr->callstack_top <= thr->callstack_size);
+	DUK__CHECK_SPACE();
 
-	if (thr->callstack_top == 0) {
-		if (flags & DUK__PUSH_THIS_FLAG_CHECK_COERC) {
+	DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(thr->valstack_top));  /* because of valstack init policy */
+	tv_slot = thr->valstack_top++;
+
+	if (DUK_UNLIKELY(thr->callstack_top == 0)) {
+		if (check_object_coercible) {
 			goto type_error;
 		}
-		duk_push_undefined(ctx);
+		/* 'undefined' already on stack top */
 	} else {
-		duk_tval tv_tmp;
 		duk_tval *tv;
 
 		/* 'this' binding is just before current activation's bottom */
 		DUK_ASSERT(thr->valstack_bottom > thr->valstack);
 		tv = thr->valstack_bottom - 1;
-		if (flags & DUK__PUSH_THIS_FLAG_CHECK_COERC) {
-			if (DUK_TVAL_IS_UNDEFINED(tv) || DUK_TVAL_IS_NULL(tv)) {
-				goto type_error;
-			}
-		}
-
-		DUK_TVAL_SET_TVAL(&tv_tmp, tv);
-		duk_push_tval(ctx, &tv_tmp);
-	}
+		if (check_object_coercible &&
+		    (DUK_TVAL_IS_UNDEFINED(tv) || DUK_TVAL_IS_NULL(tv))) {
+			/* XXX: better macro for DUK_TVAL_IS_UNDEFINED_OR_NULL(tv) */
+			goto type_error;
+		}
 
-	if (flags & DUK__PUSH_THIS_FLAG_TO_OBJECT) {
-		duk_to_object(ctx, -1);
-	} else if (flags & DUK__PUSH_THIS_FLAG_TO_STRING) {
-		duk_to_string(ctx, -1);
+		DUK_TVAL_SET_TVAL(tv_slot, tv);
+		DUK_TVAL_INCREF(thr, tv);
 	}
-
 	return;
 
  type_error:
 	DUK_ERROR(thr, DUK_ERR_TYPE_ERROR, DUK_STR_NOT_OBJECT_COERCIBLE);
 }
 
-void duk_push_this(duk_context *ctx) {
-	duk__push_this_helper(ctx, 0 /*flags*/);
+DUK_EXTERNAL void duk_push_this(duk_context *ctx) {
+	DUK_ASSERT_CTX_VALID(ctx);
+
+	duk__push_this_helper(ctx, 0 /*check_object_coercible*/);
 }
 
-void duk_push_this_check_object_coercible(duk_context *ctx) {
-	duk__push_this_helper(ctx, DUK__PUSH_THIS_FLAG_CHECK_COERC /*flags*/);
+DUK_INTERNAL void duk_push_this_check_object_coercible(duk_context *ctx) {
+	DUK_ASSERT_CTX_VALID(ctx);
+
+	duk__push_this_helper(ctx, 1 /*check_object_coercible*/);
 }
 
-duk_hobject *duk_push_this_coercible_to_object(duk_context *ctx) {
+DUK_INTERNAL duk_hobject *duk_push_this_coercible_to_object(duk_context *ctx) {
 	duk_hobject *h;
-	duk__push_this_helper(ctx, DUK__PUSH_THIS_FLAG_CHECK_COERC |
-	                           DUK__PUSH_THIS_FLAG_TO_OBJECT /*flags*/);
+
+	DUK_ASSERT_CTX_VALID(ctx);
+
+	duk__push_this_helper(ctx, 1 /*check_object_coercible*/);
+	duk_to_object(ctx, -1);
 	h = duk_get_hobject(ctx, -1);
 	DUK_ASSERT(h != NULL);
 	return h;
 }
 
-duk_hstring *duk_push_this_coercible_to_string(duk_context *ctx) {
+DUK_INTERNAL duk_hstring *duk_push_this_coercible_to_string(duk_context *ctx) {
 	duk_hstring *h;
-	duk__push_this_helper(ctx, DUK__PUSH_THIS_FLAG_CHECK_COERC |
-	                           DUK__PUSH_THIS_FLAG_TO_STRING /*flags*/);
+
+	DUK_ASSERT_CTX_VALID(ctx);
+
+	duk__push_this_helper(ctx, 1 /*check_object_coercible*/);
+	duk_to_string(ctx, -1);
 	h = duk_get_hstring(ctx, -1);
 	DUK_ASSERT(h != NULL);
 	return h;
 }
 
-void duk_push_current_function(duk_context *ctx) {
+DUK_INTERNAL duk_tval *duk_get_borrowed_this_tval(duk_context *ctx) {
+	duk_hthread *thr;
+
+	DUK_ASSERT(ctx != NULL);
+	thr = (duk_hthread *) ctx;
+
+	DUK_ASSERT(thr->callstack_top > 0);  /* caller required to know */
+	DUK_ASSERT(thr->valstack_bottom > thr->valstack);  /* consequence of above */
+	DUK_ASSERT(thr->valstack_bottom - 1 >= thr->valstack);  /* 'this' binding exists */
+
+	return thr->valstack_bottom - 1;
+}
+
+DUK_EXTERNAL void duk_push_current_function(duk_context *ctx) {
 	duk_hthread *thr = (duk_hthread *) ctx;
 	duk_activation *act;
 
+	DUK_ASSERT_CTX_VALID(ctx);
 	DUK_ASSERT(thr != NULL);
-	DUK_ASSERT(ctx != NULL);
 	DUK_ASSERT_DISABLE(thr->callstack_top >= 0);
 	DUK_ASSERT(thr->callstack_top <= thr->callstack_size);
 
 	act = duk_hthread_get_current_activation(thr);
 	if (act) {
-		DUK_ASSERT(act->func != NULL);
-		duk_push_hobject(ctx, act->func);
+		duk_push_tval(ctx, &act->tv_func);
 	} else {
 		duk_push_undefined(ctx);
 	}
 }
 
-void duk_push_current_thread(duk_context *ctx) {
+DUK_EXTERNAL void duk_push_current_thread(duk_context *ctx) {
 	duk_hthread *thr = (duk_hthread *) ctx;
 
+	DUK_ASSERT_CTX_VALID(ctx);
 	DUK_ASSERT(thr != NULL);
-	DUK_ASSERT(ctx != NULL);
 
 	if (thr->heap->curr_thread) {
 		duk_push_hobject(ctx, (duk_hobject *) thr->heap->curr_thread);
@@ -11261,46 +21563,46 @@ void duk_push_current_thread(duk_context *ctx) {
 	}
 }
 
-void duk_push_global_object(duk_context *ctx) {
-	DUK_ASSERT(ctx != NULL);
+DUK_EXTERNAL void duk_push_global_object(duk_context *ctx) {
+	DUK_ASSERT_CTX_VALID(ctx);
 
 	duk_push_hobject_bidx(ctx, DUK_BIDX_GLOBAL);
 }
 
 /* XXX: size optimize */
-static void duk__push_stash(duk_context *ctx) {
-	DUK_ASSERT(ctx != NULL);
+DUK_LOCAL void duk__push_stash(duk_context *ctx) {
+	DUK_ASSERT_CTX_VALID(ctx);
 	if (!duk_get_prop_stridx(ctx, -1, DUK_STRIDX_INT_VALUE)) {
 		DUK_DDD(DUK_DDDPRINT("creating heap/global/thread stash on first use"));
 		duk_pop(ctx);
 		duk_push_object_internal(ctx);
 		duk_dup_top(ctx);
-		duk_def_prop_stridx(ctx, -3, DUK_STRIDX_INT_VALUE, DUK_PROPDESC_FLAGS_C);  /* [ ... parent stash stash ] -> [ ... parent stash ] */
+		duk_xdef_prop_stridx(ctx, -3, DUK_STRIDX_INT_VALUE, DUK_PROPDESC_FLAGS_C);  /* [ ... parent stash stash ] -> [ ... parent stash ] */
 	}
 	duk_remove(ctx, -2);
 }
 
-void duk_push_heap_stash(duk_context *ctx) {
+DUK_EXTERNAL void duk_push_heap_stash(duk_context *ctx) {
 	duk_hthread *thr = (duk_hthread *) ctx;
 	duk_heap *heap;
-	DUK_ASSERT(ctx != NULL);
+	DUK_ASSERT_CTX_VALID(ctx);
 	heap = thr->heap;
 	DUK_ASSERT(heap->heap_object != NULL);
 	duk_push_hobject(ctx, heap->heap_object);
 	duk__push_stash(ctx);
 }
 
-void duk_push_global_stash(duk_context *ctx) {
-	DUK_ASSERT(ctx != NULL);
+DUK_EXTERNAL void duk_push_global_stash(duk_context *ctx) {
+	DUK_ASSERT_CTX_VALID(ctx);
 	duk_push_global_object(ctx);
 	duk__push_stash(ctx);
 }
 
-void duk_push_thread_stash(duk_context *ctx, duk_context *target_ctx) {
+DUK_EXTERNAL void duk_push_thread_stash(duk_context *ctx, duk_context *target_ctx) {
 	duk_hthread *thr = (duk_hthread *) ctx;
-	DUK_ASSERT(ctx != NULL);
+	DUK_ASSERT_CTX_VALID(ctx);
 	if (!target_ctx) {
-		DUK_ERROR(thr, DUK_ERR_API_ERROR, DUK_STR_INVALID_CALL_ARGS);
+		DUK_ERROR_API(thr, DUK_STR_INVALID_CALL_ARGS);
 		return;  /* not reached */
 	}
 	duk_push_hobject(ctx, (duk_hobject *) target_ctx);
@@ -11308,9 +21610,10 @@ void duk_push_thread_stash(duk_context *ctx, duk_context *target_ctx) {
 }
 
 /* XXX: duk_ssize_t would be useful here */
-static duk_int_t duk__try_push_vsprintf(duk_context *ctx, void *buf, duk_size_t sz, const char *fmt, va_list ap) {
+DUK_LOCAL duk_int_t duk__try_push_vsprintf(duk_context *ctx, void *buf, duk_size_t sz, const char *fmt, va_list ap) {
 	duk_int_t len;
 
+	DUK_ASSERT_CTX_VALID(ctx);
 	DUK_UNREF(ctx);
 
 	/* NUL terminator handling doesn't matter here */
@@ -11324,7 +21627,7 @@ static duk_int_t duk__try_push_vsprintf(duk_context *ctx, void *buf, duk_size_t
 	return -1;
 }
 
-const char *duk_push_vsprintf(duk_context *ctx, const char *fmt, va_list ap) {
+DUK_EXTERNAL const char *duk_push_vsprintf(duk_context *ctx, const char *fmt, va_list ap) {
 	duk_hthread *thr = (duk_hthread *) ctx;
 	duk_uint8_t stack_buf[DUK_PUSH_SPRINTF_INITIAL_SIZE];
 	duk_size_t sz = DUK_PUSH_SPRINTF_INITIAL_SIZE;
@@ -11333,7 +21636,7 @@ const char *duk_push_vsprintf(duk_context *ctx, const char *fmt, va_list ap) {
 	duk_int_t len;  /* XXX: duk_ssize_t */
 	const char *res;
 
-	DUK_ASSERT(ctx != NULL);
+	DUK_ASSERT_CTX_VALID(ctx);
 
 	/* special handling of fmt==NULL */
 	if (!fmt) {
@@ -11376,7 +21679,7 @@ const char *duk_push_vsprintf(duk_context *ctx, const char *fmt, va_list ap) {
 		/* failed, resize and try again */
 		sz = sz * 2;
 		if (sz >= DUK_PUSH_SPRINTF_SANITY_LIMIT) {
-			DUK_ERROR(thr, DUK_ERR_API_ERROR, DUK_STR_SPRINTF_TOO_LONG);
+			DUK_ERROR_API(thr, DUK_STR_SPRINTF_TOO_LONG);
 		}
 	}
 
@@ -11390,10 +21693,12 @@ const char *duk_push_vsprintf(duk_context *ctx, const char *fmt, va_list ap) {
 	return res;
 }
 
-const char *duk_push_sprintf(duk_context *ctx, const char *fmt, ...) {
+DUK_EXTERNAL const char *duk_push_sprintf(duk_context *ctx, const char *fmt, ...) {
 	va_list ap;
 	const char *ret;
 
+	DUK_ASSERT_CTX_VALID(ctx);
+
 	/* allow fmt==NULL */
 	va_start(ap, fmt);
 	ret = duk_push_vsprintf(ctx, fmt, ap);
@@ -11402,31 +21707,31 @@ const char *duk_push_sprintf(duk_context *ctx, const char *fmt, ...) {
 	return ret;
 }
 
-duk_idx_t duk_push_object_helper(duk_context *ctx, duk_uint_t hobject_flags_and_class, duk_small_int_t prototype_bidx) {
+DUK_INTERNAL duk_idx_t duk_push_object_helper(duk_context *ctx, duk_uint_t hobject_flags_and_class, duk_small_int_t prototype_bidx) {
 	duk_hthread *thr = (duk_hthread *) ctx;
 	duk_tval *tv_slot;
 	duk_hobject *h;
 	duk_idx_t ret;
 
-	DUK_ASSERT(ctx != NULL);
+	DUK_ASSERT_CTX_VALID(ctx);
 	DUK_ASSERT(prototype_bidx == -1 ||
 	           (prototype_bidx >= 0 && prototype_bidx < DUK_NUM_BUILTINS));
 
-	/* check stack before interning (avoid hanging temp) */
+	/* check stack first */
 	if (thr->valstack_top >= thr->valstack_end) {
-		DUK_ERROR(thr, DUK_ERR_API_ERROR, DUK_STR_PUSH_BEYOND_ALLOC_STACK);
+		DUK_ERROR_API(thr, DUK_STR_PUSH_BEYOND_ALLOC_STACK);
 	}
 
 	h = duk_hobject_alloc(thr->heap, hobject_flags_and_class);
 	if (!h) {
-		DUK_ERROR(thr, DUK_ERR_ALLOC_ERROR, DUK_STR_OBJECT_ALLOC_FAILED);
+		DUK_ERROR(thr, DUK_ERR_ALLOC_ERROR, DUK_STR_ALLOC_FAILED);
 	}
 
 	DUK_DDD(DUK_DDDPRINT("created object with flags: 0x%08lx", (unsigned long) h->hdr.h_flags));
 
 	tv_slot = thr->valstack_top;
 	DUK_TVAL_SET_OBJECT(tv_slot, h);
-	DUK_HOBJECT_INCREF(thr, h);
+	DUK_HOBJECT_INCREF(thr, h);  /* no side effects */
 	ret = (duk_idx_t) (thr->valstack_top - thr->valstack_bottom);
 	thr->valstack_top++;
 
@@ -11436,37 +21741,43 @@ duk_idx_t duk_push_object_helper(duk_context *ctx, duk_uint_t hobject_flags_and_
 		DUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr, h, thr->builtins[prototype_bidx]);
 	} else {
 		DUK_ASSERT(prototype_bidx == -1);
-		DUK_ASSERT(h->prototype == NULL);
+		DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h) == NULL);
 	}
 
 	return ret;
 }
 
-duk_idx_t duk_push_object_helper_proto(duk_context *ctx, duk_uint_t hobject_flags_and_class, duk_hobject *proto) {
+DUK_INTERNAL duk_idx_t duk_push_object_helper_proto(duk_context *ctx, duk_uint_t hobject_flags_and_class, duk_hobject *proto) {
 	duk_hthread *thr = (duk_hthread *) ctx;
 	duk_idx_t ret;
 	duk_hobject *h;
 
+	DUK_ASSERT_CTX_VALID(ctx);
+
 	ret = duk_push_object_helper(ctx, hobject_flags_and_class, -1);
 	h = duk_get_hobject(ctx, -1);
 	DUK_ASSERT(h != NULL);
-	DUK_ASSERT(h->prototype == NULL);
+	DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h) == NULL);
 	DUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr, h, proto);
 	return ret;
 }
 
-duk_idx_t duk_push_object(duk_context *ctx) {
+DUK_EXTERNAL duk_idx_t duk_push_object(duk_context *ctx) {
+	DUK_ASSERT_CTX_VALID(ctx);
+
 	return duk_push_object_helper(ctx,
 	                              DUK_HOBJECT_FLAG_EXTENSIBLE |
 	                              DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_OBJECT),
 	                              DUK_BIDX_OBJECT_PROTOTYPE);
 }
 
-duk_idx_t duk_push_array(duk_context *ctx) {
+DUK_EXTERNAL duk_idx_t duk_push_array(duk_context *ctx) {
 	duk_hthread *thr = (duk_hthread *) ctx;
 	duk_hobject *obj;
 	duk_idx_t ret;
 
+	DUK_ASSERT_CTX_VALID(ctx);
+
 	ret = duk_push_object_helper(ctx,
 	                             DUK_HOBJECT_FLAG_EXTENSIBLE |
 	                             DUK_HOBJECT_FLAG_ARRAY_PART |
@@ -11479,9 +21790,16 @@ duk_idx_t duk_push_array(duk_context *ctx) {
 	 *  An array must have a 'length' property (E5 Section 15.4.5.2).
 	 *  The special array behavior flag must only be enabled once the
 	 *  length property has been added.
+	 *
+	 *  The internal property must be a number (and preferably a
+	 *  fastint if fastint support is enabled).
 	 */
 
-	duk_push_number(ctx, 0.0);
+	duk_push_int(ctx, 0);
+#if defined(DUK_USE_FASTINT)
+	DUK_ASSERT(DUK_TVAL_IS_FASTINT(duk_require_tval(ctx, -1)));
+#endif
+
 	duk_hobject_define_property_internal(thr,
 	                                     obj,
 	                                     DUK_HTHREAD_STRING_LENGTH(thr),
@@ -11491,17 +21809,17 @@ duk_idx_t duk_push_array(duk_context *ctx) {
 	return ret;
 }
 
-duk_idx_t duk_push_thread_raw(duk_context *ctx, duk_uint_t flags) {
+DUK_EXTERNAL duk_idx_t duk_push_thread_raw(duk_context *ctx, duk_uint_t flags) {
 	duk_hthread *thr = (duk_hthread *) ctx;
 	duk_hthread *obj;
 	duk_idx_t ret;
 	duk_tval *tv_slot;
 
-	DUK_ASSERT(ctx != NULL);
+	DUK_ASSERT_CTX_VALID(ctx);
 
-	/* check stack before interning (avoid hanging temp) */
+	/* check stack first */
 	if (thr->valstack_top >= thr->valstack_end) {
-		DUK_ERROR(thr, DUK_ERR_API_ERROR, DUK_STR_PUSH_BEYOND_ALLOC_STACK);
+		DUK_ERROR_API(thr, DUK_STR_PUSH_BEYOND_ALLOC_STACK);
 	}
 
 	obj = duk_hthread_alloc(thr->heap,
@@ -11509,10 +21827,14 @@ duk_idx_t duk_push_thread_raw(duk_context *ctx, duk_uint_t flags) {
 	                        DUK_HOBJECT_FLAG_THREAD |
 	                        DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_THREAD));
 	if (!obj) {
-		DUK_ERROR(thr, DUK_ERR_ALLOC_ERROR, DUK_STR_THREAD_ALLOC_FAILED);
+		DUK_ERROR(thr, DUK_ERR_ALLOC_ERROR, DUK_STR_ALLOC_FAILED);
 	}
 	obj->state = DUK_HTHREAD_STATE_INACTIVE;
+#if defined(DUK_USE_HEAPPTR16)
+	obj->strs16 = thr->strs16;
+#else
 	obj->strs = thr->strs;
+#endif
 	DUK_DDD(DUK_DDDPRINT("created thread object with flags: 0x%08lx", (unsigned long) obj->obj.hdr.h_flags));
 
 	/* make the new thread reachable */
@@ -11524,7 +21846,7 @@ duk_idx_t duk_push_thread_raw(duk_context *ctx, duk_uint_t flags) {
 
 	/* important to do this *after* pushing, to make the thread reachable for gc */
 	if (!duk_hthread_init_stacks(thr->heap, obj)) {
-		DUK_ERROR(thr, DUK_ERR_ALLOC_ERROR, DUK_STR_THREAD_ALLOC_FAILED);
+		DUK_ERROR(thr, DUK_ERR_ALLOC_ERROR, DUK_STR_ALLOC_FAILED);
 	}
 
 	/* initialize built-ins - either by copying or creating new ones */
@@ -11546,17 +21868,17 @@ duk_idx_t duk_push_thread_raw(duk_context *ctx, duk_uint_t flags) {
 	return ret;
 }
 
-duk_idx_t duk_push_compiledfunction(duk_context *ctx) {
+DUK_INTERNAL duk_idx_t duk_push_compiledfunction(duk_context *ctx) {
 	duk_hthread *thr = (duk_hthread *) ctx;
 	duk_hcompiledfunction *obj;
 	duk_idx_t ret;
 	duk_tval *tv_slot;
 
-	DUK_ASSERT(ctx != NULL);
+	DUK_ASSERT_CTX_VALID(ctx);
 
-	/* check stack before interning (avoid hanging temp) */
+	/* check stack first */
 	if (thr->valstack_top >= thr->valstack_end) {
-		DUK_ERROR(thr, DUK_ERR_API_ERROR, DUK_STR_PUSH_BEYOND_ALLOC_STACK);
+		DUK_ERROR_API(thr, DUK_STR_PUSH_BEYOND_ALLOC_STACK);
 	}
 
 	/* Template functions are not strictly constructable (they don't
@@ -11569,7 +21891,7 @@ duk_idx_t duk_push_compiledfunction(duk_context *ctx) {
 	                                  DUK_HOBJECT_FLAG_COMPILEDFUNCTION |
 	                                  DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_FUNCTION));
 	if (!obj) {
-		DUK_ERROR(thr, DUK_ERR_ALLOC_ERROR, DUK_STR_FUNC_ALLOC_FAILED);
+		DUK_ERROR(thr, DUK_ERR_ALLOC_ERROR, DUK_STR_ALLOC_FAILED);
 	}
 
 	DUK_DDD(DUK_DDDPRINT("created compiled function object with flags: 0x%08lx", (unsigned long) obj->obj.hdr.h_flags));
@@ -11586,24 +21908,24 @@ duk_idx_t duk_push_compiledfunction(duk_context *ctx) {
 	return ret;
 }
 
-static duk_idx_t duk__push_c_function_raw(duk_context *ctx, duk_c_function func, duk_idx_t nargs, duk_uint_t flags) {
+DUK_LOCAL duk_idx_t duk__push_c_function_raw(duk_context *ctx, duk_c_function func, duk_idx_t nargs, duk_uint_t flags) {
 	duk_hthread *thr = (duk_hthread *) ctx;
 	duk_hnativefunction *obj;
 	duk_idx_t ret;
 	duk_tval *tv_slot;
-	duk_uint16_t func_nargs;
+	duk_int16_t func_nargs;
 
-	DUK_ASSERT(ctx != NULL);
+	DUK_ASSERT_CTX_VALID(ctx);
 
-	/* check stack before interning (avoid hanging temp) */
+	/* check stack first */
 	if (thr->valstack_top >= thr->valstack_end) {
-		DUK_ERROR(thr, DUK_ERR_API_ERROR, DUK_STR_PUSH_BEYOND_ALLOC_STACK);
+		DUK_ERROR_API(thr, DUK_STR_PUSH_BEYOND_ALLOC_STACK);
 	}
 	if (func == NULL) {
 		goto api_error;
 	}
 	if (nargs >= 0 && nargs < DUK_HNATIVEFUNCTION_NARGS_MAX) {
-		func_nargs = (duk_uint16_t) nargs;
+		func_nargs = (duk_int16_t) nargs;
 	} else if (nargs == DUK_VARARGS) {
 		func_nargs = DUK_HNATIVEFUNCTION_NARGS_VARARGS;
 	} else {
@@ -11612,7 +21934,7 @@ static duk_idx_t duk__push_c_function_raw(duk_context *ctx, duk_c_function func,
 
 	obj = duk_hnativefunction_alloc(thr->heap, flags);
 	if (!obj) {
-		DUK_ERROR(thr, DUK_ERR_ALLOC_ERROR, DUK_STR_FUNC_ALLOC_FAILED);
+		DUK_ERROR(thr, DUK_ERR_ALLOC_ERROR, DUK_STR_ALLOC_FAILED);
 	}
 
 	obj->func = func;
@@ -11633,13 +21955,15 @@ static duk_idx_t duk__push_c_function_raw(duk_context *ctx, duk_c_function func,
 	return ret;
 
  api_error:
-	DUK_ERROR(thr, DUK_ERR_API_ERROR, DUK_STR_INVALID_CALL_ARGS);
+	DUK_ERROR_API(thr, DUK_STR_INVALID_CALL_ARGS);
 	return 0;  /* not reached */
 }
 
-duk_idx_t duk_push_c_function(duk_context *ctx, duk_c_function func, duk_int_t nargs) {
+DUK_EXTERNAL duk_idx_t duk_push_c_function(duk_context *ctx, duk_c_function func, duk_int_t nargs) {
 	duk_uint_t flags;
 
+	DUK_ASSERT_CTX_VALID(ctx);
+
 	flags = DUK_HOBJECT_FLAG_EXTENSIBLE |
 	        DUK_HOBJECT_FLAG_CONSTRUCTABLE |
 	        DUK_HOBJECT_FLAG_NATIVEFUNCTION |
@@ -11648,13 +21972,15 @@ duk_idx_t duk_push_c_function(duk_context *ctx, duk_c_function func, duk_int_t n
 	        DUK_HOBJECT_FLAG_NOTAIL |
 	        DUK_HOBJECT_FLAG_EXOTIC_DUKFUNC |
 	        DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_FUNCTION);
-	
+
 	return duk__push_c_function_raw(ctx, func, nargs, flags);
 }
 
-void duk_push_c_function_noexotic(duk_context *ctx, duk_c_function func, duk_int_t nargs) {
+DUK_INTERNAL void duk_push_c_function_noexotic(duk_context *ctx, duk_c_function func, duk_int_t nargs) {
 	duk_uint_t flags;
 
+	DUK_ASSERT_CTX_VALID(ctx);
+
 	flags = DUK_HOBJECT_FLAG_EXTENSIBLE |
 	        DUK_HOBJECT_FLAG_CONSTRUCTABLE |
 	        DUK_HOBJECT_FLAG_NATIVEFUNCTION |
@@ -11662,4439 +21988,5759 @@ void duk_push_c_function_noexotic(duk_context *ctx, duk_c_function func, duk_int
 	        DUK_HOBJECT_FLAG_STRICT |
 	        DUK_HOBJECT_FLAG_NOTAIL |
 	        DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_FUNCTION);
-	
-	(void) duk__push_c_function_raw(ctx, func, nargs, flags);
-}
 
-void duk_push_c_function_noconstruct_noexotic(duk_context *ctx, duk_c_function func, duk_int_t nargs) {
-	duk_uint_t flags;
-
-	flags = DUK_HOBJECT_FLAG_EXTENSIBLE |
-	        DUK_HOBJECT_FLAG_NATIVEFUNCTION |
-	        DUK_HOBJECT_FLAG_NEWENV |
-	        DUK_HOBJECT_FLAG_STRICT |
-	        DUK_HOBJECT_FLAG_NOTAIL |
-	        DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_FUNCTION);
-	
 	(void) duk__push_c_function_raw(ctx, func, nargs, flags);
 }
 
-static duk_idx_t duk__push_error_object_vsprintf(duk_context *ctx, duk_errcode_t err_code, const char *filename, duk_int_t line, const char *fmt, va_list ap) {
-	duk_hthread *thr = (duk_hthread *) ctx;
-	duk_idx_t ret;
-	duk_hobject *proto;
-#ifdef DUK_USE_AUGMENT_ERROR_CREATE
-	duk_bool_t noblame_fileline;
-#endif
-
-	DUK_ASSERT(ctx != NULL);
-	DUK_ASSERT(thr != NULL);
-
-	/* Error code also packs a tracedata related flag. */
-#ifdef DUK_USE_AUGMENT_ERROR_CREATE
-	noblame_fileline = err_code & DUK_ERRCODE_FLAG_NOBLAME_FILELINE;
-#endif
-	err_code = err_code & (~DUK_ERRCODE_FLAG_NOBLAME_FILELINE);
-
-	/* error gets its 'name' from the prototype */
-	proto = duk_error_prototype_from_code(thr, err_code);
-	ret = duk_push_object_helper_proto(ctx,
-	                                   DUK_HOBJECT_FLAG_EXTENSIBLE |
-	                                   DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_ERROR),
-	                                   proto);
-
-	/* ... and its 'message' from an instance property */
-	if (fmt) {
-		duk_push_vsprintf(ctx, fmt, ap);
-		duk_def_prop_stridx(ctx, -2, DUK_STRIDX_MESSAGE, DUK_PROPDESC_FLAGS_WC);
-	} else {
-		/* If no explicit message given, put error code into message field
-		 * (as a number).  This is not fully in keeping with the Ecmascript
-		 * error model because messages are supposed to be strings (Error
-		 * constructors use ToString() on their argument).  However, it's
-		 * probably more useful than having a separate 'code' property.
-		 */
-		duk_push_int(ctx, err_code);
-		duk_def_prop_stridx(ctx, -2, DUK_STRIDX_MESSAGE, DUK_PROPDESC_FLAGS_WC);
-	}
-
-#if 0
-	/* Disabled for now, not sure this is a useful property */
-	duk_push_int(ctx, err_code);
-	duk_def_prop_stridx(ctx, -2, DUK_STRIDX_CODE, DUK_PROPDESC_FLAGS_WC);
-#endif
-
-	/* Creation time error augmentation */
-#ifdef DUK_USE_AUGMENT_ERROR_CREATE
-	/* filename may be NULL in which case file/line is not recorded */
-	duk_err_augment_error_create(thr, thr, filename, line, noblame_fileline);  /* may throw an error */
-#endif
-
-	return ret;
-}
-
-duk_idx_t duk_push_error_object_raw(duk_context *ctx, duk_errcode_t err_code, const char *filename, duk_int_t line, const char *fmt, ...) {
-	va_list ap;
-	duk_idx_t ret;
-
-	va_start(ap, fmt);
-	ret = duk__push_error_object_vsprintf(ctx, err_code, filename, line, fmt, ap);
-	va_end(ap);
-	return ret;
-}
-
-#ifndef DUK_USE_VARIADIC_MACROS
-duk_idx_t duk_push_error_object_stash(duk_context *ctx, duk_errcode_t err_code, const char *fmt, ...) {
-	const char *filename = duk_api_global_filename;
-	duk_int_t line = duk_api_global_line;
-	va_list ap;
-	duk_idx_t ret;
-
-	duk_api_global_filename = NULL;
-	duk_api_global_line = 0;
-	va_start(ap, fmt);
-	ret = duk__push_error_object_vsprintf(ctx, err_code, filename, line, fmt, ap);
-	va_end(ap);
-	return ret;
-}
-#endif
-
-/* XXX: repetition, see duk_push_object */
-void *duk_push_buffer(duk_context *ctx, duk_size_t size, duk_bool_t dynamic) {
-	duk_hthread *thr = (duk_hthread *) ctx;
-	duk_tval *tv_slot;
-	duk_hbuffer *h;
-
-	DUK_ASSERT(ctx != NULL);
-
-	/* check stack before interning (avoid hanging temp) */
-	if (thr->valstack_top >= thr->valstack_end) {
-		DUK_ERROR(thr, DUK_ERR_API_ERROR, DUK_STR_PUSH_BEYOND_ALLOC_STACK);
-	}
-
-	/* Check for maximum buffer length. */
-	if (size > DUK_HBUFFER_MAX_BYTELEN) {
-		DUK_ERROR(thr, DUK_ERR_RANGE_ERROR, DUK_STR_BUFFER_TOO_LONG);
-	}
-
-	h = duk_hbuffer_alloc(thr->heap, size, dynamic);
-	if (!h) {
-		DUK_ERROR(thr, DUK_ERR_ALLOC_ERROR, DUK_STR_BUFFER_ALLOC_FAILED);
-	}
-
-	tv_slot = thr->valstack_top;
-	DUK_TVAL_SET_BUFFER(tv_slot, h);
-	DUK_HBUFFER_INCREF(thr, h);
-	thr->valstack_top++;
-
-	return DUK_HBUFFER_GET_DATA_PTR(h);
-}
-
-void *duk_push_fixed_buffer(duk_context *ctx, duk_size_t size) {
-	return duk_push_buffer(ctx, size, 0);
-}
-
-void *duk_push_dynamic_buffer(duk_context *ctx, duk_size_t size) {
-	return duk_push_buffer(ctx, size, 1);
-}
-
-duk_idx_t duk_push_object_internal(duk_context *ctx) {
-	return duk_push_object_helper(ctx,
-	                              DUK_HOBJECT_FLAG_EXTENSIBLE |
-	                              DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_OBJECT),
-	                              -1);  /* no prototype */
-}
-
-void duk_push_hstring(duk_context *ctx, duk_hstring *h) {
-	duk_tval tv;
-	DUK_ASSERT(ctx != NULL);
-	DUK_ASSERT(h != NULL);
-	DUK_TVAL_SET_STRING(&tv, h);
-	duk_push_tval(ctx, &tv);
-}
-
-void duk_push_hstring_stridx(duk_context *ctx, duk_small_int_t stridx) {
-	duk_hthread *thr = (duk_hthread *) ctx;
-	DUK_ASSERT(stridx >= 0 && stridx < DUK_HEAP_NUM_STRINGS);
-	duk_push_hstring(ctx, thr->strs[stridx]);
-}
-
-void duk_push_hobject(duk_context *ctx, duk_hobject *h) {
-	duk_tval tv;
-	DUK_ASSERT(ctx != NULL);
-	DUK_ASSERT(h != NULL);
-	DUK_TVAL_SET_OBJECT(&tv, h);
-	duk_push_tval(ctx, &tv);
-}
-
-void duk_push_hbuffer(duk_context *ctx, duk_hbuffer *h) {
-	duk_tval tv;
-	DUK_ASSERT(ctx != NULL);
-	DUK_ASSERT(h != NULL);
-	DUK_TVAL_SET_BUFFER(&tv, h);
-	duk_push_tval(ctx, &tv);
-}
-
-void duk_push_hobject_bidx(duk_context *ctx, duk_small_int_t builtin_idx) {
-	duk_hthread *thr = (duk_hthread *) ctx;
-	DUK_ASSERT(ctx != NULL);
-	DUK_ASSERT(thr != NULL);
-	DUK_ASSERT(builtin_idx >= 0 && builtin_idx < DUK_NUM_BUILTINS);
-	DUK_ASSERT(thr->builtins[builtin_idx] != NULL);
-	duk_push_hobject(ctx, thr->builtins[builtin_idx]);
-}
-
-/*
- *  Poppers
- */
-
-void duk_pop_n(duk_context *ctx, duk_idx_t count) {
-	duk_hthread *thr = (duk_hthread *) ctx;
-	DUK_ASSERT(ctx != NULL);
-
-	if (count < 0) {
-		DUK_ERROR(thr, DUK_ERR_API_ERROR, DUK_STR_INVALID_COUNT);
-		return;
-	}
-
-	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
-	if ((duk_size_t) (thr->valstack_top - thr->valstack_bottom) < (duk_size_t) count) {
-		DUK_ERROR(thr, DUK_ERR_API_ERROR, DUK_STR_POP_TOO_MANY);
-	}
-
-	/*
-	 *  Must be very careful here, every DECREF may cause reallocation
-	 *  of our valstack.
-	 */
-
-	/* XXX: inlined DECREF macro would be nice here: no NULL check,
-	 * refzero queueing but no refzero algorithm run (= no pointer
-	 * instability), inline code.
-	 */
-	
-#ifdef DUK_USE_REFERENCE_COUNTING
-	while (count > 0) {
-		duk_tval tv_tmp;
-		duk_tval *tv;
-
-		tv = --thr->valstack_top;  /* tv points to element just below prev top */
-		DUK_ASSERT(tv >= thr->valstack_bottom);
-		DUK_TVAL_SET_TVAL(&tv_tmp, tv);
-		DUK_TVAL_SET_UNDEFINED_UNUSED(tv);
-		DUK_TVAL_DECREF(thr, &tv_tmp);  /* side effects */
-		count--;
-	}
-#else
-	while (count > 0) {
-		duk_tval *tv;
-
-		tv = --thr->valstack_top;
-		DUK_ASSERT(tv >= thr->valstack_bottom);
-		DUK_TVAL_SET_UNDEFINED_UNUSED(tv);
-		count--;
-	}
-#endif
-
-	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
-}
-
-void duk_pop(duk_context *ctx) {
-	duk_pop_n(ctx, 1);
-}
-
-void duk_pop_2(duk_context *ctx) {
-	duk_pop_n(ctx, 2);
-}
-
-void duk_pop_3(duk_context *ctx) {
-	duk_pop_n(ctx, 3);
-}
-
-/*
- *  Error throwing
- */
-
-void duk_throw(duk_context *ctx) {
-	duk_hthread *thr = (duk_hthread *) ctx;
-
-	DUK_ASSERT(thr->valstack_bottom >= thr->valstack);
-	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
-	DUK_ASSERT(thr->valstack_end >= thr->valstack_top);
-
-	if (thr->valstack_top == thr->valstack_bottom) {
-		DUK_ERROR(thr, DUK_ERR_API_ERROR, DUK_STR_INVALID_CALL_ARGS);
-	}
-
-	/* Errors are augmented when they are created, not when they are
-	 * thrown or re-thrown.  The current error handler, however, runs
-	 * just before an error is thrown.
-	 */
-
-#if defined(DUK_USE_AUGMENT_ERROR_THROW)
-	DUK_DDD(DUK_DDDPRINT("THROW ERROR (API): %!dT (before throw augment)", (duk_tval *) duk_get_tval(ctx, -1)));
-	duk_err_augment_error_throw(thr);
-#endif
-	DUK_DDD(DUK_DDDPRINT("THROW ERROR (API): %!dT (after throw augment)", (duk_tval *) duk_get_tval(ctx, -1)));
-
-	duk_err_setup_heap_ljstate(thr, DUK_LJ_TYPE_THROW);
-
-	/* thr->heap->lj.jmpbuf_ptr is checked by duk_err_longjmp() so we don't
-	 * need to check that here.  If the value is NULL, a panic occurs because
-	 * we can't return.
-	 */
-
-	duk_err_longjmp(thr);
-	DUK_UNREACHABLE();
-}
-
-void duk_fatal(duk_context *ctx, duk_errcode_t err_code, const char *err_msg) {
-	duk_hthread *thr = (duk_hthread *) ctx;
-
-	DUK_ASSERT(ctx != NULL);
-	DUK_ASSERT(thr != NULL);
-	DUK_ASSERT(thr->heap != NULL);
-	DUK_ASSERT(thr->heap->fatal_func != NULL);
-
-	DUK_D(DUK_DPRINT("fatal error occurred, code %ld, message %s",
-	                 (long) err_code, (const char *) err_msg));
-
-	/* fatal_func should be noreturn, but noreturn declarations on function
-	 * pointers has a very spotty support apparently so it's not currently
-	 * done.
-	 */
-	thr->heap->fatal_func(ctx, err_code, err_msg);
-
-	DUK_PANIC(DUK_ERR_API_ERROR, "fatal handler returned");
-}
-
-void duk_error_raw(duk_context *ctx, duk_errcode_t err_code, const char *filename, duk_int_t line, const char *fmt, ...) {
-	va_list ap;
-	va_start(ap, fmt);
-	duk__push_error_object_vsprintf(ctx, err_code, filename, line, fmt, ap);
-	va_end(ap);
-	duk_throw(ctx);
-}
-
-#ifndef DUK_USE_VARIADIC_MACROS
-void duk_error_stash(duk_context *ctx, duk_errcode_t err_code, const char *fmt, ...) {
-	const char *filename = duk_api_global_filename;
-	duk_int_t line = duk_api_global_line;
-	va_list ap;
-
-	duk_api_global_filename = NULL;
-	duk_api_global_line = 0;
-
-	va_start(ap, fmt);
-	duk__push_error_object_vsprintf(ctx, err_code, filename, line, fmt, ap);
-	va_end(ap);
-	duk_throw(ctx);
-}
-#endif
-
-duk_bool_t duk_equals(duk_context *ctx, duk_idx_t index1, duk_idx_t index2) {
-	duk_hthread *thr = (duk_hthread *) ctx;
-	duk_tval *tv1, *tv2;
-
-	tv1 = duk_get_tval(ctx, index1);
-	if (!tv1) {
-		return 0;
-	}
-	tv2 = duk_get_tval(ctx, index2);
-	if (!tv2) {
-		return 0;
-	}
-
-	/* Coercion may be needed, the helper handles that by pushing the
-	 * tagged values to the stack.
-	 */
-	return duk_js_equals(thr, tv1, tv2);
-}
-
-duk_bool_t duk_strict_equals(duk_context *ctx, duk_idx_t index1, duk_idx_t index2) {
-	duk_tval *tv1, *tv2;
-
-	tv1 = duk_get_tval(ctx, index1);
-	if (!tv1) {
-		return 0;
-	}
-	tv2 = duk_get_tval(ctx, index2);
-	if (!tv2) {
-		return 0;
-	}
-
-	/* No coercions or other side effects, so safe */
-	return duk_js_strict_equals(tv1, tv2);
-}
-
-/*
- *  Heap creation
- */
-
-duk_context *duk_create_heap(duk_alloc_function alloc_func,
-                             duk_realloc_function realloc_func,
-                             duk_free_function free_func,
-                             void *alloc_udata,
-                             duk_fatal_function fatal_handler) {
-	duk_heap *heap = NULL;
-	duk_context *ctx;
-
-	/* Assume that either all memory funcs are NULL or non-NULL, mixed
-	 * cases will now be unsafe.
-	 */
-
-	/* XXX: just assert non-NULL values here and make caller arguments
-	 * do the defaulting to the default implementations (smaller code)?
-	 */
-
-	if (!alloc_func) {
-		DUK_ASSERT(realloc_func == NULL);
-		DUK_ASSERT(free_func == NULL);
-		alloc_func = duk_default_alloc_function;
-		realloc_func = duk_default_realloc_function;
-		free_func = duk_default_free_function;
-	} else {
-		DUK_ASSERT(realloc_func != NULL);
-		DUK_ASSERT(free_func != NULL);
-	}
-
-	if (!fatal_handler) {
-		fatal_handler = duk_default_fatal_handler;
-	}
-
-	DUK_ASSERT(alloc_func != NULL);
-	DUK_ASSERT(realloc_func != NULL);
-	DUK_ASSERT(free_func != NULL);
-	DUK_ASSERT(fatal_handler != NULL);
-
-	heap = duk_heap_alloc(alloc_func, realloc_func, free_func, alloc_udata, fatal_handler);
-	if (!heap) {
-		return NULL;
-	}
-	ctx = (duk_context *) heap->heap_thread;
-	DUK_ASSERT(ctx != NULL);
-	DUK_ASSERT(((duk_hthread *) ctx)->heap != NULL);
-	return ctx;
-}
-
-void duk_destroy_heap(duk_context *ctx) {
-	duk_hthread *thr = (duk_hthread *) ctx;
-	duk_heap *heap;
-
-	if (!ctx) {
-		return;
-	}
-	heap = thr->heap;
-	DUK_ASSERT(heap != NULL);
-
-	duk_heap_free(heap);
-}
-#line 1 "duk_api_buffer.c"
-/*
- *  Buffer
- */
-
-/* include removed: duk_internal.h */
-
-void *duk_resize_buffer(duk_context *ctx, duk_idx_t index, duk_size_t new_size) {
-	duk_hthread *thr = (duk_hthread *) ctx;
-	duk_hbuffer_dynamic *h;
-
-	DUK_ASSERT(ctx != NULL);
-
-	h = (duk_hbuffer_dynamic *) duk_require_hbuffer(ctx, index);
-	DUK_ASSERT(h != NULL);
-
-	if (!DUK_HBUFFER_HAS_DYNAMIC(h)) {
-		DUK_ERROR(thr, DUK_ERR_TYPE_ERROR, "buffer is not dynamic");
-	}
-
-	/* maximum size check is handled by callee */
-	duk_hbuffer_resize(thr, h, new_size, new_size);  /* snug */
-
-	return DUK_HBUFFER_DYNAMIC_GET_CURR_DATA_PTR(h);
-}
-#line 1 "duk_api_call.c"
-/*
- *  Calls.
- *
- *  Protected variants should avoid ever throwing an error.
- */
-
-/* include removed: duk_internal.h */
-
-/* Prepare value stack for a method call through an object property.
- * May currently throw an error e.g. when getting the property.
- */
-static void duk__call_prop_prep_stack(duk_context *ctx, duk_idx_t normalized_obj_index, duk_idx_t nargs) {
-	DUK_DDD(DUK_DDDPRINT("duk__call_prop_prep_stack, normalized_obj_index=%ld, nargs=%ld, stacktop=%ld",
-	                     (long) normalized_obj_index, (long) nargs, (long) duk_get_top(ctx)));
-
-	/* [... key arg1 ... argN] */
-
-	/* duplicate key */
-	duk_dup(ctx, -nargs - 1);  /* Note: -nargs alone would fail for nargs == 0, this is OK */
-	duk_get_prop(ctx, normalized_obj_index);
-
-	DUK_DDD(DUK_DDDPRINT("func: %!T", (duk_tval *) duk_get_tval(ctx, -1)));
-
-	/* [... key arg1 ... argN func] */
-
-	duk_replace(ctx, -nargs - 2);
-
-	/* [... func arg1 ... argN] */
-
-	duk_dup(ctx, normalized_obj_index);
-	duk_insert(ctx, -nargs - 1);
-
-	/* [... func this arg1 ... argN] */
-}
-
-void duk_call(duk_context *ctx, duk_idx_t nargs) {
-	duk_hthread *thr = (duk_hthread *) ctx;
-	duk_small_uint_t call_flags;
-	duk_idx_t idx_func;
-	duk_int_t rc;
-
-	DUK_ASSERT(ctx != NULL);
-	DUK_ASSERT(thr != NULL);
-
-	idx_func = duk_get_top(ctx) - nargs - 1;
-	if (idx_func < 0 || nargs < 0) {
-		/* note that we can't reliably pop anything here */
-		DUK_ERROR(thr, DUK_ERR_API_ERROR, DUK_STR_INVALID_CALL_ARGS);
-	}
-
-	/* XXX: awkward; we assume there is space for this, overwrite
-	 * directly instead?
-	 */
-	duk_push_undefined(ctx);
-	duk_insert(ctx, idx_func + 1);
-
-	call_flags = 0;  /* not protected, respect reclimit, not constructor */
-
-	rc = duk_handle_call(thr,           /* thread */
-	                     nargs,         /* num_stack_args */
-	                     call_flags);   /* call_flags */
-	DUK_UNREF(rc);
-}
-
-void duk_call_method(duk_context *ctx, duk_idx_t nargs) {
-	duk_hthread *thr = (duk_hthread *) ctx;
-	duk_small_uint_t call_flags;
-	duk_idx_t idx_func;
-	duk_int_t rc;
-
-	DUK_ASSERT(ctx != NULL);
-	DUK_ASSERT(thr != NULL);
-
-	idx_func = duk_get_top(ctx) - nargs - 2;  /* must work for nargs <= 0 */
-	if (idx_func < 0 || nargs < 0) {
-		/* note that we can't reliably pop anything here */
-		DUK_ERROR(thr, DUK_ERR_API_ERROR, DUK_STR_INVALID_CALL_ARGS);
-	}
-
-	call_flags = 0;  /* not protected, respect reclimit, not constructor */
-
-	rc = duk_handle_call(thr,           /* thread */
-	                     nargs,         /* num_stack_args */
-	                     call_flags);   /* call_flags */
-	DUK_UNREF(rc);
-}
-
-void duk_call_prop(duk_context *ctx, duk_idx_t obj_index, duk_idx_t nargs) {
-	/*
-	 *  XXX: if duk_handle_call() took values through indices, this could be
-	 *  made much more sensible.  However, duk_handle_call() needs to fudge
-	 *  the 'this' and 'func' values to handle bound function chains, which
-	 *  is now done "in-place", so this is not a trivial change.
-	 */
+DUK_INTERNAL void duk_push_c_function_noconstruct_noexotic(duk_context *ctx, duk_c_function func, duk_int_t nargs) {
+	duk_uint_t flags;
 
-	obj_index = duk_require_normalize_index(ctx, obj_index);  /* make absolute */
+	DUK_ASSERT_CTX_VALID(ctx);
 
-	duk__call_prop_prep_stack(ctx, obj_index, nargs);
+	flags = DUK_HOBJECT_FLAG_EXTENSIBLE |
+	        DUK_HOBJECT_FLAG_NATIVEFUNCTION |
+	        DUK_HOBJECT_FLAG_NEWENV |
+	        DUK_HOBJECT_FLAG_STRICT |
+	        DUK_HOBJECT_FLAG_NOTAIL |
+	        DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_FUNCTION);
 
-	duk_call_method(ctx, nargs);
+	(void) duk__push_c_function_raw(ctx, func, nargs, flags);
 }
 
-duk_int_t duk_pcall(duk_context *ctx, duk_idx_t nargs) {
+DUK_EXTERNAL duk_idx_t duk_push_c_lightfunc(duk_context *ctx, duk_c_function func, duk_idx_t nargs, duk_idx_t length, duk_int_t magic) {
 	duk_hthread *thr = (duk_hthread *) ctx;
-	duk_small_uint_t call_flags;
-	duk_idx_t idx_func;
-	duk_int_t rc;
+	duk_tval tv_tmp;
+	duk_small_uint_t lf_flags;
 
-	DUK_ASSERT(ctx != NULL);
-	DUK_ASSERT(thr != NULL);
+	DUK_ASSERT_CTX_VALID(ctx);
 
-	idx_func = duk_get_top(ctx) - nargs - 1;  /* must work for nargs <= 0 */
-	if (idx_func < 0 || nargs < 0) {
-		/* We can't reliably pop anything here because the stack input
-		 * shape is incorrect.  So we throw an error; if the caller has
-		 * no catch point for this, a fatal error will occur.  Another
-		 * alternative would be to just return an error.  But then the
-		 * stack would be in an unknown state which might cause some
-		 * very hard to diagnose problems later on.  Also note that even
-		 * if we did not throw an error here, the underlying call handler
-		 * might STILL throw an out-of-memory error or some other internal
-		 * fatal error.
-		 */
-		DUK_ERROR(thr, DUK_ERR_API_ERROR, DUK_STR_INVALID_CALL_ARGS);
-		return DUK_EXEC_ERROR;  /* unreachable */
+	/* check stack first */
+	if (thr->valstack_top >= thr->valstack_end) {
+		DUK_ERROR_API(thr, DUK_STR_PUSH_BEYOND_ALLOC_STACK);
 	}
 
-	/* awkward; we assume there is space for this */
-	duk_push_undefined(ctx);
-	duk_insert(ctx, idx_func + 1);
-
-	call_flags = DUK_CALL_FLAG_PROTECTED;  /* protected, respect reclimit, not constructor */
+	if (nargs >= DUK_LFUNC_NARGS_MIN && nargs <= DUK_LFUNC_NARGS_MAX) {
+		/* as is */
+	} else if (nargs == DUK_VARARGS) {
+		nargs = DUK_LFUNC_NARGS_VARARGS;
+	} else {
+		goto api_error;
+	}
+	if (!(length >= DUK_LFUNC_LENGTH_MIN && length <= DUK_LFUNC_LENGTH_MAX)) {
+		goto api_error;
+	}
+	if (!(magic >= DUK_LFUNC_MAGIC_MIN && magic <= DUK_LFUNC_MAGIC_MAX)) {
+		goto api_error;
+	}
 
-	rc = duk_handle_call(thr,           /* thread */
-	                     nargs,         /* num_stack_args */
-	                     call_flags);   /* call_flags */
+	lf_flags = DUK_LFUNC_FLAGS_PACK(magic, length, nargs);
+	DUK_TVAL_SET_LIGHTFUNC(&tv_tmp, func, lf_flags);
+	duk_push_tval(ctx, &tv_tmp);  /* XXX: direct valstack write */
+	DUK_ASSERT(thr->valstack_top != thr->valstack_bottom);
+	return ((duk_idx_t) (thr->valstack_top - thr->valstack_bottom)) - 1;
 
-	return rc;
+ api_error:
+	DUK_ERROR_API(thr, DUK_STR_INVALID_CALL_ARGS);
+	return 0;  /* not reached */
 }
 
-duk_int_t duk_pcall_method(duk_context *ctx, duk_idx_t nargs) {
+DUK_INTERNAL duk_hbufferobject *duk_push_bufferobject_raw(duk_context *ctx, duk_uint_t hobject_flags_and_class, duk_small_int_t prototype_bidx) {
 	duk_hthread *thr = (duk_hthread *) ctx;
-	duk_small_uint_t call_flags;
-	duk_idx_t idx_func;
-	duk_int_t rc;
+	duk_hbufferobject *obj;
+	duk_tval *tv_slot;
 
 	DUK_ASSERT(ctx != NULL);
-	DUK_ASSERT(thr != NULL);
+	DUK_ASSERT(prototype_bidx >= 0);
 
-	idx_func = duk_get_top(ctx) - nargs - 2;  /* must work for nargs <= 0 */
-	if (idx_func < 0 || nargs < 0) {
-		/* See comments in duk_pcall(). */
-		DUK_ERROR(thr, DUK_ERR_API_ERROR, DUK_STR_INVALID_CALL_ARGS);
-		return DUK_EXEC_ERROR;  /* unreachable */
+	/* check stack first */
+	if (thr->valstack_top >= thr->valstack_end) {
+		DUK_ERROR_API(thr, DUK_STR_PUSH_BEYOND_ALLOC_STACK);
 	}
 
-	call_flags = DUK_CALL_FLAG_PROTECTED;  /* protected, respect reclimit, not constructor */
+	obj = duk_hbufferobject_alloc(thr->heap, hobject_flags_and_class);
+	if (!obj) {
+		DUK_ERROR(thr, DUK_ERR_ALLOC_ERROR, DUK_STR_ALLOC_FAILED);
+	}
 
-	rc = duk_handle_call(thr,           /* thread */
-	                     nargs,         /* num_stack_args */
-	                     call_flags);   /* call_flags */
+	DUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr, (duk_hobject *) obj, thr->builtins[prototype_bidx]);
+	DUK_ASSERT_HBUFFEROBJECT_VALID(obj);
 
-	return rc;
-}
+	tv_slot = thr->valstack_top;
+	DUK_TVAL_SET_OBJECT(tv_slot, (duk_hobject *) obj);
+	DUK_HOBJECT_INCREF(thr, obj);
+	thr->valstack_top++;
 
-static duk_ret_t duk__pcall_prop_raw(duk_context *ctx) {
-	duk_idx_t obj_index;
-	duk_idx_t nargs;
+	return obj;
+}
+
+/* XXX: There's quite a bit of overlap with buffer creation handling in
+ * duk_bi_buffer.c.  Look for overlap and refactor.
+ */
+#define DUK__PACK_ARGS(classnum,protobidx,elemtype,elemshift,isview) \
+	(((classnum) << 24) | ((protobidx) << 16) | ((elemtype) << 8) | ((elemshift) << 4) | (isview))
+
+#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
+static const duk_uint32_t duk__bufobj_flags_lookup[] = {
+	DUK__PACK_ARGS(DUK_HOBJECT_CLASS_BUFFER,            DUK_BIDX_BUFFER_PROTOTYPE,            DUK_HBUFFEROBJECT_ELEM_UINT8,        0, 0),  /* DUK_BUFOBJ_DUKTAPE_BUFFER */
+	DUK__PACK_ARGS(DUK_HOBJECT_CLASS_BUFFER,            DUK_BIDX_NODEJS_BUFFER_PROTOTYPE,     DUK_HBUFFEROBJECT_ELEM_UINT8,        0, 0),  /* DUK_BUFOBJ_NODEJS_BUFFER */
+	DUK__PACK_ARGS(DUK_HOBJECT_CLASS_ARRAYBUFFER,       DUK_BIDX_ARRAYBUFFER_PROTOTYPE,       DUK_HBUFFEROBJECT_ELEM_UINT8,        0, 0),  /* DUK_BUFOBJ_ARRAYBUFFER */
+	DUK__PACK_ARGS(DUK_HOBJECT_CLASS_DATAVIEW,          DUK_BIDX_DATAVIEW_PROTOTYPE,          DUK_HBUFFEROBJECT_ELEM_UINT8,        0, 1),  /* DUK_BUFOBJ_DATAVIEW */
+	DUK__PACK_ARGS(DUK_HOBJECT_CLASS_INT8ARRAY,         DUK_BIDX_INT8ARRAY_PROTOTYPE,         DUK_HBUFFEROBJECT_ELEM_INT8,         0, 1),  /* DUK_BUFOBJ_INT8ARRAY */
+	DUK__PACK_ARGS(DUK_HOBJECT_CLASS_UINT8ARRAY,        DUK_BIDX_UINT8ARRAY_PROTOTYPE,        DUK_HBUFFEROBJECT_ELEM_UINT8,        0, 1),  /* DUK_BUFOBJ_UINT8ARRAY */
+	DUK__PACK_ARGS(DUK_HOBJECT_CLASS_UINT8CLAMPEDARRAY, DUK_BIDX_UINT8CLAMPEDARRAY_PROTOTYPE, DUK_HBUFFEROBJECT_ELEM_UINT8CLAMPED, 0, 1),  /* DUK_BUFOBJ_UINT8CLAMPEDARRAY */
+	DUK__PACK_ARGS(DUK_HOBJECT_CLASS_INT16ARRAY,        DUK_BIDX_INT16ARRAY_PROTOTYPE,        DUK_HBUFFEROBJECT_ELEM_INT16,        1, 1),  /* DUK_BUFOBJ_INT16ARRAY */
+	DUK__PACK_ARGS(DUK_HOBJECT_CLASS_UINT16ARRAY,       DUK_BIDX_UINT16ARRAY_PROTOTYPE,       DUK_HBUFFEROBJECT_ELEM_UINT16,       1, 1),  /* DUK_BUFOBJ_UINT16ARRAY */
+	DUK__PACK_ARGS(DUK_HOBJECT_CLASS_INT32ARRAY,        DUK_BIDX_INT32ARRAY_PROTOTYPE,        DUK_HBUFFEROBJECT_ELEM_INT32,        2, 1),  /* DUK_BUFOBJ_INT32ARRAY */
+	DUK__PACK_ARGS(DUK_HOBJECT_CLASS_UINT32ARRAY,       DUK_BIDX_UINT32ARRAY_PROTOTYPE,       DUK_HBUFFEROBJECT_ELEM_UINT32,       2, 1),  /* DUK_BUFOBJ_UINT32ARRAY */
+	DUK__PACK_ARGS(DUK_HOBJECT_CLASS_FLOAT32ARRAY,      DUK_BIDX_FLOAT32ARRAY_PROTOTYPE,      DUK_HBUFFEROBJECT_ELEM_FLOAT32,      2, 1),  /* DUK_BUFOBJ_FLOAT32ARRAY */
+	DUK__PACK_ARGS(DUK_HOBJECT_CLASS_FLOAT64ARRAY,      DUK_BIDX_FLOAT64ARRAY_PROTOTYPE,      DUK_HBUFFEROBJECT_ELEM_FLOAT64,      3, 1)   /* DUK_BUFOBJ_FLOAT64ARRAY */
+};
+#else  /* DUK_USE_BUFFEROBJECT_SUPPORT */
+/* Only allow Duktape.Buffer when support disabled. */
+static const duk_uint32_t duk__bufobj_flags_lookup[] = {
+	DUK__PACK_ARGS(DUK_HOBJECT_CLASS_BUFFER,            DUK_BIDX_BUFFER_PROTOTYPE,            DUK_HBUFFEROBJECT_ELEM_UINT8,        0, 0)   /* DUK_BUFOBJ_DUKTAPE_BUFFER */
+};
+#endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
+#undef DUK__PACK_ARGS
 
-	/* Get the original arguments.  Note that obj_index may be a relative
-	 * index so the stack must have the same top when we use it.
-	 */
+DUK_EXTERNAL void duk_push_buffer_object(duk_context *ctx, duk_idx_t idx_buffer, duk_size_t byte_offset, duk_size_t byte_length, duk_uint_t flags) {
+	duk_hthread *thr;
+	duk_hbufferobject *h_bufobj;
+	duk_hbuffer *h_val;
+	duk_uint32_t tmp;
+	duk_uint_t classnum;
+	duk_uint_t protobidx;
+	duk_uint_t lookupidx;
+	duk_uint_t uint_offset, uint_length, uint_added;
 
-	obj_index = (duk_idx_t) duk_get_int(ctx, -2);
-	nargs = (duk_idx_t) duk_get_int(ctx, -1);
-	duk_pop_2(ctx);
+	DUK_ASSERT_CTX_VALID(ctx);
+	thr = (duk_hthread *) ctx;
+	DUK_UNREF(thr);
 
-	obj_index = duk_require_normalize_index(ctx, obj_index);  /* make absolute */
-	duk__call_prop_prep_stack(ctx, obj_index, nargs);
-	duk_call_method(ctx, nargs);
-	return 1;
-}
+	/* The underlying types for offset/length in duk_hbufferobject is
+	 * duk_uint_t; make sure argument values fit and that offset + length
+	 * does not wrap.
+	 */
+	uint_offset = (duk_uint_t) byte_offset;
+	uint_length = (duk_uint_t) byte_length;
+	if (sizeof(duk_size_t) != sizeof(duk_uint_t)) {
+		if ((duk_size_t) uint_offset != byte_offset || (duk_size_t) uint_length != byte_length) {
+			goto range_error;
+		}
+	}
+	uint_added = uint_offset + uint_length;
+	if (uint_added < uint_offset) {
+		goto range_error;
+	}
+	DUK_ASSERT(uint_added >= uint_offset && uint_added >= uint_length);
+
+	DUK_ASSERT_DISABLE(flags >= 0);  /* flags is unsigned */
+	lookupidx = flags & 0x0f;  /* 4 low bits */
+	if (lookupidx >= sizeof(duk__bufobj_flags_lookup) / sizeof(duk_uint32_t)) {
+		goto arg_error;
+	}
+	tmp = duk__bufobj_flags_lookup[lookupidx];
+	classnum = tmp >> 24;
+	protobidx = (tmp >> 16) & 0xff;
+
+	h_val = duk_require_hbuffer(ctx, idx_buffer);
+	DUK_ASSERT(h_val != NULL);
+
+	h_bufobj = duk_push_bufferobject_raw(ctx,
+	                                     DUK_HOBJECT_FLAG_EXTENSIBLE |
+	                                     DUK_HOBJECT_FLAG_BUFFEROBJECT |
+	                                     DUK_HOBJECT_CLASS_AS_FLAGS(classnum),
+	                                     protobidx);
+	DUK_ASSERT(h_bufobj != NULL);
+
+	h_bufobj->buf = h_val;
+	DUK_HBUFFER_INCREF(thr, h_val);
+	h_bufobj->offset = uint_offset;
+	h_bufobj->length = uint_length;
+	h_bufobj->shift = (tmp >> 4) & 0x0f;
+	h_bufobj->elem_type = (tmp >> 8) & 0xff;
+	h_bufobj->is_view = tmp & 0x0f;
+	DUK_ASSERT_HBUFFEROBJECT_VALID(h_bufobj);
+
+#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
+	/* TypedArray views need an automatic ArrayBuffer which must be
+	 * provided as .buffer property of the view.  Just create a new
+	 * ArrayBuffer sharing the same underlying buffer.
+	 */
+	if (flags & DUK_BUFOBJ_CREATE_ARRBUF) {
+		h_bufobj = duk_push_bufferobject_raw(ctx,
+		                                     DUK_HOBJECT_FLAG_EXTENSIBLE |
+		                                     DUK_HOBJECT_FLAG_BUFFEROBJECT |
+		                                     DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_ARRAYBUFFER),
+		                                     DUK_BIDX_ARRAYBUFFER_PROTOTYPE);
+
+		DUK_ASSERT(h_bufobj != NULL);
+
+		h_bufobj->buf = h_val;
+		DUK_HBUFFER_INCREF(thr, h_val);
+		h_bufobj->offset = uint_offset;
+		h_bufobj->length = uint_length;
+		DUK_ASSERT(h_bufobj->shift == 0);
+		h_bufobj->elem_type = DUK_HBUFFEROBJECT_ELEM_UINT8;
+		DUK_ASSERT(h_bufobj->is_view == 0);
+		DUK_ASSERT_HBUFFEROBJECT_VALID(h_bufobj);
+
+		duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_LC_BUFFER, DUK_PROPDESC_FLAGS_NONE);
+		duk_compact(ctx, -1);
+	}
+#endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
 
-duk_int_t duk_pcall_prop(duk_context *ctx, duk_idx_t obj_index, duk_idx_t nargs) {
-	/*
-	 *  Must be careful to catch errors related to value stack manipulation
-	 *  and property lookup, not just the call itself.
-	 */
+	return;
 
-	duk_push_idx(ctx, obj_index);
-	duk_push_idx(ctx, nargs);
+ range_error:
+	DUK_ERROR(thr, DUK_ERR_RANGE_ERROR, DUK_STR_INVALID_CALL_ARGS);
+	return;  /* not reached */
 
-	/* Inputs: explicit arguments (nargs), +1 for key, +2 for obj_index/nargs passing.
-	 * If the value stack does not contain enough args, an error is thrown; this matches
-	 * behavior of the other protected call API functions.
-	 */
-	return duk_safe_call(ctx, duk__pcall_prop_raw, nargs + 1 + 2 /*nargs*/, 1 /*nrets*/);
+ arg_error:
+	DUK_ERROR(thr, DUK_ERR_TYPE_ERROR, DUK_STR_INVALID_CALL_ARGS);
+	return;  /* not reached */
 }
 
-duk_int_t duk_safe_call(duk_context *ctx, duk_safe_call_function func, duk_idx_t nargs, duk_idx_t nrets) {
+DUK_EXTERNAL duk_idx_t duk_push_error_object_va_raw(duk_context *ctx, duk_errcode_t err_code, const char *filename, duk_int_t line, const char *fmt, va_list ap) {
 	duk_hthread *thr = (duk_hthread *) ctx;
-	duk_int_t rc;
+	duk_idx_t ret;
+	duk_hobject *proto;
+#ifdef DUK_USE_AUGMENT_ERROR_CREATE
+	duk_bool_t noblame_fileline;
+#endif
 
-	DUK_ASSERT(ctx != NULL);
+	DUK_ASSERT_CTX_VALID(ctx);
 	DUK_ASSERT(thr != NULL);
+	DUK_UNREF(filename);
+	DUK_UNREF(line);
 
-	if (duk_get_top(ctx) < nargs || nrets < 0) {
-		/* See comments in duk_pcall(). */
-		DUK_ERROR(thr, DUK_ERR_API_ERROR, DUK_STR_INVALID_CALL_ARGS);
-		return DUK_EXEC_ERROR;  /* unreachable */
+	/* Error code also packs a tracedata related flag. */
+#ifdef DUK_USE_AUGMENT_ERROR_CREATE
+	noblame_fileline = err_code & DUK_ERRCODE_FLAG_NOBLAME_FILELINE;
+#endif
+	err_code = err_code & (~DUK_ERRCODE_FLAG_NOBLAME_FILELINE);
+
+	/* error gets its 'name' from the prototype */
+	proto = duk_error_prototype_from_code(thr, err_code);
+	ret = duk_push_object_helper_proto(ctx,
+	                                   DUK_HOBJECT_FLAG_EXTENSIBLE |
+	                                   DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_ERROR),
+	                                   proto);
+
+	/* ... and its 'message' from an instance property */
+	if (fmt) {
+		duk_push_vsprintf(ctx, fmt, ap);
+		duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_MESSAGE, DUK_PROPDESC_FLAGS_WC);
+	} else {
+		/* If no explicit message given, put error code into message field
+		 * (as a number).  This is not fully in keeping with the Ecmascript
+		 * error model because messages are supposed to be strings (Error
+		 * constructors use ToString() on their argument).  However, it's
+		 * probably more useful than having a separate 'code' property.
+		 */
+		duk_push_int(ctx, err_code);
+		duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_MESSAGE, DUK_PROPDESC_FLAGS_WC);
 	}
 
-	rc = duk_handle_safe_call(thr,           /* thread */
-	                          func,          /* func */
-	                          nargs,         /* num_stack_args */
-	                          nrets);        /* num_stack_res */
+#if 0
+	/* Disabled for now, not sure this is a useful property */
+	duk_push_int(ctx, err_code);
+	duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_CODE, DUK_PROPDESC_FLAGS_WC);
+#endif
 
-	return rc;
+	/* Creation time error augmentation */
+#ifdef DUK_USE_AUGMENT_ERROR_CREATE
+	/* filename may be NULL in which case file/line is not recorded */
+	duk_err_augment_error_create(thr, thr, filename, line, noblame_fileline);  /* may throw an error */
+#endif
+
+	return ret;
 }
 
-void duk_new(duk_context *ctx, duk_idx_t nargs) {
-	/*
-	 *  There are two [[Construct]] operations in the specification:
-	 *
-	 *    - E5 Section 13.2.2: for Function objects
-	 *    - E5 Section 15.3.4.5.2: for "bound" Function objects
-	 *
-	 *  The chain of bound functions is resolved in Section 15.3.4.5.2,
-	 *  with arguments "piling up" until the [[Construct]] internal
-	 *  method is called on the final, actual Function object.  Note
-	 *  that the "prototype" property is looked up *only* from the
-	 *  final object, *before* calling the constructor.
-	 *
-	 *  Currently we follow the bound function chain here to get the
-	 *  "prototype" property value from the final, non-bound function.
-	 *  However, we let duk_handle_call() handle the argument "piling"
-	 *  when the constructor is called.  The bound function chain is
-	 *  thus now processed twice.
-	 *
-	 *  When constructing new Array instances, an unnecessary object is
-	 *  created and discarded now: the standard [[Construct]] creates an
-	 *  object, and calls the Array constructor.  The Array constructor
-	 *  returns an Array instance, which is used as the result value for
-	 *  the "new" operation; the object created before the Array constructor
-	 *  call is discarded.
-	 *
-	 *  This would be easy to fix, e.g. by knowing that the Array constructor
-	 *  will always create a replacement object and skip creating the fallback
-	 *  object in that case.
-	 *
-	 *  Note: functions called via "new" need to know they are called as a
-	 *  constructor.  For instance, built-in constructors behave differently
-	 *  depending on how they are called.
-	 */
+DUK_EXTERNAL duk_idx_t duk_push_error_object_raw(duk_context *ctx, duk_errcode_t err_code, const char *filename, duk_int_t line, const char *fmt, ...) {
+	va_list ap;
+	duk_idx_t ret;
 
-	/* XXX: merge this with duk_js_call.c, as this function implements
-	 * core semantics (or perhaps merge the two files altogether).
-	 */
+	DUK_ASSERT_CTX_VALID(ctx);
 
-	duk_hthread *thr = (duk_hthread *) ctx;
-	duk_hobject *proto;
-	duk_hobject *cons;
-	duk_hobject *fallback;
-	duk_idx_t idx_cons;
-	duk_small_uint_t call_flags;
-	duk_int_t rc;
+	va_start(ap, fmt);
+	ret = duk_push_error_object_va_raw(ctx, err_code, filename, line, fmt, ap);
+	va_end(ap);
+	return ret;
+}
 
-	/* [... constructor arg1 ... argN] */
+#if !defined(DUK_USE_VARIADIC_MACROS)
+DUK_EXTERNAL duk_idx_t duk_push_error_object_stash(duk_context *ctx, duk_errcode_t err_code, const char *fmt, ...) {
+	const char *filename = duk_api_global_filename;
+	duk_int_t line = duk_api_global_line;
+	va_list ap;
+	duk_idx_t ret;
 
-	idx_cons = duk_require_normalize_index(ctx, -nargs - 1);
+	DUK_ASSERT_CTX_VALID(ctx);
 
-	DUK_DDD(DUK_DDDPRINT("top=%ld, nargs=%ld, idx_cons=%ld",
-	                     (long) duk_get_top(ctx), (long) nargs, (long) idx_cons));
+	duk_api_global_filename = NULL;
+	duk_api_global_line = 0;
+	va_start(ap, fmt);
+	ret = duk_push_error_object_va_raw(ctx, err_code, filename, line, fmt, ap);
+	va_end(ap);
+	return ret;
+}
+#endif  /* DUK_USE_VARIADIC_MACROS */
 
-	/* XXX: code duplication */
+DUK_EXTERNAL void *duk_push_buffer_raw(duk_context *ctx, duk_size_t size, duk_small_uint_t flags) {
+	duk_hthread *thr = (duk_hthread *) ctx;
+	duk_tval *tv_slot;
+	duk_hbuffer *h;
+	void *buf_data;
 
-	/*
-	 *  Figure out the final, non-bound constructor, to get "prototype"
-	 *  property.
-	 */
+	DUK_ASSERT_CTX_VALID(ctx);
 
-	duk_dup(ctx, idx_cons);
-	for (;;) {
-		cons = duk_get_hobject(ctx, -1);
-		if (cons == NULL || !DUK_HOBJECT_HAS_CONSTRUCTABLE(cons)) {
-			/* Checking constructability from anything else than the
-			 * initial constructor is not strictly necessary, but a
-			 * nice sanity check.
-			 */
-			goto not_constructable;
-		}
-		if (!DUK_HOBJECT_HAS_BOUND(cons)) {
-			break;
-		}
-		duk_get_prop_stridx(ctx, -1, DUK_STRIDX_INT_TARGET);  /* -> [... cons target] */
-		duk_remove(ctx, -2);                                  /* -> [... target] */
+	/* check stack first */
+	if (thr->valstack_top >= thr->valstack_end) {
+		DUK_ERROR_API(thr, DUK_STR_PUSH_BEYOND_ALLOC_STACK);
 	}
-	DUK_ASSERT(cons != NULL && !DUK_HOBJECT_HAS_BOUND(cons));
 
-	/* [... constructor arg1 ... argN final_cons] */
+	/* Check for maximum buffer length. */
+	if (size > DUK_HBUFFER_MAX_BYTELEN) {
+		DUK_ERROR(thr, DUK_ERR_RANGE_ERROR, DUK_STR_BUFFER_TOO_LONG);
+	}
 
-	/*
-	 *  Create "fallback" object to be used as the object instance,
-	 *  unless the constructor returns a replacement value.
-	 *  Its internal prototype needs to be set based on "prototype"
-	 *  property of the constructor.
-	 */
+	h = duk_hbuffer_alloc(thr->heap, size, flags, &buf_data);
+	if (!h) {
+		DUK_ERROR(thr, DUK_ERR_ALLOC_ERROR, DUK_STR_ALLOC_FAILED);
+	}
 
-	duk_push_object(ctx);  /* class Object, extensible */
+	tv_slot = thr->valstack_top;
+	DUK_TVAL_SET_BUFFER(tv_slot, h);
+	DUK_HBUFFER_INCREF(thr, h);
+	thr->valstack_top++;
 
-	/* [... constructor arg1 ... argN final_cons fallback] */
+	return (void *) buf_data;
+}
 
-	duk_get_prop_stridx(ctx, -2, DUK_STRIDX_PROTOTYPE);
-	proto = duk_get_hobject(ctx, -1);
-	if (!proto) {
-		DUK_DDD(DUK_DDDPRINT("constructor has no 'prototype' property, or value not an object "
-		                     "-> leave standard Object prototype as fallback prototype"));
-	} else {
-		DUK_DDD(DUK_DDDPRINT("constructor has 'prototype' property with object value "
-		                     "-> set fallback prototype to that value: %!iO", (duk_heaphdr *) proto));
-		fallback = duk_get_hobject(ctx, -2);
-		DUK_ASSERT(fallback != NULL);
-		DUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr, fallback, proto);
+DUK_EXTERNAL duk_idx_t duk_push_heapptr(duk_context *ctx, void *ptr) {
+	duk_hthread *thr = (duk_hthread *) ctx;
+	duk_idx_t ret;
+
+	DUK_ASSERT_CTX_VALID(ctx);
+
+	ret = (duk_idx_t) (thr->valstack_top - thr->valstack_bottom);
+
+	if (ptr == NULL) {
+		goto push_undefined;
 	}
-	duk_pop(ctx);
 
-	/* [... constructor arg1 ... argN final_cons fallback] */
+	switch ((int) DUK_HEAPHDR_GET_TYPE((duk_heaphdr *) ptr)) {
+	case DUK_HTYPE_STRING:
+		duk_push_hstring(ctx, (duk_hstring *) ptr);
+		break;
+	case DUK_HTYPE_OBJECT:
+		duk_push_hobject(ctx, (duk_hobject *) ptr);
+		break;
+	case DUK_HTYPE_BUFFER:
+		duk_push_hbuffer(ctx, (duk_hbuffer *) ptr);
+		break;
+	default:
+		goto push_undefined;
+	}
+	return ret;
 
-	/*
-	 *  Manipulate callstack for the call.
-	 */
+ push_undefined:
+	duk_push_undefined(ctx);
+	return ret;
+}
 
-	duk_dup_top(ctx);
-	duk_insert(ctx, idx_cons + 1);  /* use fallback as 'this' value */
-	duk_insert(ctx, idx_cons);      /* also stash it before constructor,
-	                                 * in case we need it (as the fallback value)
-	                                 */
-	duk_pop(ctx);                   /* pop final_cons */
+DUK_INTERNAL duk_idx_t duk_push_object_internal(duk_context *ctx) {
+	return duk_push_object_helper(ctx,
+	                              DUK_HOBJECT_FLAG_EXTENSIBLE |
+	                              DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_OBJECT),
+	                              -1);  /* no prototype */
+}
 
+DUK_INTERNAL void duk_push_hstring(duk_context *ctx, duk_hstring *h) {
+	duk_tval tv;
+	DUK_ASSERT_CTX_VALID(ctx);
+	DUK_ASSERT(h != NULL);
+	DUK_TVAL_SET_STRING(&tv, h);
+	duk_push_tval(ctx, &tv);
+}
 
-	/* [... fallback constructor fallback(this) arg1 ... argN];
-	 * Note: idx_cons points to first 'fallback', not 'constructor'.
-	 */
+DUK_INTERNAL void duk_push_hstring_stridx(duk_context *ctx, duk_small_int_t stridx) {
+	duk_hthread *thr = (duk_hthread *) ctx;
+	DUK_ASSERT(stridx >= 0 && stridx < DUK_HEAP_NUM_STRINGS);
+	duk_push_hstring(ctx, DUK_HTHREAD_GET_STRING(thr, stridx));
+}
 
-	DUK_DDD(DUK_DDDPRINT("before call, idx_cons+1 (constructor) -> %!T, idx_cons+2 (fallback/this) -> %!T, "
-	                     "nargs=%ld, top=%ld",
-	                     (duk_tval *) duk_get_tval(ctx, idx_cons + 1),
-	                     (duk_tval *) duk_get_tval(ctx, idx_cons + 2),
-	                     (long) nargs,
-	                     (long) duk_get_top(ctx)));
+DUK_INTERNAL void duk_push_hobject(duk_context *ctx, duk_hobject *h) {
+	duk_tval tv;
+	DUK_ASSERT_CTX_VALID(ctx);
+	DUK_ASSERT(h != NULL);
+	DUK_TVAL_SET_OBJECT(&tv, h);
+	duk_push_tval(ctx, &tv);
+}
 
-	/*
-	 *  Call the constructor function (called in "constructor mode").
-	 */
+DUK_INTERNAL void duk_push_hbuffer(duk_context *ctx, duk_hbuffer *h) {
+	duk_tval tv;
+	DUK_ASSERT_CTX_VALID(ctx);
+	DUK_ASSERT(h != NULL);
+	DUK_TVAL_SET_BUFFER(&tv, h);
+	duk_push_tval(ctx, &tv);
+}
 
-	call_flags = DUK_CALL_FLAG_CONSTRUCTOR_CALL;  /* not protected, respect reclimit, is a constructor call */
+DUK_INTERNAL void duk_push_hobject_bidx(duk_context *ctx, duk_small_int_t builtin_idx) {
+	duk_hthread *thr = (duk_hthread *) ctx;
+	DUK_ASSERT_CTX_VALID(ctx);
+	DUK_ASSERT(thr != NULL);
+	DUK_ASSERT(builtin_idx >= 0 && builtin_idx < DUK_NUM_BUILTINS);
+	DUK_ASSERT(thr->builtins[builtin_idx] != NULL);
+	duk_push_hobject(ctx, thr->builtins[builtin_idx]);
+}
 
-	rc = duk_handle_call(thr,           /* thread */
-	                     nargs,         /* num_stack_args */
-	                     call_flags);   /* call_flags */
-	DUK_UNREF(rc);
+/*
+ *  Poppers
+ */
 
-	/* [... fallback retval] */
+DUK_EXTERNAL void duk_pop_n(duk_context *ctx, duk_idx_t count) {
+	duk_hthread *thr = (duk_hthread *) ctx;
+	duk_tval *tv;
 
-	DUK_DDD(DUK_DDDPRINT("constructor call finished, rc=%ld, fallback=%!iT, retval=%!iT",
-	                     (long) rc,
-	                     (duk_tval *) duk_get_tval(ctx, -2),
-	                     (duk_tval *) duk_get_tval(ctx, -1)));
+	DUK_ASSERT_CTX_VALID(ctx);
 
-	/*
-	 *  Determine whether to use the constructor return value as the created
-	 *  object instance or not.
-	 */
+	if (DUK_UNLIKELY(count < 0)) {
+		DUK_ERROR_API(thr, DUK_STR_INVALID_COUNT);
+		return;
+	}
 
-	if (duk_is_object(ctx, -1)) {
-		duk_remove(ctx, -2);
-	} else {
-		duk_pop(ctx);
+	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
+	if (DUK_UNLIKELY((duk_size_t) (thr->valstack_top - thr->valstack_bottom) < (duk_size_t) count)) {
+		DUK_ERROR_API(thr, DUK_STR_POP_TOO_MANY);
 	}
 
 	/*
-	 *  Augment created errors upon creation (not when they are thrown or
-	 *  rethrown).  __FILE__ and __LINE__ are not desirable here; the call
-	 *  stack reflects the caller which is correct.
+	 *  Must be very careful here, every DECREF may cause reallocation
+	 *  of our valstack.
 	 */
 
-#ifdef DUK_USE_AUGMENT_ERROR_CREATE
-	duk_err_augment_error_create(thr, thr, NULL, 0, 1 /*noblame_fileline*/);
-#endif
+	/* XXX: inlined DECREF macro would be nice here: no NULL check,
+	 * refzero queueing but no refzero algorithm run (= no pointer
+	 * instability), inline code.
+	 */
 
-	/* [... retval] */
+	/* XXX: optimize loops */
 
-	return;
+#if defined(DUK_USE_REFERENCE_COUNTING)
+	while (count > 0) {
+		count--;
+		tv = --thr->valstack_top;  /* tv points to element just below prev top */
+		DUK_ASSERT(tv >= thr->valstack_bottom);
+		DUK_TVAL_SET_UNDEFINED_UPDREF(thr, tv);  /* side effects */
+	}
+#else
+	tv = thr->valstack_top;
+	while (count > 0) {
+		count--;
+		tv--;
+		DUK_ASSERT(tv >= thr->valstack_bottom);
+		DUK_TVAL_SET_UNDEFINED(tv);
+	}
+	thr->valstack_top = tv;
+#endif
 
- not_constructable:
-	DUK_ERROR(thr, DUK_ERR_TYPE_ERROR, DUK_STR_NOT_CONSTRUCTABLE);
+	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
 }
 
-duk_bool_t duk_is_constructor_call(duk_context *ctx) {
+/* Popping one element is called so often that when footprint is not an issue,
+ * compile a specialized function for it.
+ */
+#if defined(DUK_USE_PREFER_SIZE)
+DUK_EXTERNAL void duk_pop(duk_context *ctx) {
+	DUK_ASSERT_CTX_VALID(ctx);
+	duk_pop_n(ctx, 1);
+}
+#else
+DUK_EXTERNAL void duk_pop(duk_context *ctx) {
 	duk_hthread *thr = (duk_hthread *) ctx;
-	duk_activation *act;
+	duk_tval *tv;
+	DUK_ASSERT_CTX_VALID(ctx);
 
-	DUK_ASSERT(ctx != NULL);
-	DUK_ASSERT(thr != NULL);
-	DUK_ASSERT_DISABLE(thr->callstack_top >= 0);
+	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
+	if (DUK_UNLIKELY(thr->valstack_top == thr->valstack_bottom)) {
+		DUK_ERROR_API(thr, DUK_STR_POP_TOO_MANY);
+	}
 
-	act = duk_hthread_get_current_activation(thr);
-	return (act != NULL && (act->flags & DUK_ACT_FLAG_CONSTRUCT) != 0 ? 1 : 0);
+	tv = --thr->valstack_top;  /* tv points to element just below prev top */
+	DUK_ASSERT(tv >= thr->valstack_bottom);
+#ifdef DUK_USE_REFERENCE_COUNTING
+	DUK_TVAL_SET_UNDEFINED_UPDREF(thr, tv);  /* side effects */
+#else
+	DUK_TVAL_SET_UNDEFINED(tv);
+#endif
+	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
 }
+#endif  /* !DUK_USE_PREFER_SIZE */
 
-duk_bool_t duk_is_strict_call(duk_context *ctx) {
-	duk_hthread *thr = (duk_hthread *) ctx;
-	duk_activation *act;
-
-	DUK_ASSERT(ctx != NULL);
-	DUK_ASSERT(thr != NULL);
-	DUK_ASSERT_DISABLE(thr->callstack_top >= 0);
+DUK_EXTERNAL void duk_pop_2(duk_context *ctx) {
+	DUK_ASSERT_CTX_VALID(ctx);
+	duk_pop_n(ctx, 2);
+}
 
-	act = duk_hthread_get_current_activation(thr);
-	return (act != NULL && (act->flags & DUK_ACT_FLAG_STRICT) != 0 ? 1 : 0);
+DUK_EXTERNAL void duk_pop_3(duk_context *ctx) {
+	DUK_ASSERT_CTX_VALID(ctx);
+	duk_pop_n(ctx, 3);
 }
 
 /*
- *  Duktape/C function magic
+ *  Error throwing
  */
 
-duk_int_t duk_get_magic(duk_context *ctx) {
+DUK_EXTERNAL void duk_throw(duk_context *ctx) {
 	duk_hthread *thr = (duk_hthread *) ctx;
-	duk_activation *act;
-	duk_hobject *func;
-
-	DUK_ASSERT(ctx != NULL);
-	DUK_ASSERT(thr != NULL);
-	DUK_ASSERT_DISABLE(thr->callstack_top >= 0);
 
-	act = duk_hthread_get_current_activation(thr);
-	if (act) {
-		func = act->func;
-		DUK_ASSERT(func != NULL);
+	DUK_ASSERT(thr->valstack_bottom >= thr->valstack);
+	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
+	DUK_ASSERT(thr->valstack_end >= thr->valstack_top);
 
-		if (DUK_HOBJECT_IS_NATIVEFUNCTION(func)) {
-			duk_hnativefunction *nf = (duk_hnativefunction *) func;
-			return (duk_int_t) nf->magic;
-		}
+	if (thr->valstack_top == thr->valstack_bottom) {
+		DUK_ERROR_API(thr, DUK_STR_INVALID_CALL_ARGS);
 	}
-	return 0;
-}
-#line 1 "duk_api_codec.c"
-/*
- *  Encoding and decoding basic formats: hex, base64.
- *
- *  These are in-place operations which may allow an optimized implementation.
- */
-
-/* include removed: duk_internal.h */
 
-/* dst length must be exactly ceil(len/3)*4 */
-static void duk__base64_encode_helper(const duk_uint8_t *src, const duk_uint8_t *src_end,
-                                      duk_uint8_t *dst, duk_uint8_t *dst_end) {
-	duk_small_uint_t i, snip;
-	duk_uint_fast32_t t;
-	duk_uint_fast8_t x, y;
-
-	DUK_UNREF(dst_end);
-
-	while (src < src_end) {
-		/* read 3 bytes into 't', padded by zero */
-		snip = 4;
-		t = 0;
-		for (i = 0; i < 3; i++) {
-			t = t << 8;
-			if (src >= src_end) {
-				snip--;
-			} else {
-				t += (duk_uint_fast32_t) (*src++);
-			}
-		}
+	/* Errors are augmented when they are created, not when they are
+	 * thrown or re-thrown.  The current error handler, however, runs
+	 * just before an error is thrown.
+	 */
 
-		/*
-		 *  Missing bytes    snip     base64 example
-		 *    0               4         XXXX
-		 *    1               3         XXX=
-		 *    2               2         XX==
-		 */
+	/* Sync so that augmentation sees up-to-date activations, NULL
+	 * thr->ptr_curr_pc so that it's not used if side effects occur
+	 * in augmentation or longjmp handling.
+	 */
+	duk_hthread_sync_and_null_currpc(thr);
 
-		DUK_ASSERT(snip >= 2 && snip <= 4);
+#if defined(DUK_USE_AUGMENT_ERROR_THROW)
+	DUK_DDD(DUK_DDDPRINT("THROW ERROR (API): %!dT (before throw augment)", (duk_tval *) duk_get_tval(ctx, -1)));
+	duk_err_augment_error_throw(thr);
+#endif
+	DUK_DDD(DUK_DDDPRINT("THROW ERROR (API): %!dT (after throw augment)", (duk_tval *) duk_get_tval(ctx, -1)));
 
-		for (i = 0; i < 4; i++) {
-			x = (duk_uint_fast8_t) ((t >> 18) & 0x3f);
-			t = t << 6;
+	duk_err_setup_heap_ljstate(thr, DUK_LJ_TYPE_THROW);
 
-			/* A straightforward 64-byte lookup would be faster
-			 * and cleaner, but this is shorter.
-			 */
-			if (i >= snip) {
-				y = '=';
-			} else if (x <= 25) {
-				y = x + 'A';
-			} else if (x <= 51) {
-				y = x - 26 + 'a';
-			} else if (x <= 61) {
-				y = x - 52 + '0';
-			} else if (x == 62) {
-				y = '+';
-			} else {
-				y = '/';
-			}
+	/* thr->heap->lj.jmpbuf_ptr is checked by duk_err_longjmp() so we don't
+	 * need to check that here.  If the value is NULL, a panic occurs because
+	 * we can't return.
+	 */
 
-			DUK_ASSERT(dst < dst_end);
-			*dst++ = (duk_uint8_t) y;
-		}
-	}
+	duk_err_longjmp(thr);
+	DUK_UNREACHABLE();
 }
 
-static duk_bool_t duk__base64_decode_helper(const duk_uint8_t *src, const duk_uint8_t *src_end,
-                                            duk_uint8_t *dst, duk_uint8_t *dst_end, duk_uint8_t **out_dst_final) {
-	duk_uint_fast32_t t;
-	duk_uint_fast8_t x, y;
-	duk_small_uint_t group_idx;
+DUK_EXTERNAL void duk_fatal(duk_context *ctx, duk_errcode_t err_code, const char *err_msg) {
+	duk_hthread *thr = (duk_hthread *) ctx;
 
-	DUK_UNREF(dst_end);
+	DUK_ASSERT_CTX_VALID(ctx);
+	DUK_ASSERT(thr != NULL);
+	DUK_ASSERT(thr->heap != NULL);
+	DUK_ASSERT(thr->heap->fatal_func != NULL);
 
-	t = 0;
-	group_idx = 0;
+	DUK_D(DUK_DPRINT("fatal error occurred, code %ld, message %s",
+	                 (long) err_code, (const char *) err_msg));
 
-	while (src < src_end) {
-		x = *src++;
+	/* fatal_func should be noreturn, but noreturn declarations on function
+	 * pointers has a very spotty support apparently so it's not currently
+	 * done.
+	 */
+	thr->heap->fatal_func(ctx, err_code, err_msg);
 
-		if (x >= 'A' && x <= 'Z') {
-			y = x - 'A' + 0;
-		} else if (x >= 'a' && x <= 'z') {
-			y = x - 'a' + 26;
-		} else if (x >= '0' && x <= '9') {
-			y = x - '0' + 52;
-		} else if (x == '+') {
-			y = 62;
-		} else if (x == '/') {
-			y = 63;
-		} else if (x == '=') {
-			/* We don't check the zero padding bytes here right now.
-			 * This seems to be common behavior for base-64 decoders.
-			 */
+	DUK_PANIC(DUK_ERR_API_ERROR, "fatal handler returned");
+}
 
-			if (group_idx == 2) {
-				/* xx== -> 1 byte, t contains 12 bits, 4 on right are zero */
-				t = t >> 4;
-				DUK_ASSERT(dst < dst_end);
-				*dst++ = (duk_uint8_t) t;
+DUK_EXTERNAL void duk_error_va_raw(duk_context *ctx, duk_errcode_t err_code, const char *filename, duk_int_t line, const char *fmt, va_list ap) {
+	DUK_ASSERT_CTX_VALID(ctx);
 
-				if (src >= src_end) {
-					goto error;
-				}
-				x = *src++;
-				if (x != '=') {
-					goto error;
-				}
-			} else if (group_idx == 3) {
-				/* xxx= -> 2 bytes, t contains 18 bits, 2 on right are zero */
-				t = t >> 2;
-				DUK_ASSERT(dst < dst_end);
-				*dst++ = (duk_uint8_t) ((t >> 8) & 0xff);
-				DUK_ASSERT(dst < dst_end);
-				*dst++ = (duk_uint8_t) (t & 0xff);
-			} else {
-				goto error;
-			}
+	duk_push_error_object_va_raw(ctx, err_code, filename, line, fmt, ap);
+	duk_throw(ctx);
+}
 
-			/* Here we can choose either to end parsing and ignore
-			 * whatever follows, or to continue parsing in case
-			 * multiple (possibly padded) base64 strings have been
-			 * concatenated.  Currently, keep on parsing.
-			 */
-			t = 0;
-			group_idx = 0;
-			continue;
-		} else if (x == 0x09 || x == 0x0a || x == 0x0d || x == 0x20) {
-			/* allow basic ASCII whitespace */
-			continue;
-		} else {
-			goto error;
-		}
+DUK_EXTERNAL void duk_error_raw(duk_context *ctx, duk_errcode_t err_code, const char *filename, duk_int_t line, const char *fmt, ...) {
+	va_list ap;
 
-		t = (t << 6) + y;
+	DUK_ASSERT_CTX_VALID(ctx);
 
-		if (group_idx == 3) {
-			/* output 3 bytes from 't' */
-			DUK_ASSERT(dst < dst_end);
-			*dst++ = (duk_uint8_t) ((t >> 16) & 0xff);
-			DUK_ASSERT(dst < dst_end);
-			*dst++ = (duk_uint8_t) ((t >> 8) & 0xff);
-			DUK_ASSERT(dst < dst_end);
-			*dst++ = (duk_uint8_t) (t & 0xff);
-			t = 0;
-			group_idx = 0;
-		} else {
-			group_idx++;
-		}
-	}
+	va_start(ap, fmt);
+	duk_push_error_object_va_raw(ctx, err_code, filename, line, fmt, ap);
+	va_end(ap);
+	duk_throw(ctx);
+}
 
-	if (group_idx != 0) {
-		/* Here we'd have the option of decoding unpadded base64
-		 * (e.g. "xxxxyy" instead of "xxxxyy==".  Currently not
-		 * accepted.
-		 */
-		goto error;
-	}
+#if !defined(DUK_USE_VARIADIC_MACROS)
+DUK_EXTERNAL void duk_error_stash(duk_context *ctx, duk_errcode_t err_code, const char *fmt, ...) {
+	const char *filename;
+	duk_int_t line;
+	va_list ap;
 
-	*out_dst_final = dst;
-	return 1;
+	DUK_ASSERT_CTX_VALID(ctx);
 
- error:
-	return 0;
+	filename = duk_api_global_filename;
+	line = duk_api_global_line;
+	duk_api_global_filename = NULL;
+	duk_api_global_line = 0;
+
+	va_start(ap, fmt);
+	duk_push_error_object_va_raw(ctx, err_code, filename, line, fmt, ap);
+	va_end(ap);
+	duk_throw(ctx);
 }
+#endif  /* DUK_USE_VARIADIC_MACROS */
+
+/*
+ *  Comparison
+ */
 
-const char *duk_base64_encode(duk_context *ctx, duk_idx_t index) {
+DUK_EXTERNAL duk_bool_t duk_equals(duk_context *ctx, duk_idx_t index1, duk_idx_t index2) {
 	duk_hthread *thr = (duk_hthread *) ctx;
-	duk_uint8_t *src;
-	duk_size_t srclen;
-	duk_size_t dstlen;
-	duk_uint8_t *dst;
-	const char *ret;
+	duk_tval *tv1, *tv2;
 
-	/* XXX: optimize for string inputs: no need to coerce to a buffer
-	 * which makes a copy of the input.
-	 */
+	DUK_ASSERT_CTX_VALID(ctx);
 
-	index = duk_require_normalize_index(ctx, index);
-	src = (duk_uint8_t *) duk_to_buffer(ctx, index, &srclen);
-	/* Note: for srclen=0, src may be NULL */
+	tv1 = duk_get_tval(ctx, index1);
+	tv2 = duk_get_tval(ctx, index2);
+	if ((tv1 == NULL) || (tv2 == NULL)) {
+		return 0;
+	}
 
-	/* Computation must not wrap; this limit works for 32-bit size_t:
-	 * >>> srclen = 3221225469
-	 * >>> '%x' % ((srclen + 2) / 3 * 4)
-	 * 'fffffffc'
+	/* Coercion may be needed, the helper handles that by pushing the
+	 * tagged values to the stack.
 	 */
-	if (srclen > 3221225469UL) {
-		goto type_error;
-	}
-	dstlen = (srclen + 2) / 3 * 4;
-	dst = (duk_uint8_t *) duk_push_fixed_buffer(ctx, dstlen);
+	return duk_js_equals(thr, tv1, tv2);
+}
 
-	duk__base64_encode_helper((const duk_uint8_t *) src, (const duk_uint8_t *) (src + srclen),
-	                          dst, (dst + dstlen));
+DUK_EXTERNAL duk_bool_t duk_strict_equals(duk_context *ctx, duk_idx_t index1, duk_idx_t index2) {
+	duk_tval *tv1, *tv2;
 
-	ret = duk_to_string(ctx, -1);
-	duk_replace(ctx, index);
-	return ret;
+	DUK_ASSERT_CTX_VALID(ctx);
 
- type_error:
-	DUK_ERROR(thr, DUK_ERR_TYPE_ERROR, "base64 encode failed");
-	return NULL;  /* never here */
+	tv1 = duk_get_tval(ctx, index1);
+	tv2 = duk_get_tval(ctx, index2);
+	if ((tv1 == NULL) || (tv2 == NULL)) {
+		return 0;
+	}
+
+	/* No coercions or other side effects, so safe */
+	return duk_js_strict_equals(tv1, tv2);
 }
 
-void duk_base64_decode(duk_context *ctx, duk_idx_t index) {
-	duk_hthread *thr = (duk_hthread *) ctx;
-	const duk_uint8_t *src;
-	duk_size_t srclen;
-	duk_size_t dstlen;
-	duk_uint8_t *dst;
-	duk_uint8_t *dst_final;
-	duk_bool_t retval;
+/*
+ *  instanceof
+ */
 
-	/* XXX: optimize for buffer inputs: no need to coerce to a string
-	 * which causes an unnecessary interning.
-	 */
+DUK_EXTERNAL duk_bool_t duk_instanceof(duk_context *ctx, duk_idx_t index1, duk_idx_t index2) {
+	duk_tval *tv1, *tv2;
 
-	index = duk_require_normalize_index(ctx, index);
-	src = (const duk_uint8_t *) duk_to_lstring(ctx, index, &srclen);
+	DUK_ASSERT_CTX_VALID(ctx);
 
-	/* Computation must not wrap, only srclen + 3 is at risk of
-	 * wrapping because after that the number gets smaller.
-	 * This limit works for 32-bit size_t:
-	 * 0x100000000 - 3 - 1 = 4294967292
+	/* Index validation is strict, which differs from duk_equals().
+	 * The strict behavior mimics how instanceof itself works, e.g.
+	 * it is a TypeError if rval is not a -callable- object.  It would
+	 * be somewhat inconsistent if rval would be allowed to be
+	 * non-existent without a TypeError.
 	 */
-	if (srclen > 4294967292UL) {
-		goto type_error;
-	}
-	dstlen = (srclen + 3) / 4 * 3;  /* upper limit */
-	dst = (duk_uint8_t *) duk_push_dynamic_buffer(ctx, dstlen);
-	/* Note: for dstlen=0, dst may be NULL */
+	tv1 = duk_require_tval(ctx, index1);
+	DUK_ASSERT(tv1 != NULL);
+	tv2 = duk_require_tval(ctx, index2);
+	DUK_ASSERT(tv2 != NULL);
 
-	retval = duk__base64_decode_helper((const duk_uint8_t *) src, (const duk_uint8_t *) (src + srclen),
-	                                   dst, dst + dstlen, &dst_final);
-	if (!retval) {
-		goto type_error;
-	}
+	return duk_js_instanceof((duk_hthread *) ctx, tv1, tv2);
+}
 
-	/* XXX: convert to fixed buffer? */
-	(void) duk_resize_buffer(ctx, -1, (duk_size_t) (dst_final - dst));
-	duk_replace(ctx, index);
-	return;
+/*
+ *  Lightfunc
+ */
 
- type_error:
-	DUK_ERROR(thr, DUK_ERR_TYPE_ERROR, "base64 decode failed");
+DUK_INTERNAL void duk_push_lightfunc_name(duk_context *ctx, duk_tval *tv) {
+	duk_c_function func;
+
+	DUK_ASSERT(DUK_TVAL_IS_LIGHTFUNC(tv));
+
+	/* Lightfunc name, includes Duktape/C native function pointer, which
+	 * can often be used to locate the function from a symbol table.
+	 * The name also includes the 16-bit duk_tval flags field because it
+	 * includes the magic value.  Because a single native function often
+	 * provides different functionality depending on the magic value, it
+	 * seems reasonably to include it in the name.
+	 *
+	 * On the other hand, a complicated name increases string table
+	 * pressure in low memory environments (but only when function name
+	 * is accessed).
+	 */
+
+	func = DUK_TVAL_GET_LIGHTFUNC_FUNCPTR(tv);
+	duk_push_sprintf(ctx, "light_");
+	duk_push_string_funcptr(ctx, (duk_uint8_t *) &func, sizeof(func));
+	duk_push_sprintf(ctx, "_%04x", (unsigned int) DUK_TVAL_GET_LIGHTFUNC_FLAGS(tv));
+	duk_concat(ctx, 3);
 }
 
-const char *duk_hex_encode(duk_context *ctx, duk_idx_t index) {
-	duk_uint8_t *data;
-	duk_size_t len;
-	duk_size_t i;
-	duk_uint_fast8_t t;
-	duk_uint8_t *buf;
-	const char *ret;
+DUK_INTERNAL void duk_push_lightfunc_tostring(duk_context *ctx, duk_tval *tv) {
+	DUK_ASSERT(DUK_TVAL_IS_LIGHTFUNC(tv));
 
-	/* XXX: special case for input string, no need to coerce to buffer */
+	duk_push_string(ctx, "function ");
+	duk_push_lightfunc_name(ctx, tv);
+	duk_push_string(ctx, "() {/* light */}");
+	duk_concat(ctx, 3);
+}
 
-	index = duk_require_normalize_index(ctx, index);
-	data = (duk_uint8_t *) duk_to_buffer(ctx, index, &len);
-	DUK_ASSERT(data != NULL);
+/*
+ *  Function pointers
+ *
+ *  Printing function pointers is non-portable, so we do that by hex printing
+ *  bytes from memory.
+ */
 
-	buf = (unsigned char *) duk_push_fixed_buffer(ctx, len * 2);
-	DUK_ASSERT(buf != NULL);
-	/* buf is always zeroed */
+DUK_INTERNAL void duk_push_string_funcptr(duk_context *ctx, duk_uint8_t *ptr, duk_size_t sz) {
+	duk_uint8_t buf[32 * 2];
+	duk_uint8_t *p, *q;
+	duk_small_uint_t i;
+	duk_small_uint_t t;
 
-	for (i = 0; i < len; i++) {
-		t = (duk_uint_fast8_t) data[i];
-		buf[i*2 + 0] = duk_lc_digits[t >> 4];
-		buf[i*2 + 1] = duk_lc_digits[t & 0x0f];
+	DUK_ASSERT(sz <= 32);  /* sanity limit for function pointer size */
+
+	p = buf;
+#if defined(DUK_USE_INTEGER_LE)
+	q = ptr + sz;
+#else
+	q = ptr;
+#endif
+	for (i = 0; i < sz; i++) {
+#if defined(DUK_USE_INTEGER_LE)
+		t = *(--q);
+#else
+		t = *(q++);
+#endif
+		*p++ = duk_lc_digits[t >> 4];
+		*p++ = duk_lc_digits[t & 0x0f];
 	}
 
-	ret = duk_to_string(ctx, -1);
-	duk_replace(ctx, index);
-	return ret;
+	duk_push_lstring(ctx, (const char *) buf, sz * 2);
 }
 
-void duk_hex_decode(duk_context *ctx, duk_idx_t index) {
-	duk_hthread *thr = (duk_hthread *) ctx;
-	const duk_uint8_t *str;
-	duk_size_t len;
-	duk_size_t i;
-	duk_small_int_t t;
-	duk_uint8_t *buf;
+#if !defined(DUK_USE_PARANOID_ERRORS)
+/*
+ *  Push readable string summarizing duk_tval.  The operation is side effect
+ *  free and will only throw from internal errors (e.g. out of memory).
+ *  This is used by e.g. property access code to summarize a key/base safely,
+ *  and is not intended to be fast (but small and safe).
+ */
 
-	/* XXX: optimize for buffer inputs: no need to coerce to a string
-	 * which causes an unnecessary interning.
-	 */
+#define DUK__READABLE_STRING_MAXCHARS 32
 
-	index = duk_require_normalize_index(ctx, index);
-	str = (const duk_uint8_t *) duk_to_lstring(ctx, index, &len);
-	DUK_ASSERT(str != NULL);
+/* String sanitizer which escapes ASCII control characters and a few other
+ * ASCII characters, passes Unicode as is, and replaces invalid UTF-8 with
+ * question marks.  No errors are thrown for any input string, except in out
+ * of memory situations.
+ */
+DUK_LOCAL void duk__push_hstring_readable_unicode(duk_context *ctx, duk_hstring *h_input) {
+	duk_hthread *thr;
+	const duk_uint8_t *p, *p_start, *p_end;
+	duk_uint8_t buf[DUK_UNICODE_MAX_XUTF8_LENGTH * DUK__READABLE_STRING_MAXCHARS +
+	                2 /*quotes*/ + 3 /*periods*/];
+	duk_uint8_t *q;
+	duk_ucodepoint_t cp;
+	duk_small_uint_t nchars;
 
-	if (len & 0x01) {
-		goto type_error;
-	}
+	DUK_ASSERT_CTX_VALID(ctx);
+	DUK_ASSERT(h_input != NULL);
+	thr = (duk_hthread *) ctx;
 
-	buf = (duk_uint8_t *) duk_push_fixed_buffer(ctx, len / 2);
-	DUK_ASSERT(buf != NULL);
-	/* buf is always zeroed */
+	p_start = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_input);
+	p_end = p_start + DUK_HSTRING_GET_BYTELEN(h_input);
+	p = p_start;
+	q = buf;
 
-	for (i = 0; i < len; i++) {
-		t = str[i];
-		DUK_ASSERT(t >= 0 && t <= 0xff);
-		t = duk_hex_dectab[t];
-		if (DUK_UNLIKELY(t < 0)) {
-			goto type_error;
+	nchars = 0;
+	*q++ = (duk_uint8_t) DUK_ASC_SINGLEQUOTE;
+	for (;;) {
+		if (p >= p_end) {
+			break;
 		}
-
-		if (i & 0x01) {
-			buf[i >> 1] += (duk_uint8_t) t;
+		if (nchars == DUK__READABLE_STRING_MAXCHARS) {
+			*q++ = (duk_uint8_t) DUK_ASC_PERIOD;
+			*q++ = (duk_uint8_t) DUK_ASC_PERIOD;
+			*q++ = (duk_uint8_t) DUK_ASC_PERIOD;
+			break;
+		}
+		if (duk_unicode_decode_xutf8(thr, &p, p_start, p_end, &cp)) {
+			if (cp < 0x20 || cp == 0x7f || cp == DUK_ASC_SINGLEQUOTE || cp == DUK_ASC_BACKSLASH) {
+				DUK_ASSERT(DUK_UNICODE_MAX_XUTF8_LENGTH >= 4);  /* estimate is valid */
+				DUK_ASSERT((cp >> 4) <= 0x0f);
+				*q++ = (duk_uint8_t) DUK_ASC_BACKSLASH;
+				*q++ = (duk_uint8_t) DUK_ASC_LC_X;
+				*q++ = (duk_uint8_t) duk_lc_digits[cp >> 4];
+				*q++ = (duk_uint8_t) duk_lc_digits[cp & 0x0f];
+			} else {
+				q += duk_unicode_encode_xutf8(cp, q);
+			}
 		} else {
-			buf[i >> 1] = (duk_uint8_t) (t << 4);
+			p++;  /* advance manually */
+			*q++ = (duk_uint8_t) DUK_ASC_QUESTION;
 		}
+		nchars++;
 	}
+	*q++ = (duk_uint8_t) DUK_ASC_SINGLEQUOTE;
 
-	duk_replace(ctx, index);
-	return;
-
- type_error:
-	DUK_ERROR(thr, DUK_ERR_TYPE_ERROR, "hex decode failed");
+	duk_push_lstring(ctx, (const char *) buf, (duk_size_t) (q - buf));
 }
 
-const char *duk_json_encode(duk_context *ctx, duk_idx_t index) {
-#ifdef DUK_USE_ASSERTIONS
-	duk_idx_t top_at_entry = duk_get_top(ctx);
-#endif
-	const char *ret;
+DUK_INTERNAL const char *duk_push_string_tval_readable(duk_context *ctx, duk_tval *tv) {
+	duk_hthread *thr;
 
-	index = duk_require_normalize_index(ctx, index);
-	duk_bi_json_stringify_helper(ctx,
-	                             index /*idx_value*/,
-	                             DUK_INVALID_INDEX /*idx_replacer*/,
-	                             DUK_INVALID_INDEX /*idx_space*/,
-	                             0 /*flags*/);
-	DUK_ASSERT(duk_is_string(ctx, -1));
-	duk_replace(ctx, index);
-	ret = duk_get_string(ctx, index);
+	DUK_ASSERT_CTX_VALID(ctx);
+	thr = (duk_hthread *) ctx;
+	DUK_UNREF(thr);
 
-	DUK_ASSERT(duk_get_top(ctx) == top_at_entry);
+	if (tv == NULL) {
+		duk_push_string(ctx, "none");
+	} else {
+		switch (DUK_TVAL_GET_TAG(tv)) {
+		case DUK_TAG_STRING: {
+			duk__push_hstring_readable_unicode(ctx, DUK_TVAL_GET_STRING(tv));
+			break;
+		}
+		case DUK_TAG_OBJECT: {
+			duk_hobject *h = DUK_TVAL_GET_OBJECT(tv);
+			DUK_ASSERT(h != NULL);
+			duk_push_hobject_class_string(ctx, h);
+			break;
+		}
+		case DUK_TAG_BUFFER: {
+			/* XXX: Hex encoded, length limited buffer summary here? */
+			duk_hbuffer *h = DUK_TVAL_GET_BUFFER(tv);
+			DUK_ASSERT(h != NULL);
+			duk_push_sprintf(ctx, "[buffer:%ld]", (long) DUK_HBUFFER_GET_SIZE(h));
+			break;
+		}
+		case DUK_TAG_POINTER: {
+			/* Surround with parentheses like in JX, ensures NULL pointer
+			 * is distinguishable from null value ("(null)" vs "null").
+			 */
+			duk_push_tval(ctx, tv);
+			duk_push_sprintf(ctx, "(%s)", duk_to_string(ctx, -1));
+			duk_remove(ctx, -2);
+			break;
+		}
+		default: {
+			duk_push_tval(ctx, tv);
+			break;
+		}
+		}
+	}
 
-	return ret;
+	return duk_to_string(ctx, -1);
 }
 
-void duk_json_decode(duk_context *ctx, duk_idx_t index) {
-#ifdef DUK_USE_ASSERTIONS
-	duk_idx_t top_at_entry = duk_get_top(ctx);
-#endif
-
-	index = duk_require_normalize_index(ctx, index);
-	duk_bi_json_parse_helper(ctx,
-	                         index /*idx_value*/,
-	                         DUK_INVALID_INDEX /*idx_reviver*/,
-	                         0 /*flags*/);
-	duk_replace(ctx, index);
-
-	DUK_ASSERT(duk_get_top(ctx) == top_at_entry);
+DUK_INTERNAL const char *duk_push_string_readable(duk_context *ctx, duk_idx_t index) {
+	DUK_ASSERT_CTX_VALID(ctx);
+	return duk_push_string_tval_readable(ctx, duk_get_tval(ctx, index));
 }
-#line 1 "duk_api_compile.c"
+#endif  /* !DUK_USE_PARANOID_ERRORS */
+
+#undef DUK__CHECK_SPACE
+#undef DUK__PACK_ARGS
+#undef DUK__READABLE_STRING_MAXCHARS
+#line 1 "duk_api_string.c"
 /*
- *  Compilation and evaluation
+ *  String manipulation
  */
 
 /* include removed: duk_internal.h */
 
-typedef struct duk__compile_raw_args duk__compile_raw_args;
-struct duk__compile_raw_args {
-	duk_size_t src_length;  /* should be first on 64-bit platforms */
-	const duk_uint8_t *src_buffer;
-	duk_uint_t flags;
-};
+DUK_LOCAL void duk__concat_and_join_helper(duk_context *ctx, duk_idx_t count_in, duk_bool_t is_join) {
+	duk_hthread *thr = (duk_hthread *) ctx;
+	duk_uint_t count;
+	duk_uint_t i;
+	duk_size_t idx;
+	duk_size_t len;
+	duk_hstring *h;
+	duk_uint8_t *buf;
 
-/* Eval is just a wrapper now. */
-duk_int_t duk_eval_raw(duk_context *ctx, const char *src_buffer, duk_size_t src_length, duk_uint_t flags) {
-	duk_uint_t comp_flags;
-	duk_int_t rc;
+	DUK_ASSERT_CTX_VALID(ctx);
 
-	/* [ ... source? filename ] (depends on flags) */
+	if (DUK_UNLIKELY(count_in <= 0)) {
+		if (count_in < 0) {
+			DUK_ERROR_API(thr, DUK_STR_INVALID_COUNT);
+			return;
+		}
+		DUK_ASSERT(count_in == 0);
+		duk_push_hstring_stridx(ctx, DUK_STRIDX_EMPTY_STRING);
+		return;
+	}
+	count = (duk_uint_t) count_in;
 
-	comp_flags = flags;
-	comp_flags |= DUK_COMPILE_EVAL;
-	if (duk_is_strict_call(ctx)) {
-		comp_flags |= DUK_COMPILE_STRICT;
+	if (is_join) {
+		duk_size_t t1, t2, limit;
+		h = duk_to_hstring(ctx, -((duk_idx_t) count) - 1);
+		DUK_ASSERT(h != NULL);
+
+		/* A bit tricky overflow test, see doc/code-issues.rst. */
+		t1 = (duk_size_t) DUK_HSTRING_GET_BYTELEN(h);
+		t2 = (duk_size_t) (count - 1);
+		limit = (duk_size_t) DUK_HSTRING_MAX_BYTELEN;
+		if (DUK_UNLIKELY(t2 != 0 && t1 > limit / t2)) {
+			/* Combined size of separators already overflows */
+			goto error_overflow;
+		}
+		len = (duk_size_t) (t1 * t2);
+	} else {
+		len = (duk_size_t) 0;
 	}
-	rc = duk_compile_raw(ctx, src_buffer, src_length, comp_flags);  /* may be safe, or non-safe depending on flags */
 
-	/* [ ... closure/error ] */
+	for (i = count; i >= 1; i--) {
+		duk_size_t new_len;
+		duk_to_string(ctx, -((duk_idx_t) i));
+		h = duk_require_hstring(ctx, -((duk_idx_t) i));
+		new_len = len + (duk_size_t) DUK_HSTRING_GET_BYTELEN(h);
 
-	if (rc != DUK_EXEC_SUCCESS) {
-		rc = DUK_EXEC_ERROR;
-		goto got_rc;
+		/* Impose a string maximum length, need to handle overflow
+		 * correctly.
+		 */
+		if (new_len < len ||  /* wrapped */
+		    new_len > (duk_size_t) DUK_HSTRING_MAX_BYTELEN) {
+			goto error_overflow;
+		}
+		len = new_len;
 	}
 
-	if (flags & DUK_COMPILE_SAFE) {
-		rc = duk_pcall(ctx, 0);
-	} else {
-		duk_call(ctx, 0);
-		rc = DUK_EXEC_SUCCESS;
+	DUK_DDD(DUK_DDDPRINT("join/concat %lu strings, total length %lu bytes",
+	                     (unsigned long) count, (unsigned long) len));
+
+	/* use stack allocated buffer to ensure reachability in errors (e.g. intern error) */
+	buf = (duk_uint8_t *) duk_push_fixed_buffer(ctx, len);
+	DUK_ASSERT(buf != NULL);
+
+	/* [... (sep) str1 str2 ... strN buf] */
+
+	idx = 0;
+	for (i = count; i >= 1; i--) {
+		if (is_join && i != count) {
+			h = duk_require_hstring(ctx, -((duk_idx_t) count) - 2);  /* extra -1 for buffer */
+			DUK_MEMCPY(buf + idx, DUK_HSTRING_GET_DATA(h), DUK_HSTRING_GET_BYTELEN(h));
+			idx += DUK_HSTRING_GET_BYTELEN(h);
+		}
+		h = duk_require_hstring(ctx, -((duk_idx_t) i) - 1);  /* extra -1 for buffer */
+		DUK_MEMCPY(buf + idx, DUK_HSTRING_GET_DATA(h), DUK_HSTRING_GET_BYTELEN(h));
+		idx += DUK_HSTRING_GET_BYTELEN(h);
 	}
 
-	/* [ ... result/error ] */
+	DUK_ASSERT(idx == len);
 
- got_rc:
-	if (flags & DUK_COMPILE_NORESULT) {
-		duk_pop(ctx);
+	/* [... (sep) str1 str2 ... strN buf] */
+
+	/* get rid of the strings early to minimize memory use before intern */
+
+	if (is_join) {
+		duk_replace(ctx, -((duk_idx_t) count) - 2);  /* overwrite sep */
+		duk_pop_n(ctx, count);
+	} else {
+		duk_replace(ctx, -((duk_idx_t) count) - 1);  /* overwrite str1 */
+		duk_pop_n(ctx, count-1);
 	}
 
-	return rc;
+	/* [... buf] */
+
+	(void) duk_to_string(ctx, -1);
+
+	/* [... res] */
+	return;
+
+ error_overflow:
+	DUK_ERROR(thr, DUK_ERR_RANGE_ERROR, DUK_STR_CONCAT_RESULT_TOO_LONG);
 }
 
-/* Helper which can be called both directly and with duk_safe_call(). */
-static duk_ret_t duk__do_compile(duk_context *ctx) {
-	duk_hthread *thr = (duk_hthread *) ctx;
-	duk__compile_raw_args *comp_args;
-	duk_uint_t flags;
-	duk_small_uint_t comp_flags;
-	duk_hcompiledfunction *h_templ;
+DUK_EXTERNAL void duk_concat(duk_context *ctx, duk_idx_t count) {
+	DUK_ASSERT_CTX_VALID(ctx);
 
-	/* [ ... source? filename &comp_args ] (depends on flags) */
+	duk__concat_and_join_helper(ctx, count, 0 /*is_join*/);
+}
 
-	comp_args = (duk__compile_raw_args *) duk_require_pointer(ctx, -1);
-	flags = comp_args->flags;
-	duk_pop(ctx);
+DUK_EXTERNAL void duk_join(duk_context *ctx, duk_idx_t count) {
+	DUK_ASSERT_CTX_VALID(ctx);
 
-	/* [ ... source? filename ] */
+	duk__concat_and_join_helper(ctx, count, 1 /*is_join*/);
+}
 
-	if (!comp_args->src_buffer) {
-		duk_hstring *h_sourcecode;
+/* XXX: could map/decode be unified with duk_unicode_support.c code?
+ * Case conversion needs also the character surroundings though.
+ */
+
+DUK_EXTERNAL void duk_decode_string(duk_context *ctx, duk_idx_t index, duk_decode_char_function callback, void *udata) {
+	duk_hthread *thr = (duk_hthread *) ctx;
+	duk_hstring *h_input;
+	const duk_uint8_t *p, *p_start, *p_end;
+	duk_codepoint_t cp;
+
+	DUK_ASSERT_CTX_VALID(ctx);
+
+	h_input = duk_require_hstring(ctx, index);
+	DUK_ASSERT(h_input != NULL);
+
+	p_start = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_input);
+	p_end = p_start + DUK_HSTRING_GET_BYTELEN(h_input);
+	p = p_start;
 
-		if (flags & DUK_COMPILE_NOSOURCE) {
-			DUK_ERROR(thr, DUK_ERR_API_ERROR, "no sourcecode");
+	for (;;) {
+		if (p >= p_end) {
+			break;
 		}
-		h_sourcecode = duk_require_hstring(ctx, -2);
-		comp_args->src_buffer = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_sourcecode);
-		comp_args->src_length = (duk_size_t) DUK_HSTRING_GET_BYTELEN(h_sourcecode);
+		cp = (int) duk_unicode_decode_xutf8_checked(thr, &p, p_start, p_end);
+		callback(udata, cp);
 	}
-	DUK_ASSERT(comp_args->src_buffer != NULL);
+}
 
-	/* XXX: unnecessary translation of flags */
-	comp_flags = 0;
-	if (flags & DUK_COMPILE_EVAL) {
-		comp_flags |= DUK_JS_COMPILE_FLAG_EVAL;
-	}
-	if (flags & DUK_COMPILE_FUNCTION) {
-		comp_flags |= DUK_JS_COMPILE_FLAG_EVAL |
-		              DUK_JS_COMPILE_FLAG_FUNCEXPR;
-	}
-	if (flags & DUK_COMPILE_STRICT) {
-		comp_flags |= DUK_JS_COMPILE_FLAG_STRICT;
+DUK_EXTERNAL void duk_map_string(duk_context *ctx, duk_idx_t index, duk_map_char_function callback, void *udata) {
+	duk_hthread *thr = (duk_hthread *) ctx;
+	duk_hstring *h_input;
+	duk_bufwriter_ctx bw_alloc;
+	duk_bufwriter_ctx *bw;
+	const duk_uint8_t *p, *p_start, *p_end;
+	duk_codepoint_t cp;
+
+	DUK_ASSERT_CTX_VALID(ctx);
+
+	index = duk_normalize_index(ctx, index);
+
+	h_input = duk_require_hstring(ctx, index);
+	DUK_ASSERT(h_input != NULL);
+
+	bw = &bw_alloc;
+	DUK_BW_INIT_PUSHBUF(thr, bw, DUK_HSTRING_GET_BYTELEN(h_input));  /* reasonable output estimate */
+
+	p_start = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_input);
+	p_end = p_start + DUK_HSTRING_GET_BYTELEN(h_input);
+	p = p_start;
+
+	for (;;) {
+		/* XXX: could write output in chunks with fewer ensure calls,
+		 * but relative benefit would be small here.
+		 */
+
+		if (p >= p_end) {
+			break;
+		}
+		cp = (int) duk_unicode_decode_xutf8_checked(thr, &p, p_start, p_end);
+		cp = callback(udata, cp);
+
+		DUK_BW_WRITE_ENSURE_XUTF8(thr, bw, cp);
 	}
 
-	/* [ ... source? filename ] */
+	DUK_BW_COMPACT(thr, bw);
+	duk_to_string(ctx, -1);
+	duk_replace(ctx, index);
+}
 
-	duk_js_compile(thr, comp_args->src_buffer, comp_args->src_length, comp_flags);
+DUK_EXTERNAL void duk_substring(duk_context *ctx, duk_idx_t index, duk_size_t start_offset, duk_size_t end_offset) {
+	duk_hthread *thr = (duk_hthread *) ctx;
+	duk_hstring *h;
+	duk_hstring *res;
+	duk_size_t start_byte_offset;
+	duk_size_t end_byte_offset;
 
-	/* [ ... source? func_template ] */
+	DUK_ASSERT_CTX_VALID(ctx);
 
-	if (flags & DUK_COMPILE_NOSOURCE) {
-		;
-	} else {
-		duk_remove(ctx, -2);
+	index = duk_require_normalize_index(ctx, index);
+	h = duk_require_hstring(ctx, index);
+	DUK_ASSERT(h != NULL);
+
+	if (end_offset >= DUK_HSTRING_GET_CHARLEN(h)) {
+		end_offset = DUK_HSTRING_GET_CHARLEN(h);
+	}
+	if (start_offset > end_offset) {
+		start_offset = end_offset;
 	}
 
-	/* [ ... func_template ] */
+	DUK_ASSERT_DISABLE(start_offset >= 0);
+	DUK_ASSERT(start_offset <= end_offset && start_offset <= DUK_HSTRING_GET_CHARLEN(h));
+	DUK_ASSERT_DISABLE(end_offset >= 0);
+	DUK_ASSERT(end_offset >= start_offset && end_offset <= DUK_HSTRING_GET_CHARLEN(h));
+
+	/* guaranteed by string limits */
+	DUK_ASSERT(start_offset <= DUK_UINT32_MAX);
+	DUK_ASSERT(end_offset <= DUK_UINT32_MAX);
+
+	start_byte_offset = (duk_size_t) duk_heap_strcache_offset_char2byte(thr, h, (duk_uint_fast32_t) start_offset);
+	end_byte_offset = (duk_size_t) duk_heap_strcache_offset_char2byte(thr, h, (duk_uint_fast32_t) end_offset);
 
-	h_templ = (duk_hcompiledfunction *) duk_get_hobject(ctx, -1);
-	DUK_ASSERT(h_templ != NULL);
-	duk_js_push_closure(thr,
-	                   h_templ,
-	                   thr->builtins[DUK_BIDX_GLOBAL_ENV],
-	                   thr->builtins[DUK_BIDX_GLOBAL_ENV]);
-	duk_remove(ctx, -2);   /* -> [ ... closure ] */
+	DUK_ASSERT(end_byte_offset >= start_byte_offset);
+	DUK_ASSERT(end_byte_offset - start_byte_offset <= DUK_UINT32_MAX);  /* guaranteed by string limits */
 
-	/* [ ... closure ] */
+	/* no size check is necessary */
+	res = duk_heap_string_intern_checked(thr,
+	                                     DUK_HSTRING_GET_DATA(h) + start_byte_offset,
+	                                     (duk_uint32_t) (end_byte_offset - start_byte_offset));
 
-	return 1;
+	duk_push_hstring(ctx, res);
+	duk_replace(ctx, index);
 }
 
-duk_int_t duk_compile_raw(duk_context *ctx, const char *src_buffer, duk_size_t src_length, duk_uint_t flags) {
-	duk__compile_raw_args comp_args_alloc;
-	duk__compile_raw_args *comp_args = &comp_args_alloc;
+/* XXX: this is quite clunky.  Add Unicode helpers to scan backwards and
+ * forwards with a callback to process codepoints?
+ */
+DUK_EXTERNAL void duk_trim(duk_context *ctx, duk_idx_t index) {
+	duk_hthread *thr = (duk_hthread *) ctx;
+	duk_hstring *h;
+	const duk_uint8_t *p, *p_start, *p_end, *p_tmp1, *p_tmp2;  /* pointers for scanning */
+	const duk_uint8_t *q_start, *q_end;  /* start (incl) and end (excl) of trimmed part */
+	duk_codepoint_t cp;
 
-	if ((flags & DUK_COMPILE_STRLEN) && (src_buffer != NULL)) {
-		/* String length is computed here to avoid multiple evaluation
-		 * of a macro argument in the calling side.
-		 */
-		src_length = DUK_STRLEN(src_buffer);
-	}
+	DUK_ASSERT_CTX_VALID(ctx);
 
-	comp_args->src_buffer = (const duk_uint8_t *) src_buffer;
-	comp_args->src_length = src_length;
-	comp_args->flags = flags;
-	duk_push_pointer(ctx, (void *) comp_args);
+	index = duk_require_normalize_index(ctx, index);
+	h = duk_require_hstring(ctx, index);
+	DUK_ASSERT(h != NULL);
 
-	/* [ ... source? filename &comp_args ] (depends on flags) */
+	p_start = DUK_HSTRING_GET_DATA(h);
+	p_end = p_start + DUK_HSTRING_GET_BYTELEN(h);
 
-	if (flags & DUK_COMPILE_SAFE) {
-		duk_int_t rc;
-		duk_int_t nargs;
-		duk_int_t nrets = 1;
+	p = p_start;
+	while (p < p_end) {
+		p_tmp1 = p;
+		cp = (duk_codepoint_t) duk_unicode_decode_xutf8_checked(thr, &p_tmp1, p_start, p_end);
+		if (!(duk_unicode_is_whitespace(cp) || duk_unicode_is_line_terminator(cp))) {
+			break;
+		}
+		p = p_tmp1;
+	}
+	q_start = p;
+	if (p == p_end) {
+		/* entire string is whitespace */
+		q_end = p;
+		goto scan_done;
+	}
 
-		/* Arguments are either: [ filename &comp_args ] or [ source filename &comp_args ] */
-		nargs = (flags & DUK_COMPILE_NOSOURCE) ? 2 : 3;
-		rc = duk_safe_call(ctx, duk__do_compile, nargs, nrets);
+	p = p_end;
+	while (p > p_start) {
+		p_tmp1 = p;
+		while (p > p_start) {
+			p--;
+			if (((*p) & 0xc0) != 0x80) {
+				break;
+			}
+		}
+		p_tmp2 = p;
 
-		/* [ ... closure ] */
-		return rc;
+		cp = (duk_codepoint_t) duk_unicode_decode_xutf8_checked(thr, &p_tmp2, p_start, p_end);
+		if (!(duk_unicode_is_whitespace(cp) || duk_unicode_is_line_terminator(cp))) {
+			p = p_tmp1;
+			break;
+		}
 	}
+	q_end = p;
 
-	(void) duk__do_compile(ctx);
+ scan_done:
+	/* This may happen when forward and backward scanning disagree
+	 * (possible for non-extended-UTF-8 strings).
+	 */
+	if (q_end < q_start) {
+		q_end = q_start;
+	}
 
-	/* [ ... closure ] */
-	return DUK_EXEC_SUCCESS;
+	DUK_ASSERT(q_start >= p_start && q_start <= p_end);
+	DUK_ASSERT(q_end >= p_start && q_end <= p_end);
+	DUK_ASSERT(q_end >= q_start);
+
+	DUK_DDD(DUK_DDDPRINT("trim: p_start=%p, p_end=%p, q_start=%p, q_end=%p",
+	                     (const void *) p_start, (const void *) p_end,
+	                     (const void *) q_start, (const void *) q_end));
+
+	if (q_start == p_start && q_end == p_end) {
+		DUK_DDD(DUK_DDDPRINT("nothing was trimmed: avoid interning (hashing etc)"));
+		return;
+	}
+
+	duk_push_lstring(ctx, (const char *) q_start, (duk_size_t) (q_end - q_start));
+	duk_replace(ctx, index);
 }
-#line 1 "duk_api_debug.c"
-/*
- *  Debugging related API calls
- */
 
-/* include removed: duk_internal.h */
+DUK_EXTERNAL duk_codepoint_t duk_char_code_at(duk_context *ctx, duk_idx_t index, duk_size_t char_offset) {
+	duk_hthread *thr = (duk_hthread *) ctx;
+	duk_hstring *h;
+	duk_ucodepoint_t cp;
 
-void duk_push_context_dump(duk_context *ctx) {
-	duk_idx_t idx;
-	duk_idx_t top;
+	DUK_ASSERT_CTX_VALID(ctx);
 
-	/* We don't duk_require_stack() here now, but rely on the caller having
-	 * enough space.
-	 */
+	h = duk_require_hstring(ctx, index);
+	DUK_ASSERT(h != NULL);
 
-	top = duk_get_top(ctx);
-	duk_push_array(ctx);
-	for (idx = 0; idx < top; idx++) {
-		duk_dup(ctx, idx);
-		duk_put_prop_index(ctx, -2, idx);
+	DUK_ASSERT_DISABLE(char_offset >= 0);  /* always true, arg is unsigned */
+	if (char_offset >= DUK_HSTRING_GET_CHARLEN(h)) {
+		return 0;
 	}
 
-	/* FIXME: conversion errors should not propagate outwards.
-	 * Perhaps values need to be coerced individually?
-	 */
-	duk_bi_json_stringify_helper(ctx,
-	                             duk_get_top_index(ctx),  /*idx_value*/
-	                             DUK_INVALID_INDEX,  /*idx_replacer*/
-	                             DUK_INVALID_INDEX,  /*idx_space*/
-	                             DUK_JSON_FLAG_EXT_CUSTOM |
-	                             DUK_JSON_FLAG_ASCII_ONLY |
-	                             DUK_JSON_FLAG_AVOID_KEY_QUOTES /*flags*/);
-
-	duk_push_sprintf(ctx, "ctx: top=%ld, stack=%s", (long) top, (const char *) duk_safe_to_string(ctx, -1));
-	duk_replace(ctx, -3);  /* [ ... arr jsonx(arr) res ] -> [ ... res jsonx(arr) ] */
-	duk_pop(ctx);
-	DUK_ASSERT(duk_is_string(ctx, -1));
+	DUK_ASSERT(char_offset <= DUK_UINT_MAX);  /* guaranteed by string limits */
+	cp = duk_hstring_char_code_at_raw(thr, h, (duk_uint_t) char_offset);
+	return (duk_codepoint_t) cp;
 }
-#line 1 "duk_api_logging.c"
+#line 1 "duk_api_var.c"
 /*
- *  Logging
- *
- *  Current logging primitive is a sprintf-style log which is convenient
- *  for most C code.  Another useful primitive would be to log N arguments
- *  from value stack (like the Ecmascript binding does).
+ *  Variable access
  */
 
 /* include removed: duk_internal.h */
 
-void duk_log(duk_context *ctx, duk_int_t level, const char *fmt, ...) {
-	va_list ap;
-	/* stridx_logfunc[] must be static to allow initializer with old compilers like BCC */
-	static const duk_uint16_t stridx_logfunc[6] = {
-		DUK_STRIDX_LC_TRACE, DUK_STRIDX_LC_DEBUG, DUK_STRIDX_LC_INFO,
-		DUK_STRIDX_LC_WARN, DUK_STRIDX_LC_ERROR, DUK_STRIDX_LC_FATAL
-	};
-
-	if (level < 0) {
-		level = 0;
-	} else if (level > (int) (sizeof(stridx_logfunc) / sizeof(duk_uint16_t)) - 1) {
-		level = (int) (sizeof(stridx_logfunc) / sizeof(duk_uint16_t)) - 1;
-	}
+DUK_EXTERNAL void duk_get_var(duk_context *ctx) {
+	duk_hthread *thr = (duk_hthread *) ctx;
+	duk_activation *act;
+	duk_hstring *h_varname;
+	duk_small_int_t throw_flag = 1;  /* always throw ReferenceError for unresolvable */
 
-	duk_push_hobject_bidx(ctx, DUK_BIDX_LOGGER_CONSTRUCTOR);
-	duk_get_prop_stridx(ctx, -1, DUK_STRIDX_CLOG);
-	duk_get_prop_stridx(ctx, -1, stridx_logfunc[level]);
-	duk_dup(ctx, -2);
+	DUK_ASSERT_CTX_VALID(ctx);
 
-	/* [ ... Logger clog logfunc clog ] */
+	h_varname = duk_require_hstring(ctx, -1);  /* XXX: tostring? */
+	DUK_ASSERT(h_varname != NULL);
 
-	va_start(ap, fmt);
-	duk_push_vsprintf(ctx, fmt, ap);
-	va_end(ap);
+	act = duk_hthread_get_current_activation(thr);
+	if (act) {
+		(void) duk_js_getvar_activation(thr, act, h_varname, throw_flag);  /* -> [ ... varname val this ] */
+	} else {
+		/* Outside any activation -> look up from global. */
+		DUK_ASSERT(thr->builtins[DUK_BIDX_GLOBAL_ENV] != NULL);
+		(void) duk_js_getvar_envrec(thr, thr->builtins[DUK_BIDX_GLOBAL_ENV], h_varname, throw_flag);
+	}
 
-	/* [ ... Logger clog logfunc clog(=this) msg ] */
+	/* [ ... varname val this ]  (because throw_flag == 1, always resolved) */
 
-	duk_call_method(ctx, 1 /*nargs*/);
+	duk_pop(ctx);
+	duk_remove(ctx, -2);
 
-	/* [ ... Logger clog res ] */
+	/* [ ... val ] */
 
-	duk_pop_3(ctx);
+	/* Return value would be pointless: because throw_flag==1, we always
+	 * throw if the identifier doesn't resolve.
+	 */
+	return;
 }
-#line 1 "duk_api_memory.c"
-/*
- *  Memory calls.
- */
-
-/* include removed: duk_internal.h */
 
-void *duk_alloc_raw(duk_context *ctx, duk_size_t size) {
+DUK_EXTERNAL void duk_put_var(duk_context *ctx) {
 	duk_hthread *thr = (duk_hthread *) ctx;
+	duk_activation *act;
+	duk_hstring *h_varname;
+	duk_tval *tv_val;
+	duk_small_int_t throw_flag;
 
-	DUK_ASSERT(ctx != NULL);
+	DUK_ASSERT_CTX_VALID(ctx);
 
-	return DUK_ALLOC_RAW(thr->heap, size);
-}
+	h_varname = duk_require_hstring(ctx, -2);  /* XXX: tostring? */
+	DUK_ASSERT(h_varname != NULL);
 
-void duk_free_raw(duk_context *ctx, void *ptr) {
-	duk_hthread *thr = (duk_hthread *) ctx;
+	tv_val = duk_require_tval(ctx, -1);
 
-	DUK_ASSERT(ctx != NULL);
+	throw_flag = duk_is_strict_call(ctx);
 
-	DUK_FREE_RAW(thr->heap, ptr);
-}
+	act = duk_hthread_get_current_activation(thr);
+	if (act) {
+		duk_js_putvar_activation(thr, act, h_varname, tv_val, throw_flag);  /* -> [ ... varname val this ] */
+	} else {
+		/* Outside any activation -> put to global. */
+		DUK_ASSERT(thr->builtins[DUK_BIDX_GLOBAL_ENV] != NULL);
+		duk_js_putvar_envrec(thr, thr->builtins[DUK_BIDX_GLOBAL_ENV], h_varname, tv_val, throw_flag);
+	}
 
-void *duk_realloc_raw(duk_context *ctx, void *ptr, duk_size_t size) {
-	duk_hthread *thr = (duk_hthread *) ctx;
+	/* [ ... varname val ] */
 
-	DUK_ASSERT(ctx != NULL);
+	duk_pop_2(ctx);
 
-	return DUK_REALLOC_RAW(thr->heap, ptr, size);
+	/* [ ... ] */
+
+	return;
 }
 
-void *duk_alloc(duk_context *ctx, duk_size_t size) {
-	duk_hthread *thr = (duk_hthread *) ctx;
+DUK_EXTERNAL duk_bool_t duk_del_var(duk_context *ctx) {
+	DUK_ASSERT_CTX_VALID(ctx);
 
-	DUK_ASSERT(ctx != NULL);
+	DUK_ERROR((duk_hthread *) ctx, DUK_ERR_UNIMPLEMENTED_ERROR, DUK_STR_UNIMPLEMENTED);
+	return 0;
+}
 
-	return DUK_ALLOC(thr->heap, size);
+DUK_EXTERNAL duk_bool_t duk_has_var(duk_context *ctx) {
+	DUK_ASSERT_CTX_VALID(ctx);
+
+	DUK_ERROR((duk_hthread *) ctx, DUK_ERR_UNIMPLEMENTED_ERROR, DUK_STR_UNIMPLEMENTED);
+	return 0;
 }
+#line 1 "duk_bi_array.c"
+/*
+ *  Array built-ins
+ *
+ *  Note that most Array built-ins are intentionally generic and work even
+ *  when the 'this' binding is not an Array instance.  To ensure this,
+ *  Array algorithms do not assume "magical" Array behavior for the "length"
+ *  property, for instance.
+ *
+ *  XXX: the "Throw" flag should be set for (almost?) all [[Put]] and
+ *  [[Delete]] operations, but it's currently false throughout.  Go through
+ *  all put/delete cases and check throw flag use.  Need a new API primitive
+ *  which allows throws flag to be specified.
+ *
+ *  XXX: array lengths above 2G won't work reliably.  There are many places
+ *  where one needs a full signed 32-bit range ([-0xffffffff, 0xffffffff],
+ *  i.e. -33- bits).  Although array 'length' cannot be written to be outside
+ *  the unsigned 32-bit range (E5.1 Section 15.4.5.1 throws a RangeError if so)
+ *  some intermediate values may be above 0xffffffff and this may not be always
+ *  correctly handled now (duk_uint32_t is not enough for all algorithms).
+ *
+ *  For instance, push() can legitimately write entries beyond length 0xffffffff
+ *  and cause a RangeError only at the end.  To do this properly, the current
+ *  push() implementation tracks the array index using a 'double' instead of a
+ *  duk_uint32_t (which is somewhat awkward).  See test-bi-array-push-maxlen.js.
+ *
+ *  On using "put" vs. "def" prop
+ *  =============================
+ *
+ *  Code below must be careful to use the appropriate primitive as it matters
+ *  for compliance.  When using "put" there may be inherited properties in
+ *  Array.prototype which cause side effects when values are written.  When
+ *  using "define" there are no such side effects, and many test262 test cases
+ *  check for this (for real world code, such side effects are very rare).
+ *  Both "put" and "define" are used in the E5.1 specification; as a rule,
+ *  "put" is used when modifying an existing array (or a non-array 'this'
+ *  binding) and "define" for setting values into a fresh result array.
+ *
+ *  Also note that Array instance 'length' should be writable, but not
+ *  enumerable and definitely not configurable: even Duktape code internally
+ *  assumes that an Array instance will always have a 'length' property.
+ *  Preventing deletion of the property is critical.
+ */
 
-void duk_free(duk_context *ctx, void *ptr) {
-	duk_hthread *thr = (duk_hthread *) ctx;
+/* include removed: duk_internal.h */
 
-	DUK_ASSERT(ctx != NULL);
+/* Perform an intermediate join when this many elements have been pushed
+ * on the value stack.
+ */
+#define  DUK__ARRAY_MID_JOIN_LIMIT  4096
 
-	DUK_FREE(thr->heap, ptr);
-}
+/* Shared entry code for many Array built-ins.  Note that length is left
+ * on stack (it could be popped, but that's not necessary).
+ */
+DUK_LOCAL duk_uint32_t duk__push_this_obj_len_u32(duk_context *ctx) {
+	duk_uint32_t len;
 
-void *duk_realloc(duk_context *ctx, void *ptr, duk_size_t size) {
-	duk_hthread *thr = (duk_hthread *) ctx;
+	(void) duk_push_this_coercible_to_object(ctx);
+	duk_get_prop_stridx(ctx, -1, DUK_STRIDX_LENGTH);
+	len = duk_to_uint32(ctx, -1);
 
-	DUK_ASSERT(ctx != NULL);
+	/* -> [ ... ToObject(this) ToUint32(length) ] */
+	return len;
+}
 
-	/*
-	 *  Note: since this is an exposed API call, there should be
-	 *  no way a mark-and-sweep could have a side effect on the
-	 *  memory allocation behind 'ptr'; the pointer should never
-	 *  be something that Duktape wants to change.
-	 *
-	 *  Thus, no need to use DUK_REALLOC_INDIRECT (and we don't
-	 *  have the storage location here anyway).
+DUK_LOCAL duk_uint32_t duk__push_this_obj_len_u32_limited(duk_context *ctx) {
+	/* Range limited to [0, 0x7fffffff] range, i.e. range that can be
+	 * represented with duk_int32_t.  Use this when the method doesn't
+	 * handle the full 32-bit unsigned range correctly.
 	 */
-
-	return DUK_REALLOC(thr->heap, ptr, size);
+	duk_uint32_t ret = duk__push_this_obj_len_u32(ctx);
+	if (DUK_UNLIKELY(ret >= 0x80000000UL)) {
+		DUK_ERROR((duk_hthread *) ctx, DUK_ERR_INTERNAL_ERROR, DUK_STR_ARRAY_LENGTH_OVER_2G);
+	}
+	return ret;
 }
 
-void duk_get_memory_functions(duk_context *ctx, duk_memory_functions *out_funcs) {
-	duk_hthread *thr = (duk_hthread *) ctx;
-	duk_heap *heap;
+/*
+ *  Constructor
+ */
 
-	DUK_ASSERT(ctx != NULL);
-	DUK_ASSERT(out_funcs != NULL);
-	DUK_ASSERT(thr != NULL);
-	DUK_ASSERT(thr->heap != NULL);
+DUK_INTERNAL duk_ret_t duk_bi_array_constructor(duk_context *ctx) {
+	duk_idx_t nargs;
+	duk_double_t d;
+	duk_uint32_t len;
+	duk_idx_t i;
 
-	heap = thr->heap;
-	out_funcs->alloc = heap->alloc_func;
-	out_funcs->realloc = heap->realloc_func;
-	out_funcs->free = heap->free_func;
-	out_funcs->udata = heap->alloc_udata;
-}
+	nargs = duk_get_top(ctx);
+	duk_push_array(ctx);
 
-void duk_gc(duk_context *ctx, duk_uint_t flags) {
-#ifdef DUK_USE_MARK_AND_SWEEP
-	duk_hthread *thr = (duk_hthread *) ctx;
-	duk_heap *heap;
+	if (nargs == 1 && duk_is_number(ctx, 0)) {
+		/* XXX: expensive check (also shared elsewhere - so add a shared internal API call?) */
+		d = duk_get_number(ctx, 0);
+		len = duk_to_uint32(ctx, 0);
+		if (((duk_double_t) len) != d) {
+			return DUK_RET_RANGE_ERROR;
+		}
 
-	DUK_UNREF(flags);
+		/* XXX: if 'len' is low, may want to ensure array part is kept:
+		 * the caller is likely to want a dense array.
+		 */
+		duk_push_u32(ctx, len);
+		duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_LENGTH, DUK_PROPDESC_FLAGS_W);  /* [ ToUint32(len) array ToUint32(len) ] -> [ ToUint32(len) array ] */
+		return 1;
+	}
 
-	if (!ctx) {
-		return;
+	/* XXX: optimize by creating array into correct size directly, and
+	 * operating on the array part directly; values can be memcpy()'d from
+	 * value stack directly as long as refcounts are increased.
+	 */
+	for (i = 0; i < nargs; i++) {
+		duk_dup(ctx, i);
+		duk_xdef_prop_index_wec(ctx, -2, (duk_uarridx_t) i);
 	}
-	heap = thr->heap;
-	DUK_ASSERT(heap != NULL);
 
-	DUK_D(DUK_DPRINT("mark-and-sweep requested by application"));
-	duk_heap_mark_and_sweep(heap, 0);
-#else
-	DUK_D(DUK_DPRINT("mark-and-sweep requested by application but mark-and-sweep not enabled, ignoring"));
-	DUK_UNREF(ctx);
-	DUK_UNREF(flags);
-#endif
+	duk_push_u32(ctx, (duk_uint32_t) nargs);
+	duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_LENGTH, DUK_PROPDESC_FLAGS_W);
+	return 1;
 }
-#line 1 "duk_api_object.c"
+
 /*
- *  Object handling: property access and other support functions.
+ *  isArray()
  */
 
-/* include removed: duk_internal.h */
+DUK_INTERNAL duk_ret_t duk_bi_array_constructor_is_array(duk_context *ctx) {
+	duk_hobject *h;
+
+	h = duk_get_hobject_with_class(ctx, 0, DUK_HOBJECT_CLASS_ARRAY);
+	duk_push_boolean(ctx, (h != NULL));
+	return 1;
+}
 
 /*
- *  Property handling
- *
- *  The API exposes only the most common property handling functions.
- *  The caller can invoke Ecmascript built-ins for full control (e.g.
- *  defineProperty, getOwnPropertyDescriptor).
+ *  toString()
  */
 
-duk_bool_t duk_get_prop(duk_context *ctx, duk_idx_t obj_index) {
-	duk_hthread *thr = (duk_hthread *) ctx;
-	duk_tval *tv_obj;
-	duk_tval *tv_key;
-	duk_bool_t rc;
+DUK_INTERNAL duk_ret_t duk_bi_array_prototype_to_string(duk_context *ctx) {
+	(void) duk_push_this_coercible_to_object(ctx);
+	duk_get_prop_stridx(ctx, -1, DUK_STRIDX_JOIN);
 
-	DUK_ASSERT(ctx != NULL);
+	/* [ ... this func ] */
+	if (!duk_is_callable(ctx, -1)) {
+		/* Fall back to the initial (original) Object.toString().  We don't
+		 * currently have pointers to the built-in functions, only the top
+		 * level global objects (like "Array") so this is now done in a bit
+		 * of a hacky manner.  It would be cleaner to push the (original)
+		 * function and use duk_call_method().
+		 */
 
-	/* Note: copying tv_obj and tv_key to locals to shield against a valstack
-	 * resize is not necessary for a property get right now.
-	 */
+		/* XXX: 'this' will be ToObject() coerced twice, which is incorrect
+		 * but should have no visible side effects.
+		 */
+		DUK_DDD(DUK_DDDPRINT("this.join is not callable, fall back to (original) Object.toString"));
+		duk_set_top(ctx, 0);
+		return duk_bi_object_prototype_to_string(ctx);  /* has access to 'this' binding */
+	}
 
-	tv_obj = duk_require_tval(ctx, obj_index);
-	tv_key = duk_require_tval(ctx, -1);
+	/* [ ... this func ] */
 
-	rc = duk_hobject_getprop(thr, tv_obj, tv_key);
-	DUK_ASSERT(rc == 0 || rc == 1);
-	/* a value is left on stack regardless of rc */
+	duk_insert(ctx, -2);
 
-	duk_remove(ctx, -2);  /* remove key */
-	return rc;  /* 1 if property found, 0 otherwise */
-}
+	/* [ ... func this ] */
 
-duk_bool_t duk_get_prop_string(duk_context *ctx, duk_idx_t obj_index, const char *key) {
-	DUK_ASSERT(ctx != NULL);
-	DUK_ASSERT(key != NULL);
+	DUK_DDD(DUK_DDDPRINT("calling: func=%!iT, this=%!iT",
+	                     (duk_tval *) duk_get_tval(ctx, -2),
+	                     (duk_tval *) duk_get_tval(ctx, -1)));
+	duk_call_method(ctx, 0);
 
-	obj_index = duk_require_normalize_index(ctx, obj_index);
-	duk_push_string(ctx, key);
-	return duk_get_prop(ctx, obj_index);
+	return 1;
 }
 
-duk_bool_t duk_get_prop_index(duk_context *ctx, duk_idx_t obj_index, duk_uarridx_t arr_index) {
-	DUK_ASSERT(ctx != NULL);
+/*
+ *  concat()
+ */
 
-	obj_index = duk_require_normalize_index(ctx, obj_index);
-	duk_push_number(ctx, (double) arr_index);
-	return duk_get_prop(ctx, obj_index);
-}
+DUK_INTERNAL duk_ret_t duk_bi_array_prototype_concat(duk_context *ctx) {
+	duk_idx_t i, n;
+	duk_uarridx_t idx, idx_last;
+	duk_uarridx_t j, len;
+	duk_hobject *h;
 
-duk_bool_t duk_get_prop_stridx(duk_context *ctx, duk_idx_t obj_index, duk_small_int_t stridx) {
-	duk_hthread *thr = (duk_hthread *) ctx;
+	/* XXX: the insert here is a bit expensive if there are a lot of items.
+	 * It could also be special cased in the outermost for loop quite easily
+	 * (as the element is dup()'d anyway).
+	 */
 
-	DUK_ASSERT(ctx != NULL);
-	DUK_ASSERT_DISABLE(stridx >= 0);
-	DUK_ASSERT(stridx < DUK_HEAP_NUM_STRINGS);
+	(void) duk_push_this_coercible_to_object(ctx);
+	duk_insert(ctx, 0);
+	n = duk_get_top(ctx);
+	duk_push_array(ctx);  /* -> [ ToObject(this) item1 ... itemN arr ] */
 
-	obj_index = duk_require_normalize_index(ctx, obj_index);
-	duk_push_hstring(ctx, thr->strs[stridx]);
-	return duk_get_prop(ctx, obj_index);
-}
+	/* NOTE: The Array special behaviors are NOT invoked by duk_xdef_prop_index()
+	 * (which differs from the official algorithm).  If no error is thrown, this
+	 * doesn't matter as the length is updated at the end.  However, if an error
+	 * is thrown, the length will be unset.  That shouldn't matter because the
+	 * caller won't get a reference to the intermediate value.
+	 */
 
-duk_bool_t duk_get_prop_stridx_boolean(duk_context *ctx, duk_idx_t obj_index, duk_small_int_t stridx, duk_bool_t *out_has_prop) {
-	duk_bool_t rc;
+	idx = 0;
+	idx_last = 0;
+	for (i = 0; i < n; i++) {
+		DUK_ASSERT_TOP(ctx, n + 1);
 
-	DUK_ASSERT(ctx != NULL);
-	DUK_ASSERT_DISABLE(stridx >= 0);
-	DUK_ASSERT(stridx < DUK_HEAP_NUM_STRINGS);
+		/* [ ToObject(this) item1 ... itemN arr ] */
 
-	rc = duk_get_prop_stridx(ctx, obj_index, stridx);
-	if (out_has_prop) {
-		*out_has_prop = rc;
-	}
-	rc = duk_to_boolean(ctx, -1);
-	DUK_ASSERT(rc == 0 || rc == 1);
-	duk_pop(ctx);
-	return rc;
-}
+		duk_dup(ctx, i);
+		h = duk_get_hobject_with_class(ctx, -1, DUK_HOBJECT_CLASS_ARRAY);
+		if (!h) {
+			duk_xdef_prop_index_wec(ctx, -2, idx++);
+			idx_last = idx;
+			continue;
+		}
 
-duk_bool_t duk_put_prop(duk_context *ctx, duk_idx_t obj_index) {
-	duk_hthread *thr = (duk_hthread *) ctx;
-	duk_tval *tv_obj;
-	duk_tval *tv_key;
-	duk_tval *tv_val;
-	duk_small_int_t throw_flag;
-	duk_bool_t rc;
+		/* [ ToObject(this) item1 ... itemN arr item(i) ] */
 
-	DUK_ASSERT(ctx != NULL);
+		/* XXX: an array can have length higher than 32 bits; this is not handled
+		 * correctly now.
+		 */
+		len = (duk_uarridx_t) duk_get_length(ctx, -1);
+		for (j = 0; j < len; j++) {
+			if (duk_get_prop_index(ctx, -1, j)) {
+				/* [ ToObject(this) item1 ... itemN arr item(i) item(i)[j] ] */
+				duk_xdef_prop_index_wec(ctx, -3, idx++);
+				idx_last = idx;
+			} else {
+				idx++;
+				duk_pop(ctx);
+#if defined(DUK_USE_NONSTD_ARRAY_CONCAT_TRAILER)
+				/* According to E5.1 Section 15.4.4.4 nonexistent trailing
+				 * elements do not affect 'length' of the result.  Test262
+				 * and other engines disagree, so update idx_last here too.
+				 */
+				idx_last = idx;
+#else
+				/* Strict standard behavior, ignore trailing elements for
+				 * result 'length'.
+				 */
+#endif
+			}
+		}
+		duk_pop(ctx);
+	}
 
-	/* Note: copying tv_obj and tv_key to locals to shield against a valstack
-	 * resize is not necessary for a property put right now (putprop protects
-	 * against it internally).
+	/* The E5.1 Section 15.4.4.4 algorithm doesn't set the length explicitly
+	 * in the end, but because we're operating with an internal value which
+	 * is known to be an array, this should be equivalent.
 	 */
+	duk_push_uarridx(ctx, idx_last);
+	duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_LENGTH, DUK_PROPDESC_FLAGS_W);
 
-	tv_obj = duk_require_tval(ctx, obj_index);
-	tv_key = duk_require_tval(ctx, -2);
-	tv_val = duk_require_tval(ctx, -1);
-	throw_flag = duk_is_strict_call(ctx);  /* FIXME */
-
-	rc = duk_hobject_putprop(thr, tv_obj, tv_key, tv_val, throw_flag);
-	DUK_ASSERT(rc == 0 || rc == 1);
-
-	duk_pop_2(ctx);  /* remove key and value */
-	return rc;  /* 1 if property found, 0 otherwise */
+	DUK_ASSERT_TOP(ctx, n + 1);
+	return 1;
 }
 
-duk_bool_t duk_put_prop_string(duk_context *ctx, duk_idx_t obj_index, const char *key) {
-	DUK_ASSERT(ctx != NULL);
-	DUK_ASSERT(key != NULL);
+/*
+ *  join(), toLocaleString()
+ *
+ *  Note: checking valstack is necessary, but only in the per-element loop.
+ *
+ *  Note: the trivial approach of pushing all the elements on the value stack
+ *  and then calling duk_join() fails when the array contains a large number
+ *  of elements.  This problem can't be offloaded to duk_join() because the
+ *  elements to join must be handled here and have special handling.  Current
+ *  approach is to do intermediate joins with very large number of elements.
+ *  There is no fancy handling; the prefix gets re-joined multiple times.
+ */
 
-	obj_index = duk_require_normalize_index(ctx, obj_index);
-	duk_push_string(ctx, key);
-	duk_swap_top(ctx, -2);  /* [val key] -> [key val] */
-	return duk_put_prop(ctx, obj_index);
-}
+DUK_INTERNAL duk_ret_t duk_bi_array_prototype_join_shared(duk_context *ctx) {
+	duk_uint32_t len, count;
+	duk_uint32_t idx;
+	duk_small_int_t to_locale_string = duk_get_current_magic(ctx);
+	duk_idx_t valstack_required;
 
-duk_bool_t duk_put_prop_index(duk_context *ctx, duk_idx_t obj_index, duk_uarridx_t arr_index) {
-	DUK_ASSERT(ctx != NULL);
+	/* For join(), nargs is 1.  For toLocaleString(), nargs is 0 and
+	 * setting the top essentially pushes an undefined to the stack,
+	 * thus defaulting to a comma separator.
+	 */
+	duk_set_top(ctx, 1);
+	if (duk_is_undefined(ctx, 0)) {
+		duk_pop(ctx);
+		duk_push_hstring_stridx(ctx, DUK_STRIDX_COMMA);
+	} else {
+		duk_to_string(ctx, 0);
+	}
 
-	obj_index = duk_require_normalize_index(ctx, obj_index);
-	duk_push_number(ctx, (double) arr_index);
-	duk_swap_top(ctx, -2);  /* [val key] -> [key val] */
-	return duk_put_prop(ctx, obj_index);
-}
+	len = duk__push_this_obj_len_u32(ctx);
 
-duk_bool_t duk_put_prop_stridx(duk_context *ctx, duk_idx_t obj_index, duk_small_int_t stridx) {
-	duk_hthread *thr = (duk_hthread *) ctx;
+	/* [ sep ToObject(this) len ] */
 
-	DUK_ASSERT(ctx != NULL);
-	DUK_ASSERT_DISABLE(stridx >= 0);
-	DUK_ASSERT(stridx < DUK_HEAP_NUM_STRINGS);
+	DUK_DDD(DUK_DDDPRINT("sep=%!T, this=%!T, len=%lu",
+	                     (duk_tval *) duk_get_tval(ctx, 0),
+	                     (duk_tval *) duk_get_tval(ctx, 1),
+	                     (unsigned long) len));
 
-	obj_index = duk_require_normalize_index(ctx, obj_index);
-	duk_push_hstring(ctx, thr->strs[stridx]);
-	duk_swap_top(ctx, -2);  /* [val key] -> [key val] */
-	return duk_put_prop(ctx, obj_index);
-}
+	/* The extra (+4) is tight. */
+	valstack_required = (len >= DUK__ARRAY_MID_JOIN_LIMIT ?
+	                     DUK__ARRAY_MID_JOIN_LIMIT : len) + 4;
+	duk_require_stack(ctx, valstack_required);
 
-duk_bool_t duk_del_prop(duk_context *ctx, duk_idx_t obj_index) {
-	duk_hthread *thr = (duk_hthread *) ctx;
-	duk_tval *tv_obj;
-	duk_tval *tv_key;
-	duk_small_int_t throw_flag;
-	duk_bool_t rc;
+	duk_dup(ctx, 0);
 
-	DUK_ASSERT(ctx != NULL);
+	/* [ sep ToObject(this) len sep ] */
 
-	/* Note: copying tv_obj and tv_key to locals to shield against a valstack
-	 * resize is not necessary for a property delete right now.
-	 */
+	count = 0;
+	idx = 0;
+	for (;;) {
+		if (count >= DUK__ARRAY_MID_JOIN_LIMIT ||   /* intermediate join to avoid valstack overflow */
+		    idx >= len) { /* end of loop (careful with len==0) */
+			/* [ sep ToObject(this) len sep str0 ... str(count-1) ] */
+			DUK_DDD(DUK_DDDPRINT("mid/final join, count=%ld, idx=%ld, len=%ld",
+			                     (long) count, (long) idx, (long) len));
+			duk_join(ctx, (duk_idx_t) count);  /* -> [ sep ToObject(this) len str ] */
+			duk_dup(ctx, 0);                   /* -> [ sep ToObject(this) len str sep ] */
+			duk_insert(ctx, -2);               /* -> [ sep ToObject(this) len sep str ] */
+			count = 1;
+		}
+		if (idx >= len) {
+			/* if true, the stack already contains the final result */
+			break;
+		}
 
-	tv_obj = duk_require_tval(ctx, obj_index);
-	tv_key = duk_require_tval(ctx, -1);
-	throw_flag = duk_is_strict_call(ctx);  /* FIXME */
+		duk_get_prop_index(ctx, 1, (duk_uarridx_t) idx);
+		if (duk_is_null_or_undefined(ctx, -1)) {
+			duk_pop(ctx);
+			duk_push_hstring_stridx(ctx, DUK_STRIDX_EMPTY_STRING);
+		} else {
+			if (to_locale_string) {
+				duk_to_object(ctx, -1);
+				duk_get_prop_stridx(ctx, -1, DUK_STRIDX_TO_LOCALE_STRING);
+				duk_insert(ctx, -2);  /* -> [ ... toLocaleString ToObject(val) ] */
+				duk_call_method(ctx, 0);
+				duk_to_string(ctx, -1);
+			} else {
+				duk_to_string(ctx, -1);
+			}
+		}
 
-	rc = duk_hobject_delprop(thr, tv_obj, tv_key, throw_flag);
-	DUK_ASSERT(rc == 0 || rc == 1);
+		count++;
+		idx++;
+	}
 
-	duk_pop(ctx);  /* remove key */
-	return rc;
+	/* [ sep ToObject(this) len sep result ] */
+
+	return 1;
 }
 
-duk_bool_t duk_del_prop_string(duk_context *ctx, duk_idx_t obj_index, const char *key) {
-	DUK_ASSERT(ctx != NULL);
-	DUK_ASSERT(key != NULL);
+/*
+ *  pop(), push()
+ */
 
-	obj_index = duk_require_normalize_index(ctx, obj_index);
-	duk_push_string(ctx, key);
-	return duk_del_prop(ctx, obj_index);
-}
+DUK_INTERNAL duk_ret_t duk_bi_array_prototype_pop(duk_context *ctx) {
+	duk_uint32_t len;
+	duk_uint32_t idx;
 
-duk_bool_t duk_del_prop_index(duk_context *ctx, duk_idx_t obj_index, duk_uarridx_t arr_index) {
-	DUK_ASSERT(ctx != NULL);
+	DUK_ASSERT_TOP(ctx, 0);
+	len = duk__push_this_obj_len_u32(ctx);
+	if (len == 0) {
+		duk_push_int(ctx, 0);
+		duk_put_prop_stridx(ctx, 0, DUK_STRIDX_LENGTH);
+		return 0;
+	}
+	idx = len - 1;
 
-	obj_index = duk_require_normalize_index(ctx, obj_index);
-	duk_push_number(ctx, (double) arr_index);
-	return duk_del_prop(ctx, obj_index);
+	duk_get_prop_index(ctx, 0, (duk_uarridx_t) idx);
+	duk_del_prop_index(ctx, 0, (duk_uarridx_t) idx);
+	duk_push_u32(ctx, idx);
+	duk_put_prop_stridx(ctx, 0, DUK_STRIDX_LENGTH);
+	return 1;
 }
 
-duk_bool_t duk_del_prop_stridx(duk_context *ctx, duk_idx_t obj_index, duk_small_int_t stridx) {
-	duk_hthread *thr = (duk_hthread *) ctx;
-
-	DUK_ASSERT(ctx != NULL);
-	DUK_ASSERT_DISABLE(stridx >= 0);
-	DUK_ASSERT(stridx < DUK_HEAP_NUM_STRINGS);
+DUK_INTERNAL duk_ret_t duk_bi_array_prototype_push(duk_context *ctx) {
+	/* Note: 'this' is not necessarily an Array object.  The push()
+	 * algorithm is supposed to work for other kinds of objects too,
+	 * so the algorithm has e.g. an explicit update for the 'length'
+	 * property which is normally "magical" in arrays.
+	 */
 
-	obj_index = duk_require_normalize_index(ctx, obj_index);
-	duk_push_hstring(ctx, thr->strs[stridx]);
-	return duk_del_prop(ctx, obj_index);
-}
+	duk_uint32_t len;
+	duk_idx_t i, n;
 
-duk_bool_t duk_has_prop(duk_context *ctx, duk_idx_t obj_index) {
-	duk_hthread *thr = (duk_hthread *) ctx;
-	duk_tval *tv_obj;
-	duk_tval *tv_key;
-	duk_bool_t rc;
+	n = duk_get_top(ctx);
+	len = duk__push_this_obj_len_u32(ctx);
 
-	DUK_ASSERT(ctx != NULL);
+	/* [ arg1 ... argN obj length ] */
 
-	/* Note: copying tv_obj and tv_key to locals to shield against a valstack
-	 * resize is not necessary for a property existence check right now.
+	/* Technically Array.prototype.push() can create an Array with length
+	 * longer than 2^32-1, i.e. outside the 32-bit range.  The final length
+	 * is *not* wrapped to 32 bits in the specification.
+	 *
+	 * This implementation tracks length with a uint32 because it's much
+	 * more practical.
+	 *
+	 * See: test-bi-array-push-maxlen.js.
 	 */
 
-	tv_obj = duk_require_tval(ctx, obj_index);
-	tv_key = duk_require_tval(ctx, -1);
-
-	rc = duk_hobject_hasprop(thr, tv_obj, tv_key);
-	DUK_ASSERT(rc == 0 || rc == 1);
+	if (len + (duk_uint32_t) n < len) {
+		DUK_D(DUK_DPRINT("Array.prototype.push() would go beyond 32-bit length, throw"));
+		return DUK_RET_RANGE_ERROR;
+	}
 
-	duk_pop(ctx);  /* remove key */
-	return rc;  /* 1 if property found, 0 otherwise */
-}
+	for (i = 0; i < n; i++) {
+		duk_dup(ctx, i);
+		duk_put_prop_index(ctx, -3, len + i);
+	}
+	len += n;
 
-duk_bool_t duk_has_prop_string(duk_context *ctx, duk_idx_t obj_index, const char *key) {
-	DUK_ASSERT(ctx != NULL);
-	DUK_ASSERT(key != NULL);
+	duk_push_u32(ctx, len);
+	duk_dup_top(ctx);
+	duk_put_prop_stridx(ctx, -4, DUK_STRIDX_LENGTH);
 
-	obj_index = duk_require_normalize_index(ctx, obj_index);
-	duk_push_string(ctx, key);
-	return duk_has_prop(ctx, obj_index);
+	/* [ arg1 ... argN obj length new_length ] */
+	return 1;
 }
 
-duk_bool_t duk_has_prop_index(duk_context *ctx, duk_idx_t obj_index, duk_uarridx_t arr_index) {
-	DUK_ASSERT(ctx != NULL);
+/*
+ *  sort()
+ *
+ *  Currently qsort with random pivot.  This is now really, really slow,
+ *  because there is no fast path for array parts.
+ *
+ *  Signed indices are used because qsort() leaves and degenerate cases
+ *  may use a negative offset.
+ */
 
-	obj_index = duk_require_normalize_index(ctx, obj_index);
-	duk_push_number(ctx, (double) arr_index);
-	return duk_has_prop(ctx, obj_index);
-}
+DUK_LOCAL duk_small_int_t duk__array_sort_compare(duk_context *ctx, duk_int_t idx1, duk_int_t idx2) {
+	duk_bool_t have1, have2;
+	duk_bool_t undef1, undef2;
+	duk_small_int_t ret;
+	duk_idx_t idx_obj = 1;  /* fixed offsets in valstack */
+	duk_idx_t idx_fn = 0;
+	duk_hstring *h1, *h2;
 
-duk_bool_t duk_has_prop_stridx(duk_context *ctx, duk_idx_t obj_index, duk_small_int_t stridx) {
-	duk_hthread *thr = (duk_hthread *) ctx;
+	/* Fast exit if indices are identical.  This is valid for a non-existent property,
+	 * for an undefined value, and almost always for ToString() coerced comparison of
+	 * arbitrary values (corner cases where this is not the case include e.g. a an
+	 * object with varying ToString() coercion).
+	 *
+	 * The specification does not prohibit "caching" of values read from the array, so
+	 * assuming equality for comparing an index with itself falls into the category of
+	 * "caching".
+	 *
+	 * Also, compareFn may be inconsistent, so skipping a call to compareFn here may
+	 * have an effect on the final result.  The specification does not require any
+	 * specific behavior for inconsistent compare functions, so again, this fast path
+	 * is OK.
+	 */
 
-	DUK_ASSERT(ctx != NULL);
-	DUK_ASSERT_DISABLE(stridx >= 0);
-	DUK_ASSERT(stridx < DUK_HEAP_NUM_STRINGS);
+	if (idx1 == idx2) {
+		DUK_DDD(DUK_DDDPRINT("duk__array_sort_compare: idx1=%ld, idx2=%ld -> indices identical, quick exit",
+		                     (long) idx1, (long) idx2));
+		return 0;
+	}
 
-	obj_index = duk_require_normalize_index(ctx, obj_index);
-	duk_push_hstring(ctx, thr->strs[stridx]);
-	return duk_has_prop(ctx, obj_index);
-}
+	have1 = duk_get_prop_index(ctx, idx_obj, (duk_uarridx_t) idx1);
+	have2 = duk_get_prop_index(ctx, idx_obj, (duk_uarridx_t) idx2);
 
-/* Define own property without inheritance looks and such.  This differs from
- * [[DefineOwnProperty]] because special behaviors (like Array 'length') are
- * not invoked by this method.  The caller must be careful to invoke any such
- * behaviors if necessary.
- */
-void duk_def_prop(duk_context *ctx, duk_idx_t obj_index, duk_small_uint_t desc_flags) {
-	duk_hthread *thr = (duk_hthread *) ctx;
-	duk_hobject *obj;
-	duk_hstring *key;
+	DUK_DDD(DUK_DDDPRINT("duk__array_sort_compare: idx1=%ld, idx2=%ld, have1=%ld, have2=%ld, val1=%!T, val2=%!T",
+	                     (long) idx1, (long) idx2, (long) have1, (long) have2,
+	                     (duk_tval *) duk_get_tval(ctx, -2), (duk_tval *) duk_get_tval(ctx, -1)));
 
-	DUK_ASSERT(ctx != NULL);
+	if (have1) {
+		if (have2) {
+			;
+		} else {
+			ret = -1;
+			goto pop_ret;
+		}
+	} else {
+		if (have2) {
+			ret = 1;
+			goto pop_ret;
+		} else {
+			ret = 0;
+			goto pop_ret;
+		}
+	}
 
-	obj = duk_require_hobject(ctx, obj_index);
-	DUK_ASSERT(obj != NULL);
-	key = duk_to_hstring(ctx, -2);
-	DUK_ASSERT(key != NULL);
-	DUK_ASSERT(duk_require_tval(ctx, -1) != NULL);
+	undef1 = duk_is_undefined(ctx, -2);
+	undef2 = duk_is_undefined(ctx, -1);
+	if (undef1) {
+		if (undef2) {
+			ret = 0;
+			goto pop_ret;
+		} else {
+			ret = 1;
+			goto pop_ret;
+		}
+	} else {
+		if (undef2) {
+			ret = -1;
+			goto pop_ret;
+		} else {
+			;
+		}
+	}
 
-	duk_hobject_define_property_internal(thr, obj, key, desc_flags);
+	if (!duk_is_undefined(ctx, idx_fn)) {
+		duk_double_t d;
 
-	duk_pop(ctx);  /* pop key */
-}
+		/* no need to check callable; duk_call() will do that */
+		duk_dup(ctx, idx_fn);    /* -> [ ... x y fn ] */
+		duk_insert(ctx, -3);     /* -> [ ... fn x y ] */
+		duk_call(ctx, 2);        /* -> [ ... res ] */
 
-void duk_def_prop_index(duk_context *ctx, duk_idx_t obj_index, duk_uarridx_t arr_index, duk_small_uint_t desc_flags) {
-	duk_hthread *thr = (duk_hthread *) ctx;
-	duk_hobject *obj;
+		/* The specification is a bit vague what to do if the return
+		 * value is not a number.  Other implementations seem to
+		 * tolerate non-numbers but e.g. V8 won't apparently do a
+		 * ToNumber().
+		 */
 
-	DUK_ASSERT(ctx != NULL);
+		/* XXX: best behavior for real world compatibility? */
 
-	obj = duk_require_hobject(ctx, obj_index);
-	DUK_ASSERT(obj != NULL);
+		d = duk_to_number(ctx, -1);
+		if (d < 0.0) {
+			ret = -1;
+		} else if (d > 0.0) {
+			ret = 1;
+		} else {
+			ret = 0;
+		}
 
-	duk_hobject_define_property_internal_arridx(thr, obj, arr_index, desc_flags);
-	/* value popped by call */
-}
+		duk_pop(ctx);
+		DUK_DDD(DUK_DDDPRINT("-> result %ld (from comparefn, after coercion)", (long) ret));
+		return ret;
+	}
 
-void duk_def_prop_stridx(duk_context *ctx, duk_idx_t obj_index, duk_small_int_t stridx, duk_small_uint_t desc_flags) {
-	duk_hthread *thr = (duk_hthread *) ctx;
-	duk_hobject *obj;
-	duk_hstring *key;
+	/* string compare is the default (a bit oddly) */
 
-	DUK_ASSERT(ctx != NULL);
-	DUK_ASSERT_DISABLE(stridx >= 0);
-	DUK_ASSERT(stridx < DUK_HEAP_NUM_STRINGS);
+	h1 = duk_to_hstring(ctx, -2);
+	h2 = duk_to_hstring(ctx, -1);
+	DUK_ASSERT(h1 != NULL);
+	DUK_ASSERT(h2 != NULL);
 
-	obj = duk_require_hobject(ctx, obj_index);
-	DUK_ASSERT(obj != NULL);
-	key = thr->strs[stridx];
-	DUK_ASSERT(key != NULL);
-	DUK_ASSERT(duk_require_tval(ctx, -1) != NULL);
+	ret = duk_js_string_compare(h1, h2);  /* retval is directly usable */
+	goto pop_ret;
 
-	duk_hobject_define_property_internal(thr, obj, key, desc_flags);
-	/* value popped by call */
+ pop_ret:
+	duk_pop_2(ctx);
+	DUK_DDD(DUK_DDDPRINT("-> result %ld", (long) ret));
+	return ret;
 }
 
-void duk_def_prop_stridx_builtin(duk_context *ctx, duk_idx_t obj_index, duk_small_int_t stridx, duk_small_int_t builtin_idx, duk_small_uint_t desc_flags) {
-	duk_hthread *thr = (duk_hthread *) ctx;
-	duk_hobject *obj;
-	duk_hstring *key;
+DUK_LOCAL void duk__array_sort_swap(duk_context *ctx, duk_int_t l, duk_int_t r) {
+	duk_bool_t have_l, have_r;
+	duk_idx_t idx_obj = 1;  /* fixed offset in valstack */
 
-	DUK_ASSERT(ctx != NULL);
-	DUK_ASSERT_DISABLE(stridx >= 0);
-	DUK_ASSERT(stridx < DUK_HEAP_NUM_STRINGS);
-	DUK_ASSERT_DISABLE(builtin_idx >= 0);
-	DUK_ASSERT(builtin_idx < DUK_NUM_BUILTINS);
+	if (l == r) {
+		return;
+	}
 
-	obj = duk_require_hobject(ctx, obj_index);
-	DUK_ASSERT(obj != NULL);
-	key = thr->strs[stridx];
-	DUK_ASSERT(key != NULL);
+	/* swap elements; deal with non-existent elements correctly */
+	have_l = duk_get_prop_index(ctx, idx_obj, (duk_uarridx_t) l);
+	have_r = duk_get_prop_index(ctx, idx_obj, (duk_uarridx_t) r);
 
-	duk_push_hobject(ctx, thr->builtins[builtin_idx]);
-	duk_hobject_define_property_internal(thr, obj, key, desc_flags);
-	/* value popped by call */
+	if (have_r) {
+		/* right exists, [[Put]] regardless whether or not left exists */
+		duk_put_prop_index(ctx, idx_obj, (duk_uarridx_t) l);
+	} else {
+		duk_del_prop_index(ctx, idx_obj, (duk_uarridx_t) l);
+		duk_pop(ctx);
+	}
+
+	if (have_l) {
+		duk_put_prop_index(ctx, idx_obj, (duk_uarridx_t) r);
+	} else {
+		duk_del_prop_index(ctx, idx_obj, (duk_uarridx_t) r);
+		duk_pop(ctx);
+	}
 }
 
-/* This is a rare property helper; it sets the global thrower (E5 Section 13.2.3)
- * setter/getter into an object property.  This is needed by the 'arguments'
- * object creation code, function instance creation code, and Function.prototype.bind().
- */
+#if defined(DUK_USE_DDDPRINT)
+/* Debug print which visualizes the qsort partitioning process. */
+DUK_LOCAL void duk__debuglog_qsort_state(duk_context *ctx, duk_int_t lo, duk_int_t hi, duk_int_t pivot) {
+	char buf[4096];
+	char *ptr = buf;
+	duk_int_t i, n;
+	n = (duk_int_t) duk_get_length(ctx, 1);
+	if (n > 4000) {
+		n = 4000;
+	}
+	*ptr++ = '[';
+	for (i = 0; i < n; i++) {
+		if (i == pivot) {
+			*ptr++ = '|';
+		} else if (i == lo) {
+			*ptr++ = '<';
+		} else if (i == hi) {
+			*ptr++ = '>';
+		} else if (i >= lo && i <= hi) {
+			*ptr++ = '-';
+		} else {
+			*ptr++ = ' ';
+		}
+	}
+	*ptr++ = ']';
+	*ptr++ = '\0';
 
-void duk_def_prop_stridx_thrower(duk_context *ctx, duk_idx_t obj_index, duk_small_int_t stridx, duk_small_uint_t desc_flags) {
-	duk_hthread *thr = (duk_hthread *) ctx;
-	duk_hobject *obj = duk_require_hobject(ctx, obj_index);
-	duk_hobject *thrower = thr->builtins[DUK_BIDX_TYPE_ERROR_THROWER];
-	duk_hobject_define_accessor_internal(thr, obj, DUK_HTHREAD_GET_STRING(thr, stridx), thrower, thrower, desc_flags);
+	DUK_DDD(DUK_DDDPRINT("%s   (lo=%ld, hi=%ld, pivot=%ld)",
+	                     (const char *) buf, (long) lo, (long) hi, (long) pivot));
 }
+#endif
 
-/*
- *  Object related
- *
- *  Note: seal() and freeze() are accessible through Ecmascript bindings,
- *  and are not exposed through the API.
- */
-
-void duk_compact(duk_context *ctx, duk_idx_t obj_index) {
+DUK_LOCAL void duk__array_qsort(duk_context *ctx, duk_int_t lo, duk_int_t hi) {
 	duk_hthread *thr = (duk_hthread *) ctx;
-	duk_hobject *obj;
+	duk_int_t p, l, r;
 
-	DUK_ASSERT(ctx != NULL);
+	/* The lo/hi indices may be crossed and hi < 0 is possible at entry. */
 
-	obj = duk_get_hobject(ctx, obj_index);
-	if (obj) {
-		/* Note: this may fail, caller should protect the call if necessary */
-		duk_hobject_compact_props(thr, obj);
-	}
-}
+	DUK_DDD(DUK_DDDPRINT("duk__array_qsort: lo=%ld, hi=%ld, obj=%!T",
+	                     (long) lo, (long) hi, (duk_tval *) duk_get_tval(ctx, 1)));
 
-/* FIXME: the duk_hobject_enum.c stack APIs should be reworked */
+	DUK_ASSERT_TOP(ctx, 3);
 
-void duk_enum(duk_context *ctx, duk_idx_t obj_index, duk_uint_t enum_flags) {
-	DUK_ASSERT(ctx != NULL);
+	/* In some cases it may be that lo > hi, or hi < 0; these
+	 * degenerate cases happen e.g. for empty arrays, and in
+	 * recursion leaves.
+	 */
 
-	duk_require_hobject(ctx, obj_index);
-	duk_dup(ctx, obj_index);
-	duk_hobject_enumerator_create(ctx, enum_flags);   /* [target] -> [enum] */
-}
+	/* trivial cases */
+	if (hi - lo < 1) {
+		DUK_DDD(DUK_DDDPRINT("degenerate case, return immediately"));
+		return;
+	}
+	DUK_ASSERT(hi > lo);
+	DUK_ASSERT(hi - lo + 1 >= 2);
 
-duk_bool_t duk_next(duk_context *ctx, duk_idx_t enum_index, duk_bool_t get_value) {
-	DUK_ASSERT(ctx != NULL);
+	/* randomized pivot selection */
+	p = lo + (duk_util_tinyrandom_get_bits(thr, 30) % (hi - lo + 1));  /* rnd in [lo,hi] */
+	DUK_ASSERT(p >= lo && p <= hi);
+	DUK_DDD(DUK_DDDPRINT("lo=%ld, hi=%ld, chose pivot p=%ld",
+	                     (long) lo, (long) hi, (long) p));
 
-	duk_require_hobject(ctx, enum_index);
-	duk_dup(ctx, enum_index);
-	return duk_hobject_enumerator_next(ctx, get_value);
-}
+	/* move pivot out of the way */
+	duk__array_sort_swap(ctx, p, lo);
+	p = lo;
+	DUK_DDD(DUK_DDDPRINT("pivot moved out of the way: %!T", (duk_tval *) duk_get_tval(ctx, 1)));
 
-/*
- *  Helpers for writing multiple properties
- */
+	l = lo + 1;
+	r = hi;
+	for (;;) {
+		/* find elements to swap */
+		for (;;) {
+			DUK_DDD(DUK_DDDPRINT("left scan: l=%ld, r=%ld, p=%ld",
+			                     (long) l, (long) r, (long) p));
+			if (l >= hi) {
+				break;
+			}
+			if (duk__array_sort_compare(ctx, l, p) >= 0) {  /* !(l < p) */
+				break;
+			}
+			l++;
+		}
+		for (;;) {
+			DUK_DDD(DUK_DDDPRINT("right scan: l=%ld, r=%ld, p=%ld",
+			                     (long) l, (long) r, (long) p));
+			if (r <= lo) {
+				break;
+			}
+			if (duk__array_sort_compare(ctx, p, r) >= 0) {  /* !(p < r) */
+				break;
+			}
+			r--;
+		}
+		if (l >= r) {
+			goto done;
+		}
+		DUK_ASSERT(l < r);
 
-void duk_put_function_list(duk_context *ctx, duk_idx_t obj_index, const duk_function_list_entry *funcs) {
-	const duk_function_list_entry *ent = funcs;
+		DUK_DDD(DUK_DDDPRINT("swap %ld and %ld", (long) l, (long) r));
 
-	DUK_ASSERT(ctx != NULL);
+		duk__array_sort_swap(ctx, l, r);
 
-	obj_index = duk_require_normalize_index(ctx, obj_index);
-	if (ent != NULL) {
-		while (ent->key != NULL) {
-			duk_push_c_function(ctx, ent->value, ent->nargs);
-			duk_put_prop_string(ctx, obj_index, ent->key);
-			ent++;
-		}
+		DUK_DDD(DUK_DDDPRINT("after swap: %!T", (duk_tval *) duk_get_tval(ctx, 1)));
+		l++;
+		r--;
 	}
-}
+ done:
+	/* Note that 'l' and 'r' may cross, i.e. r < l */
+	DUK_ASSERT(l >= lo && l <= hi);
+	DUK_ASSERT(r >= lo && r <= hi);
 
-void duk_put_number_list(duk_context *ctx, duk_idx_t obj_index, const duk_number_list_entry *numbers) {
-	const duk_number_list_entry *ent = numbers;
+	/* XXX: there's no explicit recursion bound here now.  For the average
+	 * qsort recursion depth O(log n) that's not really necessary: e.g. for
+	 * 2**32 recursion depth would be about 32 which is OK.  However, qsort
+	 * worst case recursion depth is O(n) which may be a problem.
+	 */
 
-	DUK_ASSERT(ctx != NULL);
+	/* move pivot to its final place */
+	DUK_DDD(DUK_DDDPRINT("before final pivot swap: %!T", (duk_tval *) duk_get_tval(ctx, 1)));
+	duk__array_sort_swap(ctx, lo, r);
 
-	obj_index = duk_require_normalize_index(ctx, obj_index);
-	if (ent != NULL) {
-		while (ent->key != NULL) {
-			duk_push_number(ctx, ent->value);
-			duk_put_prop_string(ctx, obj_index, ent->key);
-			ent++;
-		}
-	}
+#if defined(DUK_USE_DDDPRINT)
+	duk__debuglog_qsort_state(ctx, lo, hi, r);
+#endif
+
+	DUK_DDD(DUK_DDDPRINT("recurse: pivot=%ld, obj=%!T", (long) r, (duk_tval *) duk_get_tval(ctx, 1)));
+	duk__array_qsort(ctx, lo, r - 1);
+	duk__array_qsort(ctx, r + 1, hi);
 }
 
-/*
- *  Shortcut for accessing global object properties
- */
+DUK_INTERNAL duk_ret_t duk_bi_array_prototype_sort(duk_context *ctx) {
+	duk_uint32_t len;
 
-duk_bool_t duk_get_global_string(duk_context *ctx, const char *key) {
-	duk_hthread *thr = (duk_hthread *) ctx;
-	duk_bool_t ret;
+	/* XXX: len >= 0x80000000 won't work below because a signed type
+	 * is needed by qsort.
+	 */
+	len = duk__push_this_obj_len_u32_limited(ctx);
 
-	DUK_ASSERT(ctx != NULL);
-	DUK_ASSERT(thr->builtins[DUK_BIDX_GLOBAL] != NULL);
+	/* stack[0] = compareFn
+	 * stack[1] = ToObject(this)
+	 * stack[2] = ToUint32(length)
+	 */
 
-	/* XXX: direct implementation */
+	if (len > 0) {
+		/* avoid degenerate cases, so that (len - 1) won't underflow */
+		duk__array_qsort(ctx, (duk_int_t) 0, (duk_int_t) (len - 1));
+	}
 
-	duk_push_hobject(ctx, thr->builtins[DUK_BIDX_GLOBAL]);
-	ret = duk_get_prop_string(ctx, -1, key);
-	duk_remove(ctx, -2);
-	return ret;
+	DUK_ASSERT_TOP(ctx, 3);
+	duk_pop(ctx);
+	return 1;  /* return ToObject(this) */
 }
-#line 1 "duk_api_string.c"
+
 /*
- *  String manipulation
+ *  splice()
  */
 
-/* include removed: duk_internal.h */
-
-static void duk__concat_and_join_helper(duk_context *ctx, duk_idx_t count_in, duk_bool_t is_join) {
-	duk_hthread *thr = (duk_hthread *) ctx;
-	duk_uint_t count;
-	duk_uint_t i;
-	duk_size_t idx;
-	duk_size_t len;
-	duk_hstring *h;
-	duk_uint8_t *buf;
+/* XXX: this compiles to over 500 bytes now, even without special handling
+ * for an array part.  Uses signed ints so does not handle full array range correctly.
+ */
 
-	DUK_ASSERT(ctx != NULL);
+/* XXX: can shift() / unshift() use the same helper?
+ *   shift() is (close to?) <--> splice(0, 1)
+ *   unshift is (close to?) <--> splice(0, 0, [items])?
+ */
 
-	if (DUK_UNLIKELY(count_in <= 0)) {
-		if (count_in < 0) {
-			DUK_ERROR(thr, DUK_ERR_API_ERROR, DUK_STR_INVALID_COUNT);
-			return;
-		}
-		DUK_ASSERT(count_in == 0);
-		duk_push_hstring_stridx(ctx, DUK_STRIDX_EMPTY_STRING);
-		return;
-	}
-	count = (duk_uint_t) count_in;
+DUK_INTERNAL duk_ret_t duk_bi_array_prototype_splice(duk_context *ctx) {
+	duk_idx_t nargs;
+	duk_uint32_t len;
+	duk_bool_t have_delcount;
+	duk_int_t item_count;
+	duk_int_t act_start;
+	duk_int_t del_count;
+	duk_int_t i, n;
 
-	if (is_join) {
-		duk_size_t t1, t2, limit;
-		h = duk_to_hstring(ctx, -((duk_idx_t) count) - 1);
-		DUK_ASSERT(h != NULL);
+	DUK_UNREF(have_delcount);
 
-		/* A bit tricky overflow test, see doc/code-issues.txt. */
-		t1 = (duk_size_t) DUK_HSTRING_GET_BYTELEN(h);
-		t2 = (duk_size_t) (count - 1);
-		limit = (duk_size_t) DUK_HSTRING_MAX_BYTELEN;
-		if (DUK_UNLIKELY(t2 != 0 && t1 > limit / t2)) {
-			/* Combined size of separators already overflows */
-			goto error_overflow;
-		}
-		len = (duk_size_t) (t1 * t2);
+	nargs = duk_get_top(ctx);
+	if (nargs < 2) {
+		duk_set_top(ctx, 2);
+		nargs = 2;
+		have_delcount = 0;
 	} else {
-		len = (duk_size_t) 0;
-	}
-
-	for (i = count; i >= 1; i--) {
-		duk_size_t new_len;
-		duk_to_string(ctx, -((duk_idx_t) i));
-		h = duk_require_hstring(ctx, -((duk_idx_t) i));
-		new_len = len + (duk_size_t) DUK_HSTRING_GET_BYTELEN(h);
-
-		/* Impose a string maximum length, need to handle overflow
-		 * correctly.
-		 */
-		if (new_len < len ||  /* wrapped */
-		    new_len > (duk_size_t) DUK_HSTRING_MAX_BYTELEN) {
-			goto error_overflow;
-		}
-		len = new_len;
+		have_delcount = 1;
 	}
 
-	DUK_DDD(DUK_DDDPRINT("join/concat %lu strings, total length %lu bytes",
-	                     (unsigned long) count, (unsigned long) len));
-
-	/* use stack allocated buffer to ensure reachability in errors (e.g. intern error) */
-	buf = (duk_uint8_t *) duk_push_fixed_buffer(ctx, len);
-	DUK_ASSERT(buf != NULL);
-
-	/* [... (sep) str1 str2 ... strN buf] */
+	/* XXX: len >= 0x80000000 won't work below because we need to be
+	 * able to represent -len.
+	 */
+	len = duk__push_this_obj_len_u32_limited(ctx);
 
-	idx = 0;
-	for (i = count; i >= 1; i--) {
-		if (is_join && i != count) {
-			h = duk_require_hstring(ctx, -((duk_idx_t) count) - 2);  /* extra -1 for buffer */
-			DUK_MEMCPY(buf + idx, DUK_HSTRING_GET_DATA(h), DUK_HSTRING_GET_BYTELEN(h));
-			idx += DUK_HSTRING_GET_BYTELEN(h);
-		}
-		h = duk_require_hstring(ctx, -((duk_idx_t) i) - 1);  /* extra -1 for buffer */
-		DUK_MEMCPY(buf + idx, DUK_HSTRING_GET_DATA(h), DUK_HSTRING_GET_BYTELEN(h));
-		idx += DUK_HSTRING_GET_BYTELEN(h);
+	act_start = duk_to_int_clamped(ctx, 0, -((duk_int_t) len), (duk_int_t) len);
+	if (act_start < 0) {
+		act_start = len + act_start;
 	}
+	DUK_ASSERT(act_start >= 0 && act_start <= (duk_int_t) len);
 
-	DUK_ASSERT(idx == len);
-
-	/* [... (sep) str1 str2 ... strN buf] */
-
-	/* get rid of the strings early to minimize memory use before intern */
-
-	if (is_join) {
-		duk_replace(ctx, -((duk_idx_t) count) - 2);  /* overwrite sep */
-		duk_pop_n(ctx, count);
+#ifdef DUK_USE_NONSTD_ARRAY_SPLICE_DELCOUNT
+	if (have_delcount) {
+#endif
+		del_count = duk_to_int_clamped(ctx, 1, 0, len - act_start);
+#ifdef DUK_USE_NONSTD_ARRAY_SPLICE_DELCOUNT
 	} else {
-		duk_replace(ctx, -((duk_idx_t) count) - 1);  /* overwrite str1 */
-		duk_pop_n(ctx, count-1);
+		/* E5.1 standard behavior when deleteCount is not given would be
+		 * to treat it just like if 'undefined' was given, which coerces
+		 * ultimately to 0.  Real world behavior is to splice to the end
+		 * of array, see test-bi-array-proto-splice-no-delcount.js.
+		 */
+		del_count = len - act_start;
 	}
+#endif
 
-	/* [... buf] */
-
-	(void) duk_to_string(ctx, -1);
-
-	/* [... res] */
-	return;
-
- error_overflow:
-	DUK_ERROR(thr, DUK_ERR_RANGE_ERROR, "concat result too long");
-}
+	DUK_ASSERT(nargs >= 2);
+	item_count = (duk_int_t) (nargs - 2);
 
-void duk_concat(duk_context *ctx, duk_idx_t count) {
-	duk__concat_and_join_helper(ctx, count, 0 /*is_join*/);
-}
+	DUK_ASSERT(del_count >= 0 && del_count <= (duk_int_t) len - act_start);
+	DUK_ASSERT(del_count + act_start <= (duk_int_t) len);
 
-void duk_join(duk_context *ctx, duk_idx_t count) {
-	duk__concat_and_join_helper(ctx, count, 1 /*is_join*/);
-}
+	/* For now, restrict result array into 32-bit length range. */
+	if (((duk_double_t) len) - ((duk_double_t) del_count) + ((duk_double_t) item_count) > (duk_double_t) DUK_UINT32_MAX) {
+		DUK_D(DUK_DPRINT("Array.prototype.splice() would go beyond 32-bit length, throw"));
+		return DUK_RET_RANGE_ERROR;
+	}
 
-/* XXX: could map/decode be unified with duk_unicode_support.c code?
- * Case conversion needs also the character surroundings though.
- */
+	duk_push_array(ctx);
 
-void duk_decode_string(duk_context *ctx, duk_idx_t index, duk_decode_char_function callback, void *udata) {
-	duk_hthread *thr = (duk_hthread *) ctx;
-	duk_hstring *h_input;
-	duk_uint8_t *p, *p_start, *p_end;
-	duk_codepoint_t cp;
+	/* stack[0] = start
+	 * stack[1] = deleteCount
+	 * stack[2...nargs-1] = items
+	 * stack[nargs] = ToObject(this)               -3
+	 * stack[nargs+1] = ToUint32(length)           -2
+	 * stack[nargs+2] = result array               -1
+	 */
 
-	h_input = duk_require_hstring(ctx, index);
-	DUK_ASSERT(h_input != NULL);
+	DUK_ASSERT_TOP(ctx, nargs + 3);
 
-	p_start = (duk_uint8_t *) DUK_HSTRING_GET_DATA(h_input);
-	p_end = p_start + DUK_HSTRING_GET_BYTELEN(h_input);
-	p = p_start;
+	/* Step 9: copy elements-to-be-deleted into the result array */
 
-	for (;;) {
-		if (p >= p_end) {
-			break;
+	for (i = 0; i < del_count; i++) {
+		if (duk_get_prop_index(ctx, -3, (duk_uarridx_t) (act_start + i))) {
+			duk_xdef_prop_index_wec(ctx, -2, i);  /* throw flag irrelevant (false in std alg) */
+		} else {
+			duk_pop(ctx);
 		}
-		cp = (int) duk_unicode_decode_xutf8_checked(thr, &p, p_start, p_end);
-		callback(udata, cp);
 	}
-}
+	duk_push_u32(ctx, (duk_uint32_t) del_count);
+	duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_LENGTH, DUK_PROPDESC_FLAGS_W);
 
-void duk_map_string(duk_context *ctx, duk_idx_t index, duk_map_char_function callback, void *udata) {
-	duk_hthread *thr = (duk_hthread *) ctx;
-	duk_hstring *h_input;
-	duk_hbuffer_dynamic *h_buf;
-	duk_uint8_t *p, *p_start, *p_end;
-	duk_codepoint_t cp;
+	/* Steps 12 and 13: reorganize elements to make room for itemCount elements */
 
-	index = duk_normalize_index(ctx, index);
+	if (item_count < del_count) {
+		/*    [ A B C D E F G H ]    rel_index = 2, del_count 3, item count 1
+		 * -> [ A B F G H ]          (conceptual intermediate step)
+		 * -> [ A B . F G H ]        (placeholder marked)
+		 *    [ A B C F G H ]        (actual result at this point, C will be replaced)
+		 */
 
-	h_input = duk_require_hstring(ctx, index);
-	DUK_ASSERT(h_input != NULL);
+		DUK_ASSERT_TOP(ctx, nargs + 3);
 
-	/* XXX: should init with a spare of at least h_input->blen? */
-	duk_push_dynamic_buffer(ctx, 0);
-	h_buf = (duk_hbuffer_dynamic *) duk_get_hbuffer(ctx, -1);
-	DUK_ASSERT(h_buf != NULL);
-	DUK_ASSERT(DUK_HBUFFER_HAS_DYNAMIC(h_buf));
+		n = len - del_count;
+		for (i = act_start; i < n; i++) {
+			if (duk_get_prop_index(ctx, -3, (duk_uarridx_t) (i + del_count))) {
+				duk_put_prop_index(ctx, -4, (duk_uarridx_t) (i + item_count));
+			} else {
+				duk_pop(ctx);
+				duk_del_prop_index(ctx, -3, (duk_uarridx_t) (i + item_count));
+			}
+		}
 
-	p_start = (duk_uint8_t *) DUK_HSTRING_GET_DATA(h_input);
-	p_end = p_start + DUK_HSTRING_GET_BYTELEN(h_input);
-	p = p_start;
+		DUK_ASSERT_TOP(ctx, nargs + 3);
 
-	for (;;) {
-		if (p >= p_end) {
-			break;
+		/* loop iterator init and limit changed from standard algorithm */
+		n = len - del_count + item_count;
+		for (i = len - 1; i >= n; i--) {
+			duk_del_prop_index(ctx, -3, (duk_uarridx_t) i);
 		}
-		cp = (int) duk_unicode_decode_xutf8_checked(thr, &p, p_start, p_end);
-		cp = callback(udata, cp);
-		duk_hbuffer_append_xutf8(thr, h_buf, cp);
-	}
-
-	duk_to_string(ctx, -1);  /* invalidates h_buf pointer */
-	duk_replace(ctx, index);
-}
 
-void duk_substring(duk_context *ctx, duk_idx_t index, duk_size_t start_offset, duk_size_t end_offset) {
-	duk_hthread *thr = (duk_hthread *) ctx;
-	duk_hstring *h;
-	duk_hstring *res;
-	duk_size_t start_byte_offset;
-	duk_size_t end_byte_offset;
+		DUK_ASSERT_TOP(ctx, nargs + 3);
+	} else if (item_count > del_count) {
+		/*    [ A B C D E F G H ]    rel_index = 2, del_count 3, item count 4
+		 * -> [ A B F G H ]          (conceptual intermediate step)
+		 * -> [ A B . . . . F G H ]  (placeholder marked)
+		 *    [ A B C D E F F G H ]  (actual result at this point)
+		 */
 
-	DUK_ASSERT(ctx != NULL);
+		DUK_ASSERT_TOP(ctx, nargs + 3);
 
-	index = duk_require_normalize_index(ctx, index);
-	h = duk_require_hstring(ctx, index);
-	DUK_ASSERT(h != NULL);
+		/* loop iterator init and limit changed from standard algorithm */
+		for (i = len - del_count - 1; i >= act_start; i--) {
+			if (duk_get_prop_index(ctx, -3, (duk_uarridx_t) (i + del_count))) {
+				duk_put_prop_index(ctx, -4, (duk_uarridx_t) (i + item_count));
+			} else {
+				duk_pop(ctx);
+				duk_del_prop_index(ctx, -3, (duk_uarridx_t) (i + item_count));
+			}
+		}
 
-	if (end_offset >= DUK_HSTRING_GET_CHARLEN(h)) {
-		end_offset = DUK_HSTRING_GET_CHARLEN(h);
-	}
-	if (start_offset > end_offset) {
-		start_offset = end_offset;
+		DUK_ASSERT_TOP(ctx, nargs + 3);
+	} else {
+		/*    [ A B C D E F G H ]    rel_index = 2, del_count 3, item count 3
+		 * -> [ A B F G H ]          (conceptual intermediate step)
+		 * -> [ A B . . . F G H ]    (placeholder marked)
+		 *    [ A B C D E F G H ]    (actual result at this point)
+		 */
 	}
+	DUK_ASSERT_TOP(ctx, nargs + 3);
 
-	DUK_ASSERT_DISABLE(start_offset >= 0);
-	DUK_ASSERT(start_offset <= end_offset && start_offset <= DUK_HSTRING_GET_CHARLEN(h));
-	DUK_ASSERT_DISABLE(end_offset >= 0);
-	DUK_ASSERT(end_offset >= start_offset && end_offset <= DUK_HSTRING_GET_CHARLEN(h));
-
-	/* guaranteed by string limits */
-	DUK_ASSERT(start_offset <= DUK_UINT32_MAX);
-	DUK_ASSERT(end_offset <= DUK_UINT32_MAX);
+	/* Step 15: insert itemCount elements into the hole made above */
 
-	start_byte_offset = (duk_size_t) duk_heap_strcache_offset_char2byte(thr, h, (duk_uint_fast32_t) start_offset);
-	end_byte_offset = (duk_size_t) duk_heap_strcache_offset_char2byte(thr, h, (duk_uint_fast32_t) end_offset);
+	for (i = 0; i < item_count; i++) {
+		duk_dup(ctx, i + 2);  /* args start at index 2 */
+		duk_put_prop_index(ctx, -4, (duk_uarridx_t) (act_start + i));
+	}
 
-	DUK_ASSERT(end_byte_offset >= start_byte_offset);
-	DUK_ASSERT(end_byte_offset - start_byte_offset <= DUK_UINT32_MAX);  /* guaranteed by string limits */
+	/* Step 16: update length; note that the final length may be above 32 bit range
+	 * (but we checked above that this isn't the case here)
+	 */
 
-	/* no size check is necessary */
-	res = duk_heap_string_intern_checked(thr,
-	                                     DUK_HSTRING_GET_DATA(h) + start_byte_offset,
-	                                     (duk_uint32_t) (end_byte_offset - start_byte_offset));
+	duk_push_u32(ctx, len - del_count + item_count);
+	duk_put_prop_stridx(ctx, -4, DUK_STRIDX_LENGTH);
 
-	duk_push_hstring(ctx, res);
-	duk_replace(ctx, index);
+	/* result array is already at the top of stack */
+	DUK_ASSERT_TOP(ctx, nargs + 3);
+	return 1;
 }
 
-/* XXX: this is quite clunky.  Add Unicode helpers to scan backwards and
- * forwards with a callback to process codepoints?
+/*
+ *  reverse()
  */
-void duk_trim(duk_context *ctx, duk_idx_t index) {
-	duk_hthread *thr = (duk_hthread *) ctx;
-	duk_hstring *h;
-	duk_uint8_t *p, *p_start, *p_end, *p_tmp1, *p_tmp2;  /* pointers for scanning */
-	duk_uint8_t *q_start, *q_end;  /* start (incl) and end (excl) of trimmed part */
-	duk_codepoint_t cp;
-
-	index = duk_require_normalize_index(ctx, index);
-	h = duk_require_hstring(ctx, index);
-	DUK_ASSERT(h != NULL);
-
-	p_start = DUK_HSTRING_GET_DATA(h);
-	p_end = p_start + DUK_HSTRING_GET_BYTELEN(h);
-
-	p = p_start;
-	while (p < p_end) {
-		p_tmp1 = p;
-		cp = (duk_codepoint_t) duk_unicode_decode_xutf8_checked(thr, &p_tmp1, p_start, p_end);
-		if (!(duk_unicode_is_whitespace(cp) || duk_unicode_is_line_terminator(cp))) {
-			break;
-		}
-		p = p_tmp1;
-	}
-	q_start = p;
-	if (p == p_end) {
-		/* entire string is whitespace */
-		q_end = p;
-		goto scan_done;
-	}
 
-	p = p_end;
-	while (p > p_start) {
-		p_tmp1 = p;
-		while (p > p_start) {
-			p--;
-			if (((*p) & 0xc0) != 0x80) {
-				break;
-			}
-		}
-		p_tmp2 = p;
+DUK_INTERNAL duk_ret_t duk_bi_array_prototype_reverse(duk_context *ctx) {
+	duk_uint32_t len;
+	duk_uint32_t middle;
+	duk_uint32_t lower, upper;
+	duk_bool_t have_lower, have_upper;
 
-		cp = (duk_codepoint_t) duk_unicode_decode_xutf8_checked(thr, &p_tmp2, p_start, p_end);
-		if (!(duk_unicode_is_whitespace(cp) || duk_unicode_is_line_terminator(cp))) {
-			p = p_tmp1;
-			break;
-		}
-	}
-	q_end = p;
+	len = duk__push_this_obj_len_u32(ctx);
+	middle = len / 2;
 
- scan_done:
-	/* This may happen when forward and backward scanning disagree
-	 * (possible for non-extended-UTF-8 strings).
+	/* If len <= 1, middle will be 0 and for-loop bails out
+	 * immediately (0 < 0 -> false).
 	 */
-	if (q_end < q_start) {
-		q_end = q_start;
-	}
 
-	DUK_ASSERT(q_start >= p_start && q_start <= p_end);
-	DUK_ASSERT(q_end >= p_start && q_end <= p_end);
-	DUK_ASSERT(q_end >= q_start);
+	for (lower = 0; lower < middle; lower++) {
+		DUK_ASSERT(len >= 2);
+		DUK_ASSERT_TOP(ctx, 2);
 
-	DUK_DDD(DUK_DDDPRINT("trim: p_start=%p, p_end=%p, q_start=%p, q_end=%p",
-	                     (void *) p_start, (void *) p_end, (void *) q_start, (void *) q_end));
+		DUK_ASSERT(len >= lower + 1);
+		upper = len - lower - 1;
 
-	if (q_start == p_start && q_end == p_end) {
-		DUK_DDD(DUK_DDDPRINT("nothing was trimmed: avoid interning (hashing etc)"));
-		return;
-	}
+		have_lower = duk_get_prop_index(ctx, -2, (duk_uarridx_t) lower);
+		have_upper = duk_get_prop_index(ctx, -3, (duk_uarridx_t) upper);
 
-	duk_push_lstring(ctx, (const char *) q_start, (duk_size_t) (q_end - q_start));
-	duk_replace(ctx, index);
-}
+		/* [ ToObject(this) ToUint32(length) lowerValue upperValue ] */
 
-duk_codepoint_t duk_char_code_at(duk_context *ctx, duk_idx_t index, duk_size_t char_offset) {
-	duk_hthread *thr = (duk_hthread *) ctx;
-	duk_hstring *h;
-	duk_ucodepoint_t cp;
+		if (have_upper) {
+			duk_put_prop_index(ctx, -4, (duk_uarridx_t) lower);
+		} else {
+			duk_del_prop_index(ctx, -4, (duk_uarridx_t) lower);
+			duk_pop(ctx);
+		}
 
-	h = duk_require_hstring(ctx, index);
-	DUK_ASSERT(h != NULL);
+		if (have_lower) {
+			duk_put_prop_index(ctx, -3, (duk_uarridx_t) upper);
+		} else {
+			duk_del_prop_index(ctx, -3, (duk_uarridx_t) upper);
+			duk_pop(ctx);
+		}
 
-	DUK_ASSERT_DISABLE(char_offset >= 0);  /* always true, arg is unsigned */
-	if (char_offset >= DUK_HSTRING_GET_CHARLEN(h)) {
-		return 0;
+		DUK_ASSERT_TOP(ctx, 2);
 	}
 
-	DUK_ASSERT(char_offset <= DUK_UINT_MAX);  /* guaranteed by string limits */
-	cp = duk_hstring_char_code_at_raw(thr, h, (duk_uint_t) char_offset);
-	return (duk_codepoint_t) cp;
+	DUK_ASSERT_TOP(ctx, 2);
+	duk_pop(ctx);  /* -> [ ToObject(this) ] */
+	return 1;
 }
-#line 1 "duk_api_thread.c"
-/*
- *  Thread handling
- */
 
-/* include removed: duk_internal.h */
-
-/* FIXME */
-#line 1 "duk_api_var.c"
 /*
- *  Variable access
+ *  slice()
  */
 
-/* include removed: duk_internal.h */
-
-void duk_get_var(duk_context *ctx) {
-	duk_hthread *thr = (duk_hthread *) ctx;
-	duk_activation *act;
-	duk_hstring *h_varname;
-	duk_small_int_t throw_flag = 1;  /* always throw ReferenceError for unresolvable */
+DUK_INTERNAL duk_ret_t duk_bi_array_prototype_slice(duk_context *ctx) {
+	duk_uint32_t len;
+	duk_int_t start, end;
+	duk_int_t i;
+	duk_uarridx_t idx;
+	duk_uint32_t res_length = 0;
 
-	DUK_ASSERT(ctx != NULL);
+	/* XXX: len >= 0x80000000 won't work below because we need to be
+	 * able to represent -len.
+	 */
+	len = duk__push_this_obj_len_u32_limited(ctx);
+	duk_push_array(ctx);
 
-	h_varname = duk_require_hstring(ctx, -1);  /* XXX: tostring? */
-	DUK_ASSERT(h_varname != NULL);
+	/* stack[0] = start
+	 * stack[1] = end
+	 * stack[2] = ToObject(this)
+	 * stack[3] = ToUint32(length)
+	 * stack[4] = result array
+	 */
 
-	act = duk_hthread_get_current_activation(thr);
-	if (act) {
-		(void) duk_js_getvar_activation(thr, act, h_varname, throw_flag);  /* -> [ ... varname val this ] */
+	start = duk_to_int_clamped(ctx, 0, -((duk_int_t) len), (duk_int_t) len);
+	if (start < 0) {
+		start = len + start;
+	}
+	/* XXX: could duk_is_undefined() provide defaulting undefined to 'len'
+	 * (the upper limit)?
+	 */
+	if (duk_is_undefined(ctx, 1)) {
+		end = len;
 	} else {
-		/* Outside any activation -> look up from global. */
-		DUK_ASSERT(thr->builtins[DUK_BIDX_GLOBAL_ENV] != NULL);
-		(void) duk_js_getvar_envrec(thr, thr->builtins[DUK_BIDX_GLOBAL_ENV], h_varname, throw_flag);
+		end = duk_to_int_clamped(ctx, 1, -((duk_int_t) len), (duk_int_t) len);
+		if (end < 0) {
+			end = len + end;
+		}
 	}
+	DUK_ASSERT(start >= 0 && (duk_uint32_t) start <= len);
+	DUK_ASSERT(end >= 0 && (duk_uint32_t) end <= len);
 
-	/* [ ... varname val this ]  (because throw_flag == 1, always resolved) */
-
-	duk_pop(ctx);
-	duk_remove(ctx, -2);
+	idx = 0;
+	for (i = start; i < end; i++) {
+		DUK_ASSERT_TOP(ctx, 5);
+		if (duk_get_prop_index(ctx, 2, (duk_uarridx_t) i)) {
+			duk_xdef_prop_index_wec(ctx, 4, idx);
+			res_length = idx + 1;
+		} else {
+			duk_pop(ctx);
+		}
+		idx++;
+		DUK_ASSERT_TOP(ctx, 5);
+	}
 
-	/* [ ... val ] */
+	duk_push_u32(ctx, res_length);
+	duk_xdef_prop_stridx(ctx, 4, DUK_STRIDX_LENGTH, DUK_PROPDESC_FLAGS_W);
 
-	/* Return value would be pointless: because throw_flag==1, we always
-	 * throw if the identifier doesn't resolve.
-	 */
-	return;
+	DUK_ASSERT_TOP(ctx, 5);
+	return 1;
 }
 
-void duk_put_var(duk_context *ctx) {
-	duk_hthread *thr = (duk_hthread *) ctx;
-	duk_activation *act;
-	duk_hstring *h_varname;
-	duk_tval *tv_val;
-	duk_small_int_t throw_flag;
-
-	DUK_ASSERT(ctx != NULL);
-
-	h_varname = duk_require_hstring(ctx, -2);  /* XXX: tostring? */
-	DUK_ASSERT(h_varname != NULL);
-
-	tv_val = duk_require_tval(ctx, -1);
+/*
+ *  shift()
+ */
 
-	throw_flag = duk_is_strict_call(ctx);
+DUK_INTERNAL duk_ret_t duk_bi_array_prototype_shift(duk_context *ctx) {
+	duk_uint32_t len;
+	duk_uint32_t i;
 
-	act = duk_hthread_get_current_activation(thr);
-	if (act) {
-		duk_js_putvar_activation(thr, act, h_varname, tv_val, throw_flag);  /* -> [ ... varname val this ] */
-	} else {
-		/* Outside any activation -> put to global. */
-		DUK_ASSERT(thr->builtins[DUK_BIDX_GLOBAL_ENV] != NULL);
-		duk_js_putvar_envrec(thr, thr->builtins[DUK_BIDX_GLOBAL_ENV], h_varname, tv_val, throw_flag);
+	len = duk__push_this_obj_len_u32(ctx);
+	if (len == 0) {
+		duk_push_int(ctx, 0);
+		duk_put_prop_stridx(ctx, 0, DUK_STRIDX_LENGTH);
+		return 0;
 	}
 
-	/* [ ... varname val ] */
-
-	duk_pop_2(ctx);
+	duk_get_prop_index(ctx, 0, 0);
 
-	/* [ ... ] */
+	/* stack[0] = object (this)
+	 * stack[1] = ToUint32(length)
+	 * stack[2] = elem at index 0 (retval)
+	 */
 
-	return;
-}
+	for (i = 1; i < len; i++) {
+		DUK_ASSERT_TOP(ctx, 3);
+		if (duk_get_prop_index(ctx, 0, (duk_uarridx_t) i)) {
+			/* fromPresent = true */
+			duk_put_prop_index(ctx, 0, (duk_uarridx_t) (i - 1));
+		} else {
+			/* fromPresent = false */
+			duk_del_prop_index(ctx, 0, (duk_uarridx_t) (i - 1));
+			duk_pop(ctx);
+		}
+	}
+	duk_del_prop_index(ctx, 0, (duk_uarridx_t) (len - 1));
 
-duk_bool_t duk_del_var(duk_context *ctx) {
-	DUK_ERROR((duk_hthread *) ctx, DUK_ERR_UNIMPLEMENTED_ERROR, "unimplemented");
-	return 0;
-}
+	duk_push_u32(ctx, (duk_uint32_t) (len - 1));
+	duk_put_prop_stridx(ctx, 0, DUK_STRIDX_LENGTH);
 
-duk_bool_t duk_has_var(duk_context *ctx) {
-	DUK_ERROR((duk_hthread *) ctx, DUK_ERR_UNIMPLEMENTED_ERROR, "unimplemented");
-	return 0;
+	DUK_ASSERT_TOP(ctx, 3);
+	return 1;
 }
 
-#line 1 "duk_bi_array.c"
 /*
- *  Array built-ins
- *
- *  Note that most Array built-ins are intentionally generic and work even
- *  when the 'this' binding is not an Array instance.  To ensure this,
- *  Array algorithms do not assume "magical" Array behavior for the "length"
- *  property, for instance.
- *
- *  XXX: the "Throw" flag should be set for (almost?) all [[Put]] and
- *  [[Delete]] operations, but it's currently false throughout.  Go through
- *  all put/delete cases and check throw flag use.  Need a new API primitive
- *  which allows throws flag to be specified.
- *
- *  XXX: array lengths above 2G won't work reliably.  There are many places
- *  where one needs a full signed 32-bit range ([-0xffffffff, 0xffffffff],
- *  i.e. -33- bits).  Further, some valid array length values may be above
- *  2**32-1, and this is not always correctly handled (duk_uint32_t is not enough).
- *
- *  On using "put" vs. "def" prop
- *  =============================
- *
- *  Code below must be careful to use the appropriate primitive as it matters
- *  for compliance.  When using "put" there may be inherited properties in
- *  Array.prototype which cause side effects when values are written.  When
- *  using "define" there are no such side effects, and many test262 test cases
- *  check for this (for real world code, such side effects are very rare).
- *  Both "put" and "define" are used in the E5.1 specification; as a rule,
- *  "put" is used when modifying an existing array (or a non-array 'this'
- *  binding) and "define" for setting values into a fresh result array.
- *
- *  Also note that Array instance 'length' should be writable, but not
- *  enumerable and definitely not configurable: even Duktape code internally
- *  assumes that an Array instance will always have a 'length' property.
- *  Preventing deletion of the property is critical.
- */
-
-/* include removed: duk_internal.h */
-
-/* Perform an intermediate join when this many elements have been pushed
- * on the value stack.
+ *  unshift()
  */
-#define  DUK__ARRAY_MID_JOIN_LIMIT  4096
 
-/* Shared entry code for many Array built-ins.  Note that length is left
- * on stack (it could be popped, but that's not necessary).
- */
-static duk_uint32_t duk__push_this_obj_len_u32(duk_context *ctx) {
+DUK_INTERNAL duk_ret_t duk_bi_array_prototype_unshift(duk_context *ctx) {
+	duk_idx_t nargs;
 	duk_uint32_t len;
+	duk_uint32_t i;
 
-	(void) duk_push_this_coercible_to_object(ctx);
-	duk_get_prop_stridx(ctx, -1, DUK_STRIDX_LENGTH);
-	len = duk_to_uint32(ctx, -1);
+	nargs = duk_get_top(ctx);
+	len = duk__push_this_obj_len_u32(ctx);
 
-	/* -> [ ... ToObject(this) ToUint32(length) ] */
-	return len;
-}
+	/* stack[0...nargs-1] = unshift args (vararg)
+	 * stack[nargs] = ToObject(this)
+	 * stack[nargs+1] = ToUint32(length)
+	 */
 
-static duk_uint32_t duk__push_this_obj_len_u32_limited(duk_context *ctx) {
-	/* Range limited to [0, 0x7fffffff] range, i.e. range that can be
-	 * represented with duk_int32_t.  Use this when the method doesn't
-	 * handle the full 32-bit unsigned range correctly.
+	DUK_ASSERT_TOP(ctx, nargs + 2);
+
+	/* Note: unshift() may operate on indices above unsigned 32-bit range
+	 * and the final length may be >= 2**32.  However, we restrict the
+	 * final result to 32-bit range for practicality.
 	 */
-	duk_uint32_t ret = duk__push_this_obj_len_u32(ctx);
-	if (DUK_UNLIKELY(ret >= 0x80000000UL)) {
-		DUK_ERROR((duk_hthread *) ctx, DUK_ERR_INTERNAL_ERROR, "array length above 2G");
+
+	if (len + (duk_uint32_t) nargs < len) {
+		DUK_D(DUK_DPRINT("Array.prototype.unshift() would go beyond 32-bit length, throw"));
+		return DUK_RET_RANGE_ERROR;
 	}
-	return ret;
+
+	i = len;
+	while (i > 0) {
+		DUK_ASSERT_TOP(ctx, nargs + 2);
+		i--;
+		/* k+argCount-1; note that may be above 32-bit range */
+
+		if (duk_get_prop_index(ctx, -2, (duk_uarridx_t) i)) {
+			/* fromPresent = true */
+			/* [ ... ToObject(this) ToUint32(length) val ] */
+			duk_put_prop_index(ctx, -3, (duk_uarridx_t) (i + nargs));  /* -> [ ... ToObject(this) ToUint32(length) ] */
+		} else {
+			/* fromPresent = false */
+			/* [ ... ToObject(this) ToUint32(length) val ] */
+			duk_pop(ctx);
+			duk_del_prop_index(ctx, -2, (duk_uarridx_t) (i + nargs));  /* -> [ ... ToObject(this) ToUint32(length) ] */
+		}
+		DUK_ASSERT_TOP(ctx, nargs + 2);
+	}
+
+	for (i = 0; i < (duk_uint32_t) nargs; i++) {
+		DUK_ASSERT_TOP(ctx, nargs + 2);
+		duk_dup(ctx, i);  /* -> [ ... ToObject(this) ToUint32(length) arg[i] ] */
+		duk_put_prop_index(ctx, -3, (duk_uarridx_t) i);
+		DUK_ASSERT_TOP(ctx, nargs + 2);
+	}
+
+	DUK_ASSERT_TOP(ctx, nargs + 2);
+	duk_push_u32(ctx, len + nargs);
+	duk_dup_top(ctx);  /* -> [ ... ToObject(this) ToUint32(length) final_len final_len ] */
+	duk_put_prop_stridx(ctx, -4, DUK_STRIDX_LENGTH);
+	return 1;
 }
 
 /*
- *  Constructor
+ *  indexOf(), lastIndexOf()
  */
 
-duk_ret_t duk_bi_array_constructor(duk_context *ctx) {
+DUK_INTERNAL duk_ret_t duk_bi_array_prototype_indexof_shared(duk_context *ctx) {
 	duk_idx_t nargs;
-	duk_double_t d;
-	duk_uint32_t len;
-	duk_idx_t i;
+	duk_int_t i, len;
+	duk_int_t from_index;
+	duk_small_int_t idx_step = duk_get_current_magic(ctx);  /* idx_step is +1 for indexOf, -1 for lastIndexOf */
+
+	/* lastIndexOf() needs to be a vararg function because we must distinguish
+	 * between an undefined fromIndex and a "not given" fromIndex; indexOf() is
+	 * made vararg for symmetry although it doesn't strictly need to be.
+	 */
 
 	nargs = duk_get_top(ctx);
-	duk_push_array(ctx);
+	duk_set_top(ctx, 2);
 
-	if (nargs == 1 && duk_is_number(ctx, 0)) {
-		/* XXX: expensive check (also shared elsewhere - so add a shared internal API call?) */
-		d = duk_get_number(ctx, 0);
-		len = duk_to_uint32(ctx, 0);
-		if (((duk_double_t) len) != d) {
-			return DUK_RET_RANGE_ERROR;
-		}
+	/* XXX: must be able to represent -len */
+	len = (duk_int_t) duk__push_this_obj_len_u32_limited(ctx);
+	if (len == 0) {
+		goto not_found;
+	}
 
-		/* XXX: if 'len' is low, may want to ensure array part is kept:
-		 * the caller is likely to want a dense array.
+	/* Index clamping is a bit tricky, we must ensure that we'll only iterate
+	 * through elements that exist and that the specific requirements from E5.1
+	 * Sections 15.4.4.14 and 15.4.4.15 are fulfilled; especially:
+	 *
+	 *   - indexOf: clamp to [-len,len], negative handling -> [0,len],
+	 *     if clamped result is len, for-loop bails out immediately
+	 *
+	 *   - lastIndexOf: clamp to [-len-1, len-1], negative handling -> [-1, len-1],
+	 *     if clamped result is -1, for-loop bails out immediately
+	 *
+	 * If fromIndex is not given, ToInteger(undefined) = 0, which is correct
+	 * for indexOf() but incorrect for lastIndexOf().  Hence special handling,
+	 * and why lastIndexOf() needs to be a vararg function.
+	 */
+
+	if (nargs >= 2) {
+		/* indexOf: clamp fromIndex to [-len, len]
+		 * (if fromIndex == len, for-loop terminates directly)
+		 *
+		 * lastIndexOf: clamp fromIndex to [-len - 1, len - 1]
+		 * (if clamped to -len-1 -> fromIndex becomes -1, terminates for-loop directly)
 		 */
-		duk_dup(ctx, 0);
-		duk_def_prop_stridx(ctx, -2, DUK_STRIDX_LENGTH, DUK_PROPDESC_FLAGS_W);  /* [ ToUint32(len) array ToUint32(len) ] -> [ ToUint32(len) array ] */
-		return 1;
+		from_index = duk_to_int_clamped(ctx,
+		                                1,
+		                                (idx_step > 0 ? -len : -len - 1),
+		                                (idx_step > 0 ? len : len - 1));
+		if (from_index < 0) {
+			/* for lastIndexOf, result may be -1 (mark immediate termination) */
+			from_index = len + from_index;
+		}
+	} else {
+		/* for indexOf, ToInteger(undefined) would be 0, i.e. correct, but
+		 * handle both indexOf and lastIndexOf specially here.
+		 */
+		if (idx_step > 0) {
+			from_index = 0;
+		} else {
+			from_index = len - 1;
+		}
 	}
 
-	/* XXX: optimize by creating array into correct size directly, and
-	 * operating on the array part directly; values can be memcpy()'d from
-	 * value stack directly as long as refcounts are increased.
+	/* stack[0] = searchElement
+	 * stack[1] = fromIndex
+	 * stack[2] = object
+	 * stack[3] = length (not needed, but not popped above)
 	 */
-	for (i = 0; i < nargs; i++) {
-		duk_dup(ctx, i);
-		duk_def_prop_index_wec(ctx, -2, (duk_uarridx_t) i);
+
+	for (i = from_index; i >= 0 && i < len; i += idx_step) {
+		DUK_ASSERT_TOP(ctx, 4);
+
+		if (duk_get_prop_index(ctx, 2, (duk_uarridx_t) i)) {
+			DUK_ASSERT_TOP(ctx, 5);
+			if (duk_strict_equals(ctx, 0, 4)) {
+				duk_push_int(ctx, i);
+				return 1;
+			}
+		}
+
+		duk_pop(ctx);
 	}
 
-	duk_push_u32(ctx, (duk_uint32_t) nargs);
-	duk_def_prop_stridx(ctx, -2, DUK_STRIDX_LENGTH, DUK_PROPDESC_FLAGS_W);
+ not_found:
+	duk_push_int(ctx, -1);
 	return 1;
 }
 
 /*
- *  isArray()
+ *  every(), some(), forEach(), map(), filter()
  */
 
-duk_ret_t duk_bi_array_constructor_is_array(duk_context *ctx) {
-	duk_hobject *h;
-
-	h = duk_get_hobject_with_class(ctx, 0, DUK_HOBJECT_CLASS_ARRAY);
-	duk_push_boolean(ctx, (h != NULL));
-	return 1;
-}
+#define DUK__ITER_EVERY    0
+#define DUK__ITER_SOME     1
+#define DUK__ITER_FOREACH  2
+#define DUK__ITER_MAP      3
+#define DUK__ITER_FILTER   4
 
-/*
- *  toString()
+/* XXX: This helper is a bit awkward because the handling for the different iteration
+ * callers is quite different.  This now compiles to a bit less than 500 bytes, so with
+ * 5 callers the net result is about 100 bytes / caller.
  */
 
-duk_ret_t duk_bi_array_prototype_to_string(duk_context *ctx) {
-	(void) duk_push_this_coercible_to_object(ctx);
-	duk_get_prop_stridx(ctx, -1, DUK_STRIDX_JOIN);
+DUK_INTERNAL duk_ret_t duk_bi_array_prototype_iter_shared(duk_context *ctx) {
+	duk_uint32_t len;
+	duk_uint32_t i;
+	duk_uarridx_t k;
+	duk_bool_t bval;
+	duk_small_int_t iter_type = duk_get_current_magic(ctx);
+	duk_uint32_t res_length = 0;
 
-	/* [ ... this func ] */
-	if (!duk_is_callable(ctx, -1)) {
-		/* Fall back to the initial (original) Object.toString().  We don't
-		 * currently have pointers to the built-in functions, only the top
-		 * level global objects (like "Array") so this is now done in a bit
-		 * of a hacky manner.  It would be cleaner to push the (original)
-		 * function and use duk_call_method().
-		 */
+	/* each call this helper serves has nargs==2 */
+	DUK_ASSERT_TOP(ctx, 2);
 
-		/* XXX: 'this' will be ToObject() coerced twice, which is incorrect
-		 * but should have no visible side effects.
-		 */
-		DUK_DDD(DUK_DDDPRINT("this.join is not callable, fall back to (original) Object.toString"));
-		duk_set_top(ctx, 0);
-		return duk_bi_object_prototype_to_string(ctx);  /* has access to 'this' binding */
+	len = duk__push_this_obj_len_u32(ctx);
+	duk_require_callable(ctx, 0);
+	/* if thisArg not supplied, behave as if undefined was supplied */
+
+	if (iter_type == DUK__ITER_MAP || iter_type == DUK__ITER_FILTER) {
+		duk_push_array(ctx);
+	} else {
+		duk_push_undefined(ctx);
 	}
 
-	/* [ ... this func ] */
+	/* stack[0] = callback
+	 * stack[1] = thisArg
+	 * stack[2] = object
+	 * stack[3] = ToUint32(length)  (unused, but avoid unnecessary pop)
+	 * stack[4] = result array (or undefined)
+	 */
 
-	duk_insert(ctx, -2);
+	k = 0;  /* result index for filter() */
+	for (i = 0; i < len; i++) {
+		DUK_ASSERT_TOP(ctx, 5);
 
-	/* [ ... func this ] */
+		if (!duk_get_prop_index(ctx, 2, (duk_uarridx_t) i)) {
+#if defined(DUK_USE_NONSTD_ARRAY_MAP_TRAILER)
+			/* Real world behavior for map(): trailing non-existent
+			 * elements don't invoke the user callback, but are still
+			 * counted towards result 'length'.
+			 */
+			if (iter_type == DUK__ITER_MAP) {
+				res_length = i + 1;
+			}
+#else
+			/* Standard behavior for map(): trailing non-existent
+			 * elements don't invoke the user callback and are not
+			 * counted towards result 'length'.
+			 */
+#endif
+			duk_pop(ctx);
+			continue;
+		}
 
-	DUK_DDD(DUK_DDDPRINT("calling: func=%!iT, this=%!iT",
-	                     (duk_tval *) duk_get_tval(ctx, -2),
-	                     (duk_tval *) duk_get_tval(ctx, -1)));
-	duk_call_method(ctx, 0);
+		/* The original value needs to be preserved for filter(), hence
+		 * this funny order.  We can't re-get the value because of side
+		 * effects.
+		 */
+
+		duk_dup(ctx, 0);
+		duk_dup(ctx, 1);
+		duk_dup(ctx, -3);
+		duk_push_u32(ctx, i);
+		duk_dup(ctx, 2);  /* [ ... val callback thisArg val i obj ] */
+		duk_call_method(ctx, 3); /* -> [ ... val retval ] */
+
+		switch (iter_type) {
+		case DUK__ITER_EVERY:
+			bval = duk_to_boolean(ctx, -1);
+			if (!bval) {
+				/* stack top contains 'false' */
+				return 1;
+			}
+			break;
+		case DUK__ITER_SOME:
+			bval = duk_to_boolean(ctx, -1);
+			if (bval) {
+				/* stack top contains 'true' */
+				return 1;
+			}
+			break;
+		case DUK__ITER_FOREACH:
+			/* nop */
+			break;
+		case DUK__ITER_MAP:
+			duk_dup(ctx, -1);
+			duk_xdef_prop_index_wec(ctx, 4, (duk_uarridx_t) i);  /* retval to result[i] */
+			res_length = i + 1;
+			break;
+		case DUK__ITER_FILTER:
+			bval = duk_to_boolean(ctx, -1);
+			if (bval) {
+				duk_dup(ctx, -2);  /* orig value */
+				duk_xdef_prop_index_wec(ctx, 4, (duk_uarridx_t) k);
+				k++;
+				res_length = k;
+			}
+			break;
+		default:
+			DUK_UNREACHABLE();
+			break;
+		}
+		duk_pop_2(ctx);
+
+		DUK_ASSERT_TOP(ctx, 5);
+	}
+
+	switch (iter_type) {
+	case DUK__ITER_EVERY:
+		duk_push_true(ctx);
+		break;
+	case DUK__ITER_SOME:
+		duk_push_false(ctx);
+		break;
+	case DUK__ITER_FOREACH:
+		duk_push_undefined(ctx);
+		break;
+	case DUK__ITER_MAP:
+	case DUK__ITER_FILTER:
+		DUK_ASSERT_TOP(ctx, 5);
+		DUK_ASSERT(duk_is_array(ctx, -1));  /* topmost element is the result array already */
+		duk_push_u32(ctx, res_length);
+		duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_LENGTH, DUK_PROPDESC_FLAGS_W);
+		break;
+	default:
+		DUK_UNREACHABLE();
+		break;
+	}
 
 	return 1;
 }
 
 /*
- *  concat()
+ *  reduce(), reduceRight()
  */
 
-duk_ret_t duk_bi_array_prototype_concat(duk_context *ctx) {
-	duk_idx_t i, n;
-	duk_uarridx_t idx, idx_last;
-	duk_uarridx_t j, len;
-	duk_hobject *h;
+DUK_INTERNAL duk_ret_t duk_bi_array_prototype_reduce_shared(duk_context *ctx) {
+	duk_idx_t nargs;
+	duk_bool_t have_acc;
+	duk_uint32_t i, len;
+	duk_small_int_t idx_step = duk_get_current_magic(ctx);  /* idx_step is +1 for reduce, -1 for reduceRight */
 
-	/* XXX: the insert here is a bit expensive if there are a lot of items.
-	 * It could also be special cased in the outermost for loop quite easily
-	 * (as the element is dup()'d anyway).
+	/* We're a varargs function because we need to detect whether
+	 * initialValue was given or not.
 	 */
+	nargs = duk_get_top(ctx);
+	DUK_DDD(DUK_DDDPRINT("nargs=%ld", (long) nargs));
 
-	(void) duk_push_this_coercible_to_object(ctx);
-	duk_insert(ctx, 0);
-	n = duk_get_top(ctx);
-	duk_push_array(ctx);  /* -> [ ToObject(this) item1 ... itemN arr ] */
+	duk_set_top(ctx, 2);
+	len = duk__push_this_obj_len_u32(ctx);
+	if (!duk_is_callable(ctx, 0)) {
+		goto type_error;
+	}
 
-	/* NOTE: The Array special behaviors are NOT invoked by duk_def_prop_index()
-	 * (which differs from the official algorithm).  If no error is thrown, this
-	 * doesn't matter as the length is updated at the end.  However, if an error
-	 * is thrown, the length will be unset.  That shouldn't matter because the
-	 * caller won't get a reference to the intermediate value.
+	/* stack[0] = callback fn
+	 * stack[1] = initialValue
+	 * stack[2] = object (coerced this)
+	 * stack[3] = length (not needed, but not popped above)
+	 * stack[4] = accumulator
 	 */
 
-	idx = 0;
-	idx_last = 0;
-	for (i = 0; i < n; i++) {
-		DUK_ASSERT_TOP(ctx, n + 1);
+	have_acc = 0;
+	if (nargs >= 2) {
+		duk_dup(ctx, 1);
+		have_acc = 1;
+	}
+	DUK_DDD(DUK_DDDPRINT("have_acc=%ld, acc=%!T",
+	                     (long) have_acc, (duk_tval *) duk_get_tval(ctx, 3)));
 
-		/* [ ToObject(this) item1 ... itemN arr ] */
+	/* For len == 0, i is initialized to len - 1 which underflows.
+	 * The condition (i < len) will then exit the for-loop on the
+	 * first round which is correct.  Similarly, loop termination
+	 * happens by i underflowing.
+	 */
 
-		duk_dup(ctx, i);
-		h = duk_get_hobject_with_class(ctx, -1, DUK_HOBJECT_CLASS_ARRAY);
-		if (!h) {
-			duk_def_prop_index_wec(ctx, -2, idx++);
-			idx_last = idx;
+	for (i = (idx_step >= 0 ? 0 : len - 1);
+	     i < len;  /* i >= 0 would always be true */
+	     i += idx_step) {
+		DUK_DDD(DUK_DDDPRINT("i=%ld, len=%ld, have_acc=%ld, top=%ld, acc=%!T",
+		                     (long) i, (long) len, (long) have_acc,
+		                     (long) duk_get_top(ctx),
+		                     (duk_tval *) duk_get_tval(ctx, 4)));
+
+		DUK_ASSERT((have_acc && duk_get_top(ctx) == 5) ||
+		           (!have_acc && duk_get_top(ctx) == 4));
+
+		if (!duk_has_prop_index(ctx, 2, (duk_uarridx_t) i)) {
 			continue;
 		}
 
-		/* [ ToObject(this) item1 ... itemN arr item(i) ] */
-
-		/* XXX: an array can have length higher than 32 bits; this is not handled
-		 * correctly now.
-		 */
-		len = (duk_uarridx_t) duk_get_length(ctx, -1);
-		for (j = 0; j < len; j++) {
-			if (duk_get_prop_index(ctx, -1, j)) {
-				/* [ ToObject(this) item1 ... itemN arr item(i) item(i)[j] ] */
-				duk_def_prop_index_wec(ctx, -3, idx++);
-				idx_last = idx;
-			} else {
-				/* XXX: according to E5.1 Section 15.4.4.4 nonexistent trailing
-				 * elements do not affect 'length' but test262 disagrees.  Work
-				 * as E5.1 mandates for now and don't touch idx_last.
-				 */
-				idx++;
-				duk_pop(ctx);
-			}
+		if (!have_acc) {
+			DUK_ASSERT_TOP(ctx, 4);
+			duk_get_prop_index(ctx, 2, (duk_uarridx_t) i);
+			have_acc = 1;
+			DUK_ASSERT_TOP(ctx, 5);
+		} else {
+			DUK_ASSERT_TOP(ctx, 5);
+			duk_dup(ctx, 0);
+			duk_dup(ctx, 4);
+			duk_get_prop_index(ctx, 2, (duk_uarridx_t) i);
+			duk_push_u32(ctx, i);
+			duk_dup(ctx, 2);
+			DUK_DDD(DUK_DDDPRINT("calling reduce function: func=%!T, prev=%!T, curr=%!T, idx=%!T, obj=%!T",
+			                     (duk_tval *) duk_get_tval(ctx, -5), (duk_tval *) duk_get_tval(ctx, -4),
+			                     (duk_tval *) duk_get_tval(ctx, -3), (duk_tval *) duk_get_tval(ctx, -2),
+			                     (duk_tval *) duk_get_tval(ctx, -1)));
+			duk_call(ctx, 4);
+			DUK_DDD(DUK_DDDPRINT("-> result: %!T", (duk_tval *) duk_get_tval(ctx, -1)));
+			duk_replace(ctx, 4);
+			DUK_ASSERT_TOP(ctx, 5);
 		}
-		duk_pop(ctx);
 	}
 
-	duk_push_uarridx(ctx, idx_last);
-	duk_def_prop_stridx(ctx, -2, DUK_STRIDX_LENGTH, DUK_PROPDESC_FLAGS_W);
+	if (!have_acc) {
+		goto type_error;
+	}
 
-	DUK_ASSERT_TOP(ctx, n + 1);
+	DUK_ASSERT_TOP(ctx, 5);
 	return 1;
+
+ type_error:
+	return DUK_RET_TYPE_ERROR;
 }
 
+#undef DUK__ARRAY_MID_JOIN_LIMIT
+
+#undef DUK__ITER_EVERY
+#undef DUK__ITER_SOME
+#undef DUK__ITER_FOREACH
+#undef DUK__ITER_MAP
+#undef DUK__ITER_FILTER
+#line 1 "duk_bi_boolean.c"
 /*
- *  join(), toLocaleString()
- *
- *  Note: checking valstack is necessary, but only in the per-element loop.
- *
- *  Note: the trivial approach of pushing all the elements on the value stack
- *  and then calling duk_join() fails when the array contains a large number
- *  of elements.  This problem can't be offloaded to duk_join() because the
- *  elements to join must be handled here and have special handling.  Current
- *  approach is to do intermediate joins with very large number of elements.
- *  There is no fancy handling; the prefix gets re-joined multiple times.
+ *  Boolean built-ins
  */
 
-duk_ret_t duk_bi_array_prototype_join_shared(duk_context *ctx) {
-	duk_uint32_t len, count;
-	duk_uint32_t idx;
-	duk_small_int_t to_locale_string = duk_get_magic(ctx);
-	duk_idx_t valstack_required;
+/* include removed: duk_internal.h */
 
-	/* For join(), nargs is 1.  For toLocaleString(), nargs is 0 and
-	 * setting the top essentially pushes an undefined to the stack,
-	 * thus defaulting to a comma separator.
+/* Shared helper to provide toString() and valueOf().  Checks 'this', gets
+ * the primitive value to stack top, and optionally coerces with ToString().
+ */
+DUK_INTERNAL duk_ret_t duk_bi_boolean_prototype_tostring_shared(duk_context *ctx) {
+	duk_tval *tv;
+	duk_hobject *h;
+	duk_small_int_t coerce_tostring = duk_get_current_magic(ctx);
+
+	/* XXX: there is room to use a shared helper here, many built-ins
+	 * check the 'this' type, and if it's an object, check its class,
+	 * then get its internal value, etc.
 	 */
-	duk_set_top(ctx, 1);
-	if (duk_is_undefined(ctx, 0)) {
-		duk_pop(ctx);
-		duk_push_hstring_stridx(ctx, DUK_STRIDX_COMMA);
-	} else {
-		duk_to_string(ctx, 0);
-	}
 
-	len = duk__push_this_obj_len_u32(ctx);
+	duk_push_this(ctx);
+	tv = duk_get_tval(ctx, -1);
+	DUK_ASSERT(tv != NULL);
 
-	/* [ sep ToObject(this) len ] */
+	if (DUK_TVAL_IS_BOOLEAN(tv)) {
+		goto type_ok;
+	} else if (DUK_TVAL_IS_OBJECT(tv)) {
+		h = DUK_TVAL_GET_OBJECT(tv);
+		DUK_ASSERT(h != NULL);
 
-	DUK_DDD(DUK_DDDPRINT("sep=%!T, this=%!T, len=%lu",
-	                     (duk_tval *) duk_get_tval(ctx, 0),
-	                     (duk_tval *) duk_get_tval(ctx, 1),
-	                     (unsigned long) len));
+		if (DUK_HOBJECT_GET_CLASS_NUMBER(h) == DUK_HOBJECT_CLASS_BOOLEAN) {
+			duk_get_prop_stridx(ctx, -1, DUK_STRIDX_INT_VALUE);
+			DUK_ASSERT(duk_is_boolean(ctx, -1));
+			goto type_ok;
+		}
+	}
 
-	valstack_required = (len >= DUK__ARRAY_MID_JOIN_LIMIT ?
-	                     DUK__ARRAY_MID_JOIN_LIMIT : len) + 1;
-	duk_require_stack(ctx, valstack_required);
+	return DUK_RET_TYPE_ERROR;
 
-	duk_dup(ctx, 0);
+ type_ok:
+	if (coerce_tostring) {
+		duk_to_string(ctx, -1);
+	}
+	return 1;
+}
 
-	/* [ sep ToObject(this) len sep ] */
+DUK_INTERNAL duk_ret_t duk_bi_boolean_constructor(duk_context *ctx) {
+	duk_hthread *thr = (duk_hthread *) ctx;
+	duk_hobject *h_this;
 
-	count = 0;
-	idx = 0;
-	for (;;) {
-		if (count >= DUK__ARRAY_MID_JOIN_LIMIT ||   /* intermediate join to avoid valstack overflow */
-		    idx >= len) { /* end of loop (careful with len==0) */
-			/* [ sep ToObject(this) len sep str0 ... str(count-1) ] */
-			DUK_DDD(DUK_DDDPRINT("mid/final join, count=%ld, idx=%ld, len=%ld",
-			                     (long) count, (long) idx, (long) len));
-			duk_join(ctx, (duk_idx_t) count);  /* -> [ sep ToObject(this) len str ] */
-			duk_dup(ctx, 0);                   /* -> [ sep ToObject(this) len str sep ] */
-			duk_insert(ctx, -2);               /* -> [ sep ToObject(this) len sep str ] */
-			count = 1;
-		}
-		if (idx >= len) {
-			/* if true, the stack already contains the final result */
-			break;
-		}
+	DUK_UNREF(thr);
 
-		duk_get_prop_index(ctx, 1, (duk_uarridx_t) idx);
-		if (duk_is_null_or_undefined(ctx, -1)) {
-			duk_pop(ctx);
-			duk_push_hstring_stridx(ctx, DUK_STRIDX_EMPTY_STRING);
-		} else {
-			if (to_locale_string) {
-				duk_to_object(ctx, -1);
-				duk_get_prop_stridx(ctx, -1, DUK_STRIDX_TO_LOCALE_STRING);
-				duk_insert(ctx, -2);  /* -> [ ... toLocaleString ToObject(val) ] */
-				duk_call_method(ctx, 0);
-				duk_to_string(ctx, -1);
-			} else {
-				duk_to_string(ctx, -1);
-			}
-		}
+	duk_to_boolean(ctx, 0);
 
-		count++;
-		idx++;
-	}
+	if (duk_is_constructor_call(ctx)) {
+		/* XXX: helper; rely on Boolean.prototype as being non-writable, non-configurable */
+		duk_push_this(ctx);
+		h_this = duk_get_hobject(ctx, -1);
+		DUK_ASSERT(h_this != NULL);
+		DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h_this) == thr->builtins[DUK_BIDX_BOOLEAN_PROTOTYPE]);
 
-	/* [ sep ToObject(this) len sep result ] */
+		DUK_HOBJECT_SET_CLASS_NUMBER(h_this, DUK_HOBJECT_CLASS_BOOLEAN);
+
+		duk_dup(ctx, 0);  /* -> [ val obj val ] */
+		duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_INT_VALUE, DUK_PROPDESC_FLAGS_NONE);  /* XXX: proper flags? */
+	}  /* unbalanced stack */
 
 	return 1;
 }
-
+#line 1 "duk_bi_buffer.c"
 /*
- *  pop(), push()
+ *  Duktape.Buffer, Node.js Buffer, and Khronos/ES6 TypedArray built-ins
  */
 
-duk_ret_t duk_bi_array_prototype_pop(duk_context *ctx) {
-	duk_uint32_t len;
-	duk_uint32_t idx;
+/* include removed: duk_internal.h */
 
-	DUK_ASSERT_TOP(ctx, 0);
-	len = duk__push_this_obj_len_u32(ctx);
-	if (len == 0) {
-		duk_push_int(ctx, 0);
-		duk_put_prop_stridx(ctx, 0, DUK_STRIDX_LENGTH);
-		return 0;
-	}
-	idx = len - 1;
+/*
+ *  Misc helpers
+ */
 
-	duk_get_prop_index(ctx, 0, (duk_uarridx_t) idx);
-	duk_del_prop_index(ctx, 0, (duk_uarridx_t) idx);
-	duk_push_u32(ctx, idx);
-	duk_put_prop_stridx(ctx, 0, DUK_STRIDX_LENGTH);
-	return 1;
-}
+#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
+/* Map DUK_HBUFFEROBJECT_ELEM_xxx to duk_hobject class number.
+ * Sync with duk_hbufferobject.h and duk_hobject.h.
+ */
+static const duk_uint8_t duk__buffer_class_from_elemtype[9] = {
+	DUK_HOBJECT_CLASS_UINT8ARRAY,
+	DUK_HOBJECT_CLASS_UINT8CLAMPEDARRAY,
+	DUK_HOBJECT_CLASS_INT8ARRAY,
+	DUK_HOBJECT_CLASS_UINT16ARRAY,
+	DUK_HOBJECT_CLASS_INT16ARRAY,
+	DUK_HOBJECT_CLASS_UINT32ARRAY,
+	DUK_HOBJECT_CLASS_INT32ARRAY,
+	DUK_HOBJECT_CLASS_FLOAT32ARRAY,
+	DUK_HOBJECT_CLASS_FLOAT64ARRAY
+};
+#endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
+
+#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
+/* Map DUK_HBUFFEROBJECT_ELEM_xxx to prototype object built-in index.
+ * Sync with duk_hbufferobject.h.
+ */
+static const duk_uint8_t duk__buffer_proto_from_elemtype[9] = {
+	DUK_BIDX_UINT8ARRAY_PROTOTYPE,
+	DUK_BIDX_UINT8CLAMPEDARRAY_PROTOTYPE,
+	DUK_BIDX_INT8ARRAY_PROTOTYPE,
+	DUK_BIDX_UINT16ARRAY_PROTOTYPE,
+	DUK_BIDX_INT16ARRAY_PROTOTYPE,
+	DUK_BIDX_UINT32ARRAY_PROTOTYPE,
+	DUK_BIDX_INT32ARRAY_PROTOTYPE,
+	DUK_BIDX_FLOAT32ARRAY_PROTOTYPE,
+	DUK_BIDX_FLOAT64ARRAY_PROTOTYPE
+};
+#endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
+
+#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
+/* Map DUK__FLX_xxx to byte size.
+ */
+static const duk_uint8_t duk__buffer_nbytes_from_fldtype[6] = {
+	1,  /* DUK__FLD_8BIT */
+	2,  /* DUK__FLD_16BIT */
+	4,  /* DUK__FLD_32BIT */
+	4,  /* DUK__FLD_FLOAT */
+	8,  /* DUK__FLD_DOUBLE */
+	0   /* DUK__FLD_VARINT; not relevant here */
+};
+#endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
 
-duk_ret_t duk_bi_array_prototype_push(duk_context *ctx) {
-	/* Note: 'this' is not necessarily an Array object.  The push()
-	 * algorithm is supposed to work for other kinds of objects too,
-	 * so the algorithm has e.g. an explicit update for the 'length'
-	 * property which is normally "magical" in arrays.
+#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
+/* Bitfield for each DUK_HBUFFEROBJECT_ELEM_xxx indicating which element types
+ * are compatible with a blind byte copy for the TypedArray set() method (also
+ * used for TypedArray constructor).  Array index is target buffer elem type,
+ * bitfield indicates compatible source types.  The types must have same byte
+ * size and they must be coercion compatible.
+ */
+static duk_uint16_t duk__buffer_elemtype_copy_compatible[9] = {
+	/* xxx -> DUK_HBUFFEROBJECT_ELEM_UINT8 */
+	(1U << DUK_HBUFFEROBJECT_ELEM_UINT8) |
+		(1U << DUK_HBUFFEROBJECT_ELEM_UINT8CLAMPED) |
+		(1U << DUK_HBUFFEROBJECT_ELEM_INT8),
+
+	/* xxx -> DUK_HBUFFEROBJECT_ELEM_UINT8CLAMPED
+	 * Note: INT8 is -not- copy compatible, e.g. -1 would coerce to 0x00.
 	 */
+	(1U << DUK_HBUFFEROBJECT_ELEM_UINT8) |
+		(1U << DUK_HBUFFEROBJECT_ELEM_UINT8CLAMPED),
 
-	duk_double_t len;
-	duk_idx_t i, n;
+	/* xxx -> DUK_HBUFFEROBJECT_ELEM_INT8 */
+	(1U << DUK_HBUFFEROBJECT_ELEM_UINT8) |
+		(1U << DUK_HBUFFEROBJECT_ELEM_UINT8CLAMPED) |
+		(1U << DUK_HBUFFEROBJECT_ELEM_INT8),
 
-	n = duk_get_top(ctx);
-	len = (duk_double_t) duk__push_this_obj_len_u32(ctx);
+	/* xxx -> DUK_HBUFFEROBJECT_ELEM_UINT16 */
+	(1U << DUK_HBUFFEROBJECT_ELEM_UINT16) |
+		(1U << DUK_HBUFFEROBJECT_ELEM_INT16),
 
-	/* [ arg1 ... argN obj length ] */
+	/* xxx -> DUK_HBUFFEROBJECT_ELEM_INT16 */
+	(1U << DUK_HBUFFEROBJECT_ELEM_UINT16) |
+		(1U << DUK_HBUFFEROBJECT_ELEM_INT16),
 
-	/* Note: we keep track of length with a double instead of a 32-bit
-	 * (unsigned) int because the length can go beyond 32 bits and the
-	 * final length value is NOT wrapped to 32 bits on this call.
-	 */
+	/* xxx -> DUK_HBUFFEROBJECT_ELEM_UINT32 */
+	(1U << DUK_HBUFFEROBJECT_ELEM_UINT32) |
+		(1U << DUK_HBUFFEROBJECT_ELEM_INT32),
 
-	for (i = 0; i < n; i++) {
-		duk_push_number(ctx, len);
-		duk_dup(ctx, i);
-		duk_put_prop(ctx, -4);
-		len += 1.0;
+	/* xxx -> DUK_HBUFFEROBJECT_ELEM_INT32 */
+	(1U << DUK_HBUFFEROBJECT_ELEM_UINT32) |
+		(1U << DUK_HBUFFEROBJECT_ELEM_INT32),
+
+	/* xxx -> DUK_HBUFFEROBJECT_ELEM_FLOAT32 */
+	(1U << DUK_HBUFFEROBJECT_ELEM_FLOAT32),
+
+	/* xxx -> DUK_HBUFFEROBJECT_ELEM_FLOAT64 */
+	(1U << DUK_HBUFFEROBJECT_ELEM_FLOAT64)
+};
+#endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
+
+#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
+/* Shared helper. */
+DUK_LOCAL duk_hbufferobject *duk__getrequire_bufobj_this(duk_context *ctx, duk_bool_t throw_flag) {
+	duk_hthread *thr;
+	duk_tval *tv;
+	duk_hbufferobject *h_this;
+
+	DUK_ASSERT(ctx != NULL);
+	thr = (duk_hthread *) ctx;
+
+	tv = duk_get_borrowed_this_tval(ctx);
+	DUK_ASSERT(tv != NULL);
+	if (DUK_TVAL_IS_OBJECT(tv)) {
+		h_this = (duk_hbufferobject *) DUK_TVAL_GET_OBJECT(tv);
+		DUK_ASSERT(h_this != NULL);
+		if (DUK_HOBJECT_IS_BUFFEROBJECT((duk_hobject *) h_this)) {
+			DUK_ASSERT_HBUFFEROBJECT_VALID(h_this);
+			return h_this;
+		}
 	}
 
-	duk_push_number(ctx, len);
-	duk_dup_top(ctx);
-	duk_put_prop_stridx(ctx, -4, DUK_STRIDX_LENGTH);
+	if (throw_flag) {
+		DUK_ERROR(thr, DUK_ERR_TYPE_ERROR, DUK_STR_NOT_BUFFER);
+	}
+	return NULL;
+}
+#endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
 
-	/* [ arg1 ... argN obj length new_length ] */
-	return 1;
+#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
+/* Check that 'this' is a duk_hbufferobject and return a pointer to it. */
+DUK_LOCAL duk_hbufferobject *duk__get_bufobj_this(duk_context *ctx) {
+	return duk__getrequire_bufobj_this(ctx, 0);
 }
+#endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
 
-/*
- *  sort()
- *
- *  Currently qsort with random pivot.  This is now really, really slow,
- *  because there is no fast path for array parts.
- *
- *  Signed indices are used because qsort() leaves and degenerate cases
- *  may use a negative offset.
+#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
+/* Check that 'this' is a duk_hbufferobject and return a pointer to it
+ * (NULL if not).
  */
+DUK_LOCAL duk_hbufferobject *duk__require_bufobj_this(duk_context *ctx) {
+	return duk__getrequire_bufobj_this(ctx, 1);
+}
+#endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
 
-static duk_small_int_t duk__array_sort_compare(duk_context *ctx, duk_int_t idx1, duk_int_t idx2) {
-	duk_bool_t have1, have2;
-	duk_bool_t undef1, undef2;
-	duk_small_int_t ret;
-	duk_idx_t idx_obj = 1;  /* fixed offsets in valstack */
-	duk_idx_t idx_fn = 0;
-	duk_hstring *h1, *h2;
+#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
+/* Check that value is a duk_hbufferobject and return a pointer to it. */
+DUK_LOCAL duk_hbufferobject *duk__require_bufobj_value(duk_context *ctx, duk_idx_t index) {
+	duk_hthread *thr;
+	duk_tval *tv;
+	duk_hbufferobject *h_obj;
 
-	/* Fast exit if indices are identical.  This is valid for a non-existent property,
-	 * for an undefined value, and almost always for ToString() coerced comparison of
-	 * arbitrary values (corner cases where this is not the case include e.g. a an
-	 * object with varying ToString() coercion).
-	 *
-	 * The specification does not prohibit "caching" of values read from the array, so
-	 * assuming equality for comparing an index with itself falls into the category of
-	 * "caching".
-	 *
-	 * Also, compareFn may be inconsistent, so skipping a call to compareFn here may
-	 * have an effect on the final result.  The specification does not require any
-	 * specific behavior for inconsistent compare functions, so again, this fast path
-	 * is OK.
-	 */
+	thr = (duk_hthread *) ctx;
 
-	if (idx1 == idx2) {
-		DUK_DDD(DUK_DDDPRINT("duk__array_sort_compare: idx1=%ld, idx2=%ld -> indices identical, quick exit",
-		                     (long) idx1, (long) idx2));
-		return 0;
+	/* Don't accept relative indices now. */
+	DUK_ASSERT(index >= 0);
+
+	tv = duk_require_tval(ctx, index);
+	DUK_ASSERT(tv != NULL);
+	if (DUK_TVAL_IS_OBJECT(tv)) {
+		h_obj = (duk_hbufferobject *) DUK_TVAL_GET_OBJECT(tv);
+		DUK_ASSERT(h_obj != NULL);
+		if (DUK_HOBJECT_IS_BUFFEROBJECT((duk_hobject *) h_obj)) {
+			DUK_ASSERT_HBUFFEROBJECT_VALID(h_obj);
+			return h_obj;
+		}
 	}
 
-	have1 = duk_get_prop_index(ctx, idx_obj, (duk_uarridx_t) idx1);
-	have2 = duk_get_prop_index(ctx, idx_obj, (duk_uarridx_t) idx2);
+	DUK_ERROR(thr, DUK_ERR_TYPE_ERROR, DUK_STR_NOT_BUFFER);
+	return NULL;  /* not reachable */
+}
+#endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
 
-	DUK_DDD(DUK_DDDPRINT("duk__array_sort_compare: idx1=%ld, idx2=%ld, have1=%ld, have2=%ld, val1=%!T, val2=%!T",
-	                     (long) idx1, (long) idx2, (long) have1, (long) have2,
-	                     (duk_tval *) duk_get_tval(ctx, -2), (duk_tval *) duk_get_tval(ctx, -1)));
+DUK_LOCAL void duk__set_bufobj_buffer(duk_context *ctx, duk_hbufferobject *h_bufobj, duk_hbuffer *h_val) {
+	duk_hthread *thr;
 
-	if (have1) {
-		if (have2) {
-			;
-		} else {
-			ret = -1;
-			goto pop_ret;
-		}
-	} else {
-		if (have2) {
-			ret = 1;
-			goto pop_ret;
-		} else {
-			ret = 0;
-			goto pop_ret;
-		}
+	thr = (duk_hthread *) ctx;
+	DUK_UNREF(thr);
+
+	DUK_ASSERT(ctx != NULL);
+	DUK_ASSERT(h_bufobj != NULL);
+	DUK_ASSERT(h_bufobj->buf == NULL);  /* no need to decref */
+	DUK_ASSERT(h_val != NULL);
+	DUK_ASSERT_HBUFFEROBJECT_VALID(h_bufobj);
+
+	h_bufobj->buf = h_val;
+	DUK_HBUFFER_INCREF(thr, h_val);
+	h_bufobj->length = (duk_uint_t) DUK_HBUFFER_GET_SIZE(h_val);
+	DUK_ASSERT(h_bufobj->shift == 0);
+	DUK_ASSERT(h_bufobj->elem_type == DUK_HBUFFEROBJECT_ELEM_UINT8);
+
+	DUK_ASSERT_HBUFFEROBJECT_VALID(h_bufobj);
+}
+
+#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
+DUK_LOCAL duk_hbufferobject *duk__push_arraybuffer_with_length(duk_context *ctx, duk_uint_t len) {
+	duk_hbuffer *h_val;
+	duk_hbufferobject *h_bufobj;
+
+	(void) duk_push_fixed_buffer(ctx, (duk_size_t) len);
+	h_val = (duk_hbuffer *) duk_get_hbuffer(ctx, -1);
+	DUK_ASSERT(h_val != NULL);
+
+	h_bufobj = duk_push_bufferobject_raw(ctx,
+	                                     DUK_HOBJECT_FLAG_EXTENSIBLE |
+	                                     DUK_HOBJECT_FLAG_BUFFEROBJECT |
+	                                     DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_ARRAYBUFFER),
+	                                     DUK_BIDX_ARRAYBUFFER_PROTOTYPE);
+	DUK_ASSERT(h_bufobj != NULL);
+
+	duk__set_bufobj_buffer(ctx, h_bufobj, h_val);
+	DUK_ASSERT_HBUFFEROBJECT_VALID(h_bufobj);
+
+	return h_bufobj;
+}
+#endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
+
+#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
+/* Shared offset/length coercion helper. */
+DUK_LOCAL void duk__resolve_offset_opt_length(duk_context *ctx,
+                                              duk_hbufferobject *h_bufarg,
+                                              duk_idx_t idx_offset,
+                                              duk_idx_t idx_length,
+                                              duk_uint_t *out_offset,
+                                              duk_uint_t *out_length,
+                                              duk_bool_t throw_flag) {
+	duk_hthread *thr;
+	duk_int_t offset_signed;
+	duk_int_t length_signed;
+	duk_uint_t offset;
+	duk_uint_t length;
+
+	thr = (duk_hthread *) ctx;
+	DUK_UNREF(thr);
+
+	offset_signed = duk_to_int(ctx, idx_offset);
+	if (offset_signed < 0) {
+		goto fail_range;
 	}
+	offset = (duk_uint_t) offset_signed;
+	if (offset > h_bufarg->length) {
+		goto fail_range;
+	}
+	DUK_ASSERT_DISABLE(offset >= 0);  /* unsigned */
+	DUK_ASSERT(offset <= h_bufarg->length);
 
-	undef1 = duk_is_undefined(ctx, -2);
-	undef2 = duk_is_undefined(ctx, -1);
-	if (undef1) {
-		if (undef2) {
-			ret = 0;
-			goto pop_ret;
-		} else {
-			ret = 1;
-			goto pop_ret;
-		}
+	if (duk_is_undefined(ctx, idx_length)) {
+		DUK_ASSERT(h_bufarg->length >= offset);
+		length = h_bufarg->length - offset;  /* >= 0 */
 	} else {
-		if (undef2) {
-			ret = -1;
-			goto pop_ret;
-		} else {
-			;
+		length_signed = duk_to_int(ctx, idx_length);
+		if (length_signed < 0) {
+			goto fail_range;
+		}
+		length = (duk_uint_t) length_signed;
+		DUK_ASSERT(h_bufarg->length >= offset);
+		if (length > h_bufarg->length - offset) {
+			/* Unlike for negative arguments, some call sites
+			 * want length to be clamped if it's positive.
+			 */
+			if (throw_flag) {
+				goto fail_range;
+			} else {
+				length = h_bufarg->length - offset;
+			}
 		}
 	}
+	DUK_ASSERT_DISABLE(length >= 0);  /* unsigned */
+	DUK_ASSERT(offset + length <= h_bufarg->length);
 
-	if (!duk_is_undefined(ctx, idx_fn)) {
-		duk_double_t d;
+	*out_offset = offset;
+	*out_length = length;
+	return;
 
-		/* no need to check callable; duk_call() will do that */
-		duk_dup(ctx, idx_fn);    /* -> [ ... x y fn ] */
-		duk_insert(ctx, -3);     /* -> [ ... fn x y ] */
-		duk_call(ctx, 2);        /* -> [ ... res ] */
+ fail_range:
+	duk_error(thr, DUK_ERR_RANGE_ERROR, DUK_STR_INVALID_CALL_ARGS);
+}
+#endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
 
-		/* The specification is a bit vague what to do if the return
-		 * value is not a number.  Other implementations seem to
-		 * tolerate non-numbers but e.g. V8 won't apparently do a
-		 * ToNumber().
-		 */
+#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
+/* Shared lenient buffer length clamping helper.  No negative indices, no
+ * element/byte shifting.
+ */
+DUK_LOCAL void duk__clamp_startend_nonegidx_noshift(duk_context *ctx,
+                                                    duk_hbufferobject *h_bufobj,
+                                                    duk_idx_t idx_start,
+                                                    duk_idx_t idx_end,
+                                                    duk_int_t *out_start_offset,
+                                                    duk_int_t *out_end_offset) {
+	duk_int_t buffer_length;
+	duk_int_t start_offset;
+	duk_int_t end_offset;
 
-		/* XXX: best behavior for real world compatibility? */
+	DUK_ASSERT(out_start_offset != NULL);
+	DUK_ASSERT(out_end_offset != NULL);
 
-		d = duk_to_number(ctx, -1);
-		if (d < 0.0) {
-			ret = -1;
-		} else if (d > 0.0) {
-			ret = 1;
-		} else {
-			ret = 0;
-		}
+	buffer_length = (duk_int_t) h_bufobj->length;
 
-		duk_pop(ctx);
-		DUK_DDD(DUK_DDDPRINT("-> result %ld (from comparefn, after coercion)", (long) ret));
-		return ret;
+	/* undefined coerces to zero which is correct */
+	start_offset = duk_to_int_clamped(ctx, idx_start, 0, buffer_length);
+	if (duk_is_undefined(ctx, idx_end)) {
+		end_offset = buffer_length;
+	} else {
+		end_offset = duk_to_int_clamped(ctx, idx_end, start_offset, buffer_length);
 	}
 
-	/* string compare is the default (a bit oddly) */
-
-	h1 = duk_to_hstring(ctx, -2);
-	h2 = duk_to_hstring(ctx, -1);
-	DUK_ASSERT(h1 != NULL);
-	DUK_ASSERT(h2 != NULL);
-
-	ret = duk_js_string_compare(h1, h2);  /* retval is directly usable */
-	goto pop_ret;
+	DUK_ASSERT(start_offset >= 0);
+	DUK_ASSERT(start_offset <= buffer_length);
+	DUK_ASSERT(end_offset >= 0);
+	DUK_ASSERT(end_offset <= buffer_length);
+	DUK_ASSERT(start_offset <= end_offset);
 
- pop_ret:
-	duk_pop_2(ctx);
-	DUK_DDD(DUK_DDDPRINT("-> result %ld", (long) ret));
-	return ret;
+	*out_start_offset = start_offset;
+	*out_end_offset = end_offset;
 }
+#endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
 
-static void duk__array_sort_swap(duk_context *ctx, duk_int_t l, duk_int_t r) {
-	duk_bool_t have_l, have_r;
-	duk_idx_t idx_obj = 1;  /* fixed offset in valstack */
+#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
+/* Shared lenient buffer length clamping helper.  Indices are treated as
+ * element indices (though output values are byte offsets) which only
+ * really matters for TypedArray views as other buffer object have a zero
+ * shift.  Negative indices are counted from end of input slice; crossed
+ * indices are clamped to zero length; and final indices are clamped
+ * against input slice.  Used for e.g. ArrayBuffer slice().
+ */
+DUK_LOCAL void duk__clamp_startend_negidx_shifted(duk_context *ctx,
+                                                  duk_hbufferobject *h_bufobj,
+                                                  duk_idx_t idx_start,
+                                                  duk_idx_t idx_end,
+                                                  duk_int_t *out_start_offset,
+                                                  duk_int_t *out_end_offset) {
+	duk_int_t buffer_length;
+	duk_int_t start_offset;
+	duk_int_t end_offset;
 
-	if (l == r) {
-		return;
-	}
+	DUK_ASSERT(out_start_offset != NULL);
+	DUK_ASSERT(out_end_offset != NULL);
 
-	/* swap elements; deal with non-existent elements correctly */
-	have_l = duk_get_prop_index(ctx, idx_obj, (duk_uarridx_t) l);
-	have_r = duk_get_prop_index(ctx, idx_obj, (duk_uarridx_t) r);
+	buffer_length = (duk_int_t) h_bufobj->length;
+	buffer_length >>= h_bufobj->shift;  /* as elements */
 
-	if (have_r) {
-		/* right exists, [[Put]] regardless whether or not left exists */
-		duk_put_prop_index(ctx, idx_obj, (duk_uarridx_t) l);
-	} else {
-		duk_del_prop_index(ctx, idx_obj, (duk_uarridx_t) l);
-		duk_pop(ctx);
-	}
+	/* Resolve start/end offset as element indices first; arguments
+	 * at idx_start/idx_end are element offsets.  Working with element
+	 * indices first also avoids potential for wrapping.
+	 */
 
-	if (have_l) {
-		duk_put_prop_index(ctx, idx_obj, (duk_uarridx_t) r);
+	start_offset = duk_to_int(ctx, idx_start);
+	if (start_offset < 0) {
+		start_offset = buffer_length + start_offset;
+	}
+	if (duk_is_undefined(ctx, idx_end)) {
+		end_offset = buffer_length;
 	} else {
-		duk_del_prop_index(ctx, idx_obj, (duk_uarridx_t) r);
-		duk_pop(ctx);
+		end_offset = duk_to_int(ctx, idx_end);
+		if (end_offset < 0) {
+			end_offset = buffer_length + end_offset;
+		}
 	}
-}
+	/* Note: start_offset/end_offset can still be < 0 here. */
 
-#if defined(DUK_USE_DDDPRINT)
-/* Debug print which visualizes the qsort partitioning process. */
-static void duk__debuglog_qsort_state(duk_context *ctx, duk_int_t lo, duk_int_t hi, duk_int_t pivot) {
-	char buf[4096];
-	char *ptr = buf;
-	duk_int_t i, n;
-	n = (duk_int_t) duk_get_length(ctx, 1);
-	if (n > 4000) {
-		n = 4000;
+	if (start_offset < 0) {
+		start_offset = 0;
+	} else if (start_offset > buffer_length) {
+		start_offset = buffer_length;
 	}
-	*ptr++ = '[';
-	for (i = 0; i < n; i++) {
-		if (i == pivot) {
-			*ptr++ = '|';
-		} else if (i == lo) {
-			*ptr++ = '<';
-		} else if (i == hi) {
-			*ptr++ = '>';
-		} else if (i >= lo && i <= hi) {
-			*ptr++ = '-';
-		} else {
-			*ptr++ = ' ';
-		}
+	if (end_offset < start_offset) {
+		end_offset = start_offset;
+	} else if (end_offset > buffer_length) {
+		end_offset = buffer_length;
 	}
-	*ptr++ = ']';
-	*ptr++ = '\0';
+	DUK_ASSERT(start_offset >= 0);
+	DUK_ASSERT(start_offset <= buffer_length);
+	DUK_ASSERT(end_offset >= 0);
+	DUK_ASSERT(end_offset <= buffer_length);
+	DUK_ASSERT(start_offset <= end_offset);
 
-	DUK_DDD(DUK_DDDPRINT("%s   (lo=%ld, hi=%ld, pivot=%ld)",
-	                     (const char *) buf, (long) lo, (long) hi, (long) pivot));
+	/* Convert indices to byte offsets. */
+	start_offset <<= h_bufobj->shift;
+	end_offset <<= h_bufobj->shift;
+
+	*out_start_offset = start_offset;
+	*out_end_offset = end_offset;
 }
-#endif
+#endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
 
-static void duk__array_qsort(duk_context *ctx, duk_int_t lo, duk_int_t hi) {
-	duk_hthread *thr = (duk_hthread *) ctx;
-	duk_int_t p, l, r;
+/*
+ *  Indexed read/write helpers (also used from outside this file)
+ */
 
-	/* The lo/hi indices may be crossed and hi < 0 is possible at entry. */
+DUK_INTERNAL void duk_hbufferobject_push_validated_read(duk_context *ctx, duk_hbufferobject *h_bufobj, duk_uint8_t *p, duk_small_uint_t elem_size) {
+	duk_double_union du;
 
-	DUK_DDD(DUK_DDDPRINT("duk__array_qsort: lo=%ld, hi=%ld, obj=%!T",
-	                     (long) lo, (long) hi, (duk_tval *) duk_get_tval(ctx, 1)));
+	DUK_MEMCPY((void *) du.uc, (const void *) p, (size_t) elem_size);
 
-	DUK_ASSERT_TOP(ctx, 3);
+	switch (h_bufobj->elem_type) {
+	case DUK_HBUFFEROBJECT_ELEM_UINT8:
+#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
+	case DUK_HBUFFEROBJECT_ELEM_UINT8CLAMPED:
+#endif
+		duk_push_uint(ctx, (duk_uint_t) du.uc[0]);
+		break;
+#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
+	/* These are not needed when only Duktape.Buffer is supported. */
+	case DUK_HBUFFEROBJECT_ELEM_INT8:
+		duk_push_int(ctx, (duk_int_t) (duk_int8_t) du.uc[0]);
+		break;
+	case DUK_HBUFFEROBJECT_ELEM_UINT16:
+		duk_push_uint(ctx, (duk_uint_t) du.us[0]);
+		break;
+	case DUK_HBUFFEROBJECT_ELEM_INT16:
+		duk_push_int(ctx, (duk_int_t) (duk_int16_t) du.us[0]);
+		break;
+	case DUK_HBUFFEROBJECT_ELEM_UINT32:
+		duk_push_uint(ctx, (duk_uint_t) du.ui[0]);
+		break;
+	case DUK_HBUFFEROBJECT_ELEM_INT32:
+		duk_push_int(ctx, (duk_int_t) (duk_int32_t) du.ui[0]);
+		break;
+	case DUK_HBUFFEROBJECT_ELEM_FLOAT32:
+		duk_push_number(ctx, (duk_double_t) du.f[0]);
+		break;
+	case DUK_HBUFFEROBJECT_ELEM_FLOAT64:
+		duk_push_number(ctx, (duk_double_t) du.d);
+		break;
+#endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
+	default:
+		DUK_UNREACHABLE();
+	}
+}
 
-	/* In some cases it may be that lo > hi, or hi < 0; these
-	 * degenerate cases happen e.g. for empty arrays, and in
-	 * recursion leaves.
+DUK_INTERNAL void duk_hbufferobject_validated_write(duk_context *ctx, duk_hbufferobject *h_bufobj, duk_uint8_t *p, duk_small_uint_t elem_size) {
+	duk_double_union du;
+
+	/* NOTE! Caller must ensure that any side effects from the
+	 * coercions below are safe.  If that cannot be guaranteed
+	 * (which is normally the case), caller must coerce the
+	 * argument using duk_to_number() before any pointer
+	 * validations; the result of duk_to_number() always coerces
+	 * without side effects here.
 	 */
 
-	/* trivial cases */
-	if (hi - lo < 1) {
-		DUK_DDD(DUK_DDDPRINT("degenerate case, return immediately"));
-		return;
+	switch (h_bufobj->elem_type) {
+	case DUK_HBUFFEROBJECT_ELEM_UINT8:
+		du.uc[0] = (duk_uint8_t) duk_to_uint32(ctx, -1);
+		break;
+#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
+	/* These are not needed when only Duktape.Buffer is supported. */
+	case DUK_HBUFFEROBJECT_ELEM_UINT8CLAMPED:
+		du.uc[0] = (duk_uint8_t) duk_to_uint8clamped(ctx, -1);
+		break;
+	case DUK_HBUFFEROBJECT_ELEM_INT8:
+		du.uc[0] = (duk_uint8_t) duk_to_int32(ctx, -1);
+		break;
+	case DUK_HBUFFEROBJECT_ELEM_UINT16:
+		du.us[0] = (duk_uint16_t) duk_to_uint32(ctx, -1);
+		break;
+	case DUK_HBUFFEROBJECT_ELEM_INT16:
+		du.us[0] = (duk_uint16_t) duk_to_int32(ctx, -1);
+		break;
+	case DUK_HBUFFEROBJECT_ELEM_UINT32:
+		du.ui[0] = (duk_uint32_t) duk_to_uint32(ctx, -1);
+		break;
+	case DUK_HBUFFEROBJECT_ELEM_INT32:
+		du.ui[0] = (duk_uint32_t) duk_to_int32(ctx, -1);
+		break;
+	case DUK_HBUFFEROBJECT_ELEM_FLOAT32:
+		du.f[0] = (duk_float_t) duk_to_number(ctx, -1);
+		break;
+	case DUK_HBUFFEROBJECT_ELEM_FLOAT64:
+		du.d = (duk_double_t) duk_to_number(ctx, -1);
+		break;
+#endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
+	default:
+		DUK_UNREACHABLE();
 	}
-	DUK_ASSERT(hi > lo);
-	DUK_ASSERT(hi - lo + 1 >= 2);
 
-	/* randomized pivot selection */
-	p = lo + (duk_util_tinyrandom_get_bits(thr, 30) % (hi - lo + 1));  /* rnd in [lo,hi] */
-	DUK_ASSERT(p >= lo && p <= hi);
-	DUK_DDD(DUK_DDDPRINT("lo=%ld, hi=%ld, chose pivot p=%ld",
-	                     (long) lo, (long) hi, (long) p));
-
-	/* move pivot out of the way */
-	duk__array_sort_swap(ctx, p, lo);
-	p = lo;
-	DUK_DDD(DUK_DDDPRINT("pivot moved out of the way: %!T", (duk_tval *) duk_get_tval(ctx, 1)));
-
-	l = lo + 1;
-	r = hi;
-	for (;;) {
-		/* find elements to swap */
-		for (;;) {
-			DUK_DDD(DUK_DDDPRINT("left scan: l=%ld, r=%ld, p=%ld",
-			                     (long) l, (long) r, (long) p));
-			if (l >= hi) {
-				break;
-			}
-			if (duk__array_sort_compare(ctx, l, p) >= 0) {  /* !(l < p) */
-				break;
-			}
-			l++;
-		}
-		for (;;) {
-			DUK_DDD(DUK_DDDPRINT("right scan: l=%ld, r=%ld, p=%ld",
-			                     (long) l, (long) r, (long) p));
-			if (r <= lo) {
-				break;
-			}
-			if (duk__array_sort_compare(ctx, p, r) >= 0) {  /* !(p < r) */
-				break;
-			}
-			r--;
-		}
-		if (l >= r) {
-			goto done;
-		}
-		DUK_ASSERT(l < r);
+	DUK_MEMCPY((void *) p, (const void *) du.uc, (size_t) elem_size);
+}
 
-		DUK_DDD(DUK_DDDPRINT("swap %ld and %ld", (long) l, (long) r));
+/*
+ *  Duktape.Buffer: constructor
+ */
 
-		duk__array_sort_swap(ctx, l, r);
+DUK_INTERNAL duk_ret_t duk_bi_buffer_constructor(duk_context *ctx) {
+	duk_hthread *thr;
+	duk_size_t buf_size;
+	duk_small_int_t buf_dynamic;
+	duk_uint8_t *buf_data;
+	const duk_uint8_t *src_data;
 
-		DUK_DDD(DUK_DDDPRINT("after swap: %!T", (duk_tval *) duk_get_tval(ctx, 1)));
-		l++;
-		r--;
-	}
- done:
-	/* Note that 'l' and 'r' may cross, i.e. r < l */
-	DUK_ASSERT(l >= lo && l <= hi);
-	DUK_ASSERT(r >= lo && r <= hi);
+	thr = (duk_hthread *) ctx;
+	DUK_UNREF(thr);
 
-	/* XXX: there's no explicit recursion bound here now.  For the average
-	 * qsort recursion depth O(log n) that's not really necessary: e.g. for
-	 * 2**32 recursion depth would be about 32 which is OK.  However, qsort
-	 * worst case recursion depth is O(n) which may be a problem.
+	/*
+	 *  Constructor arguments are currently somewhat compatible with
+	 *  (keep it that way if possible):
+	 *
+	 *    http://nodejs.org/api/buffer.html
+	 *
+	 *  Note that the ToBuffer() coercion (duk_to_buffer()) does NOT match
+	 *  the constructor behavior.
 	 */
 
-	/* move pivot to its final place */
-	DUK_DDD(DUK_DDDPRINT("before final pivot swap: %!T", (duk_tval *) duk_get_tval(ctx, 1)));
-	duk__array_sort_swap(ctx, lo, r);	
+	buf_dynamic = duk_get_boolean(ctx, 1);  /* default to false */
+
+	switch (duk_get_type(ctx, 0)) {
+	case DUK_TYPE_NUMBER: {
+		/* new buffer of specified size */
+		buf_size = (duk_size_t) duk_to_int(ctx, 0);
+		(void) duk_push_buffer(ctx, buf_size, buf_dynamic);
+		break;
+	}
+	case DUK_TYPE_BUFFER: {
+		/* return input buffer, converted to a Duktape.Buffer object
+		 * if called as a constructor (no change if called as a
+		 * function).
+		 */
+		duk_set_top(ctx, 1);
+		break;
+	}
+	case DUK_TYPE_STRING: {
+		/* new buffer with string contents */
+		src_data = (const duk_uint8_t *) duk_get_lstring(ctx, 0, &buf_size);
+		DUK_ASSERT(src_data != NULL);  /* even for zero-length string */
+		buf_data = (duk_uint8_t *) duk_push_buffer(ctx, buf_size, buf_dynamic);
+		DUK_MEMCPY((void *) buf_data, (const void *) src_data, (size_t) buf_size);
+		break;
+	}
+	case DUK_TYPE_OBJECT: {
+		/* For all duk_hbufferobjects, get the plain buffer inside
+		 * without making a copy.  This is compatible with Duktape 1.2
+		 * but means that a slice/view information is ignored and the
+		 * full underlying buffer is returned.
+		 *
+		 * If called as a constructor, a new Duktape.Buffer object
+		 * pointing to the same plain buffer is created below.
+		 */
+		duk_hbufferobject *h_bufobj;
+		h_bufobj = (duk_hbufferobject *) duk_get_hobject(ctx, 0);
+		DUK_ASSERT(h_bufobj != NULL);
+		if (!DUK_HOBJECT_IS_BUFFEROBJECT((duk_hobject *) h_bufobj)) {
+			return DUK_RET_TYPE_ERROR;
+		}
+		if (h_bufobj->buf == NULL) {
+			return DUK_RET_TYPE_ERROR;
+		}
+		duk_push_hbuffer(ctx, h_bufobj->buf);
+		break;
+	}
+	case DUK_TYPE_NONE:
+	default: {
+		return DUK_RET_TYPE_ERROR;
+	}
+	}
+	DUK_ASSERT(duk_is_buffer(ctx, -1));
 
-#if defined(DUK_USE_DDDPRINT)
-	duk__debuglog_qsort_state(ctx, lo, hi, r);
-#endif
+	/* stack is unbalanced, but: [ <something> buf ] */
 
-	DUK_DDD(DUK_DDDPRINT("recurse: pivot=%ld, obj=%!T", (long) r, (duk_tval *) duk_get_tval(ctx, 1)));
-	duk__array_qsort(ctx, lo, r - 1);
-	duk__array_qsort(ctx, r + 1, hi);
-}
+	if (duk_is_constructor_call(ctx)) {
+		duk_hbufferobject *h_bufobj;
+		duk_hbuffer *h_val;
 
-duk_ret_t duk_bi_array_prototype_sort(duk_context *ctx) {
-	duk_uint32_t len;
+		h_val = duk_get_hbuffer(ctx, -1);
+		DUK_ASSERT(h_val != NULL);
 
-	/* XXX: len >= 0x80000000 won't work below because a signed type
-	 * is needed by qsort.
-	 */
-	len = duk__push_this_obj_len_u32_limited(ctx);
+		h_bufobj = duk_push_bufferobject_raw(ctx,
+		                                     DUK_HOBJECT_FLAG_EXTENSIBLE |
+		                                     DUK_HOBJECT_FLAG_BUFFEROBJECT |
+		                                     DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_BUFFER),
+		                                     DUK_BIDX_BUFFER_PROTOTYPE);
+		DUK_ASSERT(h_bufobj != NULL);
 
-	/* stack[0] = compareFn
-	 * stack[1] = ToObject(this)
-	 * stack[2] = ToUint32(length)
-	 */
+		duk__set_bufobj_buffer(ctx, h_bufobj, h_val);
 
-	if (len > 0) {
-		/* avoid degenerate cases, so that (len - 1) won't underflow */
-		duk__array_qsort(ctx, (duk_int_t) 0, (duk_int_t) (len - 1));
+		DUK_ASSERT_HBUFFEROBJECT_VALID(h_bufobj);
 	}
+	/* Note: unbalanced stack on purpose */
 
-	DUK_ASSERT_TOP(ctx, 3);
-	duk_pop(ctx);
-	return 1;  /* return ToObject(this) */
+	return 1;
 }
 
 /*
- *  splice()
+ *  Node.js Buffer: constructor
  */
 
-/* XXX: this compiles to over 500 bytes now, even without special handling
- * for an array part.  Uses signed ints so does not handle full array range correctly.
- */
+#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
+DUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_constructor(duk_context *ctx) {
+	/* Internal class is Object: Object.prototype.toString.call(new Buffer(0))
+	 * prints "[object Object]".
+	 */
+	duk_int_t len;
+	duk_int_t i;
+	duk_uint8_t *buf;
+	duk_hbuffer *h_buf;
+	duk_hbufferobject *h_bufobj;
+	duk_size_t buf_size;
 
-/* XXX: can shift() / unshift() use the same helper?
- *   shift() is (close to?) <--> splice(0, 1)
- *   unshift is (close to?) <--> splice(0, 0, [items])?
+	switch (duk_get_type(ctx, 0)) {
+	case DUK_TYPE_BUFFER: {
+		/* Custom behavior: plain buffer is used as internal buffer
+		 * without making a copy (matches Duktape.Buffer).
+		 */
+		duk_set_top(ctx, 1);  /* -> [ buffer ] */
+		break;
+	}
+	case DUK_TYPE_NUMBER: {
+		len = duk_to_int_clamped(ctx, 0, 0, DUK_INT_MAX);
+		buf = (duk_uint8_t *) duk_push_fixed_buffer(ctx, (duk_size_t) len);
+		break;
+	}
+	case DUK_TYPE_OBJECT: {
+		(void) duk_get_prop_string(ctx, 0, "length");
+		len = duk_to_int_clamped(ctx, -1, 0, DUK_INT_MAX);
+		duk_pop(ctx);
+		buf = (duk_uint8_t *) duk_push_fixed_buffer(ctx, (duk_size_t) len);
+		for (i = 0; i < len; i++) {
+			/* XXX: fast path for array arguments? */
+			duk_get_prop_index(ctx, 0, (duk_uarridx_t) i);
+			buf[i] = (duk_uint8_t) (duk_to_uint32(ctx, -1) & 0xffU);
+			duk_pop(ctx);
+		}
+		break;
+	}
+	case DUK_TYPE_STRING: {
+		/* ignore encoding for now */
+		duk_dup(ctx, 0);
+		buf = (duk_uint8_t *) duk_to_buffer(ctx, -1, &buf_size);
+		break;
+	}
+	default:
+		return DUK_RET_TYPE_ERROR;
+	}
+
+	DUK_ASSERT(duk_is_buffer(ctx, -1));
+	h_buf = duk_get_hbuffer(ctx, -1);
+	DUK_ASSERT(h_buf != NULL);
+
+	h_bufobj = duk_push_bufferobject_raw(ctx,
+	                                     DUK_HOBJECT_FLAG_EXTENSIBLE |
+	                                     DUK_HOBJECT_FLAG_BUFFEROBJECT |
+	                                     DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_BUFFER),
+	                                     DUK_BIDX_NODEJS_BUFFER_PROTOTYPE);
+	DUK_ASSERT(h_bufobj != NULL);
+
+	h_bufobj->buf = h_buf;
+	DUK_HBUFFER_INCREF(thr, h_buf);
+	DUK_ASSERT(h_bufobj->offset == 0);
+	h_bufobj->length = (duk_int_t) DUK_HBUFFER_GET_SIZE(h_buf);
+	DUK_ASSERT(h_bufobj->elem_type == DUK_HBUFFEROBJECT_ELEM_UINT8);
+
+	DUK_ASSERT_HBUFFEROBJECT_VALID(h_bufobj);
+
+	return 1;
+}
+#else  /* DUK_USE_BUFFEROBJECT_SUPPORT */
+DUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_constructor(duk_context *ctx) {
+	DUK_UNREF(ctx);
+	return DUK_RET_UNSUPPORTED_ERROR;
+}
+#endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
+
+/*
+ *  ArrayBuffer, DataView, and TypedArray constructors
  */
 
-duk_ret_t duk_bi_array_prototype_splice(duk_context *ctx) {
-	duk_idx_t nargs;
-	duk_uint32_t len;
-	duk_bool_t have_delcount;
-	duk_int_t item_count;
-	duk_int_t act_start;
-	duk_int_t del_count;
-	duk_int_t i, n;
+#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
+DUK_INTERNAL duk_ret_t duk_bi_arraybuffer_constructor(duk_context *ctx) {
+	duk_hthread *thr;
+	duk_hbufferobject *h_bufobj;
+	duk_hbuffer *h_val;
 
-	DUK_UNREF(have_delcount);
+	DUK_ASSERT_CTX_VALID(ctx);
+	thr = (duk_hthread *) ctx;
+	DUK_UNREF(thr);
 
-	nargs = duk_get_top(ctx);
-	if (nargs < 2) {
-		duk_set_top(ctx, 2);
-		nargs = 2;
-		have_delcount = 0;
-	} else {
-		have_delcount = 1;
+	/* XXX: function flag to make this automatic? */
+	if (!duk_is_constructor_call(ctx)) {
+		return DUK_RET_TYPE_ERROR;
 	}
 
-	/* XXX: len >= 0x80000000 won't work below because we need to be
-	 * able to represent -len.
-	 */
-	len = duk__push_this_obj_len_u32_limited(ctx);
+	if (duk_is_buffer(ctx, 0)) {
+		/* Custom behavior: plain buffer is used as internal buffer
+		 * without making a copy (matches Duktape.Buffer).
+		 */
 
-	act_start = duk_to_int_clamped(ctx, 0, -((duk_int_t) len), (duk_int_t) len);
-	if (act_start < 0) {
-		act_start = len + act_start;
-	}
-	DUK_ASSERT(act_start >= 0 && act_start <= (duk_int_t) len);
+		h_val = duk_get_hbuffer(ctx, 0);
+		DUK_ASSERT(h_val != NULL);
 
-#ifdef DUK_USE_NONSTD_ARRAY_SPLICE_DELCOUNT
-	if (have_delcount) {
-#endif
-		del_count = duk_to_int_clamped(ctx, 1, 0, len - act_start);
-#ifdef DUK_USE_NONSTD_ARRAY_SPLICE_DELCOUNT
+		/* XXX: accept any duk_hbufferobject type as an input also? */
 	} else {
-		/* E5.1 standard behavior when deleteCount is not given would be
-		 * to treat it just like if 'undefined' was given, which coerces
-		 * ultimately to 0.  Real world behavior is to splice to the end
-		 * of array, see test-bi-array-proto-splice-no-delcount.js.
+		duk_int_t len;
+		len = duk_to_int(ctx, 0);
+		if (len < 0) {
+			goto fail_length;
+		}
+		(void) duk_push_fixed_buffer(ctx, (duk_size_t) len);
+		h_val = (duk_hbuffer *) duk_get_hbuffer(ctx, -1);
+		DUK_ASSERT(h_val != NULL);
+
+#if !defined(DUK_USE_ZERO_BUFFER_DATA)
+		/* Khronos/ES6 requires zeroing even when DUK_USE_ZERO_BUFFER_DATA
+		 * is not set.
 		 */
-		del_count = len - act_start;
-	}
+		DUK_ASSERT(!DUK_HBUFFER_HAS_DYNAMIC((duk_hbuffer *) h_val));
+		DUK_MEMZERO((void *) DUK_HBUFFER_FIXED_GET_DATA_PTR(thr->heap, h_val), (duk_size_t) len);
 #endif
+	}
 
-	DUK_ASSERT(del_count >= 0 && del_count <= (duk_int_t) len - act_start);
-	DUK_ASSERT(del_count + act_start <= (duk_int_t) len);
+	h_bufobj = duk_push_bufferobject_raw(ctx,
+	                                     DUK_HOBJECT_FLAG_EXTENSIBLE |
+	                                     DUK_HOBJECT_FLAG_BUFFEROBJECT |
+	                                     DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_ARRAYBUFFER),
+	                                     DUK_BIDX_ARRAYBUFFER_PROTOTYPE);
+	DUK_ASSERT(h_bufobj != NULL);
 
-	duk_push_array(ctx);
+	duk__set_bufobj_buffer(ctx, h_bufobj, h_val);
+	DUK_ASSERT_HBUFFEROBJECT_VALID(h_bufobj);
 
-	/* stack[0] = start
-	 * stack[1] = deleteCount
-	 * stack[2...nargs-1] = items
-	 * stack[nargs] = ToObject(this)               -3
-	 * stack[nargs+1] = ToUint32(length)           -2
-	 * stack[nargs+2] = result array               -1
-	 */
+	return 1;
 
-	DUK_ASSERT_TOP(ctx, nargs + 3);
+ fail_length:
+	return DUK_RET_RANGE_ERROR;
+}
+#else  /* DUK_USE_BUFFEROBJECT_SUPPORT */
+DUK_INTERNAL duk_ret_t duk_bi_arraybuffer_constructor(duk_context *ctx) {
+	DUK_UNREF(ctx);
+	return DUK_RET_UNSUPPORTED_ERROR;
+}
+#endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
 
-	/* Step 9: copy elements-to-be-deleted into the result array */
 
-	for (i = 0; i < del_count; i++) {
-		if (duk_get_prop_index(ctx, -3, (duk_uarridx_t) (act_start + i))) {
-			duk_def_prop_index_wec(ctx, -2, i);  /* throw flag irrelevant (false in std alg) */
-		} else {
-			duk_pop(ctx);
-		}
+/* Format of magic, bits:
+ *   0...1: elem size shift (0-3)
+ *   2...5: elem type (DUK_HBUFFEROBJECT_ELEM_xxx)
+ */
+
+#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
+DUK_INTERNAL duk_ret_t duk_bi_typedarray_constructor(duk_context *ctx) {
+	duk_hthread *thr;
+	duk_tval *tv;
+	duk_hobject *h_obj;
+	duk_hbufferobject *h_bufobj = NULL;
+	duk_hbufferobject *h_bufarr = NULL;
+	duk_hbufferobject *h_bufarg = NULL;
+	duk_hbuffer *h_val;
+	duk_small_uint_t magic;
+	duk_small_uint_t shift;
+	duk_small_uint_t elem_type;
+	duk_small_uint_t elem_size;
+	duk_small_uint_t class_num;
+	duk_small_uint_t proto_bidx;
+	duk_uint_t align_mask;
+	duk_uint_t elem_length;
+	duk_int_t elem_length_signed;
+	duk_uint_t byte_length;
+	duk_small_uint_t copy_mode;
+
+	thr = (duk_hthread *) ctx;
+	DUK_UNREF(thr);
+
+	/* XXX: function flag to make this automatic? */
+	if (!duk_is_constructor_call(ctx)) {
+		return DUK_RET_TYPE_ERROR;
 	}
-	duk_push_u32(ctx, (duk_uint32_t) del_count);
-	duk_def_prop_stridx(ctx, -2, DUK_STRIDX_LENGTH, DUK_PROPDESC_FLAGS_W);
 
-	/* Steps 12 and 13: reorganize elements to make room for itemCount elements */
+	/* We could fit built-in index into magic but that'd make the magic
+	 * number dependent on built-in numbering (genbuiltins.py doesn't
+	 * handle that yet).  So map both class and prototype from the
+	 * element type.
+	 */
+	magic = duk_get_current_magic(ctx);
+	shift = magic & 0x03;               /* bits 0...1: shift */
+	elem_type = (magic >> 2) & 0x0f;    /* bits 2...5: type */
+	elem_size = 1 << shift;
+	align_mask = elem_size - 1;
+	DUK_ASSERT(elem_type < sizeof(duk__buffer_proto_from_elemtype) / sizeof(duk_uint8_t));
+	proto_bidx = duk__buffer_proto_from_elemtype[elem_type];
+	DUK_ASSERT(proto_bidx < DUK_NUM_BUILTINS);
+	DUK_ASSERT(elem_type < sizeof(duk__buffer_class_from_elemtype) / sizeof(duk_uint8_t));
+	class_num = duk__buffer_class_from_elemtype[elem_type];
 
-	DUK_ASSERT(nargs >= 2);
-	item_count = (duk_int_t) (nargs - 2);
-	if (item_count < del_count) {
-		/*    [ A B C D E F G H ]    rel_index = 2, del_count 3, item count 1
-		 * -> [ A B F G H ]          (conceptual intermediate step)
-		 * -> [ A B . F G H ]        (placeholder marked)
-		 *    [ A B C F G H ]        (actual result at this point, C will be replaced)
-		 */
+	DUK_DD(DUK_DDPRINT("typedarray constructor, magic=%d, shift=%d, elem_type=%d, "
+	                   "elem_size=%d, proto_bidx=%d, class_num=%d",
+	                   (int) magic, (int) shift, (int) elem_type, (int) elem_size,
+	                   (int) proto_bidx, (int) class_num));
 
-		DUK_ASSERT_TOP(ctx, nargs + 3);
+	/* Argument variants.  When the argument is an ArrayBuffer a view to
+	 * the same buffer is created; otherwise a new ArrayBuffer is always
+	 * created.
+	 */
 
-		n = len - del_count;
-		for (i = act_start; i < n; i++) {
-			if (duk_get_prop_index(ctx, -3, (duk_uarridx_t) (i + del_count))) {
-				duk_put_prop_index(ctx, -4, (duk_uarridx_t) (i + item_count));
+	tv = duk_get_tval(ctx, 0);
+	DUK_ASSERT(tv != NULL);  /* arg count */
+	if (DUK_TVAL_IS_OBJECT(tv)) {
+		h_obj = DUK_TVAL_GET_OBJECT(tv);
+		DUK_ASSERT(h_obj != NULL);
+
+		if (DUK_HOBJECT_GET_CLASS_NUMBER(h_obj) == DUK_HOBJECT_CLASS_ARRAYBUFFER) {
+			/* ArrayBuffer: unlike any other argument variant, create
+			 * a view into the existing buffer.
+			 */
+
+			duk_int_t byte_offset_signed;
+			duk_uint_t byte_offset;
+
+			h_bufarg = (duk_hbufferobject *) h_obj;
+
+			byte_offset_signed = duk_to_int(ctx, 1);
+			if (byte_offset_signed < 0) {
+				goto fail_arguments;
+			}
+			byte_offset = (duk_uint_t) byte_offset_signed;
+			if (byte_offset > h_bufarg->length ||
+			    (byte_offset & align_mask) != 0) {
+				/* Must be >= 0 and multiple of element size. */
+				goto fail_arguments;
+			}
+			if (duk_is_undefined(ctx, 2)) {
+				DUK_ASSERT(h_bufarg->length >= byte_offset);
+				byte_length = h_bufarg->length - byte_offset;
+				if ((byte_length & align_mask) != 0) {
+					/* Must be element size multiple from
+					 * start offset to end of buffer.
+					 */
+					goto fail_arguments;
+				}
+				elem_length = (byte_length >> shift);
 			} else {
-				duk_pop(ctx);
-				duk_del_prop_index(ctx, -3, (duk_uarridx_t) (i + item_count));
+				elem_length_signed = duk_to_int(ctx, 2);
+				if (elem_length_signed < 0) {
+					goto fail_arguments;
+				}
+				elem_length = (duk_uint_t) elem_length_signed;
+				byte_length = elem_length << shift;
+				if ((byte_length >> shift) != elem_length) {
+					/* Byte length would overflow. */
+					/* XXX: easier check with less code? */
+					goto fail_arguments;
+				}
+				DUK_ASSERT(h_bufarg->length >= byte_offset);
+				if (byte_length > h_bufarg->length - byte_offset) {
+					/* Not enough data. */
+					goto fail_arguments;
+				}
 			}
-		}
+			DUK_ASSERT_DISABLE(byte_offset >= 0);
+			DUK_ASSERT(byte_offset <= h_bufarg->length);
+			DUK_ASSERT_DISABLE(byte_length >= 0);
+			DUK_ASSERT(byte_offset + byte_length <= h_bufarg->length);
+			DUK_ASSERT((elem_length << shift) == byte_length);
+
+			h_bufobj = duk_push_bufferobject_raw(ctx,
+			                                     DUK_HOBJECT_FLAG_EXTENSIBLE |
+			                                     DUK_HOBJECT_FLAG_BUFFEROBJECT |
+			                                     DUK_HOBJECT_CLASS_AS_FLAGS(class_num),
+			                                     proto_bidx);
+			h_val = h_bufarg->buf;
+			if (h_val == NULL) {
+				return DUK_RET_TYPE_ERROR;
+			}
+			h_bufobj->buf = h_val;
+			DUK_HBUFFER_INCREF(thr, h_val);
+			h_bufobj->offset = h_bufarg->offset + byte_offset;
+			h_bufobj->length = byte_length;
+			h_bufobj->shift = (duk_uint8_t) shift;
+			h_bufobj->elem_type = (duk_uint8_t) elem_type;
+			h_bufobj->is_view = 1;
+			DUK_ASSERT_HBUFFEROBJECT_VALID(h_bufobj);
+
+			/* Set .buffer to the argument ArrayBuffer. */
+			duk_dup(ctx, 0);
+			duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_LC_BUFFER, DUK_PROPDESC_FLAGS_NONE);
+			duk_compact(ctx, -1);
+			return 1;
+		} else if (DUK_HOBJECT_IS_BUFFEROBJECT(h_obj)) {
+			/* TypedArray (or other non-ArrayBuffer duk_hbufferobject).
+			 * Conceptually same behavior as for an Array-like argument,
+			 * with a few fast paths.
+			 */
 
-		DUK_ASSERT_TOP(ctx, nargs + 3);
+			h_bufarg = (duk_hbufferobject *) h_obj;
+			DUK_ASSERT_HBUFFEROBJECT_VALID(h_bufarg);
+			elem_length_signed = (duk_int_t) (h_bufarg->length >> h_bufarg->shift);
+			if (h_bufarg->buf == NULL) {
+				return DUK_RET_TYPE_ERROR;
+			}
 
-		/* loop iterator init and limit changed from standard algorithm */
-		n = len - del_count + item_count;
-		for (i = len - 1; i >= n; i--) {
-			duk_del_prop_index(ctx, -3, (duk_uarridx_t) i);
-		}
+			/* Select copy mode.  Must take into account element
+			 * compatibility and validity of the underlying source
+			 * buffer.
+			 */
 
-		DUK_ASSERT_TOP(ctx, nargs + 3);
-	} else if (item_count > del_count) {
-		/*    [ A B C D E F G H ]    rel_index = 2, del_count 3, item count 4
-		 * -> [ A B F G H ]          (conceptual intermediate step)
-		 * -> [ A B . . . . F G H ]  (placeholder marked)
-		 *    [ A B C D E F F G H ]  (actual result at this point)
+			DUK_DDD(DUK_DDDPRINT("selecting copy mode for bufobj arg, "
+			                     "src byte_length=%ld, src shift=%d, "
+			                     "src/dst elem_length=%ld; "
+			                     "dst shift=%d -> dst byte_length=%ld",
+			                     (long) h_bufarg->length, (int) h_bufarg->shift,
+			                     (long) elem_length_signed, (int) shift,
+			                     (long) (elem_length_signed << shift)));
+
+			copy_mode = 2;  /* default is explicit index read/write copy */
+			DUK_ASSERT(elem_type < sizeof(duk__buffer_elemtype_copy_compatible) / sizeof(duk_uint16_t));
+			if (DUK_HBUFFEROBJECT_VALID_SLICE(h_bufarg)) {
+				if ((duk__buffer_elemtype_copy_compatible[elem_type] & (1 << h_bufarg->elem_type)) != 0) {
+					DUK_DDD(DUK_DDDPRINT("source/target are copy compatible, memcpy"));
+					DUK_ASSERT(shift == h_bufarg->shift);  /* byte sizes will match */
+					copy_mode = 0;
+				} else {
+					DUK_DDD(DUK_DDDPRINT("source/target not copy compatible but valid, fast copy"));
+					copy_mode = 1;
+				}
+			}
+		} else {
+			/* Array or Array-like */
+			elem_length_signed = (duk_int_t) duk_get_length(ctx, 0);
+			copy_mode = 2;
+		}
+	} else if (DUK_TVAL_IS_BUFFER(tv)) {
+		/* Accept plain buffer values like array initializers
+		 * (new in Duktape 1.4.0).
 		 */
+		duk_hbuffer *h_srcbuf;
+		h_srcbuf = DUK_TVAL_GET_BUFFER(tv);
+		elem_length_signed = (duk_int_t) DUK_HBUFFER_GET_SIZE(h_srcbuf);
+		copy_mode = 2;  /* XXX: could add fast path for u8 compatible views */
+	} else {
+		/* Non-object argument is simply int coerced, matches
+		 * V8 behavior (except for "null", which we coerce to
+		 * 0 but V8 TypeErrors).
+		 */
+		elem_length_signed = duk_to_int(ctx, 0);
+		copy_mode = 3;
+	}
+	if (elem_length_signed < 0) {
+		goto fail_arguments;
+	}
+	elem_length = (duk_uint_t) elem_length_signed;
+	byte_length = (duk_uint_t) (elem_length << shift);
+	if ((byte_length >> shift) != elem_length) {
+		/* Byte length would overflow. */
+		/* XXX: easier check with less code? */
+		goto fail_arguments;
+	}
+
+	DUK_DDD(DUK_DDDPRINT("elem_length=%ld, byte_length=%ld",
+	                     (long) elem_length, (long) byte_length));
+
+	/* ArrayBuffer argument is handled specially above; the rest of the
+	 * argument variants are handled by shared code below.
+	 */
+
+	/* Push a new ArrayBuffer (becomes view .buffer) */
+	h_bufarr = duk__push_arraybuffer_with_length(ctx, byte_length);
+	DUK_ASSERT(h_bufarr != NULL);
+	h_val = h_bufarr->buf;
+	DUK_ASSERT(h_val != NULL);
+
+	/* Push the resulting view object and attach the ArrayBuffer. */
+	h_bufobj = duk_push_bufferobject_raw(ctx,
+	                                     DUK_HOBJECT_FLAG_EXTENSIBLE |
+	                                     DUK_HOBJECT_FLAG_BUFFEROBJECT |
+	                                     DUK_HOBJECT_CLASS_AS_FLAGS(class_num),
+	                                     proto_bidx);
+
+	h_bufobj->buf = h_val;
+	DUK_HBUFFER_INCREF(thr, h_val);
+	DUK_ASSERT(h_bufobj->offset == 0);
+	h_bufobj->length = byte_length;
+	h_bufobj->shift = (duk_uint8_t) shift;
+	h_bufobj->elem_type = (duk_uint8_t) elem_type;
+	h_bufobj->is_view = 1;
+	DUK_ASSERT_HBUFFEROBJECT_VALID(h_bufobj);
+
+	/* Set .buffer */
+	duk_dup(ctx, -2);
+	duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_LC_BUFFER, DUK_PROPDESC_FLAGS_NONE);
+	duk_compact(ctx, -1);
 
-		DUK_ASSERT_TOP(ctx, nargs + 3);
+	/* Copy values, the copy method depends on the arguments.
+	 *
+	 * Copy mode decision may depend on the validity of the underlying
+	 * buffer of the source argument; there must be no harmful side effects
+	 * from there to here for copy_mode to still be valid.
+	 */
+	DUK_DDD(DUK_DDDPRINT("copy mode: %d", (int) copy_mode));
+	switch (copy_mode) {
+	case 0: {
+		/* Use byte copy. */
 
-		/* loop iterator init and limit changed from standard algorithm */
-		for (i = len - del_count - 1; i >= act_start; i--) {
-			if (duk_get_prop_index(ctx, -3, (duk_uarridx_t) (i + del_count))) {
-				duk_put_prop_index(ctx, -4, (duk_uarridx_t) (i + item_count));
-			} else {
-				duk_pop(ctx);
-				duk_del_prop_index(ctx, -3, (duk_uarridx_t) (i + item_count));
-			}
+		duk_uint8_t *p_src;
+		duk_uint8_t *p_dst;
+
+		DUK_ASSERT(h_bufobj != NULL);
+		DUK_ASSERT(h_bufobj->buf != NULL);
+		DUK_ASSERT(DUK_HBUFFEROBJECT_VALID_SLICE(h_bufobj));
+		DUK_ASSERT(h_bufarg != NULL);
+		DUK_ASSERT(h_bufarg->buf != NULL);
+		DUK_ASSERT(DUK_HBUFFEROBJECT_VALID_SLICE(h_bufarg));
+
+		p_dst = DUK_HBUFFEROBJECT_GET_SLICE_BASE(thr->heap, h_bufobj);
+		p_src = DUK_HBUFFEROBJECT_GET_SLICE_BASE(thr->heap, h_bufarg);
+
+		DUK_DDD(DUK_DDDPRINT("using memcpy: p_src=%p, p_dst=%p, byte_length=%ld",
+		                     (void *) p_src, (void *) p_dst, (long) byte_length));
+
+		DUK_MEMCPY((void *) p_dst, (const void *) p_src, (size_t) byte_length);
+		break;
+	}
+	case 1: {
+		/* Copy values through direct validated reads and writes. */
+
+		duk_small_uint_t src_elem_size;
+		duk_small_uint_t dst_elem_size;
+		duk_uint8_t *p_src;
+		duk_uint8_t *p_src_end;
+		duk_uint8_t *p_dst;
+
+		DUK_ASSERT(h_bufobj != NULL);
+		DUK_ASSERT(h_bufobj->buf != NULL);
+		DUK_ASSERT(DUK_HBUFFEROBJECT_VALID_SLICE(h_bufobj));
+		DUK_ASSERT(h_bufarg != NULL);
+		DUK_ASSERT(h_bufarg->buf != NULL);
+		DUK_ASSERT(DUK_HBUFFEROBJECT_VALID_SLICE(h_bufarg));
+
+		src_elem_size = 1 << h_bufarg->shift;
+		dst_elem_size = elem_size;
+
+		p_src = DUK_HBUFFEROBJECT_GET_SLICE_BASE(thr->heap, h_bufarg);
+		p_dst = DUK_HBUFFEROBJECT_GET_SLICE_BASE(thr->heap, h_bufobj);
+		p_src_end = p_src + h_bufarg->length;
+
+		DUK_DDD(DUK_DDDPRINT("using fast copy: p_src=%p, p_src_end=%p, p_dst=%p, "
+		                     "src_elem_size=%d, dst_elem_size=%d",
+		                     (void *) p_src, (void *) p_src_end, (void *) p_dst,
+		                     (int) src_elem_size, (int) dst_elem_size));
+
+		while (p_src != p_src_end) {
+			DUK_DDD(DUK_DDDPRINT("fast path per element copy loop: "
+			                     "p_src=%p, p_src_end=%p, p_dst=%p",
+			                     (void *) p_src, (void *) p_src_end, (void *) p_dst));
+			/* A validated read() is always a number, so it's write coercion
+			 * is always side effect free an won't invalidate pointers etc.
+			 */
+			duk_hbufferobject_push_validated_read(ctx, h_bufarg, p_src, src_elem_size);
+			duk_hbufferobject_validated_write(ctx, h_bufobj, p_dst, dst_elem_size);
+			duk_pop(ctx);
+			p_src += src_elem_size;
+			p_dst += dst_elem_size;
 		}
+		break;
+	}
+	case 2: {
+		/* Copy values by index reads and writes.  Let virtual
+		 * property handling take care of coercion.
+		 */
+		duk_uint_t i;
 
-		DUK_ASSERT_TOP(ctx, nargs + 3);
-	} else {
-		/*    [ A B C D E F G H ]    rel_index = 2, del_count 3, item count 3
-		 * -> [ A B F G H ]          (conceptual intermediate step)
-		 * -> [ A B . . . F G H ]    (placeholder marked)
-		 *    [ A B C D E F G H ]    (actual result at this point)
+		DUK_DDD(DUK_DDDPRINT("using slow copy"));
+
+		for (i = 0; i < elem_length; i++) {
+			duk_get_prop_index(ctx, 0, (duk_uarridx_t) i);
+			duk_put_prop_index(ctx, -2, (duk_uarridx_t) i);
+		}
+		break;
+	}
+	default:
+	case 3: {
+		/* No copy, leave zero bytes in the buffer.  There's no
+		 * ambiguity with Float32/Float64 because zero bytes also
+		 * represent 0.0.
+		 */
+#if !defined(DUK_USE_ZERO_BUFFER_DATA)
+		/* Khronos/ES6 requires zeroing even when DUK_USE_ZERO_BUFFER_DATA
+		 * is not set.
 		 */
+		DUK_ASSERT(!DUK_HBUFFER_HAS_DYNAMIC((duk_hbuffer *) h_val));
+		DUK_MEMZERO((void *) DUK_HBUFFER_FIXED_GET_DATA_PTR(thr->heap, h_val), (duk_size_t) byte_length);
+#endif
+
+		DUK_DDD(DUK_DDDPRINT("using no copy"));
+		break;
+	}
 	}
-	DUK_ASSERT_TOP(ctx, nargs + 3);
 
-	/* Step 15: insert itemCount elements into the hole made above */
+	return 1;
 
-	for (i = 0; i < item_count; i++) {
-		duk_dup(ctx, i + 2);  /* args start at index 2 */
-		duk_put_prop_index(ctx, -4, (duk_uarridx_t) (act_start + i));
+ fail_arguments:
+	return DUK_RET_RANGE_ERROR;
+}
+#else  /* DUK_USE_BUFFEROBJECT_SUPPORT */
+DUK_INTERNAL duk_ret_t duk_bi_typedarray_constructor(duk_context *ctx) {
+	DUK_UNREF(ctx);
+	return DUK_RET_UNSUPPORTED_ERROR;
+}
+#endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
+
+#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
+DUK_INTERNAL duk_ret_t duk_bi_dataview_constructor(duk_context *ctx) {
+	duk_hbufferobject *h_bufarg;
+	duk_hbufferobject *h_bufobj;
+	duk_hbuffer *h_val;
+	duk_uint_t offset;
+	duk_uint_t length;
+
+	/* XXX: function flag to make this automatic? */
+	if (!duk_is_constructor_call(ctx)) {
+		return DUK_RET_TYPE_ERROR;
 	}
 
-	/* Step 16: update length; note that the final length may be above 32 bit range */
+	h_bufarg = duk__require_bufobj_value(ctx, 0);
+	DUK_ASSERT(h_bufarg != NULL);
 
-	duk_push_number(ctx, ((duk_double_t) len) - ((duk_double_t) del_count) + ((duk_double_t) item_count));
-	duk_put_prop_stridx(ctx, -4, DUK_STRIDX_LENGTH);
+	duk__resolve_offset_opt_length(ctx, h_bufarg, 1, 2, &offset, &length, 1 /*throw_flag*/);
+	DUK_ASSERT(offset <= h_bufarg->length);
+	DUK_ASSERT(offset + length <= h_bufarg->length);
 
-	/* result array is already at the top of stack */
-	DUK_ASSERT_TOP(ctx, nargs + 3);
+	h_bufobj = duk_push_bufferobject_raw(ctx,
+	                                     DUK_HOBJECT_FLAG_EXTENSIBLE |
+	                                     DUK_HOBJECT_FLAG_BUFFEROBJECT |
+	                                     DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_DATAVIEW),
+	                                     DUK_BIDX_DATAVIEW_PROTOTYPE);
+
+	h_val = h_bufarg->buf;
+	if (h_val == NULL) {
+		return DUK_RET_TYPE_ERROR;
+	}
+	h_bufobj->buf = h_val;
+	DUK_HBUFFER_INCREF(thr, h_val);
+	h_bufobj->offset = h_bufarg->offset + offset;
+	h_bufobj->length = length;
+	DUK_ASSERT(h_bufobj->shift == 0);
+	DUK_ASSERT(h_bufobj->elem_type == DUK_HBUFFEROBJECT_ELEM_UINT8);
+	h_bufobj->is_view = 1;
+
+	/* The DataView .buffer property is ordinarily set to the argument
+	 * which is an ArrayBuffer.  We accept any duk_hbufferobject as
+	 * an argument and .buffer will be set to the argument regardless
+	 * of what it is.  This may be a bit confusing if the argument
+	 * is e.g. a DataView or another TypedArray view.
+	 *
+	 * XXX: Copy .buffer property from a DataView/TypedArray argument?
+	 * Create a fresh ArrayBuffer for Duktape.Buffer and Node.js Buffer
+	 * arguments?  See: test-bug-dataview-buffer-prop.js.
+	 */
+
+	duk_dup(ctx, 0);
+	duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_LC_BUFFER, DUK_PROPDESC_FLAGS_NONE);
+	duk_compact(ctx, -1);
+
+	DUK_ASSERT_HBUFFEROBJECT_VALID(h_bufobj);
 	return 1;
 }
+#else  /* DUK_USE_BUFFEROBJECT_SUPPORT */
+DUK_INTERNAL duk_ret_t duk_bi_dataview_constructor(duk_context *ctx) {
+	DUK_UNREF(ctx);
+	return DUK_RET_UNSUPPORTED_ERROR;
+}
+#endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
 
 /*
- *  reverse()
+ *  ArrayBuffer.isView()
  */
 
-duk_ret_t duk_bi_array_prototype_reverse(duk_context *ctx) {
-	duk_uint32_t len;
-	duk_uint32_t middle;
-	duk_uint32_t lower, upper;
-	duk_bool_t have_lower, have_upper;
+#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
+DUK_INTERNAL duk_ret_t duk_bi_arraybuffer_isview(duk_context *ctx) {
+	duk_hobject *h_obj;
+	duk_bool_t ret = 0;
 
-	len = duk__push_this_obj_len_u32(ctx);
-	middle = len / 2;
+	h_obj = duk_get_hobject(ctx, 0);
+	if (h_obj != NULL && DUK_HOBJECT_IS_BUFFEROBJECT(h_obj)) {
+		ret = ((duk_hbufferobject *) h_obj)->is_view;
+	}
+	duk_push_boolean(ctx, ret);
+	return 1;
+}
+#else  /* DUK_USE_BUFFEROBJECT_SUPPORT */
+DUK_INTERNAL duk_ret_t duk_bi_arraybuffer_isview(duk_context *ctx) {
+	DUK_UNREF(ctx);
+	return DUK_RET_UNSUPPORTED_ERROR;
+}
+#endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
 
-	/* If len <= 1, middle will be 0 and for-loop bails out
-	 * immediately (0 < 0 -> false).
-	 */
+/*
+ *  Node.js Buffer: toString([encoding], [start], [end])
+ */
 
-	for (lower = 0; lower < middle; lower++) {
-		DUK_ASSERT(len >= 2);
-		DUK_ASSERT_TOP(ctx, 2);
+#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
+DUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_tostring(duk_context *ctx) {
+	duk_hthread *thr;
+	duk_hbufferobject *h_this;
+	duk_int_t start_offset, end_offset;
+	duk_uint8_t *buf_slice;
+	duk_size_t slice_length;
 
-		DUK_ASSERT(len >= lower + 1);
-		upper = len - lower - 1;
+	thr = (duk_hthread *) ctx;
+	DUK_UNREF(thr);
 
-		have_lower = duk_get_prop_index(ctx, -2, (duk_uarridx_t) lower);
-		have_upper = duk_get_prop_index(ctx, -3, (duk_uarridx_t) upper);
+	h_this = duk__get_bufobj_this(ctx);
+	if (h_this == NULL) {
+		/* XXX: happens e.g. when evaluating: String(Buffer.prototype). */
+		duk_push_string(ctx, "[object Object]");
+		return 1;
+	}
+	DUK_ASSERT_HBUFFEROBJECT_VALID(h_this);
 
-		/* [ ToObject(this) ToUint32(length) lowerValue upperValue ] */
+	/* ignore encoding for now */
 
-		if (have_upper) {
-			duk_put_prop_index(ctx, -4, (duk_uarridx_t) lower);
-		} else {
-			duk_del_prop_index(ctx, -4, (duk_uarridx_t) lower);
-			duk_pop(ctx);
-		}
+	duk__clamp_startend_nonegidx_noshift(ctx, h_this, 1 /*idx_start*/, 2 /*idx_end*/, &start_offset, &end_offset);
 
-		if (have_lower) {
-			duk_put_prop_index(ctx, -3, (duk_uarridx_t) upper);
-		} else {
-			duk_del_prop_index(ctx, -3, (duk_uarridx_t) upper);
-			duk_pop(ctx);
-		}
+	slice_length = (duk_size_t) (end_offset - start_offset);
+	buf_slice = (duk_uint8_t *) duk_push_fixed_buffer(ctx, slice_length);
+	DUK_ASSERT(buf_slice != NULL);
 
-		DUK_ASSERT_TOP(ctx, 2);
+	if (h_this->buf == NULL) {
+		goto type_error;
 	}
 
-	DUK_ASSERT_TOP(ctx, 2);
-	duk_pop(ctx);  /* -> [ ToObject(this) ] */
+	if (DUK_HBUFFEROBJECT_VALID_BYTEOFFSET_EXCL(h_this, start_offset + slice_length)) {
+		DUK_MEMCPY((void *) buf_slice,
+		           (const void *) (DUK_HBUFFEROBJECT_GET_SLICE_BASE(thr->heap, h_this) + start_offset),
+		           (size_t) slice_length);
+	} else {
+		/* not covered, return all zeroes */
+		;
+	}
+
+	duk_to_string(ctx, -1);
 	return 1;
+
+ type_error:
+	return DUK_RET_TYPE_ERROR;
+}
+#else  /* DUK_USE_BUFFEROBJECT_SUPPORT */
+DUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_tostring(duk_context *ctx) {
+	DUK_UNREF(ctx);
+	return DUK_RET_UNSUPPORTED_ERROR;
 }
+#endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
 
 /*
- *  slice()
+ *  Duktape.Buffer: toString(), valueOf()
  */
 
-duk_ret_t duk_bi_array_prototype_slice(duk_context *ctx) {
-	duk_uint32_t len;
-	duk_int_t start, end;
-	duk_int_t i;
-	duk_uarridx_t idx;
-	duk_uint32_t res_length = 0;
+#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
+DUK_INTERNAL duk_ret_t duk_bi_buffer_prototype_tostring_shared(duk_context *ctx) {
+	duk_hthread *thr;
+	duk_tval *tv;
+	duk_small_int_t to_string = duk_get_current_magic(ctx);
 
-	/* XXX: len >= 0x80000000 won't work below because we need to be
-	 * able to represent -len.
-	 */
-	len = duk__push_this_obj_len_u32_limited(ctx);
-	duk_push_array(ctx);
+	thr = (duk_hthread *) ctx;
+	DUK_UNREF(thr);
 
-	/* stack[0] = start
-	 * stack[1] = end
-	 * stack[2] = ToObject(this)
-	 * stack[3] = ToUint32(length)
-	 * stack[4] = result array
-	 */
+	tv = duk_get_borrowed_this_tval(ctx);
+	DUK_ASSERT(tv != NULL);
 
-	start = duk_to_int_clamped(ctx, 0, -((duk_int_t) len), (duk_int_t) len);
-	if (start < 0) {
-		start = len + start;
-	}
-	/* XXX: could duk_is_undefined() provide defaulting undefined to 'len'
-	 * (the upper limit)?
-	 */
-	if (duk_is_undefined(ctx, 1)) {
-		end = len;
-	} else {
-		end = duk_to_int_clamped(ctx, 1, -((duk_int_t) len), (duk_int_t) len);
-		if (end < 0) {
-			end = len + end;
+	if (DUK_TVAL_IS_BUFFER(tv)) {
+		duk_hbuffer *h_buf;
+		h_buf = DUK_TVAL_GET_BUFFER(tv);
+		DUK_ASSERT(h_buf != NULL);
+		duk_push_hbuffer(ctx, h_buf);
+	} else if (DUK_TVAL_IS_OBJECT(tv)) {
+		duk_hobject *h;
+		duk_hbufferobject *h_bufobj;
+
+		/* Accept any duk_hbufferobject, though we're only normally
+		 * called for Duktape.Buffer values.
+		 */
+		h = DUK_TVAL_GET_OBJECT(tv);
+		DUK_ASSERT(h != NULL);
+		if (!DUK_HOBJECT_IS_BUFFEROBJECT(h)) {
+			DUK_DD(DUK_DDPRINT("toString/valueOf() called for a non-bufferobject object"));
+			goto type_error;
 		}
-	}
-	DUK_ASSERT(start >= 0 && (duk_uint32_t) start <= len);
-	DUK_ASSERT(end >= 0 && (duk_uint32_t) end <= len);
+		h_bufobj = (duk_hbufferobject *) h;
+		DUK_ASSERT_HBUFFEROBJECT_VALID(h_bufobj);
 
-	idx = 0;
-	for (i = start; i < end; i++) {
-		DUK_ASSERT_TOP(ctx, 5);
-		if (duk_get_prop_index(ctx, 2, (duk_uarridx_t) i)) {
-			duk_def_prop_index_wec(ctx, 4, idx);
-			res_length = idx + 1;
-		} else {
-			duk_pop(ctx);
+		if (h_bufobj->buf == NULL) {
+			DUK_DD(DUK_DDPRINT("toString/valueOf() called for a bufferobject with NULL buf"));
+			goto type_error;
 		}
-		idx++;
-		DUK_ASSERT_TOP(ctx, 5);
+		duk_push_hbuffer(ctx, h_bufobj->buf);
+	} else {
+		goto type_error;
 	}
 
-	duk_push_u32(ctx, res_length);
-	duk_def_prop_stridx(ctx, 4, DUK_STRIDX_LENGTH, DUK_PROPDESC_FLAGS_W);
-
-	DUK_ASSERT_TOP(ctx, 5);
+	if (to_string) {
+		duk_to_string(ctx, -1);
+	}
 	return 1;
+
+ type_error:
+	return DUK_RET_TYPE_ERROR;
+}
+#else  /* DUK_USE_BUFFEROBJECT_SUPPORT */
+DUK_INTERNAL duk_ret_t duk_bi_buffer_prototype_tostring_shared(duk_context *ctx) {
+	DUK_UNREF(ctx);
+	return DUK_RET_UNSUPPORTED_ERROR;
 }
+#endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
 
 /*
- *  shift()
+ *  Node.js Buffer.prototype: toJSON()
  */
 
-duk_ret_t duk_bi_array_prototype_shift(duk_context *ctx) {
-	duk_uint32_t len;
-	duk_uint32_t i;
+#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
+DUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_tojson(duk_context *ctx) {
+	duk_hthread *thr;
+	duk_hbufferobject *h_this;
+	duk_uint8_t *buf;
+	duk_uint_t i;
 
-	len = duk__push_this_obj_len_u32(ctx);
-	if (len == 0) {
-		duk_push_int(ctx, 0);
-		duk_put_prop_stridx(ctx, 0, DUK_STRIDX_LENGTH);
-		return 0;
-	}
+	thr = (duk_hthread *) ctx;
+	DUK_UNREF(thr);
+	h_this = duk__require_bufobj_this(ctx);
+	DUK_ASSERT(h_this != NULL);
 
-	duk_get_prop_index(ctx, 0, 0);
+	if (h_this->buf == NULL || !DUK_HBUFFEROBJECT_VALID_SLICE(h_this)) {
+		/* Serialize uncovered backing buffer as a null; doesn't
+		 * really matter as long we're memory safe.
+		 */
+		duk_push_null(ctx);
+		return 1;
+	}
 
-	/* stack[0] = object (this)
-	 * stack[1] = ToUint32(length)
-	 * stack[2] = elem at index 0 (retval)
-	 */
+	duk_push_object(ctx);
+	duk_push_hstring_stridx(ctx, DUK_STRIDX_UC_BUFFER);
+	duk_put_prop_stridx(ctx, -2, DUK_STRIDX_TYPE);
 
-	for (i = 1; i < len; i++) {
-		DUK_ASSERT_TOP(ctx, 3);
-		if (duk_get_prop_index(ctx, 0, (duk_uarridx_t) i)) {
-			/* fromPresent = true */
-			duk_put_prop_index(ctx, 0, (duk_uarridx_t) (i - 1));
-		} else {
-			/* fromPresent = false */
-			duk_del_prop_index(ctx, 0, (duk_uarridx_t) (i - 1));
-			duk_pop(ctx);
-		}
+	duk_push_array(ctx);
+	for (i = 0; i < h_this->length; i++) {
+		/* XXX: regetting the pointer may be overkill - we're writing
+		 * to a side-effect free array here.
+		 */
+		DUK_ASSERT(h_this->buf != NULL);
+		buf = DUK_HBUFFEROBJECT_GET_SLICE_BASE(thr->heap, h_this);
+		duk_push_uint(ctx, (duk_uint_t) buf[i]);
+		duk_put_prop_index(ctx, -2, (duk_idx_t) i);
 	}
-	duk_del_prop_index(ctx, 0, (duk_uarridx_t) (len - 1));
-
-	duk_push_u32(ctx, (duk_uint32_t) (len - 1));
-	duk_put_prop_stridx(ctx, 0, DUK_STRIDX_LENGTH);
+	duk_put_prop_stridx(ctx, -2, DUK_STRIDX_DATA);
 
-	DUK_ASSERT_TOP(ctx, 3);
 	return 1;
 }
+#else  /* DUK_USE_BUFFEROBJECT_SUPPORT */
+DUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_tojson(duk_context *ctx) {
+	DUK_UNREF(ctx);
+	return DUK_RET_UNSUPPORTED_ERROR;
+}
+#endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
 
 /*
- *  unshift()
+ *  Node.js Buffer.prototype.equals()
+ *  Node.js Buffer.prototype.compare()
+ *  Node.js Buffer.compare()
  */
 
-duk_ret_t duk_bi_array_prototype_unshift(duk_context *ctx) {
-	duk_idx_t nargs;
-	duk_uint32_t len;
-	duk_uint32_t i;
-	duk_double_t final_len;
-
-	nargs = duk_get_top(ctx);
-	len = duk__push_this_obj_len_u32(ctx);
+#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
+DUK_INTERNAL duk_ret_t duk_bi_buffer_compare_shared(duk_context *ctx) {
+	duk_hthread *thr;
+	duk_small_uint_t magic;
+	duk_hbufferobject *h_bufarg1;
+	duk_hbufferobject *h_bufarg2;
+	duk_small_int_t comp_res;
 
-	/* stack[0...nargs-1] = unshift args (vararg)
-	 * stack[nargs] = ToObject(this)
-	 * stack[nargs+1] = ToUint32(length)
-	 */
+	thr = (duk_hthread *) ctx;
+	DUK_UNREF(thr);
 
-	DUK_ASSERT_TOP(ctx, nargs + 2);
+	magic = duk_get_current_magic(ctx);
+	if (magic & 0x02) {
+		/* Static call style. */
+		h_bufarg1 = duk__require_bufobj_value(ctx, 0);
+		h_bufarg2 = duk__require_bufobj_value(ctx, 1);
+	} else {
+		h_bufarg1 = duk__require_bufobj_this(ctx);
+		h_bufarg2 = duk__require_bufobj_value(ctx, 0);
+	}
+	DUK_ASSERT(h_bufarg1 != NULL);
+	DUK_ASSERT(h_bufarg2 != NULL);
 
-	/* Note: unshift() may operate on indices above unsigned 32-bit range
-	 * and the final length may be >= 2**32.  Hence we use 'double' vars
-	 * here, when appropriate.
+	/* We want to compare the slice/view areas of the arguments.
+	 * If either slice/view is invalid (underlying buffer is shorter)
+	 * ensure equals() is false, but otherwise the only thing that
+	 * matters is to be memory safe.
 	 */
 
-	i = len;
-	while (i > 0) {
-		DUK_ASSERT_TOP(ctx, nargs + 2);
-		i--;
-		/* k+argCount-1; note that may be above 32-bit range */
-		duk_push_number(ctx, ((duk_double_t) i) + ((duk_double_t) nargs));
-		if (duk_get_prop_index(ctx, -3, (duk_uarridx_t) i)) {
-			/* fromPresent = true */
-			/* [ ... ToObject(this) ToUint32(length) to val ] */
-			duk_put_prop(ctx, -4);  /* -> [ ... ToObject(this) ToUint32(length) ] */
-		} else {
-			/* fromPresent = false */
-			/* [ ... ToObject(this) ToUint32(length) to val ] */
-			duk_pop(ctx);
-			duk_del_prop(ctx, -3);  /* -> [ ... ToObject(this) ToUint32(length) ] */
-		}
-		DUK_ASSERT_TOP(ctx, nargs + 2);
+	if (DUK_HBUFFEROBJECT_VALID_SLICE(h_bufarg1) &&
+	    DUK_HBUFFEROBJECT_VALID_SLICE(h_bufarg2)) {
+		comp_res = duk_js_data_compare((const duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h_bufarg1->buf) + h_bufarg1->offset,
+		                               (const duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h_bufarg2->buf) + h_bufarg2->offset,
+		                               (duk_size_t) h_bufarg1->length,
+		                               (duk_size_t) h_bufarg2->length);
+	} else {
+		comp_res = -1;  /* either nonzero value is ok */
 	}
 
-	for (i = 0; i < (duk_uint32_t) nargs; i++) {
-		DUK_ASSERT_TOP(ctx, nargs + 2);
-		duk_dup(ctx, i);  /* -> [ ... ToObject(this) ToUint32(length) arg[i] ] */
-		duk_put_prop_index(ctx, -3, (duk_uarridx_t) i);
-		DUK_ASSERT_TOP(ctx, nargs + 2);
+	if (magic & 0x01) {
+		/* compare: similar to string comparison but for buffer data. */
+		duk_push_int(ctx, comp_res);
+	} else {
+		/* equals */
+		duk_push_boolean(ctx, (comp_res == 0));
 	}
 
-	DUK_ASSERT_TOP(ctx, nargs + 2);
-	final_len = ((duk_double_t) len) + ((duk_double_t) nargs);
-	duk_push_number(ctx, final_len);
-	duk_dup_top(ctx);  /* -> [ ... ToObject(this) ToUint32(length) final_len final_len ] */
-	duk_put_prop_stridx(ctx, -4, DUK_STRIDX_LENGTH);
 	return 1;
 }
+#else  /* DUK_USE_BUFFEROBJECT_SUPPORT */
+DUK_INTERNAL duk_ret_t duk_bi_buffer_compare_shared(duk_context *ctx) {
+	DUK_UNREF(ctx);
+	return DUK_RET_UNSUPPORTED_ERROR;
+}
+#endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
 
 /*
- *  indexOf(), lastIndexOf()
+ *  Node.js Buffer.prototype.fill()
  */
 
-duk_ret_t duk_bi_array_prototype_indexof_shared(duk_context *ctx) {
-	duk_idx_t nargs;
-	duk_int_t i, len;
-	duk_int_t from_index;
-	duk_small_int_t idx_step = duk_get_magic(ctx);  /* idx_step is +1 for indexOf, -1 for lastIndexOf */
-
-	/* lastIndexOf() needs to be a vararg function because we must distinguish
-	 * between an undefined fromIndex and a "not given" fromIndex; indexOf() is
-	 * made vararg for symmetry although it doesn't strictly need to be.
-	 */
-
-	nargs = duk_get_top(ctx);
-	duk_set_top(ctx, 2);
-
-	/* XXX: must be able to represent -len */
-	len = (duk_int_t) duk__push_this_obj_len_u32_limited(ctx);
-	if (len == 0) {
-		goto not_found;
+#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
+DUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_fill(duk_context *ctx) {
+	duk_hthread *thr;
+	duk_hbufferobject *h_this;
+	const duk_uint8_t *fill_str_ptr;
+	duk_size_t fill_str_len;
+	duk_uint8_t fill_value;
+	duk_int_t fill_offset;
+	duk_int_t fill_end;
+	duk_size_t fill_length;
+	duk_uint8_t *p;
+
+	thr = (duk_hthread *) ctx;
+	DUK_UNREF(thr);
+
+	h_this = duk__require_bufobj_this(ctx);
+	DUK_ASSERT(h_this != NULL);
+	if (h_this->buf == NULL) {
+		return DUK_RET_TYPE_ERROR;
 	}
 
-	/* Index clamping is a bit tricky, we must ensure that we'll only iterate
-	 * through elements that exist and that the specific requirements from E5.1
-	 * Sections 15.4.4.14 and 15.4.4.15 are fulfilled; especially:
-	 *
-	 *   - indexOf: clamp to [-len,len], negative handling -> [0,len],
-	 *     if clamped result is len, for-loop bails out immediately
-	 *
-	 *   - lastIndexOf: clamp to [-len-1, len-1], negative handling -> [-1, len-1],
-	 *     if clamped result is -1, for-loop bails out immediately
-	 *
-	 * If fromIndex is not given, ToInteger(undefined) = 0, which is correct
-	 * for indexOf() but incorrect for lastIndexOf().  Hence special handling,
-	 * and why lastIndexOf() needs to be a vararg function.
-	 */
+	/* [ value offset end ] */
 
-	if (nargs >= 2) {
-		/* indexOf: clamp fromIndex to [-len, len]
-		 * (if fromIndex == len, for-loop terminates directly)
-		 *
-		 * lastIndexOf: clamp fromIndex to [-len - 1, len - 1]
-		 * (if clamped to -len-1 -> fromIndex becomes -1, terminates for-loop directly)
-		 */
-		from_index = duk_to_int_clamped(ctx,
-		                                1,
-		                                (idx_step > 0 ? -len : -len - 1),
-		                                (idx_step > 0 ? len : len - 1));
-		if (from_index < 0) {
-			/* for lastIndexOf, result may be -1 (mark immediate termination) */
-			from_index = len + from_index;
-		}
+	if (duk_is_string(ctx, 0)) {
+		fill_str_ptr = (const duk_uint8_t *) duk_get_lstring(ctx, 0, &fill_str_len);
+		DUK_ASSERT(fill_str_ptr != NULL);
 	} else {
-		/* for indexOf, ToInteger(undefined) would be 0, i.e. correct, but
-		 * handle both indexOf and lastIndexOf specially here.
-		 */
-		if (idx_step > 0) {
-			from_index = 0;
-		} else {
-			from_index = len - 1;
-		}
+		fill_value = (duk_uint8_t) duk_to_uint32(ctx, 0);
+		fill_str_ptr = (const duk_uint8_t *) &fill_value;
+		fill_str_len = 1;
 	}
 
-	/* stack[0] = searchElement
-	 * stack[1] = fromIndex
-	 * stack[2] = object
-	 * stack[3] = length (not needed, but not popped above)
-	 */
+	/* Fill offset handling is more lenient than in Node.js. */
 
-	for (i = from_index; i >= 0 && i < len; i += idx_step) {
-		DUK_ASSERT_TOP(ctx, 4);
+	duk__clamp_startend_nonegidx_noshift(ctx, h_this, 1 /*idx_start*/, 2 /*idx_end*/, &fill_offset, &fill_end);
 
-		if (duk_get_prop_index(ctx, 2, (duk_uarridx_t) i)) {
-			DUK_ASSERT_TOP(ctx, 5);
-			if (duk_strict_equals(ctx, 0, 4)) {
-				duk_push_int(ctx, i);
-				return 1;
+	DUK_DDD(DUK_DDDPRINT("fill: fill_value=%02x, fill_offset=%ld, fill_end=%ld, view length=%ld",
+	                     (unsigned int) fill_value, (long) fill_offset, (long) fill_end, (long) h_this->length));
+
+	DUK_ASSERT(fill_end - fill_offset >= 0);
+	DUK_ASSERT(h_this->buf != NULL);
+
+	p = (DUK_HBUFFEROBJECT_GET_SLICE_BASE(thr->heap, h_this) + fill_offset);
+	fill_length = (duk_size_t) (fill_end - fill_offset);
+	if (fill_str_len == 1) {
+		/* Handle single character fills as memset() even when
+		 * the fill data comes from a one-char argument.
+		 */
+		DUK_MEMSET((void *) p, (int) fill_str_ptr[0], (size_t) fill_length);
+	} else if (fill_str_len > 1) {
+		duk_size_t i, n, t;
+
+		for (i = 0, n = (fill_end - fill_offset), t = 0; i < n; i++) {
+			p[i] = fill_str_ptr[t++];
+			if (t >= fill_str_len) {
+				t = 0;
 			}
 		}
-
-		duk_pop(ctx);
+	} else {
+		DUK_DDD(DUK_DDDPRINT("zero size fill pattern, ignore silently"));
 	}
 
- not_found:
-	duk_push_int(ctx, -1);
+	/* Return the Buffer to allow chaining: b.fill(0x11).fill(0x22, 3, 5).toString() */
+	duk_push_this(ctx);
 	return 1;
 }
+#else  /* DUK_USE_BUFFEROBJECT_SUPPORT */
+DUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_fill(duk_context *ctx) {
+	DUK_UNREF(ctx);
+	return DUK_RET_UNSUPPORTED_ERROR;
+}
+#endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
 
 /*
- *  every(), some(), forEach(), map(), filter()
+ *  Node.js Buffer.prototype.write(string, [offset], [length], [encoding])
  */
 
-#define DUK__ITER_EVERY    0
-#define DUK__ITER_SOME     1
-#define DUK__ITER_FOREACH  2
-#define DUK__ITER_MAP      3
-#define DUK__ITER_FILTER   4
+#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
+DUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_write(duk_context *ctx) {
+	duk_hthread *thr;
+	duk_hbufferobject *h_this;
+	duk_uint_t offset;
+	duk_uint_t length;
+	const duk_uint8_t *str_data;
+	duk_size_t str_len;
 
-/* XXX: This helper is a bit awkward because the handling for the different iteration
- * callers is quite different.  This now compiles to a bit less than 500 bytes, so with
- * 5 callers the net result is about 100 bytes / caller.
- */
+	thr = (duk_hthread *) ctx;
+	DUK_UNREF(thr);
 
-duk_ret_t duk_bi_array_prototype_iter_shared(duk_context *ctx) {
-	duk_uint32_t len;
-	duk_uint32_t i;
-	duk_uarridx_t k;
-	duk_bool_t bval;
-	duk_small_int_t iter_type = duk_get_magic(ctx);
-	duk_uint32_t res_length = 0;
+	h_this = duk__require_bufobj_this(ctx);
+	DUK_ASSERT(h_this != NULL);
 
-	/* each call this helper serves has nargs==2 */
-	DUK_ASSERT_TOP(ctx, 2);
+	/* Argument must be a string, e.g. a buffer is not allowed. */
+	str_data = (const duk_uint8_t *) duk_require_lstring(ctx, 0, &str_len);
 
-	len = duk__push_this_obj_len_u32(ctx);
-	if (!duk_is_callable(ctx, 0)) {
-		goto type_error;
+	duk__resolve_offset_opt_length(ctx, h_this, 1, 2, &offset, &length, 0 /*throw_flag*/);
+	DUK_ASSERT(offset <= h_this->length);
+	DUK_ASSERT(offset + length <= h_this->length);
+
+	/* XXX: encoding is ignored now. */
+
+	if (length > str_len) {
+		length = (duk_uint_t) str_len;
 	}
-	/* if thisArg not supplied, behave as if undefined was supplied */
 
-	if (iter_type == DUK__ITER_MAP || iter_type == DUK__ITER_FILTER) {
-		duk_push_array(ctx);
+	if (DUK_HBUFFEROBJECT_VALID_SLICE(h_this)) {
+		/* Cannot overlap. */
+		DUK_MEMCPY((void *) (DUK_HBUFFEROBJECT_GET_SLICE_BASE(thr->heap, h_this) + offset),
+		           (const void *) str_data,
+		           (size_t) length);
 	} else {
-		duk_push_undefined(ctx);
+		DUK_DDD(DUK_DDDPRINT("write() target buffer is not covered, silent ignore"));
 	}
 
-	/* stack[0] = callback
-	 * stack[1] = thisArg
-	 * stack[2] = object
-	 * stack[3] = ToUint32(length)  (unused, but avoid unnecessary pop)
-	 * stack[4] = result array (or undefined)
-	 */
-
-	k = 0;  /* result index for filter() */
-	for (i = 0; i < len; i++) {
-		DUK_ASSERT_TOP(ctx, 5);
+	duk_push_uint(ctx, length);
+	return 1;
+}
+#else  /* DUK_USE_BUFFEROBJECT_SUPPORT */
+DUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_write(duk_context *ctx) {
+	DUK_UNREF(ctx);
+	return DUK_RET_UNSUPPORTED_ERROR;
+}
+#endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
 
-		if (!duk_get_prop_index(ctx, 2, (duk_uarridx_t) i)) {
-			duk_pop(ctx);
-			continue;
-		}
+/*
+ *  Node.js Buffer.prototype.copy()
+ */
 
-		/* The original value needs to be preserved for filter(), hence
-		 * this funny order.  We can't re-get the value because of side
-		 * effects.
-		 */
+#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
+DUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_copy(duk_context *ctx) {
+	duk_hthread *thr;
+	duk_hbufferobject *h_this;
+	duk_hbufferobject *h_bufarg;
+	duk_int_t source_length;
+	duk_int_t target_length;
+	duk_int_t target_start, source_start, source_end;
+	duk_uint_t target_ustart, source_ustart, source_uend;
+	duk_uint_t copy_size = 0;
 
-		duk_dup(ctx, 0);
-		duk_dup(ctx, 1);
-		duk_dup(ctx, -3);
-		duk_push_u32(ctx, i);
-		duk_dup(ctx, 2);  /* [ ... val callback thisArg val i obj ] */
-		duk_call_method(ctx, 3); /* -> [ ... val retval ] */
+	/* [ targetBuffer targetStart sourceStart sourceEnd ] */
 
-		switch (iter_type) {
-		case DUK__ITER_EVERY:
-			bval = duk_to_boolean(ctx, -1);
-			if (!bval) {
-				/* stack top contains 'false' */
-				return 1;
-			}
-			break;
-		case DUK__ITER_SOME:
-			bval = duk_to_boolean(ctx, -1);
-			if (bval) {
-				/* stack top contains 'true' */
-				return 1;
-			}
-			break;
-		case DUK__ITER_FOREACH:
-			/* nop */
-			break;
-		case DUK__ITER_MAP:
-			duk_dup(ctx, -1);
-			duk_def_prop_index_wec(ctx, 4, (duk_uarridx_t) i);  /* retval to result[i] */
-			res_length = i + 1;
-			break;
-		case DUK__ITER_FILTER:
-			bval = duk_to_boolean(ctx, -1);
-			if (bval) {
-				duk_dup(ctx, -2);  /* orig value */
-				duk_def_prop_index_wec(ctx, 4, (duk_uarridx_t) k);
-				k++;
-				res_length = k;
-			}
-			break;
-		default:
-			DUK_UNREACHABLE();
-			break;
-		}
-		duk_pop_2(ctx);
+	thr = (duk_hthread *) ctx;
+	DUK_UNREF(thr);
 
-		DUK_ASSERT_TOP(ctx, 5);
+	h_this = duk__require_bufobj_this(ctx);
+	h_bufarg = duk__require_bufobj_value(ctx, 0);
+	DUK_ASSERT(h_this != NULL);
+	DUK_ASSERT(h_bufarg != NULL);
+	source_length = (duk_int_t) h_this->length;
+	target_length = (duk_int_t) h_bufarg->length;
+
+	target_start = duk_to_int(ctx, 1);
+	source_start = duk_to_int(ctx, 2);
+	if (duk_is_undefined(ctx, 3)) {
+		source_end = source_length;
+	} else {
+		source_end = duk_to_int(ctx, 3);
 	}
 
-	switch (iter_type) {
-	case DUK__ITER_EVERY:
-		duk_push_true(ctx);
-		break;
-	case DUK__ITER_SOME:
-		duk_push_false(ctx);
-		break;
-	case DUK__ITER_FOREACH:
-		duk_push_undefined(ctx);
-		break;
-	case DUK__ITER_MAP:
-	case DUK__ITER_FILTER:
-		DUK_ASSERT_TOP(ctx, 5);
-		DUK_ASSERT(duk_is_array(ctx, -1));  /* topmost element is the result array already */
-		duk_push_u32(ctx, res_length);
-		duk_def_prop_stridx(ctx, -2, DUK_STRIDX_LENGTH, DUK_PROPDESC_FLAGS_W);
-		break;
-	default:
-		DUK_UNREACHABLE();
-		break;
+	DUK_DDD(DUK_DDDPRINT("checking copy args: target_start=%ld, target_length=%ld, "
+	                     "source_start=%ld, source_end=%ld, source_length=%ld",
+	                     (long) target_start, (long) h_bufarg->length,
+	                     (long) source_start, (long) source_end, (long) source_length));
+
+	/* This behavior mostly mimics Node.js now. */
+
+	if (source_start < 0 || source_end < 0 || target_start < 0) {
+		/* Negative offsets cause a RangeError. */
+		goto fail_bounds;
+	}
+	source_ustart = (duk_uint_t) source_start;
+	source_uend = (duk_uint_t) source_end;
+	target_ustart = (duk_uint_t) target_start;
+	if (source_ustart >= source_uend ||  /* crossed offsets or zero size */
+	    source_ustart >= (duk_uint_t) source_length ||  /* source out-of-bounds (but positive) */
+	    target_ustart >= (duk_uint_t) target_length) {  /* target out-of-bounds (but positive) */
+		goto silent_ignore;
+	}
+	if (source_uend >= (duk_uint_t) source_length) {
+		/* Source end clamped silently to available length. */
+		source_uend = source_length;
+	}
+	copy_size = source_uend - source_ustart;
+	if (target_ustart + copy_size > (duk_uint_t) target_length) {
+		/* Clamp to target's end if too long.
+		 *
+		 * NOTE: there's no overflow possibility in the comparison;
+		 * both target_ustart and copy_size are >= 0 and based on
+		 * values in duk_int_t range.  Adding them as duk_uint_t
+		 * values is then guaranteed not to overflow.
+		 */
+		DUK_ASSERT(target_ustart + copy_size >= target_ustart);  /* no overflow */
+		DUK_ASSERT(target_ustart + copy_size >= copy_size);  /* no overflow */
+		copy_size = (duk_uint_t) target_length - target_ustart;
+	}
+
+	DUK_DDD(DUK_DDDPRINT("making copy: target_ustart=%lu source_ustart=%lu copy_size=%lu",
+	                     (unsigned long) target_ustart, (unsigned long) source_ustart,
+	                     (unsigned long) copy_size));
+
+	DUK_ASSERT(copy_size >= 1);
+	DUK_ASSERT(source_ustart <= (duk_uint_t) source_length);
+	DUK_ASSERT(source_ustart + copy_size <= (duk_uint_t) source_length);
+	DUK_ASSERT(target_ustart <= (duk_uint_t) target_length);
+	DUK_ASSERT(target_ustart + copy_size <= (duk_uint_t) target_length);
+
+	/* Ensure copy is covered by underlying buffers. */
+	DUK_ASSERT(h_bufarg->buf != NULL);  /* length check */
+	DUK_ASSERT(h_this->buf != NULL);    /* length check */
+	if (DUK_HBUFFEROBJECT_VALID_BYTEOFFSET_EXCL(h_bufarg, target_ustart + copy_size) &&
+	    DUK_HBUFFEROBJECT_VALID_BYTEOFFSET_EXCL(h_this, source_ustart + copy_size)) {
+		/* Must use memmove() because copy area may overlap (source and target
+		 * buffer may be the same, or from different slices.
+		 */
+		DUK_MEMMOVE((void *) (DUK_HBUFFEROBJECT_GET_SLICE_BASE(thr->heap, h_bufarg) + target_ustart),
+		            (const void *) (DUK_HBUFFEROBJECT_GET_SLICE_BASE(thr->heap, h_this) + source_ustart),
+		            (size_t) copy_size);
+	} else {
+		DUK_DDD(DUK_DDDPRINT("buffer copy not covered by underlying buffer(s), ignoring"));
 	}
 
+ silent_ignore:
+	/* Return value is like write(), number of bytes written.
+	 * The return value matters because of code like:
+	 * "off += buf.copy(...)".
+         */
+	duk_push_uint(ctx, copy_size);
 	return 1;
 
- type_error:
-	return DUK_RET_TYPE_ERROR;
+ fail_bounds:
+	return DUK_RET_RANGE_ERROR;
+}
+#else  /* DUK_USE_BUFFEROBJECT_SUPPORT */
+DUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_copy(duk_context *ctx) {
+	DUK_UNREF(ctx);
+	return DUK_RET_UNSUPPORTED_ERROR;
 }
+#endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
 
 /*
- *  reduce(), reduceRight()
+ *  TypedArray.prototype.set()
+ *
+ *  TypedArray set() is pretty interesting to implement because:
+ *
+ *    - The source argument may be a plain array or a typedarray.  If the
+ *      source is a TypedArray, values are decoded and re-encoded into the
+ *      target (not as a plain byte copy).  This may happen even when the
+ *      element byte size is the same, e.g. integer values may be re-encoded
+ *      into floats.
+ *
+ *    - Source and target may refer to the same underlying buffer, so that
+ *      the set() operation may overlap.  The specification requires that this
+ *      must work as if a copy was made before the operation.  Note that this
+ *      is NOT a simple memmove() situation because the source and target
+ *      byte sizes may be different -- e.g. a 4-byte source (Int8Array) may
+ *      expand to a 16-byte target (Uint32Array) so that the target overlaps
+ *      the source both from beginning and the end (unlike in typical memmove).
+ *
+ *    - Even if 'buf' pointers of the source and target differ, there's no
+ *      guarantee that their memory areas don't overlap.  This may be the
+ *      case with external buffers.
+ *
+ *  Even so, it is nice to optimize for the common case:
+ *
+ *    - Source and target separate buffers or non-overlapping.
+ *
+ *    - Source and target have a compatible type so that a plain byte copy
+ *      is possible.  Note that while e.g. uint8 and int8 are compatible
+ *      (coercion one way or another doesn't change the byte representation),
+ *      e.g. int8 and uint8clamped are NOT compatible when writing int8
+ *      values into uint8clamped typedarray (-1 would clamp to 0 for instance).
+ *
+ *  See test-bi-typedarray-proto-set.js.
  */
 
-duk_ret_t duk_bi_array_prototype_reduce_shared(duk_context *ctx) {
-	duk_idx_t nargs;
-	duk_bool_t have_acc;
-	duk_uint32_t i, len;
-	duk_small_int_t idx_step = duk_get_magic(ctx);  /* idx_step is +1 for reduce, -1 for reduceRight */
-
-	/* We're a varargs function because we need to detect whether
-	 * initialValue was given or not.
-	 */
-	nargs = duk_get_top(ctx);
-	DUK_DDD(DUK_DDDPRINT("nargs=%ld", (long) nargs));
+#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
+DUK_INTERNAL duk_ret_t duk_bi_typedarray_set(duk_context *ctx) {
+	duk_hthread *thr;
+	duk_hbufferobject *h_this;
+	duk_hobject *h_obj;
+	duk_uarridx_t i, n;
+	duk_int_t offset_signed;
+	duk_uint_t offset_elems;
+	duk_uint_t offset_bytes;
 
-	duk_set_top(ctx, 2);
-	len = duk__push_this_obj_len_u32(ctx);
-	if (!duk_is_callable(ctx, 0)) {
-		goto type_error;
-	}
+	thr = (duk_hthread *) ctx;
+	DUK_UNREF(thr);
 
-	/* stack[0] = callback fn
-	 * stack[1] = initialValue
-	 * stack[2] = object (coerced this)
-	 * stack[3] = length (not needed, but not popped above)
-	 * stack[4] = accumulator
-	 */
+	h_this = duk__require_bufobj_this(ctx);
+	DUK_ASSERT(h_this != NULL);
+	DUK_ASSERT_HBUFFEROBJECT_VALID(h_this);
 
-	have_acc = 0;
-	if (nargs >= 2) {
-		duk_dup(ctx, 1);
-		have_acc = 1;
+	if (h_this->buf == NULL) {
+		DUK_DDD(DUK_DDDPRINT("source neutered, skip copy"));
+		return 0;
 	}
-	DUK_DDD(DUK_DDDPRINT("have_acc=%ld, acc=%!T",
-	                     (long) have_acc, (duk_tval *) duk_get_tval(ctx, 3)));
 
-	/* For len == 0, i is initialized to len - 1 which underflows.
-	 * The condition (i < len) will then exit the for-loop on the
-	 * first round which is correct.  Similarly, loop termination
-	 * happens by i underflowing.
+	h_obj = duk_require_hobject(ctx, 0);
+	DUK_ASSERT(h_obj != NULL);
+
+	/* XXX: V8 throws a TypeError for negative values.  Would it
+	 * be more useful to interpret negative offsets here from the
+	 * end of the buffer too?
 	 */
+	offset_signed = duk_to_int(ctx, 1);
+	if (offset_signed < 0) {
+		return DUK_RET_TYPE_ERROR;
+	}
+	offset_elems = (duk_uint_t) offset_signed;
+	offset_bytes = offset_elems << h_this->shift;
+	if ((offset_bytes >> h_this->shift) != offset_elems) {
+		/* Byte length would overflow. */
+		/* XXX: easier check with less code? */
+		return DUK_RET_RANGE_ERROR;
+	}
+	if (offset_bytes > h_this->length) {
+		/* Equality may be OK but >length not.  Checking
+		 * this explicitly avoids some overflow cases
+		 * below.
+		 */
+		return DUK_RET_RANGE_ERROR;
+	}
+	DUK_ASSERT(offset_bytes <= h_this->length);
+
+	/* Fast path: source is a TypedArray (or any bufferobject). */
+
+	if (DUK_HOBJECT_IS_BUFFEROBJECT(h_obj)) {
+		duk_hbufferobject *h_bufarg;
+		duk_uint16_t comp_mask;
+		duk_small_int_t no_overlap = 0;
+		duk_uint_t src_length;
+		duk_uint_t dst_length;
+		duk_uint_t dst_length_elems;
+		duk_uint8_t *p_src_base;
+		duk_uint8_t *p_src_end;
+		duk_uint8_t *p_src;
+		duk_uint8_t *p_dst_base;
+		duk_uint8_t *p_dst;
+		duk_small_uint_t src_elem_size;
+		duk_small_uint_t dst_elem_size;
+
+		h_bufarg = (duk_hbufferobject *) h_obj;
+		DUK_ASSERT_HBUFFEROBJECT_VALID(h_bufarg);
+
+		if (h_bufarg->buf == NULL) {
+			DUK_DDD(DUK_DDDPRINT("target neutered, skip copy"));
+			return 0;
+		}
 
-	for (i = (idx_step >= 0 ? 0 : len - 1);
-	     i < len;  /* i >= 0 would always be true */
-	     i += idx_step) {
-		DUK_DDD(DUK_DDDPRINT("i=%ld, len=%ld, have_acc=%ld, top=%ld, acc=%!T",
-		                     (long) i, (long) len, (long) have_acc,
-		                     (long) duk_get_top(ctx),
-		                     (duk_tval *) duk_get_tval(ctx, 4)));
+		/* Nominal size check. */
+		src_length = h_bufarg->length;  /* bytes in source */
+		dst_length_elems = (src_length >> h_bufarg->shift);  /* elems in source and dest */
+		dst_length = dst_length_elems << h_this->shift;  /* bytes in dest */
+		if ((dst_length >> h_this->shift) != dst_length_elems) {
+			/* Byte length would overflow. */
+			/* XXX: easier check with less code? */
+			return DUK_RET_RANGE_ERROR;
+		}
+		DUK_DDD(DUK_DDDPRINT("nominal size check: src_length=%ld, dst_length=%ld",
+		                     (long) src_length, (long) dst_length));
+		DUK_ASSERT(offset_bytes <= h_this->length);
+		if (dst_length > h_this->length - offset_bytes) {
+			/* Overflow not an issue because subtraction is used on the right
+			 * side and guaranteed to be >= 0.
+			 */
+			DUK_DDD(DUK_DDDPRINT("copy exceeds target buffer nominal length"));
+			return DUK_RET_RANGE_ERROR;
+		}
+		if (!DUK_HBUFFEROBJECT_VALID_BYTEOFFSET_EXCL(h_this, offset_bytes + dst_length)) {
+			DUK_DDD(DUK_DDDPRINT("copy not covered by underlying target buffer, ignore"));
+			return 0;
+		}
 
-		DUK_ASSERT((have_acc && duk_get_top(ctx) == 5) ||
-		           (!have_acc && duk_get_top(ctx) == 4));
+		p_src_base = DUK_HBUFFEROBJECT_GET_SLICE_BASE(thr->heap, h_bufarg);
+		p_dst_base = DUK_HBUFFEROBJECT_GET_SLICE_BASE(thr->heap, h_this) + offset_bytes;
 
-		if (!duk_has_prop_index(ctx, 2, (duk_uarridx_t) i)) {
-			continue;
+		/* Check actual underlying buffers for validity and that they
+		 * cover the copy.  No side effects are allowed after the check
+		 * so that the validity status doesn't change.
+		 */
+		if (!DUK_HBUFFEROBJECT_VALID_SLICE(h_this) ||
+		    !DUK_HBUFFEROBJECT_VALID_SLICE(h_bufarg)) {
+			/* The condition could be more narrow and check for the
+			 * copy area only, but there's no need for fine grained
+			 * behavior when the underlying buffer is misconfigured.
+			 */
+			DUK_DDD(DUK_DDDPRINT("source and/or target not covered by underlying buffer, skip copy"));
+			return 0;
 		}
 
-		if (!have_acc) {
-			DUK_ASSERT_TOP(ctx, 4);
-			duk_get_prop_index(ctx, 2, (duk_uarridx_t) i);
-			have_acc = 1;
-			DUK_ASSERT_TOP(ctx, 5);
-		} else {
-			DUK_ASSERT_TOP(ctx, 5);
-			duk_dup(ctx, 0);
-			duk_dup(ctx, 4);
-			duk_get_prop_index(ctx, 2, (duk_uarridx_t) i);
-			duk_push_u32(ctx, i);
-			duk_dup(ctx, 2);
-			DUK_DDD(DUK_DDDPRINT("calling reduce function: func=%!T, prev=%!T, curr=%!T, idx=%!T, obj=%!T",
-			                     (duk_tval *) duk_get_tval(ctx, -5), (duk_tval *) duk_get_tval(ctx, -4),
-			                     (duk_tval *) duk_get_tval(ctx, -3), (duk_tval *) duk_get_tval(ctx, -2),
-			                     (duk_tval *) duk_get_tval(ctx, -1)));
-			duk_call(ctx, 4);
-			DUK_DDD(DUK_DDDPRINT("-> result: %!T", (duk_tval *) duk_get_tval(ctx, -1)));
-			duk_replace(ctx, 4);
-			DUK_ASSERT_TOP(ctx, 5);
+		/* We want to do a straight memory copy if possible: this is
+		 * an important operation because .set() is the TypedArray
+		 * way to copy chunks of memory.  However, because set()
+		 * conceptually works in terms of elements, not all views are
+		 * compatible with direct byte copying.
+		 *
+		 * If we do manage a direct copy, the "overlap issue" handled
+		 * below can just be solved using memmove() because the source
+		 * and destination element sizes are necessarily equal.
+		 */
+
+		DUK_ASSERT(h_this->elem_type < sizeof(duk__buffer_elemtype_copy_compatible) / sizeof(duk_uint16_t));
+		comp_mask = duk__buffer_elemtype_copy_compatible[h_this->elem_type];
+		if (comp_mask & (1 << h_bufarg->elem_type)) {
+			DUK_ASSERT(src_length == dst_length);
+
+			DUK_DDD(DUK_DDDPRINT("fast path: able to use memmove() because views are compatible"));
+			DUK_MEMMOVE((void *) p_dst_base, (const void *) p_src_base, (size_t) dst_length);
+			return 0;
 		}
-	}
+		DUK_DDD(DUK_DDDPRINT("fast path: views are not compatible with a byte copy, copy by item"));
 
-	if (!have_acc) {
-		goto type_error;
-	}
+		/* We want to avoid making a copy to process set() but that's
+		 * not always possible: the source and the target may overlap
+		 * and because element sizes are different, the overlap cannot
+		 * always be handled with a memmove() or choosing the copy
+		 * direction in a certain way.  For example, if source type is
+		 * uint8 and target type is uint32, the target area may exceed
+		 * the source area from both ends!
+		 *
+		 * Note that because external buffers may point to the same
+		 * memory areas, we must ultimately make this check using
+		 * pointers.
+		 *
+		 * NOTE: careful with side effects: any side effect may cause
+		 * a buffer resize (or external buffer pointer/length update)!
+		 */
 
-	DUK_ASSERT_TOP(ctx, 5);
-	return 1;
+		DUK_DDD(DUK_DDDPRINT("overlap check: p_src_base=%p, src_length=%ld, "
+		                     "p_dst_base=%p, dst_length=%ld",
+		                     (void *) p_src_base, (long) src_length,
+		                     (void *) p_dst_base, (long) dst_length));
 
- type_error:
-	return DUK_RET_TYPE_ERROR;
-}
-#line 1 "duk_bi_boolean.c"
-/*
- *  Boolean built-ins
- */
+		if (p_src_base >= p_dst_base + dst_length ||  /* source starts after dest ends */
+		    p_src_base + src_length <= p_dst_base) {   /* source ends before dest starts */
+			no_overlap = 1;
+		}
 
-/* include removed: duk_internal.h */
+		if (!no_overlap) {
+			/* There's overlap: the desired end result is that
+			 * conceptually a copy is made to avoid "trampling"
+			 * of source data by destination writes.  We make
+			 * an actual temporary copy to handle this case.
+			 */
+			duk_uint8_t *p_src_copy;
 
-/* Shared helper to provide toString() and valueOf().  Checks 'this', gets
- * the primitive value to stack top, and optionally coerces with ToString().
- */
-duk_ret_t duk_bi_boolean_prototype_tostring_shared(duk_context *ctx) {
-	duk_tval *tv;
-	duk_hobject *h;
-	duk_small_int_t coerce_tostring = duk_get_magic(ctx);
+			DUK_DDD(DUK_DDDPRINT("there is overlap, make a copy of the source"));
+			p_src_copy = (duk_uint8_t *) duk_push_fixed_buffer(ctx, src_length);
+			DUK_ASSERT(p_src_copy != NULL);
+			DUK_MEMCPY((void *) p_src_copy, (const void *) p_src_base, (size_t) src_length);
 
-	/* FIXME: there is room to use a shared helper here, many built-ins
-	 * check the 'this' type, and if it's an object, check its class,
-	 * then get its internal value, etc.
-	 */
+			p_src_base = p_src_copy;  /* use p_src_base from now on */
+		}
+		/* Value stack intentionally mixed size here. */
 
-	duk_push_this(ctx);
-	tv = duk_get_tval(ctx, -1);
-	DUK_ASSERT(tv != NULL);
+		DUK_DDD(DUK_DDDPRINT("after overlap check: p_src_base=%p, src_length=%ld, "
+		                     "p_dst_base=%p, dst_length=%ld, valstack top=%ld",
+		                     (void *) p_src_base, (long) src_length,
+		                     (void *) p_dst_base, (long) dst_length,
+		                     (long) duk_get_top(ctx)));
 
-	if (DUK_TVAL_IS_BOOLEAN(tv)) {
-		goto type_ok;
-	} else if (DUK_TVAL_IS_OBJECT(tv)) {
-		h = DUK_TVAL_GET_OBJECT(tv);
-		DUK_ASSERT(h != NULL);
+		/* Ready to make the copy.  We must proceed element by element
+		 * and must avoid any side effects that might cause the buffer
+		 * validity check above to become invalid.
+		 *
+		 * Although we work through the value stack here, only plain
+		 * numbers are handled which should be side effect safe.
+		 */
 
-		if (DUK_HOBJECT_GET_CLASS_NUMBER(h) == DUK_HOBJECT_CLASS_BOOLEAN) {
-			duk_get_prop_stridx(ctx, -1, DUK_STRIDX_INT_VALUE);
-			DUK_ASSERT(duk_is_boolean(ctx, -1));
-			goto type_ok;
+		src_elem_size = 1 << h_bufarg->shift;
+		dst_elem_size = 1 << h_this->shift;
+		p_src = p_src_base;
+		p_dst = p_dst_base;
+		p_src_end = p_src_base + src_length;
+
+		while (p_src != p_src_end) {
+			DUK_DDD(DUK_DDDPRINT("fast path per element copy loop: "
+			                     "p_src=%p, p_src_end=%p, p_dst=%p",
+			                     (void *) p_src, (void *) p_src_end, (void *) p_dst));
+			/* A validated read() is always a number, so it's write coercion
+			 * is always side effect free an won't invalidate pointers etc.
+			 */
+			duk_hbufferobject_push_validated_read(ctx, h_bufarg, p_src, src_elem_size);
+			duk_hbufferobject_validated_write(ctx, h_this, p_dst, dst_elem_size);
+			duk_pop(ctx);
+			p_src += src_elem_size;
+			p_dst += dst_elem_size;
 		}
-	}
-
-	return DUK_RET_TYPE_ERROR;
 
- type_ok:
-	if (coerce_tostring) {
-		duk_to_string(ctx, -1);
-	}
-	return 1;
-}
+		return 0;
+	} else {
+		/* Slow path: quite slow, but we save space by using the property code
+		 * to write coerce target values.  We don't need to worry about overlap
+		 * here because the source is not a TypedArray.
+		 *
+		 * We could use the bufferobject write coercion helper but since the
+		 * property read may have arbitrary side effects, full validity checks
+		 * would be needed for every element anyway.
+		 */
 
-duk_ret_t duk_bi_boolean_constructor(duk_context *ctx) {
-	duk_hobject *h_this;
+		n = (duk_uarridx_t) duk_get_length(ctx, 0);
+		DUK_ASSERT(offset_bytes <= h_this->length);
+		if ((n << h_this->shift) > h_this->length - offset_bytes) {
+			/* Overflow not an issue because subtraction is used on the right
+			 * side and guaranteed to be >= 0.
+			 */
+			DUK_DDD(DUK_DDDPRINT("copy exceeds target buffer nominal length"));
+			return DUK_RET_RANGE_ERROR;
+		}
 
-	duk_to_boolean(ctx, 0);
+		/* There's no need to check for buffer validity status for the
+		 * target here: the property access code will do that for each
+		 * element.  Moreover, if we did check the validity here, side
+		 * effects from reading the source argument might invalidate
+		 * the results anyway.
+		 */
 
-	if (duk_is_constructor_call(ctx)) {
-		/* FIXME: helper; rely on Boolean.prototype as being non-writable, non-configurable */
+		DUK_ASSERT_TOP(ctx, 2);
 		duk_push_this(ctx);
-		h_this = duk_get_hobject(ctx, -1);
-		DUK_ASSERT(h_this != NULL);
-		DUK_ASSERT(h_this->prototype == ((duk_hthread *) ctx)->builtins[DUK_BIDX_BOOLEAN_PROTOTYPE]);
 
-		DUK_HOBJECT_SET_CLASS_NUMBER(h_this, DUK_HOBJECT_CLASS_BOOLEAN);
-
-		duk_dup(ctx, 0);  /* -> [ val obj val ] */
-		duk_def_prop_stridx(ctx, -2, DUK_STRIDX_INT_VALUE, DUK_PROPDESC_FLAGS_NONE);  /* FIXME: proper flags? */
-	}  /* unbalanced stack */
+		for (i = 0; i < n; i++) {
+			duk_get_prop_index(ctx, 0, i);
+			duk_put_prop_index(ctx, 2, offset_elems + i);
+		}
+	}
 
-	return 1;
+	return 0;
 }
-#line 1 "duk_bi_buffer.c"
+#else  /* DUK_USE_BUFFEROBJECT_SUPPORT */
+DUK_INTERNAL duk_ret_t duk_bi_typedarray_set(duk_context *ctx) {
+	DUK_UNREF(ctx);
+	return DUK_RET_UNSUPPORTED_ERROR;
+}
+#endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
+
 /*
- *  Buffer built-ins
+ *  Node.js Buffer.prototype.slice([start], [end])
+ *  ArrayBuffer.prototype.slice(begin, [end])
+ *  TypedArray.prototype.slice(begin, [end])
+ *
+ *  The API calls are almost identical; negative indices are counted from end
+ *  of buffer, and final indices are clamped (allowing crossed indices).  Main
+ *  differences:
+ *
+ *    - Copy/view behavior; Node.js .slice() and TypedArray .subarray() create
+ *      views, ArrayBuffer .slice() creates a copy
+ *
+ *    - Resulting object has a different class and prototype depending on the
+ *      call (or 'this' argument)
+ *
+ *    - TypedArray .subarray() arguments are element indices, not byte offsets
  */
 
-/* include removed: duk_internal.h */
+#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
+DUK_INTERNAL duk_ret_t duk_bi_buffer_slice_shared(duk_context *ctx) {
+	duk_hthread *thr;
+	duk_small_int_t magic;
+	duk_small_uint_t res_class_num;
+	duk_hobject *res_proto;
+	duk_hbufferobject *h_this;
+	duk_hbufferobject *h_bufobj;
+	duk_hbuffer *h_val;
+	duk_int_t start_offset, end_offset;
+	duk_uint_t slice_length;
+
+	thr = (duk_hthread *) ctx;
+	DUK_UNREF(thr);
 
-/*
- *  Constructor
- */
+	/* [ start end ] */
 
-duk_ret_t duk_bi_buffer_constructor(duk_context *ctx) {
-	duk_size_t buf_size;
-	duk_small_int_t buf_dynamic;
-	duk_uint8_t *buf_data;
-	const duk_uint8_t *src_data;
-	duk_hobject *h_obj;
+	magic = duk_get_current_magic(ctx);
+	h_this = duk__require_bufobj_this(ctx);
 
-	/*
-	 *  Constructor arguments are currently somewhat compatible with
-	 *  (keep it that way if possible):
-	 *
-	 *    http://nodejs.org/api/buffer.html
-	 *
+	/* Slice offsets are element (not byte) offsets, which only matters
+	 * for TypedArray views, Node.js Buffer and ArrayBuffer have shift
+	 * zero so byte and element offsets are the same.  Negative indices
+	 * are counted from end of slice, crossed indices are allowed (and
+	 * result in zero length result), and final values are clamped
+	 * against the current slice.  There's intentionally no check
+	 * against the underlying buffer here.
 	 */
 
-	buf_dynamic = duk_get_boolean(ctx, 1);  /* default to false */
+	duk__clamp_startend_negidx_shifted(ctx, h_this, 0 /*idx_start*/, 1 /*idx_end*/, &start_offset, &end_offset);
+	DUK_ASSERT(end_offset >= start_offset);
+	slice_length = (duk_uint_t) (end_offset - start_offset);
 
-	switch (duk_get_type(ctx, 0)) {
-	case DUK_TYPE_NUMBER:
-		/* new buffer of specified size */
-		buf_size = (duk_size_t) duk_to_int(ctx, 0);
-		(void) duk_push_buffer(ctx, buf_size, buf_dynamic);
-		break;
-	case DUK_TYPE_BUFFER:
-		/* return input buffer, converted to a Buffer object if called as a
-		 * constructor (no change if called as a function).
+	/* The resulting buffer object gets the same class and prototype as
+	 * the buffer in 'this', e.g. if the input is a Node.js Buffer the
+	 * result is a Node.js Buffer; if the input is a Float32Array, the
+	 * result is a Float32Array.
+	 *
+	 * For the class number this seems correct.  The internal prototype
+	 * is not so clear: if 'this' is a bufferobject with a non-standard
+	 * prototype object, that value gets copied over into the result
+	 * (instead of using the standard prototype for that object type).
+	 */
+
+	res_class_num = DUK_HOBJECT_GET_CLASS_NUMBER((duk_hobject *) h_this);
+	h_bufobj = duk_push_bufferobject_raw(ctx,
+	                                     DUK_HOBJECT_FLAG_EXTENSIBLE |
+	                                     DUK_HOBJECT_FLAG_BUFFEROBJECT |
+	                                     DUK_HOBJECT_CLASS_AS_FLAGS(res_class_num),
+	                                     DUK_BIDX_OBJECT_PROTOTYPE);  /* replaced */
+	DUK_ASSERT(h_bufobj != NULL);
+	res_proto = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, (duk_hobject *) h_this);  /* may be NULL */
+	DUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr, (duk_hobject *) h_bufobj, res_proto);
+
+	h_bufobj->length = slice_length;
+	h_bufobj->shift = h_this->shift;  /* inherit */
+	h_bufobj->elem_type = h_this->elem_type;  /* inherit */
+	h_bufobj->is_view = magic & 0x01;
+	DUK_ASSERT(h_bufobj->is_view == 0 || h_bufobj->is_view == 1);
+
+	h_val = h_this->buf;
+	if (h_val == NULL) {
+		return DUK_RET_TYPE_ERROR;
+	}
+
+	if (magic & 0x02) {
+		/* non-zero: make copy */
+		duk_uint8_t *p_copy;
+		duk_size_t copy_length;
+
+		p_copy = (duk_uint8_t *) duk_push_fixed_buffer(ctx, (duk_size_t) slice_length);
+		DUK_ASSERT(p_copy != NULL);
+
+		/* Copy slice, respecting underlying buffer limits; remainder
+		 * is left as zero.
 		 */
-		duk_set_top(ctx, 1);
-		break;
-	case DUK_TYPE_STRING:
-		/* new buffer with string contents */
-		src_data = (const duk_uint8_t *) duk_get_lstring(ctx, 0, &buf_size);
-		DUK_ASSERT(src_data != NULL);  /* even for zero-length string */
-		buf_data = (duk_uint8_t *) duk_push_buffer(ctx, buf_size, buf_dynamic);
-		DUK_MEMCPY((void *) buf_data, (const void *) src_data, (size_t) buf_size);
-		break;
-	case DUK_TYPE_OBJECT:
-		/* Buffer object: get the plain buffer inside.  If called as as
-		 * constructor, a new Buffer object pointing to the same plain
-		 * buffer is created below.
+		copy_length = DUK_HBUFFEROBJECT_CLAMP_BYTELENGTH(h_this, slice_length);
+		DUK_MEMCPY((void *) p_copy,
+		           (const void *) (DUK_HBUFFEROBJECT_GET_SLICE_BASE(thr->heap, h_this) + start_offset),
+		           copy_length);
+
+		h_val = duk_get_hbuffer(ctx, -1);
+		DUK_ASSERT(h_val != NULL);
+
+		h_bufobj->buf = h_val;
+		DUK_HBUFFER_INCREF(thr, h_val);
+		DUK_ASSERT(h_bufobj->offset == 0);
+
+		duk_pop(ctx);  /* reachable so pop OK */
+	} else {
+		h_bufobj->buf = h_val;
+		DUK_HBUFFER_INCREF(thr, h_val);
+		h_bufobj->offset = (duk_uint_t) (h_this->offset + start_offset);
+
+		/* Copy the .buffer property, needed for TypedArray.prototype.subarray().
+		 *
+		 * XXX: limit copy only for TypedArray classes specifically?
 		 */
-		h_obj = duk_get_hobject(ctx, 0);
-		DUK_ASSERT(h_obj != NULL);
-		if (DUK_HOBJECT_GET_CLASS_NUMBER(h_obj) != DUK_HOBJECT_CLASS_BUFFER) {
-			return DUK_RET_TYPE_ERROR;
+
+		duk_push_this(ctx);
+		if (duk_get_prop_stridx(ctx, -1, DUK_STRIDX_LC_BUFFER)) {
+			duk_xdef_prop_stridx(ctx, -3, DUK_STRIDX_LC_BUFFER, DUK_PROPDESC_FLAGS_NONE);
+			duk_pop(ctx);
+		} else {
+			duk_pop_2(ctx);
 		}
-		duk_get_prop_stridx(ctx, 0, DUK_STRIDX_INT_VALUE);
-		DUK_ASSERT(duk_is_buffer(ctx, -1));
-		break;
-	case DUK_TYPE_NONE:
-	default:
-		return DUK_RET_TYPE_ERROR;
 	}
+	/* unbalanced stack on purpose */
 
-	/* stack is unbalanced, but: [ <something> buf ] */
+	DUK_ASSERT_HBUFFEROBJECT_VALID(h_bufobj);
+	return 1;
+}
+#else  /* DUK_USE_BUFFEROBJECT_SUPPORT */
+DUK_INTERNAL duk_ret_t duk_bi_buffer_slice_shared(duk_context *ctx) {
+	DUK_UNREF(ctx);
+	return DUK_RET_UNSUPPORTED_ERROR;
+}
+#endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
 
-	if (duk_is_constructor_call(ctx)) {
-		duk_push_object_helper(ctx,
-		                       DUK_HOBJECT_FLAG_EXTENSIBLE |
-		                       DUK_HOBJECT_FLAG_EXOTIC_BUFFEROBJ |
-		                       DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_BUFFER),
-		                       DUK_BIDX_BUFFER_PROTOTYPE);
+/*
+ *  Node.js Buffer.isEncoding()
+ */
 
-		/* Buffer object internal value is immutable */
-		duk_dup(ctx, -2);
-		duk_def_prop_stridx(ctx, -2, DUK_STRIDX_INT_VALUE, DUK_PROPDESC_FLAGS_NONE);
-	}
-	/* Note: unbalanced stack on purpose */
+#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
+DUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_is_encoding(duk_context *ctx) {
+	const char *encoding;
+
+	/* only accept lowercase 'utf8' now. */
 
+	encoding = duk_to_string(ctx, 0);
+	DUK_ASSERT(duk_is_string(ctx, 0));  /* guaranteed by duk_to_string() */
+	duk_push_boolean(ctx, DUK_STRCMP(encoding, "utf8") == 0);
 	return 1;
 }
+#else  /* DUK_USE_BUFFEROBJECT_SUPPORT */
+DUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_is_encoding(duk_context *ctx) {
+	DUK_UNREF(ctx);
+	return DUK_RET_UNSUPPORTED_ERROR;
+}
+#endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
 
 /*
- *  toString(), valueOf()
+ *  Node.js Buffer.isBuffer()
  */
 
-duk_ret_t duk_bi_buffer_prototype_tostring_shared(duk_context *ctx) {
+#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
+DUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_is_buffer(duk_context *ctx) {
+	duk_hthread *thr;
 	duk_tval *tv;
-	duk_small_int_t to_string = duk_get_magic(ctx);
+	duk_hobject *h;
+	duk_hobject *h_proto;
+	duk_bool_t ret = 0;
 
-	duk_push_this(ctx);
-	tv = duk_require_tval(ctx, -1);
+	thr = (duk_hthread *) ctx;
+
+	DUK_ASSERT(duk_get_top(ctx) >= 1);  /* nargs */
+	tv = duk_get_tval(ctx, 0);
 	DUK_ASSERT(tv != NULL);
 
-	if (DUK_TVAL_IS_BUFFER(tv)) {
-		/* nop */
-	} else if (DUK_TVAL_IS_OBJECT(tv)) {
-		duk_hobject *h = DUK_TVAL_GET_OBJECT(tv);
+	if (DUK_TVAL_IS_OBJECT(tv)) {
+		h = DUK_TVAL_GET_OBJECT(tv);
 		DUK_ASSERT(h != NULL);
 
-		/* Must be a "buffer object", i.e. class "Buffer" */
-		if (DUK_HOBJECT_GET_CLASS_NUMBER(h) != DUK_HOBJECT_CLASS_BUFFER) {
-			goto type_error;
-		}
+		h_proto = thr->builtins[DUK_BIDX_NODEJS_BUFFER_PROTOTYPE];
+		DUK_ASSERT(h_proto != NULL);
 
-		duk_get_prop_stridx(ctx, -1, DUK_STRIDX_INT_VALUE);
-	} else {
-		goto type_error;
+		h = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h);
+		if (h) {
+			ret = duk_hobject_prototype_chain_contains(thr, h, h_proto, 0 /*ignore_loop*/);
+		}
 	}
 
-	if (to_string) {
-		duk_to_string(ctx, -1);
-	}
+	duk_push_boolean(ctx, ret);
 	return 1;
+}
+#else  /* DUK_USE_BUFFEROBJECT_SUPPORT */
+DUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_is_buffer(duk_context *ctx) {
+	DUK_UNREF(ctx);
+	return DUK_RET_UNSUPPORTED_ERROR;
+}
+#endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
 
- type_error:
-	return DUK_RET_TYPE_ERROR;
+/*
+ *  Node.js Buffer.byteLength()
+ */
+
+#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
+DUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_byte_length(duk_context *ctx) {
+	const char *str;
+	duk_size_t len;
+
+	/* At the moment Buffer(<str>) will just use the string bytes as
+	 * is (ignoring encoding), so we return the string length here
+	 * unconditionally.
+	 */
+
+	str = duk_to_lstring(ctx, 0, &len);
+	DUK_UNREF(str);
+	duk_push_size_t(ctx, len);
+	return 1;
 }
-#line 1 "duk_bi_date.c"
+#else  /* DUK_USE_BUFFEROBJECT_SUPPORT */
+DUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_byte_length(duk_context *ctx) {
+	DUK_UNREF(ctx);
+	return DUK_RET_UNSUPPORTED_ERROR;
+}
+#endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
+
 /*
- *  Date built-ins
- *
- *  Unlike most built-ins, Date has a lot of platform dependencies for
- *  getting UTC time, converting between UTC and local time, and parsing
- *  and formatting time values.
- *
- *  See doc/datetime.txt.
- *
- *  Platform specific links:
- *
- *    - http://msdn.microsoft.com/en-us/library/windows/desktop/ms725473(v=vs.85).aspx
+ *  Node.js Buffer.concat()
  */
 
-/* include removed: duk_internal.h */
+#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
+DUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_concat(duk_context *ctx) {
+	duk_hthread *thr;
+	duk_hobject *h_arg;
+	duk_int_t total_length = 0;
+	duk_hbufferobject *h_bufobj;
+	duk_hbufferobject *h_bufres;
+	duk_hbuffer *h_val;
+	duk_uint_t i, n;
+	duk_uint8_t *p;
+	duk_size_t space_left;
+	duk_size_t copy_size;
+
+	thr = (duk_hthread *) ctx;
+	DUK_UNREF(thr);
+
+	/* Node.js accepts only actual Arrays. */
+	h_arg = duk_require_hobject(ctx, 0);
+	if (DUK_HOBJECT_GET_CLASS_NUMBER(h_arg) != DUK_HOBJECT_CLASS_ARRAY) {
+		return DUK_RET_TYPE_ERROR;
+	}
+
+	/* Compute result length and validate argument buffers. */
+	n = (duk_uint_t) duk_get_length(ctx, 0);
+	for (i = 0; i < n; i++) {
+		/* Neutered checks not necessary here: neutered buffers have
+		 * zero 'length' so we'll effectively skip them.
+		 */
+		DUK_ASSERT_TOP(ctx, 2);  /* [ array totalLength ] */
+		duk_get_prop_index(ctx, 0, (duk_uarridx_t) i);  /* -> [ array totalLength buf ] */
+		h_bufobj = duk__require_bufobj_value(ctx, 2);
+		DUK_ASSERT(h_bufobj != NULL);
+		total_length += h_bufobj->length;
+		duk_pop(ctx);
+	}
+	if (n == 1) {
+		/* For the case n==1 Node.js doesn't seem to type check
+		 * the sole member but we do it before returning it.
+		 * For this case only the original buffer object is
+		 * returned (not a copy).
+		 */
+		duk_get_prop_index(ctx, 0, 0);
+		return 1;
+	}
 
-/*
- *  Platform specific includes and defines
- *
- *  Note that necessary system headers (like <sys/time.h>) are included
- *  by duk_internal.h (or duk_features.h, which is included by duk_internal.h)
- *  because the header locations vary between systems and we don't want
- *  that clutter here.
- */
+	/* User totalLength overrides a computed length, but we'll check
+	 * every copy in the copy loop.  Note that duk_to_uint() can
+	 * technically have arbitrary side effects so we need to recheck
+	 * the buffers in the copy loop.
+	 */
+	if (!duk_is_undefined(ctx, 1) && n > 0) {
+		/* For n == 0, Node.js ignores totalLength argument and
+		 * returns a zero length buffer.
+		 */
+		total_length = duk_to_int(ctx, 1);
+	}
+	if (total_length < 0) {
+		return DUK_RET_RANGE_ERROR;
+	}
 
-#define DUK__GET_NOW_TIMEVAL      duk_bi_date_get_now
-#define DUK__GET_LOCAL_TZOFFSET   duk__get_local_tzoffset
+	h_bufres = duk_push_bufferobject_raw(ctx,
+	                                     DUK_HOBJECT_FLAG_EXTENSIBLE |
+	                                     DUK_HOBJECT_FLAG_BUFFEROBJECT |
+	                                     DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_BUFFER),
+	                                     DUK_BIDX_NODEJS_BUFFER_PROTOTYPE);
+	DUK_ASSERT(h_bufres != NULL);
 
-/* Buffer sizes for some UNIX calls.  Larger than strictly necessary
- * to avoid Valgrind errors.
- */
-#define DUK__STRPTIME_BUF_SIZE  64
-#define DUK__STRFTIME_BUF_SIZE  64
+	p = (duk_uint8_t *) duk_push_fixed_buffer(ctx, total_length);
+	DUK_ASSERT(p != NULL);
+	space_left = total_length;
 
-/*
- *  Other file level defines
- */
+	for (i = 0; i < n; i++) {
+		DUK_ASSERT_TOP(ctx, 4);  /* [ array totalLength bufres buf ] */
 
-/* Forward declarations. */
-static duk_double_t duk__push_this_get_timeval_tzoffset(duk_context *ctx, duk_small_uint_t flags, duk_int_t *out_tzoffset);
-static duk_double_t duk__push_this_get_timeval(duk_context *ctx, duk_small_uint_t flags);
-static void duk__timeval_to_parts(duk_double_t d, duk_int_t *parts, duk_double_t *dparts, duk_small_uint_t flags);
-static duk_double_t duk__get_timeval_from_dparts(duk_double_t *dparts, duk_small_uint_t flags);
-static void duk__twodigit_year_fixup(duk_context *ctx, duk_idx_t idx_val);
-
-/* Millisecond count constants. */
-#define DUK__MS_SECOND          1000L
-#define DUK__MS_MINUTE          (60L * 1000L)
-#define DUK__MS_HOUR            (60L * 60L * 1000L)
-#define DUK__MS_DAY             (24L * 60L * 60L * 1000L)
-
-/* Part indices for internal breakdowns.  Part order from DUK__IDX_YEAR to
- * DUK__IDX_MILLISECOND matches argument ordering of Ecmascript API calls
- * (like Date constructor call).  A few functions in this file depend
- * on the specific ordering, so change with care.  16 bits are not enough
- * for all parts (year, specifically).
- *
- * (Must be in-sync with genbuiltins.py.)
- */
-#define DUK__IDX_YEAR           0  /* year */
-#define DUK__IDX_MONTH          1  /* month: 0 to 11 */
-#define DUK__IDX_DAY            2  /* day within month: 0 to 30 */
-#define DUK__IDX_HOUR           3
-#define DUK__IDX_MINUTE         4
-#define DUK__IDX_SECOND         5
-#define DUK__IDX_MILLISECOND    6
-#define DUK__IDX_WEEKDAY        7  /* weekday: 0 to 6, 0=sunday, 1=monday, etc */
-#define DUK__NUM_PARTS          8
-
-/* Internal API call flags, used for various functions in this file.
- * Certain flags are used by only certain functions, but since the flags
- * don't overlap, a single flags value can be passed around to multiple
- * functions.
- *
- * The unused top bits of the flags field are also used to pass values
- * to helpers (duk__get_part_helper() and duk__set_part_helper()).
- *
- * (Must be in-sync with genbuiltins.py.)
- */
-#define DUK__FLAG_NAN_TO_ZERO          (1 << 0)  /* timeval breakdown: internal time value NaN -> zero */
-#define DUK__FLAG_NAN_TO_RANGE_ERROR   (1 << 1)  /* timeval breakdown: internal time value NaN -> RangeError (toISOString) */
-#define DUK__FLAG_ONEBASED             (1 << 2)  /* timeval breakdown: convert month and day-of-month parts to one-based (default is zero-based) */
-#define DUK__FLAG_LOCALTIME            (1 << 3)  /* convert time value to local time */
-#define DUK__FLAG_SUB1900              (1 << 4)  /* getter: subtract 1900 from year when getting year part */
-#define DUK__FLAG_TOSTRING_DATE        (1 << 5)  /* include date part in string conversion result */
-#define DUK__FLAG_TOSTRING_TIME        (1 << 6)  /* include time part in string conversion result */
-#define DUK__FLAG_TOSTRING_LOCALE      (1 << 7)  /* use locale specific formatting if available */
-#define DUK__FLAG_TIMESETTER           (1 << 8)  /* setter: call is a time setter (affects hour, min, sec, ms); otherwise date setter (affects year, month, day-in-month) */
-#define DUK__FLAG_YEAR_FIXUP           (1 << 9)  /* setter: perform 2-digit year fixup (00...99 -> 1900...1999) */
-#define DUK__FLAG_SEP_T                (1 << 10) /* string conversion: use 'T' instead of ' ' as a separator */
-
-/*
- *  Platform specific helpers
- */
-
-#ifdef DUK_USE_DATE_NOW_GETTIMEOFDAY
-/* Get current Ecmascript time (= UNIX/Posix time, but in milliseconds). */
-duk_double_t duk_bi_date_get_now(duk_context *ctx) {
-	duk_hthread *thr = (duk_hthread *) ctx;
-	struct timeval tv;
-	duk_double_t d;
+		duk_get_prop_index(ctx, 0, (duk_uarridx_t) i);
+		h_bufobj = duk__require_bufobj_value(ctx, 4);
+		DUK_ASSERT(h_bufobj != NULL);
 
-	if (gettimeofday(&tv, NULL) != 0) {
-		DUK_ERROR(thr, DUK_ERR_INTERNAL_ERROR, "gettimeofday failed");
+		copy_size = h_bufobj->length;
+		if (copy_size > space_left) {
+			copy_size = space_left;
+		}
+
+		if (h_bufobj->buf != NULL &&
+		    DUK_HBUFFEROBJECT_VALID_SLICE(h_bufobj)) {
+			DUK_MEMCPY((void *) p,
+			           (const void *) DUK_HBUFFEROBJECT_GET_SLICE_BASE(thr->heap, h_bufobj),
+			           copy_size);
+		} else {
+			/* Just skip, leaving zeroes in the result. */
+			;
+		}
+		p += copy_size;
+		space_left -= copy_size;
+
+		duk_pop(ctx);
 	}
 
-	d = ((duk_double_t) tv.tv_sec) * 1000.0 +
-	    ((duk_double_t) (tv.tv_usec / 1000));
-	DUK_ASSERT(DUK_FLOOR(d) == d);  /* no fractions */
+	h_val = duk_get_hbuffer(ctx, -1);
+	DUK_ASSERT(h_val != NULL);
 
-	return d;
-}
-#endif  /* DUK_USE_DATE_NOW_GETTIMEOFDAY */
+	duk__set_bufobj_buffer(ctx, h_bufres, h_val);
+	DUK_ASSERT_HBUFFEROBJECT_VALID(h_bufres);
 
-#ifdef DUK_USE_DATE_NOW_TIME
-/* Not a very good provider: only full seconds are available. */
-duk_double_t duk_bi_date_get_now(duk_context *ctx) {
-	time_t t = time(NULL);
-	return ((duk_double_t) t) * 1000.0;
-}
-#endif  /* DUK_USE_DATE_NOW_TIME */
+	duk_pop(ctx);  /* pop plain buffer, now reachable through h_bufres */
 
-#if defined(DUK_USE_DATE_NOW_WINDOWS) || defined(DUK_USE_DATE_TZO_WINDOWS)
-/* Shared Windows helpers. */
-static void duk__convert_systime_to_ularge(const SYSTEMTIME *st, ULARGE_INTEGER *res) {
-	FILETIME ft;
-	if (SystemTimeToFileTime(st, &ft) == 0) {
-		DUK_D(DUK_DPRINT("SystemTimeToFileTime() failed, returning 0"));
-		res->QuadPart = 0;
-	} else {
-		res->LowPart = ft.dwLowDateTime;
-		res->HighPart = ft.dwHighDateTime;
-	}
+	return 1;  /* return h_bufres */
 }
-static void duk__set_systime_jan1970(SYSTEMTIME *st) {
-	DUK_MEMZERO((void *) st, sizeof(*st));
-	st->wYear = 1970;
-	st->wMonth = 1;
-	st->wDayOfWeek = 4;  /* not sure whether or not needed; Thursday */
-	st->wDay = 1;
-	DUK_ASSERT(st->wHour == 0);
-	DUK_ASSERT(st->wMinute == 0);
-	DUK_ASSERT(st->wSecond == 0);
-	DUK_ASSERT(st->wMilliseconds == 0);
+#else  /* DUK_USE_BUFFEROBJECT_SUPPORT */
+DUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_concat(duk_context *ctx) {
+	DUK_UNREF(ctx);
+	return DUK_RET_UNSUPPORTED_ERROR;
 }
-#endif  /* defined(DUK_USE_DATE_NOW_WINDOWS) || defined(DUK_USE_DATE_TZO_WINDOWS) */
+#endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
 
-#ifdef DUK_USE_DATE_NOW_WINDOWS
-duk_double_t duk_bi_date_get_now(duk_context *ctx) {
-	/* Suggested step-by-step method from documentation of RtlTimeToSecondsSince1970:
-	 * http://msdn.microsoft.com/en-us/library/windows/desktop/ms724928(v=vs.85).aspx
-	 */
-	SYSTEMTIME st1, st2;
-	ULARGE_INTEGER tmp1, tmp2;
+/*
+ *  Shared readfield and writefield methods
+ *
+ *  The readfield/writefield methods need support for endianness and field
+ *  types.  All offsets are byte based so no offset shifting is needed.
+ */
+
+#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
+/* Format of magic, bits:
+ *   0...1: field type; 0=uint8, 1=uint16, 2=uint32, 3=float, 4=double, 5=unused, 6=unused, 7=unused
+ *       3: endianness: 0=little, 1=big
+ *       4: signed: 1=yes, 0=no
+ *       5: typedarray: 1=yes, 0=no
+ */
+#define  DUK__FLD_8BIT         0
+#define  DUK__FLD_16BIT        1
+#define  DUK__FLD_32BIT        2
+#define  DUK__FLD_FLOAT        3
+#define  DUK__FLD_DOUBLE       4
+#define  DUK__FLD_VARINT       5
+#define  DUK__FLD_BIGENDIAN    (1 << 3)
+#define  DUK__FLD_SIGNED       (1 << 4)
+#define  DUK__FLD_TYPEDARRAY   (1 << 5)
+
+/* XXX: split into separate functions for each field type? */
+DUK_INTERNAL duk_ret_t duk_bi_buffer_readfield(duk_context *ctx) {
+	duk_hthread *thr;
+	duk_small_int_t magic = (duk_small_int_t) duk_get_current_magic(ctx);
+	duk_small_int_t magic_ftype;
+	duk_small_int_t magic_bigendian;
+	duk_small_int_t magic_signed;
+	duk_small_int_t magic_typedarray;
+	duk_small_int_t endswap;
+	duk_hbufferobject *h_this;
+	duk_bool_t no_assert;
+	duk_int_t offset_signed;
+	duk_uint_t offset;
+	duk_uint_t buffer_length;
+	duk_uint_t check_length;
+	duk_uint8_t *buf;
+	duk_double_union du;
 
-	DUK_UNREF(ctx);
+	thr = (duk_hthread *) ctx;
+	DUK_UNREF(thr);
 
-	GetSystemTime(&st1);
-	duk__convert_systime_to_ularge((const SYSTEMTIME *) &st1, &tmp1);
+	magic_ftype = magic & 0x0007;
+	magic_bigendian = magic & 0x0008;
+	magic_signed = magic & 0x0010;
+	magic_typedarray = magic & 0x0020;
 
-	duk__set_systime_jan1970(&st2);
-	duk__convert_systime_to_ularge((const SYSTEMTIME *) &st2, &tmp2);
+	h_this = duk__require_bufobj_this(ctx);
+	DUK_ASSERT(h_this != NULL);
+	buffer_length = h_this->length;
 
-	/* Difference is in 100ns units, convert to milliseconds w/o fractions */
-	return (duk_double_t) ((tmp1.QuadPart - tmp2.QuadPart) / 10000LL);
-}
-#endif  /* DUK_USE_DATE_NOW_WINDOWS */
+	/* [ offset noAssert                 ], when ftype != DUK__FLD_VARINT */
+	/* [ offset fieldByteLength noAssert ], when ftype == DUK__FLD_VARINT */
+	/* [ offset littleEndian             ], when DUK__FLD_TYPEDARRAY (regardless of ftype) */
 
-#if defined(DUK_USE_DATE_TZO_GMTIME) || defined(DUK_USE_DATE_TZO_GMTIME_R)
-/* Get local time offset (in seconds) for a certain (UTC) instant 'd'. */
-static duk_int_t duk__get_local_tzoffset(duk_double_t d) {
-	time_t t, t1, t2;
-	duk_int_t parts[DUK__NUM_PARTS];
-	duk_double_t dparts[DUK__NUM_PARTS];
-	struct tm tms[2];
-#ifdef DUK_USE_DATE_TZO_GMTIME
-	struct tm *tm_ptr;
+	/* Handle TypedArray vs. Node.js Buffer arg differences */
+	if (magic_typedarray) {
+		no_assert = 0;
+#if defined(DUK_USE_INTEGER_LE)
+		endswap = !duk_to_boolean(ctx, 1);  /* 1=little endian */
+#else
+		endswap = duk_to_boolean(ctx, 1);  /* 1=little endian */
+#endif
+	} else {
+		no_assert = duk_to_boolean(ctx, (magic_ftype == DUK__FLD_VARINT) ? 2 : 1);
+#if defined(DUK_USE_INTEGER_LE)
+		endswap = magic_bigendian;
+#else
+		endswap = !magic_bigendian;
 #endif
-
-	/* For NaN/inf, the return value doesn't matter. */
-	if (!DUK_ISFINITE(d)) {
-		return 0;
 	}
 
-	/*
-	 *  This is a bit tricky to implement portably.  The result depends
-	 *  on the timestamp (specifically, DST depends on the timestamp).
-	 *  If e.g. UNIX APIs are used, they'll have portability issues with
-	 *  very small and very large years.
-	 *
-	 *  Current approach:
-	 *
-	 *  - Clamp year to stay within portable UNIX limits.  Avoid 2038 as
-	 *    some conversions start to fail.  Avoid 1970, as some conversions
-	 *    in January 1970 start to fail (verified in practice).
-	 *
-	 *  - Create a UTC time breakdown from 't', and then pretend it is a
-	 *    local time breakdown and build a UTC time from it.  The timestamp
-	 *    will effectively shift backwards by time the time offset (e.g. -2h
-	 *    or -3h for EET/EEST).  Convert with mktime() twice to get the DST
-	 *    flag for the final conversion.
-	 *
-	 *  FIXME: this is probably not entirely correct nor clear, but is
-	 *  good enough for now.
+	/* Offset is coerced first to signed integer range and then to unsigned.
+	 * This ensures we can add a small byte length (1-8) to the offset in
+	 * bound checks and not wrap.
 	 */
+	offset_signed = duk_to_int(ctx, 0);
+	offset = (duk_uint_t) offset_signed;
+	if (offset_signed < 0) {
+		goto fail_bounds;
+	}
 
-	duk__timeval_to_parts(d, parts, dparts, 0 /*flags*/);
+	DUK_DDD(DUK_DDDPRINT("readfield, buffer_length=%ld, offset=%ld, no_assert=%d, "
+	                     "magic=%04x, magic_fieldtype=%d, magic_bigendian=%d, magic_signed=%d, "
+	                     "endswap=%d",
+	                     (long) buffer_length, (long) offset, (int) no_assert,
+	                     (unsigned int) magic, (int) magic_ftype, (int) (magic_bigendian >> 3),
+	                     (int) (magic_signed >> 4), (int) endswap));
 
-	/*
-	 *  FIXME: must choose 'equivalent year', E5 Section 15.9.1.8, instead
-	 *  of just clamping.
+	/* Update 'buffer_length' to be the effective, safe limit which
+	 * takes into account the underlying buffer.  This value will be
+	 * potentially invalidated by any side effect.
 	 */
-	if (parts[DUK__IDX_YEAR] < 1971) {
-		dparts[DUK__IDX_YEAR] = 1971.0;
-	} else if (parts[DUK__IDX_YEAR] > 2037) {
-		dparts[DUK__IDX_YEAR] = 2037.0;
+	check_length = DUK_HBUFFEROBJECT_CLAMP_BYTELENGTH(h_this, buffer_length);
+	DUK_DDD(DUK_DDDPRINT("buffer_length=%ld, check_length=%ld",
+	                     (long) buffer_length, (long) check_length));
+
+	if (h_this->buf) {
+		buf = DUK_HBUFFEROBJECT_GET_SLICE_BASE(thr->heap, h_this);
+	} else {
+		/* neutered, value doesn't matter because check_length is 0. */
+		DUK_ASSERT(check_length == 0);
+		buf = NULL;
 	}
 
-	d = duk__get_timeval_from_dparts(dparts, 0 /*flags*/);
-	DUK_ASSERT(d >= 0 && d < 2147483648.0 * 1000.0);  /* unsigned 31-bit range */
-	t = (time_t) (d / 1000.0);
-	DUK_DDD(DUK_DDDPRINT("timeval: %lf -> time_t %ld", (double) d, (long) t));
+	switch (magic_ftype) {
+	case DUK__FLD_8BIT: {
+		duk_uint8_t tmp;
+		if (offset + 1U > check_length) {
+			goto fail_bounds;
+		}
+		tmp = buf[offset];
+		if (magic_signed) {
+			duk_push_int(ctx, (duk_int_t) ((duk_int8_t) tmp));
+		} else {
+			duk_push_uint(ctx, (duk_uint_t) tmp);
+		}
+		break;
+	}
+	case DUK__FLD_16BIT: {
+		duk_uint16_t tmp;
+		if (offset + 2U > check_length) {
+			goto fail_bounds;
+		}
+		DUK_MEMCPY((void *) du.uc, (const void *) (buf + offset), 2);
+		tmp = du.us[0];
+		if (endswap) {
+			tmp = DUK_BSWAP16(tmp);
+		}
+		if (magic_signed) {
+			duk_push_int(ctx, (duk_int_t) ((duk_int16_t) tmp));
+		} else {
+			duk_push_uint(ctx, (duk_uint_t) tmp);
+		}
+		break;
+	}
+	case DUK__FLD_32BIT: {
+		duk_uint32_t tmp;
+		if (offset + 4U > check_length) {
+			goto fail_bounds;
+		}
+		DUK_MEMCPY((void *) du.uc, (const void *) (buf + offset), 4);
+		tmp = du.ui[0];
+		if (endswap) {
+			tmp = DUK_BSWAP32(tmp);
+		}
+		if (magic_signed) {
+			duk_push_int(ctx, (duk_int_t) ((duk_int32_t) tmp));
+		} else {
+			duk_push_uint(ctx, (duk_uint_t) tmp);
+		}
+		break;
+	}
+	case DUK__FLD_FLOAT: {
+		duk_uint32_t tmp;
+		if (offset + 4U > check_length) {
+			goto fail_bounds;
+		}
+		DUK_MEMCPY((void *) du.uc, (const void *) (buf + offset), 4);
+		if (endswap) {
+			tmp = du.ui[0];
+			tmp = DUK_BSWAP32(tmp);
+			du.ui[0] = tmp;
+		}
+		duk_push_number(ctx, (duk_double_t) du.f[0]);
+		break;
+	}
+	case DUK__FLD_DOUBLE: {
+		if (offset + 8U > check_length) {
+			goto fail_bounds;
+		}
+		DUK_MEMCPY((void *) du.uc, (const void *) (buf + offset), 8);
+		if (endswap) {
+			DUK_DBLUNION_BSWAP64(&du);
+		}
+		duk_push_number(ctx, (duk_double_t) du.d);
+		break;
+	}
+	case DUK__FLD_VARINT: {
+		/* Node.js Buffer variable width integer field.  We don't really
+		 * care about speed here, so aim for shortest algorithm.
+		 */
+		duk_int_t field_bytelen;
+		duk_int_t i, i_step, i_end;
+#if defined(DUK_USE_64BIT_OPS)
+		duk_int64_t tmp;
+		duk_small_uint_t shift_tmp;
+#else
+		duk_double_t tmp;
+		duk_small_int_t highbyte;
+#endif
+		const duk_uint8_t *p;
 
-	t1 = t;
+		field_bytelen = duk_get_int(ctx, 1);  /* avoid side effects! */
+		if (field_bytelen < 1 || field_bytelen > 6) {
+			goto fail_field_length;
+		}
+		if (offset + (duk_uint_t) field_bytelen > check_length) {
+			goto fail_bounds;
+		}
+		p = (const duk_uint8_t *) (buf + offset);
 
-	DUK_MEMZERO((void *) tms, sizeof(struct tm) * 2);
+		/* Slow gathering of value using either 64-bit arithmetic
+		 * or IEEE doubles if 64-bit types not available.  Handling
+		 * of negative numbers is a bit non-obvious in both cases.
+		 */
 
-#if defined(DUK_USE_DATE_TZO_GMTIME_R)
-	(void) gmtime_r(&t, &tms[0]);
-#elif defined(DUK_USE_DATE_TZO_GMTIME)
-	tm_ptr = gmtime(&t);
-	DUK_MEMCPY((void *) &tms[0], tm_ptr, sizeof(struct tm));
+		if (magic_bigendian) {
+			/* Gather in big endian */
+			i = 0;
+			i_step = 1;
+			i_end = field_bytelen;  /* one i_step over */
+		} else {
+			/* Gather in little endian */
+			i = field_bytelen - 1;
+			i_step = -1;
+			i_end = -1;  /* one i_step over */
+		}
+
+#if defined(DUK_USE_64BIT_OPS)
+		tmp = 0;
+		do {
+			DUK_ASSERT(i >= 0 && i < field_bytelen);
+			tmp = (tmp << 8) + (duk_int64_t) p[i];
+			i += i_step;
+		} while (i != i_end);
+
+		if (magic_signed) {
+			/* Shift to sign extend. */
+			shift_tmp = 64 - (field_bytelen * 8);
+			tmp = (tmp << shift_tmp) >> shift_tmp;
+		}
+
+		duk_push_i64(ctx, tmp);
 #else
-#error internal error
+		highbyte = p[i];
+		if (magic_signed && (highbyte & 0x80) != 0) {
+			/* 0xff => 255 - 256 = -1; 0x80 => 128 - 256 = -128 */
+			tmp = (duk_double_t) (highbyte - 256);
+		} else {
+			tmp = (duk_double_t) highbyte;
+		}
+		for (;;) {
+			i += i_step;
+			if (i == i_end) {
+				break;
+			}
+			DUK_ASSERT(i >= 0 && i < field_bytelen);
+			tmp = (tmp * 256.0) + (duk_double_t) p[i];
+		}
+
+		duk_push_number(ctx, tmp);
 #endif
-	DUK_MEMCPY((void *) &tms[1], &tms[0], sizeof(struct tm));
+		break;
+	}
+	default: {  /* should never happen but default here */
+		goto fail_bounds;
+	}
+	}
 
-	DUK_DDD(DUK_DDDPRINT("before mktime: tm={sec:%ld,min:%ld,hour:%ld,mday:%ld,mon:%ld,year:%ld,"
-	                     "wday:%ld,yday:%ld,isdst:%ld}",
-	                     (long) tms[0].tm_sec, (long) tms[0].tm_min, (long) tms[0].tm_hour,
-	                     (long) tms[0].tm_mday, (long) tms[0].tm_mon, (long) tms[0].tm_year,
-	                     (long) tms[0].tm_wday, (long) tms[0].tm_yday, (long) tms[0].tm_isdst));
+	return 1;
 
-	(void) mktime(&tms[0]);
-	tms[1].tm_isdst = tms[0].tm_isdst;
-	t2 = mktime(&tms[1]);
-	DUK_ASSERT_DISABLE(t2 >= 0);  /* On some platforms time_t is unsigned and this would cause a warning */
-	if (t2 == (time_t) -1) {
-		/* This check used to be for (t2 < 0) but on some platforms
-		 * time_t is unsigned and apparently the proper way to detect
-		 * an mktime() error return is the cast above.  See e.g.:
-		 * http://pubs.opengroup.org/onlinepubs/009695299/functions/mktime.html
+ fail_field_length:
+ fail_bounds:
+	if (no_assert) {
+		/* Node.js return value for noAssert out-of-bounds reads is
+		 * usually (but not always) NaN.  Return NaN consistently.
 		 */
-		goto error;
+		duk_push_nan(ctx);
+		return 1;
 	}
 
-	DUK_DDD(DUK_DDDPRINT("after mktime: tm={sec:%ld,min:%ld,hour:%ld,mday:%ld,mon:%ld,year:%ld,"
-	                     "wday:%ld,yday:%ld,isdst:%ld}",
-	                     (long) tms[1].tm_sec, (long) tms[1].tm_min, (long) tms[1].tm_hour,
-	                     (long) tms[1].tm_mday, (long) tms[1].tm_mon, (long) tms[1].tm_year,
-	                     (long) tms[1].tm_wday, (long) tms[1].tm_yday, (long) tms[1].tm_isdst));
-	DUK_DDD(DUK_DDDPRINT("t2=%ld", (long) t2));
+	return DUK_RET_RANGE_ERROR;
+}
+#else  /* DUK_USE_BUFFEROBJECT_SUPPORT */
+DUK_INTERNAL duk_ret_t duk_bi_buffer_readfield(duk_context *ctx) {
+	DUK_UNREF(ctx);
+	return DUK_RET_UNSUPPORTED_ERROR;
+}
+#endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
 
-	/* Positive if local time ahead of UTC. */
+#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
+/* XXX: split into separate functions for each field type? */
+DUK_INTERNAL duk_ret_t duk_bi_buffer_writefield(duk_context *ctx) {
+	duk_hthread *thr;
+	duk_small_int_t magic = (duk_small_int_t) duk_get_current_magic(ctx);
+	duk_small_int_t magic_ftype;
+	duk_small_int_t magic_bigendian;
+	duk_small_int_t magic_signed;
+	duk_small_int_t magic_typedarray;
+	duk_small_int_t endswap;
+	duk_hbufferobject *h_this;
+	duk_bool_t no_assert;
+	duk_int_t offset_signed;
+	duk_uint_t offset;
+	duk_uint_t buffer_length;
+	duk_uint_t check_length;
+	duk_uint8_t *buf;
+	duk_double_union du;
+	duk_int_t nbytes = 0;
 
-	/* difftime() returns a double, so coercion to int generates quite
-	 * a lot of code.  Direct subtraction is not portable, however.
-	 *
-	 * XXX: allow direct subtraction on known platforms.
-	 */
-#if 0
-	return (duk_int_t) (t1 - t2);
-#endif
-	return (duk_int_t) difftime(t1, t2);
+	thr = (duk_hthread *) ctx;
+	DUK_UNREF(thr);
 
- error:
-	/* FIXME: return something more useful, so that caller can throw? */
-	DUK_D(DUK_DPRINT("mktime() failed, d=%lf", (double) d));
-	return 0;
-}
-#endif  /* DUK_USE_DATE_TZO_GMTIME */
+	magic_ftype = magic & 0x0007;
+	magic_bigendian = magic & 0x0008;
+	magic_signed = magic & 0x0010;
+	magic_typedarray = magic & 0x0020;
+	DUK_UNREF(magic_signed);
 
-#if defined(DUK_USE_DATE_TZO_WINDOWS)
-static duk_int_t duk__get_local_tzoffset(duk_double_t d) {
-	SYSTEMTIME st1;
-	SYSTEMTIME st2;
-	SYSTEMTIME st3;
-	ULARGE_INTEGER tmp1;
-	ULARGE_INTEGER tmp2;
-	ULARGE_INTEGER tmp3;
-	FILETIME ft1;
+	h_this = duk__require_bufobj_this(ctx);
+	DUK_ASSERT(h_this != NULL);
+	buffer_length = h_this->length;
 
-	/* Use the approach described in "Remarks" of FileTimeToLocalFileTime:
-	 * http://msdn.microsoft.com/en-us/library/windows/desktop/ms724277(v=vs.85).aspx
-	 */
+	/* [ value  offset noAssert                 ], when ftype != DUK__FLD_VARINT */
+	/* [ value  offset fieldByteLength noAssert ], when ftype == DUK__FLD_VARINT */
+	/* [ offset value  littleEndian             ], when DUK__FLD_TYPEDARRAY (regardless of ftype) */
 
-	duk__set_systime_jan1970(&st1);
-	duk__convert_systime_to_ularge((const SYSTEMTIME *) &st1, &tmp1);
-	tmp2.QuadPart = (ULONGLONG) (d * 10000.0);  /* millisec -> 100ns units since jan 1, 1970 */
-	tmp2.QuadPart += tmp1.QuadPart;             /* input 'd' in Windows UTC, 100ns units */
+	/* Handle TypedArray vs. Node.js Buffer arg differences */
+	if (magic_typedarray) {
+		no_assert = 0;
+#if defined(DUK_USE_INTEGER_LE)
+		endswap = !duk_to_boolean(ctx, 2);  /* 1=little endian */
+#else
+		endswap = duk_to_boolean(ctx, 2);  /* 1=little endian */
+#endif
+		duk_swap(ctx, 0, 1);  /* offset/value order different from Node.js */
+	} else {
+		no_assert = duk_to_boolean(ctx, (magic_ftype == DUK__FLD_VARINT) ? 3 : 2);
+#if defined(DUK_USE_INTEGER_LE)
+		endswap = magic_bigendian;
+#else
+		endswap = !magic_bigendian;
+#endif
+	}
 
-	ft1.dwLowDateTime = tmp2.LowPart;
-	ft1.dwHighDateTime = tmp2.HighPart;
-	FileTimeToSystemTime((const FILETIME *) &ft1, &st2);
-	if (SystemTimeToTzSpecificLocalTime((LPTIME_ZONE_INFORMATION) NULL, &st2, &st3) == 0) {
-		DUK_D(DUK_DPRINT("SystemTimeToTzSpecificLocalTime() failed, return tzoffset 0"));
-		return 0;
+	/* Offset is coerced first to signed integer range and then to unsigned.
+	 * This ensures we can add a small byte length (1-8) to the offset in
+	 * bound checks and not wrap.
+	 */
+	offset_signed = duk_to_int(ctx, 1);
+	offset = (duk_uint_t) offset_signed;
+
+	/* We need 'nbytes' even for a failed offset; return value must be
+	 * (offset + nbytes) even when write fails due to invalid offset.
+	 */
+	if (magic_ftype != DUK__FLD_VARINT) {
+		DUK_ASSERT(magic_ftype >= 0 && magic_ftype < (duk_small_int_t) (sizeof(duk__buffer_nbytes_from_fldtype) / sizeof(duk_uint8_t)));
+		nbytes = duk__buffer_nbytes_from_fldtype[magic_ftype];
+	} else {
+		nbytes = duk_get_int(ctx, 2);
+		if (nbytes < 1 || nbytes > 6) {
+			goto fail_field_length;
+		}
 	}
-	duk__convert_systime_to_ularge((const SYSTEMTIME *) &st3, &tmp3);
+	DUK_ASSERT(nbytes >= 1 && nbytes <= 8);
 
-	/* Positive if local time ahead of UTC. */
-	return (duk_int_t) (((LONGLONG) tmp3.QuadPart - (LONGLONG) tmp2.QuadPart) / 10000000LL);  /* seconds */
-}
-#endif  /* DUK_USE_DATE_TZO_WINDOWS */
+	/* Now we can check offset validity. */
+	if (offset_signed < 0) {
+		goto fail_bounds;
+	}
 
-#ifdef DUK_USE_DATE_PRS_STRPTIME
-static duk_bool_t duk__parse_string_strptime(duk_context *ctx, const char *str) {
-	struct tm tm;
-	time_t t;
-	char buf[DUK__STRPTIME_BUF_SIZE];
+	DUK_DDD(DUK_DDDPRINT("writefield, value=%!T, buffer_length=%ld, offset=%ld, no_assert=%d, "
+	                     "magic=%04x, magic_fieldtype=%d, magic_bigendian=%d, magic_signed=%d, "
+	                     "endswap=%d",
+	                     duk_get_tval(ctx, 0), (long) buffer_length, (long) offset, (int) no_assert,
+	                     (unsigned int) magic, (int) magic_ftype, (int) (magic_bigendian >> 3),
+	                     (int) (magic_signed >> 4), (int) endswap));
 
-	/* copy to buffer with spare to avoid Valgrind gripes from strptime */
-	DUK_ASSERT(str != NULL);
-	DUK_MEMZERO(buf, sizeof(buf));  /* valgrind whine without this */
-	DUK_SNPRINTF(buf, sizeof(buf), "%s", (const char *) str);
-	buf[sizeof(buf) - 1] = (char) 0;
+	/* Coerce value to a number before computing check_length, so that
+	 * the field type specific coercion below can't have side effects
+	 * that would invalidate check_length.
+	 */
+	duk_to_number(ctx, 0);
 
-	DUK_DDD(DUK_DDDPRINT("parsing: '%s'", (const char *) buf));
+	/* Update 'buffer_length' to be the effective, safe limit which
+	 * takes into account the underlying buffer.  This value will be
+	 * potentially invalidated by any side effect.
+	 */
+	check_length = DUK_HBUFFEROBJECT_CLAMP_BYTELENGTH(h_this, buffer_length);
+	DUK_DDD(DUK_DDDPRINT("buffer_length=%ld, check_length=%ld",
+	                     (long) buffer_length, (long) check_length));
 
-	DUK_MEMZERO(&tm, sizeof(tm));
-	if (strptime((const char *) buf, "%c", &tm) != NULL) {
-		DUK_DDD(DUK_DDDPRINT("before mktime: tm={sec:%ld,min:%ld,hour:%ld,mday:%ld,mon:%ld,year:%ld,"
-		                     "wday:%ld,yday:%ld,isdst:%ld}",
-		                     (long) tm.tm_sec, (long) tm.tm_min, (long) tm.tm_hour,
-		                     (long) tm.tm_mday, (long) tm.tm_mon, (long) tm.tm_year,
-		                      (long) tm.tm_wday, (long) tm.tm_yday, (long) tm.tm_isdst));
-		tm.tm_isdst = -1;  /* negative: dst info not available */
+	if (h_this->buf) {
+		buf = DUK_HBUFFEROBJECT_GET_SLICE_BASE(thr->heap, h_this);
+	} else {
+		/* neutered, value doesn't matter because check_length is 0. */
+		DUK_ASSERT(check_length == 0);
+		buf = NULL;
+	}
 
-		t = mktime(&tm);
-		DUK_DDD(DUK_DDDPRINT("mktime() -> %ld", (long) t));
-		if (t >= 0) {
-			duk_push_number(ctx, ((duk_double_t) t) * 1000.0);
-			return 1;
+	switch (magic_ftype) {
+	case DUK__FLD_8BIT: {
+		if (offset + 1U > check_length) {
+			goto fail_bounds;
+		}
+		/* sign doesn't matter when writing */
+		buf[offset] = (duk_uint8_t) duk_to_uint32(ctx, 0);
+		break;
+	}
+	case DUK__FLD_16BIT: {
+		duk_uint16_t tmp;
+		if (offset + 2U > check_length) {
+			goto fail_bounds;
+		}
+		tmp = (duk_uint16_t) duk_to_uint32(ctx, 0);
+		if (endswap) {
+			tmp = DUK_BSWAP16(tmp);
 		}
+		du.us[0] = tmp;
+		/* sign doesn't matter when writing */
+		DUK_MEMCPY((void *) (buf + offset), (const void *) du.uc, 2);
+		break;
+	}
+	case DUK__FLD_32BIT: {
+		duk_uint32_t tmp;
+		if (offset + 4U > check_length) {
+			goto fail_bounds;
+		}
+		tmp = (duk_uint32_t) duk_to_uint32(ctx, 0);
+		if (endswap) {
+			tmp = DUK_BSWAP32(tmp);
+		}
+		du.ui[0] = tmp;
+		/* sign doesn't matter when writing */
+		DUK_MEMCPY((void *) (buf + offset), (const void *) du.uc, 4);
+		break;
+	}
+	case DUK__FLD_FLOAT: {
+		duk_uint32_t tmp;
+		if (offset + 4U > check_length) {
+			goto fail_bounds;
+		}
+		du.f[0] = (duk_float_t) duk_to_number(ctx, 0);
+		if (endswap) {
+			tmp = du.ui[0];
+			tmp = DUK_BSWAP32(tmp);
+			du.ui[0] = tmp;
+		}
+		/* sign doesn't matter when writing */
+		DUK_MEMCPY((void *) (buf + offset), (const void *) du.uc, 4);
+		break;
+	}
+	case DUK__FLD_DOUBLE: {
+		if (offset + 8U > check_length) {
+			goto fail_bounds;
+		}
+		du.d = (duk_double_t) duk_to_number(ctx, 0);
+		if (endswap) {
+			DUK_DBLUNION_BSWAP64(&du);
+		}
+		/* sign doesn't matter when writing */
+		DUK_MEMCPY((void *) (buf + offset), (const void *) du.uc, 8);
+		break;
 	}
+	case DUK__FLD_VARINT: {
+		/* Node.js Buffer variable width integer field.  We don't really
+		 * care about speed here, so aim for shortest algorithm.
+		 */
+		duk_int_t field_bytelen;
+		duk_int_t i, i_step, i_end;
+#if defined(DUK_USE_64BIT_OPS)
+		duk_int64_t tmp;
+#else
+		duk_double_t tmp;
+#endif
+		duk_uint8_t *p;
 
-	return 0;
-}
-#endif  /* DUK_USE_DATE_PRS_STRPTIME */
+		field_bytelen = (duk_int_t) nbytes;
+		if (offset + (duk_uint_t) field_bytelen > check_length) {
+			goto fail_bounds;
+		}
 
-#ifdef DUK_USE_DATE_PRS_GETDATE
-static duk_bool_t duk__parse_string_getdate(duk_context *ctx, const char *str) {
-	struct tm tm;
-	duk_small_int_t rc;
-	time_t t;
+		/* Slow writing of value using either 64-bit arithmetic
+		 * or IEEE doubles if 64-bit types not available.  There's
+		 * no special sign handling when writing varints.
+		 */
 
-	/* For this to work, DATEMSK must be set, so this is not very
-	 * convenient for an embeddable interpreter.
-	 */
+		if (magic_bigendian) {
+			/* Write in big endian */
+			i = field_bytelen;  /* one i_step added at top of loop */
+			i_step = -1;
+			i_end = 0;
+		} else {
+			/* Write in little endian */
+			i = -1;  /* one i_step added at top of loop */
+			i_step = 1;
+			i_end = field_bytelen - 1;
+		}
 
-	DUK_MEMZERO(&tm, sizeof(struct tm));
-	rc = (duk_small_int_t) getdate_r(str, &tm);
-	DUK_DDD(DUK_DDDPRINT("getdate_r() -> %ld", (long) rc));
+		/* XXX: The duk_to_number() cast followed by integer coercion
+		 * is platform specific so NaN, +/- Infinity, and out-of-bounds
+		 * values result in platform specific output now.
+		 * See: test-bi-nodejs-buffer-proto-varint-special.js
+		 */
 
-	if (rc == 0) {
-		t = mktime(&tm);
-		DUK_DDD(DUK_DDDPRINT("mktime() -> %ld", (long) t));
-		if (t >= 0) {
-			duk_push_number(ctx, (duk_double_t) t);
-			return 1;
-		}
+#if defined(DUK_USE_64BIT_OPS)
+		tmp = (duk_int64_t) duk_to_number(ctx, 0);
+		p = (duk_uint8_t *) (buf + offset);
+		do {
+			i += i_step;
+			DUK_ASSERT(i >= 0 && i < field_bytelen);
+			p[i] = (duk_uint8_t) (tmp & 0xff);
+			tmp = tmp >> 8;  /* unnecessary shift for last byte */
+		} while (i != i_end);
+#else
+		tmp = duk_to_number(ctx, 0);
+		p = (duk_uint8_t *) (buf + offset);
+		do {
+			i += i_step;
+			tmp = DUK_FLOOR(tmp);
+			DUK_ASSERT(i >= 0 && i < field_bytelen);
+			p[i] = (duk_uint8_t) (DUK_FMOD(tmp, 256.0));
+			tmp = tmp / 256.0;  /* unnecessary div for last byte */
+		} while (i != i_end);
+#endif
+		break;
+	}
+	default: {  /* should never happen but default here */
+		goto fail_bounds;
+	}
 	}
 
-	return 0;
+	/* Node.js Buffer: return offset + #bytes written (i.e. next
+	 * write offset).
+	 */
+	if (magic_typedarray) {
+		/* For TypedArrays 'undefined' return value is specified
+		 * by ES6 (matches V8).
+		 */
+		return 0;
+	}
+	duk_push_uint(ctx, offset + nbytes);
+	return 1;
+
+ fail_field_length:
+ fail_bounds:
+	if (no_assert) {
+		/* Node.js return value for failed writes is offset + #bytes
+		 * that would have been written.
+		 */
+		/* XXX: for negative input offsets, 'offset' will be a large
+		 * positive value so the result here is confusing.
+		 */
+		if (magic_typedarray) {
+			return 0;
+		}
+		duk_push_uint(ctx, offset + nbytes);
+		return 1;
+	}
+	return DUK_RET_RANGE_ERROR;
 }
-#endif  /* DUK_USE_DATE_PRS_GETDATE */
+#else  /* DUK_USE_BUFFEROBJECT_SUPPORT */
+DUK_INTERNAL duk_ret_t duk_bi_buffer_writefield(duk_context *ctx) {
+	DUK_UNREF(ctx);
+	return DUK_RET_UNSUPPORTED_ERROR;
+}
+#endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
+
+#undef  DUK__FLD_8BIT
+#undef  DUK__FLD_16BIT
+#undef  DUK__FLD_32BIT
+#undef  DUK__FLD_FLOAT
+#undef  DUK__FLD_DOUBLE
+#undef  DUK__FLD_VARINT
+#undef  DUK__FLD_BIGENDIAN
+#undef  DUK__FLD_SIGNED
+#undef  DUK__FLD_TYPEDARRAY
+#line 1 "duk_bi_date.c"
+/*
+ *  Date built-ins
+ *
+ *  Unlike most built-ins, Date has some platform dependencies for getting
+ *  UTC time, converting between UTC and local time, and parsing and
+ *  formatting time values.  These are all abstracted behind DUK_USE_xxx
+ *  config options.  There are built-in platform specific providers for
+ *  POSIX and Windows, but external providers can also be used.
+ *
+ *  See doc/datetime.rst.
+ *
+ */
 
-#ifdef DUK_USE_DATE_FMT_STRFTIME
-static duk_bool_t duk__format_parts_strftime(duk_context *ctx, duk_int_t *parts, duk_int_t tzoffset, duk_small_uint_t flags) {
-	char buf[DUK__STRFTIME_BUF_SIZE];
-	struct tm tm;
-	const char *fmt;
+/* include removed: duk_internal.h */
 
-	DUK_UNREF(tzoffset);
+/*
+ *  Forward declarations
+ */
 
-	/* If the platform doesn't support the entire Ecmascript range, we need
-	 * to return 0 so that the caller can fall back to the default formatter.
-	 *
-	 * For now, assume that if time_t is 8 bytes or more, the whole Ecmascript
-	 * range is supported.  For smaller time_t values (4 bytes in practice),
-	 * assumes that the signed 32-bit range is supported.
-	 *
-	 * XXX: detect this more correctly per platform.  The size of time_t is
-	 * probably not an accurate guarantee of strftime() supporting or not
-	 * supporting a large time range (the full Ecmascript range).
+DUK_LOCAL_DECL duk_double_t duk__push_this_get_timeval_tzoffset(duk_context *ctx, duk_small_uint_t flags, duk_int_t *out_tzoffset);
+DUK_LOCAL_DECL duk_double_t duk__push_this_get_timeval(duk_context *ctx, duk_small_uint_t flags);
+DUK_LOCAL_DECL void duk__twodigit_year_fixup(duk_context *ctx, duk_idx_t idx_val);
+DUK_LOCAL_DECL duk_ret_t duk__set_this_timeval_from_dparts(duk_context *ctx, duk_double_t *dparts, duk_small_uint_t flags);
+
+/*
+ *  Other file level defines
+ */
+
+/* Debug macro to print all parts and dparts (used manually because of debug level). */
+#define  DUK__DPRINT_PARTS_AND_DPARTS(parts,dparts)  do { \
+		DUK_D(DUK_DPRINT("parts: %ld %ld %ld %ld %ld %ld %ld %ld, dparts: %lf %lf %lf %lf %lf %lf %lf %lf", \
+		                 (long) (parts)[0], (long) (parts)[1], \
+		                 (long) (parts)[2], (long) (parts)[3], \
+		                 (long) (parts)[4], (long) (parts)[5], \
+		                 (long) (parts)[6], (long) (parts)[7], \
+		                 (double) (dparts)[0], (double) (dparts)[1], \
+		                 (double) (dparts)[2], (double) (dparts)[3], \
+		                 (double) (dparts)[4], (double) (dparts)[5], \
+		                 (double) (dparts)[6], (double) (dparts)[7])); \
+	} while (0)
+#define  DUK__DPRINT_PARTS(parts)  do { \
+		DUK_D(DUK_DPRINT("parts: %ld %ld %ld %ld %ld %ld %ld %ld", \
+		                 (long) (parts)[0], (long) (parts)[1], \
+		                 (long) (parts)[2], (long) (parts)[3], \
+		                 (long) (parts)[4], (long) (parts)[5], \
+		                 (long) (parts)[6], (long) (parts)[7])); \
+	} while (0)
+#define  DUK__DPRINT_DPARTS(dparts)  do { \
+		DUK_D(DUK_DPRINT("dparts: %lf %lf %lf %lf %lf %lf %lf %lf", \
+		                 (double) (dparts)[0], (double) (dparts)[1], \
+		                 (double) (dparts)[2], (double) (dparts)[3], \
+		                 (double) (dparts)[4], (double) (dparts)[5], \
+		                 (double) (dparts)[6], (double) (dparts)[7])); \
+	} while (0)
+
+/* Equivalent year for DST calculations outside [1970,2038[ range, see
+ * E5 Section 15.9.1.8.  Equivalent year has the same leap-year-ness and
+ * starts with the same weekday on Jan 1.
+ * https://bugzilla.mozilla.org/show_bug.cgi?id=351066
+ */
+#define DUK__YEAR(x) ((duk_uint8_t) ((x) - 1970))
+DUK_LOCAL duk_uint8_t duk__date_equivyear[14] = {
+#if 1
+	/* This is based on V8 EquivalentYear() algorithm (see src/genequivyear.py):
+	 * http://code.google.com/p/v8/source/browse/trunk/src/date.h#146
 	 */
-	if (sizeof(time_t) < 8 &&
-	   (parts[DUK__IDX_YEAR] < 1970 || parts[DUK__IDX_YEAR] > 2037)) {
-		/* be paranoid for 32-bit time values (even avoiding negative ones) */
-		return 0;
-	}
 
-	DUK_MEMZERO(&tm, sizeof(tm));
-	tm.tm_sec = parts[DUK__IDX_SECOND];
-	tm.tm_min = parts[DUK__IDX_MINUTE];
-	tm.tm_hour = parts[DUK__IDX_HOUR];
-	tm.tm_mday = parts[DUK__IDX_DAY];       /* already one-based */
-	tm.tm_mon = parts[DUK__IDX_MONTH] - 1;  /* one-based -> zero-based */
-	tm.tm_year = parts[DUK__IDX_YEAR] - 1900;
-	tm.tm_wday = parts[DUK__IDX_WEEKDAY];
-	tm.tm_isdst = 0;
+	/* non-leap year: sunday, monday, ... */
+	DUK__YEAR(2023), DUK__YEAR(2035), DUK__YEAR(2019), DUK__YEAR(2031),
+	DUK__YEAR(2015), DUK__YEAR(2027), DUK__YEAR(2011),
 
-	DUK_MEMZERO(buf, sizeof(buf));
-	if ((flags & DUK__FLAG_TOSTRING_DATE) && (flags & DUK__FLAG_TOSTRING_TIME)) {
-		fmt = "%c";
-	} else if (flags & DUK__FLAG_TOSTRING_DATE) {
-		fmt = "%x";
-	} else {
-		DUK_ASSERT(flags & DUK__FLAG_TOSTRING_TIME);
-		fmt = "%X";
-	}
-	(void) strftime(buf, sizeof(buf) - 1, fmt, &tm);
-	DUK_ASSERT(buf[sizeof(buf) - 1] == 0);
+	/* leap year: sunday, monday, ... */
+	DUK__YEAR(2012), DUK__YEAR(2024), DUK__YEAR(2008), DUK__YEAR(2020),
+	DUK__YEAR(2032), DUK__YEAR(2016), DUK__YEAR(2028)
+#endif
 
-	duk_push_string(ctx, buf);
-	return 1;
-}
-#endif  /* DUK_USE_DATE_FMT_STRFTIME */
+#if 0
+	/* This is based on Rhino EquivalentYear() algorithm:
+	 * https://github.com/mozilla/rhino/blob/f99cc11d616f0cdda2c42bde72b3484df6182947/src/org/mozilla/javascript/NativeDate.java
+	 */
+
+	/* non-leap year: sunday, monday, ... */
+	DUK__YEAR(1978), DUK__YEAR(1973), DUK__YEAR(1985), DUK__YEAR(1986),
+	DUK__YEAR(1981), DUK__YEAR(1971), DUK__YEAR(1977),
+
+	/* leap year: sunday, monday, ... */
+	DUK__YEAR(1984), DUK__YEAR(1996), DUK__YEAR(1980), DUK__YEAR(1992),
+	DUK__YEAR(1976), DUK__YEAR(1988), DUK__YEAR(1972)
+#endif
+};
+#undef DUK__YEAR
 
 /*
  *  ISO 8601 subset parser.
@@ -16164,13 +27810,13 @@ static duk_bool_t duk__format_parts_strftime(duk_context *ctx, duk_int_t *parts,
 #define DUK__RULE_MASK_PART_SEP  0x1ffffUL
 
 /* Matching separator index is used in the control table */
-static const duk_uint8_t duk__parse_iso8601_seps[] = {
+DUK_LOCAL const duk_uint8_t duk__parse_iso8601_seps[] = {
 	DUK_ASC_PLUS /*0*/, DUK_ASC_MINUS /*1*/, DUK_ASC_UC_T /*2*/, DUK_ASC_SPACE /*3*/,
 	DUK_ASC_COLON /*4*/, DUK_ASC_PERIOD /*5*/, DUK_ASC_UC_Z /*6*/, DUK_ASC_NUL /*7*/
 };
 
 /* Rule table: first matching rule is used to determine what to do next. */
-static const duk_uint32_t duk__parse_iso8601_control[] = {
+DUK_LOCAL const duk_uint32_t duk__parse_iso8601_control[] = {
 	DUK__PACK_RULE(DUK__PM_YEAR, DUK__SM_MINUS, DUK__PI_MONTH, 0),
 	DUK__PACK_RULE(DUK__PM_MONTH, DUK__SM_MINUS, DUK__PI_DAY, 0),
 	DUK__PACK_RULE(DUK__PM_YEAR | DUK__PM_MONTH | DUK__PM_DAY, DUK__SM_T | DUK__SM_SPACE, DUK__PI_HOUR, 0),
@@ -16191,9 +27837,9 @@ static const duk_uint32_t duk__parse_iso8601_control[] = {
 	 */
 };
 
-static duk_bool_t duk__parse_string_iso8601_subset(duk_context *ctx, const char *str) {
+DUK_LOCAL duk_bool_t duk__parse_string_iso8601_subset(duk_context *ctx, const char *str) {
 	duk_int_t parts[DUK__NUM_ISO8601_PARSER_PARTS];
-	duk_double_t dparts[DUK__NUM_PARTS];
+	duk_double_t dparts[DUK_DATE_IDX_NUM_PARTS];
 	duk_double_t d;
 	const duk_uint8_t *p;
 	duk_small_uint_t part_idx = 0;
@@ -16206,9 +27852,9 @@ static duk_bool_t duk__parse_string_iso8601_subset(duk_context *ctx, const char
 
 	/* During parsing, month and day are one-based; set defaults here. */
 	DUK_MEMZERO(parts, sizeof(parts));
-	DUK_ASSERT(parts[DUK__IDX_YEAR] == 0);  /* don't care value, year is mandatory */
-	parts[DUK__IDX_MONTH] = 1;
-	parts[DUK__IDX_DAY] = 1;
+	DUK_ASSERT(parts[DUK_DATE_IDX_YEAR] == 0);  /* don't care value, year is mandatory */
+	parts[DUK_DATE_IDX_MONTH] = 1;
+	parts[DUK_DATE_IDX_DAY] = 1;
 
 	/* Special handling for year sign. */
 	p = (const duk_uint8_t *) str;
@@ -16354,17 +28000,17 @@ static duk_bool_t duk__parse_string_iso8601_subset(duk_context *ctx, const char
 
 	/* Use double parts, they tolerate unnormalized time.
 	 *
-	 * Note: DUK__IDX_WEEKDAY is initialized with a bogus value (DUK__PI_TZHOUR)
-	 * on purpose.  It won't be actually used by duk__get_timeval_from_dparts(),
+	 * Note: DUK_DATE_IDX_WEEKDAY is initialized with a bogus value (DUK__PI_TZHOUR)
+	 * on purpose.  It won't be actually used by duk_bi_date_get_timeval_from_dparts(),
 	 * but will make the value initialized just in case, and avoid any
 	 * potential for Valgrind issues.
 	 */
-	for (i = 0; i < DUK__NUM_PARTS; i++) {
+	for (i = 0; i < DUK_DATE_IDX_NUM_PARTS; i++) {
 		DUK_DDD(DUK_DDDPRINT("part[%ld] = %ld", (long) i, (long) parts[i]));
 		dparts[i] = parts[i];
 	}
 
-	d = duk__get_timeval_from_dparts(dparts, 0 /*flags*/);
+	d = duk_bi_date_get_timeval_from_dparts(dparts, 0 /*flags*/);
 	duk_push_number(ctx, d);
 	return 1;
 }
@@ -16381,16 +28027,14 @@ static duk_bool_t duk__parse_string_iso8601_subset(duk_context *ctx, const char
  *  Note in particular that we must parse whatever toString(), toUTCString(),
  *  and toISOString() can produce; see E5.1 Section 15.9.4.2.
  *
- *  Returns 1 to allow tailcalling.
- */
-
-/*
- *  FIXME: check standard behavior and also usual behavior in other
- *  implementations.  For instance, V8 parses '2012-01-01' as UTC and
- *  '2012/01/01' as local time.
+ *  Returns 1 to allow tail calling.
+ *
+ *  There is much room for improvement here with respect to supporting
+ *  alternative datetime formats.  For instance, V8 parses '2012-01-01' as
+ *  UTC and '2012/01/01' as local time.
  */
 
-static duk_ret_t duk__parse_string(duk_context *ctx, const char *str) {
+DUK_LOCAL duk_ret_t duk__parse_string(duk_context *ctx, const char *str) {
 	/* XXX: there is a small risk here: because the ISO 8601 parser is
 	 * very loose, it may end up parsing some datetime values which
 	 * would be better parsed with a platform specific parser.
@@ -16403,12 +28047,13 @@ static duk_ret_t duk__parse_string(duk_context *ctx, const char *str) {
 		return 1;
 	}
 
-#if defined(DUK_USE_DATE_PRS_STRPTIME)
-	if (duk__parse_string_strptime(ctx, str) != 0) {
-		return 1;
-	}
-#elif defined(DUK_USE_DATE_PRS_GETDATE)
-	if (duk__parse_string_getdate(ctx, str) != 0) {
+#if defined(DUK_USE_DATE_PARSE_STRING)
+	/* Contract, either:
+	 * - Push value on stack and return 1
+	 * - Don't push anything on stack and return 0
+	 */
+
+	if (DUK_USE_DATE_PARSE_STRING(ctx, str) != 0) {
 		return 1;
 	}
 #else
@@ -16428,13 +28073,26 @@ static duk_ret_t duk__parse_string(duk_context *ctx, const char *str) {
  *  out for non-finite numbers etc.
  */
 
-static duk_uint8_t duk__days_in_month[12] = {
+DUK_LOCAL duk_uint8_t duk__days_in_month[12] = {
 	(duk_uint8_t) 31, (duk_uint8_t) 28, (duk_uint8_t) 31, (duk_uint8_t) 30,
 	(duk_uint8_t) 31, (duk_uint8_t) 30, (duk_uint8_t) 31, (duk_uint8_t) 31,
 	(duk_uint8_t) 30, (duk_uint8_t) 31, (duk_uint8_t) 30, (duk_uint8_t) 31
 };
 
-static duk_bool_t duk__is_leap_year(duk_int_t year) {
+/* Maximum iteration count for computing UTC-to-local time offset when
+ * creating an Ecmascript time value from local parts.
+ */
+#define DUK__LOCAL_TZOFFSET_MAXITER   4
+
+/* Because 'day since epoch' can be negative and is used to compute weekday
+ * using a modulo operation, add this multiple of 7 to avoid negative values
+ * when year is below 1970 epoch.  Ecmascript time values are restricted to
+ * +/- 100 million days from epoch, so this adder fits nicely into 32 bits.
+ * Round to a multiple of 7 (= floor(100000000 / 7) * 7) and add margin.
+ */
+#define DUK__WEEKDAY_MOD_ADDER  (20000000 * 7)  /* 0x08583b00 */
+
+DUK_INTERNAL duk_bool_t duk_bi_date_is_leap_year(duk_int_t year) {
 	if ((year % 4) != 0) {
 		return 0;
 	}
@@ -16447,12 +28105,24 @@ static duk_bool_t duk__is_leap_year(duk_int_t year) {
 	return 1;
 }
 
-static duk_double_t duk__timeclip(duk_double_t x) {
+DUK_INTERNAL duk_bool_t duk_bi_date_timeval_in_valid_range(duk_double_t x) {
+	return (x >= -DUK_DATE_MSEC_100M_DAYS && x <= DUK_DATE_MSEC_100M_DAYS);
+}
+
+DUK_INTERNAL duk_bool_t duk_bi_date_timeval_in_leeway_range(duk_double_t x) {
+	return (x >= -DUK_DATE_MSEC_100M_DAYS_LEEWAY && x <= DUK_DATE_MSEC_100M_DAYS_LEEWAY);
+}
+
+DUK_INTERNAL duk_bool_t duk_bi_date_year_in_valid_range(duk_double_t x) {
+	return (x >= DUK_DATE_MIN_ECMA_YEAR && x <= DUK_DATE_MAX_ECMA_YEAR);
+}
+
+DUK_LOCAL duk_double_t duk__timeclip(duk_double_t x) {
 	if (!DUK_ISFINITE(x)) {
 		return DUK_DOUBLE_NAN;
 	}
 
-	if (x > 8.64e15 || x < -8.64e15) {
+	if (!duk_bi_date_timeval_in_valid_range(x)) {
 		return DUK_DOUBLE_NAN;
 	}
 
@@ -16463,7 +28133,7 @@ static duk_double_t duk__timeclip(duk_double_t x) {
 }
 
 /* Integer division which floors also negative values correctly. */
-static duk_int_t duk__div_floor(duk_int_t a, duk_int_t b) {
+DUK_LOCAL duk_int_t duk__div_floor(duk_int_t a, duk_int_t b) {
 	DUK_ASSERT(b > 0);
 	if (a >= 0) {
 		return a / b;
@@ -16477,7 +28147,7 @@ static duk_int_t duk__div_floor(duk_int_t a, duk_int_t b) {
 }
 
 /* Compute day number of the first day of a given year. */
-static duk_int_t duk__day_from_year(duk_int_t year) {
+DUK_LOCAL duk_int_t duk__day_from_year(duk_int_t year) {
 	/* Note: in integer arithmetic, (x / 4) is same as floor(x / 4) for non-negative
 	 * values, but is incorrect for negative ones.
 	 */
@@ -16488,7 +28158,7 @@ static duk_int_t duk__day_from_year(duk_int_t year) {
 }
 
 /* Given a day number, determine year and day-within-year. */
-static duk_int_t duk__year_from_day(duk_int_t day, duk_small_int_t *out_day_within_year) {
+DUK_LOCAL duk_int_t duk__year_from_day(duk_int_t day, duk_small_int_t *out_day_within_year) {
 	duk_int_t year;
 	duk_int_t diff_days;
 
@@ -16506,12 +28176,12 @@ static duk_int_t duk__year_from_day(duk_int_t day, duk_small_int_t *out_day_with
 		diff_days = duk__day_from_year(year) - day;
 		DUK_DDD(DUK_DDDPRINT("year=%ld day=%ld, diff_days=%ld", (long) year, (long) day, (long) diff_days));
 		if (diff_days <= 0) {
-			DUK_ASSERT(-diff_days <= 366);  /* fits into duk_small_int_t */
+			DUK_ASSERT(-diff_days < 366);  /* fits into duk_small_int_t */
 			*out_day_within_year = -diff_days;
 			DUK_DDD(DUK_DDDPRINT("--> year=%ld, day-within-year=%ld",
 			                     (long) year, (long) *out_day_within_year));
 			DUK_ASSERT(*out_day_within_year >= 0);
-			DUK_ASSERT(*out_day_within_year <= (duk__is_leap_year(year) ? 366 : 365));
+			DUK_ASSERT(*out_day_within_year < (duk_bi_date_is_leap_year(year) ? 366 : 365));
 			return year;
 		}
 
@@ -16525,7 +28195,7 @@ static duk_int_t duk__year_from_day(duk_int_t day, duk_small_int_t *out_day_with
 /* Given a (year, month, day-within-month) triple, compute day number.
  * The input triple is un-normalized and may contain non-finite values.
  */
-static duk_double_t duk__make_day(duk_double_t year, duk_double_t month, duk_double_t day) {
+DUK_LOCAL duk_double_t duk__make_day(duk_double_t year, duk_double_t month, duk_double_t day) {
 	duk_int_t day_num;
 	duk_bool_t is_leap;
 	duk_small_int_t i, n;
@@ -16540,7 +28210,7 @@ static duk_double_t duk__make_day(duk_double_t year, duk_double_t month, duk_dou
 	if (!DUK_ISFINITE(year) || !DUK_ISFINITE(month)) {
 		return DUK_DOUBLE_NAN;
 	}
-	
+
 	year += DUK_FLOOR(month / 12.0);
 
 	month = DUK_FMOD(month, 12.0);
@@ -16558,10 +28228,18 @@ static duk_double_t duk__make_day(duk_double_t year, duk_double_t month, duk_dou
 	 *
 	 * Without an explicit infinity / NaN check in the beginning,
 	 * day_num would be a bogus integer here.
+	 *
+	 * It's possible for 'year' to be out of integer range here.
+	 * If so, we need to return NaN without integer overflow.
+	 * This fixes test-bug-setyear-overflow.js.
 	 */
 
+	if (!duk_bi_date_year_in_valid_range(year)) {
+		DUK_DD(DUK_DDPRINT("year not in ecmascript valid range, avoid integer overflow: %lf", (double) year));
+		return DUK_DOUBLE_NAN;
+	}
 	day_num = duk__day_from_year((duk_int_t) year);
-	is_leap = duk__is_leap_year((duk_int_t) year);
+	is_leap = duk_bi_date_is_leap_year((duk_int_t) year);
 
 	n = (duk_small_int_t) month;
 	for (i = 0; i < n; i++) {
@@ -16579,55 +28257,80 @@ static duk_double_t duk__make_day(duk_double_t year, duk_double_t month, duk_dou
  * one, i.e. finite, no fractions.  Possible local time adjustment has already
  * been applied when reading the time value.
  */
-static void duk__timeval_to_parts(duk_double_t d, duk_int_t *parts, duk_double_t *dparts, duk_small_uint_t flags) {
+DUK_INTERNAL void duk_bi_date_timeval_to_parts(duk_double_t d, duk_int_t *parts, duk_double_t *dparts, duk_small_uint_t flags) {
 	duk_double_t d1, d2;
 	duk_int_t t1, t2;
+	duk_int_t day_since_epoch;
 	duk_int_t year;  /* does not fit into 16 bits */
+	duk_small_int_t day_in_year;
 	duk_small_int_t month;
 	duk_small_int_t day;
 	duk_small_int_t dim;
+	duk_int_t jan1_since_epoch;
+	duk_small_int_t jan1_weekday;
+	duk_int_t equiv_year;
 	duk_small_uint_t i;
 	duk_bool_t is_leap;
+	duk_small_int_t arridx;
 
 	DUK_ASSERT(DUK_ISFINITE(d));    /* caller checks */
 	DUK_ASSERT(DUK_FLOOR(d) == d);  /* no fractions in internal time */
 
+	/* The timevalue must be in valid Ecmascript range, but since a local
+	 * time offset can be applied, we need to allow a +/- 24h leeway to
+	 * the value.  In other words, although the UTC time is within the
+	 * Ecmascript range, the local part values can be just outside of it.
+	 */
+	DUK_UNREF(duk_bi_date_timeval_in_leeway_range);
+	DUK_ASSERT(duk_bi_date_timeval_in_leeway_range(d));
+
 	/* these computations are guaranteed to be exact for the valid
 	 * E5 time value range, assuming milliseconds without fractions.
 	 */
-	d1 = (duk_double_t) DUK_FMOD(d, (double) DUK__MS_DAY);
+	d1 = (duk_double_t) DUK_FMOD(d, (double) DUK_DATE_MSEC_DAY);
 	if (d1 < 0.0) {
 		/* deal with negative values */
-		d1 += (duk_double_t) DUK__MS_DAY;
+		d1 += (duk_double_t) DUK_DATE_MSEC_DAY;
 	}
-	d2 = DUK_FLOOR(d / (duk_double_t) DUK__MS_DAY);
-	DUK_ASSERT(d2 * ((duk_double_t) DUK__MS_DAY) + d1 == d);
-
+	d2 = DUK_FLOOR((double) (d / (duk_double_t) DUK_DATE_MSEC_DAY));
+	DUK_ASSERT(d2 * ((duk_double_t) DUK_DATE_MSEC_DAY) + d1 == d);
 	/* now expected to fit into a 32-bit integer */
 	t1 = (duk_int_t) d1;
 	t2 = (duk_int_t) d2;
+	day_since_epoch = t2;
 	DUK_ASSERT((duk_double_t) t1 == d1);
 	DUK_ASSERT((duk_double_t) t2 == d2);
 
-	/* t1 = milliseconds within day, t2 = day number */
+	/* t1 = milliseconds within day (fits 32 bit)
+	 * t2 = day number from epoch (fits 32 bit, may be negative)
+	 */
+
+	parts[DUK_DATE_IDX_MILLISECOND] = t1 % 1000; t1 /= 1000;
+	parts[DUK_DATE_IDX_SECOND] = t1 % 60; t1 /= 60;
+	parts[DUK_DATE_IDX_MINUTE] = t1 % 60; t1 /= 60;
+	parts[DUK_DATE_IDX_HOUR] = t1;
+	DUK_ASSERT(parts[DUK_DATE_IDX_MILLISECOND] >= 0 && parts[DUK_DATE_IDX_MILLISECOND] <= 999);
+	DUK_ASSERT(parts[DUK_DATE_IDX_SECOND] >= 0 && parts[DUK_DATE_IDX_SECOND] <= 59);
+	DUK_ASSERT(parts[DUK_DATE_IDX_MINUTE] >= 0 && parts[DUK_DATE_IDX_MINUTE] <= 59);
+	DUK_ASSERT(parts[DUK_DATE_IDX_HOUR] >= 0 && parts[DUK_DATE_IDX_HOUR] <= 23);
 
-	parts[DUK__IDX_MILLISECOND] = t1 % 1000; t1 /= 1000;
-	parts[DUK__IDX_SECOND] = t1 % 60; t1 /= 60;
-	parts[DUK__IDX_MINUTE] = t1 % 60; t1 /= 60;
-	parts[DUK__IDX_HOUR] = t1;
-	DUK_ASSERT(parts[DUK__IDX_MILLISECOND] >= 0 && parts[DUK__IDX_MILLISECOND] <= 999);
-	DUK_ASSERT(parts[DUK__IDX_SECOND] >= 0 && parts[DUK__IDX_SECOND] <= 59);
-	DUK_ASSERT(parts[DUK__IDX_MINUTE] >= 0 && parts[DUK__IDX_MINUTE] <= 59);
-	DUK_ASSERT(parts[DUK__IDX_HOUR] >= 0 && parts[DUK__IDX_HOUR] <= 23);
+	DUK_DDD(DUK_DDDPRINT("d=%lf, d1=%lf, d2=%lf, t1=%ld, t2=%ld, parts: hour=%ld min=%ld sec=%ld msec=%ld",
+	                     (double) d, (double) d1, (double) d2, (long) t1, (long) t2,
+	                     (long) parts[DUK_DATE_IDX_HOUR],
+	                     (long) parts[DUK_DATE_IDX_MINUTE],
+	                     (long) parts[DUK_DATE_IDX_SECOND],
+	                     (long) parts[DUK_DATE_IDX_MILLISECOND]));
 
-	parts[DUK__IDX_WEEKDAY] = (t2 + 4) % 7;  /* E5.1 Section 15.9.1.6 */
-	if (parts[DUK__IDX_WEEKDAY] < 0) {
-		/* deal with negative values */
-		parts[DUK__IDX_WEEKDAY] += 7;
-	}
+	/* This assert depends on the input parts representing time inside
+	 * the Ecmascript range.
+	 */
+	DUK_ASSERT(t2 + DUK__WEEKDAY_MOD_ADDER >= 0);
+	parts[DUK_DATE_IDX_WEEKDAY] = (t2 + 4 + DUK__WEEKDAY_MOD_ADDER) % 7;  /* E5.1 Section 15.9.1.6 */
+	DUK_ASSERT(parts[DUK_DATE_IDX_WEEKDAY] >= 0 && parts[DUK_DATE_IDX_WEEKDAY] <= 6);
 
-	year = duk__year_from_day(t2, &day);
-	is_leap = duk__is_leap_year(year);
+	year = duk__year_from_day(t2, &day_in_year);
+	day = day_in_year;
+	is_leap = duk_bi_date_is_leap_year(year);
 	for (month = 0; month < 12; month++) {
 		dim = duk__days_in_month[month];
 		if (month == 1 && is_leap) {
@@ -16644,24 +28347,62 @@ static void duk__timeval_to_parts(duk_double_t d, duk_int_t *parts, duk_double_t
 	DUK_ASSERT(month >= 0 && month <= 11);
 	DUK_ASSERT(day >= 0 && day <= 31);
 
-	parts[DUK__IDX_YEAR] = year;
-	parts[DUK__IDX_MONTH] = month;
-	parts[DUK__IDX_DAY] = day;
+	/* Equivalent year mapping, used to avoid DST trouble when platform
+	 * may fail to provide reasonable DST answers for dates outside the
+	 * ordinary range (e.g. 1970-2038).  An equivalent year has the same
+	 * leap-year-ness as the original year and begins on the same weekday
+	 * (Jan 1).
+	 *
+	 * The year 2038 is avoided because there seem to be problems with it
+	 * on some platforms.  The year 1970 is also avoided as there were
+	 * practical problems with it; an equivalent year is used for it too,
+	 * which breaks some DST computations for 1970 right now, see e.g.
+	 * test-bi-date-tzoffset-brute-fi.js.
+	 */
+	if ((flags & DUK_DATE_FLAG_EQUIVYEAR) && (year < 1971 || year > 2037)) {
+		DUK_ASSERT(is_leap == 0 || is_leap == 1);
+
+		jan1_since_epoch = day_since_epoch - day_in_year;  /* day number for Jan 1 since epoch */
+		DUK_ASSERT(jan1_since_epoch + DUK__WEEKDAY_MOD_ADDER >= 0);
+		jan1_weekday = (jan1_since_epoch + 4 + DUK__WEEKDAY_MOD_ADDER) % 7;  /* E5.1 Section 15.9.1.6 */
+		DUK_ASSERT(jan1_weekday >= 0 && jan1_weekday <= 6);
+		arridx = jan1_weekday;
+		if (is_leap) {
+			arridx += 7;
+		}
+		DUK_ASSERT(arridx >= 0 && arridx < (duk_small_int_t) (sizeof(duk__date_equivyear) / sizeof(duk_uint8_t)));
+
+		equiv_year = (duk_int_t) duk__date_equivyear[arridx] + 1970;
+		year = equiv_year;
+		DUK_DDD(DUK_DDDPRINT("equiv year mapping, year=%ld, day_in_year=%ld, day_since_epoch=%ld, "
+		                     "jan1_since_epoch=%ld, jan1_weekday=%ld -> equiv year %ld",
+		                     (long) year, (long) day_in_year, (long) day_since_epoch,
+		                     (long) jan1_since_epoch, (long) jan1_weekday, (long) equiv_year));
+	}
+
+	parts[DUK_DATE_IDX_YEAR] = year;
+	parts[DUK_DATE_IDX_MONTH] = month;
+	parts[DUK_DATE_IDX_DAY] = day;
 
-	if (flags & DUK__FLAG_ONEBASED) {
-		parts[DUK__IDX_MONTH]++;  /* zero-based -> one-based */
-		parts[DUK__IDX_DAY]++;    /* -""- */
+	if (flags & DUK_DATE_FLAG_ONEBASED) {
+		parts[DUK_DATE_IDX_MONTH]++;  /* zero-based -> one-based */
+		parts[DUK_DATE_IDX_DAY]++;    /* -""- */
 	}
 
 	if (dparts != NULL) {
-		for (i = 0; i < DUK__NUM_PARTS; i++) {
+		for (i = 0; i < DUK_DATE_IDX_NUM_PARTS; i++) {
 			dparts[i] = (duk_double_t) parts[i];
 		}
 	}
 }
 
-/* Compute time value from (double) parts. */
-static duk_double_t duk__get_timeval_from_dparts(duk_double_t *dparts, duk_small_uint_t flags) {
+/* Compute time value from (double) parts.  The parts can be either UTC
+ * or local time; if local, they need to be (conceptually) converted into
+ * UTC time.  The parts may represent valid or invalid time, and may be
+ * wildly out of range (but may cancel each other and still come out in
+ * the valid Date range).
+ */
+DUK_INTERNAL duk_double_t duk_bi_date_get_timeval_from_dparts(duk_double_t *dparts, duk_small_uint_t flags) {
 #if defined(DUK_USE_PARANOID_DATE_COMPUTATION)
 	/* See comments below on MakeTime why these are volatile. */
 	volatile duk_double_t tmp_time;
@@ -16673,6 +28414,7 @@ static duk_double_t duk__get_timeval_from_dparts(duk_double_t *dparts, duk_small
 	duk_double_t d;
 #endif
 	duk_small_uint_t i;
+	duk_int_t tzoff, tzoffprev1, tzoffprev2;
 
 	/* Expects 'this' at top of stack on entry. */
 
@@ -16681,10 +28423,10 @@ static duk_double_t duk__get_timeval_from_dparts(duk_double_t *dparts, duk_small
 	 * zero.  If ToInteger() has already been called, this has no side
 	 * effects and is idempotent.
 	 *
-	 * Don't read dparts[DUK__IDX_WEEKDAY]; it will cause Valgrind issues
-	 * if the value is uninitialized.
+	 * Don't read dparts[DUK_DATE_IDX_WEEKDAY]; it will cause Valgrind
+	 * issues if the value is uninitialized.
 	 */
-	for (i = 0; i <= DUK__IDX_MILLISECOND; i++) {
+	for (i = 0; i <= DUK_DATE_IDX_MILLISECOND; i++) {
 		/* SCANBUILD: scan-build complains here about assigned value
 		 * being garbage or undefined.  This is correct but operating
 		 * on undefined values has no ill effect and is ignored by the
@@ -16710,40 +28452,81 @@ static duk_double_t duk__get_timeval_from_dparts(duk_double_t *dparts, duk_small
 	 * particular problem (annoyingly, also adding debug prints or
 	 * running the executable under valgrind hides it).
 	 */
-	
+
 	/* MakeTime */
 	tmp_time = 0.0;
-	tmp_time += dparts[DUK__IDX_HOUR] * ((duk_double_t) DUK__MS_HOUR);
-	tmp_time += dparts[DUK__IDX_MINUTE] * ((duk_double_t) DUK__MS_MINUTE);
-	tmp_time += dparts[DUK__IDX_SECOND] * ((duk_double_t) DUK__MS_SECOND);
-	tmp_time += dparts[DUK__IDX_MILLISECOND];
+	tmp_time += dparts[DUK_DATE_IDX_HOUR] * ((duk_double_t) DUK_DATE_MSEC_HOUR);
+	tmp_time += dparts[DUK_DATE_IDX_MINUTE] * ((duk_double_t) DUK_DATE_MSEC_MINUTE);
+	tmp_time += dparts[DUK_DATE_IDX_SECOND] * ((duk_double_t) DUK_DATE_MSEC_SECOND);
+	tmp_time += dparts[DUK_DATE_IDX_MILLISECOND];
 
 	/* MakeDay */
-	tmp_day = duk__make_day(dparts[DUK__IDX_YEAR], dparts[DUK__IDX_MONTH], dparts[DUK__IDX_DAY]);
+	tmp_day = duk__make_day(dparts[DUK_DATE_IDX_YEAR], dparts[DUK_DATE_IDX_MONTH], dparts[DUK_DATE_IDX_DAY]);
 
 	/* MakeDate */
-	d = tmp_day * ((duk_double_t) DUK__MS_DAY) + tmp_time;
+	d = tmp_day * ((duk_double_t) DUK_DATE_MSEC_DAY) + tmp_time;
 
 	DUK_DDD(DUK_DDDPRINT("time=%lf day=%lf --> timeval=%lf",
 	                     (double) tmp_time, (double) tmp_day, (double) d));
 
-	/* Optional UTC conversion followed by TimeClip().
-	 * Note that this also handles Infinity -> NaN conversion.
-	 */
-	if (flags & DUK__FLAG_LOCALTIME) {
-		/* FIXME: this is now incorrect.  'd' is local time here (as
-		 * we're converting to UTC), but DUK__GET_LOCAL_TZOFFSET() should
-		 * be called with UTC time.  This needs to be reworked to avoid
-		 * the chicken-and-egg problem.
+	/* Optional UTC conversion. */
+	if (flags & DUK_DATE_FLAG_LOCALTIME) {
+		/* DUK_USE_DATE_GET_LOCAL_TZOFFSET() needs to be called with a
+		 * time value computed from UTC parts.  At this point we only
+		 * have 'd' which is a time value computed from local parts, so
+		 * it is off by the UTC-to-local time offset which we don't know
+		 * yet.  The current solution for computing the UTC-to-local
+		 * time offset is to iterate a few times and detect a fixed
+		 * point or a two-cycle loop (or a sanity iteration limit),
+		 * see test-bi-date-local-parts.js and test-bi-date-tzoffset-basic-fi.js.
 		 *
-		 * See E5.1 Section 15.9.1.9:
+		 * E5.1 Section 15.9.1.9:
 		 * UTC(t) = t - LocalTZA - DaylightSavingTA(t - LocalTZA)
 		 *
-		 * For NaN/inf, DUK__GET_LOCAL_TZOFFSET() returns 0.
+		 * For NaN/inf, DUK_USE_DATE_GET_LOCAL_TZOFFSET() returns 0.
 		 */
 
-		d -= DUK__GET_LOCAL_TZOFFSET(d) * 1000L;
+#if 0
+		/* Old solution: don't iterate, incorrect */
+		tzoff = DUK_USE_DATE_GET_LOCAL_TZOFFSET(d);
+		DUK_DDD(DUK_DDDPRINT("tzoffset w/o iteration, tzoff=%ld", (long) tzoff));
+		d -= tzoff * 1000L;
+		DUK_UNREF(tzoffprev1);
+		DUK_UNREF(tzoffprev2);
+#endif
+
+		/* Iteration solution */
+		tzoff = 0;
+		tzoffprev1 = 999999999L;  /* invalid value which never matches */
+		for (i = 0; i < DUK__LOCAL_TZOFFSET_MAXITER; i++) {
+			tzoffprev2 = tzoffprev1;
+			tzoffprev1 = tzoff;
+			tzoff = DUK_USE_DATE_GET_LOCAL_TZOFFSET(d - tzoff * 1000L);
+			DUK_DDD(DUK_DDDPRINT("tzoffset iteration, i=%d, tzoff=%ld, tzoffprev1=%ld tzoffprev2=%ld",
+			                     (int) i, (long) tzoff, (long) tzoffprev1, (long) tzoffprev2));
+			if (tzoff == tzoffprev1) {
+				DUK_DDD(DUK_DDDPRINT("tzoffset iteration finished, i=%d, tzoff=%ld, tzoffprev1=%ld, tzoffprev2=%ld",
+				                     (int) i, (long) tzoff, (long) tzoffprev1, (long) tzoffprev2));
+				break;
+			} else if (tzoff == tzoffprev2) {
+				/* Two value cycle, see e.g. test-bi-date-tzoffset-basic-fi.js.
+				 * In these cases, favor a higher tzoffset to get a consistent
+				 * result which is independent of iteration count.  Not sure if
+				 * this is a generically correct solution.
+				 */
+				DUK_DDD(DUK_DDDPRINT("tzoffset iteration two-value cycle, i=%d, tzoff=%ld, tzoffprev1=%ld, tzoffprev2=%ld",
+				                     (int) i, (long) tzoff, (long) tzoffprev1, (long) tzoffprev2));
+				if (tzoffprev1 > tzoff) {
+					tzoff = tzoffprev1;
+				}
+				break;
+			}
+		}
+		DUK_DDD(DUK_DDDPRINT("tzoffset iteration, tzoff=%ld", (long) tzoff));
+		d -= tzoff * 1000L;
 	}
+
+	/* TimeClip(), which also handles Infinity -> NaN conversion */
 	d = duk__timeclip(d);
 
 	return d;
@@ -16757,14 +28540,14 @@ static duk_double_t duk__get_timeval_from_dparts(duk_double_t *dparts, duk_small
  * internal time value.  At the end, stack is: [ ... this timeval ].
  * Returns the time value.  Local time adjustment is done if requested.
  */
-static duk_double_t duk__push_this_get_timeval_tzoffset(duk_context *ctx, duk_small_uint_t flags, duk_int_t *out_tzoffset) {
+DUK_LOCAL duk_double_t duk__push_this_get_timeval_tzoffset(duk_context *ctx, duk_small_uint_t flags, duk_int_t *out_tzoffset) {
 	duk_hthread *thr = (duk_hthread *) ctx;
 	duk_hobject *h;
 	duk_double_t d;
 	duk_int_t tzoffset = 0;
 
 	duk_push_this(ctx);
-	h = duk_get_hobject(ctx, -1);  /* FIXME: getter with class check, useful in built-ins */
+	h = duk_get_hobject(ctx, -1);  /* XXX: getter with class check, useful in built-ins */
 	if (h == NULL || DUK_HOBJECT_GET_CLASS_NUMBER(h) != DUK_HOBJECT_CLASS_DATE) {
 		DUK_ERROR(thr, DUK_ERR_TYPE_ERROR, "expected Date");
 	}
@@ -16774,21 +28557,21 @@ static duk_double_t duk__push_this_get_timeval_tzoffset(duk_context *ctx, duk_sm
 	duk_pop(ctx);
 
 	if (DUK_ISNAN(d)) {
-		if (flags & DUK__FLAG_NAN_TO_ZERO) {
+		if (flags & DUK_DATE_FLAG_NAN_TO_ZERO) {
 			d = 0.0;
 		}
-		if (flags & DUK__FLAG_NAN_TO_RANGE_ERROR) {
+		if (flags & DUK_DATE_FLAG_NAN_TO_RANGE_ERROR) {
 			DUK_ERROR(thr, DUK_ERR_RANGE_ERROR, "Invalid Date");
 		}
 	}
 	/* if no NaN handling flag, may still be NaN here, but not Inf */
 	DUK_ASSERT(!DUK_ISINF(d));
 
-	if (flags & DUK__FLAG_LOCALTIME) {
+	if (flags & DUK_DATE_FLAG_LOCALTIME) {
 		/* Note: DST adjustment is determined using UTC time.
 		 * If 'd' is NaN, tzoffset will be 0.
 		 */
-		tzoffset = DUK__GET_LOCAL_TZOFFSET(d);  /* seconds */
+		tzoffset = DUK_USE_DATE_GET_LOCAL_TZOFFSET(d);  /* seconds */
 		d += tzoffset * 1000L;
 	}
 	if (out_tzoffset) {
@@ -16799,49 +28582,49 @@ static duk_double_t duk__push_this_get_timeval_tzoffset(duk_context *ctx, duk_sm
 	return d;
 }
 
-static duk_double_t duk__push_this_get_timeval(duk_context *ctx, duk_small_uint_t flags) {
+DUK_LOCAL duk_double_t duk__push_this_get_timeval(duk_context *ctx, duk_small_uint_t flags) {
 	return duk__push_this_get_timeval_tzoffset(ctx, flags, NULL);
 }
 
 /* Set timeval to 'this' from dparts, push the new time value onto the
- * value stack and return 1 (caller can then tailcall us).  Expects
+ * value stack and return 1 (caller can then tail call us).  Expects
  * the value stack to contain 'this' on the stack top.
  */
-static duk_ret_t duk__set_this_timeval_from_dparts(duk_context *ctx, duk_double_t *dparts, duk_small_uint_t flags) {
+DUK_LOCAL duk_ret_t duk__set_this_timeval_from_dparts(duk_context *ctx, duk_double_t *dparts, duk_small_uint_t flags) {
 	duk_double_t d;
 
 	/* [ ... this ] */
 
-	d = duk__get_timeval_from_dparts(dparts, flags);
+	d = duk_bi_date_get_timeval_from_dparts(dparts, flags);
 	duk_push_number(ctx, d);  /* -> [ ... this timeval_new ] */
 	duk_dup_top(ctx);         /* -> [ ... this timeval_new timeval_new ] */
 	duk_put_prop_stridx(ctx, -3, DUK_STRIDX_INT_VALUE);
 
-	/* stack top: new time value, return 1 to allow tailcalls */
+	/* stack top: new time value, return 1 to allow tail calls */
 	return 1;
 }
 
 /* 'out_buf' must be at least DUK_BI_DATE_ISO8601_BUFSIZE long. */
-static void duk__format_parts_iso8601(duk_int_t *parts, duk_int_t tzoffset, duk_small_uint_t flags, duk_uint8_t *out_buf) {
+DUK_LOCAL void duk__format_parts_iso8601(duk_int_t *parts, duk_int_t tzoffset, duk_small_uint_t flags, duk_uint8_t *out_buf) {
 	char yearstr[8];   /* "-123456\0" */
 	char tzstr[8];     /* "+11:22\0" */
-	char sep = (flags & DUK__FLAG_SEP_T) ? DUK_ASC_UC_T : DUK_ASC_SPACE;
+	char sep = (flags & DUK_DATE_FLAG_SEP_T) ? DUK_ASC_UC_T : DUK_ASC_SPACE;
 
-	DUK_ASSERT(parts[DUK__IDX_MONTH] >= 1 && parts[DUK__IDX_MONTH] <= 12);
-	DUK_ASSERT(parts[DUK__IDX_DAY] >= 1 && parts[DUK__IDX_DAY] <= 31);
-	DUK_ASSERT(parts[DUK__IDX_YEAR] >= -999999 && parts[DUK__IDX_YEAR] <= 999999);
+	DUK_ASSERT(parts[DUK_DATE_IDX_MONTH] >= 1 && parts[DUK_DATE_IDX_MONTH] <= 12);
+	DUK_ASSERT(parts[DUK_DATE_IDX_DAY] >= 1 && parts[DUK_DATE_IDX_DAY] <= 31);
+	DUK_ASSERT(parts[DUK_DATE_IDX_YEAR] >= -999999 && parts[DUK_DATE_IDX_YEAR] <= 999999);
 
 	/* Note: %06d for positive value, %07d for negative value to include
 	 * sign and 6 digits.
 	 */
 	DUK_SNPRINTF(yearstr,
 	             sizeof(yearstr),
-	             (parts[DUK__IDX_YEAR] >= 0 && parts[DUK__IDX_YEAR] <= 9999) ? "%04ld" :
-	                    ((parts[DUK__IDX_YEAR] >= 0) ? "+%06ld" : "%07ld"),
-	             (long) parts[DUK__IDX_YEAR]);
+	             (parts[DUK_DATE_IDX_YEAR] >= 0 && parts[DUK_DATE_IDX_YEAR] <= 9999) ? "%04ld" :
+	                    ((parts[DUK_DATE_IDX_YEAR] >= 0) ? "+%06ld" : "%07ld"),
+	             (long) parts[DUK_DATE_IDX_YEAR]);
 	yearstr[sizeof(yearstr) - 1] = (char) 0;
 
-	if (flags & DUK__FLAG_LOCALTIME) {
+	if (flags & DUK_DATE_FLAG_LOCALTIME) {
 		/* tzoffset seconds are dropped; 16 bits suffice for
 		 * time offset in minutes
 		 */
@@ -16861,19 +28644,19 @@ static void duk__format_parts_iso8601(duk_int_t *parts, duk_int_t tzoffset, duk_
 	/* Unlike year, the other parts fit into 16 bits so %d format
 	 * is portable.
 	 */
-	if ((flags & DUK__FLAG_TOSTRING_DATE) && (flags & DUK__FLAG_TOSTRING_TIME)) {
+	if ((flags & DUK_DATE_FLAG_TOSTRING_DATE) && (flags & DUK_DATE_FLAG_TOSTRING_TIME)) {
 		DUK_SPRINTF((char *) out_buf, "%s-%02d-%02d%c%02d:%02d:%02d.%03d%s",
-		            (const char *) yearstr, (int) parts[DUK__IDX_MONTH], (int) parts[DUK__IDX_DAY], (int) sep,
-		            (int) parts[DUK__IDX_HOUR], (int) parts[DUK__IDX_MINUTE],
-		            (int) parts[DUK__IDX_SECOND], (int) parts[DUK__IDX_MILLISECOND], (const char *) tzstr);
-	} else if (flags & DUK__FLAG_TOSTRING_DATE) {
+		            (const char *) yearstr, (int) parts[DUK_DATE_IDX_MONTH], (int) parts[DUK_DATE_IDX_DAY], (int) sep,
+		            (int) parts[DUK_DATE_IDX_HOUR], (int) parts[DUK_DATE_IDX_MINUTE],
+		            (int) parts[DUK_DATE_IDX_SECOND], (int) parts[DUK_DATE_IDX_MILLISECOND], (const char *) tzstr);
+	} else if (flags & DUK_DATE_FLAG_TOSTRING_DATE) {
 		DUK_SPRINTF((char *) out_buf, "%s-%02d-%02d",
-		            (const char *) yearstr, (int) parts[DUK__IDX_MONTH], (int) parts[DUK__IDX_DAY]);
+		            (const char *) yearstr, (int) parts[DUK_DATE_IDX_MONTH], (int) parts[DUK_DATE_IDX_DAY]);
 	} else {
-		DUK_ASSERT(flags & DUK__FLAG_TOSTRING_TIME);
+		DUK_ASSERT(flags & DUK_DATE_FLAG_TOSTRING_TIME);
 		DUK_SPRINTF((char *) out_buf, "%02d:%02d:%02d.%03d%s",
-		            (int) parts[DUK__IDX_HOUR], (int) parts[DUK__IDX_MINUTE],
-		            (int) parts[DUK__IDX_SECOND], (int) parts[DUK__IDX_MILLISECOND],
+		            (int) parts[DUK_DATE_IDX_HOUR], (int) parts[DUK_DATE_IDX_MINUTE],
+		            (int) parts[DUK_DATE_IDX_SECOND], (int) parts[DUK_DATE_IDX_MILLISECOND],
 		            (const char *) tzstr);
 	}
 }
@@ -16882,9 +28665,9 @@ static void duk__format_parts_iso8601(duk_int_t *parts, duk_int_t tzoffset, duk_
  * internal time value, and format date and/or time in a few formats.
  * Return value allows tail calls.
  */
-static duk_ret_t duk__to_string_helper(duk_context *ctx, duk_small_uint_t flags) {
+DUK_LOCAL duk_ret_t duk__to_string_helper(duk_context *ctx, duk_small_uint_t flags) {
 	duk_double_t d;
-	duk_int_t parts[DUK__NUM_PARTS];
+	duk_int_t parts[DUK_DATE_IDX_NUM_PARTS];
 	duk_int_t tzoffset;  /* seconds, doesn't fit into 16 bits */
 	duk_bool_t rc;
 	duk_uint8_t buf[DUK_BI_DATE_ISO8601_BUFSIZE];
@@ -16899,17 +28682,22 @@ static duk_ret_t duk__to_string_helper(duk_context *ctx, duk_small_uint_t flags)
 	DUK_ASSERT(DUK_ISFINITE(d));
 
 	/* formatters always get one-based month/day-of-month */
-	duk__timeval_to_parts(d, parts, NULL, DUK__FLAG_ONEBASED);
-	DUK_ASSERT(parts[DUK__IDX_MONTH] >= 1 && parts[DUK__IDX_MONTH] <= 12);
-	DUK_ASSERT(parts[DUK__IDX_DAY] >= 1 && parts[DUK__IDX_DAY] <= 31);
+	duk_bi_date_timeval_to_parts(d, parts, NULL, DUK_DATE_FLAG_ONEBASED);
+	DUK_ASSERT(parts[DUK_DATE_IDX_MONTH] >= 1 && parts[DUK_DATE_IDX_MONTH] <= 12);
+	DUK_ASSERT(parts[DUK_DATE_IDX_DAY] >= 1 && parts[DUK_DATE_IDX_DAY] <= 31);
 
-	if (flags & DUK__FLAG_TOSTRING_LOCALE) {
+	if (flags & DUK_DATE_FLAG_TOSTRING_LOCALE) {
 		/* try locale specific formatter; if it refuses to format the
 		 * string, fall back to an ISO 8601 formatted value in local
 		 * time.
 		 */
-#ifdef DUK_USE_DATE_FMT_STRFTIME
-		rc = duk__format_parts_strftime(ctx, parts, tzoffset, flags);
+#if defined(DUK_USE_DATE_FORMAT_STRING)
+		/* Contract, either:
+		 * - Push string to value stack and return 1
+		 * - Don't push anything and return 0
+		 */
+
+		rc = DUK_USE_DATE_FORMAT_STRING(ctx, parts, tzoffset, flags);
 		if (rc != 0) {
 			return 1;
 		}
@@ -16931,15 +28719,15 @@ static duk_ret_t duk__to_string_helper(duk_context *ctx, duk_small_uint_t flags)
 /* Helper for component getter calls: check 'this' binding, get the
  * internal time value, split it into parts (either as UTC time or
  * local time), push a specified component as a return value to the
- * value stack and return 1 (caller can then tailcall us).
+ * value stack and return 1 (caller can then tail call us).
  */
-static duk_ret_t duk__get_part_helper(duk_context *ctx, duk_small_uint_t flags_and_idx) {
+DUK_LOCAL duk_ret_t duk__get_part_helper(duk_context *ctx, duk_small_uint_t flags_and_idx) {
 	duk_double_t d;
-	duk_int_t parts[DUK__NUM_PARTS];
-	duk_small_uint_t idx_part = (duk_small_uint_t) (flags_and_idx >> 12);  /* unpack args */
+	duk_int_t parts[DUK_DATE_IDX_NUM_PARTS];
+	duk_small_uint_t idx_part = (duk_small_uint_t) (flags_and_idx >> DUK_DATE_FLAG_VALUE_SHIFT);  /* unpack args */
 
 	DUK_ASSERT_DISABLE(idx_part >= 0);  /* unsigned */
-	DUK_ASSERT(idx_part < DUK__NUM_PARTS);
+	DUK_ASSERT(idx_part < DUK_DATE_IDX_NUM_PARTS);
 
 	d = duk__push_this_get_timeval(ctx, flags_and_idx);
 	if (DUK_ISNAN(d)) {
@@ -16948,13 +28736,13 @@ static duk_ret_t duk__get_part_helper(duk_context *ctx, duk_small_uint_t flags_a
 	}
 	DUK_ASSERT(DUK_ISFINITE(d));
 
-	duk__timeval_to_parts(d, parts, NULL, flags_and_idx);  /* no need to mask idx portion */
+	duk_bi_date_timeval_to_parts(d, parts, NULL, flags_and_idx);  /* no need to mask idx portion */
 
 	/* Setter APIs detect special year numbers (0...99) and apply a +1900
 	 * only in certain cases.  The legacy getYear() getter applies -1900
 	 * unconditionally.
 	 */
-	duk_push_int(ctx, (flags_and_idx & DUK__FLAG_SUB1900) ? parts[idx_part] - 1900 : parts[idx_part]);
+	duk_push_int(ctx, (flags_and_idx & DUK_DATE_FLAG_SUB1900) ? parts[idx_part] - 1900 : parts[idx_part]);
 	return 1;
 }
 
@@ -16963,14 +28751,14 @@ static duk_ret_t duk__get_part_helper(duk_context *ctx, duk_small_uint_t flags_a
  * local time), modify one or more components as specified, recompute
  * the time value, set it as the internal value.  Finally, push the
  * new time value as a return value to the value stack and return 1
- * (caller can then tailcall us).
+ * (caller can then tail call us).
  */
-static duk_ret_t duk__set_part_helper(duk_context *ctx, duk_small_uint_t flags_and_maxnargs) {
+DUK_LOCAL duk_ret_t duk__set_part_helper(duk_context *ctx, duk_small_uint_t flags_and_maxnargs) {
 	duk_double_t d;
-	duk_int_t parts[DUK__NUM_PARTS];
-	duk_double_t dparts[DUK__NUM_PARTS];
+	duk_int_t parts[DUK_DATE_IDX_NUM_PARTS];
+	duk_double_t dparts[DUK_DATE_IDX_NUM_PARTS];
 	duk_idx_t nargs;
-	duk_small_uint_t maxnargs = (duk_small_uint_t) (flags_and_maxnargs >> 12);  /* unpack args */
+	duk_small_uint_t maxnargs = (duk_small_uint_t) (flags_and_maxnargs >> DUK_DATE_FLAG_VALUE_SHIFT);  /* unpack args */
 	duk_small_uint_t idx_first, idx;
 	duk_small_uint_t i;
 
@@ -16979,12 +28767,12 @@ static duk_ret_t duk__set_part_helper(duk_context *ctx, duk_small_uint_t flags_a
 	DUK_ASSERT(DUK_ISFINITE(d) || DUK_ISNAN(d));
 
 	if (DUK_ISFINITE(d)) {
-		duk__timeval_to_parts(d, parts, dparts, flags_and_maxnargs);
+		duk_bi_date_timeval_to_parts(d, parts, dparts, flags_and_maxnargs);
 	} else {
 		/* NaN timevalue: we need to coerce the arguments, but
 		 * the resulting internal timestamp needs to remain NaN.
 		 * This works but is not pretty: parts and dparts will
-		 * be partially uninitialized, but we only write to it.
+		 * be partially uninitialized, but we only write to them.
 		 */
 	}
 
@@ -16993,7 +28781,7 @@ static duk_ret_t duk__set_part_helper(duk_context *ctx, duk_small_uint_t flags_a
 	 *  stack arguments is a bit complicated, but important to factor
 	 *  out from setters themselves for compactness.
 	 *
-	 *  If DUK__FLAG_TIMESETTER, maxnargs indicates setter type:
+	 *  If DUK_DATE_FLAG_TIMESETTER, maxnargs indicates setter type:
 	 *
 	 *   1 -> millisecond
 	 *   2 -> second, [millisecond]
@@ -17010,15 +28798,15 @@ static duk_ret_t duk__set_part_helper(duk_context *ctx, duk_small_uint_t flags_a
 	 *  components to override.  We rely on part index ordering.
 	 */
 
-	if (flags_and_maxnargs & DUK__FLAG_TIMESETTER) {
+	if (flags_and_maxnargs & DUK_DATE_FLAG_TIMESETTER) {
 		DUK_ASSERT(maxnargs >= 1 && maxnargs <= 4);
-		idx_first = DUK__IDX_MILLISECOND - (maxnargs - 1);
+		idx_first = DUK_DATE_IDX_MILLISECOND - (maxnargs - 1);
 	} else {
 		DUK_ASSERT(maxnargs >= 1 && maxnargs <= 3);
-		idx_first = DUK__IDX_DAY - (maxnargs - 1);
+		idx_first = DUK_DATE_IDX_DAY - (maxnargs - 1);
 	}
 	DUK_ASSERT_DISABLE(idx_first >= 0);  /* unsigned */
-	DUK_ASSERT(idx_first < DUK__NUM_PARTS);
+	DUK_ASSERT(idx_first < DUK_DATE_IDX_NUM_PARTS);
 
 	for (i = 0; i < maxnargs; i++) {
 		if ((duk_idx_t) i >= nargs) {
@@ -17027,15 +28815,15 @@ static duk_ret_t duk__set_part_helper(duk_context *ctx, duk_small_uint_t flags_a
 		}
 		idx = idx_first + i;
 		DUK_ASSERT_DISABLE(idx >= 0);  /* unsigned */
-		DUK_ASSERT(idx < DUK__NUM_PARTS);
+		DUK_ASSERT(idx < DUK_DATE_IDX_NUM_PARTS);
 
-		if (idx == DUK__IDX_YEAR && (flags_and_maxnargs & DUK__FLAG_YEAR_FIXUP)) {
+		if (idx == DUK_DATE_IDX_YEAR && (flags_and_maxnargs & DUK_DATE_FLAG_YEAR_FIXUP)) {
 			duk__twodigit_year_fixup(ctx, (duk_idx_t) i);
 		}
 
 		dparts[idx] = duk_to_number(ctx, i);
 
-		if (idx == DUK__IDX_DAY) {
+		if (idx == DUK_DATE_IDX_DAY) {
 			/* Day-of-month is one-based in the API, but zero-based
 			 * internally, so fix here.  Note that month is zero-based
 			 * both in the API and internally.
@@ -17064,7 +28852,7 @@ static duk_ret_t duk__set_part_helper(duk_context *ctx, duk_small_uint_t flags_a
 /* Apply ToNumber() to specified index; if ToInteger(val) in [0,99], add
  * 1900 and replace value at idx_val.
  */
-static void duk__twodigit_year_fixup(duk_context *ctx, duk_idx_t idx_val) {
+DUK_LOCAL void duk__twodigit_year_fixup(duk_context *ctx, duk_idx_t idx_val) {
 	duk_double_t d;
 
 	/* XXX: idx_val would fit into 16 bits, but using duk_small_uint_t
@@ -17090,7 +28878,7 @@ static void duk__twodigit_year_fixup(duk_context *ctx, duk_idx_t idx_val) {
 /* Set datetime parts from stack arguments, defaulting any missing values.
  * Day-of-week is not set; it is not required when setting the time value.
  */
-static void duk__set_parts_from_args(duk_context *ctx, duk_double_t *dparts, duk_idx_t nargs) {
+DUK_LOCAL void duk__set_parts_from_args(duk_context *ctx, duk_double_t *dparts, duk_idx_t nargs) {
 	duk_double_t d;
 	duk_small_uint_t i;
 	duk_small_uint_t idx;
@@ -17101,15 +28889,15 @@ static void duk__set_parts_from_args(duk_context *ctx, duk_double_t *dparts, duk
 	duk__twodigit_year_fixup(ctx, 0);
 
 	/* There are at most 7 args, but we use 8 here so that also
-	 * DUK__IDX_WEEKDAY gets initialized (to zero) to avoid the potential
+	 * DUK_DATE_IDX_WEEKDAY gets initialized (to zero) to avoid the potential
 	 * for any Valgrind gripes later.
 	 */
 	for (i = 0; i < 8; i++) {
 		/* Note: rely on index ordering */
-		idx = DUK__IDX_YEAR + i;
+		idx = DUK_DATE_IDX_YEAR + i;
 		if ((duk_idx_t) i < nargs) {
 			d = duk_to_number(ctx, (duk_idx_t) i);
-			if (idx == DUK__IDX_DAY) {
+			if (idx == DUK_DATE_IDX_DAY) {
 				/* Convert day from one-based to zero-based (internal).  This may
 				 * cause the day part to be negative, which is OK.
 				 */
@@ -17137,30 +28925,169 @@ static void duk__set_parts_from_args(duk_context *ctx, duk_double_t *dparts, duk
  *  'out_buf' must be at least DUK_BI_DATE_ISO8601_BUFSIZE long.
  */
 
-void duk_bi_date_format_timeval(duk_double_t timeval, duk_uint8_t *out_buf) {
-	duk_int_t parts[DUK__NUM_PARTS];
+DUK_INTERNAL void duk_bi_date_format_timeval(duk_double_t timeval, duk_uint8_t *out_buf) {
+	duk_int_t parts[DUK_DATE_IDX_NUM_PARTS];
 
-	duk__timeval_to_parts(timeval,
-	                      parts,
-	                      NULL,
-	                      DUK__FLAG_ONEBASED);
+	duk_bi_date_timeval_to_parts(timeval,
+	                             parts,
+	                             NULL,
+	                             DUK_DATE_FLAG_ONEBASED);
 
 	duk__format_parts_iso8601(parts,
 	                          0 /*tzoffset*/,
-	                          DUK__FLAG_TOSTRING_DATE |
-	                          DUK__FLAG_TOSTRING_TIME |
-	                          DUK__FLAG_SEP_T /*flags*/,
+	                          DUK_DATE_FLAG_TOSTRING_DATE |
+	                          DUK_DATE_FLAG_TOSTRING_TIME |
+	                          DUK_DATE_FLAG_SEP_T /*flags*/,
 	                          out_buf);
 }
 
 /*
+ *  Indirect magic value lookup for Date methods.
+ *
+ *  Date methods don't put their control flags into the function magic value
+ *  because they wouldn't fit into a LIGHTFUNC's magic field.  Instead, the
+ *  magic value is set to an index pointing to the array of control flags
+ *  below.
+ *
+ *  This must be kept in strict sync with genbuiltins.py!
+ */
+
+static duk_uint16_t duk__date_magics[] = {
+	/* 0: toString */
+	DUK_DATE_FLAG_TOSTRING_DATE + DUK_DATE_FLAG_TOSTRING_TIME + DUK_DATE_FLAG_LOCALTIME,
+
+	/* 1: toDateString */
+	DUK_DATE_FLAG_TOSTRING_DATE + DUK_DATE_FLAG_LOCALTIME,
+
+	/* 2: toTimeString */
+	DUK_DATE_FLAG_TOSTRING_TIME + DUK_DATE_FLAG_LOCALTIME,
+
+	/* 3: toLocaleString */
+	DUK_DATE_FLAG_TOSTRING_DATE + DUK_DATE_FLAG_TOSTRING_TIME + DUK_DATE_FLAG_TOSTRING_LOCALE + DUK_DATE_FLAG_LOCALTIME,
+
+	/* 4: toLocaleDateString */
+	DUK_DATE_FLAG_TOSTRING_DATE + DUK_DATE_FLAG_TOSTRING_LOCALE + DUK_DATE_FLAG_LOCALTIME,
+
+	/* 5: toLocaleTimeString */
+	DUK_DATE_FLAG_TOSTRING_TIME + DUK_DATE_FLAG_TOSTRING_LOCALE + DUK_DATE_FLAG_LOCALTIME,
+
+	/* 6: toUTCString */
+	DUK_DATE_FLAG_TOSTRING_DATE + DUK_DATE_FLAG_TOSTRING_TIME,
+
+	/* 7: toISOString */
+	DUK_DATE_FLAG_TOSTRING_DATE + DUK_DATE_FLAG_TOSTRING_TIME + DUK_DATE_FLAG_NAN_TO_RANGE_ERROR + DUK_DATE_FLAG_SEP_T,
+
+	/* 8: getFullYear */
+	DUK_DATE_FLAG_LOCALTIME + (DUK_DATE_IDX_YEAR << DUK_DATE_FLAG_VALUE_SHIFT),
+
+	/* 9: getUTCFullYear */
+	0 + (DUK_DATE_IDX_YEAR << DUK_DATE_FLAG_VALUE_SHIFT),
+
+	/* 10: getMonth */
+	DUK_DATE_FLAG_LOCALTIME + (DUK_DATE_IDX_MONTH << DUK_DATE_FLAG_VALUE_SHIFT),
+
+	/* 11: getUTCMonth */
+	0 + (DUK_DATE_IDX_MONTH << DUK_DATE_FLAG_VALUE_SHIFT),
+
+	/* 12: getDate */
+	DUK_DATE_FLAG_ONEBASED + DUK_DATE_FLAG_LOCALTIME + (DUK_DATE_IDX_DAY << DUK_DATE_FLAG_VALUE_SHIFT),
+
+	/* 13: getUTCDate */
+	DUK_DATE_FLAG_ONEBASED + (DUK_DATE_IDX_DAY << DUK_DATE_FLAG_VALUE_SHIFT),
+
+	/* 14: getDay */
+	DUK_DATE_FLAG_LOCALTIME + (DUK_DATE_IDX_WEEKDAY << DUK_DATE_FLAG_VALUE_SHIFT),
+
+	/* 15: getUTCDay */
+	0 + (DUK_DATE_IDX_WEEKDAY << DUK_DATE_FLAG_VALUE_SHIFT),
+
+	/* 16: getHours */
+	DUK_DATE_FLAG_LOCALTIME + (DUK_DATE_IDX_HOUR << DUK_DATE_FLAG_VALUE_SHIFT),
+
+	/* 17: getUTCHours */
+	0 + (DUK_DATE_IDX_HOUR << DUK_DATE_FLAG_VALUE_SHIFT),
+
+	/* 18: getMinutes */
+	DUK_DATE_FLAG_LOCALTIME + (DUK_DATE_IDX_MINUTE << DUK_DATE_FLAG_VALUE_SHIFT),
+
+	/* 19: getUTCMinutes */
+	0 + (DUK_DATE_IDX_MINUTE << DUK_DATE_FLAG_VALUE_SHIFT),
+
+	/* 20: getSeconds */
+	DUK_DATE_FLAG_LOCALTIME + (DUK_DATE_IDX_SECOND << DUK_DATE_FLAG_VALUE_SHIFT),
+
+	/* 21: getUTCSeconds */
+	0 + (DUK_DATE_IDX_SECOND << DUK_DATE_FLAG_VALUE_SHIFT),
+
+	/* 22: getMilliseconds */
+	DUK_DATE_FLAG_LOCALTIME + (DUK_DATE_IDX_MILLISECOND << DUK_DATE_FLAG_VALUE_SHIFT),
+
+	/* 23: getUTCMilliseconds */
+	0 + (DUK_DATE_IDX_MILLISECOND << DUK_DATE_FLAG_VALUE_SHIFT),
+
+	/* 24: setMilliseconds */
+	DUK_DATE_FLAG_TIMESETTER + DUK_DATE_FLAG_LOCALTIME + (1 << DUK_DATE_FLAG_VALUE_SHIFT),
+
+	/* 25: setUTCMilliseconds */
+	DUK_DATE_FLAG_TIMESETTER + (1 << DUK_DATE_FLAG_VALUE_SHIFT),
+
+	/* 26: setSeconds */
+	DUK_DATE_FLAG_TIMESETTER + DUK_DATE_FLAG_LOCALTIME + (2 << DUK_DATE_FLAG_VALUE_SHIFT),
+
+	/* 27: setUTCSeconds */
+	DUK_DATE_FLAG_TIMESETTER + (2 << DUK_DATE_FLAG_VALUE_SHIFT),
+
+	/* 28: setMinutes */
+	DUK_DATE_FLAG_TIMESETTER + DUK_DATE_FLAG_LOCALTIME + (3 << DUK_DATE_FLAG_VALUE_SHIFT),
+
+	/* 29: setUTCMinutes */
+	DUK_DATE_FLAG_TIMESETTER + (3 << DUK_DATE_FLAG_VALUE_SHIFT),
+
+	/* 30: setHours */
+	DUK_DATE_FLAG_TIMESETTER + DUK_DATE_FLAG_LOCALTIME + (4 << DUK_DATE_FLAG_VALUE_SHIFT),
+
+	/* 31: setUTCHours */
+	DUK_DATE_FLAG_TIMESETTER + (4 << DUK_DATE_FLAG_VALUE_SHIFT),
+
+	/* 32: setDate */
+	DUK_DATE_FLAG_LOCALTIME + (1 << DUK_DATE_FLAG_VALUE_SHIFT),
+
+	/* 33: setUTCDate */
+	0 + (1 << DUK_DATE_FLAG_VALUE_SHIFT),
+
+	/* 34: setMonth */
+	DUK_DATE_FLAG_LOCALTIME + (2 << DUK_DATE_FLAG_VALUE_SHIFT),
+
+	/* 35: setUTCMonth */
+	0 + (2 << DUK_DATE_FLAG_VALUE_SHIFT),
+
+	/* 36: setFullYear */
+	DUK_DATE_FLAG_NAN_TO_ZERO + DUK_DATE_FLAG_LOCALTIME + (3 << DUK_DATE_FLAG_VALUE_SHIFT),
+
+	/* 37: setUTCFullYear */
+	DUK_DATE_FLAG_NAN_TO_ZERO + (3 << DUK_DATE_FLAG_VALUE_SHIFT),
+
+	/* 38: getYear */
+	DUK_DATE_FLAG_LOCALTIME + DUK_DATE_FLAG_SUB1900 + (DUK_DATE_IDX_YEAR << DUK_DATE_FLAG_VALUE_SHIFT),
+
+	/* 39: setYear */
+	DUK_DATE_FLAG_NAN_TO_ZERO + DUK_DATE_FLAG_YEAR_FIXUP + (3 << DUK_DATE_FLAG_VALUE_SHIFT),
+};
+
+DUK_LOCAL duk_small_uint_t duk__date_get_indirect_magic(duk_context *ctx) {
+	duk_small_int_t magicidx = (duk_small_uint_t) duk_get_current_magic(ctx);
+	DUK_ASSERT(magicidx >= 0 && magicidx < (duk_small_int_t) (sizeof(duk__date_magics) / sizeof(duk_uint16_t)));
+	return (duk_small_uint_t) duk__date_magics[magicidx];
+}
+
+/*
  *  Constructor calls
  */
 
-duk_ret_t duk_bi_date_constructor(duk_context *ctx) {
+DUK_INTERNAL duk_ret_t duk_bi_date_constructor(duk_context *ctx) {
 	duk_idx_t nargs = duk_get_top(ctx);
 	duk_bool_t is_cons = duk_is_constructor_call(ctx);
-	duk_double_t dparts[DUK__NUM_PARTS];
+	duk_double_t dparts[DUK_DATE_IDX_NUM_PARTS];
 	duk_double_t d;
 
 	DUK_DDD(DUK_DDDPRINT("Date constructor, nargs=%ld, is_cons=%ld", (long) nargs, (long) is_cons));
@@ -17175,9 +29102,9 @@ duk_ret_t duk_bi_date_constructor(duk_context *ctx) {
 	 */
 
 	if (nargs == 0 || !is_cons) {
-		d = duk__timeclip(DUK__GET_NOW_TIMEVAL(ctx));
+		d = duk__timeclip(DUK_USE_DATE_GET_NOW(ctx));
 		duk_push_number(ctx, d);
-		duk_def_prop_stridx(ctx, -2, DUK_STRIDX_INT_VALUE, DUK_PROPDESC_FLAGS_W);
+		duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_INT_VALUE, DUK_PROPDESC_FLAGS_W);
 		if (!is_cons) {
 			/* called as a normal function: return new Date().toString() */
 			duk_to_string(ctx, -1);
@@ -17191,7 +29118,7 @@ duk_ret_t duk_bi_date_constructor(duk_context *ctx) {
 		}
 		d = duk__timeclip(duk_to_number(ctx, 0));
 		duk_push_number(ctx, d);
-		duk_def_prop_stridx(ctx, -2, DUK_STRIDX_INT_VALUE, DUK_PROPDESC_FLAGS_W);
+		duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_INT_VALUE, DUK_PROPDESC_FLAGS_W);
 		return 1;
 	}
 
@@ -17199,18 +29126,18 @@ duk_ret_t duk_bi_date_constructor(duk_context *ctx) {
 
 	/* Parts are in local time, convert when setting. */
 
-	(void) duk__set_this_timeval_from_dparts(ctx, dparts, DUK__FLAG_LOCALTIME /*flags*/);  /* -> [ ... this timeval ] */
+	(void) duk__set_this_timeval_from_dparts(ctx, dparts, DUK_DATE_FLAG_LOCALTIME /*flags*/);  /* -> [ ... this timeval ] */
 	duk_pop(ctx);  /* -> [ ... this ] */
 	return 1;
 }
 
-duk_ret_t duk_bi_date_constructor_parse(duk_context *ctx) {
+DUK_INTERNAL duk_ret_t duk_bi_date_constructor_parse(duk_context *ctx) {
 	return duk__parse_string(ctx, duk_to_string(ctx, 0));
 }
 
-duk_ret_t duk_bi_date_constructor_utc(duk_context *ctx) {
+DUK_INTERNAL duk_ret_t duk_bi_date_constructor_utc(duk_context *ctx) {
 	duk_idx_t nargs = duk_get_top(ctx);
-	duk_double_t dparts[DUK__NUM_PARTS];
+	duk_double_t dparts[DUK_DATE_IDX_NUM_PARTS];
 	duk_double_t d;
 
 	/* Behavior for nargs < 2 is implementation dependent: currently we'll
@@ -17221,16 +29148,16 @@ duk_ret_t duk_bi_date_constructor_utc(duk_context *ctx) {
 		duk_push_nan(ctx);
 	} else {
 		duk__set_parts_from_args(ctx, dparts, nargs);
-		d = duk__get_timeval_from_dparts(dparts, 0 /*flags*/);
+		d = duk_bi_date_get_timeval_from_dparts(dparts, 0 /*flags*/);
 		duk_push_number(ctx, d);
 	}
 	return 1;
 }
 
-duk_ret_t duk_bi_date_constructor_now(duk_context *ctx) {
+DUK_INTERNAL duk_ret_t duk_bi_date_constructor_now(duk_context *ctx) {
 	duk_double_t d;
 
-	d = DUK__GET_NOW_TIMEVAL(ctx);
+	d = DUK_USE_DATE_GET_NOW(ctx);
 	DUK_ASSERT(duk__timeclip(d) == d);  /* TimeClip() should never be necessary */
 	duk_push_number(ctx, d);
 	return 1;
@@ -17270,12 +29197,12 @@ duk_ret_t duk_bi_date_constructor_now(duk_context *ctx) {
  *      toISOString() requires a RangeError for invalid date values.
  */
 
-duk_ret_t duk_bi_date_prototype_tostring_shared(duk_context *ctx) {
-	duk_small_uint_t flags = (duk_small_uint_t) duk_get_magic(ctx);
+DUK_INTERNAL duk_ret_t duk_bi_date_prototype_tostring_shared(duk_context *ctx) {
+	duk_small_uint_t flags = duk__date_get_indirect_magic(ctx);
 	return duk__to_string_helper(ctx, flags);
 }
 
-duk_ret_t duk_bi_date_prototype_value_of(duk_context *ctx) {
+DUK_INTERNAL duk_ret_t duk_bi_date_prototype_value_of(duk_context *ctx) {
 	/* This native function is also used for Date.prototype.getTime()
 	 * as their behavior is identical.
 	 */
@@ -17286,7 +29213,7 @@ duk_ret_t duk_bi_date_prototype_value_of(duk_context *ctx) {
 	return 1;
 }
 
-duk_ret_t duk_bi_date_prototype_to_json(duk_context *ctx) {
+DUK_INTERNAL duk_ret_t duk_bi_date_prototype_to_json(duk_context *ctx) {
 	/* Note: toJSON() is a generic function which works even if 'this'
 	 * is not a Date.  The sole argument is ignored.
 	 */
@@ -17352,12 +29279,12 @@ duk_ret_t duk_bi_date_prototype_to_json(duk_context *ctx) {
  *      function (duk_bi_date_prototype_value_of).
  */
 
-duk_ret_t duk_bi_date_prototype_get_shared(duk_context *ctx) {
-	duk_small_uint_t flags_and_idx = (duk_small_uint_t) duk_get_magic(ctx);
+DUK_INTERNAL duk_ret_t duk_bi_date_prototype_get_shared(duk_context *ctx) {
+	duk_small_uint_t flags_and_idx = duk__date_get_indirect_magic(ctx);
 	return duk__get_part_helper(ctx, flags_and_idx);
 }
 
-duk_ret_t duk_bi_date_prototype_get_timezone_offset(duk_context *ctx) {
+DUK_INTERNAL duk_ret_t duk_bi_date_prototype_get_timezone_offset(duk_context *ctx) {
 	/*
 	 *  Return (t - LocalTime(t)) in minutes:
 	 *
@@ -17382,7 +29309,7 @@ duk_ret_t duk_bi_date_prototype_get_timezone_offset(duk_context *ctx) {
 		duk_push_nan(ctx);
 	} else {
 		DUK_ASSERT(DUK_ISFINITE(d));
-		tzoffset = DUK__GET_LOCAL_TZOFFSET(d);
+		tzoffset = DUK_USE_DATE_GET_LOCAL_TZOFFSET(d);
 		duk_push_int(ctx, -tzoffset / 60);
 	}
 	return 1;
@@ -17437,12 +29364,12 @@ duk_ret_t duk_bi_date_prototype_get_timezone_offset(duk_context *ctx) {
  *      the year will be set regardless of actual argument count.
  */
 
-duk_ret_t duk_bi_date_prototype_set_shared(duk_context *ctx) {
-	duk_small_uint_t flags_and_maxnargs = (duk_small_uint_t) duk_get_magic(ctx);
+DUK_INTERNAL duk_ret_t duk_bi_date_prototype_set_shared(duk_context *ctx) {
+	duk_small_uint_t flags_and_maxnargs = duk__date_get_indirect_magic(ctx);
 	return duk__set_part_helper(ctx, flags_and_maxnargs);
 }
 
-duk_ret_t duk_bi_date_prototype_set_time(duk_context *ctx) {
+DUK_INTERNAL duk_ret_t duk_bi_date_prototype_set_time(duk_context *ctx) {
 	duk_double_t d;
 
 	(void) duk__push_this_get_timeval(ctx, 0 /*flags*/); /* -> [ timeval this ] */
@@ -17453,6 +29380,417 @@ duk_ret_t duk_bi_date_prototype_set_time(duk_context *ctx) {
 
 	return 1;
 }
+#line 1 "duk_bi_date_unix.c"
+/*
+ *  Unix-like Date providers
+ *
+ *  Generally useful Unix / POSIX / ANSI Date providers.
+ */
+
+/* include removed: duk_internal.h */
+
+/* The necessary #includes are in place in duk_config.h. */
+
+/* Buffer sizes for some UNIX calls.  Larger than strictly necessary
+ * to avoid Valgrind errors.
+ */
+#define DUK__STRPTIME_BUF_SIZE  64
+#define DUK__STRFTIME_BUF_SIZE  64
+
+#if defined(DUK_USE_DATE_NOW_GETTIMEOFDAY)
+/* Get current Ecmascript time (= UNIX/Posix time, but in milliseconds). */
+DUK_INTERNAL duk_double_t duk_bi_date_get_now_gettimeofday(duk_context *ctx) {
+	duk_hthread *thr = (duk_hthread *) ctx;
+	struct timeval tv;
+	duk_double_t d;
+
+	if (gettimeofday(&tv, NULL) != 0) {
+		DUK_ERROR(thr, DUK_ERR_INTERNAL_ERROR, "gettimeofday failed");
+	}
+
+	d = ((duk_double_t) tv.tv_sec) * 1000.0 +
+	    ((duk_double_t) (tv.tv_usec / 1000));
+	DUK_ASSERT(DUK_FLOOR(d) == d);  /* no fractions */
+
+	return d;
+}
+#endif  /* DUK_USE_DATE_NOW_GETTIMEOFDAY */
+
+#if defined(DUK_USE_DATE_NOW_TIME)
+/* Not a very good provider: only full seconds are available. */
+DUK_INTERNAL duk_double_t duk_bi_date_get_now_time(duk_context *ctx) {
+	time_t t;
+
+	DUK_UNREF(ctx);
+	t = time(NULL);
+	return ((duk_double_t) t) * 1000.0;
+}
+#endif  /* DUK_USE_DATE_NOW_TIME */
+
+#if defined(DUK_USE_DATE_TZO_GMTIME) || defined(DUK_USE_DATE_TZO_GMTIME_R)
+/* Get local time offset (in seconds) for a certain (UTC) instant 'd'. */
+DUK_INTERNAL duk_int_t duk_bi_date_get_local_tzoffset_gmtime(duk_double_t d) {
+	time_t t, t1, t2;
+	duk_int_t parts[DUK_DATE_IDX_NUM_PARTS];
+	duk_double_t dparts[DUK_DATE_IDX_NUM_PARTS];
+	struct tm tms[2];
+#ifdef DUK_USE_DATE_TZO_GMTIME
+	struct tm *tm_ptr;
+#endif
+
+	/* For NaN/inf, the return value doesn't matter. */
+	if (!DUK_ISFINITE(d)) {
+		return 0;
+	}
+
+	/* If not within Ecmascript range, some integer time calculations
+	 * won't work correctly (and some asserts will fail), so bail out
+	 * if so.  This fixes test-bug-date-insane-setyear.js.  There is
+	 * a +/- 24h leeway in this range check to avoid a test262 corner
+	 * case documented in test-bug-date-timeval-edges.js.
+	 */
+	if (!duk_bi_date_timeval_in_leeway_range(d)) {
+		DUK_DD(DUK_DDPRINT("timeval not within valid range, skip tzoffset computation to avoid integer overflows"));
+		return 0;
+	}
+
+	/*
+	 *  This is a bit tricky to implement portably.  The result depends
+	 *  on the timestamp (specifically, DST depends on the timestamp).
+	 *  If e.g. UNIX APIs are used, they'll have portability issues with
+	 *  very small and very large years.
+	 *
+	 *  Current approach:
+	 *
+	 *  - Stay within portable UNIX limits by using equivalent year mapping.
+	 *    Avoid year 1970 and 2038 as some conversions start to fail, at
+	 *    least on some platforms.  Avoiding 1970 means that there are
+	 *    currently DST discrepancies for 1970.
+	 *
+	 *  - Create a UTC and local time breakdowns from 't'.  Then create
+	 *    a time_t using gmtime() and localtime() and compute the time
+	 *    difference between the two.
+	 *
+	 *  Equivalent year mapping (E5 Section 15.9.1.8):
+	 *
+	 *    If the host environment provides functionality for determining
+	 *    daylight saving time, the implementation of ECMAScript is free
+	 *    to map the year in question to an equivalent year (same
+	 *    leap-year-ness and same starting week day for the year) for which
+	 *    the host environment provides daylight saving time information.
+	 *    The only restriction is that all equivalent years should produce
+	 *    the same result.
+	 *
+	 *  This approach is quite reasonable but not entirely correct, e.g.
+	 *  the specification also states (E5 Section 15.9.1.8):
+	 *
+	 *    The implementation of ECMAScript should not try to determine
+	 *    whether the exact time was subject to daylight saving time, but
+	 *    just whether daylight saving time would have been in effect if
+	 *    the _current daylight saving time algorithm_ had been used at the
+	 *    time.  This avoids complications such as taking into account the
+	 *    years that the locale observed daylight saving time year round.
+	 *
+	 *  Since we rely on the platform APIs for conversions between local
+	 *  time and UTC, we can't guarantee the above.  Rather, if the platform
+	 *  has historical DST rules they will be applied.  This seems to be the
+	 *  general preferred direction in Ecmascript standardization (or at least
+	 *  implementations) anyway, and even the equivalent year mapping should
+	 *  be disabled if the platform is known to handle DST properly for the
+	 *  full Ecmascript range.
+	 *
+	 *  The following has useful discussion and links:
+	 *
+	 *    https://bugzilla.mozilla.org/show_bug.cgi?id=351066
+	 */
+
+	duk_bi_date_timeval_to_parts(d, parts, dparts, DUK_DATE_FLAG_EQUIVYEAR /*flags*/);
+	DUK_ASSERT(parts[DUK_DATE_IDX_YEAR] >= 1970 && parts[DUK_DATE_IDX_YEAR] <= 2038);
+
+	d = duk_bi_date_get_timeval_from_dparts(dparts, 0 /*flags*/);
+	DUK_ASSERT(d >= 0 && d < 2147483648.0 * 1000.0);  /* unsigned 31-bit range */
+	t = (time_t) (d / 1000.0);
+	DUK_DDD(DUK_DDDPRINT("timeval: %lf -> time_t %ld", (double) d, (long) t));
+
+	t1 = t;
+
+	DUK_MEMZERO((void *) tms, sizeof(struct tm) * 2);
+
+#if defined(DUK_USE_DATE_TZO_GMTIME_R)
+	(void) gmtime_r(&t, &tms[0]);
+	(void) localtime_r(&t, &tms[1]);
+#elif defined(DUK_USE_DATE_TZO_GMTIME)
+	tm_ptr = gmtime(&t);
+	DUK_MEMCPY((void *) &tms[0], tm_ptr, sizeof(struct tm));
+	tm_ptr = localtime(&t);
+	DUK_MEMCPY((void *) &tms[1], tm_ptr, sizeof(struct tm));
+#else
+#error internal error
+#endif
+	DUK_DDD(DUK_DDDPRINT("gmtime result: tm={sec:%ld,min:%ld,hour:%ld,mday:%ld,mon:%ld,year:%ld,"
+	                     "wday:%ld,yday:%ld,isdst:%ld}",
+	                     (long) tms[0].tm_sec, (long) tms[0].tm_min, (long) tms[0].tm_hour,
+	                     (long) tms[0].tm_mday, (long) tms[0].tm_mon, (long) tms[0].tm_year,
+	                     (long) tms[0].tm_wday, (long) tms[0].tm_yday, (long) tms[0].tm_isdst));
+	DUK_DDD(DUK_DDDPRINT("localtime result: tm={sec:%ld,min:%ld,hour:%ld,mday:%ld,mon:%ld,year:%ld,"
+	                     "wday:%ld,yday:%ld,isdst:%ld}",
+	                     (long) tms[1].tm_sec, (long) tms[1].tm_min, (long) tms[1].tm_hour,
+	                     (long) tms[1].tm_mday, (long) tms[1].tm_mon, (long) tms[1].tm_year,
+	                     (long) tms[1].tm_wday, (long) tms[1].tm_yday, (long) tms[1].tm_isdst));
+
+	/* tm_isdst is both an input and an output to mktime(), use 0 to
+	 * avoid DST handling in mktime():
+	 * - https://github.com/svaarala/duktape/issues/406
+	 * - http://stackoverflow.com/questions/8558919/mktime-and-tm-isdst
+	 */
+	tms[0].tm_isdst = 0;
+	tms[1].tm_isdst = 0;
+	t1 = mktime(&tms[0]);  /* UTC */
+	t2 = mktime(&tms[1]);  /* local */
+	if (t1 == (time_t) -1 || t2 == (time_t) -1) {
+		/* This check used to be for (t < 0) but on some platforms
+		 * time_t is unsigned and apparently the proper way to detect
+		 * an mktime() error return is the cast above.  See e.g.:
+		 * http://pubs.opengroup.org/onlinepubs/009695299/functions/mktime.html
+		 */
+		goto error;
+	}
+	DUK_DDD(DUK_DDDPRINT("t1=%ld (utc), t2=%ld (local)", (long) t1, (long) t2));
+
+	/* Compute final offset in seconds, positive if local time ahead of
+	 * UTC (returned value is UTC-to-local offset).
+	 *
+	 * difftime() returns a double, so coercion to int generates quite
+	 * a lot of code.  Direct subtraction is not portable, however.
+	 * XXX: allow direct subtraction on known platforms.
+	 */
+#if 0
+	return (duk_int_t) (t2 - t1);
+#endif
+	return (duk_int_t) difftime(t2, t1);
+
+ error:
+	/* XXX: return something more useful, so that caller can throw? */
+	DUK_D(DUK_DPRINT("mktime() failed, d=%lf", (double) d));
+	return 0;
+}
+#endif  /* DUK_USE_DATE_TZO_GMTIME */
+
+#if defined(DUK_USE_DATE_PRS_STRPTIME)
+DUK_INTERNAL duk_bool_t duk_bi_date_parse_string_strptime(duk_context *ctx, const char *str) {
+	struct tm tm;
+	time_t t;
+	char buf[DUK__STRPTIME_BUF_SIZE];
+
+	/* copy to buffer with spare to avoid Valgrind gripes from strptime */
+	DUK_ASSERT(str != NULL);
+	DUK_MEMZERO(buf, sizeof(buf));  /* valgrind whine without this */
+	DUK_SNPRINTF(buf, sizeof(buf), "%s", (const char *) str);
+	buf[sizeof(buf) - 1] = (char) 0;
+
+	DUK_DDD(DUK_DDDPRINT("parsing: '%s'", (const char *) buf));
+
+	DUK_MEMZERO(&tm, sizeof(tm));
+	if (strptime((const char *) buf, "%c", &tm) != NULL) {
+		DUK_DDD(DUK_DDDPRINT("before mktime: tm={sec:%ld,min:%ld,hour:%ld,mday:%ld,mon:%ld,year:%ld,"
+		                     "wday:%ld,yday:%ld,isdst:%ld}",
+		                     (long) tm.tm_sec, (long) tm.tm_min, (long) tm.tm_hour,
+		                     (long) tm.tm_mday, (long) tm.tm_mon, (long) tm.tm_year,
+		                     (long) tm.tm_wday, (long) tm.tm_yday, (long) tm.tm_isdst));
+		tm.tm_isdst = -1;  /* negative: dst info not available */
+
+		t = mktime(&tm);
+		DUK_DDD(DUK_DDDPRINT("mktime() -> %ld", (long) t));
+		if (t >= 0) {
+			duk_push_number(ctx, ((duk_double_t) t) * 1000.0);
+			return 1;
+		}
+	}
+
+	return 0;
+}
+#endif  /* DUK_USE_DATE_PRS_STRPTIME */
+
+#if defined(DUK_USE_DATE_PRS_GETDATE)
+DUK_INTERNAL duk_bool_t duk_bi_date_parse_string_getdate(duk_context *ctx, const char *str) {
+	struct tm tm;
+	duk_small_int_t rc;
+	time_t t;
+
+	/* For this to work, DATEMSK must be set, so this is not very
+	 * convenient for an embeddable interpreter.
+	 */
+
+	DUK_MEMZERO(&tm, sizeof(struct tm));
+	rc = (duk_small_int_t) getdate_r(str, &tm);
+	DUK_DDD(DUK_DDDPRINT("getdate_r() -> %ld", (long) rc));
+
+	if (rc == 0) {
+		t = mktime(&tm);
+		DUK_DDD(DUK_DDDPRINT("mktime() -> %ld", (long) t));
+		if (t >= 0) {
+			duk_push_number(ctx, (duk_double_t) t);
+			return 1;
+		}
+	}
+
+	return 0;
+}
+#endif  /* DUK_USE_DATE_PRS_GETDATE */
+
+#if defined(DUK_USE_DATE_FMT_STRFTIME)
+DUK_INTERNAL duk_bool_t duk_bi_date_format_parts_strftime(duk_context *ctx, duk_int_t *parts, duk_int_t tzoffset, duk_small_uint_t flags) {
+	char buf[DUK__STRFTIME_BUF_SIZE];
+	struct tm tm;
+	const char *fmt;
+
+	DUK_UNREF(tzoffset);
+
+	/* If the platform doesn't support the entire Ecmascript range, we need
+	 * to return 0 so that the caller can fall back to the default formatter.
+	 *
+	 * For now, assume that if time_t is 8 bytes or more, the whole Ecmascript
+	 * range is supported.  For smaller time_t values (4 bytes in practice),
+	 * assumes that the signed 32-bit range is supported.
+	 *
+	 * XXX: detect this more correctly per platform.  The size of time_t is
+	 * probably not an accurate guarantee of strftime() supporting or not
+	 * supporting a large time range (the full Ecmascript range).
+	 */
+	if (sizeof(time_t) < 8 &&
+	   (parts[DUK_DATE_IDX_YEAR] < 1970 || parts[DUK_DATE_IDX_YEAR] > 2037)) {
+		/* be paranoid for 32-bit time values (even avoiding negative ones) */
+		return 0;
+	}
+
+	DUK_MEMZERO(&tm, sizeof(tm));
+	tm.tm_sec = parts[DUK_DATE_IDX_SECOND];
+	tm.tm_min = parts[DUK_DATE_IDX_MINUTE];
+	tm.tm_hour = parts[DUK_DATE_IDX_HOUR];
+	tm.tm_mday = parts[DUK_DATE_IDX_DAY];       /* already one-based */
+	tm.tm_mon = parts[DUK_DATE_IDX_MONTH] - 1;  /* one-based -> zero-based */
+	tm.tm_year = parts[DUK_DATE_IDX_YEAR] - 1900;
+	tm.tm_wday = parts[DUK_DATE_IDX_WEEKDAY];
+	tm.tm_isdst = 0;
+
+	DUK_MEMZERO(buf, sizeof(buf));
+	if ((flags & DUK_DATE_FLAG_TOSTRING_DATE) && (flags & DUK_DATE_FLAG_TOSTRING_TIME)) {
+		fmt = "%c";
+	} else if (flags & DUK_DATE_FLAG_TOSTRING_DATE) {
+		fmt = "%x";
+	} else {
+		DUK_ASSERT(flags & DUK_DATE_FLAG_TOSTRING_TIME);
+		fmt = "%X";
+	}
+	(void) strftime(buf, sizeof(buf) - 1, fmt, &tm);
+	DUK_ASSERT(buf[sizeof(buf) - 1] == 0);
+
+	duk_push_string(ctx, buf);
+	return 1;
+}
+#endif  /* DUK_USE_DATE_FMT_STRFTIME */
+
+#undef DUK__STRPTIME_BUF_SIZE
+#undef DUK__STRFTIME_BUF_SIZE
+#line 1 "duk_bi_date_windows.c"
+/*
+ *  Windows Date providers
+ *
+ *  Platform specific links:
+ *
+ *    - http://msdn.microsoft.com/en-us/library/windows/desktop/ms725473(v=vs.85).aspx
+ */
+
+/* include removed: duk_internal.h */
+
+/* The necessary #includes are in place in duk_config.h. */
+
+#if defined(DUK_USE_DATE_NOW_WINDOWS) || defined(DUK_USE_DATE_TZO_WINDOWS)
+/* Shared Windows helpers. */
+DUK_LOCAL void duk__convert_systime_to_ularge(const SYSTEMTIME *st, ULARGE_INTEGER *res) {
+	FILETIME ft;
+	if (SystemTimeToFileTime(st, &ft) == 0) {
+		DUK_D(DUK_DPRINT("SystemTimeToFileTime() failed, returning 0"));
+		res->QuadPart = 0;
+	} else {
+		res->LowPart = ft.dwLowDateTime;
+		res->HighPart = ft.dwHighDateTime;
+	}
+}
+DUK_LOCAL void duk__set_systime_jan1970(SYSTEMTIME *st) {
+	DUK_MEMZERO((void *) st, sizeof(*st));
+	st->wYear = 1970;
+	st->wMonth = 1;
+	st->wDayOfWeek = 4;  /* not sure whether or not needed; Thursday */
+	st->wDay = 1;
+	DUK_ASSERT(st->wHour == 0);
+	DUK_ASSERT(st->wMinute == 0);
+	DUK_ASSERT(st->wSecond == 0);
+	DUK_ASSERT(st->wMilliseconds == 0);
+}
+#endif  /* defined(DUK_USE_DATE_NOW_WINDOWS) || defined(DUK_USE_DATE_TZO_WINDOWS) */
+
+#ifdef DUK_USE_DATE_NOW_WINDOWS
+DUK_INTERNAL duk_double_t duk_bi_date_get_now_windows(duk_context *ctx) {
+	/* Suggested step-by-step method from documentation of RtlTimeToSecondsSince1970:
+	 * http://msdn.microsoft.com/en-us/library/windows/desktop/ms724928(v=vs.85).aspx
+	 */
+	SYSTEMTIME st1, st2;
+	ULARGE_INTEGER tmp1, tmp2;
+
+	DUK_UNREF(ctx);
+
+	GetSystemTime(&st1);
+	duk__convert_systime_to_ularge((const SYSTEMTIME *) &st1, &tmp1);
+
+	duk__set_systime_jan1970(&st2);
+	duk__convert_systime_to_ularge((const SYSTEMTIME *) &st2, &tmp2);
+
+	/* Difference is in 100ns units, convert to milliseconds w/o fractions */
+	return (duk_double_t) ((tmp1.QuadPart - tmp2.QuadPart) / 10000LL);
+}
+#endif  /* DUK_USE_DATE_NOW_WINDOWS */
+
+
+#if defined(DUK_USE_DATE_TZO_WINDOWS)
+DUK_INTERNAL_DECL duk_int_t duk_bi_date_get_local_tzoffset_windows(duk_double_t d) {
+	SYSTEMTIME st1;
+	SYSTEMTIME st2;
+	SYSTEMTIME st3;
+	ULARGE_INTEGER tmp1;
+	ULARGE_INTEGER tmp2;
+	ULARGE_INTEGER tmp3;
+	FILETIME ft1;
+
+	/* XXX: handling of timestamps outside Windows supported range.
+	 * How does Windows deal with dates before 1600?  Does windows
+	 * support all Ecmascript years (like -200000 and +200000)?
+	 * Should equivalent year mapping be used here too?  If so, use
+	 * a shared helper (currently integrated into timeval-to-parts).
+	 */
+
+	/* Use the approach described in "Remarks" of FileTimeToLocalFileTime:
+	 * http://msdn.microsoft.com/en-us/library/windows/desktop/ms724277(v=vs.85).aspx
+	 */
+
+	duk__set_systime_jan1970(&st1);
+	duk__convert_systime_to_ularge((const SYSTEMTIME *) &st1, &tmp1);
+	tmp2.QuadPart = (ULONGLONG) (d * 10000.0);  /* millisec -> 100ns units since jan 1, 1970 */
+	tmp2.QuadPart += tmp1.QuadPart;             /* input 'd' in Windows UTC, 100ns units */
+
+	ft1.dwLowDateTime = tmp2.LowPart;
+	ft1.dwHighDateTime = tmp2.HighPart;
+	FileTimeToSystemTime((const FILETIME *) &ft1, &st2);
+	if (SystemTimeToTzSpecificLocalTime((LPTIME_ZONE_INFORMATION) NULL, &st2, &st3) == 0) {
+		DUK_D(DUK_DPRINT("SystemTimeToTzSpecificLocalTime() failed, return tzoffset 0"));
+		return 0;
+	}
+	duk__convert_systime_to_ularge((const SYSTEMTIME *) &st3, &tmp3);
+
+	/* Positive if local time ahead of UTC. */
+	return (duk_int_t) (((LONGLONG) tmp3.QuadPart - (LONGLONG) tmp2.QuadPart) / 10000000LL);  /* seconds */
+}
+#endif  /* DUK_USE_DATE_TZO_WINDOWS */
 #line 1 "duk_bi_duktape.c"
 /*
  *  Duktape built-ins
@@ -17473,24 +29811,29 @@ duk_ret_t duk_bi_date_prototype_set_time(duk_context *ctx) {
  * 'data' buffer might be an issue).  Currently only counts and sizes and
  * such are given so there should not be a security impact.
  */
-duk_ret_t duk_bi_duktape_object_info(duk_context *ctx) {
+DUK_INTERNAL duk_ret_t duk_bi_duktape_object_info(duk_context *ctx) {
+	duk_hthread *thr = (duk_hthread *) ctx;
 	duk_tval *tv;
 	duk_heaphdr *h;
 	duk_int_t i, n;
 
-	tv = duk_get_tval(ctx, 0);
-	DUK_ASSERT(tv != NULL);  /* because arg count is 1 */
+	DUK_UNREF(thr);
 
+	/* result array */
 	duk_push_array(ctx);  /* -> [ val arr ] */
 
 	/* type tag (public) */
 	duk_push_int(ctx, duk_get_type(ctx, 0));
 
 	/* address */
+	tv = duk_get_tval(ctx, 0);
+	DUK_ASSERT(tv != NULL);  /* because arg count is 1 */
 	if (DUK_TVAL_IS_HEAP_ALLOCATED(tv)) {
 		h = DUK_TVAL_GET_HEAPHDR(tv);
 		duk_push_pointer(ctx, (void *) h);
 	} else {
+		/* internal type tag */
+		duk_push_int(ctx, (duk_int_t) DUK_TVAL_GET_TAG(tv));
 		goto done;
 	}
 	DUK_ASSERT(h != NULL);
@@ -17525,12 +29868,19 @@ duk_ret_t duk_bi_duktape_object_info(duk_context *ctx) {
 		}
 		duk_push_uint(ctx, (duk_uint_t) hdr_size);
 		duk_push_uint(ctx, (duk_uint_t) DUK_HOBJECT_E_ALLOC_SIZE(h_obj));
-		duk_push_uint(ctx, (duk_uint_t) h_obj->e_size);
-		duk_push_uint(ctx, (duk_uint_t) h_obj->e_used);
-		duk_push_uint(ctx, (duk_uint_t) h_obj->a_size);
-		duk_push_uint(ctx, (duk_uint_t) h_obj->h_size);
+		duk_push_uint(ctx, (duk_uint_t) DUK_HOBJECT_GET_ESIZE(h_obj));
+		/* Note: e_next indicates the number of gc-reachable entries
+		 * in the entry part, and also indicates the index where the
+		 * next new property would be inserted.  It does *not* indicate
+		 * the number of non-NULL keys present in the object.  That
+		 * value could be counted separately but requires a pass through
+		 * the key list.
+		 */
+		duk_push_uint(ctx, (duk_uint_t) DUK_HOBJECT_GET_ENEXT(h_obj));
+		duk_push_uint(ctx, (duk_uint_t) DUK_HOBJECT_GET_ASIZE(h_obj));
+		duk_push_uint(ctx, (duk_uint_t) DUK_HOBJECT_GET_HSIZE(h_obj));
 		if (DUK_HOBJECT_IS_COMPILEDFUNCTION(h_obj)) {
-			duk_hbuffer *h_data = ((duk_hcompiledfunction *) h_obj)->data;
+			duk_hbuffer *h_data = (duk_hbuffer *) DUK_HCOMPILEDFUNCTION_GET_DATA(thr->heap, (duk_hcompiledfunction *) h_obj);
 			if (h_data) {
 				duk_push_uint(ctx, (duk_uint_t) DUK_HBUFFER_GET_SIZE(h_data));
 			} else {
@@ -17542,12 +29892,15 @@ duk_ret_t duk_bi_duktape_object_info(duk_context *ctx) {
 	case DUK_HTYPE_BUFFER: {
 		duk_hbuffer *h_buf = (duk_hbuffer *) h;
 		if (DUK_HBUFFER_HAS_DYNAMIC(h_buf)) {
-			/* XXX: when usable_size == 0, dynamic buf ptr may now be NULL, in which case
-			 * the second allocation does not exist.
-			 */
-			duk_hbuffer_dynamic *h_dyn = (duk_hbuffer_dynamic *) h;
-			duk_push_uint(ctx, (duk_uint_t) (sizeof(duk_hbuffer_dynamic)));
-			duk_push_uint(ctx, (duk_uint_t) (DUK_HBUFFER_DYNAMIC_GET_ALLOC_SIZE(h_dyn)));
+			if (DUK_HBUFFER_HAS_EXTERNAL(h_buf)) {
+				duk_push_uint(ctx, (duk_uint_t) (sizeof(duk_hbuffer_external)));
+			} else {
+				/* When alloc_size == 0 the second allocation may not
+				 * actually exist.
+				 */
+				duk_push_uint(ctx, (duk_uint_t) (sizeof(duk_hbuffer_dynamic)));
+			}
+			duk_push_uint(ctx, (duk_uint_t) (DUK_HBUFFER_GET_SIZE(h_buf)));
 		} else {
 			duk_push_uint(ctx, (duk_uint_t) (sizeof(duk_hbuffer_fixed) + DUK_HBUFFER_GET_SIZE(h_buf) + 1));
 		}
@@ -17558,7 +29911,7 @@ duk_ret_t duk_bi_duktape_object_info(duk_context *ctx) {
 
  done:
 	/* set values into ret array */
-	/* FIXME: primitive to make array from valstack slice */
+	/* XXX: primitive to make array from valstack slice */
 	n = duk_get_top(ctx);
 	for (i = 2; i < n; i++) {
 		duk_dup(ctx, i);
@@ -17568,10 +29921,9 @@ duk_ret_t duk_bi_duktape_object_info(duk_context *ctx) {
 	return 1;
 }
 
-duk_ret_t duk_bi_duktape_object_act(duk_context *ctx) {
+DUK_INTERNAL duk_ret_t duk_bi_duktape_object_act(duk_context *ctx) {
 	duk_hthread *thr = (duk_hthread *) ctx;
 	duk_activation *act;
-	duk_hobject *h_func;
 	duk_uint_fast32_t pc;
 	duk_uint_fast32_t line;
 	duk_int_t level;
@@ -17588,14 +29940,20 @@ duk_ret_t duk_bi_duktape_object_act(duk_context *ctx) {
 
 	duk_push_object(ctx);
 
-	h_func = act->func;
-	DUK_ASSERT(h_func != NULL);
-	duk_push_hobject(ctx, h_func);
+	duk_push_tval(ctx, &act->tv_func);
 
-	pc = (duk_uint_fast32_t) act->pc;
+	/* Relevant PC is just before current one because PC is
+	 * post-incremented.  This should match what error augment
+	 * code does.
+	 */
+	pc = duk_hthread_get_act_prev_pc(thr, act);
 	duk_push_uint(ctx, (duk_uint_t) pc);
 
+#if defined(DUK_USE_PC2LINE)
 	line = duk_hobject_pc2line_query(ctx, -2, pc);
+#else
+	line = 0;
+#endif
 	duk_push_uint(ctx, (duk_uint_t) line);
 
 	/* Providing access to e.g. act->lex_env would be dangerous: these
@@ -17606,14 +29964,14 @@ duk_ret_t duk_bi_duktape_object_act(duk_context *ctx) {
 
 	/* [ level obj func pc line ] */
 
-	/* FIXME: version specific array format instead? */
-	duk_def_prop_stridx_wec(ctx, -4, DUK_STRIDX_LINE_NUMBER);
-	duk_def_prop_stridx_wec(ctx, -3, DUK_STRIDX_PC);
-	duk_def_prop_stridx_wec(ctx, -2, DUK_STRIDX_LC_FUNCTION);
+	/* XXX: version specific array format instead? */
+	duk_xdef_prop_stridx_wec(ctx, -4, DUK_STRIDX_LINE_NUMBER);
+	duk_xdef_prop_stridx_wec(ctx, -3, DUK_STRIDX_PC);
+	duk_xdef_prop_stridx_wec(ctx, -2, DUK_STRIDX_LC_FUNCTION);
 	return 1;
 }
 
-duk_ret_t duk_bi_duktape_object_gc(duk_context *ctx) {
+DUK_INTERNAL duk_ret_t duk_bi_duktape_object_gc(duk_context *ctx) {
 #ifdef DUK_USE_MARK_AND_SWEEP
 	duk_hthread *thr = (duk_hthread *) ctx;
 	duk_small_uint_t flags;
@@ -17621,7 +29979,11 @@ duk_ret_t duk_bi_duktape_object_gc(duk_context *ctx) {
 
 	flags = (duk_small_uint_t) duk_get_uint(ctx, 0);
 	rc = duk_heap_mark_and_sweep(thr->heap, flags);
-	duk_push_boolean(ctx, rc);
+
+	/* XXX: Not sure what the best return value would be in the API.
+	 * Return a boolean for now.  Note that rc == 0 is success (true).
+	 */
+	duk_push_boolean(ctx, !rc);
 	return 1;
 #else
 	DUK_UNREF(ctx);
@@ -17629,7 +29991,7 @@ duk_ret_t duk_bi_duktape_object_gc(duk_context *ctx) {
 #endif
 }
 
-duk_ret_t duk_bi_duktape_object_fin(duk_context *ctx) {
+DUK_INTERNAL duk_ret_t duk_bi_duktape_object_fin(duk_context *ctx) {
 	(void) duk_require_hobject(ctx, 0);
 	if (duk_get_top(ctx) >= 2) {
 		/* Set: currently a finalizer is disabled by setting it to
@@ -17649,7 +30011,7 @@ duk_ret_t duk_bi_duktape_object_fin(duk_context *ctx) {
 	}
 }
 
-duk_ret_t duk_bi_duktape_object_enc(duk_context *ctx) {
+DUK_INTERNAL duk_ret_t duk_bi_duktape_object_enc(duk_context *ctx) {
 	duk_hthread *thr = (duk_hthread *) ctx;
 	duk_hstring *h_str;
 
@@ -17694,7 +30056,7 @@ duk_ret_t duk_bi_duktape_object_enc(duk_context *ctx) {
 	return 1;
 }
 
-duk_ret_t duk_bi_duktape_object_dec(duk_context *ctx) {
+DUK_INTERNAL duk_ret_t duk_bi_duktape_object_dec(duk_context *ctx) {
 	duk_hthread *thr = (duk_hthread *) ctx;
 	duk_hstring *h_str;
 
@@ -17738,7 +30100,7 @@ duk_ret_t duk_bi_duktape_object_dec(duk_context *ctx) {
  *  Compact an object
  */
 
-duk_ret_t duk_bi_duktape_object_compact(duk_context *ctx) {
+DUK_INTERNAL duk_ret_t duk_bi_duktape_object_compact(duk_context *ctx) {
 	DUK_ASSERT_TOP(ctx, 1);
 	duk_compact(ctx, 0);
 	return 1;  /* return the argument object */
@@ -17750,7 +30112,7 @@ duk_ret_t duk_bi_duktape_object_compact(duk_context *ctx) {
 
 /* include removed: duk_internal.h */
 
-duk_ret_t duk_bi_error_constructor_shared(duk_context *ctx) {
+DUK_INTERNAL duk_ret_t duk_bi_error_constructor_shared(duk_context *ctx) {
 	/* Behavior for constructor and non-constructor call is
 	 * the same except for augmenting the created error.  When
 	 * called as a constructor, the caller (duk_new()) will handle
@@ -17759,12 +30121,12 @@ duk_ret_t duk_bi_error_constructor_shared(duk_context *ctx) {
 	 */
 
 	duk_hthread *thr = (duk_hthread *) ctx;
-	duk_small_int_t bidx_prototype = duk_get_magic(ctx);
+	duk_small_int_t bidx_prototype = duk_get_current_magic(ctx);
 
 	/* same for both error and each subclass like TypeError */
 	duk_uint_t flags_and_class = DUK_HOBJECT_FLAG_EXTENSIBLE |
 	                             DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_ERROR);
-	
+
 	DUK_UNREF(thr);
 
 	duk_push_object_helper(ctx, flags_and_class, bidx_prototype);
@@ -17775,7 +30137,7 @@ duk_ret_t duk_bi_error_constructor_shared(duk_context *ctx) {
 	if (!duk_is_undefined(ctx, 0)) {
 		duk_to_string(ctx, 0);
 		duk_dup(ctx, 0);  /* [ message error message ] */
-		duk_def_prop_stridx(ctx, -2, DUK_STRIDX_MESSAGE, DUK_PROPDESC_FLAGS_WC);
+		duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_MESSAGE, DUK_PROPDESC_FLAGS_WC);
 	}
 
 	/* Augment the error if called as a normal function.  __FILE__ and __LINE__
@@ -17791,13 +30153,11 @@ duk_ret_t duk_bi_error_constructor_shared(duk_context *ctx) {
 	return 1;
 }
 
-duk_ret_t duk_bi_error_prototype_to_string(duk_context *ctx) {
-	/* FIXME: optimize with more direct internal access */
+DUK_INTERNAL duk_ret_t duk_bi_error_prototype_to_string(duk_context *ctx) {
+	/* XXX: optimize with more direct internal access */
 
 	duk_push_this(ctx);
-	if (!duk_is_object(ctx, -1)) {
-		goto type_error;
-	}
+	(void) duk_require_hobject_or_lfunc_coerce(ctx, -1);
 
 	/* [ ... this ] */
 
@@ -17811,7 +30171,7 @@ duk_ret_t duk_bi_error_prototype_to_string(duk_context *ctx) {
 
 	/* [ ... this name ] */
 
-	/* FIXME: Are steps 6 and 7 in E5 Section 15.11.4.4 duplicated by
+	/* XXX: Are steps 6 and 7 in E5 Section 15.11.4.4 duplicated by
 	 * accident or are they actually needed?  The first ToString()
 	 * could conceivably return 'undefined'.
 	 */
@@ -17839,12 +30199,9 @@ duk_ret_t duk_bi_error_prototype_to_string(duk_context *ctx) {
 	duk_concat(ctx, 3);
 
 	return 1;
-
- type_error:
-	return DUK_RET_TYPE_ERROR;
 }
 
-#ifdef DUK_USE_TRACEBACKS
+#if defined(DUK_USE_TRACEBACKS)
 
 /*
  *  Traceback handling
@@ -17854,10 +30211,10 @@ duk_ret_t duk_bi_error_prototype_to_string(duk_context *ctx) {
  *  only the topmost return value matters.  For instance, traceback separator
  *  and decoded strings are pushed even when looking for filename only.
  *
- *  NOTE: because user code can currently write to the tracedata array (or
- *  replace it with something other than an array), the code below must
- *  tolerate arbitrary tracedata.  It can throw errors etc, but cannot cause
- *  a segfault or memory unsafe behavior.
+ *  NOTE: although _Tracedata is an internal property, user code can currently
+ *  write to the array (or replace it with something other than an array).
+ *  The code below must tolerate arbitrary _Tracedata.  It can throw errors
+ *  etc, but cannot cause a segfault or memory unsafe behavior.
  */
 
 /* constants arbitrary, chosen for small loads */
@@ -17865,11 +30222,12 @@ duk_ret_t duk_bi_error_prototype_to_string(duk_context *ctx) {
 #define DUK__OUTPUT_TYPE_FILENAME    0
 #define DUK__OUTPUT_TYPE_LINENUMBER  1
 
-static duk_ret_t duk__traceback_getter_helper(duk_context *ctx, duk_small_int_t output_type) {
+DUK_LOCAL duk_ret_t duk__error_getter_helper(duk_context *ctx, duk_small_int_t output_type) {
 	duk_hthread *thr = (duk_hthread *) ctx;
 	duk_idx_t idx_td;
 	duk_small_int_t i;  /* traceback depth fits into 16 bits */
 	duk_small_int_t t;  /* stack type fits into 16 bits */
+	duk_small_int_t count_func = 0;  /* traceback depth ensures fits into 16 bits */
 	const char *str_tailcalled = " tailcalled";
 	const char *str_strict = " strict";
 	const char *str_construct = " construct";
@@ -17880,16 +30238,15 @@ static duk_ret_t duk__traceback_getter_helper(duk_context *ctx, duk_small_int_t
 	DUK_ASSERT_TOP(ctx, 0);  /* fixed arg count */
 
 	duk_push_this(ctx);
-	duk_get_prop_stridx(ctx, -1, DUK_STRIDX_TRACEDATA);
+	duk_get_prop_stridx(ctx, -1, DUK_STRIDX_INT_TRACEDATA);
 	idx_td = duk_get_top_index(ctx);
 
 	duk_push_hstring_stridx(ctx, DUK_STRIDX_NEWLINE_TAB);
 	duk_push_this(ctx);
-	duk_to_string(ctx, -1);
 
-	/* [ ... this tracedata sep ToString(this) ] */
+	/* [ ... this tracedata sep this ] */
 
-	/* FIXME: skip null filename? */
+	/* XXX: skip null filename? */
 
 	if (duk_check_type(ctx, idx_td, DUK_TYPE_OBJECT)) {
 		/* Current tracedata contains 2 entries per callstack entry. */
@@ -17911,15 +30268,16 @@ static duk_ret_t duk__traceback_getter_helper(duk_context *ctx, duk_small_int_t
 			flags = (duk_int_t) DUK_FLOOR(d / DUK_DOUBLE_2TO32);
 			t = (duk_small_int_t) duk_get_type(ctx, -2);
 
-			if (t == DUK_TYPE_OBJECT) {
+			if (t == DUK_TYPE_OBJECT || t == DUK_TYPE_LIGHTFUNC) {
 				/*
-				 *  Ecmascript/native function call
+				 *  Ecmascript/native function call or lightfunc call
 				 */
 
+				count_func++;
+
 				/* [ ... v1(func) v2(pc+flags) ] */
 
-				h_func = duk_get_hobject(ctx, -2);
-				DUK_ASSERT(h_func != NULL);
+				h_func = duk_get_hobject(ctx, -2);  /* NULL for lightfunc */
 
 				duk_get_prop_stridx(ctx, -2, DUK_STRIDX_NAME);
 				duk_get_prop_stridx(ctx, -3, DUK_STRIDX_FILE_NAME);
@@ -17932,11 +30290,16 @@ static duk_ret_t duk__traceback_getter_helper(duk_context *ctx, duk_small_int_t
 
 				/* [ ... v1 v2 name filename ] */
 
-				if (output_type == DUK__OUTPUT_TYPE_FILENAME) {
-					return 1;
-				} else if (output_type == DUK__OUTPUT_TYPE_LINENUMBER) {
-					duk_push_int(ctx, line);
-					return 1;
+				/* When looking for .fileName/.lineNumber, blame first
+				 * function which has a .fileName.
+				 */
+				if (duk_is_string(ctx, -1)) {
+					if (output_type == DUK__OUTPUT_TYPE_FILENAME) {
+						return 1;
+					} else if (output_type == DUK__OUTPUT_TYPE_LINENUMBER) {
+						duk_push_int(ctx, line);
+						return 1;
+					}
 				}
 
 				h_name = duk_get_hstring(ctx, -2);  /* may be NULL */
@@ -17947,7 +30310,15 @@ static duk_ret_t duk__traceback_getter_helper(duk_context *ctx, duk_small_int_t
 				DUK_ASSERT(funcname != NULL);
 				DUK_ASSERT(filename != NULL);
 
-				if (DUK_HOBJECT_HAS_NATIVEFUNCTION(h_func)) {
+				if (h_func == NULL) {
+					duk_push_sprintf(ctx, "%s light%s%s%s%s%s",
+					                 (const char *) funcname,
+					                 (const char *) ((flags & DUK_ACT_FLAG_STRICT) ? str_strict : str_empty),
+					                 (const char *) ((flags & DUK_ACT_FLAG_TAILCALLED) ? str_tailcalled : str_empty),
+					                 (const char *) ((flags & DUK_ACT_FLAG_CONSTRUCT) ? str_construct : str_empty),
+					                 (const char *) ((flags & DUK_ACT_FLAG_DIRECT_EVAL) ? str_directeval : str_empty),
+					                 (const char *) ((flags & DUK_ACT_FLAG_PREVENT_YIELD) ? str_prevyield : str_empty));
+				} else if (DUK_HOBJECT_HAS_NATIVEFUNCTION(h_func)) {
 					duk_push_sprintf(ctx, "%s %s native%s%s%s%s%s",
 					                 (const char *) funcname,
 					                 (const char *) filename,
@@ -17956,7 +30327,6 @@ static duk_ret_t duk__traceback_getter_helper(duk_context *ctx, duk_small_int_t
 					                 (const char *) ((flags & DUK_ACT_FLAG_CONSTRUCT) ? str_construct : str_empty),
 					                 (const char *) ((flags & DUK_ACT_FLAG_DIRECT_EVAL) ? str_directeval : str_empty),
 					                 (const char *) ((flags & DUK_ACT_FLAG_PREVENT_YIELD) ? str_prevyield : str_empty));
-
 				} else {
 					duk_push_sprintf(ctx, "%s %s:%ld%s%s%s%s%s",
 					                 (const char *) funcname,
@@ -17979,6 +30349,9 @@ static duk_ret_t duk__traceback_getter_helper(duk_context *ctx, duk_small_int_t
 
 				/* [ ... v1(filename) v2(line+flags) ] */
 
+				/* When looking for .fileName/.lineNumber, blame compilation
+				 * or C call site unless flagged not to do so.
+				 */
 				if (!(flags & DUK_TB_FLAG_NOBLAME_FILELINE)) {
 					if (output_type == DUK__OUTPUT_TYPE_FILENAME) {
 						duk_pop(ctx);
@@ -18000,7 +30373,7 @@ static duk_ret_t duk__traceback_getter_helper(duk_context *ctx, duk_small_int_t
 			}
 		}
 
-		if (i >= DUK_USE_TRACEBACK_DEPTH * 2) {
+		if (count_func >= DUK_USE_TRACEBACK_DEPTH) {
 			/* Possibly truncated; there is no explicit truncation
 			 * marker so this is the best we can do.
 			 */
@@ -18009,30 +30382,34 @@ static duk_ret_t duk__traceback_getter_helper(duk_context *ctx, duk_small_int_t
 		}
 	}
 
-	/* [ ... this tracedata sep ToString(this) str1 ... strN ] */
+	/* [ ... this tracedata sep this str1 ... strN ] */
 
 	if (output_type != DUK__OUTPUT_TYPE_TRACEBACK) {
 		return 0;
 	} else {
+		/* The 'this' after 'sep' will get ToString() coerced by
+		 * duk_join() automatically.  We don't want to do that
+		 * coercion when providing .fileName or .lineNumber (GH-254).
+		 */
 		duk_join(ctx, duk_get_top(ctx) - (idx_td + 2) /*count, not including sep*/);
 		return 1;
 	}
 }
 
-/* FIXME: output type could be encoded into native function 'magic' value to
- * save space.
+/* XXX: Output type could be encoded into native function 'magic' value to
+ * save space.  For setters the stridx could be encoded into 'magic'.
  */
 
-duk_ret_t duk_bi_error_prototype_stack_getter(duk_context *ctx) {
-	return duk__traceback_getter_helper(ctx, DUK__OUTPUT_TYPE_TRACEBACK);
+DUK_INTERNAL duk_ret_t duk_bi_error_prototype_stack_getter(duk_context *ctx) {
+	return duk__error_getter_helper(ctx, DUK__OUTPUT_TYPE_TRACEBACK);
 }
 
-duk_ret_t duk_bi_error_prototype_filename_getter(duk_context *ctx) {
-	return duk__traceback_getter_helper(ctx, DUK__OUTPUT_TYPE_FILENAME);
+DUK_INTERNAL duk_ret_t duk_bi_error_prototype_filename_getter(duk_context *ctx) {
+	return duk__error_getter_helper(ctx, DUK__OUTPUT_TYPE_FILENAME);
 }
 
-duk_ret_t duk_bi_error_prototype_linenumber_getter(duk_context *ctx) {
-	return duk__traceback_getter_helper(ctx, DUK__OUTPUT_TYPE_LINENUMBER);
+DUK_INTERNAL duk_ret_t duk_bi_error_prototype_linenumber_getter(duk_context *ctx) {
+	return duk__error_getter_helper(ctx, DUK__OUTPUT_TYPE_LINENUMBER);
 }
 
 #undef DUK__OUTPUT_TYPE_TRACEBACK
@@ -18053,33 +30430,62 @@ duk_ret_t duk_bi_error_prototype_linenumber_getter(duk_context *ctx) {
  *  of the error so this makes sense.
  */
 
-duk_ret_t duk_bi_error_prototype_stack_getter(duk_context *ctx) {
-	/* FIXME: remove this native function and map 'stack' accessor
+DUK_INTERNAL duk_ret_t duk_bi_error_prototype_stack_getter(duk_context *ctx) {
+	/* XXX: remove this native function and map 'stack' accessor
 	 * to the toString() implementation directly.
 	 */
 	return duk_bi_error_prototype_to_string(ctx);
 }
 
-duk_ret_t duk_bi_error_prototype_filename_getter(duk_context *ctx) {
+DUK_INTERNAL duk_ret_t duk_bi_error_prototype_filename_getter(duk_context *ctx) {
 	DUK_UNREF(ctx);
 	return 0;
 }
 
-duk_ret_t duk_bi_error_prototype_linenumber_getter(duk_context *ctx) {
+DUK_INTERNAL duk_ret_t duk_bi_error_prototype_linenumber_getter(duk_context *ctx) {
 	DUK_UNREF(ctx);
 	return 0;
 }
 
 #endif  /* DUK_USE_TRACEBACKS */
 
-duk_ret_t duk_bi_error_prototype_nop_setter(duk_context *ctx) {
-	/* Attempt to write 'stack', 'fileName', 'lineNumber' is a silent no-op.
-	 * User can use Object.defineProperty() to override this behavior.
+DUK_LOCAL duk_ret_t duk__error_setter_helper(duk_context *ctx, duk_small_uint_t stridx_key) {
+	/* Attempt to write 'stack', 'fileName', 'lineNumber' works as if
+	 * user code called Object.defineProperty() to create an overriding
+	 * own property.  This allows user code to overwrite .fileName etc
+	 * intuitively as e.g. "err.fileName = 'dummy'" as one might expect.
+	 * See https://github.com/svaarala/duktape/issues/387.
 	 */
-	DUK_ASSERT_TOP(ctx, 1);  /* fixed arg count */
-	DUK_UNREF(ctx);
+
+	DUK_ASSERT_TOP(ctx, 1);  /* fixed arg count: value */
+
+	duk_push_this(ctx);
+	duk_push_hstring_stridx(ctx, (duk_small_int_t) stridx_key);
+	duk_dup(ctx, 0);
+
+	/* [ ... obj key value ] */
+
+	DUK_DD(DUK_DDPRINT("error setter: %!T %!T %!T",
+	                   duk_get_tval(ctx, -3), duk_get_tval(ctx, -2), duk_get_tval(ctx, -1)));
+
+	duk_def_prop(ctx, -3, DUK_DEFPROP_HAVE_VALUE |
+	                      DUK_DEFPROP_HAVE_WRITABLE | DUK_DEFPROP_WRITABLE |
+	                      DUK_DEFPROP_HAVE_ENUMERABLE | /*not enumerable*/
+	                      DUK_DEFPROP_HAVE_CONFIGURABLE | DUK_DEFPROP_CONFIGURABLE);
 	return 0;
 }
+
+DUK_INTERNAL duk_ret_t duk_bi_error_prototype_stack_setter(duk_context *ctx) {
+	return duk__error_setter_helper(ctx, DUK_STRIDX_STACK);
+}
+
+DUK_INTERNAL duk_ret_t duk_bi_error_prototype_filename_setter(duk_context *ctx) {
+	return duk__error_setter_helper(ctx, DUK_STRIDX_FILE_NAME);
+}
+
+DUK_INTERNAL duk_ret_t duk_bi_error_prototype_linenumber_setter(duk_context *ctx) {
+	return duk__error_setter_helper(ctx, DUK_STRIDX_LINE_NUMBER);
+}
 #line 1 "duk_bi_function.c"
 /*
  *  Function built-ins
@@ -18087,10 +30493,7 @@ duk_ret_t duk_bi_error_prototype_nop_setter(duk_context *ctx) {
 
 /* include removed: duk_internal.h */
 
-/* FIXME: shared string */
-const char *duk__str_anon = "anon";
-
-duk_ret_t duk_bi_function_constructor(duk_context *ctx) {
+DUK_INTERNAL duk_ret_t duk_bi_function_constructor(duk_context *ctx) {
 	duk_hthread *thr = (duk_hthread *) ctx;
 	duk_hstring *h_sourcecode;
 	duk_idx_t nargs;
@@ -18124,7 +30527,7 @@ duk_ret_t duk_bi_function_constructor(duk_context *ctx) {
 
 	DUK_ASSERT_TOP(ctx, 2);
 
-	/* FIXME: this placeholder is not always correct, but use for now.
+	/* XXX: this placeholder is not always correct, but use for now.
 	 * It will fail in corner cases; see test-dev-func-cons-args.js.
 	 */
 	duk_push_string(ctx, "function(");
@@ -18141,7 +30544,7 @@ duk_ret_t duk_bi_function_constructor(duk_context *ctx) {
 	/* strictness is not inherited, intentional */
 	comp_flags = DUK_JS_COMPILE_FLAG_FUNCEXPR;
 
-	duk_push_hstring_stridx(ctx, DUK_STRIDX_COMPILE);  /* XXX: copy from caller? */  /* FIXME: ignored now */
+	duk_push_hstring_stridx(ctx, DUK_STRIDX_COMPILE);  /* XXX: copy from caller? */  /* XXX: ignored now */
 	h_sourcecode = duk_require_hstring(ctx, -2);
 	duk_js_compile(thr,
 	               (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_sourcecode),
@@ -18167,13 +30570,13 @@ duk_ret_t duk_bi_function_constructor(duk_context *ctx) {
 	return 1;
 }
 
-duk_ret_t duk_bi_function_prototype(duk_context *ctx) {
+DUK_INTERNAL duk_ret_t duk_bi_function_prototype(duk_context *ctx) {
 	/* ignore arguments, return undefined (E5 Section 15.3.4) */
 	DUK_UNREF(ctx);
 	return 0;
 }
 
-duk_ret_t duk_bi_function_prototype_to_string(duk_context *ctx) {
+DUK_INTERNAL duk_ret_t duk_bi_function_prototype_to_string(duk_context *ctx) {
 	duk_tval *tv;
 
 	/*
@@ -18193,16 +30596,16 @@ duk_ret_t duk_bi_function_prototype_to_string(duk_context *ctx) {
 	 */
 
 
-	/* FIXME: faster internal way to get this */
+	/* XXX: faster internal way to get this */
 	duk_push_this(ctx);
 	tv = duk_get_tval(ctx, -1);
 	DUK_ASSERT(tv != NULL);
 
 	if (DUK_TVAL_IS_OBJECT(tv)) {
 		duk_hobject *obj = DUK_TVAL_GET_OBJECT(tv);
-		const char *func_name = duk__str_anon;
+		const char *func_name = DUK_STR_ANON;
 
-		/* FIXME: rework, it would be nice to avoid C formatting functions to
+		/* XXX: rework, it would be nice to avoid C formatting functions to
 		 * ensure there are no Unicode issues.
 		 */
 
@@ -18212,20 +30615,22 @@ duk_ret_t duk_bi_function_prototype_to_string(duk_context *ctx) {
 			DUK_ASSERT(func_name != NULL);
 
 			if (func_name[0] == (char) 0) {
-				func_name = duk__str_anon;
+				func_name = DUK_STR_ANON;
 			}
 		}
 
 		if (DUK_HOBJECT_HAS_COMPILEDFUNCTION(obj)) {
 			/* XXX: actual source, if available */
-			duk_push_sprintf(ctx, "function %s() {/* source code */}", (const char *) func_name);
+			duk_push_sprintf(ctx, "function %s() {/* ecmascript */}", (const char *) func_name);
 		} else if (DUK_HOBJECT_HAS_NATIVEFUNCTION(obj)) {
-			duk_push_sprintf(ctx, "function %s() {/* native code */}", (const char *) func_name);
+			duk_push_sprintf(ctx, "function %s() {/* native */}", (const char *) func_name);
 		} else if (DUK_HOBJECT_HAS_BOUND(obj)) {
 			duk_push_sprintf(ctx, "function %s() {/* bound */}", (const char *) func_name);
 		} else {
 			goto type_error;
 		}
+	} else if (DUK_TVAL_IS_LIGHTFUNC(tv)) {
+		duk_push_lightfunc_tostring(ctx, tv);
 	} else {
 		goto type_error;
 	}
@@ -18236,7 +30641,7 @@ duk_ret_t duk_bi_function_prototype_to_string(duk_context *ctx) {
 	return DUK_RET_TYPE_ERROR;
 }
 
-duk_ret_t duk_bi_function_prototype_apply(duk_context *ctx) {
+DUK_INTERNAL duk_ret_t duk_bi_function_prototype_apply(duk_context *ctx) {
 	duk_idx_t len;
 	duk_idx_t i;
 
@@ -18265,7 +30670,7 @@ duk_ret_t duk_bi_function_prototype_apply(duk_context *ctx) {
 	} else {
 		DUK_DDD(DUK_DDDPRINT("argArray is an object"));
 
-		/* FIXME: make this an internal helper */
+		/* XXX: make this an internal helper */
 		duk_get_prop_stridx(ctx, 2, DUK_STRIDX_LENGTH);
 		len = (duk_idx_t) duk_to_uint32(ctx, -1);  /* ToUint32() coercion required */
 		duk_pop(ctx);
@@ -18281,7 +30686,7 @@ duk_ret_t duk_bi_function_prototype_apply(duk_context *ctx) {
 	DUK_ASSERT_TOP(ctx, 2 + len);
 
 	/* [ func thisArg arg1 ... argN ] */
-	
+
 	DUK_DDD(DUK_DDDPRINT("apply, func=%!iT, thisArg=%!iT, len=%ld",
 	                     (duk_tval *) duk_get_tval(ctx, 0),
 	                     (duk_tval *) duk_get_tval(ctx, 1),
@@ -18293,7 +30698,7 @@ duk_ret_t duk_bi_function_prototype_apply(duk_context *ctx) {
 	return DUK_RET_TYPE_ERROR;
 }
 
-duk_ret_t duk_bi_function_prototype_call(duk_context *ctx) {
+DUK_INTERNAL duk_ret_t duk_bi_function_prototype_call(duk_context *ctx) {
 	duk_idx_t nargs;
 
 	/* Step 1 is not necessary because duk_call_method() will take
@@ -18320,17 +30725,18 @@ duk_ret_t duk_bi_function_prototype_call(duk_context *ctx) {
 	                     (duk_tval *) duk_get_tval(ctx, 1),
 	                     (long) (nargs - 1),
 	                     (long) duk_get_top(ctx)));
-	duk_call_method(ctx, nargs - 1);	
+	duk_call_method(ctx, nargs - 1);
 	return 1;
 }
 
-/* FIXME: the implementation now assumes "chained" bound functions,
+/* XXX: the implementation now assumes "chained" bound functions,
  * whereas "collapsed" bound functions (where there is ever only
  * one bound function which directly points to a non-bound, final
  * function) would require a "collapsing" implementation which
  * merges argument lists etc here.
  */
-duk_ret_t duk_bi_function_prototype_bind(duk_context *ctx) {
+DUK_INTERNAL duk_ret_t duk_bi_function_prototype_bind(duk_context *ctx) {
+	duk_hobject *h_bound;
 	duk_hobject *h_target;
 	duk_idx_t nargs;
 	duk_idx_t i;
@@ -18359,15 +30765,15 @@ duk_ret_t duk_bi_function_prototype_bind(duk_context *ctx) {
 	                       DUK_HOBJECT_FLAG_CONSTRUCTABLE |
 	                       DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_FUNCTION),
 	                       DUK_BIDX_FUNCTION_PROTOTYPE);
-
-	/* FIXME: check hobject flags (e.g. strict) */
+	h_bound = duk_get_hobject(ctx, -1);
+	DUK_ASSERT(h_bound != NULL);
 
 	/* [ thisArg arg1 ... argN func boundFunc ] */
 	duk_dup(ctx, -2);  /* func */
-	duk_def_prop_stridx(ctx, -2, DUK_STRIDX_INT_TARGET, DUK_PROPDESC_FLAGS_NONE);
+	duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_INT_TARGET, DUK_PROPDESC_FLAGS_NONE);
 
 	duk_dup(ctx, 0);   /* thisArg */
-	duk_def_prop_stridx(ctx, -2, DUK_STRIDX_INT_THIS, DUK_PROPDESC_FLAGS_NONE);
+	duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_INT_THIS, DUK_PROPDESC_FLAGS_NONE);
 
 	duk_push_array(ctx);
 
@@ -18377,14 +30783,15 @@ duk_ret_t duk_bi_function_prototype_bind(duk_context *ctx) {
 		duk_dup(ctx, 1 + i);
 		duk_put_prop_index(ctx, -2, i);
 	}
-	duk_def_prop_stridx(ctx, -2, DUK_STRIDX_INT_ARGS, DUK_PROPDESC_FLAGS_NONE);
+	duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_INT_ARGS, DUK_PROPDESC_FLAGS_NONE);
 
 	/* [ thisArg arg1 ... argN func boundFunc ] */
 
 	/* bound function 'length' property is interesting */
 	h_target = duk_get_hobject(ctx, -2);
-	DUK_ASSERT(h_target != NULL);
-	if (DUK_HOBJECT_GET_CLASS_NUMBER(h_target) == DUK_HOBJECT_CLASS_FUNCTION) {
+	if (h_target == NULL ||  /* lightfunc */
+	    DUK_HOBJECT_GET_CLASS_NUMBER(h_target) == DUK_HOBJECT_CLASS_FUNCTION) {
+		/* For lightfuncs, simply read the virtual property. */
 		duk_int_t tmp;
 		duk_get_prop_stridx(ctx, -2, DUK_STRIDX_LENGTH);
 		tmp = duk_to_int(ctx, -1) - (nargs - 1);  /* step 15.a */
@@ -18393,19 +30800,30 @@ duk_ret_t duk_bi_function_prototype_bind(duk_context *ctx) {
 	} else {
 		duk_push_int(ctx, 0);
 	}
-	duk_def_prop_stridx(ctx, -2, DUK_STRIDX_LENGTH, DUK_PROPDESC_FLAGS_NONE);  /* attrs in E5 Section 15.3.5.1 */
+	duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_LENGTH, DUK_PROPDESC_FLAGS_NONE);  /* attrs in E5 Section 15.3.5.1 */
 
 	/* caller and arguments must use the same thrower, [[ThrowTypeError]] */
-	duk_def_prop_stridx_thrower(ctx, -1, DUK_STRIDX_CALLER, DUK_PROPDESC_FLAGS_NONE);
-	duk_def_prop_stridx_thrower(ctx, -1, DUK_STRIDX_LC_ARGUMENTS, DUK_PROPDESC_FLAGS_NONE);
+	duk_xdef_prop_stridx_thrower(ctx, -1, DUK_STRIDX_CALLER, DUK_PROPDESC_FLAGS_NONE);
+	duk_xdef_prop_stridx_thrower(ctx, -1, DUK_STRIDX_LC_ARGUMENTS, DUK_PROPDESC_FLAGS_NONE);
 
 	/* these non-standard properties are copied for convenience */
 	/* XXX: 'copy properties' API call? */
 	duk_get_prop_stridx(ctx, -2, DUK_STRIDX_NAME);
-	duk_def_prop_stridx(ctx, -2, DUK_STRIDX_NAME, DUK_PROPDESC_FLAGS_WC);
+	duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_NAME, DUK_PROPDESC_FLAGS_WC);
 	duk_get_prop_stridx(ctx, -2, DUK_STRIDX_FILE_NAME);
-	duk_def_prop_stridx(ctx, -2, DUK_STRIDX_FILE_NAME, DUK_PROPDESC_FLAGS_WC);
+	duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_FILE_NAME, DUK_PROPDESC_FLAGS_WC);
 
+	/* The 'strict' flag is copied to get the special [[Get]] of E5.1
+	 * Section 15.3.5.4 to apply when a 'caller' value is a strict bound
+	 * function.  Not sure if this is correct, because the specification
+	 * is a bit ambiguous on this point but it would make sense.
+	 */
+	if (h_target == NULL) {
+		/* Lightfuncs are always strict. */
+		DUK_HOBJECT_SET_STRICT(h_bound);
+	} else if (DUK_HOBJECT_HAS_STRICT(h_target)) {
+		DUK_HOBJECT_SET_STRICT(h_bound);
+	}
 	DUK_DDD(DUK_DDDPRINT("created bound function: %!iT", (duk_tval *) duk_get_tval(ctx, -1)));
 
 	return 1;
@@ -18424,6 +30842,11 @@ duk_ret_t duk_bi_function_prototype_bind(duk_context *ctx) {
  *  Encoding/decoding helpers
  */
 
+/* XXX: Could add fast path (for each transform callback) with direct byte
+ * lookups (no shifting) and no explicit check for x < 0x80 before table
+ * lookup.
+ */
+
 /* Macros for creating and checking bitmasks for character encoding.
  * Bit number is a bit counterintuitive, but minimizes code size.
  */
@@ -18434,7 +30857,7 @@ duk_ret_t duk_bi_function_prototype_bind(duk_context *ctx) {
 #define DUK__CHECK_BITMASK(table,cp)  ((table)[(cp) >> 3] & (1 << ((cp) & 0x07)))
 
 /* E5.1 Section 15.1.3.3: uriReserved + uriUnescaped + '#' */
-static duk_uint8_t duk__encode_uriunescaped_table[16] = {
+DUK_LOCAL const duk_uint8_t duk__encode_uriunescaped_table[16] = {
 	DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0),  /* 0x00-0x0f */
 	DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0),  /* 0x10-0x1f */
 	DUK__MKBITS(0, 1, 0, 1, 1, 0, 1, 1), DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1),  /* 0x20-0x2f */
@@ -18446,7 +30869,7 @@ static duk_uint8_t duk__encode_uriunescaped_table[16] = {
 };
 
 /* E5.1 Section 15.1.3.4: uriUnescaped */
-static duk_uint8_t duk__encode_uricomponent_unescaped_table[16] = {
+DUK_LOCAL const duk_uint8_t duk__encode_uricomponent_unescaped_table[16] = {
 	DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0),  /* 0x00-0x0f */
 	DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0),  /* 0x10-0x1f */
 	DUK__MKBITS(0, 1, 0, 0, 0, 0, 0, 1), DUK__MKBITS(1, 1, 1, 0, 0, 1, 1, 0),  /* 0x20-0x2f */
@@ -18458,7 +30881,7 @@ static duk_uint8_t duk__encode_uricomponent_unescaped_table[16] = {
 };
 
 /* E5.1 Section 15.1.3.1: uriReserved + '#' */
-static duk_uint8_t duk__decode_uri_reserved_table[16] = {
+DUK_LOCAL const duk_uint8_t duk__decode_uri_reserved_table[16] = {
 	DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0),  /* 0x00-0x0f */
 	DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0),  /* 0x10-0x1f */
 	DUK__MKBITS(0, 0, 0, 1, 1, 0, 1, 0), DUK__MKBITS(0, 0, 0, 1, 1, 0, 0, 1),  /* 0x20-0x2f */
@@ -18470,7 +30893,7 @@ static duk_uint8_t duk__decode_uri_reserved_table[16] = {
 };
 
 /* E5.1 Section 15.1.3.2: empty */
-static duk_uint8_t duk__decode_uri_component_reserved_table[16] = {
+DUK_LOCAL const duk_uint8_t duk__decode_uri_component_reserved_table[16] = {
 	DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0),  /* 0x00-0x0f */
 	DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0),  /* 0x10-0x1f */
 	DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0),  /* 0x20-0x2f */
@@ -18483,7 +30906,7 @@ static duk_uint8_t duk__decode_uri_component_reserved_table[16] = {
 
 #ifdef DUK_USE_SECTION_B
 /* E5.1 Section B.2.2, step 7. */
-static duk_uint8_t duk__escape_unescaped_table[16] = {
+DUK_LOCAL const duk_uint8_t duk__escape_unescaped_table[16] = {
 	DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0),  /* 0x00-0x0f */
 	DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0),  /* 0x10-0x1f */
 	DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 1, 1, 0, 1, 1, 1),  /* 0x20-0x2f */
@@ -18495,19 +30918,21 @@ static duk_uint8_t duk__escape_unescaped_table[16] = {
 };
 #endif  /* DUK_USE_SECTION_B */
 
+#undef DUK__MKBITS
+
 typedef struct {
 	duk_hthread *thr;
 	duk_hstring *h_str;
-	duk_hbuffer_dynamic *h_buf;
-	duk_uint8_t *p;
-	duk_uint8_t *p_start;
-	duk_uint8_t *p_end;
+	duk_bufwriter_ctx bw;
+	const duk_uint8_t *p;
+	const duk_uint8_t *p_start;
+	const duk_uint8_t *p_end;
 } duk__transform_context;
 
-typedef void (*duk__transform_callback)(duk__transform_context *tfm_ctx, void *udata, duk_codepoint_t cp);
+typedef void (*duk__transform_callback)(duk__transform_context *tfm_ctx, const void *udata, duk_codepoint_t cp);
 
-/* FIXME: refactor and share with other code */
-static duk_small_int_t duk__decode_hex_escape(duk_uint8_t *p, duk_small_int_t n) {
+/* XXX: refactor and share with other code */
+DUK_LOCAL duk_small_int_t duk__decode_hex_escape(const duk_uint8_t *p, duk_small_int_t n) {
 	duk_small_int_t ch;
 	duk_small_int_t t = 0;
 
@@ -18524,7 +30949,7 @@ static duk_small_int_t duk__decode_hex_escape(duk_uint8_t *p, duk_small_int_t n)
 	return t;
 }
 
-static int duk__transform_helper(duk_context *ctx, duk__transform_callback callback, void *udata) {
+DUK_LOCAL int duk__transform_helper(duk_context *ctx, duk__transform_callback callback, const void *udata) {
 	duk_hthread *thr = (duk_hthread *) ctx;
 	duk__transform_context tfm_ctx_alloc;
 	duk__transform_context *tfm_ctx = &tfm_ctx_alloc;
@@ -18535,10 +30960,7 @@ static int duk__transform_helper(duk_context *ctx, duk__transform_callback callb
 	tfm_ctx->h_str = duk_to_hstring(ctx, 0);
 	DUK_ASSERT(tfm_ctx->h_str != NULL);
 
-	(void) duk_push_dynamic_buffer(ctx, 0);
-	tfm_ctx->h_buf = (duk_hbuffer_dynamic *) duk_get_hbuffer(ctx, -1);
-	DUK_ASSERT(tfm_ctx->h_buf != NULL);
-	DUK_ASSERT(DUK_HBUFFER_HAS_DYNAMIC(tfm_ctx->h_buf));
+	DUK_BW_INIT_PUSHBUF(thr, &tfm_ctx->bw, DUK_HSTRING_GET_BYTELEN(tfm_ctx->h_str));  /* initial size guess */
 
 	tfm_ctx->p_start = DUK_HSTRING_GET_DATA(tfm_ctx->h_str);
 	tfm_ctx->p_end = tfm_ctx->p_start + DUK_HSTRING_GET_BYTELEN(tfm_ctx->h_str);
@@ -18549,22 +30971,29 @@ static int duk__transform_helper(duk_context *ctx, duk__transform_callback callb
 		callback(tfm_ctx, udata, cp);
 	}
 
+	DUK_BW_COMPACT(thr, &tfm_ctx->bw);
+
 	duk_to_string(ctx, -1);
 	return 1;
 }
 
-static void duk__transform_callback_encode_uri(duk__transform_context *tfm_ctx, void *udata, duk_codepoint_t cp) {
+DUK_LOCAL void duk__transform_callback_encode_uri(duk__transform_context *tfm_ctx, const void *udata, duk_codepoint_t cp) {
 	duk_uint8_t xutf8_buf[DUK_UNICODE_MAX_XUTF8_LENGTH];
-	duk_uint8_t buf[3];
 	duk_small_int_t len;
 	duk_codepoint_t cp1, cp2;
 	duk_small_int_t i, t;
-	duk_uint8_t *unescaped_table = (duk_uint8_t *) udata;
+	const duk_uint8_t *unescaped_table = (const duk_uint8_t *) udata;
+
+	/* UTF-8 encoded bytes escaped as %xx%xx%xx... -> 3 * nbytes.
+	 * Codepoint range is restricted so this is a slightly too large
+	 * but doesn't matter.
+	 */
+	DUK_BW_ENSURE(tfm_ctx->thr, &tfm_ctx->bw, 3 * DUK_UNICODE_MAX_XUTF8_LENGTH);
 
 	if (cp < 0) {
 		goto uri_error;
 	} else if ((cp < 0x80L) && DUK__CHECK_BITMASK(unescaped_table, cp)) {
-		duk_hbuffer_append_byte(tfm_ctx->thr, tfm_ctx->h_buf, (duk_uint8_t) cp);
+		DUK_BW_WRITE_RAW_U8(tfm_ctx->thr, &tfm_ctx->bw, (duk_uint8_t) cp);
 		return;
 	} else if (cp >= 0xdc00L && cp <= 0xdfffL) {
 		goto uri_error;
@@ -18588,34 +31017,45 @@ static void duk__transform_callback_encode_uri(duk__transform_context *tfm_ctx,
 		goto uri_error;
 	} else {
 		/* Non-BMP characters within valid UTF-8 range: encode as is.
-		 * They'll decode back into surrogate pairs.
+		 * They'll decode back into surrogate pairs if the escaped
+		 * output is decoded.
 		 */
 		;
 	}
 
 	len = duk_unicode_encode_xutf8((duk_ucodepoint_t) cp, xutf8_buf);
-	buf[0] = (duk_uint8_t) '%';
 	for (i = 0; i < len; i++) {
 		t = (int) xutf8_buf[i];
-		buf[1] = (duk_uint8_t) duk_uc_nybbles[t >> 4];
-		buf[2] = (duk_uint8_t) duk_uc_nybbles[t & 0x0f];
-		duk_hbuffer_append_bytes(tfm_ctx->thr, tfm_ctx->h_buf, buf, 3);
+		DUK_BW_WRITE_RAW_U8_3(tfm_ctx->thr,
+		                      &tfm_ctx->bw,
+		                      DUK_ASC_PERCENT,
+		                      (duk_uint8_t) duk_uc_nybbles[t >> 4],
+                                      (duk_uint8_t) duk_uc_nybbles[t & 0x0f]);
 	}
+
 	return;
 
  uri_error:
 	DUK_ERROR(tfm_ctx->thr, DUK_ERR_URI_ERROR, "invalid input");
 }
 
-static void duk__transform_callback_decode_uri(duk__transform_context *tfm_ctx, void *udata, duk_codepoint_t cp) {
-	duk_uint8_t *reserved_table = (duk_uint8_t *) udata;
+DUK_LOCAL void duk__transform_callback_decode_uri(duk__transform_context *tfm_ctx, const void *udata, duk_codepoint_t cp) {
+	const duk_uint8_t *reserved_table = (const duk_uint8_t *) udata;
 	duk_small_uint_t utf8_blen;
 	duk_codepoint_t min_cp;
 	duk_small_int_t t;  /* must be signed */
 	duk_small_uint_t i;
 
+	/* Maximum write size: XUTF8 path writes max DUK_UNICODE_MAX_XUTF8_LENGTH,
+	 * percent escape path writes max two times CESU-8 encoded BMP length.
+	 */
+	DUK_BW_ENSURE(tfm_ctx->thr,
+	              &tfm_ctx->bw,
+	              (DUK_UNICODE_MAX_XUTF8_LENGTH >= 2 * DUK_UNICODE_MAX_CESU8_BMP_LENGTH ?
+	              DUK_UNICODE_MAX_XUTF8_LENGTH : DUK_UNICODE_MAX_CESU8_BMP_LENGTH));
+
 	if (cp == (duk_codepoint_t) '%') {
-		duk_uint8_t *p = tfm_ctx->p;
+		const duk_uint8_t *p = tfm_ctx->p;
 		duk_size_t left = (duk_size_t) (tfm_ctx->p_end - p);  /* bytes left */
 
 		DUK_DDD(DUK_DDDPRINT("percent encoding, left=%ld", (long) left));
@@ -18634,9 +31074,13 @@ static void duk__transform_callback_decode_uri(duk__transform_context *tfm_ctx,
 			if (DUK__CHECK_BITMASK(reserved_table, t)) {
 				/* decode '%xx' to '%xx' if decoded char in reserved set */
 				DUK_ASSERT(tfm_ctx->p - 1 >= tfm_ctx->p_start);
-				duk_hbuffer_append_bytes(tfm_ctx->thr, tfm_ctx->h_buf, (duk_uint8_t *) (p - 1), 3);
+				DUK_BW_WRITE_RAW_U8_3(tfm_ctx->thr,
+				                      &tfm_ctx->bw,
+				                      DUK_ASC_PERCENT,
+				                      p[0],
+				                      p[1]);
 			} else {
-				duk_hbuffer_append_byte(tfm_ctx->thr, tfm_ctx->h_buf, (duk_uint8_t) t);
+				DUK_BW_WRITE_RAW_U8(tfm_ctx->thr, &tfm_ctx->bw, (duk_uint8_t) t);
 			}
 			tfm_ctx->p += 2;
 			return;
@@ -18718,13 +31162,14 @@ static void duk__transform_callback_decode_uri(duk__transform_context *tfm_ctx,
 		if (cp >= 0x10000L) {
 			cp -= 0x10000L;
 			DUK_ASSERT(cp < 0x100000L);
-			duk_hbuffer_append_xutf8(tfm_ctx->thr, tfm_ctx->h_buf, (duk_ucodepoint_t) ((cp >> 10) + 0xd800L));
-			duk_hbuffer_append_xutf8(tfm_ctx->thr, tfm_ctx->h_buf, (duk_ucodepoint_t) ((cp & 0x03ffUL) + 0xdc00L));
+
+			DUK_BW_WRITE_RAW_XUTF8(tfm_ctx->thr, &tfm_ctx->bw, ((cp >> 10) + 0xd800L));
+			DUK_BW_WRITE_RAW_XUTF8(tfm_ctx->thr, &tfm_ctx->bw, ((cp & 0x03ffUL) + 0xdc00L));
 		} else {
-			duk_hbuffer_append_xutf8(tfm_ctx->thr, tfm_ctx->h_buf, (duk_ucodepoint_t) cp);
+			DUK_BW_WRITE_RAW_XUTF8(tfm_ctx->thr, &tfm_ctx->bw, cp);
 		}
 	} else {
-		duk_hbuffer_append_xutf8(tfm_ctx->thr, tfm_ctx->h_buf, (duk_ucodepoint_t) cp);
+		DUK_BW_WRITE_RAW_XUTF8(tfm_ctx->thr, &tfm_ctx->bw, cp);
 	}
 	return;
 
@@ -18733,30 +31178,30 @@ static void duk__transform_callback_decode_uri(duk__transform_context *tfm_ctx,
 }
 
 #ifdef DUK_USE_SECTION_B
-static void duk__transform_callback_escape(duk__transform_context *tfm_ctx, void *udata, duk_codepoint_t cp) {
-	duk_uint8_t buf[6];
-	duk_small_int_t len;
-
+DUK_LOCAL void duk__transform_callback_escape(duk__transform_context *tfm_ctx, const void *udata, duk_codepoint_t cp) {
 	DUK_UNREF(udata);
 
+	DUK_BW_ENSURE(tfm_ctx->thr, &tfm_ctx->bw, 6);
+
 	if (cp < 0) {
 		goto esc_error;
 	} else if ((cp < 0x80L) && DUK__CHECK_BITMASK(duk__escape_unescaped_table, cp)) {
-		buf[0] = (duk_uint8_t) cp;
-		len = 1;
+		DUK_BW_WRITE_RAW_U8(tfm_ctx->thr, &tfm_ctx->bw, (duk_uint8_t) cp);
 	} else if (cp < 0x100L) {
-		buf[0] = (duk_uint8_t) '%';
-		buf[1] = (duk_uint8_t) duk_uc_nybbles[cp >> 4];
-		buf[2] = (duk_uint8_t) duk_uc_nybbles[cp & 0x0f];
-		len = 3;
+		DUK_BW_WRITE_RAW_U8_3(tfm_ctx->thr,
+		                      &tfm_ctx->bw,
+		                      (duk_uint8_t) DUK_ASC_PERCENT,
+		                      (duk_uint8_t) duk_uc_nybbles[cp >> 4],
+		                      (duk_uint8_t) duk_uc_nybbles[cp & 0x0f]);
 	} else if (cp < 0x10000L) {
-		buf[0] = (duk_uint8_t) '%';
-		buf[1] = (duk_uint8_t) 'u';
-		buf[2] = (duk_uint8_t) duk_uc_nybbles[cp >> 12];
-		buf[3] = (duk_uint8_t) duk_uc_nybbles[(cp >> 8) & 0x0f];
-		buf[4] = (duk_uint8_t) duk_uc_nybbles[(cp >> 4) & 0x0f];
-		buf[5] = (duk_uint8_t) duk_uc_nybbles[cp & 0x0f];
-		len = 6;
+		DUK_BW_WRITE_RAW_U8_6(tfm_ctx->thr,
+		                      &tfm_ctx->bw,
+		                      (duk_uint8_t) DUK_ASC_PERCENT,
+		                      (duk_uint8_t) DUK_ASC_LC_U,
+		                      (duk_uint8_t) duk_uc_nybbles[cp >> 12],
+		                      (duk_uint8_t) duk_uc_nybbles[(cp >> 8) & 0x0f],
+		                      (duk_uint8_t) duk_uc_nybbles[(cp >> 4) & 0x0f],
+		                      (duk_uint8_t) duk_uc_nybbles[cp & 0x0f]);
 	} else {
 		/* Characters outside BMP cannot be escape()'d.  We could
 		 * encode them as surrogate pairs (for codepoints inside
@@ -18766,20 +31211,19 @@ static void duk__transform_callback_escape(duk__transform_context *tfm_ctx, void
 		goto esc_error;
 	}
 
-	duk_hbuffer_append_bytes(tfm_ctx->thr, tfm_ctx->h_buf, buf, len);
 	return;
 
  esc_error:
 	DUK_ERROR(tfm_ctx->thr, DUK_ERR_TYPE_ERROR, "invalid input");
 }
 
-static void duk__transform_callback_unescape(duk__transform_context *tfm_ctx, void *udata, duk_codepoint_t cp) {
+DUK_LOCAL void duk__transform_callback_unescape(duk__transform_context *tfm_ctx, const void *udata, duk_codepoint_t cp) {
 	duk_small_int_t t;
 
 	DUK_UNREF(udata);
 
 	if (cp == (duk_codepoint_t) '%') {
-		duk_uint8_t *p = tfm_ctx->p;
+		const duk_uint8_t *p = tfm_ctx->p;
 		duk_size_t left = (duk_size_t) (tfm_ctx->p_end - p);  /* bytes left */
 
 		if (left >= 5 && p[0] == 'u' &&
@@ -18793,7 +31237,7 @@ static void duk__transform_callback_unescape(duk__transform_context *tfm_ctx, vo
 		}
 	}
 
-	duk_hbuffer_append_xutf8(tfm_ctx->thr, tfm_ctx->h_buf, cp);
+	DUK_BW_WRITE_ENSURE_XUTF8(tfm_ctx->thr, &tfm_ctx->bw, cp);
 }
 #endif  /* DUK_USE_SECTION_B */
 
@@ -18808,7 +31252,7 @@ static void duk__transform_callback_unescape(duk__transform_context *tfm_ctx, vo
  *  calling activation at all which needs careful handling.
  */
 
-duk_ret_t duk_bi_global_object_eval(duk_context *ctx) {
+DUK_INTERNAL duk_ret_t duk_bi_global_object_eval(duk_context *ctx) {
 	duk_hthread *thr = (duk_hthread *) ctx;
 	duk_hstring *h;
 	duk_activation *act_caller;
@@ -18819,8 +31263,9 @@ duk_ret_t duk_bi_global_object_eval(duk_context *ctx) {
 	duk_hobject *outer_var_env;
 	duk_bool_t this_to_global = 1;
 	duk_small_uint_t comp_flags;
+	duk_int_t level = -2;
 
-	DUK_ASSERT_TOP(ctx, 1);
+	DUK_ASSERT(duk_get_top(ctx) == 1 || duk_get_top(ctx) == 2);  /* 2 when called by debugger */
 	DUK_ASSERT(thr->callstack_top >= 1);  /* at least this function exists */
 	DUK_ASSERT(((thr->callstack + thr->callstack_top - 1)->flags & DUK_ACT_FLAG_DIRECT_EVAL) == 0 || /* indirect eval */
 	           (thr->callstack_top >= 2));  /* if direct eval, calling activation must exist */
@@ -18838,15 +31283,26 @@ duk_ret_t duk_bi_global_object_eval(duk_context *ctx) {
 		return 1;  /* return arg as-is */
 	}
 
-	/* [ source ] */
+#if defined(DUK_USE_DEBUGGER_SUPPORT)
+	/* NOTE: level is used only by the debugger and should never be present
+	 * for an Ecmascript eval().
+	 */
+	DUK_ASSERT(level == -2);  /* by default, use caller's environment */
+	if (duk_get_top(ctx) >= 2 && duk_is_number(ctx, 1)) {
+		level = duk_get_int(ctx, 1);
+	}
+	DUK_ASSERT(level <= -2);  /* This is guaranteed by debugger code. */
+#endif
+
+	/* [ source ] */
 
 	comp_flags = DUK_JS_COMPILE_FLAG_EVAL;
 	act_eval = thr->callstack + thr->callstack_top - 1;    /* this function */
-	if (thr->callstack_top >= 2) {
+	if (thr->callstack_top >= (duk_size_t) -level) {
 		/* Have a calling activation, check for direct eval (otherwise
 		 * assume indirect eval.
 		 */
-		act_caller = thr->callstack + thr->callstack_top - 2;  /* caller */
+		act_caller = thr->callstack + thr->callstack_top + level;  /* caller */
 		if ((act_caller->flags & DUK_ACT_FLAG_STRICT) &&
 		    (act_eval->flags & DUK_ACT_FLAG_DIRECT_EVAL)) {
 			/* Only direct eval inherits strictness from calling code
@@ -18869,21 +31325,21 @@ duk_ret_t duk_bi_global_object_eval(duk_context *ctx) {
 	DUK_ASSERT(func != NULL);
 	DUK_ASSERT(DUK_HOBJECT_IS_COMPILEDFUNCTION((duk_hobject *) func));
 
-	/* [ source template ] */
+	/* [ source template ] */
 
 	/* E5 Section 10.4.2 */
 	DUK_ASSERT(thr->callstack_top >= 1);
 	act = thr->callstack + thr->callstack_top - 1;  /* this function */
-	if (act->flags & DUK_ACT_FLAG_DIRECT_EVAL) {	
+	if (act->flags & DUK_ACT_FLAG_DIRECT_EVAL) {
 		DUK_ASSERT(thr->callstack_top >= 2);
-		act = thr->callstack + thr->callstack_top - 2;  /* caller */
+		act = thr->callstack + thr->callstack_top + level;  /* caller */
 		if (act->lex_env == NULL) {
 			DUK_ASSERT(act->var_env == NULL);
 			DUK_DDD(DUK_DDDPRINT("delayed environment initialization"));
 
 			/* this may have side effects, so re-lookup act */
 			duk_js_init_activation_environment_records_delayed(thr, act);
-			act = thr->callstack + thr->callstack_top - 2;
+			act = thr->callstack + thr->callstack_top + level;
 		}
 		DUK_ASSERT(act->lex_env != NULL);
 		DUK_ASSERT(act->var_env != NULL);
@@ -18898,7 +31354,7 @@ duk_ret_t duk_bi_global_object_eval(duk_context *ctx) {
 			                     "var_env and lex_env to a fresh env, "
 			                     "this_binding to caller's this_binding"));
 
-			act = thr->callstack + thr->callstack_top - 2;  /* caller */
+			act = thr->callstack + thr->callstack_top + level;  /* caller */
 			act_lex_env = act->lex_env;
 			act = NULL;  /* invalidated */
 
@@ -18941,7 +31397,7 @@ duk_ret_t duk_bi_global_object_eval(duk_context *ctx) {
 
 	duk_js_push_closure(thr, func, outer_var_env, outer_lex_env);
 
-	/* [ source template closure ] */
+	/* [ source template closure ] */
 
 	if (this_to_global) {
 		DUK_ASSERT(thr->builtins[DUK_BIDX_GLOBAL] != NULL);
@@ -18949,7 +31405,7 @@ duk_ret_t duk_bi_global_object_eval(duk_context *ctx) {
 	} else {
 		duk_tval *tv;
 		DUK_ASSERT(thr->callstack_top >= 2);
-		act = thr->callstack + thr->callstack_top - 2;  /* caller */
+		act = thr->callstack + thr->callstack_top + level;  /* caller */
 		tv = thr->valstack + act->idx_bottom - 1;  /* this is just beneath bottom */
 		DUK_ASSERT(tv >= thr->valstack);
 		duk_push_tval(ctx, tv);
@@ -18960,11 +31416,11 @@ duk_ret_t duk_bi_global_object_eval(duk_context *ctx) {
 	                     (duk_heaphdr *) outer_var_env,
 	                     (duk_tval *) duk_get_tval(ctx, -1)));
 
-	/* [ source template closure this ] */
+	/* [ source template closure this ] */
 
 	duk_call_method(ctx, 0);
 
-	/* [ source template result ] */
+	/* [ source template result ] */
 
 	return 1;
 }
@@ -18973,45 +31429,40 @@ duk_ret_t duk_bi_global_object_eval(duk_context *ctx) {
  *  Parsing of ints and floats
  */
 
-duk_ret_t duk_bi_global_object_parse_int(duk_context *ctx) {
-	duk_bool_t strip_prefix;
+DUK_INTERNAL duk_ret_t duk_bi_global_object_parse_int(duk_context *ctx) {
 	duk_int32_t radix;
 	duk_small_uint_t s2n_flags;
 
 	DUK_ASSERT_TOP(ctx, 2);
 	duk_to_string(ctx, 0);
 
-	strip_prefix = 1;
 	radix = duk_to_int32(ctx, 1);
+
+	s2n_flags = DUK_S2N_FLAG_TRIM_WHITE |
+	            DUK_S2N_FLAG_ALLOW_GARBAGE |
+	            DUK_S2N_FLAG_ALLOW_PLUS |
+	            DUK_S2N_FLAG_ALLOW_MINUS |
+	            DUK_S2N_FLAG_ALLOW_LEADING_ZERO |
+	            DUK_S2N_FLAG_ALLOW_AUTO_HEX_INT;
+
+	/* Specification stripPrefix maps to DUK_S2N_FLAG_ALLOW_AUTO_HEX_INT.
+	 *
+	 * Don't autodetect octals (from leading zeroes), require user code to
+	 * provide an explicit radix 8 for parsing octal.  See write-up from Mozilla:
+	 * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/parseInt#ECMAScript_5_Removes_Octal_Interpretation
+	 */
+
 	if (radix != 0) {
 		if (radix < 2 || radix > 36) {
 			goto ret_nan;
 		}
-		/* For octal, setting strip_prefix=0 is not necessary, as zero
-		 * is tolerated anyway:
-		 *
-		 *   parseInt('123', 8) === parseInt('0123', 8)     with or without strip_prefix
-		 *   parseInt('123', 16) === parseInt('0x123', 16)  requires strip_prefix = 1
-		 */
 		if (radix != 16) {
-			strip_prefix = 0;
+			s2n_flags &= ~DUK_S2N_FLAG_ALLOW_AUTO_HEX_INT;
 		}
 	} else {
 		radix = 10;
 	}
 
-	s2n_flags = DUK_S2N_FLAG_TRIM_WHITE |
-	            DUK_S2N_FLAG_ALLOW_GARBAGE |
-	            DUK_S2N_FLAG_ALLOW_PLUS |
-	            DUK_S2N_FLAG_ALLOW_MINUS |
-	            DUK_S2N_FLAG_ALLOW_LEADING_ZERO |
-#ifdef DUK_USE_OCTAL_SUPPORT
-	            (strip_prefix ? (DUK_S2N_FLAG_ALLOW_AUTO_HEX_INT | DUK_S2N_FLAG_ALLOW_AUTO_OCT_INT) : 0)
-#else
-	            (strip_prefix ? DUK_S2N_FLAG_ALLOW_AUTO_HEX_INT : 0)
-#endif
-	            ;
-
 	duk_dup(ctx, 0);
 	duk_numconv_parse(ctx, radix, s2n_flags);
 	return 1;
@@ -19021,7 +31472,7 @@ duk_ret_t duk_bi_global_object_parse_int(duk_context *ctx) {
 	return 1;
 }
 
-duk_ret_t duk_bi_global_object_parse_float(duk_context *ctx) {
+DUK_INTERNAL duk_ret_t duk_bi_global_object_parse_float(duk_context *ctx) {
 	duk_small_uint_t s2n_flags;
 	duk_int32_t radix;
 
@@ -19050,13 +31501,13 @@ duk_ret_t duk_bi_global_object_parse_float(duk_context *ctx) {
  *  Number checkers
  */
 
-duk_ret_t duk_bi_global_object_is_nan(duk_context *ctx) {
+DUK_INTERNAL duk_ret_t duk_bi_global_object_is_nan(duk_context *ctx) {
 	duk_double_t d = duk_to_number(ctx, 0);
 	duk_push_boolean(ctx, DUK_ISNAN(d));
 	return 1;
 }
 
-duk_ret_t duk_bi_global_object_is_finite(duk_context *ctx) {
+DUK_INTERNAL duk_ret_t duk_bi_global_object_is_finite(duk_context *ctx) {
 	duk_double_t d = duk_to_number(ctx, 0);
 	duk_push_boolean(ctx, DUK_ISFINITE(d));
 	return 1;
@@ -19066,133 +31517,162 @@ duk_ret_t duk_bi_global_object_is_finite(duk_context *ctx) {
  *  URI handling
  */
 
-duk_ret_t duk_bi_global_object_decode_uri(duk_context *ctx) {
-	return duk__transform_helper(ctx, duk__transform_callback_decode_uri, (void *) duk__decode_uri_reserved_table);
+DUK_INTERNAL duk_ret_t duk_bi_global_object_decode_uri(duk_context *ctx) {
+	return duk__transform_helper(ctx, duk__transform_callback_decode_uri, (const void *) duk__decode_uri_reserved_table);
 }
 
-duk_ret_t duk_bi_global_object_decode_uri_component(duk_context *ctx) {
-	return duk__transform_helper(ctx, duk__transform_callback_decode_uri, (void *) duk__decode_uri_component_reserved_table);
+DUK_INTERNAL duk_ret_t duk_bi_global_object_decode_uri_component(duk_context *ctx) {
+	return duk__transform_helper(ctx, duk__transform_callback_decode_uri, (const void *) duk__decode_uri_component_reserved_table);
 }
 
-duk_ret_t duk_bi_global_object_encode_uri(duk_context *ctx) {
-	return duk__transform_helper(ctx, duk__transform_callback_encode_uri, (void *) duk__encode_uriunescaped_table);
+DUK_INTERNAL duk_ret_t duk_bi_global_object_encode_uri(duk_context *ctx) {
+	return duk__transform_helper(ctx, duk__transform_callback_encode_uri, (const void *) duk__encode_uriunescaped_table);
 }
 
-duk_ret_t duk_bi_global_object_encode_uri_component(duk_context *ctx) {
-	return duk__transform_helper(ctx, duk__transform_callback_encode_uri, (void *) duk__encode_uricomponent_unescaped_table);
+DUK_INTERNAL duk_ret_t duk_bi_global_object_encode_uri_component(duk_context *ctx) {
+	return duk__transform_helper(ctx, duk__transform_callback_encode_uri, (const void *) duk__encode_uricomponent_unescaped_table);
 }
 
 #ifdef DUK_USE_SECTION_B
-duk_ret_t duk_bi_global_object_escape(duk_context *ctx) {
-	return duk__transform_helper(ctx, duk__transform_callback_escape, (void *) NULL);
+DUK_INTERNAL duk_ret_t duk_bi_global_object_escape(duk_context *ctx) {
+	return duk__transform_helper(ctx, duk__transform_callback_escape, (const void *) NULL);
 }
 
-duk_ret_t duk_bi_global_object_unescape(duk_context *ctx) {
-	return duk__transform_helper(ctx, duk__transform_callback_unescape, (void *) NULL);
+DUK_INTERNAL duk_ret_t duk_bi_global_object_unescape(duk_context *ctx) {
+	return duk__transform_helper(ctx, duk__transform_callback_unescape, (const void *) NULL);
 }
 #else  /* DUK_USE_SECTION_B */
-duk_ret_t duk_bi_global_object_escape(duk_context *ctx) {
+DUK_INTERNAL duk_ret_t duk_bi_global_object_escape(duk_context *ctx) {
 	DUK_UNREF(ctx);
 	return DUK_RET_UNSUPPORTED_ERROR;
 }
 
-duk_ret_t duk_bi_global_object_unescape(duk_context *ctx) {
+DUK_INTERNAL duk_ret_t duk_bi_global_object_unescape(duk_context *ctx) {
 	DUK_UNREF(ctx);
 	return DUK_RET_UNSUPPORTED_ERROR;
 }
 #endif  /* DUK_USE_SECTION_B */
 
-#ifdef DUK_USE_BROWSER_LIKE
-#ifdef DUK_USE_FILE_IO
-static duk_ret_t duk__print_alert_helper(duk_context *ctx, duk_file *f_out) {
+#if defined(DUK_USE_BROWSER_LIKE) && (defined(DUK_USE_FILE_IO) || defined(DUK_USE_DEBUGGER_SUPPORT))
+DUK_INTERNAL duk_ret_t duk_bi_global_object_print_helper(duk_context *ctx) {
+	duk_hthread *thr = (duk_hthread *) ctx;
+	duk_int_t magic;
 	duk_idx_t nargs;
-	duk_idx_t i;
-	const char *str;
-	duk_size_t len;
-	char nl = '\n';
+	const duk_uint8_t *buf;
+	duk_size_t sz_buf;
+	const char nl = (const char) DUK_ASC_LF;
+#ifndef DUK_USE_PREFER_SIZE
+	duk_uint8_t buf_stack[256];
+#endif
+#ifdef DUK_USE_FILE_IO
+	duk_file *f_out;
+#endif
+
+	DUK_UNREF(thr);
+
+	magic = duk_get_current_magic(ctx);
+	DUK_UNREF(magic);
+
+	nargs = duk_get_top(ctx);
 
 	/* If argument count is 1 and first argument is a buffer, write the buffer
 	 * as raw data into the file without a newline; this allows exact control
 	 * over stdout/stderr without an additional entrypoint (useful for now).
+	 *
+	 * Otherwise current print/alert semantics are to ToString() coerce
+	 * arguments, join them with a single space, and append a newline.
 	 */
 
-	nargs = duk_get_top(ctx);
 	if (nargs == 1 && duk_is_buffer(ctx, 0)) {
-		const char *buf = NULL;
-		duk_size_t sz = 0;
-		buf = (const char *) duk_get_buffer(ctx, 0, &sz);
-		if (buf && sz > 0) {
-			DUK_FWRITE(buf, 1, sz, f_out);
-		}
-		goto flush;
-	}
-
-	/* XXX: What are the best semantics / specification for print()?
-	 * Now apply ToString() to arguments and join with a single space.
-	 */
-	/* XXX: ToString() coerce inplace instead? */
+		buf = (const duk_uint8_t *) duk_get_buffer(ctx, 0, &sz_buf);
+		DUK_ASSERT(buf != NULL);
+	} else if (nargs > 0) {
+#ifdef DUK_USE_PREFER_SIZE
+		/* Compact but lots of churn. */
+		duk_push_hstring_stridx(thr, DUK_STRIDX_SPACE);
+		duk_insert(ctx, 0);
+		duk_join(ctx, nargs);
+		duk_push_string(thr, "\n");
+		duk_concat(ctx, 2);
+		buf = (const duk_uint8_t *) duk_get_lstring(ctx, -1, &sz_buf);
+		DUK_ASSERT(buf != NULL);
+#else  /* DUK_USE_PREFER_SIZE */
+		/* Higher footprint, less churn. */
+		duk_idx_t i;
+		duk_size_t sz_str;
+		const duk_uint8_t *p_str;
+		duk_uint8_t *p;
 
-	if (nargs > 0) {
+		sz_buf = (duk_size_t) nargs;  /* spaces (nargs - 1) + newline */
 		for (i = 0; i < nargs; i++) {
-			if (i != 0) {
-				duk_push_hstring_stridx(ctx, DUK_STRIDX_SPACE);
-			}
-			duk_dup(ctx, i);
-			duk_to_string(ctx, -1);
+			(void) duk_to_lstring(ctx, i, &sz_str);
+			sz_buf += sz_str;
 		}
 
-		duk_concat(ctx, 2 * nargs - 1);
-
-		str = duk_get_lstring(ctx, -1, &len);
-		if (str) {
-			DUK_FWRITE(str, 1, len, f_out);
+		if (sz_buf <= sizeof(buf_stack)) {
+			p = (duk_uint8_t *) buf_stack;
+		} else {
+			p = (duk_uint8_t *) duk_push_fixed_buffer(ctx, sz_buf);
+			DUK_ASSERT(p != NULL);
 		}
+
+		buf = (const duk_uint8_t *) p;
+		for (i = 0; i < nargs; i++) {
+			p_str = (const duk_uint8_t *) duk_get_lstring(ctx, i, &sz_str);
+			DUK_ASSERT(p_str != NULL);
+			DUK_MEMCPY((void *) p, (const void *) p_str, sz_str);
+			p += sz_str;
+			*p++ = (duk_uint8_t) (i == nargs - 1 ? DUK_ASC_LF : DUK_ASC_SPACE);
+		}
+		DUK_ASSERT((const duk_uint8_t *) p == buf + sz_buf);
+#endif  /* DUK_USE_PREFER_SIZE */
+	} else {
+		buf = (const duk_uint8_t *) &nl;
+		sz_buf = 1;
 	}
 
-	DUK_FWRITE((const char *) &nl, 1, 1, f_out);
+	/* 'buf' contains the string to write, 'sz_buf' contains the length
+	 * (which may be zero).
+	 */
+	DUK_ASSERT(buf != NULL);
 
- flush:
-	DUK_FFLUSH(f_out);
-	return 0;
-}
+	if (sz_buf == 0) {
+		return 0;
+	}
 
-duk_ret_t duk_bi_global_object_print(duk_context *ctx) {
-	return duk__print_alert_helper(ctx, DUK_STDOUT);
-}
+#ifdef DUK_USE_FILE_IO
+	f_out = (magic ? DUK_STDERR : DUK_STDOUT);
+	DUK_FWRITE((const void *) buf, 1, (size_t) sz_buf, f_out);
+	DUK_FFLUSH(f_out);
+#endif
 
-duk_ret_t duk_bi_global_object_alert(duk_context *ctx) {
-	return duk__print_alert_helper(ctx, DUK_STDERR);
-}
-#else  /* DUK_USE_FILE_IO */
-/* Supported but no file I/O -> silently ignore, no error */
-duk_ret_t duk_bi_global_object_print(duk_context *ctx) {
-	DUK_UNREF(ctx);
+#if defined(DUK_USE_DEBUGGER_SUPPORT) && defined(DUK_USE_DEBUGGER_FWD_PRINTALERT)
+	if (DUK_HEAP_IS_DEBUGGER_ATTACHED(thr->heap)) {
+		duk_debug_write_notify(thr, magic ? DUK_DBG_CMD_ALERT : DUK_DBG_CMD_PRINT);
+		duk_debug_write_string(thr, (const char *) buf, sz_buf);
+		duk_debug_write_eom(thr);
+	}
+#endif
 	return 0;
 }
-
-duk_ret_t duk_bi_global_object_alert(duk_context *ctx) {
+#elif defined(DUK_USE_BROWSER_LIKE)  /* print provider */
+DUK_INTERNAL duk_ret_t duk_bi_global_object_print_helper(duk_context *ctx) {
 	DUK_UNREF(ctx);
 	return 0;
 }
-#endif  /* DUK_USE_FILE_IO */
-#else  /* DUK_USE_BROWSER_LIKE */
-duk_ret_t duk_bi_global_object_print(duk_context *ctx) {
+#else  /* print provider */
+DUK_INTERNAL duk_ret_t duk_bi_global_object_print_helper(duk_context *ctx) {
 	DUK_UNREF(ctx);
 	return DUK_RET_UNSUPPORTED_ERROR;
 }
-
-duk_ret_t duk_bi_global_object_alert(duk_context *ctx) {
-	DUK_UNREF(ctx);
-	return DUK_RET_UNSUPPORTED_ERROR;
-}
-#endif  /* DUK_USE_BROWSER_LIKE */
+#endif  /* print provider */
 
 /*
  *  CommonJS require() and modules support
  */
 
 #if defined(DUK_USE_COMMONJS_MODULES)
-static void duk__bi_global_resolve_module_id(duk_context *ctx, const char *req_id, const char *mod_id) {
+DUK_LOCAL void duk__bi_global_resolve_module_id(duk_context *ctx, const char *req_id, const char *mod_id) {
 	duk_hthread *thr = (duk_hthread *) ctx;
 	duk_size_t mod_id_len;
 	duk_size_t req_id_len;
@@ -19226,16 +31706,20 @@ static void duk__bi_global_resolve_module_id(duk_context *ctx, const char *req_i
 	 *  Set up the resolution input which is the requested ID directly
 	 *  (if absolute or no current module path) or with current module
 	 *  ID prepended (if relative and current module path exists).
+	 *
+	 *  Suppose current module is 'foo/bar' and relative path is './quux'.
+	 *  The 'bar' component must be replaced so the initial input here is
+	 *  'foo/bar/.././quux'.
 	 */
 
 	req_id_len = DUK_STRLEN(req_id);
 	if (mod_id != NULL && req_id[0] == '.') {
 		mod_id_len = DUK_STRLEN(mod_id);
-		if (mod_id_len + 1 + req_id_len + 1 >= sizeof(buf_in)) {
+		if (mod_id_len + 4 + req_id_len + 1 >= sizeof(buf_in)) {
 			DUK_DD(DUK_DDPRINT("resolve error: current and requested module ID don't fit into resolve input buffer"));
 			goto resolve_error;
 		}
-		(void) DUK_SNPRINTF((char *) buf_in, sizeof(buf_in), "%s/%s", (const char *) mod_id, (const char *) req_id);
+		(void) DUK_SNPRINTF((char *) buf_in, sizeof(buf_in), "%s/../%s", (const char *) mod_id, (const char *) req_id);
 	} else {
 		if (req_id_len + 1 >= sizeof(buf_in)) {
 			DUK_DD(DUK_DDPRINT("resolve error: requested module ID doesn't fit into resolve input buffer"));
@@ -19340,9 +31824,10 @@ static void duk__bi_global_resolve_module_id(duk_context *ctx, const char *req_i
 #endif  /* DUK_USE_COMMONJS_MODULES */
 
 #if defined(DUK_USE_COMMONJS_MODULES)
-duk_ret_t duk_bi_global_object_require(duk_context *ctx) {
+DUK_INTERNAL duk_ret_t duk_bi_global_object_require(duk_context *ctx) {
 	const char *str_req_id;  /* requested identifier */
 	const char *str_mod_id;  /* require.id of current module */
+	duk_int_t pcall_rc;
 
 	/* NOTE: we try to minimize code size by avoiding unnecessary pops,
 	 * so the stack looks a bit cluttered in this function.  DUK_ASSERT_TOP()
@@ -19396,10 +31881,11 @@ duk_ret_t duk_bi_global_object_require(duk_context *ctx) {
 		/* [ requested_id require require.id resolved_id Duktape Duktape.modLoaded Duktape.modLoaded[id] ] */
 		DUK_DD(DUK_DDPRINT("module already loaded: %!T",
 		                   (duk_tval *) duk_get_tval(ctx, 3)));
+		duk_get_prop_stridx(ctx, -1, DUK_STRIDX_EXPORTS);  /* return module.exports */
 		return 1;
 	}
 
-	/* [ requested_id require require.id resolved_id Duktape Duktape.modLoaded undefined ] */
+	/* [ requested_id require require.id resolved_id Duktape Duktape.modLoaded undefined ] */
 	DUK_ASSERT_TOP(ctx, 7);
 
 	/*
@@ -19424,21 +31910,32 @@ duk_ret_t duk_bi_global_object_require(duk_context *ctx) {
 	 */
 	duk_push_c_function(ctx, duk_bi_global_object_require, 1 /*nargs*/);
 	duk_dup(ctx, 3);
-	duk_def_prop_stridx(ctx, 7, DUK_STRIDX_ID, DUK_PROPDESC_FLAGS_C);  /* a fresh require() with require.id = resolved target module id */
-
-	/* Exports table. */
-	duk_push_object(ctx);
+	duk_xdef_prop_stridx(ctx, 7, DUK_STRIDX_ID, DUK_PROPDESC_FLAGS_C);  /* a fresh require() with require.id = resolved target module id */
 
-	/* Module table: module.id is non-writable and non-configurable, as
-	 * the CommonJS spec suggests this if possible.
+	/* Module table:
+	 * - module.exports: initial exports table (may be replaced by user)
+	 * - module.id is non-writable and non-configurable, as the CommonJS
+	 *   spec suggests this if possible.
 	 */
-	duk_push_object(ctx);
+	duk_push_object(ctx);  /* exports */
+	duk_push_object(ctx);  /* module */
+	duk_dup(ctx, -2);
+	duk_xdef_prop_stridx(ctx, 9, DUK_STRIDX_EXPORTS, DUK_PROPDESC_FLAGS_WC);  /* module.exports = exports */
 	duk_dup(ctx, 3);  /* resolved id: require(id) must return this same module */
-	duk_def_prop_stridx(ctx, 9, DUK_STRIDX_ID, DUK_PROPDESC_FLAGS_NONE);
+	duk_xdef_prop_stridx(ctx, 9, DUK_STRIDX_ID, DUK_PROPDESC_FLAGS_NONE);  /* module.id = resolved_id */
+	duk_compact(ctx, 9);  /* module table remains registered to modLoaded, minimize its size */
 
-	/* [ requested_id require require.id resolved_id Duktape Duktape.modLoaded undefined fresh_require exports module ] */
+	/* [ requested_id require require.id resolved_id Duktape Duktape.modLoaded undefined fresh_require exports module ] */
 	DUK_ASSERT_TOP(ctx, 10);
 
+	/* Register the module table early to modLoaded[] so that we can
+	 * support circular references even in modSearch().  If an error
+	 * is thrown, we'll delete the reference.
+	 */
+	duk_dup(ctx, 3);
+	duk_dup(ctx, 9);
+	duk_put_prop(ctx, 5);  /* Duktape.modLoaded[resolved_id] = module */
+
 	/*
 	 *  Call user provided module search function and build the wrapped
 	 *  module source code (if necessary).  The module search function
@@ -19451,11 +31948,9 @@ duk_ret_t duk_bi_global_object_require(duk_context *ctx) {
 	 *  is returned the module is assumed to be a pure C one).  If a module
 	 *  cannot be found, an error must be thrown by the user callback.
 	 *
-	 *  NOTE: the current arrangement allows C modules to be implemented
-	 *  but since the exports table is registered to Duktape.modLoaded only
-	 *  after the search function returns, circular requires / partially
-	 *  loaded modules don't work for C modules.  This is rarely an issue,
-	 *  as C modules usually simply expose a set of helper functions.
+	 *  Because Duktape.modLoaded[] already contains the module being
+	 *  loaded, circular references for C modules should also work
+	 *  (although expected to be quite rare).
 	 */
 
 	duk_push_string(ctx, "(function(require,exports,module){");
@@ -19466,36 +31961,34 @@ duk_ret_t duk_bi_global_object_require(duk_context *ctx) {
 	duk_dup(ctx, 7);
 	duk_dup(ctx, 8);
 	duk_dup(ctx, 9);  /* [ ... Duktape.modSearch resolved_id fresh_require exports module ] */
-	duk_call(ctx, 4 /*nargs*/);  /* -> [ ... source ] */
+	pcall_rc = duk_pcall(ctx, 4 /*nargs*/);  /* -> [ ... source ] */
 	DUK_ASSERT_TOP(ctx, 12);
 
-	/* Because user callback did not throw an error, remember exports table. */
-	duk_dup(ctx, 3);
-	duk_dup(ctx, 8);
-	duk_def_prop(ctx, 5, DUK_PROPDESC_FLAGS_EC);  /* Duktape.modLoaded[resolved_id] = exports */
+	if (pcall_rc != DUK_EXEC_SUCCESS) {
+		/* Delete entry in Duktape.modLoaded[] and rethrow. */
+		goto delete_rethrow;
+	}
 
 	/* If user callback did not return source code, module loading
 	 * is finished (user callback initialized exports table directly).
 	 */
 	if (!duk_is_string(ctx, 11)) {
-		/* User callback did not return source code, so
-		 * module loading is finished.
+		/* User callback did not return source code, so module loading
+		 * is finished: just update modLoaded with final module.exports
+		 * and we're done.
 		 */
-		duk_dup(ctx, 8);
-		return 1;
+		goto return_exports;
 	}
 
-	/* Finish the wrapped module source. */
+	/* Finish the wrapped module source.  Force resolved module ID as the
+	 * fileName so it gets set for functions defined within a module.  This
+	 * also ensures loggers created within the module get the module ID as
+	 * their default logger name.
+	 */
 	duk_push_string(ctx, "})");
 	duk_concat(ctx, 3);
-	duk_eval(ctx);
-
-	/* Force 'fileName' property of the module function so that if the
-	 * module creates a logger, the logger name defaults to the module
-	 * name.
-	 */
-	duk_dup(ctx, 3);
-	duk_put_prop_stridx(ctx, -2, DUK_STRIDX_FILE_NAME);
+	duk_dup(ctx, 3);  /* resolved module ID for fileName */
+	duk_eval_raw(ctx, NULL, 0, DUK_COMPILE_EVAL);
 
 	/* XXX: The module wrapper function is currently anonymous and is shown
 	 * in stack traces.  It would be nice to force it to match the module
@@ -19509,29 +32002,48 @@ duk_ret_t duk_bi_global_object_require(duk_context *ctx) {
 
 	/*
 	 *  Call the wrapped module function.
+	 *
+	 *  Use a protected call so that we can update Duktape.modLoaded[resolved_id]
+	 *  even if the module throws an error.
 	 */
 
-	/* [ requested_id require require.id resolved_id Duktape Duktape.modLoaded undefined fresh_require exports module mod_func ] */
+	/* [ requested_id require require.id resolved_id Duktape Duktape.modLoaded undefined fresh_require exports module mod_func ] */
 	DUK_ASSERT_TOP(ctx, 11);
 
 	duk_dup(ctx, 8);  /* exports (this binding) */
 	duk_dup(ctx, 7);  /* fresh require (argument) */
-	duk_dup(ctx, 8);  /* exports (argument) */
+	duk_get_prop_stridx(ctx, 9, DUK_STRIDX_EXPORTS);  /* relookup exports from module.exports in case it was changed by modSearch */
 	duk_dup(ctx, 9);  /* module (argument) */
 
-	/* [ requested_id require require.id resolved_id Duktape Duktape.modLoaded undefined fresh_require exports module mod_func exports fresh_require exports module ] */
+	/* [ requested_id require require.id resolved_id Duktape Duktape.modLoaded undefined fresh_require exports module mod_func exports fresh_require exports module ] */
 	DUK_ASSERT_TOP(ctx, 15);
 
-	duk_call_method(ctx, 3 /*nargs*/);
+	pcall_rc = duk_pcall_method(ctx, 3 /*nargs*/);
+	if (pcall_rc != DUK_EXEC_SUCCESS) {
+		/* Module loading failed.  Node.js will forget the module
+		 * registration so that another require() will try to load
+		 * the module again.  Mimic that behavior.
+		 */
+		goto delete_rethrow;
+	}
 
-	/* [ requested_id require require.id resolved_id Duktape Duktape.modLoaded undefined fresh_require exports module result(ignored) ] */
+	/* [ requested_id require require.id resolved_id Duktape Duktape.modLoaded undefined fresh_require exports module result(ignored) ] */
 	DUK_ASSERT_TOP(ctx, 11);
 
-	duk_pop_2(ctx);
-	return 1;  /* return exports */
+	/* fall through */
+
+ return_exports:
+	duk_get_prop_stridx(ctx, 9, DUK_STRIDX_EXPORTS);
+	return 1;  /* return module.exports */
+
+ delete_rethrow:
+	duk_dup(ctx, 3);
+	duk_del_prop(ctx, 5);  /* delete Duktape.modLoaded[resolved_id] */
+	duk_throw(ctx);  /* rethrow original error */
+	return 0;  /* not reachable */
 }
 #else
-duk_ret_t duk_bi_global_object_require(duk_context *ctx) {
+DUK_INTERNAL duk_ret_t duk_bi_global_object_require(duk_context *ctx) {
 	DUK_UNREF(ctx);
 	return DUK_RET_UNSUPPORTED_ERROR;
 }
@@ -19540,10 +32052,17 @@ duk_ret_t duk_bi_global_object_require(duk_context *ctx) {
 /*
  *  JSON built-ins.
  *
- *  See doc/json.txt.
+ *  See doc/json.rst.
  *
  *  Codepoints are handled as duk_uint_fast32_t to ensure that the full
  *  unsigned 32-bit range is supported.  This matters to e.g. JX.
+ *
+ *  Input parsing doesn't do an explicit end-of-input check at all.  This is
+ *  safe: input string data is always NUL-terminated (0x00) and valid JSON
+ *  inputs never contain plain NUL characters, so that as long as syntax checks
+ *  are correct, we'll never read past the NUL.  This approach reduces code size
+ *  and improves parsing performance, but it's critical that syntax checks are
+ *  indeed correct!
  */
 
 /* include removed: duk_internal.h */
@@ -19552,45 +32071,176 @@ duk_ret_t duk_bi_global_object_require(duk_context *ctx) {
  *  Local defines and forward declarations.
  */
 
-static void duk__dec_syntax_error(duk_json_dec_ctx *js_ctx);
-static void duk__dec_eat_white(duk_json_dec_ctx *js_ctx);
-static duk_small_int_t duk__dec_peek(duk_json_dec_ctx *js_ctx);
-static duk_small_int_t duk__dec_get(duk_json_dec_ctx *js_ctx);
-static duk_small_int_t duk__dec_get_nonwhite(duk_json_dec_ctx *js_ctx);
-static duk_uint_fast32_t duk__dec_decode_hex_escape(duk_json_dec_ctx *js_ctx, duk_small_uint_t n);
-static void duk__dec_req_stridx(duk_json_dec_ctx *js_ctx, duk_small_uint_t stridx);
-static void duk__dec_string(duk_json_dec_ctx *js_ctx);
+#define DUK__JSON_DECSTR_BUFSIZE 128
+#define DUK__JSON_DECSTR_CHUNKSIZE 64
+#define DUK__JSON_ENCSTR_CHUNKSIZE 64
+#define DUK__JSON_STRINGIFY_BUFSIZE 128
+#define DUK__JSON_MAX_ESC_LEN 10  /* '\Udeadbeef' */
+
+DUK_LOCAL_DECL void duk__dec_syntax_error(duk_json_dec_ctx *js_ctx);
+DUK_LOCAL_DECL void duk__dec_eat_white(duk_json_dec_ctx *js_ctx);
+DUK_LOCAL_DECL duk_uint8_t duk__dec_peek(duk_json_dec_ctx *js_ctx);
+DUK_LOCAL_DECL duk_uint8_t duk__dec_get(duk_json_dec_ctx *js_ctx);
+DUK_LOCAL_DECL duk_uint8_t duk__dec_get_nonwhite(duk_json_dec_ctx *js_ctx);
+DUK_LOCAL_DECL duk_uint_fast32_t duk__dec_decode_hex_escape(duk_json_dec_ctx *js_ctx, duk_small_uint_t n);
+DUK_LOCAL_DECL void duk__dec_req_stridx(duk_json_dec_ctx *js_ctx, duk_small_uint_t stridx);
+DUK_LOCAL_DECL void duk__dec_string(duk_json_dec_ctx *js_ctx);
 #ifdef DUK_USE_JX
-static void duk__dec_plain_string(duk_json_dec_ctx *js_ctx);
-static void duk__dec_pointer(duk_json_dec_ctx *js_ctx);
-static void duk__dec_buffer(duk_json_dec_ctx *js_ctx);
-#endif
-static void duk__dec_number(duk_json_dec_ctx *js_ctx);
-static void duk__dec_objarr_entry(duk_json_dec_ctx *js_ctx);
-static void duk__dec_objarr_exit(duk_json_dec_ctx *js_ctx);
-static void duk__dec_object(duk_json_dec_ctx *js_ctx);
-static void duk__dec_array(duk_json_dec_ctx *js_ctx);
-static void duk__dec_value(duk_json_dec_ctx *js_ctx);
-static void duk__dec_reviver_walk(duk_json_dec_ctx *js_ctx);
-
-static void duk__emit_1(duk_json_enc_ctx *js_ctx, duk_uint_fast8_t ch);
-static void duk__emit_2(duk_json_enc_ctx *js_ctx, duk_uint_fast16_t packed_chars);
-static void duk__emit_esc_auto(duk_json_enc_ctx *js_ctx, duk_uint_fast32_t cp);
-static void duk__emit_xutf8(duk_json_enc_ctx *js_ctx, duk_uint_fast32_t cp);
-static void duk__emit_hstring(duk_json_enc_ctx *js_ctx, duk_hstring *h);
+DUK_LOCAL_DECL void duk__dec_plain_string(duk_json_dec_ctx *js_ctx);
+DUK_LOCAL_DECL void duk__dec_pointer(duk_json_dec_ctx *js_ctx);
+DUK_LOCAL_DECL void duk__dec_buffer(duk_json_dec_ctx *js_ctx);
+#endif
+DUK_LOCAL_DECL void duk__dec_number(duk_json_dec_ctx *js_ctx);
+DUK_LOCAL_DECL void duk__dec_objarr_entry(duk_json_dec_ctx *js_ctx);
+DUK_LOCAL_DECL void duk__dec_objarr_exit(duk_json_dec_ctx *js_ctx);
+DUK_LOCAL_DECL void duk__dec_object(duk_json_dec_ctx *js_ctx);
+DUK_LOCAL_DECL void duk__dec_array(duk_json_dec_ctx *js_ctx);
+DUK_LOCAL_DECL void duk__dec_value(duk_json_dec_ctx *js_ctx);
+DUK_LOCAL_DECL void duk__dec_reviver_walk(duk_json_dec_ctx *js_ctx);
+
+DUK_LOCAL_DECL void duk__emit_1(duk_json_enc_ctx *js_ctx, duk_uint_fast8_t ch);
+DUK_LOCAL_DECL void duk__emit_2(duk_json_enc_ctx *js_ctx, duk_uint_fast8_t ch1, duk_uint_fast8_t ch2);
+#if defined(DUK_USE_JSON_STRINGIFY_FASTPATH)
+DUK_LOCAL_DECL void duk__unemit_1(duk_json_enc_ctx *js_ctx);
+#endif
+DUK_LOCAL_DECL void duk__emit_hstring(duk_json_enc_ctx *js_ctx, duk_hstring *h);
+#if defined(DUK_USE_FASTINT)
+DUK_LOCAL_DECL void duk__emit_cstring(duk_json_enc_ctx *js_ctx, const char *p);
+#endif
+DUK_LOCAL_DECL void duk__emit_stridx(duk_json_enc_ctx *js_ctx, duk_small_uint_t stridx);
+DUK_LOCAL_DECL duk_uint8_t *duk__emit_esc_auto_fast(duk_json_enc_ctx *js_ctx, duk_uint_fast32_t cp, duk_uint8_t *q);
+DUK_LOCAL_DECL duk_bool_t duk__enc_key_quotes_needed(duk_hstring *h_key);
+DUK_LOCAL_DECL void duk__enc_key_autoquote(duk_json_enc_ctx *js_ctx, duk_hstring *k);
+DUK_LOCAL_DECL void duk__enc_quote_string(duk_json_enc_ctx *js_ctx, duk_hstring *h_str);
+DUK_LOCAL_DECL void duk__enc_objarr_entry(duk_json_enc_ctx *js_ctx, duk_idx_t *entry_top);
+DUK_LOCAL_DECL void duk__enc_objarr_exit(duk_json_enc_ctx *js_ctx, duk_idx_t *entry_top);
+DUK_LOCAL_DECL void duk__enc_object(duk_json_enc_ctx *js_ctx);
+DUK_LOCAL_DECL void duk__enc_array(duk_json_enc_ctx *js_ctx);
+DUK_LOCAL_DECL duk_bool_t duk__enc_value1(duk_json_enc_ctx *js_ctx, duk_idx_t idx_holder);
+DUK_LOCAL_DECL void duk__enc_value2(duk_json_enc_ctx *js_ctx);
+DUK_LOCAL_DECL duk_bool_t duk__enc_allow_into_proplist(duk_tval *tv);
+DUK_LOCAL_DECL void duk__enc_double(duk_json_enc_ctx *js_ctx);
+#if defined(DUK_USE_FASTINT)
+DUK_LOCAL_DECL void duk__enc_fastint_tval(duk_json_enc_ctx *js_ctx, duk_tval *tv);
+#endif
 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
-static void duk__emit_cstring(duk_json_enc_ctx *js_ctx, const char *p);
+DUK_LOCAL_DECL void duk__enc_buffer(duk_json_enc_ctx *js_ctx, duk_hbuffer *h);
+DUK_LOCAL_DECL void duk__enc_pointer(duk_json_enc_ctx *js_ctx, void *ptr);
+#if defined(DUK_USE_JSON_STRINGIFY_FASTPATH)
+DUK_LOCAL_DECL void duk__enc_bufferobject(duk_json_enc_ctx *js_ctx, duk_hbufferobject *h_bufobj);
+#endif
 #endif
-static void duk__emit_stridx(duk_json_enc_ctx *js_ctx, duk_small_uint_t stridx);
-static duk_bool_t duk__enc_key_quotes_needed(duk_hstring *h_key);
-static void duk__enc_quote_string(duk_json_enc_ctx *js_ctx, duk_hstring *h_str);
-static void duk__enc_objarr_entry(duk_json_enc_ctx *js_ctx, duk_hstring **h_stepback, duk_hstring **h_indent, duk_idx_t *entry_top);
-static void duk__enc_objarr_exit(duk_json_enc_ctx *js_ctx, duk_hstring **h_stepback, duk_hstring **h_indent, duk_idx_t *entry_top);
-static void duk__enc_object(duk_json_enc_ctx *js_ctx);
-static void duk__enc_array(duk_json_enc_ctx *js_ctx);
-static duk_bool_t duk__enc_value1(duk_json_enc_ctx *js_ctx, duk_idx_t idx_holder);
-static void duk__enc_value2(duk_json_enc_ctx *js_ctx);
-static duk_bool_t duk__enc_allow_into_proplist(duk_tval *tv);
+DUK_LOCAL_DECL void duk__enc_newline_indent(duk_json_enc_ctx *js_ctx, duk_int_t depth);
+
+/*
+ *  Helper tables
+ */
+
+#if defined(DUK_USE_JSON_QUOTESTRING_FASTPATH)
+DUK_LOCAL const duk_uint8_t duk__json_quotestr_lookup[256] = {
+	/* 0x00 ... 0x7f: as is
+	 * 0x80: escape generically
+	 * 0x81: slow path
+	 * 0xa0 ... 0xff: backslash + one char
+	 */
+
+	0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xe2, 0xf4, 0xee, 0x80, 0xe6, 0xf2, 0x80, 0x80,
+	0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+	0x20, 0x21, 0xa2, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
+	0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+	0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
+	0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0xdc, 0x5d, 0x5e, 0x5f,
+	0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
+	0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x81,
+	0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
+	0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
+	0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
+	0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
+	0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
+	0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
+	0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
+	0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81
+};
+#else  /* DUK_USE_JSON_QUOTESTRING_FASTPATH */
+DUK_LOCAL const duk_uint8_t duk__json_quotestr_esc[14] = {
+	DUK_ASC_NUL, DUK_ASC_NUL, DUK_ASC_NUL, DUK_ASC_NUL,
+	DUK_ASC_NUL, DUK_ASC_NUL, DUK_ASC_NUL, DUK_ASC_NUL,
+	DUK_ASC_LC_B, DUK_ASC_LC_T, DUK_ASC_LC_N, DUK_ASC_NUL,
+	DUK_ASC_LC_F, DUK_ASC_LC_R
+};
+#endif  /* DUK_USE_JSON_QUOTESTRING_FASTPATH */
+
+#if defined(DUK_USE_JSON_DECSTRING_FASTPATH)
+DUK_LOCAL const duk_uint8_t duk__json_decstr_lookup[256] = {
+	/* 0x00: slow path
+	 * other: as is
+	 */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x20, 0x21, 0x00, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
+	0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+	0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
+	0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x00, 0x5d, 0x5e, 0x5f,
+	0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
+	0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
+	0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
+	0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
+	0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
+	0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
+	0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
+	0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
+	0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
+	0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
+};
+#endif  /* DUK_USE_JSON_DECSTRING_FASTPATH */
+
+#if defined(DUK_USE_JSON_EATWHITE_FASTPATH)
+DUK_LOCAL const duk_uint8_t duk__json_eatwhite_lookup[256] = {
+	/* 0x00: finish (non-white)
+	 * 0x01: continue
+	 */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+#endif  /* DUK_USE_JSON_EATWHITE_FASTPATH */
+
+#if defined(DUK_USE_JSON_DECNUMBER_FASTPATH)
+DUK_LOCAL const duk_uint8_t duk__json_decnumber_lookup[256] = {
+	/* 0x00: finish (not part of number)
+	 * 0x01: continue
+	 */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x01, 0x00,
+	0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+#endif  /* DUK_USE_JSON_DECNUMBER_FASTPATH */
 
 /*
  *  Parsing implementation.
@@ -19605,70 +32255,79 @@ static duk_bool_t duk__enc_allow_into_proplist(duk_tval *tv);
  *  CESU-8 encodings.
  */
 
-static void duk__dec_syntax_error(duk_json_dec_ctx *js_ctx) {
+DUK_LOCAL void duk__dec_syntax_error(duk_json_dec_ctx *js_ctx) {
 	/* Shared handler to minimize parser size.  Cause will be
-	 * hidden, unfortunately.
+	 * hidden, unfortunately, but we'll have an offset which
+	 * is often quite enough.
 	 */
-	DUK_ERROR(js_ctx->thr, DUK_ERR_SYNTAX_ERROR, DUK_STR_INVALID_JSON);
+	DUK_ERROR(js_ctx->thr, DUK_ERR_SYNTAX_ERROR, DUK_STR_FMT_INVALID_JSON,
+	         (long) (js_ctx->p - js_ctx->p_start));
 }
 
-static void duk__dec_eat_white(duk_json_dec_ctx *js_ctx) {
-	duk_small_uint_t t;
+DUK_LOCAL void duk__dec_eat_white(duk_json_dec_ctx *js_ctx) {
+	const duk_uint8_t *p;
+	duk_uint8_t t;
+
+	p = js_ctx->p;
 	for (;;) {
-		if (js_ctx->p >= js_ctx->p_end) {
+		DUK_ASSERT(p <= js_ctx->p_end);
+		t = *p;
+
+#if defined(DUK_USE_JSON_EATWHITE_FASTPATH)
+		/* This fast path is pretty marginal in practice.
+		 * XXX: candidate for removal.
+		 */
+		DUK_ASSERT(duk__json_eatwhite_lookup[0x00] == 0x00);  /* end-of-input breaks */
+		if (duk__json_eatwhite_lookup[t] == 0) {
 			break;
 		}
-		t = (*js_ctx->p);
+#else  /* DUK_USE_JSON_EATWHITE_FASTPATH */
 		if (!(t == 0x20 || t == 0x0a || t == 0x0d || t == 0x09)) {
+			/* NUL also comes here.  Comparison order matters, 0x20
+			 * is most common whitespace.
+			 */
 			break;
 		}
-		js_ctx->p++;
+#endif  /* DUK_USE_JSON_EATWHITE_FASTPATH */
+		p++;
 	}
+	js_ctx->p = p;
 }
 
-static duk_small_int_t duk__dec_peek(duk_json_dec_ctx *js_ctx) {
-	if (js_ctx->p >= js_ctx->p_end) {
-		return -1;
-	} else {
-		return (duk_small_int_t) (*js_ctx->p);
-	}
+DUK_LOCAL duk_uint8_t duk__dec_peek(duk_json_dec_ctx *js_ctx) {
+	DUK_ASSERT(js_ctx->p <= js_ctx->p_end);
+	return *js_ctx->p;
 }
 
-static duk_small_int_t duk__dec_get(duk_json_dec_ctx *js_ctx) {
-	/* Multiple EOFs will now be supplied to the caller.  This could also be
-	 * changed so that reading the second EOF would cause an error automatically.
-	 */
-	if (js_ctx->p >= js_ctx->p_end) {
-		return -1;
-	} else {
-		return (duk_small_int_t) (*js_ctx->p++);
-	}
+DUK_LOCAL duk_uint8_t duk__dec_get(duk_json_dec_ctx *js_ctx) {
+	DUK_ASSERT(js_ctx->p <= js_ctx->p_end);
+	return *js_ctx->p++;
 }
 
-static duk_small_int_t duk__dec_get_nonwhite(duk_json_dec_ctx *js_ctx) {
+DUK_LOCAL duk_uint8_t duk__dec_get_nonwhite(duk_json_dec_ctx *js_ctx) {
 	duk__dec_eat_white(js_ctx);
 	return duk__dec_get(js_ctx);
 }
 
 /* For JX, expressing the whole unsigned 32-bit range matters. */
-static duk_uint_fast32_t duk__dec_decode_hex_escape(duk_json_dec_ctx *js_ctx, duk_small_uint_t n) {
+DUK_LOCAL duk_uint_fast32_t duk__dec_decode_hex_escape(duk_json_dec_ctx *js_ctx, duk_small_uint_t n) {
 	duk_small_uint_t i;
 	duk_uint_fast32_t res = 0;
-	duk_small_int_t x;
+	duk_uint8_t x;
+	duk_small_int_t t;
 
 	for (i = 0; i < n; i++) {
-		/* FIXME: share helper from lexer; duk_lexer.c / hexval(). */
+		/* XXX: share helper from lexer; duk_lexer.c / hexval(). */
 
 		x = duk__dec_get(js_ctx);
-		DUK_ASSERT((x >= 0 && x <= 0xff) || (x == -1));
-
 		DUK_DDD(DUK_DDDPRINT("decode_hex_escape: i=%ld, n=%ld, res=%ld, x=%ld",
 		                     (long) i, (long) n, (long) res, (long) x));
 
-		/* x == -1 will map to 0xff, dectab returns -1 which causes syntax_error */
-		x = duk_hex_dectab[x & 0xff];
-		if (DUK_LIKELY(x >= 0)) {
-			res = (res * 16) + x;
+		/* x == 0x00 (EOF) causes syntax_error */
+		DUK_ASSERT(duk_hex_dectab[0] == -1);
+		t = duk_hex_dectab[x & 0xff];
+		if (DUK_LIKELY(t >= 0)) {
+			res = (res * 16) + t;
 		} else {
 			/* catches EOF and invalid digits */
 			goto syntax_error;
@@ -19684,30 +32343,32 @@ static duk_uint_fast32_t duk__dec_decode_hex_escape(duk_json_dec_ctx *js_ctx, du
 	return 0;
 }
 
-static void duk__dec_req_stridx(duk_json_dec_ctx *js_ctx, duk_small_uint_t stridx) {
+DUK_LOCAL void duk__dec_req_stridx(duk_json_dec_ctx *js_ctx, duk_small_uint_t stridx) {
 	duk_hstring *h;
-	duk_uint8_t *p;
-	duk_uint8_t *p_end;
-	duk_small_int_t x;
+	const duk_uint8_t *p;
+	duk_uint8_t x, y;
 
-	/* First character has already been eaten and checked by the caller. */
+	/* First character has already been eaten and checked by the caller.
+	 * We can scan until a NUL in stridx string because no built-in strings
+	 * have internal NULs.
+	 */
 
 	DUK_ASSERT_DISABLE(stridx >= 0);  /* unsigned */
 	DUK_ASSERT(stridx < DUK_HEAP_NUM_STRINGS);
 	h = DUK_HTHREAD_GET_STRING(js_ctx->thr, stridx);
 	DUK_ASSERT(h != NULL);
 
-	p = (duk_uint8_t *) DUK_HSTRING_GET_DATA(h);
-	p_end = ((duk_uint8_t *) DUK_HSTRING_GET_DATA(h)) +
-	        DUK_HSTRING_GET_BYTELEN(h);
+	p = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h) + 1;
+	DUK_ASSERT(*(js_ctx->p - 1) == *(p - 1));  /* first character has been matched */
 
-	DUK_ASSERT(*(js_ctx->p - 1) == *p);  /* first character has been matched */
-	p++;  /* first char */
-
-	while (p < p_end) {
-		x = duk__dec_get(js_ctx);
-		if ((duk_small_int_t) (*p) != x) {
-			/* catches EOF */
+	for (;;) {
+		x = *p;
+		if (x == 0) {
+			break;
+		}
+		y = duk__dec_get(js_ctx);
+		if (x != y) {
+			/* Catches EOF of JSON input. */
 			goto syntax_error;
 		}
 		p++;
@@ -19720,12 +32381,61 @@ static void duk__dec_req_stridx(duk_json_dec_ctx *js_ctx, duk_small_uint_t strid
 	DUK_UNREACHABLE();
 }
 
-static void duk__dec_string(duk_json_dec_ctx *js_ctx) {
+DUK_LOCAL duk_small_int_t duk__dec_string_escape(duk_json_dec_ctx *js_ctx, duk_uint8_t **ext_p) {
+	duk_uint_fast32_t cp;
+
+	/* EOF (-1) will be cast to an unsigned value first
+	 * and then re-cast for the switch.  In any case, it
+	 * will match the default case (syntax error).
+	 */
+	cp = (duk_uint_fast32_t) duk__dec_get(js_ctx);
+	switch ((int) cp) {
+	case DUK_ASC_BACKSLASH: break;
+	case DUK_ASC_DOUBLEQUOTE: break;
+	case DUK_ASC_SLASH: break;
+	case DUK_ASC_LC_T: cp = 0x09; break;
+	case DUK_ASC_LC_N: cp = 0x0a; break;
+	case DUK_ASC_LC_R: cp = 0x0d; break;
+	case DUK_ASC_LC_F: cp = 0x0c; break;
+	case DUK_ASC_LC_B: cp = 0x08; break;
+	case DUK_ASC_LC_U: {
+		cp = duk__dec_decode_hex_escape(js_ctx, 4);
+		break;
+	}
+#ifdef DUK_USE_JX
+	case DUK_ASC_UC_U: {
+		if (js_ctx->flag_ext_custom) {
+			cp = duk__dec_decode_hex_escape(js_ctx, 8);
+		} else {
+			return 1;  /* syntax error */
+		}
+		break;
+	}
+	case DUK_ASC_LC_X: {
+		if (js_ctx->flag_ext_custom) {
+			cp = duk__dec_decode_hex_escape(js_ctx, 2);
+		} else {
+			return 1;  /* syntax error */
+		}
+		break;
+	}
+#endif  /* DUK_USE_JX */
+	default:
+		/* catches EOF (0x00) */
+		return 1;  /* syntax error */
+	}
+
+	DUK_RAW_WRITE_XUTF8(*ext_p, cp);
+
+	return 0;
+}
+
+DUK_LOCAL void duk__dec_string(duk_json_dec_ctx *js_ctx) {
 	duk_hthread *thr = js_ctx->thr;
 	duk_context *ctx = (duk_context *) thr;
-	duk_hbuffer_dynamic *h_buf;
-	duk_small_int_t x;
-	duk_uint_fast32_t cp;
+	duk_bufwriter_ctx bw_alloc;
+	duk_bufwriter_ctx *bw;
+	duk_uint8_t *q;
 
 	/* '"' was eaten by caller */
 
@@ -19734,65 +32444,87 @@ static void duk__dec_string(duk_json_dec_ctx *js_ctx) {
 	 * so they'll simply pass through (valid UTF-8 or not).
 	 */
 
-	duk_push_dynamic_buffer(ctx, 0);
-	h_buf = (duk_hbuffer_dynamic *) duk_get_hbuffer(ctx, -1);
-	DUK_ASSERT(h_buf != NULL);
-	DUK_ASSERT(DUK_HBUFFER_HAS_DYNAMIC(h_buf));
+	bw = &bw_alloc;
+	DUK_BW_INIT_PUSHBUF(js_ctx->thr, bw, DUK__JSON_DECSTR_BUFSIZE);
+	q = DUK_BW_GET_PTR(js_ctx->thr, bw);
 
+#if defined(DUK_USE_JSON_DECSTRING_FASTPATH)
 	for (;;) {
-		x = duk__dec_get(js_ctx);
-		if (x == DUK_ASC_DOUBLEQUOTE) {
-			break;
-		} else if (x == DUK_ASC_BACKSLASH) {
-			/* EOF (-1) will be cast to an unsigned value first
-			 * and then re-cast for the switch.  In any case, it
-			 * will match the default case (syntax error).
-			 */
-			cp = (duk_uint_fast32_t) duk__dec_get(js_ctx);
-			switch ((int) cp) {
-			case DUK_ASC_BACKSLASH: break;
-			case DUK_ASC_DOUBLEQUOTE: break;
-			case DUK_ASC_SLASH: break;
-			case DUK_ASC_LC_T: cp = 0x09; break;
-			case DUK_ASC_LC_N: cp = 0x0a; break;
-			case DUK_ASC_LC_R: cp = 0x0d; break;
-			case DUK_ASC_LC_F: cp = 0x0c; break;
-			case DUK_ASC_LC_B: cp = 0x08; break;
-			case DUK_ASC_LC_U: {
-				cp = duk__dec_decode_hex_escape(js_ctx, 4);
-				break;
-			}
-#ifdef DUK_USE_JX
-			case DUK_ASC_UC_U: {
-				if (js_ctx->flag_ext_custom) {
-					cp = duk__dec_decode_hex_escape(js_ctx, 8);
-				} else {
-					goto syntax_error;
-				}
+		duk_small_uint_t safe;
+		duk_uint8_t b, x;
+		const duk_uint8_t *p;
+
+		/* Select a safe loop count where no output checks are
+		 * needed assuming we won't encounter escapes.  Input
+		 * bound checks are not necessary as a NUL (guaranteed)
+		 * will cause a SyntaxError before we read out of bounds.
+		 */
+
+		safe = DUK__JSON_DECSTR_CHUNKSIZE;
+
+		/* Ensure space for 1:1 output plus one escape. */
+		q = DUK_BW_ENSURE_RAW(js_ctx->thr, bw, safe + DUK_UNICODE_MAX_XUTF8_LENGTH, q);
+
+		p = js_ctx->p;  /* temp copy, write back for next loop */
+		for (;;) {
+			if (safe == 0) {
+				js_ctx->p = p;
 				break;
 			}
-			case DUK_ASC_LC_X: {
-				if (js_ctx->flag_ext_custom) {
-					cp = duk__dec_decode_hex_escape(js_ctx, 2);
-				} else {
+			safe--;
+
+			/* End of input (NUL) goes through slow path and causes SyntaxError. */
+			DUK_ASSERT(duk__json_decstr_lookup[0] == 0x00);
+
+			b = *p++;
+			x = (duk_small_int_t) duk__json_decstr_lookup[b];
+			if (DUK_LIKELY(x != 0)) {
+				/* Fast path, decode as is. */
+				*q++ = b;
+			} else if (b == DUK_ASC_DOUBLEQUOTE) {
+				js_ctx->p = p;
+				goto found_quote;
+			} else if (b == DUK_ASC_BACKSLASH) {
+				/* We've ensured space for one escaped input; then
+				 * bail out and recheck (this makes escape handling
+				 * quite slow but it's uncommon).
+				 */
+				js_ctx->p = p;
+				if (duk__dec_string_escape(js_ctx, &q) != 0) {
 					goto syntax_error;
 				}
 				break;
+			} else {
+				js_ctx->p = p;
+				goto syntax_error;
 			}
-#endif  /* DUK_USE_JX */
-			default:
-				/* catches EOF (-1) */
+		}
+	}
+ found_quote:
+#else  /* DUK_USE_JSON_DECSTRING_FASTPATH */
+	for (;;) {
+		duk_uint8_t x;
+
+		q = DUK_BW_ENSURE_RAW(js_ctx->thr, bw, DUK_UNICODE_MAX_XUTF8_LENGTH, q);
+
+		x = duk__dec_get(js_ctx);
+
+		if (x == DUK_ASC_DOUBLEQUOTE) {
+			break;
+		} else if (x == DUK_ASC_BACKSLASH) {
+			if (duk__dec_string_escape(js_ctx, &q) != 0) {
 				goto syntax_error;
 			}
-			duk_hbuffer_append_xutf8(thr, h_buf, (duk_uint32_t) cp);
 		} else if (x < 0x20) {
-			/* catches EOF (-1) */
+			/* catches EOF (NUL) */
 			goto syntax_error;
 		} else {
-			duk_hbuffer_append_byte(thr, h_buf, (duk_uint8_t) x);
+			*q++ = (duk_uint8_t) x;
 		}
 	}
+#endif  /* DUK_USE_JSON_DECSTRING_FASTPATH */
 
+	DUK_BW_SETPTR_AND_COMPACT(js_ctx->thr, bw, q);
 	duk_to_string(ctx, -1);
 
 	/* [ ... str ] */
@@ -19808,10 +32540,10 @@ static void duk__dec_string(duk_json_dec_ctx *js_ctx) {
 /* Decode a plain string consisting entirely of identifier characters.
  * Used to parse plain keys (e.g. "foo: 123").
  */
-static void duk__dec_plain_string(duk_json_dec_ctx *js_ctx) {
+DUK_LOCAL void duk__dec_plain_string(duk_json_dec_ctx *js_ctx) {
 	duk_hthread *thr = js_ctx->thr;
 	duk_context *ctx = (duk_context *) thr;
-	duk_uint8_t *p;
+	const duk_uint8_t *p;
 	duk_small_int_t x;
 
 	/* Caller has already eaten the first char so backtrack one byte. */
@@ -19851,10 +32583,10 @@ static void duk__dec_plain_string(duk_json_dec_ctx *js_ctx) {
 #endif  /* DUK_USE_JX */
 
 #ifdef DUK_USE_JX
-static void duk__dec_pointer(duk_json_dec_ctx *js_ctx) {
+DUK_LOCAL void duk__dec_pointer(duk_json_dec_ctx *js_ctx) {
 	duk_hthread *thr = js_ctx->thr;
 	duk_context *ctx = (duk_context *) thr;
-	duk_uint8_t *p;
+	const duk_uint8_t *p;
 	duk_small_int_t x;
 	void *voidptr;
 
@@ -19905,16 +32637,30 @@ static void duk__dec_pointer(duk_json_dec_ctx *js_ctx) {
 #endif  /* DUK_USE_JX */
 
 #ifdef DUK_USE_JX
-static void duk__dec_buffer(duk_json_dec_ctx *js_ctx) {
+DUK_LOCAL void duk__dec_buffer(duk_json_dec_ctx *js_ctx) {
 	duk_hthread *thr = js_ctx->thr;
 	duk_context *ctx = (duk_context *) thr;
-	duk_uint8_t *p;
+	const duk_uint8_t *p;
+	duk_uint8_t *buf;
+	duk_size_t src_len;
 	duk_small_int_t x;
 
 	/* Caller has already eaten the first character ('|') which we don't need. */
 
 	p = js_ctx->p;
 
+	/* XXX: Would be nice to share the fast path loop from duk_hex_decode()
+	 * and avoid creating a temporary buffer.  However, there are some
+	 * differences which prevent trivial sharing:
+	 *
+	 *   - Pipe char detection
+	 *   - EOF detection
+	 *   - Unknown length of input and output
+	 *
+	 * The best approach here would be a bufwriter and a reasonaly sized
+	 * safe inner loop (e.g. 64 output bytes at a time).
+	 */
+
 	for (;;) {
 		x = *p;
 
@@ -19930,8 +32676,12 @@ static void duk__dec_buffer(duk_json_dec_ctx *js_ctx) {
 		p++;
 	}
 
-	duk_push_lstring(ctx, (const char *) js_ctx->p, (duk_size_t) (p - js_ctx->p));
+	src_len = (duk_size_t) (p - js_ctx->p);
+	buf = (duk_uint8_t *) duk_push_fixed_buffer(ctx, src_len);
+	DUK_ASSERT(buf != NULL);
+	DUK_MEMCPY((void *) buf, (const void *) js_ctx->p, src_len);
 	duk_hex_decode(ctx, -1);
+
 	js_ctx->p = p + 1;  /* skip '|' */
 
 	/* [ ... buf ] */
@@ -19945,44 +32695,53 @@ static void duk__dec_buffer(duk_json_dec_ctx *js_ctx) {
 #endif  /* DUK_USE_JX */
 
 /* Parse a number, other than NaN or +/- Infinity */
-static void duk__dec_number(duk_json_dec_ctx *js_ctx) {
+DUK_LOCAL void duk__dec_number(duk_json_dec_ctx *js_ctx) {
 	duk_context *ctx = (duk_context *) js_ctx->thr;
-	duk_uint8_t *p_start;
-	duk_small_int_t x;
+	const duk_uint8_t *p_start;
+	const duk_uint8_t *p;
+	duk_uint8_t x;
 	duk_small_uint_t s2n_flags;
 
 	DUK_DDD(DUK_DDDPRINT("parse_number"));
 
-	/* Caller has already eaten the first character so backtrack one
-	 * byte.  This is correct because the first character is either
-	 * '-' or a digit (i.e. an ASCII character).
-	 */
-
-	js_ctx->p--;  /* safe */
 	p_start = js_ctx->p;
 
 	/* First pass parse is very lenient (e.g. allows '1.2.3') and extracts a
 	 * string for strict number parsing.
 	 */
 
+	p = js_ctx->p;
 	for (;;) {
-		x = duk__dec_peek(js_ctx);
+		x = *p;
 
 		DUK_DDD(DUK_DDDPRINT("parse_number: p_start=%p, p=%p, p_end=%p, x=%ld",
-		                     (void *) p_start, (void *) js_ctx->p,
-		                     (void *) js_ctx->p_end, (long) x));
+		                     (const void *) p_start, (const void *) p,
+		                     (const void *) js_ctx->p_end, (long) x));
 
+#if defined(DUK_USE_JSON_DECNUMBER_FASTPATH)
+		/* This fast path is pretty marginal in practice.
+		 * XXX: candidate for removal.
+		 */
+		DUK_ASSERT(duk__json_decnumber_lookup[0x00] == 0x00);  /* end-of-input breaks */
+		if (duk__json_decnumber_lookup[x] == 0) {
+			break;
+		}
+#else  /* DUK_USE_JSON_DECNUMBER_FASTPATH */
 		if (!((x >= DUK_ASC_0 && x <= DUK_ASC_9) ||
 		      (x == DUK_ASC_PERIOD || x == DUK_ASC_LC_E ||
-		       x == DUK_ASC_UC_E || x == DUK_ASC_MINUS))) {
+		       x == DUK_ASC_UC_E || x == DUK_ASC_MINUS || x == DUK_ASC_PLUS))) {
+			/* Plus sign must be accepted for positive exponents
+			 * (e.g. '1.5e+2').  This clause catches NULs.
+			 */
 			break;
 		}
-
-		js_ctx->p++;  /* safe, because matched char */
+#endif  /* DUK_USE_JSON_DECNUMBER_FASTPATH */
+		p++;  /* safe, because matched (NUL causes a break) */
 	}
+	js_ctx->p = p;
 
 	DUK_ASSERT(js_ctx->p > p_start);
-	duk_push_lstring(ctx, (const char *) p_start, (duk_size_t) (js_ctx->p - p_start));
+	duk_push_lstring(ctx, (const char *) p_start, (duk_size_t) (p - p_start));
 
 	s2n_flags = DUK_S2N_FLAG_ALLOW_EXP |
 	            DUK_S2N_FLAG_ALLOW_MINUS |  /* but don't allow leading plus */
@@ -19992,7 +32751,7 @@ static void duk__dec_number(duk_json_dec_ctx *js_ctx) {
 	                     (duk_tval *) duk_get_tval(ctx, -1)));
 	duk_numconv_parse(ctx, 10 /*radix*/, s2n_flags);
 	if (duk_is_nan(ctx, -1)) {
-		DUK_ERROR(js_ctx->thr, DUK_ERR_SYNTAX_ERROR, DUK_STR_INVALID_NUMBER);
+		duk__dec_syntax_error(js_ctx);
 	}
 	DUK_ASSERT(duk_is_number(ctx, -1));
 	DUK_DDD(DUK_DDDPRINT("parse_number: final number: %!T",
@@ -20001,7 +32760,7 @@ static void duk__dec_number(duk_json_dec_ctx *js_ctx) {
 	/* [ ... num ] */
 }
 
-static void duk__dec_objarr_entry(duk_json_dec_ctx *js_ctx) {
+DUK_LOCAL void duk__dec_objarr_entry(duk_json_dec_ctx *js_ctx) {
 	duk_context *ctx = (duk_context *) js_ctx->thr;
 	duk_require_stack(ctx, DUK_JSON_DEC_REQSTACK);
 
@@ -20015,7 +32774,7 @@ static void duk__dec_objarr_entry(duk_json_dec_ctx *js_ctx) {
 	js_ctx->recursion_depth++;
 }
 
-static void duk__dec_objarr_exit(duk_json_dec_ctx *js_ctx) {
+DUK_LOCAL void duk__dec_objarr_exit(duk_json_dec_ctx *js_ctx) {
 	/* c recursion check */
 
 	DUK_ASSERT(js_ctx->recursion_depth > 0);
@@ -20023,10 +32782,10 @@ static void duk__dec_objarr_exit(duk_json_dec_ctx *js_ctx) {
 	js_ctx->recursion_depth--;
 }
 
-static void duk__dec_object(duk_json_dec_ctx *js_ctx) {
+DUK_LOCAL void duk__dec_object(duk_json_dec_ctx *js_ctx) {
 	duk_context *ctx = (duk_context *) js_ctx->thr;
 	duk_int_t key_count;  /* XXX: a "first" flag would suffice */
-	duk_small_int_t x;
+	duk_uint8_t x;
 
 	DUK_DDD(DUK_DDDPRINT("parse_object"));
 
@@ -20058,7 +32817,7 @@ static void duk__dec_object(duk_json_dec_ctx *js_ctx) {
 			 */
 			;
 		} else {
-			/* catches EOF (and initial comma) */
+			/* catches EOF (NUL) and initial comma */
 			goto syntax_error;
 		}
 
@@ -20086,7 +32845,7 @@ static void duk__dec_object(duk_json_dec_ctx *js_ctx) {
 
 		/* [ ... obj key val ] */
 
-		duk_def_prop_wec(ctx, -3);
+		duk_xdef_prop_wec(ctx, -3);
 
 		/* [ ... obj ] */
 
@@ -20106,10 +32865,10 @@ static void duk__dec_object(duk_json_dec_ctx *js_ctx) {
 	DUK_UNREACHABLE();
 }
 
-static void duk__dec_array(duk_json_dec_ctx *js_ctx) {
+DUK_LOCAL void duk__dec_array(duk_json_dec_ctx *js_ctx) {
 	duk_context *ctx = (duk_context *) js_ctx->thr;
 	duk_uarridx_t arr_idx;
-	duk_small_int_t x;
+	duk_uint8_t x;
 
 	DUK_DDD(DUK_DDDPRINT("parse_array"));
 
@@ -20141,7 +32900,7 @@ static void duk__dec_array(duk_json_dec_ctx *js_ctx) {
 			 */
 			js_ctx->p--;  /* backtrack (safe) */
 		} else {
-			/* catches EOF (and initial comma) */
+			/* catches EOF (NUL) and initial comma */
 			goto syntax_error;
 		}
 
@@ -20151,11 +32910,11 @@ static void duk__dec_array(duk_json_dec_ctx *js_ctx) {
 
 		/* [ ... arr val ] */
 
-		duk_def_prop_index_wec(ctx, -2, arr_idx);
+		duk_xdef_prop_index_wec(ctx, -2, arr_idx);
 		arr_idx++;
 	}
 
-	/* Must set 'length' explicitly when using duk_def_prop_xxx() to
+	/* Must set 'length' explicitly when using duk_xdef_prop_xxx() to
 	 * set the values.
 	 */
 
@@ -20174,9 +32933,9 @@ static void duk__dec_array(duk_json_dec_ctx *js_ctx) {
 	DUK_UNREACHABLE();
 }
 
-static void duk__dec_value(duk_json_dec_ctx *js_ctx) {
+DUK_LOCAL void duk__dec_value(duk_json_dec_ctx *js_ctx) {
 	duk_context *ctx = (duk_context *) js_ctx->thr;
-	duk_small_int_t x;
+	duk_uint8_t x;
 
 	x = duk__dec_get_nonwhite(js_ctx);
 
@@ -20188,14 +32947,15 @@ static void duk__dec_value(duk_json_dec_ctx *js_ctx) {
 		duk__dec_string(js_ctx);
 	} else if ((x >= DUK_ASC_0 && x <= DUK_ASC_9) || (x == DUK_ASC_MINUS)) {
 #ifdef DUK_USE_JX
-		if (js_ctx->flag_ext_custom && duk__dec_peek(js_ctx) == DUK_ASC_UC_I) {
-			duk__dec_req_stridx(js_ctx, DUK_STRIDX_MINUS_INFINITY);  /* "-Infinity" */
+		if (js_ctx->flag_ext_custom && x == DUK_ASC_MINUS && duk__dec_peek(js_ctx) == DUK_ASC_UC_I) {
+			duk__dec_req_stridx(js_ctx, DUK_STRIDX_MINUS_INFINITY);  /* "-Infinity", '-' has been eaten */
 			duk_push_number(ctx, -DUK_DOUBLE_INFINITY);
 		} else {
 #else
 		{  /* unconditional block */
 #endif
-			/* We already ate 'x', so duk__dec_number() will back up one byte. */
+			/* We already ate 'x', so backup one byte. */
+			js_ctx->p--;  /* safe */
 			duk__dec_number(js_ctx);
 		}
 	} else if (x == DUK_ASC_LC_T) {
@@ -20227,7 +32987,7 @@ static void duk__dec_value(duk_json_dec_ctx *js_ctx) {
 	} else if (x == DUK_ASC_LBRACKET) {
 		duk__dec_array(js_ctx);
 	} else {
-		/* catches EOF */
+		/* catches EOF (NUL) */
 		goto syntax_error;
 	}
 
@@ -20245,7 +33005,7 @@ static void duk__dec_value(duk_json_dec_ctx *js_ctx) {
  * check is done here because the initial parsing step will already ensure
  * there is a reasonable limit on C recursion depth and hence object depth.
  */
-static void duk__dec_reviver_walk(duk_json_dec_ctx *js_ctx) {
+DUK_LOCAL void duk__dec_reviver_walk(duk_json_dec_ctx *js_ctx) {
 	duk_context *ctx = (duk_context *) js_ctx->thr;
 	duk_hobject *h;
 	duk_uarridx_t i, arr_len;
@@ -20270,7 +33030,7 @@ static void duk__dec_reviver_walk(duk_json_dec_ctx *js_ctx) {
 				                     (duk_tval *) duk_get_tval(ctx, -3), (duk_tval *) duk_get_tval(ctx, -2),
 				                     (duk_tval *) duk_get_tval(ctx, -1)));
 
-				/* FIXME: push_uint_string / push_u32_string */
+				/* XXX: push_uint_string / push_u32_string */
 				duk_dup_top(ctx);
 				duk_push_uint(ctx, (duk_uint_t) i);
 				duk_to_string(ctx, -1);  /* -> [ ... holder name val val ToString(i) ] */
@@ -20280,7 +33040,7 @@ static void duk__dec_reviver_walk(duk_json_dec_ctx *js_ctx) {
 					duk_pop(ctx);
 					duk_del_prop_index(ctx, -1, i);
 				} else {
-					/* XXX: duk_def_prop_index_wec() would be more appropriate
+					/* XXX: duk_xdef_prop_index_wec() would be more appropriate
 					 * here but it currently makes some assumptions that might
 					 * not hold (e.g. that previous property is not an accessor).
 					 */
@@ -20308,7 +33068,7 @@ static void duk__dec_reviver_walk(duk_json_dec_ctx *js_ctx) {
 					duk_pop(ctx);
 					duk_del_prop(ctx, -3);
 				} else {
-					/* XXX: duk_def_prop_index_wec() would be more appropriate
+					/* XXX: duk_xdef_prop_index_wec() would be more appropriate
 					 * here but it currently makes some assumptions that might
 					 * not hold (e.g. that previous property is not an accessor).
 					 *
@@ -20339,36 +33099,65 @@ static void duk__dec_reviver_walk(duk_json_dec_ctx *js_ctx) {
  */
 
 #define DUK__EMIT_1(js_ctx,ch)          duk__emit_1((js_ctx), (duk_uint_fast8_t) (ch))
-#define DUK__EMIT_2(js_ctx,ch1,ch2)     duk__emit_2((js_ctx), (((duk_uint_fast16_t)(ch1)) << 8) + (duk_uint_fast16_t)(ch2))
-#define DUK__EMIT_ESC_AUTO(js_ctx,cp)   duk__emit_esc_auto((js_ctx), (cp))
-#define DUK__EMIT_XUTF8(js_ctx,cp)      duk__emit_xutf8((js_ctx), (cp))
+#define DUK__EMIT_2(js_ctx,ch1,ch2)     duk__emit_2((js_ctx), (duk_uint_fast8_t) (ch1), (duk_uint_fast8_t) (ch2))
 #define DUK__EMIT_HSTR(js_ctx,h)        duk__emit_hstring((js_ctx), (h))
-#if defined(DUK_USE_JX) || defined(DUK_USE_JC)
+#if defined(DUK_USE_FASTINT) || defined(DUK_USE_JX) || defined(DUK_USE_JC)
 #define DUK__EMIT_CSTR(js_ctx,p)        duk__emit_cstring((js_ctx), (p))
 #endif
 #define DUK__EMIT_STRIDX(js_ctx,i)      duk__emit_stridx((js_ctx), (i))
+#if defined(DUK_USE_JSON_STRINGIFY_FASTPATH)
+#define DUK__UNEMIT_1(js_ctx)           duk__unemit_1((js_ctx))
+#endif
 
-static void duk__emit_1(duk_json_enc_ctx *js_ctx, duk_uint_fast8_t ch) {
-	duk_hbuffer_append_byte(js_ctx->thr, js_ctx->h_buf, (duk_uint8_t) ch);
+DUK_LOCAL void duk__emit_1(duk_json_enc_ctx *js_ctx, duk_uint_fast8_t ch) {
+	DUK_BW_WRITE_ENSURE_U8(js_ctx->thr, &js_ctx->bw, ch);
 }
 
-static void duk__emit_2(duk_json_enc_ctx *js_ctx, duk_uint_fast16_t packed_chars) {
-	duk_uint8_t buf[2];
-	buf[0] = (duk_uint8_t) (packed_chars >> 8);
-	buf[1] = (duk_uint8_t) (packed_chars & 0xff);
-	duk_hbuffer_append_bytes(js_ctx->thr, js_ctx->h_buf, (duk_uint8_t *) buf, 2);
+DUK_LOCAL void duk__emit_2(duk_json_enc_ctx *js_ctx, duk_uint_fast8_t ch1, duk_uint_fast8_t ch2) {
+	DUK_BW_WRITE_ENSURE_U8_2(js_ctx->thr, &js_ctx->bw, ch1, ch2);
+}
+
+DUK_LOCAL void duk__emit_hstring(duk_json_enc_ctx *js_ctx, duk_hstring *h) {
+	DUK_BW_WRITE_ENSURE_HSTRING(js_ctx->thr, &js_ctx->bw, h);
+}
+
+#if defined(DUK_USE_FASTINT) || defined(DUK_USE_JX) || defined(DUK_USE_JC)
+DUK_LOCAL void duk__emit_cstring(duk_json_enc_ctx *js_ctx, const char *str) {
+	DUK_BW_WRITE_ENSURE_CSTRING(js_ctx->thr, &js_ctx->bw, str);
 }
+#endif
+
+DUK_LOCAL void duk__emit_stridx(duk_json_enc_ctx *js_ctx, duk_small_uint_t stridx) {
+	duk_hstring *h;
+
+	DUK_ASSERT_DISABLE(stridx >= 0);  /* unsigned */
+	DUK_ASSERT(stridx < DUK_HEAP_NUM_STRINGS);
+	h = DUK_HTHREAD_GET_STRING(js_ctx->thr, stridx);
+	DUK_ASSERT(h != NULL);
+
+	DUK_BW_WRITE_ENSURE_HSTRING(js_ctx->thr, &js_ctx->bw, h);
+}
+
+#if defined(DUK_USE_JSON_STRINGIFY_FASTPATH)
+DUK_LOCAL void duk__unemit_1(duk_json_enc_ctx *js_ctx) {
+	DUK_ASSERT(DUK_BW_GET_SIZE(js_ctx->thr, &js_ctx->bw) >= 1);
+	DUK_BW_ADD_PTR(js_ctx->thr, &js_ctx->bw, -1);
+}
+#endif  /* DUK_USE_JSON_STRINGIFY_FASTPATH */
 
 #define DUK__MKESC(nybbles,esc1,esc2)  \
 	(((duk_uint_fast32_t) (nybbles)) << 16) | \
 	(((duk_uint_fast32_t) (esc1)) << 8) | \
 	((duk_uint_fast32_t) (esc2))
 
-static void duk__emit_esc_auto(duk_json_enc_ctx *js_ctx, duk_uint_fast32_t cp) {
-	duk_uint8_t buf[2];
+DUK_LOCAL duk_uint8_t *duk__emit_esc_auto_fast(duk_json_enc_ctx *js_ctx, duk_uint_fast32_t cp, duk_uint8_t *q) {
 	duk_uint_fast32_t tmp;
 	duk_small_uint_t dig;
 
+	DUK_UNREF(js_ctx);
+
+	/* Caller ensures space for at least DUK__JSON_MAX_ESC_LEN. */
+
 	/* Select appropriate escape format automatically, and set 'tmp' to a
 	 * value encoding both the escape format character and the nybble count:
 	 *
@@ -20402,46 +33191,22 @@ static void duk__emit_esc_auto(duk_json_enc_ctx *js_ctx, duk_uint_fast32_t cp) {
 		}
 	}
 
-	buf[0] = (duk_uint8_t) ((tmp >> 8) & 0xff);
-	buf[1] = (duk_uint8_t) (tmp & 0xff);
-	duk_hbuffer_append_bytes(js_ctx->thr, js_ctx->h_buf, buf, 2);
+	*q++ = (duk_uint8_t) ((tmp >> 8) & 0xff);
+	*q++ = (duk_uint8_t) (tmp & 0xff);
 
 	tmp = tmp >> 16;
 	while (tmp > 0) {
 		tmp--;
 		dig = (duk_small_uint_t) ((cp >> (4 * tmp)) & 0x0f);
-		duk_hbuffer_append_byte(js_ctx->thr, js_ctx->h_buf, duk_lc_digits[dig]);
+		*q++ = duk_lc_digits[dig];
 	}
-}
 
-static void duk__emit_xutf8(duk_json_enc_ctx *js_ctx, duk_uint_fast32_t cp) {
-	(void) duk_hbuffer_append_xutf8(js_ctx->thr, js_ctx->h_buf, cp);
-}
-
-static void duk__emit_hstring(duk_json_enc_ctx *js_ctx, duk_hstring *h) {
-	DUK_ASSERT(h != NULL);
-	duk_hbuffer_append_bytes(js_ctx->thr,
-	                         js_ctx->h_buf,
-	                         (duk_uint8_t *) DUK_HSTRING_GET_DATA(h),
-	                         (duk_size_t) DUK_HSTRING_GET_BYTELEN(h));
-}
-
-#if defined(DUK_USE_JX) || defined(DUK_USE_JC)
-static void duk__emit_cstring(duk_json_enc_ctx *js_ctx, const char *p) {
-	DUK_ASSERT(p != NULL);
-	(void) duk_hbuffer_append_cstring(js_ctx->thr, js_ctx->h_buf, p);
-}
-#endif
-
-static void duk__emit_stridx(duk_json_enc_ctx *js_ctx, duk_small_uint_t stridx) {
-	DUK_ASSERT_DISABLE(stridx >= 0);  /* unsigned */
-	DUK_ASSERT(stridx < DUK_HEAP_NUM_STRINGS);
-	duk__emit_hstring(js_ctx, DUK_HTHREAD_GET_STRING(js_ctx->thr, stridx));
+	return q;
 }
 
 /* Check whether key quotes would be needed (custom encoding). */
-static duk_bool_t duk__enc_key_quotes_needed(duk_hstring *h_key) {
-	duk_uint8_t *p, *p_start, *p_end;
+DUK_LOCAL duk_bool_t duk__enc_key_quotes_needed(duk_hstring *h_key) {
+	const duk_uint8_t *p, *p_start, *p_end;
 	duk_small_uint_t ch;
 
 	DUK_ASSERT(h_key != NULL);
@@ -20450,7 +33215,8 @@ static duk_bool_t duk__enc_key_quotes_needed(duk_hstring *h_key) {
 	p = p_start;
 
 	DUK_DDD(DUK_DDDPRINT("duk__enc_key_quotes_needed: h_key=%!O, p_start=%p, p_end=%p, p=%p",
-	                     (duk_heaphdr *) h_key, (void *) p_start, (void *) p_end, (void *) p));
+	                     (duk_heaphdr *) h_key, (const void *) p_start,
+	                     (const void *) p_end, (const void *) p));
 
 	/* Since we only accept ASCII characters, there is no need for
 	 * actual decoding.  A non-ASCII character will be >= 0x80 which
@@ -20481,21 +33247,26 @@ static duk_bool_t duk__enc_key_quotes_needed(duk_hstring *h_key) {
 	return 0;
 }
 
+DUK_LOCAL void duk__enc_key_autoquote(duk_json_enc_ctx *js_ctx, duk_hstring *k) {
+	/* XXX: could reimplement so that we start emitting the key without
+	 * quotes and backtrack if we hit a problem character.
+	 */
+	if (js_ctx->flag_avoid_key_quotes && !duk__enc_key_quotes_needed(k)) {
+		DUK__EMIT_HSTR(js_ctx, k);
+	} else {
+		duk__enc_quote_string(js_ctx, k);
+	}
+}
+
 /* The Quote(value) operation: quote a string.
  *
  * Stack policy: [ ] -> [ ].
  */
 
-static duk_uint8_t duk__quote_esc[14] = {
-	DUK_ASC_NUL, DUK_ASC_NUL, DUK_ASC_NUL, DUK_ASC_NUL,
-	DUK_ASC_NUL, DUK_ASC_NUL, DUK_ASC_NUL, DUK_ASC_NUL,
-	DUK_ASC_LC_B, DUK_ASC_LC_T, DUK_ASC_LC_N, DUK_ASC_NUL,
-	DUK_ASC_LC_F, DUK_ASC_LC_R
-};
-
-static void duk__enc_quote_string(duk_json_enc_ctx *js_ctx, duk_hstring *h_str) {
+DUK_LOCAL void duk__enc_quote_string(duk_json_enc_ctx *js_ctx, duk_hstring *h_str) {
 	duk_hthread *thr = js_ctx->thr;
-	duk_uint8_t *p, *p_start, *p_end, *p_tmp;
+	const duk_uint8_t *p, *p_start, *p_end, *p_now, *p_tmp;
+	duk_uint8_t *q;
 	duk_ucodepoint_t cp;  /* typed for duk_unicode_decode_xutf8() */
 
 	DUK_DDD(DUK_DDDPRINT("duk__enc_quote_string: h_str=%!O", (duk_heaphdr *) h_str));
@@ -20507,93 +33278,517 @@ static void duk__enc_quote_string(duk_json_enc_ctx *js_ctx, duk_hstring *h_str)
 
 	DUK__EMIT_1(js_ctx, DUK_ASC_DOUBLEQUOTE);
 
+	/* Encode string in small chunks, estimating the maximum expansion so that
+	 * there's no need to ensure space while processing the chunk.
+	 */
+
 	while (p < p_end) {
-		cp = *p;
+		duk_size_t left, now, space;
 
-		if (DUK_LIKELY(cp <= 0x7f)) {
-			/* ascii fast path: avoid decoding utf-8 */
-			p++;
-			if (cp == 0x22 || cp == 0x5c) {
-				/* double quote or backslash */
-				DUK__EMIT_2(js_ctx, DUK_ASC_BACKSLASH, cp);
-			} else if (cp < 0x20) {
-				duk_uint_fast8_t esc_char;
-
-				/* This approach is a bit shorter than a straight
-				 * if-else-ladder and also a bit faster.
-				 */
-				if (cp < (sizeof(duk__quote_esc) / sizeof(duk_uint8_t)) &&
-				    (esc_char = duk__quote_esc[cp]) != 0) {
-					DUK__EMIT_2(js_ctx, DUK_ASC_BACKSLASH, esc_char);
+		left = (duk_size_t) (p_end - p);
+		now = (left > DUK__JSON_ENCSTR_CHUNKSIZE ?
+		       DUK__JSON_ENCSTR_CHUNKSIZE : left);
+
+		/* Maximum expansion per input byte is 6:
+		 *   - invalid UTF-8 byte causes "\uXXXX" to be emitted (6/1 = 6).
+		 *   - 2-byte UTF-8 encodes as "\uXXXX" (6/2 = 3).
+		 *   - 4-byte UTF-8 encodes as "\Uxxxxxxxx" (10/4 = 2.5).
+		 */
+		space = now * 6;
+		q = DUK_BW_ENSURE_GETPTR(thr, &js_ctx->bw, space);
+
+		p_now = p + now;
+
+		while (p < p_now) {
+#if defined(DUK_USE_JSON_QUOTESTRING_FASTPATH)
+			duk_uint8_t b;
+
+			b = duk__json_quotestr_lookup[*p++];
+			if (DUK_LIKELY(b < 0x80)) {
+				/* Most input bytes go through here. */
+				*q++ = b;
+			} else if (b >= 0xa0) {
+				*q++ = DUK_ASC_BACKSLASH;
+				*q++ = (duk_uint8_t) (b - 0x80);
+			} else if (b == 0x80) {
+				cp = (duk_ucodepoint_t) (*(p - 1));
+				q = duk__emit_esc_auto_fast(js_ctx, cp, q);
+			} else if (b == 0x7f && js_ctx->flag_ascii_only) {
+				/* 0x7F is special */
+				DUK_ASSERT(b == 0x81);
+				cp = (duk_ucodepoint_t) 0x7f;
+				q = duk__emit_esc_auto_fast(js_ctx, cp, q);
+			} else {
+				DUK_ASSERT(b == 0x81);
+				p--;
+
+				/* slow path is shared */
+#else  /* DUK_USE_JSON_QUOTESTRING_FASTPATH */
+			cp = *p;
+
+			if (DUK_LIKELY(cp <= 0x7f)) {
+				/* ascii fast path: avoid decoding utf-8 */
+				p++;
+				if (cp == 0x22 || cp == 0x5c) {
+					/* double quote or backslash */
+					*q++ = DUK_ASC_BACKSLASH;
+					*q++ = (duk_uint8_t) cp;
+				} else if (cp < 0x20) {
+					duk_uint_fast8_t esc_char;
+
+					/* This approach is a bit shorter than a straight
+					 * if-else-ladder and also a bit faster.
+					 */
+					if (cp < (sizeof(duk__json_quotestr_esc) / sizeof(duk_uint8_t)) &&
+					    (esc_char = duk__json_quotestr_esc[cp]) != 0) {
+						*q++ = DUK_ASC_BACKSLASH;
+						*q++ = (duk_uint8_t) esc_char;
+					} else {
+						q = duk__emit_esc_auto_fast(js_ctx, cp, q);
+					}
+				} else if (cp == 0x7f && js_ctx->flag_ascii_only) {
+					q = duk__emit_esc_auto_fast(js_ctx, cp, q);
 				} else {
-					DUK__EMIT_ESC_AUTO(js_ctx, cp);
+					/* any other printable -> as is */
+					*q++ = (duk_uint8_t) cp;
 				}
-			} else if (cp == 0x7f && js_ctx->flag_ascii_only) {
-				DUK__EMIT_ESC_AUTO(js_ctx, cp);
 			} else {
-				/* any other printable -> as is */
-				DUK__EMIT_1(js_ctx, cp);
-			}
-		} else {
-			/* slow path decode */
-
-			/* If XUTF-8 decoding fails, treat the offending byte as a codepoint directly
-			 * and go forward one byte.  This is of course very lossy, but allows some kind
-			 * of output to be produced even for internal strings which don't conform to
-			 * XUTF-8.  All standard Ecmascript strings are always CESU-8, so this behavior
-			 * does not violate the Ecmascript specification.  The behavior is applied to
-			 * all modes, including Ecmascript standard JSON.  Because the current XUTF-8
-			 * decoding is not very strict, this behavior only really affects initial bytes
-			 * and truncated codepoints.
-			 *
-			 * XXX: another alternative would be to scan forwards to start of next codepoint
-			 * (or end of input) and emit just one replacement codepoint.
-			 */
+				/* slow path is shared */
+#endif  /* DUK_USE_JSON_QUOTESTRING_FASTPATH */
+
+				/* slow path decode */
+
+				/* If XUTF-8 decoding fails, treat the offending byte as a codepoint directly
+				 * and go forward one byte.  This is of course very lossy, but allows some kind
+				 * of output to be produced even for internal strings which don't conform to
+				 * XUTF-8.  All standard Ecmascript strings are always CESU-8, so this behavior
+				 * does not violate the Ecmascript specification.  The behavior is applied to
+				 * all modes, including Ecmascript standard JSON.  Because the current XUTF-8
+				 * decoding is not very strict, this behavior only really affects initial bytes
+				 * and truncated codepoints.
+				 *
+				 * Another alternative would be to scan forwards to start of next codepoint
+				 * (or end of input) and emit just one replacement codepoint.
+				 */
 
-			p_tmp = p;
-			if (!duk_unicode_decode_xutf8(thr, &p, p_start, p_end, &cp)) {
-				/* Decode failed. */
-				cp = *p_tmp;
-				p = p_tmp + 1;
-			}
+				p_tmp = p;
+				if (!duk_unicode_decode_xutf8(thr, &p, p_start, p_end, &cp)) {
+					/* Decode failed. */
+					cp = *p_tmp;
+					p = p_tmp + 1;
+				}
 
-			if (js_ctx->flag_ascii_only) {
-				DUK__EMIT_ESC_AUTO(js_ctx, cp);
-			} else {
-				/* as is */
-				DUK__EMIT_XUTF8(js_ctx, cp);
+#ifdef DUK_USE_NONSTD_JSON_ESC_U2028_U2029
+				if (js_ctx->flag_ascii_only || cp == 0x2028 || cp == 0x2029) {
+#else
+				if (js_ctx->flag_ascii_only) {
+#endif
+					q = duk__emit_esc_auto_fast(js_ctx, cp, q);
+				} else {
+					/* as is */
+					DUK_RAW_WRITE_XUTF8(q, cp);
+				}
 			}
 		}
+
+		DUK_BW_SET_PTR(thr, &js_ctx->bw, q);
 	}
 
 	DUK__EMIT_1(js_ctx, DUK_ASC_DOUBLEQUOTE);
 }
 
-/* Shared entry handling for object/array serialization: indent/stepback,
- * loop detection.
+/* Encode a double (checked by caller) from stack top.  Stack top may be
+ * replaced by serialized string but is not popped (caller does that).
+ */
+DUK_LOCAL void duk__enc_double(duk_json_enc_ctx *js_ctx) {
+	duk_context *ctx;
+	duk_tval *tv;
+	duk_double_t d;
+	duk_small_int_t c;
+	duk_small_int_t s;
+	duk_small_uint_t stridx;
+	duk_small_uint_t n2s_flags;
+	duk_hstring *h_str;
+
+	DUK_ASSERT(js_ctx != NULL);
+	ctx = (duk_context *) js_ctx->thr;
+	DUK_ASSERT(ctx != NULL);
+
+	/* Caller must ensure 'tv' is indeed a double and not a fastint! */
+	tv = duk_get_tval(ctx, -1);
+	DUK_ASSERT(tv != NULL);
+	DUK_ASSERT(DUK_TVAL_IS_DOUBLE(tv));
+	d = DUK_TVAL_GET_DOUBLE(tv);
+
+	c = (duk_small_int_t) DUK_FPCLASSIFY(d);
+	s = (duk_small_int_t) DUK_SIGNBIT(d);
+	DUK_UNREF(s);
+
+	if (DUK_LIKELY(!(c == DUK_FP_INFINITE || c == DUK_FP_NAN))) {
+		DUK_ASSERT(DUK_ISFINITE(d));
+
+#if defined(DUK_USE_JX) || defined(DUK_USE_JC)
+		/* Negative zero needs special handling in JX/JC because
+		 * it would otherwise serialize to '0', not '-0'.
+		 */
+		if (DUK_UNLIKELY(c == DUK_FP_ZERO && s != 0 &&
+		                 (js_ctx->flag_ext_custom_or_compatible))) {
+			duk_push_hstring_stridx(ctx, DUK_STRIDX_MINUS_ZERO);  /* '-0' */
+		} else
+#endif  /* DUK_USE_JX || DUK_USE_JC */
+		{
+			n2s_flags = 0;
+			/* [ ... number ] -> [ ... string ] */
+			duk_numconv_stringify(ctx, 10 /*radix*/, 0 /*digits*/, n2s_flags);
+		}
+		h_str = duk_to_hstring(ctx, -1);
+		DUK_ASSERT(h_str != NULL);
+		DUK__EMIT_HSTR(js_ctx, h_str);
+		return;
+	}
+
+#if defined(DUK_USE_JX) || defined(DUK_USE_JC)
+	if (!(js_ctx->flags & (DUK_JSON_FLAG_EXT_CUSTOM |
+	                       DUK_JSON_FLAG_EXT_COMPATIBLE))) {
+		stridx = DUK_STRIDX_LC_NULL;
+	} else if (c == DUK_FP_NAN) {
+		stridx = js_ctx->stridx_custom_nan;
+	} else if (s == 0) {
+		stridx = js_ctx->stridx_custom_posinf;
+	} else {
+		stridx = js_ctx->stridx_custom_neginf;
+	}
+#else
+	stridx = DUK_STRIDX_LC_NULL;
+#endif
+	DUK__EMIT_STRIDX(js_ctx, stridx);
+}
+
+#if defined(DUK_USE_FASTINT)
+/* Encode a fastint from duk_tval ptr, no value stack effects. */
+DUK_LOCAL void duk__enc_fastint_tval(duk_json_enc_ctx *js_ctx, duk_tval *tv) {
+	duk_int64_t v;
+
+	/* Fastint range is signed 48-bit so longest value is -2^47 = -140737488355328
+	 * (16 chars long), longest signed 64-bit value is -2^63 = -9223372036854775808
+	 * (20 chars long).  Alloc space for 64-bit range to be safe.
+	 */
+	duk_uint8_t buf[20 + 1];
+
+	/* Caller must ensure 'tv' is indeed a fastint! */
+	DUK_ASSERT(DUK_TVAL_IS_FASTINT(tv));
+	v = DUK_TVAL_GET_FASTINT(tv);
+
+	/* XXX: There are no format strings in duk_config.h yet, could add
+	 * one for formatting duk_int64_t.  For now, assumes "%lld" and that
+	 * "long long" type exists.  Could also rely on C99 directly but that
+	 * won't work for older MSVC.
+	 */
+	DUK_SPRINTF((char *) buf, "%lld", (long long) v);
+	DUK__EMIT_CSTR(js_ctx, (const char *) buf);
+}
+#endif
+
+#if defined(DUK_USE_JX) || defined(DUK_USE_JC)
+#if defined(DUK_USE_HEX_FASTPATH)
+DUK_LOCAL duk_uint8_t *duk__enc_buffer_data_hex(const duk_uint8_t *src, duk_size_t src_len, duk_uint8_t *dst) {
+	duk_uint8_t *q;
+	duk_uint16_t *q16;
+	duk_small_uint_t x;
+	duk_size_t i, len_safe;
+#if !defined(DUK_USE_UNALIGNED_ACCESSES_POSSIBLE)
+	duk_bool_t shift_dst;
+#endif
+
+	/* Unlike in duk_hex_encode() 'dst' is not necessarily aligned by 2.
+	 * For platforms where unaligned accesses are not allowed, shift 'dst'
+	 * ahead by 1 byte to get alignment and then DUK_MEMMOVE() the result
+	 * in place.  The faster encoding loop makes up the difference.
+	 * There's always space for one extra byte because a terminator always
+	 * follows the hex data and that's been accounted for by the caller.
+	 */
+
+#if defined(DUK_USE_UNALIGNED_ACCESSES_POSSIBLE)
+	q16 = (duk_uint16_t *) (void *) dst;
+#else
+	shift_dst = (duk_bool_t) (((duk_uintptr_t) dst) & 0x01U);
+	if (shift_dst) {
+		DUK_DD(DUK_DDPRINT("unaligned accesses not possible, dst not aligned -> step to dst + 1"));
+		q16 = (duk_uint16_t *) (void *) (dst + 1);
+	} else {
+		DUK_DD(DUK_DDPRINT("unaligned accesses not possible, dst is aligned"));
+		q16 = (duk_uint16_t *) (void *) dst;
+	}
+	DUK_ASSERT((((duk_uintptr_t) q16) & 0x01U) == 0);
+#endif
+
+	len_safe = src_len & ~0x03U;
+	for (i = 0; i < len_safe; i += 4) {
+		q16[0] = duk_hex_enctab[src[i]];
+		q16[1] = duk_hex_enctab[src[i + 1]];
+		q16[2] = duk_hex_enctab[src[i + 2]];
+		q16[3] = duk_hex_enctab[src[i + 3]];
+		q16 += 4;
+	}
+	q = (duk_uint8_t *) q16;
+
+#if !defined(DUK_USE_UNALIGNED_ACCESSES_POSSIBLE)
+	if (shift_dst) {
+		q--;
+		DUK_MEMMOVE((void *) dst, (const void *) (dst + 1), 2 * len_safe);
+		DUK_ASSERT(dst + 2 * len_safe == q);
+	}
+#endif
+
+	for (; i < src_len; i++) {
+		x = src[i];
+		*q++ = duk_lc_digits[x >> 4];
+		*q++ = duk_lc_digits[x & 0x0f];
+	}
+
+	return q;
+}
+#else  /* DUK_USE_HEX_FASTPATH */
+DUK_LOCAL duk_uint8_t *duk__enc_buffer_data_hex(const duk_uint8_t *src, duk_size_t src_len, duk_uint8_t *dst) {
+	const duk_uint8_t *p;
+	const duk_uint8_t *p_end;
+	duk_uint8_t *q;
+	duk_small_uint_t x;
+
+	p = src;
+	p_end = src + src_len;
+	q = dst;
+	while (p != p_end) {
+		x = *p++;
+		*q++ = duk_lc_digits[x >> 4];
+		*q++ = duk_lc_digits[x & 0x0f];
+	}
+
+	return q;
+}
+#endif  /* DUK_USE_HEX_FASTPATH */
+
+DUK_LOCAL void duk__enc_buffer_data(duk_json_enc_ctx *js_ctx, duk_uint8_t *buf_data, duk_size_t buf_len) {
+	duk_hthread *thr;
+	duk_uint8_t *q;
+	duk_size_t space;
+
+	thr = js_ctx->thr;
+
+	DUK_ASSERT(js_ctx->flag_ext_custom || js_ctx->flag_ext_compatible);  /* caller checks */
+	DUK_ASSERT(js_ctx->flag_ext_custom_or_compatible);
+
+	/* Buffer values are encoded in (lowercase) hex to make the
+	 * binary data readable.  Base64 or similar would be more
+	 * compact but less readable, and the point of JX/JC
+	 * variants is to be as useful to a programmer as possible.
+	 */
+
+	/* The #ifdef clutter here needs to handle the three cases:
+	 * (1) JX+JC, (2) JX only, (3) JC only.
+	 */
+
+	/* Note: space must cater for both JX and JC. */
+	space = 9 + buf_len * 2 + 2;
+	DUK_ASSERT(DUK_HBUFFER_MAX_BYTELEN <= 0x7ffffffeUL);
+	DUK_ASSERT((space - 2) / 2 >= buf_len);  /* overflow not possible, buffer limits */
+	q = DUK_BW_ENSURE_GETPTR(thr, &js_ctx->bw, space);
+
+#if defined(DUK_USE_JX) && defined(DUK_USE_JC)
+	if (js_ctx->flag_ext_custom)
+#endif
+#if defined(DUK_USE_JX)
+	{
+		*q++ = DUK_ASC_PIPE;
+		q = duk__enc_buffer_data_hex(buf_data, buf_len, q);
+		*q++ = DUK_ASC_PIPE;
+
+	}
+#endif
+#if defined(DUK_USE_JX) && defined(DUK_USE_JC)
+	else
+#endif
+#if defined(DUK_USE_JC)
+	{
+		DUK_ASSERT(js_ctx->flag_ext_compatible);
+		DUK_MEMCPY((void *) q, (const void *) "{\"_buf\":\"", 9);  /* len: 9 */
+		q += 9;
+		q = duk__enc_buffer_data_hex(buf_data, buf_len, q);
+		*q++ = DUK_ASC_DOUBLEQUOTE;
+		*q++ = DUK_ASC_RCURLY;
+	}
+#endif
+
+	DUK_BW_SET_PTR(thr, &js_ctx->bw, q);
+}
+
+DUK_LOCAL void duk__enc_buffer(duk_json_enc_ctx *js_ctx, duk_hbuffer *h) {
+	duk__enc_buffer_data(js_ctx,
+	                     (duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(js_ctx->thr->heap, h),
+	                     (duk_size_t) DUK_HBUFFER_GET_SIZE(h));
+}
+#endif  /* DUK_USE_JX || DUK_USE_JC */
+
+#if defined(DUK_USE_JX) || defined(DUK_USE_JC)
+DUK_LOCAL void duk__enc_pointer(duk_json_enc_ctx *js_ctx, void *ptr) {
+	char buf[64];  /* XXX: how to figure correct size? */
+	const char *fmt;
+
+	DUK_ASSERT(js_ctx->flag_ext_custom || js_ctx->flag_ext_compatible);  /* caller checks */
+	DUK_ASSERT(js_ctx->flag_ext_custom_or_compatible);
+
+	DUK_MEMZERO(buf, sizeof(buf));
+
+	/* The #ifdef clutter here needs to handle the three cases:
+	 * (1) JX+JC, (2) JX only, (3) JC only.
+	 */
+#if defined(DUK_USE_JX) && defined(DUK_USE_JC)
+	if (js_ctx->flag_ext_custom)
+#endif
+#if defined(DUK_USE_JX)
+	{
+		fmt = ptr ? "(%p)" : "(null)";
+	}
+#endif
+#if defined(DUK_USE_JX) && defined(DUK_USE_JC)
+	else
+#endif
+#if defined(DUK_USE_JC)
+	{
+		DUK_ASSERT(js_ctx->flag_ext_compatible);
+		fmt = ptr ? "{\"_ptr\":\"%p\"}" : "{\"_ptr\":\"null\"}";
+	}
+#endif
+
+	/* When ptr == NULL, the format argument is unused. */
+	DUK_SNPRINTF(buf, sizeof(buf) - 1, fmt, ptr);  /* must not truncate */
+	DUK__EMIT_CSTR(js_ctx, buf);
+}
+#endif  /* DUK_USE_JX || DUK_USE_JC */
+
+#if defined(DUK_USE_JX) || defined(DUK_USE_JC)
+#if defined(DUK_USE_JSON_STRINGIFY_FASTPATH)
+DUK_LOCAL void duk__enc_bufferobject(duk_json_enc_ctx *js_ctx, duk_hbufferobject *h_bufobj) {
+	DUK_ASSERT_HBUFFEROBJECT_VALID(h_bufobj);
+
+	if (h_bufobj->buf == NULL || !DUK_HBUFFEROBJECT_VALID_SLICE(h_bufobj)) {
+		DUK__EMIT_STRIDX(js_ctx, DUK_STRIDX_LC_NULL);
+	} else {
+		/* Handle both full and partial slice (as long as covered). */
+		duk__enc_buffer_data(js_ctx,
+		                     (duk_uint8_t *) DUK_HBUFFEROBJECT_GET_SLICE_BASE(js_ctx->thr->heap, h_bufobj),
+		                     (duk_size_t) h_bufobj->length);
+	}
+}
+#endif  /* DUK_USE_JSON_STRINGIFY_FASTPATH */
+#endif  /* DUK_USE_JX || DUK_USE_JC */
+
+/* Indent helper.  Calling code relies on js_ctx->recursion_depth also being
+ * directly related to indent depth.
  */
-static void duk__enc_objarr_entry(duk_json_enc_ctx *js_ctx, duk_hstring **h_stepback, duk_hstring **h_indent, duk_idx_t *entry_top) {
+#if defined(DUK_USE_PREFER_SIZE)
+DUK_LOCAL void duk__enc_newline_indent(duk_json_enc_ctx *js_ctx, duk_int_t depth) {
+	DUK_ASSERT(js_ctx->h_gap != NULL);
+	DUK_ASSERT(DUK_HSTRING_GET_BYTELEN(js_ctx->h_gap) > 0);  /* caller guarantees */
+
+	DUK__EMIT_1(js_ctx, 0x0a);
+	while (depth-- > 0) {
+		DUK__EMIT_HSTR(js_ctx, js_ctx->h_gap);
+	}
+}
+#else  /* DUK_USE_PREFER_SIZE */
+DUK_LOCAL void duk__enc_newline_indent(duk_json_enc_ctx *js_ctx, duk_int_t depth) {
+	const duk_uint8_t *gap_data;
+	duk_size_t gap_len;
+	duk_size_t avail_bytes;   /* bytes of indent available for copying */
+	duk_size_t need_bytes;    /* bytes of indent still needed */
+	duk_uint8_t *p_start;
+	duk_uint8_t *p;
+
+	DUK_ASSERT(js_ctx->h_gap != NULL);
+	DUK_ASSERT(DUK_HSTRING_GET_BYTELEN(js_ctx->h_gap) > 0);  /* caller guarantees */
+
+	DUK__EMIT_1(js_ctx, 0x0a);
+	if (DUK_UNLIKELY(depth == 0)) {
+		return;
+	}
+
+	/* To handle deeper indents efficiently, make use of copies we've
+	 * already emitted.  In effect we can emit a sequence of 1, 2, 4,
+	 * 8, etc copies, and then finish the last run.  Byte counters
+	 * avoid multiply with gap_len on every loop.
+	 */
+
+	gap_data = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(js_ctx->h_gap);
+	gap_len = (duk_size_t) DUK_HSTRING_GET_BYTELEN(js_ctx->h_gap);
+	DUK_ASSERT(gap_len > 0);
+
+	need_bytes = gap_len * depth;
+	p = DUK_BW_ENSURE_GETPTR(js_ctx->thr, &js_ctx->bw, need_bytes);
+	p_start = p;
+
+	DUK_MEMCPY((void *) p, (const void *) gap_data, (size_t) gap_len);
+	p += gap_len;
+	avail_bytes = gap_len;
+	DUK_ASSERT(need_bytes >= gap_len);
+	need_bytes -= gap_len;
+
+	while (need_bytes >= avail_bytes) {
+		DUK_MEMCPY((void *) p, (const void *) p_start, (size_t) avail_bytes);
+		p += avail_bytes;
+		need_bytes -= avail_bytes;
+		avail_bytes <<= 1;
+	}
+
+	DUK_ASSERT(need_bytes < avail_bytes);  /* need_bytes may be zero */
+	DUK_MEMCPY((void *) p, (const void *) p_start, (size_t) need_bytes);
+	p += need_bytes;
+	/*avail_bytes += need_bytes*/
+
+	DUK_BW_SET_PTR(js_ctx->thr, &js_ctx->bw, p);
+}
+#endif  /* DUK_USE_PREFER_SIZE */
+
+/* Shared entry handling for object/array serialization. */
+DUK_LOCAL void duk__enc_objarr_entry(duk_json_enc_ctx *js_ctx, duk_idx_t *entry_top) {
 	duk_context *ctx = (duk_context *) js_ctx->thr;
 	duk_hobject *h_target;
+	duk_uint_fast32_t i, n;
 
 	*entry_top = duk_get_top(ctx);
 
 	duk_require_stack(ctx, DUK_JSON_ENC_REQSTACK);
 
-	/* loop check */
+	/* Loop check using a hybrid approach: a fixed-size visited[] array
+	 * with overflow in a loop check object.
+	 */
 
 	h_target = duk_get_hobject(ctx, -1);  /* object or array */
 	DUK_ASSERT(h_target != NULL);
-	duk_push_sprintf(ctx, DUK_STR_FMT_PTR, (void *) h_target);
 
-	duk_dup_top(ctx);  /* -> [ ... voidp voidp ] */
-	if (duk_has_prop(ctx, js_ctx->idx_loop)) {
-		DUK_ERROR((duk_hthread *) ctx, DUK_ERR_TYPE_ERROR, DUK_STR_CYCLIC_INPUT);
+	n = js_ctx->recursion_depth;
+	if (DUK_UNLIKELY(n > DUK_JSON_ENC_LOOPARRAY)) {
+		n = DUK_JSON_ENC_LOOPARRAY;
+	}
+	for (i = 0; i < n; i++) {
+		if (DUK_UNLIKELY(js_ctx->visiting[i] == h_target)) {
+			DUK_DD(DUK_DDPRINT("slow path loop detect"));
+			DUK_ERROR(js_ctx->thr, DUK_ERR_TYPE_ERROR, DUK_STR_CYCLIC_INPUT);
+		}
+	}
+	if (js_ctx->recursion_depth < DUK_JSON_ENC_LOOPARRAY) {
+		js_ctx->visiting[js_ctx->recursion_depth] = h_target;
+	} else {
+		duk_push_sprintf(ctx, DUK_STR_FMT_PTR, (void *) h_target);
+		duk_dup_top(ctx);  /* -> [ ... voidp voidp ] */
+		if (duk_has_prop(ctx, js_ctx->idx_loop)) {
+			DUK_ERROR((duk_hthread *) ctx, DUK_ERR_TYPE_ERROR, DUK_STR_CYCLIC_INPUT);
+		}
+		duk_push_true(ctx);  /* -> [ ... voidp true ] */
+		duk_put_prop(ctx, js_ctx->idx_loop);  /* -> [ ... ] */
 	}
-	duk_push_true(ctx);  /* -> [ ... voidp true ] */
-	duk_put_prop(ctx, js_ctx->idx_loop);  /* -> [ ... ] */
 
-	/* c recursion check */
+	/* C recursion check. */
 
 	DUK_ASSERT(js_ctx->recursion_depth >= 0);
 	DUK_ASSERT(js_ctx->recursion_depth <= js_ctx->recursion_limit);
@@ -20602,70 +33797,34 @@ static void duk__enc_objarr_entry(duk_json_enc_ctx *js_ctx, duk_hstring **h_step
 	}
 	js_ctx->recursion_depth++;
 
-	/* figure out indent and stepback */
-
-	*h_indent = NULL;
-	*h_stepback = NULL;
-	if (js_ctx->h_gap != NULL) {
-		DUK_ASSERT(js_ctx->h_indent != NULL);
-
-		*h_stepback = js_ctx->h_indent;
-		duk_push_hstring(ctx, js_ctx->h_indent);
-		duk_push_hstring(ctx, js_ctx->h_gap);
-		duk_concat(ctx, 2);
-		js_ctx->h_indent = duk_get_hstring(ctx, -1);
-		*h_indent = js_ctx->h_indent;
-		DUK_ASSERT(js_ctx->h_indent != NULL);
-
-		/* The new indent string is left at value stack top, and will
-		 * be popped by the shared exit handler.
-	 	 */
-	} else {
-		DUK_ASSERT(js_ctx->h_indent == NULL);
-	}
-
 	DUK_DDD(DUK_DDDPRINT("shared entry finished: top=%ld, loop=%!T",
 	                     (long) duk_get_top(ctx), (duk_tval *) duk_get_tval(ctx, js_ctx->idx_loop)));
 }
 
 /* Shared exit handling for object/array serialization. */
-static void duk__enc_objarr_exit(duk_json_enc_ctx *js_ctx, duk_hstring **h_stepback, duk_hstring **h_indent, duk_idx_t *entry_top) {
+DUK_LOCAL void duk__enc_objarr_exit(duk_json_enc_ctx *js_ctx, duk_idx_t *entry_top) {
 	duk_context *ctx = (duk_context *) js_ctx->thr;
 	duk_hobject *h_target;
 
-	DUK_UNREF(h_indent);
-
-	if (js_ctx->h_gap != NULL) {
-		DUK_ASSERT(js_ctx->h_indent != NULL);
-		DUK_ASSERT(*h_stepback != NULL);
-		DUK_ASSERT(*h_indent != NULL);
-
-		js_ctx->h_indent = *h_stepback;  /* previous js_ctx->h_indent */
-
-		/* Note: we don't need to pop anything because the duk_set_top()
-		 * at the end will take care of it.
-		 */
-	} else {
-		DUK_ASSERT(js_ctx->h_indent == NULL);
-		DUK_ASSERT(*h_stepback == NULL);
-		DUK_ASSERT(*h_indent == NULL);
-	}
-
-	/* c recursion check */
+	/* C recursion check. */
 
 	DUK_ASSERT(js_ctx->recursion_depth > 0);
 	DUK_ASSERT(js_ctx->recursion_depth <= js_ctx->recursion_limit);
 	js_ctx->recursion_depth--;
 
-	/* loop check */
+	/* Loop check. */
 
 	h_target = duk_get_hobject(ctx, *entry_top - 1);  /* original target at entry_top - 1 */
 	DUK_ASSERT(h_target != NULL);
-	duk_push_sprintf(ctx, DUK_STR_FMT_PTR, (void *) h_target);
 
-	duk_del_prop(ctx, js_ctx->idx_loop);  /* -> [ ... ] */
+	if (js_ctx->recursion_depth < DUK_JSON_ENC_LOOPARRAY) {
+		/* Previous entry was inside visited[], nothing to do. */
+	} else {
+		duk_push_sprintf(ctx, DUK_STR_FMT_PTR, (void *) h_target);
+		duk_del_prop(ctx, js_ctx->idx_loop);  /* -> [ ... ] */
+	}
 
-	/* restore stack top after unbalanced code paths */
+	/* Restore stack top after unbalanced code paths. */
 	duk_set_top(ctx, *entry_top);
 
 	DUK_DDD(DUK_DDDPRINT("shared entry finished: top=%ld, loop=%!T",
@@ -20676,10 +33835,8 @@ static void duk__enc_objarr_exit(duk_json_enc_ctx *js_ctx, duk_hstring **h_stepb
  *
  * Stack policy: [ object ] -> [ object ].
  */
-static void duk__enc_object(duk_json_enc_ctx *js_ctx) {
+DUK_LOCAL void duk__enc_object(duk_json_enc_ctx *js_ctx) {
 	duk_context *ctx = (duk_context *) js_ctx->thr;
-	duk_hstring *h_stepback;
-	duk_hstring *h_indent;
 	duk_hstring *h_key;
 	duk_idx_t entry_top;
 	duk_idx_t idx_obj;
@@ -20690,14 +33847,14 @@ static void duk__enc_object(duk_json_enc_ctx *js_ctx) {
 
 	DUK_DDD(DUK_DDDPRINT("duk__enc_object: obj=%!T", (duk_tval *) duk_get_tval(ctx, -1)));
 
-	duk__enc_objarr_entry(js_ctx, &h_stepback, &h_indent, &entry_top);
+	duk__enc_objarr_entry(js_ctx, &entry_top);
 
 	idx_obj = entry_top - 1;
 
 	if (js_ctx->idx_proplist >= 0) {
 		idx_keys = js_ctx->idx_proplist;
 	} else {
-		/* FIXME: would be nice to enumerate an object at specified index */
+		/* XXX: would be nice to enumerate an object at specified index */
 		duk_dup(ctx, idx_obj);
 		(void) duk_hobject_get_enumerated_keys(ctx, DUK_ENUM_OWN_PROPERTIES_ONLY /*flags*/);  /* [ ... target ] -> [ ... target keys ] */
 		idx_keys = duk_require_normalize_index(ctx, -1);
@@ -20711,7 +33868,7 @@ static void duk__enc_object(duk_json_enc_ctx *js_ctx) {
 
 	DUK__EMIT_1(js_ctx, DUK_ASC_LCURLY);
 
-	/* FIXME: keys is an internal object with all keys to be processed
+	/* XXX: keys is an internal object with all keys to be processed
 	 * in its (gapless) array part.  Because nobody can touch the keys
 	 * object, we could iterate its array part directly (keeping in mind
 	 * that it can be reallocated).
@@ -20741,21 +33898,16 @@ static void duk__enc_object(duk_json_enc_ctx *js_ctx) {
 		} else {
 			DUK__EMIT_1(js_ctx, DUK_ASC_COMMA);
 		}
-		if (h_indent != NULL) {
-			DUK__EMIT_1(js_ctx, 0x0a);
-			DUK__EMIT_HSTR(js_ctx, h_indent);
+		if (js_ctx->h_gap != NULL) {
+			DUK_ASSERT(js_ctx->recursion_depth >= 1);
+			duk__enc_newline_indent(js_ctx, js_ctx->recursion_depth);
 		}
 
 		h_key = duk_get_hstring(ctx, -2);
 		DUK_ASSERT(h_key != NULL);
-		if (js_ctx->flag_avoid_key_quotes && !duk__enc_key_quotes_needed(h_key)) {
-			/* emit key as is */
-			DUK__EMIT_HSTR(js_ctx, h_key);
-		} else {
-			duk__enc_quote_string(js_ctx, h_key);
-		}
+		duk__enc_key_autoquote(js_ctx, h_key);
 
-		if (h_indent != NULL) {
+		if (js_ctx->h_gap != NULL) {
 			DUK__EMIT_2(js_ctx, DUK_ASC_COLON, DUK_ASC_SPACE);
 		} else {
 			DUK__EMIT_1(js_ctx, DUK_ASC_COLON);
@@ -20767,15 +33919,14 @@ static void duk__enc_object(duk_json_enc_ctx *js_ctx) {
 	}
 
 	if (!first) {
-		if (h_stepback != NULL) {
-			DUK_ASSERT(h_indent != NULL);
-			DUK__EMIT_1(js_ctx, 0x0a);
-			DUK__EMIT_HSTR(js_ctx, h_stepback);
+		if (js_ctx->h_gap != NULL) {
+			DUK_ASSERT(js_ctx->recursion_depth >= 1);
+			duk__enc_newline_indent(js_ctx, js_ctx->recursion_depth - 1);
 		}
 	}
 	DUK__EMIT_1(js_ctx, DUK_ASC_RCURLY);
 
-	duk__enc_objarr_exit(js_ctx, &h_stepback, &h_indent, &entry_top);
+	duk__enc_objarr_exit(js_ctx, &entry_top);
 
 	DUK_ASSERT_TOP(ctx, entry_top);
 }
@@ -20784,10 +33935,8 @@ static void duk__enc_object(duk_json_enc_ctx *js_ctx) {
  *
  * Stack policy: [ array ] -> [ array ].
  */
-static void duk__enc_array(duk_json_enc_ctx *js_ctx) {
+DUK_LOCAL void duk__enc_array(duk_json_enc_ctx *js_ctx) {
 	duk_context *ctx = (duk_context *) js_ctx->thr;
-	duk_hstring *h_stepback;
-	duk_hstring *h_indent;
 	duk_idx_t entry_top;
 	duk_idx_t idx_arr;
 	duk_bool_t undef;
@@ -20796,7 +33945,7 @@ static void duk__enc_array(duk_json_enc_ctx *js_ctx) {
 	DUK_DDD(DUK_DDDPRINT("duk__enc_array: array=%!T",
 	                     (duk_tval *) duk_get_tval(ctx, -1)));
 
-	duk__enc_objarr_entry(js_ctx, &h_stepback, &h_indent, &entry_top);
+	duk__enc_objarr_entry(js_ctx, &entry_top);
 
 	idx_arr = entry_top - 1;
 
@@ -20806,19 +33955,19 @@ static void duk__enc_array(duk_json_enc_ctx *js_ctx) {
 
 	arr_len = (duk_uarridx_t) duk_get_length(ctx, idx_arr);
 	for (i = 0; i < arr_len; i++) {
-		DUK_DDD(DUK_DDDPRINT("array entry loop: array=%!T, h_indent=%!O, h_stepback=%!O, index=%ld, arr_len=%ld",
-		                     (duk_tval *) duk_get_tval(ctx, idx_arr), (duk_heaphdr *) h_indent,
-		                     (duk_heaphdr *) h_stepback, (long) i, (long) arr_len));
+		DUK_DDD(DUK_DDDPRINT("array entry loop: array=%!T, index=%ld, arr_len=%ld",
+		                     (duk_tval *) duk_get_tval(ctx, idx_arr),
+		                     (long) i, (long) arr_len));
 
 		if (i > 0) {
 			DUK__EMIT_1(js_ctx, DUK_ASC_COMMA);
 		}
-		if (h_indent != NULL) {
-			DUK__EMIT_1(js_ctx, 0x0a);
-			DUK__EMIT_HSTR(js_ctx, h_indent);
+		if (js_ctx->h_gap != NULL) {
+			DUK_ASSERT(js_ctx->recursion_depth >= 1);
+			duk__enc_newline_indent(js_ctx, js_ctx->recursion_depth);
 		}
 
-		/* FIXME: duk_push_uint_string() */
+		/* XXX: duk_push_uint_string() */
 		duk_push_uint(ctx, (duk_uint_t) i);
 		duk_to_string(ctx, -1);  /* -> [ ... key ] */
 		undef = duk__enc_value1(js_ctx, idx_arr);
@@ -20832,15 +33981,14 @@ static void duk__enc_array(duk_json_enc_ctx *js_ctx) {
 	}
 
 	if (arr_len > 0) {
-		if (h_stepback != NULL) {
-			DUK_ASSERT(h_indent != NULL);
-			DUK__EMIT_1(js_ctx, 0x0a);
-			DUK__EMIT_HSTR(js_ctx, h_stepback);
+		if (js_ctx->h_gap != NULL) {
+			DUK_ASSERT(js_ctx->recursion_depth >= 1);
+			duk__enc_newline_indent(js_ctx, js_ctx->recursion_depth - 1);
 		}
 	}
 	DUK__EMIT_1(js_ctx, DUK_ASC_RBRACKET);
 
-	duk__enc_objarr_exit(js_ctx, &h_stepback, &h_indent, &entry_top);
+	duk__enc_objarr_exit(js_ctx, &entry_top);
 
 	DUK_ASSERT_TOP(ctx, entry_top);
 }
@@ -20855,8 +34003,9 @@ static void duk__enc_array(duk_json_enc_ctx *js_ctx) {
  * Stack policy: [ ... key ] -> [ ... key val ]  if retval == 0.
  *                           -> [ ... ]          if retval != 0.
  */
-static duk_bool_t duk__enc_value1(duk_json_enc_ctx *js_ctx, duk_idx_t idx_holder) {
+DUK_LOCAL duk_bool_t duk__enc_value1(duk_json_enc_ctx *js_ctx, duk_idx_t idx_holder) {
 	duk_context *ctx = (duk_context *) js_ctx->thr;
+	duk_hthread *thr = (duk_hthread *) ctx;
 	duk_hobject *h;
 	duk_tval *tv;
 	duk_small_int_t c;
@@ -20865,15 +34014,18 @@ static duk_bool_t duk__enc_value1(duk_json_enc_ctx *js_ctx, duk_idx_t idx_holder
 	                     (long) idx_holder, (duk_tval *) duk_get_tval(ctx, idx_holder),
 	                     (duk_tval *) duk_get_tval(ctx, -1)));
 
+	DUK_UNREF(thr);
+
 	duk_dup_top(ctx);               /* -> [ ... key key ] */
 	duk_get_prop(ctx, idx_holder);  /* -> [ ... key val ] */
 
 	DUK_DDD(DUK_DDDPRINT("value=%!T", (duk_tval *) duk_get_tval(ctx, -1)));
 
-	h = duk_get_hobject(ctx, -1);
+	h = duk_get_hobject_or_lfunc_coerce(ctx, -1);
 	if (h != NULL) {
 		duk_get_prop_stridx(ctx, -1, DUK_STRIDX_TO_JSON);
-		h = duk_get_hobject(ctx, -1);
+		h = duk_get_hobject_or_lfunc_coerce(ctx, -1);  /* toJSON() can also be a lightfunc */
+
 		if (h != NULL && DUK_HOBJECT_IS_CALLABLE(h)) {
 			DUK_DDD(DUK_DDDPRINT("value is object, has callable toJSON() -> call it"));
 			duk_dup(ctx, -2);         /* -> [ ... key val toJSON val ] */
@@ -20890,7 +34042,7 @@ static duk_bool_t duk__enc_value1(duk_json_enc_ctx *js_ctx, duk_idx_t idx_holder
 	DUK_DDD(DUK_DDDPRINT("value=%!T", (duk_tval *) duk_get_tval(ctx, -1)));
 
 	if (js_ctx->h_replacer) {
-		/* FIXME: here a "slice copy" would be useful */
+		/* XXX: here a "slice copy" would be useful */
 		DUK_DDD(DUK_DDDPRINT("replacer is set, call replacer"));
 		duk_push_hobject(ctx, js_ctx->h_replacer);  /* -> [ ... key val replacer ] */
 		duk_dup(ctx, idx_holder);                   /* -> [ ... key val replacer holder ] */
@@ -20910,25 +34062,52 @@ static duk_bool_t duk__enc_value1(duk_json_enc_ctx *js_ctx, duk_idx_t idx_holder
 		h = DUK_TVAL_GET_OBJECT(tv);
 		DUK_ASSERT(h != NULL);
 
-		c = (duk_small_int_t) DUK_HOBJECT_GET_CLASS_NUMBER(h);
-		switch ((int) c) {
-		case DUK_HOBJECT_CLASS_NUMBER:
-			DUK_DDD(DUK_DDDPRINT("value is a Number object -> coerce with ToNumber()"));
-			duk_to_number(ctx, -1);
-			break;
-		case DUK_HOBJECT_CLASS_STRING:
-			DUK_DDD(DUK_DDDPRINT("value is a String object -> coerce with ToString()"));
-			duk_to_string(ctx, -1);
-			break;
+		if (DUK_HOBJECT_IS_BUFFEROBJECT(h)) {
+			duk_hbufferobject *h_bufobj;
+			h_bufobj = (duk_hbufferobject *) h;
+			DUK_ASSERT_HBUFFEROBJECT_VALID(h_bufobj);
+			if (h_bufobj->buf == NULL || !DUK_HBUFFEROBJECT_VALID_SLICE(h_bufobj)) {
+				duk_push_null(ctx);
+			} else if (DUK_HBUFFEROBJECT_FULL_SLICE(h_bufobj)) {
+				duk_push_hbuffer(ctx, h_bufobj->buf);
+			} else {
+				/* This is not very good because we're making a copy
+				 * for serialization, but only for proper views.
+				 * Better support would be to serialize slices
+				 * directly but since we only push a raw buffer
+				 * here we can't convey the slice offset/length.
+				 */
+				duk_uint8_t *p_buf;
+
+				p_buf = (duk_uint8_t *) duk_push_fixed_buffer(ctx, h_bufobj->length);
+				DUK_MEMCPY((void *) p_buf,
+				           (const void *) (DUK_HBUFFEROBJECT_GET_SLICE_BASE(thr->heap, h_bufobj)),
+				           h_bufobj->length);
+			}
+			duk_remove(ctx, -2);
+		} else {
+			c = (duk_small_int_t) DUK_HOBJECT_GET_CLASS_NUMBER(h);
+			switch ((int) c) {
+			case DUK_HOBJECT_CLASS_NUMBER: {
+				DUK_DDD(DUK_DDDPRINT("value is a Number object -> coerce with ToNumber()"));
+				duk_to_number(ctx, -1);
+				break;
+			}
+			case DUK_HOBJECT_CLASS_STRING: {
+				DUK_DDD(DUK_DDDPRINT("value is a String object -> coerce with ToString()"));
+				duk_to_string(ctx, -1);
+				break;
+			}
 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
-		case DUK_HOBJECT_CLASS_BUFFER:
-		case DUK_HOBJECT_CLASS_POINTER:
+			case DUK_HOBJECT_CLASS_POINTER:
 #endif
-		case DUK_HOBJECT_CLASS_BOOLEAN:
-			DUK_DDD(DUK_DDDPRINT("value is a Boolean/Buffer/Pointer object -> get internal value"));
-			duk_get_prop_stridx(ctx, -1, DUK_STRIDX_INT_VALUE);
-			duk_remove(ctx, -2);
-			break;
+			case DUK_HOBJECT_CLASS_BOOLEAN: {
+				DUK_DDD(DUK_DDDPRINT("value is a Boolean/Buffer/Pointer object -> get internal value"));
+				duk_get_prop_stridx(ctx, -1, DUK_STRIDX_INT_VALUE);
+				duk_remove(ctx, -2);
+				break;
+			}
+			}  /* end switch */
 		}
 	}
 
@@ -20973,10 +34152,13 @@ static duk_bool_t duk__enc_value1(duk_json_enc_ctx *js_ctx, duk_idx_t idx_holder
  *
  * Stack policy: [ ... key val ] -> [ ... ].
  */
-static void duk__enc_value2(duk_json_enc_ctx *js_ctx) {
+DUK_LOCAL void duk__enc_value2(duk_json_enc_ctx *js_ctx) {
 	duk_context *ctx = (duk_context *) js_ctx->thr;
+	duk_hthread *thr = (duk_hthread *) ctx;
 	duk_tval *tv;
 
+	DUK_UNREF(thr);
+
 	DUK_DDD(DUK_DDDPRINT("duk__enc_value2: key=%!T, val=%!T",
 	                     (duk_tval *) duk_get_tval(ctx, -2),
 	                     (duk_tval *) duk_get_tval(ctx, -1)));
@@ -21006,35 +34188,7 @@ static void duk__enc_value2(duk_json_enc_ctx *js_ctx) {
 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
 	/* When JX/JC not in use, duk__enc_value1 will block pointer values. */
 	case DUK_TAG_POINTER: {
-		char buf[64];  /* XXX: how to figure correct size? */
-		const char *fmt;
-		void *ptr = DUK_TVAL_GET_POINTER(tv);
-
-		DUK_MEMZERO(buf, sizeof(buf));
-
-		/* The #ifdef clutter here needs to handle the three cases:
-		 * (1) JX+JC, (2) JX only, (3) JC only.
-		 */
-#if defined(DUK_USE_JX) && defined(DUK_USE_JC)
-		if (js_ctx->flag_ext_custom)
-#endif
-#if defined(DUK_USE_JX)
-		{
-			fmt = ptr ? "(%p)" : "(null)";
-		}
-#endif
-#if defined(DUK_USE_JX) && defined(DUK_USE_JC)
-		else
-#endif
-#if defined(DUK_USE_JC)
-		{
-			fmt = ptr ? "{\"_ptr\":\"%p\"}" : "{\"_ptr\":\"null\"}";
-		}
-#endif
-
-		/* When ptr == NULL, the format argument is unused. */
-		DUK_SNPRINTF(buf, sizeof(buf) - 1, fmt, ptr);  /* must not truncate */
-		DUK__EMIT_CSTR(js_ctx, buf);
+		duk__enc_pointer(js_ctx, DUK_TVAL_GET_POINTER(tv));
 		break;
 	}
 #endif  /* DUK_USE_JX || DUK_USE_JC */
@@ -21066,138 +34220,520 @@ static void duk__enc_value2(duk_json_enc_ctx *js_ctx) {
 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
 	/* When JX/JC not in use, duk__enc_value1 will block buffer values. */
 	case DUK_TAG_BUFFER: {
-		/* Buffer values are encoded in (lowercase) hex to make the
-		 * binary data readable.  Base64 or similar would be more
-		 * compact but less readable, and the point of JX/JC
-		 * variants is to be as useful to a programmer as possible.
+		duk__enc_buffer(js_ctx, DUK_TVAL_GET_BUFFER(tv));
+		break;
+	}
+#endif  /* DUK_USE_JX || DUK_USE_JC */
+	case DUK_TAG_LIGHTFUNC: {
+#if defined(DUK_USE_JX) || defined(DUK_USE_JC)
+		/* We only get here when doing non-standard JSON encoding */
+		DUK_ASSERT(js_ctx->flag_ext_custom || js_ctx->flag_ext_compatible);
+		DUK__EMIT_STRIDX(js_ctx, js_ctx->stridx_custom_function);
+#else
+		/* Standard JSON omits functions */
+		DUK_UNREACHABLE();
+#endif
+		break;
+	}
+#if defined(DUK_USE_FASTINT)
+	case DUK_TAG_FASTINT:
+		/* Number serialization has a significant impact relative to
+		 * other fast path code, so careful fast path for fastints.
 		 */
-
-		/* The #ifdef clutter here needs to handle the three cases:
-		 * (1) JX+JC, (2) JX only, (3) JC only.
+		duk__enc_fastint_tval(js_ctx, tv);
+		break;
+#endif
+	default: {
+		/* number */
+		DUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv));
+		DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));
+		/* XXX: A fast path for usual integers would be useful when
+		 * fastint support is not enabled.
 		 */
-#if defined(DUK_USE_JX) && defined(DUK_USE_JC)
-		if (js_ctx->flag_ext_custom)
+		duk__enc_double(js_ctx);
+		break;
+	}
+	}
+
+	/* [ ... key val ] -> [ ... ] */
+
+	duk_pop_2(ctx);
+}
+
+/* E5 Section 15.12.3, main algorithm, step 4.b.ii steps 1-4. */
+DUK_LOCAL duk_bool_t duk__enc_allow_into_proplist(duk_tval *tv) {
+	duk_hobject *h;
+	duk_small_int_t c;
+
+	DUK_ASSERT(tv != NULL);
+	if (DUK_TVAL_IS_STRING(tv) || DUK_TVAL_IS_NUMBER(tv)) {
+		return 1;
+	} else if (DUK_TVAL_IS_OBJECT(tv)) {
+		h = DUK_TVAL_GET_OBJECT(tv);
+		DUK_ASSERT(h != NULL);
+		c = (duk_small_int_t) DUK_HOBJECT_GET_CLASS_NUMBER(h);
+		if (c == DUK_HOBJECT_CLASS_STRING || c == DUK_HOBJECT_CLASS_NUMBER) {
+			return 1;
+		}
+	}
+
+	return 0;
+}
+
+/*
+ *  JSON.stringify() fast path
+ *
+ *  Otherwise supports full JSON, JX, and JC features, but bails out on any
+ *  possible side effect which might change the value being serialized.  The
+ *  fast path can take advantage of the fact that the value being serialized
+ *  is unchanged so that we can walk directly through property tables etc.
+ */
+
+#if defined(DUK_USE_JSON_STRINGIFY_FASTPATH)
+DUK_LOCAL duk_bool_t duk__json_stringify_fast_value(duk_json_enc_ctx *js_ctx, duk_tval *tv) {
+	duk_uint_fast32_t i, n;
+
+	DUK_DDD(DUK_DDDPRINT("stringify fast: %!T", tv));
+
+	DUK_ASSERT(js_ctx != NULL);
+	DUK_ASSERT(js_ctx->thr != NULL);
+
+ restart_match:
+	DUK_ASSERT(tv != NULL);
+
+	switch (DUK_TVAL_GET_TAG(tv)) {
+	case DUK_TAG_UNDEFINED: {
+#if defined(DUK_USE_JX) || defined(DUK_USE_JC)
+		if (js_ctx->flag_ext_custom || js_ctx->flag_ext_compatible) {
+			DUK__EMIT_STRIDX(js_ctx, js_ctx->stridx_custom_undefined);
+			break;
+		} else {
+			goto emit_undefined;
+		}
+#else
+		goto emit_undefined;
 #endif
-#if defined(DUK_USE_JX)
-		{
-			duk_uint8_t *p, *p_end;
-			duk_small_uint_t x;
-			duk_hbuffer *h;
+	}
+	case DUK_TAG_NULL: {
+		DUK__EMIT_STRIDX(js_ctx, DUK_STRIDX_LC_NULL);
+		break;
+	}
+	case DUK_TAG_BOOLEAN: {
+		DUK__EMIT_STRIDX(js_ctx, DUK_TVAL_GET_BOOLEAN(tv) ?
+		                 DUK_STRIDX_TRUE : DUK_STRIDX_FALSE);
+		break;
+	}
+	case DUK_TAG_STRING: {
+		duk_hstring *h;
 
-			h = DUK_TVAL_GET_BUFFER(tv);
-			DUK_ASSERT(h != NULL);
-			p = (duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(h);
-			p_end = p + DUK_HBUFFER_GET_SIZE(h);
-			DUK__EMIT_1(js_ctx, DUK_ASC_PIPE);
-			while (p < p_end) {
-				x = *p++;
-				duk_hbuffer_append_byte(js_ctx->thr, js_ctx->h_buf, duk_lc_digits[(x >> 4) & 0x0f]);
-				duk_hbuffer_append_byte(js_ctx->thr, js_ctx->h_buf, duk_lc_digits[x & 0x0f]);
+		h = DUK_TVAL_GET_STRING(tv);
+		DUK_ASSERT(h != NULL);
+		duk__enc_quote_string(js_ctx, h);
+		break;
+	}
+	case DUK_TAG_OBJECT: {
+		duk_hobject *obj;
+		duk_tval *tv_val;
+		duk_bool_t emitted = 0;
+		duk_uint32_t c_bit, c_all, c_array, c_unbox, c_undef,
+		             c_func, c_bufobj, c_object;
+
+		/* For objects JSON.stringify() only looks for own, enumerable
+		 * properties which is nice for the fast path here.
+		 *
+		 * For arrays JSON.stringify() uses [[Get]] so it will actually
+		 * inherit properties during serialization!  This fast path
+		 * supports gappy arrays as long as there's no actual inherited
+		 * property (which might be a getter etc).
+		 *
+		 * Since recursion only happens for objects, we can have both
+		 * recursion and loop checks here.  We use a simple, depth-limited
+		 * loop check in the fast path because the object-based tracking
+		 * is very slow (when tested, it accounted for 50% of fast path
+		 * execution time for input data with a lot of small objects!).
+		 */
+
+		/* XXX: for real world code, could just ignore array inheritance
+		 * and only look at array own properties.
+		 */
+
+		/* We rely on a few object flag / class number relationships here,
+		 * assert for them.
+		 */
+
+		obj = DUK_TVAL_GET_OBJECT(tv);
+		DUK_ASSERT(obj != NULL);
+		DUK_ASSERT_HOBJECT_VALID(obj);
+
+		/* Once recursion depth is increased, exit path must decrease
+		 * it (though it's OK to abort the fast path).
+		 */
+
+		DUK_ASSERT(js_ctx->recursion_depth >= 0);
+		DUK_ASSERT(js_ctx->recursion_depth <= js_ctx->recursion_limit);
+		if (js_ctx->recursion_depth >= js_ctx->recursion_limit) {
+			DUK_DD(DUK_DDPRINT("fast path recursion limit"));
+			DUK_ERROR(js_ctx->thr, DUK_ERR_RANGE_ERROR, DUK_STR_JSONDEC_RECLIMIT);
+		}
+
+		for (i = 0, n = (duk_uint_fast32_t) js_ctx->recursion_depth; i < n; i++) {
+			if (DUK_UNLIKELY(js_ctx->visiting[i] == obj)) {
+				DUK_DD(DUK_DDPRINT("fast path loop detect"));
+				DUK_ERROR(js_ctx->thr, DUK_ERR_TYPE_ERROR, DUK_STR_CYCLIC_INPUT);
 			}
-			DUK__EMIT_1(js_ctx, DUK_ASC_PIPE);
 		}
-#endif
-#if defined(DUK_USE_JX) && defined(DUK_USE_JC)
+
+		/* Guaranteed by recursion_limit setup so we don't have to
+		 * check twice.
+		 */
+		DUK_ASSERT(js_ctx->recursion_depth < DUK_JSON_ENC_LOOPARRAY);
+		js_ctx->visiting[js_ctx->recursion_depth] = obj;
+		js_ctx->recursion_depth++;
+
+		/* If object has a .toJSON() property, we can't be certain
+		 * that it wouldn't mutate any value arbitrarily, so bail
+		 * out of the fast path.
+		 *
+		 * If an object is a Proxy we also can't avoid side effects
+		 * so abandon.
+		 */
+		/* XXX: non-callable .toJSON() doesn't need to cause an abort
+		 * but does at the moment, probably not worth fixing.
+		 */
+		if (duk_hobject_hasprop_raw(js_ctx->thr, obj, DUK_HTHREAD_STRING_TO_JSON(js_ctx->thr)) ||
+		    DUK_HOBJECT_HAS_EXOTIC_PROXYOBJ(obj)) {
+			DUK_DD(DUK_DDPRINT("object has a .toJSON property or object is a Proxy, abort fast path"));
+			goto abort_fastpath;
+		}
+
+		/* We could use a switch-case for the class number but it turns out
+		 * a small if-else ladder on class masks is better.  The if-ladder
+		 * should be in order of relevancy.
+		 */
+
+		/* XXX: move masks to js_ctx? they don't change during one
+		 * fast path invocation.
+		 */
+		DUK_ASSERT(DUK_HOBJECT_CLASS_MAX <= 31);
+#if defined(DUK_USE_JX) || defined(DUK_USE_JC)
+		if (js_ctx->flag_ext_custom_or_compatible) {
+			c_all = DUK_HOBJECT_CMASK_ALL;
+			c_array = DUK_HOBJECT_CMASK_ARRAY;
+			c_unbox = DUK_HOBJECT_CMASK_NUMBER |
+			          DUK_HOBJECT_CMASK_STRING |
+			          DUK_HOBJECT_CMASK_BOOLEAN |
+			          DUK_HOBJECT_CMASK_POINTER;
+			c_func = DUK_HOBJECT_CMASK_FUNCTION;
+			c_bufobj = DUK_HOBJECT_CMASK_ALL_BUFFEROBJECTS;
+			c_undef = 0;
+			c_object = c_all & ~(c_array | c_unbox | c_func | c_bufobj | c_undef);
+		}
 		else
 #endif
-#if defined(DUK_USE_JC)
 		{
-			DUK_ASSERT(js_ctx->flag_ext_compatible);
-			duk_hex_encode(ctx, -1);
-			DUK__EMIT_CSTR(js_ctx, "{\"_buf\":");
-			duk__enc_quote_string(js_ctx, duk_require_hstring(ctx, -1));
+			c_all = DUK_HOBJECT_CMASK_ALL;
+			c_array = DUK_HOBJECT_CMASK_ARRAY;
+			c_unbox = DUK_HOBJECT_CMASK_NUMBER |
+			          DUK_HOBJECT_CMASK_STRING |
+			          DUK_HOBJECT_CMASK_BOOLEAN;
+			c_func = 0;
+			c_bufobj = 0;
+			c_undef = DUK_HOBJECT_CMASK_FUNCTION |
+			          DUK_HOBJECT_CMASK_POINTER |
+			          DUK_HOBJECT_CMASK_ALL_BUFFEROBJECTS;
+			c_object = c_all & ~(c_array | c_unbox | c_func | c_bufobj | c_undef);
+		}
+
+		c_bit = DUK_HOBJECT_GET_CLASS_MASK(obj);
+		if (c_bit & c_object) {
+			/* All other object types. */
+			DUK__EMIT_1(js_ctx, DUK_ASC_LCURLY);
+
+			/* A non-Array object should not have an array part in practice.
+			 * But since it is supported internally (and perhaps used at some
+			 * point), check and abandon if that's the case.
+			 */
+			if (DUK_HOBJECT_HAS_ARRAY_PART(obj)) {
+				DUK_DD(DUK_DDPRINT("non-Array object has array part, abort fast path"));
+				goto abort_fastpath;
+			}
+
+			for (i = 0; i < (duk_uint_fast32_t) DUK_HOBJECT_GET_ENEXT(obj); i++) {
+				duk_hstring *k;
+				duk_size_t prev_size;
+
+				k = DUK_HOBJECT_E_GET_KEY(js_ctx->thr->heap, obj, i);
+				if (!k) {
+					continue;
+				}
+				if (!DUK_HOBJECT_E_SLOT_IS_ENUMERABLE(js_ctx->thr->heap, obj, i)) {
+					continue;
+				}
+				if (DUK_HOBJECT_E_SLOT_IS_ACCESSOR(js_ctx->thr->heap, obj, i)) {
+					/* Getter might have arbitrary side effects,
+					 * so bail out.
+					 */
+					DUK_DD(DUK_DDPRINT("property is an accessor, abort fast path"));
+					goto abort_fastpath;
+				}
+				if (DUK_HSTRING_HAS_INTERNAL(k)) {
+					continue;
+				}
+
+				tv_val = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(js_ctx->thr->heap, obj, i);
+
+				prev_size = DUK_BW_GET_SIZE(js_ctx->thr, &js_ctx->bw);
+				if (DUK_UNLIKELY(js_ctx->h_gap != NULL)) {
+
+					duk__enc_newline_indent(js_ctx, js_ctx->recursion_depth);
+					duk__enc_key_autoquote(js_ctx, k);
+					DUK__EMIT_2(js_ctx, DUK_ASC_COLON, DUK_ASC_SPACE);
+				} else {
+					duk__enc_key_autoquote(js_ctx, k);
+					DUK__EMIT_1(js_ctx, DUK_ASC_COLON);
+				}
+
+				if (duk__json_stringify_fast_value(js_ctx, tv_val) == 0) {
+					DUK_DD(DUK_DDPRINT("prop value not supported, rewind key and colon"));
+					DUK_BW_SET_SIZE(js_ctx->thr, &js_ctx->bw, prev_size);
+				} else {
+					DUK__EMIT_1(js_ctx, DUK_ASC_COMMA);
+					emitted = 1;
+				}
+			}
+
+			/* If any non-Array value had enumerable virtual own
+			 * properties, they should be serialized here.  Standard
+			 * types don't.
+			 */
+
+			if (emitted) {
+				DUK_ASSERT(*((duk_uint8_t *) DUK_BW_GET_PTR(js_ctx->thr, &js_ctx->bw) - 1) == DUK_ASC_COMMA);
+				DUK__UNEMIT_1(js_ctx);  /* eat trailing comma */
+				if (DUK_UNLIKELY(js_ctx->h_gap != NULL)) {
+					DUK_ASSERT(js_ctx->recursion_depth >= 1);
+					duk__enc_newline_indent(js_ctx, js_ctx->recursion_depth - 1);
+				}
+			}
 			DUK__EMIT_1(js_ctx, DUK_ASC_RCURLY);
-		}
-#endif
-		break;
-	}
-#endif  /* DUK_USE_JX || DUK_USE_JC */
-	default: {
-		/* number */
-		duk_double_t d;
-		duk_small_int_t c;
-		duk_small_int_t s;
-		duk_small_uint_t stridx;
-		duk_small_uint_t n2s_flags;
-		duk_hstring *h_str;
+		} else if (c_bit & c_array) {
+			duk_uint_fast32_t arr_len;
+			duk_uint_fast32_t asize;
 
-		DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));
-		d = DUK_TVAL_GET_NUMBER(tv);
-		c = (duk_small_int_t) DUK_FPCLASSIFY(d);
-		s = (duk_small_int_t) DUK_SIGNBIT(d);
-		DUK_UNREF(s);
+			DUK__EMIT_1(js_ctx, DUK_ASC_LBRACKET);
 
-		if (DUK_LIKELY(!(c == DUK_FP_INFINITE || c == DUK_FP_NAN))) {
-			DUK_ASSERT(DUK_ISFINITE(d));
+			/* Assume arrays are dense in the fast path. */
+			if (!DUK_HOBJECT_HAS_ARRAY_PART(obj)) {
+				DUK_DD(DUK_DDPRINT("Array object is sparse, abort fast path"));
+				goto abort_fastpath;
+			}
 
-#if defined(DUK_USE_JX) || defined(DUK_USE_JC)
-			/* Negative zero needs special handling in JX/JC because
-			 * it would otherwise serialize to '0', not '-0'.
+			arr_len = (duk_uint_fast32_t) duk_hobject_get_length(js_ctx->thr, obj);
+			asize = (duk_uint_fast32_t) DUK_HOBJECT_GET_ASIZE(obj);
+			if (arr_len > asize) {
+				/* Array length is larger than 'asize'.  This shouldn't
+				 * happen in practice.  Bail out just in case.
+				 */
+				DUK_DD(DUK_DDPRINT("arr_len > asize, abort fast path"));
+				goto abort_fastpath;
+			}
+			/* Array part may be larger than 'length'; if so, iterate
+			 * only up to array 'length'.
 			 */
-			if (DUK_UNLIKELY(c == DUK_FP_ZERO && s != 0 &&
-			                 (js_ctx->flag_ext_custom || js_ctx->flag_ext_compatible))) {
-				duk_push_hstring_stridx(ctx, DUK_STRIDX_MINUS_ZERO);  /* '-0' */
-			} else
-#endif  /* DUK_USE_JX || DUK_USE_JC */
-			{
-				n2s_flags = 0;
-				/* [ ... number ] -> [ ... string ] */
-				duk_numconv_stringify(ctx, 10 /*radix*/, 0 /*digits*/, n2s_flags);
+			for (i = 0; i < arr_len; i++) {
+				DUK_ASSERT(i < (duk_uint_fast32_t) DUK_HOBJECT_GET_ASIZE(obj));
+
+				tv_val = DUK_HOBJECT_A_GET_VALUE_PTR(js_ctx->thr->heap, obj, i);
+
+				if (DUK_UNLIKELY(js_ctx->h_gap != NULL)) {
+					duk__enc_newline_indent(js_ctx, js_ctx->recursion_depth);
+				}
+
+				if (DUK_UNLIKELY(DUK_TVAL_IS_UNUSED(tv_val))) {
+					/* Gap in array; check for inherited property,
+					 * bail out if one exists.  This should be enough
+					 * to support gappy arrays for all practical code.
+					 */
+					duk_hstring *h_tmp;
+					duk_bool_t has_inherited;
+
+					/* XXX: refactor into an internal helper, pretty awkward */
+					duk_push_uint((duk_context *) js_ctx->thr, (duk_uint_t) i);
+					h_tmp = duk_to_hstring((duk_context *) js_ctx->thr, -1);
+					DUK_ASSERT(h_tmp != NULL);
+					has_inherited = duk_hobject_hasprop_raw(js_ctx->thr, obj, h_tmp);
+					duk_pop((duk_context *) js_ctx->thr);
+
+					if (has_inherited) {
+						DUK_D(DUK_DPRINT("gap in array, conflicting inherited property, abort fast path"));
+						goto abort_fastpath;
+					}
+
+					/* Ordinary gap, undefined encodes to 'null' in
+					 * standard JSON (and no JX/JC support here now).
+					 */
+					DUK_D(DUK_DPRINT("gap in array, no conflicting inherited property, remain on fast path"));
+					DUK__EMIT_STRIDX(js_ctx, DUK_STRIDX_LC_NULL);
+				} else {
+					if (duk__json_stringify_fast_value(js_ctx, tv_val) == 0) {
+						DUK__EMIT_STRIDX(js_ctx, DUK_STRIDX_LC_NULL);
+					}
+				}
+				DUK__EMIT_1(js_ctx, DUK_ASC_COMMA);
+				emitted = 1;
 			}
-			h_str = duk_to_hstring(ctx, -1);
-			DUK_ASSERT(h_str != NULL);
-			DUK__EMIT_HSTR(js_ctx, h_str);
-			break;
+
+			if (emitted) {
+				DUK_ASSERT(*((duk_uint8_t *) DUK_BW_GET_PTR(js_ctx->thr, &js_ctx->bw) - 1) == DUK_ASC_COMMA);
+				DUK__UNEMIT_1(js_ctx);  /* eat trailing comma */
+				if (DUK_UNLIKELY(js_ctx->h_gap != NULL)) {
+					DUK_ASSERT(js_ctx->recursion_depth >= 1);
+					duk__enc_newline_indent(js_ctx, js_ctx->recursion_depth - 1);
+				}
+			}
+			DUK__EMIT_1(js_ctx, DUK_ASC_RBRACKET);
+		} else if (c_bit & c_unbox) {
+			/* Certain boxed types are required to go through
+			 * automatic unboxing.  Rely on internal value being
+			 * sane (to avoid infinite recursion).
+			 */
+			duk_tval *tv_internal;
+
+			DUK_DD(DUK_DDPRINT("auto unboxing in fast path"));
+
+			tv_internal = duk_hobject_get_internal_value_tval_ptr(js_ctx->thr->heap, obj);
+			DUK_ASSERT(tv_internal != NULL);
+			DUK_ASSERT(DUK_TVAL_IS_STRING(tv_internal) ||
+			           DUK_TVAL_IS_NUMBER(tv_internal) ||
+			           DUK_TVAL_IS_BOOLEAN(tv_internal) ||
+			           DUK_TVAL_IS_POINTER(tv_internal));
+
+			tv = tv_internal;
+			DUK_ASSERT(js_ctx->recursion_depth > 0);
+			js_ctx->recursion_depth--;  /* required to keep recursion depth correct */
+			goto restart_match;
+#if defined(DUK_USE_JX) || defined(DUK_USE_JC)
+		} else if (c_bit & c_func) {
+			DUK__EMIT_STRIDX(js_ctx, js_ctx->stridx_custom_function);
+		} else if (c_bit & c_bufobj) {
+			duk__enc_bufferobject(js_ctx, (duk_hbufferobject *) obj);
+#endif
+		} else {
+			DUK_ASSERT((c_bit & c_undef) != 0);
+
+			/* Must decrease recursion depth before returning. */
+			DUK_ASSERT(js_ctx->recursion_depth > 0);
+			DUK_ASSERT(js_ctx->recursion_depth <= js_ctx->recursion_limit);
+			js_ctx->recursion_depth--;
+			goto emit_undefined;
 		}
 
+		DUK_ASSERT(js_ctx->recursion_depth > 0);
+		DUK_ASSERT(js_ctx->recursion_depth <= js_ctx->recursion_limit);
+		js_ctx->recursion_depth--;
+		break;
+	}
+	case DUK_TAG_BUFFER: {
 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
-		if (!(js_ctx->flags & (DUK_JSON_FLAG_EXT_CUSTOM |
-		                       DUK_JSON_FLAG_EXT_COMPATIBLE))) {
-			stridx = DUK_STRIDX_LC_NULL;
-		} else if (c == DUK_FP_NAN) {
-			stridx = js_ctx->stridx_custom_nan;
-		} else if (s == 0) {
-			stridx = js_ctx->stridx_custom_posinf;
+		if (js_ctx->flag_ext_custom_or_compatible) {
+			duk__enc_buffer(js_ctx, DUK_TVAL_GET_BUFFER(tv));
+			break;
 		} else {
-			stridx = js_ctx->stridx_custom_neginf;
+			goto emit_undefined;
 		}
 #else
-		stridx = DUK_STRIDX_LC_NULL;
+		goto emit_undefined;
+#endif
+	}
+	case DUK_TAG_POINTER: {
+#if defined(DUK_USE_JX) || defined(DUK_USE_JC)
+		if (js_ctx->flag_ext_custom_or_compatible) {
+			duk__enc_pointer(js_ctx, DUK_TVAL_GET_POINTER(tv));
+			break;
+		} else {
+			goto emit_undefined;
+		}
+#else
+		goto emit_undefined;
 #endif
-		DUK__EMIT_STRIDX(js_ctx, stridx);
+	}
+	case DUK_TAG_LIGHTFUNC: {
+		/* A lightfunc might also inherit a .toJSON() so just bail out. */
+		/* XXX: Could just lookup .toJSON() and continue in fast path,
+		 * as it would almost never be defined.
+		 */
+		DUK_DD(DUK_DDPRINT("value is a lightfunc, abort fast path"));
+		goto abort_fastpath;
+	}
+#if defined(DUK_USE_FASTINT)
+	case DUK_TAG_FASTINT: {
+		/* Number serialization has a significant impact relative to
+		 * other fast path code, so careful fast path for fastints.
+		 */
+		duk__enc_fastint_tval(js_ctx, tv);
 		break;
 	}
+#endif
+	default: {
+		/* XXX: A fast path for usual integers would be useful when
+		 * fastint support is not enabled.
+		 */
+		DUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv));
+		DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));
+
+		/* XXX: Stack discipline is annoying, could be changed in numconv. */
+		duk_push_tval((duk_context *) js_ctx->thr, tv);
+		duk__enc_double(js_ctx);
+		duk_pop((duk_context *) js_ctx->thr);
+
+#if 0
+		/* Could also rely on native sprintf(), but it will handle
+		 * values like NaN, Infinity, -0, exponent notation etc in
+		 * a JSON-incompatible way.
+		 */
+		duk_double_t d;
+		char buf[64];
+
+		DUK_ASSERT(DUK_TVAL_IS_DOUBLE(tv));
+		d = DUK_TVAL_GET_DOUBLE(tv);
+		DUK_SPRINTF(buf, "%lg", d);
+		DUK__EMIT_CSTR(js_ctx, buf);
+#endif
 	}
+	}
+	return 1;  /* not undefined */
 
-	/* [ ... key val ] -> [ ... ] */
+ emit_undefined:
+	return 0;  /* value was undefined/unsupported */
 
-	duk_pop_2(ctx);
+ abort_fastpath:
+	/* Error message doesn't matter: the error is ignored anyway. */
+	DUK_DD(DUK_DDPRINT("aborting fast path"));
+	DUK_ERROR(js_ctx->thr, DUK_ERR_ERROR, DUK_STR_INTERNAL_ERROR);
+	return 0;  /* unreachable */
 }
 
-/* E5 Section 15.12.3, main algorithm, step 4.b.ii steps 1-4. */
-static duk_bool_t duk__enc_allow_into_proplist(duk_tval *tv) {
-	duk_hobject *h;
-	duk_small_int_t c;
+DUK_LOCAL duk_ret_t duk__json_stringify_fast(duk_context *ctx) {
+	duk_json_enc_ctx *js_ctx;
 
-	DUK_ASSERT(tv != NULL);
-	if (DUK_TVAL_IS_STRING(tv) || DUK_TVAL_IS_NUMBER(tv)) {
-		return 1;
-	} else if (DUK_TVAL_IS_OBJECT(tv)) {
-		h = DUK_TVAL_GET_OBJECT(tv);
-		DUK_ASSERT(h != NULL);
-		c = (duk_small_int_t) DUK_HOBJECT_GET_CLASS_NUMBER(h);
-		if (c == DUK_HOBJECT_CLASS_STRING || c == DUK_HOBJECT_CLASS_NUMBER) {
-			return 1;
-		}
+	DUK_ASSERT(ctx != NULL);
+	js_ctx = (duk_json_enc_ctx *) duk_get_pointer(ctx, -2);
+	DUK_ASSERT(js_ctx != NULL);
+
+	if (duk__json_stringify_fast_value(js_ctx, duk_get_tval((duk_context *) (js_ctx->thr), -1)) == 0) {
+		DUK_DD(DUK_DDPRINT("top level value not supported, fail fast path"));
+		return DUK_RET_ERROR;  /* error message doesn't matter, ignored anyway */
 	}
 
 	return 0;
 }
+#endif  /* DUK_USE_JSON_STRINGIFY_FASTPATH */
 
 /*
  *  Top level wrappers
  */
 
+DUK_INTERNAL
 void duk_bi_json_parse_helper(duk_context *ctx,
                               duk_idx_t idx_value,
                               duk_idx_t idx_reviver,
@@ -21225,26 +34761,36 @@ void duk_bi_json_parse_helper(duk_context *ctx,
 #ifdef DUK_USE_EXPLICIT_NULL_INIT
 	/* nothing now */
 #endif
-	js_ctx->recursion_limit = DUK_JSON_DEC_RECURSION_LIMIT;
+	js_ctx->recursion_limit = DUK_USE_JSON_DEC_RECLIMIT;
+	DUK_ASSERT(js_ctx->recursion_depth == 0);
 
 	/* Flag handling currently assumes that flags are consistent.  This is OK
 	 * because the call sites are now strictly controlled.
 	 */
 
 	js_ctx->flags = flags;
-#ifdef DUK_USE_JX
+#if defined(DUK_USE_JX)
 	js_ctx->flag_ext_custom = flags & DUK_JSON_FLAG_EXT_CUSTOM;
 #endif
-#ifdef DUK_USE_JC
+#if defined(DUK_USE_JC)
 	js_ctx->flag_ext_compatible = flags & DUK_JSON_FLAG_EXT_COMPATIBLE;
 #endif
+#if defined(DUK_USE_JX) || defined(DUK_USE_JC)
+	js_ctx->flag_ext_custom_or_compatible = flags & (DUK_JSON_FLAG_EXT_CUSTOM | DUK_JSON_FLAG_EXT_COMPATIBLE);
+#endif
 
 	h_text = duk_to_hstring(ctx, idx_value);  /* coerce in-place */
 	DUK_ASSERT(h_text != NULL);
 
-	js_ctx->p = (duk_uint8_t *) DUK_HSTRING_GET_DATA(h_text);
-	js_ctx->p_end = ((duk_uint8_t *) DUK_HSTRING_GET_DATA(h_text)) +
+	/* JSON parsing code is allowed to read [p_start,p_end]: p_end is
+	 * valid and points to the string NUL terminator (which is always
+	 * guaranteed for duk_hstrings.
+	 */
+	js_ctx->p_start = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_text);
+	js_ctx->p = js_ctx->p_start;
+	js_ctx->p_end = ((const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_text)) +
 	                DUK_HSTRING_GET_BYTELEN(h_text);
+	DUK_ASSERT(*(js_ctx->p_end) == 0x00);
 
 	duk__dec_value(js_ctx);  /* -> [ ... value ] */
 
@@ -21253,7 +34799,7 @@ void duk_bi_json_parse_helper(duk_context *ctx,
 	 */
 
 	if (js_ctx->p != js_ctx->p_end) {
-		DUK_ERROR(thr, DUK_ERR_SYNTAX_ERROR, DUK_STR_INVALID_JSON);
+		duk__dec_syntax_error(js_ctx);
 	}
 
 	if (duk_is_callable(ctx, idx_reviver)) {
@@ -21290,6 +34836,7 @@ void duk_bi_json_parse_helper(duk_context *ctx,
 	DUK_ASSERT(duk_get_top(ctx) == entry_top + 1);
 }
 
+DUK_INTERNAL
 void duk_bi_json_stringify_helper(duk_context *ctx,
                                   duk_idx_t idx_value,
                                   duk_idx_t idx_replacer,
@@ -21326,10 +34873,8 @@ void duk_bi_json_stringify_helper(duk_context *ctx,
 #ifdef DUK_USE_EXPLICIT_NULL_INIT
 	js_ctx->h_replacer = NULL;
 	js_ctx->h_gap = NULL;
-	js_ctx->h_indent = NULL;
 #endif
 	js_ctx->idx_proplist = -1;
-	js_ctx->recursion_limit = DUK_JSON_ENC_RECURSION_LIMIT;
 
 	/* Flag handling currently assumes that flags are consistent.  This is OK
 	 * because the call sites are now strictly controlled.
@@ -21344,6 +34889,9 @@ void duk_bi_json_stringify_helper(duk_context *ctx,
 #ifdef DUK_USE_JC
 	js_ctx->flag_ext_compatible = flags & DUK_JSON_FLAG_EXT_COMPATIBLE;
 #endif
+#if defined(DUK_USE_JX) || defined(DUK_USE_JC)
+	js_ctx->flag_ext_custom_or_compatible = flags & (DUK_JSON_FLAG_EXT_CUSTOM | DUK_JSON_FLAG_EXT_COMPATIBLE);
+#endif
 
 	/* The #ifdef clutter here handles the JX/JC enable/disable
 	 * combinations properly.
@@ -21385,13 +34933,11 @@ void duk_bi_json_stringify_helper(duk_context *ctx,
 	{
 		js_ctx->mask_for_undefined = DUK_TYPE_MASK_UNDEFINED |
 		                             DUK_TYPE_MASK_POINTER |
-		                             DUK_TYPE_MASK_BUFFER;
+		                             DUK_TYPE_MASK_BUFFER |
+		                             DUK_TYPE_MASK_LIGHTFUNC;
 	}
 
-	(void) duk_push_dynamic_buffer(ctx, 0);
-	js_ctx->h_buf = (duk_hbuffer_dynamic *) duk_get_hbuffer(ctx, -1);
-	DUK_ASSERT(js_ctx->h_buf != NULL);
-	DUK_ASSERT(DUK_HBUFFER_HAS_DYNAMIC(js_ctx->h_buf));
+	DUK_BW_INIT_PUSHBUF(thr, &js_ctx->bw, DUK__JSON_STRINGIFY_BUFSIZE);
 
 	js_ctx->idx_loop = duk_push_object_internal(ctx);
 	DUK_ASSERT(js_ctx->idx_loop >= 0);
@@ -21416,7 +34962,7 @@ void duk_bi_json_stringify_helper(duk_context *ctx,
 			duk_uarridx_t plist_idx = 0;
 			duk_small_uint_t enum_flags;
 
-			js_ctx->idx_proplist = duk_push_array(ctx);  /* FIXME: array internal? */
+			js_ctx->idx_proplist = duk_push_array(ctx);  /* XXX: array internal? */
 
 			enum_flags = DUK_ENUM_ARRAY_INDICES_ONLY |
 			             DUK_ENUM_SORT_ARRAY_INDICES;  /* expensive flag */
@@ -21424,7 +34970,7 @@ void duk_bi_json_stringify_helper(duk_context *ctx,
 			while (duk_next(ctx, -1 /*enum_index*/, 1 /*get_value*/)) {
 				/* [ ... proplist enum_obj key val ] */
 				if (duk__enc_allow_into_proplist(duk_get_tval(ctx, -1))) {
-					/* FIXME: duplicates should be eliminated here */
+					/* XXX: duplicates should be eliminated here */
 					DUK_DDD(DUK_DDDPRINT("proplist enum: key=%!T, val=%!T --> accept",
 					                     (duk_tval *) duk_get_tval(ctx, -2),
 					                     (duk_tval *) duk_get_tval(ctx, -1)));
@@ -21468,7 +35014,7 @@ void duk_bi_json_stringify_helper(duk_context *ctx,
 			DUK_ASC_SPACE, DUK_ASC_SPACE, DUK_ASC_SPACE, DUK_ASC_SPACE,
 			DUK_ASC_SPACE, DUK_ASC_SPACE, DUK_ASC_SPACE, DUK_ASC_SPACE,
 			DUK_ASC_SPACE, DUK_ASC_SPACE
-		};  /* FIXME:helper */
+		};  /* XXX: helper */
 
 		/* ToInteger() coercion; NaN -> 0, infinities are clamped to 0 and 10 */
 		nspace = (duk_small_int_t) duk_to_int_clamped(ctx, idx_space, 0 /*minval*/, 10 /*maxval*/);
@@ -21478,7 +35024,7 @@ void duk_bi_json_stringify_helper(duk_context *ctx,
 		js_ctx->h_gap = duk_get_hstring(ctx, -1);
 		DUK_ASSERT(js_ctx->h_gap != NULL);
 	} else if (duk_is_string(ctx, idx_space)) {
-		/* FIXME: substring in-place at idx_place? */
+		/* XXX: substring in-place at idx_place? */
 		duk_dup(ctx, idx_space);
 		duk_substring(ctx, -1, 0, 10);  /* clamp to 10 chars */
 		js_ctx->h_gap = duk_get_hstring(ctx, -1);
@@ -21491,18 +35037,75 @@ void duk_bi_json_stringify_helper(duk_context *ctx,
 		/* if gap is empty, behave as if not given at all */
 		if (DUK_HSTRING_GET_CHARLEN(js_ctx->h_gap) == 0) {
 			js_ctx->h_gap = NULL;
-		} else {
-			/* set 'indent' only if it will actually increase */
-			js_ctx->h_indent = DUK_HTHREAD_STRING_EMPTY_STRING(thr);
 		}
 	}
 
-	DUK_ASSERT((js_ctx->h_gap == NULL && js_ctx->h_indent == NULL) ||
-	           (js_ctx->h_gap != NULL && js_ctx->h_indent != NULL));
-
 	/* [ ... buf loop (proplist) (gap) ] */
 
 	/*
+	 *  Fast path: assume no mutation, iterate object property tables
+	 *  directly; bail out if that assumption doesn't hold.
+	 */
+
+#if defined(DUK_USE_JSON_STRINGIFY_FASTPATH)
+	if (js_ctx->h_replacer == NULL &&  /* replacer is a mutation risk */
+	    js_ctx->idx_proplist == -1) {  /* proplist is very rare */
+		duk_int_t pcall_rc;
+#ifdef DUK_USE_MARK_AND_SWEEP
+		duk_small_uint_t prev_mark_and_sweep_base_flags;
+#endif
+
+		DUK_DD(DUK_DDPRINT("try JSON.stringify() fast path"));
+
+		/* Use recursion_limit to ensure we don't overwrite js_ctx->visiting[]
+		 * array so we don't need two counter checks in the fast path.  The
+		 * slow path has a much larger recursion limit which we'll use if
+		 * necessary.
+		 */
+		DUK_ASSERT(DUK_USE_JSON_ENC_RECLIMIT >= DUK_JSON_ENC_LOOPARRAY);
+		js_ctx->recursion_limit = DUK_JSON_ENC_LOOPARRAY;
+		DUK_ASSERT(js_ctx->recursion_depth == 0);
+
+		/* Execute the fast path in a protected call.  If any error is thrown,
+		 * fall back to the slow path.  This includes e.g. recursion limit
+		 * because the fast path has a smaller recursion limit (and simpler,
+		 * limited loop detection).
+		 */
+
+		duk_push_pointer(ctx, (void *) js_ctx);
+		duk_dup(ctx, idx_value);
+
+#if defined(DUK_USE_MARK_AND_SWEEP)
+		/* Must prevent finalizers which may have arbitrary side effects. */
+		prev_mark_and_sweep_base_flags = thr->heap->mark_and_sweep_base_flags;
+		thr->heap->mark_and_sweep_base_flags |=
+			DUK_MS_FLAG_NO_FINALIZERS |         /* avoid attempts to add/remove object keys */
+		        DUK_MS_FLAG_NO_OBJECT_COMPACTION;   /* avoid attempt to compact any objects */
+#endif
+
+		pcall_rc = duk_safe_call(ctx, duk__json_stringify_fast, 2 /*nargs*/, 0 /*nret*/);
+
+#if defined(DUK_USE_MARK_AND_SWEEP)
+		thr->heap->mark_and_sweep_base_flags = prev_mark_and_sweep_base_flags;
+#endif
+		if (pcall_rc == DUK_EXEC_SUCCESS) {
+			DUK_DD(DUK_DDPRINT("fast path successful"));
+			DUK_BW_PUSH_AS_STRING(thr, &js_ctx->bw);
+			goto replace_finished;
+		}
+
+		/* We come here for actual aborts (like encountering .toJSON())
+		 * but also for recursion/loop errors.  Bufwriter size can be
+		 * kept because we'll probably need at least as much as we've
+		 * allocated so far.
+		 */
+		DUK_D(DUK_DPRINT("fast path failed, serialize using slow path instead"));
+		DUK_BW_RESET_SIZE(thr, &js_ctx->bw);
+		js_ctx->recursion_depth = 0;
+	}
+#endif
+
+	/*
 	 *  Create wrapper object and serialize
 	 */
 
@@ -21510,57 +35113,50 @@ void duk_bi_json_stringify_helper(duk_context *ctx,
 	duk_dup(ctx, idx_value);
 	duk_put_prop_stridx(ctx, -2, DUK_STRIDX_EMPTY_STRING);
 
-	DUK_DDD(DUK_DDDPRINT("before: flags=0x%08lx, buf=%!O, loop=%!T, replacer=%!O, "
-	                     "proplist=%!T, gap=%!O, indent=%!O, holder=%!T",
+	DUK_DDD(DUK_DDDPRINT("before: flags=0x%08lx, loop=%!T, replacer=%!O, "
+	                     "proplist=%!T, gap=%!O, holder=%!T",
 	                     (unsigned long) js_ctx->flags,
-	                     (duk_heaphdr *) js_ctx->h_buf,
 	                     (duk_tval *) duk_get_tval(ctx, js_ctx->idx_loop),
 	                     (duk_heaphdr *) js_ctx->h_replacer,
 	                     (duk_tval *) (js_ctx->idx_proplist >= 0 ? duk_get_tval(ctx, js_ctx->idx_proplist) : NULL),
 	                     (duk_heaphdr *) js_ctx->h_gap,
-	                     (duk_heaphdr *) js_ctx->h_indent,
 	                     (duk_tval *) duk_get_tval(ctx, -1)));
-	
+
 	/* serialize the wrapper with empty string key */
 
 	duk_push_hstring_stridx(ctx, DUK_STRIDX_EMPTY_STRING);
 
 	/* [ ... buf loop (proplist) (gap) holder "" ] */
 
+	js_ctx->recursion_limit = DUK_USE_JSON_ENC_RECLIMIT;
+	DUK_ASSERT(js_ctx->recursion_depth == 0);
 	undef = duk__enc_value1(js_ctx, idx_holder);  /* [ ... holder key ] -> [ ... holder key val ] */
 
-	DUK_DDD(DUK_DDDPRINT("after: flags=0x%08lx, buf=%!O, loop=%!T, replacer=%!O, "
-	                     "proplist=%!T, gap=%!O, indent=%!O, holder=%!T",
+	DUK_DDD(DUK_DDDPRINT("after: flags=0x%08lx, loop=%!T, replacer=%!O, "
+	                     "proplist=%!T, gap=%!O, holder=%!T",
 	                     (unsigned long) js_ctx->flags,
-	                     (duk_heaphdr *) js_ctx->h_buf,
 	                     (duk_tval *) duk_get_tval(ctx, js_ctx->idx_loop),
 	                     (duk_heaphdr *) js_ctx->h_replacer,
 	                     (duk_tval *) (js_ctx->idx_proplist >= 0 ? duk_get_tval(ctx, js_ctx->idx_proplist) : NULL),
 	                     (duk_heaphdr *) js_ctx->h_gap,
-	                     (duk_heaphdr *) js_ctx->h_indent,
 	                     (duk_tval *) duk_get_tval(ctx, -3)));
 
 	if (undef) {
-		/*
-		 *  Result is undefined
-		 */
-
+		/* Result is undefined. */
 		duk_push_undefined(ctx);
 	} else {
-		/*
-		 *  Finish and convert buffer to result string
-		 */
-
+		/* Finish and convert buffer to result string. */
 		duk__enc_value2(js_ctx);  /* [ ... key val ] -> [ ... ] */
-		DUK_ASSERT(js_ctx->h_buf != NULL);
-		duk_push_hbuffer(ctx, (duk_hbuffer *) js_ctx->h_buf);
-		duk_to_string(ctx, -1);
+		DUK_BW_PUSH_AS_STRING(thr, &js_ctx->bw);
 	}
 
 	/* The stack has a variable shape here, so force it to the
 	 * desired one explicitly.
 	 */
 
+#if defined(DUK_USE_JSON_STRINGIFY_FASTPATH)
+ replace_finished:
+#endif
 	duk_replace(ctx, entry_top);
 	duk_set_top(ctx, entry_top + 1);
 
@@ -21580,7 +35176,7 @@ void duk_bi_json_stringify_helper(duk_context *ctx,
  *  Entry points
  */
 
-duk_ret_t duk_bi_json_object_parse(duk_context *ctx) {
+DUK_INTERNAL duk_ret_t duk_bi_json_object_parse(duk_context *ctx) {
 	duk_bi_json_parse_helper(ctx,
 	                         0 /*idx_value*/,
 	                         1 /*idx_replacer*/,
@@ -21588,7 +35184,7 @@ duk_ret_t duk_bi_json_object_parse(duk_context *ctx) {
 	return 1;
 }
 
-duk_ret_t duk_bi_json_object_stringify(duk_context *ctx) {
+DUK_INTERNAL duk_ret_t duk_bi_json_object_stringify(duk_context *ctx) {
 	duk_bi_json_stringify_helper(ctx,
 	                             0 /*idx_value*/,
 	                             1 /*idx_replacer*/,
@@ -21596,6 +35192,12 @@ duk_ret_t duk_bi_json_object_stringify(duk_context *ctx) {
 	                             0 /*flags*/);
 	return 1;
 }
+
+#undef DUK__JSON_DECSTR_BUFSIZE
+#undef DUK__JSON_DECSTR_CHUNKSIZE
+#undef DUK__JSON_ENCSTR_CHUNKSIZE
+#undef DUK__JSON_STRINGIFY_BUFSIZE
+#undef DUK__JSON_MAX_ESC_LEN
 #line 1 "duk_bi_logger.c"
 /*
  *  Logging support
@@ -21604,7 +35206,7 @@ duk_ret_t duk_bi_json_object_stringify(duk_context *ctx) {
 /* include removed: duk_internal.h */
 
 /* 3-letter log level strings */
-static const duk_uint8_t duk__log_level_strings[] = {
+DUK_LOCAL const duk_uint8_t duk__log_level_strings[] = {
 	(duk_uint8_t) DUK_ASC_UC_T, (duk_uint8_t) DUK_ASC_UC_R, (duk_uint8_t) DUK_ASC_UC_C,
 	(duk_uint8_t) DUK_ASC_UC_D, (duk_uint8_t) DUK_ASC_UC_B, (duk_uint8_t) DUK_ASC_UC_G,
 	(duk_uint8_t) DUK_ASC_UC_I, (duk_uint8_t) DUK_ASC_UC_N, (duk_uint8_t) DUK_ASC_UC_F,
@@ -21614,9 +35216,9 @@ static const duk_uint8_t duk__log_level_strings[] = {
 };
 
 /* Constructor */
-duk_ret_t duk_bi_logger_constructor(duk_context *ctx) {
+DUK_INTERNAL duk_ret_t duk_bi_logger_constructor(duk_context *ctx) {
 	duk_hthread *thr = (duk_hthread *) ctx;
-	duk_int_t nargs;  /* FIXME: type */
+	duk_idx_t nargs;
 
 	/* Calling as a non-constructor is not meaningful. */
 	if (!duk_is_constructor_call(ctx)) {
@@ -21638,12 +35240,15 @@ duk_ret_t duk_bi_logger_constructor(duk_context *ctx) {
 
 		if (thr->callstack_top >= 2) {
 			duk_activation *act_caller = thr->callstack + thr->callstack_top - 2;
-			if (act_caller->func) {
+			duk_hobject *func_caller;
+
+			func_caller = DUK_ACT_GET_FUNC(act_caller);
+			if (func_caller) {
 				/* Stripping the filename might be a good idea
 				 * ("/foo/bar/quux.js" -> logger name "quux"),
 				 * but now used verbatim.
 				 */
-				duk_push_hobject(ctx, act_caller->func);
+				duk_push_hobject(ctx, func_caller);
 				duk_get_prop_stridx(ctx, -1, DUK_STRIDX_FILE_NAME);
 				duk_replace(ctx, 0);
 			}
@@ -21668,7 +35273,7 @@ duk_ret_t duk_bi_logger_constructor(duk_context *ctx) {
 /* Default function to format objects.  Tries to use toLogString() but falls
  * back to toString().  Any errors are propagated out without catching.
  */
-duk_ret_t duk_bi_logger_prototype_fmt(duk_context *ctx) {
+DUK_INTERNAL duk_ret_t duk_bi_logger_prototype_fmt(duk_context *ctx) {
 	if (duk_get_prop_stridx(ctx, 0, DUK_STRIDX_TO_LOG_STRING)) {
 		/* [ arg toLogString ] */
 
@@ -21692,7 +35297,7 @@ duk_ret_t duk_bi_logger_prototype_fmt(duk_context *ctx) {
  * This function should avoid coercing the buffer to a string to avoid
  * string table traffic.
  */
-duk_ret_t duk_bi_logger_prototype_raw(duk_context *ctx) {
+DUK_INTERNAL duk_ret_t duk_bi_logger_prototype_raw(duk_context *ctx) {
 	const char *data;
 	duk_size_t data_len;
 
@@ -21702,9 +35307,9 @@ duk_ret_t duk_bi_logger_prototype_raw(duk_context *ctx) {
 
 #ifdef DUK_USE_FILE_IO
 	data = (const char *) duk_require_buffer(ctx, 0, &data_len);
-	DUK_FWRITE((const void *) data, 1, data_len, stderr);
-	DUK_FPUTC((int) '\n', stderr);
-	DUK_FFLUSH(stderr);
+	DUK_FWRITE((const void *) data, 1, data_len, DUK_STDERR);
+	DUK_FPUTC((int) '\n', DUK_STDERR);
+	DUK_FFLUSH(DUK_STDERR);
 #else
 	/* nop */
 #endif
@@ -21716,10 +35321,10 @@ duk_ret_t duk_bi_logger_prototype_raw(duk_context *ctx) {
  * This needs to have small footprint, reasonable performance, minimal
  * memory churn, etc.
  */
-duk_ret_t duk_bi_logger_prototype_log_shared(duk_context *ctx) {
+DUK_INTERNAL duk_ret_t duk_bi_logger_prototype_log_shared(duk_context *ctx) {
 	duk_hthread *thr = (duk_hthread *) ctx;
 	duk_double_t now;
-	duk_small_int_t entry_lev = duk_get_magic(ctx);
+	duk_small_int_t entry_lev = duk_get_current_magic(ctx);
 	duk_small_int_t logger_lev;
 	duk_int_t nargs;
 	duk_int_t i;
@@ -21733,6 +35338,7 @@ duk_ret_t duk_bi_logger_prototype_log_shared(duk_context *ctx) {
 	duk_small_int_t rc;
 
 	DUK_ASSERT(entry_lev >= 0 && entry_lev <= 5);
+	DUK_UNREF(thr);
 
 	/* XXX: sanitize to printable (and maybe ASCII) */
 	/* XXX: better multiline */
@@ -21770,7 +35376,7 @@ duk_ret_t duk_bi_logger_prototype_log_shared(duk_context *ctx) {
 	}
 	/* log level could be popped but that's not necessary */
 
-	now = duk_bi_date_get_now(ctx);
+	now = DUK_USE_DATE_GET_NOW(ctx);
 	duk_bi_date_format_timeval(now, date_buf);
 	date_len = DUK_STRLEN((const char *) date_buf);
 
@@ -21826,48 +35432,30 @@ duk_ret_t duk_bi_logger_prototype_log_shared(duk_context *ctx) {
 	 *  Pass 2
 	 */
 
-	if (tot_len <= DUK_BI_LOGGER_SHORT_MSG_LIMIT) {
-		duk_hbuffer_dynamic *h_buf;
-
-		DUK_DDD(DUK_DDDPRINT("reuse existing small log message buffer, tot_len %ld", (long) tot_len));
-
-		/* We can assert for all buffer properties because user code
-		 * never has access to heap->log_buffer.
-		 */
-
-		DUK_ASSERT(thr != NULL);
-		DUK_ASSERT(thr->heap != NULL);
-		h_buf = thr->heap->log_buffer;
-		DUK_ASSERT(h_buf != NULL);
-		DUK_ASSERT(DUK_HBUFFER_HAS_DYNAMIC((duk_hbuffer *) h_buf));
-		DUK_ASSERT(DUK_HBUFFER_DYNAMIC_GET_USABLE_SIZE(h_buf) == DUK_BI_LOGGER_SHORT_MSG_LIMIT);
-
-		/* Set buffer 'visible size' to actual message length and
-		 * push it to the stack.
-		 */
+	/* XXX: There used to be a shared log buffer here, but it was removed
+	 * when dynamic buffer spare was removed.  The problem with using
+	 * bufwriter is that, without the spare, the buffer gets passed on
+	 * as an argument to the raw() call so it'd need to be resized
+	 * (reallocated) anyway.  If raw() call convention is changed, this
+	 * could be made more efficient.
+	 */
 
-		DUK_HBUFFER_SET_SIZE((duk_hbuffer *) h_buf, tot_len);
-		duk_push_hbuffer(ctx, (duk_hbuffer *) h_buf);
-		buf = (duk_uint8_t *) DUK_HBUFFER_DYNAMIC_GET_CURR_DATA_PTR(h_buf);
-	} else {
-		DUK_DDD(DUK_DDDPRINT("use a one-off large log message buffer, tot_len %ld", (long) tot_len));
-		buf = (duk_uint8_t *) duk_push_fixed_buffer(ctx, tot_len);
-	}
+	buf = (duk_uint8_t *) duk_push_fixed_buffer(ctx, tot_len);
 	DUK_ASSERT(buf != NULL);
 	p = buf;
 
-	DUK_MEMCPY((void *) p, (void *) date_buf, date_len);
+	DUK_MEMCPY((void *) p, (const void *) date_buf, (size_t) date_len);
 	p += date_len;
 	*p++ = (duk_uint8_t) DUK_ASC_SPACE;
 
 	q = duk__log_level_strings + (entry_lev * 3);
-	DUK_MEMCPY((void *) p, (void *) q, (duk_size_t) 3);
+	DUK_MEMCPY((void *) p, (const void *) q, (size_t) 3);
 	p += 3;
 
 	*p++ = (duk_uint8_t) DUK_ASC_SPACE;
 
 	arg_str = (const duk_uint8_t *) duk_get_lstring(ctx, -2, &arg_len);
-	DUK_MEMCPY((void *) p, (const void *) arg_str, arg_len);
+	DUK_MEMCPY((void *) p, (const void *) arg_str, (size_t) arg_len);
 	p += arg_len;
 
 	*p++ = (duk_uint8_t) DUK_ASC_COLON;
@@ -21877,13 +35465,29 @@ duk_ret_t duk_bi_logger_prototype_log_shared(duk_context *ctx) {
 
 		arg_str = (const duk_uint8_t *) duk_get_lstring(ctx, i, &arg_len);
 		DUK_ASSERT(arg_str != NULL);
-		DUK_MEMCPY((void *) p, (const void *) arg_str, arg_len);
+		DUK_MEMCPY((void *) p, (const void *) arg_str, (size_t) arg_len);
 		p += arg_len;
 	}
 	DUK_ASSERT(buf + tot_len == p);
 
 	/* [ arg1 ... argN this loggerLevel loggerName buffer ] */
 
+#if defined(DUK_USE_DEBUGGER_SUPPORT) && defined(DUK_USE_DEBUGGER_FWD_LOGGING)
+	/* Do debugger forwarding before raw() because the raw() function
+	 * doesn't get the log level right now.
+	 */
+	if (DUK_HEAP_IS_DEBUGGER_ATTACHED(thr->heap)) {
+		const char *log_buf;
+		duk_size_t sz_buf;
+		log_buf = (const char *) duk_get_buffer(ctx, -1, &sz_buf);
+		DUK_ASSERT(log_buf != NULL);
+		duk_debug_write_notify(thr, DUK_DBG_CMD_LOG);
+		duk_debug_write_int(thr, (duk_int32_t) entry_lev);
+		duk_debug_write_string(thr, (const char *) log_buf, sz_buf);
+		duk_debug_write_eom(thr);
+	}
+#endif
+
 	/* Call this.raw(msg); look up through the instance allows user to override
 	 * the raw() function in the instance or in the prototype for maximum
 	 * flexibility.
@@ -21916,7 +35520,7 @@ duk_ret_t duk_bi_logger_prototype_log_shared(duk_context *ctx) {
 typedef double (*duk__one_arg_func)(double);
 typedef double (*duk__two_arg_func)(double, double);
 
-static duk_ret_t duk__math_minmax(duk_context *ctx, duk_double_t initial, duk__two_arg_func min_max) {
+DUK_LOCAL duk_ret_t duk__math_minmax(duk_context *ctx, duk_double_t initial, duk__two_arg_func min_max) {
 	duk_idx_t n = duk_get_top(ctx);
 	duk_idx_t i;
 	duk_double_t res = initial;
@@ -21947,7 +35551,7 @@ static duk_ret_t duk__math_minmax(duk_context *ctx, duk_double_t initial, duk__t
 	return 1;
 }
 
-static double duk__fmin_fixed(double x, double y) {
+DUK_LOCAL double duk__fmin_fixed(double x, double y) {
 	/* fmin() with args -0 and +0 is not guaranteed to return
 	 * -0 as Ecmascript requires.
 	 */
@@ -21966,7 +35570,7 @@ static double duk__fmin_fixed(double x, double y) {
 #endif
 }
 
-static double duk__fmax_fixed(double x, double y) {
+DUK_LOCAL double duk__fmax_fixed(double x, double y) {
 	/* fmax() with args -0 and +0 is not guaranteed to return
 	 * +0 as Ecmascript requires.
 	 */
@@ -21984,7 +35588,7 @@ static double duk__fmax_fixed(double x, double y) {
 #endif
 }
 
-static double duk__round_fixed(double x) {
+DUK_LOCAL double duk__round_fixed(double x) {
 	/* Numbers half-way between integers must be rounded towards +Infinity,
 	 * e.g. -3.5 must be rounded to -3 (not -4).  When rounded to zero, zero
 	 * sign must be set appropriately.  E5.1 Section 15.8.2.15.
@@ -22025,7 +35629,7 @@ static double duk__round_fixed(double x) {
 	return DUK_FLOOR(x + 0.5);
 }
 
-static double duk__pow_fixed(double x, double y) {
+DUK_LOCAL double duk__pow_fixed(double x, double y) {
 	/* The ANSI C pow() semantics differ from Ecmascript.
 	 *
 	 * E.g. when x==1 and y is +/- infinite, the Ecmascript required
@@ -22094,49 +35698,49 @@ static double duk__pow_fixed(double x, double y) {
  * or inline functions and are thus not suitable to be used as function pointers.
  */
 #if defined(DUK_USE_AVOID_PLATFORM_FUNCPTRS)
-static double duk__fabs(double x) {
-	return fabs(x);
+DUK_LOCAL double duk__fabs(double x) {
+	return DUK_FABS(x);
 }
-static double duk__acos(double x) {
-	return acos(x);
+DUK_LOCAL double duk__acos(double x) {
+	return DUK_ACOS(x);
 }
-static double duk__asin(double x) {
-	return asin(x);
+DUK_LOCAL double duk__asin(double x) {
+	return DUK_ASIN(x);
 }
-static double duk__atan(double x) {
-	return atan(x);
+DUK_LOCAL double duk__atan(double x) {
+	return DUK_ATAN(x);
 }
-static double duk__ceil(double x) {
-	return ceil(x);
+DUK_LOCAL double duk__ceil(double x) {
+	return DUK_CEIL(x);
 }
-static double duk__cos(double x) {
-	return cos(x);
+DUK_LOCAL double duk__cos(double x) {
+	return DUK_COS(x);
 }
-static double duk__exp(double x) {
-	return exp(x);
+DUK_LOCAL double duk__exp(double x) {
+	return DUK_EXP(x);
 }
-static double duk__floor(double x) {
-	return floor(x);
+DUK_LOCAL double duk__floor(double x) {
+	return DUK_FLOOR(x);
 }
-static double duk__log(double x) {
-	return log(x);
+DUK_LOCAL double duk__log(double x) {
+	return DUK_LOG(x);
 }
-static double duk__sin(double x) {
-	return sin(x);
+DUK_LOCAL double duk__sin(double x) {
+	return DUK_SIN(x);
 }
-static double duk__sqrt(double x) {
-	return sqrt(x);
+DUK_LOCAL double duk__sqrt(double x) {
+	return DUK_SQRT(x);
 }
-static double duk__tan(double x) {
-	return tan(x);
+DUK_LOCAL double duk__tan(double x) {
+	return DUK_TAN(x);
 }
-static double duk__atan2(double x, double y) {
-	return atan2(x, y);
+DUK_LOCAL double duk__atan2(double x, double y) {
+	return DUK_ATAN2(x, y);
 }
 #endif  /* DUK_USE_AVOID_PLATFORM_FUNCPTRS */
 
 /* order must match constants in genbuiltins.py */
-static const duk__one_arg_func duk__one_arg_funcs[] = {
+DUK_LOCAL const duk__one_arg_func duk__one_arg_funcs[] = {
 #if defined(DUK_USE_AVOID_PLATFORM_FUNCPTRS)
 	duk__fabs,
 	duk__acos,
@@ -22169,7 +35773,7 @@ static const duk__one_arg_func duk__one_arg_funcs[] = {
 };
 
 /* order must match constants in genbuiltins.py */
-static const duk__two_arg_func duk__two_arg_funcs[] = {
+DUK_LOCAL const duk__two_arg_func duk__two_arg_funcs[] = {
 #if defined(DUK_USE_AVOID_PLATFORM_FUNCPTRS)
 	duk__atan2,
 	duk__pow_fixed
@@ -22179,8 +35783,8 @@ static const duk__two_arg_func duk__two_arg_funcs[] = {
 #endif
 };
 
-duk_ret_t duk_bi_math_object_onearg_shared(duk_context *ctx) {
-	duk_small_int_t fun_idx = duk_get_magic(ctx);
+DUK_INTERNAL duk_ret_t duk_bi_math_object_onearg_shared(duk_context *ctx) {
+	duk_small_int_t fun_idx = duk_get_current_magic(ctx);
 	duk__one_arg_func fun;
 
 	DUK_ASSERT(fun_idx >= 0);
@@ -22190,8 +35794,8 @@ duk_ret_t duk_bi_math_object_onearg_shared(duk_context *ctx) {
 	return 1;
 }
 
-duk_ret_t duk_bi_math_object_twoarg_shared(duk_context *ctx) {
-	duk_small_int_t fun_idx = duk_get_magic(ctx);
+DUK_INTERNAL duk_ret_t duk_bi_math_object_twoarg_shared(duk_context *ctx) {
+	duk_small_int_t fun_idx = duk_get_current_magic(ctx);
 	duk__two_arg_func fun;
 
 	DUK_ASSERT(fun_idx >= 0);
@@ -22201,15 +35805,15 @@ duk_ret_t duk_bi_math_object_twoarg_shared(duk_context *ctx) {
 	return 1;
 }
 
-duk_ret_t duk_bi_math_object_max(duk_context *ctx) {
+DUK_INTERNAL duk_ret_t duk_bi_math_object_max(duk_context *ctx) {
 	return duk__math_minmax(ctx, -DUK_DOUBLE_INFINITY, duk__fmax_fixed);
 }
 
-duk_ret_t duk_bi_math_object_min(duk_context *ctx) {
+DUK_INTERNAL duk_ret_t duk_bi_math_object_min(duk_context *ctx) {
 	return duk__math_minmax(ctx, DUK_DOUBLE_INFINITY, duk__fmin_fixed);
 }
 
-duk_ret_t duk_bi_math_object_random(duk_context *ctx) {
+DUK_INTERNAL duk_ret_t duk_bi_math_object_random(duk_context *ctx) {
 	duk_push_number(ctx, (duk_double_t) duk_util_tinyrandom_get_double((duk_hthread *) ctx));
 	return 1;
 }
@@ -22218,27 +35822,27 @@ duk_ret_t duk_bi_math_object_random(duk_context *ctx) {
 
 /* A stubbed built-in is useful for e.g. compilation torture testing with BCC. */
 
-duk_ret_t duk_bi_math_object_onearg_shared(duk_context *ctx) {
+DUK_INTERNAL duk_ret_t duk_bi_math_object_onearg_shared(duk_context *ctx) {
 	DUK_UNREF(ctx);
 	return DUK_RET_UNIMPLEMENTED_ERROR;
 }
 
-duk_ret_t duk_bi_math_object_twoarg_shared(duk_context *ctx) {
+DUK_INTERNAL duk_ret_t duk_bi_math_object_twoarg_shared(duk_context *ctx) {
 	DUK_UNREF(ctx);
 	return DUK_RET_UNIMPLEMENTED_ERROR;
 }
 
-duk_ret_t duk_bi_math_object_max(duk_context *ctx) {
+DUK_INTERNAL duk_ret_t duk_bi_math_object_max(duk_context *ctx) {
 	DUK_UNREF(ctx);
 	return DUK_RET_UNIMPLEMENTED_ERROR;
 }
 
-duk_ret_t duk_bi_math_object_min(duk_context *ctx) {
+DUK_INTERNAL duk_ret_t duk_bi_math_object_min(duk_context *ctx) {
 	DUK_UNREF(ctx);
 	return DUK_RET_UNIMPLEMENTED_ERROR;
 }
 
-duk_ret_t duk_bi_math_object_random(duk_context *ctx) {
+DUK_INTERNAL duk_ret_t duk_bi_math_object_random(duk_context *ctx) {
 	DUK_UNREF(ctx);
 	return DUK_RET_UNIMPLEMENTED_ERROR;
 }
@@ -22249,13 +35853,9 @@ duk_ret_t duk_bi_math_object_random(duk_context *ctx) {
  *  Number built-ins
  */
 
-/* FIXME: needs to be refactored when exact parsing / string conversion
- * primitives are implemented.
- */
-
 /* include removed: duk_internal.h */
 
-static duk_double_t duk__push_this_number_plain(duk_context *ctx) {
+DUK_LOCAL duk_double_t duk__push_this_number_plain(duk_context *ctx) {
 	duk_hobject *h;
 
 	/* Number built-in accepts a plain number or a Number object (whose
@@ -22268,7 +35868,7 @@ static duk_double_t duk__push_this_number_plain(duk_context *ctx) {
 		goto done;
 	}
 	h = duk_get_hobject(ctx, -1);
-	if (!h || 
+	if (!h ||
 	    (DUK_HOBJECT_GET_CLASS_NUMBER(h) != DUK_HOBJECT_CLASS_NUMBER)) {
 		DUK_DDD(DUK_DDDPRINT("unacceptable this value: %!T", (duk_tval *) duk_get_tval(ctx, -1)));
 		DUK_ERROR((duk_hthread *) ctx, DUK_ERR_TYPE_ERROR, "expected a number");
@@ -22283,10 +35883,13 @@ static duk_double_t duk__push_this_number_plain(duk_context *ctx) {
 	return duk_get_number(ctx, -1);
 }
 
-duk_ret_t duk_bi_number_constructor(duk_context *ctx) {
+DUK_INTERNAL duk_ret_t duk_bi_number_constructor(duk_context *ctx) {
+	duk_hthread *thr = (duk_hthread *) ctx;
 	duk_idx_t nargs;
 	duk_hobject *h_this;
 
+	DUK_UNREF(thr);
+
 	/*
 	 *  The Number constructor uses ToNumber(arg) for number coercion
 	 *  (coercing an undefined argument to NaN).  However, if the
@@ -22319,27 +35922,27 @@ duk_ret_t duk_bi_number_constructor(duk_context *ctx) {
 	 *  (above).  String internal value is immutable.
 	 */
 
-	/* FIXME: helper */
+	/* XXX: helper */
 	duk_push_this(ctx);
 	h_this = duk_get_hobject(ctx, -1);
 	DUK_ASSERT(h_this != NULL);
 	DUK_HOBJECT_SET_CLASS_NUMBER(h_this, DUK_HOBJECT_CLASS_NUMBER);
 
-	DUK_ASSERT(h_this->prototype == ((duk_hthread *) ctx)->builtins[DUK_BIDX_NUMBER_PROTOTYPE]);
+	DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h_this) == thr->builtins[DUK_BIDX_NUMBER_PROTOTYPE]);
 	DUK_ASSERT(DUK_HOBJECT_GET_CLASS_NUMBER(h_this) == DUK_HOBJECT_CLASS_NUMBER);
 	DUK_ASSERT(DUK_HOBJECT_HAS_EXTENSIBLE(h_this));
 
 	duk_dup(ctx, 0);  /* -> [ val obj val ] */
-	duk_def_prop_stridx(ctx, -2, DUK_STRIDX_INT_VALUE, DUK_PROPDESC_FLAGS_NONE);
+	duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_INT_VALUE, DUK_PROPDESC_FLAGS_NONE);
 	return 0;  /* no return value -> don't replace created value */
 }
 
-duk_ret_t duk_bi_number_prototype_value_of(duk_context *ctx) {
+DUK_INTERNAL duk_ret_t duk_bi_number_prototype_value_of(duk_context *ctx) {
 	(void) duk__push_this_number_plain(ctx);
 	return 1;
 }
 
-duk_ret_t duk_bi_number_prototype_to_string(duk_context *ctx) {
+DUK_INTERNAL duk_ret_t duk_bi_number_prototype_to_string(duk_context *ctx) {
 	duk_small_int_t radix;
 	duk_small_uint_t n2s_flags;
 
@@ -22360,7 +35963,7 @@ duk_ret_t duk_bi_number_prototype_to_string(duk_context *ctx) {
 	return 1;
 }
 
-duk_ret_t duk_bi_number_prototype_to_locale_string(duk_context *ctx) {
+DUK_INTERNAL duk_ret_t duk_bi_number_prototype_to_locale_string(duk_context *ctx) {
 	/* XXX: just use toString() for now; permitted although not recommended.
 	 * nargs==1, so radix is passed to toString().
 	 */
@@ -22371,9 +35974,9 @@ duk_ret_t duk_bi_number_prototype_to_locale_string(duk_context *ctx) {
  *  toFixed(), toExponential(), toPrecision()
  */
 
-/* FIXME: shared helper for toFixed(), toExponential(), toPrecision()? */
+/* XXX: shared helper for toFixed(), toExponential(), toPrecision()? */
 
-duk_ret_t duk_bi_number_prototype_to_fixed(duk_context *ctx) {
+DUK_INTERNAL duk_ret_t duk_bi_number_prototype_to_fixed(duk_context *ctx) {
 	duk_small_int_t frac_digits;
 	duk_double_t d;
 	duk_small_int_t c;
@@ -22406,7 +36009,7 @@ duk_ret_t duk_bi_number_prototype_to_fixed(duk_context *ctx) {
 	return 1;
 }
 
-duk_ret_t duk_bi_number_prototype_to_exponential(duk_context *ctx) {
+DUK_INTERNAL duk_ret_t duk_bi_number_prototype_to_exponential(duk_context *ctx) {
 	duk_bool_t frac_undefined;
 	duk_small_int_t frac_digits;
 	duk_double_t d;
@@ -22440,7 +36043,7 @@ duk_ret_t duk_bi_number_prototype_to_exponential(duk_context *ctx) {
 	return 1;
 }
 
-duk_ret_t duk_bi_number_prototype_to_precision(duk_context *ctx) {
+DUK_INTERNAL duk_ret_t duk_bi_number_prototype_to_precision(duk_context *ctx) {
 	/* The specification has quite awkward order of coercion and
 	 * checks for toPrecision().  The operations below are a bit
 	 * reordered, within constraints of observable side effects.
@@ -22493,7 +36096,7 @@ duk_ret_t duk_bi_number_prototype_to_precision(duk_context *ctx) {
 
 /* include removed: duk_internal.h */
 
-duk_ret_t duk_bi_object_constructor(duk_context *ctx) {
+DUK_INTERNAL duk_ret_t duk_bi_object_constructor(duk_context *ctx) {
 	if (!duk_is_constructor_call(ctx) &&
 	    !duk_is_null_or_undefined(ctx, 0)) {
 		duk_to_object(ctx, 0);
@@ -22506,13 +36109,15 @@ duk_ret_t duk_bi_object_constructor(duk_context *ctx) {
 
 	/* Pointer and buffer primitive values are treated like other
 	 * primitives values which have a fully fledged object counterpart:
-	 * promote to an object value.
+	 * promote to an object value.  Lightfuncs are coerced with
+	 * ToObject() even they could also be returned as is.
 	 */
 	if (duk_check_type_mask(ctx, 0, DUK_TYPE_MASK_STRING |
 	                                DUK_TYPE_MASK_BOOLEAN |
 	                                DUK_TYPE_MASK_NUMBER |
 	                                DUK_TYPE_MASK_POINTER |
-	                                DUK_TYPE_MASK_BUFFER)) {
+	                                DUK_TYPE_MASK_BUFFER |
+	                                DUK_TYPE_MASK_LIGHTFUNC)) {
 		duk_to_object(ctx, 0);
 		return 1;
 	}
@@ -22527,19 +36132,23 @@ duk_ret_t duk_bi_object_constructor(duk_context *ctx) {
 /* Shared helper to implement Object.getPrototypeOf and the ES6
  * Object.prototype.__proto__ getter.
  *
- * https://people.mozilla.org/~jorendorff/es6-draft.html#sec-get-object.prototype.__proto__
+ * http://www.ecma-international.org/ecma-262/6.0/index.html#sec-get-object.prototype.__proto__
  */
-duk_ret_t duk_bi_object_getprototype_shared(duk_context *ctx) {
+DUK_INTERNAL duk_ret_t duk_bi_object_getprototype_shared(duk_context *ctx) {
+	duk_hthread *thr = (duk_hthread *) ctx;
 	duk_hobject *h;
+	duk_hobject *proto;
+
+	DUK_UNREF(thr);
 
 	/* magic: 0=getter call, 1=Object.getPrototypeOf */
-	if (duk_get_magic(ctx) == 0) {
+	if (duk_get_current_magic(ctx) == 0) {
 		duk_push_this_coercible_to_object(ctx);
 		duk_insert(ctx, 0);
 	}
 
-	h = duk_require_hobject(ctx, 0);
-	DUK_ASSERT(h != NULL);
+	h = duk_require_hobject_or_lfunc(ctx, 0);
+	/* h is NULL for lightfunc */
 
 	/* XXX: should the API call handle this directly, i.e. attempt
 	 * to duk_push_hobject(ctx, null) would push a null instead?
@@ -22547,10 +36156,15 @@ duk_ret_t duk_bi_object_getprototype_shared(duk_context *ctx) {
 	 * not wanted here.)
 	 */
 
-	if (h->prototype) {
-		duk_push_hobject(ctx, h->prototype);
+	if (h == NULL) {
+		duk_push_hobject_bidx(ctx, DUK_BIDX_FUNCTION_PROTOTYPE);
 	} else {
-		duk_push_null(ctx);
+		proto = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h);
+		if (proto) {
+			duk_push_hobject(ctx, proto);
+		} else {
+			duk_push_null(ctx);
+		}
 	}
 	return 1;
 }
@@ -22558,10 +36172,10 @@ duk_ret_t duk_bi_object_getprototype_shared(duk_context *ctx) {
 /* Shared helper to implement ES6 Object.setPrototypeOf and
  * Object.prototype.__proto__ setter.
  *
- * https://people.mozilla.org/~jorendorff/es6-draft.html#sec-get-object.prototype.__proto__
- * https://people.mozilla.org/~jorendorff/es6-draft.html#sec-object.setprototypeof
+ * http://www.ecma-international.org/ecma-262/6.0/index.html#sec-get-object.prototype.__proto__
+ * http://www.ecma-international.org/ecma-262/6.0/index.html#sec-object.setprototypeof
  */
-duk_ret_t duk_bi_object_setprototype_shared(duk_context *ctx) {
+DUK_INTERNAL duk_ret_t duk_bi_object_setprototype_shared(duk_context *ctx) {
 	duk_hthread *thr = (duk_hthread *) ctx;
 	duk_hobject *h_obj;
 	duk_hobject *h_new_proto;
@@ -22571,7 +36185,7 @@ duk_ret_t duk_bi_object_setprototype_shared(duk_context *ctx) {
 	/* Preliminaries for __proto__ and setPrototypeOf (E6 19.1.2.18 steps 1-4);
 	 * magic: 0=setter call, 1=Object.setPrototypeOf
 	 */
-	if (duk_get_magic(ctx) == 0) {
+	if (duk_get_current_magic(ctx) == 0) {
 		duk_push_this_check_object_coercible(ctx);
 		duk_insert(ctx, 0);
 		if (!duk_check_type_mask(ctx, 1, DUK_TYPE_MASK_NULL | DUK_TYPE_MASK_OBJECT)) {
@@ -22586,25 +36200,31 @@ duk_ret_t duk_bi_object_setprototype_shared(duk_context *ctx) {
 		duk_require_object_coercible(ctx, 0);
 		duk_require_type_mask(ctx, 1, DUK_TYPE_MASK_NULL | DUK_TYPE_MASK_OBJECT);
 	}
+
+	h_new_proto = duk_get_hobject(ctx, 1);
+	/* h_new_proto may be NULL */
+	if (duk_is_lightfunc(ctx, 0)) {
+		if (h_new_proto == thr->builtins[DUK_BIDX_FUNCTION_PROTOTYPE]) {
+			goto skip;
+		}
+		goto fail_nonextensible;
+	}
 	h_obj = duk_get_hobject(ctx, 0);
 	if (!h_obj) {
 		goto skip;
 	}
-	h_new_proto = duk_get_hobject(ctx, 1);
 	DUK_ASSERT(h_obj != NULL);
-	/* h_new_proto may be NULL */
 
 	/* [[SetPrototypeOf]] standard behavior, E6 9.1.2 */
-	/* NOTE: steps 7-8 seem to be a cut-paste bug in the E6 draft */
 	/* TODO: implement Proxy object support here */
 
-	if (h_new_proto == h_obj->prototype) {
+	if (h_new_proto == DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h_obj)) {
 		goto skip;
 	}
 	if (!DUK_HOBJECT_HAS_EXTENSIBLE(h_obj)) {
 		goto fail_nonextensible;
 	}
-	for (h_curr = h_new_proto; h_curr != NULL; h_curr = h_curr->prototype) {
+	for (h_curr = h_new_proto; h_curr != NULL; h_curr = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h_curr)) {
 		/* Loop prevention */
 		if (h_curr == h_obj) {
 			goto fail_loop;
@@ -22622,12 +36242,12 @@ duk_ret_t duk_bi_object_setprototype_shared(duk_context *ctx) {
 	return DUK_RET_TYPE_ERROR;
 }
 
-duk_ret_t duk_bi_object_constructor_get_own_property_descriptor(duk_context *ctx) {
+DUK_INTERNAL duk_ret_t duk_bi_object_constructor_get_own_property_descriptor(duk_context *ctx) {
 	/* XXX: no need for indirect call */
 	return duk_hobject_object_get_own_property_descriptor(ctx);
 }
 
-duk_ret_t duk_bi_object_constructor_create(duk_context *ctx) {
+DUK_INTERNAL duk_ret_t duk_bi_object_constructor_create(duk_context *ctx) {
 	duk_tval *tv;
 	duk_hobject *proto = NULL;
 
@@ -22652,15 +36272,15 @@ duk_ret_t duk_bi_object_constructor_create(duk_context *ctx) {
 	if (!duk_is_undefined(ctx, 1)) {
 		/* [ O Properties obj ] */
 
-		/* Use original function.  No need to get it explicitly,
-		 * just call the helper.
-		 */
-
 		duk_replace(ctx, 0);
 
 		/* [ obj Properties ] */
 
-		return duk_hobject_object_define_properties(ctx);
+		/* Just call the "original" Object.defineProperties() to
+		 * finish up.
+		 */
+
+		return duk_bi_object_constructor_define_properties(ctx);
 	}
 
 	/* [ O Properties obj ] */
@@ -22668,25 +36288,171 @@ duk_ret_t duk_bi_object_constructor_create(duk_context *ctx) {
 	return 1;
 }
 
-duk_ret_t duk_bi_object_constructor_define_property(duk_context *ctx) {
-	/* XXX: no need for indirect call */
-	return duk_hobject_object_define_property(ctx);
+DUK_INTERNAL duk_ret_t duk_bi_object_constructor_define_property(duk_context *ctx) {
+	duk_hobject *obj;
+	duk_hstring *key;
+	duk_hobject *get;
+	duk_hobject *set;
+	duk_idx_t idx_value;
+	duk_uint_t defprop_flags;
+
+	DUK_ASSERT(ctx != NULL);
+
+	DUK_DDD(DUK_DDDPRINT("Object.defineProperty(): ctx=%p obj=%!T key=%!T desc=%!T",
+	                     (void *) ctx,
+	                     (duk_tval *) duk_get_tval(ctx, 0),
+	                     (duk_tval *) duk_get_tval(ctx, 1),
+	                     (duk_tval *) duk_get_tval(ctx, 2)));
+
+	/* [ obj key desc ] */
+
+	/* Lightfuncs are currently supported by coercing to a temporary
+	 * Function object; changes will be allowed (the coerced value is
+	 * extensible) but will be lost.
+	 */
+	obj = duk_require_hobject_or_lfunc_coerce(ctx, 0);
+	(void) duk_to_string(ctx, 1);
+	key = duk_require_hstring(ctx, 1);
+	(void) duk_require_hobject(ctx, 2);
+
+	DUK_ASSERT(obj != NULL);
+	DUK_ASSERT(key != NULL);
+	DUK_ASSERT(duk_get_hobject(ctx, 2) != NULL);
+
+	/*
+	 *  Validate and convert argument property descriptor (an Ecmascript
+	 *  object) into a set of defprop_flags and possibly property value,
+	 *  getter, and/or setter values on the value stack.
+	 *
+	 *  Lightfunc set/get values are coerced to full Functions.
+	 */
+
+	duk_hobject_prepare_property_descriptor(ctx,
+	                                        2 /*idx_desc*/,
+	                                        &defprop_flags,
+	                                        &idx_value,
+	                                        &get,
+	                                        &set);
+
+	/*
+	 *  Use Object.defineProperty() helper for the actual operation.
+	 */
+
+	duk_hobject_define_property_helper(ctx,
+	                                   defprop_flags,
+	                                   obj,
+	                                   key,
+	                                   idx_value,
+	                                   get,
+	                                   set);
+
+	/* Ignore the normalize/validate helper outputs on the value stack,
+	 * they're popped automatically.
+	 */
+
+	/*
+	 *  Return target object.
+	 */
+
+	duk_push_hobject(ctx, obj);
+	return 1;
 }
 
-duk_ret_t duk_bi_object_constructor_define_properties(duk_context *ctx) {
-	/* XXX: no need for indirect call */
-	return duk_hobject_object_define_properties(ctx);
+DUK_INTERNAL duk_ret_t duk_bi_object_constructor_define_properties(duk_context *ctx) {
+	duk_small_uint_t pass;
+	duk_uint_t defprop_flags;
+	duk_hobject *obj;
+	duk_idx_t idx_value;
+	duk_hobject *get;
+	duk_hobject *set;
+
+	/* Lightfunc handling by ToObject() coercion. */
+	obj = duk_require_hobject_or_lfunc_coerce(ctx, 0);  /* target */
+	DUK_ASSERT(obj != NULL);
+
+	duk_to_object(ctx, 1);        /* properties object */
+
+	DUK_DDD(DUK_DDDPRINT("target=%!iT, properties=%!iT",
+	                     (duk_tval *) duk_get_tval(ctx, 0),
+	                     (duk_tval *) duk_get_tval(ctx, 1)));
+
+	/*
+	 *  Two pass approach to processing the property descriptors.
+	 *  On first pass validate and normalize all descriptors before
+	 *  any changes are made to the target object.  On second pass
+	 *  make the actual modifications to the target object.
+	 *
+	 *  Right now we'll just use the same normalize/validate helper
+	 *  on both passes, ignoring its outputs on the first pass.
+	 */
+
+	for (pass = 0; pass < 2; pass++) {
+		duk_set_top(ctx, 2);  /* -> [ hobject props ] */
+		duk_enum(ctx, 1, DUK_ENUM_OWN_PROPERTIES_ONLY /*enum_flags*/);
+
+		for (;;) {
+			duk_hstring *key;
+
+			/* [ hobject props enum(props) ] */
+
+			duk_set_top(ctx, 3);
+
+			if (!duk_next(ctx, 2, 1 /*get_value*/)) {
+				break;
+			}
+
+			DUK_DDD(DUK_DDDPRINT("-> key=%!iT, desc=%!iT",
+			                     (duk_tval *) duk_get_tval(ctx, -2),
+			                     (duk_tval *) duk_get_tval(ctx, -1)));
+
+			/* [ hobject props enum(props) key desc ] */
+
+			duk_hobject_prepare_property_descriptor(ctx,
+			                                        4 /*idx_desc*/,
+			                                        &defprop_flags,
+			                                        &idx_value,
+			                                        &get,
+			                                        &set);
+
+			/* [ hobject props enum(props) key desc value? getter? setter? ] */
+
+			if (pass == 0) {
+				continue;
+			}
+
+			key = duk_get_hstring(ctx, 3);
+			DUK_ASSERT(key != NULL);
+
+			duk_hobject_define_property_helper(ctx,
+			                                   defprop_flags,
+			                                   obj,
+			                                   key,
+			                                   idx_value,
+			                                   get,
+			                                   set);
+		}
+	}
+
+	/*
+	 *  Return target object
+	 */
+
+	duk_dup(ctx, 0);
+	return 1;
 }
 
-duk_ret_t duk_bi_object_constructor_seal_freeze_shared(duk_context *ctx) {
+DUK_INTERNAL duk_ret_t duk_bi_object_constructor_seal_freeze_shared(duk_context *ctx) {
 	duk_hthread *thr = (duk_hthread *) ctx;
 	duk_hobject *h;
 	duk_bool_t is_freeze;
 
-	h = duk_require_hobject(ctx, 0);
-	DUK_ASSERT(h != NULL);
+	h = duk_require_hobject_or_lfunc(ctx, 0);
+	if (!h) {
+		/* Lightfunc, always success. */
+		return 1;
+	}
 
-	is_freeze = (duk_bool_t) duk_get_magic(ctx);
+	is_freeze = (duk_bool_t) duk_get_current_magic(ctx);
 	duk_hobject_object_seal_freeze_helper(thr, h, is_freeze);
 
 	/* Sealed and frozen objects cannot gain any more properties,
@@ -22697,11 +36463,15 @@ duk_ret_t duk_bi_object_constructor_seal_freeze_shared(duk_context *ctx) {
 	return 1;
 }
 
-duk_ret_t duk_bi_object_constructor_prevent_extensions(duk_context *ctx) {
+DUK_INTERNAL duk_ret_t duk_bi_object_constructor_prevent_extensions(duk_context *ctx) {
 	duk_hthread *thr = (duk_hthread *) ctx;
 	duk_hobject *h;
 
-	h = duk_require_hobject(ctx, 0);
+	h = duk_require_hobject_or_lfunc(ctx, 0);
+	if (!h) {
+		/* Lightfunc, always success. */
+		return 1;
+	}
 	DUK_ASSERT(h != NULL);
 
 	DUK_HOBJECT_CLEAR_EXTENSIBLE(h);
@@ -22710,206 +36480,557 @@ duk_ret_t duk_bi_object_constructor_prevent_extensions(duk_context *ctx) {
 	 * so this is a good time to compact.
 	 */
 	duk_hobject_compact_props(thr, h);
-	
+
+	return 1;
+}
+
+DUK_INTERNAL duk_ret_t duk_bi_object_constructor_is_sealed_frozen_shared(duk_context *ctx) {
+	duk_hobject *h;
+	duk_bool_t is_frozen;
+	duk_bool_t rc;
+
+	h = duk_require_hobject_or_lfunc(ctx, 0);
+	if (!h) {
+		duk_push_true(ctx);  /* frozen and sealed */
+	} else {
+		is_frozen = duk_get_current_magic(ctx);
+		rc = duk_hobject_object_is_sealed_frozen_helper((duk_hthread *) ctx, h, is_frozen /*is_frozen*/);
+		duk_push_boolean(ctx, rc);
+	}
+	return 1;
+}
+
+DUK_INTERNAL duk_ret_t duk_bi_object_constructor_is_extensible(duk_context *ctx) {
+	duk_hobject *h;
+
+	h = duk_require_hobject_or_lfunc(ctx, 0);
+	if (!h) {
+		duk_push_false(ctx);
+	} else {
+		duk_push_boolean(ctx, DUK_HOBJECT_HAS_EXTENSIBLE(h));
+	}
 	return 1;
 }
 
-duk_ret_t duk_bi_object_constructor_is_sealed_frozen_shared(duk_context *ctx) {
-	duk_hobject *h;
-	duk_bool_t is_frozen;
-	duk_bool_t rc;
+/* Shared helper for Object.getOwnPropertyNames() and Object.keys().
+ * Magic: 0=getOwnPropertyNames, 1=Object.keys.
+ */
+DUK_INTERNAL duk_ret_t duk_bi_object_constructor_keys_shared(duk_context *ctx) {
+	duk_hthread *thr = (duk_hthread *) ctx;
+	duk_hobject *obj;
+#if defined(DUK_USE_ES6_PROXY)
+	duk_hobject *h_proxy_target;
+	duk_hobject *h_proxy_handler;
+	duk_hobject *h_trap_result;
+	duk_uarridx_t i, len, idx;
+#endif
+	duk_small_uint_t enum_flags;
+
+	DUK_ASSERT_TOP(ctx, 1);
+	DUK_UNREF(thr);
+
+	obj = duk_require_hobject_or_lfunc_coerce(ctx, 0);
+	DUK_ASSERT(obj != NULL);
+	DUK_UNREF(obj);
+
+#if defined(DUK_USE_ES6_PROXY)
+	if (DUK_LIKELY(!duk_hobject_proxy_check(thr,
+	                                        obj,
+	                                        &h_proxy_target,
+	                                        &h_proxy_handler))) {
+		goto skip_proxy;
+	}
+
+	duk_push_hobject(ctx, h_proxy_handler);
+	if (!duk_get_prop_stridx(ctx, -1, DUK_STRIDX_OWN_KEYS)) {
+		/* Careful with reachability here: don't pop 'obj' before pushing
+		 * proxy target.
+		 */
+		DUK_DDD(DUK_DDDPRINT("no ownKeys trap, get keys of target instead"));
+		duk_pop_2(ctx);
+		duk_push_hobject(ctx, h_proxy_target);
+		duk_replace(ctx, 0);
+		DUK_ASSERT_TOP(ctx, 1);
+		goto skip_proxy;
+	}
+
+	/* [ obj handler trap ] */
+	duk_insert(ctx, -2);
+	duk_push_hobject(ctx, h_proxy_target);  /* -> [ obj trap handler target ] */
+	duk_call_method(ctx, 1 /*nargs*/);      /* -> [ obj trap_result ] */
+	h_trap_result = duk_require_hobject(ctx, -1);
+	DUK_UNREF(h_trap_result);
+
+	len = (duk_uarridx_t) duk_get_length(ctx, -1);
+	idx = 0;
+	duk_push_array(ctx);
+	for (i = 0; i < len; i++) {
+		/* [ obj trap_result res_arr ] */
+		if (duk_get_prop_index(ctx, -2, i) && duk_is_string(ctx, -1)) {
+			/* XXX: for Object.keys() we should check enumerability of key */
+			/* [ obj trap_result res_arr propname ] */
+			duk_put_prop_index(ctx, -2, idx);
+			idx++;
+		} else {
+			duk_pop(ctx);
+		}
+	}
+
+	/* XXX: missing trap result validation for non-configurable target keys
+	 * (must be present), for non-extensible target all target keys must be
+	 * present and no extra keys can be present.
+	 * http://www.ecma-international.org/ecma-262/6.0/#sec-proxy-object-internal-methods-and-internal-slots-ownpropertykeys
+	 */
+
+	/* XXX: for Object.keys() the [[OwnPropertyKeys]] result (trap result)
+	 * should be filtered so that only enumerable keys remain.  Enumerability
+	 * should be checked with [[GetOwnProperty]] on the original object
+	 * (i.e., the proxy in this case).  If the proxy has a getOwnPropertyDescriptor
+	 * trap, it should be triggered for every property.  If the proxy doesn't have
+	 * the trap, enumerability should be checked against the target object instead.
+	 * We don't do any of this now, so Object.keys() and Object.getOwnPropertyNames()
+	 * return the same result now for proxy traps.  We still do clean up the trap
+	 * result, so that Object.keys() and Object.getOwnPropertyNames() will return a
+	 * clean array of strings without gaps.
+	 */
+	return 1;
+
+ skip_proxy:
+#endif  /* DUK_USE_ES6_PROXY */
+
+	DUK_ASSERT_TOP(ctx, 1);
+
+	if (duk_get_current_magic(ctx)) {
+		/* Object.keys */
+		enum_flags = DUK_ENUM_OWN_PROPERTIES_ONLY |
+		             DUK_ENUM_NO_PROXY_BEHAVIOR;
+	} else {
+		/* Object.getOwnPropertyNames */
+		enum_flags = DUK_ENUM_INCLUDE_NONENUMERABLE |
+		             DUK_ENUM_OWN_PROPERTIES_ONLY |
+		             DUK_ENUM_NO_PROXY_BEHAVIOR;
+	}
+
+	return duk_hobject_get_enumerated_keys(ctx, enum_flags);
+}
+
+DUK_INTERNAL duk_ret_t duk_bi_object_prototype_to_string(duk_context *ctx) {
+	duk_push_this(ctx);
+	duk_to_object_class_string_top(ctx);
+	return 1;
+}
+
+DUK_INTERNAL duk_ret_t duk_bi_object_prototype_to_locale_string(duk_context *ctx) {
+	DUK_ASSERT_TOP(ctx, 0);
+	(void) duk_push_this_coercible_to_object(ctx);
+	duk_get_prop_stridx(ctx, 0, DUK_STRIDX_TO_STRING);
+	if (!duk_is_callable(ctx, 1)) {
+		return DUK_RET_TYPE_ERROR;
+	}
+	duk_dup(ctx, 0);  /* -> [ O toString O ] */
+	duk_call_method(ctx, 0);  /* XXX: call method tail call? */
+	return 1;
+}
+
+DUK_INTERNAL duk_ret_t duk_bi_object_prototype_value_of(duk_context *ctx) {
+	(void) duk_push_this_coercible_to_object(ctx);
+	return 1;
+}
+
+DUK_INTERNAL duk_ret_t duk_bi_object_prototype_is_prototype_of(duk_context *ctx) {
+	duk_hthread *thr = (duk_hthread *) ctx;
+	duk_hobject *h_v;
+	duk_hobject *h_obj;
+
+	DUK_ASSERT_TOP(ctx, 1);
+
+	h_v = duk_get_hobject(ctx, 0);
+	if (!h_v) {
+		duk_push_false(ctx);  /* XXX: tail call: return duk_push_false(ctx) */
+		return 1;
+	}
+
+	h_obj = duk_push_this_coercible_to_object(ctx);
+	DUK_ASSERT(h_obj != NULL);
+
+	/* E5.1 Section 15.2.4.6, step 3.a, lookup proto once before compare.
+	 * Prototype loops should cause an error to be thrown.
+	 */
+	duk_push_boolean(ctx, duk_hobject_prototype_chain_contains(thr, DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h_v), h_obj, 0 /*ignore_loop*/));
+	return 1;
+}
+
+DUK_INTERNAL duk_ret_t duk_bi_object_prototype_has_own_property(duk_context *ctx) {
+	return duk_hobject_object_ownprop_helper(ctx, 0 /*required_desc_flags*/);
+}
+
+DUK_INTERNAL duk_ret_t duk_bi_object_prototype_property_is_enumerable(duk_context *ctx) {
+	return duk_hobject_object_ownprop_helper(ctx, DUK_PROPDESC_FLAG_ENUMERABLE /*required_desc_flags*/);
+}
+#line 1 "duk_bi_pointer.c"
+/*
+ *  Pointer built-ins
+ */
+
+/* include removed: duk_internal.h */
+
+/*
+ *  Constructor
+ */
+
+DUK_INTERNAL duk_ret_t duk_bi_pointer_constructor(duk_context *ctx) {
+	/* XXX: this behavior is quite useless now; it would be nice to be able
+	 * to create pointer values from e.g. numbers or strings.  Numbers are
+	 * problematic on 64-bit platforms though.  Hex encoded strings?
+	 */
+	if (duk_get_top(ctx) == 0) {
+		duk_push_pointer(ctx, NULL);
+	} else {
+		duk_to_pointer(ctx, 0);
+	}
+	DUK_ASSERT(duk_is_pointer(ctx, 0));
+	duk_set_top(ctx, 1);
+
+	if (duk_is_constructor_call(ctx)) {
+		duk_push_object_helper(ctx,
+		                       DUK_HOBJECT_FLAG_EXTENSIBLE |
+		                       DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_POINTER),
+		                       DUK_BIDX_POINTER_PROTOTYPE);
+
+		/* Pointer object internal value is immutable */
+		duk_dup(ctx, 0);
+		duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_INT_VALUE, DUK_PROPDESC_FLAGS_NONE);
+	}
+	/* Note: unbalanced stack on purpose */
+
+	return 1;
+}
+
+/*
+ *  toString(), valueOf()
+ */
+
+DUK_INTERNAL duk_ret_t duk_bi_pointer_prototype_tostring_shared(duk_context *ctx) {
+	duk_tval *tv;
+	duk_small_int_t to_string = duk_get_current_magic(ctx);
+
+	duk_push_this(ctx);
+	tv = duk_require_tval(ctx, -1);
+	DUK_ASSERT(tv != NULL);
+
+	if (DUK_TVAL_IS_POINTER(tv)) {
+		/* nop */
+	} else if (DUK_TVAL_IS_OBJECT(tv)) {
+		duk_hobject *h = DUK_TVAL_GET_OBJECT(tv);
+		DUK_ASSERT(h != NULL);
+
+		/* Must be a "pointer object", i.e. class "Pointer" */
+		if (DUK_HOBJECT_GET_CLASS_NUMBER(h) != DUK_HOBJECT_CLASS_POINTER) {
+			goto type_error;
+		}
+
+		duk_get_prop_stridx(ctx, -1, DUK_STRIDX_INT_VALUE);
+	} else {
+		goto type_error;
+	}
+
+	if (to_string) {
+		duk_to_string(ctx, -1);
+	}
+	return 1;
+
+ type_error:
+	return DUK_RET_TYPE_ERROR;
+}
+#line 1 "duk_bi_proxy.c"
+/*
+ *  Proxy built-in (ES6)
+ */
+
+/* include removed: duk_internal.h */
+
+#if defined(DUK_USE_ES6_PROXY)
+DUK_INTERNAL duk_ret_t duk_bi_proxy_constructor(duk_context *ctx) {
+	duk_hobject *h_target;
+	duk_hobject *h_handler;
+
+	if (!duk_is_constructor_call(ctx)) {
+		return DUK_RET_TYPE_ERROR;
+	}
+
+	/* Reject a proxy object as the target because it would need
+	 * special handler in property lookups.  (ES6 has no such restriction)
+	 */
+	h_target = duk_require_hobject_or_lfunc_coerce(ctx, 0);
+	DUK_ASSERT(h_target != NULL);
+	if (DUK_HOBJECT_HAS_EXOTIC_PROXYOBJ(h_target)) {
+		return DUK_RET_TYPE_ERROR;
+	}
+
+	/* Reject a proxy object as the handler because it would cause
+	 * potentially unbounded recursion.  (ES6 has no such restriction)
+	 */
+	h_handler = duk_require_hobject_or_lfunc_coerce(ctx, 1);
+	DUK_ASSERT(h_handler != NULL);
+	if (DUK_HOBJECT_HAS_EXOTIC_PROXYOBJ(h_handler)) {
+		return DUK_RET_TYPE_ERROR;
+	}
+
+	/* XXX: the returned value is exotic in ES6, but we use a
+	 * simple object here with no prototype.  Without a prototype,
+	 * [[DefaultValue]] coercion fails which is abit confusing.
+	 * No callable check/handling in the current Proxy subset.
+	 */
+	(void) duk_push_object_helper_proto(ctx,
+	                                    DUK_HOBJECT_FLAG_EXTENSIBLE |
+	                                    DUK_HOBJECT_FLAG_EXOTIC_PROXYOBJ |
+	                                    DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_OBJECT),
+	                                    NULL);
+	DUK_ASSERT_TOP(ctx, 3);
+
+	/* Make _Target and _Handler non-configurable and non-writable.
+	 * They can still be forcibly changed by C code (both user and
+	 * Duktape internal), but not by Ecmascript code.
+	 */
+
+	/* Proxy target */
+	duk_dup(ctx, 0);
+	duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_INT_TARGET, DUK_PROPDESC_FLAGS_NONE);
+
+	/* Proxy handler */
+	duk_dup(ctx, 1);
+	duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_INT_HANDLER, DUK_PROPDESC_FLAGS_NONE);
+
+	return 1;  /* replacement handler */
+}
+#else  /* DUK_USE_ES6_PROXY */
+DUK_INTERNAL duk_ret_t duk_bi_proxy_constructor(duk_context *ctx) {
+	DUK_UNREF(ctx);
+	return DUK_RET_UNSUPPORTED_ERROR;
+}
+#endif  /* DUK_USE_ES6_PROXY */
+#line 1 "duk_bi_regexp.c"
+/*
+ *  RegExp built-ins
+ */
+
+/* include removed: duk_internal.h */
+
+#ifdef DUK_USE_REGEXP_SUPPORT
+
+DUK_LOCAL void duk__get_this_regexp(duk_context *ctx) {
+	duk_hobject *h;
+
+	duk_push_this(ctx);
+	h = duk_require_hobject_with_class(ctx, -1, DUK_HOBJECT_CLASS_REGEXP);
+	DUK_ASSERT(h != NULL);
+	DUK_UNREF(h);
+	duk_insert(ctx, 0);  /* prepend regexp to valstack 0 index */
+}
+
+/* XXX: much to improve (code size) */
+DUK_INTERNAL duk_ret_t duk_bi_regexp_constructor(duk_context *ctx) {
+	duk_hthread *thr = (duk_hthread *) ctx;
+	duk_hobject *h_pattern;
+
+	DUK_ASSERT_TOP(ctx, 2);
+	h_pattern = duk_get_hobject(ctx, 0);
+
+	if (!duk_is_constructor_call(ctx) &&
+	    h_pattern != NULL &&
+	    DUK_HOBJECT_GET_CLASS_NUMBER(h_pattern) == DUK_HOBJECT_CLASS_REGEXP &&
+	    duk_is_undefined(ctx, 1)) {
+		/* Called as a function, pattern has [[Class]] "RegExp" and
+		 * flags is undefined -> return object as is.
+		 */
+		duk_dup(ctx, 0);
+		return 1;
+	}
+
+	/* Else functionality is identical for function call and constructor
+	 * call.
+	 */
+
+	if (h_pattern != NULL &&
+	    DUK_HOBJECT_GET_CLASS_NUMBER(h_pattern) == DUK_HOBJECT_CLASS_REGEXP) {
+		if (duk_is_undefined(ctx, 1)) {
+			duk_bool_t flag_g, flag_i, flag_m;
+			duk_get_prop_stridx(ctx, 0, DUK_STRIDX_SOURCE);
+			flag_g = duk_get_prop_stridx_boolean(ctx, 0, DUK_STRIDX_GLOBAL, NULL);
+			flag_i = duk_get_prop_stridx_boolean(ctx, 0, DUK_STRIDX_IGNORE_CASE, NULL);
+			flag_m = duk_get_prop_stridx_boolean(ctx, 0, DUK_STRIDX_MULTILINE, NULL);
+
+			duk_push_sprintf(ctx, "%s%s%s",
+			                 (const char *) (flag_g ? "g" : ""),
+			                 (const char *) (flag_i ? "i" : ""),
+			                 (const char *) (flag_m ? "m" : ""));
+
+			/* [ ... pattern flags ] */
+		} else {
+			return DUK_RET_TYPE_ERROR;
+		}
+	} else {
+		if (duk_is_undefined(ctx, 0)) {
+			duk_push_string(ctx, "");
+		} else {
+			duk_dup(ctx, 0);
+			duk_to_string(ctx, -1);
+		}
+		if (duk_is_undefined(ctx, 1)) {
+			duk_push_string(ctx, "");
+		} else {
+			duk_dup(ctx, 1);
+			duk_to_string(ctx, -1);
+		}
+
+		/* [ ... pattern flags ] */
+	}
+
+	DUK_DDD(DUK_DDDPRINT("RegExp constructor/function call, pattern=%!T, flags=%!T",
+	                     (duk_tval *) duk_get_tval(ctx, -2), (duk_tval *) duk_get_tval(ctx, -1)));
+
+	/* [ ... pattern flags ] */
 
-	h = duk_require_hobject(ctx, 0);
-	DUK_ASSERT(h != NULL);
+	duk_regexp_compile(thr);
 
-	is_frozen = duk_get_magic(ctx);
-	rc = duk_hobject_object_is_sealed_frozen_helper(h, is_frozen /*is_frozen*/);
-	duk_push_boolean(ctx, rc);
-	return 1;
-}
+	/* [ ... bytecode escaped_source ] */
 
-duk_ret_t duk_bi_object_constructor_is_extensible(duk_context *ctx) {
-	duk_hobject *h;
+	duk_regexp_create_instance(thr);
 
-	h = duk_require_hobject(ctx, 0);
-	DUK_ASSERT(h != NULL);
+	/* [ ... RegExp ] */
 
-	duk_push_boolean(ctx, DUK_HOBJECT_HAS_EXTENSIBLE(h));
 	return 1;
 }
 
-/* Shared helper for Object.getOwnPropertyNames() and Object.keys().
- * Magic: 0=getOwnPropertyNames, 1=Object.keys.
- */
-duk_ret_t duk_bi_object_constructor_keys_shared(duk_context *ctx) {
-	duk_hthread *thr = (duk_hthread *) ctx;
-	duk_hobject *obj;
-#if defined(DUK_USE_ES6_PROXY)
-	duk_hobject *h_proxy_target;
-	duk_hobject *h_proxy_handler;
-	duk_hobject *h_trap_result;
-	duk_uarridx_t i, len, idx;
-#endif
-	duk_small_uint_t enum_flags;
-
-	DUK_ASSERT_TOP(ctx, 1);
+DUK_INTERNAL duk_ret_t duk_bi_regexp_prototype_exec(duk_context *ctx) {
+	duk__get_this_regexp(ctx);
 
-	obj = duk_require_hobject(ctx, 0);
-	DUK_ASSERT(obj != NULL);
-	DUK_UNREF(obj);
+	/* [ regexp input ] */
 
-#if defined(DUK_USE_ES6_PROXY)
-	if (DUK_LIKELY(!duk_hobject_proxy_check(thr,
-	                                        obj,
-	                                        &h_proxy_target,
-	                                        &h_proxy_handler))) {
-		goto skip_proxy;
-	}
+	duk_regexp_match((duk_hthread *) ctx);
 
-	duk_push_hobject(ctx, h_proxy_handler);
-	if (!duk_get_prop_stridx(ctx, -1, DUK_STRIDX_OWN_KEYS)) {
-		/* Careful with reachability here: don't pop 'obj' before pushing
-		 * proxy target.
-		 */
-		DUK_DDD(DUK_DDDPRINT("no ownKeys trap, get keys of target instead"));
-		duk_pop_2(ctx);
-		duk_push_hobject(ctx, h_proxy_target);
-		duk_replace(ctx, 0);
-		DUK_ASSERT_TOP(ctx, 1);
-		goto skip_proxy;
-	}
+	/* [ result ] */
 
-	/* [ obj handler trap ] */
-	duk_insert(ctx, -2);
-	duk_push_hobject(ctx, h_proxy_target);  /* -> [ obj trap handler target ] */
-	duk_call_method(ctx, 1 /*nargs*/);      /* -> [ obj trap_result ] */
-	h_trap_result = duk_require_hobject(ctx, -1);
-	DUK_UNREF(h_trap_result);
+	return 1;
+}
 
-	len = (duk_uarridx_t) duk_get_length(ctx, -1);
-	idx = 0;
-	duk_push_array(ctx);
-	for (i = 0; i < len; i++) {
-		/* [ obj trap_result res_arr ] */
-		if (duk_get_prop_index(ctx, -2, i) && duk_is_string(ctx, -1)) {
-			/* XXX: for Object.keys() we should check enumerability of key */
-			/* [ obj trap_result res_arr propname ] */
-			duk_put_prop_index(ctx, -2, idx);
-			idx++;
-		} else {
-			duk_pop(ctx);
-		}
-	}
+DUK_INTERNAL duk_ret_t duk_bi_regexp_prototype_test(duk_context *ctx) {
+	duk__get_this_regexp(ctx);
 
-	/* XXX: for Object.keys() the [[OwnPropertyKeys]] result (trap result)
-	 * should be filtered so that only enumerable keys remain.  Enumerability
-	 * should be checked with [[GetOwnProperty]] on the original object
-	 * (i.e., the proxy in this case).  If the proxy has a getOwnPropertyDescriptor
-	 * trap, it should be triggered for every property.  If the proxy doesn't have
-	 * the trap, enumerability should be checked against the target object instead.
-	 * We don't do any of this now, so Object.keys() and Object.getOwnPropertyNames()
-	 * return the same result now for proxy traps.  We still do clean up the trap
-	 * result, so that Object.keys() and Object.getOwnPropertyNames() will return a
-	 * clean array of strings without gaps.
-	 */
-	return 1;
+	/* [ regexp input ] */
 
- skip_proxy:
-#endif  /* DUK_USE_ES6_PROXY */
+	/* result object is created and discarded; wasteful but saves code space */
+	duk_regexp_match((duk_hthread *) ctx);
 
-	DUK_ASSERT_TOP(ctx, 1);
+	/* [ result ] */
 
-	if (duk_get_magic(ctx)) {
-		/* Object.keys */
-		enum_flags = DUK_ENUM_OWN_PROPERTIES_ONLY |
-		             DUK_ENUM_NO_PROXY_BEHAVIOR;
-	} else {
-		/* Object.getOwnPropertyNames */
-		enum_flags = DUK_ENUM_INCLUDE_NONENUMERABLE |
-		             DUK_ENUM_OWN_PROPERTIES_ONLY |
-		             DUK_ENUM_NO_PROXY_BEHAVIOR;
-	}
+	duk_push_boolean(ctx, (duk_is_null(ctx, -1) ? 0 : 1));
 
-	return duk_hobject_get_enumerated_keys(ctx, enum_flags);
+	return 1;
 }
 
-duk_ret_t duk_bi_object_prototype_to_string(duk_context *ctx) {
-	duk_hthread *thr = (duk_hthread *) ctx;
+DUK_INTERNAL duk_ret_t duk_bi_regexp_prototype_to_string(duk_context *ctx) {
+	duk_hstring *h_bc;
+	duk_small_int_t re_flags;
 
-	duk_push_this(ctx);
-	duk_push_string(ctx, "[object ");
+#if 0
+	/* A little tricky string approach to provide the flags string.
+	 * This depends on the specific flag values in duk_regexp.h,
+	 * which needs to be asserted for.  In practice this doesn't
+	 * produce more compact code than the easier approach in use.
+	 */
 
-	if (duk_is_undefined(ctx, -2)) {
-		duk_push_hstring_stridx(ctx, DUK_STRIDX_UC_UNDEFINED);
-	} else if (duk_is_null(ctx, -2)) {
-		duk_push_hstring_stridx(ctx, DUK_STRIDX_UC_NULL);
-	} else {
-		duk_hobject *h_this;
-		duk_hstring *h_classname;
+	const char *flag_strings = "gim\0gi\0gm\0g\0";
+	duk_uint8_t flag_offsets[8] = {
+		(duk_uint8_t) 3,   /* flags: ""    */
+		(duk_uint8_t) 10,  /* flags: "g"   */
+		(duk_uint8_t) 5,   /* flags: "i"   */
+		(duk_uint8_t) 4,   /* flags: "gi"  */
+		(duk_uint8_t) 2,   /* flags: "m"   */
+		(duk_uint8_t) 7,   /* flags: "gm"  */
+		(duk_uint8_t) 1,   /* flags: "im"  */
+		(duk_uint8_t) 0,   /* flags: "gim" */
+	};
+	DUK_ASSERT(DUK_RE_FLAG_GLOBAL == 1);
+	DUK_ASSERT(DUK_RE_FLAG_IGNORE_CASE == 2);
+	DUK_ASSERT(DUK_RE_FLAG_MULTILINE == 4);
+#endif
 
-		duk_to_object(ctx, -2);
-		h_this = duk_get_hobject(ctx, -2);
-		DUK_ASSERT(h_this != NULL);
+	duk__get_this_regexp(ctx);
 
-		h_classname = DUK_HOBJECT_GET_CLASS_STRING(thr->heap, h_this);
-		DUK_ASSERT(h_classname != NULL);
+	/* [ regexp ] */
 
-		duk_push_hstring(ctx, h_classname);
-	}
+	duk_get_prop_stridx(ctx, 0, DUK_STRIDX_SOURCE);
+	duk_get_prop_stridx(ctx, 0, DUK_STRIDX_INT_BYTECODE);
+	h_bc = duk_get_hstring(ctx, -1);
+	DUK_ASSERT(h_bc != NULL);
+	DUK_ASSERT(DUK_HSTRING_GET_BYTELEN(h_bc) >= 1);
+	DUK_ASSERT(DUK_HSTRING_GET_CHARLEN(h_bc) >= 1);
+	DUK_ASSERT(DUK_HSTRING_GET_DATA(h_bc)[0] < 0x80);
+	re_flags = (duk_small_int_t) DUK_HSTRING_GET_DATA(h_bc)[0];
 
-	duk_push_string(ctx, "]");
-	duk_concat(ctx, 3);
-	return 1;
-}
+	/* [ regexp source bytecode ] */
 
-duk_ret_t duk_bi_object_prototype_to_locale_string(duk_context *ctx) {
-	DUK_ASSERT_TOP(ctx, 0);
-	(void) duk_push_this_coercible_to_object(ctx);
-	duk_get_prop_stridx(ctx, 0, DUK_STRIDX_TO_STRING);
-	if (!duk_is_callable(ctx, 1)) {
-		return DUK_RET_TYPE_ERROR;
-	}
-	duk_dup(ctx, 0);  /* -> [ O toString O ] */
-	duk_call_method(ctx, 0);  /* XXX: call method tailcall? */
-	return 1;
-}
+#if 1
+	/* This is a cleaner approach and also produces smaller code than
+	 * the other alternative.  Use duk_require_string() for format
+	 * safety (although the source property should always exist).
+	 */
+	duk_push_sprintf(ctx, "/%s/%s%s%s",
+	                 (const char *) duk_require_string(ctx, -2),  /* require to be safe */
+	                 (re_flags & DUK_RE_FLAG_GLOBAL) ? "g" : "",
+	                 (re_flags & DUK_RE_FLAG_IGNORE_CASE) ? "i" : "",
+	                 (re_flags & DUK_RE_FLAG_MULTILINE) ? "m" : "");
+#else
+	/* This should not be necessary because no-one should tamper with the
+	 * regexp bytecode, but is prudent to avoid potential segfaults if that
+	 * were to happen for some reason.
+	 */
+	re_flags &= 0x07;
+	DUK_ASSERT(re_flags >= 0 && re_flags <= 7);  /* three flags */
+	duk_push_sprintf(ctx, "/%s/%s",
+	                 (const char *) duk_require_string(ctx, -2),
+	                 (const char *) (flag_strings + flag_offsets[re_flags]));
+#endif
 
-duk_ret_t duk_bi_object_prototype_value_of(duk_context *ctx) {
-	(void) duk_push_this_coercible_to_object(ctx);
 	return 1;
 }
 
-duk_ret_t duk_bi_object_prototype_is_prototype_of(duk_context *ctx) {
-	duk_hthread *thr = (duk_hthread *) ctx;
-	duk_hobject *h_v;
-	duk_hobject *h_obj;
-
-	DUK_ASSERT_TOP(ctx, 1);
-
-	h_v = duk_get_hobject(ctx, 0);
-	if (!h_v) {
-		duk_push_false(ctx);  /* XXX: tail call: return duk_push_false(ctx) */
-		return 1;
-	}
+#else  /* DUK_USE_REGEXP_SUPPORT */
 
-	h_obj = duk_push_this_coercible_to_object(ctx);
-	DUK_ASSERT(h_obj != NULL);
+DUK_INTERNAL duk_ret_t duk_bi_regexp_constructor(duk_context *ctx) {
+	DUK_UNREF(ctx);
+	return DUK_RET_UNSUPPORTED_ERROR;
+}
 
-	/* E5.1 Section 15.2.4.6, step 3.a, lookup proto once before compare */
-	duk_push_boolean(ctx, duk_hobject_prototype_chain_contains(thr, h_v->prototype, h_obj));
-	return 1;
+DUK_INTERNAL duk_ret_t duk_bi_regexp_prototype_exec(duk_context *ctx) {
+	DUK_UNREF(ctx);
+	return DUK_RET_UNSUPPORTED_ERROR;
 }
 
-duk_ret_t duk_bi_object_prototype_has_own_property(duk_context *ctx) {
-	return duk_hobject_object_ownprop_helper(ctx, 0 /*required_desc_flags*/);
+DUK_INTERNAL duk_ret_t duk_bi_regexp_prototype_test(duk_context *ctx) {
+	DUK_UNREF(ctx);
+	return DUK_RET_UNSUPPORTED_ERROR;
 }
 
-duk_ret_t duk_bi_object_prototype_property_is_enumerable(duk_context *ctx) {
-	return duk_hobject_object_ownprop_helper(ctx, DUK_PROPDESC_FLAG_ENUMERABLE /*required_desc_flags*/);
+DUK_INTERNAL duk_ret_t duk_bi_regexp_prototype_to_string(duk_context *ctx) {
+	DUK_UNREF(ctx);
+	return DUK_RET_UNSUPPORTED_ERROR;
 }
-#line 1 "duk_bi_pointer.c"
+
+#endif  /* DUK_USE_REGEXP_SUPPORT */
+#line 1 "duk_bi_string.c"
 /*
- *  Pointer built-ins
+ *  String built-ins
+ */
+
+/* XXX: There are several limitations in the current implementation for
+ * strings with >= 0x80000000UL characters.  In some cases one would need
+ * to be able to represent the range [-0xffffffff,0xffffffff] and so on.
+ * Generally character and byte length are assumed to fit into signed 32
+ * bits (< 0x80000000UL).  Places with issues are not marked explicitly
+ * below in all cases, look for signed type usage (duk_int_t etc) for
+ * offsets/lengths.
  */
 
 /* include removed: duk_internal.h */
@@ -22918,4833 +37039,5007 @@ duk_ret_t duk_bi_object_prototype_property_is_enumerable(duk_context *ctx) {
  *  Constructor
  */
 
-duk_ret_t duk_bi_pointer_constructor(duk_context *ctx) {
-	/* FIXME: this behavior is quite useless now; it would be nice to be able
-	 * to create pointer values from e.g. numbers or strings.  Numbers are
-	 * problematic on 64-bit platforms though.  Hex encoded strings?
+DUK_INTERNAL duk_ret_t duk_bi_string_constructor(duk_context *ctx) {
+	/* String constructor needs to distinguish between an argument not given at all
+	 * vs. given as 'undefined'.  We're a vararg function to handle this properly.
 	 */
+
 	if (duk_get_top(ctx) == 0) {
-		duk_push_pointer(ctx, NULL);
+		duk_push_hstring_stridx(ctx, DUK_STRIDX_EMPTY_STRING);
 	} else {
-		duk_to_pointer(ctx, 0);
+		duk_to_string(ctx, 0);
 	}
-	DUK_ASSERT(duk_is_pointer(ctx, 0));
+	DUK_ASSERT(duk_is_string(ctx, 0));
 	duk_set_top(ctx, 1);
 
 	if (duk_is_constructor_call(ctx)) {
 		duk_push_object_helper(ctx,
 		                       DUK_HOBJECT_FLAG_EXTENSIBLE |
-		                       DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_POINTER),
-		                       DUK_BIDX_POINTER_PROTOTYPE);
+		                       DUK_HOBJECT_FLAG_EXOTIC_STRINGOBJ |
+		                       DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_STRING),
+		                       DUK_BIDX_STRING_PROTOTYPE);
 
-		/* Pointer object internal value is immutable */
+		/* String object internal value is immutable */
 		duk_dup(ctx, 0);
-		duk_def_prop_stridx(ctx, -2, DUK_STRIDX_INT_VALUE, DUK_PROPDESC_FLAGS_NONE);
+		duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_INT_VALUE, DUK_PROPDESC_FLAGS_NONE);
 	}
 	/* Note: unbalanced stack on purpose */
 
 	return 1;
 }
 
+DUK_INTERNAL duk_ret_t duk_bi_string_constructor_from_char_code(duk_context *ctx) {
+	duk_hthread *thr = (duk_hthread *) ctx;
+	duk_bufwriter_ctx bw_alloc;
+	duk_bufwriter_ctx *bw;
+	duk_idx_t i, n;
+	duk_ucodepoint_t cp;
+
+	/* XXX: It would be nice to build the string directly but ToUint16()
+	 * coercion is needed so a generic helper would not be very
+	 * helpful (perhaps coerce the value stack first here and then
+	 * build a string from a duk_tval number sequence in one go?).
+	 */
+
+	n = duk_get_top(ctx);
+
+	bw = &bw_alloc;
+	DUK_BW_INIT_PUSHBUF(thr, bw, n);  /* initial estimate for ASCII only codepoints */
+
+	for (i = 0; i < n; i++) {
+		/* XXX: could improve bufwriter handling to write multiple codepoints
+		 * with one ensure call but the relative benefit would be quite small.
+		 */
+
+#if defined(DUK_USE_NONSTD_STRING_FROMCHARCODE_32BIT)
+		/* ToUint16() coercion is mandatory in the E5.1 specification, but
+		 * this non-compliant behavior makes more sense because we support
+		 * non-BMP codepoints.  Don't use CESU-8 because that'd create
+		 * surrogate pairs.
+		 */
+
+		cp = (duk_ucodepoint_t) duk_to_uint32(ctx, i);
+		DUK_BW_WRITE_ENSURE_XUTF8(thr, bw, cp);
+#else
+		cp = (duk_ucodepoint_t) duk_to_uint32(ctx, i);
+		DUK_BW_WRITE_ENSURE_CESU8(thr, bw, cp);
+#endif
+	}
+
+	DUK_BW_COMPACT(thr, bw);
+	duk_to_string(ctx, -1);
+	return 1;
+}
+
 /*
  *  toString(), valueOf()
  */
 
-duk_ret_t duk_bi_pointer_prototype_tostring_shared(duk_context *ctx) {
+DUK_INTERNAL duk_ret_t duk_bi_string_prototype_to_string(duk_context *ctx) {
 	duk_tval *tv;
-	duk_small_int_t to_string = duk_get_magic(ctx);
 
 	duk_push_this(ctx);
 	tv = duk_require_tval(ctx, -1);
 	DUK_ASSERT(tv != NULL);
 
-	if (DUK_TVAL_IS_POINTER(tv)) {
-		/* nop */
+	if (DUK_TVAL_IS_STRING(tv)) {
+		/* return as is */
+		return 1;
 	} else if (DUK_TVAL_IS_OBJECT(tv)) {
 		duk_hobject *h = DUK_TVAL_GET_OBJECT(tv);
 		DUK_ASSERT(h != NULL);
 
-		/* Must be a "pointer object", i.e. class "Pointer" */
-		if (DUK_HOBJECT_GET_CLASS_NUMBER(h) != DUK_HOBJECT_CLASS_POINTER) {
+		/* Must be a "string object", i.e. class "String" */
+		if (DUK_HOBJECT_GET_CLASS_NUMBER(h) != DUK_HOBJECT_CLASS_STRING) {
 			goto type_error;
 		}
 
 		duk_get_prop_stridx(ctx, -1, DUK_STRIDX_INT_VALUE);
+		DUK_ASSERT(duk_is_string(ctx, -1));
+
+		return 1;
 	} else {
 		goto type_error;
 	}
 
-	if (to_string) {
-		duk_to_string(ctx, -1);
-	}
-	return 1;
+	/* never here, but fall through */
 
  type_error:
 	return DUK_RET_TYPE_ERROR;
 }
-#line 1 "duk_bi_proxy.c"
+
 /*
- *  Proxy built-in (ES6 draft)
+ *  Character and charcode access
  */
 
-/* include removed: duk_internal.h */
+DUK_INTERNAL duk_ret_t duk_bi_string_prototype_char_at(duk_context *ctx) {
+	duk_int_t pos;
 
-#if defined(DUK_USE_ES6_PROXY)
-duk_ret_t duk_bi_proxy_constructor(duk_context *ctx) {
-	duk_hobject *h_target;
-	duk_hobject *h_handler;
+	/* XXX: faster implementation */
 
-	if (!duk_is_constructor_call(ctx)) {
-		return DUK_RET_TYPE_ERROR;
+	(void) duk_push_this_coercible_to_string(ctx);
+	pos = duk_to_int(ctx, 0);
+	duk_substring(ctx, -1, pos, pos + 1);
+	return 1;
+}
+
+DUK_INTERNAL duk_ret_t duk_bi_string_prototype_char_code_at(duk_context *ctx) {
+	duk_hthread *thr = (duk_hthread *) ctx;
+	duk_int_t pos;
+	duk_hstring *h;
+	duk_bool_t clamped;
+
+	/* XXX: faster implementation */
+
+	DUK_DDD(DUK_DDDPRINT("arg=%!T", (duk_tval *) duk_get_tval(ctx, 0)));
+
+	h = duk_push_this_coercible_to_string(ctx);
+	DUK_ASSERT(h != NULL);
+
+	pos = duk_to_int_clamped_raw(ctx,
+	                             0 /*index*/,
+	                             0 /*min(incl)*/,
+	                             DUK_HSTRING_GET_CHARLEN(h) - 1 /*max(incl)*/,
+	                             &clamped /*out_clamped*/);
+	if (clamped) {
+		duk_push_number(ctx, DUK_DOUBLE_NAN);
+		return 1;
 	}
 
-	/* Reject a proxy object as the target because it would need
-	 * special handler in property lookups.  (ES6 has no such restriction)
-	 */
-	h_target = duk_require_hobject(ctx, 0);
-	DUK_ASSERT(h_target != NULL);
-	if (DUK_HOBJECT_HAS_EXOTIC_PROXYOBJ(h_target)) {
-		return DUK_RET_TYPE_ERROR;
+	duk_push_u32(ctx, (duk_uint32_t) duk_hstring_char_code_at_raw(thr, h, pos));
+	return 1;
+}
+
+/*
+ *  substring(), substr(), slice()
+ */
+
+/* XXX: any chance of merging these three similar but still slightly
+ * different algorithms so that footprint would be reduced?
+ */
+
+DUK_INTERNAL duk_ret_t duk_bi_string_prototype_substring(duk_context *ctx) {
+	duk_hstring *h;
+	duk_int_t start_pos, end_pos;
+	duk_int_t len;
+
+	h = duk_push_this_coercible_to_string(ctx);
+	DUK_ASSERT(h != NULL);
+	len = (duk_int_t) DUK_HSTRING_GET_CHARLEN(h);
+
+	/* [ start end str ] */
+
+	start_pos = duk_to_int_clamped(ctx, 0, 0, len);
+	if (duk_is_undefined(ctx, 1)) {
+		end_pos = len;
+	} else {
+		end_pos = duk_to_int_clamped(ctx, 1, 0, len);
 	}
+	DUK_ASSERT(start_pos >= 0 && start_pos <= len);
+	DUK_ASSERT(end_pos >= 0 && end_pos <= len);
 
-	/* Reject a proxy object as the handler because it would cause
-	 * potentially unbounded recursion.  (ES6 has no such restriction)
+	if (start_pos > end_pos) {
+		duk_int_t tmp = start_pos;
+		start_pos = end_pos;
+		end_pos = tmp;
+	}
+
+	DUK_ASSERT(end_pos >= start_pos);
+
+	duk_substring(ctx, -1, (duk_size_t) start_pos, (duk_size_t) end_pos);
+	return 1;
+}
+
+#ifdef DUK_USE_SECTION_B
+DUK_INTERNAL duk_ret_t duk_bi_string_prototype_substr(duk_context *ctx) {
+	duk_hstring *h;
+	duk_int_t start_pos, end_pos;
+	duk_int_t len;
+
+	/* Unlike non-obsolete String calls, substr() algorithm in E5.1
+	 * specification will happily coerce undefined and null to strings
+	 * ("undefined" and "null").
 	 */
-	h_handler = duk_require_hobject(ctx, 1);
-	DUK_ASSERT(h_handler != NULL);
-	if (DUK_HOBJECT_HAS_EXOTIC_PROXYOBJ(h_handler)) {
-		return DUK_RET_TYPE_ERROR;
+	duk_push_this(ctx);
+	h = duk_to_hstring(ctx, -1);
+	DUK_ASSERT(h != NULL);
+	len = (duk_int_t) DUK_HSTRING_GET_CHARLEN(h);
+
+	/* [ start length str ] */
+
+	/* The implementation for computing of start_pos and end_pos differs
+	 * from the standard algorithm, but is intended to result in the exactly
+	 * same behavior.  This is not always obvious.
+	 */
+
+	/* combines steps 2 and 5; -len ensures max() not needed for step 5 */
+	start_pos = duk_to_int_clamped(ctx, 0, -len, len);
+	if (start_pos < 0) {
+		start_pos = len + start_pos;
 	}
+	DUK_ASSERT(start_pos >= 0 && start_pos <= len);
 
-	/* XXX: the returned value is exotic in ES6 (draft), but we use a
-	 * simple object here with no prototype.  Without a prototype,
-	 * [[DefaultValue]] coercion fails which is abit confusing.
-	 * No callable check/handling in the current Proxy subset.
+	/* combines steps 3, 6; step 7 is not needed */
+	if (duk_is_undefined(ctx, 1)) {
+		end_pos = len;
+	} else {
+		DUK_ASSERT(start_pos <= len);
+		end_pos = start_pos + duk_to_int_clamped(ctx, 1, 0, len - start_pos);
+	}
+	DUK_ASSERT(start_pos >= 0 && start_pos <= len);
+	DUK_ASSERT(end_pos >= 0 && end_pos <= len);
+	DUK_ASSERT(end_pos >= start_pos);
+
+	duk_substring(ctx, -1, (duk_size_t) start_pos, (duk_size_t) end_pos);
+	return 1;
+}
+#else  /* DUK_USE_SECTION_B */
+DUK_INTERNAL duk_ret_t duk_bi_string_prototype_substr(duk_context *ctx) {
+	DUK_UNREF(ctx);
+	return DUK_RET_UNSUPPORTED_ERROR;
+}
+#endif  /* DUK_USE_SECTION_B */
+
+DUK_INTERNAL duk_ret_t duk_bi_string_prototype_slice(duk_context *ctx) {
+	duk_hstring *h;
+	duk_int_t start_pos, end_pos;
+	duk_int_t len;
+
+	h = duk_push_this_coercible_to_string(ctx);
+	DUK_ASSERT(h != NULL);
+	len = (duk_int_t) DUK_HSTRING_GET_CHARLEN(h);
+
+	/* [ start end str ] */
+
+	start_pos = duk_to_int_clamped(ctx, 0, -len, len);
+	if (start_pos < 0) {
+		start_pos = len + start_pos;
+	}
+	if (duk_is_undefined(ctx, 1)) {
+		end_pos = len;
+	} else {
+		end_pos = duk_to_int_clamped(ctx, 1, -len, len);
+		if (end_pos < 0) {
+			end_pos = len + end_pos;
+		}
+	}
+	DUK_ASSERT(start_pos >= 0 && start_pos <= len);
+	DUK_ASSERT(end_pos >= 0 && end_pos <= len);
+
+	if (end_pos < start_pos) {
+		end_pos = start_pos;
+	}
+
+	DUK_ASSERT(end_pos >= start_pos);
+
+	duk_substring(ctx, -1, (duk_size_t) start_pos, (duk_size_t) end_pos);
+	return 1;
+}
+
+/*
+ *  Case conversion
+ */
+
+DUK_INTERNAL duk_ret_t duk_bi_string_prototype_caseconv_shared(duk_context *ctx) {
+	duk_hthread *thr = (duk_hthread *) ctx;
+	duk_small_int_t uppercase = duk_get_current_magic(ctx);
+
+	(void) duk_push_this_coercible_to_string(ctx);
+	duk_unicode_case_convert_string(thr, (duk_bool_t) uppercase);
+	return 1;
+}
+
+/*
+ *  indexOf() and lastIndexOf()
+ */
+
+DUK_INTERNAL duk_ret_t duk_bi_string_prototype_indexof_shared(duk_context *ctx) {
+	duk_hthread *thr = (duk_hthread *) ctx;
+	duk_hstring *h_this;
+	duk_hstring *h_search;
+	duk_int_t clen_this;
+	duk_int_t cpos;
+	duk_int_t bpos;
+	const duk_uint8_t *p_start, *p_end, *p;
+	const duk_uint8_t *q_start;
+	duk_int_t q_blen;
+	duk_uint8_t firstbyte;
+	duk_uint8_t t;
+	duk_small_int_t is_lastindexof = duk_get_current_magic(ctx);  /* 0=indexOf, 1=lastIndexOf */
+
+	h_this = duk_push_this_coercible_to_string(ctx);
+	DUK_ASSERT(h_this != NULL);
+	clen_this = (duk_int_t) DUK_HSTRING_GET_CHARLEN(h_this);
+
+	h_search = duk_to_hstring(ctx, 0);
+	DUK_ASSERT(h_search != NULL);
+	q_start = DUK_HSTRING_GET_DATA(h_search);
+	q_blen = (duk_int_t) DUK_HSTRING_GET_BYTELEN(h_search);
+
+	duk_to_number(ctx, 1);
+	if (duk_is_nan(ctx, 1) && is_lastindexof) {
+		/* indexOf: NaN should cause pos to be zero.
+		 * lastIndexOf: NaN should cause pos to be +Infinity
+		 * (and later be clamped to len).
+		 */
+		cpos = clen_this;
+	} else {
+		cpos = duk_to_int_clamped(ctx, 1, 0, clen_this);
+	}
+
+	/* Empty searchstring always matches; cpos must be clamped here.
+	 * (If q_blen were < 0 due to clamped coercion, it would also be
+	 * caught here.)
 	 */
-	(void) duk_push_object_helper_proto(ctx,
-	                                    DUK_HOBJECT_FLAG_EXTENSIBLE |
-	                                    DUK_HOBJECT_FLAG_EXOTIC_PROXYOBJ |
-	                                    DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_OBJECT),
-	                                    NULL);
-	DUK_ASSERT_TOP(ctx, 3);
+	if (q_blen <= 0) {
+		duk_push_int(ctx, cpos);
+		return 1;
+	}
+	DUK_ASSERT(q_blen > 0);
 
-	/* Proxy target */
-	duk_dup(ctx, 0);
-	duk_def_prop_stridx(ctx, -2, DUK_STRIDX_INT_TARGET, DUK_PROPDESC_FLAGS_WC);
+	bpos = (duk_int_t) duk_heap_strcache_offset_char2byte(thr, h_this, (duk_uint32_t) cpos);
 
-	/* Proxy handler */
-	duk_dup(ctx, 1);
-	duk_def_prop_stridx(ctx, -2, DUK_STRIDX_INT_HANDLER, DUK_PROPDESC_FLAGS_WC);
+	p_start = DUK_HSTRING_GET_DATA(h_this);
+	p_end = p_start + DUK_HSTRING_GET_BYTELEN(h_this);
+	p = p_start + bpos;
 
-	return 1;  /* replacement handler */
-}
-#else  /* DUK_USE_ES6_PROXY */
-duk_ret_t duk_bi_proxy_constructor(duk_context *ctx) {
-	DUK_UNREF(ctx);
-	return DUK_RET_UNSUPPORTED_ERROR;
-}
-#endif  /* DUK_USE_ES6_PROXY */
-#line 1 "duk_bi_regexp.c"
-/*
- *  RegExp built-ins
- */
+	/* This loop is optimized for size.  For speed, there should be
+	 * two separate loops, and we should ensure that memcmp() can be
+	 * used without an extra "will searchstring fit" check.  Doing
+	 * the preconditioning for 'p' and 'p_end' is easy but cpos
+	 * must be updated if 'p' is wound back (backward scanning).
+	 */
 
-/* include removed: duk_internal.h */
+	firstbyte = q_start[0];  /* leading byte of match string */
+	while (p <= p_end && p >= p_start) {
+		t = *p;
 
-#ifdef DUK_USE_REGEXP_SUPPORT
+		/* For Ecmascript strings, this check can only match for
+		 * initial UTF-8 bytes (not continuation bytes).  For other
+		 * strings all bets are off.
+		 */
 
-static void duk__get_this_regexp(duk_context *ctx) {
-	duk_hobject *h;
+		if ((t == firstbyte) && ((duk_size_t) (p_end - p) >= (duk_size_t) q_blen)) {
+			DUK_ASSERT(q_blen > 0);  /* no issues with memcmp() zero size, even if broken */
+			if (DUK_MEMCMP((const void *) p, (const void *) q_start, (size_t) q_blen) == 0) {
+				duk_push_int(ctx, cpos);
+				return 1;
+			}
+		}
 
-	duk_push_this(ctx);
-	h = duk_require_hobject_with_class(ctx, -1, DUK_HOBJECT_CLASS_REGEXP);
-	DUK_ASSERT(h != NULL);
-	DUK_UNREF(h);
-	duk_insert(ctx, 0);  /* prepend regexp to valstack 0 index */
+		/* track cpos while scanning */
+		if (is_lastindexof) {
+			/* when going backwards, we decrement cpos 'early';
+			 * 'p' may point to a continuation byte of the char
+			 * at offset 'cpos', but that's OK because we'll
+			 * backtrack all the way to the initial byte.
+			 */
+			if ((t & 0xc0) != 0x80) {
+				cpos--;
+			}
+			p--;
+		} else {
+			if ((t & 0xc0) != 0x80) {
+				cpos++;
+			}
+			p++;
+		}
+	}
+
+	/* Not found.  Empty string case is handled specially above. */
+	duk_push_int(ctx, -1);
+	return 1;
 }
 
-/* FIXME: much to improve (code size) */
-duk_ret_t duk_bi_regexp_constructor(duk_context *ctx) {
+/*
+ *  replace()
+ */
+
+/* XXX: the current implementation works but is quite clunky; it compiles
+ * to almost 1,4kB of x86 code so it needs to be simplified (better approach,
+ * shared helpers, etc).  Some ideas for refactoring:
+ *
+ * - a primitive to convert a string into a regexp matcher (reduces matching
+ *   code at the cost of making matching much slower)
+ * - use replace() as a basic helper for match() and split(), which are both
+ *   much simpler
+ * - API call to get_prop and to_boolean
+ */
+
+DUK_INTERNAL duk_ret_t duk_bi_string_prototype_replace(duk_context *ctx) {
 	duk_hthread *thr = (duk_hthread *) ctx;
-	duk_hobject *h_pattern;
+	duk_hstring *h_input;
+	duk_hstring *h_match;
+	duk_hstring *h_search;
+	duk_hobject *h_re;
+	duk_bufwriter_ctx bw_alloc;
+	duk_bufwriter_ctx *bw;
+#ifdef DUK_USE_REGEXP_SUPPORT
+	duk_bool_t is_regexp;
+	duk_bool_t is_global;
+#endif
+	duk_bool_t is_repl_func;
+	duk_uint32_t match_start_coff, match_start_boff;
+#ifdef DUK_USE_REGEXP_SUPPORT
+	duk_int_t match_caps;
+#endif
+	duk_uint32_t prev_match_end_boff;
+	const duk_uint8_t *r_start, *r_end, *r;   /* repl string scan */
+	duk_size_t tmp_sz;
 
 	DUK_ASSERT_TOP(ctx, 2);
-	h_pattern = duk_get_hobject(ctx, 0);
+	h_input = duk_push_this_coercible_to_string(ctx);
+	DUK_ASSERT(h_input != NULL);
 
-	if (!duk_is_constructor_call(ctx) &&
-	    h_pattern != NULL &&
-	    DUK_HOBJECT_GET_CLASS_NUMBER(h_pattern) == DUK_HOBJECT_CLASS_REGEXP &&
-	    duk_is_undefined(ctx, 1)) {
-		/* Called as a function, pattern has [[Class]] "RegExp" and
-		 * flags is undefined -> return object as is.
-		 */
-		duk_dup(ctx, 0);
-		return 1;
-	}
+	bw = &bw_alloc;
+	DUK_BW_INIT_PUSHBUF(thr, bw, DUK_HSTRING_GET_BYTELEN(h_input));  /* input size is good output starting point */
 
-	/* Else functionality is identical for function call and constructor
-	 * call.
-	 */
+	DUK_ASSERT_TOP(ctx, 4);
 
-	if (h_pattern != NULL &&
-	    DUK_HOBJECT_GET_CLASS_NUMBER(h_pattern) == DUK_HOBJECT_CLASS_REGEXP) {
-		if (duk_is_undefined(ctx, 1)) {
-			duk_bool_t flag_g, flag_i, flag_m;
-			duk_get_prop_stridx(ctx, 0, DUK_STRIDX_SOURCE);
-			flag_g = duk_get_prop_stridx_boolean(ctx, 0, DUK_STRIDX_GLOBAL, NULL);
-			flag_i = duk_get_prop_stridx_boolean(ctx, 0, DUK_STRIDX_IGNORE_CASE, NULL);
-			flag_m = duk_get_prop_stridx_boolean(ctx, 0, DUK_STRIDX_MULTILINE, NULL);
+	/* stack[0] = search value
+	 * stack[1] = replace value
+	 * stack[2] = input string
+	 * stack[3] = result buffer
+	 */
 
-			duk_push_sprintf(ctx, "%s%s%s",
-			                 (const char *) (flag_g ? "g" : ""),
-			                 (const char *) (flag_i ? "i" : ""),
-			                 (const char *) (flag_m ? "m" : ""));
+	h_re = duk_get_hobject_with_class(ctx, 0, DUK_HOBJECT_CLASS_REGEXP);
+	if (h_re) {
+#ifdef DUK_USE_REGEXP_SUPPORT
+		is_regexp = 1;
+		is_global = duk_get_prop_stridx_boolean(ctx, 0, DUK_STRIDX_GLOBAL, NULL);
 
-			/* [ ... pattern flags ] */
-		} else {
-			return DUK_RET_TYPE_ERROR;
+		if (is_global) {
+			/* start match from beginning */
+			duk_push_int(ctx, 0);
+			duk_put_prop_stridx(ctx, 0, DUK_STRIDX_LAST_INDEX);
 		}
+#else  /* DUK_USE_REGEXP_SUPPORT */
+		return DUK_RET_UNSUPPORTED_ERROR;
+#endif  /* DUK_USE_REGEXP_SUPPORT */
 	} else {
-		if (duk_is_undefined(ctx, 0)) {
-			duk_push_string(ctx, "");
-		} else {
-			duk_dup(ctx, 0);
-			duk_to_string(ctx, -1);
-		}
-		if (duk_is_undefined(ctx, 1)) {
-			duk_push_string(ctx, "");
-		} else {
-			duk_dup(ctx, 1);
-			duk_to_string(ctx, -1);
-		}
+		duk_to_string(ctx, 0);
+#ifdef DUK_USE_REGEXP_SUPPORT
+		is_regexp = 0;
+		is_global = 0;
+#endif
+	}
 
-		/* [ ... pattern flags ] */
+	if (duk_is_function(ctx, 1)) {
+		is_repl_func = 1;
+		r_start = NULL;
+		r_end = NULL;
+	} else {
+		duk_hstring *h_repl;
+
+		is_repl_func = 0;
+		h_repl = duk_to_hstring(ctx, 1);
+		DUK_ASSERT(h_repl != NULL);
+		r_start = DUK_HSTRING_GET_DATA(h_repl);
+		r_end = r_start + DUK_HSTRING_GET_BYTELEN(h_repl);
 	}
 
-	DUK_DDD(DUK_DDDPRINT("RegExp constructor/function call, pattern=%!T, flags=%!T",
-	                     (duk_tval *) duk_get_tval(ctx, -2), (duk_tval *) duk_get_tval(ctx, -1)));
+	prev_match_end_boff = 0;
 
-	/* [ ... pattern flags ] */
+	for (;;) {
+		/*
+		 *  If matching with a regexp:
+		 *    - non-global RegExp: lastIndex not touched on a match, zeroed
+		 *      on a non-match
+		 *    - global RegExp: on match, lastIndex will be updated by regexp
+		 *      executor to point to next char after the matching part (so that
+		 *      characters in the matching part are not matched again)
+		 *
+		 *  If matching with a string:
+		 *    - always non-global match, find first occurrence
+		 *
+		 *  We need:
+		 *    - The character offset of start-of-match for the replacer function
+		 *    - The byte offsets for start-of-match and end-of-match to implement
+		 *      the replacement values $&, $`, and $', and to copy non-matching
+		 *      input string portions (including header and trailer) verbatim.
+		 *
+		 *  NOTE: the E5.1 specification is a bit vague how the RegExp should
+		 *  behave in the replacement process; e.g. is matching done first for
+		 *  all matches (in the global RegExp case) before any replacer calls
+		 *  are made?  See: test-bi-string-proto-replace.js for discussion.
+		 */
 
-	duk_regexp_compile(thr);
+		DUK_ASSERT_TOP(ctx, 4);
 
-	/* [ ... bytecode escaped_source ] */
+#ifdef DUK_USE_REGEXP_SUPPORT
+		if (is_regexp) {
+			duk_dup(ctx, 0);
+			duk_dup(ctx, 2);
+			duk_regexp_match(thr);  /* [ ... regexp input ] -> [ res_obj ] */
+			if (!duk_is_object(ctx, -1)) {
+				duk_pop(ctx);
+				break;
+			}
 
-	duk_regexp_create_instance(thr);
+			duk_get_prop_stridx(ctx, -1, DUK_STRIDX_INDEX);
+			DUK_ASSERT(duk_is_number(ctx, -1));
+			match_start_coff = duk_get_int(ctx, -1);
+			duk_pop(ctx);
 
-	/* [ ... RegExp ] */
+			duk_get_prop_index(ctx, -1, 0);
+			DUK_ASSERT(duk_is_string(ctx, -1));
+			h_match = duk_get_hstring(ctx, -1);
+			DUK_ASSERT(h_match != NULL);
+			duk_pop(ctx);  /* h_match is borrowed, remains reachable through match_obj */
 
-	return 1;
-}
+			if (DUK_HSTRING_GET_BYTELEN(h_match) == 0) {
+				/* This should be equivalent to match() algorithm step 8.f.iii.2:
+				 * detect an empty match and allow it, but don't allow it twice.
+				 */
+				duk_uint32_t last_index;
 
-duk_ret_t duk_bi_regexp_prototype_exec(duk_context *ctx) {
-	duk__get_this_regexp(ctx);
+				duk_get_prop_stridx(ctx, 0, DUK_STRIDX_LAST_INDEX);
+				last_index = (duk_uint32_t) duk_get_uint(ctx, -1);
+				DUK_DDD(DUK_DDDPRINT("empty match, bump lastIndex: %ld -> %ld",
+				                     (long) last_index, (long) (last_index + 1)));
+				duk_pop(ctx);
+				duk_push_int(ctx, last_index + 1);
+				duk_put_prop_stridx(ctx, 0, DUK_STRIDX_LAST_INDEX);
+			}
 
-	/* [ regexp input ] */
+			DUK_ASSERT(duk_get_length(ctx, -1) <= DUK_INT_MAX);  /* string limits */
+			match_caps = (duk_int_t) duk_get_length(ctx, -1);
+		} else {
+#else  /* DUK_USE_REGEXP_SUPPORT */
+		{  /* unconditionally */
+#endif  /* DUK_USE_REGEXP_SUPPORT */
+			const duk_uint8_t *p_start, *p_end, *p;   /* input string scan */
+			const duk_uint8_t *q_start;               /* match string */
+			duk_size_t q_blen;
 
-	duk_regexp_match((duk_hthread *) ctx);
+#ifdef DUK_USE_REGEXP_SUPPORT
+			DUK_ASSERT(!is_global);  /* single match always */
+#endif
 
-	/* [ result ] */
+			p_start = DUK_HSTRING_GET_DATA(h_input);
+			p_end = p_start + DUK_HSTRING_GET_BYTELEN(h_input);
+			p = p_start;
 
-	return 1;
-}
+			h_search = duk_get_hstring(ctx, 0);
+			DUK_ASSERT(h_search != NULL);
+			q_start = DUK_HSTRING_GET_DATA(h_search);
+			q_blen = (duk_size_t) DUK_HSTRING_GET_BYTELEN(h_search);
 
-duk_ret_t duk_bi_regexp_prototype_test(duk_context *ctx) {
-	duk__get_this_regexp(ctx);
+			p_end -= q_blen;  /* ensure full memcmp() fits in while */
 
-	/* [ regexp input ] */
+			match_start_coff = 0;
 
-	/* result object is created and discarded; wasteful but saves code space */
-	duk_regexp_match((duk_hthread *) ctx);
+			while (p <= p_end) {
+				DUK_ASSERT(p + q_blen <= DUK_HSTRING_GET_DATA(h_input) + DUK_HSTRING_GET_BYTELEN(h_input));
+				if (DUK_MEMCMP((const void *) p, (const void *) q_start, (size_t) q_blen) == 0) {
+					duk_dup(ctx, 0);
+					h_match = duk_get_hstring(ctx, -1);
+					DUK_ASSERT(h_match != NULL);
+#ifdef DUK_USE_REGEXP_SUPPORT
+					match_caps = 0;
+#endif
+					goto found;
+				}
 
-	/* [ result ] */
+				/* track utf-8 non-continuation bytes */
+				if ((p[0] & 0xc0) != 0x80) {
+					match_start_coff++;
+				}
+				p++;
+			}
 
-	duk_push_boolean(ctx, (duk_is_null(ctx, -1) ? 0 : 1));
+			/* not found */
+			break;
+		}
+	 found:
 
-	return 1;
-}
+		/* stack[0] = search value
+		 * stack[1] = replace value
+		 * stack[2] = input string
+		 * stack[3] = result buffer
+		 * stack[4] = regexp match OR match string
+		 */
 
-duk_ret_t duk_bi_regexp_prototype_to_string(duk_context *ctx) {
-	duk_hstring *h_bc;
-	duk_small_int_t re_flags;
+		match_start_boff = duk_heap_strcache_offset_char2byte(thr, h_input, match_start_coff);
 
-#if 0
-	/* A little tricky string approach to provide the flags string.
-	 * This depends on the specific flag values in duk_regexp.h,
-	 * which needs to be asserted for.  In practice this doesn't
-	 * produce more compact code than the easier approach in use.
-	 */
+		tmp_sz = (duk_size_t) (match_start_boff - prev_match_end_boff);
+		DUK_BW_WRITE_ENSURE_BYTES(thr, bw, DUK_HSTRING_GET_DATA(h_input) + prev_match_end_boff, tmp_sz);
 
-	const char *flag_strings = "gim\0gi\0gm\0g\0";
-	duk_uint8_t flag_offsets[8] = {
-		(duk_uint8_t) 3,   /* flags: ""    */
-		(duk_uint8_t) 10,  /* flags: "g"   */
-		(duk_uint8_t) 5,   /* flags: "i"   */
-		(duk_uint8_t) 4,   /* flags: "gi"  */
-		(duk_uint8_t) 2,   /* flags: "m"   */
-		(duk_uint8_t) 7,   /* flags: "gm"  */
-		(duk_uint8_t) 1,   /* flags: "im"  */
-		(duk_uint8_t) 0,   /* flags: "gim" */
-	};
-	DUK_ASSERT(DUK_RE_FLAG_GLOBAL == 1);
-	DUK_ASSERT(DUK_RE_FLAG_IGNORE_CASE == 2);
-	DUK_ASSERT(DUK_RE_FLAG_MULTILINE == 4);
-#endif
+		prev_match_end_boff = match_start_boff + DUK_HSTRING_GET_BYTELEN(h_match);
 
-	duk__get_this_regexp(ctx);
+		if (is_repl_func) {
+			duk_idx_t idx_args;
+			duk_hstring *h_repl;
 
-	/* [ regexp ] */
+			/* regexp res_obj is at index 4 */
 
-	duk_get_prop_stridx(ctx, 0, DUK_STRIDX_SOURCE);
-	duk_get_prop_stridx(ctx, 0, DUK_STRIDX_INT_BYTECODE);
-	h_bc = duk_get_hstring(ctx, -1);
-	DUK_ASSERT(h_bc != NULL);
-	DUK_ASSERT(DUK_HSTRING_GET_BYTELEN(h_bc) >= 1);
-	DUK_ASSERT(DUK_HSTRING_GET_CHARLEN(h_bc) >= 1);
-	DUK_ASSERT(DUK_HSTRING_GET_DATA(h_bc)[0] < 0x80);
-	re_flags = (duk_small_int_t) DUK_HSTRING_GET_DATA(h_bc)[0];
+			duk_dup(ctx, 1);
+			idx_args = duk_get_top(ctx);
 
-	/* [ regexp source bytecode ] */
+#ifdef DUK_USE_REGEXP_SUPPORT
+			if (is_regexp) {
+				duk_int_t idx;
+				duk_require_stack(ctx, match_caps + 2);
+				for (idx = 0; idx < match_caps; idx++) {
+					/* match followed by capture(s) */
+					duk_get_prop_index(ctx, 4, idx);
+				}
+			} else {
+#else  /* DUK_USE_REGEXP_SUPPORT */
+			{  /* unconditionally */
+#endif  /* DUK_USE_REGEXP_SUPPORT */
+				/* match == search string, by definition */
+				duk_dup(ctx, 0);
+			}
+			duk_push_int(ctx, match_start_coff);
+			duk_dup(ctx, 2);
 
-#if 1
-	/* This is a cleaner approach and also produces smaller code than
-	 * the other alternative.  Use duk_require_string() for format
-	 * safety (although the source property should always exist).
-	 */
-	duk_push_sprintf(ctx, "/%s/%s%s%s",
-	                 (const char *) duk_require_string(ctx, -2),  /* require to be safe */
-	                 (re_flags & DUK_RE_FLAG_GLOBAL) ? "g" : "",
-	                 (re_flags & DUK_RE_FLAG_IGNORE_CASE) ? "i" : "",
-	                 (re_flags & DUK_RE_FLAG_MULTILINE) ? "m" : "");
-#else
-	/* This should not be necessary because no-one should tamper with the
-	 * regexp bytecode, but is prudent to avoid potential segfaults if that
-	 * were to happen for some reason.
-	 */
-	re_flags &= 0x07;
-	DUK_ASSERT(re_flags >= 0 && re_flags <= 7);  /* three flags */
-	duk_push_sprintf(ctx, "/%s/%s",
-	                 (const char *) duk_require_string(ctx, -2),
-	                 (const char *) (flag_strings + flag_offsets[re_flags]));
-#endif
+			/* [ ... replacer match [captures] match_char_offset input ] */
 
-	return 1;
-}
+			duk_call(ctx, duk_get_top(ctx) - idx_args);
+			h_repl = duk_to_hstring(ctx, -1);  /* -> [ ... repl_value ] */
+			DUK_ASSERT(h_repl != NULL);
 
-#else  /* DUK_USE_REGEXP_SUPPORT */
+			DUK_BW_WRITE_ENSURE_HSTRING(thr, bw, h_repl);
 
-duk_ret_t duk_bi_regexp_constructor(duk_context *ctx) {
-	DUK_UNREF(ctx);
-	return DUK_RET_UNSUPPORTED_ERROR;
-}
+			duk_pop(ctx);  /* repl_value */
+		} else {
+			r = r_start;
 
-duk_ret_t duk_bi_regexp_prototype_exec(duk_context *ctx) {
-	DUK_UNREF(ctx);
-	return DUK_RET_UNSUPPORTED_ERROR;
-}
+			while (r < r_end) {
+				duk_int_t ch1;
+				duk_int_t ch2;
+#ifdef DUK_USE_REGEXP_SUPPORT
+				duk_int_t ch3;
+#endif
+				duk_size_t left;
 
-duk_ret_t duk_bi_regexp_prototype_test(duk_context *ctx) {
-	DUK_UNREF(ctx);
-	return DUK_RET_UNSUPPORTED_ERROR;
-}
+				ch1 = *r++;
+				if (ch1 != DUK_ASC_DOLLAR) {
+					goto repl_write;
+				}
+				left = r_end - r;
 
-duk_ret_t duk_bi_regexp_prototype_to_string(duk_context *ctx) {
-	DUK_UNREF(ctx);
-	return DUK_RET_UNSUPPORTED_ERROR;
-}
+				if (left <= 0) {
+					goto repl_write;
+				}
 
-#endif  /* DUK_USE_REGEXP_SUPPORT */
-#line 1 "duk_bi_string.c"
-/*
- *  String built-ins
- */
+				ch2 = r[0];
+				switch ((int) ch2) {
+				case DUK_ASC_DOLLAR: {
+					ch1 = (1 << 8) + DUK_ASC_DOLLAR;
+					goto repl_write;
+				}
+				case DUK_ASC_AMP: {
+					DUK_BW_WRITE_ENSURE_HSTRING(thr, bw, h_match);
+					r++;
+					continue;
+				}
+				case DUK_ASC_GRAVE: {
+					tmp_sz = (duk_size_t) match_start_boff;
+					DUK_BW_WRITE_ENSURE_BYTES(thr, bw, DUK_HSTRING_GET_DATA(h_input), tmp_sz);
+					r++;
+					continue;
+				}
+				case DUK_ASC_SINGLEQUOTE: {
+					duk_uint32_t match_end_boff;
 
-/* XXX: There are several limitations in the current implementation for
- * strings with >= 0x80000000UL characters.  In some cases one would need
- * to be able to represent the range [-0xffffffff,0xffffffff] and so on.
- * Generally character and byte length are assumed to fit into signed 32
- * bits (< 0x80000000UL).  Places with issues are not marked explicitly
- * below in all cases, look for signed type usage (duk_int_t etc) for
- * offsets/lengths.
- */
+					/* Use match charlen instead of bytelen, just in case the input and
+					 * match codepoint encodings would have different lengths.
+					 */
+					match_end_boff = duk_heap_strcache_offset_char2byte(thr,
+					                                                    h_input,
+					                                                    match_start_coff + DUK_HSTRING_GET_CHARLEN(h_match));
 
-/* include removed: duk_internal.h */
+					tmp_sz = (duk_size_t) (DUK_HSTRING_GET_BYTELEN(h_input) - match_end_boff);
+					DUK_BW_WRITE_ENSURE_BYTES(thr, bw, DUK_HSTRING_GET_DATA(h_input) + match_end_boff, tmp_sz);
+					r++;
+					continue;
+				}
+				default: {
+#ifdef DUK_USE_REGEXP_SUPPORT
+					duk_int_t capnum, captmp, capadv;
+					/* XXX: optional check, match_caps is zero if no regexp,
+					 * so dollar will be interpreted literally anyway.
+					 */
 
-/*
- *  Constructor
- */
+					if (!is_regexp) {
+						goto repl_write;
+					}
 
-duk_ret_t duk_bi_string_constructor(duk_context *ctx) {
-	/* String constructor needs to distinguish between an argument not given at all
-	 * vs. given as 'undefined'.  We're a vararg function to handle this properly.
-	 */
+					if (!(ch2 >= DUK_ASC_0 && ch2 <= DUK_ASC_9)) {
+						goto repl_write;
+					}
+					capnum = ch2 - DUK_ASC_0;
+					capadv = 1;
 
-	if (duk_get_top(ctx) == 0) {
-		duk_push_hstring_stridx(ctx, DUK_STRIDX_EMPTY_STRING);
-	} else {
-		duk_to_string(ctx, 0);
-	}
-	DUK_ASSERT(duk_is_string(ctx, 0));
-	duk_set_top(ctx, 1);
+					if (left >= 2) {
+						ch3 = r[1];
+						if (ch3 >= DUK_ASC_0 && ch3 <= DUK_ASC_9) {
+							captmp = capnum * 10 + (ch3 - DUK_ASC_0);
+							if (captmp < match_caps) {
+								capnum = captmp;
+								capadv = 2;
+							}
+						}
+					}
 
-	if (duk_is_constructor_call(ctx)) {
-		duk_push_object_helper(ctx,
-		                       DUK_HOBJECT_FLAG_EXTENSIBLE |
-		                       DUK_HOBJECT_FLAG_EXOTIC_STRINGOBJ |
-		                       DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_STRING),
-		                       DUK_BIDX_STRING_PROTOTYPE);
+					if (capnum > 0 && capnum < match_caps) {
+						DUK_ASSERT(is_regexp != 0);  /* match_caps == 0 without regexps */
 
-		/* String object internal value is immutable */
-		duk_dup(ctx, 0);
-		duk_def_prop_stridx(ctx, -2, DUK_STRIDX_INT_VALUE, DUK_PROPDESC_FLAGS_NONE);
-	}
-	/* Note: unbalanced stack on purpose */
+						/* regexp res_obj is at offset 4 */
+						duk_get_prop_index(ctx, 4, (duk_uarridx_t) capnum);
+						if (duk_is_string(ctx, -1)) {
+							duk_hstring *h_tmp_str;
 
-	return 1;
-}
+							h_tmp_str = duk_get_hstring(ctx, -1);
+							DUK_ASSERT(h_tmp_str != NULL);
+
+							DUK_BW_WRITE_ENSURE_HSTRING(thr, bw, h_tmp_str);
+						} else {
+							/* undefined -> skip (replaced with empty) */
+						}
+						duk_pop(ctx);
+						r += capadv;
+						continue;
+					} else {
+						goto repl_write;
+					}
+#else  /* DUK_USE_REGEXP_SUPPORT */
+					goto repl_write;  /* unconditionally */
+#endif  /* DUK_USE_REGEXP_SUPPORT */
+				}  /* default case */
+				}  /* switch (ch2) */
 
-duk_ret_t duk_bi_string_constructor_from_char_code(duk_context *ctx) {
-	duk_hthread *thr = (duk_hthread *) ctx;
-	duk_hbuffer_dynamic *h;
-	duk_idx_t i, n;
-	duk_ucodepoint_t cp;
+			 repl_write:
+				/* ch1 = (r_increment << 8) + byte */
 
-	/* XXX: It would be nice to build the string directly but ToUint16()
-	 * coercion is needed so a generic helper would not be very
-	 * helpful (perhaps coerce the value stack first here and then
-	 * build a string from a duk_tval number sequence in one go?).
-	 */
+				DUK_BW_WRITE_ENSURE_U8(thr, bw, (duk_uint8_t) (ch1 & 0xff));
+				r += ch1 >> 8;
+			}  /* while repl */
+		}  /* if (is_repl_func) */
 
-	n = duk_get_top(ctx);
-	duk_push_dynamic_buffer(ctx, 0);  /* XXX: initial spare size estimate from 'n' */
-	h = (duk_hbuffer_dynamic *) duk_get_hbuffer(ctx, -1);
+		duk_pop(ctx);  /* pop regexp res_obj or match string */
 
-	for (i = 0; i < n; i++) {
-		cp = duk_to_uint16(ctx, i);
-		duk_hbuffer_append_cesu8(thr, h, cp);
+#ifdef DUK_USE_REGEXP_SUPPORT
+		if (!is_global) {
+#else
+		{  /* unconditionally; is_global==0 */
+#endif
+			break;
+		}
 	}
 
+	/* trailer */
+	tmp_sz = (duk_size_t) (DUK_HSTRING_GET_BYTELEN(h_input) - prev_match_end_boff);
+	DUK_BW_WRITE_ENSURE_BYTES(thr, bw, DUK_HSTRING_GET_DATA(h_input) + prev_match_end_boff, tmp_sz);
+
+	DUK_ASSERT_TOP(ctx, 4);
+	DUK_BW_COMPACT(thr, bw);
 	duk_to_string(ctx, -1);
 	return 1;
 }
 
 /*
- *  toString(), valueOf()
+ *  split()
  */
 
-duk_ret_t duk_bi_string_prototype_to_string(duk_context *ctx) {
-	duk_tval *tv;
+/* XXX: very messy now, but works; clean up, remove unused variables (nomimally
+ * used so compiler doesn't complain).
+ */
 
-	duk_push_this(ctx);
-	tv = duk_require_tval(ctx, -1);
-	DUK_ASSERT(tv != NULL);
+DUK_INTERNAL duk_ret_t duk_bi_string_prototype_split(duk_context *ctx) {
+	duk_hthread *thr = (duk_hthread *) ctx;
+	duk_hstring *h_input;
+	duk_hstring *h_sep;
+	duk_uint32_t limit;
+	duk_uint32_t arr_idx;
+#ifdef DUK_USE_REGEXP_SUPPORT
+	duk_bool_t is_regexp;
+#endif
+	duk_bool_t matched;  /* set to 1 if any match exists (needed for empty input special case) */
+	duk_uint32_t prev_match_end_coff, prev_match_end_boff;
+	duk_uint32_t match_start_boff, match_start_coff;
+	duk_uint32_t match_end_boff, match_end_coff;
 
-	if (DUK_TVAL_IS_STRING(tv)) {
-		/* return as is */
-		return 1;
-	} else if (DUK_TVAL_IS_OBJECT(tv)) {
-		duk_hobject *h = DUK_TVAL_GET_OBJECT(tv);
-		DUK_ASSERT(h != NULL);
+	DUK_UNREF(thr);
 
-		/* Must be a "string object", i.e. class "String" */
-		if (DUK_HOBJECT_GET_CLASS_NUMBER(h) != DUK_HOBJECT_CLASS_STRING) {
-			goto type_error;
-		}
+	h_input = duk_push_this_coercible_to_string(ctx);
+	DUK_ASSERT(h_input != NULL);
 
-		duk_get_prop_stridx(ctx, -1, DUK_STRIDX_INT_VALUE);
-		DUK_ASSERT(duk_is_string(ctx, -1));
+	duk_push_array(ctx);
+
+	if (duk_is_undefined(ctx, 1)) {
+		limit = 0xffffffffUL;
+	} else {
+		limit = duk_to_uint32(ctx, 1);
+	}
+
+	if (limit == 0) {
+		return 1;
+	}
 
+	/* If the separator is a RegExp, make a "clone" of it.  The specification
+	 * algorithm calls [[Match]] directly for specific indices; we emulate this
+	 * by tweaking lastIndex and using a "force global" variant of duk_regexp_match()
+	 * which will use global-style matching even when the RegExp itself is non-global.
+	 */
+
+	if (duk_is_undefined(ctx, 0)) {
+		/* The spec algorithm first does "R = ToString(separator)" before checking
+		 * whether separator is undefined.  Since this is side effect free, we can
+		 * skip the ToString() here.
+		 */
+		duk_dup(ctx, 2);
+		duk_put_prop_index(ctx, 3, 0);
 		return 1;
+	} else if (duk_get_hobject_with_class(ctx, 0, DUK_HOBJECT_CLASS_REGEXP) != NULL) {
+#ifdef DUK_USE_REGEXP_SUPPORT
+		duk_push_hobject_bidx(ctx, DUK_BIDX_REGEXP_CONSTRUCTOR);
+		duk_dup(ctx, 0);
+		duk_new(ctx, 1);  /* [ ... RegExp val ] -> [ ... res ] */
+		duk_replace(ctx, 0);
+		/* lastIndex is initialized to zero by new RegExp() */
+		is_regexp = 1;
+#else
+		return DUK_RET_UNSUPPORTED_ERROR;
+#endif
 	} else {
-		goto type_error;
+		duk_to_string(ctx, 0);
+#ifdef DUK_USE_REGEXP_SUPPORT
+		is_regexp = 0;
+#endif
 	}
 
-	/* never here, but fall through */
+	/* stack[0] = separator (string or regexp)
+	 * stack[1] = limit
+	 * stack[2] = input string
+	 * stack[3] = result array
+	 */
 
- type_error:
-	return DUK_RET_TYPE_ERROR;
-}
+	prev_match_end_boff = 0;
+	prev_match_end_coff = 0;
+	arr_idx = 0;
+	matched = 0;
 
-/*
- *  Character and charcode access
- */
+	for (;;) {
+		/*
+		 *  The specification uses RegExp [[Match]] to attempt match at specific
+		 *  offsets.  We don't have such a primitive, so we use an actual RegExp
+		 *  and tweak lastIndex.  Since the RegExp may be non-global, we use a
+		 *  special variant which forces global-like behavior for matching.
+		 */
 
-duk_ret_t duk_bi_string_prototype_char_at(duk_context *ctx) {
-	duk_int_t pos;
+		DUK_ASSERT_TOP(ctx, 4);
 
-	/* XXX: faster implementation */
+#ifdef DUK_USE_REGEXP_SUPPORT
+		if (is_regexp) {
+			duk_dup(ctx, 0);
+			duk_dup(ctx, 2);
+			duk_regexp_match_force_global(thr);  /* [ ... regexp input ] -> [ res_obj ] */
+			if (!duk_is_object(ctx, -1)) {
+				duk_pop(ctx);
+				break;
+			}
+			matched = 1;
 
-	(void) duk_push_this_coercible_to_string(ctx);
-	pos = duk_to_int(ctx, 0);
-	duk_substring(ctx, -1, pos, pos + 1);
-	return 1;
-}
+			duk_get_prop_stridx(ctx, -1, DUK_STRIDX_INDEX);
+			DUK_ASSERT(duk_is_number(ctx, -1));
+			match_start_coff = duk_get_int(ctx, -1);
+			match_start_boff = duk_heap_strcache_offset_char2byte(thr, h_input, match_start_coff);
+			duk_pop(ctx);
 
-duk_ret_t duk_bi_string_prototype_char_code_at(duk_context *ctx) {
-	duk_hthread *thr = (duk_hthread *) ctx;
-	duk_int_t pos;
-	duk_hstring *h;
-	duk_bool_t clamped;
+			if (match_start_coff == DUK_HSTRING_GET_CHARLEN(h_input)) {
+				/* don't allow an empty match at the end of the string */
+				duk_pop(ctx);
+				break;
+			}
 
-	/* XXX: faster implementation */
+			duk_get_prop_stridx(ctx, 0, DUK_STRIDX_LAST_INDEX);
+			DUK_ASSERT(duk_is_number(ctx, -1));
+			match_end_coff = duk_get_int(ctx, -1);
+			match_end_boff = duk_heap_strcache_offset_char2byte(thr, h_input, match_end_coff);
+			duk_pop(ctx);
 
-	DUK_DDD(DUK_DDDPRINT("arg=%!T", (duk_tval *) duk_get_tval(ctx, 0)));
+			/* empty match -> bump and continue */
+			if (prev_match_end_boff == match_end_boff) {
+				duk_push_int(ctx, match_end_coff + 1);
+				duk_put_prop_stridx(ctx, 0, DUK_STRIDX_LAST_INDEX);
+				duk_pop(ctx);
+				continue;
+			}
+		} else {
+#else  /* DUK_USE_REGEXP_SUPPORT */
+		{  /* unconditionally */
+#endif  /* DUK_USE_REGEXP_SUPPORT */
+			const duk_uint8_t *p_start, *p_end, *p;   /* input string scan */
+			const duk_uint8_t *q_start;               /* match string */
+			duk_size_t q_blen, q_clen;
 
-	h = duk_push_this_coercible_to_string(ctx);
-	DUK_ASSERT(h != NULL);
+			p_start = DUK_HSTRING_GET_DATA(h_input);
+			p_end = p_start + DUK_HSTRING_GET_BYTELEN(h_input);
+			p = p_start + prev_match_end_boff;
 
-	pos = duk_to_int_clamped_raw(ctx,
-	                             0 /*index*/,
-	                             0 /*min(incl)*/,
-	                             DUK_HSTRING_GET_CHARLEN(h) - 1 /*max(incl)*/,
-	                             &clamped /*out_clamped*/);
-	if (clamped) {
-		duk_push_number(ctx, DUK_DOUBLE_NAN);
-		return 1;
-	}
+			h_sep = duk_get_hstring(ctx, 0);
+			DUK_ASSERT(h_sep != NULL);
+			q_start = DUK_HSTRING_GET_DATA(h_sep);
+			q_blen = (duk_size_t) DUK_HSTRING_GET_BYTELEN(h_sep);
+			q_clen = (duk_size_t) DUK_HSTRING_GET_CHARLEN(h_sep);
 
-	duk_push_u32(ctx, (duk_uint32_t) duk_hstring_char_code_at_raw(thr, h, pos));
-	return 1;
-}
+			p_end -= q_blen;  /* ensure full memcmp() fits in while */
 
-/*
- *  substring(), substr(), slice()
- */
+			match_start_coff = prev_match_end_coff;
 
-/* XXX: any chance of merging these three similar but still slightly
- * different algorithms so that footprint would be reduced?
- */
+			if (q_blen == 0) {
+				/* Handle empty separator case: it will always match, and always
+				 * triggers the check in step 13.c.iii initially.  Note that we
+				 * must skip to either end of string or start of first codepoint,
+				 * skipping over any continuation bytes!
+				 *
+				 * Don't allow an empty string to match at the end of the input.
+				 */
 
-duk_ret_t duk_bi_string_prototype_substring(duk_context *ctx) {
-	duk_hstring *h;
-	duk_int_t start_pos, end_pos;
-	duk_int_t len;
+				matched = 1;  /* empty separator can always match */
 
-	h = duk_push_this_coercible_to_string(ctx);
-	DUK_ASSERT(h != NULL);
-	len = (duk_int_t) DUK_HSTRING_GET_CHARLEN(h);
+				match_start_coff++;
+				p++;
+				while (p < p_end) {
+					if ((p[0] & 0xc0) != 0x80) {
+						goto found;
+					}
+					p++;
+				}
+				goto not_found;
+			}
 
-	/* [ start end str ] */
+			DUK_ASSERT(q_blen > 0 && q_clen > 0);
+			while (p <= p_end) {
+				DUK_ASSERT(p + q_blen <= DUK_HSTRING_GET_DATA(h_input) + DUK_HSTRING_GET_BYTELEN(h_input));
+				DUK_ASSERT(q_blen > 0);  /* no issues with empty memcmp() */
+				if (DUK_MEMCMP((const void *) p, (const void *) q_start, (size_t) q_blen) == 0) {
+					/* never an empty match, so step 13.c.iii can't be triggered */
+					goto found;
+				}
 
-	start_pos = duk_to_int_clamped(ctx, 0, 0, len);
-	if (duk_is_undefined(ctx, 1)) {
-		end_pos = len;
-	} else {
-		end_pos = duk_to_int_clamped(ctx, 1, 0, len);
-	}
-	DUK_ASSERT(start_pos >= 0 && start_pos <= len);
-	DUK_ASSERT(end_pos >= 0 && end_pos <= len);
+				/* track utf-8 non-continuation bytes */
+				if ((p[0] & 0xc0) != 0x80) {
+					match_start_coff++;
+				}
+				p++;
+			}
 
-	if (start_pos > end_pos) {
-		duk_int_t tmp = start_pos;
-		start_pos = end_pos;
-		end_pos = tmp;
-	}
+		 not_found:
+			/* not found */
+			break;
 
-	DUK_ASSERT(end_pos >= start_pos);
+		 found:
+			matched = 1;
+			match_start_boff = (duk_uint32_t) (p - p_start);
+			match_end_coff = (duk_uint32_t) (match_start_coff + q_clen);  /* constrained by string length */
+			match_end_boff = (duk_uint32_t) (match_start_boff + q_blen);  /* ditto */
 
-	duk_substring(ctx, -1, (duk_size_t) start_pos, (duk_size_t) end_pos);
-	return 1;
-}
+			/* empty match (may happen with empty separator) -> bump and continue */
+			if (prev_match_end_boff == match_end_boff) {
+				prev_match_end_boff++;
+				prev_match_end_coff++;
+				continue;
+			}
+		}  /* if (is_regexp) */
 
-#ifdef DUK_USE_SECTION_B
-duk_ret_t duk_bi_string_prototype_substr(duk_context *ctx) {
-	duk_hstring *h;
-	duk_int_t start_pos, end_pos;
-	duk_int_t len;
+		/* stack[0] = separator (string or regexp)
+		 * stack[1] = limit
+		 * stack[2] = input string
+		 * stack[3] = result array
+		 * stack[4] = regexp res_obj (if is_regexp)
+		 */
 
-	/* Unlike non-obsolete String calls, substr() algorithm in E5.1
-	 * specification will happily coerce undefined and null to strings
-	 * ("undefined" and "null").
-	 */
-	duk_push_this(ctx);
-	h = duk_to_hstring(ctx, -1);
-	DUK_ASSERT(h != NULL);
-	len = (duk_int_t) DUK_HSTRING_GET_CHARLEN(h);
+		DUK_DDD(DUK_DDDPRINT("split; match_start b=%ld,c=%ld, match_end b=%ld,c=%ld, prev_end b=%ld,c=%ld",
+		                     (long) match_start_boff, (long) match_start_coff,
+		                     (long) match_end_boff, (long) match_end_coff,
+		                     (long) prev_match_end_boff, (long) prev_match_end_coff));
 
-	/* [ start length str ] */
+		duk_push_lstring(ctx,
+		                 (const char *) (DUK_HSTRING_GET_DATA(h_input) + prev_match_end_boff),
+		                 (duk_size_t) (match_start_boff - prev_match_end_boff));
+		duk_put_prop_index(ctx, 3, arr_idx);
+		arr_idx++;
+		if (arr_idx >= limit) {
+			goto hit_limit;
+		}
 
-	/* The implementation for computing of start_pos and end_pos differs
-	 * from the standard algorithm, but is intended to result in the exactly
-	 * same behavior.  This is not always obvious.
-	 */
+#ifdef DUK_USE_REGEXP_SUPPORT
+		if (is_regexp) {
+			duk_size_t i, len;
 
-	/* combines steps 2 and 5; -len ensures max() not needed for step 5 */
-	start_pos = duk_to_int_clamped(ctx, 0, -len, len);
-	if (start_pos < 0) {
-		start_pos = len + start_pos;
-	}
-	DUK_ASSERT(start_pos >= 0 && start_pos <= len);
+			len = duk_get_length(ctx, 4);
+			for (i = 1; i < len; i++) {
+				DUK_ASSERT(i <= DUK_UARRIDX_MAX);  /* cannot have >4G captures */
+				duk_get_prop_index(ctx, 4, (duk_uarridx_t) i);
+				duk_put_prop_index(ctx, 3, arr_idx);
+				arr_idx++;
+				if (arr_idx >= limit) {
+					goto hit_limit;
+				}
+			}
 
-	/* combines steps 3, 6; step 7 is not needed */
-	if (duk_is_undefined(ctx, 1)) {
-		end_pos = len;
-	} else {
-		DUK_ASSERT(start_pos <= len);
-		end_pos = start_pos + duk_to_int_clamped(ctx, 1, 0, len - start_pos);
-	}
-	DUK_ASSERT(start_pos >= 0 && start_pos <= len);
-	DUK_ASSERT(end_pos >= 0 && end_pos <= len);
-	DUK_ASSERT(end_pos >= start_pos);
+			duk_pop(ctx);
+			/* lastIndex already set up for next match */
+		} else {
+#else  /* DUK_USE_REGEXP_SUPPORT */
+		{  /* unconditionally */
+#endif  /* DUK_USE_REGEXP_SUPPORT */
+			/* no action */
+		}
 
-	duk_substring(ctx, -1, (duk_size_t) start_pos, (duk_size_t) end_pos);
-	return 1;
-}
-#else  /* DUK_USE_SECTION_B */
-duk_ret_t duk_bi_string_prototype_substr(duk_context *ctx) {
-	DUK_UNREF(ctx);
-	return DUK_RET_UNSUPPORTED_ERROR;
-}
-#endif  /* DUK_USE_SECTION_B */
+		prev_match_end_boff = match_end_boff;
+		prev_match_end_coff = match_end_coff;
+		continue;
+	}  /* for */
 
-duk_ret_t duk_bi_string_prototype_slice(duk_context *ctx) {
-	duk_hstring *h;
-	duk_int_t start_pos, end_pos;
-	duk_int_t len;
+	/* Combined step 11 (empty string special case) and 14-15. */
 
-	h = duk_push_this_coercible_to_string(ctx);
-	DUK_ASSERT(h != NULL);
-	len = (duk_int_t) DUK_HSTRING_GET_CHARLEN(h);
+	DUK_DDD(DUK_DDDPRINT("split trailer; prev_end b=%ld,c=%ld",
+	                     (long) prev_match_end_boff, (long) prev_match_end_coff));
 
-	/* [ start end str ] */
+	if (DUK_HSTRING_GET_CHARLEN(h_input) > 0 || !matched) {
+		/* Add trailer if:
+		 *   a) non-empty input
+		 *   b) empty input and no (zero size) match found (step 11)
+		 */
 
-	start_pos = duk_to_int_clamped(ctx, 0, -len, len);
-	if (start_pos < 0) {
-		start_pos = len + start_pos;
-	}
-	if (duk_is_undefined(ctx, 1)) {
-		end_pos = len;
-	} else {
-		end_pos = duk_to_int_clamped(ctx, 1, -len, len);
-		if (end_pos < 0) {
-			end_pos = len + end_pos;
-		}
+		duk_push_lstring(ctx,
+		                 (const char *) DUK_HSTRING_GET_DATA(h_input) + prev_match_end_boff,
+		                 (duk_size_t) (DUK_HSTRING_GET_BYTELEN(h_input) - prev_match_end_boff));
+		duk_put_prop_index(ctx, 3, arr_idx);
+		/* No arr_idx update or limit check */
 	}
-	DUK_ASSERT(start_pos >= 0 && start_pos <= len);
-	DUK_ASSERT(end_pos >= 0 && end_pos <= len);
 
-	if (end_pos < start_pos) {
-		end_pos = start_pos;
-	}
+	return 1;
 
-	DUK_ASSERT(end_pos >= start_pos);
+ hit_limit:
+#ifdef DUK_USE_REGEXP_SUPPORT
+	if (is_regexp) {
+		duk_pop(ctx);
+	}
+#endif
 
-	duk_substring(ctx, -1, (duk_size_t) start_pos, (duk_size_t) end_pos);
 	return 1;
 }
 
 /*
- *  Case conversion
+ *  Various
  */
 
-duk_ret_t duk_bi_string_prototype_caseconv_shared(duk_context *ctx) {
-	duk_hthread *thr = (duk_hthread *) ctx;
-	duk_small_int_t uppercase = duk_get_magic(ctx);
+#ifdef DUK_USE_REGEXP_SUPPORT
+DUK_LOCAL void duk__to_regexp_helper(duk_context *ctx, duk_idx_t index, duk_bool_t force_new) {
+	duk_hobject *h;
 
-	(void) duk_push_this_coercible_to_string(ctx);
-	duk_unicode_case_convert_string(thr, (duk_bool_t) uppercase);
-	return 1;
-}
+	/* Shared helper for match() steps 3-4, search() steps 3-4. */
 
-/*
- *  indexOf() and lastIndexOf()
- */
+	DUK_ASSERT(index >= 0);
+
+	if (force_new) {
+		goto do_new;
+	}
+
+	h = duk_get_hobject_with_class(ctx, index, DUK_HOBJECT_CLASS_REGEXP);
+	if (!h) {
+		goto do_new;
+	}
+	return;
+
+ do_new:
+	duk_push_hobject_bidx(ctx, DUK_BIDX_REGEXP_CONSTRUCTOR);
+	duk_dup(ctx, index);
+	duk_new(ctx, 1);  /* [ ... RegExp val ] -> [ ... res ] */
+	duk_replace(ctx, index);
+}
+#endif  /* DUK_USE_REGEXP_SUPPORT */
 
-duk_ret_t duk_bi_string_prototype_indexof_shared(duk_context *ctx) {
+#ifdef DUK_USE_REGEXP_SUPPORT
+DUK_INTERNAL duk_ret_t duk_bi_string_prototype_search(duk_context *ctx) {
 	duk_hthread *thr = (duk_hthread *) ctx;
-	duk_hstring *h_this;
-	duk_hstring *h_search;
-	duk_int_t clen_this;
-	duk_int_t cpos;
-	duk_int_t bpos;
-	duk_uint8_t *p_start, *p_end, *p;
-	duk_uint8_t *q_start;
-	duk_int_t q_blen;
-	duk_uint8_t firstbyte;
-	duk_uint8_t t;
-	duk_small_int_t is_lastindexof = duk_get_magic(ctx);  /* 0=indexOf, 1=lastIndexOf */
 
-	h_this = duk_push_this_coercible_to_string(ctx);
-	DUK_ASSERT(h_this != NULL);
-	clen_this = (duk_int_t) DUK_HSTRING_GET_CHARLEN(h_this);
+	/* Easiest way to implement the search required by the specification
+	 * is to do a RegExp test() with lastIndex forced to zero.  To avoid
+	 * side effects on the argument, "clone" the RegExp if a RegExp was
+	 * given as input.
+	 *
+	 * The global flag of the RegExp should be ignored; setting lastIndex
+	 * to zero (which happens when "cloning" the RegExp) should have an
+	 * equivalent effect.
+	 */
 
-	h_search = duk_to_hstring(ctx, 0);
-	DUK_ASSERT(h_search != NULL);
-	q_start = DUK_HSTRING_GET_DATA(h_search);
-	q_blen = (duk_int_t) DUK_HSTRING_GET_BYTELEN(h_search);
+	DUK_ASSERT_TOP(ctx, 1);
+	(void) duk_push_this_coercible_to_string(ctx);  /* at index 1 */
+	duk__to_regexp_helper(ctx, 0 /*index*/, 1 /*force_new*/);
 
-	duk_to_number(ctx, 1);
-	if (duk_is_nan(ctx, 1) && is_lastindexof) {
-		/* indexOf: NaN should cause pos to be zero.
-		 * lastIndexOf: NaN should cause pos to be +Infinity
-	 	 * (and later be clamped to len).
-		 */
-		cpos = clen_this;
-	} else {
-		cpos = duk_to_int_clamped(ctx, 1, 0, clen_this);
-	}
+	/* stack[0] = regexp
+	 * stack[1] = string
+	 */
 
-	/* Empty searchstring always matches; cpos must be clamped here.
-	 * (If q_blen were < 0 due to clamped coercion, it would also be
-	 * caught here.)
+	/* Avoid using RegExp.prototype methods, as they're writable and
+	 * configurable and may have been changed.
 	 */
-	if (q_blen <= 0) {
-		duk_push_int(ctx, cpos);
+
+	duk_dup(ctx, 0);
+	duk_dup(ctx, 1);  /* [ ... re_obj input ] */
+	duk_regexp_match(thr);  /* -> [ ... res_obj ] */
+
+	if (!duk_is_object(ctx, -1)) {
+		duk_push_int(ctx, -1);
 		return 1;
 	}
-	DUK_ASSERT(q_blen > 0);
 
-	bpos = (duk_int_t) duk_heap_strcache_offset_char2byte(thr, h_this, (duk_uint32_t) cpos);
+	duk_get_prop_stridx(ctx, -1, DUK_STRIDX_INDEX);
+	DUK_ASSERT(duk_is_number(ctx, -1));
+	return 1;
+}
+#else  /* DUK_USE_REGEXP_SUPPORT */
+DUK_INTERNAL duk_ret_t duk_bi_string_prototype_search(duk_context *ctx) {
+	DUK_UNREF(ctx);
+	return DUK_RET_UNSUPPORTED_ERROR;
+}
+#endif  /* DUK_USE_REGEXP_SUPPORT */
+
+#ifdef DUK_USE_REGEXP_SUPPORT
+DUK_INTERNAL duk_ret_t duk_bi_string_prototype_match(duk_context *ctx) {
+	duk_hthread *thr = (duk_hthread *) ctx;
+	duk_bool_t global;
+	duk_int_t prev_last_index;
+	duk_int_t this_index;
+	duk_int_t arr_idx;
 
-	p_start = DUK_HSTRING_GET_DATA(h_this);
-	p_end = p_start + DUK_HSTRING_GET_BYTELEN(h_this);
-	p = p_start + bpos;
+	DUK_ASSERT_TOP(ctx, 1);
+	(void) duk_push_this_coercible_to_string(ctx);
+	duk__to_regexp_helper(ctx, 0 /*index*/, 0 /*force_new*/);
+	global = duk_get_prop_stridx_boolean(ctx, 0, DUK_STRIDX_GLOBAL, NULL);
+	DUK_ASSERT_TOP(ctx, 2);
 
-	/* This loop is optimized for size.  For speed, there should be
-	 * two separate loops, and we should ensure that memcmp() can be
-	 * used without an extra "will searchstring fit" check.  Doing
-	 * the preconditioning for 'p' and 'p_end' is easy but cpos
-	 * must be updated if 'p' is wound back (backward scanning).
+	/* stack[0] = regexp
+	 * stack[1] = string
 	 */
 
-	firstbyte = q_start[0];  /* leading byte of match string */
-	while (p <= p_end && p >= p_start) {
-		t = *p;
-
-		/* For Ecmascript strings, this check can only match for
-		 * initial UTF-8 bytes (not continuation bytes).  For other
-		 * strings all bets are off.
-		 */
+	if (!global) {
+		duk_regexp_match(thr);  /* -> [ res_obj ] */
+		return 1;  /* return 'res_obj' */
+	}
 
-		if ((t == firstbyte) && ((duk_size_t) (p_end - p) >= (duk_size_t) q_blen)) {
-			DUK_ASSERT(q_blen > 0);  /* no issues with memcmp() zero size, even if broken */
-			if (DUK_MEMCMP(p, q_start, (duk_size_t) q_blen) == 0) {
-				duk_push_int(ctx, cpos);
-				return 1;
-			}
-		}
+	/* Global case is more complex. */
 
-		/* track cpos while scanning */
-		if (is_lastindexof) {
-			/* when going backwards, we decrement cpos 'early';
-			 * 'p' may point to a continuation byte of the char
-			 * at offset 'cpos', but that's OK because we'll
-			 * backtrack all the way to the initial byte.
-			 */
-			if ((t & 0xc0) != 0x80) {
-				cpos--;
-			}
-			p--;
-		} else {
-			if ((t & 0xc0) != 0x80) {
-				cpos++;
-			}
-			p++;
-		}
-	}
+	/* [ regexp string ] */
 
-	/* Not found.  Empty string case is handled specially above. */
-	duk_push_int(ctx, -1);
-	return 1;
-}
+	duk_push_int(ctx, 0);
+	duk_put_prop_stridx(ctx, 0, DUK_STRIDX_LAST_INDEX);
+	duk_push_array(ctx);
 
-/*
- *  replace()
- */
+	/* [ regexp string res_arr ] */
 
-/* XXX: the current implementation works but is quite clunky; it compiles
- * to almost 1,4kB of x86 code so it needs to be simplified (better approach,
- * shared helpers, etc).  Some ideas for refactoring:
- *
- * - a primitive to convert a string into a regexp matcher (reduces matching
- *   code at the cost of making matching much slower)
- * - use replace() as a basic helper for match() and split(), which are both
- *   much simpler
- * - API call to get_prop and to_boolean
- */
+	prev_last_index = 0;
+	arr_idx = 0;
 
-duk_ret_t duk_bi_string_prototype_replace(duk_context *ctx) {
-	duk_hthread *thr = (duk_hthread *) ctx;
-	duk_hstring *h_input;
-	duk_hstring *h_repl;
-	duk_hstring *h_match;
-	duk_hstring *h_search;
-	duk_hobject *h_re;
-	duk_hbuffer_dynamic *h_buf;
-#ifdef DUK_USE_REGEXP_SUPPORT
-	duk_bool_t is_regexp;
-	duk_bool_t is_global;
-#endif
-	duk_bool_t is_repl_func;
-	duk_uint32_t match_start_coff, match_start_boff;
-#ifdef DUK_USE_REGEXP_SUPPORT
-	duk_int_t match_caps;
-#endif
-	duk_uint32_t prev_match_end_boff;
-	duk_uint8_t *r_start, *r_end, *r;   /* repl string scan */
+	for (;;) {
+		DUK_ASSERT_TOP(ctx, 3);
 
-	DUK_ASSERT_TOP(ctx, 2);
-	h_input = duk_push_this_coercible_to_string(ctx);
-	DUK_ASSERT(h_input != NULL);
-	duk_push_dynamic_buffer(ctx, 0);
-	h_buf = (duk_hbuffer_dynamic *) duk_get_hbuffer(ctx, -1);
-	DUK_ASSERT(h_buf != NULL);
-	DUK_ASSERT_TOP(ctx, 4);
+		duk_dup(ctx, 0);
+		duk_dup(ctx, 1);
+		duk_regexp_match(thr);  /* -> [ ... regexp string ] -> [ ... res_obj ] */
 
-	/* stack[0] = search value
-	 * stack[1] = replace value
-	 * stack[2] = input string
-	 * stack[3] = result buffer
-	 */
+		if (!duk_is_object(ctx, -1)) {
+			duk_pop(ctx);
+			break;
+		}
 
-	h_re = duk_get_hobject_with_class(ctx, 0, DUK_HOBJECT_CLASS_REGEXP);
-	if (h_re) {
-#ifdef DUK_USE_REGEXP_SUPPORT
-		is_regexp = 1;
-		is_global = duk_get_prop_stridx_boolean(ctx, 0, DUK_STRIDX_GLOBAL, NULL);
+		duk_get_prop_stridx(ctx, 0, DUK_STRIDX_LAST_INDEX);
+		DUK_ASSERT(duk_is_number(ctx, -1));
+		this_index = duk_get_int(ctx, -1);
+		duk_pop(ctx);
 
-		if (is_global) {
-			/* start match from beginning */
-			duk_push_int(ctx, 0);
+		if (this_index == prev_last_index) {
+			this_index++;
+			duk_push_int(ctx, this_index);
 			duk_put_prop_stridx(ctx, 0, DUK_STRIDX_LAST_INDEX);
 		}
-#else  /* DUK_USE_REGEXP_SUPPORT */
-		return DUK_RET_UNSUPPORTED_ERROR;
-#endif  /* DUK_USE_REGEXP_SUPPORT */
-	} else {
-		duk_to_string(ctx, 0);
-#ifdef DUK_USE_REGEXP_SUPPORT
-		is_regexp = 0;
-		is_global = 0;
-#endif
+		prev_last_index = this_index;
+
+		duk_get_prop_index(ctx, -1, 0);  /* match string */
+		duk_put_prop_index(ctx, 2, arr_idx);
+		arr_idx++;
+		duk_pop(ctx);  /* res_obj */
 	}
 
-	if (duk_is_function(ctx, 1)) {
-		is_repl_func = 1;
-		r_start = NULL;
-		r_end = NULL;
-	} else {
-		is_repl_func = 0;
-		h_repl = duk_to_hstring(ctx, 1);
-		DUK_ASSERT(h_repl != NULL);
-		r_start = DUK_HSTRING_GET_DATA(h_repl);
-		r_end = r_start + DUK_HSTRING_GET_BYTELEN(h_repl);
+	if (arr_idx == 0) {
+		duk_push_null(ctx);
 	}
 
-	prev_match_end_boff = 0;
+	return 1;  /* return 'res_arr' or 'null' */
+}
+#else  /* DUK_USE_REGEXP_SUPPORT */
+DUK_INTERNAL duk_ret_t duk_bi_string_prototype_match(duk_context *ctx) {
+	DUK_UNREF(ctx);
+	return DUK_RET_UNSUPPORTED_ERROR;
+}
+#endif  /* DUK_USE_REGEXP_SUPPORT */
 
-	for (;;) {
-		/*
-		 *  If matching with a regexp:
-		 *    - non-global RegExp: lastIndex not touched on a match, zeroed
-		 *      on a non-match
-		 *    - global RegExp: on match, lastIndex will be updated by regexp
-		 *      executor to point to next char after the matching part (so that
-		 *      characters in the matching part are not matched again)
-		 *
-		 *  If matching with a string:
-		 *    - always non-global match, find first occurrence
-		 *
-		 *  We need:
-		 *    - The character offset of start-of-match for the replacer function
-		 *    - The byte offsets for start-of-match and end-of-match to implement
-		 *      the replacement values $&, $`, and $', and to copy non-matching
-		 *      input string portions (including header and trailer) verbatim.
-		 *
-		 *  NOTE: the E5.1 specification is a bit vague how the RegExp should
-		 *  behave in the replacement process; e.g. is matching done first for
-		 *  all matches (in the global RegExp case) before any replacer calls
-		 *  are made?  See: test-bi-string-proto-replace.js for discussion.
-		 */
+DUK_INTERNAL duk_ret_t duk_bi_string_prototype_concat(duk_context *ctx) {
+	/* duk_concat() coerces arguments with ToString() in correct order */
+	(void) duk_push_this_coercible_to_string(ctx);
+	duk_insert(ctx, 0);  /* this is relatively expensive */
+	duk_concat(ctx, duk_get_top(ctx));
+	return 1;
+}
 
-		DUK_ASSERT_TOP(ctx, 4);
+DUK_INTERNAL duk_ret_t duk_bi_string_prototype_trim(duk_context *ctx) {
+	DUK_ASSERT_TOP(ctx, 0);
+	(void) duk_push_this_coercible_to_string(ctx);
+	duk_trim(ctx, 0);
+	DUK_ASSERT_TOP(ctx, 1);
+	return 1;
+}
 
-#ifdef DUK_USE_REGEXP_SUPPORT
-		if (is_regexp) {
-			duk_dup(ctx, 0);
-			duk_dup(ctx, 2);
-			duk_regexp_match(thr);  /* [ ... regexp input ] -> [ res_obj ] */
-			if (!duk_is_object(ctx, -1)) {
-				duk_pop(ctx);
-				break;
-			}
+DUK_INTERNAL duk_ret_t duk_bi_string_prototype_locale_compare(duk_context *ctx) {
+	duk_hstring *h1;
+	duk_hstring *h2;
+	duk_size_t h1_len, h2_len, prefix_len;
+	duk_small_int_t ret = 0;
+	duk_small_int_t rc;
 
-			duk_get_prop_stridx(ctx, -1, DUK_STRIDX_INDEX);
-			DUK_ASSERT(duk_is_number(ctx, -1));
-			match_start_coff = duk_get_int(ctx, -1);
-			duk_pop(ctx);
+	/* The current implementation of localeCompare() is simply a codepoint
+	 * by codepoint comparison, implemented with a simple string compare
+	 * because UTF-8 should preserve codepoint ordering (assuming valid
+	 * shortest UTF-8 encoding).
+	 *
+	 * The specification requires that the return value must be related
+	 * to the sort order: e.g. negative means that 'this' comes before
+	 * 'that' in sort order.  We assume an ascending sort order.
+	 */
 
-			duk_get_prop_index(ctx, -1, 0);
-			DUK_ASSERT(duk_is_string(ctx, -1));
-			h_match = duk_get_hstring(ctx, -1);
-			DUK_ASSERT(h_match != NULL);
-			duk_pop(ctx);  /* h_match is borrowed, remains reachable through match_obj */
+	/* XXX: could share code with duk_js_ops.c, duk_js_compare_helper */
 
-			if (DUK_HSTRING_GET_BYTELEN(h_match) == 0) {
-				/* This should be equivalent to match() algorithm step 8.f.iii.2:
-				 * detect an empty match and allow it, but don't allow it twice.
-				 */
-				duk_uint32_t last_index;
+	h1 = duk_push_this_coercible_to_string(ctx);
+	DUK_ASSERT(h1 != NULL);
 
-				duk_get_prop_stridx(ctx, 0, DUK_STRIDX_LAST_INDEX);
-				last_index = (duk_uint32_t) duk_get_uint(ctx, -1);
-				DUK_DDD(DUK_DDDPRINT("empty match, bump lastIndex: %ld -> %ld",
-				                     (long) last_index, (long) (last_index + 1)));
-				duk_pop(ctx);
-				duk_push_int(ctx, last_index + 1);
-				duk_put_prop_stridx(ctx, 0, DUK_STRIDX_LAST_INDEX);
-			}
+	h2 = duk_to_hstring(ctx, 0);
+	DUK_ASSERT(h2 != NULL);
 
-			DUK_ASSERT(duk_get_length(ctx, -1) <= DUK_INT_MAX);  /* string limits */
-			match_caps = (duk_int_t) duk_get_length(ctx, -1);
-		} else {
-#else  /* DUK_USE_REGEXP_SUPPORT */
-		{  /* unconditionally */
-#endif  /* DUK_USE_REGEXP_SUPPORT */
-			duk_uint8_t *p_start, *p_end, *p;   /* input string scan */
-			duk_uint8_t *q_start;               /* match string */
-			duk_size_t q_blen;
+	h1_len = (duk_size_t) DUK_HSTRING_GET_BYTELEN(h1);
+	h2_len = (duk_size_t) DUK_HSTRING_GET_BYTELEN(h2);
+	prefix_len = (h1_len <= h2_len ? h1_len : h2_len);
 
-#ifdef DUK_USE_REGEXP_SUPPORT
-			DUK_ASSERT(!is_global);  /* single match always */
-#endif
+	/* Zero size compare not an issue with DUK_MEMCMP. */
+	rc = (duk_small_int_t) DUK_MEMCMP((const void *) DUK_HSTRING_GET_DATA(h1),
+	                                  (const void *) DUK_HSTRING_GET_DATA(h2),
+	                                  (size_t) prefix_len);
 
-			p_start = DUK_HSTRING_GET_DATA(h_input);
-			p_end = p_start + DUK_HSTRING_GET_BYTELEN(h_input);
-			p = p_start;
+	if (rc < 0) {
+		ret = -1;
+		goto done;
+	} else if (rc > 0) {
+		ret = 1;
+		goto done;
+	}
 
-			h_search = duk_get_hstring(ctx, 0);
-			DUK_ASSERT(h_search != NULL);
-			q_start = DUK_HSTRING_GET_DATA(h_search);
-			q_blen = (duk_size_t) DUK_HSTRING_GET_BYTELEN(h_search);
+	/* prefix matches, lengths matter now */
+	if (h1_len > h2_len) {
+		ret = 1;
+		goto done;
+	} else if (h1_len == h2_len) {
+		DUK_ASSERT(ret == 0);
+		goto done;
+	}
+	ret = -1;
+	goto done;
 
-			p_end -= q_blen;  /* ensure full memcmp() fits in while */
+ done:
+	duk_push_int(ctx, (duk_int_t) ret);
+	return 1;
+}
+#line 1 "duk_bi_thread.c"
+/*
+ *  Thread builtins
+ */
 
-			match_start_coff = 0;
+/* include removed: duk_internal.h */
 
-			while (p <= p_end) {
-				DUK_ASSERT(p + q_blen <= DUK_HSTRING_GET_DATA(h_input) + DUK_HSTRING_GET_BYTELEN(h_input));
-				if (DUK_MEMCMP((void *) p, (void *) q_start, (size_t) q_blen) == 0) {
-					duk_dup(ctx, 0);
-					h_match = duk_get_hstring(ctx, -1);
-					DUK_ASSERT(h_match != NULL);
-#ifdef DUK_USE_REGEXP_SUPPORT
-					match_caps = 0;
-#endif
-					goto found;
-				}
+/*
+ *  Constructor
+ */
 
-				/* track utf-8 non-continuation bytes */
-				if ((p[0] & 0xc0) != 0x80) {
-					match_start_coff++;
-				}
-				p++;
-			}
+DUK_INTERNAL duk_ret_t duk_bi_thread_constructor(duk_context *ctx) {
+	duk_hthread *new_thr;
+	duk_hobject *func;
 
-			/* not found */
-			break;
-		}
-	 found:
+	/* XXX: need a duk_require_func_or_lfunc_coerce() */
+	if (!duk_is_callable(ctx, 0)) {
+		return DUK_RET_TYPE_ERROR;
+	}
+	func = duk_require_hobject_or_lfunc_coerce(ctx, 0);
+	DUK_ASSERT(func != NULL);
 
-		/* stack[0] = search value
-		 * stack[1] = replace value
-		 * stack[2] = input string
-		 * stack[3] = result buffer
-		 * stack[4] = regexp match OR match string
-		 */
+	duk_push_thread(ctx);
+	new_thr = (duk_hthread *) duk_get_hobject(ctx, -1);
+	DUK_ASSERT(new_thr != NULL);
+	new_thr->state = DUK_HTHREAD_STATE_INACTIVE;
 
-		match_start_boff = duk_heap_strcache_offset_char2byte(thr, h_input, match_start_coff);
+	/* push initial function call to new thread stack; this is
+	 * picked up by resume().
+	 */
+	duk_push_hobject((duk_context *) new_thr, func);
 
-		duk_hbuffer_append_bytes(thr,
-		                         h_buf,
-		                         DUK_HSTRING_GET_DATA(h_input) + prev_match_end_boff,
-		                         (duk_size_t) (match_start_boff - prev_match_end_boff));
+	return 1;  /* return thread */
+}
 
-		prev_match_end_boff = match_start_boff + DUK_HSTRING_GET_BYTELEN(h_match);
+/*
+ *  Resume a thread.
+ *
+ *  The thread must be in resumable state, either (a) new thread which hasn't
+ *  yet started, or (b) a thread which has previously yielded.  This method
+ *  must be called from an Ecmascript function.
+ *
+ *  Args:
+ *    - thread
+ *    - value
+ *    - isError (defaults to false)
+ *
+ *  Note: yield and resume handling is currently asymmetric.
+ */
 
-		if (is_repl_func) {
-			duk_idx_t idx_args;
-			duk_hstring *h_repl;
+DUK_INTERNAL duk_ret_t duk_bi_thread_resume(duk_context *ctx) {
+	duk_hthread *thr = (duk_hthread *) ctx;
+	duk_hthread *thr_resume;
+	duk_tval *tv;
+	duk_hobject *func;
+	duk_hobject *caller_func;
+	duk_small_int_t is_error;
 
-			/* regexp res_obj is at index 4 */
+	DUK_DDD(DUK_DDDPRINT("Duktape.Thread.resume(): thread=%!T, value=%!T, is_error=%!T",
+	                     (duk_tval *) duk_get_tval(ctx, 0),
+	                     (duk_tval *) duk_get_tval(ctx, 1),
+	                     (duk_tval *) duk_get_tval(ctx, 2)));
 
-			duk_dup(ctx, 1);
-			idx_args = duk_get_top(ctx);
+	DUK_ASSERT(thr->state == DUK_HTHREAD_STATE_RUNNING);
+	DUK_ASSERT(thr->heap->curr_thread == thr);
 
-#ifdef DUK_USE_REGEXP_SUPPORT
-			if (is_regexp) {
-				duk_int_t idx;
-				duk_require_stack(ctx, match_caps + 2);
-				for (idx = 0; idx < match_caps; idx++) {
-					/* match followed by capture(s) */
-					duk_get_prop_index(ctx, 4, idx);
-				}
-			} else {
-#else  /* DUK_USE_REGEXP_SUPPORT */
-			{  /* unconditionally */
-#endif  /* DUK_USE_REGEXP_SUPPORT */
-				/* match == search string, by definition */
-				duk_dup(ctx, 0);
-			}
-			duk_push_int(ctx, match_start_coff);
-			duk_dup(ctx, 2);
+	thr_resume = duk_require_hthread(ctx, 0);
+	is_error = (duk_small_int_t) duk_to_boolean(ctx, 2);
+	duk_set_top(ctx, 2);
 
-			/* [ ... replacer match [captures] match_char_offset input ] */
+	/* [ thread value ] */
 
-			duk_call(ctx, duk_get_top(ctx) - idx_args);
-			h_repl = duk_to_hstring(ctx, -1);  /* -> [ ... repl_value ] */
-			DUK_ASSERT(h_repl != NULL);
-			duk_hbuffer_append_hstring(thr, h_buf, h_repl);
-			duk_pop(ctx);  /* repl_value */
-		} else {
-			r = r_start;
+	/*
+	 *  Thread state and calling context checks
+	 */
 
-			while (r < r_end) {
-				duk_int_t ch1;
-				duk_int_t ch2;
-#ifdef DUK_USE_REGEXP_SUPPORT
-				duk_int_t ch3;
-#endif
-				duk_size_t left;
+	if (thr->callstack_top < 2) {
+		DUK_DD(DUK_DDPRINT("resume state invalid: callstack should contain at least 2 entries (caller and Duktape.Thread.resume)"));
+		goto state_error;
+	}
+	DUK_ASSERT(DUK_ACT_GET_FUNC(thr->callstack + thr->callstack_top - 1) != NULL);  /* us */
+	DUK_ASSERT(DUK_HOBJECT_IS_NATIVEFUNCTION(DUK_ACT_GET_FUNC(thr->callstack + thr->callstack_top - 1)));
+	DUK_ASSERT(DUK_ACT_GET_FUNC(thr->callstack + thr->callstack_top - 2) != NULL);  /* caller */
 
-				ch1 = *r++;
-				if (ch1 != DUK_ASC_DOLLAR) {
-					goto repl_write;
-				}
-				left = r_end - r;
+	caller_func = DUK_ACT_GET_FUNC(thr->callstack + thr->callstack_top - 2);
+	if (!DUK_HOBJECT_IS_COMPILEDFUNCTION(caller_func)) {
+		DUK_DD(DUK_DDPRINT("resume state invalid: caller must be Ecmascript code"));
+		goto state_error;
+	}
 
-				if (left <= 0) {
-					goto repl_write;
-				}
+	/* Note: there is no requirement that: 'thr->callstack_preventcount == 1'
+	 * like for yield.
+	 */
 
-				ch2 = r[0];
-				switch ((int) ch2) {
-				case DUK_ASC_DOLLAR: {
-					ch1 = (1 << 8) + DUK_ASC_DOLLAR;
-					goto repl_write;
-				}
-				case DUK_ASC_AMP: {
-					duk_hbuffer_append_hstring(thr, h_buf, h_match);
-					r++;
-					continue;
-				}
-				case DUK_ASC_GRAVE: {
-					duk_hbuffer_append_bytes(thr,
-					                         h_buf,
-					                         DUK_HSTRING_GET_DATA(h_input),
-					                         match_start_boff);
-					r++;
-					continue;
-				}
-				case DUK_ASC_SINGLEQUOTE: {
-					duk_uint32_t match_end_boff;
+	if (thr_resume->state != DUK_HTHREAD_STATE_INACTIVE &&
+	    thr_resume->state != DUK_HTHREAD_STATE_YIELDED) {
+		DUK_DD(DUK_DDPRINT("resume state invalid: target thread must be INACTIVE or YIELDED"));
+		goto state_error;
+	}
 
-					/* Use match charlen instead of bytelen, just in case the input and
-					 * match codepoint encodings would have different lengths.
-					 */
-					match_end_boff = duk_heap_strcache_offset_char2byte(thr,
-					                                                    h_input,
-					                                                    match_start_coff + DUK_HSTRING_GET_CHARLEN(h_match));
+	DUK_ASSERT(thr_resume->state == DUK_HTHREAD_STATE_INACTIVE ||
+	           thr_resume->state == DUK_HTHREAD_STATE_YIELDED);
 
-					duk_hbuffer_append_bytes(thr,
-					                         h_buf,
-					                         DUK_HSTRING_GET_DATA(h_input) + match_end_boff,
-					                         DUK_HSTRING_GET_BYTELEN(h_input) - match_end_boff);
-					r++;
-					continue;
-				}
-				default: {
-#ifdef DUK_USE_REGEXP_SUPPORT
-					duk_int_t capnum, captmp, capadv;
-					/* XXX: optional check, match_caps is zero if no regexp,
-					 * so dollar will be interpreted literally anyway.
-					 */
+	/* Further state-dependent pre-checks */
 
-					if (!is_regexp) {
-						goto repl_write;
-					}
+	if (thr_resume->state == DUK_HTHREAD_STATE_YIELDED) {
+		/* no pre-checks now, assume a previous yield() has left things in
+		 * tip-top shape (longjmp handler will assert for these).
+		 */
+	} else {
+		DUK_ASSERT(thr_resume->state == DUK_HTHREAD_STATE_INACTIVE);
+
+		if ((thr_resume->callstack_top != 0) ||
+		    (thr_resume->valstack_top - thr_resume->valstack != 1)) {
+			goto state_invalid_initial;
+		}
+		tv = &thr_resume->valstack_top[-1];
+		DUK_ASSERT(tv >= thr_resume->valstack && tv < thr_resume->valstack_top);
+		if (!DUK_TVAL_IS_OBJECT(tv)) {
+			goto state_invalid_initial;
+		}
+		func = DUK_TVAL_GET_OBJECT(tv);
+		DUK_ASSERT(func != NULL);
+		if (!DUK_HOBJECT_IS_COMPILEDFUNCTION(func)) {
+			/* Note: cannot be a bound function either right now,
+			 * this would be easy to relax though.
+			 */
+			goto state_invalid_initial;
+		}
+
+	}
+
+	/*
+	 *  The error object has been augmented with a traceback and other
+	 *  info from its creation point -- usually another thread.  The
+	 *  error handler is called here right before throwing, but it also
+	 *  runs in the resumer's thread.  It might be nice to get a traceback
+	 *  from the resumee but this is not the case now.
+	 */
 
-					if (!(ch2 >= DUK_ASC_0 && ch2 <= DUK_ASC_9)) {
-						goto repl_write;
-					}
-					capnum = ch2 - DUK_ASC_0;
-					capadv = 1;
+#if defined(DUK_USE_AUGMENT_ERROR_THROW)
+	if (is_error) {
+		DUK_ASSERT_TOP(ctx, 2);  /* value (error) is at stack top */
+		duk_err_augment_error_throw(thr);  /* in resumer's context */
+	}
+#endif
 
-					if (left >= 2) {
-						ch3 = r[1];
-						if (ch3 >= DUK_ASC_0 && ch3 <= DUK_ASC_9) {
-							captmp = capnum * 10 + (ch3 - DUK_ASC_0);
-							if (captmp < match_caps) {
-								capnum = captmp;
-								capadv = 2;
-							}
-						}
-					}
+#ifdef DUK_USE_DEBUG
+	if (is_error) {
+		DUK_DDD(DUK_DDDPRINT("RESUME ERROR: thread=%!T, value=%!T",
+		                     (duk_tval *) duk_get_tval(ctx, 0),
+		                     (duk_tval *) duk_get_tval(ctx, 1)));
+	} else if (thr_resume->state == DUK_HTHREAD_STATE_YIELDED) {
+		DUK_DDD(DUK_DDDPRINT("RESUME NORMAL: thread=%!T, value=%!T",
+		                     (duk_tval *) duk_get_tval(ctx, 0),
+		                     (duk_tval *) duk_get_tval(ctx, 1)));
+	} else {
+		DUK_DDD(DUK_DDDPRINT("RESUME INITIAL: thread=%!T, value=%!T",
+		                     (duk_tval *) duk_get_tval(ctx, 0),
+		                     (duk_tval *) duk_get_tval(ctx, 1)));
+	}
+#endif
 
-					if (capnum > 0 && capnum < match_caps) {
-						DUK_ASSERT(is_regexp != 0);  /* match_caps == 0 without regexps */
+	thr->heap->lj.type = DUK_LJ_TYPE_RESUME;
 
-						/* regexp res_obj is at offset 4 */
-						duk_get_prop_index(ctx, 4, (duk_uarridx_t) capnum);
-						if (duk_is_string(ctx, -1)) {
-							DUK_ASSERT(duk_get_hstring(ctx, -1) != NULL);
-							duk_hbuffer_append_hstring(thr, h_buf, duk_get_hstring(ctx, -1));
-						} else {
-							/* undefined -> skip (replaced with empty) */
-						}
-						duk_pop(ctx);
-						r += capadv;
-						continue;
-					} else {
-						goto repl_write;
-					}
-#else  /* DUK_USE_REGEXP_SUPPORT */
-					goto repl_write;  /* unconditionally */
-#endif  /* DUK_USE_REGEXP_SUPPORT */
-				}  /* default case */
-				}  /* switch (ch2) */
+	/* lj value2: thread */
+	DUK_ASSERT(thr->valstack_bottom < thr->valstack_top);
+	DUK_TVAL_SET_TVAL_UPDREF(thr, &thr->heap->lj.value2, &thr->valstack_bottom[0]);  /* side effects */
 
-			 repl_write:
-				/* ch1 = (r_increment << 8) + byte */
-				duk_hbuffer_append_byte(thr, h_buf, (duk_uint8_t) (ch1 & 0xff));
-				r += ch1 >> 8;
-			}  /* while repl */
-		}  /* if (is_repl_func) */
+	/* lj value1: value */
+	DUK_ASSERT(thr->valstack_bottom + 1 < thr->valstack_top);
+	DUK_TVAL_SET_TVAL_UPDREF(thr, &thr->heap->lj.value1, &thr->valstack_bottom[1]);  /* side effects */
+	DUK_TVAL_CHKFAST_INPLACE(&thr->heap->lj.value1);
 
-		duk_pop(ctx);  /* pop regexp res_obj or match string */
+	thr->heap->lj.iserror = is_error;
 
-#ifdef DUK_USE_REGEXP_SUPPORT
-		if (!is_global) {
-#else
-		{  /* unconditionally; is_global==0 */
+#if !defined(DUK_USE_CPP_EXCEPTIONS)
+	DUK_ASSERT(thr->heap->lj.jmpbuf_ptr != NULL);  /* call is from executor, so we know we have a jmpbuf */
 #endif
-			break;
-		}
-	}
+	duk_err_longjmp(thr);  /* execution resumes in bytecode executor */
+	return 0;  /* never here */
 
-	/* trailer */
-	duk_hbuffer_append_bytes(thr,
-	                         h_buf,
-	                         DUK_HSTRING_GET_DATA(h_input) + prev_match_end_boff,
-	                         (duk_size_t) (DUK_HSTRING_GET_BYTELEN(h_input) - prev_match_end_boff));
+ state_invalid_initial:
+	DUK_ERROR(thr, DUK_ERR_TYPE_ERROR, "invalid initial thread state/stack");
+	return 0;  /* never here */
 
-	DUK_ASSERT_TOP(ctx, 4);
-	duk_to_string(ctx, -1);
-	return 1;
+ state_error:
+	DUK_ERROR(thr, DUK_ERR_TYPE_ERROR, "invalid state for resume");
+	return 0;  /* never here */
 }
 
 /*
- *  split()
- */
-
-/* XXX: very messy now, but works; clean up, remove unused variables (nomimally
- * used so compiler doesn't complain).
+ *  Yield the current thread.
+ *
+ *  The thread must be in yieldable state: it must have a resumer, and there
+ *  must not be any yield-preventing calls (native calls and constructor calls,
+ *  currently) in the thread's call stack (otherwise a resume would not be
+ *  possible later).  This method must be called from an Ecmascript function.
+ *
+ *  Args:
+ *    - value
+ *    - isError (defaults to false)
+ *
+ *  Note: yield and resume handling is currently asymmetric.
  */
 
-duk_ret_t duk_bi_string_prototype_split(duk_context *ctx) {
+DUK_INTERNAL duk_ret_t duk_bi_thread_yield(duk_context *ctx) {
 	duk_hthread *thr = (duk_hthread *) ctx;
-	duk_hstring *h_input;
-	duk_hstring *h_sep;
-	duk_uint32_t limit;
-	duk_uint32_t arr_idx;
-#ifdef DUK_USE_REGEXP_SUPPORT
-	duk_bool_t is_regexp;
-#endif
-	duk_bool_t matched;  /* set to 1 if any match exists (needed for empty input special case) */
-	duk_uint32_t prev_match_end_coff, prev_match_end_boff;
-	duk_uint32_t match_start_boff, match_start_coff;
-	duk_uint32_t match_end_boff, match_end_coff;
+	duk_hobject *caller_func;
+	duk_small_int_t is_error;
 
-	DUK_UNREF(thr);
+	DUK_DDD(DUK_DDDPRINT("Duktape.Thread.yield(): value=%!T, is_error=%!T",
+	                     (duk_tval *) duk_get_tval(ctx, 0),
+	                     (duk_tval *) duk_get_tval(ctx, 1)));
 
-	h_input = duk_push_this_coercible_to_string(ctx);
-	DUK_ASSERT(h_input != NULL);
+	DUK_ASSERT(thr->state == DUK_HTHREAD_STATE_RUNNING);
+	DUK_ASSERT(thr->heap->curr_thread == thr);
 
-	duk_push_array(ctx);
+	is_error = (duk_small_int_t) duk_to_boolean(ctx, 1);
+	duk_set_top(ctx, 1);
 
-	if (duk_is_undefined(ctx, 1)) {
-		limit = 0xffffffffUL;
-	} else {
-		limit = duk_to_uint32(ctx, 1);
+	/* [ value ] */
+
+	/*
+	 *  Thread state and calling context checks
+	 */
+
+	if (!thr->resumer) {
+		DUK_DD(DUK_DDPRINT("yield state invalid: current thread must have a resumer"));
+		goto state_error;
 	}
+	DUK_ASSERT(thr->resumer->state == DUK_HTHREAD_STATE_RESUMED);
 
-	if (limit == 0) {
-		return 1;
+	if (thr->callstack_top < 2) {
+		DUK_DD(DUK_DDPRINT("yield state invalid: callstack should contain at least 2 entries (caller and Duktape.Thread.yield)"));
+		goto state_error;
 	}
+	DUK_ASSERT(DUK_ACT_GET_FUNC(thr->callstack + thr->callstack_top - 1) != NULL);  /* us */
+	DUK_ASSERT(DUK_HOBJECT_IS_NATIVEFUNCTION(DUK_ACT_GET_FUNC(thr->callstack + thr->callstack_top - 1)));
+	DUK_ASSERT(DUK_ACT_GET_FUNC(thr->callstack + thr->callstack_top - 2) != NULL);  /* caller */
 
-	/* If the separator is a RegExp, make a "clone" of it.  The specification
-	 * algorithm calls [[Match]] directly for specific indices; we emulate this
-	 * by tweaking lastIndex and using a "force global" variant of duk_regexp_match()
-	 * which will use global-style matching even when the RegExp itself is non-global.
-	 */
+	caller_func = DUK_ACT_GET_FUNC(thr->callstack + thr->callstack_top - 2);
+	if (!DUK_HOBJECT_IS_COMPILEDFUNCTION(caller_func)) {
+		DUK_DD(DUK_DDPRINT("yield state invalid: caller must be Ecmascript code"));
+		goto state_error;
+	}
 
-	if (duk_is_undefined(ctx, 0)) {
-		/* The spec algorithm first does "R = ToString(separator)" before checking
-		 * whether separator is undefined.  Since this is side effect free, we can
-		 * skip the ToString() here.
-		 */
-		duk_dup(ctx, 2);
-		duk_put_prop_index(ctx, 3, 0);
-		return 1;
-	} else if (duk_get_hobject_with_class(ctx, 0, DUK_HOBJECT_CLASS_REGEXP) != NULL) {
-#ifdef DUK_USE_REGEXP_SUPPORT
-		duk_push_hobject_bidx(ctx, DUK_BIDX_REGEXP_CONSTRUCTOR);
-		duk_dup(ctx, 0);
-		duk_new(ctx, 1);  /* [ ... RegExp val ] -> [ ... res ] */
-		duk_replace(ctx, 0);
-		/* lastIndex is initialized to zero by new RegExp() */
-		is_regexp = 1;
-#else
-		return DUK_RET_UNSUPPORTED_ERROR;
-#endif
-	} else {
-		duk_to_string(ctx, 0);
-#ifdef DUK_USE_REGEXP_SUPPORT
-		is_regexp = 0;
-#endif
+	DUK_ASSERT(thr->callstack_preventcount >= 1);  /* should never be zero, because we (Duktape.Thread.yield) are on the stack */
+	if (thr->callstack_preventcount != 1) {
+		/* Note: the only yield-preventing call is Duktape.Thread.yield(), hence check for 1, not 0 */
+		DUK_DD(DUK_DDPRINT("yield state invalid: there must be no yield-preventing calls in current thread callstack (preventcount is %ld)",
+		                   (long) thr->callstack_preventcount));
+		goto state_error;
 	}
 
-	/* stack[0] = separator (string or regexp)
-	 * stack[1] = limit
-	 * stack[2] = input string
-	 * stack[3] = result array
+	/*
+	 *  The error object has been augmented with a traceback and other
+	 *  info from its creation point -- usually the current thread.
+	 *  The error handler, however, is called right before throwing
+	 *  and runs in the yielder's thread.
 	 */
 
-	prev_match_end_boff = 0;
-	prev_match_end_coff = 0;
-	arr_idx = 0;
-	matched = 0;
-
-	for (;;) {
-		/*
-		 *  The specification uses RegExp [[Match]] to attempt match at specific
-		 *  offsets.  We don't have such a primitive, so we use an actual RegExp
-		 *  and tweak lastIndex.  Since the RegExp may be non-global, we use a
-		 *  special variant which forces global-like behavior for matching.
-		 */
+#if defined(DUK_USE_AUGMENT_ERROR_THROW)
+	if (is_error) {
+		DUK_ASSERT_TOP(ctx, 1);  /* value (error) is at stack top */
+		duk_err_augment_error_throw(thr);  /* in yielder's context */
+	}
+#endif
 
-		DUK_ASSERT_TOP(ctx, 4);
+#ifdef DUK_USE_DEBUG
+	if (is_error) {
+		DUK_DDD(DUK_DDDPRINT("YIELD ERROR: value=%!T",
+		                     (duk_tval *) duk_get_tval(ctx, 0)));
+	} else {
+		DUK_DDD(DUK_DDDPRINT("YIELD NORMAL: value=%!T",
+		                     (duk_tval *) duk_get_tval(ctx, 0)));
+	}
+#endif
 
-#ifdef DUK_USE_REGEXP_SUPPORT
-		if (is_regexp) {
-			duk_dup(ctx, 0);
-			duk_dup(ctx, 2);
-			duk_regexp_match_force_global(thr);  /* [ ... regexp input ] -> [ res_obj ] */
-			if (!duk_is_object(ctx, -1)) {
-				duk_pop(ctx);
-				break;
-			}
-			matched = 1;
+	/*
+	 *  Process yield
+	 *
+	 *  After longjmp(), processing continues in bytecode executor longjmp
+	 *  handler, which will e.g. update thr->resumer to NULL.
+	 */
 
-			duk_get_prop_stridx(ctx, -1, DUK_STRIDX_INDEX);
-			DUK_ASSERT(duk_is_number(ctx, -1));
-			match_start_coff = duk_get_int(ctx, -1);
-			match_start_boff = duk_heap_strcache_offset_char2byte(thr, h_input, match_start_coff);
-			duk_pop(ctx);
+	thr->heap->lj.type = DUK_LJ_TYPE_YIELD;
 
-			if (match_start_coff == DUK_HSTRING_GET_CHARLEN(h_input)) {
-				/* don't allow an empty match at the end of the string */
-				duk_pop(ctx);
-				break;
-			}
+	/* lj value1: value */
+	DUK_ASSERT(thr->valstack_bottom < thr->valstack_top);
+	DUK_TVAL_SET_TVAL_UPDREF(thr, &thr->heap->lj.value1, &thr->valstack_bottom[0]);  /* side effects */
+	DUK_TVAL_CHKFAST_INPLACE(&thr->heap->lj.value1);
 
-			duk_get_prop_stridx(ctx, 0, DUK_STRIDX_LAST_INDEX);
-			DUK_ASSERT(duk_is_number(ctx, -1));
-			match_end_coff = duk_get_int(ctx, -1);
-			match_end_boff = duk_heap_strcache_offset_char2byte(thr, h_input, match_end_coff);
-			duk_pop(ctx);
+	thr->heap->lj.iserror = is_error;
 
-			/* empty match -> bump and continue */
-			if (prev_match_end_boff == match_end_boff) {
-				duk_push_int(ctx, match_end_coff + 1);
-				duk_put_prop_stridx(ctx, 0, DUK_STRIDX_LAST_INDEX);
-				duk_pop(ctx);
-				continue;
-			}
-		} else {
-#else  /* DUK_USE_REGEXP_SUPPORT */
-		{  /* unconditionally */
-#endif  /* DUK_USE_REGEXP_SUPPORT */
-			duk_uint8_t *p_start, *p_end, *p;   /* input string scan */
-			duk_uint8_t *q_start;               /* match string */
-			duk_size_t q_blen, q_clen;
+#if !defined(DUK_USE_CPP_EXCEPTIONS)
+	DUK_ASSERT(thr->heap->lj.jmpbuf_ptr != NULL);  /* call is from executor, so we know we have a jmpbuf */
+#endif
+	duk_err_longjmp(thr);  /* execution resumes in bytecode executor */
+	return 0;  /* never here */
 
-			p_start = DUK_HSTRING_GET_DATA(h_input);
-			p_end = p_start + DUK_HSTRING_GET_BYTELEN(h_input);
-			p = p_start + prev_match_end_boff;
+ state_error:
+	DUK_ERROR(thr, DUK_ERR_TYPE_ERROR, "invalid state for yield");
+	return 0;  /* never here */
+}
 
-			h_sep = duk_get_hstring(ctx, 0);
-			DUK_ASSERT(h_sep != NULL);
-			q_start = DUK_HSTRING_GET_DATA(h_sep);
-			q_blen = (duk_size_t) DUK_HSTRING_GET_BYTELEN(h_sep);
-			q_clen = (duk_size_t) DUK_HSTRING_GET_CHARLEN(h_sep);
+DUK_INTERNAL duk_ret_t duk_bi_thread_current(duk_context *ctx) {
+	duk_push_current_thread(ctx);
+	return 1;
+}
+#line 1 "duk_bi_thrower.c"
+/*
+ *  Type error thrower, E5 Section 13.2.3.
+ */
 
-			p_end -= q_blen;  /* ensure full memcmp() fits in while */
+/* include removed: duk_internal.h */
 
-			match_start_coff = prev_match_end_coff;
+DUK_INTERNAL duk_ret_t duk_bi_type_error_thrower(duk_context *ctx) {
+	DUK_UNREF(ctx);
+	return DUK_RET_TYPE_ERROR;
+}
+#line 1 "duk_debug_fixedbuffer.c"
+/*
+ *  Fixed buffer helper useful for debugging, requires no allocation
+ *  which is critical for debugging.
+ */
 
-			if (q_blen == 0) {
-				/* Handle empty separator case: it will always match, and always
-				 * triggers the check in step 13.c.iii initially.  Note that we
-				 * must skip to either end of string or start of first codepoint,
-				 * skipping over any continuation bytes!
-				 *
-				 * Don't allow an empty string to match at the end of the input.
-				 */
+/* include removed: duk_internal.h */
 
-				matched = 1;  /* empty separator can always match */
+#ifdef DUK_USE_DEBUG
 
-				match_start_coff++;
-				p++;
-				while (p < p_end) {
-					if ((p[0] & 0xc0) != 0x80) {
-						goto found;
-					}
-					p++;
-				}
-				goto not_found;
-			}
+DUK_INTERNAL void duk_fb_put_bytes(duk_fixedbuffer *fb, const duk_uint8_t *buffer, duk_size_t length) {
+	duk_size_t avail;
+	duk_size_t copylen;
 
-			DUK_ASSERT(q_blen > 0 && q_clen > 0);
-			while (p <= p_end) {
-				DUK_ASSERT(p + q_blen <= DUK_HSTRING_GET_DATA(h_input) + DUK_HSTRING_GET_BYTELEN(h_input));
-				DUK_ASSERT(q_blen > 0);  /* no issues with empty memcmp() */
-				if (DUK_MEMCMP((void *) p, (void *) q_start, (duk_size_t) q_blen) == 0) {
-					/* never an empty match, so step 13.c.iii can't be triggered */
-					goto found;
-				}
+	avail = (fb->offset >= fb->length ? (duk_size_t) 0 : (duk_size_t) (fb->length - fb->offset));
+	if (length > avail) {
+		copylen = avail;
+		fb->truncated = 1;
+	} else {
+		copylen = length;
+	}
+	DUK_MEMCPY(fb->buffer + fb->offset, buffer, copylen);
+	fb->offset += copylen;
+}
 
-				/* track utf-8 non-continuation bytes */
-				if ((p[0] & 0xc0) != 0x80) {
-					match_start_coff++;
-				}
-				p++;
-			}
+DUK_INTERNAL void duk_fb_put_byte(duk_fixedbuffer *fb, duk_uint8_t x) {
+	duk_fb_put_bytes(fb, (const duk_uint8_t *) &x, 1);
+}
 
-		 not_found:
-			/* not found */
-			break;
+DUK_INTERNAL void duk_fb_put_cstring(duk_fixedbuffer *fb, const char *x) {
+	duk_fb_put_bytes(fb, (const duk_uint8_t *) x, (duk_size_t) DUK_STRLEN(x));
+}
 
-		 found:
-			matched = 1;
-			match_start_boff = (duk_uint32_t) (p - p_start);
-			match_end_coff = match_start_coff + q_clen;
-			match_end_boff = match_start_boff + q_blen;
+DUK_INTERNAL void duk_fb_sprintf(duk_fixedbuffer *fb, const char *fmt, ...) {
+	duk_size_t avail;
+	va_list ap;
 
-			/* empty match (may happen with empty separator) -> bump and continue */
-			if (prev_match_end_boff == match_end_boff) {
-				prev_match_end_boff++;
-				prev_match_end_coff++;
-				continue;
+	va_start(ap, fmt);
+	avail = (fb->offset >= fb->length ? (duk_size_t) 0 : (duk_size_t) (fb->length - fb->offset));
+	if (avail > 0) {
+		duk_int_t res = (duk_int_t) DUK_VSNPRINTF((char *) (fb->buffer + fb->offset), avail, fmt, ap);
+		if (res < 0) {
+			/* error */
+		} else if ((duk_size_t) res >= avail) {
+			/* (maybe) truncated */
+			fb->offset += avail;
+			if ((duk_size_t) res > avail) {
+				/* actual chars dropped (not just NUL term) */
+				fb->truncated = 1;
 			}
-		}  /* if (is_regexp) */
-
-		/* stack[0] = separator (string or regexp)
-		 * stack[1] = limit
-		 * stack[2] = input string
-		 * stack[3] = result array
-		 * stack[4] = regexp res_obj (if is_regexp)
-		 */
-
-		DUK_DDD(DUK_DDDPRINT("split; match_start b=%ld,c=%ld, match_end b=%ld,c=%ld, prev_end b=%ld,c=%ld",
-		                     (long) match_start_boff, (long) match_start_coff,
-		                     (long) match_end_boff, (long) match_end_coff,
-		                     (long) prev_match_end_boff, (long) prev_match_end_coff));
-
-		duk_push_lstring(ctx,
-		                 (const char *) (DUK_HSTRING_GET_DATA(h_input) + prev_match_end_boff),
-		                 (duk_size_t) (match_start_boff - prev_match_end_boff));
-		duk_put_prop_index(ctx, 3, arr_idx);
-		arr_idx++;
-		if (arr_idx >= limit) {
-			goto hit_limit;
+		} else {
+			/* normal */
+			fb->offset += res;
 		}
+	}
+	va_end(ap);
+}
 
-#ifdef DUK_USE_REGEXP_SUPPORT
-		if (is_regexp) {
-			duk_size_t i, len;
+DUK_INTERNAL void duk_fb_put_funcptr(duk_fixedbuffer *fb, duk_uint8_t *fptr, duk_size_t fptr_size) {
+	char buf[64+1];
+	duk_debug_format_funcptr(buf, sizeof(buf), fptr, fptr_size);
+	buf[sizeof(buf) - 1] = (char) 0;
+	duk_fb_put_cstring(fb, buf);
+}
 
-			len = duk_get_length(ctx, 4);
-			for (i = 1; i < len; i++) {
-				DUK_ASSERT(i <= DUK_UARRIDX_MAX);  /* cannot have >4G captures */
-				duk_get_prop_index(ctx, 4, (duk_uarridx_t) i);
-				duk_put_prop_index(ctx, 3, arr_idx);
-				arr_idx++;
-				if (arr_idx >= limit) {
-					goto hit_limit;
-				}
-			}
+DUK_INTERNAL duk_bool_t duk_fb_is_full(duk_fixedbuffer *fb) {
+	return (fb->offset >= fb->length);
+}
 
-			duk_pop(ctx);
-			/* lastIndex already set up for next match */
-		} else {
-#else  /* DUK_USE_REGEXP_SUPPORT */
-		{  /* unconditionally */
-#endif  /* DUK_USE_REGEXP_SUPPORT */
-			/* no action */
-		}
+#endif  /* DUK_USE_DEBUG */
+#line 1 "duk_debug_heap.c"
+/*
+ *  Debug dumping of duk_heap.
+ */
 
-		prev_match_end_boff = match_end_boff;
-		prev_match_end_coff = match_end_coff;
-		continue;
-	}  /* for */
+/* include removed: duk_internal.h */
 
-	/* Combined step 11 (empty string special case) and 14-15. */
+#ifdef DUK_USE_DEBUG
 
-	DUK_DDD(DUK_DDDPRINT("split trailer; prev_end b=%ld,c=%ld",
-	                     (long) prev_match_end_boff, (long) prev_match_end_coff));
+#if 0  /*unused*/
+DUK_LOCAL void duk__sanitize_snippet(char *buf, duk_size_t buf_size, duk_hstring *str) {
+	duk_size_t i;
+	duk_size_t nchars;
+	duk_size_t maxchars;
+	duk_uint8_t *data;
 
-	if (DUK_HSTRING_GET_CHARLEN(h_input) > 0 || !matched) {
-		/* Add trailer if:
-		 *   a) non-empty input
-		 *   b) empty input and no (zero size) match found (step 11)
-		 */
+	DUK_MEMZERO(buf, buf_size);
 
-		duk_push_lstring(ctx,
-		                 (const char *) DUK_HSTRING_GET_DATA(h_input) + prev_match_end_boff,
-		                 (duk_size_t) (DUK_HSTRING_GET_BYTELEN(h_input) - prev_match_end_boff));
-		duk_put_prop_index(ctx, 3, arr_idx);
-		/* No arr_idx update or limit check */
+	maxchars = (duk_size_t) (buf_size - 1);
+	data = DUK_HSTRING_GET_DATA(str);
+	nchars = ((duk_size_t) str->blen < maxchars ? (duk_size_t) str->blen : maxchars);
+	for (i = 0; i < nchars; i++) {
+		duk_small_int_t c = (duk_small_int_t) data[i];
+		if (c < 0x20 || c > 0x7e) {
+			c = '.';
+		}
+		buf[i] = (char) c;
 	}
+}
+#endif
 
-	return 1;
-
- hit_limit:
-#ifdef DUK_USE_REGEXP_SUPPORT
-	if (is_regexp) {
-		duk_pop(ctx);
+#if 0
+DUK_LOCAL const char *duk__get_heap_type_string(duk_heaphdr *hdr) {
+	switch (DUK_HEAPHDR_GET_TYPE(hdr)) {
+	case DUK_HTYPE_STRING:
+		return "string";
+	case DUK_HTYPE_OBJECT:
+		return "object";
+	case DUK_HTYPE_BUFFER:
+		return "buffer";
+	default:
+		return "???";
 	}
+}
 #endif
 
-	return 1;
+#if 0
+DUK_LOCAL void duk__dump_indented(duk_heaphdr *obj, int index) {
+	DUK_UNREF(obj);
+	DUK_UNREF(index);
+	DUK_UNREF(duk__get_heap_type_string);
+
+#ifdef DUK_USE_REFERENCE_COUNTING
+	DUK_D(DUK_DPRINT("  [%ld]: %p %s (flags: 0x%08lx, ref: %ld) -> %!O",
+	                 (long) index,
+	                 (void *) obj,
+	                 (const char *) duk__get_heap_type_string(obj),
+	                 (unsigned long) DUK_HEAPHDR_GET_FLAGS(obj),
+	                 (long) DUK_HEAPHDR_GET_REFCOUNT(obj),
+	                 (duk_heaphdr *) obj));
+#else
+	DUK_D(DUK_DPRINT("  [%ld]: %p %s (flags: 0x%08lx) -> %!O",
+	                 (long) index,
+	                 (void *) obj,
+	                 (const char *) duk__get_heap_type_string(obj),
+	                 (unsigned long) DUK_HEAPHDR_GET_FLAGS(obj),
+	                 (duk_heaphdr *) obj));
+#endif
 }
+#endif
 
-/*
- *  Various
- */
-
-#ifdef DUK_USE_REGEXP_SUPPORT
-static void duk__to_regexp_helper(duk_context *ctx, duk_idx_t index, duk_bool_t force_new) {
-	duk_hobject *h;
-
-	/* Shared helper for match() steps 3-4, search() steps 3-4. */
+#if 0  /*unused*/
+DUK_LOCAL void duk__dump_heaphdr_list(duk_heap *heap, duk_heaphdr *root, const char *name) {
+	duk_int_t count;
+	duk_heaphdr *curr;
 
-	DUK_ASSERT(index >= 0);
+	DUK_UNREF(heap);
+	DUK_UNREF(name);
 
-	if (force_new) {
-		goto do_new;
+	count = 0;
+	curr = root;
+	while (curr) {
+		count++;
+		curr = DUK_HEAPHDR_GET_NEXT(curr);
 	}
 
-	h = duk_get_hobject_with_class(ctx, index, DUK_HOBJECT_CLASS_REGEXP);
-	if (!h) {
-		goto do_new;
-	}
-	return;
+	DUK_D(DUK_DPRINT("%s, %ld objects", (const char *) name, (long) count));
 
- do_new:
-	duk_push_hobject_bidx(ctx, DUK_BIDX_REGEXP_CONSTRUCTOR);
-	duk_dup(ctx, index);
-	duk_new(ctx, 1);  /* [ ... RegExp val ] -> [ ... res ] */
-	duk_replace(ctx, index);
+	count = 0;
+	curr = root;
+	while (curr) {
+		count++;
+		duk__dump_indented(curr, count);
+		curr = DUK_HEAPHDR_GET_NEXT(curr);
+	}
 }
-#endif  /* DUK_USE_REGEXP_SUPPORT */
-
-#ifdef DUK_USE_REGEXP_SUPPORT
-duk_ret_t duk_bi_string_prototype_search(duk_context *ctx) {
-	duk_hthread *thr = (duk_hthread *) ctx;
-
-	/* Easiest way to implement the search required by the specification
-	 * is to do a RegExp test() with lastIndex forced to zero.  To avoid
-	 * side effects on the argument, "clone" the RegExp if a RegExp was
-	 * given as input.
-	 *
-	 * The global flag of the RegExp should be ignored; setting lastIndex
-	 * to zero (which happens when "cloning" the RegExp) should have an
-	 * equivalent effect.
-	 */
+#endif
 
-	DUK_ASSERT_TOP(ctx, 1);
-	(void) duk_push_this_coercible_to_string(ctx);  /* at index 1 */
-	duk__to_regexp_helper(ctx, 0 /*index*/, 1 /*force_new*/);
+#if 0  /*unused*/
+DUK_LOCAL void duk__dump_stringtable(duk_heap *heap) {
+	duk_uint_fast32_t i;
+	char buf[64+1];
 
-	/* stack[0] = regexp
-	 * stack[1] = string
-	 */
+	DUK_D(DUK_DPRINT("stringtable %p, used %ld, size %ld, load %ld%%",
+	                 (void *) heap->strtable,
+	                 (long) heap->st_used,
+	                 (long) heap->st_size,
+	                 (long) (((double) heap->st_used) / ((double) heap->st_size) * 100.0)));
 
-	/* Avoid using RegExp.prototype methods, as they're writable and
-	 * configurable and may have been changed.
-	 */
+	for (i = 0; i < (duk_uint_fast32_t) heap->st_size; i++) {
+		duk_hstring *e = heap->strtable[i];
 
-	duk_dup(ctx, 0);
-	duk_dup(ctx, 1);  /* [ ... re_obj input ] */
-	duk_regexp_match(thr);  /* -> [ ... res_obj ] */
+		if (!e) {
+			DUK_D(DUK_DPRINT("  [%ld]: NULL", (long) i));
+		} else if (e == DUK_STRTAB_DELETED_MARKER(heap)) {
+			DUK_D(DUK_DPRINT("  [%ld]: DELETED", (long) i));
+		} else {
+			duk__sanitize_snippet(buf, sizeof(buf), e);
 
-	if (!duk_is_object(ctx, -1)) {
-		duk_push_int(ctx, -1);
-		return 1;
+#ifdef DUK_USE_REFERENCE_COUNTING
+			DUK_D(DUK_DPRINT("  [%ld]: %p (flags: 0x%08lx, ref: %ld) '%s', strhash=0x%08lx, blen=%ld, clen=%ld, "
+			                 "arridx=%ld, internal=%ld, reserved_word=%ld, strict_reserved_word=%ld, eval_or_arguments=%ld",
+			                 (long) i,
+			                 (void *) e,
+			                 (unsigned long) DUK_HEAPHDR_GET_FLAGS((duk_heaphdr *) e),
+			                 (long) DUK_HEAPHDR_GET_REFCOUNT((duk_heaphdr *) e),
+			                 (const char *) buf,
+			                 (unsigned long) e->hash,
+			                 (long) e->blen,
+			                 (long) e->clen,
+			                 (long) (DUK_HSTRING_HAS_ARRIDX(e) ? 1 : 0),
+			                 (long) (DUK_HSTRING_HAS_INTERNAL(e) ? 1 : 0),
+			                 (long) (DUK_HSTRING_HAS_RESERVED_WORD(e) ? 1 : 0),
+			                 (long) (DUK_HSTRING_HAS_STRICT_RESERVED_WORD(e) ? 1 : 0),
+			                 (long) (DUK_HSTRING_HAS_EVAL_OR_ARGUMENTS(e) ? 1 : 0)));
+#else
+			DUK_D(DUK_DPRINT("  [%ld]: %p (flags: 0x%08lx) '%s', strhash=0x%08lx, blen=%ld, clen=%ld, "
+			                 "arridx=%ld, internal=%ld, reserved_word=%ld, strict_reserved_word=%ld, eval_or_arguments=%ld",
+			                 (long) i,
+			                 (void *) e,
+			                 (unsigned long) DUK_HEAPHDR_GET_FLAGS((duk_heaphdr *) e),
+			                 (const char *) buf,
+			                 (long) e->hash,
+			                 (long) e->blen,
+			                 (long) e->clen,
+			                 (long) (DUK_HSTRING_HAS_ARRIDX(e) ? 1 : 0),
+			                 (long) (DUK_HSTRING_HAS_INTERNAL(e) ? 1 : 0),
+			                 (long) (DUK_HSTRING_HAS_RESERVED_WORD(e) ? 1 : 0),
+			                 (long) (DUK_HSTRING_HAS_STRICT_RESERVED_WORD(e) ? 1 : 0),
+			                 (long) (DUK_HSTRING_HAS_EVAL_OR_ARGUMENTS(e) ? 1 : 0)));
+#endif
+		}
 	}
-
-	duk_get_prop_stridx(ctx, -1, DUK_STRIDX_INDEX);
-	DUK_ASSERT(duk_is_number(ctx, -1));
-	return 1;
-}
-#else  /* DUK_USE_REGEXP_SUPPORT */
-duk_ret_t duk_bi_string_prototype_search(duk_context *ctx) {
-	DUK_UNREF(ctx);
-	return DUK_RET_UNSUPPORTED_ERROR;
 }
-#endif  /* DUK_USE_REGEXP_SUPPORT */
-
-#ifdef DUK_USE_REGEXP_SUPPORT
-duk_ret_t duk_bi_string_prototype_match(duk_context *ctx) {
-	duk_hthread *thr = (duk_hthread *) ctx;
-	duk_bool_t global;
-	duk_int_t prev_last_index;
-	duk_int_t this_index;
-	duk_int_t arr_idx;
+#endif
 
-	DUK_ASSERT_TOP(ctx, 1);
-	(void) duk_push_this_coercible_to_string(ctx);
-	duk__to_regexp_helper(ctx, 0 /*index*/, 0 /*force_new*/);
-	global = duk_get_prop_stridx_boolean(ctx, 0, DUK_STRIDX_GLOBAL, NULL);
-	DUK_ASSERT_TOP(ctx, 2);
+#if 0  /*unused*/
+DUK_LOCAL void duk__dump_strcache(duk_heap *heap) {
+	duk_uint_fast32_t i;
+	char buf[64+1];
 
-	/* stack[0] = regexp
-	 * stack[1] = string
-	 */
+	DUK_D(DUK_DPRINT("stringcache"));
 
-	if (!global) {
-		duk_regexp_match(thr);  /* -> [ res_obj ] */
-		return 1;  /* return 'res_obj' */
+	for (i = 0; i < (duk_uint_fast32_t) DUK_HEAP_STRCACHE_SIZE; i++) {
+		duk_strcache *c = &heap->strcache[i];
+		if (!c->h) {
+			DUK_D(DUK_DPRINT("  [%ld]: bidx=%ld, cidx=%ld, str=NULL",
+			                 (long) i, (long) c->bidx, (long) c->cidx));
+		} else {
+			duk__sanitize_snippet(buf, sizeof(buf), c->h);
+			DUK_D(DUK_DPRINT("  [%ld]: bidx=%ld cidx=%ld str=%s",
+			                 (long) i, (long) c->bidx, (long) c->cidx, (const char *) buf));
+		}
 	}
+}
+#endif
 
-	/* Global case is more complex. */
-
-	/* [ regexp string ] */
+#if 0  /*unused*/
+DUK_INTERNAL void duk_debug_dump_heap(duk_heap *heap) {
+	char buf[64+1];
 
-	duk_push_int(ctx, 0);
-	duk_put_prop_stridx(ctx, 0, DUK_STRIDX_LAST_INDEX);
-	duk_push_array(ctx);
+	DUK_D(DUK_DPRINT("=== heap %p ===", (void *) heap));
+	DUK_D(DUK_DPRINT("  flags: 0x%08lx", (unsigned long) heap->flags));
 
-	/* [ regexp string res_arr ] */
+	/* Note: there is no standard formatter for function pointers */
+#ifdef DUK_USE_GCC_PRAGMAS
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-pedantic"
+#endif
+	duk_debug_format_funcptr(buf, sizeof(buf), (duk_uint8_t *) &heap->alloc_func, sizeof(heap->alloc_func));
+	DUK_D(DUK_DPRINT("  alloc_func: %s", (const char *) buf));
+	duk_debug_format_funcptr(buf, sizeof(buf), (duk_uint8_t *) &heap->realloc_func, sizeof(heap->realloc_func));
+	DUK_D(DUK_DPRINT("  realloc_func: %s", (const char *) buf));
+	duk_debug_format_funcptr(buf, sizeof(buf), (duk_uint8_t *) &heap->free_func, sizeof(heap->free_func));
+	DUK_D(DUK_DPRINT("  free_func: %s", (const char *) buf));
+	duk_debug_format_funcptr(buf, sizeof(buf), (duk_uint8_t *) &heap->fatal_func, sizeof(heap->fatal_func));
+	DUK_D(DUK_DPRINT("  fatal_func: %s", (const char *) buf));
+#ifdef DUK_USE_GCC_PRAGMAS
+#pragma GCC diagnostic pop
+#endif
 
-	prev_last_index = 0;
-	arr_idx = 0;
+	DUK_D(DUK_DPRINT("  heap_udata: %p", (void *) heap->heap_udata));
 
-	for (;;) {
-		DUK_ASSERT_TOP(ctx, 3);
+#ifdef DUK_USE_MARK_AND_SWEEP
+#ifdef DUK_USE_VOLUNTARY_GC
+	DUK_D(DUK_DPRINT("  mark-and-sweep trig counter: %ld", (long) heap->mark_and_sweep_trigger_counter));
+#endif
+	DUK_D(DUK_DPRINT("  mark-and-sweep rec depth: %ld", (long) heap->mark_and_sweep_recursion_depth));
+	DUK_D(DUK_DPRINT("  mark-and-sweep base flags: 0x%08lx", (unsigned long) heap->mark_and_sweep_base_flags));
+#endif
 
-		duk_dup(ctx, 0);
-		duk_dup(ctx, 1);
-		duk_regexp_match(thr);  /* -> [ ... regexp string ] -> [ ... res_obj ] */
+	DUK_D(DUK_DPRINT("  lj.jmpbuf_ptr: %p", (void *) heap->lj.jmpbuf_ptr));
+	DUK_D(DUK_DPRINT("  lj.type: %ld", (long) heap->lj.type));
+	DUK_D(DUK_DPRINT("  lj.value1: %!T", (duk_tval *) &heap->lj.value1));
+	DUK_D(DUK_DPRINT("  lj.value2: %!T", (duk_tval *) &heap->lj.value2));
+	DUK_D(DUK_DPRINT("  lj.iserror: %ld", (long) heap->lj.iserror));
 
-		if (!duk_is_object(ctx, -1)) {
-			duk_pop(ctx);
-			break;
-		}
+	DUK_D(DUK_DPRINT("  handling_error: %ld", (long) heap->handling_error));
 
-		duk_get_prop_stridx(ctx, 0, DUK_STRIDX_LAST_INDEX);
-		DUK_ASSERT(duk_is_number(ctx, -1));
-		this_index = duk_get_int(ctx, -1);
-		duk_pop(ctx);
+	DUK_D(DUK_DPRINT("  heap_thread: %!@O", (duk_heaphdr *) heap->heap_thread));
+	DUK_D(DUK_DPRINT("  curr_thread: %!@O", (duk_heaphdr *) heap->curr_thread));
+	DUK_D(DUK_DPRINT("  heap_object: %!@O", (duk_heaphdr *) heap->heap_object));
 
-		if (this_index == prev_last_index) {
-			this_index++;
-			duk_push_int(ctx, this_index);
-			duk_put_prop_stridx(ctx, 0, DUK_STRIDX_LAST_INDEX);
-		}
-		prev_last_index = this_index;
+	DUK_D(DUK_DPRINT("  call_recursion_depth: %ld", (long) heap->call_recursion_depth));
+	DUK_D(DUK_DPRINT("  call_recursion_limit: %ld", (long) heap->call_recursion_limit));
 
-		duk_get_prop_index(ctx, -1, 0);  /* match string */
-		duk_put_prop_index(ctx, 2, arr_idx);
-		arr_idx++;
-		duk_pop(ctx);  /* res_obj */
-	}
+	DUK_D(DUK_DPRINT("  hash_seed: 0x%08lx", (unsigned long) heap->hash_seed));
+	DUK_D(DUK_DPRINT("  rnd_state: 0x%08lx", (unsigned long) heap->rnd_state));
 
-	if (arr_idx == 0) {
-		duk_push_null(ctx);
-	}
+	duk__dump_strcache(heap);
 
-	return 1;  /* return 'res_arr' or 'null' */
-}
-#else  /* DUK_USE_REGEXP_SUPPORT */
-duk_ret_t duk_bi_string_prototype_match(duk_context *ctx) {
-	DUK_UNREF(ctx);
-	return DUK_RET_UNSUPPORTED_ERROR;
-}
-#endif  /* DUK_USE_REGEXP_SUPPORT */
+	duk__dump_heaphdr_list(heap, heap->heap_allocated, "heap allocated");
 
-duk_ret_t duk_bi_string_prototype_concat(duk_context *ctx) {
-	/* duk_concat() coerces arguments with ToString() in correct order */
-	(void) duk_push_this_coercible_to_string(ctx);
-	duk_insert(ctx, 0);  /* this is relatively expensive */
-	duk_concat(ctx, duk_get_top(ctx));
-	return 1;
-}
+#ifdef DUK_USE_REFERENCE_COUNTING
+	duk__dump_heaphdr_list(heap, heap->refzero_list, "refcounting refzero list");
+#endif
 
-duk_ret_t duk_bi_string_prototype_trim(duk_context *ctx) {
-	DUK_ASSERT_TOP(ctx, 0);
-	(void) duk_push_this_coercible_to_string(ctx);
-	duk_trim(ctx, 0);
-	DUK_ASSERT_TOP(ctx, 1);
-	return 1;
-}
+#ifdef DUK_USE_MARK_AND_SWEEP
+	duk__dump_heaphdr_list(heap, heap->finalize_list, "mark-and-sweep finalize list");
+#endif
 
-duk_ret_t duk_bi_string_prototype_locale_compare(duk_context *ctx) {
-	duk_hstring *h1;
-	duk_hstring *h2;
-	duk_size_t h1_len, h2_len, prefix_len;
-	duk_small_int_t ret = 0;
-	duk_small_int_t rc;
+	duk__dump_stringtable(heap);
 
-	/* The current implementation of localeCompare() is simply a codepoint
-	 * by codepoint comparison, implemented with a simple string compare
-	 * because UTF-8 should preserve codepoint ordering (assuming valid
-	 * shortest UTF-8 encoding).
-	 *
-	 * The specification requires that the return value must be related
-	 * to the sort order: e.g. negative means that 'this' comes before
-	 * 'that' in sort order.  We assume an ascending sort order.
-	 */
+	/* heap->strs: not worth dumping */
+}
+#endif
 
-	/* XXX: could share code with duk_js_ops.c, duk_js_compare_helper */
+#endif  /* DUK_USE_DEBUG */
+#line 1 "duk_debug_vsnprintf.c"
+/*
+ *  Custom formatter for debug printing, allowing Duktape specific data
+ *  structures (such as tagged values and heap objects) to be printed with
+ *  a nice format string.  Because debug printing should not affect execution
+ *  state, formatting here must be independent of execution (see implications
+ *  below) and must not allocate memory.
+ *
+ *  Custom format tags begin with a '%!' to safely distinguish them from
+ *  standard format tags.  The following conversions are supported:
+ *
+ *     %!T    tagged value (duk_tval *)
+ *     %!O    heap object (duk_heaphdr *)
+ *     %!I    decoded bytecode instruction
+ *     %!C    bytecode instruction opcode name (arg is long)
+ *
+ *  Everything is serialized in a JSON-like manner.  The default depth is one
+ *  level, internal prototype is not followed, and internal properties are not
+ *  serialized.  The following modifiers change this behavior:
+ *
+ *     @      print pointers
+ *     #      print binary representations (where applicable)
+ *     d      deep traversal of own properties (not prototype)
+ *     p      follow prototype chain (useless without 'd')
+ *     i      include internal properties (other than prototype)
+ *     x      hexdump buffers
+ *     h      heavy formatting
+ *
+ *  For instance, the following serializes objects recursively, but does not
+ *  follow the prototype chain nor print internal properties: "%!dO".
+ *
+ *  Notes:
+ *
+ *    * Standard snprintf return value semantics seem to vary.  This
+ *      implementation returns the number of bytes it actually wrote
+ *      (excluding the null terminator).  If retval == buffer size,
+ *      output was truncated (except for corner cases).
+ *
+ *    * Output format is intentionally different from Ecmascript
+ *      formatting requirements, as formatting here serves debugging
+ *      of internals.
+ *
+ *    * Depth checking (and updating) is done in each type printer
+ *      separately, to allow them to call each other freely.
+ *
+ *    * Some pathological structures might take ages to print (e.g.
+ *      self recursion with 100 properties pointing to the object
+ *      itself).  To guard against these, each printer also checks
+ *      whether the output buffer is full; if so, early exit.
+ *
+ *    * Reference loops are detected using a loop stack.
+ */
 
-	h1 = duk_push_this_coercible_to_string(ctx);
-	DUK_ASSERT(h1 != NULL);
+/* include removed: duk_internal.h */
 
-	h2 = duk_to_hstring(ctx, 0);
-	DUK_ASSERT(h2 != NULL);
+#ifdef DUK_USE_DEBUG
 
-	h1_len = (duk_size_t) DUK_HSTRING_GET_BYTELEN(h1);
-	h2_len = (duk_size_t) DUK_HSTRING_GET_BYTELEN(h2);
-	prefix_len = (h1_len <= h2_len ? h1_len : h2_len);
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
 
-	/* Zero size compare not an issue with DUK_MEMCMP. */
-	rc = (duk_small_int_t) DUK_MEMCMP((const char *) DUK_HSTRING_GET_DATA(h1),
-	                                  (const char *) DUK_HSTRING_GET_DATA(h2),
-	                                  prefix_len);
+/* list of conversion specifiers that terminate a format tag;
+ * this is unfortunately guesswork.
+ */
+#define DUK__ALLOWED_STANDARD_SPECIFIERS  "diouxXeEfFgGaAcsCSpnm"
 
-	if (rc < 0) {
-		ret = -1;
-		goto done;
-	} else if (rc > 0) {
-		ret = 1;
-		goto done;
-	}
+/* maximum length of standard format tag that we support */
+#define DUK__MAX_FORMAT_TAG_LENGTH  32
 
-	/* prefix matches, lengths matter now */
-	if (h1_len > h2_len) {
-		ret = 1;
-		goto done;
-	} else if (h1_len == h2_len) {
-		DUK_ASSERT(ret == 0);
-		goto done;
-	}
-	ret = -1;
-	goto done;
+/* heapobj recursion depth when deep printing is selected */
+#define DUK__DEEP_DEPTH_LIMIT  8
 
- done:
-	duk_push_int(ctx, (duk_int_t) ret);
-	return 1;
-}
-#line 1 "duk_bi_thread.c"
-/*
- *  Thread builtins
- */
+/* maximum recursion depth for loop detection stacks */
+#define DUK__LOOP_STACK_DEPTH  256
 
-/* include removed: duk_internal.h */
+/* must match bytecode defines now; build autogenerate? */
+DUK_LOCAL const char *duk__bc_optab[64] = {
+	"LDREG",    "STREG",    "LDCONST",  "LDINT",    "LDINTX",   "MPUTOBJ",  "MPUTOBJI", "MPUTARR",  "MPUTARRI", "NEW",
+	"NEWI",     "REGEXP",   "CSREG",    "CSREGI",   "GETVAR",   "PUTVAR",   "DECLVAR",  "DELVAR",   "CSVAR",    "CSVARI",
+	"CLOSURE",  "GETPROP",  "PUTPROP",  "DELPROP",  "CSPROP",   "CSPROPI",  "ADD",      "SUB",      "MUL",      "DIV",
+	"MOD",      "BAND",     "BOR",      "BXOR",     "BASL",     "BLSR",     "BASR",     "EQ",       "NEQ",      "SEQ",
+	"SNEQ",     "GT",       "GE",       "LT",       "LE",       "IF",       "JUMP",     "RETURN",   "CALL",     "CALLI",
+	"TRYCATCH", "EXTRA",    "PREINCR",  "PREDECR",  "POSTINCR", "POSTDECR", "PREINCV",  "PREDECV",  "POSTINCV", "POSTDECV",
+	"PREINCP",  "PREDECP",  "POSTINCP", "POSTDECP"
+};
 
-/*
- *  Constructor
- */
+DUK_LOCAL const char *duk__bc_extraoptab[256] = {
+	"NOP", "INVALID", "LDTHIS", "LDUNDEF", "LDNULL", "LDTRUE", "LDFALSE", "NEWOBJ", "NEWARR", "SETALEN",
+	"TYPEOF", "TYPEOFID", "INITENUM", "NEXTENUM", "INITSET", "INITSETI", "INITGET", "INITGETI", "ENDTRY", "ENDCATCH",
+	"ENDFIN", "THROW", "INVLHS", "UNM", "UNP", "DEBUGGER", "BREAK", "CONTINUE", "BNOT", "LNOT",
+	"INSTOF", "IN", "LABEL", "ENDLABEL", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX",
+	"XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX",
 
-duk_ret_t duk_bi_thread_constructor(duk_context *ctx) {
-	duk_hthread *new_thr;
-	duk_hobject *func;
+	"XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX",
+	"XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX",
+	"XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX",
+	"XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX",
+	"XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX",
 
-	if (!duk_is_callable(ctx, 0)) {
-		return DUK_RET_TYPE_ERROR;
-	}
-	func = duk_get_hobject(ctx, 0);
-	DUK_ASSERT(func != NULL);
+	"XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX",
+	"XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX",
+	"XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX",
+	"XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX",
+	"XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX",
 
-	duk_push_thread(ctx);
-	new_thr = (duk_hthread *) duk_get_hobject(ctx, -1);
-	DUK_ASSERT(new_thr != NULL);
-	new_thr->state = DUK_HTHREAD_STATE_INACTIVE;
+	"XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX",
+	"XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX",
+	"XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX",
+	"XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX",
+	"XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX",
 
-	/* push initial function call to new thread stack; this is
-	 * picked up by resume().
-	 */
-	duk_push_hobject((duk_context *) new_thr, func);
+	"XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX",
+	"XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX",
+	"XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX",
+	"XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX",
+	"XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX",
 
-	return 1;  /* return thread */
-}
+	"XXX", "XXX", "XXX", "XXX", "XXX", "XXX"
+};
 
-/*
- *  Resume a thread.
- *
- *  The thread must be in resumable state, either (a) new thread which hasn't
- *  yet started, or (b) a thread which has previously yielded.  This method
- *  must be called from an Ecmascript function.
- *
- *  Args:
- *    - thread
- *    - value
- *    - isError (defaults to false)
- *
- *  Note: yield and resume handling is currently asymmetric.
- */
+typedef struct duk__dprint_state duk__dprint_state;
+struct duk__dprint_state {
+	duk_fixedbuffer *fb;
 
-duk_ret_t duk_bi_thread_resume(duk_context *ctx) {
-	duk_hthread *thr = (duk_hthread *) ctx;
-	duk_hthread *thr_resume;
-	duk_tval tv_tmp;
-	duk_tval *tv;
-	duk_hobject *func;
-	duk_small_int_t is_error;
+	/* loop_stack_index could be perhaps be replaced by 'depth', but it's nice
+	 * to not couple these two mechanisms unnecessarily.
+	 */
+	duk_hobject *loop_stack[DUK__LOOP_STACK_DEPTH];
+	duk_int_t loop_stack_index;
+	duk_int_t loop_stack_limit;
 
-	DUK_DDD(DUK_DDDPRINT("Duktape.Thread.resume(): thread=%!T, value=%!T, is_error=%!T",
-	                     (duk_tval *) duk_get_tval(ctx, 0),
-	                     (duk_tval *) duk_get_tval(ctx, 1),
-	                     (duk_tval *) duk_get_tval(ctx, 2)));
+	duk_int_t depth;
+	duk_int_t depth_limit;
 
-	DUK_ASSERT(thr->state == DUK_HTHREAD_STATE_RUNNING);
-	DUK_ASSERT(thr->heap->curr_thread == thr);
+	duk_bool_t pointer;
+	duk_bool_t heavy;
+	duk_bool_t binary;
+	duk_bool_t follow_proto;
+	duk_bool_t internal;
+	duk_bool_t hexdump;
+};
 
-	thr_resume = duk_require_hthread(ctx, 0);
-	is_error = (duk_small_int_t) duk_to_boolean(ctx, 2);
-	duk_set_top(ctx, 2);
+/* helpers */
+DUK_LOCAL_DECL void duk__print_hstring(duk__dprint_state *st, duk_hstring *k, duk_bool_t quotes);
+DUK_LOCAL_DECL void duk__print_hobject(duk__dprint_state *st, duk_hobject *h);
+DUK_LOCAL_DECL void duk__print_hbuffer(duk__dprint_state *st, duk_hbuffer *h);
+DUK_LOCAL_DECL void duk__print_tval(duk__dprint_state *st, duk_tval *tv);
+DUK_LOCAL_DECL void duk__print_instr(duk__dprint_state *st, duk_instr_t ins);
+DUK_LOCAL_DECL void duk__print_heaphdr(duk__dprint_state *st, duk_heaphdr *h);
+DUK_LOCAL_DECL void duk__print_shared_heaphdr(duk__dprint_state *st, duk_heaphdr *h);
+DUK_LOCAL_DECL void duk__print_shared_heaphdr_string(duk__dprint_state *st, duk_heaphdr_string *h);
+
+DUK_LOCAL void duk__print_shared_heaphdr(duk__dprint_state *st, duk_heaphdr *h) {
+	duk_fixedbuffer *fb = st->fb;
 
-	/* [ thread value ] */
+	if (st->heavy) {
+		duk_fb_sprintf(fb, "(%p)", (void *) h);
+	}
 
-	/*
-	 *  Thread state and calling context checks
-	 */
+	if (!h) {
+		return;
+	}
 
-	if (thr->callstack_top < 2) {
-		DUK_DD(DUK_DDPRINT("resume state invalid: callstack should contain at least 2 entries (caller and Duktape.Thread.resume)"));
-		goto state_error;
+	if (st->binary) {
+		duk_size_t i;
+		duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_LBRACKET);
+		for (i = 0; i < (duk_size_t) sizeof(*h); i++) {
+			duk_fb_sprintf(fb, "%02lx", (unsigned long) ((duk_uint8_t *)h)[i]);
+		}
+		duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_RBRACKET);
 	}
-	DUK_ASSERT((thr->callstack + thr->callstack_top - 1)->func != NULL);  /* us */
-	DUK_ASSERT(DUK_HOBJECT_IS_NATIVEFUNCTION((thr->callstack + thr->callstack_top - 1)->func));
-	DUK_ASSERT((thr->callstack + thr->callstack_top - 2)->func != NULL);  /* caller */
 
-	if (!DUK_HOBJECT_IS_COMPILEDFUNCTION((thr->callstack + thr->callstack_top - 2)->func)) {
-		DUK_DD(DUK_DDPRINT("resume state invalid: caller must be Ecmascript code"));
-		goto state_error;
+#ifdef DUK_USE_REFERENCE_COUNTING  /* currently implicitly also DUK_USE_DOUBLE_LINKED_HEAP */
+	if (st->heavy) {
+		duk_fb_sprintf(fb, "[h_next=%p,h_prev=%p,h_refcount=%lu,h_flags=%08lx,type=%ld,"
+		               "reachable=%ld,temproot=%ld,finalizable=%ld,finalized=%ld]",
+		               (void *) DUK_HEAPHDR_GET_NEXT(NULL, h),
+		               (void *) DUK_HEAPHDR_GET_PREV(NULL, h),
+		               (unsigned long) DUK_HEAPHDR_GET_REFCOUNT(h),
+		               (unsigned long) DUK_HEAPHDR_GET_FLAGS(h),
+		               (long) DUK_HEAPHDR_GET_TYPE(h),
+		               (long) (DUK_HEAPHDR_HAS_REACHABLE(h) ? 1 : 0),
+		               (long) (DUK_HEAPHDR_HAS_TEMPROOT(h) ? 1 : 0),
+		               (long) (DUK_HEAPHDR_HAS_FINALIZABLE(h) ? 1 : 0),
+		               (long) (DUK_HEAPHDR_HAS_FINALIZED(h) ? 1 : 0));
+	}
+#else
+	if (st->heavy) {
+		duk_fb_sprintf(fb, "[h_next=%p,h_flags=%08lx,type=%ld,reachable=%ld,temproot=%ld,finalizable=%ld,finalized=%ld]",
+		               (void *) DUK_HEAPHDR_GET_NEXT(NULL, h),
+		               (unsigned long) DUK_HEAPHDR_GET_FLAGS(h),
+		               (long) DUK_HEAPHDR_GET_TYPE(h),
+		               (long) (DUK_HEAPHDR_HAS_REACHABLE(h) ? 1 : 0),
+		               (long) (DUK_HEAPHDR_HAS_TEMPROOT(h) ? 1 : 0),
+		               (long) (DUK_HEAPHDR_HAS_FINALIZABLE(h) ? 1 : 0),
+		               (long) (DUK_HEAPHDR_HAS_FINALIZED(h) ? 1 : 0));
 	}
+#endif
+}
 
-	/* Note: there is no requirement that: 'thr->callstack_preventcount == 1'
-	 * like for yield.
-	 */
+DUK_LOCAL void duk__print_shared_heaphdr_string(duk__dprint_state *st, duk_heaphdr_string *h) {
+	duk_fixedbuffer *fb = st->fb;
 
-	if (thr_resume->state != DUK_HTHREAD_STATE_INACTIVE &&
-	    thr_resume->state != DUK_HTHREAD_STATE_YIELDED) {
-		DUK_DD(DUK_DDPRINT("resume state invalid: target thread must be INACTIVE or YIELDED"));
-		goto state_error;
+	if (st->heavy) {
+		duk_fb_sprintf(fb, "(%p)", (void *) h);
 	}
 
-	DUK_ASSERT(thr_resume->state == DUK_HTHREAD_STATE_INACTIVE ||
-	           thr_resume->state == DUK_HTHREAD_STATE_YIELDED);
-
-	/* Further state-dependent pre-checks */
-
-	if (thr_resume->state == DUK_HTHREAD_STATE_YIELDED) {
-		/* no pre-checks now, assume a previous yield() has left things in
-		 * tip-top shape (longjmp handler will assert for these).
-		 */
-	} else {
-		DUK_ASSERT(thr_resume->state == DUK_HTHREAD_STATE_INACTIVE);
+	if (!h) {
+		return;
+	}
 
-		if ((thr_resume->callstack_top != 0) ||
-		    (thr_resume->valstack_top - thr_resume->valstack != 1)) {
-			goto state_invalid_initial;
-		}
-		tv = &thr_resume->valstack_top[-1];
-		DUK_ASSERT(tv >= thr_resume->valstack && tv < thr_resume->valstack_top);
-		if (!DUK_TVAL_IS_OBJECT(tv)) {
-			goto state_invalid_initial;
-		}
-		func = DUK_TVAL_GET_OBJECT(tv);
-		DUK_ASSERT(func != NULL);
-		if (!DUK_HOBJECT_IS_COMPILEDFUNCTION(func)) {
-			/* Note: cannot be a bound function either right now,
-			 * this would be easy to relax though.
-			 */
-			goto state_invalid_initial;
+	if (st->binary) {
+		duk_size_t i;
+		duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_LBRACKET);
+		for (i = 0; i < (duk_size_t) sizeof(*h); i++) {
+			duk_fb_sprintf(fb, "%02lx", (unsigned long) ((duk_uint8_t *)h)[i]);
 		}
-
+		duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_RBRACKET);
 	}
 
-	/*
-	 *  The error object has been augmented with a traceback and other
-	 *  info from its creation point -- usually another thread.  The
-	 *  error handler is called here right before throwing, but it also
-	 *  runs in the resumer's thread.  It might be nice to get a traceback
-	 *  from the resumee but this is not the case now.
-	 */
-
-#if defined(DUK_USE_AUGMENT_ERROR_THROW)
-	if (is_error) {
-		DUK_ASSERT_TOP(ctx, 2);  /* value (error) is at stack top */
-		duk_err_augment_error_throw(thr);  /* in resumer's context */
+#ifdef DUK_USE_REFERENCE_COUNTING
+	if (st->heavy) {
+		duk_fb_sprintf(fb, "[h_refcount=%lu,h_flags=%08lx,type=%ld,reachable=%ld,temproot=%ld,finalizable=%ld,finalized=%ld]",
+		               (unsigned long) DUK_HEAPHDR_GET_REFCOUNT((duk_heaphdr *) h),
+		               (unsigned long) DUK_HEAPHDR_GET_FLAGS((duk_heaphdr *) h),
+		               (long) DUK_HEAPHDR_GET_TYPE((duk_heaphdr *) h),
+		               (long) (DUK_HEAPHDR_HAS_REACHABLE((duk_heaphdr *) h) ? 1 : 0),
+		               (long) (DUK_HEAPHDR_HAS_TEMPROOT((duk_heaphdr *) h) ? 1 : 0),
+		               (long) (DUK_HEAPHDR_HAS_FINALIZABLE((duk_heaphdr *) h) ? 1 : 0),
+		               (long) (DUK_HEAPHDR_HAS_FINALIZED((duk_heaphdr *) h) ? 1 : 0));
 	}
-#endif
-
-#ifdef DUK_USE_DEBUG
-	if (is_error) {
-		DUK_DDD(DUK_DDDPRINT("RESUME ERROR: thread=%!T, value=%!T",
-		                     (duk_tval *) duk_get_tval(ctx, 0),
-		                     (duk_tval *) duk_get_tval(ctx, 1)));
-	} else if (thr_resume->state == DUK_HTHREAD_STATE_YIELDED) {
-		DUK_DDD(DUK_DDDPRINT("RESUME NORMAL: thread=%!T, value=%!T",
-		                     (duk_tval *) duk_get_tval(ctx, 0),
-		                     (duk_tval *) duk_get_tval(ctx, 1)));
-	} else {
-		DUK_DDD(DUK_DDDPRINT("RESUME INITIAL: thread=%!T, value=%!T",
-		                     (duk_tval *) duk_get_tval(ctx, 0),
-		                     (duk_tval *) duk_get_tval(ctx, 1)));
+#else
+	if (st->heavy) {
+		duk_fb_sprintf(fb, "[h_flags=%08lx,type=%ld,reachable=%ld,temproot=%ld,finalizable=%ld,finalized=%ld]",
+		               (unsigned long) DUK_HEAPHDR_GET_FLAGS((duk_heaphdr *) h),
+		               (long) DUK_HEAPHDR_GET_TYPE((duk_heaphdr *) h),
+		               (long) (DUK_HEAPHDR_HAS_REACHABLE((duk_heaphdr *) h) ? 1 : 0),
+		               (long) (DUK_HEAPHDR_HAS_TEMPROOT((duk_heaphdr *) h) ? 1 : 0),
+		               (long) (DUK_HEAPHDR_HAS_FINALIZABLE((duk_heaphdr *) h) ? 1 : 0),
+		               (long) (DUK_HEAPHDR_HAS_FINALIZED((duk_heaphdr *) h) ? 1 : 0));
 	}
 #endif
+}
 
-	thr->heap->lj.type = DUK_LJ_TYPE_RESUME;
+DUK_LOCAL void duk__print_hstring(duk__dprint_state *st, duk_hstring *h, duk_bool_t quotes) {
+	duk_fixedbuffer *fb = st->fb;
+	const duk_uint8_t *p;
+	const duk_uint8_t *p_end;
 
-	/* lj value2: thread */
-	DUK_ASSERT(thr->valstack_bottom < thr->valstack_top);
-	DUK_TVAL_SET_TVAL(&tv_tmp, &thr->heap->lj.value2);
-	DUK_TVAL_SET_TVAL(&thr->heap->lj.value2, &thr->valstack_bottom[0]);
-	DUK_TVAL_INCREF(thr, &thr->heap->lj.value2);
-	DUK_TVAL_DECREF(thr, &tv_tmp);
+	/* terminal type: no depth check */
 
-	/* lj value1: value */
-	DUK_ASSERT(thr->valstack_bottom + 1 < thr->valstack_top);
-	DUK_TVAL_SET_TVAL(&tv_tmp, &thr->heap->lj.value1);
-	DUK_TVAL_SET_TVAL(&thr->heap->lj.value1, &thr->valstack_bottom[1]);
-	DUK_TVAL_INCREF(thr, &thr->heap->lj.value1);
-	DUK_TVAL_DECREF(thr, &tv_tmp);
+	if (duk_fb_is_full(fb)) {
+		return;
+	}
 
-	thr->heap->lj.iserror = is_error;
+	duk__print_shared_heaphdr_string(st, &h->hdr);
 
-	DUK_ASSERT(thr->heap->lj.jmpbuf_ptr != NULL);  /* call is from executor, so we know we have a jmpbuf */
-	duk_err_longjmp(thr);  /* execution resumes in bytecode executor */
-	return 0;  /* never here */
+	if (!h) {
+		duk_fb_put_cstring(fb, "NULL");
+		return;
+	}
 
- state_invalid_initial:
-	DUK_ERROR(thr, DUK_ERR_TYPE_ERROR, "invalid initial thread state/stack");
-	return 0;  /* never here */
+	p = DUK_HSTRING_GET_DATA(h);
+	p_end = p + DUK_HSTRING_GET_BYTELEN(h);
 
- state_error:
-	DUK_ERROR(thr, DUK_ERR_TYPE_ERROR, "invalid state for resume");
-	return 0;  /* never here */
-}
+	if (p_end > p && p[0] == DUK_ASC_UNDERSCORE) {
+		/* if property key begins with underscore, encode it with
+		 * forced quotes (e.g. "_Foo") to distinguish it from encoded
+		 * internal properties (e.g. \xffBar -> _Bar).
+		 */
+		quotes = 1;
+	}
 
-/*
- *  Yield the current thread.
- *
- *  The thread must be in yieldable state: it must have a resumer, and there
- *  must not be any yield-preventing calls (native calls and constructor calls,
- *  currently) in the thread's call stack (otherwise a resume would not be
- *  possible later).  This method must be called from an Ecmascript function.
- *
- *  Args:
- *    - value
- *    - isError (defaults to false)
- *
- *  Note: yield and resume handling is currently asymmetric.
- */
+	if (quotes) {
+		duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_DOUBLEQUOTE);
+	}
+	while (p < p_end) {
+		duk_uint8_t ch = *p++;
 
-duk_ret_t duk_bi_thread_yield(duk_context *ctx) {
-	duk_hthread *thr = (duk_hthread *) ctx;
-	duk_tval tv_tmp;
-	duk_small_int_t is_error;
+		/* two special escapes: '\' and '"', other printables as is */
+		if (ch == '\\') {
+			duk_fb_sprintf(fb, "\\\\");
+		} else if (ch == '"') {
+			duk_fb_sprintf(fb, "\\\"");
+		} else if (ch >= 0x20 && ch <= 0x7e) {
+			duk_fb_put_byte(fb, ch);
+		} else if (ch == 0xff && !quotes) {
+			/* encode \xffBar as _Bar if no quotes are applied, this is for
+			 * readable internal keys.
+			 */
+			duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_UNDERSCORE);
+		} else {
+			duk_fb_sprintf(fb, "\\x%02lx", (unsigned long) ch);
+		}
+	}
+	if (quotes) {
+		duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_DOUBLEQUOTE);
+	}
+#ifdef DUK_USE_REFERENCE_COUNTING
+	/* XXX: limit to quoted strings only, to save keys from being cluttered? */
+	duk_fb_sprintf(fb, "/%lu", (unsigned long) DUK_HEAPHDR_GET_REFCOUNT(&h->hdr));
+#endif
+}
 
-	DUK_DDD(DUK_DDDPRINT("Duktape.Thread.yield(): value=%!T, is_error=%!T",
-	                     (duk_tval *) duk_get_tval(ctx, 0),
-	                     (duk_tval *) duk_get_tval(ctx, 1)));
+#ifdef DUK__COMMA
+#undef DUK__COMMA
+#endif
+#define DUK__COMMA()  do { \
+		if (first) { \
+			first = 0; \
+		} else { \
+			duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_COMMA); \
+		} \
+	} while (0)
 
-	DUK_ASSERT(thr->state == DUK_HTHREAD_STATE_RUNNING);
-	DUK_ASSERT(thr->heap->curr_thread == thr);
+DUK_LOCAL void duk__print_hobject(duk__dprint_state *st, duk_hobject *h) {
+	duk_fixedbuffer *fb = st->fb;
+	duk_uint_fast32_t i;
+	duk_tval *tv;
+	duk_hstring *key;
+	duk_bool_t first = 1;
+	const char *brace1 = "{";
+	const char *brace2 = "}";
+	duk_bool_t pushed_loopstack = 0;
 
-	is_error = (duk_small_int_t) duk_to_boolean(ctx, 1);
-	duk_set_top(ctx, 1);
+	if (duk_fb_is_full(fb)) {
+		return;
+	}
 
-	/* [ value ] */
+	duk__print_shared_heaphdr(st, &h->hdr);
 
-	/*
-	 *  Thread state and calling context checks
-	 */
+	if (h && DUK_HOBJECT_HAS_ARRAY_PART(h)) {
+		brace1 = "[";
+		brace2 = "]";
+	}
 
-	if (!thr->resumer) {
-		DUK_DD(DUK_DDPRINT("yield state invalid: current thread must have a resumer"));
-		goto state_error;
+	if (!h) {
+		duk_fb_put_cstring(fb, "NULL");
+		goto finished;
 	}
-	DUK_ASSERT(thr->resumer->state == DUK_HTHREAD_STATE_RESUMED);
 
-	if (thr->callstack_top < 2) {
-		DUK_DD(DUK_DDPRINT("yield state invalid: callstack should contain at least 2 entries (caller and Duktape.Thread.yield)"));
-		goto state_error;
+	if (st->depth >= st->depth_limit) {
+		if (DUK_HOBJECT_IS_COMPILEDFUNCTION(h)) {
+			duk_fb_sprintf(fb, "%sobject/compiledfunction %p%s", (const char *) brace1, (void *) h, (const char *) brace2);
+		} else if (DUK_HOBJECT_IS_NATIVEFUNCTION(h)) {
+			duk_fb_sprintf(fb, "%sobject/nativefunction %p%s", (const char *) brace1, (void *) h, (const char *) brace2);
+		} else if (DUK_HOBJECT_IS_THREAD(h)) {
+			duk_fb_sprintf(fb, "%sobject/thread %p%s", (const char *) brace1, (void *) h, (const char *) brace2);
+		} else {
+			duk_fb_sprintf(fb, "%sobject %p%s", (const char *) brace1, (void *) h, (const char *) brace2);  /* may be NULL */
+		}
+		return;
 	}
-	DUK_ASSERT((thr->callstack + thr->callstack_top - 1)->func != NULL);  /* us */
-	DUK_ASSERT(DUK_HOBJECT_IS_NATIVEFUNCTION((thr->callstack + thr->callstack_top - 1)->func));
-	DUK_ASSERT((thr->callstack + thr->callstack_top - 2)->func != NULL);  /* caller */
 
-	if (!DUK_HOBJECT_IS_COMPILEDFUNCTION((thr->callstack + thr->callstack_top - 2)->func)) {
-		DUK_DD(DUK_DDPRINT("yield state invalid: caller must be Ecmascript code"));
-		goto state_error;
+	for (i = 0; i < (duk_uint_fast32_t) st->loop_stack_index; i++) {
+		if (st->loop_stack[i] == h) {
+			duk_fb_sprintf(fb, "%sLOOP:%p%s", (const char *) brace1, (void *) h, (const char *) brace2);
+			return;
+		}
 	}
 
-	DUK_ASSERT(thr->callstack_preventcount >= 1);  /* should never be zero, because we (Duktape.Thread.yield) are on the stack */
-	if (thr->callstack_preventcount != 1) {
-		/* Note: the only yield-preventing call is Duktape.Thread.yield(), hence check for 1, not 0 */
-		DUK_DD(DUK_DDPRINT("yield state invalid: there must be no yield-preventing calls in current thread callstack (preventcount is %ld)",
-		                   (long) thr->callstack_preventcount));
-		goto state_error;
+	/* after this, return paths should 'goto finished' for decrement */
+	st->depth++;
+
+	if (st->loop_stack_index >= st->loop_stack_limit) {
+		duk_fb_sprintf(fb, "%sOUT-OF-LOOP-STACK%s", (const char *) brace1, (const char *) brace2);
+		goto finished;
 	}
+	st->loop_stack[st->loop_stack_index++] = h;
+	pushed_loopstack = 1;
 
 	/*
-	 *  The error object has been augmented with a traceback and other
-	 *  info from its creation point -- usually the current thread.
-	 *  The error handler, however, is called right before throwing
-	 *  and runs in the yielder's thread.
+	 *  Notation: double underscore used for internal properties which are not
+	 *  stored in the property allocation (e.g. '__valstack').
 	 */
 
-#if defined(DUK_USE_AUGMENT_ERROR_THROW)
-	if (is_error) {
-		DUK_ASSERT_TOP(ctx, 1);  /* value (error) is at stack top */
-		duk_err_augment_error_throw(thr);  /* in yielder's context */
+	duk_fb_put_cstring(fb, brace1);
+
+	if (DUK_HOBJECT_GET_PROPS(NULL, h)) {
+		duk_uint32_t a_limit;
+
+		a_limit = DUK_HOBJECT_GET_ASIZE(h);
+		if (st->internal) {
+			/* dump all allocated entries, unused entries print as 'unused',
+			 * note that these may extend beyond current 'length' and look
+			 * a bit funny.
+			 */
+		} else {
+			/* leave out trailing 'unused' elements */
+			while (a_limit > 0) {
+				tv = DUK_HOBJECT_A_GET_VALUE_PTR(NULL, h, a_limit - 1);
+				if (!DUK_TVAL_IS_UNUSED(tv)) {
+					break;
+				}
+				a_limit--;
+			}
+		}
+
+		for (i = 0; i < a_limit; i++) {
+			tv = DUK_HOBJECT_A_GET_VALUE_PTR(NULL, h, i);
+			DUK__COMMA();
+			duk__print_tval(st, tv);
+		}
+		for (i = 0; i < DUK_HOBJECT_GET_ENEXT(h); i++) {
+			key = DUK_HOBJECT_E_GET_KEY(NULL, h, i);
+			if (!key) {
+				continue;
+			}
+			if (!st->internal &&
+			    DUK_HSTRING_GET_BYTELEN(key) > 0 &&
+			    DUK_HSTRING_GET_DATA(key)[0] == 0xff) {
+				/* XXX: use DUK_HSTRING_FLAG_INTERNAL? */
+				continue;
+			}
+			DUK__COMMA();
+			duk__print_hstring(st, key, 0);
+			duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_COLON);
+			if (DUK_HOBJECT_E_SLOT_IS_ACCESSOR(NULL, h, i)) {
+				duk_fb_sprintf(fb, "[get:%p,set:%p]",
+				               (void *) DUK_HOBJECT_E_GET_VALUE(NULL, h, i).a.get,
+				               (void *) DUK_HOBJECT_E_GET_VALUE(NULL, h, i).a.set);
+			} else {
+				tv = &DUK_HOBJECT_E_GET_VALUE(NULL, h, i).v;
+				duk__print_tval(st, tv);
+			}
+			if (st->heavy) {
+				duk_fb_sprintf(fb, "<%02lx>", (unsigned long) DUK_HOBJECT_E_GET_FLAGS(NULL, h, i));
+			}
+		}
+	}
+	if (st->internal) {
+		if (DUK_HOBJECT_HAS_EXTENSIBLE(h)) {
+			DUK__COMMA(); duk_fb_sprintf(fb, "__extensible:true");
+		} else {
+			;
+		}
+		if (DUK_HOBJECT_HAS_CONSTRUCTABLE(h)) {
+			DUK__COMMA(); duk_fb_sprintf(fb, "__constructable:true");
+		} else {
+			;
+		}
+		if (DUK_HOBJECT_HAS_BOUND(h)) {
+			DUK__COMMA(); duk_fb_sprintf(fb, "__bound:true");
+		} else {
+			;
+		}
+		if (DUK_HOBJECT_HAS_COMPILEDFUNCTION(h)) {
+			DUK__COMMA(); duk_fb_sprintf(fb, "__compiledfunction:true");
+		} else {
+			;
+		}
+		if (DUK_HOBJECT_HAS_NATIVEFUNCTION(h)) {
+			DUK__COMMA(); duk_fb_sprintf(fb, "__nativefunction:true");
+		} else {
+			;
+		}
+		if (DUK_HOBJECT_HAS_THREAD(h)) {
+			DUK__COMMA(); duk_fb_sprintf(fb, "__thread:true");
+		} else {
+			;
+		}
+		if (DUK_HOBJECT_HAS_ARRAY_PART(h)) {
+			DUK__COMMA(); duk_fb_sprintf(fb, "__array_part:true");
+		} else {
+			;
+		}
+		if (DUK_HOBJECT_HAS_STRICT(h)) {
+			DUK__COMMA(); duk_fb_sprintf(fb, "__strict:true");
+		} else {
+			;
+		}
+		if (DUK_HOBJECT_HAS_NEWENV(h)) {
+			DUK__COMMA(); duk_fb_sprintf(fb, "__newenv:true");
+		} else {
+			;
+		}
+		if (DUK_HOBJECT_HAS_NAMEBINDING(h)) {
+			DUK__COMMA(); duk_fb_sprintf(fb, "__namebinding:true");
+		} else {
+			;
+		}
+		if (DUK_HOBJECT_HAS_CREATEARGS(h)) {
+			DUK__COMMA(); duk_fb_sprintf(fb, "__createargs:true");
+		} else {
+			;
+		}
+		if (DUK_HOBJECT_HAS_ENVRECCLOSED(h)) {
+			DUK__COMMA(); duk_fb_sprintf(fb, "__envrecclosed:true");
+		} else {
+			;
+		}
+		if (DUK_HOBJECT_HAS_EXOTIC_ARRAY(h)) {
+			DUK__COMMA(); duk_fb_sprintf(fb, "__special_array:true");
+		} else {
+			;
+		}
+		if (DUK_HOBJECT_HAS_EXOTIC_STRINGOBJ(h)) {
+			DUK__COMMA(); duk_fb_sprintf(fb, "__special_stringobj:true");
+		} else {
+			;
+		}
+		if (DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(h)) {
+			DUK__COMMA(); duk_fb_sprintf(fb, "__special_arguments:true");
+		} else {
+			;
+		}
+		if (DUK_HOBJECT_HAS_EXOTIC_DUKFUNC(h)) {
+			DUK__COMMA(); duk_fb_sprintf(fb, "__special_dukfunc:true");
+		} else {
+			;
+		}
+		if (DUK_HOBJECT_IS_BUFFEROBJECT(h)) {
+			DUK__COMMA(); duk_fb_sprintf(fb, "__special_bufferobj:true");
+		} else {
+			;
+		}
+		if (DUK_HOBJECT_HAS_EXOTIC_PROXYOBJ(h)) {
+			DUK__COMMA(); duk_fb_sprintf(fb, "__special_proxyobj:true");
+		} else {
+			;
+		}
 	}
+	if (st->internal && DUK_HOBJECT_IS_COMPILEDFUNCTION(h)) {
+		duk_hcompiledfunction *f = (duk_hcompiledfunction *) h;
+		DUK__COMMA(); duk_fb_put_cstring(fb, "__data:");
+		duk__print_hbuffer(st, (duk_hbuffer *) DUK_HCOMPILEDFUNCTION_GET_DATA(NULL, f));
+		DUK__COMMA(); duk_fb_sprintf(fb, "__nregs:%ld", (long) f->nregs);
+		DUK__COMMA(); duk_fb_sprintf(fb, "__nargs:%ld", (long) f->nargs);
+#if defined(DUK_USE_DEBUGGER_SUPPORT)
+		DUK__COMMA(); duk_fb_sprintf(fb, "__start_line:%ld", (long) f->start_line);
+		DUK__COMMA(); duk_fb_sprintf(fb, "__end_line:%ld", (long) f->end_line);
 #endif
+		DUK__COMMA(); duk_fb_put_cstring(fb, "__data:");
+		duk__print_hbuffer(st, (duk_hbuffer *) DUK_HCOMPILEDFUNCTION_GET_DATA(NULL, f));
+	} else if (st->internal && DUK_HOBJECT_IS_NATIVEFUNCTION(h)) {
+		duk_hnativefunction *f = (duk_hnativefunction *) h;
+		DUK__COMMA(); duk_fb_sprintf(fb, "__func:");
+		duk_fb_put_funcptr(fb, (duk_uint8_t *) &f->func, sizeof(f->func));
+		DUK__COMMA(); duk_fb_sprintf(fb, "__nargs:%ld", (long) f->nargs);
+	} else if (st->internal && DUK_HOBJECT_IS_BUFFEROBJECT(h)) {
+		duk_hbufferobject *b = (duk_hbufferobject *) h;
+		DUK__COMMA(); duk_fb_sprintf(fb, "__buf:");
+		duk__print_hbuffer(st, (duk_hbuffer *) b->buf);
+		DUK__COMMA(); duk_fb_sprintf(fb, "__offset:%ld", (long) b->offset);
+		DUK__COMMA(); duk_fb_sprintf(fb, "__length:%ld", (long) b->length);
+		DUK__COMMA(); duk_fb_sprintf(fb, "__shift:%ld", (long) b->shift);
+		DUK__COMMA(); duk_fb_sprintf(fb, "__elemtype:%ld", (long) b->elem_type);
+	} else if (st->internal && DUK_HOBJECT_IS_THREAD(h)) {
+		duk_hthread *t = (duk_hthread *) h;
+		DUK__COMMA(); duk_fb_sprintf(fb, "__strict:%ld", (long) t->strict);
+		DUK__COMMA(); duk_fb_sprintf(fb, "__state:%ld", (long) t->state);
+		DUK__COMMA(); duk_fb_sprintf(fb, "__unused1:%ld", (long) t->unused1);
+		DUK__COMMA(); duk_fb_sprintf(fb, "__unused2:%ld", (long) t->unused2);
+		DUK__COMMA(); duk_fb_sprintf(fb, "__valstack_max:%ld", (long) t->valstack_max);
+		DUK__COMMA(); duk_fb_sprintf(fb, "__callstack_max:%ld", (long) t->callstack_max);
+		DUK__COMMA(); duk_fb_sprintf(fb, "__catchstack_max:%ld", (long) t->catchstack_max);
+		DUK__COMMA(); duk_fb_sprintf(fb, "__valstack:%p", (void *) t->valstack);
+		DUK__COMMA(); duk_fb_sprintf(fb, "__valstack_end:%p/%ld", (void *) t->valstack_end, (long) (t->valstack_end - t->valstack));
+		DUK__COMMA(); duk_fb_sprintf(fb, "__valstack_bottom:%p/%ld", (void *) t->valstack_bottom, (long) (t->valstack_bottom - t->valstack));
+		DUK__COMMA(); duk_fb_sprintf(fb, "__valstack_top:%p/%ld", (void *) t->valstack_top, (long) (t->valstack_top - t->valstack));
+		DUK__COMMA(); duk_fb_sprintf(fb, "__catchstack:%p", (void *) t->catchstack);
+		DUK__COMMA(); duk_fb_sprintf(fb, "__catchstack_size:%ld", (long) t->catchstack_size);
+		DUK__COMMA(); duk_fb_sprintf(fb, "__catchstack_top:%ld", (long) t->catchstack_top);
+		DUK__COMMA(); duk_fb_sprintf(fb, "__resumer:"); duk__print_hobject(st, (duk_hobject *) t->resumer);
+		/* XXX: print built-ins array? */
 
-#ifdef DUK_USE_DEBUG
-	if (is_error) {
-		DUK_DDD(DUK_DDDPRINT("YIELD ERROR: value=%!T",
-		                     (duk_tval *) duk_get_tval(ctx, 0)));
-	} else {
-		DUK_DDD(DUK_DDDPRINT("YIELD NORMAL: value=%!T",
-		                     (duk_tval *) duk_get_tval(ctx, 0)));
+	}
+#ifdef DUK_USE_REFERENCE_COUNTING
+	if (st->internal) {
+		DUK__COMMA(); duk_fb_sprintf(fb, "__refcount:%lu", (unsigned long) DUK_HEAPHDR_GET_REFCOUNT((duk_heaphdr *) h));
 	}
 #endif
+	if (st->internal) {
+		DUK__COMMA(); duk_fb_sprintf(fb, "__class:%ld", (long) DUK_HOBJECT_GET_CLASS_NUMBER(h));
+	}
 
-	/*
-	 *  Process yield
-	 *
-	 *  After longjmp(), processing continues in bytecode executor longjmp
-	 *  handler, which will e.g. update thr->resumer to NULL.
-	 */
+	/* prototype should be last, for readability */
+	if (st->follow_proto && DUK_HOBJECT_GET_PROTOTYPE(NULL, h)) {
+		DUK__COMMA(); duk_fb_put_cstring(fb, "__prototype:"); duk__print_hobject(st, DUK_HOBJECT_GET_PROTOTYPE(NULL, h));
+	}
 
-	thr->heap->lj.type = DUK_LJ_TYPE_YIELD;
+	duk_fb_put_cstring(fb, brace2);
 
-	/* lj value1: value */
-	DUK_ASSERT(thr->valstack_bottom < thr->valstack_top);
-	DUK_TVAL_SET_TVAL(&tv_tmp, &thr->heap->lj.value1);
-	DUK_TVAL_SET_TVAL(&thr->heap->lj.value1, &thr->valstack_bottom[0]);
-	DUK_TVAL_INCREF(thr, &thr->heap->lj.value1);
-	DUK_TVAL_DECREF(thr, &tv_tmp);
+#if defined(DUK_USE_HOBJECT_HASH_PART)
+	if (st->heavy && DUK_HOBJECT_GET_HSIZE(h) > 0) {
+		duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_LANGLE);
+		for (i = 0; i < DUK_HOBJECT_GET_HSIZE(h); i++) {
+			duk_uint_t h_idx = DUK_HOBJECT_H_GET_INDEX(NULL, h, i);
+			if (i > 0) {
+				duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_COMMA);
+			}
+			if (h_idx == DUK_HOBJECT_HASHIDX_UNUSED) {
+				duk_fb_sprintf(fb, "u");
+			} else if (h_idx == DUK_HOBJECT_HASHIDX_DELETED) {
+				duk_fb_sprintf(fb, "d");
+			} else {
+				duk_fb_sprintf(fb, "%ld", (long) h_idx);
+			}
+		}
+		duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_RANGLE);
+	}
+#endif
 
-	thr->heap->lj.iserror = is_error;
+ finished:
+	st->depth--;
+	if (pushed_loopstack) {
+		st->loop_stack_index--;
+		st->loop_stack[st->loop_stack_index] = NULL;
+	}
+}
 
-	DUK_ASSERT(thr->heap->lj.jmpbuf_ptr != NULL);  /* call is from executor, so we know we have a jmpbuf */
-	duk_err_longjmp(thr);  /* execution resumes in bytecode executor */
-	return 0;  /* never here */
+#undef DUK__COMMA
 
- state_error:
-	DUK_ERROR(thr, DUK_ERR_TYPE_ERROR, "invalid state for yield");
-	return 0;  /* never here */
-}
+DUK_LOCAL void duk__print_hbuffer(duk__dprint_state *st, duk_hbuffer *h) {
+	duk_fixedbuffer *fb = st->fb;
+	duk_size_t i, n;
+	duk_uint8_t *p;
 
-duk_ret_t duk_bi_thread_current(duk_context *ctx) {
-	duk_push_current_thread(ctx);
-	return 1;
-}
+	if (duk_fb_is_full(fb)) {
+		return;
+	}
 
-#line 1 "duk_bi_thrower.c"
-/*
- *  Type error thrower, E5 Section 13.2.3.
- */
+	/* terminal type: no depth check */
 
-/* include removed: duk_internal.h */
+	if (!h) {
+		duk_fb_put_cstring(fb, "NULL");
+		return;
+	}
 
-int duk_bi_type_error_thrower(duk_context *ctx) {
-	DUK_UNREF(ctx);
-	return DUK_RET_TYPE_ERROR;
+	if (DUK_HBUFFER_HAS_DYNAMIC(h)) {
+		if (DUK_HBUFFER_HAS_EXTERNAL(h)) {
+			duk_hbuffer_external *g = (duk_hbuffer_external *) h;
+			duk_fb_sprintf(fb, "buffer:external:%p:%ld",
+			               (void *) DUK_HBUFFER_EXTERNAL_GET_DATA_PTR(NULL, g),
+			               (long) DUK_HBUFFER_EXTERNAL_GET_SIZE(g));
+		} else {
+			duk_hbuffer_dynamic *g = (duk_hbuffer_dynamic *) h;
+			duk_fb_sprintf(fb, "buffer:dynamic:%p:%ld",
+			               (void *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(NULL, g),
+			               (long) DUK_HBUFFER_DYNAMIC_GET_SIZE(g));
+		}
+	} else {
+		duk_fb_sprintf(fb, "buffer:fixed:%ld", (long) DUK_HBUFFER_GET_SIZE(h));
+	}
+
+#ifdef DUK_USE_REFERENCE_COUNTING
+	duk_fb_sprintf(fb, "/%lu", (unsigned long) DUK_HEAPHDR_GET_REFCOUNT(&h->hdr));
+#endif
+
+	if (st->hexdump) {
+		duk_fb_sprintf(fb, "=[");
+		n = DUK_HBUFFER_GET_SIZE(h);
+		p = (duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(NULL, h);
+		for (i = 0; i < n; i++) {
+			duk_fb_sprintf(fb, "%02lx", (unsigned long) p[i]);
+		}
+		duk_fb_sprintf(fb, "]");
+	}
 }
-#line 1 "duk_builtins.c"
-/*
- *  Automatically generated by genbuiltins.py, do not edit!
- */
 
-/* include removed: duk_internal.h */
+DUK_LOCAL void duk__print_heaphdr(duk__dprint_state *st, duk_heaphdr *h) {
+	duk_fixedbuffer *fb = st->fb;
 
-#if defined(DUK_USE_DOUBLE_LE)
-const duk_uint8_t duk_strings_data[] = {
-55,86,227,24,145,55,102,120,144,3,63,94,228,54,100,137,186,26,20,164,137,
-186,50,11,164,109,77,215,5,61,35,106,3,25,110,8,22,158,130,38,163,8,217,
-200,158,76,156,210,117,128,153,203,210,70,46,137,187,18,27,164,187,201,209,
-130,100,55,91,70,4,145,63,66,231,44,128,105,187,41,197,13,49,122,8,196,24,
-71,75,70,138,104,115,77,215,5,36,20,201,214,209,107,79,104,209,144,168,105,
-6,207,251,209,104,209,125,212,227,66,127,235,191,239,232,180,90,52,95,69,
-247,83,141,9,255,174,255,191,162,211,80,210,253,23,221,78,52,39,254,183,
-254,254,139,72,105,126,139,238,167,26,19,255,91,255,127,69,166,129,191,69,
-247,83,141,9,255,175,255,191,162,213,26,50,23,232,190,234,113,161,63,245,
-115,119,86,227,118,83,138,26,98,9,110,48,86,22,148,160,152,22,82,70,46,137,
-44,8,180,163,32,104,98,206,32,17,7,16,88,101,100,206,42,70,36,108,205,18,
-74,140,33,196,230,60,2,152,146,33,38,230,8,36,79,182,251,65,156,151,24,200,
-33,145,162,25,80,209,24,67,0,166,68,52,174,61,73,25,33,205,25,27,84,177,
-195,234,220,1,144,105,99,135,217,16,17,17,208,72,199,179,60,93,100,146,49,
-232,162,64,76,135,19,152,244,44,136,220,72,96,130,68,62,230,120,144,3,70,
-206,6,141,100,138,182,84,52,11,70,73,19,236,64,90,200,66,109,128,121,118,8,
-154,69,220,206,137,35,111,23,217,45,13,33,247,39,82,34,33,247,80,68,141,
-169,246,178,92,141,169,247,80,69,128,122,54,87,69,128,92,147,176,226,100,
-19,134,66,237,164,188,207,185,130,38,36,205,186,129,116,33,222,228,54,100,
-137,131,66,148,145,76,226,1,16,96,152,20,180,52,157,109,24,18,69,5,66,201,
-214,129,132,19,196,89,76,2,83,187,51,197,214,236,240,242,116,145,139,162,
-126,142,138,152,30,65,32,103,137,33,68,68,137,214,159,23,77,218,211,164,73,
-245,241,116,221,60,60,157,113,78,235,55,170,38,36,146,54,140,36,65,50,56,
-100,89,38,78,190,46,121,35,60,12,224,145,122,248,186,248,48,128,181,144,
-140,234,27,80,45,3,250,14,140,19,33,127,111,235,190,187,235,191,116,95,21,
-241,33,250,0,253,96,190,183,236,5,245,127,96,31,176,79,214,245,13,42,26,
-137,225,63,87,212,52,168,106,39,132,117,13,42,26,137,224,206,10,72,41,154,
-83,138,26,99,54,140,9,34,112,185,203,32,26,154,52,100,42,26,65,166,83,138,
-26,100,23,3,152,26,73,66,51,28,144,210,197,212,104,205,16,52,110,96,222,
-235,13,136,104,216,11,141,110,49,74,183,58,35,37,222,49,58,68,17,16,178,
-130,96,111,217,16,19,3,72,9,33,164,0,157,33,128,50,47,165,8,207,236,143,
-233,66,51,251,29,125,144,188,244,27,203,113,190,199,236,8,95,45,198,251,34,
-15,203,111,217,19,203,111,216,253,128,122,67,176,146,144,12,66,52,12,33,80,
-215,210,101,67,70,75,147,234,62,255,238,190,165,43,4,167,212,52,100,186,89,
-69,205,11,67,72,164,25,174,137,58,32,72,134,147,169,17,16,147,36,166,66,92,
-130,92,221,227,50,114,244,226,134,152,242,36,251,130,2,39,49,39,220,16,17,
-52,221,228,201,205,92,221,228,73,210,244,226,134,153,115,119,169,49,75,211,
-138,26,103,72,147,245,38,34,250,139,95,112,64,69,114,36,250,90,45,125,193,
-1,21,200,147,245,38,38,121,205,153,209,34,79,172,115,102,117,72,147,245,38,
-33,248,19,33,228,73,244,96,153,23,34,79,212,152,143,231,82,50,68,137,62,
-157,212,140,155,34,79,212,152,153,228,54,147,36,149,34,79,172,67,105,50,73,
-178,36,253,73,138,94,32,156,209,201,82,36,251,34,9,205,28,165,34,79,212,
-152,153,228,45,104,145,4,230,142,79,145,39,214,33,107,68,136,39,52,114,60,
-137,62,205,12,36,76,73,246,104,97,50,230,147,174,41,100,73,200,196,159,169,
-49,51,200,90,209,34,9,205,28,158,98,79,172,66,214,137,16,78,104,228,211,18,
-126,164,197,47,16,78,104,228,163,18,125,145,4,230,142,77,49,39,234,76,76,
-242,27,73,146,74,49,39,214,33,180,153,36,179,18,126,164,196,127,58,145,146,
-12,73,244,238,164,100,147,18,126,164,196,63,3,6,49,39,209,131,10,49,39,234,
-76,67,240,38,67,152,147,232,193,50,44,196,159,169,49,51,206,108,206,131,18,
-125,99,155,51,184,196,159,169,49,23,212,90,251,130,2,43,49,39,210,209,107,
-238,8,8,156,196,159,102,134,18,83,119,86,225,1,100,236,208,194,118,83,138,
-26,105,77,221,91,132,5,147,163,4,201,217,78,40,105,153,55,118,104,97,59,41,
-197,13,51,38,238,140,19,39,101,56,161,166,27,93,97,250,147,17,94,8,200,139,
-155,186,248,144,72,146,28,214,205,221,37,222,230,145,179,64,22,121,187,165,
-69,200,56,249,238,146,38,138,147,72,105,80,212,79,17,243,72,96,77,21,38,
-144,210,161,168,158,7,214,131,173,79,152,134,234,160,93,8,159,48,23,213,64,
-186,16,210,160,101,56,146,113,67,35,55,117,110,16,22,78,209,239,36,122,32,
-72,139,155,187,71,188,145,232,129,34,70,110,234,220,32,44,157,91,172,72,
-244,64,145,23,55,117,110,177,35,209,2,68,76,168,25,78,40,105,139,39,173,19,
-52,136,8,136,231,137,30,176,8,133,96,38,35,181,110,16,22,78,137,204,120,34,
-69,8,224,143,68,225,147,160,153,132,112,71,160,155,11,23,51,162,56,35,209,
-56,100,92,72,58,8,157,138,12,121,154,36,29,4,67,21,11,153,34,54,1,231,43,
-163,210,0,71,36,156,194,20,149,36,112,181,130,83,234,26,50,95,174,41,208,
-209,146,253,113,79,70,200,232,44,205,39,173,2,33,36,232,204,178,90,4,66,
-200,232,44,207,18,84,145,145,8,250,72,227,123,158,68,185,13,48,156,209,2,
-103,68,186,8,196,24,72,34,106,48,141,156,140,32,45,100,137,2,134,140,130,2,
-214,80,61,235,197,31,23,60,145,158,58,137,116,141,163,9,16,5,100,106,37,
-215,197,211,116,240,242,117,197,113,193,46,186,205,235,226,231,146,51,193,
-234,5,208,157,113,93,55,117,110,16,22,78,202,113,67,76,137,187,178,156,80,
-211,44,78,108,167,26,10,110,136,228,73,140,196,154,136,218,48,145,0,86,70,
-9,205,42,13,72,128,43,34,45,20,76,1,89,11,80,46,132,34,137,137,49,18,233,
-47,50,54,72,10,200,132,75,165,139,178,70,161,18,236,136,5,144,113,124,73,
-82,54,125,37,230,70,201,14,108,140,88,144,153,33,36,64,46,3,33,80,210,117,
-241,115,201,25,160,146,112,200,84,52,157,124,92,242,70,120,48,162,64,76,
-147,49,39,215,89,189,124,92,242,70,120,235,64,194,75,6,36,250,235,55,175,
-139,158,72,207,29,25,36,40,161,243,116,92,98,79,175,139,166,233,225,228,
-235,138,151,197,211,116,240,242,25,100,105,166,114,129,100,140,202,248,161,
-179,69,26,73,8,15,33,137,33,1,228,145,26,39,12,158,164,80,47,57,143,115,72,
-217,164,141,19,134,79,82,40,144,200,39,12,158,164,80,47,57,143,115,72,217,
-164,100,19,134,79,82,40,66,37,210,161,168,153,10,137,117,160,235,84,240,70,
-68,233,86,224,77,15,4,100,78,161,179,33,42,5,163,212,138,9,232,197,209,79,
-103,135,147,164,140,93,21,246,88,108,193,126,146,49,116,93,216,144,164,137,
-26,34,116,145,139,162,174,196,13,49,58,72,197,209,79,73,80,47,164,140,93,
-18,134,36,2,136,32,72,133,16,38,35,160,78,108,208,218,17,3,32,104,99,18,39,
-25,10,10,46,102,25,22,73,144,67,113,8,185,16,229,67,64,181,224,101,116,80,
-90,52,83,67,154,36,20,72,106,144,217,76,13,17,28,81,180,150,52,73,58,69,
-166,149,145,49,28,147,58,36,89,158,46,176,231,28,26,120,121,28,81,212,17,
-37,92,129,150,199,66,200,75,34,103,40,150,9,72,162,115,101,50,17,180,97,
-137,119,186,51,57,47,50,52,114,50,24,247,70,101,149,30,72,145,180,90,201,
-56,208,133,40,23,34,41,12,122,200,194,54,114,74,27,50,68,160,17,6,178,76,
-239,0,148,3,16,239,138,42,9,145,47,139,166,65,76,131,51,232,21,160,70,148,
-193,52,8,184,65,22,48,
-};
+	if (duk_fb_is_full(fb)) {
+		return;
+	}
 
-/* to convert a heap stridx to a token number, subtract
- * DUK_STRIDX_START_RESERVED and add DUK_TOK_START_RESERVED.
- */
+	if (!h) {
+		duk_fb_put_cstring(fb, "NULL");
+		return;
+	}
 
-/* native functions: 129 */
-const duk_c_function duk_bi_native_functions[] = {
-	duk_bi_array_constructor,
-	duk_bi_array_constructor_is_array,
-	duk_bi_array_prototype_concat,
-	duk_bi_array_prototype_indexof_shared,
-	duk_bi_array_prototype_iter_shared,
-	duk_bi_array_prototype_join_shared,
-	duk_bi_array_prototype_pop,
-	duk_bi_array_prototype_push,
-	duk_bi_array_prototype_reduce_shared,
-	duk_bi_array_prototype_reverse,
-	duk_bi_array_prototype_shift,
-	duk_bi_array_prototype_slice,
-	duk_bi_array_prototype_sort,
-	duk_bi_array_prototype_splice,
-	duk_bi_array_prototype_to_string,
-	duk_bi_array_prototype_unshift,
-	duk_bi_boolean_constructor,
-	duk_bi_boolean_prototype_tostring_shared,
-	duk_bi_buffer_constructor,
-	duk_bi_buffer_prototype_tostring_shared,
-	duk_bi_date_constructor,
-	duk_bi_date_constructor_now,
-	duk_bi_date_constructor_parse,
-	duk_bi_date_constructor_utc,
-	duk_bi_date_prototype_get_shared,
-	duk_bi_date_prototype_get_timezone_offset,
-	duk_bi_date_prototype_set_shared,
-	duk_bi_date_prototype_set_time,
-	duk_bi_date_prototype_to_json,
-	duk_bi_date_prototype_tostring_shared,
-	duk_bi_date_prototype_value_of,
-	duk_bi_duktape_object_act,
-	duk_bi_duktape_object_compact,
-	duk_bi_duktape_object_dec,
-	duk_bi_duktape_object_enc,
-	duk_bi_duktape_object_fin,
-	duk_bi_duktape_object_gc,
-	duk_bi_duktape_object_info,
-	duk_bi_error_constructor_shared,
-	duk_bi_error_prototype_filename_getter,
-	duk_bi_error_prototype_linenumber_getter,
-	duk_bi_error_prototype_nop_setter,
-	duk_bi_error_prototype_stack_getter,
-	duk_bi_error_prototype_to_string,
-	duk_bi_function_constructor,
-	duk_bi_function_prototype,
-	duk_bi_function_prototype_apply,
-	duk_bi_function_prototype_bind,
-	duk_bi_function_prototype_call,
-	duk_bi_function_prototype_to_string,
-	duk_bi_global_object_alert,
-	duk_bi_global_object_decode_uri,
-	duk_bi_global_object_decode_uri_component,
-	duk_bi_global_object_encode_uri,
-	duk_bi_global_object_encode_uri_component,
-	duk_bi_global_object_escape,
-	duk_bi_global_object_eval,
-	duk_bi_global_object_is_finite,
-	duk_bi_global_object_is_nan,
-	duk_bi_global_object_parse_float,
-	duk_bi_global_object_parse_int,
-	duk_bi_global_object_print,
-	duk_bi_global_object_require,
-	duk_bi_global_object_unescape,
-	duk_bi_json_object_parse,
-	duk_bi_json_object_stringify,
-	duk_bi_logger_constructor,
-	duk_bi_logger_prototype_fmt,
-	duk_bi_logger_prototype_log_shared,
-	duk_bi_logger_prototype_raw,
-	duk_bi_math_object_max,
-	duk_bi_math_object_min,
-	duk_bi_math_object_onearg_shared,
-	duk_bi_math_object_random,
-	duk_bi_math_object_twoarg_shared,
-	duk_bi_number_constructor,
-	duk_bi_number_prototype_to_exponential,
-	duk_bi_number_prototype_to_fixed,
-	duk_bi_number_prototype_to_locale_string,
-	duk_bi_number_prototype_to_precision,
-	duk_bi_number_prototype_to_string,
-	duk_bi_number_prototype_value_of,
-	duk_bi_object_constructor,
-	duk_bi_object_constructor_create,
-	duk_bi_object_constructor_define_properties,
-	duk_bi_object_constructor_define_property,
-	duk_bi_object_constructor_get_own_property_descriptor,
-	duk_bi_object_constructor_is_extensible,
-	duk_bi_object_constructor_is_sealed_frozen_shared,
-	duk_bi_object_constructor_keys_shared,
-	duk_bi_object_constructor_prevent_extensions,
-	duk_bi_object_constructor_seal_freeze_shared,
-	duk_bi_object_getprototype_shared,
-	duk_bi_object_prototype_has_own_property,
-	duk_bi_object_prototype_is_prototype_of,
-	duk_bi_object_prototype_property_is_enumerable,
-	duk_bi_object_prototype_to_locale_string,
-	duk_bi_object_prototype_to_string,
-	duk_bi_object_prototype_value_of,
-	duk_bi_object_setprototype_shared,
-	duk_bi_pointer_constructor,
-	duk_bi_pointer_prototype_tostring_shared,
-	duk_bi_proxy_constructor,
-	duk_bi_regexp_constructor,
-	duk_bi_regexp_prototype_exec,
-	duk_bi_regexp_prototype_test,
-	duk_bi_regexp_prototype_to_string,
-	duk_bi_string_constructor,
-	duk_bi_string_constructor_from_char_code,
-	duk_bi_string_prototype_caseconv_shared,
-	duk_bi_string_prototype_char_at,
-	duk_bi_string_prototype_char_code_at,
-	duk_bi_string_prototype_concat,
-	duk_bi_string_prototype_indexof_shared,
-	duk_bi_string_prototype_locale_compare,
-	duk_bi_string_prototype_match,
-	duk_bi_string_prototype_replace,
-	duk_bi_string_prototype_search,
-	duk_bi_string_prototype_slice,
-	duk_bi_string_prototype_split,
-	duk_bi_string_prototype_substr,
-	duk_bi_string_prototype_substring,
-	duk_bi_string_prototype_to_string,
-	duk_bi_string_prototype_trim,
-	duk_bi_thread_constructor,
-	duk_bi_thread_current,
-	duk_bi_thread_resume,
-	duk_bi_thread_yield,
-	duk_bi_type_error_thrower,
-};
+	switch (DUK_HEAPHDR_GET_TYPE(h)) {
+	case DUK_HTYPE_STRING:
+		duk__print_hstring(st, (duk_hstring *) h, 1);
+		break;
+	case DUK_HTYPE_OBJECT:
+		duk__print_hobject(st, (duk_hobject *) h);
+		break;
+	case DUK_HTYPE_BUFFER:
+		duk__print_hbuffer(st, (duk_hbuffer *) h);
+		break;
+	default:
+		duk_fb_sprintf(fb, "[unknown htype %ld]", (long) DUK_HEAPHDR_GET_TYPE(h));
+		break;
+	}
+}
 
-const duk_uint8_t duk_builtins_data[] = {
-105,195,74,144,77,40,105,44,9,124,104,45,3,3,72,0,71,225,65,165,172,33,243,
-6,145,0,122,24,210,150,14,249,35,120,160,55,226,13,76,224,196,177,164,152,
-22,192,4,202,52,147,72,152,0,169,70,146,105,11,0,23,40,210,77,32,96,3,37,
-26,73,163,236,0,108,163,73,52,121,128,14,148,105,38,142,176,1,242,144,56,
-209,0,84,6,166,98,242,80,210,248,1,250,67,72,144,15,232,13,44,128,47,162,
-52,161,0,62,80,160,255,253,102,76,0,0,0,0,0,0,15,135,243,84,0,0,0,0,0,0,15,
-7,243,124,64,153,132,18,49,2,38,48,64,200,7,153,64,227,48,26,103,3,13,0,89,
-165,34,53,36,38,180,128,216,143,155,81,227,114,58,111,2,142,0,73,194,94,56,
-202,167,33,209,195,130,70,207,17,26,59,36,100,232,145,131,146,69,204,201,
-22,52,36,84,212,145,67,98,68,205,201,18,63,36,68,244,122,32,100,60,87,62,
-39,255,254,9,46,24,0,10,31,224,29,13,92,40,0,9,101,141,32,0,48,197,100,66,
-214,73,10,83,68,37,85,144,133,68,65,214,201,6,91,40,0,12,21,104,144,69,130,
-64,214,10,0,3,2,87,36,5,100,160,0,63,254,16,37,135,92,99,25,242,194,7,195,
-0,30,236,64,123,46,145,234,188,71,162,249,5,23,240,0,15,241,0,17,242,98,7,
-153,114,30,70,7,207,18,243,225,71,252,0,93,192,36,15,241,128,85,242,28,7,
-192,40,64,0,93,160,71,206,192,82,58,193,128,234,7,62,116,132,129,208,20,7,
-56,90,28,193,132,114,134,175,57,3,207,156,96,103,224,0,46,32,51,255,255,
-247,8,33,163,128,16,212,0,5,190,8,106,0,4,222,4,53,0,3,110,130,26,128,2,55,
-2,15,192,0,91,97,7,255,255,226,147,248,0,182,155,15,131,252,128,73,144,128,
-202,62,94,128,247,122,3,101,184,141,134,242,59,92,15,156,110,38,142,39,19,
-80,0,22,187,145,26,206,100,106,186,33,168,234,71,59,178,26,110,232,105,60,
-161,162,218,6,131,104,25,237,161,0,1,103,54,132,0,5,154,246,6,99,194,5,47,
-240,0,15,242,129,38,70,9,242,34,16,0,23,184,136,5,55,241,89,112,63,255,255,
-255,255,255,251,223,217,80,0,64,0,0,0,0,0,0,25,48,0,0,0,0,0,0,62,31,216,
-240,0,0,0,0,0,0,60,31,217,16,0,0,0,0,0,0,60,63,192,15,243,1,38,64,0,0,0,0,
-0,0,0,0,25,242,160,71,194,113,30,234,32,99,38,145,138,152,70,34,121,5,63,
-240,3,97,139,17,132,47,252,193,21,0,127,156,9,50,64,0,0,0,0,0,7,195,253,
-175,145,208,128,52,48,7,66,0,80,191,29,8,2,67,224,116,32,29,11,225,208,128,
-84,47,71,66,1,144,155,29,8,3,2,104,116,32,140,73,145,194,61,199,128,188,30,
-2,236,96,32,1,11,161,128,46,70,2,32,16,184,24,8,128,2,220,96,36,1,139,97,
-128,144,2,45,70,2,224,16,180,24,11,128,2,204,96,38,1,11,33,128,152,0,44,70,
-2,128,16,176,24,10,0,2,188,96,42,1,10,225,128,168,0,43,70,2,192,16,172,24,
-11,0,2,172,100,10,161,178,42,70,138,34,16,168,26,40,136,2,156,105,124,132,
-33,76,52,190,66,0,165,26,127,49,8,82,13,63,152,128,40,198,167,208,66,20,67,
-83,232,32,10,17,162,136,4,40,6,138,32,0,159,26,95,32,8,79,13,47,144,0,39,
-70,159,204,2,83,131,79,230,0,41,129,128,128,12,37,198,138,100,2,42,63,128,
-0,127,160,49,38,8,24,0,64,82,112,145,224,120,201,40,201,24,201,9,0,0,0,0,0,
-0,0,0,1,165,90,8,148,105,35,229,168,2,167,248,0,7,250,66,163,8,22,139,32,
-49,77,202,138,74,46,78,82,80,114,130,144,95,37,96,21,95,192,1,63,212,9,24,
-82,36,89,1,128,21,127,192,1,63,214,9,24,82,20,89,1,128,21,159,192,1,63,216,
-9,24,82,4,89,1,128,21,191,192,1,63,218,9,24,81,244,89,1,128,21,223,192,1,
-63,220,9,24,81,228,89,1,128,21,255,192,1,63,222,9,24,81,212,89,1,128,15,
-255,200,69,64,105,87,20,139,10,191,5,64,68,192,22,85,181,187,177,107,2,64,
-68,64,239,57,250,254,66,46,230,63,67,192,254,130,43,101,71,21,247,63,67,64,
-14,229,38,21,123,203,219,63,66,192,24,45,68,84,251,33,9,64,66,64,205,59,
-127,102,158,160,230,63,65,192,205,59,127,102,158,160,246,63,73,4,144,68,10,
-65,64,0,80,9,5,0,2,63,164,20,0,12,252,148,131,234,65,64,1,15,137,5,0,5,61,
-164,20,0,24,244,144,80,0,115,202,65,64,2,15,8,203,199,116,117,227,178,82,
-64,0,78,169,32,58,36,20,0,36,230,144,80,0,163,146,65,64,2,206,41,5,0,12,15,
-255,192,9,134,128,131,130,11,5,255,240,0,23,255,192,0,63,255,20,105,0,0,0,
-0,0,0,194,69,0,6,115,128,142,144,9,202,0,58,199,25,146,144,100,62,65,137,
-33,6,4,99,194,242,33,225,113,8,240,164,128,130,205,248,1,211,223,208,40,
-126,96,157,244,1,255,40,0,11,71,224,0,31,243,128,19,228,76,32,0,47,113,48,
-11,87,224,0,31,244,128,19,229,148,32,0,47,118,80,11,103,224,0,31,245,132,
-30,144,0,0,0,0,0,0,0,128,31,146,9,135,118,253,196,9,144,200,37,69,32,145,
-16,120,70,136,62,0,2,51,68,31,0,2,17,34,15,128,1,136,81,7,192,1,4,8,131,
-224,0,169,255,248,72,200,33,113,55,245,197,179,44,94,92,183,242,69,193,23,
-203,203,150,254,72,52,238,65,151,151,45,252,144,104,195,187,38,205,59,179,
-128,
-};
-#ifdef DUK_USE_BUILTIN_INITJS
-const duk_uint8_t duk_initjs_data[] = {
-40,102,117,110,99,116,105,111,110,40,100,44,97,41,123,102,117,110,99,116,
-105,111,110,32,98,40,97,44,98,44,99,41,123,79,98,106,101,99,116,46,100,101,
-102,105,110,101,80,114,111,112,101,114,116,121,40,97,44,98,44,123,118,97,
-108,117,101,58,99,44,119,114,105,116,97,98,108,101,58,33,48,44,101,110,117,
-109,101,114,97,98,108,101,58,33,49,44,99,111,110,102,105,103,117,114,97,98,
-108,101,58,33,48,125,41,125,98,40,97,46,76,111,103,103,101,114,44,34,99,
-108,111,103,34,44,110,101,119,32,97,46,76,111,103,103,101,114,40,34,67,34,
-41,41,59,98,40,97,44,34,109,111,100,76,111,97,100,101,100,34,44,123,125,41,
-125,41,40,116,104,105,115,44,68,117,107,116,97,112,101,41,59,10,0,
-};
-#endif  /* DUK_USE_BUILTIN_INITJS */
-#elif defined(DUK_USE_DOUBLE_BE)
-const duk_uint8_t duk_strings_data[] = {
-55,86,227,24,145,55,102,120,144,3,63,94,228,54,100,137,186,26,20,164,137,
-186,50,11,164,109,77,215,5,61,35,106,3,25,110,8,22,158,130,38,163,8,217,
-200,158,76,156,210,117,128,153,203,210,70,46,137,187,18,27,164,187,201,209,
-130,100,55,91,70,4,145,63,66,231,44,128,105,187,41,197,13,49,122,8,196,24,
-71,75,70,138,104,115,77,215,5,36,20,201,214,209,107,79,104,209,144,168,105,
-6,207,251,209,104,209,125,212,227,66,127,235,191,239,232,180,90,52,95,69,
-247,83,141,9,255,174,255,191,162,211,80,210,253,23,221,78,52,39,254,183,
-254,254,139,72,105,126,139,238,167,26,19,255,91,255,127,69,166,129,191,69,
-247,83,141,9,255,175,255,191,162,213,26,50,23,232,190,234,113,161,63,245,
-115,119,86,227,118,83,138,26,98,9,110,48,86,22,148,160,152,22,82,70,46,137,
-44,8,180,163,32,104,98,206,32,17,7,16,88,101,100,206,42,70,36,108,205,18,
-74,140,33,196,230,60,2,152,146,33,38,230,8,36,79,182,251,65,156,151,24,200,
-33,145,162,25,80,209,24,67,0,166,68,52,174,61,73,25,33,205,25,27,84,177,
-195,234,220,1,144,105,99,135,217,16,17,17,208,72,199,179,60,93,100,146,49,
-232,162,64,76,135,19,152,244,44,136,220,72,96,130,68,62,230,120,144,3,70,
-206,6,141,100,138,182,84,52,11,70,73,19,236,64,90,200,66,109,128,121,118,8,
-154,69,220,206,137,35,111,23,217,45,13,33,247,39,82,34,33,247,80,68,141,
-169,246,178,92,141,169,247,80,69,128,122,54,87,69,128,92,147,176,226,100,
-19,134,66,237,164,188,207,185,130,38,36,205,186,129,116,33,222,228,54,100,
-137,131,66,148,145,76,226,1,16,96,152,20,180,52,157,109,24,18,69,5,66,201,
-214,129,132,19,196,89,76,2,83,187,51,197,214,236,240,242,116,145,139,162,
-126,142,138,152,30,65,32,103,137,33,68,68,137,214,159,23,77,218,211,164,73,
-245,241,116,221,60,60,157,113,78,235,55,170,38,36,146,54,140,36,65,50,56,
-100,89,38,78,190,46,121,35,60,12,224,145,122,248,186,248,48,128,181,144,
-140,234,27,80,45,3,250,14,140,19,33,127,111,235,190,187,235,191,116,95,21,
-241,33,250,0,253,96,190,183,236,5,245,127,96,31,176,79,214,245,13,42,26,
-137,225,63,87,212,52,168,106,39,132,117,13,42,26,137,224,206,10,72,41,154,
-83,138,26,99,54,140,9,34,112,185,203,32,26,154,52,100,42,26,65,166,83,138,
-26,100,23,3,152,26,73,66,51,28,144,210,197,212,104,205,16,52,110,96,222,
-235,13,136,104,216,11,141,110,49,74,183,58,35,37,222,49,58,68,17,16,178,
-130,96,111,217,16,19,3,72,9,33,164,0,157,33,128,50,47,165,8,207,236,143,
-233,66,51,251,29,125,144,188,244,27,203,113,190,199,236,8,95,45,198,251,34,
-15,203,111,217,19,203,111,216,253,128,122,67,176,146,144,12,66,52,12,33,80,
-215,210,101,67,70,75,147,234,62,255,238,190,165,43,4,167,212,52,100,186,89,
-69,205,11,67,72,164,25,174,137,58,32,72,134,147,169,17,16,147,36,166,66,92,
-130,92,221,227,50,114,244,226,134,152,242,36,251,130,2,39,49,39,220,16,17,
-52,221,228,201,205,92,221,228,73,210,244,226,134,153,115,119,169,49,75,211,
-138,26,103,72,147,245,38,34,250,139,95,112,64,69,114,36,250,90,45,125,193,
-1,21,200,147,245,38,38,121,205,153,209,34,79,172,115,102,117,72,147,245,38,
-33,248,19,33,228,73,244,96,153,23,34,79,212,152,143,231,82,50,68,137,62,
-157,212,140,155,34,79,212,152,153,228,54,147,36,149,34,79,172,67,105,50,73,
-178,36,253,73,138,94,32,156,209,201,82,36,251,34,9,205,28,165,34,79,212,
-152,153,228,45,104,145,4,230,142,79,145,39,214,33,107,68,136,39,52,114,60,
-137,62,205,12,36,76,73,246,104,97,50,230,147,174,41,100,73,200,196,159,169,
-49,51,200,90,209,34,9,205,28,158,98,79,172,66,214,137,16,78,104,228,211,18,
-126,164,197,47,16,78,104,228,163,18,125,145,4,230,142,77,49,39,234,76,76,
-242,27,73,146,74,49,39,214,33,180,153,36,179,18,126,164,196,127,58,145,146,
-12,73,244,238,164,100,147,18,126,164,196,63,3,6,49,39,209,131,10,49,39,234,
-76,67,240,38,67,152,147,232,193,50,44,196,159,169,49,51,206,108,206,131,18,
-125,99,155,51,184,196,159,169,49,23,212,90,251,130,2,43,49,39,210,209,107,
-238,8,8,156,196,159,102,134,18,83,119,86,225,1,100,236,208,194,118,83,138,
-26,105,77,221,91,132,5,147,163,4,201,217,78,40,105,153,55,118,104,97,59,41,
-197,13,51,38,238,140,19,39,101,56,161,166,27,93,97,250,147,17,94,8,200,139,
-155,186,248,144,72,146,28,214,205,221,37,222,230,145,179,64,22,121,187,165,
-69,200,56,249,238,146,38,138,147,72,105,80,212,79,17,243,72,96,77,21,38,
-144,210,161,168,158,7,214,131,173,79,152,134,234,160,93,8,159,48,23,213,64,
-186,16,210,160,101,56,146,113,67,35,55,117,110,16,22,78,209,239,36,122,32,
-72,139,155,187,71,188,145,232,129,34,70,110,234,220,32,44,157,91,172,72,
-244,64,145,23,55,117,110,177,35,209,2,68,76,168,25,78,40,105,139,39,173,19,
-52,136,8,136,231,137,30,176,8,133,96,38,35,181,110,16,22,78,137,204,120,34,
-69,8,224,143,68,225,147,160,153,132,112,71,160,155,11,23,51,162,56,35,209,
-56,100,92,72,58,8,157,138,12,121,154,36,29,4,67,21,11,153,34,54,1,231,43,
-163,210,0,71,36,156,194,20,149,36,112,181,130,83,234,26,50,95,174,41,208,
-209,146,253,113,79,70,200,232,44,205,39,173,2,33,36,232,204,178,90,4,66,
-200,232,44,207,18,84,145,145,8,250,72,227,123,158,68,185,13,48,156,209,2,
-103,68,186,8,196,24,72,34,106,48,141,156,140,32,45,100,137,2,134,140,130,2,
-214,80,61,235,197,31,23,60,145,158,58,137,116,141,163,9,16,5,100,106,37,
-215,197,211,116,240,242,117,197,113,193,46,186,205,235,226,231,146,51,193,
-234,5,208,157,113,93,55,117,110,16,22,78,202,113,67,76,137,187,178,156,80,
-211,44,78,108,167,26,10,110,136,228,73,140,196,154,136,218,48,145,0,86,70,
-9,205,42,13,72,128,43,34,45,20,76,1,89,11,80,46,132,34,137,137,49,18,233,
-47,50,54,72,10,200,132,75,165,139,178,70,161,18,236,136,5,144,113,124,73,
-82,54,125,37,230,70,201,14,108,140,88,144,153,33,36,64,46,3,33,80,210,117,
-241,115,201,25,160,146,112,200,84,52,157,124,92,242,70,120,48,162,64,76,
-147,49,39,215,89,189,124,92,242,70,120,235,64,194,75,6,36,250,235,55,175,
-139,158,72,207,29,25,36,40,161,243,116,92,98,79,175,139,166,233,225,228,
-235,138,151,197,211,116,240,242,25,100,105,166,114,129,100,140,202,248,161,
-179,69,26,73,8,15,33,137,33,1,228,145,26,39,12,158,164,80,47,57,143,115,72,
-217,164,141,19,134,79,82,40,144,200,39,12,158,164,80,47,57,143,115,72,217,
-164,100,19,134,79,82,40,66,37,210,161,168,153,10,137,117,160,235,84,240,70,
-68,233,86,224,77,15,4,100,78,161,179,33,42,5,163,212,138,9,232,197,209,79,
-103,135,147,164,140,93,21,246,88,108,193,126,146,49,116,93,216,144,164,137,
-26,34,116,145,139,162,174,196,13,49,58,72,197,209,79,73,80,47,164,140,93,
-18,134,36,2,136,32,72,133,16,38,35,160,78,108,208,218,17,3,32,104,99,18,39,
-25,10,10,46,102,25,22,73,144,67,113,8,185,16,229,67,64,181,224,101,116,80,
-90,52,83,67,154,36,20,72,106,144,217,76,13,17,28,81,180,150,52,73,58,69,
-166,149,145,49,28,147,58,36,89,158,46,176,231,28,26,120,121,28,81,212,17,
-37,92,129,150,199,66,200,75,34,103,40,150,9,72,162,115,101,50,17,180,97,
-137,119,186,51,57,47,50,52,114,50,24,247,70,101,149,30,72,145,180,90,201,
-56,208,133,40,23,34,41,12,122,200,194,54,114,74,27,50,68,160,17,6,178,76,
-239,0,148,3,16,239,138,42,9,145,47,139,166,65,76,131,51,232,21,160,70,148,
-193,52,8,184,65,22,48,
-};
+DUK_LOCAL void duk__print_tval(duk__dprint_state *st, duk_tval *tv) {
+	duk_fixedbuffer *fb = st->fb;
 
-/* to convert a heap stridx to a token number, subtract
- * DUK_STRIDX_START_RESERVED and add DUK_TOK_START_RESERVED.
- */
+	if (duk_fb_is_full(fb)) {
+		return;
+	}
 
-/* native functions: 129 */
-const duk_c_function duk_bi_native_functions[] = {
-	duk_bi_array_constructor,
-	duk_bi_array_constructor_is_array,
-	duk_bi_array_prototype_concat,
-	duk_bi_array_prototype_indexof_shared,
-	duk_bi_array_prototype_iter_shared,
-	duk_bi_array_prototype_join_shared,
-	duk_bi_array_prototype_pop,
-	duk_bi_array_prototype_push,
-	duk_bi_array_prototype_reduce_shared,
-	duk_bi_array_prototype_reverse,
-	duk_bi_array_prototype_shift,
-	duk_bi_array_prototype_slice,
-	duk_bi_array_prototype_sort,
-	duk_bi_array_prototype_splice,
-	duk_bi_array_prototype_to_string,
-	duk_bi_array_prototype_unshift,
-	duk_bi_boolean_constructor,
-	duk_bi_boolean_prototype_tostring_shared,
-	duk_bi_buffer_constructor,
-	duk_bi_buffer_prototype_tostring_shared,
-	duk_bi_date_constructor,
-	duk_bi_date_constructor_now,
-	duk_bi_date_constructor_parse,
-	duk_bi_date_constructor_utc,
-	duk_bi_date_prototype_get_shared,
-	duk_bi_date_prototype_get_timezone_offset,
-	duk_bi_date_prototype_set_shared,
-	duk_bi_date_prototype_set_time,
-	duk_bi_date_prototype_to_json,
-	duk_bi_date_prototype_tostring_shared,
-	duk_bi_date_prototype_value_of,
-	duk_bi_duktape_object_act,
-	duk_bi_duktape_object_compact,
-	duk_bi_duktape_object_dec,
-	duk_bi_duktape_object_enc,
-	duk_bi_duktape_object_fin,
-	duk_bi_duktape_object_gc,
-	duk_bi_duktape_object_info,
-	duk_bi_error_constructor_shared,
-	duk_bi_error_prototype_filename_getter,
-	duk_bi_error_prototype_linenumber_getter,
-	duk_bi_error_prototype_nop_setter,
-	duk_bi_error_prototype_stack_getter,
-	duk_bi_error_prototype_to_string,
-	duk_bi_function_constructor,
-	duk_bi_function_prototype,
-	duk_bi_function_prototype_apply,
-	duk_bi_function_prototype_bind,
-	duk_bi_function_prototype_call,
-	duk_bi_function_prototype_to_string,
-	duk_bi_global_object_alert,
-	duk_bi_global_object_decode_uri,
-	duk_bi_global_object_decode_uri_component,
-	duk_bi_global_object_encode_uri,
-	duk_bi_global_object_encode_uri_component,
-	duk_bi_global_object_escape,
-	duk_bi_global_object_eval,
-	duk_bi_global_object_is_finite,
-	duk_bi_global_object_is_nan,
-	duk_bi_global_object_parse_float,
-	duk_bi_global_object_parse_int,
-	duk_bi_global_object_print,
-	duk_bi_global_object_require,
-	duk_bi_global_object_unescape,
-	duk_bi_json_object_parse,
-	duk_bi_json_object_stringify,
-	duk_bi_logger_constructor,
-	duk_bi_logger_prototype_fmt,
-	duk_bi_logger_prototype_log_shared,
-	duk_bi_logger_prototype_raw,
-	duk_bi_math_object_max,
-	duk_bi_math_object_min,
-	duk_bi_math_object_onearg_shared,
-	duk_bi_math_object_random,
-	duk_bi_math_object_twoarg_shared,
-	duk_bi_number_constructor,
-	duk_bi_number_prototype_to_exponential,
-	duk_bi_number_prototype_to_fixed,
-	duk_bi_number_prototype_to_locale_string,
-	duk_bi_number_prototype_to_precision,
-	duk_bi_number_prototype_to_string,
-	duk_bi_number_prototype_value_of,
-	duk_bi_object_constructor,
-	duk_bi_object_constructor_create,
-	duk_bi_object_constructor_define_properties,
-	duk_bi_object_constructor_define_property,
-	duk_bi_object_constructor_get_own_property_descriptor,
-	duk_bi_object_constructor_is_extensible,
-	duk_bi_object_constructor_is_sealed_frozen_shared,
-	duk_bi_object_constructor_keys_shared,
-	duk_bi_object_constructor_prevent_extensions,
-	duk_bi_object_constructor_seal_freeze_shared,
-	duk_bi_object_getprototype_shared,
-	duk_bi_object_prototype_has_own_property,
-	duk_bi_object_prototype_is_prototype_of,
-	duk_bi_object_prototype_property_is_enumerable,
-	duk_bi_object_prototype_to_locale_string,
-	duk_bi_object_prototype_to_string,
-	duk_bi_object_prototype_value_of,
-	duk_bi_object_setprototype_shared,
-	duk_bi_pointer_constructor,
-	duk_bi_pointer_prototype_tostring_shared,
-	duk_bi_proxy_constructor,
-	duk_bi_regexp_constructor,
-	duk_bi_regexp_prototype_exec,
-	duk_bi_regexp_prototype_test,
-	duk_bi_regexp_prototype_to_string,
-	duk_bi_string_constructor,
-	duk_bi_string_constructor_from_char_code,
-	duk_bi_string_prototype_caseconv_shared,
-	duk_bi_string_prototype_char_at,
-	duk_bi_string_prototype_char_code_at,
-	duk_bi_string_prototype_concat,
-	duk_bi_string_prototype_indexof_shared,
-	duk_bi_string_prototype_locale_compare,
-	duk_bi_string_prototype_match,
-	duk_bi_string_prototype_replace,
-	duk_bi_string_prototype_search,
-	duk_bi_string_prototype_slice,
-	duk_bi_string_prototype_split,
-	duk_bi_string_prototype_substr,
-	duk_bi_string_prototype_substring,
-	duk_bi_string_prototype_to_string,
-	duk_bi_string_prototype_trim,
-	duk_bi_thread_constructor,
-	duk_bi_thread_current,
-	duk_bi_thread_resume,
-	duk_bi_thread_yield,
-	duk_bi_type_error_thrower,
-};
+	/* depth check is done when printing an actual type */
 
-const duk_uint8_t duk_builtins_data[] = {
-105,195,74,144,77,40,105,44,9,124,104,45,3,3,72,0,71,225,65,165,172,33,243,
-6,145,0,122,24,210,150,14,249,35,120,160,55,226,13,76,224,196,177,164,152,
-22,192,4,202,52,147,72,152,0,169,70,146,105,11,0,23,40,210,77,32,96,3,37,
-26,73,163,236,0,108,163,73,52,121,128,14,148,105,38,142,176,1,242,144,56,
-209,0,84,6,166,98,242,80,210,248,1,250,67,72,144,15,232,13,44,128,47,162,
-52,161,0,62,80,160,255,253,102,76,7,255,128,0,0,0,0,0,3,84,7,255,0,0,0,0,0,
-0,3,124,64,153,132,18,49,2,38,48,64,200,7,153,64,227,48,26,103,3,13,0,89,
-165,34,53,36,38,180,128,216,143,155,81,227,114,58,111,2,142,0,73,194,94,56,
-202,167,33,209,195,130,70,207,17,26,59,36,100,232,145,131,146,69,204,201,
-22,52,36,84,212,145,67,98,68,205,201,18,63,36,68,244,122,32,100,60,87,62,
-39,255,254,9,46,24,0,10,31,224,29,13,92,40,0,9,101,141,32,0,48,197,100,66,
-214,73,10,83,68,37,85,144,133,68,65,214,201,6,91,40,0,12,21,104,144,69,130,
-64,214,10,0,3,2,87,36,5,100,160,0,63,254,16,37,135,92,99,25,242,194,7,195,
-0,30,236,64,123,46,145,234,188,71,162,249,5,23,240,0,15,241,0,17,242,98,7,
-153,114,30,70,7,207,18,243,225,71,252,0,93,192,36,15,241,128,85,242,28,7,
-192,40,64,0,93,160,71,206,192,82,58,193,128,234,7,62,116,132,129,208,20,7,
-56,90,28,193,132,114,134,175,57,3,207,156,96,103,224,0,46,32,51,255,255,
-247,8,33,163,128,16,212,0,5,190,8,106,0,4,222,4,53,0,3,110,130,26,128,2,55,
-2,15,192,0,91,97,7,255,255,226,147,248,0,182,155,15,131,252,128,73,144,128,
-202,62,94,128,247,122,3,101,184,141,134,242,59,92,15,156,110,38,142,39,19,
-80,0,22,187,145,26,206,100,106,186,33,168,234,71,59,178,26,110,232,105,60,
-161,162,218,6,131,104,25,237,161,0,1,103,54,132,0,5,154,246,6,99,194,5,47,
-240,0,15,242,129,38,70,9,242,34,16,0,23,184,136,5,55,241,89,112,31,251,255,
-255,255,255,255,255,217,80,0,0,0,0,0,0,0,0,89,48,31,254,0,0,0,0,0,0,24,240,
-31,252,0,0,0,0,0,0,25,16,63,252,0,0,0,0,0,0,0,15,243,1,38,64,0,0,0,0,0,0,0,
-0,25,242,160,71,194,113,30,234,32,99,38,145,138,152,70,34,121,5,63,240,3,
-97,139,17,132,47,252,193,21,0,127,156,9,50,67,255,192,0,0,0,0,0,5,175,145,
-208,128,52,48,7,66,0,80,191,29,8,2,67,224,116,32,29,11,225,208,128,84,47,
-71,66,1,144,155,29,8,3,2,104,116,32,140,73,145,194,61,199,128,188,30,2,236,
-96,32,1,11,161,128,46,70,2,32,16,184,24,8,128,2,220,96,36,1,139,97,128,144,
-2,45,70,2,224,16,180,24,11,128,2,204,96,38,1,11,33,128,152,0,44,70,2,128,
-16,176,24,10,0,2,188,96,42,1,10,225,128,168,0,43,70,2,192,16,172,24,11,0,2,
-172,100,10,161,178,42,70,138,34,16,168,26,40,136,2,156,105,124,132,33,76,
-52,190,66,0,165,26,127,49,8,82,13,63,152,128,40,198,167,208,66,20,67,83,
-232,32,10,17,162,136,4,40,6,138,32,0,159,26,95,32,8,79,13,47,144,0,39,70,
-159,204,2,83,131,79,230,0,41,129,128,128,12,37,198,138,100,2,42,63,128,0,
-127,160,49,38,8,24,0,64,82,112,145,224,120,201,40,201,24,201,9,0,0,0,0,0,0,
-0,0,1,165,90,8,148,105,35,229,168,2,167,248,0,7,250,66,163,8,22,139,32,49,
-77,202,138,74,46,78,82,80,114,130,144,95,37,96,21,95,192,1,63,212,9,24,82,
-36,89,1,128,21,127,192,1,63,214,9,24,82,20,89,1,128,21,159,192,1,63,216,9,
-24,82,4,89,1,128,21,191,192,1,63,218,9,24,81,244,89,1,128,21,223,192,1,63,
-220,9,24,81,228,89,1,128,21,255,192,1,63,222,9,24,81,212,89,1,128,15,255,
-200,69,64,64,5,191,10,139,20,87,105,68,192,64,2,107,177,187,181,85,22,68,
-64,63,230,46,66,254,250,57,239,67,192,63,247,21,71,101,43,130,254,67,64,63,
-219,203,123,21,38,229,14,66,192,64,9,33,251,84,68,45,24,66,64,63,230,160,
-158,102,127,59,205,65,192,63,246,160,158,102,127,59,205,73,4,144,68,10,65,
-64,0,80,9,5,0,2,63,164,20,0,12,252,148,131,234,65,64,1,15,137,5,0,5,61,164,
-20,0,24,244,144,80,0,115,202,65,64,2,15,8,203,199,116,117,227,178,82,64,0,
-78,169,32,58,36,20,0,36,230,144,80,0,163,146,65,64,2,206,41,5,0,12,15,255,
-192,9,134,128,131,130,11,5,255,240,0,23,255,192,0,63,255,20,105,1,2,68,192,
-0,0,0,0,0,6,115,128,142,144,9,202,0,58,199,25,146,144,100,62,65,137,33,6,4,
-99,194,242,33,225,113,8,240,164,128,130,205,248,1,211,223,208,40,126,96,
-157,244,1,255,40,0,11,71,224,0,31,243,128,19,228,76,32,0,47,113,48,11,87,
-224,0,31,244,128,19,229,148,32,0,47,118,80,11,103,224,0,31,245,132,30,144,
-128,0,0,0,0,0,0,0,31,146,9,135,118,253,196,9,144,200,37,69,32,145,16,120,
-70,136,62,0,2,51,68,31,0,2,17,34,15,128,1,136,81,7,192,1,4,8,131,224,0,169,
-255,248,72,200,33,113,55,245,197,179,44,94,92,183,242,69,193,23,203,203,
-150,254,72,52,238,65,151,151,45,252,144,104,195,187,38,205,59,179,128,
-};
-#ifdef DUK_USE_BUILTIN_INITJS
-const duk_uint8_t duk_initjs_data[] = {
-40,102,117,110,99,116,105,111,110,40,100,44,97,41,123,102,117,110,99,116,
-105,111,110,32,98,40,97,44,98,44,99,41,123,79,98,106,101,99,116,46,100,101,
-102,105,110,101,80,114,111,112,101,114,116,121,40,97,44,98,44,123,118,97,
-108,117,101,58,99,44,119,114,105,116,97,98,108,101,58,33,48,44,101,110,117,
-109,101,114,97,98,108,101,58,33,49,44,99,111,110,102,105,103,117,114,97,98,
-108,101,58,33,48,125,41,125,98,40,97,46,76,111,103,103,101,114,44,34,99,
-108,111,103,34,44,110,101,119,32,97,46,76,111,103,103,101,114,40,34,67,34,
-41,41,59,98,40,97,44,34,109,111,100,76,111,97,100,101,100,34,44,123,125,41,
-125,41,40,116,104,105,115,44,68,117,107,116,97,112,101,41,59,10,0,
-};
-#endif  /* DUK_USE_BUILTIN_INITJS */
-#elif defined(DUK_USE_DOUBLE_ME)
-const duk_uint8_t duk_strings_data[] = {
-55,86,227,24,145,55,102,120,144,3,63,94,228,54,100,137,186,26,20,164,137,
-186,50,11,164,109,77,215,5,61,35,106,3,25,110,8,22,158,130,38,163,8,217,
-200,158,76,156,210,117,128,153,203,210,70,46,137,187,18,27,164,187,201,209,
-130,100,55,91,70,4,145,63,66,231,44,128,105,187,41,197,13,49,122,8,196,24,
-71,75,70,138,104,115,77,215,5,36,20,201,214,209,107,79,104,209,144,168,105,
-6,207,251,209,104,209,125,212,227,66,127,235,191,239,232,180,90,52,95,69,
-247,83,141,9,255,174,255,191,162,211,80,210,253,23,221,78,52,39,254,183,
-254,254,139,72,105,126,139,238,167,26,19,255,91,255,127,69,166,129,191,69,
-247,83,141,9,255,175,255,191,162,213,26,50,23,232,190,234,113,161,63,245,
-115,119,86,227,118,83,138,26,98,9,110,48,86,22,148,160,152,22,82,70,46,137,
-44,8,180,163,32,104,98,206,32,17,7,16,88,101,100,206,42,70,36,108,205,18,
-74,140,33,196,230,60,2,152,146,33,38,230,8,36,79,182,251,65,156,151,24,200,
-33,145,162,25,80,209,24,67,0,166,68,52,174,61,73,25,33,205,25,27,84,177,
-195,234,220,1,144,105,99,135,217,16,17,17,208,72,199,179,60,93,100,146,49,
-232,162,64,76,135,19,152,244,44,136,220,72,96,130,68,62,230,120,144,3,70,
-206,6,141,100,138,182,84,52,11,70,73,19,236,64,90,200,66,109,128,121,118,8,
-154,69,220,206,137,35,111,23,217,45,13,33,247,39,82,34,33,247,80,68,141,
-169,246,178,92,141,169,247,80,69,128,122,54,87,69,128,92,147,176,226,100,
-19,134,66,237,164,188,207,185,130,38,36,205,186,129,116,33,222,228,54,100,
-137,131,66,148,145,76,226,1,16,96,152,20,180,52,157,109,24,18,69,5,66,201,
-214,129,132,19,196,89,76,2,83,187,51,197,214,236,240,242,116,145,139,162,
-126,142,138,152,30,65,32,103,137,33,68,68,137,214,159,23,77,218,211,164,73,
-245,241,116,221,60,60,157,113,78,235,55,170,38,36,146,54,140,36,65,50,56,
-100,89,38,78,190,46,121,35,60,12,224,145,122,248,186,248,48,128,181,144,
-140,234,27,80,45,3,250,14,140,19,33,127,111,235,190,187,235,191,116,95,21,
-241,33,250,0,253,96,190,183,236,5,245,127,96,31,176,79,214,245,13,42,26,
-137,225,63,87,212,52,168,106,39,132,117,13,42,26,137,224,206,10,72,41,154,
-83,138,26,99,54,140,9,34,112,185,203,32,26,154,52,100,42,26,65,166,83,138,
-26,100,23,3,152,26,73,66,51,28,144,210,197,212,104,205,16,52,110,96,222,
-235,13,136,104,216,11,141,110,49,74,183,58,35,37,222,49,58,68,17,16,178,
-130,96,111,217,16,19,3,72,9,33,164,0,157,33,128,50,47,165,8,207,236,143,
-233,66,51,251,29,125,144,188,244,27,203,113,190,199,236,8,95,45,198,251,34,
-15,203,111,217,19,203,111,216,253,128,122,67,176,146,144,12,66,52,12,33,80,
-215,210,101,67,70,75,147,234,62,255,238,190,165,43,4,167,212,52,100,186,89,
-69,205,11,67,72,164,25,174,137,58,32,72,134,147,169,17,16,147,36,166,66,92,
-130,92,221,227,50,114,244,226,134,152,242,36,251,130,2,39,49,39,220,16,17,
-52,221,228,201,205,92,221,228,73,210,244,226,134,153,115,119,169,49,75,211,
-138,26,103,72,147,245,38,34,250,139,95,112,64,69,114,36,250,90,45,125,193,
-1,21,200,147,245,38,38,121,205,153,209,34,79,172,115,102,117,72,147,245,38,
-33,248,19,33,228,73,244,96,153,23,34,79,212,152,143,231,82,50,68,137,62,
-157,212,140,155,34,79,212,152,153,228,54,147,36,149,34,79,172,67,105,50,73,
-178,36,253,73,138,94,32,156,209,201,82,36,251,34,9,205,28,165,34,79,212,
-152,153,228,45,104,145,4,230,142,79,145,39,214,33,107,68,136,39,52,114,60,
-137,62,205,12,36,76,73,246,104,97,50,230,147,174,41,100,73,200,196,159,169,
-49,51,200,90,209,34,9,205,28,158,98,79,172,66,214,137,16,78,104,228,211,18,
-126,164,197,47,16,78,104,228,163,18,125,145,4,230,142,77,49,39,234,76,76,
-242,27,73,146,74,49,39,214,33,180,153,36,179,18,126,164,196,127,58,145,146,
-12,73,244,238,164,100,147,18,126,164,196,63,3,6,49,39,209,131,10,49,39,234,
-76,67,240,38,67,152,147,232,193,50,44,196,159,169,49,51,206,108,206,131,18,
-125,99,155,51,184,196,159,169,49,23,212,90,251,130,2,43,49,39,210,209,107,
-238,8,8,156,196,159,102,134,18,83,119,86,225,1,100,236,208,194,118,83,138,
-26,105,77,221,91,132,5,147,163,4,201,217,78,40,105,153,55,118,104,97,59,41,
-197,13,51,38,238,140,19,39,101,56,161,166,27,93,97,250,147,17,94,8,200,139,
-155,186,248,144,72,146,28,214,205,221,37,222,230,145,179,64,22,121,187,165,
-69,200,56,249,238,146,38,138,147,72,105,80,212,79,17,243,72,96,77,21,38,
-144,210,161,168,158,7,214,131,173,79,152,134,234,160,93,8,159,48,23,213,64,
-186,16,210,160,101,56,146,113,67,35,55,117,110,16,22,78,209,239,36,122,32,
-72,139,155,187,71,188,145,232,129,34,70,110,234,220,32,44,157,91,172,72,
-244,64,145,23,55,117,110,177,35,209,2,68,76,168,25,78,40,105,139,39,173,19,
-52,136,8,136,231,137,30,176,8,133,96,38,35,181,110,16,22,78,137,204,120,34,
-69,8,224,143,68,225,147,160,153,132,112,71,160,155,11,23,51,162,56,35,209,
-56,100,92,72,58,8,157,138,12,121,154,36,29,4,67,21,11,153,34,54,1,231,43,
-163,210,0,71,36,156,194,20,149,36,112,181,130,83,234,26,50,95,174,41,208,
-209,146,253,113,79,70,200,232,44,205,39,173,2,33,36,232,204,178,90,4,66,
-200,232,44,207,18,84,145,145,8,250,72,227,123,158,68,185,13,48,156,209,2,
-103,68,186,8,196,24,72,34,106,48,141,156,140,32,45,100,137,2,134,140,130,2,
-214,80,61,235,197,31,23,60,145,158,58,137,116,141,163,9,16,5,100,106,37,
-215,197,211,116,240,242,117,197,113,193,46,186,205,235,226,231,146,51,193,
-234,5,208,157,113,93,55,117,110,16,22,78,202,113,67,76,137,187,178,156,80,
-211,44,78,108,167,26,10,110,136,228,73,140,196,154,136,218,48,145,0,86,70,
-9,205,42,13,72,128,43,34,45,20,76,1,89,11,80,46,132,34,137,137,49,18,233,
-47,50,54,72,10,200,132,75,165,139,178,70,161,18,236,136,5,144,113,124,73,
-82,54,125,37,230,70,201,14,108,140,88,144,153,33,36,64,46,3,33,80,210,117,
-241,115,201,25,160,146,112,200,84,52,157,124,92,242,70,120,48,162,64,76,
-147,49,39,215,89,189,124,92,242,70,120,235,64,194,75,6,36,250,235,55,175,
-139,158,72,207,29,25,36,40,161,243,116,92,98,79,175,139,166,233,225,228,
-235,138,151,197,211,116,240,242,25,100,105,166,114,129,100,140,202,248,161,
-179,69,26,73,8,15,33,137,33,1,228,145,26,39,12,158,164,80,47,57,143,115,72,
-217,164,141,19,134,79,82,40,144,200,39,12,158,164,80,47,57,143,115,72,217,
-164,100,19,134,79,82,40,66,37,210,161,168,153,10,137,117,160,235,84,240,70,
-68,233,86,224,77,15,4,100,78,161,179,33,42,5,163,212,138,9,232,197,209,79,
-103,135,147,164,140,93,21,246,88,108,193,126,146,49,116,93,216,144,164,137,
-26,34,116,145,139,162,174,196,13,49,58,72,197,209,79,73,80,47,164,140,93,
-18,134,36,2,136,32,72,133,16,38,35,160,78,108,208,218,17,3,32,104,99,18,39,
-25,10,10,46,102,25,22,73,144,67,113,8,185,16,229,67,64,181,224,101,116,80,
-90,52,83,67,154,36,20,72,106,144,217,76,13,17,28,81,180,150,52,73,58,69,
-166,149,145,49,28,147,58,36,89,158,46,176,231,28,26,120,121,28,81,212,17,
-37,92,129,150,199,66,200,75,34,103,40,150,9,72,162,115,101,50,17,180,97,
-137,119,186,51,57,47,50,52,114,50,24,247,70,101,149,30,72,145,180,90,201,
-56,208,133,40,23,34,41,12,122,200,194,54,114,74,27,50,68,160,17,6,178,76,
-239,0,148,3,16,239,138,42,9,145,47,139,166,65,76,131,51,232,21,160,70,148,
-193,52,8,184,65,22,48,
-};
+	if (st->heavy) {
+		duk_fb_sprintf(fb, "(%p)", (void *) tv);
+	}
 
-/* to convert a heap stridx to a token number, subtract
- * DUK_STRIDX_START_RESERVED and add DUK_TOK_START_RESERVED.
- */
+	if (!tv) {
+		duk_fb_put_cstring(fb, "NULL");
+		return;
+	}
 
-/* native functions: 129 */
-const duk_c_function duk_bi_native_functions[] = {
-	duk_bi_array_constructor,
-	duk_bi_array_constructor_is_array,
-	duk_bi_array_prototype_concat,
-	duk_bi_array_prototype_indexof_shared,
-	duk_bi_array_prototype_iter_shared,
-	duk_bi_array_prototype_join_shared,
-	duk_bi_array_prototype_pop,
-	duk_bi_array_prototype_push,
-	duk_bi_array_prototype_reduce_shared,
-	duk_bi_array_prototype_reverse,
-	duk_bi_array_prototype_shift,
-	duk_bi_array_prototype_slice,
-	duk_bi_array_prototype_sort,
-	duk_bi_array_prototype_splice,
-	duk_bi_array_prototype_to_string,
-	duk_bi_array_prototype_unshift,
-	duk_bi_boolean_constructor,
-	duk_bi_boolean_prototype_tostring_shared,
-	duk_bi_buffer_constructor,
-	duk_bi_buffer_prototype_tostring_shared,
-	duk_bi_date_constructor,
-	duk_bi_date_constructor_now,
-	duk_bi_date_constructor_parse,
-	duk_bi_date_constructor_utc,
-	duk_bi_date_prototype_get_shared,
-	duk_bi_date_prototype_get_timezone_offset,
-	duk_bi_date_prototype_set_shared,
-	duk_bi_date_prototype_set_time,
-	duk_bi_date_prototype_to_json,
-	duk_bi_date_prototype_tostring_shared,
-	duk_bi_date_prototype_value_of,
-	duk_bi_duktape_object_act,
-	duk_bi_duktape_object_compact,
-	duk_bi_duktape_object_dec,
-	duk_bi_duktape_object_enc,
-	duk_bi_duktape_object_fin,
-	duk_bi_duktape_object_gc,
-	duk_bi_duktape_object_info,
-	duk_bi_error_constructor_shared,
-	duk_bi_error_prototype_filename_getter,
-	duk_bi_error_prototype_linenumber_getter,
-	duk_bi_error_prototype_nop_setter,
-	duk_bi_error_prototype_stack_getter,
-	duk_bi_error_prototype_to_string,
-	duk_bi_function_constructor,
-	duk_bi_function_prototype,
-	duk_bi_function_prototype_apply,
-	duk_bi_function_prototype_bind,
-	duk_bi_function_prototype_call,
-	duk_bi_function_prototype_to_string,
-	duk_bi_global_object_alert,
-	duk_bi_global_object_decode_uri,
-	duk_bi_global_object_decode_uri_component,
-	duk_bi_global_object_encode_uri,
-	duk_bi_global_object_encode_uri_component,
-	duk_bi_global_object_escape,
-	duk_bi_global_object_eval,
-	duk_bi_global_object_is_finite,
-	duk_bi_global_object_is_nan,
-	duk_bi_global_object_parse_float,
-	duk_bi_global_object_parse_int,
-	duk_bi_global_object_print,
-	duk_bi_global_object_require,
-	duk_bi_global_object_unescape,
-	duk_bi_json_object_parse,
-	duk_bi_json_object_stringify,
-	duk_bi_logger_constructor,
-	duk_bi_logger_prototype_fmt,
-	duk_bi_logger_prototype_log_shared,
-	duk_bi_logger_prototype_raw,
-	duk_bi_math_object_max,
-	duk_bi_math_object_min,
-	duk_bi_math_object_onearg_shared,
-	duk_bi_math_object_random,
-	duk_bi_math_object_twoarg_shared,
-	duk_bi_number_constructor,
-	duk_bi_number_prototype_to_exponential,
-	duk_bi_number_prototype_to_fixed,
-	duk_bi_number_prototype_to_locale_string,
-	duk_bi_number_prototype_to_precision,
-	duk_bi_number_prototype_to_string,
-	duk_bi_number_prototype_value_of,
-	duk_bi_object_constructor,
-	duk_bi_object_constructor_create,
-	duk_bi_object_constructor_define_properties,
-	duk_bi_object_constructor_define_property,
-	duk_bi_object_constructor_get_own_property_descriptor,
-	duk_bi_object_constructor_is_extensible,
-	duk_bi_object_constructor_is_sealed_frozen_shared,
-	duk_bi_object_constructor_keys_shared,
-	duk_bi_object_constructor_prevent_extensions,
-	duk_bi_object_constructor_seal_freeze_shared,
-	duk_bi_object_getprototype_shared,
-	duk_bi_object_prototype_has_own_property,
-	duk_bi_object_prototype_is_prototype_of,
-	duk_bi_object_prototype_property_is_enumerable,
-	duk_bi_object_prototype_to_locale_string,
-	duk_bi_object_prototype_to_string,
-	duk_bi_object_prototype_value_of,
-	duk_bi_object_setprototype_shared,
-	duk_bi_pointer_constructor,
-	duk_bi_pointer_prototype_tostring_shared,
-	duk_bi_proxy_constructor,
-	duk_bi_regexp_constructor,
-	duk_bi_regexp_prototype_exec,
-	duk_bi_regexp_prototype_test,
-	duk_bi_regexp_prototype_to_string,
-	duk_bi_string_constructor,
-	duk_bi_string_constructor_from_char_code,
-	duk_bi_string_prototype_caseconv_shared,
-	duk_bi_string_prototype_char_at,
-	duk_bi_string_prototype_char_code_at,
-	duk_bi_string_prototype_concat,
-	duk_bi_string_prototype_indexof_shared,
-	duk_bi_string_prototype_locale_compare,
-	duk_bi_string_prototype_match,
-	duk_bi_string_prototype_replace,
-	duk_bi_string_prototype_search,
-	duk_bi_string_prototype_slice,
-	duk_bi_string_prototype_split,
-	duk_bi_string_prototype_substr,
-	duk_bi_string_prototype_substring,
-	duk_bi_string_prototype_to_string,
-	duk_bi_string_prototype_trim,
-	duk_bi_thread_constructor,
-	duk_bi_thread_current,
-	duk_bi_thread_resume,
-	duk_bi_thread_yield,
-	duk_bi_type_error_thrower,
-};
+	if (st->binary) {
+		duk_size_t i;
+		duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_LBRACKET);
+		for (i = 0; i < (duk_size_t) sizeof(*tv); i++) {
+			duk_fb_sprintf(fb, "%02lx", (unsigned long) ((duk_uint8_t *)tv)[i]);
+		}
+		duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_RBRACKET);
+	}
 
-const duk_uint8_t duk_builtins_data[] = {
-105,195,74,144,77,40,105,44,9,124,104,45,3,3,72,0,71,225,65,165,172,33,243,
-6,145,0,122,24,210,150,14,249,35,120,160,55,226,13,76,224,196,177,164,152,
-22,192,4,202,52,147,72,152,0,169,70,146,105,11,0,23,40,210,77,32,96,3,37,
-26,73,163,236,0,108,163,73,52,121,128,14,148,105,38,142,176,1,242,144,56,
-209,0,84,6,166,98,242,80,210,248,1,250,67,72,144,15,232,13,44,128,47,162,
-52,161,0,62,80,160,255,253,102,76,0,0,15,135,240,0,0,0,3,84,0,0,15,7,240,0,
-0,0,3,124,64,153,132,18,49,2,38,48,64,200,7,153,64,227,48,26,103,3,13,0,89,
-165,34,53,36,38,180,128,216,143,155,81,227,114,58,111,2,142,0,73,194,94,56,
-202,167,33,209,195,130,70,207,17,26,59,36,100,232,145,131,146,69,204,201,
-22,52,36,84,212,145,67,98,68,205,201,18,63,36,68,244,122,32,100,60,87,62,
-39,255,254,9,46,24,0,10,31,224,29,13,92,40,0,9,101,141,32,0,48,197,100,66,
-214,73,10,83,68,37,85,144,133,68,65,214,201,6,91,40,0,12,21,104,144,69,130,
-64,214,10,0,3,2,87,36,5,100,160,0,63,254,16,37,135,92,99,25,242,194,7,195,
-0,30,236,64,123,46,145,234,188,71,162,249,5,23,240,0,15,241,0,17,242,98,7,
-153,114,30,70,7,207,18,243,225,71,252,0,93,192,36,15,241,128,85,242,28,7,
-192,40,64,0,93,160,71,206,192,82,58,193,128,234,7,62,116,132,129,208,20,7,
-56,90,28,193,132,114,134,175,57,3,207,156,96,103,224,0,46,32,51,255,255,
-247,8,33,163,128,16,212,0,5,190,8,106,0,4,222,4,53,0,3,110,130,26,128,2,55,
-2,15,192,0,91,97,7,255,255,226,147,248,0,182,155,15,131,252,128,73,144,128,
-202,62,94,128,247,122,3,101,184,141,134,242,59,92,15,156,110,38,142,39,19,
-80,0,22,187,145,26,206,100,106,186,33,168,234,71,59,178,26,110,232,105,60,
-161,162,218,6,131,104,25,237,161,0,1,103,54,132,0,5,154,246,6,99,194,5,47,
-240,0,15,242,129,38,70,9,242,34,16,0,23,184,136,5,55,241,89,112,63,255,251,
-223,255,255,255,255,217,80,0,0,0,0,0,64,0,0,25,48,0,0,62,31,192,0,0,0,24,
-240,0,0,60,31,192,0,0,0,25,16,0,0,60,63,192,0,0,0,0,15,243,1,38,64,0,0,0,0,
-0,0,0,0,25,242,160,71,194,113,30,234,32,99,38,145,138,152,70,34,121,5,63,
-240,3,97,139,17,132,47,252,193,21,0,127,156,9,50,64,0,7,195,248,0,0,0,5,
-175,145,208,128,52,48,7,66,0,80,191,29,8,2,67,224,116,32,29,11,225,208,128,
-84,47,71,66,1,144,155,29,8,3,2,104,116,32,140,73,145,194,61,199,128,188,30,
-2,236,96,32,1,11,161,128,46,70,2,32,16,184,24,8,128,2,220,96,36,1,139,97,
-128,144,2,45,70,2,224,16,180,24,11,128,2,204,96,38,1,11,33,128,152,0,44,70,
-2,128,16,176,24,10,0,2,188,96,42,1,10,225,128,168,0,43,70,2,192,16,172,24,
-11,0,2,172,100,10,161,178,42,70,138,34,16,168,26,40,136,2,156,105,124,132,
-33,76,52,190,66,0,165,26,127,49,8,82,13,63,152,128,40,198,167,208,66,20,67,
-83,232,32,10,17,162,136,4,40,6,138,32,0,159,26,95,32,8,79,13,47,144,0,39,
-70,159,204,2,83,131,79,230,0,41,129,128,128,12,37,198,138,100,2,42,63,128,
-0,127,160,49,38,8,24,0,64,82,112,145,224,120,201,40,201,24,201,9,0,0,0,0,0,
-0,0,0,1,165,90,8,148,105,35,229,168,2,167,248,0,7,250,66,163,8,22,139,32,
-49,77,202,138,74,46,78,82,80,114,130,144,95,37,96,21,95,192,1,63,212,9,24,
-82,36,89,1,128,21,127,192,1,63,214,9,24,82,20,89,1,128,21,159,192,1,63,216,
-9,24,82,4,89,1,128,21,191,192,1,63,218,9,24,81,244,89,1,128,21,223,192,1,
-63,220,9,24,81,228,89,1,128,21,255,192,1,63,222,9,24,81,212,89,1,128,15,
-255,200,69,64,10,191,5,64,105,87,20,139,68,192,177,107,2,64,22,85,181,187,
-68,64,66,46,230,63,239,57,250,254,67,192,71,21,247,63,254,130,43,101,67,64,
-123,203,219,63,14,229,38,21,66,192,251,33,9,64,24,45,68,84,66,64,158,160,
-230,63,205,59,127,102,65,192,158,160,246,63,205,59,127,102,73,4,144,68,10,
-65,64,0,80,9,5,0,2,63,164,20,0,12,252,148,131,234,65,64,1,15,137,5,0,5,61,
-164,20,0,24,244,144,80,0,115,202,65,64,2,15,8,203,199,116,117,227,178,82,
-64,0,78,169,32,58,36,20,0,36,230,144,80,0,163,146,65,64,2,206,41,5,0,12,15,
-255,192,9,134,128,131,130,11,5,255,240,0,23,255,192,0,63,255,20,105,0,0,
-194,69,0,0,0,0,0,6,115,128,142,144,9,202,0,58,199,25,146,144,100,62,65,137,
-33,6,4,99,194,242,33,225,113,8,240,164,128,130,205,248,1,211,223,208,40,
-126,96,157,244,1,255,40,0,11,71,224,0,31,243,128,19,228,76,32,0,47,113,48,
-11,87,224,0,31,244,128,19,229,148,32,0,47,118,80,11,103,224,0,31,245,132,
-30,144,0,0,0,128,0,0,0,0,31,146,9,135,118,253,196,9,144,200,37,69,32,145,
-16,120,70,136,62,0,2,51,68,31,0,2,17,34,15,128,1,136,81,7,192,1,4,8,131,
-224,0,169,255,248,72,200,33,113,55,245,197,179,44,94,92,183,242,69,193,23,
-203,203,150,254,72,52,238,65,151,151,45,252,144,104,195,187,38,205,59,179,
-128,
-};
-#ifdef DUK_USE_BUILTIN_INITJS
-const duk_uint8_t duk_initjs_data[] = {
-40,102,117,110,99,116,105,111,110,40,100,44,97,41,123,102,117,110,99,116,
-105,111,110,32,98,40,97,44,98,44,99,41,123,79,98,106,101,99,116,46,100,101,
-102,105,110,101,80,114,111,112,101,114,116,121,40,97,44,98,44,123,118,97,
-108,117,101,58,99,44,119,114,105,116,97,98,108,101,58,33,48,44,101,110,117,
-109,101,114,97,98,108,101,58,33,49,44,99,111,110,102,105,103,117,114,97,98,
-108,101,58,33,48,125,41,125,98,40,97,46,76,111,103,103,101,114,44,34,99,
-108,111,103,34,44,110,101,119,32,97,46,76,111,103,103,101,114,40,34,67,34,
-41,41,59,98,40,97,44,34,109,111,100,76,111,97,100,101,100,34,44,123,125,41,
-125,41,40,116,104,105,115,44,68,117,107,116,97,112,101,41,59,10,0,
-};
-#endif  /* DUK_USE_BUILTIN_INITJS */
-#else
-#error invalid endianness defines
+	if (st->heavy) {
+		duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_LANGLE);
+	}
+	switch (DUK_TVAL_GET_TAG(tv)) {
+	case DUK_TAG_UNDEFINED: {
+		duk_fb_put_cstring(fb, "undefined");
+		break;
+	}
+	case DUK_TAG_UNUSED: {
+		duk_fb_put_cstring(fb, "unused");
+		break;
+	}
+	case DUK_TAG_NULL: {
+		duk_fb_put_cstring(fb, "null");
+		break;
+	}
+	case DUK_TAG_BOOLEAN: {
+		duk_fb_put_cstring(fb, DUK_TVAL_GET_BOOLEAN(tv) ? "true" : "false");
+		break;
+	}
+	case DUK_TAG_STRING: {
+		/* Note: string is a terminal heap object, so no depth check here */
+		duk__print_hstring(st, DUK_TVAL_GET_STRING(tv), 1);
+		break;
+	}
+	case DUK_TAG_OBJECT: {
+		duk__print_hobject(st, DUK_TVAL_GET_OBJECT(tv));
+		break;
+	}
+	case DUK_TAG_BUFFER: {
+		duk__print_hbuffer(st, DUK_TVAL_GET_BUFFER(tv));
+		break;
+	}
+	case DUK_TAG_POINTER: {
+		duk_fb_sprintf(fb, "pointer:%p", (void *) DUK_TVAL_GET_POINTER(tv));
+		break;
+	}
+	case DUK_TAG_LIGHTFUNC: {
+		duk_c_function func;
+		duk_small_uint_t lf_flags;
+
+		DUK_TVAL_GET_LIGHTFUNC(tv, func, lf_flags);
+		duk_fb_sprintf(fb, "lightfunc:");
+		duk_fb_put_funcptr(fb, (duk_uint8_t *) &func, sizeof(func));
+		duk_fb_sprintf(fb, ":%04lx", (long) lf_flags);
+		break;
+	}
+#if defined(DUK_USE_FASTINT)
+	case DUK_TAG_FASTINT:
 #endif
-#line 1 "duk_debug_fixedbuffer.c"
-/*
- *  Fixed buffer helper useful for debugging, requires no allocation
- *  which is critical for debugging.
- */
+	default: {
+		/* IEEE double is approximately 16 decimal digits; print a couple extra */
+		DUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv));
+		DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));
+		duk_fb_sprintf(fb, "%.18g", (double) DUK_TVAL_GET_NUMBER(tv));
+		break;
+	}
+	}
+	if (st->heavy) {
+		duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_RANGLE);
+	}
+}
 
-/* include removed: duk_internal.h */
+DUK_LOCAL void duk__print_instr(duk__dprint_state *st, duk_instr_t ins) {
+	duk_fixedbuffer *fb = st->fb;
+	duk_small_int_t op;
+	const char *op_name;
+	const char *extraop_name;
 
-#ifdef DUK_USE_DEBUG
+	op = (duk_small_int_t) DUK_DEC_OP(ins);
+	op_name = duk__bc_optab[op];
 
-void duk_fb_put_bytes(duk_fixedbuffer *fb, duk_uint8_t *buffer, duk_size_t length) {
-	duk_size_t avail;
-	duk_size_t copylen;
+	/* XXX: option to fix opcode length so it lines up nicely */
 
-	avail = (fb->offset >= fb->length ? (duk_size_t) 0 : (duk_size_t) (fb->length - fb->offset));
-	if (length > avail) {
-		copylen = avail;
-		fb->truncated = 1;
+	if (op == DUK_OP_EXTRA) {
+		extraop_name = duk__bc_extraoptab[DUK_DEC_A(ins)];
+
+		duk_fb_sprintf(fb, "%s %ld, %ld",
+		               (const char *) extraop_name, (long) DUK_DEC_B(ins), (long) DUK_DEC_C(ins));
+	} else if (op == DUK_OP_JUMP) {
+		duk_int_t diff1 = DUK_DEC_ABC(ins) - DUK_BC_JUMP_BIAS;  /* from next pc */
+		duk_int_t diff2 = diff1 + 1;                            /* from curr pc */
+
+		duk_fb_sprintf(fb, "%s %ld (to pc%c%ld)",
+		               (const char *) op_name, (long) diff1,
+		               (int) (diff2 >= 0 ? '+' : '-'),  /* char format: use int */
+		               (long) (diff2 >= 0 ? diff2 : -diff2));
 	} else {
-		copylen = length;
+		duk_fb_sprintf(fb, "%s %ld, %ld, %ld",
+		               (const char *) op_name, (long) DUK_DEC_A(ins),
+		               (long) DUK_DEC_B(ins), (long) DUK_DEC_C(ins));
 	}
-	DUK_MEMCPY(fb->buffer + fb->offset, buffer, copylen);
-	fb->offset += copylen;
 }
 
-void duk_fb_put_byte(duk_fixedbuffer *fb, duk_uint8_t x) {
-	duk_fb_put_bytes(fb, &x, 1);
-}
+DUK_LOCAL void duk__print_opcode(duk__dprint_state *st, duk_small_int_t opcode) {
+	duk_fixedbuffer *fb = st->fb;
 
-void duk_fb_put_cstring(duk_fixedbuffer *fb, const char *x) {
-	duk_fb_put_bytes(fb, (duk_uint8_t *) x, (duk_size_t) DUK_STRLEN(x));
+	if (opcode < DUK_BC_OP_MIN || opcode > DUK_BC_OP_MAX) {
+		duk_fb_sprintf(fb, "?(%ld)", (long) opcode);
+	} else {
+		duk_fb_sprintf(fb, "%s", (const char *) duk__bc_optab[opcode]);
+	}
 }
 
-void duk_fb_sprintf(duk_fixedbuffer *fb, const char *fmt, ...) {
-	duk_size_t avail;
-	va_list ap;
+DUK_INTERNAL duk_int_t duk_debug_vsnprintf(char *str, duk_size_t size, const char *format, va_list ap) {
+	duk_fixedbuffer fb;
+	const char *p = format;
+	const char *p_end = p + DUK_STRLEN(format);
+	duk_int_t retval;
 
-	va_start(ap, fmt);
-	avail = (fb->offset >= fb->length ? (duk_size_t) 0 : (duk_size_t) (fb->length - fb->offset));
-	if (avail > 0) {
-		duk_int_t res = (duk_int_t) DUK_VSNPRINTF((char *) (fb->buffer + fb->offset), avail, fmt, ap);
-		if (res < 0) {
-			/* error */
-		} else if ((duk_size_t) res >= avail) {
-			/* (maybe) truncated */
-			fb->offset += avail;
-			if ((duk_size_t) res > avail) {
-				/* actual chars dropped (not just NUL term) */
-				fb->truncated = 1;
+	DUK_MEMZERO(&fb, sizeof(fb));
+	fb.buffer = (duk_uint8_t *) str;
+	fb.length = size;
+	fb.offset = 0;
+	fb.truncated = 0;
+
+	while (p < p_end) {
+		char ch = *p++;
+		const char *p_begfmt = NULL;
+		duk_bool_t got_exclamation = 0;
+		duk_bool_t got_long = 0;  /* %lf, %ld etc */
+		duk__dprint_state st;
+
+		if (ch != DUK_ASC_PERCENT) {
+			duk_fb_put_byte(&fb, (duk_uint8_t) ch);
+			continue;
+		}
+
+		/*
+		 *  Format tag parsing.  Since we don't understand all the
+		 *  possible format tags allowed, we just scan for a terminating
+		 *  specifier and keep track of relevant modifiers that we do
+		 *  understand.  See man 3 printf.
+		 */
+
+		DUK_MEMZERO(&st, sizeof(st));
+		st.fb = &fb;
+		st.depth = 0;
+		st.depth_limit = 1;
+		st.loop_stack_index = 0;
+		st.loop_stack_limit = DUK__LOOP_STACK_DEPTH;
+
+		p_begfmt = p - 1;
+		while (p < p_end) {
+			ch = *p++;
+
+			if (ch == DUK_ASC_STAR) {
+				/* unsupported: would consume multiple args */
+				goto error;
+			} else if (ch == DUK_ASC_PERCENT) {
+				duk_fb_put_byte(&fb, (duk_uint8_t) DUK_ASC_PERCENT);
+				break;
+			} else if (ch == DUK_ASC_EXCLAMATION) {
+				got_exclamation = 1;
+			} else if (!got_exclamation && ch == DUK_ASC_LC_L) {
+				got_long = 1;
+			} else if (got_exclamation && ch == DUK_ASC_LC_D) {
+				st.depth_limit = DUK__DEEP_DEPTH_LIMIT;
+			} else if (got_exclamation && ch == DUK_ASC_LC_P) {
+				st.follow_proto = 1;
+			} else if (got_exclamation && ch == DUK_ASC_LC_I) {
+				st.internal = 1;
+			} else if (got_exclamation && ch == DUK_ASC_LC_X) {
+				st.hexdump = 1;
+			} else if (got_exclamation && ch == DUK_ASC_LC_H) {
+				st.heavy = 1;
+			} else if (got_exclamation && ch == DUK_ASC_ATSIGN) {
+				st.pointer = 1;
+			} else if (got_exclamation && ch == DUK_ASC_HASH) {
+				st.binary = 1;
+			} else if (got_exclamation && ch == DUK_ASC_UC_T) {
+				duk_tval *t = va_arg(ap, duk_tval *);
+				if (st.pointer && !st.heavy) {
+					duk_fb_sprintf(&fb, "(%p)", (void *) t);
+				}
+				duk__print_tval(&st, t);
+				break;
+			} else if (got_exclamation && ch == DUK_ASC_UC_O) {
+				duk_heaphdr *t = va_arg(ap, duk_heaphdr *);
+				if (st.pointer && !st.heavy) {
+					duk_fb_sprintf(&fb, "(%p)", (void *) t);
+				}
+				duk__print_heaphdr(&st, t);
+				break;
+			} else if (got_exclamation && ch == DUK_ASC_UC_I) {
+				duk_instr_t t = va_arg(ap, duk_instr_t);
+				duk__print_instr(&st, t);
+				break;
+			} else if (got_exclamation && ch == DUK_ASC_UC_C) {
+				long t = va_arg(ap, long);
+				duk__print_opcode(&st, (duk_small_int_t) t);
+				break;
+			} else if (!got_exclamation && strchr(DUK__ALLOWED_STANDARD_SPECIFIERS, (int) ch)) {
+				char fmtbuf[DUK__MAX_FORMAT_TAG_LENGTH];
+				duk_size_t fmtlen;
+
+				DUK_ASSERT(p >= p_begfmt);
+				fmtlen = (duk_size_t) (p - p_begfmt);
+				if (fmtlen >= sizeof(fmtbuf)) {
+					/* format is too large, abort */
+					goto error;
+				}
+				DUK_MEMZERO(fmtbuf, sizeof(fmtbuf));
+				DUK_MEMCPY(fmtbuf, p_begfmt, fmtlen);
+
+				/* assume exactly 1 arg, which is why '*' is forbidden; arg size still
+				 * depends on type though.
+				 */
+
+				if (ch == DUK_ASC_LC_F || ch == DUK_ASC_LC_G || ch == DUK_ASC_LC_E) {
+					/* %f and %lf both consume a 'long' */
+					double arg = va_arg(ap, double);
+					duk_fb_sprintf(&fb, fmtbuf, arg);
+				} else if (ch == DUK_ASC_LC_D && got_long) {
+					/* %ld */
+					long arg = va_arg(ap, long);
+					duk_fb_sprintf(&fb, fmtbuf, arg);
+				} else if (ch == DUK_ASC_LC_D) {
+					/* %d; only 16 bits are guaranteed */
+					int arg = va_arg(ap, int);
+					duk_fb_sprintf(&fb, fmtbuf, arg);
+				} else if (ch == DUK_ASC_LC_U && got_long) {
+					/* %lu */
+					unsigned long arg = va_arg(ap, unsigned long);
+					duk_fb_sprintf(&fb, fmtbuf, arg);
+				} else if (ch == DUK_ASC_LC_U) {
+					/* %u; only 16 bits are guaranteed */
+					unsigned int arg = va_arg(ap, unsigned int);
+					duk_fb_sprintf(&fb, fmtbuf, arg);
+				} else if (ch == DUK_ASC_LC_X && got_long) {
+					/* %lx */
+					unsigned long arg = va_arg(ap, unsigned long);
+					duk_fb_sprintf(&fb, fmtbuf, arg);
+				} else if (ch == DUK_ASC_LC_X) {
+					/* %x; only 16 bits are guaranteed */
+					unsigned int arg = va_arg(ap, unsigned int);
+					duk_fb_sprintf(&fb, fmtbuf, arg);
+				} else if (ch == DUK_ASC_LC_S) {
+					/* %s */
+					const char *arg = va_arg(ap, const char *);
+					if (arg == NULL) {
+						/* '%s' and NULL is not portable, so special case
+						 * it for debug printing.
+						 */
+						duk_fb_sprintf(&fb, "NULL");
+					} else {
+						duk_fb_sprintf(&fb, fmtbuf, arg);
+					}
+				} else if (ch == DUK_ASC_LC_P) {
+					/* %p */
+					void *arg = va_arg(ap, void *);
+					if (arg == NULL) {
+						/* '%p' and NULL is portable, but special case it
+						 * anyway to get a standard NULL marker in logs.
+						 */
+						duk_fb_sprintf(&fb, "NULL");
+					} else {
+						duk_fb_sprintf(&fb, fmtbuf, arg);
+					}
+				} else if (ch == DUK_ASC_LC_C) {
+					/* '%c', passed concretely as int */
+					int arg = va_arg(ap, int);
+					duk_fb_sprintf(&fb, fmtbuf, arg);
+				} else {
+					/* Should not happen. */
+					duk_fb_sprintf(&fb, "INVALID-FORMAT(%s)", (const char *) fmtbuf);
+				}
+				break;
+			} else {
+				/* ignore */
 			}
-		} else {
-			/* normal */
-			fb->offset += res;
 		}
 	}
+	goto done;
+
+ error:
+	duk_fb_put_cstring(&fb, "FMTERR");
+	/* fall through */
+
+ done:
+	retval = (duk_int_t) fb.offset;
+	duk_fb_put_byte(&fb, (duk_uint8_t) 0);
+
+	/* return total chars written excluding terminator */
+	return retval;
+}
+
+#if 0  /*unused*/
+DUK_INTERNAL duk_int_t duk_debug_snprintf(char *str, duk_size_t size, const char *format, ...) {
+	duk_int_t retval;
+	va_list ap;
+	va_start(ap, format);
+	retval = duk_debug_vsnprintf(str, size, format, ap);
 	va_end(ap);
+	return retval;
 }
+#endif
 
-duk_bool_t duk_fb_is_full(duk_fixedbuffer *fb) {
-	return (fb->offset >= fb->length);
+/* Formatting function pointers is tricky: there is no standard pointer for
+ * function pointers and the size of a function pointer may depend on the
+ * specific pointer type.  This helper formats a function pointer based on
+ * its memory layout to get something useful on most platforms.
+ */
+DUK_INTERNAL void duk_debug_format_funcptr(char *buf, duk_size_t buf_size, duk_uint8_t *fptr, duk_size_t fptr_size) {
+	duk_size_t i;
+	duk_uint8_t *p = (duk_uint8_t *) buf;
+	duk_uint8_t *p_end = (duk_uint8_t *) (buf + buf_size - 1);
+
+	DUK_MEMZERO(buf, buf_size);
+
+	for (i = 0; i < fptr_size; i++) {
+		duk_int_t left = (duk_int_t) (p_end - p);
+		duk_uint8_t ch;
+		if (left <= 0) {
+			break;
+		}
+
+		/* Quite approximate but should be useful for little and big endian. */
+#ifdef DUK_USE_INTEGER_BE
+		ch = fptr[i];
+#else
+		ch = fptr[fptr_size - 1 - i];
+#endif
+		p += DUK_SNPRINTF((char *) p, left, "%02lx", (unsigned long) ch);
+	}
 }
 
 #endif  /* DUK_USE_DEBUG */
-#line 1 "duk_debug_heap.c"
+#line 1 "duk_debugger.c"
 /*
- *  Debug dumping of duk_heap.
+ *  Duktape debugger
  */
 
 /* include removed: duk_internal.h */
 
-#ifdef DUK_USE_DEBUG
+#if defined(DUK_USE_DEBUGGER_SUPPORT)
 
-static void duk__sanitize_snippet(char *buf, duk_size_t buf_size, duk_hstring *str) {
-	duk_size_t i;
-	duk_size_t nchars;
-	duk_size_t maxchars;
-	duk_uint8_t *data;
+/*
+ *  Helper structs
+ */
 
-	DUK_MEMZERO(buf, buf_size);
+typedef union {
+	void *p;
+	duk_uint_t b[1];
+	/* Use b[] to access the size of the union, which is strictly not
+	 * correct.  Can't use fixed size unless there's feature detection
+	 * for pointer byte size.
+	 */
+} duk__ptr_union;
 
-	maxchars = (duk_size_t) (buf_size - 1);
-	data = DUK_HSTRING_GET_DATA(str);
-	nchars = ((duk_size_t) str->blen < maxchars ? (duk_size_t) str->blen : maxchars);
-	for (i = 0; i < nchars; i++) {
-		duk_small_int_t c = (duk_small_int_t) data[i];
-		if (c < 0x20 || c > 0x7e) {
-			c = '.';
-		}
-		buf[i] = (char) c;
+/*
+ *  Detach handling
+ */
+
+#define DUK__SET_CONN_BROKEN(thr,reason) do { \
+		/* For now shared handler is fine. */ \
+		duk__debug_do_detach1((thr)->heap, (reason)); \
+	} while (0)
+
+DUK_LOCAL void duk__debug_do_detach1(duk_heap *heap, duk_int_t reason) {
+	/* Can be called multiple times with no harm.  Mark the transport
+	 * bad (dbg_read_cb == NULL) and clear state except for the detached
+	 * callback and the udata field.  The detached callback is delayed
+	 * to the message loop so that it can be called between messages;
+	 * this avoids corner cases related to immediate debugger reattach
+	 * inside the detached callback.
+	 */
+
+	if (heap->dbg_detaching) {
+		return;
 	}
+
+	DUK_D(DUK_DPRINT("debugger transport detaching, marking transport broken"));
+
+	heap->dbg_detaching = 1;  /* prevent multiple in-progress detaches */
+
+	if (heap->dbg_write_cb != NULL) {
+		duk_hthread *thr;
+
+		thr = heap->heap_thread;
+		DUK_ASSERT(thr != NULL);
+
+		duk_debug_write_notify(thr, DUK_DBG_CMD_DETACHING);
+		duk_debug_write_int(thr, reason);
+		duk_debug_write_eom(thr);
+	}
+
+	heap->dbg_read_cb = NULL;
+	heap->dbg_write_cb = NULL;
+	heap->dbg_peek_cb = NULL;
+	heap->dbg_read_flush_cb = NULL;
+	heap->dbg_write_flush_cb = NULL;
+	/* heap->dbg_detached_cb: keep */
+	/* heap->dbg_udata: keep */
+	heap->dbg_processing = 0;
+	heap->dbg_paused = 0;
+	heap->dbg_state_dirty = 0;
+	heap->dbg_force_restart = 0;
+	heap->dbg_step_type = 0;
+	heap->dbg_step_thread = NULL;
+	heap->dbg_step_csindex = 0;
+	heap->dbg_step_startline = 0;
+	heap->dbg_have_next_byte = 0;
+
+	/* Ensure there are no stale active breakpoint pointers.
+	 * Breakpoint list is currently kept - we could empty it
+	 * here but we'd need to handle refcounts correctly, and
+	 * we'd need a 'thr' reference for that.
+	 *
+	 * XXX: clear breakpoint on either attach or detach?
+	 */
+	heap->dbg_breakpoints_active[0] = (duk_breakpoint *) NULL;
 }
 
-static const char *duk__get_heap_type_string(duk_heaphdr *hdr) {
-	switch (DUK_HEAPHDR_GET_TYPE(hdr)) {
-	case DUK_HTYPE_STRING:
-		return "string";
-	case DUK_HTYPE_OBJECT:
-		return "object";
-	case DUK_HTYPE_BUFFER:
-		return "buffer";
-	default:
-		return "???";
+DUK_LOCAL void duk__debug_do_detach2(duk_heap *heap) {
+	duk_debug_detached_function detached_cb;
+	void *detached_udata;
+
+	/* Safe to call multiple times. */
+
+	detached_cb = heap->dbg_detached_cb;
+	detached_udata = heap->dbg_udata;
+	heap->dbg_detached_cb = NULL;
+	heap->dbg_udata = NULL;
+
+	if (detached_cb) {
+		/* Careful here: state must be wiped before the call
+		 * so that we can cleanly handle a re-attach from
+		 * inside the callback.
+		 */
+		DUK_D(DUK_DPRINT("detached during message loop, delayed call to detached_cb"));
+		detached_cb(detached_udata);
 	}
+
+	heap->dbg_detaching = 0;
 }
 
-static void duk__dump_indented(duk_heaphdr *obj, int index) {
-#ifdef DUK_USE_REFERENCE_COUNTING
-	DUK_D(DUK_DPRINT("  [%ld]: %p %s (flags: 0x%08lx, ref: %ld) -> %!O",
-	                 (long) index,
-	                 (void *) obj,
-	                 (const char *) duk__get_heap_type_string(obj),
-	                 (unsigned long) DUK_HEAPHDR_GET_FLAGS(obj),
-	                 (long) DUK_HEAPHDR_GET_REFCOUNT(obj),
-	                 (duk_heaphdr *) obj));
-#else
-	DUK_D(DUK_DPRINT("  [%ld]: %p %s (flags: 0x%08lx) -> %!O",
-	                 (long) index,
-	                 (void *) obj,
-	                 (const char *) duk__get_heap_type_string(obj),
-	                 (unsigned long) DUK_HEAPHDR_GET_FLAGS(obj),
-	                 (duk_heaphdr *) obj));
-#endif
+DUK_INTERNAL void duk_debug_do_detach(duk_heap *heap) {
+	duk__debug_do_detach1(heap, 0);
+	duk__debug_do_detach2(heap);
 }
 
-static void duk__dump_heaphdr_list(duk_heap *heap, duk_heaphdr *root, const char *name) {
-	duk_int_t count;
-	duk_heaphdr *curr;
+/*
+ *  Debug connection peek and flush primitives
+ */
 
-	DUK_UNREF(heap);
+DUK_INTERNAL duk_bool_t duk_debug_read_peek(duk_hthread *thr) {
+	duk_heap *heap;
 
-	count = 0;
-	curr = root;
-	while (curr) {
-		count++;
-		curr = DUK_HEAPHDR_GET_NEXT(curr);
+	DUK_ASSERT(thr != NULL);
+	heap = thr->heap;
+	DUK_ASSERT(heap != NULL);
+
+	if (heap->dbg_read_cb == NULL) {
+		DUK_D(DUK_DPRINT("attempt to peek in detached state, return zero (= no data)"));
+		return 0;
+	}
+	if (heap->dbg_peek_cb == NULL) {
+		DUK_DD(DUK_DDPRINT("no peek callback, return zero (= no data)"));
+		return 0;
 	}
 
-	DUK_D(DUK_DPRINT("%s, %ld objects", (const char *) name, (long) count));
+	return (duk_bool_t) (heap->dbg_peek_cb(heap->dbg_udata) > 0);
+}
 
-	count = 0;
-	curr = root;
-	while (curr) {
-		count++;
-		duk__dump_indented(curr, count);
-		curr = DUK_HEAPHDR_GET_NEXT(curr);
+DUK_INTERNAL void duk_debug_read_flush(duk_hthread *thr) {
+	duk_heap *heap;
+
+	DUK_ASSERT(thr != NULL);
+	heap = thr->heap;
+	DUK_ASSERT(heap != NULL);
+
+	if (heap->dbg_read_cb == NULL) {
+		DUK_D(DUK_DPRINT("attempt to read flush in detached state, ignore"));
+		return;
+	}
+	if (heap->dbg_read_flush_cb == NULL) {
+		DUK_DD(DUK_DDPRINT("no read flush callback, ignore"));
+		return;
 	}
+
+	heap->dbg_read_flush_cb(heap->dbg_udata);
 }
 
-static void duk__dump_stringtable(duk_heap *heap) {
-	duk_uint_fast32_t i;
-	char buf[64+1];
+DUK_INTERNAL void duk_debug_write_flush(duk_hthread *thr) {
+	duk_heap *heap;
 
-	DUK_D(DUK_DPRINT("stringtable %p, used %ld, size %ld, load %ld%%",
-	                 (void *) heap->st,
-	                 (long) heap->st_used,
-	                 (long) heap->st_size,
-	                 (long) (((double) heap->st_used) / ((double) heap->st_size) * 100.0)));
+	DUK_ASSERT(thr != NULL);
+	heap = thr->heap;
+	DUK_ASSERT(heap != NULL);
 
-	for (i = 0; i < (duk_uint_fast32_t) heap->st_size; i++) {
-		duk_hstring *e = heap->st[i];
+	if (heap->dbg_read_cb == NULL) {
+		DUK_D(DUK_DPRINT("attempt to write flush in detached state, ignore"));
+		return;
+	}
+	if (heap->dbg_write_flush_cb == NULL) {
+		DUK_DD(DUK_DDPRINT("no write flush callback, ignore"));
+		return;
+	}
 
-		if (!e) {
-			DUK_D(DUK_DPRINT("  [%ld]: NULL", (long) i));
-		} else if (e == DUK_STRTAB_DELETED_MARKER(heap)) {
-			DUK_D(DUK_DPRINT("  [%ld]: DELETED", (long) i));
-		} else {
-			duk__sanitize_snippet(buf, sizeof(buf), e);
+	heap->dbg_write_flush_cb(heap->dbg_udata);
+}
 
-#ifdef DUK_USE_REFERENCE_COUNTING
-			DUK_D(DUK_DPRINT("  [%ld]: %p (flags: 0x%08lx, ref: %ld) '%s', strhash=0x%08lx, blen=%ld, clen=%ld, "
-			                 "arridx=%ld, internal=%ld, reserved_word=%ld, strict_reserved_word=%ld, eval_or_arguments=%ld",
-			                 (long) i,
-			                 (void *) e,
-			                 (unsigned long) DUK_HEAPHDR_GET_FLAGS((duk_heaphdr *) e),
-			                 (long) DUK_HEAPHDR_GET_REFCOUNT((duk_heaphdr *) e),
-			                 (const char *) buf,
-			                 (unsigned long) e->hash,
-			                 (long) e->blen,
-			                 (long) e->clen,
-			                 (long) (DUK_HSTRING_HAS_ARRIDX(e) ? 1 : 0),
-			                 (long) (DUK_HSTRING_HAS_INTERNAL(e) ? 1 : 0),
-			                 (long) (DUK_HSTRING_HAS_RESERVED_WORD(e) ? 1 : 0),
-			                 (long) (DUK_HSTRING_HAS_STRICT_RESERVED_WORD(e) ? 1 : 0),
-			                 (long) (DUK_HSTRING_HAS_EVAL_OR_ARGUMENTS(e) ? 1 : 0)));
-#else
-			DUK_D(DUK_DPRINT("  [%ld]: %p (flags: 0x%08lx) '%s', strhash=0x%08lx, blen=%ld, clen=%ld, "
-			                 "arridx=%ld, internal=%ld, reserved_word=%ld, strict_reserved_word=%ld, eval_or_arguments=%ld",
-			                 (long) i,
-			                 (void *) e,
-			                 (unsigned long) DUK_HEAPHDR_GET_FLAGS((duk_heaphdr *) e),
-			                 (const char *) buf,
-			                 (long) e->hash,
-			                 (long) e->blen,
-			                 (long) e->clen,
-			                 (long) (DUK_HSTRING_HAS_ARRIDX(e) ? 1 : 0),
-			                 (long) (DUK_HSTRING_HAS_INTERNAL(e) ? 1 : 0),
-			                 (long) (DUK_HSTRING_HAS_RESERVED_WORD(e) ? 1 : 0),
-			                 (long) (DUK_HSTRING_HAS_STRICT_RESERVED_WORD(e) ? 1 : 0),
-			                 (long) (DUK_HSTRING_HAS_EVAL_OR_ARGUMENTS(e) ? 1 : 0)));
+/*
+ *  Debug connection skip primitives
+ */
+
+/* Skip fully. */
+DUK_INTERNAL void duk_debug_skip_bytes(duk_hthread *thr, duk_size_t length) {
+	duk_uint8_t dummy[64];
+	duk_size_t now;
+
+	DUK_ASSERT(thr != NULL);
+
+	while (length > 0) {
+		now = (length > sizeof(dummy) ? sizeof(dummy) : length);
+		duk_debug_read_bytes(thr, dummy, now);
+		length -= now;
+	}
+}
+
+DUK_INTERNAL void duk_debug_skip_byte(duk_hthread *thr) {
+	DUK_ASSERT(thr != NULL);
+
+	(void) duk_debug_read_byte(thr);
+}
+
+/*
+ *  Debug connection read primitives
+ */
+
+/* Peek ahead in the stream one byte. */
+DUK_INTERNAL uint8_t duk_debug_peek_byte(duk_hthread *thr) {
+	/* It is important not to call this if the last byte read was an EOM.
+	 * Reading ahead in this scenario would cause unnecessary blocking if
+	 * another message is not available.
+	 */
+
+	duk_uint8_t x;
+
+	x = duk_debug_read_byte(thr);
+	thr->heap->dbg_have_next_byte = 1;
+	thr->heap->dbg_next_byte = x;
+	return x;
+}
+
+/* Read fully. */
+DUK_INTERNAL void duk_debug_read_bytes(duk_hthread *thr, duk_uint8_t *data, duk_size_t length) {
+	duk_heap *heap;
+	duk_uint8_t *p;
+	duk_size_t left;
+	duk_size_t got;
+
+	DUK_ASSERT(thr != NULL);
+	heap = thr->heap;
+	DUK_ASSERT(heap != NULL);
+
+	if (heap->dbg_read_cb == NULL) {
+		DUK_D(DUK_DPRINT("attempt to read %ld bytes in detached state, return zero data", (long) length));
+		goto fail;
+	}
+
+	/* NOTE: length may be zero */
+	p = data;
+	if (length >= 1 && heap->dbg_have_next_byte) {
+		heap->dbg_have_next_byte = 0;
+		*p++ = heap->dbg_next_byte;
+	}
+	for (;;) {
+		left = (duk_size_t) ((data + length) - p);
+		if (left == 0) {
+			break;
+		}
+		DUK_ASSERT(heap->dbg_read_cb != NULL);
+		DUK_ASSERT(left >= 1);
+#if defined(DUK_USE_DEBUGGER_TRANSPORT_TORTURE)
+		left = 1;
 #endif
+		got = heap->dbg_read_cb(heap->dbg_udata, (char *) p, left);
+		if (got == 0 || got > left) {
+			heap->dbg_write_cb = NULL;  /* squelch further writes */
+			DUK_D(DUK_DPRINT("connection error during read, return zero data"));
+			DUK__SET_CONN_BROKEN(thr, 1);
+			goto fail;
 		}
+		p += got;
 	}
+	return;
+
+ fail:
+	DUK_MEMZERO((void *) data, (size_t) length);
 }
 
-static void duk__dump_strcache(duk_heap *heap) {
-	duk_uint_fast32_t i;
-	char buf[64+1];
+DUK_INTERNAL duk_uint8_t duk_debug_read_byte(duk_hthread *thr) {
+	duk_uint8_t x;
 
-	DUK_D(DUK_DPRINT("stringcache"));
+	x = 0;  /* just in case callback is broken and won't write 'x' */
+	duk_debug_read_bytes(thr, &x, 1);
+	return x;
+}
 
-	for (i = 0; i < (duk_uint_fast32_t) DUK_HEAP_STRCACHE_SIZE; i++) {
-		duk_strcache *c = &heap->strcache[i];
-		if (!c->h) {
-			DUK_D(DUK_DPRINT("  [%ld]: bidx=%ld, cidx=%ld, str=NULL",
-			                 (long) i, (long) c->bidx, (long) c->cidx));
-		} else {
-			duk__sanitize_snippet(buf, sizeof(buf), c->h);
-			DUK_D(DUK_DPRINT("  [%ld]: bidx=%ld cidx=%ld str=%s",
-			                 (long) i, (long) c->bidx, (long) c->cidx, (const char *) buf));
-		}
-	} 
+DUK_LOCAL duk_uint32_t duk__debug_read_uint32_raw(duk_hthread *thr) {
+	duk_uint8_t buf[4];
+
+	DUK_ASSERT(thr != NULL);
+
+	duk_debug_read_bytes(thr, buf, 4);
+	return ((duk_uint32_t) buf[0] << 24) |
+	       ((duk_uint32_t) buf[1] << 16) |
+	       ((duk_uint32_t) buf[2] << 8) |
+	       (duk_uint32_t) buf[3];
 }
 
-void duk_debug_dump_heap(duk_heap *heap) {
-	char buf[64+1];
+DUK_LOCAL duk_uint32_t duk__debug_read_int32_raw(duk_hthread *thr) {
+	return (duk_int32_t) duk__debug_read_uint32_raw(thr);
+}
 
-	DUK_D(DUK_DPRINT("=== heap %p ===", (void *) heap));
-	DUK_D(DUK_DPRINT("  flags: 0x%08lx", (unsigned long) heap->flags));
+DUK_LOCAL duk_uint16_t duk__debug_read_uint16_raw(duk_hthread *thr) {
+	duk_uint8_t buf[2];
 
-	/* Note: there is no standard formatter for function pointers */
-#ifdef DUK_USE_GCC_PRAGMAS
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-pedantic"
-#endif
-	duk_debug_format_funcptr(buf, sizeof(buf), (unsigned char *) &heap->alloc_func, sizeof(heap->alloc_func));
-	DUK_D(DUK_DPRINT("  alloc_func: %s", (const char *) buf));
-	duk_debug_format_funcptr(buf, sizeof(buf), (unsigned char *) &heap->realloc_func, sizeof(heap->realloc_func));
-	DUK_D(DUK_DPRINT("  realloc_func: %s", (const char *) buf));
-	duk_debug_format_funcptr(buf, sizeof(buf), (unsigned char *) &heap->free_func, sizeof(heap->free_func));
-	DUK_D(DUK_DPRINT("  free_func: %s", (const char *) buf));
-	duk_debug_format_funcptr(buf, sizeof(buf), (unsigned char *) &heap->fatal_func, sizeof(heap->fatal_func));
-	DUK_D(DUK_DPRINT("  fatal_func: %s", (const char *) buf));
-#ifdef DUK_USE_GCC_PRAGMAS
-#pragma GCC diagnostic pop
-#endif
+	DUK_ASSERT(thr != NULL);
 
-	DUK_D(DUK_DPRINT("  alloc_udata: %p", (void *) heap->alloc_udata));
+	duk_debug_read_bytes(thr, buf, 2);
+	return ((duk_uint16_t) buf[0] << 8) |
+	       (duk_uint16_t) buf[1];
+}
 
-#ifdef DUK_USE_MARK_AND_SWEEP
-#ifdef DUK_USE_VOLUNTARY_GC
-	DUK_D(DUK_DPRINT("  mark-and-sweep trig counter: %ld", (long) heap->mark_and_sweep_trigger_counter));
-#endif
-	DUK_D(DUK_DPRINT("  mark-and-sweep rec depth: %ld", (long) heap->mark_and_sweep_recursion_depth));
-	DUK_D(DUK_DPRINT("  mark-and-sweep base flags: 0x%08lx", (unsigned long) heap->mark_and_sweep_base_flags));
-#endif
+DUK_INTERNAL duk_int32_t duk_debug_read_int(duk_hthread *thr) {
+	duk_small_uint_t x;
+	duk_small_uint_t t;
 
-	DUK_D(DUK_DPRINT("  lj.jmpbuf_ptr: %p", (void *) heap->lj.jmpbuf_ptr));
-	DUK_D(DUK_DPRINT("  lj.type: %ld", (long) heap->lj.type));
-	DUK_D(DUK_DPRINT("  lj.value1: %!T", (duk_tval *) &heap->lj.value1));
-	DUK_D(DUK_DPRINT("  lj.value2: %!T", (duk_tval *) &heap->lj.value2));
-	DUK_D(DUK_DPRINT("  lj.iserror: %ld", (long) heap->lj.iserror));
+	DUK_ASSERT(thr != NULL);
 
-	DUK_D(DUK_DPRINT("  handling_error: %ld", (long) heap->handling_error));
+	x = duk_debug_read_byte(thr);
+	if (x >= 0xc0) {
+		t = duk_debug_read_byte(thr);
+		return (duk_int32_t) (((x - 0xc0) << 8) + t);
+	} else if (x >= 0x80) {
+		return (duk_int32_t) (x - 0x80);
+	} else if (x == 0x10) {
+		return (duk_int32_t) duk__debug_read_uint32_raw(thr);
+	}
 
-	DUK_D(DUK_DPRINT("  heap_thread: %!@O", (duk_heaphdr *) heap->heap_thread));
-	DUK_D(DUK_DPRINT("  curr_thread: %!@O", (duk_heaphdr *) heap->curr_thread));
-	DUK_D(DUK_DPRINT("  heap_object: %!@O", (duk_heaphdr *) heap->heap_object));
+	DUK_D(DUK_DPRINT("debug connection error: failed to decode int"));
+	DUK__SET_CONN_BROKEN(thr, 1);
+	return 0;
+}
 
-	DUK_D(DUK_DPRINT("  call_recursion_depth: %ld", (long) heap->call_recursion_depth));
-	DUK_D(DUK_DPRINT("  call_recursion_limit: %ld", (long) heap->call_recursion_limit));
+DUK_LOCAL duk_hstring *duk__debug_read_hstring_raw(duk_hthread *thr, duk_uint32_t len) {
+	duk_context *ctx = (duk_context *) thr;
+	duk_uint8_t buf[31];
+	duk_uint8_t *p;
 
-	DUK_D(DUK_DPRINT("  hash_seed: 0x%08lx", (unsigned long) heap->hash_seed));
-	DUK_D(DUK_DPRINT("  rnd_state: 0x%08lx", (unsigned long) heap->rnd_state));
+	if (len <= sizeof(buf)) {
+		duk_debug_read_bytes(thr, buf, (duk_size_t) len);
+		duk_push_lstring(ctx, (const char *) buf, (duk_size_t) len);
+	} else {
+		p = (duk_uint8_t *) duk_push_fixed_buffer(ctx, (duk_size_t) len);
+		DUK_ASSERT(p != NULL);
+		duk_debug_read_bytes(thr, p, (duk_size_t) len);
+		duk_to_string(ctx, -1);
+	}
 
-	duk__dump_strcache(heap);
+	return duk_require_hstring(ctx, -1);
+}
 
-	duk__dump_heaphdr_list(heap, heap->heap_allocated, "heap allocated");
+DUK_INTERNAL duk_hstring *duk_debug_read_hstring(duk_hthread *thr) {
+	duk_context *ctx = (duk_context *) thr;
+	duk_small_uint_t x;
+	duk_uint32_t len;
 
-#ifdef DUK_USE_REFERENCE_COUNTING
-	duk__dump_heaphdr_list(heap, heap->refzero_list, "refcounting refzero list");
-#endif
+	DUK_ASSERT(thr != NULL);
 
-#ifdef DUK_USE_MARK_AND_SWEEP
-	duk__dump_heaphdr_list(heap, heap->finalize_list, "mark-and-sweep finalize list");
-#endif
+	x = duk_debug_read_byte(thr);
+	if (x >= 0x60 && x <= 0x7f) {
+		/* For short strings, use a fixed temp buffer. */
+		len = (duk_uint32_t) (x - 0x60);
+	} else if (x == 0x12) {
+		len = (duk_uint32_t) duk__debug_read_uint16_raw(thr);
+	} else if (x == 0x11) {
+		len = (duk_uint32_t) duk__debug_read_uint32_raw(thr);
+	} else {
+		goto fail;
+	}
 
-	duk__dump_stringtable(heap);
+	return duk__debug_read_hstring_raw(thr, len);
 
-	/* heap->strs: not worth dumping */
+ fail:
+	DUK_D(DUK_DPRINT("debug connection error: failed to decode int"));
+	DUK__SET_CONN_BROKEN(thr, 1);
+	duk_push_hstring_stridx(thr, DUK_STRIDX_EMPTY_STRING);  /* always push some string */
+	return duk_require_hstring(ctx, -1);
 }
 
-#endif  /* DUK_USE_DEBUG */
-#line 1 "duk_debug_hobject.c"
-/*
- *  Debug dumping of duk_hobject.
- */
+DUK_LOCAL duk_hbuffer *duk__debug_read_hbuffer_raw(duk_hthread *thr, duk_uint32_t len) {
+	duk_context *ctx = (duk_context *) thr;
+	duk_uint8_t *p;
 
-/* include removed: duk_internal.h */
+	p = (duk_uint8_t *) duk_push_fixed_buffer(ctx, (duk_size_t) len);
+	DUK_ASSERT(p != NULL);
+	duk_debug_read_bytes(thr, p, (duk_size_t) len);
 
-#ifdef DUK_USE_DEBUG
+	return duk_require_hbuffer(ctx, -1);
+}
 
-/* must match duk_hobject.h */
-static const char *duk__class_names[32] = {
-	"unused",
-	"Arguments",
-	"Array",
-	"Boolean",
-	"Date",
-	"Error",
-	"Function",
-	"JSON",
-	"Math",
-	"Number",
-	"Object",
-	"RegExp",
-	"String",
-	"global",
-	"ObjEnv",
-	"DecEnv",
-	"Buffer",
-	"Pointer",
-	"unused",
-	"unused",
-	"unused",
-	"unused",
-	"unused",
-	"unused",
-	"unused",
-	"unused",
-	"unused",
-	"unused",
-	"unused",
-	"unused",
-	"unused",
-	"unused",
-};
+DUK_LOCAL void *duk__debug_read_pointer_raw(duk_hthread *thr) {
+	duk_small_uint_t x;
+	duk__ptr_union pu;
 
-/* for thread dumping */
-static char duk__get_act_summary_char(duk_activation *act) {
-	if (act->func) {
-		if (DUK_HOBJECT_IS_COMPILEDFUNCTION(act->func)) {
-			return 'c';
-		} else if (DUK_HOBJECT_IS_NATIVEFUNCTION(act->func)) {
-			return 'n';
-		} else {
-			/* should not happen */
-			return '?';
-		}
-	} else {
-		/* should not happen */
-		return '?';
+	DUK_ASSERT(thr != NULL);
+
+	x = duk_debug_read_byte(thr);
+	if (x != sizeof(pu)) {
+		goto fail;
 	}
+	duk_debug_read_bytes(thr, (duk_uint8_t *) &pu.p, sizeof(pu));
+#if defined(DUK_USE_INTEGER_LE)
+	duk_byteswap_bytes((duk_uint8_t *) pu.b, sizeof(pu));
+#endif
+	return (void *) pu.p;
+
+ fail:
+	DUK_D(DUK_DPRINT("debug connection error: failed to decode pointer"));
+	DUK__SET_CONN_BROKEN(thr, 1);
+	return (void *) NULL;
 }
 
-/* for thread dumping */
-static char duk__get_tval_summary_char(duk_tval *tv) {
-	switch (DUK_TVAL_GET_TAG(tv)) {
-	case DUK_TAG_UNDEFINED:
-		if (DUK_TVAL_IS_UNDEFINED_UNUSED(tv)) {
-			return '.';
-		}
-		return 'u';
-	case DUK_TAG_NULL:
-		return 'n';
-	case DUK_TAG_BOOLEAN:
-		return 'b';
-	case DUK_TAG_STRING:
-		return 's';
-	case DUK_TAG_OBJECT: {
-		duk_hobject *h = DUK_TVAL_GET_OBJECT(tv);
+DUK_LOCAL duk_double_t duk__debug_read_double_raw(duk_hthread *thr) {
+	duk_double_union du;
 
-		if (DUK_HOBJECT_IS_ARRAY(h)) {
-			return 'A';
-		} else if (DUK_HOBJECT_IS_COMPILEDFUNCTION(h)) {
-			return 'C';
-		} else if (DUK_HOBJECT_IS_NATIVEFUNCTION(h)) {
-			return 'N';
-		} else if (DUK_HOBJECT_IS_THREAD(h)) {
-			return 'T';
-		}
-		return 'O';
-	}
-	case DUK_TAG_BUFFER: {
-		return 'B';
+	DUK_ASSERT(sizeof(du.uc) == 8);
+	duk_debug_read_bytes(thr, (duk_uint8_t *) du.uc, sizeof(du.uc));
+	DUK_DBLUNION_DOUBLE_NTOH(&du);
+	return du.d;
+}
+
+DUK_INTERNAL void duk_debug_read_tval(duk_hthread *thr) {
+	duk_context *ctx = (duk_context *) thr;
+	duk_uint8_t x;
+	duk_uint_t t;
+	duk_uint32_t len;
+
+	DUK_ASSERT(thr != NULL);
+
+	x = duk_debug_read_byte(thr);
+
+	if (x >= 0xc0) {
+		t = (duk_uint_t) (x - 0xc0);
+		t = (t << 8) + duk_debug_read_byte(thr);
+		duk_push_uint(ctx, (duk_uint_t) t);
+		return;
 	}
-	case DUK_TAG_POINTER: {
-		return 'P';
+	if (x >= 0x80) {
+		duk_push_uint(ctx, (duk_uint_t) (x - 0x80));
+		return;
 	}
-	default:
-		DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));
-		return 'd';
+	if (x >= 0x60) {
+		len = (duk_uint32_t) (x - 0x60);
+		duk__debug_read_hstring_raw(thr, len);
+		return;
 	}
 
-	DUK_UNREACHABLE();
-}
-
-/* for thread dumping */
-static char duk__get_cat_summary_char(duk_catcher *catcher) {
-	switch (DUK_CAT_GET_TYPE(catcher)) {
-	case DUK_CAT_TYPE_TCF:
-		if (DUK_CAT_HAS_CATCH_ENABLED(catcher)) {
-			if (DUK_CAT_HAS_FINALLY_ENABLED(catcher)) {
-				return 'C';  /* catch and finally active */
-			} else {
-				return 'c';  /* only catch active */
-			}
-		} else {
-			if (DUK_CAT_HAS_FINALLY_ENABLED(catcher)) {
-				return 'f';  /* only finally active */
-			} else {
-				return 'w';  /* neither active (usually 'with') */
-			}
-		}
-	case DUK_CAT_TYPE_LABEL:
-		return 'l';
-	case DUK_CAT_TYPE_UNKNOWN:
+	switch (x) {
+	case 0x10: {
+		duk_int32_t i = duk__debug_read_int32_raw(thr);
+		duk_push_i32(ctx, i);
+		break;
+	}
+	case 0x11:
+		len = duk__debug_read_uint32_raw(thr);
+		duk__debug_read_hstring_raw(thr, len);
+		break;
+	case 0x12:
+		len = duk__debug_read_uint16_raw(thr);
+		duk__debug_read_hstring_raw(thr, len);
+		break;
+	case 0x13:
+		len = duk__debug_read_uint32_raw(thr);
+		duk__debug_read_hbuffer_raw(thr, len);
+		break;
+	case 0x14:
+		len = duk__debug_read_uint16_raw(thr);
+		duk__debug_read_hbuffer_raw(thr, len);
+		break;
+	case 0x16:
+		duk_push_undefined(ctx);
+		break;
+	case 0x17:
+		duk_push_null(ctx);
+		break;
+	case 0x18:
+		duk_push_true(ctx);
+		break;
+	case 0x19:
+		duk_push_false(ctx);
+		break;
+	case 0x1a: {
+		duk_double_t d;
+		d = duk__debug_read_double_raw(thr);
+		duk_push_number(ctx, d);
+		break;
+	}
+	case 0x1b:
+		/* XXX: not needed for now, so not implemented */
+		DUK_D(DUK_DPRINT("reading object values unimplemented"));
+		goto fail;
+	case 0x1c: {
+		void *ptr;
+		ptr = duk__debug_read_pointer_raw(thr);
+		duk_push_pointer(thr, ptr);
+		break;
+	}
+	case 0x1d:
+		/* XXX: not needed for now, so not implemented */
+		DUK_D(DUK_DPRINT("reading lightfunc values unimplemented"));
+		goto fail;
+	case 0x1e: {
+		duk_heaphdr *h;
+		h = (duk_heaphdr *) duk__debug_read_pointer_raw(thr);
+		duk_push_heapptr(thr, (void *) h);
+		break;
+	}
+	case 0x15:  /* unused: not accepted in inbound messages */
 	default:
-		return '?';
+		goto fail;
 	}
 
-	DUK_UNREACHABLE();
+	return;
+
+ fail:
+	DUK_D(DUK_DPRINT("debug connection error: failed to decode tval"));
+	DUK__SET_CONN_BROKEN(thr, 1);
 }
 
-void duk_debug_dump_hobject(duk_hobject *obj) {
-	duk_uint_fast32_t i;
-	const char *str_empty = "";
-	const char *str_excl = "!";
+/*
+ *  Debug connection write primitives
+ */
 
-	DUK_UNREF(str_empty);
-	DUK_UNREF(str_excl);
+/* Write fully. */
+DUK_INTERNAL void duk_debug_write_bytes(duk_hthread *thr, const duk_uint8_t *data, duk_size_t length) {
+	duk_heap *heap;
+	const duk_uint8_t *p;
+	duk_size_t left;
+	duk_size_t got;
 
-	DUK_D(DUK_DPRINT("=== hobject %p ===", (void *) obj));
-	if (!obj) {
+	DUK_ASSERT(thr != NULL);
+	DUK_ASSERT(length == 0 || data != NULL);
+	heap = thr->heap;
+	DUK_ASSERT(heap != NULL);
+
+	if (heap->dbg_write_cb == NULL) {
+		DUK_D(DUK_DPRINT("attempt to write %ld bytes in detached state, ignore", (long) length));
 		return;
 	}
+	if (length == 0) {
+		/* Avoid doing an actual write callback with length == 0,
+		 * because that's reserved for a write flush.
+		 */
+		return;
+	}
+	DUK_ASSERT(data != NULL);
 
-	DUK_D(DUK_DPRINT("  %sextensible", (const char *) (DUK_HOBJECT_HAS_EXTENSIBLE(obj) ? str_empty : str_excl)));
-	DUK_D(DUK_DPRINT("  %sconstructable", (const char *) (DUK_HOBJECT_HAS_CONSTRUCTABLE(obj) ? str_empty : str_excl)));
-	DUK_D(DUK_DPRINT("  %sbound", (const char *) (DUK_HOBJECT_HAS_BOUND(obj) ? str_empty : str_excl)));
-	DUK_D(DUK_DPRINT("  %scompiledfunction", (const char *) (DUK_HOBJECT_HAS_COMPILEDFUNCTION(obj) ? str_empty : str_excl)));
-	DUK_D(DUK_DPRINT("  %snativefunction", (const char *) (DUK_HOBJECT_HAS_NATIVEFUNCTION(obj) ? str_empty : str_excl)));
-	DUK_D(DUK_DPRINT("  %sthread", (const char *) (DUK_HOBJECT_HAS_THREAD(obj) ? str_empty : str_excl)));
-	DUK_D(DUK_DPRINT("  %sarray_part", (const char *) (DUK_HOBJECT_HAS_ARRAY_PART(obj) ? str_empty : str_excl)));
-	DUK_D(DUK_DPRINT("  %sstrict", (const char *) (DUK_HOBJECT_HAS_STRICT(obj) ? str_empty : str_excl)));
-	DUK_D(DUK_DPRINT("  %snewenv", (const char *) (DUK_HOBJECT_HAS_NEWENV(obj) ? str_empty : str_excl)));
-	DUK_D(DUK_DPRINT("  %snamebinding", (const char *) (DUK_HOBJECT_HAS_NAMEBINDING(obj) ? str_empty : str_excl)));
-	DUK_D(DUK_DPRINT("  %screateargs", (const char *) (DUK_HOBJECT_HAS_CREATEARGS(obj) ? str_empty : str_excl)));
-	DUK_D(DUK_DPRINT("  %senvrecclosed", (const char *) (DUK_HOBJECT_HAS_ENVRECCLOSED(obj) ? str_empty : str_excl)));
-	DUK_D(DUK_DPRINT("  %sexotic_array", (const char *) (DUK_HOBJECT_HAS_EXOTIC_ARRAY(obj) ? str_empty : str_excl)));
-	DUK_D(DUK_DPRINT("  %sexotic_stringobj", (const char *) (DUK_HOBJECT_HAS_EXOTIC_STRINGOBJ(obj) ? str_empty : str_excl)));
-	DUK_D(DUK_DPRINT("  %sexotic_arguments", (const char *) (DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(obj) ? str_empty : str_excl)));
-	DUK_D(DUK_DPRINT("  %sexotic_dukfunc", (const char *) (DUK_HOBJECT_HAS_EXOTIC_DUKFUNC(obj) ? str_empty : str_excl)));
-	DUK_D(DUK_DPRINT("  %sexotic_bufferobj", (const char *) (DUK_HOBJECT_HAS_EXOTIC_BUFFEROBJ(obj) ? str_empty : str_excl)));
-	DUK_D(DUK_DPRINT("  %sexotic_proxyobj", (const char *) (DUK_HOBJECT_HAS_EXOTIC_PROXYOBJ(obj) ? str_empty : str_excl)));
-
-	DUK_D(DUK_DPRINT("  class: number %ld -> %s",
-	                 (long) DUK_HOBJECT_GET_CLASS_NUMBER(obj),
-	                 (const char *) (duk__class_names[(DUK_HOBJECT_GET_CLASS_NUMBER(obj)) & ((1 << DUK_HOBJECT_FLAG_CLASS_BITS) - 1)])));
-
-	DUK_D(DUK_DPRINT("  prototype: %p -> %!O",
-	                 (void *) obj->prototype,
-	                 (duk_heaphdr *) obj->prototype));
-
-	DUK_D(DUK_DPRINT("  props: p=%p, e_size=%ld, e_used=%ld, a_size=%ld, h_size=%ld",
-	                 (void *) obj->p,
-	                 (long) obj->e_size,
-	                 (long) obj->e_used,
-	                 (long) obj->a_size,
-	                 (long) obj->h_size));
-
-	/*
-	 *  Object (struct layout) specific dumping.  Inline code here
-	 *  instead of helpers, to ensure debug line prefix is identical.
-	 */
-
-	if (DUK_HOBJECT_IS_COMPILEDFUNCTION(obj)) {
-		duk_hcompiledfunction *h = (duk_hcompiledfunction *) obj;
-
-		DUK_D(DUK_DPRINT("  hcompiledfunction"));
-		DUK_D(DUK_DPRINT("  data: %!O", (duk_heaphdr *) h->data));
-		DUK_D(DUK_DPRINT("  nregs: %ld", (long) h->nregs));
-		DUK_D(DUK_DPRINT("  nargs: %ld", (long) h->nargs));
-
-		if (h->data && DUK_HBUFFER_HAS_DYNAMIC(h->data) && DUK_HBUFFER_GET_DATA_PTR(h->data)) {
-			DUK_D(DUK_DPRINT("  consts: %p (%ld, %ld bytes)",
-			                 (void *) DUK_HCOMPILEDFUNCTION_GET_CONSTS_BASE(h),
-			                 (long) DUK_HCOMPILEDFUNCTION_GET_CONSTS_COUNT(h),
-			                 (long) DUK_HCOMPILEDFUNCTION_GET_CONSTS_SIZE(h)));
-			DUK_D(DUK_DPRINT("  funcs: %p (%ld, %ld bytes)",
-			                 (void *) DUK_HCOMPILEDFUNCTION_GET_FUNCS_BASE(h),
-			                 (long) DUK_HCOMPILEDFUNCTION_GET_FUNCS_COUNT(h),
-			                 (long) DUK_HCOMPILEDFUNCTION_GET_FUNCS_SIZE(h)));
-			DUK_D(DUK_DPRINT("  bytecode: %p (%ld, %ld bytes)",
-			                 (void *) DUK_HCOMPILEDFUNCTION_GET_CODE_BASE(h),
-			                 (long) DUK_HCOMPILEDFUNCTION_GET_CODE_COUNT(h),
-			                 (long) DUK_HCOMPILEDFUNCTION_GET_CODE_SIZE(h)));
-		} else {
-			DUK_D(DUK_DPRINT("  consts: ???"));
-			DUK_D(DUK_DPRINT("  funcs: ???"));
-			DUK_D(DUK_DPRINT("  bytecode: ???"));
-		}
-	} else if (DUK_HOBJECT_IS_NATIVEFUNCTION(obj)) {
-		duk_hnativefunction *h = (duk_hnativefunction *) obj;
-		DUK_UNREF(h);
-
-		DUK_D(DUK_DPRINT("  hnativefunction"));
-		/* XXX: h->func, cannot print function pointers portably */
-		DUK_D(DUK_DPRINT("  nargs: %ld", (long) h->nargs));
-	} else if (DUK_HOBJECT_IS_THREAD(obj)) {
-		duk_hthread *thr = (duk_hthread *) obj;
-		duk_tval *p;
-
-		DUK_D(DUK_DPRINT("  hthread"));
-		DUK_D(DUK_DPRINT("  strict: %ld", (long) thr->strict));
-		DUK_D(DUK_DPRINT("  state: %ld", (long) thr->state));
-
-		DUK_D(DUK_DPRINT("  valstack_max: %ld, callstack_max: %ld, catchstack_max: %ld",
-		                 (long) thr->valstack_max, (long) thr->callstack_max, (long) thr->catchstack_max));
-
-		DUK_D(DUK_DPRINT("  callstack: ptr %p, size %ld, top %ld, preventcount %ld, used size %ld entries (%ld bytes), alloc size %ld entries (%ld bytes)",
-		                 (void *) thr->callstack,
-		                 (long) thr->callstack_size,
-		                 (long) thr->callstack_top,
-		                 (long) thr->callstack_preventcount,
-		                 (long) thr->callstack_top,
-		                 (long) (thr->callstack_top * sizeof(duk_activation)),
-		                 (long) thr->callstack_size,
-		                 (long) (thr->callstack_size * sizeof(duk_activation))));
-
-		DUK_DEBUG_SUMMARY_INIT();
-		DUK_DEBUG_SUMMARY_CHAR('[');
-		for (i = 0; i <= (duk_uint_fast32_t) thr->callstack_size; i++) {
-			if (i == thr->callstack_top) {
-				DUK_DEBUG_SUMMARY_CHAR('|');
-			}
-			if (!thr->callstack) {
-				DUK_DEBUG_SUMMARY_CHAR('@');
-			} else if (i < thr->callstack_size) {
-				if (i < thr->callstack_top) {
-					/* tailcalling is nice to see immediately; other flags (e.g. strict)
-					 * not that important.
-					 */
-					if (thr->callstack[i].flags & DUK_ACT_FLAG_TAILCALLED) {
-						DUK_DEBUG_SUMMARY_CHAR('/');
-					}
-					DUK_DEBUG_SUMMARY_CHAR(duk__get_act_summary_char(thr->callstack + i));
-				} else {
-					DUK_DEBUG_SUMMARY_CHAR('.');
-				}
-			}
-		}
-		DUK_DEBUG_SUMMARY_CHAR(']');
-		DUK_DEBUG_SUMMARY_FINISH();
-
-		DUK_D(DUK_DPRINT("  valstack: ptr %p, end %p (%ld), bottom %p (%ld), top %p (%ld), used size %ld entries (%ld bytes), alloc size %ld entries (%ld bytes)",
-		                 (void *) thr->valstack,
-		                 (void *) thr->valstack_end,
-		                 (long) (thr->valstack_end - thr->valstack),
-		                 (void *) thr->valstack_bottom,
-		                 (long) (thr->valstack_bottom - thr->valstack),
-		                 (void *) thr->valstack_top,
-		                 (long) (thr->valstack_top - thr->valstack),
-		                 (long) (thr->valstack_top - thr->valstack),
-		                 (long) (thr->valstack_top - thr->valstack) * sizeof(duk_tval),
-		                 (long) (thr->valstack_end - thr->valstack),
-		                 (long) (thr->valstack_end - thr->valstack) * sizeof(duk_tval)));
-
-		DUK_DEBUG_SUMMARY_INIT();
-		DUK_DEBUG_SUMMARY_CHAR('[');
-		p = thr->valstack;
-		while (p <= thr->valstack_end) {
-			i = (duk_uint_fast32_t) (p - thr->valstack);
-			if (thr->callstack &&
-			    thr->callstack_top > 0 &&
-			    i == (duk_size_t) (thr->callstack + thr->callstack_top - 1)->idx_bottom) {
-				DUK_DEBUG_SUMMARY_CHAR('>');
-			}
-			if (p == thr->valstack_top) {
-				DUK_DEBUG_SUMMARY_CHAR('|');
-			}
-			if (p < thr->valstack_end) {
-				if (p < thr->valstack_top) {
-					DUK_DEBUG_SUMMARY_CHAR(duk__get_tval_summary_char(p));
-				} else {
-					/* XXX: safe printer for these?  would be nice, because
-					 * we could visualize whether the values are in proper
-					 * state.
-					 */
-					DUK_DEBUG_SUMMARY_CHAR('.');
-				}
-			}
-			p++;
+	p = data;
+	for (;;) {
+		left = (duk_size_t) ((data + length) - p);
+		if (left == 0) {
+			break;
 		}
-		DUK_DEBUG_SUMMARY_CHAR(']');
-		DUK_DEBUG_SUMMARY_FINISH();
-
-		DUK_D(DUK_DPRINT("  catchstack: ptr %p, size %ld, top %ld, used size %ld entries (%ld bytes), alloc size %ld entries (%ld bytes)",
-		                 (void *) thr->catchstack,
-		                 (long) thr->catchstack_size,
-		                 (long) thr->catchstack_top,
-		                 (long) thr->catchstack_top,
-		                 (long) (thr->catchstack_top * sizeof(duk_catcher)),
-		                 (long) thr->catchstack_size,
-		                 (long) (thr->catchstack_size * sizeof(duk_catcher))));
-
-		DUK_DEBUG_SUMMARY_INIT();
-		DUK_DEBUG_SUMMARY_CHAR('[');
-		for (i = 0; i <= (duk_uint_fast32_t) thr->catchstack_size; i++) {
-			if (i == thr->catchstack_top) {
-				DUK_DEBUG_SUMMARY_CHAR('|');
-			}
-			if (!thr->catchstack) {
-				DUK_DEBUG_SUMMARY_CHAR('@');
-			} else if (i < thr->catchstack_size) {
-				if (i < thr->catchstack_top) {
-					DUK_DEBUG_SUMMARY_CHAR(duk__get_cat_summary_char(thr->catchstack + i));
-				} else {
-					DUK_DEBUG_SUMMARY_CHAR('.');
-				}
-			}
+		DUK_ASSERT(heap->dbg_write_cb != NULL);
+		DUK_ASSERT(left >= 1);
+#if defined(DUK_USE_DEBUGGER_TRANSPORT_TORTURE)
+		left = 1;
+#endif
+		got = heap->dbg_write_cb(heap->dbg_udata, (const char *) p, left);
+		if (got == 0 || got > left) {
+			heap->dbg_write_cb = NULL;  /* squelch further writes */
+			DUK_D(DUK_DPRINT("connection error during write"));
+			DUK__SET_CONN_BROKEN(thr, 1);
+			return;
 		}
-		DUK_DEBUG_SUMMARY_CHAR(']');
-		DUK_DEBUG_SUMMARY_FINISH();
+		p += got;
+	}
+}
 
-		DUK_D(DUK_DPRINT("  resumer: ptr %p", (void *) thr->resumer));
+DUK_INTERNAL void duk_debug_write_byte(duk_hthread *thr, duk_uint8_t x) {
+	duk_heap *heap;
+	duk_size_t got;
 
-#if 0  /* worth dumping? */
-		for (i = 0; i < DUK_NUM_BUILTINS; i++) {
-			DUK_D(DUK_DPRINT("  builtins[%ld] -> %!@O", (long) i, (duk_heaphdr *) thr->builtins[i]));
-		}
-#endif
-	}
+	DUK_ASSERT(thr != NULL);
+	heap = thr->heap;
+	DUK_ASSERT(heap != NULL);
 
-	if (obj->p) {
-		DUK_D(DUK_DPRINT("  props alloc size: %ld",
-		                 (long) DUK_HOBJECT_P_COMPUTE_SIZE(obj->e_size, obj->a_size, obj->h_size)));
-	} else {
-		DUK_D(DUK_DPRINT("  props alloc size: n/a"));
+	if (heap->dbg_write_cb == NULL) {
+		DUK_D(DUK_DPRINT("attempt to write 1 bytes in detached state, ignore"));
+		return;
 	}
 
-	DUK_D(DUK_DPRINT("  prop entries:"));
-	for (i = 0; i < (duk_uint_fast32_t) obj->e_size; i++) {
-		duk_hstring *k;
-		duk_propvalue *v;
+	DUK_ASSERT(heap->dbg_write_cb != NULL);
+	got = heap->dbg_write_cb(heap->dbg_udata, (const char *) (&x), 1);
+	if (got != 1) {
+		DUK_D(DUK_DPRINT("connection error during write"));
+		DUK__SET_CONN_BROKEN(thr, 1);
+	}
+}
 
-		k = DUK_HOBJECT_E_GET_KEY(obj, i);
-		v = DUK_HOBJECT_E_GET_VALUE_PTR(obj, i);
-		DUK_UNREF(v);
+DUK_INTERNAL void duk_debug_write_unused(duk_hthread *thr) {
+	duk_debug_write_byte(thr, 0x15);
+}
 
-		if (i >= obj->e_used) {
-			DUK_D(DUK_DPRINT("    [%ld]: UNUSED", (long) i));
-			continue;
-		}
+DUK_INTERNAL void duk_debug_write_undefined(duk_hthread *thr) {
+	duk_debug_write_byte(thr, 0x16);
+}
 
-		if (!k) {
-			DUK_D(DUK_DPRINT("    [%ld]: NULL", (long) i));
-			continue;
-		}
+/* Write signed 32-bit integer. */
+DUK_INTERNAL void duk_debug_write_int(duk_hthread *thr, duk_int32_t x) {
+	duk_uint8_t buf[5];
+	duk_size_t len;
 
-		if (DUK_HOBJECT_E_SLOT_IS_ACCESSOR(obj, i)) {
-			DUK_D(DUK_DPRINT("    [%ld]: [w=%ld e=%ld c=%ld a=%ld] %!O -> get:%p set:%p; get %!O; set %!O",
-			                 (long) i,
-			                 (long) (DUK_HOBJECT_E_SLOT_IS_WRITABLE(obj, i) ? 1 : 0),
-			                 (long) (DUK_HOBJECT_E_SLOT_IS_ENUMERABLE(obj, i) ? 1 : 0),
-			                 (long) (DUK_HOBJECT_E_SLOT_IS_CONFIGURABLE(obj, i) ? 1 : 0),
-			                 (long) (DUK_HOBJECT_E_SLOT_IS_ACCESSOR(obj, i) ? 1 : 0),
-			                 (duk_heaphdr *) k,
-			                 (void *) v->a.get,
-			                 (void *) v->a.set,
-			                 (duk_heaphdr *) v->a.get,
-			                 (duk_heaphdr *) v->a.set));
-		} else {
-			DUK_D(DUK_DPRINT("    [%ld]: [w=%ld e=%ld c=%ld a=%ld] %!O -> %!T",
-			                 (long) i,
-			                 (long) (DUK_HOBJECT_E_SLOT_IS_WRITABLE(obj, i) ? 1 : 0),
-			                 (long) (DUK_HOBJECT_E_SLOT_IS_ENUMERABLE(obj, i) ? 1 : 0),
-			                 (long) (DUK_HOBJECT_E_SLOT_IS_CONFIGURABLE(obj, i) ? 1 : 0),
-			                 (long) (DUK_HOBJECT_E_SLOT_IS_ACCESSOR(obj, i) ? 1 : 0),
-			                 (duk_heaphdr *) k,
-			                 (duk_tval *) &v->v));
-		}
-	}
+	DUK_ASSERT(thr != NULL);
 
-	DUK_D(DUK_DPRINT("  array entries:"));
-	for (i = 0; i < (duk_uint_fast32_t) obj->a_size; i++) {
-		DUK_D(DUK_DPRINT("    [%ld]: [w=%ld e=%ld c=%ld a=%ld] %ld -> %!T",
-		                 (long) i,
-		                 (long) 1,  /* implicit attributes */
-		                 (long) 1,
-		                 (long) 1,
-		                 (long) 0,
-		                 (long) i,
-		                 (duk_tval *) DUK_HOBJECT_A_GET_VALUE_PTR(obj, i)));
+	if (x >= 0 && x <= 0x3fL) {
+		buf[0] = (duk_uint8_t) (0x80 + x);
+		len = 1;
+	} else if (x >= 0 && x <= 0x3fffL) {
+		buf[0] = (duk_uint8_t) (0xc0 + (x >> 8));
+		buf[1] = (duk_uint8_t) (x & 0xff);
+		len = 2;
+	} else {
+		/* Signed integers always map to 4 bytes now. */
+		buf[0] = (duk_uint8_t) 0x10;
+		buf[1] = (duk_uint8_t) ((x >> 24) & 0xff);
+		buf[2] = (duk_uint8_t) ((x >> 16) & 0xff);
+		buf[3] = (duk_uint8_t) ((x >> 8) & 0xff);
+		buf[4] = (duk_uint8_t) (x & 0xff);
+		len = 5;
 	}
+	duk_debug_write_bytes(thr, buf, len);
+}
 
-	DUK_D(DUK_DPRINT("  hash entries:"));
-	for (i = 0; i < (duk_uint_fast32_t) obj->h_size; i++) {
-		duk_uint32_t t = DUK_HOBJECT_H_GET_INDEX(obj, i);
-		if (t == DUK_HOBJECT_HASHIDX_UNUSED) {
-			DUK_D(DUK_DPRINT("    [%ld]: unused", (long) i));
-		} else if (t == DUK_HOBJECT_HASHIDX_DELETED) {
-			DUK_D(DUK_DPRINT("    [%ld]: deleted", (long) i));
-		} else {
-			DUK_D(DUK_DPRINT("    [%ld]: %ld", (long) i, (long) t));
-		}
-	}
+/* Write unsigned 32-bit integer. */
+DUK_INTERNAL void duk_debug_write_uint(duk_hthread *thr, duk_uint32_t x) {
+	/* XXX: there's currently no need to support full 32-bit unsigned
+	 * integer range in practice.  If that becomes necessary, add a new
+	 * dvalue type or encode as an IEEE double.
+	 */
+	duk_debug_write_int(thr, (duk_int32_t) x);
 }
 
-void duk_debug_dump_callstack(duk_hthread *thr) {
-	duk_uint_fast32_t i;
+DUK_INTERNAL void duk_debug_write_strbuf(duk_hthread *thr, const char *data, duk_size_t length, duk_uint8_t marker_base) {
+	duk_uint8_t buf[5];
+	duk_size_t buflen;
 
-	DUK_D(DUK_DPRINT("=== hthread %p callstack: %ld entries ===",
-	                 (void *) thr,
-	                 (thr == NULL ? (long) 0 : (long) thr->callstack_top)));
-	if (!thr) {
-		return;
+	DUK_ASSERT(thr != NULL);
+	DUK_ASSERT(length == 0 || data != NULL);
+
+	if (length <= 0x1fUL && marker_base == 0x11) {
+		/* For strings, special form for short lengths. */
+		buf[0] = (duk_uint8_t) (0x60 + length);
+		buflen = 1;
+	} else if (length <= 0xffffUL) {
+		buf[0] = (duk_uint8_t) (marker_base + 1);
+		buf[1] = (duk_uint8_t) (length >> 8);
+		buf[2] = (duk_uint8_t) (length & 0xff);
+		buflen = 3;
+	} else {
+		buf[0] = (duk_uint8_t) marker_base;
+		buf[1] = (duk_uint8_t) (length >> 24);
+		buf[2] = (duk_uint8_t) ((length >> 16) & 0xff);
+		buf[3] = (duk_uint8_t) ((length >> 8) & 0xff);
+		buf[4] = (duk_uint8_t) (length & 0xff);
+		buflen = 5;
 	}
 
-	for (i = 0; i < (duk_uint_fast32_t) thr->callstack_top; i++) {
-		duk_activation *act = thr->callstack + i;
-		duk_tval *this_binding = NULL;
+	duk_debug_write_bytes(thr, (const duk_uint8_t *) buf, buflen);
+	duk_debug_write_bytes(thr, (const duk_uint8_t *) data, length);
+}
 
-		this_binding = thr->valstack + act->idx_bottom - 1;
-		if (this_binding < thr->valstack || this_binding >= thr->valstack_top) {
-			this_binding = NULL;
-		}
+DUK_INTERNAL void duk_debug_write_string(duk_hthread *thr, const char *data, duk_size_t length) {
+	duk_debug_write_strbuf(thr, data, length, 0x11);
+}
 
-		DUK_D(DUK_DPRINT("  [%ld] -> flags=0x%08lx, func=%!O, var_env=%!iO, lex_env=%!iO, "
-		                 "pc=%ld, idx_bottom=%ld, idx_retval=%ld, this_binding=%!T",
-		                 (long) i,
-		                 (unsigned long) act->flags,
-		                 (duk_heaphdr *) act->func,
-		                 (duk_heaphdr *) act->var_env,
-		                 (duk_heaphdr *) act->lex_env,
-		                 (long) act->pc,
-		                 (long) act->idx_bottom,
-		                 (long) act->idx_retval,
-		                 (duk_tval *) this_binding));
-	}
+DUK_INTERNAL void duk_debug_write_cstring(duk_hthread *thr, const char *data) {
+	DUK_ASSERT(thr != NULL);
+
+	duk_debug_write_string(thr,
+	                       data,
+	                       data ? DUK_STRLEN(data) : 0);
 }
 
-void duk_debug_dump_activation(duk_hthread *thr, duk_activation *act) {
-	if (!act) {
-		DUK_D(DUK_DPRINT("duk_activation: NULL"));
-	} else {
-		duk_tval *this_binding = NULL;
+DUK_INTERNAL void duk_debug_write_hstring(duk_hthread *thr, duk_hstring *h) {
+	DUK_ASSERT(thr != NULL);
 
-		this_binding = thr->valstack + act->idx_bottom - 1;
-		if (this_binding < thr->valstack || this_binding >= thr->valstack_top) {
-			this_binding = NULL;
-		}
+	/* XXX: differentiate null pointer from empty string? */
+	duk_debug_write_string(thr,
+	                       (h != NULL ? (const char *) DUK_HSTRING_GET_DATA(h) : NULL),
+	                       (h != NULL ? (duk_size_t) DUK_HSTRING_GET_BYTELEN(h) : 0));
+}
 
-		DUK_D(DUK_DPRINT("duk_activation: %p -> flags=0x%08lx, func=%!O, var_env=%!O, "
-		                 "lex_env=%!O, pc=%ld, idx_bottom=%ld, idx_retval=%ld, this_binding=%!T",
-		                 (void *) act,
-		                 (unsigned long) act->flags,
-		                 (duk_heaphdr *) act->func,
-		                 (duk_heaphdr *) act->var_env,
-		                 (duk_heaphdr *) act->lex_env,
-		                 (long) act->pc,
-		                 (long) act->idx_bottom,
-		                 (long) act->idx_retval,
-		                 (duk_tval *) this_binding));
-	}
+DUK_LOCAL void duk__debug_write_hstring_safe_top(duk_hthread *thr) {
+	duk_context *ctx = (duk_context *) thr;
+	duk_debug_write_hstring(thr, duk_safe_to_hstring(ctx, -1));
 }
 
-#endif  /* DUK_USE_DEBUG */
-#line 1 "duk_debug_macros.c"
-/*
- *  Debugging macro calls.
- */
+DUK_INTERNAL void duk_debug_write_buffer(duk_hthread *thr, const char *data, duk_size_t length) {
+	duk_debug_write_strbuf(thr, data, length, 0x13);
+}
 
-/* include removed: duk_internal.h */
+DUK_INTERNAL void duk_debug_write_hbuffer(duk_hthread *thr, duk_hbuffer *h) {
+	DUK_ASSERT(thr != NULL);
 
-#ifdef DUK_USE_DEBUG
+	duk_debug_write_buffer(thr,
+	                       (h != NULL ? (const char *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h) : NULL),
+	                       (h != NULL ? (duk_size_t) DUK_HBUFFER_GET_SIZE(h) : 0));
+}
 
-/*
- *  Debugging enabled
- */
+DUK_LOCAL void duk__debug_write_pointer_raw(duk_hthread *thr, void *ptr, duk_uint8_t ibyte) {
+	duk_uint8_t buf[2];
+	duk__ptr_union pu;
 
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdarg.h>
+	DUK_ASSERT(thr != NULL);
+	DUK_ASSERT(sizeof(ptr) >= 1 && sizeof(ptr) <= 16);
+	/* ptr may be NULL */
 
-/* for one-char summaries (usable for e.g. valstack) */
-char duk_debug_summary_buf[DUK_DEBUG_SUMMARY_BUF_SIZE];
-duk_int_t duk_debug_summary_idx;
+	buf[0] = ibyte;
+	buf[1] = sizeof(pu);
+	duk_debug_write_bytes(thr, buf, 2);
+	pu.p = (void *) ptr;
+#if defined(DUK_USE_INTEGER_LE)
+	duk_byteswap_bytes((duk_uint8_t *) pu.b, sizeof(pu));
+#endif
+	duk_debug_write_bytes(thr, (const duk_uint8_t *) &pu.p, (duk_size_t) sizeof(pu));
+}
 
-#define DUK__DEBUG_BUFSIZE  DUK_USE_DEBUG_BUFSIZE
-static char duk__debug_buf[DUK__DEBUG_BUFSIZE];
+DUK_INTERNAL void duk_debug_write_pointer(duk_hthread *thr, void *ptr) {
+	duk__debug_write_pointer_raw(thr, ptr, 0x1c);
+}
 
-static const char *duk__get_level_string(duk_small_int_t level) {
-	switch ((int) level) {
-	case DUK_LEVEL_DEBUG:
-		return "D";
-	case DUK_LEVEL_DDEBUG:
-		return "DD";
-	case DUK_LEVEL_DDDEBUG:
-		return "DDD";
-	}
-	return "???";
+#if defined(DUK_USE_DEBUGGER_DUMPHEAP)
+DUK_INTERNAL void duk_debug_write_heapptr(duk_hthread *thr, duk_heaphdr *h) {
+	duk__debug_write_pointer_raw(thr, (void *) h, 0x1e);
 }
+#endif  /* DUK_USE_DEBUGGER_DUMPHEAP */
 
-#ifdef DUK_USE_DPRINT_COLORS
+DUK_INTERNAL void duk_debug_write_hobject(duk_hthread *thr, duk_hobject *obj) {
+	duk_uint8_t buf[3];
+	duk__ptr_union pu;
 
-/* http://en.wikipedia.org/wiki/ANSI_escape_code */
-#define DUK__TERM_REVERSE  "\x1b[7m"
-#define DUK__TERM_BRIGHT   "\x1b[1m"
-#define DUK__TERM_RESET    "\x1b[0m"
-#define DUK__TERM_BLUE     "\x1b[34m"
-#define DUK__TERM_RED      "\x1b[31m"
+	DUK_ASSERT(thr != NULL);
+	DUK_ASSERT(sizeof(obj) >= 1 && sizeof(obj) <= 16);
+	DUK_ASSERT(obj != NULL);
 
-static const char *duk__get_term_1(duk_small_int_t level) {
-	DUK_UNREF(level);
-	return (const char *) DUK__TERM_RED;
+	buf[0] = 0x1b;
+	buf[1] = (duk_uint8_t) DUK_HOBJECT_GET_CLASS_NUMBER(obj);
+	buf[2] = sizeof(pu);
+	duk_debug_write_bytes(thr, buf, 3);
+	pu.p = (void *) obj;
+#if defined(DUK_USE_INTEGER_LE)
+	duk_byteswap_bytes((duk_uint8_t *) pu.b, sizeof(pu));
+#endif
+	duk_debug_write_bytes(thr, (const duk_uint8_t *) &pu.p, (duk_size_t) sizeof(pu));
 }
 
-static const char *duk__get_term_2(duk_small_int_t level) {
-	switch ((int) level) {
-	case DUK_LEVEL_DEBUG:
-		return (const char *) (DUK__TERM_RESET DUK__TERM_BRIGHT);
-	case DUK_LEVEL_DDEBUG:
-		return (const char *) (DUK__TERM_RESET);
-	case DUK_LEVEL_DDDEBUG:
-		return (const char *) (DUK__TERM_RESET DUK__TERM_BLUE);
+DUK_INTERNAL void duk_debug_write_tval(duk_hthread *thr, duk_tval *tv) {
+	duk_c_function lf_func;
+	duk_small_uint_t lf_flags;
+	duk_uint8_t buf[4];
+	duk_double_union du;
+
+	DUK_ASSERT(thr != NULL);
+	DUK_ASSERT(tv != NULL);
+
+	switch (DUK_TVAL_GET_TAG(tv)) {
+	case DUK_TAG_UNDEFINED:
+		duk_debug_write_byte(thr, 0x16);
+		break;
+	case DUK_TAG_UNUSED:
+		duk_debug_write_byte(thr, 0x15);
+		break;
+	case DUK_TAG_NULL:
+		duk_debug_write_byte(thr, 0x17);
+		break;
+	case DUK_TAG_BOOLEAN:
+		DUK_ASSERT(DUK_TVAL_GET_BOOLEAN(tv) == 0 ||
+		           DUK_TVAL_GET_BOOLEAN(tv) == 1);
+		duk_debug_write_byte(thr, DUK_TVAL_GET_BOOLEAN(tv) ? 0x18 : 0x19);
+		break;
+	case DUK_TAG_POINTER:
+		duk_debug_write_pointer(thr, (void *) DUK_TVAL_GET_POINTER(tv));
+		break;
+	case DUK_TAG_LIGHTFUNC:
+		DUK_TVAL_GET_LIGHTFUNC(tv, lf_func, lf_flags);
+		buf[0] = 0x1d;
+		buf[1] = (duk_uint8_t) (lf_flags >> 8);
+		buf[2] = (duk_uint8_t) (lf_flags & 0xff);
+		buf[3] = sizeof(lf_func);
+		duk_debug_write_bytes(thr, buf, 4);
+		duk_debug_write_bytes(thr, (const duk_uint8_t *) &lf_func, sizeof(lf_func));
+		break;
+	case DUK_TAG_STRING:
+		duk_debug_write_hstring(thr, DUK_TVAL_GET_STRING(tv));
+		break;
+	case DUK_TAG_OBJECT:
+		duk_debug_write_hobject(thr, DUK_TVAL_GET_OBJECT(tv));
+		break;
+	case DUK_TAG_BUFFER:
+		duk_debug_write_hbuffer(thr, DUK_TVAL_GET_BUFFER(tv));
+		break;
+#if defined(DUK_USE_FASTINT)
+	case DUK_TAG_FASTINT:
+#endif
+	default:
+		/* Numbers are normalized to big (network) endian. */
+		DUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv));
+		DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));
+		du.d = DUK_TVAL_GET_NUMBER(tv);
+		DUK_DBLUNION_DOUBLE_HTON(&du);
+
+		duk_debug_write_byte(thr, 0x1a);
+		duk_debug_write_bytes(thr, (const duk_uint8_t *) du.uc, sizeof(du.uc));
 	}
-	return (const char *) DUK__TERM_RESET;
 }
 
-static const char *duk__get_term_3(duk_small_int_t level) {
-	DUK_UNREF(level);
-	return (const char *) DUK__TERM_RESET;
+#if defined(DUK_USE_DEBUGGER_DUMPHEAP)
+/* Variant for writing duk_tvals so that any heap allocated values are
+ * written out as tagged heap pointers.
+ */
+DUK_LOCAL void duk__debug_write_tval_heapptr(duk_hthread *thr, duk_tval *tv) {
+	if (DUK_TVAL_IS_HEAP_ALLOCATED(tv)) {
+		duk_heaphdr *h = DUK_TVAL_GET_HEAPHDR(tv);
+		duk_debug_write_heapptr(thr, h);
+	} else {
+		duk_debug_write_tval(thr, tv);
+	}
 }
+#endif  /* DUK_USE_DEBUGGER_DUMPHEAP */
 
-#else
+/*
+ *  Debug connection message write helpers
+ */
 
-static const char *duk__get_term_1(duk_small_int_t level) {
-	DUK_UNREF(level);
-	return (const char *) "";
+#if 0  /* unused */
+DUK_INTERNAL void duk_debug_write_request(duk_hthread *thr, duk_small_uint_t command) {
+	duk_debug_write_byte(thr, DUK_DBG_MARKER_REQUEST);
+	duk_debug_write_int(thr, command);
 }
+#endif
 
-static const char *duk__get_term_2(duk_small_int_t level) {
-	DUK_UNREF(level);
-	return (const char *) "";
+DUK_INTERNAL void duk_debug_write_reply(duk_hthread *thr) {
+	duk_debug_write_byte(thr, DUK_DBG_MARKER_REPLY);
 }
 
-static const char *duk__get_term_3(duk_small_int_t level) {
-	DUK_UNREF(level);
-	return (const char *) "";
+DUK_INTERNAL void duk_debug_write_error_eom(duk_hthread *thr, duk_small_uint_t err_code, const char *msg) {
+	/* Allow NULL 'msg' */
+	duk_debug_write_byte(thr, DUK_DBG_MARKER_ERROR);
+	duk_debug_write_int(thr, (duk_int32_t) err_code);
+	duk_debug_write_cstring(thr, msg);
+	duk_debug_write_eom(thr);
 }
 
-#endif  /* DUK_USE_DPRINT_COLORS */
+DUK_INTERNAL void duk_debug_write_notify(duk_hthread *thr, duk_small_uint_t command) {
+	duk_debug_write_byte(thr, DUK_DBG_MARKER_NOTIFY);
+	duk_debug_write_int(thr, command);
+}
 
-#ifdef DUK_USE_VARIADIC_MACROS
+DUK_INTERNAL void duk_debug_write_eom(duk_hthread *thr) {
+	duk_debug_write_byte(thr, DUK_DBG_MARKER_EOM);
 
-void duk_debug_log(duk_small_int_t level, const char *file, duk_int_t line, const char *func, char *fmt, ...) {
-	va_list ap;
+	/* As an initial implementation, write flush after every EOM (and the
+	 * version identifier).  A better implementation would flush only when
+	 * Duktape is finished processing messages so that a flush only happens
+	 * after all outbound messages are finished on that occasion.
+	 */
+	duk_debug_write_flush(thr);
+}
 
-	va_start(ap, fmt);
+/*
+ *  Status message and helpers
+ */
 
-	DUK_MEMZERO((void *) duk__debug_buf, (size_t) DUK__DEBUG_BUFSIZE);
-	duk_debug_vsnprintf(duk__debug_buf, DUK__DEBUG_BUFSIZE - 1, fmt, ap);
+DUK_INTERNAL duk_uint_fast32_t duk_debug_curr_line(duk_hthread *thr) {
+	duk_context *ctx = (duk_context *) thr;
+	duk_activation *act;
+	duk_uint_fast32_t line;
+	duk_uint_fast32_t pc;
 
-#ifdef DUK_USE_DPRINT_RDTSC
-	DUK_FPRINTF(DUK_STDERR, "%s[%s] <%llu> %s:%ld (%s):%s %s%s\n",
-	            (const char *) duk__get_term_1(level),
-	            (const char *) duk__get_level_string(level),
-	            (unsigned long long) duk_rdtsc(),  /* match the inline asm in duk_features.h */
-	            (const char *) file,
-	            (long) line,
-	            (const char *) func,
-	            (const char *) duk__get_term_2(level),
-	            (const char *) duk__debug_buf,
-	            (const char *) duk__get_term_3(level));
-#else
-	DUK_FPRINTF(DUK_STDERR, "%s[%s] %s:%ld (%s):%s %s%s\n",
-	            (const char *) duk__get_term_1(level),
-	            (const char *) duk__get_level_string(level),
-	            (const char *) file,
-	            (long) line,
-	            (const char *) func,
-	            (const char *) duk__get_term_2(level),
-	            (const char *) duk__debug_buf,
-	            (const char *) duk__get_term_3(level));
-#endif
-	DUK_FFLUSH(DUK_STDERR);
+	act = duk_hthread_get_current_activation(thr);  /* may be NULL */
+	if (act == NULL) {
+		return 0;
+	}
 
-	va_end(ap);
+	/* We're conceptually between two opcodes; act->pc indicates the next
+	 * instruction to be executed.  This is usually the correct pc/line to
+	 * indicate in Status.  (For the 'debugger' statement this now reports
+	 * the pc/line after the debugger statement because the debugger opcode
+	 * has already been executed.)
+	 */
+
+	pc = duk_hthread_get_act_curr_pc(thr, act);
+
+	/* XXX: this should be optimized to be a raw query and avoid valstack
+	 * operations if possible.
+	 */
+	duk_push_tval(ctx, &act->tv_func);
+	line = duk_hobject_pc2line_query(ctx, -1, pc);
+	duk_pop(ctx);
+	return line;
 }
 
-#else  /* DUK_USE_VARIADIC_MACROS */
+DUK_INTERNAL void duk_debug_send_status(duk_hthread *thr) {
+	duk_context *ctx = (duk_context *) thr;
+	duk_activation *act;
 
-char duk_debug_file_stash[DUK_DEBUG_STASH_SIZE];
-char duk_debug_line_stash[DUK_DEBUG_STASH_SIZE];
-char duk_debug_func_stash[DUK_DEBUG_STASH_SIZE];
-duk_small_int_t duk_debug_level_stash;
+	duk_debug_write_notify(thr, DUK_DBG_CMD_STATUS);
+	duk_debug_write_int(thr, thr->heap->dbg_paused);
 
-void duk_debug_log(char *fmt, ...) {
-	va_list ap;
-	duk_small_int_t level = duk_debug_level_stash;
+	DUK_ASSERT_DISABLE(thr->callstack_top >= 0);  /* unsigned */
+	if (thr->callstack_top == 0) {
+		duk_debug_write_undefined(thr);
+		duk_debug_write_undefined(thr);
+		duk_debug_write_int(thr, 0);
+		duk_debug_write_int(thr, 0);
+	} else {
+		act = thr->callstack + thr->callstack_top - 1;
+		duk_push_tval(ctx, &act->tv_func);
+		duk_get_prop_string(ctx, -1, "fileName");
+		duk__debug_write_hstring_safe_top(thr);
+		duk_get_prop_string(ctx, -2, "name");
+		duk__debug_write_hstring_safe_top(thr);
+		duk_pop_3(ctx);
+		/* Report next pc/line to be executed. */
+		duk_debug_write_uint(thr, (duk_uint32_t) duk_debug_curr_line(thr));
+		duk_debug_write_uint(thr, (duk_uint32_t) duk_hthread_get_act_curr_pc(thr, act));
+	}
 
-	va_start(ap, fmt);
+	duk_debug_write_eom(thr);
+}
 
-	DUK_MEMZERO((void *) duk__debug_buf, (size_t) DUK__DEBUG_BUFSIZE);
-	duk_debug_vsnprintf(duk__debug_buf, DUK__DEBUG_BUFSIZE - 1, fmt, ap);
+#if defined(DUK_USE_DEBUGGER_THROW_NOTIFY)
+DUK_INTERNAL void duk_debug_send_throw(duk_hthread *thr, duk_bool_t fatal) {
+	/*
+	 *  NFY <int: 5> <int: fatal> <str: msg> <str: filename> <int: linenumber> EOM
+	 */
 
-#ifdef DUK_USE_DPRINT_RDTSC
-	DUK_FPRINTF(DUK_STDERR, "%s[%s] <%llu> %s:%s (%s):%s %s%s\n",
-	            (const char *) duk__get_term_1(level),
-	            (const char *) duk__get_level_string(duk_debug_level_stash),
-	            (unsigned long long) duk_rdtsc(),  /* match duk_features.h */
-	            (const char *) duk_debug_file_stash,
-	            (const char *) duk_debug_line_stash,
-	            (const char *) duk_debug_func_stash,
-	            (const char *) duk__get_term_2(level),
-	            (const char *) duk__debug_buf,
-	            (const char *) duk__get_term_3(level));
-#else
-	DUK_FPRINTF(DUK_STDERR, "%s[%s] %s:%s (%s):%s %s%s\n",
-	            (const char *) duk__get_term_1(level),
-	            (const char *) duk__get_level_string(duk_debug_level_stash),
-	            (const char *) duk_debug_file_stash,
-	            (const char *) duk_debug_line_stash,
-	            (const char *) duk_debug_func_stash,
-	            (const char *) duk__get_term_2(level),
-	            (const char *) duk__debug_buf,
-	            (const char *) duk__get_term_3(level));
-#endif
-	DUK_FFLUSH(DUK_STDERR);
+	duk_context *ctx = (duk_context *) thr;
+	duk_activation *act;
+	duk_uint32_t pc;
 
-	va_end(ap);
-}
+	DUK_ASSERT(thr->valstack_top > thr->valstack);  /* At least: ... [err] */
 
-#endif  /* DUK_USE_VARIADIC_MACROS */
+	duk_debug_write_notify(thr, DUK_DBG_CMD_THROW);
+	duk_debug_write_int(thr, fatal);
 
-#else  /* DUK_USE_DEBUG */
+	/* Report thrown value to client coerced to string */
+	duk_dup(ctx, -1);
+	duk__debug_write_hstring_safe_top(thr);
+	duk_pop(ctx);
 
-/*
- *  Debugging disabled
- */
+	if (duk_is_error(ctx, -1)) {
+		/* Error instance, use augmented error data directly */
+		duk_get_prop_stridx(ctx, -1, DUK_STRIDX_FILE_NAME);
+		duk__debug_write_hstring_safe_top(thr);
+		duk_get_prop_stridx(ctx, -2, DUK_STRIDX_LINE_NUMBER);
+		duk_debug_write_uint(thr, duk_get_uint(ctx, -1));
+	} else {
+		/* For anything other than an Error instance, we calculate the error
+		 * location directly from the current activation.
+		 */
+		act = thr->callstack + thr->callstack_top - 1;
+		duk_push_tval(ctx, &act->tv_func);
+		duk_get_prop_string(ctx, -1, "fileName");
+		duk__debug_write_hstring_safe_top(thr);
+		pc = duk_hthread_get_act_prev_pc(thr, act);
+		duk_debug_write_uint(thr, (duk_uint32_t) duk_hobject_pc2line_query(ctx, -2, pc));
+	}
+	duk_pop_2(ctx);  /* shared pop */
+
+	duk_debug_write_eom(thr);
+}
+#endif  /* DUK_USE_DEBUGGER_THROW_NOTIFY */
 
-#endif  /* DUK_USE_DEBUG */
-#line 1 "duk_debug_vsnprintf.c"
 /*
- *  Custom formatter for debug printing, allowing Duktape specific data
- *  structures (such as tagged values and heap objects) to be printed with
- *  a nice format string.  Because debug printing should not affect execution
- *  state, formatting here must be independent of execution (see implications
- *  below) and must not allocate memory.
- *
- *  Custom format tags begin with a '%!' to safely distinguish them from
- *  standard format tags.  The following conversions are supported:
- *
- *     %!T    tagged value (duk_tval *)
- *     %!O    heap object (duk_heaphdr *)
- *     %!I    decoded bytecode instruction
- *     %!C    bytecode instruction opcode name (arg is long)
- *
- *  Everything is serialized in a JSON-like manner.  The default depth is one
- *  level, internal prototype is not followed, and internal properties are not
- *  serialized.  The following modifiers change this behavior:
- *
- *     @      print pointers
- *     #      print binary representations (where applicable)
- *     d      deep traversal of own properties (not prototype)
- *     p      follow prototype chain (useless without 'd')
- *     i      include internal properties (other than prototype)
- *     x      hexdump buffers
- *     h      heavy formatting
- *
- *  For instance, the following serializes objects recursively, but does not
- *  follow the prototype chain nor print internal properties: "%!dO".
- *
- *  Notes:
- *
- *    * Standard snprintf return value semantics seem to vary.  This
- *      implementation returns the number of bytes it actually wrote
- *      (excluding the null terminator).  If retval == buffer size,
- *      output was truncated (except for corner cases).
- *
- *    * Output format is intentionally different from Ecmascript
- *      formatting requirements, as formatting here serves debugging
- *      of internals.
- *
- *    * Depth checking (and updating) is done in each type printer
- *      separately, to allow them to call each other freely.
- *
- *    * Some pathological structures might take ages to print (e.g.
- *      self recursion with 100 properties pointing to the object
- *      itself).  To guard against these, each printer also checks
- *      whether the output buffer is full; if so, early exit.
- *
- *    * Reference loops are detected using a loop stack.
+ *  Debug message processing
  */
 
-/* include removed: duk_internal.h */
+/* Skip dvalue. */
+DUK_LOCAL duk_bool_t duk__debug_skip_dvalue(duk_hthread *thr) {
+	duk_uint8_t x;
+	duk_uint32_t len;
+
+	x = duk_debug_read_byte(thr);
+
+	if (x >= 0xc0) {
+		duk_debug_skip_byte(thr);
+		return 0;
+	}
+	if (x >= 0x80) {
+		return 0;
+	}
+	if (x >= 0x60) {
+		duk_debug_skip_bytes(thr, x - 0x60);
+		return 0;
+	}
+	switch(x) {
+	case 0x00:
+		return 1;  /* Return 1: got EOM */
+	case 0x01:
+	case 0x02:
+	case 0x03:
+	case 0x04:
+		break;
+	case 0x10:
+		(void) duk__debug_read_uint32_raw(thr);
+		break;
+	case 0x11:
+	case 0x13:
+		len = duk__debug_read_uint32_raw(thr);
+		duk_debug_skip_bytes(thr, len);
+		break;
+	case 0x12:
+	case 0x14:
+		len = duk__debug_read_uint16_raw(thr);
+		duk_debug_skip_bytes(thr, len);
+		break;
+	case 0x15:
+	case 0x16:
+	case 0x17:
+	case 0x18:
+	case 0x19:
+		break;
+	case 0x1a:
+		duk_debug_skip_bytes(thr, 8);
+		break;
+	case 0x1b:
+		duk_debug_skip_byte(thr);
+		len = duk_debug_read_byte(thr);
+		duk_debug_skip_bytes(thr, len);
+		break;
+	case 0x1c:
+		len = duk_debug_read_byte(thr);
+		duk_debug_skip_bytes(thr, len);
+		break;
+	case 0x1d:
+		duk_debug_skip_bytes(thr, 2);
+		len = duk_debug_read_byte(thr);
+		duk_debug_skip_bytes(thr, len);
+		break;
+	default:
+		goto fail;
+	}
+
+	return 0;
 
-#ifdef DUK_USE_DEBUG
+ fail:
+	DUK__SET_CONN_BROKEN(thr, 1);
+	return 1;  /* Pretend like we got EOM */
+}
 
-#include <stdio.h>
-#include <stdarg.h>
-#include <string.h>
+/* Skip dvalues to EOM. */
+DUK_LOCAL void duk__debug_skip_to_eom(duk_hthread *thr) {
+	for (;;) {
+		if (duk__debug_skip_dvalue(thr)) {
+			break;
+		}
+	}
+}
 
-/* list of conversion specifiers that terminate a format tag;
- * this is unfortunately guesswork.
+/*
+ *  Process incoming debug requests
+ *
+ *  Individual request handlers can push temporaries on the value stack and
+ *  rely on duk__debug_process_message() to restore the value stack top
+ *  automatically.
  */
-#define DUK__ALLOWED_STANDARD_SPECIFIERS  "diouxXeEfFgGaAcsCSpnm"
-
-/* maximum length of standard format tag that we support */
-#define DUK__MAX_FORMAT_TAG_LENGTH  32
 
-/* heapobj recursion depth when deep printing is selected */
-#define DUK__DEEP_DEPTH_LIMIT  8
+DUK_LOCAL void duk__debug_handle_basic_info(duk_hthread *thr, duk_heap *heap) {
+	DUK_UNREF(heap);
+	DUK_D(DUK_DPRINT("debug command Version"));
 
-/* maximum recursion depth for loop detection stacks */
-#define DUK__LOOP_STACK_DEPTH  256
+	duk_debug_write_reply(thr);
+	duk_debug_write_int(thr, DUK_VERSION);
+	duk_debug_write_cstring(thr, DUK_GIT_DESCRIBE);
+	duk_debug_write_cstring(thr, DUK_USE_TARGET_INFO);
+#if defined(DUK_USE_DOUBLE_LE)
+	duk_debug_write_int(thr, 1);
+#elif defined(DUK_USE_DOUBLE_ME)
+	duk_debug_write_int(thr, 2);
+#elif defined(DUK_USE_DOUBLE_BE)
+	duk_debug_write_int(thr, 3);
+#else
+	duk_debug_write_int(thr, 0);
+#endif
+	duk_debug_write_eom(thr);
+}
 
-/* must match bytecode defines now; build autogenerate? */
-static const char *duk__bc_optab[] = {
-	"LDREG",    "STREG",    "LDCONST",  "LDINT",    "LDINTX",   "MPUTOBJ",  "MPUTOBJI", "MPUTARR",  "MPUTARRI", "NEW",
-	"NEWI",     "REGEXP", 	"CSREG",    "CSREGI",   "GETVAR",   "PUTVAR",   "DECLVAR",  "DELVAR",   "CSVAR",    "CSVARI",
-	"CLOSURE",  "GETPROP", 	"PUTPROP",  "DELPROP",  "CSPROP",   "CSPROPI",  "ADD",      "SUB",      "MUL",      "DIV",
-	"MOD",      "BAND",     "BOR",      "BXOR",     "BASL",     "BLSR", 	"BASR",     "BNOT", 	"LNOT",     "EQ",
-	"NEQ",      "SEQ",      "SNEQ",     "GT",       "GE",       "LT",       "LE",       "IF", 	"INSTOF",   "IN",
-	"JUMP",     "RETURN",   "CALL",     "CALLI",    "LABEL",    "ENDLABEL", "BREAK",    "CONTINUE", "TRYCATCH", "UNUSED59",
-	"UNUSED60", "EXTRA",    "DEBUG",    "INVALID",
-};
+DUK_LOCAL void duk__debug_handle_trigger_status(duk_hthread *thr, duk_heap *heap) {
+	DUK_UNREF(heap);
+	DUK_D(DUK_DPRINT("debug command TriggerStatus"));
 
-static const char *duk__bc_extraoptab[] = {
-	"NOP", "LDTHIS", "LDUNDEF", "LDNULL", "LDTRUE", "LDFALSE", "NEWOBJ", "NEWARR", "SETALEN", "TYPEOF",
-	"TYPEOFID", "TONUM", "INITENUM", "NEXTENUM", "INITSET", "INITSETI", "INITGET", "INITGETI", "ENDTRY", "ENDCATCH",
-	"ENDFIN", "THROW", "INVLHS", "UNM", "UNP", "INC", "DEC", "XXX", "XXX", "XXX",
-	"XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX",
-	"XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX",
+	duk_debug_write_reply(thr);
+	duk_debug_write_eom(thr);
+	heap->dbg_state_dirty = 1;
+}
 
-	"XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX",
-	"XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX",
-	"XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX",
-	"XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX",
-	"XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX",
+DUK_LOCAL void duk__debug_handle_pause(duk_hthread *thr, duk_heap *heap) {
+	DUK_D(DUK_DPRINT("debug command Pause"));
 
-	"XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX",
-	"XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX",
-	"XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX",
-	"XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX",
-	"XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX",
+	DUK_HEAP_SET_PAUSED(heap);
+	duk_debug_write_reply(thr);
+	duk_debug_write_eom(thr);
+}
 
-	"XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX",
-	"XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX",
-	"XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX",
-	"XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX",
-	"XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX",
+DUK_LOCAL void duk__debug_handle_resume(duk_hthread *thr, duk_heap *heap) {
+	DUK_D(DUK_DPRINT("debug command Resume"));
 
-	"XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX",
-	"XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX",
-	"XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX",
-	"XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX",
-	"XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX",
+	DUK_HEAP_CLEAR_PAUSED(heap);
+	duk_debug_write_reply(thr);
+	duk_debug_write_eom(thr);
+}
 
-	"XXX", "XXX", "XXX", "XXX", "XXX", "XXX",
-};
+DUK_LOCAL void duk__debug_handle_step(duk_hthread *thr, duk_heap *heap, duk_int32_t cmd) {
+	duk_small_uint_t step_type;
+	duk_uint_fast32_t line;
 
-typedef struct duk__dprint_state duk__dprint_state;
-struct duk__dprint_state {
-	duk_fixedbuffer *fb;
+	if (cmd == DUK_DBG_CMD_STEPINTO) {
+		step_type = DUK_STEP_TYPE_INTO;
+	} else if (cmd == DUK_DBG_CMD_STEPOVER) {
+		step_type = DUK_STEP_TYPE_OVER;
+	} else {
+		DUK_ASSERT(cmd == DUK_DBG_CMD_STEPOUT);
+		step_type = DUK_STEP_TYPE_OUT;
+	}
+
+	DUK_D(DUK_DPRINT("debug command StepInto/StepOver/StepOut: %d", (int) cmd));
+	line = duk_debug_curr_line(thr);
+	if (line > 0) {
+		heap->dbg_paused = 0;
+		heap->dbg_step_type = step_type;
+		heap->dbg_step_thread = thr;
+		heap->dbg_step_csindex = thr->callstack_top - 1;
+		heap->dbg_step_startline = line;
+		heap->dbg_state_dirty = 1;
+	} else {
+		DUK_D(DUK_DPRINT("cannot determine current line, stepinto/stepover/stepout ignored"));
+	}
+	duk_debug_write_reply(thr);
+	duk_debug_write_eom(thr);
+}
 
-	/* loop_stack_index could be perhaps be replaced by 'depth', but it's nice
-	 * to not couple these two mechanisms unnecessarily.
-	 */
-	duk_hobject *loop_stack[DUK__LOOP_STACK_DEPTH];
-	duk_int_t loop_stack_index;
-	duk_int_t loop_stack_limit;
+DUK_LOCAL void duk__debug_handle_list_break(duk_hthread *thr, duk_heap *heap) {
+	duk_small_int_t i;
 
-	duk_int_t depth;
-	duk_int_t depth_limit;
+	DUK_D(DUK_DPRINT("debug command ListBreak"));
+	duk_debug_write_reply(thr);
+	for (i = 0; i < (duk_small_int_t) heap->dbg_breakpoint_count; i++) {
+		duk_debug_write_hstring(thr, heap->dbg_breakpoints[i].filename);
+		duk_debug_write_uint(thr, (duk_uint32_t) heap->dbg_breakpoints[i].line);
+	}
+	duk_debug_write_eom(thr);
+}
 
-	duk_bool_t pointer;
-	duk_bool_t heavy;
-	duk_bool_t binary;
-	duk_bool_t follow_proto;
-	duk_bool_t internal;
-	duk_bool_t hexdump;
-};
+DUK_LOCAL void duk__debug_handle_add_break(duk_hthread *thr, duk_heap *heap) {
+	duk_hstring *filename;
+	duk_uint32_t linenumber;
+	duk_small_int_t idx;
 
-/* helpers */
-static void duk__print_hstring(duk__dprint_state *st, duk_hstring *k, duk_bool_t quotes);
-static void duk__print_hobject(duk__dprint_state *st, duk_hobject *h);
-static void duk__print_hbuffer(duk__dprint_state *st, duk_hbuffer *h);
-static void duk__print_tval(duk__dprint_state *st, duk_tval *tv);
-static void duk__print_instr(duk__dprint_state *st, duk_instr_t ins);
-static void duk__print_heaphdr(duk__dprint_state *st, duk_heaphdr *h);
-static void duk__print_shared_heaphdr(duk__dprint_state *st, duk_heaphdr *h);
-static void duk__print_shared_heaphdr_string(duk__dprint_state *st, duk_heaphdr_string *h);
-
-static void duk__print_shared_heaphdr(duk__dprint_state *st, duk_heaphdr *h) {
-	duk_fixedbuffer *fb = st->fb;
+	DUK_UNREF(heap);
 
-	if (st->heavy) {
-		duk_fb_sprintf(fb, "(%p)", (void *) h);
+	filename = duk_debug_read_hstring(thr);
+	linenumber = (duk_uint32_t) duk_debug_read_int(thr);
+	DUK_D(DUK_DPRINT("debug command AddBreak: %!O:%ld", (duk_hobject *) filename, (long) linenumber));
+	idx = duk_debug_add_breakpoint(thr, filename, linenumber);
+	if (idx >= 0) {
+		duk_debug_write_reply(thr);
+		duk_debug_write_int(thr, (duk_int32_t) idx);
+		duk_debug_write_eom(thr);
+	} else {
+		duk_debug_write_error_eom(thr, DUK_DBG_ERR_TOOMANY, "no space for breakpoint");
 	}
+}
 
-	if (!h) {
-		return;
-	}
+DUK_LOCAL void duk__debug_handle_del_break(duk_hthread *thr, duk_heap *heap) {
+	duk_small_uint_t idx;
 
-	if (st->binary) {
-		duk_size_t i;
-		duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_LBRACKET);
-		for (i = 0; i < (duk_size_t) sizeof(*h); i++) {
-			duk_fb_sprintf(fb, "%02lx", (unsigned long) ((duk_uint8_t *)h)[i]);
-		}
-		duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_RBRACKET);
-	}
+	DUK_UNREF(heap);
 
-#ifdef DUK_USE_REFERENCE_COUNTING  /* currently implicitly also DUK_USE_DOUBLE_LINKED_HEAP */
-	if (st->heavy) {
-		duk_fb_sprintf(fb, "[h_next=%p,h_prev=%p,h_refcount=%lu,h_flags=%08lx,type=%ld,"
-		               "reachable=%ld,temproot=%ld,finalizable=%ld,finalized=%ld]",
-		               (void *) DUK_HEAPHDR_GET_NEXT(h),
-		               (void *) DUK_HEAPHDR_GET_PREV(h),
-		               (unsigned long) DUK_HEAPHDR_GET_REFCOUNT(h),
-		               (unsigned long) DUK_HEAPHDR_GET_FLAGS(h),
-		               (long) DUK_HEAPHDR_GET_TYPE(h),
-		               (long) (DUK_HEAPHDR_HAS_REACHABLE(h) ? 1 : 0),
-		               (long) (DUK_HEAPHDR_HAS_TEMPROOT(h) ? 1 : 0),
-		               (long) (DUK_HEAPHDR_HAS_FINALIZABLE(h) ? 1 : 0),
-		               (long) (DUK_HEAPHDR_HAS_FINALIZED(h) ? 1 : 0));
-	}
-#else
-	if (st->heavy) {
-		duk_fb_sprintf(fb, "[h_next=%p,h_flags=%08lx,type=%ld,reachable=%ld,temproot=%ld,finalizable=%ld,finalized=%ld]",
-		               (void *) DUK_HEAPHDR_GET_NEXT(h),
-		               (unsigned long) DUK_HEAPHDR_GET_FLAGS(h),
-		               (long) DUK_HEAPHDR_GET_TYPE(h),
-		               (long) (DUK_HEAPHDR_HAS_REACHABLE(h) ? 1 : 0),
-		               (long) (DUK_HEAPHDR_HAS_TEMPROOT(h) ? 1 : 0),
-		               (long) (DUK_HEAPHDR_HAS_FINALIZABLE(h) ? 1 : 0),
-		               (long) (DUK_HEAPHDR_HAS_FINALIZED(h) ? 1 : 0));
+	DUK_D(DUK_DPRINT("debug command DelBreak"));
+	idx = (duk_small_uint_t) duk_debug_read_int(thr);
+	if (duk_debug_remove_breakpoint(thr, idx)) {
+		duk_debug_write_reply(thr);
+		duk_debug_write_eom(thr);
+	} else {
+		duk_debug_write_error_eom(thr, DUK_DBG_ERR_NOTFOUND, "invalid breakpoint index");
 	}
-#endif
 }
 
-static void duk__print_shared_heaphdr_string(duk__dprint_state *st, duk_heaphdr_string *h) {
-	duk_fixedbuffer *fb = st->fb;
-
-	if (st->heavy) {
-		duk_fb_sprintf(fb, "(%p)", (void *) h);
-	}
+DUK_LOCAL void duk__debug_handle_get_var(duk_hthread *thr, duk_heap *heap) {
+	duk_context *ctx = (duk_context *) thr;
+	duk_hstring *str;
+	duk_bool_t rc;
+	duk_int32_t level;
 
-	if (!h) {
-		return;
-	}
+	DUK_UNREF(heap);
+	DUK_D(DUK_DPRINT("debug command GetVar"));
 
-	if (st->binary) {
-		duk_size_t i;
-		duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_LBRACKET);
-		for (i = 0; i < (duk_size_t) sizeof(*h); i++) {
-			duk_fb_sprintf(fb, "%02lx", (unsigned long) ((duk_uint8_t *)h)[i]);
+	str = duk_debug_read_hstring(thr);  /* push to stack */
+	DUK_ASSERT(str != NULL);
+	if (duk_debug_peek_byte(thr) != DUK_DBG_MARKER_EOM) {
+		level = duk_debug_read_int(thr);  /* optional callstack level */
+		if (level >= 0 || -level > (duk_int32_t) thr->callstack_top) {
+			DUK_D(DUK_DPRINT("invalid callstack level for GetVar"));
+			duk_debug_write_error_eom(thr, DUK_DBG_ERR_NOTFOUND, "invalid callstack level");
+			return;
 		}
-		duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_RBRACKET);
+	} else {
+		level = -1;
 	}
 
-#ifdef DUK_USE_REFERENCE_COUNTING
-	if (st->heavy) {
-		duk_fb_sprintf(fb, "[h_refcount=%lu,h_flags=%08lx,type=%ld,reachable=%ld,temproot=%ld,finalizable=%ld,finalized=%ld]",
-		               (unsigned long) DUK_HEAPHDR_GET_REFCOUNT((duk_heaphdr *) h),
-		               (unsigned long) DUK_HEAPHDR_GET_FLAGS((duk_heaphdr *) h),
-		               (long) DUK_HEAPHDR_GET_TYPE((duk_heaphdr *) h),
-		               (long) (DUK_HEAPHDR_HAS_REACHABLE((duk_heaphdr *) h) ? 1 : 0),
-		               (long) (DUK_HEAPHDR_HAS_TEMPROOT((duk_heaphdr *) h) ? 1 : 0),
-		               (long) (DUK_HEAPHDR_HAS_FINALIZABLE((duk_heaphdr *) h) ? 1 : 0),
-		               (long) (DUK_HEAPHDR_HAS_FINALIZED((duk_heaphdr *) h) ? 1 : 0));
+	if (thr->callstack_top > 0) {
+		rc = duk_js_getvar_activation(thr,
+		                              thr->callstack + thr->callstack_top + level,
+		                              str,
+		                              0);
+	} else {
+		/* No activation, no variable access.  Could also pretend
+		 * we're in the global program context and read stuff off
+		 * the global object.
+		 */
+		DUK_D(DUK_DPRINT("callstack empty, no activation -> ignore getvar"));
+		rc = 0;
 	}
-#else
-	if (st->heavy) {
-		duk_fb_sprintf(fb, "[h_flags=%08lx,type=%ld,reachable=%ld,temproot=%ld,finalizable=%ld,finalized=%ld]",
-		               (unsigned long) DUK_HEAPHDR_GET_FLAGS((duk_heaphdr *) h),
-		               (long) DUK_HEAPHDR_GET_TYPE((duk_heaphdr *) h),
-		               (long) (DUK_HEAPHDR_HAS_REACHABLE((duk_heaphdr *) h) ? 1 : 0),
-		               (long) (DUK_HEAPHDR_HAS_TEMPROOT((duk_heaphdr *) h) ? 1 : 0),
-		               (long) (DUK_HEAPHDR_HAS_FINALIZABLE((duk_heaphdr *) h) ? 1 : 0),
-		               (long) (DUK_HEAPHDR_HAS_FINALIZED((duk_heaphdr *) h) ? 1 : 0));
+
+	duk_debug_write_reply(thr);
+	if (rc) {
+		duk_debug_write_int(thr, 1);
+		DUK_ASSERT(duk_get_tval(ctx, -2) != NULL);
+		duk_debug_write_tval(thr, duk_get_tval(ctx, -2));
+	} else {
+		duk_debug_write_int(thr, 0);
+		duk_debug_write_unused(thr);
 	}
-#endif
+	duk_debug_write_eom(thr);
 }
 
-static void duk__print_hstring(duk__dprint_state *st, duk_hstring *h, duk_bool_t quotes) {
-	duk_fixedbuffer *fb = st->fb;
-	duk_uint8_t *p;
-	duk_uint8_t *p_end;
+DUK_LOCAL void duk__debug_handle_put_var(duk_hthread *thr, duk_heap *heap) {
+	duk_context *ctx = (duk_context *) thr;
+	duk_hstring *str;
+	duk_tval *tv;
+	duk_int32_t level;
 
-	/* terminal type: no depth check */
+	DUK_UNREF(heap);
+	DUK_D(DUK_DPRINT("debug command PutVar"));
 
-	if (duk_fb_is_full(fb)) {
-		return;
+	str = duk_debug_read_hstring(thr);  /* push to stack */
+	DUK_ASSERT(str != NULL);
+	duk_debug_read_tval(thr);           /* push to stack */
+	tv = duk_get_tval(ctx, -1);
+	DUK_ASSERT(tv != NULL);
+	if (duk_debug_peek_byte(thr) != DUK_DBG_MARKER_EOM) {
+		level = duk_debug_read_int(thr);  /* optional callstack level */
+		if (level >= 0 || -level > (duk_int32_t) thr->callstack_top) {
+			DUK_D(DUK_DPRINT("invalid callstack level for PutVar"));
+			duk_debug_write_error_eom(thr, DUK_DBG_ERR_NOTFOUND, "invalid callstack level");
+			return;
+		}
+	} else {
+		level = -1;
 	}
 
-	duk__print_shared_heaphdr_string(st, &h->hdr);
-
-	if (!h) {
-		duk_fb_put_cstring(fb, "NULL");
-		return;
+	if (thr->callstack_top > 0) {
+		duk_js_putvar_activation(thr,
+		                         thr->callstack + thr->callstack_top + level,
+		                         str,
+		                         tv,
+		                         0);
+	} else {
+		DUK_D(DUK_DPRINT("callstack empty, no activation -> ignore putvar"));
 	}
 
-	p = DUK_HSTRING_GET_DATA(h);
-	p_end = p + DUK_HSTRING_GET_BYTELEN(h);
+	/* XXX: Current putvar implementation doesn't have a success flag,
+	 * add one and send to debug client?
+	 */
+	duk_debug_write_reply(thr);
+	duk_debug_write_eom(thr);
+}
 
-	if (p_end > p && p[0] == DUK_ASC_UNDERSCORE) {
-		/* if property key begins with underscore, encode it with
-		 * forced quotes (e.g. "_foo") to distinguish it from encoded
-		 * internal properties (e.g. \xffbar -> _bar).
-		 */
-		quotes = 1;
-	}
+DUK_LOCAL void duk__debug_handle_get_call_stack(duk_hthread *thr, duk_heap *heap) {
+	duk_context *ctx = (duk_context *) thr;
+	duk_hthread *curr_thr = thr;
+	duk_activation *curr_act;
+	duk_uint_fast32_t pc;
+	duk_uint_fast32_t line;
+	duk_size_t i;
 
-	if (quotes) {
-		duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_DOUBLEQUOTE);
-	}
-	while (p < p_end) {
-		duk_uint8_t ch = *p++;
+	DUK_UNREF(heap);
 
-		/* two special escapes: '\' and '"', other printables as is */
-		if (ch == '\\') {
-			duk_fb_sprintf(fb, "\\\\");
-		} else if (ch == '"') {
-			duk_fb_sprintf(fb, "\\\"");
-		} else if (ch >= 0x20 && ch <= 0x7e) {
-			duk_fb_put_byte(fb, ch);
-		} else if (ch == 0xff && !quotes) {
-			/* encode \xffbar as _bar if no quotes are applied, this is for
-			 * readable internal keys.
+	duk_debug_write_reply(thr);
+	while (curr_thr != NULL) {
+		i = curr_thr->callstack_top;
+		while (i > 0) {
+			i--;
+			curr_act = curr_thr->callstack + i;
+
+			/* PC/line semantics here are:
+			 *   - For callstack top we're conceptually between two
+			 *     opcodes and current PC indicates next line to
+			 *     execute, so report that (matches Status).
+			 *   - For other activations we're conceptually still
+			 *     executing the instruction at PC-1, so report that
+			 *     (matches error stacktrace behavior).
+			 *   - See: https://github.com/svaarala/duktape/issues/281
 			 */
-			duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_UNDERSCORE);
-		} else {
-			duk_fb_sprintf(fb, "\\x%02lx", (unsigned long) ch);
+
+			/* XXX: optimize to use direct reads, i.e. avoid
+			 * value stack operations.
+			 */
+			duk_push_tval(ctx, &curr_act->tv_func);
+			duk_get_prop_stridx(ctx, -1, DUK_STRIDX_FILE_NAME);
+			duk__debug_write_hstring_safe_top(thr);
+			duk_get_prop_stridx(ctx, -2, DUK_STRIDX_NAME);
+			duk__debug_write_hstring_safe_top(thr);
+			pc = duk_hthread_get_act_curr_pc(thr, curr_act);
+			if (i != curr_thr->callstack_top - 1 && pc > 0) {
+				pc--;
+			}
+			line = duk_hobject_pc2line_query(ctx, -3, pc);
+			duk_debug_write_uint(thr, (duk_uint32_t) line);
+			duk_debug_write_uint(thr, (duk_uint32_t) pc);
+			duk_pop_3(ctx);
 		}
+		curr_thr = curr_thr->resumer;
 	}
-	if (quotes) {
-		duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_DOUBLEQUOTE);
-	}
-#ifdef DUK_USE_REFERENCE_COUNTING
-	/* XXX: limit to quoted strings only, to save keys from being cluttered? */
-	duk_fb_sprintf(fb, "/%lu", (unsigned long) DUK_HEAPHDR_GET_REFCOUNT(&h->hdr));
-#endif
+	duk_debug_write_eom(thr);
 }
 
-#ifdef DUK__COMMA
-#undef DUK__COMMA
-#endif
-#define DUK__COMMA()  do { \
-		if (first) { \
-			first = 0; \
-		} else { \
-			duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_COMMA); \
-		} \
-	} while (0)
+DUK_LOCAL void duk__debug_handle_get_locals(duk_hthread *thr, duk_heap *heap) {
+	duk_context *ctx = (duk_context *) thr;
+	duk_activation *curr_act;
+	duk_int32_t level;
+	duk_hstring *varname;
 
-static void duk__print_hobject(duk__dprint_state *st, duk_hobject *h) {
-	duk_fixedbuffer *fb = st->fb;
-	duk_uint_fast32_t i;
-	duk_tval *tv;
-	duk_hstring *key;
-	duk_bool_t first = 1;
-	char *brace1 = "{";
-	char *brace2 = "}";
-	duk_bool_t pushed_loopstack = 0;
+	DUK_UNREF(heap);
 
-	if (duk_fb_is_full(fb)) {
-		return;
+	if (duk_debug_peek_byte(thr) != DUK_DBG_MARKER_EOM) {
+		level = duk_debug_read_int(thr);  /* optional callstack level */
+		if (level >= 0 || -level > (duk_int32_t) thr->callstack_top) {
+			DUK_D(DUK_DPRINT("invalid callstack level for GetLocals"));
+			duk_debug_write_error_eom(thr, DUK_DBG_ERR_NOTFOUND, "invalid callstack level");
+			return;
+		}
+		duk_debug_write_reply(thr);
+	} else {
+		duk_debug_write_reply(thr);
+		if (thr->callstack_top == 0) {
+			goto callstack_empty;
+		}
+		level = -1;
 	}
 
-	duk__print_shared_heaphdr(st, &h->hdr);
-
-	if (h && DUK_HOBJECT_HAS_ARRAY_PART(h)) {
-		brace1 = "[";
-		brace2 = "]";
-	}
+	curr_act = thr->callstack + thr->callstack_top + level;
 
-	if (!h) {
-		duk_fb_put_cstring(fb, "NULL");
-		goto finished;
-	}
+	/* XXX: several nice-to-have improvements here:
+	 *   - Use direct reads avoiding value stack operations
+	 *   - Avoid triggering getters, indicate getter values to debug client
+	 *   - If side effects are possible, add error catching
+	 */
 
-	if (st->depth >= st->depth_limit) {
-		if (DUK_HOBJECT_IS_COMPILEDFUNCTION(h)) {
-			duk_fb_sprintf(fb, "%sobject/compiledfunction %p%s", (const char *) brace1, (void *) h, (const char *) brace2);
-		} else if (DUK_HOBJECT_IS_NATIVEFUNCTION(h)) {
-			duk_fb_sprintf(fb, "%sobject/nativefunction %p%s", (const char *) brace1, (void *) h, (const char *) brace2);
-		} else if (DUK_HOBJECT_IS_THREAD(h)) {
-			duk_fb_sprintf(fb, "%sobject/thread %p%s", (const char *) brace1, (void *) h, (const char *) brace2);
-		} else {
-			duk_fb_sprintf(fb, "%sobject %p%s", (const char *) brace1, (void *) h, (const char *) brace2);  /* may be NULL */
-		}
-		return;
-	}
+	duk_push_tval(ctx, &curr_act->tv_func);
+	duk_get_prop_stridx(ctx, -1, DUK_STRIDX_INT_VARMAP);
+	if (duk_is_object(ctx, -1)) {
+		duk_enum(ctx, -1, 0 /*enum_flags*/);
+		while (duk_next(ctx, -1 /*enum_index*/, 0 /*get_value*/)) {
+			varname = duk_get_hstring(ctx, -1);
+			DUK_ASSERT(varname != NULL);
 
-	for (i = 0; i < (duk_uint_fast32_t) st->loop_stack_index; i++) {
-		if (st->loop_stack[i] == h) {
-			duk_fb_sprintf(fb, "%sLOOP:%p%s", (const char *) brace1, (void *) h, (const char *) brace2);
-			return;
+			duk_js_getvar_activation(thr, curr_act, varname, 0 /*throw_flag*/);
+			/* [ ... func varmap enum key value this ] */
+			duk_debug_write_hstring(thr, duk_get_hstring(ctx, -3));
+			duk_debug_write_tval(thr, duk_get_tval(ctx, -2));
+			duk_pop_3(ctx);  /* -> [ ... func varmap enum ] */
 		}
+	} else {
+		DUK_D(DUK_DPRINT("varmap is not an object in GetLocals, ignore"));
 	}
 
-	/* after this, return paths should 'goto finished' for decrement */
-	st->depth++;
+ callstack_empty:
+	duk_debug_write_eom(thr);
+}
 
-	if (st->loop_stack_index >= st->loop_stack_limit) {
-		duk_fb_sprintf(fb, "%sOUT-OF-LOOP-STACK%s", (const char *) brace1, (const char *) brace2);
-		goto finished;
-	}
-	st->loop_stack[st->loop_stack_index++] = h;
-	pushed_loopstack = 1;
+DUK_LOCAL void duk__debug_handle_eval(duk_hthread *thr, duk_heap *heap) {
+	duk_context *ctx = (duk_context *) thr;
+	duk_small_uint_t call_flags;
+	duk_int_t call_ret;
+	duk_small_int_t eval_err;
+	duk_int32_t level;
 
-	/*
-	 *  Notation: double underscore used for internal properties which are not
-	 *  stored in the property allocation (e.g. '__valstack').
-	 */
+	DUK_UNREF(heap);
 
-	duk_fb_put_cstring(fb, brace1);
+	DUK_D(DUK_DPRINT("debug command Eval"));
 
-	if (h->p) {
-		duk_uint32_t a_limit;
+	/* The eval code is executed within the lexical environment of a specified
+	 * activation.  For now, use global object eval() function, with the eval
+	 * considered a 'direct call to eval'.
+	 *
+	 * Callstack level for debug commands only affects scope -- the callstack
+	 * as seen by, e.g. Duktape.act() will be the same regardless.
+	 */
 
-		a_limit = h->a_size;
-		if (st->internal) {
-			/* dump all allocated entries, unused entries print as 'unused',
-			 * note that these may extend beyond current 'length' and look
-			 * a bit funny.
-			 */
-		} else {
-			/* leave out trailing 'unused' elements */
-			while (a_limit > 0) {
-				tv = DUK_HOBJECT_A_GET_VALUE_PTR(h, a_limit - 1);
-				if (!DUK_TVAL_IS_UNDEFINED_UNUSED(tv)) {
-					break;
-				}
-				a_limit--;
-			}
-		}
+	/* nargs == 2 so we can pass a callstack level to eval(). */
+	duk_push_c_function(ctx, duk_bi_global_object_eval, 2 /*nargs*/);
+	duk_push_undefined(ctx);  /* 'this' binding shouldn't matter here */
 
-		for (i = 0; i < a_limit; i++) {
-			tv = DUK_HOBJECT_A_GET_VALUE_PTR(h, i);
-			DUK__COMMA();
-			duk__print_tval(st, tv);
-		}
-		for (i = 0; i < h->e_used; i++) {
-			key = DUK_HOBJECT_E_GET_KEY(h, i);
-			if (!key) {
-				continue;
-			}
-			if (!st->internal &&
-			    DUK_HSTRING_GET_BYTELEN(key) > 0 &&
-			    DUK_HSTRING_GET_DATA(key)[0] == 0xff) {
-				/* XXX: use DUK_HSTRING_FLAG_INTERNAL? */
-				continue;
-			}
-			DUK__COMMA();
-			duk__print_hstring(st, key, 0);
-			duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_COLON);
-			if (DUK_HOBJECT_E_SLOT_IS_ACCESSOR(h, i)) {
-				duk_fb_sprintf(fb, "[get:%p,set:%p]",
-				               (void *) DUK_HOBJECT_E_GET_VALUE(h, i).a.get,
-				               (void *) DUK_HOBJECT_E_GET_VALUE(h, i).a.set);
-			} else {
-				tv = &DUK_HOBJECT_E_GET_VALUE(h, i).v;
-				duk__print_tval(st, tv);
-			}
-			if (st->heavy) {
-				duk_fb_sprintf(fb, "<%02lx>", (unsigned long) DUK_HOBJECT_E_GET_FLAGS(h, i));
-			}
+	(void) duk_debug_read_hstring(thr);
+	if (duk_debug_peek_byte(thr) != DUK_DBG_MARKER_EOM) {
+		level = duk_debug_read_int(thr);  /* optional callstack level */
+		if (level >= 0 || -level > (duk_int32_t) thr->callstack_top) {
+			DUK_D(DUK_DPRINT("invalid callstack level for Eval"));
+			duk_debug_write_error_eom(thr, DUK_DBG_ERR_NOTFOUND, "invalid callstack level");
+			return;
 		}
 	}
-	if (st->internal) {
-		if (DUK_HOBJECT_HAS_EXTENSIBLE(h)) {
-			DUK__COMMA(); duk_fb_sprintf(fb, "__extensible:true");
-		} else {
-			;
-		}
-		if (DUK_HOBJECT_HAS_CONSTRUCTABLE(h)) {
-			DUK__COMMA(); duk_fb_sprintf(fb, "__constructable:true");
-		} else {
-			;
-		}
-		if (DUK_HOBJECT_HAS_BOUND(h)) {
-			DUK__COMMA(); duk_fb_sprintf(fb, "__bound:true");
-		} else {
-			;
-		}
-		if (DUK_HOBJECT_HAS_COMPILEDFUNCTION(h)) {
-			DUK__COMMA(); duk_fb_sprintf(fb, "__compiledfunction:true");
-		} else {
-			;
-		}
-		if (DUK_HOBJECT_HAS_NATIVEFUNCTION(h)) {
-			DUK__COMMA(); duk_fb_sprintf(fb, "__nativefunction:true");
-		} else {
-			;
-		}
-		if (DUK_HOBJECT_HAS_THREAD(h)) {
-			DUK__COMMA(); duk_fb_sprintf(fb, "__thread:true");
-		} else {
-			;
-		}
-		if (DUK_HOBJECT_HAS_ARRAY_PART(h)) {
-			DUK__COMMA(); duk_fb_sprintf(fb, "__array_part:true");
-		} else {
-			;
-		}
-		if (DUK_HOBJECT_HAS_STRICT(h)) {
-			DUK__COMMA(); duk_fb_sprintf(fb, "__strict:true");
-		} else {
-			;
-		}
-		if (DUK_HOBJECT_HAS_NEWENV(h)) {
-			DUK__COMMA(); duk_fb_sprintf(fb, "__newenv:true");
-		} else {
-			;
-		}
-		if (DUK_HOBJECT_HAS_NAMEBINDING(h)) {
-			DUK__COMMA(); duk_fb_sprintf(fb, "__namebinding:true");
-		} else {
-			;
-		}
-		if (DUK_HOBJECT_HAS_CREATEARGS(h)) {
-			DUK__COMMA(); duk_fb_sprintf(fb, "__createargs:true");
-		} else {
-			;
-		}
-		if (DUK_HOBJECT_HAS_ENVRECCLOSED(h)) {
-			DUK__COMMA(); duk_fb_sprintf(fb, "__envrecclosed:true");
-		} else {
-			;
-		}
-		if (DUK_HOBJECT_HAS_EXOTIC_ARRAY(h)) {
-			DUK__COMMA(); duk_fb_sprintf(fb, "__special_array:true");
-		} else {
-			;
-		}
-		if (DUK_HOBJECT_HAS_EXOTIC_STRINGOBJ(h)) {
-			DUK__COMMA(); duk_fb_sprintf(fb, "__special_stringobj:true");
-		} else {
-			;
-		}
-		if (DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(h)) {
-			DUK__COMMA(); duk_fb_sprintf(fb, "__special_arguments:true");
-		} else {
-			;
-		}
-		if (DUK_HOBJECT_HAS_EXOTIC_DUKFUNC(h)) {
-			DUK__COMMA(); duk_fb_sprintf(fb, "__special_dukfunc:true");
-		} else {
-			;
-		}
-		if (DUK_HOBJECT_HAS_EXOTIC_BUFFEROBJ(h)) {
-			DUK__COMMA(); duk_fb_sprintf(fb, "__special_bufferobj:true");
-		} else {
-			;
-		}
-		if (DUK_HOBJECT_HAS_EXOTIC_PROXYOBJ(h)) {
-			DUK__COMMA(); duk_fb_sprintf(fb, "__special_proxyobj:true");
-		} else {
-			;
-		}
+	else {
+		level = -1;
 	}
-	if (st->internal && DUK_HOBJECT_IS_COMPILEDFUNCTION(h)) {
-		duk_hcompiledfunction *f = (duk_hcompiledfunction *) h;
-		DUK__COMMA(); duk_fb_put_cstring(fb, "__data:"); duk__print_hbuffer(st, f->data);
-		DUK__COMMA(); duk_fb_sprintf(fb, "__nregs:%ld", (long) f->nregs);
-		DUK__COMMA(); duk_fb_sprintf(fb, "__nargs:%ld", (long) f->nargs);
-	} else if (st->internal && DUK_HOBJECT_IS_NATIVEFUNCTION(h)) {
-		duk_hnativefunction *f = (duk_hnativefunction *) h;
-#if 0  /* FIXME: no portable way to print function pointers */
-		DUK__COMMA(); duk_fb_sprintf(fb, "__func:%p", (void *) f->func);
-#endif
-		DUK__COMMA(); duk_fb_sprintf(fb, "__nargs:%ld", (long) f->nargs);
+	DUK_ASSERT(level < 0 && -level <= (duk_int32_t) thr->callstack_top);
+	duk_push_int(ctx, level - 1);  /* compensate for eval() call */
 
-	} else if (st->internal && DUK_HOBJECT_IS_THREAD(h)) {
-		duk_hthread *t = (duk_hthread *) h;
-		DUK__COMMA(); duk_fb_sprintf(fb, "__strict:%ld", (long) t->strict);
-		DUK__COMMA(); duk_fb_sprintf(fb, "__state:%ld", (long) t->state);
-		DUK__COMMA(); duk_fb_sprintf(fb, "__unused1:%ld", (long) t->unused1);
-		DUK__COMMA(); duk_fb_sprintf(fb, "__unused2:%ld", (long) t->unused2);
-		DUK__COMMA(); duk_fb_sprintf(fb, "__valstack_max:%ld", (long) t->valstack_max);
-		DUK__COMMA(); duk_fb_sprintf(fb, "__callstack_max:%ld", (long) t->callstack_max);
-		DUK__COMMA(); duk_fb_sprintf(fb, "__catchstack_max:%ld", (long) t->catchstack_max);
-		DUK__COMMA(); duk_fb_sprintf(fb, "__valstack:%p", (void *) t->valstack);
-		DUK__COMMA(); duk_fb_sprintf(fb, "__valstack_end:%p/%ld", (void *) t->valstack_end, (long) (t->valstack_end - t->valstack));
-		DUK__COMMA(); duk_fb_sprintf(fb, "__valstack_bottom:%p/%ld", (void *) t->valstack_bottom, (long) (t->valstack_bottom - t->valstack));
-		DUK__COMMA(); duk_fb_sprintf(fb, "__valstack_top:%p/%ld", (void *) t->valstack_top, (long) (t->valstack_top - t->valstack));
-		DUK__COMMA(); duk_fb_sprintf(fb, "__catchstack:%p", (void *) t->catchstack);
-		DUK__COMMA(); duk_fb_sprintf(fb, "__catchstack_size:%ld", (long) t->catchstack_size);
-		DUK__COMMA(); duk_fb_sprintf(fb, "__catchstack_top:%ld", (long) t->catchstack_top);
-		DUK__COMMA(); duk_fb_sprintf(fb, "__resumer:"); duk__print_hobject(st, (duk_hobject *) t->resumer);
-		/* XXX: print built-ins array? */
+	/* [ ... eval "eval" eval_input level ] */
 
+	call_flags = 0;
+	if (thr->callstack_top >= (duk_size_t) -level) {
+		duk_activation *act;
+		duk_hobject *fun;
+
+		act = thr->callstack + thr->callstack_top + level;
+		fun = DUK_ACT_GET_FUNC(act);
+		if (fun != NULL && DUK_HOBJECT_IS_COMPILEDFUNCTION(fun)) {
+			/* Direct eval requires that there's a current
+			 * activation and it is an Ecmascript function.
+			 * When Eval is executed from e.g. cooperate API
+			 * call we'll need to do an indirect eval instead.
+			 */
+			call_flags |= DUK_CALL_FLAG_DIRECT_EVAL;
+		}
 	}
-#ifdef DUK_USE_REFERENCE_COUNTING
-	if (st->internal) {
-		DUK__COMMA(); duk_fb_sprintf(fb, "__refcount:%lu", (unsigned long) DUK_HEAPHDR_GET_REFCOUNT((duk_heaphdr *) h));
+
+	call_ret = duk_handle_call_protected(thr, 2 /*num_stack_args*/, call_flags);
+
+	if (call_ret == DUK_EXEC_SUCCESS) {
+		eval_err = 0;
+		/* Use result value as is. */
+	} else {
+		/* For errors a string coerced result is most informative
+		 * right now, as the debug client doesn't have the capability
+		 * to traverse the error object.
+		 */
+		eval_err = 1;
+		duk_safe_to_string(ctx, -1);
 	}
+
+	/* [ ... result ] */
+
+	duk_debug_write_reply(thr);
+	duk_debug_write_int(thr, (duk_int32_t) eval_err);
+	DUK_ASSERT(duk_get_tval(ctx, -1) != NULL);
+	duk_debug_write_tval(thr, duk_get_tval(ctx, -1));
+	duk_debug_write_eom(thr);
+}
+
+DUK_LOCAL void duk__debug_handle_detach(duk_hthread *thr, duk_heap *heap) {
+	DUK_UNREF(heap);
+	DUK_D(DUK_DPRINT("debug command Detach"));
+
+	duk_debug_write_reply(thr);
+	duk_debug_write_eom(thr);
+
+	DUK_D(DUK_DPRINT("debug connection detached, mark broken"));
+	DUK__SET_CONN_BROKEN(thr, 0);  /* not an error */
+}
+
+#if defined(DUK_USE_DEBUGGER_DUMPHEAP)
+DUK_LOCAL void duk__debug_dump_heaphdr(duk_hthread *thr, duk_heap *heap, duk_heaphdr *hdr) {
+	DUK_UNREF(heap);
+
+	duk_debug_write_heapptr(thr, hdr);
+	duk_debug_write_uint(thr, (duk_uint32_t) DUK_HEAPHDR_GET_TYPE(hdr));
+	duk_debug_write_uint(thr, (duk_uint32_t) DUK_HEAPHDR_GET_FLAGS_RAW(hdr));
+#if defined(DUK_USE_REFERENCE_COUNTING)
+	duk_debug_write_uint(thr, (duk_uint32_t) DUK_HEAPHDR_GET_REFCOUNT(hdr));
+#else
+	duk_debug_write_int(thr, (duk_int32_t) -1);
 #endif
-	if (st->internal) {
-		DUK__COMMA(); duk_fb_sprintf(fb, "__class:%ld", (long) DUK_HOBJECT_GET_CLASS_NUMBER(h));
-	}
 
-	/* prototype should be last, for readability */
-	if (st->follow_proto && h->prototype) {
-		DUK__COMMA(); duk_fb_put_cstring(fb, "__prototype:"); duk__print_hobject(st, h->prototype);
-	}
+	switch (DUK_HEAPHDR_GET_TYPE(hdr)) {
+	case DUK_HTYPE_STRING: {
+		duk_hstring *h = (duk_hstring *) hdr;
 
-	duk_fb_put_cstring(fb, brace2);
+		duk_debug_write_uint(thr, (duk_int32_t) DUK_HSTRING_GET_BYTELEN(h));
+		duk_debug_write_uint(thr, (duk_int32_t) DUK_HSTRING_GET_CHARLEN(h));
+		duk_debug_write_uint(thr, (duk_int32_t) DUK_HSTRING_GET_HASH(h));
+		duk_debug_write_hstring(thr, h);
+		break;
+	}
+	case DUK_HTYPE_OBJECT: {
+		duk_hobject *h = (duk_hobject *) hdr;
+		duk_hstring *k;
+		duk_uint_fast32_t i;
 
-	if (st->heavy && h->h_size > 0) {
-		duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_LANGLE);
-		for (i = 0; i < h->h_size; i++) {
-			duk_uint_t h_idx = DUK_HOBJECT_H_GET_INDEX(h, i);
-			if (i > 0) {
-				duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_COMMA);
+		duk_debug_write_uint(thr, (duk_uint32_t) DUK_HOBJECT_GET_CLASS_NUMBER(h));
+		duk_debug_write_heapptr(thr, (duk_heaphdr *) DUK_HOBJECT_GET_PROTOTYPE(heap, h));
+		duk_debug_write_uint(thr, (duk_uint32_t) DUK_HOBJECT_GET_ESIZE(h));
+		duk_debug_write_uint(thr, (duk_uint32_t) DUK_HOBJECT_GET_ENEXT(h));
+		duk_debug_write_uint(thr, (duk_uint32_t) DUK_HOBJECT_GET_ASIZE(h));
+		duk_debug_write_uint(thr, (duk_uint32_t) DUK_HOBJECT_GET_HSIZE(h));
+
+		for (i = 0; i < (duk_uint_fast32_t) DUK_HOBJECT_GET_ENEXT(h); i++) {
+			duk_debug_write_uint(thr, (duk_uint32_t) DUK_HOBJECT_E_GET_FLAGS(heap, h, i));
+			k = DUK_HOBJECT_E_GET_KEY(heap, h, i);
+			duk_debug_write_heapptr(thr, (duk_heaphdr *) k);
+			if (k == NULL) {
+				duk_debug_write_int(thr, 0);  /* isAccessor */
+				duk_debug_write_unused(thr);
+				continue;
 			}
-			if (h_idx == DUK_HOBJECT_HASHIDX_UNUSED) {
-				duk_fb_sprintf(fb, "u");
-			} else if (h_idx == DUK_HOBJECT_HASHIDX_DELETED) {
-				duk_fb_sprintf(fb, "d");
+			if (DUK_HOBJECT_E_SLOT_IS_ACCESSOR(heap, h, i)) {
+				duk_debug_write_int(thr, 1);  /* isAccessor */
+				duk_debug_write_heapptr(thr, (duk_heaphdr *) DUK_HOBJECT_E_GET_VALUE_PTR(heap, h, i)->a.get);
+				duk_debug_write_heapptr(thr, (duk_heaphdr *) DUK_HOBJECT_E_GET_VALUE_PTR(heap, h, i)->a.set);
 			} else {
-				duk_fb_sprintf(fb, "%ld", (long) h_idx);
+				duk_debug_write_int(thr, 0);  /* isAccessor */
+
+				duk__debug_write_tval_heapptr(thr, &DUK_HOBJECT_E_GET_VALUE_PTR(heap, h, i)->v);
 			}
 		}
-		duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_RANGLE);
-	}
 
- finished:
-	st->depth--;
-	if (pushed_loopstack) {
-		st->loop_stack_index--;
-		st->loop_stack[st->loop_stack_index] = NULL;
+		for (i = 0; i < (duk_uint_fast32_t) DUK_HOBJECT_GET_ASIZE(h); i++) {
+			/* Note: array dump will include elements beyond
+			 * 'length'.
+			 */
+			duk__debug_write_tval_heapptr(thr, DUK_HOBJECT_A_GET_VALUE_PTR(heap, h, i));
+		}
+		break;
 	}
-}
-
-#undef DUK__COMMA
-
-static void duk__print_hbuffer(duk__dprint_state *st, duk_hbuffer *h) {
-	duk_fixedbuffer *fb = st->fb;
-	duk_size_t i, n;
-	duk_uint8_t *p;
+	case DUK_HTYPE_BUFFER: {
+		duk_hbuffer *h = (duk_hbuffer *) hdr;
 
-	if (duk_fb_is_full(fb)) {
-		return;
+		duk_debug_write_uint(thr, (duk_uint32_t) DUK_HBUFFER_GET_SIZE(h));
+		duk_debug_write_buffer(thr, (const char *) DUK_HBUFFER_GET_DATA_PTR(heap, h), (duk_size_t) DUK_HBUFFER_GET_SIZE(h));
+		break;
+	}
+	default: {
+		DUK_D(DUK_DPRINT("invalid htype: %d", (int) DUK_HEAPHDR_GET_TYPE(hdr)));
+	}
 	}
+}
 
-	/* terminal type: no depth check */
+DUK_LOCAL void duk__debug_dump_heap_allocated(duk_hthread *thr, duk_heap *heap) {
+	duk_heaphdr *hdr;
 
-	if (!h) {
-		duk_fb_put_cstring(fb, "NULL");
-		return;
+	hdr = heap->heap_allocated;
+	while (hdr != NULL) {
+		duk__debug_dump_heaphdr(thr, heap, hdr);
+		hdr = DUK_HEAPHDR_GET_NEXT(heap, hdr);
 	}
+}
 
-	if (DUK_HBUFFER_HAS_DYNAMIC(h)) {
-		duk_hbuffer_dynamic *g = (duk_hbuffer_dynamic *) h;
-		duk_fb_sprintf(fb, "buffer:dynamic:%p:%ld:%ld",
-		               (void *) g->curr_alloc, (long) g->size, (long) g->usable_size);
-	} else {
-		duk_fb_sprintf(fb, "buffer:fixed:%ld", (long) DUK_HBUFFER_GET_SIZE(h));
-	}
+#if defined(DUK_USE_STRTAB_CHAIN)
+DUK_LOCAL void duk__debug_dump_strtab_chain(duk_hthread *thr, duk_heap *heap) {
+	duk_uint_fast32_t i, j;
+	duk_strtab_entry *e;
+#if defined(DUK_USE_HEAPPTR16)
+	duk_uint16_t *lst;
+#else
+	duk_hstring **lst;
+#endif
+	duk_hstring *h;
 
-#ifdef DUK_USE_REFERENCE_COUNTING
-	duk_fb_sprintf(fb, "/%lu", (unsigned long) DUK_HEAPHDR_GET_REFCOUNT(&h->hdr));
+	for (i = 0; i < DUK_STRTAB_CHAIN_SIZE; i++) {
+		e = heap->strtable + i;
+		if (e->listlen > 0) {
+#if defined(DUK_USE_HEAPPTR16)
+			lst = (duk_uint16_t *) DUK_USE_HEAPPTR_DEC16(heap->heap_udata, e->u.strlist16);
+#else
+			lst = e->u.strlist;
 #endif
+			DUK_ASSERT(lst != NULL);
 
-	if (st->hexdump) {
-		duk_fb_sprintf(fb, "=[");
-		n = DUK_HBUFFER_GET_SIZE(h);
-		p = (duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(h);
-		for (i = 0; i < n; i++) {
-			duk_fb_sprintf(fb, "%02lx", (unsigned long) p[i]);
+			for (j = 0; j < e->listlen; j++) {
+#if defined(DUK_USE_HEAPPTR16)
+				h = DUK_USE_HEAPPTR_DEC16(heap->heap_udata, lst[j]);
+#else
+				h = lst[j];
+#endif
+				if (h != NULL) {
+					duk__debug_dump_heaphdr(thr, heap, (duk_heaphdr *) h);
+				}
+			}
+		} else {
+#if defined(DUK_USE_HEAPPTR16)
+			h = DUK_USE_HEAPPTR_DEC16(heap->heap_udata, e->u.str16);
+#else
+			h = e->u.str;
+#endif
+			if (h != NULL) {
+				duk__debug_dump_heaphdr(thr, heap, (duk_heaphdr *) h);
+			}
 		}
-		duk_fb_sprintf(fb, "]");
 	}
 }
+#endif  /* DUK_USE_STRTAB_CHAIN */
 
-static void duk__print_heaphdr(duk__dprint_state *st, duk_heaphdr *h) {
-	duk_fixedbuffer *fb = st->fb;
+#if defined(DUK_USE_STRTAB_PROBE)
+DUK_LOCAL void duk__debug_dump_strtab_probe(duk_hthread *thr, duk_heap *heap) {
+	duk_uint32_t i;
+	duk_hstring *h;
 
-	if (duk_fb_is_full(fb)) {
-		return;
-	}
+	for (i = 0; i < heap->st_size; i++) {
+#if defined(DUK_USE_HEAPPTR16)
+		h = DUK_USE_HEAPPTR_DEC16(heap->strtable16[i]);
+#else
+		h = heap->strtable[i];
+#endif
+		if (h == NULL || h == DUK_STRTAB_DELETED_MARKER(heap)) {
+			continue;
+		}
 
-	if (!h) {
-		duk_fb_put_cstring(fb, "NULL");
-		return;
+		duk__debug_dump_heaphdr(thr, heap, (duk_heaphdr *) h);
 	}
+}
+#endif  /* DUK_USE_STRTAB_PROBE */
 
-	switch (DUK_HEAPHDR_GET_TYPE(h)) {
-	case DUK_HTYPE_STRING:
-		duk__print_hstring(st, (duk_hstring *) h, 1);
-		break;
-	case DUK_HTYPE_OBJECT:
-		duk__print_hobject(st, (duk_hobject *) h);
-		break;
-	case DUK_HTYPE_BUFFER:
-		duk__print_hbuffer(st, (duk_hbuffer *) h);
-		break;
-	default:
-		duk_fb_sprintf(fb, "[unknown htype %ld]", (long) DUK_HEAPHDR_GET_TYPE(h));
-		break;
-	}
+DUK_LOCAL void duk__debug_handle_dump_heap(duk_hthread *thr, duk_heap *heap) {
+	DUK_D(DUK_DPRINT("debug command DumpHeap"));
+
+	duk_debug_write_reply(thr);
+	duk__debug_dump_heap_allocated(thr, heap);
+#if defined(DUK_USE_STRTAB_CHAIN)
+	duk__debug_dump_strtab_chain(thr, heap);
+#endif
+#if defined(DUK_USE_STRTAB_PROBE)
+	duk__debug_dump_strtab_probe(thr, heap);
+#endif
+	duk_debug_write_eom(thr);
 }
+#endif  /* DUK_USE_DEBUGGER_DUMPHEAP */
 
-static void duk__print_tval(duk__dprint_state *st, duk_tval *tv) {
-	duk_fixedbuffer *fb = st->fb;
+DUK_LOCAL void duk__debug_handle_get_bytecode(duk_hthread *thr, duk_heap *heap) {
+	duk_activation *act;
+	duk_hcompiledfunction *fun;
+	duk_size_t i, n;
+	duk_tval *tv;
+	duk_hobject **fn;
 
-	if (duk_fb_is_full(fb)) {
-		return;
-	}
+	DUK_UNREF(heap);
 
-	/* depth check is done when printing an actual type */
+	DUK_D(DUK_DPRINT("debug command GetBytecode"));
 
-	if (st->heavy) {
-		duk_fb_sprintf(fb, "(%p)", (void *) tv);
+	duk_debug_write_reply(thr);
+	if (thr->callstack_top == 0) {
+		fun = NULL;
+	} else {
+		act = thr->callstack + thr->callstack_top - 1;
+		fun = (duk_hcompiledfunction *) DUK_ACT_GET_FUNC(act);
+		if (!DUK_HOBJECT_IS_COMPILEDFUNCTION((duk_hobject *) fun)) {
+			fun = NULL;
+		}
 	}
+	DUK_ASSERT(fun == NULL || DUK_HOBJECT_IS_COMPILEDFUNCTION((duk_hobject *) fun));
 
-	if (!tv) {
-		duk_fb_put_cstring(fb, "NULL");
-		return;
-	}
+	if (fun != NULL) {
+		n = DUK_HCOMPILEDFUNCTION_GET_CONSTS_COUNT(heap, fun);
+		duk_debug_write_int(thr, (duk_int32_t) n);
+		tv = DUK_HCOMPILEDFUNCTION_GET_CONSTS_BASE(heap, fun);
+		for (i = 0; i < n; i++) {
+			duk_debug_write_tval(thr, tv);
+			tv++;
+		}
 
-	if (st->binary) {
-		duk_size_t i;
-		duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_LBRACKET);
-		for (i = 0; i < (duk_size_t) sizeof(*tv); i++) {
-			duk_fb_sprintf(fb, "%02lx", (unsigned long) ((duk_uint8_t *)tv)[i]);
+		n = DUK_HCOMPILEDFUNCTION_GET_FUNCS_COUNT(heap, fun);
+		duk_debug_write_int(thr, (duk_int32_t) n);
+		fn = DUK_HCOMPILEDFUNCTION_GET_FUNCS_BASE(heap, fun);
+		for (i = 0; i < n; i++) {
+			duk_debug_write_hobject(thr, *fn);
+			fn++;
 		}
-		duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_RBRACKET);
-	}
 
-	if (st->heavy) {
-		duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_LANGLE);
+		duk_debug_write_string(thr,
+		                       (const char *) DUK_HCOMPILEDFUNCTION_GET_CODE_BASE(heap, fun),
+		                       (duk_size_t) DUK_HCOMPILEDFUNCTION_GET_CODE_SIZE(heap, fun));
+	} else {
+		duk_debug_write_int(thr, 0);
+		duk_debug_write_int(thr, 0);
+		duk_debug_write_cstring(thr, "");
 	}
-	switch (DUK_TVAL_GET_TAG(tv)) {
-	case DUK_TAG_UNDEFINED: {
-		if (DUK_TVAL_IS_UNDEFINED_UNUSED(tv)) {
-			duk_fb_put_cstring(fb, "unused");
-		} else {
-			duk_fb_put_cstring(fb, "undefined");
+	duk_debug_write_eom(thr);
+}
+
+/* Process one debug message.  Automatically restore value stack top to its
+ * entry value, so that individual message handlers don't need exact value
+ * stack handling which is convenient.
+ */
+DUK_LOCAL void duk__debug_process_message(duk_hthread *thr) {
+	duk_context *ctx = (duk_context *) thr;
+	duk_heap *heap;
+	duk_uint8_t x;
+	duk_int32_t cmd;
+	duk_idx_t entry_top;
+
+	DUK_ASSERT(thr != NULL);
+	heap = thr->heap;
+	DUK_ASSERT(heap != NULL);
+	DUK_UNREF(ctx);
+
+	entry_top = duk_get_top(ctx);
+
+	x = duk_debug_read_byte(thr);
+	switch (x) {
+	case DUK_DBG_MARKER_REQUEST: {
+		cmd = duk_debug_read_int(thr);
+		switch (cmd) {
+		case DUK_DBG_CMD_BASICINFO: {
+			duk__debug_handle_basic_info(thr, heap);
+			break;
 		}
+		case DUK_DBG_CMD_TRIGGERSTATUS: {
+			duk__debug_handle_trigger_status(thr, heap);
+			break;
+		}
+		case DUK_DBG_CMD_PAUSE: {
+			duk__debug_handle_pause(thr, heap);
+			break;
+		}
+		case DUK_DBG_CMD_RESUME: {
+			duk__debug_handle_resume(thr, heap);
+			break;
+		}
+		case DUK_DBG_CMD_STEPINTO:
+		case DUK_DBG_CMD_STEPOVER:
+		case DUK_DBG_CMD_STEPOUT: {
+			duk__debug_handle_step(thr, heap, cmd);
+			break;
+		}
+		case DUK_DBG_CMD_LISTBREAK: {
+			duk__debug_handle_list_break(thr, heap);
+			break;
+		}
+		case DUK_DBG_CMD_ADDBREAK: {
+			duk__debug_handle_add_break(thr, heap);
+			break;
+		}
+		case DUK_DBG_CMD_DELBREAK: {
+			duk__debug_handle_del_break(thr, heap);
+			break;
+		}
+		case DUK_DBG_CMD_GETVAR: {
+			duk__debug_handle_get_var(thr, heap);
+			break;
+		}
+		case DUK_DBG_CMD_PUTVAR: {
+			duk__debug_handle_put_var(thr, heap);
+			break;
+		}
+		case DUK_DBG_CMD_GETCALLSTACK: {
+			duk__debug_handle_get_call_stack(thr, heap);
+			break;
+		}
+		case DUK_DBG_CMD_GETLOCALS: {
+			duk__debug_handle_get_locals(thr, heap);
+			break;
+		}
+		case DUK_DBG_CMD_EVAL: {
+			duk__debug_handle_eval(thr, heap);
+			break;
+		}
+		case DUK_DBG_CMD_DETACH: {
+			/* The actual detached_cb call is postponed to message loop so
+			 * we don't need any special precautions here (just skip to EOM
+			 * on the already closed connection).
+			 */
+			duk__debug_handle_detach(thr, heap);
+			break;
+		}
+#if defined(DUK_USE_DEBUGGER_DUMPHEAP)
+		case DUK_DBG_CMD_DUMPHEAP: {
+			duk__debug_handle_dump_heap(thr, heap);
+			break;
+		}
+#endif  /* DUK_USE_DEBUGGER_DUMPHEAP */
+		case DUK_DBG_CMD_GETBYTECODE: {
+			duk__debug_handle_get_bytecode(thr, heap);
+			break;
+		}
+		default: {
+			DUK_D(DUK_DPRINT("debug command unsupported: %d", (int) cmd));
+			duk_debug_write_error_eom(thr, DUK_DBG_ERR_UNSUPPORTED, "unsupported command");
+		}
+		}  /* switch cmd */
 		break;
 	}
-	case DUK_TAG_NULL: {
-		duk_fb_put_cstring(fb, "null");
-		break;
-	}
-	case DUK_TAG_BOOLEAN: {
-		duk_fb_put_cstring(fb, DUK_TVAL_GET_BOOLEAN(tv) ? "true" : "false");
-		break;
-	}
-	case DUK_TAG_STRING: {
-		/* Note: string is a terminal heap object, so no depth check here */
-		duk__print_hstring(st, DUK_TVAL_GET_STRING(tv), 1);
-		break;
-	}
-	case DUK_TAG_OBJECT: {
-		duk__print_hobject(st, DUK_TVAL_GET_OBJECT(tv));
+	case DUK_DBG_MARKER_REPLY: {
+		DUK_D(DUK_DPRINT("debug reply, skipping"));
 		break;
 	}
-	case DUK_TAG_BUFFER: {
-		duk__print_hbuffer(st, DUK_TVAL_GET_BUFFER(tv));
+	case DUK_DBG_MARKER_ERROR: {
+		DUK_D(DUK_DPRINT("debug error, skipping"));
 		break;
 	}
-	case DUK_TAG_POINTER: {
-		duk_fb_sprintf(fb, "pointer:%p", (void *) DUK_TVAL_GET_POINTER(tv));
+	case DUK_DBG_MARKER_NOTIFY: {
+		DUK_D(DUK_DPRINT("debug notify, skipping"));
 		break;
 	}
 	default: {
-		/* IEEE double is approximately 16 decimal digits; print a couple extra */
-		DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));
-		duk_fb_sprintf(fb, "%.18g", (double) DUK_TVAL_GET_NUMBER(tv));
-		break;
-	}
-	}
-	if (st->heavy) {
-		duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_RANGLE);
+		DUK_D(DUK_DPRINT("invalid initial byte, drop connection: %d", (int) x));
+		goto fail;
 	}
+	}  /* switch initial byte */
+
+	DUK_ASSERT(duk_get_top(ctx) >= entry_top);
+	duk_set_top(ctx, entry_top);
+	duk__debug_skip_to_eom(thr);
+	return;
+
+ fail:
+	DUK_ASSERT(duk_get_top(ctx) >= entry_top);
+	duk_set_top(ctx, entry_top);
+	DUK__SET_CONN_BROKEN(thr, 1);
+	return;
 }
 
-static void duk__print_instr(duk__dprint_state *st, duk_instr_t ins) {
-	duk_fixedbuffer *fb = st->fb;
-	duk_small_int_t op;
-	const char *op_name;
-	const char *extraop_name;
+/* Halt execution and enter a debugger message loop until execution is resumed
+ * by the client.  PC for the current activation may be temporarily decremented
+ * so that the "current" instruction will be shown by the client.  This helper
+ * is callable from anywhere, also outside bytecode executor.
+ */
 
-	op = (duk_small_int_t) DUK_DEC_OP(ins);
-	op_name = duk__bc_optab[op];
+DUK_INTERNAL void duk_debug_halt_execution(duk_hthread *thr, duk_bool_t use_prev_pc) {
+	duk_activation *act;
+	duk_hcompiledfunction *fun;
+	duk_instr_t *old_pc = NULL;
 
-	/* XXX: option to fix opcode length so it lines up nicely */
+	DUK_ASSERT(thr != NULL);
+	DUK_ASSERT(thr->heap != NULL);
+	DUK_ASSERT(DUK_HEAP_IS_DEBUGGER_ATTACHED(thr->heap));
+	DUK_ASSERT(thr->heap->dbg_processing == 0);
 
-	if (op == DUK_OP_EXTRA) {
-		extraop_name = duk__bc_extraoptab[DUK_DEC_A(ins)];
+	DUK_HEAP_SET_PAUSED(thr->heap);
 
-		duk_fb_sprintf(fb, "%s %ld, %ld",
-		               (const char *) extraop_name, (long) DUK_DEC_B(ins), (long) DUK_DEC_C(ins));
-	} else if (op == DUK_OP_JUMP) {
-		duk_int_t diff1 = DUK_DEC_ABC(ins) - DUK_BC_JUMP_BIAS;  /* from next pc */
-		duk_int_t diff2 = diff1 + 1;                            /* from curr pc */
+	act = duk_hthread_get_current_activation(thr);
 
-		duk_fb_sprintf(fb, "%s %ld (to pc%c%ld)",
-		               (const char *) op_name, (long) diff1,
-		               (int) (diff2 >= 0 ? '+' : '-'),  /* char format: use int */
-		               (long) (diff2 >= 0 ? diff2 : -diff2));
-	} else {
-		duk_fb_sprintf(fb, "%s %ld, %ld, %ld",
-		               (const char *) op_name, (long) DUK_DEC_A(ins),
-		               (long) DUK_DEC_B(ins), (long) DUK_DEC_C(ins));
-	}
-}
+	/* NOTE: act may be NULL if an error is thrown outside of any activation,
+	 * which may happen in the case of, e.g. syntax errors.
+	 */
 
-static void duk__print_opcode(duk__dprint_state *st, duk_small_int_t opcode) {
-	duk_fixedbuffer *fb = st->fb;
+	/* Decrement PC if that was requested, this requires a PC sync. */
+	if (act != NULL) {
+		duk_hthread_sync_currpc(thr);
+		old_pc = act->curr_pc;
+		fun = (duk_hcompiledfunction *) DUK_ACT_GET_FUNC(act);
 
-	if (opcode < DUK_BC_OP_MIN || opcode > DUK_BC_OP_MAX) {
-		duk_fb_sprintf(fb, "?(%ld)", (long) opcode);
-	} else {
-		duk_fb_sprintf(fb, "%s", (const char *) duk__bc_optab[opcode]);
+		/* Short circuit if is safe: if act->curr_pc != NULL, 'fun' is
+		 * guaranteed to be a non-NULL Ecmascript function.
+		 */
+		DUK_ASSERT(act->curr_pc == NULL ||
+		           (fun != NULL && DUK_HOBJECT_IS_COMPILEDFUNCTION((duk_hobject *) fun)));
+		if (use_prev_pc &&
+		    act->curr_pc != NULL &&
+		    act->curr_pc > DUK_HCOMPILEDFUNCTION_GET_CODE_BASE(thr->heap, fun)) {
+			act->curr_pc--;
+		}
 	}
-}
-
-duk_int_t duk_debug_vsnprintf(char *str, duk_size_t size, const char *format, va_list ap) {
-	duk_fixedbuffer fb;
-	const char *p = format;
-	const char *p_end = p + DUK_STRLEN(format);
-	duk_int_t retval;
-	
-	DUK_MEMZERO(&fb, sizeof(fb));
-	fb.buffer = (duk_uint8_t *) str;
-	fb.length = size;
-	fb.offset = 0;
-	fb.truncated = 0;
 
-	while (p < p_end) {
-		char ch = *p++;
-		const char *p_begfmt = NULL;
-		duk_bool_t got_exclamation = 0;
-		duk_bool_t got_long = 0;  /* %lf, %ld etc */
-		duk__dprint_state st;
+	/* Process debug messages until we are no longer paused. */
 
-		if (ch != DUK_ASC_PERCENT) {
-			duk_fb_put_byte(&fb, (duk_uint8_t) ch);
-			continue;
-		}
+	/* NOTE: This is a bit fragile. It's important to ensure that neither
+	 * duk_debug_send_status() or duk_debug_process_messages() throws an
+	 * error or act->curr_pc will never be reset.
+	 */
 
-		/*
-		 *  Format tag parsing.  Since we don't understand all the
-		 *  possible format tags allowed, we just scan for a terminating
-		 *  specifier and keep track of relevant modifiers that we do
-		 *  understand.  See man 3 printf.
-		 */
+	thr->heap->dbg_processing = 1;
+	duk_debug_send_status(thr);
+	while (thr->heap->dbg_paused) {
+		DUK_ASSERT(thr->heap->dbg_processing);
+		duk_debug_process_messages(thr, 0 /*no_block*/);
+	}
+	thr->heap->dbg_processing = 0;
 
-		DUK_MEMZERO(&st, sizeof(st));
-		st.fb = &fb;
-		st.depth = 0;
-		st.depth_limit = 1;
-		st.loop_stack_index = 0;
-		st.loop_stack_limit = DUK__LOOP_STACK_DEPTH;
+	/* XXX: Decrementing and restoring act->curr_pc works now, but if the
+	 * debugger message loop gains the ability to adjust the current PC
+	 * (e.g. a forced jump) restoring the PC here will break.  Another
+	 * approach would be to use a state flag for the "decrement 1 from
+	 * topmost activation's PC" and take it into account whenever dealing
+	 * with PC values.
+	 */
+	if (act != NULL) {
+		act->curr_pc = old_pc;  /* restore PC */
+	}
+}
 
-		p_begfmt = p - 1;
-		while (p < p_end) {
-			ch = *p++;
+DUK_INTERNAL duk_bool_t duk_debug_process_messages(duk_hthread *thr, duk_bool_t no_block) {
+	duk_context *ctx = (duk_context *) thr;
+#if defined(DUK_USE_ASSERTIONS)
+	duk_idx_t entry_top;
+#endif
+	duk_bool_t retval = 0;
 
-			if (ch == DUK_ASC_STAR) {
-				/* unsupported: would consume multiple args */
-				goto error;
-			} else if (ch == DUK_ASC_PERCENT) {
-				duk_fb_put_byte(&fb, (duk_uint8_t) DUK_ASC_PERCENT);
-				break;
-			} else if (ch == DUK_ASC_EXCLAMATION) {
-				got_exclamation = 1;
-			} else if (!got_exclamation && ch == DUK_ASC_LC_L) {
-				got_long = 1;
-			} else if (got_exclamation && ch == DUK_ASC_LC_D) {
-				st.depth_limit = DUK__DEEP_DEPTH_LIMIT;
-			} else if (got_exclamation && ch == DUK_ASC_LC_P) {
-				st.follow_proto = 1;
-			} else if (got_exclamation && ch == DUK_ASC_LC_I) {
-				st.internal = 1;
-			} else if (got_exclamation && ch == DUK_ASC_LC_X) {
-				st.hexdump = 1;
-			} else if (got_exclamation && ch == DUK_ASC_LC_H) {
-				st.heavy = 1;
-			} else if (got_exclamation && ch == DUK_ASC_ATSIGN) {
-				st.pointer = 1;
-			} else if (got_exclamation && ch == DUK_ASC_HASH) {
-				st.binary = 1;
-			} else if (got_exclamation && ch == DUK_ASC_UC_T) {
-				duk_tval *t = va_arg(ap, duk_tval *);
-				if (st.pointer && !st.heavy) {
-					duk_fb_sprintf(&fb, "(%p)", (void *) t);
-				}
-				duk__print_tval(&st, t);
-				break;
-			} else if (got_exclamation && ch == DUK_ASC_UC_O) {
-				duk_heaphdr *t = va_arg(ap, duk_heaphdr *);
-				if (st.pointer && !st.heavy) {
-					duk_fb_sprintf(&fb, "(%p)", (void *) t);
-				}
-				duk__print_heaphdr(&st, t);
-				break;
-			} else if (got_exclamation && ch == DUK_ASC_UC_I) {
-				duk_instr_t t = va_arg(ap, duk_instr_t);
-				duk__print_instr(&st, t);
-				break;
-			} else if (got_exclamation && ch == DUK_ASC_UC_C) {
-				long t = va_arg(ap, long);
-				duk__print_opcode(&st, (duk_small_int_t) t);
-				break;
-			} else if (!got_exclamation && strchr(DUK__ALLOWED_STANDARD_SPECIFIERS, (int) ch)) {
-				char fmtbuf[DUK__MAX_FORMAT_TAG_LENGTH];
-				duk_size_t fmtlen;
+	DUK_ASSERT(thr != NULL);
+	DUK_UNREF(ctx);
+	DUK_ASSERT(thr->heap != NULL);
+	DUK_ASSERT(DUK_HEAP_IS_DEBUGGER_ATTACHED(thr->heap));
+#if defined(DUK_USE_ASSERTIONS)
+	entry_top = duk_get_top(ctx);
+#endif
 
-				DUK_ASSERT(p >= p_begfmt);
-				fmtlen = (duk_size_t) (p - p_begfmt);
-				if (fmtlen >= sizeof(fmtbuf)) {
-					/* format is too large, abort */
-					goto error;
-				}
-				DUK_MEMZERO(fmtbuf, sizeof(fmtbuf));
-				DUK_MEMCPY(fmtbuf, p_begfmt, fmtlen);
+	DUK_DD(DUK_DDPRINT("top at entry: %ld", (long) duk_get_top(ctx)));
 
-				/* assume exactly 1 arg, which is why '*' is forbidden; arg size still
-				 * depends on type though.
-				 */
+	for (;;) {
+		/* Process messages until we're no longer paused or we peek
+		 * and see there's nothing to read right now.
+		 */
+		DUK_DD(DUK_DDPRINT("top at loop top: %ld", (long) duk_get_top(ctx)));
 
-				if (ch == DUK_ASC_LC_F || ch == DUK_ASC_LC_G || ch == DUK_ASC_LC_E) {
-					/* %f and %lf both consume a 'long' */
-					double arg = va_arg(ap, double);
-					duk_fb_sprintf(&fb, fmtbuf, arg);
-				} else if (ch == DUK_ASC_LC_D && got_long) {
-					/* %ld */
-					long arg = va_arg(ap, long);
-					duk_fb_sprintf(&fb, fmtbuf, arg);
-				} else if (ch == DUK_ASC_LC_D) {
-					/* %d; only 16 bits are guaranteed */
-					int arg = va_arg(ap, int);
-					duk_fb_sprintf(&fb, fmtbuf, arg);
-				} else if (ch == DUK_ASC_LC_U && got_long) {
-					/* %lu */
-					unsigned long arg = va_arg(ap, unsigned long);
-					duk_fb_sprintf(&fb, fmtbuf, arg);
-				} else if (ch == DUK_ASC_LC_U) {
-					/* %u; only 16 bits are guaranteed */
-					unsigned int arg = va_arg(ap, unsigned int);
-					duk_fb_sprintf(&fb, fmtbuf, arg);
-				} else if (ch == DUK_ASC_LC_X && got_long) {
-					/* %lx */
-					unsigned long arg = va_arg(ap, unsigned long);
-					duk_fb_sprintf(&fb, fmtbuf, arg);
-				} else if (ch == DUK_ASC_LC_X) {
-					/* %x; only 16 bits are guaranteed */
-					unsigned int arg = va_arg(ap, unsigned int);
-					duk_fb_sprintf(&fb, fmtbuf, arg);
-				} else if (ch == DUK_ASC_LC_S) {
-					/* %s */
-					const char *arg = va_arg(ap, const char *);
-					if (arg == NULL) {
-						/* '%s' and NULL is not portable, so special case
-						 * it for debug printing.
-						 */
-						duk_fb_sprintf(&fb, "NULL");
-					} else {
-						duk_fb_sprintf(&fb, fmtbuf, arg);
-					}
-				} else if (ch == DUK_ASC_LC_P) {
-					/* %p */
-					void *arg = va_arg(ap, void *);
-					if (arg == NULL) {
-						/* '%p' and NULL is portable, but special case it
-						 * anyway to get a standard NULL marker in logs.
-						 */
-						duk_fb_sprintf(&fb, "NULL");
-					} else {
-						duk_fb_sprintf(&fb, fmtbuf, arg);
-					}
-				} else if (ch == DUK_ASC_LC_C) {
-					/* '%c', passed concretely as int */
-					int arg = va_arg(ap, int);
-					duk_fb_sprintf(&fb, fmtbuf, arg);
-				} else {
-					/* Should not happen. */
-					duk_fb_sprintf(&fb, "INVALID-FORMAT(%s)", (const char *) fmtbuf);
-				}
+		if (thr->heap->dbg_read_cb == NULL) {
+			DUK_D(DUK_DPRINT("debug connection broken, stop processing messages"));
+			break;
+		} else if (!thr->heap->dbg_paused || no_block) {
+			if (!duk_debug_read_peek(thr)) {
+				DUK_D(DUK_DPRINT("processing debug message, peek indicated no data, stop processing"));
 				break;
-			} else {
-				/* ignore */
 			}
+			DUK_D(DUK_DPRINT("processing debug message, peek indicated there is data, handle it"));
+		} else {
+			DUK_D(DUK_DPRINT("paused, process debug message, blocking if necessary"));
+		}
+
+		duk__debug_process_message(thr);
+
+		if (thr->heap->dbg_read_cb == NULL) {
+			/* Became detached during message handling (perhaps because
+			 * of an error or by an explicit Detach).  Call detached
+			 * callback here, between messages, to avoid confusing the
+			 * broken connection and a possible replacement (which may
+			 * be provided by an instant reattach inside the detached
+			 * callback).
+			 */
+			duk__debug_do_detach2(thr->heap);
+		}
+		if (thr->heap->dbg_state_dirty) {
+			/* Executed something that may have affected status,
+			 * resend.
+			 */
+			duk_debug_send_status(thr);
+			thr->heap->dbg_state_dirty = 0;
 		}
+		retval = 1;  /* processed one or more messages */
 	}
-	goto done;
 
- error:
-	duk_fb_put_cstring(&fb, "FMTERR");
-	/* fall through */
+	/* As an initial implementation, read flush after exiting the message
+	 * loop.
+	 */
+	duk_debug_read_flush(thr);
 
- done:
-	retval = (duk_int_t) fb.offset;
-	duk_fb_put_byte(&fb, (duk_uint8_t) 0);
+	DUK_DD(DUK_DDPRINT("top at exit: %ld", (long) duk_get_top(ctx)));
 
-	/* return total chars written excluding terminator */
-	return retval;
-}
+#if defined(DUK_USE_ASSERTIONS)
+	/* Easy to get wrong, so assert for it. */
+	DUK_ASSERT(entry_top == duk_get_top(ctx));
+#endif
 
-duk_int_t duk_debug_snprintf(char *str, duk_size_t size, const char *format, ...) {
-	duk_int_t retval;
-	va_list ap;
-	va_start(ap, format);
-	retval = duk_debug_vsnprintf(str, size, format, ap);
-	va_end(ap);
 	return retval;
 }
 
-/* Formatting function pointers is tricky: there is no standard pointer for
- * function pointers and the size of a function pointer may depend on the
- * specific pointer type.  This helper formats a function pointer based on
- * its memory layout to get something useful on most platforms.
+/*
+ *  Breakpoint management
  */
-void duk_debug_format_funcptr(char *buf, duk_size_t buf_size, duk_uint8_t *fptr, duk_size_t fptr_size) {
-	duk_size_t i;
-	duk_uint8_t *p = (duk_uint8_t *) buf;
-	duk_uint8_t *p_end = (duk_uint8_t *) (buf + buf_size - 1);
 
-	DUK_MEMZERO(buf, buf_size);
+DUK_INTERNAL duk_small_int_t duk_debug_add_breakpoint(duk_hthread *thr, duk_hstring *filename, duk_uint32_t line) {
+	duk_heap *heap;
+	duk_breakpoint *b;
 
-	for (i = 0; i < fptr_size; i++) {
-		duk_int_t left = (duk_int_t) (p_end - p);
-		duk_uint8_t ch;
-		if (left <= 0) {
-			break;
-		}
+	/* Caller must trigger recomputation of active breakpoint list.  To
+	 * ensure stale values are not used if that doesn't happen, clear the
+	 * active breakpoint list here.
+	 */
 
-		/* Quite approximate but should be useful for little and big endian. */
-#ifdef DUK_USE_INTEGER_BE
-		ch = fptr[i];
-#else
-		ch = fptr[fptr_size - 1 - i];
-#endif
-		p += DUK_SNPRINTF((char *) p, left, "%02lx", (unsigned long) ch);
-	}	
+	DUK_ASSERT(thr != NULL);
+	DUK_ASSERT(filename != NULL);
+	heap = thr->heap;
+	DUK_ASSERT(heap != NULL);
+
+	if (heap->dbg_breakpoint_count >= DUK_HEAP_MAX_BREAKPOINTS) {
+		DUK_D(DUK_DPRINT("failed to add breakpoint for %O:%ld, all breakpoint slots used",
+		                 (duk_heaphdr *) filename, (long) line));
+		return -1;
+	}
+	heap->dbg_breakpoints_active[0] = (duk_breakpoint *) NULL;
+	b = heap->dbg_breakpoints + (heap->dbg_breakpoint_count++);
+	b->filename = filename;
+	b->line = line;
+	DUK_HSTRING_INCREF(thr, filename);
+
+	return heap->dbg_breakpoint_count - 1;  /* index */
 }
 
-#endif  /* DUK_USE_DEBUG */
+DUK_INTERNAL duk_bool_t duk_debug_remove_breakpoint(duk_hthread *thr, duk_small_uint_t breakpoint_index) {
+	duk_heap *heap;
+	duk_hstring *h;
+	duk_breakpoint *b;
+	duk_size_t move_size;
+
+	/* Caller must trigger recomputation of active breakpoint list.  To
+	 * ensure stale values are not used if that doesn't happen, clear the
+	 * active breakpoint list here.
+	 */
+
+	DUK_ASSERT(thr != NULL);
+	heap = thr->heap;
+	DUK_ASSERT(heap != NULL);
+	DUK_ASSERT(DUK_HEAP_IS_DEBUGGER_ATTACHED(thr->heap));
+	DUK_ASSERT_DISABLE(breakpoint_index >= 0);  /* unsigned */
+
+	if (breakpoint_index >= heap->dbg_breakpoint_count) {
+		DUK_D(DUK_DPRINT("invalid breakpoint index: %ld", (long) breakpoint_index));
+		return 0;
+	}
+	b = heap->dbg_breakpoints + breakpoint_index;
+
+	h = b->filename;
+	DUK_ASSERT(h != NULL);
+
+	move_size = sizeof(duk_breakpoint) * (heap->dbg_breakpoint_count - breakpoint_index - 1);
+	if (move_size > 0) {
+		DUK_MEMMOVE((void *) b,
+		            (const void *) (b + 1),
+		            (size_t) move_size);
+	}
+	heap->dbg_breakpoint_count--;
+	heap->dbg_breakpoints_active[0] = (duk_breakpoint *) NULL;
+
+	DUK_HSTRING_DECREF(thr, h);  /* side effects */
+	DUK_UNREF(h);  /* w/o refcounting */
+
+	/* Breakpoint entries above the used area are left as garbage. */
+
+	return 1;
+}
+
+#undef DUK__SET_CONN_BROKEN
+
+#else  /* DUK_USE_DEBUGGER_SUPPORT */
+
+/* No debugger support. */
+
+#endif  /* DUK_USE_DEBUGGER_SUPPORT */
 #line 1 "duk_error_augment.c"
 /*
  *  Augmenting errors at their creation site and their throw site.
@@ -27796,7 +42091,7 @@ void duk_debug_format_funcptr(char *buf, duk_size_t buf_size, duk_uint8_t *fptr,
  *  The user error handler is stored in 'Duktape.errCreate' or
  *  'Duktape.errThrow' depending on whether we're augmenting the error at
  *  creation or throw time.  There are several alternatives to this approach,
- *  see doc/error-objects.txt for discussion.
+ *  see doc/error-objects.rst for discussion.
  *
  *  Note: since further longjmp()s may occur while calling the error handler
  *  (for many reasons, e.g. a labeled 'break' inside the handler), the
@@ -27807,7 +42102,7 @@ void duk_debug_format_funcptr(char *buf, duk_size_t buf_size, duk_uint8_t *fptr,
  */
 
 #if defined(DUK_USE_ERRTHROW) || defined(DUK_USE_ERRCREATE)
-static void duk__err_augment_user(duk_hthread *thr, duk_small_uint_t stridx_cb) {
+DUK_LOCAL void duk__err_augment_user(duk_hthread *thr, duk_small_uint_t stridx_cb) {
 	duk_context *ctx = (duk_context *) thr;
 	duk_tval *tv_hnd;
 	duk_small_uint_t call_flags;
@@ -27844,8 +42139,9 @@ static void duk__err_augment_user(duk_hthread *thr, duk_small_uint_t stridx_cb)
 		DUK_DD(DUK_DDPRINT("error occurred when DUK_BIDX_DUKTAPE is NULL, ignoring"));
 		return;
 	}
-	tv_hnd = duk_hobject_find_existing_entry_tval_ptr(thr->builtins[DUK_BIDX_DUKTAPE],
-	                                                  thr->strs[stridx_cb]);
+	tv_hnd = duk_hobject_find_existing_entry_tval_ptr(thr->heap,
+	                                                  thr->builtins[DUK_BIDX_DUKTAPE],
+	                                                  DUK_HTHREAD_GET_STRING(thr, stridx_cb));
 	if (tv_hnd == NULL) {
 		DUK_DD(DUK_DDPRINT("error handler does not exist or is not a plain value: %!T",
 		                   (duk_tval *) tv_hnd));
@@ -27883,12 +42179,11 @@ static void duk__err_augment_user(duk_hthread *thr, duk_small_uint_t stridx_cb)
 	DUK_ASSERT(!DUK_HEAP_HAS_ERRHANDLER_RUNNING(thr->heap));  /* since no recursive error handler calls */
 	DUK_HEAP_SET_ERRHANDLER_RUNNING(thr->heap);
 
-	call_flags = DUK_CALL_FLAG_PROTECTED |
-	             DUK_CALL_FLAG_IGNORE_RECLIMIT;  /* protected, ignore reclimit, not constructor */
+	call_flags = DUK_CALL_FLAG_IGNORE_RECLIMIT;  /* ignore reclimit, not constructor */
 
-	rc = duk_handle_call(thr,
-	                     1,            /* num args */
-	                     call_flags);  /* call_flags */
+	rc = duk_handle_call_protected(thr,
+	                               1,            /* num args */
+	                               call_flags);  /* call_flags */
 	DUK_UNREF(rc);  /* no need to check now: both success and error are OK */
 
 	DUK_ASSERT(DUK_HEAP_HAS_ERRHANDLER_RUNNING(thr->heap));
@@ -27896,14 +42191,14 @@ static void duk__err_augment_user(duk_hthread *thr, duk_small_uint_t stridx_cb)
 
 	/* [ ... errval ] */
 }
-#endif  /* DUK_USE_ERRTHROW || DUK_USE_ERRHANDLE */
+#endif  /* DUK_USE_ERRTHROW || DUK_USE_ERRCREATE */
 
 /*
- *  Add tracedata to an error on the stack top.
+ *  Add ._Tracedata to an error on the stack top.
  */
 
-#ifdef DUK_USE_TRACEBACKS
-static void duk__add_traceback(duk_hthread *thr, duk_hthread *thr_callstack, const char *filename, duk_int_t line, duk_bool_t noblame_fileline) {
+#if defined(DUK_USE_TRACEBACKS)
+DUK_LOCAL void duk__add_traceback(duk_hthread *thr, duk_hthread *thr_callstack, const char *c_filename, duk_int_t c_line, duk_bool_t noblame_fileline) {
 	duk_context *ctx = (duk_context *) thr;
 	duk_small_uint_t depth;
 	duk_int_t i, i_min;
@@ -27921,7 +42216,7 @@ static void duk__add_traceback(duk_hthread *thr, duk_hthread *thr_callstack, con
 	 *  and cheap to create.  It may change arbitrarily from version to version.
 	 *  It should be decoded/accessed through version specific accessors only.
 	 *
-	 *  See doc/error-objects.txt.
+	 *  See doc/error-objects.rst.
 	 */
 
 	DUK_DDD(DUK_DDDPRINT("adding traceback to object: %!T",
@@ -27930,7 +42225,20 @@ static void duk__add_traceback(duk_hthread *thr, duk_hthread *thr_callstack, con
 	duk_push_array(ctx);  /* XXX: specify array size, as we know it */
 	arr_idx = 0;
 
-	/* filename/line from C macros (__FILE__, __LINE__) are added as an
+	/* Compiler SyntaxErrors (and other errors) come first, and are
+	 * blamed by default (not flagged "noblame").
+	 */
+	if (thr->compile_ctx != NULL && thr->compile_ctx->h_filename != NULL) {
+		duk_push_hstring(ctx, thr->compile_ctx->h_filename);
+		duk_xdef_prop_index_wec(ctx, -2, arr_idx);
+		arr_idx++;
+
+		duk_push_uint(ctx, (duk_uint_t) thr->compile_ctx->curr_token.start_line);  /* (flags<<32) + (line), flags = 0 */
+		duk_xdef_prop_index_wec(ctx, -2, arr_idx);
+		arr_idx++;
+	}
+
+	/* Filename/line from C macros (__FILE__, __LINE__) are added as an
 	 * entry with a special format: (string, number).  The number contains
 	 * the line and flags.
 	 */
@@ -27942,21 +42250,23 @@ static void duk__add_traceback(duk_hthread *thr, duk_hthread *thr_callstack, con
 
 	/* XXX: using duk_put_prop_index() would cause obscure error cases when Array.prototype
 	 * has write-protected array index named properties.  This was seen as DoubleErrors
-	 * in e.g. some test262 test cases.  Using duk_def_prop_index() is better but heavier.
-	 * The best fix is to fill in the tracedata directly into the array part.
+	 * in e.g. some test262 test cases.  Using duk_xdef_prop_index() is better but heavier.
+	 * The best fix is to fill in the tracedata directly into the array part.  There are
+	 * no side effect concerns if the array part is allocated directly and only INCREFs
+	 * happen after that.
 	 */
 
 	/* [ ... error arr ] */
 
-	if (filename) {
-		duk_push_string(ctx, filename);
-		duk_def_prop_index_wec(ctx, -2, arr_idx);
+	if (c_filename) {
+		duk_push_string(ctx, c_filename);
+		duk_xdef_prop_index_wec(ctx, -2, arr_idx);
 		arr_idx++;
 
 		d = (noblame_fileline ? ((duk_double_t) DUK_TB_FLAG_NOBLAME_FILELINE) * DUK_DOUBLE_2TO32 : 0.0) +
-		    (duk_double_t) line;
+		    (duk_double_t) c_line;
 		duk_push_number(ctx, d);
-		duk_def_prop_index_wec(ctx, -2, arr_idx);
+		duk_xdef_prop_index_wec(ctx, -2, arr_idx);
 		arr_idx++;
 	}
 
@@ -27983,71 +42293,53 @@ static void duk__add_traceback(duk_hthread *thr, duk_hthread *thr_callstack, con
 
 		/* [... arr] */
 
-		DUK_ASSERT(thr_callstack->callstack[i].func != NULL);
 		DUK_ASSERT_DISABLE(thr_callstack->callstack[i].pc >= 0);  /* unsigned */
 
-		/* add function */
-		duk_push_hobject(ctx, thr_callstack->callstack[i].func);  /* -> [... arr func] */
-		duk_def_prop_index_wec(ctx, -2, arr_idx);
+		/* Add function object. */
+		duk_push_tval(ctx, &(thr_callstack->callstack + i)->tv_func);
+		duk_xdef_prop_index_wec(ctx, -2, arr_idx);
 		arr_idx++;
 
-		/* add a number containing: pc, activation flags */
-
-		/* Add a number containing: pc, activation flag
+		/* Add a number containing: pc, activation flags.
 		 *
 		 * PC points to next instruction, find offending PC.  Note that
 		 * PC == 0 for native code.
 		 */
-		pc = thr_callstack->callstack[i].pc;
-		if (pc > 0) {
-			pc--;
-		}
+		pc = duk_hthread_get_act_prev_pc(thr_callstack, thr_callstack->callstack + i);
 		DUK_ASSERT_DISABLE(pc >= 0);  /* unsigned */
 		DUK_ASSERT((duk_double_t) pc < DUK_DOUBLE_2TO32);  /* assume PC is at most 32 bits and non-negative */
 		d = ((duk_double_t) thr_callstack->callstack[i].flags) * DUK_DOUBLE_2TO32 + (duk_double_t) pc;
 		duk_push_number(ctx, d);  /* -> [... arr num] */
-		duk_def_prop_index_wec(ctx, -2, arr_idx);
+		duk_xdef_prop_index_wec(ctx, -2, arr_idx);
 		arr_idx++;
 	}
 
 	/* XXX: set with duk_hobject_set_length() when tracedata is filled directly */
 	duk_push_uint(ctx, (duk_uint_t) arr_idx);
-	duk_def_prop_stridx(ctx, -2, DUK_STRIDX_LENGTH, DUK_PROPDESC_FLAGS_WC);
+	duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_LENGTH, DUK_PROPDESC_FLAGS_WC);
 
 	/* [ ... error arr ] */
 
-	duk_def_prop_stridx_wec(ctx, -2, DUK_STRIDX_TRACEDATA);  /* -> [ ... error ] */
+	duk_xdef_prop_stridx_wec(ctx, -2, DUK_STRIDX_INT_TRACEDATA);  /* -> [ ... error ] */
 }
 #endif  /* DUK_USE_TRACEBACKS */
 
-#if defined(DUK_USE_AUGMENT_ERROR_CREATE)
-static void duk__err_augment_builtin_throw(duk_hthread *thr, duk_hthread *thr_callstack, const char *filename, duk_int_t line, duk_small_int_t noblame_fileline, duk_hobject *obj) {
-	duk_context *ctx = (duk_context *) thr;
-#ifdef DUK_USE_ASSERTIONS
+/*
+ *  Add .fileName and .lineNumber to an error on the stack top.
+ */
+
+#if !defined(DUK_USE_TRACEBACKS)
+DUK_LOCAL void duk__add_fileline(duk_hthread *thr, duk_hthread *thr_callstack, const char *c_filename, duk_int_t c_line, duk_bool_t noblame_fileline) {
+	duk_context *ctx;
+#if defined(DUK_USE_ASSERTIONS)
 	duk_int_t entry_top;
 #endif
 
-#ifdef DUK_USE_ASSERTIONS
+	ctx = (duk_context *) thr;
+#if defined(DUK_USE_ASSERTIONS)
 	entry_top = duk_get_top(ctx);
 #endif
-	DUK_ASSERT(obj != NULL);
-
-	DUK_UNREF(obj);  /* unreferenced w/o tracebacks */
-	DUK_UNREF(ctx);  /* unreferenced w/ tracebacks */
 
-#ifdef DUK_USE_TRACEBACKS
-	/*
-	 *  If tracebacks are enabled, the 'tracedata' property is the only
-	 *  thing we need: 'fileName' and 'lineNumber' are virtual properties
-	 *  which use 'tracedata'.
-	 */
-
-	if (duk_hobject_hasprop_raw(thr, obj, DUK_HTHREAD_STRING_TRACEDATA(thr))) {
-		DUK_DDD(DUK_DDDPRINT("error value already has a 'tracedata' property, not modifying it"));
-	} else {
-		duk__add_traceback(thr, thr_callstack, filename, line, noblame_fileline);
-	}
-#else
 	/*
 	 *  If tracebacks are disabled, 'fileName' and 'lineNumber' are added
 	 *  as plain own properties.  Since Error.prototype has accessors of
@@ -28056,32 +42348,50 @@ static void duk__err_augment_builtin_throw(duk_hthread *thr, duk_hthread *thr_ca
 	 *  overwritten in case they already exist.
 	 */
 
-	if (filename && !noblame_fileline) {
-		/* XXX: file/line is disabled in minimal builds, so disable this too
-		 * when appropriate.
+	if (thr->compile_ctx != NULL && thr->compile_ctx->h_filename != NULL) {
+		/* Compiler SyntaxError (or other error) gets the primary blame.
+		 * Currently no flag to prevent blaming.
 		 */
-		duk_push_string(ctx, filename);
-		duk_def_prop_stridx(ctx, -2, DUK_STRIDX_FILE_NAME, DUK_PROPDESC_FLAGS_WC | DUK_PROPDESC_FLAG_NO_OVERWRITE);
-		duk_push_int(ctx, line);
-		duk_def_prop_stridx(ctx, -2, DUK_STRIDX_LINE_NUMBER, DUK_PROPDESC_FLAGS_WC | DUK_PROPDESC_FLAG_NO_OVERWRITE);
-	} else if (thr_callstack->callstack_top > 0) {
-		duk_activation *act;
-		duk_hobject *func;
-
-		act = thr_callstack->callstack + thr_callstack->callstack_top - 1;
-		DUK_ASSERT(act >= thr_callstack->callstack && act < thr_callstack->callstack + thr_callstack->callstack_size);
-		func = act->func;
-		if (func) {
+		duk_push_uint(ctx, (duk_uint_t) thr->compile_ctx->curr_token.start_line);
+		duk_push_hstring(ctx, thr->compile_ctx->h_filename);
+	} else if (c_filename && !noblame_fileline) {
+		/* C call site gets blamed next, unless flagged not to do so.
+		 * XXX: file/line is disabled in minimal builds, so disable this
+		 * too when appropriate.
+		 */
+		duk_push_int(ctx, c_line);
+		duk_push_string(ctx, c_filename);
+	} else {
+		/* Finally, blame the innermost callstack entry which has a
+		 * .fileName property.
+		 */
+		duk_small_uint_t depth;
+		duk_int_t i, i_min;
+		duk_uint32_t ecma_line;
+
+		depth = DUK_USE_TRACEBACK_DEPTH;
+		i_min = (thr_callstack->callstack_top > (duk_size_t) depth ? (duk_int_t) (thr_callstack->callstack_top - depth) : 0);
+		DUK_ASSERT(i_min >= 0);
+
+		DUK_ASSERT(thr_callstack->callstack_top <= DUK_INT_MAX);  /* callstack limits */
+		for (i = (duk_int_t) (thr_callstack->callstack_top - 1); i >= i_min; i--) {
+			duk_activation *act;
+			duk_hobject *func;
 			duk_uint32_t pc;
-			duk_uint32_t line;
 
-			/* PC points to next instruction, find offending PC.  Note that
+			act = thr_callstack->callstack + i;
+			DUK_ASSERT(act >= thr_callstack->callstack && act < thr_callstack->callstack + thr_callstack->callstack_size);
+
+			func = DUK_ACT_GET_FUNC(act);
+			if (func == NULL) {
+				/* Lightfunc, not blamed now. */
+				continue;
+			}
+
+			/* PC points to next instruction, find offending PC,
 			 * PC == 0 for native code.
 			 */
-			pc = act->pc;
-			if (pc > 0) {
-				pc--;
-			}
+			pc = duk_hthread_get_act_prev_pc(thr, act);  /* thr argument only used for thr->heap, so specific thread doesn't matter */
 			DUK_ASSERT_DISABLE(pc >= 0);  /* unsigned */
 			DUK_ASSERT((duk_double_t) pc < DUK_DOUBLE_2TO32);  /* assume PC is at most 32 bits and non-negative */
 			act = NULL;  /* invalidated by pushes, so get out of the way */
@@ -28091,51 +42401,150 @@ static void duk__err_augment_builtin_throw(duk_hthread *thr, duk_hthread *thr_ca
 			/* [ ... error func ] */
 
 			duk_get_prop_stridx(ctx, -1, DUK_STRIDX_FILE_NAME);
-			duk_def_prop_stridx(ctx, -3, DUK_STRIDX_FILE_NAME, DUK_PROPDESC_FLAGS_WC | DUK_PROPDESC_FLAG_NO_OVERWRITE);
+			if (!duk_is_string(ctx, -1)) {
+				duk_pop_2(ctx);
+				continue;
+			}
+
+			/* [ ... error func fileName ] */
+
+			ecma_line = 0;
+#if defined(DUK_USE_PC2LINE)
 			if (DUK_HOBJECT_IS_COMPILEDFUNCTION(func)) {
-#if 0
-				duk_push_number(ctx, pc);
-				duk_def_prop_stridx(ctx, -3, DUK_STRIDX_PC, DUK_PROPDESC_FLAGS_WC | DUK_PROPDESC_FLAGS_NO_OVERWRITE);
-#endif
-				line = duk_hobject_pc2line_query(ctx, -1, (duk_uint_fast32_t) pc);
-				if (line > 0) {
-					duk_push_u32(ctx, (duk_uint32_t) line); /* -> [ ... error func line ] */
-					duk_def_prop_stridx(ctx, -3, DUK_STRIDX_LINE_NUMBER, DUK_PROPDESC_FLAGS_WC | DUK_PROPDESC_FLAG_NO_OVERWRITE);
-				}
+				ecma_line = duk_hobject_pc2line_query(ctx, -2, (duk_uint_fast32_t) pc);
 			} else {
 				/* Native function, no relevant lineNumber. */
 			}
+#endif  /* DUK_USE_PC2LINE */
+			duk_push_u32(ctx, ecma_line);
 
-			duk_pop(ctx);
+			/* [ ... error func fileName lineNumber ] */
+
+			duk_replace(ctx, -3);
+
+			/* [ ... error lineNumber fileName ] */
+			goto define_props;
 		}
+
+		/* No activation matches, use undefined for both .fileName and
+		 * .lineNumber (matches what we do with a _Tracedata based
+		 * no-match lookup.
+		 */
+		duk_push_undefined(ctx);
+		duk_push_undefined(ctx);
 	}
-#endif  /* DUK_USE_TRACEBACKS */
 
-#ifdef DUK_USE_ASSERTIONS
+ define_props:
+	/* [ ... error lineNumber fileName ] */
+#if defined(DUK_USE_ASSERTIONS)
+	DUK_ASSERT(duk_get_top(ctx) == entry_top + 2);
+#endif
+	duk_xdef_prop_stridx(ctx, -3, DUK_STRIDX_FILE_NAME, DUK_PROPDESC_FLAGS_WC | DUK_PROPDESC_FLAG_NO_OVERWRITE);
+	duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_LINE_NUMBER, DUK_PROPDESC_FLAGS_WC | DUK_PROPDESC_FLAG_NO_OVERWRITE);
+}
+#endif  /* !DUK_USE_TRACEBACKS */
+
+/*
+ *  Add line number to a compiler error.
+ */
+
+DUK_LOCAL void duk__add_compiler_error_line(duk_hthread *thr) {
+	duk_context *ctx;
+
+	/* Append a "(line NNN)" to the "message" property of any error
+	 * thrown during compilation.  Usually compilation errors are
+	 * SyntaxErrors but they can also be out-of-memory errors and
+	 * the like.
+	 */
+
+	/* [ ... error ] */
+
+	ctx = (duk_context *) thr;
+	DUK_ASSERT(duk_is_object(ctx, -1));
+
+	if (!(thr->compile_ctx != NULL && thr->compile_ctx->h_filename != NULL)) {
+		return;
+	}
+
+	DUK_DDD(DUK_DDDPRINT("compile error, before adding line info: %!T",
+	                     (duk_tval *) duk_get_tval(ctx, -1)));
+
+	if (duk_get_prop_stridx(ctx, -1, DUK_STRIDX_MESSAGE)) {
+		duk_push_sprintf(ctx, " (line %ld)", (long) thr->compile_ctx->curr_token.start_line);
+		duk_concat(ctx, 2);
+		duk_put_prop_stridx(ctx, -2, DUK_STRIDX_MESSAGE);
+	} else {
+		duk_pop(ctx);
+	}
+
+	DUK_DDD(DUK_DDDPRINT("compile error, after adding line info: %!T",
+	                     (duk_tval *) duk_get_tval(ctx, -1)));
+}
+
+/*
+ *  Augment an error being created using Duktape specific properties
+ *  like _Tracedata or .fileName/.lineNumber.
+ */
+
+#if defined(DUK_USE_AUGMENT_ERROR_CREATE)
+DUK_LOCAL void duk__err_augment_builtin_create(duk_hthread *thr, duk_hthread *thr_callstack, const char *c_filename, duk_int_t c_line, duk_small_int_t noblame_fileline, duk_hobject *obj) {
+	duk_context *ctx = (duk_context *) thr;
+#if defined(DUK_USE_ASSERTIONS)
+	duk_int_t entry_top;
+#endif
+
+#if defined(DUK_USE_ASSERTIONS)
+	entry_top = duk_get_top(ctx);
+#endif
+	DUK_ASSERT(obj != NULL);
+
+	DUK_UNREF(obj);  /* unreferenced w/o tracebacks */
+	DUK_UNREF(ctx);  /* unreferenced w/o asserts */
+
+	duk__add_compiler_error_line(thr);
+
+#if defined(DUK_USE_TRACEBACKS)
+	/* If tracebacks are enabled, the '_Tracedata' property is the only
+	 * thing we need: 'fileName' and 'lineNumber' are virtual properties
+	 * which use '_Tracedata'.
+	 */
+	if (duk_hobject_hasprop_raw(thr, obj, DUK_HTHREAD_STRING_INT_TRACEDATA(thr))) {
+		DUK_DDD(DUK_DDDPRINT("error value already has a '_Tracedata' property, not modifying it"));
+	} else {
+		duk__add_traceback(thr, thr_callstack, c_filename, c_line, noblame_fileline);
+	}
+#else
+	/* Without tracebacks the concrete .fileName and .lineNumber need
+	 * to be added directly.
+	 */
+	duk__add_fileline(thr, thr_callstack, c_filename, c_line, noblame_fileline);
+#endif
+
+#if defined(DUK_USE_ASSERTIONS)
 	DUK_ASSERT(duk_get_top(ctx) == entry_top);
 #endif
 }
 #endif  /* DUK_USE_AUGMENT_ERROR_CREATE */
 
 /*
- *  Augment an error at creation time with tracedata/fileName/lineNumber
+ *  Augment an error at creation time with _Tracedata/fileName/lineNumber
  *  and allow a user error handler (if defined) to process/replace the error.
  *  The error to be augmented is at the stack top.
  *
  *  thr: thread containing the error value
  *  thr_callstack: thread which should be used for generating callstack etc.
- *  filename: C __FILE__ related to the error
- *  line: C __LINE__ related to the error
+ *  c_filename: C __FILE__ related to the error
+ *  c_line: C __LINE__ related to the error
  *  noblame_fileline: if true, don't fileName/line as error source, otherwise use traceback
  *                    (needed because user code filename/line are reported but internal ones
  *                    are not)
  *
- *  FIXME: rename noblame_fileline to flags field; combine it to some existing
+ *  XXX: rename noblame_fileline to flags field; combine it to some existing
  *  field (there are only a few call sites so this may not be worth it).
  */
 
 #if defined(DUK_USE_AUGMENT_ERROR_CREATE)
-void duk_err_augment_error_create(duk_hthread *thr, duk_hthread *thr_callstack, const char *filename, duk_int_t line, duk_bool_t noblame_fileline) {
+DUK_INTERNAL void duk_err_augment_error_create(duk_hthread *thr, duk_hthread *thr_callstack, const char *c_filename, duk_int_t c_line, duk_bool_t noblame_fileline) {
 	duk_context *ctx = (duk_context *) thr;
 	duk_hobject *obj;
 
@@ -28162,14 +42571,17 @@ void duk_err_augment_error_create(duk_hthread *thr, duk_hthread *thr_callstack,
 		DUK_DDD(DUK_DDDPRINT("value is not an object, skip both built-in and user augment"));
 		return;
 	}
-	if (!duk_hobject_prototype_chain_contains(thr, obj, thr->builtins[DUK_BIDX_ERROR_PROTOTYPE])) {
+	if (!duk_hobject_prototype_chain_contains(thr, obj, thr->builtins[DUK_BIDX_ERROR_PROTOTYPE], 1 /*ignore_loop*/)) {
+		/* If the value has a prototype loop, it's critical not to
+		 * throw here.  Instead, assume the value is not to be
+		 * augmented.
+		 */
 		DUK_DDD(DUK_DDDPRINT("value is not an error instance, skip both built-in and user augment"));
 		return;
 	}
-
 	if (DUK_HOBJECT_HAS_EXTENSIBLE(obj)) {
 		DUK_DDD(DUK_DDDPRINT("error meets criteria, built-in augment"));
-		duk__err_augment_builtin_throw(thr, thr_callstack, filename, line, noblame_fileline, obj);
+		duk__err_augment_builtin_create(thr, thr_callstack, c_filename, c_line, noblame_fileline, obj);
 	} else {
 		DUK_DDD(DUK_DDDPRINT("error does not meet criteria, no built-in augment"));
 	}
@@ -28189,7 +42601,7 @@ void duk_err_augment_error_create(duk_hthread *thr, duk_hthread *thr_callstack,
  */
 
 #if defined(DUK_USE_AUGMENT_ERROR_THROW)
-void duk_err_augment_error_throw(duk_hthread *thr) {
+DUK_INTERNAL void duk_err_augment_error_throw(duk_hthread *thr) {
 #if defined(DUK_USE_ERRTHROW)
 	duk__err_augment_user(thr, DUK_STRIDX_ERR_THROW);
 #endif  /* DUK_USE_ERRTHROW */
@@ -28203,9 +42615,15 @@ void duk_err_augment_error_throw(duk_hthread *thr) {
 
 /* include removed: duk_internal.h */
 
-void duk_err_longjmp(duk_hthread *thr) {
+DUK_INTERNAL void duk_err_longjmp(duk_hthread *thr) {
 	DUK_ASSERT(thr != NULL);
 
+#if defined(DUK_USE_CPP_EXCEPTIONS)
+	/* XXX: detecting uncaught exception case for C++ case; perhaps need
+	 * some marker in heap->lj state that a try-catch is active.  For now,
+	 * invokes C++ uncaught exception handling.
+	 */
+#else
 	if (!thr->heap->lj.jmpbuf_ptr) {
 		/*
 		 *  If we don't have a jmpbuf_ptr, there is little we can do
@@ -28213,152 +42631,69 @@ void duk_err_longjmp(duk_hthread *thr) {
 		 *  return.
 		 */
 
+		DUK_D(DUK_DPRINT("uncaught error: type=%d iserror=%d value1=%!T value2=%!T",
+		                 (int) thr->heap->lj.type, (int) thr->heap->lj.iserror,
+		                 &thr->heap->lj.value1, &thr->heap->lj.value2));
+
 		duk_fatal((duk_context *) thr, DUK_ERR_UNCAUGHT_ERROR, "uncaught error");
 		DUK_UNREACHABLE();
 	}
+#endif
 
-	DUK_LONGJMP(thr->heap->lj.jmpbuf_ptr->jb, DUK_LONGJMP_DUMMY_VALUE);
+#if defined(DUK_USE_CPP_EXCEPTIONS)
+	{
+		duk_internal_exception exc;  /* dummy */
+		throw exc;
+	}
+#else
+	DUK_LONGJMP(thr->heap->lj.jmpbuf_ptr->jb);
+#endif
 	DUK_UNREACHABLE();
 }
-#line 1 "duk_error_macros.c"
+#line 1 "duk_error_misc.c"
 /*
- *  Error, fatal, and panic handling.
+ *  Error helpers
  */
 
 /* include removed: duk_internal.h */
 
-#define DUK__ERRFMT_BUFSIZE  256  /* size for formatting buffers */
-
-#ifdef DUK_USE_VERBOSE_ERRORS
-
-#ifdef DUK_USE_VARIADIC_MACROS
-void duk_err_handle_error(const char *filename, duk_int_t line, duk_hthread *thr, duk_errcode_t code, const char *fmt, ...) {
-	va_list ap;
-	char msg[DUK__ERRFMT_BUFSIZE];
-	va_start(ap, fmt);
-	(void) DUK_VSNPRINTF(msg, sizeof(msg), fmt, ap);
-	msg[sizeof(msg) - 1] = (char) 0;
-	duk_err_create_and_throw(thr, code, msg, filename, line);
-	va_end(ap);  /* dead code, but ensures portability (see Linux man page notes) */
-}
-#else  /* DUK_USE_VARIADIC_MACROS */
-const char *duk_err_file_stash = NULL;
-duk_int_t duk_err_line_stash = 0;
-
-DUK_NORETURN(static void duk__handle_error(const char *filename, duk_int_t line, duk_hthread *thr, duk_errcode_t code, const char *fmt, va_list ap));
-
-static void duk__handle_error(const char *filename, duk_int_t line, duk_hthread *thr, duk_errcode_t code, const char *fmt, va_list ap) {
-	char msg[DUK__ERRFMT_BUFSIZE];
-	(void) DUK_VSNPRINTF(msg, sizeof(msg), fmt, ap);
-	msg[sizeof(msg) - 1] = (char) 0;
-	duk_err_create_and_throw(thr, code, msg, filename, line);
-}
-
-void duk_err_handle_error(const char *filename, duk_int_t line, duk_hthread *thr, duk_errcode_t code, const char *fmt, ...) {
-	va_list ap;
-	va_start(ap, fmt);
-	duk__handle_error(filename, line, thr, code, fmt, ap);
-	va_end(ap);  /* dead code */
-}
-
-void duk_err_handle_error_stash(duk_hthread *thr, duk_errcode_t code, const char *fmt, ...) {
-	va_list ap;
-	va_start(ap, fmt);
-	duk__handle_error(duk_err_file_stash, duk_err_line_stash, thr, code, fmt, ap);
-	va_end(ap);  /* dead code */
-}
-#endif  /* DUK_USE_VARIADIC_MACROS */
-
-#else  /* DUK_USE_VERBOSE_ERRORS */
-
-#ifdef DUK_USE_VARIADIC_MACROS
-void duk_err_handle_error(duk_hthread *thr, duk_errcode_t code) {
-	duk_err_create_and_throw(thr, code);
-}
-
-#else  /* DUK_USE_VARIADIC_MACROS */
-void duk_err_handle_error_nonverbose1(duk_hthread *thr, duk_errcode_t code, const char *fmt, ...) {
-	duk_err_create_and_throw(thr, code);
-}
-
-void duk_err_handle_error_nonverbose2(const char *filename, duk_int_t line, duk_hthread *thr, duk_errcode_t code, const char *fmt, ...) {
-	duk_err_create_and_throw(thr, code);
-}
-#endif  /* DUK_USE_VARIADIC_MACROS */
-
-#endif  /* DUK_USE_VERBOSE_ERRORS */
-
 /*
- *  Default fatal error handler
+ *  Helper to walk the thread chain and see if there is an active error
+ *  catcher.  Protected calls or finally blocks aren't considered catching.
  */
 
-void duk_default_fatal_handler(duk_context *ctx, duk_errcode_t code, const char *msg) {
-	DUK_UNREF(ctx);
-#ifdef DUK_USE_FILE_IO
-	DUK_FPRINTF(DUK_STDERR, "FATAL %ld: %s\n", (long) code, (const char *) (msg ? msg : "null"));
-	DUK_FFLUSH(DUK_STDERR);
-#else
-	/* omit print */
-#endif
-	DUK_D(DUK_DPRINT("default fatal handler called, code %ld -> calling DUK_PANIC()", (long) code));
-	DUK_PANIC(code, msg);
-	DUK_UNREACHABLE();
-}
-
-/*
- *  Default panic handler
- */
+#if defined(DUK_USE_DEBUGGER_SUPPORT) && \
+    (defined(DUK_USE_DEBUGGER_THROW_NOTIFY) || defined(DUK_USE_DEBUGGER_PAUSE_UNCAUGHT))
+DUK_LOCAL duk_bool_t duk__have_active_catcher(duk_hthread *thr) {
+	/*
+	 * XXX: As noted above, a protected API call won't be counted as a
+	 * catcher. This is usually convenient, e.g. in the case of a top-
+	 * level duk_pcall(), but may not always be desirable. Perhaps add an
+	 * argument to treat them as catchers?
+	 */
 
-#if !defined(DUK_USE_PANIC_HANDLER)
-void duk_default_panic_handler(duk_errcode_t code, const char *msg) {
-#ifdef DUK_USE_FILE_IO
-	DUK_FPRINTF(DUK_STDERR, "PANIC %ld: %s ("
-#if defined(DUK_USE_PANIC_ABORT)
-	            "calling abort"
-#elif defined(DUK_USE_PANIC_EXIT)
-	            "calling exit"
-#elif defined(DUK_USE_PANIC_SEGFAULT)
-	            "segfaulting on purpose"
-#else
-#error no DUK_USE_PANIC_xxx macro defined
-#endif	
-	            ")\n", (long) code, (const char *) (msg ? msg : "null"));
-	DUK_FFLUSH(DUK_STDERR);
-#else
-	/* omit print */
-	DUK_UNREF(code);
-	DUK_UNREF(msg);
-#endif
+	duk_size_t i;
 
-#if defined(DUK_USE_PANIC_ABORT)
-	DUK_ABORT();
-#elif defined(DUK_USE_PANIC_EXIT)
-	DUK_EXIT(-1);
-#elif defined(DUK_USE_PANIC_SEGFAULT)
-	/* exit() afterwards to satisfy "noreturn" */
-	DUK_CAUSE_SEGFAULT();  /* SCANBUILD: "Dereference of null pointer", normal */
-	DUK_EXIT(-1);
-#else
-#error no DUK_USE_PANIC_xxx macro defined
-#endif
+	DUK_ASSERT(thr != NULL);
 
-	DUK_UNREACHABLE();
+	while (thr != NULL) {
+		for (i = 0; i < thr->catchstack_top; i++) {
+			duk_catcher *cat = thr->catchstack + i;
+			if (DUK_CAT_HAS_CATCH_ENABLED(cat)) {
+				return 1;  /* all we need to know */
+			}
+		}
+		thr = thr->resumer;
+	}
+	return 0;
 }
-#endif  /* !DUK_USE_PANIC_HANDLER */
-
-#undef DUK__ERRFMT_BUFSIZE
-#line 1 "duk_error_misc.c"
-/*
- *  Error helpers
- */
-
-/* include removed: duk_internal.h */
+#endif  /* DUK_USE_DEBUGGER_SUPPORT && (DUK_USE_DEBUGGER_THROW_NOTIFY || DUK_USE_DEBUGGER_PAUSE_UNCAUGHT) */
 
 /*
  *  Get prototype object for an integer error code.
  */
 
-duk_hobject *duk_error_prototype_from_code(duk_hthread *thr, duk_errcode_t code) {
+DUK_INTERNAL duk_hobject *duk_error_prototype_from_code(duk_hthread *thr, duk_errcode_t code) {
 	switch (code) {
 	case DUK_ERR_EVAL_ERROR:
 		return thr->builtins[DUK_BIDX_EVAL_ERROR_PROTOTYPE];
@@ -28389,16 +42724,62 @@ duk_hobject *duk_error_prototype_from_code(duk_hthread *thr, duk_errcode_t code)
  *  Exposed helper for setting up heap longjmp state.
  */
 
-void duk_err_setup_heap_ljstate(duk_hthread *thr, duk_small_int_t lj_type) {
-	duk_tval tv_tmp;
+DUK_INTERNAL void duk_err_setup_heap_ljstate(duk_hthread *thr, duk_small_int_t lj_type) {
+#if defined(DUK_USE_DEBUGGER_SUPPORT)
+	/* If something is thrown with the debugger attached and nobody will
+	 * catch it, execution is paused before the longjmp, turning over
+	 * control to the debug client.  This allows local state to be examined
+	 * before the stack is unwound.  Errors are not intercepted when debug
+	 * message loop is active (e.g. for Eval).
+	 */
+
+	/* XXX: Allow customizing the pause and notify behavior at runtime
+	 * using debugger runtime flags.  For now the behavior is fixed using
+	 * config options.
+	 */
+#if defined(DUK_USE_DEBUGGER_THROW_NOTIFY) || defined(DUK_USE_DEBUGGER_PAUSE_UNCAUGHT)
+	if (DUK_HEAP_IS_DEBUGGER_ATTACHED(thr->heap) &&
+	    !thr->heap->dbg_processing &&
+	    lj_type == DUK_LJ_TYPE_THROW) {
+		duk_context *ctx = (duk_context *) thr;
+		duk_bool_t fatal;
+		duk_hobject *h_obj;
+
+		/* Don't intercept a DoubleError, we may have caused the initial double
+		 * fault and attempting to intercept it will cause us to be called
+		 * recursively and exhaust the C stack.
+		 */
+		h_obj = duk_get_hobject(ctx, -1);
+		if (h_obj == thr->builtins[DUK_BIDX_DOUBLE_ERROR]) {
+			DUK_D(DUK_DPRINT("built-in DoubleError instance thrown, not intercepting"));
+			goto skip_throw_intercept;
+		}
+
+		DUK_D(DUK_DPRINT("throw with debugger attached, report to client"));
+
+		fatal = !duk__have_active_catcher(thr);
+
+#if defined(DUK_USE_DEBUGGER_THROW_NOTIFY)
+		/* Report it to the debug client */
+		duk_debug_send_throw(thr, fatal);
+#endif
+
+#if defined(DUK_USE_DEBUGGER_PAUSE_UNCAUGHT)
+		if (fatal) {
+			DUK_D(DUK_DPRINT("throw will be fatal, halt before longjmp"));
+			duk_debug_halt_execution(thr, 1 /*use_prev_pc*/);
+		}
+#endif
+	}
+
+ skip_throw_intercept:
+#endif  /* DUK_USE_DEBUGGER_THROW_NOTIFY || DUK_USE_DEBUGGER_PAUSE_UNCAUGHT */
+#endif  /* DUK_USE_DEBUGGER_SUPPORT */
 
 	thr->heap->lj.type = lj_type;
 
 	DUK_ASSERT(thr->valstack_top > thr->valstack);
-	DUK_TVAL_SET_TVAL(&tv_tmp, &thr->heap->lj.value1);
-	DUK_TVAL_SET_TVAL(&thr->heap->lj.value1, thr->valstack_top - 1);
-	DUK_TVAL_INCREF(thr, &thr->heap->lj.value1);
-	DUK_TVAL_DECREF(thr, &tv_tmp);
+	DUK_TVAL_SET_TVAL_UPDREF(thr, &thr->heap->lj.value1, thr->valstack_top - 1);  /* side effects */
 
 	duk_pop((duk_context *) thr);
 }
@@ -28426,9 +42807,9 @@ void duk_err_setup_heap_ljstate(duk_hthread *thr, duk_small_int_t lj_type) {
  */
 
 #ifdef DUK_USE_VERBOSE_ERRORS
-void duk_err_create_and_throw(duk_hthread *thr, duk_errcode_t code, const char *msg, const char *filename, duk_int_t line) {
+DUK_INTERNAL void duk_err_create_and_throw(duk_hthread *thr, duk_errcode_t code, const char *msg, const char *filename, duk_int_t line) {
 #else
-void duk_err_create_and_throw(duk_hthread *thr, duk_errcode_t code) {
+DUK_INTERNAL void duk_err_create_and_throw(duk_hthread *thr, duk_errcode_t code) {
 #endif
 	duk_context *ctx = (duk_context *) thr;
 	duk_bool_t double_error = thr->heap->handling_error;
@@ -28446,13 +42827,30 @@ void duk_err_create_and_throw(duk_hthread *thr, duk_errcode_t code) {
 
 	thr->heap->handling_error = 1;
 
+	if (!double_error) {
+		/* Allow headroom for calls during error handling (see GH-191).
+		 * We allow space for 10 additional recursions, with one extra
+		 * for, e.g. a print() call at the deepest level.
+		 */
+		DUK_ASSERT(thr->callstack_max == DUK_CALLSTACK_DEFAULT_MAX);
+		thr->callstack_max = DUK_CALLSTACK_DEFAULT_MAX + DUK_CALLSTACK_GROW_STEP + 11;
+	}
+
+	DUK_ASSERT(thr->callstack_max == DUK_CALLSTACK_DEFAULT_MAX + DUK_CALLSTACK_GROW_STEP + 11);  /* just making sure */
+
+	/* Sync so that augmentation sees up-to-date activations, NULL
+	 * thr->ptr_curr_pc so that it's not used if side effects occur
+	 * in augmentation or longjmp handling.
+	 */
+	duk_hthread_sync_and_null_currpc(thr);
+
 	/*
 	 *  Create and push an error object onto the top of stack.
 	 *  If a "double error" occurs, use a fixed error instance
 	 *  to avoid further trouble.
 	 */
 
-	/* FIXME: if attempt to push beyond allocated valstack, this double fault
+	/* XXX: if attempt to push beyond allocated valstack, this double fault
 	 * handling fails miserably.  We should really write the double error
 	 * directly to thr->heap->lj.value1 and avoid valstack use entirely.
 	 */
@@ -28506,10 +42904,11 @@ void duk_err_create_and_throw(duk_hthread *thr, duk_errcode_t code) {
 	 *  Finally, longjmp
 	 */
 
-	thr->heap->handling_error = 0;
-
 	duk_err_setup_heap_ljstate(thr, DUK_LJ_TYPE_THROW);
 
+	thr->callstack_max = DUK_CALLSTACK_DEFAULT_MAX;  /* reset callstack limit */
+	thr->heap->handling_error = 0;
+
 	DUK_DDD(DUK_DDDPRINT("THROW ERROR (INTERNAL): %!iT, %!iT (after throw augment)",
 	                     (duk_tval *) &thr->heap->lj.value1, (duk_tval *) &thr->heap->lj.value2));
 
@@ -28521,7 +42920,7 @@ void duk_err_create_and_throw(duk_hthread *thr, duk_errcode_t code) {
  *  Helper for C function call negative return values.
  */
 
-void duk_error_throw_from_negative_rc(duk_hthread *thr, duk_ret_t rc) {
+DUK_INTERNAL void duk_error_throw_from_negative_rc(duk_hthread *thr, duk_ret_t rc) {
 	duk_context *ctx = (duk_context *) thr;
 	const char *msg;
 	duk_errcode_t code;
@@ -28529,9 +42928,10 @@ void duk_error_throw_from_negative_rc(duk_hthread *thr, duk_ret_t rc) {
 	DUK_ASSERT(thr != NULL);
 	DUK_ASSERT(rc < 0);
 
-	/* FIXME: this generates quite large code - perhaps select the error
+	/* XXX: this generates quite large code - perhaps select the error
 	 * class based on the code and then just use the error 'name'?
 	 */
+	/* XXX: shared strings */
 
 	code = -rc;
 
@@ -28572,37 +42972,74 @@ void duk_error_throw_from_negative_rc(duk_hthread *thr, duk_ret_t rc) {
 
 /* include removed: duk_internal.h */
 
-duk_hbuffer *duk_hbuffer_alloc(duk_heap *heap, duk_size_t size, duk_bool_t dynamic) {
+/* Allocate a new duk_hbuffer of a certain type and return a pointer to it
+ * (NULL on error).  Write buffer data pointer to 'out_bufdata' (only if
+ * allocation successful).
+ */
+DUK_INTERNAL duk_hbuffer *duk_hbuffer_alloc(duk_heap *heap, duk_size_t size, duk_small_uint_t flags, void **out_bufdata) {
 	duk_hbuffer *res = NULL;
+	duk_size_t header_size;
 	duk_size_t alloc_size;
 
+	DUK_ASSERT(heap != NULL);
+	DUK_ASSERT(out_bufdata != NULL);
+
 	DUK_DDD(DUK_DDDPRINT("allocate hbuffer"));
 
-	if (dynamic) {
+	/* Size sanity check.  Should not be necessary because caller is
+	 * required to check this, but we don't want to cause a segfault
+	 * if the size wraps either in duk_size_t computation or when
+	 * storing the size in a 16-bit field.
+	 */
+	if (size > DUK_HBUFFER_MAX_BYTELEN) {
+		DUK_D(DUK_DPRINT("hbuffer alloc failed: size too large: %ld", (long) size));
+		return NULL;  /* no need to write 'out_bufdata' */
+	}
+
+	if (flags & DUK_BUF_FLAG_EXTERNAL) {
+		header_size = sizeof(duk_hbuffer_external);
+		alloc_size = sizeof(duk_hbuffer_external);
+	} if (flags & DUK_BUF_FLAG_DYNAMIC) {
+		header_size = sizeof(duk_hbuffer_dynamic);
 		alloc_size = sizeof(duk_hbuffer_dynamic);
 	} else {
+		header_size = sizeof(duk_hbuffer_fixed);
 		alloc_size = sizeof(duk_hbuffer_fixed) + size;
+		DUK_ASSERT(alloc_size >= sizeof(duk_hbuffer_fixed));  /* no wrapping */
 	}
 
-#ifdef DUK_USE_ZERO_BUFFER_DATA
-	/* zero everything */
-	res = (duk_hbuffer *) DUK_ALLOC_ZEROED(heap, alloc_size);
-#else
 	res = (duk_hbuffer *) DUK_ALLOC(heap, alloc_size);
-#endif
 	if (!res) {
 		goto error;
 	}
 
-#ifndef DUK_USE_ZERO_BUFFER_DATA
-	/* if no buffer zeroing, zero the header anyway */
-	DUK_MEMZERO((void *) res, dynamic ? sizeof(duk_hbuffer_dynamic) : sizeof(duk_hbuffer_fixed));
+	/* zero everything unless requested not to do so */
+#if defined(DUK_USE_ZERO_BUFFER_DATA)
+	DUK_MEMZERO((void *) res,
+	            (flags & DUK_BUF_FLAG_NOZERO) ? header_size : alloc_size);
+#else
+	DUK_MEMZERO((void *) res, header_size);
 #endif
 
-	if (dynamic) {
+	if (flags & DUK_BUF_FLAG_EXTERNAL) {
+		duk_hbuffer_external *h;
+		h = (duk_hbuffer_external *) res;
+		DUK_UNREF(h);
+		*out_bufdata = NULL;
+#if defined(DUK_USE_EXPLICIT_NULL_INIT)
+#if defined(DUK_USE_HEAPPTR16)
+/* the compressed pointer is zeroed which maps to NULL, so nothing to do. */
+#else
+		DUK_HBUFFER_EXTERNAL_SET_DATA_PTR(heap, h, NULL);
+#endif
+#endif
+		DUK_ASSERT(DUK_HBUFFER_EXTERNAL_GET_DATA_PTR(heap, h) == NULL);
+	} else if (flags & DUK_BUF_FLAG_DYNAMIC) {
 		duk_hbuffer_dynamic *h = (duk_hbuffer_dynamic *) res;
 		void *ptr;
+
 		if (size > 0) {
+			DUK_ASSERT(!(flags & DUK_BUF_FLAG_EXTERNAL));  /* alloc external with size zero */
 			DUK_DDD(DUK_DDDPRINT("dynamic buffer with nonzero size, alloc actual buffer"));
 #ifdef DUK_USE_ZERO_BUFFER_DATA
 			ptr = DUK_ALLOC_ZEROED(heap, size);
@@ -28613,22 +43050,34 @@ duk_hbuffer *duk_hbuffer_alloc(duk_heap *heap, duk_size_t size, duk_bool_t dynam
 				/* Because size > 0, NULL check is correct */
 				goto error;
 			}
+			*out_bufdata = ptr;
 
-			h->curr_alloc = ptr;
-			h->usable_size = size;  /* snug */
+			DUK_HBUFFER_DYNAMIC_SET_DATA_PTR(heap, h, ptr);
 		} else {
-#ifdef DUK_USE_EXPLICIT_NULL_INIT
-			h->curr_alloc = NULL;
+			*out_bufdata = NULL;
+#if defined(DUK_USE_EXPLICIT_NULL_INIT)
+#if defined(DUK_USE_HEAPPTR16)
+/* the compressed pointer is zeroed which maps to NULL, so nothing to do. */
+#else
+			DUK_HBUFFER_DYNAMIC_SET_DATA_PTR(heap, h, NULL);
+#endif
 #endif
-			DUK_ASSERT(h->usable_size == 0);
+			DUK_ASSERT(DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(heap, h) == NULL);
 		}
+	} else {
+		*out_bufdata = (void *) ((duk_hbuffer_fixed *) res + 1);
 	}
 
-	res->size = size;
+	DUK_HBUFFER_SET_SIZE(res, size);
 
 	DUK_HEAPHDR_SET_TYPE(&res->hdr, DUK_HTYPE_BUFFER);
-	if (dynamic) {
+	if (flags & DUK_BUF_FLAG_DYNAMIC) {
 		DUK_HBUFFER_SET_DYNAMIC(res);
+		if (flags & DUK_BUF_FLAG_EXTERNAL) {
+			DUK_HBUFFER_SET_EXTERNAL(res);
+		}
+	} else {
+		DUK_ASSERT(!(flags & DUK_BUF_FLAG_EXTERNAL));
 	}
         DUK_HEAP_INSERT_INTO_HEAP_ALLOCATED(heap, &res->hdr);
 
@@ -28639,14 +43088,15 @@ duk_hbuffer *duk_hbuffer_alloc(duk_heap *heap, duk_size_t size, duk_bool_t dynam
 	DUK_DD(DUK_DDPRINT("hbuffer allocation failed"));
 
 	DUK_FREE(heap, res);
-	return NULL;
+	return NULL;  /* no need to write 'out_bufdata' */
 }
 
 /* For indirect allocs. */
 
-void *duk_hbuffer_get_dynalloc_ptr(void *ud) {
+DUK_INTERNAL void *duk_hbuffer_get_dynalloc_ptr(duk_heap *heap, void *ud) {
 	duk_hbuffer_dynamic *buf = (duk_hbuffer_dynamic *) ud;
-	return (void *) buf->curr_alloc;
+	DUK_UNREF(heap);
+	return (void *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(heap, buf);
 }
 #line 1 "duk_hbuffer_ops.c"
 /*
@@ -28666,33 +43116,17 @@ void *duk_hbuffer_get_dynalloc_ptr(void *ud) {
  *  Resizing
  */
 
-static duk_size_t duk__add_spare(duk_size_t size) {
-	duk_size_t spare = (size / DUK_HBUFFER_SPARE_DIVISOR) + DUK_HBUFFER_SPARE_ADD;
-	duk_size_t res;
-
-	res = size + spare;
-	if (res < size) {
-		/* XXX: handle corner cases where size is close to size limit (wraparound) */
-		DUK_PANIC(DUK_ERR_INTERNAL_ERROR, "duk_size_t wrapped");
-	}
-	DUK_ASSERT(res >= size);
-
-	return res;
-}
-
-void duk_hbuffer_resize(duk_hthread *thr, duk_hbuffer_dynamic *buf, duk_size_t new_size, duk_size_t new_usable_size) {
-	duk_size_t new_alloc_size;
+DUK_INTERNAL void duk_hbuffer_resize(duk_hthread *thr, duk_hbuffer_dynamic *buf, duk_size_t new_size) {
 	void *res;
+	duk_size_t prev_size;
 
 	DUK_ASSERT(thr != NULL);
 	DUK_ASSERT(buf != NULL);
-	DUK_ASSERT(new_usable_size >= new_size);
 	DUK_ASSERT(DUK_HBUFFER_HAS_DYNAMIC(buf));
+	DUK_ASSERT(!DUK_HBUFFER_HAS_EXTERNAL(buf));
 
 	/*
 	 *  Maximum size check
-	 *
-	 *  XXX: check against usable size?
 	 */
 
 	if (new_size > DUK_HBUFFER_MAX_BYTELEN) {
@@ -28705,444 +43139,71 @@ void duk_hbuffer_resize(duk_hthread *thr, duk_hbuffer_dynamic *buf, duk_size_t n
 	 *  collection.
 	 */
 
-	new_alloc_size = new_usable_size;
-	res = DUK_REALLOC_INDIRECT(thr->heap, duk_hbuffer_get_dynalloc_ptr, (void *) buf, new_alloc_size);
-	if (res != NULL || new_alloc_size == 0) {
+	res = DUK_REALLOC_INDIRECT(thr->heap, duk_hbuffer_get_dynalloc_ptr, (void *) buf, new_size);
+	if (res != NULL || new_size == 0) {
 		/* 'res' may be NULL if new allocation size is 0. */
 
-		DUK_DDD(DUK_DDDPRINT("resized dynamic buffer %p:%ld:%ld -> %p:%ld:%ld",
-		                     (void *) buf->curr_alloc, (long) buf->size, (long) buf->usable_size,
-		                     (void *) res, (long) new_size, (long) new_usable_size));
+		DUK_DDD(DUK_DDDPRINT("resized dynamic buffer %p:%ld -> %p:%ld",
+		                     (void *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(thr->heap, buf),
+		                     (long) DUK_HBUFFER_DYNAMIC_GET_SIZE(buf),
+		                     (void *) res,
+		                     (long) new_size));
 
 		/*
 		 *  The entire allocated buffer area, regardless of actual used
 		 *  size, is kept zeroed in resizes for simplicity.  If the buffer
-		 *  is grown, zero the new part.  Another policy would be to
-		 *  ensure data is zeroed as the used part is extended.  The
-		 *  current approach is much more simple and is not a big deal
-		 *  because the spare part is relatively small.
+		 *  is grown, zero the new part.
 		 */
 
-		if (new_alloc_size > buf->usable_size) {
-			DUK_ASSERT(new_alloc_size - buf->usable_size > 0);
+		prev_size = DUK_HBUFFER_DYNAMIC_GET_SIZE(buf);
+		if (new_size > prev_size) {
+			DUK_ASSERT(new_size - prev_size > 0);
 #ifdef DUK_USE_ZERO_BUFFER_DATA
-			DUK_MEMZERO((void *) ((char *) res + buf->usable_size),
-			            new_alloc_size - buf->usable_size);
+			DUK_MEMZERO((void *) ((char *) res + prev_size),
+			            (duk_size_t) (new_size - prev_size));
 #endif
 		}
 
-		buf->size = new_size;
-		buf->usable_size = new_usable_size;
-		buf->curr_alloc = res;
+		DUK_HBUFFER_DYNAMIC_SET_SIZE(buf, new_size);
+		DUK_HBUFFER_DYNAMIC_SET_DATA_PTR(thr->heap, buf, res);
 	} else {
-		DUK_ERROR(thr, DUK_ERR_ALLOC_ERROR, "buffer resize failed: %ld:%ld to %ld:%ld",
-		          (long) buf->size, (long) buf->usable_size,
-		          (long) new_size, (long) new_usable_size);
+		DUK_ERROR(thr, DUK_ERR_ALLOC_ERROR, "buffer resize failed: %ld to %ld",
+		          (long) DUK_HBUFFER_DYNAMIC_GET_SIZE(buf),
+		          (long) new_size);
 	}
 
-	DUK_ASSERT(res != NULL || new_alloc_size == 0);
+	DUK_ASSERT(res != NULL || new_size == 0);
 }
 
-void duk_hbuffer_reset(duk_hthread *thr, duk_hbuffer_dynamic *buf) {
+DUK_INTERNAL void duk_hbuffer_reset(duk_hthread *thr, duk_hbuffer_dynamic *buf) {
 	DUK_ASSERT(thr != NULL);
 	DUK_ASSERT(buf != NULL);
 	DUK_ASSERT(DUK_HBUFFER_HAS_DYNAMIC(buf));
+	DUK_ASSERT(!DUK_HBUFFER_HAS_EXTERNAL(buf));
 
-	duk_hbuffer_resize(thr, buf, 0, 0);
+	duk_hbuffer_resize(thr, buf, 0);
 }
+/* include removed: duk_internal.h */
+#line 2 "duk_hbufferobject_misc.c"
 
-void duk_hbuffer_compact(duk_hthread *thr, duk_hbuffer_dynamic *buf) {
-	duk_size_t curr_size;
-
-	DUK_ASSERT(thr != NULL);
-	DUK_ASSERT(buf != NULL);
-	DUK_ASSERT(DUK_HBUFFER_HAS_DYNAMIC(buf));
-
-	curr_size = DUK_HBUFFER_GET_SIZE(buf);
-	duk_hbuffer_resize(thr, buf, curr_size, curr_size);
-}
-
-/*
- *  Inserts
- */
-
-void duk_hbuffer_insert_bytes(duk_hthread *thr, duk_hbuffer_dynamic *buf, duk_size_t offset, duk_uint8_t *data, duk_size_t length) {
-	duk_uint8_t *p;
-
-	/* XXX: allow inserts with offset > curr_size? i.e., insert zeroes automatically? */
-
-	DUK_ASSERT(thr != NULL);
-	DUK_ASSERT(buf != NULL);
-	DUK_ASSERT(DUK_HBUFFER_HAS_DYNAMIC(buf));
-	DUK_ASSERT_DISABLE(offset >= 0);  /* unsigned, so always true */
-	DUK_ASSERT(offset <= DUK_HBUFFER_GET_SIZE(buf));  /* equality is OK (= append) */
-	DUK_ASSERT(data != NULL);
-	DUK_ASSERT_DISABLE(length >= 0);  /* unsigned, so always true */
-
-	if (length == 0) {
-		return;
-	}
-
-	if (DUK_HBUFFER_DYNAMIC_GET_SPARE_SIZE(buf) < length) {
-		duk_hbuffer_resize(thr,
-		                   buf,
-		                   DUK_HBUFFER_GET_SIZE(buf),
-		                   duk__add_spare(DUK_HBUFFER_GET_SIZE(buf) + length));
-	}
-	DUK_ASSERT(DUK_HBUFFER_DYNAMIC_GET_SPARE_SIZE(buf) >= length);
-
-	p = (duk_uint8_t *) DUK_HBUFFER_DYNAMIC_GET_CURR_DATA_PTR(buf);
-	if (offset < DUK_HBUFFER_GET_SIZE(buf)) {
-		/* not an append */
-
-		DUK_ASSERT(DUK_HBUFFER_GET_SIZE(buf) - offset > 0);
-		DUK_MEMMOVE((void *) (p + offset + length),
-		            (void *) (p + offset),
-		            DUK_HBUFFER_GET_SIZE(buf) - offset);
-	}
-
-	DUK_ASSERT(length > 0);
-	DUK_MEMCPY((void *) (p + offset),
-	           data,
-	           length);
-
-	buf->size += length;
-}
-
-void duk_hbuffer_insert_byte(duk_hthread *thr, duk_hbuffer_dynamic *buf, duk_size_t offset, duk_uint8_t byte) {
-	DUK_ASSERT(thr != NULL);
-	DUK_ASSERT(buf != NULL);
-	DUK_ASSERT(DUK_HBUFFER_HAS_DYNAMIC(buf));
-
-	duk_hbuffer_insert_bytes(thr, buf, offset, &byte, 1);
-}
-
-duk_size_t duk_hbuffer_insert_cstring(duk_hthread *thr, duk_hbuffer_dynamic *buf, duk_size_t offset, const char *str) {
-	duk_size_t len;
-
-	DUK_ASSERT(thr != NULL);
-	DUK_ASSERT(buf != NULL);
-	DUK_ASSERT(str != NULL);
-	DUK_ASSERT(DUK_HBUFFER_HAS_DYNAMIC(buf));
-
-	len = DUK_STRLEN(str);
-	duk_hbuffer_insert_bytes(thr, buf, offset, (duk_uint8_t *) str, len);
-	return len;
-}
-
-duk_size_t duk_hbuffer_insert_hstring(duk_hthread *thr, duk_hbuffer_dynamic *buf, duk_size_t offset, duk_hstring *str) {
-	duk_size_t len;
-
-	DUK_ASSERT(thr != NULL);
-	DUK_ASSERT(buf != NULL);
-	DUK_ASSERT(str != NULL);
-	DUK_ASSERT(DUK_HBUFFER_HAS_DYNAMIC(buf));
-
-	len = DUK_HSTRING_GET_BYTELEN(str);
-	duk_hbuffer_insert_bytes(thr, buf, offset, (duk_uint8_t *) DUK_HSTRING_GET_DATA(str), len);
-	return len;
-}
-
-duk_size_t duk_hbuffer_insert_xutf8(duk_hthread *thr, duk_hbuffer_dynamic *buf, duk_size_t offset, duk_ucodepoint_t codepoint) {
-	duk_uint8_t tmp[DUK_UNICODE_MAX_XUTF8_LENGTH];
-	duk_size_t len;
-
-	DUK_ASSERT(thr != NULL);
-	DUK_ASSERT(buf != NULL);
-	DUK_ASSERT(DUK_HBUFFER_HAS_DYNAMIC(buf));
-	/* No range assertion for 'codepoint' */
-
-	/* Intentionally no fast path: insertion is not that central */
-
-	len = (duk_size_t) duk_unicode_encode_xutf8(codepoint, tmp);
-	duk_hbuffer_insert_bytes(thr, buf, offset, tmp, len);
-	return len;
-}
-
-/* Append a Unicode codepoint to the buffer in CESU-8 format, i.e., convert
- * non-BMP characters to surrogate pairs which are then "UTF-8" encoded.
- * If the codepoint is initially a surrogate, it is also encoded into CESU-8.
- * Codepoints above valid Unicode range (> U+10FFFF) are mangled.
- */
-
-duk_size_t duk_hbuffer_insert_cesu8(duk_hthread *thr, duk_hbuffer_dynamic *buf, duk_size_t offset, duk_ucodepoint_t codepoint) {
-	duk_uint8_t tmp[DUK_UNICODE_MAX_CESU8_LENGTH];
-	duk_size_t len;
-
-	DUK_ASSERT(thr != NULL);
-	DUK_ASSERT(buf != NULL);
-	DUK_ASSERT(DUK_HBUFFER_HAS_DYNAMIC(buf));
-	DUK_ASSERT_DISABLE(codepoint >= 0);  /* unsigned */
-	DUK_ASSERT(codepoint <= 0x10ffff);  /* if not in this range, results are garbage (but no crash) */
-
-	/* Intentionally no fast path: insertion is not that central */
-
-	len = (duk_size_t) duk_unicode_encode_cesu8(codepoint, tmp);
-	duk_hbuffer_insert_bytes(thr, buf, offset, tmp, len);
-	return len;
-}
-
-/*
- *  Appends
- *
- *  Note: an optimized duk_hbuffer_append_bytes() could be implemented, but
- *  it is more compact to use duk_hbuffer_insert_bytes() instead.  The
- *  important fast paths bypass these functions. anyway.
- */
-
-void duk_hbuffer_append_bytes(duk_hthread *thr, duk_hbuffer_dynamic *buf, duk_uint8_t *data, duk_size_t length) {
-	DUK_ASSERT(thr != NULL);
-	DUK_ASSERT(buf != NULL);
-	DUK_ASSERT(DUK_HBUFFER_HAS_DYNAMIC(buf));
-	DUK_ASSERT(data != NULL);
-
-	duk_hbuffer_insert_bytes(thr, buf, DUK_HBUFFER_GET_SIZE(buf), data, length);
-}
-
-void duk_hbuffer_append_byte(duk_hthread *thr, duk_hbuffer_dynamic *buf, duk_uint8_t byte) {
-	DUK_ASSERT(thr != NULL);
-	DUK_ASSERT(buf != NULL);
-	DUK_ASSERT(DUK_HBUFFER_HAS_DYNAMIC(buf));
-
-	duk_hbuffer_insert_bytes(thr, buf, DUK_HBUFFER_GET_SIZE(buf), &byte, 1);
-}
-
-duk_size_t duk_hbuffer_append_cstring(duk_hthread *thr, duk_hbuffer_dynamic *buf, const char *str) {
-	duk_size_t len;
-
-	DUK_ASSERT(thr != NULL);
-	DUK_ASSERT(buf != NULL);
-	DUK_ASSERT(str != NULL);
-	DUK_ASSERT(DUK_HBUFFER_HAS_DYNAMIC(buf));
-
-	len = DUK_STRLEN(str);
-	duk_hbuffer_insert_bytes(thr, buf, DUK_HBUFFER_GET_SIZE(buf), (duk_uint8_t *) str, len);
-	return len;
-}
-
-duk_size_t duk_hbuffer_append_hstring(duk_hthread *thr, duk_hbuffer_dynamic *buf, duk_hstring *str) {
-	duk_size_t len;
-
-	DUK_ASSERT(thr != NULL);
-	DUK_ASSERT(buf != NULL);
-	DUK_ASSERT(str != NULL);
-	DUK_ASSERT(DUK_HBUFFER_HAS_DYNAMIC(buf));
-
-	len = DUK_HSTRING_GET_BYTELEN(str);
-	duk_hbuffer_insert_bytes(thr, buf, DUK_HBUFFER_GET_SIZE(buf), (duk_uint8_t *) DUK_HSTRING_GET_DATA(str), len);
-	return len;
-}
-
-/* Append a Unicode codepoint to the buffer in extended UTF-8 format, i.e.
- * allow codepoints above standard Unicode range (> U+10FFFF) up to seven
- * byte encoding (36 bits, but argument type is 32 bits).  In particular,
- * allows encoding of all unsigned 32-bit integers.  If the codepoint is
- * initially a surrogate, it is encoded without checking (and will become,
- * effectively, CESU-8 encoded).
- */
-
-duk_size_t duk_hbuffer_append_xutf8(duk_hthread *thr, duk_hbuffer_dynamic *buf, duk_ucodepoint_t codepoint) {
-	duk_uint8_t tmp[DUK_UNICODE_MAX_XUTF8_LENGTH];
-	duk_size_t len;
-
-	DUK_ASSERT(thr != NULL);
-	DUK_ASSERT(buf != NULL);
-	DUK_ASSERT(DUK_HBUFFER_HAS_DYNAMIC(buf));
-	/* No range assertion for 'codepoint' */
-
-	if (DUK_LIKELY(codepoint < 0x80 && DUK_HBUFFER_DYNAMIC_GET_SPARE_SIZE(buf) > 0)) {
-		/* fast path: ASCII and there is spare */
-		duk_uint8_t *p = ((duk_uint8_t *) DUK_HBUFFER_DYNAMIC_GET_CURR_DATA_PTR(buf));
-		p[buf->size++] = (duk_uint8_t) codepoint;
-		return 1;
-	}
-
-	len = (duk_size_t) duk_unicode_encode_xutf8(codepoint, tmp);
-	duk_hbuffer_insert_bytes(thr, buf, DUK_HBUFFER_GET_SIZE(buf), tmp, len);
-	return len;
-}
-
-/* Append a Unicode codepoint to the buffer in CESU-8 format, i.e., convert
- * non-BMP characters to surrogate pairs which are then "UTF-8" encoded.
- * If the codepoint is initially a surrogate, it is also encoded into CESU-8.
- * Codepoints above valid Unicode range (> U+10FFFF) are mangled.
- */
-
-duk_size_t duk_hbuffer_append_cesu8(duk_hthread *thr, duk_hbuffer_dynamic *buf, duk_ucodepoint_t codepoint) {
-	duk_uint8_t tmp[DUK_UNICODE_MAX_CESU8_LENGTH];
-	duk_size_t len;
-
-	DUK_ASSERT(thr != NULL);
-	DUK_ASSERT(buf != NULL);
-	DUK_ASSERT(DUK_HBUFFER_HAS_DYNAMIC(buf));
-	DUK_ASSERT_DISABLE(codepoint >= 0);  /* unsigned */
-	DUK_ASSERT(codepoint <= 0x10ffff);  /* if not in this range, results are garbage (but no crash) */
-
-	if (DUK_LIKELY(codepoint < 0x80 && DUK_HBUFFER_DYNAMIC_GET_SPARE_SIZE(buf) > 0)) {
-		/* fast path: ASCII and there is spare */
-		duk_uint8_t *p = ((duk_uint8_t *) DUK_HBUFFER_DYNAMIC_GET_CURR_DATA_PTR(buf));
-		p[buf->size++] = (duk_uint8_t) codepoint;
-		return 1;
-	}
-
-	len = (duk_size_t) duk_unicode_encode_cesu8(codepoint, tmp);
-	duk_hbuffer_insert_bytes(thr, buf, DUK_HBUFFER_GET_SIZE(buf), tmp, len);
-	return len;
-}
-
-/* Append an duk_uint32_t in native byte order.  This is used to emit bytecode
- * instructions.
- */
-
-void duk_hbuffer_append_native_u32(duk_hthread *thr, duk_hbuffer_dynamic *buf, duk_uint32_t val) {
-	/* relies on duk_uint32_t being exactly right size */
-	DUK_ASSERT(sizeof(val) == 4);
-	duk_hbuffer_insert_bytes(thr,
-	                         buf,
-	                         DUK_HBUFFER_GET_SIZE(buf),
-	                         (duk_uint8_t *) &val,
-	                         sizeof(duk_uint32_t));
-}
-
-/*
- *  In-buffer "slices"
- *
- *  Slices are identified with an offset+length pair, referring to the current
- *  buffer data.  A caller cannot otherwise reliably refer to existing data,
- *  because the buffer may be reallocated before a data pointer is referenced.
- */
-
-void duk_hbuffer_remove_slice(duk_hthread *thr, duk_hbuffer_dynamic *buf, duk_size_t offset, duk_size_t length) {
-	duk_uint8_t *p;
-	duk_size_t end_offset;
-
-	DUK_UNREF(thr);
-
-	DUK_ASSERT(thr != NULL);
-	DUK_ASSERT(buf != NULL);
-	DUK_ASSERT(DUK_HBUFFER_HAS_DYNAMIC(buf));
-	DUK_ASSERT_DISABLE(offset >= 0);                               /* always true */
-	DUK_ASSERT(offset <= DUK_HBUFFER_GET_SIZE(buf));               /* allow equality */
-	DUK_ASSERT_DISABLE(length >= 0);                               /* always true */
-	DUK_ASSERT(offset + length <= DUK_HBUFFER_GET_SIZE(buf));      /* allow equality */
-
-	if (length == 0) {
-		return;
-	}
-
-	p = (duk_uint8_t *) DUK_HBUFFER_DYNAMIC_GET_CURR_DATA_PTR(buf);
-
-	end_offset = offset + length;
-
-	if (end_offset < DUK_HBUFFER_GET_SIZE(buf)) {
-		/* not strictly from end of buffer; need to shuffle data */
-		DUK_ASSERT(DUK_HBUFFER_GET_SIZE(buf) - end_offset > 0);
-		DUK_MEMMOVE(p + offset,
-		            p + end_offset,
-		            DUK_HBUFFER_GET_SIZE(buf) - end_offset);
-	}
-
-	/* Here we want to zero data even with automatic buffer zeroing
-	 * disabled as we depend on this internally too.
-	 */
-	DUK_ASSERT(length > 0);
-	DUK_MEMZERO(p + DUK_HBUFFER_GET_SIZE(buf) - length,
-	            length);
-
-	buf->size -= length;
-
-	/* Note: no shrink check, intentional */
-}
-
-void duk_hbuffer_insert_slice(duk_hthread *thr, duk_hbuffer_dynamic *buf, duk_size_t dst_offset, duk_size_t src_offset, duk_size_t length) {
-	duk_uint8_t *p;
-	duk_size_t src_end_offset;  /* source end (exclusive) in initial buffer */
-	duk_size_t len;
-
-	DUK_ASSERT(thr != NULL);
-	DUK_ASSERT(buf != NULL);
-	DUK_ASSERT(DUK_HBUFFER_HAS_DYNAMIC(buf));
-	DUK_ASSERT_DISABLE(dst_offset >= 0);                           /* always true */
-	DUK_ASSERT(dst_offset <= DUK_HBUFFER_GET_SIZE(buf));           /* allow equality */
-	DUK_ASSERT_DISABLE(src_offset >= 0);                           /* always true */
-	DUK_ASSERT(src_offset <= DUK_HBUFFER_GET_SIZE(buf));           /* allow equality */
-	DUK_ASSERT_DISABLE(length >= 0);                               /* always true */
-	DUK_ASSERT(src_offset + length <= DUK_HBUFFER_GET_SIZE(buf));  /* allow equality */
-
-	if (length == 0) {
-		return;
-	}
-
-	if (DUK_HBUFFER_DYNAMIC_GET_SPARE_SIZE(buf) < length) {
-		duk_hbuffer_resize(thr,
-		                   buf,
-		                   DUK_HBUFFER_GET_SIZE(buf),
-		                   duk__add_spare(DUK_HBUFFER_GET_SIZE(buf) + length));
-	}
-	DUK_ASSERT(DUK_HBUFFER_DYNAMIC_GET_SPARE_SIZE(buf) >= length);
-
-	p = (duk_uint8_t *) DUK_HBUFFER_DYNAMIC_GET_CURR_DATA_PTR(buf);
-	DUK_ASSERT(p != NULL);  /* must be the case because length > 0, and buffer has been resized if necessary */
-
-	/*
-	 *  src_offset and dst_offset refer to the state of the buffer
-	 *  before any changes are made.  This must be taken into account
-	 *  when moving data around; in particular, the source data may
-	 *  "straddle" the dst_offset, so the insert may need to be handled
-	 *  in two pieces.
-	 */
-
-	src_end_offset = src_offset + length;
+#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
+DUK_INTERNAL duk_uint_t duk_hbufferobject_clamp_bytelength(duk_hbufferobject *h_bufobj, duk_uint_t len) {
+	duk_uint_t buf_size;
+	duk_uint_t buf_avail;
 
-	/* create a hole for the insert */
-	len = DUK_HBUFFER_GET_SIZE(buf) - dst_offset;
-	DUK_MEMMOVE(p + dst_offset + length,
-	            p + dst_offset,
-	            len);  /* zero size is not an issue: pointers are valid */
+	DUK_ASSERT(h_bufobj != NULL);
+	DUK_ASSERT(h_bufobj->buf != NULL);
 
-	if (src_offset < dst_offset) {
-		if (src_end_offset <= dst_offset) {
-			/* entire source is before 'dst_offset' */
-			DUK_MEMCPY(p + dst_offset,
-			           p + src_offset,
-			           length);
-		} else {
-			/* part of the source is before 'dst_offset'; straddles */
-			len = dst_offset - src_offset;
-			DUK_ASSERT(len >= 1 && len < length);
-			DUK_ASSERT(length - len >= 1);
-			DUK_MEMCPY(p + dst_offset,
-			           p + src_offset,
-			           len);
-			DUK_MEMCPY(p + dst_offset + len,
-			           p + src_offset + length + len,  /* take above memmove() into account */
-			           length - len);
-		}
-	} else {
-		/* entire source is after 'dst_offset' */
-		DUK_MEMCPY(p + dst_offset,
-		           p + src_offset + length,  /* take above memmove() into account */
-		           length);
+	buf_size = (duk_uint_t) DUK_HBUFFER_GET_SIZE(h_bufobj->buf);
+	if (h_bufobj->offset > buf_size) {
+		/* Slice starting point is beyond current length. */
+		return 0;
 	}
+	buf_avail = buf_size - h_bufobj->offset;
 
-	buf->size += length;
-}
-
-void duk_hbuffer_append_slice(duk_hthread *thr, duk_hbuffer_dynamic *buf, duk_size_t src_offset, duk_size_t length) {
-	DUK_ASSERT(thr != NULL);
-	DUK_ASSERT(buf != NULL);
-	DUK_ASSERT(DUK_HBUFFER_HAS_DYNAMIC(buf));
-	DUK_ASSERT_DISABLE(src_offset >= 0);                           /* always true */
-	DUK_ASSERT(src_offset <= DUK_HBUFFER_GET_SIZE(buf));           /* allow equality */
-	DUK_ASSERT_DISABLE(length >= 0);                               /* always true */
-	DUK_ASSERT(src_offset + length <= DUK_HBUFFER_GET_SIZE(buf));  /* allow equality */
-
-	duk_hbuffer_insert_slice(thr,
-	                         buf,
-	                         DUK_HBUFFER_GET_SIZE(buf),
-	                         src_offset,
-	                         length);
+	return buf_avail >= len ? len : buf_avail;
 }
+#endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
 #line 1 "duk_heap_alloc.c"
 /*
  *  duk_heap allocation and freeing.
@@ -29167,11 +43228,11 @@ void duk_hbuffer_append_slice(duk_hthread *thr, duk_hbuffer_dynamic *buf, duk_si
  *  been already dealt with.
  */
 
-static void duk__free_hobject_inner(duk_heap *heap, duk_hobject *h) {
+DUK_INTERNAL void duk_free_hobject_inner(duk_heap *heap, duk_hobject *h) {
 	DUK_ASSERT(heap != NULL);
 	DUK_ASSERT(h != NULL);
 
-	DUK_FREE(heap, h->p);
+	DUK_FREE(heap, DUK_HOBJECT_GET_PROPS(heap, h));
 
 	if (DUK_HOBJECT_IS_COMPILEDFUNCTION(h)) {
 		duk_hcompiledfunction *f = (duk_hcompiledfunction *) h;
@@ -29198,18 +43259,34 @@ static void duk__free_hobject_inner(duk_heap *heap, duk_hobject *h) {
 	}
 }
 
-static void duk__free_hbuffer_inner(duk_heap *heap, duk_hbuffer *h) {
+DUK_INTERNAL void duk_free_hbuffer_inner(duk_heap *heap, duk_hbuffer *h) {
 	DUK_ASSERT(heap != NULL);
 	DUK_ASSERT(h != NULL);
 
-	if (DUK_HBUFFER_HAS_DYNAMIC(h)) {
+	if (DUK_HBUFFER_HAS_DYNAMIC(h) && !DUK_HBUFFER_HAS_EXTERNAL(h)) {
 		duk_hbuffer_dynamic *g = (duk_hbuffer_dynamic *) h;
-		DUK_DDD(DUK_DDDPRINT("free dynamic buffer %p", (void *) g->curr_alloc));
-		DUK_FREE(heap, g->curr_alloc);
+		DUK_DDD(DUK_DDDPRINT("free dynamic buffer %p", (void *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(heap, g)));
+		DUK_FREE(heap, DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(heap, g));
 	}
 }
 
-void duk_heap_free_heaphdr_raw(duk_heap *heap, duk_heaphdr *hdr) {
+DUK_INTERNAL void duk_free_hstring_inner(duk_heap *heap, duk_hstring *h) {
+	DUK_ASSERT(heap != NULL);
+	DUK_ASSERT(h != NULL);
+
+	DUK_UNREF(heap);
+	DUK_UNREF(h);
+
+#if defined(DUK_USE_HSTRING_EXTDATA) && defined(DUK_USE_EXTSTR_FREE)
+	if (DUK_HSTRING_HAS_EXTDATA(h)) {
+		DUK_DDD(DUK_DDDPRINT("free extstr: hstring %!O, extdata: %p",
+		                     h, DUK_HSTRING_GET_EXTDATA((duk_hstring_external *) h)));
+		DUK_USE_EXTSTR_FREE(heap->heap_udata, (const void *) DUK_HSTRING_GET_EXTDATA((duk_hstring_external *) h));
+	}
+#endif
+}
+
+DUK_INTERNAL void duk_heap_free_heaphdr_raw(duk_heap *heap, duk_heaphdr *hdr) {
 	DUK_ASSERT(heap);
 	DUK_ASSERT(hdr);
 
@@ -29217,13 +43294,13 @@ void duk_heap_free_heaphdr_raw(duk_heap *heap, duk_heaphdr *hdr) {
 
 	switch ((int) DUK_HEAPHDR_GET_TYPE(hdr)) {
 	case DUK_HTYPE_STRING:
-		/* no inner refs to free */
+		duk_free_hstring_inner(heap, (duk_hstring *) hdr);
 		break;
 	case DUK_HTYPE_OBJECT:
-		duk__free_hobject_inner(heap, (duk_hobject *) hdr);
+		duk_free_hobject_inner(heap, (duk_hobject *) hdr);
 		break;
 	case DUK_HTYPE_BUFFER:
-		duk__free_hbuffer_inner(heap, (duk_hbuffer *) hdr);
+		duk_free_hbuffer_inner(heap, (duk_hbuffer *) hdr);
 		break;
 	default:
 		DUK_UNREACHABLE();
@@ -29245,7 +43322,7 @@ void duk_heap_free_heaphdr_raw(duk_heap *heap, duk_heaphdr *hdr) {
  *  after this call.
  */
 
-static void duk__free_allocated(duk_heap *heap) {
+DUK_LOCAL void duk__free_allocated(duk_heap *heap) {
 	duk_heaphdr *curr;
 	duk_heaphdr *next;
 
@@ -29257,14 +43334,14 @@ static void duk__free_allocated(duk_heap *heap) {
 
 		DUK_DDD(DUK_DDDPRINT("FINALFREE (allocated): %!iO",
 		                     (duk_heaphdr *) curr));
-		next = DUK_HEAPHDR_GET_NEXT(curr);
+		next = DUK_HEAPHDR_GET_NEXT(heap, curr);
 		duk_heap_free_heaphdr_raw(heap, curr);
 		curr = next;
 	}
 }
 
-#ifdef DUK_USE_REFERENCE_COUNTING
-static void duk__free_refzero_list(duk_heap *heap) {
+#if defined(DUK_USE_REFERENCE_COUNTING)
+DUK_LOCAL void duk__free_refzero_list(duk_heap *heap) {
 	duk_heaphdr *curr;
 	duk_heaphdr *next;
 
@@ -29272,15 +43349,15 @@ static void duk__free_refzero_list(duk_heap *heap) {
 	while (curr) {
 		DUK_DDD(DUK_DDDPRINT("FINALFREE (refzero_list): %!iO",
 		                     (duk_heaphdr *) curr));
-		next = DUK_HEAPHDR_GET_NEXT(curr);
+		next = DUK_HEAPHDR_GET_NEXT(heap, curr);
 		duk_heap_free_heaphdr_raw(heap, curr);
 		curr = next;
 	}
 }
 #endif
 
-#ifdef DUK_USE_MARK_AND_SWEEP
-static void duk__free_markandsweep_finalize_list(duk_heap *heap) {
+#if defined(DUK_USE_MARK_AND_SWEEP)
+DUK_LOCAL void duk__free_markandsweep_finalize_list(duk_heap *heap) {
 	duk_heaphdr *curr;
 	duk_heaphdr *next;
 
@@ -29288,112 +43365,171 @@ static void duk__free_markandsweep_finalize_list(duk_heap *heap) {
 	while (curr) {
 		DUK_DDD(DUK_DDDPRINT("FINALFREE (finalize_list): %!iO",
 		                     (duk_heaphdr *) curr));
-		next = DUK_HEAPHDR_GET_NEXT(curr);
+		next = DUK_HEAPHDR_GET_NEXT(heap, curr);
 		duk_heap_free_heaphdr_raw(heap, curr);
 		curr = next;
 	}
 }
 #endif
 
-static void duk__free_stringtable(duk_heap *heap) {
-	duk_uint_fast32_t i;
-
+DUK_LOCAL void duk__free_stringtable(duk_heap *heap) {
 	/* strings are only tracked by stringtable */
-	if (heap->st) {
-		for (i = 0; i < (duk_uint_fast32_t) heap->st_size; i++) {
-			duk_hstring *e = heap->st[i];
-			if (e == DUK_STRTAB_DELETED_MARKER(heap)) {
-				continue;
-			}
-
-			/* strings have no inner allocations so free directly */
-			DUK_DDD(DUK_DDDPRINT("FINALFREE (string): %!iO",
-			                     (duk_heaphdr *) e));
-			DUK_FREE(heap, e);
-#if 0  /* not strictly necessary */
-			heap->st[i] = NULL;
-#endif
-		}
-		DUK_FREE(heap, heap->st);
-#if 0  /* not strictly necessary */
-		heap->st = NULL;
-#endif
-	}
+	duk_heap_free_strtab(heap);
 }
 
-static void duk__free_run_finalizers(duk_heap *heap) {
+DUK_LOCAL void duk__free_run_finalizers(duk_heap *heap) {
+	duk_hthread *thr;
 	duk_heaphdr *curr;
-#ifdef DUK_USE_DEBUG
-	duk_size_t count_obj = 0;
-#endif
+	duk_uint_t round_no;
+	duk_size_t count_all;
+	duk_size_t count_finalized;
+	duk_size_t curr_limit;
 
 	DUK_ASSERT(heap != NULL);
 	DUK_ASSERT(heap->heap_thread != NULL);
-#ifdef DUK_USE_REFERENCE_COUNTING
+#if defined(DUK_USE_REFERENCE_COUNTING)
 	DUK_ASSERT(heap->refzero_list == NULL);  /* refzero not running -> must be empty */
 #endif
-#ifdef DUK_USE_MARK_AND_SWEEP
+#if defined(DUK_USE_MARK_AND_SWEEP)
 	DUK_ASSERT(heap->finalize_list == NULL);  /* mark-and-sweep not running -> must be empty */
 #endif
 
-	/* FIXME: here again finalizer thread is the heap_thread which needs
+	/* XXX: here again finalizer thread is the heap_thread which needs
 	 * to be coordinated with finalizer thread fixes.
 	 */
+	thr = heap->heap_thread;
+	DUK_ASSERT(thr != NULL);
 
-	curr = heap->heap_allocated;
-	while (curr) {
-		if (DUK_HEAPHDR_GET_TYPE(curr) == DUK_HTYPE_OBJECT) {
-			/* Only objects in heap_allocated may have finalizers. */
-			DUK_ASSERT(heap->heap_thread != NULL);
-			DUK_ASSERT(curr != NULL);
-			duk_hobject_run_finalizer(heap->heap_thread, (duk_hobject *) curr);
-#ifdef DUK_USE_DEBUG
-			count_obj++;
-#endif
+	/* Prevent mark-and-sweep for the pending finalizers, also prevents
+	 * refzero handling from moving objects away from the heap_allocated
+	 * list.
+	 */
+	DUK_ASSERT(!DUK_HEAP_HAS_MARKANDSWEEP_RUNNING(heap));
+	DUK_HEAP_SET_MARKANDSWEEP_RUNNING(heap);
+
+	curr_limit = 0;  /* suppress warning, not used */
+	for (round_no = 0; ; round_no++) {
+		curr = heap->heap_allocated;
+		count_all = 0;
+		count_finalized = 0;
+		while (curr) {
+			count_all++;
+			if (DUK_HEAPHDR_GET_TYPE(curr) == DUK_HTYPE_OBJECT) {
+				/* Only objects in heap_allocated may have finalizers.  Check that
+				 * the object itself has a _Finalizer property (own or inherited)
+				 * so that we don't execute finalizers for e.g. Proxy objects.
+				 */
+				DUK_ASSERT(thr != NULL);
+				DUK_ASSERT(curr != NULL);
+
+				if (duk_hobject_hasprop_raw(thr, (duk_hobject *) curr, DUK_HTHREAD_STRING_INT_FINALIZER(thr))) {
+					if (!DUK_HEAPHDR_HAS_FINALIZED((duk_heaphdr *) curr)) {
+						DUK_ASSERT(DUK_HEAP_HAS_FINALIZER_NORESCUE(heap));  /* maps to finalizer 2nd argument */
+						duk_hobject_run_finalizer(thr, (duk_hobject *) curr);
+						count_finalized++;
+					}
+				}
+			}
+			curr = DUK_HEAPHDR_GET_NEXT(heap, curr);
+		}
+
+		/* Each round of finalizer execution may spawn new finalizable objects
+		 * which is normal behavior for some applications.  Allow multiple
+		 * rounds of finalization, but use a shrinking limit based on the
+		 * first round to detect the case where a runaway finalizer creates
+		 * an unbounded amount of new finalizable objects.  Finalizer rescue
+		 * is not supported: the semantics are unclear because most of the
+		 * objects being finalized here are already reachable.  The finalizer
+		 * is given a boolean to indicate that rescue is not possible.
+		 *
+		 * See discussion in: https://github.com/svaarala/duktape/pull/473
+		 */
+
+		if (round_no == 0) {
+			/* Cannot wrap: each object is at least 8 bytes so count is
+			 * at most 1/8 of that.
+			 */
+			curr_limit = count_all * 2;
+		} else {
+			curr_limit = (curr_limit * 3) / 4;   /* Decrease by 25% every round */
+		}
+		DUK_D(DUK_DPRINT("finalizer round %ld complete, %ld objects, tried to execute %ld finalizers, current limit is %ld",
+		                 (long) round_no, (long) count_all, (long) count_finalized, (long) curr_limit));
+
+		if (count_finalized == 0) {
+			DUK_D(DUK_DPRINT("no more finalizable objects, forced finalization finished"));
+			break;
+		}
+		if (count_finalized >= curr_limit) {
+			DUK_D(DUK_DPRINT("finalizer count above limit, potentially runaway finalizer; skip remaining finalizers"));
+			break;
 		}
-		curr = DUK_HEAPHDR_GET_NEXT(curr);
 	}
 
-	/* Note: count includes all objects, not only those with an actual finalizer. */
-#ifdef DUK_USE_DEBUG
-	DUK_D(DUK_DPRINT("checked %ld objects for finalizers before freeing heap", (long) count_obj));
-#endif
+	DUK_ASSERT(DUK_HEAP_HAS_MARKANDSWEEP_RUNNING(heap));
+	DUK_HEAP_CLEAR_MARKANDSWEEP_RUNNING(heap);
 }
 
-void duk_heap_free(duk_heap *heap) {
+DUK_INTERNAL void duk_heap_free(duk_heap *heap) {
 	DUK_D(DUK_DPRINT("free heap: %p", (void *) heap));
 
+#if defined(DUK_USE_DEBUG)
+	duk_heap_dump_strtab(heap);
+#endif
+
+#if defined(DUK_USE_DEBUGGER_SUPPORT)
+	/* Detach a debugger if attached (can be called multiple times)
+	 * safely.
+	 */
+	/* XXX: Add a flag to reject an attempt to re-attach?  Otherwise
+	 * the detached callback may immediately reattach.
+	 */
+	duk_debug_do_detach(heap);
+#endif
+
 	/* Execute finalizers before freeing the heap, even for reachable
 	 * objects, and regardless of whether or not mark-and-sweep is
 	 * enabled.  This gives finalizers the chance to free any native
 	 * resources like file handles, allocations made outside Duktape,
-	 * etc.
+	 * etc.  This is quite tricky to get right, so that all finalizer
+	 * guarantees are honored.
 	 *
-	 * FIXME: this perhaps requires an execution time limit.
+	 * XXX: this perhaps requires an execution time limit.
 	 */
 	DUK_D(DUK_DPRINT("execute finalizers before freeing heap"));
-#ifdef DUK_USE_MARK_AND_SWEEP
-	/* run mark-and-sweep a few times just in case (unreachable
-	 * object finalizers run already here)
-	 */
+#if defined(DUK_USE_MARK_AND_SWEEP)
+	/* Run mark-and-sweep a few times just in case (unreachable object
+	 * finalizers run already here).  The last round must rescue objects
+	 * from the previous round without running any more finalizers.  This
+	 * ensures rescued objects get their FINALIZED flag cleared so that
+	 * their finalizer is called once more in forced finalization to
+	 * satisfy finalizer guarantees.  However, we don't want to run any
+	 * more finalizer because that'd required one more loop, and so on.
+	 */
+	DUK_D(DUK_DPRINT("forced gc #1 in heap destruction"));
 	duk_heap_mark_and_sweep(heap, 0);
+	DUK_D(DUK_DPRINT("forced gc #2 in heap destruction"));
 	duk_heap_mark_and_sweep(heap, 0);
+	DUK_D(DUK_DPRINT("forced gc #3 in heap destruction (don't run finalizers)"));
+	duk_heap_mark_and_sweep(heap, DUK_MS_FLAG_SKIP_FINALIZERS);  /* skip finalizers; queue finalizable objects to heap_allocated */
 #endif
+
+	DUK_HEAP_SET_FINALIZER_NORESCUE(heap);  /* rescue no longer supported */
 	duk__free_run_finalizers(heap);
 
-	/* Note: heap->heap_thread, heap->curr_thread, heap->heap_object,
-	 * and heap->log_buffer are on the heap allocated list.
+	/* Note: heap->heap_thread, heap->curr_thread, and heap->heap_object
+	 * are on the heap allocated list.
 	 */
 
 	DUK_D(DUK_DPRINT("freeing heap objects of heap: %p", (void *) heap));
 	duk__free_allocated(heap);
 
-#ifdef DUK_USE_REFERENCE_COUNTING
+#if defined(DUK_USE_REFERENCE_COUNTING)
 	DUK_D(DUK_DPRINT("freeing refzero list of heap: %p", (void *) heap));
 	duk__free_refzero_list(heap);
 #endif
 
-#ifdef DUK_USE_MARK_AND_SWEEP
+#if defined(DUK_USE_MARK_AND_SWEEP)
 	DUK_D(DUK_DPRINT("freeing mark-and-sweep finalize list of heap: %p", (void *) heap));
 	duk__free_markandsweep_finalize_list(heap);
 #endif
@@ -29402,7 +43538,7 @@ void duk_heap_free(duk_heap *heap) {
 	duk__free_stringtable(heap);
 
 	DUK_D(DUK_DPRINT("freeing heap structure: %p", (void *) heap));
-	heap->free_func(heap->alloc_udata, heap);
+	heap->free_func(heap->heap_udata, heap);
 }
 
 /*
@@ -29412,7 +43548,7 @@ void duk_heap_free(duk_heap *heap) {
  */
 
 /* intern built-in strings from precooked data (genstrings.py) */
-static int duk__init_heap_strings(duk_heap *heap) {
+DUK_LOCAL duk_bool_t duk__init_heap_strings(duk_heap *heap) {
 	duk_bitdecoder_ctx bd_ctx;
 	duk_bitdecoder_ctx *bd = &bd_ctx;  /* convenience */
 	duk_small_uint_t i, j;
@@ -29429,7 +43565,7 @@ static int duk__init_heap_strings(duk_heap *heap) {
 		duk_small_uint_t t;
 
 		len = duk_bd_decode(bd, 5);
-		mode = 32;		/* 0 = uppercase, 32 = lowercase (= 'a' - 'A') */
+		mode = 32;  /* 0 = uppercase, 32 = lowercase (= 'a' - 'A') */
 		for (j = 0; j < len; j++) {
 			t = duk_bd_decode(bd, 5);
 			if (t < DUK__BITPACK_LETTER_LIMIT) {
@@ -29458,17 +43594,21 @@ static int duk__init_heap_strings(duk_heap *heap) {
 			tmp[j] = (duk_uint8_t) t;
 		}
 
+		/* No need to length check string: it will never exceed even
+		 * the 16-bit length maximum.
+		 */
+		DUK_ASSERT(len <= 0xffffUL);
 		DUK_DDD(DUK_DDDPRINT("intern built-in string %ld", (long) i));
 		h = duk_heap_string_intern(heap, tmp, len);
 		if (!h) {
 			goto error;
 		}
 
-		/* special flags */
-
-		if (len > 0 && tmp[0] == (duk_uint8_t) 0xff) {
-			DUK_HSTRING_SET_INTERNAL(h);
-		}
+		/* Special flags checks.  Since these strings are always
+		 * reachable and a string cannot appear twice in the string
+		 * table, there's no need to check/set these flags elsewhere.
+		 * The 'internal' flag is set by string intern code.
+		 */
 		if (i == DUK_STRIDX_EVAL || i == DUK_STRIDX_LC_ARGUMENTS) {
 			DUK_HSTRING_SET_EVAL_OR_ARGUMENTS(h);
 		}
@@ -29486,7 +43626,11 @@ static int duk__init_heap_strings(duk_heap *heap) {
 		 */
 		DUK_HSTRING_INCREF(_never_referenced_, h);
 
+#if defined(DUK_USE_HEAPPTR16)
+		heap->strs16[i] = DUK_USE_HEAPPTR_ENC16(heap->heap_udata, (void *) h);
+#else
 		heap->strs[i] = h;
+#endif
 	}
 
 	return 1;
@@ -29495,9 +43639,9 @@ static int duk__init_heap_strings(duk_heap *heap) {
 	return 0;
 }
 
-static int duk__init_heap_thread(duk_heap *heap) {
+DUK_LOCAL duk_bool_t duk__init_heap_thread(duk_heap *heap) {
 	duk_hthread *thr;
-	
+
 	DUK_DD(DUK_DDPRINT("heap init: alloc heap thread"));
 	thr = duk_hthread_alloc(heap,
 	                        DUK_HOBJECT_FLAG_EXTENSIBLE |
@@ -29508,7 +43652,11 @@ static int duk__init_heap_thread(duk_heap *heap) {
 		return 0;
 	}
 	thr->state = DUK_HTHREAD_STATE_INACTIVE;
+#if defined(DUK_USE_HEAPPTR16)
+	thr->strs16 = heap->strs16;
+#else
 	thr->strs = heap->strs;
+#endif
 
 	heap->heap_thread = thr;
 	DUK_HTHREAD_INCREF(thr, thr);  /* Note: first argument not really used */
@@ -29519,7 +43667,7 @@ static int duk__init_heap_thread(duk_heap *heap) {
 		return 0;
 	}
 
-	/* FIXME: this may now fail, and is not handled correctly */
+	/* XXX: this may now fail, and is not handled correctly */
 	duk_hthread_create_builtin_objects(thr);
 
 	/* default prototype (Note: 'thr' must be reachable) */
@@ -29528,7 +43676,7 @@ static int duk__init_heap_thread(duk_heap *heap) {
 	return 1;
 }
 
-#ifdef DUK_USE_DEBUG
+#if defined(DUK_USE_DEBUG)
 #define DUK__DUMPSZ(t)  do { \
 		DUK_D(DUK_DPRINT("" #t "=%ld", (long) sizeof(t))); \
 	} while (0)
@@ -29542,20 +43690,20 @@ static int duk__init_heap_thread(duk_heap *heap) {
 		DUK_D(DUK_DPRINT(t "=[%ld,%ld]=[%lf,%lf]", \
 		                 (long) (a), (long) (b), \
 		                 (double) (a), (double) (b))); \
-	} while(0)
+	} while (0)
 #define DUK__DUMPLM_UNSIGNED_RAW(t,a,b)  do { \
 		DUK_D(DUK_DPRINT(t "=[%lu,%lu]=[%lf,%lf]", \
 		                 (unsigned long) (a), (unsigned long) (b), \
 		                 (double) (a), (double) (b))); \
-	} while(0)
+	} while (0)
 #define DUK__DUMPLM_SIGNED(t)  do { \
 		DUK__DUMPLM_SIGNED_RAW("DUK_" #t "_{MIN,MAX}", DUK_##t##_MIN, DUK_##t##_MAX); \
-	} while(0)
+	} while (0)
 #define DUK__DUMPLM_UNSIGNED(t)  do { \
 		DUK__DUMPLM_UNSIGNED_RAW("DUK_" #t "_{MIN,MAX}", DUK_##t##_MIN, DUK_##t##_MAX); \
-	} while(0)
+	} while (0)
 
-static void duk__dump_type_sizes(void) {
+DUK_LOCAL void duk__dump_type_sizes(void) {
 	DUK_D(DUK_DPRINT("sizeof()"));
 
 	/* basic platform types */
@@ -29624,10 +43772,13 @@ static void duk__dump_type_sizes(void) {
 	DUK__DUMPSZ(duk_tval);
 
 	/* structs from duk_forwdecl.h */
+#if !defined(DUK_USE_CPP_EXCEPTIONS)
 	DUK__DUMPSZ(duk_jmpbuf);
+#endif
 	DUK__DUMPSZ(duk_heaphdr);
 	DUK__DUMPSZ(duk_heaphdr_string);
 	DUK__DUMPSZ(duk_hstring);
+	DUK__DUMPSZ(duk_hstring_external);
 	DUK__DUMPSZ(duk_hobject);
 	DUK__DUMPSZ(duk_hcompiledfunction);
 	DUK__DUMPSZ(duk_hnativefunction);
@@ -29635,10 +43786,14 @@ static void duk__dump_type_sizes(void) {
 	DUK__DUMPSZ(duk_hbuffer);
 	DUK__DUMPSZ(duk_hbuffer_fixed);
 	DUK__DUMPSZ(duk_hbuffer_dynamic);
+	DUK__DUMPSZ(duk_hbuffer_external);
 	DUK__DUMPSZ(duk_propaccessor);
 	DUK__DUMPSZ(duk_propvalue);
 	DUK__DUMPSZ(duk_propdesc);
 	DUK__DUMPSZ(duk_heap);
+#if defined(DUK_USE_STRTAB_CHAIN)
+	DUK__DUMPSZ(duk_strtab_entry);
+#endif
 	DUK__DUMPSZ(duk_activation);
 	DUK__DUMPSZ(duk_catcher);
 	DUK__DUMPSZ(duk_strcache);
@@ -29656,7 +43811,7 @@ static void duk__dump_type_sizes(void) {
 	DUK__DUMPSZ(duk_re_matcher_ctx);
 	DUK__DUMPSZ(duk_re_compiler_ctx);
 }
-static void duk__dump_type_limits(void) {
+DUK_LOCAL void duk__dump_type_limits(void) {
 	DUK_D(DUK_DPRINT("limits"));
 
 	/* basic types */
@@ -29706,31 +43861,81 @@ static void duk__dump_type_limits(void) {
 #undef DUK__DUMPLM_UNSIGNED_RAW
 #undef DUK__DUMPLM_SIGNED
 #undef DUK__DUMPLM_UNSIGNED
+
+DUK_LOCAL void duk__dump_misc_options(void) {
+	DUK_D(DUK_DPRINT("DUK_VERSION: %ld", (long) DUK_VERSION));
+	DUK_D(DUK_DPRINT("DUK_GIT_DESCRIBE: %s", DUK_GIT_DESCRIBE));
+	DUK_D(DUK_DPRINT("OS string: %s", DUK_USE_OS_STRING));
+	DUK_D(DUK_DPRINT("architecture string: %s", DUK_USE_ARCH_STRING));
+	DUK_D(DUK_DPRINT("compiler string: %s", DUK_USE_COMPILER_STRING));
+#if defined(DUK_USE_PACKED_TVAL)
+	DUK_D(DUK_DPRINT("DUK_USE_PACKED_TVAL: yes"));
+#else
+	DUK_D(DUK_DPRINT("DUK_USE_PACKED_TVAL: no"));
+#endif
+#if defined(DUK_USE_VARIADIC_MACROS)
+	DUK_D(DUK_DPRINT("DUK_USE_VARIADIC_MACROS: yes"));
+#else
+	DUK_D(DUK_DPRINT("DUK_USE_VARIADIC_MACROS: no"));
+#endif
+#if defined(DUK_USE_INTEGER_LE)
+	DUK_D(DUK_DPRINT("integer endianness: little"));
+#elif defined(DUK_USE_INTEGER_ME)
+	DUK_D(DUK_DPRINT("integer endianness: mixed"));
+#elif defined(DUK_USE_INTEGER_BE)
+	DUK_D(DUK_DPRINT("integer endianness: big"));
+#else
+	DUK_D(DUK_DPRINT("integer endianness: ???"));
+#endif
+#if defined(DUK_USE_DOUBLE_LE)
+	DUK_D(DUK_DPRINT("IEEE double endianness: little"));
+#elif defined(DUK_USE_DOUBLE_ME)
+	DUK_D(DUK_DPRINT("IEEE double endianness: mixed"));
+#elif defined(DUK_USE_DOUBLE_BE)
+	DUK_D(DUK_DPRINT("IEEE double endianness: big"));
+#else
+	DUK_D(DUK_DPRINT("IEEE double endianness: ???"));
+#endif
+}
 #endif  /* DUK_USE_DEBUG */
 
+DUK_INTERNAL
 duk_heap *duk_heap_alloc(duk_alloc_function alloc_func,
                          duk_realloc_function realloc_func,
                          duk_free_function free_func,
-                         void *alloc_udata,
+                         void *heap_udata,
                          duk_fatal_function fatal_func) {
 	duk_heap *res = NULL;
 
+	/* Silence a few global unused warnings here. */
+	DUK_UNREF(duk_str_unsupported);
+
 	DUK_D(DUK_DPRINT("allocate heap"));
 
-	/* Debug dump type sizes */
-#ifdef DUK_USE_DEBUG
+	/*
+	 *  Debug dump type sizes
+	 */
+
+#if defined(DUK_USE_DEBUG)
+	duk__dump_misc_options();
 	duk__dump_type_sizes();
 	duk__dump_type_limits();
 #endif
 
-	/* If selftests enabled, run them as early as possible. */
-#ifdef DUK_USE_SELF_TESTS
+	/*
+	 *  If selftests enabled, run them as early as possible
+	 */
+#if defined(DUK_USE_SELF_TESTS)
 	DUK_D(DUK_DPRINT("running self tests"));
 	duk_selftest_run_tests();
 	DUK_D(DUK_DPRINT("self tests passed"));
 #endif
 
-#ifdef DUK_USE_COMPUTED_NAN
+	/*
+	 *  Computed values (e.g. INFINITY)
+	 */
+
+#if defined(DUK_USE_COMPUTED_NAN)
 	do {
 		/* Workaround for some exotic platforms where NAN is missing
 		 * and the expression (0.0 / 0.0) does NOT result in a NaN.
@@ -29746,7 +43951,7 @@ duk_heap *duk_heap_alloc(duk_alloc_function alloc_func,
 	} while (0);
 #endif
 
-#ifdef DUK_USE_COMPUTED_INFINITY
+#if defined(DUK_USE_COMPUTED_INFINITY)
 	do {
 		/* Similar workaround for INFINITY. */
 		volatile double dbl1 = 1.0;
@@ -29755,52 +43960,85 @@ duk_heap *duk_heap_alloc(duk_alloc_function alloc_func,
 	} while (0);
 #endif
 
-	/* use a raw call, all macros expect the heap to be initialized */
-	res = (duk_heap *) alloc_func(alloc_udata, sizeof(duk_heap));
+	/*
+	 *  Allocate heap struct
+	 *
+	 *  Use a raw call, all macros expect the heap to be initialized
+	 */
+
+	res = (duk_heap *) alloc_func(heap_udata, sizeof(duk_heap));
 	if (!res) {
 		goto error;
 	}
 
-	/* zero everything */
+	/*
+	 *  Zero the struct, and start initializing roughly in order
+	 */
+
 	DUK_MEMZERO(res, sizeof(*res));
 
 	/* explicit NULL inits */
-#ifdef DUK_USE_EXPLICIT_NULL_INIT
-	res->alloc_udata = NULL;
+#if defined(DUK_USE_EXPLICIT_NULL_INIT)
+	res->heap_udata = NULL;
 	res->heap_allocated = NULL;
-#ifdef DUK_USE_REFERENCE_COUNTING
+#if defined(DUK_USE_REFERENCE_COUNTING)
 	res->refzero_list = NULL;
 	res->refzero_list_tail = NULL;
 #endif
-#ifdef DUK_USE_MARK_AND_SWEEP
+#if defined(DUK_USE_MARK_AND_SWEEP)
 	res->finalize_list = NULL;
 #endif
 	res->heap_thread = NULL;
 	res->curr_thread = NULL;
 	res->heap_object = NULL;
-	res->log_buffer = NULL;
-	res->st = NULL;
+#if defined(DUK_USE_STRTAB_CHAIN)
+	/* nothing to NULL */
+#elif defined(DUK_USE_STRTAB_PROBE)
+#if defined(DUK_USE_HEAPPTR16)
+	res->strtable16 = (duk_uint16_t *) NULL;
+#else
+	res->strtable = (duk_hstring **) NULL;
+#endif
+#endif
+#if defined(DUK_USE_HEAPPTR16)
+/* res->strs16[] is zeroed and zero decodes to NULL, so no NULL inits. */
+#else
 	{
 		duk_small_uint_t i;
 	        for (i = 0; i < DUK_HEAP_NUM_STRINGS; i++) {
-        	        res->strs[i] = NULL;
+			res->strs[i] = NULL;
 	        }
 	}
 #endif
+#if defined(DUK_USE_DEBUGGER_SUPPORT)
+	res->dbg_read_cb = NULL;
+	res->dbg_write_cb = NULL;
+	res->dbg_peek_cb = NULL;
+	res->dbg_read_flush_cb = NULL;
+	res->dbg_write_flush_cb = NULL;
+	res->dbg_udata = NULL;
+	res->dbg_step_thread = NULL;
+#endif
+#endif  /* DUK_USE_EXPLICIT_NULL_INIT */
 
-	/* initialize the structure, roughly in order */
 	res->alloc_func = alloc_func;
 	res->realloc_func = realloc_func;
 	res->free_func = free_func;
-	res->alloc_udata = alloc_udata;
+	res->heap_udata = heap_udata;
 	res->fatal_func = fatal_func;
 
+#if defined(DUK_USE_HEAPPTR16)
+	/* XXX: zero assumption */
+	res->heapptr_null16 = DUK_USE_HEAPPTR_ENC16(res->heap_udata, (void *) NULL);
+	res->heapptr_deleted16 = DUK_USE_HEAPPTR_ENC16(res->heap_udata, (void *) DUK_STRTAB_DELETED_MARKER(res));
+#endif
+
 	/* res->mark_and_sweep_trigger_counter == 0 -> now causes immediate GC; which is OK */
 
 	res->call_recursion_depth = 0;
-	res->call_recursion_limit = DUK_HEAP_DEFAULT_CALL_RECURSION_LIMIT;
+	res->call_recursion_limit = DUK_USE_NATIVE_CALL_RECLIMIT;
 
-	/* FIXME: use the pointer as a seed for now: mix in time at least */
+	/* XXX: use the pointer as a seed for now: mix in time at least */
 
 	/* The casts through duk_intr_pt is to avoid the following GCC warning:
 	 *
@@ -29810,44 +44048,85 @@ duk_heap *duk_heap_alloc(duk_alloc_function alloc_func,
 	 */
 	res->hash_seed = (duk_uint32_t) (duk_intptr_t) res;
 	res->rnd_state = (duk_uint32_t) (duk_intptr_t) res;
-
-#ifdef DUK_USE_INTERRUPT_COUNTER
-	/* zero value causes an interrupt before executing first instruction */
-	DUK_ASSERT(res->interrupt_counter == 0);
-	DUK_ASSERT(res->interrupt_init == 0);
+#if !defined(DUK_USE_STRHASH_DENSE)
+	res->hash_seed ^= 5381;  /* Bernstein hash init value is normally 5381; XOR it in in case pointer low bits are 0 */
 #endif
 
-#ifdef DUK_USE_EXPLICIT_NULL_INIT
+#if defined(DUK_USE_EXPLICIT_NULL_INIT)
 	res->lj.jmpbuf_ptr = NULL;
 #endif
 	DUK_ASSERT(res->lj.type == DUK_LJ_TYPE_UNKNOWN);  /* zero */
 
-	DUK_TVAL_SET_UNDEFINED_UNUSED(&res->lj.value1);
-	DUK_TVAL_SET_UNDEFINED_UNUSED(&res->lj.value2);
+	DUK_TVAL_SET_UNDEFINED(&res->lj.value1);
+	DUK_TVAL_SET_UNDEFINED(&res->lj.value2);
 
 #if (DUK_STRTAB_INITIAL_SIZE < DUK_UTIL_MIN_HASH_PRIME)
 #error initial heap stringtable size is defined incorrectly
 #endif
 
-	res->st = (duk_hstring **) alloc_func(alloc_udata, sizeof(duk_hstring *) * DUK_STRTAB_INITIAL_SIZE);
-	if (!res->st) {
+	/*
+	 *  Init stringtable: fixed variant
+	 */
+
+#if defined(DUK_USE_STRTAB_CHAIN)
+	DUK_MEMZERO(res->strtable, sizeof(duk_strtab_entry) * DUK_STRTAB_CHAIN_SIZE);
+#if defined(DUK_USE_EXPLICIT_NULL_INIT)
+	{
+		duk_small_uint_t i;
+	        for (i = 0; i < DUK_STRTAB_CHAIN_SIZE; i++) {
+#if defined(DUK_USE_HEAPPTR16)
+			res->strtable[i].u.str16 = res->heapptr_null16;
+#else
+			res->strtable[i].u.str = NULL;
+#endif
+	        }
+	}
+#endif  /* DUK_USE_EXPLICIT_NULL_INIT */
+#endif  /* DUK_USE_STRTAB_CHAIN */
+
+	/*
+	 *  Init stringtable: probe variant
+	 */
+
+#if defined(DUK_USE_STRTAB_PROBE)
+#if defined(DUK_USE_HEAPPTR16)
+	res->strtable16 = (duk_uint16_t *) alloc_func(heap_udata, sizeof(duk_uint16_t) * DUK_STRTAB_INITIAL_SIZE);
+	if (!res->strtable16) {
+		goto error;
+	}
+#else  /* DUK_USE_HEAPPTR16 */
+	res->strtable = (duk_hstring **) alloc_func(heap_udata, sizeof(duk_hstring *) * DUK_STRTAB_INITIAL_SIZE);
+	if (!res->strtable) {
 		goto error;
 	}
+#endif  /* DUK_USE_HEAPPTR16 */
 	res->st_size = DUK_STRTAB_INITIAL_SIZE;
-#ifdef DUK_USE_EXPLICIT_NULL_INIT
+#if defined(DUK_USE_EXPLICIT_NULL_INIT)
 	{
 		duk_small_uint_t i;
 		DUK_ASSERT(res->st_size == DUK_STRTAB_INITIAL_SIZE);
 	        for (i = 0; i < DUK_STRTAB_INITIAL_SIZE; i++) {
-        	        res->st[i] = NULL;
+#if defined(DUK_USE_HEAPPTR16)
+			res->strtable16[i] = res->heapptr_null16;
+#else
+			res->strtable[i] = NULL;
+#endif
 	        }
 	}
+#else  /* DUK_USE_EXPLICIT_NULL_INIT */
+#if defined(DUK_USE_HEAPPTR16)
+	DUK_MEMZERO(res->strtable16, sizeof(duk_uint16_t) * DUK_STRTAB_INITIAL_SIZE);
 #else
-	DUK_MEMZERO(res->st, sizeof(duk_hstring *) * DUK_STRTAB_INITIAL_SIZE);
+	DUK_MEMZERO(res->strtable, sizeof(duk_hstring *) * DUK_STRTAB_INITIAL_SIZE);
 #endif
+#endif  /* DUK_USE_EXPLICIT_NULL_INIT */
+#endif  /* DUK_USE_STRTAB_PROBE */
 
-	/* strcache init */
-#ifdef DUK_USE_EXPLICIT_NULL_INIT
+	/*
+	 *  Init stringcache
+	 */
+
+#if defined(DUK_USE_EXPLICIT_NULL_INIT)
 	{
 		duk_small_uint_t i;
 		for (i = 0; i < DUK_HEAP_STRCACHE_SIZE; i++) {
@@ -29856,25 +44135,34 @@ duk_heap *duk_heap_alloc(duk_alloc_function alloc_func,
 	}
 #endif
 
-	/* FIXME: error handling is incomplete.  It would be cleanest if
+	/* XXX: error handling is incomplete.  It would be cleanest if
 	 * there was a setjmp catchpoint, so that all init code could
 	 * freely throw errors.  If that were the case, the return code
 	 * passing here could be removed.
 	 */
 
-	/* built-in strings */
+	/*
+	 *  Init built-in strings
+	 */
+
 	DUK_DD(DUK_DDPRINT("HEAP: INIT STRINGS"));
 	if (!duk__init_heap_strings(res)) {
 		goto error;
 	}
 
-	/* heap thread */
+	/*
+	 *  Init the heap thread
+	 */
+
 	DUK_DD(DUK_DDPRINT("HEAP: INIT HEAP THREAD"));
 	if (!duk__init_heap_thread(res)) {
 		goto error;
 	}
 
-	/* heap object */
+	/*
+	 *  Init the heap object
+	 */
+
 	DUK_DD(DUK_DDPRINT("HEAP: INIT HEAP OBJECT"));
 	DUK_ASSERT(res->heap_thread != NULL);
 	res->heap_object = duk_hobject_alloc(res, DUK_HOBJECT_FLAG_EXTENSIBLE |
@@ -29884,15 +44172,9 @@ duk_heap *duk_heap_alloc(duk_alloc_function alloc_func,
 	}
 	DUK_HOBJECT_INCREF(res->heap_thread, res->heap_object);
 
-	/* log buffer */
-	DUK_DD(DUK_DDPRINT("HEAP: INIT LOG BUFFER"));
-	res->log_buffer = (duk_hbuffer_dynamic *) duk_hbuffer_alloc(res,
-	                                                            DUK_BI_LOGGER_SHORT_MSG_LIMIT,
-	                                                            1 /*dynamic*/);
-	if (!res->log_buffer) {
-		goto error;
-	}
-	DUK_HBUFFER_INCREF(res->heap_thread, res->log_buffer);
+	/*
+	 *  All done
+	 */
 
 	DUK_D(DUK_DPRINT("allocated heap: %p", (void *) res));
 	return res;
@@ -29914,44 +44196,53 @@ duk_heap *duk_heap_alloc(duk_alloc_function alloc_func,
 #line 1 "duk_heap_hashstring.c"
 /*
  *  String hash computation (interning).
+ *
+ *  String hashing is performance critical because a string hash is computed
+ *  for all new strings which are candidates to be added to the string table.
+ *  However, strings actually added to the string table go through a codepoint
+ *  length calculation which dominates performance because it goes through
+ *  every byte of the input string (but only for strings added).
+ *
+ *  The string hash algorithm should be fast, but on the other hand provide
+ *  good enough hashes to ensure both string table and object property table
+ *  hash tables work reasonably well (i.e., there aren't too many collisions
+ *  with real world inputs).  Unless the hash is cryptographic, it's always
+ *  possible to craft inputs with maximal hash collisions.
  */
 
 /* include removed: duk_internal.h */
 
-/* constants for duk_hashstring() */
+#if defined(DUK_USE_STRHASH_DENSE)
 #define DUK__STRHASH_SHORTSTRING   4096L
 #define DUK__STRHASH_MEDIUMSTRING  (256L * 1024L)
 #define DUK__STRHASH_BLOCKSIZE     256L
 
-duk_uint32_t duk_heap_hashstring(duk_heap *heap, duk_uint8_t *str, duk_size_t len) {
-	/*
-	 *  Sampling long strings by byte skipping (like Lua does) is potentially
-	 *  a cache problem.  Here we do 'block skipping' instead for long strings:
-	 *  hash an initial part, and then sample the rest of the string with
-	 *  reasonably sized chunks.
-	 *
-	 *  Skip should depend on length and bound the total time to roughly
-	 *  logarithmic.
+DUK_INTERNAL duk_uint32_t duk_heap_hashstring(duk_heap *heap, const duk_uint8_t *str, duk_size_t len) {
+	duk_uint32_t hash;
+
+	/* Use Murmurhash2 directly for short strings, and use "block skipping"
+	 * for long strings: hash an initial part and then sample the rest of
+	 * the string with reasonably sized chunks.  An initial offset for the
+	 * sampling is computed based on a hash of the initial part of the string;
+	 * this is done to (usually) avoid the case where all long strings have
+	 * certain offset ranges which are never sampled.
 	 *
-	 *  With current values:
+	 * Skip should depend on length and bound the total time to roughly
+	 * logarithmic.  With current values:
 	 *
-	 *    1M string => 256 * 241 = 61696 bytes (0.06M) of hashing
-	 *    1G string => 256 * 16321 = 4178176 bytes (3.98M) of hashing
+	 *   1M string => 256 * 241 = 61696 bytes (0.06M) of hashing
+	 *   1G string => 256 * 16321 = 4178176 bytes (3.98M) of hashing
 	 *
-	 *  After an initial part has been hashed, an offset is applied before
-	 *  starting the sampling.  The initial offset is computed from the
-	 *  hash of the initial part of the string.  The idea is to avoid the
-	 *  case that all long strings have certain offset ranges that are never
-	 *  sampled.
+	 * XXX: It would be better to compute the skip offset more "smoothly"
+	 * instead of having a few boundary values.
 	 */
-	
+
 	/* note: mixing len into seed improves hashing when skipping */
-	duk_uint32_t str_seed = heap->hash_seed ^ len;
+	duk_uint32_t str_seed = heap->hash_seed ^ ((duk_uint32_t) len);
 
 	if (len <= DUK__STRHASH_SHORTSTRING) {
-		return duk_util_hashbytes(str, len, str_seed);
+		hash = duk_util_hashbytes(str, len, str_seed);
 	} else {
-		duk_uint32_t hash;
 		duk_size_t off;
 		duk_size_t skip;
 
@@ -29971,10 +44262,54 @@ duk_uint32_t duk_heap_hashstring(duk_heap *heap, duk_uint8_t *str, duk_size_t le
 			hash ^= duk_util_hashbytes(str + off, now, str_seed);
 			off += skip;
 		}
+	}
+
+#if defined(DUK_USE_STRHASH16)
+	/* Truncate to 16 bits here, so that a computed hash can be compared
+	 * against a hash stored in a 16-bit field.
+	 */
+	hash &= 0x0000ffffUL;
+#endif
+	return hash;
+}
 
-		return hash;
+#undef DUK__STRHASH_SHORTSTRING
+#undef DUK__STRHASH_MEDIUMSTRING
+#undef DUK__STRHASH_BLOCKSIZE
+#else  /* DUK_USE_STRHASH_DENSE */
+DUK_INTERNAL duk_uint32_t duk_heap_hashstring(duk_heap *heap, const duk_uint8_t *str, duk_size_t len) {
+	duk_uint32_t hash;
+	duk_size_t step;
+	duk_size_t off;
+
+	/* Slightly modified "Bernstein hash" from:
+	 *
+	 *     http://eternallyconfuzzled.com/tuts/algorithms/jsw_tut_hashing.aspx
+	 *
+	 * Modifications: string skipping and reverse direction similar to
+	 * Lua 5.1.5, and different hash initializer.
+	 *
+	 * The reverse direction ensures last byte it always included in the
+	 * hash which is a good default as changing parts of the string are
+	 * more often in the suffix than in the prefix.
+	 */
+
+	hash = heap->hash_seed ^ ((duk_uint32_t) len);  /* Bernstein hash init value is normally 5381 */
+	step = (len >> DUK_USE_STRHASH_SKIP_SHIFT) + 1;
+	for (off = len; off >= step; off -= step) {
+		DUK_ASSERT(off >= 1);  /* off >= step, and step >= 1 */
+		hash = (hash * 33) + str[off - 1];
 	}
+
+#if defined(DUK_USE_STRHASH16)
+	/* Truncate to 16 bits here, so that a computed hash can be compared
+	 * against a hash stored in a 16-bit field.
+	 */
+	hash &= 0x0000ffffUL;
+#endif
+	return hash;
 }
+#endif  /* DUK_USE_STRHASH_DENSE */
 #line 1 "duk_heap_markandsweep.c"
 /*
  *  Mark-and-sweep garbage collection.
@@ -29984,8 +44319,8 @@ duk_uint32_t duk_heap_hashstring(duk_heap *heap, duk_uint8_t *str, duk_size_t le
 
 #ifdef DUK_USE_MARK_AND_SWEEP
 
-static void duk__mark_heaphdr(duk_heap *heap, duk_heaphdr *h);
-static void duk__mark_tval(duk_heap *heap, duk_tval *tv);
+DUK_LOCAL_DECL void duk__mark_heaphdr(duk_heap *heap, duk_heaphdr *h);
+DUK_LOCAL_DECL void duk__mark_tval(duk_heap *heap, duk_tval *tv);
 
 /*
  *  Misc
@@ -29993,9 +44328,9 @@ static void duk__mark_tval(duk_heap *heap, duk_tval *tv);
 
 /* Select a thread for mark-and-sweep use.
  *
- * FIXME: This needs to change later.
+ * XXX: This needs to change later.
  */
-static duk_hthread *duk__get_temp_hthread(duk_heap *heap) {
+DUK_LOCAL duk_hthread *duk__get_temp_hthread(duk_heap *heap) {
 	if (heap->curr_thread) {
 		return heap->curr_thread;
 	}
@@ -30006,7 +44341,7 @@ static duk_hthread *duk__get_temp_hthread(duk_heap *heap) {
  *  Marking functions for heap types: mark children recursively
  */
 
-static void duk__mark_hstring(duk_heap *heap, duk_hstring *h) {
+DUK_LOCAL void duk__mark_hstring(duk_heap *heap, duk_hstring *h) {
 	DUK_UNREF(heap);
 	DUK_UNREF(h);
 
@@ -30016,7 +44351,7 @@ static void duk__mark_hstring(duk_heap *heap, duk_hstring *h) {
 	/* nothing to process */
 }
 
-static void duk__mark_hobject(duk_heap *heap, duk_hobject *h) {
+DUK_LOCAL void duk__mark_hobject(duk_heap *heap, duk_hobject *h) {
 	duk_uint_fast32_t i;
 
 	DUK_DDD(DUK_DDDPRINT("duk__mark_hobject: %p", (void *) h));
@@ -30025,69 +44360,72 @@ static void duk__mark_hobject(duk_heap *heap, duk_hobject *h) {
 
 	/* XXX: use advancing pointers instead of index macros -> faster and smaller? */
 
-	for (i = 0; i < (duk_uint_fast32_t) h->e_used; i++) {
-		duk_hstring *key = DUK_HOBJECT_E_GET_KEY(h, i);
+	for (i = 0; i < (duk_uint_fast32_t) DUK_HOBJECT_GET_ENEXT(h); i++) {
+		duk_hstring *key = DUK_HOBJECT_E_GET_KEY(heap, h, i);
 		if (!key) {
 			continue;
 		}
 		duk__mark_heaphdr(heap, (duk_heaphdr *) key);
-		if (DUK_HOBJECT_E_SLOT_IS_ACCESSOR(h, i)) {
-			duk__mark_heaphdr(heap, (duk_heaphdr *) DUK_HOBJECT_E_GET_VALUE_PTR(h, i)->a.get);
-			duk__mark_heaphdr(heap, (duk_heaphdr *) DUK_HOBJECT_E_GET_VALUE_PTR(h, i)->a.set);
+		if (DUK_HOBJECT_E_SLOT_IS_ACCESSOR(heap, h, i)) {
+			duk__mark_heaphdr(heap, (duk_heaphdr *) DUK_HOBJECT_E_GET_VALUE_PTR(heap, h, i)->a.get);
+			duk__mark_heaphdr(heap, (duk_heaphdr *) DUK_HOBJECT_E_GET_VALUE_PTR(heap, h, i)->a.set);
 		} else {
-			duk__mark_tval(heap, &DUK_HOBJECT_E_GET_VALUE_PTR(h, i)->v);
+			duk__mark_tval(heap, &DUK_HOBJECT_E_GET_VALUE_PTR(heap, h, i)->v);
 		}
 	}
 
-	for (i = 0; i < (duk_uint_fast32_t) h->a_size; i++) {
-		duk__mark_tval(heap, DUK_HOBJECT_A_GET_VALUE_PTR(h, i));
+	for (i = 0; i < (duk_uint_fast32_t) DUK_HOBJECT_GET_ASIZE(h); i++) {
+		duk__mark_tval(heap, DUK_HOBJECT_A_GET_VALUE_PTR(heap, h, i));
 	}
 
 	/* hash part is a 'weak reference' and does not contribute */
 
-	duk__mark_heaphdr(heap, (duk_heaphdr *) h->prototype);
+	duk__mark_heaphdr(heap, (duk_heaphdr *) DUK_HOBJECT_GET_PROTOTYPE(heap, h));
 
 	if (DUK_HOBJECT_IS_COMPILEDFUNCTION(h)) {
 		duk_hcompiledfunction *f = (duk_hcompiledfunction *) h;
 		duk_tval *tv, *tv_end;
-		duk_hobject **funcs, **funcs_end;
+		duk_hobject **fn, **fn_end;
 
 		/* 'data' is reachable through every compiled function which
 		 * contains a reference.
 		 */
 
-		duk__mark_heaphdr(heap, (duk_heaphdr *) f->data);
+		duk__mark_heaphdr(heap, (duk_heaphdr *) DUK_HCOMPILEDFUNCTION_GET_DATA(heap, f));
 
-		tv = DUK_HCOMPILEDFUNCTION_GET_CONSTS_BASE(f);
-		tv_end = DUK_HCOMPILEDFUNCTION_GET_CONSTS_END(f);
+		tv = DUK_HCOMPILEDFUNCTION_GET_CONSTS_BASE(heap, f);
+		tv_end = DUK_HCOMPILEDFUNCTION_GET_CONSTS_END(heap, f);
 		while (tv < tv_end) {
 			duk__mark_tval(heap, tv);
 			tv++;
 		}
 
-		funcs = DUK_HCOMPILEDFUNCTION_GET_FUNCS_BASE(f);
-		funcs_end = DUK_HCOMPILEDFUNCTION_GET_FUNCS_END(f);
-		while (funcs < funcs_end) {
-			duk__mark_heaphdr(heap, (duk_heaphdr *) *funcs);
-			funcs++;
+		fn = DUK_HCOMPILEDFUNCTION_GET_FUNCS_BASE(heap, f);
+		fn_end = DUK_HCOMPILEDFUNCTION_GET_FUNCS_END(heap, f);
+		while (fn < fn_end) {
+			duk__mark_heaphdr(heap, (duk_heaphdr *) *fn);
+			fn++;
 		}
 	} else if (DUK_HOBJECT_IS_NATIVEFUNCTION(h)) {
 		duk_hnativefunction *f = (duk_hnativefunction *) h;
 		DUK_UNREF(f);
 		/* nothing to mark */
+	} else if (DUK_HOBJECT_IS_BUFFEROBJECT(h)) {
+		duk_hbufferobject *b = (duk_hbufferobject *) h;
+		duk__mark_heaphdr(heap, (duk_heaphdr *) b->buf);
 	} else if (DUK_HOBJECT_IS_THREAD(h)) {
 		duk_hthread *t = (duk_hthread *) h;
 		duk_tval *tv;
 
 		tv = t->valstack;
-		while (tv < t->valstack_end) {
+		while (tv < t->valstack_top) {
 			duk__mark_tval(heap, tv);
 			tv++;
 		}
 
 		for (i = 0; i < (duk_uint_fast32_t) t->callstack_top; i++) {
 			duk_activation *act = t->callstack + i;
-			duk__mark_heaphdr(heap, (duk_heaphdr *) act->func);
+			duk__mark_heaphdr(heap, (duk_heaphdr *) DUK_ACT_GET_FUNC(act));
 			duk__mark_heaphdr(heap, (duk_heaphdr *) act->var_env);
 			duk__mark_heaphdr(heap, (duk_heaphdr *) act->lex_env);
 #ifdef DUK_USE_NONSTD_FUNC_CALLER_PROPERTY
@@ -30111,7 +44449,7 @@ static void duk__mark_hobject(duk_heap *heap, duk_hobject *h) {
 }
 
 /* recursion tracking happens here only */
-static void duk__mark_heaphdr(duk_heap *heap, duk_heaphdr *h) {
+DUK_LOCAL void duk__mark_heaphdr(duk_heap *heap, duk_heaphdr *h) {
 	DUK_DDD(DUK_DDDPRINT("duk__mark_heaphdr %p, type %ld",
 	                     (void *) h,
 	                     (h != NULL ? (long) DUK_HEAPHDR_GET_TYPE(h) : (long) -1)));
@@ -30125,7 +44463,7 @@ static void duk__mark_heaphdr(duk_heap *heap, duk_heaphdr *h) {
 	}
 	DUK_HEAPHDR_SET_REACHABLE(h);
 
-	if (heap->mark_and_sweep_recursion_depth >= DUK_HEAP_MARK_AND_SWEEP_RECURSION_LIMIT) {
+	if (heap->mark_and_sweep_recursion_depth >= DUK_USE_MARK_AND_SWEEP_RECLIMIT) {
 		/* log this with a normal debug level because this should be relatively rare */
 		DUK_D(DUK_DPRINT("mark-and-sweep recursion limit reached, marking as temproot: %p", (void *) h));
 		DUK_HEAP_SET_MARKANDSWEEP_RECLIMIT_REACHED(heap);
@@ -30153,13 +44491,13 @@ static void duk__mark_heaphdr(duk_heap *heap, duk_heaphdr *h) {
 	heap->mark_and_sweep_recursion_depth--;
 }
 
-static void duk__mark_tval(duk_heap *heap, duk_tval *tv) {
+DUK_LOCAL void duk__mark_tval(duk_heap *heap, duk_tval *tv) {
 	DUK_DDD(DUK_DDDPRINT("duk__mark_tval %p", (void *) tv));
 	if (!tv) {
 		return;
 	}
 	if (DUK_TVAL_IS_HEAP_ALLOCATED(tv)) {
-		duk__mark_heaphdr(heap, DUK_TVAL_GET_HEAPHDR(tv)); 
+		duk__mark_heaphdr(heap, DUK_TVAL_GET_HEAPHDR(tv));
 	}
 }
 
@@ -30167,22 +44505,27 @@ static void duk__mark_tval(duk_heap *heap, duk_tval *tv) {
  *  Mark the heap.
  */
 
-static void duk__mark_roots_heap(duk_heap *heap) {
+DUK_LOCAL void duk__mark_roots_heap(duk_heap *heap) {
 	duk_small_uint_t i;
 
 	DUK_DD(DUK_DDPRINT("duk__mark_roots_heap: %p", (void *) heap));
 
 	duk__mark_heaphdr(heap, (duk_heaphdr *) heap->heap_thread);
 	duk__mark_heaphdr(heap, (duk_heaphdr *) heap->heap_object);
-	duk__mark_heaphdr(heap, (duk_heaphdr *) heap->log_buffer);
 
 	for (i = 0; i < DUK_HEAP_NUM_STRINGS; i++) {
-		duk_hstring *h = heap->strs[i];
+		duk_hstring *h = DUK_HEAP_GET_STRING(heap, i);
 		duk__mark_heaphdr(heap, (duk_heaphdr *) h);
 	}
 
 	duk__mark_tval(heap, &heap->lj.value1);
 	duk__mark_tval(heap, &heap->lj.value2);
+
+#if defined(DUK_USE_DEBUGGER_SUPPORT)
+	for (i = 0; i < heap->dbg_breakpoint_count; i++) {
+		duk__mark_heaphdr(heap, (duk_heaphdr *) heap->dbg_breakpoints[i].filename);
+	}
+#endif
 }
 
 /*
@@ -30197,7 +44540,7 @@ static void duk__mark_roots_heap(duk_heap *heap) {
  */
 
 #ifdef DUK_USE_REFERENCE_COUNTING
-static void duk__mark_refzero_list(duk_heap *heap) {
+DUK_LOCAL void duk__mark_refzero_list(duk_heap *heap) {
 	duk_heaphdr *hdr;
 
 	DUK_DD(DUK_DDPRINT("duk__mark_refzero_list: %p", (void *) heap));
@@ -30205,7 +44548,7 @@ static void duk__mark_refzero_list(duk_heap *heap) {
 	hdr = heap->refzero_list;
 	while (hdr) {
 		duk__mark_heaphdr(heap, hdr);
-		hdr = DUK_HEAPHDR_GET_NEXT(hdr);
+		hdr = DUK_HEAPHDR_GET_NEXT(heap, hdr);
 	}
 }
 #endif
@@ -30222,7 +44565,7 @@ static void duk__mark_refzero_list(duk_heap *heap) {
  *  roots; otherwise circular references might be handled inconsistently.
  */
 
-static void duk__mark_finalizable(duk_heap *heap) {
+DUK_LOCAL void duk__mark_finalizable(duk_heap *heap) {
 	duk_hthread *thr;
 	duk_heaphdr *hdr;
 	duk_size_t count_finalizable = 0;
@@ -30235,8 +44578,11 @@ static void duk__mark_finalizable(duk_heap *heap) {
 	hdr = heap->heap_allocated;
 	while (hdr) {
 		/* A finalizer is looked up from the object and up its prototype chain
-		 * (which allows inherited finalizers).
+		 * (which allows inherited finalizers).  A prototype loop must not cause
+		 * an error to be thrown here; duk_hobject_hasprop_raw() will ignore a
+		 * prototype loop silently and indicate that the property doesn't exist.
 		 */
+
 		if (!DUK_HEAPHDR_HAS_REACHABLE(hdr) &&
 		    DUK_HEAPHDR_GET_TYPE(hdr) == DUK_HTYPE_OBJECT &&
 		    !DUK_HEAPHDR_HAS_FINALIZED(hdr) &&
@@ -30257,7 +44603,7 @@ static void duk__mark_finalizable(duk_heap *heap) {
 			count_finalizable ++;
 		}
 
-		hdr = DUK_HEAPHDR_GET_NEXT(hdr);
+		hdr = DUK_HEAPHDR_GET_NEXT(heap, hdr);
 	}
 
 	if (count_finalizable == 0) {
@@ -30273,13 +44619,43 @@ static void duk__mark_finalizable(duk_heap *heap) {
 			duk__mark_heaphdr(heap, hdr);
 		}
 
-		hdr = DUK_HEAPHDR_GET_NEXT(hdr);
+		hdr = DUK_HEAPHDR_GET_NEXT(heap, hdr);
 	}
 
 	/* Caller will finish the marking process if we hit a recursion limit. */
 }
 
 /*
+ *  Mark objects on finalize_list.
+ *
+ */
+
+DUK_LOCAL void duk__mark_finalize_list(duk_heap *heap) {
+	duk_heaphdr *hdr;
+#ifdef DUK_USE_DEBUG
+	duk_size_t count_finalize_list = 0;
+#endif
+
+	DUK_DD(DUK_DDPRINT("duk__mark_finalize_list: %p", (void *) heap));
+
+	hdr = heap->finalize_list;
+	while (hdr) {
+		duk__mark_heaphdr(heap, hdr);
+		hdr = DUK_HEAPHDR_GET_NEXT(heap, hdr);
+#ifdef DUK_USE_DEBUG
+		count_finalize_list++;
+#endif
+	}
+
+#ifdef DUK_USE_DEBUG
+	if (count_finalize_list > 0) {
+		DUK_D(DUK_DPRINT("marked %ld objects on the finalize_list as reachable (previous finalizer run skipped)",
+		                 (long) count_finalize_list));
+	}
+#endif
+}
+
+/*
  *  Fallback marking handler if recursion limit is reached.
  *
  *  Iterates 'temproots' until recursion limit is no longer hit.  Note
@@ -30294,9 +44670,9 @@ static void duk__mark_finalizable(duk_heap *heap) {
  */
 
 #ifdef DUK_USE_DEBUG
-static void duk__handle_temproot(duk_heap *heap, duk_heaphdr *hdr, duk_size_t *count) {
+DUK_LOCAL void duk__handle_temproot(duk_heap *heap, duk_heaphdr *hdr, duk_size_t *count) {
 #else
-static void duk__handle_temproot(duk_heap *heap, duk_heaphdr *hdr) {
+DUK_LOCAL void duk__handle_temproot(duk_heap *heap, duk_heaphdr *hdr) {
 #endif
 	if (!DUK_HEAPHDR_HAS_TEMPROOT(hdr)) {
 		DUK_DDD(DUK_DDDPRINT("not a temp root: %p", (void *) hdr));
@@ -30313,7 +44689,7 @@ static void duk__handle_temproot(duk_heap *heap, duk_heaphdr *hdr) {
 #endif
 }
 
-static void duk__mark_temproots_by_heap_scan(duk_heap *heap) {
+DUK_LOCAL void duk__mark_temproots_by_heap_scan(duk_heap *heap) {
 	duk_heaphdr *hdr;
 #ifdef DUK_USE_DEBUG
 	duk_size_t count;
@@ -30336,7 +44712,7 @@ static void duk__mark_temproots_by_heap_scan(duk_heap *heap) {
 #else
 			duk__handle_temproot(heap, hdr);
 #endif
-			hdr = DUK_HEAPHDR_GET_NEXT(hdr);
+			hdr = DUK_HEAPHDR_GET_NEXT(heap, hdr);
 		}
 
 		/* must also check refzero_list */
@@ -30348,7 +44724,7 @@ static void duk__mark_temproots_by_heap_scan(duk_heap *heap) {
 #else
 			duk__handle_temproot(heap, hdr);
 #endif
-			hdr = DUK_HEAPHDR_GET_NEXT(hdr);
+			hdr = DUK_HEAPHDR_GET_NEXT(heap, hdr);
 		}
 #endif  /* DUK_USE_REFERENCE_COUNTING */
 
@@ -30368,7 +44744,7 @@ static void duk__mark_temproots_by_heap_scan(duk_heap *heap) {
  */
 
 #ifdef DUK_USE_REFERENCE_COUNTING
-static void duk__finalize_refcounts(duk_heap *heap) {
+DUK_LOCAL void duk__finalize_refcounts(duk_heap *heap) {
 	duk_hthread *thr;
 	duk_heaphdr *hdr;
 
@@ -30392,10 +44768,10 @@ static void duk__finalize_refcounts(duk_heap *heap) {
 			 */
 
 			DUK_DDD(DUK_DDDPRINT("unreachable object, refcount finalize before sweeping: %p", (void *) hdr));
-			duk_heap_refcount_finalize_heaphdr(thr, hdr);
+			duk_heaphdr_refcount_finalize(thr, hdr);
 		}
 
-		hdr = DUK_HEAPHDR_GET_NEXT(hdr);
+		hdr = DUK_HEAPHDR_GET_NEXT(heap, hdr);
 	}
 }
 #endif  /* DUK_USE_REFERENCE_COUNTING */
@@ -30405,7 +44781,7 @@ static void duk__finalize_refcounts(duk_heap *heap) {
  */
 
 #ifdef DUK_USE_REFERENCE_COUNTING
-static void duk__clear_refzero_list_flags(duk_heap *heap) {
+DUK_LOCAL void duk__clear_refzero_list_flags(duk_heap *heap) {
 	duk_heaphdr *hdr;
 
 	DUK_DD(DUK_DDPRINT("duk__clear_refzero_list_flags: %p", (void *) heap));
@@ -30416,16 +44792,158 @@ static void duk__clear_refzero_list_flags(duk_heap *heap) {
 		DUK_ASSERT(!DUK_HEAPHDR_HAS_FINALIZABLE(hdr));
 		DUK_ASSERT(!DUK_HEAPHDR_HAS_FINALIZED(hdr));
 		DUK_ASSERT(!DUK_HEAPHDR_HAS_TEMPROOT(hdr));
-		hdr = DUK_HEAPHDR_GET_NEXT(hdr);
+		hdr = DUK_HEAPHDR_GET_NEXT(heap, hdr);
 	}
 }
 #endif  /* DUK_USE_REFERENCE_COUNTING */
 
 /*
+ *  Clear (reachable) flags of finalize_list
+ *
+ *  We could mostly do in the sweep phase when we move objects from the
+ *  heap into the finalize_list.  However, if a finalizer run is skipped
+ *  during a mark-and-sweep, the objects on the finalize_list will be marked
+ *  reachable during the next mark-and-sweep.  Since they're already on the
+ *  finalize_list, no-one will be clearing their REACHABLE flag so we do it
+ *  here.  (This now overlaps with the sweep handling in a harmless way.)
+ */
+
+DUK_LOCAL void duk__clear_finalize_list_flags(duk_heap *heap) {
+	duk_heaphdr *hdr;
+
+	DUK_DD(DUK_DDPRINT("duk__clear_finalize_list_flags: %p", (void *) heap));
+
+	hdr = heap->finalize_list;
+	while (hdr) {
+		DUK_HEAPHDR_CLEAR_REACHABLE(hdr);
+		DUK_ASSERT(!DUK_HEAPHDR_HAS_FINALIZABLE(hdr));
+		DUK_ASSERT(!DUK_HEAPHDR_HAS_FINALIZED(hdr));
+		DUK_ASSERT(!DUK_HEAPHDR_HAS_TEMPROOT(hdr));
+		hdr = DUK_HEAPHDR_GET_NEXT(heap, hdr);
+	}
+}
+
+/*
  *  Sweep stringtable
  */
 
-static void duk__sweep_stringtable(duk_heap *heap, duk_size_t *out_count_keep) {
+#if defined(DUK_USE_STRTAB_CHAIN)
+
+/* XXX: skip count_free w/o debug? */
+#if defined(DUK_USE_HEAPPTR16)
+DUK_LOCAL void duk__sweep_string_chain16(duk_heap *heap, duk_uint16_t *slot, duk_size_t *count_keep, duk_size_t *count_free) {
+	duk_uint16_t h16 = *slot;
+	duk_hstring *h;
+	duk_uint16_t null16 = heap->heapptr_null16;
+
+	if (h16 == null16) {
+		/* nop */
+		return;
+	}
+	h = (duk_hstring *) DUK_USE_HEAPPTR_DEC16(heap->heap_udata, h16);
+	DUK_ASSERT(h != NULL);
+
+	if (DUK_HEAPHDR_HAS_REACHABLE((duk_heaphdr *) h)) {
+		DUK_HEAPHDR_CLEAR_REACHABLE((duk_heaphdr *) h);
+		(*count_keep)++;
+	} else {
+#if defined(DUK_USE_REFERENCE_COUNTING)
+		DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT((duk_heaphdr *) h) == 0);
+#endif
+		/* deal with weak references first */
+		duk_heap_strcache_string_remove(heap, (duk_hstring *) h);
+		*slot = null16;
+
+		/* free inner references (these exist e.g. when external
+		 * strings are enabled)
+		 */
+		duk_free_hstring_inner(heap, h);
+		DUK_FREE(heap, h);
+		(*count_free)++;
+	}
+}
+#else  /* DUK_USE_HEAPPTR16 */
+DUK_LOCAL void duk__sweep_string_chain(duk_heap *heap, duk_hstring **slot, duk_size_t *count_keep, duk_size_t *count_free) {
+	duk_hstring *h = *slot;
+
+	if (h == NULL) {
+		/* nop */
+		return;
+	}
+
+	if (DUK_HEAPHDR_HAS_REACHABLE((duk_heaphdr *) h)) {
+		DUK_HEAPHDR_CLEAR_REACHABLE((duk_heaphdr *) h);
+		(*count_keep)++;
+	} else {
+#if defined(DUK_USE_REFERENCE_COUNTING)
+		DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT((duk_heaphdr *) h) == 0);
+#endif
+		/* deal with weak references first */
+		duk_heap_strcache_string_remove(heap, (duk_hstring *) h);
+		*slot = NULL;
+
+		/* free inner references (these exist e.g. when external
+		 * strings are enabled)
+		 */
+		duk_free_hstring_inner(heap, h);
+		DUK_FREE(heap, h);
+		(*count_free)++;
+	}
+}
+#endif  /* DUK_USE_HEAPPTR16 */
+
+DUK_LOCAL void duk__sweep_stringtable_chain(duk_heap *heap, duk_size_t *out_count_keep) {
+	duk_strtab_entry *e;
+	duk_uint_fast32_t i;
+	duk_size_t count_free = 0;
+	duk_size_t count_keep = 0;
+	duk_size_t j, n;
+#if defined(DUK_USE_HEAPPTR16)
+	duk_uint16_t *lst;
+#else
+	duk_hstring **lst;
+#endif
+
+	DUK_DD(DUK_DDPRINT("duk__sweep_stringtable: %p", (void *) heap));
+
+	/* Non-zero refcounts should not happen for unreachable strings,
+	 * because we refcount finalize all unreachable objects which
+	 * should have decreased unreachable string refcounts to zero
+	 * (even for cycles).
+	 */
+
+	for (i = 0; i < DUK_STRTAB_CHAIN_SIZE; i++) {
+		e = heap->strtable + i;
+		if (e->listlen == 0) {
+#if defined(DUK_USE_HEAPPTR16)
+			duk__sweep_string_chain16(heap, &e->u.str16, &count_keep, &count_free);
+#else
+			duk__sweep_string_chain(heap, &e->u.str, &count_keep, &count_free);
+#endif
+		} else {
+#if defined(DUK_USE_HEAPPTR16)
+			lst = (duk_uint16_t *) DUK_USE_HEAPPTR_DEC16(heap->heap_udata, e->u.strlist16);
+#else
+			lst = e->u.strlist;
+#endif
+			for (j = 0, n = e->listlen; j < n; j++) {
+#if defined(DUK_USE_HEAPPTR16)
+				duk__sweep_string_chain16(heap, lst + j, &count_keep, &count_free);
+#else
+				duk__sweep_string_chain(heap, lst + j, &count_keep, &count_free);
+#endif
+			}
+		}
+	}
+
+	DUK_D(DUK_DPRINT("mark-and-sweep sweep stringtable: %ld freed, %ld kept",
+	                 (long) count_free, (long) count_keep));
+	*out_count_keep = count_keep;
+}
+#endif  /* DUK_USE_STRTAB_CHAIN */
+
+#if defined(DUK_USE_STRTAB_PROBE)
+DUK_LOCAL void duk__sweep_stringtable_probe(duk_heap *heap, duk_size_t *out_count_keep) {
 	duk_hstring *h;
 	duk_uint_fast32_t i;
 #ifdef DUK_USE_DEBUG
@@ -30436,7 +44954,11 @@ static void duk__sweep_stringtable(duk_heap *heap, duk_size_t *out_count_keep) {
 	DUK_DD(DUK_DDPRINT("duk__sweep_stringtable: %p", (void *) heap));
 
 	for (i = 0; i < heap->st_size; i++) {
-		h = heap->st[i];
+#if defined(DUK_USE_HEAPPTR16)
+		h = (duk_hstring *) DUK_USE_HEAPPTR_DEC16(heap->strtable16[i]);
+#else
+		h = heap->strtable[i];
+#endif
 		if (h == NULL || h == DUK_STRTAB_DELETED_MARKER(heap)) {
 			continue;
 		} else if (DUK_HEAPHDR_HAS_REACHABLE((duk_heaphdr *) h)) {
@@ -30467,14 +44989,19 @@ static void duk__sweep_stringtable(duk_heap *heap, duk_size_t *out_count_keep) {
 		 * duk_heap_string_remove() but that would be slow and
 		 * pointless because we already know the slot.
 		 */
-		heap->st[i] = DUK_STRTAB_DELETED_MARKER(heap);
-
-		/* then free */
-#if 1
-		DUK_FREE(heap, (duk_heaphdr *) h);  /* no inner refs/allocs, just free directly */
+#if defined(DUK_USE_HEAPPTR16)
+		heap->strtable16[i] = heap->heapptr_deleted16;
 #else
-		duk_heap_free_heaphdr_raw(heap, (duk_heaphdr *) h);  /* this would be OK but unnecessary */
+		heap->strtable[i] = DUK_STRTAB_DELETED_MARKER(heap);
 #endif
+
+		/* free inner references (these exist e.g. when external
+		 * strings are enabled)
+		 */
+		duk_free_hstring_inner(heap, (duk_hstring *) h);
+
+		/* finally free the struct itself */
+		DUK_FREE(heap, h);
 	}
 
 #ifdef DUK_USE_DEBUG
@@ -30483,12 +45010,13 @@ static void duk__sweep_stringtable(duk_heap *heap, duk_size_t *out_count_keep) {
 #endif
 	*out_count_keep = count_keep;
 }
+#endif  /* DUK_USE_STRTAB_PROBE */
 
 /*
  *  Sweep heap
  */
 
-static void duk__sweep_heap(duk_heap *heap, duk_int_t flags, duk_size_t *out_count_keep) {
+DUK_LOCAL void duk__sweep_heap(duk_heap *heap, duk_int_t flags, duk_size_t *out_count_keep) {
 	duk_heaphdr *prev;  /* last element that was left in the heap */
 	duk_heaphdr *curr;
 	duk_heaphdr *next;
@@ -30509,7 +45037,7 @@ static void duk__sweep_heap(duk_heap *heap, duk_int_t flags, duk_size_t *out_cou
 		/* strings are never placed on the heap allocated list */
 		DUK_ASSERT(DUK_HEAPHDR_GET_TYPE(curr) != DUK_HTYPE_STRING);
 
-		next = DUK_HEAPHDR_GET_NEXT(curr);
+		next = DUK_HEAPHDR_GET_NEXT(heap, curr);
 
 		if (DUK_HEAPHDR_HAS_REACHABLE(curr)) {
 			/*
@@ -30532,11 +45060,11 @@ static void duk__sweep_heap(duk_heap *heap, duk_int_t flags, duk_size_t *out_cou
 
 #ifdef DUK_USE_DOUBLE_LINKED_HEAP
 				if (heap->finalize_list) {
-					DUK_HEAPHDR_SET_PREV(heap->finalize_list, curr);
+					DUK_HEAPHDR_SET_PREV(heap, heap->finalize_list, curr);
 				}
-				DUK_HEAPHDR_SET_PREV(curr, NULL);
+				DUK_HEAPHDR_SET_PREV(heap, curr, NULL);
 #endif
-				DUK_HEAPHDR_SET_NEXT(curr, heap->finalize_list);
+				DUK_HEAPHDR_SET_NEXT(heap, curr, heap->finalize_list);
 				heap->finalize_list = curr;
 #ifdef DUK_USE_DEBUG
 				count_finalize++;
@@ -30569,10 +45097,10 @@ static void duk__sweep_heap(duk_heap *heap, duk_int_t flags, duk_size_t *out_cou
 					heap->heap_allocated = curr;
 				}
 				if (prev) {
-					DUK_HEAPHDR_SET_NEXT(prev, curr);
+					DUK_HEAPHDR_SET_NEXT(heap, prev, curr);
 				}
 #ifdef DUK_USE_DOUBLE_LINKED_HEAP
-				DUK_HEAPHDR_SET_PREV(curr, prev);
+				DUK_HEAPHDR_SET_PREV(heap, curr, prev);
 #endif
 				prev = curr;
 			}
@@ -30626,7 +45154,7 @@ static void duk__sweep_heap(duk_heap *heap, duk_int_t flags, duk_size_t *out_cou
 		}
 	}
 	if (prev) {
-		DUK_HEAPHDR_SET_NEXT(prev, NULL);
+		DUK_HEAPHDR_SET_NEXT(heap, prev, NULL);
 	}
 
 #ifdef DUK_USE_DEBUG
@@ -30640,7 +45168,7 @@ static void duk__sweep_heap(duk_heap *heap, duk_int_t flags, duk_size_t *out_cou
  *  Run (object) finalizers in the "to be finalized" work list.
  */
 
-static void duk__run_object_finalizers(duk_heap *heap) {
+DUK_LOCAL void duk__run_object_finalizers(duk_heap *heap, duk_small_uint_t flags) {
 	duk_heaphdr *curr;
 	duk_heaphdr *next;
 #ifdef DUK_USE_DEBUG
@@ -30663,16 +45191,25 @@ static void duk__run_object_finalizers(duk_heap *heap) {
 		DUK_ASSERT(!DUK_HEAPHDR_HAS_FINALIZABLE(curr));
 		DUK_ASSERT(!DUK_HEAPHDR_HAS_FINALIZED(curr));
 
-		/* run the finalizer */
-		duk_hobject_run_finalizer(thr, (duk_hobject *) curr);  /* must never longjmp */
-
-		/* mark FINALIZED, for next mark-and-sweep (will collect unless has become reachable;
-		 * prevent running finalizer again if reachable)
-		 */
-		DUK_HEAPHDR_SET_FINALIZED(curr);
+		if (DUK_LIKELY((flags & DUK_MS_FLAG_SKIP_FINALIZERS) == 0)) {
+			/* Run the finalizer, duk_hobject_run_finalizer() sets FINALIZED.
+			 * Next mark-and-sweep will collect the object unless it has
+			 * become reachable (i.e. rescued).  FINALIZED prevents the
+			 * finalizer from being executed again before that.
+			 */
+			duk_hobject_run_finalizer(thr, (duk_hobject *) curr);  /* must never longjmp */
+			DUK_ASSERT(DUK_HEAPHDR_HAS_FINALIZED(curr));
+		} else {
+			/* Used during heap destruction: don't actually run finalizers
+			 * because we're heading into forced finalization.  Instead,
+			 * queue finalizable objects back to the heap_allocated list.
+			 */
+			DUK_D(DUK_DPRINT("skip finalizers flag set, queue object to heap_allocated without finalizing"));
+			DUK_ASSERT(!DUK_HEAPHDR_HAS_FINALIZED(curr));
+		}
 
 		/* queue back to heap_allocated */
-		next = DUK_HEAPHDR_GET_NEXT(curr);
+		next = DUK_HEAPHDR_GET_NEXT(heap, curr);
 		DUK_HEAP_INSERT_INTO_HEAP_ALLOCATED(heap, curr);
 
 		curr = next;
@@ -30695,7 +45232,7 @@ static void duk__run_object_finalizers(duk_heap *heap) {
  *  Compaction is assumed to never throw an error.
  */
 
-static int duk__protected_compact_object(duk_context *ctx) {
+DUK_LOCAL int duk__protected_compact_object(duk_context *ctx) {
 	/* XXX: for threads, compact value stack, call stack, catch stack? */
 
 	duk_hobject *obj = duk_get_hobject(ctx, -1);
@@ -30705,9 +45242,9 @@ static int duk__protected_compact_object(duk_context *ctx) {
 }
 
 #ifdef DUK_USE_DEBUG
-static void duk__compact_object_list(duk_heap *heap, duk_hthread *thr, duk_heaphdr *start, duk_size_t *p_count_check, duk_size_t *p_count_compact, duk_size_t *p_count_bytes_saved) {
+DUK_LOCAL void duk__compact_object_list(duk_heap *heap, duk_hthread *thr, duk_heaphdr *start, duk_size_t *p_count_check, duk_size_t *p_count_compact, duk_size_t *p_count_bytes_saved) {
 #else
-static void duk__compact_object_list(duk_heap *heap, duk_hthread *thr, duk_heaphdr *start) {
+DUK_LOCAL void duk__compact_object_list(duk_heap *heap, duk_hthread *thr, duk_heaphdr *start) {
 #endif
 	duk_heaphdr *curr;
 #ifdef DUK_USE_DEBUG
@@ -30722,12 +45259,14 @@ static void duk__compact_object_list(duk_heap *heap, duk_hthread *thr, duk_heaph
 		DUK_DDD(DUK_DDDPRINT("mark-and-sweep compact: %p", (void *) curr));
 
 		if (DUK_HEAPHDR_GET_TYPE(curr) != DUK_HTYPE_OBJECT) {
-			goto next;	
+			goto next;
 		}
 		obj = (duk_hobject *) curr;
 
 #ifdef DUK_USE_DEBUG
-		old_size = DUK_HOBJECT_P_COMPUTE_SIZE(obj->e_size, obj->a_size, obj->h_size);
+		old_size = DUK_HOBJECT_P_COMPUTE_SIZE(DUK_HOBJECT_GET_ESIZE(obj),
+		                                      DUK_HOBJECT_GET_ASIZE(obj),
+		                                      DUK_HOBJECT_GET_HSIZE(obj));
 #endif
 
 		DUK_DD(DUK_DDPRINT("compact object: %p", (void *) obj));
@@ -30736,7 +45275,9 @@ static void duk__compact_object_list(duk_heap *heap, duk_hthread *thr, duk_heaph
 		duk_safe_call((duk_context *) thr, duk__protected_compact_object, 1, 0);
 
 #ifdef DUK_USE_DEBUG
-		new_size = DUK_HOBJECT_P_COMPUTE_SIZE(obj->e_size, obj->a_size, obj->h_size);
+		new_size = DUK_HOBJECT_P_COMPUTE_SIZE(DUK_HOBJECT_GET_ESIZE(obj),
+		                                      DUK_HOBJECT_GET_ASIZE(obj),
+		                                      DUK_HOBJECT_GET_HSIZE(obj));
 #endif
 
 #ifdef DUK_USE_DEBUG
@@ -30745,14 +45286,14 @@ static void duk__compact_object_list(duk_heap *heap, duk_hthread *thr, duk_heaph
 #endif
 
 	 next:
-		curr = DUK_HEAPHDR_GET_NEXT(curr);
+		curr = DUK_HEAPHDR_GET_NEXT(heap, curr);
 #ifdef DUK_USE_DEBUG
 		(*p_count_check)++;
 #endif
 	}
 }
 
-static void duk__compact_objects(duk_heap *heap) {
+DUK_LOCAL void duk__compact_objects(duk_heap *heap) {
 	/* XXX: which lists should participate?  to be finalized? */
 #ifdef DUK_USE_DEBUG
 	duk_size_t count_check = 0;
@@ -30791,7 +45332,7 @@ static void duk__compact_objects(duk_heap *heap) {
  */
 
 #ifdef DUK_USE_ASSERTIONS
-static void duk__assert_heaphdr_flags(duk_heap *heap) {
+DUK_LOCAL void duk__assert_heaphdr_flags(duk_heap *heap) {
 	duk_heaphdr *hdr;
 
 	hdr = heap->heap_allocated;
@@ -30800,7 +45341,7 @@ static void duk__assert_heaphdr_flags(duk_heap *heap) {
 		DUK_ASSERT(!DUK_HEAPHDR_HAS_TEMPROOT(hdr));
 		DUK_ASSERT(!DUK_HEAPHDR_HAS_FINALIZABLE(hdr));
 		/* may have FINALIZED */
-		hdr = DUK_HEAPHDR_GET_NEXT(hdr);
+		hdr = DUK_HEAPHDR_GET_NEXT(heap, hdr);
 	}
 
 #ifdef DUK_USE_REFERENCE_COUNTING
@@ -30810,13 +45351,13 @@ static void duk__assert_heaphdr_flags(duk_heap *heap) {
 		DUK_ASSERT(!DUK_HEAPHDR_HAS_TEMPROOT(hdr));
 		DUK_ASSERT(!DUK_HEAPHDR_HAS_FINALIZABLE(hdr));
 		DUK_ASSERT(!DUK_HEAPHDR_HAS_FINALIZED(hdr));
-		hdr = DUK_HEAPHDR_GET_NEXT(hdr);
+		hdr = DUK_HEAPHDR_GET_NEXT(heap, hdr);
 	}
 #endif  /* DUK_USE_REFERENCE_COUNTING */
 }
 
 #ifdef DUK_USE_REFERENCE_COUNTING
-static void duk__assert_valid_refcounts(duk_heap *heap) {
+DUK_LOCAL void duk__assert_valid_refcounts(duk_heap *heap) {
 	duk_heaphdr *hdr = heap->heap_allocated;
 	while (hdr) {
 		if (DUK_HEAPHDR_GET_REFCOUNT(hdr) == 0 &&
@@ -30841,13 +45382,59 @@ static void duk__assert_valid_refcounts(duk_heap *heap) {
 			DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT(hdr) > 0);
 #endif
 		}
-		hdr = DUK_HEAPHDR_GET_NEXT(hdr);
+		hdr = DUK_HEAPHDR_GET_NEXT(heap, hdr);
 	}
 }
 #endif  /* DUK_USE_REFERENCE_COUNTING */
 #endif  /* DUK_USE_ASSERTIONS */
 
 /*
+ *  Finalizer torture.  Do one fake finalizer call which causes side effects
+ *  similar to one or more finalizers on actual objects.
+ */
+
+#if defined(DUK_USE_MARKANDSWEEP_FINALIZER_TORTURE)
+DUK_LOCAL duk_ret_t duk__markandsweep_fake_finalizer(duk_context *ctx) {
+	DUK_D(DUK_DPRINT("fake mark-and-sweep torture finalizer executed"));
+
+	/* Require a lot of stack to force a value stack grow/shrink.
+	 * Recursive mark-and-sweep is prevented by allocation macros
+	 * so this won't trigger another mark-and-sweep.
+	 */
+	duk_require_stack(ctx, 100000);
+
+	/* XXX: do something to force a callstack grow/shrink, perhaps
+	 * just a manual forced resize or a forced relocating realloc?
+	 */
+
+	return 0;
+}
+
+DUK_LOCAL void duk__markandsweep_torture_finalizer(duk_hthread *thr) {
+	duk_context *ctx;
+	duk_int_t rc;
+
+	DUK_ASSERT(thr != NULL);
+	ctx = (duk_context *) thr;
+
+	/* Avoid fake finalization when callstack limit has been reached.
+	 * Otherwise a callstack limit error will be created, then refzero'ed.
+	 */
+	if (thr->heap->call_recursion_depth >= thr->heap->call_recursion_limit ||
+	    thr->callstack_size + 2 * DUK_CALLSTACK_GROW_STEP >= thr->callstack_max /*approximate*/) {
+		DUK_D(DUK_DPRINT("call recursion depth reached, avoid fake mark-and-sweep torture finalizer"));
+		return;
+	}
+
+	/* Run fake finalizer.  Avoid creating unnecessary garbage. */
+	duk_push_c_function(ctx, duk__markandsweep_fake_finalizer, 0 /*nargs*/);
+	rc = duk_pcall(ctx, 0 /*nargs*/);
+	DUK_UNREF(rc);  /* ignored */
+	duk_pop(ctx);
+}
+#endif  /* DUK_USE_MARKANDSWEEP_FINALIZER_TORTURE */
+
+/*
  *  Main mark-and-sweep function.
  *
  *  'flags' represents the features requested by the caller.  The current
@@ -30856,16 +45443,23 @@ static void duk__assert_valid_refcounts(duk_heap *heap) {
  *  to avoid trouble.
  */
 
-duk_bool_t duk_heap_mark_and_sweep(duk_heap *heap, duk_small_uint_t flags) {
+DUK_INTERNAL duk_bool_t duk_heap_mark_and_sweep(duk_heap *heap, duk_small_uint_t flags) {
+	duk_hthread *thr;
 	duk_size_t count_keep_obj;
 	duk_size_t count_keep_str;
+#ifdef DUK_USE_VOLUNTARY_GC
 	duk_size_t tmp;
+#endif
 
-	/* FIXME: thread selection for mark-and-sweep is currently a hack.
+	/* XXX: thread selection for mark-and-sweep is currently a hack.
 	 * If we don't have a thread, the entire mark-and-sweep is now
 	 * skipped (although we could just skip finalizations).
 	 */
-	if (duk__get_temp_hthread(heap) == NULL) {
+	/* XXX: if thr != NULL, the thr may still be in the middle of
+	 * initialization; improve the thread viability test.
+	 */
+	thr = duk__get_temp_hthread(heap);
+	if (thr == NULL) {
 		DUK_D(DUK_DPRINT("temporary hack: gc skipped because we don't have a temp thread"));
 
 		/* reset voluntary gc trigger count */
@@ -30913,6 +45507,10 @@ duk_bool_t duk_heap_mark_and_sweep(duk_heap *heap, duk_small_uint_t flags) {
 	 *  check which objects are unreachable and are finalizable; such
 	 *  objects are marked as FINALIZABLE and marked as reachability
 	 *  (and "temproots" is run again to complete the process).
+	 *
+	 *  The heap finalize_list must also be marked as a reachability root.
+	 *  There may be objects on the list from a previous round if the
+	 *  previous run had finalizer skip flag.
 	 */
 
 	duk__mark_roots_heap(heap);               /* main reachability roots */
@@ -30922,6 +45520,7 @@ duk_bool_t duk_heap_mark_and_sweep(duk_heap *heap, duk_small_uint_t flags) {
 	duk__mark_temproots_by_heap_scan(heap);   /* temproots */
 
 	duk__mark_finalizable(heap);              /* mark finalizable as reachability roots */
+	duk__mark_finalize_list(heap);            /* mark finalizer work list as reachability roots */
 	duk__mark_temproots_by_heap_scan(heap);   /* temproots */
 
 	/*
@@ -30944,10 +45543,17 @@ duk_bool_t duk_heap_mark_and_sweep(duk_heap *heap, duk_small_uint_t flags) {
 	duk__finalize_refcounts(heap);
 #endif
 	duk__sweep_heap(heap, flags, &count_keep_obj);
-	duk__sweep_stringtable(heap, &count_keep_str);
+#if defined(DUK_USE_STRTAB_CHAIN)
+	duk__sweep_stringtable_chain(heap, &count_keep_str);
+#elif defined(DUK_USE_STRTAB_PROBE)
+	duk__sweep_stringtable_probe(heap, &count_keep_str);
+#else
+#error internal error, invalid strtab options
+#endif
 #ifdef DUK_USE_REFERENCE_COUNTING
 	duk__clear_refzero_list_flags(heap);
 #endif
+	duk__clear_finalize_list_flags(heap);
 
 	/*
 	 *  Object compaction (emergency only).
@@ -30985,7 +45591,7 @@ duk_bool_t duk_heap_mark_and_sweep(duk_heap *heap, duk_small_uint_t flags) {
 #if defined(DUK_USE_MS_STRINGTABLE_RESIZE)
 	if (!(flags & DUK_MS_FLAG_NO_STRINGTABLE_RESIZE)) {
 		DUK_DD(DUK_DDPRINT("resize stringtable: %p", (void *) heap));
-		duk_heap_force_stringtable_resize(heap);
+		duk_heap_force_strtab_resize(heap);
 	} else {
 		DUK_D(DUK_DPRINT("stringtable resize skipped because DUK_MS_FLAG_NO_STRINGTABLE_RESIZE is set"));
 	}
@@ -31018,10 +45624,26 @@ duk_bool_t duk_heap_mark_and_sweep(duk_heap *heap, duk_small_uint_t flags) {
 	 *  already happened, this is probably good enough for now.
 	 */
 
-	if (!(flags & DUK_MS_FLAG_NO_FINALIZERS)) {
-		duk__run_object_finalizers(heap);
+#if defined(DUK_USE_MARKANDSWEEP_FINALIZER_TORTURE)
+	/* Cannot simulate individual finalizers because finalize_list only
+	 * contains objects with actual finalizers.  But simulate side effects
+	 * from finalization by doing a bogus function call and resizing the
+	 * stacks.
+	 */
+	if (flags & DUK_MS_FLAG_NO_FINALIZERS) {
+		DUK_D(DUK_DPRINT("skip mark-and-sweep torture finalizer, DUK_MS_FLAG_NO_FINALIZERS is set"));
+	} else if (!(thr->valstack != NULL && thr->callstack != NULL && thr->catchstack != NULL)) {
+		DUK_D(DUK_DPRINT("skip mark-and-sweep torture finalizer, thread not yet viable"));
 	} else {
+		DUK_D(DUK_DPRINT("run mark-and-sweep torture finalizer"));
+		duk__markandsweep_torture_finalizer(thr);
+	}
+#endif  /* DUK_USE_MARKANDSWEEP_FINALIZER_TORTURE */
+
+	if (flags & DUK_MS_FLAG_NO_FINALIZERS) {
 		DUK_D(DUK_DPRINT("finalizer run skipped because DUK_MS_FLAG_NO_FINALIZERS is set"));
+	} else {
+		duk__run_object_finalizers(heap, flags);
 	}
 
 	/*
@@ -31062,6 +45684,7 @@ duk_bool_t duk_heap_mark_and_sweep(duk_heap *heap, duk_small_uint_t flags) {
 	DUK_D(DUK_DPRINT("garbage collect (mark-and-sweep) finished: %ld objects kept, %ld strings kept, no voluntary trigger",
 	                 (long) count_keep_obj, (long) count_keep_str));
 #endif
+
 	return 0;  /* OK */
 }
 
@@ -31093,7 +45716,7 @@ duk_bool_t duk_heap_mark_and_sweep(duk_heap *heap, duk_small_uint_t flags) {
 		} \
 	} while (0)
 
-static void duk__run_voluntary_gc(duk_heap *heap) {
+DUK_LOCAL void duk__run_voluntary_gc(duk_heap *heap) {
 	if (DUK_HEAP_HAS_MARKANDSWEEP_RUNNING(heap)) {
 		DUK_DD(DUK_DDPRINT("mark-and-sweep in progress -> skip voluntary mark-and-sweep now"));
 	} else {
@@ -31115,7 +45738,7 @@ static void duk__run_voluntary_gc(duk_heap *heap) {
  */
 
 #ifdef DUK_USE_MARK_AND_SWEEP
-void *duk_heap_mem_alloc(duk_heap *heap, duk_size_t size) {
+DUK_INTERNAL void *duk_heap_mem_alloc(duk_heap *heap, duk_size_t size) {
 	void *res;
 	duk_bool_t rc;
 	duk_small_int_t i;
@@ -31142,7 +45765,7 @@ void *duk_heap_mem_alloc(duk_heap *heap, duk_size_t size) {
 		goto skip_attempt;
 	}
 #endif
-	res = heap->alloc_func(heap->alloc_udata, size);
+	res = heap->alloc_func(heap->heap_udata, size);
 	if (res || size == 0) {
 		/* for zero size allocations NULL is allowed */
 		return res;
@@ -31181,116 +45804,116 @@ void *duk_heap_mem_alloc(duk_heap *heap, duk_size_t size) {
 		rc = duk_heap_mark_and_sweep(heap, flags);
 		DUK_UNREF(rc);
 
-		res = heap->alloc_func(heap->alloc_udata, size);
-		if (res) {
-			DUK_D(DUK_DPRINT("duk_heap_mem_alloc() succeeded after gc (pass %ld), alloc size %ld",
-			                 (long) (i + 1), (long) size));
-			return res;
-		}
-	}
-
-	DUK_D(DUK_DPRINT("duk_heap_mem_alloc() failed even after gc, alloc size %ld", (long) size));
-	return NULL;
-}
-#else  /* DUK_USE_MARK_AND_SWEEP */
-/*
- *  Compared to a direct macro expansion this wrapper saves a few
- *  instructions because no heap dereferencing is required.
- */
-void *duk_heap_mem_alloc(duk_heap *heap, duk_size_t size) {
-	DUK_ASSERT(heap != NULL);
-	DUK_ASSERT_DISABLE(size >= 0);
-
-	return heap->alloc_func(heap->alloc_udata, size);
-}
-#endif  /* DUK_USE_MARK_AND_SWEEP */
-
-void *duk_heap_mem_alloc_zeroed(duk_heap *heap, duk_size_t size) {
-	void *res;
-
-	DUK_ASSERT(heap != NULL);
-	DUK_ASSERT_DISABLE(size >= 0);
-
-	res = DUK_ALLOC(heap, size);
-	if (res) {
-		/* assume memset with zero size is OK */
-		DUK_MEMZERO(res, size);
-	}
-	return res;
-}
-
-/*
- *  Reallocate memory with garbage collection
- */
-
-#ifdef DUK_USE_MARK_AND_SWEEP
-void *duk_heap_mem_realloc(duk_heap *heap, void *ptr, duk_size_t newsize) {
-	void *res;
-	duk_bool_t rc;
-	duk_small_int_t i;
-
-	DUK_ASSERT(heap != NULL);
-	/* ptr may be NULL */
-	DUK_ASSERT_DISABLE(newsize >= 0);
-
-	/*
-	 *  Voluntary periodic GC (if enabled)
-	 */
-
-	DUK__VOLUNTARY_PERIODIC_GC(heap);
-
-	/*
-	 *  First attempt
-	 */
-
-#ifdef DUK_USE_GC_TORTURE
-	/* simulate alloc failure on every realloc (except when mark-and-sweep is running) */
-	if (!DUK_HEAP_HAS_MARKANDSWEEP_RUNNING(heap)) {
-		DUK_DDD(DUK_DDDPRINT("gc torture enabled, pretend that first realloc attempt fails"));
-		res = NULL;
-		DUK_UNREF(res);
-		goto skip_attempt;
-	}
-#endif
-	res = heap->realloc_func(heap->alloc_udata, ptr, newsize);
-	if (res || newsize == 0) {
-		/* for zero size allocations NULL is allowed */
-		return res;
-	}
-#ifdef DUK_USE_GC_TORTURE
- skip_attempt:
-#endif
-
-	DUK_D(DUK_DPRINT("first realloc attempt failed, attempt to gc and retry"));
-
-	/*
-	 *  Avoid a GC if GC is already running.  See duk_heap_mem_alloc().
-	 */
-
-	if (DUK_HEAP_HAS_MARKANDSWEEP_RUNNING(heap)) {
-		DUK_D(DUK_DPRINT("duk_heap_mem_realloc() failed, gc in progress (gc skipped), alloc size %ld", (long) newsize));
-		return NULL;
-	}
-
-	/*
-	 *  Retry with several GC attempts.  Initial attempts are made without
-	 *  emergency mode; later attempts use emergency mode which minimizes
-	 *  memory allocations forcibly.
-	 */
-
-	for (i = 0; i < DUK_HEAP_ALLOC_FAIL_MARKANDSWEEP_LIMIT; i++) {
-		duk_small_uint_t flags;
-
-		flags = 0;
-		if (i >= DUK_HEAP_ALLOC_FAIL_MARKANDSWEEP_EMERGENCY_LIMIT - 1) {
-			flags |= DUK_MS_FLAG_EMERGENCY;
-		}
-
-		rc = duk_heap_mark_and_sweep(heap, flags);
-		DUK_UNREF(rc);
-
-		res = heap->realloc_func(heap->alloc_udata, ptr, newsize);
+		res = heap->alloc_func(heap->heap_udata, size);
 		if (res) {
+			DUK_D(DUK_DPRINT("duk_heap_mem_alloc() succeeded after gc (pass %ld), alloc size %ld",
+			                 (long) (i + 1), (long) size));
+			return res;
+		}
+	}
+
+	DUK_D(DUK_DPRINT("duk_heap_mem_alloc() failed even after gc, alloc size %ld", (long) size));
+	return NULL;
+}
+#else  /* DUK_USE_MARK_AND_SWEEP */
+/*
+ *  Compared to a direct macro expansion this wrapper saves a few
+ *  instructions because no heap dereferencing is required.
+ */
+DUK_INTERNAL void *duk_heap_mem_alloc(duk_heap *heap, duk_size_t size) {
+	DUK_ASSERT(heap != NULL);
+	DUK_ASSERT_DISABLE(size >= 0);
+
+	return heap->alloc_func(heap->heap_udata, size);
+}
+#endif  /* DUK_USE_MARK_AND_SWEEP */
+
+DUK_INTERNAL void *duk_heap_mem_alloc_zeroed(duk_heap *heap, duk_size_t size) {
+	void *res;
+
+	DUK_ASSERT(heap != NULL);
+	DUK_ASSERT_DISABLE(size >= 0);
+
+	res = DUK_ALLOC(heap, size);
+	if (res) {
+		/* assume memset with zero size is OK */
+		DUK_MEMZERO(res, size);
+	}
+	return res;
+}
+
+/*
+ *  Reallocate memory with garbage collection
+ */
+
+#ifdef DUK_USE_MARK_AND_SWEEP
+DUK_INTERNAL void *duk_heap_mem_realloc(duk_heap *heap, void *ptr, duk_size_t newsize) {
+	void *res;
+	duk_bool_t rc;
+	duk_small_int_t i;
+
+	DUK_ASSERT(heap != NULL);
+	/* ptr may be NULL */
+	DUK_ASSERT_DISABLE(newsize >= 0);
+
+	/*
+	 *  Voluntary periodic GC (if enabled)
+	 */
+
+	DUK__VOLUNTARY_PERIODIC_GC(heap);
+
+	/*
+	 *  First attempt
+	 */
+
+#ifdef DUK_USE_GC_TORTURE
+	/* simulate alloc failure on every realloc (except when mark-and-sweep is running) */
+	if (!DUK_HEAP_HAS_MARKANDSWEEP_RUNNING(heap)) {
+		DUK_DDD(DUK_DDDPRINT("gc torture enabled, pretend that first realloc attempt fails"));
+		res = NULL;
+		DUK_UNREF(res);
+		goto skip_attempt;
+	}
+#endif
+	res = heap->realloc_func(heap->heap_udata, ptr, newsize);
+	if (res || newsize == 0) {
+		/* for zero size allocations NULL is allowed */
+		return res;
+	}
+#ifdef DUK_USE_GC_TORTURE
+ skip_attempt:
+#endif
+
+	DUK_D(DUK_DPRINT("first realloc attempt failed, attempt to gc and retry"));
+
+	/*
+	 *  Avoid a GC if GC is already running.  See duk_heap_mem_alloc().
+	 */
+
+	if (DUK_HEAP_HAS_MARKANDSWEEP_RUNNING(heap)) {
+		DUK_D(DUK_DPRINT("duk_heap_mem_realloc() failed, gc in progress (gc skipped), alloc size %ld", (long) newsize));
+		return NULL;
+	}
+
+	/*
+	 *  Retry with several GC attempts.  Initial attempts are made without
+	 *  emergency mode; later attempts use emergency mode which minimizes
+	 *  memory allocations forcibly.
+	 */
+
+	for (i = 0; i < DUK_HEAP_ALLOC_FAIL_MARKANDSWEEP_LIMIT; i++) {
+		duk_small_uint_t flags;
+
+		flags = 0;
+		if (i >= DUK_HEAP_ALLOC_FAIL_MARKANDSWEEP_EMERGENCY_LIMIT - 1) {
+			flags |= DUK_MS_FLAG_EMERGENCY;
+		}
+
+		rc = duk_heap_mark_and_sweep(heap, flags);
+		DUK_UNREF(rc);
+
+		res = heap->realloc_func(heap->heap_udata, ptr, newsize);
+		if (res || newsize == 0) {
 			DUK_D(DUK_DPRINT("duk_heap_mem_realloc() succeeded after gc (pass %ld), alloc size %ld",
 			                 (long) (i + 1), (long) newsize));
 			return res;
@@ -31302,12 +45925,12 @@ void *duk_heap_mem_realloc(duk_heap *heap, void *ptr, duk_size_t newsize) {
 }
 #else  /* DUK_USE_MARK_AND_SWEEP */
 /* saves a few instructions to have this wrapper (see comment on duk_heap_mem_alloc) */
-void *duk_heap_mem_realloc(duk_heap *heap, void *ptr, duk_size_t newsize) {
+DUK_INTERNAL void *duk_heap_mem_realloc(duk_heap *heap, void *ptr, duk_size_t newsize) {
 	DUK_ASSERT(heap != NULL);
 	/* ptr may be NULL */
 	DUK_ASSERT_DISABLE(newsize >= 0);
 
-	return heap->realloc_func(heap->alloc_udata, ptr, newsize);
+	return heap->realloc_func(heap->heap_udata, ptr, newsize);
 }
 #endif  /* DUK_USE_MARK_AND_SWEEP */
 
@@ -31318,7 +45941,7 @@ void *duk_heap_mem_realloc(duk_heap *heap, void *ptr, duk_size_t newsize) {
  */
 
 #ifdef DUK_USE_MARK_AND_SWEEP
-void *duk_heap_mem_realloc_indirect(duk_heap *heap, duk_mem_getptr cb, void *ud, duk_size_t newsize) {
+DUK_INTERNAL void *duk_heap_mem_realloc_indirect(duk_heap *heap, duk_mem_getptr cb, void *ud, duk_size_t newsize) {
 	void *res;
 	duk_bool_t rc;
 	duk_small_int_t i;
@@ -31345,7 +45968,7 @@ void *duk_heap_mem_realloc_indirect(duk_heap *heap, duk_mem_getptr cb, void *ud,
 		goto skip_attempt;
 	}
 #endif
-	res = heap->realloc_func(heap->alloc_udata, cb(ud), newsize);
+	res = heap->realloc_func(heap->heap_udata, cb(heap, ud), newsize);
 	if (res || newsize == 0) {
 		/* for zero size allocations NULL is allowed */
 		return res;
@@ -31380,7 +46003,7 @@ void *duk_heap_mem_realloc_indirect(duk_heap *heap, duk_mem_getptr cb, void *ud,
 #endif
 
 #ifdef DUK_USE_ASSERTIONS
-		ptr_pre = cb(ud);
+		ptr_pre = cb(heap, ud);
 #endif
 		flags = 0;
 		if (i >= DUK_HEAP_ALLOC_FAIL_MARKANDSWEEP_EMERGENCY_LIMIT - 1) {
@@ -31390,20 +46013,20 @@ void *duk_heap_mem_realloc_indirect(duk_heap *heap, duk_mem_getptr cb, void *ud,
 		rc = duk_heap_mark_and_sweep(heap, flags);
 		DUK_UNREF(rc);
 #ifdef DUK_USE_ASSERTIONS
-		ptr_post = cb(ud);
+		ptr_post = cb(heap, ud);
 		if (ptr_pre != ptr_post) {
 			/* useful for debugging */
 			DUK_DD(DUK_DDPRINT("note: base pointer changed by mark-and-sweep: %p -> %p",
 			                   (void *) ptr_pre, (void *) ptr_post));
 		}
 #endif
-	
+
 		/* Note: key issue here is to re-lookup the base pointer on every attempt.
 		 * The pointer being reallocated may change after every mark-and-sweep.
 		 */
 
-		res = heap->realloc_func(heap->alloc_udata, cb(ud), newsize);
-		if (res) {
+		res = heap->realloc_func(heap->heap_udata, cb(heap, ud), newsize);
+		if (res || newsize == 0) {
 			DUK_D(DUK_DPRINT("duk_heap_mem_realloc_indirect() succeeded after gc (pass %ld), alloc size %ld",
 			                 (long) (i + 1), (long) newsize));
 			return res;
@@ -31415,8 +46038,8 @@ void *duk_heap_mem_realloc_indirect(duk_heap *heap, duk_mem_getptr cb, void *ud,
 }
 #else  /* DUK_USE_MARK_AND_SWEEP */
 /* saves a few instructions to have this wrapper (see comment on duk_heap_mem_alloc) */
-void *duk_heap_mem_realloc_indirect(duk_heap *heap, duk_mem_getptr cb, void *ud, duk_size_t newsize) {
-	return heap->realloc_func(heap->alloc_udata, cb(ud), newsize);
+DUK_INTERNAL void *duk_heap_mem_realloc_indirect(duk_heap *heap, duk_mem_getptr cb, void *ud, duk_size_t newsize) {
+	return heap->realloc_func(heap->heap_udata, cb(heap, ud), newsize);
 }
 #endif  /* DUK_USE_MARK_AND_SWEEP */
 
@@ -31425,14 +46048,14 @@ void *duk_heap_mem_realloc_indirect(duk_heap *heap, duk_mem_getptr cb, void *ud,
  */
 
 #ifdef DUK_USE_MARK_AND_SWEEP
-void duk_heap_mem_free(duk_heap *heap, void *ptr) {
+DUK_INTERNAL void duk_heap_mem_free(duk_heap *heap, void *ptr) {
 	DUK_ASSERT(heap != NULL);
 	/* ptr may be NULL */
 
 	/* Must behave like a no-op with NULL and any pointer returned from
 	 * malloc/realloc with zero size.
 	 */
-	heap->free_func(heap->alloc_udata, ptr);
+	heap->free_func(heap->heap_udata, ptr);
 
 	/* Count free operations toward triggering a GC but never actually trigger
 	 * a GC from a free.  Otherwise code which frees internal structures would
@@ -31445,110 +46068,16 @@ void duk_heap_mem_free(duk_heap *heap, void *ptr) {
 }
 #else
 /* saves a few instructions to have this wrapper (see comment on duk_heap_mem_alloc) */
-void duk_heap_mem_free(duk_heap *heap, void *ptr) {
+DUK_INTERNAL void duk_heap_mem_free(duk_heap *heap, void *ptr) {
 	DUK_ASSERT(heap != NULL);
 	/* ptr may be NULL */
 
 	/* Note: must behave like a no-op with NULL and any pointer
 	 * returned from malloc/realloc with zero size.
 	 */
-	heap->free_func(heap->alloc_udata, ptr);
-}
-#endif
-
-/*
- *  Checked variants
- */
-
-#ifdef DUK_USE_VERBOSE_ERRORS
-void *duk_heap_mem_alloc_checked(duk_hthread *thr, duk_size_t size, const char *filename, duk_int_t line) {
-#else
-void *duk_heap_mem_alloc_checked(duk_hthread *thr, duk_size_t size) {
-#endif
-	void *res;
-
-	DUK_ASSERT(thr != NULL);
-	DUK_ASSERT_DISABLE(size >= 0);
-
-	res = DUK_ALLOC(thr->heap, size);
-	if (!res) {
-#ifdef DUK_USE_VERBOSE_ERRORS
-		DUK_ERROR_RAW(filename, line, thr, DUK_ERR_ALLOC_ERROR, "memory alloc failed");
-#else
-		DUK_ERROR(thr, DUK_ERR_ALLOC_ERROR, "memory alloc failed");
-#endif
-	}
-	return res;
-}
-
-#ifdef DUK_USE_VERBOSE_ERRORS
-void *duk_heap_mem_alloc_checked_zeroed(duk_hthread *thr, duk_size_t size, const char *filename, duk_int_t line) {
-#else
-void *duk_heap_mem_alloc_checked_zeroed(duk_hthread *thr, duk_size_t size) {
-#endif
-	void *res;
-
-	DUK_ASSERT(thr != NULL);
-	DUK_ASSERT_DISABLE(size >= 0);
-
-	res = DUK_ALLOC(thr->heap, size);
-	if (!res) {
-#ifdef DUK_USE_VERBOSE_ERRORS
-		DUK_ERROR_RAW(filename, line, thr, DUK_ERR_ALLOC_ERROR, "memory alloc failed");
-#else
-		DUK_ERROR(thr, DUK_ERR_ALLOC_ERROR, "memory alloc failed");
-#endif
-	}
-	/* assume memset with zero size is OK */
-	DUK_MEMZERO(res, size);
-	return res;
-}
-
-#ifdef DUK_USE_VERBOSE_ERRORS
-void *duk_heap_mem_realloc_checked(duk_hthread *thr, void *ptr, duk_size_t newsize, const char *filename, duk_int_t line) {
-#else
-void *duk_heap_mem_realloc_checked(duk_hthread *thr, void *ptr, duk_size_t newsize) {
-#endif
-	void *res;
-
-	DUK_ASSERT(thr != NULL);
-	/* ptr may be NULL */
-	DUK_ASSERT_DISABLE(newsize >= 0);
-
-	res = DUK_REALLOC(thr->heap, ptr, newsize);
-	if (!res) {
-#ifdef DUK_USE_VERBOSE_ERRORS
-		DUK_ERROR_RAW(filename, line, thr, DUK_ERR_ALLOC_ERROR, "memory realloc failed");
-#else
-		DUK_ERROR(thr, DUK_ERR_ALLOC_ERROR, "memory realloc failed");
-#endif
-	}
-	return res;
+	heap->free_func(heap->heap_udata, ptr);
 }
-
-#ifdef DUK_USE_VERBOSE_ERRORS
-void *duk_heap_mem_realloc_indirect_checked(duk_hthread *thr, duk_mem_getptr cb, void *ud, duk_size_t newsize, const char *filename, duk_int_t line) {
-#else
-void *duk_heap_mem_realloc_indirect_checked(duk_hthread *thr, duk_mem_getptr cb, void *ud, duk_size_t newsize) {
 #endif
-	void *res;
-	DUK_ASSERT(thr != NULL);
-	DUK_ASSERT_DISABLE(newsize >= 0);
-
-	res = DUK_REALLOC_INDIRECT(thr->heap, cb, ud, newsize);
-	if (!res) {
-#ifdef DUK_USE_VERBOSE_ERRORS
-		DUK_ERROR_RAW(filename, line, thr, DUK_ERR_ALLOC_ERROR, "memory realloc failed");
-#else
-		DUK_ERROR(thr, DUK_ERR_ALLOC_ERROR, "memory realloc failed");
-#endif
-	}
-	return res;
-}
-
-/* Note: no need for duk_heap_mem_free_checked(), as free must not fail.
- * There is a DUK_FREE_CHECKED() macro just in case, though.
- */
 #line 1 "duk_heap_misc.c"
 /*
  *  Support functions for duk_heap.
@@ -31560,46 +46089,67 @@ void *duk_heap_mem_realloc_indirect_checked(duk_hthread *thr, duk_mem_getptr cb,
 /* arbitrary remove only works with double linked heap, and is only required by
  * reference counting so far.
  */
-void duk_heap_remove_any_from_heap_allocated(duk_heap *heap, duk_heaphdr *hdr) {
+DUK_INTERNAL void duk_heap_remove_any_from_heap_allocated(duk_heap *heap, duk_heaphdr *hdr) {
 	DUK_ASSERT(DUK_HEAPHDR_GET_TYPE(hdr) != DUK_HTYPE_STRING);
 
-	if (DUK_HEAPHDR_GET_PREV(hdr)) {
-		DUK_HEAPHDR_SET_NEXT(DUK_HEAPHDR_GET_PREV(hdr), DUK_HEAPHDR_GET_NEXT(hdr));
+	if (DUK_HEAPHDR_GET_PREV(heap, hdr)) {
+		DUK_HEAPHDR_SET_NEXT(heap, DUK_HEAPHDR_GET_PREV(heap, hdr), DUK_HEAPHDR_GET_NEXT(heap, hdr));
 	} else {
-		heap->heap_allocated = DUK_HEAPHDR_GET_NEXT(hdr);
+		heap->heap_allocated = DUK_HEAPHDR_GET_NEXT(heap, hdr);
 	}
-	if (DUK_HEAPHDR_GET_NEXT(hdr)) {
-		DUK_HEAPHDR_SET_PREV(DUK_HEAPHDR_GET_NEXT(hdr), DUK_HEAPHDR_GET_PREV(hdr));
+	if (DUK_HEAPHDR_GET_NEXT(heap, hdr)) {
+		DUK_HEAPHDR_SET_PREV(heap, DUK_HEAPHDR_GET_NEXT(heap, hdr), DUK_HEAPHDR_GET_PREV(heap, hdr));
 	} else {
 		;
 	}
 }
 #endif
 
-void duk_heap_insert_into_heap_allocated(duk_heap *heap, duk_heaphdr *hdr) {
+DUK_INTERNAL void duk_heap_insert_into_heap_allocated(duk_heap *heap, duk_heaphdr *hdr) {
 	DUK_ASSERT(DUK_HEAPHDR_GET_TYPE(hdr) != DUK_HTYPE_STRING);
 
 #ifdef DUK_USE_DOUBLE_LINKED_HEAP
 	if (heap->heap_allocated) {
-		DUK_ASSERT(DUK_HEAPHDR_GET_PREV(heap->heap_allocated) == NULL);
-		DUK_HEAPHDR_SET_PREV(heap->heap_allocated, hdr);
+		DUK_ASSERT(DUK_HEAPHDR_GET_PREV(heap, heap->heap_allocated) == NULL);
+		DUK_HEAPHDR_SET_PREV(heap, heap->heap_allocated, hdr);
 	}
-	DUK_HEAPHDR_SET_PREV(hdr, NULL);
+	DUK_HEAPHDR_SET_PREV(heap, hdr, NULL);
 #endif
-	DUK_HEAPHDR_SET_NEXT(hdr, heap->heap_allocated);
+	DUK_HEAPHDR_SET_NEXT(heap, hdr, heap->heap_allocated);
 	heap->heap_allocated = hdr;
 }
 
 #ifdef DUK_USE_INTERRUPT_COUNTER
-void duk_heap_switch_thread(duk_heap *heap, duk_hthread *new_thr) {
-	/* Copy currently active interrupt counter from the active thread
-	 * back to the heap structure.  It doesn't need to be copied to
-	 * the target thread, as the bytecode executor does that when it
-	 * resumes execution for a new thread.
-	 */
-	if (heap->curr_thread != NULL) {
-		heap->interrupt_counter = heap->curr_thread->interrupt_counter;
+DUK_INTERNAL void duk_heap_switch_thread(duk_heap *heap, duk_hthread *new_thr) {
+	duk_hthread *curr_thr;
+
+	DUK_ASSERT(heap != NULL);
+
+	if (new_thr != NULL) {
+		curr_thr = heap->curr_thread;
+		if (curr_thr == NULL) {
+			/* For initial entry use default value; zero forces an
+			 * interrupt before executing the first insturction.
+			 */
+			DUK_DD(DUK_DDPRINT("switch thread, initial entry, init default interrupt counter"));
+			new_thr->interrupt_counter = 0;
+			new_thr->interrupt_init = 0;
+		} else {
+			/* Copy interrupt counter/init value state to new thread (if any).
+			 * It's OK for new_thr to be the same as curr_thr.
+			 */
+#if defined(DUK_USE_DEBUG)
+			if (new_thr != curr_thr) {
+				DUK_DD(DUK_DDPRINT("switch thread, not initial entry, copy interrupt counter"));
+			}
+#endif
+			new_thr->interrupt_counter = curr_thr->interrupt_counter;
+			new_thr->interrupt_init = curr_thr->interrupt_init;
+		}
+	} else {
+		DUK_DD(DUK_DDPRINT("switch thread, new thread is NULL, no interrupt counter changes"));
 	}
+
 	heap->curr_thread = new_thr;  /* may be NULL */
 }
 #endif  /* DUK_USE_INTERRUPT_COUNTER */
@@ -31620,7 +46170,7 @@ void duk_heap_switch_thread(duk_heap *heap, duk_hthread *new_thr) {
  *  Misc
  */
 
-static void duk__queue_refzero(duk_heap *heap, duk_heaphdr *hdr) {
+DUK_LOCAL void duk__queue_refzero(duk_heap *heap, duk_heaphdr *hdr) {
 	/* tail insert: don't disturb head in case refzero is running */
 
 	if (heap->refzero_list != NULL) {
@@ -31628,16 +46178,16 @@ static void duk__queue_refzero(duk_heap *heap, duk_heaphdr *hdr) {
 
 		hdr_prev = heap->refzero_list_tail;
 		DUK_ASSERT(hdr_prev != NULL);
-		DUK_ASSERT(DUK_HEAPHDR_GET_NEXT(hdr_prev) == NULL);
+		DUK_ASSERT(DUK_HEAPHDR_GET_NEXT(heap, hdr_prev) == NULL);
 
-		DUK_HEAPHDR_SET_NEXT(hdr, NULL);
-		DUK_HEAPHDR_SET_PREV(hdr, hdr_prev);
-		DUK_HEAPHDR_SET_NEXT(hdr_prev, hdr);
+		DUK_HEAPHDR_SET_NEXT(heap, hdr, NULL);
+		DUK_HEAPHDR_SET_PREV(heap, hdr, hdr_prev);
+		DUK_HEAPHDR_SET_NEXT(heap, hdr_prev, hdr);
 		heap->refzero_list_tail = hdr;
 	} else {
 		DUK_ASSERT(heap->refzero_list_tail == NULL);
-		DUK_HEAPHDR_SET_NEXT(hdr, NULL);
-		DUK_HEAPHDR_SET_PREV(hdr, NULL);
+		DUK_HEAPHDR_SET_NEXT(heap, hdr, NULL);
+		DUK_HEAPHDR_SET_PREV(heap, hdr, NULL);
 		heap->refzero_list = hdr;
 		heap->refzero_list_tail = hdr;
 	}
@@ -31657,7 +46207,7 @@ static void duk__queue_refzero(duk_heap *heap, duk_heaphdr *hdr) {
  *  later.  This eliminates C recursion.
  */
 
-static void duk__refcount_finalize_hobject(duk_hthread *thr, duk_hobject *h) {
+DUK_LOCAL void duk__refcount_finalize_hobject(duk_hthread *thr, duk_hobject *h) {
 	duk_uint_fast32_t i;
 
 	DUK_ASSERT(h);
@@ -31665,71 +46215,76 @@ static void duk__refcount_finalize_hobject(duk_hthread *thr, duk_hobject *h) {
 
 	/* XXX: better to get base and walk forwards? */
 
-	for (i = 0; i < (duk_uint_fast32_t) h->e_used; i++) {
-		duk_hstring *key = DUK_HOBJECT_E_GET_KEY(h, i);
+	for (i = 0; i < (duk_uint_fast32_t) DUK_HOBJECT_GET_ENEXT(h); i++) {
+		duk_hstring *key = DUK_HOBJECT_E_GET_KEY(thr->heap, h, i);
 		if (!key) {
 			continue;
 		}
-		duk_heap_heaphdr_decref(thr, (duk_heaphdr *) key);
-		if (DUK_HOBJECT_E_SLOT_IS_ACCESSOR(h, i)) {
-			duk_heap_heaphdr_decref(thr, (duk_heaphdr *) DUK_HOBJECT_E_GET_VALUE_GETTER(h, i));
-			duk_heap_heaphdr_decref(thr, (duk_heaphdr *) DUK_HOBJECT_E_GET_VALUE_SETTER(h, i));
+		duk_heaphdr_decref(thr, (duk_heaphdr *) key);
+		if (DUK_HOBJECT_E_SLOT_IS_ACCESSOR(thr->heap, h, i)) {
+			duk_heaphdr_decref_allownull(thr, (duk_heaphdr *) DUK_HOBJECT_E_GET_VALUE_GETTER(thr->heap, h, i));
+			duk_heaphdr_decref_allownull(thr, (duk_heaphdr *) DUK_HOBJECT_E_GET_VALUE_SETTER(thr->heap, h, i));
 		} else {
-			duk_heap_tval_decref(thr, DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(h, i));
+			duk_tval_decref(thr, DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, h, i));
 		}
 	}
 
-	for (i = 0; i < (duk_uint_fast32_t) h->a_size; i++) {
-		duk_heap_tval_decref(thr, DUK_HOBJECT_A_GET_VALUE_PTR(h, i));
+	for (i = 0; i < (duk_uint_fast32_t) DUK_HOBJECT_GET_ASIZE(h); i++) {
+		duk_tval_decref(thr, DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, h, i));
 	}
 
 	/* hash part is a 'weak reference' and does not contribute */
 
-	duk_heap_heaphdr_decref(thr, (duk_heaphdr *) h->prototype);
+	duk_heaphdr_decref_allownull(thr, (duk_heaphdr *) DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h));
 
 	if (DUK_HOBJECT_IS_COMPILEDFUNCTION(h)) {
 		duk_hcompiledfunction *f = (duk_hcompiledfunction *) h;
 		duk_tval *tv, *tv_end;
 		duk_hobject **funcs, **funcs_end;
 
-		DUK_ASSERT(f->data != NULL);  /* compiled functions must be created 'atomically' */
+		DUK_ASSERT(DUK_HCOMPILEDFUNCTION_GET_DATA(thr->heap, f) != NULL);  /* compiled functions must be created 'atomically' */
 
-		tv = DUK_HCOMPILEDFUNCTION_GET_CONSTS_BASE(f);
-		tv_end = DUK_HCOMPILEDFUNCTION_GET_CONSTS_END(f);
+		tv = DUK_HCOMPILEDFUNCTION_GET_CONSTS_BASE(thr->heap, f);
+		tv_end = DUK_HCOMPILEDFUNCTION_GET_CONSTS_END(thr->heap, f);
 		while (tv < tv_end) {
-			duk_heap_tval_decref(thr, tv);
+			duk_tval_decref(thr, tv);
 			tv++;
 		}
 
-		funcs = DUK_HCOMPILEDFUNCTION_GET_FUNCS_BASE(f);
-		funcs_end = DUK_HCOMPILEDFUNCTION_GET_FUNCS_END(f);
+		funcs = DUK_HCOMPILEDFUNCTION_GET_FUNCS_BASE(thr->heap, f);
+		funcs_end = DUK_HCOMPILEDFUNCTION_GET_FUNCS_END(thr->heap, f);
 		while (funcs < funcs_end) {
-			duk_heap_heaphdr_decref(thr, (duk_heaphdr *) *funcs);
+			duk_heaphdr_decref(thr, (duk_heaphdr *) *funcs);
 			funcs++;
 		}
 
-		duk_heap_heaphdr_decref(thr, (duk_heaphdr *) f->data);
+		duk_heaphdr_decref(thr, (duk_heaphdr *) DUK_HCOMPILEDFUNCTION_GET_DATA(thr->heap, f));
 	} else if (DUK_HOBJECT_IS_NATIVEFUNCTION(h)) {
 		duk_hnativefunction *f = (duk_hnativefunction *) h;
 		DUK_UNREF(f);
 		/* nothing to finalize */
+	} else if (DUK_HOBJECT_IS_BUFFEROBJECT(h)) {
+		duk_hbufferobject *b = (duk_hbufferobject *) h;
+		if (b->buf) {
+			duk_heaphdr_decref(thr, (duk_heaphdr *) b->buf);
+		}
 	} else if (DUK_HOBJECT_IS_THREAD(h)) {
 		duk_hthread *t = (duk_hthread *) h;
 		duk_tval *tv;
 
 		tv = t->valstack;
-		while (tv < t->valstack_end) {
-			duk_heap_tval_decref(thr, tv);
+		while (tv < t->valstack_top) {
+			duk_tval_decref(thr, tv);
 			tv++;
 		}
 
 		for (i = 0; i < (duk_uint_fast32_t) t->callstack_top; i++) {
 			duk_activation *act = t->callstack + i;
-			duk_heap_heaphdr_decref(thr, (duk_heaphdr *) act->func);
-			duk_heap_heaphdr_decref(thr, (duk_heaphdr *) act->var_env);
-			duk_heap_heaphdr_decref(thr, (duk_heaphdr *) act->lex_env);
+			duk_heaphdr_decref_allownull(thr, (duk_heaphdr *) DUK_ACT_GET_FUNC(act));
+			duk_heaphdr_decref_allownull(thr, (duk_heaphdr *) act->var_env);
+			duk_heaphdr_decref_allownull(thr, (duk_heaphdr *) act->lex_env);
 #ifdef DUK_USE_NONSTD_FUNC_CALLER_PROPERTY
-			duk_heap_heaphdr_decref(thr, (duk_heaphdr *) act->prev_caller);
+			duk_heaphdr_decref_allownull(thr, (duk_heaphdr *) act->prev_caller);
 #endif
 		}
 
@@ -31740,14 +46295,14 @@ static void duk__refcount_finalize_hobject(duk_hthread *thr, duk_hobject *h) {
 #endif
 
 		for (i = 0; i < DUK_NUM_BUILTINS; i++) {
-			duk_heap_heaphdr_decref(thr, (duk_heaphdr *) t->builtins[i]);
+			duk_heaphdr_decref_allownull(thr, (duk_heaphdr *) t->builtins[i]);
 		}
 
-		duk_heap_heaphdr_decref(thr, (duk_heaphdr *) t->resumer);
+		duk_heaphdr_decref_allownull(thr, (duk_heaphdr *) t->resumer);
 	}
 }
 
-void duk_heap_refcount_finalize_heaphdr(duk_hthread *thr, duk_heaphdr *hdr) {
+DUK_INTERNAL void duk_heaphdr_refcount_finalize(duk_hthread *thr, duk_heaphdr *hdr) {
 	DUK_ASSERT(hdr);
 
 	switch ((int) DUK_HEAPHDR_GET_TYPE(hdr)) {
@@ -31764,6 +46319,60 @@ void duk_heap_refcount_finalize_heaphdr(duk_hthread *thr, duk_heaphdr *hdr) {
 	}
 }
 
+#if defined(DUK_USE_REFZERO_FINALIZER_TORTURE)
+DUK_LOCAL duk_ret_t duk__refcount_fake_finalizer(duk_context *ctx) {
+	DUK_UNREF(ctx);
+	DUK_D(DUK_DPRINT("fake refcount torture finalizer executed"));
+#if 0
+	DUK_DD(DUK_DDPRINT("fake torture finalizer for: %!T", duk_get_tval(ctx, 0)));
+#endif
+	/* Require a lot of stack to force a value stack grow/shrink. */
+	duk_require_stack(ctx, 100000);
+
+	/* XXX: do something to force a callstack grow/shrink, perhaps
+	 * just a manual forced resize?
+	 */
+	return 0;
+}
+
+DUK_LOCAL void duk__refcount_run_torture_finalizer(duk_hthread *thr, duk_hobject *obj) {
+	duk_context *ctx;
+	duk_int_t rc;
+
+	DUK_ASSERT(thr != NULL);
+	DUK_ASSERT(obj != NULL);
+	ctx = (duk_context *) thr;
+
+	/* Avoid fake finalization for the duk__refcount_fake_finalizer function
+	 * itself, otherwise we're in infinite recursion.
+	 */
+	if (DUK_HOBJECT_HAS_NATIVEFUNCTION(obj)) {
+		if (((duk_hnativefunction *) obj)->func == duk__refcount_fake_finalizer) {
+			DUK_DD(DUK_DDPRINT("avoid fake torture finalizer for duk__refcount_fake_finalizer itself"));
+			return;
+		}
+	}
+	/* Avoid fake finalization when callstack limit has been reached.
+	 * Otherwise a callstack limit error will be created, then refzero'ed,
+	 * and we're in an infinite loop.
+	 */
+	if (thr->heap->call_recursion_depth >= thr->heap->call_recursion_limit ||
+	    thr->callstack_size + 2 * DUK_CALLSTACK_GROW_STEP >= thr->callstack_max /*approximate*/) {
+		DUK_D(DUK_DPRINT("call recursion depth reached, avoid fake torture finalizer"));
+		return;
+	}
+
+	/* Run fake finalizer.  Avoid creating new refzero queue entries
+	 * so that we are not forced into a forever loop.
+	 */
+	duk_push_c_function(ctx, duk__refcount_fake_finalizer, 1 /*nargs*/);
+	duk_push_hobject(ctx, obj);
+	rc = duk_pcall(ctx, 1);
+	DUK_UNREF(rc);  /* ignored */
+	duk_pop(ctx);
+}
+#endif  /* DUK_USE_REFZERO_FINALIZER_TORTURE */
+
 /*
  *  Refcount memory freeing loop.
  *
@@ -31775,7 +46384,7 @@ void duk_heap_refcount_finalize_heaphdr(duk_hthread *thr, duk_heaphdr *hdr) {
  *  early and resume at a future alloc/decref/refzero.
  */
 
-static void duk__refzero_free_pending(duk_hthread *thr) {
+DUK_LOCAL void duk__refzero_free_pending(duk_hthread *thr) {
 	duk_heaphdr *h1, *h2;
 	duk_heap *heap;
 	duk_int_t count = 0;
@@ -31810,9 +46419,23 @@ static void duk__refzero_free_pending(duk_hthread *thr) {
 		h1 = heap->refzero_list;
 		obj = (duk_hobject *) h1;
 		DUK_DD(DUK_DDPRINT("refzero processing %p: %!O", (void *) h1, (duk_heaphdr *) h1));
-		DUK_ASSERT(DUK_HEAPHDR_GET_PREV(h1) == NULL);
+		DUK_ASSERT(DUK_HEAPHDR_GET_PREV(heap, h1) == NULL);
 		DUK_ASSERT(DUK_HEAPHDR_GET_TYPE(h1) == DUK_HTYPE_OBJECT);  /* currently, always the case */
 
+#if defined(DUK_USE_REFZERO_FINALIZER_TORTURE)
+		/* Torture option to shake out finalizer side effect issues:
+		 * make a bogus function call for every finalizable object,
+		 * essentially simulating the case where everything has a
+		 * finalizer.
+		 */
+		DUK_DD(DUK_DDPRINT("refzero torture enabled, fake finalizer"));
+		DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT(h1) == 0);
+		DUK_HEAPHDR_PREINC_REFCOUNT(h1);  /* bump refcount to prevent refzero during finalizer processing */
+		duk__refcount_run_torture_finalizer(thr, obj);  /* must never longjmp */
+		DUK_HEAPHDR_PREDEC_REFCOUNT(h1);  /* remove artificial bump */
+		DUK_ASSERT_DISABLE(h1->h_refcount >= 0);  /* refcount is unsigned, so always true */
+#endif
+
 		/*
 		 *  Finalizer check.
 		 *
@@ -31824,10 +46447,9 @@ static void duk__refzero_free_pending(duk_hthread *thr) {
 		 *  objects and must be safe (not throw any errors, ever).
 		 */
 
-		/* FIXME: If object has FINALIZED, it was finalized by mark-and-sweep on
-		 * its previous run.  Any point in running finalizer again here?  If
-		 * finalization semantics is changed so that finalizer is only run once,
-		 * checking for FINALIZED would happen here.
+		/* An object may have FINALIZED here if it was finalized by mark-and-sweep
+		 * on a previous run and refcount then decreased to zero.  We won't run the
+		 * finalizer again here.
 		 */
 
 		/* A finalizer is looked up from the object and up its prototype chain
@@ -31836,15 +46458,16 @@ static void duk__refzero_free_pending(duk_hthread *thr) {
 		if (duk_hobject_hasprop_raw(thr, obj, DUK_HTHREAD_STRING_INT_FINALIZER(thr))) {
 			DUK_DDD(DUK_DDDPRINT("object has a finalizer, run it"));
 
-			DUK_ASSERT(h1->h_refcount == 0);
-			h1->h_refcount++;  /* bump refcount to prevent refzero during finalizer processing */
+			DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT(h1) == 0);
+			DUK_HEAPHDR_PREINC_REFCOUNT(h1);  /* bump refcount to prevent refzero during finalizer processing */
 
 			duk_hobject_run_finalizer(thr, obj);  /* must never longjmp */
+			DUK_ASSERT(DUK_HEAPHDR_HAS_FINALIZED(h1));  /* duk_hobject_run_finalizer() sets */
 
-			h1->h_refcount--;  /* remove artificial bump */
+			DUK_HEAPHDR_PREDEC_REFCOUNT(h1);  /* remove artificial bump */
 			DUK_ASSERT_DISABLE(h1->h_refcount >= 0);  /* refcount is unsigned, so always true */
 
-			if (h1->h_refcount != 0) {
+			if (DUK_HEAPHDR_GET_REFCOUNT(h1) != 0) {
 				DUK_DDD(DUK_DDDPRINT("-> object refcount after finalization non-zero, object will be rescued"));
 				rescued = 1;
 			} else {
@@ -31852,7 +46475,7 @@ static void duk__refzero_free_pending(duk_hthread *thr) {
 			}
 		}
 
-  		/* Refzero head is still the same.  This is the case even if finalizer
+		/* Refzero head is still the same.  This is the case even if finalizer
 		 * inserted more refzero objects; they are inserted to the tail.
 		 */
 		DUK_ASSERT(h1 == heap->refzero_list);
@@ -31864,9 +46487,9 @@ static void duk__refzero_free_pending(duk_hthread *thr) {
 		 *  to traverse a complete refzero_list.
 		 */
 
-		h2 = DUK_HEAPHDR_GET_NEXT(h1);
+		h2 = DUK_HEAPHDR_GET_NEXT(heap, h1);
 		if (h2) {
-			DUK_HEAPHDR_SET_PREV(h2, NULL);  /* not strictly necessary */
+			DUK_HEAPHDR_SET_PREV(heap, h2, NULL);  /* not strictly necessary */
 			heap->refzero_list = h2;
 		} else {
 			heap->refzero_list = NULL;
@@ -31880,8 +46503,11 @@ static void duk__refzero_free_pending(duk_hthread *thr) {
 		if (rescued) {
 			/* yes -> move back to heap allocated */
 			DUK_DD(DUK_DDPRINT("object rescued during refcount finalization: %p", (void *) h1));
-			DUK_HEAPHDR_SET_PREV(h1, NULL);
-			DUK_HEAPHDR_SET_NEXT(h1, heap->heap_allocated);
+			DUK_ASSERT(!DUK_HEAPHDR_HAS_FINALIZABLE(h1));
+			DUK_ASSERT(DUK_HEAPHDR_HAS_FINALIZED(h1));
+			DUK_HEAPHDR_CLEAR_FINALIZED(h1);
+			DUK_HEAPHDR_SET_PREV(heap, h1, NULL);
+			DUK_HEAPHDR_SET_NEXT(heap, h1, heap->heap_allocated);
 			heap->heap_allocated = h1;
 		} else {
 			/* no -> decref members, then free */
@@ -31921,111 +46547,37 @@ static void duk__refzero_free_pending(duk_hthread *thr) {
  *
  *  Decref may trigger immediate refzero handling, which may free and finalize
  *  an arbitrary number of objects.
- *  
+ *
  */
 
-void duk_heap_tval_incref(duk_tval *tv) {
-#if 0
-	DUK_DDD(DUK_DDDPRINT("tval incref %p (%ld->%ld): %!T",
-	                     (void *) tv,
-	                     (tv != NULL && DUK_TVAL_IS_HEAP_ALLOCATED(tv) ? (long) DUK_TVAL_GET_HEAPHDR(tv)->h_refcount : (long) 0),
-	                     (tv != NULL && DUK_TVAL_IS_HEAP_ALLOCATED(tv) ? (long) (DUK_TVAL_GET_HEAPHDR(tv)->h_refcount + 1) : (long) 0),
-	                     (duk_tval *) tv));
-#endif
-
-	if (!tv) {
-		return;
-	}
-
-	if (DUK_TVAL_IS_HEAP_ALLOCATED(tv)) {
-		duk_heaphdr *h = DUK_TVAL_GET_HEAPHDR(tv);
-		if (h) {
-			DUK_ASSERT(DUK_HEAPHDR_HTYPE_VALID(h));
-			DUK_ASSERT_DISABLE(h->h_refcount >= 0);
-			h->h_refcount++;
-		}
-	}
-}
-
-void duk_heap_tval_decref(duk_hthread *thr, duk_tval *tv) {
-#if 0
-	DUK_DDD(DUK_DDDPRINT("tval decref %p (%ld->%ld): %!T",
-	                     (void *) tv,
-	                     (tv != NULL && DUK_TVAL_IS_HEAP_ALLOCATED(tv) ? (long) DUK_TVAL_GET_HEAPHDR(tv)->h_refcount : (long) 0),
-	                     (tv != NULL && DUK_TVAL_IS_HEAP_ALLOCATED(tv) ? (long) (DUK_TVAL_GET_HEAPHDR(tv)->h_refcount - 1) : (long) 0),
-	                     (duk_tval *) tv));
-#endif
-
-	if (!tv) {
-		return;
-	}
-
-	if (DUK_TVAL_IS_HEAP_ALLOCATED(tv)) {
-		duk_heap_heaphdr_decref(thr, DUK_TVAL_GET_HEAPHDR(tv));
-	}
-}
-
-void duk_heap_heaphdr_incref(duk_heaphdr *h) {
-#if 0
-	DUK_DDD(DUK_DDDPRINT("heaphdr incref %p (%ld->%ld): %!O",
-	                     (void *) h,
-	                     (h != NULL ? (long) h->h_refcount : (long) 0),
-	                     (h != NULL ? (long) (h->h_refcount + 1) : (long) 0),
-	                     (duk_heaphdr *) h));
-#endif
-
-	if (!h) {
-		return;
-	}
-	DUK_ASSERT(DUK_HEAPHDR_HTYPE_VALID(h));
-	DUK_ASSERT_DISABLE(h->h_refcount >= 0);
-
-	h->h_refcount++;
-}
-
-void duk_heap_heaphdr_decref(duk_hthread *thr, duk_heaphdr *h) {
+DUK_INTERNAL void duk_heaphdr_refzero(duk_hthread *thr, duk_heaphdr *h) {
 	duk_heap *heap;
 
-#if 0
-	DUK_DDD(DUK_DDDPRINT("heaphdr decref %p (%ld->%ld): %!O",
-	                     (void *) h,
-	                     (h != NULL ? (long) h->h_refcount : (long) 0),
-	                     (h != NULL ? (long) (h->h_refcount - 1) : (long) 0),
-	                     (duk_heaphdr *) h));
-#endif
-
 	DUK_ASSERT(thr != NULL);
-	DUK_ASSERT(thr->heap != NULL);
-
-	if (!h) {
-		return;
-	}
-	DUK_ASSERT(DUK_HEAPHDR_HTYPE_VALID(h));
-	DUK_ASSERT(h->h_refcount >= 1);
-
-	if (--h->h_refcount != 0) {
-		return;
-	}
+	DUK_ASSERT(h != NULL);
 
 	heap = thr->heap;
 	DUK_DDD(DUK_DDDPRINT("refzero %p: %!O", (void *) h, (duk_heaphdr *) h));
 
-#ifdef DUK_USE_MARK_AND_SWEEP
 	/*
 	 *  If mark-and-sweep is running, don't process 'refzero' situations at all.
 	 *  They may happen because mark-and-sweep needs to finalize refcounts for
 	 *  each object it sweeps.  Otherwise the target objects of swept objects
 	 *  would have incorrect refcounts.
 	 *
+	 *  This check must be enabled also when mark-and-sweep support has been
+	 *  disabled: the flag is also used in heap destruction when running
+	 *  finalizers for remaining objects, and the flag prevents objects from
+	 *  being moved around in heap linked lists.
+	 *
 	 *  Note: mark-and-sweep could use a separate decref handler to avoid coming
 	 *  here at all.  However, mark-and-sweep may also call finalizers, which
 	 *  can do arbitrary operations and would use this decref variant anyway.
 	 */
-	if (DUK_HEAP_HAS_MARKANDSWEEP_RUNNING(heap)) {
+	if (DUK_UNLIKELY(DUK_HEAP_HAS_MARKANDSWEEP_RUNNING(heap))) {
 		DUK_DDD(DUK_DDDPRINT("refzero handling suppressed when mark-and-sweep running, object: %p", (void *) h));
 		return;
 	}
-#endif
 
 	switch ((duk_small_int_t) DUK_HEAPHDR_GET_TYPE(h)) {
 	case DUK_HTYPE_STRING:
@@ -32069,6 +46621,115 @@ void duk_heap_heaphdr_decref(duk_hthread *thr, duk_heaphdr *h) {
 	}
 }
 
+#if !defined(DUK_USE_FAST_REFCOUNT_DEFAULT)
+DUK_INTERNAL void duk_tval_incref(duk_tval *tv) {
+	DUK_ASSERT(tv != NULL);
+
+	if (DUK_TVAL_IS_HEAP_ALLOCATED(tv)) {
+		duk_heaphdr *h = DUK_TVAL_GET_HEAPHDR(tv);
+		DUK_ASSERT(h != NULL);
+		DUK_ASSERT(DUK_HEAPHDR_HTYPE_VALID(h));
+		DUK_ASSERT_DISABLE(h->h_refcount >= 0);
+		DUK_HEAPHDR_PREINC_REFCOUNT(h);
+	}
+}
+#endif
+
+#if 0  /* unused */
+DUK_INTERNAL void duk_tval_incref_allownull(duk_tval *tv) {
+	if (tv == NULL) {
+		return;
+	}
+	if (DUK_TVAL_IS_HEAP_ALLOCATED(tv)) {
+		duk_heaphdr *h = DUK_TVAL_GET_HEAPHDR(tv);
+		DUK_ASSERT(h != NULL);
+		DUK_ASSERT(DUK_HEAPHDR_HTYPE_VALID(h));
+		DUK_ASSERT_DISABLE(h->h_refcount >= 0);
+		DUK_HEAPHDR_PREINC_REFCOUNT(h);
+	}
+}
+#endif
+
+DUK_INTERNAL void duk_tval_decref(duk_hthread *thr, duk_tval *tv) {
+	DUK_ASSERT(thr != NULL);
+	DUK_ASSERT(tv != NULL);
+
+	if (DUK_TVAL_IS_HEAP_ALLOCATED(tv)) {
+		duk_heaphdr *h = DUK_TVAL_GET_HEAPHDR(tv);
+		DUK_ASSERT(h != NULL);
+		DUK_ASSERT(DUK_HEAPHDR_HTYPE_VALID(h));
+		duk_heaphdr_decref(thr, h);
+	}
+}
+
+#if 0  /* unused */
+DUK_INTERNAL void duk_tval_decref_allownull(duk_hthread *thr, duk_tval *tv) {
+	DUK_ASSERT(thr != NULL);
+
+	if (tv == NULL) {
+		return;
+	}
+	if (DUK_TVAL_IS_HEAP_ALLOCATED(tv)) {
+		duk_heaphdr *h = DUK_TVAL_GET_HEAPHDR(tv);
+		DUK_ASSERT(h != NULL);
+		DUK_ASSERT(DUK_HEAPHDR_HTYPE_VALID(h));
+		duk_heaphdr_decref(thr, h);
+	}
+}
+#endif
+
+#if !defined(DUK_USE_FAST_REFCOUNT_DEFAULT)
+DUK_INTERNAL void duk_heaphdr_incref(duk_heaphdr *h) {
+	DUK_ASSERT(h != NULL);
+	DUK_ASSERT(DUK_HEAPHDR_HTYPE_VALID(h));
+	DUK_ASSERT_DISABLE(DUK_HEAPHDR_GET_REFCOUNT(h) >= 0);
+
+	DUK_HEAPHDR_PREINC_REFCOUNT(h);
+}
+#endif
+
+#if 0  /* unused */
+DUK_INTERNAL void duk_heaphdr_incref_allownull(duk_heaphdr *h) {
+	if (h == NULL) {
+		return;
+	}
+	DUK_ASSERT(DUK_HEAPHDR_HTYPE_VALID(h));
+	DUK_ASSERT_DISABLE(DUK_HEAPHDR_GET_REFCOUNT(h) >= 0);
+
+	DUK_HEAPHDR_PREINC_REFCOUNT(h);
+}
+#endif
+
+DUK_INTERNAL void duk_heaphdr_decref(duk_hthread *thr, duk_heaphdr *h) {
+	DUK_ASSERT(thr != NULL);
+	DUK_ASSERT(thr->heap != NULL);
+	DUK_ASSERT(h != NULL);
+	DUK_ASSERT(DUK_HEAPHDR_HTYPE_VALID(h));
+	DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT(h) >= 1);
+
+	if (DUK_HEAPHDR_PREDEC_REFCOUNT(h) != 0) {
+		return;
+	}
+	duk_heaphdr_refzero(thr, h);
+}
+
+DUK_INTERNAL void duk_heaphdr_decref_allownull(duk_hthread *thr, duk_heaphdr *h) {
+	DUK_ASSERT(thr != NULL);
+	DUK_ASSERT(thr->heap != NULL);
+
+	if (h == NULL) {
+		return;
+	}
+
+	DUK_ASSERT(DUK_HEAPHDR_HTYPE_VALID(h));
+	DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT(h) >= 1);
+
+	if (DUK_HEAPHDR_PREDEC_REFCOUNT(h) != 0) {
+		return;
+	}
+	duk_heaphdr_refzero(thr, h);
+}
+
 #else
 
 /* no refcounting */
@@ -32094,7 +46755,7 @@ void duk_heap_heaphdr_decref(duk_hthread *thr, duk_heaphdr *h) {
  *  object is about to be freed, such references need to be removed.
  */
 
-void duk_heap_strcache_string_remove(duk_heap *heap, duk_hstring *h) {
+DUK_INTERNAL void duk_heap_strcache_string_remove(duk_heap *heap, duk_hstring *h) {
 	duk_small_int_t i;
 	for (i = 0; i < DUK_HEAP_STRCACHE_SIZE; i++) {
 		duk_strcache *c = heap->strcache + i;
@@ -32113,9 +46774,13 @@ void duk_heap_strcache_string_remove(duk_heap *heap, duk_hstring *h) {
 
 /*
  *  String scanning helpers
+ *
+ *  All bytes other than UTF-8 continuation bytes ([0x80,0xbf]) are
+ *  considered to contribute a character.  This must match how string
+ *  character length is computed.
  */
 
-static duk_uint8_t *duk__scan_forwards(duk_uint8_t *p, duk_uint8_t *q, duk_uint_fast32_t n) {
+DUK_LOCAL const duk_uint8_t *duk__scan_forwards(const duk_uint8_t *p, const duk_uint8_t *q, duk_uint_fast32_t n) {
 	while (n > 0) {
 		for (;;) {
 			p++;
@@ -32131,7 +46796,7 @@ static duk_uint8_t *duk__scan_forwards(duk_uint8_t *p, duk_uint8_t *q, duk_uint_
 	return p;
 }
 
-static duk_uint8_t *duk__scan_backwards(duk_uint8_t *p, duk_uint8_t *q, duk_uint_fast32_t n) {
+DUK_LOCAL const duk_uint8_t *duk__scan_backwards(const duk_uint8_t *p, const duk_uint8_t *q, duk_uint_fast32_t n) {
 	while (n > 0) {
 		for (;;) {
 			p--;
@@ -32159,16 +46824,16 @@ static duk_uint8_t *duk__scan_backwards(duk_uint8_t *p, duk_uint8_t *q, duk_uint
  *  Better typing might be to use duk_size_t.
  */
 
-duk_uint_fast32_t duk_heap_strcache_offset_char2byte(duk_hthread *thr, duk_hstring *h, duk_uint_fast32_t char_offset) {
+DUK_INTERNAL duk_uint_fast32_t duk_heap_strcache_offset_char2byte(duk_hthread *thr, duk_hstring *h, duk_uint_fast32_t char_offset) {
 	duk_heap *heap;
 	duk_strcache *sce;
 	duk_uint_fast32_t byte_offset;
 	duk_small_int_t i;
 	duk_bool_t use_cache;
 	duk_uint_fast32_t dist_start, dist_end, dist_sce;
-	duk_uint8_t *p_start;
-	duk_uint8_t *p_end;
-	duk_uint8_t *p_found;
+	const duk_uint8_t *p_start;
+	const duk_uint8_t *p_end;
+	const duk_uint8_t *p_found;
 
 	if (char_offset > DUK_HSTRING_GET_CHARLEN(h)) {
 		goto error;
@@ -32235,8 +46900,8 @@ duk_uint_fast32_t duk_heap_strcache_offset_char2byte(duk_hthread *thr, duk_hstri
 	dist_end = DUK_HSTRING_GET_CHARLEN(h) - char_offset;
 	dist_sce = 0; DUK_UNREF(dist_sce);  /* initialize for debug prints, needed if sce==NULL */
 
-	p_start = (duk_uint8_t *) DUK_HSTRING_GET_DATA(h);
-	p_end = (duk_uint8_t *) (p_start + DUK_HSTRING_GET_BYTELEN(h));
+	p_start = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h);
+	p_end = (const duk_uint8_t *) (p_start + DUK_HSTRING_GET_BYTELEN(h));
 	p_found = NULL;
 
 	if (sce) {
@@ -32324,7 +46989,7 @@ duk_uint_fast32_t duk_heap_strcache_offset_char2byte(duk_hthread *thr, duk_hstri
 	 *  Update cache entry (allocating if necessary), and move the
 	 *  cache entry to the first place (in an "LRU" policy).
 	 */
-	
+
 	if (use_cache) {
 		/* update entry, allocating if necessary */
 		if (!sce) {
@@ -32347,7 +47012,7 @@ duk_uint_fast32_t duk_heap_strcache_offset_char2byte(duk_hthread *thr, duk_hstri
 
 			tmp = *sce;
 			DUK_MEMMOVE((void *) (&heap->strcache[1]),
-			            (void *) (&heap->strcache[0]),
+			            (const void *) (&heap->strcache[0]),
 			            (size_t) (((char *) sce) - ((char *) &heap->strcache[0])));
 			heap->strcache[0] = tmp;
 
@@ -32376,9 +47041,11 @@ duk_uint_fast32_t duk_heap_strcache_offset_char2byte(duk_hthread *thr, duk_hstri
 
 /* include removed: duk_internal.h */
 
+#if defined(DUK_USE_STRTAB_PROBE)
 #define DUK__HASH_INITIAL(hash,h_size)        DUK_STRTAB_HASH_INITIAL((hash),(h_size))
 #define DUK__HASH_PROBE_STEP(hash)            DUK_STRTAB_HASH_PROBE_STEP((hash))
 #define DUK__DELETED_MARKER(heap)             DUK_STRTAB_DELETED_MARKER((heap))
+#endif
 
 /*
  *  Create a hstring and insert into the heap.  The created object
@@ -32389,96 +47056,502 @@ duk_uint_fast32_t duk_heap_strcache_offset_char2byte(duk_hthread *thr, duk_hstri
  *  is lost.
  */
 
-static duk_hstring *duk__alloc_init_hstring(duk_heap *heap,
-                                            duk_uint8_t *str,
-                                            duk_uint32_t blen,
-                                            duk_uint32_t strhash) {
+DUK_LOCAL
+duk_hstring *duk__alloc_init_hstring(duk_heap *heap,
+                                     const duk_uint8_t *str,
+                                     duk_uint32_t blen,
+                                     duk_uint32_t strhash,
+                                     const duk_uint8_t *extdata) {
 	duk_hstring *res = NULL;
 	duk_uint8_t *data;
 	duk_size_t alloc_size;
 	duk_uarridx_t dummy;
+	duk_uint32_t clen;
 
-	/* NUL terminate for convenient C access */
-
-	alloc_size = (duk_size_t) (sizeof(duk_hstring) + blen + 1);
-	res = (duk_hstring *) DUK_ALLOC(heap, alloc_size);
-	if (!res) {
-		goto error;
+#if defined(DUK_USE_STRLEN16)
+	/* If blen <= 0xffffUL, clen is also guaranteed to be <= 0xffffUL. */
+	if (blen > 0xffffUL) {
+		DUK_D(DUK_DPRINT("16-bit string blen/clen active and blen over 16 bits, reject intern"));
+		return NULL;
 	}
+#endif
 
-	DUK_MEMZERO(res, sizeof(duk_hstring));
+	if (extdata) {
+		alloc_size = (duk_size_t) sizeof(duk_hstring_external);
+		res = (duk_hstring *) DUK_ALLOC(heap, alloc_size);
+		if (!res) {
+			goto alloc_error;
+		}
+		DUK_MEMZERO(res, sizeof(duk_hstring_external));
 #ifdef DUK_USE_EXPLICIT_NULL_INIT
-	DUK_HEAPHDR_STRING_INIT_NULLS(&res->hdr);
+		DUK_HEAPHDR_STRING_INIT_NULLS(&res->hdr);
 #endif
-	DUK_HEAPHDR_SET_TYPE_AND_FLAGS(&res->hdr, DUK_HTYPE_STRING, 0);
+		DUK_HEAPHDR_SET_TYPE_AND_FLAGS(&res->hdr, DUK_HTYPE_STRING, DUK_HSTRING_FLAG_EXTDATA);
+
+		((duk_hstring_external *) res)->extdata = extdata;
+	} else {
+		/* NUL terminate for convenient C access */
+		alloc_size = (duk_size_t) (sizeof(duk_hstring) + blen + 1);
+		res = (duk_hstring *) DUK_ALLOC(heap, alloc_size);
+		if (!res) {
+			goto alloc_error;
+		}
+		DUK_MEMZERO(res, sizeof(duk_hstring));
+#ifdef DUK_USE_EXPLICIT_NULL_INIT
+		DUK_HEAPHDR_STRING_INIT_NULLS(&res->hdr);
+#endif
+		DUK_HEAPHDR_SET_TYPE_AND_FLAGS(&res->hdr, DUK_HTYPE_STRING, 0);
+
+		data = (duk_uint8_t *) (res + 1);
+		DUK_MEMCPY(data, str, blen);
+		data[blen] = (duk_uint8_t) 0;
+	}
 
 	if (duk_js_to_arrayindex_raw_string(str, blen, &dummy)) {
 		DUK_HSTRING_SET_ARRIDX(res);
 	}
 
-	res->hash = strhash;
-	res->blen = blen;
-	res->clen = (duk_uint32_t) duk_unicode_unvalidated_utf8_length(str, (duk_size_t) blen);  /* clen <= blen */
+	/* All strings beginning with 0xff are treated as "internal",
+	 * even strings interned by the user.  This allows user code to
+	 * create internal properties too, and makes behavior consistent
+	 * in case user code happens to use a string also used by Duktape
+	 * (such as string has already been interned and has the 'internal'
+	 * flag set).
+	 */
+	if (blen > 0 && str[0] == (duk_uint8_t) 0xff) {
+		DUK_HSTRING_SET_INTERNAL(res);
+	}
 
-	data = (duk_uint8_t *) (res + 1);
-	DUK_MEMCPY(data, str, blen);
-	data[blen] = (duk_uint8_t) 0;
+	DUK_HSTRING_SET_HASH(res, strhash);
+	DUK_HSTRING_SET_BYTELEN(res, blen);
+	clen = (duk_uint32_t) duk_unicode_unvalidated_utf8_length(str, (duk_size_t) blen);
+	DUK_ASSERT(clen <= blen);
+	DUK_HSTRING_SET_CHARLEN(res, clen);
 
-	DUK_DDD(DUK_DDDPRINT("interned string, hash=0x%08lx, blen=%ld, clen=%ld, has_arridx=%ld",
+	DUK_DDD(DUK_DDDPRINT("interned string, hash=0x%08lx, blen=%ld, clen=%ld, has_arridx=%ld, has_extdata=%ld",
 	                     (unsigned long) DUK_HSTRING_GET_HASH(res),
 	                     (long) DUK_HSTRING_GET_BYTELEN(res),
 	                     (long) DUK_HSTRING_GET_CHARLEN(res),
-	                     (long) DUK_HSTRING_HAS_ARRIDX(res) ? 1 : 0));
+	                     (long) DUK_HSTRING_HAS_ARRIDX(res) ? 1 : 0,
+	                     (long) DUK_HSTRING_HAS_EXTDATA(res) ? 1 : 0));
 
 	return res;
 
- error:
+ alloc_error:
 	DUK_FREE(heap, res);
 	return NULL;
 }
 
 /*
- *  Count actually used (non-NULL, non-DELETED) entries
+ *  String table algorithm: fixed size string table with array chaining
+ *
+ *  The top level string table has a fixed size, with each slot holding
+ *  either NULL, string pointer, or pointer to a separately allocated
+ *  string pointer list.
+ *
+ *  This is good for low memory environments using a pool allocator: the
+ *  top level allocation has a fixed size and the pointer lists have quite
+ *  small allocation size, which further matches the typical pool sizes
+ *  needed by objects, strings, property tables, etc.
  */
 
-static duk_int_t duk__count_used(duk_heap *heap) {
+#if defined(DUK_USE_STRTAB_CHAIN)
+
+#if defined(DUK_USE_HEAPPTR16)
+DUK_LOCAL duk_bool_t duk__insert_hstring_chain(duk_heap *heap, duk_hstring *h) {
+	duk_small_uint_t slotidx;
+	duk_strtab_entry *e;
+	duk_uint16_t *lst;
+	duk_uint16_t *new_lst;
+	duk_size_t i, n;
+	duk_uint16_t null16 = heap->heapptr_null16;
+	duk_uint16_t h16 = DUK_USE_HEAPPTR_ENC16(heap->heap_udata, (void *) h);
+
+	DUK_ASSERT(heap != NULL);
+	DUK_ASSERT(h != NULL);
+
+	slotidx = DUK_HSTRING_GET_HASH(h) % DUK_STRTAB_CHAIN_SIZE;
+	DUK_ASSERT(slotidx < DUK_STRTAB_CHAIN_SIZE);
+
+	e = heap->strtable + slotidx;
+	if (e->listlen == 0) {
+		if (e->u.str16 == null16) {
+			e->u.str16 = h16;
+		} else {
+			/* Now two entries in the same slot, alloc list */
+			lst = (duk_uint16_t *) DUK_ALLOC(heap, sizeof(duk_uint16_t) * 2);
+			if (lst == NULL) {
+				return 1;  /* fail */
+			}
+			lst[0] = e->u.str16;
+			lst[1] = h16;
+			e->u.strlist16 = DUK_USE_HEAPPTR_ENC16(heap->heap_udata, (void *) lst);
+			e->listlen = 2;
+		}
+	} else {
+		DUK_ASSERT(e->u.strlist16 != null16);
+		lst = (duk_uint16_t *) DUK_USE_HEAPPTR_DEC16(heap->heap_udata, e->u.strlist16);
+		DUK_ASSERT(lst != NULL);
+		for (i = 0, n = e->listlen; i < n; i++) {
+			if (lst[i] == null16) {
+				lst[i] = h16;
+				return 0;
+			}
+		}
+
+		if (e->listlen + 1 == 0) {
+			/* Overflow, relevant mainly when listlen is 16 bits. */
+			return 1;  /* fail */
+		}
+
+		new_lst = (duk_uint16_t *) DUK_REALLOC(heap, lst, sizeof(duk_uint16_t) * (e->listlen + 1));
+		if (new_lst == NULL) {
+			return 1;  /* fail */
+		}
+		new_lst[e->listlen++] = h16;
+		e->u.strlist16 = DUK_USE_HEAPPTR_ENC16(heap->heap_udata, (void *) new_lst);
+	}
+	return 0;
+}
+#else  /* DUK_USE_HEAPPTR16 */
+DUK_LOCAL duk_bool_t duk__insert_hstring_chain(duk_heap *heap, duk_hstring *h) {
+	duk_small_uint_t slotidx;
+	duk_strtab_entry *e;
+	duk_hstring **lst;
+	duk_hstring **new_lst;
+	duk_size_t i, n;
+
+	DUK_ASSERT(heap != NULL);
+	DUK_ASSERT(h != NULL);
+
+	slotidx = DUK_HSTRING_GET_HASH(h) % DUK_STRTAB_CHAIN_SIZE;
+	DUK_ASSERT(slotidx < DUK_STRTAB_CHAIN_SIZE);
+
+	e = heap->strtable + slotidx;
+	if (e->listlen == 0) {
+		if (e->u.str == NULL) {
+			e->u.str = h;
+		} else {
+			/* Now two entries in the same slot, alloc list */
+			lst = (duk_hstring **) DUK_ALLOC(heap, sizeof(duk_hstring *) * 2);
+			if (lst == NULL) {
+				return 1;  /* fail */
+			}
+			lst[0] = e->u.str;
+			lst[1] = h;
+			e->u.strlist = lst;
+			e->listlen = 2;
+		}
+	} else {
+		DUK_ASSERT(e->u.strlist != NULL);
+		lst = e->u.strlist;
+		for (i = 0, n = e->listlen; i < n; i++) {
+			if (lst[i] == NULL) {
+				lst[i] = h;
+				return 0;
+			}
+		}
+
+		if (e->listlen + 1 == 0) {
+			/* Overflow, relevant mainly when listlen is 16 bits. */
+			return 1;  /* fail */
+		}
+
+		new_lst = (duk_hstring **) DUK_REALLOC(heap, e->u.strlist, sizeof(duk_hstring *) * (e->listlen + 1));
+		if (new_lst == NULL) {
+			return 1;  /* fail */
+		}
+		new_lst[e->listlen++] = h;
+		e->u.strlist = new_lst;
+	}
+	return 0;
+}
+#endif  /* DUK_USE_HEAPPTR16 */
+
+#if defined(DUK_USE_HEAPPTR16)
+DUK_LOCAL duk_hstring *duk__find_matching_string_chain(duk_heap *heap, const duk_uint8_t *str, duk_uint32_t blen, duk_uint32_t strhash) {
+	duk_small_uint_t slotidx;
+	duk_strtab_entry *e;
+	duk_uint16_t *lst;
+	duk_size_t i, n;
+	duk_uint16_t null16 = heap->heapptr_null16;
+
+	DUK_ASSERT(heap != NULL);
+
+	slotidx = strhash % DUK_STRTAB_CHAIN_SIZE;
+	DUK_ASSERT(slotidx < DUK_STRTAB_CHAIN_SIZE);
+
+	e = heap->strtable + slotidx;
+	if (e->listlen == 0) {
+		if (e->u.str16 != null16) {
+			duk_hstring *h = (duk_hstring *) DUK_USE_HEAPPTR_DEC16(heap->heap_udata, e->u.str16);
+			DUK_ASSERT(h != NULL);
+			if (DUK_HSTRING_GET_BYTELEN(h) == blen &&
+			    DUK_MEMCMP((const void *) str, (const void *) DUK_HSTRING_GET_DATA(h), (size_t) blen) == 0) {
+				return h;
+			}
+		}
+	} else {
+		DUK_ASSERT(e->u.strlist16 != null16);
+		lst = (duk_uint16_t *) DUK_USE_HEAPPTR_DEC16(heap->heap_udata, e->u.strlist16);
+		DUK_ASSERT(lst != NULL);
+		for (i = 0, n = e->listlen; i < n; i++) {
+			if (lst[i] != null16) {
+				duk_hstring *h = (duk_hstring *) DUK_USE_HEAPPTR_DEC16(heap->heap_udata, lst[i]);
+				DUK_ASSERT(h != NULL);
+				if (DUK_HSTRING_GET_BYTELEN(h) == blen &&
+				    DUK_MEMCMP((const void *) str, (const void *) DUK_HSTRING_GET_DATA(h), (size_t) blen) == 0) {
+					return h;
+				}
+			}
+		}
+	}
+
+	return NULL;
+}
+#else  /* DUK_USE_HEAPPTR16 */
+DUK_LOCAL duk_hstring *duk__find_matching_string_chain(duk_heap *heap, const duk_uint8_t *str, duk_uint32_t blen, duk_uint32_t strhash) {
+	duk_small_uint_t slotidx;
+	duk_strtab_entry *e;
+	duk_hstring **lst;
+	duk_size_t i, n;
+
+	DUK_ASSERT(heap != NULL);
+
+	slotidx = strhash % DUK_STRTAB_CHAIN_SIZE;
+	DUK_ASSERT(slotidx < DUK_STRTAB_CHAIN_SIZE);
+
+	e = heap->strtable + slotidx;
+	if (e->listlen == 0) {
+		if (e->u.str != NULL &&
+	           DUK_HSTRING_GET_BYTELEN(e->u.str) == blen &&
+	           DUK_MEMCMP((const void *) str, (const void *) DUK_HSTRING_GET_DATA(e->u.str), (size_t) blen) == 0) {
+			return e->u.str;
+		}
+	} else {
+		DUK_ASSERT(e->u.strlist != NULL);
+		lst = e->u.strlist;
+		for (i = 0, n = e->listlen; i < n; i++) {
+			if (lst[i] != NULL &&
+		           DUK_HSTRING_GET_BYTELEN(lst[i]) == blen &&
+		           DUK_MEMCMP((const void *) str, (const void *) DUK_HSTRING_GET_DATA(lst[i]), (size_t) blen) == 0) {
+				return lst[i];
+			}
+		}
+	}
+
+	return NULL;
+}
+#endif  /* DUK_USE_HEAPPTR16 */
+
+#if defined(DUK_USE_HEAPPTR16)
+DUK_LOCAL void duk__remove_matching_hstring_chain(duk_heap *heap, duk_hstring *h) {
+	duk_small_uint_t slotidx;
+	duk_strtab_entry *e;
+	duk_uint16_t *lst;
+	duk_size_t i, n;
+	duk_uint16_t h16;
+	duk_uint16_t null16 = heap->heapptr_null16;
+
+	DUK_ASSERT(heap != NULL);
+	DUK_ASSERT(h != NULL);
+
+	slotidx = DUK_HSTRING_GET_HASH(h) % DUK_STRTAB_CHAIN_SIZE;
+	DUK_ASSERT(slotidx < DUK_STRTAB_CHAIN_SIZE);
+
+	DUK_ASSERT(h != NULL);
+	h16 = DUK_USE_HEAPPTR_ENC16(heap->heap_udata, (void *) h);
+
+	e = heap->strtable + slotidx;
+	if (e->listlen == 0) {
+		if (e->u.str16 == h16) {
+			e->u.str16 = null16;
+			return;
+		}
+	} else {
+		DUK_ASSERT(e->u.strlist16 != null16);
+		lst = (duk_uint16_t *) DUK_USE_HEAPPTR_DEC16(heap->heap_udata, e->u.strlist16);
+		DUK_ASSERT(lst != NULL);
+		for (i = 0, n = e->listlen; i < n; i++) {
+			if (lst[i] == h16) {
+				lst[i] = null16;
+				return;
+			}
+		}
+	}
+
+	DUK_D(DUK_DPRINT("failed to find string that should be in stringtable"));
+	DUK_UNREACHABLE();
+	return;
+}
+#else  /* DUK_USE_HEAPPTR16 */
+DUK_LOCAL void duk__remove_matching_hstring_chain(duk_heap *heap, duk_hstring *h) {
+	duk_small_uint_t slotidx;
+	duk_strtab_entry *e;
+	duk_hstring **lst;
+	duk_size_t i, n;
+
+	DUK_ASSERT(heap != NULL);
+	DUK_ASSERT(h != NULL);
+
+	slotidx = DUK_HSTRING_GET_HASH(h) % DUK_STRTAB_CHAIN_SIZE;
+	DUK_ASSERT(slotidx < DUK_STRTAB_CHAIN_SIZE);
+
+	e = heap->strtable + slotidx;
+	if (e->listlen == 0) {
+		DUK_ASSERT(h != NULL);
+		if (e->u.str == h) {
+			e->u.str = NULL;
+			return;
+		}
+	} else {
+		DUK_ASSERT(e->u.strlist != NULL);
+		lst = e->u.strlist;
+		for (i = 0, n = e->listlen; i < n; i++) {
+			DUK_ASSERT(h != NULL);
+			if (lst[i] == h) {
+				lst[i] = NULL;
+				return;
+			}
+		}
+	}
+
+	DUK_D(DUK_DPRINT("failed to find string that should be in stringtable"));
+	DUK_UNREACHABLE();
+	return;
+}
+#endif  /* DUK_USE_HEAPPTR16 */
+
+#if defined(DUK_USE_DEBUG)
+DUK_INTERNAL void duk_heap_dump_strtab(duk_heap *heap) {
+	duk_strtab_entry *e;
+	duk_small_uint_t i;
+	duk_size_t j, n, used;
+#if defined(DUK_USE_HEAPPTR16)
+	duk_uint16_t *lst;
+	duk_uint16_t null16 = heap->heapptr_null16;
+#else
+	duk_hstring **lst;
+#endif
+
+	DUK_ASSERT(heap != NULL);
+
+	for (i = 0; i < DUK_STRTAB_CHAIN_SIZE; i++) {
+		e = heap->strtable + i;
+
+		if (e->listlen == 0) {
+#if defined(DUK_USE_HEAPPTR16)
+			DUK_DD(DUK_DDPRINT("[%03d] -> plain %d", (int) i, (int) (e->u.str16 != null16 ? 1 : 0)));
+#else
+			DUK_DD(DUK_DDPRINT("[%03d] -> plain %d", (int) i, (int) (e->u.str ? 1 : 0)));
+#endif
+		} else {
+			used = 0;
+#if defined(DUK_USE_HEAPPTR16)
+			lst = (duk_uint16_t *) DUK_USE_HEAPPTR_DEC16(heap->heap_udata, e->u.strlist16);
+#else
+			lst = e->u.strlist;
+#endif
+			DUK_ASSERT(lst != NULL);
+			for (j = 0, n = e->listlen; j < n; j++) {
+#if defined(DUK_USE_HEAPPTR16)
+				if (lst[j] != null16) {
+#else
+				if (lst[j] != NULL) {
+#endif
+					used++;
+				}
+			}
+			DUK_DD(DUK_DDPRINT("[%03d] -> array %d/%d", (int) i, (int) used, (int) e->listlen));
+		}
+	}
+}
+#endif  /* DUK_USE_DEBUG */
+
+#endif  /* DUK_USE_STRTAB_CHAIN */
+
+/*
+ *  String table algorithm: closed hashing with a probe sequence
+ *
+ *  This is the default algorithm and works fine for environments with
+ *  minimal memory constraints.
+ */
+
+#if defined(DUK_USE_STRTAB_PROBE)
+
+/* Count actually used (non-NULL, non-DELETED) entries. */
+DUK_LOCAL duk_int_t duk__count_used_probe(duk_heap *heap) {
 	duk_int_t res = 0;
 	duk_uint_fast32_t i, n;
+#if defined(DUK_USE_HEAPPTR16)
+	duk_uint16_t null16 = heap->heapptr_null16;
+	duk_uint16_t deleted16 = heap->heapptr_deleted16;
+#endif
 
 	n = (duk_uint_fast32_t) heap->st_size;
 	for (i = 0; i < n; i++) {
-		if (heap->st[i] != NULL && heap->st[i] != DUK__DELETED_MARKER(heap)) {
+#if defined(DUK_USE_HEAPPTR16)
+		if (heap->strtable16[i] != null16 && heap->strtable16[i] != deleted16) {
+#else
+		if (heap->strtable[i] != NULL && heap->strtable[i] != DUK__DELETED_MARKER(heap)) {
+#endif
 			res++;
 		}
 	}
 	return res;
 }
 
-/*
- *  Hashtable lookup and insert helpers
- */
-
-static void duk__insert_hstring(duk_heap *heap, duk_hstring **entries, duk_uint32_t size, duk_uint32_t *p_used, duk_hstring *h) {
+#if defined(DUK_USE_HEAPPTR16)
+DUK_LOCAL void duk__insert_hstring_probe(duk_heap *heap, duk_uint16_t *entries16, duk_uint32_t size, duk_uint32_t *p_used, duk_hstring *h) {
+#else
+DUK_LOCAL void duk__insert_hstring_probe(duk_heap *heap, duk_hstring **entries, duk_uint32_t size, duk_uint32_t *p_used, duk_hstring *h) {
+#endif
 	duk_uint32_t i;
 	duk_uint32_t step;
+#if defined(DUK_USE_HEAPPTR16)
+	duk_uint16_t null16 = heap->heapptr_null16;
+	duk_uint16_t deleted16 = heap->heapptr_deleted16;
+#endif
 
 	DUK_ASSERT(size > 0);
 
 	i = DUK__HASH_INITIAL(DUK_HSTRING_GET_HASH(h), size);
-	step = DUK__HASH_PROBE_STEP(DUK_HSTRING_GET_HASH(h)); 
+	step = DUK__HASH_PROBE_STEP(DUK_HSTRING_GET_HASH(h));
 	for (;;) {
-		duk_hstring *e;
-		
-		e = entries[i];
+#if defined(DUK_USE_HEAPPTR16)
+		duk_uint16_t e16 = entries16[i];
+#else
+		duk_hstring *e = entries[i];
+#endif
+
+#if defined(DUK_USE_HEAPPTR16)
+		/* XXX: could check for e16 == 0 because NULL is guaranteed to
+		 * encode to zero.
+		 */
+		if (e16 == null16) {
+#else
 		if (e == NULL) {
+#endif
 			DUK_DDD(DUK_DDDPRINT("insert hit (null): %ld", (long) i));
+#if defined(DUK_USE_HEAPPTR16)
+			entries16[i] = DUK_USE_HEAPPTR_ENC16(heap->heap_udata, (void *) h);
+#else
 			entries[i] = h;
+#endif
 			(*p_used)++;
 			break;
+#if defined(DUK_USE_HEAPPTR16)
+		} else if (e16 == deleted16) {
+#else
 		} else if (e == DUK__DELETED_MARKER(heap)) {
+#endif
 			/* st_used remains the same, DELETED is counted as used */
 			DUK_DDD(DUK_DDDPRINT("insert hit (deleted): %ld", (long) i));
+#if defined(DUK_USE_HEAPPTR16)
+			entries16[i] = DUK_USE_HEAPPTR_ENC16(heap->heap_udata, (void *) h);
+#else
 			entries[i] = h;
+#endif
 			break;
 		}
 		DUK_DDD(DUK_DDDPRINT("insert miss: %ld", (long) i));
@@ -32489,7 +47562,11 @@ static void duk__insert_hstring(duk_heap *heap, duk_hstring **entries, duk_uint3
 	}
 }
 
-static duk_hstring *duk__find_matching_string(duk_heap *heap, duk_hstring **entries, duk_uint32_t size, duk_uint8_t *str, duk_uint32_t blen, duk_uint32_t strhash) {
+#if defined(DUK_USE_HEAPPTR16)
+DUK_LOCAL duk_hstring *duk__find_matching_string_probe(duk_heap *heap, duk_uint16_t *entries16, duk_uint32_t size, const duk_uint8_t *str, duk_uint32_t blen, duk_uint32_t strhash) {
+#else
+DUK_LOCAL duk_hstring *duk__find_matching_string_probe(duk_heap *heap, duk_hstring **entries, duk_uint32_t size, const duk_uint8_t *str, duk_uint32_t blen, duk_uint32_t strhash) {
+#endif
 	duk_uint32_t i;
 	duk_uint32_t step;
 
@@ -32499,13 +47576,17 @@ static duk_hstring *duk__find_matching_string(duk_heap *heap, duk_hstring **entr
 	step = DUK__HASH_PROBE_STEP(strhash);
 	for (;;) {
 		duk_hstring *e;
-
+#if defined(DUK_USE_HEAPPTR16)
+		e = (duk_hstring *) DUK_USE_HEAPPTR_DEC16(heap->heap_udata, entries16[i]);
+#else
 		e = entries[i];
+#endif
+
 		if (!e) {
 			return NULL;
 		}
 		if (e != DUK__DELETED_MARKER(heap) && DUK_HSTRING_GET_BYTELEN(e) == blen) {
-			if (DUK_MEMCMP(str, DUK_HSTRING_GET_DATA(e), blen) == 0) {
+			if (DUK_MEMCMP((const void *) str, (const void *) DUK_HSTRING_GET_DATA(e), (size_t) blen) == 0) {
 				DUK_DDD(DUK_DDDPRINT("find matching hit: %ld (step %ld, size %ld)",
 				                     (long) i, (long) step, (long) size));
 				return e;
@@ -32521,26 +47602,51 @@ static duk_hstring *duk__find_matching_string(duk_heap *heap, duk_hstring **entr
 	DUK_UNREACHABLE();
 }
 
-static void duk__remove_matching_hstring(duk_heap *heap, duk_hstring **entries, duk_uint32_t size, duk_hstring *h) {
+#if defined(DUK_USE_HEAPPTR16)
+DUK_LOCAL void duk__remove_matching_hstring_probe(duk_heap *heap, duk_uint16_t *entries16, duk_uint32_t size, duk_hstring *h) {
+#else
+DUK_LOCAL void duk__remove_matching_hstring_probe(duk_heap *heap, duk_hstring **entries, duk_uint32_t size, duk_hstring *h) {
+#endif
 	duk_uint32_t i;
 	duk_uint32_t step;
+	duk_uint32_t hash;
+#if defined(DUK_USE_HEAPPTR16)
+	duk_uint16_t null16 = heap->heapptr_null16;
+	duk_uint16_t h16 = DUK_USE_HEAPPTR_ENC16(heap->heap_udata, (void *) h);
+#endif
 
 	DUK_ASSERT(size > 0);
 
-	i = DUK__HASH_INITIAL(h->hash, size);
-	step = DUK__HASH_PROBE_STEP(h->hash);
+	hash = DUK_HSTRING_GET_HASH(h);
+	i = DUK__HASH_INITIAL(hash, size);
+	step = DUK__HASH_PROBE_STEP(hash);
 	for (;;) {
-		duk_hstring *e;
+#if defined(DUK_USE_HEAPPTR16)
+		duk_uint16_t e16 = entries16[i];
+#else
+		duk_hstring *e = entries[i];
+#endif
 
-		e = entries[i];
+#if defined(DUK_USE_HEAPPTR16)
+		if (e16 == null16) {
+#else
 		if (!e) {
+#endif
 			DUK_UNREACHABLE();
 			break;
 		}
+#if defined(DUK_USE_HEAPPTR16)
+		if (e16 == h16) {
+#else
 		if (e == h) {
+#endif
 			/* st_used remains the same, DELETED is counted as used */
 			DUK_DDD(DUK_DDDPRINT("free matching hit: %ld", (long) i));
+#if defined(DUK_USE_HEAPPTR16)
+			entries16[i] = heap->heapptr_deleted16;
+#else
 			entries[i] = DUK__DELETED_MARKER(heap);
+#endif
 			break;
 		}
 
@@ -32548,15 +47654,11 @@ static void duk__remove_matching_hstring(duk_heap *heap, duk_hstring **entries,
 		i = (i + step) % size;
 
 		/* looping should never happen */
-		DUK_ASSERT(i != DUK__HASH_INITIAL(h->hash, size));
+		DUK_ASSERT(i != DUK__HASH_INITIAL(hash, size));
 	}
 }
 
-/*
- *  Hash resizing and resizing policy
- */
-
-static duk_bool_t duk__resize_strtab_raw(duk_heap *heap, duk_uint32_t new_size) {
+DUK_LOCAL duk_bool_t duk__resize_strtab_raw_probe(duk_heap *heap, duk_uint32_t new_size) {
 #ifdef DUK_USE_MARK_AND_SWEEP
 	duk_small_uint_t prev_mark_and_sweep_base_flags;
 #endif
@@ -32564,8 +47666,13 @@ static duk_bool_t duk__resize_strtab_raw(duk_heap *heap, duk_uint32_t new_size)
 	duk_uint32_t old_used = heap->st_used;
 #endif
 	duk_uint32_t old_size = heap->st_size;
-	duk_hstring **old_entries = heap->st;
+#if defined(DUK_USE_HEAPPTR16)
+	duk_uint16_t *old_entries = heap->strtable16;
+	duk_uint16_t *new_entries = NULL;
+#else
+	duk_hstring **old_entries = heap->strtable;
 	duk_hstring **new_entries = NULL;
+#endif
 	duk_uint32_t new_used = 0;
 	duk_uint32_t i;
 
@@ -32577,11 +47684,11 @@ static duk_bool_t duk__resize_strtab_raw(duk_heap *heap, duk_uint32_t new_size)
 	DUK_DDD(DUK_DDDPRINT("attempt to resize stringtable: %ld entries, %ld bytes, %ld used, %ld%% load -> %ld entries, %ld bytes, %ld used, %ld%% load",
 	                     (long) old_size, (long) (sizeof(duk_hstring *) * old_size), (long) old_used,
 	                     (long) (((double) old_used) / ((double) old_size) * 100.0),
-	                     (long) new_size, (long) (sizeof(duk_hstring *) * new_size), (long) duk__count_used(heap),
-	                     (long) (((double) duk__count_used(heap)) / ((double) new_size) * 100.0)));
+	                     (long) new_size, (long) (sizeof(duk_hstring *) * new_size), (long) duk__count_used_probe(heap),
+	                     (long) (((double) duk__count_used_probe(heap)) / ((double) new_size) * 100.0)));
 #endif
 
-	DUK_ASSERT(new_size > (duk_uint32_t) duk__count_used(heap));  /* required for rehash to succeed, equality not that useful */
+	DUK_ASSERT(new_size > (duk_uint32_t) duk__count_used_probe(heap));  /* required for rehash to succeed, equality not that useful */
 	DUK_ASSERT(old_entries);
 #ifdef DUK_USE_MARK_AND_SWEEP
 	DUK_ASSERT((heap->mark_and_sweep_base_flags & DUK_MS_FLAG_NO_STRINGTABLE_RESIZE) == 0);
@@ -32602,34 +47709,51 @@ static duk_bool_t duk__resize_strtab_raw(duk_heap *heap, duk_uint32_t new_size)
 	        DUK_MS_FLAG_NO_OBJECT_COMPACTION;    /* avoid array abandoning which interns strings */
 #endif
 
+#if defined(DUK_USE_HEAPPTR16)
+	new_entries = (duk_uint16_t *) DUK_ALLOC(heap, sizeof(duk_uint16_t) * new_size);
+#else
 	new_entries = (duk_hstring **) DUK_ALLOC(heap, sizeof(duk_hstring *) * new_size);
+#endif
 
 #ifdef DUK_USE_MARK_AND_SWEEP
 	heap->mark_and_sweep_base_flags = prev_mark_and_sweep_base_flags;
 #endif
 
 	if (!new_entries) {
-		goto error;
+		goto resize_error;
 	}
 
 #ifdef DUK_USE_EXPLICIT_NULL_INIT
 	for (i = 0; i < new_size; i++) {
+#if defined(DUK_USE_HEAPPTR16)
+		new_entries[i] = heap->heapptr_null16;
+#else
 		new_entries[i] = NULL;
+#endif
 	}
 #else
+#if defined(DUK_USE_HEAPPTR16)
+	/* Relies on NULL encoding to zero. */
+	DUK_MEMZERO(new_entries, sizeof(duk_uint16_t) * new_size);
+#else
 	DUK_MEMZERO(new_entries, sizeof(duk_hstring *) * new_size);
 #endif
+#endif
 
-	/* Because new_size > duk__count_used(heap), guaranteed to work */
+	/* Because new_size > duk__count_used_probe(heap), guaranteed to work */
 	for (i = 0; i < old_size; i++) {
 		duk_hstring *e;
 
+#if defined(DUK_USE_HEAPPTR16)
+		e = (duk_hstring *) DUK_USE_HEAPPTR_DEC16(heap->heap_udata, old_entries[i]);
+#else
 		e = old_entries[i];
+#endif
 		if (e == NULL || e == DUK__DELETED_MARKER(heap)) {
 			continue;
 		}
 		/* checking for DUK__DELETED_MARKER is not necessary here, but helper does it now */
-		duk__insert_hstring(heap, new_entries, new_size, &new_used, e);
+		duk__insert_hstring_probe(heap, new_entries, new_size, &new_used, e);
 	}
 
 #ifdef DUK_USE_DDPRINT
@@ -32640,23 +47764,28 @@ static duk_bool_t duk__resize_strtab_raw(duk_heap *heap, duk_uint32_t new_size)
 	                   (long) (((double) new_used) / ((double) new_size) * 100.0)));
 #endif
 
-	DUK_FREE(heap, heap->st);
-	heap->st = new_entries;
+#if defined(DUK_USE_HEAPPTR16)
+	DUK_FREE(heap, heap->strtable16);
+	heap->strtable16 = new_entries;
+#else
+	DUK_FREE(heap, heap->strtable);
+	heap->strtable = new_entries;
+#endif
 	heap->st_size = new_size;
 	heap->st_used = new_used;  /* may be less, since DELETED entries are NULLed by rehash */
 
 	return 0;  /* OK */
 
- error:
+ resize_error:
 	DUK_FREE(heap, new_entries);
 	return 1;  /* FAIL */
 }
 
-static duk_bool_t duk__resize_strtab(duk_heap *heap) {
+DUK_LOCAL duk_bool_t duk__resize_strtab_probe(duk_heap *heap) {
 	duk_uint32_t new_size;
 	duk_bool_t ret;
 
-	new_size = (duk_uint32_t) duk__count_used(heap);
+	new_size = (duk_uint32_t) duk__count_used_probe(heap);
 	if (new_size >= 0x80000000UL) {
 		new_size = DUK_STRTAB_HIGHEST_32BIT_PRIME;
 	} else {
@@ -32667,14 +47796,14 @@ static duk_bool_t duk__resize_strtab(duk_heap *heap) {
 
 	/* rehash even if old and new sizes are the same to get rid of
 	 * DELETED entries.
-	*/ 
+	*/
 
-	ret = duk__resize_strtab_raw(heap, new_size);
+	ret = duk__resize_strtab_raw_probe(heap, new_size);
 
 	return ret;
 }
 
-static duk_bool_t duk__recheck_strtab_size(duk_heap *heap, duk_uint32_t new_used) {
+DUK_LOCAL duk_bool_t duk__recheck_strtab_size_probe(duk_heap *heap, duk_uint32_t new_used) {
 	duk_uint32_t new_free;
 	duk_uint32_t tmp1;
 	duk_uint32_t tmp2;
@@ -32690,46 +47819,100 @@ static duk_bool_t duk__recheck_strtab_size(duk_heap *heap, duk_uint32_t new_used
 
 	if (new_free <= tmp1 || new_used <= tmp2) {
 		/* load factor too low or high, count actually used entries and resize */
-		return duk__resize_strtab(heap);
+		return duk__resize_strtab_probe(heap);
 	} else {
 		return 0;  /* OK */
 	}
 }
 
+#if defined(DUK_USE_DEBUG)
+DUK_INTERNAL void duk_heap_dump_strtab(duk_heap *heap) {
+	duk_uint32_t i;
+	duk_hstring *h;
+
+	DUK_ASSERT(heap != NULL);
+#if defined(DUK_USE_HEAPPTR16)
+	DUK_ASSERT(heap->strtable16 != NULL);
+#else
+	DUK_ASSERT(heap->strtable != NULL);
+#endif
+	DUK_UNREF(h);
+
+	for (i = 0; i < heap->st_size; i++) {
+#if defined(DUK_USE_HEAPPTR16)
+		h = (duk_hstring *) DUK_USE_HEAPPTR_DEC16(heap->strtable16[i]);
+#else
+		h = heap->strtable[i];
+#endif
+
+		DUK_DD(DUK_DDPRINT("[%03d] -> %p", (int) i, (void *) h));
+	}
+}
+#endif  /* DUK_USE_DEBUG */
+
+#endif  /* DUK_USE_STRTAB_PROBE */
+
 /*
  *  Raw intern and lookup
  */
 
-static duk_hstring *duk__do_intern(duk_heap *heap, duk_uint8_t *str, duk_uint32_t blen, duk_uint32_t strhash) {
+DUK_LOCAL duk_hstring *duk__do_intern(duk_heap *heap, const duk_uint8_t *str, duk_uint32_t blen, duk_uint32_t strhash) {
 	duk_hstring *res;
+	const duk_uint8_t *extdata;
 
-	if (duk__recheck_strtab_size(heap, heap->st_used + 1)) {
+#if defined(DUK_USE_STRTAB_PROBE)
+	if (duk__recheck_strtab_size_probe(heap, heap->st_used + 1)) {
 		return NULL;
 	}
+#endif
 
 	/* For manual testing only. */
 #if 0
 	{
 		duk_size_t i;
-		printf("INTERN: \"");
+		DUK_PRINTF("INTERN: \"");
 		for (i = 0; i < blen; i++) {
 			duk_uint8_t x = str[i];
 			if (x >= 0x20 && x <= 0x7e && x != '"' && x != '\\') {
-				printf("%c", (int) x);  /* char: use int cast */
+				DUK_PRINTF("%c", (int) x);  /* char: use int cast */
 			} else {
-				printf("\\x%02lx", (long) x);
+				DUK_PRINTF("\\x%02lx", (long) x);
 			}
 		}
-		printf("\"\n");
+		DUK_PRINTF("\"\n");
 	}
 #endif
 
-	res = duk__alloc_init_hstring(heap, str, blen, strhash);
+#if defined(DUK_USE_HSTRING_EXTDATA) && defined(DUK_USE_EXTSTR_INTERN_CHECK)
+	extdata = (const duk_uint8_t *) DUK_USE_EXTSTR_INTERN_CHECK(heap->heap_udata, (void *) str, (duk_size_t) blen);
+#else
+	extdata = (const duk_uint8_t *) NULL;
+#endif
+	res = duk__alloc_init_hstring(heap, str, blen, strhash, extdata);
 	if (!res) {
 		return NULL;
 	}
 
-	duk__insert_hstring(heap, heap->st, heap->st_size, &heap->st_used, res);  /* guaranteed to succeed */
+#if defined(DUK_USE_STRTAB_CHAIN)
+	if (duk__insert_hstring_chain(heap, res)) {
+		/* failed */
+		DUK_FREE(heap, res);
+		return NULL;
+	}
+#elif defined(DUK_USE_STRTAB_PROBE)
+	/* guaranteed to succeed */
+	duk__insert_hstring_probe(heap,
+#if defined(DUK_USE_HEAPPTR16)
+	                          heap->strtable16,
+#else
+	                          heap->strtable,
+#endif
+	                          heap->st_size,
+	                          &heap->st_used,
+	                          res);
+#else
+#error internal error, invalid strtab options
+#endif
 
 	/* Note: hstring is in heap but has refcount zero and is not strongly reachable.
 	 * Caller should increase refcount and make the hstring reachable before any
@@ -32739,13 +47922,30 @@ static duk_hstring *duk__do_intern(duk_heap *heap, duk_uint8_t *str, duk_uint32_
 	return res;
 }
 
-static duk_hstring *duk__do_lookup(duk_heap *heap, duk_uint8_t *str, duk_uint32_t blen, duk_uint32_t *out_strhash) {
+DUK_LOCAL duk_hstring *duk__do_lookup(duk_heap *heap, const duk_uint8_t *str, duk_uint32_t blen, duk_uint32_t *out_strhash) {
 	duk_hstring *res;
 
 	DUK_ASSERT(out_strhash);
 
 	*out_strhash = duk_heap_hashstring(heap, str, (duk_size_t) blen);
-	res = duk__find_matching_string(heap, heap->st, heap->st_size, str, blen, *out_strhash);
+
+#if defined(DUK_USE_STRTAB_CHAIN)
+	res = duk__find_matching_string_chain(heap, str, blen, *out_strhash);
+#elif defined(DUK_USE_STRTAB_PROBE)
+	res = duk__find_matching_string_probe(heap,
+#if defined(DUK_USE_HEAPPTR16)
+	                                      heap->strtable16,
+#else
+	                                      heap->strtable,
+#endif
+	                                      heap->st_size,
+	                                      str,
+	                                      blen,
+	                                      *out_strhash);
+#else
+#error internal error, invalid strtab options
+#endif
+
 	return res;
 }
 
@@ -32753,12 +47953,14 @@ static duk_hstring *duk__do_lookup(duk_heap *heap, duk_uint8_t *str, duk_uint32_
  *  Exposed calls
  */
 
-duk_hstring *duk_heap_string_lookup(duk_heap *heap, duk_uint8_t *str, duk_uint32_t blen) {
+#if 0  /*unused*/
+DUK_INTERNAL duk_hstring *duk_heap_string_lookup(duk_heap *heap, const duk_uint8_t *str, duk_uint32_t blen) {
 	duk_uint32_t strhash;  /* dummy */
 	return duk__do_lookup(heap, str, blen, &strhash);
 }
+#endif
 
-duk_hstring *duk_heap_string_intern(duk_heap *heap, duk_uint8_t *str, duk_uint32_t blen) {
+DUK_INTERNAL duk_hstring *duk_heap_string_intern(duk_heap *heap, const duk_uint8_t *str, duk_uint32_t blen) {
 	duk_hstring *res;
 	duk_uint32_t strhash;
 
@@ -32774,7 +47976,7 @@ duk_hstring *duk_heap_string_intern(duk_heap *heap, duk_uint8_t *str, duk_uint32
 	return res;  /* may be NULL */
 }
 
-duk_hstring *duk_heap_string_intern_checked(duk_hthread *thr, duk_uint8_t *str, duk_uint32_t blen) {
+DUK_INTERNAL duk_hstring *duk_heap_string_intern_checked(duk_hthread *thr, const duk_uint8_t *str, duk_uint32_t blen) {
 	duk_hstring *res = duk_heap_string_intern(thr->heap, str, blen);
 	if (!res) {
 		DUK_ERROR(thr, DUK_ERR_ALLOC_ERROR, "failed to intern string");
@@ -32782,23 +47984,25 @@ duk_hstring *duk_heap_string_intern_checked(duk_hthread *thr, duk_uint8_t *str,
 	return res;
 }
 
-duk_hstring *duk_heap_string_lookup_u32(duk_heap *heap, duk_uint32_t val) {
+#if 0  /*unused*/
+DUK_INTERNAL duk_hstring *duk_heap_string_lookup_u32(duk_heap *heap, duk_uint32_t val) {
 	char buf[DUK_STRTAB_U32_MAX_STRLEN+1];
 	DUK_SNPRINTF(buf, sizeof(buf), "%lu", (unsigned long) val);
 	buf[sizeof(buf) - 1] = (char) 0;
 	DUK_ASSERT(DUK_STRLEN(buf) <= DUK_UINT32_MAX);  /* formatted result limited */
-	return duk_heap_string_lookup(heap, (duk_uint8_t *) buf, (duk_uint32_t) DUK_STRLEN(buf));
+	return duk_heap_string_lookup(heap, (const duk_uint8_t *) buf, (duk_uint32_t) DUK_STRLEN(buf));
 }
+#endif
 
-duk_hstring *duk_heap_string_intern_u32(duk_heap *heap, duk_uint32_t val) {
+DUK_INTERNAL duk_hstring *duk_heap_string_intern_u32(duk_heap *heap, duk_uint32_t val) {
 	char buf[DUK_STRTAB_U32_MAX_STRLEN+1];
 	DUK_SNPRINTF(buf, sizeof(buf), "%lu", (unsigned long) val);
 	buf[sizeof(buf) - 1] = (char) 0;
 	DUK_ASSERT(DUK_STRLEN(buf) <= DUK_UINT32_MAX);  /* formatted result limited */
-	return duk_heap_string_intern(heap, (duk_uint8_t *) buf, (duk_uint32_t) DUK_STRLEN(buf));
+	return duk_heap_string_intern(heap, (const duk_uint8_t *) buf, (duk_uint32_t) DUK_STRLEN(buf));
 }
 
-duk_hstring *duk_heap_string_intern_u32_checked(duk_hthread *thr, duk_uint32_t val) {
+DUK_INTERNAL duk_hstring *duk_heap_string_intern_u32_checked(duk_hthread *thr, duk_uint32_t val) {
 	duk_hstring *res = duk_heap_string_intern_u32(thr->heap, val);
 	if (!res) {
 		DUK_ERROR(thr, DUK_ERR_ALLOC_ERROR, "failed to intern string");
@@ -32807,22 +48011,145 @@ duk_hstring *duk_heap_string_intern_u32_checked(duk_hthread *thr, duk_uint32_t v
 }
 
 /* find and remove string from stringtable; caller must free the string itself */
-void duk_heap_string_remove(duk_heap *heap, duk_hstring *h) {
+#if defined(DUK_USE_REFERENCE_COUNTING)
+DUK_INTERNAL void duk_heap_string_remove(duk_heap *heap, duk_hstring *h) {
 	DUK_DDD(DUK_DDDPRINT("remove string from stringtable: %!O", (duk_heaphdr *) h));
-	duk__remove_matching_hstring(heap, heap->st, heap->st_size, h);
+
+#if defined(DUK_USE_STRTAB_CHAIN)
+	duk__remove_matching_hstring_chain(heap, h);
+#elif defined(DUK_USE_STRTAB_PROBE)
+	duk__remove_matching_hstring_probe(heap,
+#if defined(DUK_USE_HEAPPTR16)
+	                                   heap->strtable16,
+#else
+	                                   heap->strtable,
+#endif
+	                                   heap->st_size,
+	                                   h);
+#else
+#error internal error, invalid strtab options
+#endif
 }
+#endif
 
 #if defined(DUK_USE_MARK_AND_SWEEP) && defined(DUK_USE_MS_STRINGTABLE_RESIZE)
-void duk_heap_force_stringtable_resize(duk_heap *heap) {
+DUK_INTERNAL void duk_heap_force_strtab_resize(duk_heap *heap) {
 	/* Force a resize so that DELETED entries are eliminated.
-	 * Another option would be duk__recheck_strtab_size(); but since
-	 * that happens on every intern anyway, this whole check
-	 * can now be disabled.
+	 * Another option would be duk__recheck_strtab_size_probe();
+	 * but since that happens on every intern anyway, this whole
+	 * check can now be disabled.
 	 */
-	duk__resize_strtab(heap);
+#if defined(DUK_USE_STRTAB_CHAIN)
+	DUK_UNREF(heap);
+#elif defined(DUK_USE_STRTAB_PROBE)
+	duk__resize_strtab_probe(heap);
+#endif
 }
 #endif
 
+#if defined(DUK_USE_STRTAB_CHAIN)
+DUK_INTERNAL void duk_heap_free_strtab(duk_heap *heap) {
+	/* Free strings in the stringtable and any allocations needed
+	 * by the stringtable itself.
+	 */
+	duk_uint_fast32_t i, j;
+	duk_strtab_entry *e;
+#if defined(DUK_USE_HEAPPTR16)
+	duk_uint16_t *lst;
+	duk_uint16_t null16 = heap->heapptr_null16;
+#else
+	duk_hstring **lst;
+#endif
+	duk_hstring *h;
+
+	for (i = 0; i < DUK_STRTAB_CHAIN_SIZE; i++) {
+		e = heap->strtable + i;
+		if (e->listlen > 0) {
+#if defined(DUK_USE_HEAPPTR16)
+			lst = (duk_uint16_t *) DUK_USE_HEAPPTR_DEC16(heap->heap_udata, e->u.strlist16);
+#else
+			lst = e->u.strlist;
+#endif
+			DUK_ASSERT(lst != NULL);
+
+			for (j = 0; j < e->listlen; j++) {
+#if defined(DUK_USE_HEAPPTR16)
+				h = DUK_USE_HEAPPTR_DEC16(heap->heap_udata, lst[j]);
+				lst[j] = null16;
+#else
+				h = lst[j];
+				lst[j] = NULL;
+#endif
+				/* strings may have inner refs (extdata) in some cases */
+				if (h != NULL) {
+					duk_free_hstring_inner(heap, h);
+					DUK_FREE(heap, h);
+				}
+			}
+#if defined(DUK_USE_HEAPPTR16)
+			e->u.strlist16 = null16;
+#else
+			e->u.strlist = NULL;
+#endif
+			DUK_FREE(heap, lst);
+		} else {
+#if defined(DUK_USE_HEAPPTR16)
+			h = DUK_USE_HEAPPTR_DEC16(heap->heap_udata, e->u.str16);
+			e->u.str16 = null16;
+#else
+			h = e->u.str;
+			e->u.str = NULL;
+#endif
+			if (h != NULL) {
+				duk_free_hstring_inner(heap, h);
+				DUK_FREE(heap, h);
+			}
+		}
+		e->listlen = 0;
+	}
+}
+#endif  /* DUK_USE_STRTAB_CHAIN */
+
+#if defined(DUK_USE_STRTAB_PROBE)
+DUK_INTERNAL void duk_heap_free_strtab(duk_heap *heap) {
+	duk_uint_fast32_t i;
+	duk_hstring *h;
+
+#if defined(DUK_USE_HEAPPTR16)
+	if (heap->strtable16) {
+#else
+	if (heap->strtable) {
+#endif
+		for (i = 0; i < (duk_uint_fast32_t) heap->st_size; i++) {
+#if defined(DUK_USE_HEAPPTR16)
+			h = (duk_hstring *) DUK_USE_HEAPPTR_DEC16(heap->heap_udata, heap->strtable16[i]);
+#else
+			h = heap->strtable[i];
+#endif
+			if (h == NULL || h == DUK_STRTAB_DELETED_MARKER(heap)) {
+				continue;
+			}
+			DUK_ASSERT(h != NULL);
+
+			/* strings may have inner refs (extdata) in some cases */
+			duk_free_hstring_inner(heap, h);
+			DUK_FREE(heap, h);
+#if 0  /* not strictly necessary */
+			heap->strtable[i] = NULL;
+#endif
+		}
+#if defined(DUK_USE_HEAPPTR16)
+		DUK_FREE(heap, heap->strtable16);
+#else
+		DUK_FREE(heap, heap->strtable);
+#endif
+#if 0  /* not strictly necessary */
+		heap->strtable = NULL;
+#endif
+	}
+}
+#endif  /* DUK_USE_STRTAB_PROBE */
+
 /* Undefine local defines */
 #undef DUK__HASH_INITIAL
 #undef DUK__HASH_PROBE_STEP
@@ -32838,19 +48165,26 @@ void duk_heap_force_stringtable_resize(duk_heap *heap) {
 
 /* include removed: duk_internal.h */
 
-static void duk__init_object_parts(duk_heap *heap, duk_hobject *obj, duk_uint_t hobject_flags) {
+DUK_LOCAL void duk__init_object_parts(duk_heap *heap, duk_hobject *obj, duk_uint_t hobject_flags) {
 #ifdef DUK_USE_EXPLICIT_NULL_INIT
-	obj->p = NULL;
+	DUK_HOBJECT_SET_PROPS(heap, obj, NULL);
 #endif
 
-	/* FIXME: macro? sets both heaphdr and object flags */
+	/* XXX: macro? sets both heaphdr and object flags */
 	obj->hdr.h_flags = hobject_flags;
 	DUK_HEAPHDR_SET_TYPE(&obj->hdr, DUK_HTYPE_OBJECT);  /* also goes into flags */
 
+#if defined(DUK_USE_HEAPPTR16)
+	/* Zero encoded pointer is required to match NULL */
+	DUK_HEAPHDR_SET_NEXT(heap, &obj->hdr, NULL);
+#if defined(DUK_USE_DOUBLE_LINKED_HEAP)
+	DUK_HEAPHDR_SET_PREV(heap, &obj->hdr, NULL);
+#endif
+#endif
         DUK_HEAP_INSERT_INTO_HEAP_ALLOCATED(heap, &obj->hdr);
 
 	/*
-	 *  obj->p is intentionally left as NULL, and duk_hobject_props.c must deal
+	 *  obj->props is intentionally left as NULL, and duk_hobject_props.c must deal
 	 *  with this properly.  This is intentional: empty objects consume a minimum
 	 *  amount of memory.  Further, an initial allocation might fail and cause
 	 *  'obj' to "leak" (require a mark-and-sweep) since it is not reachable yet.
@@ -32868,7 +48202,7 @@ static void duk__init_object_parts(duk_heap *heap, duk_hobject *obj, duk_uint_t
  *  count before invoking any operation that might require memory allocation.
  */
 
-duk_hobject *duk_hobject_alloc(duk_heap *heap, duk_uint_t hobject_flags) {
+DUK_INTERNAL duk_hobject *duk_hobject_alloc(duk_heap *heap, duk_uint_t hobject_flags) {
 	duk_hobject *res;
 
 	DUK_ASSERT(heap != NULL);
@@ -32889,7 +48223,7 @@ duk_hobject *duk_hobject_alloc(duk_heap *heap, duk_uint_t hobject_flags) {
 	return res;
 }
 
-duk_hcompiledfunction *duk_hcompiledfunction_alloc(duk_heap *heap, duk_uint_t hobject_flags) {
+DUK_INTERNAL duk_hcompiledfunction *duk_hcompiledfunction_alloc(duk_heap *heap, duk_uint_t hobject_flags) {
 	duk_hcompiledfunction *res;
 
 	res = (duk_hcompiledfunction *) DUK_ALLOC(heap, sizeof(duk_hcompiledfunction));
@@ -32901,15 +48235,19 @@ duk_hcompiledfunction *duk_hcompiledfunction_alloc(duk_heap *heap, duk_uint_t ho
 	duk__init_object_parts(heap, &res->obj, hobject_flags);
 
 #ifdef DUK_USE_EXPLICIT_NULL_INIT
+#ifdef DUK_USE_HEAPPTR16
+	/* NULL pointer is required to encode to zero, so memset is enough. */
+#else
 	res->data = NULL;
 	res->funcs = NULL;
 	res->bytecode = NULL;
 #endif
+#endif
 
 	return res;
 }
 
-duk_hnativefunction *duk_hnativefunction_alloc(duk_heap *heap, duk_uint_t hobject_flags) {
+DUK_INTERNAL duk_hnativefunction *duk_hnativefunction_alloc(duk_heap *heap, duk_uint_t hobject_flags) {
 	duk_hnativefunction *res;
 
 	res = (duk_hnativefunction *) DUK_ALLOC(heap, sizeof(duk_hnativefunction));
@@ -32927,6 +48265,25 @@ duk_hnativefunction *duk_hnativefunction_alloc(duk_heap *heap, duk_uint_t hobjec
 	return res;
 }
 
+DUK_INTERNAL duk_hbufferobject *duk_hbufferobject_alloc(duk_heap *heap, duk_uint_t hobject_flags) {
+	duk_hbufferobject *res;
+
+	res = (duk_hbufferobject *) DUK_ALLOC(heap, sizeof(duk_hbufferobject));
+	if (!res) {
+		return NULL;
+	}
+	DUK_MEMZERO(res, sizeof(duk_hbufferobject));
+
+	duk__init_object_parts(heap, &res->obj, hobject_flags);
+
+#ifdef DUK_USE_EXPLICIT_NULL_INIT
+	res->buf = NULL;
+#endif
+
+	DUK_ASSERT_HBUFFEROBJECT_VALID(res);
+	return res;
+}
+
 /*
  *  Allocate a new thread.
  *
@@ -32935,7 +48292,7 @@ duk_hnativefunction *duk_hnativefunction_alloc(duk_heap *heap, duk_uint_t hobjec
  *  another thread.
  */
 
-duk_hthread *duk_hthread_alloc(duk_heap *heap, duk_uint_t hobject_flags) {
+DUK_INTERNAL duk_hthread *duk_hthread_alloc(duk_heap *heap, duk_uint_t hobject_flags) {
 	duk_hthread *res;
 
 	res = (duk_hthread *) DUK_ALLOC(heap, sizeof(duk_hthread));
@@ -32947,6 +48304,7 @@ duk_hthread *duk_hthread_alloc(duk_heap *heap, duk_uint_t hobject_flags) {
 	duk__init_object_parts(heap, &res->obj, hobject_flags);
 
 #ifdef DUK_USE_EXPLICIT_NULL_INIT
+	res->ptr_curr_pc = NULL;
 	res->heap = NULL;
 	res->valstack = NULL;
 	res->valstack_end = NULL;
@@ -32955,7 +48313,12 @@ duk_hthread *duk_hthread_alloc(duk_heap *heap, duk_uint_t hobject_flags) {
 	res->callstack = NULL;
 	res->catchstack = NULL;
 	res->resumer = NULL;
+	res->compile_ctx = NULL,
+#ifdef DUK_USE_HEAPPTR16
+	res->strs16 = NULL;
+#else
 	res->strs = NULL;
+#endif
 	{
 		int i;
 		for (i = 0; i < DUK_NUM_BUILTINS; i++) {
@@ -32974,100 +48337,15 @@ duk_hthread *duk_hthread_alloc(duk_heap *heap, duk_uint_t hobject_flags) {
 	return res;
 }
 
-/* FIXME: unused now, remove */
-duk_hobject *duk_hobject_alloc_checked(duk_hthread *thr, duk_uint_t hobject_flags) {
+#if 0  /* unused now */
+DUK_INTERNAL duk_hobject *duk_hobject_alloc_checked(duk_hthread *thr, duk_uint_t hobject_flags) {
 	duk_hobject *res = duk_hobject_alloc(thr->heap, hobject_flags);
 	if (!res) {
 		DUK_ERROR(thr, DUK_ERR_ALLOC_ERROR, "failed to allocate an object");
 	}
 	return res;
 }
-#line 1 "duk_hobject_class.c"
-/*
- *  Hobject Ecmascript [[Class]].
- */
-
-/* include removed: duk_internal.h */
-
-/* Maybe better to check these elsewhere */
-#if (DUK_STRIDX_UC_ARGUMENTS > 255)
-#error constant too large
-#endif
-#if (DUK_STRIDX_ARRAY > 255)
-#error constant too large
-#endif
-#if (DUK_STRIDX_UC_BOOLEAN > 255)
-#error constant too large
-#endif
-#if (DUK_STRIDX_DATE > 255)
-#error constant too large
-#endif
-#if (DUK_STRIDX_UC_ERROR > 255)
-#error constant too large
-#endif
-#if (DUK_STRIDX_UC_FUNCTION > 255)
-#error constant too large
-#endif
-#if (DUK_STRIDX_JSON > 255)
-#error constant too large
-#endif
-#if (DUK_STRIDX_MATH > 255)
-#error constant too large
-#endif
-#if (DUK_STRIDX_UC_NUMBER > 255)
-#error constant too large
-#endif
-#if (DUK_STRIDX_UC_OBJECT > 255)
-#error constant too large
-#endif
-#if (DUK_STRIDX_REG_EXP > 255)
-#error constant too large
-#endif
-#if (DUK_STRIDX_UC_STRING > 255)
-#error constant too large
 #endif
-#if (DUK_STRIDX_GLOBAL > 255)
-#error constant too large
-#endif
-#if (DUK_STRIDX_EMPTY_STRING > 255)
-#error constant too large
-#endif
-
-/* Note: assumes that these string indexes are 8-bit, genstrings.py must ensure that */
-duk_uint8_t duk_class_number_to_stridx[32] = {
-	DUK_STRIDX_EMPTY_STRING,  /* UNUSED, intentionally empty */
-	DUK_STRIDX_UC_ARGUMENTS,
-	DUK_STRIDX_ARRAY,
-	DUK_STRIDX_UC_BOOLEAN,
-	DUK_STRIDX_DATE,
-	DUK_STRIDX_UC_ERROR,
-	DUK_STRIDX_UC_FUNCTION,
-	DUK_STRIDX_JSON,
-	DUK_STRIDX_MATH,
-	DUK_STRIDX_UC_NUMBER,
-	DUK_STRIDX_UC_OBJECT,
-	DUK_STRIDX_REG_EXP,
-	DUK_STRIDX_UC_STRING,
-	DUK_STRIDX_GLOBAL,
-	DUK_STRIDX_OBJ_ENV,
-	DUK_STRIDX_DEC_ENV,
-	DUK_STRIDX_UC_BUFFER,
-	DUK_STRIDX_UC_POINTER,
-	DUK_STRIDX_UC_THREAD,     /* UNUSED, intentionally empty */
-	DUK_STRIDX_EMPTY_STRING,  /* UNUSED, intentionally empty */
-	DUK_STRIDX_EMPTY_STRING,  /* UNUSED, intentionally empty */
-	DUK_STRIDX_EMPTY_STRING,  /* UNUSED, intentionally empty */
-	DUK_STRIDX_EMPTY_STRING,  /* UNUSED, intentionally empty */
-	DUK_STRIDX_EMPTY_STRING,  /* UNUSED, intentionally empty */
-	DUK_STRIDX_EMPTY_STRING,  /* UNUSED, intentionally empty */
-	DUK_STRIDX_EMPTY_STRING,  /* UNUSED, intentionally empty */
-	DUK_STRIDX_EMPTY_STRING,  /* UNUSED, intentionally empty */
-	DUK_STRIDX_EMPTY_STRING,  /* UNUSED, intentionally empty */
-	DUK_STRIDX_EMPTY_STRING,  /* UNUSED, intentionally empty */
-	DUK_STRIDX_EMPTY_STRING,  /* UNUSED, intentionally empty */
-	DUK_STRIDX_EMPTY_STRING,  /* UNUSED, intentionally empty */
-	DUK_STRIDX_EMPTY_STRING,  /* UNUSED, intentionally empty */
-};
 #line 1 "duk_hobject_enum.c"
 /*
  *  Hobject enumeration support.
@@ -33090,11 +48368,18 @@ duk_uint8_t duk_class_number_to_stridx[32] = {
 
 /* include removed: duk_internal.h */
 
-/* FIXME: identify enumeration target with an object index (not top of stack) */
+/* XXX: identify enumeration target with an object index (not top of stack) */
 
 /* must match exactly the number of internal properties inserted to enumerator */
 #define DUK__ENUM_START_INDEX  2
 
+DUK_LOCAL const duk_uint16_t duk__bufferobject_virtual_props[] = {
+	DUK_STRIDX_LENGTH,
+	DUK_STRIDX_BYTE_LENGTH,
+	DUK_STRIDX_BYTE_OFFSET,
+	DUK_STRIDX_BYTES_PER_ELEMENT
+};
+
 /*
  *  Helper to sort array index keys.  The keys are in the enumeration object
  *  entry part, starting from DUK__ENUM_START_INDEX, and the entry part is dense.
@@ -33118,21 +48403,22 @@ duk_uint8_t duk_class_number_to_stridx[32] = {
  *  (Compiles to about 160 bytes now as a stand-alone function.)
  */
 
-static void duk__sort_array_indices(duk_hobject *h_obj) {
+DUK_LOCAL void duk__sort_array_indices(duk_hthread *thr, duk_hobject *h_obj) {
 	duk_hstring **keys;
 	duk_hstring **p_curr, **p_insert, **p_end;
 	duk_hstring *h_curr;
 	duk_uarridx_t val_highest, val_curr, val_insert;
 
 	DUK_ASSERT(h_obj != NULL);
-	DUK_ASSERT(h_obj->e_used >= 2);  /* control props */
+	DUK_ASSERT(DUK_HOBJECT_GET_ENEXT(h_obj) >= 2);  /* control props */
+	DUK_UNREF(thr);
 
-	if (h_obj->e_used <= 1 + DUK__ENUM_START_INDEX) {
+	if (DUK_HOBJECT_GET_ENEXT(h_obj) <= 1 + DUK__ENUM_START_INDEX) {
 		return;
 	}
 
-	keys = DUK_HOBJECT_E_GET_KEY_BASE(h_obj);
-	p_end = keys + h_obj->e_used;
+	keys = DUK_HOBJECT_E_GET_KEY_BASE(thr->heap, h_obj);
+	p_end = keys + DUK_HOBJECT_GET_ENEXT(h_obj);
 	keys += DUK__ENUM_START_INDEX;
 
 	DUK_DDD(DUK_DDDPRINT("keys=%p, p_end=%p (after skipping enum props)",
@@ -33141,11 +48427,11 @@ static void duk__sort_array_indices(duk_hobject *h_obj) {
 #ifdef DUK_USE_DDDPRINT
 	{
 		duk_uint_fast32_t i;
-		for (i = 0; i < (duk_uint_fast32_t) h_obj->e_used; i++) {
+		for (i = 0; i < (duk_uint_fast32_t) DUK_HOBJECT_GET_ENEXT(h_obj); i++) {
 			DUK_DDD(DUK_DDDPRINT("initial: %ld %p -> %!O",
 			                     (long) i,
-			                     (void *) DUK_HOBJECT_E_GET_KEY_PTR(h_obj, i),
-			                     (duk_heaphdr *) DUK_HOBJECT_E_GET_KEY(h_obj, i)));
+			                     (void *) DUK_HOBJECT_E_GET_KEY_PTR(thr->heap, h_obj, i),
+			                     (duk_heaphdr *) DUK_HOBJECT_E_GET_KEY(thr->heap, h_obj, i)));
 		}
 	}
 #endif
@@ -33166,7 +48452,7 @@ static void duk__sort_array_indices(duk_hobject *h_obj) {
 		DUK_DDD(DUK_DDDPRINT("p_curr=%p, p_end=%p, val_highest=%ld, val_curr=%ld -> "
 		                     "needs to be inserted",
 		                     (void *) p_curr, (void *) p_end, (long) val_highest, (long) val_curr));
-	
+
 		/* Needs to be inserted; scan backwards, since we optimize
 		 * for the case where elements are nearly in order.
 		 */
@@ -33202,7 +48488,7 @@ static void duk__sort_array_indices(duk_hobject *h_obj) {
 		                     (long) (p_curr - p_insert), (void *) h_curr));
 
 		DUK_MEMMOVE((void *) (p_insert + 1),
-		            (void *) p_insert,
+		            (const void *) p_insert,
 		            (size_t) ((p_curr - p_insert) * sizeof(duk_hstring *)));
 		*p_insert = h_curr;
 		/* keep val_highest */
@@ -33211,11 +48497,11 @@ static void duk__sort_array_indices(duk_hobject *h_obj) {
 #ifdef DUK_USE_DDDPRINT
 	{
 		duk_uint_fast32_t i;
-		for (i = 0; i < (duk_uint_fast32_t) h_obj->e_used; i++) {
+		for (i = 0; i < (duk_uint_fast32_t) DUK_HOBJECT_GET_ENEXT(h_obj); i++) {
 			DUK_DDD(DUK_DDDPRINT("final: %ld %p -> %!O",
 			                     (long) i,
-			                     (void *) DUK_HOBJECT_E_GET_KEY_PTR(h_obj, i),
-			                     (duk_heaphdr *) DUK_HOBJECT_E_GET_KEY(h_obj, i)));
+			                     (void *) DUK_HOBJECT_E_GET_KEY_PTR(thr->heap, h_obj, i),
+			                     (duk_heaphdr *) DUK_HOBJECT_E_GET_KEY(thr->heap, h_obj, i)));
 		}
 	}
 #endif
@@ -33230,7 +48516,7 @@ static void duk__sort_array_indices(duk_hobject *h_obj) {
  *  scan would be needed to eliminate duplicates found in the prototype chain.
  */
 
-void duk_hobject_enumerator_create(duk_context *ctx, duk_small_uint_t enum_flags) {
+DUK_INTERNAL void duk_hobject_enumerator_create(duk_context *ctx, duk_small_uint_t enum_flags) {
 	duk_hthread *thr = (duk_hthread *) ctx;
 	duk_hobject *enum_target;
 	duk_hobject *curr;
@@ -33289,7 +48575,7 @@ void duk_hobject_enumerator_create(duk_context *ctx, duk_small_uint_t enum_flags
 		/* No need to replace the 'enum_target' value in stack, only the
 		 * enum_target reference.  This also ensures that the original
 		 * enum target is reachable, which keeps the proxy and the proxy
-		 * target reachable.  We do need to replace the internal _target.
+		 * target reachable.  We do need to replace the internal _Target.
 		 */
 		DUK_DDD(DUK_DDDPRINT("no enumerate trap, enumerate proxy target instead"));
 		DUK_DDD(DUK_DDDPRINT("h_proxy_target=%!O", (duk_heaphdr *) h_proxy_target));
@@ -33318,7 +48604,7 @@ void duk_hobject_enumerator_create(duk_context *ctx, duk_small_uint_t enum_flags
 		 *
 		 * For keys, we simply skip non-string keys which seems to be
 		 * consistent with how e.g. Object.keys() will process proxy trap
-		 * results (ES6 draft, Section 19.1.2.14).
+		 * results (ES6, Section 19.1.2.14).
 		 */
 		if (duk_get_prop_index(ctx, -1, i) && duk_is_string(ctx, -1)) {
 			/* [ ... enum_target res trap_result val ] */
@@ -33335,10 +48621,10 @@ void duk_hobject_enumerator_create(duk_context *ctx, duk_small_uint_t enum_flags
 
 	/* [ ... res ] */
 
-	/* The internal _target property is kept pointing to the original
+	/* The internal _Target property is kept pointing to the original
 	 * enumeration target (the proxy object), so that the enumerator
 	 * 'next' operation can read property values if so requested.  The
-	 * fact that the _target is a proxy disables key existence check
+	 * fact that the _Target is a proxy disables key existence check
 	 * during enumeration.
 	 */
 	DUK_DDD(DUK_DDDPRINT("proxy enumeration, final res: %!O", (duk_heaphdr *) res));
@@ -33358,7 +48644,7 @@ void duk_hobject_enumerator_create(duk_context *ctx, duk_small_uint_t enum_flags
 		 */
 
 		if (DUK_HOBJECT_HAS_EXOTIC_STRINGOBJ(curr) ||
-		    DUK_HOBJECT_HAS_EXOTIC_BUFFEROBJ(curr)) {
+		    DUK_HOBJECT_IS_BUFFEROBJECT(curr)) {
 			/* String and buffer enumeration behavior is identical now,
 			 * so use shared handler.
 			 */
@@ -33368,11 +48654,20 @@ void duk_hobject_enumerator_create(duk_context *ctx, duk_small_uint_t enum_flags
 				DUK_ASSERT(h_val != NULL);  /* string objects must not created without internal value */
 				len = (duk_uint_fast32_t) DUK_HSTRING_GET_CHARLEN(h_val);
 			} else {
-				duk_hbuffer *h_val;
-				DUK_ASSERT(DUK_HOBJECT_HAS_EXOTIC_BUFFEROBJ(curr));
-				h_val = duk_hobject_get_internal_value_buffer(thr->heap, curr);
-				DUK_ASSERT(h_val != NULL);  /* buffer objects must not created without internal value */
-				len = (duk_uint_fast32_t) DUK_HBUFFER_GET_SIZE(h_val);
+				duk_hbufferobject *h_bufobj;
+				DUK_ASSERT(DUK_HOBJECT_IS_BUFFEROBJECT(curr));
+				h_bufobj = (duk_hbufferobject *) curr;
+				if (h_bufobj == NULL) {
+					/* Neutered buffer, zero length seems
+					 * like good behavior here.
+					 */
+					len = 0;
+				} else {
+					/* There's intentionally no check for
+					 * current underlying buffer length.
+					 */
+					len = (duk_uint_fast32_t) (h_bufobj->length >> h_bufobj->shift);
+				}
 			}
 
 			for (i = 0; i < len; i++) {
@@ -33389,14 +48684,28 @@ void duk_hobject_enumerator_create(duk_context *ctx, duk_small_uint_t enum_flags
 				/* [enum_target res] */
 			}
 
-			/* 'length' property is not enumerable, but is included if
-			 * non-enumerable properties are requested.
+			/* 'length' and other virtual properties are not
+			 * enumerable, but are included if non-enumerable
+			 * properties are requested.
 			 */
 
 			if (enum_flags & DUK_ENUM_INCLUDE_NONENUMERABLE) {
-				duk_push_hstring_stridx(ctx, DUK_STRIDX_LENGTH);
-				duk_push_true(ctx);
-				duk_put_prop(ctx, -3);
+				duk_uint_fast32_t n;
+
+				if (DUK_HOBJECT_IS_BUFFEROBJECT(curr)) {
+					n = sizeof(duk__bufferobject_virtual_props) / sizeof(duk_uint16_t);
+				} else {
+					DUK_ASSERT(DUK_HOBJECT_HAS_EXOTIC_STRINGOBJ(curr));
+					DUK_ASSERT(duk__bufferobject_virtual_props[0] == DUK_STRIDX_LENGTH);
+					n = 1;  /* only 'length' */
+				}
+
+				for (i = 0; i < n; i++) {
+					duk_push_hstring_stridx(ctx, duk__bufferobject_virtual_props[i]);
+					duk_push_true(ctx);
+					duk_put_prop(ctx, -3);
+				}
+
 			}
 		} else if (DUK_HOBJECT_HAS_EXOTIC_DUKFUNC(curr)) {
 			if (enum_flags & DUK_ENUM_INCLUDE_NONENUMERABLE) {
@@ -33414,12 +48723,12 @@ void duk_hobject_enumerator_create(duk_context *ctx, duk_small_uint_t enum_flags
 		 *  must be the same.
 		 */
 
-		for (i = 0; i < (duk_uint_fast32_t) curr->a_size; i++) {
+		for (i = 0; i < (duk_uint_fast32_t) DUK_HOBJECT_GET_ASIZE(curr); i++) {
 			duk_hstring *k;
 			duk_tval *tv;
 
-			tv = DUK_HOBJECT_A_GET_VALUE_PTR(curr, i);
-			if (DUK_TVAL_IS_UNDEFINED_UNUSED(tv)) {
+			tv = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, curr, i);
+			if (DUK_TVAL_IS_UNUSED(tv)) {
 				continue;
 			}
 			k = duk_heap_string_intern_u32_checked(thr, i);
@@ -33438,14 +48747,14 @@ void duk_hobject_enumerator_create(duk_context *ctx, duk_small_uint_t enum_flags
 		 *  Entries part
 		 */
 
-		for (i = 0; i < (duk_uint_fast32_t) curr->e_used; i++) {
+		for (i = 0; i < (duk_uint_fast32_t) DUK_HOBJECT_GET_ENEXT(curr); i++) {
 			duk_hstring *k;
 
-			k = DUK_HOBJECT_E_GET_KEY(curr, i);
+			k = DUK_HOBJECT_E_GET_KEY(thr->heap, curr, i);
 			if (!k) {
 				continue;
 			}
-			if (!DUK_HOBJECT_E_SLOT_IS_ENUMERABLE(curr, i) &&
+			if (!DUK_HOBJECT_E_SLOT_IS_ENUMERABLE(thr->heap, curr, i) &&
 			    !(enum_flags & DUK_ENUM_INCLUDE_NONENUMERABLE)) {
 				continue;
 			}
@@ -33458,8 +48767,8 @@ void duk_hobject_enumerator_create(duk_context *ctx, duk_small_uint_t enum_flags
 				continue;
 			}
 
-			DUK_ASSERT(DUK_HOBJECT_E_SLOT_IS_ACCESSOR(curr, i) ||
-			           !DUK_TVAL_IS_UNDEFINED_UNUSED(&DUK_HOBJECT_E_GET_VALUE_PTR(curr, i)->v));
+			DUK_ASSERT(DUK_HOBJECT_E_SLOT_IS_ACCESSOR(thr->heap, curr, i) ||
+			           !DUK_TVAL_IS_UNUSED(&DUK_HOBJECT_E_GET_VALUE_PTR(thr->heap, curr, i)->v));
 
 			duk_push_hstring(ctx, k);
 			duk_push_true(ctx);
@@ -33474,7 +48783,7 @@ void duk_hobject_enumerator_create(duk_context *ctx, duk_small_uint_t enum_flags
 			break;
 		}
 
-		curr = curr->prototype;
+		curr = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, curr);
 	}
 
 	/* [enum_target res] */
@@ -33497,15 +48806,15 @@ void duk_hobject_enumerator_create(duk_context *ctx, duk_small_uint_t enum_flags
 		 *  here.
 		 */
 
-		/* FIXME: avoid this at least when enum_target is an Array, it has an
+		/* XXX: avoid this at least when enum_target is an Array, it has an
 		 * array part, and no ancestor properties were included?  Not worth
 		 * it for JSON, but maybe worth it for forEach().
 		 */
 
-		/* FIXME: may need a 'length' filter for forEach()
+		/* XXX: may need a 'length' filter for forEach()
 		 */
 		DUK_DDD(DUK_DDDPRINT("sort array indices by caller request"));
-		duk__sort_array_indices(res);
+		duk__sort_array_indices(thr, res);
 	}
 
 #if defined(DUK_USE_ES6_PROXY)
@@ -33525,7 +48834,7 @@ void duk_hobject_enumerator_create(duk_context *ctx, duk_small_uint_t enum_flags
  *
  *  Returns zero without pushing anything on the stack otherwise.
  */
-duk_bool_t duk_hobject_enumerator_next(duk_context *ctx, duk_bool_t get_value) {
+DUK_INTERNAL duk_bool_t duk_hobject_enumerator_next(duk_context *ctx, duk_bool_t get_value) {
 	duk_hthread *thr = (duk_hthread *) ctx;
 	duk_hobject *e;
 	duk_hobject *enum_target;
@@ -33546,7 +48855,7 @@ duk_bool_t duk_hobject_enumerator_next(duk_context *ctx, duk_bool_t get_value) {
 	DUK_DDD(DUK_DDDPRINT("enumeration: index is: %ld", (long) idx));
 
 	/* Enumeration keys are checked against the enumeration target (to see
-	 * that they still exist).  In the proxy enumeration case _target will
+	 * that they still exist).  In the proxy enumeration case _Target will
 	 * be the proxy, and checking key existence against the proxy is not
 	 * required (or sensible, as the keys may be fully virtual).
 	 */
@@ -33554,7 +48863,6 @@ duk_bool_t duk_hobject_enumerator_next(duk_context *ctx, duk_bool_t get_value) {
 	enum_target = duk_require_hobject(ctx, -1);
 	DUK_ASSERT(enum_target != NULL);
 #if defined(DUK_USE_ES6_PROXY)
-	/* FIXME: typing issue here? */
 	check_existence = (!DUK_HOBJECT_HAS_EXOTIC_PROXYOBJ(enum_target));
 #else
 	check_existence = 1;
@@ -33568,16 +48876,16 @@ duk_bool_t duk_hobject_enumerator_next(duk_context *ctx, duk_bool_t get_value) {
 	for (;;) {
 		duk_hstring *k;
 
-		if (idx >= e->e_used) {
+		if (idx >= DUK_HOBJECT_GET_ENEXT(e)) {
 			DUK_DDD(DUK_DDDPRINT("enumeration: ran out of elements"));
 			break;
 		}
 
 		/* we know these because enum objects are internally created */
-		k = DUK_HOBJECT_E_GET_KEY(e, idx);
+		k = DUK_HOBJECT_E_GET_KEY(thr->heap, e, idx);
 		DUK_ASSERT(k != NULL);
-		DUK_ASSERT(!DUK_HOBJECT_E_SLOT_IS_ACCESSOR(e, idx));
-		DUK_ASSERT(!DUK_TVAL_IS_UNDEFINED_UNUSED(&DUK_HOBJECT_E_GET_VALUE(e, idx).v));
+		DUK_ASSERT(!DUK_HOBJECT_E_SLOT_IS_ACCESSOR(thr->heap, e, idx));
+		DUK_ASSERT(!DUK_TVAL_IS_UNUSED(&DUK_HOBJECT_E_GET_VALUE(thr->heap, e, idx).v));
 
 		idx++;
 
@@ -33594,7 +48902,7 @@ duk_bool_t duk_hobject_enumerator_next(duk_context *ctx, duk_bool_t get_value) {
 
 	DUK_DDD(DUK_DDDPRINT("enumeration: updating next index to %ld", (long) idx));
 
-	duk_push_number(ctx, (double) idx);
+	duk_push_u32(ctx, (duk_uint32_t) idx);
 	duk_put_prop_stridx(ctx, -2, DUK_STRIDX_INT_NEXT);
 
 	/* [... enum] */
@@ -33622,13 +48930,15 @@ duk_bool_t duk_hobject_enumerator_next(duk_context *ctx, duk_bool_t get_value) {
  *  described in E5 Section 15.2.3.14.
  */
 
-duk_ret_t duk_hobject_get_enumerated_keys(duk_context *ctx, duk_small_uint_t enum_flags) {
+DUK_INTERNAL duk_ret_t duk_hobject_get_enumerated_keys(duk_context *ctx, duk_small_uint_t enum_flags) {
+	duk_hthread *thr = (duk_hthread *) ctx;
 	duk_hobject *e;
 	duk_uint_fast32_t i;
 	duk_uint_fast32_t idx;
 
 	DUK_ASSERT(ctx != NULL);
 	DUK_ASSERT(duk_get_hobject(ctx, -1) != NULL);
+	DUK_UNREF(thr);
 
 	/* Create a temporary enumerator to get the (non-duplicated) key list;
 	 * the enumerator state is initialized without being needed, but that
@@ -33644,10 +48954,10 @@ duk_ret_t duk_hobject_get_enumerated_keys(duk_context *ctx, duk_small_uint_t enu
 	DUK_ASSERT(e != NULL);
 
 	idx = 0;
-	for (i = DUK__ENUM_START_INDEX; i < (duk_uint_fast32_t) e->e_used; i++) {
+	for (i = DUK__ENUM_START_INDEX; i < (duk_uint_fast32_t) DUK_HOBJECT_GET_ENEXT(e); i++) {
 		duk_hstring *k;
 
-		k = DUK_HOBJECT_E_GET_KEY(e, i);
+		k = DUK_HOBJECT_E_GET_KEY(thr->heap, e, i);
 		DUK_ASSERT(k);  /* enumerator must have no keys deleted */
 
 		/* [enum_target enum res] */
@@ -33683,16 +48993,21 @@ duk_ret_t duk_hobject_get_enumerated_keys(duk_context *ctx, duk_small_uint_t enu
 
 /* include removed: duk_internal.h */
 
-static duk_ret_t duk__finalize_helper(duk_context *ctx) {
+DUK_LOCAL duk_ret_t duk__finalize_helper(duk_context *ctx) {
+	duk_hthread *thr;
+
 	DUK_ASSERT(ctx != NULL);
+	thr = (duk_hthread *) ctx;
 
 	DUK_DDD(DUK_DDDPRINT("protected finalization helper running"));
 
 	/* [... obj] */
 
-	/* FIXME: finalizer lookup should traverse the prototype chain (to allow
+	/* XXX: Finalizer lookup should traverse the prototype chain (to allow
 	 * inherited finalizers) but should not invoke accessors or proxy object
-	 * behavior.
+	 * behavior.  At the moment this lookup will invoke proxy behavior, so
+	 * caller must ensure that this function is not called if the target is
+	 * a Proxy.
 	 */
 
 	duk_get_prop_stridx(ctx, -1, DUK_STRIDX_INT_FINALIZER);  /* -> [... obj finalizer] */
@@ -33700,9 +49015,10 @@ static duk_ret_t duk__finalize_helper(duk_context *ctx) {
 		DUK_DDD(DUK_DDDPRINT("-> no finalizer or finalizer not callable"));
 		return 0;
 	}
-	duk_dup(ctx, -2);  /* -> [... obj finalizer obj] */
+	duk_dup(ctx, -2);
+	duk_push_boolean(ctx, DUK_HEAP_HAS_FINALIZER_NORESCUE(thr->heap));
 	DUK_DDD(DUK_DDDPRINT("-> finalizer found, calling finalizer"));
-	duk_call(ctx, 1);  /* -> [... obj retval] */
+	duk_call(ctx, 2);  /* [ ... obj finalizer obj heapDestruct ]  -> [ ... obj retval ] */
 	DUK_DDD(DUK_DDDPRINT("finalizer finished successfully"));
 	return 0;
 
@@ -33712,7 +49028,7 @@ static duk_ret_t duk__finalize_helper(duk_context *ctx) {
 	 */
 }
 
-void duk_hobject_run_finalizer(duk_hthread *thr, duk_hobject *obj) {
+DUK_INTERNAL void duk_hobject_run_finalizer(duk_hthread *thr, duk_hobject *obj) {
 	duk_context *ctx = (duk_context *) thr;
 	duk_ret_t rc;
 #ifdef DUK_USE_ASSERTIONS
@@ -33724,8 +49040,7 @@ void duk_hobject_run_finalizer(duk_hthread *thr, duk_hobject *obj) {
 	DUK_ASSERT(thr != NULL);
 	DUK_ASSERT(ctx != NULL);
 	DUK_ASSERT(obj != NULL);
-
-	/* FIXME: assert stack space */
+	DUK_ASSERT_VALSTACK_SPACE(thr, 1);
 
 #ifdef DUK_USE_ASSERTIONS
 	entry_top = duk_get_top(ctx);
@@ -33736,7 +49051,21 @@ void duk_hobject_run_finalizer(duk_hthread *thr, duk_hobject *obj) {
 	 *  may trigger an error (getter may throw one, for instance).
 	 */
 
-	/* FIXME: use a NULL error handler for the finalizer call? */
+	if (DUK_HEAPHDR_HAS_FINALIZED((duk_heaphdr *) obj)) {
+		DUK_D(DUK_DPRINT("object already finalized, avoid running finalizer twice: %!O", obj));
+		return;
+	}
+	DUK_HEAPHDR_SET_FINALIZED((duk_heaphdr *) obj);  /* ensure never re-entered until rescue cycle complete */
+	if (DUK_HOBJECT_HAS_EXOTIC_PROXYOBJ(obj)) {
+		/* This shouldn't happen; call sites should avoid looking up
+		 * _Finalizer "through" a Proxy, but ignore if we come here
+		 * with a Proxy to avoid finalizer re-entry.
+		 */
+		DUK_D(DUK_DPRINT("object is a proxy, skip finalizer call"));
+		return;
+	}
+
+	/* XXX: use a NULL error handler for the finalizer call? */
 
 	DUK_DDD(DUK_DDDPRINT("-> finalizer found, calling wrapped finalize helper"));
 	duk_push_hobject(ctx, obj);  /* this also increases refcount by one */
@@ -33761,7 +49090,7 @@ void duk_hobject_run_finalizer(duk_hthread *thr, duk_hobject *obj) {
 
 /* include removed: duk_internal.h */
 
-duk_bool_t duk_hobject_prototype_chain_contains(duk_hthread *thr, duk_hobject *h, duk_hobject *p) {
+DUK_INTERNAL duk_bool_t duk_hobject_prototype_chain_contains(duk_hthread *thr, duk_hobject *h, duk_hobject *p, duk_bool_t ignore_loop) {
 	duk_uint_t sanity;
 
 	DUK_ASSERT(thr != NULL);
@@ -33775,27 +49104,31 @@ duk_bool_t duk_hobject_prototype_chain_contains(duk_hthread *thr, duk_hobject *h
 		}
 
 		if (sanity-- == 0) {
-			DUK_ERROR(thr, DUK_ERR_INTERNAL_ERROR, DUK_STR_PROTOTYPE_CHAIN_LIMIT);
+			if (ignore_loop) {
+				break;
+			} else {
+				DUK_ERROR(thr, DUK_ERR_INTERNAL_ERROR, DUK_STR_PROTOTYPE_CHAIN_LIMIT);
+			}
 		}
-		h = h->prototype;
+		h = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h);
 	} while (h);
 
 	return 0;
 }
 
-/* FIXME: needed? */
-void duk_hobject_set_prototype(duk_hthread *thr, duk_hobject *h, duk_hobject *p) {
+DUK_INTERNAL void duk_hobject_set_prototype_updref(duk_hthread *thr, duk_hobject *h, duk_hobject *p) {
 #ifdef DUK_USE_REFERENCE_COUNTING
 	duk_hobject *tmp;
 
 	DUK_ASSERT(h);
-	tmp = h->prototype;
-	h->prototype = p;
-	DUK_HOBJECT_INCREF(thr, p);  /* avoid problems if p == h->prototype */
-	DUK_HOBJECT_DECREF(thr, tmp);
+	tmp = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h);
+	DUK_HOBJECT_SET_PROTOTYPE(thr->heap, h, p);
+	DUK_HOBJECT_INCREF_ALLOWNULL(thr, p);  /* avoid problems if p == h->prototype */
+	DUK_HOBJECT_DECREF_ALLOWNULL(thr, tmp);
 #else
 	DUK_ASSERT(h);
-	h->prototype = p;
+	DUK_UNREF(thr);
+	DUK_HOBJECT_SET_PROTOTYPE(thr->heap, h, p);
 #endif
 }
 #line 1 "duk_hobject_pc2line.c"
@@ -33805,7 +49138,7 @@ void duk_hobject_set_prototype(duk_hthread *thr, duk_hobject *h, duk_hobject *p)
  *
  *  The run-time pc2line data is bit-packed, and documented in:
  *
- *    doc/function-objects.txt
+ *    doc/function-objects.rst
  */
 
 /* include removed: duk_internal.h */
@@ -33813,7 +49146,7 @@ void duk_hobject_set_prototype(duk_hthread *thr, duk_hobject *h, duk_hobject *p)
 #if defined(DUK_USE_PC2LINE)
 
 /* Generate pc2line data for an instruction sequence, leaving a buffer on stack top. */
-void duk_hobject_pc2line_pack(duk_hthread *thr, duk_compiler_instr *instrs, duk_uint_fast32_t length) {
+DUK_INTERNAL void duk_hobject_pc2line_pack(duk_hthread *thr, duk_compiler_instr *instrs, duk_uint_fast32_t length) {
 	duk_context *ctx = (duk_context *) thr;
 	duk_hbuffer_dynamic *h_buf;
 	duk_bitencoder_ctx be_ctx_alloc;
@@ -33828,7 +49161,7 @@ void duk_hobject_pc2line_pack(duk_hthread *thr, duk_compiler_instr *instrs, duk_
 
 	DUK_ASSERT(length <= DUK_COMPILER_MAX_BYTECODE_LENGTH);
 
-	/* FIXME: add proper spare handling to dynamic buffer, to minimize
+	/* XXX: add proper spare handling to dynamic buffer, to minimize
 	 * reallocs; currently there is no spare at all.
 	 */
 
@@ -33838,18 +49171,18 @@ void duk_hobject_pc2line_pack(duk_hthread *thr, duk_compiler_instr *instrs, duk_
 	duk_push_dynamic_buffer(ctx, (duk_size_t) curr_offset);
 	h_buf = (duk_hbuffer_dynamic *) duk_get_hbuffer(ctx, -1);
 	DUK_ASSERT(h_buf != NULL);
-	DUK_ASSERT(DUK_HBUFFER_HAS_DYNAMIC(h_buf));
+	DUK_ASSERT(DUK_HBUFFER_HAS_DYNAMIC(h_buf) && !DUK_HBUFFER_HAS_EXTERNAL(h_buf));
 
-	hdr = (duk_uint32_t *) DUK_HBUFFER_DYNAMIC_GET_CURR_DATA_PTR(h_buf);
+	hdr = (duk_uint32_t *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(thr->heap, h_buf);
 	DUK_ASSERT(hdr != NULL);
 	hdr[0] = (duk_uint32_t) length;  /* valid pc range is [0, length[ */
 
 	curr_pc = 0U;
 	while (curr_pc < length) {
 		new_size = (duk_size_t) (curr_offset + DUK_PC2LINE_MAX_DIFF_LENGTH);
-		duk_hbuffer_resize(thr, h_buf, new_size, new_size);
+		duk_hbuffer_resize(thr, h_buf, new_size);
 
-		hdr = (duk_uint32_t *) DUK_HBUFFER_DYNAMIC_GET_CURR_DATA_PTR(h_buf);
+		hdr = (duk_uint32_t *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(thr->heap, h_buf);
 		DUK_ASSERT(hdr != NULL);
 		DUK_ASSERT(curr_pc < length);
 		hdr_index = 1 + (curr_pc / DUK_PC2LINE_SKIP) * 2;
@@ -33914,7 +49247,7 @@ void duk_hobject_pc2line_pack(duk_hthread *thr, duk_compiler_instr *instrs, duk_
 
 	/* compact */
 	new_size = (duk_size_t) curr_offset;
-	duk_hbuffer_resize(thr, h_buf, new_size, new_size);
+	duk_hbuffer_resize(thr, h_buf, new_size);
 
 	(void) duk_to_fixed_buffer(ctx, -1, NULL);
 
@@ -33927,7 +49260,7 @@ void duk_hobject_pc2line_pack(duk_hthread *thr, duk_compiler_instr *instrs, duk_
  * it will map to a large PC which is out of bounds and causes a zero to be
  * returned.
  */
-static duk_uint_fast32_t duk__hobject_pc2line_query_raw(duk_hbuffer_fixed *buf, duk_uint_fast32_t pc) {
+DUK_LOCAL duk_uint_fast32_t duk__hobject_pc2line_query_raw(duk_hthread *thr, duk_hbuffer_fixed *buf, duk_uint_fast32_t pc) {
 	duk_bitdecoder_ctx bd_ctx_alloc;
 	duk_bitdecoder_ctx *bd_ctx = &bd_ctx_alloc;
 	duk_uint32_t *hdr;
@@ -33939,7 +49272,12 @@ static duk_uint_fast32_t duk__hobject_pc2line_query_raw(duk_hbuffer_fixed *buf,
 	duk_uint_fast32_t curr_line;
 
 	DUK_ASSERT(buf != NULL);
-	DUK_ASSERT(!DUK_HBUFFER_HAS_DYNAMIC((duk_hbuffer *) buf));
+	DUK_ASSERT(!DUK_HBUFFER_HAS_DYNAMIC((duk_hbuffer *) buf) && !DUK_HBUFFER_HAS_EXTERNAL((duk_hbuffer *) buf));
+	DUK_UNREF(thr);
+
+	/*
+	 *  Use the index in the header to find the right starting point
+	 */
 
 	hdr_index = pc / DUK_PC2LINE_SKIP;
 	pc_base = hdr_index * DUK_PC2LINE_SKIP;
@@ -33950,7 +49288,7 @@ static duk_uint_fast32_t duk__hobject_pc2line_query_raw(duk_hbuffer_fixed *buf,
 		goto error;
 	}
 
-	hdr = (duk_uint32_t *) DUK_HBUFFER_FIXED_GET_DATA_PTR(buf);
+	hdr = (duk_uint32_t *) (void *) DUK_HBUFFER_FIXED_GET_DATA_PTR(thr->heap, buf);
 	pc_limit = hdr[0];
 	if (pc >= pc_limit) {
 		/* Note: pc is unsigned and cannot be negative */
@@ -33967,6 +49305,10 @@ static duk_uint_fast32_t duk__hobject_pc2line_query_raw(duk_hbuffer_fixed *buf,
 		goto error;
 	}
 
+	/*
+	 *  Iterate the bitstream (line diffs) until PC is reached
+	 */
+
 	DUK_MEMZERO(bd_ctx, sizeof(*bd_ctx));
 	bd_ctx->data = ((duk_uint8_t *) hdr) + start_offset;
 	bd_ctx->length = (duk_size_t) (DUK_HBUFFER_FIXED_GET_SIZE(buf) - start_offset);
@@ -34016,15 +49358,21 @@ static duk_uint_fast32_t duk__hobject_pc2line_query_raw(duk_hbuffer_fixed *buf,
 	return 0;
 }
 
-duk_uint_fast32_t duk_hobject_pc2line_query(duk_context *ctx, duk_idx_t idx_func, duk_uint_fast32_t pc) {
+DUK_INTERNAL duk_uint_fast32_t duk_hobject_pc2line_query(duk_context *ctx, duk_idx_t idx_func, duk_uint_fast32_t pc) {
 	duk_hbuffer_fixed *pc2line;
 	duk_uint_fast32_t line;
 
+	/* XXX: now that pc2line is used by the debugger quite heavily in
+	 * checked execution, this should be optimized to avoid value stack
+	 * and perhaps also implement some form of pc2line caching (see
+	 * future work in debugger.rst).
+	 */
+
 	duk_get_prop_stridx(ctx, idx_func, DUK_STRIDX_INT_PC2LINE);
 	pc2line = (duk_hbuffer_fixed *) duk_get_hbuffer(ctx, -1);
 	if (pc2line != NULL) {
-		DUK_ASSERT(!DUK_HBUFFER_HAS_DYNAMIC((duk_hbuffer *) pc2line));
-		line = duk__hobject_pc2line_query_raw(pc2line, (duk_uint_fast32_t) pc);
+		DUK_ASSERT(!DUK_HBUFFER_HAS_DYNAMIC((duk_hbuffer *) pc2line) && !DUK_HBUFFER_HAS_EXTERNAL((duk_hbuffer *) pc2line));
+		line = duk__hobject_pc2line_query_raw((duk_hthread *) ctx, pc2line, (duk_uint_fast32_t) pc);
 	} else {
 		line = 0;
 	}
@@ -34032,14 +49380,15 @@ duk_uint_fast32_t duk_hobject_pc2line_query(duk_context *ctx, duk_idx_t idx_func
 
 	return line;
 }
+
 #endif  /* DUK_USE_PC2LINE */
 #line 1 "duk_hobject_props.c"
 /*
  *  Hobject property set/get functionality.
  *
  *  This is very central functionality for size, performance, and compliance.
- *  It is also rather intricate; see hobject-algorithms.txt for discussion on
- *  the algorithms and memory-management.txt for discussion on refcounts and
+ *  It is also rather intricate; see hobject-algorithms.rst for discussion on
+ *  the algorithms and memory-management.rst for discussion on refcounts and
  *  side effect issues.
  *
  *  Notes:
@@ -34109,16 +49458,20 @@ duk_uint_fast32_t duk_hobject_pc2line_query(duk_context *ctx, duk_idx_t idx_func
  *  Local prototypes
  */
 
-static duk_bool_t duk__check_arguments_map_for_get(duk_hthread *thr, duk_hobject *obj, duk_hstring *key, duk_propdesc *temp_desc);
-static void duk__check_arguments_map_for_put(duk_hthread *thr, duk_hobject *obj, duk_hstring *key, duk_propdesc *temp_desc, duk_bool_t throw_flag);
-static void duk__check_arguments_map_for_delete(duk_hthread *thr, duk_hobject *obj, duk_hstring *key, duk_propdesc *temp_desc);
+#define DUK__DESC_FLAG_PUSH_VALUE          (1 << 0)  /* push value to stack */
+#define DUK__DESC_FLAG_IGNORE_PROTOLOOP    (1 << 1)  /* don't throw for prototype loop */
 
-static duk_bool_t duk__handle_put_array_length_smaller(duk_hthread *thr, duk_hobject *obj, duk_uint32_t old_len, duk_uint32_t new_len, duk_uint32_t *out_result_len);
-static duk_bool_t duk__handle_put_array_length(duk_hthread *thr, duk_hobject *obj);
+DUK_LOCAL_DECL duk_bool_t duk__check_arguments_map_for_get(duk_hthread *thr, duk_hobject *obj, duk_hstring *key, duk_propdesc *temp_desc);
+DUK_LOCAL_DECL void duk__check_arguments_map_for_put(duk_hthread *thr, duk_hobject *obj, duk_hstring *key, duk_propdesc *temp_desc, duk_bool_t throw_flag);
+DUK_LOCAL_DECL void duk__check_arguments_map_for_delete(duk_hthread *thr, duk_hobject *obj, duk_hstring *key, duk_propdesc *temp_desc);
 
-static duk_bool_t duk__get_property_desc(duk_hthread *thr, duk_hobject *obj, duk_hstring *key, duk_propdesc *out_desc, duk_bool_t push_value);
-static duk_bool_t duk__get_own_property_desc_raw(duk_hthread *thr, duk_hobject *obj, duk_hstring *key, duk_uint32_t arr_idx, duk_propdesc *out_desc, duk_bool_t push_value);
-static duk_bool_t duk__get_own_property_desc(duk_hthread *thr, duk_hobject *obj, duk_hstring *key, duk_propdesc *out_desc, duk_bool_t push_value);
+DUK_LOCAL_DECL duk_bool_t duk__handle_put_array_length_smaller(duk_hthread *thr, duk_hobject *obj, duk_uint32_t old_len, duk_uint32_t new_len, duk_bool_t force_flag, duk_uint32_t *out_result_len);
+DUK_LOCAL_DECL duk_bool_t duk__handle_put_array_length(duk_hthread *thr, duk_hobject *obj);
+
+DUK_LOCAL_DECL duk_bool_t duk__get_property_desc(duk_hthread *thr, duk_hobject *obj, duk_hstring *key, duk_propdesc *out_desc, duk_small_uint_t flags);
+DUK_LOCAL_DECL duk_bool_t duk__get_own_property_desc_raw(duk_hthread *thr, duk_hobject *obj, duk_hstring *key, duk_uint32_t arr_idx, duk_propdesc *out_desc, duk_small_uint_t flags);
+DUK_LOCAL_DECL duk_bool_t duk__get_own_property_desc(duk_hthread *thr, duk_hobject *obj, duk_hstring *key, duk_propdesc *out_desc, duk_small_uint_t flags);
+DUK_LOCAL duk_uint32_t duk__get_old_array_length(duk_hthread *thr, duk_hobject *obj, duk_propdesc *temp_desc);
 
 /*
  *  Misc helpers
@@ -34128,7 +49481,10 @@ static duk_bool_t duk__get_own_property_desc(duk_hthread *thr, duk_hobject *obj,
  * DUK__NO_ARRAY_INDEX if the number is not whole or not a valid array
  * index.
  */
-static duk_uint32_t duk__tval_number_to_arr_idx(duk_tval *tv) {
+/* XXX: for fastints, could use a variant which assumes a double duk_tval
+ * (and doesn't need to check for fastint again).
+ */
+DUK_LOCAL duk_uint32_t duk__tval_number_to_arr_idx(duk_tval *tv) {
 	duk_double_t dbl;
 	duk_uint32_t idx;
 
@@ -34146,10 +49502,31 @@ static duk_uint32_t duk__tval_number_to_arr_idx(duk_tval *tv) {
 	return DUK__NO_ARRAY_INDEX;
 }
 
+#if defined(DUK_USE_FASTINT)
+/* Convert a duk_tval fastint (caller checks) to a 32-bit index. */
+DUK_LOCAL duk_uint32_t duk__tval_fastint_to_arr_idx(duk_tval *tv) {
+	duk_int64_t t;
+
+	DUK_ASSERT(tv != NULL);
+	DUK_ASSERT(DUK_TVAL_IS_FASTINT(tv));
+
+	t = DUK_TVAL_GET_FASTINT(tv);
+	if ((t & ~0xffffffffULL) != 0) {
+		/* Catches >0x100000000 and negative values. */
+		return DUK__NO_ARRAY_INDEX;
+	}
+
+	/* If the value happens to be 0xFFFFFFFF, it's not a valid array index
+	 * but will then match DUK__NO_ARRAY_INDEX.
+	 */
+	return (duk_uint32_t) t;
+}
+#endif  /* DUK_USE_FASTINT */
+
 /* Push an arbitrary duk_tval to the stack, coerce it to string, and return
  * both a duk_hstring pointer and an array index (or DUK__NO_ARRAY_INDEX).
  */
-static duk_uint32_t duk__push_tval_to_hstring_arr_idx(duk_context *ctx, duk_tval *tv, duk_hstring **out_h) {
+DUK_LOCAL duk_uint32_t duk__push_tval_to_hstring_arr_idx(duk_context *ctx, duk_tval *tv, duk_hstring **out_h) {
 	duk_uint32_t arr_idx;
 	duk_hstring *h;
 
@@ -34167,12 +49544,19 @@ static duk_uint32_t duk__push_tval_to_hstring_arr_idx(duk_context *ctx, duk_tval
 	return arr_idx;
 }
 
+/* String is an own (virtual) property of a lightfunc. */
+DUK_LOCAL duk_bool_t duk__key_is_lightfunc_ownprop(duk_hthread *thr, duk_hstring *key) {
+	return (key == DUK_HTHREAD_STRING_LENGTH(thr) ||
+	        key == DUK_HTHREAD_STRING_NAME(thr));
+}
+
 /*
  *  Helpers for managing property storage size
  */
 
 /* Get default hash part size for a certain entry part size. */
-static duk_uint32_t duk__get_default_h_size(duk_uint32_t e_size) {
+#if defined(DUK_USE_HOBJECT_HASH_PART)
+DUK_LOCAL duk_uint32_t duk__get_default_h_size(duk_uint32_t e_size) {
 	DUK_ASSERT(e_size <= DUK_HOBJECT_MAX_PROPERTIES);
 
 	if (e_size >= DUK_HOBJECT_E_USE_HASH_LIMIT) {
@@ -34188,9 +49572,10 @@ static duk_uint32_t duk__get_default_h_size(duk_uint32_t e_size) {
 		return 0;
 	}
 }
+#endif  /* USE_PROP_HASH_PART */
 
 /* Get minimum entry part growth for a certain size. */
-static duk_uint32_t duk__get_min_grow_e(duk_uint32_t e_size) {
+DUK_LOCAL duk_uint32_t duk__get_min_grow_e(duk_uint32_t e_size) {
 	duk_uint32_t res;
 
 	DUK_ASSERT(e_size <= DUK_HOBJECT_MAX_PROPERTIES);
@@ -34201,7 +49586,7 @@ static duk_uint32_t duk__get_min_grow_e(duk_uint32_t e_size) {
 }
 
 /* Get minimum array part growth for a certain size. */
-static duk_uint32_t duk__get_min_grow_a(duk_uint32_t a_size) {
+DUK_LOCAL duk_uint32_t duk__get_min_grow_a(duk_uint32_t a_size) {
 	duk_uint32_t res;
 
 	DUK_ASSERT((duk_size_t) a_size <= DUK_HOBJECT_MAX_PROPERTIES);
@@ -34212,15 +49597,16 @@ static duk_uint32_t duk__get_min_grow_a(duk_uint32_t a_size) {
 }
 
 /* Count actually used entry part entries (non-NULL keys). */
-static duk_uint32_t duk__count_used_e_keys(duk_hobject *obj) {
+DUK_LOCAL duk_uint32_t duk__count_used_e_keys(duk_hthread *thr, duk_hobject *obj) {
 	duk_uint_fast32_t i;
 	duk_uint_fast32_t n = 0;
 	duk_hstring **e;
 
 	DUK_ASSERT(obj != NULL);
+	DUK_UNREF(thr);
 
-	e = DUK_HOBJECT_E_GET_KEY_BASE(obj);
-	for (i = 0; i < obj->e_used; i++) {
+	e = DUK_HOBJECT_E_GET_KEY_BASE(thr->heap, obj);
+	for (i = 0; i < DUK_HOBJECT_GET_ENEXT(obj); i++) {
 		if (*e++) {
 			n++;
 		}
@@ -34233,7 +49619,7 @@ static duk_uint32_t duk__count_used_e_keys(duk_hobject *obj) {
  * end and breaking out early when finding first used entry, but this is
  * not needed now.
  */
-static void duk__compute_a_stats(duk_hobject *obj, duk_uint32_t *out_used, duk_uint32_t *out_min_size) {
+DUK_LOCAL void duk__compute_a_stats(duk_hthread *thr, duk_hobject *obj, duk_uint32_t *out_used, duk_uint32_t *out_min_size) {
 	duk_uint_fast32_t i;
 	duk_uint_fast32_t used = 0;
 	duk_uint_fast32_t highest_idx = (duk_uint_fast32_t) -1;  /* see below */
@@ -34242,11 +49628,12 @@ static void duk__compute_a_stats(duk_hobject *obj, duk_uint32_t *out_used, duk_u
 	DUK_ASSERT(obj != NULL);
 	DUK_ASSERT(out_used != NULL);
 	DUK_ASSERT(out_min_size != NULL);
+	DUK_UNREF(thr);
 
-	a = DUK_HOBJECT_A_GET_BASE(obj);
-	for (i = 0; i < obj->a_size; i++) {
+	a = DUK_HOBJECT_A_GET_BASE(thr->heap, obj);
+	for (i = 0; i < DUK_HOBJECT_GET_ASIZE(obj); i++) {
 		duk_tval *tv = a++;
-		if (!DUK_TVAL_IS_UNDEFINED_UNUSED(tv)) {
+		if (!DUK_TVAL_IS_UNUSED(tv)) {
 			used++;
 			highest_idx = i;
 		}
@@ -34262,7 +49649,7 @@ static void duk__compute_a_stats(duk_hobject *obj, duk_uint32_t *out_used, duk_u
 }
 
 /* Check array density and indicate whether or not the array part should be abandoned. */
-static duk_bool_t duk__abandon_array_density_check(duk_uint32_t a_used, duk_uint32_t a_size) {
+DUK_LOCAL duk_bool_t duk__abandon_array_density_check(duk_uint32_t a_used, duk_uint32_t a_size) {
 	/*
 	 *  Array abandon check; abandon if:
 	 *
@@ -34283,7 +49670,7 @@ static duk_bool_t duk__abandon_array_density_check(duk_uint32_t a_used, duk_uint
 }
 
 /* Fast check for extending array: check whether or not a slow density check is required. */
-static duk_bool_t duk__abandon_array_slow_check_required(duk_uint32_t arr_idx, duk_uint32_t old_size) {
+DUK_LOCAL duk_bool_t duk__abandon_array_slow_check_required(duk_uint32_t arr_idx, duk_uint32_t old_size) {
 	/*
 	 *  In a fast check we assume old_size equals old_used (i.e., existing
 	 *  array is fully dense).
@@ -34313,7 +49700,7 @@ static duk_bool_t duk__abandon_array_slow_check_required(duk_uint32_t arr_idx, d
  */
 
 #if defined(DUK_USE_ES6_PROXY)
-duk_bool_t duk_hobject_proxy_check(duk_hthread *thr, duk_hobject *obj, duk_hobject **out_target, duk_hobject **out_handler) {
+DUK_INTERNAL duk_bool_t duk_hobject_proxy_check(duk_hthread *thr, duk_hobject *obj, duk_hobject **out_target, duk_hobject **out_handler) {
 	duk_tval *tv_target;
 	duk_tval *tv_handler;
 	duk_hobject *h_target;
@@ -34331,7 +49718,7 @@ duk_bool_t duk_hobject_proxy_check(duk_hthread *thr, duk_hobject *obj, duk_hobje
 		return 0;
 	}
 
-	tv_handler = duk_hobject_find_existing_entry_tval_ptr(obj, DUK_HTHREAD_STRING_INT_HANDLER(thr));
+	tv_handler = duk_hobject_find_existing_entry_tval_ptr(thr->heap, obj, DUK_HTHREAD_STRING_INT_HANDLER(thr));
 	if (!tv_handler) {
 		DUK_ERROR(thr, DUK_ERR_TYPE_ERROR, DUK_STR_PROXY_REVOKED);
 		return 0;
@@ -34342,7 +49729,7 @@ duk_bool_t duk_hobject_proxy_check(duk_hthread *thr, duk_hobject *obj, duk_hobje
 	*out_handler = h_handler;
 	tv_handler = NULL;  /* avoid issues with relocation */
 
-	tv_target = duk_hobject_find_existing_entry_tval_ptr(obj, DUK_HTHREAD_STRING_INT_TARGET(thr));
+	tv_target = duk_hobject_find_existing_entry_tval_ptr(thr->heap, obj, DUK_HTHREAD_STRING_INT_TARGET(thr));
 	if (!tv_target) {
 		DUK_ERROR(thr, DUK_ERR_TYPE_ERROR, DUK_STR_PROXY_REVOKED);
 		return 0;
@@ -34355,10 +49742,40 @@ duk_bool_t duk_hobject_proxy_check(duk_hthread *thr, duk_hobject *obj, duk_hobje
 
 	return 1;
 }
-#endif
+#endif  /* DUK_USE_ES6_PROXY */
+
+/* Get Proxy target object.  If the argument is not a Proxy, return it as is.
+ * If a Proxy is revoked, an error is thrown.
+ */
+#if defined(DUK_USE_ES6_PROXY)
+DUK_INTERNAL duk_hobject *duk_hobject_resolve_proxy_target(duk_hthread *thr, duk_hobject *obj) {
+	duk_hobject *h_target;
+	duk_hobject *h_handler;
+
+	DUK_ASSERT(thr != NULL);
+	DUK_ASSERT(obj != NULL);
+
+	/* Resolve Proxy targets until Proxy chain ends.  No explicit check for
+	 * a Proxy loop: user code cannot create such a loop without tweaking
+	 * internal properties directly.
+	 */
+
+	while (DUK_UNLIKELY(DUK_HOBJECT_HAS_EXOTIC_PROXYOBJ(obj))) {
+		if (duk_hobject_proxy_check(thr, obj, &h_target, &h_handler)) {
+			DUK_ASSERT(h_target != NULL);
+			obj = h_target;
+		} else {
+			break;
+		}
+	}
+
+	DUK_ASSERT(obj != NULL);
+	return obj;
+}
+#endif  /* DUK_USE_ES6_PROXY */
 
 #if defined(DUK_USE_ES6_PROXY)
-static duk_bool_t duk__proxy_check_prop(duk_hthread *thr, duk_hobject *obj, duk_small_uint_t stridx_trap, duk_tval *tv_key, duk_hobject **out_target) {
+DUK_LOCAL duk_bool_t duk__proxy_check_prop(duk_hthread *thr, duk_hobject *obj, duk_small_uint_t stridx_trap, duk_tval *tv_key, duk_hobject **out_target) {
 	duk_context *ctx = (duk_context *) thr;
 	duk_hobject *h_handler;
 
@@ -34373,7 +49790,7 @@ static duk_bool_t duk__proxy_check_prop(duk_hthread *thr, duk_hobject *obj, duk_
 	DUK_ASSERT(*out_target != NULL);
 	DUK_ASSERT(h_handler != NULL);
 
-	/* XXX: At the moment Duktape accesses internal keys like _finalizer using a
+	/* XXX: At the moment Duktape accesses internal keys like _Finalizer using a
 	 * normal property set/get which would allow a proxy handler to interfere with
 	 * such behavior and to get access to internal key strings.  This is not a problem
 	 * as such because internal key strings can be created in other ways too (e.g.
@@ -34452,12 +49869,13 @@ static duk_bool_t duk__proxy_check_prop(duk_hthread *thr, duk_hobject *obj, duk_
  *  will become invalid after this call.
  */
 
-static void duk__realloc_props(duk_hthread *thr,
-                               duk_hobject *obj,
-                               duk_uint32_t new_e_size,
-                               duk_uint32_t new_a_size,
-                               duk_uint32_t new_h_size,
-                               duk_bool_t abandon_array) {
+DUK_LOCAL
+void duk__realloc_props(duk_hthread *thr,
+                        duk_hobject *obj,
+                        duk_uint32_t new_e_size,
+                        duk_uint32_t new_a_size,
+                        duk_uint32_t new_h_size,
+                        duk_bool_t abandon_array) {
 	duk_context *ctx = (duk_context *) thr;
 #ifdef DUK_USE_MARK_AND_SWEEP
 	duk_small_uint_t prev_mark_and_sweep_base_flags;
@@ -34470,17 +49888,17 @@ static void duk__realloc_props(duk_hthread *thr,
 	duk_uint8_t *new_e_f;
 	duk_tval *new_a;
 	duk_uint32_t *new_h;
-	duk_uint32_t new_e_used;
+	duk_uint32_t new_e_next;
 	duk_uint_fast32_t i;
 
 	DUK_ASSERT(thr != NULL);
 	DUK_ASSERT(ctx != NULL);
 	DUK_ASSERT(obj != NULL);
 	DUK_ASSERT(!abandon_array || new_a_size == 0);  /* if abandon_array, new_a_size must be 0 */
-	DUK_ASSERT(obj->p != NULL || (obj->e_size == 0 && obj->a_size == 0));
+	DUK_ASSERT(DUK_HOBJECT_GET_PROPS(thr->heap, obj) != NULL || (DUK_HOBJECT_GET_ESIZE(obj) == 0 && DUK_HOBJECT_GET_ASIZE(obj) == 0));
 	DUK_ASSERT(new_h_size == 0 || new_h_size >= new_e_size);  /* required to guarantee success of rehashing,
 	                                                           * intentionally use unadjusted new_e_size
-	                                                           */	
+	                                                           */
 	DUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);
 
 	/*
@@ -34488,7 +49906,7 @@ static void duk__realloc_props(duk_hthread *thr,
 	 */
 
 #ifdef DUK_USE_ASSERTIONS
-	/* XXX: pre checks (such as no duplicate keys) */
+	/* XXX: pre-checks (such as no duplicate keys) */
 #endif
 
 	/*
@@ -34519,16 +49937,18 @@ static void duk__realloc_props(duk_hthread *thr,
 	 *  Debug logging after adjustment.
 	 */
 
-	DUK_DDD(DUK_DDDPRINT("attempt to resize hobject %p props (%ld -> %ld bytes), from {p=%p,e_size=%ld,e_used=%ld,a_size=%ld,h_size=%ld} to "
+	DUK_DDD(DUK_DDDPRINT("attempt to resize hobject %p props (%ld -> %ld bytes), from {p=%p,e_size=%ld,e_next=%ld,a_size=%ld,h_size=%ld} to "
 	                     "{e_size=%ld,a_size=%ld,h_size=%ld}, abandon_array=%ld, unadjusted new_e_size=%ld",
 	                     (void *) obj,
-	                     (long) DUK_HOBJECT_P_COMPUTE_SIZE(obj->e_size, obj->a_size, obj->h_size),
+	                     (long) DUK_HOBJECT_P_COMPUTE_SIZE(DUK_HOBJECT_GET_ESIZE(obj),
+	                                                       DUK_HOBJECT_GET_ASIZE(obj),
+	                                                       DUK_HOBJECT_GET_HSIZE(obj)),
 	                     (long) DUK_HOBJECT_P_COMPUTE_SIZE(new_e_size_adjusted, new_a_size, new_h_size),
-	                     (void *) obj->p,
-	                     (long) obj->e_size,
-	                     (long) obj->e_used,
-	                     (long) obj->a_size,
-	                     (long) obj->h_size,
+	                     (void *) DUK_HOBJECT_GET_PROPS(thr->heap, obj),
+	                     (long) DUK_HOBJECT_GET_ESIZE(obj),
+	                     (long) DUK_HOBJECT_GET_ENEXT(obj),
+	                     (long) DUK_HOBJECT_GET_ASIZE(obj),
+	                     (long) DUK_HOBJECT_GET_HSIZE(obj),
 	                     (long) new_e_size_adjusted,
 	                     (long) new_a_size,
 	                     (long) new_h_size,
@@ -34567,7 +49987,7 @@ static void duk__realloc_props(duk_hthread *thr,
 #ifdef DUK_USE_MARK_AND_SWEEP
 	prev_mark_and_sweep_base_flags = thr->heap->mark_and_sweep_base_flags;
 	thr->heap->mark_and_sweep_base_flags |=
-                DUK_MS_FLAG_NO_FINALIZERS |         /* avoid attempts to add/remove object keys */
+	        DUK_MS_FLAG_NO_FINALIZERS |         /* avoid attempts to add/remove object keys */
 	        DUK_MS_FLAG_NO_OBJECT_COMPACTION;   /* avoid attempt to compact the current object */
 #endif
 
@@ -34599,7 +50019,8 @@ static void duk__realloc_props(duk_hthread *thr,
 	 */
 	DUK_HOBJECT_P_SET_REALLOC_PTRS(new_p, new_e_k, new_e_pv, new_e_f, new_a, new_h,
 	                               new_e_size_adjusted, new_a_size, new_h_size);
-	new_e_used = 0;
+	DUK_UNREF(new_h);  /* happens when hash part dropped */
+	new_e_next = 0;
 
 	/* if new_p == NULL, all of these pointers are NULL */
 	DUK_ASSERT((new_p != NULL) ||
@@ -34635,15 +50056,15 @@ static void duk__realloc_props(duk_hthread *thr,
 		 */
 		DUK_ASSERT(new_a_size == 0);
 
-		for (i = 0; i < obj->a_size; i++) {
+		for (i = 0; i < DUK_HOBJECT_GET_ASIZE(obj); i++) {
 			duk_tval *tv1;
 			duk_tval *tv2;
 			duk_hstring *key;
 
-			DUK_ASSERT(obj->p != NULL);
+			DUK_ASSERT(DUK_HOBJECT_GET_PROPS(thr->heap, obj) != NULL);
 
-			tv1 = DUK_HOBJECT_A_GET_VALUE_PTR(obj, i);
-			if (DUK_TVAL_IS_UNDEFINED_UNUSED(tv1)) {
+			tv1 = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, obj, i);
+			if (DUK_TVAL_IS_UNUSED(tv1)) {
 				continue;
 			}
 
@@ -34674,33 +50095,33 @@ static void duk__realloc_props(duk_hthread *thr,
 			/* key is now reachable in the valstack */
 
 			DUK_HSTRING_INCREF(thr, key);   /* second incref for the entry reference */
-			new_e_k[new_e_used] = key;
-			tv2 = &new_e_pv[new_e_used].v;  /* array entries are all plain values */
+			new_e_k[new_e_next] = key;
+			tv2 = &new_e_pv[new_e_next].v;  /* array entries are all plain values */
 			DUK_TVAL_SET_TVAL(tv2, tv1);
-			new_e_f[new_e_used] = DUK_PROPDESC_FLAG_WRITABLE |
+			new_e_f[new_e_next] = DUK_PROPDESC_FLAG_WRITABLE |
 			                      DUK_PROPDESC_FLAG_ENUMERABLE |
 			                      DUK_PROPDESC_FLAG_CONFIGURABLE;
-			new_e_used++;
+			new_e_next++;
 
-			/* Note: new_e_used matches pushed temp key count, and nothing can
+			/* Note: new_e_next matches pushed temp key count, and nothing can
 			 * fail above between the push and this point.
 			 */
 		}
 
-		DUK_DDD(DUK_DDDPRINT("abandon array: pop %ld key temps from valstack", (long) new_e_used));
-		duk_pop_n(ctx, new_e_used);
+		DUK_DDD(DUK_DDDPRINT("abandon array: pop %ld key temps from valstack", (long) new_e_next));
+		duk_pop_n(ctx, new_e_next);
 	}
 
 	/*
 	 *  Copy keys and values in the entry part (compacting them at the same time).
 	 */
 
-	for (i = 0; i < obj->e_used; i++) {
+	for (i = 0; i < DUK_HOBJECT_GET_ENEXT(obj); i++) {
 		duk_hstring *key;
 
-		DUK_ASSERT(obj->p != NULL);
+		DUK_ASSERT(DUK_HOBJECT_GET_PROPS(thr->heap, obj) != NULL);
 
-		key = DUK_HOBJECT_E_GET_KEY(obj, i);
+		key = DUK_HOBJECT_E_GET_KEY(thr->heap, obj, i);
 		if (!key) {
 			continue;
 		}
@@ -34708,45 +50129,45 @@ static void duk__realloc_props(duk_hthread *thr,
 		DUK_ASSERT(new_p != NULL && new_e_k != NULL &&
 		           new_e_pv != NULL && new_e_f != NULL);
 
-		new_e_k[new_e_used] = key;
-		new_e_pv[new_e_used] = DUK_HOBJECT_E_GET_VALUE(obj, i);
-		new_e_f[new_e_used] = DUK_HOBJECT_E_GET_FLAGS(obj, i);
-		new_e_used++;
+		new_e_k[new_e_next] = key;
+		new_e_pv[new_e_next] = DUK_HOBJECT_E_GET_VALUE(thr->heap, obj, i);
+		new_e_f[new_e_next] = DUK_HOBJECT_E_GET_FLAGS(thr->heap, obj, i);
+		new_e_next++;
 	}
-	/* the entries [new_e_used, new_e_size_adjusted[ are left uninitialized on purpose (ok, not gc reachable) */
+	/* the entries [new_e_next, new_e_size_adjusted[ are left uninitialized on purpose (ok, not gc reachable) */
 
 	/*
 	 *  Copy array elements to new array part.
 	 */
 
-	if (new_a_size > obj->a_size) {
+	if (new_a_size > DUK_HOBJECT_GET_ASIZE(obj)) {
 		/* copy existing entries as is */
 		DUK_ASSERT(new_p != NULL && new_a != NULL);
-		if (obj->a_size > 0) {
+		if (DUK_HOBJECT_GET_ASIZE(obj) > 0) {
 			/* Avoid zero copy with an invalid pointer.  If obj->p is NULL,
 			 * the 'new_a' pointer will be invalid which is not allowed even
 			 * when copy size is zero.
 			 */
-			DUK_ASSERT(obj->p != NULL);
-			DUK_ASSERT(obj->a_size > 0);
-			DUK_MEMCPY((void *) new_a, (void *) DUK_HOBJECT_A_GET_BASE(obj), sizeof(duk_tval) * obj->a_size);
+			DUK_ASSERT(DUK_HOBJECT_GET_PROPS(thr->heap, obj) != NULL);
+			DUK_ASSERT(DUK_HOBJECT_GET_ASIZE(obj) > 0);
+			DUK_MEMCPY((void *) new_a, (void *) DUK_HOBJECT_A_GET_BASE(thr->heap, obj), sizeof(duk_tval) * DUK_HOBJECT_GET_ASIZE(obj));
 		}
 
 		/* fill new entries with -unused- (required, gc reachable) */
-		for (i = obj->a_size; i < new_a_size; i++) {
+		for (i = DUK_HOBJECT_GET_ASIZE(obj); i < new_a_size; i++) {
 			duk_tval *tv = &new_a[i];
-			DUK_TVAL_SET_UNDEFINED_UNUSED(tv);
+			DUK_TVAL_SET_UNUSED(tv);
 		}
 	} else {
 #ifdef DUK_USE_ASSERTIONS
 		/* caller must have decref'd values above new_a_size (if that is necessary) */
 		if (!abandon_array) {
-			for (i = new_a_size; i < obj->a_size; i++) {
+			for (i = new_a_size; i < DUK_HOBJECT_GET_ASIZE(obj); i++) {
 				duk_tval *tv;
-				tv = DUK_HOBJECT_A_GET_VALUE_PTR(obj, i);
+				tv = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, obj, i);
 
 				/* current assertion is quite strong: decref's and set to unused */
-				DUK_ASSERT(DUK_TVAL_IS_UNDEFINED_UNUSED(tv));
+				DUK_ASSERT(DUK_TVAL_IS_UNUSED(tv));
 			}
 		}
 #endif
@@ -34755,9 +50176,9 @@ static void duk__realloc_props(duk_hthread *thr,
 			 * the 'new_a' pointer will be invalid which is not allowed even
 			 * when copy size is zero.
 			 */
-			DUK_ASSERT(obj->p != NULL);
+			DUK_ASSERT(DUK_HOBJECT_GET_PROPS(thr->heap, obj) != NULL);
 			DUK_ASSERT(new_a_size > 0);
-			DUK_MEMCPY((void *) new_a, (void *) DUK_HOBJECT_A_GET_BASE(obj), sizeof(duk_tval) * new_a_size);
+			DUK_MEMCPY((void *) new_a, (void *) DUK_HOBJECT_A_GET_BASE(thr->heap, obj), sizeof(duk_tval) * new_a_size);
 		}
 	}
 
@@ -34769,16 +50190,17 @@ static void duk__realloc_props(duk_hthread *thr,
 	 *  to ensuring the hash part never fills up.
 	 */
 
+#if defined(DUK_USE_HOBJECT_HASH_PART)
 	if (DUK_UNLIKELY(new_h_size > 0)) {
 		DUK_ASSERT(new_h != NULL);
 
 		/* fill new_h with u32 0xff = UNUSED */
-		DUK_ASSERT(obj->p != NULL);
+		DUK_ASSERT(DUK_HOBJECT_GET_PROPS(thr->heap, obj) != NULL);
 		DUK_ASSERT(new_h_size > 0);
 		DUK_MEMSET(new_h, 0xff, sizeof(duk_uint32_t) * new_h_size);
 
-		DUK_ASSERT(new_e_used <= new_h_size);  /* equality not actually possible */
-		for (i = 0; i < new_e_used; i++) {
+		DUK_ASSERT(new_e_next <= new_h_size);  /* equality not actually possible */
+		for (i = 0; i < new_e_next; i++) {
 			duk_hstring *key = new_e_k[i];
 			duk_uint32_t j, step;
 
@@ -34803,24 +50225,27 @@ static void duk__realloc_props(duk_hthread *thr,
 	} else {
 		DUK_DDD(DUK_DDDPRINT("no hash part, no rehash"));
 	}
+#endif  /* DUK_USE_HOBJECT_HASH_PART */
 
 	/*
 	 *  Nice debug log.
 	 */
 
-	DUK_DD(DUK_DDPRINT("resized hobject %p props (%ld -> %ld bytes), from {p=%p,e_size=%ld,e_used=%ld,a_size=%ld,h_size=%ld} to "
-	                   "{p=%p,e_size=%ld,e_used=%ld,a_size=%ld,h_size=%ld}, abandon_array=%ld, unadjusted new_e_size=%ld",
+	DUK_DD(DUK_DDPRINT("resized hobject %p props (%ld -> %ld bytes), from {p=%p,e_size=%ld,e_next=%ld,a_size=%ld,h_size=%ld} to "
+	                   "{p=%p,e_size=%ld,e_next=%ld,a_size=%ld,h_size=%ld}, abandon_array=%ld, unadjusted new_e_size=%ld",
 	                   (void *) obj,
-	                   (long) DUK_HOBJECT_P_COMPUTE_SIZE(obj->e_size, obj->a_size, obj->h_size),
+	                   (long) DUK_HOBJECT_P_COMPUTE_SIZE(DUK_HOBJECT_GET_ESIZE(obj),
+	                                                     DUK_HOBJECT_GET_ASIZE(obj),
+	                                                     DUK_HOBJECT_GET_HSIZE(obj)),
 	                   (long) new_alloc_size,
-	                   (void *) obj->p,
-	                   (long) obj->e_size,
-	                   (long) obj->e_used,
-	                   (long) obj->a_size,
-	                   (long) obj->h_size,
+	                   (void *) DUK_HOBJECT_GET_PROPS(thr->heap, obj),
+	                   (long) DUK_HOBJECT_GET_ESIZE(obj),
+	                   (long) DUK_HOBJECT_GET_ENEXT(obj),
+	                   (long) DUK_HOBJECT_GET_ASIZE(obj),
+	                   (long) DUK_HOBJECT_GET_HSIZE(obj),
 	                   (void *) new_p,
 	                   (long) new_e_size_adjusted,
-	                   (long) new_e_used,
+	                   (long) new_e_next,
 	                   (long) new_a_size,
 	                   (long) new_h_size,
 	                   (long) abandon_array,
@@ -34830,12 +50255,12 @@ static void duk__realloc_props(duk_hthread *thr,
 	 *  All done, switch properties ('p') allocation to new one.
 	 */
 
-	DUK_FREE(thr->heap, obj->p);  /* NULL obj->p is OK */
-	obj->p = new_p;
-	obj->e_size = new_e_size_adjusted;
-	obj->e_used = new_e_used;
-	obj->a_size = new_a_size;
-	obj->h_size = new_h_size;
+	DUK_FREE(thr->heap, DUK_HOBJECT_GET_PROPS(thr->heap, obj));  /* NULL obj->p is OK */
+	DUK_HOBJECT_SET_PROPS(thr->heap, obj, new_p);
+	DUK_HOBJECT_SET_ESIZE(obj, new_e_size_adjusted);
+	DUK_HOBJECT_SET_ENEXT(obj, new_e_next);
+	DUK_HOBJECT_SET_ASIZE(obj, new_a_size);
+	DUK_HOBJECT_SET_HSIZE(obj, new_h_size);
 
 	if (new_p) {
 		/*
@@ -34846,15 +50271,7 @@ static void duk__realloc_props(duk_hthread *thr,
 		 *  so it would be nice to free it forcibly even with only
 		 *  mark-and-sweep enabled.  Not a big issue though.
 		 */
-		duk_hbuffer_dynamic *buf;
-		DUK_ASSERT(new_alloc_size > 0);
-		DUK_ASSERT(duk_is_buffer(ctx, -1));
-		buf = (duk_hbuffer_dynamic *) duk_require_hbuffer(ctx, -1);
-		DUK_ASSERT(buf != NULL);
-		DUK_ASSERT(DUK_HBUFFER_HAS_DYNAMIC(buf));
-		buf->curr_alloc = NULL;
-		buf->size = 0;  /* these size resets are not strictly necessary, but nice for consistency */
-		buf->usable_size = 0;
+		(void) duk_steal_buffer(ctx, -1, NULL);
 		duk_pop(ctx);
 	} else {
 		DUK_ASSERT(new_alloc_size == 0);
@@ -34877,7 +50294,7 @@ static void duk__realloc_props(duk_hthread *thr,
 	 */
 
 #ifdef DUK_USE_ASSERTIONS
-	/* XXX: post checks (such as no duplicate keys) */
+	/* XXX: post-checks (such as no duplicate keys) */
 #endif
 	return;
 
@@ -34888,12 +50305,12 @@ static void duk__realloc_props(duk_hthread *thr,
 
  abandon_error:
 	DUK_D(DUK_DPRINT("hobject resize failed during abandon array, decref keys"));
-	i = new_e_used;
+	i = new_e_next;
 	while (i > 0) {
 		i--;
 		DUK_ASSERT(new_e_k != NULL);
 		DUK_ASSERT(new_e_k[i] != NULL);
-		DUK_HSTRING_DECREF(thr, new_e_k[i]);
+		DUK_HSTRING_DECREF(thr, new_e_k[i]);  /* side effects */
 	}
 
 #ifdef DUK_USE_MARK_AND_SWEEP
@@ -34908,7 +50325,8 @@ static void duk__realloc_props(duk_hthread *thr,
  */
 
 /* Grow entry part allocation for one additional entry. */
-static void duk__grow_props_for_new_entry_item(duk_hthread *thr, duk_hobject *obj) {
+DUK_LOCAL void duk__grow_props_for_new_entry_item(duk_hthread *thr, duk_hobject *obj) {
+	duk_uint32_t old_e_used;  /* actually used, non-NULL entries */
 	duk_uint32_t new_e_size;
 	duk_uint32_t new_a_size;
 	duk_uint32_t new_h_size;
@@ -34916,28 +50334,40 @@ static void duk__grow_props_for_new_entry_item(duk_hthread *thr, duk_hobject *ob
 	DUK_ASSERT(thr != NULL);
 	DUK_ASSERT(obj != NULL);
 
-	new_e_size = obj->e_size + duk__get_min_grow_e(obj->e_size);
+	/* Duktape 0.11.0 and prior tried to optimize the resize by not
+	 * counting the number of actually used keys prior to the resize.
+	 * This worked mostly well but also caused weird leak-like behavior
+	 * as in: test-bug-object-prop-alloc-unbounded.js.  So, now we count
+	 * the keys explicitly to compute the new entry part size.
+	 */
+
+	old_e_used = duk__count_used_e_keys(thr, obj);
+	new_e_size = old_e_used + duk__get_min_grow_e(old_e_used);
+#if defined(DUK_USE_HOBJECT_HASH_PART)
 	new_h_size = duk__get_default_h_size(new_e_size);
-	new_a_size = obj->a_size;
-	DUK_ASSERT(new_e_size >= obj->e_size + 1);  /* duk__get_min_grow_e() is always >= 1 */
+#else
+	new_h_size = 0;
+#endif
+	new_a_size = DUK_HOBJECT_GET_ASIZE(obj);
+	DUK_ASSERT(new_e_size >= old_e_used + 1);  /* duk__get_min_grow_e() is always >= 1 */
 
 	duk__realloc_props(thr, obj, new_e_size, new_a_size, new_h_size, 0);
 }
 
 /* Grow array part for a new highest array index. */
-static void duk__grow_props_for_array_item(duk_hthread *thr, duk_hobject *obj, duk_uint32_t highest_arr_idx) {
+DUK_LOCAL void duk__grow_props_for_array_item(duk_hthread *thr, duk_hobject *obj, duk_uint32_t highest_arr_idx) {
 	duk_uint32_t new_e_size;
 	duk_uint32_t new_a_size;
 	duk_uint32_t new_h_size;
 
 	DUK_ASSERT(thr != NULL);
 	DUK_ASSERT(obj != NULL);
-	DUK_ASSERT(highest_arr_idx >= obj->a_size);
+	DUK_ASSERT(highest_arr_idx >= DUK_HOBJECT_GET_ASIZE(obj));
 
 	/* minimum new length is highest_arr_idx + 1 */
 
-	new_e_size = obj->e_size;
-	new_h_size = obj->h_size;
+	new_e_size = DUK_HOBJECT_GET_ESIZE(obj);
+	new_h_size = DUK_HOBJECT_GET_HSIZE(obj);
 	new_a_size = highest_arr_idx + duk__get_min_grow_a(highest_arr_idx);
 	DUK_ASSERT(new_a_size >= highest_arr_idx + 1);  /* duk__get_min_grow_a() is always >= 1 */
 
@@ -34949,19 +50379,19 @@ static void duk__grow_props_for_array_item(duk_hthread *thr, duk_hobject *obj, d
  * We also compact the entries part while we're at it, although
  * this is not strictly required.
  */
-static void duk__abandon_array_checked(duk_hthread *thr, duk_hobject *obj) {
+DUK_LOCAL void duk__abandon_array_checked(duk_hthread *thr, duk_hobject *obj) {
 	duk_uint32_t new_e_size;
 	duk_uint32_t new_a_size;
 	duk_uint32_t new_h_size;
-	duk_uint32_t e_used;
+	duk_uint32_t e_used;  /* actually used, non-NULL keys */
 	duk_uint32_t a_used;
 	duk_uint32_t a_size;
 
 	DUK_ASSERT(thr != NULL);
 	DUK_ASSERT(obj != NULL);
 
-	e_used = duk__count_used_e_keys(obj);
-	duk__compute_a_stats(obj, &a_used, &a_size);
+	e_used = duk__count_used_e_keys(thr, obj);
+	duk__compute_a_stats(thr, obj, &a_used, &a_size);
 
 	/*
 	 *  Must guarantee all actually used array entries will fit into
@@ -34972,7 +50402,11 @@ static void duk__abandon_array_checked(duk_hthread *thr, duk_hobject *obj) {
 	new_e_size = e_used + a_used;
 	new_e_size = new_e_size + duk__get_min_grow_e(new_e_size);
 	new_a_size = 0;
+#if defined(DUK_USE_HOBJECT_HASH_PART)
 	new_h_size = duk__get_default_h_size(new_e_size);
+#else
+	new_h_size = 0;
+#endif
 
 	DUK_DD(DUK_DDPRINT("abandon array part for hobject %p, "
 	                   "array stats before: e_used=%ld, a_used=%ld, a_size=%ld; "
@@ -34995,7 +50429,7 @@ static void duk__abandon_array_checked(duk_hthread *thr, duk_hobject *obj) {
  *  The call may fail due to allocation error.
  */
 
-void duk_hobject_compact_props(duk_hthread *thr, duk_hobject *obj) {
+DUK_INTERNAL void duk_hobject_compact_props(duk_hthread *thr, duk_hobject *obj) {
 	duk_uint32_t e_size;       /* currently used -> new size */
 	duk_uint32_t a_size;       /* currently required */
 	duk_uint32_t a_used;       /* actually used */
@@ -35005,8 +50439,8 @@ void duk_hobject_compact_props(duk_hthread *thr, duk_hobject *obj) {
 	DUK_ASSERT(thr != NULL);
 	DUK_ASSERT(obj != NULL);
 
-	e_size = duk__count_used_e_keys(obj);
-	duk__compute_a_stats(obj, &a_used, &a_size);
+	e_size = duk__count_used_e_keys(thr, obj);
+	duk__compute_a_stats(thr, obj, &a_used, &a_size);
 
 	DUK_DD(DUK_DDPRINT("compacting hobject, used e keys %ld, used a keys %ld, min a size %ld, "
 	                   "resized array density would be: %ld/%ld = %lf",
@@ -35025,11 +50459,15 @@ void duk_hobject_compact_props(duk_hthread *thr, duk_hobject *obj) {
 		abandon_array = 0;
 	}
 
+#if defined(DUK_USE_HOBJECT_HASH_PART)
 	if (e_size >= DUK_HOBJECT_E_USE_HASH_LIMIT) {
 		h_size = duk__get_default_h_size(e_size);
 	} else {
 		h_size = 0;
 	}
+#else
+	h_size = 0;
+#endif
 
 	DUK_DD(DUK_DDPRINT("compacting hobject -> new e_size %ld, new a_size=%ld, new h_size=%ld, abandon_array=%ld",
 	                   (long) e_size, (long) a_size, (long) h_size, (long) abandon_array));
@@ -35047,13 +50485,15 @@ void duk_hobject_compact_props(duk_hthread *thr, duk_hobject *obj) {
  *  but there is no hash part, h_idx is set to -1.
  */
 
-void duk_hobject_find_existing_entry(duk_hobject *obj, duk_hstring *key, duk_int_t *e_idx, duk_int_t *h_idx) {
+DUK_INTERNAL void duk_hobject_find_existing_entry(duk_heap *heap, duk_hobject *obj, duk_hstring *key, duk_int_t *e_idx, duk_int_t *h_idx) {
 	DUK_ASSERT(obj != NULL);
 	DUK_ASSERT(key != NULL);
 	DUK_ASSERT(e_idx != NULL);
 	DUK_ASSERT(h_idx != NULL);
+	DUK_UNREF(heap);
 
-	if (DUK_LIKELY(obj->h_size == 0)) {
+	if (DUK_LIKELY(DUK_HOBJECT_GET_HSIZE(obj) == 0))
+	{
 		/* Linear scan: more likely because most objects are small.
 		 * This is an important fast path.
 		 *
@@ -35064,8 +50504,8 @@ void duk_hobject_find_existing_entry(duk_hobject *obj, duk_hstring *key, duk_int
 		duk_hstring **h_keys_base;
 		DUK_DDD(DUK_DDDPRINT("duk_hobject_find_existing_entry() using linear scan for lookup"));
 
-		h_keys_base = DUK_HOBJECT_E_GET_KEY_BASE(obj);
-		n = obj->e_used;
+		h_keys_base = DUK_HOBJECT_E_GET_KEY_BASE(heap, obj);
+		n = DUK_HOBJECT_GET_ENEXT(obj);
 		for (i = 0; i < n; i++) {
 			if (h_keys_base[i] == key) {
 				*e_idx = i;
@@ -35073,7 +50513,10 @@ void duk_hobject_find_existing_entry(duk_hobject *obj, duk_hstring *key, duk_int
 				return;
 			}
 		}
-	} else {
+	}
+#if defined(DUK_USE_HOBJECT_HASH_PART)
+	else
+	{
 		/* hash lookup */
 		duk_uint32_t n;
 		duk_uint32_t i, step;
@@ -35081,8 +50524,8 @@ void duk_hobject_find_existing_entry(duk_hobject *obj, duk_hstring *key, duk_int
 
 		DUK_DDD(DUK_DDDPRINT("duk_hobject_find_existing_entry() using hash part for lookup"));
 
-		h_base = DUK_HOBJECT_H_GET_BASE(obj);
-		n = obj->h_size;
+		h_base = DUK_HOBJECT_H_GET_BASE(heap, obj);
+		n = DUK_HOBJECT_GET_HSIZE(obj);
 		i = DUK__HASH_INITIAL(DUK_HSTRING_GET_HASH(key), n);
 		step = DUK__HASH_PROBE_STEP(DUK_HSTRING_GET_HASH(key));
 
@@ -35090,10 +50533,10 @@ void duk_hobject_find_existing_entry(duk_hobject *obj, duk_hstring *key, duk_int
 			duk_uint32_t t;
 
 			DUK_ASSERT_DISABLE(i >= 0);  /* unsigned */
-			DUK_ASSERT(i < obj->h_size);
+			DUK_ASSERT(i < DUK_HOBJECT_GET_HSIZE(obj));
 			t = h_base[i];
 			DUK_ASSERT(t == DUK__HASH_UNUSED || t == DUK__HASH_DELETED ||
-			           (t < obj->e_size));  /* t >= 0 always true, unsigned */
+			           (t < DUK_HOBJECT_GET_ESIZE(obj)));  /* t >= 0 always true, unsigned */
 
 			if (t == DUK__HASH_UNUSED) {
 				break;
@@ -35101,8 +50544,8 @@ void duk_hobject_find_existing_entry(duk_hobject *obj, duk_hstring *key, duk_int
 				DUK_DDD(DUK_DDDPRINT("lookup miss (deleted) i=%ld, t=%ld",
 				                     (long) i, (long) t));
 			} else {
-				DUK_ASSERT(t < obj->e_size);
-				if (DUK_HOBJECT_E_GET_KEY(obj, t) == key) {
+				DUK_ASSERT(t < DUK_HOBJECT_GET_ESIZE(obj));
+				if (DUK_HOBJECT_E_GET_KEY(heap, obj, t) == key) {
 					DUK_DDD(DUK_DDDPRINT("lookup hit i=%ld, t=%ld -> key %p",
 					                     (long) i, (long) t, (void *) key));
 					*e_idx = t;
@@ -35118,6 +50561,7 @@ void duk_hobject_find_existing_entry(duk_hobject *obj, duk_hstring *key, duk_int
 			DUK_ASSERT(i != (duk_uint32_t) DUK__HASH_INITIAL(DUK_HSTRING_GET_HASH(key), n));
 		}
 	}
+#endif  /* DUK_USE_HOBJECT_HASH_PART */
 
 	/* not found */
 	*e_idx = -1;
@@ -35125,34 +50569,36 @@ void duk_hobject_find_existing_entry(duk_hobject *obj, duk_hstring *key, duk_int
 }
 
 /* For internal use: get non-accessor entry value */
-duk_tval *duk_hobject_find_existing_entry_tval_ptr(duk_hobject *obj, duk_hstring *key) {
+DUK_INTERNAL duk_tval *duk_hobject_find_existing_entry_tval_ptr(duk_heap *heap, duk_hobject *obj, duk_hstring *key) {
 	duk_int_t e_idx;
 	duk_int_t h_idx;
 
 	DUK_ASSERT(obj != NULL);
 	DUK_ASSERT(key != NULL);
+	DUK_UNREF(heap);
 
-	duk_hobject_find_existing_entry(obj, key, &e_idx, &h_idx);
-	if (e_idx >= 0 && !DUK_HOBJECT_E_SLOT_IS_ACCESSOR(obj, e_idx)) {
-		return DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(obj, e_idx);
+	duk_hobject_find_existing_entry(heap, obj, key, &e_idx, &h_idx);
+	if (e_idx >= 0 && !DUK_HOBJECT_E_SLOT_IS_ACCESSOR(heap, obj, e_idx)) {
+		return DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(heap, obj, e_idx);
 	} else {
 		return NULL;
 	}
 }
 
 /* For internal use: get non-accessor entry value and attributes */
-duk_tval *duk_hobject_find_existing_entry_tval_ptr_and_attrs(duk_hobject *obj, duk_hstring *key, duk_int_t *out_attrs) {
+DUK_INTERNAL duk_tval *duk_hobject_find_existing_entry_tval_ptr_and_attrs(duk_heap *heap, duk_hobject *obj, duk_hstring *key, duk_int_t *out_attrs) {
 	duk_int_t e_idx;
 	duk_int_t h_idx;
 
 	DUK_ASSERT(obj != NULL);
 	DUK_ASSERT(key != NULL);
 	DUK_ASSERT(out_attrs != NULL);
+	DUK_UNREF(heap);
 
-	duk_hobject_find_existing_entry(obj, key, &e_idx, &h_idx);
-	if (e_idx >= 0 && !DUK_HOBJECT_E_SLOT_IS_ACCESSOR(obj, e_idx)) {
-		*out_attrs = DUK_HOBJECT_E_GET_FLAGS(obj, e_idx);
-		return DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(obj, e_idx);
+	duk_hobject_find_existing_entry(heap, obj, key, &e_idx, &h_idx);
+	if (e_idx >= 0 && !DUK_HOBJECT_E_SLOT_IS_ACCESSOR(heap, obj, e_idx)) {
+		*out_attrs = DUK_HOBJECT_E_GET_FLAGS(heap, obj, e_idx);
+		return DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(heap, obj, e_idx);
 	} else {
 		*out_attrs = 0;
 		return NULL;
@@ -35160,18 +50606,19 @@ duk_tval *duk_hobject_find_existing_entry_tval_ptr_and_attrs(duk_hobject *obj, d
 }
 
 /* For internal use: get array part value */
-duk_tval *duk_hobject_find_existing_array_entry_tval_ptr(duk_hobject *obj, duk_uarridx_t i) {
+DUK_INTERNAL duk_tval *duk_hobject_find_existing_array_entry_tval_ptr(duk_heap *heap, duk_hobject *obj, duk_uarridx_t i) {
 	duk_tval *tv;
 
 	DUK_ASSERT(obj != NULL);
+	DUK_UNREF(heap);
 
 	if (!DUK_HOBJECT_HAS_ARRAY_PART(obj)) {
 		return NULL;
 	}
-	if (i >= obj->a_size) {
+	if (i >= DUK_HOBJECT_GET_ASIZE(obj)) {
 		return NULL;
 	}
-	tv = DUK_HOBJECT_A_GET_VALUE_PTR(obj, i);
+	tv = DUK_HOBJECT_A_GET_VALUE_PTR(heap, obj, i);
 	return tv;
 }
 
@@ -35184,42 +50631,43 @@ duk_tval *duk_hobject_find_existing_array_entry_tval_ptr(duk_hobject *obj, duk_u
  *  the entry value refcount.  A decref for the previous value is not necessary.
  */
 
-static duk_bool_t duk__alloc_entry_checked(duk_hthread *thr, duk_hobject *obj, duk_hstring *key) {
+DUK_LOCAL duk_bool_t duk__alloc_entry_checked(duk_hthread *thr, duk_hobject *obj, duk_hstring *key) {
 	duk_uint32_t idx;
 
 	DUK_ASSERT(thr != NULL);
 	DUK_ASSERT(obj != NULL);
 	DUK_ASSERT(key != NULL);
-	DUK_ASSERT(obj->e_used <= obj->e_size);
+	DUK_ASSERT(DUK_HOBJECT_GET_ENEXT(obj) <= DUK_HOBJECT_GET_ESIZE(obj));
 
 #ifdef DUK_USE_ASSERTIONS
 	/* key must not already exist in entry part */
 	{
 		duk_uint_fast32_t i;
-		for (i = 0; i < obj->e_used; i++) {
-			DUK_ASSERT(DUK_HOBJECT_E_GET_KEY(obj, i) != key);
+		for (i = 0; i < DUK_HOBJECT_GET_ENEXT(obj); i++) {
+			DUK_ASSERT(DUK_HOBJECT_E_GET_KEY(thr->heap, obj, i) != key);
 		}
 	}
 #endif
 
-	if (obj->e_used >= obj->e_size) {
+	if (DUK_HOBJECT_GET_ENEXT(obj) >= DUK_HOBJECT_GET_ESIZE(obj)) {
 		/* only need to guarantee 1 more slot, but allocation growth is in chunks */
 		DUK_DDD(DUK_DDDPRINT("entry part full, allocate space for one more entry"));
 		duk__grow_props_for_new_entry_item(thr, obj);
 	}
-	DUK_ASSERT(obj->e_used < obj->e_size);
-	idx = obj->e_used++;
+	DUK_ASSERT(DUK_HOBJECT_GET_ENEXT(obj) < DUK_HOBJECT_GET_ESIZE(obj));
+	idx = DUK_HOBJECT_POSTINC_ENEXT(obj);
 
 	/* previous value is assumed to be garbage, so don't touch it */
-	DUK_HOBJECT_E_SET_KEY(obj, idx, key);
+	DUK_HOBJECT_E_SET_KEY(thr->heap, obj, idx, key);
 	DUK_HSTRING_INCREF(thr, key);
 
-	if (DUK_UNLIKELY(obj->h_size > 0)) {
+#if defined(DUK_USE_HOBJECT_HASH_PART)
+	if (DUK_UNLIKELY(DUK_HOBJECT_GET_HSIZE(obj) > 0)) {
 		duk_uint32_t n;
 		duk_uint32_t i, step;
-		duk_uint32_t *h_base = DUK_HOBJECT_H_GET_BASE(obj);
+		duk_uint32_t *h_base = DUK_HOBJECT_H_GET_BASE(thr->heap, obj);
 
-		n = obj->h_size;
+		n = DUK_HOBJECT_GET_HSIZE(obj);
 		i = DUK__HASH_INITIAL(DUK_HSTRING_GET_HASH(key), n);
 		step = DUK__HASH_PROBE_STEP(DUK_HSTRING_GET_HASH(key));
 
@@ -35229,9 +50677,9 @@ static duk_bool_t duk__alloc_entry_checked(duk_hthread *thr, duk_hobject *obj, d
 				DUK_DDD(DUK_DDDPRINT("duk__alloc_entry_checked() inserted key into hash part, %ld -> %ld",
 				                     (long) i, (long) idx));
 				DUK_ASSERT_DISABLE(i >= 0);  /* unsigned */
-				DUK_ASSERT(i < obj->h_size);
+				DUK_ASSERT(i < DUK_HOBJECT_GET_HSIZE(obj));
 				DUK_ASSERT_DISABLE(idx >= 0);
-				DUK_ASSERT(idx < obj->e_size);
+				DUK_ASSERT(idx < DUK_HOBJECT_GET_ESIZE(obj));
 				h_base[i] = idx;
 				break;
 			}
@@ -35239,28 +50687,29 @@ static duk_bool_t duk__alloc_entry_checked(duk_hthread *thr, duk_hobject *obj, d
 			i = (i + step) % n;
 
 			/* guaranteed to find an empty slot */
-			DUK_ASSERT(i != (duk_uint32_t) DUK__HASH_INITIAL(DUK_HSTRING_GET_HASH(key), obj->h_size));
+			DUK_ASSERT(i != (duk_uint32_t) DUK__HASH_INITIAL(DUK_HSTRING_GET_HASH(key), DUK_HOBJECT_GET_HSIZE(obj)));
 		}
 	}
+#endif  /* DUK_USE_HOBJECT_HASH_PART */
 
 	/* Note: we could return the hash index here too, but it's not
 	 * needed right now.
 	 */
 
 	DUK_ASSERT_DISABLE(idx >= 0);
-	DUK_ASSERT(idx < obj->e_size);
-	DUK_ASSERT(idx < obj->e_used);
+	DUK_ASSERT(idx < DUK_HOBJECT_GET_ESIZE(obj));
+	DUK_ASSERT(idx < DUK_HOBJECT_GET_ENEXT(obj));
 	return idx;
 }
 
 /*
  *  Object internal value
  *
- *  Returned value is guaranteed to be reachable / incref'd, caller does not need 
+ *  Returned value is guaranteed to be reachable / incref'd, caller does not need
  *  to incref OR decref.  No proxies or accessors are invoked, no prototype walk.
  */
 
-duk_bool_t duk_hobject_get_internal_value(duk_heap *heap, duk_hobject *obj, duk_tval *tv_out) {
+DUK_INTERNAL duk_bool_t duk_hobject_get_internal_value(duk_heap *heap, duk_hobject *obj, duk_tval *tv_out) {
 	duk_int_t e_idx;
 	duk_int_t h_idx;
 
@@ -35268,24 +50717,28 @@ duk_bool_t duk_hobject_get_internal_value(duk_heap *heap, duk_hobject *obj, duk_
 	DUK_ASSERT(obj != NULL);
 	DUK_ASSERT(tv_out != NULL);
 
-	DUK_TVAL_SET_UNDEFINED_UNUSED(tv_out);
-
 	/* always in entry part, no need to look up parents etc */
-	duk_hobject_find_existing_entry(obj, DUK_HEAP_STRING_INT_VALUE(heap), &e_idx, &h_idx);
+	duk_hobject_find_existing_entry(heap, obj, DUK_HEAP_STRING_INT_VALUE(heap), &e_idx, &h_idx);
 	if (e_idx >= 0) {
-		DUK_ASSERT(!DUK_HOBJECT_E_SLOT_IS_ACCESSOR(obj, e_idx));
-		DUK_TVAL_SET_TVAL(tv_out, DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(obj, e_idx));
+		DUK_ASSERT(!DUK_HOBJECT_E_SLOT_IS_ACCESSOR(heap, obj, e_idx));
+		DUK_TVAL_SET_TVAL(tv_out, DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(heap, obj, e_idx));
 		return 1;
 	}
+	DUK_TVAL_SET_UNDEFINED(tv_out);
 	return 0;
 }
 
-duk_hstring *duk_hobject_get_internal_value_string(duk_heap *heap, duk_hobject *obj) {
+DUK_INTERNAL duk_hstring *duk_hobject_get_internal_value_string(duk_heap *heap, duk_hobject *obj) {
 	duk_tval tv;
 
 	DUK_ASSERT(heap != NULL);
 	DUK_ASSERT(obj != NULL);
 
+	/* This is not strictly necessary, but avoids compiler warnings; e.g.
+	 * gcc won't reliably detect that no uninitialized data is read below.
+	 */
+	DUK_MEMZERO((void *) &tv, sizeof(duk_tval));
+
 	if (duk_hobject_get_internal_value(heap, obj, &tv)) {
 		duk_hstring *h;
 		DUK_ASSERT(DUK_TVAL_IS_STRING(&tv));
@@ -35296,22 +50749,6 @@ duk_hstring *duk_hobject_get_internal_value_string(duk_heap *heap, duk_hobject *
 	return NULL;
 }
 
-duk_hbuffer *duk_hobject_get_internal_value_buffer(duk_heap *heap, duk_hobject *obj) {
-	duk_tval tv;
-
-	DUK_ASSERT(heap != NULL);
-	DUK_ASSERT(obj != NULL);
-
-	if (duk_hobject_get_internal_value(heap, obj, &tv)) {
-		duk_hbuffer *h;
-		DUK_ASSERT(DUK_TVAL_IS_BUFFER(&tv));
-		h = DUK_TVAL_GET_BUFFER(&tv);
-		return h;
-	}
-
-	return NULL;
-}
-
 /*
  *  Arguments handling helpers (argument map mainly).
  *
@@ -35325,12 +50762,13 @@ duk_hbuffer *duk_hobject_get_internal_value_buffer(duk_heap *heap, duk_hobject *
  * if mapped, and leave the result on top of stack (and return non-zero).
  * Used in E5 Section 10.6 algorithms [[Get]] and [[GetOwnProperty]].
  */
-static duk_bool_t duk__lookup_arguments_map(duk_hthread *thr,
-                                            duk_hobject *obj,
-                                            duk_hstring *key,
-                                            duk_propdesc *temp_desc,
-                                            duk_hobject **out_map,
-                                            duk_hobject **out_varenv) {
+DUK_LOCAL
+duk_bool_t duk__lookup_arguments_map(duk_hthread *thr,
+                                     duk_hobject *obj,
+                                     duk_hstring *key,
+                                     duk_propdesc *temp_desc,
+                                     duk_hobject **out_map,
+                                     duk_hobject **out_varenv) {
 	duk_context *ctx = (duk_context *) thr;
 	duk_hobject *map;
 	duk_hobject *varenv;
@@ -35343,7 +50781,7 @@ static duk_bool_t duk__lookup_arguments_map(duk_hthread *thr,
 	                     (void *) thr, (void *) obj, (void *) key, (void *) temp_desc,
 	                     (duk_heaphdr *) obj, (duk_heaphdr *) key));
 
-	if (!duk__get_own_property_desc(thr, obj, DUK_HTHREAD_STRING_INT_MAP(thr), temp_desc, 1)) {  /* push_value = 1 */
+	if (!duk__get_own_property_desc(thr, obj, DUK_HTHREAD_STRING_INT_MAP(thr), temp_desc, DUK__DESC_FLAG_PUSH_VALUE)) {
 		DUK_DDD(DUK_DDDPRINT("-> no 'map'"));
 		return 0;
 	}
@@ -35351,8 +50789,8 @@ static duk_bool_t duk__lookup_arguments_map(duk_hthread *thr,
 	map = duk_require_hobject(ctx, -1);
 	DUK_ASSERT(map != NULL);
 	duk_pop(ctx);  /* map is reachable through obj */
-	
-	if (!duk__get_own_property_desc(thr, map, key, temp_desc, 1)) {  /* push_value = 1 */
+
+	if (!duk__get_own_property_desc(thr, map, key, temp_desc, DUK__DESC_FLAG_PUSH_VALUE)) {
 		DUK_DDD(DUK_DDDPRINT("-> 'map' exists, but key not in map"));
 		return 0;
 	}
@@ -35363,7 +50801,7 @@ static duk_bool_t duk__lookup_arguments_map(duk_hthread *thr,
 	DUK_ASSERT(duk_is_string(ctx, -1));  /* guaranteed when building arguments */
 
 	/* get varenv for varname (callee's declarative lexical environment) */
-	rc = duk__get_own_property_desc(thr, obj, DUK_HTHREAD_STRING_INT_VARENV(thr), temp_desc, 1);  /* push_value = 1 */
+	rc = duk__get_own_property_desc(thr, obj, DUK_HTHREAD_STRING_INT_VARENV(thr), temp_desc, DUK__DESC_FLAG_PUSH_VALUE);
 	DUK_UNREF(rc);
 	DUK_ASSERT(rc != 0);  /* arguments MUST have an initialized lexical environment reference */
 	varenv = duk_require_hobject(ctx, -1);
@@ -35382,7 +50820,7 @@ static duk_bool_t duk__lookup_arguments_map(duk_hthread *thr,
  * on stack top if mapped (and return non-zero).
  * Used in E5 Section 10.6 algorithm for [[GetOwnProperty]] (used by [[Get]]).
  */
-static duk_bool_t duk__check_arguments_map_for_get(duk_hthread *thr, duk_hobject *obj, duk_hstring *key, duk_propdesc *temp_desc) {
+DUK_LOCAL duk_bool_t duk__check_arguments_map_for_get(duk_hthread *thr, duk_hobject *obj, duk_hstring *key, duk_propdesc *temp_desc) {
 	duk_context *ctx = (duk_context *) thr;
 	duk_hobject *map;
 	duk_hobject *varenv;
@@ -35420,7 +50858,7 @@ static duk_bool_t duk__check_arguments_map_for_get(duk_hthread *thr, duk_hobject
  * Used in E5 Section 10.6 algorithm for [[DefineOwnProperty]] (used by [[Put]]).
  * Assumes stack top contains 'put' value (which is NOT popped).
  */
-static void duk__check_arguments_map_for_put(duk_hthread *thr, duk_hobject *obj, duk_hstring *key, duk_propdesc *temp_desc, duk_bool_t throw_flag) {
+DUK_LOCAL void duk__check_arguments_map_for_put(duk_hthread *thr, duk_hobject *obj, duk_hstring *key, duk_propdesc *temp_desc, duk_bool_t throw_flag) {
 	duk_context *ctx = (duk_context *) thr;
 	duk_hobject *map;
 	duk_hobject *varenv;
@@ -35464,13 +50902,13 @@ static void duk__check_arguments_map_for_put(duk_hthread *thr, duk_hobject *obj,
  * Used in E5 Section 10.6 algorithm for [[Delete]].  Note that the
  * variable/argument itself (where the map points) is not deleted.
  */
-static void duk__check_arguments_map_for_delete(duk_hthread *thr, duk_hobject *obj, duk_hstring *key, duk_propdesc *temp_desc) {
+DUK_LOCAL void duk__check_arguments_map_for_delete(duk_hthread *thr, duk_hobject *obj, duk_hstring *key, duk_propdesc *temp_desc) {
 	duk_context *ctx = (duk_context *) thr;
 	duk_hobject *map;
 
 	DUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);
 
-	if (!duk__get_own_property_desc(thr, obj, DUK_HTHREAD_STRING_INT_MAP(thr), temp_desc, 1)) {  /* push_value = 1 */
+	if (!duk__get_own_property_desc(thr, obj, DUK_HTHREAD_STRING_INT_MAP(thr), temp_desc, DUK__DESC_FLAG_PUSH_VALUE)) {
 		DUK_DDD(DUK_DDDPRINT("arguments: key not mapped, no exotic delete behavior"));
 		return;
 	}
@@ -35478,7 +50916,7 @@ static void duk__check_arguments_map_for_delete(duk_hthread *thr, duk_hobject *o
 	map = duk_require_hobject(ctx, -1);
 	DUK_ASSERT(map != NULL);
 	duk_pop(ctx);  /* map is reachable through obj */
-	
+
 	DUK_DDD(DUK_DDDPRINT("-> have 'map', delete key %!O from map (if exists)); ignore result",
 	                     (duk_heaphdr *) key));
 
@@ -35494,13 +50932,14 @@ static void duk__check_arguments_map_for_delete(duk_hthread *thr, duk_hobject *o
  *
  *  If property is found:
  *    - Fills descriptor fields to 'out_desc'
- *    - If 'push_value' is non-zero, pushes a value related to the
+ *    - If DUK__DESC_FLAG_PUSH_VALUE is set, pushes a value related to the
  *      property onto the stack ('undefined' for accessor properties).
  *    - Returns non-zero
  *
  *  If property is not found:
  *    - 'out_desc' is left in untouched state (possibly garbage)
- *    - Nothing is pushed onto the stack (not even with push_value set)
+ *    - Nothing is pushed onto the stack (not even with DUK__DESC_FLAG_PUSH_VALUE
+ *      set)
  *    - Returns zero
  *
  *  Notes:
@@ -35527,14 +50966,14 @@ static void duk__check_arguments_map_for_delete(duk_hthread *thr, duk_hobject *o
  *      accessor properties later, this would need to change.
  */
 
-static duk_bool_t duk__get_own_property_desc_raw(duk_hthread *thr, duk_hobject *obj, duk_hstring *key, duk_uint32_t arr_idx, duk_propdesc *out_desc, duk_bool_t push_value) {
+DUK_LOCAL duk_bool_t duk__get_own_property_desc_raw(duk_hthread *thr, duk_hobject *obj, duk_hstring *key, duk_uint32_t arr_idx, duk_propdesc *out_desc, duk_small_uint_t flags) {
 	duk_context *ctx = (duk_context *) thr;
 	duk_tval *tv;
 
-	DUK_DDD(DUK_DDDPRINT("duk__get_own_property_desc: thr=%p, obj=%p, key=%p, out_desc=%p, push_value=%ld, "
+	DUK_DDD(DUK_DDDPRINT("duk__get_own_property_desc: thr=%p, obj=%p, key=%p, out_desc=%p, flags=%lx, "
 	                     "arr_idx=%ld (obj -> %!O, key -> %!O)",
 	                     (void *) thr, (void *) obj, (void *) key, (void *) out_desc,
-	                     (long) push_value, (long) arr_idx,
+	                     (long) flags, (long) arr_idx,
 	                     (duk_heaphdr *) obj, (duk_heaphdr *) key));
 
 	DUK_ASSERT(ctx != NULL);
@@ -35558,11 +50997,11 @@ static duk_bool_t duk__get_own_property_desc_raw(duk_hthread *thr, duk_hobject *
 	 */
 
 	if (DUK_HOBJECT_HAS_ARRAY_PART(obj) && arr_idx != DUK__NO_ARRAY_INDEX) {
-		if (arr_idx < obj->a_size) {
-			tv = DUK_HOBJECT_A_GET_VALUE_PTR(obj, arr_idx);
-			if (!DUK_TVAL_IS_UNDEFINED_UNUSED(tv)) {
+		if (arr_idx < DUK_HOBJECT_GET_ASIZE(obj)) {
+			tv = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, obj, arr_idx);
+			if (!DUK_TVAL_IS_UNUSED(tv)) {
 				DUK_DDD(DUK_DDDPRINT("-> found in array part"));
-				if (push_value) {
+				if (flags & DUK__DESC_FLAG_PUSH_VALUE) {
 					duk_push_tval(ctx, tv);
 				}
 				/* implicit attributes */
@@ -35585,15 +51024,15 @@ static duk_bool_t duk__get_own_property_desc_raw(duk_hthread *thr, duk_hobject *
 	 *  Entries part
 	 */
 
-	duk_hobject_find_existing_entry(obj, key, &out_desc->e_idx, &out_desc->h_idx);
+	duk_hobject_find_existing_entry(thr->heap, obj, key, &out_desc->e_idx, &out_desc->h_idx);
 	if (out_desc->e_idx >= 0) {
 		duk_int_t e_idx = out_desc->e_idx;
-		out_desc->flags = DUK_HOBJECT_E_GET_FLAGS(obj, e_idx);
+		out_desc->flags = DUK_HOBJECT_E_GET_FLAGS(thr->heap, obj, e_idx);
 		if (out_desc->flags & DUK_PROPDESC_FLAG_ACCESSOR) {
 			DUK_DDD(DUK_DDDPRINT("-> found accessor property in entry part"));
-			out_desc->get = DUK_HOBJECT_E_GET_VALUE_GETTER(obj, e_idx);
-			out_desc->set = DUK_HOBJECT_E_GET_VALUE_SETTER(obj, e_idx);
-			if (push_value) {
+			out_desc->get = DUK_HOBJECT_E_GET_VALUE_GETTER(thr->heap, obj, e_idx);
+			out_desc->set = DUK_HOBJECT_E_GET_VALUE_SETTER(thr->heap, obj, e_idx);
+			if (flags & DUK__DESC_FLAG_PUSH_VALUE) {
 				/* a dummy undefined value is pushed to make valstack
 				 * behavior uniform for caller
 				 */
@@ -35601,8 +51040,8 @@ static duk_bool_t duk__get_own_property_desc_raw(duk_hthread *thr, duk_hobject *
 			}
 		} else {
 			DUK_DDD(DUK_DDDPRINT("-> found plain property in entry part"));
-			tv = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(obj, e_idx);
-			if (push_value) {
+			tv = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, obj, e_idx);
+			if (flags & DUK__DESC_FLAG_PUSH_VALUE) {
 				duk_push_tval(ctx, tv);
 			}
 		}
@@ -35625,11 +51064,11 @@ static duk_bool_t duk__get_own_property_desc_raw(duk_hthread *thr, duk_hobject *
 
 			DUK_DDD(DUK_DDDPRINT("array index exists"));
 
- 			h_val = duk_hobject_get_internal_value_string(thr->heap, obj);
+			h_val = duk_hobject_get_internal_value_string(thr->heap, obj);
 			DUK_ASSERT(h_val);
 			if (arr_idx < DUK_HSTRING_GET_CHARLEN(h_val)) {
 				DUK_DDD(DUK_DDDPRINT("-> found, array index inside string"));
-				if (push_value) {
+				if (flags & DUK__DESC_FLAG_PUSH_VALUE) {
 					duk_push_hstring(ctx, h_val);
 					duk_substring(ctx, -1, arr_idx, arr_idx + 1);  /* [str] -> [substr] */
 				}
@@ -35647,9 +51086,9 @@ static duk_bool_t duk__get_own_property_desc_raw(duk_hthread *thr, duk_hobject *
 
 			DUK_DDD(DUK_DDDPRINT("-> found, key is 'length', length exotic behavior"));
 
- 			h_val = duk_hobject_get_internal_value_string(thr->heap, obj);
+			h_val = duk_hobject_get_internal_value_string(thr->heap, obj);
 			DUK_ASSERT(h_val != NULL);
-			if (push_value) {
+			if (flags & DUK__DESC_FLAG_PUSH_VALUE) {
 				duk_push_uint(ctx, (duk_uint_t) DUK_HSTRING_GET_CHARLEN(h_val));
 			}
 			out_desc->flags = DUK_PROPDESC_FLAG_VIRTUAL;  /* E5 Section 15.5.5.1 */
@@ -35657,26 +51096,35 @@ static duk_bool_t duk__get_own_property_desc_raw(duk_hthread *thr, duk_hobject *
 			DUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(obj));
 			return 1;  /* cannot be arguments exotic */
 		}
-	} else if (DUK_HOBJECT_HAS_EXOTIC_BUFFEROBJ(obj)) {
-		DUK_DDD(DUK_DDDPRINT("buffer object exotic property get for key: %!O, arr_idx: %ld",
+	} else if (DUK_HOBJECT_IS_BUFFEROBJECT(obj)) {
+		duk_hbufferobject *h_bufobj;
+		duk_uint_t byte_off;
+		duk_small_uint_t elem_size;
+
+		h_bufobj = (duk_hbufferobject *) obj;
+		DUK_ASSERT_HBUFFEROBJECT_VALID(h_bufobj);
+		DUK_DDD(DUK_DDDPRINT("bufferobject property get for key: %!O, arr_idx: %ld",
 		                     (duk_heaphdr *) key, (long) arr_idx));
 
 		if (arr_idx != DUK__NO_ARRAY_INDEX) {
-			duk_hbuffer *h_val;
-
 			DUK_DDD(DUK_DDDPRINT("array index exists"));
 
-			h_val = duk_hobject_get_internal_value_buffer(thr->heap, obj);
-			DUK_ASSERT(h_val);
-			/* SCANBUILD: h_val is known to be non-NULL but scan-build cannot
-			 * know it, so it produces NULL pointer dereference warnings for
-			 * 'h_val'.
+			/* Careful with wrapping: arr_idx upshift may easily wrap, whereas
+			 * length downshift won't.
 			 */
-
-			if (arr_idx < DUK_HBUFFER_GET_SIZE(h_val)) {
-				DUK_DDD(DUK_DDDPRINT("-> found, array index inside buffer"));
-				if (push_value) {
-					duk_push_int(ctx, ((duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(h_val))[arr_idx]);
+			if (arr_idx < (h_bufobj->length >> h_bufobj->shift)) {
+				byte_off = arr_idx << h_bufobj->shift;  /* no wrap assuming h_bufobj->length is valid */
+				elem_size = 1 << h_bufobj->shift;
+				if (flags & DUK__DESC_FLAG_PUSH_VALUE) {
+					duk_uint8_t *data;
+
+					if (h_bufobj->buf != NULL && DUK_HBUFFEROBJECT_VALID_BYTEOFFSET_EXCL(h_bufobj, byte_off + elem_size)) {
+						data = (duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h_bufobj->buf) + h_bufobj->offset + byte_off;
+						duk_hbufferobject_push_validated_read(ctx, h_bufobj, data, elem_size);
+					} else {
+						DUK_D(DUK_DPRINT("bufferobject access out of underlying buffer, ignoring (read zero)"));
+						duk_push_uint(ctx, 0);
+					}
 				}
 				out_desc->flags = DUK_PROPDESC_FLAG_WRITABLE |
 				                  DUK_PROPDESC_FLAG_ENUMERABLE |
@@ -35689,24 +51137,42 @@ static duk_bool_t duk__get_own_property_desc_raw(duk_hthread *thr, duk_hobject *
 				DUK_DDD(DUK_DDDPRINT("array index outside buffer -> normal property"));
 			}
 		} else if (key == DUK_HTHREAD_STRING_LENGTH(thr)) {
-			duk_hbuffer *h_val;
-
 			DUK_DDD(DUK_DDDPRINT("-> found, key is 'length', length exotic behavior"));
 
-			/* XXX: buffer length should be writable and have exotic behavior
-			 * like arrays.  For now, make it read-only and use explicit methods
-			 * to operate on buffer length.
-			 */
-
-			h_val = duk_hobject_get_internal_value_buffer(thr->heap, obj);
-			DUK_ASSERT(h_val != NULL);
-			if (push_value) {
-				duk_push_uint(ctx, (duk_uint_t) DUK_HBUFFER_GET_SIZE(h_val));
+			if (flags & DUK__DESC_FLAG_PUSH_VALUE) {
+				/* Length in elements: take into account shift, but
+				 * intentionally don't check the underlying buffer here.
+				 */
+				duk_push_uint(ctx, h_bufobj->length >> h_bufobj->shift);
 			}
 			out_desc->flags = DUK_PROPDESC_FLAG_VIRTUAL;
 
 			DUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(obj));
 			return 1;  /* cannot be arguments exotic */
+		} else if (key == DUK_HTHREAD_STRING_BYTE_LENGTH(thr)) {
+			/* If neutered must return 0; length is zeroed during
+			 * neutering.
+			 */
+			if (flags & DUK__DESC_FLAG_PUSH_VALUE) {
+				duk_push_uint(ctx, h_bufobj->length);
+			}
+			out_desc->flags = DUK_PROPDESC_FLAG_VIRTUAL;
+			return 1;  /* cannot be arguments exotic */
+		} else if (key == DUK_HTHREAD_STRING_BYTE_OFFSET(thr)) {
+			/* If neutered must return 0; offset is zeroed during
+			 * neutering.
+			 */
+			if (flags & DUK__DESC_FLAG_PUSH_VALUE) {
+				duk_push_uint(ctx, h_bufobj->offset);
+			}
+			out_desc->flags = DUK_PROPDESC_FLAG_VIRTUAL;
+			return 1;  /* cannot be arguments exotic */
+		} else if (key == DUK_HTHREAD_STRING_BYTES_PER_ELEMENT(thr)) {
+			if (flags & DUK__DESC_FLAG_PUSH_VALUE) {
+				duk_push_uint(ctx, 1 << h_bufobj->shift);
+			}
+			out_desc->flags = DUK_PROPDESC_FLAG_VIRTUAL;
+			return 1;  /* cannot be arguments exotic */
 		}
 	} else if (DUK_HOBJECT_HAS_EXOTIC_DUKFUNC(obj)) {
 		DUK_DDD(DUK_DDDPRINT("duktape/c object exotic property get for key: %!O, arr_idx: %ld",
@@ -35715,7 +51181,7 @@ static duk_bool_t duk__get_own_property_desc_raw(duk_hthread *thr, duk_hobject *
 		if (key == DUK_HTHREAD_STRING_LENGTH(thr)) {
 			DUK_DDD(DUK_DDDPRINT("-> found, key is 'length', length exotic behavior"));
 
-			if (push_value) {
+			if (flags & DUK__DESC_FLAG_PUSH_VALUE) {
 				duk_int16_t func_nargs = ((duk_hnativefunction *) obj)->nargs;
 				duk_push_int(ctx, func_nargs == DUK_HNATIVEFUNCTION_NARGS_VARARGS ? 0 : func_nargs);
 			}
@@ -35755,12 +51221,12 @@ static duk_bool_t duk__get_own_property_desc_raw(duk_hthread *thr, duk_hobject *
 	 *  - only numbered indices are relevant, so arr_idx fast reject is good
 	 *    (this is valid unless there are more than 4**32-1 arguments).
 	 *  - since variable lookup has no side effects, this can be skipped if
-	 *    push_value == 0.
+	 *    DUK__DESC_FLAG_PUSH_VALUE is not set.
 	 */
 
 	if (DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(obj) &&
 	    arr_idx != DUK__NO_ARRAY_INDEX &&
-	    push_value) {
+	    (flags & DUK__DESC_FLAG_PUSH_VALUE)) {
 		duk_propdesc temp_desc;
 
 		/* Magically bound variable cannot be an accessor.  However,
@@ -35771,7 +51237,7 @@ static duk_bool_t duk__get_own_property_desc_raw(duk_hthread *thr, duk_hobject *
 		 */
 
 		/* replaces top of stack with new value if necessary */
-		DUK_ASSERT(push_value != 0);
+		DUK_ASSERT((flags & DUK__DESC_FLAG_PUSH_VALUE) != 0);
 
 		if (duk__check_arguments_map_for_get(thr, obj, key, &temp_desc)) {
 			DUK_DDD(DUK_DDDPRINT("-> arguments exotic behavior overrides result: %!T -> %!T",
@@ -35785,14 +51251,14 @@ static duk_bool_t duk__get_own_property_desc_raw(duk_hthread *thr, duk_hobject *
 	return 1;
 }
 
-static duk_bool_t duk__get_own_property_desc(duk_hthread *thr, duk_hobject *obj, duk_hstring *key, duk_propdesc *out_desc, duk_bool_t push_value) {
+DUK_LOCAL duk_bool_t duk__get_own_property_desc(duk_hthread *thr, duk_hobject *obj, duk_hstring *key, duk_propdesc *out_desc, duk_small_uint_t flags) {
 	DUK_ASSERT(thr != NULL);
 	DUK_ASSERT(obj != NULL);
 	DUK_ASSERT(key != NULL);
 	DUK_ASSERT(out_desc != NULL);
 	DUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);
 
-	return duk__get_own_property_desc_raw(thr, obj, key, DUK_HSTRING_GET_ARRIDX_SLOW(key), out_desc, push_value);
+	return duk__get_own_property_desc_raw(thr, obj, key, DUK_HSTRING_GET_ARRIDX_SLOW(key), out_desc, flags);
 }
 
 /*
@@ -35800,20 +51266,21 @@ static duk_bool_t duk__get_own_property_desc(duk_hthread *thr, duk_hobject *obj,
  *
  *  If property is found:
  *    - Fills descriptor fields to 'out_desc'
- *    - If 'push_value' is non-zero, pushes a value related to the
+ *    - If DUK__DESC_FLAG_PUSH_VALUE is set, pushes a value related to the
  *      property onto the stack ('undefined' for accessor properties).
  *    - Returns non-zero
  *
  *  If property is not found:
  *    - 'out_desc' is left in untouched state (possibly garbage)
- *    - Nothing is pushed onto the stack (not even with push_value set)
+ *    - Nothing is pushed onto the stack (not even with DUK__DESC_FLAG_PUSH_VALUE
+ *      set)
  *    - Returns zero
  *
  *  May cause arbitrary side effects and invalidate (most) duk_tval
  *  pointers.
  */
 
-static duk_bool_t duk__get_property_desc(duk_hthread *thr, duk_hobject *obj, duk_hstring *key, duk_propdesc *out_desc, duk_bool_t push_value) {
+DUK_LOCAL duk_bool_t duk__get_property_desc(duk_hthread *thr, duk_hobject *obj, duk_hstring *key, duk_propdesc *out_desc, duk_small_uint_t flags) {
 	duk_hobject *curr;
 	duk_uint32_t arr_idx;
 	duk_uint_t sanity;
@@ -35827,26 +51294,31 @@ static duk_bool_t duk__get_property_desc(duk_hthread *thr, duk_hobject *obj, duk
 
 	arr_idx = DUK_HSTRING_GET_ARRIDX_FAST(key);
 
-	DUK_DDD(DUK_DDDPRINT("duk__get_property_desc: thr=%p, obj=%p, key=%p, out_desc=%p, push_value=%ld, "
+	DUK_DDD(DUK_DDDPRINT("duk__get_property_desc: thr=%p, obj=%p, key=%p, out_desc=%p, flags=%lx, "
 	                     "arr_idx=%ld (obj -> %!O, key -> %!O)",
 	                     (void *) thr, (void *) obj, (void *) key, (void *) out_desc,
-	                     (long) push_value, (long) arr_idx,
+	                     (long) flags, (long) arr_idx,
 	                     (duk_heaphdr *) obj, (duk_heaphdr *) key));
 
 	curr = obj;
 	DUK_ASSERT(curr != NULL);
 	sanity = DUK_HOBJECT_PROTOTYPE_CHAIN_SANITY;
 	do {
-		if (duk__get_own_property_desc_raw(thr, curr, key, arr_idx, out_desc, push_value)) {
-			/* stack contains value, 'out_desc' is set */
+		if (duk__get_own_property_desc_raw(thr, curr, key, arr_idx, out_desc, flags)) {
+			/* stack contains value (if requested), 'out_desc' is set */
 			return 1;
 		}
 
 		/* not found in 'curr', next in prototype chain; impose max depth */
 		if (sanity-- == 0) {
-			DUK_ERROR(thr, DUK_ERR_INTERNAL_ERROR, DUK_STR_PROTOTYPE_CHAIN_LIMIT);
+			if (flags & DUK__DESC_FLAG_IGNORE_PROTOLOOP) {
+				/* treat like property not found */
+				break;
+			} else {
+				DUK_ERROR(thr, DUK_ERR_INTERNAL_ERROR, DUK_STR_PROTOTYPE_CHAIN_LIMIT);
+			}
 		}
-		curr = curr->prototype;
+		curr = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, curr);
 	} while (curr);
 
 	/* out_desc is left untouched (possibly garbage), caller must use return
@@ -35876,98 +51348,251 @@ static duk_bool_t duk__get_property_desc(duk_hthread *thr, duk_hobject *obj, duk
  *  standard Array objects.
  */
 
-#if 0  /* XXX: unused now */
-static duk_tval *duk__shallow_fast_path_array_check_u32(duk_hobject *obj, duk_uint32_t key_idx) {
+DUK_LOCAL duk_tval *duk__getprop_shallow_fastpath_array_tval(duk_hthread *thr, duk_hobject *obj, duk_tval *tv_key) {
 	duk_tval *tv;
+	duk_uint32_t idx;
+
+	DUK_UNREF(thr);
 
-	if ((!DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(obj)) &&
-	    (!DUK_HOBJECT_HAS_EXOTIC_STRINGOBJ(obj)) &&
-	    (!DUK_HOBJECT_HAS_EXOTIC_BUFFEROBJ(obj)) &&
-	    (!DUK_HOBJECT_HAS_EXOTIC_PROXYOBJ(obj)) &&
-	    (DUK_HOBJECT_HAS_ARRAY_PART(obj)) &&
-	    (key_idx < obj->a_size)) {
-		/* technically required to check, but obj->a_size check covers this */
-		DUK_ASSERT(key_idx != 0xffffffffUL);
+	if (!(DUK_HOBJECT_HAS_ARRAY_PART(obj) &&
+	     !DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(obj) &&
+	     !DUK_HOBJECT_HAS_EXOTIC_STRINGOBJ(obj) &&
+	     !DUK_HOBJECT_IS_BUFFEROBJECT(obj) &&
+	     !DUK_HOBJECT_HAS_EXOTIC_PROXYOBJ(obj))) {
+		/* Must have array part and no conflicting exotic behaviors.
+		 * Doesn't need to have array special behavior, e.g. Arguments
+		 * object has array part.
+		 */
+		return NULL;
+	}
 
-		DUK_DDD(DUK_DDDPRINT("fast path attempt (key is an array index, no exotic "
-		                     "string/arguments/buffer behavior, object has array part, key "
-		                     "inside array size)"));
+	/* Arrays never have other exotic behaviors. */
 
-		DUK_ASSERT(obj->a_size > 0);  /* true even for key_idx == 0 */
-		tv = DUK_HOBJECT_A_GET_VALUE_PTR(obj, key_idx);
-		if (!DUK_TVAL_IS_UNDEFINED_UNUSED(tv)) {
-			DUK_DDD(DUK_DDDPRINT("-> fast path successful"));
-			return tv;
-		}
+	DUK_DDD(DUK_DDDPRINT("fast path attempt (no exotic string/arguments/buffer "
+	                     "behavior, object has array part)"));
 
-		/*
-		 *  Not found, fall back to slow path.
-		 *
-		 *  Note: this approach has the unfortunate side effect that accesses
-		 *  to undefined entries (or entries outside valid array range) cause
-		 *  a string intern operation.
-		 */
+#if defined(DUK_USE_FASTINT)
+	if (DUK_TVAL_IS_FASTINT(tv_key)) {
+		idx = duk__tval_fastint_to_arr_idx(tv_key);
+	} else
+#endif
+	if (DUK_TVAL_IS_DOUBLE(tv_key)) {
+		idx = duk__tval_number_to_arr_idx(tv_key);
+	} else {
+		DUK_DDD(DUK_DDDPRINT("key is not a number"));
+		return NULL;
+	}
+
+	/* If index is not valid, idx will be DUK__NO_ARRAY_INDEX which
+	 * is 0xffffffffUL.  We don't need to check for that explicitly
+	 * because 0xffffffffUL will never be inside object 'a_size'.
+	 */
+
+	if (idx >= DUK_HOBJECT_GET_ASIZE(obj)) {
+		DUK_DDD(DUK_DDDPRINT("key is not an array index or outside array part"));
+		return NULL;
+	}
+	DUK_ASSERT(idx != 0xffffffffUL);
+	DUK_ASSERT(idx != DUK__NO_ARRAY_INDEX);
 
-		DUK_DDD(DUK_DDDPRINT("fast path attempt failed, fall back to slow path"));
+	/* XXX: for array instances we could take a shortcut here and assume
+	 * Array.prototype doesn't contain an array index property.
+	 */
+
+	DUK_DDD(DUK_DDDPRINT("key is a valid array index and inside array part"));
+	tv = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, obj, idx);
+	if (!DUK_TVAL_IS_UNUSED(tv)) {
+		DUK_DDD(DUK_DDDPRINT("-> fast path successful"));
+		return tv;
 	}
 
+	DUK_DDD(DUK_DDDPRINT("fast path attempt failed, fall back to slow path"));
 	return NULL;
 }
-#endif
 
-static duk_tval *duk__shallow_fast_path_array_check_tval(duk_hobject *obj, duk_tval *key_tv) {
+DUK_LOCAL duk_bool_t duk__putprop_shallow_fastpath_array_tval(duk_hthread *thr, duk_hobject *obj, duk_tval *tv_key, duk_tval *tv_val, duk_propdesc *temp_desc) {
 	duk_tval *tv;
+	duk_uint32_t idx;
+	duk_uint32_t old_len, new_len;
 
-	if (DUK_TVAL_IS_NUMBER(key_tv) &&
-	    (!DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(obj)) &&
-	    (!DUK_HOBJECT_HAS_EXOTIC_STRINGOBJ(obj)) &&
-	    (!DUK_HOBJECT_HAS_EXOTIC_BUFFEROBJ(obj)) &&
-	    (!DUK_HOBJECT_HAS_EXOTIC_PROXYOBJ(obj)) &&
-	    (DUK_HOBJECT_HAS_ARRAY_PART(obj))) {
-		duk_uint32_t idx;
-
-		DUK_DDD(DUK_DDDPRINT("fast path attempt (key is a number, no exotic string/arguments/buffer "
-		                     "behavior, object has array part)"));
-
-		idx = duk__tval_number_to_arr_idx(key_tv);
-
-		if (idx != DUK__NO_ARRAY_INDEX) {
-			/* Note: idx is not necessarily a valid array index (0xffffffffUL is not valid) */
-			DUK_ASSERT_DISABLE(idx >= 0);  /* disabled because idx is duk_uint32_t so always true */
-			DUK_ASSERT_DISABLE(idx <= 0xffffffffUL);  /* same */
-
-			if (idx < obj->a_size) {
-				/* technically required to check, but obj->a_size check covers this */
-				DUK_ASSERT(idx != 0xffffffffUL);
-
-				DUK_DDD(DUK_DDDPRINT("key is a valid array index and inside array part"));
-				tv = DUK_HOBJECT_A_GET_VALUE_PTR(obj, idx);
-				if (!DUK_TVAL_IS_UNDEFINED_UNUSED(tv)) {
-					DUK_DDD(DUK_DDDPRINT("-> fast path successful"));
-					return tv;
-				}
-			} else {
-				DUK_DDD(DUK_DDDPRINT("key is outside array part"));
-			}
-		} else {
-			DUK_DDD(DUK_DDDPRINT("key is not a valid array index"));
+	if (!(DUK_HOBJECT_HAS_EXOTIC_ARRAY(obj) &&
+	      DUK_HOBJECT_HAS_ARRAY_PART(obj) &&
+	      DUK_HOBJECT_HAS_EXTENSIBLE(obj))) {
+		return 0;
+	}
+
+#if defined(DUK_USE_FASTINT)
+	if (DUK_TVAL_IS_FASTINT(tv_key)) {
+		idx = duk__tval_fastint_to_arr_idx(tv_key);
+	} else
+#endif
+	if (DUK_TVAL_IS_DOUBLE(tv_key)) {
+		idx = duk__tval_number_to_arr_idx(tv_key);
+	} else {
+		DUK_DDD(DUK_DDDPRINT("key is not a number"));
+		return 0;
+	}
+
+	/* If index is not valid, idx will be DUK__NO_ARRAY_INDEX which
+	 * is 0xffffffffUL.  We don't need to check for that explicitly
+	 * because 0xffffffffUL will never be inside object 'a_size'.
+	 */
+
+	if (idx >= DUK_HOBJECT_GET_ASIZE(obj)) {  /* for resizing of array part, use slow path */
+		return 0;
+	}
+	DUK_ASSERT(idx != 0xffffffffUL);
+	DUK_ASSERT(idx != DUK__NO_ARRAY_INDEX);
+
+	old_len = duk__get_old_array_length(thr, obj, temp_desc);
+
+	if (idx >= old_len) {
+		DUK_DDD(DUK_DDDPRINT("write new array entry requires length update "
+		                     "(arr_idx=%ld, old_len=%ld)",
+		                     (long) idx, (long) old_len));
+		if (!(temp_desc->flags & DUK_PROPDESC_FLAG_WRITABLE)) {
+			DUK_ERROR(thr, DUK_ERR_TYPE_ERROR, DUK_STR_NOT_WRITABLE);
+			return 0;  /* not reachable */
 		}
+		new_len = idx + 1;
 
-		/*
-		 *  Not found in array part, use slow path.
-		 */
+		/* No resize has occurred so temp_desc->e_idx is still OK */
+		tv = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, obj, temp_desc->e_idx);
+		DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));
+#if defined(DUK_USE_FASTINT)
+		DUK_TVAL_SET_FASTINT_U32(tv, new_len);  /* no need for decref/incref because value is a number */
+#else
+		DUK_TVAL_SET_NUMBER(tv, (duk_double_t) new_len);  /* no need for decref/incref because value is a number */
+#endif
+	} else {
+		;
+	}
+
+	tv = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, obj, idx);
+	DUK_TVAL_SET_TVAL_UPDREF(thr, tv, tv_val);  /* side effects */
+
+	DUK_DDD(DUK_DDDPRINT("array fast path success for index %ld", (long) idx));
+	return 1;
+}
+
+/*
+ *  Fast path for bufferobject getprop/putprop
+ */
+
+DUK_LOCAL duk_bool_t duk__getprop_fastpath_bufobj_tval(duk_hthread *thr, duk_hobject *obj, duk_tval *tv_key) {
+	duk_context *ctx;
+	duk_uint32_t idx;
+	duk_hbufferobject *h_bufobj;
+	duk_uint_t byte_off;
+	duk_small_uint_t elem_size;
+	duk_uint8_t *data;
+
+	ctx = (duk_context *) thr;
 
-		DUK_DDD(DUK_DDDPRINT("fast path attempt failed, fall back to slow path"));
+	if (!DUK_HOBJECT_IS_BUFFEROBJECT(obj)) {
+		return 0;
 	}
+	h_bufobj = (duk_hbufferobject *) obj;
 
-	return NULL;
+#if defined(DUK_USE_FASTINT)
+	if (DUK_TVAL_IS_FASTINT(tv_key)) {
+		idx = duk__tval_fastint_to_arr_idx(tv_key);
+	} else
+#endif
+	if (DUK_TVAL_IS_DOUBLE(tv_key)) {
+		idx = duk__tval_number_to_arr_idx(tv_key);
+	} else {
+		return 0;
+	}
+
+	/* If index is not valid, idx will be DUK__NO_ARRAY_INDEX which
+	 * is 0xffffffffUL.  We don't need to check for that explicitly
+	 * because 0xffffffffUL will never be inside bufferobject length.
+	 */
+
+	/* Careful with wrapping (left shifting idx would be unsafe). */
+	if (idx >= (h_bufobj->length >> h_bufobj->shift)) {
+		return 0;
+	}
+	DUK_ASSERT(idx != DUK__NO_ARRAY_INDEX);
+
+	byte_off = idx << h_bufobj->shift;  /* no wrap assuming h_bufobj->length is valid */
+	elem_size = 1 << h_bufobj->shift;
+
+	if (h_bufobj->buf != NULL && DUK_HBUFFEROBJECT_VALID_BYTEOFFSET_EXCL(h_bufobj, byte_off + elem_size)) {
+		data = (duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h_bufobj->buf) + h_bufobj->offset + byte_off;
+		duk_hbufferobject_push_validated_read(ctx, h_bufobj, data, elem_size);
+	} else {
+		DUK_D(DUK_DPRINT("bufferobject access out of underlying buffer, ignoring (read zero)"));
+		duk_push_uint(ctx, 0);
+	}
+
+	return 1;
+}
+
+DUK_LOCAL duk_bool_t duk__putprop_fastpath_bufobj_tval(duk_hthread *thr, duk_hobject *obj, duk_tval *tv_key, duk_tval *tv_val) {
+	duk_context *ctx;
+	duk_uint32_t idx;
+	duk_hbufferobject *h_bufobj;
+	duk_uint_t byte_off;
+	duk_small_uint_t elem_size;
+	duk_uint8_t *data;
+
+	ctx = (duk_context *) thr;
+
+	if (!(DUK_HOBJECT_IS_BUFFEROBJECT(obj) &&
+	      DUK_TVAL_IS_NUMBER(tv_val))) {
+		return 0;
+	}
+	h_bufobj = (duk_hbufferobject *) obj;
+
+#if defined(DUK_USE_FASTINT)
+	if (DUK_TVAL_IS_FASTINT(tv_key)) {
+		idx = duk__tval_fastint_to_arr_idx(tv_key);
+	} else
+#endif
+	if (DUK_TVAL_IS_DOUBLE(tv_key)) {
+		idx = duk__tval_number_to_arr_idx(tv_key);
+	} else {
+		return 0;
+	}
+
+	/* If index is not valid, idx will be DUK__NO_ARRAY_INDEX which
+	 * is 0xffffffffUL.  We don't need to check for that explicitly
+	 * because 0xffffffffUL will never be inside bufferobject length.
+	 */
+
+	/* Careful with wrapping (left shifting idx would be unsafe). */
+	if (idx >= (h_bufobj->length >> h_bufobj->shift)) {
+		return 0;
+	}
+	DUK_ASSERT(idx != DUK__NO_ARRAY_INDEX);
+
+	byte_off = idx << h_bufobj->shift;  /* no wrap assuming h_bufobj->length is valid */
+	elem_size = 1 << h_bufobj->shift;
+
+	/* Value is required to be a number in the fast path so there
+	 * are no side effects in write coercion.
+	 */
+	duk_push_tval(ctx, tv_val);
+	DUK_ASSERT(duk_is_number(ctx, -1));
+
+	if (h_bufobj->buf != NULL && DUK_HBUFFEROBJECT_VALID_BYTEOFFSET_EXCL(h_bufobj, byte_off + elem_size)) {
+		data = (duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h_bufobj->buf) + h_bufobj->offset + byte_off;
+		duk_hbufferobject_validated_write(ctx, h_bufobj, data, elem_size);
+	} else {
+		DUK_D(DUK_DPRINT("bufferobject access out of underlying buffer, ignoring (write skipped)"));
+	}
+
+	duk_pop(ctx);
+	return 1;
 }
 
 /*
  *  GETPROP: Ecmascript property read.
  */
 
-duk_bool_t duk_hobject_getprop(duk_hthread *thr, duk_tval *tv_obj, duk_tval *tv_key) {
+DUK_INTERNAL duk_bool_t duk_hobject_getprop(duk_hthread *thr, duk_tval *tv_obj, duk_tval *tv_key) {
 	duk_context *ctx = (duk_context *) thr;
 	duk_tval tv_obj_copy;
 	duk_tval tv_key_copy;
@@ -36012,7 +51637,12 @@ duk_bool_t duk_hobject_getprop(duk_hthread *thr, duk_tval *tv_obj, duk_tval *tv_
 	case DUK_TAG_NULL: {
 		/* Note: unconditional throw */
 		DUK_DDD(DUK_DDDPRINT("base object is undefined or null -> reject"));
+#if defined(DUK_USE_PARANOID_ERRORS)
 		DUK_ERROR(thr, DUK_ERR_TYPE_ERROR, DUK_STR_INVALID_BASE);
+#else
+		DUK_ERROR(thr, DUK_ERR_TYPE_ERROR, "cannot read property %s of %s",
+		          duk_push_string_tval_readable(ctx, tv_key), duk_push_string_tval_readable(ctx, tv_obj));
+#endif
 		return 0;
 	}
 
@@ -36026,6 +51656,13 @@ duk_bool_t duk_hobject_getprop(duk_hthread *thr, duk_tval *tv_obj, duk_tval *tv_
 		duk_hstring *h = DUK_TVAL_GET_STRING(tv_obj);
 		duk_int_t pop_count;
 
+#if defined(DUK_USE_FASTINT)
+		if (DUK_TVAL_IS_FASTINT(tv_key)) {
+			arr_idx = duk__tval_fastint_to_arr_idx(tv_key);
+			DUK_DDD(DUK_DDDPRINT("base object string, key is a fast-path fastint; arr_idx %ld", (long) arr_idx));
+			pop_count = 0;
+		} else
+#endif
 		if (DUK_TVAL_IS_NUMBER(tv_key)) {
 			arr_idx = duk__tval_number_to_arr_idx(tv_key);
 			DUK_DDD(DUK_DDDPRINT("base object string, key is a fast-path number; arr_idx %ld", (long) arr_idx));
@@ -36082,6 +51719,24 @@ duk_bool_t duk_hobject_getprop(duk_hthread *thr, duk_tval *tv_obj, duk_tval *tv_
 		curr = DUK_TVAL_GET_OBJECT(tv_obj);
 		DUK_ASSERT(curr != NULL);
 
+		tmp = duk__getprop_shallow_fastpath_array_tval(thr, curr, tv_key);
+		if (tmp) {
+			duk_push_tval(ctx, tmp);
+
+			DUK_DDD(DUK_DDDPRINT("-> %!T (base is object, key is a number, array part "
+			                     "fast path)",
+			                     (duk_tval *) duk_get_tval(ctx, -1)));
+			return 1;
+		}
+
+		if (duk__getprop_fastpath_bufobj_tval(thr, curr, tv_key) != 0) {
+			/* Read value pushed on stack. */
+			DUK_DDD(DUK_DDDPRINT("-> %!T (base is bufobj, key is a number, bufferobject "
+			                     "fast path)",
+			                     (duk_tval *) duk_get_tval(ctx, -1)));
+			return 1;
+		}
+
 #if defined(DUK_USE_ES6_PROXY)
 		if (DUK_UNLIKELY(DUK_HOBJECT_HAS_EXOTIC_PROXYOBJ(curr))) {
 			duk_hobject *h_target;
@@ -36100,7 +51755,7 @@ duk_bool_t duk_hobject_getprop(duk_hthread *thr, duk_tval *tv_obj, duk_tval *tv_
 				arr_idx = duk__push_tval_to_hstring_arr_idx(ctx, tv_key, &key);
 				DUK_ASSERT(key != NULL);
 
-				if (duk__get_own_property_desc_raw(thr, h_target, key, arr_idx, &desc, 1 /*push_value*/)) {
+				if (duk__get_own_property_desc_raw(thr, h_target, key, arr_idx, &desc, DUK__DESC_FLAG_PUSH_VALUE)) {
 					duk_tval *tv_hook = duk_require_tval(ctx, -3);  /* value from hook */
 					duk_tval *tv_targ = duk_require_tval(ctx, -1);  /* value from target */
 					duk_bool_t datadesc_reject;
@@ -36137,16 +51792,6 @@ duk_bool_t duk_hobject_getprop(duk_hthread *thr, duk_tval *tv_obj, duk_tval *tv_
 		}
 #endif  /* DUK_USE_ES6_PROXY */
 
-		tmp = duk__shallow_fast_path_array_check_tval(curr, tv_key);
-		if (tmp) {
-			duk_push_tval(ctx, tmp);
-
-			DUK_DDD(DUK_DDDPRINT("-> %!T (base is object, key is a number, array part "
-			                     "fast path)",
-			                     (duk_tval *) duk_get_tval(ctx, -1)));
-			return 1;
-		}
-
 		if (DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(curr)) {
 			arr_idx = duk__push_tval_to_hstring_arr_idx(ctx, tv_key, &key);
 			DUK_ASSERT(key != NULL);
@@ -36180,6 +51825,14 @@ duk_bool_t duk_hobject_getprop(duk_hthread *thr, duk_tval *tv_obj, duk_tval *tv_
 		 *  is important.
 		 */
 
+#if defined(DUK_USE_FASTINT)
+		if (DUK_TVAL_IS_FASTINT(tv_key)) {
+			arr_idx = duk__tval_fastint_to_arr_idx(tv_key);
+			DUK_DDD(DUK_DDDPRINT("base object buffer, key is a fast-path fastint; arr_idx %ld", (long) arr_idx));
+			pop_count = 0;
+		}
+		else
+#endif
 		if (DUK_TVAL_IS_NUMBER(tv_key)) {
 			arr_idx = duk__tval_number_to_arr_idx(tv_key);
 			DUK_DDD(DUK_DDDPRINT("base object buffer, key is a fast-path number; arr_idx %ld", (long) arr_idx));
@@ -36196,7 +51849,7 @@ duk_bool_t duk_hobject_getprop(duk_hthread *thr, duk_tval *tv_obj, duk_tval *tv_
 		if (arr_idx != DUK__NO_ARRAY_INDEX &&
 		    arr_idx < DUK_HBUFFER_GET_SIZE(h)) {
 			duk_pop_n(ctx, pop_count);
-			duk_push_int(ctx, ((duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(h))[arr_idx]);
+			duk_push_uint(ctx, ((duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h))[arr_idx]);
 
 			DUK_DDD(DUK_DDDPRINT("-> %!T (base is buffer, key is an index inside buffer length "
 			                     "after coercion -> return byte as number)",
@@ -36215,12 +51868,29 @@ duk_bool_t duk_hobject_getprop(duk_hthread *thr, duk_tval *tv_obj, duk_tval *tv_
 			                     (duk_tval *) duk_get_tval(ctx, -1), (long) arr_idx));
 		}
 
-		if (key == DUK_HTHREAD_STRING_LENGTH(thr)) {
+		if (key == DUK_HTHREAD_STRING_LENGTH(thr) ||
+		    key == DUK_HTHREAD_STRING_BYTE_LENGTH(thr)) {
 			duk_pop(ctx);  /* [key] -> [] */
 			duk_push_uint(ctx, (duk_uint_t) DUK_HBUFFER_GET_SIZE(h));  /* [] -> [res] */
 
-			DUK_DDD(DUK_DDDPRINT("-> %!T (base is buffer, key is 'length' after coercion -> "
-			                     "return buffer length)",
+			DUK_DDD(DUK_DDDPRINT("-> %!T (base is buffer, key is 'length' or 'byteLength' "
+			                     "after coercion -> return buffer length)",
+			                     (duk_tval *) duk_get_tval(ctx, -1)));
+			return 1;
+		} else if (key == DUK_HTHREAD_STRING_BYTE_OFFSET(thr)) {
+			duk_pop(ctx);  /* [key] -> [] */
+			duk_push_uint(ctx, 0);  /* [] -> [res] */
+
+			DUK_DDD(DUK_DDDPRINT("-> %!T (base is buffer, key is 'byteOffset' after coercion -> "
+			                     "return 0 for consistency with Buffer objects)",
+			                     (duk_tval *) duk_get_tval(ctx, -1)));
+			return 1;
+		} else if (key == DUK_HTHREAD_STRING_BYTES_PER_ELEMENT(thr)) {
+			duk_pop(ctx);  /* [key] -> [] */
+			duk_push_uint(ctx, 1);  /* [] -> [res] */
+
+			DUK_DDD(DUK_DDDPRINT("-> %!T (base is buffer, key is 'BYTES_PER_ELEMENT' after coercion -> "
+			                     "return 1 for consistency with Buffer objects)",
 			                     (duk_tval *) duk_get_tval(ctx, -1)));
 			return 1;
 		}
@@ -36236,9 +51906,35 @@ duk_bool_t duk_hobject_getprop(duk_hthread *thr, duk_tval *tv_obj, duk_tval *tv_
 		break;
 	}
 
+	case DUK_TAG_LIGHTFUNC: {
+		duk_int_t lf_flags = DUK_TVAL_GET_LIGHTFUNC_FLAGS(tv_obj);
+
+		/* Must coerce key: if key is an object, it may coerce to e.g. 'length'. */
+		arr_idx = duk__push_tval_to_hstring_arr_idx(ctx, tv_key, &key);
+
+		if (key == DUK_HTHREAD_STRING_LENGTH(thr)) {
+			duk_int_t lf_len = DUK_LFUNC_FLAGS_GET_LENGTH(lf_flags);
+			duk_pop(ctx);
+			duk_push_int(ctx, lf_len);
+			return 1;
+		} else if (key == DUK_HTHREAD_STRING_NAME(thr)) {
+			duk_pop(ctx);
+			duk_push_lightfunc_name(ctx, tv_obj);
+			return 1;
+		}
+
+		DUK_DDD(DUK_DDDPRINT("base object is a lightfunc, start lookup from function prototype"));
+		curr = thr->builtins[DUK_BIDX_FUNCTION_PROTOTYPE];
+		goto lookup;  /* avoid double coercion */
+	}
+
+#if defined(DUK_USE_FASTINT)
+	case DUK_TAG_FASTINT:
+#endif
 	default: {
 		/* number */
 		DUK_DDD(DUK_DDDPRINT("base object is a number, start lookup from number prototype"));
+		DUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv_obj));
 		DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv_obj));
 		curr = thr->builtins[DUK_BIDX_NUMBER_PROTOTYPE];
 		break;
@@ -36261,7 +51957,7 @@ duk_bool_t duk_hobject_getprop(duk_hthread *thr, duk_tval *tv_obj, duk_tval *tv_
 
 	sanity = DUK_HOBJECT_PROTOTYPE_CHAIN_SANITY;
 	do {
-		if (!duk__get_own_property_desc_raw(thr, curr, key, arr_idx, &desc, 1 /*push_value*/)) {
+		if (!duk__get_own_property_desc_raw(thr, curr, key, arr_idx, &desc, DUK__DESC_FLAG_PUSH_VALUE)) {
 			goto next_in_chain;
 		}
 
@@ -36299,10 +51995,13 @@ duk_bool_t duk_hobject_getprop(duk_hthread *thr, duk_tval *tv_obj, duk_tval *tv_
 		goto found;  /* [key result] */
 
 	 next_in_chain:
+		/* XXX: option to pretend property doesn't exist if sanity limit is
+		 * hit might be useful.
+		 */
 		if (sanity-- == 0) {
 			DUK_ERROR(thr, DUK_ERR_INTERNAL_ERROR, DUK_STR_PROTOTYPE_CHAIN_LIMIT);
 		}
-		curr = curr->prototype;
+		curr = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, curr);
 	} while (curr);
 
 	/*
@@ -36322,25 +52021,47 @@ duk_bool_t duk_hobject_getprop(duk_hthread *thr, duk_tval *tv_obj, duk_tval *tv_
 	/* [key result] */
 
 #if !defined(DUK_USE_NONSTD_FUNC_CALLER_PROPERTY)
-	/* This exotic behavior is disabled when the non-standard 'caller' property
+	/* Special behavior for 'caller' property of (non-bound) function objects
+	 * and non-strict Arguments objects: if 'caller' -value- (!) is a strict
+	 * mode function, throw a TypeError (E5 Sections 15.3.5.4, 10.6).
+	 * Quite interestingly, a non-strict function with no formal arguments
+	 * will get an arguments object -without- special 'caller' behavior!
+	 *
+	 * The E5.1 spec is a bit ambiguous if this special behavior applies when
+	 * a bound function is the base value (not the 'caller' value): Section
+	 * 15.3.4.5 (describing bind()) states that [[Get]] for bound functions
+	 * matches that of Section 15.3.5.4 ([[Get]] for Function instances).
+	 * However, Section 13.3.5.4 has "NOTE: Function objects created using
+	 * Function.prototype.bind use the default [[Get]] internal method."
+	 * The current implementation assumes this means that bound functions
+	 * should not have the special [[Get]] behavior.
+	 *
+	 * The E5.1 spec is also a bit unclear if the TypeError throwing is
+	 * applied if the 'caller' value is a strict bound function.  The
+	 * current implementation will throw even for both strict non-bound
+	 * and strict bound functions.
+	 *
+	 * See test-dev-strict-func-as-caller-prop-value.js for quite extensive
+	 * tests.
+	 *
+	 * This exotic behavior is disabled when the non-standard 'caller' property
 	 * is enabled, as it conflicts with the free use of 'caller'.
 	 */
 	if (key == DUK_HTHREAD_STRING_CALLER(thr) &&
 	    DUK_TVAL_IS_OBJECT(tv_obj)) {
 		duk_hobject *orig = DUK_TVAL_GET_OBJECT(tv_obj);
+		DUK_ASSERT(orig != NULL);
 
 		if (DUK_HOBJECT_IS_NONBOUND_FUNCTION(orig) ||
 		    DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(orig)) {
 			duk_hobject *h;
 
-			/* FIXME: is this behavior desired for bound functions too?
-			 * E5.1 Section 15.3.4.5 step 6 seems to indicate so, while
-			 * E5.1 Section 15.3.5.4 "NOTE" indicates that bound functions
-			 * have a default [[Get]] method.
-			 *
-			 * Also, must the value Function object be a non-bound function?
+			/* XXX: The TypeError is currently not applied to bound
+			 * functions because the 'strict' flag is not copied by
+			 * bind().  This may or may not be correct, the specification
+			 * only refers to the value being a "strict mode Function
+			 * object" which is ambiguous.
 			 */
-
 			DUK_ASSERT(!DUK_HOBJECT_HAS_BOUND(orig));
 
 			h = duk_get_hobject(ctx, -1);  /* NULL if not an object */
@@ -36367,7 +52088,7 @@ duk_bool_t duk_hobject_getprop(duk_hthread *thr, duk_tval *tv_obj, duk_tval *tv_
  *  the target object.
  */
 
-duk_bool_t duk_hobject_hasprop(duk_hthread *thr, duk_tval *tv_obj, duk_tval *tv_key) {
+DUK_INTERNAL duk_bool_t duk_hobject_hasprop(duk_hthread *thr, duk_tval *tv_obj, duk_tval *tv_key) {
 	duk_context *ctx = (duk_context *) thr;
 	duk_tval tv_key_copy;
 	duk_hobject *obj;
@@ -36389,18 +52110,49 @@ duk_bool_t duk_hobject_hasprop(duk_hthread *thr, duk_tval *tv_obj, duk_tval *tv_
 	DUK_TVAL_SET_TVAL(&tv_key_copy, tv_key);
 	tv_key = &tv_key_copy;
 
-	if (!DUK_TVAL_IS_OBJECT(tv_obj)) {
+	/*
+	 *  The 'in' operator requires an object as its right hand side,
+	 *  throwing a TypeError unconditionally if this is not the case.
+	 *
+	 *  However, lightfuncs need to behave like fully fledged objects
+	 *  here to be maximally transparent, so we need to handle them
+	 *  here.
+	 */
+
+	/* XXX: Refactor key coercion so that it's only called once.  It can't
+	 * be trivially lifted here because the object must be type checked
+	 * first.
+	 */
+
+	if (DUK_TVAL_IS_OBJECT(tv_obj)) {
+		obj = DUK_TVAL_GET_OBJECT(tv_obj);
+		DUK_ASSERT(obj != NULL);
+
+		arr_idx = duk__push_tval_to_hstring_arr_idx(ctx, tv_key, &key);
+	} else if (DUK_TVAL_IS_LIGHTFUNC(tv_obj)) {
+		arr_idx = duk__push_tval_to_hstring_arr_idx(ctx, tv_key, &key);
+		if (duk__key_is_lightfunc_ownprop(thr, key)) {
+			/* FOUND */
+			rc = 1;
+			goto pop_and_return;
+		}
+
+		/* If not found, resume existence check from Function.prototype.
+		 * We can just substitute the value in this case; nothing will
+		 * need the original base value (as would be the case with e.g.
+		 * setters/getters.
+		 */
+		obj = thr->builtins[DUK_BIDX_FUNCTION_PROTOTYPE];
+	} else {
 		/* Note: unconditional throw */
 		DUK_DDD(DUK_DDDPRINT("base object is not an object -> reject"));
 		DUK_ERROR(thr, DUK_ERR_TYPE_ERROR, DUK_STR_INVALID_BASE);
 	}
-	obj = DUK_TVAL_GET_OBJECT(tv_obj);
-	DUK_ASSERT(obj != NULL);
 
 	/* XXX: fast path for arrays? */
 
-	arr_idx = duk__push_tval_to_hstring_arr_idx(ctx, tv_key, &key);
 	DUK_ASSERT(key != NULL);
+	DUK_ASSERT(obj != NULL);
 	DUK_UNREF(arr_idx);
 
 #if defined(DUK_USE_ES6_PROXY)
@@ -36425,7 +52177,7 @@ duk_bool_t duk_hobject_hasprop(duk_hthread *thr, duk_tval *tv_obj, duk_tval *tv_
 				 * non-configurable property.
 				 */
 
-				if (duk__get_own_property_desc_raw(thr, h_target, key, arr_idx, &desc, 0 /*push_value*/)) {
+				if (duk__get_own_property_desc_raw(thr, h_target, key, arr_idx, &desc, 0 /*flags*/)) {  /* don't push value */
 					DUK_DDD(DUK_DDDPRINT("proxy 'has': target has matching property %!O, check for "
 					                     "conflicting property; desc.flags=0x%08lx, "
 					                     "desc.get=%p, desc.set=%p",
@@ -36452,8 +52204,10 @@ duk_bool_t duk_hobject_hasprop(duk_hthread *thr, duk_tval *tv_obj, duk_tval *tv_
 
 	/* XXX: inline into a prototype walking loop? */
 
-	rc = duk__get_property_desc(thr, obj, key, &desc, 0);  /* push_value = 0 */
+	rc = duk__get_property_desc(thr, obj, key, &desc, 0 /*flags*/);  /* don't push value */
+	/* fall through */
 
+ pop_and_return:
 	duk_pop(ctx);  /* [ key ] -> [] */
 	return rc;
 }
@@ -36462,11 +52216,15 @@ duk_bool_t duk_hobject_hasprop(duk_hthread *thr, duk_tval *tv_obj, duk_tval *tv_
  *  HASPROP variant used internally.
  *
  *  This primitive must never throw an error, callers rely on this.
+ *  In particular, don't throw an error for prototype loops; instead,
+ *  pretend like the property doesn't exist if a prototype sanity limit
+ *  is reached.
+ *
  *  Does not implement proxy behavior: if applied to a proxy object,
  *  returns key existence on the proxy object itself.
  */
 
-duk_bool_t duk_hobject_hasprop_raw(duk_hthread *thr, duk_hobject *obj, duk_hstring *key) {
+DUK_INTERNAL duk_bool_t duk_hobject_hasprop_raw(duk_hthread *thr, duk_hobject *obj, duk_hstring *key) {
 	duk_propdesc dummy;
 
 	DUK_ASSERT(thr != NULL);
@@ -36476,7 +52234,7 @@ duk_bool_t duk_hobject_hasprop_raw(duk_hthread *thr, duk_hobject *obj, duk_hstri
 
 	DUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);
 
-	return duk__get_property_desc(thr, obj, key, &dummy, 0 /*push_value*/);
+	return duk__get_property_desc(thr, obj, key, &dummy, DUK__DESC_FLAG_IGNORE_PROTOLOOP);  /* don't push value */
 }
 
 /*
@@ -36487,50 +52245,69 @@ duk_bool_t duk_hobject_hasprop_raw(duk_hthread *thr, duk_hobject *obj, duk_hstri
  *  Used by duk_hobject_putprop().
  */
 
-static duk_uint32_t duk__get_old_array_length(duk_hthread *thr, duk_hobject *obj, duk_propdesc *temp_desc) {
+DUK_LOCAL duk_uint32_t duk__get_old_array_length(duk_hthread *thr, duk_hobject *obj, duk_propdesc *temp_desc) {
 	duk_bool_t rc;
 	duk_tval *tv;
 	duk_uint32_t res;
 
 	DUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);
 
-	/* FIXME: this assumption is actually invalid, because e.g. Array.prototype.push()
-	 * can create an array whose length is above 2**32.
-	 */
-
-	/* Call only for objects with array exotic behavior, as we assume
-	 * that the length property always exists, and always contains a
-	 * valid number value (in unsigned 32-bit range).
+	/* This function is only called for objects with array exotic behavior.
+	 * The [[DefineOwnProperty]] algorithm for arrays requires that
+	 * 'length' can never have a value outside the unsigned 32-bit range,
+	 * attempt to write such a value is a RangeError.  Here we can thus
+	 * assert for this.  When Duktape internals go around the official
+	 * property write interface (doesn't happen often) this assumption is
+	 * easy to accidentally break, so such code must be written carefully.
+	 * See test-bi-array-push-maxlen.js.
 	 */
 
-	rc = duk__get_own_property_desc_raw(thr, obj, DUK_HTHREAD_STRING_LENGTH(thr), DUK__NO_ARRAY_INDEX, temp_desc, 0);
+	rc = duk__get_own_property_desc_raw(thr, obj, DUK_HTHREAD_STRING_LENGTH(thr), DUK__NO_ARRAY_INDEX, temp_desc, 0 /*flags*/);  /* don't push value */
 	DUK_UNREF(rc);
 	DUK_ASSERT(rc != 0);  /* arrays MUST have a 'length' property */
 	DUK_ASSERT(temp_desc->e_idx >= 0);
 
-	tv = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(obj, temp_desc->e_idx);
+	tv = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, obj, temp_desc->e_idx);
 	DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));  /* array 'length' is always a number, as we coerce it */
 	DUK_ASSERT(DUK_TVAL_GET_NUMBER(tv) >= 0.0);
 	DUK_ASSERT(DUK_TVAL_GET_NUMBER(tv) <= (double) 0xffffffffUL);
+	DUK_ASSERT((duk_double_t) (duk_uint32_t) DUK_TVAL_GET_NUMBER(tv) == DUK_TVAL_GET_NUMBER(tv));
+#if defined(DUK_USE_FASTINT)
+	/* Downgrade checks are not made everywhere, so 'length' is not always
+	 * a fastint (it is a number though).  This can be removed once length
+	 * is always guaranteed to be a fastint.
+	 */
+	DUK_ASSERT(DUK_TVAL_IS_FASTINT(tv) || DUK_TVAL_IS_DOUBLE(tv));
+	if (DUK_TVAL_IS_FASTINT(tv)) {
+		res = (duk_uint32_t) DUK_TVAL_GET_FASTINT_U32(tv);
+	} else {
+		res = (duk_uint32_t) DUK_TVAL_GET_DOUBLE(tv);
+	}
+#else
 	res = (duk_uint32_t) DUK_TVAL_GET_NUMBER(tv);
-	DUK_ASSERT((duk_double_t) res == DUK_TVAL_GET_NUMBER(tv));
+#endif  /* DUK_USE_FASTINT */
 
 	return res;
 }
 
-static duk_uint32_t duk__to_new_array_length_checked(duk_hthread *thr) {
+DUK_LOCAL duk_uint32_t duk__to_new_array_length_checked(duk_hthread *thr) {
 	duk_context *ctx = (duk_context *) thr;
 	duk_uint32_t res;
+	duk_double_t d;
 
 	/* Input value should be on stack top and will be coerced and
-	 * left on stack top.
+	 * popped.  Refuse to update an Array's 'length' to a value
+	 * outside the 32-bit range.  Negative zero is accepted as zero.
 	 */
 
-	/* FIXME: coerce in_val to new_len, check that this is correct */
-	res = ((duk_uint32_t) duk_to_number(ctx, -1)) & 0xffffffffUL;
-	if (res != duk_get_number(ctx, -1)) {
+	/* XXX: fastint */
+
+	d = duk_to_number(ctx, -1);
+	res = (duk_uint32_t) d;
+	if ((duk_double_t) res != d) {
 		DUK_ERROR(thr, DUK_ERR_RANGE_ERROR, DUK_STR_INVALID_ARRAY_LENGTH);
 	}
+	duk_pop(ctx);
 	return res;
 }
 
@@ -36541,17 +52318,18 @@ static duk_uint32_t duk__to_new_array_length_checked(duk_hthread *thr) {
  * This is the length value that should go into the 'length' property
  * (must be set by the caller).  Never throws an error.
  */
-static duk_bool_t duk__handle_put_array_length_smaller(duk_hthread *thr,
-                                                       duk_hobject *obj,
-                                                       duk_uint32_t old_len,
-                                                       duk_uint32_t new_len,
-                                                       duk_uint32_t *out_result_len) {
+DUK_LOCAL
+duk_bool_t duk__handle_put_array_length_smaller(duk_hthread *thr,
+                                                duk_hobject *obj,
+                                                duk_uint32_t old_len,
+                                                duk_uint32_t new_len,
+                                                duk_bool_t force_flag,
+                                                duk_uint32_t *out_result_len) {
 	duk_uint32_t target_len;
 	duk_uint_fast32_t i;
 	duk_uint32_t arr_idx;
 	duk_hstring *key;
 	duk_tval *tv;
-	duk_tval tv_tmp;
 	duk_bool_t rc;
 
 	DUK_DDD(DUK_DDDPRINT("new array length smaller than old (%ld -> %ld), "
@@ -36588,20 +52366,18 @@ static duk_bool_t duk__handle_put_array_length_smaller(duk_hthread *thr,
 
 		DUK_DDD(DUK_DDDPRINT("have array part, easy case"));
 
-		if (old_len < obj->a_size) {
+		if (old_len < DUK_HOBJECT_GET_ASIZE(obj)) {
 			/* XXX: assertion that entries >= old_len are already unused */
 			i = old_len;
 		} else {
-			i = obj->a_size;
+			i = DUK_HOBJECT_GET_ASIZE(obj);
 		}
-		DUK_ASSERT(i <= obj->a_size);
+		DUK_ASSERT(i <= DUK_HOBJECT_GET_ASIZE(obj));
 
 		while (i > new_len) {
 			i--;
-			tv = DUK_HOBJECT_A_GET_VALUE_PTR(obj, i);
-			DUK_TVAL_SET_TVAL(&tv_tmp, tv);
-			DUK_TVAL_SET_UNDEFINED_UNUSED(tv);
-			DUK_TVAL_DECREF(thr, &tv_tmp);
+			tv = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, obj, i);
+			DUK_TVAL_SET_UNUSED_UPDREF(thr, tv);  /* side effects */
 		}
 
 		*out_result_len = new_len;
@@ -36611,7 +52387,9 @@ static duk_bool_t duk__handle_put_array_length_smaller(duk_hthread *thr,
 		 *  Entries part is a bit more complex
 		 */
 
-		/* stage 1: find highest preventing non-configurable entry (if any) */
+		/* Stage 1: find highest preventing non-configurable entry (if any).
+		 * When forcing, ignore non-configurability.
+		 */
 
 		DUK_DDD(DUK_DDDPRINT("no array part, slow case"));
 
@@ -36619,8 +52397,12 @@ static duk_bool_t duk__handle_put_array_length_smaller(duk_hthread *thr,
 		                     "(highest preventing non-configurable entry (if any))"));
 
 		target_len = new_len;
-		for (i = 0; i < obj->e_used; i++) {
-			key = DUK_HOBJECT_E_GET_KEY(obj, i);
+		if (force_flag) {
+			DUK_DDD(DUK_DDDPRINT("array length write, no array part; force flag -> skip stage 1"));
+			goto skip_stage1;
+		}
+		for (i = 0; i < DUK_HOBJECT_GET_ENEXT(obj); i++) {
+			key = DUK_HOBJECT_E_GET_KEY(thr->heap, obj, i);
 			if (!key) {
 				DUK_DDD(DUK_DDDPRINT("skip entry index %ld: null key", (long) i));
 				continue;
@@ -36640,7 +52422,7 @@ static duk_bool_t duk__handle_put_array_length_smaller(duk_hthread *thr,
 				                     (long) i, (long) arr_idx));
 				continue;
 			}
-			if (DUK_HOBJECT_E_SLOT_IS_CONFIGURABLE(obj, i)) {
+			if (DUK_HOBJECT_E_SLOT_IS_CONFIGURABLE(thr->heap, obj, i)) {
 				DUK_DDD(DUK_DDDPRINT("skip entry index %ld: key is a relevant array index %ld, but configurable",
 				                     (long) i, (long) arr_idx));
 				continue;
@@ -36655,6 +52437,7 @@ static duk_bool_t duk__handle_put_array_length_smaller(duk_hthread *thr,
 				target_len = arr_idx + 1;
 			}
 		}
+	 skip_stage1:
 
 		/* stage 2: delete configurable entries above target length */
 
@@ -36664,8 +52447,8 @@ static duk_bool_t duk__handle_put_array_length_smaller(duk_hthread *thr,
 		DUK_DDD(DUK_DDDPRINT("array length write, no array part, stage 2: remove "
 		                     "entries >= target_len"));
 
-		for (i = 0; i < obj->e_used; i++) {
-			key = DUK_HOBJECT_E_GET_KEY(obj, i);
+		for (i = 0; i < DUK_HOBJECT_GET_ENEXT(obj); i++) {
+			key = DUK_HOBJECT_E_GET_KEY(thr->heap, obj, i);
 			if (!key) {
 				DUK_DDD(DUK_DDDPRINT("skip entry index %ld: null key", (long) i));
 				continue;
@@ -36685,7 +52468,7 @@ static duk_bool_t duk__handle_put_array_length_smaller(duk_hthread *thr,
 				                     (long) i, (long) arr_idx));
 				continue;
 			}
-			DUK_ASSERT(DUK_HOBJECT_E_SLOT_IS_CONFIGURABLE(obj, i));  /* stage 1 guarantees */
+			DUK_ASSERT(force_flag || DUK_HOBJECT_E_SLOT_IS_CONFIGURABLE(thr->heap, obj, i));  /* stage 1 guarantees */
 
 			DUK_DDD(DUK_DDDPRINT("delete entry index %ld: key is array index %ld",
 			                     (long) i, (long) arr_idx));
@@ -36695,7 +52478,7 @@ static duk_bool_t duk__handle_put_array_length_smaller(duk_hthread *thr,
 			 *  The delete always succeeds: key has no exotic behavior, property
 			 *  is configurable, and no resize occurs.
 			 */
-			rc = duk_hobject_delprop_raw(thr, obj, key, 0);
+			rc = duk_hobject_delprop_raw(thr, obj, key, force_flag ? DUK_DELPROP_FLAG_FORCE : 0);
 			DUK_UNREF(rc);
 			DUK_ASSERT(rc != 0);
 		}
@@ -36719,7 +52502,7 @@ static duk_bool_t duk__handle_put_array_length_smaller(duk_hthread *thr,
 }
 
 /* XXX: is valstack top best place for argument? */
-static duk_bool_t duk__handle_put_array_length(duk_hthread *thr, duk_hobject *obj) {
+DUK_LOCAL duk_bool_t duk__handle_put_array_length(duk_hthread *thr, duk_hobject *obj) {
 	duk_context *ctx = (duk_context *) thr;
 	duk_propdesc desc;
 	duk_uint32_t old_len;
@@ -36746,8 +52529,7 @@ static duk_bool_t duk__handle_put_array_length(duk_hthread *thr, duk_hobject *ob
 
 	old_len = duk__get_old_array_length(thr, obj, &desc);
 	duk_dup(ctx, -1);  /* [in_val in_val] */
-	new_len = duk__to_new_array_length_checked(thr);
-	duk_pop(ctx);  /* [in_val in_val] -> [in_val] */
+	new_len = duk__to_new_array_length_checked(thr);  /* -> [in_val] */
 	DUK_DDD(DUK_DDDPRINT("old_len=%ld, new_len=%ld", (long) old_len, (long) new_len));
 
 	/*
@@ -36768,10 +52550,15 @@ static duk_bool_t duk__handle_put_array_length(duk_hthread *thr, duk_hobject *ob
 		DUK_DDD(DUK_DDDPRINT("new length is higher than old length, just update length, no deletions"));
 
 		DUK_ASSERT(desc.e_idx >= 0);
-		DUK_ASSERT(!DUK_HOBJECT_E_SLOT_IS_ACCESSOR(obj, desc.e_idx));
-		tv = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(obj, desc.e_idx);
+		DUK_ASSERT(!DUK_HOBJECT_E_SLOT_IS_ACCESSOR(thr->heap, obj, desc.e_idx));
+		tv = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, obj, desc.e_idx);
 		DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));
-		DUK_TVAL_SET_NUMBER(tv, (duk_double_t) new_len);  /* no decref needed for a number */
+		/* no decref needed for a number */
+#if defined(DUK_USE_FASTINT)
+		DUK_TVAL_SET_FASTINT_U32(tv, new_len);
+#else
+		DUK_TVAL_SET_NUMBER(tv, (duk_double_t) new_len);
+#endif
 		DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));
 		return 1;
 	}
@@ -36786,14 +52573,19 @@ static duk_bool_t duk__handle_put_array_length(duk_hthread *thr, duk_hobject *ob
 	 *  still valid as properties haven't been resized (and entries compacted).
 	 */
 
-	rc = duk__handle_put_array_length_smaller(thr, obj, old_len, new_len, &result_len);
+	rc = duk__handle_put_array_length_smaller(thr, obj, old_len, new_len, 0 /*force_flag*/, &result_len);
 	DUK_ASSERT(result_len >= new_len && result_len <= old_len);
 
 	DUK_ASSERT(desc.e_idx >= 0);
-	DUK_ASSERT(!DUK_HOBJECT_E_SLOT_IS_ACCESSOR(obj, desc.e_idx));
-	tv = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(obj, desc.e_idx);
+	DUK_ASSERT(!DUK_HOBJECT_E_SLOT_IS_ACCESSOR(thr->heap, obj, desc.e_idx));
+	tv = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, obj, desc.e_idx);
 	DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));
-	DUK_TVAL_SET_NUMBER(tv, (duk_double_t) result_len);  /* no decref needed for a number */
+	/* no decref needed for a number */
+#if defined(DUK_USE_FASTINT)
+	DUK_TVAL_SET_FASTINT_U32(tv, result_len);
+#else
+	DUK_TVAL_SET_NUMBER(tv, (duk_double_t) result_len);
+#endif
 	DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));
 
 	/* XXX: shrink array allocation or entries compaction here? */
@@ -36830,7 +52622,7 @@ static duk_bool_t duk__handle_put_array_length(duk_hthread *thr, duk_hobject *ob
  *      (We currently make a copy of all of the input values to avoid issues.)
  */
 
-duk_bool_t duk_hobject_putprop(duk_hthread *thr, duk_tval *tv_obj, duk_tval *tv_key, duk_tval *tv_val, duk_bool_t throw_flag) {
+DUK_INTERNAL duk_bool_t duk_hobject_putprop(duk_hthread *thr, duk_tval *tv_obj, duk_tval *tv_key, duk_tval *tv_val, duk_bool_t throw_flag) {
 	duk_context *ctx = (duk_context *) thr;
 	duk_tval tv_obj_copy;
 	duk_tval tv_key_copy;
@@ -36885,7 +52677,12 @@ duk_bool_t duk_hobject_putprop(duk_hthread *thr, duk_tval *tv_obj, duk_tval *tv_
 		/* Note: unconditional throw */
 		DUK_DDD(DUK_DDDPRINT("base object is undefined or null -> reject (object=%!iT)",
 		                     (duk_tval *) tv_obj));
+#if defined(DUK_USE_PARANOID_ERRORS)
 		DUK_ERROR(thr, DUK_ERR_TYPE_ERROR, DUK_STR_INVALID_BASE);
+#else
+		DUK_ERROR(thr, DUK_ERR_TYPE_ERROR, "cannot write property %s of %s",
+		          duk_push_string_tval_readable(ctx, tv_key), duk_push_string_tval_readable(ctx, tv_obj));
+#endif
 		return 0;
 	}
 
@@ -36922,10 +52719,34 @@ duk_bool_t duk_hobject_putprop(duk_hthread *thr, duk_tval *tv_obj, duk_tval *tv_
 	}
 
 	case DUK_TAG_OBJECT: {
-		/* Note: no fast paths for property put now */
 		orig = DUK_TVAL_GET_OBJECT(tv_obj);
 		DUK_ASSERT(orig != NULL);
 
+		/* The fast path for array property put is not fully compliant:
+		 * If one places conflicting number-indexed properties into
+		 * Array.prototype (for example, a non-writable Array.prototype[7])
+		 * the fast path will incorrectly ignore them.
+		 *
+		 * This fast path could be made compliant by falling through
+		 * to the slow path if the previous value was UNUSED.  This would
+		 * also remove the need to check for extensibility.  Right now a
+		 * non-extensible array is slower than an extensible one as far
+		 * as writes are concerned.
+		 *
+		 * The fast path behavior is documented in more detail here:
+		 * tests/ecmascript/test-misc-array-fast-write.js
+		 */
+
+		if (duk__putprop_shallow_fastpath_array_tval(thr, orig, tv_key, tv_val, &desc) != 0) {
+			DUK_DDD(DUK_DDDPRINT("array fast path success"));
+			return 1;
+		}
+
+		if (duk__putprop_fastpath_bufobj_tval(thr, orig, tv_key, tv_val) != 0) {
+			DUK_DDD(DUK_DDDPRINT("base is bufobj, key is a number, bufferobject fast path"));
+			return 1;
+		}
+
 #if defined(DUK_USE_ES6_PROXY)
 		if (DUK_UNLIKELY(DUK_HOBJECT_HAS_EXOTIC_PROXYOBJ(orig))) {
 			duk_hobject *h_target;
@@ -36951,7 +52772,7 @@ duk_bool_t duk_hobject_putprop(duk_hthread *thr, duk_tval *tv_obj, duk_tval *tv_
 				arr_idx = duk__push_tval_to_hstring_arr_idx(ctx, tv_key, &key);
 				DUK_ASSERT(key != NULL);
 
-				if (duk__get_own_property_desc_raw(thr, h_target, key, arr_idx, &desc, 1 /*push_value*/)) {
+				if (duk__get_own_property_desc_raw(thr, h_target, key, arr_idx, &desc, DUK__DESC_FLAG_PUSH_VALUE)) {
 					duk_tval *tv_targ = duk_require_tval(ctx, -1);
 					duk_bool_t datadesc_reject;
 					duk_bool_t accdesc_reject;
@@ -36999,6 +52820,13 @@ duk_bool_t duk_hobject_putprop(duk_hthread *thr, duk_tval *tv_obj, duk_tval *tv_
 		 *  from, an array index fast path is important.
 		 */
 
+#if defined(DUK_USE_FASTINT)
+		if (DUK_TVAL_IS_FASTINT(tv_key)) {
+			arr_idx = duk__tval_fastint_to_arr_idx(tv_key);
+			DUK_DDD(DUK_DDDPRINT("base object buffer, key is a fast-path fastint; arr_idx %ld", (long) arr_idx));
+			pop_count = 0;
+		} else
+#endif
 		if (DUK_TVAL_IS_NUMBER(tv_key)) {
 			arr_idx = duk__tval_number_to_arr_idx(tv_key);
 			DUK_DDD(DUK_DDDPRINT("base object buffer, key is a fast-path number; arr_idx %ld", (long) arr_idx));
@@ -37016,10 +52844,24 @@ duk_bool_t duk_hobject_putprop(duk_hthread *thr, duk_tval *tv_obj, duk_tval *tv_
 		    arr_idx < DUK_HBUFFER_GET_SIZE(h)) {
 			duk_uint8_t *data;
 			DUK_DDD(DUK_DDDPRINT("writing to buffer data at index %ld", (long) arr_idx));
-			data = (duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(h);
-			duk_push_tval(ctx, tv_val);
-			data[arr_idx] = (duk_uint8_t) duk_to_number(ctx, -1);
-			pop_count++;
+			data = (duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h);
+
+			/* XXX: duk_to_int() ensures we'll get 8 lowest bits as
+			 * as input is within duk_int_t range (capped outside it).
+			 */
+#if defined(DUK_USE_FASTINT)
+			/* Buffer writes are often integers. */
+			if (DUK_TVAL_IS_FASTINT(tv_val)) {
+				data[arr_idx] = (duk_uint8_t) DUK_TVAL_GET_FASTINT_U32(tv_val);
+			}
+			else
+#endif
+			{
+				duk_push_tval(ctx, tv_val);
+				data[arr_idx] = (duk_uint8_t) duk_to_uint32(ctx, -1);
+				pop_count++;
+			}
+
 			duk_pop_n(ctx, pop_count);
 			DUK_DDD(DUK_DDDPRINT("result: success (buffer data write)"));
 			return 1;
@@ -37036,7 +52878,10 @@ duk_bool_t duk_hobject_putprop(duk_hthread *thr, duk_tval *tv_obj, duk_tval *tv_
 			                     (duk_tval *) duk_get_tval(ctx, -1), (long) arr_idx));
 		}
 
-		if (key == DUK_HTHREAD_STRING_LENGTH(thr)) {
+		if (key == DUK_HTHREAD_STRING_LENGTH(thr) ||
+		    key == DUK_HTHREAD_STRING_BYTE_LENGTH(thr) ||
+		    key == DUK_HTHREAD_STRING_BYTE_OFFSET(thr) ||
+		    key == DUK_HTHREAD_STRING_BYTES_PER_ELEMENT(thr)) {
 			goto fail_not_writable;
 		}
 
@@ -37051,6 +52896,26 @@ duk_bool_t duk_hobject_putprop(duk_hthread *thr, duk_tval *tv_obj, duk_tval *tv_
 		break;
 	}
 
+	case DUK_TAG_LIGHTFUNC: {
+		/* All lightfunc own properties are non-writable and the lightfunc
+		 * is considered non-extensible.  However, the write may be captured
+		 * by an inherited setter which means we can't stop the lookup here.
+		 */
+
+		arr_idx = duk__push_tval_to_hstring_arr_idx(ctx, tv_key, &key);
+
+		if (duk__key_is_lightfunc_ownprop(thr, key)) {
+			goto fail_not_writable;
+		}
+
+		DUK_DDD(DUK_DDDPRINT("base object is a lightfunc, start lookup from function prototype"));
+		curr = thr->builtins[DUK_BIDX_FUNCTION_PROTOTYPE];
+		goto lookup;  /* avoid double coercion */
+	}
+
+#if defined(DUK_USE_FASTINT)
+	case DUK_TAG_FASTINT:
+#endif
 	default: {
 		/* number */
 		DUK_DDD(DUK_DDDPRINT("base object is a number, start lookup from number prototype"));
@@ -37077,8 +52942,7 @@ duk_bool_t duk_hobject_putprop(duk_hthread *thr, duk_tval *tv_obj, duk_tval *tv_
 	DUK_ASSERT(curr != NULL);
 	sanity = DUK_HOBJECT_PROTOTYPE_CHAIN_SANITY;
 	do {
-		/* 0 = don't push current value */
-		if (!duk__get_own_property_desc_raw(thr, curr, key, arr_idx, &desc, 0)) {
+		if (!duk__get_own_property_desc_raw(thr, curr, key, arr_idx, &desc, 0 /*flags*/)) {  /* don't push value */
 			goto next_in_chain;
 		}
 
@@ -37095,7 +52959,7 @@ duk_bool_t duk_hobject_putprop(duk_hthread *thr, duk_tval *tv_obj, duk_tval *tv_
 
 			DUK_DD(DUK_DDPRINT("put to an own or inherited accessor, calling setter"));
 
-			setter = DUK_HOBJECT_E_GET_VALUE_SETTER(curr, desc.e_idx);
+			setter = DUK_HOBJECT_E_GET_VALUE_SETTER(thr->heap, curr, desc.e_idx);
 			if (!setter) {
 				goto fail_no_setter;
 			}
@@ -37106,7 +52970,7 @@ duk_bool_t duk_hobject_putprop(duk_hthread *thr, duk_tval *tv_obj, duk_tval *tv_
 			duk_dup(ctx, -4);
 			duk_call_method(ctx, 2);     /* [key setter this val key] -> [key retval] */
 #else
-			duk_call_method(ctx, 1);     /* [key setter this val] -> [key retval] */
+			duk_call_method(ctx, 1);     /* [key setter this val] -> [key retval] */
 #endif
 			duk_pop(ctx);                /* ignore retval -> [key] */
 			goto success_no_arguments_exotic;
@@ -37149,20 +53013,41 @@ duk_bool_t duk_hobject_putprop(duk_hthread *thr, duk_tval *tv_obj, duk_tval *tv_
 			}
 			if (desc.flags & DUK_PROPDESC_FLAG_VIRTUAL) {
 				DUK_DD(DUK_DDPRINT("found existing own (non-inherited) virtual property, property is writable"));
-				if (DUK_HOBJECT_HAS_EXOTIC_BUFFEROBJ(curr)) {
-					duk_hbuffer *h;
+				if (DUK_HOBJECT_IS_BUFFEROBJECT(curr)) {
+					duk_hbufferobject *h_bufobj;
+					duk_uint_t byte_off;
+					duk_small_uint_t elem_size;
+
+					h_bufobj = (duk_hbufferobject *) curr;
+					DUK_ASSERT_HBUFFEROBJECT_VALID(h_bufobj);
 
 					DUK_DD(DUK_DDPRINT("writable virtual property is in buffer object"));
-					h = duk_hobject_get_internal_value_buffer(thr->heap, curr);
-					DUK_ASSERT(h != NULL);
 
-					if (arr_idx != DUK__NO_ARRAY_INDEX &&
-					    arr_idx < DUK_HBUFFER_GET_SIZE(h)) {
+					/* Careful with wrapping: arr_idx upshift may easily wrap, whereas
+					 * length downshift won't.
+					 */
+					if (arr_idx < (h_bufobj->length >> h_bufobj->shift)) {
 						duk_uint8_t *data;
 						DUK_DDD(DUK_DDDPRINT("writing to buffer data at index %ld", (long) arr_idx));
-						data = (duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(h);
+
+						DUK_ASSERT(arr_idx != DUK__NO_ARRAY_INDEX);  /* index/length check guarantees */
+						byte_off = arr_idx << h_bufobj->shift;       /* no wrap assuming h_bufobj->length is valid */
+						elem_size = 1 << h_bufobj->shift;
+
+						/* Coerce to number before validating pointers etc so that the
+						 * number coercions in duk_hbufferobject_validated_write() are
+						 * guaranteed to be side effect free and not invalidate the
+						 * pointer checks we do here.
+						 */
 						duk_push_tval(ctx, tv_val);
-						data[arr_idx] = (duk_uint8_t) duk_to_number(ctx, -1);
+						duk_to_number(ctx, -1);
+
+						if (h_bufobj->buf != NULL && DUK_HBUFFEROBJECT_VALID_BYTEOFFSET_EXCL(h_bufobj, byte_off + elem_size)) {
+							data = (duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h_bufobj->buf) + h_bufobj->offset + byte_off;
+							duk_hbufferobject_validated_write(ctx, h_bufobj, data, elem_size);
+						} else {
+							DUK_D(DUK_DPRINT("bufferobject access out of underlying buffer, ignoring (write skipped)"));
+						}
 						duk_pop(ctx);
 						goto success_no_arguments_exotic;
 					}
@@ -37176,10 +53061,13 @@ duk_bool_t duk_hobject_putprop(duk_hthread *thr, duk_tval *tv_obj, duk_tval *tv_
 		DUK_UNREACHABLE();
 
 	 next_in_chain:
+		/* XXX: option to pretend property doesn't exist if sanity limit is
+		 * hit might be useful.
+		 */
 		if (sanity-- == 0) {
 			DUK_ERROR(thr, DUK_ERR_INTERNAL_ERROR, DUK_STR_PROTOTYPE_CHAIN_LIMIT);
 		}
-		curr = curr->prototype;
+		curr = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, curr);
 	} while (curr);
 
 	/*
@@ -37234,7 +53122,7 @@ duk_bool_t duk_hobject_putprop(duk_hthread *thr, duk_tval *tv_obj, duk_tval *tv_
 
 		DUK_DDD(DUK_DDDPRINT("writing existing 'length' property to array exotic, invoke complex helper"));
 
-		/* FIXME: the helper currently assumes stack top contains new
+		/* XXX: the helper currently assumes stack top contains new
 		 * 'length' value and the whole calling convention is not very
 		 * compatible with what we need.
 		 */
@@ -37251,14 +53139,9 @@ duk_bool_t duk_hobject_putprop(duk_hthread *thr, duk_tval *tv_obj, duk_tval *tv_
 	}
 
 	if (desc.e_idx >= 0) {
-		duk_tval tv_tmp;
-
-		tv = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(orig, desc.e_idx);
+		tv = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, orig, desc.e_idx);
 		DUK_DDD(DUK_DDDPRINT("previous entry value: %!iT", (duk_tval *) tv));
-		DUK_TVAL_SET_TVAL(&tv_tmp, tv);
-		DUK_TVAL_SET_TVAL(tv, tv_val);
-		DUK_TVAL_INCREF(thr, tv);
-		DUK_TVAL_DECREF(thr, &tv_tmp);  /* note: may trigger gc and props compaction, must be last */
+		DUK_TVAL_SET_TVAL_UPDREF(thr, tv, tv_val);  /* side effects */
 		/* don't touch property attributes or hash part */
 		DUK_DD(DUK_DDPRINT("put to an existing entry at index %ld -> new value %!iT",
 		                   (long) desc.e_idx, (duk_tval *) tv));
@@ -37267,15 +53150,11 @@ duk_bool_t duk_hobject_putprop(duk_hthread *thr, duk_tval *tv_obj, duk_tval *tv_
 		 * above is pointless for them.  The check could be avoided with some
 		 * refactoring but is probably not worth it.
 		 */
-		duk_tval tv_tmp;
 
 		DUK_ASSERT(desc.a_idx >= 0);
-		tv = DUK_HOBJECT_A_GET_VALUE_PTR(orig, desc.a_idx);
+		tv = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, orig, desc.a_idx);
 		DUK_DDD(DUK_DDDPRINT("previous array value: %!iT", (duk_tval *) tv));
-		DUK_TVAL_SET_TVAL(&tv_tmp, tv);
-		DUK_TVAL_SET_TVAL(tv, tv_val);
-		DUK_TVAL_INCREF(thr, tv);
-		DUK_TVAL_DECREF(thr, &tv_tmp);  /* note: may trigger gc and props compaction, must be last */
+		DUK_TVAL_SET_TVAL_UPDREF(thr, tv, tv_val);  /* side effects */
 		DUK_DD(DUK_DDPRINT("put to an existing array entry at index %ld -> new value %!iT",
 		                   (long) desc.a_idx, (duk_tval *) tv));
 	}
@@ -37355,7 +53234,7 @@ duk_bool_t duk_hobject_putprop(duk_hthread *thr, duk_tval *tv_obj, duk_tval *tv_
 
 	if (arr_idx != DUK__NO_ARRAY_INDEX &&
 	    DUK_HOBJECT_HAS_ARRAY_PART(orig)) {
-		if (arr_idx < orig->a_size) {
+		if (arr_idx < DUK_HOBJECT_GET_ASIZE(orig)) {
 			goto no_array_growth;
 		}
 
@@ -37379,15 +53258,15 @@ duk_bool_t duk_hobject_putprop(duk_hthread *thr, duk_tval *tv_obj, duk_tval *tv_
 
 		DUK_DDD(DUK_DDDPRINT("write to new array requires array resize, decide whether to do a "
 		                     "fast resize without abandon check (arr_idx=%ld, old_size=%ld)",
-		                     (long) arr_idx, (long) orig->a_size));
+		                     (long) arr_idx, (long) DUK_HOBJECT_GET_ASIZE(orig)));
 
-		if (duk__abandon_array_slow_check_required(arr_idx, orig->a_size)) {
+		if (duk__abandon_array_slow_check_required(arr_idx, DUK_HOBJECT_GET_ASIZE(orig))) {
 			duk_uint32_t old_used;
 			duk_uint32_t old_size;
 
 			DUK_DDD(DUK_DDDPRINT("=> fast check is NOT OK, do slow check for array abandon"));
 
-			duk__compute_a_stats(orig, &old_used, &old_size);
+			duk__compute_a_stats(thr, orig, &old_used, &old_size);
 
 			DUK_DDD(DUK_DDDPRINT("abandon check, array stats: old_used=%ld, old_size=%ld, arr_idx=%ld",
 			                     (long) old_used, (long) old_size, (long) arr_idx));
@@ -37428,11 +53307,11 @@ duk_bool_t duk_hobject_putprop(duk_hthread *thr, duk_tval *tv_obj, duk_tval *tv_
 		 */
 
 		DUK_ASSERT(DUK_HOBJECT_HAS_ARRAY_PART(orig));
-		DUK_ASSERT(arr_idx < orig->a_size);
+		DUK_ASSERT(arr_idx < DUK_HOBJECT_GET_ASIZE(orig));
 
-		tv = DUK_HOBJECT_A_GET_VALUE_PTR(orig, arr_idx);
+		tv = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, orig, arr_idx);
 		/* prev value must be unused, no decref */
-		DUK_ASSERT(DUK_TVAL_IS_UNDEFINED_UNUSED(tv));
+		DUK_ASSERT(DUK_TVAL_IS_UNUSED(tv));
 		DUK_TVAL_SET_TVAL(tv, tv_val);
 		DUK_TVAL_INCREF(thr, tv);
 		DUK_DD(DUK_DDPRINT("put to new array entry: %ld -> %!T",
@@ -37458,11 +53337,11 @@ duk_bool_t duk_hobject_putprop(duk_hthread *thr, duk_tval *tv_obj, duk_tval *tv_
 	e_idx = duk__alloc_entry_checked(thr, orig, key);
 	DUK_ASSERT(e_idx >= 0);
 
-	tv = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(orig, e_idx);
+	tv = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, orig, e_idx);
 	/* prev value can be garbage, no decref */
 	DUK_TVAL_SET_TVAL(tv, tv_val);
 	DUK_TVAL_INCREF(thr, tv);
-	DUK_HOBJECT_E_SET_FLAGS(orig, e_idx, DUK_PROPDESC_FLAGS_WEC);
+	DUK_HOBJECT_E_SET_FLAGS(thr->heap, orig, e_idx, DUK_PROPDESC_FLAGS_WEC);
 	goto entry_updated;
 
  entry_updated:
@@ -37470,7 +53349,7 @@ duk_bool_t duk_hobject_putprop(duk_hthread *thr, duk_tval *tv_obj, duk_tval *tv_
 	/*
 	 *  Possible pending array length update, which must only be done
 	 *  if the actual entry write succeeded.
-	 */	
+	 */
 
 	if (new_array_length > 0) {
 		/*
@@ -37484,14 +53363,19 @@ duk_bool_t duk_hobject_putprop(duk_hthread *thr, duk_tval *tv_obj, duk_tval *tv_
 		DUK_DDD(DUK_DDDPRINT("write successful, pending array length update to: %ld",
 		                     (long) new_array_length));
 
-		rc = duk__get_own_property_desc_raw(thr, orig, DUK_HTHREAD_STRING_LENGTH(thr), DUK__NO_ARRAY_INDEX, &desc, 0);
+		rc = duk__get_own_property_desc_raw(thr, orig, DUK_HTHREAD_STRING_LENGTH(thr), DUK__NO_ARRAY_INDEX, &desc, 0 /*flags*/);  /* don't push value */
 		DUK_UNREF(rc);
 		DUK_ASSERT(rc != 0);
 		DUK_ASSERT(desc.e_idx >= 0);
 
-		tv = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(orig, desc.e_idx);
+		tv = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, orig, desc.e_idx);
 		DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));
-		DUK_TVAL_SET_NUMBER(tv, (duk_double_t) new_array_length);  /* no need for decref/incref because value is a number */
+		/* no need for decref/incref because value is a number */
+#if defined(DUK_USE_FASTINT)
+		DUK_TVAL_SET_FASTINT_U32(tv, new_array_length);
+#else
+		DUK_TVAL_SET_NUMBER(tv, (duk_double_t) new_array_length);
+#endif
 	}
 
 	/*
@@ -37528,7 +53412,7 @@ duk_bool_t duk_hobject_putprop(duk_hthread *thr, duk_tval *tv_obj, duk_tval *tv_
 
 		/* Note: we can reuse 'desc' here */
 
-		/* FIXME: top of stack must contain value, which helper doesn't touch,
+		/* XXX: top of stack must contain value, which helper doesn't touch,
 		 * rework to use tv_val directly?
 		 */
 
@@ -37555,7 +53439,12 @@ duk_bool_t duk_hobject_putprop(duk_hthread *thr, duk_tval *tv_obj, duk_tval *tv_
  fail_base_primitive:
 	DUK_DDD(DUK_DDDPRINT("result: error, base primitive"));
 	if (throw_flag) {
+#if defined(DUK_USE_PARANOID_ERRORS)
 		DUK_ERROR(thr, DUK_ERR_TYPE_ERROR, DUK_STR_INVALID_BASE);
+#else
+		DUK_ERROR(thr, DUK_ERR_TYPE_ERROR, "cannot write property %s of %s",
+		          duk_push_string_tval_readable(ctx, tv_key), duk_push_string_tval_readable(ctx, tv_obj));
+#endif
 	}
 	duk_pop(ctx);  /* remove key */
 	return 0;
@@ -37567,7 +53456,7 @@ duk_bool_t duk_hobject_putprop(duk_hthread *thr, duk_tval *tv_obj, duk_tval *tv_
 	}
 	duk_pop(ctx);  /* remove key */
 	return 0;
-	
+
  fail_not_writable:
 	DUK_DDD(DUK_DDDPRINT("result: error, not writable"));
 	if (throw_flag) {
@@ -37605,14 +53494,18 @@ duk_bool_t duk_hobject_putprop(duk_hthread *thr, duk_tval *tv_obj, duk_tval *tv_
  *  Ecmascript compliant [[Delete]](P, Throw).
  */
 
-duk_bool_t duk_hobject_delprop_raw(duk_hthread *thr, duk_hobject *obj, duk_hstring *key, duk_bool_t throw_flag) {
+DUK_INTERNAL duk_bool_t duk_hobject_delprop_raw(duk_hthread *thr, duk_hobject *obj, duk_hstring *key, duk_small_uint_t flags) {
 	duk_propdesc desc;
 	duk_tval *tv;
-	duk_tval tv_tmp;
 	duk_uint32_t arr_idx;
+	duk_bool_t throw_flag;
+	duk_bool_t force_flag;
 
-	DUK_DDD(DUK_DDDPRINT("delprop_raw: thr=%p, obj=%p, key=%p, throw=%ld (obj -> %!O, key -> %!O)",
-	                     (void *) thr, (void *) obj, (void *) key, (long) throw_flag,
+	throw_flag = (flags & DUK_DELPROP_FLAG_THROW);
+	force_flag = (flags & DUK_DELPROP_FLAG_FORCE);
+
+	DUK_DDD(DUK_DDDPRINT("delprop_raw: thr=%p, obj=%p, key=%p, throw=%ld, force=%ld (obj -> %!O, key -> %!O)",
+	                     (void *) thr, (void *) obj, (void *) key, (long) throw_flag, (long) force_flag,
 	                     (duk_heaphdr *) obj, (duk_heaphdr *) key));
 
 	DUK_ASSERT(thr != NULL);
@@ -37625,79 +53518,83 @@ duk_bool_t duk_hobject_delprop_raw(duk_hthread *thr, duk_hobject *obj, duk_hstri
 	arr_idx = DUK_HSTRING_GET_ARRIDX_FAST(key);
 
 	/* 0 = don't push current value */
-	if (!duk__get_own_property_desc_raw(thr, obj, key, arr_idx, &desc, 0)) {
+	if (!duk__get_own_property_desc_raw(thr, obj, key, arr_idx, &desc, 0 /*flags*/)) {  /* don't push value */
 		DUK_DDD(DUK_DDDPRINT("property not found, succeed always"));
 		goto success;
 	}
 
-	if ((desc.flags & DUK_PROPDESC_FLAG_CONFIGURABLE) == 0) {
+	if ((desc.flags & DUK_PROPDESC_FLAG_CONFIGURABLE) == 0 && !force_flag) {
 		goto fail_not_configurable;
 	}
-
-	/* currently there are no deletable virtual properties */
-	DUK_ASSERT(desc.a_idx >= 0 || desc.e_idx >= 0);
+	if (desc.a_idx < 0 && desc.e_idx < 0) {
+		/* Currently there are no deletable virtual properties, but
+		 * with force_flag we might attempt to delete one.
+		 */
+		goto fail_virtual;
+	}
 
 	if (desc.a_idx >= 0) {
 		DUK_ASSERT(desc.e_idx < 0);
 
-		tv = DUK_HOBJECT_A_GET_VALUE_PTR(obj, desc.a_idx);
-		DUK_TVAL_SET_TVAL(&tv_tmp, tv);
-		DUK_TVAL_SET_UNDEFINED_UNUSED(tv);
-		DUK_TVAL_DECREF(thr, &tv_tmp);
+		tv = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, obj, desc.a_idx);
+		DUK_TVAL_SET_UNUSED_UPDREF(thr, tv);  /* side effects */
 		goto success;
 	} else {
 		DUK_ASSERT(desc.a_idx < 0);
 
 		/* remove hash entry (no decref) */
+#if defined(DUK_USE_HOBJECT_HASH_PART)
 		if (desc.h_idx >= 0) {
-			duk_uint32_t *h_base = DUK_HOBJECT_H_GET_BASE(obj);
+			duk_uint32_t *h_base = DUK_HOBJECT_H_GET_BASE(thr->heap, obj);
 
 			DUK_DDD(DUK_DDDPRINT("removing hash entry at h_idx %ld", (long) desc.h_idx));
-			DUK_ASSERT(obj->h_size > 0);
-			DUK_ASSERT((duk_uint32_t) desc.h_idx < obj->h_size);
+			DUK_ASSERT(DUK_HOBJECT_GET_HSIZE(obj) > 0);
+			DUK_ASSERT((duk_uint32_t) desc.h_idx < DUK_HOBJECT_GET_HSIZE(obj));
 			h_base[desc.h_idx] = DUK__HASH_DELETED;
 		} else {
-			DUK_ASSERT(obj->h_size == 0);
+			DUK_ASSERT(DUK_HOBJECT_GET_HSIZE(obj) == 0);
 		}
+#else
+		DUK_ASSERT(DUK_HOBJECT_GET_HSIZE(obj) == 0);
+#endif
 
 		/* remove value */
 		DUK_DDD(DUK_DDDPRINT("before removing value, e_idx %ld, key %p, key at slot %p",
-		                     (long) desc.e_idx, (void *) key, (void *) DUK_HOBJECT_E_GET_KEY(obj, desc.e_idx)));
+		                     (long) desc.e_idx, (void *) key, (void *) DUK_HOBJECT_E_GET_KEY(thr->heap, obj, desc.e_idx)));
 		DUK_DDD(DUK_DDDPRINT("removing value at e_idx %ld", (long) desc.e_idx));
-		if (DUK_HOBJECT_E_SLOT_IS_ACCESSOR(obj, desc.e_idx)) {
+		if (DUK_HOBJECT_E_SLOT_IS_ACCESSOR(thr->heap, obj, desc.e_idx)) {
 			duk_hobject *tmp;
 
-			tmp = DUK_HOBJECT_E_GET_VALUE_GETTER(obj, desc.e_idx);
-			DUK_HOBJECT_E_SET_VALUE_GETTER(obj, desc.e_idx, NULL);
+			tmp = DUK_HOBJECT_E_GET_VALUE_GETTER(thr->heap, obj, desc.e_idx);
+			DUK_HOBJECT_E_SET_VALUE_GETTER(thr->heap, obj, desc.e_idx, NULL);
 			DUK_UNREF(tmp);
-			DUK_HOBJECT_DECREF(thr, tmp);
+			DUK_HOBJECT_DECREF_ALLOWNULL(thr, tmp);  /* side effects */
 
-			tmp = DUK_HOBJECT_E_GET_VALUE_SETTER(obj, desc.e_idx);
-			DUK_HOBJECT_E_SET_VALUE_SETTER(obj, desc.e_idx, NULL);
+			tmp = DUK_HOBJECT_E_GET_VALUE_SETTER(thr->heap, obj, desc.e_idx);
+			DUK_HOBJECT_E_SET_VALUE_SETTER(thr->heap, obj, desc.e_idx, NULL);
 			DUK_UNREF(tmp);
-			DUK_HOBJECT_DECREF(thr, tmp);
+			DUK_HOBJECT_DECREF_ALLOWNULL(thr, tmp);  /* side effects */
 		} else {
-			tv = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(obj, desc.e_idx);
-			DUK_TVAL_SET_TVAL(&tv_tmp, tv);
-			DUK_TVAL_SET_UNDEFINED_UNUSED(tv);
-			DUK_TVAL_DECREF(thr, &tv_tmp);
+			tv = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, obj, desc.e_idx);
+			DUK_TVAL_SET_UNDEFINED_UPDREF(thr, tv);  /* side effects */
 		}
-		/* this is not strictly necessary because if key == NULL, value MUST be ignored */
-		DUK_HOBJECT_E_SET_FLAGS(obj, desc.e_idx, 0);
-		DUK_TVAL_SET_UNDEFINED_UNUSED(DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(obj, desc.e_idx));
+#if 0
+		/* Not strictly necessary because if key == NULL, flag MUST be ignored. */
+		DUK_HOBJECT_E_SET_FLAGS(thr->heap, obj, desc.e_idx, 0);
+#endif
 
 		/* remove key */
 		DUK_DDD(DUK_DDDPRINT("before removing key, e_idx %ld, key %p, key at slot %p",
-		                     (long) desc.e_idx, (void *) key, (void *) DUK_HOBJECT_E_GET_KEY(obj, desc.e_idx)));
+		                     (long) desc.e_idx, (void *) key, (void *) DUK_HOBJECT_E_GET_KEY(thr->heap, obj, desc.e_idx)));
 		DUK_DDD(DUK_DDDPRINT("removing key at e_idx %ld", (long) desc.e_idx));
-		DUK_ASSERT(key == DUK_HOBJECT_E_GET_KEY(obj, desc.e_idx));
-		DUK_HOBJECT_E_SET_KEY(obj, desc.e_idx, NULL);
-		DUK_HSTRING_DECREF(thr, key);
+		DUK_ASSERT(key == DUK_HOBJECT_E_GET_KEY(thr->heap, obj, desc.e_idx));
+		DUK_HOBJECT_E_SET_KEY(thr->heap, obj, desc.e_idx, NULL);
+		DUK_HSTRING_DECREF(thr, key);  /* side effects */
 		goto success;
 	}
 
 	DUK_UNREACHABLE();
-	
+
  success:
 	/*
 	 *  Argument exotic [[Delete]] behavior (E5 Section 10.6) is
@@ -37725,6 +53622,14 @@ duk_bool_t duk_hobject_delprop_raw(duk_hthread *thr, duk_hobject *obj, duk_hstri
 	DUK_DDD(DUK_DDDPRINT("delete successful"));
 	return 1;
 
+ fail_virtual:
+	DUK_DDD(DUK_DDDPRINT("delete failed: property found, force flag, but virtual"));
+
+	if (throw_flag) {
+		DUK_ERROR(thr, DUK_ERR_TYPE_ERROR, DUK_STR_PROPERTY_IS_VIRTUAL);
+	}
+	return 0;
+
  fail_not_configurable:
 	DUK_DDD(DUK_DDDPRINT("delete failed: property found, not configurable"));
 
@@ -37738,7 +53643,7 @@ duk_bool_t duk_hobject_delprop_raw(duk_hthread *thr, duk_hobject *obj, duk_hstri
  *  DELPROP: Ecmascript property deletion.
  */
 
-duk_bool_t duk_hobject_delprop(duk_hthread *thr, duk_tval *tv_obj, duk_tval *tv_key, duk_bool_t throw_flag) {
+DUK_INTERNAL duk_bool_t duk_hobject_delprop(duk_hthread *thr, duk_tval *tv_obj, duk_tval *tv_key, duk_bool_t throw_flag) {
 	duk_context *ctx = (duk_context *) thr;
 	duk_hstring *key = NULL;
 #if defined(DUK_USE_ES6_PROXY)
@@ -37804,7 +53709,7 @@ duk_bool_t duk_hobject_delprop(duk_hthread *thr, duk_tval *tv_obj, duk_tval *tv_
 				arr_idx = duk__push_tval_to_hstring_arr_idx(ctx, tv_key, &key);
 				DUK_ASSERT(key != NULL);
 
-				if (duk__get_own_property_desc_raw(thr, h_target, key, arr_idx, &desc, 0 /*push_value*/)) {
+				if (duk__get_own_property_desc_raw(thr, h_target, key, arr_idx, &desc, 0 /*flags*/)) {  /* don't push value */
 					int desc_reject;
 
 					DUK_DDD(DUK_DDDPRINT("proxy 'deleteProperty': target has matching property %!O, check for "
@@ -37831,9 +53736,12 @@ duk_bool_t duk_hobject_delprop(duk_hthread *thr, duk_tval *tv_obj, duk_tval *tv_
 		key = duk_get_hstring(ctx, -1);
 		DUK_ASSERT(key != NULL);
 
-		rc = duk_hobject_delprop_raw(thr, obj, key, throw_flag);
+		rc = duk_hobject_delprop_raw(thr, obj, key, throw_flag ? DUK_DELPROP_FLAG_THROW : 0);
 		goto done_rc;
 	} else if (DUK_TVAL_IS_STRING(tv_obj)) {
+		/* XXX: unnecessary string coercion for array indices,
+		 * intentional to keep small.
+		 */
 		duk_hstring *h = DUK_TVAL_GET_STRING(tv_obj);
 		DUK_ASSERT(h != NULL);
 
@@ -37851,8 +53759,41 @@ duk_bool_t duk_hobject_delprop(duk_hthread *thr, duk_tval *tv_obj, duk_tval *tv_
 		    arr_idx < DUK_HSTRING_GET_CHARLEN(h)) {
 			goto fail_not_configurable;
 		}
+	} else if (DUK_TVAL_IS_BUFFER(tv_obj)) {
+		/* XXX: unnecessary string coercion for array indices,
+		 * intentional to keep small; some overlap with string
+		 * handling.
+		 */
+		duk_hbuffer *h = DUK_TVAL_GET_BUFFER(tv_obj);
+		DUK_ASSERT(h != NULL);
+
+		duk_to_string(ctx, -1);
+		key = duk_get_hstring(ctx, -1);
+		DUK_ASSERT(key != NULL);
+
+		if (key == DUK_HTHREAD_STRING_LENGTH(thr)) {
+			goto fail_not_configurable;
+		}
+
+		arr_idx = DUK_HSTRING_GET_ARRIDX_FAST(key);
+
+		if (arr_idx != DUK__NO_ARRAY_INDEX &&
+		    arr_idx < DUK_HBUFFER_GET_SIZE(h)) {
+			goto fail_not_configurable;
+		}
+	} else if (DUK_TVAL_IS_LIGHTFUNC(tv_obj)) {
+		/* Lightfunc virtual properties are non-configurable, so
+		 * reject if match any of them.
+		 */
+
+		duk_to_string(ctx, -1);
+		key = duk_get_hstring(ctx, -1);
+		DUK_ASSERT(key != NULL);
+
+		if (duk__key_is_lightfunc_ownprop(thr, key)) {
+			goto fail_not_configurable;
+		}
 	}
-	/* FIXME: buffer virtual properties? */
 
 	/* non-object base, no offending virtual property */
 	rc = 1;
@@ -37865,7 +53806,12 @@ duk_bool_t duk_hobject_delprop(duk_hthread *thr, duk_tval *tv_obj, duk_tval *tv_
  fail_invalid_base_uncond:
 	/* Note: unconditional throw */
 	DUK_ASSERT(duk_get_top(ctx) == entry_top);
+#if defined(DUK_USE_PARANOID_ERRORS)
 	DUK_ERROR(thr, DUK_ERR_TYPE_ERROR, DUK_STR_INVALID_BASE);
+#else
+	DUK_ERROR(thr, DUK_ERR_TYPE_ERROR, "cannot delete property %s of %s",
+	          duk_push_string_tval_readable(ctx, tv_key), duk_push_string_tval_readable(ctx, tv_obj));
+#endif
 	return 0;
 
  fail_proxy_rejected:
@@ -37902,12 +53848,11 @@ duk_bool_t duk_hobject_delprop(duk_hthread *thr, duk_tval *tv_obj, duk_tval *tv_
  *  operations.
  */
 
-void duk_hobject_define_property_internal(duk_hthread *thr, duk_hobject *obj, duk_hstring *key, duk_small_uint_t flags) {
+DUK_INTERNAL void duk_hobject_define_property_internal(duk_hthread *thr, duk_hobject *obj, duk_hstring *key, duk_small_uint_t flags) {
 	duk_context *ctx = (duk_context *) thr;
 	duk_propdesc desc;
 	duk_uint32_t arr_idx;
 	duk_int_t e_idx;
-	duk_tval tv_tmp;
 	duk_tval *tv1 = NULL;
 	duk_tval *tv2 = NULL;
 	duk_small_uint_t propflags = flags & DUK_PROPDESC_FLAGS_MASK;  /* mask out flags not actually stored */
@@ -37926,20 +53871,20 @@ void duk_hobject_define_property_internal(duk_hthread *thr, duk_hobject *obj, du
 
 	arr_idx = DUK_HSTRING_GET_ARRIDX_SLOW(key);
 
-	if (duk__get_own_property_desc_raw(thr, obj, key, arr_idx, &desc, 0)) {  /* push_value = 0 */
+	if (duk__get_own_property_desc_raw(thr, obj, key, arr_idx, &desc, 0 /*flags*/)) {  /* don't push value */
 		if (desc.e_idx >= 0) {
 			if (flags & DUK_PROPDESC_FLAG_NO_OVERWRITE) {
 				DUK_DDD(DUK_DDDPRINT("property already exists in the entry part -> skip as requested"));
 				goto pop_exit;
 			}
 			DUK_DDD(DUK_DDDPRINT("property already exists in the entry part -> update value and attributes"));
-			if (DUK_UNLIKELY(DUK_HOBJECT_E_SLOT_IS_ACCESSOR(obj, desc.e_idx))) {
+			if (DUK_UNLIKELY(DUK_HOBJECT_E_SLOT_IS_ACCESSOR(thr->heap, obj, desc.e_idx))) {
 				DUK_D(DUK_DPRINT("existing property is an accessor, not supported"));
 				goto error_internal;
 			}
 
-			DUK_HOBJECT_E_SET_FLAGS(obj, desc.e_idx, propflags);
-			tv1 = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(obj, desc.e_idx);
+			DUK_HOBJECT_E_SET_FLAGS(thr->heap, obj, desc.e_idx, propflags);
+			tv1 = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, obj, desc.e_idx);
 		} else if (desc.a_idx >= 0) {
 			if (flags & DUK_PROPDESC_FLAG_NO_OVERWRITE) {
 				DUK_DDD(DUK_DDDPRINT("property already exists in the array part -> skip as requested"));
@@ -37952,7 +53897,7 @@ void duk_hobject_define_property_internal(duk_hthread *thr, duk_hobject *obj, du
 				goto error_internal;
 			}
 
-			tv1 = DUK_HOBJECT_A_GET_VALUE_PTR(obj, desc.a_idx);
+			tv1 = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, obj, desc.a_idx);
 		} else {
 			if (flags & DUK_PROPDESC_FLAG_NO_OVERWRITE) {
 				DUK_DDD(DUK_DDDPRINT("property already exists but is virtual -> skip as requested"));
@@ -37971,23 +53916,23 @@ void duk_hobject_define_property_internal(duk_hthread *thr, duk_hobject *obj, du
 			DUK_ASSERT(propflags == DUK_PROPDESC_FLAGS_WEC);
 
 			/* always grow the array, no sparse / abandon support here */
-			if (arr_idx >= obj->a_size) {
+			if (arr_idx >= DUK_HOBJECT_GET_ASIZE(obj)) {
 				duk__grow_props_for_array_item(thr, obj, arr_idx);
 			}
 
-			DUK_ASSERT(arr_idx < obj->a_size);
-			tv1 = DUK_HOBJECT_A_GET_VALUE_PTR(obj, arr_idx);
-			goto write_value;			
+			DUK_ASSERT(arr_idx < DUK_HOBJECT_GET_ASIZE(obj));
+			tv1 = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, obj, arr_idx);
+			goto write_value;
 		}
 	}
 
 	DUK_DDD(DUK_DDDPRINT("property does not exist, object belongs in entry part -> allocate new entry and write value and attributes"));
 	e_idx = duk__alloc_entry_checked(thr, obj, key);  /* increases key refcount */
 	DUK_ASSERT(e_idx >= 0);
-	DUK_HOBJECT_E_SET_FLAGS(obj, e_idx, propflags);
-	tv1 = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(obj, e_idx);
+	DUK_HOBJECT_E_SET_FLAGS(thr->heap, obj, e_idx, propflags);
+	tv1 = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, obj, e_idx);
 	/* new entry: previous value is garbage; set to undefined to share write_value */
-	DUK_TVAL_SET_UNDEFINED_ACTUAL(tv1);
+	DUK_TVAL_SET_UNDEFINED(tv1);
 	goto write_value;
 
  write_value:
@@ -37997,10 +53942,7 @@ void duk_hobject_define_property_internal(duk_hthread *thr, duk_hobject *obj, du
 	DUK_DDD(DUK_DDDPRINT("writing/updating value: %!T -> %!T",
 	                     (duk_tval *) tv1, (duk_tval *) tv2));
 
-	DUK_TVAL_SET_TVAL(&tv_tmp, tv1);
-	DUK_TVAL_SET_TVAL(tv1, tv2);
-	DUK_TVAL_INCREF(thr, tv1);
-	DUK_TVAL_DECREF(thr, &tv_tmp);  /* side effects */
+	DUK_TVAL_SET_TVAL_UPDREF(thr, tv1, tv2);  /* side effects */
 	goto pop_exit;
 
  pop_exit:
@@ -38022,11 +53964,10 @@ void duk_hobject_define_property_internal(duk_hthread *thr, duk_hobject *obj, du
  *  must avoid interning.
  */
 
-void duk_hobject_define_property_internal_arridx(duk_hthread *thr, duk_hobject *obj, duk_uarridx_t arr_idx, duk_small_uint_t flags) {
+DUK_INTERNAL void duk_hobject_define_property_internal_arridx(duk_hthread *thr, duk_hobject *obj, duk_uarridx_t arr_idx, duk_small_uint_t flags) {
 	duk_context *ctx = (duk_context *) thr;
 	duk_hstring *key;
 	duk_tval *tv1, *tv2;
-	duk_tval tv_tmp;
 
 	DUK_DDD(DUK_DDDPRINT("define new property (internal) arr_idx fast path: thr=%p, obj=%!O, "
 	                     "arr_idx=%ld, flags=0x%02lx, val=%!T",
@@ -38045,18 +53986,15 @@ void duk_hobject_define_property_internal_arridx(duk_hthread *thr, duk_hobject *
 		DUK_DDD(DUK_DDDPRINT("define property to array part (property may or may not exist yet)"));
 
 		/* always grow the array, no sparse / abandon support here */
-		if (arr_idx >= obj->a_size) {
+		if (arr_idx >= DUK_HOBJECT_GET_ASIZE(obj)) {
 			duk__grow_props_for_array_item(thr, obj, arr_idx);
 		}
 
-		DUK_ASSERT(arr_idx < obj->a_size);
-		tv1 = DUK_HOBJECT_A_GET_VALUE_PTR(obj, arr_idx);
+		DUK_ASSERT(arr_idx < DUK_HOBJECT_GET_ASIZE(obj));
+		tv1 = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, obj, arr_idx);
 		tv2 = duk_require_tval(ctx, -1);
 
-		DUK_TVAL_SET_TVAL(&tv_tmp, tv1);
-		DUK_TVAL_SET_TVAL(tv1, tv2);
-		DUK_TVAL_INCREF(thr, tv1);
-		DUK_TVAL_DECREF(thr, &tv_tmp);  /* side effects */
+		DUK_TVAL_SET_TVAL_UPDREF(thr, tv1, tv2);  /* side effects */
 
 		duk_pop(ctx);  /* [ ...val ] -> [ ... ] */
 		return;
@@ -38082,7 +54020,7 @@ void duk_hobject_define_property_internal_arridx(duk_hthread *thr, duk_hobject *
  *  and then changes the entry to an accessor (this is to save code space).
  */
 
-void duk_hobject_define_accessor_internal(duk_hthread *thr, duk_hobject *obj, duk_hstring *key, duk_hobject *getter, duk_hobject *setter, duk_small_uint_t propflags) {
+DUK_INTERNAL void duk_hobject_define_accessor_internal(duk_hthread *thr, duk_hobject *obj, duk_hstring *key, duk_hobject *getter, duk_hobject *setter, duk_small_uint_t propflags) {
 	duk_context *ctx = (duk_context *) thr;
 	duk_int_t e_idx;
 	duk_int_t h_idx;
@@ -38105,17 +54043,17 @@ void duk_hobject_define_accessor_internal(duk_hthread *thr, duk_hobject *obj, du
 	/* force the property to 'undefined' to create a slot for it */
 	duk_push_undefined(ctx);
 	duk_hobject_define_property_internal(thr, obj, key, propflags);
-	duk_hobject_find_existing_entry(obj, key, &e_idx, &h_idx);
+	duk_hobject_find_existing_entry(thr->heap, obj, key, &e_idx, &h_idx);
 	DUK_DDD(DUK_DDDPRINT("accessor slot: e_idx=%ld, h_idx=%ld", (long) e_idx, (long) h_idx));
 	DUK_ASSERT(e_idx >= 0);
-	DUK_ASSERT((duk_uint32_t) e_idx < obj->e_used);
+	DUK_ASSERT((duk_uint32_t) e_idx < DUK_HOBJECT_GET_ENEXT(obj));
 
 	/* no need to decref, as previous value is 'undefined' */
-	DUK_HOBJECT_E_SLOT_SET_ACCESSOR(obj, e_idx);
-	DUK_HOBJECT_E_SET_VALUE_GETTER(obj, e_idx, getter);
-	DUK_HOBJECT_E_SET_VALUE_SETTER(obj, e_idx, setter);
-	DUK_HOBJECT_INCREF(thr, getter);
-	DUK_HOBJECT_INCREF(thr, setter);
+	DUK_HOBJECT_E_SLOT_SET_ACCESSOR(thr->heap, obj, e_idx);
+	DUK_HOBJECT_E_SET_VALUE_GETTER(thr->heap, obj, e_idx, getter);
+	DUK_HOBJECT_E_SET_VALUE_SETTER(thr->heap, obj, e_idx, setter);
+	DUK_HOBJECT_INCREF_ALLOWNULL(thr, getter);
+	DUK_HOBJECT_INCREF_ALLOWNULL(thr, setter);
 }
 
 /*
@@ -38124,7 +54062,7 @@ void duk_hobject_define_accessor_internal(duk_hthread *thr, duk_hobject *obj, du
 
 /* XXX: awkward helpers */
 
-void duk_hobject_set_length(duk_hthread *thr, duk_hobject *obj, duk_uint32_t length) {
+DUK_INTERNAL void duk_hobject_set_length(duk_hthread *thr, duk_hobject *obj, duk_uint32_t length) {
 	duk_context *ctx = (duk_context *) thr;
 	duk_push_hobject(ctx, obj);
 	duk_push_hstring_stridx(ctx, DUK_STRIDX_LENGTH);
@@ -38133,11 +54071,11 @@ void duk_hobject_set_length(duk_hthread *thr, duk_hobject *obj, duk_uint32_t len
 	duk_pop_n(ctx, 3);
 }
 
-void duk_hobject_set_length_zero(duk_hthread *thr, duk_hobject *obj) {
+DUK_INTERNAL void duk_hobject_set_length_zero(duk_hthread *thr, duk_hobject *obj) {
 	duk_hobject_set_length(thr, obj, 0);
 }
 
-duk_uint32_t duk_hobject_get_length(duk_hthread *thr, duk_hobject *obj) {
+DUK_INTERNAL duk_uint32_t duk_hobject_get_length(duk_hthread *thr, duk_hobject *obj) {
 	duk_context *ctx = (duk_context *) thr;
 	duk_double_t val;
 	duk_push_hobject(ctx, obj);
@@ -38157,7 +54095,7 @@ duk_uint32_t duk_hobject_get_length(duk_hthread *thr, duk_hobject *obj) {
  *  This is an actual function call.
  */
 
-duk_ret_t duk_hobject_object_get_own_property_descriptor(duk_context *ctx) {
+DUK_INTERNAL duk_ret_t duk_hobject_object_get_own_property_descriptor(duk_context *ctx) {
 	duk_hthread *thr = (duk_hthread *) ctx;
 	duk_hobject *obj;
 	duk_hstring *key;
@@ -38168,7 +54106,7 @@ duk_ret_t duk_hobject_object_get_own_property_descriptor(duk_context *ctx) {
 	DUK_ASSERT(thr != NULL);
 	DUK_ASSERT(thr->heap != NULL);
 
-	obj = duk_require_hobject(ctx, 0);
+	obj = duk_require_hobject_or_lfunc_coerce(ctx, 0);
 	(void) duk_to_string(ctx, 1);
 	key = duk_require_hstring(ctx, 1);
 
@@ -38177,7 +54115,7 @@ duk_ret_t duk_hobject_object_get_own_property_descriptor(duk_context *ctx) {
 
 	DUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);
 
-	rc = duk__get_own_property_desc(thr, obj, key, &pd, 1);  /* push_value = 1 */
+	rc = duk__get_own_property_desc(thr, obj, key, &pd, DUK__DESC_FLAG_PUSH_VALUE);
 	if (!rc) {
 		duk_push_undefined(ctx);
 
@@ -38223,95 +54161,149 @@ duk_ret_t duk_hobject_object_get_own_property_descriptor(duk_context *ctx) {
 }
 
 /*
- *  NormalizePropertyDescriptor().
+ *  NormalizePropertyDescriptor() related helper.
  *
- *  Internal helper to convert an external property descriptor on stack top
- *  to a normalized form with plain, coerced values.  The original descriptor
- *  object is not altered.
+ *  Internal helper which validates and normalizes a property descriptor
+ *  represented as an Ecmascript object (e.g. argument to defineProperty()).
+ *  The output of this conversion is a set of defprop_flags and possibly
+ *  some values pushed on the value stack; some subset of: property value,
+ *  getter, setter.  Caller must manage stack top carefully because the
+ *  number of values pushed depends on the input property descriptor.
+ *
+ *  The original descriptor object must not be altered in the process.
  */
 
 /* XXX: very basic optimization -> duk_get_prop_stridx_top */
 
-static void duk__normalize_property_descriptor(duk_context *ctx) {
+DUK_INTERNAL
+void duk_hobject_prepare_property_descriptor(duk_context *ctx,
+                                             duk_idx_t idx_in,
+                                             duk_uint_t *out_defprop_flags,
+                                             duk_idx_t *out_idx_value,
+                                             duk_hobject **out_getter,
+                                             duk_hobject **out_setter) {
 	duk_hthread *thr = (duk_hthread *) ctx;
-	duk_idx_t idx_in;
-	duk_idx_t idx_out;
-	duk_idx_t target_top;
+	duk_idx_t idx_value = -1;
+	duk_hobject *getter = NULL;
+	duk_hobject *setter = NULL;
 	duk_bool_t is_data_desc = 0;
 	duk_bool_t is_acc_desc = 0;
+	duk_uint_t defprop_flags = 0;
 
 	DUK_ASSERT(ctx != NULL);
+	DUK_ASSERT(out_defprop_flags != NULL);
+	DUK_ASSERT(out_idx_value != NULL);
+	DUK_ASSERT(out_getter != NULL);
+	DUK_ASSERT(out_setter != NULL);
 
-	/* must be an object, otherwise TypeError (E5.1 Section 8.10.5, step 1) */
-	(void) duk_require_hobject(ctx, -1);
-
-	idx_in = duk_require_normalize_index(ctx, -1);
-	duk_push_object(ctx);  /* [... desc_in desc_out] */
-	idx_out = idx_in + 1;
+	/* Must be an object, otherwise TypeError (E5.1 Section 8.10.5, step 1). */
+	idx_in = duk_require_normalize_index(ctx, idx_in);
+	(void) duk_require_hobject(ctx, idx_in);
 
-	/* this approach allows us to be care-free with the "stack policy"
-	 * until the very end.
+	/* The coercion order must match the ToPropertyDescriptor() algorithm
+	 * so that side effects in coercion happen in the correct order.
+	 * (This order also happens to be compatible with duk_def_prop(),
+	 * although it doesn't matter in practice.)
 	 */
-	target_top = duk_get_top(ctx);
 
 	if (duk_get_prop_stridx(ctx, idx_in, DUK_STRIDX_VALUE)) {
 		is_data_desc = 1;
-		duk_put_prop_stridx(ctx, idx_out, DUK_STRIDX_VALUE);
+		defprop_flags |= DUK_DEFPROP_HAVE_VALUE;
+		idx_value = duk_get_top_index(ctx);
+		/* Leave 'value' on stack */
+	} else {
+		duk_pop(ctx);
 	}
 
 	if (duk_get_prop_stridx(ctx, idx_in, DUK_STRIDX_WRITABLE)) {
 		is_data_desc = 1;
-		duk_to_boolean(ctx, -1);
-		duk_put_prop_stridx(ctx, idx_out, DUK_STRIDX_WRITABLE);
+		if (duk_to_boolean(ctx, -1)) {
+			defprop_flags |= DUK_DEFPROP_HAVE_WRITABLE | DUK_DEFPROP_WRITABLE;
+		} else {
+			defprop_flags |= DUK_DEFPROP_HAVE_WRITABLE;
+		}
 	}
+	duk_pop(ctx);
 
 	if (duk_get_prop_stridx(ctx, idx_in, DUK_STRIDX_GET)) {
 		duk_tval *tv = duk_require_tval(ctx, -1);
-		is_acc_desc = 1;
-		if (DUK_TVAL_IS_UNDEFINED(tv) ||
-		    (DUK_TVAL_IS_OBJECT(tv) &&
-		     DUK_HOBJECT_IS_CALLABLE(DUK_TVAL_GET_OBJECT(tv)))) {
-			duk_put_prop_stridx(ctx, idx_out, DUK_STRIDX_GET);
+		duk_hobject *h_get;
+
+		if (DUK_TVAL_IS_UNDEFINED(tv)) {
+			/* undefined is accepted */
+			DUK_ASSERT(getter == NULL);
 		} else {
-			goto type_error;
+			/* NOTE: lightfuncs are coerced to full functions because
+			 * lightfuncs don't fit into a property value slot.  This
+			 * has some side effects, see test-dev-lightfunc-accessor.js.
+			 */
+			h_get = duk_get_hobject_or_lfunc_coerce(ctx, -1);
+			if (h_get == NULL || !DUK_HOBJECT_IS_CALLABLE(h_get)) {
+				goto type_error;
+			}
+			getter = h_get;
 		}
+		is_acc_desc = 1;
+		defprop_flags |= DUK_DEFPROP_HAVE_GETTER;
+		/* Leave 'getter' on stack */
+	} else {
+		duk_pop(ctx);
 	}
 
 	if (duk_get_prop_stridx(ctx, idx_in, DUK_STRIDX_SET)) {
 		duk_tval *tv = duk_require_tval(ctx, -1);
+		duk_hobject *h_set;
+
 		is_acc_desc = 1;
-		if (DUK_TVAL_IS_UNDEFINED(tv) ||
-		    (DUK_TVAL_IS_OBJECT(tv) &&
-		     DUK_HOBJECT_IS_CALLABLE(DUK_TVAL_GET_OBJECT(tv)))) {
-			duk_put_prop_stridx(ctx, idx_out, DUK_STRIDX_SET);
-		} else {
-			goto type_error;
+		if (DUK_TVAL_IS_UNDEFINED(tv)) {
+			/* undefined is accepted */
+			DUK_ASSERT(setter == NULL);
+		}  else {
+			/* NOTE: lightfuncs are coerced to full functions because
+			 * lightfuncs don't fit into a property value slot.  This
+			 * has some side effects, see test-dev-lightfunc-accessor.js.
+			 */
+			h_set = duk_get_hobject_or_lfunc_coerce(ctx, -1);
+			if (h_set == NULL || !DUK_HOBJECT_IS_CALLABLE(h_set)) {
+				goto type_error;
+			}
+			setter = h_set;
 		}
+		is_acc_desc = 1;
+		defprop_flags |= DUK_DEFPROP_HAVE_SETTER;
+		/* Leave 'setter' on stack */
+	} else {
+		duk_pop(ctx);
 	}
 
 	if (duk_get_prop_stridx(ctx, idx_in, DUK_STRIDX_ENUMERABLE)) {
-		duk_to_boolean(ctx, -1);
-		duk_put_prop_stridx(ctx, idx_out, DUK_STRIDX_ENUMERABLE);
+		if (duk_to_boolean(ctx, -1)) {
+			defprop_flags |= DUK_DEFPROP_HAVE_ENUMERABLE | DUK_DEFPROP_ENUMERABLE;
+		} else {
+			defprop_flags |= DUK_DEFPROP_HAVE_ENUMERABLE;
+		}
 	}
+	duk_pop(ctx);
 
 	if (duk_get_prop_stridx(ctx, idx_in, DUK_STRIDX_CONFIGURABLE)) {
-		duk_to_boolean(ctx, -1);
-		duk_put_prop_stridx(ctx, idx_out, DUK_STRIDX_CONFIGURABLE);
+		if (duk_to_boolean(ctx, -1)) {
+			defprop_flags |= DUK_DEFPROP_HAVE_CONFIGURABLE | DUK_DEFPROP_CONFIGURABLE;
+		} else {
+			defprop_flags |= DUK_DEFPROP_HAVE_CONFIGURABLE;
+		}
 	}
+	duk_pop(ctx);
 
 	if (is_data_desc && is_acc_desc) {
 		goto type_error;
 	}
 
-	/* pop any crud */
-	duk_set_top(ctx, target_top);
-
-	/* [... desc_in desc_out] */
-
-	duk_remove(ctx, -2);
-
-	/* [... desc_out] */
+	*out_defprop_flags = defprop_flags;
+	*out_idx_value = idx_value;
+	*out_getter = getter;
+	*out_setter = setter;
 
+	/* [ ... value? getter? setter? ] */
 	return;
 
  type_error:
@@ -38319,10 +54311,9 @@ static void duk__normalize_property_descriptor(duk_context *ctx) {
 }
 
 /*
- *  Object.defineProperty()  (E5 Section 15.2.3.6)
+ *  Object.defineProperty() related helper  (E5 Section 15.2.3.6)
  *
- *  Inlines ToPropertyDescriptor() and all [[DefineOwnProperty]] exotic
- *  behaviors.
+ *  Inlines all [[DefineOwnProperty]] exotic behaviors.
  *
  *  Note: Ecmascript compliant [[DefineOwnProperty]](P, Desc, Throw) is not
  *  implemented directly, but Object.defineProperty() serves its purpose.
@@ -38330,18 +54321,24 @@ static void duk__normalize_property_descriptor(duk_context *ctx) {
  *  property descriptor with 'missing values' so it's easier to avoid it
  *  entirely.
  *
- *  This is a Duktape/C function.
+ *  Note: this is only called for actual objects, not primitive values.
+ *  This must support virtual properties for full objects (e.g. Strings)
+ *  but not for plain values (e.g. strings).  Lightfuncs, even though
+ *  primitive in a sense, are treated like objects and accepted as target
+ *  values.
  */
 
 /* XXX: this is a major target for size optimization */
-
-duk_ret_t duk_hobject_object_define_property(duk_context *ctx) {
+DUK_INTERNAL
+void duk_hobject_define_property_helper(duk_context *ctx,
+                                        duk_uint_t defprop_flags,
+                                        duk_hobject *obj,
+                                        duk_hstring *key,
+                                        duk_idx_t idx_value,
+                                        duk_hobject *get,
+                                        duk_hobject *set) {
 	duk_hthread *thr = (duk_hthread *) ctx;
-	duk_hobject *obj;
-	duk_hstring *key;
-	duk_hobject *desc;
 	duk_uint32_t arr_idx;
-	duk_idx_t idx_desc;
 	duk_tval tv;
 	duk_bool_t has_enumerable;
 	duk_bool_t has_configurable;
@@ -38352,137 +54349,59 @@ duk_ret_t duk_hobject_object_define_property(duk_context *ctx) {
 	duk_bool_t is_enumerable;
 	duk_bool_t is_configurable;
 	duk_bool_t is_writable;
-	duk_idx_t idx_value;
-	duk_hobject *get;
-	duk_hobject *set;
+	duk_bool_t throw_flag;
+	duk_bool_t force_flag;
 	duk_small_uint_t new_flags;
 	duk_propdesc curr;
 	duk_uint32_t arridx_new_array_length;  /* != 0 => post-update for array 'length' (used when key is an array index) */
 	duk_uint32_t arrlen_old_len;
 	duk_uint32_t arrlen_new_len;
 	duk_bool_t pending_write_protect;
-	duk_bool_t throw_flag = 1;   /* Object.defineProperty() calls [[DefineOwnProperty]] with Throw=true */
-
-	DUK_DDD(DUK_DDDPRINT("Object.defineProperty(): thr=%p obj=%!T key=%!T desc=%!T",
-	                     (void *) thr,
-	                     (duk_tval *) duk_get_tval(ctx, 0),
-	                     (duk_tval *) duk_get_tval(ctx, 1),
-	                     (duk_tval *) duk_get_tval(ctx, 2)));
 
 	DUK_ASSERT(thr != NULL);
 	DUK_ASSERT(thr->heap != NULL);
 	DUK_ASSERT(ctx != NULL);
+	DUK_ASSERT(obj != NULL);
+	DUK_ASSERT(key != NULL);
+	/* idx_value may be < 0 (no value), set and get may be NULL */
 
 	DUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);
 
-	obj = duk_require_hobject(ctx, 0);
-	(void) duk_to_string(ctx, 1);
-	key = duk_require_hstring(ctx, 1);
-	desc = duk_require_hobject(ctx, 2);
-	DUK_UNREF(desc);
-	idx_desc = 2;
+	/* All the flags fit in 16 bits, so will fit into duk_bool_t. */
 
-	DUK_ASSERT(obj != NULL);
-	DUK_ASSERT(key != NULL);
-	DUK_ASSERT(desc != NULL);
+	has_writable = (defprop_flags & DUK_DEFPROP_HAVE_WRITABLE);
+	has_enumerable = (defprop_flags & DUK_DEFPROP_HAVE_ENUMERABLE);
+	has_configurable = (defprop_flags & DUK_DEFPROP_HAVE_CONFIGURABLE);
+	has_value = (defprop_flags & DUK_DEFPROP_HAVE_VALUE);
+	has_get = (defprop_flags & DUK_DEFPROP_HAVE_GETTER);
+	has_set = (defprop_flags & DUK_DEFPROP_HAVE_SETTER);
+	is_writable = (defprop_flags & DUK_DEFPROP_WRITABLE);
+	is_enumerable = (defprop_flags & DUK_DEFPROP_ENUMERABLE);
+	is_configurable = (defprop_flags & DUK_DEFPROP_CONFIGURABLE);
+	throw_flag = 1;   /* Object.defineProperty() calls [[DefineOwnProperty]] with Throw=true */
+	force_flag = (defprop_flags & DUK_DEFPROP_FORCE);
 
 	arr_idx = DUK_HSTRING_GET_ARRIDX_SLOW(key);
 
-	DUK_DDD(DUK_DDDPRINT("Object.defineProperty(): thr=%p obj=%!O key=%!O arr_idx=0x%08lx desc=%!O",
-	                     (void *) thr, (duk_heaphdr *) obj, (duk_heaphdr *) key,
-	                     (unsigned long) arr_idx, (duk_heaphdr *) desc));
-
-	/* Many of the above are just assigned over but are given base values to
-	 * avoid warnings with some compilers.  But because the values are unused,
-	 * scan-build will complain about them; silence with DUK_UNREF().
-	 */
-
-	has_enumerable = 0; DUK_UNREF(has_enumerable);
-	has_configurable = 0; DUK_UNREF(has_configurable);
-	has_value = 0; DUK_UNREF(has_value);
-	has_writable = 0; DUK_UNREF(has_writable);
-	has_get = 0; DUK_UNREF(has_get);
-	has_set = 0; DUK_UNREF(has_set);
-	is_enumerable = 0; DUK_UNREF(is_enumerable);
-	is_configurable = 0; DUK_UNREF(is_configurable);
-	is_writable = 0; DUK_UNREF(is_writable);
-	idx_value = -1; DUK_UNREF(idx_value);
-	get = NULL; DUK_UNREF(get);
-	set = NULL; DUK_UNREF(set);
-
 	arridx_new_array_length = 0;
 	pending_write_protect = 0;
 	arrlen_old_len = 0;
 	arrlen_new_len = 0;
 
-	/*
-	 *  Extract property descriptor values as required in ToPropertyDescriptor().
-	 *  However, don't create an explicit property descriptor object: we don't
-	 *  want to create a new Ecmascript object, and the internal property descriptor
-	 *  does not support partial descriptors.
-	 *
-	 *  Note that ToPropertyDescriptor() does coercions with potential errors, so
-	 *  all coercions must be done first.  Boolean conversion of 'undefined' is false.
-	 */
-
-	is_enumerable = duk_get_prop_stridx_boolean(ctx, idx_desc, DUK_STRIDX_ENUMERABLE, &has_enumerable);
-	is_configurable = duk_get_prop_stridx_boolean(ctx, idx_desc, DUK_STRIDX_CONFIGURABLE, &has_configurable);
-
-	has_value = duk_get_prop_stridx(ctx, idx_desc, DUK_STRIDX_VALUE);
-	if (has_value) {
-		/* Note: we don't want to store a pointer to an duk_tval in the
-		 * valstack here, because a valstack resize (which may occur
-		 * on any gc) might invalidate it.
-		 */
-		idx_value = duk_require_top_index(ctx);
-	} else {
-		idx_value = -1;
-	}
-	/* leave value on stack intentionally to ensure we can refer to it later */
-
-	is_writable = duk_get_prop_stridx_boolean(ctx, idx_desc, DUK_STRIDX_WRITABLE, &has_writable);
-
-	has_get = duk_get_prop_stridx(ctx, idx_desc, DUK_STRIDX_GET);
-	get = NULL;
-	if (has_get && !duk_is_undefined(ctx, -1)) {
-		/* XXX: get = duk_require_callable_hobject(ctx, -1)? */
-		get = duk_require_hobject(ctx, -1);
-		DUK_ASSERT(get != NULL);
-		if (!DUK_HOBJECT_IS_CALLABLE(get)) {
-			goto fail_invalid_desc;
-		}
-	}
-	/* leave get on stack */
-
-	has_set = duk_get_prop_stridx(ctx, idx_desc, DUK_STRIDX_SET);
-	set = NULL;
-	if (has_set && !duk_is_undefined(ctx, -1)) {
-		set = duk_require_hobject(ctx, -1);
-		DUK_ASSERT(set != NULL);
-		if (!DUK_HOBJECT_IS_CALLABLE(set)) {
-			goto fail_invalid_desc;
-		}
-	}
-	/* leave set on stack */
-
-	if ((has_set || has_get) && (has_value || has_writable)) {
-		goto fail_invalid_desc;
-	}
-
-	/* [obj key desc value get set] */
-
 	DUK_DDD(DUK_DDDPRINT("has_enumerable=%ld is_enumerable=%ld "
 	                     "has_configurable=%ld is_configurable=%ld "
 	                     "has_writable=%ld is_writable=%ld "
 	                     "has_value=%ld value=%!T "
 	                     "has_get=%ld get=%p=%!O "
-	                     "has_set=%ld set=%p=%!O ",
+	                     "has_set=%ld set=%p=%!O "
+	                     "arr_idx=%ld",
 	                     (long) has_enumerable, (long) is_enumerable,
 	                     (long) has_configurable, (long) is_configurable,
 	                     (long) has_writable, (long) is_writable,
-	                     (long) has_value, (duk_tval *) duk_get_tval(ctx, idx_value),
+	                     (long) has_value, (duk_tval *) (idx_value >= 0 ? duk_get_tval(ctx, idx_value) : NULL),
 	                     (long) has_get, (void *) get, (duk_heaphdr *) get,
-	                     (long) has_set, (void *) set, (duk_heaphdr *) set));
+	                     (long) has_set, (void *) set, (duk_heaphdr *) set,
+	                     (long) arr_idx));
 
 	/*
 	 *  Array exotic behaviors can be implemented at this point.  The local variables
@@ -38500,7 +54419,7 @@ duk_ret_t duk_hobject_object_define_property(duk_context *ctx) {
 			DUK_DDD(DUK_DDDPRINT("exotic array behavior for 'length', but no value in descriptor -> normal behavior"));
 			goto skip_array_exotic;
 		}
-	
+
 		DUK_DDD(DUK_DDDPRINT("exotic array behavior for 'length', value present in descriptor -> exotic behavior"));
 
 		/*
@@ -38512,6 +54431,7 @@ duk_ret_t duk_hobject_object_define_property(duk_context *ctx) {
 
 		duk_dup(ctx, idx_value);
 		arrlen_new_len = duk__to_new_array_length_checked(thr);
+		duk_push_u32(ctx, arrlen_new_len);
 		duk_replace(ctx, idx_value);  /* step 3.e: replace 'Desc.[[Value]]' */
 
 		DUK_DDD(DUK_DDDPRINT("old_len=%ld, new_len=%ld", (long) arrlen_old_len, (long) arrlen_new_len));
@@ -38523,8 +54443,8 @@ duk_ret_t duk_hobject_object_define_property(duk_context *ctx) {
 		}
 		DUK_DDD(DUK_DDDPRINT("new length is smaller than previous => exotic post behavior"));
 
-		/* FIXME: consolidated algorithm step 15.f -> redundant? */
-		if (!(curr.flags & DUK_PROPDESC_FLAG_WRITABLE)) {
+		/* XXX: consolidated algorithm step 15.f -> redundant? */
+		if (!(curr.flags & DUK_PROPDESC_FLAG_WRITABLE) && !force_flag) {
 			/* Note: 'curr' refers to 'length' propdesc */
 			goto fail_not_writable_array_length;
 		}
@@ -38538,7 +54458,7 @@ duk_ret_t duk_hobject_object_define_property(duk_context *ctx) {
 
 		/* remaining actual steps are carried out if standard DefineOwnProperty succeeds */
 	} else if (arr_idx != DUK__NO_ARRAY_INDEX) {
-		/* FIXME: any chance of unifying this with the 'length' key handling? */
+		/* XXX: any chance of unifying this with the 'length' key handling? */
 
 		/* E5 Section 15.4.5.1, step 4 */
 		duk_uint32_t old_len;
@@ -38569,6 +54489,13 @@ duk_ret_t duk_hobject_object_define_property(duk_context *ctx) {
 	}
  skip_array_exotic:
 
+	/* XXX: There is currently no support for writing buffer object
+	 * indexed elements here.  Attempt to do so will succeed and
+	 * write a concrete property into the buffer object.  This should
+	 * be fixed at some point but because buffers are a custom feature
+	 * anyway, this is relatively unimportant.
+	 */
+
 	/*
 	 *  Actual Object.defineProperty() default algorithm.
 	 */
@@ -38578,14 +54505,14 @@ duk_ret_t duk_hobject_object_define_property(duk_context *ctx) {
 	 *  steps 1-4.
 	 */
 
-	if (!duk__get_own_property_desc_raw(thr, obj, key, arr_idx, &curr, 1)) {
+	if (!duk__get_own_property_desc_raw(thr, obj, key, arr_idx, &curr, DUK__DESC_FLAG_PUSH_VALUE)) {
 		DUK_DDD(DUK_DDDPRINT("property does not exist"));
 
-		if (!DUK_HOBJECT_HAS_EXTENSIBLE(obj)) {
+		if (!DUK_HOBJECT_HAS_EXTENSIBLE(obj) && !force_flag) {
 			goto fail_not_extensible;
 		}
 
-		/* FIXME: share final setting code for value and flags?  difficult because
+		/* XXX: share final setting code for value and flags?  difficult because
 		 * refcount code is different.  Share entry allocation?  But can't allocate
 		 * until array index checked.
 		 */
@@ -38618,12 +54545,12 @@ duk_ret_t duk_hobject_object_define_property(duk_context *ctx) {
 			e_idx = duk__alloc_entry_checked(thr, obj, key);
 			DUK_ASSERT(e_idx >= 0);
 
-			DUK_HOBJECT_E_SET_VALUE_GETTER(obj, e_idx, get);
-			DUK_HOBJECT_E_SET_VALUE_SETTER(obj, e_idx, set);
-			DUK_HOBJECT_INCREF(thr, get);
-			DUK_HOBJECT_INCREF(thr, set);
+			DUK_HOBJECT_E_SET_VALUE_GETTER(thr->heap, obj, e_idx, get);
+			DUK_HOBJECT_E_SET_VALUE_SETTER(thr->heap, obj, e_idx, set);
+			DUK_HOBJECT_INCREF_ALLOWNULL(thr, get);
+			DUK_HOBJECT_INCREF_ALLOWNULL(thr, set);
 
-			DUK_HOBJECT_E_SET_FLAGS(obj, e_idx, new_flags);
+			DUK_HOBJECT_E_SET_FLAGS(thr->heap, obj, e_idx, new_flags);
 			goto success_exotics;
 		} else {
 			duk_int_t e_idx;
@@ -38648,7 +54575,7 @@ duk_ret_t duk_hobject_object_define_property(duk_context *ctx) {
 				duk_tval *tv_tmp = duk_require_tval(ctx, idx_value);
 				DUK_TVAL_SET_TVAL(&tv, tv_tmp);
 			} else {
-				DUK_TVAL_SET_UNDEFINED_ACTUAL(&tv);  /* default value */
+				DUK_TVAL_SET_UNDEFINED(&tv);  /* default value */
 			}
 
 			if (arr_idx != DUK__NO_ARRAY_INDEX && DUK_HOBJECT_HAS_ARRAY_PART(obj)) {
@@ -38657,7 +54584,7 @@ duk_ret_t duk_hobject_object_define_property(duk_context *ctx) {
 					DUK_DDD(DUK_DDDPRINT("new data property attributes match array defaults, attempt to write to array part"));
 					/* may become sparse...*/
 #endif
-					/* FIXME: handling for array part missing now; this doesn't affect
+					/* XXX: handling for array part missing now; this doesn't affect
 					 * compliance but causes array entry writes using defineProperty()
 					 * to always abandon array part.
 					 */
@@ -38670,11 +54597,11 @@ duk_ret_t duk_hobject_object_define_property(duk_context *ctx) {
 			/* write to entry part */
 			e_idx = duk__alloc_entry_checked(thr, obj, key);
 			DUK_ASSERT(e_idx >= 0);
-			tv2 = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(obj, e_idx);
+			tv2 = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, obj, e_idx);
 			DUK_TVAL_SET_TVAL(tv2, &tv);
 			DUK_TVAL_INCREF(thr, tv2);
 
-			DUK_HOBJECT_E_SET_FLAGS(obj, e_idx, new_flags);
+			DUK_HOBJECT_E_SET_FLAGS(thr->heap, obj, e_idx, new_flags);
 			goto success_exotics;
 		}
 		DUK_UNREACHABLE();
@@ -38715,7 +54642,7 @@ duk_ret_t duk_hobject_object_define_property(duk_context *ctx) {
 	if (has_value) {
 		duk_tval *tmp1;
 		duk_tval *tmp2;
-	
+
 		/* attempt to change from accessor to data property */
 		if (curr.flags & DUK_PROPDESC_FLAG_ACCESSOR) {
 			goto need_check;
@@ -38774,7 +54701,7 @@ duk_ret_t duk_hobject_object_define_property(duk_context *ctx) {
 	 */
 
 	/* shared checks for all descriptor types */
-	if (!(curr.flags & DUK_PROPDESC_FLAG_CONFIGURABLE)) {
+	if (!(curr.flags & DUK_PROPDESC_FLAG_CONFIGURABLE) && !force_flag) {
 		if (has_configurable && is_configurable) {
 			goto fail_not_configurable;
 		}
@@ -38791,9 +54718,10 @@ duk_ret_t duk_hobject_object_define_property(duk_context *ctx) {
 		}
 	}
 
-	/* reject attempt to change virtual properties: not part of the
+	/* Reject attempt to change virtual properties: not part of the
 	 * standard algorithm, applies currently to e.g. virtual index
 	 * properties of buffer objects (which are virtual but writable).
+	 * (Cannot "force" modification of a virtual property.)
 	 */
 	if (curr.flags & DUK_PROPDESC_FLAG_VIRTUAL) {
 		goto fail_virtual;
@@ -38807,7 +54735,7 @@ duk_ret_t duk_hobject_object_define_property(duk_context *ctx) {
 
 		if (curr.flags & DUK_PROPDESC_FLAG_ACCESSOR) {
 			/* curr and desc are accessors */
-			if (!(curr.flags & DUK_PROPDESC_FLAG_CONFIGURABLE)) {
+			if (!(curr.flags & DUK_PROPDESC_FLAG_CONFIGURABLE) && !force_flag) {
 				if (has_set && set != curr.set) {
 					goto fail_not_configurable;
 				}
@@ -38816,12 +54744,11 @@ duk_ret_t duk_hobject_object_define_property(duk_context *ctx) {
 				}
 			}
 		} else {
-			int rc;
-			duk_tval tv_tmp;
+			duk_bool_t rc;
 			duk_tval *tv1;
 
 			/* curr is data, desc is accessor */
-			if (!(curr.flags & DUK_PROPDESC_FLAG_CONFIGURABLE)) {
+			if (!(curr.flags & DUK_PROPDESC_FLAG_CONFIGURABLE) && !force_flag) {
 				goto fail_not_configurable;
 			}
 
@@ -38830,30 +54757,31 @@ duk_ret_t duk_hobject_object_define_property(duk_context *ctx) {
 				DUK_DDD(DUK_DDDPRINT("property to convert is stored in an array entry, abandon array and re-lookup"));
 				duk__abandon_array_checked(thr, obj);
 				duk_pop(ctx);  /* remove old value */
-				rc = duk__get_own_property_desc_raw(thr, obj, key, arr_idx, &curr, 1);
+				rc = duk__get_own_property_desc_raw(thr, obj, key, arr_idx, &curr, DUK__DESC_FLAG_PUSH_VALUE);
 				DUK_UNREF(rc);
 				DUK_ASSERT(rc != 0);
 				DUK_ASSERT(curr.e_idx >= 0 && curr.a_idx < 0);
 			}
 
-			DUK_ASSERT(!DUK_HOBJECT_E_SLOT_IS_ACCESSOR(obj, curr.e_idx));
+			DUK_ASSERT(!DUK_HOBJECT_E_SLOT_IS_ACCESSOR(thr->heap, obj, curr.e_idx));
 
-			tv1 = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(obj, curr.e_idx);
-			DUK_TVAL_SET_TVAL(&tv_tmp, tv1);
-			DUK_TVAL_SET_UNDEFINED_UNUSED(tv1);
-			DUK_TVAL_DECREF(thr, &tv_tmp);
+			tv1 = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, obj, curr.e_idx);
+			/* XXX: just decref */
+			DUK_TVAL_SET_UNDEFINED_UPDREF(thr, tv1);  /* side effects */
 
-			DUK_HOBJECT_E_SET_VALUE_GETTER(obj, curr.e_idx, NULL);
-			DUK_HOBJECT_E_SET_VALUE_SETTER(obj, curr.e_idx, NULL);
-			DUK_HOBJECT_E_SLOT_CLEAR_WRITABLE(obj, curr.e_idx);
-			DUK_HOBJECT_E_SLOT_SET_ACCESSOR(obj, curr.e_idx);
+			DUK_HOBJECT_E_SET_VALUE_GETTER(thr->heap, obj, curr.e_idx, NULL);
+			DUK_HOBJECT_E_SET_VALUE_SETTER(thr->heap, obj, curr.e_idx, NULL);
+			DUK_HOBJECT_E_SLOT_CLEAR_WRITABLE(thr->heap, obj, curr.e_idx);
+			DUK_HOBJECT_E_SLOT_SET_ACCESSOR(thr->heap, obj, curr.e_idx);
 
 			DUK_DDD(DUK_DDDPRINT("flags after data->accessor conversion: 0x%02lx",
-			                     (unsigned long) DUK_HOBJECT_E_GET_FLAGS(obj, curr.e_idx)));
+			                     (unsigned long) DUK_HOBJECT_E_GET_FLAGS(thr->heap, obj, curr.e_idx)));
 
-			/* re-lookup to update curr.flags -- FIXME: faster to update directly */
+			/* re-lookup to update curr.flags
+			 * XXX: would be faster to update directly
+			 */
 			duk_pop(ctx);  /* remove old value */
-			rc = duk__get_own_property_desc_raw(thr, obj, key, arr_idx, &curr, 1);
+			rc = duk__get_own_property_desc_raw(thr, obj, key, arr_idx, &curr, DUK__DESC_FLAG_PUSH_VALUE);
 			DUK_UNREF(rc);
 			DUK_ASSERT(rc != 0);
 		}
@@ -38867,7 +54795,7 @@ duk_ret_t duk_hobject_object_define_property(duk_context *ctx) {
 			duk_hobject *tmp;
 
 			/* curr is accessor, desc is data */
-			if (!(curr.flags & DUK_PROPDESC_FLAG_CONFIGURABLE)) {
+			if (!(curr.flags & DUK_PROPDESC_FLAG_CONFIGURABLE) && !force_flag) {
 				goto fail_not_configurable;
 			}
 
@@ -38876,31 +54804,33 @@ duk_ret_t duk_hobject_object_define_property(duk_context *ctx) {
 
 			DUK_DDD(DUK_DDDPRINT("convert property to data property"));
 
-			DUK_ASSERT(DUK_HOBJECT_E_SLOT_IS_ACCESSOR(obj, curr.e_idx));
-			tmp = DUK_HOBJECT_E_GET_VALUE_GETTER(obj, curr.e_idx);
+			DUK_ASSERT(DUK_HOBJECT_E_SLOT_IS_ACCESSOR(thr->heap, obj, curr.e_idx));
+			tmp = DUK_HOBJECT_E_GET_VALUE_GETTER(thr->heap, obj, curr.e_idx);
 			DUK_UNREF(tmp);
-			DUK_HOBJECT_E_SET_VALUE_GETTER(obj, curr.e_idx, NULL);
-			DUK_HOBJECT_DECREF(thr, tmp);
-			tmp = DUK_HOBJECT_E_GET_VALUE_SETTER(obj, curr.e_idx);
+			DUK_HOBJECT_E_SET_VALUE_GETTER(thr->heap, obj, curr.e_idx, NULL);
+			DUK_HOBJECT_DECREF_ALLOWNULL(thr, tmp);  /* side effects */
+			tmp = DUK_HOBJECT_E_GET_VALUE_SETTER(thr->heap, obj, curr.e_idx);
 			DUK_UNREF(tmp);
-			DUK_HOBJECT_E_SET_VALUE_SETTER(obj, curr.e_idx, NULL);
-			DUK_HOBJECT_DECREF(thr, tmp);
+			DUK_HOBJECT_E_SET_VALUE_SETTER(thr->heap, obj, curr.e_idx, NULL);
+			DUK_HOBJECT_DECREF_ALLOWNULL(thr, tmp);  /* side effects */
 
-			DUK_TVAL_SET_UNDEFINED_ACTUAL(DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(obj, curr.e_idx));
-			DUK_HOBJECT_E_SLOT_CLEAR_WRITABLE(obj, curr.e_idx);
-			DUK_HOBJECT_E_SLOT_CLEAR_ACCESSOR(obj, curr.e_idx);
+			DUK_TVAL_SET_UNDEFINED(DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, obj, curr.e_idx));
+			DUK_HOBJECT_E_SLOT_CLEAR_WRITABLE(thr->heap, obj, curr.e_idx);
+			DUK_HOBJECT_E_SLOT_CLEAR_ACCESSOR(thr->heap, obj, curr.e_idx);
 
 			DUK_DDD(DUK_DDDPRINT("flags after accessor->data conversion: 0x%02lx",
-			                     (unsigned long) DUK_HOBJECT_E_GET_FLAGS(obj, curr.e_idx)));
+			                     (unsigned long) DUK_HOBJECT_E_GET_FLAGS(thr->heap, obj, curr.e_idx)));
 
-			/* re-lookup to update curr.flags -- FIXME: faster to update directly */
+			/* re-lookup to update curr.flags
+			 * XXX: would be faster to update directly
+			 */
 			duk_pop(ctx);  /* remove old value */
-			rc = duk__get_own_property_desc_raw(thr, obj, key, arr_idx, &curr, 1);
+			rc = duk__get_own_property_desc_raw(thr, obj, key, arr_idx, &curr, DUK__DESC_FLAG_PUSH_VALUE);
 			DUK_UNREF(rc);
 			DUK_ASSERT(rc != 0);
 		} else {
 			/* curr and desc are data */
-			if (!(curr.flags & DUK_PROPDESC_FLAG_CONFIGURABLE)) {
+			if (!(curr.flags & DUK_PROPDESC_FLAG_CONFIGURABLE) && !force_flag) {
 				if (!(curr.flags & DUK_PROPDESC_FLAG_WRITABLE) && has_writable && is_writable) {
 					goto fail_not_configurable;
 				}
@@ -38954,7 +54884,7 @@ duk_ret_t duk_hobject_object_define_property(duk_context *ctx) {
 		}
 	}
 
-	/* FIXME: write protect after flag? -> any chance of handling it here? */
+	/* XXX: write protect after flag? -> any chance of handling it here? */
 
 	DUK_DDD(DUK_DDDPRINT("new flags that we want to write: 0x%02lx",
 	                     (unsigned long) new_flags));
@@ -38970,7 +54900,6 @@ duk_ret_t duk_hobject_object_define_property(duk_context *ctx) {
 
 		if (new_flags == DUK_PROPDESC_FLAGS_WEC) {
 			duk_tval *tv1, *tv2;
-			duk_tval tv_tmp;
 
 			DUK_DDD(DUK_DDDPRINT("array index, new property attributes match array defaults, update in-place"));
 
@@ -38979,18 +54908,15 @@ duk_ret_t duk_hobject_object_define_property(duk_context *ctx) {
 			DUK_ASSERT(!has_get);
 
 			tv2 = duk_require_tval(ctx, idx_value);
-			tv1 = DUK_HOBJECT_A_GET_VALUE_PTR(obj, curr.a_idx);
-			DUK_TVAL_SET_TVAL(&tv_tmp, tv1);
-			DUK_TVAL_SET_TVAL(tv1, tv2);
-			DUK_TVAL_INCREF(thr, tv1);
-			DUK_TVAL_DECREF(thr, &tv_tmp);
+			tv1 = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, obj, curr.a_idx);
+			DUK_TVAL_SET_TVAL_UPDREF(thr, tv1, tv2);  /* side effects */
 			goto success_exotics;
 		}
 
 		DUK_DDD(DUK_DDDPRINT("array index, new property attributes do not match array defaults, abandon array and re-lookup"));
 		duk__abandon_array_checked(thr, obj);
 		duk_pop(ctx);  /* remove old value */
-		rc = duk__get_own_property_desc_raw(thr, obj, key, arr_idx, &curr, 1);
+		rc = duk__get_own_property_desc_raw(thr, obj, key, arr_idx, &curr, DUK__DESC_FLAG_PUSH_VALUE);
 		DUK_UNREF(rc);
 		DUK_ASSERT(rc != 0);
 		DUK_ASSERT(curr.e_idx >= 0 && curr.a_idx < 0);
@@ -39002,45 +54928,41 @@ duk_ret_t duk_hobject_object_define_property(duk_context *ctx) {
 	DUK_ASSERT(curr.e_idx >= 0 && curr.a_idx < 0);
 
 	DUK_DDD(DUK_DDDPRINT("update existing property attributes"));
-	DUK_HOBJECT_E_SET_FLAGS(obj, curr.e_idx, new_flags);
+	DUK_HOBJECT_E_SET_FLAGS(thr->heap, obj, curr.e_idx, new_flags);
 
 	if (has_set) {
 		duk_hobject *tmp;
 
 		DUK_DDD(DUK_DDDPRINT("update existing property setter"));
-		DUK_ASSERT(DUK_HOBJECT_E_SLOT_IS_ACCESSOR(obj, curr.e_idx));
+		DUK_ASSERT(DUK_HOBJECT_E_SLOT_IS_ACCESSOR(thr->heap, obj, curr.e_idx));
 
-		tmp = DUK_HOBJECT_E_GET_VALUE_SETTER(obj, curr.e_idx);
+		tmp = DUK_HOBJECT_E_GET_VALUE_SETTER(thr->heap, obj, curr.e_idx);
 		DUK_UNREF(tmp);
-		DUK_HOBJECT_E_SET_VALUE_SETTER(obj, curr.e_idx, set);
-		DUK_HOBJECT_INCREF(thr, set);
-		DUK_HOBJECT_DECREF(thr, tmp);
+		DUK_HOBJECT_E_SET_VALUE_SETTER(thr->heap, obj, curr.e_idx, set);
+		DUK_HOBJECT_INCREF_ALLOWNULL(thr, set);
+		DUK_HOBJECT_DECREF_ALLOWNULL(thr, tmp);  /* side effects */
 	}
 	if (has_get) {
 		duk_hobject *tmp;
 
 		DUK_DDD(DUK_DDDPRINT("update existing property getter"));
-		DUK_ASSERT(DUK_HOBJECT_E_SLOT_IS_ACCESSOR(obj, curr.e_idx));
+		DUK_ASSERT(DUK_HOBJECT_E_SLOT_IS_ACCESSOR(thr->heap, obj, curr.e_idx));
 
-		tmp = DUK_HOBJECT_E_GET_VALUE_GETTER(obj, curr.e_idx);
+		tmp = DUK_HOBJECT_E_GET_VALUE_GETTER(thr->heap, obj, curr.e_idx);
 		DUK_UNREF(tmp);
-		DUK_HOBJECT_E_SET_VALUE_GETTER(obj, curr.e_idx, get);
-		DUK_HOBJECT_INCREF(thr, get);
-		DUK_HOBJECT_DECREF(thr, tmp);
+		DUK_HOBJECT_E_SET_VALUE_GETTER(thr->heap, obj, curr.e_idx, get);
+		DUK_HOBJECT_INCREF_ALLOWNULL(thr, get);
+		DUK_HOBJECT_DECREF_ALLOWNULL(thr, tmp);  /* side effects */
 	}
 	if (has_value) {
 		duk_tval *tv1, *tv2;
-		duk_tval tv_tmp;
 
 		DUK_DDD(DUK_DDDPRINT("update existing property value"));
-		DUK_ASSERT(!DUK_HOBJECT_E_SLOT_IS_ACCESSOR(obj, curr.e_idx));
+		DUK_ASSERT(!DUK_HOBJECT_E_SLOT_IS_ACCESSOR(thr->heap, obj, curr.e_idx));
 
 		tv2 = duk_require_tval(ctx, idx_value);
-		tv1 = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(obj, curr.e_idx);
-		DUK_TVAL_SET_TVAL(&tv_tmp, tv1);
-		DUK_TVAL_SET_TVAL(tv1, tv2);
-		DUK_TVAL_INCREF(thr, tv1);
-		DUK_TVAL_DECREF(thr, &tv_tmp);
+		tv1 = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, obj, curr.e_idx);
+		DUK_TVAL_SET_TVAL_UPDREF(thr, tv1, tv2);  /* side effects */
 	}
 
 	/*
@@ -39075,14 +54997,19 @@ duk_ret_t duk_hobject_object_define_property(duk_context *ctx) {
 			                     (long) arridx_new_array_length));
 
 			/* Note: reuse 'curr' */
-			rc = duk__get_own_property_desc_raw(thr, obj, DUK_HTHREAD_STRING_LENGTH(thr), DUK__NO_ARRAY_INDEX, &curr, 0);
+			rc = duk__get_own_property_desc_raw(thr, obj, DUK_HTHREAD_STRING_LENGTH(thr), DUK__NO_ARRAY_INDEX, &curr, 0 /*flags*/);  /* don't push value */
 			DUK_UNREF(rc);
 			DUK_ASSERT(rc != 0);
 			DUK_ASSERT(curr.e_idx >= 0);
 
-			tmp = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(obj, curr.e_idx);
+			tmp = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, obj, curr.e_idx);
 			DUK_ASSERT(DUK_TVAL_IS_NUMBER(tmp));
-			DUK_TVAL_SET_NUMBER(tmp, (duk_double_t) arridx_new_array_length);  /* no need for decref/incref because value is a number */
+			/* no need for decref/incref because value is a number */
+#if defined(DUK_USE_FASTINT)
+			DUK_TVAL_SET_FASTINT_U32(tmp, arridx_new_array_length);
+#else
+			DUK_TVAL_SET_NUMBER(tmp, (duk_double_t) arridx_new_array_length);
+#endif
 		}
 		if (key == DUK_HTHREAD_STRING_LENGTH(thr) && arrlen_new_len < arrlen_old_len) {
 			/*
@@ -39093,36 +55020,41 @@ duk_ret_t duk_hobject_object_define_property(duk_context *ctx) {
 			 *  'writable' update.
 			 */
 
-			/* FIXME: investigate whether write protect can be handled above, if we
+			/* XXX: investigate whether write protect can be handled above, if we
 			 * just update length here while ignoring its protected status
 			 */
 
 			duk_tval *tmp;
 			duk_uint32_t result_len;
-			int rc;
+			duk_bool_t rc;
 
 			DUK_DDD(DUK_DDDPRINT("defineProperty successful, key is 'length', exotic array behavior, "
 			                     "doing array element deletion and length update"));
 
-			rc = duk__handle_put_array_length_smaller(thr, obj, arrlen_old_len, arrlen_new_len, &result_len);
+			rc = duk__handle_put_array_length_smaller(thr, obj, arrlen_old_len, arrlen_new_len, force_flag, &result_len);
 
 			/* update length (curr points to length, and we assume it's still valid) */
 			DUK_ASSERT(result_len >= arrlen_new_len && result_len <= arrlen_old_len);
 
 			DUK_ASSERT(curr.e_idx >= 0);
-			DUK_ASSERT(!DUK_HOBJECT_E_SLOT_IS_ACCESSOR(obj, curr.e_idx));
-			tmp = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(obj, curr.e_idx);
+			DUK_ASSERT(!DUK_HOBJECT_E_SLOT_IS_ACCESSOR(thr->heap, obj, curr.e_idx));
+			tmp = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, obj, curr.e_idx);
 			DUK_ASSERT(DUK_TVAL_IS_NUMBER(tmp));
-			DUK_TVAL_SET_NUMBER(tmp, (duk_double_t) result_len);  /* no decref needed for a number */
+			/* no decref needed for a number */
+#if defined(DUK_USE_FASTINT)
+			DUK_TVAL_SET_FASTINT_U32(tmp, result_len);
+#else
+			DUK_TVAL_SET_NUMBER(tmp, (duk_double_t) result_len);
+#endif
 			DUK_ASSERT(DUK_TVAL_IS_NUMBER(tmp));
 
 			if (pending_write_protect) {
 				DUK_DDD(DUK_DDDPRINT("setting array length non-writable (pending writability update)"));
-				DUK_HOBJECT_E_SLOT_CLEAR_WRITABLE(obj, curr.e_idx);
+				DUK_HOBJECT_E_SLOT_CLEAR_WRITABLE(thr->heap, obj, curr.e_idx);
 			}
 
 			/*
-			 *  FIXME: shrink array allocation or entries compaction here?
+			 *  XXX: shrink array allocation or entries compaction here?
 			 */
 
 			if (!rc) {
@@ -39189,141 +55121,34 @@ duk_ret_t duk_hobject_object_define_property(duk_context *ctx) {
 	}
 
  success_no_exotics:
-	/* no need to unwind stack (rewound automatically) */
-	duk_set_top(ctx, 1);  /* -> [ obj ] */
-	return 1;
+	return;
 
  fail_virtual:
 	DUK_ERROR(thr, DUK_ERR_TYPE_ERROR, DUK_STR_PROPERTY_IS_VIRTUAL);
-	return 0;
-
- fail_invalid_desc:
-	DUK_ERROR(thr, DUK_ERR_TYPE_ERROR, DUK_STR_INVALID_DESCRIPTOR);
-	return 0;
+	return;
 
  fail_not_writable_array_length:
 	DUK_ERROR(thr, DUK_ERR_TYPE_ERROR, DUK_STR_ARRAY_LENGTH_NOT_WRITABLE);
-	return 0;
+	return;
 
  fail_not_extensible:
 	DUK_ERROR(thr, DUK_ERR_TYPE_ERROR, DUK_STR_NOT_EXTENSIBLE);
-	return 0;
+	return;
 
  fail_not_configurable:
 	DUK_ERROR(thr, DUK_ERR_TYPE_ERROR, DUK_STR_NOT_CONFIGURABLE);
-	return 0;
+	return;
 
  fail_array_length_partial:
 	DUK_ERROR(thr, DUK_ERR_TYPE_ERROR, DUK_STR_ARRAY_LENGTH_WRITE_FAILED);
-	return 0;
-}
-
-/*
- *  Object.defineProperties()  (E5 Section 15.2.3.7)
- *
- *  This is an actual function call.
- */
-
-duk_ret_t duk_hobject_object_define_properties(duk_context *ctx) {
-	duk_require_hobject(ctx, 0);  /* target */
-	duk_to_object(ctx, 1);        /* properties object */
-
-	DUK_DDD(DUK_DDDPRINT("target=%!iT, properties=%!iT",
-	                     (duk_tval *) duk_get_tval(ctx, 0),
-	                     (duk_tval *) duk_get_tval(ctx, 1)));
-
-	duk_push_object(ctx);
-	duk_enum(ctx, 1, DUK_ENUM_OWN_PROPERTIES_ONLY /*enum_flags*/);
-
-	/* [hobject props descriptors enum(props)] */
-
-	DUK_DDD(DUK_DDDPRINT("enum(properties)=%!iT",
-	                     (duk_tval *) duk_get_tval(ctx, 3)));
-
-	for (;;) {
-		if (!duk_next(ctx, 3, 1 /*get_value*/)) {
-			break;
-		}
-
-		DUK_DDD(DUK_DDDPRINT("-> key=%!iT, desc=%!iT",
-		                     (duk_tval *) duk_get_tval(ctx, -2),
-		                     (duk_tval *) duk_get_tval(ctx, -1)));
-
-		/* [hobject props descriptors enum(props) key desc] */
-
-		duk__normalize_property_descriptor(ctx);
-		
-		/* [hobject props descriptors enum(props) key desc_norm] */
-
-		duk_put_prop(ctx, 2);
-
-		/* [hobject props descriptors enum(props)] */
-	}
-
-	DUK_DDD(DUK_DDDPRINT("-> descriptors=%!iT",
-	                     (duk_tval *) duk_get_tval(ctx, 2)));
-
-	/* We rely on 'descriptors' having the same key order as 'props'
-	 * to match the array semantics of E5 Section 15.2.3.7.
-	 */
-
-	duk_pop(ctx);
-	duk_enum(ctx, 2, 0 /*enum_flags*/);
-
-	/* [hobject props descriptors enum(descriptors)] */
-
-	DUK_DDD(DUK_DDDPRINT("enum(descriptors)=%!iT",
-	                     (duk_tval *) duk_get_tval(ctx, 3)));
-
-	for (;;) {
-		if (!duk_next(ctx, 3, 1 /*get_value*/)) {
-			break;
-		}
-
-		DUK_DDD(DUK_DDDPRINT("-> key=%!iT, desc=%!iT",
-		                     (duk_tval *) duk_get_tval(ctx, -2),
-		                     (duk_tval *) duk_get_tval(ctx, -1)));
-
-		/* [hobject props descriptors enum(descriptors) key desc_norm] */
-
-		duk_dup(ctx, 0);
-		duk_insert(ctx, -3);
-
-		/* [hobject props descriptors enum(descriptors) hobject key desc_norm] */
-
-		/* FIXME: need access to the -original- Object.defineProperty function
-		 * object here (the property is configurable so a caller may have changed
-		 * it).  This is not a good approach as a new Ecmascript function is created
-		 * for every loop.
-		 */
-		duk_push_c_function(ctx, duk_hobject_object_define_property, 3);
-		duk_insert(ctx, -4);
-
-		/* [hobject props descriptors enum(descriptors) Object.defineProperty hobject key desc_norm] */
-
-		duk_call(ctx, 3);
-
-		/* [hobject props descriptors enum(descriptors) retval] */
-
-		/* FIXME: call which ignores result would be nice */
-
-		duk_pop(ctx);
-	}
-
-	/* [hobject props descriptors enum(descriptors)] */
-
-	duk_dup(ctx, 0);
-	
-	/* [hobject props descriptors enum(descriptors) hobject] */
-
-	return 1;
+	return;
 }
 
 /*
  *  Object.prototype.hasOwnProperty() and Object.prototype.propertyIsEnumerable().
  */
 
-duk_bool_t duk_hobject_object_ownprop_helper(duk_context *ctx, duk_small_uint_t required_desc_flags) {
+DUK_INTERNAL duk_bool_t duk_hobject_object_ownprop_helper(duk_context *ctx, duk_small_uint_t required_desc_flags) {
 	duk_hthread *thr = (duk_hthread *) ctx;
 	duk_hstring *h_v;
 	duk_hobject *h_obj;
@@ -39337,7 +55162,7 @@ duk_bool_t duk_hobject_object_ownprop_helper(duk_context *ctx, duk_small_uint_t
 	h_obj = duk_push_this_coercible_to_object(ctx);
 	DUK_ASSERT(h_obj != NULL);
 
-	ret = duk__get_own_property_desc(thr, h_obj, h_v, &desc, 0 /*push_value*/);
+	ret = duk__get_own_property_desc(thr, h_obj, h_v, &desc, 0 /*flags*/);  /* don't push value */
 
 	duk_push_boolean(ctx, ret && ((desc.flags & required_desc_flags) == required_desc_flags));
 	return 1;
@@ -39345,7 +55170,7 @@ duk_bool_t duk_hobject_object_ownprop_helper(duk_context *ctx, duk_small_uint_t
 
 /*
  *  Object.seal() and Object.freeze()  (E5 Sections 15.2.3.8 and 15.2.3.9)
- * 
+ *
  *  Since the algorithms are similar, a helper provides both functions.
  *  Freezing is essentially sealing + making plain properties non-writable.
  *
@@ -39358,7 +55183,7 @@ duk_bool_t duk_hobject_object_ownprop_helper(duk_context *ctx, duk_small_uint_t
  *  requiring some additional flags in the object.
  */
 
-void duk_hobject_object_seal_freeze_helper(duk_hthread *thr, duk_hobject *obj, duk_bool_t is_freeze) {
+DUK_INTERNAL void duk_hobject_object_seal_freeze_helper(duk_hthread *thr, duk_hobject *obj, duk_bool_t is_freeze) {
 	duk_uint_fast32_t i;
 
 	DUK_ASSERT(thr != NULL);
@@ -39375,16 +55200,16 @@ void duk_hobject_object_seal_freeze_helper(duk_hthread *thr, duk_hobject *obj, d
 	 */
 
 	duk__abandon_array_checked(thr, obj);
-	DUK_ASSERT(obj->a_size == 0);
+	DUK_ASSERT(DUK_HOBJECT_GET_ASIZE(obj) == 0);
 
-	for (i = 0; i < obj->e_used; i++) {
+	for (i = 0; i < DUK_HOBJECT_GET_ENEXT(obj); i++) {
 		duk_uint8_t *fp;
 
 		/* since duk__abandon_array_checked() causes a resize, there should be no gaps in keys */
-		DUK_ASSERT(DUK_HOBJECT_E_GET_KEY(obj, i) != NULL);
+		DUK_ASSERT(DUK_HOBJECT_E_GET_KEY(thr->heap, obj, i) != NULL);
 
 		/* avoid multiple computations of flags address; bypasses macros */
-		fp = DUK_HOBJECT_E_GET_FLAGS_PTR(obj, i);
+		fp = DUK_HOBJECT_E_GET_FLAGS_PTR(thr->heap, obj, i);
 		if (is_freeze && !((*fp) & DUK_PROPDESC_FLAG_ACCESSOR)) {
 			*fp &= ~(DUK_PROPDESC_FLAG_WRITABLE | DUK_PROPDESC_FLAG_CONFIGURABLE);
 		} else {
@@ -39412,10 +55237,11 @@ void duk_hobject_object_seal_freeze_helper(duk_hthread *thr, duk_hobject *obj, d
  *  need to be considered here now.
  */
 
-duk_bool_t duk_hobject_object_is_sealed_frozen_helper(duk_hobject *obj, duk_bool_t is_frozen) {
+DUK_INTERNAL duk_bool_t duk_hobject_object_is_sealed_frozen_helper(duk_hthread *thr, duk_hobject *obj, duk_bool_t is_frozen) {
 	duk_uint_fast32_t i;
 
 	DUK_ASSERT(obj != NULL);
+	DUK_UNREF(thr);
 
 	/* Note: no allocation pressure, no need to check refcounts etc */
 
@@ -39429,15 +55255,15 @@ duk_bool_t duk_hobject_object_is_sealed_frozen_helper(duk_hobject *obj, duk_bool
 	/* entry part must not contain any configurable properties, or
 	 * writable properties (if is_frozen).
 	 */
-	for (i = 0; i < obj->e_used; i++) {
+	for (i = 0; i < DUK_HOBJECT_GET_ENEXT(obj); i++) {
 		duk_small_uint_t flags;
 
-		if (!DUK_HOBJECT_E_GET_KEY(obj, i)) {
+		if (!DUK_HOBJECT_E_GET_KEY(thr->heap, obj, i)) {
 			continue;
 		}
 
 		/* avoid multiple computations of flags address; bypasses macros */
-		flags = (duk_small_uint_t) DUK_HOBJECT_E_GET_FLAGS(obj, i);
+		flags = (duk_small_uint_t) DUK_HOBJECT_E_GET_FLAGS(thr->heap, obj, i);
 
 		if (flags & DUK_PROPDESC_FLAG_CONFIGURABLE) {
 			return 0;
@@ -39452,9 +55278,9 @@ duk_bool_t duk_hobject_object_is_sealed_frozen_helper(duk_hobject *obj, duk_bool
 	/* array part must not contain any non-unused properties, as they would
 	 * be configurable and writable.
 	 */
-	for (i = 0; i < obj->a_size; i++) {
-		duk_tval *tv = DUK_HOBJECT_A_GET_VALUE_PTR(obj, i);
-		if (!DUK_TVAL_IS_UNDEFINED_UNUSED(tv)) {
+	for (i = 0; i < DUK_HOBJECT_GET_ASIZE(obj); i++) {
+		duk_tval *tv = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, obj, i);
+		if (!DUK_TVAL_IS_UNUSED(tv)) {
 			return 0;
 		}
 	}
@@ -39465,10 +55291,8 @@ duk_bool_t duk_hobject_object_is_sealed_frozen_helper(duk_hobject *obj, duk_bool
 /*
  *  Object.preventExtensions() and Object.isExtensible()  (E5 Sections 15.2.3.10, 15.2.3.13)
  *
- *  Implemented directly in macros:
- *
- *    DUK_HOBJECT_OBJECT_PREVENT_EXTENSIONS()
- *    DUK_HOBJECT_OBJECT_IS_EXTENSIBLE()
+ *  Not needed, implemented by macros DUK_HOBJECT_{HAS,CLEAR,SET}_EXTENSIBLE
+ *  and the Object built-in bindings.
  */
 
 /* Undefine local defines */
@@ -39486,9 +55310,9 @@ duk_bool_t duk_hobject_object_is_sealed_frozen_helper(duk_hobject *obj, duk_bool
 
 /* include removed: duk_internal.h */
 
-duk_ucodepoint_t duk_hstring_char_code_at_raw(duk_hthread *thr, duk_hstring *h, duk_uint_t pos) {
+DUK_INTERNAL duk_ucodepoint_t duk_hstring_char_code_at_raw(duk_hthread *thr, duk_hstring *h, duk_uint_t pos) {
 	duk_uint32_t boff;
-	duk_uint8_t *p, *p_start, *p_end;
+	const duk_uint8_t *p, *p_start, *p_end;
 	duk_ucodepoint_t cp;
 
 	/* Caller must check character offset to be inside the string. */
@@ -39507,7 +55331,8 @@ duk_ucodepoint_t duk_hstring_char_code_at_raw(duk_hthread *thr, duk_hstring *h,
 	p_end = p_start + DUK_HSTRING_GET_BYTELEN(h);
 	p = p_start + boff;
 	DUK_DDD(DUK_DDDPRINT("p_start=%p, p_end=%p, p=%p",
-	                     (void *) p_start, (void *) p_end, (void *) p));
+	                     (const void *) p_start, (const void *) p_end,
+	                     (const void *) p));
 
 	/* This may throw an error though not for valid E5 strings. */
 	cp = duk_unicode_decode_xutf8_checked(thr, &p, p_start, p_end);
@@ -39526,7 +55351,7 @@ duk_ucodepoint_t duk_hstring_char_code_at_raw(duk_hthread *thr, duk_hstring *h,
  *  Returns zero (without leaking memory) if init fails.
  */
 
-duk_bool_t duk_hthread_init_stacks(duk_heap *heap, duk_hthread *thr) {
+DUK_INTERNAL duk_bool_t duk_hthread_init_stacks(duk_heap *heap, duk_hthread *thr) {
 	duk_size_t alloc_size;
 	duk_size_t i;
 
@@ -39547,11 +55372,14 @@ duk_bool_t duk_hthread_init_stacks(duk_heap *heap, duk_hthread *thr) {
 	}
 	DUK_MEMZERO(thr->valstack, alloc_size);
 	thr->valstack_end = thr->valstack + DUK_VALSTACK_INITIAL_SIZE;
+#if !defined(DUK_USE_PREFER_SIZE)
+	thr->valstack_size = DUK_VALSTACK_INITIAL_SIZE;
+#endif
 	thr->valstack_bottom = thr->valstack;
 	thr->valstack_top = thr->valstack;
 
 	for (i = 0; i < DUK_VALSTACK_INITIAL_SIZE; i++) {
-		DUK_TVAL_SET_UNDEFINED_UNUSED(&thr->valstack[i]);
+		DUK_TVAL_SET_UNDEFINED(&thr->valstack[i]);
 	}
 
 	/* callstack */
@@ -39589,18 +55417,21 @@ duk_bool_t duk_hthread_init_stacks(duk_heap *heap, duk_hthread *thr) {
 
 /* For indirect allocs. */
 
-void *duk_hthread_get_valstack_ptr(void *ud) {
+DUK_INTERNAL void *duk_hthread_get_valstack_ptr(duk_heap *heap, void *ud) {
 	duk_hthread *thr = (duk_hthread *) ud;
+	DUK_UNREF(heap);
 	return (void *) thr->valstack;
 }
 
-void *duk_hthread_get_callstack_ptr(void *ud) {
+DUK_INTERNAL void *duk_hthread_get_callstack_ptr(duk_heap *heap, void *ud) {
 	duk_hthread *thr = (duk_hthread *) ud;
+	DUK_UNREF(heap);
 	return (void *) thr->callstack;
 }
 
-void *duk_hthread_get_catchstack_ptr(void *ud) {
+DUK_INTERNAL void *duk_hthread_get_catchstack_ptr(duk_heap *heap, void *ud) {
 	duk_hthread *thr = (duk_hthread *) ud;
+	DUK_UNREF(heap);
 	return (void *) thr->catchstack;
 }
 #line 1 "duk_hthread_builtins.c"
@@ -39617,7 +55448,7 @@ void *duk_hthread_get_catchstack_ptr(void *ud) {
  */
 
 #define DUK__CLASS_BITS                  5
-#define DUK__BIDX_BITS                   6
+#define DUK__BIDX_BITS                   7
 #define DUK__STRIDX_BITS                 9  /* XXX: try to optimize to 8 */
 #define DUK__NATIDX_BITS                 8
 #define DUK__NUM_NORMAL_PROPS_BITS       6
@@ -39632,7 +55463,7 @@ void *duk_hthread_get_catchstack_ptr(void *ud) {
 
 #define DUK__NARGS_VARARGS_MARKER        0x07
 #define DUK__NO_CLASS_MARKER             0x00   /* 0 = DUK_HOBJECT_CLASS_UNUSED */
-#define DUK__NO_BIDX_MARKER              0x3f
+#define DUK__NO_BIDX_MARKER              0x7f
 #define DUK__NO_STRIDX_MARKER            0xff
 
 #define DUK__PROP_TYPE_DOUBLE            0
@@ -39649,7 +55480,7 @@ void *duk_hthread_get_catchstack_ptr(void *ud) {
  *  by genbuiltins.py.
  */
 
-void duk_hthread_create_builtin_objects(duk_hthread *thr) {
+DUK_INTERNAL void duk_hthread_create_builtin_objects(duk_hthread *thr) {
 	duk_context *ctx = (duk_context *) thr;
 	duk_bitdecoder_ctx bd_ctx;
 	duk_bitdecoder_ctx *bd = &bd_ctx;  /* convenience */
@@ -39716,7 +55547,7 @@ void duk_hthread_create_builtin_objects(duk_hthread *thr) {
 			/* XXX: function properties */
 
 			duk_push_hstring_stridx(ctx, stridx);
-			duk_def_prop_stridx(ctx, -2, DUK_STRIDX_NAME, DUK_PROPDESC_FLAGS_NONE);
+			duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_NAME, DUK_PROPDESC_FLAGS_NONE);
 
 			/* Almost all global level Function objects are constructable
 			 * but not all: Function.prototype is a non-constructable,
@@ -39762,11 +55593,11 @@ void duk_hthread_create_builtin_objects(duk_hthread *thr) {
 			 */
 
 			duk_push_int(ctx, len);
-			duk_def_prop_stridx(ctx,
-			                    -2,
-			                    DUK_STRIDX_LENGTH,
-			                    (class_num == DUK_HOBJECT_CLASS_ARRAY ?  /* only Array.prototype matches */
-			                     DUK_PROPDESC_FLAGS_W : DUK_PROPDESC_FLAGS_NONE));
+			duk_xdef_prop_stridx(ctx,
+			                     -2,
+			                     DUK_STRIDX_LENGTH,
+			                     (class_num == DUK_HOBJECT_CLASS_ARRAY ?  /* only Array.prototype matches */
+			                      DUK_PROPDESC_FLAGS_W : DUK_PROPDESC_FLAGS_NONE));
 		}
 
 		/* enable exotic behaviors last */
@@ -39827,18 +55658,18 @@ void duk_hthread_create_builtin_objects(duk_hthread *thr) {
 			 *  [[Configurable]] = false
 			 */
 			DUK_DDD(DUK_DDDPRINT("set external prototype: built-in %ld", (long) t));
-			duk_def_prop_stridx_builtin(ctx, i, DUK_STRIDX_PROTOTYPE, t, DUK_PROPDESC_FLAGS_NONE);
+			duk_xdef_prop_stridx_builtin(ctx, i, DUK_STRIDX_PROTOTYPE, t, DUK_PROPDESC_FLAGS_NONE);
 		}
 
 		t = (duk_small_uint_t) duk_bd_decode(bd, DUK__BIDX_BITS);
 		if (t != DUK__NO_BIDX_MARKER) {
 			/* 'constructor' property for all built-in objects (which have it) has attributes:
 			 *  [[Writable]] = true,
-			 *  [[Enumerable]] = false,	
+			 *  [[Enumerable]] = false,
 			 *  [[Configurable]] = true
 			 */
 			DUK_DDD(DUK_DDDPRINT("set external constructor: built-in %ld", (long) t));
-			duk_def_prop_stridx_builtin(ctx, i, DUK_STRIDX_CONSTRUCTOR, t, DUK_PROPDESC_FLAGS_WC);
+			duk_xdef_prop_stridx_builtin(ctx, i, DUK_STRIDX_CONSTRUCTOR, t, DUK_PROPDESC_FLAGS_WC);
 		}
 
 		/* normal valued properties */
@@ -39936,9 +55767,6 @@ void duk_hthread_create_builtin_objects(duk_hthread *thr) {
 				duk_c_function c_func_getter;
 				duk_c_function c_func_setter;
 
-				/* XXX: this is a bit awkward because there is no exposed helper
-				 * in the API style, only this internal helper.
-				 */
 				DUK_DDD(DUK_DDDPRINT("built-in accessor property: objidx=%ld, stridx=%ld, getteridx=%ld, setteridx=%ld, flags=0x%04lx",
 				                     (long) i, (long) stridx, (long) natidx_getter, (long) natidx_setter, (unsigned long) prop_flags));
 
@@ -39947,7 +55775,7 @@ void duk_hthread_create_builtin_objects(duk_hthread *thr) {
 				duk_push_c_function_noconstruct_noexotic(ctx, c_func_getter, 0);  /* always 0 args */
 				duk_push_c_function_noconstruct_noexotic(ctx, c_func_setter, 1);  /* always 1 arg */
 
-				/* XXX: magic for getter/setter? */
+				/* XXX: magic for getter/setter? use duk_def_prop()? */
 
 				prop_flags |= DUK_PROPDESC_FLAG_ACCESSOR;  /* accessor flag not encoded explicitly */
 				duk_hobject_define_accessor_internal(thr,
@@ -39966,7 +55794,7 @@ void duk_hthread_create_builtin_objects(duk_hthread *thr) {
 			}
 
 			DUK_ASSERT((prop_flags & DUK_PROPDESC_FLAG_ACCESSOR) == 0);
-			duk_def_prop_stridx(ctx, i, stridx, prop_flags);
+			duk_xdef_prop_stridx(ctx, i, stridx, prop_flags);
 
 		 skip_value:
 			continue;  /* avoid empty label at the end of a compound statement */
@@ -39983,6 +55811,9 @@ void duk_hthread_create_builtin_objects(duk_hthread *thr) {
 			duk_int16_t magic;
 			duk_c_function c_func;
 			duk_hnativefunction *h_func;
+#if defined(DUK_USE_LIGHTFUNC_BUILTINS)
+			duk_small_int_t lightfunc_eligible;
+#endif
 
 			stridx = (duk_small_uint_t) duk_bd_decode(bd, DUK__STRIDX_BITS);
 			natidx = (duk_small_uint_t) duk_bd_decode(bd, DUK__NATIDX_BITS);
@@ -39999,6 +55830,39 @@ void duk_hthread_create_builtin_objects(duk_hthread *thr) {
 			                     (long) i, (long) j, (long) stridx, (long) natidx, (long) c_length,
 			                     (c_nargs == DUK_VARARGS ? (long) -1 : (long) c_nargs)));
 
+			/* Cast converts magic to 16-bit signed value */
+			magic = (duk_int16_t) duk_bd_decode_flagged(bd, DUK__MAGIC_BITS, 0);
+
+#if defined(DUK_USE_LIGHTFUNC_BUILTINS)
+			lightfunc_eligible =
+				((c_nargs >= DUK_LFUNC_NARGS_MIN && c_nargs <= DUK_LFUNC_NARGS_MAX) || (c_nargs == DUK_VARARGS)) &&
+				(c_length <= DUK_LFUNC_LENGTH_MAX) &&
+				(magic >= DUK_LFUNC_MAGIC_MIN && magic <= DUK_LFUNC_MAGIC_MAX);
+			if (stridx == DUK_STRIDX_EVAL ||
+			    stridx == DUK_STRIDX_YIELD ||
+			    stridx == DUK_STRIDX_RESUME ||
+			    stridx == DUK_STRIDX_REQUIRE) {
+				/* These functions have trouble working as lightfuncs.
+				 * Some of them have specific asserts and some may have
+			         * additional properties (e.g. 'require.id' may be written).
+				 */
+				DUK_D(DUK_DPRINT("reject as lightfunc: stridx=%d, i=%d, j=%d", (int) stridx, (int) i, (int) j));
+				lightfunc_eligible = 0;
+			}
+
+			if (lightfunc_eligible) {
+				duk_tval tv_lfunc;
+				duk_small_uint_t lf_nargs = (c_nargs == DUK_VARARGS ? DUK_LFUNC_NARGS_VARARGS : c_nargs);
+				duk_small_uint_t lf_flags = DUK_LFUNC_FLAGS_PACK(magic, c_length, lf_nargs);
+				DUK_TVAL_SET_LIGHTFUNC(&tv_lfunc, c_func, lf_flags);
+				duk_push_tval(ctx, &tv_lfunc);
+				DUK_D(DUK_DPRINT("built-in function eligible as light function: i=%d, j=%d c_length=%ld, c_nargs=%ld, magic=%ld -> %!iT", (int) i, (int) j, (long) c_length, (long) c_nargs, (long) magic, duk_get_tval(ctx, -1)));
+				goto lightfunc_skip;
+			}
+
+			DUK_D(DUK_DPRINT("built-in function NOT ELIGIBLE as light function: i=%d, j=%d c_length=%ld, c_nargs=%ld, magic=%ld", (int) i, (int) j, (long) c_length, (long) c_nargs, (long) magic));
+#endif  /* DUK_USE_LIGHTFUNC_BUILTINS */
+
 			/* [ (builtin objects) ] */
 
 			duk_push_c_function_noconstruct_noexotic(ctx, c_func, c_nargs);
@@ -40021,17 +55885,15 @@ void duk_hthread_create_builtin_objects(duk_hthread *thr) {
 			/* XXX: any way to avoid decoding magic bit; there are quite
 			 * many function properties and relatively few with magic values.
 			 */
-			/* Cast converts magic to 16-bit signed value */
-			magic = (duk_int16_t) duk_bd_decode_flagged(bd, DUK__MAGIC_BITS, 0);
 			h_func->magic = magic;
 
 			/* [ (builtin objects) func ] */
 
 			duk_push_int(ctx, c_length);
-			duk_def_prop_stridx(ctx, -2, DUK_STRIDX_LENGTH, DUK_PROPDESC_FLAGS_NONE);
+			duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_LENGTH, DUK_PROPDESC_FLAGS_NONE);
 
 			duk_push_hstring_stridx(ctx, stridx);
-			duk_def_prop_stridx(ctx, -2, DUK_STRIDX_NAME, DUK_PROPDESC_FLAGS_NONE);
+			duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_NAME, DUK_PROPDESC_FLAGS_NONE);
 
 			/* XXX: other properties of function instances; 'arguments', 'caller'. */
 
@@ -40045,7 +55907,11 @@ void duk_hthread_create_builtin_objects(duk_hthread *thr) {
 			 *  function valued properties of built-in objects now.
 			 */
 
-			duk_def_prop_stridx(ctx, i, stridx, DUK_PROPDESC_FLAGS_WC);
+#if defined(DUK_USE_LIGHTFUNC_BUILTINS)
+		 lightfunc_skip:
+#endif
+
+			duk_xdef_prop_stridx(ctx, i, stridx, DUK_PROPDESC_FLAGS_WC);
 
 			/* [ (builtin objects) ] */
 		}
@@ -40069,7 +55935,7 @@ void duk_hthread_create_builtin_objects(duk_hthread *thr) {
 	 */
 
 	duk_get_prop_stridx(ctx, DUK_BIDX_DATE_PROTOTYPE, DUK_STRIDX_TO_UTC_STRING);
-	duk_def_prop_stridx(ctx, DUK_BIDX_DATE_PROTOTYPE, DUK_STRIDX_TO_GMT_STRING, DUK_PROPDESC_FLAGS_WC);
+	duk_xdef_prop_stridx(ctx, DUK_BIDX_DATE_PROTOTYPE, DUK_STRIDX_TO_GMT_STRING, DUK_PROPDESC_FLAGS_WC);
 
 	h = duk_require_hobject(ctx, DUK_BIDX_DOUBLE_ERROR);
 	DUK_ASSERT(h != NULL);
@@ -40077,15 +55943,16 @@ void duk_hthread_create_builtin_objects(duk_hthread *thr) {
 
 #if !defined(DUK_USE_ES6_OBJECT_PROTO_PROPERTY)
 	DUK_DD(DUK_DDPRINT("delete Object.prototype.__proto__ built-in which is not enabled in features"));
-	(void) duk_hobject_delprop_raw(thr, thr->builtins[DUK_BIDX_OBJECT_PROTOTYPE], DUK_HTHREAD_STRING___PROTO__(thr), 1 /*throw_flag*/);
+	(void) duk_hobject_delprop_raw(thr, thr->builtins[DUK_BIDX_OBJECT_PROTOTYPE], DUK_HTHREAD_STRING___PROTO__(thr), DUK_DELPROP_FLAG_THROW);
 #endif
 
 #if !defined(DUK_USE_ES6_OBJECT_SETPROTOTYPEOF)
 	DUK_DD(DUK_DDPRINT("delete Object.setPrototypeOf built-in which is not enabled in features"));
-	(void) duk_hobject_delprop_raw(thr, thr->builtins[DUK_BIDX_OBJECT_CONSTRUCTOR], DUK_HTHREAD_STRING_SET_PROTOTYPE_OF(thr), 1 /*throw_flag*/);
+	(void) duk_hobject_delprop_raw(thr, thr->builtins[DUK_BIDX_OBJECT_CONSTRUCTOR], DUK_HTHREAD_STRING_SET_PROTOTYPE_OF(thr), DUK_DELPROP_FLAG_THROW);
 #endif
 
 	duk_push_string(ctx,
+			/* Endianness indicator */
 #if defined(DUK_USE_INTEGER_LE)
 	                "l"
 #elif defined(DUK_USE_INTEGER_BE)
@@ -40104,16 +55971,57 @@ void duk_hthread_create_builtin_objects(duk_hthread *thr) {
 #else
 	                "?"
 #endif
-#if defined(DUK_USE_BYTEORDER_FORCED)
-			"f"
-#endif
 	                " "
+			/* Packed or unpacked tval */
 #if defined(DUK_USE_PACKED_TVAL)
 	                "p"
 #else
 	                "u"
 #endif
+#if defined(DUK_USE_FASTINT)
+			"f"
+#endif
+			" "
+			/* Low memory options */
+#if defined(DUK_USE_STRTAB_CHAIN)
+			"c"  /* chain */
+#elif defined(DUK_USE_STRTAB_PROBE)
+			"p"  /* probe */
+#else
+			"?"
+#endif
+#if !defined(DUK_USE_HEAPPTR16) && !defined(DUK_DATAPTR16) && !defined(DUK_FUNCPTR16)
+			"n"
+#endif
+#if defined(DUK_USE_HEAPPTR16)
+			"h"
+#endif
+#if defined(DUK_USE_DATAPTR16)
+			"d"
+#endif
+#if defined(DUK_USE_FUNCPTR16)
+			"f"
+#endif
+#if defined(DUK_USE_REFCOUNT16)
+			"R"
+#endif
+#if defined(DUK_USE_STRHASH16)
+			"H"
+#endif
+#if defined(DUK_USE_STRLEN16)
+			"S"
+#endif
+#if defined(DUK_USE_BUFLEN16)
+			"B"
+#endif
+#if defined(DUK_USE_OBJSIZES16)
+			"O"
+#endif
+#if defined(DUK_USE_LIGHTFUNC_BUILTINS)
+			"L"
+#endif
 	                " "
+			/* Object property allocation layout */
 #if defined(DUK_USE_HOBJECT_LAYOUT_1)
 			"p1"
 #elif defined(DUK_USE_HOBJECT_LAYOUT_2)
@@ -40124,16 +56032,24 @@ void duk_hthread_create_builtin_objects(duk_hthread *thr) {
 			"p?"
 #endif
 			" "
-#if defined(DUK_USE_ALIGN_4)
+			/* Alignment guarantee */
+#if (DUK_USE_ALIGN_BY == 4)
 			"a4"
-#elif defined(DUK_USE_ALIGN_8)
+#elif (DUK_USE_ALIGN_BY == 8)
 			"a8"
-#else
+#elif (DUK_USE_ALIGN_BY == 1)
 			"a1"
+#else
+#error invalid DUK_USE_ALIGN_BY
 #endif
 			" "
-	                DUK_USE_ARCH_STRING);
-	duk_def_prop_stridx(ctx, DUK_BIDX_DUKTAPE, DUK_STRIDX_ENV, DUK_PROPDESC_FLAGS_WC);
+			/* Architecture, OS, and compiler strings */
+	                DUK_USE_ARCH_STRING
+			" "
+	                DUK_USE_OS_STRING
+			" "
+	                DUK_USE_COMPILER_STRING);
+	duk_xdef_prop_stridx(ctx, DUK_BIDX_DUKTAPE, DUK_STRIDX_ENV, DUK_PROPDESC_FLAGS_WC);
 
 	/*
 	 *  InitJS code - Ecmascript code evaluated from a built-in source
@@ -40171,13 +56087,6 @@ void duk_hthread_create_builtin_objects(duk_hthread *thr) {
 		                   (long) i, (duk_heaphdr *) thr->builtins[i]));
 	}
 #endif
-	
-#ifdef DUK_USE_DDDPRINT /*XXX:incorrect*/
-	for (i = 0; i < DUK_NUM_BUILTINS; i++) {
-		DUK_DDD(DUK_DDDPRINT("built-in object %ld after initialization and compacting", (long) i));
-		DUK_DEBUG_DUMP_HOBJECT(thr->builtins[i]);
-	}
-#endif
 
 	/*
 	 *  Pop built-ins from stack: they are now INCREF'd and
@@ -40188,15 +56097,14 @@ void duk_hthread_create_builtin_objects(duk_hthread *thr) {
 	DUK_ASSERT_TOP(ctx, 0);
 }
 
-void duk_hthread_copy_builtin_objects(duk_hthread *thr_from, duk_hthread *thr_to) {
+DUK_INTERNAL void duk_hthread_copy_builtin_objects(duk_hthread *thr_from, duk_hthread *thr_to) {
 	duk_small_uint_t i;
 
 	for (i = 0; i < DUK_NUM_BUILTINS; i++) {
 		thr_to->builtins[i] = thr_from->builtins[i];
-		DUK_HOBJECT_INCREF(thr_to, thr_to->builtins[i]);  /* side effect free */
+		DUK_HOBJECT_INCREF_ALLOWNULL(thr_to, thr_to->builtins[i]);  /* side effect free */
 	}
 }
-
 #line 1 "duk_hthread_misc.c"
 /*
  *  Thread support.
@@ -40204,7 +56112,7 @@ void duk_hthread_copy_builtin_objects(duk_hthread *thr_from, duk_hthread *thr_to
 
 /* include removed: duk_internal.h */
 
-void duk_hthread_terminate(duk_hthread *thr) {
+DUK_INTERNAL void duk_hthread_terminate(duk_hthread *thr) {
 	DUK_ASSERT(thr != NULL);
 
 	/* Order of unwinding is important */
@@ -40233,7 +56141,7 @@ void duk_hthread_terminate(duk_hthread *thr) {
 	 */
 }
 
-duk_activation *duk_hthread_get_current_activation(duk_hthread *thr) {
+DUK_INTERNAL duk_activation *duk_hthread_get_current_activation(duk_hthread *thr) {
 	DUK_ASSERT(thr != NULL);
 
 	if (thr->callstack_top > 0) {
@@ -40242,6 +56150,70 @@ duk_activation *duk_hthread_get_current_activation(duk_hthread *thr) {
 		return NULL;
 	}
 }
+
+#if defined(DUK_USE_DEBUGGER_SUPPORT)
+DUK_INTERNAL duk_uint_fast32_t duk_hthread_get_act_curr_pc(duk_hthread *thr, duk_activation *act) {
+	duk_instr_t *bcode;
+
+	DUK_ASSERT(thr != NULL);
+	DUK_ASSERT(act != NULL);
+	DUK_UNREF(thr);
+
+	/* XXX: store 'bcode' pointer to activation for faster lookup? */
+	if (act->func && DUK_HOBJECT_IS_COMPILEDFUNCTION(act->func)) {
+		bcode = DUK_HCOMPILEDFUNCTION_GET_CODE_BASE(thr->heap, (duk_hcompiledfunction *) (act->func));
+		return (duk_uint_fast32_t) (act->curr_pc - bcode);
+	}
+	return 0;
+}
+#endif  /* DUK_USE_DEBUGGER_SUPPORT */
+
+DUK_INTERNAL duk_uint_fast32_t duk_hthread_get_act_prev_pc(duk_hthread *thr, duk_activation *act) {
+	duk_instr_t *bcode;
+	duk_uint_fast32_t ret;
+
+	DUK_ASSERT(thr != NULL);
+	DUK_ASSERT(act != NULL);
+	DUK_UNREF(thr);
+
+	if (act->func && DUK_HOBJECT_IS_COMPILEDFUNCTION(act->func)) {
+		bcode = DUK_HCOMPILEDFUNCTION_GET_CODE_BASE(thr->heap, (duk_hcompiledfunction *) (act->func));
+		ret = (duk_uint_fast32_t) (act->curr_pc - bcode);
+		if (ret > 0) {
+			ret--;
+		}
+		return ret;
+	}
+	return 0;
+}
+
+/* Write bytecode executor's curr_pc back to topmost activation (if any). */
+DUK_INTERNAL void duk_hthread_sync_currpc(duk_hthread *thr) {
+	duk_activation *act;
+
+	DUK_ASSERT(thr != NULL);
+
+	if (thr->ptr_curr_pc != NULL) {
+		/* ptr_curr_pc != NULL only when bytecode executor is active. */
+		DUK_ASSERT(thr->callstack_top > 0);
+		act = thr->callstack + thr->callstack_top - 1;
+		act->curr_pc = *thr->ptr_curr_pc;
+	}
+}
+
+DUK_INTERNAL void duk_hthread_sync_and_null_currpc(duk_hthread *thr) {
+	duk_activation *act;
+
+	DUK_ASSERT(thr != NULL);
+
+	if (thr->ptr_curr_pc != NULL) {
+		/* ptr_curr_pc != NULL only when bytecode executor is active. */
+		DUK_ASSERT(thr->callstack_top > 0);
+		act = thr->callstack + thr->callstack_top - 1;
+		act->curr_pc = *thr->ptr_curr_pc;
+		thr->ptr_curr_pc = NULL;
+	}
+}
 #line 1 "duk_hthread_stacks.c"
 /*
  *  Manipulation of thread stacks (valstack, callstack, catchstack).
@@ -40254,7 +56226,7 @@ duk_activation *duk_hthread_get_current_activation(duk_hthread *thr) {
  *  needs to DECREF multiple objects, close environment records, etc.
  *  Stacks must thus be unwound in the correct order by the caller.
  *
- *  (FIXME: This should be probably reworked so that there is a shared
+ *  (XXX: This should be probably reworked so that there is a shared
  *  unwind primitive which handles all stacks as requested, and knows
  *  the proper order for unwinding.)
  *
@@ -40268,7 +56240,8 @@ duk_activation *duk_hthread_get_current_activation(duk_hthread *thr) {
 /* include removed: duk_internal.h */
 
 /* check that there is space for at least one new entry */
-void duk_hthread_callstack_grow(duk_hthread *thr) {
+DUK_INTERNAL void duk_hthread_callstack_grow(duk_hthread *thr) {
+	duk_activation *new_ptr;
 	duk_size_t old_size;
 	duk_size_t new_size;
 
@@ -40285,7 +56258,7 @@ void duk_hthread_callstack_grow(duk_hthread *thr) {
 
 	/* this is a bit approximate (errors out before max is reached); this is OK */
 	if (new_size >= thr->callstack_max) {
-		DUK_ERROR(thr, DUK_ERR_RANGE_ERROR, "callstack limit");
+		DUK_ERROR(thr, DUK_ERR_RANGE_ERROR, DUK_STR_CALLSTACK_LIMIT);
 	}
 
 	DUK_DD(DUK_DDPRINT("growing callstack %ld -> %ld", (long) old_size, (long) new_size));
@@ -40295,13 +56268,19 @@ void duk_hthread_callstack_grow(duk_hthread *thr) {
 	 *  pointer may be changed by mark-and-sweep.
 	 */
 
-	thr->callstack = (duk_activation *) DUK_REALLOC_INDIRECT_CHECKED(thr, duk_hthread_get_callstack_ptr, (void *) thr, sizeof(duk_activation) * new_size);
+	DUK_ASSERT(new_size > 0);
+	new_ptr = (duk_activation *) DUK_REALLOC_INDIRECT(thr->heap, duk_hthread_get_callstack_ptr, (void *) thr, sizeof(duk_activation) * new_size);
+	if (!new_ptr) {
+		/* No need for a NULL/zero-size check because new_size > 0) */
+		DUK_ERROR(thr, DUK_ERR_ALLOC_ERROR, DUK_STR_REALLOC_FAILED);
+	}
+	thr->callstack = new_ptr;
 	thr->callstack_size = new_size;
 
 	/* note: any entries above the callstack top are garbage and not zeroed */
 }
 
-void duk_hthread_callstack_shrink_check(duk_hthread *thr) {
+DUK_INTERNAL void duk_hthread_callstack_shrink_check(duk_hthread *thr) {
 	duk_size_t new_size;
 	duk_activation *p;
 
@@ -40329,13 +56308,17 @@ void duk_hthread_callstack_shrink_check(duk_hthread *thr) {
 		thr->callstack = p;
 		thr->callstack_size = new_size;
 	} else {
+		/* Because new_size != 0, if condition doesn't need to be
+		 * (p != NULL || new_size == 0).
+		 */
+		DUK_ASSERT(new_size != 0);
 		DUK_D(DUK_DPRINT("callstack shrink failed, ignoring"));
 	}
 
 	/* note: any entries above the callstack top are garbage and not zeroed */
 }
 
-void duk_hthread_callstack_unwind(duk_hthread *thr, duk_size_t new_top) {
+DUK_INTERNAL void duk_hthread_callstack_unwind(duk_hthread *thr, duk_size_t new_top) {
 	duk_size_t idx;
 
 	DUK_DDD(DUK_DDDPRINT("unwind callstack top of thread %p from %ld to %ld",
@@ -40362,57 +56345,79 @@ void duk_hthread_callstack_unwind(duk_hthread *thr, duk_size_t new_top) {
 
 	idx = thr->callstack_top;
 	while (idx > new_top) {
-		duk_activation *p;
+		duk_activation *act;
+		duk_hobject *func;
 #ifdef DUK_USE_REFERENCE_COUNTING
 		duk_hobject *tmp;
 #endif
+#ifdef DUK_USE_DEBUGGER_SUPPORT
+		duk_heap *heap;
+#endif
 
 		idx--;
 		DUK_ASSERT_DISABLE(idx >= 0);  /* unsigned */
 		DUK_ASSERT((duk_size_t) idx < thr->callstack_size);  /* true, despite side effect resizes */
 
-		p = thr->callstack + idx;
-		DUK_ASSERT(p->func != NULL);
+		act = thr->callstack + idx;
+		/* With lightfuncs, act 'func' may be NULL */
 
 #ifdef DUK_USE_NONSTD_FUNC_CALLER_PROPERTY
 		/*
 		 *  Restore 'caller' property for non-strict callee functions.
 		 */
 
-		if (!DUK_HOBJECT_HAS_STRICT(p->func)) {
+		func = DUK_ACT_GET_FUNC(act);
+		if (func != NULL && !DUK_HOBJECT_HAS_STRICT(func)) {
 			duk_tval *tv_caller;
 			duk_tval tv_tmp;
 			duk_hobject *h_tmp;
 
-			tv_caller = duk_hobject_find_existing_entry_tval_ptr(p->func, DUK_HTHREAD_STRING_CALLER(thr));
+			tv_caller = duk_hobject_find_existing_entry_tval_ptr(thr->heap, func, DUK_HTHREAD_STRING_CALLER(thr));
 
-			/* The p->prev_caller should only be set if the entry for 'caller'
+			/* The act->prev_caller should only be set if the entry for 'caller'
 			 * exists (as it is only set in that case, and the property is not
 			 * configurable), but handle all the cases anyway.
 			 */
 
 			if (tv_caller) {
 				DUK_TVAL_SET_TVAL(&tv_tmp, tv_caller);
-				if (p->prev_caller) {
-					/* Just transfer the refcount from p->prev_caller to tv_caller,
+				if (act->prev_caller) {
+					/* Just transfer the refcount from act->prev_caller to tv_caller,
 					 * so no need for a refcount update.  This is the expected case.
 					 */
-					DUK_TVAL_SET_OBJECT(tv_caller, p->prev_caller);
-					p->prev_caller = NULL;
+					DUK_TVAL_SET_OBJECT(tv_caller, act->prev_caller);
+					act->prev_caller = NULL;
 				} else {
 					DUK_TVAL_SET_NULL(tv_caller);   /* no incref needed */
-					DUK_ASSERT(p->prev_caller == NULL);
+					DUK_ASSERT(act->prev_caller == NULL);
 				}
 				DUK_TVAL_DECREF(thr, &tv_tmp);  /* side effects */
 			} else {
-				h_tmp = p->prev_caller;
+				h_tmp = act->prev_caller;
 				if (h_tmp) {
-					p->prev_caller = NULL;
+					act->prev_caller = NULL;
 					DUK_HOBJECT_DECREF(thr, h_tmp);  /* side effects */
 				}
 			}
-			p = thr->callstack + idx;  /* avoid side effects */
-			DUK_ASSERT(p->prev_caller == NULL);
+			act = thr->callstack + idx;  /* avoid side effects */
+			DUK_ASSERT(act->prev_caller == NULL);
+		}
+#endif
+
+		/*
+		 *  Unwind debugger state.  If we unwind while stepping
+		 *  (either step over or step into), pause execution.
+		 */
+
+#if defined(DUK_USE_DEBUGGER_SUPPORT)
+		heap = thr->heap;
+		if (heap->dbg_step_thread == thr &&
+		    heap->dbg_step_csindex == idx) {
+			/* Pause for all step types: step into, step over, step out.
+			 * This is the only place explicitly handling a step out.
+			 */
+			DUK_HEAP_SET_PAUSED(heap);
+			DUK_ASSERT(heap->dbg_step_thread == NULL);
 		}
 #endif
 
@@ -40426,46 +56431,48 @@ void duk_hthread_callstack_unwind(duk_hthread *thr, duk_size_t new_top) {
 		 *  environment is created for e.g. an eval call, it must not be closed.
 		 */
 
-		if (!DUK_HOBJECT_HAS_NEWENV(p->func)) {
+		func = DUK_ACT_GET_FUNC(act);
+		if (func != NULL && !DUK_HOBJECT_HAS_NEWENV(func)) {
 			DUK_DDD(DUK_DDDPRINT("skip closing environments, envs not owned by this activation"));
 			goto skip_env_close;
 		}
+		/* func is NULL for lightfunc */
 
-		DUK_ASSERT(p->lex_env == p->var_env);
-		if (p->var_env != NULL) {
+		DUK_ASSERT(act->lex_env == act->var_env);
+		if (act->var_env != NULL) {
 			DUK_DDD(DUK_DDDPRINT("closing var_env record %p -> %!O",
-			                     (void *) p->var_env, (duk_heaphdr *) p->var_env));
-			duk_js_close_environment_record(thr, p->var_env, p->func, p->idx_bottom);
-			p = thr->callstack + idx;  /* avoid side effect issues */
+			                     (void *) act->var_env, (duk_heaphdr *) act->var_env));
+			duk_js_close_environment_record(thr, act->var_env, func, act->idx_bottom);
+			act = thr->callstack + idx;  /* avoid side effect issues */
 		}
 
 #if 0
-		if (p->lex_env != NULL) {
-			if (p->lex_env == p->var_env) {
+		if (act->lex_env != NULL) {
+			if (act->lex_env == act->var_env) {
 				/* common case, already closed, so skip */
 				DUK_DD(DUK_DDPRINT("lex_env and var_env are the same and lex_env "
 				                   "already closed -> skip closing lex_env"));
 				;
 			} else {
 				DUK_DD(DUK_DDPRINT("closing lex_env record %p -> %!O",
-				                   (void *) p->lex_env, (duk_heaphdr *) p->lex_env));
-				duk_js_close_environment_record(thr, p->lex_env, p->func, p->idx_bottom);
-				p = thr->callstack + idx;  /* avoid side effect issues */
+				                   (void *) act->lex_env, (duk_heaphdr *) act->lex_env));
+				duk_js_close_environment_record(thr, act->lex_env, DUK_ACT_GET_FUNC(act), act->idx_bottom);
+				act = thr->callstack + idx;  /* avoid side effect issues */
 			}
 		}
 #endif
 
-		DUK_ASSERT((p->lex_env == NULL) ||
-		           ((duk_hobject_find_existing_entry_tval_ptr(p->lex_env, DUK_HTHREAD_STRING_INT_CALLEE(thr)) == NULL) &&
-		            (duk_hobject_find_existing_entry_tval_ptr(p->lex_env, DUK_HTHREAD_STRING_INT_VARMAP(thr)) == NULL) &&
-		            (duk_hobject_find_existing_entry_tval_ptr(p->lex_env, DUK_HTHREAD_STRING_INT_THREAD(thr)) == NULL) &&
-		            (duk_hobject_find_existing_entry_tval_ptr(p->lex_env, DUK_HTHREAD_STRING_INT_REGBASE(thr)) == NULL)));
+		DUK_ASSERT((act->lex_env == NULL) ||
+		           ((duk_hobject_find_existing_entry_tval_ptr(thr->heap, act->lex_env, DUK_HTHREAD_STRING_INT_CALLEE(thr)) == NULL) &&
+		            (duk_hobject_find_existing_entry_tval_ptr(thr->heap, act->lex_env, DUK_HTHREAD_STRING_INT_VARMAP(thr)) == NULL) &&
+		            (duk_hobject_find_existing_entry_tval_ptr(thr->heap, act->lex_env, DUK_HTHREAD_STRING_INT_THREAD(thr)) == NULL) &&
+		            (duk_hobject_find_existing_entry_tval_ptr(thr->heap, act->lex_env, DUK_HTHREAD_STRING_INT_REGBASE(thr)) == NULL)));
 
-		DUK_ASSERT((p->var_env == NULL) ||
-		           ((duk_hobject_find_existing_entry_tval_ptr(p->var_env, DUK_HTHREAD_STRING_INT_CALLEE(thr)) == NULL) &&
-		            (duk_hobject_find_existing_entry_tval_ptr(p->var_env, DUK_HTHREAD_STRING_INT_VARMAP(thr)) == NULL) &&
-		            (duk_hobject_find_existing_entry_tval_ptr(p->var_env, DUK_HTHREAD_STRING_INT_THREAD(thr)) == NULL) &&
-		            (duk_hobject_find_existing_entry_tval_ptr(p->var_env, DUK_HTHREAD_STRING_INT_REGBASE(thr)) == NULL)));
+		DUK_ASSERT((act->var_env == NULL) ||
+		           ((duk_hobject_find_existing_entry_tval_ptr(thr->heap, act->var_env, DUK_HTHREAD_STRING_INT_CALLEE(thr)) == NULL) &&
+		            (duk_hobject_find_existing_entry_tval_ptr(thr->heap, act->var_env, DUK_HTHREAD_STRING_INT_VARMAP(thr)) == NULL) &&
+		            (duk_hobject_find_existing_entry_tval_ptr(thr->heap, act->var_env, DUK_HTHREAD_STRING_INT_THREAD(thr)) == NULL) &&
+		            (duk_hobject_find_existing_entry_tval_ptr(thr->heap, act->var_env, DUK_HTHREAD_STRING_INT_REGBASE(thr)) == NULL)));
 
 	 skip_env_close:
 
@@ -40473,7 +56480,7 @@ void duk_hthread_callstack_unwind(duk_hthread *thr, duk_size_t new_top) {
 		 *  Update preventcount
 		 */
 
-		if (p->flags & DUK_ACT_FLAG_PREVENT_YIELD) {
+		if (act->flags & DUK_ACT_FLAG_PREVENT_YIELD) {
 			DUK_ASSERT(thr->callstack_preventcount >= 1);
 			thr->callstack_preventcount--;
 		}
@@ -40488,34 +56495,34 @@ void duk_hthread_callstack_unwind(duk_hthread *thr, duk_size_t new_top) {
 		 */
 
 #ifdef DUK_USE_REFERENCE_COUNTING
-		tmp = p->var_env;
+		tmp = act->var_env;
 #endif
-		p->var_env = NULL;
+		act->var_env = NULL;
 #ifdef DUK_USE_REFERENCE_COUNTING
-		DUK_HOBJECT_DECREF(thr, tmp);
-		p = thr->callstack + idx;  /* avoid side effect issues */
+		DUK_HOBJECT_DECREF_ALLOWNULL(thr, tmp);
+		act = thr->callstack + idx;  /* avoid side effect issues */
 #endif
 
 #ifdef DUK_USE_REFERENCE_COUNTING
-		tmp = p->lex_env;
+		tmp = act->lex_env;
 #endif
-		p->lex_env = NULL;
+		act->lex_env = NULL;
 #ifdef DUK_USE_REFERENCE_COUNTING
-		DUK_HOBJECT_DECREF(thr, tmp);
-		p = thr->callstack + idx;  /* avoid side effect issues */
+		DUK_HOBJECT_DECREF_ALLOWNULL(thr, tmp);
+		act = thr->callstack + idx;  /* avoid side effect issues */
 #endif
 
 		/* Note: this may cause a corner case situation where a finalizer
 		 * may see a currently reachable activation whose 'func' is NULL.
 		 */
 #ifdef DUK_USE_REFERENCE_COUNTING
-		tmp = p->func;
+		tmp = DUK_ACT_GET_FUNC(act);
 #endif
-		p->func = NULL;
+		act->func = NULL;
 #ifdef DUK_USE_REFERENCE_COUNTING
-		DUK_HOBJECT_DECREF(thr, tmp);
-		p = thr->callstack + idx;  /* avoid side effect issues */
-		DUK_UNREF(p);
+		DUK_HOBJECT_DECREF_ALLOWNULL(thr, tmp);
+		act = thr->callstack + idx;  /* avoid side effect issues */
+		DUK_UNREF(act);
 #endif
 	}
 
@@ -40527,8 +56534,8 @@ void duk_hthread_callstack_unwind(duk_hthread *thr, duk_size_t new_top) {
 	 */
 #if 0
 	if (thr->callstack_top > 0) {
-		duk_activation *p = thr->callstack + thr->callstack_top - 1;
-		p->idx_retval = 0;
+		duk_activation *act = thr->callstack + thr->callstack_top - 1;
+		act->idx_retval = 0;
 	}
 #endif
 
@@ -40538,7 +56545,8 @@ void duk_hthread_callstack_unwind(duk_hthread *thr, duk_size_t new_top) {
 	 */
 }
 
-void duk_hthread_catchstack_grow(duk_hthread *thr) {
+DUK_INTERNAL void duk_hthread_catchstack_grow(duk_hthread *thr) {
+	duk_catcher *new_ptr;
 	duk_size_t old_size;
 	duk_size_t new_size;
 
@@ -40555,7 +56563,7 @@ void duk_hthread_catchstack_grow(duk_hthread *thr) {
 
 	/* this is a bit approximate (errors out before max is reached); this is OK */
 	if (new_size >= thr->catchstack_max) {
-		DUK_ERROR(thr, DUK_ERR_RANGE_ERROR, "catchstack limit");
+		DUK_ERROR(thr, DUK_ERR_RANGE_ERROR, DUK_STR_CATCHSTACK_LIMIT);
 	}
 
 	DUK_DD(DUK_DDPRINT("growing catchstack %ld -> %ld", (long) old_size, (long) new_size));
@@ -40565,13 +56573,19 @@ void duk_hthread_catchstack_grow(duk_hthread *thr) {
 	 *  pointer may be changed by mark-and-sweep.
 	 */
 
-	thr->catchstack = (duk_catcher *) DUK_REALLOC_INDIRECT_CHECKED(thr, duk_hthread_get_catchstack_ptr, (void *) thr, sizeof(duk_catcher) * new_size);
+	DUK_ASSERT(new_size > 0);
+	new_ptr = (duk_catcher *) DUK_REALLOC_INDIRECT(thr->heap, duk_hthread_get_catchstack_ptr, (void *) thr, sizeof(duk_catcher) * new_size);
+	if (!new_ptr) {
+		/* No need for a NULL/zero-size check because new_size > 0) */
+		DUK_ERROR(thr, DUK_ERR_ALLOC_ERROR, DUK_STR_REALLOC_FAILED);
+	}
+	thr->catchstack = new_ptr;
 	thr->catchstack_size = new_size;
 
 	/* note: any entries above the catchstack top are garbage and not zeroed */
 }
 
-void duk_hthread_catchstack_shrink_check(duk_hthread *thr) {
+DUK_INTERNAL void duk_hthread_catchstack_shrink_check(duk_hthread *thr) {
 	duk_size_t new_size;
 	duk_catcher *p;
 
@@ -40599,13 +56613,17 @@ void duk_hthread_catchstack_shrink_check(duk_hthread *thr) {
 		thr->catchstack = p;
 		thr->catchstack_size = new_size;
 	} else {
+		/* Because new_size != 0, if condition doesn't need to be
+		 * (p != NULL || new_size == 0).
+		 */
+		DUK_ASSERT(new_size != 0);
 		DUK_D(DUK_DPRINT("catchstack shrink failed, ignoring"));
 	}
 
 	/* note: any entries above the catchstack top are garbage and not zeroed */
 }
 
-void duk_hthread_catchstack_unwind(duk_hthread *thr, duk_size_t new_top) {
+DUK_INTERNAL void duk_hthread_catchstack_unwind(duk_hthread *thr, duk_size_t new_top) {
 	duk_size_t idx;
 
 	DUK_DDD(DUK_DDDPRINT("unwind catchstack top of thread %p from %ld to %ld",
@@ -40641,7 +56659,7 @@ void duk_hthread_catchstack_unwind(duk_hthread *thr, duk_size_t new_top) {
 			DUK_DDD(DUK_DDDPRINT("unwinding catchstack idx %ld, callstack idx %ld, callstack top %ld: lexical environment active",
 			                     (long) idx, (long) p->callstack_index, (long) thr->callstack_top));
 
-			/* FIXME: Here we have a nasty dependency: the need to manipulate
+			/* XXX: Here we have a nasty dependency: the need to manipulate
 			 * the callstack means that catchstack must always be unwound by
 			 * the caller before unwinding the callstack.  This should be fixed
 			 * later.
@@ -40660,7 +56678,7 @@ void duk_hthread_catchstack_unwind(duk_hthread *thr, duk_size_t new_top) {
 
 			env = act->lex_env;             /* current lex_env of the activation (created for catcher) */
 			DUK_ASSERT(env != NULL);        /* must be, since env was created when catcher was created */
-			act->lex_env = env->prototype;  /* prototype is lex_env before catcher created */
+			act->lex_env = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, env);  /* prototype is lex_env before catcher created */
 			DUK_HOBJECT_DECREF(thr, env);
 
 			/* There is no need to decref anything else than 'env': if 'env'
@@ -40677,29 +56695,122 @@ void duk_hthread_catchstack_unwind(duk_hthread *thr, duk_size_t new_top) {
 /*
  *  Call handling.
  *
- *  The main work horse functions are:
- *    - duk_handle_call(): call to a C/Ecmascript functions
- *    - duk_handle_safe_call(): make a protected C call within current activation
- *    - duk_handle_ecma_call_setup(): Ecmascript-to-Ecmascript calls, including
- *      tail calls and coroutine resume
+ *  Main functions are:
+ *
+ *    - duk_handle_call_unprotected(): unprotected call to Ecmascript or
+ *      Duktape/C function
+ *    - duk_handle_call_protected(): protected call to Ecmascript or
+ *      Duktape/C function
+ *    - duk_handle_safe_call(): make a protected C call within current
+ *      activation
+ *    - duk_handle_ecma_call_setup(): Ecmascript-to-Ecmascript calls
+ *      (not always possible), including tail calls and coroutine resume
+ *
+ *  See 'execution.rst'.
+ *
+ *  Note: setjmp() and local variables have a nasty interaction,
+ *  see execution.rst; non-volatile locals modified after setjmp()
+ *  call are not guaranteed to keep their value.
  */
 
 /* include removed: duk_internal.h */
 
 /*
+ *  Forward declarations.
+ */
+
+DUK_LOCAL void duk__handle_call_inner(duk_hthread *thr,
+                                      duk_idx_t num_stack_args,
+                                      duk_small_uint_t call_flags,
+                                      duk_idx_t idx_func);
+DUK_LOCAL void duk__handle_call_error(duk_hthread *thr,
+                                      duk_size_t entry_valstack_bottom_index,
+                                      duk_size_t entry_valstack_end,
+                                      duk_size_t entry_catchstack_top,
+                                      duk_size_t entry_callstack_top,
+                                      duk_int_t entry_call_recursion_depth,
+                                      duk_hthread *entry_curr_thread,
+                                      duk_uint_fast8_t entry_thread_state,
+                                      duk_instr_t **entry_ptr_curr_pc,
+                                      duk_idx_t idx_func
+#if !defined(DUK_USE_CPP_EXCEPTIONS)
+                                      , duk_jmpbuf *old_jmpbuf_ptr
+#endif
+                                      );
+DUK_LOCAL void duk__handle_safe_call_inner(duk_hthread *thr,
+                                           duk_safe_call_function func,
+                                           duk_idx_t idx_retbase,
+                                           duk_idx_t num_stack_rets,
+                                           duk_size_t entry_valstack_bottom_index,
+                                           duk_size_t entry_callstack_top,
+                                           duk_size_t entry_catchstack_top);
+DUK_LOCAL void duk__handle_safe_call_error(duk_hthread *thr,
+                                           duk_idx_t idx_retbase,
+                                           duk_idx_t num_stack_rets,
+                                           duk_size_t entry_valstack_bottom_index,
+                                           duk_size_t entry_callstack_top,
+                                           duk_size_t entry_catchstack_top
+#if !defined(DUK_USE_CPP_EXCEPTIONS)
+                                           , duk_jmpbuf *old_jmpbuf_ptr
+#endif
+                                           );
+DUK_LOCAL void duk__handle_safe_call_shared(duk_hthread *thr,
+                                            duk_idx_t idx_retbase,
+                                            duk_idx_t num_stack_rets,
+                                            duk_int_t entry_call_recursion_depth,
+                                            duk_hthread *entry_curr_thread,
+                                            duk_uint_fast8_t entry_thread_state,
+                                            duk_instr_t **entry_ptr_curr_pc);
+
+/*
+ *  Interrupt counter fixup (for development only).
+ */
+
+#if defined(DUK_USE_INTERRUPT_COUNTER) && defined(DUK_USE_DEBUG)
+DUK_LOCAL void duk__interrupt_fixup(duk_hthread *thr, duk_hthread *entry_curr_thread) {
+	/* Currently the bytecode executor and executor interrupt
+	 * instruction counts are off because we don't execute the
+	 * interrupt handler when we're about to exit from the initial
+	 * user call into Duktape.
+	 *
+	 * If we were to execute the interrupt handler here, the counts
+	 * would match.  You can enable this block manually to check
+	 * that this is the case.
+	 */
+
+	DUK_ASSERT(thr != NULL);
+	DUK_ASSERT(thr->heap != NULL);
+
+#if defined(DUK_USE_INTERRUPT_DEBUG_FIXUP)
+	if (entry_curr_thread == NULL) {
+		thr->interrupt_init = thr->interrupt_init - thr->interrupt_counter;
+		thr->heap->inst_count_interrupt += thr->interrupt_init;
+		DUK_DD(DUK_DDPRINT("debug test: updated interrupt count on exit to "
+		                   "user code, instruction counts: executor=%ld, interrupt=%ld",
+		                   (long) thr->heap->inst_count_exec, (long) thr->heap->inst_count_interrupt));
+		DUK_ASSERT(thr->heap->inst_count_exec == thr->heap->inst_count_interrupt);
+	}
+#else
+	DUK_UNREF(thr);
+	DUK_UNREF(entry_curr_thread);
+#endif
+}
+#endif
+
+/*
  *  Arguments object creation.
  *
- *  Creating arguments objects is a bit finicky, see E5 Section 10.6 for the
- *  specific requirements.  Much of the arguments object exotic behavior is
- *  implemented in duk_hobject_props.c, and is enabled by the object flag
- *  DUK_HOBJECT_FLAG_EXOTIC_ARGUMENTS.
+ *  Creating arguments objects involves many small details, see E5 Section
+ *  10.6 for the specific requirements.  Much of the arguments object exotic
+ *  behavior is implemented in duk_hobject_props.c, and is enabled by the
+ *  object flag DUK_HOBJECT_FLAG_EXOTIC_ARGUMENTS.
  */
 
-static void duk__create_arguments_object(duk_hthread *thr,
-                                         duk_hobject *func,
-                                         duk_hobject *varenv,
-                                         duk_idx_t idx_argbase,        /* idx of first argument on stack */
-                                         duk_idx_t num_stack_args) {   /* num args starting from idx_argbase */
+DUK_LOCAL void duk__create_arguments_object(duk_hthread *thr,
+                                            duk_hobject *func,
+                                            duk_hobject *varenv,
+                                            duk_idx_t idx_argbase,        /* idx of first argument on stack */
+                                            duk_idx_t num_stack_args) {   /* num args starting from idx_argbase */
 	duk_context *ctx = (duk_context *) thr;
 	duk_hobject *arg;          /* 'arguments' */
 	duk_hobject *formals;      /* formals for 'func' (may be NULL if func is a C function) */
@@ -40778,7 +56889,7 @@ static void duk__create_arguments_object(duk_hthread *thr,
 	                                       -1);  /* no prototype */
 	DUK_ASSERT(i_mappednames >= 0);
 
-	/* [... formals arguments map mappedNames] */
+	/* [ ... formals arguments map mappedNames ] */
 
 	DUK_DDD(DUK_DDDPRINT("created arguments related objects: "
 	                     "arguments at index %ld -> %!O "
@@ -40793,7 +56904,7 @@ static void duk__create_arguments_object(duk_hthread *thr,
 	 */
 
 	duk_push_int(ctx, num_stack_args);
-	duk_def_prop_stridx(ctx, i_arg, DUK_STRIDX_LENGTH, DUK_PROPDESC_FLAGS_WC);
+	duk_xdef_prop_stridx(ctx, i_arg, DUK_STRIDX_LENGTH, DUK_PROPDESC_FLAGS_WC);
 
 	/*
 	 *  Init argument related properties
@@ -40807,7 +56918,7 @@ static void duk__create_arguments_object(duk_hthread *thr,
 
 		DUK_DDD(DUK_DDDPRINT("define arguments[%ld]=arg", (long) idx));
 		duk_dup(ctx, i_argbase + idx);
-		duk_def_prop_index_wec(ctx, i_arg, (duk_uarridx_t) idx);
+		duk_xdef_prop_index_wec(ctx, i_arg, (duk_uarridx_t) idx);
 		DUK_DDD(DUK_DDDPRINT("defined arguments[%ld]=arg", (long) idx));
 
 		/* step 11.c is relevant only if non-strict (checked in 11.c.ii) */
@@ -40820,14 +56931,14 @@ static void duk__create_arguments_object(duk_hthread *thr,
 			duk_get_prop_index(ctx, i_formals, idx);
 			DUK_ASSERT(duk_is_string(ctx, -1));
 
-			duk_dup(ctx, -1);  /* [... name name] */
+			duk_dup(ctx, -1);  /* [ ... name name ] */
 
 			if (!duk_has_prop(ctx, i_mappednames)) {
 				/* steps 11.c.ii.1 - 11.c.ii.4, but our internal book-keeping
 				 * differs from the reference model
 				 */
 
-				/* [... name] */
+				/* [ ... name ] */
 
 				need_map = 1;
 
@@ -40837,18 +56948,18 @@ static void duk__create_arguments_object(duk_hthread *thr,
 				duk_dup(ctx, -1);                      /* name */
 				duk_push_uint(ctx, (duk_uint_t) idx);  /* index */
 				duk_to_string(ctx, -1);
-				duk_def_prop_wec(ctx, i_mappednames);  /* out of spec, must be configurable */
+				duk_xdef_prop_wec(ctx, i_mappednames);  /* out of spec, must be configurable */
 
 				DUK_DDD(DUK_DDDPRINT("set map[%ld]=%s",
 				                     (long) idx,
 				                     duk_get_string(ctx, -1)));
 				duk_dup(ctx, -1);         /* name */
-				duk_def_prop_index_wec(ctx, i_map, (duk_uarridx_t) idx);  /* out of spec, must be configurable */
+				duk_xdef_prop_index_wec(ctx, i_map, (duk_uarridx_t) idx);  /* out of spec, must be configurable */
 			} else {
 				/* duk_has_prop() popped the second 'name' */
 			}
 
-			/* [... name] */
+			/* [ ... name ] */
 			duk_pop(ctx);  /* pop 'name' */
 		}
 
@@ -40865,7 +56976,7 @@ static void duk__create_arguments_object(duk_hthread *thr,
 		DUK_ASSERT(!DUK_HOBJECT_HAS_STRICT(func));
 
 		duk_dup(ctx, i_map);
-		duk_def_prop_stridx(ctx, i_arg, DUK_STRIDX_INT_MAP, DUK_PROPDESC_FLAGS_NONE);  /* out of spec, don't care */
+		duk_xdef_prop_stridx(ctx, i_arg, DUK_STRIDX_INT_MAP, DUK_PROPDESC_FLAGS_NONE);  /* out of spec, don't care */
 
 		/* The variable environment for magic variable bindings needs to be
 		 * given by the caller and recorded in the arguments object.
@@ -40877,46 +56988,44 @@ static void duk__create_arguments_object(duk_hthread *thr,
 		 */
 
 		duk_push_hobject(ctx, varenv);
-		duk_def_prop_stridx(ctx, i_arg, DUK_STRIDX_INT_VARENV, DUK_PROPDESC_FLAGS_NONE);  /* out of spec, don't care */
+		duk_xdef_prop_stridx(ctx, i_arg, DUK_STRIDX_INT_VARENV, DUK_PROPDESC_FLAGS_NONE);  /* out of spec, don't care */
 	}
 
 	/* steps 13-14 */
 	if (DUK_HOBJECT_HAS_STRICT(func)) {
-		/*
-		 *  Note: callee/caller are throwers and are not deletable etc.
-		 *  They could be implemented as virtual properties, but currently
-		 *  there is no support for virtual properties which are accessors
-		 *  (only plain virtual properties).  This would not be difficult
-		 *  to change in duk_hobject_props, but we can make the throwers
-		 *  normal, concrete properties just as easily.
+		/* Callee/caller are throwers and are not deletable etc.  They
+		 * could be implemented as virtual properties, but currently
+		 * there is no support for virtual properties which are accessors
+		 * (only plain virtual properties).  This would not be difficult
+		 * to change in duk_hobject_props, but we can make the throwers
+		 * normal, concrete properties just as easily.
 		 *
-		 *  Note that the specification requires that the *same* thrower
-		 *  built-in object is used here!  See E5 Section 10.6 main
-		 *  algoritm, step 14, and Section 13.2.3 which describes the
-		 *  thrower.  See test case test-arguments-throwers.js.
+		 * Note that the specification requires that the *same* thrower
+		 * built-in object is used here!  See E5 Section 10.6 main
+		 * algoritm, step 14, and Section 13.2.3 which describes the
+		 * thrower.  See test case test-arguments-throwers.js.
 		 */
 
 		DUK_DDD(DUK_DDDPRINT("strict function, setting caller/callee to throwers"));
 
-		duk_def_prop_stridx_thrower(ctx, i_arg, DUK_STRIDX_CALLER, DUK_PROPDESC_FLAGS_NONE);
-		duk_def_prop_stridx_thrower(ctx, i_arg, DUK_STRIDX_CALLEE, DUK_PROPDESC_FLAGS_NONE);
+		duk_xdef_prop_stridx_thrower(ctx, i_arg, DUK_STRIDX_CALLER, DUK_PROPDESC_FLAGS_NONE);
+		duk_xdef_prop_stridx_thrower(ctx, i_arg, DUK_STRIDX_CALLEE, DUK_PROPDESC_FLAGS_NONE);
 	} else {
 		DUK_DDD(DUK_DDDPRINT("non-strict function, setting callee to actual value"));
 		duk_push_hobject(ctx, func);
-		duk_def_prop_stridx(ctx, i_arg, DUK_STRIDX_CALLEE, DUK_PROPDESC_FLAGS_WC);
+		duk_xdef_prop_stridx(ctx, i_arg, DUK_STRIDX_CALLEE, DUK_PROPDESC_FLAGS_WC);
 	}
 
 	/* set exotic behavior only after we're done */
 	if (need_map) {
-		/*
-		 *  Note: exotic behaviors are only enabled for arguments
-		 *  objects which have a parameter map (see E5 Section 10.6
-		 *  main algorithm, step 12).
+		/* Exotic behaviors are only enabled for arguments objects
+		 * which have a parameter map (see E5 Section 10.6 main
+		 * algorithm, step 12).
 		 *
-		 *  In particular, a non-strict arguments object with no
-		 *  mapped formals does *NOT* get exotic behavior, even
-		 *  for e.g. "caller" property.  This seems counterintuitive
-		 *  but seems to be the case.
+		 * In particular, a non-strict arguments object with no
+		 * mapped formals does *NOT* get exotic behavior, even
+		 * for e.g. "caller" property.  This seems counterintuitive
+		 * but seems to be the case.
 		 */
 
 		/* cannot be strict (never mapped variables) */
@@ -40928,7 +57037,6 @@ static void duk__create_arguments_object(duk_hthread *thr,
 		DUK_DDD(DUK_DDDPRINT("not enabling exotic behavior for arguments object"));
 	}
 
-	/* nice log */
 	DUK_DDD(DUK_DDDPRINT("final arguments related objects: "
 	                     "arguments at index %ld -> %!O "
 	                     "map at index %ld -> %!O "
@@ -40937,19 +57045,22 @@ static void duk__create_arguments_object(duk_hthread *thr,
 	                     (long) i_map, (duk_heaphdr *) duk_get_hobject(ctx, i_map),
 	                     (long) i_mappednames, (duk_heaphdr *) duk_get_hobject(ctx, i_mappednames)));
 
-	/* [args(n) [crud] formals arguments map mappednames] -> [args [crud] arguments] */
+	/* [ args(n) [crud] formals arguments map mappednames ] */
+
 	duk_pop_2(ctx);
 	duk_remove(ctx, -2);
+
+	/* [ args [crud] arguments ] */
 }
 
 /* Helper for creating the arguments object and adding it to the env record
  * on top of the value stack.  This helper has a very strict dependency on
  * the shape of the input stack.
  */
-static void duk__handle_createargs_for_call(duk_hthread *thr,
-                                            duk_hobject *func,
-                                            duk_hobject *env,
-                                            duk_idx_t num_stack_args) {
+DUK_LOCAL void duk__handle_createargs_for_call(duk_hthread *thr,
+                                               duk_hobject *func,
+                                               duk_hobject *env,
+                                               duk_idx_t num_stack_args) {
 	duk_context *ctx = (duk_context *) thr;
 
 	DUK_DDD(DUK_DDDPRINT("creating arguments object for function call"));
@@ -40960,7 +57071,7 @@ static void duk__handle_createargs_for_call(duk_hthread *thr,
 	DUK_ASSERT(DUK_HOBJECT_HAS_CREATEARGS(func));
 	DUK_ASSERT(duk_get_top(ctx) >= num_stack_args + 1);
 
-	/* [... arg1 ... argN envobj] */
+	/* [ ... arg1 ... argN envobj ] */
 
 	duk__create_arguments_object(thr,
 	                             func,
@@ -40968,14 +57079,14 @@ static void duk__handle_createargs_for_call(duk_hthread *thr,
 	                             duk_get_top(ctx) - num_stack_args - 1,    /* idx_argbase */
 	                             num_stack_args);
 
-	/* [... arg1 ... argN envobj argobj] */
+	/* [ ... arg1 ... argN envobj argobj ] */
 
-	duk_def_prop_stridx(ctx,
-	                    -2,
-	                    DUK_STRIDX_LC_ARGUMENTS,
-	                    DUK_HOBJECT_HAS_STRICT(func) ? DUK_PROPDESC_FLAGS_E :   /* strict: non-deletable, non-writable */
-	                                                   DUK_PROPDESC_FLAGS_WE);  /* non-strict: non-deletable, writable */
-	/* [... arg1 ... argN envobj] */
+	duk_xdef_prop_stridx(ctx,
+	                     -2,
+	                     DUK_STRIDX_LC_ARGUMENTS,
+	                     DUK_HOBJECT_HAS_STRICT(func) ? DUK_PROPDESC_FLAGS_E :   /* strict: non-deletable, non-writable */
+	                                                    DUK_PROPDESC_FLAGS_WE);  /* non-strict: non-deletable, writable */
+	/* [ ... arg1 ... argN envobj ] */
 }
 
 /*
@@ -40992,47 +57103,61 @@ static void duk__handle_createargs_for_call(duk_hthread *thr,
  *  function.  This would make call time handling much easier.
  */
 
-static void duk__handle_bound_chain_for_call(duk_hthread *thr,
-                                             duk_idx_t idx_func,
-                                             duk_idx_t *p_num_stack_args,   /* may be changed by call */
-                                             duk_hobject **p_func,    /* changed by call */
-                                             duk_bool_t is_constructor_call) {
+DUK_LOCAL void duk__handle_bound_chain_for_call(duk_hthread *thr,
+                                                duk_idx_t idx_func,
+                                                duk_idx_t *p_num_stack_args,   /* may be changed by call */
+                                                duk_bool_t is_constructor_call) {
 	duk_context *ctx = (duk_context *) thr;
 	duk_idx_t num_stack_args;
+	duk_tval *tv_func;
 	duk_hobject *func;
 	duk_uint_t sanity;
 
 	DUK_ASSERT(thr != NULL);
 	DUK_ASSERT(p_num_stack_args != NULL);
-	DUK_ASSERT(p_func != NULL);
-	DUK_ASSERT(*p_func != NULL);
-	DUK_ASSERT(DUK_HOBJECT_HAS_BOUND(*p_func));
+
+	/* On entry, item at idx_func is a bound, non-lightweight function,
+	 * but we don't rely on that below.
+	 */
 
 	num_stack_args = *p_num_stack_args;
-	func = *p_func;
 
 	sanity = DUK_HOBJECT_BOUND_CHAIN_SANITY;
-	do {	
+	do {
 		duk_idx_t i, len;
 
-		if (!DUK_HOBJECT_HAS_BOUND(func)) {
+		tv_func = duk_require_tval(ctx, idx_func);
+		DUK_ASSERT(tv_func != NULL);
+
+		if (DUK_TVAL_IS_LIGHTFUNC(tv_func)) {
+			/* Lightweight function: never bound, so terminate. */
 			break;
+		} else if (DUK_TVAL_IS_OBJECT(tv_func)) {
+			func = DUK_TVAL_GET_OBJECT(tv_func);
+			if (!DUK_HOBJECT_HAS_BOUND(func)) {
+				/* Normal non-bound function. */
+				break;
+			}
+		} else {
+			/* Function.prototype.bind() should never let this happen,
+			 * ugly error message is enough.
+			 */
+			DUK_ERROR(thr, DUK_ERR_INTERNAL_ERROR, DUK_STR_INTERNAL_ERROR);
 		}
-
-		DUK_DDD(DUK_DDDPRINT("bound function encountered, ptr=%p", (void *) func));
+		DUK_ASSERT(DUK_TVAL_GET_OBJECT(tv_func) != NULL);
 
 		/* XXX: this could be more compact by accessing the internal properties
 		 * directly as own properties (they cannot be inherited, and are not
 		 * externally visible).
 		 */
 
-		DUK_DDD(DUK_DDDPRINT("bound function encountered, ptr=%p, num_stack_args=%ld",
-		                     (void *) func, (long) num_stack_args));
+		DUK_DDD(DUK_DDDPRINT("bound function encountered, ptr=%p, num_stack_args=%ld: %!T",
+		                     (void *) DUK_TVAL_GET_OBJECT(tv_func), (long) num_stack_args, tv_func));
 
 		/* [ ... func this arg1 ... argN ] */
 
 		if (is_constructor_call) {
-			/* See: ecmascript-testcases/test-spec-bound-constructor.js */
+			/* See: tests/ecmascript/test-spec-bound-constructor.js */
 			DUK_DDD(DUK_DDDPRINT("constructor call: don't update this binding"));
 		} else {
 			duk_get_prop_stridx(ctx, idx_func, DUK_STRIDX_INT_THIS);
@@ -41042,8 +57167,8 @@ static void duk__handle_bound_chain_for_call(duk_hthread *thr,
 		/* [ ... func this arg1 ... argN ] */
 
 		/* XXX: duk_get_length? */
-		duk_get_prop_stridx(ctx, idx_func, DUK_STRIDX_INT_ARGS);  /* -> [ ... func this arg1 ... argN _args ] */
-		duk_get_prop_stridx(ctx, -1, DUK_STRIDX_LENGTH);          /* -> [ ... func this arg1 ... argN _args length ] */
+		duk_get_prop_stridx(ctx, idx_func, DUK_STRIDX_INT_ARGS);  /* -> [ ... func this arg1 ... argN _Args ] */
+		duk_get_prop_stridx(ctx, -1, DUK_STRIDX_LENGTH);          /* -> [ ... func this arg1 ... argN _Args length ] */
 		len = (duk_idx_t) duk_require_int(ctx, -1);
 		duk_pop(ctx);
 		for (i = 0; i < len; i++) {
@@ -41052,7 +57177,7 @@ static void duk__handle_bound_chain_for_call(duk_hthread *thr,
 			 * part, etc).
 			 */
 
-			/* [ ... func this <some bound args> arg1 ... argN _args ] */
+			/* [ ... func this <some bound args> arg1 ... argN _Args ] */
 			duk_get_prop_index(ctx, -1, i);
 			duk_insert(ctx, idx_func + 2 + i);  /* idx_args = idx_func + 2 */
 		}
@@ -41062,25 +57187,32 @@ static void duk__handle_bound_chain_for_call(duk_hthread *thr,
 		/* [ ... func this <bound args> arg1 ... argN ] */
 
 		duk_get_prop_stridx(ctx, idx_func, DUK_STRIDX_INT_TARGET);
-		duk_replace(ctx, idx_func);  /* replace also in stack; not strictly necessary */
-		func = duk_require_hobject(ctx, idx_func);
+		duk_replace(ctx, idx_func);  /* replace in stack */
 
-		DUK_DDD(DUK_DDDPRINT("bound function handled, num_stack_args=%ld, idx_func=%ld",
-		                     (long) num_stack_args, (long) idx_func));
+		DUK_DDD(DUK_DDDPRINT("bound function handled, num_stack_args=%ld, idx_func=%ld, curr func=%!T",
+		                     (long) num_stack_args, (long) idx_func, duk_get_tval(ctx, idx_func)));
 	} while (--sanity > 0);
 
 	if (sanity == 0) {
 		DUK_ERROR(thr, DUK_ERR_INTERNAL_ERROR, DUK_STR_BOUND_CHAIN_LIMIT);
 	}
 
-	DUK_DDD(DUK_DDDPRINT("final non-bound function is: %p", (void *) func));
+	DUK_DDD(DUK_DDDPRINT("final non-bound function is: %!T", duk_get_tval(ctx, idx_func)));
 
-	DUK_ASSERT(!DUK_HOBJECT_HAS_BOUND(func));
-	DUK_ASSERT(DUK_HOBJECT_HAS_COMPILEDFUNCTION(func) || DUK_HOBJECT_HAS_NATIVEFUNCTION(func));
+#if defined(DUK_USE_ASSERTIONS)
+	tv_func = duk_require_tval(ctx, idx_func);
+	DUK_ASSERT(DUK_TVAL_IS_LIGHTFUNC(tv_func) || DUK_TVAL_IS_OBJECT(tv_func));
+	if (DUK_TVAL_IS_OBJECT(tv_func)) {
+		func = DUK_TVAL_GET_OBJECT(tv_func);
+		DUK_ASSERT(func != NULL);
+		DUK_ASSERT(!DUK_HOBJECT_HAS_BOUND(func));
+		DUK_ASSERT(DUK_HOBJECT_HAS_COMPILEDFUNCTION(func) ||
+		           DUK_HOBJECT_HAS_NATIVEFUNCTION(func));
+	}
+#endif
 
 	/* write back */
 	*p_num_stack_args = num_stack_args;
-	*p_func = func;
 }
 
 /*
@@ -41088,9 +57220,9 @@ static void duk__handle_bound_chain_for_call(duk_hthread *thr,
  *  assuming it does NOT have the DUK_HOBJECT_FLAG_NEWENV flag.
  */
 
-static void duk__handle_oldenv_for_call(duk_hthread *thr,
-                                        duk_hobject *func,
-                                        duk_activation *act) {
+DUK_LOCAL void duk__handle_oldenv_for_call(duk_hthread *thr,
+                                           duk_hobject *func,
+                                           duk_activation *act) {
 	duk_tval *tv;
 
 	DUK_ASSERT(thr != NULL);
@@ -41099,13 +57231,13 @@ static void duk__handle_oldenv_for_call(duk_hthread *thr,
 	DUK_ASSERT(!DUK_HOBJECT_HAS_NEWENV(func));
 	DUK_ASSERT(!DUK_HOBJECT_HAS_CREATEARGS(func));
 
-	tv = duk_hobject_find_existing_entry_tval_ptr(func, DUK_HTHREAD_STRING_INT_LEXENV(thr));
+	tv = duk_hobject_find_existing_entry_tval_ptr(thr->heap, func, DUK_HTHREAD_STRING_INT_LEXENV(thr));
 	if (tv) {
 		DUK_ASSERT(DUK_TVAL_IS_OBJECT(tv));
 		DUK_ASSERT(DUK_HOBJECT_IS_ENV(DUK_TVAL_GET_OBJECT(tv)));
 		act->lex_env = DUK_TVAL_GET_OBJECT(tv);
 
-		tv = duk_hobject_find_existing_entry_tval_ptr(func, DUK_HTHREAD_STRING_INT_VARENV(thr));
+		tv = duk_hobject_find_existing_entry_tval_ptr(thr->heap, func, DUK_HTHREAD_STRING_INT_VARENV(thr));
 		if (tv) {
 			DUK_ASSERT(DUK_TVAL_IS_OBJECT(tv));
 			DUK_ASSERT(DUK_HOBJECT_IS_ENV(DUK_TVAL_GET_OBJECT(tv)));
@@ -41118,16 +57250,16 @@ static void duk__handle_oldenv_for_call(duk_hthread *thr,
 		act->var_env = act->lex_env;
 	}
 
-	DUK_HOBJECT_INCREF(thr, act->lex_env);
-	DUK_HOBJECT_INCREF(thr, act->var_env);
+	DUK_HOBJECT_INCREF_ALLOWNULL(thr, act->lex_env);
+	DUK_HOBJECT_INCREF_ALLOWNULL(thr, act->var_env);
 }
 
 /*
  *  Helper for updating callee 'caller' property.
  */
 
-#ifdef DUK_USE_NONSTD_FUNC_CALLER_PROPERTY
-static void duk__update_func_caller_prop(duk_hthread *thr, duk_hobject *func) {
+#if defined(DUK_USE_NONSTD_FUNC_CALLER_PROPERTY)
+DUK_LOCAL void duk__update_func_caller_prop(duk_hthread *thr, duk_hobject *func) {
 	duk_tval *tv_caller;
 	duk_hobject *h_tmp;
 	duk_activation *act_callee;
@@ -41146,8 +57278,10 @@ static void duk__update_func_caller_prop(duk_hthread *thr, duk_hobject *func) {
 	act_callee = thr->callstack + thr->callstack_top - 1;
 	act_caller = (thr->callstack_top >= 2 ? act_callee - 1 : NULL);
 
+	/* XXX: check .caller writability? */
+
 	/* Backup 'caller' property and update its value. */
-	tv_caller = duk_hobject_find_existing_entry_tval_ptr(func, DUK_HTHREAD_STRING_CALLER(thr));
+	tv_caller = duk_hobject_find_existing_entry_tval_ptr(thr->heap, func, DUK_HTHREAD_STRING_CALLER(thr));
 	if (tv_caller) {
 		/* If caller is global/eval code, 'caller' should be set to
 		 * 'null'.
@@ -41228,154 +57362,375 @@ static void duk__update_func_caller_prop(duk_hthread *thr, duk_hobject *func) {
  *  side effects, because ToObject() may be called.
  */
 
-static void duk__coerce_effective_this_binding(duk_hthread *thr,
-                                               duk_hobject *func,
-                                               duk_idx_t idx_this) {
+DUK_LOCAL void duk__coerce_effective_this_binding(duk_hthread *thr,
+                                                  duk_hobject *func,
+                                                  duk_idx_t idx_this) {
 	duk_context *ctx = (duk_context *) thr;
+	duk_tval *tv_this;
+	duk_hobject *obj_global;
 
-	if (DUK_HOBJECT_HAS_STRICT(func)) {
+	if (func == NULL || DUK_HOBJECT_HAS_STRICT(func)) {
+		/* Lightfuncs are always considered strict. */
 		DUK_DDD(DUK_DDDPRINT("this binding: strict -> use directly"));
-	} else {
-		duk_tval *tv_this = duk_require_tval(ctx, idx_this);
-		duk_hobject *obj_global;
+		return;
+	}
 
-		if (DUK_TVAL_IS_OBJECT(tv_this)) {
-			DUK_DDD(DUK_DDDPRINT("this binding: non-strict, object -> use directly"));
-		} else if (DUK_TVAL_IS_UNDEFINED(tv_this) || DUK_TVAL_IS_NULL(tv_this)) {
-			DUK_DDD(DUK_DDDPRINT("this binding: non-strict, undefined/null -> use global object"));
-			obj_global = thr->builtins[DUK_BIDX_GLOBAL];
-			if (obj_global) {
-				duk_push_hobject(ctx, obj_global);
-			} else {
-				/*
-				 *  This may only happen if built-ins are being "torn down".
-				 *  This behavior is out of specification scope.
+	/* XXX: byte offset */
+	tv_this = thr->valstack_bottom + idx_this;
+	switch (DUK_TVAL_GET_TAG(tv_this)) {
+	case DUK_TAG_OBJECT:
+	case DUK_TAG_LIGHTFUNC:  /* lightfuncs are treated like objects and not coerced */
+		DUK_DDD(DUK_DDDPRINT("this binding: non-strict, object -> use directly"));
+		break;
+	case DUK_TAG_UNDEFINED:
+	case DUK_TAG_NULL:
+		DUK_DDD(DUK_DDDPRINT("this binding: non-strict, undefined/null -> use global object"));
+		obj_global = thr->builtins[DUK_BIDX_GLOBAL];
+		/* XXX: avoid this check somehow */
+		if (DUK_LIKELY(obj_global != NULL)) {
+			DUK_ASSERT(!DUK_TVAL_IS_HEAP_ALLOCATED(tv_this));  /* no need to decref previous value */
+			DUK_TVAL_SET_OBJECT(tv_this, obj_global);
+			DUK_HOBJECT_INCREF(thr, obj_global);
+		} else {
+			/* This may only happen if built-ins are being "torn down".
+			 * This behavior is out of specification scope.
+			 */
+			DUK_D(DUK_DPRINT("this binding: wanted to use global object, but it is NULL -> using undefined instead"));
+			DUK_ASSERT(!DUK_TVAL_IS_HEAP_ALLOCATED(tv_this));  /* no need to decref previous value */
+			DUK_TVAL_SET_UNDEFINED(tv_this);  /* nothing to incref */
+		}
+		break;
+	default:
+		DUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv_this));
+		DUK_DDD(DUK_DDDPRINT("this binding: non-strict, not object/undefined/null -> use ToObject(value)"));
+		duk_to_object(ctx, idx_this);  /* may have side effects */
+		break;
+	}
+}
+
+/*
+ *  Shared helper for non-bound func lookup.
+ *
+ *  Returns duk_hobject * to the final non-bound function (NULL for lightfunc).
+ */
+
+DUK_LOCAL duk_hobject *duk__nonbound_func_lookup(duk_context *ctx,
+                                                 duk_idx_t idx_func,
+                                                 duk_idx_t *out_num_stack_args,
+                                                 duk_tval **out_tv_func,
+                                                 duk_small_uint_t call_flags) {
+	duk_hthread *thr = (duk_hthread *) ctx;
+	duk_tval *tv_func;
+	duk_hobject *func;
+
+	for (;;) {
+		/* Use loop to minimize code size of relookup after bound function case */
+		tv_func = duk_get_tval(ctx, idx_func);
+		DUK_ASSERT(tv_func != NULL);
+
+		if (DUK_TVAL_IS_OBJECT(tv_func)) {
+			func = DUK_TVAL_GET_OBJECT(tv_func);
+			if (!DUK_HOBJECT_IS_CALLABLE(func)) {
+				goto not_callable_error;
+			}
+			if (DUK_HOBJECT_HAS_BOUND(func)) {
+				duk__handle_bound_chain_for_call(thr, idx_func, out_num_stack_args, call_flags & DUK_CALL_FLAG_CONSTRUCTOR_CALL);
+
+				/* The final object may be a normal function or a lightfunc.
+				 * We need to re-lookup tv_func because it may have changed
+				 * (also value stack may have been resized).  Loop again to
+				 * do that; we're guaranteed not to come here again.
 				 */
-				DUK_D(DUK_DPRINT("this binding: wanted to use global object, but it is NULL -> using undefined instead"));
-				duk_push_undefined(ctx);
+				DUK_ASSERT(DUK_TVAL_IS_OBJECT(duk_require_tval(ctx, idx_func)) ||
+				           DUK_TVAL_IS_LIGHTFUNC(duk_require_tval(ctx, idx_func)));
+				continue;
 			}
-			duk_replace(ctx, idx_this);
+		} else if (DUK_TVAL_IS_LIGHTFUNC(tv_func)) {
+			func = NULL;
 		} else {
-			DUK_DDD(DUK_DDDPRINT("this binding: non-strict, not object/undefined/null -> use ToObject(value)"));
-			duk_to_object(ctx, idx_this);  /* may have side effects */
+			goto not_callable_error;
 		}
+		break;
 	}
+
+	DUK_ASSERT((DUK_TVAL_IS_OBJECT(tv_func) && DUK_HOBJECT_IS_CALLABLE(DUK_TVAL_GET_OBJECT(tv_func))) ||
+	           DUK_TVAL_IS_LIGHTFUNC(tv_func));
+	DUK_ASSERT(func == NULL || !DUK_HOBJECT_HAS_BOUND(func));
+	DUK_ASSERT(func == NULL || (DUK_HOBJECT_IS_COMPILEDFUNCTION(func) ||
+	                            DUK_HOBJECT_IS_NATIVEFUNCTION(func)));
+
+	*out_tv_func = tv_func;
+	return func;
+
+ not_callable_error:
+	DUK_ASSERT(tv_func != NULL);
+#if defined(DUK_USE_PARANOID_ERRORS)
+	DUK_ERROR(thr, DUK_ERR_TYPE_ERROR, DUK_STR_NOT_CALLABLE);
+#else
+	DUK_ERROR(thr, DUK_ERR_TYPE_ERROR, "%s not callable", duk_push_string_tval_readable(ctx, tv_func));
+#endif
+	DUK_UNREACHABLE();
+	return NULL;  /* never executed */
 }
 
 /*
- *  Helper for making various kinds of calls.
+ *  Value stack resize and stack top adjustment helper.
  *
- *  Call flags:
+ *  XXX: This should all be merged to duk_valstack_resize_raw().
+ */
+
+DUK_LOCAL void duk__adjust_valstack_and_top(duk_hthread *thr,
+                                            duk_idx_t num_stack_args,
+                                            duk_idx_t idx_args,
+                                            duk_idx_t nregs,
+                                            duk_idx_t nargs,
+                                            duk_hobject *func) {
+	duk_context *ctx = (duk_context *) thr;
+	duk_size_t vs_min_size;
+	duk_bool_t adjusted_top = 0;
+
+	vs_min_size = (thr->valstack_bottom - thr->valstack) +  /* bottom of current func */
+	              idx_args;                                 /* bottom of new func */
+
+	if (nregs >= 0) {
+		DUK_ASSERT(nargs >= 0);
+		DUK_ASSERT(nregs >= nargs);
+		vs_min_size += nregs;
+	} else {
+		/* 'func' wants stack "as is" */
+		vs_min_size += num_stack_args;  /* num entries of new func at entry */
+	}
+	if (func == NULL || DUK_HOBJECT_IS_NATIVEFUNCTION(func)) {
+		vs_min_size += DUK_VALSTACK_API_ENTRY_MINIMUM;  /* Duktape/C API guaranteed entries (on top of args) */
+	}
+	vs_min_size += DUK_VALSTACK_INTERNAL_EXTRA;             /* + spare */
+
+	/* XXX: We can't resize the value stack to a size smaller than the
+	 * current top, so the order of the resize and adjusting the stack
+	 * top depends on the current vs. final size of the value stack.
+	 * The operations could be combined to avoid this, but the proper
+	 * fix is to only grow the value stack on a function call, and only
+	 * shrink it (without throwing if the shrink fails) on function
+	 * return.
+	 */
+
+	if (vs_min_size < (duk_size_t) (thr->valstack_top  - thr->valstack)) {
+		DUK_DDD(DUK_DDDPRINT(("final size smaller, set top before resize")));
+
+		DUK_ASSERT(nregs >= 0);  /* can't happen when keeping current stack size */
+		duk_set_top(ctx, idx_args + nargs);  /* clamp anything above nargs */
+		duk_set_top(ctx, idx_args + nregs);  /* extend with undefined */
+		adjusted_top = 1;
+	}
+
+	(void) duk_valstack_resize_raw((duk_context *) thr,
+	                               vs_min_size,
+	                               DUK_VSRESIZE_FLAG_SHRINK |      /* flags */
+	                               0 /* no compact */ |
+	                               DUK_VSRESIZE_FLAG_THROW);
+
+	if (!adjusted_top) {
+		if (nregs >= 0) {
+			DUK_ASSERT(nregs >= nargs);
+			duk_set_top(ctx, idx_args + nargs);  /* clamp anything above nargs */
+			duk_set_top(ctx, idx_args + nregs);  /* extend with undefined */
+		}
+	}
+}
+
+/*
+ *  Manipulate value stack so that exactly 'num_stack_rets' return
+ *  values are at 'idx_retbase' in every case, assuming there are
+ *  'rc' return values on top of stack.
  *
- *    DUK_CALL_FLAG_PROTECTED        <-->  protected call
- *    DUK_CALL_FLAG_IGNORE_RECLIMIT  <-->  ignore C recursion limit,
- *                                         for errhandler calls
- *    DUK_CALL_FLAG_CONSTRUCTOR_CALL <-->  for 'new Foo()' calls
+ *  This is a bit tricky, because the called C function operates in
+ *  the same activation record and may have e.g. popped the stack
+ *  empty (below idx_retbase).
+ */
+
+DUK_LOCAL void duk__safe_call_adjust_valstack(duk_hthread *thr, duk_idx_t idx_retbase, duk_idx_t num_stack_rets, duk_idx_t num_actual_rets) {
+	duk_context *ctx = (duk_context *) thr;
+	duk_idx_t idx_rcbase;
+
+	DUK_ASSERT(thr != NULL);
+	DUK_ASSERT(idx_retbase >= 0);
+	DUK_ASSERT(num_stack_rets >= 0);
+	DUK_ASSERT(num_actual_rets >= 0);
+
+	idx_rcbase = duk_get_top(ctx) - num_actual_rets;  /* base of known return values */
+
+	DUK_DDD(DUK_DDDPRINT("adjust valstack after func call: "
+	                     "num_stack_rets=%ld, num_actual_rets=%ld, stack_top=%ld, idx_retbase=%ld, idx_rcbase=%ld",
+	                     (long) num_stack_rets, (long) num_actual_rets, (long) duk_get_top(ctx),
+	                     (long) idx_retbase, (long) idx_rcbase));
+
+	DUK_ASSERT(idx_rcbase >= 0);  /* caller must check */
+
+	/* Ensure space for final configuration (idx_retbase + num_stack_rets)
+	 * and intermediate configurations.
+	 */
+	duk_require_stack_top(ctx,
+	                      (idx_rcbase > idx_retbase ? idx_rcbase : idx_retbase) +
+	                      num_stack_rets);
+
+	/* Chop extra retvals away / extend with undefined. */
+	duk_set_top(ctx, idx_rcbase + num_stack_rets);
+
+	if (idx_rcbase >= idx_retbase) {
+		duk_idx_t count = idx_rcbase - idx_retbase;
+		duk_idx_t i;
+
+		DUK_DDD(DUK_DDDPRINT("elements at/after idx_retbase have enough to cover func retvals "
+		                     "(idx_retbase=%ld, idx_rcbase=%ld)", (long) idx_retbase, (long) idx_rcbase));
+
+		/* nuke values at idx_retbase to get the first retval (initially
+		 * at idx_rcbase) to idx_retbase
+		 */
+
+		DUK_ASSERT(count >= 0);
+
+		for (i = 0; i < count; i++) {
+			/* XXX: inefficient; block remove primitive */
+			duk_remove(ctx, idx_retbase);
+		}
+	} else {
+		duk_idx_t count = idx_retbase - idx_rcbase;
+		duk_idx_t i;
+
+		DUK_DDD(DUK_DDDPRINT("not enough elements at/after idx_retbase to cover func retvals "
+		                     "(idx_retbase=%ld, idx_rcbase=%ld)", (long) idx_retbase, (long) idx_rcbase));
+
+		/* insert 'undefined' values at idx_rcbase to get the
+		 * return values to idx_retbase
+		 */
+
+		DUK_ASSERT(count > 0);
+
+		for (i = 0; i < count; i++) {
+			/* XXX: inefficient; block insert primitive */
+			duk_push_undefined(ctx);
+			duk_insert(ctx, idx_rcbase);
+		}
+	}
+}
+
+/*
+ *  Misc shared helpers.
+ */
+
+/* Get valstack index for the func argument or throw if insane stack. */
+DUK_LOCAL duk_idx_t duk__get_idx_func(duk_hthread *thr, duk_idx_t num_stack_args) {
+	duk_size_t off_stack_top;
+	duk_size_t off_stack_args;
+	duk_size_t off_stack_all;
+	duk_idx_t idx_func;         /* valstack index of 'func' and retval (relative to entry valstack_bottom) */
+
+	/* Argument validation and func/args offset. */
+	off_stack_top = (duk_size_t) ((duk_uint8_t *) thr->valstack_top - (duk_uint8_t *) thr->valstack_bottom);
+	off_stack_args = (duk_size_t) ((duk_size_t) num_stack_args * sizeof(duk_tval));
+	off_stack_all = off_stack_args + 2 * sizeof(duk_tval);
+	if (DUK_UNLIKELY(off_stack_all > off_stack_top)) {
+		/* Since stack indices are not reliable, we can't do anything useful
+		 * here.  Invoke the existing setjmp catcher, or if it doesn't exist,
+		 * call the fatal error handler.
+		 */
+		DUK_ERROR_API(thr, DUK_STR_INVALID_CALL_ARGS);
+		return 0;
+	}
+	idx_func = (duk_idx_t) ((off_stack_top - off_stack_all) / sizeof(duk_tval));
+	return idx_func;
+}
+
+/*
+ *  duk_handle_call_protected() and duk_handle_call_unprotected():
+ *  call into a Duktape/C or an Ecmascript function from any state.
  *
- *  Input stack:
+ *  Input stack (thr):
  *
  *    [ func this arg1 ... argN ]
  *
- *  Output stack:
+ *  Output stack (thr):
  *
  *    [ retval ]         (DUK_EXEC_SUCCESS)
  *    [ errobj ]         (DUK_EXEC_ERROR (normal error), protected call)
  *
- *  Even when executing a protected call an error may be thrown in rare cases.
- *  For instance, if we run out of memory when setting up the return stack
- *  after a caught error, the out of memory is propagated to the caller.
- *  Similarly, API errors (such as invalid input stack shape and invalid
- *  indices) cause an error to propagate out of this function.  If there is
- *  no catchpoint for this error, the fatal error handler is called.
- *
- *  See 'execution.txt'.
- *
- *  The allowed thread states for making a call are:
- *    - thr matches heap->curr_thread, and thr is already RUNNING
- *    - thr does not match heap->curr_thread (may be NULL or other),
- *      and thr is INACTIVE (in this case, a setjmp() catchpoint is
- *      always used for thread book-keeping to work properly)
+ *  Even when executing a protected call an error may be thrown in rare cases
+ *  such as an insane num_stack_args argument.  If there is no catchpoint for
+ *  such errors, the fatal error handler is called.
  *
- *  Like elsewhere, gotos are used to keep indent level minimal and
- *  avoiding a dozen helpers with awkward plumbing.
- *
- *  Note: setjmp() and local variables have a nasty interaction,
- *  see execution.txt; non-volatile locals modified after setjmp()
- *  call are not guaranteed to keep their value.
+ *  The error handling path should be error free, even for out-of-memory
+ *  errors, to ensure safe sandboxing.  (As of Duktape 1.4.0 this is not
+ *  yet the case, see XXX notes below.)
  */
 
-duk_int_t duk_handle_call(duk_hthread *thr,
-                          duk_idx_t num_stack_args,
-                          duk_small_uint_t call_flags) {
-	duk_context *ctx = (duk_context *) thr;
+DUK_INTERNAL duk_int_t duk_handle_call_protected(duk_hthread *thr,
+                                                 duk_idx_t num_stack_args,
+                                                 duk_small_uint_t call_flags) {
+	duk_context *ctx;
 	duk_size_t entry_valstack_bottom_index;
+	duk_size_t entry_valstack_end;
 	duk_size_t entry_callstack_top;
 	duk_size_t entry_catchstack_top;
 	duk_int_t entry_call_recursion_depth;
 	duk_hthread *entry_curr_thread;
 	duk_uint_fast8_t entry_thread_state;
-	volatile duk_bool_t need_setjmp;
-	duk_jmpbuf * volatile old_jmpbuf_ptr = NULL;    /* ptr is volatile (not the target) */
-	duk_idx_t idx_func;         /* valstack index of 'func' and retval (relative to entry valstack_bottom) */
-	duk_idx_t idx_args;         /* valstack index of start of args (arg1) (relative to entry valstack_bottom) */
-	duk_idx_t nargs;            /* # argument registers target function wants (< 0 => "as is") */
-	duk_idx_t nregs;            /* # total registers target function wants on entry (< 0 => "as is") */
-	duk_size_t vs_min_size;
-	duk_hobject *func;    /* 'func' on stack (borrowed reference) */
-	duk_activation *act;
-	duk_hobject *env;
+	duk_instr_t **entry_ptr_curr_pc;
+#if !defined(DUK_USE_CPP_EXCEPTIONS)
+	duk_jmpbuf *old_jmpbuf_ptr = NULL;
 	duk_jmpbuf our_jmpbuf;
-	duk_tval tv_tmp;
-	duk_int_t retval = DUK_EXEC_ERROR;
-	duk_ret_t rc;
+#endif
+	duk_idx_t idx_func;  /* valstack index of 'func' and retval (relative to entry valstack_bottom) */
 
+	/* XXX: Multiple tv_func lookups are now avoided by making a local
+	 * copy of tv_func.  Another approach would be to compute an offset
+	 * for tv_func from valstack bottom and recomputing the tv_func
+	 * pointer quickly as valstack + offset instead of calling duk_get_tval().
+	 */
+
+	ctx = (duk_context *) thr;
+	DUK_UNREF(ctx);
 	DUK_ASSERT(thr != NULL);
-	DUK_ASSERT(ctx != NULL);
+	DUK_ASSERT_CTX_VALID(ctx);
 	DUK_ASSERT(num_stack_args >= 0);
-
 	/* XXX: currently NULL allocations are not supported; remove if later allowed */
 	DUK_ASSERT(thr->valstack != NULL);
 	DUK_ASSERT(thr->callstack != NULL);
 	DUK_ASSERT(thr->catchstack != NULL);
 
-	/*
-	 *  Preliminaries, required by setjmp() handler.
-	 *
-	 *  Must be careful not to throw an unintended error here.
-	 *
-	 *  Note: careful with indices like '-x'; if 'x' is zero, it
-	 *  refers to valstack_bottom.
+	/* Argument validation and func/args offset. */
+	idx_func = duk__get_idx_func(thr, num_stack_args);
+
+	/* Preliminaries, required by setjmp() handler.  Must be careful not
+	 * to throw an unintended error here.
 	 */
 
 	entry_valstack_bottom_index = (duk_size_t) (thr->valstack_bottom - thr->valstack);
+#if defined(DUK_USE_PREFER_SIZE)
+	entry_valstack_end = (duk_size_t) (thr->valstack_end - thr->valstack);
+#else
+	DUK_ASSERT((duk_size_t) (thr->valstack_end - thr->valstack) == thr->valstack_size);
+	entry_valstack_end = thr->valstack_size;
+#endif
 	entry_callstack_top = thr->callstack_top;
 	entry_catchstack_top = thr->catchstack_top;
 	entry_call_recursion_depth = thr->heap->call_recursion_depth;
 	entry_curr_thread = thr->heap->curr_thread;  /* Note: may be NULL if first call */
 	entry_thread_state = thr->state;
-	idx_func = duk_normalize_index(ctx, -num_stack_args - 2);  /* idx_func must be valid, note: non-throwing! */
-	idx_args = idx_func + 2;                                   /* idx_args is not necessarily valid if num_stack_args == 0 (idx_args then equals top) */
+	entry_ptr_curr_pc = thr->ptr_curr_pc;  /* may be NULL */
 
-	/* Need a setjmp() catchpoint if a protected call OR if we need to
-	 * do mandatory cleanup.
-	 */
-	need_setjmp = ((call_flags & DUK_CALL_FLAG_PROTECTED) != 0) || (thr->heap->curr_thread != thr);
-
-	DUK_DD(DUK_DDPRINT("duk_handle_call: thr=%p, num_stack_args=%ld, "
-	                   "call_flags=0x%08lx (protected=%ld, ignorerec=%ld, constructor=%ld), need_setjmp=%ld, "
+	DUK_DD(DUK_DDPRINT("duk_handle_call_protected: thr=%p, num_stack_args=%ld, "
+	                   "call_flags=0x%08lx (ignorerec=%ld, constructor=%ld), "
 	                   "valstack_top=%ld, idx_func=%ld, idx_args=%ld, rec_depth=%ld/%ld, "
 	                   "entry_valstack_bottom_index=%ld, entry_callstack_top=%ld, entry_catchstack_top=%ld, "
 	                   "entry_call_recursion_depth=%ld, entry_curr_thread=%p, entry_thread_state=%ld",
 	                   (void *) thr,
 	                   (long) num_stack_args,
 	                   (unsigned long) call_flags,
-	                   (long) ((call_flags & DUK_CALL_FLAG_PROTECTED) != 0 ? 1 : 0),
 	                   (long) ((call_flags & DUK_CALL_FLAG_IGNORE_RECLIMIT) != 0 ? 1 : 0),
 	                   (long) ((call_flags & DUK_CALL_FLAG_CONSTRUCTOR_CALL) != 0 ? 1 : 0),
-	                   (long) need_setjmp,
 	                   (long) duk_get_top(ctx),
 	                   (long) idx_func,
-	                   (long) idx_args,
+	                   (long) (idx_func + 2),
 	                   (long) thr->heap->call_recursion_depth,
 	                   (long) thr->heap->call_recursion_limit,
 	                   (long) entry_valstack_bottom_index,
@@ -41385,142 +57740,207 @@ duk_int_t duk_handle_call(duk_hthread *thr,
 	                   (void *) entry_curr_thread,
 	                   (long) entry_thread_state));
 
-#ifdef DUK_USE_DDDPRINT /*XXX:incorrect*/
-	DUK_D(DUK_DPRINT("callstack before call setup:"));
-	DUK_DEBUG_DUMP_CALLSTACK(thr);
-#endif
-
-	if (idx_func < 0 || idx_args < 0) {
-		/*
-		 *  Since stack indices are not reliable, we can't do anything useful
-		 *  here.  Invoke the existing setjmp catcher, or if it doesn't exist,
-		 *  call the fatal error handler.
-		 */
-
-		DUK_ERROR(thr, DUK_ERR_API_ERROR, DUK_STR_INVALID_CALL_ARGS);
-	}
-
-	/*
-	 *  Setup a setjmp() catchpoint first because even the call setup
-	 *  may fail.
-	 */
-
-	if (!need_setjmp) {
-		DUK_DDD(DUK_DDDPRINT("don't need a setjmp catchpoint"));
-		goto handle_call;
-	}
-
+#if !defined(DUK_USE_CPP_EXCEPTIONS)
 	old_jmpbuf_ptr = thr->heap->lj.jmpbuf_ptr;
 	thr->heap->lj.jmpbuf_ptr = &our_jmpbuf;
+#endif
 
-	if (DUK_SETJMP(thr->heap->lj.jmpbuf_ptr->jb) == 0) {
-		DUK_DDD(DUK_DDDPRINT("setjmp catchpoint setup complete"));
-		goto handle_call;
-	}
-
-	/*
-	 *  Error during setup, call, or postprocessing of the call.
-	 *  The error value is in heap->lj.value1.
-	 *
-	 *  Note: any local variables accessed here must have their value
-	 *  assigned *before* the setjmp() call, OR they must be declared
-	 *  volatile.  Otherwise their value is not guaranteed to be correct.
-	 *
-	 *  The following are such variables:
-	 *    - duk_handle_call() parameters
-	 *    - entry_*
-	 *    - idx_func
-	 *    - idx_args
-	 *
-	 *  The very first thing we do is restore the previous setjmp catcher.
-	 *  This means that any error in error handling will propagate outwards
-	 *  instead of causing a setjmp() re-entry above.  The *only* actual
-	 *  errors that should happen here are allocation errors.
-	 */
-
-	DUK_DDD(DUK_DDDPRINT("error caught during protected duk_handle_call(): %!T",
-	                     (duk_tval *) &thr->heap->lj.value1));
-
-	DUK_ASSERT(thr->heap->lj.type == DUK_LJ_TYPE_THROW);
-	DUK_ASSERT(thr->callstack_top >= entry_callstack_top);
-	DUK_ASSERT(thr->catchstack_top >= entry_catchstack_top);
+#if defined(DUK_USE_CPP_EXCEPTIONS)
+	try {
+#else
+	if (DUK_LIKELY(DUK_SETJMP(thr->heap->lj.jmpbuf_ptr->jb) == 0)) {
+#endif
+		/* Call handling and success path.  Success path exit cleans
+		 * up almost all state.
+		 */
+		duk__handle_call_inner(thr, num_stack_args, call_flags, idx_func);
 
-	/*
-	 *  Restore previous setjmp catchpoint
-	 */
+		/* Success path handles */
+		DUK_ASSERT(thr->heap->call_recursion_depth == entry_call_recursion_depth);
+		DUK_ASSERT(thr->ptr_curr_pc == entry_ptr_curr_pc);
 
-	/* Note: either pointer may be NULL (at entry), so don't assert */
-	DUK_DDD(DUK_DDDPRINT("restore jmpbuf_ptr: %p -> %p",
-	                     (void *) (thr && thr->heap ? thr->heap->lj.jmpbuf_ptr : NULL),
-	                     (void *) old_jmpbuf_ptr));
+		/* Longjmp state is kept clean in success path */
+		DUK_ASSERT(thr->heap->lj.type == DUK_LJ_TYPE_UNKNOWN);
+		DUK_ASSERT(thr->heap->lj.iserror == 0);
+		DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(&thr->heap->lj.value1));
+		DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(&thr->heap->lj.value2));
 
-	thr->heap->lj.jmpbuf_ptr = old_jmpbuf_ptr;
+#if !defined(DUK_USE_CPP_EXCEPTIONS)
+		thr->heap->lj.jmpbuf_ptr = old_jmpbuf_ptr;
+#endif
 
-	if (!(call_flags & DUK_CALL_FLAG_PROTECTED)) {
-		/*
-		 *  Caller did not request a protected call but a setjmp
-		 *  catchpoint was set up to allow cleanup.  So, clean up
-		 *  and rethrow.
-		 *
-		 *  We must restore curr_thread here to ensure that its
-		 *  current value doesn't end up pointing to a thread object
-		 *  which has been freed.  This is now a problem because some
-		 *  call sites (namely duk_safe_call()) *first* unwind stacks
-		 *  and only then deal with curr_thread.  If those call sites
-		 *  were fixed, this wouldn't matter here.
-		 *
-		 *  Note: this case happens e.g. when heap->curr_thread is
-		 *  NULL on entry.
-		 */
+		return DUK_EXEC_SUCCESS;
+#if defined(DUK_USE_CPP_EXCEPTIONS)
+	} catch (duk_internal_exception &exc) {
+#else
+	} else {
+#endif
+		/* Error; error value is in heap->lj.value1. */
+
+#if defined(DUK_USE_CPP_EXCEPTIONS)
+		DUK_UNREF(exc);
+#endif
+
+		duk__handle_call_error(thr,
+		                       entry_valstack_bottom_index,
+		                       entry_valstack_end,
+		                       entry_catchstack_top,
+		                       entry_callstack_top,
+		                       entry_call_recursion_depth,
+		                       entry_curr_thread,
+		                       entry_thread_state,
+		                       entry_ptr_curr_pc,
+		                       idx_func
+#if !defined(DUK_USE_CPP_EXCEPTIONS)
+		                       , old_jmpbuf_ptr
+#endif
+                                       );
+
+		/* Longjmp state is cleaned up by error handling */
+		DUK_ASSERT(thr->heap->lj.type == DUK_LJ_TYPE_UNKNOWN);
+		DUK_ASSERT(thr->heap->lj.iserror == 0);
+		DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(&thr->heap->lj.value1));
+		DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(&thr->heap->lj.value2));
+		return DUK_EXEC_ERROR;
+	}
+#if defined(DUK_USE_CPP_EXCEPTIONS)
+	catch (std::exception &exc) {
+		const char *what = exc.what();
+		if (!what) {
+			what = "unknown";
+		}
+		DUK_D(DUK_DPRINT("unexpected c++ std::exception (perhaps thrown by user code)"));
+		try {
+			DUK_ERROR(thr, DUK_ERR_API_ERROR, "caught invalid c++ std::exception '%s' (perhaps thrown by user code)", what);
+		} catch (duk_internal_exception exc) {
+			DUK_D(DUK_DPRINT("caught api error thrown from unexpected c++ std::exception"));
+			duk__handle_call_error(thr,
+			                       entry_valstack_bottom_index,
+			                       entry_valstack_end,
+			                       entry_catchstack_top,
+			                       entry_callstack_top,
+			                       entry_call_recursion_depth,
+			                       entry_curr_thread,
+			                       entry_thread_state,
+			                       entry_ptr_curr_pc,
+			                       idx_func);
+			return DUK_EXEC_ERROR;
+		}
+	} catch (...) {
+		DUK_D(DUK_DPRINT("unexpected c++ exception (perhaps thrown by user code)"));
+		try {
+			DUK_ERROR(thr, DUK_ERR_API_ERROR, "caught invalid c++ exception (perhaps thrown by user code)");
+		} catch (duk_internal_exception exc) {
+			DUK_D(DUK_DPRINT("caught api error thrown from unexpected c++ exception"));
+			duk__handle_call_error(thr,
+			                       entry_valstack_bottom_index,
+			                       entry_valstack_end,
+			                       entry_catchstack_top,
+			                       entry_callstack_top,
+			                       entry_call_recursion_depth,
+			                       entry_curr_thread,
+			                       entry_thread_state,
+			                       entry_ptr_curr_pc,
+			                       idx_func);
+			return DUK_EXEC_ERROR;
+		}
+	}
+#endif
+}
+
+DUK_INTERNAL void duk_handle_call_unprotected(duk_hthread *thr,
+                                              duk_idx_t num_stack_args,
+                                              duk_small_uint_t call_flags) {
+	duk_idx_t idx_func;         /* valstack index of 'func' and retval (relative to entry valstack_bottom) */
 
-		DUK_DDD(DUK_DDDPRINT("call is not protected -> clean up and rethrow"));
+	/* Argument validation and func/args offset. */
+	idx_func = duk__get_idx_func(thr, num_stack_args);
 
-		DUK_HEAP_SWITCH_THREAD(thr->heap, entry_curr_thread);  /* may be NULL */
-		thr->state = entry_thread_state;
-		DUK_ASSERT((thr->state == DUK_HTHREAD_STATE_INACTIVE && thr->heap->curr_thread == NULL) ||  /* first call */
-		           (thr->state == DUK_HTHREAD_STATE_INACTIVE && thr->heap->curr_thread != NULL) ||  /* other call */
-		           (thr->state == DUK_HTHREAD_STATE_RUNNING && thr->heap->curr_thread == thr));     /* current thread */
+	duk__handle_call_inner(thr, num_stack_args, call_flags, idx_func);
+}
 
-		/* XXX: should setjmp catcher be responsible for this instead? */
-		thr->heap->call_recursion_depth = entry_call_recursion_depth;
-		duk_err_longjmp(thr);
-		DUK_UNREACHABLE();
-	}
+DUK_LOCAL void duk__handle_call_inner(duk_hthread *thr,
+                                      duk_idx_t num_stack_args,
+                                      duk_small_uint_t call_flags,
+                                      duk_idx_t idx_func) {
+	duk_context *ctx;
+	duk_size_t entry_valstack_bottom_index;
+	duk_size_t entry_valstack_end;
+	duk_size_t entry_callstack_top;
+	duk_size_t entry_catchstack_top;
+	duk_int_t entry_call_recursion_depth;
+	duk_hthread *entry_curr_thread;
+	duk_uint_fast8_t entry_thread_state;
+	duk_instr_t **entry_ptr_curr_pc;
+	duk_idx_t nargs;            /* # argument registers target function wants (< 0 => "as is") */
+	duk_idx_t nregs;            /* # total registers target function wants on entry (< 0 => "as is") */
+	duk_hobject *func;          /* 'func' on stack (borrowed reference) */
+	duk_tval *tv_func;          /* duk_tval ptr for 'func' on stack (borrowed reference) or tv_func_copy */
+	duk_tval tv_func_copy;      /* to avoid relookups */
+	duk_activation *act;
+	duk_hobject *env;
+	duk_ret_t rc;
 
-	duk_hthread_catchstack_unwind(thr, entry_catchstack_top);
-	duk_hthread_callstack_unwind(thr, entry_callstack_top);
-	thr->valstack_bottom = thr->valstack + entry_valstack_bottom_index;
+	ctx = (duk_context *) thr;
+	DUK_ASSERT(thr != NULL);
+	DUK_ASSERT_CTX_VALID(ctx);
+	DUK_ASSERT(ctx != NULL);
+	DUK_ASSERT(num_stack_args >= 0);
+	/* XXX: currently NULL allocations are not supported; remove if later allowed */
+	DUK_ASSERT(thr->valstack != NULL);
+	DUK_ASSERT(thr->callstack != NULL);
+	DUK_ASSERT(thr->catchstack != NULL);
 
-	/* [ ... func this (crud) errobj ] */
+	DUK_DD(DUK_DDPRINT("duk__handle_call_inner: num_stack_args=%ld, call_flags=0x%08lx, top=%ld",
+	                   (long) num_stack_args, (long) call_flags, (long) duk_get_top(ctx)));
 
-	/* FIXME: is there space?  better implementation: write directly over
-	 * 'func' slot to avoid valstack grow issues.
+	/*
+	 *  Store entry state.
 	 */
-	duk_push_tval(ctx, &thr->heap->lj.value1);
-
-	/* [ ... func this (crud) errobj ] */
-
-	duk_replace(ctx, idx_func);
-	duk_set_top(ctx, idx_func + 1);
 
-	/* [ ... errobj ] */
+	entry_valstack_bottom_index = (duk_size_t) (thr->valstack_bottom - thr->valstack);
+#if defined(DUK_USE_PREFER_SIZE)
+	entry_valstack_end = (duk_size_t) (thr->valstack_end - thr->valstack);
+#else
+	DUK_ASSERT((duk_size_t) (thr->valstack_end - thr->valstack) == thr->valstack_size);
+	entry_valstack_end = thr->valstack_size;
+#endif
+	entry_callstack_top = thr->callstack_top;
+	entry_catchstack_top = thr->catchstack_top;
+	entry_call_recursion_depth = thr->heap->call_recursion_depth;
+	entry_curr_thread = thr->heap->curr_thread;  /* Note: may be NULL if first call */
+	entry_thread_state = thr->state;
+	entry_ptr_curr_pc = thr->ptr_curr_pc;  /* may be NULL */
 
-	/* ensure there is internal valstack spare before we exit; this may
-	 * throw an alloc error
+	/* If thr->ptr_curr_pc is set, sync curr_pc to act->pc.  Then NULL
+	 * thr->ptr_curr_pc so that it's not accidentally used with an incorrect
+	 * activation when side effects occur.
 	 */
+	duk_hthread_sync_and_null_currpc(thr);
 
-	duk_require_valstack_resize((duk_context *) thr,
-	                            (thr->valstack_top - thr->valstack) +            /* top of current func */
-	                                DUK_VALSTACK_INTERNAL_EXTRA,                 /* + spare => min_new_size */
-	                            1);                                              /* allow_shrink */
+	DUK_DD(DUK_DDPRINT("duk__handle_call_inner: thr=%p, num_stack_args=%ld, "
+	                   "call_flags=0x%08lx (ignorerec=%ld, constructor=%ld), "
+	                   "valstack_top=%ld, idx_func=%ld, idx_args=%ld, rec_depth=%ld/%ld, "
+	                   "entry_valstack_bottom_index=%ld, entry_callstack_top=%ld, entry_catchstack_top=%ld, "
+	                   "entry_call_recursion_depth=%ld, entry_curr_thread=%p, entry_thread_state=%ld",
+	                   (void *) thr,
+	                   (long) num_stack_args,
+	                   (unsigned long) call_flags,
+	                   (long) ((call_flags & DUK_CALL_FLAG_IGNORE_RECLIMIT) != 0 ? 1 : 0),
+	                   (long) ((call_flags & DUK_CALL_FLAG_CONSTRUCTOR_CALL) != 0 ? 1 : 0),
+	                   (long) duk_get_top(ctx),
+	                   (long) idx_func,
+	                   (long) (idx_func + 2),
+	                   (long) thr->heap->call_recursion_depth,
+	                   (long) thr->heap->call_recursion_limit,
+	                   (long) entry_valstack_bottom_index,
+	                   (long) entry_callstack_top,
+	                   (long) entry_catchstack_top,
+	                   (long) entry_call_recursion_depth,
+	                   (void *) entry_curr_thread,
+	                   (long) entry_thread_state));
 
-	/* Note: currently a second setjmp restoration is done at the target;
-	 * this is OK, but could be refactored away.
-	 */
-	retval = DUK_EXEC_ERROR;
-	goto shrink_and_finished;
 
- handle_call:
 	/*
 	 *  Thread state check and book-keeping.
 	 */
@@ -41545,7 +57965,6 @@ duk_int_t duk_handle_call(duk_hthread *thr,
 		 * state, but not in the same "resume chain".
 		 */
 	}
-
 	DUK_ASSERT(thr->heap->curr_thread == thr);
 	DUK_ASSERT(thr->state == DUK_HTHREAD_STATE_RUNNING);
 
@@ -41555,12 +57974,15 @@ duk_int_t duk_handle_call(duk_hthread *thr,
 	 *  possible by recursive handle_call / handle_safe_call calls).
 	 */
 
+	/* XXX: remove DUK_CALL_FLAG_IGNORE_RECLIMIT flag: there's now the
+	 * reclimit bump?
+	 */
+
 	DUK_ASSERT(thr->heap->call_recursion_depth >= 0);
 	DUK_ASSERT(thr->heap->call_recursion_depth <= thr->heap->call_recursion_limit);
-
 	if (call_flags & DUK_CALL_FLAG_IGNORE_RECLIMIT) {
 		DUK_DD(DUK_DDPRINT("ignoring reclimit for this call (probably an errhandler call)"));
-	} else {	
+	} else {
 		if (thr->heap->call_recursion_depth >= thr->heap->call_recursion_limit) {
 			/* XXX: error message is a bit misleading: we reached a recursion
 			 * limit which is also essentially the same as a C callstack limit
@@ -41572,169 +57994,156 @@ duk_int_t duk_handle_call(duk_hthread *thr,
 	}
 
 	/*
-	 *  Check the function type, handle bound function chains,
-	 *  and prepare parameters for the rest of the call handling.
-	 *  Also figure out the effective 'this' binding, which
-	 *  replaces the current value at idx_func + 1.
+	 *  Check the function type, handle bound function chains, and prepare
+	 *  parameters for the rest of the call handling.  Also figure out the
+	 *  effective 'this' binding, which replaces the current value at
+	 *  idx_func + 1.
+	 *
+	 *  If the target function is a 'bound' one, follow the chain of 'bound'
+	 *  functions until a non-bound function is found.  During this process,
+	 *  bound arguments are 'prepended' to existing ones, and the "this"
+	 *  binding is overridden.  See E5 Section 15.3.4.5.1.
 	 *
-	 *  If the target function is a 'bound' one, follow the chain
-	 *  of 'bound' functions until a non-bound function is found.
-	 *  During this process, bound arguments are 'prepended' to
-	 *  existing ones, and the "this" binding is overridden.
-	 *  See E5 Section 15.3.4.5.1.
+	 *  Lightfunc detection happens here too.  Note that lightweight functions
+	 *  can be wrapped by (non-lightweight) bound functions so we must resolve
+	 *  the bound function chain first.
 	 */
 
-	if (!duk_is_callable(thr, idx_func)) {
-		DUK_ERROR(thr, DUK_ERR_TYPE_ERROR, DUK_STR_NOT_CALLABLE);
-	}
-	func = duk_get_hobject(thr, idx_func);
-	DUK_ASSERT(func != NULL);
+	func = duk__nonbound_func_lookup(ctx, idx_func, &num_stack_args, &tv_func, call_flags);
+	DUK_TVAL_SET_TVAL(&tv_func_copy, tv_func);
+	tv_func = &tv_func_copy;  /* local copy to avoid relookups */
 
-	if (DUK_HOBJECT_HAS_BOUND(func)) {
-		/* slow path for bound functions */
-		duk__handle_bound_chain_for_call(thr, idx_func, &num_stack_args, &func, call_flags & DUK_CALL_FLAG_CONSTRUCTOR_CALL);
-	}
-	DUK_ASSERT(!DUK_HOBJECT_HAS_BOUND(func));
-	DUK_ASSERT(DUK_HOBJECT_IS_COMPILEDFUNCTION(func) ||
-	           DUK_HOBJECT_IS_NATIVEFUNCTION(func));
+	DUK_ASSERT(func == NULL || !DUK_HOBJECT_HAS_BOUND(func));
+	DUK_ASSERT(func == NULL || (DUK_HOBJECT_IS_COMPILEDFUNCTION(func) ||
+	                            DUK_HOBJECT_IS_NATIVEFUNCTION(func)));
 
 	duk__coerce_effective_this_binding(thr, func, idx_func + 1);
 	DUK_DDD(DUK_DDDPRINT("effective 'this' binding is: %!T",
 	                     (duk_tval *) duk_get_tval(ctx, idx_func + 1)));
 
-	/* These base values are never used, but if the compiler doesn't know
-	 * that DUK_ERROR() won't return, these are needed to silence warnings.
-	 * On the other hand, scan-build will warn about the values not being
-	 * used, so add a DUK_UNREF.
-	 */
-	nargs = 0; DUK_UNREF(nargs);
-	nregs = 0; DUK_UNREF(nregs);
-
-	if (DUK_HOBJECT_IS_COMPILEDFUNCTION(func)) {
-		nargs = ((duk_hcompiledfunction *) func)->nargs;
-		nregs = ((duk_hcompiledfunction *) func)->nregs;
-		DUK_ASSERT(nregs >= nargs);
-	} else if (DUK_HOBJECT_IS_NATIVEFUNCTION(func)) {
-		/* Note: nargs (and nregs) may be negative for a native,
-		 * function, which indicates that the function wants the
-		 * input stack "as is" (i.e. handles "vararg" arguments).
-		 */
-		nargs = ((duk_hnativefunction *) func)->nargs;
-		nregs = nargs;
-	} else {
-		/* XXX: this should be an assert */
-		DUK_ERROR(thr, DUK_ERR_TYPE_ERROR, DUK_STR_NOT_CALLABLE);
-	}
-
 	/* [ ... func this arg1 ... argN ] */
 
 	/*
-	 *  Check stack sizes and resize if necessary.
+	 *  Setup a preliminary activation and figure out nargs/nregs.
 	 *
-	 *  Call stack is grown by one, catch stack doesn't grow here.
-	 *  Value stack may either grow or shrink, depending on the number
-	 *  of func registers and the number of actual arguments.
+	 *  Don't touch valstack_bottom or valstack_top yet so that Duktape API
+	 *  calls work normally.
 	 */
 
 	duk_hthread_callstack_grow(thr);
 
-	/* if nregs >= 0, func wants args clamped to 'nargs'; else it wants
-	 * all args (= 'num_stack_args')
-	 */
-
-	vs_min_size = (thr->valstack_bottom - thr->valstack) +         /* bottom of current func */
-	              idx_args;                                        /* bottom of new func */
-	vs_min_size += (nregs >= 0 ? nregs : num_stack_args);          /* num entries of new func at entry */
-	if (DUK_HOBJECT_IS_NATIVEFUNCTION(func)) {
-		vs_min_size += DUK_VALSTACK_API_ENTRY_MINIMUM;         /* Duktape/C API guaranteed entries (on top of args) */
-	}
-	vs_min_size += DUK_VALSTACK_INTERNAL_EXTRA,                    /* + spare */
-
-	duk_require_valstack_resize((duk_context *) thr, vs_min_size, 1 /*allow_shrink*/);
-
-	/*
-	 *  Update idx_retval of current activation.
-	 *
-	 *  Although it might seem this is not necessary (bytecode executor
-	 *  does this for Ecmascript-to-Ecmascript calls; other calls are
-	 *  handled here), this turns out to be necessary for handling yield
-	 *  and resume.  For them, an Ecmascript-to-native call happens, and
-	 *  the Ecmascript call's idx_retval must be set for things to work.
-	 */
-
 	if (thr->callstack_top > 0) {
-		/* now set unconditionally, regardless of whether current activation
-		 * is native or not.
-	 	 */
+		/*
+		 *  Update idx_retval of current activation.
+		 *
+		 *  Although it might seem this is not necessary (bytecode executor
+		 *  does this for Ecmascript-to-Ecmascript calls; other calls are
+		 *  handled here), this turns out to be necessary for handling yield
+		 *  and resume.  For them, an Ecmascript-to-native call happens, and
+		 *  the Ecmascript call's idx_retval must be set for things to work.
+		 */
+
 		(thr->callstack + thr->callstack_top - 1)->idx_retval = entry_valstack_bottom_index + idx_func;
 	}
 
-	/*
-	 *  Setup a preliminary activation.
-	 *
-	 *  Don't touch valstack_bottom or valstack_top yet so that Duktape API
-	 *  calls work normally.
-	 */
-
-	/* [ ... func this arg1 ... argN ] */
-
 	DUK_ASSERT(thr->callstack_top < thr->callstack_size);
 	act = thr->callstack + thr->callstack_top;
 	thr->callstack_top++;
 	DUK_ASSERT(thr->callstack_top <= thr->callstack_size);
 	DUK_ASSERT(thr->valstack_top > thr->valstack_bottom);  /* at least effective 'this' */
-	DUK_ASSERT(!DUK_HOBJECT_HAS_BOUND(func));
+	DUK_ASSERT(func == NULL || !DUK_HOBJECT_HAS_BOUND(func));
 
 	act->flags = 0;
-	if (DUK_HOBJECT_HAS_STRICT(func)) {
-		act->flags |= DUK_ACT_FLAG_STRICT;
-	}
+
+	/* For now all calls except Ecma-to-Ecma calls prevent a yield. */
+	act->flags |= DUK_ACT_FLAG_PREVENT_YIELD;
 	if (call_flags & DUK_CALL_FLAG_CONSTRUCTOR_CALL) {
 		act->flags |= DUK_ACT_FLAG_CONSTRUCT;
-		/*act->flags |= DUK_ACT_FLAG_PREVENT_YIELD;*/
-	}
-	if (DUK_HOBJECT_IS_NATIVEFUNCTION(func)) {
-		/*act->flags |= DUK_ACT_FLAG_PREVENT_YIELD;*/
 	}
 	if (call_flags & DUK_CALL_FLAG_DIRECT_EVAL) {
 		act->flags |= DUK_ACT_FLAG_DIRECT_EVAL;
 	}
 
-	/* As a first approximation, all calls except Ecmascript-to-Ecmascript
-	 * calls prevent a yield.
+	/* These base values are never used, but if the compiler doesn't know
+	 * that DUK_ERROR() won't return, these are needed to silence warnings.
+	 * On the other hand, scan-build will warn about the values not being
+	 * used, so add a DUK_UNREF.
 	 */
-	act->flags |= DUK_ACT_FLAG_PREVENT_YIELD;
+	nargs = 0; DUK_UNREF(nargs);
+	nregs = 0; DUK_UNREF(nregs);
+
+	if (DUK_LIKELY(func != NULL)) {
+		if (DUK_HOBJECT_HAS_STRICT(func)) {
+			act->flags |= DUK_ACT_FLAG_STRICT;
+		}
+		if (DUK_HOBJECT_IS_COMPILEDFUNCTION(func)) {
+			nargs = ((duk_hcompiledfunction *) func)->nargs;
+			nregs = ((duk_hcompiledfunction *) func)->nregs;
+			DUK_ASSERT(nregs >= nargs);
+		} else if (DUK_HOBJECT_IS_NATIVEFUNCTION(func)) {
+			/* Note: nargs (and nregs) may be negative for a native,
+			 * function, which indicates that the function wants the
+			 * input stack "as is" (i.e. handles "vararg" arguments).
+			 */
+			nargs = ((duk_hnativefunction *) func)->nargs;
+			nregs = nargs;
+		} else {
+			/* XXX: this should be an assert */
+			DUK_ERROR(thr, DUK_ERR_TYPE_ERROR, DUK_STR_NOT_CALLABLE);
+		}
+	} else {
+		duk_small_uint_t lf_flags;
+
+		DUK_ASSERT(DUK_TVAL_IS_LIGHTFUNC(tv_func));
+		lf_flags = DUK_TVAL_GET_LIGHTFUNC_FLAGS(tv_func);
+		nargs = DUK_LFUNC_FLAGS_GET_NARGS(lf_flags);
+		if (nargs == DUK_LFUNC_NARGS_VARARGS) {
+			nargs = -1;  /* vararg */
+		}
+		nregs = nargs;
+
+		act->flags |= DUK_ACT_FLAG_STRICT;
+	}
 
-	act->func = func;
+	act->func = func;  /* NULL for lightfunc */
 	act->var_env = NULL;
 	act->lex_env = NULL;
-#ifdef DUK_USE_NONSTD_FUNC_CALLER_PROPERTY
+#if defined(DUK_USE_NONSTD_FUNC_CALLER_PROPERTY)
 	act->prev_caller = NULL;
 #endif
-	act->pc = 0;
-	act->idx_bottom = entry_valstack_bottom_index + idx_args;
+	act->curr_pc = NULL;
+#if defined(DUK_USE_DEBUGGER_SUPPORT)
+	act->prev_line = 0;
+#endif
+	act->idx_bottom = entry_valstack_bottom_index + idx_func + 2;
 #if 0  /* topmost activation idx_retval is considered garbage, no need to init */
 	act->idx_retval = 0;
 #endif
+	DUK_TVAL_SET_TVAL(&act->tv_func, tv_func);  /* borrowed, no refcount */
 
+	/* XXX: remove the preventcount and make yield walk the callstack?
+	 * Or perhaps just use a single flag, not a counter, faster to just
+	 * set and restore?
+	 */
 	if (act->flags & DUK_ACT_FLAG_PREVENT_YIELD) {
 		/* duk_hthread_callstack_unwind() will decrease this on unwind */
 		thr->callstack_preventcount++;
 	}
 
-	DUK_HOBJECT_INCREF(thr, func);  /* act->func */
+	/* XXX: Is this INCREF necessary? 'func' is always a borrowed
+	 * reference reachable through the value stack?  If changed, stack
+	 * unwind code also needs to be fixed to match.
+	 */
+	DUK_HOBJECT_INCREF_ALLOWNULL(thr, func);  /* act->func */
 
-#ifdef DUK_USE_NONSTD_FUNC_CALLER_PROPERTY
-	duk__update_func_caller_prop(thr, func);
+#if defined(DUK_USE_NONSTD_FUNC_CALLER_PROPERTY)
+	if (func) {
+		duk__update_func_caller_prop(thr, func);
+	}
 	act = thr->callstack + thr->callstack_top - 1;
 #endif
 
-	/* [... func this arg1 ... argN] */
-
-#ifdef DUK_USE_DDDPRINT /*XXX:incorrect*/
-	DUK_D(DUK_DPRINT("pushed new activation:"));
-	DUK_DEBUG_DUMP_ACTIVATION(thr, thr->callstack + thr->callstack_top - 1);
-#endif
+	/* [ ... func this arg1 ... argN ] */
 
 	/*
 	 *  Environment record creation and 'arguments' object creation.
@@ -41749,286 +58158,242 @@ duk_int_t duk_handle_call(duk_hthread *thr,
 	 *  Delayed creation (on demand) is handled in duk_js_var.c.
 	 */
 
-	DUK_ASSERT(!DUK_HOBJECT_HAS_BOUND(func));  /* bound function chain has already been resolved */
-
-	if (!DUK_HOBJECT_HAS_NEWENV(func)) {
-		/* use existing env (e.g. for non-strict eval); cannot have
-		 * an own 'arguments' object (but can refer to the existing one)
-		 */
-
-		DUK_ASSERT(!DUK_HOBJECT_HAS_CREATEARGS(func));
-
-		duk__handle_oldenv_for_call(thr, func, act);
-
-		DUK_ASSERT(act->lex_env != NULL);
-		DUK_ASSERT(act->var_env != NULL);
-		goto env_done;
-	}
-
-	DUK_ASSERT(DUK_HOBJECT_HAS_NEWENV(func));
-
-	if (!DUK_HOBJECT_HAS_CREATEARGS(func)) {
-		/* no need to create environment record now; leave as NULL */
-		DUK_ASSERT(act->lex_env == NULL);
-		DUK_ASSERT(act->var_env == NULL);
-		goto env_done;
-	}
-
-	/* third arg: absolute index (to entire valstack) of idx_bottom of new activation */
-	env = duk_create_activation_environment_record(thr, func, act->idx_bottom);
-	DUK_ASSERT(env != NULL);
-	
-	/* [... func this arg1 ... argN envobj] */
-
-	DUK_ASSERT(DUK_HOBJECT_HAS_CREATEARGS(func));
-	duk__handle_createargs_for_call(thr, func, env, num_stack_args);
+	DUK_ASSERT(func == NULL || !DUK_HOBJECT_HAS_BOUND(func));  /* bound function chain has already been resolved */
 
-	/* [... func this arg1 ... argN envobj] */
+	if (DUK_LIKELY(func != NULL)) {
+		if (DUK_LIKELY(DUK_HOBJECT_HAS_NEWENV(func))) {
+			if (DUK_LIKELY(!DUK_HOBJECT_HAS_CREATEARGS(func))) {
+				/* Use a new environment but there's no 'arguments' object;
+				 * delayed environment initialization.  This is the most
+				 * common case.
+				 */
+				DUK_ASSERT(act->lex_env == NULL);
+				DUK_ASSERT(act->var_env == NULL);
+			} else {
+				/* Use a new environment and there's an 'arguments' object.
+				 * We need to initialize it right now.
+				 */
 
-	act->lex_env = env;
-	act->var_env = env;
-	DUK_HOBJECT_INCREF(thr, env);
-	DUK_HOBJECT_INCREF(thr, env);  /* XXX: incref by count (2) directly */
-	duk_pop(ctx);
+				/* third arg: absolute index (to entire valstack) of idx_bottom of new activation */
+				env = duk_create_activation_environment_record(thr, func, act->idx_bottom);
+				DUK_ASSERT(env != NULL);
 
- env_done:
-	/* [... func this arg1 ... argN] */
+				/* [ ... func this arg1 ... argN envobj ] */
 
-	/*
-	 *  Setup value stack: clamp to 'nargs', fill up to 'nregs'
-	 */
+				DUK_ASSERT(DUK_HOBJECT_HAS_CREATEARGS(func));
+				duk__handle_createargs_for_call(thr, func, env, num_stack_args);
 
-	/* XXX: replace with a single operation */
+				/* [ ... func this arg1 ... argN envobj ] */
 
-	if (nregs >= 0) {
-		duk_set_top(ctx, idx_args + nargs);  /* clamp anything above nargs */
-		duk_set_top(ctx, idx_args + nregs);  /* extend with undefined */
-	} else {
-		/* 'func' wants stack "as is" */
-	}
+				act = thr->callstack + thr->callstack_top - 1;
+				act->lex_env = env;
+				act->var_env = env;
+				DUK_HOBJECT_INCREF(thr, env);
+				DUK_HOBJECT_INCREF(thr, env);  /* XXX: incref by count (2) directly */
+				duk_pop(ctx);
+			}
+		} else {
+			/* Use existing env (e.g. for non-strict eval); cannot have
+			 * an own 'arguments' object (but can refer to an existing one).
+			 */
 
-#ifdef DUK_USE_DDDPRINT /*XXX:incorrect*/
-	DUK_D(DUK_DPRINT("callstack after call setup:"));
-	DUK_DEBUG_DUMP_CALLSTACK(thr);
-#endif
+			DUK_ASSERT(!DUK_HOBJECT_HAS_CREATEARGS(func));
 
-	/*
-	 *  Determine call type; then setup activation and call
-	 */
+			duk__handle_oldenv_for_call(thr, func, act);
 
-	if (DUK_HOBJECT_IS_COMPILEDFUNCTION(func)) {
-		goto ecmascript_call;
+			DUK_ASSERT(act->lex_env != NULL);
+			DUK_ASSERT(act->var_env != NULL);
+		}
 	} else {
-		goto native_call;
+		/* Lightfuncs are always native functions and have "newenv". */
+		DUK_ASSERT(act->lex_env == NULL);
+		DUK_ASSERT(act->var_env == NULL);
 	}
-	DUK_UNREACHABLE();
-
-	/*
-	 *  Native (C) call
-	 */
-
- native_call:
-	/*
-	 *  Shift to new valstack_bottom.
-	 */
-
-	thr->valstack_bottom = thr->valstack_bottom + idx_args;
-	/* keep current valstack_top */
-	DUK_ASSERT(thr->valstack_bottom >= thr->valstack);
-	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
-	DUK_ASSERT(thr->valstack_end >= thr->valstack_top);
-	DUK_ASSERT(((duk_hnativefunction *) func)->func != NULL);
 
-	/* [... func this | arg1 ... argN] ('this' must precede new bottom) */
+	/* [ ... func this arg1 ... argN ] */
 
 	/*
-	 *  Actual function call and return value check.
+	 *  Setup value stack: clamp to 'nargs', fill up to 'nregs'
 	 *
-	 *  Return values:
-	 *    0    success, no return value (default to 'undefined')
-	 *    1    success, one return value on top of stack
-	 *  < 0    error, throw a "magic" error
-	 *  other  invalid
-	 */
-
-	rc = ((duk_hnativefunction *) func)->func((duk_context *) thr);
-
-	if (rc < 0) {
-		duk_error_throw_from_negative_rc(thr, rc);
-		DUK_UNREACHABLE();
-	} else if (rc > 1) {
-		DUK_ERROR(thr, DUK_ERR_API_ERROR, "c function returned invalid rc");
-	}
-	DUK_ASSERT(rc == 0 || rc == 1);
-
-	/*
-	 *  Unwind stack(s) and shift back to old valstack_bottom.
+	 *  Value stack may either grow or shrink, depending on the
+	 *  number of func registers and the number of actual arguments.
+	 *  If nregs >= 0, func wants args clamped to 'nargs'; else it
+	 *  wants all args (= 'num_stack_args').
 	 */
 
-	DUK_ASSERT(thr->catchstack_top == entry_catchstack_top);
-	DUK_ASSERT(thr->callstack_top == entry_callstack_top + 1);
-
-#if 0  /* should be no need to unwind */
-	duk_hthread_catchstack_unwind(thr, entry_catchstack_top);
-#endif
-	duk_hthread_callstack_unwind(thr, entry_callstack_top);
-
-	thr->valstack_bottom = thr->valstack + entry_valstack_bottom_index;
-	/* keep current valstack_top */
+	/* XXX: optimize value stack operation */
+	/* XXX: don't want to shrink allocation here */
 
-	DUK_ASSERT(thr->valstack_bottom >= thr->valstack);
-	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
-	DUK_ASSERT(thr->valstack_end >= thr->valstack_top);
-	DUK_ASSERT(thr->valstack_top - thr->valstack_bottom >= idx_func + 1);
+	duk__adjust_valstack_and_top(thr,
+	                             num_stack_args,
+	                             idx_func + 2,
+	                             nregs,
+	                             nargs,
+	                             func);
 
 	/*
-	 *  Manipulate value stack so that return value is on top
-	 *  (pushing an 'undefined' if necessary).
+	 *  Determine call type, then finalize activation, shift to
+	 *  new value stack bottom, and call the target.
 	 */
 
-	/* XXX: should this happen in the callee's activation or after unwinding? */
-	if (rc == 0) {
-		duk_require_stack(ctx, 1);
-		duk_push_undefined(ctx);
-	}
-	/* [... func this (crud) retval] */
+	if (func != NULL && DUK_HOBJECT_IS_COMPILEDFUNCTION(func)) {
+		/*
+		 *  Ecmascript call
+		 */
 
-	DUK_DDD(DUK_DDDPRINT("native call retval -> %!T (rc=%ld)",
-	                     (duk_tval *) duk_get_tval(ctx, -1), (long) rc));
+		duk_tval *tv_ret;
+		duk_tval *tv_funret;
 
-	duk_replace(ctx, idx_func);
-	duk_set_top(ctx, idx_func + 1);
+		DUK_ASSERT(func != NULL);
+		DUK_ASSERT(DUK_HOBJECT_HAS_COMPILEDFUNCTION(func));
+		act->curr_pc = DUK_HCOMPILEDFUNCTION_GET_CODE_BASE(thr->heap, (duk_hcompiledfunction *) func);
 
-	/* [... retval] */
+		thr->valstack_bottom = thr->valstack_bottom + idx_func + 2;
+		/* keep current valstack_top */
+		DUK_ASSERT(thr->valstack_bottom >= thr->valstack);
+		DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
+		DUK_ASSERT(thr->valstack_end >= thr->valstack_top);
 
-	/* ensure there is internal valstack spare before we exit */
+		/* [ ... func this | arg1 ... argN ] ('this' must precede new bottom) */
 
-	duk_require_valstack_resize((duk_context *) thr,
-	                            (thr->valstack_top - thr->valstack) +            /* top of current func */
-	                                DUK_VALSTACK_INTERNAL_EXTRA,                 /* + spare => min_new_size */
-	                            1);                                              /* allow_shrink */
+		/*
+		 *  Bytecode executor call.
+		 *
+		 *  Execute bytecode, handling any recursive function calls and
+		 *  thread resumptions.  Returns when execution would return from
+		 *  the entry level activation.  When the executor returns, a
+		 *  single return value is left on the stack top.
+		 *
+		 *  The only possible longjmp() is an error (DUK_LJ_TYPE_THROW),
+		 *  other types are handled internally by the executor.
+		 */
 
+		/* thr->ptr_curr_pc is set by bytecode executor early on entry */
+		DUK_ASSERT(thr->ptr_curr_pc == NULL);
+		DUK_DDD(DUK_DDDPRINT("entering bytecode execution"));
+		duk_js_execute_bytecode(thr);
+		DUK_DDD(DUK_DDDPRINT("returned from bytecode execution"));
 
-	/*
-	 *  Shrink checks and return with success.
-	 */
+		/* Unwind. */
 
-	retval = DUK_EXEC_SUCCESS;
-	goto shrink_and_finished;	
+		DUK_ASSERT(thr->catchstack_top >= entry_catchstack_top);  /* may need unwind */
+		DUK_ASSERT(thr->callstack_top == entry_callstack_top + 1);
+		DUK_ASSERT(thr->callstack_top == entry_callstack_top + 1);
+		duk_hthread_catchstack_unwind(thr, entry_catchstack_top);
+		duk_hthread_catchstack_shrink_check(thr);
+		duk_hthread_callstack_unwind(thr, entry_callstack_top);
+		duk_hthread_callstack_shrink_check(thr);
 
-	/*
-	 *  Ecmascript call
-	 */
+		thr->valstack_bottom = thr->valstack + entry_valstack_bottom_index;
+		/* keep current valstack_top */
+		DUK_ASSERT(thr->valstack_bottom >= thr->valstack);
+		DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
+		DUK_ASSERT(thr->valstack_end >= thr->valstack_top);
+		DUK_ASSERT(thr->valstack_top - thr->valstack_bottom >= idx_func + 1);
 
- ecmascript_call:
+		/* Return value handling. */
 
-	/*
-	 *  Shift to new valstack_bottom.
-	 */
+		/* [ ... func this (crud) retval ] */
 
-	thr->valstack_bottom = thr->valstack_bottom + idx_args;
-	/* keep current valstack_top */
-	DUK_ASSERT(thr->valstack_bottom >= thr->valstack);
-	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
-	DUK_ASSERT(thr->valstack_end >= thr->valstack_top);
+		tv_ret = thr->valstack_bottom + idx_func;
+		tv_funret = thr->valstack_top - 1;
+#if defined(DUK_USE_FASTINT)
+		/* Explicit check for fastint downgrade. */
+		DUK_TVAL_CHKFAST_INPLACE(tv_funret);
+#endif
+		DUK_TVAL_SET_TVAL_UPDREF(thr, tv_ret, tv_funret);  /* side effects */
+	} else {
+		/*
+		 *  Native call.
+		 */
 
-	/* [... func this | arg1 ... argN] ('this' must precede new bottom) */
+		duk_tval *tv_ret;
+		duk_tval *tv_funret;
 
-	/*
-	 *  Bytecode executor call.
-	 *
-	 *  Execute bytecode, handling any recursive function calls and
-	 *  thread resumptions.  Returns when execution would return from
-	 *  the entry level activation.  When the executor returns, a
-	 *  single return value is left on the stack top.
-	 *
-	 *  The only possible longjmp() is an error (DUK_LJ_TYPE_THROW),
-	 *  other types are handled internally by the executor.
-	 *
-	 */
+		thr->valstack_bottom = thr->valstack_bottom + idx_func + 2;
+		/* keep current valstack_top */
+		DUK_ASSERT(thr->valstack_bottom >= thr->valstack);
+		DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
+		DUK_ASSERT(thr->valstack_end >= thr->valstack_top);
+		DUK_ASSERT(func == NULL || ((duk_hnativefunction *) func)->func != NULL);
 
-	DUK_DDD(DUK_DDDPRINT("entering bytecode execution"));
-	duk_js_execute_bytecode(thr);
-	DUK_DDD(DUK_DDDPRINT("returned from bytecode execution"));
+		/* [ ... func this | arg1 ... argN ] ('this' must precede new bottom) */
 
-	/*
-	 *  Unwind stack(s) and shift back to old valstack_bottom.
-	 */
+		/* For native calls must be NULL so we don't sync back */
+		DUK_ASSERT(thr->ptr_curr_pc == NULL);
 
-	DUK_ASSERT(thr->callstack_top == entry_callstack_top + 1);
+		if (func) {
+			rc = ((duk_hnativefunction *) func)->func((duk_context *) thr);
+		} else {
+			duk_c_function funcptr = DUK_TVAL_GET_LIGHTFUNC_FUNCPTR(tv_func);
+			rc = funcptr((duk_context *) thr);
+		}
 
-	duk_hthread_catchstack_unwind(thr, entry_catchstack_top);
-	duk_hthread_callstack_unwind(thr, entry_callstack_top);
+		/* Automatic error throwing, retval check. */
 
-	thr->valstack_bottom = thr->valstack + entry_valstack_bottom_index;
-	/* keep current valstack_top */
+		if (rc < 0) {
+			duk_error_throw_from_negative_rc(thr, rc);
+			DUK_UNREACHABLE();
+		} else if (rc > 1) {
+			DUK_ERROR(thr, DUK_ERR_API_ERROR, "c function returned invalid rc");
+		}
+		DUK_ASSERT(rc == 0 || rc == 1);
 
-	DUK_ASSERT(thr->valstack_bottom >= thr->valstack);
-	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
-	DUK_ASSERT(thr->valstack_end >= thr->valstack_top);
-	DUK_ASSERT(thr->valstack_top - thr->valstack_bottom >= idx_func + 1);
+		/* Unwind. */
 
-	/*
-	 *  Manipulate value stack so that return value is on top.
-	 */
+		DUK_ASSERT(thr->catchstack_top == entry_catchstack_top);  /* no need to unwind */
+		DUK_ASSERT(thr->callstack_top == entry_callstack_top + 1);
+		duk_hthread_callstack_unwind(thr, entry_callstack_top);
+		duk_hthread_callstack_shrink_check(thr);
 
-	/* [... func this (crud) retval] */
+		thr->valstack_bottom = thr->valstack + entry_valstack_bottom_index;
+		/* keep current valstack_top */
+		DUK_ASSERT(thr->valstack_bottom >= thr->valstack);
+		DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
+		DUK_ASSERT(thr->valstack_end >= thr->valstack_top);
+		DUK_ASSERT(thr->valstack_top - thr->valstack_bottom >= idx_func + 1);
 
-	duk_replace(ctx, idx_func);
-	duk_set_top(ctx, idx_func + 1);
+		/* Return value handling. */
 
-	/* [... retval] */
+		/* XXX: should this happen in the callee's activation or after unwinding? */
+		tv_ret = thr->valstack_bottom + idx_func;
+		if (rc == 0) {
+			DUK_TVAL_SET_UNDEFINED_UPDREF(thr, tv_ret);  /* side effects */
+		} else {
+			/* [ ... func this (crud) retval ] */
+			tv_funret = thr->valstack_top - 1;
+#if defined(DUK_USE_FASTINT)
+			/* Explicit check for fastint downgrade. */
+			DUK_TVAL_CHKFAST_INPLACE(tv_funret);
+#endif
+			DUK_TVAL_SET_TVAL_UPDREF(thr, tv_ret, tv_funret);  /* side effects */
+		}
+	}
 
-	/* ensure there is internal valstack spare before we exit */
+	duk_set_top(ctx, idx_func + 1);  /* XXX: unnecessary, handle in adjust */
 
-	duk_require_valstack_resize((duk_context *) thr,
-	                            (thr->valstack_top - thr->valstack) +            /* top of current func */
-	                                DUK_VALSTACK_INTERNAL_EXTRA,                 /* + spare => min_new_size */
-	                            1);                                              /* allow_shrink */
+	/* [ ... retval ] */
 
-	/*
-	 *  Shrink checks and return with success.
+	/* Ensure there is internal valstack spare before we exit; this may
+	 * throw an alloc error.  The same guaranteed size must be available
+	 * as before the call.  This is not optimal now: we store the valstack
+	 * allocated size during entry; this value may be higher than the
+	 * minimal guarantee for an application.
 	 */
 
-	retval = DUK_EXEC_SUCCESS;
-	goto shrink_and_finished;	
-
- shrink_and_finished:
-	/* these are "soft" shrink checks, whose failures are ignored */
-	/* XXX: would be nice if fast path was inlined */
-	duk_hthread_catchstack_shrink_check(thr);
-	duk_hthread_callstack_shrink_check(thr);
-	goto finished;
-
- finished:
-	if (need_setjmp) {
-		/* Note: either pointer may be NULL (at entry), so don't assert;
-		 * this is now done potentially twice, which is OK
-		 */
-		DUK_DDD(DUK_DDDPRINT("restore jmpbuf_ptr: %p -> %p (possibly already done)",
-		                     (void *) (thr && thr->heap ? thr->heap->lj.jmpbuf_ptr : NULL),
-		                     (void *) old_jmpbuf_ptr));
-		thr->heap->lj.jmpbuf_ptr = old_jmpbuf_ptr;
-
-		/* These are just convenience "wiping" of state */
-		thr->heap->lj.type = DUK_LJ_TYPE_UNKNOWN;
-		thr->heap->lj.iserror = 0;
-
-		/* Side effects should not be an issue here: tv_tmp is local and
-		 * thr->heap (and thr->heap->lj) have a stable pointer.  Finalizer
-		 * runs etc capture even out-of-memory errors so nothing should
-		 * throw here.
-		 */
-		DUK_TVAL_SET_TVAL(&tv_tmp, &thr->heap->lj.value1);
-		DUK_TVAL_SET_UNDEFINED_UNUSED(&thr->heap->lj.value1);
-		DUK_TVAL_DECREF(thr, &tv_tmp);
+	/* XXX: we should never shrink here; when we error out later, we'd
+	 * need to potentially grow the value stack in error unwind which could
+	 * cause another error.
+	 */
 
-		DUK_TVAL_SET_TVAL(&tv_tmp, &thr->heap->lj.value2);
-		DUK_TVAL_SET_UNDEFINED_UNUSED(&thr->heap->lj.value2);
-		DUK_TVAL_DECREF(thr, &tv_tmp);
+	(void) duk_valstack_resize_raw((duk_context *) thr,
+	                               entry_valstack_end,                    /* same as during entry */
+	                               DUK_VSRESIZE_FLAG_SHRINK |             /* flags */
+	                               DUK_VSRESIZE_FLAG_COMPACT |
+	                               DUK_VSRESIZE_FLAG_THROW);
 
-		DUK_DDD(DUK_DDDPRINT("setjmp catchpoint torn down"));
-	}
+	/* Restore entry thread executor curr_pc stack frame pointer. */
+	thr->ptr_curr_pc = entry_ptr_curr_pc;
 
 	DUK_HEAP_SWITCH_THREAD(thr->heap, entry_curr_thread);  /* may be NULL */
 	thr->state = (duk_uint8_t) entry_thread_state;
@@ -42036,120 +58401,187 @@ duk_int_t duk_handle_call(duk_hthread *thr,
 	DUK_ASSERT((thr->state == DUK_HTHREAD_STATE_INACTIVE && thr->heap->curr_thread == NULL) ||  /* first call */
 	           (thr->state == DUK_HTHREAD_STATE_INACTIVE && thr->heap->curr_thread != NULL) ||  /* other call */
 	           (thr->state == DUK_HTHREAD_STATE_RUNNING && thr->heap->curr_thread == thr));     /* current thread */
-	
+
 	thr->heap->call_recursion_depth = entry_call_recursion_depth;
 
-	return retval;
+	/* If the debugger is active we need to force an interrupt so that
+	 * debugger breakpoints are rechecked.  This is important for function
+	 * calls caused by side effects (e.g. when doing a DUK_OP_GETPROP), see
+	 * GH-303.  Only needed for success path, error path always causes a
+	 * breakpoint recheck in the executor.  It would be enough to set this
+	 * only when returning to an Ecmascript activation, but setting the flag
+	 * on every return should have no ill effect.
+	 */
+#if defined(DUK_USE_DEBUGGER_SUPPORT)
+	if (DUK_HEAP_IS_DEBUGGER_ATTACHED(thr->heap)) {
+		DUK_DD(DUK_DDPRINT("returning with debugger enabled, force interrupt"));
+		DUK_ASSERT(thr->interrupt_counter <= thr->interrupt_init);
+		thr->interrupt_init -= thr->interrupt_counter;
+		thr->interrupt_counter = 0;
+		thr->heap->dbg_force_restart = 1;
+	}
+#endif
+
+#if defined(DUK_USE_INTERRUPT_COUNTER) && defined(DUK_USE_DEBUG)
+	duk__interrupt_fixup(thr, entry_curr_thread);
+#endif
+
+	return;
 
  thread_state_error:
 	DUK_ERROR(thr, DUK_ERR_TYPE_ERROR, "invalid thread state for call (%ld)", (long) thr->state);
 	DUK_UNREACHABLE();
-	return DUK_EXEC_ERROR;  /* never executed */
-}
-
-/*
- *  Manipulate value stack so that exactly 'num_stack_rets' return
- *  values are at 'idx_retbase' in every case, assuming there are
- *  'rc' return values on top of stack.
- *
- *  This is a bit tricky, because the called C function operates in
- *  the same activation record and may have e.g. popped the stack
- *  empty (below idx_retbase).
- */
+	return;  /* never executed */
+}
+
+DUK_LOCAL void duk__handle_call_error(duk_hthread *thr,
+                                      duk_size_t entry_valstack_bottom_index,
+                                      duk_size_t entry_valstack_end,
+                                      duk_size_t entry_catchstack_top,
+                                      duk_size_t entry_callstack_top,
+                                      duk_int_t entry_call_recursion_depth,
+                                      duk_hthread *entry_curr_thread,
+                                      duk_uint_fast8_t entry_thread_state,
+                                      duk_instr_t **entry_ptr_curr_pc,
+                                      duk_idx_t idx_func
+#if !defined(DUK_USE_CPP_EXCEPTIONS)
+                                      , duk_jmpbuf *old_jmpbuf_ptr
+#endif
+                                      ) {
+	duk_context *ctx;
+	duk_tval *tv_ret;
 
-static void duk__safe_call_adjust_valstack(duk_hthread *thr, duk_idx_t idx_retbase, duk_idx_t num_stack_rets, duk_idx_t num_actual_rets) {
-	duk_context *ctx = (duk_context *) thr;
-	duk_idx_t idx_rcbase;
+	ctx = (duk_context *) thr;
 
-	DUK_ASSERT(thr != NULL);
-	DUK_ASSERT(idx_retbase >= 0);
-	DUK_ASSERT(num_stack_rets >= 0);
-	DUK_ASSERT(num_actual_rets >= 0);
+	DUK_DDD(DUK_DDDPRINT("error caught during duk__handle_call_inner(): %!T",
+	                     (duk_tval *) &thr->heap->lj.value1));
 
-	idx_rcbase = duk_get_top(ctx) - num_actual_rets;  /* base of known return values */
+	/* Other longjmp types are handled by executor before propagating
+	 * the error here.
+	 */
+	DUK_ASSERT(thr->heap->lj.type == DUK_LJ_TYPE_THROW);
+	DUK_ASSERT(thr->callstack_top >= entry_callstack_top);
+	DUK_ASSERT(thr->catchstack_top >= entry_catchstack_top);
 
-	DUK_DDD(DUK_DDDPRINT("adjust valstack after func call: "
-	                     "num_stack_rets=%ld, num_actual_rets=%ld, stack_top=%ld, idx_retbase=%ld, idx_rcbase=%ld",
-	                     (long) num_stack_rets, (long) num_actual_rets, (long) duk_get_top(ctx),
-	                     (long) idx_retbase, (long) idx_rcbase));
+	/* We don't need to sync back thr->ptr_curr_pc here because
+	 * the bytecode executor always has a setjmp catchpoint which
+	 * does that before errors propagate to here.
+	 */
+	DUK_ASSERT(thr->ptr_curr_pc == NULL);
 
-	DUK_ASSERT(idx_rcbase >= 0);  /* caller must check */
+#if !defined(DUK_USE_CPP_EXCEPTIONS)
+	/* Restore the previous setjmp catcher so that any error in
+	 * error handling will propagate outwards rather than re-enter
+	 * the same handler.  However, the error handling path must be
+	 * designed to be error free so that sandboxing guarantees are
+	 * reliable, see e.g. https://github.com/svaarala/duktape/issues/476.
+	 */
+	thr->heap->lj.jmpbuf_ptr = old_jmpbuf_ptr;
+#endif
 
-	/* ensure space for final configuration (idx_retbase + num_stack_rets) and
-	 * intermediate configurations
+	/* XXX: callstack unwind may now throw an error when closing
+	 * scopes; this is a sandboxing issue, described in:
+	 * https://github.com/svaarala/duktape/issues/476
 	 */
-	duk_require_stack_top(ctx,
-	                      (idx_rcbase > idx_retbase ? idx_rcbase : idx_retbase) +
-	                      num_stack_rets);
+	duk_hthread_catchstack_unwind(thr, entry_catchstack_top);
+	duk_hthread_catchstack_shrink_check(thr);
+	duk_hthread_callstack_unwind(thr, entry_callstack_top);
+	duk_hthread_callstack_shrink_check(thr);
 
-	/* chop extra retvals away / extend with undefined */
-	duk_set_top(ctx, idx_rcbase + num_stack_rets);
+	thr->valstack_bottom = thr->valstack + entry_valstack_bottom_index;
+	tv_ret = thr->valstack_bottom + idx_func;  /* XXX: byte offset? */
+	DUK_TVAL_SET_TVAL_UPDREF(thr, tv_ret, &thr->heap->lj.value1);  /* side effects */
+#if defined(DUK_USE_FASTINT)
+	/* Explicit check for fastint downgrade. */
+	DUK_TVAL_CHKFAST_INPLACE(tv_ret);
+#endif
+	duk_set_top(ctx, idx_func + 1);  /* XXX: could be eliminated with valstack adjust */
 
-	if (idx_rcbase >= idx_retbase) {
-		duk_idx_t count = idx_rcbase - idx_retbase;
-		duk_idx_t i;
+	/* [ ... errobj ] */
 
-		DUK_DDD(DUK_DDDPRINT("elements at/after idx_retbase have enough to cover func retvals "
-		                     "(idx_retbase=%ld, idx_rcbase=%ld)", (long) idx_retbase, (long) idx_rcbase));
+	/* Ensure there is internal valstack spare before we exit; this may
+	 * throw an alloc error.  The same guaranteed size must be available
+	 * as before the call.  This is not optimal now: we store the valstack
+	 * allocated size during entry; this value may be higher than the
+	 * minimal guarantee for an application.
+	 */
 
-		/* nuke values at idx_retbase to get the first retval (initially
-		 * at idx_rcbase) to idx_retbase
-		 */
+	/* XXX: this needs to be reworked so that we never shrink the value
+	 * stack on function entry so that we never need to grow it here.
+	 * Needing to grow here is a sandboxing issue because we need to
+	 * allocate which may cause an error in the error handling path
+	 * and thus propagate an error out of a protected call.
+	 */
 
-		DUK_ASSERT(count >= 0);
+	(void) duk_valstack_resize_raw((duk_context *) thr,
+	                               entry_valstack_end,                    /* same as during entry */
+	                               DUK_VSRESIZE_FLAG_SHRINK |             /* flags */
+	                               DUK_VSRESIZE_FLAG_COMPACT |
+	                               DUK_VSRESIZE_FLAG_THROW);
 
-		for (i = 0; i < count; i++) {
-			/* XXX: inefficient; block remove primitive */
-			duk_remove(ctx, idx_retbase);
-		}
-	} else {
-		duk_idx_t count = idx_retbase - idx_rcbase;
-		duk_idx_t i;
 
-		DUK_DDD(DUK_DDDPRINT("not enough elements at/after idx_retbase to cover func retvals "
-		                     "(idx_retbase=%ld, idx_rcbase=%ld)", (long) idx_retbase, (long) idx_rcbase));
+	/* These are just convenience "wiping" of state.  Side effects should
+	 * not be an issue here: thr->heap and thr->heap->lj have a stable
+	 * pointer.  Finalizer runs etc capture even out-of-memory errors so
+	 * nothing should throw here.
+	 */
+	thr->heap->lj.type = DUK_LJ_TYPE_UNKNOWN;
+	thr->heap->lj.iserror = 0;
+	DUK_TVAL_SET_UNDEFINED_UPDREF(thr, &thr->heap->lj.value1);  /* side effects */
+	DUK_TVAL_SET_UNDEFINED_UPDREF(thr, &thr->heap->lj.value2);  /* side effects */
 
-		/* insert 'undefined' values at idx_rcbase to get the
-		 * return values to idx_retbase
-		 */
+	/* Restore entry thread executor curr_pc stack frame pointer. */
+	thr->ptr_curr_pc = entry_ptr_curr_pc;
 
-		DUK_ASSERT(count > 0);
+	DUK_HEAP_SWITCH_THREAD(thr->heap, entry_curr_thread);  /* may be NULL */
+	thr->state = (duk_uint8_t) entry_thread_state;
 
-		for (i = 0; i < count; i++) {
-			/* XXX: inefficient; block insert primitive */
-			duk_push_undefined(ctx);
-			duk_insert(ctx, idx_rcbase);
-		}
+	DUK_ASSERT((thr->state == DUK_HTHREAD_STATE_INACTIVE && thr->heap->curr_thread == NULL) ||  /* first call */
+	           (thr->state == DUK_HTHREAD_STATE_INACTIVE && thr->heap->curr_thread != NULL) ||  /* other call */
+	           (thr->state == DUK_HTHREAD_STATE_RUNNING && thr->heap->curr_thread == thr));     /* current thread */
+
+	thr->heap->call_recursion_depth = entry_call_recursion_depth;
+
+	/* If the debugger is active we need to force an interrupt so that
+	 * debugger breakpoints are rechecked.  This is important for function
+	 * calls caused by side effects (e.g. when doing a DUK_OP_GETPROP), see
+	 * GH-303.  Only needed for success path, error path always causes a
+	 * breakpoint recheck in the executor.  It would be enough to set this
+	 * only when returning to an Ecmascript activation, but setting the flag
+	 * on every return should have no ill effect.
+	 */
+#if defined(DUK_USE_DEBUGGER_SUPPORT)
+	if (DUK_HEAP_IS_DEBUGGER_ATTACHED(thr->heap)) {
+		DUK_DD(DUK_DDPRINT("returning with debugger enabled, force interrupt"));
+		DUK_ASSERT(thr->interrupt_counter <= thr->interrupt_init);
+		thr->interrupt_init -= thr->interrupt_counter;
+		thr->interrupt_counter = 0;
+		thr->heap->dbg_force_restart = 1;
 	}
+#endif
+
+#if defined(DUK_USE_INTERRUPT_COUNTER) && defined(DUK_USE_DEBUG)
+	duk__interrupt_fixup(thr, entry_curr_thread);
+#endif
 }
 
 /*
- *  Make a "C protected call" within the current activation.
+ *  duk_handle_safe_call(): make a "C protected call" within the
+ *  current activation.
  *
  *  The allowed thread states for making a call are the same as for
- *  duk_handle_call().
- *
- *  Note that like duk_handle_call(), even if this call is protected,
- *  there are a few situations where the current (pre-entry) setjmp
- *  catcher (or a fatal error handler if no such catcher exists) is
- *  invoked:
- *
- *    - Blatant API argument errors (e.g. num_stack_args is invalid,
- *      so we can't form a reasonable return stack)
+ *  duk_handle_call_xxx().
  *
- *    - Errors during error handling, e.g. failure to reallocate
- *      space in the value stack due to an alloc error
- *
- *  Such errors propagate outwards, ultimately to the fatal error
- *  handler if nothing else.
+ *  Error handling is similar to duk_handle_call_xxx(); errors may be thrown
+ *  (and result in a fatal error) for insane arguments.
  */
 
-/* FIXME: bump preventcount by one for the duration of this call? */
+/* XXX: bump preventcount by one for the duration of this call? */
 
-duk_int_t duk_handle_safe_call(duk_hthread *thr,
-                               duk_safe_call_function func,
-                               duk_idx_t num_stack_args,
-                               duk_idx_t num_stack_rets) {
+DUK_INTERNAL duk_int_t duk_handle_safe_call(duk_hthread *thr,
+                                            duk_safe_call_function func,
+                                            duk_idx_t num_stack_args,
+                                            duk_idx_t num_stack_rets) {
 	duk_context *ctx = (duk_context *) thr;
 	duk_size_t entry_valstack_bottom_index;
 	duk_size_t entry_callstack_top;
@@ -42157,12 +58589,13 @@ duk_int_t duk_handle_safe_call(duk_hthread *thr,
 	duk_int_t entry_call_recursion_depth;
 	duk_hthread *entry_curr_thread;
 	duk_uint_fast8_t entry_thread_state;
+	duk_instr_t **entry_ptr_curr_pc;
+#if !defined(DUK_USE_CPP_EXCEPTIONS)
 	duk_jmpbuf *old_jmpbuf_ptr = NULL;
 	duk_jmpbuf our_jmpbuf;
-	duk_tval tv_tmp;
+#endif
 	duk_idx_t idx_retbase;
 	duk_int_t retval;
-	duk_ret_t rc;
 
 	DUK_ASSERT(thr != NULL);
 	DUK_ASSERT(ctx != NULL);
@@ -42174,6 +58607,7 @@ duk_int_t duk_handle_safe_call(duk_hthread *thr,
 	entry_call_recursion_depth = thr->heap->call_recursion_depth;
 	entry_curr_thread = thr->heap->curr_thread;  /* Note: may be NULL if first call */
 	entry_thread_state = thr->state;
+	entry_ptr_curr_pc = thr->ptr_curr_pc;  /* may be NULL */
 	idx_retbase = duk_get_top(ctx) - num_stack_args;  /* Note: not a valid stack index if num_stack_args == 0 */
 
 	/* Note: cannot portably debug print a function pointer, hence 'func' not printed! */
@@ -42196,90 +58630,146 @@ duk_int_t duk_handle_safe_call(duk_hthread *thr,
 	                   (long) entry_thread_state));
 
 	if (idx_retbase < 0) {
-		/*
-		 *  Since stack indices are not reliable, we can't do anything useful
-		 *  here.  Invoke the existing setjmp catcher, or if it doesn't exist,
-		 *  call the fatal error handler.
+		/* Since stack indices are not reliable, we can't do anything useful
+		 * here.  Invoke the existing setjmp catcher, or if it doesn't exist,
+		 * call the fatal error handler.
 		 */
 
-		DUK_ERROR(thr, DUK_ERR_API_ERROR, DUK_STR_INVALID_CALL_ARGS);
+		DUK_ERROR_API(thr, DUK_STR_INVALID_CALL_ARGS);
 	}
 
 	/* setjmp catchpoint setup */
 
+#if !defined(DUK_USE_CPP_EXCEPTIONS)
 	old_jmpbuf_ptr = thr->heap->lj.jmpbuf_ptr;
 	thr->heap->lj.jmpbuf_ptr = &our_jmpbuf;
+#endif
 
-	if (DUK_SETJMP(thr->heap->lj.jmpbuf_ptr->jb) == 0) {
-		goto handle_call;
-	}
-
-	/*
-	 *  Error during call.  The error value is at heap->lj.value1.
-	 *
-	 *  Careful with variable accesses here; must be assigned to before
-	 *  setjmp() or be declared volatile.  See duk_handle_call().
-	 *
-	 *  The following are such variables:
-	 *    - duk_handle_safe_call() parameters
-	 *    - entry_*
-	 *    - idx_retbase
-	 *
-	 *  The very first thing we do is restore the previous setjmp catcher.
-	 *  This means that any error in error handling will propagate outwards
-	 *  instead of causing a setjmp() re-entry above.  The *only* actual
-	 *  errors that should happen here are allocation errors.
-	 */
-
-	DUK_DDD(DUK_DDDPRINT("error caught during protected duk_handle_safe_call()"));
-
-	DUK_ASSERT(thr->heap->lj.type == DUK_LJ_TYPE_THROW);
-	DUK_ASSERT(thr->callstack_top >= entry_callstack_top);
-	DUK_ASSERT(thr->catchstack_top >= entry_catchstack_top);
-
-	/* Note: either pointer may be NULL (at entry), so don't assert;
-	 * these are now restored twice which is OK.
-	 */
-	thr->heap->lj.jmpbuf_ptr = old_jmpbuf_ptr;
-
-	duk_hthread_catchstack_unwind(thr, entry_catchstack_top);
-	duk_hthread_callstack_unwind(thr, entry_callstack_top);
-	thr->valstack_bottom = thr->valstack + entry_valstack_bottom_index;
-
-	/* [ ... | (crud) ] */
-
-	/* FIXME: space in valstack?  see discussion in duk_handle_call. */
-	duk_push_tval(ctx, &thr->heap->lj.value1);
-
-	/* [ ... | (crud) errobj ] */
-
-	DUK_ASSERT(duk_get_top(ctx) >= 1);  /* at least errobj must be on stack */
-
-	/* check that the valstack has space for the final amount and any
-	 * intermediate space needed; this is unoptimal but should be safe
-	 */
-	duk_require_stack_top(ctx, idx_retbase + num_stack_rets);  /* final configuration */
-	duk_require_stack(ctx, num_stack_rets);
-
-	duk__safe_call_adjust_valstack(thr, idx_retbase, num_stack_rets, 1);  /* 1 = num actual 'return values' */
-
-	/* [ ... | ] or [ ... | errobj (M * undefined)] where M = num_stack_rets - 1 */
-
-#ifdef DUK_USE_DDDPRINT /*XXX:incorrect*/
-	DUK_DD(DUK_DDPRINT("protected safe_call error handling finished, thread dump:"));
-	DUK_DEBUG_DUMP_HTHREAD(thr);
+#if defined(DUK_USE_CPP_EXCEPTIONS)
+	try {
+#else
+	if (DUK_LIKELY(DUK_SETJMP(thr->heap->lj.jmpbuf_ptr->jb) == 0)) {
+		/* Success path. */
+#endif
+		DUK_DDD(DUK_DDDPRINT("safe_call setjmp catchpoint setup complete"));
+
+		duk__handle_safe_call_inner(thr,
+		                            func,
+		                            idx_retbase,
+		                            num_stack_rets,
+		                            entry_valstack_bottom_index,
+		                            entry_callstack_top,
+		                            entry_catchstack_top);
+
+		/* Longjmp state is kept clean in success path */
+		DUK_ASSERT(thr->heap->lj.type == DUK_LJ_TYPE_UNKNOWN);
+		DUK_ASSERT(thr->heap->lj.iserror == 0);
+		DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(&thr->heap->lj.value1));
+		DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(&thr->heap->lj.value2));
+
+#if !defined(DUK_USE_CPP_EXCEPTIONS)
+		/* Note: either pointer may be NULL (at entry), so don't assert */
+		thr->heap->lj.jmpbuf_ptr = old_jmpbuf_ptr;
 #endif
 
-	retval = DUK_EXEC_ERROR;
-	goto shrink_and_finished;
+		retval = DUK_EXEC_SUCCESS;
+#if defined(DUK_USE_CPP_EXCEPTIONS)
+	} catch (duk_internal_exception &exc) {
+#else
+	} else {
+		/* Error path. */
+#endif
+
+#if defined(DUK_USE_CPP_EXCEPTIONS)
+		DUK_UNREF(exc);
+#endif
+
+		duk__handle_safe_call_error(thr,
+		                            idx_retbase,
+		                            num_stack_rets,
+		                            entry_valstack_bottom_index,
+		                            entry_callstack_top,
+		                            entry_catchstack_top
+#if !defined(DUK_USE_CPP_EXCEPTIONS)
+		                            , old_jmpbuf_ptr
+#endif
+                                            );
+
+		/* Longjmp state is cleaned up by error handling */
+		DUK_ASSERT(thr->heap->lj.type == DUK_LJ_TYPE_UNKNOWN);
+		DUK_ASSERT(thr->heap->lj.iserror == 0);
+		DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(&thr->heap->lj.value1));
+		DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(&thr->heap->lj.value2));
+
+		retval = DUK_EXEC_ERROR;
+	}
+#if defined(DUK_USE_CPP_EXCEPTIONS)
+	catch (std::exception &exc) {
+		const char *what = exc.what();
+		if (!what) {
+			what = "unknown";
+		}
+		DUK_D(DUK_DPRINT("unexpected c++ std::exception (perhaps thrown by user code)"));
+		try {
+			DUK_ERROR(thr, DUK_ERR_API_ERROR, "caught invalid c++ std::exception '%s' (perhaps thrown by user code)", what);
+		} catch (duk_internal_exception exc) {
+			DUK_D(DUK_DPRINT("caught api error thrown from unexpected c++ std::exception"));
+			duk__handle_safe_call_error(thr,
+			                            idx_retbase,
+			                            num_stack_rets,
+			                            entry_valstack_bottom_index,
+			                            entry_callstack_top,
+			                            entry_catchstack_top);
+			retval = DUK_EXEC_ERROR;
+		}
+	} catch (...) {
+		DUK_D(DUK_DPRINT("unexpected c++ exception (perhaps thrown by user code)"));
+		try {
+			DUK_ERROR(thr, DUK_ERR_API_ERROR, "caught invalid c++ exception (perhaps thrown by user code)");
+		} catch (duk_internal_exception exc) {
+			DUK_D(DUK_DPRINT("caught api error thrown from unexpected c++ exception"));
+			duk__handle_safe_call_error(thr,
+			                            idx_retbase,
+			                            num_stack_rets,
+			                            entry_valstack_bottom_index,
+			                            entry_callstack_top,
+			                            entry_catchstack_top);
+			retval = DUK_EXEC_ERROR;
+		}
+	}
+#endif
+
+#if !defined(DUK_USE_CPP_EXCEPTIONS)
+	DUK_ASSERT(thr->heap->lj.jmpbuf_ptr == old_jmpbuf_ptr);  /* success/error path both do this */
+#endif
+
+	duk__handle_safe_call_shared(thr,
+	                             idx_retbase,
+	                             num_stack_rets,
+	                             entry_call_recursion_depth,
+	                             entry_curr_thread,
+	                             entry_thread_state,
+	                             entry_ptr_curr_pc);
 
-	/*
-	 *  Handle call (inside setjmp)
-	 */
+	return retval;
+}
 
- handle_call:
+DUK_LOCAL void duk__handle_safe_call_inner(duk_hthread *thr,
+                                           duk_safe_call_function func,
+                                           duk_idx_t idx_retbase,
+                                           duk_idx_t num_stack_rets,
+                                           duk_size_t entry_valstack_bottom_index,
+                                           duk_size_t entry_callstack_top,
+                                           duk_size_t entry_catchstack_top) {
+	duk_context *ctx;
+	duk_ret_t rc;
 
-	DUK_DDD(DUK_DDDPRINT("safe_call setjmp catchpoint setup complete"));
+	DUK_ASSERT(thr != NULL);
+	ctx = (duk_context *) thr;
+	DUK_ASSERT_CTX_VALID(ctx);
+	DUK_UNREF(entry_valstack_bottom_index);
+	DUK_UNREF(entry_callstack_top);
+	DUK_UNREF(entry_catchstack_top);
 
 	/*
 	 *  Thread state check and book-keeping.
@@ -42342,7 +58832,7 @@ duk_int_t duk_handle_safe_call(duk_hthread *thr,
 	DUK_DDD(DUK_DDDPRINT("safe_call, func rc=%ld", (long) rc));
 
 	/*
-	 *  Valstack manipulation for results
+	 *  Valstack manipulation for results.
 	 */
 
 	/* we're running inside the caller's activation, so no change in call/catch stack or valstack bottom */
@@ -42359,44 +58849,114 @@ duk_int_t duk_handle_safe_call(duk_hthread *thr,
 	DUK_ASSERT(rc >= 0);
 
 	if (duk_get_top(ctx) < rc) {
-		DUK_ERROR(thr, DUK_ERR_API_ERROR, "not enough stack values for safe_call rc");
+		DUK_ERROR_API(thr, "not enough stack values for safe_call rc");
 	}
 
+	DUK_ASSERT(thr->catchstack_top == entry_catchstack_top);  /* no need to unwind */
+	DUK_ASSERT(thr->callstack_top == entry_callstack_top);
+
 	duk__safe_call_adjust_valstack(thr, idx_retbase, num_stack_rets, rc);
+	return;
 
-	/* Note: no need from callstack / catchstack shrink check */
-	retval = DUK_EXEC_SUCCESS;
-	goto finished;
+ thread_state_error:
+	DUK_ERROR(thr, DUK_ERR_TYPE_ERROR, "invalid thread state for safe_call (%ld)", (long) thr->state);
+	DUK_UNREACHABLE();
+}
+
+DUK_LOCAL void duk__handle_safe_call_error(duk_hthread *thr,
+                                           duk_idx_t idx_retbase,
+                                           duk_idx_t num_stack_rets,
+                                           duk_size_t entry_valstack_bottom_index,
+                                           duk_size_t entry_callstack_top,
+                                           duk_size_t entry_catchstack_top
+#if !defined(DUK_USE_CPP_EXCEPTIONS)
+                                           , duk_jmpbuf *old_jmpbuf_ptr
+#endif
+                                           ) {
+	duk_context *ctx;
+
+	DUK_ASSERT(thr != NULL);
+	ctx = (duk_context *) thr;
+	DUK_ASSERT_CTX_VALID(ctx);
+
+	/*
+	 *  Error during call.  The error value is at heap->lj.value1.
+	 *
+	 *  The very first thing we do is restore the previous setjmp catcher.
+	 *  This means that any error in error handling will propagate outwards
+	 *  instead of causing a setjmp() re-entry above.
+	 */
+
+	DUK_DDD(DUK_DDDPRINT("error caught during protected duk_handle_safe_call()"));
+
+	/* Other longjmp types are handled by executor before propagating
+	 * the error here.
+	 */
+	DUK_ASSERT(thr->heap->lj.type == DUK_LJ_TYPE_THROW);
+	DUK_ASSERT(thr->callstack_top >= entry_callstack_top);
+	DUK_ASSERT(thr->catchstack_top >= entry_catchstack_top);
+
+	/* Note: either pointer may be NULL (at entry), so don't assert. */
+#if !defined(DUK_USE_CPP_EXCEPTIONS)
+	thr->heap->lj.jmpbuf_ptr = old_jmpbuf_ptr;
+#endif
 
- shrink_and_finished:
-	/* these are "soft" shrink checks, whose failures are ignored */
-	/* XXX: would be nice if fast path was inlined */
+	DUK_ASSERT(thr->catchstack_top >= entry_catchstack_top);
+	DUK_ASSERT(thr->callstack_top >= entry_callstack_top);
+	duk_hthread_catchstack_unwind(thr, entry_catchstack_top);
 	duk_hthread_catchstack_shrink_check(thr);
+	duk_hthread_callstack_unwind(thr, entry_callstack_top);
 	duk_hthread_callstack_shrink_check(thr);
-	goto finished;
+	thr->valstack_bottom = thr->valstack + entry_valstack_bottom_index;
 
- finished:
-	/* Note: either pointer may be NULL (at entry), so don't assert */
-	thr->heap->lj.jmpbuf_ptr = old_jmpbuf_ptr;
+	/* [ ... | (crud) ] */
+
+	/* XXX: space in valstack?  see discussion in duk_handle_call_xxx(). */
+	duk_push_tval(ctx, &thr->heap->lj.value1);
+
+	/* [ ... | (crud) errobj ] */
+
+	DUK_ASSERT(duk_get_top(ctx) >= 1);  /* at least errobj must be on stack */
+
+	/* check that the valstack has space for the final amount and any
+	 * intermediate space needed; this is unoptimal but should be safe
+	 */
+	duk_require_stack_top(ctx, idx_retbase + num_stack_rets);  /* final configuration */
+	duk_require_stack(ctx, num_stack_rets);
+
+	duk__safe_call_adjust_valstack(thr, idx_retbase, num_stack_rets, 1);  /* 1 = num actual 'return values' */
+
+	/* [ ... | ] or [ ... | errobj (M * undefined)] where M = num_stack_rets - 1 */
 
-	/* These are just convenience "wiping" of state */
+	/* These are just convenience "wiping" of state.  Side effects should
+	 * not be an issue here: thr->heap and thr->heap->lj have a stable
+	 * pointer.  Finalizer runs etc capture even out-of-memory errors so
+	 * nothing should throw here.
+	 */
 	thr->heap->lj.type = DUK_LJ_TYPE_UNKNOWN;
 	thr->heap->lj.iserror = 0;
+	DUK_TVAL_SET_UNDEFINED_UPDREF(thr, &thr->heap->lj.value1);  /* side effects */
+	DUK_TVAL_SET_UNDEFINED_UPDREF(thr, &thr->heap->lj.value2);  /* side effects */
+}
 
-	/* Side effects should not be an issue here: tv_tmp is local and
-	 * thr->heap (and thr->heap->lj) have a stable pointer.  Finalizer
-	 * runs etc capture even out-of-memory errors so nothing should
-	 * throw here.
-	 */
-	DUK_TVAL_SET_TVAL(&tv_tmp, &thr->heap->lj.value1);
-	DUK_TVAL_SET_UNDEFINED_UNUSED(&thr->heap->lj.value1);
-	DUK_TVAL_DECREF(thr, &tv_tmp);
+DUK_LOCAL void duk__handle_safe_call_shared(duk_hthread *thr,
+                                            duk_idx_t idx_retbase,
+                                            duk_idx_t num_stack_rets,
+                                            duk_int_t entry_call_recursion_depth,
+                                            duk_hthread *entry_curr_thread,
+                                            duk_uint_fast8_t entry_thread_state,
+                                            duk_instr_t **entry_ptr_curr_pc) {
+	duk_context *ctx;
 
-	DUK_TVAL_SET_TVAL(&tv_tmp, &thr->heap->lj.value2);
-	DUK_TVAL_SET_UNDEFINED_UNUSED(&thr->heap->lj.value2);
-	DUK_TVAL_DECREF(thr, &tv_tmp);
+	DUK_ASSERT(thr != NULL);
+	ctx = (duk_context *) thr;
+	DUK_ASSERT_CTX_VALID(ctx);
+	DUK_UNREF(ctx);
+	DUK_UNREF(idx_retbase);
+	DUK_UNREF(num_stack_rets);
 
-	DUK_DDD(DUK_DDDPRINT("setjmp catchpoint torn down"));
+	/* Restore entry thread executor curr_pc stack frame pointer. */
+	thr->ptr_curr_pc = entry_ptr_curr_pc;
 
 	/* XXX: because we unwind stacks above, thr->heap->curr_thread is at
 	 * risk of pointing to an already freed thread.  This was indeed the
@@ -42416,12 +58976,13 @@ duk_int_t duk_handle_safe_call(duk_hthread *thr,
 	/* stack discipline consistency check */
 	DUK_ASSERT(duk_get_top(ctx) == idx_retbase + num_stack_rets);
 
-	return retval;
+	/* A debugger forced interrupt check is not needed here, as
+	 * problematic safe calls are not caused by side effects.
+	 */
 
- thread_state_error:
-	DUK_ERROR(thr, DUK_ERR_TYPE_ERROR, "invalid thread state for safe_call (%ld)", (long) thr->state);
-	DUK_UNREACHABLE();
-	return DUK_EXEC_ERROR;  /* never executed */
+#if defined(DUK_USE_INTERRUPT_COUNTER) && defined(DUK_USE_DEBUG)
+	duk__interrupt_fixup(thr, entry_curr_thread);
+#endif
 }
 
 /*
@@ -42443,11 +59004,16 @@ duk_int_t duk_handle_safe_call(duk_hthread *thr,
  *  The callstack of the target contains an earlier Ecmascript call in case
  *  of an Ecmascript-to-Ecmascript call (whose idx_retval is updated), or
  *  is empty in case of an initial Duktape.Thread.resume().
+ *
+ *  The first thing to do here is to figure out whether an ecma-to-ecma
+ *  call is actually possible.  It's not always the case if the target is
+ *  a bound function; the final function may be native.  In that case,
+ *  return an error so caller can fall back to a normal call path.
  */
 
-void duk_handle_ecma_call_setup(duk_hthread *thr,
-                                duk_idx_t num_stack_args,
-                                duk_small_uint_t call_flags) {
+DUK_INTERNAL duk_bool_t duk_handle_ecma_call_setup(duk_hthread *thr,
+                                                   duk_idx_t num_stack_args,
+                                                   duk_small_uint_t call_flags) {
 	duk_context *ctx = (duk_context *) thr;
 	duk_size_t entry_valstack_bottom_index;
 	duk_idx_t idx_func;     /* valstack index of 'func' and retval (relative to entry valstack_bottom) */
@@ -42455,9 +59021,11 @@ void duk_handle_ecma_call_setup(duk_hthread *thr,
 	duk_idx_t nargs;        /* # argument registers target function wants (< 0 => never for ecma calls) */
 	duk_idx_t nregs;        /* # total registers target function wants on entry (< 0 => never for ecma calls) */
 	duk_hobject *func;      /* 'func' on stack (borrowed reference) */
+	duk_tval *tv_func;      /* duk_tval ptr for 'func' on stack (borrowed reference) */
 	duk_activation *act;
 	duk_hobject *env;
 	duk_bool_t use_tailcall;
+	duk_instr_t **entry_ptr_curr_pc;
 
 	DUK_ASSERT(thr != NULL);
 	DUK_ASSERT(ctx != NULL);
@@ -42473,11 +59041,19 @@ void duk_handle_ecma_call_setup(duk_hthread *thr,
 	           (thr->state == DUK_HTHREAD_STATE_RUNNING &&
 	            thr->heap->curr_thread == thr));
 
-	/* if a tailcall:
+	/* If thr->ptr_curr_pc is set, sync curr_pc to act->pc.  Then NULL
+	 * thr->ptr_curr_pc so that it's not accidentally used with an incorrect
+	 * activation when side effects occur.  If we end up not making the
+	 * call we must restore the value.
+	 */
+	entry_ptr_curr_pc = thr->ptr_curr_pc;
+	duk_hthread_sync_and_null_currpc(thr);
+
+	/* if a tail call:
 	 *   - an Ecmascript activation must be on top of the callstack
 	 *   - there cannot be any active catchstack entries
 	 */
-#ifdef DUK_USE_ASSERTIONS
+#if defined(DUK_USE_ASSERTIONS)
 	if (call_flags & DUK_CALL_FLAG_IS_TAILCALL) {
 		duk_size_t our_callstack_index;
 		duk_size_t i;
@@ -42486,8 +59062,8 @@ void duk_handle_ecma_call_setup(duk_hthread *thr,
 		our_callstack_index = thr->callstack_top - 1;
 		DUK_ASSERT_DISABLE(our_callstack_index >= 0);
 		DUK_ASSERT(our_callstack_index < thr->callstack_size);
-		DUK_ASSERT(thr->callstack[our_callstack_index].func != NULL);
-		DUK_ASSERT(DUK_HOBJECT_IS_COMPILEDFUNCTION(thr->callstack[our_callstack_index].func));
+		DUK_ASSERT(DUK_ACT_GET_FUNC(thr->callstack + our_callstack_index) != NULL);
+		DUK_ASSERT(DUK_HOBJECT_IS_COMPILEDFUNCTION(DUK_ACT_GET_FUNC(thr->callstack + our_callstack_index)));
 
 		/* No entry in the catchstack which would actually catch a
 		 * throw can refer to the callstack entry being reused.
@@ -42503,6 +59079,7 @@ void duk_handle_ecma_call_setup(duk_hthread *thr,
 #endif  /* DUK_USE_ASSERTIONS */
 
 	entry_valstack_bottom_index = (duk_size_t) (thr->valstack_bottom - thr->valstack);
+	/* XXX: rework */
 	idx_func = duk_normalize_index(thr, -num_stack_args - 2);
 	idx_args = idx_func + 2;
 
@@ -42518,41 +59095,39 @@ void duk_handle_ecma_call_setup(duk_hthread *thr,
 	                   (long) idx_args,
 	                   (long) entry_valstack_bottom_index));
 
-#ifdef DUK_USE_DDDPRINT /*XXX:incorrect*/
-	DUK_D(DUK_DPRINT("callstack before call setup:"));
-	DUK_DEBUG_DUMP_CALLSTACK(thr);
-#endif
-
-	if (idx_func < 0 || idx_args < 0) {
+	if (DUK_UNLIKELY(idx_func < 0 || idx_args < 0)) {
 		/* XXX: assert? compiler is responsible for this never happening */
-		DUK_ERROR(thr, DUK_ERR_API_ERROR, DUK_STR_INVALID_CALL_ARGS);
+		DUK_ERROR_API(thr, DUK_STR_INVALID_CALL_ARGS);
 	}
 
 	/*
-	 *  Check the function type, handle bound function chains,
-	 *  and prepare parameters for the rest of the call handling.
-	 *  Also figure out the effective 'this' binding, which replaces
-	 *  the current value at idx_func + 1.
+	 *  Check the function type, handle bound function chains, and prepare
+	 *  parameters for the rest of the call handling.  Also figure out the
+	 *  effective 'this' binding, which replaces the current value at
+	 *  idx_func + 1.
+	 *
+	 *  If the target function is a 'bound' one, follow the chain of 'bound'
+	 *  functions until a non-bound function is found.  During this process,
+	 *  bound arguments are 'prepended' to existing ones, and the "this"
+	 *  binding is overridden.  See E5 Section 15.3.4.5.1.
 	 *
-	 *  If the target function is a 'bound' one, follow the chain
-	 *  of 'bound' functions until a non-bound function is found.
-	 *  During this process, bound arguments are 'prepended' to
-	 *  existing ones, and the "this" binding is overridden.
-	 *  See E5 Section 15.3.4.5.1.
+	 *  If the final target function cannot be handled by an ecma-to-ecma
+	 *  call, return to the caller with a return value indicating this case.
+	 *  The bound chain is resolved and the caller can resume with a plain
+	 *  function call.
 	 */
 
-	if (!duk_is_callable(thr, idx_func)) {
-		DUK_ERROR(thr, DUK_ERR_TYPE_ERROR, DUK_STR_NOT_CALLABLE);
+	func = duk__nonbound_func_lookup(ctx, idx_func, &num_stack_args, &tv_func, call_flags);
+	if (func == NULL || !DUK_HOBJECT_IS_COMPILEDFUNCTION(func)) {
+		DUK_DDD(DUK_DDDPRINT("final target is a lightfunc/nativefunc, cannot do ecma-to-ecma call"));
+		thr->ptr_curr_pc = entry_ptr_curr_pc;
+		return 0;
 	}
-	func = duk_get_hobject(thr, idx_func);
-	DUK_ASSERT(func != NULL);
+	/* XXX: tv_func is not actually needed */
 
-	if (DUK_HOBJECT_HAS_BOUND(func)) {
-		/* slow path for bound functions */
-		duk__handle_bound_chain_for_call(thr, idx_func, &num_stack_args, &func, call_flags & DUK_CALL_FLAG_CONSTRUCTOR_CALL);
-	}
+	DUK_ASSERT(func != NULL);
 	DUK_ASSERT(!DUK_HOBJECT_HAS_BOUND(func));
-	DUK_ASSERT(DUK_HOBJECT_IS_COMPILEDFUNCTION(func));  /* caller must ensure this */
+	DUK_ASSERT(DUK_HOBJECT_IS_COMPILEDFUNCTION(func));
 
 	duk__coerce_effective_this_binding(thr, func, idx_func + 1);
 	DUK_DDD(DUK_DDDPRINT("effective 'this' binding is: %!T",
@@ -42567,7 +59142,7 @@ void duk_handle_ecma_call_setup(duk_hthread *thr,
 	/*
 	 *  Preliminary activation record and valstack manipulation.
 	 *  The concrete actions depend on whether the we're dealing
-	 *  with a tailcall (reuse an existing activation), a resume,
+	 *  with a tail call (reuse an existing activation), a resume,
 	 *  or a normal call.
 	 *
 	 *  The basic actions, in varying order, are:
@@ -42598,17 +59173,16 @@ void duk_handle_ecma_call_setup(duk_hthread *thr,
 		act = thr->callstack + thr->callstack_top - 1;
 		if (act->flags & DUK_ACT_FLAG_PREVENT_YIELD) {
 			/* See: test-bug-tailcall-preventyield-assert.c. */
-			DUK_DDD(DUK_DDDPRINT("tailcall prevented by current activation having DUK_ACT_FLAG_PREVENTYIELD"));
+			DUK_DDD(DUK_DDDPRINT("tail call prevented by current activation having DUK_ACT_FLAG_PREVENTYIELD"));
 			use_tailcall = 0;
 		} else if (DUK_HOBJECT_HAS_NOTAIL(func)) {
-			DUK_D(DUK_DPRINT("tailcall prevented by function having a notail flag"));
+			DUK_D(DUK_DPRINT("tail call prevented by function having a notail flag"));
 			use_tailcall = 0;
 		}
 	}
 
 	if (use_tailcall) {
 		duk_tval *tv1, *tv2;
-		duk_tval tv_tmp;
 		duk_size_t cs_index;
 		duk_int_t i_stk;  /* must be signed for loop structure */
 		duk_idx_t i_arg;
@@ -42620,10 +59194,10 @@ void duk_handle_ecma_call_setup(duk_hthread *thr,
 		 *  the current activation (or simulate an unwind).  In particular, the
 		 *  current activation must be closed, otherwise something like
 		 *  test-bug-reduce-judofyr.js results.  Also catchstack needs be unwound
-		 *  because there may be non-error-catching label entries in valid tailcalls.
+		 *  because there may be non-error-catching label entries in valid tail calls.
 		 */
 
-		DUK_DDD(DUK_DDDPRINT("is tailcall, reusing activation at callstack top, at index %ld",
+		DUK_DDD(DUK_DDDPRINT("is tail call, reusing activation at callstack top, at index %ld",
 		                     (long) (thr->callstack_top - 1)));
 
 		/* 'act' already set above */
@@ -42656,18 +59230,25 @@ void duk_handle_ecma_call_setup(duk_hthread *thr,
 
 		/* Start filling in the activation */
 		act->func = func;  /* don't want an intermediate exposed state with func == NULL */
-#ifdef DUK_USE_NONSTD_FUNC_CALLER_PROPERTY
+#if defined(DUK_USE_NONSTD_FUNC_CALLER_PROPERTY)
 		act->prev_caller = NULL;
 #endif
-		act->pc = 0;       /* don't want an intermediate exposed state with invalid pc */
-#ifdef DUK_USE_REFERENCE_COUNTING
+		DUK_ASSERT(func != NULL);
+		DUK_ASSERT(DUK_HOBJECT_HAS_COMPILEDFUNCTION(func));
+		/* don't want an intermediate exposed state with invalid pc */
+		act->curr_pc = DUK_HCOMPILEDFUNCTION_GET_CODE_BASE(thr->heap, (duk_hcompiledfunction *) func);
+#if defined(DUK_USE_DEBUGGER_SUPPORT)
+		act->prev_line = 0;
+#endif
+		DUK_TVAL_SET_OBJECT(&act->tv_func, func);  /* borrowed, no refcount */
+#if defined(DUK_USE_REFERENCE_COUNTING)
 		DUK_HOBJECT_INCREF(thr, func);
 		act = thr->callstack + thr->callstack_top - 1;  /* side effects (currently none though) */
 #endif
 
-#ifdef DUK_USE_NONSTD_FUNC_CALLER_PROPERTY
-#ifdef DUK_USE_TAILCALL
-#error incorrect options: tailcalls enabled with function caller property
+#if defined(DUK_USE_NONSTD_FUNC_CALLER_PROPERTY)
+#if defined(DUK_USE_TAILCALL)
+#error incorrect options: tail calls enabled with function caller property
 #endif
 		/* XXX: this doesn't actually work properly for tail calls, so
 		 * tail calls are disabled when DUK_USE_NONSTD_FUNC_CALLER_PROPERTY
@@ -42679,12 +59260,11 @@ void duk_handle_ecma_call_setup(duk_hthread *thr,
 
 		act->flags = (DUK_HOBJECT_HAS_STRICT(func) ?
 		              DUK_ACT_FLAG_STRICT | DUK_ACT_FLAG_TAILCALLED :
-	        	      DUK_ACT_FLAG_TAILCALLED);
+		              DUK_ACT_FLAG_TAILCALLED);
 
-		DUK_ASSERT(act->func == func);      /* already updated */
+		DUK_ASSERT(DUK_ACT_GET_FUNC(act) == func);      /* already updated */
 		DUK_ASSERT(act->var_env == NULL);   /* already NULLed (by unwind) */
 		DUK_ASSERT(act->lex_env == NULL);   /* already NULLed (by unwind) */
-		DUK_ASSERT(act->pc == 0);           /* already zeroed */
 		act->idx_bottom = entry_valstack_bottom_index;  /* tail call -> reuse current "frame" */
 		DUK_ASSERT(nregs >= 0);
 #if 0  /* topmost activation idx_retval is considered garbage, no need to init */
@@ -42699,7 +59279,7 @@ void duk_handle_ecma_call_setup(duk_hthread *thr,
 		 *       [ ... this_old | (crud) func this_new arg1 ... argN ]
 		 *  -->  [ ... this_new | arg1 ... argN ]
 		 *
-		 *  For tailcalling to work properly, the valstack bottom must not grow
+		 *  For tail calling to work properly, the valstack bottom must not grow
 		 *  here; otherwise crud would accumulate on the valstack.
 		 */
 
@@ -42707,11 +59287,8 @@ void duk_handle_ecma_call_setup(duk_hthread *thr,
 		tv2 = thr->valstack_bottom + idx_func + 1;
 		DUK_ASSERT(tv1 >= thr->valstack && tv1 < thr->valstack_top);  /* tv1 is -below- valstack_bottom */
 		DUK_ASSERT(tv2 >= thr->valstack_bottom && tv2 < thr->valstack_top);
-		DUK_TVAL_SET_TVAL(&tv_tmp, tv1);
-		DUK_TVAL_SET_TVAL(tv1, tv2);
-		DUK_TVAL_INCREF(thr, tv1);
-		DUK_TVAL_DECREF(thr, &tv_tmp);  /* side effects */
-		
+		DUK_TVAL_SET_TVAL_UPDREF(thr, tv1, tv2);  /* side effects */
+
 		for (i_arg = 0; i_arg < idx_args; i_arg++) {
 			/* XXX: block removal API primitive */
 			/* Note: 'func' is popped from valstack here, but it is
@@ -42723,30 +59300,12 @@ void duk_handle_ecma_call_setup(duk_hthread *thr,
 		idx_args = 0;
 
 		/* [ ... this_new | arg1 ... argN ] */
-
-		/* now we can also do the valstack resize check */
-
-		duk_require_valstack_resize((duk_context *) thr,
-		                            (thr->valstack_bottom - thr->valstack) +         /* bottom of current func */
-		                                idx_args +                                   /* bottom of new func (always 0 here) */
-		                                nregs +                                      /* num entries of new func at entry */
-		                                DUK_VALSTACK_INTERNAL_EXTRA,                 /* + spare => min_new_size */
-		                            1);                                              /* allow_shrink */
 	} else {
-		DUK_DDD(DUK_DDDPRINT("not a tailcall, pushing a new activation to callstack, to index %ld",
+		DUK_DDD(DUK_DDDPRINT("not a tail call, pushing a new activation to callstack, to index %ld",
 		                     (long) (thr->callstack_top)));
 
 		duk_hthread_callstack_grow(thr);
 
-		/* func wants args clamped to 'nargs' */
-
-		duk_require_valstack_resize((duk_context *) thr,
-		                            (thr->valstack_bottom - thr->valstack) +         /* bottom of current func */
-		                                idx_args +                                   /* bottom of new func */
-		                                nregs +                                      /* num entries of new func at entry */
-		                                DUK_VALSTACK_INTERNAL_EXTRA,                 /* + spare => min_new_size */
-		                            1);                                              /* allow_shrink */
-
 		if (call_flags & DUK_CALL_FLAG_IS_RESUME) {
 			DUK_DDD(DUK_DDDPRINT("is resume -> no update to current activation (may not even exist)"));
 		} else {
@@ -42754,8 +59313,8 @@ void duk_handle_ecma_call_setup(duk_hthread *thr,
 			DUK_ASSERT(thr->callstack_top < thr->callstack_size);
 			DUK_ASSERT(thr->callstack_top >= 1);
 			act = thr->callstack + thr->callstack_top - 1;
-			DUK_ASSERT(act->func != NULL);
-			DUK_ASSERT(DUK_HOBJECT_IS_COMPILEDFUNCTION(act->func));
+			DUK_ASSERT(DUK_ACT_GET_FUNC(act) != NULL);
+			DUK_ASSERT(DUK_HOBJECT_IS_COMPILEDFUNCTION(DUK_ACT_GET_FUNC(act)));
 			act->idx_retval = entry_valstack_bottom_index + idx_func;
 		}
 
@@ -42770,39 +59329,40 @@ void duk_handle_ecma_call_setup(duk_hthread *thr,
 
 		act->flags = (DUK_HOBJECT_HAS_STRICT(func) ?
 		              DUK_ACT_FLAG_STRICT :
-	        	      0);
+		              0);
 		act->func = func;
 		act->var_env = NULL;
 		act->lex_env = NULL;
-#ifdef DUK_USE_NONSTD_FUNC_CALLER_PROPERTY
+#if defined(DUK_USE_NONSTD_FUNC_CALLER_PROPERTY)
 		act->prev_caller = NULL;
 #endif
-		act->pc = 0;
+		DUK_ASSERT(func != NULL);
+		DUK_ASSERT(DUK_HOBJECT_HAS_COMPILEDFUNCTION(func));
+		act->curr_pc = DUK_HCOMPILEDFUNCTION_GET_CODE_BASE(thr->heap, (duk_hcompiledfunction *) func);
+#if defined(DUK_USE_DEBUGGER_SUPPORT)
+		act->prev_line = 0;
+#endif
 		act->idx_bottom = entry_valstack_bottom_index + idx_args;
 		DUK_ASSERT(nregs >= 0);
 #if 0  /* topmost activation idx_retval is considered garbage, no need to init */
 		act->idx_retval = 0;
 #endif
+		DUK_TVAL_SET_OBJECT(&act->tv_func, func);  /* borrowed, no refcount */
 
 		DUK_HOBJECT_INCREF(thr, func);  /* act->func */
 
-#ifdef DUK_USE_NONSTD_FUNC_CALLER_PROPERTY
+#if defined(DUK_USE_NONSTD_FUNC_CALLER_PROPERTY)
 		duk__update_func_caller_prop(thr, func);
 		act = thr->callstack + thr->callstack_top - 1;
 #endif
 	}
 
-	/* [... func this arg1 ... argN]  (not tail call)
-	 * [this | arg1 ... argN]         (tail call)
+	/* [ ... func this arg1 ... argN ]  (not tail call)
+	 * [ this | arg1 ... argN ]         (tail call)
 	 *
 	 * idx_args updated to match
 	 */
 
-#ifdef DUK_USE_DDDPRINT /*XXX:incorrect*/
-	DUK_D(DUK_DPRINT("pushed new activation:"));
-	DUK_DEBUG_DUMP_ACTIVATION(thr, thr->callstack + thr->callstack_top - 1);
-#endif
-
 	/*
 	 *  Environment record creation and 'arguments' object creation.
 	 *  Named function expression name binding is handled by the
@@ -42812,6 +59372,8 @@ void duk_handle_ecma_call_setup(duk_hthread *thr,
 	 *  Delayed creation (on demand) is handled in duk_js_var.c.
 	 */
 
+	/* XXX: unify handling with native call. */
+
 	DUK_ASSERT(!DUK_HOBJECT_HAS_BOUND(func));  /* bound function chain has already been resolved */
 
 	if (!DUK_HOBJECT_HAS_NEWENV(func)) {
@@ -42839,13 +59401,17 @@ void duk_handle_ecma_call_setup(duk_hthread *thr,
 	env = duk_create_activation_environment_record(thr, func, act->idx_bottom);
 	DUK_ASSERT(env != NULL);
 
-	/* [... arg1 ... argN envobj] */
+	/* [ ... arg1 ... argN envobj ] */
 
+	/* original input stack before nargs/nregs handling must be
+	 * intact for 'arguments' object
+	 */
 	DUK_ASSERT(DUK_HOBJECT_HAS_CREATEARGS(func));
 	duk__handle_createargs_for_call(thr, func, env, num_stack_args);
 
-	/* [... arg1 ... argN envobj] */
+	/* [ ... arg1 ... argN envobj ] */
 
+	act = thr->callstack + thr->callstack_top - 1;
 	act->lex_env = env;
 	act->var_env = env;
 	DUK_HOBJECT_INCREF(thr, act->lex_env);
@@ -42853,22 +59419,18 @@ void duk_handle_ecma_call_setup(duk_hthread *thr,
 	duk_pop(ctx);
 
  env_done:
-	/* [... arg1 ... argN] */
+	/* [ ... arg1 ... argN ] */
 
 	/*
 	 *  Setup value stack: clamp to 'nargs', fill up to 'nregs'
 	 */
 
-	/* XXX: replace with a single operation */
-
-	DUK_ASSERT(nregs >= 0);
-	duk_set_top(ctx, idx_args + nargs);  /* clamp anything above nargs */
-	duk_set_top(ctx, idx_args + nregs);  /* extend with undefined */
-
-#ifdef DUK_USE_DDDPRINT /*XXX:incorrect*/
-	DUK_D(DUK_DPRINT("callstack after call setup:"));
-	DUK_DEBUG_DUMP_CALLSTACK(thr);
-#endif
+	duk__adjust_valstack_and_top(thr,
+	                             num_stack_args,
+	                             idx_args,
+	                             nregs,
+	                             nargs,
+	                             func);
 
 	/*
 	 *  Shift to new valstack_bottom.
@@ -42884,6 +59446,8 @@ void duk_handle_ecma_call_setup(duk_hthread *thr,
 	 *  Return to bytecode executor, which will resume execution from
 	 *  the topmost activation.
 	 */
+
+	return 1;
 }
 #line 1 "duk_js_compiler.c"
 /*
@@ -42905,7 +59469,7 @@ void duk_handle_ecma_call_setup(duk_hthread *thr,
  *  Recursion limits are in key functions to prevent arbitrary C recursion:
  *  function body parsing, statement parsing, and expression parsing.
  *
- *  See doc/compiler.txt for discussion on the design.
+ *  See doc/compiler.rst for discussion on the design.
  *
  *  A few typing notes:
  *
@@ -42926,10 +59490,15 @@ void duk_handle_ecma_call_setup(duk_hthread *thr,
 /* XXX: hack, remove when const lookup is not O(n) */
 #define DUK__GETCONST_MAX_CONSTS_CHECK    256
 
-/* these limits are based on bytecode limits */
-#define DUK__MAX_CONSTS                   (DUK_BC_BC_MAX + 1)
-#define DUK__MAX_FUNCS                    (DUK_BC_BC_MAX + 1)
-#define DUK__MAX_TEMPS                    (DUK_BC_BC_MAX + 1)
+/* These limits are based on bytecode limits.  Max temps is limited
+ * by duk_hcompiledfunction nargs/nregs fields being 16 bits.
+ */
+#define DUK__MAX_CONSTS                   DUK_BC_BC_MAX
+#define DUK__MAX_FUNCS                    DUK_BC_BC_MAX
+#define DUK__MAX_TEMPS                    0xffffL
+
+/* Initial bytecode size allocation. */
+#define DUK__BC_INITIAL_INSTS 256
 
 #define DUK__RECURSION_INCREASE(comp_ctx,thr)  do { \
 		DUK_DDD(DUK_DDDPRINT("RECURSION INCREASE: %s:%ld", (const char *) DUK_FILE_MACRO, (long) DUK_LINE_MACRO)); \
@@ -42964,139 +59533,148 @@ typedef struct {
  */
 
 /* lexing */
-static void duk__advance_helper(duk_compiler_ctx *comp_ctx, duk_small_int_t expect);
-static void duk__advance_expect(duk_compiler_ctx *comp_ctx, duk_small_int_t expect);
-static void duk__advance(duk_compiler_ctx *ctx);
+DUK_LOCAL_DECL void duk__advance_helper(duk_compiler_ctx *comp_ctx, duk_small_int_t expect);
+DUK_LOCAL_DECL void duk__advance_expect(duk_compiler_ctx *comp_ctx, duk_small_int_t expect);
+DUK_LOCAL_DECL void duk__advance(duk_compiler_ctx *ctx);
 
 /* function helpers */
-static void duk__init_func_valstack_slots(duk_compiler_ctx *comp_ctx);
-static void duk__reset_func_for_pass2(duk_compiler_ctx *comp_ctx);
-static void duk__init_varmap_and_prologue_for_pass2(duk_compiler_ctx *comp_ctx, duk_reg_t *out_stmt_value_reg);
-static void duk__convert_to_func_template(duk_compiler_ctx *comp_ctx);
-static duk_int_t duk__cleanup_varmap(duk_compiler_ctx *comp_ctx);
+DUK_LOCAL_DECL void duk__init_func_valstack_slots(duk_compiler_ctx *comp_ctx);
+DUK_LOCAL_DECL void duk__reset_func_for_pass2(duk_compiler_ctx *comp_ctx);
+DUK_LOCAL_DECL void duk__init_varmap_and_prologue_for_pass2(duk_compiler_ctx *comp_ctx, duk_reg_t *out_stmt_value_reg);
+DUK_LOCAL_DECL void duk__convert_to_func_template(duk_compiler_ctx *comp_ctx, duk_bool_t force_no_namebind);
+DUK_LOCAL_DECL duk_int_t duk__cleanup_varmap(duk_compiler_ctx *comp_ctx);
 
 /* code emission */
-static duk_int_t duk__get_current_pc(duk_compiler_ctx *comp_ctx);
-static duk_compiler_instr *duk__get_instr_ptr(duk_compiler_ctx *comp_ctx, duk_int_t pc);
-static void duk__emit(duk_compiler_ctx *comp_ctx, duk_instr_t ins);
+DUK_LOCAL_DECL duk_int_t duk__get_current_pc(duk_compiler_ctx *comp_ctx);
+DUK_LOCAL_DECL duk_compiler_instr *duk__get_instr_ptr(duk_compiler_ctx *comp_ctx, duk_int_t pc);
+DUK_LOCAL_DECL void duk__emit(duk_compiler_ctx *comp_ctx, duk_instr_t ins);
 #if 0  /* unused */
-static void duk__emit_op_only(duk_compiler_ctx *comp_ctx, duk_small_uint_t op);
+DUK_LOCAL_DECL void duk__emit_op_only(duk_compiler_ctx *comp_ctx, duk_small_uint_t op);
 #endif
-static void duk__emit_a_b_c(duk_compiler_ctx *comp_ctx, duk_small_uint_t op_flags, duk_regconst_t a, duk_regconst_t b, duk_regconst_t c);
-static void duk__emit_a_b(duk_compiler_ctx *comp_ctx, duk_small_uint_t op_flags, duk_regconst_t a, duk_regconst_t b);
+DUK_LOCAL_DECL void duk__emit_a_b_c(duk_compiler_ctx *comp_ctx, duk_small_uint_t op_flags, duk_regconst_t a, duk_regconst_t b, duk_regconst_t c);
+DUK_LOCAL_DECL void duk__emit_a_b(duk_compiler_ctx *comp_ctx, duk_small_uint_t op_flags, duk_regconst_t a, duk_regconst_t b);
 #if 0  /* unused */
-static void duk__emit_a(duk_compiler_ctx *comp_ctx, duk_small_uint_t op_flags, duk_regconst_t a);
-#endif
-static void duk__emit_a_bc(duk_compiler_ctx *comp_ctx, duk_small_uint_t op_flags, duk_regconst_t a, duk_regconst_t bc);
-static void duk__emit_abc(duk_compiler_ctx *comp_ctx, duk_small_uint_t op, duk_regconst_t abc);
-static void duk__emit_extraop_b_c(duk_compiler_ctx *comp_ctx, duk_small_uint_t extraop_flags, duk_regconst_t b, duk_regconst_t c);
-static void duk__emit_extraop_b(duk_compiler_ctx *comp_ctx, duk_small_uint_t extraop_flags, duk_regconst_t b);
-static void duk__emit_extraop_bc(duk_compiler_ctx *comp_ctx, duk_small_uint_t extraop, duk_regconst_t bc);
-static void duk__emit_extraop_only(duk_compiler_ctx *comp_ctx, duk_small_uint_t extraop_flags);
-static void duk__emit_load_int32(duk_compiler_ctx *comp_ctx, duk_reg_t reg, duk_int32_t val);
-static void duk__emit_jump(duk_compiler_ctx *comp_ctx, duk_int_t target_pc);
-static duk_int_t duk__emit_jump_empty(duk_compiler_ctx *comp_ctx);
-static void duk__insert_jump_entry(duk_compiler_ctx *comp_ctx, duk_int_t jump_pc);
-static void duk__patch_jump(duk_compiler_ctx *comp_ctx, duk_int_t jump_pc, duk_int_t target_pc);
-static void duk__patch_jump_here(duk_compiler_ctx *comp_ctx, duk_int_t jump_pc);
-static void duk__patch_trycatch(duk_compiler_ctx *comp_ctx, duk_int_t trycatch_pc, duk_regconst_t reg_catch, duk_regconst_t const_varname, duk_small_uint_t flags);
-static void duk__emit_if_false_skip(duk_compiler_ctx *comp_ctx, duk_regconst_t regconst);
-static void duk__emit_if_true_skip(duk_compiler_ctx *comp_ctx, duk_regconst_t regconst);
-static void duk__emit_invalid(duk_compiler_ctx *comp_ctx);
+DUK_LOCAL_DECL void duk__emit_a(duk_compiler_ctx *comp_ctx, duk_small_uint_t op_flags, duk_regconst_t a);
+#endif
+DUK_LOCAL_DECL void duk__emit_a_bc(duk_compiler_ctx *comp_ctx, duk_small_uint_t op_flags, duk_regconst_t a, duk_regconst_t bc);
+DUK_LOCAL_DECL void duk__emit_abc(duk_compiler_ctx *comp_ctx, duk_small_uint_t op, duk_regconst_t abc);
+DUK_LOCAL_DECL void duk__emit_extraop_b_c(duk_compiler_ctx *comp_ctx, duk_small_uint_t extraop_flags, duk_regconst_t b, duk_regconst_t c);
+DUK_LOCAL_DECL void duk__emit_extraop_b(duk_compiler_ctx *comp_ctx, duk_small_uint_t extraop_flags, duk_regconst_t b);
+DUK_LOCAL_DECL void duk__emit_extraop_bc(duk_compiler_ctx *comp_ctx, duk_small_uint_t extraop, duk_regconst_t bc);
+DUK_LOCAL_DECL void duk__emit_extraop_only(duk_compiler_ctx *comp_ctx, duk_small_uint_t extraop_flags);
+DUK_LOCAL_DECL void duk__emit_load_int32(duk_compiler_ctx *comp_ctx, duk_reg_t reg, duk_int32_t val);
+DUK_LOCAL_DECL void duk__emit_load_int32_noshuffle(duk_compiler_ctx *comp_ctx, duk_reg_t reg, duk_int32_t val);
+DUK_LOCAL_DECL void duk__emit_jump(duk_compiler_ctx *comp_ctx, duk_int_t target_pc);
+DUK_LOCAL_DECL duk_int_t duk__emit_jump_empty(duk_compiler_ctx *comp_ctx);
+DUK_LOCAL_DECL void duk__insert_jump_entry(duk_compiler_ctx *comp_ctx, duk_int_t jump_pc);
+DUK_LOCAL_DECL void duk__patch_jump(duk_compiler_ctx *comp_ctx, duk_int_t jump_pc, duk_int_t target_pc);
+DUK_LOCAL_DECL void duk__patch_jump_here(duk_compiler_ctx *comp_ctx, duk_int_t jump_pc);
+DUK_LOCAL_DECL void duk__patch_trycatch(duk_compiler_ctx *comp_ctx, duk_int_t ldconst_pc, duk_int_t trycatch_pc, duk_regconst_t reg_catch, duk_regconst_t const_varname, duk_small_uint_t flags);
+DUK_LOCAL_DECL void duk__emit_if_false_skip(duk_compiler_ctx *comp_ctx, duk_regconst_t regconst);
+DUK_LOCAL_DECL void duk__emit_if_true_skip(duk_compiler_ctx *comp_ctx, duk_regconst_t regconst);
+DUK_LOCAL_DECL void duk__emit_invalid(duk_compiler_ctx *comp_ctx);
 
 /* ivalue/ispec helpers */
-static void duk__copy_ispec(duk_compiler_ctx *comp_ctx, duk_ispec *src, duk_ispec *dst);
-static void duk__copy_ivalue(duk_compiler_ctx *comp_ctx, duk_ivalue *src, duk_ivalue *dst);
-static duk_bool_t duk__is_whole_get_int32(duk_double_t x, duk_int32_t *ival);
-static duk_reg_t duk__alloctemps(duk_compiler_ctx *comp_ctx, duk_small_int_t num);
-static duk_reg_t duk__alloctemp(duk_compiler_ctx *comp_ctx);
-static void duk__settemp_checkmax(duk_compiler_ctx *comp_ctx, duk_reg_t temp_next);
-static duk_regconst_t duk__getconst(duk_compiler_ctx *comp_ctx);
-static duk_regconst_t duk__ispec_toregconst_raw(duk_compiler_ctx *comp_ctx,
-                                                duk_ispec *x,
-                                                duk_reg_t forced_reg,
-                                                duk_small_uint_t flags);
-static void duk__ispec_toforcedreg(duk_compiler_ctx *comp_ctx, duk_ispec *x, duk_reg_t forced_reg);
-static void duk__ivalue_toplain_raw(duk_compiler_ctx *comp_ctx, duk_ivalue *x, duk_reg_t forced_reg);
-static void duk__ivalue_toplain(duk_compiler_ctx *comp_ctx, duk_ivalue *x);
-static void duk__ivalue_toplain_ignore(duk_compiler_ctx *comp_ctx, duk_ivalue *x);
-static duk_regconst_t duk__ivalue_toregconst_raw(duk_compiler_ctx *comp_ctx,
-                                                 duk_ivalue *x,
-                                                 duk_reg_t forced_reg,
-                                                 duk_small_uint_t flags);
-static duk_reg_t duk__ivalue_toreg(duk_compiler_ctx *comp_ctx, duk_ivalue *x);
+DUK_LOCAL_DECL void duk__copy_ispec(duk_compiler_ctx *comp_ctx, duk_ispec *src, duk_ispec *dst);
+DUK_LOCAL_DECL void duk__copy_ivalue(duk_compiler_ctx *comp_ctx, duk_ivalue *src, duk_ivalue *dst);
+DUK_LOCAL_DECL duk_bool_t duk__is_whole_get_int32(duk_double_t x, duk_int32_t *ival);
+DUK_LOCAL_DECL duk_reg_t duk__alloctemps(duk_compiler_ctx *comp_ctx, duk_small_int_t num);
+DUK_LOCAL_DECL duk_reg_t duk__alloctemp(duk_compiler_ctx *comp_ctx);
+DUK_LOCAL_DECL void duk__settemp_checkmax(duk_compiler_ctx *comp_ctx, duk_reg_t temp_next);
+DUK_LOCAL_DECL duk_regconst_t duk__getconst(duk_compiler_ctx *comp_ctx);
+DUK_LOCAL_DECL
+duk_regconst_t duk__ispec_toregconst_raw(duk_compiler_ctx *comp_ctx,
+                                         duk_ispec *x,
+                                         duk_reg_t forced_reg,
+                                         duk_small_uint_t flags);
+DUK_LOCAL_DECL void duk__ispec_toforcedreg(duk_compiler_ctx *comp_ctx, duk_ispec *x, duk_reg_t forced_reg);
+DUK_LOCAL_DECL void duk__ivalue_toplain_raw(duk_compiler_ctx *comp_ctx, duk_ivalue *x, duk_reg_t forced_reg);
+DUK_LOCAL_DECL void duk__ivalue_toplain(duk_compiler_ctx *comp_ctx, duk_ivalue *x);
+DUK_LOCAL_DECL void duk__ivalue_toplain_ignore(duk_compiler_ctx *comp_ctx, duk_ivalue *x);
+DUK_LOCAL_DECL
+duk_regconst_t duk__ivalue_toregconst_raw(duk_compiler_ctx *comp_ctx,
+                                          duk_ivalue *x,
+                                          duk_reg_t forced_reg,
+                                          duk_small_uint_t flags);
+DUK_LOCAL_DECL duk_reg_t duk__ivalue_toreg(duk_compiler_ctx *comp_ctx, duk_ivalue *x);
 #if 0  /* unused */
-static duk_reg_t duk__ivalue_totempreg(duk_compiler_ctx *comp_ctx, duk_ivalue *x);
+DUK_LOCAL_DECL duk_reg_t duk__ivalue_totemp(duk_compiler_ctx *comp_ctx, duk_ivalue *x);
 #endif
-static void duk__ivalue_toforcedreg(duk_compiler_ctx *comp_ctx, duk_ivalue *x, duk_int_t forced_reg);
-static duk_regconst_t duk__ivalue_toregconst(duk_compiler_ctx *comp_ctx, duk_ivalue *x);
+DUK_LOCAL_DECL void duk__ivalue_toforcedreg(duk_compiler_ctx *comp_ctx, duk_ivalue *x, duk_int_t forced_reg);
+DUK_LOCAL_DECL duk_regconst_t duk__ivalue_toregconst(duk_compiler_ctx *comp_ctx, duk_ivalue *x);
+DUK_LOCAL_DECL duk_regconst_t duk__ivalue_totempconst(duk_compiler_ctx *comp_ctx, duk_ivalue *x);
 
 /* identifier handling */
-static duk_reg_t duk__lookup_active_register_binding(duk_compiler_ctx *comp_ctx);
-static duk_bool_t duk__lookup_lhs(duk_compiler_ctx *ctx, duk_reg_t *out_reg_varbind, duk_regconst_t *out_rc_varname);
+DUK_LOCAL_DECL duk_reg_t duk__lookup_active_register_binding(duk_compiler_ctx *comp_ctx);
+DUK_LOCAL_DECL duk_bool_t duk__lookup_lhs(duk_compiler_ctx *ctx, duk_reg_t *out_reg_varbind, duk_regconst_t *out_rc_varname);
 
 /* label handling */
-static void duk__add_label(duk_compiler_ctx *comp_ctx, duk_hstring *h_label, duk_int_t pc_label, duk_int_t label_id);
-static void duk__update_label_flags(duk_compiler_ctx *comp_ctx, duk_int_t label_id, duk_small_uint_t flags);
-static void duk__lookup_active_label(duk_compiler_ctx *comp_ctx, duk_hstring *h_label, duk_bool_t is_break, duk_int_t *out_label_id, duk_int_t *out_label_catch_depth, duk_int_t *out_label_pc, duk_bool_t *out_is_closest);
-static void duk__reset_labels_to_length(duk_compiler_ctx *comp_ctx, duk_int_t len);
+DUK_LOCAL_DECL void duk__add_label(duk_compiler_ctx *comp_ctx, duk_hstring *h_label, duk_int_t pc_label, duk_int_t label_id);
+DUK_LOCAL_DECL void duk__update_label_flags(duk_compiler_ctx *comp_ctx, duk_int_t label_id, duk_small_uint_t flags);
+DUK_LOCAL_DECL void duk__lookup_active_label(duk_compiler_ctx *comp_ctx, duk_hstring *h_label, duk_bool_t is_break, duk_int_t *out_label_id, duk_int_t *out_label_catch_depth, duk_int_t *out_label_pc, duk_bool_t *out_is_closest);
+DUK_LOCAL_DECL void duk__reset_labels_to_length(duk_compiler_ctx *comp_ctx, duk_int_t len);
 
 /* top-down expression parser */
-static void duk__expr_nud(duk_compiler_ctx *comp_ctx, duk_ivalue *res);
-static void duk__expr_led(duk_compiler_ctx *comp_ctx, duk_ivalue *left, duk_ivalue *res);
-static duk_small_uint_t duk__expr_lbp(duk_compiler_ctx *comp_ctx);
-static duk_bool_t duk__expr_is_empty(duk_compiler_ctx *comp_ctx);
+DUK_LOCAL_DECL void duk__expr_nud(duk_compiler_ctx *comp_ctx, duk_ivalue *res);
+DUK_LOCAL_DECL void duk__expr_led(duk_compiler_ctx *comp_ctx, duk_ivalue *left, duk_ivalue *res);
+DUK_LOCAL_DECL duk_small_uint_t duk__expr_lbp(duk_compiler_ctx *comp_ctx);
+DUK_LOCAL_DECL duk_bool_t duk__expr_is_empty(duk_compiler_ctx *comp_ctx);
 
 /* exprtop is the top level variant which resets nud/led counts */
-static void duk__expr(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags);
-static void duk__exprtop(duk_compiler_ctx *ctx, duk_ivalue *res, duk_small_uint_t rbp_flags);
+DUK_LOCAL_DECL void duk__expr(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags);
+DUK_LOCAL_DECL void duk__exprtop(duk_compiler_ctx *ctx, duk_ivalue *res, duk_small_uint_t rbp_flags);
 
 /* convenience helpers */
-static duk_reg_t duk__expr_toreg(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags);
 #if 0  /* unused */
-static duk_reg_t duk__expr_totempreg(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags);
+DUK_LOCAL_DECL duk_reg_t duk__expr_toreg(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags);
+#endif
+#if 0  /* unused */
+DUK_LOCAL_DECL duk_reg_t duk__expr_totemp(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags);
 #endif
-static void duk__expr_toforcedreg(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags, duk_reg_t forced_reg);
-static duk_regconst_t duk__expr_toregconst(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags);
-static void duk__expr_toplain(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags);
-static void duk__expr_toplain_ignore(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags);
-static duk_reg_t duk__exprtop_toreg(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags);
+DUK_LOCAL_DECL void duk__expr_toforcedreg(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags, duk_reg_t forced_reg);
+DUK_LOCAL_DECL duk_regconst_t duk__expr_toregconst(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags);
 #if 0  /* unused */
-static duk_reg_t duk__exprtop_totempreg(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags);
-static void duk__exprtop_toforcedreg(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags, duk_reg_t forced_reg);
+DUK_LOCAL_DECL duk_regconst_t duk__expr_totempconst(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags);
 #endif
-static duk_regconst_t duk__exprtop_toregconst(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags);
+DUK_LOCAL_DECL void duk__expr_toplain(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags);
+DUK_LOCAL_DECL void duk__expr_toplain_ignore(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags);
+DUK_LOCAL_DECL duk_reg_t duk__exprtop_toreg(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags);
 #if 0  /* unused */
-static void duk__exprtop_toplain_ignore(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags);
+DUK_LOCAL_DECL duk_reg_t duk__exprtop_totemp(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags);
+#endif
+DUK_LOCAL_DECL void duk__exprtop_toforcedreg(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags, duk_reg_t forced_reg);
+DUK_LOCAL_DECL duk_regconst_t duk__exprtop_toregconst(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags);
+#if 0  /* unused */
+DUK_LOCAL_DECL void duk__exprtop_toplain_ignore(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags);
 #endif
 
 /* expression parsing helpers */
-static duk_int_t duk__parse_arguments(duk_compiler_ctx *comp_ctx, duk_ivalue *res);
-static void duk__nud_array_literal(duk_compiler_ctx *comp_ctx, duk_ivalue *res);
-static void duk__nud_object_literal(duk_compiler_ctx *comp_ctx, duk_ivalue *res);
-static duk_bool_t duk__nud_object_literal_key_check(duk_compiler_ctx *comp_ctx, duk_small_uint_t new_key_flags);
+DUK_LOCAL_DECL duk_int_t duk__parse_arguments(duk_compiler_ctx *comp_ctx, duk_ivalue *res);
+DUK_LOCAL_DECL void duk__nud_array_literal(duk_compiler_ctx *comp_ctx, duk_ivalue *res);
+DUK_LOCAL_DECL void duk__nud_object_literal(duk_compiler_ctx *comp_ctx, duk_ivalue *res);
+DUK_LOCAL_DECL duk_bool_t duk__nud_object_literal_key_check(duk_compiler_ctx *comp_ctx, duk_small_uint_t new_key_flags);
 
 /* statement parsing */
-static void duk__parse_var_decl(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t expr_flags, duk_reg_t *out_reg_varbind, duk_regconst_t *out_rc_varname);
-static void duk__parse_var_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res);
-static void duk__parse_for_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_int_t pc_label_site);
-static void duk__parse_switch_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_int_t pc_label_site);
-static void duk__parse_if_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res);
-static void duk__parse_do_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_int_t pc_label_site);
-static void duk__parse_while_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_int_t pc_label_site);
-static void duk__parse_break_or_continue_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res);
-static void duk__parse_return_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res);
-static void duk__parse_throw_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res);
-static void duk__parse_try_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res);
-static void duk__parse_with_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res);
-static void duk__parse_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_bool_t allow_source_elem);
-static duk_int_t duk__stmt_label_site(duk_compiler_ctx *comp_ctx, duk_int_t label_id);
-static void duk__parse_stmts(duk_compiler_ctx *comp_ctx, duk_bool_t allow_source_elem, duk_bool_t expect_eof);
-
-static void duk__parse_func_body(duk_compiler_ctx *comp_ctx, duk_bool_t expect_eof, duk_bool_t implicit_return_value);
-static void duk__parse_func_formals(duk_compiler_ctx *comp_ctx);
-static void duk__parse_func_like_raw(duk_compiler_ctx *comp_ctx, duk_bool_t is_decl, duk_bool_t is_setget);
-static duk_int_t duk__parse_func_like_fnum(duk_compiler_ctx *comp_ctx, duk_bool_t is_decl, duk_bool_t is_setget);
+DUK_LOCAL_DECL void duk__parse_var_decl(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t expr_flags, duk_reg_t *out_reg_varbind, duk_regconst_t *out_rc_varname);
+DUK_LOCAL_DECL void duk__parse_var_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t expr_flags);
+DUK_LOCAL_DECL void duk__parse_for_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_int_t pc_label_site);
+DUK_LOCAL_DECL void duk__parse_switch_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_int_t pc_label_site);
+DUK_LOCAL_DECL void duk__parse_if_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res);
+DUK_LOCAL_DECL void duk__parse_do_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_int_t pc_label_site);
+DUK_LOCAL_DECL void duk__parse_while_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_int_t pc_label_site);
+DUK_LOCAL_DECL void duk__parse_break_or_continue_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res);
+DUK_LOCAL_DECL void duk__parse_return_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res);
+DUK_LOCAL_DECL void duk__parse_throw_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res);
+DUK_LOCAL_DECL void duk__parse_try_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res);
+DUK_LOCAL_DECL void duk__parse_with_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res);
+DUK_LOCAL_DECL void duk__parse_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_bool_t allow_source_elem);
+DUK_LOCAL_DECL duk_int_t duk__stmt_label_site(duk_compiler_ctx *comp_ctx, duk_int_t label_id);
+DUK_LOCAL_DECL void duk__parse_stmts(duk_compiler_ctx *comp_ctx, duk_bool_t allow_source_elem, duk_bool_t expect_eof);
+
+DUK_LOCAL_DECL void duk__parse_func_body(duk_compiler_ctx *comp_ctx, duk_bool_t expect_eof, duk_bool_t implicit_return_value, duk_small_int_t expect_token);
+DUK_LOCAL_DECL void duk__parse_func_formals(duk_compiler_ctx *comp_ctx);
+DUK_LOCAL_DECL void duk__parse_func_like_raw(duk_compiler_ctx *comp_ctx, duk_bool_t is_decl, duk_bool_t is_setget);
+DUK_LOCAL_DECL duk_int_t duk__parse_func_like_fnum(duk_compiler_ctx *comp_ctx, duk_bool_t is_decl, duk_bool_t is_setget);
 
 /*
  *  Parser control values for tokens.  The token table is ordered by the
@@ -43112,7 +59690,7 @@ static duk_int_t duk__parse_func_like_fnum(duk_compiler_ctx *comp_ctx, duk_bool_
 
 /* XXX: actually single step levels would work just fine, clean up */
 
-/* binding power "levels" (see doc/compiler.txt) */
+/* binding power "levels" (see doc/compiler.rst) */
 #define DUK__BP_INVALID                0             /* always terminates led() */
 #define DUK__BP_EOF                    2
 #define DUK__BP_CLOSING                4             /* token closes expression, e.g. ')', ']' */
@@ -43144,10 +59722,8 @@ static duk_int_t duk__parse_func_like_fnum(duk_compiler_ctx *comp_ctx, duk_bool_
 #define DUK__MK_LBP(bp)                ((bp) >> 1)    /* bp is assumed to be even */
 #define DUK__MK_LBP_FLAGS(bp,flags)    (((bp) >> 1) | (flags))
 
-static const duk_uint8_t duk__token_lbp[] = {
+DUK_LOCAL const duk_uint8_t duk__token_lbp[] = {
 	DUK__MK_LBP(DUK__BP_EOF),                                 /* DUK_TOK_EOF */
-	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_LINETERM */
-	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_COMMENT */
 	DUK__MK_LBP_FLAGS(DUK__BP_INVALID, DUK__TOKEN_LBP_FLAG_NO_REGEXP),  /* DUK_TOK_IDENTIFIER */
 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_BREAK */
 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_CASE */
@@ -43172,11 +59748,11 @@ static const duk_uint8_t duk__token_lbp[] = {
 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_TRY */
 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_TYPEOF */
 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_VAR */
+	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_CONST */
 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_VOID */
 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_WHILE */
 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_WITH */
 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_CLASS */
-	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_CONST */
 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_ENUM */
 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_EXPORT */
 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_EXTENDS */
@@ -43253,7 +59829,7 @@ static const duk_uint8_t duk__token_lbp[] = {
  *  Misc helpers
  */
 
-static void duk__recursion_increase(duk_compiler_ctx *comp_ctx) {
+DUK_LOCAL void duk__recursion_increase(duk_compiler_ctx *comp_ctx) {
 	DUK_ASSERT(comp_ctx != NULL);
 	DUK_ASSERT(comp_ctx->recursion_depth >= 0);
 	if (comp_ctx->recursion_depth >= comp_ctx->recursion_limit) {
@@ -43262,19 +59838,19 @@ static void duk__recursion_increase(duk_compiler_ctx *comp_ctx) {
 	comp_ctx->recursion_depth++;
 }
 
-static void duk__recursion_decrease(duk_compiler_ctx *comp_ctx) {
+DUK_LOCAL void duk__recursion_decrease(duk_compiler_ctx *comp_ctx) {
 	DUK_ASSERT(comp_ctx != NULL);
 	DUK_ASSERT(comp_ctx->recursion_depth > 0);
 	comp_ctx->recursion_depth--;
 }
 
-static duk_bool_t duk__hstring_is_eval_or_arguments(duk_compiler_ctx *comp_ctx, duk_hstring *h) {
+DUK_LOCAL duk_bool_t duk__hstring_is_eval_or_arguments(duk_compiler_ctx *comp_ctx, duk_hstring *h) {
 	DUK_UNREF(comp_ctx);
 	DUK_ASSERT(h != NULL);
 	return DUK_HSTRING_HAS_EVAL_OR_ARGUMENTS(h);
 }
 
-static duk_bool_t duk__hstring_is_eval_or_arguments_in_strict_mode(duk_compiler_ctx *comp_ctx, duk_hstring *h) {
+DUK_LOCAL duk_bool_t duk__hstring_is_eval_or_arguments_in_strict_mode(duk_compiler_ctx *comp_ctx, duk_hstring *h) {
 	DUK_ASSERT(h != NULL);
 	return (comp_ctx->curr_func.is_strict &&
 	        DUK_HSTRING_HAS_EVAL_OR_ARGUMENTS(h));
@@ -43288,7 +59864,7 @@ static duk_bool_t duk__hstring_is_eval_or_arguments_in_strict_mode(duk_compiler_
  * avoids dup():ing; valstack_copy(src, dst)?
  */
 
-static void duk__advance_helper(duk_compiler_ctx *comp_ctx, duk_small_int_t expect) {
+DUK_LOCAL void duk__advance_helper(duk_compiler_ctx *comp_ctx, duk_small_int_t expect) {
 	duk_hthread *thr = comp_ctx->thr;
 	duk_context *ctx = (duk_context *) thr;
 	duk_bool_t regexp;
@@ -43301,7 +59877,7 @@ static void duk__advance_helper(duk_compiler_ctx *comp_ctx, duk_small_int_t expe
 	 *  We can use either 't' or 't_nores'; the latter would not
 	 *  recognize keywords.  Some keywords can be followed by a
 	 *  RegExp (e.g. "return"), so using 't' is better.  This is
-	 *  not trivial, see doc/compiler.txt.
+	 *  not trivial, see doc/compiler.rst.
 	 */
 
 	regexp = 1;
@@ -43330,31 +59906,29 @@ static void duk__advance_helper(duk_compiler_ctx *comp_ctx, duk_small_int_t expe
 	                                 comp_ctx->curr_func.is_strict,
 	                                 regexp);
 
-	DUK_DDD(DUK_DDDPRINT("advance: curr: tok=%ld/%ld,%ld-%ld,term=%ld,%!T,%!T "
-	                     "prev: tok=%ld/%ld,%ld-%ld,term=%ld,%!T,%!T",
+	DUK_DDD(DUK_DDDPRINT("advance: curr: tok=%ld/%ld,%ld,term=%ld,%!T,%!T "
+	                     "prev: tok=%ld/%ld,%ld,term=%ld,%!T,%!T",
 	                     (long) comp_ctx->curr_token.t,
 	                     (long) comp_ctx->curr_token.t_nores,
 	                     (long) comp_ctx->curr_token.start_line,
-	                     (long) comp_ctx->curr_token.end_line,
 	                     (long) comp_ctx->curr_token.lineterm,
 	                     (duk_tval *) duk_get_tval(ctx, comp_ctx->tok11_idx),
 	                     (duk_tval *) duk_get_tval(ctx, comp_ctx->tok12_idx),
 	                     (long) comp_ctx->prev_token.t,
 	                     (long) comp_ctx->prev_token.t_nores,
 	                     (long) comp_ctx->prev_token.start_line,
-	                     (long) comp_ctx->prev_token.end_line,
 	                     (long) comp_ctx->prev_token.lineterm,
 	                     (duk_tval *) duk_get_tval(ctx, comp_ctx->tok21_idx),
 	                     (duk_tval *) duk_get_tval(ctx, comp_ctx->tok22_idx)));
 }
 
 /* advance, expecting current token to be a specific token; parse next token in regexp context */
-static void duk__advance_expect(duk_compiler_ctx *comp_ctx, duk_small_int_t expect) {
+DUK_LOCAL void duk__advance_expect(duk_compiler_ctx *comp_ctx, duk_small_int_t expect) {
 	duk__advance_helper(comp_ctx, expect);
 }
 
 /* advance, whatever the current token is; parse next token in regexp context */
-static void duk__advance(duk_compiler_ctx *comp_ctx) {
+DUK_LOCAL void duk__advance(duk_compiler_ctx *comp_ctx) {
 	duk__advance_helper(comp_ctx, -1);
 }
 
@@ -43363,7 +59937,7 @@ static void duk__advance(duk_compiler_ctx *comp_ctx) {
  */
 
 /* init function state: inits valstack allocations */
-static void duk__init_func_valstack_slots(duk_compiler_ctx *comp_ctx) {
+DUK_LOCAL void duk__init_func_valstack_slots(duk_compiler_ctx *comp_ctx) {
 	duk_compiler_func *func = &comp_ctx->curr_func;
 	duk_hthread *thr = comp_ctx->thr;
 	duk_context *ctx = (duk_context *) thr;
@@ -43374,7 +59948,6 @@ static void duk__init_func_valstack_slots(duk_compiler_ctx *comp_ctx) {
 	DUK_MEMZERO(func, sizeof(*func));  /* intentional overlap with earlier memzero */
 #ifdef DUK_USE_EXPLICIT_NULL_INIT
 	func->h_name = NULL;
-	func->h_code = NULL;
 	func->h_consts = NULL;
 	func->h_funcs = NULL;
 	func->h_decls = NULL;
@@ -43386,13 +59959,8 @@ static void duk__init_func_valstack_slots(duk_compiler_ctx *comp_ctx) {
 
 	duk_require_stack(ctx, DUK__FUNCTION_INIT_REQUIRE_SLOTS);
 
-	/* XXX: getter for dynamic buffer */
-
-	duk_push_dynamic_buffer(ctx, 0);
-	func->code_idx = entry_top + 0;
-	func->h_code = (duk_hbuffer_dynamic *) duk_get_hbuffer(ctx, entry_top + 0);
-	DUK_ASSERT(func->h_code != NULL);
-	DUK_ASSERT(DUK_HBUFFER_HAS_DYNAMIC(func->h_code));
+	DUK_BW_INIT_PUSHBUF(thr, &func->bw_code, DUK__BC_INITIAL_INSTS * sizeof(duk_compiler_instr));
+	/* code_idx = entry_top + 0 */
 
 	duk_push_array(ctx);
 	func->consts_idx = entry_top + 1;
@@ -43419,7 +59987,7 @@ static void duk__init_func_valstack_slots(duk_compiler_ctx *comp_ctx) {
 	func->labelinfos_idx = entry_top + 5;
 	func->h_labelinfos = (duk_hbuffer_dynamic *) duk_get_hbuffer(ctx, entry_top + 5);
 	DUK_ASSERT(func->h_labelinfos != NULL);
-	DUK_ASSERT(DUK_HBUFFER_HAS_DYNAMIC(func->h_labelinfos));
+	DUK_ASSERT(DUK_HBUFFER_HAS_DYNAMIC(func->h_labelinfos) && !DUK_HBUFFER_HAS_EXTERNAL(func->h_labelinfos));
 
 	duk_push_array(ctx);
 	func->argnames_idx = entry_top + 6;
@@ -43433,13 +60001,16 @@ static void duk__init_func_valstack_slots(duk_compiler_ctx *comp_ctx) {
 }
 
 /* reset function state (prepare for pass 2) */
-static void duk__reset_func_for_pass2(duk_compiler_ctx *comp_ctx) {
+DUK_LOCAL void duk__reset_func_for_pass2(duk_compiler_ctx *comp_ctx) {
 	duk_compiler_func *func = &comp_ctx->curr_func;
 	duk_hthread *thr = comp_ctx->thr;
+	duk_context *ctx = (duk_context *) thr;
 
-	/* XXX: reset buffers while keeping existing spare */
+	/* reset bytecode buffer but keep current size; pass 2 will
+	 * require same amount or more.
+	 */
+	DUK_BW_RESET_SIZE(thr, &func->bw_code);
 
-	duk_hbuffer_reset(thr, func->h_code);
 	duk_hobject_set_length_zero(thr, func->h_consts);
 	/* keep func->h_funcs; inner functions are not reparsed to avoid O(depth^2) parsing */
 	func->fnum_next = 0;
@@ -43447,18 +60018,24 @@ static void duk__reset_func_for_pass2(duk_compiler_ctx *comp_ctx) {
 	duk_hobject_set_length_zero(thr, func->h_labelnames);
 	duk_hbuffer_reset(thr, func->h_labelinfos);
 	/* keep func->h_argnames; it is fixed for all passes */
+
+	/* truncated in case pass 3 needed */
+	duk_push_object_internal(ctx);
+	duk_replace(ctx, func->varmap_idx);
+	func->h_varmap = duk_get_hobject(ctx, func->varmap_idx);
+	DUK_ASSERT(func->h_varmap != NULL);
 }
 
 /* cleanup varmap from any null entries, compact it, etc; returns number
  * of final entries after cleanup.
  */
-static duk_int_t duk__cleanup_varmap(duk_compiler_ctx *comp_ctx) {
+DUK_LOCAL duk_int_t duk__cleanup_varmap(duk_compiler_ctx *comp_ctx) {
 	duk_hthread *thr = comp_ctx->thr;
 	duk_context *ctx = (duk_context *) thr;
 	duk_hobject *h_varmap;
 	duk_hstring *h_key;
 	duk_tval *tv;
-	duk_uint32_t i, e_used;
+	duk_uint32_t i, e_next;
 	duk_int_t ret;
 
 	/* [ ... varmap ] */
@@ -43467,14 +60044,14 @@ static duk_int_t duk__cleanup_varmap(duk_compiler_ctx *comp_ctx) {
 	DUK_ASSERT(h_varmap != NULL);
 
 	ret = 0;
-	e_used = h_varmap->e_used;
-	for (i = 0; i < e_used; i++) {
-		h_key = DUK_HOBJECT_E_GET_KEY(h_varmap, i);
+	e_next = DUK_HOBJECT_GET_ENEXT(h_varmap);
+	for (i = 0; i < e_next; i++) {
+		h_key = DUK_HOBJECT_E_GET_KEY(thr->heap, h_varmap, i);
 		if (!h_key) {
 			continue;
 		}
 
-		DUK_ASSERT(!DUK_HOBJECT_E_SLOT_IS_ACCESSOR(h_varmap, i));
+		DUK_ASSERT(!DUK_HOBJECT_E_SLOT_IS_ACCESSOR(thr->heap, h_varmap, i));
 
 		/* The entries can either be register numbers or 'null' values.
 		 * Thus, no need to DECREF them and get side effects.  DECREF'ing
@@ -43483,12 +60060,12 @@ static duk_int_t duk__cleanup_varmap(duk_compiler_ctx *comp_ctx) {
 		 * rely on the object properties not changing from underneath us.
 		 */
 
-		tv = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(h_varmap, i);
+		tv = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, h_varmap, i);
 		if (!DUK_TVAL_IS_NUMBER(tv)) {
 			DUK_ASSERT(!DUK_TVAL_IS_HEAP_ALLOCATED(tv));
-			DUK_TVAL_SET_UNDEFINED_UNUSED(tv);
-			DUK_HOBJECT_E_SET_KEY(h_varmap, i, NULL);
+			DUK_HOBJECT_E_SET_KEY(thr->heap, h_varmap, i, NULL);
 			DUK_HSTRING_DECREF(thr, h_key);
+			/* when key is NULL, value is garbage so no need to set */
 		} else {
 			ret++;
 		}
@@ -43503,7 +60080,7 @@ static duk_int_t duk__cleanup_varmap(duk_compiler_ctx *comp_ctx) {
  * on top of stack.
  */
 /* XXX: awkward and bloated asm -- use faster internal accesses */
-static void duk__convert_to_func_template(duk_compiler_ctx *comp_ctx) {
+DUK_LOCAL void duk__convert_to_func_template(duk_compiler_ctx *comp_ctx, duk_bool_t force_no_namebind) {
 	duk_compiler_func *func = &comp_ctx->curr_func;
 	duk_hthread *thr = comp_ctx->thr;
 	duk_context *ctx = (duk_context *) thr;
@@ -43522,10 +60099,6 @@ static void duk__convert_to_func_template(duk_compiler_ctx *comp_ctx) {
 	duk_tval *tv;
 
 	DUK_DDD(DUK_DDDPRINT("converting duk_compiler_func to function/template"));
-	DUK_DD(DUK_DDPRINT("code=%!xO consts=%!O funcs=%!O",
-	                   (duk_heaphdr *) func->h_code,
-	                   (duk_heaphdr *) func->h_consts,
-	                   (duk_heaphdr *) func->h_funcs));
 
 	/*
 	 *  Push result object and init its flags
@@ -43535,6 +60108,7 @@ static void duk__convert_to_func_template(duk_compiler_ctx *comp_ctx) {
 
 	(void) duk_push_compiledfunction(ctx);
 	h_res = (duk_hcompiledfunction *) duk_get_hobject(ctx, -1);  /* XXX: specific getter */
+	DUK_ASSERT(h_res != NULL);
 
 	if (func->is_function) {
 		DUK_DDD(DUK_DDDPRINT("function -> set NEWENV"));
@@ -43563,7 +60137,11 @@ static void duk__convert_to_func_template(duk_compiler_ctx *comp_ctx) {
 		DUK_ASSERT(!DUK_HOBJECT_HAS_NEWENV((duk_hobject *) h_res));
 	}
 
-	if (func->is_function && !func->is_decl && func->h_name != NULL) {
+	if (func->is_function && !func->is_decl && func->h_name != NULL && !force_no_namebind) {
+		/* Object literal set/get functions have a name (property
+		 * name) but must not have a lexical name binding, see
+		 * test-bug-getset-func-name.js.
+		 */
 		DUK_DDD(DUK_DDDPRINT("function expression with a name -> set NAMEBINDING"));
 		DUK_HOBJECT_SET_NAMEBINDING((duk_hobject *) h_res);
 	}
@@ -43587,9 +60165,9 @@ static void duk__convert_to_func_template(duk_compiler_ctx *comp_ctx) {
 	 *  so the building process is atomic.
 	 */
 
-	consts_count = duk_hobject_get_length(comp_ctx->thr, func->h_consts);
-	funcs_count = duk_hobject_get_length(comp_ctx->thr, func->h_funcs) / 3;
-	code_count = DUK_HBUFFER_GET_SIZE(func->h_code) / sizeof(duk_compiler_instr);
+	consts_count = duk_hobject_get_length(thr, func->h_consts);
+	funcs_count = duk_hobject_get_length(thr, func->h_funcs) / 3;
+	code_count = DUK_BW_GET_SIZE(thr, &func->bw_code) / sizeof(duk_compiler_instr);
 	code_size = code_count * sizeof(duk_instr_t);
 
 	data_size = consts_count * sizeof(duk_tval) +
@@ -43607,13 +60185,13 @@ static void duk__convert_to_func_template(duk_compiler_ctx *comp_ctx) {
 	h_data = (duk_hbuffer_fixed *) duk_get_hbuffer(ctx, -1);
 	DUK_ASSERT(h_data != NULL);
 
-	h_res->data = (duk_hbuffer *) h_data;
+	DUK_HCOMPILEDFUNCTION_SET_DATA(thr->heap, h_res, (duk_hbuffer *) h_data);
 	DUK_HEAPHDR_INCREF(thr, h_data);
 
-	p_const = (duk_tval *) DUK_HBUFFER_FIXED_GET_DATA_PTR(h_data);
+	p_const = (duk_tval *) (void *) DUK_HBUFFER_FIXED_GET_DATA_PTR(thr->heap, h_data);
 	for (i = 0; i < consts_count; i++) {
 		DUK_ASSERT(i <= DUK_UARRIDX_MAX);  /* const limits */
-		tv = duk_hobject_find_existing_array_entry_tval_ptr(func->h_consts, (duk_uarridx_t) i);
+		tv = duk_hobject_find_existing_array_entry_tval_ptr(thr->heap, func->h_consts, (duk_uarridx_t) i);
 		DUK_ASSERT(tv != NULL);
 		DUK_TVAL_SET_TVAL(p_const, tv);
 		p_const++;
@@ -43623,11 +60201,11 @@ static void duk__convert_to_func_template(duk_compiler_ctx *comp_ctx) {
 	}
 
 	p_func = (duk_hobject **) p_const;
-	h_res->funcs = p_func;
+	DUK_HCOMPILEDFUNCTION_SET_FUNCS(thr->heap, h_res, p_func);
 	for (i = 0; i < funcs_count; i++) {
 		duk_hobject *h;
 		DUK_ASSERT(i * 3 <= DUK_UARRIDX_MAX);  /* func limits */
-		tv = duk_hobject_find_existing_array_entry_tval_ptr(func->h_funcs, (duk_uarridx_t) (i * 3));
+		tv = duk_hobject_find_existing_array_entry_tval_ptr(thr->heap, func->h_funcs, (duk_uarridx_t) (i * 3));
 		DUK_ASSERT(tv != NULL);
 		DUK_ASSERT(DUK_TVAL_IS_OBJECT(tv));
 		h = DUK_TVAL_GET_OBJECT(tv);
@@ -43641,16 +60219,17 @@ static void duk__convert_to_func_template(duk_compiler_ctx *comp_ctx) {
 	}
 
 	p_instr = (duk_instr_t *) p_func;
-	h_res->bytecode = p_instr;
+	DUK_HCOMPILEDFUNCTION_SET_BYTECODE(thr->heap, h_res, p_instr);
 
 	/* copy bytecode instructions one at a time */
-	DUK_ASSERT(DUK_HBUFFER_HAS_DYNAMIC(func->h_code));
-	q_instr = (duk_compiler_instr *) DUK_HBUFFER_DYNAMIC_GET_CURR_DATA_PTR(func->h_code);
+	q_instr = (duk_compiler_instr *) (void *) DUK_BW_GET_BASEPTR(thr, &func->bw_code);
 	for (i = 0; i < code_count; i++) {
 		p_instr[i] = q_instr[i].ins;
 	}
 	/* Note: 'q_instr' is still used below */
 
+	DUK_ASSERT((duk_uint8_t *) (p_instr + code_count) == DUK_HBUFFER_FIXED_GET_DATA_PTR(thr->heap, h_data) + data_size);
+
 	duk_pop(ctx);  /* 'data' (and everything in it) is reachable through h_res now */
 
 	/*
@@ -43664,13 +60243,18 @@ static void duk__convert_to_func_template(duk_compiler_ctx *comp_ctx) {
 
 	/* [ ... res ] */
 
-	/* _varmap: omitted if function is guaranteed not to do slow path identifier
+	/* _Varmap: omitted if function is guaranteed not to do slow path identifier
 	 * accesses or if it would turn out to be empty of actual register mappings
-	 * after a cleanup.
+	 * after a cleanup.  When debugging is enabled, we always need the varmap to
+	 * be able to lookup variables at any point.
 	 */
+#if defined(DUK_USE_DEBUGGER_SUPPORT)
+	if (1) {
+#else
 	if (func->id_access_slow ||     /* directly uses slow accesses */
 	    func->may_direct_eval ||    /* may indirectly slow access through a direct eval */
 	    funcs_count > 0) {          /* has inner functions which may slow access (XXX: this can be optimized by looking at the inner functions) */
+#endif
 		duk_int_t num_used;
 		duk_dup(ctx, func->varmap_idx);
 		num_used = duk__cleanup_varmap(comp_ctx);
@@ -43678,41 +60262,49 @@ static void duk__convert_to_func_template(duk_compiler_ctx *comp_ctx) {
 		                     (duk_tval *) duk_get_tval(ctx, -1), (long) num_used));
 
 		if (num_used > 0) {
-			duk_def_prop_stridx(ctx, -2, DUK_STRIDX_INT_VARMAP, DUK_PROPDESC_FLAGS_NONE);
+			duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_INT_VARMAP, DUK_PROPDESC_FLAGS_NONE);
 		} else {
 			DUK_DDD(DUK_DDDPRINT("varmap is empty after cleanup -> no need to add"));
 			duk_pop(ctx);
 		}
 	}
 
-	/* _formals: omitted if function is guaranteed not to need a (non-strict) arguments object */
-	if (1) {  /* FIXME: condition */
-		/* FIXME: if omitted, recheck handling for 'length' in duk_js_push_closure();
-		 * it currently relies on _formals being set.
+	/* _Formals: omitted if function is guaranteed not to need a (non-strict) arguments object */
+	if (1) {
+		/* XXX: Add a proper condition.  If formals list is omitted, recheck
+		 * handling for 'length' in duk_js_push_closure(); it currently relies
+		 * on _Formals being set.  Removal may need to be conditional to debugging
+		 * being enabled/disabled too.
 		 */
 		duk_dup(ctx, func->argnames_idx);
-		duk_def_prop_stridx(ctx, -2, DUK_STRIDX_INT_FORMALS, DUK_PROPDESC_FLAGS_NONE);
+		duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_INT_FORMALS, DUK_PROPDESC_FLAGS_NONE);
 	}
 
 	/* name */
 	if (func->h_name) {
 		duk_push_hstring(ctx, func->h_name);
-		duk_def_prop_stridx(ctx, -2, DUK_STRIDX_NAME, DUK_PROPDESC_FLAGS_NONE);
+		duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_NAME, DUK_PROPDESC_FLAGS_NONE);
 	}
 
-	/* _source */
+	/* _Source */
 #if defined(DUK_USE_NONSTD_FUNC_SOURCE_PROPERTY)
 	if (0) {
-		/* FIXME: Currently function source code is not stored, as it is not
+		/* XXX: Currently function source code is not stored, as it is not
 		 * required by the standard.  Source code should not be stored by
 		 * default (user should enable it explicitly), and the source should
 		 * probably be compressed with a trivial text compressor; average
 		 * compression of 20-30% is quite easy to achieve even with a trivial
 		 * compressor (RLE + backwards lookup).
-		 */
-		/* FIXME: Debugging needs source code to be useful: sometimes input
-		 * code is not found in files as it may be generated and then eval()'d,
-		 * given by dynamic C code, etc.
+		 *
+		 * Debugging needs source code to be useful: sometimes input code is
+		 * not found in files as it may be generated and then eval()'d, given
+		 * by dynamic C code, etc.
+		 *
+		 * Other issues:
+		 *
+		 *   - Need tokenizer indices for start and end to substring
+		 *   - Always normalize function declaration part?
+		 *   - If we keep _Formals, only need to store body
 		 */
 
 		/*
@@ -43735,17 +60327,14 @@ static void duk__convert_to_func_template(duk_compiler_ctx *comp_ctx) {
 		 *    'function a(foo,bar) { print(foo); }'
 		 */
 
-		/* FIXME: need tokenizer indices for start and end to substring */
-		/* FIXME: always normalize function declaration part? */
-		/* FIXME: if we keep _formals, only need to store body */
 #if 0
-		duk_push_string(ctx, "FIXME");
-		duk_def_prop_stridx(ctx, -2, DUK_STRIDX_INT_SOURCE, DUK_PROPDESC_FLAGS_NONE);
+		duk_push_string(ctx, "XXX");
+		duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_INT_SOURCE, DUK_PROPDESC_FLAGS_NONE);
 #endif
 	}
 #endif  /* DUK_USE_NONSTD_FUNC_SOURCE_PROPERTY */
 
-	/* _pc2line */
+	/* _Pc2line */
 #if defined(DUK_USE_PC2LINE)
 	if (1) {
 		/*
@@ -43754,7 +60343,7 @@ static void duk__convert_to_func_template(duk_compiler_ctx *comp_ctx) {
 
 		DUK_ASSERT(code_count <= DUK_COMPILER_MAX_BYTECODE_LENGTH);
 		duk_hobject_pc2line_pack(thr, q_instr, (duk_uint_fast32_t) code_count);  /* -> pushes fixed buffer */
-		duk_def_prop_stridx(ctx, -2, DUK_STRIDX_INT_PC2LINE, DUK_PROPDESC_FLAGS_NONE);
+		duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_INT_PC2LINE, DUK_PROPDESC_FLAGS_NONE);
 
 		/* XXX: if assertions enabled, walk through all valid PCs
 		 * and check line mapping.
@@ -43769,7 +60358,7 @@ static void duk__convert_to_func_template(duk_compiler_ctx *comp_ctx) {
 		 */
 
 		duk_push_hstring(ctx, comp_ctx->h_filename);
-		duk_def_prop_stridx(ctx, -2, DUK_STRIDX_FILE_NAME, DUK_PROPDESC_FLAGS_NONE);
+		duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_FILE_NAME, DUK_PROPDESC_FLAGS_NONE);
 	}
 
 	/*
@@ -43783,9 +60372,13 @@ static void duk__convert_to_func_template(duk_compiler_ctx *comp_ctx) {
 	 */
 
 	DUK_ASSERT(func->temp_max >= 0);
-	h_res->nregs = func->temp_max;
-	h_res->nargs = duk_hobject_get_length(thr, func->h_argnames);
+	h_res->nregs = (duk_uint16_t) func->temp_max;
+	h_res->nargs = (duk_uint16_t) duk_hobject_get_length(thr, func->h_argnames);
 	DUK_ASSERT(h_res->nregs >= h_res->nargs);  /* pass2 allocation handles this */
+#if defined(DUK_USE_DEBUGGER_SUPPORT)
+	h_res->start_line = (duk_uint32_t) func->min_line;
+	h_res->end_line = (duk_uint32_t) func->max_line;
+#endif
 
 	DUK_DD(DUK_DDPRINT("converted function: %!ixT",
 	                   (duk_tval *) duk_get_tval(ctx, -1)));
@@ -43806,8 +60399,8 @@ static void duk__convert_to_func_template(duk_compiler_ctx *comp_ctx) {
 		duk_instr_t *p, *p_start, *p_end;
 
 		h = (duk_hcompiledfunction *) duk_get_hobject(ctx, -1);
-		p_start = (duk_instr_t *) DUK_HCOMPILEDFUNCTION_GET_CODE_BASE(h);
-		p_end = (duk_instr_t *) DUK_HCOMPILEDFUNCTION_GET_CODE_END(h);
+		p_start = (duk_instr_t *) DUK_HCOMPILEDFUNCTION_GET_CODE_BASE(thr->heap, h);
+		p_end = (duk_instr_t *) DUK_HCOMPILEDFUNCTION_GET_CODE_END(thr->heap, h);
 
 		p = p_start;
 		while (p < p_end) {
@@ -43860,89 +60453,143 @@ static void duk__convert_to_func_template(duk_compiler_ctx *comp_ctx) {
 /* Code emission flags, passed in the 'opcode' field.  Opcode + flags
  * fit into 16 bits for now, so use duk_small_uint.t.
  */
-#define DUK__EMIT_FLAG_NO_SHUFFLE_A  (1 << 8)
-#define DUK__EMIT_FLAG_NO_SHUFFLE_B  (1 << 9)
-#define DUK__EMIT_FLAG_NO_SHUFFLE_C  (1 << 10)
-#define DUK__EMIT_FLAG_A_IS_SOURCE   (1 << 11)  /* slot A is a source (default: target) */
-#define DUK__EMIT_FLAG_B_IS_TARGET   (1 << 12)  /* slot B is a target (default: source) */
-#define DUK__EMIT_FLAG_C_IS_TARGET   (1 << 13)  /* slot C is a target (default: source) */
+#define DUK__EMIT_FLAG_NO_SHUFFLE_A      (1 << 8)
+#define DUK__EMIT_FLAG_NO_SHUFFLE_B      (1 << 9)
+#define DUK__EMIT_FLAG_NO_SHUFFLE_C      (1 << 10)
+#define DUK__EMIT_FLAG_A_IS_SOURCE       (1 << 11)  /* slot A is a source (default: target) */
+#define DUK__EMIT_FLAG_B_IS_TARGET       (1 << 12)  /* slot B is a target (default: source) */
+#define DUK__EMIT_FLAG_C_IS_TARGET       (1 << 13)  /* slot C is a target (default: source) */
+#define DUK__EMIT_FLAG_B_IS_TARGETSOURCE (1 << 14)  /* slot B is both a target and a source (used by extraops like DUK_EXTRAOP_INSTOF */
+#define DUK__EMIT_FLAG_RESERVE_JUMPSLOT  (1 << 15)  /* reserve a jumpslot after instr before target spilling, used for NEXTENUM */
 
 /* XXX: clarify on when and where DUK__CONST_MARKER is allowed */
 /* XXX: opcode specific assertions on when consts are allowed */
 
 /* XXX: macro smaller than call? */
-static duk_int_t duk__get_current_pc(duk_compiler_ctx *comp_ctx) {
-	return (duk_int_t) (DUK_HBUFFER_GET_SIZE(comp_ctx->curr_func.h_code) / sizeof(duk_compiler_instr));
+DUK_LOCAL duk_int_t duk__get_current_pc(duk_compiler_ctx *comp_ctx) {
+	duk_compiler_func *func;
+	func = &comp_ctx->curr_func;
+	return (duk_int_t) (DUK_BW_GET_SIZE(comp_ctx->thr, &func->bw_code) / sizeof(duk_compiler_instr));
 }
 
-static duk_compiler_instr *duk__get_instr_ptr(duk_compiler_ctx *comp_ctx, duk_int_t pc) {
-	duk_compiler_func *f = &comp_ctx->curr_func;
-	duk_uint8_t *p;
-	duk_compiler_instr *code_begin, *code_end;
-
-	p = (duk_uint8_t *) DUK_HBUFFER_DYNAMIC_GET_CURR_DATA_PTR(f->h_code);
-	code_begin = (duk_compiler_instr *) p;
-	code_end = (duk_compiler_instr *) (p + DUK_HBUFFER_GET_SIZE(f->h_code));
-	DUK_UNREF(code_end);
-
+DUK_LOCAL duk_compiler_instr *duk__get_instr_ptr(duk_compiler_ctx *comp_ctx, duk_int_t pc) {
 	DUK_ASSERT(pc >= 0);
-	DUK_ASSERT((duk_size_t) pc < (duk_size_t) (code_end - code_begin));
-
-	return code_begin + pc;
+	DUK_ASSERT((duk_size_t) pc < (duk_size_t) (DUK_BW_GET_SIZE(comp_ctx->thr, &comp_ctx->curr_func.bw_code) / sizeof(duk_compiler_instr)));
+	return ((duk_compiler_instr *) (void *) DUK_BW_GET_BASEPTR(comp_ctx->thr, &comp_ctx->curr_func.bw_code)) + pc;
 }
 
 /* emit instruction; could return PC but that's not needed in the majority
  * of cases.
  */
-static void duk__emit(duk_compiler_ctx *comp_ctx, duk_instr_t ins) {
-	duk_hbuffer_dynamic *h;
+DUK_LOCAL void duk__emit(duk_compiler_ctx *comp_ctx, duk_instr_t ins) {
 #if defined(DUK_USE_PC2LINE)
 	duk_int_t line;
 #endif
-	duk_compiler_instr instr;
+	duk_compiler_instr *instr;
 
-	DUK_DDD(DUK_DDDPRINT("duk__emit: 0x%08lx line=%ld pc=%ld --> %!I",
-	                     (unsigned long) ins, (long) comp_ctx->curr_token.start_line,
-	                     (long) duk__get_current_pc(comp_ctx), (duk_instr_t) ins));
+	DUK_DDD(DUK_DDDPRINT("duk__emit: 0x%08lx curr_token.start_line=%ld prev_token.start_line=%ld pc=%ld --> %!I",
+	                     (unsigned long) ins,
+	                     (long) comp_ctx->curr_token.start_line,
+	                     (long) comp_ctx->prev_token.start_line,
+	                     (long) duk__get_current_pc(comp_ctx),
+	                     (duk_instr_t) ins));
+
+	instr = (duk_compiler_instr *) (void *) DUK_BW_ENSURE_GETPTR(comp_ctx->thr, &comp_ctx->curr_func.bw_code, sizeof(duk_compiler_instr));
+	DUK_BW_ADD_PTR(comp_ctx->thr, &comp_ctx->curr_func.bw_code, sizeof(duk_compiler_instr));
 
-	h = comp_ctx->curr_func.h_code;
 #if defined(DUK_USE_PC2LINE)
-	line = comp_ctx->curr_token.start_line;  /* approximation, close enough */
+	/* The line number tracking is a bit inconsistent right now, which
+	 * affects debugger accuracy.  Mostly call sites emit opcodes when
+	 * they have parsed a token (say a terminating semicolon) and called
+	 * duk__advance().  In this case the line number of the previous
+	 * token is the most accurate one (except in prologue where
+	 * prev_token.start_line is 0).  This is probably not 100% correct
+	 * right now.
+	 */
+	/* approximation, close enough */
+	line = comp_ctx->prev_token.start_line;
+	if (line == 0) {
+		line = comp_ctx->curr_token.start_line;
+	}
 #endif
 
-	instr.ins = ins;
+	instr->ins = ins;
 #if defined(DUK_USE_PC2LINE)
-	instr.line = line;
+	instr->line = line;
+#endif
+#if defined(DUK_USE_DEBUGGER_SUPPORT)
+	if (line < comp_ctx->curr_func.min_line) {
+		comp_ctx->curr_func.min_line = line;
+	}
+	if (line > comp_ctx->curr_func.max_line) {
+		comp_ctx->curr_func.max_line = line;
+	}
 #endif
 
 	/* Limit checks for bytecode byte size and line number. */
-#if defined(DUK_USE_ESBC_LIMITS)
-	if (DUK_UNLIKELY(line > DUK_USE_ESBC_MAX_LINENUMBER ||
-	                 DUK_HBUFFER_GET_SIZE((duk_hbuffer *) h) > DUK_USE_ESBC_MAX_BYTES)) {
-		DUK_ERROR(comp_ctx->thr, DUK_ERR_RANGE_ERROR, DUK_STR_BYTECODE_LIMIT);
+	if (DUK_UNLIKELY(DUK_BW_GET_SIZE(comp_ctx->thr, &comp_ctx->curr_func.bw_code) > DUK_USE_ESBC_MAX_BYTES)) {
+		goto fail_bc_limit;
+	}
+#if defined(DUK_USE_PC2LINE) && defined(DUK_USE_ESBC_LIMITS)
+#if defined(DUK_USE_BUFLEN16)
+	/* Buffer length is bounded to 0xffff automatically, avoid compile warning. */
+	if (DUK_UNLIKELY(line > DUK_USE_ESBC_MAX_LINENUMBER)) {
+		goto fail_bc_limit;
+	}
+#else
+	if (DUK_UNLIKELY(line > DUK_USE_ESBC_MAX_LINENUMBER)) {
+		goto fail_bc_limit;
 	}
 #endif
+#endif
+
+	return;
 
-	duk_hbuffer_append_bytes(comp_ctx->thr, h, (duk_uint8_t *) &instr, sizeof(instr));
+  fail_bc_limit:
+	DUK_ERROR(comp_ctx->thr, DUK_ERR_RANGE_ERROR, DUK_STR_BYTECODE_LIMIT);
+}
+
+/* Update function min/max line from current token.  Needed to improve
+ * function line range information for debugging, so that e.g. opening
+ * curly brace is covered by line range even when no opcodes are emitted
+ * for the line containing the brace.
+ */
+DUK_LOCAL void duk__update_lineinfo_currtoken(duk_compiler_ctx *comp_ctx) {
+#if defined(DUK_USE_DEBUGGER_SUPPORT)
+	duk_int_t line;
+
+	line = comp_ctx->curr_token.start_line;
+	if (line == 0) {
+		return;
+	}
+	if (line < comp_ctx->curr_func.min_line) {
+		comp_ctx->curr_func.min_line = line;
+	}
+	if (line > comp_ctx->curr_func.max_line) {
+		comp_ctx->curr_func.max_line = line;
+	}
+#else
+	DUK_UNREF(comp_ctx);
+#endif
 }
 
 #if 0 /* unused */
-static void duk__emit_op_only(duk_compiler_ctx *comp_ctx, duk_small_uint_t op) {
+DUK_LOCAL void duk__emit_op_only(duk_compiler_ctx *comp_ctx, duk_small_uint_t op) {
 	duk__emit(comp_ctx, DUK_ENC_OP_ABC(op, 0));
 }
 #endif
 
 /* Important main primitive. */
-static void duk__emit_a_b_c(duk_compiler_ctx *comp_ctx, duk_small_uint_t op_flags, duk_regconst_t a, duk_regconst_t b, duk_regconst_t c) {
+DUK_LOCAL void duk__emit_a_b_c(duk_compiler_ctx *comp_ctx, duk_small_uint_t op_flags, duk_regconst_t a, duk_regconst_t b, duk_regconst_t c) {
 	duk_instr_t ins = 0;
-	duk_int_t a_out = 0;
-	duk_int_t b_out = 0;
-	duk_int_t c_out = 0;
+	duk_int_t a_out = -1;
+	duk_int_t b_out = -1;
+	duk_int_t c_out = -1;
 	duk_int_t tmp;
 
 	DUK_DDD(DUK_DDDPRINT("emit: op_flags=%04lx, a=%ld, b=%ld, c=%ld",
 	                     (unsigned long) op_flags, (long) a, (long) b, (long) c));
-	
+
 	/* We could rely on max temp/const checks: if they don't exceed BC
 	 * limit, nothing here can either (just asserts would be enough).
 	 * Currently we check for the limits, which provides additional
@@ -43961,7 +60608,11 @@ static void duk__emit_a_b_c(duk_compiler_ctx *comp_ctx, duk_small_uint_t op_flag
 
 	/* Slot A */
 
+#if defined(DUK_USE_SHUFFLE_TORTURE)
+	if (a <= DUK_BC_A_MAX && (op_flags & DUK__EMIT_FLAG_NO_SHUFFLE_A)) {
+#else
 	if (a <= DUK_BC_A_MAX) {
+#endif
 		;
 	} else if (op_flags & DUK__EMIT_FLAG_NO_SHUFFLE_A) {
 		DUK_D(DUK_DPRINT("out of regs: 'a' (reg) needs shuffling but shuffle prohibited, a: %ld", (long) a));
@@ -43978,7 +60629,7 @@ static void duk__emit_a_b_c(duk_compiler_ctx *comp_ctx, duk_small_uint_t op_flag
 				 * is expressed indirectly, but there is no output shuffling.
 				 */
 				DUK_ASSERT((op_flags & DUK__EMIT_FLAG_A_IS_SOURCE) == 0);
-				duk__emit_load_int32(comp_ctx, tmp, a);
+				duk__emit_load_int32_noshuffle(comp_ctx, tmp, a);
 				DUK_ASSERT(DUK_OP_CSVARI == DUK_OP_CSVAR + 1);
 				DUK_ASSERT(DUK_OP_CSREGI == DUK_OP_CSREG + 1);
 				DUK_ASSERT(DUK_OP_CSPROPI == DUK_OP_CSPROP + 1);
@@ -44002,7 +60653,11 @@ static void duk__emit_a_b_c(duk_compiler_ctx *comp_ctx, duk_small_uint_t op_flag
 		DUK_ASSERT((op_flags & 0xff) != DUK_OP_CALL);
 		DUK_ASSERT((op_flags & 0xff) != DUK_OP_NEW);
 		b = b & ~DUK__CONST_MARKER;
+#if defined(DUK_USE_SHUFFLE_TORTURE)
+		if (0) {
+#else
 		if (b <= 0xff) {
+#endif
 			ins |= DUK_ENC_OP_A_B_C(0, 0, 0x100, 0);  /* const flag for B */
 		} else if (b <= DUK_BC_BC_MAX) {
 			comp_ctx->curr_func.needs_shuffle = 1;
@@ -44014,7 +60669,11 @@ static void duk__emit_a_b_c(duk_compiler_ctx *comp_ctx, duk_small_uint_t op_flag
 			goto error_outofregs;
 		}
 	} else {
+#if defined(DUK_USE_SHUFFLE_TORTURE)
+		if (b <= 0xff && (op_flags & DUK__EMIT_FLAG_NO_SHUFFLE_B)) {
+#else
 		if (b <= 0xff) {
+#endif
 			;
 		} else if (op_flags & DUK__EMIT_FLAG_NO_SHUFFLE_B) {
 			if (b > DUK_BC_B_MAX) {
@@ -44028,7 +60687,8 @@ static void duk__emit_a_b_c(duk_compiler_ctx *comp_ctx, duk_small_uint_t op_flag
 			if (op_flags & DUK__EMIT_FLAG_B_IS_TARGET) {
 				/* Output shuffle needed after main operation */
 				b_out = b;
-			} else {
+			}
+			if (!(op_flags & DUK__EMIT_FLAG_B_IS_TARGET) || (op_flags & DUK__EMIT_FLAG_B_IS_TARGETSOURCE)) {
 				duk_small_int_t op = op_flags & 0xff;
 				if (op == DUK_OP_CALL || op == DUK_OP_NEW ||
 				    op == DUK_OP_MPUTOBJ || op == DUK_OP_MPUTARR) {
@@ -44038,7 +60698,7 @@ static void duk__emit_a_b_c(duk_compiler_ctx *comp_ctx, duk_small_uint_t op_flag
 					 * an indirect version of the opcode is used.
 					 */
 					DUK_ASSERT((op_flags & DUK__EMIT_FLAG_B_IS_TARGET) == 0);
-					duk__emit_load_int32(comp_ctx, tmp, b);
+					duk__emit_load_int32_noshuffle(comp_ctx, tmp, b);
 					DUK_ASSERT(DUK_OP_CALLI == DUK_OP_CALL + 1);
 					DUK_ASSERT(DUK_OP_NEWI == DUK_OP_NEW + 1);
 					DUK_ASSERT(DUK_OP_MPUTOBJI == DUK_OP_MPUTOBJ + 1);
@@ -44061,7 +60721,11 @@ static void duk__emit_a_b_c(duk_compiler_ctx *comp_ctx, duk_small_uint_t op_flag
 		DUK_ASSERT((op_flags & DUK__EMIT_FLAG_NO_SHUFFLE_C) == 0);
 		DUK_ASSERT((op_flags & DUK__EMIT_FLAG_C_IS_TARGET) == 0);
 		c = c & ~DUK__CONST_MARKER;
+#if defined(DUK_USE_SHUFFLE_TORTURE)
+		if (0) {
+#else
 		if (c <= 0xff) {
+#endif
 			ins |= DUK_ENC_OP_A_B_C(0, 0, 0, 0x100);  /* const flag for C */
 		} else if (c <= DUK_BC_BC_MAX) {
 			comp_ctx->curr_func.needs_shuffle = 1;
@@ -44073,7 +60737,11 @@ static void duk__emit_a_b_c(duk_compiler_ctx *comp_ctx, duk_small_uint_t op_flag
 			goto error_outofregs;
 		}
 	} else {
+#if defined(DUK_USE_SHUFFLE_TORTURE)
+		if (c <= 0xff && (op_flags & DUK__EMIT_FLAG_NO_SHUFFLE_C)) {
+#else
 		if (c <= 0xff) {
+#endif
 			;
 		} else if (op_flags & DUK__EMIT_FLAG_NO_SHUFFLE_C) {
 			if (c > DUK_BC_C_MAX) {
@@ -44096,7 +60764,7 @@ static void duk__emit_a_b_c(duk_compiler_ctx *comp_ctx, duk_small_uint_t op_flag
 					 * normally.  Use an indirect variant instead.
 					 */
 					DUK_ASSERT((op_flags & DUK__EMIT_FLAG_C_IS_TARGET) == 0);
-					duk__emit_load_int32(comp_ctx, tmp, c);
+					duk__emit_load_int32_noshuffle(comp_ctx, tmp, c);
 					DUK_ASSERT(DUK_EXTRAOP_INITGETI == DUK_EXTRAOP_INITGET + 1);
 					DUK_ASSERT(DUK_EXTRAOP_INITSETI == DUK_EXTRAOP_INITSET + 1);
 					a++;  /* indirect opcode follows direct */
@@ -44123,22 +60791,34 @@ static void duk__emit_a_b_c(duk_compiler_ctx *comp_ctx, duk_small_uint_t op_flag
 	ins |= DUK_ENC_OP_A_B_C(op_flags & 0xff, a, b, c);
 	duk__emit(comp_ctx, ins);
 
+	/* NEXTENUM needs a jump slot right after the main instruction.
+	 * When the JUMP is taken, output spilling is not needed so this
+	 * workaround is possible.  The jump slot PC is exceptionally
+	 * plumbed through comp_ctx to minimize call sites.
+	 */
+	if (op_flags & DUK__EMIT_FLAG_RESERVE_JUMPSLOT) {
+		comp_ctx->emit_jumpslot_pc = duk__get_current_pc(comp_ctx);
+		duk__emit_abc(comp_ctx, DUK_OP_JUMP, 0);
+	}
+
 	/* Output shuffling: only one output register is realistically possible.
-	 * Zero is OK to check against: if the target register was zero, it is
-	 * never shuffled.
+	 *
+	 * (Zero would normally be an OK marker value: if the target register
+	 * was zero, it would never be shuffled.  But with DUK_USE_SHUFFLE_TORTURE
+	 * this is no longer true, so use -1 as a marker instead.)
 	 */
 
-	if (a_out != 0) {
-		DUK_ASSERT(b_out == 0);
-		DUK_ASSERT(c_out == 0);
+	if (a_out >= 0) {
+		DUK_ASSERT(b_out < 0);
+		DUK_ASSERT(c_out < 0);
 		duk__emit(comp_ctx, DUK_ENC_OP_A_BC(DUK_OP_STREG, a, a_out));
-	} else if (b_out != 0) {
-		DUK_ASSERT(a_out == 0);
-		DUK_ASSERT(c_out == 0);
+	} else if (b_out >= 0) {
+		DUK_ASSERT(a_out < 0);
+		DUK_ASSERT(c_out < 0);
 		duk__emit(comp_ctx, DUK_ENC_OP_A_BC(DUK_OP_STREG, b, b_out));
-	} else if (c_out != 0) {
-		DUK_ASSERT(b_out == 0);
-		DUK_ASSERT(c_out == 0);
+	} else if (c_out >= 0) {
+		DUK_ASSERT(b_out < 0);
+		DUK_ASSERT(c_out < 0);
 		duk__emit(comp_ctx, DUK_ENC_OP_A_BC(DUK_OP_STREG, c, c_out));
 	}
 
@@ -44148,17 +60828,17 @@ static void duk__emit_a_b_c(duk_compiler_ctx *comp_ctx, duk_small_uint_t op_flag
 	DUK_ERROR(comp_ctx->thr, DUK_ERR_RANGE_ERROR, DUK_STR_REG_LIMIT);
 }
 
-static void duk__emit_a_b(duk_compiler_ctx *comp_ctx, duk_small_uint_t op_flags, duk_regconst_t a, duk_regconst_t b) {
-	duk__emit_a_b_c(comp_ctx, op_flags, a, b, 0);
+DUK_LOCAL void duk__emit_a_b(duk_compiler_ctx *comp_ctx, duk_small_uint_t op_flags, duk_regconst_t a, duk_regconst_t b) {
+	duk__emit_a_b_c(comp_ctx, op_flags | DUK__EMIT_FLAG_NO_SHUFFLE_C, a, b, 0);
 }
 
 #if 0  /* unused */
-static void duk__emit_a(duk_compiler_ctx *comp_ctx, int op_flags, int a) {
-	duk__emit_a_b_c(comp_ctx, op_flags, a, 0, 0);
+DUK_LOCAL void duk__emit_a(duk_compiler_ctx *comp_ctx, int op_flags, int a) {
+	duk__emit_a_b_c(comp_ctx, op_flags | DUK__EMIT_FLAG_NO_SHUFFLE_B | DUK__EMIT_FLAG_NO_SHUFFLE_C, a, 0, 0);
 }
 #endif
 
-static void duk__emit_a_bc(duk_compiler_ctx *comp_ctx, duk_small_uint_t op_flags, duk_regconst_t a, duk_regconst_t bc) {
+DUK_LOCAL void duk__emit_a_bc(duk_compiler_ctx *comp_ctx, duk_small_uint_t op_flags, duk_regconst_t a, duk_regconst_t bc) {
 	duk_instr_t ins;
 	duk_int_t tmp;
 
@@ -44178,7 +60858,11 @@ static void duk__emit_a_bc(duk_compiler_ctx *comp_ctx, duk_small_uint_t op_flags
 		goto error_outofregs;
 	}
 
+#if defined(DUK_USE_SHUFFLE_TORTURE)
+	if (a <= DUK_BC_A_MAX && (op_flags & DUK__EMIT_FLAG_NO_SHUFFLE_A)) {
+#else
 	if (a <= DUK_BC_A_MAX) {
+#endif
 		ins = DUK_ENC_OP_A_BC(op_flags & 0xff, a, bc);
 		duk__emit(comp_ctx, ins);
 	} else if (op_flags & DUK__EMIT_FLAG_NO_SHUFFLE_A) {
@@ -44203,7 +60887,7 @@ static void duk__emit_a_bc(duk_compiler_ctx *comp_ctx, duk_small_uint_t op_flags
 	DUK_ERROR(comp_ctx->thr, DUK_ERR_RANGE_ERROR, DUK_STR_REG_LIMIT);
 }
 
-static void duk__emit_abc(duk_compiler_ctx *comp_ctx, duk_small_uint_t op, duk_regconst_t abc) {
+DUK_LOCAL void duk__emit_abc(duk_compiler_ctx *comp_ctx, duk_small_uint_t op, duk_regconst_t abc) {
 	duk_instr_t ins;
 
 	DUK_ASSERT_DISABLE(op >= DUK_BC_OP_MIN);  /* unsigned */
@@ -44212,58 +60896,76 @@ static void duk__emit_abc(duk_compiler_ctx *comp_ctx, duk_small_uint_t op, duk_r
 	DUK_ASSERT(abc <= DUK_BC_ABC_MAX);
 	DUK_ASSERT((abc & DUK__CONST_MARKER) == 0);
 
+	if (abc <= DUK_BC_ABC_MAX) {
+		;
+	} else {
+		goto error_outofregs;
+	}
 	ins = DUK_ENC_OP_ABC(op, abc);
 	DUK_DDD(DUK_DDDPRINT("duk__emit_abc: 0x%08lx line=%ld pc=%ld op=%ld (%!C) abc=%ld (%!I)",
 	                     (unsigned long) ins, (long) comp_ctx->curr_token.start_line,
 	                     (long) duk__get_current_pc(comp_ctx), (long) op, (long) op,
 	                     (long) abc, (duk_instr_t) ins));
 	duk__emit(comp_ctx, ins);
+	return;
+
+ error_outofregs:
+	DUK_ERROR(comp_ctx->thr, DUK_ERR_RANGE_ERROR, DUK_STR_REG_LIMIT);
 }
 
-static void duk__emit_extraop_b_c(duk_compiler_ctx *comp_ctx, duk_small_uint_t extraop_flags, duk_regconst_t b, duk_regconst_t c) {
+DUK_LOCAL void duk__emit_extraop_b_c(duk_compiler_ctx *comp_ctx, duk_small_uint_t extraop_flags, duk_regconst_t b, duk_regconst_t c) {
 	DUK_ASSERT_DISABLE((extraop_flags & 0xff) >= DUK_BC_EXTRAOP_MIN);  /* unsigned */
 	DUK_ASSERT((extraop_flags & 0xff) <= DUK_BC_EXTRAOP_MAX);
-	/* Setting "no shuffle A" would be prudent but not necessary, assert covers it. */
+	/* Setting "no shuffle A" is covered by the assert, but it's needed
+	 * with DUK_USE_SHUFFLE_TORTURE.
+	 */
 	duk__emit_a_b_c(comp_ctx,
-	                DUK_OP_EXTRA | (extraop_flags & ~0xff),  /* transfer flags */
+	                DUK_OP_EXTRA | DUK__EMIT_FLAG_NO_SHUFFLE_A | (extraop_flags & ~0xff),  /* transfer flags */
 	                extraop_flags & 0xff,
 	                b,
 	                c);
 }
 
-static void duk__emit_extraop_b(duk_compiler_ctx *comp_ctx, duk_small_uint_t extraop_flags, duk_regconst_t b) {
+DUK_LOCAL void duk__emit_extraop_b(duk_compiler_ctx *comp_ctx, duk_small_uint_t extraop_flags, duk_regconst_t b) {
 	DUK_ASSERT_DISABLE((extraop_flags & 0xff) >= DUK_BC_EXTRAOP_MIN);  /* unsigned */
 	DUK_ASSERT((extraop_flags & 0xff) <= DUK_BC_EXTRAOP_MAX);
-	/* Setting "no shuffle A" would be prudent but not necessary, assert covers it. */
+	/* Setting "no shuffle A" is covered by the assert, but it's needed
+	 * with DUK_USE_SHUFFLE_TORTURE.
+	 */
 	duk__emit_a_b_c(comp_ctx,
-	                DUK_OP_EXTRA | (extraop_flags & ~0xff),  /* transfer flags */
+	                DUK_OP_EXTRA | DUK__EMIT_FLAG_NO_SHUFFLE_A | (extraop_flags & ~0xff),  /* transfer flags */
 	                extraop_flags & 0xff,
 	                b,
 	                0);
 }
 
-static void duk__emit_extraop_bc(duk_compiler_ctx *comp_ctx, duk_small_uint_t extraop, duk_regconst_t bc) {
+DUK_LOCAL void duk__emit_extraop_bc(duk_compiler_ctx *comp_ctx, duk_small_uint_t extraop, duk_regconst_t bc) {
 	DUK_ASSERT_DISABLE(extraop >= DUK_BC_EXTRAOP_MIN);  /* unsigned */
 	DUK_ASSERT(extraop <= DUK_BC_EXTRAOP_MAX);
-	/* Setting "no shuffle A" would be prudent but not necessary, assert covers it. */
+	/* Setting "no shuffle A" is covered by the assert, but it's needed
+	 * with DUK_USE_SHUFFLE_TORTURE.
+	 */
 	duk__emit_a_bc(comp_ctx,
-	               DUK_OP_EXTRA,
+	               DUK_OP_EXTRA | DUK__EMIT_FLAG_NO_SHUFFLE_A,
 	               extraop,
 	               bc);
 }
 
-static void duk__emit_extraop_only(duk_compiler_ctx *comp_ctx, duk_small_uint_t extraop_flags) {
+DUK_LOCAL void duk__emit_extraop_only(duk_compiler_ctx *comp_ctx, duk_small_uint_t extraop_flags) {
 	DUK_ASSERT_DISABLE((extraop_flags & 0xff) >= DUK_BC_EXTRAOP_MIN);  /* unsigned */
 	DUK_ASSERT((extraop_flags & 0xff) <= DUK_BC_EXTRAOP_MAX);
-	/* Setting "no shuffle A" would be prudent but not necessary, assert covers it. */
+	/* Setting "no shuffle A" is covered by the assert, but it's needed
+	 * with DUK_USE_SHUFFLE_TORTURE.
+	 */
 	duk__emit_a_b_c(comp_ctx,
-	                DUK_OP_EXTRA | (extraop_flags & ~0xff),  /* transfer flags */
+	                DUK_OP_EXTRA | DUK__EMIT_FLAG_NO_SHUFFLE_A | DUK__EMIT_FLAG_NO_SHUFFLE_B |
+	                    DUK__EMIT_FLAG_NO_SHUFFLE_C | (extraop_flags & ~0xff),  /* transfer flags */
 	                extraop_flags & 0xff,
 	                0,
 	                0);
 }
 
-static void duk__emit_load_int32(duk_compiler_ctx *comp_ctx, duk_reg_t reg, duk_int32_t val) {
+DUK_LOCAL void duk__emit_load_int32_raw(duk_compiler_ctx *comp_ctx, duk_reg_t reg, duk_int32_t val, duk_small_uint_t op_flags) {
 	/* XXX: Shuffling support could be implemented here so that LDINT+LDINTX
 	 * would only shuffle once (instead of twice).  The current code works
 	 * though, and has a smaller compiler footprint.
@@ -44272,32 +60974,51 @@ static void duk__emit_load_int32(duk_compiler_ctx *comp_ctx, duk_reg_t reg, duk_
 	if ((val >= (duk_int32_t) DUK_BC_BC_MIN - (duk_int32_t) DUK_BC_LDINT_BIAS) &&
 	    (val <= (duk_int32_t) DUK_BC_BC_MAX - (duk_int32_t) DUK_BC_LDINT_BIAS)) {
 		DUK_DDD(DUK_DDDPRINT("emit LDINT to reg %ld for %ld", (long) reg, (long) val));
-		duk__emit_a_bc(comp_ctx, DUK_OP_LDINT, reg, (duk_regconst_t) (val + (duk_int32_t) DUK_BC_LDINT_BIAS));
+		duk__emit_a_bc(comp_ctx, DUK_OP_LDINT | op_flags, reg, (duk_regconst_t) (val + (duk_int32_t) DUK_BC_LDINT_BIAS));
 	} else {
 		duk_int32_t hi = val >> DUK_BC_LDINTX_SHIFT;
 		duk_int32_t lo = val & ((((duk_int32_t) 1) << DUK_BC_LDINTX_SHIFT) - 1);
 		DUK_ASSERT(lo >= 0);
 		DUK_DDD(DUK_DDDPRINT("emit LDINT+LDINTX to reg %ld for %ld -> hi %ld, lo %ld",
 		                     (long) reg, (long) val, (long) hi, (long) lo));
-		duk__emit_a_bc(comp_ctx, DUK_OP_LDINT, reg, (duk_regconst_t) (hi + (duk_int32_t) DUK_BC_LDINT_BIAS));
-		duk__emit_a_bc(comp_ctx, DUK_OP_LDINTX, reg, (duk_regconst_t) lo);
+		duk__emit_a_bc(comp_ctx, DUK_OP_LDINT | op_flags, reg, (duk_regconst_t) (hi + (duk_int32_t) DUK_BC_LDINT_BIAS));
+		duk__emit_a_bc(comp_ctx, DUK_OP_LDINTX | op_flags, reg, (duk_regconst_t) lo);
 	}
 }
 
-static void duk__emit_jump(duk_compiler_ctx *comp_ctx, duk_int_t target_pc) {
-	duk_hbuffer_dynamic *h;
+DUK_LOCAL void duk__emit_load_int32(duk_compiler_ctx *comp_ctx, duk_reg_t reg, duk_int32_t val) {
+	duk__emit_load_int32_raw(comp_ctx, reg, val, 0 /*op_flags*/);
+}
+
+#if defined(DUK_USE_SHUFFLE_TORTURE)
+/* Used by duk__emit*() calls so that we don't shuffle the loadints that
+ * are needed to handle indirect opcodes.
+ */
+DUK_LOCAL void duk__emit_load_int32_noshuffle(duk_compiler_ctx *comp_ctx, duk_reg_t reg, duk_int32_t val) {
+	duk__emit_load_int32_raw(comp_ctx, reg, val, DUK__EMIT_FLAG_NO_SHUFFLE_A /*op_flags*/);
+}
+#else
+DUK_LOCAL void duk__emit_load_int32_noshuffle(duk_compiler_ctx *comp_ctx, duk_reg_t reg, duk_int32_t val) {
+	/* When torture not enabled, can just use the same helper because
+	 * 'reg' won't get spilled.
+	 */
+	DUK_ASSERT(reg <= DUK_BC_A_MAX);
+	duk__emit_load_int32(comp_ctx, reg, val);
+}
+#endif
+
+DUK_LOCAL void duk__emit_jump(duk_compiler_ctx *comp_ctx, duk_int_t target_pc) {
 	duk_int_t curr_pc;
 	duk_int_t offset;
 
-	h = comp_ctx->curr_func.h_code;
-	curr_pc = (duk_int_t) (DUK_HBUFFER_GET_SIZE(h) / sizeof(duk_compiler_instr));
+	curr_pc = (duk_int_t) (DUK_BW_GET_SIZE(comp_ctx->thr, &comp_ctx->curr_func.bw_code) / sizeof(duk_compiler_instr));
 	offset = (duk_int_t) target_pc - (duk_int_t) curr_pc - 1;
 	DUK_ASSERT(offset + DUK_BC_JUMP_BIAS >= DUK_BC_ABC_MIN);
 	DUK_ASSERT(offset + DUK_BC_JUMP_BIAS <= DUK_BC_ABC_MAX);
 	duk__emit_abc(comp_ctx, DUK_OP_JUMP, (duk_regconst_t) (offset + DUK_BC_JUMP_BIAS));
 }
 
-static duk_int_t duk__emit_jump_empty(duk_compiler_ctx *comp_ctx) {
+DUK_LOCAL duk_int_t duk__emit_jump_empty(duk_compiler_ctx *comp_ctx) {
 	duk_int_t ret;
 
 	ret = duk__get_current_pc(comp_ctx);  /* useful for patching jumps later */
@@ -44308,33 +61029,42 @@ static duk_int_t duk__emit_jump_empty(duk_compiler_ctx *comp_ctx) {
 /* Insert an empty jump in the middle of code emitted earlier.  This is
  * currently needed for compiling for-in.
  */
-static void duk__insert_jump_entry(duk_compiler_ctx *comp_ctx, duk_int_t jump_pc) {
-	duk_hbuffer_dynamic *h;
+DUK_LOCAL void duk__insert_jump_entry(duk_compiler_ctx *comp_ctx, duk_int_t jump_pc) {
 #if defined(DUK_USE_PC2LINE)
 	duk_int_t line;
 #endif
-	duk_compiler_instr instr;
+	duk_compiler_instr *instr;
 	duk_size_t offset;
 
-	h = comp_ctx->curr_func.h_code;
+	offset = jump_pc * sizeof(duk_compiler_instr),
+	instr = (duk_compiler_instr *) (void *)
+	        DUK_BW_INSERT_ENSURE_AREA(comp_ctx->thr,
+	                                  &comp_ctx->curr_func.bw_code,
+	                                  offset,
+	                                  sizeof(duk_compiler_instr));
+
 #if defined(DUK_USE_PC2LINE)
 	line = comp_ctx->curr_token.start_line;  /* approximation, close enough */
 #endif
-
-	instr.ins = DUK_ENC_OP_ABC(DUK_OP_JUMP, 0);
+	instr->ins = DUK_ENC_OP_ABC(DUK_OP_JUMP, 0);
 #if defined(DUK_USE_PC2LINE)
-	instr.line = line;
+	instr->line = line;
 #endif
 
-	offset = jump_pc * sizeof(duk_compiler_instr);
+	DUK_BW_ADD_PTR(comp_ctx->thr, &comp_ctx->curr_func.bw_code, sizeof(duk_compiler_instr));
+	if (DUK_UNLIKELY(DUK_BW_GET_SIZE(comp_ctx->thr, &comp_ctx->curr_func.bw_code) > DUK_USE_ESBC_MAX_BYTES)) {
+		goto fail_bc_limit;
+	}
+	return;
 
-	duk_hbuffer_insert_bytes(comp_ctx->thr, h, offset, (duk_uint8_t *) &instr, sizeof(instr));
+  fail_bc_limit:
+	DUK_ERROR(comp_ctx->thr, DUK_ERR_RANGE_ERROR, DUK_STR_BYTECODE_LIMIT);
 }
 
 /* Does not assume that jump_pc contains a DUK_OP_JUMP previously; this is intentional
  * to allow e.g. an INVALID opcode be overwritten with a JUMP (label management uses this).
  */
-static void duk__patch_jump(duk_compiler_ctx *comp_ctx, duk_int_t jump_pc, duk_int_t target_pc) {
+DUK_LOCAL void duk__patch_jump(duk_compiler_ctx *comp_ctx, duk_int_t jump_pc, duk_int_t target_pc) {
 	duk_compiler_instr *instr;
 	duk_int_t offset;
 
@@ -44358,29 +61088,66 @@ static void duk__patch_jump(duk_compiler_ctx *comp_ctx, duk_int_t jump_pc, duk_i
 	                     (long) jump_pc, (long) target_pc, (long) offset));
 }
 
-static void duk__patch_jump_here(duk_compiler_ctx *comp_ctx, duk_int_t jump_pc) {
+DUK_LOCAL void duk__patch_jump_here(duk_compiler_ctx *comp_ctx, duk_int_t jump_pc) {
 	duk__patch_jump(comp_ctx, jump_pc, duk__get_current_pc(comp_ctx));
 }
 
-static void duk__patch_trycatch(duk_compiler_ctx *comp_ctx, duk_int_t trycatch_pc, duk_regconst_t reg_catch, duk_regconst_t const_varname, duk_small_uint_t flags) {
+DUK_LOCAL void duk__patch_trycatch(duk_compiler_ctx *comp_ctx, duk_int_t ldconst_pc, duk_int_t trycatch_pc, duk_regconst_t reg_catch, duk_regconst_t const_varname, duk_small_uint_t flags) {
 	duk_compiler_instr *instr;
 
-	instr = duk__get_instr_ptr(comp_ctx, trycatch_pc);
+	DUK_ASSERT((reg_catch & DUK__CONST_MARKER) == 0);
+
+	instr = duk__get_instr_ptr(comp_ctx, ldconst_pc);
+	DUK_ASSERT(DUK_DEC_OP(instr->ins) == DUK_OP_LDCONST);
 	DUK_ASSERT(instr != NULL);
+	if (const_varname & DUK__CONST_MARKER) {
+		/* Have a catch variable. */
+		const_varname = const_varname & (~DUK__CONST_MARKER);
+		if (reg_catch > DUK_BC_BC_MAX || const_varname > DUK_BC_BC_MAX) {
+			/* Catch attempts to use out-of-range reg/const.  Without this
+			 * check Duktape 0.12.0 could generate invalid code which caused
+			 * an assert failure on execution.  This error is triggered e.g.
+			 * for functions with a lot of constants and a try-catch statement.
+			 * Shuffling or opcode semantics change is needed to fix the issue.
+			 * See: test-bug-trycatch-many-constants.js.
+			 */
+			DUK_D(DUK_DPRINT("failed to patch trycatch: flags=%ld, reg_catch=%ld, const_varname=%ld (0x%08lx)",
+			                 (long) flags, (long) reg_catch, (long) const_varname, (long) const_varname));
+			DUK_ERROR(comp_ctx->thr, DUK_ERR_INTERNAL_ERROR, DUK_STR_REG_LIMIT);
+		}
+		instr->ins |= DUK_ENC_OP_A_BC(0, 0, const_varname);
+	} else {
+		/* No catch variable, e.g. a try-finally; replace LDCONST with
+		 * NOP to avoid a bogus LDCONST.
+		 */
+		instr->ins = DUK_ENC_OP_A(DUK_OP_EXTRA, DUK_EXTRAOP_NOP);
+	}
 
-	instr->ins = DUK_ENC_OP_A_B_C(DUK_OP_TRYCATCH, flags, reg_catch, const_varname);
+	instr = duk__get_instr_ptr(comp_ctx, trycatch_pc);
+	DUK_ASSERT(instr != NULL);
+	DUK_ASSERT_DISABLE(flags >= DUK_BC_A_MIN);
+	DUK_ASSERT(flags <= DUK_BC_A_MAX);
+	instr->ins = DUK_ENC_OP_A_BC(DUK_OP_TRYCATCH, flags, reg_catch);
 }
 
-static void duk__emit_if_false_skip(duk_compiler_ctx *comp_ctx, duk_regconst_t regconst) {
-	duk__emit_a_b_c(comp_ctx, DUK_OP_IF, 0 /*false*/, regconst, 0);
+DUK_LOCAL void duk__emit_if_false_skip(duk_compiler_ctx *comp_ctx, duk_regconst_t regconst) {
+	duk__emit_a_b_c(comp_ctx,
+	                DUK_OP_IF | DUK__EMIT_FLAG_NO_SHUFFLE_A | DUK__EMIT_FLAG_NO_SHUFFLE_C,
+	                0 /*false*/,
+	                regconst,
+	                0 /*unused*/);
 }
 
-static void duk__emit_if_true_skip(duk_compiler_ctx *comp_ctx, duk_regconst_t regconst) {
-	duk__emit_a_b_c(comp_ctx, DUK_OP_IF, 1 /*true*/, regconst, 0);
+DUK_LOCAL void duk__emit_if_true_skip(duk_compiler_ctx *comp_ctx, duk_regconst_t regconst) {
+	duk__emit_a_b_c(comp_ctx,
+	                DUK_OP_IF | DUK__EMIT_FLAG_NO_SHUFFLE_A | DUK__EMIT_FLAG_NO_SHUFFLE_C,
+	                1 /*true*/,
+	                regconst,
+	                0 /*unused*/);
 }
 
-static void duk__emit_invalid(duk_compiler_ctx *comp_ctx) {
-	duk__emit_abc(comp_ctx, DUK_OP_INVALID, 0);
+DUK_LOCAL void duk__emit_invalid(duk_compiler_ctx *comp_ctx) {
+	duk__emit_extraop_bc(comp_ctx, DUK_EXTRAOP_INVALID, 0);
 }
 
 /*
@@ -44390,20 +61157,19 @@ static void duk__emit_invalid(duk_compiler_ctx *comp_ctx) {
  *  jump chains which are generated by several control structures.
  */
 
-static void duk__peephole_optimize_bytecode(duk_compiler_ctx *comp_ctx) {
-	duk_hbuffer_dynamic *h;
+DUK_LOCAL void duk__peephole_optimize_bytecode(duk_compiler_ctx *comp_ctx) {
 	duk_compiler_instr *bc;
 	duk_small_uint_t iter;
 	duk_int_t i, n;
 	duk_int_t count_opt;
 
-	h = comp_ctx->curr_func.h_code;
-	DUK_ASSERT(h != NULL);
-	DUK_ASSERT(DUK_HBUFFER_HAS_DYNAMIC(h));
-
-	bc = (duk_compiler_instr *) DUK_HBUFFER_DYNAMIC_GET_CURR_DATA_PTR(h);
-	DUK_ASSERT(DUK_HBUFFER_GET_SIZE(h) / sizeof(duk_compiler_instr) <= DUK_INT_MAX);  /* bytecode limits */
-	n = (duk_int_t) (DUK_HBUFFER_GET_SIZE(h) / sizeof(duk_compiler_instr));
+	bc = (duk_compiler_instr *) (void *) DUK_BW_GET_BASEPTR(comp_ctx->thr, &comp_ctx->curr_func.bw_code);
+#if defined(DUK_USE_BUFLEN16)
+	/* No need to assert, buffer size maximum is 0xffff. */
+#else
+	DUK_ASSERT((duk_size_t) DUK_BW_GET_SIZE(comp_ctx->thr, &comp_ctx->curr_func.bw_code) / sizeof(duk_compiler_instr) <= (duk_size_t) DUK_INT_MAX);  /* bytecode limits */
+#endif
+	n = (duk_int_t) (DUK_BW_GET_SIZE(comp_ctx->thr, &comp_ctx->curr_func.bw_code) / sizeof(duk_compiler_instr));
 
 	for (iter = 0; iter < DUK_COMPILER_PEEPHOLE_MAXITER; iter++) {
 		count_opt = 0;
@@ -44417,7 +61183,7 @@ static void duk__peephole_optimize_bytecode(duk_compiler_ctx *comp_ctx) {
 			if (DUK_DEC_OP(ins) != DUK_OP_JUMP) {
 				continue;
 			}
-	
+
 			target_pc1 = i + 1 + DUK_DEC_ABC(ins) - DUK_BC_JUMP_BIAS;
 			DUK_DDD(DUK_DDDPRINT("consider jump at pc %ld; target_pc=%ld", (long) i, (long) target_pc1));
 			DUK_ASSERT(target_pc1 >= 0);
@@ -44469,12 +61235,36 @@ static void duk__peephole_optimize_bytecode(duk_compiler_ctx *comp_ctx) {
  * code (it is checked as it is used).
  */
 #define DUK__IVAL_FLAG_ALLOW_CONST          (1 << 0)  /* allow a constant to be returned */
-#define DUK__IVAL_FLAG_REQUIRE_TEMP         (1 << 1)  /* require a (mutable) temporary as a result */
+#define DUK__IVAL_FLAG_REQUIRE_TEMP         (1 << 1)  /* require a (mutable) temporary as a result (or a const if allowed) */
 #define DUK__IVAL_FLAG_REQUIRE_SHORT        (1 << 2)  /* require a short (8-bit) reg/const which fits into bytecode B/C slot */
 
 /* XXX: some code might benefit from DUK__SETTEMP_IFTEMP(ctx,x) */
 
-static void duk__copy_ispec(duk_compiler_ctx *comp_ctx, duk_ispec *src, duk_ispec *dst) {
+#if 0  /* enable manually for dumping */
+#define DUK__DUMP_ISPEC(compctx,ispec) do { duk__dump_ispec((compctx), (ispec)); } while (0)
+#define DUK__DUMP_IVALUE(compctx,ivalue) do { duk__dump_ivalue((compctx), (ivalue)); } while (0)
+
+DUK_LOCAL void duk__dump_ispec(duk_compiler_ctx *comp_ctx, duk_ispec *x) {
+	DUK_D(DUK_DPRINT("ispec dump: t=%ld regconst=0x%08lx, valstack_idx=%ld, value=%!T",
+	                 (long) x->t, (unsigned long) x->regconst, (long) x->valstack_idx,
+	                 duk_get_tval((duk_context *) comp_ctx->thr, x->valstack_idx)));
+}
+DUK_LOCAL void duk__dump_ivalue(duk_compiler_ctx *comp_ctx, duk_ivalue *x) {
+	DUK_D(DUK_DPRINT("ivalue dump: t=%ld op=%ld "
+	                 "x1={t=%ld regconst=0x%08lx valstack_idx=%ld value=%!T} "
+	                 "x2={t=%ld regconst=0x%08lx valstack_idx=%ld value=%!T}",
+		         (long) x->t, (long) x->op,
+	                 (long) x->x1.t, (unsigned long) x->x1.regconst, (long) x->x1.valstack_idx,
+	                 duk_get_tval((duk_context *) comp_ctx->thr, x->x1.valstack_idx),
+	                 (long) x->x2.t, (unsigned long) x->x2.regconst, (long) x->x2.valstack_idx,
+	                 duk_get_tval((duk_context *) comp_ctx->thr, x->x2.valstack_idx)));
+}
+#else
+#define DUK__DUMP_ISPEC(comp_ctx,x) do {} while (0)
+#define DUK__DUMP_IVALUE(comp_ctx,x) do {} while (0)
+#endif
+
+DUK_LOCAL void duk__copy_ispec(duk_compiler_ctx *comp_ctx, duk_ispec *src, duk_ispec *dst) {
 	duk_context *ctx = (duk_context *) comp_ctx->thr;
 
 	dst->t = src->t;
@@ -44482,7 +61272,7 @@ static void duk__copy_ispec(duk_compiler_ctx *comp_ctx, duk_ispec *src, duk_ispe
 	duk_copy(ctx, src->valstack_idx, dst->valstack_idx);
 }
 
-static void duk__copy_ivalue(duk_compiler_ctx *comp_ctx, duk_ivalue *src, duk_ivalue *dst) {
+DUK_LOCAL void duk__copy_ivalue(duk_compiler_ctx *comp_ctx, duk_ivalue *src, duk_ivalue *dst) {
 	duk_context *ctx = (duk_context *) comp_ctx->thr;
 
 	dst->t = src->t;
@@ -44496,7 +61286,7 @@ static void duk__copy_ivalue(duk_compiler_ctx *comp_ctx, duk_ivalue *src, duk_iv
 }
 
 /* XXX: to util */
-static duk_bool_t duk__is_whole_get_int32(duk_double_t x, duk_int32_t *ival) {
+DUK_LOCAL duk_bool_t duk__is_whole_get_int32(duk_double_t x, duk_int32_t *ival) {
 	duk_small_int_t c;
 	duk_int32_t t;
 
@@ -44515,7 +61305,7 @@ static duk_bool_t duk__is_whole_get_int32(duk_double_t x, duk_int32_t *ival) {
 	return 0;
 }
 
-static duk_reg_t duk__alloctemps(duk_compiler_ctx *comp_ctx, duk_small_int_t num) {
+DUK_LOCAL duk_reg_t duk__alloctemps(duk_compiler_ctx *comp_ctx, duk_small_int_t num) {
 	duk_reg_t res;
 
 	res = comp_ctx->curr_func.temp_next;
@@ -44533,11 +61323,11 @@ static duk_reg_t duk__alloctemps(duk_compiler_ctx *comp_ctx, duk_small_int_t num
 	return res;
 }
 
-static duk_reg_t duk__alloctemp(duk_compiler_ctx *comp_ctx) {
+DUK_LOCAL duk_reg_t duk__alloctemp(duk_compiler_ctx *comp_ctx) {
 	return duk__alloctemps(comp_ctx, 1);
 }
 
-static void duk__settemp_checkmax(duk_compiler_ctx *comp_ctx, duk_reg_t temp_next) {
+DUK_LOCAL void duk__settemp_checkmax(duk_compiler_ctx *comp_ctx, duk_reg_t temp_next) {
 	comp_ctx->curr_func.temp_next = temp_next;
 	if (temp_next > comp_ctx->curr_func.temp_max) {
 		comp_ctx->curr_func.temp_max = temp_next;
@@ -44545,7 +61335,7 @@ static void duk__settemp_checkmax(duk_compiler_ctx *comp_ctx, duk_reg_t temp_nex
 }
 
 /* get const for value at valstack top */
-static duk_regconst_t duk__getconst(duk_compiler_ctx *comp_ctx) {
+DUK_LOCAL duk_regconst_t duk__getconst(duk_compiler_ctx *comp_ctx) {
 	duk_hthread *thr = comp_ctx->thr;
 	duk_context *ctx = (duk_context *) thr;
 	duk_compiler_func *f = &comp_ctx->curr_func;
@@ -44557,13 +61347,18 @@ static duk_regconst_t duk__getconst(duk_compiler_ctx *comp_ctx) {
 	tv1 = duk_get_tval(ctx, -1);
 	DUK_ASSERT(tv1 != NULL);
 
+#if defined(DUK_USE_FASTINT)
+	/* Explicit check for fastint downgrade. */
+	DUK_TVAL_CHKFAST_INPLACE(tv1);
+#endif
+
 	/* Sanity workaround for handling functions with a large number of
 	 * constants at least somewhat reasonably.  Otherwise checking whether
 	 * we already have the constant would grow very slow (as it is O(N^2)).
 	 */
 	n_check = (n > DUK__GETCONST_MAX_CONSTS_CHECK ? DUK__GETCONST_MAX_CONSTS_CHECK : n);
 	for (i = 0; i < n_check; i++) {
-		duk_tval *tv2 = DUK_HOBJECT_A_GET_VALUE_PTR(f->h_consts, i);
+		duk_tval *tv2 = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, f->h_consts, i);
 
 		/* Strict equality is NOT enough, because we cannot use the same
 		 * constant for e.g. +0 and -0.
@@ -44576,7 +61371,7 @@ static duk_regconst_t duk__getconst(duk_compiler_ctx *comp_ctx) {
 		}
 	}
 
-	if (n >= DUK__MAX_CONSTS) {
+	if (n > DUK__MAX_CONSTS) {
 		DUK_ERROR(comp_ctx->thr, DUK_ERR_INTERNAL_ERROR, DUK_STR_CONST_LIMIT);
 	}
 
@@ -44602,10 +61397,11 @@ static duk_regconst_t duk__getconst(duk_compiler_ctx *comp_ctx) {
  * value is either a register or a constant.
  */
 
-static duk_regconst_t duk__ispec_toregconst_raw(duk_compiler_ctx *comp_ctx,
-                                                duk_ispec *x,
-                                                duk_reg_t forced_reg,
-                                                duk_small_uint_t flags) {
+DUK_LOCAL
+duk_regconst_t duk__ispec_toregconst_raw(duk_compiler_ctx *comp_ctx,
+                                         duk_ispec *x,
+                                         duk_reg_t forced_reg,
+                                         duk_small_uint_t flags) {
 	duk_hthread *thr = comp_ctx->thr;
 	duk_context *ctx = (duk_context *) thr;
 
@@ -44689,6 +61485,13 @@ static duk_regconst_t duk__ispec_toregconst_raw(duk_compiler_ctx *comp_ctx,
 			DUK_UNREACHABLE();
 			break;
 		}
+		case DUK_TAG_LIGHTFUNC: {
+			DUK_UNREACHABLE();
+			break;
+		}
+#if defined(DUK_USE_FASTINT)
+		case DUK_TAG_FASTINT:
+#endif
 		default: {
 			/* number */
 			duk_reg_t dest;
@@ -44696,6 +61499,7 @@ static duk_regconst_t duk__ispec_toregconst_raw(duk_compiler_ctx *comp_ctx,
 			duk_double_t dval;
 			duk_int32_t ival;
 
+			DUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv));
 			DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));
 			dval = DUK_TVAL_GET_NUMBER(tv);
 
@@ -44727,26 +61531,34 @@ static duk_regconst_t duk__ispec_toregconst_raw(duk_compiler_ctx *comp_ctx,
 		}  /* end switch */
 	}
 	case DUK_ISPEC_REGCONST: {
-		if ((x->regconst & DUK__CONST_MARKER) && !(flags & DUK__IVAL_FLAG_ALLOW_CONST)) {
-			duk_reg_t dest = (forced_reg >= 0 ? forced_reg : DUK__ALLOCTEMP(comp_ctx));
-			duk__emit_a_bc(comp_ctx, DUK_OP_LDCONST, (duk_regconst_t) dest, x->regconst);
-			return (duk_regconst_t) dest;
-		} else {
-			if (forced_reg >= 0) {
-				if (x->regconst != (duk_regconst_t) forced_reg) {
-					duk__emit_a_bc(comp_ctx, DUK_OP_LDREG, forced_reg, x->regconst);
-				}
-				return (duk_regconst_t) forced_reg;
+		if (forced_reg >= 0) {
+			if (x->regconst & DUK__CONST_MARKER) {
+				duk__emit_a_bc(comp_ctx, DUK_OP_LDCONST, forced_reg, x->regconst);
+			} else if (x->regconst != (duk_regconst_t) forced_reg) {
+				duk__emit_a_bc(comp_ctx, DUK_OP_LDREG, forced_reg, x->regconst);
 			} else {
-				if ((flags & DUK__IVAL_FLAG_REQUIRE_TEMP) && !DUK__ISTEMP(comp_ctx, x->regconst)) {
-					duk_reg_t dest = DUK__ALLOCTEMP(comp_ctx);
-					duk__emit_a_bc(comp_ctx, DUK_OP_LDREG, (duk_regconst_t) dest, x->regconst);
-					return (duk_regconst_t) dest;
-				} else {
-					return x->regconst;
-				}
+				; /* already in correct reg */
+			}
+			return (duk_regconst_t) forced_reg;
+		}
+
+		DUK_ASSERT(forced_reg < 0);
+		if (x->regconst & DUK__CONST_MARKER) {
+			if (!(flags & DUK__IVAL_FLAG_ALLOW_CONST)) {
+				duk_reg_t dest = DUK__ALLOCTEMP(comp_ctx);
+				duk__emit_a_bc(comp_ctx, DUK_OP_LDCONST, (duk_regconst_t) dest, x->regconst);
+				return (duk_regconst_t) dest;
 			}
+			return x->regconst;
 		}
+
+		DUK_ASSERT(forced_reg < 0 && !(x->regconst & DUK__CONST_MARKER));
+		if ((flags & DUK__IVAL_FLAG_REQUIRE_TEMP) && !DUK__ISTEMP(comp_ctx, x->regconst)) {
+			duk_reg_t dest = DUK__ALLOCTEMP(comp_ctx);
+			duk__emit_a_bc(comp_ctx, DUK_OP_LDREG, (duk_regconst_t) dest, x->regconst);
+			return (duk_regconst_t) dest;
+		}
+		return x->regconst;
 	}
 	default: {
 		break;
@@ -44757,7 +61569,7 @@ static duk_regconst_t duk__ispec_toregconst_raw(duk_compiler_ctx *comp_ctx,
 	return 0;
 }
 
-static void duk__ispec_toforcedreg(duk_compiler_ctx *comp_ctx, duk_ispec *x, duk_reg_t forced_reg) {
+DUK_LOCAL void duk__ispec_toforcedreg(duk_compiler_ctx *comp_ctx, duk_ispec *x, duk_reg_t forced_reg) {
 	DUK_ASSERT(forced_reg >= 0);
 	(void) duk__ispec_toregconst_raw(comp_ctx, x, forced_reg, 0 /*flags*/);
 }
@@ -44767,7 +61579,7 @@ static void duk__ispec_toforcedreg(duk_compiler_ctx *comp_ctx, duk_ispec *x, duk
  * The duk_ivalue argument ('x') is converted into a plain value as a
  * side effect.
  */
-static void duk__ivalue_toplain_raw(duk_compiler_ctx *comp_ctx, duk_ivalue *x, duk_reg_t forced_reg) {
+DUK_LOCAL void duk__ivalue_toplain_raw(duk_compiler_ctx *comp_ctx, duk_ivalue *x, duk_reg_t forced_reg) {
 	duk_hthread *thr = comp_ctx->thr;
 	duk_context *ctx = (duk_context *) thr;
 
@@ -44785,7 +61597,8 @@ static void duk__ivalue_toplain_raw(duk_compiler_ctx *comp_ctx, duk_ivalue *x, d
 		return;
 	}
 	/* XXX: support unary arithmetic ivalues (useful?) */
-	case DUK_IVAL_ARITH: {
+	case DUK_IVAL_ARITH:
+	case DUK_IVAL_ARITH_EXTRAOP: {
 		duk_regconst_t arg1;
 		duk_regconst_t arg2;
 		duk_reg_t dest;
@@ -44796,7 +61609,7 @@ static void duk__ivalue_toplain_raw(duk_compiler_ctx *comp_ctx, duk_ivalue *x, d
 
 		/* inline arithmetic check for constant values */
 		/* XXX: use the exactly same arithmetic function here as in executor */
-		if (x->x1.t == DUK_ISPEC_VALUE && x->x2.t == DUK_ISPEC_VALUE) {
+		if (x->x1.t == DUK_ISPEC_VALUE && x->x2.t == DUK_ISPEC_VALUE && x->t == DUK_IVAL_ARITH) {
 			tv1 = duk_get_tval(ctx, x->x1.valstack_idx);
 			tv2 = duk_get_tval(ctx, x->x2.valstack_idx);
 			DUK_ASSERT(tv1 != NULL);
@@ -44815,11 +61628,11 @@ static void duk__ivalue_toplain_raw(duk_compiler_ctx *comp_ctx, duk_ivalue *x, d
 				DUK_DDD(DUK_DDDPRINT("arith inline check: d1=%lf, d2=%lf, op=%ld",
 				                     (double) d1, (double) d2, (long) x->op));
 				switch (x->op) {
-				case DUK_OP_ADD:	d3 = d1 + d2; break;
-				case DUK_OP_SUB:	d3 = d1 - d2; break;
-				case DUK_OP_MUL:	d3 = d1 * d2; break;
-				case DUK_OP_DIV:	d3 = d1 / d2; break;
-				default:		accept = 0; break;
+				case DUK_OP_ADD:  d3 = d1 + d2; break;
+				case DUK_OP_SUB:  d3 = d1 - d2; break;
+				case DUK_OP_MUL:  d3 = d1 * d2; break;
+				case DUK_OP_DIV:  d3 = d1 / d2; break;
+				default:          accept = 0; break;
 				}
 
 				if (accept) {
@@ -44850,18 +61663,62 @@ static void duk__ivalue_toplain_raw(duk_compiler_ctx *comp_ctx, duk_ivalue *x, d
 
 		/* If forced reg, use it as destination.  Otherwise try to
 		 * use either coerced ispec if it is a temporary.
+		 *
+		 * When using extraops, avoid reusing arg2 as dest because that
+		 * would lead to an LDREG shuffle below.  We still can't guarantee
+		 * dest != arg2 because we may have a forced_reg.
 		 */
 		if (forced_reg >= 0) {
 			dest = forced_reg;
 		} else if (DUK__ISTEMP(comp_ctx, arg1)) {
 			dest = (duk_reg_t) arg1;
-		} else if (DUK__ISTEMP(comp_ctx, arg2)) {
+		} else if (DUK__ISTEMP(comp_ctx, arg2) && x->t != DUK_IVAL_ARITH_EXTRAOP) {
 			dest = (duk_reg_t) arg2;
 		} else {
 			dest = DUK__ALLOCTEMP(comp_ctx);
 		}
 
-		duk__emit_a_b_c(comp_ctx, x->op, (duk_regconst_t) dest, arg1, arg2);
+		/* Extraop arithmetic opcodes must have destination same as
+		 * first source.  If second source matches destination we need
+		 * a temporary register to avoid clobbering the second source.
+		 *
+		 * XXX: change calling code to avoid this situation in most cases.
+		 */
+
+		if (x->t == DUK_IVAL_ARITH_EXTRAOP) {
+			if (!(DUK__ISREG(comp_ctx, arg1) && (duk_reg_t) arg1 == dest)) {
+				if (DUK__ISREG(comp_ctx, arg2) && (duk_reg_t) arg2 == dest) {
+					/* arg2 would be clobbered so reassign it to a temp. */
+					duk_reg_t tempreg;
+					tempreg = DUK__ALLOCTEMP(comp_ctx);
+					duk__emit_a_bc(comp_ctx, DUK_OP_LDREG, tempreg, arg2);
+					arg2 = tempreg;
+				}
+
+				if (DUK__ISREG(comp_ctx, arg1)) {
+					duk__emit_a_bc(comp_ctx, DUK_OP_LDREG, dest, arg1);
+				} else {
+					DUK_ASSERT(DUK__ISCONST(comp_ctx, arg1));
+					duk__emit_a_bc(comp_ctx, DUK_OP_LDCONST, dest, arg1);
+				}
+			}
+
+			/* Note: special DUK__EMIT_FLAG_B_IS_TARGETSOURCE
+			 * used to indicate that B is both a source and a
+			 * target register.  When shuffled, it needs to be
+			 * both input and output shuffled.
+			 */
+			DUK_ASSERT(DUK__ISREG(comp_ctx, dest));
+			duk__emit_extraop_b_c(comp_ctx,
+			                      x->op | DUK__EMIT_FLAG_B_IS_TARGET |
+			                              DUK__EMIT_FLAG_B_IS_TARGETSOURCE,
+			                      (duk_regconst_t) dest,
+			                      (duk_regconst_t) arg2);
+
+		} else {
+			DUK_ASSERT(DUK__ISREG(comp_ctx, dest));
+			duk__emit_a_b_c(comp_ctx, x->op, (duk_regconst_t) dest, arg1, arg2);
+		}
 
 		x->t = DUK_IVAL_PLAIN;
 		x->x1.t = DUK_ISPEC_REGCONST;
@@ -44874,17 +61731,24 @@ static void duk__ivalue_toplain_raw(duk_compiler_ctx *comp_ctx, duk_ivalue *x, d
 		duk_regconst_t arg2;
 		duk_reg_t dest;
 
-		/* need a short reg/const, does not have to be a mutable temp */
+		/* Need a short reg/const, does not have to be a mutable temp. */
 		arg1 = duk__ispec_toregconst_raw(comp_ctx, &x->x1, -1, DUK__IVAL_FLAG_ALLOW_CONST | DUK__IVAL_FLAG_REQUIRE_SHORT /*flags*/);
 		arg2 = duk__ispec_toregconst_raw(comp_ctx, &x->x2, -1, DUK__IVAL_FLAG_ALLOW_CONST | DUK__IVAL_FLAG_REQUIRE_SHORT /*flags*/);
 
+		/* Pick a destination register.  If either base value or key
+		 * happens to be a temp value, reuse it as the destination.
+		 *
+		 * XXX: The temp must be a "mutable" one, i.e. such that no
+		 * other expression is using it anymore.  Here this should be
+		 * the case because the value of a property access expression
+		 * is neither the base nor the key, but the lookup result.
+		 */
+
 		if (forced_reg >= 0) {
 			dest = forced_reg;
 		} else if (DUK__ISTEMP(comp_ctx, arg1)) {
-			/* FIXME: arg1 being used as a mutable temp? */
 			dest = (duk_reg_t) arg1;
 		} else if (DUK__ISTEMP(comp_ctx, arg2)) {
-			/* FIXME: arg1 being used as a mutable temp? */
 			dest = (duk_reg_t) arg2;
 		} else {
 			dest = DUK__ALLOCTEMP(comp_ctx);
@@ -44930,12 +61794,12 @@ static void duk__ivalue_toplain_raw(duk_compiler_ctx *comp_ctx, duk_ivalue *x, d
 }
 
 /* evaluate to plain value, no forced register (temp/bound reg both ok) */
-static void duk__ivalue_toplain(duk_compiler_ctx *comp_ctx, duk_ivalue *x) {
+DUK_LOCAL void duk__ivalue_toplain(duk_compiler_ctx *comp_ctx, duk_ivalue *x) {
 	duk__ivalue_toplain_raw(comp_ctx, x, -1 /*forced_reg*/);
 }
 
 /* evaluate to final form (e.g. coerce GETPROP to code), throw away temp */
-static void duk__ivalue_toplain_ignore(duk_compiler_ctx *comp_ctx, duk_ivalue *x) {
+DUK_LOCAL void duk__ivalue_toplain_ignore(duk_compiler_ctx *comp_ctx, duk_ivalue *x) {
 	duk_reg_t temp;
 
 	/* If duk__ivalue_toplain_raw() allocates a temp, forget it and
@@ -44952,10 +61816,11 @@ static void duk__ivalue_toplain_ignore(duk_compiler_ctx *comp_ctx, duk_ivalue *x
  * The duk_ivalue argument ('x') is converted into a regconst as a
  * side effect.
  */
-static duk_regconst_t duk__ivalue_toregconst_raw(duk_compiler_ctx *comp_ctx,
-                                                 duk_ivalue *x,
-                                                 duk_reg_t forced_reg,
-                                                 duk_small_uint_t flags) {
+DUK_LOCAL
+duk_regconst_t duk__ivalue_toregconst_raw(duk_compiler_ctx *comp_ctx,
+                                          duk_ivalue *x,
+                                          duk_reg_t forced_reg,
+                                          duk_small_uint_t flags) {
 	duk_hthread *thr = comp_ctx->thr;
 	duk_context *ctx = (duk_context *) thr;
 	duk_regconst_t reg;
@@ -44987,25 +61852,29 @@ static duk_regconst_t duk__ivalue_toregconst_raw(duk_compiler_ctx *comp_ctx,
 	return reg;
 }
 
-static duk_reg_t duk__ivalue_toreg(duk_compiler_ctx *comp_ctx, duk_ivalue *x) {
+DUK_LOCAL duk_reg_t duk__ivalue_toreg(duk_compiler_ctx *comp_ctx, duk_ivalue *x) {
 	return duk__ivalue_toregconst_raw(comp_ctx, x, -1, 0 /*flags*/);
 }
 
 #if 0  /* unused */
-static duk_reg_t duk__ivalue_totempreg(duk_compiler_ctx *comp_ctx, duk_ivalue *x) {
+DUK_LOCAL duk_reg_t duk__ivalue_totemp(duk_compiler_ctx *comp_ctx, duk_ivalue *x) {
 	return duk__ivalue_toregconst_raw(comp_ctx, x, -1, DUK__IVAL_FLAG_REQUIRE_TEMP /*flags*/);
 }
 #endif
 
-static void duk__ivalue_toforcedreg(duk_compiler_ctx *comp_ctx, duk_ivalue *x, duk_int_t forced_reg) {
+DUK_LOCAL void duk__ivalue_toforcedreg(duk_compiler_ctx *comp_ctx, duk_ivalue *x, duk_int_t forced_reg) {
 	DUK_ASSERT(forced_reg >= 0);
 	(void) duk__ivalue_toregconst_raw(comp_ctx, x, forced_reg, 0 /*flags*/);
 }
 
-static duk_regconst_t duk__ivalue_toregconst(duk_compiler_ctx *comp_ctx, duk_ivalue *x) {
+DUK_LOCAL duk_regconst_t duk__ivalue_toregconst(duk_compiler_ctx *comp_ctx, duk_ivalue *x) {
 	return duk__ivalue_toregconst_raw(comp_ctx, x, -1, DUK__IVAL_FLAG_ALLOW_CONST /*flags*/);
 }
 
+DUK_LOCAL duk_regconst_t duk__ivalue_totempconst(duk_compiler_ctx *comp_ctx, duk_ivalue *x) {
+	return duk__ivalue_toregconst_raw(comp_ctx, x, -1, DUK__IVAL_FLAG_ALLOW_CONST | DUK__IVAL_FLAG_REQUIRE_TEMP /*flags*/);
+}
+
 /* The issues below can be solved with better flags */
 
 /* XXX: many operations actually want toforcedtemp() -- brand new temp? */
@@ -45018,7 +61887,7 @@ static duk_regconst_t duk__ivalue_toregconst(duk_compiler_ctx *comp_ctx, duk_iva
  *  Identifier handling
  */
 
-static duk_reg_t duk__lookup_active_register_binding(duk_compiler_ctx *comp_ctx) {
+DUK_LOCAL duk_reg_t duk__lookup_active_register_binding(duk_compiler_ctx *comp_ctx) {
 	duk_hthread *thr = comp_ctx->thr;
 	duk_context *ctx = (duk_context *) thr;
 	duk_hstring *h_varname;
@@ -45084,7 +61953,7 @@ static duk_reg_t duk__lookup_active_register_binding(duk_compiler_ctx *comp_ctx)
  * return code is 0 or out_reg_varbind is < 0; this is becuase out_rc_varname
  * is unsigned and doesn't have a "unused" / none value.
  */
-static duk_bool_t duk__lookup_lhs(duk_compiler_ctx *comp_ctx, duk_reg_t *out_reg_varbind, duk_regconst_t *out_rc_varname) {
+DUK_LOCAL duk_bool_t duk__lookup_lhs(duk_compiler_ctx *comp_ctx, duk_reg_t *out_reg_varbind, duk_regconst_t *out_rc_varname) {
 	duk_hthread *thr = comp_ctx->thr;
 	duk_context *ctx = (duk_context *) thr;
 	duk_reg_t reg_varbind;
@@ -45116,7 +61985,7 @@ static duk_bool_t duk__lookup_lhs(duk_compiler_ctx *comp_ctx, duk_reg_t *out_reg
  *  labels), all the labels are updated to allow/prohibit break and continue.
  */
 
-static void duk__add_label(duk_compiler_ctx *comp_ctx, duk_hstring *h_label, duk_int_t pc_label, duk_int_t label_id) {
+DUK_LOCAL void duk__add_label(duk_compiler_ctx *comp_ctx, duk_hstring *h_label, duk_int_t pc_label, duk_int_t label_id) {
 	duk_hthread *thr = comp_ctx->thr;
 	duk_context *ctx = (duk_context *) thr;
 	duk_size_t n;
@@ -45133,9 +62002,9 @@ static void duk__add_label(duk_compiler_ctx *comp_ctx, duk_hstring *h_label, duk
 	 * of the E5 specification, see Section 12.12.
 	 */
 
-	p = (duk_uint8_t *) DUK_HBUFFER_DYNAMIC_GET_CURR_DATA_PTR(comp_ctx->curr_func.h_labelinfos);
-	li_start = (duk_labelinfo *) p;
-	li = (duk_labelinfo *) (p + DUK_HBUFFER_GET_SIZE(comp_ctx->curr_func.h_labelinfos));
+	p = (duk_uint8_t *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(thr->heap, comp_ctx->curr_func.h_labelinfos);
+	li_start = (duk_labelinfo *) (void *) p;
+	li = (duk_labelinfo *) (void *) (p + DUK_HBUFFER_GET_SIZE(comp_ctx->curr_func.h_labelinfos));
 	n = (duk_size_t) (li - li_start);
 
 	while (li > li_start) {
@@ -45151,23 +62020,24 @@ static void duk__add_label(duk_compiler_ctx *comp_ctx, duk_hstring *h_label, duk
 	(void) duk_put_prop_index(ctx, comp_ctx->curr_func.labelnames_idx, (duk_uarridx_t) n);
 
 	new_size = (n + 1) * sizeof(duk_labelinfo);
-	duk_hbuffer_resize(thr, comp_ctx->curr_func.h_labelinfos, new_size, new_size);
+	duk_hbuffer_resize(thr, comp_ctx->curr_func.h_labelinfos, new_size);
 	/* XXX: spare handling, slow now */
 
 	/* relookup after possible realloc */
-	p = (duk_uint8_t *) DUK_HBUFFER_DYNAMIC_GET_CURR_DATA_PTR(comp_ctx->curr_func.h_labelinfos);
-	li_start = (duk_labelinfo *) p;
+	p = (duk_uint8_t *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(thr->heap, comp_ctx->curr_func.h_labelinfos);
+	li_start = (duk_labelinfo *) (void *) p;
 	DUK_UNREF(li_start);  /* silence scan-build warning */
-	li = (duk_labelinfo *) (p + DUK_HBUFFER_GET_SIZE(comp_ctx->curr_func.h_labelinfos));
+	li = (duk_labelinfo *) (void *) (p + DUK_HBUFFER_GET_SIZE(comp_ctx->curr_func.h_labelinfos));
 	li--;
 
-	/* Labels need to be recorded as pending before we know whether they will be
-	 * actually be used as part of an iteration statement or a switch statement.
-	 * The flags to allow break/continue are updated when we figure out the
+	/* Labels can be used for iteration statements but also for other statements,
+	 * in particular a label can be used for a block statement.  All cases of a
+	 * named label accept a 'break' so that flag is set here.  Iteration statements
+	 * also allow 'continue', so that flag is updated when we figure out the
 	 * statement type.
 	 */
 
-	li->flags = 0;
+	li->flags = DUK_LABEL_FLAG_ALLOW_BREAK;
 	li->label_id = label_id;
 	li->h_label = h_label;
 	li->catch_depth = comp_ctx->curr_func.catch_depth;   /* catch depth from current func */
@@ -45179,13 +62049,13 @@ static void duk__add_label(duk_compiler_ctx *comp_ctx, duk_hstring *h_label, duk
 }
 
 /* Update all labels with matching label_id. */
-static void duk__update_label_flags(duk_compiler_ctx *comp_ctx, duk_int_t label_id, duk_small_uint_t flags) {
+DUK_LOCAL void duk__update_label_flags(duk_compiler_ctx *comp_ctx, duk_int_t label_id, duk_small_uint_t flags) {
 	duk_uint8_t *p;
 	duk_labelinfo *li_start, *li;
 
-	p = (duk_uint8_t *) DUK_HBUFFER_DYNAMIC_GET_CURR_DATA_PTR(comp_ctx->curr_func.h_labelinfos);
-	li_start = (duk_labelinfo *) p;
-	li = (duk_labelinfo *) (p + DUK_HBUFFER_GET_SIZE(comp_ctx->curr_func.h_labelinfos));
+	p = (duk_uint8_t *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(comp_ctx->thr->heap, comp_ctx->curr_func.h_labelinfos);
+	li_start = (duk_labelinfo *) (void *) p;
+	li = (duk_labelinfo *) (void *) (p + DUK_HBUFFER_GET_SIZE(comp_ctx->curr_func.h_labelinfos));
 
 	/* Match labels starting from latest; once label_id no longer matches, we can
 	 * safely exit without checking the rest of the labels (only the topmost labels
@@ -45220,7 +62090,7 @@ static void duk__update_label_flags(duk_compiler_ctx *comp_ctx, duk_int_t label_
  */
 
 /* XXX: awkward, especially the bunch of separate output values -> output struct? */
-static void duk__lookup_active_label(duk_compiler_ctx *comp_ctx, duk_hstring *h_label, duk_bool_t is_break, duk_int_t *out_label_id, duk_int_t *out_label_catch_depth, duk_int_t *out_label_pc, duk_bool_t *out_is_closest) {
+DUK_LOCAL void duk__lookup_active_label(duk_compiler_ctx *comp_ctx, duk_hstring *h_label, duk_bool_t is_break, duk_int_t *out_label_id, duk_int_t *out_label_catch_depth, duk_int_t *out_label_pc, duk_bool_t *out_is_closest) {
 	duk_hthread *thr = comp_ctx->thr;
 	duk_context *ctx = (duk_context *) thr;
 	duk_uint8_t *p;
@@ -45232,9 +62102,9 @@ static void duk__lookup_active_label(duk_compiler_ctx *comp_ctx, duk_hstring *h_
 
 	DUK_UNREF(ctx);
 
-	p = (duk_uint8_t *) DUK_HBUFFER_DYNAMIC_GET_CURR_DATA_PTR(comp_ctx->curr_func.h_labelinfos);
-	li_start = (duk_labelinfo *) p;
-	li_end = (duk_labelinfo *) (p + DUK_HBUFFER_GET_SIZE(comp_ctx->curr_func.h_labelinfos));
+	p = (duk_uint8_t *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(thr->heap, comp_ctx->curr_func.h_labelinfos);
+	li_start = (duk_labelinfo *) (void *) p;
+	li_end = (duk_labelinfo *) (void *) (p + DUK_HBUFFER_GET_SIZE(comp_ctx->curr_func.h_labelinfos));
 	li = li_end;
 
 	/* Match labels starting from latest label because there can be duplicate empty
@@ -45293,7 +62163,7 @@ static void duk__lookup_active_label(duk_compiler_ctx *comp_ctx, duk_hstring *h_
 	*out_is_closest = (li == li_end - 1);
 }
 
-static void duk__reset_labels_to_length(duk_compiler_ctx *comp_ctx, duk_int_t len) {
+DUK_LOCAL void duk__reset_labels_to_length(duk_compiler_ctx *comp_ctx, duk_int_t len) {
 	duk_hthread *thr = comp_ctx->thr;
 	duk_context *ctx = (duk_context *) thr;
 	duk_size_t new_size;
@@ -45302,7 +62172,7 @@ static void duk__reset_labels_to_length(duk_compiler_ctx *comp_ctx, duk_int_t le
 	new_size = sizeof(duk_labelinfo) * (duk_size_t) len;
 	duk_push_int(ctx, len);
 	duk_put_prop_stridx(ctx, comp_ctx->curr_func.labelnames_idx, DUK_STRIDX_LENGTH);
-	duk_hbuffer_resize(thr, comp_ctx->curr_func.h_labelinfos, new_size, new_size);  /* XXX: spare handling */
+	duk_hbuffer_resize(thr, comp_ctx->curr_func.h_labelinfos, new_size);
 }
 
 /*
@@ -45318,7 +62188,7 @@ static void duk__reset_labels_to_length(duk_compiler_ctx *comp_ctx, duk_int_t le
 #define DUK__OBJ_LIT_KEY_GET    (1 << 1)  /* key encountered as a getter */
 #define DUK__OBJ_LIT_KEY_SET    (1 << 2)  /* key encountered as a setter */
 
-static void duk__nud_array_literal(duk_compiler_ctx *comp_ctx, duk_ivalue *res) {
+DUK_LOCAL void duk__nud_array_literal(duk_compiler_ctx *comp_ctx, duk_ivalue *res) {
 	duk_hthread *thr = comp_ctx->thr;
 	duk_reg_t reg_obj;                 /* result reg */
 	duk_reg_t reg_temp;                /* temp reg */
@@ -45337,10 +62207,10 @@ static void duk__nud_array_literal(duk_compiler_ctx *comp_ctx, duk_ivalue *res)
 
 	reg_obj = DUK__ALLOCTEMP(comp_ctx);
 	duk__emit_extraop_b_c(comp_ctx,
-	                      DUK_EXTRAOP_NEWARR | DUK__EMIT_FLAG_B_IS_TARGET, 
+	                      DUK_EXTRAOP_NEWARR | DUK__EMIT_FLAG_B_IS_TARGET,
 	                      reg_obj,
 	                      0);  /* XXX: patch initial size afterwards? */
- 	temp_start = DUK__GETTEMP(comp_ctx);
+	temp_start = DUK__GETTEMP(comp_ctx);
 
 	/*
 	 *  Emit initializers in sets of maximum max_init_values.
@@ -45435,7 +62305,7 @@ static void duk__nud_array_literal(duk_compiler_ctx *comp_ctx, duk_ivalue *res)
 			init_idx = start_idx + num_values;
 
 			/* num_values and temp_start reset at top of outer loop */
-		}	
+		}
 	}
 
 	DUK_ASSERT(comp_ctx->curr_token.t == DUK_TOK_RBRACKET);
@@ -45468,7 +62338,7 @@ static void duk__nud_array_literal(duk_compiler_ctx *comp_ctx, duk_ivalue *res)
 }
 
 /* duplicate/invalid key checks; returns 1 if syntax error */
-static duk_bool_t duk__nud_object_literal_key_check(duk_compiler_ctx *comp_ctx, duk_small_uint_t new_key_flags) {
+DUK_LOCAL duk_bool_t duk__nud_object_literal_key_check(duk_compiler_ctx *comp_ctx, duk_small_uint_t new_key_flags) {
 	duk_hthread *thr = comp_ctx->thr;
 	duk_context *ctx = (duk_context *) thr;
 	duk_small_uint_t key_flags;
@@ -45526,7 +62396,7 @@ static duk_bool_t duk__nud_object_literal_key_check(duk_compiler_ctx *comp_ctx,
 	return 0;
 }
 
-static void duk__nud_object_literal(duk_compiler_ctx *comp_ctx, duk_ivalue *res) {
+DUK_LOCAL void duk__nud_object_literal(duk_compiler_ctx *comp_ctx, duk_ivalue *res) {
 	duk_hthread *thr = comp_ctx->thr;
 	duk_context *ctx = (duk_context *) thr;
 	duk_reg_t reg_obj;                /* result reg */
@@ -45592,7 +62462,7 @@ static void duk__nud_object_literal(duk_compiler_ctx *comp_ctx, duk_ivalue *res)
 			 *  a string constant) even for numeric keys (e.g. "{1:'foo'}").
 			 *  These could be emitted using e.g. LDINT, but that seems hardly
 			 *  worth the effort and would increase code size.
-			 */ 
+			 */
 
 			DUK_DDD(DUK_DDDPRINT("object literal inner loop, curr_token->t = %ld",
 			                     (long) comp_ctx->curr_token.t));
@@ -45619,7 +62489,7 @@ static void duk__nud_object_literal(duk_compiler_ctx *comp_ctx, duk_ivalue *res)
 				}
 			}
 
-			/* advance to get one step of lookup */		
+			/* advance to get one step of lookup */
 			duk__advance(comp_ctx);
 
 			/* NOTE: "get" and "set" are not officially ReservedWords and the lexer
@@ -45772,7 +62642,7 @@ static void duk__nud_object_literal(duk_compiler_ctx *comp_ctx, duk_ivalue *res)
  * "next temp".  Returns number of arguments parsed.  Expects left paren
  * to be already eaten, and eats the right paren before returning.
  */
-static duk_int_t duk__parse_arguments(duk_compiler_ctx *comp_ctx, duk_ivalue *res) {
+DUK_LOCAL duk_int_t duk__parse_arguments(duk_compiler_ctx *comp_ctx, duk_ivalue *res) {
 	duk_int_t nargs = 0;
 	duk_reg_t reg_temp;
 
@@ -45816,23 +62686,23 @@ static duk_int_t duk__parse_arguments(duk_compiler_ctx *comp_ctx, duk_ivalue *re
 	return nargs;
 }
 
-static duk_bool_t duk__expr_is_empty(duk_compiler_ctx *comp_ctx) {
+DUK_LOCAL duk_bool_t duk__expr_is_empty(duk_compiler_ctx *comp_ctx) {
 	/* empty expressions can be detected conveniently with nud/led counts */
 	return (comp_ctx->curr_func.nud_count == 0) &&
 	       (comp_ctx->curr_func.led_count == 0);
 }
 
-static void duk__expr_nud(duk_compiler_ctx *comp_ctx, duk_ivalue *res) {
+DUK_LOCAL void duk__expr_nud(duk_compiler_ctx *comp_ctx, duk_ivalue *res) {
 	duk_hthread *thr = comp_ctx->thr;
 	duk_context *ctx = (duk_context *) thr;
 	duk_token *tk;
 	duk_reg_t temp_at_entry;
 	duk_small_int_t tok;
-	duk_uint32_t args;	/* temp variable to pass constants and flags to shared code */
+	duk_uint32_t args;  /* temp variable to pass constants and flags to shared code */
 
 	/*
-	 *  ctx->prev_token	token to process with duk__expr_nud()
-	 *  ctx->curr_token	updated by caller
+	 *  ctx->prev_token     token to process with duk__expr_nud()
+	 *  ctx->curr_token     updated by caller
 	 *
 	 *  Note: the token in the switch below has already been eaten.
 	 */
@@ -45855,9 +62725,9 @@ static void duk__expr_nud(duk_compiler_ctx *comp_ctx, duk_ivalue *res) {
 	case DUK_TOK_THIS: {
 		duk_reg_t reg_temp;
 		reg_temp = DUK__ALLOCTEMP(comp_ctx);
-		duk__emit_extraop_b(comp_ctx,
-		                    DUK_EXTRAOP_LDTHIS | DUK__EMIT_FLAG_B_IS_TARGET,
-		                    (duk_regconst_t) reg_temp);
+		duk__emit_extraop_bc(comp_ctx,
+		                     DUK_EXTRAOP_LDTHIS,
+		                     (duk_regconst_t) reg_temp);
 		res->t = DUK_IVAL_PLAIN;
 		res->x1.t = DUK_ISPEC_REGCONST;
 		res->x1.regconst = (duk_regconst_t) reg_temp;
@@ -45969,7 +62839,7 @@ static void duk__expr_nud(duk_compiler_ctx *comp_ctx, duk_ivalue *res) {
 		 *  such that parsing ends at an LPAREN (CallExpression) but not at
 		 *  a PERIOD or LBRACKET (MemberExpression).
 		 *
-		 *  See doc/compiler.txt for discussion on the parsing approach,
+		 *  See doc/compiler.rst for discussion on the parsing approach,
 		 *  and testcases/test-dev-new.js for a bunch of documented tests.
 		 */
 
@@ -46151,12 +63021,12 @@ static void duk__expr_nud(duk_compiler_ctx *comp_ctx, duk_ivalue *res) {
 		goto unary_extraop;
 	}
 	case DUK_TOK_INCREMENT: {
-		args = (DUK_EXTRAOP_INC << 8) + 0;
-		goto preincdec_extraop;
+		args = (DUK_OP_PREINCR << 8) + 0;
+		goto preincdec;
 	}
 	case DUK_TOK_DECREMENT: {
-		args = (DUK_EXTRAOP_DEC << 8) + 0;
-		goto preincdec_extraop;
+		args = (DUK_OP_PREDECR << 8) + 0;
+		goto preincdec;
 	}
 	case DUK_TOK_ADD: {
 		/* unary plus */
@@ -46194,8 +63064,8 @@ static void duk__expr_nud(duk_compiler_ctx *comp_ctx, duk_ivalue *res) {
 	}
 	case DUK_TOK_BNOT: {
 		duk__expr(comp_ctx, res, DUK__BP_MULTIPLICATIVE /*rbp_flags*/);  /* UnaryExpression */
-		args = (DUK_OP_BNOT << 8) + 0;
-		goto unary;
+		args = (DUK_EXTRAOP_BNOT << 8) + 0;
+		goto unary_extraop;
 	}
 	case DUK_TOK_LNOT: {
 		duk__expr(comp_ctx, res, DUK__BP_MULTIPLICATIVE /*rbp_flags*/);  /* UnaryExpression */
@@ -46228,8 +63098,8 @@ static void duk__expr_nud(duk_compiler_ctx *comp_ctx, duk_ivalue *res) {
 				return;
 			}
 		}
-		args = (DUK_OP_LNOT << 8) + 0;
-		goto unary;
+		args = (DUK_EXTRAOP_LNOT << 8) + 0;
+		goto unary_extraop;
 	}
 
 	}  /* end switch */
@@ -46237,45 +63107,35 @@ static void duk__expr_nud(duk_compiler_ctx *comp_ctx, duk_ivalue *res) {
 	DUK_ERROR(thr, DUK_ERR_SYNTAX_ERROR, DUK_STR_PARSE_ERROR);
 	return;
 
- unary:
+ unary_extraop:
 	{
 		/* Note: must coerce to a (writable) temp register, so that e.g. "!x" where x
 		 * is a reg-mapped variable works correctly (does not mutate the variable register).
 		 */
 
-		duk_regconst_t rc_temp;
-		rc_temp = duk__ivalue_toregconst_raw(comp_ctx, res, -1 /*forced_reg*/, DUK__IVAL_FLAG_REQUIRE_TEMP /*flags*/);
-		duk__emit_a_b(comp_ctx,
-		              args >> 8,
-		              rc_temp,
-		              rc_temp);
-		res->t = DUK_IVAL_PLAIN;
-		res->x1.t = DUK_ISPEC_REGCONST;
-		res->x1.regconst = rc_temp;
-		return;
-	}
-
- unary_extraop:
-	{
-		/* XXX: refactor into unary2: above? */
 		duk_reg_t reg_temp;
 		reg_temp = duk__ivalue_toregconst_raw(comp_ctx, res, -1 /*forced_reg*/, DUK__IVAL_FLAG_REQUIRE_TEMP /*flags*/);
-		duk__emit_extraop_b_c(comp_ctx,
-		                      (args >> 8) | DUK__EMIT_FLAG_B_IS_TARGET,
-		                      (duk_regconst_t) reg_temp,
-		                      (duk_regconst_t) reg_temp);
+		duk__emit_extraop_bc(comp_ctx,
+		                     (args >> 8),
+		                     (duk_regconst_t) reg_temp);
 		res->t = DUK_IVAL_PLAIN;
 		res->x1.t = DUK_ISPEC_REGCONST;
 		res->x1.regconst = (duk_regconst_t) reg_temp;
 		return;
 	}
 
- preincdec_extraop:
+ preincdec:
 	{
 		/* preincrement and predecrement */
 		duk_reg_t reg_res;
 		duk_small_uint_t args_op = args >> 8;
 
+		/* Specific assumptions for opcode numbering. */
+		DUK_ASSERT(DUK_OP_PREINCR + 4 == DUK_OP_PREINCV);
+		DUK_ASSERT(DUK_OP_PREDECR + 4 == DUK_OP_PREDECV);
+		DUK_ASSERT(DUK_OP_PREINCR + 8 == DUK_OP_PREINCP);
+		DUK_ASSERT(DUK_OP_PREDECR + 8 == DUK_OP_PREDECP);
+
 		reg_res = DUK__ALLOCTEMP(comp_ctx);
 
 		duk__expr(comp_ctx, res, DUK__BP_MULTIPLICATIVE /*rbp_flags*/);  /* UnaryExpression */
@@ -46293,30 +63153,18 @@ static void duk__expr_nud(duk_compiler_ctx *comp_ctx, duk_ivalue *res) {
 
 			duk_dup(ctx, res->x1.valstack_idx);
 			if (duk__lookup_lhs(comp_ctx, &reg_varbind, &rc_varname)) {
-				duk__emit_extraop_b_c(comp_ctx,
-				                      args_op | DUK__EMIT_FLAG_B_IS_TARGET,
-				                      reg_varbind,
-				                      reg_varbind);
 				duk__emit_a_bc(comp_ctx,
-				               DUK_OP_LDREG,
+				               args_op,  /* e.g. DUK_OP_PREINCR */
 				               (duk_regconst_t) reg_res,
 				               (duk_regconst_t) reg_varbind);
 			} else {
 				duk__emit_a_bc(comp_ctx,
-				               DUK_OP_GETVAR,
-				               (duk_regconst_t) reg_res,
-				               rc_varname);
-				duk__emit_extraop_b_c(comp_ctx,
-				                      args_op | DUK__EMIT_FLAG_B_IS_TARGET,
-				                      (duk_regconst_t) reg_res,
-				                      (duk_regconst_t) reg_res);
-				duk__emit_a_bc(comp_ctx,
-				               DUK_OP_PUTVAR | DUK__EMIT_FLAG_A_IS_SOURCE,
-				               (duk_regconst_t) reg_res,
-				               rc_varname);
+				                args_op + 4,  /* e.g. DUK_OP_PREINCV */
+				                (duk_regconst_t) reg_res,
+				                rc_varname);
 			}
 
-			DUK_DDD(DUK_DDDPRINT("postincdec to '%!O' -> reg_varbind=%ld, rc_varname=%ld",
+			DUK_DDD(DUK_DDDPRINT("preincdec to '%!O' -> reg_varbind=%ld, rc_varname=%ld",
 			                     (duk_heaphdr *) h_varname, (long) reg_varbind, (long) rc_varname));
 		} else if (res->t == DUK_IVAL_PROP) {
 			duk_reg_t reg_obj;  /* allocate to reg only (not const) */
@@ -46324,29 +63172,21 @@ static void duk__expr_nud(duk_compiler_ctx *comp_ctx, duk_ivalue *res) {
 			reg_obj = duk__ispec_toregconst_raw(comp_ctx, &res->x1, -1 /*forced_reg*/, 0 /*flags*/);  /* don't allow const */
 			rc_key = duk__ispec_toregconst_raw(comp_ctx, &res->x2, -1 /*forced_reg*/, DUK__IVAL_FLAG_ALLOW_CONST /*flags*/);
 			duk__emit_a_b_c(comp_ctx,
-			                DUK_OP_GETPROP,
+			                args_op + 8,  /* e.g. DUK_OP_PREINCP */
 			                (duk_regconst_t) reg_res,
 			                (duk_regconst_t) reg_obj,
 			                rc_key);
-			duk__emit_extraop_b_c(comp_ctx,
-			                      args_op | DUK__EMIT_FLAG_B_IS_TARGET,
-			                      (duk_regconst_t) reg_res,
-			                      (duk_regconst_t) reg_res);
-			duk__emit_a_b_c(comp_ctx,
-			                DUK_OP_PUTPROP,
-			                (duk_regconst_t) reg_obj,
-			                rc_key,
-			                (duk_regconst_t) reg_res);
 		} else {
 			/* Technically return value is not needed because INVLHS will
 			 * unconditially throw a ReferenceError.  Coercion is necessary
 			 * for proper semantics (consider ToNumber() called for an object).
+			 * Use DUK_EXTRAOP_UNP with a dummy register to get ToNumber().
 			 */
+
 			duk__ivalue_toforcedreg(comp_ctx, res, reg_res);
-			duk__emit_extraop_b_c(comp_ctx,
-			                      DUK_EXTRAOP_TONUM | DUK__EMIT_FLAG_B_IS_TARGET,
-			                      (duk_regconst_t) reg_res,
-			                      (duk_regconst_t) reg_res);  /* for side effects */
+			duk__emit_extraop_bc(comp_ctx,
+			                     DUK_EXTRAOP_UNP,
+			                     reg_res);  /* for side effects, result ignored */
 			duk__emit_extraop_only(comp_ctx,
 			                       DUK_EXTRAOP_INVLHS);
 		}
@@ -46374,16 +63214,16 @@ static void duk__expr_nud(duk_compiler_ctx *comp_ctx, duk_ivalue *res) {
  * affects e.g. handling of assignment expressions.  This change needs API
  * changes elsewhere too.
  */
-static void duk__expr_led(duk_compiler_ctx *comp_ctx, duk_ivalue *left, duk_ivalue *res) {
+DUK_LOCAL void duk__expr_led(duk_compiler_ctx *comp_ctx, duk_ivalue *left, duk_ivalue *res) {
 	duk_hthread *thr = comp_ctx->thr;
 	duk_context *ctx = (duk_context *) thr;
 	duk_token *tk;
 	duk_small_int_t tok;
-	duk_uint32_t args;	/* temp variable to pass constants and flags to shared code */
+	duk_uint32_t args;  /* temp variable to pass constants and flags to shared code */
 
 	/*
-	 *  ctx->prev_token	token to process with duk__expr_led()
-	 *  ctx->curr_token	updated by caller
+	 *  ctx->prev_token     token to process with duk__expr_led()
+	 *  ctx->curr_token     updated by caller
 	 */
 
 	comp_ctx->curr_func.led_count++;
@@ -46402,7 +63242,19 @@ static void duk__expr_led(duk_compiler_ctx *comp_ctx, duk_ivalue *left, duk_ival
 	/* PRIMARY EXPRESSIONS */
 
 	case DUK_TOK_PERIOD: {
-		/* XXX: this now coerces an identifier into a GETVAR to a temp, which
+		/* Property access expressions are critical for correct LHS ordering,
+		 * see comments in duk__expr()!
+		 *
+		 * A conservative approach would be to use duk__ivalue_totempconst()
+		 * for 'left'.  However, allowing a reg-bound variable seems safe here
+		 * and is nice because "foo.bar" is a common expression.  If the ivalue
+		 * is used in an expression a GETPROP will occur before any changes to
+		 * the base value can occur.  If the ivalue is used as an assignment
+		 * LHS, the assignment code will ensure the base value is safe from
+		 * RHS mutation.
+		 */
+
+		/* XXX: This now coerces an identifier into a GETVAR to a temp, which
 		 * causes an extra LDREG in call setup.  It's sufficient to coerce to a
 		 * unary ivalue?
 		 */
@@ -46427,19 +63279,30 @@ static void duk__expr_led(duk_compiler_ctx *comp_ctx, duk_ivalue *left, duk_ival
 		return;
 	}
 	case DUK_TOK_LBRACKET: {
+		/* Property access expressions are critical for correct LHS ordering,
+		 * see comments in duk__expr()!
+		 */
+
 		/* XXX: optimize temp reg use */
 		/* XXX: similar coercion issue as in DUK_TOK_PERIOD */
-
-		duk__ivalue_toplain(comp_ctx, left);
-
-		duk__expr_toplain(comp_ctx, res, DUK__BP_FOR_EXPR /*rbp_flags*/);  /* Expression, ']' terminates */
-
-		duk__advance_expect(comp_ctx, DUK_TOK_RBRACKET);
-
 		/* XXX: coerce to regs? it might be better for enumeration use, where the
 		 * same PROP ivalue is used multiple times.  Or perhaps coerce PROP further
 		 * there?
 		 */
+		/* XXX: for simple cases like x['y'] an unnecessary LDREG is
+		 * emitted for the base value; could avoid it if we knew that
+		 * the key expression is safe (e.g. just a single literal).
+		 */
+
+		/* The 'left' value must not be a register bound variable
+		 * because it may be mutated during the rest of the expression
+		 * and E5.1 Section 11.2.1 specifies the order of evaluation
+		 * so that the base value is evaluated first.
+		 * See: test-bug-nested-prop-mutate.js.
+		 */
+		duk__ivalue_totempconst(comp_ctx, left);
+		duk__expr_toplain(comp_ctx, res, DUK__BP_FOR_EXPR /*rbp_flags*/);  /* Expression, ']' terminates */
+		duk__advance_expect(comp_ctx, DUK_TOK_RBRACKET);
 
 		res->t = DUK_IVAL_PROP;
 		duk__copy_ispec(comp_ctx, &res->x1, &res->x2);   /* res.x1 -> res.x2 */
@@ -46505,7 +63368,7 @@ static void duk__expr_led(duk_compiler_ctx *comp_ctx, duk_ivalue *left, duk_ival
 			}
 		} else if (left->t == DUK_IVAL_PROP) {
 			DUK_DDD(DUK_DDDPRINT("function call with property base"));
-			
+
 			duk__ispec_toforcedreg(comp_ctx, &left->x1, reg_cs + 0);  /* base */
 			duk__ispec_toforcedreg(comp_ctx, &left->x2, reg_cs + 1);  /* key */
 			duk__emit_a_b_c(comp_ctx,
@@ -46547,12 +63410,12 @@ static void duk__expr_led(duk_compiler_ctx *comp_ctx, duk_ivalue *left, duk_ival
 	/* POSTFIX EXPRESSION */
 
 	case DUK_TOK_INCREMENT: {
-		args = (DUK_EXTRAOP_INC << 8) + 0;
-		goto postincdec_extraop;
+		args = (DUK_OP_POSTINCR << 8) + 0;
+		goto postincdec;
 	}
 	case DUK_TOK_DECREMENT: {
-		args = (DUK_EXTRAOP_DEC << 8) + 0;
-		goto postincdec_extraop;
+		args = (DUK_OP_POSTDECR << 8) + 0;
+		goto postincdec;
 	}
 
 	/* MULTIPLICATIVE EXPRESSION */
@@ -46619,11 +63482,11 @@ static void duk__expr_led(duk_compiler_ctx *comp_ctx, duk_ivalue *left, duk_ival
 		goto binary;
 	}
 	case DUK_TOK_INSTANCEOF: {
-		args = (DUK_OP_INSTOF << 8) + DUK__BP_RELATIONAL;
+		args = (1 << 16 /*is_extra*/) + (DUK_EXTRAOP_INSTOF << 8) + DUK__BP_RELATIONAL;
 		goto binary;
 	}
 	case DUK_TOK_IN: {
-		args = (DUK_OP_IN << 8) + DUK__BP_RELATIONAL;
+		args = (1 << 16 /*is_extra*/) + (DUK_EXTRAOP_IN << 8) + DUK__BP_RELATIONAL;
 		goto binary;
 	}
 
@@ -46716,7 +63579,7 @@ static void duk__expr_led(duk_compiler_ctx *comp_ctx, duk_ivalue *left, duk_ival
 		 *
 		 *  XXX: just use DUK__BP_COMMA (i.e. no need for 2-step bp levels)?
 		 */
-		args = (DUK_OP_INVALID << 8) + DUK__BP_ASSIGNMENT - 1;   /* DUK_OP_INVALID marks a 'plain' assignment */
+		args = (DUK_OP_NONE << 8) + DUK__BP_ASSIGNMENT - 1;   /* DUK_OP_NONE marks a 'plain' assignment */
 		goto assign;
 	}
 	case DUK_TOK_ADD_EQ: {
@@ -46807,7 +63670,7 @@ static void duk__expr_led(duk_compiler_ctx *comp_ctx, duk_ivalue *left, duk_ival
 	/*
 	 *  Shared handling of binary operations
 	 *
-	 *  args = (opcode << 8) + rbp
+	 *  args = (is_extraop << 16) + (opcode << 8) + rbp
 	 */
 	{
 		duk__ivalue_toplain(comp_ctx, left);
@@ -46817,8 +63680,8 @@ static void duk__expr_led(duk_compiler_ctx *comp_ctx, duk_ivalue *left, duk_ival
 		DUK_ASSERT(left->t == DUK_IVAL_PLAIN);
 		DUK_ASSERT(res->t == DUK_IVAL_PLAIN);
 
-		res->t = DUK_IVAL_ARITH;
-		res->op = args >> 8;
+		res->t = (args >> 16) ? DUK_IVAL_ARITH_EXTRAOP : DUK_IVAL_ARITH;
+		res->op = (args >> 8) & 0xff;
 
 		res->x2.t = res->x1.t;
 		res->x2.regconst = res->x1.regconst;
@@ -46828,8 +63691,8 @@ static void duk__expr_led(duk_compiler_ctx *comp_ctx, duk_ivalue *left, duk_ival
 		res->x1.regconst = left->x1.regconst;
 		duk_copy(ctx, left->x1.valstack_idx, res->x1.valstack_idx);
 
-		DUK_DDD(DUK_DDDPRINT("binary op, res: t=%ld, x1.t=%ld, x2.t=%ld",
-		                     (long) res->t, (long) res->x1.t, (long) res->x2.t));
+		DUK_DDD(DUK_DDDPRINT("binary op, res: t=%ld, x1.t=%ld, x1.regconst=0x%08lx, x2.t=%ld, x2.regconst=0x%08lx",
+		                     (long) res->t, (long) res->x1.t, (unsigned long) res->x1.regconst, (long) res->x2.t, (unsigned long) res->x2.regconst));
 		return;
 	}
 
@@ -46842,7 +63705,7 @@ static void duk__expr_led(duk_compiler_ctx *comp_ctx, duk_ivalue *left, duk_ival
 	 *  Truthval determines when to skip right-hand-side.
 	 *  For logical AND truthval=1, for logical OR truthval=0.
 	 *
-	 *  See doc/compiler.txt for discussion on compiling logical
+	 *  See doc/compiler.rst for discussion on compiling logical
 	 *  AND and OR expressions.  The approach here is very simplistic,
 	 *  generating extra jumps and multiple evaluations of truth values,
 	 *  but generates code on-the-fly with only local back-patching.
@@ -46865,7 +63728,7 @@ static void duk__expr_led(duk_compiler_ctx *comp_ctx, duk_ivalue *left, duk_ival
 
 		duk__ivalue_toforcedreg(comp_ctx, left, reg_temp);
 		duk__emit_a_b(comp_ctx,
-		              DUK_OP_IF,
+		              DUK_OP_IF | DUK__EMIT_FLAG_NO_SHUFFLE_A,
 		              (duk_regconst_t) args_truthval,
 		              (duk_regconst_t) reg_temp);  /* skip jump conditionally */
 		pc_jump = duk__emit_jump_empty(comp_ctx);
@@ -46884,15 +63747,25 @@ static void duk__expr_led(duk_compiler_ctx *comp_ctx, duk_ivalue *left, duk_ival
 	 *
 	 *  args = (opcode << 8) + rbp
 	 *
-	 *  If 'opcode' is DUK_OP_INVALID, plain assignment without arithmetic.
+	 *  If 'opcode' is DUK_OP_NONE, plain assignment without arithmetic.
 	 *  Syntactically valid left-hand-side forms which are not accepted as
 	 *  left-hand-side values (e.g. as in "f() = 1") must NOT cause a
 	 *  SyntaxError, but rather a run-time ReferenceError.
+	 *
+	 *  Assignment expression value is conceptually the LHS/RHS value
+	 *  copied into a fresh temporary so that it won't change even if
+	 *  LHS/RHS values change (e.g. when they're identifiers).  Doing this
+	 *  concretely produces inefficient bytecode, so we try to avoid the
+	 *  extra temporary for some known-to-be-safe cases.  Currently the
+	 *  only safe case we detect is a "top level assignment", for example
+	 *  "x = y + z;", where the assignment expression value is ignored.
+	 *  See: test-dev-assign-expr.js and test-bug-assign-mutate-gh381.js.
 	 */
 
 	{
 		duk_small_uint_t args_op = args >> 8;
 		duk_small_uint_t args_rbp = args & 0xff;
+		duk_bool_t toplevel_assign;
 
 		/* XXX: here we need to know if 'left' is left-hand-side compatible.
 		 * That information is no longer available from current expr parsing
@@ -46900,44 +63773,89 @@ static void duk__expr_led(duk_compiler_ctx *comp_ctx, duk_ivalue *left, duk_ival
 		 * some other means.
 		 */
 
+		/* A top-level assignment is e.g. "x = y;".  For these it's safe
+		 * to use the RHS as-is as the expression value, even if the RHS
+		 * is a reg-bound identifier.  The RHS ('res') is right associative
+		 * so it has consumed all other assignment level operations; the
+		 * only relevant lower binding power construct is comma operator
+		 * which will ignore the expression value provided here.
+		 */
+		toplevel_assign = (comp_ctx->curr_func.nud_count == 1 && /* one token before */
+		                   comp_ctx->curr_func.led_count == 1);  /* one operator (= assign) */
+		DUK_DDD(DUK_DDDPRINT("assignment: nud_count=%ld, led_count=%ld, toplevel_assign=%ld",
+		                     (long) comp_ctx->curr_func.nud_count,
+		                     (long) comp_ctx->curr_func.led_count,
+		                     (long) toplevel_assign));
+
 		if (left->t == DUK_IVAL_VAR) {
 			duk_hstring *h_varname;
 			duk_reg_t reg_varbind;
 			duk_regconst_t rc_varname;
-			duk_regconst_t rc_res;
-			duk_reg_t reg_temp;
 
-			/* already in fluly evaluated form */
-			DUK_ASSERT(left->x1.t == DUK_ISPEC_VALUE);
+			DUK_ASSERT(left->x1.t == DUK_ISPEC_VALUE);  /* LHS is already side effect free */
 
-			duk__expr_toreg(comp_ctx, res, args_rbp /*rbp_flags*/);
-			DUK_ASSERT(res->t == DUK_IVAL_PLAIN && res->x1.t == DUK_ISPEC_REGCONST);
+			/* Keep the RHS as an unresolved ivalue for now, so it
+			 * can be a plain value or a unary/binary operation here.
+			 * We resolve it before finishing but doing it later allows
+			 * better bytecode in some cases.
+			 */
+			duk__expr(comp_ctx, res, args_rbp /*rbp_flags*/);
 
 			h_varname = duk_get_hstring(ctx, left->x1.valstack_idx);
 			DUK_ASSERT(h_varname != NULL);
-
-			/* E5 Section 11.13.1 (and others for other assignments), step 4 */
 			if (duk__hstring_is_eval_or_arguments_in_strict_mode(comp_ctx, h_varname)) {
+				/* E5 Section 11.13.1 (and others for other assignments), step 4 */
 				goto syntax_error_lvalue;
 			}
-
 			duk_dup(ctx, left->x1.valstack_idx);
 			(void) duk__lookup_lhs(comp_ctx, &reg_varbind, &rc_varname);
 
-			DUK_DDD(DUK_DDDPRINT("assign to '%!O' -> reg_varbind=%ld, rc_varname=%ld",
-			                     (duk_heaphdr *) h_varname, (long) reg_varbind, (long) rc_varname));
-
-			if (args_op == DUK_OP_INVALID) {
-				rc_res = res->x1.regconst;
+			if (args_op == DUK_OP_NONE) {
+				if (toplevel_assign) {
+					/* Any 'res' will do. */
+					DUK_DDD(DUK_DDDPRINT("plain assignment, toplevel assign, use as is"));
+				} else {
+					/* 'res' must be a plain ivalue, and not register-bound variable. */
+					DUK_DDD(DUK_DDDPRINT("plain assignment, not toplevel assign, ensure not a reg-bound identifier"));
+					if (res->t != DUK_IVAL_PLAIN || (res->x1.t == DUK_ISPEC_REGCONST &&
+					                                 (res->x1.regconst & DUK__CONST_MARKER) == 0 &&
+					                                 !DUK__ISTEMP(comp_ctx, res->x1.regconst))) {
+						duk__ivalue_totempconst(comp_ctx, res);
+					}
+				}
 			} else {
-				reg_temp = DUK__ALLOCTEMP(comp_ctx);
+				duk__ivalue_toregconst(comp_ctx, res);
+				DUK_ASSERT(res->t == DUK_IVAL_PLAIN && res->x1.t == DUK_ISPEC_REGCONST);
+
 				if (reg_varbind >= 0) {
+					duk_reg_t reg_res;
+
+					if (toplevel_assign) {
+						/* 'reg_varbind' is the operation result and can also
+						 * become the expression value for top level assignments
+						 * such as: "var x; x += y;".
+						 */
+						reg_res = reg_varbind;
+					} else {
+						/* Not safe to use 'reg_varbind' as assignment expression
+						 * value, so go through a temp.
+						 */
+						reg_res = DUK__ALLOCTEMP(comp_ctx);
+					}
+
 					duk__emit_a_b_c(comp_ctx,
 					                args_op,
-					                (duk_regconst_t) reg_temp,
+					                (duk_regconst_t) reg_res,
 					                (duk_regconst_t) reg_varbind,
 					                res->x1.regconst);
+					res->x1.regconst = (duk_regconst_t) reg_res;
 				} else {
+					/* When LHS is not register bound, always go through a
+					 * temporary.  No optimization for top level assignment.
+					 */
+					duk_reg_t reg_temp;
+					reg_temp = DUK__ALLOCTEMP(comp_ctx);
+
 					duk__emit_a_bc(comp_ctx,
 					               DUK_OP_GETVAR,
 					               (duk_regconst_t) reg_temp,
@@ -46947,40 +63865,57 @@ static void duk__expr_led(duk_compiler_ctx *comp_ctx, duk_ivalue *left, duk_ival
 					                (duk_regconst_t) reg_temp,
 					                (duk_regconst_t) reg_temp,
 					                res->x1.regconst);
+					res->x1.regconst = (duk_regconst_t) reg_temp;
 				}
-				rc_res = (duk_regconst_t) reg_temp;
+
+				DUK_ASSERT(res->t == DUK_IVAL_PLAIN && res->x1.t == DUK_ISPEC_REGCONST);
 			}
 
+			/* At this point 'res' holds the potential expression value.
+			 * It can be basically any ivalue here, including a reg-bound
+			 * identifier (if code above deems it safe) or a unary/binary
+			 * operation.  Operations must be resolved to a side effect free
+			 * plain value, and the side effects must happen exactly once.
+			 */
+
 			if (reg_varbind >= 0) {
-				duk__emit_a_bc(comp_ctx,
-				               DUK_OP_LDREG,
-				               (duk_regconst_t) reg_varbind,
-				               rc_res);
+				if (res->t != DUK_IVAL_PLAIN) {
+					/* Resolve 'res' directly into the LHS binding, and use
+					 * that as the expression value if safe.  If not safe,
+					 * resolve to a temp/const and copy to LHS.
+					 */
+					if (toplevel_assign) {
+						duk__ivalue_toforcedreg(comp_ctx, res, (duk_int_t) reg_varbind);
+					} else {
+						duk__ivalue_totempconst(comp_ctx, res);
+						duk__copy_ivalue(comp_ctx, res, left);  /* use 'left' as a temp */
+						duk__ivalue_toforcedreg(comp_ctx, left, (duk_int_t) reg_varbind);
+					}
+				} else {
+					/* Use 'res' as the expression value (it's side effect
+					 * free and may be a plain value, a register, or a
+					 * constant) and write it to the LHS binding too.
+					 */
+					duk__copy_ivalue(comp_ctx, res, left);  /* use 'left' as a temp */
+					duk__ivalue_toforcedreg(comp_ctx, left, (duk_int_t) reg_varbind);
+				}
 			} else {
-				/* Only a reg fits into 'A' and reg_res may be a const in
-				 * straight assignment.
+				/* Only a reg fits into 'A' so coerce 'res' into a register
+				 * for PUTVAR.
 				 *
 				 * XXX: here the current A/B/C split is suboptimal: we could
 				 * just use 9 bits for reg_res (and support constants) and 17
 				 * instead of 18 bits for the varname const index.
 				 */
-				if (DUK__ISCONST(comp_ctx, rc_res)) {
-					reg_temp = DUK__ALLOCTEMP(comp_ctx);
-					duk__emit_a_bc(comp_ctx,
-					               DUK_OP_LDCONST,
-					               (duk_regconst_t) reg_temp,
-					               rc_res);
-					rc_res = (duk_regconst_t) reg_temp;
-				}
+
+				duk__ivalue_toreg(comp_ctx, res);
 				duk__emit_a_bc(comp_ctx,
 				               DUK_OP_PUTVAR | DUK__EMIT_FLAG_A_IS_SOURCE,
-				               rc_res,
+				               res->x1.regconst,
 				               rc_varname);
 			}
 
-			res->t = DUK_IVAL_PLAIN;
-			res->x1.t = DUK_ISPEC_REGCONST;
-			res->x1.regconst = rc_res;
+			/* 'res' contains expression value */
 		} else if (left->t == DUK_IVAL_PROP) {
 			/* E5 Section 11.13.1 (and others) step 4 never matches for prop writes -> no check */
 			duk_reg_t reg_obj;
@@ -46988,17 +63923,32 @@ static void duk__expr_led(duk_compiler_ctx *comp_ctx, duk_ivalue *left, duk_ival
 			duk_regconst_t rc_res;
 			duk_reg_t reg_temp;
 
+			/* Property access expressions ('a[b]') are critical to correct
+			 * LHS evaluation ordering, see test-dev-assign-eval-order*.js.
+			 * We must make sure that the LHS target slot (base object and
+			 * key) don't change during RHS evaluation.  The only concrete
+			 * problem is a register reference to a variable-bound register
+			 * (i.e., non-temp).  Require temp regs for both key and base.
+			 *
+			 * Don't allow a constant for the object (even for a number
+			 * etc), as it goes into the 'A' field of the opcode.
+			 */
+
+			reg_obj = duk__ispec_toregconst_raw(comp_ctx,
+			                                    &left->x1,
+			                                    -1 /*forced_reg*/,
+			                                    DUK__IVAL_FLAG_REQUIRE_TEMP /*flags*/);
+
+			rc_key = duk__ispec_toregconst_raw(comp_ctx,
+			                                   &left->x2,
+			                                   -1 /*forced_reg*/,
+			                                   DUK__IVAL_FLAG_REQUIRE_TEMP | DUK__IVAL_FLAG_ALLOW_CONST /*flags*/);
+
+			/* Evaluate RHS only when LHS is safe. */
 			duk__expr_toregconst(comp_ctx, res, args_rbp /*rbp_flags*/);
 			DUK_ASSERT(res->t == DUK_IVAL_PLAIN && res->x1.t == DUK_ISPEC_REGCONST);
 
-			/* Don't allow a constant for the object (even for a number etc), as
-			 * it goes into the 'A' field of the opcode.
-			 */
-
-			reg_obj = duk__ispec_toregconst_raw(comp_ctx, &left->x1, -1 /*forced_reg*/, 0 /*flags*/);  /* don't allow const */
-			rc_key = duk__ispec_toregconst_raw(comp_ctx, &left->x2, -1 /*forced_reg*/, DUK__IVAL_FLAG_ALLOW_CONST /*flags*/);
-	
-			if (args_op == DUK_OP_INVALID) {
+			if (args_op == DUK_OP_NONE) {
 				rc_res = res->x1.regconst;
 			} else {
 				reg_temp = DUK__ALLOCTEMP(comp_ctx);
@@ -47016,7 +63966,7 @@ static void duk__expr_led(duk_compiler_ctx *comp_ctx, duk_ivalue *left, duk_ival
 			}
 
 			duk__emit_a_b_c(comp_ctx,
-			                DUK_OP_PUTPROP,
+			                DUK_OP_PUTPROP | DUK__EMIT_FLAG_A_IS_SOURCE,
 			                (duk_regconst_t) reg_obj,
 			                rc_key,
 			                rc_res);
@@ -47043,7 +63993,7 @@ static void duk__expr_led(duk_compiler_ctx *comp_ctx, duk_ivalue *left, duk_ival
 
 			/* then evaluate RHS fully (its value becomes the expression value too) */
 			rc_res = duk__expr_toregconst(comp_ctx, res, args_rbp /*rbp_flags*/);
-	
+
 			duk__emit_extraop_only(comp_ctx,
 			                       DUK_EXTRAOP_INVLHS);
 
@@ -47057,14 +64007,13 @@ static void duk__expr_led(duk_compiler_ctx *comp_ctx, duk_ivalue *left, duk_ival
 		return;
 	}
 
- postincdec_extraop:
+ postincdec:
 	{
 		/*
 		 *  Post-increment/decrement will return the original value as its
 		 *  result value.  However, even that value will be coerced using
-		 *  ToNumber().
-		 *
-		 *  XXX: the current solution for this is very ugly.
+		 *  ToNumber() which is quite awkward.  Specific bytecode opcodes
+		 *  are used to handle these semantics.
 		 *
 		 *  Note that post increment/decrement has a "no LineTerminator here"
 		 *  restriction.  This is handled by duk__expr_lbp(), which forcibly terminates
@@ -47074,6 +64023,12 @@ static void duk__expr_led(duk_compiler_ctx *comp_ctx, duk_ivalue *left, duk_ival
 		duk_reg_t reg_res;
 		duk_small_uint_t args_op = args >> 8;
 
+		/* Specific assumptions for opcode numbering. */
+		DUK_ASSERT(DUK_OP_POSTINCR + 4 == DUK_OP_POSTINCV);
+		DUK_ASSERT(DUK_OP_POSTDECR + 4 == DUK_OP_POSTDECV);
+		DUK_ASSERT(DUK_OP_POSTINCR + 8 == DUK_OP_POSTINCP);
+		DUK_ASSERT(DUK_OP_POSTDECR + 8 == DUK_OP_POSTDECP);
+
 		reg_res = DUK__ALLOCTEMP(comp_ctx);
 
 		if (left->t == DUK_IVAL_VAR) {
@@ -47091,35 +64046,14 @@ static void duk__expr_led(duk_compiler_ctx *comp_ctx, duk_ivalue *left, duk_ival
 			duk_dup(ctx, left->x1.valstack_idx);
 			if (duk__lookup_lhs(comp_ctx, &reg_varbind, &rc_varname)) {
 				duk__emit_a_bc(comp_ctx,
-				               DUK_OP_LDREG,
+				               args_op,  /* e.g. DUK_OP_POSTINCR */
 				               (duk_regconst_t) reg_res,
 				               (duk_regconst_t) reg_varbind);
-				duk__emit_extraop_b_c(comp_ctx,
-				                      DUK_EXTRAOP_TONUM | DUK__EMIT_FLAG_B_IS_TARGET,
-				                      (duk_regconst_t) reg_res,
-				                      (duk_regconst_t) reg_res);
-				duk__emit_extraop_b_c(comp_ctx,
-				                      args_op | DUK__EMIT_FLAG_B_IS_TARGET,
-				                      (duk_regconst_t) reg_varbind,
-				                      (duk_regconst_t) reg_res);
 			} else {
-				duk_reg_t reg_temp = DUK__ALLOCTEMP(comp_ctx);
 				duk__emit_a_bc(comp_ctx,
-				               DUK_OP_GETVAR,
+				               args_op + 4,  /* e.g. DUK_OP_POSTINCV */
 				               (duk_regconst_t) reg_res,
 				               rc_varname);
-				duk__emit_extraop_b_c(comp_ctx,
-				                      DUK_EXTRAOP_TONUM | DUK__EMIT_FLAG_B_IS_TARGET,
-				                      (duk_regconst_t) reg_res,
-				                      (duk_regconst_t) reg_res);
-				duk__emit_extraop_b_c(comp_ctx,
-				                      args_op | DUK__EMIT_FLAG_B_IS_TARGET,
-				                      (duk_regconst_t) reg_temp,
-				                      (duk_regconst_t) reg_res);
-				duk__emit_a_bc(comp_ctx,
-				               DUK_OP_PUTVAR | DUK__EMIT_FLAG_A_IS_SOURCE,
-				               (duk_regconst_t) reg_temp,
-				               rc_varname);
 			}
 
 			DUK_DDD(DUK_DDDPRINT("postincdec to '%!O' -> reg_varbind=%ld, rc_varname=%ld",
@@ -47127,38 +64061,24 @@ static void duk__expr_led(duk_compiler_ctx *comp_ctx, duk_ivalue *left, duk_ival
 		} else if (left->t == DUK_IVAL_PROP) {
 			duk_reg_t reg_obj;  /* allocate to reg only (not const) */
 			duk_regconst_t rc_key;
-			duk_reg_t reg_temp = DUK__ALLOCTEMP(comp_ctx);
 
 			reg_obj = duk__ispec_toregconst_raw(comp_ctx, &left->x1, -1 /*forced_reg*/, 0 /*flags*/);  /* don't allow const */
 			rc_key = duk__ispec_toregconst_raw(comp_ctx, &left->x2, -1 /*forced_reg*/, DUK__IVAL_FLAG_ALLOW_CONST /*flags*/);
 			duk__emit_a_b_c(comp_ctx,
-			                DUK_OP_GETPROP, 
+			                args_op + 8,  /* e.g. DUK_OP_POSTINCP */
 			                (duk_regconst_t) reg_res,
 			                (duk_regconst_t) reg_obj,
 			                rc_key);
-			duk__emit_extraop_b_c(comp_ctx,
-			                      DUK_EXTRAOP_TONUM | DUK__EMIT_FLAG_B_IS_TARGET,
-			                      (duk_regconst_t) reg_res,
-			                      (duk_regconst_t) reg_res);
-			duk__emit_extraop_b_c(comp_ctx,
-			                      args_op | DUK__EMIT_FLAG_B_IS_TARGET,
-			                      (duk_regconst_t) reg_temp,
-			                      (duk_regconst_t) reg_res);
-			duk__emit_a_b_c(comp_ctx,
-			                DUK_OP_PUTPROP,
-			                (duk_regconst_t) reg_obj,
-			                rc_key,
-			                (duk_regconst_t) reg_temp);
 		} else {
 			/* Technically return value is not needed because INVLHS will
 			 * unconditially throw a ReferenceError.  Coercion is necessary
 			 * for proper semantics (consider ToNumber() called for an object).
+			 * Use DUK_EXTRAOP_UNP with a dummy register to get ToNumber().
 			 */
 			duk__ivalue_toforcedreg(comp_ctx, left, reg_res);
-			duk__emit_extraop_b_c(comp_ctx,
-			                      DUK_EXTRAOP_TONUM | DUK__EMIT_FLAG_B_IS_TARGET,
-			                      (duk_regconst_t) reg_res,
-			                      (duk_regconst_t) reg_res);  /* for side effects */
+			duk__emit_extraop_bc(comp_ctx,
+			                     DUK_EXTRAOP_UNP,
+			                     reg_res);  /* for side effects, result ignored */
 			duk__emit_extraop_only(comp_ctx,
 			                       DUK_EXTRAOP_INVLHS);
 		}
@@ -47179,7 +64099,7 @@ static void duk__expr_led(duk_compiler_ctx *comp_ctx, duk_ivalue *left, duk_ival
 	return;
 }
 
-static duk_small_uint_t duk__expr_lbp(duk_compiler_ctx *comp_ctx) {
+DUK_LOCAL duk_small_uint_t duk__expr_lbp(duk_compiler_ctx *comp_ctx) {
 	duk_small_int_t tok = comp_ctx->curr_token.t;
 
 	DUK_ASSERT(tok >= DUK_TOK_MINVAL && tok <= DUK_TOK_MAXVAL);
@@ -47218,11 +64138,12 @@ static duk_small_uint_t duk__expr_lbp(duk_compiler_ctx *comp_ctx) {
  */
 
 #define DUK__EXPR_RBP_MASK           0xff
-#define DUK__EXPR_FLAG_REJECT_IN     (1 << 8)
-#define DUK__EXPR_FLAG_ALLOW_EMPTY   (1 << 9)
+#define DUK__EXPR_FLAG_REJECT_IN     (1 << 8)   /* reject 'in' token (used for for-in) */
+#define DUK__EXPR_FLAG_ALLOW_EMPTY   (1 << 9)   /* allow empty expression */
+#define DUK__EXPR_FLAG_REQUIRE_INIT  (1 << 10)  /* require initializer for var/const */
 
 /* main expression parser function */
-static void duk__expr(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags) {
+DUK_LOCAL void duk__expr(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags) {
 	duk_hthread *thr = comp_ctx->thr;
 	duk_context *ctx = (duk_context *) thr;
 	duk_ivalue tmp_alloc;   /* 'res' is used for "left", and 'tmp' for "right" */
@@ -47284,7 +64205,7 @@ static void duk__expr(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uin
 	DUK__RECURSION_DECREASE(comp_ctx, thr);
 }
 
-static void duk__exprtop(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags) {
+DUK_LOCAL void duk__exprtop(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags) {
 	duk_hthread *thr = comp_ctx->thr;
 
 	/* Note: these variables must reside in 'curr_func' instead of the global
@@ -47309,66 +64230,73 @@ static void duk__exprtop(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_
  * Each helper needs at least 2-3 calls to make it worth while to wrap.
  */
 
-static duk_reg_t duk__expr_toreg(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags) {
+#if 0  /* unused */
+DUK_LOCAL duk_reg_t duk__expr_toreg(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags) {
 	duk__expr(comp_ctx, res, rbp_flags);
 	return duk__ivalue_toreg(comp_ctx, res);
 }
+#endif
 
 #if 0  /* unused */
-static duk_reg_t duk__expr_totempreg(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags) {
+DUK_LOCAL duk_reg_t duk__expr_totemp(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags) {
 	duk__expr(comp_ctx, res, rbp_flags);
-	return duk__ivalue_totempreg(comp_ctx, res);
+	return duk__ivalue_totemp(comp_ctx, res);
 }
 #endif
 
-static void duk__expr_toforcedreg(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags, duk_reg_t forced_reg) {
+DUK_LOCAL void duk__expr_toforcedreg(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags, duk_reg_t forced_reg) {
 	DUK_ASSERT(forced_reg >= 0);
 	duk__expr(comp_ctx, res, rbp_flags);
 	duk__ivalue_toforcedreg(comp_ctx, res, forced_reg);
 }
 
-static duk_regconst_t duk__expr_toregconst(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags) {
+DUK_LOCAL duk_regconst_t duk__expr_toregconst(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags) {
 	duk__expr(comp_ctx, res, rbp_flags);
 	return duk__ivalue_toregconst(comp_ctx, res);
 }
 
-static void duk__expr_toplain(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags) {
+#if 0  /* unused */
+DUK_LOCAL duk_regconst_t duk__expr_totempconst(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags) {
+	duk__expr(comp_ctx, res, rbp_flags);
+	return duk__ivalue_totempconst(comp_ctx, res);
+}
+#endif
+
+DUK_LOCAL void duk__expr_toplain(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags) {
 	duk__expr(comp_ctx, res, rbp_flags);
 	duk__ivalue_toplain(comp_ctx, res);
 }
 
-static void duk__expr_toplain_ignore(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags) {
+DUK_LOCAL void duk__expr_toplain_ignore(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags) {
 	duk__expr(comp_ctx, res, rbp_flags);
 	duk__ivalue_toplain_ignore(comp_ctx, res);
 }
 
-static duk_reg_t duk__exprtop_toreg(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags) {
+DUK_LOCAL duk_reg_t duk__exprtop_toreg(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags) {
 	duk__exprtop(comp_ctx, res, rbp_flags);
 	return duk__ivalue_toreg(comp_ctx, res);
 }
 
 #if 0  /* unused */
-static duk_reg_t duk__exprtop_totempreg(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags) {
+DUK_LOCAL duk_reg_t duk__exprtop_totemp(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags) {
 	duk__exprtop(comp_ctx, res, rbp_flags);
-	return duk__ivalue_totempreg(comp_ctx, res);
+	return duk__ivalue_totemp(comp_ctx, res);
 }
 #endif
 
-#if 0  /* unused */
-static void duk__exprtop_toforcedreg(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags, duk_reg_t forced_reg) {
+DUK_LOCAL void duk__exprtop_toforcedreg(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags, duk_reg_t forced_reg) {
 	DUK_ASSERT(forced_reg >= 0);
 	duk__exprtop(comp_ctx, res, rbp_flags);
 	duk__ivalue_toforcedreg(comp_ctx, res, forced_reg);
 }
-#endif
 
-static duk_regconst_t duk__exprtop_toregconst(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags) {
+DUK_LOCAL duk_regconst_t duk__exprtop_toregconst(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags) {
 	duk__exprtop(comp_ctx, res, rbp_flags);
 	return duk__ivalue_toregconst(comp_ctx, res);
 }
 
 #if 0  /* unused */
-static void duk__exprtop_toplain_ignore(duk_compiler_ctx *comp_ctx, duk_ivalue *res, int rbp_flags) {
+DUK_LOCAL void duk__exprtop_toplain_ignore(duk_compiler_ctx *comp_ctx, duk_ivalue *res, int rbp_flags) {
 	duk__exprtop(comp_ctx, res, rbp_flags);
 	duk__ivalue_toplain_ignore(comp_ctx, res);
 }
@@ -47426,7 +64354,7 @@ static void duk__exprtop_toplain_ignore(duk_compiler_ctx *comp_ctx, duk_ivalue *
  * as is done in 'for-in' parsing.
  */
 
-static void duk__parse_var_decl(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t expr_flags, duk_reg_t *out_reg_varbind, duk_regconst_t *out_rc_varname) {
+DUK_LOCAL void duk__parse_var_decl(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t expr_flags, duk_reg_t *out_reg_varbind, duk_regconst_t *out_rc_varname) {
 	duk_hthread *thr = comp_ctx->thr;
 	duk_context *ctx = (duk_context *) thr;
 	duk_hstring *h_varname;
@@ -47486,6 +64414,11 @@ static void duk__parse_var_decl(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk
 			               (duk_regconst_t) reg_val,
 			               rc_varname);
 		}
+	} else {
+		if (expr_flags & DUK__EXPR_FLAG_REQUIRE_INIT) {
+			/* Used for minimal 'const': initializer required. */
+			goto syntax_error;
+		}
 	}
 
 	duk_pop(ctx);  /* pop varname */
@@ -47499,7 +64432,7 @@ static void duk__parse_var_decl(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk
 	DUK_ERROR(thr, DUK_ERR_SYNTAX_ERROR, DUK_STR_INVALID_VAR_DECLARATION);
 }
 
-static void duk__parse_var_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res) {
+DUK_LOCAL void duk__parse_var_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t expr_flags) {
 	duk_reg_t reg_varbind;
 	duk_regconst_t rc_varname;
 
@@ -47507,19 +64440,19 @@ static void duk__parse_var_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res) {
 
 	for (;;) {
 		/* rc_varname and reg_varbind are ignored here */
-		duk__parse_var_decl(comp_ctx, res, 0, &reg_varbind, &rc_varname);
+		duk__parse_var_decl(comp_ctx, res, 0 | expr_flags, &reg_varbind, &rc_varname);
 
 		if (comp_ctx->curr_token.t != DUK_TOK_COMMA) {
 			break;
 		}
 		duk__advance(comp_ctx);
-	} 
+	}
 }
 
-static void duk__parse_for_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_int_t pc_label_site) {
+DUK_LOCAL void duk__parse_for_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_int_t pc_label_site) {
 	duk_hthread *thr = comp_ctx->thr;
 	duk_context *ctx = (duk_context *) thr;
-	duk_int_t pc_v34_lhs;    /* start variant 3/4 left-hand-side code (L1 in doc/compiler.txt example) */
+	duk_int_t pc_v34_lhs;    /* start variant 3/4 left-hand-side code (L1 in doc/compiler.rst example) */
 	duk_reg_t temp_reset;    /* knock back "next temp" to this whenever possible */
 	duk_reg_t reg_temps;     /* preallocated temporaries (2) for variants 3 and 4 */
 
@@ -47546,10 +64479,10 @@ static void duk__parse_for_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk
 	 *  Parsing these without arbitrary lookahead or backtracking is relatively
 	 *  tricky but we manage to do so for now.
 	 *
-	 *  See doc/compiler.txt for a detailed discussion of control flow
+	 *  See doc/compiler.rst for a detailed discussion of control flow
 	 *  issues, evaluation order issues, etc.
 	 */
-	
+
 	duk__advance(comp_ctx);  /* eat 'for' */
 	duk__advance_expect(comp_ctx, DUK_TOK_LPAREN);
 
@@ -47657,7 +64590,7 @@ static void duk__parse_for_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk
 				reg_obj = duk__ispec_toregconst_raw(comp_ctx, &res->x1, -1 /*forced_reg*/, 0 /*flags*/);  /* don't allow const */
 				rc_key = duk__ispec_toregconst_raw(comp_ctx, &res->x2, -1 /*forced_reg*/, DUK__IVAL_FLAG_ALLOW_CONST /*flags*/);
 				duk__emit_a_b_c(comp_ctx,
-				                DUK_OP_PUTPROP,
+				                DUK_OP_PUTPROP | DUK__EMIT_FLAG_A_IS_SOURCE,
 				                (duk_regconst_t) reg_obj,
 				                rc_key,
 				                (duk_regconst_t) (reg_temps + 0));
@@ -47773,7 +64706,7 @@ static void duk__parse_for_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk
 	 *
 	 *  Variables set before entering here:
 	 *
-	 *    pc_v34_lhs:    insert a "JUMP L2" here (see doc/compiler.txt example).
+	 *    pc_v34_lhs:    insert a "JUMP L2" here (see doc/compiler.rst example).
 	 *    reg_temps + 0: iteration target value (written to LHS)
 	 *    reg_temps + 1: enumerator object
 	 */
@@ -47788,7 +64721,7 @@ static void duk__parse_for_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk
 
 		/* First we need to insert a jump in the middle of previously
 		 * emitted code to get the control flow right.  No jumps can
-		 * cross the position where the jump is inserted.  See doc/compiler.txt
+		 * cross the position where the jump is inserted.  See doc/compiler.rst
 		 * for discussion on the intricacies of control flow and side effects
 		 * for variants 3 and 4.
 		 */
@@ -47809,12 +64742,12 @@ static void duk__parse_for_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk
 		 * INITENUM will creates a 'null' enumerator which works like an empty enumerator
 		 * (E5 Section 12.6.4, step 3).  Note that INITENUM requires the value to be in a
 		 * register (constant not allowed).
-	 	 */
+		 */
 
 		pc_l2 = duk__get_current_pc(comp_ctx);
 		reg_target = duk__exprtop_toreg(comp_ctx, res, DUK__BP_FOR_EXPR /*rbp_flags*/);  /* Expression */
 		duk__emit_extraop_b_c(comp_ctx,
-		                      DUK_EXTRAOP_INITENUM,
+		                      DUK_EXTRAOP_INITENUM | DUK__EMIT_FLAG_B_IS_TARGET,
 		                      (duk_regconst_t) (reg_temps + 1),
 		                      (duk_regconst_t) reg_target);
 		pc_jumpto_l4 = duk__emit_jump_empty(comp_ctx);
@@ -47826,12 +64759,18 @@ static void duk__parse_for_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk
 		duk__parse_stmt(comp_ctx, res, 0 /*allow_source_elem*/);
 		/* temp reset is not necessary after duk__parse_stmt(), which already does it */
 
+		/* NEXTENUM needs a jump slot right after the main opcode.
+		 * We need the code emitter to reserve the slot: if there's
+		 * target shuffling, the target shuffle opcodes must happen
+		 * after the jump slot (for NEXTENUM the shuffle opcodes are
+		 * not needed if the enum is finished).
+		 */
 		pc_l4 = duk__get_current_pc(comp_ctx);
 		duk__emit_extraop_b_c(comp_ctx,
-		                      DUK_EXTRAOP_NEXTENUM,
+		                      DUK_EXTRAOP_NEXTENUM | DUK__EMIT_FLAG_B_IS_TARGET | DUK__EMIT_FLAG_RESERVE_JUMPSLOT,
 		                      (duk_regconst_t) (reg_temps + 0),
 		                      (duk_regconst_t) (reg_temps + 1));
-		pc_jumpto_l5 = duk__emit_jump_empty(comp_ctx);  /* NEXTENUM jump slot: executed when enum finished */
+		pc_jumpto_l5 = comp_ctx->emit_jumpslot_pc;  /* NEXTENUM jump slot: executed when enum finished */
 		duk__emit_jump(comp_ctx, pc_l1);  /* jump to next loop, using reg_v34_iter as iterated value */
 
 		pc_l5 = duk__get_current_pc(comp_ctx);
@@ -47861,11 +64800,11 @@ static void duk__parse_for_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk
 	DUK_DDD(DUK_DDDPRINT("end parsing a for/for-in statement"));
 	return;
 
- syntax_error:		
+ syntax_error:
 	DUK_ERROR(thr, DUK_ERR_SYNTAX_ERROR, DUK_STR_INVALID_FOR);
 }
 
-static void duk__parse_switch_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_int_t pc_label_site) {
+DUK_LOCAL void duk__parse_switch_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_int_t pc_label_site) {
 	duk_hthread *thr = comp_ctx->thr;
 	duk_reg_t temp_at_loop;
 	duk_regconst_t rc_switch;    /* reg/const for switch value */
@@ -47886,7 +64825,7 @@ static void duk__parse_switch_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res,
 	 *    - Case selectors are expressions, not values, and may thus e.g. throw
 	 *      exceptions (which causes evaluation order concerns)
 	 *
-	 *    - Evaluation semantics of case selectors and default clause need to be 
+	 *    - Evaluation semantics of case selectors and default clause need to be
 	 *      carefully implemented to provide correct behavior even with case value
 	 *      side effects
 	 *
@@ -47897,7 +64836,7 @@ static void duk__parse_switch_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res,
 	 *      only process the first match before switching to a "propagation" mode
 	 *      where case values are no longer evaluated
 	 *
-	 *  See E5 Section 12.11.  Also see doc/compiler.txt for compilation
+	 *  See E5 Section 12.11.  Also see doc/compiler.rst for compilation
 	 *  discussion.
 	 */
 
@@ -47965,6 +64904,15 @@ static void duk__parse_switch_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res,
 			duk__advance(comp_ctx);
 			duk__advance_expect(comp_ctx, DUK_TOK_COLON);
 
+			/* Fix for https://github.com/svaarala/duktape/issues/155:
+			 * If 'default' is first clause (detected by pc_prevcase < 0)
+			 * we need to ensure we stay in the matching chain.
+			 */
+			if (pc_prevcase < 0) {
+				DUK_DD(DUK_DDPRINT("default clause is first, emit prevcase jump"));
+				pc_prevcase = duk__emit_jump_empty(comp_ctx);
+			}
+
 			/* default clause matches next statement list (if any) */
 			pc_default = -2;
 		} else {
@@ -48055,7 +65003,7 @@ static void duk__parse_switch_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res,
 	DUK_ERROR(thr, DUK_ERR_SYNTAX_ERROR, DUK_STR_INVALID_SWITCH);
 }
 
-static void duk__parse_if_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res) {
+DUK_LOCAL void duk__parse_if_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res) {
 	duk_reg_t temp_reset;
 	duk_regconst_t rc_cond;
 	duk_int_t pc_jump_false;
@@ -48102,7 +65050,7 @@ static void duk__parse_if_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res) {
 	DUK_DDD(DUK_DDDPRINT("end parsing if statement"));
 }
 
-static void duk__parse_do_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_int_t pc_label_site) {
+DUK_LOCAL void duk__parse_do_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_int_t pc_label_site) {
 	duk_regconst_t rc_cond;
 	duk_int_t pc_start;
 
@@ -48129,7 +65077,7 @@ static void duk__parse_do_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_
 	DUK_DDD(DUK_DDDPRINT("end parsing do statement"));
 }
 
-static void duk__parse_while_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_int_t pc_label_site) {
+DUK_LOCAL void duk__parse_while_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_int_t pc_label_site) {
 	duk_reg_t temp_reset;
 	duk_regconst_t rc_cond;
 	duk_int_t pc_start;
@@ -48162,7 +65110,7 @@ static void duk__parse_while_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, d
 	DUK_DDD(DUK_DDDPRINT("end parsing while statement"));
 }
 
-static void duk__parse_break_or_continue_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res) {
+DUK_LOCAL void duk__parse_break_or_continue_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res) {
 	duk_hthread *thr = comp_ctx->thr;
 	duk_bool_t is_break = (comp_ctx->curr_token.t == DUK_TOK_BREAK);
 	duk_int_t label_id;
@@ -48211,13 +65159,13 @@ static void duk__parse_break_or_continue_stmt(duk_compiler_ctx *comp_ctx, duk_iv
 		                     (long) is_break, (long) label_id, (long) label_is_closest,
 		                     (long) label_catch_depth, (long) comp_ctx->curr_func.catch_depth));
 
-		duk__emit_abc(comp_ctx,
-		              is_break ? DUK_OP_BREAK : DUK_OP_CONTINUE,
+		duk__emit_extraop_bc(comp_ctx,
+		              is_break ? DUK_EXTRAOP_BREAK : DUK_EXTRAOP_CONTINUE,
 		              (duk_regconst_t) label_id);
 	}
 }
 
-static void duk__parse_return_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res) {
+DUK_LOCAL void duk__parse_return_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res) {
 	duk_hthread *thr = comp_ctx->thr;
 	duk_regconst_t rc_val;
 	duk_small_uint_t ret_flags;
@@ -48231,12 +65179,6 @@ static void duk__parse_return_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res)
 		DUK_ERROR(thr, DUK_ERR_SYNTAX_ERROR, DUK_STR_INVALID_RETURN);
 	}
 
-	/* Use a fast return when possible.  A fast return does not cause a longjmp()
-	 * unnecessarily.  A fast return can be done when no TCF catchers are active
-	 * (this includes 'try' and 'with' statements).  Active label catches do not
-	 * prevent a fast return; they're unwound on return automatically.
-	 */
-
 	ret_flags = 0;
 
 	if (comp_ctx->curr_token.t == DUK_TOK_SEMICOLON ||  /* explicit semi follows */
@@ -48257,8 +65199,36 @@ static void duk__parse_return_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res)
 		rc_val = duk__exprtop_toregconst(comp_ctx, res, DUK__BP_FOR_EXPR /*rbp_flags*/);
 		pc_after_expr = duk__get_current_pc(comp_ctx);
 
-		/* Tail call check: if last opcode emitted was CALL, and
-		 * the context allows it, change the CALL to a tailcall.
+		/* Tail call check: if last opcode emitted was CALL(I), and
+		 * the context allows it, change the CALL(I) to a tail call.
+		 * This doesn't guarantee that a tail call will be allowed at
+		 * runtime, so the RETURN must still be emitted.  (Duktape
+		 * 0.10.0 avoided this and simulated a RETURN if a tail call
+		 * couldn't be used at runtime; but this didn't work
+		 * correctly with a thread yield/resume, see
+		 * test-bug-tailcall-thread-yield-resume.js for discussion.)
+		 *
+		 * In addition to the last opcode being CALL, we also need to
+		 * be sure that 'rc_val' is the result register of the CALL(I).
+		 * For instance, for the expression 'return 0, (function ()
+		 * { return 1; }), 2' the last opcode emitted is CALL (no
+		 * bytecode is emitted for '2') but 'rc_val' indicates
+		 * constant '2'.  Similarly if '2' is replaced by a register
+		 * bound variable, no opcodes are emitted but tail call would
+		 * be incorrect.
+		 *
+		 * This is tricky and easy to get wrong.  It would be best to
+		 * track enough expression metadata to check that 'rc_val' came
+		 * from that last CALL instruction.  We don't have that metadata
+		 * now, so we check that 'rc_val' is a temporary register result
+		 * (not a constant or a register bound variable).  There should
+		 * be no way currently for 'rc_val' to be a temporary for an
+		 * expression following the CALL instruction without emitting
+		 * some opcodes following the CALL.  This proxy check is used
+		 * below.
+		 *
+		 * See: test-bug-comma-expr-gh131.js.
+		 *
 		 * The non-standard 'caller' property disables tail calls
 		 * because they pose some special cases which haven't been
 		 * fixed yet.
@@ -48274,24 +65244,14 @@ static void duk__parse_return_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res)
 			DUK_ASSERT(instr != NULL);
 
 			op = (duk_small_uint_t) DUK_DEC_OP(instr->ins);
-			if (op == DUK_OP_CALL || op == DUK_OP_CALLI) {
+			if ((op == DUK_OP_CALL || op == DUK_OP_CALLI) &&
+			    DUK__ISTEMP(comp_ctx, rc_val) /* see above */) {
 				DUK_DDD(DUK_DDDPRINT("return statement detected a tail call opportunity: "
 				                     "catch depth is 0, duk__exprtop() emitted >= 1 instructions, "
 				                     "and last instruction is a CALL "
 				                     "-> set TAILCALL flag"));
 				/* Just flip the single bit. */
 				instr->ins |= DUK_ENC_OP_A_B_C(0, DUK_BC_CALL_FLAG_TAILCALL, 0, 0);
-
-				/* In Duktape 0.10.0 no RETURN was emitted; the executor would
-				 * simulate a RETURN if a tailcall could not actually be performed
-				 * (e.g. if the target was a native function).  This would break
-				 * during execution if the target function turned out to be
-				 * thread yield/resume.  So now we just omit the RETURN which
-				 * also obviates the need for a simulated return in the executor
-				 * when a tailcall cannot be actually done as requested.
-				 *
-				 * See test-bug-tailcall-thread-yield-resume.js for discussion.
-				 */
 			}
 		}
 #endif  /* DUK_USE_TAILCALL */
@@ -48299,49 +65259,36 @@ static void duk__parse_return_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res)
 		ret_flags = DUK_BC_RETURN_FLAG_HAVE_RETVAL;
 	}
 
-	if (comp_ctx->curr_func.catch_depth == 0) {
-		DUK_DDD(DUK_DDDPRINT("fast return allowed -> use fast return"));
-		ret_flags |= DUK_BC_RETURN_FLAG_FAST;
-	} else {
-		DUK_DDD(DUK_DDDPRINT("fast return not allowed -> use slow return"));
-	}
-
 	duk__emit_a_b(comp_ctx,
-	              DUK_OP_RETURN,
+	              DUK_OP_RETURN | DUK__EMIT_FLAG_NO_SHUFFLE_A,
 	              (duk_regconst_t) ret_flags /*flags*/,
 	              rc_val /*reg*/);
 }
 
-static void duk__parse_throw_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res) {
+DUK_LOCAL void duk__parse_throw_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res) {
 	duk_reg_t reg_val;
 
 	duk__advance(comp_ctx);  /* eat 'throw' */
 
-	if (comp_ctx->curr_token.t == DUK_TOK_SEMICOLON ||  /* explicit semi follows */
-	    comp_ctx->curr_token.lineterm ||                /* automatic semi will be inserted */
-	    comp_ctx->curr_token.allow_auto_semi) {         /* automatic semi will be inserted */
-		DUK_DDD(DUK_DDDPRINT("empty throw value -> undefined"));
-		reg_val = DUK__ALLOCTEMP(comp_ctx);
-		duk__emit_extraop_bc(comp_ctx,
-		                     DUK_EXTRAOP_LDUNDEF,
-		                     (duk_regconst_t) reg_val);
-	} else {
-		DUK_DDD(DUK_DDDPRINT("throw with a value"));
-		reg_val = duk__exprtop_toreg(comp_ctx, res, DUK__BP_FOR_EXPR /*rbp_flags*/);
+	/* Unlike break/continue, throw statement does not allow an empty value. */
+
+	if (comp_ctx->curr_token.lineterm) {
+		DUK_ERROR(comp_ctx->thr, DUK_ERR_SYNTAX_ERROR, DUK_STR_INVALID_THROW);
 	}
 
-	duk__emit_extraop_b_c(comp_ctx,
-	                      DUK_EXTRAOP_THROW,
-	                      (duk_regconst_t) reg_val,
-	                      (duk_regconst_t) 0);
+	reg_val = duk__exprtop_toreg(comp_ctx, res, DUK__BP_FOR_EXPR /*rbp_flags*/);
+	duk__emit_extraop_bc(comp_ctx,
+	                     DUK_EXTRAOP_THROW,
+	                     (duk_regconst_t) reg_val);
 }
 
-static void duk__parse_try_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res) {
+DUK_LOCAL void duk__parse_try_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res) {
 	duk_hthread *thr = comp_ctx->thr;
 	duk_context *ctx = (duk_context *) thr;
 	duk_reg_t reg_catch;      /* reg_catch+0 and reg_catch+1 are reserved for TRYCATCH */
 	duk_regconst_t rc_varname = 0;
 	duk_small_uint_t trycatch_flags = 0;
+	duk_int_t pc_ldconst = -1;
 	duk_int_t pc_trycatch = -1;
 	duk_int_t pc_catch = -1;
 	duk_int_t pc_finally = -1;
@@ -48351,7 +65298,7 @@ static void duk__parse_try_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res) {
 	/*
 	 *  See the following documentation for discussion:
 	 *
-	 *    doc/execution.txt: control flow details
+	 *    doc/execution.rst: control flow details
 	 *
 	 *  Try, catch, and finally "parts" are Blocks, not Statements, so
 	 *  they must always be delimited by curly braces.  This is unlike e.g.
@@ -48369,6 +65316,14 @@ static void duk__parse_try_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res) {
 
 	reg_catch = DUK__ALLOCTEMPS(comp_ctx, 2);
 
+	/* The target for this LDCONST may need output shuffling, but we assume
+	 * that 'pc_ldconst' will be the LDCONST that we can patch later.  This
+	 * should be the case because there's no input shuffling.  (If there's
+	 * no catch clause, this LDCONST will be replaced with a NOP.)
+	 */
+	pc_ldconst = duk__get_current_pc(comp_ctx);
+	duk__emit_a_bc(comp_ctx, DUK_OP_LDCONST, reg_catch, 0 /*patched later*/);
+
 	pc_trycatch = duk__get_current_pc(comp_ctx);
 	duk__emit_invalid(comp_ctx);  /* TRYCATCH, cannot emit now (not enough info) */
 	duk__emit_invalid(comp_ctx);  /* jump for 'catch' case */
@@ -48530,7 +65485,13 @@ static void duk__parse_try_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res) {
 		goto syntax_error;
 	}
 
+	/* If there's no catch block, rc_varname will be 0 and duk__patch_trycatch()
+	 * will replace the LDCONST with a NOP.  For any actual constant (including
+	 * constant 0) the DUK__CONST_MARKER flag will be set in rc_varname.
+	 */
+
 	duk__patch_trycatch(comp_ctx,
+	                    pc_ldconst,
 	                    pc_trycatch,
 	                    reg_catch,
 	                    rc_varname,
@@ -48556,11 +65517,10 @@ static void duk__parse_try_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res) {
 	DUK_ERROR(thr, DUK_ERR_SYNTAX_ERROR, DUK_STR_INVALID_TRY);
 }
 
-static void duk__parse_with_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res) {
+DUK_LOCAL void duk__parse_with_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res) {
 	duk_int_t pc_trycatch;
 	duk_int_t pc_finished;
 	duk_reg_t reg_catch;
-	duk_regconst_t rc_target;
 	duk_small_uint_t trycatch_flags;
 
 	if (comp_ctx->curr_func.is_strict) {
@@ -48574,16 +65534,15 @@ static void duk__parse_with_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res) {
 	reg_catch = DUK__ALLOCTEMPS(comp_ctx, 2);
 
 	duk__advance_expect(comp_ctx, DUK_TOK_LPAREN);
-	rc_target = duk__exprtop_toregconst(comp_ctx, res, DUK__BP_FOR_EXPR /*rbp_flags*/);
+	duk__exprtop_toforcedreg(comp_ctx, res, DUK__BP_FOR_EXPR /*rbp_flags*/, reg_catch);
 	duk__advance_expect(comp_ctx, DUK_TOK_RPAREN);
 
 	pc_trycatch = duk__get_current_pc(comp_ctx);
 	trycatch_flags = DUK_BC_TRYCATCH_FLAG_WITH_BINDING;
-	duk__emit_a_b_c(comp_ctx,
-	                DUK_OP_TRYCATCH,
+	duk__emit_a_bc(comp_ctx,
+	                DUK_OP_TRYCATCH | DUK__EMIT_FLAG_NO_SHUFFLE_A,
 	                (duk_regconst_t) trycatch_flags /*a*/,
-	                (duk_regconst_t) reg_catch /*b*/,
-	                rc_target /*c*/);
+	                (duk_regconst_t) reg_catch /*bc*/);
 	duk__emit_invalid(comp_ctx);  /* catch jump */
 	duk__emit_invalid(comp_ctx);  /* finished jump */
 
@@ -48598,7 +65557,7 @@ static void duk__parse_with_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res) {
 	comp_ctx->curr_func.catch_depth--;
 }
 
-static duk_int_t duk__stmt_label_site(duk_compiler_ctx *comp_ctx, duk_int_t label_id) {
+DUK_LOCAL duk_int_t duk__stmt_label_site(duk_compiler_ctx *comp_ctx, duk_int_t label_id) {
 	/* if a site already exists, nop: max one label site per statement */
 	if (label_id >= 0) {
 		return label_id;
@@ -48607,9 +65566,9 @@ static duk_int_t duk__stmt_label_site(duk_compiler_ctx *comp_ctx, duk_int_t labe
 	label_id = comp_ctx->curr_func.label_next++;
 	DUK_DDD(DUK_DDDPRINT("allocated new label id for label site: %ld", (long) label_id));
 
-	duk__emit_abc(comp_ctx,
-	              DUK_OP_LABEL,
-	              (duk_regconst_t) label_id);
+	duk__emit_extraop_bc(comp_ctx,
+	                     DUK_EXTRAOP_LABEL,
+	                     (duk_regconst_t) label_id);
 	duk__emit_invalid(comp_ctx);
 	duk__emit_invalid(comp_ctx);
 
@@ -48621,7 +65580,7 @@ static duk_int_t duk__stmt_label_site(duk_compiler_ctx *comp_ctx, duk_int_t labe
  * Creates a label site (with an empty label) automatically for iteration
  * statements.  Also "peels off" any label statements for explicit labels.
  */
-static void duk__parse_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_bool_t allow_source_elem) {
+DUK_LOCAL void duk__parse_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_bool_t allow_source_elem) {
 	duk_hthread *thr = comp_ctx->thr;
 	duk_context *ctx = (duk_context *) thr;
 	duk_bool_t dir_prol_at_entry;    /* directive prologue status at entry */
@@ -48710,7 +65669,7 @@ static void duk__parse_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_boo
 		{
 			/* FunctionDeclaration: not strictly a statement but handled as such.
 			 *
-		 	 * O(depth^2) parse count for inner functions is handled by recording a
+			 * O(depth^2) parse count for inner functions is handled by recording a
 			 * lexer offset on the first compilation pass, so that the function can
 			 * be efficiently skipped on the second pass.  This is encapsulated into
 			 * duk__parse_func_like_fnum().
@@ -48756,12 +65715,21 @@ static void duk__parse_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_boo
 		duk__advance(comp_ctx);
 		duk__parse_stmts(comp_ctx, 0 /*allow_source_elem*/, 0 /*expect_eof*/);
 		/* the DUK_TOK_RCURLY is eaten by duk__parse_stmts() */
+		if (label_id >= 0) {
+			duk__patch_jump_here(comp_ctx, pc_at_entry + 1);  /* break jump */
+		}
 		stmt_flags = 0;
 		break;
 	}
+	case DUK_TOK_CONST: {
+		DUK_DDD(DUK_DDDPRINT("constant declaration statement"));
+		duk__parse_var_stmt(comp_ctx, res, DUK__EXPR_FLAG_REQUIRE_INIT /*expr_flags*/);
+		stmt_flags = DUK__HAS_TERM;
+		break;
+	}
 	case DUK_TOK_VAR: {
 		DUK_DDD(DUK_DDDPRINT("variable declaration statement"));
-		duk__parse_var_stmt(comp_ctx, res);
+		duk__parse_var_stmt(comp_ctx, res, 0 /*expr_flags*/);
 		stmt_flags = DUK__HAS_TERM;
 		break;
 	}
@@ -48774,6 +65742,9 @@ static void duk__parse_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_boo
 	case DUK_TOK_IF: {
 		DUK_DDD(DUK_DDDPRINT("if statement"));
 		duk__parse_if_stmt(comp_ctx, res);
+		if (label_id >= 0) {
+			duk__patch_jump_here(comp_ctx, pc_at_entry + 1);  /* break jump */
+		}
 		stmt_flags = 0;
 		break;
 	}
@@ -48785,7 +65756,7 @@ static void duk__parse_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_boo
 		 *
 		 *    https://bugs.ecmascript.org/show_bug.cgi?id=8
 		 *
-		 *  See doc/compiler.txt for details.
+		 *  See doc/compiler.rst for details.
 		 */
 		DUK_DDD(DUK_DDDPRINT("do statement"));
 		DUK_ASSERT(label_id >= 0);
@@ -48840,6 +65811,9 @@ static void duk__parse_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_boo
 		DUK_DDD(DUK_DDDPRINT("with statement"));
 		comp_ctx->curr_func.with_depth++;
 		duk__parse_with_stmt(comp_ctx, res);
+		if (label_id >= 0) {
+			duk__patch_jump_here(comp_ctx, pc_at_entry + 1);  /* break jump */
+		}
 		comp_ctx->curr_func.with_depth--;
 		stmt_flags = 0;
 		break;
@@ -48871,8 +65845,13 @@ static void duk__parse_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_boo
 		break;
 	}
 	case DUK_TOK_DEBUGGER: {
-		DUK_DDD(DUK_DDDPRINT("debugger statement: ignored"));
 		duk__advance(comp_ctx);
+#if defined(DUK_USE_DEBUGGER_SUPPORT)
+		DUK_DDD(DUK_DDDPRINT("debugger statement: debugging enabled, emit debugger opcode"));
+		duk__emit_extraop_only(comp_ctx, DUK_EXTRAOP_DEBUGGER);
+#else
+		DUK_DDD(DUK_DDDPRINT("debugger statement: ignored"));
+#endif
 		stmt_flags = DUK__HAS_TERM;
 		break;
 	}
@@ -48945,7 +65924,7 @@ static void duk__parse_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_boo
 			               h_lab,
 			               pc_at_entry /*pc_label*/,
 			               label_id);
-	
+
 			/* a statement following a label cannot be a source element
 			 * (a function declaration).
 			 */
@@ -48962,7 +65941,6 @@ static void duk__parse_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_boo
 		    comp_ctx->prev_token.t == DUK_TOK_STRING) {
 			/*
 			 *  Detected a directive
-
 			 */
 			duk_hstring *h_dir;
 
@@ -48973,6 +65951,8 @@ static void duk__parse_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_boo
 			h_dir = comp_ctx->prev_token.str1;
 			DUK_ASSERT(h_dir != NULL);
 
+			DUK_DDD(DUK_DDDPRINT("potential directive: %!O", h_dir));
+
 			stmt_flags |= DUK__STILL_PROLOGUE;
 
 			/* Note: escaped characters differentiate directives */
@@ -48981,18 +65961,20 @@ static void duk__parse_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_boo
 				DUK_DDD(DUK_DDDPRINT("directive contains escapes: valid directive "
 				                     "but we ignore such directives"));
 			} else {
-				/* XXX: how to compare 'use strict' most compactly?
-				 * We don't necessarily want to add it to the built-ins
-				 * because it's not needed at run time.
+				/*
 				 * The length comparisons are present to handle
 				 * strings like "use strict\u0000foo" as required.
 				 */
 
 				if (DUK_HSTRING_GET_BYTELEN(h_dir) == 10 &&
 				    DUK_STRNCMP((const char *) DUK_HSTRING_GET_DATA(h_dir), "use strict", 10) == 0) {
+#if defined(DUK_USE_STRICT_DECL)
 					DUK_DDD(DUK_DDDPRINT("use strict directive detected: strict flag %ld -> %ld",
 					                     (long) comp_ctx->curr_func.is_strict, (long) 1));
 					comp_ctx->curr_func.is_strict = 1;
+#else
+					DUK_DDD(DUK_DDDPRINT("use strict detected but strict declarations disabled, ignoring"));
+#endif
 				} else if (DUK_HSTRING_GET_BYTELEN(h_dir) == 14 &&
 				           DUK_STRNCMP((const char *) DUK_HSTRING_GET_DATA(h_dir), "use duk notail", 14) == 0) {
 					DUK_DDD(DUK_DDDPRINT("use duk notail directive detected: notail flag %ld -> %ld",
@@ -49085,7 +66067,9 @@ static void duk__parse_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_boo
 	 */
 
 	if (label_id >= 0) {
-		duk__emit_abc(comp_ctx, DUK_OP_ENDLABEL, label_id);
+		duk__emit_extraop_bc(comp_ctx,
+		                     DUK_EXTRAOP_ENDLABEL,
+		                     (duk_regconst_t) label_id);
 	}
 
 	DUK__SETTEMP(comp_ctx, temp_at_entry);
@@ -49112,7 +66096,7 @@ static void duk__parse_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_boo
  *  (EOF or closing brace).
  */
 
-static void duk__parse_stmts(duk_compiler_ctx *comp_ctx, duk_bool_t allow_source_elem, duk_bool_t expect_eof) {
+DUK_LOCAL void duk__parse_stmts(duk_compiler_ctx *comp_ctx, duk_bool_t allow_source_elem, duk_bool_t expect_eof) {
 	duk_hthread *thr = comp_ctx->thr;
 	duk_context *ctx = (duk_context *) thr;
 	duk_ivalue res_alloc;
@@ -49187,7 +66171,7 @@ static void duk__parse_stmts(duk_compiler_ctx *comp_ctx, duk_bool_t allow_source
  *
  *  Some bindings in E5 are not configurable (= deletable) and almost all
  *  are mutable (writable).  Exceptions are:
- * 
+ *
  *    - The 'arguments' binding, established only if no shadowing argument
  *      or function declaration exists.  We handle 'arguments' creation
  *      and binding through an explicit slow path environment record.
@@ -49196,11 +66180,11 @@ static void duk__parse_stmts(duk_compiler_ctx *comp_ctx, duk_bool_t allow_source
  *      handled through an explicit slow path environment record.
  */
 
-/* XXX: add support for variables to not be register bound always, to 
+/* XXX: add support for variables to not be register bound always, to
  * handle cases with a very large number of variables?
  */
 
-static void duk__init_varmap_and_prologue_for_pass2(duk_compiler_ctx *comp_ctx, duk_reg_t *out_stmt_value_reg) {
+DUK_LOCAL void duk__init_varmap_and_prologue_for_pass2(duk_compiler_ctx *comp_ctx, duk_reg_t *out_stmt_value_reg) {
 	duk_hthread *thr = comp_ctx->thr;
 	duk_context *ctx = (duk_context *) thr;
 	duk_hstring *h_name;
@@ -49377,7 +66361,7 @@ static void duk__init_varmap_and_prologue_for_pass2(duk_compiler_ctx *comp_ctx,
 			}
 
 			duk__emit_a_b_c(comp_ctx,
-			                DUK_OP_DECLVAR,
+			                DUK_OP_DECLVAR | DUK__EMIT_FLAG_NO_SHUFFLE_A,
 			                (duk_regconst_t) declvar_flags /*flags*/,
 			                rc_name /*name*/,
 			                (duk_regconst_t) reg_temp /*value*/);
@@ -49462,7 +66446,7 @@ static void duk__init_varmap_and_prologue_for_pass2(duk_compiler_ctx *comp_ctx,
 				}
 
 				duk__emit_a_b_c(comp_ctx,
-				                DUK_OP_DECLVAR,
+				                DUK_OP_DECLVAR | DUK__EMIT_FLAG_NO_SHUFFLE_A,
 				                (duk_regconst_t) declvar_flags /*flags*/,
 				                rc_name /*name*/,
 				                (duk_regconst_t) 0 /*value*/);
@@ -49528,15 +66512,22 @@ static void duk__init_varmap_and_prologue_for_pass2(duk_compiler_ctx *comp_ctx,
  *  token (EOF or closing brace).
  */
 
-static void duk__parse_func_body(duk_compiler_ctx *comp_ctx, duk_bool_t expect_eof, duk_bool_t implicit_return_value) {
-	duk_compiler_func *func = &comp_ctx->curr_func;
-	duk_hthread *thr = comp_ctx->thr;
-	duk_context *ctx = (duk_context *) thr;
+DUK_LOCAL void duk__parse_func_body(duk_compiler_ctx *comp_ctx, duk_bool_t expect_eof, duk_bool_t implicit_return_value, duk_small_int_t expect_token) {
+	duk_compiler_func *func;
+	duk_hthread *thr;
+	duk_context *ctx;
 	duk_reg_t reg_stmt_value = -1;
 	duk_lexer_point lex_pt;
 	duk_reg_t temp_first;
+	duk_small_int_t compile_round = 1;
 
 	DUK_ASSERT(comp_ctx != NULL);
+
+	thr = comp_ctx->thr;
+	ctx = (duk_context *) thr;
+	DUK_ASSERT(thr != NULL);
+
+	func = &comp_ctx->curr_func;
 	DUK_ASSERT(func != NULL);
 
 	DUK__RECURSION_INCREASE(comp_ctx, thr);
@@ -49577,7 +66568,10 @@ static void duk__parse_func_body(duk_compiler_ctx *comp_ctx, duk_bool_t expect_e
 	}
 
 	/*
-	 *  First pass parsing.
+	 *  First pass.
+	 *
+	 *  Gather variable/function declarations needed for second pass.
+	 *  Code generated is dummy and discarded.
 	 */
 
 	func->in_directive_prologue = 1;
@@ -49586,12 +66580,26 @@ static void duk__parse_func_body(duk_compiler_ctx *comp_ctx, duk_bool_t expect_e
 	func->id_access_arguments = 0;
 	func->id_access_slow = 0;
 	func->reg_stmt_value = reg_stmt_value;
+#if defined(DUK_USE_DEBUGGER_SUPPORT)
+	func->min_line = DUK_INT_MAX;
+	func->max_line = 0;
+#endif
 
-	/* Need to set curr_token.t because lexing regexp mode depends on current
-	 * token type.  Zero value causes "allow regexp" mode.
-	 */
-	comp_ctx->curr_token.t = 0;
-	duk__advance(comp_ctx);  /* duk__parse_stmts() expects curr_tok to be set; parse in "allow regexp literal" mode with current strictness */
+	/* duk__parse_stmts() expects curr_tok to be set; parse in "allow regexp literal" mode with current strictness */
+	if (expect_token >= 0) {
+		/* Eating a left curly; regexp mode is allowed by left curly
+		 * based on duk__token_lbp[] automatically.
+		 */
+		DUK_ASSERT(expect_token == DUK_TOK_LCURLY);
+		duk__update_lineinfo_currtoken(comp_ctx);
+		duk__advance_expect(comp_ctx, expect_token);
+	} else {
+		/* Need to set curr_token.t because lexing regexp mode depends on current
+		 * token type.  Zero value causes "allow regexp" mode.
+		 */
+		comp_ctx->curr_token.t = 0;
+		duk__advance(comp_ctx);
+	}
 
 	DUK_DDD(DUK_DDDPRINT("begin 1st pass"));
 	duk__parse_stmts(comp_ctx,
@@ -49600,94 +66608,124 @@ static void duk__parse_func_body(duk_compiler_ctx *comp_ctx, duk_bool_t expect_e
 	DUK_DDD(DUK_DDDPRINT("end 1st pass"));
 
 	/*
-	 *  Rewind lexer.
+	 *  Second (and possibly third) pass.
 	 *
-	 *  duk__parse_stmts() expects curr_tok to be set; parse in "allow regexp
-	 *  literal" mode with current strictness.
-	 *
-	 *  curr_token line number info should be initialized for pass 2 before
-	 *  generating prologue, to ensure prologue bytecode gets nice line numbers.
+	 *  Generate actual code.  In most cases the need for shuffle
+	 *  registers is detected during pass 1, but in some corner cases
+	 *  we'll only detect it during pass 2 and a third pass is then
+	 *  needed (see GH-115).
 	 */
 
-	DUK_DDD(DUK_DDDPRINT("rewind lexer"));
-	DUK_LEXER_SETPOINT(&comp_ctx->lex, &lex_pt);
-	comp_ctx->curr_token.t = 0;  /* this is needed for regexp mode */
-	duk__advance(comp_ctx);
+	for (;;) {
+		duk_bool_t needs_shuffle_before = comp_ctx->curr_func.needs_shuffle;
+		compile_round++;
 
-	/*
-	 *  Reset function state and perform register allocation, which creates
-	 *  'varmap' for second pass.  Function prologue for variable declarations,
-	 *  binding value initializations etc is emitted as a by-product.
-	 *
-	 *  Strict mode restrictions for duplicate and invalid argument
-	 *  names are checked here now that we know whether the function
-	 *  is actually strict.  See: test-dev-strict-mode-boundary.js.
-	 */
+		/*
+		 *  Rewind lexer.
+		 *
+		 *  duk__parse_stmts() expects curr_tok to be set; parse in "allow regexp
+		 *  literal" mode with current strictness.
+		 *
+		 *  curr_token line number info should be initialized for pass 2 before
+		 *  generating prologue, to ensure prologue bytecode gets nice line numbers.
+		 */
 
-	duk__reset_func_for_pass2(comp_ctx);
-	func->in_directive_prologue = 1;
-	func->in_scanning = 0;
+		DUK_DDD(DUK_DDDPRINT("rewind lexer"));
+		DUK_LEXER_SETPOINT(&comp_ctx->lex, &lex_pt);
+		comp_ctx->curr_token.t = 0;  /* this is needed for regexp mode */
+		comp_ctx->curr_token.start_line = 0;  /* needed for line number tracking (becomes prev_token.start_line) */
+		duk__advance(comp_ctx);
 
-	/* must be able to emit code, alloc consts, etc. */
+		/*
+		 *  Reset function state and perform register allocation, which creates
+		 *  'varmap' for second pass.  Function prologue for variable declarations,
+		 *  binding value initializations etc is emitted as a by-product.
+		 *
+		 *  Strict mode restrictions for duplicate and invalid argument
+		 *  names are checked here now that we know whether the function
+		 *  is actually strict.  See: test-dev-strict-mode-boundary.js.
+		 *
+		 *  Inner functions are compiled during pass 1 and are not reset.
+		 */
 
-	duk__init_varmap_and_prologue_for_pass2(comp_ctx,
-	                                        (implicit_return_value ? &reg_stmt_value : NULL));
-	func->reg_stmt_value = reg_stmt_value;
+		duk__reset_func_for_pass2(comp_ctx);
+		func->in_directive_prologue = 1;
+		func->in_scanning = 0;
 
-	temp_first = DUK__GETTEMP(comp_ctx);
+		/* must be able to emit code, alloc consts, etc. */
 
-	func->temp_first = temp_first;
-	func->temp_next = temp_first;
-	func->stmt_next = 0;
-	func->label_next = 0;
+		duk__init_varmap_and_prologue_for_pass2(comp_ctx,
+		                                        (implicit_return_value ? &reg_stmt_value : NULL));
+		func->reg_stmt_value = reg_stmt_value;
 
-	/* XXX: init or assert catch depth etc -- all values */
-	func->id_access_arguments = 0;
-	func->id_access_slow = 0;
+		temp_first = DUK__GETTEMP(comp_ctx);
 
-	/*
-	 *  Check function name validity now that we know strictness.
-	 *  This only applies to function declarations and expressions,
-	 *  not setter/getter name.
-	 *
-	 *  See: test-dev-strict-mode-boundary.js
-	 */
+		func->temp_first = temp_first;
+		func->temp_next = temp_first;
+		func->stmt_next = 0;
+		func->label_next = 0;
 
-	if (func->is_function && !func->is_setget && func->h_name != NULL) {
-		if (func->is_strict) {
-			if (duk__hstring_is_eval_or_arguments(comp_ctx, func->h_name)) {
-				DUK_DDD(DUK_DDDPRINT("func name is 'eval' or 'arguments' in strict mode"));
-				goto error_funcname;
-			}
-			if (DUK_HSTRING_HAS_STRICT_RESERVED_WORD(func->h_name)) {
-				DUK_DDD(DUK_DDDPRINT("func name is a reserved word in strict mode"));
-				goto error_funcname;
-			}
-		} else {
-			if (DUK_HSTRING_HAS_RESERVED_WORD(func->h_name) &&
-			    !DUK_HSTRING_HAS_STRICT_RESERVED_WORD(func->h_name)) {
-				DUK_DDD(DUK_DDDPRINT("func name is a reserved word in non-strict mode"));
-				goto error_funcname;
+		/* XXX: init or assert catch depth etc -- all values */
+		func->id_access_arguments = 0;
+		func->id_access_slow = 0;
+
+		/*
+		 *  Check function name validity now that we know strictness.
+		 *  This only applies to function declarations and expressions,
+		 *  not setter/getter name.
+		 *
+		 *  See: test-dev-strict-mode-boundary.js
+		 */
+
+		if (func->is_function && !func->is_setget && func->h_name != NULL) {
+			if (func->is_strict) {
+				if (duk__hstring_is_eval_or_arguments(comp_ctx, func->h_name)) {
+					DUK_DDD(DUK_DDDPRINT("func name is 'eval' or 'arguments' in strict mode"));
+					goto error_funcname;
+				}
+				if (DUK_HSTRING_HAS_STRICT_RESERVED_WORD(func->h_name)) {
+					DUK_DDD(DUK_DDDPRINT("func name is a reserved word in strict mode"));
+					goto error_funcname;
+				}
+			} else {
+				if (DUK_HSTRING_HAS_RESERVED_WORD(func->h_name) &&
+				    !DUK_HSTRING_HAS_STRICT_RESERVED_WORD(func->h_name)) {
+					DUK_DDD(DUK_DDDPRINT("func name is a reserved word in non-strict mode"));
+					goto error_funcname;
+				}
 			}
 		}
-	}
 
-	/*
-	 *  Second pass parsing.
-	 */
+		/*
+		 *  Second pass parsing.
+		 */
 
-	if (implicit_return_value) {
-		/* Default implicit return value. */
-		duk__emit_extraop_bc(comp_ctx,
-		                     DUK_EXTRAOP_LDUNDEF,
-		                     0);
-	}
+		if (implicit_return_value) {
+			/* Default implicit return value. */
+			duk__emit_extraop_bc(comp_ctx,
+			                     DUK_EXTRAOP_LDUNDEF,
+			                     0);
+		}
 
-	DUK_DDD(DUK_DDDPRINT("begin 2nd pass"));
-	duk__parse_stmts(comp_ctx,
-	                 1,             /* allow source elements */
-	                 expect_eof);   /* expect EOF instead of } */
-	DUK_DDD(DUK_DDDPRINT("end 2nd pass"));
+		DUK_DDD(DUK_DDDPRINT("begin 2nd pass"));
+		duk__parse_stmts(comp_ctx,
+		                 1,             /* allow source elements */
+		                 expect_eof);   /* expect EOF instead of } */
+		DUK_DDD(DUK_DDDPRINT("end 2nd pass"));
+
+		duk__update_lineinfo_currtoken(comp_ctx);
+
+		if (needs_shuffle_before == comp_ctx->curr_func.needs_shuffle) {
+			/* Shuffle decision not changed. */
+			break;
+		}
+		if (compile_round >= 3) {
+			/* Should never happen but avoid infinite loop just in case. */
+			DUK_D(DUK_DPRINT("more than 3 compile passes needed, should never happen"));
+			DUK_ERROR(thr, DUK_ERR_INTERNAL_ERROR, DUK_STR_INTERNAL_ERROR);
+		}
+		DUK_D(DUK_DPRINT("need additional round to compile function, round now %d", (int) compile_round));
+	}
 
 	/*
 	 *  Emit a final RETURN.
@@ -49704,16 +66742,16 @@ static void duk__parse_func_body(duk_compiler_ctx *comp_ctx, duk_bool_t expect_e
 	 * (directly or via a jump)
 	 */
 
-	DUK_ASSERT(comp_ctx->curr_func.catch_depth == 0);  /* fast returns are always OK here */
+	DUK_ASSERT(comp_ctx->curr_func.catch_depth == 0);
 	if (reg_stmt_value >= 0) {
 		duk__emit_a_b(comp_ctx,
-		              DUK_OP_RETURN,
-		              (duk_regconst_t) (DUK_BC_RETURN_FLAG_HAVE_RETVAL | DUK_BC_RETURN_FLAG_FAST) /*flags*/,
+		              DUK_OP_RETURN | DUK__EMIT_FLAG_NO_SHUFFLE_A,
+		              (duk_regconst_t) DUK_BC_RETURN_FLAG_HAVE_RETVAL /*flags*/,
 		              (duk_regconst_t) reg_stmt_value /*reg*/);
 	} else {
 		duk__emit_a_b(comp_ctx,
-		              DUK_OP_RETURN,
-		              (duk_regconst_t) DUK_BC_RETURN_FLAG_FAST /*flags*/,
+		              DUK_OP_RETURN | DUK__EMIT_FLAG_NO_SHUFFLE_A,
+		              (duk_regconst_t) 0 /*flags*/,
 		              (duk_regconst_t) 0 /*reg(ignored)*/);
 	}
 
@@ -49753,7 +66791,7 @@ static void duk__parse_func_body(duk_compiler_ctx *comp_ctx, duk_bool_t expect_e
  */
 
 /* Parse formals. */
-static void duk__parse_func_formals(duk_compiler_ctx *comp_ctx) {
+DUK_LOCAL void duk__parse_func_formals(duk_compiler_ctx *comp_ctx) {
 	duk_hthread *thr = comp_ctx->thr;
 	duk_context *ctx = (duk_context *) thr;
 	duk_bool_t first = 1;
@@ -49801,7 +66839,7 @@ static void duk__parse_func_formals(duk_compiler_ctx *comp_ctx) {
  * correctly set up.  Assumes that curr_token is just after 'function' (or
  * 'set'/'get' etc).
  */
-static void duk__parse_func_like_raw(duk_compiler_ctx *comp_ctx, duk_bool_t is_decl, duk_bool_t is_setget) {
+DUK_LOCAL void duk__parse_func_like_raw(duk_compiler_ctx *comp_ctx, duk_bool_t is_decl, duk_bool_t is_setget) {
 	duk_hthread *thr = comp_ctx->thr;
 	duk_context *ctx = (duk_context *) thr;
 
@@ -49812,6 +66850,8 @@ static void duk__parse_func_like_raw(duk_compiler_ctx *comp_ctx, duk_bool_t is_d
 	DUK_ASSERT(comp_ctx->curr_func.is_setget == is_setget);
 	DUK_ASSERT(comp_ctx->curr_func.is_decl == is_decl);
 
+	duk__update_lineinfo_currtoken(comp_ctx);
+
 	/*
 	 *  Function name (if any)
 	 *
@@ -49882,14 +66922,15 @@ static void duk__parse_func_like_raw(duk_compiler_ctx *comp_ctx, duk_bool_t is_d
 
 	duk__parse_func_body(comp_ctx,
 	                     0,   /* expect_eof */
-	                     0);  /* implicit_return_value */
+	                     0,   /* implicit_return_value */
+	                     DUK_TOK_LCURLY);  /* expect_token */
 
 	/*
 	 *  Convert duk_compiler_func to a function template and add it
 	 *  to the parent function table.
 	 */
 
-	duk__convert_to_func_template(comp_ctx);  /* -> [ ... func ] */
+	duk__convert_to_func_template(comp_ctx, is_setget /*force_no_namebind*/);  /* -> [ ... func ] */
 }
 
 /* Parse an inner function, adding the function template to the current function's
@@ -49906,7 +66947,7 @@ static void duk__parse_func_like_raw(duk_compiler_ctx *comp_ctx, duk_bool_t is_d
  * need that information at the moment, but it would allow some optimizations if it
  * were used.
  */
-static duk_int_t duk__parse_func_like_fnum(duk_compiler_ctx *comp_ctx, duk_bool_t is_decl, duk_bool_t is_setget) {
+DUK_LOCAL duk_int_t duk__parse_func_like_fnum(duk_compiler_ctx *comp_ctx, duk_bool_t is_decl, duk_bool_t is_setget) {
 	duk_hthread *thr = comp_ctx->thr;
 	duk_context *ctx = (duk_context *) thr;
 	duk_compiler_func old_func;
@@ -49933,6 +66974,7 @@ static duk_int_t duk__parse_func_like_fnum(duk_compiler_ctx *comp_ctx, duk_bool_
 
 		DUK_LEXER_SETPOINT(&comp_ctx->lex, &lex_pt);
 		comp_ctx->curr_token.t = 0;  /* this is needed for regexp mode */
+		comp_ctx->curr_token.start_line = 0;  /* needed for line number tracking (becomes prev_token.start_line) */
 		duk__advance(comp_ctx);
 		duk__advance_expect(comp_ctx, DUK_TOK_RCURLY);
 
@@ -49982,7 +67024,7 @@ static duk_int_t duk__parse_func_like_fnum(duk_compiler_ctx *comp_ctx, duk_bool_
 	DUK_ASSERT(duk_get_length(ctx, old_func.funcs_idx) == (duk_size_t) (old_func.fnum_next * 3));
 	fnum = old_func.fnum_next++;
 
-	if (fnum >= DUK__MAX_FUNCS) {
+	if (fnum > DUK__MAX_FUNCS) {
 		DUK_ERROR(comp_ctx->thr, DUK_ERR_INTERNAL_ERROR, DUK_STR_FUNC_LIMIT);
 	}
 
@@ -49996,7 +67038,7 @@ static duk_int_t duk__parse_func_like_fnum(duk_compiler_ctx *comp_ctx, duk_bool_
 	/*
 	 *  Cleanup: restore original function, restore valstack state.
 	 */
-	
+
 	DUK_MEMCPY((void *) &comp_ctx->curr_func, (void *) &old_func, sizeof(duk_compiler_func));
 	duk_set_top(ctx, entry_top);
 
@@ -50019,7 +67061,7 @@ static duk_int_t duk__parse_func_like_fnum(duk_compiler_ctx *comp_ctx, duk_bool_
 
 /* XXX: source code property */
 
-static duk_ret_t duk__js_compile_raw(duk_context *ctx) {
+DUK_LOCAL duk_ret_t duk__js_compile_raw(duk_context *ctx) {
 	duk_hthread *thr = (duk_hthread *) ctx;
 	duk_hstring *h_filename;
 	duk__compiler_stkstate *comp_stk;
@@ -50082,7 +67124,7 @@ static duk_ret_t duk__js_compile_raw(duk_context *ctx) {
 	comp_ctx->tok12_idx = entry_top + 2;
 	comp_ctx->tok21_idx = entry_top + 3;
 	comp_ctx->tok22_idx = entry_top + 4;
-	comp_ctx->recursion_limit = DUK_COMPILER_RECURSION_LIMIT;
+	comp_ctx->recursion_limit = DUK_USE_COMPILER_RECLIMIT;
 
 	/* comp_ctx->lex has been pre-initialized by caller: it has been
 	 * zeroed and input/input_length has been set.
@@ -50094,12 +67136,13 @@ static duk_ret_t duk__js_compile_raw(duk_context *ctx) {
 	comp_ctx->lex.buf_idx = entry_top + 0;
 	comp_ctx->lex.buf = (duk_hbuffer_dynamic *) duk_get_hbuffer(ctx, entry_top + 0);
 	DUK_ASSERT(comp_ctx->lex.buf != NULL);
-	DUK_ASSERT(DUK_HBUFFER_HAS_DYNAMIC(comp_ctx->lex.buf));
+	DUK_ASSERT(DUK_HBUFFER_HAS_DYNAMIC(comp_ctx->lex.buf) && !DUK_HBUFFER_HAS_EXTERNAL(comp_ctx->lex.buf));
 	comp_ctx->lex.token_limit = DUK_COMPILER_TOKEN_LIMIT;
 
 	lex_pt->offset = 0;
 	lex_pt->line = 1;
 	DUK_LEXER_SETPOINT(&comp_ctx->lex, lex_pt);    /* fills window */
+	comp_ctx->curr_token.start_line = 0;  /* needed for line number tracking (becomes prev_token.start_line) */
 
 	/*
 	 *  Initialize function state for a zero-argument function
@@ -50146,14 +67189,15 @@ static duk_ret_t duk__js_compile_raw(duk_context *ctx) {
 
 		duk__parse_func_body(comp_ctx,
 		                     1,             /* expect_eof */
-		                     1);            /* implicit_return_value */
+		                     1,             /* implicit_return_value */
+		                     -1);           /* expect_token */
 	}
 
 	/*
 	 *  Convert duk_compiler_func to a function template
 	 */
 
-	duk__convert_to_func_template(comp_ctx);
+	duk__convert_to_func_template(comp_ctx, 0 /*force_no_namebind*/);
 
 	/*
 	 *  Wrapping duk_safe_call() will mangle the stack, just return stack top
@@ -50164,9 +67208,11 @@ static duk_ret_t duk__js_compile_raw(duk_context *ctx) {
 	return 1;
 }
 
-void duk_js_compile(duk_hthread *thr, const duk_uint8_t *src_buffer, duk_size_t src_length, duk_small_uint_t flags) {
+DUK_INTERNAL void duk_js_compile(duk_hthread *thr, const duk_uint8_t *src_buffer, duk_size_t src_length, duk_small_uint_t flags) {
 	duk_context *ctx = (duk_context *) thr;
 	duk__compiler_stkstate comp_stk;
+	duk_compiler_ctx *prev_ctx;
+	duk_ret_t safe_rc;
 
 	/* XXX: this illustrates that a C catchpoint implemented using duk_safe_call()
 	 * is a bit heavy at the moment.  The wrapper compiles to ~180 bytes on x64.
@@ -50187,25 +67233,12 @@ void duk_js_compile(duk_hthread *thr, const duk_uint8_t *src_buffer, duk_size_t
 
 	/* [ ... filename &comp_stk ] */
 
-	if (duk_safe_call(ctx, duk__js_compile_raw, 2 /*nargs*/, 1 /*nret*/) != DUK_EXEC_SUCCESS) {
-		/* This now adds a line number to -any- error thrown during compilation.
-		 * Usually compilation errors are SyntaxErrors but they could also be
-		 * out-of-memory errors and the like.
-		 */
+	prev_ctx = thr->compile_ctx;
+	thr->compile_ctx = &comp_stk.comp_ctx_alloc;  /* for duk_error_augment.c */
+	safe_rc = duk_safe_call(ctx, duk__js_compile_raw, 2 /*nargs*/, 1 /*nret*/);
+	thr->compile_ctx = prev_ctx;  /* must restore reliably before returning */
 
-		DUK_DDD(DUK_DDDPRINT("compile error, before adding line info: %!T",
-		                     (duk_tval *) duk_get_tval(ctx, -1)));
-		if (duk_is_object(ctx, -1)) {
-			if (duk_get_prop_stridx(ctx, -1, DUK_STRIDX_MESSAGE)) {
-				duk_push_sprintf(ctx, " (line %ld)", (long) comp_stk.comp_ctx_alloc.curr_token.start_line);
-				duk_concat(ctx, 2);
-				duk_put_prop_stridx(ctx, -2, DUK_STRIDX_MESSAGE);
-			} else {
-				duk_pop(ctx);
-			}
-		}
-		DUK_DDD(DUK_DDDPRINT("compile error, after adding line info: %!T",
-		                     (duk_tval *) duk_get_tval(ctx, -1)));
+	if (safe_rc != DUK_EXEC_SUCCESS) {
 		duk_throw(ctx);
 	}
 
@@ -50219,60 +67252,27 @@ void duk_js_compile(duk_hthread *thr, const duk_uint8_t *src_buffer, duk_size_t
 /* include removed: duk_internal.h */
 
 /*
- *  Local forward declarations
+ *  Local declarations.
  */
 
-static void duk__reconfig_valstack(duk_hthread *thr, duk_size_t act_idx, duk_small_uint_t retval_count);
-
-/*
- *  Helper for finding the final non-bound function in a "bound function" chain.
- */
-
-/* XXX: overlap with other helpers, rework */
-static duk_hobject *duk__find_nonbound_function(duk_hthread *thr, duk_hobject *func) {
-	duk_context *ctx = (duk_context *) thr;
-	duk_uint_t sanity;
-
-	DUK_ASSERT(thr != NULL);
-	DUK_ASSERT(func != NULL);
-	DUK_ASSERT(DUK_HOBJECT_HAS_BOUND(func));
-
-	sanity = DUK_HOBJECT_BOUND_CHAIN_SANITY;
-	do {	
-		if (!DUK_HOBJECT_HAS_BOUND(func)) {
-			break;
-		}
-
-		duk_push_hobject(ctx, func);
-		duk_get_prop_stridx(ctx, -1, DUK_STRIDX_INT_TARGET);
-		func = duk_require_hobject(ctx, -1);
-		duk_pop_2(ctx);
-	} while (--sanity > 0);
-
-	if (sanity == 0) {
-		DUK_ERROR(thr, DUK_ERR_INTERNAL_ERROR, DUK_STR_BOUND_CHAIN_LIMIT);
-	}
-
-	DUK_ASSERT(!DUK_HOBJECT_HAS_BOUND(func));
-	DUK_ASSERT(DUK_HOBJECT_HAS_COMPILEDFUNCTION(func) || DUK_HOBJECT_HAS_NATIVEFUNCTION(func));
-
-	return func;
-}
+DUK_LOCAL_DECL void duk__js_execute_bytecode_inner(duk_hthread *entry_thread, duk_size_t entry_callstack_top);
 
 /*
  *  Arithmetic, binary, and logical helpers.
  *
  *  Note: there is no opcode for logical AND or logical OR; this is on
  *  purpose, because the evalution order semantics for them make such
- *  opcodes pretty pointless (short circuiting means they are most
- *  comfortably implemented as jumps).  However, a logical NOT opcode
+ *  opcodes pretty pointless: short circuiting means they are most
+ *  comfortably implemented as jumps.  However, a logical NOT opcode
  *  is useful.
  *
  *  Note: careful with duk_tval pointers here: they are potentially
- *  invalidated by any DECREF and almost any API call.
+ *  invalidated by any DECREF and almost any API call.  It's still
+ *  preferable to work without making a copy but that's not always
+ *  possible.
  */
 
-static duk_double_t duk__compute_mod(duk_double_t d1, duk_double_t d2) {
+DUK_LOCAL duk_double_t duk__compute_mod(duk_double_t d1, duk_double_t d2) {
 	/*
 	 *  Ecmascript modulus ('%') does not match IEEE 754 "remainder"
 	 *  operation (implemented by remainder() in C99) but does seem
@@ -50284,7 +67284,7 @@ static duk_double_t duk__compute_mod(duk_double_t d1, duk_double_t d2) {
 	return (duk_double_t) DUK_FMOD((double) d1, (double) d2);
 }
 
-static void duk__vm_arith_add(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_y, duk_small_uint_fast_t idx_z) {
+DUK_LOCAL void duk__vm_arith_add(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_y, duk_small_uint_fast_t idx_z) {
 	/*
 	 *  Addition operator is different from other arithmetic
 	 *  operations in that it also provides string concatenation.
@@ -50315,8 +67315,32 @@ static void duk__vm_arith_add(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_y,
 	 *  Fast paths
 	 */
 
+#if defined(DUK_USE_FASTINT)
+	if (DUK_TVAL_IS_FASTINT(tv_x) && DUK_TVAL_IS_FASTINT(tv_y)) {
+		duk_int64_t v1, v2, v3;
+		duk_int32_t v3_hi;
+		duk_tval *tv_z;
+
+		/* Input values are signed 48-bit so we can detect overflow
+		 * reliably from high bits or just a comparison.
+		 */
+
+		v1 = DUK_TVAL_GET_FASTINT(tv_x);
+		v2 = DUK_TVAL_GET_FASTINT(tv_y);
+		v3 = v1 + v2;
+		v3_hi = (duk_int32_t) (v3 >> 32);
+		if (DUK_LIKELY(v3_hi >= -0x8000LL && v3_hi <= 0x7fffLL)) {
+			tv_z = thr->valstack_bottom + idx_z;
+			DUK_TVAL_SET_FASTINT_UPDREF(thr, tv_z, v3);  /* side effects */
+			return;
+		} else {
+			/* overflow, fall through */
+			;
+		}
+	}
+#endif  /* DUK_USE_FASTINT */
+
 	if (DUK_TVAL_IS_NUMBER(tv_x) && DUK_TVAL_IS_NUMBER(tv_y)) {
-		duk_tval tv_tmp;
 		duk_tval *tv_z;
 
 		du.d = DUK_TVAL_GET_NUMBER(tv_x) + DUK_TVAL_GET_NUMBER(tv_y);
@@ -50324,10 +67348,7 @@ static void duk__vm_arith_add(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_y,
 		DUK_ASSERT(DUK_DBLUNION_IS_NORMALIZED(&du));
 
 		tv_z = thr->valstack_bottom + idx_z;
-		DUK_TVAL_SET_TVAL(&tv_tmp, tv_z);
-		DUK_TVAL_SET_NUMBER(tv_z, du.d);
-		DUK_ASSERT(!DUK_TVAL_IS_HEAP_ALLOCATED(tv_z));  /* no need to incref */
-		DUK_TVAL_DECREF(thr, &tv_tmp);   /* side effects */
+		DUK_TVAL_SET_NUMBER_UPDREF(thr, tv_z, du.d);  /* side effects */
 		return;
 	}
 
@@ -50370,7 +67391,7 @@ static void duk__vm_arith_add(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_y,
 	}
 }
 
-static void duk__vm_arith_binary_op(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_y, duk_idx_t idx_z, duk_small_uint_fast_t opcode) {
+DUK_LOCAL void duk__vm_arith_binary_op(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_y, duk_idx_t idx_z, duk_small_uint_fast_t opcode) {
 	/*
 	 *  Arithmetic operations other than '+' have number-only semantics
 	 *  and are implemented here.  The separate switch-case here means a
@@ -50380,7 +67401,6 @@ static void duk__vm_arith_binary_op(duk_hthread *thr, duk_tval *tv_x, duk_tval *
 	 */
 
 	duk_context *ctx = (duk_context *) thr;
-	duk_tval tv_tmp;
 	duk_tval *tv_z;
 	duk_double_t d1, d2;
 	duk_double_union du;
@@ -50392,6 +67412,79 @@ static void duk__vm_arith_binary_op(duk_hthread *thr, duk_tval *tv_x, duk_tval *
 	DUK_ASSERT_DISABLE(idx_z >= 0);  /* unsigned */
 	DUK_ASSERT((duk_uint_t) idx_z < (duk_uint_t) duk_get_top(ctx));
 
+#if defined(DUK_USE_FASTINT)
+	if (DUK_TVAL_IS_FASTINT(tv_x) && DUK_TVAL_IS_FASTINT(tv_y)) {
+		duk_int64_t v1, v2, v3;
+		duk_int32_t v3_hi;
+
+		v1 = DUK_TVAL_GET_FASTINT(tv_x);
+		v2 = DUK_TVAL_GET_FASTINT(tv_y);
+
+		switch (opcode) {
+		case DUK_OP_SUB: {
+			v3 = v1 - v2;
+			break;
+		}
+		case DUK_OP_MUL: {
+			/* Must ensure result is 64-bit (no overflow); a
+			 * simple and sufficient fast path is to allow only
+			 * 32-bit inputs.  Avoid zero inputs to avoid
+			 * negative zero issues (-1 * 0 = -0, for instance).
+			 */
+			if (v1 >= -0x80000000LL && v1 <= 0x7fffffffLL && v1 != 0 &&
+			    v2 >= -0x80000000LL && v2 <= 0x7fffffffLL && v2 != 0) {
+				v3 = v1 * v2;
+			} else {
+				goto skip_fastint;
+			}
+			break;
+		}
+		case DUK_OP_DIV: {
+			/* Don't allow a zero divisor.  Fast path check by
+			 * "verifying" with multiplication.  Also avoid zero
+			 * dividend to avoid negative zero issues (0 / -1 = -0
+			 * for instance).
+			 */
+			if (v1 == 0 || v2 == 0) {
+				goto skip_fastint;
+			}
+			v3 = v1 / v2;
+			if (v3 * v2 != v1) {
+				goto skip_fastint;
+			}
+			break;
+		}
+		case DUK_OP_MOD: {
+			/* Don't allow a zero divisor.  Restrict both v1 and
+			 * v2 to positive values to avoid compiler specific
+			 * behavior.
+			 */
+			if (v1 < 1 || v2 < 1) {
+				goto skip_fastint;
+			}
+			v3 = v1 % v2;
+			DUK_ASSERT(v3 >= 0);
+			DUK_ASSERT(v3 < v2);
+			DUK_ASSERT(v1 - (v1 / v2) * v2 == v3);
+			break;
+		}
+		default: {
+			DUK_UNREACHABLE();
+			goto skip_fastint;
+		}
+		}
+
+		v3_hi = (duk_int32_t) (v3 >> 32);
+		if (DUK_LIKELY(v3_hi >= -0x8000LL && v3_hi <= 0x7fffLL)) {
+			tv_z = thr->valstack_bottom + idx_z;
+			DUK_TVAL_SET_FASTINT_UPDREF(thr, tv_z, v3);  /* side effects */
+			return;
+		}
+		/* fall through if overflow etc */
+	}
+ skip_fastint:
+#endif  /* DUK_USE_FASTINT */
+
 	if (DUK_TVAL_IS_NUMBER(tv_x) && DUK_TVAL_IS_NUMBER(tv_y)) {
 		/* fast path */
 		d1 = DUK_TVAL_GET_NUMBER(tv_x);
@@ -50426,6 +67519,7 @@ static void duk__vm_arith_binary_op(duk_hthread *thr, duk_tval *tv_x, duk_tval *
 		break;
 	}
 	default: {
+		DUK_UNREACHABLE();
 		du.d = DUK_DOUBLE_NAN;  /* should not happen */
 		break;
 	}
@@ -50434,15 +67528,12 @@ static void duk__vm_arith_binary_op(duk_hthread *thr, duk_tval *tv_x, duk_tval *
 	/* important to use normalized NaN with 8-byte tagged types */
 	DUK_DBLUNION_NORMALIZE_NAN_CHECK(&du);
 	DUK_ASSERT(DUK_DBLUNION_IS_NORMALIZED(&du));
-	
+
 	tv_z = thr->valstack_bottom + idx_z;
-	DUK_TVAL_SET_TVAL(&tv_tmp, tv_z);
-	DUK_TVAL_SET_NUMBER(tv_z, du.d);
-	DUK_ASSERT(!DUK_TVAL_IS_HEAP_ALLOCATED(tv_z));  /* no need to incref */
-	DUK_TVAL_DECREF(thr, &tv_tmp);   /* side effects */
+	DUK_TVAL_SET_NUMBER_UPDREF(thr, tv_z, du.d);  /* side effects */
 }
 
-static void duk__vm_bitwise_binary_op(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_y, duk_small_uint_fast_t idx_z, duk_small_uint_fast_t opcode) {
+DUK_LOCAL void duk__vm_bitwise_binary_op(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_y, duk_small_uint_fast_t idx_z, duk_small_uint_fast_t opcode) {
 	/*
 	 *  Binary bitwise operations use different coercions (ToInt32, ToUint32)
 	 *  depending on the operation.  We coerce the arguments first using
@@ -50454,10 +67545,14 @@ static void duk__vm_bitwise_binary_op(duk_hthread *thr, duk_tval *tv_x, duk_tval
 	 */
 
 	duk_context *ctx = (duk_context *) thr;
-	duk_tval tv_tmp;
 	duk_tval *tv_z;
-	duk_int32_t i1, i2;
-	duk_double_t val;
+	duk_int32_t i1, i2, i3;
+	duk_uint32_t u1, u2, u3;
+#if defined(DUK_USE_FASTINT)
+	duk_int64_t fi3;
+#else
+	duk_double_t d3;
+#endif
 
 	DUK_ASSERT(thr != NULL);
 	DUK_ASSERT(ctx != NULL);
@@ -50466,23 +67561,32 @@ static void duk__vm_bitwise_binary_op(duk_hthread *thr, duk_tval *tv_x, duk_tval
 	DUK_ASSERT_DISABLE(idx_z >= 0);  /* unsigned */
 	DUK_ASSERT((duk_uint_t) idx_z < (duk_uint_t) duk_get_top(ctx));
 
-	duk_push_tval(ctx, tv_x);
-	duk_push_tval(ctx, tv_y);
-	i1 = duk_to_int32(ctx, -2);
-	i2 = duk_to_int32(ctx, -1);
-	duk_pop_2(ctx);
+#if defined(DUK_USE_FASTINT)
+	if (DUK_TVAL_IS_FASTINT(tv_x) && DUK_TVAL_IS_FASTINT(tv_y)) {
+		i1 = (duk_int32_t) DUK_TVAL_GET_FASTINT_I32(tv_x);
+		i2 = (duk_int32_t) DUK_TVAL_GET_FASTINT_I32(tv_y);
+	}
+	else
+#endif  /* DUK_USE_FASTINT */
+	{
+		duk_push_tval(ctx, tv_x);
+		duk_push_tval(ctx, tv_y);
+		i1 = duk_to_int32(ctx, -2);
+		i2 = duk_to_int32(ctx, -1);
+		duk_pop_2(ctx);
+	}
 
 	switch (opcode) {
 	case DUK_OP_BAND: {
-		val = (duk_double_t) (i1 & i2);
+		i3 = i1 & i2;
 		break;
 	}
 	case DUK_OP_BOR: {
-		val = (duk_double_t) (i1 | i2);
+		i3 = i1 | i2;
 		break;
 	}
 	case DUK_OP_BXOR: {
-		val = (duk_double_t) (i1 ^ i2);
+		i3 = i1 ^ i2;
 		break;
 	}
 	case DUK_OP_BASL: {
@@ -50491,53 +67595,65 @@ static void duk__vm_bitwise_binary_op(duk_hthread *thr, duk_tval *tv_x, duk_tval
 		 * must be masked.
 		 */
 
-		duk_uint32_t u2;
-		duk_int32_t i3;
-
 		u2 = ((duk_uint32_t) i2) & 0xffffffffUL;
-		i3 = i1 << (u2 & 0x1f);                     /* E5 Section 11.7.1, steps 7 and 8 */
+		i3 = i1 << (u2 & 0x1f);                      /* E5 Section 11.7.1, steps 7 and 8 */
 		i3 = i3 & ((duk_int32_t) 0xffffffffUL);      /* Note: left shift, should mask */
-		val = (duk_double_t) i3;
 		break;
 	}
 	case DUK_OP_BASR: {
 		/* signed shift */
 
-		duk_uint32_t u2;
-
 		u2 = ((duk_uint32_t) i2) & 0xffffffffUL;
-		val = (duk_double_t) (i1 >> (u2 & 0x1f));     /* E5 Section 11.7.2, steps 7 and 8 */
+		i3 = i1 >> (u2 & 0x1f);                      /* E5 Section 11.7.2, steps 7 and 8 */
 		break;
 	}
 	case DUK_OP_BLSR: {
 		/* unsigned shift */
 
-		duk_uint32_t u1;
-		duk_uint32_t u2;
-
 		u1 = ((duk_uint32_t) i1) & 0xffffffffUL;
 		u2 = ((duk_uint32_t) i2) & 0xffffffffUL;
 
-		val = (duk_double_t) (u1 >> (u2 & 0x1f));     /* E5 Section 11.7.2, steps 7 and 8 */
-		break;
+		/* special result value handling */
+		u3 = u1 >> (u2 & 0x1f);     /* E5 Section 11.7.2, steps 7 and 8 */
+#if defined(DUK_USE_FASTINT)
+		fi3 = (duk_int64_t) u3;
+		goto fastint_result_set;
+#else
+		d3 = (duk_double_t) u3;
+		goto result_set;
+#endif
 	}
 	default: {
-		val = (duk_double_t) 0;  /* should not happen */
+		DUK_UNREACHABLE();
+		i3 = 0;  /* should not happen */
 		break;
 	}
 	}
 
-	DUK_ASSERT(!DUK_ISNAN(val));            /* 'val' is never NaN, so no need to normalize */
-	DUK_ASSERT_DOUBLE_IS_NORMALIZED(val);   /* always normalized */
+#if defined(DUK_USE_FASTINT)
+	/* Result is always fastint compatible. */
+	/* XXX: Set 32-bit result (but must then handle signed and
+	 * unsigned results separately).
+	 */
+	fi3 = (duk_int64_t) i3;
+
+ fastint_result_set:
+	tv_z = thr->valstack_bottom + idx_z;
+	DUK_TVAL_SET_FASTINT_UPDREF(thr, tv_z, fi3);  /* side effects */
+#else
+	d3 = (duk_double_t) i3;
+
+ result_set:
+	DUK_ASSERT(!DUK_ISNAN(d3));            /* 'd3' is never NaN, so no need to normalize */
+	DUK_ASSERT_DOUBLE_IS_NORMALIZED(d3);   /* always normalized */
 
 	tv_z = thr->valstack_bottom + idx_z;
-	DUK_TVAL_SET_TVAL(&tv_tmp, tv_z);
-	DUK_TVAL_SET_NUMBER(tv_z, val);
-	DUK_ASSERT(!DUK_TVAL_IS_HEAP_ALLOCATED(tv_z));  /* no need to incref */
-	DUK_TVAL_DECREF(thr, &tv_tmp);   /* side effects */
+	DUK_TVAL_SET_NUMBER_UPDREF(thr, tv_z, d3);  /* side effects */
+#endif
 }
 
-static void duk__vm_arith_unary_op(duk_hthread *thr, duk_tval *tv_x, duk_small_uint_fast_t idx_z, duk_small_uint_fast_t opcode) {
+/* In-place unary operation. */
+DUK_LOCAL void duk__vm_arith_unary_op(duk_hthread *thr, duk_tval *tv_x, duk_idx_t idx_x, duk_small_uint_fast_t opcode) {
 	/*
 	 *  Arithmetic operations other than '+' have number-only semantics
 	 *  and are implemented here.  The separate switch-case here means a
@@ -50547,71 +67663,77 @@ static void duk__vm_arith_unary_op(duk_hthread *thr, duk_tval *tv_x, duk_small_u
 	 */
 
 	duk_context *ctx = (duk_context *) thr;
-	duk_tval tv_tmp;
-	duk_tval *tv_z;
 	duk_double_t d1;
 	duk_double_union du;
 
 	DUK_ASSERT(thr != NULL);
 	DUK_ASSERT(ctx != NULL);
-	DUK_ASSERT(tv_x != NULL);  /* may be reg or const */
-	DUK_ASSERT_DISABLE(idx_z >= 0);  /* unsigned */
-	DUK_ASSERT((duk_uint_t) idx_z < (duk_uint_t) duk_get_top(ctx));
+	DUK_ASSERT(opcode == DUK_EXTRAOP_UNM || opcode == DUK_EXTRAOP_UNP);
 
-	if (DUK_TVAL_IS_NUMBER(tv_x)) {
-		/* fast path */
-		d1 = DUK_TVAL_GET_NUMBER(tv_x);
-	} else {
-		duk_push_tval(ctx, tv_x);
-		d1 = duk_to_number(ctx, -1);  /* side effects */
-		DUK_ASSERT(duk_is_number(ctx, -1));
-		DUK_ASSERT_DOUBLE_IS_NORMALIZED(d1);
-		duk_pop(ctx);
+#if defined(DUK_USE_FASTINT)
+	if (DUK_TVAL_IS_FASTINT(tv_x)) {
+		duk_int64_t v1, v2;
+
+		v1 = DUK_TVAL_GET_FASTINT(tv_x);
+		if (opcode == DUK_EXTRAOP_UNM) {
+			/* The smallest fastint is no longer 48-bit when
+			 * negated.  Positive zero becames negative zero
+			 * (cannot be represented) when negated.
+			 */
+			if (DUK_LIKELY(v1 != DUK_FASTINT_MIN && v1 != 0)) {
+				v2 = -v1;
+				DUK_TVAL_SET_FASTINT(tv_x, v2);  /* no refcount changes */
+				return;
+			}
+		} else {
+			/* ToNumber() for a fastint is a no-op. */
+			DUK_ASSERT(opcode == DUK_EXTRAOP_UNP);
+			return;
+		}
+		/* fall through if overflow etc */
 	}
+#endif  /* DUK_USE_FASTINT */
 
-	switch (opcode) {
-	case DUK_EXTRAOP_UNM: {
-		du.d = -d1;
-		break;
+	if (!DUK_TVAL_IS_NUMBER(tv_x)) {
+		duk_to_number(ctx, idx_x);  /* side effects, perform in-place */
+		tv_x = duk_get_tval(ctx, idx_x);
+		DUK_ASSERT(tv_x != NULL);
+		DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv_x));
 	}
-	case DUK_EXTRAOP_UNP: {
+
+	d1 = DUK_TVAL_GET_NUMBER(tv_x);
+	if (opcode == DUK_EXTRAOP_UNM) {
+		du.d = -d1;
+	} else {
+		/* ToNumber() for a double is a no-op. */
+		DUK_ASSERT(opcode == DUK_EXTRAOP_UNP);
 		du.d = d1;
-		break;
-	}
-	case DUK_EXTRAOP_INC: {
-		du.d = d1 + 1.0;
-		break;
-	}
-	case DUK_EXTRAOP_DEC: {
-		du.d = d1 - 1.0;
-		break;
-	}
-	default: {
-		du.d = DUK_DOUBLE_NAN;  /* should not happen */
-		break;
-	}
 	}
+	DUK_DBLUNION_NORMALIZE_NAN_CHECK(&du);  /* mandatory if du.d is a NaN */
 
-	DUK_DBLUNION_NORMALIZE_NAN_CHECK(&du);
 	DUK_ASSERT(DUK_DBLUNION_IS_NORMALIZED(&du));
 
-	tv_z = thr->valstack_bottom + idx_z;
-	DUK_TVAL_SET_TVAL(&tv_tmp, tv_z);
-	DUK_TVAL_SET_NUMBER(tv_z, du.d);
-	DUK_ASSERT(!DUK_TVAL_IS_HEAP_ALLOCATED(tv_z));  /* no need to incref */
-	DUK_TVAL_DECREF(thr, &tv_tmp);   /* side effects */
+#if defined(DUK_USE_FASTINT)
+	/* Unary plus is used to force a fastint check, so must include
+	 * downgrade check.
+	 */
+	DUK_TVAL_SET_NUMBER_CHKFAST(tv_x, du.d);  /* no refcount changes */
+#else
+	DUK_TVAL_SET_NUMBER(tv_x, du.d);  /* no refcount changes */
+#endif
 }
 
-static void duk__vm_bitwise_not(duk_hthread *thr, duk_tval *tv_x, duk_small_uint_fast_t idx_z) {
+DUK_LOCAL void duk__vm_bitwise_not(duk_hthread *thr, duk_tval *tv_x, duk_uint_fast_t idx_z) {
 	/*
 	 *  E5 Section 11.4.8
 	 */
 
 	duk_context *ctx = (duk_context *) thr;
-	duk_tval tv_tmp;
 	duk_tval *tv_z;
 	duk_int32_t i1, i2;
-	duk_double_t val;
+#if !defined(DUK_USE_FASTINT)
+	duk_double_t d2;
+#endif
 
 	DUK_ASSERT(thr != NULL);
 	DUK_ASSERT(ctx != NULL);
@@ -50619,35 +67741,48 @@ static void duk__vm_bitwise_not(duk_hthread *thr, duk_tval *tv_x, duk_small_uint
 	DUK_ASSERT_DISABLE(idx_z >= 0);
 	DUK_ASSERT((duk_uint_t) idx_z < (duk_uint_t) duk_get_top(ctx));
 
-	duk_push_tval(ctx, tv_x);
-	i1 = duk_to_int32(ctx, -1);
-	duk_pop(ctx);
+#if defined(DUK_USE_FASTINT)
+	if (DUK_TVAL_IS_FASTINT(tv_x)) {
+		i1 = (duk_int32_t) DUK_TVAL_GET_FASTINT_I32(tv_x);
+	}
+	else
+#endif  /* DUK_USE_FASTINT */
+	{
+		duk_push_tval(ctx, tv_x);
+		i1 = duk_to_int32(ctx, -1);
+		duk_pop(ctx);
+	}
 
 	i2 = ~i1;
-	val = (duk_double_t) i2;
 
-	DUK_ASSERT(!DUK_ISNAN(val));            /* 'val' is never NaN, so no need to normalize */
-	DUK_ASSERT_DOUBLE_IS_NORMALIZED(val);   /* always normalized */
+#if defined(DUK_USE_FASTINT)
+	/* Result is always fastint compatible. */
+	tv_z = thr->valstack_bottom + idx_z;
+	DUK_TVAL_SET_FASTINT_I32_UPDREF(thr, tv_z, i2);  /* side effects */
+#else
+	d2 = (duk_double_t) i2;
+
+	DUK_ASSERT(!DUK_ISNAN(d2));            /* 'val' is never NaN, so no need to normalize */
+	DUK_ASSERT_DOUBLE_IS_NORMALIZED(d2);   /* always normalized */
 
 	tv_z = thr->valstack_bottom + idx_z;
-	DUK_TVAL_SET_TVAL(&tv_tmp, tv_z);
-	DUK_TVAL_SET_NUMBER(tv_z, val);
-	DUK_ASSERT(!DUK_TVAL_IS_HEAP_ALLOCATED(tv_z));  /* no need to incref */
-	DUK_TVAL_DECREF(thr, &tv_tmp);   /* side effects */
+	DUK_TVAL_SET_NUMBER_UPDREF(thr, tv_z, d2);  /* side effects */
+#endif
 }
 
-static void duk__vm_logical_not(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_z) {
+DUK_LOCAL void duk__vm_logical_not(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_z) {
 	/*
 	 *  E5 Section 11.4.9
 	 */
 
-	duk_tval tv_tmp;
 	duk_bool_t res;
 
 	DUK_ASSERT(thr != NULL);
 	DUK_ASSERT(tv_x != NULL);  /* may be reg or const */
 	DUK_ASSERT(tv_z != NULL);  /* reg */
 
+	DUK_UNREF(thr);  /* w/o refcounts */
+
 	/* ToBoolean() does not require any operations with side effects so
 	 * we can do it efficiently.  For footprint it would be better to use
 	 * duk_js_toboolean() and then push+replace to the result slot.
@@ -50655,127 +67790,145 @@ static void duk__vm_logical_not(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_z
 	res = duk_js_toboolean(tv_x);  /* does not modify tv_x */
 	DUK_ASSERT(res == 0 || res == 1);
 	res ^= 1;
-	DUK_TVAL_SET_TVAL(&tv_tmp, tv_z);
-	DUK_TVAL_SET_BOOLEAN(tv_z, res);  /* no need to incref */
-	DUK_TVAL_DECREF(thr, &tv_tmp);  /* side effects */
+	DUK_TVAL_SET_BOOLEAN_UPDREF(thr, tv_z, res);  /* side effects */
 }
 
 /*
- *  Longjmp handler for the bytecode executor (and a bunch of static
- *  helpers for it).
- *
- *  Any type of longjmp() can be caught here, including intra-function
- *  longjmp()s like 'break', 'continue', (slow) 'return', 'yield', etc.
+ *  Longjmp and other control flow transfer for the bytecode executor.
  *
- *  Error policy: should not ordinarily throw errors.  Errors thrown
- *  will bubble outwards.
+ *  The longjmp handler can handle all longjmp types: error, yield, and
+ *  resume (pseudotypes are never actually thrown).
  *
- *  Returns:
- *    0   restart execution
- *    1   bytecode executor finished
- *    2   rethrow longjmp
+ *  Error policy for longjmp: should not ordinarily throw errors; if errors
+ *  occur (e.g. due to out-of-memory) they bubble outwards rather than being
+ *  handled recursively.
  */
 
-/* XXX: duk_api operations for cross-thread reg manipulation? */
-/* XXX: post-condition: value stack must be correct; for ecmascript functions, clamped to 'nregs' */
-
 #define DUK__LONGJMP_RESTART   0  /* state updated, restart bytecode execution */
-#define DUK__LONGJMP_FINISHED  1  /* exit bytecode executor with return value */
-#define DUK__LONGJMP_RETHROW   2  /* exit bytecode executor by rethrowing an error to caller */
+#define DUK__LONGJMP_RETHROW   1  /* exit bytecode executor by rethrowing an error to caller */
+
+#define DUK__RETHAND_RESTART   0  /* state updated, restart bytecode execution */
+#define DUK__RETHAND_FINISHED  1  /* exit bytecode execution with return value */
 
-/* only called when act_idx points to an Ecmascript function */
-static void duk__reconfig_valstack(duk_hthread *thr, duk_size_t act_idx, duk_small_uint_t retval_count) {
+/* XXX: optimize reconfig valstack operations so that resize, clamp, and setting
+ * top are combined into one pass.
+ */
+
+/* Reconfigure value stack for return to an Ecmascript function at 'act_idx'. */
+DUK_LOCAL void duk__reconfig_valstack_ecma_return(duk_hthread *thr, duk_size_t act_idx) {
+	duk_activation *act;
 	duk_hcompiledfunction *h_func;
+	duk_idx_t clamp_top;
 
 	DUK_ASSERT(thr != NULL);
 	DUK_ASSERT_DISABLE(act_idx >= 0);  /* unsigned */
-	DUK_ASSERT(thr->callstack[act_idx].func != NULL);
-	DUK_ASSERT(DUK_HOBJECT_IS_COMPILEDFUNCTION(thr->callstack[act_idx].func));
+	DUK_ASSERT(DUK_ACT_GET_FUNC(thr->callstack + act_idx) != NULL);
+	DUK_ASSERT(DUK_HOBJECT_IS_COMPILEDFUNCTION(DUK_ACT_GET_FUNC(thr->callstack + act_idx)));
 	DUK_ASSERT_DISABLE(thr->callstack[act_idx].idx_retval >= 0);  /* unsigned */
 
-	thr->valstack_bottom = thr->valstack + thr->callstack[act_idx].idx_bottom;
-
-	/* clamp so that retval is at the top (retval_count == 1) or register just before
-	 * intended retval is at the top (retval_count == 0, happens e.g. with 'finally').
+	/* Clamp so that values at 'clamp_top' and above are wiped and won't
+	 * retain reachable garbage.  Then extend to 'nregs' because we're
+	 * returning to an Ecmascript function.
 	 */
-	duk_set_top((duk_context *) thr, 
-	            (duk_idx_t) (thr->callstack[act_idx].idx_retval -
-	                         thr->callstack[act_idx].idx_bottom +
-	                         retval_count));
 
-	/*
-	 *  When returning to an Ecmascript function, extend the valstack
-	 *  top to 'nregs' always.
-	 */
+	act = thr->callstack + act_idx;
+	h_func = (duk_hcompiledfunction *) DUK_ACT_GET_FUNC(act);
 
-	h_func = (duk_hcompiledfunction *) thr->callstack[act_idx].func;
+	thr->valstack_bottom = thr->valstack + act->idx_bottom;
+	DUK_ASSERT(act->idx_retval >= act->idx_bottom);
+	clamp_top = (duk_idx_t) (act->idx_retval - act->idx_bottom + 1);  /* +1 = one retval */
+	duk_set_top((duk_context *) thr, clamp_top);
+	act = NULL;
 
-	duk_require_valstack_resize((duk_context *) thr,
-	                            (thr->valstack_bottom - thr->valstack) +          /* bottom of current func */
-	                                h_func->nregs +                               /* reg count */
-	                                DUK_VALSTACK_INTERNAL_EXTRA,                  /* + spare */
-	                            1);                                               /* allow_shrink */
+	(void) duk_valstack_resize_raw((duk_context *) thr,
+	                               (thr->valstack_bottom - thr->valstack) +  /* bottom of current func */
+	                                   h_func->nregs +                       /* reg count */
+	                                   DUK_VALSTACK_INTERNAL_EXTRA,          /* + spare */
+	                               DUK_VSRESIZE_FLAG_SHRINK |                /* flags */
+	                               0 /* no compact */ |
+	                               DUK_VSRESIZE_FLAG_THROW);
 
 	duk_set_top((duk_context *) thr, h_func->nregs);
 }
 
-static void duk__handle_catch_or_finally(duk_hthread *thr, duk_size_t cat_idx, duk_bool_t is_finally) {
-	duk_context *ctx = (duk_context *) thr;
-	duk_tval tv_tmp;
-	duk_tval *tv1;
+DUK_LOCAL void duk__reconfig_valstack_ecma_catcher(duk_hthread *thr, duk_size_t act_idx, duk_size_t cat_idx) {
+	duk_activation *act;
+	duk_catcher *cat;
+	duk_hcompiledfunction *h_func;
+	duk_idx_t clamp_top;
+
+	DUK_ASSERT(thr != NULL);
+	DUK_ASSERT_DISABLE(act_idx >= 0);  /* unsigned */
+	DUK_ASSERT(DUK_ACT_GET_FUNC(thr->callstack + act_idx) != NULL);
+	DUK_ASSERT(DUK_HOBJECT_IS_COMPILEDFUNCTION(DUK_ACT_GET_FUNC(thr->callstack + act_idx)));
+	DUK_ASSERT_DISABLE(thr->callstack[act_idx].idx_retval >= 0);  /* unsigned */
 
-	DUK_DDD(DUK_DDDPRINT("handling catch/finally, cat_idx=%ld, is_finally=%ld",
-	                     (long) cat_idx, (long) is_finally));
+	act = thr->callstack + act_idx;
+	cat = thr->catchstack + cat_idx;
+	h_func = (duk_hcompiledfunction *) DUK_ACT_GET_FUNC(act);
 
-	/*
-	 *  Set caught value and longjmp type to catcher regs.
-	 */
+	thr->valstack_bottom = thr->valstack + act->idx_bottom;
+	DUK_ASSERT(cat->idx_base >= act->idx_bottom);
+	clamp_top = (duk_idx_t) (cat->idx_base - act->idx_bottom + 2);  /* +2 = catcher value, catcher lj_type */
+	duk_set_top((duk_context *) thr, clamp_top);
+	act = NULL;
+	cat = NULL;
+
+	(void) duk_valstack_resize_raw((duk_context *) thr,
+	                               (thr->valstack_bottom - thr->valstack) +  /* bottom of current func */
+	                                   h_func->nregs +                       /* reg count */
+	                                   DUK_VALSTACK_INTERNAL_EXTRA,          /* + spare */
+	                               DUK_VSRESIZE_FLAG_SHRINK |                /* flags */
+	                               0 /* no compact */ |
+	                               DUK_VSRESIZE_FLAG_THROW);
+
+	duk_set_top((duk_context *) thr, h_func->nregs);
+}
+
+/* Set catcher regs: idx_base+0 = value, idx_base+1 = lj_type. */
+DUK_LOCAL void duk__set_catcher_regs(duk_hthread *thr, duk_size_t cat_idx, duk_tval *tv_val_unstable, duk_small_uint_t lj_type) {
+	duk_tval *tv1;
 
-	DUK_DDD(DUK_DDDPRINT("writing catch registers: idx_base=%ld -> %!T, idx_base+1=%ld -> %!T",
-	                     (long) thr->catchstack[cat_idx].idx_base,
-	                     (duk_tval *) &thr->heap->lj.value1,
-	                     (long) (thr->catchstack[cat_idx].idx_base + 1),
-	                     (duk_tval *) &thr->heap->lj.value2));
+	DUK_ASSERT(thr != NULL);
+	DUK_ASSERT(tv_val_unstable != NULL);
 
 	tv1 = thr->valstack + thr->catchstack[cat_idx].idx_base;
-	DUK_TVAL_SET_TVAL(&tv_tmp, tv1);
-	DUK_TVAL_SET_TVAL(tv1, &thr->heap->lj.value1);
-	DUK_TVAL_INCREF(thr, tv1);
-	DUK_TVAL_DECREF(thr, &tv_tmp);  /* side effects */
+	DUK_ASSERT(tv1 < thr->valstack_top);
+	DUK_TVAL_SET_TVAL_UPDREF(thr, tv1, tv_val_unstable);  /* side effects */
 
 	tv1 = thr->valstack + thr->catchstack[cat_idx].idx_base + 1;
-	DUK_TVAL_SET_TVAL(&tv_tmp, tv1);
-	DUK_TVAL_SET_NUMBER(tv1, (duk_double_t) thr->heap->lj.type);  /* XXX: set int */
-	DUK_ASSERT(!DUK_TVAL_IS_HEAP_ALLOCATED(tv1));   /* no need to incref */
-	DUK_TVAL_DECREF(thr, &tv_tmp);  /* side effects */
+	DUK_ASSERT(tv1 < thr->valstack_top);
 
-	/*
-	 *  Unwind catchstack and callstack.
-	 *
-	 *  The 'cat_idx' catcher is always kept, even when executing finally.
-	 */
+#if defined(DUK_USE_FASTINT)
+	DUK_TVAL_SET_FASTINT_U32_UPDREF(thr, tv1, (duk_uint32_t) lj_type);  /* side effects */
+#else
+	DUK_TVAL_SET_NUMBER_UPDREF(thr, tv1, (duk_double_t) lj_type);  /* side effects */
+#endif
+}
+
+DUK_LOCAL void duk__handle_catch(duk_hthread *thr, duk_size_t cat_idx, duk_tval *tv_val_unstable, duk_small_uint_t lj_type) {
+	duk_context *ctx;
+	duk_activation *act;
+
+	DUK_ASSERT(thr != NULL);
+	DUK_ASSERT(tv_val_unstable != NULL);
+	ctx = (duk_context *) thr;
+
+	duk__set_catcher_regs(thr, cat_idx, tv_val_unstable, lj_type);
 
 	duk_hthread_catchstack_unwind(thr, cat_idx + 1);
 	duk_hthread_callstack_unwind(thr, thr->catchstack[cat_idx].callstack_index + 1);
 
-	/*
-	 *  Reconfigure valstack to 'nregs' (this is always the case for
-	 *  Ecmascript functions).
-	 */
-
 	DUK_ASSERT(thr->callstack_top >= 1);
-	DUK_ASSERT(thr->callstack[thr->callstack_top - 1].func != NULL);
-	DUK_ASSERT(DUK_HOBJECT_IS_COMPILEDFUNCTION(thr->callstack[thr->callstack_top - 1].func));
+	DUK_ASSERT(DUK_ACT_GET_FUNC(thr->callstack + thr->callstack_top - 1) != NULL);
+	DUK_ASSERT(DUK_HOBJECT_IS_COMPILEDFUNCTION(DUK_ACT_GET_FUNC(thr->callstack + thr->callstack_top - 1)));
 
-	thr->valstack_bottom = thr->valstack + (thr->callstack + thr->callstack_top - 1)->idx_bottom;
-	duk_set_top((duk_context *) thr, ((duk_hcompiledfunction *) (thr->callstack + thr->callstack_top - 1)->func)->nregs);
+	duk__reconfig_valstack_ecma_catcher(thr, thr->callstack_top - 1, cat_idx);
 
-	/*
-	 *  Reset PC: resume execution from catch or finally jump slot.
-	 */
-
-	(thr->callstack + thr->callstack_top - 1)->pc =
-		thr->catchstack[cat_idx].pc_base + (is_finally ? 1 : 0);
+	DUK_ASSERT(thr->callstack_top >= 1);
+	act = thr->callstack + thr->callstack_top - 1;
+	act->curr_pc = thr->catchstack[cat_idx].pc_base + 0;  /* +0 = catch */
+	act = NULL;
 
 	/*
 	 *  If entering a 'catch' block which requires an automatic
@@ -50787,8 +67940,7 @@ static void duk__handle_catch_or_finally(duk_hthread *thr, duk_size_t cat_idx, d
 	 *  which implies the binding is not deletable.
 	 */
 
-	if (!is_finally && DUK_CAT_HAS_CATCH_BINDING_ENABLED(&thr->catchstack[cat_idx])) {
-		duk_activation *act;
+	if (DUK_CAT_HAS_CATCH_BINDING_ENABLED(&thr->catchstack[cat_idx])) {
 		duk_hobject *new_env;
 		duk_hobject *act_lex_env;
 
@@ -50810,7 +67962,7 @@ static void duk__handle_catch_or_finally(duk_hthread *thr, duk_size_t cat_idx, d
 		}
 		DUK_ASSERT(act->lex_env != NULL);
 		DUK_ASSERT(act->var_env != NULL);
-		DUK_ASSERT(act->func != NULL);
+		DUK_ASSERT(DUK_ACT_GET_FUNC(act) != NULL);
 		DUK_UNREF(act);  /* unreferenced without assertions */
 
 		act = thr->callstack + thr->callstack_top - 1;
@@ -50821,7 +67973,7 @@ static void duk__handle_catch_or_finally(duk_hthread *thr, duk_size_t cat_idx, d
 		                                    DUK_HOBJECT_FLAG_EXTENSIBLE |
 		                                    DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_DECENV),
 		                                    act_lex_env);
-		new_env = duk_require_hobject(ctx, -1);
+		new_env = duk_get_hobject(ctx, -1);
 		DUK_ASSERT(new_env != NULL);
 		DUK_DDD(DUK_DDDPRINT("new_env allocated: %!iO", (duk_heaphdr *) new_env));
 
@@ -50833,8 +67985,8 @@ static void duk__handle_catch_or_finally(duk_hthread *thr, duk_size_t cat_idx, d
 
 		DUK_ASSERT(thr->catchstack[cat_idx].h_varname != NULL);
 		duk_push_hstring(ctx, thr->catchstack[cat_idx].h_varname);
-		duk_push_tval(ctx, &thr->heap->lj.value1);
-		duk_def_prop(ctx, -3, DUK_PROPDESC_FLAGS_W);  /* writable, not configurable */
+		duk_push_tval(ctx, thr->valstack + thr->catchstack[cat_idx].idx_base);
+		duk_xdef_prop(ctx, -3, DUK_PROPDESC_FLAGS_W);  /* writable, not configurable */
 
 		act = thr->callstack + thr->callstack_top - 1;
 		act->lex_env = new_env;
@@ -50847,58 +67999,88 @@ static void duk__handle_catch_or_finally(duk_hthread *thr, duk_size_t cat_idx, d
 		DUK_DDD(DUK_DDDPRINT("new_env finished: %!iO", (duk_heaphdr *) new_env));
 	}
 
-	if (is_finally) {
-		DUK_CAT_CLEAR_FINALLY_ENABLED(&thr->catchstack[cat_idx]);
-	} else {
-		DUK_CAT_CLEAR_CATCH_ENABLED(&thr->catchstack[cat_idx]);
-	}
+	DUK_CAT_CLEAR_CATCH_ENABLED(&thr->catchstack[cat_idx]);
+}
+
+DUK_LOCAL void duk__handle_finally(duk_hthread *thr, duk_size_t cat_idx, duk_tval *tv_val_unstable, duk_small_uint_t lj_type) {
+	duk_activation *act;
+
+	DUK_ASSERT(thr != NULL);
+	DUK_ASSERT(tv_val_unstable != NULL);
+
+	duk__set_catcher_regs(thr, cat_idx, tv_val_unstable, lj_type);
+
+	duk_hthread_catchstack_unwind(thr, cat_idx + 1);  /* cat_idx catcher is kept, even for finally */
+	duk_hthread_callstack_unwind(thr, thr->catchstack[cat_idx].callstack_index + 1);
+
+	DUK_ASSERT(thr->callstack_top >= 1);
+	DUK_ASSERT(DUK_ACT_GET_FUNC(thr->callstack + thr->callstack_top - 1) != NULL);
+	DUK_ASSERT(DUK_HOBJECT_IS_COMPILEDFUNCTION(DUK_ACT_GET_FUNC(thr->callstack + thr->callstack_top - 1)));
+
+	duk__reconfig_valstack_ecma_catcher(thr, thr->callstack_top - 1, cat_idx);
+
+	DUK_ASSERT(thr->callstack_top >= 1);
+	act = thr->callstack + thr->callstack_top - 1;
+	act->curr_pc = thr->catchstack[cat_idx].pc_base + 1;  /* +1 = finally */
+	act = NULL;
+
+	DUK_CAT_CLEAR_FINALLY_ENABLED(&thr->catchstack[cat_idx]);
 }
 
-static void duk__handle_label(duk_hthread *thr, duk_size_t cat_idx) {
-	/* no callstack changes, no value stack changes */
+DUK_LOCAL void duk__handle_label(duk_hthread *thr, duk_size_t cat_idx, duk_small_uint_t lj_type) {
+	duk_activation *act;
+
+	DUK_ASSERT(thr != NULL);
+
+	DUK_ASSERT(thr->callstack_top >= 1);
+	act = thr->callstack + thr->callstack_top - 1;
+
+	DUK_ASSERT(DUK_ACT_GET_FUNC(act) != NULL);
+	DUK_ASSERT(DUK_HOBJECT_HAS_COMPILEDFUNCTION(DUK_ACT_GET_FUNC(act)));
 
 	/* +0 = break, +1 = continue */
-	(thr->callstack + thr->callstack_top - 1)->pc =
-		thr->catchstack[cat_idx].pc_base + (thr->heap->lj.type == DUK_LJ_TYPE_CONTINUE ? 1 : 0);
+	act->curr_pc = thr->catchstack[cat_idx].pc_base + (lj_type == DUK_LJ_TYPE_CONTINUE ? 1 : 0);
+	act = NULL;  /* invalidated */
 
 	duk_hthread_catchstack_unwind(thr, cat_idx + 1);  /* keep label catcher */
 	/* no need to unwind callstack */
+
+	/* valstack should not need changes */
+#if defined(DUK_USE_ASSERTIONS)
+	DUK_ASSERT(thr->callstack_top >= 1);
+	act = thr->callstack + thr->callstack_top - 1;
+	DUK_ASSERT((duk_size_t) (thr->valstack_top - thr->valstack_bottom) ==
+	           (duk_size_t) ((duk_hcompiledfunction *) DUK_ACT_GET_FUNC(act))->nregs);
+#endif
 }
 
-/* Note: called for DUK_LJ_TYPE_YIELD and for DUK_LJ_TYPE_RETURN, when a
- * return terminates a thread and yields to the resumer.
+/* Called for handling both a longjmp() with type DUK_LJ_TYPE_YIELD and
+ * when a RETURN opcode terminates a thread and yields to the resumer.
  */
-static void duk__handle_yield(duk_hthread *thr, duk_hthread *resumer, duk_size_t act_idx) {
-	duk_tval tv_tmp;
+DUK_LOCAL void duk__handle_yield(duk_hthread *thr, duk_hthread *resumer, duk_size_t act_idx, duk_tval *tv_val_unstable) {
 	duk_tval *tv1;
 
-	/* this may also be called for DUK_LJ_TYPE_RETURN; this is OK as long as
-	 * lj.value1 is correct.
-	 */
-
-	DUK_ASSERT(resumer->callstack[act_idx].func != NULL);
-	DUK_ASSERT(DUK_HOBJECT_IS_COMPILEDFUNCTION(resumer->callstack[act_idx].func));  /* resume caller must be an ecmascript func */
-
-	DUK_DDD(DUK_DDDPRINT("resume idx_retval is %ld", (long) resumer->callstack[act_idx].idx_retval));
+	DUK_ASSERT(thr != NULL);
+	DUK_ASSERT(resumer != NULL);
+	DUK_ASSERT(tv_val_unstable != NULL);
+	DUK_ASSERT(DUK_ACT_GET_FUNC(resumer->callstack + act_idx) != NULL);
+	DUK_ASSERT(DUK_HOBJECT_IS_COMPILEDFUNCTION(DUK_ACT_GET_FUNC(resumer->callstack + act_idx)));  /* resume caller must be an ecmascript func */
 
 	tv1 = resumer->valstack + resumer->callstack[act_idx].idx_retval;  /* return value from Duktape.Thread.resume() */
-	DUK_TVAL_SET_TVAL(&tv_tmp, tv1);
-	DUK_TVAL_SET_TVAL(tv1, &thr->heap->lj.value1);
-	DUK_TVAL_INCREF(thr, tv1);
-	DUK_TVAL_DECREF(thr, &tv_tmp);  /* side effects */
+	DUK_TVAL_SET_TVAL_UPDREF(thr, tv1, tv_val_unstable);  /* side effects */
 
 	duk_hthread_callstack_unwind(resumer, act_idx + 1);  /* unwind to 'resume' caller */
 
 	/* no need to unwind catchstack */
-	duk__reconfig_valstack(resumer, act_idx, 1);  /* 1 = have retval */
+	duk__reconfig_valstack_ecma_return(resumer, act_idx);
 
 	/* caller must change active thread, and set thr->resumer to NULL */
 }
 
-static duk_small_uint_t duk__handle_longjmp(duk_hthread *thr,
-                                            duk_hthread *entry_thread,
-                                            duk_size_t entry_callstack_top) {
-	duk_tval tv_tmp;
+DUK_LOCAL
+duk_small_uint_t duk__handle_longjmp(duk_hthread *thr,
+                                     duk_hthread *entry_thread,
+                                     duk_size_t entry_callstack_top) {
 	duk_size_t entry_callstack_index;
 	duk_small_uint_t retval = DUK__LONGJMP_RESTART;
 
@@ -50911,6 +68093,7 @@ static duk_small_uint_t duk__handle_longjmp(duk_hthread *thr,
 	/* 'thr' is the current thread, as no-one resumes except us and we
 	 * switch 'thr' in that case.
 	 */
+	DUK_ASSERT(thr == thr->heap->curr_thread);
 
 	/*
 	 *  (Re)try handling the longjmp.
@@ -50947,11 +68130,11 @@ static duk_small_uint_t duk__handle_longjmp(duk_hthread *thr,
 
 		DUK_ASSERT(thr->state == DUK_HTHREAD_STATE_RUNNING);                                                         /* unchanged by Duktape.Thread.resume() */
 		DUK_ASSERT(thr->callstack_top >= 2);                                                                         /* Ecmascript activation + Duktape.Thread.resume() activation */
-		DUK_ASSERT((thr->callstack + thr->callstack_top - 1)->func != NULL &&
-		           DUK_HOBJECT_IS_NATIVEFUNCTION((thr->callstack + thr->callstack_top - 1)->func) &&
-		           ((duk_hnativefunction *) (thr->callstack + thr->callstack_top - 1)->func)->func == duk_bi_thread_resume);
-		DUK_ASSERT((thr->callstack + thr->callstack_top - 2)->func != NULL &&
-		           DUK_HOBJECT_IS_COMPILEDFUNCTION((thr->callstack + thr->callstack_top - 2)->func));                /* an Ecmascript function */
+		DUK_ASSERT(DUK_ACT_GET_FUNC(thr->callstack + thr->callstack_top - 1) != NULL &&
+		           DUK_HOBJECT_IS_NATIVEFUNCTION(DUK_ACT_GET_FUNC(thr->callstack + thr->callstack_top - 1)) &&
+		           ((duk_hnativefunction *) DUK_ACT_GET_FUNC(thr->callstack + thr->callstack_top - 1))->func == duk_bi_thread_resume);
+		DUK_ASSERT(DUK_ACT_GET_FUNC(thr->callstack + thr->callstack_top - 2) != NULL &&
+		           DUK_HOBJECT_IS_COMPILEDFUNCTION(DUK_ACT_GET_FUNC(thr->callstack + thr->callstack_top - 2)));      /* an Ecmascript function */
 		DUK_ASSERT_DISABLE((thr->callstack + thr->callstack_top - 2)->idx_retval >= 0);                              /* unsigned */
 
 		tv = &thr->heap->lj.value2;  /* resumee */
@@ -50967,12 +68150,12 @@ static duk_small_uint_t duk__handle_longjmp(duk_hthread *thr,
 		DUK_ASSERT(resumee->state != DUK_HTHREAD_STATE_YIELDED ||
 		           resumee->callstack_top >= 2);                                                                     /* YIELDED: Ecmascript activation + Duktape.Thread.yield() activation */
 		DUK_ASSERT(resumee->state != DUK_HTHREAD_STATE_YIELDED ||
-		           ((resumee->callstack + resumee->callstack_top - 1)->func != NULL &&
-		            DUK_HOBJECT_IS_NATIVEFUNCTION((resumee->callstack + resumee->callstack_top - 1)->func) &&
-		            ((duk_hnativefunction *) (resumee->callstack + resumee->callstack_top - 1)->func)->func == duk_bi_thread_yield));
+		           (DUK_ACT_GET_FUNC(resumee->callstack + resumee->callstack_top - 1) != NULL &&
+		            DUK_HOBJECT_IS_NATIVEFUNCTION(DUK_ACT_GET_FUNC(resumee->callstack + resumee->callstack_top - 1)) &&
+		            ((duk_hnativefunction *) DUK_ACT_GET_FUNC(resumee->callstack + resumee->callstack_top - 1))->func == duk_bi_thread_yield));
 		DUK_ASSERT(resumee->state != DUK_HTHREAD_STATE_YIELDED ||
-		           ((resumee->callstack + resumee->callstack_top - 2)->func != NULL &&
-		            DUK_HOBJECT_IS_COMPILEDFUNCTION((resumee->callstack + resumee->callstack_top - 2)->func)));      /* an Ecmascript function */
+		           (DUK_ACT_GET_FUNC(resumee->callstack + resumee->callstack_top - 2) != NULL &&
+		            DUK_HOBJECT_IS_COMPILEDFUNCTION(DUK_ACT_GET_FUNC(resumee->callstack + resumee->callstack_top - 2))));      /* an Ecmascript function */
 		DUK_ASSERT_DISABLE(resumee->state != DUK_HTHREAD_STATE_YIELDED ||
 		           (resumee->callstack + resumee->callstack_top - 2)->idx_retval >= 0);                              /* idx_retval unsigned */
 		DUK_ASSERT(resumee->state != DUK_HTHREAD_STATE_INACTIVE ||
@@ -50995,7 +68178,7 @@ static duk_small_uint_t duk__handle_longjmp(duk_hthread *thr,
 
 			resumee->resumer = thr;
 			resumee->state = DUK_HTHREAD_STATE_RUNNING;
-			thr->state = DUK_HTHREAD_STATE_RESUMED;	
+			thr->state = DUK_HTHREAD_STATE_RESUMED;
 			DUK_HEAP_SWITCH_THREAD(thr->heap, resumee);
 			thr = resumee;
 
@@ -51015,16 +68198,13 @@ static duk_small_uint_t duk__handle_longjmp(duk_hthread *thr,
 			tv = resumee->valstack + resumee->callstack[act_idx].idx_retval;  /* return value from Duktape.Thread.yield() */
 			DUK_ASSERT(tv >= resumee->valstack && tv < resumee->valstack_top);
 			tv2 = &thr->heap->lj.value1;
-			DUK_TVAL_SET_TVAL(&tv_tmp, tv);
-			DUK_TVAL_SET_TVAL(tv, tv2);
-			DUK_TVAL_INCREF(thr, tv);
-			DUK_TVAL_DECREF(thr, &tv_tmp);  /* side effects */
+			DUK_TVAL_SET_TVAL_UPDREF(thr, tv, tv2);  /* side effects */
 
 			duk_hthread_callstack_unwind(resumee, act_idx + 1);  /* unwind to 'yield' caller */
 
 			/* no need to unwind catchstack */
 
-			duk__reconfig_valstack(resumee, act_idx, 1);  /* 1 = have retval */
+			duk__reconfig_valstack_ecma_return(resumee, act_idx);
 
 			resumee->resumer = thr;
 			resumee->state = DUK_HTHREAD_STATE_RUNNING;
@@ -51037,7 +68217,8 @@ static duk_small_uint_t duk__handle_longjmp(duk_hthread *thr,
 			retval = DUK__LONGJMP_RESTART;
 			goto wipe_and_return;
 		} else {
-			int call_flags;
+			duk_small_uint_t call_flags;
+			duk_bool_t setup_rc;
 
 			/* resumee: [... initial_func]  (currently actually: [initial_func]) */
 
@@ -51047,11 +68228,15 @@ static duk_small_uint_t duk__handle_longjmp(duk_hthread *thr,
 
 			/* resumee: [... initial_func undefined(= this) resume_value ] */
 
-			call_flags = DUK_CALL_FLAG_IS_RESUME;  /* is resume, not a tailcall */
+			call_flags = DUK_CALL_FLAG_IS_RESUME;  /* is resume, not a tail call */
 
-			duk_handle_ecma_call_setup(resumee,
-			                           1,              /* num_stack_args */
-			                           call_flags);    /* call_flags */
+			setup_rc = duk_handle_ecma_call_setup(resumee,
+			                                      1,              /* num_stack_args */
+			                                      call_flags);    /* call_flags */
+			if (setup_rc == 0) {
+				/* Shouldn't happen but check anyway. */
+				DUK_ERROR(thr, DUK_ERR_INTERNAL_ERROR, DUK_STR_INTERNAL_ERROR);
+			}
 
 			resumee->resumer = thr;
 			resumee->state = DUK_HTHREAD_STATE_RUNNING;
@@ -51086,11 +68271,11 @@ static duk_small_uint_t duk__handle_longjmp(duk_hthread *thr,
 		DUK_ASSERT(thr != entry_thread);                                                                             /* Duktape.Thread.yield() should prevent */
 		DUK_ASSERT(thr->state == DUK_HTHREAD_STATE_RUNNING);                                                         /* unchanged from Duktape.Thread.yield() */
 		DUK_ASSERT(thr->callstack_top >= 2);                                                                         /* Ecmascript activation + Duktape.Thread.yield() activation */
-		DUK_ASSERT((thr->callstack + thr->callstack_top - 1)->func != NULL &&
-		           DUK_HOBJECT_IS_NATIVEFUNCTION((thr->callstack + thr->callstack_top - 1)->func) &&
-		           ((duk_hnativefunction *) (thr->callstack + thr->callstack_top - 1)->func)->func == duk_bi_thread_yield);
-		DUK_ASSERT((thr->callstack + thr->callstack_top - 2)->func != NULL &&
-		           DUK_HOBJECT_IS_COMPILEDFUNCTION((thr->callstack + thr->callstack_top - 2)->func));                /* an Ecmascript function */
+		DUK_ASSERT(DUK_ACT_GET_FUNC(thr->callstack + thr->callstack_top - 1) != NULL &&
+		           DUK_HOBJECT_IS_NATIVEFUNCTION(DUK_ACT_GET_FUNC(thr->callstack + thr->callstack_top - 1)) &&
+		           ((duk_hnativefunction *) DUK_ACT_GET_FUNC(thr->callstack + thr->callstack_top - 1))->func == duk_bi_thread_yield);
+		DUK_ASSERT(DUK_ACT_GET_FUNC(thr->callstack + thr->callstack_top - 2) != NULL &&
+		           DUK_HOBJECT_IS_COMPILEDFUNCTION(DUK_ACT_GET_FUNC(thr->callstack + thr->callstack_top - 2)));      /* an Ecmascript function */
 		DUK_ASSERT_DISABLE((thr->callstack + thr->callstack_top - 2)->idx_retval >= 0);                              /* unsigned */
 
 		resumer = thr->resumer;
@@ -51098,11 +68283,11 @@ static duk_small_uint_t duk__handle_longjmp(duk_hthread *thr,
 		DUK_ASSERT(resumer != NULL);
 		DUK_ASSERT(resumer->state == DUK_HTHREAD_STATE_RESUMED);                                                     /* written by a previous RESUME handling */
 		DUK_ASSERT(resumer->callstack_top >= 2);                                                                     /* Ecmascript activation + Duktape.Thread.resume() activation */
-		DUK_ASSERT((resumer->callstack + resumer->callstack_top - 1)->func != NULL &&
-		           DUK_HOBJECT_IS_NATIVEFUNCTION((resumer->callstack + resumer->callstack_top - 1)->func) &&
-		           ((duk_hnativefunction *) (resumer->callstack + resumer->callstack_top - 1)->func)->func == duk_bi_thread_resume);
-		DUK_ASSERT((resumer->callstack + resumer->callstack_top - 2)->func != NULL &&
-		           DUK_HOBJECT_IS_COMPILEDFUNCTION((resumer->callstack + resumer->callstack_top - 2)->func));        /* an Ecmascript function */
+		DUK_ASSERT(DUK_ACT_GET_FUNC(resumer->callstack + resumer->callstack_top - 1) != NULL &&
+		           DUK_HOBJECT_IS_NATIVEFUNCTION(DUK_ACT_GET_FUNC(resumer->callstack + resumer->callstack_top - 1)) &&
+		           ((duk_hnativefunction *) DUK_ACT_GET_FUNC(resumer->callstack + resumer->callstack_top - 1))->func == duk_bi_thread_resume);
+		DUK_ASSERT(DUK_ACT_GET_FUNC(resumer->callstack + resumer->callstack_top - 2) != NULL &&
+		           DUK_HOBJECT_IS_COMPILEDFUNCTION(DUK_ACT_GET_FUNC(resumer->callstack + resumer->callstack_top - 2)));        /* an Ecmascript function */
 		DUK_ASSERT_DISABLE((resumer->callstack + resumer->callstack_top - 2)->idx_retval >= 0);                      /* unsigned */
 
 		if (thr->heap->lj.iserror) {
@@ -51119,7 +68304,7 @@ static duk_small_uint_t duk__handle_longjmp(duk_hthread *thr,
 			DUK_DD(DUK_DDPRINT("-> yield an error, converted to a throw in the resumer, propagate"));
 			goto check_longjmp;
 		} else {
-			duk__handle_yield(thr, resumer, resumer->callstack_top - 2);
+			duk__handle_yield(thr, resumer, resumer->callstack_top - 2, &thr->heap->lj.value1);
 
 			thr->state = DUK_HTHREAD_STATE_YIELDED;
 			thr->resumer = NULL;
@@ -51137,203 +68322,6 @@ static duk_small_uint_t duk__handle_longjmp(duk_hthread *thr,
 		break;  /* never here */
 	}
 
-	case DUK_LJ_TYPE_RETURN: {
-		/*
-		 *  Four possible outcomes:
-		 *    * A 'finally' in the same function catches the 'return'.
-		 *      (or)
-		 *    * The return happens at the entry level of the bytecode
-		 *      executor, so return from the executor (in C stack).
-		 *      (or)
-		 *    * There is a calling (Ecmascript) activation in the call
-		 *      stack => return to it.
-		 *      (or)
-		 *    * There is no calling activation, and the thread is
-		 *      terminated.  There is always a resumer in this case,
-		 *      which gets the return value similarly to a 'yield'
-		 *      (except that the current thread can no longer be
-		 *      resumed).
-		 */
-
-		duk_tval *tv1;
-		duk_hthread *resumer;
-		duk_catcher *cat;
-		duk_size_t orig_callstack_index;
-
-		DUK_ASSERT(thr != NULL);
-		DUK_ASSERT(thr->callstack_top >= 1);
-		DUK_ASSERT(thr->catchstack != NULL);
-
-		/* XXX: does not work if thr->catchstack is NULL */
-		/* XXX: does not work if thr->catchstack is allocated but lowest pointer */
-
-		cat = thr->catchstack + thr->catchstack_top - 1;  /* may be < thr->catchstack initially */
-		DUK_ASSERT(thr->callstack_top > 0);  /* ensures callstack_top - 1 >= 0 */
-		orig_callstack_index = thr->callstack_top - 1;
-
-		while (cat >= thr->catchstack) {
-			if (cat->callstack_index != orig_callstack_index) {
-				break;
-			}
-			if (DUK_CAT_GET_TYPE(cat) == DUK_CAT_TYPE_TCF &&
-			    DUK_CAT_HAS_FINALLY_ENABLED(cat)) {
-				/* 'finally' catches */
-				duk__handle_catch_or_finally(thr,
-				                             cat - thr->catchstack,
-				                             1); /* is_finally */
-
-				DUK_DD(DUK_DDPRINT("-> return caught by a finally (in the same function), restart execution"));
-				retval = DUK__LONGJMP_RESTART;
-				goto wipe_and_return;
-			}
-			cat--;
-		}
-		/* if out of catchstack, cat = thr->catchstack - 1 */
-
-		DUK_DD(DUK_DDPRINT("no catcher in catch stack, return to calling activation / yield"));
-
-		/* return to calling activation (if any) */
-
-		if (thr == entry_thread &&
-		    thr->callstack_top == entry_callstack_top) {
-			/* return to the bytecode executor caller */
-
-			duk_push_tval((duk_context *) thr, &thr->heap->lj.value1);
-
-			/* [ ... retval ] */
-
-			DUK_DD(DUK_DDPRINT("-> return propagated up to entry level, exit bytecode executor"));
-			retval = DUK__LONGJMP_FINISHED;
-			goto wipe_and_return;
-		}
-
-		if (thr->callstack_top >= 2) {
-			/* there is a caller; it MUST be an Ecmascript caller (otherwise it would
-			 * match entry level check)
-			 */
-
-			DUK_DDD(DUK_DDDPRINT("slow return to Ecmascript caller, idx_retval=%ld, lj_value1=%!T",
-			                     (long) (thr->callstack + thr->callstack_top - 2)->idx_retval,
-			                     (duk_tval *) &thr->heap->lj.value1));
-
-			DUK_ASSERT(DUK_HOBJECT_IS_COMPILEDFUNCTION((thr->callstack + thr->callstack_top - 2)->func));   /* must be ecmascript */
-
-			tv1 = thr->valstack + (thr->callstack + thr->callstack_top - 2)->idx_retval;
-			DUK_TVAL_SET_TVAL(&tv_tmp, tv1);
-			DUK_TVAL_SET_TVAL(tv1, &thr->heap->lj.value1);
-			DUK_TVAL_INCREF(thr, tv1);
-			DUK_TVAL_DECREF(thr, &tv_tmp);  /* side effects */
-
-			DUK_DDD(DUK_DDDPRINT("return value at idx_retval=%ld is %!T",
-			                     (long) (thr->callstack + thr->callstack_top - 2)->idx_retval,
-			                     (duk_tval *) (thr->valstack + (thr->callstack + thr->callstack_top - 2)->idx_retval)));
-
-			duk_hthread_catchstack_unwind(thr, (cat - thr->catchstack) + 1);  /* leave 'cat' as top catcher (also works if catchstack exhausted) */
-			duk_hthread_callstack_unwind(thr, thr->callstack_top - 1);
-			duk__reconfig_valstack(thr, thr->callstack_top - 1, 1);    /* new top, i.e. callee */
-
-			DUK_DD(DUK_DDPRINT("-> return not caught, restart execution in caller"));
-			retval = DUK__LONGJMP_RESTART;
-			goto wipe_and_return;
-		}
-	
-		DUK_DD(DUK_DDPRINT("no calling activation, thread finishes (similar to yield)"));
-
-		DUK_ASSERT(thr->resumer != NULL);
-		DUK_ASSERT(thr->resumer->callstack_top >= 2);  /* Ecmascript activation + Duktape.Thread.resume() activation */
-		DUK_ASSERT((thr->resumer->callstack + thr->resumer->callstack_top - 1)->func != NULL &&
-		           DUK_HOBJECT_IS_NATIVEFUNCTION((thr->resumer->callstack + thr->resumer->callstack_top - 1)->func) &&
-		           ((duk_hnativefunction *) (thr->resumer->callstack + thr->resumer->callstack_top - 1)->func)->func == duk_bi_thread_resume);  /* Duktape.Thread.resume() */
-		DUK_ASSERT((thr->resumer->callstack + thr->resumer->callstack_top - 2)->func != NULL &&
-		           DUK_HOBJECT_IS_COMPILEDFUNCTION((thr->resumer->callstack + thr->resumer->callstack_top - 2)->func));  /* an Ecmascript function */
-		DUK_ASSERT_DISABLE((thr->resumer->callstack + thr->resumer->callstack_top - 2)->idx_retval >= 0);                /* unsigned */
-		DUK_ASSERT(thr->state == DUK_HTHREAD_STATE_RUNNING);
-		DUK_ASSERT(thr->resumer->state == DUK_HTHREAD_STATE_RESUMED);
-
-		resumer = thr->resumer;
-
-		duk__handle_yield(thr, resumer, resumer->callstack_top - 2);
-
-		duk_hthread_terminate(thr);  /* updates thread state, minimizes its allocations */
-		DUK_ASSERT(thr->state == DUK_HTHREAD_STATE_TERMINATED);
-
-		thr->resumer = NULL;
-		resumer->state = DUK_HTHREAD_STATE_RUNNING;
-		DUK_HEAP_SWITCH_THREAD(thr->heap, resumer);
-#if 0
-		thr = resumer;  /* not needed */
-#endif
-
-		DUK_DD(DUK_DDPRINT("-> return not caught, thread terminated; handle like yield, restart execution in resumer"));
-		retval = DUK__LONGJMP_RESTART;
-		goto wipe_and_return;
-	}
-
-	case DUK_LJ_TYPE_BREAK:
-	case DUK_LJ_TYPE_CONTINUE: {
-		/*
-		 *  Find a matching label catcher or 'finally' catcher in
-		 *  the same function.
-		 *  
-		 *  A label catcher must always exist and will match unless
-		 *  a 'finally' captures the break/continue first.  It is the
-		 *  compiler's responsibility to ensure that labels are used
-		 *  correctly.
-		 */
-
-		duk_catcher *cat;
-		duk_size_t orig_callstack_index;
-		duk_uint_t lj_label;
-
-		cat = thr->catchstack + thr->catchstack_top - 1;
-		orig_callstack_index = cat->callstack_index;
-
-		DUK_ASSERT(DUK_TVAL_IS_NUMBER(&thr->heap->lj.value1));
-		lj_label = (duk_uint_t) DUK_TVAL_GET_NUMBER(&thr->heap->lj.value1);
-
-		DUK_DDD(DUK_DDDPRINT("handling break/continue with label=%ld, callstack index=%ld",
-		                     (long) lj_label, (long) cat->callstack_index));
-
-		while (cat >= thr->catchstack) {
-			if (cat->callstack_index != orig_callstack_index) {
-				break;
-			}
-			DUK_DDD(DUK_DDDPRINT("considering catcher %ld: type=%ld label=%ld",
-			                     (long) (cat - thr->catchstack),
-			                     (long) DUK_CAT_GET_TYPE(cat),
-			                     (long) DUK_CAT_GET_LABEL(cat)));
-
-			if (DUK_CAT_GET_TYPE(cat) == DUK_CAT_TYPE_TCF &&
-			    DUK_CAT_HAS_FINALLY_ENABLED(cat)) {
-				/* finally catches */
-				duk__handle_catch_or_finally(thr,
-				                             cat - thr->catchstack,
-				                             1); /* is_finally */
-
-				DUK_DD(DUK_DDPRINT("-> break/continue caught by a finally (in the same function), restart execution"));
-				retval = DUK__LONGJMP_RESTART;
-				goto wipe_and_return;
-			}
-			if (DUK_CAT_GET_TYPE(cat) == DUK_CAT_TYPE_LABEL &&
-			    (duk_uint_t) DUK_CAT_GET_LABEL(cat) == lj_label) {
-				/* found label */
-				duk__handle_label(thr,
-				                  cat - thr->catchstack);
-
-				/* FIXME: reset valstack to 'nregs' (or assert it) */
-
-				DUK_DD(DUK_DDPRINT("-> break/continue caught by a label catcher (in the same function), restart execution"));
-				retval = DUK__LONGJMP_RESTART;
-				goto wipe_and_return;
-			}
-			cat--;
-		}
-
-		/* should never happen, but be robust */
-		DUK_D(DUK_DPRINT("break/continue not caught by anything in the current function (should never happen)"));
-		goto convert_to_internal_error;
-	}
-
 	case DUK_LJ_TYPE_THROW: {
 		/*
 		 *  Three possible outcomes:
@@ -51365,12 +68353,12 @@ static duk_small_uint_t duk__handle_longjmp(duk_hthread *thr,
 			}
 
 			if (DUK_CAT_HAS_CATCH_ENABLED(cat)) {
-				/* try catches */
 				DUK_ASSERT(DUK_CAT_GET_TYPE(cat) == DUK_CAT_TYPE_TCF);
 
-				duk__handle_catch_or_finally(thr,
-				                             cat - thr->catchstack,
-				                             0); /* is_finally */
+				duk__handle_catch(thr,
+				                  cat - thr->catchstack,
+				                  &thr->heap->lj.value1,
+				                  DUK_LJ_TYPE_THROW);
 
 				DUK_DD(DUK_DDPRINT("-> throw caught by a 'catch' clause, restart execution"));
 				retval = DUK__LONGJMP_RESTART;
@@ -51381,11 +68369,10 @@ static duk_small_uint_t duk__handle_longjmp(duk_hthread *thr,
 				DUK_ASSERT(DUK_CAT_GET_TYPE(cat) == DUK_CAT_TYPE_TCF);
 				DUK_ASSERT(!DUK_CAT_HAS_CATCH_ENABLED(cat));
 
-				duk__handle_catch_or_finally(thr,
-				                             cat - thr->catchstack,
-				                             1); /* is_finally */
-
-				/* FIXME: reset valstack to 'nregs' (or assert it) */
+				duk__handle_finally(thr,
+				                    cat - thr->catchstack,
+				                    &thr->heap->lj.value1,
+				                    DUK_LJ_TYPE_THROW);
 
 				DUK_DD(DUK_DDPRINT("-> throw caught by a 'finally' clause, restart execution"));
 				retval = DUK__LONGJMP_RESTART;
@@ -51410,7 +68397,7 @@ static duk_small_uint_t duk__handle_longjmp(duk_hthread *thr,
 			/* Note: MUST NOT wipe_and_return here, as heap->lj must remain intact */
 		}
 
-		DUK_DD(DUK_DDPRINT("not caught by current thread, yield error to resumer"));
+		DUK_DD(DUK_DDPRINT("-> throw not caught by current thread, yield error to resumer and recheck longjmp"));
 
 		/* not caught by current thread, thread terminates (yield error to resumer);
 		 * note that this may cause a cascade if the resumer terminates with an uncaught
@@ -51419,11 +68406,11 @@ static duk_small_uint_t duk__handle_longjmp(duk_hthread *thr,
 
 		DUK_ASSERT(thr->resumer != NULL);
 		DUK_ASSERT(thr->resumer->callstack_top >= 2);  /* Ecmascript activation + Duktape.Thread.resume() activation */
-		DUK_ASSERT((thr->resumer->callstack + thr->resumer->callstack_top - 1)->func != NULL &&
-		           DUK_HOBJECT_IS_NATIVEFUNCTION((thr->resumer->callstack + thr->resumer->callstack_top - 1)->func) &&
-		           ((duk_hnativefunction *) (thr->resumer->callstack + thr->resumer->callstack_top - 1)->func)->func == duk_bi_thread_resume);  /* Duktape.Thread.resume() */
-		DUK_ASSERT((thr->resumer->callstack + thr->resumer->callstack_top - 2)->func != NULL &&
-		           DUK_HOBJECT_IS_COMPILEDFUNCTION((thr->resumer->callstack + thr->resumer->callstack_top - 2)->func));  /* an Ecmascript function */
+		DUK_ASSERT(DUK_ACT_GET_FUNC(thr->resumer->callstack + thr->resumer->callstack_top - 1) != NULL &&
+		           DUK_HOBJECT_IS_NATIVEFUNCTION(DUK_ACT_GET_FUNC(thr->resumer->callstack + thr->resumer->callstack_top - 1)) &&
+		           ((duk_hnativefunction *) DUK_ACT_GET_FUNC(thr->resumer->callstack + thr->resumer->callstack_top - 1))->func == duk_bi_thread_resume);  /* Duktape.Thread.resume() */
+		DUK_ASSERT(DUK_ACT_GET_FUNC(thr->resumer->callstack + thr->resumer->callstack_top - 2) != NULL &&
+		           DUK_HOBJECT_IS_COMPILEDFUNCTION(DUK_ACT_GET_FUNC(thr->resumer->callstack + thr->resumer->callstack_top - 2)));  /* an Ecmascript function */
 
 		resumer = thr->resumer;
 
@@ -51442,11 +68429,10 @@ static duk_small_uint_t duk__handle_longjmp(duk_hthread *thr,
 		goto check_longjmp;
 	}
 
-	case DUK_LJ_TYPE_NORMAL: {
-		DUK_D(DUK_DPRINT("caught DUK_LJ_TYPE_NORMAL, should never happen, treat as internal error"));
-		goto convert_to_internal_error;
-	}
-
+	case DUK_LJ_TYPE_BREAK:  /* pseudotypes, not used in actual longjmps */
+	case DUK_LJ_TYPE_CONTINUE:
+	case DUK_LJ_TYPE_RETURN:
+	case DUK_LJ_TYPE_NORMAL:
 	default: {
 		/* should never happen, but be robust */
 		DUK_D(DUK_DPRINT("caught unknown longjmp type %ld, treat as internal error", (long) thr->heap->lj.type));
@@ -51462,26 +68448,253 @@ static duk_small_uint_t duk__handle_longjmp(duk_hthread *thr,
 	thr->heap->lj.type = DUK_LJ_TYPE_UNKNOWN;
 	thr->heap->lj.iserror = 0;
 
-	DUK_TVAL_SET_TVAL(&tv_tmp, &thr->heap->lj.value1);
-	DUK_TVAL_SET_UNDEFINED_UNUSED(&thr->heap->lj.value1);
-	DUK_TVAL_DECREF(thr, &tv_tmp);  /* side effects */
-
-	DUK_TVAL_SET_TVAL(&tv_tmp, &thr->heap->lj.value2);
-	DUK_TVAL_SET_UNDEFINED_UNUSED(&thr->heap->lj.value2);
-	DUK_TVAL_DECREF(thr, &tv_tmp);  /* side effects */
+	DUK_TVAL_SET_UNDEFINED_UPDREF(thr, &thr->heap->lj.value1);  /* side effects */
+	DUK_TVAL_SET_UNDEFINED_UPDREF(thr, &thr->heap->lj.value2);  /* side effects */
 
  just_return:
 	return retval;
 
  convert_to_internal_error:
 	/* This could also be thrown internally (set the error, goto check_longjmp),
-	 * but it's better for internal errors to bubble outwards.
+	 * but it's better for internal errors to bubble outwards so that we won't
+	 * infinite loop in this catchpoint.
 	 */
 	DUK_ERROR(thr, DUK_ERR_INTERNAL_ERROR, DUK_STR_INTERNAL_ERROR_EXEC_LONGJMP);
 	DUK_UNREACHABLE();
 	return retval;
 }
 
+/* Handle a BREAK/CONTINUE opcode.  Avoid using longjmp() for BREAK/CONTINUE
+ * handling because it has a measurable performance impact in ordinary
+ * environments and an extreme impact in Emscripten (GH-342).
+ */
+DUK_LOCAL void duk__handle_break_or_continue(duk_hthread *thr,
+                                             duk_uint_t label_id,
+                                             duk_small_uint_t lj_type) {
+	duk_catcher *cat;
+	duk_size_t orig_callstack_index;
+
+	DUK_ASSERT(thr != NULL);
+
+	/*
+	 *  Find a matching label catcher or 'finally' catcher in
+	 *  the same function.
+	 *
+	 *  A label catcher must always exist and will match unless
+	 *  a 'finally' captures the break/continue first.  It is the
+	 *  compiler's responsibility to ensure that labels are used
+	 *  correctly.
+	 */
+
+	/* Note: thr->catchstack_top may be 0, so that cat < thr->catchstack
+	 * initially.  This is OK and intended.
+	 */
+	cat = thr->catchstack + thr->catchstack_top - 1;
+	DUK_ASSERT(thr->callstack_top > 0);
+	orig_callstack_index = thr->callstack_top - 1;
+
+	DUK_DDD(DUK_DDDPRINT("handling break/continue with label=%ld, callstack index=%ld",
+	                     (long) label_id, (long) cat->callstack_index));
+
+	while (cat >= thr->catchstack) {
+		if (cat->callstack_index != orig_callstack_index) {
+			break;
+		}
+		DUK_DDD(DUK_DDDPRINT("considering catcher %ld: type=%ld label=%ld",
+		                     (long) (cat - thr->catchstack),
+		                     (long) DUK_CAT_GET_TYPE(cat),
+		                     (long) DUK_CAT_GET_LABEL(cat)));
+
+		if (DUK_CAT_GET_TYPE(cat) == DUK_CAT_TYPE_TCF &&
+		    DUK_CAT_HAS_FINALLY_ENABLED(cat)) {
+			duk_size_t cat_idx;
+			duk_tval tv_tmp;
+
+			cat_idx = (duk_size_t) (cat - thr->catchstack);  /* get before side effects */
+
+#if defined(DUK_USE_FASTINT)
+			DUK_TVAL_SET_FASTINT_U32(&tv_tmp, (duk_uint32_t) label_id);
+#else
+			DUK_TVAL_SET_NUMBER(&tv_tmp, (duk_double_t) label_id);
+#endif
+			duk__handle_finally(thr, cat_idx, &tv_tmp, lj_type);
+
+			DUK_DD(DUK_DDPRINT("-> break/continue caught by 'finally', restart execution"));
+			return;
+		}
+		if (DUK_CAT_GET_TYPE(cat) == DUK_CAT_TYPE_LABEL &&
+		    (duk_uint_t) DUK_CAT_GET_LABEL(cat) == label_id) {
+			duk_size_t cat_idx;
+
+			cat_idx = (duk_size_t) (cat - thr->catchstack);
+			duk__handle_label(thr, cat_idx, lj_type);
+
+			DUK_DD(DUK_DDPRINT("-> break/continue caught by a label catcher (in the same function), restart execution"));
+			return;
+		}
+		cat--;
+	}
+
+	/* should never happen, but be robust */
+	DUK_D(DUK_DPRINT("-> break/continue not caught by anything in the current function (should never happen), throw internal error"));
+	DUK_ERROR(thr, DUK_ERR_INTERNAL_ERROR, DUK_STR_INTERNAL_ERROR);
+	return;
+}
+
+/* Handle a RETURN opcode.  Avoid using longjmp() for return handling because
+ * it has a measurable performance impact in ordinary environments and an extreme
+ * impact in Emscripten (GH-342).  Return value is on value stack top.
+ */
+DUK_LOCAL duk_small_uint_t duk__handle_return(duk_hthread *thr,
+                                              duk_hthread *entry_thread,
+                                              duk_size_t entry_callstack_top) {
+	duk_tval *tv1;
+	duk_tval *tv2;
+	duk_hthread *resumer;
+	duk_catcher *cat;
+	duk_size_t new_cat_top;
+	duk_size_t orig_callstack_index;
+
+	/* We can directly access value stack here. */
+
+	DUK_ASSERT(thr != NULL);
+	DUK_ASSERT(entry_thread != NULL);
+	DUK_ASSERT(thr->valstack_top - 1 >= thr->valstack_bottom);
+	tv1 = thr->valstack_top - 1;
+	DUK_TVAL_CHKFAST_INPLACE(tv1);  /* fastint downgrade check for return values */
+
+	/*
+	 *  Four possible outcomes:
+	 *
+	 *    1. A 'finally' in the same function catches the 'return'.
+	 *       It may continue to propagate when 'finally' is finished,
+	 *       or it may be neutralized by 'finally' (both handled by
+	 *       ENDFIN).
+	 *
+	 *    2. The return happens at the entry level of the bytecode
+	 *       executor, so return from the executor (in C stack).
+	 *
+	 *    3. There is a calling (Ecmascript) activation in the call
+	 *       stack => return to it, in the same executor instance.
+	 *
+	 *    4. There is no calling activation, and the thread is
+	 *       terminated.  There is always a resumer in this case,
+	 *       which gets the return value similarly to a 'yield'
+	 *       (except that the current thread can no longer be
+	 *       resumed).
+	 */
+
+	DUK_ASSERT(thr != NULL);
+	DUK_ASSERT(thr->callstack_top >= 1);
+	DUK_ASSERT(thr->catchstack != NULL);
+
+	/* XXX: does not work if thr->catchstack is NULL */
+	/* XXX: does not work if thr->catchstack is allocated but lowest pointer */
+
+	cat = thr->catchstack + thr->catchstack_top - 1;  /* may be < thr->catchstack initially */
+	DUK_ASSERT(thr->callstack_top > 0);  /* ensures callstack_top - 1 >= 0 */
+	orig_callstack_index = thr->callstack_top - 1;
+
+	while (cat >= thr->catchstack) {
+		if (cat->callstack_index != orig_callstack_index) {
+			break;
+		}
+		if (DUK_CAT_GET_TYPE(cat) == DUK_CAT_TYPE_TCF &&
+		    DUK_CAT_HAS_FINALLY_ENABLED(cat)) {
+			duk_size_t cat_idx;
+
+			cat_idx = (duk_size_t) (cat - thr->catchstack);  /* get before side effects */
+
+			DUK_ASSERT(thr->valstack_top - 1 >= thr->valstack_bottom);
+			duk__handle_finally(thr, cat_idx, thr->valstack_top - 1, DUK_LJ_TYPE_RETURN);
+
+			DUK_DD(DUK_DDPRINT("-> return caught by 'finally', restart execution"));
+			return DUK__RETHAND_RESTART;
+		}
+		cat--;
+	}
+	/* If out of catchstack, cat = thr->catchstack - 1;
+	 * new_cat_top will be 0 in that case.
+	 */
+	new_cat_top = (duk_size_t) ((cat + 1) - thr->catchstack);
+	cat = NULL;  /* avoid referencing, invalidated */
+
+	DUK_DDD(DUK_DDDPRINT("no catcher in catch stack, return to calling activation / yield"));
+
+	if (thr == entry_thread &&
+	    thr->callstack_top == entry_callstack_top) {
+		/* Return to the bytecode executor caller which will unwind stacks.
+		 * Return value is already on the stack top: [ ... retval ].
+		 */
+
+		/* XXX: could unwind catchstack here, so that call handling
+		 * didn't need to do that?
+		 */
+		DUK_DDD(DUK_DDDPRINT("-> return propagated up to entry level, exit bytecode executor"));
+		return DUK__RETHAND_FINISHED;
+	}
+
+	if (thr->callstack_top >= 2) {
+		/* There is a caller; it MUST be an Ecmascript caller (otherwise it would
+		 * match entry level check)
+		 */
+
+		DUK_DDD(DUK_DDDPRINT("return to Ecmascript caller, idx_retval=%ld, lj_value1=%!T",
+		                     (long) (thr->callstack + thr->callstack_top - 2)->idx_retval,
+		                     (duk_tval *) &thr->heap->lj.value1));
+
+		DUK_ASSERT(DUK_HOBJECT_IS_COMPILEDFUNCTION(DUK_ACT_GET_FUNC(thr->callstack + thr->callstack_top - 2)));   /* must be ecmascript */
+
+		tv1 = thr->valstack + (thr->callstack + thr->callstack_top - 2)->idx_retval;
+		DUK_ASSERT(thr->valstack_top - 1 >= thr->valstack_bottom);
+		tv2 = thr->valstack_top - 1;
+		DUK_TVAL_SET_TVAL_UPDREF(thr, tv1, tv2);  /* side effects */
+
+		DUK_DDD(DUK_DDDPRINT("return value at idx_retval=%ld is %!T",
+		                     (long) (thr->callstack + thr->callstack_top - 2)->idx_retval,
+		                     (duk_tval *) (thr->valstack + (thr->callstack + thr->callstack_top - 2)->idx_retval)));
+
+		duk_hthread_catchstack_unwind(thr, new_cat_top);  /* leave 'cat' as top catcher (also works if catchstack exhausted) */
+		duk_hthread_callstack_unwind(thr, thr->callstack_top - 1);
+		duk__reconfig_valstack_ecma_return(thr, thr->callstack_top - 1);
+
+		DUK_DD(DUK_DDPRINT("-> return not intercepted, restart execution in caller"));
+		return DUK__RETHAND_RESTART;
+	}
+
+	DUK_DD(DUK_DDPRINT("no calling activation, thread finishes (similar to yield)"));
+
+	DUK_ASSERT(thr->resumer != NULL);
+	DUK_ASSERT(thr->resumer->callstack_top >= 2);  /* Ecmascript activation + Duktape.Thread.resume() activation */
+	DUK_ASSERT(DUK_ACT_GET_FUNC(thr->resumer->callstack + thr->resumer->callstack_top - 1) != NULL &&
+	           DUK_HOBJECT_IS_NATIVEFUNCTION(DUK_ACT_GET_FUNC(thr->resumer->callstack + thr->resumer->callstack_top - 1)) &&
+	           ((duk_hnativefunction *) DUK_ACT_GET_FUNC(thr->resumer->callstack + thr->resumer->callstack_top - 1))->func == duk_bi_thread_resume);  /* Duktape.Thread.resume() */
+	DUK_ASSERT(DUK_ACT_GET_FUNC(thr->resumer->callstack + thr->resumer->callstack_top - 2) != NULL &&
+	           DUK_HOBJECT_IS_COMPILEDFUNCTION(DUK_ACT_GET_FUNC(thr->resumer->callstack + thr->resumer->callstack_top - 2)));  /* an Ecmascript function */
+	DUK_ASSERT_DISABLE((thr->resumer->callstack + thr->resumer->callstack_top - 2)->idx_retval >= 0);                /* unsigned */
+	DUK_ASSERT(thr->state == DUK_HTHREAD_STATE_RUNNING);
+	DUK_ASSERT(thr->resumer->state == DUK_HTHREAD_STATE_RESUMED);
+
+	resumer = thr->resumer;
+
+	/* Share yield longjmp handler. */
+	DUK_ASSERT(thr->valstack_top - 1 >= thr->valstack_bottom);
+	duk__handle_yield(thr, resumer, resumer->callstack_top - 2, thr->valstack_top - 1);
+
+	duk_hthread_terminate(thr);  /* updates thread state, minimizes its allocations */
+	DUK_ASSERT(thr->state == DUK_HTHREAD_STATE_TERMINATED);
+
+	thr->resumer = NULL;
+	resumer->state = DUK_HTHREAD_STATE_RUNNING;
+	DUK_HEAP_SWITCH_THREAD(thr->heap, resumer);
+#if 0
+	thr = resumer;  /* not needed */
+#endif
+
+	DUK_DD(DUK_DDPRINT("-> return not caught, thread terminated; handle like yield, restart execution in resumer"));
+	return DUK__RETHAND_RESTART;
+}
+
 /*
  *  Executor interrupt handling
  *
@@ -51507,63 +68720,436 @@ static duk_small_uint_t duk__handle_longjmp(duk_hthread *thr,
  *  work accurately even when single stepping.
  */
 
-#ifdef DUK_USE_INTERRUPT_COUNTER
-static void duk__executor_interrupt(duk_hthread *thr) {
+#if defined(DUK_USE_INTERRUPT_COUNTER)
+
+#define DUK__INT_NOACTION    0    /* no specific action, resume normal execution */
+#define DUK__INT_RESTART     1    /* must "goto restart_execution", e.g. breakpoints changed */
+
+#if defined(DUK_USE_DEBUGGER_SUPPORT)
+DUK_LOCAL void duk__interrupt_handle_debugger(duk_hthread *thr, duk_bool_t *out_immediate, duk_small_uint_t *out_interrupt_retval) {
+	duk_context *ctx;
+	duk_activation *act;
+	duk_breakpoint *bp;
+	duk_breakpoint **bp_active;
+	duk_uint_fast32_t line = 0;
+	duk_bool_t send_status;
+	duk_bool_t process_messages;
+	duk_bool_t processed_messages = 0;
+
+	ctx = (duk_context *) thr;
+	act = thr->callstack + thr->callstack_top - 1;
+
+	/* It might seem that replacing 'thr->heap' with just 'heap' below
+	 * might be a good idea, but it increases code size slightly
+	 * (probably due to unnecessary spilling) at least on x64.
+	 */
+
+	/*
+	 *  Breakpoint and step state checks
+	 */
+
+	if (act->flags & DUK_ACT_FLAG_BREAKPOINT_ACTIVE ||
+	    (thr->heap->dbg_step_thread == thr &&
+	     thr->heap->dbg_step_csindex == thr->callstack_top - 1)) {
+		line = duk_debug_curr_line(thr);
+
+		if (act->prev_line != line) {
+			/* Stepped?  Step out is handled by callstack unwind. */
+			if ((thr->heap->dbg_step_type == DUK_STEP_TYPE_INTO ||
+			     thr->heap->dbg_step_type == DUK_STEP_TYPE_OVER) &&
+			    (thr->heap->dbg_step_thread == thr) &&
+			    (thr->heap->dbg_step_csindex == thr->callstack_top - 1) &&
+			    (line != thr->heap->dbg_step_startline)) {
+				DUK_D(DUK_DPRINT("STEP STATE TRIGGERED PAUSE at line %ld",
+				                 (long) line));
+
+				DUK_HEAP_SET_PAUSED(thr->heap);
+			}
+
+			/* Check for breakpoints only on line transition.
+			 * Breakpoint is triggered when we enter the target
+			 * line from a different line, and the previous line
+			 * was within the same function.
+			 *
+			 * This condition is tricky: the condition used to be
+			 * that transition to -or across- the breakpoint line
+			 * triggered the breakpoint.  This seems intuitively
+			 * better because it handles breakpoints on lines with
+			 * no emitted opcodes; but this leads to the issue
+			 * described in: https://github.com/svaarala/duktape/issues/263.
+			 */
+			bp_active = thr->heap->dbg_breakpoints_active;
+			for (;;) {
+				bp = *bp_active++;
+				if (bp == NULL) {
+					break;
+				}
+
+				DUK_ASSERT(bp->filename != NULL);
+				if (act->prev_line != bp->line && line == bp->line) {
+					DUK_D(DUK_DPRINT("BREAKPOINT TRIGGERED at %!O:%ld",
+					                 (duk_heaphdr *) bp->filename, (long) bp->line));
+
+					DUK_HEAP_SET_PAUSED(thr->heap);
+				}
+			}
+		} else {
+			;
+		}
+
+		act->prev_line = line;
+	}
+
+	/*
+	 *  Rate limit check for sending status update or peeking into
+	 *  the debug transport.  Both can be expensive operations that
+	 *  we don't want to do on every opcode.
+	 *
+	 *  Making sure the interval remains reasonable on a wide variety
+	 *  of targets and bytecode is difficult without a timestamp, so
+	 *  we use a Date-provided timestamp for the rate limit check.
+	 *  But since it's also expensive to get a timestamp, a bytecode
+	 *  counter is used to rate limit getting timestamps.
+	 */
+
+	if (thr->heap->dbg_state_dirty || thr->heap->dbg_paused) {
+		send_status = 1;
+	} else {
+		send_status = 0;
+	}
+
+	if (thr->heap->dbg_paused) {
+		process_messages = 1;
+	} else {
+		process_messages = 0;
+	}
+
+	/* XXX: remove heap->dbg_exec_counter, use heap->inst_count_interrupt instead? */
+	thr->heap->dbg_exec_counter += thr->interrupt_init;
+	if (thr->heap->dbg_exec_counter - thr->heap->dbg_last_counter >= DUK_HEAP_DBG_RATELIMIT_OPCODES) {
+		/* Overflow of the execution counter is fine and doesn't break
+		 * anything here.
+		 */
+
+		duk_double_t now, diff_last;
+
+		thr->heap->dbg_last_counter = thr->heap->dbg_exec_counter;
+		now = DUK_USE_DATE_GET_NOW(ctx);
+
+		diff_last = now - thr->heap->dbg_last_time;
+		if (diff_last < 0.0 || diff_last >= (duk_double_t) DUK_HEAP_DBG_RATELIMIT_MILLISECS) {
+			/* Negative value checked so that a "time jump" works
+			 * reasonably.
+			 *
+			 * Same interval is now used for status sending and
+			 * peeking.
+			 */
+
+			thr->heap->dbg_last_time = now;
+			send_status = 1;
+			process_messages = 1;
+		}
+	}
+
+	/*
+	 *  Send status
+	 */
+
+	act = NULL;  /* may be changed */
+	if (send_status) {
+		duk_debug_send_status(thr);
+		thr->heap->dbg_state_dirty = 0;
+	}
+
+	/*
+	 *  Process messages.  If we're paused, we'll block for new messages.
+	 *  if we're not paused, we'll process anything we can peek but won't
+	 *  block for more.
+	 */
+
+	if (process_messages) {
+		processed_messages = duk_debug_process_messages(thr, 0 /*no_block*/);
+	}
+
+	/* XXX: any case here where we need to re-send status? */
+
+	/* Continue checked execution if there are breakpoints or we're stepping.
+	 * Also use checked execution if paused flag is active - it shouldn't be
+	 * because the debug message loop shouldn't terminate if it was.  Step out
+	 * is handled by callstack unwind and doesn't need checked execution.
+	 * Note that debugger may have detached due to error or explicit request
+	 * above, so we must recheck attach status.
+	 */
+
+	if (DUK_HEAP_IS_DEBUGGER_ATTACHED(thr->heap)) {
+		act = thr->callstack + thr->callstack_top - 1;  /* relookup, may have changed */
+		if (act->flags & DUK_ACT_FLAG_BREAKPOINT_ACTIVE ||
+		    ((thr->heap->dbg_step_type == DUK_STEP_TYPE_INTO ||
+		      thr->heap->dbg_step_type == DUK_STEP_TYPE_OVER) &&
+		     thr->heap->dbg_step_thread == thr &&
+		     thr->heap->dbg_step_csindex == thr->callstack_top - 1) ||
+		     thr->heap->dbg_paused) {
+			*out_immediate = 1;
+		}
+
+		/* If we processed any debug messages breakpoints may have
+		 * changed; restart execution to re-check active breakpoints.
+		 */
+		if (processed_messages) {
+			DUK_D(DUK_DPRINT("processed debug messages, restart execution to recheck possibly changed breakpoints"));
+			*out_interrupt_retval = DUK__INT_RESTART;
+		}
+	} else {
+		DUK_D(DUK_DPRINT("debugger became detached, resume normal execution"));
+	}
+}
+#endif  /* DUK_USE_DEBUGGER_SUPPORT */
+
+DUK_LOCAL duk_small_uint_t duk__executor_interrupt(duk_hthread *thr) {
 	duk_int_t ctr;
 	duk_activation *act;
 	duk_hcompiledfunction *fun;
+	duk_bool_t immediate = 0;
+	duk_small_uint_t retval;
 
 	DUK_ASSERT(thr != NULL);
+	DUK_ASSERT(thr->heap != NULL);
 	DUK_ASSERT(thr->callstack != NULL);
 	DUK_ASSERT(thr->callstack_top > 0);
 
+#if defined(DUK_USE_DEBUG)
+	thr->heap->inst_count_interrupt += thr->interrupt_init;
+	DUK_DD(DUK_DDPRINT("execution interrupt, counter=%ld, init=%ld, "
+	                   "instruction counts: executor=%ld, interrupt=%ld",
+	                   (long) thr->interrupt_counter, (long) thr->interrupt_init,
+	                   (long) thr->heap->inst_count_exec, (long) thr->heap->inst_count_interrupt));
+#endif
+
+	retval = DUK__INT_NOACTION;
+	ctr = DUK_HTHREAD_INTCTR_DEFAULT;
+
+	/*
+	 *  Avoid nested calls.  Concretely this happens during debugging, e.g.
+	 *  when we eval() an expression.
+	 *
+	 *  Also don't interrupt if we're currently doing debug processing
+	 *  (which can be initiated outside the bytecode executor) as this
+	 *  may cause the debugger to be called recursively.  Check required
+	 *  for correct operation of throw intercept and other "exotic" halting
+	 * scenarios.
+	 */
+
+#if defined(DUK_USE_DEBUGGER_SUPPORT)
+	if (DUK_HEAP_HAS_INTERRUPT_RUNNING(thr->heap) || thr->heap->dbg_processing) {
+#else
+	if (DUK_HEAP_HAS_INTERRUPT_RUNNING(thr->heap)) {
+#endif
+		DUK_DD(DUK_DDPRINT("nested executor interrupt, ignoring"));
+
+		/* Set a high interrupt counter; the original executor
+		 * interrupt invocation will rewrite before exiting.
+		 */
+		thr->interrupt_init = ctr;
+		thr->interrupt_counter = ctr - 1;
+		return DUK__INT_NOACTION;
+	}
+	DUK_HEAP_SET_INTERRUPT_RUNNING(thr->heap);
+
 	act = thr->callstack + thr->callstack_top - 1;
-	fun = (duk_hcompiledfunction *) act->func;
+
+	fun = (duk_hcompiledfunction *) DUK_ACT_GET_FUNC(act);
 	DUK_ASSERT(DUK_HOBJECT_HAS_COMPILEDFUNCTION((duk_hobject *) fun));
+
 	DUK_UNREF(fun);
 
-	ctr = DUK_HEAP_INTCTR_DEFAULT;
+#if defined(DUK_USE_EXEC_TIMEOUT_CHECK)
+	/*
+	 *  Execution timeout check
+	 */
 
-#if 0
-	/* XXX: cumulative instruction count example */
-	static int step_count = 0;
-	step_count += thr->heap->interrupt_init;
-	if (step_count >= 1000000L) {
+	if (DUK_USE_EXEC_TIMEOUT_CHECK(thr->heap->heap_udata)) {
 		/* Keep throwing an error whenever we get here.  The unusual values
 		 * are set this way because no instruction is ever executed, we just
 		 * throw an error until all try/catch/finally and other catchpoints
-		 * have been exhausted.
+		 * have been exhausted.  Duktape/C code gets control at each protected
+		 * call but whenever it enters back into Duktape the RangeError gets
+		 * raised.  User exec timeout check must consistently indicate a timeout
+		 * until we've fully bubbled out of Duktape.
 		 */
-		DUK_D(DUK_DPRINT("execution step limit reached, throwing a RangeError"));
-		thr->heap->interrupt_init = 0;
-		thr->heap->interrupt_counter = 0;
+		DUK_D(DUK_DPRINT("execution timeout, throwing a RangeError"));
+		thr->interrupt_init = 0;
 		thr->interrupt_counter = 0;
-		DUK_ERROR(thr, DUK_ERR_RANGE_ERROR, "execution step limit");
+		DUK_HEAP_CLEAR_INTERRUPT_RUNNING(thr->heap);
+		DUK_ERROR(thr, DUK_ERR_RANGE_ERROR, "execution timeout");
 	}
-#endif
+#endif  /* DUK_USE_EXEC_TIMEOUT_CHECK */
 
-#if 0
-	/* XXX: debugger integration: single step, breakpoint checks, etc */
-	if (0) {
+#if defined(DUK_USE_DEBUGGER_SUPPORT)
+	if (DUK_HEAP_IS_DEBUGGER_ATTACHED(thr->heap)) {
+		duk__interrupt_handle_debugger(thr, &immediate, &retval);
+		act = thr->callstack + thr->callstack_top - 1;  /* relookup if changed */
+	}
+#endif  /* DUK_USE_DEBUGGER_SUPPORT */
+
+	/*
+	 *  Update the interrupt counter
+	 */
+
+	if (immediate) {
 		/* Cause an interrupt after executing one instruction. */
 		ctr = 1;
 	}
-#endif
-
-	DUK_DDD(DUK_DDDPRINT("executor interrupt finished, cstop=%ld, pc=%ld, nextctr=%ld",
-	                     (long) thr->callstack_top, (long) act->pc, (long) ctr));
 
 	/* The counter value is one less than the init value: init value should
 	 * indicate how many instructions are executed before interrupt.  To
-	 * execute 1 instruction, counter must be 0.
+	 * execute 1 instruction (after interrupt handler return), counter must
+	 * be 0.
 	 */
-	thr->heap->interrupt_init = ctr;
-	thr->heap->interrupt_counter = ctr - 1;
+	DUK_ASSERT(ctr >= 1);
+	thr->interrupt_init = ctr;
 	thr->interrupt_counter = ctr - 1;
+	DUK_HEAP_CLEAR_INTERRUPT_RUNNING(thr->heap);
+
+	return retval;
 }
 #endif  /* DUK_USE_INTERRUPT_COUNTER */
 
 /*
+ *  Debugger handling for executor restart
+ *
+ *  Check for breakpoints, stepping, etc, and figure out if we should execute
+ *  in checked or normal mode.  Note that we can't do this when an activation
+ *  is created, because breakpoint status (and stepping status) may change
+ *  later, so we must recheck every time we're executing an activation.
+ */
+
+#if defined(DUK_USE_DEBUGGER_SUPPORT)
+DUK_LOCAL void duk__executor_recheck_debugger(duk_hthread *thr, duk_activation *act, duk_hcompiledfunction *fun) {
+	duk_heap *heap;
+	duk_tval *tv_tmp;
+	duk_hstring *filename;
+	duk_small_uint_t bp_idx;
+	duk_breakpoint **bp_active;
+
+	DUK_ASSERT(thr != NULL);
+	DUK_ASSERT(act != NULL);
+	DUK_ASSERT(fun != NULL);
+
+	heap = thr->heap;
+	bp_active = heap->dbg_breakpoints_active;
+	act->flags &= ~DUK_ACT_FLAG_BREAKPOINT_ACTIVE;
+
+	tv_tmp = duk_hobject_find_existing_entry_tval_ptr(thr->heap, (duk_hobject *) fun, DUK_HTHREAD_STRING_FILE_NAME(thr));
+	if (tv_tmp && DUK_TVAL_IS_STRING(tv_tmp)) {
+		filename = DUK_TVAL_GET_STRING(tv_tmp);
+
+		/* Figure out all active breakpoints.  A breakpoint is
+		 * considered active if the current function's fileName
+		 * matches the breakpoint's fileName, AND there is no
+		 * inner function that has matching line numbers
+		 * (otherwise a breakpoint would be triggered both
+		 * inside and outside of the inner function which would
+		 * be confusing).  Example:
+		 *
+		 *     function foo() {
+		 *         print('foo');
+		 *         function bar() {    <-.  breakpoints in these
+		 *             print('bar');     |  lines should not affect
+		 *         }                   <-'  foo() execution
+		 *         bar();
+		 *     }
+		 *
+		 * We need a few things that are only available when
+		 * debugger support is enabled: (1) a line range for
+		 * each function, and (2) access to the function
+		 * template to access the inner functions (and their
+		 * line ranges).
+		 *
+		 * It's important to have a narrow match for active
+		 * breakpoints so that we don't enter checked execution
+		 * when that's not necessary.  For instance, if we're
+		 * running inside a certain function and there's
+		 * breakpoint outside in (after the call site), we
+		 * don't want to slow down execution of the function.
+		 */
+
+		for (bp_idx = 0; bp_idx < heap->dbg_breakpoint_count; bp_idx++) {
+			duk_breakpoint *bp = heap->dbg_breakpoints + bp_idx;
+			duk_hobject **funcs, **funcs_end;
+			duk_hcompiledfunction *inner_fun;
+			duk_bool_t bp_match;
+
+			if (bp->filename == filename &&
+			    bp->line >= fun->start_line && bp->line <= fun->end_line) {
+				bp_match = 1;
+				DUK_DD(DUK_DDPRINT("breakpoint filename and line match: "
+				                   "%s:%ld vs. %s (line %ld vs. %ld-%ld)",
+				                   DUK_HSTRING_GET_DATA(bp->filename),
+				                   (long) bp->line,
+				                   DUK_HSTRING_GET_DATA(filename),
+				                   (long) bp->line,
+				                   (long) fun->start_line,
+				                   (long) fun->end_line));
+
+				funcs = DUK_HCOMPILEDFUNCTION_GET_FUNCS_BASE(thr->heap, fun);
+				funcs_end = DUK_HCOMPILEDFUNCTION_GET_FUNCS_END(thr->heap, fun);
+				while (funcs != funcs_end) {
+					inner_fun = (duk_hcompiledfunction *) *funcs;
+					DUK_ASSERT(DUK_HOBJECT_IS_COMPILEDFUNCTION((duk_hobject *) inner_fun));
+					if (bp->line >= inner_fun->start_line && bp->line <= inner_fun->end_line) {
+						DUK_DD(DUK_DDPRINT("inner function masks ('captures') breakpoint"));
+						bp_match = 0;
+						break;
+					}
+					funcs++;
+				}
+
+				if (bp_match) {
+					/* No need to check for size of bp_active list,
+					 * it's always larger than maximum number of
+					 * breakpoints.
+					 */
+					act->flags |= DUK_ACT_FLAG_BREAKPOINT_ACTIVE;
+					*bp_active = heap->dbg_breakpoints + bp_idx;
+					bp_active++;
+				}
+			}
+		}
+	}
+
+	*bp_active = NULL;  /* terminate */
+
+	DUK_DD(DUK_DDPRINT("ACTIVE BREAKPOINTS: %ld", (long) (bp_active - thr->heap->dbg_breakpoints_active)));
+
+	/* Force pause if we were doing "step into" in another activation. */
+	if (thr->heap->dbg_step_thread != NULL &&
+	    thr->heap->dbg_step_type == DUK_STEP_TYPE_INTO &&
+	    (thr->heap->dbg_step_thread != thr ||
+	     thr->heap->dbg_step_csindex != thr->callstack_top - 1)) {
+		DUK_D(DUK_DPRINT("STEP INTO ACTIVE, FORCE PAUSED"));
+		DUK_HEAP_SET_PAUSED(thr->heap);
+	}
+
+	/* Force interrupt right away if we're paused or in "checked mode".
+	 * Step out is handled by callstack unwind.
+	 */
+	if (act->flags & (DUK_ACT_FLAG_BREAKPOINT_ACTIVE) ||
+	    thr->heap->dbg_paused ||
+	    (thr->heap->dbg_step_type != DUK_STEP_TYPE_OUT &&
+	     thr->heap->dbg_step_csindex == thr->callstack_top - 1)) {
+		/* We'll need to interrupt early so recompute the init
+		 * counter to reflect the number of bytecode instructions
+		 * executed so that step counts for e.g. debugger rate
+		 * limiting are accurate.
+		 */
+		DUK_ASSERT(thr->interrupt_counter <= thr->interrupt_init);
+		thr->interrupt_init = thr->interrupt_init - thr->interrupt_counter;
+		thr->interrupt_counter = 0;
+	}
+}
+#endif  /* DUK_USE_DEBUGGER_SUPPORT */
+
+/*
  *  Ecmascript bytecode executor.
  *
  *  Resume execution for the current thread from its current activation.
@@ -51574,28 +69160,35 @@ static void duk__executor_interrupt(duk_hthread *thr) {
  *  setjmp() jmpbuf.
  *
  *  Ecmascript function calls and coroutine resumptions are handled
- *  internally without recursive C calls.  Other function calls are
- *  handled using duk_handle_call(), increasing C recursion depth.
- *
- *  There are many other tricky control flow situations, such as:
+ *  internally (by the outer executor function) without recursive C calls.
+ *  Other function calls are handled using duk_handle_call(), increasing
+ *  C recursion depth.
  *
- *    - Break and continue (fast and slow)
- *    - Return (fast and slow)
- *    - Error throwing
- *    - Thread resume and yield
+ *  Abrupt completions (= long control tranfers) are handled either
+ *  directly by reconfiguring relevant stacks and restarting execution,
+ *  or via a longjmp.  Longjmp-free handling is preferable for performance
+ *  (especially Emscripten performance), and is used for: break, continue,
+ *  and return.
  *
- *  For more detailed notes, see doc/execution.txt.
+ *  For more detailed notes, see doc/execution.rst.
  *
- *  Note: setjmp() and local variables have a nasty interaction,
- *  see execution.txt; non-volatile locals modified after setjmp()
- *  call are not guaranteed to keep their value.
+ *  Also see doc/code-issues.rst for discussion of setjmp(), longjmp(),
+ *  and volatile.
  */
 
-#define DUK__STRICT()       (DUK_HOBJECT_HAS_STRICT(&(fun)->obj))
-#define DUK__REG(x)         (thr->valstack_bottom[(x)])
-#define DUK__REGP(x)        (&thr->valstack_bottom[(x)])
-#define DUK__CONST(x)       (DUK_HCOMPILEDFUNCTION_GET_CONSTS_BASE(fun)[(x)])
-#define DUK__CONSTP(x)      (&DUK_HCOMPILEDFUNCTION_GET_CONSTS_BASE(fun)[(x)])
+/* Presence of 'fun' is config based, there's a marginal performance
+ * difference and the best option is architecture dependent.
+ */
+#if defined(DUK_USE_EXEC_FUN_LOCAL)
+#define DUK__FUN()          fun
+#else
+#define DUK__FUN()          ((duk_hcompiledfunction *) DUK_ACT_GET_FUNC((thr)->callstack + (thr)->callstack_top - 1))
+#endif
+#define DUK__STRICT()       (DUK_HOBJECT_HAS_STRICT((duk_hobject *) DUK__FUN()))
+#define DUK__REG(x)         (*(thr->valstack_bottom + (x)))
+#define DUK__REGP(x)        (thr->valstack_bottom + (x))
+#define DUK__CONST(x)       (*(consts + (x)))
+#define DUK__CONSTP(x)      (consts + (x))
 #define DUK__REGCONST(x)    ((x) < DUK_BC_REGLIMIT ? DUK__REG((x)) : DUK__CONST((x) - DUK_BC_REGLIMIT))
 #define DUK__REGCONSTP(x)   ((x) < DUK_BC_REGLIMIT ? DUK__REGP((x)) : DUK__CONSTP((x) - DUK_BC_REGLIMIT))
 
@@ -51609,178 +69202,230 @@ static void duk__executor_interrupt(duk_hthread *thr) {
 	} while (0)
 #endif
 
-void duk_js_execute_bytecode(duk_hthread *entry_thread) {
-	/* entry level info */
-	duk_size_t entry_callstack_top;
-	duk_int_t entry_call_recursion_depth;
-	duk_jmpbuf *entry_jmpbuf_ptr;
+#define DUK__SYNC_CURR_PC()  do { \
+		duk_activation *act; \
+		act = thr->callstack + thr->callstack_top - 1; \
+		act->curr_pc = curr_pc; \
+	} while (0)
+#define DUK__SYNC_AND_NULL_CURR_PC()  do { \
+		duk_activation *act; \
+		act = thr->callstack + thr->callstack_top - 1; \
+		act->curr_pc = curr_pc; \
+		thr->ptr_curr_pc = NULL; \
+	} while (0)
 
-	/* "hot" variables for interpretation -- not volatile, value not guaranteed in setjmp error handling */
-	duk_hthread *thr;             /* stable */
-	duk_activation *act;          /* semi-stable (ok as long as callstack not resized) */
-	duk_hcompiledfunction *fun;   /* stable */
-	duk_instr_t *bcode;           /* stable */
-	/* 'consts' is computed on-the-fly */
-	/* 'funcs' is quite rarely used, so no local for it */
+DUK_LOCAL void duk__handle_executor_error(duk_heap *heap,
+                                          duk_hthread *entry_thread,
+                                          duk_size_t entry_callstack_top,
+                                          duk_int_t entry_call_recursion_depth
+#if !defined(DUK_USE_CPP_EXCEPTIONS)
+                                          , duk_jmpbuf *entry_jmpbuf_ptr
+#endif
+                                          ) {
+	duk_small_uint_t lj_ret;
 
-	/* "hot" temps for interpretation -- not volatile, value not guaranteed in setjmp error handling */
-	duk_uint_fast32_t ins;  /* XXX: check performance impact on x64 between fast/non-fast variant */
+	/* Longjmp callers are required to sync-and-null thr->ptr_curr_pc
+	 * before longjmp.
+	 */
+	DUK_ASSERT(heap->curr_thread != NULL);
+	DUK_ASSERT(heap->curr_thread->ptr_curr_pc == NULL);
 
-	/* jmpbuf */
-	duk_jmpbuf jmpbuf;
+	/* XXX: signalling the need to shrink check (only if unwound) */
 
-#ifdef DUK_USE_INTERRUPT_COUNTER
-	duk_int_t int_ctr;
-#endif
+	/* Must be restored here to handle e.g. yields properly. */
+	heap->call_recursion_depth = entry_call_recursion_depth;
 
-#ifdef DUK_USE_ASSERTIONS
-	duk_size_t valstack_top_base;    /* valstack top, should match before interpreting each op (no leftovers) */
+#if !defined(DUK_USE_CPP_EXCEPTIONS)
+	/* Switch to caller's setjmp() catcher so that if an error occurs
+	 * during error handling, it is always propagated outwards instead
+	 * of causing an infinite loop in our own handler.
+	 */
+	heap->lj.jmpbuf_ptr = (duk_jmpbuf *) entry_jmpbuf_ptr;
 #endif
 
-	/* XXX: document assumptions on setjmp and volatile variables
-	 * (see duk_handle_call()).
-	 */
+	lj_ret = duk__handle_longjmp(heap->curr_thread, entry_thread, entry_callstack_top);
 
-	/*
-	 *  Preliminaries
-	 */
+	if (lj_ret == DUK__LONGJMP_RESTART) {
+		/* Restart bytecode execution, possibly with a changed thread. */
+		;
+	} else {
+		/* Rethrow error to calling state. */
+		DUK_ASSERT(lj_ret == DUK__LONGJMP_RETHROW);
 
-	DUK_ASSERT(entry_thread != NULL);
-	DUK_ASSERT_REFCOUNT_NONZERO_HEAPHDR((duk_heaphdr *) entry_thread);
-	DUK_ASSERT(entry_thread->callstack_top >= 1);  /* at least one activation, ours */
-	DUK_ASSERT((entry_thread->callstack + entry_thread->callstack_top - 1)->func != NULL);
-	DUK_ASSERT(DUK_HOBJECT_IS_COMPILEDFUNCTION((entry_thread->callstack + entry_thread->callstack_top - 1)->func));
+#if !defined(DUK_USE_CPP_EXCEPTIONS)
+		/* Longjmp handling has restored jmpbuf_ptr. */
+		DUK_ASSERT(heap->lj.jmpbuf_ptr == entry_jmpbuf_ptr);
+#endif
 
-	thr = entry_thread;
+		/* Thread may have changed, e.g. YIELD converted to THROW. */
+		duk_err_longjmp(heap->curr_thread);
+		DUK_UNREACHABLE();
+	}
+}
 
-	entry_callstack_top = thr->callstack_top;
-	entry_call_recursion_depth = thr->heap->call_recursion_depth;
-	entry_jmpbuf_ptr = thr->heap->lj.jmpbuf_ptr;
+/* Outer executor with setjmp/longjmp handling. */
+DUK_INTERNAL void duk_js_execute_bytecode(duk_hthread *exec_thr) {
+	/* Entry level info. */
+	duk_hthread *entry_thread;
+	duk_size_t entry_callstack_top;
+	duk_int_t entry_call_recursion_depth;
+#if !defined(DUK_USE_CPP_EXCEPTIONS)
+	duk_jmpbuf *entry_jmpbuf_ptr;
+	duk_jmpbuf jmpbuf;
+#endif
+	duk_heap *heap;
+
+	DUK_ASSERT(exec_thr != NULL);
+	DUK_ASSERT(exec_thr->heap != NULL);
+	DUK_ASSERT(exec_thr->heap->curr_thread != NULL);
+	DUK_ASSERT_REFCOUNT_NONZERO_HEAPHDR((duk_heaphdr *) exec_thr);
+	DUK_ASSERT(exec_thr->callstack_top >= 1);  /* at least one activation, ours */
+	DUK_ASSERT(DUK_ACT_GET_FUNC(exec_thr->callstack + exec_thr->callstack_top - 1) != NULL);
+	DUK_ASSERT(DUK_HOBJECT_IS_COMPILEDFUNCTION(DUK_ACT_GET_FUNC(exec_thr->callstack + exec_thr->callstack_top - 1)));
+
+	entry_thread = exec_thr;
+	heap = entry_thread->heap;
+	entry_callstack_top = entry_thread->callstack_top;
+	entry_call_recursion_depth = entry_thread->heap->call_recursion_depth;
+#if !defined(DUK_USE_CPP_EXCEPTIONS)
+	entry_jmpbuf_ptr = entry_thread->heap->lj.jmpbuf_ptr;
+#endif
 
 	/*
-	 *  Setjmp catchpoint setup.
-	 *
 	 *  Note: we currently assume that the setjmp() catchpoint is
 	 *  not re-entrant (longjmp() cannot be called more than once
 	 *  for a single setjmp()).
+	 *
+	 *  See doc/code-issues.rst for notes on variable assignment
+	 *  before and after setjmp().
 	 */
 
- reset_setjmp_catchpoint:
-
-	DUK_ASSERT(thr != NULL);
-	thr->heap->lj.jmpbuf_ptr = &jmpbuf;
-	DUK_ASSERT(thr->heap->lj.jmpbuf_ptr != NULL);
-
-	if (DUK_SETJMP(thr->heap->lj.jmpbuf_ptr->jb)) {
-		/*
-		 *  Note: any local variables accessed here must have their value
-		 *  assigned *before* the setjmp() call, OR they must be declared
-		 *  volatile.  Otherwise their value is not guaranteed to be correct.
-		 *
-		 *  'thr' might seem to be a risky variable because it is changed
-		 *  for yield and resume.  However, yield and resume are handled
-		 *  using longjmp()s.
-		 */
-
-		duk_small_uint_t lj_ret;
-
-		/* XXX: signalling the need to shrink check (only if unwound) */
-
-		DUK_DDD(DUK_DDDPRINT("longjmp caught by bytecode executor, thr=%p, curr_thread=%p",
-		                     (void *) thr, (void *) ((thr && thr->heap) ? thr->heap->curr_thread : NULL)));
-
-		/* must be restored here to handle e.g. yields properly */
-		thr->heap->call_recursion_depth = entry_call_recursion_depth;
-
-		/* Longjmp callers should not switch threads, the longjmp handler
-		 * does that (even for RESUME and YIELD).
-		 */
-
-		DUK_ASSERT(thr != NULL);
-		DUK_ASSERT(thr == thr->heap->curr_thread);
+	for (;;) {
+#if !defined(DUK_USE_CPP_EXCEPTIONS)
+		heap->lj.jmpbuf_ptr = &jmpbuf;
+		DUK_ASSERT(heap->lj.jmpbuf_ptr != NULL);
+#endif
 
-		/* Switch to caller's setjmp() catcher so that if an error occurs
-		 * during error handling, it is always propagated outwards instead
-		 * of causing an infinite loop in our own handler.
-		 */
+#if defined(DUK_USE_CPP_EXCEPTIONS)
+		try {
+#else
+		if (DUK_LIKELY(DUK_SETJMP(heap->lj.jmpbuf_ptr->jb) == 0)) {
+#endif
+			/* Execute bytecode until returned or longjmp(). */
+			duk__js_execute_bytecode_inner(entry_thread, entry_callstack_top);
 
-		DUK_DDD(DUK_DDDPRINT("restore jmpbuf_ptr: %p -> %p",
-		                     (void *) ((thr && thr->heap) ? thr->heap->lj.jmpbuf_ptr : NULL),
-		                     (void *) entry_jmpbuf_ptr));
-		thr->heap->lj.jmpbuf_ptr = entry_jmpbuf_ptr;
+#if !defined(DUK_USE_CPP_EXCEPTIONS)
+			/* Successful return: restore jmpbuf and return to caller. */
+			heap->lj.jmpbuf_ptr = (duk_jmpbuf *) entry_jmpbuf_ptr;
+#endif
 
-		lj_ret = duk__handle_longjmp(thr, entry_thread, entry_callstack_top);
+			return;
+#if defined(DUK_USE_CPP_EXCEPTIONS)
+		} catch (duk_internal_exception &exc) {
+#else
+		} else {
+#endif
+#if defined(DUK_USE_CPP_EXCEPTIONS)
+			DUK_UNREF(exc);
+#endif
+			DUK_DDD(DUK_DDDPRINT("longjmp caught by bytecode executor"));
 
-		if (lj_ret == DUK__LONGJMP_RESTART) {
-			/*
-			 *  Restart bytecode execution, possibly with a changed thread.
-			 */
-			thr = thr->heap->curr_thread;
-			goto reset_setjmp_catchpoint;
-		} else if (lj_ret == DUK__LONGJMP_RETHROW) {
-			/*
-			 *  Rethrow error to calling state.
-			 */
+			duk__handle_executor_error(heap,
+			                           entry_thread,
+			                           entry_callstack_top,
+			                           entry_call_recursion_depth
+#if !defined(DUK_USE_CPP_EXCEPTIONS)
+			                           , entry_jmpbuf_ptr
+#endif
+			                           );
+		}
+#if defined(DUK_USE_CPP_EXCEPTIONS)
+		catch (std::exception &exc) {
+			const char *what = exc.what();
+			if (!what) {
+				what = "unknown";
+			}
+			DUK_D(DUK_DPRINT("unexpected c++ std::exception (perhaps thrown by user code)"));
+			try {
+				DUK_ASSERT(heap->curr_thread != NULL);
+				DUK_ERROR(heap->curr_thread, DUK_ERR_API_ERROR, "caught invalid c++ std::exception '%s' (perhaps thrown by user code)", what);
+			} catch (duk_internal_exception exc) {
+				DUK_D(DUK_DPRINT("caught api error thrown from unexpected c++ std::exception"));
+				duk__handle_executor_error(heap,
+				                           entry_thread,
+				                           entry_callstack_top,
+				                           entry_call_recursion_depth
+#if !defined(DUK_USE_CPP_EXCEPTIONS)
+				                           , entry_jmpbuf_ptr
+#endif
+				                           );
+			}
+		} catch (...) {
+			DUK_D(DUK_DPRINT("unexpected c++ exception (perhaps thrown by user code)"));
+			try {
+				DUK_ASSERT(heap->curr_thread != NULL);
+				DUK_ERROR(heap->curr_thread, DUK_ERR_API_ERROR, "caught invalid c++ exception (perhaps thrown by user code)");
+			} catch (duk_internal_exception exc) {
+				DUK_D(DUK_DPRINT("caught api error thrown from unexpected c++ exception"));
+				duk__handle_executor_error(heap,
+				                           entry_thread,
+				                           entry_callstack_top,
+				                           entry_call_recursion_depth
+#if !defined(DUK_USE_CPP_EXCEPTIONS)
+				                           , entry_jmpbuf_ptr
+#endif
+				                           );
+			}
+		}
+#endif
+	}
 
-			/* thread may have changed (e.g. YIELD converted to THROW) */
-			thr = thr->heap->curr_thread;
+	DUK_UNREACHABLE();
+}
 
-			DUK_ASSERT(thr->heap->lj.jmpbuf_ptr == entry_jmpbuf_ptr);
+/* Inner executor, performance critical. */
+DUK_LOCAL DUK_NOINLINE void duk__js_execute_bytecode_inner(duk_hthread *entry_thread, duk_size_t entry_callstack_top) {
+	/* Current PC, accessed by other functions through thr->ptr_to_curr_pc.
+	 * Critical for performance.  It would be safest to make this volatile,
+	 * but that eliminates performance benefits; aliasing guarantees
+	 * should be enough though.
+	 */
+	duk_instr_t *curr_pc;         /* bytecode has a stable pointer */
 
-			duk_err_longjmp(thr);
-			DUK_UNREACHABLE();
-		} else {
-			/*
-			 *  Return from bytecode executor with a return value.
-			 */
-			DUK_ASSERT(lj_ret == DUK__LONGJMP_FINISHED);
+	/* Hot variables for interpretation.  Critical for performance,
+	 * but must add sparingly to minimize register shuffling.
+	 */
+	duk_hthread *thr;             /* stable */
+	duk_tval *consts;             /* stable */
+	duk_uint_fast32_t ins;
+	/* 'funcs' is quite rarely used, so no local for it */
+#if defined(DUK_USE_EXEC_FUN_LOCAL)
+	duk_hcompiledfunction *fun;
+#else
+	/* 'fun' is quite rarely used, so no local for it */
+#endif
 
-			/* XXX: return assertions for valstack, callstack, catchstack */
+#ifdef DUK_USE_INTERRUPT_COUNTER
+	duk_int_t int_ctr;
+#endif
 
-			DUK_ASSERT(thr->heap->lj.jmpbuf_ptr == entry_jmpbuf_ptr);
-			return;
-		}
-		DUK_UNREACHABLE();
-	}
+#ifdef DUK_USE_ASSERTIONS
+	duk_size_t valstack_top_base;    /* valstack top, should match before interpreting each op (no leftovers) */
+#endif
 
 	/*
 	 *  Restart execution by reloading thread state.
 	 *
 	 *  Note that 'thr' and any thread configuration may have changed,
-	 *  so all local variables are suspect.
+	 *  so all local variables are suspect and we need to reinitialize.
 	 *
 	 *  The number of local variables should be kept to a minimum: if
 	 *  the variables are spilled, they will need to be loaded from
 	 *  memory anyway.
-	 */
-
- restart_execution:
-
-	/* Lookup current thread; note that we can use 'thr' for this even
-	 * though it is not the current thread (any thread will do).
-	 */
-	thr = thr->heap->curr_thread;
-#ifdef DUK_USE_INTERRUPT_COUNTER
-	thr->interrupt_counter = thr->heap->interrupt_counter;
-#endif
-
-	DUK_ASSERT(thr != NULL);
-	DUK_ASSERT(thr->callstack_top >= 1);
-	DUK_ASSERT((thr->callstack + thr->callstack_top - 1)->func != NULL);
-	DUK_ASSERT(DUK_HOBJECT_IS_COMPILEDFUNCTION((thr->callstack + thr->callstack_top - 1)->func));
-
-	/* XXX: shrink check flag? */
-
-	/* assume that thr->valstack_bottom has been set-up before getting here */
-	act = thr->callstack + thr->callstack_top - 1;
-	fun = (duk_hcompiledfunction *) act->func;
-	bcode = DUK_HCOMPILEDFUNCTION_GET_CODE_BASE(fun);
-
-	DUK_ASSERT(thr->valstack_top - thr->valstack_bottom >= fun->nregs);
-	DUK_ASSERT(thr->valstack_top - thr->valstack_bottom == fun->nregs);  /* XXX: correct? */
-
-	/*
-	 *  Bytecode interpreter.
+	 *
+	 *  Any 'goto restart_execution;' code path in opcode dispatch must
+	 *  ensure 'curr_pc' is synced back to act->curr_pc before the goto
+	 *  takes place.
 	 *
 	 *  The interpreter must be very careful with memory pointers, as
 	 *  many pointers are not guaranteed to be 'stable' and may be
@@ -51798,43 +69443,83 @@ void duk_js_execute_bytecode(duk_hthread *entry_thread) {
 	 *      is not changed (reallocated by growing or shrinking), or
 	 *      by any garbage collection invocation (through finalizers)
 	 *    - Note in particular that ANY DECREF can invalidate the
-	 *      activation pointer
+	 *      activation pointer, so for the most part a fresh lookup
+	 *      is required
 	 *
 	 *  The following are not assumed to have stable pointers at all:
 	 *    - the value stack (registers) of the current thread
 	 *    - the catch stack of the current thread
 	 *
-	 *  See execution.txt for discussion.
+	 *  See execution.rst for discussion.
 	 */
 
+ restart_execution:
+
+	/* Lookup current thread; use the stable 'entry_thread' for this to
+	 * avoid clobber warnings.  Any valid, reachable 'thr' value would be
+	 * fine for this, so using 'entry_thread' is just to silence warnings.
+	 */
+	thr = entry_thread->heap->curr_thread;
 	DUK_ASSERT(thr != NULL);
-	DUK_ASSERT(act != NULL);
-	DUK_ASSERT(fun != NULL);
-	DUK_ASSERT(bcode != NULL);
+	DUK_ASSERT(thr->callstack_top >= 1);
+	DUK_ASSERT(DUK_ACT_GET_FUNC(thr->callstack + thr->callstack_top - 1) != NULL);
+	DUK_ASSERT(DUK_HOBJECT_IS_COMPILEDFUNCTION(DUK_ACT_GET_FUNC(thr->callstack + thr->callstack_top - 1)));
+
+	thr->ptr_curr_pc = &curr_pc;
 
-	DUK_DD(DUK_DDPRINT("restarting execution, thr %p, act %p (idx %ld), fun %p, bcode %p, "
+	/* Relookup and initialize dispatch loop variables.  Debugger check. */
+	{
+		duk_activation *act;
+#if !defined(DUK_USE_EXEC_FUN_LOCAL)
+		duk_hcompiledfunction *fun;
+#endif
+
+		/* Assume interrupt init/counter are properly initialized here. */
+		/* Assume that thr->valstack_bottom has been set-up before getting here. */
+
+		act = thr->callstack + thr->callstack_top - 1;
+		fun = (duk_hcompiledfunction *) DUK_ACT_GET_FUNC(act);
+		DUK_ASSERT(fun != NULL);
+		DUK_ASSERT(thr->valstack_top - thr->valstack_bottom == fun->nregs);
+		consts = DUK_HCOMPILEDFUNCTION_GET_CONSTS_BASE(thr->heap, fun);
+		DUK_ASSERT(consts != NULL);
+
+#if defined(DUK_USE_DEBUGGER_SUPPORT)
+		if (DUK_HEAP_IS_DEBUGGER_ATTACHED(thr->heap) && !thr->heap->dbg_processing) {
+			thr->heap->dbg_processing = 1;
+			duk__executor_recheck_debugger(thr, act, fun);
+			act = thr->callstack + thr->callstack_top - 1;  /* relookup after side effects */
+			thr->heap->dbg_processing = 0;
+		}
+#endif  /* DUK_USE_DEBUGGER_SUPPORT */
+
+#ifdef DUK_USE_ASSERTIONS
+		valstack_top_base = (duk_size_t) (thr->valstack_top - thr->valstack);
+#endif
+
+		/* Set up curr_pc for opcode dispatch. */
+		curr_pc = act->curr_pc;
+	}
+
+	DUK_DD(DUK_DDPRINT("restarting execution, thr %p, act idx %ld, fun %p,"
 	                   "consts %p, funcs %p, lev %ld, regbot %ld, regtop %ld, catchstack_top=%ld, "
 	                   "preventcount=%ld",
 	                   (void *) thr,
-	                   (void *) act,
 	                   (long) (thr->callstack_top - 1),
-	                   (void *) fun,
-	                   (void *) bcode,
-	                   (void *) DUK_HCOMPILEDFUNCTION_GET_CONSTS_BASE(fun),
-	                   (void *) DUK_HCOMPILEDFUNCTION_GET_FUNCS_BASE(fun),
+	                   (void *) DUK__FUN(),
+	                   (void *) DUK_HCOMPILEDFUNCTION_GET_CONSTS_BASE(thr->heap, DUK__FUN()),
+	                   (void *) DUK_HCOMPILEDFUNCTION_GET_FUNCS_BASE(thr->heap, DUK__FUN()),
 	                   (long) (thr->callstack_top - 1),
 	                   (long) (thr->valstack_bottom - thr->valstack),
 	                   (long) (thr->valstack_top - thr->valstack),
 	                   (long) thr->catchstack_top,
 	                   (long) thr->callstack_preventcount));
 
-#ifdef DUK_USE_ASSERTIONS
-	valstack_top_base = (duk_size_t) (thr->valstack_top - thr->valstack);
-#endif
+	/* Dispatch loop. */
 
 	for (;;) {
 		DUK_ASSERT(thr->callstack_top >= 1);
-		DUK_ASSERT(thr->valstack_top - thr->valstack_bottom == fun->nregs);
+		DUK_ASSERT(thr->valstack_top - thr->valstack_bottom == DUK__FUN()->nregs);
 		DUK_ASSERT((duk_size_t) (thr->valstack_top - thr->valstack) == valstack_top_base);
 
 		/* Executor interrupt counter check, used to implement breakpoints,
@@ -51843,42 +69528,84 @@ void duk_js_execute_bytecode(duk_hthread *entry_thread) {
 		 * as fast as possible.  The counter is copied back to the heap struct
 		 * whenever a thread switch occurs by the DUK_HEAP_SWITCH_THREAD() macro.
 		 */
-#ifdef DUK_USE_INTERRUPT_COUNTER
+#if defined(DUK_USE_INTERRUPT_COUNTER)
 		int_ctr = thr->interrupt_counter;
 		if (DUK_LIKELY(int_ctr > 0)) {
 			thr->interrupt_counter = int_ctr - 1;
 		} else {
 			/* Trigger at zero or below */
-			duk__executor_interrupt(thr);
-		}
+			duk_small_uint_t exec_int_ret;
+
+			/* Write curr_pc back for the debugger. */
+			DUK_ASSERT(thr->callstack_top > 0);
+			{
+				duk_activation *act;
+				act = thr->callstack + thr->callstack_top - 1;
+				act->curr_pc = (duk_instr_t *) curr_pc;
+			}
+
+			/* Force restart caused by a function return; must recheck
+			 * debugger breakpoints before checking line transitions,
+			 * see GH-303.  Restart and then handle interrupt_counter
+			 * zero again.
+			 */
+#if defined(DUK_USE_DEBUGGER_SUPPORT)
+			if (thr->heap->dbg_force_restart) {
+				DUK_DD(DUK_DDPRINT("dbg_force_restart flag forced restart execution"));  /* GH-303 */
+				thr->heap->dbg_force_restart = 0;
+				goto restart_execution;
+			}
 #endif
 
-		/* Because ANY DECREF potentially invalidates 'act' now (through
-		 * finalization), we need to re-lookup 'act' in almost every case.
-		 *
-		 * XXX: future work for performance optimization:
-		 * This is not nice; it would be nice if the program counter was a
-		 * behind a stable pointer.  For instance, put a raw bytecode pointer
-		 * into duk_hthread struct (not into the callstack); since bytecode
-		 * has a stable pointer this would work nicely.  Whenever a call is
-		 * made, the bytecode pointer could be backed up as an integer index
-		 * to the calling activation.  Perhaps add a macro for setting up a
-		 * new activation (same as for setting up / switching threads)?
+			exec_int_ret = duk__executor_interrupt(thr);
+			if (exec_int_ret == DUK__INT_RESTART) {
+				/* curr_pc synced back above */
+				goto restart_execution;
+			}
+		}
+#endif  /* DUK_USE_INTERRUPT_COUNTER */
+#if defined(DUK_USE_INTERRUPT_COUNTER) && defined(DUK_USE_DEBUG)
+		/* For cross-checking during development: ensure dispatch count
+		 * matches cumulative interrupt counter init value sums.
 		 */
+		thr->heap->inst_count_exec++;
+#endif
 
-		act = thr->callstack + thr->callstack_top - 1;
-		DUK_ASSERT(bcode + act->pc >= DUK_HCOMPILEDFUNCTION_GET_CODE_BASE(fun));
-		DUK_ASSERT(bcode + act->pc < DUK_HCOMPILEDFUNCTION_GET_CODE_END(fun));
+#if defined(DUK_USE_ASSERTIONS) || defined(DUK_USE_DEBUG)
+		{
+			duk_activation *act;
+			act = thr->callstack + thr->callstack_top - 1;
+			DUK_ASSERT(curr_pc >= DUK_HCOMPILEDFUNCTION_GET_CODE_BASE(thr->heap, DUK__FUN()));
+			DUK_ASSERT(curr_pc < DUK_HCOMPILEDFUNCTION_GET_CODE_END(thr->heap, DUK__FUN()));
+			DUK_UNREF(act);  /* if debugging disabled */
+
+			DUK_DDD(DUK_DDDPRINT("executing bytecode: pc=%ld, ins=0x%08lx, op=%ld, valstack_top=%ld/%ld, nregs=%ld  -->  %!I",
+			                     (long) (curr_pc - DUK_HCOMPILEDFUNCTION_GET_CODE_BASE(thr->heap, DUK__FUN())),
+			                     (unsigned long) *curr_pc,
+			                     (long) DUK_DEC_OP(*curr_pc),
+			                     (long) (thr->valstack_top - thr->valstack),
+			                     (long) (thr->valstack_end - thr->valstack),
+			                     (long) (DUK__FUN() ? DUK__FUN()->nregs : -1),
+			                     (duk_instr_t) *curr_pc));
+		}
+#endif
 
-		DUK_DDD(DUK_DDDPRINT("executing bytecode: pc=%ld ins=0x%08lx, op=%ld, valstack_top=%ld/%ld  -->  %!I",
-		                     (long) act->pc,
-		                     (unsigned long) bcode[act->pc],
-		                     (long) DUK_DEC_OP(bcode[act->pc]),
-		                     (long) (thr->valstack_top - thr->valstack),
-		                     (long) (thr->valstack_end - thr->valstack),
-		                     (duk_instr_t) bcode[act->pc]));
+#if defined(DUK_USE_ASSERTIONS)
+		/* Quite heavy assert: check valstack policy.  Improper
+		 * shuffle instructions can write beyond valstack_top/end
+		 * so this check catches them in the act.
+		 */
+		{
+			duk_tval *tv;
+			tv = thr->valstack_top;
+			while (tv != thr->valstack_end) {
+				DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(tv));
+				tv++;
+			}
+		}
+#endif
 
-		ins = bcode[act->pc++];
+		ins = *curr_pc++;
 
 		/* Typing: use duk_small_(u)int_fast_t when decoding small
 		 * opcode fields (op, A, B, C) and duk_(u)int_fast_t when
@@ -51902,60 +69629,55 @@ void duk_js_execute_bytecode(duk_hthread *entry_thread) {
 		case DUK_OP_LDREG: {
 			duk_small_uint_fast_t a;
 			duk_uint_fast_t bc;
-			duk_tval tv_tmp;
 			duk_tval *tv1, *tv2;
 
 			a = DUK_DEC_A(ins); tv1 = DUK__REGP(a);
 			bc = DUK_DEC_BC(ins); tv2 = DUK__REGP(bc);
-			DUK_TVAL_SET_TVAL(&tv_tmp, tv1);
-			DUK_TVAL_SET_TVAL(tv1, tv2);
-			DUK_TVAL_INCREF(thr, tv1);
-			DUK_TVAL_DECREF(thr, &tv_tmp);  /* side effects */
+			DUK_TVAL_SET_TVAL_UPDREF_FAST(thr, tv1, tv2);  /* side effects */
 			break;
 		}
 
 		case DUK_OP_STREG: {
 			duk_small_uint_fast_t a;
 			duk_uint_fast_t bc;
-			duk_tval tv_tmp;
 			duk_tval *tv1, *tv2;
 
 			a = DUK_DEC_A(ins); tv1 = DUK__REGP(a);
 			bc = DUK_DEC_BC(ins); tv2 = DUK__REGP(bc);
-			DUK_TVAL_SET_TVAL(&tv_tmp, tv2);
-			DUK_TVAL_SET_TVAL(tv2, tv1);
-			DUK_TVAL_INCREF(thr, tv2);
-			DUK_TVAL_DECREF(thr, &tv_tmp);  /* side effects */
+			DUK_TVAL_SET_TVAL_UPDREF_FAST(thr, tv2, tv1);  /* side effects */
 			break;
 		}
 
 		case DUK_OP_LDCONST: {
 			duk_small_uint_fast_t a;
 			duk_uint_fast_t bc;
-			duk_tval tv_tmp;
 			duk_tval *tv1, *tv2;
 
 			a = DUK_DEC_A(ins); tv1 = DUK__REGP(a);
 			bc = DUK_DEC_BC(ins); tv2 = DUK__CONSTP(bc);
-			DUK_TVAL_SET_TVAL(&tv_tmp, tv1);
-			DUK_TVAL_SET_TVAL(tv1, tv2);
-			DUK_TVAL_INCREF(thr, tv2);  /* may be e.g. string */
-			DUK_TVAL_DECREF(thr, &tv_tmp);  /* side effects */
+			DUK_TVAL_SET_TVAL_UPDREF_FAST(thr, tv1, tv2);  /* side effects */
 			break;
 		}
 
 		case DUK_OP_LDINT: {
 			duk_small_uint_fast_t a;
 			duk_int_fast_t bc;
-			duk_tval tv_tmp;
 			duk_tval *tv1;
+#if defined(DUK_USE_FASTINT)
+			duk_int32_t val;
+#else
 			duk_double_t val;
+#endif
 
+#if defined(DUK_USE_FASTINT)
+			a = DUK_DEC_A(ins); tv1 = DUK__REGP(a);
+			bc = DUK_DEC_BC(ins); val = (duk_int32_t) (bc - DUK_BC_LDINT_BIAS);
+			DUK_TVAL_SET_FASTINT_I32_UPDREF(thr, tv1, val);  /* side effects */
+#else
 			a = DUK_DEC_A(ins); tv1 = DUK__REGP(a);
 			bc = DUK_DEC_BC(ins); val = (duk_double_t) (bc - DUK_BC_LDINT_BIAS);
-			DUK_TVAL_SET_TVAL(&tv_tmp, tv1);
-			DUK_TVAL_SET_NUMBER(tv1, val);
-			DUK_TVAL_DECREF(thr, &tv_tmp);  /* side effects */
+			DUK_TVAL_SET_NUMBER_UPDREF(thr, tv1, val);  /* side effects */
+#endif
 			break;
 		}
 
@@ -51964,13 +69686,22 @@ void duk_js_execute_bytecode(duk_hthread *entry_thread) {
 			duk_tval *tv1;
 			duk_double_t val;
 
+			/* LDINTX is not necessarily in FASTINT range, so
+			 * no fast path for now.
+			 *
+			 * XXX: perhaps restrict LDINTX to fastint range, wider
+			 * range very rarely needed.
+			 */
+
 			a = DUK_DEC_A(ins); tv1 = DUK__REGP(a);
-			if (!DUK_TVAL_IS_NUMBER(tv1)) {
-				DUK__INTERNAL_ERROR("LDINTX target not a number");
-			}
+			DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv1));
 			val = DUK_TVAL_GET_NUMBER(tv1) * ((duk_double_t) (1L << DUK_BC_LDINTX_SHIFT)) +
 			      (duk_double_t) DUK_DEC_BC(ins);
+#if defined(DUK_USE_FASTINT)
+			DUK_TVAL_SET_NUMBER_CHKFAST(tv1, val);
+#else
 			DUK_TVAL_SET_NUMBER(tv1, val);
+#endif
 			break;
 		}
 
@@ -51989,17 +69720,13 @@ void duk_js_execute_bytecode(duk_hthread *entry_thread) {
 			 */
 
 			a = DUK_DEC_A(ins); tv1 = DUK__REGP(a);
-			if (!DUK_TVAL_IS_OBJECT(tv1)) {
-				DUK__INTERNAL_ERROR("MPUTOBJ target not an object");
-			}
+			DUK_ASSERT(DUK_TVAL_IS_OBJECT(tv1));
 			obj = DUK_TVAL_GET_OBJECT(tv1);
 
 			idx = (duk_uint_fast_t) DUK_DEC_B(ins);
 			if (DUK_DEC_OP(ins) == DUK_OP_MPUTOBJI) {
 				duk_tval *tv_ind = DUK__REGP(idx);
-				if (!DUK_TVAL_IS_NUMBER(tv_ind)) {
-					DUK__INTERNAL_ERROR("MPUTOBJI target is not a number");
-				}
+				DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv_ind));
 				idx = (duk_uint_fast_t) DUK_TVAL_GET_NUMBER(tv_ind);
 			}
 
@@ -52019,11 +69746,9 @@ void duk_js_execute_bytecode(duk_hthread *entry_thread) {
 				/* XXX: faster initialization (direct access or better primitives) */
 
 				duk_push_tval(ctx, DUK__REGP(idx));
-				if (!duk_is_string(ctx, -1)) {
-					DUK__INTERNAL_ERROR("MPUTOBJ key not a string");
-				}
+				DUK_ASSERT(duk_is_string(ctx, -1));
 				duk_push_tval(ctx, DUK__REGP(idx + 1));  /* -> [... obj key value] */
-				duk_def_prop_wec(ctx, -3);               /* -> [... obj] */
+				duk_xdef_prop_wec(ctx, -3);              /* -> [... obj] */
 
 				count--;
 				idx += 2;
@@ -52049,17 +69774,14 @@ void duk_js_execute_bytecode(duk_hthread *entry_thread) {
 			 */
 
 			a = DUK_DEC_A(ins); tv1 = DUK__REGP(a);
-			if (!DUK_TVAL_IS_OBJECT(tv1)) {
-				DUK__INTERNAL_ERROR("MPUTARR target not an object");
-			}
+			DUK_ASSERT(DUK_TVAL_IS_OBJECT(tv1));
 			obj = DUK_TVAL_GET_OBJECT(tv1);
+			DUK_ASSERT(obj != NULL);
 
 			idx = (duk_uint_fast_t) DUK_DEC_B(ins);
 			if (DUK_DEC_OP(ins) == DUK_OP_MPUTARRI) {
 				duk_tval *tv_ind = DUK__REGP(idx);
-				if (!DUK_TVAL_IS_NUMBER(tv_ind)) {
-					DUK__INTERNAL_ERROR("MPUTARRI target is not a number");
-				}
+				DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv_ind));
 				idx = (duk_uint_fast_t) DUK_TVAL_GET_NUMBER(tv_ind);
 			}
 
@@ -52074,30 +69796,27 @@ void duk_js_execute_bytecode(duk_hthread *entry_thread) {
 #endif
 
 			tv1 = DUK__REGP(idx);
-			if (!DUK_TVAL_IS_NUMBER(tv1)) {
-				DUK__INTERNAL_ERROR("MPUTARR start index not a number");
-			}
+			DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv1));
 			arr_idx = (duk_uint32_t) DUK_TVAL_GET_NUMBER(tv1);
 			idx++;
 
 			duk_push_hobject(ctx, obj);
 
 			while (count > 0) {
-				/* duk_def_prop() will define an own property without any array
+				/* duk_xdef_prop() will define an own property without any array
 				 * special behaviors.  We'll need to set the array length explicitly
 				 * in the end.  For arrays with elisions, the compiler will emit an
 				 * explicit SETALEN which will update the length.
 				 */
 
-				/*
-				 * XXX: because we're dealing with 'own' properties of a fresh array,
+				/* XXX: because we're dealing with 'own' properties of a fresh array,
 				 * the array initializer should just ensure that the array has a large
 				 * enough array part and write the values directly into array part,
 				 * and finally set 'length' manually in the end (as already happens now).
 				 */
 
 				duk_push_tval(ctx, DUK__REGP(idx));          /* -> [... obj value] */
-				duk_def_prop_index_wec(ctx, -2, arr_idx);    /* -> [... obj] */
+				duk_xdef_prop_index_wec(ctx, -2, arr_idx);   /* -> [... obj] */
 
 				/* XXX: could use at least one fewer loop counters */
 				count--;
@@ -52128,11 +69847,15 @@ void duk_js_execute_bytecode(duk_hthread *entry_thread) {
 			 * C -> num args (N)
 			 */
 
-			/* Note: duk_new() will call the constuctor using duk_handle_call().
+			/* duk_new() will call the constuctor using duk_handle_call().
 			 * A constructor call prevents a yield from inside the constructor,
 			 * even if the constructor is an Ecmascript function.
 			 */
 
+			/* Don't need to sync curr_pc here; duk_new() will do that
+			 * when it augments the created error.
+			 */
+
 			/* XXX: unnecessary copying of values?  Just set 'top' to
 			 * b + c, and let the return handling fix up the stack frame?
 			 */
@@ -52140,9 +69863,7 @@ void duk_js_execute_bytecode(duk_hthread *entry_thread) {
 			idx = (duk_uint_fast_t) DUK_DEC_B(ins);
 			if (DUK_DEC_OP(ins) == DUK_OP_NEWI) {
 				duk_tval *tv_ind = DUK__REGP(idx);
-				if (!DUK_TVAL_IS_NUMBER(tv_ind)) {
-					DUK__INTERNAL_ERROR("NEWI target is not a number");
-				}
+				DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv_ind));
 				idx = (duk_uint_fast_t) DUK_TVAL_GET_NUMBER(tv_ind);
 			}
 
@@ -52162,6 +69883,11 @@ void duk_js_execute_bytecode(duk_hthread *entry_thread) {
 			duk_new(ctx, (duk_idx_t) c);  /* [... constructor arg1 ... argN] -> [retval] */
 			DUK_DDD(DUK_DDDPRINT("NEW -> %!iT", (duk_tval *) duk_get_tval(ctx, -1)));
 			duk_replace(ctx, (duk_idx_t) idx);
+
+			/* When debugger is enabled, we need to recheck the activation
+			 * status after returning.  This is now handled by call handling
+			 * and heap->dbg_force_restart.
+			 */
 			break;
 		}
 
@@ -52218,9 +69944,7 @@ void duk_js_execute_bytecode(duk_hthread *entry_thread) {
 			idx = (duk_uint_fast_t) DUK_DEC_A(ins);
 			if (DUK_DEC_OP(ins) == DUK_OP_CSREGI) {
 				duk_tval *tv_ind = DUK__REGP(idx);
-				if (!DUK_TVAL_IS_NUMBER(tv_ind)) {
-					DUK__INTERNAL_ERROR("CSREGI target is not a number");
-				}
+				DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv_ind));
 				idx = (duk_uint_fast_t) DUK_TVAL_GET_NUMBER(tv_ind);
 			}
 
@@ -52241,18 +69965,18 @@ void duk_js_execute_bytecode(duk_hthread *entry_thread) {
 
 		case DUK_OP_GETVAR: {
 			duk_context *ctx = (duk_context *) thr;
+			duk_activation *act;
 			duk_small_uint_fast_t a = DUK_DEC_A(ins);
 			duk_uint_fast_t bc = DUK_DEC_BC(ins);
 			duk_tval *tv1;
 			duk_hstring *name;
 
 			tv1 = DUK__CONSTP(bc);
-			if (!DUK_TVAL_IS_STRING(tv1)) {
-				DUK_DDD(DUK_DDDPRINT("GETVAR not a string: %!T", (duk_tval *) tv1));
-				DUK__INTERNAL_ERROR("GETVAR name not a string");
-			}
+			DUK_ASSERT(DUK_TVAL_IS_STRING(tv1));
 			name = DUK_TVAL_GET_STRING(tv1);
+			DUK_ASSERT(name != NULL);
 			DUK_DDD(DUK_DDDPRINT("GETVAR: '%!O'", (duk_heaphdr *) name));
+			act = thr->callstack + thr->callstack_top - 1;
 			(void) duk_js_getvar_activation(thr, act, name, 1 /*throw*/);  /* -> [... val this] */
 
 			duk_pop(ctx);  /* 'this' binding is not needed here */
@@ -52261,27 +69985,29 @@ void duk_js_execute_bytecode(duk_hthread *entry_thread) {
 		}
 
 		case DUK_OP_PUTVAR: {
+			duk_activation *act;
 			duk_small_uint_fast_t a = DUK_DEC_A(ins);
 			duk_uint_fast_t bc = DUK_DEC_BC(ins);
 			duk_tval *tv1;
 			duk_hstring *name;
 
 			tv1 = DUK__CONSTP(bc);
-			if (!DUK_TVAL_IS_STRING(tv1)) {
-				DUK__INTERNAL_ERROR("PUTVAR name not a string");
-			}
+			DUK_ASSERT(DUK_TVAL_IS_STRING(tv1));
 			name = DUK_TVAL_GET_STRING(tv1);
+			DUK_ASSERT(name != NULL);
 
 			/* XXX: putvar takes a duk_tval pointer, which is awkward and
 			 * should be reworked.
 			 */
 
 			tv1 = DUK__REGP(a);  /* val */
+			act = thr->callstack + thr->callstack_top - 1;
 			duk_js_putvar_activation(thr, act, name, tv1, DUK__STRICT());
 			break;
 		}
 
 		case DUK_OP_DECLVAR: {
+			duk_activation *act;
 			duk_context *ctx = (duk_context *) thr;
 			duk_small_uint_fast_t a = DUK_DEC_A(ins);
 			duk_small_uint_fast_t b = DUK_DEC_B(ins);
@@ -52293,10 +70019,9 @@ void duk_js_execute_bytecode(duk_hthread *entry_thread) {
 			duk_bool_t is_undef_value;
 
 			tv1 = DUK__REGCONSTP(b);
-			if (!DUK_TVAL_IS_STRING(tv1)) {
-				DUK__INTERNAL_ERROR("DECLVAR name not a string");
-			}
+			DUK_ASSERT(DUK_TVAL_IS_STRING(tv1));
 			name = DUK_TVAL_GET_STRING(tv1);
+			DUK_ASSERT(name != NULL);
 
 			is_undef_value = ((a & DUK_BC_DECLVAR_FLAG_UNDEF_VALUE) != 0);
 			is_func_decl = ((a & DUK_BC_DECLVAR_FLAG_FUNC_DECL) != 0);
@@ -52317,6 +70042,7 @@ void duk_js_execute_bytecode(duk_hthread *entry_thread) {
 			}
 			tv1 = duk_get_tval(ctx, -1);
 
+			act = thr->callstack + thr->callstack_top - 1;
 			if (duk_js_declvar_activation(thr, act, name, tv1, prop_flags, is_func_decl)) {
 				/* already declared, must update binding value */
 				tv1 = duk_get_tval(ctx, -1);
@@ -52328,6 +70054,7 @@ void duk_js_execute_bytecode(duk_hthread *entry_thread) {
 		}
 
 		case DUK_OP_DELVAR: {
+			duk_activation *act;
 			duk_context *ctx = (duk_context *) thr;
 			duk_small_uint_fast_t a = DUK_DEC_A(ins);
 			duk_small_uint_fast_t b = DUK_DEC_B(ins);
@@ -52336,11 +70063,11 @@ void duk_js_execute_bytecode(duk_hthread *entry_thread) {
 			duk_bool_t rc;
 
 			tv1 = DUK__REGCONSTP(b);
-			if (!DUK_TVAL_IS_STRING(tv1)) {
-				DUK__INTERNAL_ERROR("DELVAR name not a string");
-			}
+			DUK_ASSERT(DUK_TVAL_IS_STRING(tv1));
 			name = DUK_TVAL_GET_STRING(tv1);
+			DUK_ASSERT(name != NULL);
 			DUK_DDD(DUK_DDDPRINT("DELVAR '%!O'", (duk_heaphdr *) name));
+			act = thr->callstack + thr->callstack_top - 1;
 			rc = duk_js_delvar_activation(thr, act, name);
 
 			duk_push_boolean(ctx, rc);
@@ -52360,16 +70087,17 @@ void duk_js_execute_bytecode(duk_hthread *entry_thread) {
 			 */
 
 			duk_context *ctx = (duk_context *) thr;
+			duk_activation *act;
 			duk_small_uint_fast_t b = DUK_DEC_B(ins);
 			duk_uint_fast_t idx;
 			duk_tval *tv1;
 			duk_hstring *name;
 
 			tv1 = DUK__REGCONSTP(b);
-			if (!DUK_TVAL_IS_STRING(tv1)) {
-				DUK__INTERNAL_ERROR("CSVAR name not a string");
-			}
+			DUK_ASSERT(DUK_TVAL_IS_STRING(tv1));
 			name = DUK_TVAL_GET_STRING(tv1);
+			DUK_ASSERT(name != NULL);
+			act = thr->callstack + thr->callstack_top - 1;
 			(void) duk_js_getvar_activation(thr, act, name, 1 /*throw*/);  /* -> [... val this] */
 
 			/* Note: target registers a and a+1 may overlap with DUK__REGCONSTP(b)
@@ -52379,9 +70107,7 @@ void duk_js_execute_bytecode(duk_hthread *entry_thread) {
 			idx = (duk_uint_fast_t) DUK_DEC_A(ins);
 			if (DUK_DEC_OP(ins) == DUK_OP_CSVARI) {
 				duk_tval *tv_ind = DUK__REGP(idx);
-				if (!DUK_TVAL_IS_NUMBER(tv_ind)) {
-					DUK__INTERNAL_ERROR("CSVARI target is not a number");
-				}
+				DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv_ind));
 				idx = (duk_uint_fast_t) DUK_TVAL_GET_NUMBER(tv_ind);
 			}
 
@@ -52400,6 +70126,8 @@ void duk_js_execute_bytecode(duk_hthread *entry_thread) {
 
 		case DUK_OP_CLOSURE: {
 			duk_context *ctx = (duk_context *) thr;
+			duk_activation *act;
+			duk_hcompiledfunction *fun;
 			duk_small_uint_fast_t a = DUK_DEC_A(ins);
 			duk_uint_fast_t bc = DUK_DEC_BC(ins);
 			duk_hobject *fun_temp;
@@ -52409,11 +70137,14 @@ void duk_js_execute_bytecode(duk_hthread *entry_thread) {
 			 */
 
 			DUK_DDD(DUK_DDDPRINT("CLOSURE to target register %ld, fnum %ld (count %ld)",
-			                     (long) a, (long) bc, (long) DUK_HCOMPILEDFUNCTION_GET_FUNCS_COUNT(fun)));
+			                     (long) a, (long) bc, (long) DUK_HCOMPILEDFUNCTION_GET_FUNCS_COUNT(thr->heap, DUK__FUN())));
 
 			DUK_ASSERT_DISABLE(bc >= 0); /* unsigned */
-			DUK_ASSERT((duk_uint_t) bc < (duk_uint_t) DUK_HCOMPILEDFUNCTION_GET_FUNCS_COUNT(fun));
-			fun_temp = DUK_HCOMPILEDFUNCTION_GET_FUNCS_BASE(fun)[bc];
+			DUK_ASSERT((duk_uint_t) bc < (duk_uint_t) DUK_HCOMPILEDFUNCTION_GET_FUNCS_COUNT(thr->heap, DUK__FUN()));
+
+			act = thr->callstack + thr->callstack_top - 1;
+			fun = (duk_hcompiledfunction *) DUK_ACT_GET_FUNC(act);
+			fun_temp = DUK_HCOMPILEDFUNCTION_GET_FUNCS_BASE(thr->heap, fun)[bc];
 			DUK_ASSERT(fun_temp != NULL);
 			DUK_ASSERT(DUK_HOBJECT_IS_COMPILEDFUNCTION(fun_temp));
 
@@ -52546,7 +70277,10 @@ void duk_js_execute_bytecode(duk_hthread *entry_thread) {
 			/* E5 Section 11.2.3, step 6.a.i */
 			/* E5 Section 10.4.3 */
 
-			/* FIXME: allow object to be a const, e.g. in 'foo'.toString() */
+			/* XXX: allow object to be a const, e.g. in 'foo'.toString()?
+			 * On the other hand, DUK_REGCONSTP() is slower and generates
+			 * more code.
+			 */
 
 			tv_obj = DUK__REGP(b);
 			tv_key = DUK__REGCONSTP(c);
@@ -52562,9 +70296,7 @@ void duk_js_execute_bytecode(duk_hthread *entry_thread) {
 			idx = (duk_uint_fast_t) DUK_DEC_A(ins);
 			if (DUK_DEC_OP(ins) == DUK_OP_CSPROPI) {
 				duk_tval *tv_ind = DUK__REGP(idx);
-				if (!DUK_TVAL_IS_NUMBER(tv_ind)) {
-					DUK__INTERNAL_ERROR("CSPROPI target is not a number");
-				}
+				DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv_ind));
 				idx = (duk_uint_fast_t) DUK_TVAL_GET_NUMBER(tv_ind);
 			}
 
@@ -52619,22 +70351,6 @@ void duk_js_execute_bytecode(duk_hthread *entry_thread) {
 			break;
 		}
 
-		case DUK_OP_BNOT: {
-			duk_small_uint_fast_t a = DUK_DEC_A(ins);
-			duk_small_uint_fast_t b = DUK_DEC_B(ins);
-
-			duk__vm_bitwise_not(thr, DUK__REGCONSTP(b), a);
-			break;
-		}
-
-		case DUK_OP_LNOT: {
-			duk_small_uint_fast_t a = DUK_DEC_A(ins);
-			duk_small_uint_fast_t b = DUK_DEC_B(ins);
-
-			duk__vm_logical_not(thr, DUK__REGCONSTP(b), DUK__REGP(a));
-			break;
-		}
-
 		case DUK_OP_EQ:
 		case DUK_OP_NEQ: {
 			duk_context *ctx = (duk_context *) thr;
@@ -52762,43 +70478,17 @@ void duk_js_execute_bytecode(duk_hthread *entry_thread) {
 			tmp = duk_js_toboolean(DUK__REGCONSTP(b));
 			if (tmp == (duk_bool_t) a) {
 				/* if boolean matches A, skip next inst */
-				act->pc++;
+				curr_pc++;
 			} else {
 				;
 			}
 			break;
 		}
 
-		case DUK_OP_INSTOF: {
-			duk_context *ctx = (duk_context *) thr;
-			duk_small_uint_fast_t a = DUK_DEC_A(ins);
-			duk_small_uint_fast_t b = DUK_DEC_B(ins);
-			duk_small_uint_fast_t c = DUK_DEC_C(ins);
-			duk_bool_t tmp;
-
-			tmp = duk_js_instanceof(thr, DUK__REGCONSTP(b), DUK__REGCONSTP(c));
-			duk_push_boolean(ctx, tmp);
-			duk_replace(ctx, (duk_idx_t) a);
-			break;
-		}
-
-		case DUK_OP_IN: {
-			duk_context *ctx = (duk_context *) thr;
-			duk_small_uint_fast_t a = DUK_DEC_A(ins);
-			duk_small_uint_fast_t b = DUK_DEC_B(ins);
-			duk_small_uint_fast_t c = DUK_DEC_C(ins);
-			duk_bool_t tmp;
-
-			tmp = duk_js_in(thr, DUK__REGCONSTP(b), DUK__REGCONSTP(c));
-			duk_push_boolean(ctx, tmp);
-			duk_replace(ctx, (duk_idx_t) a);
-			break;
-		}
-
 		case DUK_OP_JUMP: {
 			duk_int_fast_t abc = DUK_DEC_ABC(ins);
 
-			act->pc += abc - DUK_BC_JUMP_BIAS;
+			curr_pc += abc - DUK_BC_JUMP_BIAS;
 			break;
 		}
 
@@ -52807,35 +70497,35 @@ void duk_js_execute_bytecode(duk_hthread *entry_thread) {
 			duk_small_uint_fast_t a = DUK_DEC_A(ins);
 			duk_small_uint_fast_t b = DUK_DEC_B(ins);
 			/* duk_small_uint_fast_t c = DUK_DEC_C(ins); */
+			duk_small_uint_t ret_result;
 
 			/* A -> flags
 			 * B -> return value reg/const
 			 * C -> currently unused
 			 */
 
-			/* FIXME: fast return not implemented, always do a slow return now */
-			/* FIXME: limit fast return to the case with no catchstack at all (not even labels)?) */
-			if (a & DUK_BC_RETURN_FLAG_FAST && 0 /*FIXME*/) {
-				/* fast return: no TCF catchers (but may have e.g. labels) */
-				DUK__INTERNAL_ERROR("FIXME: fast return unimplemented");
-			} else {
-				/* slow return */
-
-				DUK_DDD(DUK_DDDPRINT("SLOWRETURN a=%ld b=%ld", (long) a, (long) b));
-
-				if (a & DUK_BC_RETURN_FLAG_HAVE_RETVAL) {
-					duk_push_tval(ctx, DUK__REGCONSTP(b));
-				} else {
-					duk_push_undefined(ctx);
-				}
+			DUK__SYNC_AND_NULL_CURR_PC();
 
-				duk_err_setup_heap_ljstate(thr, DUK_LJ_TYPE_RETURN);
+			/* duk__handle_return() is guaranteed never to throw, except
+			 * for potential out-of-memory situations which will then
+			 * propagate out of the executor longjmp handler.
+			 */
 
-				DUK_ASSERT(thr->heap->lj.jmpbuf_ptr != NULL);  /* in bytecode executor, should always be set */
-				duk_err_longjmp(thr);
-				DUK_UNREACHABLE();
+			if (a & DUK_BC_RETURN_FLAG_HAVE_RETVAL) {
+				duk_push_tval(ctx, DUK__REGCONSTP(b));
+			} else {
+				duk_push_undefined(ctx);
 			}
-			break;
+			ret_result = duk__handle_return(thr,
+				                        entry_thread,
+				                        entry_callstack_top);
+			if (ret_result == DUK__RETHAND_RESTART) {
+				goto restart_execution;
+			}
+			DUK_ASSERT(ret_result == DUK__RETHAND_FINISHED);
+
+			DUK_DDD(DUK_DDDPRINT("exiting executor after RETURN handling"));
+			return;
 		}
 
 		case DUK_OP_CALL:
@@ -52848,8 +70538,12 @@ void duk_js_execute_bytecode(duk_hthread *entry_thread) {
 			duk_small_uint_t flag_tailcall;
 			duk_small_uint_t flag_evalcall;
 			duk_tval *tv_func;
-			duk_hobject *obj_func;        /* target function, possibly a bound function */
-			duk_hobject *obj_final_func;  /* final target function, non-bound function */
+			duk_hobject *obj_func;
+			duk_bool_t setup_rc;
+			duk_idx_t num_stack_args;
+#if !defined(DUK_USE_EXEC_FUN_LOCAL)
+			duk_hcompiledfunction *fun;
+#endif
 
 			/* A -> flags
 			 * B -> base register for call (base -> func, base+1 -> this, base+2 -> arg1 ... base+2+N-1 -> argN)
@@ -52864,9 +70558,7 @@ void duk_js_execute_bytecode(duk_hthread *entry_thread) {
 			idx = (duk_uint_fast_t) DUK_DEC_B(ins);
 			if (DUK_DEC_OP(ins) == DUK_OP_CALLI) {
 				duk_tval *tv_ind = DUK__REGP(idx);
-				if (!DUK_TVAL_IS_NUMBER(tv_ind)) {
-					DUK__INTERNAL_ERROR("CALLI target is not a number");
-				}
+				DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv_ind));
 				idx = (duk_uint_fast_t) DUK_TVAL_GET_NUMBER(tv_ind);
 			}
 
@@ -52877,72 +70569,102 @@ void duk_js_execute_bytecode(duk_hthread *entry_thread) {
 			}
 #endif
 
-			tv_func = DUK__REGP(idx);
-			if (!DUK_TVAL_IS_OBJECT(tv_func)) {
-				DUK_ERROR(thr, DUK_ERR_TYPE_ERROR, "call target not an object");
-			}
-			obj_func = DUK_TVAL_GET_OBJECT(tv_func);
-
 			/*
 			 *  To determine whether to use an optimized Ecmascript-to-Ecmascript
 			 *  call, we need to know whether the final, non-bound function is an
-			 *  Ecmascript function.  We need to follow the "bound" chain to do that;
-			 *  the "bound" chain will be followed for the second time when calling.
-			 *  This overhead only affects bound functions (in particular, helper
-			 *  functions should not be called if the immediate target function is
-			 *  not bound).
-			 * 
-			 *  Even so, this awkward solution could be avoided by e.g. replicating
-			 *  final, non-bound target function flags to the bound function objects
-			 *  (so that a bound function would e.g. have both a "BOUND" flag and
-			 *  a "COMPILEDFUNCTION" flag).  Also, bound functions could also keep
-			 *  a direct reference to the final non-bound function ("shortcut").
-			 */
-
-			if (DUK_HOBJECT_HAS_BOUND(obj_func)) {
-				obj_final_func = duk__find_nonbound_function(thr, obj_func);
-			} else {
-				obj_final_func = obj_func;
-			}
+			 *  Ecmascript function.
+			 *
+			 *  This is now implemented so that we start to do an ecma-to-ecma call
+			 *  setup which will resolve the bound chain as the first thing.  If the
+			 *  final function is not eligible, the return value indicates that the
+			 *  ecma-to-ecma call is not possible.  The setup will overwrite the call
+			 *  target at DUK__REGP(idx) with the final, non-bound function (which
+			 *  may be a lightfunc), and fudge arguments if necessary.
+			 *
+			 *  XXX: If an ecma-to-ecma call is not possible, this initial call
+			 *  setup will do bound function chain resolution but won't do the
+			 *  "effective this binding" resolution which is quite confusing.
+			 *  Perhaps add a helper for doing bound function and effective this
+			 *  binding resolution - and call that explicitly?  Ecma-to-ecma call
+			 *  setup and normal function handling can then assume this prestep has
+			 *  been done by the caller.
+			 */
 
 			duk_set_top(ctx, (duk_idx_t) (idx + c + 2));   /* [ ... func this arg1 ... argN ] */
 
-			if (DUK_HOBJECT_IS_COMPILEDFUNCTION(obj_final_func)) {
-				/*
-				 *  Ecmascript-to-Ecmascript call: avoid C recursion
-				 *  by being clever.
+			call_flags = 0;
+			if (flag_tailcall) {
+				/* We request a tail call, but in some corner cases
+				 * call handling can decide that a tail call is
+				 * actually not possible.
+				 * See: test-bug-tailcall-preventyield-assert.c.
 				 */
+				call_flags |= DUK_CALL_FLAG_IS_TAILCALL;
+			}
 
-				/* Compared to duk_handle_call():
-				 *   - protected call: never
-				 *   - ignore recursion limit: never
+			/* Compared to duk_handle_call():
+			 *   - protected call: never
+			 *   - ignore recursion limit: never
+			 */
+			num_stack_args = c;
+			setup_rc = duk_handle_ecma_call_setup(thr,
+			                                      num_stack_args,
+			                                      call_flags);
+
+			if (setup_rc) {
+				/* Ecma-to-ecma call possible, may or may not be a tail call.
+				 * Avoid C recursion by being clever.
 				 */
+				DUK_DDD(DUK_DDDPRINT("ecma-to-ecma call setup possible, restart execution"));
+				/* curr_pc synced by duk_handle_ecma_call_setup() */
+				goto restart_execution;
+			}
+			DUK_ASSERT(thr->ptr_curr_pc != NULL);  /* restored if ecma-to-ecma setup fails */
 
-				/* XXX: optimize flag handling, by coordinating with bytecode */
+			DUK_DDD(DUK_DDDPRINT("ecma-to-ecma call not possible, target is native (may be lightfunc)"));
 
-				call_flags = 0;
-				if (flag_tailcall) {
-					/* We request a tailcall, but in some corner cases
-					 * call handling can decide that a tailcall is
-					 * actually not possible.
-					 * See: test-bug-tailcall-preventyield-assert.c.
-					 */
-					call_flags |= DUK_CALL_FLAG_IS_TAILCALL;
-				}
+			/* Recompute argument count: bound function handling may have shifted. */
+			num_stack_args = duk_get_top(ctx) - (idx + 2);
+			DUK_DDD(DUK_DDDPRINT("recomputed arg count: %ld\n", (long) num_stack_args));
 
-				duk_handle_ecma_call_setup(thr,
-				                           c,              /* num_stack_args */
-				                           call_flags);    /* call_flags */
+			tv_func = DUK__REGP(idx);  /* Relookup if relocated */
+			if (DUK_TVAL_IS_LIGHTFUNC(tv_func)) {
 
-				/* restart execution -> starts executing new function */
-				goto restart_execution;
+				call_flags = 0;  /* not protected, respect reclimit, not constructor */
+
+				/* There is no eval() special handling here: eval() is never
+				 * automatically converted to a lightfunc.
+				 */
+				DUK_ASSERT(DUK_TVAL_GET_LIGHTFUNC_FUNCPTR(tv_func) != duk_bi_global_object_eval);
+
+				duk_handle_call_unprotected(thr,
+				                            num_stack_args,
+				                            call_flags);
+
+				/* duk_js_call.c is required to restore the stack reserve
+				 * so we only need to reset the top.
+				 */
+#if !defined(DUK_USE_EXEC_FUN_LOCAL)
+				fun = DUK__FUN();
+#endif
+				duk_set_top(ctx, (duk_idx_t) fun->nregs);
+
+				/* No need to reinit setjmp() catchpoint, as call handling
+				 * will store and restore our state.
+				 */
 			} else {
+				/* Call setup checks callability. */
+				DUK_ASSERT(DUK_TVAL_IS_OBJECT(tv_func));
+				obj_func = DUK_TVAL_GET_OBJECT(tv_func);
+				DUK_ASSERT(obj_func != NULL);
+				DUK_ASSERT(!DUK_HOBJECT_HAS_BOUND(obj_func));
+
 				/*
 				 *  Other cases, use C recursion.
 				 *
-				 *  If a tailcall was requested we ignore it and execute a normal call.
+				 *  If a tail call was requested we ignore it and execute a normal call.
 				 *  Since Duktape 0.11.0 the compiler emits a RETURN opcode even after
-				 *  a tailcall to avoid test-bug-tailcall-thread-yield-resume.js.
+				 *  a tail call to avoid test-bug-tailcall-thread-yield-resume.js.
 				 *
 				 *  Direct eval call: (1) call target (before following bound function
 				 *  chain) is the built-in eval() function, and (2) call was made with
@@ -52961,140 +70683,70 @@ void duk_js_execute_bytecode(duk_hthread *entry_thread) {
 					}
 				}
 
-				duk_handle_call(thr,
-				                c,            /* num_stack_args */
-				                call_flags);  /* call_flags */
+				duk_handle_call_unprotected(thr,
+				                            num_stack_args,
+				                            call_flags);
 
-				/* FIXME: who should restore? */
-				duk_require_stack_top(ctx, (duk_idx_t) fun->nregs);  /* may have shrunk by inner calls, must recheck */
+				/* duk_js_call.c is required to restore the stack reserve
+				 * so we only need to reset the top.
+				 */
+#if !defined(DUK_USE_EXEC_FUN_LOCAL)
+				fun = DUK__FUN();
+#endif
 				duk_set_top(ctx, (duk_idx_t) fun->nregs);
 
 				/* No need to reinit setjmp() catchpoint, as call handling
 				 * will store and restore our state.
 				 */
 			}
-			break;
-		}
-
-		case DUK_OP_LABEL: {
-			duk_catcher *cat;
-			duk_uint_fast_t abc = DUK_DEC_ABC(ins);
-
-			/* allocate catcher and populate it (should be atomic) */
-
-			duk_hthread_catchstack_grow(thr);
-			cat = thr->catchstack + thr->catchstack_top;
-			thr->catchstack_top++;
-
-			cat->flags = DUK_CAT_TYPE_LABEL | (abc << DUK_CAT_LABEL_SHIFT);
-			cat->callstack_index = thr->callstack_top - 1;
-			cat->pc_base = act->pc;  /* pre-incremented, points to first jump slot */
-			cat->idx_base = 0;  /* unused for label */
-			cat->h_varname = NULL;
 
-			DUK_DDD(DUK_DDDPRINT("LABEL catcher: flags=0x%08lx, callstack_index=%ld, pc_base=%ld, "
-			                     "idx_base=%ld, h_varname=%!O, label_id=%ld",
-			                     (long) cat->flags, (long) cat->callstack_index, (long) cat->pc_base,
-			                     (long) cat->idx_base, (duk_heaphdr *) cat->h_varname, (long) DUK_CAT_GET_LABEL(cat)));
-
-			act->pc += 2;  /* skip jump slots */
-			break;
-		}
-
-		case DUK_OP_ENDLABEL: {
-			duk_catcher *cat;
-#if defined(DUK_USE_DDDPRINT) || defined(DUK_USE_ASSERTIONS)
-			duk_uint_fast_t abc = DUK_DEC_ABC(ins);
-#endif
-#if defined(DUK_USE_DDDPRINT)
-			DUK_DDD(DUK_DDDPRINT("ENDLABEL %ld", (long) abc));
-#endif
-
-			DUK_ASSERT(thr->catchstack_top >= 1);
-
-			cat = thr->catchstack + thr->catchstack_top - 1;
-			DUK_UNREF(cat);
-			DUK_ASSERT(DUK_CAT_GET_TYPE(cat) == DUK_CAT_TYPE_LABEL);
-			DUK_ASSERT((duk_uint_fast_t) DUK_CAT_GET_LABEL(cat) == abc);
-
-			duk_hthread_catchstack_unwind(thr, thr->catchstack_top - 1);
-			/* no need to unwind callstack */
-			break;
-		}
-
-		case DUK_OP_BREAK: {
-			duk_context *ctx = (duk_context *) thr;
-			duk_uint_fast_t abc = DUK_DEC_ABC(ins);
-
-			/* always the "slow break" variant (longjmp'ing); a "fast break" is
-			 * simply an DUK_OP_JUMP.
+			/* When debugger is enabled, we need to recheck the activation
+			 * status after returning.  This is now handled by call handling
+			 * and heap->dbg_force_restart.
 			 */
-
-			DUK_DDD(DUK_DDDPRINT("BREAK: %ld", (long) abc));
-
-			duk_push_uint(ctx, (duk_uint_t) abc);
-			duk_err_setup_heap_ljstate(thr, DUK_LJ_TYPE_BREAK);
-
-			DUK_ASSERT(thr->heap->lj.jmpbuf_ptr != NULL);  /* always in executor */
-			duk_err_longjmp(thr);
-
-			DUK_UNREACHABLE();
-			break;
-		}
-
-		case DUK_OP_CONTINUE: {
-			duk_context *ctx = (duk_context *) thr;
-			duk_uint_fast_t abc = DUK_DEC_ABC(ins);
-
-			/* always the "slow continue" variant (longjmp'ing); a "fast continue" is
-			 * simply an DUK_OP_JUMP.
-			 */
-
-			DUK_DDD(DUK_DDDPRINT("CONTINUE: %ld", (long) abc));
-
-			duk_push_uint(ctx, (duk_uint_t) abc);
-			duk_err_setup_heap_ljstate(thr, DUK_LJ_TYPE_CONTINUE);
-
-			DUK_ASSERT(thr->heap->lj.jmpbuf_ptr != NULL);  /* always in executor */
-			duk_err_longjmp(thr);
-
-			DUK_UNREACHABLE();
 			break;
 		}
 
 		case DUK_OP_TRYCATCH: {
 			duk_context *ctx = (duk_context *) thr;
+			duk_activation *act;
 			duk_catcher *cat;
 			duk_tval *tv1;
 			duk_small_uint_fast_t a;
-			duk_small_uint_fast_t b;
-			duk_small_uint_fast_t c;
+			duk_uint_fast_t bc;
 
 			/* A -> flags
-			 * B -> reg_catch; base register for 2 regs
-			 * C -> semantics depend on flags: var_name or with_target
+			 * BC -> reg_catch; base register for two registers used both during
+			 *       trycatch setup and when catch is triggered
 			 *
 			 *      If DUK_BC_TRYCATCH_FLAG_CATCH_BINDING set:
-			 *          C is constant index for catch binding variable name.
+			 *          reg_catch + 0: catch binding variable name (string).
 			 *          Automatic declarative environment is established for
 			 *          the duration of the 'catch' clause.
 			 *
 			 *      If DUK_BC_TRYCATCH_FLAG_WITH_BINDING set:
-			 *          C is reg/const index for with 'target value', which
-			 *          is coerced to an object and then used as a binding
-			 *          object for an environment record.  The binding is
-			 *          initialized here, for the 'try' clause.
+			 *          reg_catch + 0: with 'target value', which is coerced to
+			 *          an object and then used as a bindind object for an
+			 *          environment record.  The binding is initialized here, for
+			 *          the 'try' clause.
 			 *
 			 * Note that a TRYCATCH generated for a 'with' statement has no
 			 * catch or finally parts.
 			 */
 
+			/* XXX: TRYCATCH handling should be reworked to avoid creating
+			 * an explicit scope unless it is actually needed (e.g. function
+			 * instances or eval is executed inside the catch block).  This
+			 * rework is not trivial because the compiler doesn't have an
+			 * intermediate representation.  When the rework is done, the
+			 * opcode format can also be made more straightforward.
+			 */
+
 			/* XXX: side effect handling is quite awkward here */
 
-			DUK_DDD(DUK_DDDPRINT("TRYCATCH: reg_catch=%ld, var_name/with_target=%ld, have_catch=%ld, "
+			DUK_DDD(DUK_DDDPRINT("TRYCATCH: reg_catch=%ld, have_catch=%ld, "
 			                     "have_finally=%ld, catch_binding=%ld, with_binding=%ld (flags=0x%02lx)",
-			                     (long) DUK_DEC_B(ins),
-			                     (long) DUK_DEC_C(ins),
+			                     (long) DUK_DEC_BC(ins),
 			                     (long) (DUK_DEC_A(ins) & DUK_BC_TRYCATCH_FLAG_HAVE_CATCH ? 1 : 0),
 			                     (long) (DUK_DEC_A(ins) & DUK_BC_TRYCATCH_FLAG_HAVE_FINALLY ? 1 : 0),
 			                     (long) (DUK_DEC_A(ins) & DUK_BC_TRYCATCH_FLAG_CATCH_BINDING ? 1 : 0),
@@ -53102,9 +70754,9 @@ void duk_js_execute_bytecode(duk_hthread *entry_thread) {
 			                     (unsigned long) DUK_DEC_A(ins)));
 
 			a = DUK_DEC_A(ins);
-			b = DUK_DEC_B(ins);
-			c = DUK_DEC_C(ins);
+			bc = DUK_DEC_BC(ins);
 
+			act = thr->callstack + thr->callstack_top - 1;
 			DUK_ASSERT(thr->callstack_top >= 1);
 
 			/* 'with' target must be created first, in case we run out of memory */
@@ -53129,15 +70781,15 @@ void duk_js_execute_bytecode(duk_hthread *entry_thread) {
 				                              DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_OBJENV),
 				                              -1);  /* no prototype, updated below */
 
-				duk_push_tval(ctx, DUK__REGCONSTP(c));
+				duk_push_tval(ctx, DUK__REGP(bc));
 				duk_to_object(ctx, -1);
 				duk_dup(ctx, -1);
 
 				/* [ ... env target ] */
 				/* [ ... env target target ] */
 
-				duk_def_prop_stridx(thr, -3, DUK_STRIDX_INT_TARGET, DUK_PROPDESC_FLAGS_NONE);
-				duk_def_prop_stridx(thr, -2, DUK_STRIDX_INT_THIS, DUK_PROPDESC_FLAGS_NONE);  /* always provideThis=true */
+				duk_xdef_prop_stridx(thr, -3, DUK_STRIDX_INT_TARGET, DUK_PROPDESC_FLAGS_NONE);
+				duk_xdef_prop_stridx(thr, -2, DUK_STRIDX_INT_THIS, DUK_PROPDESC_FLAGS_NONE);  /* always provideThis=true */
 
 				/* [ ... env ] */
 
@@ -53164,8 +70816,13 @@ void duk_js_execute_bytecode(duk_hthread *entry_thread) {
 			if (a & DUK_BC_TRYCATCH_FLAG_CATCH_BINDING) {
 				DUK_DDD(DUK_DDDPRINT("catch binding flag set to catcher"));
 				cat->flags |= DUK_CAT_FLAG_CATCH_BINDING_ENABLED;
-				tv1 = DUK__CONSTP(c);
+				tv1 = DUK__REGP(bc);
 				DUK_ASSERT(DUK_TVAL_IS_STRING(tv1));
+
+				/* borrowed reference; although 'tv1' comes from a register,
+				 * its value was loaded using LDCONST so the constant will
+				 * also exist and be reachable.
+				 */
 				cat->h_varname = DUK_TVAL_GET_STRING(tv1);
 			} else if (a & DUK_BC_TRYCATCH_FLAG_WITH_BINDING) {
 				/* env created above to stack top */
@@ -53181,7 +70838,7 @@ void duk_js_execute_bytecode(duk_hthread *entry_thread) {
 				DUK_ASSERT(new_env != NULL);
 
 				act = thr->callstack + thr->callstack_top - 1;  /* relookup (side effects) */
-				DUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr, new_env, act->lex_env);
+				DUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr, new_env, act->lex_env);  /* side effects */
 
 				act = thr->callstack + thr->callstack_top - 1;  /* relookup (side effects) */
 				act->lex_env = new_env;
@@ -53191,17 +70848,217 @@ void duk_js_execute_bytecode(duk_hthread *entry_thread) {
 				;
 			}
 
+			/* Registers 'bc' and 'bc + 1' are written in longjmp handling
+			 * and if their previous values (which are temporaries) become
+			 * unreachable -and- have a finalizer, there'll be a function
+			 * call during error handling which is not supported now (GH-287).
+			 * Ensure that both 'bc' and 'bc + 1' have primitive values to
+			 * guarantee no finalizer calls in error handling.  Scrubbing also
+			 * ensures finalizers for the previous values run here rather than
+			 * later.  Error handling related values are also written to 'bc'
+			 * and 'bc + 1' but those values never become unreachable during
+			 * error handling, so there's no side effect problem even if the
+			 * error value has a finalizer.
+			 */
+			duk_to_undefined(ctx, bc);
+			duk_to_undefined(ctx, bc + 1);
+
 			cat = thr->catchstack + thr->catchstack_top - 1;  /* relookup (side effects) */
 			cat->callstack_index = thr->callstack_top - 1;
-			cat->pc_base = act->pc;  /* pre-incremented, points to first jump slot */
-			cat->idx_base = (duk_size_t) (thr->valstack_bottom - thr->valstack) + b;
+			cat->pc_base = (duk_instr_t *) curr_pc;  /* pre-incremented, points to first jump slot */
+			cat->idx_base = (duk_size_t) (thr->valstack_bottom - thr->valstack) + bc;
 
 			DUK_DDD(DUK_DDDPRINT("TRYCATCH catcher: flags=0x%08lx, callstack_index=%ld, pc_base=%ld, "
 			                     "idx_base=%ld, h_varname=%!O",
 			                     (unsigned long) cat->flags, (long) cat->callstack_index,
 			                     (long) cat->pc_base, (long) cat->idx_base, (duk_heaphdr *) cat->h_varname));
 
-			act->pc += 2;  /* skip jump slots */
+			curr_pc += 2;  /* skip jump slots */
+			break;
+		}
+
+		/* Pre/post inc/dec for register variables, important for loops. */
+		case DUK_OP_PREINCR:
+		case DUK_OP_PREDECR:
+		case DUK_OP_POSTINCR:
+		case DUK_OP_POSTDECR: {
+			duk_context *ctx = (duk_context *) thr;
+			duk_small_uint_fast_t a = DUK_DEC_A(ins);
+			duk_uint_fast_t bc = DUK_DEC_BC(ins);
+			duk_tval *tv1, *tv2;
+			duk_double_t x, y, z;
+
+			/* Two lowest bits of opcode are used to distinguish
+			 * variants.  Bit 0 = inc(0)/dec(1), bit 1 = pre(0)/post(1).
+			 */
+			DUK_ASSERT((DUK_OP_PREINCR & 0x03) == 0x00);
+			DUK_ASSERT((DUK_OP_PREDECR & 0x03) == 0x01);
+			DUK_ASSERT((DUK_OP_POSTINCR & 0x03) == 0x02);
+			DUK_ASSERT((DUK_OP_POSTDECR & 0x03) == 0x03);
+
+			tv1 = DUK__REGP(bc);
+#if defined(DUK_USE_FASTINT)
+			if (DUK_TVAL_IS_FASTINT(tv1)) {
+				duk_int64_t x_fi, y_fi, z_fi;
+				x_fi = DUK_TVAL_GET_FASTINT(tv1);
+				if (ins & DUK_ENC_OP(0x01)) {
+					if (x_fi == DUK_FASTINT_MIN) {
+						goto skip_fastint;
+					}
+					y_fi = x_fi - 1;
+				} else {
+					if (x_fi == DUK_FASTINT_MAX) {
+						goto skip_fastint;
+					}
+					y_fi = x_fi + 1;
+				}
+
+				DUK_TVAL_SET_FASTINT(tv1, y_fi);  /* no need for refcount update */
+
+				tv2 = DUK__REGP(a);
+				z_fi = (ins & DUK_ENC_OP(0x02)) ? x_fi : y_fi;
+				DUK_TVAL_SET_FASTINT_UPDREF(thr, tv2, z_fi);  /* side effects */
+				break;
+			}
+		 skip_fastint:
+#endif
+			if (DUK_TVAL_IS_NUMBER(tv1)) {
+				/* Fast path for the case where the register
+				 * is a number (e.g. loop counter).
+				 */
+
+				x = DUK_TVAL_GET_NUMBER(tv1);
+				if (ins & DUK_ENC_OP(0x01)) {
+					y = x - 1.0;
+				} else {
+					y = x + 1.0;
+				}
+
+				DUK_TVAL_SET_NUMBER(tv1, y);  /* no need for refcount update */
+			} else {
+				x = duk_to_number(ctx, bc);
+
+				if (ins & DUK_ENC_OP(0x01)) {
+					y = x - 1.0;
+				} else {
+					y = x + 1.0;
+				}
+
+				duk_push_number(ctx, y);
+				duk_replace(ctx, bc);
+			}
+
+			tv2 = DUK__REGP(a);
+			z = (ins & DUK_ENC_OP(0x02)) ? x : y;
+			DUK_TVAL_SET_NUMBER_UPDREF(thr, tv2, z);  /* side effects */
+			break;
+		}
+
+		/* Preinc/predec for var-by-name, slow path. */
+		case DUK_OP_PREINCV:
+		case DUK_OP_PREDECV:
+		case DUK_OP_POSTINCV:
+		case DUK_OP_POSTDECV: {
+			duk_context *ctx = (duk_context *) thr;
+			duk_activation *act;
+			duk_small_uint_fast_t a = DUK_DEC_A(ins);
+			duk_uint_fast_t bc = DUK_DEC_BC(ins);
+			duk_double_t x, y;
+			duk_tval *tv1;
+			duk_hstring *name;
+
+			/* Two lowest bits of opcode are used to distinguish
+			 * variants.  Bit 0 = inc(0)/dec(1), bit 1 = pre(0)/post(1).
+			 */
+			DUK_ASSERT((DUK_OP_PREINCV & 0x03) == 0x00);
+			DUK_ASSERT((DUK_OP_PREDECV & 0x03) == 0x01);
+			DUK_ASSERT((DUK_OP_POSTINCV & 0x03) == 0x02);
+			DUK_ASSERT((DUK_OP_POSTDECV & 0x03) == 0x03);
+
+			tv1 = DUK__CONSTP(bc);
+			DUK_ASSERT(DUK_TVAL_IS_STRING(tv1));
+			name = DUK_TVAL_GET_STRING(tv1);
+			DUK_ASSERT(name != NULL);
+			act = thr->callstack + thr->callstack_top - 1;
+			(void) duk_js_getvar_activation(thr, act, name, 1 /*throw*/);  /* -> [... val this] */
+
+			/* XXX: fastint fast path would be very useful here */
+
+			x = duk_to_number(ctx, -2);
+			duk_pop_2(ctx);
+			if (ins & DUK_ENC_OP(0x01)) {
+				y = x - 1.0;
+			} else {
+				y = x + 1.0;
+			}
+
+			duk_push_number(ctx, y);
+			tv1 = duk_get_tval(ctx, -1);
+			DUK_ASSERT(tv1 != NULL);
+			duk_js_putvar_activation(thr, act, name, tv1, DUK__STRICT());
+			duk_pop(ctx);
+
+			duk_push_number(ctx, (ins & DUK_ENC_OP(0x02)) ? x : y);
+			duk_replace(ctx, (duk_idx_t) a);
+			break;
+		}
+
+		/* Preinc/predec for object properties. */
+		case DUK_OP_PREINCP:
+		case DUK_OP_PREDECP:
+		case DUK_OP_POSTINCP:
+		case DUK_OP_POSTDECP: {
+			duk_context *ctx = (duk_context *) thr;
+			duk_small_uint_fast_t a = DUK_DEC_A(ins);
+			duk_small_uint_fast_t b = DUK_DEC_B(ins);
+			duk_small_uint_fast_t c = DUK_DEC_C(ins);
+			duk_tval *tv_obj;
+			duk_tval *tv_key;
+			duk_tval *tv_val;
+			duk_bool_t rc;
+			duk_double_t x, y;
+
+			/* A -> target reg
+			 * B -> object reg/const (may be const e.g. in "'foo'[1]")
+			 * C -> key reg/const
+			 */
+
+			/* Two lowest bits of opcode are used to distinguish
+			 * variants.  Bit 0 = inc(0)/dec(1), bit 1 = pre(0)/post(1).
+			 */
+			DUK_ASSERT((DUK_OP_PREINCP & 0x03) == 0x00);
+			DUK_ASSERT((DUK_OP_PREDECP & 0x03) == 0x01);
+			DUK_ASSERT((DUK_OP_POSTINCP & 0x03) == 0x02);
+			DUK_ASSERT((DUK_OP_POSTDECP & 0x03) == 0x03);
+
+			tv_obj = DUK__REGCONSTP(b);
+			tv_key = DUK__REGCONSTP(c);
+			rc = duk_hobject_getprop(thr, tv_obj, tv_key);  /* -> [val] */
+			DUK_UNREF(rc);  /* ignore */
+			tv_obj = NULL;  /* invalidated */
+			tv_key = NULL;  /* invalidated */
+
+			x = duk_to_number(ctx, -1);
+			duk_pop(ctx);
+			if (ins & DUK_ENC_OP(0x01)) {
+				y = x - 1.0;
+			} else {
+				y = x + 1.0;
+			}
+
+			duk_push_number(ctx, y);
+			tv_val = duk_get_tval(ctx, -1);
+			DUK_ASSERT(tv_val != NULL);
+			tv_obj = DUK__REGCONSTP(b);
+			tv_key = DUK__REGCONSTP(c);
+			rc = duk_hobject_putprop(thr, tv_obj, tv_key, tv_val, DUK__STRICT());
+			DUK_UNREF(rc);  /* ignore */
+			tv_obj = NULL;  /* invalidated */
+			tv_key = NULL;  /* invalidated */
+			duk_pop(ctx);
+
+			duk_push_number(ctx, (ins & DUK_ENC_OP(0x02)) ? x : y);
+			duk_replace(ctx, (duk_idx_t) a);
 			break;
 		}
 
@@ -53217,60 +71074,52 @@ void duk_js_execute_bytecode(duk_hthread *entry_thread) {
 				break;
 			}
 
+			case DUK_EXTRAOP_INVALID: {
+				DUK_ERROR(thr, DUK_ERR_INTERNAL_ERROR, "INVALID opcode (%ld)", (long) DUK_DEC_BC(ins));
+				break;
+			}
+
 			case DUK_EXTRAOP_LDTHIS: {
 				/* Note: 'this' may be bound to any value, not just an object */
-				duk_small_uint_fast_t b = DUK_DEC_B(ins);
-				duk_tval tv_tmp;
+				duk_uint_fast_t bc = DUK_DEC_BC(ins);
 				duk_tval *tv1, *tv2;
 
-				tv1 = DUK__REGP(b);
+				tv1 = DUK__REGP(bc);
 				tv2 = thr->valstack_bottom - 1;  /* 'this binding' is just under bottom */
 				DUK_ASSERT(tv2 >= thr->valstack);
 
-				DUK_DDD(DUK_DDDPRINT("LDTHIS: %!T to r%ld", (duk_tval *) tv2, (long) b));
+				DUK_DDD(DUK_DDDPRINT("LDTHIS: %!T to r%ld", (duk_tval *) tv2, (long) bc));
 
-				DUK_TVAL_SET_TVAL(&tv_tmp, tv1);
-				DUK_TVAL_SET_TVAL(tv1, tv2);
-				DUK_TVAL_INCREF(thr, tv1);
-				DUK_TVAL_DECREF(thr, &tv_tmp);  /* side effects */
+				DUK_TVAL_SET_TVAL_UPDREF_FAST(thr, tv1, tv2);  /* side effects */
 				break;
 			}
 
 			case DUK_EXTRAOP_LDUNDEF: {
 				duk_uint_fast_t bc = DUK_DEC_BC(ins);
-				duk_tval tv_tmp;
 				duk_tval *tv1;
 
 				tv1 = DUK__REGP(bc);
-				DUK_TVAL_SET_TVAL(&tv_tmp, tv1);
-				DUK_TVAL_SET_UNDEFINED_ACTUAL(tv1);
-				DUK_TVAL_DECREF(thr, &tv_tmp);  /* side effects */
+				DUK_TVAL_SET_UNDEFINED_UPDREF(thr, tv1);  /* side effects */
 				break;
 			}
 
 			case DUK_EXTRAOP_LDNULL: {
 				duk_uint_fast_t bc = DUK_DEC_BC(ins);
-				duk_tval tv_tmp;
 				duk_tval *tv1;
 
 				tv1 = DUK__REGP(bc);
-				DUK_TVAL_SET_TVAL(&tv_tmp, tv1);
-				DUK_TVAL_SET_NULL(tv1);
-				DUK_TVAL_DECREF(thr, &tv_tmp);  /* side effects */
+				DUK_TVAL_SET_NULL_UPDREF(thr, tv1);  /* side effects */
 				break;
 			}
 
 			case DUK_EXTRAOP_LDTRUE:
 			case DUK_EXTRAOP_LDFALSE: {
 				duk_uint_fast_t bc = DUK_DEC_BC(ins);
-				duk_tval tv_tmp;
 				duk_tval *tv1;
 				duk_small_uint_fast_t bval = (extraop == DUK_EXTRAOP_LDTRUE ? 1 : 0);
 
 				tv1 = DUK__REGP(bc);
-				DUK_TVAL_SET_TVAL(&tv_tmp, tv1);
-				DUK_TVAL_SET_BOOLEAN(tv1, bval);
-				DUK_TVAL_DECREF(thr, &tv_tmp);  /* side effects */
+				DUK_TVAL_SET_BOOLEAN_UPDREF(thr, tv1, bval);  /* side effects */
 				break;
 			}
 
@@ -53303,7 +71152,7 @@ void duk_js_execute_bytecode(duk_hthread *entry_thread) {
 				DUK_ASSERT(DUK_TVAL_IS_OBJECT(tv1));
 				h = DUK_TVAL_GET_OBJECT(tv1);
 
-				c= DUK_DEC_C(ins); tv1 = DUK__REGP(c);
+				c = DUK_DEC_C(ins); tv1 = DUK__REGP(c);
 				DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv1));
 				len = (duk_uint32_t) DUK_TVAL_GET_NUMBER(tv1);
 
@@ -53314,15 +71163,15 @@ void duk_js_execute_bytecode(duk_hthread *entry_thread) {
 
 			case DUK_EXTRAOP_TYPEOF: {
 				duk_context *ctx = (duk_context *) thr;
-				duk_small_uint_fast_t b = DUK_DEC_B(ins);
-				duk_small_uint_fast_t c = DUK_DEC_C(ins);
-				duk_push_hstring(ctx, duk_js_typeof(thr, DUK__REGCONSTP(c)));
-				duk_replace(ctx, (duk_idx_t) b);
+				duk_uint_fast_t bc = DUK_DEC_BC(ins);
+				duk_push_hstring(ctx, duk_js_typeof(thr, DUK__REGP(bc)));
+				duk_replace(ctx, (duk_idx_t) bc);
 				break;
 			}
 
 			case DUK_EXTRAOP_TYPEOFID: {
 				duk_context *ctx = (duk_context *) thr;
+				duk_activation *act;
 				duk_small_uint_fast_t b = DUK_DEC_B(ins);
 				duk_small_uint_fast_t c = DUK_DEC_C(ins);
 				duk_hstring *name;
@@ -53332,9 +71181,10 @@ void duk_js_execute_bytecode(duk_hthread *entry_thread) {
 				 * C -> constant index of identifier name
 				 */
 
-				tv = DUK__REGCONSTP(c);  /* FIXME: this could be a DUK__CONSTP instead */
+				tv = DUK__REGCONSTP(c);  /* XXX: this could be a DUK__CONSTP instead */
 				DUK_ASSERT(DUK_TVAL_IS_STRING(tv));
 				name = DUK_TVAL_GET_STRING(tv);
+				act = thr->callstack + thr->callstack_top - 1;
 				if (duk_js_getvar_activation(thr, act, name, 0 /*throw*/)) {
 					/* -> [... val this] */
 					tv = duk_get_tval(ctx, -2);
@@ -53350,16 +71200,6 @@ void duk_js_execute_bytecode(duk_hthread *entry_thread) {
 				break;
 			}
 
-			case DUK_EXTRAOP_TONUM: {
-				duk_context *ctx = (duk_context *) thr;
-				duk_small_uint_fast_t b = DUK_DEC_B(ins);
-				duk_small_uint_fast_t c = DUK_DEC_C(ins);
-				duk_dup(ctx, (duk_idx_t) c);
-				duk_to_number(ctx, -1);
-				duk_replace(ctx, (duk_idx_t) b);
-				break;
-			}
-
 			case DUK_EXTRAOP_INITENUM: {
 				duk_context *ctx = (duk_context *) thr;
 				duk_small_uint_fast_t b = DUK_DEC_B(ins);
@@ -53373,7 +71213,7 @@ void duk_js_execute_bytecode(duk_hthread *entry_thread) {
 				 */
 
 				/* B -> register for writing enumerator object
-				 * C -> value to be enumerated (expect a register)
+				 * C -> value to be enumerated (register)
 				 */
 
 				if (duk_is_null_or_undefined(ctx, (duk_idx_t) c)) {
@@ -53415,7 +71255,7 @@ void duk_js_execute_bytecode(duk_hthread *entry_thread) {
 						/* [ ... enum ] -> [ ... next_key ] */
 						DUK_DDD(DUK_DDDPRINT("enum active, next key is %!T, skip jump slot ",
 						                     (duk_tval *) duk_get_tval(ctx, -1)));
-						act->pc++;;
+						curr_pc++;
 					} else {
 						/* [ ... enum ] -> [ ... ] */
 						DUK_DDD(DUK_DDDPRINT("enum finished, execute jump slot"));
@@ -53427,7 +71267,7 @@ void duk_js_execute_bytecode(duk_hthread *entry_thread) {
 					DUK_ASSERT(duk_is_null(ctx, (duk_idx_t) c));
 					DUK_DDD(DUK_DDDPRINT("enum is null, execute jump slot"));
 				}
-				break;				
+				break;
 			}
 
 			case DUK_EXTRAOP_INITSET:
@@ -53453,9 +71293,7 @@ void duk_js_execute_bytecode(duk_hthread *entry_thread) {
 				idx = (duk_uint_fast_t) DUK_DEC_C(ins);
 				if (extraop == DUK_EXTRAOP_INITSETI || extraop == DUK_EXTRAOP_INITGETI) {
 					duk_tval *tv_ind = DUK__REGP(idx);
-					if (!DUK_TVAL_IS_NUMBER(tv_ind)) {
-						DUK__INTERNAL_ERROR("DUK_EXTRAOP_INITSETI/DUK_EXTRAOP_INITGETI target is not a number");
-					}
+					DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv_ind));
 					idx = (duk_uint_fast_t) DUK_TVAL_GET_NUMBER(tv_ind);
 				}
 
@@ -53501,7 +71339,6 @@ void duk_js_execute_bytecode(duk_hthread *entry_thread) {
 
 			case DUK_EXTRAOP_ENDTRY: {
 				duk_catcher *cat;
-				duk_tval tv_tmp;
 				duk_tval *tv1;
 
 				DUK_ASSERT(thr->catchstack_top >= 1);
@@ -53515,19 +71352,19 @@ void duk_js_execute_bytecode(duk_hthread *entry_thread) {
 
 				if (DUK_CAT_HAS_FINALLY_ENABLED(cat)) {
 					DUK_DDD(DUK_DDDPRINT("ENDTRY: finally part is active, jump through 2nd jump slot with 'normal continuation'"));
-			
+
 					tv1 = thr->valstack + cat->idx_base;
 					DUK_ASSERT(tv1 >= thr->valstack && tv1 < thr->valstack_top);
-					DUK_TVAL_SET_TVAL(&tv_tmp, tv1);
-					DUK_TVAL_SET_UNDEFINED_ACTUAL(tv1);
-					DUK_TVAL_DECREF(thr, &tv_tmp);     /* side effects */
+					DUK_TVAL_SET_UNDEFINED_UPDREF(thr, tv1);  /* side effects */
 					tv1 = NULL;
 
 					tv1 = thr->valstack + cat->idx_base + 1;
 					DUK_ASSERT(tv1 >= thr->valstack && tv1 < thr->valstack_top);
-					DUK_TVAL_SET_TVAL(&tv_tmp, tv1);
-					DUK_TVAL_SET_NUMBER(tv1, (duk_double_t) DUK_LJ_TYPE_NORMAL);  /* XXX: set int */
-					DUK_TVAL_DECREF(thr, &tv_tmp);     /* side effects */
+#if defined(DUK_USE_FASTINT)
+					DUK_TVAL_SET_FASTINT_U32_UPDREF(thr, tv1, (duk_uint32_t) DUK_LJ_TYPE_NORMAL);  /* side effects */
+#else
+					DUK_TVAL_SET_NUMBER_UPDREF(thr, tv1, (duk_double_t) DUK_LJ_TYPE_NORMAL);  /* side effects */
+#endif
 					tv1 = NULL;
 
 					DUK_CAT_CLEAR_FINALLY_ENABLED(cat);
@@ -53537,13 +71374,13 @@ void duk_js_execute_bytecode(duk_hthread *entry_thread) {
 					/* no need to unwind callstack */
 				}
 
-				act->pc = cat->pc_base + 1;
+				curr_pc = cat->pc_base + 1;
 				break;
 			}
 
 			case DUK_EXTRAOP_ENDCATCH: {
+				duk_activation *act;
 				duk_catcher *cat;
-				duk_tval tv_tmp;
 				duk_tval *tv1;
 
 				DUK_ASSERT(thr->catchstack_top >= 1);
@@ -53553,6 +71390,8 @@ void duk_js_execute_bytecode(duk_hthread *entry_thread) {
 				cat = thr->catchstack + thr->catchstack_top - 1;
 				DUK_ASSERT(!DUK_CAT_HAS_CATCH_ENABLED(cat));  /* cleared before entering catch part */
 
+				act = thr->callstack + thr->callstack_top - 1;
+
 				if (DUK_CAT_HAS_LEXENV_ACTIVE(cat)) {
 					duk_hobject *prev_env;
 
@@ -53564,26 +71403,26 @@ void duk_js_execute_bytecode(duk_hthread *entry_thread) {
 
 					prev_env = act->lex_env;
 					DUK_ASSERT(prev_env != NULL);
-					act->lex_env = prev_env->prototype;
+					act->lex_env = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, prev_env);
 					DUK_CAT_CLEAR_LEXENV_ACTIVE(cat);
 					DUK_HOBJECT_DECREF(thr, prev_env);  /* side effects */
 				}
 
 				if (DUK_CAT_HAS_FINALLY_ENABLED(cat)) {
 					DUK_DDD(DUK_DDDPRINT("ENDCATCH: finally part is active, jump through 2nd jump slot with 'normal continuation'"));
-			
+
 					tv1 = thr->valstack + cat->idx_base;
 					DUK_ASSERT(tv1 >= thr->valstack && tv1 < thr->valstack_top);
-					DUK_TVAL_SET_TVAL(&tv_tmp, tv1);
-					DUK_TVAL_SET_UNDEFINED_ACTUAL(tv1);
-					DUK_TVAL_DECREF(thr, &tv_tmp);     /* side effects */
+					DUK_TVAL_SET_UNDEFINED_UPDREF(thr, tv1);  /* side effects */
 					tv1 = NULL;
 
 					tv1 = thr->valstack + cat->idx_base + 1;
 					DUK_ASSERT(tv1 >= thr->valstack && tv1 < thr->valstack_top);
-					DUK_TVAL_SET_TVAL(&tv_tmp, tv1);
-					DUK_TVAL_SET_NUMBER(tv1, (duk_double_t) DUK_LJ_TYPE_NORMAL);  /* XXX: set int */
-					DUK_TVAL_DECREF(thr, &tv_tmp);     /* side effects */
+#if defined(DUK_USE_FASTINT)
+					DUK_TVAL_SET_FASTINT_U32_UPDREF(thr, tv1, (duk_uint32_t) DUK_LJ_TYPE_NORMAL);  /* side effects */
+#else
+					DUK_TVAL_SET_NUMBER_UPDREF(thr, tv1, (duk_double_t) DUK_LJ_TYPE_NORMAL);  /* side effects */
+#endif
 					tv1 = NULL;
 
 					DUK_CAT_CLEAR_FINALLY_ENABLED(cat);
@@ -53593,7 +71432,7 @@ void duk_js_execute_bytecode(duk_hthread *entry_thread) {
 					/* no need to unwind callstack */
 				}
 
-				act->pc = cat->pc_base + 1;
+				curr_pc = cat->pc_base + 1;
 				break;
 			}
 
@@ -53601,7 +71440,11 @@ void duk_js_execute_bytecode(duk_hthread *entry_thread) {
 				duk_context *ctx = (duk_context *) thr;
 				duk_catcher *cat;
 				duk_tval *tv1;
-				duk_small_uint_fast_t cont_type;
+				duk_small_uint_t cont_type;
+				duk_small_uint_t ret_result;
+
+				/* Sync and NULL early. */
+				DUK__SYNC_AND_NULL_CURR_PC();
 
 				DUK_ASSERT(thr->catchstack_top >= 1);
 				DUK_ASSERT(thr->callstack_top >= 1);
@@ -53622,42 +71465,105 @@ void duk_js_execute_bytecode(duk_hthread *entry_thread) {
 
 				tv1 = thr->valstack + cat->idx_base + 1;  /* type */
 				DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv1));
-				cont_type = (duk_small_uint_fast_t) DUK_TVAL_GET_NUMBER(tv1);
+				cont_type = (duk_small_uint_t) DUK_TVAL_GET_NUMBER(tv1);
 
-				if (cont_type == DUK_LJ_TYPE_NORMAL) {
+				switch (cont_type) {
+				case DUK_LJ_TYPE_NORMAL: {
 					DUK_DDD(DUK_DDDPRINT("ENDFIN: finally part finishing with 'normal' (non-abrupt) completion -> "
 					                     "dismantle catcher, resume execution after ENDFIN"));
 					duk_hthread_catchstack_unwind(thr, thr->catchstack_top - 1);
 					/* no need to unwind callstack */
-				} else {
+					goto restart_execution;
+				}
+				case DUK_LJ_TYPE_RETURN: {
+					DUK_DDD(DUK_DDDPRINT("ENDFIN: finally part finishing with 'return' complation -> dismantle "
+					                     "catcher, handle return, lj.value1=%!T", thr->valstack + cat->idx_base));
+
+					/* Not necessary to unwind catchstack: return handling will
+					 * do it.  The finally flag of 'cat' is no longer set.  The
+					 * catch flag may be set, but it's not checked by return handling.
+					 */
+					DUK_ASSERT(!DUK_CAT_HAS_FINALLY_ENABLED(cat));  /* cleared before entering finally */
+#if 0
+					duk_hthread_catchstack_unwind(thr, thr->catchstack_top - 1);
+#endif
+
+					duk_push_tval(ctx, thr->valstack + cat->idx_base);
+					ret_result = duk__handle_return(thr,
+						                        entry_thread,
+						                        entry_callstack_top);
+					if (ret_result == DUK__RETHAND_RESTART) {
+						goto restart_execution;
+					}
+					DUK_ASSERT(ret_result == DUK__RETHAND_FINISHED);
+
+					DUK_DDD(DUK_DDDPRINT("exiting executor after ENDFIN and RETURN (pseudo) longjmp type"));
+					return;
+				}
+				case DUK_LJ_TYPE_BREAK:
+				case DUK_LJ_TYPE_CONTINUE: {
+					duk_uint_t label_id;
+					duk_small_uint_t lj_type;
+
+					/* Not necessary to unwind catchstack: break/continue
+					 * handling will do it.  The finally flag of 'cat' is
+					 * no longer set.  The catch flag may be set, but it's
+					 * not checked by break/continue handling.
+					 */
+#if 0
+					duk_hthread_catchstack_unwind(thr, thr->catchstack_top - 1);
+#endif
+
+					tv1 = thr->valstack + cat->idx_base;
+					DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv1));
+#if defined(DUK_USE_FASTINT)
+					DUK_ASSERT(DUK_TVAL_IS_FASTINT(tv1));
+					label_id = (duk_small_uint_t) DUK_TVAL_GET_FASTINT_U32(tv1);
+#else
+					label_id = (duk_small_uint_t) DUK_TVAL_GET_NUMBER(tv1);
+#endif
+					lj_type = cont_type;
+					duk__handle_break_or_continue(thr, label_id, lj_type);
+					goto restart_execution;
+				}
+				default: {
 					DUK_DDD(DUK_DDDPRINT("ENDFIN: finally part finishing with abrupt completion, lj_type=%ld -> "
 					                     "dismantle catcher, re-throw error",
 					                     (long) cont_type));
 
 					duk_push_tval(ctx, thr->valstack + cat->idx_base);
 
-					/* XXX: assert lj type valid */
 					duk_err_setup_heap_ljstate(thr, (duk_small_int_t) cont_type);
 
+#if !defined(DUK_USE_CPP_EXCEPTIONS)
 					DUK_ASSERT(thr->heap->lj.jmpbuf_ptr != NULL);  /* always in executor */
+#endif
 					duk_err_longjmp(thr);
 					DUK_UNREACHABLE();
 				}
+				}
 
-				/* continue execution after ENDFIN */
+				/* Must restart in all cases because we NULLed thr->ptr_curr_pc. */
+				DUK_UNREACHABLE();
 				break;
 			}
 
 			case DUK_EXTRAOP_THROW: {
 				duk_context *ctx = (duk_context *) thr;
-				duk_small_uint_fast_t b = DUK_DEC_B(ins);
+				duk_uint_fast_t bc = DUK_DEC_BC(ins);
 
 				/* Note: errors are augmented when they are created, not
 				 * when they are thrown.  So, don't augment here, it would
 				 * break re-throwing for instance.
 				 */
 
-				duk_dup(ctx, (duk_idx_t) b);
+				/* Sync so that augmentation sees up-to-date activations, NULL
+				 * thr->ptr_curr_pc so that it's not used if side effects occur
+				 * in augmentation or longjmp handling.
+				 */
+				DUK__SYNC_AND_NULL_CURR_PC();
+
+				duk_dup(ctx, (duk_idx_t) bc);
 				DUK_DDD(DUK_DDDPRINT("THROW ERROR (BYTECODE): %!dT (before throw augment)",
 				                     (duk_tval *) duk_get_tval(ctx, -1)));
 #if defined(DUK_USE_AUGMENT_ERROR_THROW)
@@ -53668,9 +71574,10 @@ void duk_js_execute_bytecode(duk_hthread *entry_thread) {
 
 				duk_err_setup_heap_ljstate(thr, DUK_LJ_TYPE_THROW);
 
+#if !defined(DUK_USE_CPP_EXCEPTIONS)
 				DUK_ASSERT(thr->heap->lj.jmpbuf_ptr != NULL);  /* always in executor */
+#endif
 				duk_err_longjmp(thr);
-
 				DUK_UNREACHABLE();
 				break;
 			}
@@ -53683,46 +71590,139 @@ void duk_js_execute_bytecode(duk_hthread *entry_thread) {
 			}
 
 			case DUK_EXTRAOP_UNM:
-			case DUK_EXTRAOP_UNP:
-			case DUK_EXTRAOP_INC:
-			case DUK_EXTRAOP_DEC: {
-				duk_small_uint_fast_t b = DUK_DEC_B(ins);
-				duk_small_uint_fast_t c = DUK_DEC_C(ins);
+			case DUK_EXTRAOP_UNP: {
+				duk_uint_fast_t bc = DUK_DEC_BC(ins);
+				duk__vm_arith_unary_op(thr, DUK__REGP(bc), bc, extraop);
+				break;
+			}
 
-				duk__vm_arith_unary_op(thr, DUK__REGCONSTP(c), b, extraop);
+			case DUK_EXTRAOP_DEBUGGER: {
+				/* Opcode only emitted by compiler when debugger
+				 * support is enabled.  Ignore it silently without
+				 * debugger support, in case it has been loaded
+				 * from precompiled bytecode.
+				 */
+#if defined(DUK_USE_DEBUGGER_SUPPORT)
+				if (DUK_HEAP_IS_DEBUGGER_ATTACHED(thr->heap)) {
+					DUK_D(DUK_DPRINT("DEBUGGER statement encountered, halt execution"));
+					DUK__SYNC_AND_NULL_CURR_PC();
+					duk_debug_halt_execution(thr, 1 /*use_prev_pc*/);
+					DUK_D(DUK_DPRINT("DEBUGGER statement finished, resume execution"));
+					goto restart_execution;
+				} else {
+					DUK_D(DUK_DPRINT("DEBUGGER statement ignored, debugger not attached"));
+				}
+#else
+				DUK_D(DUK_DPRINT("DEBUGGER statement ignored, no debugger support"));
+#endif
 				break;
 			}
 
-#ifdef DUK_USE_DEBUG
-			case DUK_EXTRAOP_DUMPREG: {
-				DUK_D(DUK_DPRINT("DUMPREG: %ld -> %!T",
-				                 (long) DUK_DEC_BC(ins),
-				                 (duk_tval *) duk_get_tval((duk_context *) thr, (duk_idx_t) DUK_DEC_BC(ins))));
+			case DUK_EXTRAOP_BREAK: {
+				duk_uint_fast_t bc = DUK_DEC_BC(ins);
+
+				DUK_DDD(DUK_DDDPRINT("BREAK: %ld", (long) bc));
+
+				DUK__SYNC_AND_NULL_CURR_PC();
+				duk__handle_break_or_continue(thr, (duk_uint_t) bc, DUK_LJ_TYPE_BREAK);
+				goto restart_execution;
+			}
+
+			case DUK_EXTRAOP_CONTINUE: {
+				duk_uint_fast_t bc = DUK_DEC_BC(ins);
+
+				DUK_DDD(DUK_DDDPRINT("CONTINUE: %ld", (long) bc));
+
+				DUK__SYNC_AND_NULL_CURR_PC();
+				duk__handle_break_or_continue(thr, (duk_uint_t) bc, DUK_LJ_TYPE_CONTINUE);
+				goto restart_execution;
+			}
+
+			case DUK_EXTRAOP_BNOT: {
+				duk_uint_fast_t bc = DUK_DEC_BC(ins);
+
+				duk__vm_bitwise_not(thr, DUK__REGP(bc), bc);
 				break;
 			}
 
-			case DUK_EXTRAOP_DUMPREGS: {
-				duk_idx_t i, i_top;
-				i_top = duk_get_top((duk_context *) thr);
-				DUK_D(DUK_DPRINT("DUMPREGS: %ld regs", (long) i_top));
-				for (i = 0; i < i_top; i++) {
-					DUK_D(DUK_DPRINT("  r%ld -> %!dT",
-					                 (long) i,
-					                 (duk_tval *) duk_get_tval((duk_context *) thr, i)));
-				}
+			case DUK_EXTRAOP_LNOT: {
+				duk_uint_fast_t bc = DUK_DEC_BC(ins);
+				duk_tval *tv1;
+
+				tv1 = DUK__REGP(bc);
+				duk__vm_logical_not(thr, tv1, tv1);
 				break;
 			}
 
-			case DUK_EXTRAOP_DUMPTHREAD: {
-				DUK_DEBUG_DUMP_HTHREAD(thr);
+			case DUK_EXTRAOP_INSTOF: {
+				duk_context *ctx = (duk_context *) thr;
+				duk_small_uint_fast_t b = DUK_DEC_B(ins);
+				duk_small_uint_fast_t c = DUK_DEC_C(ins);
+				duk_bool_t tmp;
+
+				tmp = duk_js_instanceof(thr, DUK__REGP(b), DUK__REGCONSTP(c));
+				duk_push_boolean(ctx, tmp);
+				duk_replace(ctx, (duk_idx_t) b);
 				break;
 			}
 
-			case DUK_EXTRAOP_LOGMARK: {
-				DUK_D(DUK_DPRINT("LOGMARK: mark %ld at pc %ld", (long) DUK_DEC_BC(ins), (long) (act->pc - 1)));  /* -1, autoinc */
+			case DUK_EXTRAOP_IN: {
+				duk_context *ctx = (duk_context *) thr;
+				duk_small_uint_fast_t b = DUK_DEC_B(ins);
+				duk_small_uint_fast_t c = DUK_DEC_C(ins);
+				duk_bool_t tmp;
+
+				tmp = duk_js_in(thr, DUK__REGP(b), DUK__REGCONSTP(c));
+				duk_push_boolean(ctx, tmp);
+				duk_replace(ctx, (duk_idx_t) b);
+				break;
+			}
+
+			case DUK_EXTRAOP_LABEL: {
+				duk_catcher *cat;
+				duk_uint_fast_t bc = DUK_DEC_BC(ins);
+
+				/* allocate catcher and populate it (should be atomic) */
+
+				duk_hthread_catchstack_grow(thr);
+				cat = thr->catchstack + thr->catchstack_top;
+				thr->catchstack_top++;
+
+				cat->flags = DUK_CAT_TYPE_LABEL | (bc << DUK_CAT_LABEL_SHIFT);
+				cat->callstack_index = thr->callstack_top - 1;
+				cat->pc_base = (duk_instr_t *) curr_pc;  /* pre-incremented, points to first jump slot */
+				cat->idx_base = 0;  /* unused for label */
+				cat->h_varname = NULL;
+
+				DUK_DDD(DUK_DDDPRINT("LABEL catcher: flags=0x%08lx, callstack_index=%ld, pc_base=%ld, "
+				                     "idx_base=%ld, h_varname=%!O, label_id=%ld",
+				                     (long) cat->flags, (long) cat->callstack_index, (long) cat->pc_base,
+				                     (long) cat->idx_base, (duk_heaphdr *) cat->h_varname, (long) DUK_CAT_GET_LABEL(cat)));
+
+				curr_pc += 2;  /* skip jump slots */
+				break;
+			}
+
+			case DUK_EXTRAOP_ENDLABEL: {
+				duk_catcher *cat;
+#if defined(DUK_USE_DDDPRINT) || defined(DUK_USE_ASSERTIONS)
+				duk_uint_fast_t bc = DUK_DEC_BC(ins);
+#endif
+#if defined(DUK_USE_DDDPRINT)
+				DUK_DDD(DUK_DDDPRINT("ENDLABEL %ld", (long) bc));
+#endif
+
+				DUK_ASSERT(thr->catchstack_top >= 1);
+
+				cat = thr->catchstack + thr->catchstack_top - 1;
+				DUK_UNREF(cat);
+				DUK_ASSERT(DUK_CAT_GET_TYPE(cat) == DUK_CAT_TYPE_LABEL);
+				DUK_ASSERT((duk_uint_fast_t) DUK_CAT_GET_LABEL(cat) == bc);
+
+				duk_hthread_catchstack_unwind(thr, thr->catchstack_top - 1);
+				/* no need to unwind callstack */
 				break;
 			}
-#endif  /* DUK_USE_DEBUG */
 
 			default: {
 				DUK__INTERNAL_ERROR("invalid extra opcode");
@@ -53733,11 +71733,6 @@ void duk_js_execute_bytecode(duk_hthread *entry_thread) {
 			break;
 		}
 
-		case DUK_OP_INVALID: {
-			DUK_ERROR(thr, DUK_ERR_INTERNAL_ERROR, "INVALID opcode (%ld)", (long) DUK_DEC_ABC(ins));
-			break;
-		}
-
 		default: {
 			/* this should never be possible, because the switch-case is
 			 * comprehensive
@@ -53756,7 +71751,16 @@ void duk_js_execute_bytecode(duk_hthread *entry_thread) {
 #endif
 }
 
+#undef DUK__LONGJMP_RESTART
+#undef DUK__LONGJMP_FINISHED
+#undef DUK__LONGJMP_RETHROW
+
+#undef DUK__RETHAND_RESTART
+#undef DUK__RETHAND_FINISHED
+
 #undef DUK__INTERNAL_ERROR
+#undef DUK__SYNC_CURR_PC
+#undef DUK__SYNC_AND_NULL_CURR_PC
 #line 1 "duk_js_ops.c"
 /*
  *  Ecmascript specification algorithm and conversion helpers.
@@ -53822,7 +71826,7 @@ void duk_js_execute_bytecode(duk_hthread *entry_thread) {
  *  ToBoolean()  (E5 Section 9.2)
  */
 
-duk_bool_t duk_js_toboolean(duk_tval *tv) {
+DUK_INTERNAL duk_bool_t duk_js_toboolean(duk_tval *tv) {
 	switch (DUK_TVAL_GET_TAG(tv)) {
 	case DUK_TAG_UNDEFINED:
 	case DUK_TAG_NULL:
@@ -53832,7 +71836,7 @@ duk_bool_t duk_js_toboolean(duk_tval *tv) {
 	case DUK_TAG_STRING: {
 		duk_hstring *h = DUK_TVAL_GET_STRING(tv);
 		DUK_ASSERT(h != NULL);
-		return (h->blen > 0 ? 1 : 0);
+		return (DUK_HSTRING_GET_BYTELEN(h) > 0 ? 1 : 0);
 	}
 	case DUK_TAG_OBJECT: {
 		return 1;
@@ -53847,11 +71851,25 @@ duk_bool_t duk_js_toboolean(duk_tval *tv) {
 		void *p = DUK_TVAL_GET_POINTER(tv);
 		return (p != NULL ? 1 : 0);
 	}
+	case DUK_TAG_LIGHTFUNC: {
+		return 1;
+	}
+#if defined(DUK_USE_FASTINT)
+	case DUK_TAG_FASTINT:
+		if (DUK_TVAL_GET_FASTINT(tv) != 0) {
+			return 1;
+		} else {
+			return 0;
+		}
+#endif
 	default: {
 		/* number */
+		duk_double_t d;
 		int c;
-		DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));
-		c = DUK_FPCLASSIFY(DUK_TVAL_GET_NUMBER(tv));
+		DUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv));
+		DUK_ASSERT(DUK_TVAL_IS_DOUBLE(tv));
+		d = DUK_TVAL_GET_DOUBLE(tv);
+		c = DUK_FPCLASSIFY((double) d);
 		if (c == DUK_FP_ZERO || c == DUK_FP_NAN) {
 			return 0;
 		} else {
@@ -53888,10 +71906,10 @@ duk_bool_t duk_js_toboolean(duk_tval *tv) {
  *
  *    - Unlike source code literals, ToNumber() coerces empty strings
  *      and strings with only whitespace to zero (not NaN).
- */	
+ */
 
 /* E5 Section 9.3.1 */
-static duk_double_t duk__tonumber_string_raw(duk_hthread *thr) {
+DUK_LOCAL duk_double_t duk__tonumber_string_raw(duk_hthread *thr) {
 	duk_context *ctx = (duk_context *) thr;
 	duk_small_uint_t s2n_flags;
 	duk_double_t d;
@@ -53918,7 +71936,7 @@ static duk_double_t duk__tonumber_string_raw(duk_hthread *thr) {
 	return d;
 }
 
-duk_double_t duk_js_tonumber(duk_hthread *thr, duk_tval *tv) {
+DUK_INTERNAL duk_double_t duk_js_tonumber(duk_hthread *thr, duk_tval *tv) {
 	duk_context *ctx = (duk_hthread *) thr;
 
 	DUK_ASSERT(thr != NULL);
@@ -53973,17 +71991,23 @@ duk_double_t duk_js_tonumber(duk_hthread *thr, duk_tval *tv) {
 		return duk__tonumber_string_raw(thr);
 	}
 	case DUK_TAG_POINTER: {
-		/* Coerce like boolean.  This allows code to do something like:
-		 *
-		 *    if (ptr) { ... }
-		 */
+		/* Coerce like boolean */
 		void *p = DUK_TVAL_GET_POINTER(tv);
 		return (p != NULL ? 1.0 : 0.0);
 	}
+	case DUK_TAG_LIGHTFUNC: {
+		/* +(function(){}) -> NaN */
+		return DUK_DOUBLE_NAN;
+	}
+#if defined(DUK_USE_FASTINT)
+	case DUK_TAG_FASTINT:
+		return (duk_double_t) DUK_TVAL_GET_FASTINT(tv);
+#endif
 	default: {
 		/* number */
-		DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));
-		return DUK_TVAL_GET_NUMBER(tv);
+		DUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv));
+		DUK_ASSERT(DUK_TVAL_IS_DOUBLE(tv));
+		return DUK_TVAL_GET_DOUBLE(tv);
 	}
 	}
 
@@ -53995,7 +72019,7 @@ duk_double_t duk_js_tonumber(duk_hthread *thr, duk_tval *tv) {
  */
 
 /* exposed, used by e.g. duk_bi_date.c */
-duk_double_t duk_js_tointeger_number(duk_double_t x) {
+DUK_INTERNAL duk_double_t duk_js_tointeger_number(duk_double_t x) {
 	duk_small_int_t c = (duk_small_int_t) DUK_FPCLASSIFY(x);
 
 	if (c == DUK_FP_NAN) {
@@ -54015,7 +72039,8 @@ duk_double_t duk_js_tointeger_number(duk_double_t x) {
 	}
 }
 
-duk_double_t duk_js_tointeger(duk_hthread *thr, duk_tval *tv) {
+DUK_INTERNAL duk_double_t duk_js_tointeger(duk_hthread *thr, duk_tval *tv) {
+	/* XXX: fastint */
 	duk_double_t d = duk_js_tonumber(thr, tv);  /* invalidates tv */
 	return duk_js_tointeger_number(d);
 }
@@ -54024,8 +72049,8 @@ duk_double_t duk_js_tointeger(duk_hthread *thr, duk_tval *tv) {
  *  ToInt32(), ToUint32(), ToUint16()  (E5 Sections 9.5, 9.6, 9.7)
  */
 
-/* combined algorithm matching E5 Sections 9.5 and 9.6 */	
-static duk_double_t duk__toint32_touint32_helper(duk_double_t x, duk_bool_t is_toint32) {
+/* combined algorithm matching E5 Sections 9.5 and 9.6 */
+DUK_LOCAL duk_double_t duk__toint32_touint32_helper(duk_double_t x, duk_bool_t is_toint32) {
 	duk_small_int_t c = (duk_small_int_t) DUK_FPCLASSIFY(x);
 	duk_small_int_t s;
 
@@ -54040,7 +72065,7 @@ static duk_double_t duk__toint32_touint32_helper(duk_double_t x, duk_bool_t is_t
 	if (s) {
 		x = -x;
 	}
-	
+
 	/* NOTE: fmod(x) result sign is same as sign of x, which
 	 * differs from what Javascript wants (see Section 9.6).
 	 */
@@ -54063,8 +72088,16 @@ static duk_double_t duk__toint32_touint32_helper(duk_double_t x, duk_bool_t is_t
 	return x;
 }
 
-duk_int32_t duk_js_toint32(duk_hthread *thr, duk_tval *tv) {
-	duk_double_t d = duk_js_tonumber(thr, tv);  /* invalidates tv */
+DUK_INTERNAL duk_int32_t duk_js_toint32(duk_hthread *thr, duk_tval *tv) {
+	duk_double_t d;
+
+#if defined(DUK_USE_FASTINT)
+	if (DUK_TVAL_IS_FASTINT(tv)) {
+		return DUK_TVAL_GET_FASTINT_I32(tv);
+	}
+#endif
+
+	d = duk_js_tonumber(thr, tv);  /* invalidates tv */
 	d = duk__toint32_touint32_helper(d, 1);
 	DUK_ASSERT(DUK_FPCLASSIFY(d) == DUK_FP_ZERO || DUK_FPCLASSIFY(d) == DUK_FP_NORMAL);
 	DUK_ASSERT(d >= -2147483648.0 && d <= 2147483647.0);  /* [-0x80000000,0x7fffffff] */
@@ -54073,8 +72106,16 @@ duk_int32_t duk_js_toint32(duk_hthread *thr, duk_tval *tv) {
 }
 
 
-duk_uint32_t duk_js_touint32(duk_hthread *thr, duk_tval *tv) {
-	duk_double_t d = duk_js_tonumber(thr, tv);  /* invalidates tv */
+DUK_INTERNAL duk_uint32_t duk_js_touint32(duk_hthread *thr, duk_tval *tv) {
+	duk_double_t d;
+
+#if defined(DUK_USE_FASTINT)
+	if (DUK_TVAL_IS_FASTINT(tv)) {
+		return DUK_TVAL_GET_FASTINT_U32(tv);
+	}
+#endif
+
+	d = duk_js_tonumber(thr, tv);  /* invalidates tv */
 	d = duk__toint32_touint32_helper(d, 0);
 	DUK_ASSERT(DUK_FPCLASSIFY(d) == DUK_FP_ZERO || DUK_FPCLASSIFY(d) == DUK_FP_NORMAL);
 	DUK_ASSERT(d >= 0.0 && d <= 4294967295.0);  /* [0x00000000, 0xffffffff] */
@@ -54083,7 +72124,7 @@ duk_uint32_t duk_js_touint32(duk_hthread *thr, duk_tval *tv) {
 
 }
 
-duk_uint16_t duk_js_touint16(duk_hthread *thr, duk_tval *tv) {
+DUK_INTERNAL duk_uint16_t duk_js_touint16(duk_hthread *thr, duk_tval *tv) {
 	/* should be a safe way to compute this */
 	return (duk_uint16_t) (duk_js_touint32(thr, tv) & 0x0000ffffU);
 }
@@ -54107,7 +72148,7 @@ duk_uint16_t duk_js_touint16(duk_hthread *thr, duk_tval *tv) {
  */
 
 #if 0  /* unused */
-void duk_js_checkobjectcoercible(duk_hthread *thr, duk_tval *tv_x) {
+DUK_INTERNAL void duk_js_checkobjectcoercible(duk_hthread *thr, duk_tval *tv_x) {
 	duk_small_uint_t tag = DUK_TVAL_GET_TAG(tv_x);
 
 	/* Note: this must match ToObject() behavior */
@@ -54129,7 +72170,7 @@ void duk_js_checkobjectcoercible(duk_hthread *thr, duk_tval *tv_x) {
  */
 
 #if 0  /* unused */
-int duk_js_iscallable(duk_tval *tv_x) {
+DUK_INTERNAL duk_bool_t duk_js_iscallable(duk_tval *tv_x) {
 	duk_hobject *obj;
 
 	if (!DUK_TVAL_IS_OBJECT(tv_x)) {
@@ -54160,7 +72201,7 @@ int duk_js_iscallable(duk_tval *tv_x) {
  *  - E5 Section 11.9.6, step 4 (strict)
  */
 
-static duk_bool_t duk__js_equals_number(duk_double_t x, duk_double_t y) {
+DUK_LOCAL duk_bool_t duk__js_equals_number(duk_double_t x, duk_double_t y) {
 #if defined(DUK_USE_PARANOID_MATH)
 	/* Straightforward algorithm, makes fewer compiler assumptions. */
 	duk_small_int_t cx = (duk_small_int_t) DUK_FPCLASSIFY(x);
@@ -54198,7 +72239,7 @@ static duk_bool_t duk__js_equals_number(duk_double_t x, duk_double_t y) {
 #endif  /* DUK_USE_PARANOID_MATH */
 }
 
-static duk_bool_t duk__js_samevalue_number(duk_double_t x, duk_double_t y) {
+DUK_LOCAL duk_bool_t duk__js_samevalue_number(duk_double_t x, duk_double_t y) {
 #if defined(DUK_USE_PARANOID_MATH)
 	duk_small_int_t cx = (duk_small_int_t) DUK_FPCLASSIFY(x);
 	duk_small_int_t cy = (duk_small_int_t) DUK_FPCLASSIFY(y);
@@ -54265,7 +72306,7 @@ static duk_bool_t duk__js_samevalue_number(duk_double_t x, duk_double_t y) {
 #endif  /* DUK_USE_PARANOID_MATH */
 }
 
-duk_bool_t duk_js_equals_helper(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_y, duk_small_int_t flags) {
+DUK_INTERNAL duk_bool_t duk_js_equals_helper(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_y, duk_small_int_t flags) {
 	duk_context *ctx = (duk_context *) thr;
 	duk_tval *tv_tmp;
 
@@ -54281,7 +72322,18 @@ duk_bool_t duk_js_equals_helper(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_y
 	 *  representation, need the awkward if + switch.
 	 */
 
+#if defined(DUK_USE_FASTINT)
+	if (DUK_TVAL_IS_FASTINT(tv_x) && DUK_TVAL_IS_FASTINT(tv_y)) {
+		if (DUK_TVAL_GET_FASTINT(tv_x) == DUK_TVAL_GET_FASTINT(tv_y)) {
+			return 1;
+		} else {
+			return 0;
+		}
+	}
+	else
+#endif
 	if (DUK_TVAL_IS_NUMBER(tv_x) && DUK_TVAL_IS_NUMBER(tv_y)) {
+		/* Catches both doubles and cases where only one argument is a fastint */
 		if (DUK_UNLIKELY((flags & DUK_EQUALS_FLAG_SAMEVALUE) != 0)) {
 			/* SameValue */
 			return duk__js_samevalue_number(DUK_TVAL_GET_NUMBER(tv_x),
@@ -54323,18 +72375,36 @@ duk_bool_t duk_js_equals_helper(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_y
 				if (len_x != len_y) {
 					return 0;
 				}
-				buf_x = (void *) DUK_HBUFFER_GET_DATA_PTR(h_x);
-				buf_y = (void *) DUK_HBUFFER_GET_DATA_PTR(h_y);
+				buf_x = (void *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h_x);
+				buf_y = (void *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h_y);
 				/* if len_x == len_y == 0, buf_x and/or buf_y may
 				 * be NULL, but that's OK.
 				 */
 				DUK_ASSERT(len_x == len_y);
 				DUK_ASSERT(len_x == 0 || buf_x != NULL);
 				DUK_ASSERT(len_y == 0 || buf_y != NULL);
-				return (DUK_MEMCMP(buf_x, buf_y, len_x) == 0) ? 1 : 0;
+				return (DUK_MEMCMP((const void *) buf_x, (const void *) buf_y, (size_t) len_x) == 0) ? 1 : 0;
 			}
 		}
+		case DUK_TAG_LIGHTFUNC: {
+			/* At least 'magic' has a significant impact on function
+			 * identity.
+			 */
+			duk_small_uint_t lf_flags_x;
+			duk_small_uint_t lf_flags_y;
+			duk_c_function func_x;
+			duk_c_function func_y;
+
+			DUK_TVAL_GET_LIGHTFUNC(tv_x, func_x, lf_flags_x);
+			DUK_TVAL_GET_LIGHTFUNC(tv_y, func_y, lf_flags_y);
+			return ((func_x == func_y) && (lf_flags_x == lf_flags_y)) ? 1 : 0;
+		}
+#if defined(DUK_USE_FASTINT)
+		case DUK_TAG_FASTINT:
+#endif
 		default: {
+			DUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv_x));
+			DUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv_y));
 			DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv_x));
 			DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv_y));
 			DUK_UNREACHABLE();
@@ -54392,20 +72462,20 @@ duk_bool_t duk_js_equals_helper(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_y
 		duk_hbuffer *h_y = DUK_TVAL_GET_BUFFER(tv_y);
 		duk_size_t len_x = DUK_HSTRING_GET_BYTELEN(h_x);
 		duk_size_t len_y = DUK_HBUFFER_GET_SIZE(h_y);
-		void *buf_x;
-		void *buf_y;
+		const void *buf_x;
+		const void *buf_y;
 		if (len_x != len_y) {
 			return 0;
 		}
-		buf_x = (void *) DUK_HSTRING_GET_DATA(h_x);
-		buf_y = (void *) DUK_HBUFFER_GET_DATA_PTR(h_y);
+		buf_x = (const void *) DUK_HSTRING_GET_DATA(h_x);
+		buf_y = (const void *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h_y);
 		/* if len_x == len_y == 0, buf_x and/or buf_y may
 		 * be NULL, but that's OK.
 		 */
 		DUK_ASSERT(len_x == len_y);
 		DUK_ASSERT(len_x == 0 || buf_x != NULL);
 		DUK_ASSERT(len_y == 0 || buf_y != NULL);
-		return (DUK_MEMCMP(buf_x, buf_y, len_x) == 0) ? 1 : 0;
+		return (DUK_MEMCMP((const void *) buf_x, (const void *) buf_y, (size_t) len_x) == 0) ? 1 : 0;
 	}
 
 	/* Boolean/any -> coerce boolean to number and try again.  If boolean is
@@ -54462,7 +72532,37 @@ duk_bool_t duk_js_equals_helper(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_y
  * needs to push stuff on the stack anyway...
  */
 
-duk_small_int_t duk_js_string_compare(duk_hstring *h1, duk_hstring *h2) {
+DUK_INTERNAL duk_small_int_t duk_js_data_compare(const duk_uint8_t *buf1, const duk_uint8_t *buf2, duk_size_t len1, duk_size_t len2) {
+	duk_size_t prefix_len;
+	duk_small_int_t rc;
+
+	prefix_len = (len1 <= len2 ? len1 : len2);
+
+	/* DUK_MEMCMP() is guaranteed to return zero (equal) for zero length
+	 * inputs so no zero length check is needed.
+	 */
+	rc = DUK_MEMCMP((const void *) buf1,
+	                (const void *) buf2,
+	                (size_t) prefix_len);
+
+	if (rc < 0) {
+		return -1;
+	} else if (rc > 0) {
+		return 1;
+	}
+
+	/* prefix matches, lengths matter now */
+	if (len1 < len2) {
+		/* e.g. "x" < "xx" */
+		return -1;
+	} else if (len1 > len2) {
+		return 1;
+	}
+
+	return 0;
+}
+
+DUK_INTERNAL duk_small_int_t duk_js_string_compare(duk_hstring *h1, duk_hstring *h2) {
 	/*
 	 *  String comparison (E5 Section 11.8.5, step 4), which
 	 *  needs to compare codepoint by codepoint.
@@ -54476,47 +72576,31 @@ duk_small_int_t duk_js_string_compare(duk_hstring *h1, duk_hstring *h2) {
 	 *  is not an issue for compliance.
 	 */
 
-	duk_size_t h1_len, h2_len, prefix_len;
-	duk_small_int_t rc;
-
 	DUK_ASSERT(h1 != NULL);
 	DUK_ASSERT(h2 != NULL);
-	h1_len = DUK_HSTRING_GET_BYTELEN(h1);
-	h2_len = DUK_HSTRING_GET_BYTELEN(h2);
-	prefix_len = (h1_len <= h2_len ? h1_len : h2_len);
-
-	/* XXX: this special case can now be removed with DUK_MEMCMP */
-	/* memcmp() should return zero (equal) for zero length, but avoid
-	 * it because there are some platform specific bugs.  Don't use
-	 * strncmp() because it stops comparing at a NUL.
-	 */
 
-	if (prefix_len == 0) {
-		rc = 0;
-	} else {
-		rc = DUK_MEMCMP((const char *) DUK_HSTRING_GET_DATA(h1),
-		                (const char *) DUK_HSTRING_GET_DATA(h2),
-		                prefix_len);
-	}
+	return duk_js_data_compare((const duk_uint8_t *) DUK_HSTRING_GET_DATA(h1),
+	                           (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h2),
+	                           (duk_size_t) DUK_HSTRING_GET_BYTELEN(h1),
+	                           (duk_size_t) DUK_HSTRING_GET_BYTELEN(h2));
+}
 
-	if (rc < 0) {
-		return -1;
-	} else if (rc > 0) {
-		return 1;
-	}
+#if 0  /* unused */
+DUK_INTERNAL duk_small_int_t duk_js_buffer_compare(duk_heap *heap, duk_hbuffer *h1, duk_hbuffer *h2) {
+	/* Similar to String comparison. */
 
-	/* prefix matches, lengths matter now */
-	if (h1_len < h2_len) {
-		/* e.g. "x" < "xx" */
-		return -1;
-	} else if (h1_len > h2_len) {
-		return 1;
-	}
+	DUK_ASSERT(h1 != NULL);
+	DUK_ASSERT(h2 != NULL);
+	DUK_UNREF(heap);
 
-	return 0;
+	return duk_js_data_compare((const duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(heap, h1),
+	                           (const duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(heap, h2),
+	                           (duk_size_t) DUK_HBUFFER_GET_SIZE(h1),
+	                           (duk_size_t) DUK_HBUFFER_GET_SIZE(h2));
 }
+#endif
 
-duk_bool_t duk_js_compare_helper(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_y, duk_small_int_t flags) {
+DUK_INTERNAL duk_bool_t duk_js_compare_helper(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_y, duk_small_int_t flags) {
 	duk_context *ctx = (duk_context *) thr;
 	duk_double_t d1, d2;
 	duk_small_int_t c1, c2;
@@ -54524,6 +72608,53 @@ duk_bool_t duk_js_compare_helper(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_
 	duk_small_int_t rc;
 	duk_bool_t retval;
 
+	/* Fast path for fastints */
+#if defined(DUK_USE_FASTINT)
+	if (DUK_TVAL_IS_FASTINT(tv_x) && DUK_TVAL_IS_FASTINT(tv_y)) {
+		duk_int64_t v1 = DUK_TVAL_GET_FASTINT(tv_x);
+		duk_int64_t v2 = DUK_TVAL_GET_FASTINT(tv_y);
+		if (v1 < v2) {
+			/* 'lt is true' */
+			retval = 1;
+		} else {
+			retval = 0;
+		}
+		if (flags & DUK_COMPARE_FLAG_NEGATE) {
+			retval ^= 1;
+		}
+		return retval;
+	}
+#endif  /* DUK_USE_FASTINT */
+
+	/* Fast path for numbers (one of which may be a fastint) */
+#if 1  /* XXX: make fast paths optional for size minimization? */
+	if (DUK_TVAL_IS_NUMBER(tv_x) && DUK_TVAL_IS_NUMBER(tv_y)) {
+		d1 = DUK_TVAL_GET_NUMBER(tv_x);
+		d2 = DUK_TVAL_GET_NUMBER(tv_y);
+		c1 = DUK_FPCLASSIFY(d1);
+		c2 = DUK_FPCLASSIFY(d2);
+
+		if (c1 == DUK_FP_NORMAL && c2 == DUK_FP_NORMAL) {
+			/* XXX: this is a very narrow check, and doesn't cover
+			 * zeroes, subnormals, infinities, which compare normally.
+			 */
+
+			if (d1 < d2) {
+				/* 'lt is true' */
+				retval = 1;
+			} else {
+				retval = 0;
+			}
+			if (flags & DUK_COMPARE_FLAG_NEGATE) {
+				retval ^= 1;
+			}
+			return retval;
+		}
+	}
+#endif
+
+	/* Slow path */
+
 	duk_push_tval(ctx, tv_x);
 	duk_push_tval(ctx, tv_y);
 
@@ -54658,9 +72789,12 @@ duk_bool_t duk_js_compare_helper(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_
  *      E5 Section 15.3.4.5.3
  *
  *  For other objects, a TypeError is thrown.
+ *
+ *  Limited Proxy support: don't support 'getPrototypeOf' trap but
+ *  continue lookup in Proxy target if the value is a Proxy.
  */
 
-duk_bool_t duk_js_instanceof(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_y) {
+DUK_INTERNAL duk_bool_t duk_js_instanceof(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_y) {
 	duk_context *ctx = (duk_context *) thr;
 	duk_hobject *func;
 	duk_hobject *val;
@@ -54670,6 +72804,11 @@ duk_bool_t duk_js_instanceof(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_y) {
 	/*
 	 *  Get the values onto the stack first.  It would be possible to cover
 	 *  some normal cases without resorting to the value stack.
+	 *
+	 *  The right hand side could be a light function (as they generally
+	 *  behave like objects).  Light functions never have a 'prototype'
+	 *  property so E5.1 Section 15.3.5.3 step 3 always throws a TypeError.
+	 *  Using duk_require_hobject() is thus correct (except for error msg).
 	 */
 
 	duk_push_tval(ctx, tv_x);
@@ -54694,7 +72833,7 @@ duk_bool_t duk_js_instanceof(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_y) {
 
 		if (!DUK_HOBJECT_IS_CALLABLE(func)) {
 			/*
-		 	 *  Note: of native Ecmascript objects, only Function instances
+			 *  Note: of native Ecmascript objects, only Function instances
 			 *  have a [[HasInstance]] internal property.  Custom objects might
 			 *  also have it, but not in current implementation.
 			 *
@@ -54731,7 +72870,9 @@ duk_bool_t duk_js_instanceof(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_y) {
 
 	/* [ ... lval rval(func) ] */
 
-	val = duk_get_hobject(ctx, -2);
+	/* Handle lightfuncs through object coercion for now. */
+	/* XXX: direct implementation */
+	val = duk_get_hobject_or_lfunc_coerce(ctx, -2);
 	if (!val) {
 		goto pop_and_false;
 	}
@@ -54740,6 +72881,13 @@ duk_bool_t duk_js_instanceof(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_y) {
 	proto = duk_require_hobject(ctx, -1);
 	duk_pop(ctx);  /* -> [ ... lval rval ] */
 
+	DUK_ASSERT(val != NULL);
+
+#if defined(DUK_USE_ES6_PROXY)
+	val = duk_hobject_resolve_proxy_target(thr, val);
+	DUK_ASSERT(val != NULL);
+#endif
+
 	sanity = DUK_HOBJECT_PROTOTYPE_CHAIN_SANITY;
 	do {
 		/*
@@ -54760,11 +72908,19 @@ duk_bool_t duk_js_instanceof(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_y) {
 		 *  also the built-in Function prototype, the result is true.
 		 */
 
-		val = val->prototype;
+		DUK_ASSERT(val != NULL);
+		val = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, val);
 
 		if (!val) {
 			goto pop_and_false;
-		} else if (val == proto) {
+		}
+
+		DUK_ASSERT(val != NULL);
+#if defined(DUK_USE_ES6_PROXY)
+		val = duk_hobject_resolve_proxy_target(thr, val);
+#endif
+
+		if (val == proto) {
 			goto pop_and_true;
 		}
 
@@ -54772,7 +72928,7 @@ duk_bool_t duk_js_instanceof(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_y) {
 	} while (--sanity > 0);
 
 	if (sanity == 0) {
-		DUK_ERROR(thr, DUK_ERR_INTERNAL_ERROR, "instanceof prototype chain sanity exceeded");
+		DUK_ERROR(thr, DUK_ERR_INTERNAL_ERROR, DUK_STR_PROTOTYPE_CHAIN_LIMIT);
 	}
 	DUK_UNREACHABLE();
 
@@ -54794,8 +72950,8 @@ duk_bool_t duk_js_instanceof(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_y) {
  *
  *  Basically just a property existence check using [[HasProperty]].
  */
-	
-duk_bool_t duk_js_in(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_y) {
+
+DUK_INTERNAL duk_bool_t duk_js_in(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_y) {
 	duk_context *ctx = (duk_context *) thr;
 	duk_bool_t retval;
 
@@ -54813,9 +72969,12 @@ duk_bool_t duk_js_in(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_y) {
 	 * form (which is a shame).
 	 */
 
+	/* TypeError if rval is not an object (or lightfunc which should behave
+	 * like a Function instance).
+	 */
 	duk_push_tval(ctx, tv_x);
 	duk_push_tval(ctx, tv_y);
-	(void) duk_require_hobject(ctx, -1);  /* TypeError if rval not object */
+	duk_require_type_mask(ctx, -1, DUK_TYPE_MASK_OBJECT | DUK_TYPE_MASK_LIGHTFUNC);
 	duk_to_string(ctx, -2);               /* coerce lval with ToString() */
 
 	retval = duk_hobject_hasprop(thr, duk_get_tval(ctx, -1), duk_get_tval(ctx, -2));
@@ -54838,7 +72997,7 @@ duk_bool_t duk_js_in(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_y) {
  *  lowercase variants now.
  */
 
-duk_hstring *duk_js_typeof(duk_hthread *thr, duk_tval *tv_x) {
+DUK_INTERNAL duk_hstring *duk_js_typeof(duk_hthread *thr, duk_tval *tv_x) {
 	duk_small_int_t stridx = 0;
 
 	switch (DUK_TVAL_GET_TAG(tv_x)) {
@@ -54879,8 +73038,16 @@ duk_hstring *duk_js_typeof(duk_hthread *thr, duk_tval *tv_x) {
 		stridx = DUK_STRIDX_LC_BUFFER;
 		break;
 	}
+	case DUK_TAG_LIGHTFUNC: {
+		stridx = DUK_STRIDX_LC_FUNCTION;
+		break;
+	}
+#if defined(DUK_USE_FASTINT)
+	case DUK_TAG_FASTINT:
+#endif
 	default: {
 		/* number */
+		DUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv_x));
 		DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv_x));
 		stridx = DUK_STRIDX_LC_NUMBER;
 		break;
@@ -54888,7 +73055,7 @@ duk_hstring *duk_js_typeof(duk_hthread *thr, duk_tval *tv_x) {
 	}
 
 	DUK_ASSERT(stridx >= 0 && stridx < DUK_HEAP_NUM_STRINGS);
-	return thr->strs[stridx];
+	return DUK_HTHREAD_GET_STRING(thr, stridx);
 }
 
 /*
@@ -54901,7 +73068,7 @@ duk_hstring *duk_js_typeof(duk_hthread *thr, duk_tval *tv_x) {
  *  call duk_js_to_arrayindex_string_helper().
  */
 
-duk_small_int_t duk_js_to_arrayindex_raw_string(duk_uint8_t *str, duk_uint32_t blen, duk_uarridx_t *out_idx) {
+DUK_INTERNAL duk_small_int_t duk_js_to_arrayindex_raw_string(const duk_uint8_t *str, duk_uint32_t blen, duk_uarridx_t *out_idx) {
 	duk_uarridx_t res, new_res;
 
 	if (blen == 0 || blen > 10) {
@@ -54937,10 +73104,10 @@ duk_small_int_t duk_js_to_arrayindex_raw_string(duk_uint8_t *str, duk_uint32_t b
  parse_fail:
 	*out_idx = DUK_HSTRING_NO_ARRAY_INDEX;
 	return 0;
-}	
+}
 
 /* Called by duk_hstring.h macros */
-duk_uarridx_t duk_js_to_arrayindex_string_helper(duk_hstring *h) {
+DUK_INTERNAL duk_uarridx_t duk_js_to_arrayindex_string_helper(duk_hstring *h) {
 	duk_uarridx_t res;
 	duk_small_int_t rc;
 
@@ -54971,8 +73138,8 @@ duk_uarridx_t duk_js_to_arrayindex_string_helper(duk_hstring *h) {
  *  convenient field).  The prototype chain is not followed in the ordinary
  *  sense for variable lookups.
  *
- *  See identifier-handling.txt for more details on the identifier algorithms
- *  and the internal representation.  See function-objects.txt for details on
+ *  See identifier-handling.rst for more details on the identifier algorithms
+ *  and the internal representation.  See function-objects.rst for details on
  *  what function templates and instances are expected to look like.
  *
  *  Care must be taken to avoid duk_tval pointer invalidation caused by
@@ -55013,7 +73180,7 @@ typedef struct {
  *
  *  See E5 Section 13.2 for detailed requirements on the function objects;
  *  there are no similar requirements for function "templates" which are an
- *  implementation dependent internal feature.  Also see function-objects.txt
+ *  implementation dependent internal feature.  Also see function-objects.rst
  *  for a discussion on the function instance properties provided by this
  *  implementation.
  *
@@ -55028,22 +73195,22 @@ typedef struct {
  *     even if the closure object remains reachable.
  */
 
-static void duk__inc_data_inner_refcounts(duk_hthread *thr, duk_hcompiledfunction *f) {
+DUK_LOCAL void duk__inc_data_inner_refcounts(duk_hthread *thr, duk_hcompiledfunction *f) {
 	duk_tval *tv, *tv_end;
 	duk_hobject **funcs, **funcs_end;
 
-	DUK_ASSERT(f->data != NULL);  /* compiled functions must be created 'atomically' */
+	DUK_ASSERT(DUK_HCOMPILEDFUNCTION_GET_DATA(thr->heap, f) != NULL);  /* compiled functions must be created 'atomically' */
 	DUK_UNREF(thr);
 
-	tv = DUK_HCOMPILEDFUNCTION_GET_CONSTS_BASE(f);
-	tv_end = DUK_HCOMPILEDFUNCTION_GET_CONSTS_END(f);
+	tv = DUK_HCOMPILEDFUNCTION_GET_CONSTS_BASE(thr->heap, f);
+	tv_end = DUK_HCOMPILEDFUNCTION_GET_CONSTS_END(thr->heap, f);
 	while (tv < tv_end) {
 		DUK_TVAL_INCREF(thr, tv);
 		tv++;
 	}
 
-	funcs = DUK_HCOMPILEDFUNCTION_GET_FUNCS_BASE(f);
-	funcs_end = DUK_HCOMPILEDFUNCTION_GET_FUNCS_END(f);
+	funcs = DUK_HCOMPILEDFUNCTION_GET_FUNCS_BASE(thr->heap, f);
+	funcs_end = DUK_HCOMPILEDFUNCTION_GET_FUNCS_END(thr->heap, f);
 	while (funcs < funcs_end) {
 		DUK_HEAPHDR_INCREF(thr, (duk_heaphdr *) *funcs);
 		funcs++;
@@ -55057,7 +73224,7 @@ static void duk__inc_data_inner_refcounts(duk_hthread *thr, duk_hcompiledfunctio
  * (outer_var_env is ignored and may or may not be same as outer_lex_env).
  */
 
-static const duk_uint16_t duk__closure_copy_proplist[] = {
+DUK_LOCAL const duk_uint16_t duk__closure_copy_proplist[] = {
 	/* order: most frequent to least frequent */
 	DUK_STRIDX_INT_VARMAP,
 	DUK_STRIDX_INT_FORMALS,
@@ -55066,7 +73233,8 @@ static const duk_uint16_t duk__closure_copy_proplist[] = {
 	DUK_STRIDX_FILE_NAME,
 	DUK_STRIDX_INT_SOURCE
 };
-	
+
+DUK_INTERNAL
 void duk_js_push_closure(duk_hthread *thr,
                          duk_hcompiledfunction *fun_temp,
                          duk_hobject *outer_var_env,
@@ -55077,9 +73245,9 @@ void duk_js_push_closure(duk_hthread *thr,
 	duk_uint_t len_value;
 
 	DUK_ASSERT(fun_temp != NULL);
-	DUK_ASSERT(fun_temp->data != NULL);
-	DUK_ASSERT(fun_temp->funcs != NULL);
-	DUK_ASSERT(fun_temp->bytecode != NULL);
+	DUK_ASSERT(DUK_HCOMPILEDFUNCTION_GET_DATA(thr->heap, fun_temp) != NULL);
+	DUK_ASSERT(DUK_HCOMPILEDFUNCTION_GET_FUNCS(thr->heap, fun_temp) != NULL);
+	DUK_ASSERT(DUK_HCOMPILEDFUNCTION_GET_BYTECODE(thr->heap, fun_temp) != NULL);
 	DUK_ASSERT(outer_var_env != NULL);
 	DUK_ASSERT(outer_lex_env != NULL);
 
@@ -55087,30 +73255,34 @@ void duk_js_push_closure(duk_hthread *thr,
 	duk_push_hobject(ctx, &fun_temp->obj);  /* -> [ ... closure template ] */
 
 	fun_clos = (duk_hcompiledfunction *) duk_get_hcompiledfunction(ctx, -2);
-	DUK_ASSERT(DUK_HOBJECT_IS_COMPILEDFUNCTION((duk_hobject *) fun_clos));
 	DUK_ASSERT(fun_clos != NULL);
-	DUK_ASSERT(fun_clos->data == NULL);
-	DUK_ASSERT(fun_clos->funcs == NULL);
-	DUK_ASSERT(fun_clos->bytecode == NULL);
+	DUK_ASSERT(DUK_HOBJECT_IS_COMPILEDFUNCTION((duk_hobject *) fun_clos));
+	DUK_ASSERT(DUK_HCOMPILEDFUNCTION_GET_DATA(thr->heap, fun_clos) == NULL);
+	DUK_ASSERT(DUK_HCOMPILEDFUNCTION_GET_FUNCS(thr->heap, fun_clos) == NULL);
+	DUK_ASSERT(DUK_HCOMPILEDFUNCTION_GET_BYTECODE(thr->heap, fun_clos) == NULL);
 
-	fun_clos->data = fun_temp->data;
-	fun_clos->funcs = fun_temp->funcs;
-	fun_clos->bytecode = fun_temp->bytecode;
+	DUK_HCOMPILEDFUNCTION_SET_DATA(thr->heap, fun_clos, DUK_HCOMPILEDFUNCTION_GET_DATA(thr->heap, fun_temp));
+	DUK_HCOMPILEDFUNCTION_SET_FUNCS(thr->heap, fun_clos, DUK_HCOMPILEDFUNCTION_GET_FUNCS(thr->heap, fun_temp));
+	DUK_HCOMPILEDFUNCTION_SET_BYTECODE(thr->heap, fun_clos, DUK_HCOMPILEDFUNCTION_GET_BYTECODE(thr->heap, fun_temp));
 
 	/* Note: all references inside 'data' need to get their refcounts
 	 * upped too.  This is the case because refcounts are decreased
 	 * through every function referencing 'data' independently.
 	 */
 
-	DUK_HBUFFER_INCREF(thr, fun_clos->data);
+	DUK_HBUFFER_INCREF(thr, DUK_HCOMPILEDFUNCTION_GET_DATA(thr->heap, fun_clos));
 	duk__inc_data_inner_refcounts(thr, fun_temp);
 
 	fun_clos->nregs = fun_temp->nregs;
 	fun_clos->nargs = fun_temp->nargs;
+#if defined(DUK_USE_DEBUGGER_SUPPORT)
+	fun_clos->start_line = fun_temp->start_line;
+	fun_clos->end_line = fun_temp->end_line;
+#endif
 
-	DUK_ASSERT(fun_clos->data != NULL);
-	DUK_ASSERT(fun_clos->funcs != NULL);
-	DUK_ASSERT(fun_clos->bytecode != NULL);
+	DUK_ASSERT(DUK_HCOMPILEDFUNCTION_GET_DATA(thr->heap, fun_clos) != NULL);
+	DUK_ASSERT(DUK_HCOMPILEDFUNCTION_GET_FUNCS(thr->heap, fun_clos) != NULL);
+	DUK_ASSERT(DUK_HCOMPILEDFUNCTION_GET_BYTECODE(thr->heap, fun_clos) != NULL);
 
 	/* XXX: could also copy from template, but there's no way to have any
 	 * other value here now (used code has no access to the template).
@@ -55139,7 +73311,13 @@ void duk_js_push_closure(duk_hthread *thr,
 		DUK_HOBJECT_SET_NOTAIL(&fun_clos->obj);
 	}
 	/* DUK_HOBJECT_FLAG_NEWENV: handled below */
-	DUK_ASSERT(!DUK_HOBJECT_HAS_NAMEBINDING(&fun_clos->obj));
+	if (DUK_HOBJECT_HAS_NAMEBINDING(&fun_temp->obj)) {
+		/* Although NAMEBINDING is not directly needed for using
+		 * function instances, it's needed by bytecode dump/load
+		 * so copy it too.
+		 */
+		DUK_HOBJECT_SET_NAMEBINDING(&fun_clos->obj);
+	}
 	if (DUK_HOBJECT_HAS_CREATEARGS(&fun_temp->obj)) {
 		DUK_HOBJECT_SET_CREATEARGS(&fun_clos->obj);
 	}
@@ -55157,10 +73335,10 @@ void duk_js_push_closure(duk_hthread *thr,
 	 *  the environment records are those that will be directly used
 	 *  (e.g. for declarations).
 	 *
-	 *  _lexenv is always set; _varenv defaults to _lexenv if missing,
-	 *  so _varenv is only set if _lexenv != _varenv.
+	 *  _Lexenv is always set; _Varenv defaults to _Lexenv if missing,
+	 *  so _Varenv is only set if _Lexenv != _Varenv.
 	 *
-	 *  This is relatively complex, see doc/identifier-handling.txt.
+	 *  This is relatively complex, see doc/identifier-handling.rst.
 	 */
 
 	if (DUK_HOBJECT_HAS_NEWENV(&fun_temp->obj)) {
@@ -55174,8 +73352,8 @@ void duk_js_push_closure(duk_hthread *thr,
 			 *  in an intermediate environment record.  The "outer"
 			 *  lexical/variable environment will thus be:
 			 *
-			 *  a) { funcname: <func>, _prototype: outer_lex_env }
-			 *  b) { funcname: <func>, _prototype:  <globalenv> }  (if outer_lex_env missing)
+			 *  a) { funcname: <func>, __prototype: outer_lex_env }
+			 *  b) { funcname: <func>, __prototype:  <globalenv> }  (if outer_lex_env missing)
 			 */
 
 			DUK_ASSERT(duk_has_prop_stridx(ctx, -1, DUK_STRIDX_NAME));  /* required if NAMEBINDING set */
@@ -55188,22 +73366,22 @@ void duk_js_push_closure(duk_hthread *thr,
 
 			/* -> [ ... closure template env ] */
 			(void) duk_push_object_helper_proto(ctx,
-	   		                                    DUK_HOBJECT_FLAG_EXTENSIBLE |
+			                                    DUK_HOBJECT_FLAG_EXTENSIBLE |
 			                                    DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_DECENV),
 			                                    proto);
 
-			/* It's important that duk_def_prop() is a 'raw define' so that any
+			/* It's important that duk_xdef_prop() is a 'raw define' so that any
 			 * properties in an ancestor are never an issue (they should never be
 			 * e.g. non-writable, but just in case).
 			 */
 			duk_get_prop_stridx(ctx, -2, DUK_STRIDX_NAME);       /* -> [ ... closure template env funcname ] */
 			duk_dup(ctx, -4);                                    /* -> [ ... closure template env funcname closure ] */
-			duk_def_prop(ctx, -3, DUK_PROPDESC_FLAGS_NONE);      /* -> [ ... closure template env ] */
+			duk_xdef_prop(ctx, -3, DUK_PROPDESC_FLAGS_NONE);     /* -> [ ... closure template env ] */
 			/* env[funcname] = closure */
 
 			/* [ ... closure template env ] */
 
-			duk_def_prop_stridx(ctx, -3, DUK_STRIDX_INT_LEXENV, DUK_PROPDESC_FLAGS_WC);
+			duk_xdef_prop_stridx(ctx, -3, DUK_STRIDX_INT_LEXENV, DUK_PROPDESC_FLAGS_WC);
 			/* since closure has NEWENV, never define DUK_STRIDX_INT_VARENV, as it
 			 * will be ignored anyway
 			 */
@@ -55217,7 +73395,7 @@ void duk_js_push_closure(duk_hthread *thr,
 			 */
 
 			duk_push_hobject(ctx, outer_lex_env);  /* -> [ ... closure template env ] */
-			duk_def_prop_stridx(ctx, -3, DUK_STRIDX_INT_LEXENV, DUK_PROPDESC_FLAGS_WC);
+			duk_xdef_prop_stridx(ctx, -3, DUK_STRIDX_INT_LEXENV, DUK_PROPDESC_FLAGS_WC);
 			/* since closure has NEWENV, never define DUK_STRIDX_INT_VARENV, as it
 			 * will be ignored anyway
 			 */
@@ -55236,11 +73414,11 @@ void duk_js_push_closure(duk_hthread *thr,
 		DUK_ASSERT(!DUK_HOBJECT_HAS_NAMEBINDING(&fun_temp->obj));
 
 		duk_push_hobject(ctx, outer_lex_env);  /* -> [ ... closure template env ] */
-		duk_def_prop_stridx(ctx, -3, DUK_STRIDX_INT_LEXENV, DUK_PROPDESC_FLAGS_WC);
+		duk_xdef_prop_stridx(ctx, -3, DUK_STRIDX_INT_LEXENV, DUK_PROPDESC_FLAGS_WC);
 
 		if (outer_var_env != outer_lex_env) {
 			duk_push_hobject(ctx, outer_var_env);  /* -> [ ... closure template env ] */
-			duk_def_prop_stridx(ctx, -3, DUK_STRIDX_INT_VARENV, DUK_PROPDESC_FLAGS_WC);
+			duk_xdef_prop_stridx(ctx, -3, DUK_STRIDX_INT_VARENV, DUK_PROPDESC_FLAGS_WC);
 		}
 	}
 #ifdef DUK_USE_DDDPRINT
@@ -55269,7 +73447,7 @@ void duk_js_push_closure(duk_hthread *thr,
 		if (duk_get_prop_stridx(ctx, -1, stridx)) {
 			/* [ ... closure template val ] */
 			DUK_DDD(DUK_DDDPRINT("copying property, stridx=%ld -> found", (long) stridx));
-			duk_def_prop_stridx(ctx, -3, stridx, DUK_PROPDESC_FLAGS_WC);
+			duk_xdef_prop_stridx(ctx, -3, stridx, DUK_PROPDESC_FLAGS_WC);
 		} else {
 			DUK_DDD(DUK_DDDPRINT("copying property, stridx=%ld -> not found", (long) stridx));
 			duk_pop(ctx);
@@ -55293,7 +73471,7 @@ void duk_js_push_closure(duk_hthread *thr,
 		DUK_ASSERT(duk_get_length(ctx, -1) <= DUK_UINT_MAX);  /* formal arg limits */
 		len_value = (duk_uint_t) duk_get_length(ctx, -1);
 	} else {
-		/* XXX: what to do if _formals is not empty but compiler has
+		/* XXX: what to do if _Formals is not empty but compiler has
 		 * optimized it away -- read length from an explicit property
 		 * then?
 		 */
@@ -55301,7 +73479,7 @@ void duk_js_push_closure(duk_hthread *thr,
 	duk_pop(ctx);
 
 	duk_push_uint(ctx, len_value);  /* [ ... closure template len_value ] */
-	duk_def_prop_stridx(ctx, -3, DUK_STRIDX_LENGTH, DUK_PROPDESC_FLAGS_NONE);
+	duk_xdef_prop_stridx(ctx, -3, DUK_STRIDX_LENGTH, DUK_PROPDESC_FLAGS_NONE);
 
 	/*
 	 *  "prototype" is, by default, a fresh object with the "constructor"
@@ -55321,9 +73499,9 @@ void duk_js_push_closure(duk_hthread *thr,
 
 	duk_push_object(ctx);  /* -> [ ... closure template newobj ] */
 	duk_dup(ctx, -3);          /* -> [ ... closure template newobj closure ] */
-	duk_def_prop_stridx(ctx, -2, DUK_STRIDX_CONSTRUCTOR, DUK_PROPDESC_FLAGS_WC);  /* -> [ ... closure template newobj ] */
+	duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_CONSTRUCTOR, DUK_PROPDESC_FLAGS_WC);  /* -> [ ... closure template newobj ] */
 	duk_compact(ctx, -1);  /* compact the prototype */
-	duk_def_prop_stridx(ctx, -3, DUK_STRIDX_PROTOTYPE, DUK_PROPDESC_FLAGS_W);     /* -> [ ... closure template ] */
+	duk_xdef_prop_stridx(ctx, -3, DUK_STRIDX_PROTOTYPE, DUK_PROPDESC_FLAGS_W);     /* -> [ ... closure template ] */
 
 	/*
 	 *  "arguments" and "caller" must be mapped to throwers for strict
@@ -55336,13 +73514,13 @@ void duk_js_push_closure(duk_hthread *thr,
 	/* [ ... closure template ] */
 
 	if (DUK_HOBJECT_HAS_STRICT(&fun_clos->obj)) {
-		duk_def_prop_stridx_thrower(ctx, -2, DUK_STRIDX_CALLER, DUK_PROPDESC_FLAGS_NONE);
-		duk_def_prop_stridx_thrower(ctx, -2, DUK_STRIDX_LC_ARGUMENTS, DUK_PROPDESC_FLAGS_NONE);
+		duk_xdef_prop_stridx_thrower(ctx, -2, DUK_STRIDX_CALLER, DUK_PROPDESC_FLAGS_NONE);
+		duk_xdef_prop_stridx_thrower(ctx, -2, DUK_STRIDX_LC_ARGUMENTS, DUK_PROPDESC_FLAGS_NONE);
 	} else {
 #ifdef DUK_USE_NONSTD_FUNC_CALLER_PROPERTY
 		DUK_DDD(DUK_DDDPRINT("function is non-strict and non-standard 'caller' property in use, add initial 'null' value"));
 		duk_push_null(ctx);
-		duk_def_prop_stridx(ctx, -3, DUK_STRIDX_CALLER, DUK_PROPDESC_FLAGS_NONE);
+		duk_xdef_prop_stridx(ctx, -3, DUK_STRIDX_CALLER, DUK_PROPDESC_FLAGS_NONE);
 #else
 		DUK_DDD(DUK_DDDPRINT("function is non-strict and non-standard 'caller' property not used"));
 #endif
@@ -55369,7 +73547,7 @@ void duk_js_push_closure(duk_hthread *thr,
 		duk_pop(ctx);
 		duk_push_hstring_stridx(ctx, DUK_STRIDX_EMPTY_STRING);
 	}
-	duk_def_prop_stridx(ctx, -3, DUK_STRIDX_NAME, DUK_PROPDESC_FLAGS_NONE);  /* -> [ ... closure template ] */
+	duk_xdef_prop_stridx(ctx, -3, DUK_STRIDX_NAME, DUK_PROPDESC_FLAGS_NONE);  /* -> [ ... closure template ] */
 
 	/*
 	 *  Compact the closure, in most cases no properties will be added later.
@@ -55387,7 +73565,7 @@ void duk_js_push_closure(duk_hthread *thr,
 	 */
 
 	DUK_ASSERT(DUK_HOBJECT_GET_CLASS_NUMBER(&fun_clos->obj) == DUK_HOBJECT_CLASS_FUNCTION);
-	DUK_ASSERT(fun_clos->obj.prototype == thr->builtins[DUK_BIDX_FUNCTION_PROTOTYPE]);
+	DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, &fun_clos->obj) == thr->builtins[DUK_BIDX_FUNCTION_PROTOTYPE]);
 	DUK_ASSERT(DUK_HOBJECT_HAS_EXTENSIBLE(&fun_clos->obj));
 	DUK_ASSERT(duk_has_prop_stridx(ctx, -2, DUK_STRIDX_LENGTH) != 0);
 	DUK_ASSERT(duk_has_prop_stridx(ctx, -2, DUK_STRIDX_PROTOTYPE) != 0);
@@ -55400,7 +73578,7 @@ void duk_js_push_closure(duk_hthread *thr,
 	/*
 	 *  Finish
 	 */
-	
+
 	/* [ ... closure template ] */
 
 	DUK_DDD(DUK_DDDPRINT("created function instance: template=%!iT -> closure=%!iT",
@@ -55420,6 +73598,7 @@ void duk_js_push_closure(duk_hthread *thr,
  */
 
 /* shared helper */
+DUK_INTERNAL
 duk_hobject *duk_create_activation_environment_record(duk_hthread *thr,
                                                       duk_hobject *func,
                                                       duk_size_t idx_bottom) {
@@ -55431,7 +73610,7 @@ duk_hobject *duk_create_activation_environment_record(duk_hthread *thr,
 	DUK_ASSERT(thr != NULL);
 	DUK_ASSERT(func != NULL);
 
-	tv = duk_hobject_find_existing_entry_tval_ptr(func, DUK_HTHREAD_STRING_INT_LEXENV(thr));
+	tv = duk_hobject_find_existing_entry_tval_ptr(thr->heap, func, DUK_HTHREAD_STRING_INT_LEXENV(thr));
 	if (tv) {
 		DUK_ASSERT(DUK_TVAL_IS_OBJECT(tv));
 		DUK_ASSERT(DUK_HOBJECT_IS_ENV(DUK_TVAL_GET_OBJECT(tv)));
@@ -55452,25 +73631,26 @@ duk_hobject *duk_create_activation_environment_record(duk_hthread *thr,
 
 	if (DUK_HOBJECT_IS_COMPILEDFUNCTION(func)) {
 		duk_push_hthread(ctx, thr);
-		duk_def_prop_stridx_wec(ctx, -2, DUK_STRIDX_INT_THREAD);
+		duk_xdef_prop_stridx_wec(ctx, -2, DUK_STRIDX_INT_THREAD);
 		duk_push_hobject(ctx, func);
-		duk_def_prop_stridx_wec(ctx, -2, DUK_STRIDX_INT_CALLEE);
+		duk_xdef_prop_stridx_wec(ctx, -2, DUK_STRIDX_INT_CALLEE);
 		duk_push_size_t(ctx, idx_bottom);
-		duk_def_prop_stridx_wec(ctx, -2, DUK_STRIDX_INT_REGBASE);
+		duk_xdef_prop_stridx_wec(ctx, -2, DUK_STRIDX_INT_REGBASE);
 	}
 
 	return env;
 }
 
+DUK_INTERNAL
 void duk_js_init_activation_environment_records_delayed(duk_hthread *thr,
                                                         duk_activation *act) {
 	duk_context *ctx = (duk_context *) thr;
 	duk_hobject *func;
 	duk_hobject *env;
 
-	func = act->func;
+	func = DUK_ACT_GET_FUNC(act);
 	DUK_ASSERT(func != NULL);
-	DUK_ASSERT(!DUK_HOBJECT_HAS_BOUND(func));  /* bound functions are never in act->func */
+	DUK_ASSERT(!DUK_HOBJECT_HAS_BOUND(func));  /* bound functions are never in act 'func' */
 
 	/*
 	 *  Delayed initialization only occurs for 'NEWENV' functions.
@@ -55489,7 +73669,7 @@ void duk_js_init_activation_environment_records_delayed(duk_hthread *thr,
 		duk_hobject *p = env;
 		while (p) {
 			DUK_DDD(DUK_DDDPRINT("  -> %!ipO", (duk_heaphdr *) p));
-			p = p->prototype;
+			p = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, p);
 		}
 	}
 #endif
@@ -55517,13 +73697,13 @@ void duk_js_init_activation_environment_records_delayed(duk_hthread *thr,
  *  XXX: should access the own properties directly instead of using the API
  */
 
-void duk_js_close_environment_record(duk_hthread *thr, duk_hobject *env, duk_hobject *func, duk_size_t regbase) {
+DUK_INTERNAL void duk_js_close_environment_record(duk_hthread *thr, duk_hobject *env, duk_hobject *func, duk_size_t regbase) {
 	duk_context *ctx = (duk_context *) thr;
 	duk_uint_fast32_t i;
 
 	DUK_ASSERT(thr != NULL);
 	DUK_ASSERT(env != NULL);
-	DUK_ASSERT(func != NULL);
+	/* func is NULL for lightfuncs */
 
 	if (!DUK_HOBJECT_IS_DECENV(env) || DUK_HOBJECT_HAS_ENVRECCLOSED(env)) {
 		DUK_DDD(DUK_DDDPRINT("environment record not a declarative record, "
@@ -55564,7 +73744,7 @@ void duk_js_close_environment_record(duk_hthread *thr, duk_hobject *env, duk_hob
 	}
 #endif
 
-	if (DUK_HOBJECT_IS_COMPILEDFUNCTION(func)) {
+	if (func != NULL && DUK_HOBJECT_IS_COMPILEDFUNCTION(func)) {
 		duk_hobject *varmap;
 		duk_hstring *key;
 		duk_tval *tv;
@@ -55576,10 +73756,10 @@ void duk_js_close_environment_record(duk_hthread *thr, duk_hobject *env, duk_hob
 		 */
 
 		/* XXX: any way to detect faster whether something needs to be closed?
-		 * We now look up _callee and then skip the rest.
+		 * We now look up _Callee and then skip the rest.
 		 */
 
-		/* Note: we rely on the _varmap having a bunch of nice properties, like:
+		/* Note: we rely on the _Varmap having a bunch of nice properties, like:
 		 *  - being compacted and unmodified during this process
 		 *  - not containing an array part
 		 *  - having correct value types
@@ -55607,15 +73787,15 @@ void duk_js_close_environment_record(duk_hthread *thr, duk_hobject *env, duk_hob
 
 		/* [... env callee varmap] */
 
-		DUK_DDD(DUK_DDDPRINT("copying bound register values, %ld bound regs", (long) varmap->e_used));
+		DUK_DDD(DUK_DDDPRINT("copying bound register values, %ld bound regs", (long) DUK_HOBJECT_GET_ENEXT(varmap)));
 
-		for (i = 0; i < (duk_uint_fast32_t) varmap->e_used; i++) {
-			key = DUK_HOBJECT_E_GET_KEY(varmap, i);
+		for (i = 0; i < (duk_uint_fast32_t) DUK_HOBJECT_GET_ENEXT(varmap); i++) {
+			key = DUK_HOBJECT_E_GET_KEY(thr->heap, varmap, i);
 			DUK_ASSERT(key != NULL);   /* assume keys are compacted */
 
-			DUK_ASSERT(!DUK_HOBJECT_E_SLOT_IS_ACCESSOR(varmap, i));  /* assume plain values */
+			DUK_ASSERT(!DUK_HOBJECT_E_SLOT_IS_ACCESSOR(thr->heap, varmap, i));  /* assume plain values */
 
-			tv = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(varmap, i);
+			tv = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, varmap, i);
 			DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));  /* assume value is a number */
 			regnum = (duk_uint_t) DUK_TVAL_GET_NUMBER(tv);
 			DUK_ASSERT_DISABLE(regnum >= 0);  /* unsigned */
@@ -55634,7 +73814,7 @@ void duk_js_close_environment_record(duk_hthread *thr, duk_hobject *env, duk_hob
 			/* [... env callee varmap key val] */
 
 			/* if property already exists, overwrites silently */
-			duk_def_prop(ctx, -5, DUK_PROPDESC_FLAGS_WE);  /* writable but not deletable */
+			duk_xdef_prop(ctx, -5, DUK_PROPDESC_FLAGS_WE);  /* writable but not deletable */
 		}
 
 		duk_pop_2(ctx);
@@ -55682,10 +73862,11 @@ void duk_js_close_environment_record(duk_hthread *thr, duk_hobject *env, duk_hob
  */
 
 /* lookup name from an open declarative record's registers */
-static duk_bool_t duk__getid_open_decl_env_regs(duk_hthread *thr,
-                                                duk_hstring *name,
-                                                duk_hobject *env,
-                                                duk__id_lookup_result *out) {
+DUK_LOCAL
+duk_bool_t duk__getid_open_decl_env_regs(duk_hthread *thr,
+                                         duk_hstring *name,
+                                         duk_hobject *env,
+                                         duk__id_lookup_result *out) {
 	duk_hthread *env_thr;
 	duk_hobject *env_func;
 	duk_size_t env_regbase;
@@ -55701,12 +73882,12 @@ static duk_bool_t duk__getid_open_decl_env_regs(duk_hthread *thr,
 
 	DUK_ASSERT(DUK_HOBJECT_IS_DECENV(env));
 
-	tv = duk_hobject_find_existing_entry_tval_ptr(env, DUK_HTHREAD_STRING_INT_CALLEE(thr));
+	tv = duk_hobject_find_existing_entry_tval_ptr(thr->heap, env, DUK_HTHREAD_STRING_INT_CALLEE(thr));
 	if (!tv) {
-		/* env is closed, should be missing _callee, _thread, _regbase */
-		DUK_ASSERT(duk_hobject_find_existing_entry_tval_ptr(env, DUK_HTHREAD_STRING_INT_CALLEE(thr)) == NULL);
-		DUK_ASSERT(duk_hobject_find_existing_entry_tval_ptr(env, DUK_HTHREAD_STRING_INT_THREAD(thr)) == NULL);
-		DUK_ASSERT(duk_hobject_find_existing_entry_tval_ptr(env, DUK_HTHREAD_STRING_INT_REGBASE(thr)) == NULL);
+		/* env is closed, should be missing _Callee, _Thread, _Regbase */
+		DUK_ASSERT(duk_hobject_find_existing_entry_tval_ptr(thr->heap, env, DUK_HTHREAD_STRING_INT_CALLEE(thr)) == NULL);
+		DUK_ASSERT(duk_hobject_find_existing_entry_tval_ptr(thr->heap, env, DUK_HTHREAD_STRING_INT_THREAD(thr)) == NULL);
+		DUK_ASSERT(duk_hobject_find_existing_entry_tval_ptr(thr->heap, env, DUK_HTHREAD_STRING_INT_REGBASE(thr)) == NULL);
 		return 0;
 	}
 
@@ -55716,7 +73897,7 @@ static duk_bool_t duk__getid_open_decl_env_regs(duk_hthread *thr,
 	env_func = DUK_TVAL_GET_OBJECT(tv);
 	DUK_ASSERT(env_func != NULL);
 
-	tv = duk_hobject_find_existing_entry_tval_ptr(env_func, DUK_HTHREAD_STRING_INT_VARMAP(thr));
+	tv = duk_hobject_find_existing_entry_tval_ptr(thr->heap, env_func, DUK_HTHREAD_STRING_INT_VARMAP(thr));
 	if (!tv) {
 		return 0;
 	}
@@ -55724,7 +73905,7 @@ static duk_bool_t duk__getid_open_decl_env_regs(duk_hthread *thr,
 	varmap = DUK_TVAL_GET_OBJECT(tv);
 	DUK_ASSERT(varmap != NULL);
 
-	tv = duk_hobject_find_existing_entry_tval_ptr(varmap, name);
+	tv = duk_hobject_find_existing_entry_tval_ptr(thr->heap, varmap, name);
 	if (!tv) {
 		return 0;
 	}
@@ -55733,7 +73914,7 @@ static duk_bool_t duk__getid_open_decl_env_regs(duk_hthread *thr,
 	DUK_ASSERT_DISABLE(reg_rel >= 0);  /* unsigned */
 	DUK_ASSERT(reg_rel < ((duk_hcompiledfunction *) env_func)->nregs);
 
-	tv = duk_hobject_find_existing_entry_tval_ptr(env, DUK_HTHREAD_STRING_INT_THREAD(thr));
+	tv = duk_hobject_find_existing_entry_tval_ptr(thr->heap, env, DUK_HTHREAD_STRING_INT_THREAD(thr));
 	DUK_ASSERT(tv != NULL);
 	DUK_ASSERT(DUK_TVAL_IS_OBJECT(tv));
 	DUK_ASSERT(DUK_TVAL_GET_OBJECT(tv) != NULL);
@@ -55745,7 +73926,7 @@ static duk_bool_t duk__getid_open_decl_env_regs(duk_hthread *thr,
 	 * with what thread is used for valstack lookup.
 	 */
 
-	tv = duk_hobject_find_existing_entry_tval_ptr(env, DUK_HTHREAD_STRING_INT_REGBASE(thr));
+	tv = duk_hobject_find_existing_entry_tval_ptr(thr->heap, env, DUK_HTHREAD_STRING_INT_REGBASE(thr));
 	DUK_ASSERT(tv != NULL);
 	DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));
 	env_regbase = (duk_size_t) DUK_TVAL_GET_NUMBER(tv);
@@ -55766,10 +73947,11 @@ static duk_bool_t duk__getid_open_decl_env_regs(duk_hthread *thr,
 }
 
 /* lookup name from current activation record's functions' registers */
-static duk_bool_t duk__getid_activation_regs(duk_hthread *thr,
-                                             duk_hstring *name,
-                                             duk_activation *act,
-                                             duk__id_lookup_result *out) {
+DUK_LOCAL
+duk_bool_t duk__getid_activation_regs(duk_hthread *thr,
+                                      duk_hstring *name,
+                                      duk_activation *act,
+                                      duk__id_lookup_result *out) {
 	duk_tval *tv;
 	duk_hobject *func;
 	duk_hobject *varmap;
@@ -55781,7 +73963,7 @@ static duk_bool_t duk__getid_activation_regs(duk_hthread *thr,
 	DUK_ASSERT(act != NULL);
 	DUK_ASSERT(out != NULL);
 
-	func = act->func;
+	func = DUK_ACT_GET_FUNC(act);
 	DUK_ASSERT(func != NULL);
 	DUK_ASSERT(DUK_HOBJECT_HAS_NEWENV(func));
 
@@ -55789,7 +73971,7 @@ static duk_bool_t duk__getid_activation_regs(duk_hthread *thr,
 		return 0;
 	}
 
-	tv = duk_hobject_find_existing_entry_tval_ptr(func, DUK_HTHREAD_STRING_INT_VARMAP(thr));
+	tv = duk_hobject_find_existing_entry_tval_ptr(thr->heap, func, DUK_HTHREAD_STRING_INT_VARMAP(thr));
 	if (!tv) {
 		return 0;
 	}
@@ -55797,7 +73979,7 @@ static duk_bool_t duk__getid_activation_regs(duk_hthread *thr,
 	varmap = DUK_TVAL_GET_OBJECT(tv);
 	DUK_ASSERT(varmap != NULL);
 
-	tv = duk_hobject_find_existing_entry_tval_ptr(varmap, name);
+	tv = duk_hobject_find_existing_entry_tval_ptr(thr->heap, varmap, name);
 	if (!tv) {
 		return 0;
 	}
@@ -55821,13 +74003,16 @@ static duk_bool_t duk__getid_activation_regs(duk_hthread *thr,
 	return 1;
 }
 
-static duk_bool_t duk__get_identifier_reference(duk_hthread *thr,
-                                                duk_hobject *env,
-                                                duk_hstring *name,
-                                                duk_activation *act,
-                                                duk_bool_t parents,
-                                                duk__id_lookup_result *out) {
+DUK_LOCAL
+duk_bool_t duk__get_identifier_reference(duk_hthread *thr,
+                                         duk_hobject *env,
+                                         duk_hstring *name,
+                                         duk_activation *act,
+                                         duk_bool_t parents,
+                                         duk__id_lookup_result *out) {
 	duk_tval *tv;
+	duk_tval *tv_target;
+	duk_tval tv_name;
 	duk_uint_t sanity;
 
 	DUK_ASSERT(thr != NULL);
@@ -55887,8 +74072,8 @@ static duk_bool_t duk__get_identifier_reference(duk_hthread *thr,
 		 *    - Function code
 		 *    - Strict eval code
 		 *
-		 *  We only need to check _lexenv here; _varenv exists only if it
-		 *  differs from _lexenv (and thus _lexenv will also be present).
+		 *  We only need to check _Lexenv here; _Varenv exists only if it
+		 *  differs from _Lexenv (and thus _Lexenv will also be present).
 		 */
 
 		if (!parents) {
@@ -55897,16 +74082,16 @@ static duk_bool_t duk__get_identifier_reference(duk_hthread *thr,
 			goto fail_not_found;
 		}
 
-		func = act->func;
+		func = DUK_ACT_GET_FUNC(act);
 		DUK_ASSERT(func != NULL);
 		DUK_ASSERT(DUK_HOBJECT_HAS_NEWENV(func));
 
-		tv = duk_hobject_find_existing_entry_tval_ptr(func, DUK_HTHREAD_STRING_INT_LEXENV(thr));
+		tv = duk_hobject_find_existing_entry_tval_ptr(thr->heap, func, DUK_HTHREAD_STRING_INT_LEXENV(thr));
 		if (tv) {
 			DUK_ASSERT(DUK_TVAL_IS_OBJECT(tv));
 			env = DUK_TVAL_GET_OBJECT(tv);
 		} else {
-			DUK_ASSERT(duk_hobject_find_existing_entry_tval_ptr(func, DUK_HTHREAD_STRING_INT_VARENV(thr)) == NULL);
+			DUK_ASSERT(duk_hobject_find_existing_entry_tval_ptr(thr->heap, func, DUK_HTHREAD_STRING_INT_VARENV(thr)) == NULL);
 			env = thr->builtins[DUK_BIDX_GLOBAL_ENV];
 		}
 
@@ -55922,7 +74107,6 @@ static duk_bool_t duk__get_identifier_reference(duk_hthread *thr,
 
 	sanity = DUK_HOBJECT_PROTOTYPE_CHAIN_SANITY;
 	while (env != NULL) {
-		duk_tval *tv;
 		duk_small_int_t cl;
 		duk_int_t attrs;
 
@@ -55966,7 +74150,7 @@ static duk_bool_t duk__get_identifier_reference(duk_hthread *thr,
 			}
 		 skip_regs:
 
-			tv = duk_hobject_find_existing_entry_tval_ptr_and_attrs(env, name, &attrs);
+			tv = duk_hobject_find_existing_entry_tval_ptr_and_attrs(thr->heap, env, name, &attrs);
 			if (tv) {
 				out->value = tv;
 				out->attrs = attrs;
@@ -55990,36 +74174,51 @@ static duk_bool_t duk__get_identifier_reference(duk_hthread *thr,
 			 *
 			 *  Binding (target) object is an external, uncontrolled object.
 			 *  Identifier may be bound in an ancestor property, and may be
-			 *  an accessor.
+			 *  an accessor.  Target can also be a Proxy which we must support
+			 *  here.
 			 */
 
-			/* XXX: we could save space by using _target OR _this.  If _target, assume
-			 * this binding is undefined.  If _this, assumes this binding is _this, and
-			 * target is also _this.  One property would then be enough.
+			/* XXX: we could save space by using _Target OR _This.  If _Target, assume
+			 * this binding is undefined.  If _This, assumes this binding is _This, and
+			 * target is also _This.  One property would then be enough.
 			 */
 
 			duk_hobject *target;
+			duk_bool_t found;
 
 			DUK_ASSERT(cl == DUK_HOBJECT_CLASS_OBJENV);
 
-			tv = duk_hobject_find_existing_entry_tval_ptr(env, DUK_HTHREAD_STRING_INT_TARGET(thr));
-			DUK_ASSERT(tv != NULL);
-			DUK_ASSERT(DUK_TVAL_IS_OBJECT(tv));
-			target = DUK_TVAL_GET_OBJECT(tv);
+			tv_target = duk_hobject_find_existing_entry_tval_ptr(thr->heap, env, DUK_HTHREAD_STRING_INT_TARGET(thr));
+			DUK_ASSERT(tv_target != NULL);
+			DUK_ASSERT(DUK_TVAL_IS_OBJECT(tv_target));
+			target = DUK_TVAL_GET_OBJECT(tv_target);
 			DUK_ASSERT(target != NULL);
 
-			/* Note: we must traverse the prototype chain, so use an actual
-			 * hasprop call here.  The property may also be an accessor, so
-			 * we can't get an duk_tval pointer here.
+			/* Target may be a Proxy or property may be an accessor, so we must
+			 * use an actual, Proxy-aware hasprop check here.
 			 *
 			 * out->holder is NOT set to the actual duk_hobject where the
-			 * property is found, but rather the target object.
+			 * property is found, but rather the object binding target object.
 			 */
 
-			if (duk_hobject_hasprop_raw(thr, target, name)) {
+			if (DUK_HOBJECT_HAS_EXOTIC_PROXYOBJ(target)) {
+				DUK_ASSERT(name != NULL);
+				DUK_TVAL_SET_STRING(&tv_name, name);
+
+				found = duk_hobject_hasprop(thr, tv_target, &tv_name);
+			} else {
+				/* XXX: duk_hobject_hasprop() would be correct for
+				 * non-Proxy objects too, but it is about ~20-25%
+				 * slower at present so separate code paths for
+				 * Proxy and non-Proxy now.
+				 */
+				found = duk_hobject_hasprop_raw(thr, target, name);
+			}
+
+			if (found) {
 				out->value = NULL;  /* can't get value, may be accessor */
 				out->attrs = 0;     /* irrelevant when out->value == NULL */
-				tv = duk_hobject_find_existing_entry_tval_ptr(env, DUK_HTHREAD_STRING_INT_THIS(thr));
+				tv = duk_hobject_find_existing_entry_tval_ptr(thr->heap, env, DUK_HTHREAD_STRING_INT_THIS(thr));
 				out->this_binding = tv;  /* may be NULL */
 				out->env = env;
 				out->holder = target;
@@ -56043,7 +74242,7 @@ static duk_bool_t duk__get_identifier_reference(duk_hthread *thr,
                 if (sanity-- == 0) {
                         DUK_ERROR(thr, DUK_ERR_INTERNAL_ERROR, DUK_STR_PROTOTYPE_CHAIN_LIMIT);
                 }
-		env = env->prototype;
+		env = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, env);
 	};
 
 	/*
@@ -56069,6 +74268,8 @@ static duk_bool_t duk__get_identifier_reference(duk_hthread *thr,
  *  a 'strict' parameter.
  */
 
+#if 0  /*unused*/
+DUK_INTERNAL
 duk_bool_t duk_js_hasvar_envrec(duk_hthread *thr,
                                 duk_hobject *env,
                                 duk_hstring *name) {
@@ -56094,6 +74295,7 @@ duk_bool_t duk_js_hasvar_envrec(duk_hthread *thr,
 	parents = 0;
 	return duk__get_identifier_reference(thr, env, name, NULL, parents, &ref);
 }
+#endif
 
 /*
  *  GETVAR
@@ -56121,11 +74323,12 @@ duk_bool_t duk_js_hasvar_envrec(duk_hthread *thr,
  *  ReferenceError.
  */
 
-static duk_bool_t duk__getvar_helper(duk_hthread *thr,
-                                     duk_hobject *env,
-                                     duk_activation *act,
-                                     duk_hstring *name,
-                                     duk_bool_t throw_flag) {
+DUK_LOCAL
+duk_bool_t duk__getvar_helper(duk_hthread *thr,
+                              duk_hobject *env,
+                              duk_activation *act,
+                              duk_hstring *name,
+                              duk_bool_t throw_flag) {
 	duk_context *ctx = (duk_context *) thr;
 	duk__id_lookup_result ref;
 	duk_tval tv_tmp_obj;
@@ -56184,6 +74387,7 @@ static duk_bool_t duk__getvar_helper(duk_hthread *thr,
 	}
 }
 
+DUK_INTERNAL
 duk_bool_t duk_js_getvar_envrec(duk_hthread *thr,
                                 duk_hobject *env,
                                 duk_hstring *name,
@@ -56191,6 +74395,7 @@ duk_bool_t duk_js_getvar_envrec(duk_hthread *thr,
 	return duk__getvar_helper(thr, env, NULL, name, throw_flag);
 }
 
+DUK_INTERNAL
 duk_bool_t duk_js_getvar_activation(duk_hthread *thr,
                                     duk_activation *act,
                                     duk_hstring *name,
@@ -56214,12 +74419,13 @@ duk_bool_t duk_js_getvar_activation(duk_hthread *thr,
  *  putting a value may reallocate any object or any valstack.  Caller beware.
  */
 
-static void duk__putvar_helper(duk_hthread *thr,
-                               duk_hobject *env,
-                               duk_activation *act,
-                               duk_hstring *name,
-                               duk_tval *val,
-                               duk_bool_t strict) {
+DUK_LOCAL
+void duk__putvar_helper(duk_hthread *thr,
+                        duk_hobject *env,
+                        duk_activation *act,
+                        duk_hstring *name,
+                        duk_tval *val,
+                        duk_bool_t strict) {
 	duk__id_lookup_result ref;
 	duk_tval tv_tmp_obj;
 	duk_tval tv_tmp_key;
@@ -56267,17 +74473,13 @@ static void duk__putvar_helper(duk_hthread *thr,
 			 * (immutable binding), use duk_hobject_putprop() which
 			 * will respect mutability.
 			 */
-			duk_tval tv_tmp;
 			duk_tval *tv_val;
 
 			DUK_ASSERT(ref.this_binding == NULL);  /* always for register bindings */
 
- 			tv_val = ref.value;
+			tv_val = ref.value;
 			DUK_ASSERT(tv_val != NULL);
-			DUK_TVAL_SET_TVAL(&tv_tmp, tv_val);
-			DUK_TVAL_SET_TVAL(tv_val, val);
-			DUK_TVAL_INCREF(thr, val);
-			DUK_TVAL_DECREF(thr, &tv_tmp);  /* must be last */
+			DUK_TVAL_SET_TVAL_UPDREF(thr, tv_val, val);  /* side effects */
 
 			/* ref.value and ref.this_binding invalidated here */
 		} else {
@@ -56292,7 +74494,7 @@ static void duk__putvar_helper(duk_hthread *thr,
 
 		return;
 	}
-	
+
 	/*
 	 *  Not found: write to global object (non-strict) or ReferenceError
 	 *  (strict); see E5 Section 8.7.2, step 3.
@@ -56314,6 +74516,7 @@ static void duk__putvar_helper(duk_hthread *thr,
 	 */
 }
 
+DUK_INTERNAL
 void duk_js_putvar_envrec(duk_hthread *thr,
                           duk_hobject *env,
                           duk_hstring *name,
@@ -56322,6 +74525,7 @@ void duk_js_putvar_envrec(duk_hthread *thr,
 	duk__putvar_helper(thr, env, NULL, name, val, strict);
 }
 
+DUK_INTERNAL
 void duk_js_putvar_activation(duk_hthread *thr,
                               duk_activation *act,
                               duk_hstring *name,
@@ -56350,10 +74554,11 @@ void duk_js_putvar_activation(duk_hthread *thr,
  *  should never be called from strict mode code!
  */
 
-static duk_bool_t duk__delvar_helper(duk_hthread *thr,
-                                     duk_hobject *env,
-                                     duk_activation *act,
-                                     duk_hstring *name) {
+DUK_LOCAL
+duk_bool_t duk__delvar_helper(duk_hthread *thr,
+                              duk_hobject *env,
+                              duk_activation *act,
+                              duk_hstring *name) {
 	duk__id_lookup_result ref;
 	duk_bool_t parents;
 
@@ -56396,12 +74601,16 @@ static duk_bool_t duk__delvar_helper(duk_hthread *thr,
 	return 1;
 }
 
+#if 0  /*unused*/
+DUK_INTERNAL
 duk_bool_t duk_js_delvar_envrec(duk_hthread *thr,
                                 duk_hobject *env,
                                 duk_hstring *name) {
 	return duk__delvar_helper(thr, env, NULL, name);
 }
-	
+#endif
+
+DUK_INTERNAL
 duk_bool_t duk_js_delvar_activation(duk_hthread *thr,
                                     duk_activation *act,
                                     duk_hstring *name) {
@@ -56459,12 +74668,13 @@ duk_bool_t duk_js_delvar_activation(duk_hthread *thr,
  *  otherwise returns 0.
  */
 
-static duk_bool_t duk__declvar_helper(duk_hthread *thr,
-                                      duk_hobject *env,
-                                      duk_hstring *name,
-                                      duk_tval *val,
-                                      duk_small_int_t prop_flags,
-                                      duk_bool_t is_func_decl) {
+DUK_LOCAL
+duk_bool_t duk__declvar_helper(duk_hthread *thr,
+                               duk_hobject *env,
+                               duk_hstring *name,
+                               duk_tval *val,
+                               duk_small_int_t prop_flags,
+                               duk_bool_t is_func_decl) {
 	duk_context *ctx = (duk_context *) thr;
 	duk_hobject *holder;
 	duk_bool_t parents;
@@ -56553,14 +74763,14 @@ static duk_bool_t duk__declvar_helper(duk_hthread *thr,
 		/* must be found: was found earlier, and cannot be inherited */
 		for (;;) {
 			DUK_ASSERT(holder != NULL);
-			duk_hobject_find_existing_entry(holder, name, &e_idx, &h_idx);
+			duk_hobject_find_existing_entry(thr->heap, holder, name, &e_idx, &h_idx);
 			if (e_idx >= 0) {
 				break;
 			}
 			/* SCANBUILD: NULL pointer dereference, doesn't actually trigger,
 			 * asserted above.
 			 */
-			holder = holder->prototype;
+			holder = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, holder);
 		}
 		DUK_ASSERT(holder != NULL);
 		DUK_ASSERT(e_idx >= 0);
@@ -56573,7 +74783,7 @@ static duk_bool_t duk__declvar_helper(duk_hthread *thr,
 		 * conflicting property.
 		 */
 
-		flags = DUK_HOBJECT_E_GET_FLAGS(holder, e_idx);
+		flags = DUK_HOBJECT_E_GET_FLAGS(thr->heap, holder, e_idx);
 		if (!(flags & DUK_PROPDESC_FLAG_CONFIGURABLE)) {
 			if (flags & DUK_PROPDESC_FLAG_ACCESSOR) {
 				DUK_DDD(DUK_DDDPRINT("existing property is a non-configurable "
@@ -56603,35 +74813,31 @@ static duk_bool_t duk__declvar_helper(duk_hthread *thr,
 			if (flags & DUK_PROPDESC_FLAG_ACCESSOR) {
 				duk_hobject *tmp;
 
-				tmp = DUK_HOBJECT_E_GET_VALUE_GETTER(holder, e_idx);
-				DUK_HOBJECT_E_SET_VALUE_GETTER(holder, e_idx, NULL);
-				DUK_HOBJECT_DECREF(thr, tmp);
+				tmp = DUK_HOBJECT_E_GET_VALUE_GETTER(thr->heap, holder, e_idx);
+				DUK_HOBJECT_E_SET_VALUE_GETTER(thr->heap, holder, e_idx, NULL);
+				DUK_HOBJECT_DECREF_ALLOWNULL(thr, tmp);
 				DUK_UNREF(tmp);
-				tmp = DUK_HOBJECT_E_GET_VALUE_SETTER(holder, e_idx);
-				DUK_HOBJECT_E_SET_VALUE_SETTER(holder, e_idx, NULL);
-				DUK_HOBJECT_DECREF(thr, tmp);
+				tmp = DUK_HOBJECT_E_GET_VALUE_SETTER(thr->heap, holder, e_idx);
+				DUK_HOBJECT_E_SET_VALUE_SETTER(thr->heap, holder, e_idx, NULL);
+				DUK_HOBJECT_DECREF_ALLOWNULL(thr, tmp);
 				DUK_UNREF(tmp);
 			} else {
-				duk_tval tv_tmp;
-
-				tv = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(holder, e_idx);
-				DUK_TVAL_SET_TVAL(&tv_tmp, tv);
-				DUK_TVAL_SET_UNDEFINED_UNUSED(tv);
-				DUK_TVAL_DECREF(thr, &tv_tmp);
+				tv = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, holder, e_idx);
+				DUK_TVAL_SET_UNDEFINED_UPDREF(thr, tv);
 			}
 
 			/* Here val would be potentially invalid if we didn't make
 			 * a value copy at the caller.
 			 */
 
-			tv = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(holder, e_idx);
+			tv = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, holder, e_idx);
 			DUK_TVAL_SET_TVAL(tv, val);
 			DUK_TVAL_INCREF(thr, tv);
-			DUK_HOBJECT_E_SET_FLAGS(holder, e_idx, prop_flags);
+			DUK_HOBJECT_E_SET_FLAGS(thr->heap, holder, e_idx, prop_flags);
 
 			DUK_DDD(DUK_DDDPRINT("updated global binding, final result: "
 			                     "value -> %!T, prop_flags=0x%08lx",
-			                     (duk_tval *) DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(holder, e_idx),
+			                     (duk_tval *) DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, holder, e_idx),
 			                     (unsigned long) prop_flags));
 		} else {
 			DUK_DDD(DUK_DDDPRINT("redefine, offending property in ancestor"));
@@ -56658,7 +74864,7 @@ static duk_bool_t duk__declvar_helper(duk_hthread *thr,
 	} else {
 		DUK_ASSERT(DUK_HOBJECT_IS_OBJENV(env));
 
-		tv = duk_hobject_find_existing_entry_tval_ptr(env, DUK_HTHREAD_STRING_INT_TARGET(thr));
+		tv = duk_hobject_find_existing_entry_tval_ptr(thr->heap, env, DUK_HTHREAD_STRING_INT_TARGET(thr));
 		DUK_ASSERT(tv != NULL);
 		DUK_ASSERT(DUK_TVAL_IS_OBJECT(tv));
 		holder = DUK_TVAL_GET_OBJECT(tv);
@@ -56683,7 +74889,7 @@ static duk_bool_t duk__declvar_helper(duk_hthread *thr,
 	duk_push_hobject(ctx, holder);
 	duk_push_hstring(ctx, name);
 	duk_push_tval(ctx, val);
-	duk_def_prop(ctx, -3, prop_flags);  /* [holder name val] -> [holder] */
+	duk_xdef_prop(ctx, -3, prop_flags);  /* [holder name val] -> [holder] */
 	duk_pop(ctx);
 
 	return 0;
@@ -56694,6 +74900,7 @@ static duk_bool_t duk__declvar_helper(duk_hthread *thr,
 	return 0;
 }
 
+DUK_INTERNAL
 duk_bool_t duk_js_declvar_activation(duk_hthread *thr,
                                      duk_activation *act,
                                      duk_hstring *name,
@@ -56745,8 +74952,8 @@ duk_bool_t duk_js_declvar_activation(duk_hthread *thr,
  *  perform multiple character lookups efficiently and with few sanity
  *  checks (such as access outside the end of the input), which keeps the
  *  tokenization code small at the cost of performance.
- * 
- *  Character data in tokens (such as identifier names and string literals)
+ *
+ *  Character data in tokens, such as identifier names and string literals,
  *  is encoded into CESU-8 format on-the-fly while parsing the token in
  *  question.  The string data is made reachable to garbage collection by
  *  placing the token-related values in value stack entries allocated for
@@ -56772,12 +74979,7 @@ duk_bool_t duk_js_declvar_activation(duk_hthread *thr,
  *
  *  Future work:
  *
- *    * Make the input window a circular array to avoid copying.  This would
- *      not necessarily complicate the tokenizer much, although it would make
- *      the window fetches more expensive (one AND).
- *
- *    * Make line number tracking optional, as it consumes space.  Also, is
- *      tracking end line really useful for tokens?
+ *    * Make line number tracking optional, as it consumes space.
  *
  *    * Add a feature flag for disabling UTF-8 decoding of input, as most
  *      source code is ASCII.  Because of Unicode escapes written in ASCII,
@@ -56802,7 +75004,8 @@ duk_bool_t duk_js_declvar_activation(duk_hthread *thr,
  *      not after tokens have been formed (as is done now).  However, the fix
  *      is not trivial because two characters are decoded from one codepoint.
  *
- *    * Optimize for speed as well as size.  Large if-else ladders are slow.
+ *    * Optimize for speed as well as size.  Large if-else ladders are (at
+ *      least potentially) slow.
  */
 
 /* include removed: duk_internal.h */
@@ -56814,11 +75017,6 @@ duk_bool_t duk_js_declvar_activation(duk_hthread *thr,
 #define DUK__MAX_RE_DECESC_DIGITS     9
 #define DUK__MAX_RE_QUANT_DIGITS      9   /* Does not allow e.g. 2**31-1, but one more would allow overflows of u32. */
 
-#define DUK__LOOKUP(lex_ctx,index)    ((lex_ctx)->window[(index)])
-#define DUK__ADVANCE(lex_ctx,count)   duk__advance_chars((lex_ctx), (count))
-#define DUK__INITBUFFER(lex_ctx)      duk__initbuffer((lex_ctx))
-#define DUK__APPENDBUFFER(lex_ctx,x)  duk__appendbuffer((lex_ctx), (duk_codepoint_t) (x))
-
 /* whether to use macros or helper function depends on call count */
 #define DUK__ISDIGIT(x)          ((x) >= DUK_ASC_0 && (x) <= DUK_ASC_9)
 #define DUK__ISHEXDIGIT(x)       duk__is_hex_digit((x))
@@ -56826,6 +75024,13 @@ duk_bool_t duk_js_declvar_activation(duk_hthread *thr,
 #define DUK__ISDIGIT03(x)        ((x) >= DUK_ASC_0 && (x) <= DUK_ASC_3)
 #define DUK__ISDIGIT47(x)        ((x) >= DUK_ASC_4 && (x) <= DUK_ASC_7)
 
+/* lexer character window helpers */
+#define DUK__LOOKUP(lex_ctx,index)        ((lex_ctx)->window[(index)].codepoint)
+#define DUK__ADVANCECHARS(lex_ctx,count)  duk__advance_bytes((lex_ctx), (count) * sizeof(duk_lexer_codepoint))
+#define DUK__ADVANCEBYTES(lex_ctx,count)  duk__advance_bytes((lex_ctx), (count))
+#define DUK__INITBUFFER(lex_ctx)          duk__initbuffer((lex_ctx))
+#define DUK__APPENDBUFFER(lex_ctx,x)      duk__appendbuffer((lex_ctx), (duk_codepoint_t) (x))
+
 /* lookup shorthands (note: assume context variable is named 'lex_ctx') */
 #define DUK__L0()  DUK__LOOKUP(lex_ctx, 0)
 #define DUK__L1()  DUK__LOOKUP(lex_ctx, 1)
@@ -56835,10 +75040,23 @@ duk_bool_t duk_js_declvar_activation(duk_hthread *thr,
 #define DUK__L5()  DUK__LOOKUP(lex_ctx, 5)
 
 /* packed advance/token number macro used by multiple functions */
-#define DUK__ADVTOK(adv,tok)  (((adv) << 8) + (tok))
+#define DUK__ADVTOK(advbytes,tok)  ((((advbytes) * sizeof(duk_lexer_codepoint)) << 8) + (tok))
 
 /*
- *  Read a character from the window leading edge and update the line counter.
+ *  Advance lookup window by N characters, filling in new characters as
+ *  necessary.  After returning caller is guaranteed a character window of
+ *  at least DUK_LEXER_WINDOW_SIZE characters.
+ *
+ *  The main function duk__advance_bytes() is called at least once per every
+ *  token so it has a major lexer/compiler performance impact.  There are two
+ *  variants for the main duk__advance_bytes() algorithm: a sliding window
+ *  approach which is slightly faster at the cost of larger code footprint,
+ *  and a simple copying one.
+ *
+ *  Decoding directly from the source string would be another lexing option.
+ *  But the lookup window based approach has the advantage of hiding the
+ *  source string and its encoding effectively which gives more flexibility
+ *  going forward to e.g. support chunked streaming of source from flash.
  *
  *  Decodes UTF-8/CESU-8 leniently with support for code points from U+0000 to
  *  U+10FFFF, causing an error if the input is unparseable.  Leniency means:
@@ -56882,22 +75100,198 @@ duk_bool_t duk_js_declvar_activation(duk_hthread *thr,
  *
  *    * Reject other invalid Unicode sequences (see Wikipedia entry for examples)
  *      in strict UTF-8 mode.
- * 
+ *
  *    * Size optimize.  An attempt to use a 16-byte lookup table for the first
  *      byte resulted in a code increase though.
  *
  *    * Is checking against maximum 0x10ffff really useful?  4-byte encoding
  *      imposes a certain limit anyway.
+ *
+ *    * Support chunked streaming of source code.  Can be implemented either
+ *      by streaming chunks of bytes or chunks of codepoints.
  */
 
-static duk_codepoint_t duk__read_char(duk_lexer_ctx *lex_ctx) {
-	/* attempting to reduce size of 'len' and/or 'i' resulted in larger code */
-	duk_codepoint_t x;
-	duk_small_int_t len;
-	duk_small_int_t i;
+#if defined(DUK_USE_LEXER_SLIDING_WINDOW)
+DUK_LOCAL void duk__fill_lexer_buffer(duk_lexer_ctx *lex_ctx, duk_small_uint_t start_offset_bytes) {
+	duk_lexer_codepoint *cp, *cp_end;
+	duk_ucodepoint_t x;
+	duk_small_uint_t contlen;
+	const duk_uint8_t *p, *p_end;
+#ifdef DUK_USE_STRICT_UTF8_SOURCE
+	duk_ucodepoint_t mincp;
+#endif
+	duk_int_t input_line;
+
+	/* Use temporaries and update lex_ctx only when finished. */
+	input_line = lex_ctx->input_line;
+	p = lex_ctx->input + lex_ctx->input_offset;
+	p_end = lex_ctx->input + lex_ctx->input_length;
+
+	cp = (duk_lexer_codepoint *) (void *) ((duk_uint8_t *) lex_ctx->buffer + start_offset_bytes);
+	cp_end = lex_ctx->buffer + DUK_LEXER_BUFFER_SIZE;
+
+	for (; cp != cp_end; cp++) {
+		cp->offset = (duk_size_t) (p - lex_ctx->input);
+		cp->line = input_line;
+
+		/* XXX: potential issue with signed pointers, p_end < p. */
+		if (DUK_UNLIKELY(p >= p_end)) {
+			/* If input_offset were assigned a negative value, it would
+			 * result in a large positive value.  Most likely it would be
+			 * larger than input_length and be caught here.  In any case
+			 * no memory unsafe behavior would happen.
+			 */
+			cp->codepoint = -1;
+			continue;
+		}
+
+		x = (duk_ucodepoint_t) (*p++);
+
+		/* Fast path. */
+
+		if (DUK_LIKELY(x < 0x80UL)) {
+			DUK_ASSERT(x != 0x2028UL && x != 0x2029UL);  /* not LS/PS */
+			if (DUK_UNLIKELY(x <= 0x000dUL)) {
+				if ((x == 0x000aUL) ||
+				    ((x == 0x000dUL) && (p >= p_end || *p != 0x000aUL))) {
+					/* lookup for 0x000a above assumes shortest encoding now */
+
+					/* E5 Section 7.3, treat the following as newlines:
+					 *   LF
+					 *   CR [not followed by LF]
+					 *   LS
+					 *   PS
+					 *
+					 * For CR LF, CR is ignored if it is followed by LF, and the LF will bump
+					 * the line number.
+					 */
+					input_line++;
+				}
+			}
+
+			cp->codepoint = (duk_codepoint_t) x;
+			continue;
+		}
+
+		/* Slow path. */
+
+		if (x < 0xc0UL) {
+			/* 10xx xxxx -> invalid */
+			goto error_encoding;
+		} else if (x < 0xe0UL) {
+			/* 110x xxxx   10xx xxxx  */
+			contlen = 1;
+#ifdef DUK_USE_STRICT_UTF8_SOURCE
+			mincp = 0x80UL;
+#endif
+			x = x & 0x1fUL;
+		} else if (x < 0xf0UL) {
+			/* 1110 xxxx   10xx xxxx   10xx xxxx */
+			contlen = 2;
+#ifdef DUK_USE_STRICT_UTF8_SOURCE
+			mincp = 0x800UL;
+#endif
+			x = x & 0x0fUL;
+		} else if (x < 0xf8UL) {
+			/* 1111 0xxx   10xx xxxx   10xx xxxx   10xx xxxx */
+			contlen = 3;
+#ifdef DUK_USE_STRICT_UTF8_SOURCE
+			mincp = 0x10000UL;
+#endif
+			x = x & 0x07UL;
+		} else {
+			/* no point in supporting encodings of 5 or more bytes */
+			goto error_encoding;
+		}
+
+		DUK_ASSERT(p_end >= p);
+		if ((duk_size_t) contlen > (duk_size_t) (p_end - p)) {
+			goto error_clipped;
+		}
+
+		while (contlen > 0) {
+			duk_small_uint_t y;
+			y = *p++;
+			if ((y & 0xc0U) != 0x80U) {
+				/* check that byte has the form 10xx xxxx */
+				goto error_encoding;
+			}
+			x = x << 6;
+			x += y & 0x3fUL;
+			contlen--;
+		}
+
+		/* check final character validity */
+
+		if (x > 0x10ffffUL) {
+			goto error_encoding;
+		}
+#ifdef DUK_USE_STRICT_UTF8_SOURCE
+		if (x < mincp || (x >= 0xd800UL && x <= 0xdfffUL) || x == 0xfffeUL) {
+			goto error_encoding;
+		}
+#endif
+
+		DUK_ASSERT(x != 0x000aUL && x != 0x000dUL);
+		if ((x == 0x2028UL) || (x == 0x2029UL)) {
+			input_line++;
+		}
+
+		cp->codepoint = (duk_codepoint_t) x;
+	}
+
+	lex_ctx->input_offset = (duk_size_t) (p - lex_ctx->input);
+	lex_ctx->input_line = input_line;
+	return;
+
+ error_clipped:   /* clipped codepoint */
+ error_encoding:  /* invalid codepoint encoding or codepoint */
+	lex_ctx->input_offset = (duk_size_t) (p - lex_ctx->input);
+	lex_ctx->input_line = input_line;
+
+	DUK_ERROR(lex_ctx->thr, DUK_ERR_SYNTAX_ERROR, "utf8 decode failed");
+}
+
+DUK_LOCAL void duk__advance_bytes(duk_lexer_ctx *lex_ctx, duk_small_uint_t count_bytes) {
+	duk_small_uint_t used_bytes, avail_bytes;
+
+	DUK_ASSERT_DISABLE(count_bytes >= 0);  /* unsigned */
+	DUK_ASSERT(count_bytes <= (duk_small_uint_t) (DUK_LEXER_WINDOW_SIZE * sizeof(duk_lexer_codepoint)));
+	DUK_ASSERT(lex_ctx->window >= lex_ctx->buffer);
+	DUK_ASSERT(lex_ctx->window < lex_ctx->buffer + DUK_LEXER_BUFFER_SIZE);
+	DUK_ASSERT((duk_uint8_t *) lex_ctx->window + count_bytes <= (duk_uint8_t *) lex_ctx->buffer + DUK_LEXER_BUFFER_SIZE * sizeof(duk_lexer_codepoint));
+
+	/* Zero 'count' is also allowed to make call sites easier.
+	 * Arithmetic in bytes generates better code in GCC.
+	 */
+
+	lex_ctx->window = (duk_lexer_codepoint *) (void *) ((duk_uint8_t *) lex_ctx->window + count_bytes);  /* avoid multiply */
+	used_bytes = (duk_small_uint_t) ((duk_uint8_t *) lex_ctx->window - (duk_uint8_t *) lex_ctx->buffer);
+	avail_bytes = DUK_LEXER_BUFFER_SIZE * sizeof(duk_lexer_codepoint) - used_bytes;
+	if (avail_bytes < (duk_small_uint_t) (DUK_LEXER_WINDOW_SIZE * sizeof(duk_lexer_codepoint))) {
+		/* Not enough data to provide a full window, so "scroll" window to
+		 * start of buffer and fill up the rest.
+		 */
+		DUK_MEMMOVE((void *) lex_ctx->buffer,
+		            (const void *) lex_ctx->window,
+		            (size_t) avail_bytes);
+		lex_ctx->window = lex_ctx->buffer;
+		duk__fill_lexer_buffer(lex_ctx, avail_bytes);
+	}
+}
+
+DUK_LOCAL void duk__init_lexer_window(duk_lexer_ctx *lex_ctx) {
+	lex_ctx->window = lex_ctx->buffer;
+	duk__fill_lexer_buffer(lex_ctx, 0);
+}
+#else  /* DUK_USE_LEXER_SLIDING_WINDOW */
+DUK_LOCAL duk_codepoint_t duk__read_char(duk_lexer_ctx *lex_ctx) {
+	duk_ucodepoint_t x;
+	duk_small_uint_t len;
+	duk_small_uint_t i;
 	const duk_uint8_t *p;
 #ifdef DUK_USE_STRICT_UTF8_SOURCE
-	duk_codepoint_t mincp;
+	duk_ucodepoint_t mincp;
 #endif
 	duk_size_t input_offset;
 
@@ -56912,36 +75306,63 @@ static duk_codepoint_t duk__read_char(duk_lexer_ctx *lex_ctx) {
 	}
 
 	p = lex_ctx->input + input_offset;
-	x = (int) *p++;
+	x = (duk_ucodepoint_t) (*p);
 
-	if (x < 0x80L) {
+	if (DUK_LIKELY(x < 0x80UL)) {
 		/* 0xxx xxxx -> fast path */
-		len = 1;
-		goto fastpath;
-	} else if (x < 0xc0L) {
+
+		/* input offset tracking */
+		lex_ctx->input_offset++;
+
+		DUK_ASSERT(x != 0x2028UL && x != 0x2029UL);  /* not LS/PS */
+		if (DUK_UNLIKELY(x <= 0x000dUL)) {
+			if ((x == 0x000aUL) ||
+			    ((x == 0x000dUL) && (lex_ctx->input_offset >= lex_ctx->input_length ||
+			                         lex_ctx->input[lex_ctx->input_offset] != 0x000aUL))) {
+				/* lookup for 0x000a above assumes shortest encoding now */
+
+				/* E5 Section 7.3, treat the following as newlines:
+				 *   LF
+				 *   CR [not followed by LF]
+				 *   LS
+				 *   PS
+				 *
+				 * For CR LF, CR is ignored if it is followed by LF, and the LF will bump
+				 * the line number.
+				 */
+				lex_ctx->input_line++;
+			}
+		}
+
+		return (duk_codepoint_t) x;
+	}
+
+	/* Slow path. */
+
+	if (x < 0xc0UL) {
 		/* 10xx xxxx -> invalid */
 		goto error_encoding;
-	} else if (x < 0xe0L) {
+	} else if (x < 0xe0UL) {
 		/* 110x xxxx   10xx xxxx  */
 		len = 2;
 #ifdef DUK_USE_STRICT_UTF8_SOURCE
-		mincp = 0x80L;
+		mincp = 0x80UL;
 #endif
-		x = x & 0x1fL;
-	} else if (x < 0xf0L) {
+		x = x & 0x1fUL;
+	} else if (x < 0xf0UL) {
 		/* 1110 xxxx   10xx xxxx   10xx xxxx */
 		len = 3;
 #ifdef DUK_USE_STRICT_UTF8_SOURCE
-		mincp = 0x800L;
+		mincp = 0x800UL;
 #endif
-		x = x & 0x0fL;
-	} else if (x < 0xf8L) {
+		x = x & 0x0fUL;
+	} else if (x < 0xf8UL) {
 		/* 1111 0xxx   10xx xxxx   10xx xxxx   10xx xxxx */
 		len = 4;
 #ifdef DUK_USE_STRICT_UTF8_SOURCE
-		mincp = 0x10000L;
+		mincp = 0x10000UL;
 #endif
-		x = x & 0x07;
+		x = x & 0x07UL;
 	} else {
 		/* no point in supporting encodings of 5 or more bytes */
 		goto error_encoding;
@@ -56952,107 +75373,89 @@ static duk_codepoint_t duk__read_char(duk_lexer_ctx *lex_ctx) {
 		goto error_clipped;
 	}
 
+	p++;
 	for (i = 1; i < len; i++) {
-		duk_small_int_t y = *p++;
-		if ((y & 0xc0) != 0x80) {
+		duk_small_uint_t y;
+		y = *p++;
+		if ((y & 0xc0U) != 0x80U) {
 			/* check that byte has the form 10xx xxxx */
 			goto error_encoding;
 		}
 		x = x << 6;
-		x += y & 0x3f;
+		x += y & 0x3fUL;
 	}
 
 	/* check final character validity */
 
-	if (x > 0x10ffffL) {
+	if (x > 0x10ffffUL) {
 		goto error_encoding;
 	}
 #ifdef DUK_USE_STRICT_UTF8_SOURCE
-	if (x < mincp || (x >= 0xd800L && x <= 0xdfffL) || x == 0xfffeL) {
+	if (x < mincp || (x >= 0xd800UL && x <= 0xdfffUL) || x == 0xfffeUL) {
 		goto error_encoding;
 	}
 #endif
 
-	/* fall through */
-
- fastpath:
 	/* input offset tracking */
 	lex_ctx->input_offset += len;
 
 	/* line tracking */
-	if ((x == 0x000aL) ||
-	    ((x == 0x000dL) && (lex_ctx->input_offset >= lex_ctx->input_length ||
-	                        lex_ctx->input[lex_ctx->input_offset] != 0x000aL)) ||
-	    (x == 0x2028L) ||
-	    (x == 0x2029L)) {
-		/* lookup for 0x000a above assumes shortest encoding now */
-
-		/* E5 Section 7.3, treat the following as newlines:
-		 *   LF
-		 *   CR [not followed by LF]
-		 *   LS
-		 *   PS
-		 *
-		 * For CR LF, CR is ignored if it is followed by LF, and the LF will bump
-		 * the line number.
-		 */
+	DUK_ASSERT(x != 0x000aUL && x != 0x000dUL);
+	if ((x == 0x2028UL) || (x == 0x2029UL)) {
 		lex_ctx->input_line++;
 	}
 
-	return x;
+	return (duk_codepoint_t) x;
 
  error_clipped:   /* clipped codepoint */
  error_encoding:  /* invalid codepoint encoding or codepoint */
-	DUK_ERROR(lex_ctx->thr, DUK_ERR_SYNTAX_ERROR, "char decode failed");
+	DUK_ERROR(lex_ctx->thr, DUK_ERR_SYNTAX_ERROR, "utf8 decode failed");
 	return 0;
 }
 
-/*
- *  Advance lookup window by N characters.  Also used to fill the window
- *  after position is changed (call with count == DUK_LEXER_WINDOW_SIZE).
- *
- *  XXX: A lot of copying now, perhaps change to circular array or at
- *  least use memcpy().  For memcpy(), putting all elements of the
- *  window (code point, offset, line) into a struct would allow one
- *  memcpy() to slide the window, instead of three separate copys.
- */
+DUK_LOCAL void duk__advance_bytes(duk_lexer_ctx *lex_ctx, duk_small_uint_t count_bytes) {
+	duk_small_uint_t keep_bytes;
+	duk_lexer_codepoint *cp, *cp_end;
 
-static void duk__advance_chars(duk_lexer_ctx *lex_ctx, duk_small_int_t count) {
-	duk_small_int_t i, n;
+	DUK_ASSERT_DISABLE(count_bytes >= 0);  /* unsigned */
+	DUK_ASSERT(count_bytes <= (duk_small_uint_t) (DUK_LEXER_WINDOW_SIZE * sizeof(duk_lexer_codepoint)));
 
-	DUK_ASSERT(count >= 0 && count <= DUK_LEXER_WINDOW_SIZE);
+	/* Zero 'count' is also allowed to make call sites easier. */
 
-	if (count == 0) {
-		/* allowing zero count makes some special caller flows easier */
-		return;
-	}
+	keep_bytes = DUK_LEXER_WINDOW_SIZE * sizeof(duk_lexer_codepoint) - count_bytes;
+	DUK_MEMMOVE((void *) lex_ctx->window,
+	            (const void *) ((duk_uint8_t *) lex_ctx->window + count_bytes),
+	            (size_t) keep_bytes);
 
-	n = DUK_LEXER_WINDOW_SIZE - count;
-	for (i = 0; i < n; i++) {
-		lex_ctx->offsets[i] = lex_ctx->offsets[i + count];
-		lex_ctx->lines[i] = lex_ctx->lines[i + count];
-		lex_ctx->window[i] = lex_ctx->window[i + count];
+	cp = (duk_lexer_codepoint *) ((duk_uint8_t *) lex_ctx->window + keep_bytes);
+	cp_end = lex_ctx->window + DUK_LEXER_WINDOW_SIZE;
+	for (; cp != cp_end; cp++) {
+		cp->offset = lex_ctx->input_offset;
+		cp->line = lex_ctx->input_line;
+		cp->codepoint = duk__read_char(lex_ctx);
 	}
+}
 
-	for (; i < DUK_LEXER_WINDOW_SIZE; i++) {
-		lex_ctx->offsets[i] = lex_ctx->input_offset;
-		lex_ctx->lines[i] = lex_ctx->input_line;
-		lex_ctx->window[i] = duk__read_char(lex_ctx);
-	}
+DUK_LOCAL void duk__init_lexer_window(duk_lexer_ctx *lex_ctx) {
+	/* Call with count == DUK_LEXER_WINDOW_SIZE to fill buffer initially. */
+	duk__advance_bytes(lex_ctx, DUK_LEXER_WINDOW_SIZE * sizeof(duk_lexer_codepoint));  /* fill window */
 }
+#endif  /* DUK_USE_LEXER_SLIDING_WINDOW */
 
 /*
  *  (Re)initialize the temporary byte buffer.  May be called extra times
  *  with little impact.
  */
 
-static void duk__initbuffer(duk_lexer_ctx *lex_ctx) {
-	if (lex_ctx->buf->usable_size < DUK_LEXER_TEMP_BUF_LIMIT) {
-		/* Resize (zero) without realloc. */
-		lex_ctx->buf->size = 0;
+DUK_LOCAL void duk__initbuffer(duk_lexer_ctx *lex_ctx) {
+	/* Reuse buffer as is unless buffer has grown large. */
+	if (DUK_HBUFFER_DYNAMIC_GET_SIZE(lex_ctx->buf) < DUK_LEXER_TEMP_BUF_LIMIT) {
+		/* Keep current size */
 	} else {
-		duk_hbuffer_resize(lex_ctx->thr, lex_ctx->buf, 0, DUK_LEXER_TEMP_BUF_LIMIT);
+		duk_hbuffer_resize(lex_ctx->thr, lex_ctx->buf, DUK_LEXER_TEMP_BUF_LIMIT);
 	}
+
+	DUK_BW_INIT_WITHBUF(lex_ctx->thr, &lex_ctx->bw, lex_ctx->buf);
 }
 
 /*
@@ -57061,7 +75464,7 @@ static void duk__initbuffer(duk_lexer_ctx *lex_ctx) {
  *  Existing surrogate pairs are allowed and also encoded into CESU-8.
  */
 
-static void duk__appendbuffer(duk_lexer_ctx *lex_ctx, duk_codepoint_t x) {
+DUK_LOCAL void duk__appendbuffer(duk_lexer_ctx *lex_ctx, duk_codepoint_t x) {
 	/*
 	 *  Since character data is only generated by decoding the source or by
 	 *  the compiler itself, we rely on the input codepoints being correct
@@ -57074,7 +75477,7 @@ static void duk__appendbuffer(duk_lexer_ctx *lex_ctx, duk_codepoint_t x) {
 
 	DUK_ASSERT(x >= 0 && x <= 0x10ffff);
 
-	duk_hbuffer_append_cesu8(lex_ctx->thr, lex_ctx->buf, (duk_ucodepoint_t) x);
+	DUK_BW_WRITE_ENSURE_CESU8(lex_ctx->thr, &lex_ctx->bw, (duk_ucodepoint_t) x);
 }
 
 /*
@@ -57082,13 +75485,12 @@ static void duk__appendbuffer(duk_lexer_ctx *lex_ctx, duk_codepoint_t x) {
  *  (in practice, slot1 or slot2).
  */
 
-static void duk__internbuffer(duk_lexer_ctx *lex_ctx, duk_idx_t valstack_idx) {
+DUK_LOCAL void duk__internbuffer(duk_lexer_ctx *lex_ctx, duk_idx_t valstack_idx) {
 	duk_context *ctx = (duk_context *) lex_ctx->thr;
 
 	DUK_ASSERT(valstack_idx == lex_ctx->slot1_idx || valstack_idx == lex_ctx->slot2_idx);
 
-	duk_dup(ctx, lex_ctx->buf_idx);
-	duk_to_string(ctx, -1);
+	DUK_BW_PUSH_AS_STRING(lex_ctx->thr, &lex_ctx->bw);
 	duk_replace(ctx, valstack_idx);
 }
 
@@ -57096,11 +75498,14 @@ static void duk__internbuffer(duk_lexer_ctx *lex_ctx, duk_idx_t valstack_idx) {
  *  Init lexer context
  */
 
-void duk_lexer_initctx(duk_lexer_ctx *lex_ctx) {
+DUK_INTERNAL void duk_lexer_initctx(duk_lexer_ctx *lex_ctx) {
 	DUK_ASSERT(lex_ctx != NULL);
 
 	DUK_MEMZERO(lex_ctx, sizeof(*lex_ctx));
 #ifdef DUK_USE_EXPLICIT_NULL_INIT
+#if defined(DUK_USE_LEXER_SLIDING_WINDOW)
+	lex_ctx->window = NULL;
+#endif
 	lex_ctx->thr = NULL;
 	lex_ctx->input = NULL;
 	lex_ctx->buf = NULL;
@@ -57113,12 +75518,12 @@ void duk_lexer_initctx(duk_lexer_ctx *lex_ctx) {
 
 /* NB: duk_lexer_getpoint() is a macro only */
 
-void duk_lexer_setpoint(duk_lexer_ctx *lex_ctx, duk_lexer_point *pt) {
+DUK_INTERNAL void duk_lexer_setpoint(duk_lexer_ctx *lex_ctx, duk_lexer_point *pt) {
 	DUK_ASSERT_DISABLE(pt->offset >= 0);  /* unsigned */
 	DUK_ASSERT(pt->line >= 1);
 	lex_ctx->input_offset = pt->offset;
 	lex_ctx->input_line = pt->line;
-	duk__advance_chars(lex_ctx, DUK_LEXER_WINDOW_SIZE);  /* fill window */
+	duk__init_lexer_window(lex_ctx);
 }
 
 /*
@@ -57126,7 +75531,7 @@ void duk_lexer_setpoint(duk_lexer_ctx *lex_ctx, duk_lexer_point *pt) {
  */
 
 /* numeric value of a hex digit (also covers octal and decimal digits) */
-static duk_codepoint_t duk__hexval(duk_lexer_ctx *lex_ctx, duk_codepoint_t x) {
+DUK_LOCAL duk_codepoint_t duk__hexval(duk_lexer_ctx *lex_ctx, duk_codepoint_t x) {
 	duk_small_int_t t;
 
 	/* Here 'x' is a Unicode codepoint */
@@ -57145,52 +75550,42 @@ static duk_codepoint_t duk__hexval(duk_lexer_ctx *lex_ctx, duk_codepoint_t x) {
 }
 
 /* having this as a separate function provided a size benefit */
-static duk_bool_t duk__is_hex_digit(duk_codepoint_t x) {
+DUK_LOCAL duk_bool_t duk__is_hex_digit(duk_codepoint_t x) {
 	if (DUK_LIKELY(x >= 0 && x <= 0xff)) {
 		return (duk_hex_dectab[x] >= 0);
 	}
 	return 0;
 }
 
-static duk_codepoint_t duk__decode_hexesc_from_window(duk_lexer_ctx *lex_ctx, duk_small_int_t lookup_offset) {
+DUK_LOCAL duk_codepoint_t duk__decode_hexesc_from_window(duk_lexer_ctx *lex_ctx, duk_small_int_t lookup_offset) {
 	/* validation performed by duk__hexval */
-	return (duk__hexval(lex_ctx, lex_ctx->window[lookup_offset]) << 4) |
-	       (duk__hexval(lex_ctx, lex_ctx->window[lookup_offset + 1]));
+	return (duk__hexval(lex_ctx, lex_ctx->window[lookup_offset].codepoint) << 4) |
+	       (duk__hexval(lex_ctx, lex_ctx->window[lookup_offset + 1].codepoint));
 }
 
-static duk_codepoint_t duk__decode_uniesc_from_window(duk_lexer_ctx *lex_ctx, duk_small_int_t lookup_offset) {
+DUK_LOCAL duk_codepoint_t duk__decode_uniesc_from_window(duk_lexer_ctx *lex_ctx, duk_small_int_t lookup_offset) {
 	/* validation performed by duk__hexval */
-	return (duk__hexval(lex_ctx, lex_ctx->window[lookup_offset]) << 12) |
-	       (duk__hexval(lex_ctx, lex_ctx->window[lookup_offset + 1]) << 8) |
-	       (duk__hexval(lex_ctx, lex_ctx->window[lookup_offset + 2]) << 4) |
-	       (duk__hexval(lex_ctx, lex_ctx->window[lookup_offset + 3]));
-}
-
-/*
- *  Eat input characters until first character of window is not
- *  a white space (may be -1 if EOF encountered).
- */
-static void duk__eat_whitespace(duk_lexer_ctx *lex_ctx) {
-	/* guaranteed to finish, as EOF (-1) is not a whitespace */
-	while (duk_unicode_is_whitespace(DUK__LOOKUP(lex_ctx, 0))) {
-		DUK__ADVANCE(lex_ctx, 1);
-	}
+	return (duk__hexval(lex_ctx, lex_ctx->window[lookup_offset].codepoint) << 12) |
+	       (duk__hexval(lex_ctx, lex_ctx->window[lookup_offset + 1].codepoint) << 8) |
+	       (duk__hexval(lex_ctx, lex_ctx->window[lookup_offset + 2].codepoint) << 4) |
+	       (duk__hexval(lex_ctx, lex_ctx->window[lookup_offset + 3].codepoint));
 }
 
 /*
  *  Parse Ecmascript source InputElementDiv or InputElementRegExp
- *  (E5 Section 7).
+ *  (E5 Section 7), skipping whitespace, comments, and line terminators.
  *
  *  Possible results are:
  *    (1) a token
- *    (2) a line terminator
- *    (3) a comment
+ *    (2) a line terminator (skipped)
+ *    (3) a comment (skipped)
  *    (4) EOF
  *
  *  White space is automatically skipped from the current position (but
  *  not after the input element).  If input has already ended, returns
  *  DUK_TOK_EOF indefinitely.  If a parse error occurs, uses an DUK_ERROR()
  *  macro call (and hence a longjmp through current heap longjmp context).
+ *  Comments and line terminator tokens are automatically skipped.
  *
  *  The input element being matched is determined by regexp_mode; if set,
  *  parses a InputElementRegExp, otherwise a InputElementDiv.  The
@@ -57235,43 +75630,46 @@ static void duk__eat_whitespace(duk_lexer_ctx *lex_ctx) {
  *      number of escapes.  Directive detection can then check that the
  *      number of escapes is zero.
  *
- *    * Comments are expressed as DUK_TOK_COMMENT tokens, with the type
- *      (single- or multi-line) and contents of the comments lost.
- *      Furthermore, multi-line comments with one or more internal
- *      LineTerminator are treated as DUK_TOK_LINETERM to comply with
- *      automatic semicolon insertion and to avoid complicating the
- *      tokenization process.  See E5 Section 7.4.
+ *    * Multi-line comments with one or more internal LineTerminator are
+ *      treated like a line terminator to comply with automatic semicolon
+ *      insertion.
  */
 
-static void duk__parse_input_element_raw(duk_lexer_ctx *lex_ctx,
-                                         duk_token *out_token,
-                                         duk_bool_t strict_mode,
-                                         duk_bool_t regexp_mode) {
-	duk_codepoint_t x, y;        /* temporaries, must be signed and 32-bit to hold Unicode code points */
+DUK_INTERNAL
+void duk_lexer_parse_js_input_element(duk_lexer_ctx *lex_ctx,
+                                      duk_token *out_token,
+                                      duk_bool_t strict_mode,
+                                      duk_bool_t regexp_mode) {
+	duk_codepoint_t x;           /* temporary, must be signed and 32-bit to hold Unicode code points */
 	duk_small_uint_t advtok = 0; /* (advance << 8) + token_type, updated at function end,
 	                              * init is unnecessary but suppresses "may be used uninitialized" warnings.
 	                              */
+	duk_bool_t got_lineterm = 0;  /* got lineterm preceding non-whitespace, non-lineterm token */
 
 	if (++lex_ctx->token_count >= lex_ctx->token_limit) {
 		DUK_ERROR(lex_ctx->thr, DUK_ERR_RANGE_ERROR, "token limit");
 		return;  /* unreachable */
 	}
 
-	duk__eat_whitespace(lex_ctx);
-
 	out_token->t = DUK_TOK_EOF;
-	out_token->t_nores = -1;	/* marker: copy t if not changed */
+	out_token->t_nores = -1;  /* marker: copy t if not changed */
+#if 0  /* not necessary to init, disabled for faster parsing */
 	out_token->num = DUK_DOUBLE_NAN;
 	out_token->str1 = NULL;
 	out_token->str2 = NULL;
+#endif
 	out_token->num_escapes = 0;
-	out_token->start_line = lex_ctx->lines[0];
-	out_token->start_offset = lex_ctx->offsets[0];
-	/* out_token->end_line set at exit */
 	/* out_token->lineterm set by caller */
 
+	/* This would be nice, but parsing is faster without resetting the
+	 * value slots.  The only side effect is that references to temporary
+	 * string values may linger until lexing is finished; they're then
+	 * freed normally.
+	 */
+#if 0
 	duk_to_undefined((duk_context *) lex_ctx->thr, lex_ctx->slot1_idx);
 	duk_to_undefined((duk_context *) lex_ctx->thr, lex_ctx->slot2_idx);
+#endif
 
 	/* 'advtok' indicates how much to advance and which token id to assign
 	 * at the end.  This shared functionality minimizes code size.  All
@@ -57293,57 +75691,66 @@ static void duk__parse_input_element_raw(duk_lexer_ctx *lex_ctx,
 	 *  The order does not matter as long as the longest match is
 	 *  always correctly identified.  There are order dependencies
 	 *  in the clauses, so it's not trivial to convert to a switch.
-	 *
-	 *  XXX: This is quite inefficient.  Maybe change to a switch
-	 *  statement which handles all single character cases and then
-	 *  use a followup if-else chain?  Switch matches need to use
-	 *  goto to bypass the if-else chain.
 	 */
 
+ restart_lineupdate:
+	out_token->start_line = lex_ctx->window[0].line;
+
+ restart:
+	out_token->start_offset = lex_ctx->window[0].offset;
+
 	x = DUK__L0();
-	y = DUK__L1();
 
-	if (x == '/') {
-		if (y == '/') {
+	switch (x) {
+	case DUK_ASC_SPACE:
+	case DUK_ASC_HT:  /* fast paths for space and tab */
+		DUK__ADVANCECHARS(lex_ctx, 1);
+		goto restart;
+	case DUK_ASC_LF:  /* LF line terminator; CR LF and Unicode lineterms are handled in slow path */
+		DUK__ADVANCECHARS(lex_ctx, 1);
+		got_lineterm = 1;
+		goto restart_lineupdate;
+	case DUK_ASC_SLASH:  /* '/' */
+		if (DUK__L1() == '/') {
 			/*
 			 *  E5 Section 7.4, allow SourceCharacter (which is any 16-bit
 			 *  code point).
 			 */
 
-			/* DUK__ADVANCE(lex_ctx, 2) would be correct here, but it unnecessary */
+			/* DUK__ADVANCECHARS(lex_ctx, 2) would be correct here, but it unnecessary */
 			for (;;) {
 				x = DUK__L0();
 				if (x < 0 || duk_unicode_is_line_terminator(x)) {
 					break;
 				}
-				DUK__ADVANCE(lex_ctx, 1);
+				DUK__ADVANCECHARS(lex_ctx, 1);
 			}
-			advtok = DUK__ADVTOK(0, DUK_TOK_COMMENT);
-		} else if (y == '*') {
+			goto restart;  /* line terminator will be handled on next round */
+		} else if (DUK__L1() == '*') {
 			/*
 			 *  E5 Section 7.4.  If the multi-line comment contains a newline,
-			 *  it is treated like a single DUK_TOK_LINETERM to facilitate
-			 *  automatic semicolon insertion.
+			 *  it is treated like a single line terminator for automatic
+			 *  semicolon insertion.
 			 */
 
 			duk_bool_t last_asterisk = 0;
-			advtok = DUK__ADVTOK(0, DUK_TOK_COMMENT);
-			DUK__ADVANCE(lex_ctx, 2);
+			DUK__ADVANCECHARS(lex_ctx, 2);
 			for (;;) {
 				x = DUK__L0();
 				if (x < 0) {
 					DUK_ERROR(lex_ctx->thr, DUK_ERR_SYNTAX_ERROR,
 					          "eof while parsing multiline comment");
 				}
-				DUK__ADVANCE(lex_ctx, 1);
+				DUK__ADVANCECHARS(lex_ctx, 1);
 				if (last_asterisk && x == '/') {
 					break;
 				}
 				if (duk_unicode_is_line_terminator(x)) {
-					advtok = DUK__ADVTOK(0, DUK_TOK_LINETERM);
+					got_lineterm = 1;
 				}
 				last_asterisk = (x == '*');
 			}
+			goto restart_lineupdate;
 		} else if (regexp_mode) {
 #ifdef DUK_USE_REGEXP_SUPPORT
 			/*
@@ -57378,14 +75785,14 @@ static void duk__parse_input_element_raw(duk_lexer_ctx *lex_ctx,
 			 *
 			 *      should first be parsed by the lexical grammar as:
 			 *
-			 *          '\' 'u'		RegularExpressionBackslashSequence
-			 *          '1'			RegularExpressionNonTerminator
-			 *          '2'			RegularExpressionNonTerminator
-			 *          '3'			RegularExpressionNonTerminator
-			 *          '4'			RegularExpressionNonTerminator
+			 *          '\' 'u'      RegularExpressionBackslashSequence
+			 *          '1'          RegularExpressionNonTerminator
+			 *          '2'          RegularExpressionNonTerminator
+			 *          '3'          RegularExpressionNonTerminator
+			 *          '4'          RegularExpressionNonTerminator
 			 *
 			 *      and the escape itself is then parsed by the regexp engine.
-			 *      This is the current implementation. 
+			 *      This is the current implementation.
 			 *
 			 *  Minor spec inconsistency:
 			 *
@@ -57396,9 +75803,9 @@ static void duk__parse_input_element_raw(duk_lexer_ctx *lex_ctx,
 			 *      while Section A.1 RegularExpressionBackslashSequence is:
 			 *
 			 *         \ NonTerminator
-			 * 
+			 *
 			 *      The latter is not normative and a typo.
-			 * 
+			 *
 			 */
 
 			/* first, parse regexp body roughly */
@@ -57407,16 +75814,16 @@ static void duk__parse_input_element_raw(duk_lexer_ctx *lex_ctx,
 
 			DUK__INITBUFFER(lex_ctx);
 			for (;;) {
-				DUK__ADVANCE(lex_ctx, 1);	/* skip opening slash on first loop */
+				DUK__ADVANCECHARS(lex_ctx, 1);  /* skip opening slash on first loop */
 				x = DUK__L0();
 				if (x < 0 || duk_unicode_is_line_terminator(x)) {
 					DUK_ERROR(lex_ctx->thr, DUK_ERR_SYNTAX_ERROR,
 					          "eof or line terminator while parsing regexp");
 				}
-				x = DUK__L0();	/* re-read to avoid spill / fetch */
+				x = DUK__L0();  /* re-read to avoid spill / fetch */
 				if (state == 0) {
 					if (x == '/') {
-						DUK__ADVANCE(lex_ctx, 1);	/* eat closing slash */
+						DUK__ADVANCECHARS(lex_ctx, 1);  /* eat closing slash */
 						break;
 					} else if (x == '\\') {
 						state = 1;
@@ -57447,14 +75854,14 @@ static void duk__parse_input_element_raw(duk_lexer_ctx *lex_ctx,
 				if (!duk_unicode_is_identifier_part(x)) {
 					break;
 				}
-				x = DUK__L0();	/* re-read to avoid spill / fetch */
+				x = DUK__L0();  /* re-read to avoid spill / fetch */
 				DUK__APPENDBUFFER(lex_ctx, x);
-				DUK__ADVANCE(lex_ctx, 1);
+				DUK__ADVANCECHARS(lex_ctx, 1);
 			}
 			duk__internbuffer(lex_ctx, lex_ctx->slot2_idx);
 			out_token->str2 = duk_get_hstring((duk_context *) lex_ctx->thr, lex_ctx->slot2_idx);
 
-			DUK__INITBUFFER(lex_ctx);	/* free some memory */
+			DUK__INITBUFFER(lex_ctx);  /* free some memory */
 
 			/* validation of the regexp is caller's responsibility */
 
@@ -57462,139 +75869,325 @@ static void duk__parse_input_element_raw(duk_lexer_ctx *lex_ctx,
 #else
 			DUK_ERROR(lex_ctx->thr, DUK_ERR_SYNTAX_ERROR, "regexp support disabled");
 #endif
-		} else if (y == '=') {
+		} else if (DUK__L1() == '=') {
 			/* "/=" and not in regexp mode */
 			advtok = DUK__ADVTOK(2, DUK_TOK_DIV_EQ);
 		} else {
 			/* "/" and not in regexp mode */
 			advtok = DUK__ADVTOK(1, DUK_TOK_DIV);
 		}
-	} else if (x == '{') {
+		break;
+	case DUK_ASC_LCURLY:  /* '{' */
 		advtok = DUK__ADVTOK(1, DUK_TOK_LCURLY);
-	} else if (x == '}') {
+		break;
+	case DUK_ASC_RCURLY:  /* '}' */
 		advtok = DUK__ADVTOK(1, DUK_TOK_RCURLY);
-	} else if (x == '(') {
+		break;
+	case DUK_ASC_LPAREN:  /* '(' */
 		advtok = DUK__ADVTOK(1, DUK_TOK_LPAREN);
-	} else if (x == ')') {
+		break;
+	case DUK_ASC_RPAREN:  /* ')' */
 		advtok = DUK__ADVTOK(1, DUK_TOK_RPAREN);
-	} else if (x == '[') {
+		break;
+	case DUK_ASC_LBRACKET:  /* '[' */
 		advtok = DUK__ADVTOK(1, DUK_TOK_LBRACKET);
-	} else if (x == ']') {
+		break;
+	case DUK_ASC_RBRACKET:  /* ']' */
 		advtok = DUK__ADVTOK(1, DUK_TOK_RBRACKET);
-	} else if (x == '.' && !DUK__ISDIGIT(y)) {
-		/* Note: period followed by a digit can only start DecimalLiteral (captured below) */
+		break;
+	case DUK_ASC_PERIOD:  /* '.' */
+		if (DUK__ISDIGIT(DUK__L1())) {
+			/* Period followed by a digit can only start DecimalLiteral
+			 * (handled in slow path).  We could jump straight into the
+			 * DecimalLiteral handling but should avoid goto to inside
+			 * a block.
+			 */
+			goto slow_path;
+		}
 		advtok = DUK__ADVTOK(1, DUK_TOK_PERIOD);
-	} else if (x == ';') {
+		break;
+	case DUK_ASC_SEMICOLON:  /* ';' */
 		advtok = DUK__ADVTOK(1, DUK_TOK_SEMICOLON);
-	} else if (x == ',') {
+		break;
+	case DUK_ASC_COMMA:  /* ',' */
 		advtok = DUK__ADVTOK(1, DUK_TOK_COMMA);
-	} else if (x == '<') {
-		if (y == '<' && DUK__L2() == '=') {
+		break;
+	case DUK_ASC_LANGLE:  /* '<' */
+		if (DUK__L1() == '<' && DUK__L2() == '=') {
 			advtok = DUK__ADVTOK(3, DUK_TOK_ALSHIFT_EQ);
-		} else if (y == '=') {
+		} else if (DUK__L1() == '=') {
 			advtok = DUK__ADVTOK(2, DUK_TOK_LE);
-		} else if (y == '<') {
+		} else if (DUK__L1() == '<') {
 			advtok = DUK__ADVTOK(2, DUK_TOK_ALSHIFT);
 		} else {
 			advtok = DUK__ADVTOK(1, DUK_TOK_LT);
 		}
-	} else if (x == '>') {
-		if (y == '>' && DUK__L2() == '>' && DUK__L3() == '=') {
+		break;
+	case DUK_ASC_RANGLE:  /* '>' */
+		if (DUK__L1() == '>' && DUK__L2() == '>' && DUK__L3() == '=') {
 			advtok = DUK__ADVTOK(4, DUK_TOK_RSHIFT_EQ);
-		} else if (y == '>' && DUK__L2() == '>') {
+		} else if (DUK__L1() == '>' && DUK__L2() == '>') {
 			advtok = DUK__ADVTOK(3, DUK_TOK_RSHIFT);
-		} else if (y == '>' && DUK__L2() == '=') {
+		} else if (DUK__L1() == '>' && DUK__L2() == '=') {
 			advtok = DUK__ADVTOK(3, DUK_TOK_ARSHIFT_EQ);
-		} else if (y == '=') {
+		} else if (DUK__L1() == '=') {
 			advtok = DUK__ADVTOK(2, DUK_TOK_GE);
-		} else if (y == '>') {
+		} else if (DUK__L1() == '>') {
 			advtok = DUK__ADVTOK(2, DUK_TOK_ARSHIFT);
 		} else {
 			advtok = DUK__ADVTOK(1, DUK_TOK_GT);
 		}
-	} else if (x == '=') {
-		if (y == '=' && DUK__L2() == '=') {
+		break;
+	case DUK_ASC_EQUALS:  /* '=' */
+		if (DUK__L1() == '=' && DUK__L2() == '=') {
 			advtok = DUK__ADVTOK(3, DUK_TOK_SEQ);
-		} else if (y == '=') {
+		} else if (DUK__L1() == '=') {
 			advtok = DUK__ADVTOK(2, DUK_TOK_EQ);
 		} else {
 			advtok = DUK__ADVTOK(1, DUK_TOK_EQUALSIGN);
 		}
-	} else if (x == '!') {
-		if (y == '=' && DUK__L2() == '=') {
+		break;
+	case DUK_ASC_EXCLAMATION:  /* '!' */
+		if (DUK__L1() == '=' && DUK__L2() == '=') {
 			advtok = DUK__ADVTOK(3, DUK_TOK_SNEQ);
-		} else if (y == '=') {
+		} else if (DUK__L1() == '=') {
 			advtok = DUK__ADVTOK(2, DUK_TOK_NEQ);
 		} else {
 			advtok = DUK__ADVTOK(1, DUK_TOK_LNOT);
 		}
-	} else if (x == '+') {
-		if (y == '+') {
+		break;
+	case DUK_ASC_PLUS:  /* '+' */
+		if (DUK__L1() == '+') {
 			advtok = DUK__ADVTOK(2, DUK_TOK_INCREMENT);
-		} else if (y == '=') {
+		} else if (DUK__L1() == '=') {
 			advtok = DUK__ADVTOK(2, DUK_TOK_ADD_EQ);
 		} else {
 			advtok = DUK__ADVTOK(1, DUK_TOK_ADD);
 		}
-	} else if (x == '-') {
-		if (y == '-') {
+		break;
+	case DUK_ASC_MINUS:  /* '-' */
+		if (DUK__L1() == '-') {
 			advtok = DUK__ADVTOK(2, DUK_TOK_DECREMENT);
-		} else if (y == '=') {
+		} else if (DUK__L1() == '=') {
 			advtok = DUK__ADVTOK(2, DUK_TOK_SUB_EQ);
 		} else {
 			advtok = DUK__ADVTOK(1, DUK_TOK_SUB);
 		}
-	} else if (x == '*') {
-		if (y == '=') {
+		break;
+	case DUK_ASC_STAR:  /* '*' */
+		if (DUK__L1() == '=') {
 			advtok = DUK__ADVTOK(2, DUK_TOK_MUL_EQ);
 		} else {
 			advtok = DUK__ADVTOK(1, DUK_TOK_MUL);
 		}
-	} else if (x == '%') {
-		if (y == '=') {
+		break;
+	case DUK_ASC_PERCENT:  /* '%' */
+		if (DUK__L1() == '=') {
 			advtok = DUK__ADVTOK(2, DUK_TOK_MOD_EQ);
 		} else {
 			advtok = DUK__ADVTOK(1, DUK_TOK_MOD);
 		}
-	} else if (x == '&') {
-		if (y == '&') {
+		break;
+	case DUK_ASC_AMP:  /* '&' */
+		if (DUK__L1() == '&') {
 			advtok = DUK__ADVTOK(2, DUK_TOK_LAND);
-		} else if (y == '=') {
+		} else if (DUK__L1() == '=') {
 			advtok = DUK__ADVTOK(2, DUK_TOK_BAND_EQ);
 		} else {
 			advtok = DUK__ADVTOK(1, DUK_TOK_BAND);
 		}
-	} else if (x == '|') {
-		if (y == '|') {
+		break;
+	case DUK_ASC_PIPE:  /* '|' */
+		if (DUK__L1() == '|') {
 			advtok = DUK__ADVTOK(2, DUK_TOK_LOR);
-		} else if (y == '=') {
+		} else if (DUK__L1() == '=') {
 			advtok = DUK__ADVTOK(2, DUK_TOK_BOR_EQ);
 		} else {
 			advtok = DUK__ADVTOK(1, DUK_TOK_BOR);
 		}
-	} else if (x == '^') {
-		if (y == '=') {
+		break;
+	case DUK_ASC_CARET:  /* '^' */
+		if (DUK__L1() == '=') {
 			advtok = DUK__ADVTOK(2, DUK_TOK_BXOR_EQ);
 		} else {
 			advtok = DUK__ADVTOK(1, DUK_TOK_BXOR);
 		}
-	} else if (x == '~') {
+		break;
+	case DUK_ASC_TILDE:  /* '~' */
 		advtok = DUK__ADVTOK(1, DUK_TOK_BNOT);
-	} else if (x == '?') {
+		break;
+	case DUK_ASC_QUESTION:  /* '?' */
 		advtok = DUK__ADVTOK(1, DUK_TOK_QUESTION);
-	} else if (x == ':') {
+		break;
+	case DUK_ASC_COLON:  /* ':' */
 		advtok = DUK__ADVTOK(1, DUK_TOK_COLON);
-	} else if (duk_unicode_is_line_terminator(x)) {
-		if (x == 0x000d && y == 0x000a) {
+		break;
+	case DUK_ASC_DOUBLEQUOTE:    /* '"' */
+	case DUK_ASC_SINGLEQUOTE: {  /* '\'' */
+		duk_small_int_t quote = x;  /* Note: duk_uint8_t type yields larger code */
+		duk_small_int_t adv;
+
+		DUK__INITBUFFER(lex_ctx);
+		for (;;) {
+			DUK__ADVANCECHARS(lex_ctx, 1);  /* eat opening quote on first loop */
+			x = DUK__L0();
+			if (x < 0 || duk_unicode_is_line_terminator(x)) {
+				DUK_ERROR(lex_ctx->thr, DUK_ERR_SYNTAX_ERROR,
+				          "eof or line terminator while parsing string literal");
+			}
+			if (x == quote) {
+				DUK__ADVANCECHARS(lex_ctx, 1);  /* eat closing quote */
+				break;
+			}
+			if (x == '\\') {
+				/* DUK__L0        -> '\' char
+				 * DUK__L1 ... DUK__L5 -> more lookup
+				 */
+
+				x = DUK__L1();
+
+				/* How much to advance before next loop; note that next loop
+				 * will advance by 1 anyway, so -1 from the total escape
+				 * length (e.g. len('\uXXXX') - 1 = 6 - 1).  As a default,
+				 * 1 is good.
+				 */
+				adv = 2 - 1;  /* note: long live range */
+
+				if (x < 0) {
+					DUK_ERROR(lex_ctx->thr, DUK_ERR_SYNTAX_ERROR,
+					          "eof while parsing string literal");
+				}
+				if (duk_unicode_is_line_terminator(x)) {
+					/* line continuation */
+					if (x == 0x000d && DUK__L2() == 0x000a) {
+						/* CR LF again a special case */
+						adv = 3 - 1;
+					}
+				} else if (x == '\'') {
+					DUK__APPENDBUFFER(lex_ctx, 0x0027);
+				} else if (x == '"') {
+					DUK__APPENDBUFFER(lex_ctx, 0x0022);
+				} else if (x == '\\') {
+					DUK__APPENDBUFFER(lex_ctx, 0x005c);
+				} else if (x == 'b') {
+					DUK__APPENDBUFFER(lex_ctx, 0x0008);
+				} else if (x == 'f') {
+					DUK__APPENDBUFFER(lex_ctx, 0x000c);
+				} else if (x == 'n') {
+					DUK__APPENDBUFFER(lex_ctx, 0x000a);
+				} else if (x == 'r') {
+					DUK__APPENDBUFFER(lex_ctx, 0x000d);
+				} else if (x == 't') {
+					DUK__APPENDBUFFER(lex_ctx, 0x0009);
+				} else if (x == 'v') {
+					DUK__APPENDBUFFER(lex_ctx, 0x000b);
+				} else if (x == 'x') {
+					adv = 4 - 1;
+					DUK__APPENDBUFFER(lex_ctx, duk__decode_hexesc_from_window(lex_ctx, 2));
+				} else if (x == 'u') {
+					adv = 6 - 1;
+					DUK__APPENDBUFFER(lex_ctx, duk__decode_uniesc_from_window(lex_ctx, 2));
+				} else if (DUK__ISDIGIT(x)) {
+					duk_codepoint_t ch = 0;  /* initialized to avoid warnings of unused var */
+
+					/*
+					 *  Octal escape or zero escape:
+					 *    \0                                     (lookahead not DecimalDigit)
+					 *    \1 ... \7                              (lookahead not DecimalDigit)
+					 *    \ZeroToThree OctalDigit                (lookahead not DecimalDigit)
+					 *    \FourToSeven OctalDigit                (no lookahead restrictions)
+					 *    \ZeroToThree OctalDigit OctalDigit     (no lookahead restrictions)
+					 *
+					 *  Zero escape is part of the standard syntax.  Octal escapes are
+					 *  defined in E5 Section B.1.2, and are only allowed in non-strict mode.
+					 *  Any other productions starting with a decimal digit are invalid.
+					 */
+
+					if (x == '0' && !DUK__ISDIGIT(DUK__L2())) {
+						/* Zero escape (also allowed in non-strict mode) */
+						ch = 0;
+						/* adv = 2 - 1 default OK */
+#ifdef DUK_USE_OCTAL_SUPPORT
+					} else if (strict_mode) {
+						/* No other escape beginning with a digit in strict mode */
+						DUK_ERROR(lex_ctx->thr, DUK_ERR_SYNTAX_ERROR,
+						          "invalid escape while parsing string literal");
+					} else if (DUK__ISDIGIT03(x) && DUK__ISOCTDIGIT(DUK__L2()) && DUK__ISOCTDIGIT(DUK__L3())) {
+						/* Three digit octal escape, digits validated. */
+						adv = 4 - 1;
+						ch = (duk__hexval(lex_ctx, x) << 6) +
+						     (duk__hexval(lex_ctx, DUK__L2()) << 3) +
+						     duk__hexval(lex_ctx, DUK__L3());
+					} else if (((DUK__ISDIGIT03(x) && !DUK__ISDIGIT(DUK__L3())) || DUK__ISDIGIT47(x)) &&
+					           DUK__ISOCTDIGIT(DUK__L2())) {
+						/* Two digit octal escape, digits validated.
+						 *
+						 * The if-condition is a bit tricky.  We could catch e.g.
+						 * '\039' in the three-digit escape and fail it there (by
+					         * validating the digits), but we want to avoid extra
+						 * additional validation code.
+						 */
+						adv = 3 - 1;
+						ch = (duk__hexval(lex_ctx, x) << 3) +
+						     duk__hexval(lex_ctx, DUK__L2());
+					} else if (DUK__ISDIGIT(x) && !DUK__ISDIGIT(DUK__L2())) {
+						/* One digit octal escape, digit validated. */
+						/* adv = 2 default OK */
+						ch = duk__hexval(lex_ctx, x);
+#else
+					/* fall through to error */
+#endif
+					} else {
+						DUK_ERROR(lex_ctx->thr, DUK_ERR_SYNTAX_ERROR,
+						          "invalid escape while parsing string literal");
+					}
+
+					DUK__APPENDBUFFER(lex_ctx, ch);
+				} else {
+					/* escaped NonEscapeCharacter */
+					DUK__APPENDBUFFER(lex_ctx, x);
+				}
+				DUK__ADVANCECHARS(lex_ctx, adv);
+
+				/* Track number of escapes; count not really needed but directive
+				 * prologues need to detect whether there were any escapes or line
+				 * continuations or not.
+				 */
+				out_token->num_escapes++;
+			} else {
+				/* part of string */
+				DUK__APPENDBUFFER(lex_ctx, x);
+			}
+		}
+
+		duk__internbuffer(lex_ctx, lex_ctx->slot1_idx);
+		out_token->str1 = duk_get_hstring((duk_context *) lex_ctx->thr, lex_ctx->slot1_idx);
+
+		DUK__INITBUFFER(lex_ctx);  /* free some memory */
+
+		advtok = DUK__ADVTOK(0, DUK_TOK_STRING);
+		break;
+	}
+	default:
+		goto slow_path;
+	}  /* switch */
+
+	goto skip_slow_path;
+
+ slow_path:
+	if (duk_unicode_is_line_terminator(x)) {
+		if (x == 0x000d && DUK__L1() == 0x000a) {
 			/*
 			 *  E5 Section 7.3: CR LF is detected as a single line terminator for
 			 *  line numbers.  Here we also detect it as a single line terminator
 			 *  token.
 			 */
-			advtok = DUK__ADVTOK(2, DUK_TOK_LINETERM);
+			DUK__ADVANCECHARS(lex_ctx, 2);
 		} else {
-			advtok = DUK__ADVTOK(1, DUK_TOK_LINETERM);
+			DUK__ADVANCECHARS(lex_ctx, 1);
 		}
+		got_lineterm = 1;
+		goto restart_lineupdate;
 	} else if (duk_unicode_is_identifier_start(x) || x == '\\') {
 		/*
 		 *  Parse an identifier and then check whether it is:
@@ -57651,7 +76244,7 @@ static void duk__parse_input_element_raw(duk_lexer_ctx *lex_ctx,
 					          "invalid unicode escaped character while parsing identifier");
 				}
 				DUK__APPENDBUFFER(lex_ctx, ch);
-				DUK__ADVANCE(lex_ctx, 6);
+				DUK__ADVANCECHARS(lex_ctx, 6);
 
 				/* Track number of escapes: necessary for proper keyword
 				 * detection.
@@ -57667,7 +76260,7 @@ static void duk__parse_input_element_raw(duk_lexer_ctx *lex_ctx,
 					break;
 				}
 				DUK__APPENDBUFFER(lex_ctx, DUK__L0());
-				DUK__ADVANCE(lex_ctx, 1);
+				DUK__ADVANCECHARS(lex_ctx, 1);
 			}
 			first = 0;
 		}
@@ -57678,7 +76271,7 @@ static void duk__parse_input_element_raw(duk_lexer_ctx *lex_ctx,
 		DUK_ASSERT(str != NULL);
 		out_token->t_nores = DUK_TOK_IDENTIFIER;
 
-		DUK__INITBUFFER(lex_ctx);	/* free some memory */
+		DUK__INITBUFFER(lex_ctx);  /* free some memory */
 
 		/*
 		 *  Interned identifier is compared against reserved words, which are
@@ -57706,7 +76299,7 @@ static void duk__parse_input_element_raw(duk_lexer_ctx *lex_ctx,
 		if (out_token->num_escapes == 0) {
 			for (i = DUK_STRIDX_START_RESERVED; i < i_end; i++) {
 				DUK_ASSERT(i >= 0 && i < DUK_HEAP_NUM_STRINGS);
-				if (lex_ctx->thr->strs[i] == str) {
+				if (DUK_HTHREAD_GET_STRING(lex_ctx->thr, i) == str) {
 					advtok = DUK__ADVTOK(0, DUK_STRIDX_TO_TOK(i));
 					break;
 				}
@@ -57746,12 +76339,14 @@ static void duk__parse_input_element_raw(duk_lexer_ctx *lex_ctx,
 		                         * 3=after exp and exp sign
 		                         */
 		duk_small_uint_t s2n_flags;
+		duk_codepoint_t y;
 
 		DUK__INITBUFFER(lex_ctx);
+		y = DUK__L1();
 		if (x == '0' && (y == 'x' || y == 'X')) {
 			DUK__APPENDBUFFER(lex_ctx, x);
 			DUK__APPENDBUFFER(lex_ctx, y);
-			DUK__ADVANCE(lex_ctx, 2);
+			DUK__ADVANCECHARS(lex_ctx, 2);
 			int_only = 1;
 			allow_hex = 1;
 #ifdef DUK_USE_OCTAL_SUPPORT
@@ -57762,16 +76357,16 @@ static void duk__parse_input_element_raw(duk_lexer_ctx *lex_ctx,
 			 * OctalIntegerLiteral is the only valid NumericLiteral
 			 * alternative at this point (even if y is, say, '9').
 			 */
-	
+
 			DUK__APPENDBUFFER(lex_ctx, x);
-			DUK__ADVANCE(lex_ctx, 1);
+			DUK__ADVANCECHARS(lex_ctx, 1);
 			int_only = 1;
 #endif
 		}
 
 		state = 0;
 		for (;;) {
-			x = DUK__L0();	/* re-lookup curr char on first round */
+			x = DUK__L0();  /* re-lookup curr char on first round */
 			if (DUK__ISDIGIT(x)) {
 				/* Note: intentionally allow leading zeroes here, as the
 				 * actual parser will check for them.
@@ -57804,250 +76399,67 @@ static void duk__parse_input_element_raw(duk_lexer_ctx *lex_ctx,
 				break;
 			}
 			DUK__APPENDBUFFER(lex_ctx, x);
-			DUK__ADVANCE(lex_ctx, 1);
-		}
-
-		/* XXX: better coercion */
-		duk__internbuffer(lex_ctx, lex_ctx->slot1_idx);
-
-		s2n_flags = DUK_S2N_FLAG_ALLOW_EXP |
-		            DUK_S2N_FLAG_ALLOW_FRAC |
-		            DUK_S2N_FLAG_ALLOW_NAKED_FRAC |
-		            DUK_S2N_FLAG_ALLOW_EMPTY_FRAC |
-#ifdef DUK_USE_OCTAL_SUPPORT
-		            (strict_mode ? 0 : DUK_S2N_FLAG_ALLOW_AUTO_OCT_INT) |
-#endif
-		            DUK_S2N_FLAG_ALLOW_AUTO_HEX_INT;
-
-		duk_dup((duk_context *) lex_ctx->thr, lex_ctx->slot1_idx);
-		duk_numconv_parse((duk_context *) lex_ctx->thr, 10 /*radix*/, s2n_flags);
-		val = duk_to_number((duk_context *) lex_ctx->thr, -1);
-		if (DUK_ISNAN(val)) {
-			DUK_ERROR(lex_ctx->thr, DUK_ERR_SYNTAX_ERROR, "invalid numeric literal");
-		}
-		duk_replace((duk_context *) lex_ctx->thr, lex_ctx->slot1_idx);  /* could also just pop? */
-
-		DUK__INITBUFFER(lex_ctx);	/* free some memory */
-
-		/* Section 7.8.3 (note): NumericLiteral must be followed by something other than
-		 * IdentifierStart or DecimalDigit.
-		 */
-
-		if (DUK__ISDIGIT(DUK__L0()) || duk_unicode_is_identifier_start(DUK__L0())) {
-			DUK_ERROR(lex_ctx->thr, DUK_ERR_SYNTAX_ERROR, "invalid numeric literal");
-		}
-
-		out_token->num = val;
-		advtok = DUK__ADVTOK(0, DUK_TOK_NUMBER);
-	} else if (x == '"' || x == '\'') {
-		duk_small_int_t quote = x;    /* Note: duk_uint8_t type yields larger code */
-		duk_small_int_t adv;
-
-		DUK__INITBUFFER(lex_ctx);
-		for (;;) {
-			DUK__ADVANCE(lex_ctx, 1);	/* eat opening quote on first loop */
-			x = DUK__L0();
-			if (x < 0 || duk_unicode_is_line_terminator(x)) {
-				DUK_ERROR(lex_ctx->thr, DUK_ERR_SYNTAX_ERROR,
-				          "eof or line terminator while parsing string literal");
-			}
-			if (x == quote) {
-				DUK__ADVANCE(lex_ctx, 1);	/* eat closing quote */
-				break;
-			}
-			if (x == '\\') {
-				/* DUK__L0        -> '\' char
-				 * DUK__L1 ... DUK__L5 -> more lookup
-				 */
-
-				x = DUK__L1();
-				y = DUK__L2();
-
-				/* How much to advance before next loop; note that next loop
-				 * will advance by 1 anyway, so -1 from the total escape
-				 * length (e.g. len('\uXXXX') - 1 = 6 - 1).  As a default,
-				 * 1 is good.
-				 */
-				adv = 2 - 1;	/* note: long live range */
-
-				if (x < 0) {
-					DUK_ERROR(lex_ctx->thr, DUK_ERR_SYNTAX_ERROR,
-					          "eof while parsing string literal");
-				}
-				if (duk_unicode_is_line_terminator(x)) {
-					/* line continuation */
-					if (x == 0x000d && y == 0x000a) {
-						/* CR LF again a special case */
-						adv = 3 - 1;
-					}
-				} else if (x == '\'') {
-					DUK__APPENDBUFFER(lex_ctx, 0x0027);
-				} else if (x == '"') {
-					DUK__APPENDBUFFER(lex_ctx, 0x0022);
-				} else if (x == '\\') {
-					DUK__APPENDBUFFER(lex_ctx, 0x005c);
-				} else if (x == 'b') {
-					DUK__APPENDBUFFER(lex_ctx, 0x0008);
-				} else if (x == 'f') {
-					DUK__APPENDBUFFER(lex_ctx, 0x000c);
-				} else if (x == 'n') {
-					DUK__APPENDBUFFER(lex_ctx, 0x000a);
-				} else if (x == 'r') {
-					DUK__APPENDBUFFER(lex_ctx, 0x000d);
-				} else if (x == 't') {
-					DUK__APPENDBUFFER(lex_ctx, 0x0009);
-				} else if (x == 'v') {
-					DUK__APPENDBUFFER(lex_ctx, 0x000b);
-				} else if (x == 'x') {
-					adv = 4 - 1;
-					DUK__APPENDBUFFER(lex_ctx, duk__decode_hexesc_from_window(lex_ctx, 2));
-				} else if (x == 'u') {
-					adv = 6 - 1;
-					DUK__APPENDBUFFER(lex_ctx, duk__decode_uniesc_from_window(lex_ctx, 2));
-				} else if (DUK__ISDIGIT(x)) {
-					duk_codepoint_t ch = 0;  /* initialized to avoid warnings of unused var */
-
-					/*
-					 *  Octal escape or zero escape:
-					 *    \0                                     (lookahead not DecimalDigit)
-					 *    \1 ... \7                              (lookahead not DecimalDigit)
-					 *    \ZeroToThree OctalDigit                (lookahead not DecimalDigit)
-					 *    \FourToSeven OctalDigit                (no lookahead restrictions)
-					 *    \ZeroToThree OctalDigit OctalDigit     (no lookahead restrictions)
-					 *
-					 *  Zero escape is part of the standard syntax.  Octal escapes are
-					 *  defined in E5 Section B.1.2, and are only allowed in non-strict mode.
-					 *  Any other productions starting with a decimal digit are invalid.
-					 */
-
-					if (x == '0' && !DUK__ISDIGIT(y)) {
-						/* Zero escape (also allowed in non-strict mode) */
-						ch = 0;
-						/* adv = 2 - 1 default OK */
-#ifdef DUK_USE_OCTAL_SUPPORT
-					} else if (strict_mode) {
-						/* No other escape beginning with a digit in strict mode */
-						DUK_ERROR(lex_ctx->thr, DUK_ERR_SYNTAX_ERROR,
-						          "invalid escape while parsing string literal");
-					} else if (DUK__ISDIGIT03(x) && DUK__ISOCTDIGIT(y) && DUK__ISOCTDIGIT(DUK__L3())) {
-						/* Three digit octal escape, digits validated. */
-						adv = 4 - 1;
-						ch = (duk__hexval(lex_ctx, x) << 6) +
-						     (duk__hexval(lex_ctx, y) << 3) +
-						     duk__hexval(lex_ctx, DUK__L3());
-					} else if (((DUK__ISDIGIT03(x) && !DUK__ISDIGIT(DUK__L3())) || DUK__ISDIGIT47(x)) &&
-					           DUK__ISOCTDIGIT(y)) {
-						/* Two digit octal escape, digits validated.
-						 * 
-						 * The if-condition is a bit tricky.  We could catch e.g.
-						 * '\039' in the three-digit escape and fail it there (by
-					         * validating the digits), but we want to avoid extra
-						 * additional validation code.
-						 */
-						adv = 3 - 1;
-						ch = (duk__hexval(lex_ctx, x) << 3) +
-						     duk__hexval(lex_ctx, y);
-					} else if (DUK__ISDIGIT(x) && !DUK__ISDIGIT(y)) {
-						/* One digit octal escape, digit validated. */
-						/* adv = 2 default OK */
-						ch = duk__hexval(lex_ctx, x);
-#else
-					/* fall through to error */
-#endif
-					} else {
-						DUK_ERROR(lex_ctx->thr, DUK_ERR_SYNTAX_ERROR,
-						          "invalid escape while parsing string literal");
-					}
-
-					DUK__APPENDBUFFER(lex_ctx, ch);
-				} else {
-					/* escaped NonEscapeCharacter */
-					DUK__APPENDBUFFER(lex_ctx, x);
-				}
-				DUK__ADVANCE(lex_ctx, adv);
-
-				/* Track number of escapes; count not really needed but directive
-				 * prologues need to detect whether there were any escapes or line
-				 * continuations or not.
-				 */
-				out_token->num_escapes++;
-			} else {
-				/* part of string */
-				DUK__APPENDBUFFER(lex_ctx, x);
-			}
+			DUK__ADVANCECHARS(lex_ctx, 1);
 		}
 
+		/* XXX: better coercion */
 		duk__internbuffer(lex_ctx, lex_ctx->slot1_idx);
-		out_token->str1 = duk_get_hstring((duk_context *) lex_ctx->thr, lex_ctx->slot1_idx);
 
-		DUK__INITBUFFER(lex_ctx);	/* free some memory */
+		s2n_flags = DUK_S2N_FLAG_ALLOW_EXP |
+		            DUK_S2N_FLAG_ALLOW_FRAC |
+		            DUK_S2N_FLAG_ALLOW_NAKED_FRAC |
+		            DUK_S2N_FLAG_ALLOW_EMPTY_FRAC |
+#ifdef DUK_USE_OCTAL_SUPPORT
+		            (strict_mode ? 0 : DUK_S2N_FLAG_ALLOW_AUTO_OCT_INT) |
+#endif
+		            DUK_S2N_FLAG_ALLOW_AUTO_HEX_INT;
 
-		advtok = DUK__ADVTOK(0, DUK_TOK_STRING);
+		duk_dup((duk_context *) lex_ctx->thr, lex_ctx->slot1_idx);
+		duk_numconv_parse((duk_context *) lex_ctx->thr, 10 /*radix*/, s2n_flags);
+		val = duk_to_number((duk_context *) lex_ctx->thr, -1);
+		if (DUK_ISNAN(val)) {
+			DUK_ERROR(lex_ctx->thr, DUK_ERR_SYNTAX_ERROR, "invalid numeric literal");
+		}
+		duk_replace((duk_context *) lex_ctx->thr, lex_ctx->slot1_idx);  /* could also just pop? */
+
+		DUK__INITBUFFER(lex_ctx);  /* free some memory */
+
+		/* Section 7.8.3 (note): NumericLiteral must be followed by something other than
+		 * IdentifierStart or DecimalDigit.
+		 */
+
+		if (DUK__ISDIGIT(DUK__L0()) || duk_unicode_is_identifier_start(DUK__L0())) {
+			DUK_ERROR(lex_ctx->thr, DUK_ERR_SYNTAX_ERROR, "invalid numeric literal");
+		}
+
+		out_token->num = val;
+		advtok = DUK__ADVTOK(0, DUK_TOK_NUMBER);
+	} else if (duk_unicode_is_whitespace(DUK__LOOKUP(lex_ctx, 0))) {
+		DUK__ADVANCECHARS(lex_ctx, 1);
+		goto restart;
 	} else if (x < 0) {
 		advtok = DUK__ADVTOK(0, DUK_TOK_EOF);
 	} else {
 		DUK_ERROR(lex_ctx->thr, DUK_ERR_SYNTAX_ERROR, "error parsing token");
 	}
+ skip_slow_path:
 
 	/*
 	 *  Shared exit path
 	 */
 
-	DUK__ADVANCE(lex_ctx, advtok >> 8);
+	DUK__ADVANCEBYTES(lex_ctx, advtok >> 8);
 	out_token->t = advtok & 0xff;
 	if (out_token->t_nores < 0) {
 		out_token->t_nores = out_token->t;
 	}
-	out_token->end_line = lex_ctx->lines[0];
-}
-
-/*
- *  Tokenize input until a non-whitespace, non-lineterm token is found.
- *  Note in the output token whether a lineterm token preceded the starting
- *  point (inclusive) and the result token.  This information is needed for
- *  automatic semicolon insertion.
- *
- *  Future work:
- *
- *    * Merge with duk__parse_input_element_raw() because only this function is
- *      called in practice.
- */
-
-/* XXX: change mode flags into one flags argument? */
-
-void duk_lexer_parse_js_input_element(duk_lexer_ctx *lex_ctx,
-                                      duk_token *out_token,
-                                      duk_bool_t strict_mode,
-                                      duk_bool_t regexp_mode) {
-	duk_small_int_t tok;
-	duk_bool_t got_lineterm = 0;  /* got lineterm preceding non-whitespace, non-lineterm token */
-
-	for (;;) {
-		duk__parse_input_element_raw(lex_ctx, out_token, strict_mode, regexp_mode);
-		tok = out_token->t;
-
-		DUK_DDD(DUK_DDDPRINT("RAWTOKEN: %ld (line %ld-%ld)",
-		                     (long) tok, (long) out_token->start_line, (long) out_token->end_line));
-
-		if (tok == DUK_TOK_COMMENT) {
-			/* single-line comment or multi-line comment without an internal lineterm */
-			continue;
-		} else if (tok == DUK_TOK_LINETERM) {
-			/* lineterm or multi-line comment with an internal lineterm */
-			got_lineterm = 1;
-			continue;
-		} else {
-			break;
-		}
-	}
-
 	out_token->lineterm = got_lineterm;
 
 	/* Automatic semicolon insertion is allowed if a token is preceded
 	 * by line terminator(s), or terminates a statement list (right curly
 	 * or EOF).
 	 */
-	if (got_lineterm || tok == DUK_TOK_RCURLY || tok == DUK_TOK_EOF) {
+	if (got_lineterm || out_token->t == DUK_TOK_RCURLY || out_token->t == DUK_TOK_EOF) {
 		out_token->allow_auto_semi = 1;
 	} else {
 		out_token->allow_auto_semi = 0;
@@ -58065,7 +76477,7 @@ void duk_lexer_parse_js_input_element(duk_lexer_ctx *lex_ctx,
  *  will be accepted for a quantifier.
  */
 
-void duk_lexer_parse_re_token(duk_lexer_ctx *lex_ctx, duk_re_token *out_token) {
+DUK_INTERNAL void duk_lexer_parse_re_token(duk_lexer_ctx *lex_ctx, duk_re_token *out_token) {
 	duk_small_int_t advtok = 0;  /* init is unnecessary but suppresses "may be used uninitialized" warnings */
 	duk_codepoint_t x, y;
 
@@ -58096,7 +76508,7 @@ void duk_lexer_parse_re_token(duk_lexer_ctx *lex_ctx, duk_re_token *out_token) {
 	}
 	case '?': {
 		out_token->qmin = 0;
-		out_token->qmax = 1;	
+		out_token->qmax = 1;
 		if (y == '?') {
 			advtok = DUK__ADVTOK(2, DUK_RETOK_QUANTIFIER);
 			out_token->greedy = 0;
@@ -58136,7 +76548,7 @@ void duk_lexer_parse_re_token(duk_lexer_ctx *lex_ctx, duk_re_token *out_token) {
 		duk_uint_fast32_t val2 = DUK_RE_QUANTIFIER_INFINITE;
 		duk_small_int_t digits = 0;
 		for (;;) {
-			DUK__ADVANCE(lex_ctx, 1);	/* eat '{' on entry */
+			DUK__ADVANCECHARS(lex_ctx, 1);  /* eat '{' on entry */
 			x = DUK__L0();
 			if (DUK__ISDIGIT(x)) {
 				if (digits >= DUK__MAX_RE_QUANT_DIGITS) {
@@ -58158,12 +76570,12 @@ void duk_lexer_parse_re_token(duk_lexer_ctx *lex_ctx, duk_re_token *out_token) {
 					}
 					out_token->qmin = val1;
 					out_token->qmax = DUK_RE_QUANTIFIER_INFINITE;
-					DUK__ADVANCE(lex_ctx, 2);
+					DUK__ADVANCECHARS(lex_ctx, 2);
 					break;
 				}
 				val2 = val1;
 				val1 = 0;
-				digits = 0;	/* not strictly necessary because of lookahead '}' above */
+				digits = 0;  /* not strictly necessary because of lookahead '}' above */
 			} else if (x == '}') {
 				if (digits == 0) {
 					DUK_ERROR(lex_ctx->thr, DUK_ERR_SYNTAX_ERROR,
@@ -58178,7 +76590,7 @@ void duk_lexer_parse_re_token(duk_lexer_ctx *lex_ctx, duk_re_token *out_token) {
 					out_token->qmin = val1;
 					out_token->qmax = val1;
 				}
-				DUK__ADVANCE(lex_ctx, 1);
+				DUK__ADVANCECHARS(lex_ctx, 1);
 				break;
 			} else {
 				DUK_ERROR(lex_ctx->thr, DUK_ERR_SYNTAX_ERROR,
@@ -58187,7 +76599,7 @@ void duk_lexer_parse_re_token(duk_lexer_ctx *lex_ctx, duk_re_token *out_token) {
 		}
 		if (DUK__L0() == '?') {
 			out_token->greedy = 0;
-			DUK__ADVANCE(lex_ctx, 1);
+			DUK__ADVANCECHARS(lex_ctx, 1);
 		} else {
 			out_token->greedy = 1;
 		}
@@ -58207,7 +76619,7 @@ void duk_lexer_parse_re_token(duk_lexer_ctx *lex_ctx, duk_re_token *out_token) {
 		 * See: test-regexp-identity-escape-dollar.js.
 		 */
 
-		advtok = DUK__ADVTOK(2, DUK_RETOK_ATOM_CHAR);	/* default: char escape (two chars) */
+		advtok = DUK__ADVTOK(2, DUK_RETOK_ATOM_CHAR);  /* default: char escape (two chars) */
 		if (y == 'b') {
 			advtok = DUK__ADVTOK(2, DUK_RETOK_ASSERT_WORD_BOUNDARY);
 		} else if (y == 'B') {
@@ -58268,7 +76680,7 @@ void duk_lexer_parse_re_token(duk_lexer_ctx *lex_ctx, duk_re_token *out_token) {
 						DUK_ERROR(lex_ctx->thr, DUK_ERR_SYNTAX_ERROR,
 						          "invalid regexp escape (decimal escape too long)");
 					}
-					DUK__ADVANCE(lex_ctx, 1);	/* eat backslash on entry */
+					DUK__ADVANCECHARS(lex_ctx, 1);  /* eat backslash on entry */
 					x = DUK__L0();
 					if (!DUK__ISDIGIT(x)) {
 						break;
@@ -58287,6102 +76699,5255 @@ void duk_lexer_parse_re_token(duk_lexer_ctx *lex_ctx, duk_re_token *out_token) {
 		           y == DUK_UNICODE_CP_ZWJ) {
 			/* IdentityEscape, with dollar added as a valid additional
 			 * non-standard escape (see test-regexp-identity-escape-dollar.js).
-			 * Careful not to match end-of-buffer (<0) here.
-			 */
-			out_token->num = y;
-		} else {
-			DUK_ERROR(lex_ctx->thr, DUK_ERR_SYNTAX_ERROR,
-			          "invalid regexp escape");
-		}
-		break;
-	}
-	case '(': {
-		/* XXX: naming is inconsistent: ATOM_END_GROUP ends an ASSERT_START_LOOKAHEAD */
-
-		if (y == '?') {
-			if (DUK__L2() == '=') {
-				/* (?= */
-				advtok = DUK__ADVTOK(3, DUK_RETOK_ASSERT_START_POS_LOOKAHEAD);
-			} else if (DUK__L2() == '!') {
-				/* (?! */
-				advtok = DUK__ADVTOK(3, DUK_RETOK_ASSERT_START_NEG_LOOKAHEAD);
-			} else if (DUK__L2() == ':') {
-				/* (?: */
-				advtok = DUK__ADVTOK(3, DUK_RETOK_ATOM_START_NONCAPTURE_GROUP);
-			}
-		} else {
-			/* ( */
-			advtok = DUK__ADVTOK(1, DUK_RETOK_ATOM_START_CAPTURE_GROUP);
-		}
-		break;
-	}
-	case ')': {
-		advtok = DUK__ADVTOK(1, DUK_RETOK_ATOM_END_GROUP);
-		break;
-	}
-	case '[': {
-		/*
-		 *  To avoid creating a heavy intermediate value for the list of ranges,
-		 *  only the start token ('[' or '[^') is parsed here.  The regexp
-		 *  compiler parses the ranges itself.
-		 */
-		advtok = DUK__ADVTOK(1, DUK_RETOK_ATOM_START_CHARCLASS);
-		if (y == '^') {
-			advtok = DUK__ADVTOK(2, DUK_RETOK_ATOM_START_CHARCLASS_INVERTED);
-		}
-		break;
-	}
-	case ']':
-	case '}': {
-		/* Although these could be parsed as PatternCharacters unambiguously (here),
-		 * E5 Section 15.10.1 grammar explicitly forbids these as PatternCharacters.
-		 */
-		DUK_ERROR(lex_ctx->thr, DUK_ERR_SYNTAX_ERROR,
-		          "invalid regexp character");
-		break;
-	}
-	case -1: {
-		/* EOF */
-		advtok = DUK__ADVTOK(0, DUK_TOK_EOF);
-		break;
-	}
-	default: {
-		/* PatternCharacter, all excluded characters are matched by cases above */
-		advtok = DUK__ADVTOK(1, DUK_RETOK_ATOM_CHAR);
-		out_token->num = x;
-		break;
-	}
-	}
-
-	/*
-	 *  Shared exit path
-	 */
-
-	DUK__ADVANCE(lex_ctx, advtok >> 8);
-	out_token->t = advtok & 0xff;
-}
-
-/*
- *  Special parser for character classes; calls callback for every
- *  range parsed and returns the number of ranges present.
- */
-
-/* XXX: this duplicates functionality in duk_regexp.c where a similar loop is
- * required anyway.  We could use that BUT we need to update the regexp compiler
- * 'nranges' too.  Work this out a bit more cleanly to save space.
- */
-
-/* XXX: the handling of character range detection is a bit convoluted.
- * Try to simplify and make smaller.
- */
-
-/* XXX: logic for handling character ranges is now incorrect, it will accept
- * e.g. [\d-z] whereas it should croak from it?  SMJS accepts this too, though.
- *
- * Needs a read through and a lot of additional tests.
- */
-
-static void duk__emit_u16_direct_ranges(duk_lexer_ctx *lex_ctx,
-                                        duk_re_range_callback gen_range,
-                                        void *userdata,
-                                        duk_uint16_t *ranges,
-                                        int num) {
-	duk_uint16_t *ranges_end;
-
-	DUK_UNREF(lex_ctx);
-
-	ranges_end = ranges + num;
-	while (ranges < ranges_end) {
-		/* mark range 'direct', bypass canonicalization (see Wiki) */
-		gen_range(userdata, (duk_codepoint_t) ranges[0], (duk_codepoint_t) ranges[1], 1);
-		ranges += 2;
-	}
-}
-
-void duk_lexer_parse_re_ranges(duk_lexer_ctx *lex_ctx, duk_re_range_callback gen_range, void *userdata) {
-	duk_codepoint_t start = -1;
-	duk_codepoint_t ch;
-	duk_codepoint_t x;
-	duk_bool_t dash = 0;
-
-	DUK_DD(DUK_DDPRINT("parsing regexp ranges"));
-
-	for (;;) {
-		x = DUK__L0();
-		DUK__ADVANCE(lex_ctx, 1);
-
-		ch = -1;  /* not strictly necessary, but avoids "uninitialized variable" warnings */
-		DUK_UNREF(ch);
-
-		if (x < 0) {
-			DUK_ERROR(lex_ctx->thr, DUK_ERR_SYNTAX_ERROR,
-			          "eof while parsing character class");
-		} else if (x == ']') {
-			DUK_ASSERT(!dash);	/* lookup should prevent this */
-			if (start >= 0) {
-				gen_range(userdata, start, start, 0);
-			}
-			break;
-		} else if (x == '-') {
-			if (start >= 0 && !dash && DUK__L0() != ']') {
-				/* '-' as a range indicator */
-				dash = 1;
-				continue;
-			} else {
-				/* '-' verbatim */
-				ch = x;
-			}
-		} else if (x == '\\') {
-			/*
-			 *  The escapes are same as outside a character class, except that \b has a
-			 *  different meaning, and \B and backreferences are prohibited (see E5
-			 *  Section 15.10.2.19).  However, it's difficult to share code because we
-			 *  handle e.g. "\n" very differently: here we generate a single character
-			 *  range for it.
-			 */
-
-			x = DUK__L0();
-			DUK__ADVANCE(lex_ctx, 1);
-
-			if (x == 'b') {
-				/* Note: '\b' in char class is different than outside (assertion),
-				 * '\B' is not allowed and is caught by the duk_unicode_is_identifier_part()
-				 * check below.
-				 */
-				ch = 0x0008;
-			} else if (x == 'f') {
-				ch = 0x000c;
-			} else if (x == 'n') {
-				ch = 0x000a;
-			} else if (x == 't') {
-				ch = 0x0009;
-			} else if (x == 'r') {
-				ch = 0x000d;
-			} else if (x == 'v') {
-				ch = 0x000b;
-			} else if (x == 'c') {
-				x = DUK__L0();
-				DUK__ADVANCE(lex_ctx, 1);
-				if ((x >= 'a' && x <= 'z') ||
-				    (x >= 'A' && x <= 'Z')) {
-					ch = (x % 32);
-				} else {
-					DUK_ERROR(lex_ctx->thr, DUK_ERR_SYNTAX_ERROR,
-					          "invalid regexp control escape");
-					return;  /* never reached, but avoids warnings of
-					          * potentially unused variables.
-					          */
-				}
-			} else if (x == 'x') {
-				ch = duk__decode_hexesc_from_window(lex_ctx, 0);
-				DUK__ADVANCE(lex_ctx, 2);
-			} else if (x == 'u') {
-				ch = duk__decode_uniesc_from_window(lex_ctx, 0);
-				DUK__ADVANCE(lex_ctx, 4);
-			} else if (x == 'd') {
-				duk__emit_u16_direct_ranges(lex_ctx,
-				                            gen_range,
-				                            userdata,
-				                            duk_unicode_re_ranges_digit,
-				                            sizeof(duk_unicode_re_ranges_digit) / sizeof(duk_uint16_t));
-				ch = -1;
-			} else if (x == 'D') {
-				duk__emit_u16_direct_ranges(lex_ctx,
-				                            gen_range,
-				                            userdata,
-				                            duk_unicode_re_ranges_not_digit,
-				                            sizeof(duk_unicode_re_ranges_not_digit) / sizeof(duk_uint16_t));
-				ch = -1;
-			} else if (x == 's') {
-				duk__emit_u16_direct_ranges(lex_ctx,
-				                            gen_range,
-				                            userdata,
-				                            duk_unicode_re_ranges_white,
-				                            sizeof(duk_unicode_re_ranges_white) / sizeof(duk_uint16_t));
-				ch = -1;
-			} else if (x == 'S') {
-				duk__emit_u16_direct_ranges(lex_ctx,
-				                            gen_range,
-				                            userdata,
-				                            duk_unicode_re_ranges_not_white,
-				                            sizeof(duk_unicode_re_ranges_not_white) / sizeof(duk_uint16_t));
-				ch = -1;
-			} else if (x == 'w') {
-				duk__emit_u16_direct_ranges(lex_ctx,
-				                            gen_range,
-				                            userdata,
-				                            duk_unicode_re_ranges_wordchar,
-				                            sizeof(duk_unicode_re_ranges_wordchar) / sizeof(duk_uint16_t));
-				ch = -1;
-			} else if (x == 'W') {
-				duk__emit_u16_direct_ranges(lex_ctx,
-				                            gen_range,
-				                            userdata,
-				                            duk_unicode_re_ranges_not_wordchar,
-				                            sizeof(duk_unicode_re_ranges_not_wordchar) / sizeof(duk_uint16_t));
-				ch = -1;
-			} else if (DUK__ISDIGIT(x)) {
-				/* DecimalEscape, only \0 is allowed, no leading zeroes are allowed */
-				if (x == 0 && !DUK__ISDIGIT(DUK__L0())) {
-					ch = 0x0000;
-				} else {
-					DUK_ERROR(lex_ctx->thr, DUK_ERR_SYNTAX_ERROR,
-					          "invalid decimal escape");
-				}
-			} else if (!duk_unicode_is_identifier_part(x)
-#if defined(DUK_USE_NONSTD_REGEXP_DOLLAR_ESCAPE)
-			           || x == '$'
-#endif
-			          ) {
-				/* IdentityEscape */
-				ch = x;
-			} else {
-				DUK_ERROR(lex_ctx->thr, DUK_ERR_SYNTAX_ERROR,
-				          "invalid regexp escape");
-			}
-		} else {
-			/* character represents itself */
-			ch = x;
-		}
-
-		/* ch is a literal character here or -1 if parsed entity was
-		 * an escape such as "\s".
-		 */
-
-		if (ch < 0) {
-			/* multi-character sets not allowed as part of ranges, see
-			 * E5 Section 15.10.2.15, abstract operation CharacterRange.
-			 */
-			if (start >= 0) {
-				if (dash) {
-					DUK_ERROR(lex_ctx->thr, DUK_ERR_SYNTAX_ERROR,
-					          "invalid range");
-				} else {
-					gen_range(userdata, start, start, 0);
-					start = -1;
-					/* dash is already 0 */
-				}
-			}
-		} else {
-			if (start >= 0) {
-				if (dash) {
-					if (start > ch) {
-						DUK_ERROR(lex_ctx->thr, DUK_ERR_SYNTAX_ERROR,
-						          "invalid range");
-					}
-					gen_range(userdata, start, ch, 0);
-					start = -1;
-					dash = 0;
-				} else {
-					gen_range(userdata, start, start, 0);
-					start = ch;
-					/* dash is already 0 */
-				}
-			} else {
-				start = ch;
-			}
-		}
-	}
-
-	return;
-}
-
-#endif  /* DUK_USE_REGEXP_SUPPORT */
-#line 1 "duk_numconv.c"
-/*
- *  Number-to-string and string-to-number conversions.
- *
- *  Slow path number-to-string and string-to-number conversion is based on
- *  a Dragon4 variant, with fast paths for small integers.  Big integer
- *  arithmetic is needed for guaranteeing that the conversion is correct
- *  and uses a minimum number of digits.  The big number arithmetic has a
- *  fixed maximum size and does not require dynamic allocations.
- *
- *  See: doc/number-conversion.txt.
- */
-
-/* include removed: duk_internal.h */
-
-#define DUK__IEEE_DOUBLE_EXP_BIAS  1023
-#define DUK__IEEE_DOUBLE_EXP_MIN   (-1022)   /* biased exp == 0 -> denormal, exp -1022 */
-
-#define DUK__DIGITCHAR(x)  duk_lc_digits[(x)]
-
-/*
- *  Tables generated with src/gennumdigits.py.
- *
- *  duk__str2num_digits_for_radix indicates, for each radix, how many input
- *  digits should be considered significant for string-to-number conversion.
- *  The input is also padded to this many digits to give the Dragon4
- *  conversion enough (apparent) precision to work with.
- *
- *  duk__str2num_exp_limits indicates, for each radix, the radix-specific
- *  minimum/maximum exponent values (for a Dragon4 integer mantissa)
- *  below and above which the number is guaranteed to underflow to zero
- *  or overflow to Infinity.  This allows parsing to keep bigint values
- *  bounded.
- */
-
-static const duk_uint8_t duk__str2num_digits_for_radix[] = {
-	69, 44, 35, 30, 27, 25, 23, 22, 20, 20,    /* 2 to 11 */
-	20, 19, 19, 18, 18, 17, 17, 17, 16, 16,    /* 12 to 21 */
-	16, 16, 16, 15, 15, 15, 15, 15, 15, 14,    /* 22 to 31 */
-	14, 14, 14, 14, 14                         /* 31 to 36 */
-};
-
-typedef struct {
-	duk_int16_t upper;
-	duk_int16_t lower;
-} duk__exp_limits;
-
-static const duk__exp_limits duk__str2num_exp_limits[] = {
-	{ 957, -1147 }, { 605, -725 },  { 479, -575 },  { 414, -496 },
-	{ 372, -446 },  { 342, -411 },  { 321, -384 },  { 304, -364 },
-	{ 291, -346 },  { 279, -334 },  { 268, -323 },  { 260, -312 },
-	{ 252, -304 },  { 247, -296 },  { 240, -289 },  { 236, -283 },
-	{ 231, -278 },  { 227, -273 },  { 223, -267 },  { 220, -263 },
-	{ 216, -260 },  { 213, -256 },  { 210, -253 },  { 208, -249 },
-	{ 205, -246 },  { 203, -244 },  { 201, -241 },  { 198, -239 },
-	{ 196, -237 },  { 195, -234 },  { 193, -232 },  { 191, -230 },
-	{ 190, -228 },  { 188, -226 },  { 187, -225 },
-};
-
-/*
- *  Limited functionality bigint implementation.
- *
- *  Restricted to non-negative numbers with less than 32 * DUK__BI_MAX_PARTS bits,
- *  with the caller responsible for ensuring this is never exceeded.  No memory
- *  allocation (except stack) is needed for bigint computation.  Operations
- *  have been tailored for number conversion needs.
- *
- *  Argument order is "assignment order", i.e. target first, then arguments:
- *  x <- y * z  -->  duk__bi_mul(x, y, z);
- */
-
-/* This upper value has been experimentally determined; debug build will check
- * bigint size with assertions.
- */
-#define DUK__BI_MAX_PARTS  37  /* 37x32 = 1184 bits */
-
-#ifdef DUK_USE_DDDPRINT
-#define DUK__BI_PRINT(name,x)  duk__bi_print((name),(x))
-#else
-#define DUK__BI_PRINT(name,x)
-#endif
-
-/* Current size is about 152 bytes. */
-typedef struct {
-	duk_small_int_t n;
-	duk_uint32_t v[DUK__BI_MAX_PARTS];  /* low to high */
-} duk__bigint;
-
-#ifdef DUK_USE_DDDPRINT
-static void duk__bi_print(const char *name, duk__bigint *x) {
-	/* Overestimate required size; debug code so not critical to be tight. */
-	char buf[DUK__BI_MAX_PARTS * 9 + 64];
-	char *p = buf;
-	duk_small_int_t i;
-
-	/* No NUL term checks in this debug code. */
-	p += DUK_SPRINTF(p, "%p n=%ld", (void *) x, (long) x->n);
-	if (x->n == 0) {
-		p += DUK_SPRINTF(p, " 0");
-	}
-	for (i = x->n - 1; i >= 0; i--) {
-		p += DUK_SPRINTF(p, " %08lx", (unsigned long) x->v[i]);
-	}
-
-	DUK_DDD(DUK_DDDPRINT("%s: %s", (const char *) name, (const char *) buf));
-}
-#endif
-
-#ifdef DUK_USE_ASSERTIONS
-static duk_small_int_t duk__bi_is_valid(duk__bigint *x) {
-	return (duk_small_int_t) 
-	       ( ((x->n >= 0) && (x->n <= DUK__BI_MAX_PARTS)) /* is valid size */ &&
-	         ((x->n == 0) || (x->v[x->n - 1] != 0)) /* is normalized */ );
-}
-#endif
-
-static void duk__bi_normalize(duk__bigint *x) {
-	duk_small_int_t i;
-
-	for (i = x->n - 1; i >= 0; i--) {
-		if (x->v[i] != 0) {
-			break;
-		}
-	}
-
-	/* Note: if 'x' is zero, x->n becomes 0 here */
-	x->n = i + 1;
-	DUK_ASSERT(duk__bi_is_valid(x));
-}
-
-/* x <- y */
-static void duk__bi_copy(duk__bigint *x, duk__bigint *y) {
-	duk_small_int_t n;
-
-	n = y->n;
-	x->n = n;
-	if (n == 0) {
-		return;
-	}
-	DUK_MEMCPY((void *) x->v, (void *) y->v, (size_t) (sizeof(duk_uint32_t) * n));
-}
-
-static void duk__bi_set_small(duk__bigint *x, duk_uint32_t v) {
-	if (v == 0U) {
-		x->n = 0;
-	} else {
-		x->n = 1;
-		x->v[0] = v;
-	}
-	DUK_ASSERT(duk__bi_is_valid(x));
-}
-
-/* Return value: <0  <=>  x < y
- *                0  <=>  x == y
- *               >0  <=>  x > y
- */
-static int duk__bi_compare(duk__bigint *x, duk__bigint *y) {
-	duk_small_int_t i, nx, ny;
-	duk_uint32_t tx, ty;
-
-	DUK_ASSERT(duk__bi_is_valid(x));
-	DUK_ASSERT(duk__bi_is_valid(y));
-
-	nx = x->n;
-	ny = y->n;
-	if (nx > ny) {
-		goto ret_gt;
-	}
-	if (nx < ny) {
-		goto ret_lt;
-	}
-	for (i = nx - 1; i >= 0; i--) {
-		tx = x->v[i];
-		ty = y->v[i];
-
-		if (tx > ty) {
-			goto ret_gt;
-		}
-		if (tx < ty) {
-			goto ret_lt;
+			 * Careful not to match end-of-buffer (<0) here.
+			 */
+			out_token->num = y;
+		} else {
+			DUK_ERROR(lex_ctx->thr, DUK_ERR_SYNTAX_ERROR,
+			          "invalid regexp escape");
 		}
+		break;
 	}
+	case '(': {
+		/* XXX: naming is inconsistent: ATOM_END_GROUP ends an ASSERT_START_LOOKAHEAD */
 
-	return 0;
-
- ret_gt:
-	return 1;
-
- ret_lt:
-	return -1;
-}
-
-/* x <- y + z */
-#ifdef DUK_USE_64BIT_OPS
-static void duk__bi_add(duk__bigint *x, duk__bigint *y, duk__bigint *z) {
-	duk_uint64_t tmp;
-	duk_small_int_t i, ny, nz;
-
-	DUK_ASSERT(duk__bi_is_valid(y));
-	DUK_ASSERT(duk__bi_is_valid(z));
-
-	if (z->n > y->n) {
-		duk__bigint *t;
-		t = y; y = z; z = t;
-	}
-	DUK_ASSERT(y->n >= z->n);
-
-	ny = y->n; nz = z->n;
-	tmp = 0U;
-	for (i = 0; i < ny; i++) {
-		DUK_ASSERT(i < DUK__BI_MAX_PARTS);
-		tmp += y->v[i];
-		if (i < nz) {
-			tmp += z->v[i];
+		if (y == '?') {
+			if (DUK__L2() == '=') {
+				/* (?= */
+				advtok = DUK__ADVTOK(3, DUK_RETOK_ASSERT_START_POS_LOOKAHEAD);
+			} else if (DUK__L2() == '!') {
+				/* (?! */
+				advtok = DUK__ADVTOK(3, DUK_RETOK_ASSERT_START_NEG_LOOKAHEAD);
+			} else if (DUK__L2() == ':') {
+				/* (?: */
+				advtok = DUK__ADVTOK(3, DUK_RETOK_ATOM_START_NONCAPTURE_GROUP);
+			}
+		} else {
+			/* ( */
+			advtok = DUK__ADVTOK(1, DUK_RETOK_ATOM_START_CAPTURE_GROUP);
 		}
-		x->v[i] = (duk_uint32_t) (tmp & 0xffffffffUL);
-		tmp = tmp >> 32;
-	}
-	if (tmp != 0U) {
-		DUK_ASSERT(i < DUK__BI_MAX_PARTS);
-		x->v[i++] = (duk_uint32_t) tmp;
+		break;
 	}
-	x->n = i;
-	DUK_ASSERT(x->n <= DUK__BI_MAX_PARTS);
-
-	/* no need to normalize */
-	DUK_ASSERT(duk__bi_is_valid(x));
-}
-#else  /* DUK_USE_64BIT_OPS */
-static void duk__bi_add(duk__bigint *x, duk__bigint *y, duk__bigint *z) {
-	duk_uint32_t carry, tmp1, tmp2;
-	duk_small_int_t i, ny, nz;
-
-	DUK_ASSERT(duk__bi_is_valid(y));
-	DUK_ASSERT(duk__bi_is_valid(z));
-
-	if (z->n > y->n) {
-		duk__bigint *t;
-		t = y; y = z; z = t;
+	case ')': {
+		advtok = DUK__ADVTOK(1, DUK_RETOK_ATOM_END_GROUP);
+		break;
 	}
-	DUK_ASSERT(y->n >= z->n);
-
-	ny = y->n; nz = z->n;
-	carry = 0U;
-	for (i = 0; i < ny; i++) {
-		/* Carry is detected based on wrapping which relies on exact 32-bit
-		 * types.
+	case '[': {
+		/*
+		 *  To avoid creating a heavy intermediate value for the list of ranges,
+		 *  only the start token ('[' or '[^') is parsed here.  The regexp
+		 *  compiler parses the ranges itself.
 		 */
-		DUK_ASSERT(i < DUK__BI_MAX_PARTS);
-		tmp1 = y->v[i];
-		tmp2 = tmp1;
-		if (i < nz) {
-			tmp2 += z->v[i];
+		advtok = DUK__ADVTOK(1, DUK_RETOK_ATOM_START_CHARCLASS);
+		if (y == '^') {
+			advtok = DUK__ADVTOK(2, DUK_RETOK_ATOM_START_CHARCLASS_INVERTED);
 		}
-
-		/* Careful with carry condition:
-		 *  - If carry not added: 0x12345678 + 0 + 0xffffffff = 0x12345677 (< 0x12345678)
-		 *  - If carry added:     0x12345678 + 1 + 0xffffffff = 0x12345678 (== 0x12345678)
+		break;
+	}
+	case ']':
+	case '}': {
+		/* Although these could be parsed as PatternCharacters unambiguously (here),
+		 * E5 Section 15.10.1 grammar explicitly forbids these as PatternCharacters.
 		 */
-		if (carry) {
-			tmp2++;
-			carry = (tmp2 <= tmp1 ? 1U : 0U);
-		} else {
-			carry = (tmp2 < tmp1 ? 1U : 0U);
-		}
-
-		x->v[i] = tmp2;
+		DUK_ERROR(lex_ctx->thr, DUK_ERR_SYNTAX_ERROR,
+		          "invalid regexp character");
+		break;
 	}
-	if (carry) {
-		DUK_ASSERT(i < DUK__BI_MAX_PARTS);
-		DUK_ASSERT(carry == 1U);
-		x->v[i++] = carry;
+	case -1: {
+		/* EOF */
+		advtok = DUK__ADVTOK(0, DUK_TOK_EOF);
+		break;
 	}
-	x->n = i;
-	DUK_ASSERT(x->n <= DUK__BI_MAX_PARTS);
-
-	/* no need to normalize */
-	DUK_ASSERT(duk__bi_is_valid(x));
-}
-#endif  /* DUK_USE_64BIT_OPS */
-
-/* x <- y + z */
-static void duk__bi_add_small(duk__bigint *x, duk__bigint *y, duk_uint32_t z) {
-	duk__bigint tmp;
-
-	DUK_ASSERT(duk__bi_is_valid(y));
-
-	/* XXX: this could be optimized; there is only one call site now though */
-	duk__bi_set_small(&tmp, z);
-	duk__bi_add(x, y, &tmp);
-
-	DUK_ASSERT(duk__bi_is_valid(x));
-}
-
-#if 0  /* unused */
-/* x <- x + y, use t as temp */
-static void duk__bi_add_copy(duk__bigint *x, duk__bigint *y, duk__bigint *t) {
-	duk__bi_add(t, x, y);
-	duk__bi_copy(x, t);
-}
-#endif
-
-/* x <- y - z, require x >= y => z >= 0, i.e. y >= z */
-#ifdef DUK_USE_64BIT_OPS
-static void duk__bi_sub(duk__bigint *x, duk__bigint *y, duk__bigint *z) {
-	duk_small_int_t i, ny, nz;
-	duk_uint32_t ty, tz;
-	duk_int64_t tmp;
-
-	DUK_ASSERT(duk__bi_is_valid(y));
-	DUK_ASSERT(duk__bi_is_valid(z));
-	DUK_ASSERT(duk__bi_compare(y, z) >= 0);
-	DUK_ASSERT(y->n >= z->n);
-
-	ny = y->n; nz = z->n;
-	tmp = 0;
-	for (i = 0; i < ny; i++) {
-		ty = y->v[i];
-		if (i < nz) {
-			tz = z->v[i];
-		} else {
-			tz = 0;
-		}
-		tmp = (duk_int64_t) ty - (duk_int64_t) tz + tmp;
-		x->v[i] = (duk_uint32_t) (tmp & 0xffffffffUL);
-		tmp = tmp >> 32;  /* 0 or -1 */
+	default: {
+		/* PatternCharacter, all excluded characters are matched by cases above */
+		advtok = DUK__ADVTOK(1, DUK_RETOK_ATOM_CHAR);
+		out_token->num = x;
+		break;
 	}
-	DUK_ASSERT(tmp == 0);
-
-	x->n = i;
-	duk__bi_normalize(x);  /* need to normalize, may even cancel to 0 */
-	DUK_ASSERT(duk__bi_is_valid(x));
-}
-#else
-static void duk__bi_sub(duk__bigint *x, duk__bigint *y, duk__bigint *z) {
-	duk_small_int_t i, ny, nz;
-	duk_uint32_t tmp1, tmp2, borrow;
-
-	DUK_ASSERT(duk__bi_is_valid(y));
-	DUK_ASSERT(duk__bi_is_valid(z));
-	DUK_ASSERT(duk__bi_compare(y, z) >= 0);
-	DUK_ASSERT(y->n >= z->n);
-
-	ny = y->n; nz = z->n;
-	borrow = 0U;
-	for (i = 0; i < ny; i++) {
-		/* Borrow is detected based on wrapping which relies on exact 32-bit
-		 * types.
-		 */
-		tmp1 = y->v[i];
-		tmp2 = tmp1;
-		if (i < nz) {
-			tmp2 -= z->v[i];
-		}
-
-		/* Careful with borrow condition:
-		 *  - If borrow not subtracted: 0x12345678 - 0 - 0xffffffff = 0x12345679 (> 0x12345678)
-		 *  - If borrow subtracted:     0x12345678 - 1 - 0xffffffff = 0x12345678 (== 0x12345678)
-		 */
-		if (borrow) {
-			tmp2--;
-			borrow = (tmp2 >= tmp1 ? 1U : 0U);
-		} else {
-			borrow = (tmp2 > tmp1 ? 1U : 0U);
-		}
-
-		x->v[i] = tmp2;
 	}
-	DUK_ASSERT(borrow == 0U);
-
-	x->n = i;
-	duk__bi_normalize(x);  /* need to normalize, may even cancel to 0 */
-	DUK_ASSERT(duk__bi_is_valid(x));
-}
-#endif
-
-#if 0  /* unused */
-/* x <- y - z */
-static void duk__bi_sub_small(duk__bigint *x, duk__bigint *y, duk_uint32_t z) {
-	duk__bigint tmp;
-
-	DUK_ASSERT(duk__bi_is_valid(y));
-
-	/* XXX: this could be optimized */
-	duk__bi_set_small(&tmp, z);
-	duk__bi_sub(x, y, &tmp);
 
-	DUK_ASSERT(duk__bi_is_valid(x));
-}
-#endif
+	/*
+	 *  Shared exit path
+	 */
 
-/* x <- x - y, use t as temp */
-static void duk__bi_sub_copy(duk__bigint *x, duk__bigint *y, duk__bigint *t) {
-	duk__bi_sub(t, x, y);
-	duk__bi_copy(x, t);
+	DUK__ADVANCEBYTES(lex_ctx, advtok >> 8);
+	out_token->t = advtok & 0xff;
 }
 
-/* x <- y * z */
-static void duk__bi_mul(duk__bigint *x, duk__bigint *y, duk__bigint *z) {
-	duk_small_int_t i, j, nx, nz;
-
-	DUK_ASSERT(duk__bi_is_valid(y));
-	DUK_ASSERT(duk__bi_is_valid(z));
-
-	nx = y->n + z->n;  /* max possible */
-	DUK_ASSERT(nx <= DUK__BI_MAX_PARTS);
-
-	if (nx == 0) {
-		/* Both inputs are zero; cases where only one is zero can go
-		 * through main algorithm.
-		 */
-		x->n = 0;
-		return;
-	}
-
-	DUK_MEMZERO((void *) x->v, (size_t) (sizeof(duk_uint32_t) * nx));
-	x->n = nx;
-
-	nz = z->n;
-	for (i = 0; i < y->n; i++) {
-#ifdef DUK_USE_64BIT_OPS
-		duk_uint64_t tmp = 0U;
-		for (j = 0; j < nz; j++) {
-			tmp += (duk_uint64_t) y->v[i] * (duk_uint64_t) z->v[j] + x->v[i+j];
-			x->v[i+j] = (duk_uint32_t) (tmp & 0xffffffffUL);
-			tmp = tmp >> 32;
-		}
-		if (tmp > 0) {
-			DUK_ASSERT(i + j < nx);
-			DUK_ASSERT(i + j < DUK__BI_MAX_PARTS);
-			DUK_ASSERT(x->v[i+j] == 0U);
-			x->v[i+j] = (duk_uint32_t) tmp;
-		}
-#else
-		/*
-		 *  Multiply + add + carry for 32-bit components using only 16x16->32
-		 *  multiplies and carry detection based on unsigned overflow.
-		 *
-		 *    1st mult, 32-bit: (A*2^16 + B)
-		 *    2nd mult, 32-bit: (C*2^16 + D)
-		 *    3rd add, 32-bit: E
-		 *    4th add, 32-bit: F
-		 *
-		 *      (AC*2^16 + B) * (C*2^16 + D) + E + F
-		 *    = AC*2^32 + AD*2^16 + BC*2^16 + BD + E + F
-		 *    = AC*2^32 + (AD + BC)*2^16 + (BD + E + F)
-		 *    = AC*2^32 + AD*2^16 + BC*2^16 + (BD + E + F)
-		 */
-		duk_uint32_t a, b, c, d, e, f;
-		duk_uint32_t r, s, t;
-
-		a = y->v[i]; b = a & 0xffffUL; a = a >> 16;
-
-		f = 0;
-		for (j = 0; j < nz; j++) {
-			c = z->v[j]; d = c & 0xffffUL; c = c >> 16;
-			e = x->v[i+j];
-
-			/* build result as: (r << 32) + s: start with (BD + E + F) */
-			r = 0;
-			s = b * d;
-
-			/* add E */
-			t = s + e;
-			if (t < s) { r++; }  /* carry */
-			s = t;
+/*
+ *  Special parser for character classes; calls callback for every
+ *  range parsed and returns the number of ranges present.
+ */
 
-			/* add F */
-			t = s + f;
-			if (t < s) { r++; }  /* carry */
-			s = t;
+/* XXX: this duplicates functionality in duk_regexp.c where a similar loop is
+ * required anyway.  We could use that BUT we need to update the regexp compiler
+ * 'nranges' too.  Work this out a bit more cleanly to save space.
+ */
 
-			/* add BC*2^16 */
-			t = b * c;
-			r += (t >> 16);
-			t = s + ((t & 0xffffUL) << 16);
-			if (t < s) { r++; }  /* carry */
-			s = t;
+/* XXX: the handling of character range detection is a bit convoluted.
+ * Try to simplify and make smaller.
+ */
 
-			/* add AD*2^16 */
-			t = a * d;
-			r += (t >> 16);
-			t = s + ((t & 0xffffUL) << 16);
-			if (t < s) { r++; }  /* carry */
-			s = t;
+/* XXX: logic for handling character ranges is now incorrect, it will accept
+ * e.g. [\d-z] whereas it should croak from it?  SMJS accepts this too, though.
+ *
+ * Needs a read through and a lot of additional tests.
+ */
 
-			/* add AC*2^32 */
-			t = a * c;
-			r += t;
+DUK_LOCAL
+void duk__emit_u16_direct_ranges(duk_lexer_ctx *lex_ctx,
+                                 duk_re_range_callback gen_range,
+                                 void *userdata,
+                                 duk_uint16_t *ranges,
+                                 duk_small_int_t num) {
+	duk_uint16_t *ranges_end;
 
-			DUK_DDD(DUK_DDDPRINT("ab=%08lx cd=%08lx ef=%08lx -> rs=%08lx %08lx",
-			                     (unsigned long) y->v[i], (unsigned long) z->v[j],
-			                     (unsigned long) x->v[i+j], (unsigned long) r,
-			                     (unsigned long) s));
+	DUK_UNREF(lex_ctx);
 
-			x->v[i+j] = s;
-			f = r;
-		}
-		if (f > 0U) {
-			DUK_ASSERT(i + j < nx);
-			DUK_ASSERT(i + j < DUK__BI_MAX_PARTS);
-			DUK_ASSERT(x->v[i+j] == 0U);
-			x->v[i+j] = (duk_uint32_t) f;
-		}
-#endif  /* DUK_USE_64BIT_OPS */
+	ranges_end = ranges + num;
+	while (ranges < ranges_end) {
+		/* mark range 'direct', bypass canonicalization (see Wiki) */
+		gen_range(userdata, (duk_codepoint_t) ranges[0], (duk_codepoint_t) ranges[1], 1);
+		ranges += 2;
 	}
-
-	duk__bi_normalize(x);
-	DUK_ASSERT(duk__bi_is_valid(x));
 }
 
-/* x <- y * z */
-static void duk__bi_mul_small(duk__bigint *x, duk__bigint *y, duk_uint32_t z) {
-	duk__bigint tmp;
+DUK_INTERNAL void duk_lexer_parse_re_ranges(duk_lexer_ctx *lex_ctx, duk_re_range_callback gen_range, void *userdata) {
+	duk_codepoint_t start = -1;
+	duk_codepoint_t ch;
+	duk_codepoint_t x;
+	duk_bool_t dash = 0;
 
-	DUK_ASSERT(duk__bi_is_valid(y));
+	DUK_DD(DUK_DDPRINT("parsing regexp ranges"));
 
-	/* XXX: this could be optimized */
-	duk__bi_set_small(&tmp, z);
-	duk__bi_mul(x, y, &tmp);
+	for (;;) {
+		x = DUK__L0();
+		DUK__ADVANCECHARS(lex_ctx, 1);
 
-	DUK_ASSERT(duk__bi_is_valid(x));
-}
+		ch = -1;  /* not strictly necessary, but avoids "uninitialized variable" warnings */
+		DUK_UNREF(ch);
 
-/* x <- x * y, use t as temp */
-static void duk__bi_mul_copy(duk__bigint *x, duk__bigint *y, duk__bigint *t) {
-	duk__bi_mul(t, x, y);
-	duk__bi_copy(x, t);
-}
+		if (x < 0) {
+			DUK_ERROR(lex_ctx->thr, DUK_ERR_SYNTAX_ERROR,
+			          "eof while parsing character class");
+		} else if (x == ']') {
+			DUK_ASSERT(!dash);  /* lookup should prevent this */
+			if (start >= 0) {
+				gen_range(userdata, start, start, 0);
+			}
+			break;
+		} else if (x == '-') {
+			if (start >= 0 && !dash && DUK__L0() != ']') {
+				/* '-' as a range indicator */
+				dash = 1;
+				continue;
+			} else {
+				/* '-' verbatim */
+				ch = x;
+			}
+		} else if (x == '\\') {
+			/*
+			 *  The escapes are same as outside a character class, except that \b has a
+			 *  different meaning, and \B and backreferences are prohibited (see E5
+			 *  Section 15.10.2.19).  However, it's difficult to share code because we
+			 *  handle e.g. "\n" very differently: here we generate a single character
+			 *  range for it.
+			 */
+
+			x = DUK__L0();
+			DUK__ADVANCECHARS(lex_ctx, 1);
+
+			if (x == 'b') {
+				/* Note: '\b' in char class is different than outside (assertion),
+				 * '\B' is not allowed and is caught by the duk_unicode_is_identifier_part()
+				 * check below.
+				 */
+				ch = 0x0008;
+			} else if (x == 'f') {
+				ch = 0x000c;
+			} else if (x == 'n') {
+				ch = 0x000a;
+			} else if (x == 't') {
+				ch = 0x0009;
+			} else if (x == 'r') {
+				ch = 0x000d;
+			} else if (x == 'v') {
+				ch = 0x000b;
+			} else if (x == 'c') {
+				x = DUK__L0();
+				DUK__ADVANCECHARS(lex_ctx, 1);
+				if ((x >= 'a' && x <= 'z') ||
+				    (x >= 'A' && x <= 'Z')) {
+					ch = (x % 32);
+				} else {
+					DUK_ERROR(lex_ctx->thr, DUK_ERR_SYNTAX_ERROR,
+					          "invalid regexp control escape");
+					return;  /* never reached, but avoids warnings of
+					          * potentially unused variables.
+					          */
+				}
+			} else if (x == 'x') {
+				ch = duk__decode_hexesc_from_window(lex_ctx, 0);
+				DUK__ADVANCECHARS(lex_ctx, 2);
+			} else if (x == 'u') {
+				ch = duk__decode_uniesc_from_window(lex_ctx, 0);
+				DUK__ADVANCECHARS(lex_ctx, 4);
+			} else if (x == 'd') {
+				duk__emit_u16_direct_ranges(lex_ctx,
+				                            gen_range,
+				                            userdata,
+				                            duk_unicode_re_ranges_digit,
+				                            sizeof(duk_unicode_re_ranges_digit) / sizeof(duk_uint16_t));
+				ch = -1;
+			} else if (x == 'D') {
+				duk__emit_u16_direct_ranges(lex_ctx,
+				                            gen_range,
+				                            userdata,
+				                            duk_unicode_re_ranges_not_digit,
+				                            sizeof(duk_unicode_re_ranges_not_digit) / sizeof(duk_uint16_t));
+				ch = -1;
+			} else if (x == 's') {
+				duk__emit_u16_direct_ranges(lex_ctx,
+				                            gen_range,
+				                            userdata,
+				                            duk_unicode_re_ranges_white,
+				                            sizeof(duk_unicode_re_ranges_white) / sizeof(duk_uint16_t));
+				ch = -1;
+			} else if (x == 'S') {
+				duk__emit_u16_direct_ranges(lex_ctx,
+				                            gen_range,
+				                            userdata,
+				                            duk_unicode_re_ranges_not_white,
+				                            sizeof(duk_unicode_re_ranges_not_white) / sizeof(duk_uint16_t));
+				ch = -1;
+			} else if (x == 'w') {
+				duk__emit_u16_direct_ranges(lex_ctx,
+				                            gen_range,
+				                            userdata,
+				                            duk_unicode_re_ranges_wordchar,
+				                            sizeof(duk_unicode_re_ranges_wordchar) / sizeof(duk_uint16_t));
+				ch = -1;
+			} else if (x == 'W') {
+				duk__emit_u16_direct_ranges(lex_ctx,
+				                            gen_range,
+				                            userdata,
+				                            duk_unicode_re_ranges_not_wordchar,
+				                            sizeof(duk_unicode_re_ranges_not_wordchar) / sizeof(duk_uint16_t));
+				ch = -1;
+			} else if (DUK__ISDIGIT(x)) {
+				/* DecimalEscape, only \0 is allowed, no leading zeroes are allowed */
+				if (x == '0' && !DUK__ISDIGIT(DUK__L0())) {
+					ch = 0x0000;
+				} else {
+					DUK_ERROR(lex_ctx->thr, DUK_ERR_SYNTAX_ERROR,
+					          "invalid decimal escape");
+				}
+			} else if (!duk_unicode_is_identifier_part(x)
+#if defined(DUK_USE_NONSTD_REGEXP_DOLLAR_ESCAPE)
+			           || x == '$'
+#endif
+			          ) {
+				/* IdentityEscape */
+				ch = x;
+			} else {
+				DUK_ERROR(lex_ctx->thr, DUK_ERR_SYNTAX_ERROR,
+				          "invalid regexp escape");
+			}
+		} else {
+			/* character represents itself */
+			ch = x;
+		}
 
-/* x <- x * y, use t as temp */
-static void duk__bi_mul_small_copy(duk__bigint *x, duk_uint32_t y, duk__bigint *t) {
-	duk__bi_mul_small(t, x, y);
-	duk__bi_copy(x, t);
-}
+		/* ch is a literal character here or -1 if parsed entity was
+		 * an escape such as "\s".
+		 */
 
-static int duk__bi_is_even(duk__bigint *x) {
-	DUK_ASSERT(duk__bi_is_valid(x));
-	return (x->n == 0) || ((x->v[0] & 0x01) == 0);
-}
+		if (ch < 0) {
+			/* multi-character sets not allowed as part of ranges, see
+			 * E5 Section 15.10.2.15, abstract operation CharacterRange.
+			 */
+			if (start >= 0) {
+				if (dash) {
+					DUK_ERROR(lex_ctx->thr, DUK_ERR_SYNTAX_ERROR,
+					          "invalid range");
+				} else {
+					gen_range(userdata, start, start, 0);
+					start = -1;
+					/* dash is already 0 */
+				}
+			}
+		} else {
+			if (start >= 0) {
+				if (dash) {
+					if (start > ch) {
+						DUK_ERROR(lex_ctx->thr, DUK_ERR_SYNTAX_ERROR,
+						          "invalid range");
+					}
+					gen_range(userdata, start, ch, 0);
+					start = -1;
+					dash = 0;
+				} else {
+					gen_range(userdata, start, start, 0);
+					start = ch;
+					/* dash is already 0 */
+				}
+			} else {
+				start = ch;
+			}
+		}
+	}
 
-static int duk__bi_is_zero(duk__bigint *x) {
-	DUK_ASSERT(duk__bi_is_valid(x));
-	return (x->n == 0);  /* this is the case for normalized numbers */
+	return;
 }
 
-/* Bigint is 2^52.  Used to detect normalized IEEE double mantissa values
- * which are at the lowest edge (next floating point value downwards has
- * a different exponent).  The lowest mantissa has the form:
+#endif  /* DUK_USE_REGEXP_SUPPORT */
+#line 1 "duk_numconv.c"
+/*
+ *  Number-to-string and string-to-number conversions.
  *
- *     1000........000    (52 zeroes; only "hidden bit" is set)
+ *  Slow path number-to-string and string-to-number conversion is based on
+ *  a Dragon4 variant, with fast paths for small integers.  Big integer
+ *  arithmetic is needed for guaranteeing that the conversion is correct
+ *  and uses a minimum number of digits.  The big number arithmetic has a
+ *  fixed maximum size and does not require dynamic allocations.
+ *
+ *  See: doc/number-conversion.rst.
  */
-static duk_small_int_t duk__bi_is_2to52(duk__bigint *x) {
-	DUK_ASSERT(duk__bi_is_valid(x));
-	return (duk_small_int_t)
-	        (x->n == 2) && (x->v[0] == 0U) && (x->v[1] == (1U << (52-32)));
-}
-
-/* x <- (1<<y) */
-static void duk__bi_twoexp(duk__bigint *x, duk_small_int_t y) {
-	duk_small_int_t n, r;
-
-	n = (y / 32) + 1;
-	DUK_ASSERT(n > 0);
-	r = y % 32;
-	DUK_MEMZERO((void *) x->v, sizeof(duk_uint32_t) * n);
-	x->n = n;
-	x->v[n - 1] = (((duk_uint32_t) 1) << r);
-}
-
-/* x <- b^y; use t1 and t2 as temps */
-static void duk__bi_exp_small(duk__bigint *x, duk_small_int_t b, duk_small_int_t y, duk__bigint *t1, duk__bigint *t2) {
-	/* Fast path the binary case */
-
-	DUK_ASSERT(x != t1 && x != t2 && t1 != t2);  /* distinct bignums, easy mistake to make */
-	DUK_ASSERT(b >= 0);
-	DUK_ASSERT(y >= 0);
-
-	if (b == 2) {
-		duk__bi_twoexp(x, y);
-		return;
-	}
-
-	/* http://en.wikipedia.org/wiki/Exponentiation_by_squaring */
 
-	DUK_DDD(DUK_DDDPRINT("exp_small: b=%ld, y=%ld", (long) b, (long) y));
+/* include removed: duk_internal.h */
 
-	duk__bi_set_small(x, 1);
-	duk__bi_set_small(t1, b);
-	for (;;) {
-		/* Loop structure ensures that we don't compute t1^2 unnecessarily
-		 * on the final round, as that might create a bignum exceeding the
-		 * current DUK__BI_MAX_PARTS limit.
-		 */
-		if (y & 0x01) {
-			duk__bi_mul_copy(x, t1, t2);
-		}
-		y = y >> 1;
-		if (y == 0) {
-			break;
-		}
-		duk__bi_mul_copy(t1, t1, t2);
-	}
+#define DUK__IEEE_DOUBLE_EXP_BIAS  1023
+#define DUK__IEEE_DOUBLE_EXP_MIN   (-1022)   /* biased exp == 0 -> denormal, exp -1022 */
 
-	DUK__BI_PRINT("exp_small result", x);
-}
+#define DUK__DIGITCHAR(x)  duk_lc_digits[(x)]
 
 /*
- *  A Dragon4 number-to-string variant, based on:
- *
- *    Guy L. Steele Jr., Jon L. White: "How to Print Floating-Point Numbers
- *    Accurately"
- *
- *    Robert G. Burger, R. Kent Dybvig: "Printing Floating-Point Numbers
- *    Quickly and Accurately"
- *
- *  The current algorithm is based on Figure 1 of the Burger-Dybvig paper,
- *  i.e. the base implementation without logarithm estimation speedups
- *  (these would increase code footprint considerably).  Fixed-format output
- *  does not follow the suggestions in the paper; instead, we generate an
- *  extra digit and round-with-carry.
+ *  Tables generated with src/gennumdigits.py.
  *
- *  The same algorithm is used for number parsing (with b=10 and B=2)
- *  by generating one extra digit and doing rounding manually.
+ *  duk__str2num_digits_for_radix indicates, for each radix, how many input
+ *  digits should be considered significant for string-to-number conversion.
+ *  The input is also padded to this many digits to give the Dragon4
+ *  conversion enough (apparent) precision to work with.
  *
- *  See doc/number-conversion.txt for limitations.
+ *  duk__str2num_exp_limits indicates, for each radix, the radix-specific
+ *  minimum/maximum exponent values (for a Dragon4 integer mantissa)
+ *  below and above which the number is guaranteed to underflow to zero
+ *  or overflow to Infinity.  This allows parsing to keep bigint values
+ *  bounded.
  */
 
-/* Maximum number of digits generated. */
-#define DUK__MAX_OUTPUT_DIGITS          1040  /* (Number.MAX_VALUE).toString(2).length == 1024, + spare */
-
-/* Maximum number of characters in formatted value. */
-#define DUK__MAX_FORMATTED_LENGTH       1040  /* (-Number.MAX_VALUE).toString(2).length == 1025, + spare */
-
-/* Number and (minimum) size of bigints in the nc_ctx structure. */
-#define DUK__NUMCONV_CTX_NUM_BIGINTS    7
-#define DUK__NUMCONV_CTX_BIGINTS_SIZE   (sizeof(duk__bigint) * DUK__NUMCONV_CTX_NUM_BIGINTS)
+DUK_LOCAL const duk_uint8_t duk__str2num_digits_for_radix[] = {
+	69, 44, 35, 30, 27, 25, 23, 22, 20, 20,    /* 2 to 11 */
+	20, 19, 19, 18, 18, 17, 17, 17, 16, 16,    /* 12 to 21 */
+	16, 16, 16, 15, 15, 15, 15, 15, 15, 14,    /* 22 to 31 */
+	14, 14, 14, 14, 14                         /* 31 to 36 */
+};
 
 typedef struct {
-	/* Currently about 7*152 = 1064 bytes.  The space for these
-	 * duk__bigints is used also as a temporary buffer for generating
-	 * the final string.  This is a bit awkard; a union would be
-	 * more correct.
-	 */
-	duk__bigint f, r, s, mp, mm, t1, t2;
-
-	duk_small_int_t is_s2n;        /* if 1, doing a string-to-number; else doing a number-to-string */
-	duk_small_int_t is_fixed;      /* if 1, doing a fixed format output (not free format) */
-	duk_small_int_t req_digits;    /* requested number of output digits; 0 = free-format */
-	duk_small_int_t abs_pos;       /* digit position is absolute, not relative */
-	duk_small_int_t e;             /* exponent for 'f' */
-	duk_small_int_t b;             /* input radix */
-	duk_small_int_t B;             /* output radix */
-	duk_small_int_t k;             /* see algorithm */
-	duk_small_int_t low_ok;        /* see algorithm */
-	duk_small_int_t high_ok;       /* see algorithm */
-	duk_small_int_t unequal_gaps;  /* m+ != m- (very rarely) */
+	duk_int16_t upper;
+	duk_int16_t lower;
+} duk__exp_limits;
 
-	/* Buffer used for generated digits, values are in the range [0,B-1]. */
-	duk_uint8_t digits[DUK__MAX_OUTPUT_DIGITS];
-	duk_small_int_t count;  /* digit count */
-} duk__numconv_stringify_ctx;
+DUK_LOCAL const duk__exp_limits duk__str2num_exp_limits[] = {
+	{ 957, -1147 }, { 605, -725 },  { 479, -575 },  { 414, -496 },
+	{ 372, -446 },  { 342, -411 },  { 321, -384 },  { 304, -364 },
+	{ 291, -346 },  { 279, -334 },  { 268, -323 },  { 260, -312 },
+	{ 252, -304 },  { 247, -296 },  { 240, -289 },  { 236, -283 },
+	{ 231, -278 },  { 227, -273 },  { 223, -267 },  { 220, -263 },
+	{ 216, -260 },  { 213, -256 },  { 210, -253 },  { 208, -249 },
+	{ 205, -246 },  { 203, -244 },  { 201, -241 },  { 198, -239 },
+	{ 196, -237 },  { 195, -234 },  { 193, -232 },  { 191, -230 },
+	{ 190, -228 },  { 188, -226 },  { 187, -225 },
+};
 
-/* Note: computes with 'idx' in assertions, so caller beware.
- * 'idx' is preincremented, i.e. '1' on first call, because it
- * is more convenient for the caller.
+/*
+ *  Limited functionality bigint implementation.
+ *
+ *  Restricted to non-negative numbers with less than 32 * DUK__BI_MAX_PARTS bits,
+ *  with the caller responsible for ensuring this is never exceeded.  No memory
+ *  allocation (except stack) is needed for bigint computation.  Operations
+ *  have been tailored for number conversion needs.
+ *
+ *  Argument order is "assignment order", i.e. target first, then arguments:
+ *  x <- y * z  -->  duk__bi_mul(x, y, z);
  */
-#define DUK__DRAGON4_OUTPUT_PREINC(nc_ctx,preinc_idx,x)  do { \
-		DUK_ASSERT((preinc_idx) - 1 >= 0); \
-		DUK_ASSERT((preinc_idx) - 1 < DUK__MAX_OUTPUT_DIGITS); \
-		((nc_ctx)->digits[(preinc_idx) - 1]) = (duk_uint8_t) (x); \
-	} while (0)
-
-static duk_size_t duk__dragon4_format_uint32(duk_uint8_t *buf, duk_uint32_t x, duk_small_int_t radix) {
-	duk_uint8_t *p;
-	duk_size_t len;
-	duk_small_int_t dig;
-	duk_small_int_t t;
 
-	DUK_ASSERT(radix >= 2 && radix <= 36);
+/* This upper value has been experimentally determined; debug build will check
+ * bigint size with assertions.
+ */
+#define DUK__BI_MAX_PARTS  37  /* 37x32 = 1184 bits */
 
-	/* A 32-bit unsigned integer formats to at most 32 digits (the
-	 * worst case happens with radix == 2).  Output the digits backwards,
-	 * and use a memmove() to get them in the right place.
-	 */
+#ifdef DUK_USE_DDDPRINT
+#define DUK__BI_PRINT(name,x)  duk__bi_print((name),(x))
+#else
+#define DUK__BI_PRINT(name,x)
+#endif
 
-	p = buf + 32;
-	for (;;) {
-		t = x / radix;
-		dig = x - t * radix;
-		x = t;
+/* Current size is about 152 bytes. */
+typedef struct {
+	duk_small_int_t n;
+	duk_uint32_t v[DUK__BI_MAX_PARTS];  /* low to high */
+} duk__bigint;
 
-		DUK_ASSERT(dig >= 0 && dig < 36);
-		*(--p) = DUK__DIGITCHAR(dig);
+#ifdef DUK_USE_DDDPRINT
+DUK_LOCAL void duk__bi_print(const char *name, duk__bigint *x) {
+	/* Overestimate required size; debug code so not critical to be tight. */
+	char buf[DUK__BI_MAX_PARTS * 9 + 64];
+	char *p = buf;
+	duk_small_int_t i;
 
-		if (x == 0) {
-			break;
-		}
+	/* No NUL term checks in this debug code. */
+	p += DUK_SPRINTF(p, "%p n=%ld", (void *) x, (long) x->n);
+	if (x->n == 0) {
+		p += DUK_SPRINTF(p, " 0");
+	}
+	for (i = x->n - 1; i >= 0; i--) {
+		p += DUK_SPRINTF(p, " %08lx", (unsigned long) x->v[i]);
 	}
-	len = (duk_size_t) ((buf + 32) - p);
-
-	DUK_MEMMOVE((void *) buf, (void *) p, (size_t) len);
 
-	return len;
+	DUK_DDD(DUK_DDDPRINT("%s: %s", (const char *) name, (const char *) buf));
 }
-
-static void duk__dragon4_prepare(duk__numconv_stringify_ctx *nc_ctx) {
-	duk_small_int_t lowest_mantissa;
-
-#if 1
-	/* Assume IEEE round-to-even, so that shorter encoding can be used
-	 * when round-to-even would produce correct result.  By removing
-	 * this check (and having low_ok == high_ok == 0) the results would
-	 * still be accurate but in some cases longer than necessary.
-	 */
-	if (duk__bi_is_even(&nc_ctx->f)) {
-		DUK_DDD(DUK_DDDPRINT("f is even"));
-		nc_ctx->low_ok = 1;
-		nc_ctx->high_ok = 1;
-	} else {
-		DUK_DDD(DUK_DDDPRINT("f is odd"));
-		nc_ctx->low_ok = 0;
-		nc_ctx->high_ok = 0;
-	}
-#else
-	/* Note: not honoring round-to-even should work but now generates incorrect
-	 * results.  For instance, 1e23 serializes to "a000...", i.e. the first digit
-	 * equals the radix (10).  Scaling stops one step too early in this case.
-	 * Don't know why this is the case, but since this code path is unused, it
-	 * doesn't matter.
-	 */
-	nc_ctx->low_ok = 0;
-	nc_ctx->high_ok = 0;
 #endif
 
-	/* For string-to-number, pretend we never have the lowest mantissa as there
-	 * is no natural "precision" for inputs.  Having lowest_mantissa == 0, we'll
-	 * fall into the base cases for both e >= 0 and e < 0.
-	 */
-	if (nc_ctx->is_s2n) {
-		lowest_mantissa = 0;
-	} else {
-		lowest_mantissa = duk__bi_is_2to52(&nc_ctx->f);
-	}
-
-	nc_ctx->unequal_gaps = 0;
-	if (nc_ctx->e >= 0) {
-		/* exponent non-negative (and thus not minimum exponent) */
-
-		if (lowest_mantissa) {
-			/* (>= e 0) AND (= f (expt b (- p 1)))
-			 *
-			 * be <- (expt b e) == b^e
-			 * be1 <- (* be b) == (expt b (+ e 1)) == b^(e+1)
-			 * r <- (* f be1 2) == 2 * f * b^(e+1)    [if b==2 -> f * b^(e+2)]
-			 * s <- (* b 2)                           [if b==2 -> 4]
-			 * m+ <- be1 == b^(e+1)
-			 * m- <- be == b^e
-			 * k <- 0
-			 * B <- B
-			 * low_ok <- round
-			 * high_ok <- round
-			 */
-
-			DUK_DDD(DUK_DDDPRINT("non-negative exponent (not smallest exponent); "
-			                     "lowest mantissa value for this exponent -> "
-			                     "unequal gaps"));
-
-			duk__bi_exp_small(&nc_ctx->mm, nc_ctx->b, nc_ctx->e, &nc_ctx->t1, &nc_ctx->t2);  /* mm <- b^e */
-			duk__bi_mul_small(&nc_ctx->mp, &nc_ctx->mm, nc_ctx->b);  /* mp <- b^(e+1) */
-			duk__bi_mul_small(&nc_ctx->t1, &nc_ctx->f, 2);
-			duk__bi_mul(&nc_ctx->r, &nc_ctx->t1, &nc_ctx->mp);       /* r <- (2 * f) * b^(e+1) */
-			duk__bi_set_small(&nc_ctx->s, nc_ctx->b * 2);            /* s <- 2 * b */
-			nc_ctx->unequal_gaps = 1;
-		} else {
-			/* (>= e 0) AND (not (= f (expt b (- p 1))))
-			 *
-			 * be <- (expt b e) == b^e
-			 * r <- (* f be 2) == 2 * f * b^e    [if b==2 -> f * b^(e+1)]
-			 * s <- 2
-			 * m+ <- be == b^e
-			 * m- <- be == b^e
-			 * k <- 0
-			 * B <- B
-			 * low_ok <- round
-			 * high_ok <- round
-			 */
-
-			DUK_DDD(DUK_DDDPRINT("non-negative exponent (not smallest exponent); "
-			                     "not lowest mantissa for this exponent -> "
-			                     "equal gaps"));
-
-			duk__bi_exp_small(&nc_ctx->mm, nc_ctx->b, nc_ctx->e, &nc_ctx->t1, &nc_ctx->t2);  /* mm <- b^e */
-			duk__bi_copy(&nc_ctx->mp, &nc_ctx->mm);                /* mp <- b^e */
-			duk__bi_mul_small(&nc_ctx->t1, &nc_ctx->f, 2);
-			duk__bi_mul(&nc_ctx->r, &nc_ctx->t1, &nc_ctx->mp);     /* r <- (2 * f) * b^e */
-			duk__bi_set_small(&nc_ctx->s, 2);                      /* s <- 2 */
-		}
-	} else {
-		/* When doing string-to-number, lowest_mantissa is always 0 so
-		 * the exponent check, while incorrect, won't matter.
-		 */
-		if (nc_ctx->e > DUK__IEEE_DOUBLE_EXP_MIN /*not minimum exponent*/ &&
-		    lowest_mantissa /* lowest mantissa for this exponent*/) {
-			/* r <- (* f b 2)                                [if b==2 -> (* f 4)]
-			 * s <- (* (expt b (- 1 e)) 2) == b^(1-e) * 2    [if b==2 -> b^(2-e)]
-			 * m+ <- b == 2
-			 * m- <- 1
-			 * k <- 0
-			 * B <- B
-			 * low_ok <- round
-			 * high_ok <- round
-			 */
-
-			DUK_DDD(DUK_DDDPRINT("negative exponent; not minimum exponent and "
-			                     "lowest mantissa for this exponent -> "
-			                     "unequal gaps"));
-
-			duk__bi_mul_small(&nc_ctx->r, &nc_ctx->f, nc_ctx->b * 2);  /* r <- (2 * b) * f */
-			duk__bi_exp_small(&nc_ctx->t1, nc_ctx->b, 1 - nc_ctx->e, &nc_ctx->s, &nc_ctx->t2);  /* NB: use 's' as temp on purpose */
-			duk__bi_mul_small(&nc_ctx->s, &nc_ctx->t1, 2);             /* s <- b^(1-e) * 2 */
-			duk__bi_set_small(&nc_ctx->mp, 2);
-			duk__bi_set_small(&nc_ctx->mm, 1);
-			nc_ctx->unequal_gaps = 1;
-		} else {
-			/* r <- (* f 2)
-			 * s <- (* (expt b (- e)) 2) == b^(-e) * 2    [if b==2 -> b^(1-e)]
-			 * m+ <- 1
-			 * m- <- 1
-			 * k <- 0
-			 * B <- B
-			 * low_ok <- round
-			 * high_ok <- round
-			 */
+#ifdef DUK_USE_ASSERTIONS
+DUK_LOCAL duk_small_int_t duk__bi_is_valid(duk__bigint *x) {
+	return (duk_small_int_t)
+	       ( ((x->n >= 0) && (x->n <= DUK__BI_MAX_PARTS)) /* is valid size */ &&
+	         ((x->n == 0) || (x->v[x->n - 1] != 0)) /* is normalized */ );
+}
+#endif
 
-			DUK_DDD(DUK_DDDPRINT("negative exponent; minimum exponent or not "
-			                     "lowest mantissa for this exponent -> "
-			                     "equal gaps"));
+DUK_LOCAL void duk__bi_normalize(duk__bigint *x) {
+	duk_small_int_t i;
 
-			duk__bi_mul_small(&nc_ctx->r, &nc_ctx->f, 2);            /* r <- 2 * f */
-			duk__bi_exp_small(&nc_ctx->t1, nc_ctx->b, -nc_ctx->e, &nc_ctx->s, &nc_ctx->t2);  /* NB: use 's' as temp on purpose */
-			duk__bi_mul_small(&nc_ctx->s, &nc_ctx->t1, 2);           /* s <- b^(-e) * 2 */
-			duk__bi_set_small(&nc_ctx->mp, 1);
-			duk__bi_set_small(&nc_ctx->mm, 1);
+	for (i = x->n - 1; i >= 0; i--) {
+		if (x->v[i] != 0) {
+			break;
 		}
 	}
-}
-
-static void duk__dragon4_scale(duk__numconv_stringify_ctx *nc_ctx) {
-	duk_small_int_t k = 0;
-
-	/* This is essentially the 'scale' algorithm, with recursion removed.
-	 * Note that 'k' is either correct immediately, or will move in one
-	 * direction in the loop.  There's no need to do the low/high checks
-	 * on every round (like the Scheme algorithm does).
-	 *
-	 * The scheme algorithm finds 'k' and updates 's' simultaneously,
-	 * while the logical algorithm finds 'k' with 's' having its initial
-	 * value, after which 's' is updated separately (see the Burger-Dybvig
-	 * paper, Section 3.1, steps 2 and 3).
-	 *
-	 * The case where m+ == m- (almost always) is optimized for, because
-	 * it reduces the bigint operations considerably and almost always
-	 * applies.  The scale loop only needs to work with m+, so this works.
-	 */
-
-	/* XXX: this algorithm could be optimized quite a lot by using e.g.
-	 * a logarithm based estimator for 'k' and performing B^n multiplication
-	 * using a lookup table or using some bit-representation based exp
-	 * algorithm.  Currently we just loop, with significant performance
-	 * impact for very large and very small numbers.
-	 */
-
-	DUK_DDD(DUK_DDDPRINT("scale: B=%ld, low_ok=%ld, high_ok=%ld",
-	                     (long) nc_ctx->B, (long) nc_ctx->low_ok, (long) nc_ctx->high_ok));
-	DUK__BI_PRINT("r(init)", &nc_ctx->r);
-	DUK__BI_PRINT("s(init)", &nc_ctx->s);
-	DUK__BI_PRINT("mp(init)", &nc_ctx->mp);
-	DUK__BI_PRINT("mm(init)", &nc_ctx->mm);
 
-	for (;;) {
-		DUK_DDD(DUK_DDDPRINT("scale loop (inc k), k=%ld", (long) k));
-		DUK__BI_PRINT("r", &nc_ctx->r);
-		DUK__BI_PRINT("s", &nc_ctx->s);
-		DUK__BI_PRINT("m+", &nc_ctx->mp);
-		DUK__BI_PRINT("m-", &nc_ctx->mm);
+	/* Note: if 'x' is zero, x->n becomes 0 here */
+	x->n = i + 1;
+	DUK_ASSERT(duk__bi_is_valid(x));
+}
 
-		duk__bi_add(&nc_ctx->t1, &nc_ctx->r, &nc_ctx->mp);  /* t1 = (+ r m+) */
-		if (duk__bi_compare(&nc_ctx->t1, &nc_ctx->s) >= (nc_ctx->high_ok ? 0 : 1)) {
-			DUK_DDD(DUK_DDDPRINT("k is too low"));
-			/* r <- r
-			 * s <- (* s B)
-			 * m+ <- m+
-			 * m- <- m-
-			 * k <- (+ k 1)
-			 */
+/* x <- y */
+DUK_LOCAL void duk__bi_copy(duk__bigint *x, duk__bigint *y) {
+	duk_small_int_t n;
 
-			duk__bi_mul_small_copy(&nc_ctx->s, nc_ctx->B, &nc_ctx->t1);
-			k++;
-		} else {
-			break;
-		}
+	n = y->n;
+	x->n = n;
+	if (n == 0) {
+		return;
 	}
+	DUK_MEMCPY((void *) x->v, (const void *) y->v, (size_t) (sizeof(duk_uint32_t) * n));
+}
 
-	/* k > 0 -> k was too low, and cannot be too high */
-	if (k > 0) {
-		goto skip_dec_k;
+DUK_LOCAL void duk__bi_set_small(duk__bigint *x, duk_uint32_t v) {
+	if (v == 0U) {
+		x->n = 0;
+	} else {
+		x->n = 1;
+		x->v[0] = v;
 	}
+	DUK_ASSERT(duk__bi_is_valid(x));
+}
 
-	for (;;) {
-		DUK_DDD(DUK_DDDPRINT("scale loop (dec k), k=%ld", (long) k));
-		DUK__BI_PRINT("r", &nc_ctx->r);
-		DUK__BI_PRINT("s", &nc_ctx->s);
-		DUK__BI_PRINT("m+", &nc_ctx->mp);
-		DUK__BI_PRINT("m-", &nc_ctx->mm);
-
-		duk__bi_add(&nc_ctx->t1, &nc_ctx->r, &nc_ctx->mp);  /* t1 = (+ r m+) */
-		duk__bi_mul_small(&nc_ctx->t2, &nc_ctx->t1, nc_ctx->B);   /* t2 = (* (+ r m+) B) */
-		if (duk__bi_compare(&nc_ctx->t2, &nc_ctx->s) <= (nc_ctx->high_ok ? -1 : 0)) {
-			DUK_DDD(DUK_DDDPRINT("k is too high"));
-			/* r <- (* r B)
-			 * s <- s
-			 * m+ <- (* m+ B)
-			 * m- <- (* m- B)
-			 * k <- (- k 1)
-			 */
-			duk__bi_mul_small_copy(&nc_ctx->r, nc_ctx->B, &nc_ctx->t1);
-			duk__bi_mul_small_copy(&nc_ctx->mp, nc_ctx->B, &nc_ctx->t1);
-			if (nc_ctx->unequal_gaps) {
-				DUK_DDD(DUK_DDDPRINT("m+ != m- -> need to update m- too"));
-				duk__bi_mul_small_copy(&nc_ctx->mm, nc_ctx->B, &nc_ctx->t1);
-			}
-			k--;
-		} else {
-			break;
+/* Return value: <0  <=>  x < y
+ *                0  <=>  x == y
+ *               >0  <=>  x > y
+ */
+DUK_LOCAL int duk__bi_compare(duk__bigint *x, duk__bigint *y) {
+	duk_small_int_t i, nx, ny;
+	duk_uint32_t tx, ty;
+
+	DUK_ASSERT(duk__bi_is_valid(x));
+	DUK_ASSERT(duk__bi_is_valid(y));
+
+	nx = x->n;
+	ny = y->n;
+	if (nx > ny) {
+		goto ret_gt;
+	}
+	if (nx < ny) {
+		goto ret_lt;
+	}
+	for (i = nx - 1; i >= 0; i--) {
+		tx = x->v[i];
+		ty = y->v[i];
+
+		if (tx > ty) {
+			goto ret_gt;
+		}
+		if (tx < ty) {
+			goto ret_lt;
 		}
 	}
 
- skip_dec_k:
+	return 0;
 
-	if (!nc_ctx->unequal_gaps) {
-		DUK_DDD(DUK_DDDPRINT("equal gaps, copy m- from m+"));
-		duk__bi_copy(&nc_ctx->mm, &nc_ctx->mp);  /* mm <- mp */
-	}
-	nc_ctx->k = k;
+ ret_gt:
+	return 1;
 
-	DUK_DDD(DUK_DDDPRINT("final k: %ld", (long) k));
-	DUK__BI_PRINT("r(final)", &nc_ctx->r);
-	DUK__BI_PRINT("s(final)", &nc_ctx->s);
-	DUK__BI_PRINT("mp(final)", &nc_ctx->mp);
-	DUK__BI_PRINT("mm(final)", &nc_ctx->mm);
+ ret_lt:
+	return -1;
 }
 
-static void duk__dragon4_generate(duk__numconv_stringify_ctx *nc_ctx) {
-	duk_small_int_t tc1, tc2;    /* terminating conditions */
-	duk_small_int_t d;           /* current digit */
-	duk_small_int_t count = 0;   /* digit count */
+/* x <- y + z */
+#ifdef DUK_USE_64BIT_OPS
+DUK_LOCAL void duk__bi_add(duk__bigint *x, duk__bigint *y, duk__bigint *z) {
+	duk_uint64_t tmp;
+	duk_small_int_t i, ny, nz;
 
-	/*
-	 *  Digit generation loop.
-	 *
-	 *  Different termination conditions:
-	 *
-	 *    1. Free format output.  Terminate when shortest accurate
-	 *       representation found.
-	 *
-	 *    2. Fixed format output, with specific number of digits.
-	 *       Ignore termination conditions, terminate when digits
-	 *       generated.  Caller requests an extra digit and rounds.
-	 *
-	 *    3. Fixed format output, with a specific absolute cut-off
-	 *       position (e.g. 10 digits after decimal point).  Note
-	 *       that we always generate at least one digit, even if
-	 *       the digit is below the cut-off point already.
-	 */
+	DUK_ASSERT(duk__bi_is_valid(y));
+	DUK_ASSERT(duk__bi_is_valid(z));
 
-	for (;;) {
-		DUK_DDD(DUK_DDDPRINT("generate loop, count=%ld, k=%ld, B=%ld, low_ok=%ld, high_ok=%ld",
-		                     (long) count, (long) nc_ctx->k, (long) nc_ctx->B,
-		                     (long) nc_ctx->low_ok, (long) nc_ctx->high_ok));
-		DUK__BI_PRINT("r", &nc_ctx->r);
-		DUK__BI_PRINT("s", &nc_ctx->s);
-		DUK__BI_PRINT("m+", &nc_ctx->mp);
-		DUK__BI_PRINT("m-", &nc_ctx->mm);
+	if (z->n > y->n) {
+		duk__bigint *t;
+		t = y; y = z; z = t;
+	}
+	DUK_ASSERT(y->n >= z->n);
 
-		/* (quotient-remainder (* r B) s) using a dummy subtraction loop */
-		duk__bi_mul_small(&nc_ctx->t1, &nc_ctx->r, nc_ctx->B);       /* t1 <- (* r B) */
-		d = 0;
-		for (;;) {
-			if (duk__bi_compare(&nc_ctx->t1, &nc_ctx->s) < 0) {
-				break;
-			}
-			duk__bi_sub_copy(&nc_ctx->t1, &nc_ctx->s, &nc_ctx->t2);  /* t1 <- t1 - s */
-			d++;
+	ny = y->n; nz = z->n;
+	tmp = 0U;
+	for (i = 0; i < ny; i++) {
+		DUK_ASSERT(i < DUK__BI_MAX_PARTS);
+		tmp += y->v[i];
+		if (i < nz) {
+			tmp += z->v[i];
 		}
-		duk__bi_copy(&nc_ctx->r, &nc_ctx->t1);  /* r <- (remainder (* r B) s) */
-		                                        /* d <- (quotient (* r B) s)   (in range 0...B-1) */
-		DUK_DDD(DUK_DDDPRINT("-> d(quot)=%ld", (long) d));
-		DUK__BI_PRINT("r(rem)", &nc_ctx->r);
-
-		duk__bi_mul_small_copy(&nc_ctx->mp, nc_ctx->B, &nc_ctx->t2); /* m+ <- (* m+ B) */
-		duk__bi_mul_small_copy(&nc_ctx->mm, nc_ctx->B, &nc_ctx->t2); /* m- <- (* m- B) */
-		DUK__BI_PRINT("mp(upd)", &nc_ctx->mp);
-		DUK__BI_PRINT("mm(upd)", &nc_ctx->mm);
+		x->v[i] = (duk_uint32_t) (tmp & 0xffffffffUL);
+		tmp = tmp >> 32;
+	}
+	if (tmp != 0U) {
+		DUK_ASSERT(i < DUK__BI_MAX_PARTS);
+		x->v[i++] = (duk_uint32_t) tmp;
+	}
+	x->n = i;
+	DUK_ASSERT(x->n <= DUK__BI_MAX_PARTS);
 
-		/* Terminating conditions.  For fixed width output, we just ignore the
-		 * terminating conditions (and pretend that tc1 == tc2 == false).  The
-		 * the current shortcut for fixed-format output is to generate a few
-		 * extra digits and use rounding (with carry) to finish the output.
-		 */
+	/* no need to normalize */
+	DUK_ASSERT(duk__bi_is_valid(x));
+}
+#else  /* DUK_USE_64BIT_OPS */
+DUK_LOCAL void duk__bi_add(duk__bigint *x, duk__bigint *y, duk__bigint *z) {
+	duk_uint32_t carry, tmp1, tmp2;
+	duk_small_int_t i, ny, nz;
 
-		if (nc_ctx->is_fixed == 0) {
-			/* free-form */
-			tc1 = (duk__bi_compare(&nc_ctx->r, &nc_ctx->mm) <= (nc_ctx->low_ok ? 0 : -1));
+	DUK_ASSERT(duk__bi_is_valid(y));
+	DUK_ASSERT(duk__bi_is_valid(z));
 
-			duk__bi_add(&nc_ctx->t1, &nc_ctx->r, &nc_ctx->mp);  /* t1 <- (+ r m+) */
-			tc2 = (duk__bi_compare(&nc_ctx->t1, &nc_ctx->s) >= (&nc_ctx->high_ok ? 0 : 1));
+	if (z->n > y->n) {
+		duk__bigint *t;
+		t = y; y = z; z = t;
+	}
+	DUK_ASSERT(y->n >= z->n);
 
-			DUK_DDD(DUK_DDDPRINT("tc1=%ld, tc2=%ld", (long) tc1, (long) tc2));
-		} else {
-			/* fixed-format */
-			tc1 = 0;
-			tc2 = 0;
+	ny = y->n; nz = z->n;
+	carry = 0U;
+	for (i = 0; i < ny; i++) {
+		/* Carry is detected based on wrapping which relies on exact 32-bit
+		 * types.
+		 */
+		DUK_ASSERT(i < DUK__BI_MAX_PARTS);
+		tmp1 = y->v[i];
+		tmp2 = tmp1;
+		if (i < nz) {
+			tmp2 += z->v[i];
 		}
 
-		/* Count is incremented before DUK__DRAGON4_OUTPUT_PREINC() call
-		 * on purpose, which is taken into account by the macro.
+		/* Careful with carry condition:
+		 *  - If carry not added: 0x12345678 + 0 + 0xffffffff = 0x12345677 (< 0x12345678)
+		 *  - If carry added:     0x12345678 + 1 + 0xffffffff = 0x12345678 (== 0x12345678)
 		 */
-		count++;
-
-		if (tc1) {
-			if (tc2) {
-				/* tc1 = true, tc2 = true */
-				duk__bi_mul_small(&nc_ctx->t1, &nc_ctx->r, 2);
-				if (duk__bi_compare(&nc_ctx->t1, &nc_ctx->s) < 0) {  /* (< (* r 2) s) */
-					DUK_DDD(DUK_DDDPRINT("tc1=true, tc2=true, 2r > s: output d --> %ld (k=%ld)",
-					                     (long) d, (long) nc_ctx->k));
-					DUK__DRAGON4_OUTPUT_PREINC(nc_ctx, count, d);
-				} else {
-					DUK_DDD(DUK_DDDPRINT("tc1=true, tc2=true, 2r <= s: output d+1 --> %ld (k=%ld)",
-					                     (long) (d + 1), (long) nc_ctx->k));
-					DUK__DRAGON4_OUTPUT_PREINC(nc_ctx, count, d + 1);
-				}
-				break;
-			} else {
-				/* tc1 = true, tc2 = false */
-				DUK_DDD(DUK_DDDPRINT("tc1=true, tc2=false: output d --> %ld (k=%ld)",
-				                     (long) d, (long) nc_ctx->k));
-				DUK__DRAGON4_OUTPUT_PREINC(nc_ctx, count, d);
-				break;
-			}
+		if (carry) {
+			tmp2++;
+			carry = (tmp2 <= tmp1 ? 1U : 0U);
 		} else {
-			if (tc2) {
-				/* tc1 = false, tc2 = true */
-				DUK_DDD(DUK_DDDPRINT("tc1=false, tc2=true: output d+1 --> %ld (k=%ld)",
-				                     (long) (d + 1), (long) nc_ctx->k));
-				DUK__DRAGON4_OUTPUT_PREINC(nc_ctx, count, d + 1);
-				break;
-			} else {
-				/* tc1 = false, tc2 = false */
-				DUK_DDD(DUK_DDDPRINT("tc1=false, tc2=false: output d --> %ld (k=%ld)",
-				                     (long) d, (long) nc_ctx->k));
-				DUK__DRAGON4_OUTPUT_PREINC(nc_ctx, count, d);
+			carry = (tmp2 < tmp1 ? 1U : 0U);
+		}
 
-				/* r <- r    (updated above: r <- (remainder (* r B) s)
-				 * s <- s
-				 * m+ <- m+  (updated above: m+ <- (* m+ B)
-				 * m- <- m-  (updated above: m- <- (* m- B)
-				 * B, low_ok, high_ok are fixed
-				 */
+		x->v[i] = tmp2;
+	}
+	if (carry) {
+		DUK_ASSERT(i < DUK__BI_MAX_PARTS);
+		DUK_ASSERT(carry == 1U);
+		x->v[i++] = carry;
+	}
+	x->n = i;
+	DUK_ASSERT(x->n <= DUK__BI_MAX_PARTS);
 
-				/* fall through and continue for-loop */
-			}
-		}
+	/* no need to normalize */
+	DUK_ASSERT(duk__bi_is_valid(x));
+}
+#endif  /* DUK_USE_64BIT_OPS */
 
-		/* fixed-format termination conditions */
-		if (nc_ctx->is_fixed) {
-			if (nc_ctx->abs_pos) {
-				int pos = nc_ctx->k - count + 1;  /* count is already incremented, take into account */
-				DUK_DDD(DUK_DDDPRINT("fixed format, absolute: abs pos=%ld, k=%ld, count=%ld, req=%ld",
-				                     (long) pos, (long) nc_ctx->k, (long) count, (long) nc_ctx->req_digits));
-				if (pos <= nc_ctx->req_digits) {
-					DUK_DDD(DUK_DDDPRINT("digit position reached req_digits, end generate loop"));
-					break;
-				}
-			} else {
-				DUK_DDD(DUK_DDDPRINT("fixed format, relative: k=%ld, count=%ld, req=%ld",
-				                     (long) nc_ctx->k, (long) count, (long) nc_ctx->req_digits));
-				if (count >= nc_ctx->req_digits) {
-					DUK_DDD(DUK_DDDPRINT("digit count reached req_digits, end generate loop"));
-					break;
-				}
-			}
-		}
-	}  /* for */
+/* x <- y + z */
+DUK_LOCAL void duk__bi_add_small(duk__bigint *x, duk__bigint *y, duk_uint32_t z) {
+	duk__bigint tmp;
 
-	nc_ctx->count = count;
+	DUK_ASSERT(duk__bi_is_valid(y));
 
-	DUK_DDD(DUK_DDDPRINT("generate finished"));
+	/* XXX: this could be optimized; there is only one call site now though */
+	duk__bi_set_small(&tmp, z);
+	duk__bi_add(x, y, &tmp);
 
-#ifdef DUK_USE_DDDPRINT
-	{
-		duk_uint8_t buf[2048];
-		duk_small_int_t i, t;
-		DUK_MEMZERO(buf, sizeof(buf));
-		for (i = 0; i < nc_ctx->count; i++) {
-			t = nc_ctx->digits[i];
-			if (t < 0 || t > 36) {
-				buf[i] = (duk_uint8_t) '?';
-			} else {
-				buf[i] = (duk_uint8_t) DUK__DIGITCHAR(t);
-			}
-		}
-		DUK_DDD(DUK_DDDPRINT("-> generated digits; k=%ld, digits='%s'",
-		                     (long) nc_ctx->k, (const char *) buf));
-	}
-#endif
+	DUK_ASSERT(duk__bi_is_valid(x));
 }
 
-/* Round up digits to a given position.  If position is out-of-bounds,
- * does nothing.  If carry propagates over the first digit, a '1' is
- * prepended to digits and 'k' will be updated.  Return value indicates
- * whether carry propagated over the first digit.
- *
- * Note that nc_ctx->count is NOT updated based on the rounding position
- * (it is updated only if carry overflows over the first digit and an
- * extra digit is prepended).
- */
-static duk_small_int_t duk__dragon4_fixed_format_round(duk__numconv_stringify_ctx *nc_ctx, duk_small_int_t round_idx) {
-	duk_small_int_t t;
-	duk_uint8_t *p;
-	duk_uint8_t roundup_limit;
-	duk_small_int_t ret = 0;
+#if 0  /* unused */
+/* x <- x + y, use t as temp */
+DUK_LOCAL void duk__bi_add_copy(duk__bigint *x, duk__bigint *y, duk__bigint *t) {
+	duk__bi_add(t, x, y);
+	duk__bi_copy(x, t);
+}
+#endif
 
-	/*
-	 *  round_idx points to the digit which is considered for rounding; the
-	 *  digit to its left is the final digit of the rounded value.  If round_idx
-	 *  is zero, rounding will be performed; the result will either be an empty
-	 *  rounded value or if carry happens a '1' digit is generated.
-	 */
+/* x <- y - z, require x >= y => z >= 0, i.e. y >= z */
+#ifdef DUK_USE_64BIT_OPS
+DUK_LOCAL void duk__bi_sub(duk__bigint *x, duk__bigint *y, duk__bigint *z) {
+	duk_small_int_t i, ny, nz;
+	duk_uint32_t ty, tz;
+	duk_int64_t tmp;
 
-	if (round_idx >= nc_ctx->count) {
-		DUK_DDD(DUK_DDDPRINT("round_idx out of bounds (%ld >= %ld (count)) -> no rounding",
-		                     (long) round_idx, (long) nc_ctx->count));
-		return 0;
-	} else if (round_idx < 0) {
-		DUK_DDD(DUK_DDDPRINT("round_idx out of bounds (%ld < 0) -> no rounding",
-		                     (long) round_idx));
-		return 0;
+	DUK_ASSERT(duk__bi_is_valid(y));
+	DUK_ASSERT(duk__bi_is_valid(z));
+	DUK_ASSERT(duk__bi_compare(y, z) >= 0);
+	DUK_ASSERT(y->n >= z->n);
+
+	ny = y->n; nz = z->n;
+	tmp = 0;
+	for (i = 0; i < ny; i++) {
+		ty = y->v[i];
+		if (i < nz) {
+			tz = z->v[i];
+		} else {
+			tz = 0;
+		}
+		tmp = (duk_int64_t) ty - (duk_int64_t) tz + tmp;
+		x->v[i] = (duk_uint32_t) (tmp & 0xffffffffUL);
+		tmp = tmp >> 32;  /* 0 or -1 */
 	}
+	DUK_ASSERT(tmp == 0);
 
-	/*
-	 *  Round-up limit.
-	 *
-	 *  For even values, divides evenly, e.g. 10 -> roundup_limit=5.
-	 *
-	 *  For odd values, rounds up, e.g. 3 -> roundup_limit=2.
-	 *  If radix is 3, 0/3 -> down, 1/3 -> down, 2/3 -> up.
-	 */
-	roundup_limit = (duk_uint8_t) ((nc_ctx->B + 1) / 2);
+	x->n = i;
+	duk__bi_normalize(x);  /* need to normalize, may even cancel to 0 */
+	DUK_ASSERT(duk__bi_is_valid(x));
+}
+#else
+DUK_LOCAL void duk__bi_sub(duk__bigint *x, duk__bigint *y, duk__bigint *z) {
+	duk_small_int_t i, ny, nz;
+	duk_uint32_t tmp1, tmp2, borrow;
 
-	p = &nc_ctx->digits[round_idx];
-	if (*p >= roundup_limit) {
-		DUK_DDD(DUK_DDDPRINT("fixed-format rounding carry required"));
-		/* carry */
-		for (;;) {
-			*p = 0;
-			if (p == &nc_ctx->digits[0]) {
-				DUK_DDD(DUK_DDDPRINT("carry propagated to first digit -> special case handling"));
-				DUK_MEMMOVE((void *) (&nc_ctx->digits[1]),
-				            (void *) (&nc_ctx->digits[0]),
-				            (size_t) (sizeof(char) * nc_ctx->count));
-				nc_ctx->digits[0] = 1;  /* don't increase 'count' */
-				nc_ctx->k++;  /* position of highest digit changed */
-				nc_ctx->count++;  /* number of digits changed */
-				ret = 1;
-				break;
-			}
+	DUK_ASSERT(duk__bi_is_valid(y));
+	DUK_ASSERT(duk__bi_is_valid(z));
+	DUK_ASSERT(duk__bi_compare(y, z) >= 0);
+	DUK_ASSERT(y->n >= z->n);
 
-			DUK_DDD(DUK_DDDPRINT("fixed-format rounding carry: B=%ld, roundup_limit=%ld, p=%p, digits=%p",
-			                     (long) nc_ctx->B, (long) roundup_limit, (void *) p, (void *) nc_ctx->digits));
-			p--;
-			t = *p;
-			DUK_DDD(DUK_DDDPRINT("digit before carry: %ld", (long) t));
-			if (++t < nc_ctx->B) {
-				DUK_DDD(DUK_DDDPRINT("rounding carry terminated"));
-				*p = t;
-				break;
-			}
+	ny = y->n; nz = z->n;
+	borrow = 0U;
+	for (i = 0; i < ny; i++) {
+		/* Borrow is detected based on wrapping which relies on exact 32-bit
+		 * types.
+		 */
+		tmp1 = y->v[i];
+		tmp2 = tmp1;
+		if (i < nz) {
+			tmp2 -= z->v[i];
+		}
 
-			DUK_DDD(DUK_DDDPRINT("wraps, carry to next digit"));
+		/* Careful with borrow condition:
+		 *  - If borrow not subtracted: 0x12345678 - 0 - 0xffffffff = 0x12345679 (> 0x12345678)
+		 *  - If borrow subtracted:     0x12345678 - 1 - 0xffffffff = 0x12345678 (== 0x12345678)
+		 */
+		if (borrow) {
+			tmp2--;
+			borrow = (tmp2 >= tmp1 ? 1U : 0U);
+		} else {
+			borrow = (tmp2 > tmp1 ? 1U : 0U);
 		}
+
+		x->v[i] = tmp2;
 	}
+	DUK_ASSERT(borrow == 0U);
 
-	return ret;
+	x->n = i;
+	duk__bi_normalize(x);  /* need to normalize, may even cancel to 0 */
+	DUK_ASSERT(duk__bi_is_valid(x));
 }
+#endif
 
-#define DUK__NO_EXP  (65536)  /* arbitrary marker, outside valid exp range */
+#if 0  /* unused */
+/* x <- y - z */
+DUK_LOCAL void duk__bi_sub_small(duk__bigint *x, duk__bigint *y, duk_uint32_t z) {
+	duk__bigint tmp;
 
-static void duk__dragon4_convert_and_push(duk__numconv_stringify_ctx *nc_ctx,
-                                          duk_context *ctx,
-                                          duk_small_int_t radix,
-                                          duk_small_int_t digits,
-                                          duk_small_uint_t flags,
-                                          duk_small_int_t neg) {
-	duk_small_int_t k;
-	duk_small_int_t pos, pos_end;
-	duk_small_int_t exp;
-	duk_small_int_t dig;
-	duk_uint8_t *q;
-	duk_uint8_t *buf;
+	DUK_ASSERT(duk__bi_is_valid(y));
 
-	/*
-	 *  The string conversion here incorporates all the necessary Ecmascript
-	 *  semantics without attempting to be generic.  nc_ctx->digits contains
-	 *  nc_ctx->count digits (>= 1), with the topmost digit's 'position'
-	 *  indicated by nc_ctx->k as follows:
-	 *
-	 *    digits="123" count=3 k=0   -->   0.123
-	 *    digits="123" count=3 k=1   -->   1.23
-	 *    digits="123" count=3 k=5   -->   12300
-	 *    digits="123" count=3 k=-1  -->   0.0123
-	 *
-	 *  Note that the identifier names used for format selection are different
-	 *  in Burger-Dybvig paper and Ecmascript specification (quite confusingly
-	 *  so, because e.g. 'k' has a totally different meaning in each).  See
-	 *  documentation for discussion.
-	 *
-	 *  Ecmascript doesn't specify any specific behavior for format selection
-	 *  (e.g. when to use exponent notation) for non-base-10 numbers.
-	 *
-	 *  The bigint space in the context is reused for string output, as there
-	 *  is more than enough space for that (>1kB at the moment), and we avoid
-	 *  allocating even more stack.
-	 */
+	/* XXX: this could be optimized */
+	duk__bi_set_small(&tmp, z);
+	duk__bi_sub(x, y, &tmp);
 
-	DUK_ASSERT(DUK__NUMCONV_CTX_BIGINTS_SIZE >= DUK__MAX_FORMATTED_LENGTH);
-	DUK_ASSERT(nc_ctx->count >= 1);
+	DUK_ASSERT(duk__bi_is_valid(x));
+}
+#endif
 
-	k = nc_ctx->k;
-	buf = (duk_uint8_t *) &nc_ctx->f;  /* XXX: union would be more correct */
-	q = buf;
+/* x <- x - y, use t as temp */
+DUK_LOCAL void duk__bi_sub_copy(duk__bigint *x, duk__bigint *y, duk__bigint *t) {
+	duk__bi_sub(t, x, y);
+	duk__bi_copy(x, t);
+}
 
-	/* Exponent handling: if exponent format is used, record exponent value and
-	 * fake k such that one leading digit is generated (e.g. digits=123 -> "1.23").
-	 *
-	 * toFixed() prevents exponent use; otherwise apply a set of criteria to
-	 * match the other API calls (toString(), toPrecision, etc).
-	 */
+/* x <- y * z */
+DUK_LOCAL void duk__bi_mul(duk__bigint *x, duk__bigint *y, duk__bigint *z) {
+	duk_small_int_t i, j, nx, nz;
 
-	exp = DUK__NO_EXP;
-	if (!nc_ctx->abs_pos /* toFixed() */) {
-		if ((flags & DUK_N2S_FLAG_FORCE_EXP) ||             /* exponential notation forced */
-		    ((flags & DUK_N2S_FLAG_NO_ZERO_PAD) &&          /* fixed precision and zero padding would be required */
-	             (k - digits >= 1)) ||                          /* (e.g. k=3, digits=2 -> "12X") */
-		    ((k > 21 || k <= -6) && (radix == 10))) {       /* toString() conditions */
-			DUK_DDD(DUK_DDDPRINT("use exponential notation: k=%ld -> exp=%ld",
-			                     (long) k, (long) (k - 1)));
-			exp = k - 1;  /* e.g. 12.3 -> digits="123" k=2 -> 1.23e1 */
-			k = 1;  /* generate mantissa with a single leading whole number digit */
-		}
-	}
+	DUK_ASSERT(duk__bi_is_valid(y));
+	DUK_ASSERT(duk__bi_is_valid(z));
 
-	if (neg) {
-		*q++ = '-';
-	}
+	nx = y->n + z->n;  /* max possible */
+	DUK_ASSERT(nx <= DUK__BI_MAX_PARTS);
 
-	/* Start position (inclusive) and end position (exclusive) */
-	pos = (k >= 1 ? k : 1);
-	if (nc_ctx->is_fixed) {
-		if (nc_ctx->abs_pos) {
-			/* toFixed() */
-			pos_end = -digits;
-		} else {
-			pos_end = k - digits;
-		}
-	} else {
-		pos_end = k - nc_ctx->count;
-	}
-	if (pos_end > 0) {
-		pos_end = 0;
+	if (nx == 0) {
+		/* Both inputs are zero; cases where only one is zero can go
+		 * through main algorithm.
+		 */
+		x->n = 0;
+		return;
 	}
 
-	DUK_DDD(DUK_DDDPRINT("exp=%ld, k=%ld, count=%ld, pos=%ld, pos_end=%ld, is_fixed=%ld, "
-	                     "digits=%ld, abs_pos=%ld",
-	                     (long) exp, (long) k, (long) nc_ctx->count, (long) pos, (long) pos_end,
-	                     (long) nc_ctx->is_fixed, (long) digits, (long) nc_ctx->abs_pos));
+	DUK_MEMZERO((void *) x->v, (size_t) (sizeof(duk_uint32_t) * nx));
+	x->n = nx;
 
-	/* Digit generation */
-	while (pos > pos_end) {
-		DUK_DDD(DUK_DDDPRINT("digit generation: pos=%ld, pos_end=%ld",
-		                     (long) pos, (long) pos_end));
-		if (pos == 0) {
-			*q++ = (duk_uint8_t) '.';
+	nz = z->n;
+	for (i = 0; i < y->n; i++) {
+#ifdef DUK_USE_64BIT_OPS
+		duk_uint64_t tmp = 0U;
+		for (j = 0; j < nz; j++) {
+			tmp += (duk_uint64_t) y->v[i] * (duk_uint64_t) z->v[j] + x->v[i+j];
+			x->v[i+j] = (duk_uint32_t) (tmp & 0xffffffffUL);
+			tmp = tmp >> 32;
+		}
+		if (tmp > 0) {
+			DUK_ASSERT(i + j < nx);
+			DUK_ASSERT(i + j < DUK__BI_MAX_PARTS);
+			DUK_ASSERT(x->v[i+j] == 0U);
+			x->v[i+j] = (duk_uint32_t) tmp;
 		}
-		if (pos > k) {
-			*q++ = (duk_uint8_t) '0';
-		} else if (pos <= k - nc_ctx->count) {
-			*q++ = (duk_uint8_t) '0';
-		} else {
-			dig = nc_ctx->digits[k - pos];
-			DUK_ASSERT(dig >= 0 && dig < nc_ctx->B);
-			*q++ = (duk_uint8_t) DUK__DIGITCHAR(dig);
-		} 
-
-		pos--;
-	}
-	DUK_ASSERT(pos <= 1);
-
-	/* Exponent */
-	if (exp != DUK__NO_EXP) {
+#else
 		/*
-		 *  Exponent notation for non-base-10 numbers isn't specified in Ecmascript
-		 *  specification, as it never explicitly turns up: non-decimal numbers can
-		 *  only be formatted with Number.prototype.toString([radix]) and for that,
-		 *  behavior is not explicitly specified.
+		 *  Multiply + add + carry for 32-bit components using only 16x16->32
+		 *  multiplies and carry detection based on unsigned overflow.
 		 *
-		 *  Logical choices include formatting the exponent as decimal (e.g. binary
-		 *  100000 as 1e+5) or in current radix (e.g. binary 100000 as 1e+101).
-		 *  The Dragon4 algorithm (in the original paper) prints the exponent value
-		 *  in the target radix B.  However, for radix values 15 and above, the
-		 *  exponent separator 'e' is no longer easily parseable.  Consider, for
-		 *  instance, the number "1.faecee+1c".
+		 *    1st mult, 32-bit: (A*2^16 + B)
+		 *    2nd mult, 32-bit: (C*2^16 + D)
+		 *    3rd add, 32-bit: E
+		 *    4th add, 32-bit: F
+		 *
+		 *      (AC*2^16 + B) * (C*2^16 + D) + E + F
+		 *    = AC*2^32 + AD*2^16 + BC*2^16 + BD + E + F
+		 *    = AC*2^32 + (AD + BC)*2^16 + (BD + E + F)
+		 *    = AC*2^32 + AD*2^16 + BC*2^16 + (BD + E + F)
 		 */
+		duk_uint32_t a, b, c, d, e, f;
+		duk_uint32_t r, s, t;
 
-		duk_size_t len;
-		char exp_sign;
+		a = y->v[i]; b = a & 0xffffUL; a = a >> 16;
 
-		*q++ = 'e';
-		if (exp >= 0) {
-			exp_sign = '+';
-		} else {
-			exp_sign = '-';
-			exp = -exp;
-		}
-		*q++ = (duk_uint8_t) exp_sign;
-		len = duk__dragon4_format_uint32(q, (duk_uint32_t) exp, radix);
-		q += len;
-	}
+		f = 0;
+		for (j = 0; j < nz; j++) {
+			c = z->v[j]; d = c & 0xffffUL; c = c >> 16;
+			e = x->v[i+j];
 
-	duk_push_lstring(ctx, (const char *) buf, (size_t) (q - buf));
-}
+			/* build result as: (r << 32) + s: start with (BD + E + F) */
+			r = 0;
+			s = b * d;
 
-/*
- *  Conversion helpers
- */
+			/* add E */
+			t = s + e;
+			if (t < s) { r++; }  /* carry */
+			s = t;
 
-static void duk__dragon4_double_to_ctx(duk__numconv_stringify_ctx *nc_ctx, duk_double_t x) {
-	duk_double_union u;
-	duk_uint32_t tmp;
-	duk_small_int_t exp;
+			/* add F */
+			t = s + f;
+			if (t < s) { r++; }  /* carry */
+			s = t;
 
-	/*
-	 *    seeeeeee eeeeffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff
-	 *       A        B        C        D        E        F        G        H
-	 *
-	 *    s       sign bit
-	 *    eee...  exponent field
-	 *    fff...  fraction
-	 *
-	 *    ieee value = 1.ffff... * 2^(e - 1023)  (normal)
-	 *               = 0.ffff... * 2^(-1022)     (denormal)
-	 *
-	 *    algorithm v = f * b^e
-	 */
+			/* add BC*2^16 */
+			t = b * c;
+			r += (t >> 16);
+			t = s + ((t & 0xffffUL) << 16);
+			if (t < s) { r++; }  /* carry */
+			s = t;
 
-	DUK_DBLUNION_SET_DOUBLE(&u, x);
+			/* add AD*2^16 */
+			t = a * d;
+			r += (t >> 16);
+			t = s + ((t & 0xffffUL) << 16);
+			if (t < s) { r++; }  /* carry */
+			s = t;
 
-	nc_ctx->f.n = 2;
+			/* add AC*2^32 */
+			t = a * c;
+			r += t;
 
-	tmp = DUK_DBLUNION_GET_LOW32(&u);
-	nc_ctx->f.v[0] = tmp;
-	tmp = DUK_DBLUNION_GET_HIGH32(&u);
-	nc_ctx->f.v[1] = tmp & 0x000fffffUL;
-	exp = (duk_small_int_t) ((tmp >> 20) & 0x07ffUL);
+			DUK_DDD(DUK_DDDPRINT("ab=%08lx cd=%08lx ef=%08lx -> rs=%08lx %08lx",
+			                     (unsigned long) y->v[i], (unsigned long) z->v[j],
+			                     (unsigned long) x->v[i+j], (unsigned long) r,
+			                     (unsigned long) s));
 
-	if (exp == 0) {
-		/* denormal */
-		exp = DUK__IEEE_DOUBLE_EXP_MIN - 52;
-		duk__bi_normalize(&nc_ctx->f);
-	} else {
-		/* normal: implicit leading 1-bit */
-		nc_ctx->f.v[1] |= 0x00100000UL;
-		exp = exp - DUK__IEEE_DOUBLE_EXP_BIAS - 52;
-		DUK_ASSERT(duk__bi_is_valid(&nc_ctx->f));  /* true, because v[1] has at least one bit set */
+			x->v[i+j] = s;
+			f = r;
+		}
+		if (f > 0U) {
+			DUK_ASSERT(i + j < nx);
+			DUK_ASSERT(i + j < DUK__BI_MAX_PARTS);
+			DUK_ASSERT(x->v[i+j] == 0U);
+			x->v[i+j] = (duk_uint32_t) f;
+		}
+#endif  /* DUK_USE_64BIT_OPS */
 	}
 
-	DUK_ASSERT(duk__bi_is_valid(&nc_ctx->f));
+	duk__bi_normalize(x);
+	DUK_ASSERT(duk__bi_is_valid(x));
+}
+
+/* x <- y * z */
+DUK_LOCAL void duk__bi_mul_small(duk__bigint *x, duk__bigint *y, duk_uint32_t z) {
+	duk__bigint tmp;
 
-	nc_ctx->e = exp;
+	DUK_ASSERT(duk__bi_is_valid(y));
+
+	/* XXX: this could be optimized */
+	duk__bi_set_small(&tmp, z);
+	duk__bi_mul(x, y, &tmp);
+
+	DUK_ASSERT(duk__bi_is_valid(x));
 }
 
-void duk__dragon4_ctx_to_double(duk__numconv_stringify_ctx *nc_ctx, duk_double_t *x) {
-	duk_double_union u;
-	duk_small_int_t exp;
-	duk_small_int_t i;
-	duk_small_int_t bitstart;
-	duk_small_int_t bitround;
-	duk_small_int_t bitidx;
-	duk_small_int_t skip_round;
-	duk_uint32_t t, v;
+/* x <- x * y, use t as temp */
+DUK_LOCAL void duk__bi_mul_copy(duk__bigint *x, duk__bigint *y, duk__bigint *t) {
+	duk__bi_mul(t, x, y);
+	duk__bi_copy(x, t);
+}
 
-	DUK_ASSERT(nc_ctx->count == 53 + 1);
+/* x <- x * y, use t as temp */
+DUK_LOCAL void duk__bi_mul_small_copy(duk__bigint *x, duk_uint32_t y, duk__bigint *t) {
+	duk__bi_mul_small(t, x, y);
+	duk__bi_copy(x, t);
+}
 
-	/* Sometimes this assert is not true right now; it will be true after
-	 * rounding.  See: test-bug-numconv-mantissa-assert.js.
-	 */
-	DUK_ASSERT_DISABLE(nc_ctx->digits[0] == 1);  /* zero handled by caller */
+DUK_LOCAL int duk__bi_is_even(duk__bigint *x) {
+	DUK_ASSERT(duk__bi_is_valid(x));
+	return (x->n == 0) || ((x->v[0] & 0x01) == 0);
+}
 
-	/* Should not be required because the code below always sets both high
-	 * and low parts, but at least gcc-4.4.5 fails to deduce this correctly
-	 * (perhaps because the low part is set (seemingly) conditionally in a
-	 * loop), so this is here to avoid the bogus warning.
-	 */
-	DUK_MEMZERO((void *) &u, sizeof(u));
+DUK_LOCAL int duk__bi_is_zero(duk__bigint *x) {
+	DUK_ASSERT(duk__bi_is_valid(x));
+	return (x->n == 0);  /* this is the case for normalized numbers */
+}
 
-	/*
-	 *  Figure out how generated digits match up with the mantissa,
-	 *  and then perform rounding.  If mantissa overflows, need to
-	 *  recompute the exponent (it is bumped and may overflow to
-	 *  infinity).
-	 *
-	 *  For normal numbers the leading '1' is hidden and ignored,
-	 *  and the last bit is used for rounding:
-	 *
-	 *                          rounding pt
-	 *       <--------52------->|
-	 *     1 x x x x ... x x x x|y  ==>  x x x x ... x x x x
-	 *
-	 *  For denormals, the leading '1' is included in the number,
-	 *  and the rounding point is different:
-	 *
-	 *                      rounding pt
-	 *     <--52 or less--->|
-	 *     1 x x x x ... x x|x x y  ==>  0 0 ... 1 x x ... x x
-	 *
-	 *  The largest denormals will have a mantissa beginning with
-	 *  a '1' (the explicit leading bit); smaller denormals will
-	 *  have leading zero bits.
-	 *
-	 *  If the exponent would become too high, the result becomes
-	 *  Infinity.  If the exponent is so small that the entire
-	 *  mantissa becomes zero, the result becomes zero.
-	 *
-	 *  Note: the Dragon4 'k' is off-by-one with respect to the IEEE
-	 *  exponent.  For instance, k==0 indicates that the leading '1'
-	 *  digit is at the first binary fraction position (0.1xxx...);
-	 *  the corresponding IEEE exponent would be -1.
-	 */
+/* Bigint is 2^52.  Used to detect normalized IEEE double mantissa values
+ * which are at the lowest edge (next floating point value downwards has
+ * a different exponent).  The lowest mantissa has the form:
+ *
+ *     1000........000    (52 zeroes; only "hidden bit" is set)
+ */
+DUK_LOCAL duk_small_int_t duk__bi_is_2to52(duk__bigint *x) {
+	DUK_ASSERT(duk__bi_is_valid(x));
+	return (duk_small_int_t)
+	        (x->n == 2) && (x->v[0] == 0U) && (x->v[1] == (1U << (52-32)));
+}
 
-	skip_round = 0;
+/* x <- (1<<y) */
+DUK_LOCAL void duk__bi_twoexp(duk__bigint *x, duk_small_int_t y) {
+	duk_small_int_t n, r;
 
- recheck_exp:
+	n = (y / 32) + 1;
+	DUK_ASSERT(n > 0);
+	r = y % 32;
+	DUK_MEMZERO((void *) x->v, sizeof(duk_uint32_t) * n);
+	x->n = n;
+	x->v[n - 1] = (((duk_uint32_t) 1) << r);
+}
 
-	exp = nc_ctx->k - 1;   /* IEEE exp without bias */
-	if (exp > 1023) {
-		/* Infinity */
-		bitstart = -255;  /* needed for inf: causes mantissa to become zero,
-		                   * and rounding to be skipped.
-		                   */
-		exp = 2047;
-	} else if (exp >= -1022) {
-		/* normal */
-		bitstart = 1;  /* skip leading digit */
-		exp += DUK__IEEE_DOUBLE_EXP_BIAS;
-		DUK_ASSERT(exp >= 1 && exp <= 2046);
-	} else {
-		/* denormal or zero */
-		bitstart = 1023 + exp;  /* exp==-1023 -> bitstart=0 (leading 1);
-		                         * exp==-1024 -> bitstart=-1 (one left of leading 1), etc
-		                         */
-		exp = 0;
-	}
-	bitround = bitstart + 52;
+/* x <- b^y; use t1 and t2 as temps */
+DUK_LOCAL void duk__bi_exp_small(duk__bigint *x, duk_small_int_t b, duk_small_int_t y, duk__bigint *t1, duk__bigint *t2) {
+	/* Fast path the binary case */
 
-	DUK_DDD(DUK_DDDPRINT("ieee exp=%ld, bitstart=%ld, bitround=%ld",
-	                     (long) exp, (long) bitstart, (long) bitround));
+	DUK_ASSERT(x != t1 && x != t2 && t1 != t2);  /* distinct bignums, easy mistake to make */
+	DUK_ASSERT(b >= 0);
+	DUK_ASSERT(y >= 0);
 
-	if (!skip_round) {
-		if (duk__dragon4_fixed_format_round(nc_ctx, bitround)) {
-			/* Corner case: see test-numconv-parse-mant-carry.js.  We could
-			 * just bump the exponent and update bitstart, but it's more robust
-			 * to recompute (but avoid rounding twice).
-			 */
-			DUK_DDD(DUK_DDDPRINT("rounding caused exponent to be bumped, recheck exponent"));
-			skip_round = 1;
-			goto recheck_exp;
-		}
+	if (b == 2) {
+		duk__bi_twoexp(x, y);
+		return;
 	}
 
-	/*
-	 *  Create mantissa
-	 */
+	/* http://en.wikipedia.org/wiki/Exponentiation_by_squaring */
 
-	t = 0;
-	for (i = 0; i < 52; i++) {
-		bitidx = bitstart + 52 - 1 - i;
-		if (bitidx >= nc_ctx->count) {
-			v = 0;
-		} else if (bitidx < 0) {
-			v = 0;
-		} else {
-			v = nc_ctx->digits[bitidx];
+	DUK_DDD(DUK_DDDPRINT("exp_small: b=%ld, y=%ld", (long) b, (long) y));
+
+	duk__bi_set_small(x, 1);
+	duk__bi_set_small(t1, b);
+	for (;;) {
+		/* Loop structure ensures that we don't compute t1^2 unnecessarily
+		 * on the final round, as that might create a bignum exceeding the
+		 * current DUK__BI_MAX_PARTS limit.
+		 */
+		if (y & 0x01) {
+			duk__bi_mul_copy(x, t1, t2);
 		}
-		DUK_ASSERT(v == 0 || v == 1);
-		t += v << (i % 32);
-		if (i == 31) {
-			/* low 32 bits is complete */
-			DUK_DBLUNION_SET_LOW32(&u, t);
-			t = 0;
+		y = y >> 1;
+		if (y == 0) {
+			break;
 		}
+		duk__bi_mul_copy(t1, t1, t2);
 	}
-	/* t has high mantissa */
-
-	DUK_DDD(DUK_DDDPRINT("mantissa is complete: %08lx %08lx",
-	                     (unsigned long) t,
-	                     (unsigned long) DUK_DBLUNION_GET_LOW32(&u)));
-
-	DUK_ASSERT(exp >= 0 && exp <= 0x7ffL);
-	t += exp << 20;
-#if 0  /* caller handles sign change */
-	if (negative) {
-		t |= 0x80000000U;
-	}
-#endif
-	DUK_DBLUNION_SET_HIGH32(&u, t);
 
-	DUK_DDD(DUK_DDDPRINT("number is complete: %08lx %08lx",
-	                     (unsigned long) DUK_DBLUNION_GET_HIGH32(&u),
-	                     (unsigned long) DUK_DBLUNION_GET_LOW32(&u)));
-
-	*x = DUK_DBLUNION_GET_DOUBLE(&u);
+	DUK__BI_PRINT("exp_small result", x);
 }
 
 /*
- *  Exposed number-to-string API
+ *  A Dragon4 number-to-string variant, based on:
  *
- *  Input: [ number ]
- *  Output: [ string ]
+ *    Guy L. Steele Jr., Jon L. White: "How to Print Floating-Point Numbers
+ *    Accurately"
+ *
+ *    Robert G. Burger, R. Kent Dybvig: "Printing Floating-Point Numbers
+ *    Quickly and Accurately"
+ *
+ *  The current algorithm is based on Figure 1 of the Burger-Dybvig paper,
+ *  i.e. the base implementation without logarithm estimation speedups
+ *  (these would increase code footprint considerably).  Fixed-format output
+ *  does not follow the suggestions in the paper; instead, we generate an
+ *  extra digit and round-with-carry.
+ *
+ *  The same algorithm is used for number parsing (with b=10 and B=2)
+ *  by generating one extra digit and doing rounding manually.
+ *
+ *  See doc/number-conversion.rst for limitations.
  */
 
-void duk_numconv_stringify(duk_context *ctx, duk_small_int_t radix, duk_small_int_t digits, duk_small_uint_t flags) {
-	duk_double_t x;
-	duk_small_int_t c;
-	duk_small_int_t neg;
-	duk_uint32_t uval;
-	duk__numconv_stringify_ctx nc_ctx_alloc;  /* large context; around 2kB now */
-	duk__numconv_stringify_ctx *nc_ctx = &nc_ctx_alloc;
+/* Maximum number of digits generated. */
+#define DUK__MAX_OUTPUT_DIGITS          1040  /* (Number.MAX_VALUE).toString(2).length == 1024, + spare */
 
-	x = (duk_double_t) duk_require_number(ctx, -1);
-	duk_pop(ctx);
+/* Maximum number of characters in formatted value. */
+#define DUK__MAX_FORMATTED_LENGTH       1040  /* (-Number.MAX_VALUE).toString(2).length == 1025, + spare */
 
-	/*
-	 *  Handle special cases (NaN, infinity, zero).
+/* Number and (minimum) size of bigints in the nc_ctx structure. */
+#define DUK__NUMCONV_CTX_NUM_BIGINTS    7
+#define DUK__NUMCONV_CTX_BIGINTS_SIZE   (sizeof(duk__bigint) * DUK__NUMCONV_CTX_NUM_BIGINTS)
+
+typedef struct {
+	/* Currently about 7*152 = 1064 bytes.  The space for these
+	 * duk__bigints is used also as a temporary buffer for generating
+	 * the final string.  This is a bit awkard; a union would be
+	 * more correct.
 	 */
+	duk__bigint f, r, s, mp, mm, t1, t2;
 
-	c = (duk_small_int_t) DUK_FPCLASSIFY(x);
-	if (DUK_SIGNBIT((double) x)) {
-		x = -x;
-		neg = 1;
-	} else {
-		neg = 0;
-	}
+	duk_small_int_t is_s2n;        /* if 1, doing a string-to-number; else doing a number-to-string */
+	duk_small_int_t is_fixed;      /* if 1, doing a fixed format output (not free format) */
+	duk_small_int_t req_digits;    /* requested number of output digits; 0 = free-format */
+	duk_small_int_t abs_pos;       /* digit position is absolute, not relative */
+	duk_small_int_t e;             /* exponent for 'f' */
+	duk_small_int_t b;             /* input radix */
+	duk_small_int_t B;             /* output radix */
+	duk_small_int_t k;             /* see algorithm */
+	duk_small_int_t low_ok;        /* see algorithm */
+	duk_small_int_t high_ok;       /* see algorithm */
+	duk_small_int_t unequal_gaps;  /* m+ != m- (very rarely) */
 
-	/* NaN sign bit is platform specific with unpacked, un-normalized NaNs */
-	DUK_ASSERT(c == DUK_FP_NAN || DUK_SIGNBIT((double) x) == 0);
+	/* Buffer used for generated digits, values are in the range [0,B-1]. */
+	duk_uint8_t digits[DUK__MAX_OUTPUT_DIGITS];
+	duk_small_int_t count;  /* digit count */
+} duk__numconv_stringify_ctx;
 
-	if (c == DUK_FP_NAN) {
-		duk_push_hstring_stridx(ctx, DUK_STRIDX_NAN);
-		return;
-	} else if (c == DUK_FP_INFINITE) {
-		if (neg) {
-			/* -Infinity */
-			duk_push_hstring_stridx(ctx, DUK_STRIDX_MINUS_INFINITY);
-		} else {
-			/* Infinity */
-			duk_push_hstring_stridx(ctx, DUK_STRIDX_INFINITY);
-		}
-		return;
-	} else if (c == DUK_FP_ZERO) {
-		/* We can't shortcut zero here if it goes through special formatting
-		 * (such as forced exponential notation).
-		 */
-		;
-	}
+/* Note: computes with 'idx' in assertions, so caller beware.
+ * 'idx' is preincremented, i.e. '1' on first call, because it
+ * is more convenient for the caller.
+ */
+#define DUK__DRAGON4_OUTPUT_PREINC(nc_ctx,preinc_idx,x)  do { \
+		DUK_ASSERT((preinc_idx) - 1 >= 0); \
+		DUK_ASSERT((preinc_idx) - 1 < DUK__MAX_OUTPUT_DIGITS); \
+		((nc_ctx)->digits[(preinc_idx) - 1]) = (duk_uint8_t) (x); \
+	} while (0)
 
-	/*
-	 *  Handle integers in 32-bit range (that is, [-(2**32-1),2**32-1])
-	 *  specially, as they're very likely for embedded programs.  This
-	 *  is now done for all radix values.  We must be careful not to use
-	 *  the fast path when special formatting (e.g. forced exponential)
-	 *  is in force.
-	 *
-	 *  XXX: could save space by supporting radix 10 only and using
-	 *  sprintf "%lu" for the fast path and for exponent formatting.
+DUK_LOCAL duk_size_t duk__dragon4_format_uint32(duk_uint8_t *buf, duk_uint32_t x, duk_small_int_t radix) {
+	duk_uint8_t *p;
+	duk_size_t len;
+	duk_small_int_t dig;
+	duk_small_int_t t;
+
+	DUK_ASSERT(radix >= 2 && radix <= 36);
+
+	/* A 32-bit unsigned integer formats to at most 32 digits (the
+	 * worst case happens with radix == 2).  Output the digits backwards,
+	 * and use a memmove() to get them in the right place.
 	 */
 
-	uval = (unsigned int) x;
-	if (((double) uval) == x &&  /* integer number in range */
-	    flags == 0) {            /* no special formatting */
-		/* use bigint area as a temp */
-		duk_uint8_t *buf = (duk_uint8_t *) (&nc_ctx->f);
-		duk_uint8_t *p = buf;
+	p = buf + 32;
+	for (;;) {
+		t = x / radix;
+		dig = x - t * radix;
+		x = t;
 
-		DUK_ASSERT(DUK__NUMCONV_CTX_BIGINTS_SIZE >= 32 + 1);  /* max size: radix=2 + sign */
-		if (neg && uval != 0) {
-			/* no negative sign for zero */
-			*p++ = (duk_uint8_t) '-';
+		DUK_ASSERT(dig >= 0 && dig < 36);
+		*(--p) = DUK__DIGITCHAR(dig);
+
+		if (x == 0) {
+			break;
 		}
-		p += duk__dragon4_format_uint32(p, uval, radix);
-		duk_push_lstring(ctx, (const char *) buf, (duk_size_t) (p - buf));
-		return;
 	}
+	len = (duk_size_t) ((buf + 32) - p);
 
-	/*
-	 *  Dragon4 setup.
-	 *
-	 *  Convert double from IEEE representation for conversion;
-	 *  normal finite values have an implicit leading 1-bit.  The
-	 *  slow path algorithm doesn't handle zero, so zero is special
-	 *  cased here but still creates a valid nc_ctx, and goes
-	 *  through normal formatting in case special formatting has
-	 *  been requested (e.g. forced exponential format: 0 -> "0e+0").
-	 */
+	DUK_MEMMOVE((void *) buf, (const void *) p, (size_t) len);
 
-	/* Would be nice to bulk clear the allocation, but the context
-	 * is 1-2 kilobytes and nothing should rely on it being zeroed.
-	 */
-#if 0
-	DUK_MEMZERO((void *) nc_ctx, sizeof(*nc_ctx));  /* slow init, do only for slow path cases */
-#endif
+	return len;
+}
 
-	nc_ctx->is_s2n = 0;
-	nc_ctx->b = 2;
-	nc_ctx->B = radix;
-	nc_ctx->abs_pos = 0;
-	if (flags & DUK_N2S_FLAG_FIXED_FORMAT) {
-		nc_ctx->is_fixed = 1;
-		if (flags & DUK_N2S_FLAG_FRACTION_DIGITS) {
-			/* absolute req_digits; e.g. digits = 1 -> last digit is 0,
-			 * but add an extra digit for rounding.
-			 */
-			nc_ctx->abs_pos = 1;
-			nc_ctx->req_digits = (-digits + 1) - 1;
-		} else {
-			nc_ctx->req_digits = digits + 1;
-		}
-	} else {
-		nc_ctx->is_fixed = 0;
-		nc_ctx->req_digits = 0;
-	}
+DUK_LOCAL void duk__dragon4_prepare(duk__numconv_stringify_ctx *nc_ctx) {
+	duk_small_int_t lowest_mantissa;
 
-	if (c == DUK_FP_ZERO) {
-		/* Zero special case: fake requested number of zero digits; ensure
-		 * no sign bit is printed.  Relative and absolute fixed format
-		 * require separate handling.
-		 */
-		duk_small_int_t count;
-		if (nc_ctx->is_fixed) {
-			if (nc_ctx->abs_pos) {
-				count = digits + 2;  /* lead zero + 'digits' fractions + 1 for rounding */
-			} else {
-				count = digits + 1;  /* + 1 for rounding */
-			}
-		} else {
-			count = 1;
-		}
-		DUK_DDD(DUK_DDDPRINT("count=%ld", (long) count));
-		DUK_ASSERT(count >= 1);
-		DUK_MEMZERO((void *) nc_ctx->digits, count);
-		nc_ctx->count = count;
-		nc_ctx->k = 1;  /* 0.000... */
-		neg = 0;
-		goto zero_skip;
+#if 1
+	/* Assume IEEE round-to-even, so that shorter encoding can be used
+	 * when round-to-even would produce correct result.  By removing
+	 * this check (and having low_ok == high_ok == 0) the results would
+	 * still be accurate but in some cases longer than necessary.
+	 */
+	if (duk__bi_is_even(&nc_ctx->f)) {
+		DUK_DDD(DUK_DDDPRINT("f is even"));
+		nc_ctx->low_ok = 1;
+		nc_ctx->high_ok = 1;
+	} else {
+		DUK_DDD(DUK_DDDPRINT("f is odd"));
+		nc_ctx->low_ok = 0;
+		nc_ctx->high_ok = 0;
 	}
+#else
+	/* Note: not honoring round-to-even should work but now generates incorrect
+	 * results.  For instance, 1e23 serializes to "a000...", i.e. the first digit
+	 * equals the radix (10).  Scaling stops one step too early in this case.
+	 * Don't know why this is the case, but since this code path is unused, it
+	 * doesn't matter.
+	 */
+	nc_ctx->low_ok = 0;
+	nc_ctx->high_ok = 0;
+#endif
 
-	duk__dragon4_double_to_ctx(nc_ctx, x);   /* -> sets 'f' and 'e' */
-	DUK__BI_PRINT("f", &nc_ctx->f);
-	DUK_DDD(DUK_DDDPRINT("e=%ld", (long) nc_ctx->e));
-
-	/*
-	 *  Dragon4 slow path digit generation.
+	/* For string-to-number, pretend we never have the lowest mantissa as there
+	 * is no natural "precision" for inputs.  Having lowest_mantissa == 0, we'll
+	 * fall into the base cases for both e >= 0 and e < 0.
 	 */
+	if (nc_ctx->is_s2n) {
+		lowest_mantissa = 0;
+	} else {
+		lowest_mantissa = duk__bi_is_2to52(&nc_ctx->f);
+	}
 
-	duk__dragon4_prepare(nc_ctx);  /* setup many variables in nc_ctx */
+	nc_ctx->unequal_gaps = 0;
+	if (nc_ctx->e >= 0) {
+		/* exponent non-negative (and thus not minimum exponent) */
 
-	DUK_DDD(DUK_DDDPRINT("after prepare:"));
-	DUK__BI_PRINT("r", &nc_ctx->r);
-	DUK__BI_PRINT("s", &nc_ctx->s);
-	DUK__BI_PRINT("mp", &nc_ctx->mp);
-	DUK__BI_PRINT("mm", &nc_ctx->mm);
+		if (lowest_mantissa) {
+			/* (>= e 0) AND (= f (expt b (- p 1)))
+			 *
+			 * be <- (expt b e) == b^e
+			 * be1 <- (* be b) == (expt b (+ e 1)) == b^(e+1)
+			 * r <- (* f be1 2) == 2 * f * b^(e+1)    [if b==2 -> f * b^(e+2)]
+			 * s <- (* b 2)                           [if b==2 -> 4]
+			 * m+ <- be1 == b^(e+1)
+			 * m- <- be == b^e
+			 * k <- 0
+			 * B <- B
+			 * low_ok <- round
+			 * high_ok <- round
+			 */
 
-	duk__dragon4_scale(nc_ctx);
+			DUK_DDD(DUK_DDDPRINT("non-negative exponent (not smallest exponent); "
+			                     "lowest mantissa value for this exponent -> "
+			                     "unequal gaps"));
 
-	DUK_DDD(DUK_DDDPRINT("after scale; k=%ld", (long) nc_ctx->k));
-	DUK__BI_PRINT("r", &nc_ctx->r);
-	DUK__BI_PRINT("s", &nc_ctx->s);
-	DUK__BI_PRINT("mp", &nc_ctx->mp);
-	DUK__BI_PRINT("mm", &nc_ctx->mm);
+			duk__bi_exp_small(&nc_ctx->mm, nc_ctx->b, nc_ctx->e, &nc_ctx->t1, &nc_ctx->t2);  /* mm <- b^e */
+			duk__bi_mul_small(&nc_ctx->mp, &nc_ctx->mm, nc_ctx->b);  /* mp <- b^(e+1) */
+			duk__bi_mul_small(&nc_ctx->t1, &nc_ctx->f, 2);
+			duk__bi_mul(&nc_ctx->r, &nc_ctx->t1, &nc_ctx->mp);       /* r <- (2 * f) * b^(e+1) */
+			duk__bi_set_small(&nc_ctx->s, nc_ctx->b * 2);            /* s <- 2 * b */
+			nc_ctx->unequal_gaps = 1;
+		} else {
+			/* (>= e 0) AND (not (= f (expt b (- p 1))))
+			 *
+			 * be <- (expt b e) == b^e
+			 * r <- (* f be 2) == 2 * f * b^e    [if b==2 -> f * b^(e+1)]
+			 * s <- 2
+			 * m+ <- be == b^e
+			 * m- <- be == b^e
+			 * k <- 0
+			 * B <- B
+			 * low_ok <- round
+			 * high_ok <- round
+			 */
 
-	duk__dragon4_generate(nc_ctx);
+			DUK_DDD(DUK_DDDPRINT("non-negative exponent (not smallest exponent); "
+			                     "not lowest mantissa for this exponent -> "
+			                     "equal gaps"));
 
-	/*
-	 *  Convert and push final string.
-	 */
+			duk__bi_exp_small(&nc_ctx->mm, nc_ctx->b, nc_ctx->e, &nc_ctx->t1, &nc_ctx->t2);  /* mm <- b^e */
+			duk__bi_copy(&nc_ctx->mp, &nc_ctx->mm);                /* mp <- b^e */
+			duk__bi_mul_small(&nc_ctx->t1, &nc_ctx->f, 2);
+			duk__bi_mul(&nc_ctx->r, &nc_ctx->t1, &nc_ctx->mp);     /* r <- (2 * f) * b^e */
+			duk__bi_set_small(&nc_ctx->s, 2);                      /* s <- 2 */
+		}
+	} else {
+		/* When doing string-to-number, lowest_mantissa is always 0 so
+		 * the exponent check, while incorrect, won't matter.
+		 */
+		if (nc_ctx->e > DUK__IEEE_DOUBLE_EXP_MIN /*not minimum exponent*/ &&
+		    lowest_mantissa /* lowest mantissa for this exponent*/) {
+			/* r <- (* f b 2)                                [if b==2 -> (* f 4)]
+			 * s <- (* (expt b (- 1 e)) 2) == b^(1-e) * 2    [if b==2 -> b^(2-e)]
+			 * m+ <- b == 2
+			 * m- <- 1
+			 * k <- 0
+			 * B <- B
+			 * low_ok <- round
+			 * high_ok <- round
+			 */
 
- zero_skip:
+			DUK_DDD(DUK_DDDPRINT("negative exponent; not minimum exponent and "
+			                     "lowest mantissa for this exponent -> "
+			                     "unequal gaps"));
 
-	if (flags & DUK_N2S_FLAG_FIXED_FORMAT) {
-		/* Perform fixed-format rounding. */
-		duk_small_int_t roundpos;
-		if (flags & DUK_N2S_FLAG_FRACTION_DIGITS) {
-			/* 'roundpos' is relative to nc_ctx->k and increases to the right
-			 * (opposite of how 'k' changes).
-			 */
-			roundpos = -digits;  /* absolute position for digit considered for rounding */
-			roundpos = nc_ctx->k - roundpos;
-			
+			duk__bi_mul_small(&nc_ctx->r, &nc_ctx->f, nc_ctx->b * 2);  /* r <- (2 * b) * f */
+			duk__bi_exp_small(&nc_ctx->t1, nc_ctx->b, 1 - nc_ctx->e, &nc_ctx->s, &nc_ctx->t2);  /* NB: use 's' as temp on purpose */
+			duk__bi_mul_small(&nc_ctx->s, &nc_ctx->t1, 2);             /* s <- b^(1-e) * 2 */
+			duk__bi_set_small(&nc_ctx->mp, 2);
+			duk__bi_set_small(&nc_ctx->mm, 1);
+			nc_ctx->unequal_gaps = 1;
 		} else {
-			roundpos = digits;
-		}
-		DUK_DDD(DUK_DDDPRINT("rounding: k=%ld, count=%ld, digits=%ld, roundpos=%ld",
-		                     (long) nc_ctx->k, (long) nc_ctx->count, (long) digits, (long) roundpos));
-		(void) duk__dragon4_fixed_format_round(nc_ctx, roundpos);
+			/* r <- (* f 2)
+			 * s <- (* (expt b (- e)) 2) == b^(-e) * 2    [if b==2 -> b^(1-e)]
+			 * m+ <- 1
+			 * m- <- 1
+			 * k <- 0
+			 * B <- B
+			 * low_ok <- round
+			 * high_ok <- round
+			 */
 
-		/* Note: 'count' is currently not adjusted by rounding (i.e. the
-		 * digits are not "chopped off".  That shouldn't matter because
-		 * the digit position (absolute or relative) is passed on to the
-		 * convert-and-push function.
-		 */
-	}
+			DUK_DDD(DUK_DDDPRINT("negative exponent; minimum exponent or not "
+			                     "lowest mantissa for this exponent -> "
+			                     "equal gaps"));
 
-	duk__dragon4_convert_and_push(nc_ctx, ctx, radix, digits, flags, neg);
+			duk__bi_mul_small(&nc_ctx->r, &nc_ctx->f, 2);            /* r <- 2 * f */
+			duk__bi_exp_small(&nc_ctx->t1, nc_ctx->b, -nc_ctx->e, &nc_ctx->s, &nc_ctx->t2);  /* NB: use 's' as temp on purpose */
+			duk__bi_mul_small(&nc_ctx->s, &nc_ctx->t1, 2);           /* s <- b^(-e) * 2 */
+			duk__bi_set_small(&nc_ctx->mp, 1);
+			duk__bi_set_small(&nc_ctx->mm, 1);
+		}
+	}
 }
 
-/*
- *  Exposed string-to-number API
- *
- *  Input: [ string ]
- *  Output: [ number ]
- *
- *  If number parsing fails, a NaN is pushed as the result.  If number parsing
- *  fails due to an internal error, an InternalError is thrown.
- */
-
-void duk_numconv_parse(duk_context *ctx, duk_small_int_t radix, duk_small_uint_t flags) {
-	duk_hthread *thr = (duk_hthread *) ctx;
-	duk__numconv_stringify_ctx nc_ctx_alloc;  /* large context; around 2kB now */
-	duk__numconv_stringify_ctx *nc_ctx = &nc_ctx_alloc;
-	duk_double_t res;
-	duk_hstring *h_str;
-	duk_small_int_t exp;
-	duk_small_int_t exp_neg;
-	duk_small_int_t exp_adj;
-	duk_small_int_t neg;
-	duk_small_int_t dig;
-	duk_small_int_t dig_whole;
-	duk_small_int_t dig_lzero;
-	duk_small_int_t dig_frac;
-	duk_small_int_t dig_exp;
-	duk_small_int_t dig_prec;
-	const duk__exp_limits *explim;
-	const duk_uint8_t *p;
-	duk_small_int_t ch;
+DUK_LOCAL void duk__dragon4_scale(duk__numconv_stringify_ctx *nc_ctx) {
+	duk_small_int_t k = 0;
 
-	/* This seems to waste a lot of stack frame entries, but good compilers
-	 * will compute these as needed below.  Some of these initial flags are
-	 * also modified in the code below, so they can't all be removed.
+	/* This is essentially the 'scale' algorithm, with recursion removed.
+	 * Note that 'k' is either correct immediately, or will move in one
+	 * direction in the loop.  There's no need to do the low/high checks
+	 * on every round (like the Scheme algorithm does).
+	 *
+	 * The scheme algorithm finds 'k' and updates 's' simultaneously,
+	 * while the logical algorithm finds 'k' with 's' having its initial
+	 * value, after which 's' is updated separately (see the Burger-Dybvig
+	 * paper, Section 3.1, steps 2 and 3).
+	 *
+	 * The case where m+ == m- (almost always) is optimized for, because
+	 * it reduces the bigint operations considerably and almost always
+	 * applies.  The scale loop only needs to work with m+, so this works.
 	 */
-	duk_small_int_t trim_white = (flags & DUK_S2N_FLAG_TRIM_WHITE);
-	duk_small_int_t allow_exp = (flags & DUK_S2N_FLAG_ALLOW_EXP);
-	duk_small_int_t allow_garbage = (flags & DUK_S2N_FLAG_ALLOW_GARBAGE);
-	duk_small_int_t allow_plus = (flags & DUK_S2N_FLAG_ALLOW_PLUS);
-	duk_small_int_t allow_minus = (flags & DUK_S2N_FLAG_ALLOW_MINUS);
-	duk_small_int_t allow_infinity = (flags & DUK_S2N_FLAG_ALLOW_INF);
-	duk_small_int_t allow_frac = (flags & DUK_S2N_FLAG_ALLOW_FRAC);
-	duk_small_int_t allow_naked_frac = (flags & DUK_S2N_FLAG_ALLOW_NAKED_FRAC);
-	duk_small_int_t allow_empty_frac = (flags & DUK_S2N_FLAG_ALLOW_EMPTY_FRAC);
-	duk_small_int_t allow_empty = (flags & DUK_S2N_FLAG_ALLOW_EMPTY_AS_ZERO);
-	duk_small_int_t allow_leading_zero = (flags & DUK_S2N_FLAG_ALLOW_LEADING_ZERO);
-	duk_small_int_t allow_auto_hex_int = (flags & DUK_S2N_FLAG_ALLOW_AUTO_HEX_INT);
-	duk_small_int_t allow_auto_oct_int = (flags & DUK_S2N_FLAG_ALLOW_AUTO_OCT_INT);
 
-	DUK_DDD(DUK_DDDPRINT("parse number: %!T, radix=%ld, flags=0x%08lx",
-	                     (duk_tval *) duk_get_tval(ctx, -1),
-	                     (long) radix, (unsigned long) flags));
+	/* XXX: this algorithm could be optimized quite a lot by using e.g.
+	 * a logarithm based estimator for 'k' and performing B^n multiplication
+	 * using a lookup table or using some bit-representation based exp
+	 * algorithm.  Currently we just loop, with significant performance
+	 * impact for very large and very small numbers.
+	 */
 
-	DUK_ASSERT(radix >= 2 && radix <= 36);
-	DUK_ASSERT(radix - 2 < (duk_small_int_t) sizeof(duk__str2num_digits_for_radix));
+	DUK_DDD(DUK_DDDPRINT("scale: B=%ld, low_ok=%ld, high_ok=%ld",
+	                     (long) nc_ctx->B, (long) nc_ctx->low_ok, (long) nc_ctx->high_ok));
+	DUK__BI_PRINT("r(init)", &nc_ctx->r);
+	DUK__BI_PRINT("s(init)", &nc_ctx->s);
+	DUK__BI_PRINT("mp(init)", &nc_ctx->mp);
+	DUK__BI_PRINT("mm(init)", &nc_ctx->mm);
 
-	/*
-	 *  Preliminaries: trim, sign, Infinity check
-	 *
-	 *  We rely on the interned string having a NUL terminator, which will
-	 *  cause a parse failure wherever it is encountered.  As a result, we
-	 *  don't need separate pointer checks.
-	 *
-	 *  There is no special parsing for 'NaN' in the specification although
-	 *  'Infinity' (with an optional sign) is allowed in some contexts.
-	 *  Some contexts allow plus/minus sign, while others only allow the
-	 *  minus sign (like JSON.parse()).
-	 *
-	 *  Automatic hex number detection (leading '0x' or '0X') and octal
-	 *  number detection (leading '0' followed by at least one octal digit)
-	 *  is done here too.
-	 */
+	for (;;) {
+		DUK_DDD(DUK_DDDPRINT("scale loop (inc k), k=%ld", (long) k));
+		DUK__BI_PRINT("r", &nc_ctx->r);
+		DUK__BI_PRINT("s", &nc_ctx->s);
+		DUK__BI_PRINT("m+", &nc_ctx->mp);
+		DUK__BI_PRINT("m-", &nc_ctx->mm);
 
-	if (trim_white) {
-		/* Leading / trailing whitespace is sometimes accepted and
-		 * sometimes not.  After white space trimming, all valid input
-		 * characters are pure ASCII.
-		 */
-		duk_trim(ctx, -1);
-	}
-	h_str = duk_require_hstring(ctx, -1);
-	DUK_ASSERT(h_str != NULL);
-	p = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_str);
+		duk__bi_add(&nc_ctx->t1, &nc_ctx->r, &nc_ctx->mp);  /* t1 = (+ r m+) */
+		if (duk__bi_compare(&nc_ctx->t1, &nc_ctx->s) >= (nc_ctx->high_ok ? 0 : 1)) {
+			DUK_DDD(DUK_DDDPRINT("k is too low"));
+			/* r <- r
+			 * s <- (* s B)
+			 * m+ <- m+
+			 * m- <- m-
+			 * k <- (+ k 1)
+			 */
 
-	neg = 0;
-	ch = *p;
-	if (ch == (duk_small_int_t) '+') {
-		if (!allow_plus) {
-			DUK_DDD(DUK_DDDPRINT("parse failed: leading plus sign not allowed"));
-			goto parse_fail;
-		}
-		p++;
-	} else if (ch == (duk_small_int_t) '-') {
-		if (!allow_minus) {
-			DUK_DDD(DUK_DDDPRINT("parse failed: leading minus sign not allowed"));
-			goto parse_fail;
+			duk__bi_mul_small_copy(&nc_ctx->s, nc_ctx->B, &nc_ctx->t1);
+			k++;
+		} else {
+			break;
 		}
-		p++;
-		neg = 1;
 	}
 
-	ch = *p;
-	if (allow_infinity && ch == (duk_small_int_t) 'I') {
-		/* Don't check for Infinity unless the context allows it.
-		 * 'Infinity' is a valid integer literal in e.g. base-36:
-		 *
-		 *   parseInt('Infinity', 36)
-		 *   1461559270678
-		 */
+	/* k > 0 -> k was too low, and cannot be too high */
+	if (k > 0) {
+		goto skip_dec_k;
+	}
 
-		const duk_uint8_t *q;
+	for (;;) {
+		DUK_DDD(DUK_DDDPRINT("scale loop (dec k), k=%ld", (long) k));
+		DUK__BI_PRINT("r", &nc_ctx->r);
+		DUK__BI_PRINT("s", &nc_ctx->s);
+		DUK__BI_PRINT("m+", &nc_ctx->mp);
+		DUK__BI_PRINT("m-", &nc_ctx->mm);
 
-		/* borrow literal Infinity from builtin string */
-		q = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(DUK_HTHREAD_STRING_INFINITY(thr));
-		if (DUK_STRNCMP((const char *) p, (const char *) q, 8) == 0) {
-			if (!allow_garbage && (p[8] != (duk_uint8_t) 0)) {
-				DUK_DDD(DUK_DDDPRINT("parse failed: trailing garbage after matching 'Infinity' not allowed"));
-				goto parse_fail;
-			} else {
-				res = DUK_DOUBLE_INFINITY;
-				goto negcheck_and_ret;
+		duk__bi_add(&nc_ctx->t1, &nc_ctx->r, &nc_ctx->mp);  /* t1 = (+ r m+) */
+		duk__bi_mul_small(&nc_ctx->t2, &nc_ctx->t1, nc_ctx->B);   /* t2 = (* (+ r m+) B) */
+		if (duk__bi_compare(&nc_ctx->t2, &nc_ctx->s) <= (nc_ctx->high_ok ? -1 : 0)) {
+			DUK_DDD(DUK_DDDPRINT("k is too high"));
+			/* r <- (* r B)
+			 * s <- s
+			 * m+ <- (* m+ B)
+			 * m- <- (* m- B)
+			 * k <- (- k 1)
+			 */
+			duk__bi_mul_small_copy(&nc_ctx->r, nc_ctx->B, &nc_ctx->t1);
+			duk__bi_mul_small_copy(&nc_ctx->mp, nc_ctx->B, &nc_ctx->t1);
+			if (nc_ctx->unequal_gaps) {
+				DUK_DDD(DUK_DDDPRINT("m+ != m- -> need to update m- too"));
+				duk__bi_mul_small_copy(&nc_ctx->mm, nc_ctx->B, &nc_ctx->t1);
 			}
+			k--;
+		} else {
+			break;
 		}
 	}
-	if (ch == (duk_small_int_t) '0') {
-		duk_small_int_t detect_radix = 0;
-		ch = p[1];
-		if (allow_auto_hex_int && (ch == (duk_small_int_t) 'x' || ch == (duk_small_int_t) 'X')) {
-			DUK_DDD(DUK_DDDPRINT("detected 0x/0X hex prefix, changing radix and preventing fractions and exponent"));
-			detect_radix = 16;
-			allow_empty = 0;  /* interpret e.g. '0x' and '0xg' as a NaN (= parse error) */
-			p += 2;
-		} else if (allow_auto_oct_int && (ch >= (duk_small_int_t) '0' && ch <= (duk_small_int_t) '9')) {
-			DUK_DDD(DUK_DDDPRINT("detected 0n oct prefix, changing radix and preventing fractions and exponent"));
-			detect_radix = 8;
-			allow_empty = 1;  /* interpret e.g. '09' as '0', not NaN */
-			p += 1;
-		}
-		if (detect_radix > 0) {
-			radix = detect_radix;
-			allow_exp = 0;
-			allow_frac = 0;
-			allow_naked_frac = 0;
-			allow_empty_frac = 0;
-			allow_leading_zero = 1;  /* allow e.g. '0x0009' and '00077' */
-		}
+
+ skip_dec_k:
+
+	if (!nc_ctx->unequal_gaps) {
+		DUK_DDD(DUK_DDDPRINT("equal gaps, copy m- from m+"));
+		duk__bi_copy(&nc_ctx->mm, &nc_ctx->mp);  /* mm <- mp */
 	}
+	nc_ctx->k = k;
+
+	DUK_DDD(DUK_DDDPRINT("final k: %ld", (long) k));
+	DUK__BI_PRINT("r(final)", &nc_ctx->r);
+	DUK__BI_PRINT("s(final)", &nc_ctx->s);
+	DUK__BI_PRINT("mp(final)", &nc_ctx->mp);
+	DUK__BI_PRINT("mm(final)", &nc_ctx->mm);
+}
+
+DUK_LOCAL void duk__dragon4_generate(duk__numconv_stringify_ctx *nc_ctx) {
+	duk_small_int_t tc1, tc2;    /* terminating conditions */
+	duk_small_int_t d;           /* current digit */
+	duk_small_int_t count = 0;   /* digit count */
 
 	/*
-	 *  Scan number and setup for Dragon4.
-	 *
-	 *  The fast path case is detected during setup: an integer which
-	 *  can be converted without rounding, no net exponent.  The fast
-	 *  path could be implemented as a separate scan, but may not really
-	 *  be worth it: the multiplications for building 'f' are not
-	 *  expensive when 'f' is small.
-	 *
-	 *  The significand ('f') must contain enough bits of (apparent)
-	 *  accuracy, so that Dragon4 will generate enough binary output digits.
-	 *  For decimal numbers, this means generating a 20-digit significand,
-	 *  which should yield enough practical accuracy to parse IEEE doubles.
-	 *  In fact, the Ecmascript specification explicitly allows an
-	 *  implementation to treat digits beyond 20 as zeroes (and even
-	 *  to round the 20th digit upwards).  For non-decimal numbers, the
-	 *  appropriate number of digits has been precomputed for comparable
-	 *  accuracy.
-	 *
-	 *  Digit counts:
+	 *  Digit generation loop.
 	 *
-	 *    [ dig_lzero ]
-	 *      |
-	 *     .+-..---[ dig_prec ]----.
-	 *     |  ||                   |
-	 *     0000123.456789012345678901234567890e+123456
-	 *     |     | |                         |  |    |
-	 *     `--+--' `------[ dig_frac ]-------'  `-+--'
-	 *        |                                   |
-	 *    [ dig_whole ]                       [ dig_exp ]
+	 *  Different termination conditions:
 	 *
-	 *    dig_frac and dig_exp are -1 if not present
-	 *    dig_lzero is only computed for whole number part
+	 *    1. Free format output.  Terminate when shortest accurate
+	 *       representation found.
 	 *
-	 *  Parsing state
+	 *    2. Fixed format output, with specific number of digits.
+	 *       Ignore termination conditions, terminate when digits
+	 *       generated.  Caller requests an extra digit and rounds.
 	 *
-	 *     Parsing whole part      dig_frac < 0 AND dig_exp < 0
-	 *     Parsing fraction part   dig_frac >= 0 AND dig_exp < 0
-	 *     Parsing exponent part   dig_exp >= 0   (dig_frac may be < 0 or >= 0)
-	 * 
-	 *  Note: in case we hit an implementation limit (like exponent range),
-	 *  we should throw an error, NOT return NaN or Infinity.  Even with
-	 *  very large exponent (or significand) values the final result may be
-	 *  finite, so NaN/Infinity would be incorrect.
+	 *    3. Fixed format output, with a specific absolute cut-off
+	 *       position (e.g. 10 digits after decimal point).  Note
+	 *       that we always generate at least one digit, even if
+	 *       the digit is below the cut-off point already.
 	 */
 
-	duk__bi_set_small(&nc_ctx->f, 0);
-	dig_prec = 0;
-	dig_lzero = 0;
-	dig_whole = 0;
-	dig_frac = -1;
-	dig_exp = -1;
-	exp = 0;
-	exp_adj = 0;  /* essentially tracks digit position of lowest 'f' digit */
-	exp_neg = 0;
 	for (;;) {
-		ch = *p++;
-
-		DUK_DDD(DUK_DDDPRINT("parse digits: p=%p, ch='%c' (%ld), exp=%ld, exp_adj=%ld, "
-		                     "dig_whole=%ld, dig_frac=%ld, dig_exp=%ld, dig_lzero=%ld, dig_prec=%ld",
-		                     (void *) p, (int) ((ch >= 0x20 && ch <= 0x7e) ? ch : '?'), (long) ch,
-		                     (long) exp, (long) exp_adj, (long) dig_whole, (long) dig_frac,
-		                     (long) dig_exp, (long) dig_lzero, (long) dig_prec));
-		DUK__BI_PRINT("f", &nc_ctx->f);
-
-		/* Most common cases first. */
-		if (ch >= (duk_small_int_t) '0' && ch <= (duk_small_int_t) '9') {
-			dig = (int) ch - '0' + 0;
-		} else if (ch == (duk_small_int_t) '.') {
-			/* A leading digit is not required in some cases, e.g. accept ".123".
-			 * In other cases (JSON.parse()) a leading digit is required.  This
-			 * is checked for after the loop.
-			 */
-			if (dig_frac >= 0 || dig_exp >= 0) {
-				if (allow_garbage) {
-					DUK_DDD(DUK_DDDPRINT("garbage termination (invalid period)"));
-					break;
-				} else {
-					DUK_DDD(DUK_DDDPRINT("parse failed: period not allowed"));
-					goto parse_fail;
-				}
-			}
+		DUK_DDD(DUK_DDDPRINT("generate loop, count=%ld, k=%ld, B=%ld, low_ok=%ld, high_ok=%ld",
+		                     (long) count, (long) nc_ctx->k, (long) nc_ctx->B,
+		                     (long) nc_ctx->low_ok, (long) nc_ctx->high_ok));
+		DUK__BI_PRINT("r", &nc_ctx->r);
+		DUK__BI_PRINT("s", &nc_ctx->s);
+		DUK__BI_PRINT("m+", &nc_ctx->mp);
+		DUK__BI_PRINT("m-", &nc_ctx->mm);
 
-			if (!allow_frac) {
-				/* Some contexts don't allow fractions at all; this can't be a
-				 * post-check because the state ('f' and exp) would be incorrect.
-				 */
-				if (allow_garbage) {
-					DUK_DDD(DUK_DDDPRINT("garbage termination (invalid first period)"));
-					break;
-				} else {
-					DUK_DDD(DUK_DDDPRINT("parse failed: fraction part not allowed"));
-				}
+		/* (quotient-remainder (* r B) s) using a dummy subtraction loop */
+		duk__bi_mul_small(&nc_ctx->t1, &nc_ctx->r, nc_ctx->B);       /* t1 <- (* r B) */
+		d = 0;
+		for (;;) {
+			if (duk__bi_compare(&nc_ctx->t1, &nc_ctx->s) < 0) {
+				break;
 			}
+			duk__bi_sub_copy(&nc_ctx->t1, &nc_ctx->s, &nc_ctx->t2);  /* t1 <- t1 - s */
+			d++;
+		}
+		duk__bi_copy(&nc_ctx->r, &nc_ctx->t1);  /* r <- (remainder (* r B) s) */
+		                                        /* d <- (quotient (* r B) s)   (in range 0...B-1) */
+		DUK_DDD(DUK_DDDPRINT("-> d(quot)=%ld", (long) d));
+		DUK__BI_PRINT("r(rem)", &nc_ctx->r);
 
-			DUK_DDD(DUK_DDDPRINT("start fraction part"));
-			dig_frac = 0;
-			continue;
-		} else if (ch == (duk_small_int_t) 0) {
-			DUK_DDD(DUK_DDDPRINT("NUL termination"));
-			break;
-		} else if (allow_exp && dig_exp < 0 && (ch == (duk_small_int_t) 'e' || ch == (duk_small_int_t) 'E')) {
-			/* Note: we don't parse back exponent notation for anything else
-			 * than radix 10, so this is not an ambiguous check (e.g. hex
-			 * exponent values may have 'e' either as a significand digit
-			 * or as an exponent separator).
-			 *
-			 * If the exponent separator occurs twice, 'e' will be interpreted
-			 * as a digit (= 14) and will be rejected as an invalid decimal
-			 * digit.
-			 */
+		duk__bi_mul_small_copy(&nc_ctx->mp, nc_ctx->B, &nc_ctx->t2); /* m+ <- (* m+ B) */
+		duk__bi_mul_small_copy(&nc_ctx->mm, nc_ctx->B, &nc_ctx->t2); /* m- <- (* m- B) */
+		DUK__BI_PRINT("mp(upd)", &nc_ctx->mp);
+		DUK__BI_PRINT("mm(upd)", &nc_ctx->mm);
 
-			DUK_DDD(DUK_DDDPRINT("start exponent part"));
+		/* Terminating conditions.  For fixed width output, we just ignore the
+		 * terminating conditions (and pretend that tc1 == tc2 == false).  The
+		 * the current shortcut for fixed-format output is to generate a few
+		 * extra digits and use rounding (with carry) to finish the output.
+		 */
 
-			/* Exponent without a sign or with a +/- sign is accepted
-			 * by all call sites (even JSON.parse()).
-			 */
-			ch = *p;
-			if (ch == (duk_small_int_t) '-') {
-				exp_neg = 1;
-				p++;
-			} else if (ch == (duk_small_int_t) '+') {
-				p++;
-			}
-			dig_exp = 0;
-			continue;
-		} else if (ch >= (duk_small_int_t) 'a' && ch <= (duk_small_int_t) 'z') {
-			dig = (duk_small_int_t) (ch - (duk_small_int_t) 'a' + 0x0a);
-		} else if (ch >= (duk_small_int_t) 'A' && ch <= (duk_small_int_t) 'Z') {
-			dig = (duk_small_int_t) (ch - (duk_small_int_t) 'A' + 0x0a);
-		} else {
-			dig = 255;  /* triggers garbage digit check below */
-		}
-		DUK_ASSERT((dig >= 0 && dig <= 35) || dig == 255);
+		if (nc_ctx->is_fixed == 0) {
+			/* free-form */
+			tc1 = (duk__bi_compare(&nc_ctx->r, &nc_ctx->mm) <= (nc_ctx->low_ok ? 0 : -1));
 
-		if (dig >= radix) {
-			if (allow_garbage) {
-				DUK_DDD(DUK_DDDPRINT("garbage termination"));
-				break;
-			} else {
-				DUK_DDD(DUK_DDDPRINT("parse failed: trailing garbage or invalid digit"));
-				goto parse_fail;
-			}
-		}
+			duk__bi_add(&nc_ctx->t1, &nc_ctx->r, &nc_ctx->mp);  /* t1 <- (+ r m+) */
+			tc2 = (duk__bi_compare(&nc_ctx->t1, &nc_ctx->s) >= (nc_ctx->high_ok ? 0 : 1));
 
-		if (dig_exp < 0) {
-			/* whole or fraction digit */
+			DUK_DDD(DUK_DDDPRINT("tc1=%ld, tc2=%ld", (long) tc1, (long) tc2));
+		} else {
+			/* fixed-format */
+			tc1 = 0;
+			tc2 = 0;
+		}
 
-			if (dig_prec < duk__str2num_digits_for_radix[radix - 2]) {
-				/* significant from precision perspective */
+		/* Count is incremented before DUK__DRAGON4_OUTPUT_PREINC() call
+		 * on purpose, which is taken into account by the macro.
+		 */
+		count++;
 
-				duk_small_int_t f_zero = duk__bi_is_zero(&nc_ctx->f);
-				if (f_zero && dig == 0) {
-					/* Leading zero is not counted towards precision digits; not
-					 * in the integer part, nor in the fraction part.
-					 */
-					if (dig_frac < 0) {
-						dig_lzero++;
-					}
+		if (tc1) {
+			if (tc2) {
+				/* tc1 = true, tc2 = true */
+				duk__bi_mul_small(&nc_ctx->t1, &nc_ctx->r, 2);
+				if (duk__bi_compare(&nc_ctx->t1, &nc_ctx->s) < 0) {  /* (< (* r 2) s) */
+					DUK_DDD(DUK_DDDPRINT("tc1=true, tc2=true, 2r > s: output d --> %ld (k=%ld)",
+					                     (long) d, (long) nc_ctx->k));
+					DUK__DRAGON4_OUTPUT_PREINC(nc_ctx, count, d);
 				} else {
-					/* XXX: join these ops (multiply-accumulate), but only if
-					 * code footprint decreases.
-					 */
-					duk__bi_mul_small(&nc_ctx->t1, &nc_ctx->f, radix);
-					duk__bi_add_small(&nc_ctx->f, &nc_ctx->t1, dig);
-					dig_prec++;
+					DUK_DDD(DUK_DDDPRINT("tc1=true, tc2=true, 2r <= s: output d+1 --> %ld (k=%ld)",
+					                     (long) (d + 1), (long) nc_ctx->k));
+					DUK__DRAGON4_OUTPUT_PREINC(nc_ctx, count, d + 1);
 				}
+				break;
 			} else {
-				/* Ignore digits beyond a radix-specific limit, but note them
-				 * in exp_adj.
-				 */
-				exp_adj++;
-			}
-	
-			if (dig_frac >= 0) {
-				dig_frac++;
-				exp_adj--;
-			} else {
-				dig_whole++;
+				/* tc1 = true, tc2 = false */
+				DUK_DDD(DUK_DDDPRINT("tc1=true, tc2=false: output d --> %ld (k=%ld)",
+				                     (long) d, (long) nc_ctx->k));
+				DUK__DRAGON4_OUTPUT_PREINC(nc_ctx, count, d);
+				break;
 			}
 		} else {
-			/* exponent digit */
+			if (tc2) {
+				/* tc1 = false, tc2 = true */
+				DUK_DDD(DUK_DDDPRINT("tc1=false, tc2=true: output d+1 --> %ld (k=%ld)",
+				                     (long) (d + 1), (long) nc_ctx->k));
+				DUK__DRAGON4_OUTPUT_PREINC(nc_ctx, count, d + 1);
+				break;
+			} else {
+				/* tc1 = false, tc2 = false */
+				DUK_DDD(DUK_DDDPRINT("tc1=false, tc2=false: output d --> %ld (k=%ld)",
+				                     (long) d, (long) nc_ctx->k));
+				DUK__DRAGON4_OUTPUT_PREINC(nc_ctx, count, d);
 
-			exp = exp * radix + dig;
-			if (exp > DUK_S2N_MAX_EXPONENT) {
-				/* impose a reasonable exponent limit, so that exp
-				 * doesn't need to get tracked using a bigint.
+				/* r <- r    (updated above: r <- (remainder (* r B) s)
+				 * s <- s
+				 * m+ <- m+  (updated above: m+ <- (* m+ B)
+				 * m- <- m-  (updated above: m- <- (* m- B)
+				 * B, low_ok, high_ok are fixed
 				 */
-				DUK_DDD(DUK_DDDPRINT("parse failed: exponent too large"));
-				goto parse_int_error;
+
+				/* fall through and continue for-loop */
 			}
-			dig_exp++;
 		}
-	}
-
-	/* Leading zero. */
 
-	if (dig_lzero > 0 && dig_whole > 1) {
-		if (!allow_leading_zero) {
-			DUK_DDD(DUK_DDDPRINT("parse failed: leading zeroes not allowed in integer part"));
-			goto parse_fail;
+		/* fixed-format termination conditions */
+		if (nc_ctx->is_fixed) {
+			if (nc_ctx->abs_pos) {
+				int pos = nc_ctx->k - count + 1;  /* count is already incremented, take into account */
+				DUK_DDD(DUK_DDDPRINT("fixed format, absolute: abs pos=%ld, k=%ld, count=%ld, req=%ld",
+				                     (long) pos, (long) nc_ctx->k, (long) count, (long) nc_ctx->req_digits));
+				if (pos <= nc_ctx->req_digits) {
+					DUK_DDD(DUK_DDDPRINT("digit position reached req_digits, end generate loop"));
+					break;
+				}
+			} else {
+				DUK_DDD(DUK_DDDPRINT("fixed format, relative: k=%ld, count=%ld, req=%ld",
+				                     (long) nc_ctx->k, (long) count, (long) nc_ctx->req_digits));
+				if (count >= nc_ctx->req_digits) {
+					DUK_DDD(DUK_DDDPRINT("digit count reached req_digits, end generate loop"));
+					break;
+				}
+			}
 		}
-	}
+	}  /* for */
 
-	/* Validity checks for various fraction formats ("0.1", ".1", "1.", "."). */
+	nc_ctx->count = count;
 
-	if (dig_whole == 0) {
-		if (dig_frac == 0) {
-			/* "." is not accepted in any format */
-			DUK_DDD(DUK_DDDPRINT("parse failed: plain period without leading or trailing digits"));
-			goto parse_fail;
-		} else if (dig_frac > 0) {
-			/* ".123" */
-			if (!allow_naked_frac) {
-				DUK_DDD(DUK_DDDPRINT("parse failed: fraction part not allowed without "
-				                     "leading integer digit(s)"));
-				goto parse_fail;
-			}
-		} else {
-			/* empty ("") is allowed in some formats (e.g. Number(''), as zero */
-			if (!allow_empty) {
-				DUK_DDD(DUK_DDDPRINT("parse failed: empty string not allowed (as zero)"));
-				goto parse_fail;
-			}
-		}
-	} else {
-		if (dig_frac == 0) {
-			/* "123." is allowed in some formats */
-			if (!allow_empty_frac) {
-				DUK_DDD(DUK_DDDPRINT("parse failed: empty fractions"));
-				goto parse_fail;
+	DUK_DDD(DUK_DDDPRINT("generate finished"));
+
+#ifdef DUK_USE_DDDPRINT
+	{
+		duk_uint8_t buf[2048];
+		duk_small_int_t i, t;
+		DUK_MEMZERO(buf, sizeof(buf));
+		for (i = 0; i < nc_ctx->count; i++) {
+			t = nc_ctx->digits[i];
+			if (t < 0 || t > 36) {
+				buf[i] = (duk_uint8_t) '?';
+			} else {
+				buf[i] = (duk_uint8_t) DUK__DIGITCHAR(t);
 			}
-		} else if (dig_frac > 0) {
-			/* "123.456" */
-			;
-		} else {
-			/* "123" */
-			;
 		}
+		DUK_DDD(DUK_DDDPRINT("-> generated digits; k=%ld, digits='%s'",
+		                     (long) nc_ctx->k, (const char *) buf));
 	}
+#endif
+}
 
-	/* Exponent without digits (e.g. "1e" or "1e+").  If trailing garbage is
-	 * allowed, ignore exponent part as garbage (= parse as "1", i.e. exp 0).
+/* Round up digits to a given position.  If position is out-of-bounds,
+ * does nothing.  If carry propagates over the first digit, a '1' is
+ * prepended to digits and 'k' will be updated.  Return value indicates
+ * whether carry propagated over the first digit.
+ *
+ * Note that nc_ctx->count is NOT updated based on the rounding position
+ * (it is updated only if carry overflows over the first digit and an
+ * extra digit is prepended).
+ */
+DUK_LOCAL duk_small_int_t duk__dragon4_fixed_format_round(duk__numconv_stringify_ctx *nc_ctx, duk_small_int_t round_idx) {
+	duk_small_int_t t;
+	duk_uint8_t *p;
+	duk_uint8_t roundup_limit;
+	duk_small_int_t ret = 0;
+
+	/*
+	 *  round_idx points to the digit which is considered for rounding; the
+	 *  digit to its left is the final digit of the rounded value.  If round_idx
+	 *  is zero, rounding will be performed; the result will either be an empty
+	 *  rounded value or if carry happens a '1' digit is generated.
 	 */
 
-	if (dig_exp == 0) {
-		if (!allow_garbage) {
-			DUK_DDD(DUK_DDDPRINT("parse failed: empty exponent"));
-			goto parse_fail;
-		}
-		DUK_ASSERT(exp == 0);
+	if (round_idx >= nc_ctx->count) {
+		DUK_DDD(DUK_DDDPRINT("round_idx out of bounds (%ld >= %ld (count)) -> no rounding",
+		                     (long) round_idx, (long) nc_ctx->count));
+		return 0;
+	} else if (round_idx < 0) {
+		DUK_DDD(DUK_DDDPRINT("round_idx out of bounds (%ld < 0) -> no rounding",
+		                     (long) round_idx));
+		return 0;
 	}
 
-	if (exp_neg) {
-		exp = -exp;
-	}
-	DUK_DDD(DUK_DDDPRINT("exp=%ld, exp_adj=%ld, net exponent -> %ld",
-	                     (long) exp, (long) exp_adj, (long) (exp + exp_adj)));
-	exp += exp_adj;
+	/*
+	 *  Round-up limit.
+	 *
+	 *  For even values, divides evenly, e.g. 10 -> roundup_limit=5.
+	 *
+	 *  For odd values, rounds up, e.g. 3 -> roundup_limit=2.
+	 *  If radix is 3, 0/3 -> down, 1/3 -> down, 2/3 -> up.
+	 */
+	roundup_limit = (duk_uint8_t) ((nc_ctx->B + 1) / 2);
 
-	/* Fast path check. */
+	p = &nc_ctx->digits[round_idx];
+	if (*p >= roundup_limit) {
+		DUK_DDD(DUK_DDDPRINT("fixed-format rounding carry required"));
+		/* carry */
+		for (;;) {
+			*p = 0;
+			if (p == &nc_ctx->digits[0]) {
+				DUK_DDD(DUK_DDDPRINT("carry propagated to first digit -> special case handling"));
+				DUK_MEMMOVE((void *) (&nc_ctx->digits[1]),
+				            (const void *) (&nc_ctx->digits[0]),
+				            (size_t) (sizeof(char) * nc_ctx->count));
+				nc_ctx->digits[0] = 1;  /* don't increase 'count' */
+				nc_ctx->k++;  /* position of highest digit changed */
+				nc_ctx->count++;  /* number of digits changed */
+				ret = 1;
+				break;
+			}
 
-	if (nc_ctx->f.n <= 1 &&   /* 32-bit value */
-	    exp == 0    /* no net exponent */) {
-		/* Fast path is triggered for no exponent and also for balanced exponent
-		 * and fraction parts, e.g. for "1.23e2" == "123".  Remember to respect
-		 * zero sign.
-		 */
+			DUK_DDD(DUK_DDDPRINT("fixed-format rounding carry: B=%ld, roundup_limit=%ld, p=%p, digits=%p",
+			                     (long) nc_ctx->B, (long) roundup_limit, (void *) p, (void *) nc_ctx->digits));
+			p--;
+			t = *p;
+			DUK_DDD(DUK_DDDPRINT("digit before carry: %ld", (long) t));
+			if (++t < nc_ctx->B) {
+				DUK_DDD(DUK_DDDPRINT("rounding carry terminated"));
+				*p = (duk_uint8_t) t;
+				break;
+			}
 
-		/* XXX: could accept numbers larger than 32 bits, e.g. up to 53 bits? */
-		DUK_DDD(DUK_DDDPRINT("fast path number parse"));
-		if (nc_ctx->f.n == 1) {
-			res = (double) nc_ctx->f.v[0];
-		} else {
-			res = 0.0;
+			DUK_DDD(DUK_DDDPRINT("wraps, carry to next digit"));
 		}
-		goto negcheck_and_ret;
-	}
-
-	/* Significand ('f') padding. */
-
-	while (dig_prec < duk__str2num_digits_for_radix[radix - 2]) {
-		/* Pad significand with "virtual" zero digits so that Dragon4 will
-		 * have enough (apparent) precision to work with.
-		 */
-		DUK_DDD(DUK_DDDPRINT("dig_prec=%ld, pad significand with zero", (long) dig_prec));
-		duk__bi_mul_small_copy(&nc_ctx->f, radix, &nc_ctx->t1);
-		DUK__BI_PRINT("f", &nc_ctx->f);
-		exp--;
-		dig_prec++;
 	}
 
-	DUK_DDD(DUK_DDDPRINT("final exponent: %ld", (long) exp));
-
-	/* Detect zero special case. */
+	return ret;
+}
 
-	if (nc_ctx->f.n == 0) {
-		/* This may happen even after the fast path check, if exponent is
-		 * not balanced (e.g. "0e1").  Remember to respect zero sign.
-		 */
-		DUK_DDD(DUK_DDDPRINT("significand is zero"));
-		res = 0.0;
-		goto negcheck_and_ret;
-	}
+#define DUK__NO_EXP  (65536)  /* arbitrary marker, outside valid exp range */
 
+DUK_LOCAL void duk__dragon4_convert_and_push(duk__numconv_stringify_ctx *nc_ctx,
+                                          duk_context *ctx,
+                                          duk_small_int_t radix,
+                                          duk_small_int_t digits,
+                                          duk_small_uint_t flags,
+                                          duk_small_int_t neg) {
+	duk_small_int_t k;
+	duk_small_int_t pos, pos_end;
+	duk_small_int_t expt;
+	duk_small_int_t dig;
+	duk_uint8_t *q;
+	duk_uint8_t *buf;
 
-	/* Quick reject of too large or too small exponents.  This check
-	 * would be incorrect for zero (e.g. "0e1000" is zero, not Infinity)
-	 * so zero check must be above.
+	/*
+	 *  The string conversion here incorporates all the necessary Ecmascript
+	 *  semantics without attempting to be generic.  nc_ctx->digits contains
+	 *  nc_ctx->count digits (>= 1), with the topmost digit's 'position'
+	 *  indicated by nc_ctx->k as follows:
+	 *
+	 *    digits="123" count=3 k=0   -->   0.123
+	 *    digits="123" count=3 k=1   -->   1.23
+	 *    digits="123" count=3 k=5   -->   12300
+	 *    digits="123" count=3 k=-1  -->   0.0123
+	 *
+	 *  Note that the identifier names used for format selection are different
+	 *  in Burger-Dybvig paper and Ecmascript specification (quite confusingly
+	 *  so, because e.g. 'k' has a totally different meaning in each).  See
+	 *  documentation for discussion.
+	 *
+	 *  Ecmascript doesn't specify any specific behavior for format selection
+	 *  (e.g. when to use exponent notation) for non-base-10 numbers.
+	 *
+	 *  The bigint space in the context is reused for string output, as there
+	 *  is more than enough space for that (>1kB at the moment), and we avoid
+	 *  allocating even more stack.
 	 */
 
-	explim = &duk__str2num_exp_limits[radix - 2];
-	if (exp > explim->upper) {
-		DUK_DDD(DUK_DDDPRINT("exponent too large -> infinite"));
-		res = (duk_double_t) DUK_DOUBLE_INFINITY;
-		goto negcheck_and_ret;
-	} else if (exp < explim->lower) {
-		DUK_DDD(DUK_DDDPRINT("exponent too small -> zero"));
-		res = (duk_double_t) 0.0;
-		goto negcheck_and_ret;
-	}
-
-	nc_ctx->is_s2n = 1;
-	nc_ctx->e = exp;
-	nc_ctx->b = radix;
-	nc_ctx->B = 2;
-	nc_ctx->is_fixed = 1;
-	nc_ctx->abs_pos = 0;
-	nc_ctx->req_digits = 53 + 1;
+	DUK_ASSERT(DUK__NUMCONV_CTX_BIGINTS_SIZE >= DUK__MAX_FORMATTED_LENGTH);
+	DUK_ASSERT(nc_ctx->count >= 1);
 
-	DUK__BI_PRINT("f", &nc_ctx->f);
-	DUK_DDD(DUK_DDDPRINT("e=%ld", (long) nc_ctx->e));
+	k = nc_ctx->k;
+	buf = (duk_uint8_t *) &nc_ctx->f;  /* XXX: union would be more correct */
+	q = buf;
 
-	/*
-	 *  Dragon4 slow path (binary) digit generation.
-	 *  An extra digit is generated for rounding.
+	/* Exponent handling: if exponent format is used, record exponent value and
+	 * fake k such that one leading digit is generated (e.g. digits=123 -> "1.23").
+	 *
+	 * toFixed() prevents exponent use; otherwise apply a set of criteria to
+	 * match the other API calls (toString(), toPrecision, etc).
 	 */
 
-	duk__dragon4_prepare(nc_ctx);  /* setup many variables in nc_ctx */
+	expt = DUK__NO_EXP;
+	if (!nc_ctx->abs_pos /* toFixed() */) {
+		if ((flags & DUK_N2S_FLAG_FORCE_EXP) ||             /* exponential notation forced */
+		    ((flags & DUK_N2S_FLAG_NO_ZERO_PAD) &&          /* fixed precision and zero padding would be required */
+	             (k - digits >= 1)) ||                          /* (e.g. k=3, digits=2 -> "12X") */
+		    ((k > 21 || k <= -6) && (radix == 10))) {       /* toString() conditions */
+			DUK_DDD(DUK_DDDPRINT("use exponential notation: k=%ld -> expt=%ld",
+			                     (long) k, (long) (k - 1)));
+			expt = k - 1;  /* e.g. 12.3 -> digits="123" k=2 -> 1.23e1 */
+			k = 1;  /* generate mantissa with a single leading whole number digit */
+		}
+	}
 
-	DUK_DDD(DUK_DDDPRINT("after prepare:"));
-	DUK__BI_PRINT("r", &nc_ctx->r);
-	DUK__BI_PRINT("s", &nc_ctx->s);
-	DUK__BI_PRINT("mp", &nc_ctx->mp);
-	DUK__BI_PRINT("mm", &nc_ctx->mm);
+	if (neg) {
+		*q++ = '-';
+	}
 
-	duk__dragon4_scale(nc_ctx);
+	/* Start position (inclusive) and end position (exclusive) */
+	pos = (k >= 1 ? k : 1);
+	if (nc_ctx->is_fixed) {
+		if (nc_ctx->abs_pos) {
+			/* toFixed() */
+			pos_end = -digits;
+		} else {
+			pos_end = k - digits;
+		}
+	} else {
+		pos_end = k - nc_ctx->count;
+	}
+	if (pos_end > 0) {
+		pos_end = 0;
+	}
 
-	DUK_DDD(DUK_DDDPRINT("after scale; k=%ld", (long) nc_ctx->k));
-	DUK__BI_PRINT("r", &nc_ctx->r);
-	DUK__BI_PRINT("s", &nc_ctx->s);
-	DUK__BI_PRINT("mp", &nc_ctx->mp);
-	DUK__BI_PRINT("mm", &nc_ctx->mm);
+	DUK_DDD(DUK_DDDPRINT("expt=%ld, k=%ld, count=%ld, pos=%ld, pos_end=%ld, is_fixed=%ld, "
+	                     "digits=%ld, abs_pos=%ld",
+	                     (long) expt, (long) k, (long) nc_ctx->count, (long) pos, (long) pos_end,
+	                     (long) nc_ctx->is_fixed, (long) digits, (long) nc_ctx->abs_pos));
 
-	duk__dragon4_generate(nc_ctx);
+	/* Digit generation */
+	while (pos > pos_end) {
+		DUK_DDD(DUK_DDDPRINT("digit generation: pos=%ld, pos_end=%ld",
+		                     (long) pos, (long) pos_end));
+		if (pos == 0) {
+			*q++ = (duk_uint8_t) '.';
+		}
+		if (pos > k) {
+			*q++ = (duk_uint8_t) '0';
+		} else if (pos <= k - nc_ctx->count) {
+			*q++ = (duk_uint8_t) '0';
+		} else {
+			dig = nc_ctx->digits[k - pos];
+			DUK_ASSERT(dig >= 0 && dig < nc_ctx->B);
+			*q++ = (duk_uint8_t) DUK__DIGITCHAR(dig);
+		}
 
-	DUK_ASSERT(nc_ctx->count == 53 + 1);
+		pos--;
+	}
+	DUK_ASSERT(pos <= 1);
 
-	/*
-	 *  Convert binary digits into an IEEE double.  Need to handle
-	 *  denormals and rounding correctly.
-	 */
+	/* Exponent */
+	if (expt != DUK__NO_EXP) {
+		/*
+		 *  Exponent notation for non-base-10 numbers isn't specified in Ecmascript
+		 *  specification, as it never explicitly turns up: non-decimal numbers can
+		 *  only be formatted with Number.prototype.toString([radix]) and for that,
+		 *  behavior is not explicitly specified.
+		 *
+		 *  Logical choices include formatting the exponent as decimal (e.g. binary
+		 *  100000 as 1e+5) or in current radix (e.g. binary 100000 as 1e+101).
+		 *  The Dragon4 algorithm (in the original paper) prints the exponent value
+		 *  in the target radix B.  However, for radix values 15 and above, the
+		 *  exponent separator 'e' is no longer easily parseable.  Consider, for
+		 *  instance, the number "1.faecee+1c".
+		 */
 
-	duk__dragon4_ctx_to_double(nc_ctx, &res);
-	goto negcheck_and_ret;
+		duk_size_t len;
+		char expt_sign;
 
- negcheck_and_ret:
-	if (neg) {
-		res = -res;
+		*q++ = 'e';
+		if (expt >= 0) {
+			expt_sign = '+';
+		} else {
+			expt_sign = '-';
+			expt = -expt;
+		}
+		*q++ = (duk_uint8_t) expt_sign;
+		len = duk__dragon4_format_uint32(q, (duk_uint32_t) expt, radix);
+		q += len;
 	}
-	duk_pop(ctx);
-	duk_push_number(ctx, (double) res);
-	DUK_DDD(DUK_DDDPRINT("result: %!T", (duk_tval *) duk_get_tval(ctx, -1)));
-	return;
-
- parse_fail:
-	DUK_DDD(DUK_DDDPRINT("parse failed"));
-	duk_pop(ctx);
-	duk_push_nan(ctx);
-	return;
 
- parse_int_error:
-	DUK_DDD(DUK_DDDPRINT("parse failed, internal error, can't return a value"));
-	DUK_ERROR(thr, DUK_ERR_INTERNAL_ERROR, "number parse error");
-	return;
+	duk_push_lstring(ctx, (const char *) buf, (size_t) (q - buf));
 }
 
-#line 1 "duk_regexp_compiler.c"
 /*
- *  Regexp compilation.
- *
- *  See doc/regexp.txt for a discussion of the compilation approach and
- *  current limitations.
- *
- *  Regexp bytecode assumes jumps can be expressed with signed 32-bit
- *  integers.  Consequently the bytecode size must not exceed 0x7fffffffL.
- *  The implementation casts duk_size_t (buffer size) to duk_(u)int32_t
- *  in many places.  Although this could be changed, the bytecode format
- *  limit would still prevent regexps exceeding the signed 32-bit limit
- *  from working.
- *
- *  XXX: The implementation does not prevent bytecode from exceeding the
- *  maximum supported size.  This could be done by limiting the maximum
- *  input string size (assuming an upper bound can be computed for number
- *  of bytecode bytes emitted per input byte) or checking buffer maximum
- *  size when emitting bytecode (slower).
+ *  Conversion helpers
  */
 
-/* include removed: duk_internal.h */
+DUK_LOCAL void duk__dragon4_double_to_ctx(duk__numconv_stringify_ctx *nc_ctx, duk_double_t x) {
+	duk_double_union u;
+	duk_uint32_t tmp;
+	duk_small_int_t expt;
 
-#ifdef DUK_USE_REGEXP_SUPPORT
+	/*
+	 *    seeeeeee eeeeffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff
+	 *       A        B        C        D        E        F        G        H
+	 *
+	 *    s       sign bit
+	 *    eee...  exponent field
+	 *    fff...  fraction
+	 *
+	 *    ieee value = 1.ffff... * 2^(e - 1023)  (normal)
+	 *               = 0.ffff... * 2^(-1022)     (denormal)
+	 *
+	 *    algorithm v = f * b^e
+	 */
 
-/*
- *  Helper macros
- */
+	DUK_DBLUNION_SET_DOUBLE(&u, x);
 
-#ifdef DUK__BUFLEN
-#undef DUK__BUFLEN
-#endif
+	nc_ctx->f.n = 2;
+
+	tmp = DUK_DBLUNION_GET_LOW32(&u);
+	nc_ctx->f.v[0] = tmp;
+	tmp = DUK_DBLUNION_GET_HIGH32(&u);
+	nc_ctx->f.v[1] = tmp & 0x000fffffUL;
+	expt = (duk_small_int_t) ((tmp >> 20) & 0x07ffUL);
 
-#define DUK__BUFLEN(re_ctx)   DUK_HBUFFER_GET_SIZE((duk_hbuffer *) re_ctx->buf)
+	if (expt == 0) {
+		/* denormal */
+		expt = DUK__IEEE_DOUBLE_EXP_MIN - 52;
+		duk__bi_normalize(&nc_ctx->f);
+	} else {
+		/* normal: implicit leading 1-bit */
+		nc_ctx->f.v[1] |= 0x00100000UL;
+		expt = expt - DUK__IEEE_DOUBLE_EXP_BIAS - 52;
+		DUK_ASSERT(duk__bi_is_valid(&nc_ctx->f));  /* true, because v[1] has at least one bit set */
+	}
 
-/*
- *  Disjunction struct: result of parsing a disjunction
- */
+	DUK_ASSERT(duk__bi_is_valid(&nc_ctx->f));
 
-typedef struct {
-	/* Number of characters that the atom matches (e.g. 3 for 'abc'),
-	 * -1 if atom is complex and number of matched characters either
-	 * varies or is not known.
+	nc_ctx->e = expt;
+}
+
+DUK_LOCAL void duk__dragon4_ctx_to_double(duk__numconv_stringify_ctx *nc_ctx, duk_double_t *x) {
+	duk_double_union u;
+	duk_small_int_t expt;
+	duk_small_int_t i;
+	duk_small_int_t bitstart;
+	duk_small_int_t bitround;
+	duk_small_int_t bitidx;
+	duk_small_int_t skip_round;
+	duk_uint32_t t, v;
+
+	DUK_ASSERT(nc_ctx->count == 53 + 1);
+
+	/* Sometimes this assert is not true right now; it will be true after
+	 * rounding.  See: test-bug-numconv-mantissa-assert.js.
 	 */
-	duk_int32_t charlen;
+	DUK_ASSERT_DISABLE(nc_ctx->digits[0] == 1);  /* zero handled by caller */
 
-#if 0
-	/* These are not needed to implement quantifier capture handling,
-	 * but might be needed at some point.
+	/* Should not be required because the code below always sets both high
+	 * and low parts, but at least gcc-4.4.5 fails to deduce this correctly
+	 * (perhaps because the low part is set (seemingly) conditionally in a
+	 * loop), so this is here to avoid the bogus warning.
 	 */
+	DUK_MEMZERO((void *) &u, sizeof(u));
 
-	/* re_ctx->captures at start and end of atom parsing.
-	 * Since 'captures' indicates highest capture number emitted
-	 * so far in a DUK_REOP_SAVE, the captures numbers saved by
-	 * the atom are: ]start_captures,end_captures].
+	/*
+	 *  Figure out how generated digits match up with the mantissa,
+	 *  and then perform rounding.  If mantissa overflows, need to
+	 *  recompute the exponent (it is bumped and may overflow to
+	 *  infinity).
+	 *
+	 *  For normal numbers the leading '1' is hidden and ignored,
+	 *  and the last bit is used for rounding:
+	 *
+	 *                          rounding pt
+	 *       <--------52------->|
+	 *     1 x x x x ... x x x x|y  ==>  x x x x ... x x x x
+	 *
+	 *  For denormals, the leading '1' is included in the number,
+	 *  and the rounding point is different:
+	 *
+	 *                      rounding pt
+	 *     <--52 or less--->|
+	 *     1 x x x x ... x x|x x y  ==>  0 0 ... 1 x x ... x x
+	 *
+	 *  The largest denormals will have a mantissa beginning with
+	 *  a '1' (the explicit leading bit); smaller denormals will
+	 *  have leading zero bits.
+	 *
+	 *  If the exponent would become too high, the result becomes
+	 *  Infinity.  If the exponent is so small that the entire
+	 *  mantissa becomes zero, the result becomes zero.
+	 *
+	 *  Note: the Dragon4 'k' is off-by-one with respect to the IEEE
+	 *  exponent.  For instance, k==0 indicates that the leading '1'
+	 *  digit is at the first binary fraction position (0.1xxx...);
+	 *  the corresponding IEEE exponent would be -1.
 	 */
-	duk_uint32_t start_captures;
-	duk_uint32_t end_captures;
-#endif
-} duk__re_disjunction_info;
 
-/*
- *  Encoding helpers
- *
- *  Some of the typing is bytecode based, e.g. slice sizes are unsigned 32-bit
- *  even though the buffer operations will use duk_size_t.
- */
+	skip_round = 0;
 
-/* XXX: the insert helpers should ensure that the bytecode result is not
- * larger than expected (or at least assert for it).  Many things in the
- * bytecode, like skip offsets, won't work correctly if the bytecode is
- * larger than say 2G.
- */
+ recheck_exp:
 
-static duk_uint32_t duk__encode_i32(duk_int32_t x) {
-	if (x < 0) {
-		return ((duk_uint32_t) (-x)) * 2 + 1;
+	expt = nc_ctx->k - 1;   /* IEEE exp without bias */
+	if (expt > 1023) {
+		/* Infinity */
+		bitstart = -255;  /* needed for inf: causes mantissa to become zero,
+		                   * and rounding to be skipped.
+		                   */
+		expt = 2047;
+	} else if (expt >= -1022) {
+		/* normal */
+		bitstart = 1;  /* skip leading digit */
+		expt += DUK__IEEE_DOUBLE_EXP_BIAS;
+		DUK_ASSERT(expt >= 1 && expt <= 2046);
 	} else {
-		return ((duk_uint32_t) x) * 2;
+		/* denormal or zero */
+		bitstart = 1023 + expt;  /* expt==-1023 -> bitstart=0 (leading 1);
+		                          * expt==-1024 -> bitstart=-1 (one left of leading 1), etc
+		                          */
+		expt = 0;
 	}
-}
-
-/* XXX: return type should probably be duk_size_t, or explicit checks are needed for
- * maximum size.
- */
-static duk_uint32_t duk__insert_u32(duk_re_compiler_ctx *re_ctx, duk_uint32_t offset, duk_uint32_t x) {
-	return (duk_uint32_t) duk_hbuffer_insert_xutf8(re_ctx->thr, re_ctx->buf, offset, x);
-}
-
-static duk_uint32_t duk__append_u32(duk_re_compiler_ctx *re_ctx, duk_uint32_t x) {
-	return (duk_uint32_t) duk_hbuffer_append_xutf8(re_ctx->thr, re_ctx->buf, x);
-}
-
-static duk_uint32_t duk__insert_i32(duk_re_compiler_ctx *re_ctx, duk_uint32_t offset, duk_int32_t x) {
-	return (duk_uint32_t) duk_hbuffer_insert_xutf8(re_ctx->thr, re_ctx->buf, offset, duk__encode_i32(x));
-}
+	bitround = bitstart + 52;
 
-#if 0  /* unused */
-static duk_uint32_t duk__append_i32(duk_re_compiler_ctx *re_ctx, duk_int32_t x) {
-	return duk_hbuffer_append_xutf8(re_ctx->thr, re_ctx->buf, duk__encode_i32(x));
-}
-#endif
+	DUK_DDD(DUK_DDDPRINT("ieee expt=%ld, bitstart=%ld, bitround=%ld",
+	                     (long) expt, (long) bitstart, (long) bitround));
 
-/* special helper for emitting u16 lists (used for character ranges for built-in char classes) */
-static void duk__append_u16_list(duk_re_compiler_ctx *re_ctx, duk_uint16_t *values, duk_uint32_t count) {
-	/* Call sites don't need the result length so it's not accumulated. */
-	while (count > 0) {
-		(void) duk__append_u32(re_ctx, (duk_uint32_t) (*values++));
-		count--;
+	if (!skip_round) {
+		if (duk__dragon4_fixed_format_round(nc_ctx, bitround)) {
+			/* Corner case: see test-numconv-parse-mant-carry.js.  We could
+			 * just bump the exponent and update bitstart, but it's more robust
+			 * to recompute (but avoid rounding twice).
+			 */
+			DUK_DDD(DUK_DDDPRINT("rounding caused exponent to be bumped, recheck exponent"));
+			skip_round = 1;
+			goto recheck_exp;
+		}
 	}
-}
 
-static void duk__insert_slice(duk_re_compiler_ctx *re_ctx, duk_uint32_t offset, duk_uint32_t data_offset, duk_uint32_t data_length) {
-	duk_hbuffer_insert_slice(re_ctx->thr, re_ctx->buf, offset, data_offset, (duk_size_t) data_length);
-}
-
-static void duk__append_slice(duk_re_compiler_ctx *re_ctx, duk_uint32_t data_offset, duk_uint32_t data_length) {
-	duk_hbuffer_append_slice(re_ctx->thr, re_ctx->buf, data_offset, (duk_size_t) data_length);
-}
-
-static void duk__remove_slice(duk_re_compiler_ctx *re_ctx, duk_uint32_t offset, duk_uint32_t length) {
-	duk_hbuffer_remove_slice(re_ctx->thr, re_ctx->buf, offset, (duk_size_t) length);
-}
+	/*
+	 *  Create mantissa
+	 */
 
-/*
- *  Insert a jump offset at 'offset' to complete an instruction
- *  (the jump offset is always the last component of an instruction).
- *  The 'skip' argument must be computed relative to 'offset',
- *  -without- taking into account the skip field being inserted.
- *
- *       ... A B C ins X Y Z ...   (ins may be a JUMP, SPLIT1/SPLIT2, etc)
- *   =>  ... A B C ins SKIP X Y Z
- *
- *  Computing the final (adjusted) skip value, which is relative to the
- *  first byte of the next instruction, is a bit tricky because of the
- *  variable length UTF-8 encoding.  See doc/regexp.txt for discussion.
- */
-static duk_uint32_t duk__insert_jump_offset(duk_re_compiler_ctx *re_ctx, duk_uint32_t offset, duk_int32_t skip) {
-	duk_small_int_t len;
+	t = 0;
+	for (i = 0; i < 52; i++) {
+		bitidx = bitstart + 52 - 1 - i;
+		if (bitidx >= nc_ctx->count) {
+			v = 0;
+		} else if (bitidx < 0) {
+			v = 0;
+		} else {
+			v = nc_ctx->digits[bitidx];
+		}
+		DUK_ASSERT(v == 0 || v == 1);
+		t += v << (i % 32);
+		if (i == 31) {
+			/* low 32 bits is complete */
+			DUK_DBLUNION_SET_LOW32(&u, t);
+			t = 0;
+		}
+	}
+	/* t has high mantissa */
 
-	/* XXX: solve into closed form (smaller code) */
+	DUK_DDD(DUK_DDDPRINT("mantissa is complete: %08lx %08lx",
+	                     (unsigned long) t,
+	                     (unsigned long) DUK_DBLUNION_GET_LOW32(&u)));
 
-	if (skip < 0) {
-		/* two encoding attempts suffices */
-		len = duk_unicode_get_xutf8_length((duk_codepoint_t) duk__encode_i32(skip));
-		len = duk_unicode_get_xutf8_length((duk_codepoint_t) duk__encode_i32(skip - (duk_int32_t) len));
-		DUK_ASSERT(duk_unicode_get_xutf8_length(duk__encode_i32(skip - (duk_int32_t) len)) == len);  /* no change */
-		skip -= (duk_int32_t) len;
+	DUK_ASSERT(expt >= 0 && expt <= 0x7ffL);
+	t += expt << 20;
+#if 0  /* caller handles sign change */
+	if (negative) {
+		t |= 0x80000000U;
 	}
-	return duk__insert_i32(re_ctx, offset, skip);
-}
+#endif
+	DUK_DBLUNION_SET_HIGH32(&u, t);
+
+	DUK_DDD(DUK_DDDPRINT("number is complete: %08lx %08lx",
+	                     (unsigned long) DUK_DBLUNION_GET_HIGH32(&u),
+	                     (unsigned long) DUK_DBLUNION_GET_LOW32(&u)));
 
-static duk_uint32_t duk__append_jump_offset(duk_re_compiler_ctx *re_ctx, duk_int32_t skip) {
-	return (duk_uint32_t) duk__insert_jump_offset(re_ctx, (duk_uint32_t) DUK__BUFLEN(re_ctx), skip);
+	*x = DUK_DBLUNION_GET_DOUBLE(&u);
 }
 
 /*
- *  duk_re_range_callback for generating character class ranges.
- *
- *  When ignoreCase is false, the range is simply emitted as is.
- *  We don't, for instance, eliminate duplicates or overlapping
- *  ranges in a character class.
- *
- *  When ignoreCase is true, the range needs to be normalized through
- *  canonicalization.  Unfortunately a canonicalized version of a
- *  continuous range is not necessarily continuous (e.g. [x-{] is
- *  continuous but [X-{] is not).  The current algorithm creates the
- *  canonicalized range(s) space efficiently at the cost of compile
- *  time execution time (see doc/regexp.txt for discussion).
+ *  Exposed number-to-string API
  *
- *  Note that the ctx->nranges is a context-wide temporary value
- *  (this is OK because there cannot be multiple character classes
- *  being parsed simultaneously).
+ *  Input: [ number ]
+ *  Output: [ string ]
  */
 
-static void duk__generate_ranges(void *userdata, duk_codepoint_t r1, duk_codepoint_t r2, duk_bool_t direct) {
-	duk_re_compiler_ctx *re_ctx = (duk_re_compiler_ctx *) userdata;
-
-	DUK_DD(DUK_DDPRINT("duk__generate_ranges(): re_ctx=%p, range=[%ld,%ld] direct=%ld",
-	                   (void *) re_ctx, (long) r1, (long) r2, (long) direct));
+DUK_INTERNAL void duk_numconv_stringify(duk_context *ctx, duk_small_int_t radix, duk_small_int_t digits, duk_small_uint_t flags) {
+	duk_double_t x;
+	duk_small_int_t c;
+	duk_small_int_t neg;
+	duk_uint32_t uval;
+	duk__numconv_stringify_ctx nc_ctx_alloc;  /* large context; around 2kB now */
+	duk__numconv_stringify_ctx *nc_ctx = &nc_ctx_alloc;
 
-	if (!direct && (re_ctx->re_flags & DUK_RE_FLAG_IGNORE_CASE)) {
-		/*
-		 *  Canonicalize a range, generating result ranges as necessary.
-		 *  Needs to exhaustively scan the entire range (at most 65536
-		 *  code points).  If 'direct' is set, caller (lexer) has ensured
-		 *  that the range is already canonicalization compatible (this
-		 *  is used to avoid unnecessary canonicalization of built-in
-		 *  ranges like \W, which are not affected by canonicalization).
-		 *
-		 *  NOTE: here is one place where we don't want to support chars
-		 *  outside the BMP, because the exhaustive search would be
-		 *  massively larger.
-		 */
+	x = (duk_double_t) duk_require_number(ctx, -1);
+	duk_pop(ctx);
 
-		duk_codepoint_t i;
-		duk_codepoint_t t;
-		duk_codepoint_t r_start, r_end;
+	/*
+	 *  Handle special cases (NaN, infinity, zero).
+	 */
 
-		r_start = duk_unicode_re_canonicalize_char(re_ctx->thr, r1);
-		r_end = r_start;
-		for (i = r1 + 1; i <= r2; i++) {
-			t = duk_unicode_re_canonicalize_char(re_ctx->thr, i);
-			if (t == r_end + 1) {
-				r_end = t;
-			} else {
-				DUK_DD(DUK_DDPRINT("canonicalized, emit range: [%ld,%ld]", (long) r_start, (long) r_end));
-				duk__append_u32(re_ctx, (duk_uint32_t) r_start);
-				duk__append_u32(re_ctx, (duk_uint32_t) r_end);
-				re_ctx->nranges++;
-				r_start = t;
-				r_end = t;
-			}
-		}
-		DUK_DD(DUK_DDPRINT("canonicalized, emit range: [%ld,%ld]", (long) r_start, (long) r_end));
-		duk__append_u32(re_ctx, (duk_uint32_t) r_start);
-		duk__append_u32(re_ctx, (duk_uint32_t) r_end);
-		re_ctx->nranges++;
+	c = (duk_small_int_t) DUK_FPCLASSIFY(x);
+	if (DUK_SIGNBIT((double) x)) {
+		x = -x;
+		neg = 1;
 	} else {
-		DUK_DD(DUK_DDPRINT("direct, emit range: [%ld,%ld]", (long) r1, (long) r2));
-		duk__append_u32(re_ctx, (duk_uint32_t) r1);
-		duk__append_u32(re_ctx, (duk_uint32_t) r2);
-		re_ctx->nranges++;
+		neg = 0;
 	}
-}
 
-/*
- *  Parse regexp Disjunction.  Most of regexp compilation happens here.
- *
- *  Handles Disjunction, Alternative, and Term productions directly without
- *  recursion.  The only constructs requiring recursion are positive/negative
- *  lookaheads, capturing parentheses, and non-capturing parentheses.
- *
- *  The function determines whether the entire disjunction is a 'simple atom'
- *  (see doc/regexp.txt discussion on 'simple quantifiers') and if so,
- *  returns the atom character length which is needed by the caller to keep
- *  track of its own atom character length.  A disjunction with more than one
- *  alternative is never considered a simple atom (although in some cases
- *  that might be the case).
- *
- *  Return value: simple atom character length or < 0 if not a simple atom.
- *  Appends the bytecode for the disjunction matcher to the end of the temp
- *  buffer.
- *
- *  Regexp top level structure is:
- *
- *    Disjunction = Term*
- *                | Term* | Disjunction
- *
- *    Term = Assertion
- *         | Atom
- *         | Atom Quantifier
- *
- *  An empty Term sequence is a valid disjunction alternative (e.g. /|||c||/).
- *
- *  Notes:
- *
- *    * Tracking of the 'simple-ness' of the current atom vs. the entire
- *      disjunction are separate matters.  For instance, the disjunction
- *      may be complex, but individual atoms may be simple.  Furthermore,
- *      simple quantifiers are used whenever possible, even if the
- *      disjunction as a whole is complex.
- *
- *    * The estimate of whether an atom is simple is conservative now,
- *      and it would be possible to expand it.  For instance, captures
- *      cause the disjunction to be marked complex, even though captures
- *      -can- be handled by simple quantifiers with some minor modifications.
- *
- *    * Disjunction 'tainting' as 'complex' is handled at the end of the
- *      main for loop collectively for atoms.  Assertions, quantifiers,
- *      and '|' tokens need to taint the result manually if necessary.
- *      Assertions cannot add to result char length, only atoms (and
- *      quantifiers) can; currently quantifiers will taint the result
- *      as complex though.
- */
+	/* NaN sign bit is platform specific with unpacked, un-normalized NaNs */
+	DUK_ASSERT(c == DUK_FP_NAN || DUK_SIGNBIT((double) x) == 0);
 
-static void duk__parse_disjunction(duk_re_compiler_ctx *re_ctx, duk_bool_t expect_eof, duk__re_disjunction_info *out_atom_info) {
-	duk_int32_t atom_start_offset = -1;                   /* negative -> no atom matched on previous round */
-	duk_int32_t atom_char_length = 0;                     /* negative -> complex atom */
-	duk_uint32_t atom_start_captures = re_ctx->captures;  /* value of re_ctx->captures at start of atom */
-	duk_int32_t unpatched_disjunction_split = -1;
-	duk_int32_t unpatched_disjunction_jump = -1;
-	duk_uint32_t entry_offset = (duk_uint32_t) DUK__BUFLEN(re_ctx);
-	duk_int32_t res_charlen = 0;  /* -1 if disjunction is complex, char length if simple */
-	duk__re_disjunction_info tmp_disj;
+	if (c == DUK_FP_NAN) {
+		duk_push_hstring_stridx(ctx, DUK_STRIDX_NAN);
+		return;
+	} else if (c == DUK_FP_INFINITE) {
+		if (neg) {
+			/* -Infinity */
+			duk_push_hstring_stridx(ctx, DUK_STRIDX_MINUS_INFINITY);
+		} else {
+			/* Infinity */
+			duk_push_hstring_stridx(ctx, DUK_STRIDX_INFINITY);
+		}
+		return;
+	} else if (c == DUK_FP_ZERO) {
+		/* We can't shortcut zero here if it goes through special formatting
+		 * (such as forced exponential notation).
+		 */
+		;
+	}
 
-	DUK_ASSERT(out_atom_info != NULL);
+	/*
+	 *  Handle integers in 32-bit range (that is, [-(2**32-1),2**32-1])
+	 *  specially, as they're very likely for embedded programs.  This
+	 *  is now done for all radix values.  We must be careful not to use
+	 *  the fast path when special formatting (e.g. forced exponential)
+	 *  is in force.
+	 *
+	 *  XXX: could save space by supporting radix 10 only and using
+	 *  sprintf "%lu" for the fast path and for exponent formatting.
+	 */
 
-	if (re_ctx->recursion_depth >= re_ctx->recursion_limit) {
-		DUK_ERROR(re_ctx->thr, DUK_ERR_INTERNAL_ERROR,
-		          "regexp compiler recursion limit reached");
+	uval = (unsigned int) x;
+	if (((double) uval) == x &&  /* integer number in range */
+	    flags == 0) {            /* no special formatting */
+		/* use bigint area as a temp */
+		duk_uint8_t *buf = (duk_uint8_t *) (&nc_ctx->f);
+		duk_uint8_t *p = buf;
+
+		DUK_ASSERT(DUK__NUMCONV_CTX_BIGINTS_SIZE >= 32 + 1);  /* max size: radix=2 + sign */
+		if (neg && uval != 0) {
+			/* no negative sign for zero */
+			*p++ = (duk_uint8_t) '-';
+		}
+		p += duk__dragon4_format_uint32(p, uval, radix);
+		duk_push_lstring(ctx, (const char *) buf, (duk_size_t) (p - buf));
+		return;
 	}
-	re_ctx->recursion_depth++;
 
+	/*
+	 *  Dragon4 setup.
+	 *
+	 *  Convert double from IEEE representation for conversion;
+	 *  normal finite values have an implicit leading 1-bit.  The
+	 *  slow path algorithm doesn't handle zero, so zero is special
+	 *  cased here but still creates a valid nc_ctx, and goes
+	 *  through normal formatting in case special formatting has
+	 *  been requested (e.g. forced exponential format: 0 -> "0e+0").
+	 */
+
+	/* Would be nice to bulk clear the allocation, but the context
+	 * is 1-2 kilobytes and nothing should rely on it being zeroed.
+	 */
 #if 0
-	out_atom_info->start_captures = re_ctx->captures;
+	DUK_MEMZERO((void *) nc_ctx, sizeof(*nc_ctx));  /* slow init, do only for slow path cases */
 #endif
 
-	for (;;) {
-		/* atom_char_length, atom_start_offset, atom_start_offset reflect the
-		 * atom matched on the previous loop.  If a quantifier is encountered
-		 * on this loop, these are needed to handle the quantifier correctly.
-		 * new_atom_char_length etc are for the atom parsed on this round;
-		 * they're written to atom_char_length etc at the end of the round.
-		 */
-		duk_int32_t new_atom_char_length;   /* char length of the atom parsed in this loop */
-		duk_int32_t new_atom_start_offset;  /* bytecode start offset of the atom parsed in this loop
-		                                     * (allows quantifiers to copy the atom bytecode)
-		                                     */
-		duk_uint32_t new_atom_start_captures;  /* re_ctx->captures at the start of the atom parsed in this loop */
-
-		duk_lexer_parse_re_token(&re_ctx->lex, &re_ctx->curr_token);
+	nc_ctx->is_s2n = 0;
+	nc_ctx->b = 2;
+	nc_ctx->B = radix;
+	nc_ctx->abs_pos = 0;
+	if (flags & DUK_N2S_FLAG_FIXED_FORMAT) {
+		nc_ctx->is_fixed = 1;
+		if (flags & DUK_N2S_FLAG_FRACTION_DIGITS) {
+			/* absolute req_digits; e.g. digits = 1 -> last digit is 0,
+			 * but add an extra digit for rounding.
+			 */
+			nc_ctx->abs_pos = 1;
+			nc_ctx->req_digits = (-digits + 1) - 1;
+		} else {
+			nc_ctx->req_digits = digits + 1;
+		}
+	} else {
+		nc_ctx->is_fixed = 0;
+		nc_ctx->req_digits = 0;
+	}
 
-		DUK_DD(DUK_DDPRINT("re token: %ld (num=%ld, char=%c)",
-		                   (long) re_ctx->curr_token.t,
-		                   (long) re_ctx->curr_token.num,
-		                   (re_ctx->curr_token.num >= 0x20 && re_ctx->curr_token.num <= 0x7e) ?
-		                   (int) re_ctx->curr_token.num : (int) '?'));
+	if (c == DUK_FP_ZERO) {
+		/* Zero special case: fake requested number of zero digits; ensure
+		 * no sign bit is printed.  Relative and absolute fixed format
+		 * require separate handling.
+		 */
+		duk_small_int_t count;
+		if (nc_ctx->is_fixed) {
+			if (nc_ctx->abs_pos) {
+				count = digits + 2;  /* lead zero + 'digits' fractions + 1 for rounding */
+			} else {
+				count = digits + 1;  /* + 1 for rounding */
+			}
+		} else {
+			count = 1;
+		}
+		DUK_DDD(DUK_DDDPRINT("count=%ld", (long) count));
+		DUK_ASSERT(count >= 1);
+		DUK_MEMZERO((void *) nc_ctx->digits, count);
+		nc_ctx->count = count;
+		nc_ctx->k = 1;  /* 0.000... */
+		neg = 0;
+		goto zero_skip;
+	}
 
-		/* set by atom case clauses */
-		new_atom_start_offset = -1;
-		new_atom_char_length = -1;
-		new_atom_start_captures = re_ctx->captures;
+	duk__dragon4_double_to_ctx(nc_ctx, x);   /* -> sets 'f' and 'e' */
+	DUK__BI_PRINT("f", &nc_ctx->f);
+	DUK_DDD(DUK_DDDPRINT("e=%ld", (long) nc_ctx->e));
 
-		switch (re_ctx->curr_token.t) {
-		case DUK_RETOK_DISJUNCTION: {
-			/*
-			 *  The handling here is a bit tricky.  If a previous '|' has been processed,
-			 *  we have a pending split1 and a pending jump (for a previous match).  These
-			 *  need to be back-patched carefully.  See docs for a detailed example.
-			 */
+	/*
+	 *  Dragon4 slow path digit generation.
+	 */
 
-			/* patch pending jump and split */
-			if (unpatched_disjunction_jump >= 0) {
-				duk_uint32_t offset;
+	duk__dragon4_prepare(nc_ctx);  /* setup many variables in nc_ctx */
 
-				DUK_ASSERT(unpatched_disjunction_split >= 0);
-				offset = unpatched_disjunction_jump;
-				offset += duk__insert_jump_offset(re_ctx,
-				                                  offset,
-				                                  (duk_int32_t) (DUK__BUFLEN(re_ctx) - offset));
-				/* offset is now target of the pending split (right after jump) */
-				duk__insert_jump_offset(re_ctx,
-				                        unpatched_disjunction_split,
-				                        offset - unpatched_disjunction_split);
-			}
+	DUK_DDD(DUK_DDDPRINT("after prepare:"));
+	DUK__BI_PRINT("r", &nc_ctx->r);
+	DUK__BI_PRINT("s", &nc_ctx->s);
+	DUK__BI_PRINT("mp", &nc_ctx->mp);
+	DUK__BI_PRINT("mm", &nc_ctx->mm);
 
-			/* add a new pending split to the beginning of the entire disjunction */
-			(void) duk__insert_u32(re_ctx,
-			                       entry_offset,
-			                       DUK_REOP_SPLIT1);   /* prefer direct execution */
-			unpatched_disjunction_split = entry_offset + 1;   /* +1 for opcode */
+	duk__dragon4_scale(nc_ctx);
 
-			/* add a new pending match jump for latest finished alternative */
-			duk__append_u32(re_ctx, DUK_REOP_JUMP);
-			unpatched_disjunction_jump = (duk_int32_t) DUK__BUFLEN(re_ctx);
+	DUK_DDD(DUK_DDDPRINT("after scale; k=%ld", (long) nc_ctx->k));
+	DUK__BI_PRINT("r", &nc_ctx->r);
+	DUK__BI_PRINT("s", &nc_ctx->s);
+	DUK__BI_PRINT("mp", &nc_ctx->mp);
+	DUK__BI_PRINT("mm", &nc_ctx->mm);
 
-			/* 'taint' result as complex */
-			res_charlen = -1;
-			break;
-		}
-		case DUK_RETOK_QUANTIFIER: {
-			if (atom_start_offset < 0) {
-				DUK_ERROR(re_ctx->thr, DUK_ERR_SYNTAX_ERROR,
-				          "quantifier without preceding atom");
-			}
-			if (re_ctx->curr_token.qmin > re_ctx->curr_token.qmax) {
-				DUK_ERROR(re_ctx->thr, DUK_ERR_SYNTAX_ERROR,
-				          "quantifier values invalid (qmin > qmax)");
-			}
-			if (atom_char_length >= 0) {
-				/*
-				 *  Simple atom
-				 *
-				 *  If atom_char_length is zero, we'll have unbounded execution time for e.g.
-			 	 *  /()*x/.exec('x').  We can't just skip the match because it might have some
-				 *  side effects (for instance, if we allowed captures in simple atoms, the
-				 *  capture needs to happen).  The simple solution below is to force the
-				 *  quantifier to match at most once, since the additional matches have no effect.
-				 *
-				 *  With a simple atom there can be no capture groups, so no captures need
-				 *  to be reset.
-				 */
-				duk_int32_t atom_code_length;
-				duk_uint32_t offset;
-				duk_uint32_t qmin, qmax;
+	duk__dragon4_generate(nc_ctx);
 
-				qmin = re_ctx->curr_token.qmin;
-				qmax = re_ctx->curr_token.qmax;
-				if (atom_char_length == 0) {
-					/* qmin and qmax will be 0 or 1 */
-					if (qmin > 1) {
-						qmin = 1;
-					}
-					if (qmax > 1) {
-						qmax = 1;
-					}
-				}
+	/*
+	 *  Convert and push final string.
+	 */
 
-				duk__append_u32(re_ctx, DUK_REOP_MATCH);   /* complete 'sub atom' */
-				atom_code_length = (duk_int32_t) (DUK__BUFLEN(re_ctx) - atom_start_offset);
+ zero_skip:
 
-				offset = atom_start_offset;
-				if (re_ctx->curr_token.greedy) {
-					offset += duk__insert_u32(re_ctx, offset, DUK_REOP_SQGREEDY);
-					offset += duk__insert_u32(re_ctx, offset, qmin);
-					offset += duk__insert_u32(re_ctx, offset, qmax);
-					offset += duk__insert_u32(re_ctx, offset, atom_char_length);
-					offset += duk__insert_jump_offset(re_ctx, offset, atom_code_length);
-				} else {
-					offset += duk__insert_u32(re_ctx, offset, DUK_REOP_SQMINIMAL);
-					offset += duk__insert_u32(re_ctx, offset, qmin);
-					offset += duk__insert_u32(re_ctx, offset, qmax);
-					offset += duk__insert_jump_offset(re_ctx, offset, atom_code_length);
-				}
-				DUK_UNREF(offset);  /* silence scan-build warning */
-			} else {
-				/*
-				 *  Complex atom
-				 *
-				 *  The original code is used as a template, and removed at the end
-				 *  (this differs from the handling of simple quantifiers).
-				 *
-				 *  NOTE: there is no current solution for empty atoms in complex
-				 *  quantifiers.  This would need some sort of a 'progress' instruction.
-				 *
-				 *  XXX: impose limit on maximum result size, i.e. atom_code_len * atom_copies?
-				 */
-				duk_int32_t atom_code_length;
-				duk_uint32_t atom_copies;
-				duk_uint32_t tmp_qmin, tmp_qmax;
+	if (flags & DUK_N2S_FLAG_FIXED_FORMAT) {
+		/* Perform fixed-format rounding. */
+		duk_small_int_t roundpos;
+		if (flags & DUK_N2S_FLAG_FRACTION_DIGITS) {
+			/* 'roundpos' is relative to nc_ctx->k and increases to the right
+			 * (opposite of how 'k' changes).
+			 */
+			roundpos = -digits;  /* absolute position for digit considered for rounding */
+			roundpos = nc_ctx->k - roundpos;
+		} else {
+			roundpos = digits;
+		}
+		DUK_DDD(DUK_DDDPRINT("rounding: k=%ld, count=%ld, digits=%ld, roundpos=%ld",
+		                     (long) nc_ctx->k, (long) nc_ctx->count, (long) digits, (long) roundpos));
+		(void) duk__dragon4_fixed_format_round(nc_ctx, roundpos);
 
-				/* pre-check how many atom copies we're willing to make (atom_copies not needed below) */
-				atom_copies = (re_ctx->curr_token.qmax == DUK_RE_QUANTIFIER_INFINITE) ?
-				              re_ctx->curr_token.qmin : re_ctx->curr_token.qmax;
-				if (atom_copies > DUK_RE_MAX_ATOM_COPIES) {
-					DUK_ERROR(re_ctx->thr, DUK_ERR_INTERNAL_ERROR,
-					          "quantifier expansion requires too many atom copies");
-				}
+		/* Note: 'count' is currently not adjusted by rounding (i.e. the
+		 * digits are not "chopped off".  That shouldn't matter because
+		 * the digit position (absolute or relative) is passed on to the
+		 * convert-and-push function.
+		 */
+	}
 
-				/* wipe the capture range made by the atom (if any) */
-				DUK_ASSERT(atom_start_captures <= re_ctx->captures);
-				if (atom_start_captures != re_ctx->captures) {
-					DUK_ASSERT(atom_start_captures < re_ctx->captures);
-					DUK_DDD(DUK_DDDPRINT("must wipe ]atom_start_captures,re_ctx->captures]: ]%ld,%ld]",
-					                     (long) atom_start_captures, (long) re_ctx->captures));
+	duk__dragon4_convert_and_push(nc_ctx, ctx, radix, digits, flags, neg);
+}
 
-					/* insert (DUK_REOP_WIPERANGE, start, count) in reverse order so the order ends up right */
-					duk__insert_u32(re_ctx, atom_start_offset, (re_ctx->captures - atom_start_captures) * 2);
-					duk__insert_u32(re_ctx, atom_start_offset, (atom_start_captures + 1) * 2);
-					duk__insert_u32(re_ctx, atom_start_offset, DUK_REOP_WIPERANGE);
-				} else {
-					DUK_DDD(DUK_DDDPRINT("no need to wipe captures: atom_start_captures == re_ctx->captures == %ld",
-					                     (long) atom_start_captures));
-				}
+/*
+ *  Exposed string-to-number API
+ *
+ *  Input: [ string ]
+ *  Output: [ number ]
+ *
+ *  If number parsing fails, a NaN is pushed as the result.  If number parsing
+ *  fails due to an internal error, an InternalError is thrown.
+ */
 
-				atom_code_length = (duk_int32_t) DUK__BUFLEN(re_ctx) - atom_start_offset;
+DUK_INTERNAL void duk_numconv_parse(duk_context *ctx, duk_small_int_t radix, duk_small_uint_t flags) {
+	duk_hthread *thr = (duk_hthread *) ctx;
+	duk__numconv_stringify_ctx nc_ctx_alloc;  /* large context; around 2kB now */
+	duk__numconv_stringify_ctx *nc_ctx = &nc_ctx_alloc;
+	duk_double_t res;
+	duk_hstring *h_str;
+	duk_small_int_t expt;
+	duk_small_int_t expt_neg;
+	duk_small_int_t expt_adj;
+	duk_small_int_t neg;
+	duk_small_int_t dig;
+	duk_small_int_t dig_whole;
+	duk_small_int_t dig_lzero;
+	duk_small_int_t dig_frac;
+	duk_small_int_t dig_expt;
+	duk_small_int_t dig_prec;
+	const duk__exp_limits *explim;
+	const duk_uint8_t *p;
+	duk_small_int_t ch;
 
-				/* insert the required matches (qmin) by copying the atom */
-				tmp_qmin = re_ctx->curr_token.qmin;
-				tmp_qmax = re_ctx->curr_token.qmax;
-				while (tmp_qmin > 0) {
-					duk__append_slice(re_ctx, atom_start_offset, atom_code_length);
-					tmp_qmin--;
-					if (tmp_qmax != DUK_RE_QUANTIFIER_INFINITE) {
-						tmp_qmax--;
-					}
-				}
-				DUK_ASSERT(tmp_qmin == 0);
+	/* This seems to waste a lot of stack frame entries, but good compilers
+	 * will compute these as needed below.  Some of these initial flags are
+	 * also modified in the code below, so they can't all be removed.
+	 */
+	duk_small_int_t trim_white = (flags & DUK_S2N_FLAG_TRIM_WHITE);
+	duk_small_int_t allow_expt = (flags & DUK_S2N_FLAG_ALLOW_EXP);
+	duk_small_int_t allow_garbage = (flags & DUK_S2N_FLAG_ALLOW_GARBAGE);
+	duk_small_int_t allow_plus = (flags & DUK_S2N_FLAG_ALLOW_PLUS);
+	duk_small_int_t allow_minus = (flags & DUK_S2N_FLAG_ALLOW_MINUS);
+	duk_small_int_t allow_infinity = (flags & DUK_S2N_FLAG_ALLOW_INF);
+	duk_small_int_t allow_frac = (flags & DUK_S2N_FLAG_ALLOW_FRAC);
+	duk_small_int_t allow_naked_frac = (flags & DUK_S2N_FLAG_ALLOW_NAKED_FRAC);
+	duk_small_int_t allow_empty_frac = (flags & DUK_S2N_FLAG_ALLOW_EMPTY_FRAC);
+	duk_small_int_t allow_empty = (flags & DUK_S2N_FLAG_ALLOW_EMPTY_AS_ZERO);
+	duk_small_int_t allow_leading_zero = (flags & DUK_S2N_FLAG_ALLOW_LEADING_ZERO);
+	duk_small_int_t allow_auto_hex_int = (flags & DUK_S2N_FLAG_ALLOW_AUTO_HEX_INT);
+	duk_small_int_t allow_auto_oct_int = (flags & DUK_S2N_FLAG_ALLOW_AUTO_OCT_INT);
 
-				/* insert code for matching the remainder - infinite or finite */
-				if (tmp_qmax == DUK_RE_QUANTIFIER_INFINITE) {
-					/* reuse last emitted atom for remaining 'infinite' quantifier */
+	DUK_DDD(DUK_DDDPRINT("parse number: %!T, radix=%ld, flags=0x%08lx",
+	                     (duk_tval *) duk_get_tval(ctx, -1),
+	                     (long) radix, (unsigned long) flags));
 
-					if (re_ctx->curr_token.qmin == 0) {
-						/* Special case: original qmin was zero so there is nothing
-						 * to repeat.  Emit an atom copy but jump over it here.
-						 */
-						duk__append_u32(re_ctx, DUK_REOP_JUMP);
-						duk__append_jump_offset(re_ctx, atom_code_length);
-						duk__append_slice(re_ctx, atom_start_offset, atom_code_length);
-					}
-					if (re_ctx->curr_token.greedy) {
-						duk__append_u32(re_ctx, DUK_REOP_SPLIT2);   /* prefer jump */
-					} else {
-						duk__append_u32(re_ctx, DUK_REOP_SPLIT1);   /* prefer direct */
-					}
-					duk__append_jump_offset(re_ctx, -atom_code_length - 1);  /* -1 for opcode */
-				} else {
-					/*
-					 *  The remaining matches are emitted as sequence of SPLITs and atom
-					 *  copies; the SPLITs skip the remaining copies and match the sequel.
-					 *  This sequence needs to be emitted starting from the last copy
-					 *  because the SPLITs are variable length due to the variable length
-					 *  skip offset.  This causes a lot of memory copying now.
-					 *
-					 *  Example structure (greedy, match maximum # atoms):
-					 *
-					 *      SPLIT1 LSEQ
-					 *      (atom)
-					 *      SPLIT1 LSEQ    ; <- the byte length of this instruction is needed
-					 *      (atom)	       ; to encode the above SPLIT1 correctly
-					 *      ...
-					 *   LSEQ:
-					 */
-					duk_uint32_t offset = (duk_uint32_t) DUK__BUFLEN(re_ctx);
-					while (tmp_qmax > 0) {
-						duk__insert_slice(re_ctx, offset, atom_start_offset, atom_code_length);
-						if (re_ctx->curr_token.greedy) {
-							duk__insert_u32(re_ctx, offset, DUK_REOP_SPLIT1);   /* prefer direct */
-						} else {
-							duk__insert_u32(re_ctx, offset, DUK_REOP_SPLIT2);   /* prefer jump */
-						}
-						duk__insert_jump_offset(re_ctx,
-						                        offset + 1,   /* +1 for opcode */
-						                        (duk_int32_t) (DUK__BUFLEN(re_ctx) - (offset + 1)));
-						tmp_qmax--;
-					}
-				}
+	DUK_ASSERT(radix >= 2 && radix <= 36);
+	DUK_ASSERT(radix - 2 < (duk_small_int_t) sizeof(duk__str2num_digits_for_radix));
 
-				/* remove the original 'template' atom */
-				duk__remove_slice(re_ctx, atom_start_offset, atom_code_length);
-			}
+	/*
+	 *  Preliminaries: trim, sign, Infinity check
+	 *
+	 *  We rely on the interned string having a NUL terminator, which will
+	 *  cause a parse failure wherever it is encountered.  As a result, we
+	 *  don't need separate pointer checks.
+	 *
+	 *  There is no special parsing for 'NaN' in the specification although
+	 *  'Infinity' (with an optional sign) is allowed in some contexts.
+	 *  Some contexts allow plus/minus sign, while others only allow the
+	 *  minus sign (like JSON.parse()).
+	 *
+	 *  Automatic hex number detection (leading '0x' or '0X') and octal
+	 *  number detection (leading '0' followed by at least one octal digit)
+	 *  is done here too.
+	 */
 
-			/* 'taint' result as complex */
-			res_charlen = -1;
-			break;
+	if (trim_white) {
+		/* Leading / trailing whitespace is sometimes accepted and
+		 * sometimes not.  After white space trimming, all valid input
+		 * characters are pure ASCII.
+		 */
+		duk_trim(ctx, -1);
+	}
+	h_str = duk_require_hstring(ctx, -1);
+	DUK_ASSERT(h_str != NULL);
+	p = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_str);
+
+	neg = 0;
+	ch = *p;
+	if (ch == (duk_small_int_t) '+') {
+		if (!allow_plus) {
+			DUK_DDD(DUK_DDDPRINT("parse failed: leading plus sign not allowed"));
+			goto parse_fail;
 		}
-		case DUK_RETOK_ASSERT_START: {
-			duk__append_u32(re_ctx, DUK_REOP_ASSERT_START);
-			break;
+		p++;
+	} else if (ch == (duk_small_int_t) '-') {
+		if (!allow_minus) {
+			DUK_DDD(DUK_DDDPRINT("parse failed: leading minus sign not allowed"));
+			goto parse_fail;
 		}
-		case DUK_RETOK_ASSERT_END: {
-			duk__append_u32(re_ctx, DUK_REOP_ASSERT_END);
-			break;
+		p++;
+		neg = 1;
+	}
+
+	ch = *p;
+	if (allow_infinity && ch == (duk_small_int_t) 'I') {
+		/* Don't check for Infinity unless the context allows it.
+		 * 'Infinity' is a valid integer literal in e.g. base-36:
+		 *
+		 *   parseInt('Infinity', 36)
+		 *   1461559270678
+		 */
+
+		const duk_uint8_t *q;
+
+		/* borrow literal Infinity from builtin string */
+		q = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(DUK_HTHREAD_STRING_INFINITY(thr));
+		if (DUK_STRNCMP((const char *) p, (const char *) q, 8) == 0) {
+			if (!allow_garbage && (p[8] != (duk_uint8_t) 0)) {
+				DUK_DDD(DUK_DDDPRINT("parse failed: trailing garbage after matching 'Infinity' not allowed"));
+				goto parse_fail;
+			} else {
+				res = DUK_DOUBLE_INFINITY;
+				goto negcheck_and_ret;
+			}
 		}
-		case DUK_RETOK_ASSERT_WORD_BOUNDARY: {
-			duk__append_u32(re_ctx, DUK_REOP_ASSERT_WORD_BOUNDARY);
-			break;
+	}
+	if (ch == (duk_small_int_t) '0') {
+		duk_small_int_t detect_radix = 0;
+		ch = p[1];
+		if (allow_auto_hex_int && (ch == (duk_small_int_t) 'x' || ch == (duk_small_int_t) 'X')) {
+			DUK_DDD(DUK_DDDPRINT("detected 0x/0X hex prefix, changing radix and preventing fractions and exponent"));
+			detect_radix = 16;
+			allow_empty = 0;  /* interpret e.g. '0x' and '0xg' as a NaN (= parse error) */
+			p += 2;
+		} else if (allow_auto_oct_int && (ch >= (duk_small_int_t) '0' && ch <= (duk_small_int_t) '9')) {
+			DUK_DDD(DUK_DDDPRINT("detected 0n oct prefix, changing radix and preventing fractions and exponent"));
+			detect_radix = 8;
+			allow_empty = 1;  /* interpret e.g. '09' as '0', not NaN */
+			p += 1;
 		}
-		case DUK_RETOK_ASSERT_NOT_WORD_BOUNDARY: {
-			duk__append_u32(re_ctx, DUK_REOP_ASSERT_NOT_WORD_BOUNDARY);
-			break;
+		if (detect_radix > 0) {
+			radix = detect_radix;
+			allow_expt = 0;
+			allow_frac = 0;
+			allow_naked_frac = 0;
+			allow_empty_frac = 0;
+			allow_leading_zero = 1;  /* allow e.g. '0x0009' and '00077' */
 		}
-		case DUK_RETOK_ASSERT_START_POS_LOOKAHEAD:
-		case DUK_RETOK_ASSERT_START_NEG_LOOKAHEAD: {
-			duk_uint32_t offset;
-			duk_uint32_t opcode = (re_ctx->curr_token.t == DUK_RETOK_ASSERT_START_POS_LOOKAHEAD) ?
-			                      DUK_REOP_LOOKPOS : DUK_REOP_LOOKNEG;
+	}
 
-			offset = (duk_uint32_t) DUK__BUFLEN(re_ctx);
-			duk__parse_disjunction(re_ctx, 0, &tmp_disj);
-			duk__append_u32(re_ctx, DUK_REOP_MATCH);
+	/*
+	 *  Scan number and setup for Dragon4.
+	 *
+	 *  The fast path case is detected during setup: an integer which
+	 *  can be converted without rounding, no net exponent.  The fast
+	 *  path could be implemented as a separate scan, but may not really
+	 *  be worth it: the multiplications for building 'f' are not
+	 *  expensive when 'f' is small.
+	 *
+	 *  The significand ('f') must contain enough bits of (apparent)
+	 *  accuracy, so that Dragon4 will generate enough binary output digits.
+	 *  For decimal numbers, this means generating a 20-digit significand,
+	 *  which should yield enough practical accuracy to parse IEEE doubles.
+	 *  In fact, the Ecmascript specification explicitly allows an
+	 *  implementation to treat digits beyond 20 as zeroes (and even
+	 *  to round the 20th digit upwards).  For non-decimal numbers, the
+	 *  appropriate number of digits has been precomputed for comparable
+	 *  accuracy.
+	 *
+	 *  Digit counts:
+	 *
+	 *    [ dig_lzero ]
+	 *      |
+	 *     .+-..---[ dig_prec ]----.
+	 *     |  ||                   |
+	 *     0000123.456789012345678901234567890e+123456
+	 *     |     | |                         |  |    |
+	 *     `--+--' `------[ dig_frac ]-------'  `-+--'
+	 *        |                                   |
+	 *    [ dig_whole ]                       [ dig_expt ]
+	 *
+	 *    dig_frac and dig_expt are -1 if not present
+	 *    dig_lzero is only computed for whole number part
+	 *
+	 *  Parsing state
+	 *
+	 *     Parsing whole part      dig_frac < 0 AND dig_expt < 0
+	 *     Parsing fraction part   dig_frac >= 0 AND dig_expt < 0
+	 *     Parsing exponent part   dig_expt >= 0   (dig_frac may be < 0 or >= 0)
+	 *
+	 *  Note: in case we hit an implementation limit (like exponent range),
+	 *  we should throw an error, NOT return NaN or Infinity.  Even with
+	 *  very large exponent (or significand) values the final result may be
+	 *  finite, so NaN/Infinity would be incorrect.
+	 */
 
-			(void) duk__insert_u32(re_ctx, offset, opcode);
-			(void) duk__insert_jump_offset(re_ctx,
-			                               offset + 1,   /* +1 for opcode */
-			                               (duk_int32_t) (DUK__BUFLEN(re_ctx) - (offset + 1)));
+	duk__bi_set_small(&nc_ctx->f, 0);
+	dig_prec = 0;
+	dig_lzero = 0;
+	dig_whole = 0;
+	dig_frac = -1;
+	dig_expt = -1;
+	expt = 0;
+	expt_adj = 0;  /* essentially tracks digit position of lowest 'f' digit */
+	expt_neg = 0;
+	for (;;) {
+		ch = *p++;
 
-			/* 'taint' result as complex -- this is conservative,
-			 * as lookaheads do not backtrack.
-			 */
-			res_charlen = -1;
-			break;
-		}
-		case DUK_RETOK_ATOM_PERIOD: {
-			new_atom_char_length = 1;
-			new_atom_start_offset = (duk_int32_t) DUK__BUFLEN(re_ctx);
-			duk__append_u32(re_ctx, DUK_REOP_PERIOD);
-			break;
-		}
-		case DUK_RETOK_ATOM_CHAR: {
-			/* Note: successive characters could be joined into string matches
-			 * but this is not trivial (consider e.g. '/xyz+/); see docs for
-			 * more discussion.
-			 */
-			duk_uint32_t ch;
+		DUK_DDD(DUK_DDDPRINT("parse digits: p=%p, ch='%c' (%ld), expt=%ld, expt_adj=%ld, "
+		                     "dig_whole=%ld, dig_frac=%ld, dig_expt=%ld, dig_lzero=%ld, dig_prec=%ld",
+		                     (const void *) p, (int) ((ch >= 0x20 && ch <= 0x7e) ? ch : '?'), (long) ch,
+		                     (long) expt, (long) expt_adj, (long) dig_whole, (long) dig_frac,
+		                     (long) dig_expt, (long) dig_lzero, (long) dig_prec));
+		DUK__BI_PRINT("f", &nc_ctx->f);
 
-			new_atom_char_length = 1;
-			new_atom_start_offset = (duk_int32_t) DUK__BUFLEN(re_ctx);
-			duk__append_u32(re_ctx, DUK_REOP_CHAR);
-			ch = re_ctx->curr_token.num;
-			if (re_ctx->re_flags & DUK_RE_FLAG_IGNORE_CASE) {
-				ch = duk_unicode_re_canonicalize_char(re_ctx->thr, ch);
+		/* Most common cases first. */
+		if (ch >= (duk_small_int_t) '0' && ch <= (duk_small_int_t) '9') {
+			dig = (int) ch - '0' + 0;
+		} else if (ch == (duk_small_int_t) '.') {
+			/* A leading digit is not required in some cases, e.g. accept ".123".
+			 * In other cases (JSON.parse()) a leading digit is required.  This
+			 * is checked for after the loop.
+			 */
+			if (dig_frac >= 0 || dig_expt >= 0) {
+				if (allow_garbage) {
+					DUK_DDD(DUK_DDDPRINT("garbage termination (invalid period)"));
+					break;
+				} else {
+					DUK_DDD(DUK_DDDPRINT("parse failed: period not allowed"));
+					goto parse_fail;
+				}
 			}
-			duk__append_u32(re_ctx, ch);
-			break;
-		}
-		case DUK_RETOK_ATOM_DIGIT:
-		case DUK_RETOK_ATOM_NOT_DIGIT: {
-			new_atom_char_length = 1;
-			new_atom_start_offset = (duk_int32_t) DUK__BUFLEN(re_ctx);
-			duk__append_u32(re_ctx,
-			                (re_ctx->curr_token.t == DUK_RETOK_ATOM_DIGIT) ?
-			                DUK_REOP_RANGES : DUK_REOP_INVRANGES);
-			duk__append_u32(re_ctx, sizeof(duk_unicode_re_ranges_digit) / (2 * sizeof(duk_uint16_t)));
-			duk__append_u16_list(re_ctx, duk_unicode_re_ranges_digit, sizeof(duk_unicode_re_ranges_digit) / sizeof(duk_uint16_t));
-			break;
-		}
-		case DUK_RETOK_ATOM_WHITE:
-		case DUK_RETOK_ATOM_NOT_WHITE: {
-			new_atom_char_length = 1;
-			new_atom_start_offset = (duk_int32_t) DUK__BUFLEN(re_ctx);
-			duk__append_u32(re_ctx,
-			                (re_ctx->curr_token.t == DUK_RETOK_ATOM_WHITE) ?
-			                DUK_REOP_RANGES : DUK_REOP_INVRANGES);
-			duk__append_u32(re_ctx, sizeof(duk_unicode_re_ranges_white) / (2 * sizeof(duk_uint16_t)));
-			duk__append_u16_list(re_ctx, duk_unicode_re_ranges_white, sizeof(duk_unicode_re_ranges_white) / sizeof(duk_uint16_t));
-			break;
-		}
-		case DUK_RETOK_ATOM_WORD_CHAR:
-		case DUK_RETOK_ATOM_NOT_WORD_CHAR: {
-			new_atom_char_length = 1;
-			new_atom_start_offset = (duk_int32_t) DUK__BUFLEN(re_ctx);
-			duk__append_u32(re_ctx,
-			                (re_ctx->curr_token.t == DUK_RETOK_ATOM_WORD_CHAR) ?
-			                DUK_REOP_RANGES : DUK_REOP_INVRANGES);
-			duk__append_u32(re_ctx, sizeof(duk_unicode_re_ranges_wordchar) / (2 * sizeof(duk_uint16_t)));
-			duk__append_u16_list(re_ctx, duk_unicode_re_ranges_wordchar, sizeof(duk_unicode_re_ranges_wordchar) / sizeof(duk_uint16_t));
-			break;
-		}
-		case DUK_RETOK_ATOM_BACKREFERENCE: {
-			duk_uint32_t backref = (duk_uint32_t) re_ctx->curr_token.num;
-			if (backref > re_ctx->highest_backref) {
-				re_ctx->highest_backref = backref;
+
+			if (!allow_frac) {
+				/* Some contexts don't allow fractions at all; this can't be a
+				 * post-check because the state ('f' and expt) would be incorrect.
+				 */
+				if (allow_garbage) {
+					DUK_DDD(DUK_DDDPRINT("garbage termination (invalid first period)"));
+					break;
+				} else {
+					DUK_DDD(DUK_DDDPRINT("parse failed: fraction part not allowed"));
+				}
 			}
-			new_atom_char_length = -1;   /* mark as complex */
-			new_atom_start_offset = (duk_int32_t) DUK__BUFLEN(re_ctx);
-			duk__append_u32(re_ctx, DUK_REOP_BACKREFERENCE);
-			duk__append_u32(re_ctx, backref);
-			break;
-		}
-		case DUK_RETOK_ATOM_START_CAPTURE_GROUP: {
-			duk_uint32_t cap;
 
-			new_atom_char_length = -1;   /* mark as complex (capture handling) */
-			new_atom_start_offset = (duk_int32_t) DUK__BUFLEN(re_ctx);
-			cap = ++re_ctx->captures;
-			duk__append_u32(re_ctx, DUK_REOP_SAVE);
-			duk__append_u32(re_ctx, cap * 2);
-			duk__parse_disjunction(re_ctx, 0, &tmp_disj);  /* retval (sub-atom char length) unused, tainted as complex above */
-			duk__append_u32(re_ctx, DUK_REOP_SAVE);
-			duk__append_u32(re_ctx, cap * 2 + 1);
-			break;
-		}
-		case DUK_RETOK_ATOM_START_NONCAPTURE_GROUP: {
-			new_atom_start_offset = (duk_int32_t) DUK__BUFLEN(re_ctx);
-			duk__parse_disjunction(re_ctx, 0, &tmp_disj);
-			new_atom_char_length = tmp_disj.charlen;
+			DUK_DDD(DUK_DDDPRINT("start fraction part"));
+			dig_frac = 0;
+			continue;
+		} else if (ch == (duk_small_int_t) 0) {
+			DUK_DDD(DUK_DDDPRINT("NUL termination"));
 			break;
-		}
-		case DUK_RETOK_ATOM_START_CHARCLASS:
-		case DUK_RETOK_ATOM_START_CHARCLASS_INVERTED: {
-			/*
-			 *  Range parsing is done with a special lexer function which calls
-			 *  us for every range parsed.  This is different from how rest of
-			 *  the parsing works, but avoids a heavy, arbitrary size intermediate
-			 *  value type to hold the ranges.
-			 *
-			 *  Another complication is the handling of character ranges when
-			 *  case insensitive matching is used (see docs for discussion).
-			 *  The range handler callback given to the lexer takes care of this
-			 *  as well.
-			 *
-			 *  Note that duplicate ranges are not eliminated when parsing character
-			 *  classes, so that canonicalization of
-			 *
-			 *    [0-9a-fA-Fx-{]
-			 *
-			 *  creates the result (note the duplicate ranges):
-			 *
-			 *    [0-9A-FA-FX-Z{-{]
+		} else if (allow_expt && dig_expt < 0 && (ch == (duk_small_int_t) 'e' || ch == (duk_small_int_t) 'E')) {
+			/* Note: we don't parse back exponent notation for anything else
+			 * than radix 10, so this is not an ambiguous check (e.g. hex
+			 * exponent values may have 'e' either as a significand digit
+			 * or as an exponent separator).
 			 *
-			 *  where [x-{] is split as a result of canonicalization.  The duplicate
-			 *  ranges are not a semantics issue: they work correctly.
+			 * If the exponent separator occurs twice, 'e' will be interpreted
+			 * as a digit (= 14) and will be rejected as an invalid decimal
+			 * digit.
 			 */
 
-			duk_uint32_t offset;
-
-			DUK_DD(DUK_DDPRINT("character class"));
-
-			/* insert ranges instruction, range count patched in later */
-			new_atom_char_length = 1;
-			new_atom_start_offset = (duk_int32_t) DUK__BUFLEN(re_ctx);
-			duk__append_u32(re_ctx,
-			                (re_ctx->curr_token.t == DUK_RETOK_ATOM_START_CHARCLASS) ?
-			                DUK_REOP_RANGES : DUK_REOP_INVRANGES);
-			offset = (duk_uint32_t) DUK__BUFLEN(re_ctx);    /* patch in range count later */
-
-			/* parse ranges until character class ends */
-			re_ctx->nranges = 0;    /* note: ctx-wide temporary */
-			duk_lexer_parse_re_ranges(&re_ctx->lex, duk__generate_ranges, (void *) re_ctx);
+			DUK_DDD(DUK_DDDPRINT("start exponent part"));
 
-			/* insert range count */
-			duk__insert_u32(re_ctx, offset, re_ctx->nranges);
-			break;
-		}
-		case DUK_RETOK_ATOM_END_GROUP: {
-			if (expect_eof) {
-				DUK_ERROR(re_ctx->thr, DUK_ERR_SYNTAX_ERROR,
-				          "unexpected closing parenthesis");
-			}
-			goto done;
-		}
-		case DUK_RETOK_EOF: {
-			if (!expect_eof) {
-				DUK_ERROR(re_ctx->thr, DUK_ERR_SYNTAX_ERROR,
-				          "unexpected end of pattern");
-			}
-			goto done;
-		}
-		default: {
-			DUK_ERROR(re_ctx->thr, DUK_ERR_SYNTAX_ERROR,
-			          "unexpected token in regexp");
-		}
+			/* Exponent without a sign or with a +/- sign is accepted
+			 * by all call sites (even JSON.parse()).
+			 */
+			ch = *p;
+			if (ch == (duk_small_int_t) '-') {
+				expt_neg = 1;
+				p++;
+			} else if (ch == (duk_small_int_t) '+') {
+				p++;
+			}
+			dig_expt = 0;
+			continue;
+		} else if (ch >= (duk_small_int_t) 'a' && ch <= (duk_small_int_t) 'z') {
+			dig = (duk_small_int_t) (ch - (duk_small_int_t) 'a' + 0x0a);
+		} else if (ch >= (duk_small_int_t) 'A' && ch <= (duk_small_int_t) 'Z') {
+			dig = (duk_small_int_t) (ch - (duk_small_int_t) 'A' + 0x0a);
+		} else {
+			dig = 255;  /* triggers garbage digit check below */
 		}
+		DUK_ASSERT((dig >= 0 && dig <= 35) || dig == 255);
 
-		/* a complex (new) atom taints the result */
-		if (new_atom_start_offset >= 0) {
-			if (new_atom_char_length < 0) {
-				res_charlen = -1;
-			} else if (res_charlen >= 0) {
-				/* only advance if not tainted */
-				res_charlen += new_atom_char_length;
+		if (dig >= radix) {
+			if (allow_garbage) {
+				DUK_DDD(DUK_DDDPRINT("garbage termination"));
+				break;
+			} else {
+				DUK_DDD(DUK_DDDPRINT("parse failed: trailing garbage or invalid digit"));
+				goto parse_fail;
 			}
 		}
 
-		/* record previous atom info in case next token is a quantifier */
-		atom_start_offset = new_atom_start_offset;
-		atom_char_length = new_atom_char_length;
-		atom_start_captures = new_atom_start_captures;
-	}
-
- done:
-
-	/* finish up pending jump and split for last alternative */
-	if (unpatched_disjunction_jump >= 0) {
-		duk_uint32_t offset;
+		if (dig_expt < 0) {
+			/* whole or fraction digit */
 
-		DUK_ASSERT(unpatched_disjunction_split >= 0);
-		offset = unpatched_disjunction_jump;
-		offset += duk__insert_jump_offset(re_ctx,
-		                                  offset,
-		                                  (duk_int32_t) (DUK__BUFLEN(re_ctx) - offset));
-		/* offset is now target of the pending split (right after jump) */
-		duk__insert_jump_offset(re_ctx,
-		                        unpatched_disjunction_split,
-		                        offset - unpatched_disjunction_split);
-	}
+			if (dig_prec < duk__str2num_digits_for_radix[radix - 2]) {
+				/* significant from precision perspective */
 
-#if 0
-	out_atom_info->end_captures = re_ctx->captures;
-#endif
-	out_atom_info->charlen = res_charlen;
-	DUK_DDD(DUK_DDDPRINT("parse disjunction finished: charlen=%ld",
-	                     (long) out_atom_info->charlen));
+				duk_small_int_t f_zero = duk__bi_is_zero(&nc_ctx->f);
+				if (f_zero && dig == 0) {
+					/* Leading zero is not counted towards precision digits; not
+					 * in the integer part, nor in the fraction part.
+					 */
+					if (dig_frac < 0) {
+						dig_lzero++;
+					}
+				} else {
+					/* XXX: join these ops (multiply-accumulate), but only if
+					 * code footprint decreases.
+					 */
+					duk__bi_mul_small(&nc_ctx->t1, &nc_ctx->f, radix);
+					duk__bi_add_small(&nc_ctx->f, &nc_ctx->t1, dig);
+					dig_prec++;
+				}
+			} else {
+				/* Ignore digits beyond a radix-specific limit, but note them
+				 * in expt_adj.
+				 */
+				expt_adj++;
+			}
 
-	re_ctx->recursion_depth--;
-}
+			if (dig_frac >= 0) {
+				dig_frac++;
+				expt_adj--;
+			} else {
+				dig_whole++;
+			}
+		} else {
+			/* exponent digit */
 
-/*
- *  Flags parsing (see E5 Section 15.10.4.1).
- */
+			expt = expt * radix + dig;
+			if (expt > DUK_S2N_MAX_EXPONENT) {
+				/* impose a reasonable exponent limit, so that exp
+				 * doesn't need to get tracked using a bigint.
+				 */
+				DUK_DDD(DUK_DDDPRINT("parse failed: exponent too large"));
+				goto parse_int_error;
+			}
+			dig_expt++;
+		}
+	}
 
-static duk_uint32_t duk__parse_regexp_flags(duk_hthread *thr, duk_hstring *h) {
-	duk_uint8_t *p;
-	duk_uint8_t *p_end;
-	duk_uint32_t flags = 0;
+	/* Leading zero. */
 
-	p = DUK_HSTRING_GET_DATA(h);
-	p_end = p + DUK_HSTRING_GET_BYTELEN(h);
+	if (dig_lzero > 0 && dig_whole > 1) {
+		if (!allow_leading_zero) {
+			DUK_DDD(DUK_DDDPRINT("parse failed: leading zeroes not allowed in integer part"));
+			goto parse_fail;
+		}
+	}
 
-	/* Note: can be safely scanned as bytes (undecoded) */
+	/* Validity checks for various fraction formats ("0.1", ".1", "1.", "."). */
 
-	while (p < p_end) {
-		duk_uint8_t c = *p++;
-		switch ((int) c) {
-		case (int) 'g': {
-			if (flags & DUK_RE_FLAG_GLOBAL) {
-				goto error;
+	if (dig_whole == 0) {
+		if (dig_frac == 0) {
+			/* "." is not accepted in any format */
+			DUK_DDD(DUK_DDDPRINT("parse failed: plain period without leading or trailing digits"));
+			goto parse_fail;
+		} else if (dig_frac > 0) {
+			/* ".123" */
+			if (!allow_naked_frac) {
+				DUK_DDD(DUK_DDDPRINT("parse failed: fraction part not allowed without "
+				                     "leading integer digit(s)"));
+				goto parse_fail;
 			}
-			flags |= DUK_RE_FLAG_GLOBAL;
-			break;
-		}
-		case (int) 'i': {
-			if (flags & DUK_RE_FLAG_IGNORE_CASE) {
-				goto error;
+		} else {
+			/* empty ("") is allowed in some formats (e.g. Number(''), as zero */
+			if (!allow_empty) {
+				DUK_DDD(DUK_DDDPRINT("parse failed: empty string not allowed (as zero)"));
+				goto parse_fail;
 			}
-			flags |= DUK_RE_FLAG_IGNORE_CASE;
-			break;
 		}
-		case (int) 'm': {
-			if (flags & DUK_RE_FLAG_MULTILINE) {
-				goto error;
+	} else {
+		if (dig_frac == 0) {
+			/* "123." is allowed in some formats */
+			if (!allow_empty_frac) {
+				DUK_DDD(DUK_DDDPRINT("parse failed: empty fractions"));
+				goto parse_fail;
 			}
-			flags |= DUK_RE_FLAG_MULTILINE;
-			break;
-		}
-		default: {
-			goto error;
-		}
+		} else if (dig_frac > 0) {
+			/* "123.456" */
+			;
+		} else {
+			/* "123" */
+			;
 		}
 	}
 
-	return flags;
-
- error:
-	DUK_ERROR(thr, DUK_ERR_SYNTAX_ERROR, "invalid regexp flags");
-	return 0;  /* never here */
-}
-
-/*
- *  Create escaped RegExp source (E5 Section 15.10.3).
- *
- *  The current approach is to special case the empty RegExp
- *  ('' -> '(?:)') and otherwise replace unescaped '/' characters
- *  with '\/' regardless of where they occur in the regexp.
- *
- *  Note that normalization does not seem to be necessary for
- *  RegExp literals (e.g. '/foo/') because to be acceptable as
- *  a RegExp literal, the text between forward slashes must
- *  already match the escaping requirements (e.g. must not contain
- *  unescaped forward slashes or be empty).  Escaping IS needed
- *  for expressions like 'new Regexp("...", "")' however.
- *  Currently, we re-escape in either case.
- *
- *  Also note that we process the source here in UTF-8 encoded
- *  form.  This is correct, because any non-ASCII characters are
- *  passed through without change.
- */
-
-static void duk__create_escaped_source(duk_hthread *thr, int idx_pattern) {
-	duk_context *ctx = (duk_context *) thr;
-	duk_hstring *h;
-	duk_hbuffer_dynamic *buf;
-	const duk_uint8_t *p;
-	duk_size_t i, n;
-	duk_uint_fast8_t c_prev, c;
-
-	h = duk_get_hstring(ctx, idx_pattern);
-	DUK_ASSERT(h != NULL);
-	p = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h);
-	n = (duk_size_t) DUK_HSTRING_GET_BYTELEN(h);
+	/* Exponent without digits (e.g. "1e" or "1e+").  If trailing garbage is
+	 * allowed, ignore exponent part as garbage (= parse as "1", i.e. exp 0).
+	 */
 
-	if (n == 0) {
-		/* return '(?:)' */
-		duk_push_hstring_stridx(ctx, DUK_STRIDX_ESCAPED_EMPTY_REGEXP);
-		return;
+	if (dig_expt == 0) {
+		if (!allow_garbage) {
+			DUK_DDD(DUK_DDDPRINT("parse failed: empty exponent"));
+			goto parse_fail;
+		}
+		DUK_ASSERT(expt == 0);
 	}
 
-	duk_push_dynamic_buffer(ctx, 0);
-	buf = (duk_hbuffer_dynamic *) duk_get_hbuffer(ctx, -1);
-	DUK_ASSERT(buf != NULL);
+	if (expt_neg) {
+		expt = -expt;
+	}
+	DUK_DDD(DUK_DDDPRINT("expt=%ld, expt_adj=%ld, net exponent -> %ld",
+	                     (long) expt, (long) expt_adj, (long) (expt + expt_adj)));
+	expt += expt_adj;
 
-	c_prev = (duk_uint_fast8_t) 0;
+	/* Fast path check. */
 
-	for (i = 0; i < n; i++) {
-		c = p[i];
+	if (nc_ctx->f.n <= 1 &&   /* 32-bit value */
+	    expt == 0    /* no net exponent */) {
+		/* Fast path is triggered for no exponent and also for balanced exponent
+		 * and fraction parts, e.g. for "1.23e2" == "123".  Remember to respect
+		 * zero sign.
+		 */
 
-		if (c == (duk_uint_fast8_t) '/' && c_prev != (duk_uint_fast8_t) '\\') {
-			/* Unescaped '/' ANYWHERE in the regexp (in disjunction,
-			 * inside a character class, ...) => same escape works.
-			 */
-			duk_hbuffer_append_byte(thr, buf, (duk_uint8_t) '\\');
+		/* XXX: could accept numbers larger than 32 bits, e.g. up to 53 bits? */
+		DUK_DDD(DUK_DDDPRINT("fast path number parse"));
+		if (nc_ctx->f.n == 1) {
+			res = (double) nc_ctx->f.v[0];
+		} else {
+			res = 0.0;
 		}
-		duk_hbuffer_append_byte(thr, buf, (duk_uint8_t) c);
-
-		c_prev = c;
+		goto negcheck_and_ret;
 	}
 
-	duk_to_string(ctx, -1);  /* -> [ ... escaped_source ] */
-}
+	/* Significand ('f') padding. */
 
-/*
- *  Exposed regexp compilation primitive.
- *
- *  Sets up a regexp compilation context, and calls duk__parse_disjunction() to do the
- *  actual parsing.  Handles generation of the compiled regexp header and the
- *  "boilerplate" capture of the matching substring (save 0 and 1).  Also does some
- *  global level regexp checks after recursive compilation has finished.
- *
- *  An escaped version of the regexp source, suitable for use as a RegExp instance
- *  'source' property (see E5 Section 15.10.3), is also left on the stack.
- *
- *  Input stack:  [ pattern flags ]
- *  Output stack: [ bytecode escaped_source ]  (both as strings)
- */
+	while (dig_prec < duk__str2num_digits_for_radix[radix - 2]) {
+		/* Pad significand with "virtual" zero digits so that Dragon4 will
+		 * have enough (apparent) precision to work with.
+		 */
+		DUK_DDD(DUK_DDDPRINT("dig_prec=%ld, pad significand with zero", (long) dig_prec));
+		duk__bi_mul_small_copy(&nc_ctx->f, radix, &nc_ctx->t1);
+		DUK__BI_PRINT("f", &nc_ctx->f);
+		expt--;
+		dig_prec++;
+	}
 
-void duk_regexp_compile(duk_hthread *thr) {
-	duk_context *ctx = (duk_context *) thr;
-	duk_re_compiler_ctx re_ctx;
-	duk_lexer_point lex_point;
-	duk_hstring *h_pattern;
-	duk_hstring *h_flags;
-	duk_hbuffer_dynamic *h_buffer;
-	duk__re_disjunction_info ign_disj;
+	DUK_DDD(DUK_DDDPRINT("final exponent: %ld", (long) expt));
 
-	DUK_ASSERT(thr != NULL);
-	DUK_ASSERT(ctx != NULL);
+	/* Detect zero special case. */
 
-	/*
-	 *  Args validation
-	 */
+	if (nc_ctx->f.n == 0) {
+		/* This may happen even after the fast path check, if exponent is
+		 * not balanced (e.g. "0e1").  Remember to respect zero sign.
+		 */
+		DUK_DDD(DUK_DDDPRINT("significand is zero"));
+		res = 0.0;
+		goto negcheck_and_ret;
+	}
 
-	/* TypeError if fails */
-	h_pattern = duk_require_hstring(ctx, -2);
-	h_flags = duk_require_hstring(ctx, -1);
 
-	/*
-	 *  Create normalized 'source' property (E5 Section 15.10.3).
+	/* Quick reject of too large or too small exponents.  This check
+	 * would be incorrect for zero (e.g. "0e1000" is zero, not Infinity)
+	 * so zero check must be above.
 	 */
 
-	/* [ ... pattern flags ] */
+	explim = &duk__str2num_exp_limits[radix - 2];
+	if (expt > explim->upper) {
+		DUK_DDD(DUK_DDDPRINT("exponent too large -> infinite"));
+		res = (duk_double_t) DUK_DOUBLE_INFINITY;
+		goto negcheck_and_ret;
+	} else if (expt < explim->lower) {
+		DUK_DDD(DUK_DDDPRINT("exponent too small -> zero"));
+		res = (duk_double_t) 0.0;
+		goto negcheck_and_ret;
+	}
 
-	duk__create_escaped_source(thr, -2);
+	nc_ctx->is_s2n = 1;
+	nc_ctx->e = expt;
+	nc_ctx->b = radix;
+	nc_ctx->B = 2;
+	nc_ctx->is_fixed = 1;
+	nc_ctx->abs_pos = 0;
+	nc_ctx->req_digits = 53 + 1;
 
-	/* [ ... pattern flags escaped_source ] */
+	DUK__BI_PRINT("f", &nc_ctx->f);
+	DUK_DDD(DUK_DDDPRINT("e=%ld", (long) nc_ctx->e));
 
 	/*
-	 *  Init compilation context
+	 *  Dragon4 slow path (binary) digit generation.
+	 *  An extra digit is generated for rounding.
 	 */
 
-	duk_push_dynamic_buffer(ctx, 0);
-	h_buffer = (duk_hbuffer_dynamic *) duk_require_hbuffer(ctx, -1);
-	DUK_ASSERT(DUK_HBUFFER_HAS_DYNAMIC(h_buffer));
+	duk__dragon4_prepare(nc_ctx);  /* setup many variables in nc_ctx */
 
-	/* [ ... pattern flags escaped_source buffer ] */
+	DUK_DDD(DUK_DDDPRINT("after prepare:"));
+	DUK__BI_PRINT("r", &nc_ctx->r);
+	DUK__BI_PRINT("s", &nc_ctx->s);
+	DUK__BI_PRINT("mp", &nc_ctx->mp);
+	DUK__BI_PRINT("mm", &nc_ctx->mm);
 
-	DUK_MEMZERO(&re_ctx, sizeof(re_ctx));
-	DUK_LEXER_INITCTX(&re_ctx.lex);  /* duplicate zeroing, expect for (possible) NULL inits */
-	re_ctx.thr = thr;
-	re_ctx.lex.thr = thr;
-	re_ctx.lex.input = DUK_HSTRING_GET_DATA(h_pattern);
-	re_ctx.lex.input_length = DUK_HSTRING_GET_BYTELEN(h_pattern);
-	re_ctx.lex.token_limit = DUK_RE_COMPILE_TOKEN_LIMIT;
-	re_ctx.buf = h_buffer;
-	re_ctx.recursion_limit = DUK_RE_COMPILE_RECURSION_LIMIT;
-	re_ctx.re_flags = duk__parse_regexp_flags(thr, h_flags);
+	duk__dragon4_scale(nc_ctx);
 
-	DUK_DD(DUK_DDPRINT("regexp compiler ctx initialized, flags=0x%08lx, recursion_limit=%ld",
-	                   (unsigned long) re_ctx.re_flags, (long) re_ctx.recursion_limit));
+	DUK_DDD(DUK_DDDPRINT("after scale; k=%ld", (long) nc_ctx->k));
+	DUK__BI_PRINT("r", &nc_ctx->r);
+	DUK__BI_PRINT("s", &nc_ctx->s);
+	DUK__BI_PRINT("mp", &nc_ctx->mp);
+	DUK__BI_PRINT("mm", &nc_ctx->mm);
 
-	/*
-	 *  Init lexer
-	 */
+	duk__dragon4_generate(nc_ctx);
 
-	lex_point.offset = 0;		/* expensive init, just want to fill window */
-	lex_point.line = 1;
-	DUK_LEXER_SETPOINT(&re_ctx.lex, &lex_point);
+	DUK_ASSERT(nc_ctx->count == 53 + 1);
 
 	/*
-	 *  Compilation
+	 *  Convert binary digits into an IEEE double.  Need to handle
+	 *  denormals and rounding correctly.
 	 */
 
-	DUK_D(DUK_DPRINT("starting regexp compilation"));
-
-	duk__append_u32(&re_ctx, DUK_REOP_SAVE);
-	duk__append_u32(&re_ctx, 0);
-	duk__parse_disjunction(&re_ctx, 1 /*expect_eof*/, &ign_disj);
-	duk__append_u32(&re_ctx, DUK_REOP_SAVE);
-	duk__append_u32(&re_ctx, 1);
-	duk__append_u32(&re_ctx, DUK_REOP_MATCH);
-
-	DUK_D(DUK_DPRINT("regexp bytecode size (before header) is %ld bytes",
-	                 (long) DUK_HBUFFER_GET_SIZE(re_ctx.buf)));
-
-	/*
-	 *  Check for invalid backreferences; note that it is NOT an error
-	 *  to back-reference a capture group which has not yet been introduced
-	 *  in the pattern (as in /\1(foo)/); in fact, the backreference will
-	 *  always match!  It IS an error to back-reference a capture group
-	 *  which will never be introduced in the pattern.  Thus, we can check
-	 *  for such references only after parsing is complete.
-	 */
+	duk__dragon4_ctx_to_double(nc_ctx, &res);
+	goto negcheck_and_ret;
 
-	if (re_ctx.highest_backref > re_ctx.captures) {
-		DUK_ERROR(thr, DUK_ERR_SYNTAX_ERROR, "invalid backreference(s)");
+ negcheck_and_ret:
+	if (neg) {
+		res = -res;
 	}
+	duk_pop(ctx);
+	duk_push_number(ctx, (double) res);
+	DUK_DDD(DUK_DDDPRINT("result: %!T", (duk_tval *) duk_get_tval(ctx, -1)));
+	return;
 
-	/*
-	 *  Emit compiled regexp header: flags, ncaptures
-	 *  (insertion order inverted on purpose)
-	 */
-
-	duk__insert_u32(&re_ctx, 0, (re_ctx.captures + 1) * 2);
-	duk__insert_u32(&re_ctx, 0, re_ctx.re_flags);
-
-	DUK_D(DUK_DPRINT("regexp bytecode size (after header) is %ld bytes",
-	                 (long) DUK_HBUFFER_GET_SIZE(re_ctx.buf)));
-	DUK_DDD(DUK_DDDPRINT("compiled regexp: %!xO", (duk_heaphdr *) re_ctx.buf));
-
-	/* [ ... pattern flags escaped_source buffer ] */
-
-	duk_to_string(ctx, -1);  /* coerce to string */
-
-	/* [ ... pattern flags escaped_source bytecode ] */
-
-	/*
-	 *  Finalize stack
-	 */
-
-	duk_remove(ctx, -4);     /* -> [ ... flags escaped_source bytecode ] */
-	duk_remove(ctx, -3);     /* -> [ ... escaped_source bytecode ] */
+ parse_fail:
+	DUK_DDD(DUK_DDDPRINT("parse failed"));
+	duk_pop(ctx);
+	duk_push_nan(ctx);
+	return;
 
-	DUK_D(DUK_DPRINT("regexp compilation successful, bytecode: %!T, escaped source: %!T",
-	                 (duk_tval *) duk_get_tval(ctx, -1), (duk_tval *) duk_get_tval(ctx, -2)));
+ parse_int_error:
+	DUK_DDD(DUK_DDDPRINT("parse failed, internal error, can't return a value"));
+	DUK_ERROR(thr, DUK_ERR_INTERNAL_ERROR, "number parse error");
+	return;
 }
-
+#line 1 "duk_regexp_compiler.c"
 /*
- *  Create a RegExp instance (E5 Section 15.10.7).
+ *  Regexp compilation.
  *
- *  Note: the output stack left by duk_regexp_compile() is directly compatible
- *  with the input here.
+ *  See doc/regexp.rst for a discussion of the compilation approach and
+ *  current limitations.
  *
- *  Input stack:  [ escaped_source bytecode ]  (both as strings)
- *  Output stack: [ RegExp ]
+ *  Regexp bytecode assumes jumps can be expressed with signed 32-bit
+ *  integers.  Consequently the bytecode size must not exceed 0x7fffffffL.
+ *  The implementation casts duk_size_t (buffer size) to duk_(u)int32_t
+ *  in many places.  Although this could be changed, the bytecode format
+ *  limit would still prevent regexps exceeding the signed 32-bit limit
+ *  from working.
+ *
+ *  XXX: The implementation does not prevent bytecode from exceeding the
+ *  maximum supported size.  This could be done by limiting the maximum
+ *  input string size (assuming an upper bound can be computed for number
+ *  of bytecode bytes emitted per input byte) or checking buffer maximum
+ *  size when emitting bytecode (slower).
  */
- 
-void duk_regexp_create_instance(duk_hthread *thr) {
-	duk_context *ctx = (duk_context *) thr;
-	duk_hobject *h;
-	duk_hstring *h_bc;
-	duk_small_int_t re_flags;
-
-	/* [ ... escape_source bytecode ] */
-
-	h_bc = duk_get_hstring(ctx, -1);
-	DUK_ASSERT(h_bc != NULL);
-	DUK_ASSERT(DUK_HSTRING_GET_BYTELEN(h_bc) >= 1);          /* always at least the header */
-	DUK_ASSERT(DUK_HSTRING_GET_CHARLEN(h_bc) >= 1);
-	DUK_ASSERT((duk_small_int_t) DUK_HSTRING_GET_DATA(h_bc)[0] < 0x80);  /* flags always encodes to 1 byte */
-	re_flags = (duk_small_int_t) DUK_HSTRING_GET_DATA(h_bc)[0];
-
-	/* [ ... escaped_source bytecode ] */
-
-	duk_push_object(ctx);
-	h = duk_get_hobject(ctx, -1);
-	DUK_ASSERT(h != NULL);
-	duk_insert(ctx, -3);
-
-	/* [ ... regexp_object escaped_source bytecode ] */
-
-	DUK_HOBJECT_SET_CLASS_NUMBER(h, DUK_HOBJECT_CLASS_REGEXP);
-	DUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr, h, thr->builtins[DUK_BIDX_REGEXP_PROTOTYPE]);
-
-	duk_def_prop_stridx(ctx, -3, DUK_STRIDX_INT_BYTECODE, DUK_PROPDESC_FLAGS_NONE);
-
-	/* [ ... regexp_object escaped_source ] */
-
-	duk_def_prop_stridx(ctx, -2, DUK_STRIDX_SOURCE, DUK_PROPDESC_FLAGS_NONE);
-
-	/* [ ... regexp_object ] */
-
-	duk_push_boolean(ctx, (re_flags & DUK_RE_FLAG_GLOBAL));
-	duk_def_prop_stridx(ctx, -2, DUK_STRIDX_GLOBAL, DUK_PROPDESC_FLAGS_NONE);
-
-	duk_push_boolean(ctx, (re_flags & DUK_RE_FLAG_IGNORE_CASE));
-	duk_def_prop_stridx(ctx, -2, DUK_STRIDX_IGNORE_CASE, DUK_PROPDESC_FLAGS_NONE);
 
-	duk_push_boolean(ctx, (re_flags & DUK_RE_FLAG_MULTILINE));
-	duk_def_prop_stridx(ctx, -2, DUK_STRIDX_MULTILINE, DUK_PROPDESC_FLAGS_NONE);
-
-	duk_push_int(ctx, 0);
-	duk_def_prop_stridx(ctx, -2, DUK_STRIDX_LAST_INDEX, DUK_PROPDESC_FLAGS_W);
-
-	/* [ ... regexp_object ] */
-}
+/* include removed: duk_internal.h */
 
-#undef DUK__BUFLEN
+#ifdef DUK_USE_REGEXP_SUPPORT
 
-#else  /* DUK_USE_REGEXP_SUPPORT */
+/*
+ *  Helper macros
+ */
 
-/* regexp support disabled */
+#define DUK__RE_INITIAL_BUFSIZE 64
 
-#endif  /* DUK_USE_REGEXP_SUPPORT */
+#undef DUK__RE_BUFLEN
+#define DUK__RE_BUFLEN(re_ctx) \
+	DUK_BW_GET_SIZE(re_ctx->thr, &re_ctx->bw)
 
-#line 1 "duk_regexp_executor.c"
 /*
- *  Regexp executor.
- *
- *  Safety: the Ecmascript executor should prevent user from reading and
- *  replacing regexp bytecode.  Even so, the executor must validate all
- *  memory accesses etc.  When an invalid access is detected (e.g. a 'save'
- *  opcode to invalid, unallocated index) it should fail with an internal
- *  error but not cause a segmentation fault.
- *
- *  Notes:
- *
- *    - Backtrack counts are limited to unsigned 32 bits but should
- *      technically be duk_size_t for strings longer than 4G chars.
- *      This also requires a regexp bytecode change.
+ *  Disjunction struct: result of parsing a disjunction
  */
 
-/* include removed: duk_internal.h */
+typedef struct {
+	/* Number of characters that the atom matches (e.g. 3 for 'abc'),
+	 * -1 if atom is complex and number of matched characters either
+	 * varies or is not known.
+	 */
+	duk_int32_t charlen;
 
-#ifdef DUK_USE_REGEXP_SUPPORT
+#if 0
+	/* These are not needed to implement quantifier capture handling,
+	 * but might be needed at some point.
+	 */
+
+	/* re_ctx->captures at start and end of atom parsing.
+	 * Since 'captures' indicates highest capture number emitted
+	 * so far in a DUK_REOP_SAVE, the captures numbers saved by
+	 * the atom are: ]start_captures,end_captures].
+	 */
+	duk_uint32_t start_captures;
+	duk_uint32_t end_captures;
+#endif
+} duk__re_disjunction_info;
 
 /*
- *  Helpers for UTF-8 handling
+ *  Encoding helpers
  *
- *  For bytecode readers the duk_uint32_t and duk_int32_t types are correct
- *  because they're used for more than just codepoints.
+ *  Some of the typing is bytecode based, e.g. slice sizes are unsigned 32-bit
+ *  even though the buffer operations will use duk_size_t.
  */
 
-static duk_uint32_t duk__bc_get_u32(duk_re_matcher_ctx *re_ctx, duk_uint8_t **pc) {
-	return (duk_uint32_t) duk_unicode_decode_xutf8_checked(re_ctx->thr, pc, re_ctx->bytecode, re_ctx->bytecode_end);
-}
-
-static duk_int32_t duk__bc_get_i32(duk_re_matcher_ctx *re_ctx, duk_uint8_t **pc) {
-	duk_uint32_t t;
+/* XXX: the insert helpers should ensure that the bytecode result is not
+ * larger than expected (or at least assert for it).  Many things in the
+ * bytecode, like skip offsets, won't work correctly if the bytecode is
+ * larger than say 2G.
+ */
 
-	/* signed integer encoding needed to work with UTF-8 */
-	t = (duk_uint32_t) duk_unicode_decode_xutf8_checked(re_ctx->thr, pc, re_ctx->bytecode, re_ctx->bytecode_end);
-	if (t & 1) {
-		return -((duk_int32_t) (t >> 1));
+DUK_LOCAL duk_uint32_t duk__encode_i32(duk_int32_t x) {
+	if (x < 0) {
+		return ((duk_uint32_t) (-x)) * 2 + 1;
 	} else {
-		return (duk_int32_t) (t >> 1);
+		return ((duk_uint32_t) x) * 2;
 	}
 }
 
-static duk_uint8_t *duk__utf8_backtrack(duk_hthread *thr, duk_uint8_t **ptr, duk_uint8_t *ptr_start, duk_uint8_t *ptr_end, duk_uint_fast32_t count) {
-	duk_uint8_t *p;
+/* XXX: return type should probably be duk_size_t, or explicit checks are needed for
+ * maximum size.
+ */
+DUK_LOCAL duk_uint32_t duk__insert_u32(duk_re_compiler_ctx *re_ctx, duk_uint32_t offset, duk_uint32_t x) {
+	duk_uint8_t buf[DUK_UNICODE_MAX_XUTF8_LENGTH];
+	duk_small_int_t len;
 
-	/* Note: allow backtracking from p == ptr_end */
-	p = *ptr;
-	if (p < ptr_start || p > ptr_end) {
-		goto fail;
-	}
+	len = duk_unicode_encode_xutf8((duk_ucodepoint_t) x, buf);
+	DUK_BW_INSERT_ENSURE_BYTES(re_ctx->thr, &re_ctx->bw, offset, buf, len);
+	return (duk_uint32_t) len;
+}
 
-	while (count > 0) {
-		for (;;) {
-			p--;
-			if (p < ptr_start) {
-				goto fail;
-			}
-			if ((*p & 0xc0) != 0x80) {
-				/* utf-8 continuation bytes have the form 10xx xxxx */
-				break;
-			}
-		}
-		count--;
-	}
-	*ptr = p;
-	return p;
+DUK_LOCAL duk_uint32_t duk__append_u32(duk_re_compiler_ctx *re_ctx, duk_uint32_t x) {
+	duk_uint8_t buf[DUK_UNICODE_MAX_XUTF8_LENGTH];
+	duk_small_int_t len;
 
- fail:
-	DUK_ERROR(thr, DUK_ERR_INTERNAL_ERROR, "regexp backtrack failed");
-	return NULL;  /* never here */
+	len = duk_unicode_encode_xutf8((duk_ucodepoint_t) x, buf);
+	DUK_BW_WRITE_ENSURE_BYTES(re_ctx->thr, &re_ctx->bw, buf, len);
+	return (duk_uint32_t) len;
 }
 
-static duk_uint8_t *duk__utf8_advance(duk_hthread *thr, duk_uint8_t **ptr, duk_uint8_t *ptr_start, duk_uint8_t *ptr_end, duk_uint_fast32_t count) {
-	duk_uint8_t *p;
+DUK_LOCAL duk_uint32_t duk__insert_i32(duk_re_compiler_ctx *re_ctx, duk_uint32_t offset, duk_int32_t x) {
+	return duk__insert_u32(re_ctx, offset, duk__encode_i32(x));
+}
 
-	p = *ptr;
-	if (p < ptr_start || p >= ptr_end) {
-		goto fail;
-	}
+#if 0  /* unused */
+DUK_LOCAL duk_uint32_t duk__append_i32(duk_re_compiler_ctx *re_ctx, duk_int32_t x) {
+	return duk__append_u32(re_ctx, duk__encode_i32(x));
+}
+#endif
 
+/* special helper for emitting u16 lists (used for character ranges for built-in char classes) */
+DUK_LOCAL void duk__append_u16_list(duk_re_compiler_ctx *re_ctx, duk_uint16_t *values, duk_uint32_t count) {
+	/* Call sites don't need the result length so it's not accumulated. */
 	while (count > 0) {
-		for (;;) {
-			p++;
-
-			/* Note: if encoding ends by hitting end of input, we don't check that
-			 * the encoding is valid, we just assume it is.
-			 */
-			if (p >= ptr_end || ((*p & 0xc0) != 0x80)) {
-				/* utf-8 continuation bytes have the form 10xx xxxx */
-				break;
-			}
-		}
+		(void) duk__append_u32(re_ctx, (duk_uint32_t) (*values++));
 		count--;
 	}
+}
 
-	*ptr = p;
-	return p;
+DUK_LOCAL void duk__insert_slice(duk_re_compiler_ctx *re_ctx, duk_uint32_t offset, duk_uint32_t data_offset, duk_uint32_t data_length) {
+	DUK_BW_INSERT_ENSURE_SLICE(re_ctx->thr, &re_ctx->bw, offset, data_offset, data_length);
+}
 
- fail:
-	DUK_ERROR(thr, DUK_ERR_INTERNAL_ERROR, "regexp advance failed");
-	return NULL;  /* never here */
+DUK_LOCAL void duk__append_slice(duk_re_compiler_ctx *re_ctx, duk_uint32_t data_offset, duk_uint32_t data_length) {
+	DUK_BW_WRITE_ENSURE_SLICE(re_ctx->thr, &re_ctx->bw, data_offset, data_length);
+}
+
+DUK_LOCAL void duk__remove_slice(duk_re_compiler_ctx *re_ctx, duk_uint32_t data_offset, duk_uint32_t data_length) {
+	DUK_BW_REMOVE_ENSURE_SLICE(re_ctx->thr, &re_ctx->bw, data_offset, data_length);
 }
 
 /*
- *  Helpers for dealing with the input string
+ *  Insert a jump offset at 'offset' to complete an instruction
+ *  (the jump offset is always the last component of an instruction).
+ *  The 'skip' argument must be computed relative to 'offset',
+ *  -without- taking into account the skip field being inserted.
+ *
+ *       ... A B C ins X Y Z ...   (ins may be a JUMP, SPLIT1/SPLIT2, etc)
+ *   =>  ... A B C ins SKIP X Y Z
+ *
+ *  Computing the final (adjusted) skip value, which is relative to the
+ *  first byte of the next instruction, is a bit tricky because of the
+ *  variable length UTF-8 encoding.  See doc/regexp.rst for discussion.
  */
+DUK_LOCAL duk_uint32_t duk__insert_jump_offset(duk_re_compiler_ctx *re_ctx, duk_uint32_t offset, duk_int32_t skip) {
+	duk_small_int_t len;
 
-/* Get a (possibly canonicalized) input character from current sp.  The input
- * itself is never modified, and captures always record non-canonicalized
- * characters even in case-insensitive matching.
- */
-static duk_codepoint_t duk__inp_get_cp(duk_re_matcher_ctx *re_ctx, duk_uint8_t **sp) {
-	duk_codepoint_t res = (duk_codepoint_t) duk_unicode_decode_xutf8_checked(re_ctx->thr, sp, re_ctx->input, re_ctx->input_end);
-	if (re_ctx->re_flags & DUK_RE_FLAG_IGNORE_CASE) {
-		res = duk_unicode_re_canonicalize_char(re_ctx->thr, res);
+	/* XXX: solve into closed form (smaller code) */
+
+	if (skip < 0) {
+		/* two encoding attempts suffices */
+		len = duk_unicode_get_xutf8_length((duk_codepoint_t) duk__encode_i32(skip));
+		len = duk_unicode_get_xutf8_length((duk_codepoint_t) duk__encode_i32(skip - (duk_int32_t) len));
+		DUK_ASSERT(duk_unicode_get_xutf8_length(duk__encode_i32(skip - (duk_int32_t) len)) == len);  /* no change */
+		skip -= (duk_int32_t) len;
 	}
-	return res;
+	return duk__insert_i32(re_ctx, offset, skip);
 }
 
-static duk_uint8_t *duk__inp_backtrack(duk_re_matcher_ctx *re_ctx, duk_uint8_t **sp, duk_uint_fast32_t count) {
-	return duk__utf8_backtrack(re_ctx->thr, sp, re_ctx->input, re_ctx->input_end, count);
+DUK_LOCAL duk_uint32_t duk__append_jump_offset(duk_re_compiler_ctx *re_ctx, duk_int32_t skip) {
+	return (duk_uint32_t) duk__insert_jump_offset(re_ctx, (duk_uint32_t) DUK__RE_BUFLEN(re_ctx), skip);
 }
 
-/* Backtrack utf-8 input and return a (possibly canonicalized) input character. */
-static duk_codepoint_t duk__inp_get_prev_cp(duk_re_matcher_ctx *re_ctx, duk_uint8_t *sp) {
-	/* note: caller 'sp' is intentionally not updated here */
-	(void) duk__inp_backtrack(re_ctx, &sp, (duk_uint_fast32_t) 1);
-	return duk__inp_get_cp(re_ctx, &sp);
+/*
+ *  duk_re_range_callback for generating character class ranges.
+ *
+ *  When ignoreCase is false, the range is simply emitted as is.
+ *  We don't, for instance, eliminate duplicates or overlapping
+ *  ranges in a character class.
+ *
+ *  When ignoreCase is true, the range needs to be normalized through
+ *  canonicalization.  Unfortunately a canonicalized version of a
+ *  continuous range is not necessarily continuous (e.g. [x-{] is
+ *  continuous but [X-{] is not).  The current algorithm creates the
+ *  canonicalized range(s) space efficiently at the cost of compile
+ *  time execution time (see doc/regexp.rst for discussion).
+ *
+ *  Note that the ctx->nranges is a context-wide temporary value
+ *  (this is OK because there cannot be multiple character classes
+ *  being parsed simultaneously).
+ */
+
+DUK_LOCAL void duk__generate_ranges(void *userdata, duk_codepoint_t r1, duk_codepoint_t r2, duk_bool_t direct) {
+	duk_re_compiler_ctx *re_ctx = (duk_re_compiler_ctx *) userdata;
+
+	DUK_DD(DUK_DDPRINT("duk__generate_ranges(): re_ctx=%p, range=[%ld,%ld] direct=%ld",
+	                   (void *) re_ctx, (long) r1, (long) r2, (long) direct));
+
+	if (!direct && (re_ctx->re_flags & DUK_RE_FLAG_IGNORE_CASE)) {
+		/*
+		 *  Canonicalize a range, generating result ranges as necessary.
+		 *  Needs to exhaustively scan the entire range (at most 65536
+		 *  code points).  If 'direct' is set, caller (lexer) has ensured
+		 *  that the range is already canonicalization compatible (this
+		 *  is used to avoid unnecessary canonicalization of built-in
+		 *  ranges like \W, which are not affected by canonicalization).
+		 *
+		 *  NOTE: here is one place where we don't want to support chars
+		 *  outside the BMP, because the exhaustive search would be
+		 *  massively larger.
+		 */
+
+		duk_codepoint_t i;
+		duk_codepoint_t t;
+		duk_codepoint_t r_start, r_end;
+
+		r_start = duk_unicode_re_canonicalize_char(re_ctx->thr, r1);
+		r_end = r_start;
+		for (i = r1 + 1; i <= r2; i++) {
+			t = duk_unicode_re_canonicalize_char(re_ctx->thr, i);
+			if (t == r_end + 1) {
+				r_end = t;
+			} else {
+				DUK_DD(DUK_DDPRINT("canonicalized, emit range: [%ld,%ld]", (long) r_start, (long) r_end));
+				duk__append_u32(re_ctx, (duk_uint32_t) r_start);
+				duk__append_u32(re_ctx, (duk_uint32_t) r_end);
+				re_ctx->nranges++;
+				r_start = t;
+				r_end = t;
+			}
+		}
+		DUK_DD(DUK_DDPRINT("canonicalized, emit range: [%ld,%ld]", (long) r_start, (long) r_end));
+		duk__append_u32(re_ctx, (duk_uint32_t) r_start);
+		duk__append_u32(re_ctx, (duk_uint32_t) r_end);
+		re_ctx->nranges++;
+	} else {
+		DUK_DD(DUK_DDPRINT("direct, emit range: [%ld,%ld]", (long) r1, (long) r2));
+		duk__append_u32(re_ctx, (duk_uint32_t) r1);
+		duk__append_u32(re_ctx, (duk_uint32_t) r2);
+		re_ctx->nranges++;
+	}
 }
-	
+
 /*
- *  Regexp recursive matching function.
+ *  Parse regexp Disjunction.  Most of regexp compilation happens here.
  *
- *  Returns 'sp' on successful match (points to character after last matched one),
- *  NULL otherwise.
+ *  Handles Disjunction, Alternative, and Term productions directly without
+ *  recursion.  The only constructs requiring recursion are positive/negative
+ *  lookaheads, capturing parentheses, and non-capturing parentheses.
  *
- *  The C recursion depth limit check is only performed in this function, this
- *  suffices because the function is present in all true recursion required by
- *  regexp execution.
+ *  The function determines whether the entire disjunction is a 'simple atom'
+ *  (see doc/regexp.rst discussion on 'simple quantifiers') and if so,
+ *  returns the atom character length which is needed by the caller to keep
+ *  track of its own atom character length.  A disjunction with more than one
+ *  alternative is never considered a simple atom (although in some cases
+ *  that might be the case).
+ *
+ *  Return value: simple atom character length or < 0 if not a simple atom.
+ *  Appends the bytecode for the disjunction matcher to the end of the temp
+ *  buffer.
+ *
+ *  Regexp top level structure is:
+ *
+ *    Disjunction = Term*
+ *                | Term* | Disjunction
+ *
+ *    Term = Assertion
+ *         | Atom
+ *         | Atom Quantifier
+ *
+ *  An empty Term sequence is a valid disjunction alternative (e.g. /|||c||/).
+ *
+ *  Notes:
+ *
+ *    * Tracking of the 'simple-ness' of the current atom vs. the entire
+ *      disjunction are separate matters.  For instance, the disjunction
+ *      may be complex, but individual atoms may be simple.  Furthermore,
+ *      simple quantifiers are used whenever possible, even if the
+ *      disjunction as a whole is complex.
+ *
+ *    * The estimate of whether an atom is simple is conservative now,
+ *      and it would be possible to expand it.  For instance, captures
+ *      cause the disjunction to be marked complex, even though captures
+ *      -can- be handled by simple quantifiers with some minor modifications.
+ *
+ *    * Disjunction 'tainting' as 'complex' is handled at the end of the
+ *      main for loop collectively for atoms.  Assertions, quantifiers,
+ *      and '|' tokens need to taint the result manually if necessary.
+ *      Assertions cannot add to result char length, only atoms (and
+ *      quantifiers) can; currently quantifiers will taint the result
+ *      as complex though.
  */
 
-static duk_uint8_t *duk__match_regexp(duk_re_matcher_ctx *re_ctx, duk_uint8_t *pc, duk_uint8_t *sp) {
+DUK_LOCAL void duk__parse_disjunction(duk_re_compiler_ctx *re_ctx, duk_bool_t expect_eof, duk__re_disjunction_info *out_atom_info) {
+	duk_int32_t atom_start_offset = -1;                   /* negative -> no atom matched on previous round */
+	duk_int32_t atom_char_length = 0;                     /* negative -> complex atom */
+	duk_uint32_t atom_start_captures = re_ctx->captures;  /* value of re_ctx->captures at start of atom */
+	duk_int32_t unpatched_disjunction_split = -1;
+	duk_int32_t unpatched_disjunction_jump = -1;
+	duk_uint32_t entry_offset = (duk_uint32_t) DUK__RE_BUFLEN(re_ctx);
+	duk_int32_t res_charlen = 0;  /* -1 if disjunction is complex, char length if simple */
+	duk__re_disjunction_info tmp_disj;
+
+	DUK_ASSERT(out_atom_info != NULL);
+
 	if (re_ctx->recursion_depth >= re_ctx->recursion_limit) {
-		DUK_ERROR(re_ctx->thr, DUK_ERR_RANGE_ERROR, "regexp executor recursion limit");
+		DUK_ERROR(re_ctx->thr, DUK_ERR_RANGE_ERROR,
+		          DUK_STR_REGEXP_COMPILER_RECURSION_LIMIT);
 	}
 	re_ctx->recursion_depth++;
 
+#if 0
+	out_atom_info->start_captures = re_ctx->captures;
+#endif
+
 	for (;;) {
-		duk_small_int_t op;
+		/* atom_char_length, atom_start_offset, atom_start_offset reflect the
+		 * atom matched on the previous loop.  If a quantifier is encountered
+		 * on this loop, these are needed to handle the quantifier correctly.
+		 * new_atom_char_length etc are for the atom parsed on this round;
+		 * they're written to atom_char_length etc at the end of the round.
+		 */
+		duk_int32_t new_atom_char_length;   /* char length of the atom parsed in this loop */
+		duk_int32_t new_atom_start_offset;  /* bytecode start offset of the atom parsed in this loop
+		                                     * (allows quantifiers to copy the atom bytecode)
+		                                     */
+		duk_uint32_t new_atom_start_captures;  /* re_ctx->captures at the start of the atom parsed in this loop */
 
-		if (re_ctx->steps_count >= re_ctx->steps_limit) {
-			DUK_ERROR(re_ctx->thr, DUK_ERR_RANGE_ERROR, "regexp step limit");
-		}
-		re_ctx->steps_count++;
+		duk_lexer_parse_re_token(&re_ctx->lex, &re_ctx->curr_token);
 
-		op = (duk_small_int_t) duk__bc_get_u32(re_ctx, &pc);
+		DUK_DD(DUK_DDPRINT("re token: %ld (num=%ld, char=%c)",
+		                   (long) re_ctx->curr_token.t,
+		                   (long) re_ctx->curr_token.num,
+		                   (re_ctx->curr_token.num >= 0x20 && re_ctx->curr_token.num <= 0x7e) ?
+		                   (int) re_ctx->curr_token.num : (int) '?'));
 
-		DUK_DDD(DUK_DDDPRINT("match: rec=%ld, steps=%ld, pc (after op)=%ld, sp=%ld, op=%ld",
-		                     (long) re_ctx->recursion_depth,
-		                     (long) re_ctx->steps_count,
-		                     (long) (pc - re_ctx->bytecode),
-		                     (long) (sp - re_ctx->input),
-		                     (long) op));
+		/* set by atom case clauses */
+		new_atom_start_offset = -1;
+		new_atom_char_length = -1;
+		new_atom_start_captures = re_ctx->captures;
 
-		switch (op) {
-		case DUK_REOP_MATCH: {
-			goto match;
-		}
-		case DUK_REOP_CHAR: {
+		switch (re_ctx->curr_token.t) {
+		case DUK_RETOK_DISJUNCTION: {
 			/*
-			 *  Byte-based matching would be possible for case-sensitive
-			 *  matching but not for case-insensitive matching.  So, we
-			 *  match by decoding the input and bytecode character normally.
-			 *
-			 *  Bytecode characters are assumed to be already canonicalized.
-			 *  Input characters are canonicalized automatically by
-			 *  duk__inp_get_cp() if necessary.
-			 *
-			 *  There is no opcode for matching multiple characters.  The
-			 *  regexp compiler has trouble joining strings efficiently
-			 *  during compilation.  See doc/regexp.txt for more discussion.
+			 *  The handling here is a bit tricky.  If a previous '|' has been processed,
+			 *  we have a pending split1 and a pending jump (for a previous match).  These
+			 *  need to be back-patched carefully.  See docs for a detailed example.
 			 */
-			duk_codepoint_t c1, c2;
 
-			c1 = (duk_codepoint_t) duk__bc_get_u32(re_ctx, &pc);
-			DUK_ASSERT(!(re_ctx->re_flags & DUK_RE_FLAG_IGNORE_CASE) ||
-			           c1 == duk_unicode_re_canonicalize_char(re_ctx->thr, c1));  /* canonicalized by compiler */
-			if (sp >= re_ctx->input_end) {
-				goto fail;
-			}
-			c2 = duk__inp_get_cp(re_ctx, &sp);
-			DUK_DDD(DUK_DDDPRINT("char match, c1=%ld, c2=%ld", (long) c1, (long) c2));
-			if (c1 != c2) {
-				goto fail;
-			}
-			break;
-		}
-		case DUK_REOP_PERIOD: {
-			duk_codepoint_t c;
+			/* patch pending jump and split */
+			if (unpatched_disjunction_jump >= 0) {
+				duk_uint32_t offset;
 
-			if (sp >= re_ctx->input_end) {
-				goto fail;
-			}
-			c = duk__inp_get_cp(re_ctx, &sp);
-			if (duk_unicode_is_line_terminator(c)) {
-				/* E5 Sections 15.10.2.8, 7.3 */
-				goto fail;
+				DUK_ASSERT(unpatched_disjunction_split >= 0);
+				offset = unpatched_disjunction_jump;
+				offset += duk__insert_jump_offset(re_ctx,
+				                                  offset,
+				                                  (duk_int32_t) (DUK__RE_BUFLEN(re_ctx) - offset));
+				/* offset is now target of the pending split (right after jump) */
+				duk__insert_jump_offset(re_ctx,
+				                        unpatched_disjunction_split,
+				                        offset - unpatched_disjunction_split);
 			}
+
+			/* add a new pending split to the beginning of the entire disjunction */
+			(void) duk__insert_u32(re_ctx,
+			                       entry_offset,
+			                       DUK_REOP_SPLIT1);   /* prefer direct execution */
+			unpatched_disjunction_split = entry_offset + 1;   /* +1 for opcode */
+
+			/* add a new pending match jump for latest finished alternative */
+			duk__append_u32(re_ctx, DUK_REOP_JUMP);
+			unpatched_disjunction_jump = (duk_int32_t) DUK__RE_BUFLEN(re_ctx);
+
+			/* 'taint' result as complex */
+			res_charlen = -1;
 			break;
 		}
-		case DUK_REOP_RANGES:
-		case DUK_REOP_INVRANGES: {
-			duk_uint32_t n;
-			duk_codepoint_t c;
-			duk_small_int_t match;
-	
-			n = duk__bc_get_u32(re_ctx, &pc);
-			if (sp >= re_ctx->input_end) {
-				goto fail;
+		case DUK_RETOK_QUANTIFIER: {
+			if (atom_start_offset < 0) {
+				DUK_ERROR(re_ctx->thr, DUK_ERR_SYNTAX_ERROR,
+				          DUK_STR_INVALID_QUANTIFIER_NO_ATOM);
 			}
-			c = duk__inp_get_cp(re_ctx, &sp);
+			if (re_ctx->curr_token.qmin > re_ctx->curr_token.qmax) {
+				DUK_ERROR(re_ctx->thr, DUK_ERR_SYNTAX_ERROR,
+				          DUK_STR_INVALID_QUANTIFIER_VALUES);
+			}
+			if (atom_char_length >= 0) {
+				/*
+				 *  Simple atom
+				 *
+				 *  If atom_char_length is zero, we'll have unbounded execution time for e.g.
+				 *  /()*x/.exec('x').  We can't just skip the match because it might have some
+				 *  side effects (for instance, if we allowed captures in simple atoms, the
+				 *  capture needs to happen).  The simple solution below is to force the
+				 *  quantifier to match at most once, since the additional matches have no effect.
+				 *
+				 *  With a simple atom there can be no capture groups, so no captures need
+				 *  to be reset.
+				 */
+				duk_int32_t atom_code_length;
+				duk_uint32_t offset;
+				duk_uint32_t qmin, qmax;
 
-			match = 0;
-			while (n) {
-				duk_codepoint_t r1, r2;
-				r1 = (duk_codepoint_t) duk__bc_get_u32(re_ctx, &pc);
-				r2 = (duk_codepoint_t) duk__bc_get_u32(re_ctx, &pc);
-				DUK_DDD(DUK_DDDPRINT("matching ranges/invranges, n=%ld, r1=%ld, r2=%ld, c=%ld",
-				                     (long) n, (long) r1, (long) r2, (long) c));
-				if (c >= r1 && c <= r2) {
-					/* Note: don't bail out early, we must read all the ranges from
-					 * bytecode.  Another option is to skip them efficiently after
-					 * breaking out of here.  Prefer smallest code.
-					 */
-					match = 1;
+				qmin = re_ctx->curr_token.qmin;
+				qmax = re_ctx->curr_token.qmax;
+				if (atom_char_length == 0) {
+					/* qmin and qmax will be 0 or 1 */
+					if (qmin > 1) {
+						qmin = 1;
+					}
+					if (qmax > 1) {
+						qmax = 1;
+					}
 				}
-				n--;
-			}
 
-			if (op == DUK_REOP_RANGES) {
-				if (!match) {
-					goto fail;
+				duk__append_u32(re_ctx, DUK_REOP_MATCH);   /* complete 'sub atom' */
+				atom_code_length = (duk_int32_t) (DUK__RE_BUFLEN(re_ctx) - atom_start_offset);
+
+				offset = atom_start_offset;
+				if (re_ctx->curr_token.greedy) {
+					offset += duk__insert_u32(re_ctx, offset, DUK_REOP_SQGREEDY);
+					offset += duk__insert_u32(re_ctx, offset, qmin);
+					offset += duk__insert_u32(re_ctx, offset, qmax);
+					offset += duk__insert_u32(re_ctx, offset, atom_char_length);
+					offset += duk__insert_jump_offset(re_ctx, offset, atom_code_length);
+				} else {
+					offset += duk__insert_u32(re_ctx, offset, DUK_REOP_SQMINIMAL);
+					offset += duk__insert_u32(re_ctx, offset, qmin);
+					offset += duk__insert_u32(re_ctx, offset, qmax);
+					offset += duk__insert_jump_offset(re_ctx, offset, atom_code_length);
 				}
+				DUK_UNREF(offset);  /* silence scan-build warning */
 			} else {
-				DUK_ASSERT(op == DUK_REOP_INVRANGES);
-				if (match) {
-					goto fail;
+				/*
+				 *  Complex atom
+				 *
+				 *  The original code is used as a template, and removed at the end
+				 *  (this differs from the handling of simple quantifiers).
+				 *
+				 *  NOTE: there is no current solution for empty atoms in complex
+				 *  quantifiers.  This would need some sort of a 'progress' instruction.
+				 *
+				 *  XXX: impose limit on maximum result size, i.e. atom_code_len * atom_copies?
+				 */
+				duk_int32_t atom_code_length;
+				duk_uint32_t atom_copies;
+				duk_uint32_t tmp_qmin, tmp_qmax;
+
+				/* pre-check how many atom copies we're willing to make (atom_copies not needed below) */
+				atom_copies = (re_ctx->curr_token.qmax == DUK_RE_QUANTIFIER_INFINITE) ?
+				              re_ctx->curr_token.qmin : re_ctx->curr_token.qmax;
+				if (atom_copies > DUK_RE_MAX_ATOM_COPIES) {
+					DUK_ERROR(re_ctx->thr, DUK_ERR_RANGE_ERROR,
+					          DUK_STR_QUANTIFIER_TOO_MANY_COPIES);
+				}
+
+				/* wipe the capture range made by the atom (if any) */
+				DUK_ASSERT(atom_start_captures <= re_ctx->captures);
+				if (atom_start_captures != re_ctx->captures) {
+					DUK_ASSERT(atom_start_captures < re_ctx->captures);
+					DUK_DDD(DUK_DDDPRINT("must wipe ]atom_start_captures,re_ctx->captures]: ]%ld,%ld]",
+					                     (long) atom_start_captures, (long) re_ctx->captures));
+
+					/* insert (DUK_REOP_WIPERANGE, start, count) in reverse order so the order ends up right */
+					duk__insert_u32(re_ctx, atom_start_offset, (re_ctx->captures - atom_start_captures) * 2);
+					duk__insert_u32(re_ctx, atom_start_offset, (atom_start_captures + 1) * 2);
+					duk__insert_u32(re_ctx, atom_start_offset, DUK_REOP_WIPERANGE);
+				} else {
+					DUK_DDD(DUK_DDDPRINT("no need to wipe captures: atom_start_captures == re_ctx->captures == %ld",
+					                     (long) atom_start_captures));
+				}
+
+				atom_code_length = (duk_int32_t) DUK__RE_BUFLEN(re_ctx) - atom_start_offset;
+
+				/* insert the required matches (qmin) by copying the atom */
+				tmp_qmin = re_ctx->curr_token.qmin;
+				tmp_qmax = re_ctx->curr_token.qmax;
+				while (tmp_qmin > 0) {
+					duk__append_slice(re_ctx, atom_start_offset, atom_code_length);
+					tmp_qmin--;
+					if (tmp_qmax != DUK_RE_QUANTIFIER_INFINITE) {
+						tmp_qmax--;
+					}
+				}
+				DUK_ASSERT(tmp_qmin == 0);
+
+				/* insert code for matching the remainder - infinite or finite */
+				if (tmp_qmax == DUK_RE_QUANTIFIER_INFINITE) {
+					/* reuse last emitted atom for remaining 'infinite' quantifier */
+
+					if (re_ctx->curr_token.qmin == 0) {
+						/* Special case: original qmin was zero so there is nothing
+						 * to repeat.  Emit an atom copy but jump over it here.
+						 */
+						duk__append_u32(re_ctx, DUK_REOP_JUMP);
+						duk__append_jump_offset(re_ctx, atom_code_length);
+						duk__append_slice(re_ctx, atom_start_offset, atom_code_length);
+					}
+					if (re_ctx->curr_token.greedy) {
+						duk__append_u32(re_ctx, DUK_REOP_SPLIT2);   /* prefer jump */
+					} else {
+						duk__append_u32(re_ctx, DUK_REOP_SPLIT1);   /* prefer direct */
+					}
+					duk__append_jump_offset(re_ctx, -atom_code_length - 1);  /* -1 for opcode */
+				} else {
+					/*
+					 *  The remaining matches are emitted as sequence of SPLITs and atom
+					 *  copies; the SPLITs skip the remaining copies and match the sequel.
+					 *  This sequence needs to be emitted starting from the last copy
+					 *  because the SPLITs are variable length due to the variable length
+					 *  skip offset.  This causes a lot of memory copying now.
+					 *
+					 *  Example structure (greedy, match maximum # atoms):
+					 *
+					 *      SPLIT1 LSEQ
+					 *      (atom)
+					 *      SPLIT1 LSEQ    ; <- the byte length of this instruction is needed
+					 *      (atom)         ; to encode the above SPLIT1 correctly
+					 *      ...
+					 *   LSEQ:
+					 */
+					duk_uint32_t offset = (duk_uint32_t) DUK__RE_BUFLEN(re_ctx);
+					while (tmp_qmax > 0) {
+						duk__insert_slice(re_ctx, offset, atom_start_offset, atom_code_length);
+						if (re_ctx->curr_token.greedy) {
+							duk__insert_u32(re_ctx, offset, DUK_REOP_SPLIT1);   /* prefer direct */
+						} else {
+							duk__insert_u32(re_ctx, offset, DUK_REOP_SPLIT2);   /* prefer jump */
+						}
+						duk__insert_jump_offset(re_ctx,
+						                        offset + 1,   /* +1 for opcode */
+						                        (duk_int32_t) (DUK__RE_BUFLEN(re_ctx) - (offset + 1)));
+						tmp_qmax--;
+					}
 				}
+
+				/* remove the original 'template' atom */
+				duk__remove_slice(re_ctx, atom_start_offset, atom_code_length);
 			}
+
+			/* 'taint' result as complex */
+			res_charlen = -1;
 			break;
 		}
-		case DUK_REOP_ASSERT_START: {
-			duk_codepoint_t c;
-
-			if (sp <= re_ctx->input) {
-				break;
-			}
-			if (!(re_ctx->re_flags & DUK_RE_FLAG_MULTILINE)) {
-				goto fail;
-			}
-			c = duk__inp_get_prev_cp(re_ctx, sp);
-			if (duk_unicode_is_line_terminator(c)) {
-				/* E5 Sections 15.10.2.8, 7.3 */
-				break;
-			}
-			goto fail;
+		case DUK_RETOK_ASSERT_START: {
+			duk__append_u32(re_ctx, DUK_REOP_ASSERT_START);
+			break;
 		}
-		case DUK_REOP_ASSERT_END: {
-			duk_codepoint_t c;
-			duk_uint8_t *temp_sp;
-
-			if (sp >= re_ctx->input_end) {
-				break;
-			}
-			if (!(re_ctx->re_flags & DUK_RE_FLAG_MULTILINE)) {
-				goto fail;
-			}
-			temp_sp = sp;
-			c = duk__inp_get_cp(re_ctx, &temp_sp);
-			if (duk_unicode_is_line_terminator(c)) {
-				/* E5 Sections 15.10.2.8, 7.3 */
-				break;
-			}
-			goto fail;
+		case DUK_RETOK_ASSERT_END: {
+			duk__append_u32(re_ctx, DUK_REOP_ASSERT_END);
+			break;
 		}
-		case DUK_REOP_ASSERT_WORD_BOUNDARY:
-		case DUK_REOP_ASSERT_NOT_WORD_BOUNDARY: {
-			/*
-			 *  E5 Section 15.10.2.6.  The previous and current character
-			 *  should -not- be canonicalized as they are now.  However,
-			 *  canonicalization does not affect the result of IsWordChar()
-			 *  (which depends on Unicode characters never canonicalizing
-			 *  into ASCII characters) so this does not matter.
-			 */
-			duk_small_int_t w1, w2;
+		case DUK_RETOK_ASSERT_WORD_BOUNDARY: {
+			duk__append_u32(re_ctx, DUK_REOP_ASSERT_WORD_BOUNDARY);
+			break;
+		}
+		case DUK_RETOK_ASSERT_NOT_WORD_BOUNDARY: {
+			duk__append_u32(re_ctx, DUK_REOP_ASSERT_NOT_WORD_BOUNDARY);
+			break;
+		}
+		case DUK_RETOK_ASSERT_START_POS_LOOKAHEAD:
+		case DUK_RETOK_ASSERT_START_NEG_LOOKAHEAD: {
+			duk_uint32_t offset;
+			duk_uint32_t opcode = (re_ctx->curr_token.t == DUK_RETOK_ASSERT_START_POS_LOOKAHEAD) ?
+			                      DUK_REOP_LOOKPOS : DUK_REOP_LOOKNEG;
 
-			if (sp <= re_ctx->input) {
-				w1 = 0;  /* not a wordchar */
-			} else {
-				duk_codepoint_t c;
-				c = duk__inp_get_prev_cp(re_ctx, sp);
-				w1 = duk_unicode_re_is_wordchar(c);
-			}
-			if (sp >= re_ctx->input_end) {
-				w2 = 0;  /* not a wordchar */
-			} else {
-				duk_uint8_t *tmp_sp = sp;  /* dummy so sp won't get updated */
-				duk_codepoint_t c;
-				c = duk__inp_get_cp(re_ctx, &tmp_sp);
-				w2 = duk_unicode_re_is_wordchar(c);
-			}
+			offset = (duk_uint32_t) DUK__RE_BUFLEN(re_ctx);
+			duk__parse_disjunction(re_ctx, 0, &tmp_disj);
+			duk__append_u32(re_ctx, DUK_REOP_MATCH);
 
-			if (op == DUK_REOP_ASSERT_WORD_BOUNDARY) {
-				if (w1 == w2) {
-					goto fail;
-				}
-			} else {
-				DUK_ASSERT(op == DUK_REOP_ASSERT_NOT_WORD_BOUNDARY);
-				if (w1 != w2) {
-					goto fail;
-				}
-			}
+			(void) duk__insert_u32(re_ctx, offset, opcode);
+			(void) duk__insert_jump_offset(re_ctx,
+			                               offset + 1,   /* +1 for opcode */
+			                               (duk_int32_t) (DUK__RE_BUFLEN(re_ctx) - (offset + 1)));
+
+			/* 'taint' result as complex -- this is conservative,
+			 * as lookaheads do not backtrack.
+			 */
+			res_charlen = -1;
 			break;
 		}
-		case DUK_REOP_JUMP: {
-			duk_int32_t skip;
-
-			skip = duk__bc_get_i32(re_ctx, &pc);
-			pc += skip;
+		case DUK_RETOK_ATOM_PERIOD: {
+			new_atom_char_length = 1;
+			new_atom_start_offset = (duk_int32_t) DUK__RE_BUFLEN(re_ctx);
+			duk__append_u32(re_ctx, DUK_REOP_PERIOD);
 			break;
 		}
-		case DUK_REOP_SPLIT1: {
-			/* split1: prefer direct execution (no jump) */
-			duk_uint8_t *sub_sp;
-			duk_int32_t skip;
+		case DUK_RETOK_ATOM_CHAR: {
+			/* Note: successive characters could be joined into string matches
+			 * but this is not trivial (consider e.g. '/xyz+/); see docs for
+			 * more discussion.
+			 */
+			duk_uint32_t ch;
 
-			skip = duk__bc_get_i32(re_ctx, &pc);
-			sub_sp = duk__match_regexp(re_ctx, pc, sp);
-			if (sub_sp) {
-				sp = sub_sp;
-				goto match;
+			new_atom_char_length = 1;
+			new_atom_start_offset = (duk_int32_t) DUK__RE_BUFLEN(re_ctx);
+			duk__append_u32(re_ctx, DUK_REOP_CHAR);
+			ch = re_ctx->curr_token.num;
+			if (re_ctx->re_flags & DUK_RE_FLAG_IGNORE_CASE) {
+				ch = duk_unicode_re_canonicalize_char(re_ctx->thr, ch);
 			}
-			pc += skip;
+			duk__append_u32(re_ctx, ch);
 			break;
 		}
-		case DUK_REOP_SPLIT2: {
-			/* split2: prefer jump execution (not direct) */
-			duk_uint8_t *sub_sp;
-			duk_int32_t skip;
-
-			skip = duk__bc_get_i32(re_ctx, &pc);
-			sub_sp = duk__match_regexp(re_ctx, pc + skip, sp);
-			if (sub_sp) {
-				sp = sub_sp;
-				goto match;
+		case DUK_RETOK_ATOM_DIGIT:
+		case DUK_RETOK_ATOM_NOT_DIGIT: {
+			new_atom_char_length = 1;
+			new_atom_start_offset = (duk_int32_t) DUK__RE_BUFLEN(re_ctx);
+			duk__append_u32(re_ctx,
+			                (re_ctx->curr_token.t == DUK_RETOK_ATOM_DIGIT) ?
+			                DUK_REOP_RANGES : DUK_REOP_INVRANGES);
+			duk__append_u32(re_ctx, sizeof(duk_unicode_re_ranges_digit) / (2 * sizeof(duk_uint16_t)));
+			duk__append_u16_list(re_ctx, duk_unicode_re_ranges_digit, sizeof(duk_unicode_re_ranges_digit) / sizeof(duk_uint16_t));
+			break;
+		}
+		case DUK_RETOK_ATOM_WHITE:
+		case DUK_RETOK_ATOM_NOT_WHITE: {
+			new_atom_char_length = 1;
+			new_atom_start_offset = (duk_int32_t) DUK__RE_BUFLEN(re_ctx);
+			duk__append_u32(re_ctx,
+			                (re_ctx->curr_token.t == DUK_RETOK_ATOM_WHITE) ?
+			                DUK_REOP_RANGES : DUK_REOP_INVRANGES);
+			duk__append_u32(re_ctx, sizeof(duk_unicode_re_ranges_white) / (2 * sizeof(duk_uint16_t)));
+			duk__append_u16_list(re_ctx, duk_unicode_re_ranges_white, sizeof(duk_unicode_re_ranges_white) / sizeof(duk_uint16_t));
+			break;
+		}
+		case DUK_RETOK_ATOM_WORD_CHAR:
+		case DUK_RETOK_ATOM_NOT_WORD_CHAR: {
+			new_atom_char_length = 1;
+			new_atom_start_offset = (duk_int32_t) DUK__RE_BUFLEN(re_ctx);
+			duk__append_u32(re_ctx,
+			                (re_ctx->curr_token.t == DUK_RETOK_ATOM_WORD_CHAR) ?
+			                DUK_REOP_RANGES : DUK_REOP_INVRANGES);
+			duk__append_u32(re_ctx, sizeof(duk_unicode_re_ranges_wordchar) / (2 * sizeof(duk_uint16_t)));
+			duk__append_u16_list(re_ctx, duk_unicode_re_ranges_wordchar, sizeof(duk_unicode_re_ranges_wordchar) / sizeof(duk_uint16_t));
+			break;
+		}
+		case DUK_RETOK_ATOM_BACKREFERENCE: {
+			duk_uint32_t backref = (duk_uint32_t) re_ctx->curr_token.num;
+			if (backref > re_ctx->highest_backref) {
+				re_ctx->highest_backref = backref;
 			}
+			new_atom_char_length = -1;   /* mark as complex */
+			new_atom_start_offset = (duk_int32_t) DUK__RE_BUFLEN(re_ctx);
+			duk__append_u32(re_ctx, DUK_REOP_BACKREFERENCE);
+			duk__append_u32(re_ctx, backref);
 			break;
 		}
-		case DUK_REOP_SQMINIMAL: {
-			duk_uint32_t q, qmin, qmax;
-			duk_int32_t skip;
-			duk_uint8_t *sub_sp;
-
-			qmin = duk__bc_get_u32(re_ctx, &pc);
-			qmax = duk__bc_get_u32(re_ctx, &pc);
-			skip = duk__bc_get_i32(re_ctx, &pc);
-			DUK_DDD(DUK_DDDPRINT("minimal quantifier, qmin=%lu, qmax=%lu, skip=%ld",
-			                     (unsigned long) qmin, (unsigned long) qmax, (long) skip));
+		case DUK_RETOK_ATOM_START_CAPTURE_GROUP: {
+			duk_uint32_t cap;
 
-			q = 0;
-			while (q <= qmax) {
-				if (q >= qmin) {
-					sub_sp = duk__match_regexp(re_ctx, pc + skip, sp);
-					if (sub_sp) {
-						sp = sub_sp;
-						goto match;
-					}
-				}
-				sub_sp = duk__match_regexp(re_ctx, pc, sp);
-				if (!sub_sp) {
-					break;
-				}
-				sp = sub_sp;
-				q++;
-			}
-			goto fail;
+			new_atom_char_length = -1;   /* mark as complex (capture handling) */
+			new_atom_start_offset = (duk_int32_t) DUK__RE_BUFLEN(re_ctx);
+			cap = ++re_ctx->captures;
+			duk__append_u32(re_ctx, DUK_REOP_SAVE);
+			duk__append_u32(re_ctx, cap * 2);
+			duk__parse_disjunction(re_ctx, 0, &tmp_disj);  /* retval (sub-atom char length) unused, tainted as complex above */
+			duk__append_u32(re_ctx, DUK_REOP_SAVE);
+			duk__append_u32(re_ctx, cap * 2 + 1);
+			break;
 		}
-		case DUK_REOP_SQGREEDY: {
-			duk_uint32_t q, qmin, qmax, atomlen;
-			duk_int32_t skip;
-			duk_uint8_t *sub_sp;
+		case DUK_RETOK_ATOM_START_NONCAPTURE_GROUP: {
+			new_atom_start_offset = (duk_int32_t) DUK__RE_BUFLEN(re_ctx);
+			duk__parse_disjunction(re_ctx, 0, &tmp_disj);
+			new_atom_char_length = tmp_disj.charlen;
+			break;
+		}
+		case DUK_RETOK_ATOM_START_CHARCLASS:
+		case DUK_RETOK_ATOM_START_CHARCLASS_INVERTED: {
+			/*
+			 *  Range parsing is done with a special lexer function which calls
+			 *  us for every range parsed.  This is different from how rest of
+			 *  the parsing works, but avoids a heavy, arbitrary size intermediate
+			 *  value type to hold the ranges.
+			 *
+			 *  Another complication is the handling of character ranges when
+			 *  case insensitive matching is used (see docs for discussion).
+			 *  The range handler callback given to the lexer takes care of this
+			 *  as well.
+			 *
+			 *  Note that duplicate ranges are not eliminated when parsing character
+			 *  classes, so that canonicalization of
+			 *
+			 *    [0-9a-fA-Fx-{]
+			 *
+			 *  creates the result (note the duplicate ranges):
+			 *
+			 *    [0-9A-FA-FX-Z{-{]
+			 *
+			 *  where [x-{] is split as a result of canonicalization.  The duplicate
+			 *  ranges are not a semantics issue: they work correctly.
+			 */
 
-			qmin = duk__bc_get_u32(re_ctx, &pc);
-			qmax = duk__bc_get_u32(re_ctx, &pc);
-			atomlen = duk__bc_get_u32(re_ctx, &pc);
-			skip = duk__bc_get_i32(re_ctx, &pc);
-			DUK_DDD(DUK_DDDPRINT("greedy quantifier, qmin=%lu, qmax=%lu, atomlen=%lu, skip=%ld",
-			                     (unsigned long) qmin, (unsigned long) qmax, (unsigned long) atomlen, (long) skip));
+			duk_uint32_t offset;
 
-			q = 0;
-			while (q < qmax) {
-				sub_sp = duk__match_regexp(re_ctx, pc, sp);
-				if (!sub_sp) {
-					break;
-				}
-				sp = sub_sp;
-				q++;
-			}
-			while (q >= qmin) {
-				sub_sp = duk__match_regexp(re_ctx, pc + skip, sp);
-				if (sub_sp) {
-					sp = sub_sp;
-					goto match;
-				}
-				if (q == qmin) {
-					break;
-				}
+			DUK_DD(DUK_DDPRINT("character class"));
 
-				/* Note: if atom were to contain e.g. captures, we would need to
-				 * re-match the atom to get correct captures.  Simply quantifiers
-				 * do not allow captures in their atom now, so this is not an issue.
-				 */
+			/* insert ranges instruction, range count patched in later */
+			new_atom_char_length = 1;
+			new_atom_start_offset = (duk_int32_t) DUK__RE_BUFLEN(re_ctx);
+			duk__append_u32(re_ctx,
+			                (re_ctx->curr_token.t == DUK_RETOK_ATOM_START_CHARCLASS) ?
+			                DUK_REOP_RANGES : DUK_REOP_INVRANGES);
+			offset = (duk_uint32_t) DUK__RE_BUFLEN(re_ctx);    /* patch in range count later */
 
-				DUK_DDD(DUK_DDDPRINT("greedy quantifier, backtrack %ld characters (atomlen)",
-				                     (long) atomlen));
-				sp = duk__inp_backtrack(re_ctx, &sp, (duk_uint_fast32_t) atomlen);
-				q--;
-			}
-			goto fail;
-		}
-		case DUK_REOP_SAVE: {
-			duk_uint32_t idx;
-			duk_uint8_t *old;
-			duk_uint8_t *sub_sp;
+			/* parse ranges until character class ends */
+			re_ctx->nranges = 0;    /* note: ctx-wide temporary */
+			duk_lexer_parse_re_ranges(&re_ctx->lex, duk__generate_ranges, (void *) re_ctx);
 
-			idx = duk__bc_get_u32(re_ctx, &pc);
-			if (idx >= re_ctx->nsaved) {
-				/* idx is unsigned, < 0 check is not necessary */
-				DUK_D(DUK_DPRINT("internal error, regexp save index insane: idx=%ld", (long) idx));
-				goto internal_error;
-			}
-			old = re_ctx->saved[idx];
-			re_ctx->saved[idx] = sp;
-			sub_sp = duk__match_regexp(re_ctx, pc, sp);
-			if (sub_sp) {
-				sp = sub_sp;
-				goto match;
+			/* insert range count */
+			duk__insert_u32(re_ctx, offset, re_ctx->nranges);
+			break;
+		}
+		case DUK_RETOK_ATOM_END_GROUP: {
+			if (expect_eof) {
+				DUK_ERROR(re_ctx->thr, DUK_ERR_SYNTAX_ERROR,
+				          DUK_STR_UNEXPECTED_CLOSING_PAREN);
 			}
-			re_ctx->saved[idx] = old;
-			goto fail;
+			goto done;
 		}
-		case DUK_REOP_WIPERANGE: {
-			/* Wipe capture range and save old values for backtracking.
-			 *
-			 * XXX: this typically happens with a relatively small idx_count.
-			 * It might be useful to handle cases where the count is small
-			 * (say <= 8) by saving the values in stack instead.  This would
-			 * reduce memory churn and improve performance, at the cost of a
-			 * slightly higher code footprint.
-			 */
-			duk_uint32_t idx_start, idx_count;
-#ifdef DUK_USE_EXPLICIT_NULL_INIT
-			duk_uint32_t idx_end, idx;
-#endif
-			duk_uint8_t **range_save;
-			duk_uint8_t *sub_sp;
-
-			idx_start = duk__bc_get_u32(re_ctx, &pc);
-			idx_count = duk__bc_get_u32(re_ctx, &pc);
-			DUK_DDD(DUK_DDDPRINT("wipe saved range: start=%ld, count=%ld -> [%ld,%ld] (captures [%ld,%ld])",
-			                     (long) idx_start, (long) idx_count,
-			                     (long) idx_start, (long) (idx_start + idx_count - 1),
-			                     (long) (idx_start / 2), (long) ((idx_start + idx_count - 1) / 2)));
-			if (idx_start + idx_count > re_ctx->nsaved || idx_count == 0) {
-				/* idx is unsigned, < 0 check is not necessary */
-				DUK_D(DUK_DPRINT("internal error, regexp wipe indices insane: idx_start=%ld, idx_count=%ld",
-				                 (long) idx_start, (long) idx_count));
-				goto internal_error;
+		case DUK_RETOK_EOF: {
+			if (!expect_eof) {
+				DUK_ERROR(re_ctx->thr, DUK_ERR_SYNTAX_ERROR,
+				          DUK_STR_UNEXPECTED_END_OF_PATTERN);
 			}
-			DUK_ASSERT(idx_count > 0);
+			goto done;
+		}
+		default: {
+			DUK_ERROR(re_ctx->thr, DUK_ERR_SYNTAX_ERROR,
+			          DUK_STR_UNEXPECTED_REGEXP_TOKEN);
+		}
+		}
 
-			duk_require_stack((duk_context *) re_ctx->thr, 1);
-			range_save = (duk_uint8_t **) duk_push_fixed_buffer((duk_context *) re_ctx->thr,
-			                                                    sizeof(duk_uint8_t *) * idx_count);
-			DUK_ASSERT(range_save != NULL);
-			DUK_MEMCPY(range_save, re_ctx->saved + idx_start, sizeof(duk_uint8_t *) * idx_count);
-#ifdef DUK_USE_EXPLICIT_NULL_INIT
-			idx_end = idx_start + idx_count;
-			for (idx = idx_start; idx < idx_end; idx++) {
-				re_ctx->saved[idx] = NULL;
+		/* a complex (new) atom taints the result */
+		if (new_atom_start_offset >= 0) {
+			if (new_atom_char_length < 0) {
+				res_charlen = -1;
+			} else if (res_charlen >= 0) {
+				/* only advance if not tainted */
+				res_charlen += new_atom_char_length;
 			}
-#else
-			DUK_MEMZERO(re_ctx->saved + idx_start, sizeof(duk_uint8_t *) * idx_count);
-#endif
+		}
 
-			sub_sp = duk__match_regexp(re_ctx, pc, sp);
-			if (sub_sp) {
-				/* match: keep wiped/resaved values */
-				DUK_DDD(DUK_DDDPRINT("match: keep wiped/resaved values [%ld,%ld] (captures [%ld,%ld])",
-				                     (long) idx_start, (long) (idx_start + idx_count - 1),
-			                             (long) (idx_start / 2), (long) ((idx_start + idx_count - 1) / 2)));
-				duk_pop((duk_context *) re_ctx->thr);
-				sp = sub_sp;
-				goto match;
-			}
+		/* record previous atom info in case next token is a quantifier */
+		atom_start_offset = new_atom_start_offset;
+		atom_char_length = new_atom_char_length;
+		atom_start_captures = new_atom_start_captures;
+	}
 
-			/* fail: restore saves */
-			DUK_DDD(DUK_DDDPRINT("fail: restore wiped/resaved values [%ld,%ld] (captures [%ld,%ld])",
-			                     (long) idx_start, (long) (idx_start + idx_count - 1),
-			                     (long) (idx_start / 2), (long) ((idx_start + idx_count - 1) / 2)));
-			DUK_MEMCPY(re_ctx->saved + idx_start, range_save, sizeof(duk_uint8_t *) * idx_count);
-			duk_pop((duk_context *) re_ctx->thr);
-			goto fail;
-		}
-		case DUK_REOP_LOOKPOS:
-		case DUK_REOP_LOOKNEG: {
-			/*
-			 *  Needs a save of multiple saved[] entries depending on what range
-			 *  may be overwritten.  Because the regexp parser does no such analysis,
-			 *  we currently save the entire saved array here.  Lookaheads are thus
-			 *  a bit expensive.  Note that the saved array is not needed for just
-			 *  the lookahead sub-match, but for the matching of the entire sequel.
-			 *
-			 *  The temporary save buffer is pushed on to the valstack to handle
-			 *  errors correctly.  Each lookahead causes a C recursion and pushes
-			 *  more stuff on the value stack.  If the C recursion limit is less
-			 *  than the value stack spare, there is no need to check the stack.
-			 *  We do so regardless, just in case.
-			 */
+ done:
 
-			duk_int32_t skip;
-			duk_uint8_t **full_save;
-			duk_uint8_t *sub_sp;
+	/* finish up pending jump and split for last alternative */
+	if (unpatched_disjunction_jump >= 0) {
+		duk_uint32_t offset;
 
-			DUK_ASSERT(re_ctx->nsaved > 0);
+		DUK_ASSERT(unpatched_disjunction_split >= 0);
+		offset = unpatched_disjunction_jump;
+		offset += duk__insert_jump_offset(re_ctx,
+		                                  offset,
+		                                  (duk_int32_t) (DUK__RE_BUFLEN(re_ctx) - offset));
+		/* offset is now target of the pending split (right after jump) */
+		duk__insert_jump_offset(re_ctx,
+		                        unpatched_disjunction_split,
+		                        offset - unpatched_disjunction_split);
+	}
 
-			duk_require_stack((duk_context *) re_ctx->thr, 1);
-			full_save = (duk_uint8_t **) duk_push_fixed_buffer((duk_context *) re_ctx->thr,
-			                                                   sizeof(duk_uint8_t *) * re_ctx->nsaved);
-			DUK_ASSERT(full_save != NULL);
-			DUK_MEMCPY(full_save, re_ctx->saved, sizeof(duk_uint8_t *) * re_ctx->nsaved);
+#if 0
+	out_atom_info->end_captures = re_ctx->captures;
+#endif
+	out_atom_info->charlen = res_charlen;
+	DUK_DDD(DUK_DDDPRINT("parse disjunction finished: charlen=%ld",
+	                     (long) out_atom_info->charlen));
 
-			skip = duk__bc_get_i32(re_ctx, &pc);
-			sub_sp = duk__match_regexp(re_ctx, pc, sp);
-			if (op == DUK_REOP_LOOKPOS) {
-				if (!sub_sp) {
-					goto lookahead_fail;
-				}
-			} else {
-				if (sub_sp) {
-					goto lookahead_fail;
-				}
-			}
-			sub_sp = duk__match_regexp(re_ctx, pc + skip, sp);
-			if (sub_sp) {
-				/* match: keep saves */
-				duk_pop((duk_context *) re_ctx->thr);
-				sp = sub_sp;
-				goto match;
-			}
+	re_ctx->recursion_depth--;
+}
 
-			/* fall through */
+/*
+ *  Flags parsing (see E5 Section 15.10.4.1).
+ */
 
-		 lookahead_fail:
-			/* fail: restore saves */
-			DUK_MEMCPY(re_ctx->saved, full_save, sizeof(duk_uint8_t *) * re_ctx->nsaved);
-			duk_pop((duk_context *) re_ctx->thr);
-			goto fail;
-		}
-		case DUK_REOP_BACKREFERENCE: {
-			/*
-			 *  Byte matching for back-references would be OK in case-
-			 *  sensitive matching.  In case-insensitive matching we need
-			 *  to canonicalize characters, so back-reference matching needs
-			 *  to be done with codepoints instead.  So, we just decode
-			 *  everything normally here, too.
-			 *
-			 *  Note: back-reference index which is 0 or higher than
-			 *  NCapturingParens (= number of capturing parens in the
-			 *  -entire- regexp) is a compile time error.  However, a
-			 *  backreference referring to a valid capture which has
-			 *  not matched anything always succeeds!  See E5 Section
-			 *  15.10.2.9, step 5, sub-step 3.
-			 */
-			duk_uint32_t idx;
-			duk_uint8_t *p;
+DUK_LOCAL duk_uint32_t duk__parse_regexp_flags(duk_hthread *thr, duk_hstring *h) {
+	const duk_uint8_t *p;
+	const duk_uint8_t *p_end;
+	duk_uint32_t flags = 0;
 
-			idx = duk__bc_get_u32(re_ctx, &pc);
-			idx = idx << 1;		/* backref n -> saved indices [n*2, n*2+1] */
-			if (idx < 2 || idx + 1 >= re_ctx->nsaved) {
-				/* regexp compiler should catch these */
-				DUK_D(DUK_DPRINT("internal error, backreference index insane"));
-				goto internal_error;
-			}
-			if (!re_ctx->saved[idx] || !re_ctx->saved[idx+1]) {
-				/* capture is 'undefined', always matches! */
-				DUK_DDD(DUK_DDDPRINT("backreference: saved[%ld,%ld] not complete, always match",
-				                     (long) idx, (long) (idx + 1)));
-				break;
-			}
-			DUK_DDD(DUK_DDDPRINT("backreference: match saved[%ld,%ld]", (long) idx, (long) (idx + 1)));
+	p = DUK_HSTRING_GET_DATA(h);
+	p_end = p + DUK_HSTRING_GET_BYTELEN(h);
 
-			p = re_ctx->saved[idx];
-			while (p < re_ctx->saved[idx+1]) {
-				duk_codepoint_t c1, c2;
+	/* Note: can be safely scanned as bytes (undecoded) */
 
-				/* Note: not necessary to check p against re_ctx->input_end:
-				 * the memory access is checked by duk__inp_get_cp(), while
-				 * valid compiled regexps cannot write a saved[] entry
-				 * which points to outside the string.
-				 */
-				if (sp >= re_ctx->input_end) {
-					goto fail;
-				}
-				c1 = duk__inp_get_cp(re_ctx, &p);
-				c2 = duk__inp_get_cp(re_ctx, &sp);
-				if (c1 != c2) {
-					goto fail;
-				}
+	while (p < p_end) {
+		duk_uint8_t c = *p++;
+		switch ((int) c) {
+		case (int) 'g': {
+			if (flags & DUK_RE_FLAG_GLOBAL) {
+				goto error;
+			}
+			flags |= DUK_RE_FLAG_GLOBAL;
+			break;
+		}
+		case (int) 'i': {
+			if (flags & DUK_RE_FLAG_IGNORE_CASE) {
+				goto error;
+			}
+			flags |= DUK_RE_FLAG_IGNORE_CASE;
+			break;
+		}
+		case (int) 'm': {
+			if (flags & DUK_RE_FLAG_MULTILINE) {
+				goto error;
 			}
+			flags |= DUK_RE_FLAG_MULTILINE;
 			break;
 		}
 		default: {
-			DUK_D(DUK_DPRINT("internal error, regexp opcode error: %ld", (long) op));
-			goto internal_error;
+			goto error;
 		}
 		}
 	}
 
- match:
-	re_ctx->recursion_depth--;
-	return sp;
+	return flags;
 
- fail:
-	re_ctx->recursion_depth--;
-	return NULL;
+ error:
+	DUK_ERROR(thr, DUK_ERR_SYNTAX_ERROR, DUK_STR_INVALID_REGEXP_FLAGS);
+	return 0;  /* never here */
+}
 
- internal_error:
-	DUK_ERROR(re_ctx->thr, DUK_ERR_INTERNAL_ERROR, "regexp internal error");
-	return NULL;  /* never here */
+/*
+ *  Create escaped RegExp source (E5 Section 15.10.3).
+ *
+ *  The current approach is to special case the empty RegExp
+ *  ('' -> '(?:)') and otherwise replace unescaped '/' characters
+ *  with '\/' regardless of where they occur in the regexp.
+ *
+ *  Note that normalization does not seem to be necessary for
+ *  RegExp literals (e.g. '/foo/') because to be acceptable as
+ *  a RegExp literal, the text between forward slashes must
+ *  already match the escaping requirements (e.g. must not contain
+ *  unescaped forward slashes or be empty).  Escaping IS needed
+ *  for expressions like 'new Regexp("...", "")' however.
+ *  Currently, we re-escape in either case.
+ *
+ *  Also note that we process the source here in UTF-8 encoded
+ *  form.  This is correct, because any non-ASCII characters are
+ *  passed through without change.
+ */
+
+DUK_LOCAL void duk__create_escaped_source(duk_hthread *thr, int idx_pattern) {
+	duk_context *ctx = (duk_context *) thr;
+	duk_hstring *h;
+	const duk_uint8_t *p;
+	duk_bufwriter_ctx bw_alloc;
+	duk_bufwriter_ctx *bw;
+	duk_uint8_t *q;
+	duk_size_t i, n;
+	duk_uint_fast8_t c_prev, c;
+
+	h = duk_get_hstring(ctx, idx_pattern);
+	DUK_ASSERT(h != NULL);
+	p = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h);
+	n = (duk_size_t) DUK_HSTRING_GET_BYTELEN(h);
+
+	if (n == 0) {
+		/* return '(?:)' */
+		duk_push_hstring_stridx(ctx, DUK_STRIDX_ESCAPED_EMPTY_REGEXP);
+		return;
+	}
+
+	bw = &bw_alloc;
+	DUK_BW_INIT_PUSHBUF(thr, bw, n);
+	q = DUK_BW_GET_PTR(thr, bw);
+
+	c_prev = (duk_uint_fast8_t) 0;
+
+	for (i = 0; i < n; i++) {
+		c = p[i];
+
+		q = DUK_BW_ENSURE_RAW(thr, bw, 2, q);
+
+		if (c == (duk_uint_fast8_t) '/' && c_prev != (duk_uint_fast8_t) '\\') {
+			/* Unescaped '/' ANYWHERE in the regexp (in disjunction,
+			 * inside a character class, ...) => same escape works.
+			 */
+			*q++ = DUK_ASC_BACKSLASH;
+		}
+		*q++ = (duk_uint8_t) c;
+
+		c_prev = c;
+	}
+
+	DUK_BW_SETPTR_AND_COMPACT(thr, bw, q);
+	duk_to_string(ctx, -1);  /* -> [ ... escaped_source ] */
 }
 
 /*
- *  Exposed matcher function which provides the semantics of RegExp.prototype.exec().
+ *  Exposed regexp compilation primitive.
  *
- *  RegExp.prototype.test() has the same semantics as exec() but does not return the
- *  result object (which contains the matching string and capture groups).  Currently
- *  there is no separate test() helper, so a temporary result object is created and
- *  discarded if test() is needed.  This is intentional, to save code space.
+ *  Sets up a regexp compilation context, and calls duk__parse_disjunction() to do the
+ *  actual parsing.  Handles generation of the compiled regexp header and the
+ *  "boilerplate" capture of the matching substring (save 0 and 1).  Also does some
+ *  global level regexp checks after recursive compilation has finished.
  *
- *  Input stack:  [ ... re_obj input ]
- *  Output stack: [ ... result ]
+ *  An escaped version of the regexp source, suitable for use as a RegExp instance
+ *  'source' property (see E5 Section 15.10.3), is also left on the stack.
+ *
+ *  Input stack:  [ pattern flags ]
+ *  Output stack: [ bytecode escaped_source ]  (both as strings)
  */
 
-static void duk__regexp_match_helper(duk_hthread *thr, duk_small_int_t force_global) {
+DUK_INTERNAL void duk_regexp_compile(duk_hthread *thr) {
 	duk_context *ctx = (duk_context *) thr;
-	duk_re_matcher_ctx re_ctx;
-	duk_hobject *h_regexp;
-	duk_hstring *h_bytecode;
-	duk_hstring *h_input;
-	duk_uint8_t *pc;
-	duk_uint8_t *sp;
-	duk_small_int_t match = 0;
-	duk_small_int_t global;
-	duk_uint_fast32_t i;
-	double d;
-	duk_uint32_t char_offset;
+	duk_re_compiler_ctx re_ctx;
+	duk_lexer_point lex_point;
+	duk_hstring *h_pattern;
+	duk_hstring *h_flags;
+	duk__re_disjunction_info ign_disj;
 
 	DUK_ASSERT(thr != NULL);
 	DUK_ASSERT(ctx != NULL);
 
-	DUK_DD(DUK_DDPRINT("regexp match: regexp=%!T, input=%!T",
-	                   (duk_tval *) duk_get_tval(ctx, -2),
-	                   (duk_tval *) duk_get_tval(ctx, -1)));
+	/*
+	 *  Args validation
+	 */
+
+	/* TypeError if fails */
+	h_pattern = duk_require_hstring(ctx, -2);
+	h_flags = duk_require_hstring(ctx, -1);
 
 	/*
-	 *  Regexp instance check, bytecode check, input coercion.
-	 *
-	 *  See E5 Section 15.10.6.
+	 *  Create normalized 'source' property (E5 Section 15.10.3).
 	 */
 
-	/* TypeError if wrong; class check, see E5 Section 15.10.6 */
-	h_regexp = duk_require_hobject_with_class(ctx, -2, DUK_HOBJECT_CLASS_REGEXP);
-	DUK_ASSERT(h_regexp != NULL);
-	DUK_ASSERT(DUK_HOBJECT_GET_CLASS_NUMBER(h_regexp) == DUK_HOBJECT_CLASS_REGEXP);
-	DUK_UNREF(h_regexp);
+	/* [ ... pattern flags ] */
 
-	duk_to_string(ctx, -1);
-	h_input = duk_get_hstring(ctx, -1);
-	DUK_ASSERT(h_input != NULL);
+	duk__create_escaped_source(thr, -2);
 
-	duk_get_prop_stridx(ctx, -2, DUK_STRIDX_INT_BYTECODE);  /* [ ... re_obj input ] -> [ ... re_obj input bc ] */
-	h_bytecode = duk_require_hstring(ctx, -1);  /* no regexp instance should exist without a non-configurable bytecode property */
-	DUK_ASSERT(h_bytecode != NULL);
+	/* [ ... pattern flags escaped_source ] */
 
 	/*
-	 *  Basic context initialization.
-	 *
-	 *  Some init values are read from the bytecode header
-	 *  whose format is (UTF-8 codepoints):
-	 *
-	 *    uint   flags
-	 *    uint   nsaved (even, 2n+2 where n = num captures)
+	 *  Init compilation context
 	 */
 
-	/* [ ... re_obj input bc ] */
+	/* [ ... pattern flags escaped_source buffer ] */
 
 	DUK_MEMZERO(&re_ctx, sizeof(re_ctx));
-
+	DUK_LEXER_INITCTX(&re_ctx.lex);  /* duplicate zeroing, expect for (possible) NULL inits */
 	re_ctx.thr = thr;
-	re_ctx.input = (duk_uint8_t *) DUK_HSTRING_GET_DATA(h_input);
-	re_ctx.input_end = re_ctx.input + DUK_HSTRING_GET_BYTELEN(h_input);
-	re_ctx.bytecode = (duk_uint8_t *) DUK_HSTRING_GET_DATA(h_bytecode);
-	re_ctx.bytecode_end = re_ctx.bytecode + DUK_HSTRING_GET_BYTELEN(h_bytecode);
-	re_ctx.saved = NULL;
-	re_ctx.recursion_limit = DUK_RE_EXECUTE_RECURSION_LIMIT;
-	re_ctx.steps_limit = DUK_RE_EXECUTE_STEPS_LIMIT;
+	re_ctx.lex.thr = thr;
+	re_ctx.lex.input = DUK_HSTRING_GET_DATA(h_pattern);
+	re_ctx.lex.input_length = DUK_HSTRING_GET_BYTELEN(h_pattern);
+	re_ctx.lex.token_limit = DUK_RE_COMPILE_TOKEN_LIMIT;
+	re_ctx.recursion_limit = DUK_USE_REGEXP_COMPILER_RECLIMIT;
+	re_ctx.re_flags = duk__parse_regexp_flags(thr, h_flags);
 
-	/* read header */
-	pc = re_ctx.bytecode;
-	re_ctx.re_flags = duk__bc_get_u32(&re_ctx, &pc);
-	re_ctx.nsaved = duk__bc_get_u32(&re_ctx, &pc);
-	re_ctx.bytecode = pc;
+	DUK_BW_INIT_PUSHBUF(thr, &re_ctx.bw, DUK__RE_INITIAL_BUFSIZE);
 
-	DUK_ASSERT(DUK_RE_FLAG_GLOBAL < 0x10000UL);  /* must fit into duk_small_int_t */
-	global = (duk_small_int_t) (force_global | (re_ctx.re_flags & DUK_RE_FLAG_GLOBAL));
+	DUK_DD(DUK_DDPRINT("regexp compiler ctx initialized, flags=0x%08lx, recursion_limit=%ld",
+	                   (unsigned long) re_ctx.re_flags, (long) re_ctx.recursion_limit));
 
-	DUK_ASSERT(re_ctx.nsaved >= 2);
-	DUK_ASSERT((re_ctx.nsaved % 2) == 0);
+	/*
+	 *  Init lexer
+	 */
 
-	duk_push_fixed_buffer(ctx, sizeof(duk_uint8_t *) * re_ctx.nsaved);
-	re_ctx.saved = (duk_uint8_t **) duk_get_buffer(ctx, -1, NULL);
-	DUK_ASSERT(re_ctx.saved != NULL);
+	lex_point.offset = 0;  /* expensive init, just want to fill window */
+	lex_point.line = 1;
+	DUK_LEXER_SETPOINT(&re_ctx.lex, &lex_point);
 
-	/* [ ... re_obj input bc saved_buf ] */
+	/*
+	 *  Compilation
+	 */
 
-	/* buffer is automatically zeroed */
-#ifdef DUK_USE_EXPLICIT_NULL_INIT
-	for (i = 0; i < re_ctx.nsaved; i++) {
-		re_ctx.saved[i] = (duk_uint8_t *) NULL;
-	}
-#endif
+	DUK_D(DUK_DPRINT("starting regexp compilation"));
 
-	DUK_DDD(DUK_DDDPRINT("regexp ctx initialized, flags=0x%08lx, nsaved=%ld, recursion_limit=%ld, steps_limit=%ld",
-	                     (unsigned long) re_ctx.re_flags, (long) re_ctx.nsaved, (long) re_ctx.recursion_limit,
-	                     (long) re_ctx.steps_limit));
+	duk__append_u32(&re_ctx, DUK_REOP_SAVE);
+	duk__append_u32(&re_ctx, 0);
+	duk__parse_disjunction(&re_ctx, 1 /*expect_eof*/, &ign_disj);
+	duk__append_u32(&re_ctx, DUK_REOP_SAVE);
+	duk__append_u32(&re_ctx, 1);
+	duk__append_u32(&re_ctx, DUK_REOP_MATCH);
 
 	/*
-	 *  Get starting character offset for match, and initialize 'sp' based on it.
-	 *
-	 *  Note: lastIndex is non-configurable so it must be present (we check the
-	 *  internal class of the object above, so we know it is).  User code can set
-	 *  its value to an arbitrary (garbage) value though; E5 requires that lastIndex
-	 *  be coerced to a number before using.  The code below works even if the
-	 *  property is missing: the value will then be coerced to zero.
-	 *
-	 *  Note: lastIndex may be outside Uint32 range even after ToInteger() coercion.
-	 *  For instance, ToInteger(+Infinity) = +Infinity.  We track the match offset
-	 *  as an integer, but pre-check it to be inside the 32-bit range before the loop.
-	 *  If not, the check in E5 Section 15.10.6.2, step 9.a applies.
+	 *  Check for invalid backreferences; note that it is NOT an error
+	 *  to back-reference a capture group which has not yet been introduced
+	 *  in the pattern (as in /\1(foo)/); in fact, the backreference will
+	 *  always match!  It IS an error to back-reference a capture group
+	 *  which will never be introduced in the pattern.  Thus, we can check
+	 *  for such references only after parsing is complete.
 	 */
 
-	/* XXX: lastIndex handling produces a lot of asm */
+	if (re_ctx.highest_backref > re_ctx.captures) {
+		DUK_ERROR(thr, DUK_ERR_SYNTAX_ERROR, DUK_STR_INVALID_BACKREFS);
+	}
 
-	/* [ ... re_obj input bc saved_buf ] */
+	/*
+	 *  Emit compiled regexp header: flags, ncaptures
+	 *  (insertion order inverted on purpose)
+	 */
 
-	duk_get_prop_stridx(ctx, -4, DUK_STRIDX_LAST_INDEX);  /* -> [ ... re_obj input bc saved_buf lastIndex ] */
-	(void) duk_to_int(ctx, -1);  /* ToInteger(lastIndex) */
-	d = duk_get_number(ctx, -1);  /* integer, but may be +/- Infinite, +/- zero (not NaN, though) */
-	duk_pop(ctx);
+	duk__insert_u32(&re_ctx, 0, (re_ctx.captures + 1) * 2);
+	duk__insert_u32(&re_ctx, 0, re_ctx.re_flags);
 
-	if (global) {
-		if (d < 0.0 || d > (double) DUK_HSTRING_GET_CHARLEN(h_input)) {
-			/* match fail */
-			char_offset = 0;   /* not really necessary */
-			DUK_ASSERT(match == 0);
-			goto match_over;
-		}
-		char_offset = (duk_uint32_t) d;
-	} else {
-		/* lastIndex must be ignored for non-global regexps, but get the
-		 * value for (theoretical) side effects.  No side effects can
-		 * really occur, because lastIndex is a normal property and is
-		 * always non-configurable for RegExp instances.
-		 */
-		char_offset = (duk_uint32_t) 0;
-	}
+	/* [ ... pattern flags escaped_source buffer ] */
 
-	sp = re_ctx.input + duk_heap_strcache_offset_char2byte(thr, h_input, char_offset);
+	DUK_BW_COMPACT(thr, &re_ctx.bw);
+	duk_to_string(ctx, -1);  /* coerce to string */
+
+	/* [ ... pattern flags escaped_source bytecode ] */
 
 	/*
-	 *  Match loop.
-	 *
-	 *  Try matching at different offsets until match found or input exhausted.
+	 *  Finalize stack
 	 */
 
-	/* [ ... re_obj input bc saved_buf ] */
+	duk_remove(ctx, -4);     /* -> [ ... flags escaped_source bytecode ] */
+	duk_remove(ctx, -3);     /* -> [ ... escaped_source bytecode ] */
 
-	DUK_ASSERT(match == 0);
+	DUK_D(DUK_DPRINT("regexp compilation successful, bytecode: %!T, escaped source: %!T",
+	                 (duk_tval *) duk_get_tval(ctx, -1), (duk_tval *) duk_get_tval(ctx, -2)));
+}
 
-	for (;;) {
-		/* char offset in [0, h_input->clen] (both ends inclusive), checked before entry */
-		DUK_ASSERT_DISABLE(char_offset >= 0);
-		DUK_ASSERT(char_offset <= DUK_HSTRING_GET_CHARLEN(h_input));
+/*
+ *  Create a RegExp instance (E5 Section 15.10.7).
+ *
+ *  Note: the output stack left by duk_regexp_compile() is directly compatible
+ *  with the input here.
+ *
+ *  Input stack:  [ escaped_source bytecode ]  (both as strings)
+ *  Output stack: [ RegExp ]
+ */
 
-		/* Note: ctx.steps is intentionally not reset, it applies to the entire unanchored match */
-		DUK_ASSERT(re_ctx.recursion_depth == 0);
+DUK_INTERNAL void duk_regexp_create_instance(duk_hthread *thr) {
+	duk_context *ctx = (duk_context *) thr;
+	duk_hobject *h;
+	duk_hstring *h_bc;
+	duk_small_int_t re_flags;
 
-		DUK_DDD(DUK_DDDPRINT("attempt match at char offset %ld; %p [%p,%p]",
-		                     (long) char_offset, (void *) sp, (void *) re_ctx.input,
-		                     (void *) re_ctx.input_end));
+	/* [ ... escape_source bytecode ] */
 
-		/*
-		 *  Note:
-		 *
-		 *    - duk__match_regexp() is required not to longjmp() in ordinary "non-match"
-		 *      conditions; a longjmp() will terminate the entire matching process.
-		 *
-		 *    - Clearing saved[] is not necessary because backtracking does it
-		 *
-		 *    - Backtracking also rewinds ctx.recursion back to zero, unless an
-		 *      internal/limit error occurs (which causes a longjmp())
-		 *
-		 *    - If we supported anchored matches, we would break out here
-		 *      unconditionally; however, Ecmascript regexps don't have anchored
-		 *      matches.  It might make sense to implement a fast bail-out if
-		 *      the regexp begins with '^' and sp is not 0: currently we'll just
-		 *      run through the entire input string, trivially failing the match
-		 *      at every non-zero offset.
-		 */
+	h_bc = duk_get_hstring(ctx, -1);
+	DUK_ASSERT(h_bc != NULL);
+	DUK_ASSERT(DUK_HSTRING_GET_BYTELEN(h_bc) >= 1);          /* always at least the header */
+	DUK_ASSERT(DUK_HSTRING_GET_CHARLEN(h_bc) >= 1);
+	DUK_ASSERT((duk_small_int_t) DUK_HSTRING_GET_DATA(h_bc)[0] < 0x80);  /* flags always encodes to 1 byte */
+	re_flags = (duk_small_int_t) DUK_HSTRING_GET_DATA(h_bc)[0];
 
-		if (duk__match_regexp(&re_ctx, re_ctx.bytecode, sp) != NULL) {
-			DUK_DDD(DUK_DDDPRINT("match at offset %ld", (long) char_offset));
-			match = 1;
-			break;
-		}
+	/* [ ... escaped_source bytecode ] */
 
-		/* advance by one character (code point) and one char_offset */
-		char_offset++;
-		if (char_offset > DUK_HSTRING_GET_CHARLEN(h_input)) {
-			/*
-			 *  Note:
-			 *
-			 *    - Intentionally attempt (empty) match at char_offset == k_input->clen
-			 *
-			 *    - Negative char_offsets have been eliminated and char_offset is duk_uint32_t
-			 *      -> no need or use for a negative check
-			 */
+	duk_push_object(ctx);
+	h = duk_get_hobject(ctx, -1);
+	DUK_ASSERT(h != NULL);
+	duk_insert(ctx, -3);
 
-			DUK_DDD(DUK_DDDPRINT("no match after trying all sp offsets"));
-			break;
-		}
+	/* [ ... regexp_object escaped_source bytecode ] */
 
-		/* avoid calling at end of input, will DUK_ERROR (above check suffices to avoid this) */
-		(void) duk__utf8_advance(thr, &sp, re_ctx.input, re_ctx.input_end, (duk_uint_fast32_t) 1);
-	}
+	DUK_HOBJECT_SET_CLASS_NUMBER(h, DUK_HOBJECT_CLASS_REGEXP);
+	DUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr, h, thr->builtins[DUK_BIDX_REGEXP_PROTOTYPE]);
 
- match_over:
+	duk_xdef_prop_stridx(ctx, -3, DUK_STRIDX_INT_BYTECODE, DUK_PROPDESC_FLAGS_NONE);
 
-	/*
-	 *  Matching complete, create result array or return a 'null'.  Update lastIndex
-	 *  if necessary.  See E5 Section 15.10.6.2.
-	 *
-	 *  Because lastIndex is a character (not byte) offset, we need the character
-	 *  length of the match which we conveniently get as a side effect of interning
-	 *  the matching substring (0th index of result array).
-	 *
-	 *  saved[0]         start pointer (~ byte offset) of current match
-	 *  saved[1]         end pointer (~ byte offset) of current match (exclusive)
-	 *  char_offset      start character offset of current match (-> .index of result)
-	 *  char_end_offset  end character offset (computed below)
-	 */
+	/* [ ... regexp_object escaped_source ] */
 
-	/* [ ... re_obj input bc saved_buf ] */
+	duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_SOURCE, DUK_PROPDESC_FLAGS_NONE);
 
-	if (match) {
-#ifdef DUK_USE_ASSERTIONS
-		duk_hobject *h_res;
-#endif
-		duk_uint32_t char_end_offset = 0;
+	/* [ ... regexp_object ] */
 
-		DUK_DDD(DUK_DDDPRINT("regexp matches at char_offset %ld", (long) char_offset));
+	duk_push_boolean(ctx, (re_flags & DUK_RE_FLAG_GLOBAL));
+	duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_GLOBAL, DUK_PROPDESC_FLAGS_NONE);
 
-		DUK_ASSERT(re_ctx.nsaved >= 2);        /* must have start and end */
-		DUK_ASSERT((re_ctx.nsaved % 2) == 0);  /* and even number */
+	duk_push_boolean(ctx, (re_flags & DUK_RE_FLAG_IGNORE_CASE));
+	duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_IGNORE_CASE, DUK_PROPDESC_FLAGS_NONE);
 
-		/* XXX: Array size is known before and (2 * re_ctx.nsaved) but not taken
-		 * advantage of now.  The array is not compacted either, as regexp match
-		 * objects are usually short lived.
-		 */
+	duk_push_boolean(ctx, (re_flags & DUK_RE_FLAG_MULTILINE));
+	duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_MULTILINE, DUK_PROPDESC_FLAGS_NONE);
 
-		duk_push_array(ctx);
+	duk_push_int(ctx, 0);
+	duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_LAST_INDEX, DUK_PROPDESC_FLAGS_W);
 
-#ifdef DUK_USE_ASSERTIONS
-		h_res = duk_require_hobject(ctx, -1);
-		DUK_ASSERT(DUK_HOBJECT_HAS_EXTENSIBLE(h_res));
-		DUK_ASSERT(DUK_HOBJECT_HAS_EXOTIC_ARRAY(h_res));
-		DUK_ASSERT(DUK_HOBJECT_GET_CLASS_NUMBER(h_res) == DUK_HOBJECT_CLASS_ARRAY);
-#endif
+	/* [ ... regexp_object ] */
+}
 
-		/* [ ... re_obj input bc saved_buf res_obj ] */
+#undef DUK__RE_BUFLEN
 
-		duk_push_number(ctx, (double) char_offset);
-		duk_def_prop_stridx_wec(ctx, -2, DUK_STRIDX_INDEX);
+#else  /* DUK_USE_REGEXP_SUPPORT */
 
-		duk_dup(ctx, -4);
-		duk_def_prop_stridx_wec(ctx, -2, DUK_STRIDX_INPUT);
+/* regexp support disabled */
 
-		for (i = 0; i < re_ctx.nsaved; i += 2) {
-			/* Captures which are undefined have NULL pointers and are returned
-			 * as 'undefined'.  The same is done when saved[] pointers are insane
-			 * (this should, of course, never happen in practice).
-			 */
-			if (re_ctx.saved[i] && re_ctx.saved[i+1] && re_ctx.saved[i+1] >= re_ctx.saved[i]) {
-				duk_hstring *h_saved;
+#endif  /* DUK_USE_REGEXP_SUPPORT */
+#line 1 "duk_regexp_executor.c"
+/*
+ *  Regexp executor.
+ *
+ *  Safety: the Ecmascript executor should prevent user from reading and
+ *  replacing regexp bytecode.  Even so, the executor must validate all
+ *  memory accesses etc.  When an invalid access is detected (e.g. a 'save'
+ *  opcode to invalid, unallocated index) it should fail with an internal
+ *  error but not cause a segmentation fault.
+ *
+ *  Notes:
+ *
+ *    - Backtrack counts are limited to unsigned 32 bits but should
+ *      technically be duk_size_t for strings longer than 4G chars.
+ *      This also requires a regexp bytecode change.
+ */
 
-				duk_push_lstring(ctx,
-				                 (char *) re_ctx.saved[i],
-				                 (duk_size_t) (re_ctx.saved[i+1] - re_ctx.saved[i]));
-				h_saved = duk_get_hstring(ctx, -1);
-				DUK_ASSERT(h_saved != NULL);
+/* include removed: duk_internal.h */
 
-				if (i == 0) {
-					/* Assumes that saved[0] and saved[1] are always
-					 * set by regexp bytecode (if not, char_end_offset
-					 * will be zero).  Also assumes clen reflects the
-					 * correct char length.
-					 */
-					char_end_offset = char_offset + DUK_HSTRING_GET_CHARLEN(h_saved);
-				}
-			} else {
-				duk_push_undefined(ctx);
-			}
+#ifdef DUK_USE_REGEXP_SUPPORT
 
-			/* [ ... re_obj input bc saved_buf res_obj val ] */
-			duk_put_prop_index(ctx, -2, i / 2);
-		}
+/*
+ *  Helpers for UTF-8 handling
+ *
+ *  For bytecode readers the duk_uint32_t and duk_int32_t types are correct
+ *  because they're used for more than just codepoints.
+ */
 
-		/* [ ... re_obj input bc saved_buf res_obj ] */
+DUK_LOCAL duk_uint32_t duk__bc_get_u32(duk_re_matcher_ctx *re_ctx, const duk_uint8_t **pc) {
+	return (duk_uint32_t) duk_unicode_decode_xutf8_checked(re_ctx->thr, pc, re_ctx->bytecode, re_ctx->bytecode_end);
+}
 
-		/* NB: 'length' property is automatically updated by the array setup loop */
+DUK_LOCAL duk_int32_t duk__bc_get_i32(duk_re_matcher_ctx *re_ctx, const duk_uint8_t **pc) {
+	duk_uint32_t t;
 
-		if (global) {
-			/* global regexp: lastIndex updated on match */
-			duk_push_number(ctx, (double) char_end_offset);
-			duk_put_prop_stridx(ctx, -6, DUK_STRIDX_LAST_INDEX);
-		} else {
-			/* non-global regexp: lastIndex never updated on match */
-			;
-		}
+	/* signed integer encoding needed to work with UTF-8 */
+	t = (duk_uint32_t) duk_unicode_decode_xutf8_checked(re_ctx->thr, pc, re_ctx->bytecode, re_ctx->bytecode_end);
+	if (t & 1) {
+		return -((duk_int32_t) (t >> 1));
 	} else {
-		/*
-		 *  No match, E5 Section 15.10.6.2, step 9.a.i - 9.a.ii apply, regardless
-		 *  of 'global' flag of the RegExp.  In particular, if lastIndex is invalid
-		 *  initially, it is reset to zero.
-		 */
-
-		DUK_DDD(DUK_DDDPRINT("regexp does not match"));
+		return (duk_int32_t) (t >> 1);
+	}
+}
 
-		duk_push_null(ctx);
+DUK_LOCAL const duk_uint8_t *duk__utf8_backtrack(duk_hthread *thr, const duk_uint8_t **ptr, const duk_uint8_t *ptr_start, const duk_uint8_t *ptr_end, duk_uint_fast32_t count) {
+	const duk_uint8_t *p;
 
-		/* [ ... re_obj input bc saved_buf res_obj ] */
+	/* Note: allow backtracking from p == ptr_end */
+	p = *ptr;
+	if (p < ptr_start || p > ptr_end) {
+		goto fail;
+	}
 
-		duk_push_int(ctx, 0);
-		duk_put_prop_stridx(ctx, -6, DUK_STRIDX_LAST_INDEX);
+	while (count > 0) {
+		for (;;) {
+			p--;
+			if (p < ptr_start) {
+				goto fail;
+			}
+			if ((*p & 0xc0) != 0x80) {
+				/* utf-8 continuation bytes have the form 10xx xxxx */
+				break;
+			}
+		}
+		count--;
 	}
+	*ptr = p;
+	return p;
 
-	/* [ ... re_obj input bc saved_buf res_obj ] */
+ fail:
+	DUK_ERROR(thr, DUK_ERR_INTERNAL_ERROR, DUK_STR_REGEXP_BACKTRACK_FAILED);
+	return NULL;  /* never here */
+}
 
-	duk_insert(ctx, -5);
+DUK_LOCAL const duk_uint8_t *duk__utf8_advance(duk_hthread *thr, const duk_uint8_t **ptr, const duk_uint8_t *ptr_start, const duk_uint8_t *ptr_end, duk_uint_fast32_t count) {
+	const duk_uint8_t *p;
 
-	/* [ ... res_obj re_obj input bc saved_buf ] */
+	p = *ptr;
+	if (p < ptr_start || p >= ptr_end) {
+		goto fail;
+	}
 
-	duk_pop_n(ctx, 4);
+	while (count > 0) {
+		for (;;) {
+			p++;
+
+			/* Note: if encoding ends by hitting end of input, we don't check that
+			 * the encoding is valid, we just assume it is.
+			 */
+			if (p >= ptr_end || ((*p & 0xc0) != 0x80)) {
+				/* utf-8 continuation bytes have the form 10xx xxxx */
+				break;
+			}
+		}
+		count--;
+	}
 
-	/* [ ... res_obj ] */
+	*ptr = p;
+	return p;
 
-	/* XXX: these last tricks are unnecessary if the function is made
-	 * a genuine native function.
-	 */
+ fail:
+	DUK_ERROR(thr, DUK_ERR_INTERNAL_ERROR, DUK_STR_REGEXP_ADVANCE_FAILED);
+	return NULL;  /* never here */
 }
 
-void duk_regexp_match(duk_hthread *thr) {
-	duk__regexp_match_helper(thr, 0 /*force_global*/);
-}
+/*
+ *  Helpers for dealing with the input string
+ */
 
-/* This variant is needed by String.prototype.split(); it needs to perform
- * global-style matching on a cloned RegExp which is potentially non-global.
+/* Get a (possibly canonicalized) input character from current sp.  The input
+ * itself is never modified, and captures always record non-canonicalized
+ * characters even in case-insensitive matching.
  */
-void duk_regexp_match_force_global(duk_hthread *thr) {
-	duk__regexp_match_helper(thr, 1 /*force_global*/);
+DUK_LOCAL duk_codepoint_t duk__inp_get_cp(duk_re_matcher_ctx *re_ctx, const duk_uint8_t **sp) {
+	duk_codepoint_t res = (duk_codepoint_t) duk_unicode_decode_xutf8_checked(re_ctx->thr, sp, re_ctx->input, re_ctx->input_end);
+	if (re_ctx->re_flags & DUK_RE_FLAG_IGNORE_CASE) {
+		res = duk_unicode_re_canonicalize_char(re_ctx->thr, res);
+	}
+	return res;
 }
 
-#else  /* DUK_USE_REGEXP_SUPPORT */
-
-/* regexp support disabled */
+DUK_LOCAL const duk_uint8_t *duk__inp_backtrack(duk_re_matcher_ctx *re_ctx, const duk_uint8_t **sp, duk_uint_fast32_t count) {
+	return duk__utf8_backtrack(re_ctx->thr, sp, re_ctx->input, re_ctx->input_end, count);
+}
 
-#endif  /* DUK_USE_REGEXP_SUPPORT */
+/* Backtrack utf-8 input and return a (possibly canonicalized) input character. */
+DUK_LOCAL duk_codepoint_t duk__inp_get_prev_cp(duk_re_matcher_ctx *re_ctx, const duk_uint8_t *sp) {
+	/* note: caller 'sp' is intentionally not updated here */
+	(void) duk__inp_backtrack(re_ctx, &sp, (duk_uint_fast32_t) 1);
+	return duk__inp_get_cp(re_ctx, &sp);
+}
 
-#line 1 "duk_replacements.c"
 /*
- *  Replacements for missing platform functions.
+ *  Regexp recursive matching function.
  *
- *  Unlike the originals, fpclassify() and signbit() replacements don't
- *  work on any floating point types, only doubles.  The C typing here
- *  mimics the standard prototypes.
+ *  Returns 'sp' on successful match (points to character after last matched one),
+ *  NULL otherwise.
+ *
+ *  The C recursion depth limit check is only performed in this function, this
+ *  suffices because the function is present in all true recursion required by
+ *  regexp execution.
  */
 
-/* include removed: duk_internal.h */
-
-#ifdef DUK_USE_COMPUTED_NAN
-double duk_computed_nan;
-#endif
-
-#ifdef DUK_USE_COMPUTED_INFINITY
-double duk_computed_infinity;
-#endif
-
-#ifdef DUK_USE_REPL_FPCLASSIFY
-int duk_repl_fpclassify(double x) {
-	duk_double_union u;
-	duk_uint_fast16_t exp;
-	duk_small_int_t mzero;
-
-	u.d = x;
-	exp = (duk_uint_fast16_t) (u.us[DUK_DBL_IDX_US0] & 0x7ff0UL);
-	if (exp > 0x0000UL && exp < 0x7ff0UL) {
-		/* exp values [0x001,0x7fe] = normal */
-		return DUK_FP_NORMAL;
+DUK_LOCAL const duk_uint8_t *duk__match_regexp(duk_re_matcher_ctx *re_ctx, const duk_uint8_t *pc, const duk_uint8_t *sp) {
+	if (re_ctx->recursion_depth >= re_ctx->recursion_limit) {
+		DUK_ERROR(re_ctx->thr, DUK_ERR_RANGE_ERROR, DUK_STR_REGEXP_EXECUTOR_RECURSION_LIMIT);
 	}
+	re_ctx->recursion_depth++;
 
-	mzero = (u.ui[DUK_DBL_IDX_UI1] == 0 && (u.ui[DUK_DBL_IDX_UI0] & 0x000fffffUL) == 0);
-	if (exp == 0x0000UL) {
-		/* exp 0x000 is zero/subnormal */
-		if (mzero) {
-			return DUK_FP_ZERO;
-		} else {
-			return DUK_FP_SUBNORMAL;
-		}
-	} else {
-		/* exp 0xfff is infinite/nan */
-		if (mzero) {
-			return DUK_FP_INFINITE;
-		} else {
-			return DUK_FP_NAN;
+	for (;;) {
+		duk_small_int_t op;
+
+		if (re_ctx->steps_count >= re_ctx->steps_limit) {
+			DUK_ERROR(re_ctx->thr, DUK_ERR_RANGE_ERROR, DUK_STR_REGEXP_EXECUTOR_STEP_LIMIT);
 		}
-	}
-}
-#endif
+		re_ctx->steps_count++;
 
-#ifdef DUK_USE_REPL_SIGNBIT
-int duk_repl_signbit(double x) {
-	duk_double_union u;
-	u.d = x;
-	return (int) (u.uc[DUK_DBL_IDX_UC0] & 0x80UL);
-}
-#endif
+		op = (duk_small_int_t) duk__bc_get_u32(re_ctx, &pc);
 
-#ifdef DUK_USE_REPL_ISFINITE
-int duk_repl_isfinite(double x) {
-	int c = DUK_FPCLASSIFY(x);
-	if (c == DUK_FP_NAN || c == DUK_FP_INFINITE) {
-		return 0;
-	} else {
-		return 1;
-	}
-}
-#endif
+		DUK_DDD(DUK_DDDPRINT("match: rec=%ld, steps=%ld, pc (after op)=%ld, sp=%ld, op=%ld",
+		                     (long) re_ctx->recursion_depth,
+		                     (long) re_ctx->steps_count,
+		                     (long) (pc - re_ctx->bytecode),
+		                     (long) (sp - re_ctx->input),
+		                     (long) op));
 
-#ifdef DUK_USE_REPL_ISNAN
-int duk_repl_isnan(double x) {
-	int c = DUK_FPCLASSIFY(x);
-	return (c == DUK_FP_NAN);
-}
-#endif
+		switch (op) {
+		case DUK_REOP_MATCH: {
+			goto match;
+		}
+		case DUK_REOP_CHAR: {
+			/*
+			 *  Byte-based matching would be possible for case-sensitive
+			 *  matching but not for case-insensitive matching.  So, we
+			 *  match by decoding the input and bytecode character normally.
+			 *
+			 *  Bytecode characters are assumed to be already canonicalized.
+			 *  Input characters are canonicalized automatically by
+			 *  duk__inp_get_cp() if necessary.
+			 *
+			 *  There is no opcode for matching multiple characters.  The
+			 *  regexp compiler has trouble joining strings efficiently
+			 *  during compilation.  See doc/regexp.rst for more discussion.
+			 */
+			duk_codepoint_t c1, c2;
 
-#ifdef DUK_USE_REPL_ISINF
-int duk_repl_isinf(double x) {
-	int c = DUK_FPCLASSIFY(x);
-	return (c == DUK_FP_INFINITE);
-}
-#endif
+			c1 = (duk_codepoint_t) duk__bc_get_u32(re_ctx, &pc);
+			DUK_ASSERT(!(re_ctx->re_flags & DUK_RE_FLAG_IGNORE_CASE) ||
+			           c1 == duk_unicode_re_canonicalize_char(re_ctx->thr, c1));  /* canonicalized by compiler */
+			if (sp >= re_ctx->input_end) {
+				goto fail;
+			}
+			c2 = duk__inp_get_cp(re_ctx, &sp);
+			DUK_DDD(DUK_DDDPRINT("char match, c1=%ld, c2=%ld", (long) c1, (long) c2));
+			if (c1 != c2) {
+				goto fail;
+			}
+			break;
+		}
+		case DUK_REOP_PERIOD: {
+			duk_codepoint_t c;
 
-#line 1 "duk_selftest.c"
-/*
- *  Self tests to ensure execution environment is sane.  Intended to catch
- *  compiler/platform problems which cannot be detected at compile time.
- */
+			if (sp >= re_ctx->input_end) {
+				goto fail;
+			}
+			c = duk__inp_get_cp(re_ctx, &sp);
+			if (duk_unicode_is_line_terminator(c)) {
+				/* E5 Sections 15.10.2.8, 7.3 */
+				goto fail;
+			}
+			break;
+		}
+		case DUK_REOP_RANGES:
+		case DUK_REOP_INVRANGES: {
+			duk_uint32_t n;
+			duk_codepoint_t c;
+			duk_small_int_t match;
 
-/* include removed: duk_internal.h */
+			n = duk__bc_get_u32(re_ctx, &pc);
+			if (sp >= re_ctx->input_end) {
+				goto fail;
+			}
+			c = duk__inp_get_cp(re_ctx, &sp);
 
-#if defined(DUK_USE_SELF_TESTS)
+			match = 0;
+			while (n) {
+				duk_codepoint_t r1, r2;
+				r1 = (duk_codepoint_t) duk__bc_get_u32(re_ctx, &pc);
+				r2 = (duk_codepoint_t) duk__bc_get_u32(re_ctx, &pc);
+				DUK_DDD(DUK_DDDPRINT("matching ranges/invranges, n=%ld, r1=%ld, r2=%ld, c=%ld",
+				                     (long) n, (long) r1, (long) r2, (long) c));
+				if (c >= r1 && c <= r2) {
+					/* Note: don't bail out early, we must read all the ranges from
+					 * bytecode.  Another option is to skip them efficiently after
+					 * breaking out of here.  Prefer smallest code.
+					 */
+					match = 1;
+				}
+				n--;
+			}
 
-/*
- *  Unions and structs for self tests
- */
+			if (op == DUK_REOP_RANGES) {
+				if (!match) {
+					goto fail;
+				}
+			} else {
+				DUK_ASSERT(op == DUK_REOP_INVRANGES);
+				if (match) {
+					goto fail;
+				}
+			}
+			break;
+		}
+		case DUK_REOP_ASSERT_START: {
+			duk_codepoint_t c;
 
-typedef union {
-	double d;
-	duk_uint8_t c[8];
-} duk__test_double_union;
+			if (sp <= re_ctx->input) {
+				break;
+			}
+			if (!(re_ctx->re_flags & DUK_RE_FLAG_MULTILINE)) {
+				goto fail;
+			}
+			c = duk__inp_get_prev_cp(re_ctx, sp);
+			if (duk_unicode_is_line_terminator(c)) {
+				/* E5 Sections 15.10.2.8, 7.3 */
+				break;
+			}
+			goto fail;
+		}
+		case DUK_REOP_ASSERT_END: {
+			duk_codepoint_t c;
+			const duk_uint8_t *tmp_sp;
 
-#define DUK__DBLUNION_CMP_TRUE(a,b)  do { \
-		if (DUK_MEMCMP((void *) (a), (void *) (b), sizeof(duk__test_double_union)) != 0) { \
-			DUK_PANIC(DUK_ERR_INTERNAL_ERROR, "self test failed: double union compares false (expected true)"); \
-		} \
-	} while (0)
+			if (sp >= re_ctx->input_end) {
+				break;
+			}
+			if (!(re_ctx->re_flags & DUK_RE_FLAG_MULTILINE)) {
+				goto fail;
+			}
+			tmp_sp = sp;
+			c = duk__inp_get_cp(re_ctx, &tmp_sp);
+			if (duk_unicode_is_line_terminator(c)) {
+				/* E5 Sections 15.10.2.8, 7.3 */
+				break;
+			}
+			goto fail;
+		}
+		case DUK_REOP_ASSERT_WORD_BOUNDARY:
+		case DUK_REOP_ASSERT_NOT_WORD_BOUNDARY: {
+			/*
+			 *  E5 Section 15.10.2.6.  The previous and current character
+			 *  should -not- be canonicalized as they are now.  However,
+			 *  canonicalization does not affect the result of IsWordChar()
+			 *  (which depends on Unicode characters never canonicalizing
+			 *  into ASCII characters) so this does not matter.
+			 */
+			duk_small_int_t w1, w2;
 
-#define DUK__DBLUNION_CMP_FALSE(a,b)  do { \
-		if (DUK_MEMCMP((void *) (a), (void *) (b), sizeof(duk__test_double_union)) == 0) { \
-			DUK_PANIC(DUK_ERR_INTERNAL_ERROR, "self test failed: double union compares true (expected false)"); \
-		} \
-	} while (0)
+			if (sp <= re_ctx->input) {
+				w1 = 0;  /* not a wordchar */
+			} else {
+				duk_codepoint_t c;
+				c = duk__inp_get_prev_cp(re_ctx, sp);
+				w1 = duk_unicode_re_is_wordchar(c);
+			}
+			if (sp >= re_ctx->input_end) {
+				w2 = 0;  /* not a wordchar */
+			} else {
+				const duk_uint8_t *tmp_sp = sp;  /* dummy so sp won't get updated */
+				duk_codepoint_t c;
+				c = duk__inp_get_cp(re_ctx, &tmp_sp);
+				w2 = duk_unicode_re_is_wordchar(c);
+			}
 
-typedef union {
-	duk_uint32_t i;
-	duk_uint8_t c[8];
-} duk__test_u32_union;
+			if (op == DUK_REOP_ASSERT_WORD_BOUNDARY) {
+				if (w1 == w2) {
+					goto fail;
+				}
+			} else {
+				DUK_ASSERT(op == DUK_REOP_ASSERT_NOT_WORD_BOUNDARY);
+				if (w1 != w2) {
+					goto fail;
+				}
+			}
+			break;
+		}
+		case DUK_REOP_JUMP: {
+			duk_int32_t skip;
 
-/*
- *  Various sanity checks for typing
- */
+			skip = duk__bc_get_i32(re_ctx, &pc);
+			pc += skip;
+			break;
+		}
+		case DUK_REOP_SPLIT1: {
+			/* split1: prefer direct execution (no jump) */
+			const duk_uint8_t *sub_sp;
+			duk_int32_t skip;
 
-static void duk__selftest_types(void) {
-	if (!(sizeof(duk_int8_t) == 1 &&
-	      sizeof(duk_uint8_t) == 1 &&
-	      sizeof(duk_int16_t) == 2 &&
-	      sizeof(duk_uint16_t) == 2 &&
-	      sizeof(duk_int32_t) == 4 &&
-	      sizeof(duk_uint32_t) == 4)) {
-		DUK_PANIC(DUK_ERR_INTERNAL_ERROR, "self test failed: duk_(u)int{8,16,32}_t size");
-	}
-#if defined(DUK_USE_64BIT_OPS)
-	if (!(sizeof(duk_int64_t) == 8 &&
-	      sizeof(duk_uint64_t) == 8)) {
-		DUK_PANIC(DUK_ERR_INTERNAL_ERROR, "self test failed: duk_(u)int64_t size");
-	}
-#endif
+			skip = duk__bc_get_i32(re_ctx, &pc);
+			sub_sp = duk__match_regexp(re_ctx, pc, sp);
+			if (sub_sp) {
+				sp = sub_sp;
+				goto match;
+			}
+			pc += skip;
+			break;
+		}
+		case DUK_REOP_SPLIT2: {
+			/* split2: prefer jump execution (not direct) */
+			const duk_uint8_t *sub_sp;
+			duk_int32_t skip;
 
-	if (!(sizeof(duk_size_t) >= sizeof(duk_uint_t))) {
-		/* Some internal code now assumes that all duk_uint_t values
-		 * can be expressed with a duk_size_t.
-		 */
-		DUK_PANIC(DUK_ERR_INTERNAL_ERROR, "self test failed: duk_size_t is smaller than duk_uint_t");
-	}
-	if (!(sizeof(duk_int_t) >= 4)) {
-		DUK_PANIC(DUK_ERR_INTERNAL_ERROR, "self test failed: duk_int_t is not 32 bits");
-	}
-}
+			skip = duk__bc_get_i32(re_ctx, &pc);
+			sub_sp = duk__match_regexp(re_ctx, pc + skip, sp);
+			if (sub_sp) {
+				sp = sub_sp;
+				goto match;
+			}
+			break;
+		}
+		case DUK_REOP_SQMINIMAL: {
+			duk_uint32_t q, qmin, qmax;
+			duk_int32_t skip;
+			const duk_uint8_t *sub_sp;
 
-/*
- *  Packed tval sanity
- */
+			qmin = duk__bc_get_u32(re_ctx, &pc);
+			qmax = duk__bc_get_u32(re_ctx, &pc);
+			skip = duk__bc_get_i32(re_ctx, &pc);
+			DUK_DDD(DUK_DDDPRINT("minimal quantifier, qmin=%lu, qmax=%lu, skip=%ld",
+			                     (unsigned long) qmin, (unsigned long) qmax, (long) skip));
 
-static void duk__selftest_packed_tval(void) {
-#if defined(DUK_USE_PACKED_TVAL)
-	if (sizeof(void *) > 4) {
-		DUK_PANIC(DUK_ERR_INTERNAL_ERROR, "self test failed: packed duk_tval in use but sizeof(void *) > 4");
-	}
-#endif
-}
+			q = 0;
+			while (q <= qmax) {
+				if (q >= qmin) {
+					sub_sp = duk__match_regexp(re_ctx, pc + skip, sp);
+					if (sub_sp) {
+						sp = sub_sp;
+						goto match;
+					}
+				}
+				sub_sp = duk__match_regexp(re_ctx, pc, sp);
+				if (!sub_sp) {
+					break;
+				}
+				sp = sub_sp;
+				q++;
+			}
+			goto fail;
+		}
+		case DUK_REOP_SQGREEDY: {
+			duk_uint32_t q, qmin, qmax, atomlen;
+			duk_int32_t skip;
+			const duk_uint8_t *sub_sp;
 
-/*
- *  Two's complement arithmetic.
- */
+			qmin = duk__bc_get_u32(re_ctx, &pc);
+			qmax = duk__bc_get_u32(re_ctx, &pc);
+			atomlen = duk__bc_get_u32(re_ctx, &pc);
+			skip = duk__bc_get_i32(re_ctx, &pc);
+			DUK_DDD(DUK_DDDPRINT("greedy quantifier, qmin=%lu, qmax=%lu, atomlen=%lu, skip=%ld",
+			                     (unsigned long) qmin, (unsigned long) qmax, (unsigned long) atomlen, (long) skip));
 
-static void duk__selftest_twos_complement(void) {
-	volatile int test;
-	test = -1;
-	if (((duk_uint8_t *) &test)[0] != (duk_uint8_t) 0xff) {
-		DUK_PANIC(DUK_ERR_INTERNAL_ERROR, "self test failed: two's complement arithmetic");
-	}
-}
+			q = 0;
+			while (q < qmax) {
+				sub_sp = duk__match_regexp(re_ctx, pc, sp);
+				if (!sub_sp) {
+					break;
+				}
+				sp = sub_sp;
+				q++;
+			}
+			while (q >= qmin) {
+				sub_sp = duk__match_regexp(re_ctx, pc + skip, sp);
+				if (sub_sp) {
+					sp = sub_sp;
+					goto match;
+				}
+				if (q == qmin) {
+					break;
+				}
 
-/*
- *  Byte order.  Important to self check, because on some exotic platforms
- *  there is no actual detection but rather assumption based on platform
- *  defines.
- */
+				/* Note: if atom were to contain e.g. captures, we would need to
+				 * re-match the atom to get correct captures.  Simply quantifiers
+				 * do not allow captures in their atom now, so this is not an issue.
+				 */
 
-static void duk__selftest_byte_order(void) {
-	duk__test_u32_union u1;
-	duk__test_double_union u2;
+				DUK_DDD(DUK_DDDPRINT("greedy quantifier, backtrack %ld characters (atomlen)",
+				                     (long) atomlen));
+				sp = duk__inp_backtrack(re_ctx, &sp, (duk_uint_fast32_t) atomlen);
+				q--;
+			}
+			goto fail;
+		}
+		case DUK_REOP_SAVE: {
+			duk_uint32_t idx;
+			const duk_uint8_t *old;
+			const duk_uint8_t *sub_sp;
 
-	/*
-	 *  >>> struct.pack('>d', 102030405060).encode('hex')
-	 *  '4237c17c6dc40000'
-	 */
-#if defined(DUK_USE_INTEGER_LE)
-	u1.c[0] = 0xef; u1.c[1] = 0xbe; u1.c[2] = 0xad; u1.c[3] = 0xde;
-#elif defined(DUK_USE_INTEGER_ME)
-#error integer mixed endian not supported now
-#elif defined(DUK_USE_INTEGER_BE)
-	u1.c[0] = 0xde; u1.c[1] = 0xad; u1.c[2] = 0xbe; u1.c[3] = 0xef;
-#else
-#error unknown integer endianness
+			idx = duk__bc_get_u32(re_ctx, &pc);
+			if (idx >= re_ctx->nsaved) {
+				/* idx is unsigned, < 0 check is not necessary */
+				DUK_D(DUK_DPRINT("internal error, regexp save index insane: idx=%ld", (long) idx));
+				goto internal_error;
+			}
+			old = re_ctx->saved[idx];
+			re_ctx->saved[idx] = sp;
+			sub_sp = duk__match_regexp(re_ctx, pc, sp);
+			if (sub_sp) {
+				sp = sub_sp;
+				goto match;
+			}
+			re_ctx->saved[idx] = old;
+			goto fail;
+		}
+		case DUK_REOP_WIPERANGE: {
+			/* Wipe capture range and save old values for backtracking.
+			 *
+			 * XXX: this typically happens with a relatively small idx_count.
+			 * It might be useful to handle cases where the count is small
+			 * (say <= 8) by saving the values in stack instead.  This would
+			 * reduce memory churn and improve performance, at the cost of a
+			 * slightly higher code footprint.
+			 */
+			duk_uint32_t idx_start, idx_count;
+#ifdef DUK_USE_EXPLICIT_NULL_INIT
+			duk_uint32_t idx_end, idx;
 #endif
+			duk_uint8_t **range_save;
+			const duk_uint8_t *sub_sp;
 
-#if defined(DUK_USE_DOUBLE_LE)
-	u2.c[0] = 0x00; u2.c[1] = 0x00; u2.c[2] = 0xc4; u2.c[3] = 0x6d;
-	u2.c[4] = 0x7c; u2.c[5] = 0xc1; u2.c[6] = 0x37; u2.c[7] = 0x42;
-#elif defined(DUK_USE_DOUBLE_ME)
-	u2.c[0] = 0x7c; u2.c[1] = 0xc1; u2.c[2] = 0x37; u2.c[3] = 0x42;
-	u2.c[4] = 0x00; u2.c[5] = 0x00; u2.c[6] = 0xc4; u2.c[7] = 0x6d;
-#elif defined(DUK_USE_DOUBLE_BE)
-	u2.c[0] = 0x42; u2.c[1] = 0x37; u2.c[2] = 0xc1; u2.c[3] = 0x7c;
-	u2.c[4] = 0x6d; u2.c[5] = 0xc4; u2.c[6] = 0x00; u2.c[7] = 0x00;
+			idx_start = duk__bc_get_u32(re_ctx, &pc);
+			idx_count = duk__bc_get_u32(re_ctx, &pc);
+			DUK_DDD(DUK_DDDPRINT("wipe saved range: start=%ld, count=%ld -> [%ld,%ld] (captures [%ld,%ld])",
+			                     (long) idx_start, (long) idx_count,
+			                     (long) idx_start, (long) (idx_start + idx_count - 1),
+			                     (long) (idx_start / 2), (long) ((idx_start + idx_count - 1) / 2)));
+			if (idx_start + idx_count > re_ctx->nsaved || idx_count == 0) {
+				/* idx is unsigned, < 0 check is not necessary */
+				DUK_D(DUK_DPRINT("internal error, regexp wipe indices insane: idx_start=%ld, idx_count=%ld",
+				                 (long) idx_start, (long) idx_count));
+				goto internal_error;
+			}
+			DUK_ASSERT(idx_count > 0);
+
+			duk_require_stack((duk_context *) re_ctx->thr, 1);
+			range_save = (duk_uint8_t **) duk_push_fixed_buffer((duk_context *) re_ctx->thr,
+			                                                    sizeof(duk_uint8_t *) * idx_count);
+			DUK_ASSERT(range_save != NULL);
+			DUK_MEMCPY(range_save, re_ctx->saved + idx_start, sizeof(duk_uint8_t *) * idx_count);
+#ifdef DUK_USE_EXPLICIT_NULL_INIT
+			idx_end = idx_start + idx_count;
+			for (idx = idx_start; idx < idx_end; idx++) {
+				re_ctx->saved[idx] = NULL;
+			}
 #else
-#error unknown double endianness
+			DUK_MEMZERO((void *) (re_ctx->saved + idx_start), sizeof(duk_uint8_t *) * idx_count);
 #endif
 
-	if (u1.i != (duk_uint32_t) 0xdeadbeefUL) {
-		DUK_PANIC(DUK_ERR_INTERNAL_ERROR, "self test failed: duk_uint32_t byte order");
-	}
+			sub_sp = duk__match_regexp(re_ctx, pc, sp);
+			if (sub_sp) {
+				/* match: keep wiped/resaved values */
+				DUK_DDD(DUK_DDDPRINT("match: keep wiped/resaved values [%ld,%ld] (captures [%ld,%ld])",
+				                     (long) idx_start, (long) (idx_start + idx_count - 1),
+			                             (long) (idx_start / 2), (long) ((idx_start + idx_count - 1) / 2)));
+				duk_pop((duk_context *) re_ctx->thr);
+				sp = sub_sp;
+				goto match;
+			}
 
-	if (u2.d != (double) 102030405060.0) {
-		DUK_PANIC(DUK_ERR_INTERNAL_ERROR, "self test failed: double byte order");
-	}
-}
+			/* fail: restore saves */
+			DUK_DDD(DUK_DDDPRINT("fail: restore wiped/resaved values [%ld,%ld] (captures [%ld,%ld])",
+			                     (long) idx_start, (long) (idx_start + idx_count - 1),
+			                     (long) (idx_start / 2), (long) ((idx_start + idx_count - 1) / 2)));
+			DUK_MEMCPY((void *) (re_ctx->saved + idx_start),
+			           (const void *) range_save,
+			           sizeof(duk_uint8_t *) * idx_count);
+			duk_pop((duk_context *) re_ctx->thr);
+			goto fail;
+		}
+		case DUK_REOP_LOOKPOS:
+		case DUK_REOP_LOOKNEG: {
+			/*
+			 *  Needs a save of multiple saved[] entries depending on what range
+			 *  may be overwritten.  Because the regexp parser does no such analysis,
+			 *  we currently save the entire saved array here.  Lookaheads are thus
+			 *  a bit expensive.  Note that the saved array is not needed for just
+			 *  the lookahead sub-match, but for the matching of the entire sequel.
+			 *
+			 *  The temporary save buffer is pushed on to the valstack to handle
+			 *  errors correctly.  Each lookahead causes a C recursion and pushes
+			 *  more stuff on the value stack.  If the C recursion limit is less
+			 *  than the value stack spare, there is no need to check the stack.
+			 *  We do so regardless, just in case.
+			 */
 
-/*
- *  Basic double / byte union memory layout.
- */
+			duk_int32_t skip;
+			duk_uint8_t **full_save;
+			const duk_uint8_t *sub_sp;
 
-static void duk__selftest_double_union_size(void) {
-	if (sizeof(duk__test_double_union) != 8) {
-		DUK_PANIC(DUK_ERR_INTERNAL_ERROR, "self test failed: invalid union size");
-	}
-}
+			DUK_ASSERT(re_ctx->nsaved > 0);
 
-/*
- *  Union aliasing, see misc/clang_aliasing.c.
- */
+			duk_require_stack((duk_context *) re_ctx->thr, 1);
+			full_save = (duk_uint8_t **) duk_push_fixed_buffer((duk_context *) re_ctx->thr,
+			                                                   sizeof(duk_uint8_t *) * re_ctx->nsaved);
+			DUK_ASSERT(full_save != NULL);
+			DUK_MEMCPY(full_save, re_ctx->saved, sizeof(duk_uint8_t *) * re_ctx->nsaved);
 
-static void duk__selftest_double_aliasing(void) {
-	duk__test_double_union a, b;
+			skip = duk__bc_get_i32(re_ctx, &pc);
+			sub_sp = duk__match_regexp(re_ctx, pc, sp);
+			if (op == DUK_REOP_LOOKPOS) {
+				if (!sub_sp) {
+					goto lookahead_fail;
+				}
+			} else {
+				if (sub_sp) {
+					goto lookahead_fail;
+				}
+			}
+			sub_sp = duk__match_regexp(re_ctx, pc + skip, sp);
+			if (sub_sp) {
+				/* match: keep saves */
+				duk_pop((duk_context *) re_ctx->thr);
+				sp = sub_sp;
+				goto match;
+			}
 
-	/* This testcase fails when Emscripten-generated code runs on Firefox.
-	 * It's not an issue because the failure should only affect packed
-	 * duk_tval representation, which is not used with Emscripten.
-	 */
-#if defined(DUK_USE_NO_DOUBLE_ALIASING_SELFTEST)
-#if defined(DUK_USE_PACKED_TVAL)
-#error inconsistent defines: skipping double aliasing selftest when using packed duk_tval
-#endif
-	return;
-#endif
+			/* fall through */
 
-	/* Test signaling NaN and alias assignment in all
-	 * endianness combinations.
-	 */
+		 lookahead_fail:
+			/* fail: restore saves */
+			DUK_MEMCPY((void *) re_ctx->saved,
+			           (const void *) full_save,
+			           sizeof(duk_uint8_t *) * re_ctx->nsaved);
+			duk_pop((duk_context *) re_ctx->thr);
+			goto fail;
+		}
+		case DUK_REOP_BACKREFERENCE: {
+			/*
+			 *  Byte matching for back-references would be OK in case-
+			 *  sensitive matching.  In case-insensitive matching we need
+			 *  to canonicalize characters, so back-reference matching needs
+			 *  to be done with codepoints instead.  So, we just decode
+			 *  everything normally here, too.
+			 *
+			 *  Note: back-reference index which is 0 or higher than
+			 *  NCapturingParens (= number of capturing parens in the
+			 *  -entire- regexp) is a compile time error.  However, a
+			 *  backreference referring to a valid capture which has
+			 *  not matched anything always succeeds!  See E5 Section
+			 *  15.10.2.9, step 5, sub-step 3.
+			 */
+			duk_uint32_t idx;
+			const duk_uint8_t *p;
 
-	/* little endian */
-	a.c[0] = 0x11; a.c[1] = 0x22; a.c[2] = 0x33; a.c[3] = 0x44;
-	a.c[4] = 0x00; a.c[5] = 0x00; a.c[6] = 0xf1; a.c[7] = 0xff;
-	b = a;
-	DUK__DBLUNION_CMP_TRUE(&a, &b);
+			idx = duk__bc_get_u32(re_ctx, &pc);
+			idx = idx << 1;  /* backref n -> saved indices [n*2, n*2+1] */
+			if (idx < 2 || idx + 1 >= re_ctx->nsaved) {
+				/* regexp compiler should catch these */
+				DUK_D(DUK_DPRINT("internal error, backreference index insane"));
+				goto internal_error;
+			}
+			if (!re_ctx->saved[idx] || !re_ctx->saved[idx+1]) {
+				/* capture is 'undefined', always matches! */
+				DUK_DDD(DUK_DDDPRINT("backreference: saved[%ld,%ld] not complete, always match",
+				                     (long) idx, (long) (idx + 1)));
+				break;
+			}
+			DUK_DDD(DUK_DDDPRINT("backreference: match saved[%ld,%ld]", (long) idx, (long) (idx + 1)));
 
-	/* big endian */
-	a.c[0] = 0xff; a.c[1] = 0xf1; a.c[2] = 0x00; a.c[3] = 0x00;
-	a.c[4] = 0x44; a.c[5] = 0x33; a.c[6] = 0x22; a.c[7] = 0x11;
-	b = a;
-	DUK__DBLUNION_CMP_TRUE(&a, &b);
+			p = re_ctx->saved[idx];
+			while (p < re_ctx->saved[idx+1]) {
+				duk_codepoint_t c1, c2;
 
-	/* mixed endian */
-	a.c[0] = 0x00; a.c[1] = 0x00; a.c[2] = 0xf1; a.c[3] = 0xff;
-	a.c[4] = 0x11; a.c[5] = 0x22; a.c[6] = 0x33; a.c[7] = 0x44;
-	b = a;
-	DUK__DBLUNION_CMP_TRUE(&a, &b);
-}
+				/* Note: not necessary to check p against re_ctx->input_end:
+				 * the memory access is checked by duk__inp_get_cp(), while
+				 * valid compiled regexps cannot write a saved[] entry
+				 * which points to outside the string.
+				 */
+				if (sp >= re_ctx->input_end) {
+					goto fail;
+				}
+				c1 = duk__inp_get_cp(re_ctx, &p);
+				c2 = duk__inp_get_cp(re_ctx, &sp);
+				if (c1 != c2) {
+					goto fail;
+				}
+			}
+			break;
+		}
+		default: {
+			DUK_D(DUK_DPRINT("internal error, regexp opcode error: %ld", (long) op));
+			goto internal_error;
+		}
+		}
+	}
 
-/*
- *  Zero sign, see misc/tcc_zerosign2.c.
- */
+ match:
+	re_ctx->recursion_depth--;
+	return sp;
 
-static void duk__selftest_double_zero_sign(void) {
-	volatile duk__test_double_union a, b;
+ fail:
+	re_ctx->recursion_depth--;
+	return NULL;
 
-	a.d = 0.0;
-	b.d = -a.d;
-	DUK__DBLUNION_CMP_FALSE(&a, &b);
+ internal_error:
+	DUK_ERROR(re_ctx->thr, DUK_ERR_INTERNAL_ERROR, DUK_STR_REGEXP_INTERNAL_ERROR);
+	return NULL;  /* never here */
 }
 
 /*
- *  Struct size/alignment if platform requires it
+ *  Exposed matcher function which provides the semantics of RegExp.prototype.exec().
  *
- *  There are some compiler specific struct padding pragmas etc in use, this
- *  selftest ensures they're correctly detected and used.
+ *  RegExp.prototype.test() has the same semantics as exec() but does not return the
+ *  result object (which contains the matching string and capture groups).  Currently
+ *  there is no separate test() helper, so a temporary result object is created and
+ *  discarded if test() is needed.  This is intentional, to save code space.
+ *
+ *  Input stack:  [ ... re_obj input ]
+ *  Output stack: [ ... result ]
  */
 
-static void duk__selftest_struct_align(void) {
-#if defined(DUK_USE_ALIGN_4)
-	if ((sizeof(duk_hbuffer_fixed) % 4) != 0) {
-		DUK_PANIC(DUK_ERR_INTERNAL_ERROR, "self test failed: sizeof(duk_hbuffer_fixed) not aligned to 4");
-	}
-#elif defined(DUK_USE_ALIGN_8)
-	if ((sizeof(duk_hbuffer_fixed) % 8) != 0) {
-		DUK_PANIC(DUK_ERR_INTERNAL_ERROR, "self test failed: sizeof(duk_hbuffer_fixed) not aligned to 8");
-	}
-#else
-	/* no check */
-#endif
-}
+DUK_LOCAL void duk__regexp_match_helper(duk_hthread *thr, duk_small_int_t force_global) {
+	duk_context *ctx = (duk_context *) thr;
+	duk_re_matcher_ctx re_ctx;
+	duk_hobject *h_regexp;
+	duk_hstring *h_bytecode;
+	duk_hstring *h_input;
+	const duk_uint8_t *pc;
+	const duk_uint8_t *sp;
+	duk_small_int_t match = 0;
+	duk_small_int_t global;
+	duk_uint_fast32_t i;
+	double d;
+	duk_uint32_t char_offset;
 
-/*
- *  Self test main
- */
+	DUK_ASSERT(thr != NULL);
+	DUK_ASSERT(ctx != NULL);
 
-void duk_selftest_run_tests(void) {
-	duk__selftest_types();
-	duk__selftest_packed_tval();
-	duk__selftest_twos_complement();
-	duk__selftest_byte_order();
-	duk__selftest_double_union_size();
-	duk__selftest_double_aliasing();
-	duk__selftest_double_zero_sign();
-	duk__selftest_struct_align();
-}
+	DUK_DD(DUK_DDPRINT("regexp match: regexp=%!T, input=%!T",
+	                   (duk_tval *) duk_get_tval(ctx, -2),
+	                   (duk_tval *) duk_get_tval(ctx, -1)));
 
-#undef DUK__DBLUNION_CMP_TRUE
-#undef DUK__DBLUNION_CMP_FALSE
+	/*
+	 *  Regexp instance check, bytecode check, input coercion.
+	 *
+	 *  See E5 Section 15.10.6.
+	 */
 
-#endif  /* DUK_USE_SELF_TESTS */
-#line 1 "duk_strings.c"
-/*
- *  Shared error message strings
- *
- *  To minimize code footprint, try to share error messages inside Duktape
- *  code.
- */
+	/* TypeError if wrong; class check, see E5 Section 15.10.6 */
+	h_regexp = duk_require_hobject_with_class(ctx, -2, DUK_HOBJECT_CLASS_REGEXP);
+	DUK_ASSERT(h_regexp != NULL);
+	DUK_ASSERT(DUK_HOBJECT_GET_CLASS_NUMBER(h_regexp) == DUK_HOBJECT_CLASS_REGEXP);
+	DUK_UNREF(h_regexp);
 
-/* include removed: duk_internal.h */
+	duk_to_string(ctx, -1);
+	h_input = duk_get_hstring(ctx, -1);
+	DUK_ASSERT(h_input != NULL);
 
-/* Mostly API related */
-const char *duk_str_internal_error = "internal error";
-const char *duk_str_invalid_count = "invalid count";
-const char *duk_str_invalid_call_args = "invalid call args";
-const char *duk_str_not_constructable = "not constructable";
-const char *duk_str_not_callable = "not callable";
-const char *duk_str_not_extensible = "not extensible";
-const char *duk_str_not_writable = "not writable";
-const char *duk_str_not_configurable = "not configurable";
-
-const char *duk_str_invalid_index = "invalid index";
-const char *duk_str_push_beyond_alloc_stack = "attempt to push beyond currently allocated stack";
-const char *duk_str_src_stack_not_enough = "source stack does not contain enough elements";
-const char *duk_str_not_undefined = "not undefined";
-const char *duk_str_not_null = "not null";
-const char *duk_str_not_boolean = "not boolean";
-const char *duk_str_not_number = "not number";
-const char *duk_str_not_string = "not string";
-const char *duk_str_not_pointer = "not pointer";
-const char *duk_str_not_buffer = "not buffer";
-const char *duk_str_not_object = "not object";
-const char *duk_str_unexpected_type = "unexpected type";
-const char *duk_str_not_thread = "not thread";
-const char *duk_str_not_compiledfunction = "not compiledfunction";
-const char *duk_str_not_nativefunction = "not nativefunction";
-const char *duk_str_not_c_function = "not c function";
-const char *duk_str_defaultvalue_coerce_failed = "[[DefaultValue]] coerce failed";
-const char *duk_str_number_outside_range = "number outside range";
-const char *duk_str_not_object_coercible = "not object coercible";
-const char *duk_str_string_too_long = "string too long";
-const char *duk_str_buffer_too_long = "buffer too long";
-const char *duk_str_sprintf_too_long = "sprintf message too long";
-const char *duk_str_object_alloc_failed = "object alloc failed";
-const char *duk_str_thread_alloc_failed = "thread alloc failed";
-const char *duk_str_func_alloc_failed = "func alloc failed";
-const char *duk_str_buffer_alloc_failed = "buffer alloc failed";
-const char *duk_str_pop_too_many = "attempt to pop too many entries";
+	duk_get_prop_stridx(ctx, -2, DUK_STRIDX_INT_BYTECODE);  /* [ ... re_obj input ] -> [ ... re_obj input bc ] */
+	h_bytecode = duk_require_hstring(ctx, -1);  /* no regexp instance should exist without a non-configurable bytecode property */
+	DUK_ASSERT(h_bytecode != NULL);
 
-/* JSON */
-const char *duk_str_fmt_ptr = "%p";
-const char *duk_str_invalid_json = "invalid json";
-const char *duk_str_invalid_number = "invalid number";
-const char *duk_str_jsondec_reclimit = "json decode recursion limit";
-const char *duk_str_jsonenc_reclimit = "json encode recursion limit";
-const char *duk_str_cyclic_input = "cyclic input";
+	/*
+	 *  Basic context initialization.
+	 *
+	 *  Some init values are read from the bytecode header
+	 *  whose format is (UTF-8 codepoints):
+	 *
+	 *    uint   flags
+	 *    uint   nsaved (even, 2n+2 where n = num captures)
+	 */
 
-/* Object property access */
-const char *duk_str_proxy_revoked = "proxy revoked";
-const char *duk_str_object_resize_failed = "object resize failed";
-const char *duk_str_invalid_base = "invalid base value";
-const char *duk_str_strict_caller_read = "attempt to read strict 'caller'";
-const char *duk_str_proxy_rejected = "proxy rejected";
-const char *duk_str_invalid_array_length = "invalid array length";
-const char *duk_str_array_length_write_failed = "array length write failed";
-const char *duk_str_array_length_not_writable = "array length non-writable";
-const char *duk_str_setter_undefined = "setter undefined";
-const char *duk_str_redefine_virt_prop = "attempt to redefine virtual property";
-const char *duk_str_invalid_descriptor = "invalid descriptor";
-const char *duk_str_property_is_virtual = "property is virtual";
+	/* [ ... re_obj input bc ] */
 
-/* Compiler */
-const char *duk_str_parse_error = "parse error";
-const char *duk_str_duplicate_label = "duplicate label";
-const char *duk_str_invalid_label = "invalid label";
-const char *duk_str_invalid_array_literal = "invalid array literal";
-const char *duk_str_invalid_object_literal = "invalid object literal";
-const char *duk_str_invalid_var_declaration = "invalid variable declaration";
-const char *duk_str_cannot_delete_identifier = "cannot delete identifier";
-const char *duk_str_invalid_expression = "invalid expression";
-const char *duk_str_invalid_lvalue = "invalid lvalue";
-const char *duk_str_expected_identifier = "expected identifier";
-const char *duk_str_empty_expr_not_allowed = "empty expression not allowed";
-const char *duk_str_invalid_for = "invalid for statement";
-const char *duk_str_invalid_switch = "invalid switch statement";
-const char *duk_str_invalid_break_cont_label = "invalid break/continue label";
-const char *duk_str_invalid_return = "invalid return";
-const char *duk_str_invalid_try = "invalid try";
-const char *duk_str_with_in_strict_mode = "with in strict mode";
-const char *duk_str_func_stmt_not_allowed = "function statement not allowed";
-const char *duk_str_unterminated_stmt = "unterminated statement";
-const char *duk_str_invalid_arg_name = "invalid argument name";
-const char *duk_str_invalid_func_name = "invalid function name";
-const char *duk_str_invalid_getset_name = "invalid getter/setter name";
-const char *duk_str_func_name_required = "function name required";
+	DUK_MEMZERO(&re_ctx, sizeof(re_ctx));
 
-/* Executor */
-const char *duk_str_internal_error_exec_longjmp = "internal error in bytecode executor longjmp handler";
+	re_ctx.thr = thr;
+	re_ctx.input = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_input);
+	re_ctx.input_end = re_ctx.input + DUK_HSTRING_GET_BYTELEN(h_input);
+	re_ctx.bytecode = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_bytecode);
+	re_ctx.bytecode_end = re_ctx.bytecode + DUK_HSTRING_GET_BYTELEN(h_bytecode);
+	re_ctx.saved = NULL;
+	re_ctx.recursion_limit = DUK_USE_REGEXP_EXECUTOR_RECLIMIT;
+	re_ctx.steps_limit = DUK_RE_EXECUTE_STEPS_LIMIT;
 
-/* Limits */
-const char *duk_str_valstack_limit = "valstack limit";
-const char *duk_str_object_property_limit = "object property limit";
-const char *duk_str_prototype_chain_limit = "prototype chain limit";
-const char *duk_str_bound_chain_limit = "function call bound chain limit";
-const char *duk_str_c_callstack_limit = "C call stack depth limit";
-const char *duk_str_compiler_recursion_limit = "compiler recursion limit";
-const char *duk_str_bytecode_limit = "bytecode limit";
-const char *duk_str_reg_limit = "register limit";
-const char *duk_str_temp_limit = "temp limit";
-const char *duk_str_const_limit = "const limit";
-const char *duk_str_func_limit = "function limit";
-#line 1 "duk_unicode_support.c"
-/*
- *  Various Unicode help functions for character classification predicates,
- *  case conversion, decoding, etc.
- */
+	/* read header */
+	pc = re_ctx.bytecode;
+	re_ctx.re_flags = duk__bc_get_u32(&re_ctx, &pc);
+	re_ctx.nsaved = duk__bc_get_u32(&re_ctx, &pc);
+	re_ctx.bytecode = pc;
 
-/* include removed: duk_internal.h */
+	DUK_ASSERT(DUK_RE_FLAG_GLOBAL < 0x10000UL);  /* must fit into duk_small_int_t */
+	global = (duk_small_int_t) (force_global | (re_ctx.re_flags & DUK_RE_FLAG_GLOBAL));
 
-/*
- *  XUTF-8 and CESU-8 encoding/decoding
- */
+	DUK_ASSERT(re_ctx.nsaved >= 2);
+	DUK_ASSERT((re_ctx.nsaved % 2) == 0);
 
-duk_small_int_t duk_unicode_get_xutf8_length(duk_ucodepoint_t cp) {
-	duk_uint_fast32_t x = (duk_uint_fast32_t) cp;
-	if (x < 0x80UL) {
-		/* 7 bits */
-		return 1;
-	} else if (x < 0x800UL) {
-		/* 11 bits */
-		return 2;
-	} else if (x < 0x10000UL) {
-		/* 16 bits */
-		return 3;
-	} else if (x < 0x200000UL) {
-		/* 21 bits */
-		return 4;
-	} else if (x < 0x4000000UL) {
-		/* 26 bits */
-		return 5;
-	} else if (x < (duk_ucodepoint_t) 0x80000000UL) {
-		/* 31 bits */
-		return 6;
-	} else {
-		/* 36 bits */
-		return 7;
-	}
-}
+	duk_push_fixed_buffer(ctx, sizeof(duk_uint8_t *) * re_ctx.nsaved);
+	re_ctx.saved = (const duk_uint8_t **) duk_get_buffer(ctx, -1, NULL);
+	DUK_ASSERT(re_ctx.saved != NULL);
 
-duk_uint8_t duk_unicode_xutf8_markers[7] = {
-	0x00, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe
-};
+	/* [ ... re_obj input bc saved_buf ] */
 
-/* Encode to extended UTF-8; 'out' must have space for at least
- * DUK_UNICODE_MAX_XUTF8_LENGTH bytes.  Allows encoding of any
- * 32-bit (unsigned) codepoint.
- */
-duk_small_int_t duk_unicode_encode_xutf8(duk_ucodepoint_t cp, duk_uint8_t *out) {
-	duk_uint_fast32_t x = (duk_uint_fast32_t) cp;
-	duk_small_int_t len;
-	duk_uint8_t marker;
-	duk_small_int_t i;
+	/* buffer is automatically zeroed */
+#ifdef DUK_USE_EXPLICIT_NULL_INIT
+	for (i = 0; i < re_ctx.nsaved; i++) {
+		re_ctx.saved[i] = (duk_uint8_t *) NULL;
+	}
+#endif
 
-	len = duk_unicode_get_xutf8_length(cp);
-	DUK_ASSERT(len > 0);
+	DUK_DDD(DUK_DDDPRINT("regexp ctx initialized, flags=0x%08lx, nsaved=%ld, recursion_limit=%ld, steps_limit=%ld",
+	                     (unsigned long) re_ctx.re_flags, (long) re_ctx.nsaved, (long) re_ctx.recursion_limit,
+	                     (long) re_ctx.steps_limit));
 
-	marker = duk_unicode_xutf8_markers[len - 1];  /* 64-bit OK because always >= 0 */
+	/*
+	 *  Get starting character offset for match, and initialize 'sp' based on it.
+	 *
+	 *  Note: lastIndex is non-configurable so it must be present (we check the
+	 *  internal class of the object above, so we know it is).  User code can set
+	 *  its value to an arbitrary (garbage) value though; E5 requires that lastIndex
+	 *  be coerced to a number before using.  The code below works even if the
+	 *  property is missing: the value will then be coerced to zero.
+	 *
+	 *  Note: lastIndex may be outside Uint32 range even after ToInteger() coercion.
+	 *  For instance, ToInteger(+Infinity) = +Infinity.  We track the match offset
+	 *  as an integer, but pre-check it to be inside the 32-bit range before the loop.
+	 *  If not, the check in E5 Section 15.10.6.2, step 9.a applies.
+	 */
 
-	i = len;
-	DUK_ASSERT(i > 0);
-	do {
-		i--;
-		if (i > 0) {
-			out[i] = (duk_uint8_t) (0x80 + (x & 0x3f));
-			x >>= 6;
-		} else {
-			/* Note: masking of 'x' is not necessary because of
-			 * range check and shifting -> no bits overlapping
-			 * the marker should be set.
-			 */
-			out[0] = (duk_uint8_t) (marker + x);
-		}
-	} while (i > 0);
+	/* XXX: lastIndex handling produces a lot of asm */
 
-	return len;
-}
+	/* [ ... re_obj input bc saved_buf ] */
 
-/* Encode to CESU-8; 'out' must have space for at least
- * DUK_UNICODE_MAX_CESU8_LENGTH bytes; codepoints above U+10FFFF
- * will encode to garbage but won't overwrite the output buffer.
- */
-duk_small_int_t duk_unicode_encode_cesu8(duk_ucodepoint_t cp, duk_uint8_t *out) {
-	duk_uint_fast32_t x = (duk_uint_fast32_t) cp;
-	duk_small_int_t len;
+	duk_get_prop_stridx(ctx, -4, DUK_STRIDX_LAST_INDEX);  /* -> [ ... re_obj input bc saved_buf lastIndex ] */
+	(void) duk_to_int(ctx, -1);  /* ToInteger(lastIndex) */
+	d = duk_get_number(ctx, -1);  /* integer, but may be +/- Infinite, +/- zero (not NaN, though) */
+	duk_pop(ctx);
 
-	if (x < 0x80UL) {
-		out[0] = (duk_uint8_t) x;
-		len = 1;
-	} else if (x < 0x800UL) {
-		out[0] = (duk_uint8_t) (0xc0 + ((x >> 6) & 0x1f));
-		out[1] = (duk_uint8_t) (0x80 + (x & 0x3f));
-		len = 2;
-	} else if (x < 0x10000UL) {
-		/* surrogate pairs get encoded here */
-		out[0] = (duk_uint8_t) (0xe0 + ((x >> 12) & 0x0f));
-		out[1] = (duk_uint8_t) (0x80 + ((x >> 6) & 0x3f));
-		out[2] = (duk_uint8_t) (0x80 + (x & 0x3f));
-		len = 3;
+	if (global) {
+		if (d < 0.0 || d > (double) DUK_HSTRING_GET_CHARLEN(h_input)) {
+			/* match fail */
+			char_offset = 0;   /* not really necessary */
+			DUK_ASSERT(match == 0);
+			goto match_over;
+		}
+		char_offset = (duk_uint32_t) d;
 	} else {
-		/*
-		 *  Unicode codepoints above U+FFFF are encoded as surrogate
-		 *  pairs here.  This ensures that all CESU-8 codepoints are
-		 *  16-bit values as expected in Ecmascript.  The surrogate
-		 *  pairs always get a 3-byte encoding (each) in CESU-8.
-		 *  See: http://en.wikipedia.org/wiki/Surrogate_pair
-		 *
-		 *  20-bit codepoint, 10 bits (A and B) per surrogate pair:
-		 * 
-		 *    x = 0b00000000 0000AAAA AAAAAABB BBBBBBBB
-		 *  sp1 = 0b110110AA AAAAAAAA  (0xd800 + ((x >> 10) & 0x3ff))
-		 *  sp2 = 0b110111BB BBBBBBBB  (0xdc00 + (x & 0x3ff))
-		 *
-		 *  Encoded into CESU-8:
-		 *
-		 *  sp1 -> 0b11101101  (0xe0 + ((sp1 >> 12) & 0x0f))
-		 *      -> 0b1010AAAA  (0x80 + ((sp1 >> 6) & 0x3f))
-		 *      -> 0b10AAAAAA  (0x80 + (sp1 & 0x3f))
-		 *  sp2 -> 0b11101101  (0xe0 + ((sp2 >> 12) & 0x0f))
-		 *      -> 0b1011BBBB  (0x80 + ((sp2 >> 6) & 0x3f))
-		 *      -> 0b10BBBBBB  (0x80 + (sp2 & 0x3f))
-		 *
-		 *  Note that 0x10000 must be subtracted first.  The code below
-		 *  avoids the sp1, sp2 temporaries which saves around 20 bytes
-		 *  of code.
+		/* lastIndex must be ignored for non-global regexps, but get the
+		 * value for (theoretical) side effects.  No side effects can
+		 * really occur, because lastIndex is a normal property and is
+		 * always non-configurable for RegExp instances.
 		 */
+		char_offset = (duk_uint32_t) 0;
+	}
 
-		x -= 0x10000UL;
+	sp = re_ctx.input + duk_heap_strcache_offset_char2byte(thr, h_input, char_offset);
 
-		out[0] = (duk_uint8_t) (0xed);
-		out[1] = (duk_uint8_t) (0xa0 + ((x >> 16) & 0x0f));
-		out[2] = (duk_uint8_t) (0x80 + ((x >> 10) & 0x3f));
-		out[3] = (duk_uint8_t) (0xed);
-		out[4] = (duk_uint8_t) (0xb0 + ((x >> 6) & 0x0f));
-		out[5] = (duk_uint8_t) (0x80 + (x & 0x3f));
-		len = 6;
-	}
+	/*
+	 *  Match loop.
+	 *
+	 *  Try matching at different offsets until match found or input exhausted.
+	 */
 
-	return len;
-}
+	/* [ ... re_obj input bc saved_buf ] */
 
-/* Decode helper.  Return zero on error. */
-duk_small_int_t duk_unicode_decode_xutf8(duk_hthread *thr, duk_uint8_t **ptr, duk_uint8_t *ptr_start, duk_uint8_t *ptr_end, duk_ucodepoint_t *out_cp) {
-	duk_uint8_t *p;
-	duk_uint32_t res;
-	duk_uint_fast8_t ch;
-	duk_small_int_t n;
+	DUK_ASSERT(match == 0);
 
-	DUK_UNREF(thr);
+	for (;;) {
+		/* char offset in [0, h_input->clen] (both ends inclusive), checked before entry */
+		DUK_ASSERT_DISABLE(char_offset >= 0);
+		DUK_ASSERT(char_offset <= DUK_HSTRING_GET_CHARLEN(h_input));
 
-	p = *ptr;
-	if (p < ptr_start || p >= ptr_end) {
-		goto fail;
-	}
+		/* Note: ctx.steps is intentionally not reset, it applies to the entire unanchored match */
+		DUK_ASSERT(re_ctx.recursion_depth == 0);
 
-	/*
-	 *  UTF-8 decoder which accepts longer than standard byte sequences.
-	 *  This allows full 32-bit code points to be used.
-	 */
+		DUK_DDD(DUK_DDDPRINT("attempt match at char offset %ld; %p [%p,%p]",
+		                     (long) char_offset, (const void *) sp,
+		                     (const void *) re_ctx.input, (const void *) re_ctx.input_end));
 
-	ch = (duk_uint_fast8_t) (*p++);
-	if (ch < 0x80) {
-		/* 0xxx xxxx   [7 bits] */
-		res = (duk_uint32_t) (ch & 0x7f);
-		n = 0;
-	} else if (ch < 0xc0) {
-		/* 10xx xxxx -> invalid */
-		goto fail;
-	} else if (ch < 0xe0) {
-		/* 110x xxxx   10xx xxxx   [11 bits] */
-		res = (duk_uint32_t) (ch & 0x1f);
-		n = 1;
-	} else if (ch < 0xf0) {
-		/* 1110 xxxx   10xx xxxx   10xx xxxx   [16 bits] */
-		res = (duk_uint32_t) (ch & 0x0f);
-		n = 2;
-	} else if (ch < 0xf8) {
-		/* 1111 0xxx   10xx xxxx   10xx xxxx   10xx xxxx   [21 bits] */
-		res = (duk_uint32_t) (ch & 0x07);
-		n = 3;
-	} else if (ch < 0xfc) {
-		/* 1111 10xx   10xx xxxx   10xx xxxx   10xx xxxx   10xx xxxx   [26 bits] */
-		res = (duk_uint32_t) (ch & 0x03);
-		n = 4;
-	} else if (ch < 0xfe) {
-		/* 1111 110x   10xx xxxx   10xx xxxx   10xx xxxx   10xx xxxx   10xx xxxx   [31 bits] */
-		res = (duk_uint32_t) (ch & 0x01);
-		n = 5;
-	} else if (ch < 0xff) {
-		/* 1111 1110   10xx xxxx   10xx xxxx   10xx xxxx   10xx xxxx   10xx xxxx   10xx xxxx   [36 bits] */
-		res = (duk_uint32_t) (0);
-		n = 6;
-	} else {
-		/* 8-byte format could be:
-		 * 1111 1111   10xx xxxx   10xx xxxx   10xx xxxx   10xx xxxx   10xx xxxx   10xx xxxx   10xx xxxx   [41 bits]
+		/*
+		 *  Note:
 		 *
-		 * However, this format would not have a zero bit following the
-		 * leading one bits and would not allow 0xFF to be used as an
-		 * "invalid xutf-8" marker for internal keys.  Further, 8-byte
-		 * encodings (up to 41 bit code points) are not currently needed.
+		 *    - duk__match_regexp() is required not to longjmp() in ordinary "non-match"
+		 *      conditions; a longjmp() will terminate the entire matching process.
+		 *
+		 *    - Clearing saved[] is not necessary because backtracking does it
+		 *
+		 *    - Backtracking also rewinds ctx.recursion back to zero, unless an
+		 *      internal/limit error occurs (which causes a longjmp())
+		 *
+		 *    - If we supported anchored matches, we would break out here
+		 *      unconditionally; however, Ecmascript regexps don't have anchored
+		 *      matches.  It might make sense to implement a fast bail-out if
+		 *      the regexp begins with '^' and sp is not 0: currently we'll just
+		 *      run through the entire input string, trivially failing the match
+		 *      at every non-zero offset.
 		 */
-		goto fail;
-	}
 
-	DUK_ASSERT(p >= ptr_start);  /* verified at beginning */
-	if (p + n > ptr_end) {
-		/* check pointer at end */
-		goto fail;
-	}
+		if (duk__match_regexp(&re_ctx, re_ctx.bytecode, sp) != NULL) {
+			DUK_DDD(DUK_DDDPRINT("match at offset %ld", (long) char_offset));
+			match = 1;
+			break;
+		}
 
-	while (n > 0) {
-		DUK_ASSERT(p >= ptr_start && p < ptr_end);
-		res = res << 6;
-		res += (duk_uint32_t) ((*p++) & 0x3f);
-		n--;
+		/* advance by one character (code point) and one char_offset */
+		char_offset++;
+		if (char_offset > DUK_HSTRING_GET_CHARLEN(h_input)) {
+			/*
+			 *  Note:
+			 *
+			 *    - Intentionally attempt (empty) match at char_offset == k_input->clen
+			 *
+			 *    - Negative char_offsets have been eliminated and char_offset is duk_uint32_t
+			 *      -> no need or use for a negative check
+			 */
+
+			DUK_DDD(DUK_DDDPRINT("no match after trying all sp offsets"));
+			break;
+		}
+
+		/* avoid calling at end of input, will DUK_ERROR (above check suffices to avoid this) */
+		(void) duk__utf8_advance(thr, &sp, re_ctx.input, re_ctx.input_end, (duk_uint_fast32_t) 1);
 	}
 
-	*ptr = p;
-	*out_cp = res;
-	return 1;
+ match_over:
 
- fail:
-	return 0;
-}
+	/*
+	 *  Matching complete, create result array or return a 'null'.  Update lastIndex
+	 *  if necessary.  See E5 Section 15.10.6.2.
+	 *
+	 *  Because lastIndex is a character (not byte) offset, we need the character
+	 *  length of the match which we conveniently get as a side effect of interning
+	 *  the matching substring (0th index of result array).
+	 *
+	 *  saved[0]         start pointer (~ byte offset) of current match
+	 *  saved[1]         end pointer (~ byte offset) of current match (exclusive)
+	 *  char_offset      start character offset of current match (-> .index of result)
+	 *  char_end_offset  end character offset (computed below)
+	 */
 
-/* used by e.g. duk_regexp_executor.c, string built-ins */
-duk_ucodepoint_t duk_unicode_decode_xutf8_checked(duk_hthread *thr, duk_uint8_t **ptr, duk_uint8_t *ptr_start, duk_uint8_t *ptr_end) {
-	duk_ucodepoint_t cp;
+	/* [ ... re_obj input bc saved_buf ] */
 
-	if (duk_unicode_decode_xutf8(thr, ptr, ptr_start, ptr_end, &cp)) {
-		return cp;
-	}
-	DUK_ERROR(thr, DUK_ERR_INTERNAL_ERROR, "utf-8 decode failed");
-	DUK_UNREACHABLE();
-	return 0;
-}
+	if (match) {
+#ifdef DUK_USE_ASSERTIONS
+		duk_hobject *h_res;
+#endif
+		duk_uint32_t char_end_offset = 0;
 
-/* (extended) utf-8 length without codepoint encoding validation, used
- * for string interning (should probably be inlined).
- */
-duk_size_t duk_unicode_unvalidated_utf8_length(duk_uint8_t *data, duk_size_t blen) {
-	duk_uint8_t *p = data;
-	duk_uint8_t *p_end = data + blen;
-	duk_size_t clen = 0;
+		DUK_DDD(DUK_DDDPRINT("regexp matches at char_offset %ld", (long) char_offset));
 
-	while (p < p_end) {
-		duk_uint8_t x = *p++;
-		if (x < 0x80 || x >= 0xc0) {
-			/* 10xxxxxx = continuation chars (0x80...0xbf), above
-			 * and below that initial bytes.
-			 */
-			clen++;
-		}
-	}
+		DUK_ASSERT(re_ctx.nsaved >= 2);        /* must have start and end */
+		DUK_ASSERT((re_ctx.nsaved % 2) == 0);  /* and even number */
 
-	return clen;
-}
+		/* XXX: Array size is known before and (2 * re_ctx.nsaved) but not taken
+		 * advantage of now.  The array is not compacted either, as regexp match
+		 * objects are usually short lived.
+		 */
 
-/*
- *  Unicode range matcher
- *
- *  Matches a codepoint against a packed bitstream of character ranges.
- *  Used for slow path Unicode matching.
- */
+		duk_push_array(ctx);
 
-/* Must match src/extract_chars.py, generate_match_table3(). */
-static duk_uint32_t duk__uni_decode_value(duk_bitdecoder_ctx *bd_ctx) {
-	duk_uint32_t t;
+#ifdef DUK_USE_ASSERTIONS
+		h_res = duk_require_hobject(ctx, -1);
+		DUK_ASSERT(DUK_HOBJECT_HAS_EXTENSIBLE(h_res));
+		DUK_ASSERT(DUK_HOBJECT_HAS_EXOTIC_ARRAY(h_res));
+		DUK_ASSERT(DUK_HOBJECT_GET_CLASS_NUMBER(h_res) == DUK_HOBJECT_CLASS_ARRAY);
+#endif
 
-	t = (duk_uint32_t) duk_bd_decode(bd_ctx, 4);
-	if (t <= 0x0eU) {
-		return t;
-	}
-	t = (duk_uint32_t) duk_bd_decode(bd_ctx, 8);
-	if (t <= 0xfdU) {
-		return t + 0x0f;
-	}
-	if (t == 0xfeU) {
-		t = (duk_uint32_t) duk_bd_decode(bd_ctx, 12);
-		return t + 0x0fU + 0xfeU;
-	} else {
-		t = (duk_uint32_t) duk_bd_decode(bd_ctx, 24);
-		return t + 0x0fU + 0xfeU + 0x1000UL;
-	}
-}
+		/* [ ... re_obj input bc saved_buf res_obj ] */
 
-static duk_small_int_t duk__uni_range_match(const duk_uint8_t *unitab, duk_size_t unilen, duk_codepoint_t cp) {
-	duk_bitdecoder_ctx bd_ctx;
-	duk_codepoint_t prev_re;
+		duk_push_u32(ctx, char_offset);
+		duk_xdef_prop_stridx_wec(ctx, -2, DUK_STRIDX_INDEX);
 
-	DUK_MEMZERO(&bd_ctx, sizeof(bd_ctx));
-	bd_ctx.data = (duk_uint8_t *) unitab;
-	bd_ctx.length = (duk_size_t) unilen;
+		duk_dup(ctx, -4);
+		duk_xdef_prop_stridx_wec(ctx, -2, DUK_STRIDX_INPUT);
 
-	prev_re = 0;
-	for (;;) {
-		duk_codepoint_t r1, r2;
-		r1 = (duk_codepoint_t) duk__uni_decode_value(&bd_ctx);
-		if (r1 == 0) {
-			break;
-		}
-		r2 = (duk_codepoint_t) duk__uni_decode_value(&bd_ctx);
+		for (i = 0; i < re_ctx.nsaved; i += 2) {
+			/* Captures which are undefined have NULL pointers and are returned
+			 * as 'undefined'.  The same is done when saved[] pointers are insane
+			 * (this should, of course, never happen in practice).
+			 */
+			if (re_ctx.saved[i] && re_ctx.saved[i+1] && re_ctx.saved[i+1] >= re_ctx.saved[i]) {
+				duk_hstring *h_saved;
 
-		r1 = prev_re + r1;
-		r2 = r1 + r2;
-		prev_re = r2;
+				duk_push_lstring(ctx,
+				                 (const char *) re_ctx.saved[i],
+				                 (duk_size_t) (re_ctx.saved[i+1] - re_ctx.saved[i]));
+				h_saved = duk_get_hstring(ctx, -1);
+				DUK_ASSERT(h_saved != NULL);
 
-		/* [r1,r2] is the range */
+				if (i == 0) {
+					/* Assumes that saved[0] and saved[1] are always
+					 * set by regexp bytecode (if not, char_end_offset
+					 * will be zero).  Also assumes clen reflects the
+					 * correct char length.
+					 */
+					char_end_offset = char_offset + DUK_HSTRING_GET_CHARLEN(h_saved);
+				}
+			} else {
+				duk_push_undefined(ctx);
+			}
 
-		DUK_DDD(DUK_DDDPRINT("duk__uni_range_match: cp=%06lx range=[0x%06lx,0x%06lx]",
-		                     (unsigned long) cp, (unsigned long) r1, (unsigned long) r2));
-		if (cp >= r1 && cp <= r2) {
-			return 1;
+			/* [ ... re_obj input bc saved_buf res_obj val ] */
+			duk_put_prop_index(ctx, -2, i / 2);
 		}
-	}
 
-	return 0;
-}
+		/* [ ... re_obj input bc saved_buf res_obj ] */
 
-/*
- *  "WhiteSpace" production check.
- */
+		/* NB: 'length' property is automatically updated by the array setup loop */
 
-duk_small_int_t duk_unicode_is_whitespace(duk_codepoint_t cp) {
-	/*
-	 *  E5 Section 7.2 specifies six characters specifically as
-	 *  white space:
-	 *
-	 *    0009;<control>;Cc;0;S;;;;;N;CHARACTER TABULATION;;;;
-	 *    000B;<control>;Cc;0;S;;;;;N;LINE TABULATION;;;;
-	 *    000C;<control>;Cc;0;WS;;;;;N;FORM FEED (FF);;;;
-	 *    0020;SPACE;Zs;0;WS;;;;;N;;;;;
-	 *    00A0;NO-BREAK SPACE;Zs;0;CS;<noBreak> 0020;;;;N;NON-BREAKING SPACE;;;;
-	 *    FEFF;ZERO WIDTH NO-BREAK SPACE;Cf;0;BN;;;;;N;BYTE ORDER MARK;;;;
-	 *
-	 *  It also specifies any Unicode category 'Zs' characters as white
-	 *  space.  These can be extracted with the "src/extract_chars.py" script.
-	 *  Current result:
-	 *  
-	 *    RAW OUTPUT:
-	 *    ===========
-	 *    0020;SPACE;Zs;0;WS;;;;;N;;;;;
-	 *    00A0;NO-BREAK SPACE;Zs;0;CS;<noBreak> 0020;;;;N;NON-BREAKING SPACE;;;;
-	 *    1680;OGHAM SPACE MARK;Zs;0;WS;;;;;N;;;;;
-	 *    180E;MONGOLIAN VOWEL SEPARATOR;Zs;0;WS;;;;;N;;;;;
-	 *    2000;EN QUAD;Zs;0;WS;2002;;;;N;;;;;
-	 *    2001;EM QUAD;Zs;0;WS;2003;;;;N;;;;;
-	 *    2002;EN SPACE;Zs;0;WS;<compat> 0020;;;;N;;;;;
-	 *    2003;EM SPACE;Zs;0;WS;<compat> 0020;;;;N;;;;;
-	 *    2004;THREE-PER-EM SPACE;Zs;0;WS;<compat> 0020;;;;N;;;;;
-	 *    2005;FOUR-PER-EM SPACE;Zs;0;WS;<compat> 0020;;;;N;;;;;
-	 *    2006;SIX-PER-EM SPACE;Zs;0;WS;<compat> 0020;;;;N;;;;;
-	 *    2007;FIGURE SPACE;Zs;0;WS;<noBreak> 0020;;;;N;;;;;
-	 *    2008;PUNCTUATION SPACE;Zs;0;WS;<compat> 0020;;;;N;;;;;
-	 *    2009;THIN SPACE;Zs;0;WS;<compat> 0020;;;;N;;;;;
-	 *    200A;HAIR SPACE;Zs;0;WS;<compat> 0020;;;;N;;;;;
-	 *    202F;NARROW NO-BREAK SPACE;Zs;0;CS;<noBreak> 0020;;;;N;;;;;
-	 *    205F;MEDIUM MATHEMATICAL SPACE;Zs;0;WS;<compat> 0020;;;;N;;;;;
-	 *    3000;IDEOGRAPHIC SPACE;Zs;0;WS;<wide> 0020;;;;N;;;;;
-	 *  
-	 *    RANGES:
-	 *    =======
-	 *    0x0020
-	 *    0x00a0
-	 *    0x1680
-	 *    0x180e
-	 *    0x2000 ... 0x200a
-	 *    0x202f
-	 *    0x205f
-	 *    0x3000
-	 *
-	 *  A manual decoder (below) is probably most compact for this.
-	 */
+		if (global) {
+			/* global regexp: lastIndex updated on match */
+			duk_push_u32(ctx, char_end_offset);
+			duk_put_prop_stridx(ctx, -6, DUK_STRIDX_LAST_INDEX);
+		} else {
+			/* non-global regexp: lastIndex never updated on match */
+			;
+		}
+	} else {
+		/*
+		 *  No match, E5 Section 15.10.6.2, step 9.a.i - 9.a.ii apply, regardless
+		 *  of 'global' flag of the RegExp.  In particular, if lastIndex is invalid
+		 *  initially, it is reset to zero.
+		 */
 
-	duk_uint_fast8_t lo;
-	duk_uint_fast32_t hi;
+		DUK_DDD(DUK_DDDPRINT("regexp does not match"));
 
-	/* cp == -1 (EOF) never matches and causes return value 0 */
+		duk_push_null(ctx);
 
-	lo = (duk_uint_fast8_t) (cp & 0xff);
-	hi = (duk_uint_fast32_t) (cp >> 8);  /* does not fit into an uchar */
+		/* [ ... re_obj input bc saved_buf res_obj ] */
 
-	if (hi == 0x0000UL) {
-		if (lo == 0x09U || lo == 0x0bU || lo == 0x0cU ||
-		    lo == 0x20U || lo == 0xa0U) {
-			return 1;
-		}
-	} else if (hi == 0x0020UL) {
-		if (lo <= 0x0aU || lo == 0x2fU || lo == 0x5fU) {
-			return 1;
-		}
-	} else if (cp == 0x1680L || cp == 0x180eL || cp == 0x3000L ||
-	           cp == 0xfeffL) {
-		return 1;
+		duk_push_int(ctx, 0);
+		duk_put_prop_stridx(ctx, -6, DUK_STRIDX_LAST_INDEX);
 	}
 
-	return 0;
-}
+	/* [ ... re_obj input bc saved_buf res_obj ] */
 
-/*
- *  "LineTerminator" production check.
- */
+	duk_insert(ctx, -5);
 
-duk_small_int_t duk_unicode_is_line_terminator(duk_codepoint_t cp) {
-	/*
-	 *  E5 Section 7.3
-	 *
-	 *  A LineTerminatorSequence essentially merges <CR> <LF> sequences
-	 *  into a single line terminator.  This must be handled by the caller.
+	/* [ ... res_obj re_obj input bc saved_buf ] */
+
+	duk_pop_n(ctx, 4);
+
+	/* [ ... res_obj ] */
+
+	/* XXX: these last tricks are unnecessary if the function is made
+	 * a genuine native function.
 	 */
+}
 
-	if (cp == 0x000aL || cp == 0x000dL || cp == 0x2028L ||
-	    cp == 0x2029L) {
-		return 1;
-	}
+DUK_INTERNAL void duk_regexp_match(duk_hthread *thr) {
+	duk__regexp_match_helper(thr, 0 /*force_global*/);
+}
 
-	return 0;
+/* This variant is needed by String.prototype.split(); it needs to perform
+ * global-style matching on a cloned RegExp which is potentially non-global.
+ */
+DUK_INTERNAL void duk_regexp_match_force_global(duk_hthread *thr) {
+	duk__regexp_match_helper(thr, 1 /*force_global*/);
 }
 
+#else  /* DUK_USE_REGEXP_SUPPORT */
+
+/* regexp support disabled */
+
+#endif  /* DUK_USE_REGEXP_SUPPORT */
+#line 1 "duk_replacements.c"
 /*
- *  "IdentifierStart" production check.
+ *  Replacements for missing platform functions.
+ *
+ *  Unlike the originals, fpclassify() and signbit() replacements don't
+ *  work on any floating point types, only doubles.  The C typing here
+ *  mimics the standard prototypes.
  */
 
-duk_small_int_t duk_unicode_is_identifier_start(duk_codepoint_t cp) {
-	/*
-	 *  E5 Section 7.6:
-	 *
-	 *    IdentifierStart:
-	 *      UnicodeLetter
-	 *      $
-	 *      _
-	 *      \ UnicodeEscapeSequence
-	 *
-	 *  IdentifierStart production has one multi-character production:
-	 *
-	 *    \ UnicodeEscapeSequence
-	 *
-	 *  The '\' character is -not- matched by this function.  Rather, the caller
-	 *  should decode the escape and then call this function to check whether the
-	 *  decoded character is acceptable (see discussion in E5 Section 7.6).
-	 *
-	 *  The "UnicodeLetter" alternative of the production allows letters
-	 *  from various Unicode categories.  These can be extracted with the
-	 *  "src/extract_chars.py" script.
-	 *
-	 *  Because the result has hundreds of Unicode codepoint ranges, matching
-	 *  for any values >= 0x80 are done using a very slow range-by-range scan
-	 *  and a packed range format.
-	 *
-	 *  The ASCII portion (codepoints 0x00 ... 0x7f) is fast-pathed below because
-	 *  it matters the most.  The ASCII related ranges of IdentifierStart are:
-	 *
-	 *    0x0041 ... 0x005a		['A' ... 'Z']
-	 *    0x0061 ... 0x007a		['a' ... 'z']
-	 *    0x0024			['$']
-	 *    0x005f			['_']
-	 */
+/* include removed: duk_internal.h */
 
-	/* ASCII (and EOF) fast path -- quick accept and reject */
-	if (cp <= 0x7fL) {
-		if ((cp >= 'a' && cp <= 'z') ||
-		    (cp >= 'A' && cp <= 'Z') ||
-		    cp == '_' || cp == '$') {
-			return 1;
-		}
-		return 0;
-	}
+#if defined(DUK_USE_COMPUTED_NAN)
+DUK_INTERNAL double duk_computed_nan;
+#endif
 
-	/* Non-ASCII slow path (range-by-range linear comparison), very slow */
+#if defined(DUK_USE_COMPUTED_INFINITY)
+DUK_INTERNAL double duk_computed_infinity;
+#endif
 
-#ifdef DUK_USE_SOURCE_NONBMP
-	if (duk__uni_range_match(duk_unicode_ids_noa,
-	                         (duk_size_t) sizeof(duk_unicode_ids_noa),
-	                         (duk_codepoint_t) cp)) {
-		return 1;
+#if defined(DUK_USE_REPL_FPCLASSIFY)
+DUK_INTERNAL int duk_repl_fpclassify(double x) {
+	duk_double_union u;
+	duk_uint_fast16_t expt;
+	duk_small_int_t mzero;
+
+	u.d = x;
+	expt = (duk_uint_fast16_t) (u.us[DUK_DBL_IDX_US0] & 0x7ff0UL);
+	if (expt > 0x0000UL && expt < 0x7ff0UL) {
+		/* expt values [0x001,0x7fe] = normal */
+		return DUK_FP_NORMAL;
 	}
-	return 0;
-#else
-	if (cp < 0x10000L) {
-		if (duk__uni_range_match(duk_unicode_ids_noabmp,
-		                         sizeof(duk_unicode_ids_noabmp),
-		                         (duk_codepoint_t) cp)) {
-			return 1;
+
+	mzero = (u.ui[DUK_DBL_IDX_UI1] == 0 && (u.ui[DUK_DBL_IDX_UI0] & 0x000fffffUL) == 0);
+	if (expt == 0x0000UL) {
+		/* expt 0x000 is zero/subnormal */
+		if (mzero) {
+			return DUK_FP_ZERO;
+		} else {
+			return DUK_FP_SUBNORMAL;
+		}
+	} else {
+		/* expt 0xfff is infinite/nan */
+		if (mzero) {
+			return DUK_FP_INFINITE;
+		} else {
+			return DUK_FP_NAN;
 		}
+	}
+}
+#endif
+
+#if defined(DUK_USE_REPL_SIGNBIT)
+DUK_INTERNAL int duk_repl_signbit(double x) {
+	duk_double_union u;
+	u.d = x;
+	return (int) (u.uc[DUK_DBL_IDX_UC0] & 0x80UL);
+}
+#endif
+
+#if defined(DUK_USE_REPL_ISFINITE)
+DUK_INTERNAL int duk_repl_isfinite(double x) {
+	int c = DUK_FPCLASSIFY(x);
+	if (c == DUK_FP_NAN || c == DUK_FP_INFINITE) {
 		return 0;
 	} else {
-		/* without explicit non-BMP support, assume non-BMP characters
-		 * are always accepted as identifier characters.
-		 */
 		return 1;
 	}
+}
 #endif
+
+#if defined(DUK_USE_REPL_ISNAN)
+DUK_INTERNAL int duk_repl_isnan(double x) {
+	int c = DUK_FPCLASSIFY(x);
+	return (c == DUK_FP_NAN);
 }
+#endif
 
+#if defined(DUK_USE_REPL_ISINF)
+DUK_INTERNAL int duk_repl_isinf(double x) {
+	int c = DUK_FPCLASSIFY(x);
+	return (c == DUK_FP_INFINITE);
+}
+#endif
+#line 1 "duk_selftest.c"
 /*
- *  "IdentifierPart" production check.
+ *  Self tests to ensure execution environment is sane.  Intended to catch
+ *  compiler/platform problems which cannot be detected at compile time.
  */
 
-duk_small_int_t duk_unicode_is_identifier_part(duk_codepoint_t cp) {
-	/*
-	 *  E5 Section 7.6:
-	 *
-	 *    IdentifierPart:
-	 *      IdentifierStart
-	 *      UnicodeCombiningMark
-	 *      UnicodeDigit
-	 *      UnicodeConnectorPunctuation
-	 *      <ZWNJ>	[U+200C]
-	 *      <ZWJ>	[U+200D]
-	 *
-	 *  IdentifierPart production has one multi-character production
-	 *  as part of its IdentifierStart alternative.  The '\' character
-	 *  of an escape sequence is not matched here, see discussion in
-	 *  duk_unicode_is_identifier_start().
-	 *
-	 *  To match non-ASCII characters (codepoints >= 0x80), a very slow
-	 *  linear range-by-range scan is used.  The codepoint is first compared
-	 *  to the IdentifierStart ranges, and if it doesn't match, then to a
-	 *  set consisting of code points in IdentifierPart but not in
-	 *  IdentifierStart.  This is done to keep the unicode range data small,
-	 *  at the expense of speed.
-	 *
-	 *  The ASCII fast path consists of:
-	 *
-	 *    0x0030 ... 0x0039		['0' ... '9', UnicodeDigit]
-	 *    0x0041 ... 0x005a		['A' ... 'Z', IdentifierStart]
-	 *    0x0061 ... 0x007a		['a' ... 'z', IdentifierStart]
-	 *    0x0024			['$', IdentifierStart]
-	 *    0x005f			['_', IdentifierStart and
-	 *                               UnicodeConnectorPunctuation]
-	 *
-	 *  UnicodeCombiningMark has no code points <= 0x7f.
-	 *
-	 *  The matching code reuses the "identifier start" tables, and then
-	 *  consults a separate range set for characters in "identifier part"
-	 *  but not in "identifier start".  These can be extracted with the
-	 *  "src/extract_chars.py" script.
-	 *
-	 *  UnicodeCombiningMark -> categories Mn, Mc
-	 *  UnicodeDigit -> categories Nd
-	 *  UnicodeConnectorPunctuation -> categories Pc
-	 */
+/* include removed: duk_internal.h */
 
-	/* ASCII (and EOF) fast path -- quick accept and reject */
-	if (cp <= 0x7fL) {
-		if ((cp >= 'a' && cp <= 'z') ||
-		    (cp >= 'A' && cp <= 'Z') ||
-		    (cp >= '0' && cp <= '9') ||
-		    cp == '_' || cp == '$') {
-			return 1;
-		}
-		return 0;
-	}
+#if defined(DUK_USE_SELF_TESTS)
 
-	/* Non-ASCII slow path (range-by-range linear comparison), very slow */
+/*
+ *  Unions and structs for self tests
+ */
 
-#ifdef DUK_USE_SOURCE_NONBMP
-	if (duk__uni_range_match(duk_unicode_ids_noa,
-	                         sizeof(duk_unicode_ids_noa),
-	                         (duk_codepoint_t) cp) ||
-	    duk__uni_range_match(duk_unicode_idp_m_ids_noa,
-	                         sizeof(duk_unicode_idp_m_ids_noa),
-	                         (duk_codepoint_t) cp)) {
-		return 1;
+typedef union {
+	double d;
+	duk_uint8_t c[8];
+} duk__test_double_union;
+
+#define DUK__DBLUNION_CMP_TRUE(a,b)  do { \
+		if (DUK_MEMCMP((const void *) (a), (const void *) (b), sizeof(duk__test_double_union)) != 0) { \
+			DUK_PANIC(DUK_ERR_INTERNAL_ERROR, "self test failed: double union compares false (expected true)"); \
+		} \
+	} while (0)
+
+#define DUK__DBLUNION_CMP_FALSE(a,b)  do { \
+		if (DUK_MEMCMP((const void *) (a), (const void *) (b), sizeof(duk__test_double_union)) == 0) { \
+			DUK_PANIC(DUK_ERR_INTERNAL_ERROR, "self test failed: double union compares true (expected false)"); \
+		} \
+	} while (0)
+
+typedef union {
+	duk_uint32_t i;
+	duk_uint8_t c[8];
+} duk__test_u32_union;
+
+/*
+ *  Various sanity checks for typing
+ */
+
+DUK_LOCAL void duk__selftest_types(void) {
+	if (!(sizeof(duk_int8_t) == 1 &&
+	      sizeof(duk_uint8_t) == 1 &&
+	      sizeof(duk_int16_t) == 2 &&
+	      sizeof(duk_uint16_t) == 2 &&
+	      sizeof(duk_int32_t) == 4 &&
+	      sizeof(duk_uint32_t) == 4)) {
+		DUK_PANIC(DUK_ERR_INTERNAL_ERROR, "self test failed: duk_(u)int{8,16,32}_t size");
 	}
-	return 0;
-#else
-	if (cp < 0x10000L) {
-		if (duk__uni_range_match(duk_unicode_ids_noabmp,
-		                         sizeof(duk_unicode_ids_noabmp),
-		                         (duk_codepoint_t) cp) ||
-		    duk__uni_range_match(duk_unicode_idp_m_ids_noabmp,
-		                         sizeof(duk_unicode_idp_m_ids_noabmp),
-		                         (duk_codepoint_t) cp)) {
-			return 1;
-		}
-		return 0;
-	} else {
-		/* without explicit non-BMP support, assume non-BMP characters
-		 * are always accepted as identifier characters.
-		 */
-		return 1;
+#if defined(DUK_USE_64BIT_OPS)
+	if (!(sizeof(duk_int64_t) == 8 &&
+	      sizeof(duk_uint64_t) == 8)) {
+		DUK_PANIC(DUK_ERR_INTERNAL_ERROR, "self test failed: duk_(u)int64_t size");
 	}
 #endif
+
+	if (!(sizeof(duk_size_t) >= sizeof(duk_uint_t))) {
+		/* Some internal code now assumes that all duk_uint_t values
+		 * can be expressed with a duk_size_t.
+		 */
+		DUK_PANIC(DUK_ERR_INTERNAL_ERROR, "self test failed: duk_size_t is smaller than duk_uint_t");
+	}
+	if (!(sizeof(duk_int_t) >= 4)) {
+		DUK_PANIC(DUK_ERR_INTERNAL_ERROR, "self test failed: duk_int_t is not 32 bits");
+	}
 }
 
 /*
- *  Unicode letter check.
+ *  Packed tval sanity
  */
 
-duk_small_int_t duk_unicode_is_letter(duk_codepoint_t cp) {
-	/*
-	 *  Unicode letter is now taken to be the categories:
-	 *
-	 *    Lu, Ll, Lt, Lm, Lo
-	 *
-	 *  (Not sure if this is exactly correct.)
-	 *
-	 *  The ASCII fast path consists of:
-	 *
-	 *    0x0041 ... 0x005a		['A' ... 'Z']
-	 *    0x0061 ... 0x007a		['a' ... 'z']
-	 */
-
-	/* ASCII (and EOF) fast path -- quick accept and reject */
-	if (cp <= 0x7fL) {
-		if ((cp >= 'a' && cp <= 'z') ||
-		    (cp >= 'A' && cp <= 'Z')) {
-			return 1;
-		}
-		return 0;
+DUK_LOCAL void duk__selftest_packed_tval(void) {
+#if defined(DUK_USE_PACKED_TVAL)
+	if (sizeof(void *) > 4) {
+		DUK_PANIC(DUK_ERR_INTERNAL_ERROR, "self test failed: packed duk_tval in use but sizeof(void *) > 4");
 	}
+#endif
+}
 
-	/* Non-ASCII slow path (range-by-range linear comparison), very slow */
+/*
+ *  Two's complement arithmetic.
+ */
 
-#ifdef DUK_USE_SOURCE_NONBMP
-	if (duk__uni_range_match(duk_unicode_ids_noa,
-	                         sizeof(duk_unicode_ids_noa),
-	                         (duk_codepoint_t) cp) &&
-	    !duk__uni_range_match(duk_unicode_ids_m_let_noa,
-	                          sizeof(duk_unicode_ids_m_let_noa),
-	                          (duk_codepoint_t) cp)) {
-		return 1;
-	}
-	return 0;
-#else
-	if (cp < 0x10000L) {
-		if (duk__uni_range_match(duk_unicode_ids_noabmp,
-		                         sizeof(duk_unicode_ids_noabmp),
-		                         (duk_codepoint_t) cp) &&
-		    !duk__uni_range_match(duk_unicode_ids_m_let_noabmp,
-		                          sizeof(duk_unicode_ids_m_let_noabmp),
-		                          (duk_codepoint_t) cp)) {
-			return 1;
-		}
-		return 0;
-	} else {
-		/* without explicit non-BMP support, assume non-BMP characters
-		 * are always accepted as letters.
-		 */
-		return 1;
+DUK_LOCAL void duk__selftest_twos_complement(void) {
+	volatile int test;
+	test = -1;
+
+	/* Note that byte order doesn't affect this test: all bytes in
+	 * 'test' will be 0xFF for two's complement.
+	 */
+	if (((volatile duk_uint8_t *) &test)[0] != (duk_uint8_t) 0xff) {
+		DUK_PANIC(DUK_ERR_INTERNAL_ERROR, "self test failed: two's complement arithmetic");
 	}
-#endif
 }
 
 /*
- *  Complex case conversion helper which decodes a bit-packed conversion
- *  control stream generated by unicode/extract_caseconv.py.  The conversion
- *  is very slow because it runs through the conversion data in a linear
- *  fashion to save space (which is why ASCII characters have a special
- *  fast path before arriving here).
- * 
- *  The particular bit counts etc have been determined experimentally to
- *  be small but still sufficient, and must match the Python script
- *  (src/extract_caseconv.py).
- *
- *  The return value is the case converted codepoint or -1 if the conversion
- *  results in multiple characters (this is useful for regexp Canonicalization
- *  operation).  If 'buf' is not NULL, the result codepoint(s) are also
- *  appended to the hbuffer.
- *
- *  Context and locale specific rules must be checked before consulting
- *  this function.
+ *  Byte order.  Important to self check, because on some exotic platforms
+ *  there is no actual detection but rather assumption based on platform
+ *  defines.
  */
 
-static duk_codepoint_t duk__slow_case_conversion(duk_hthread *thr,
-                                                 duk_hbuffer_dynamic *buf,
-                                                 duk_codepoint_t cp,
-                                                 duk_bitdecoder_ctx *bd_ctx) {
-	duk_small_int_t skip = 0;
-	duk_small_int_t n;
-	duk_small_int_t t;
-	duk_small_int_t count;
-	duk_codepoint_t tmp_cp;
-	duk_codepoint_t start_i;
-	duk_codepoint_t start_o;
+DUK_LOCAL void duk__selftest_byte_order(void) {
+	duk__test_u32_union u1;
+	duk__test_double_union u2;
 
-	DUK_DDD(DUK_DDDPRINT("slow case conversion for codepoint: %ld", (long) cp));
+	/*
+	 *  >>> struct.pack('>d', 102030405060).encode('hex')
+	 *  '4237c17c6dc40000'
+	 */
+#if defined(DUK_USE_INTEGER_LE)
+	u1.c[0] = 0xef; u1.c[1] = 0xbe; u1.c[2] = 0xad; u1.c[3] = 0xde;
+#elif defined(DUK_USE_INTEGER_ME)
+#error integer mixed endian not supported now
+#elif defined(DUK_USE_INTEGER_BE)
+	u1.c[0] = 0xde; u1.c[1] = 0xad; u1.c[2] = 0xbe; u1.c[3] = 0xef;
+#else
+#error unknown integer endianness
+#endif
 
-	/* range conversion with a "skip" */
-	DUK_DDD(DUK_DDDPRINT("checking ranges"));
-	for (;;) {
-		skip++;
-		n = (duk_small_int_t) duk_bd_decode(bd_ctx, 6);
-		if (n == 0x3f) {
-			/* end marker */
-			break;
-		}
-		DUK_DDD(DUK_DDDPRINT("skip=%ld, n=%ld", (long) skip, (long) n));
+#if defined(DUK_USE_DOUBLE_LE)
+	u2.c[0] = 0x00; u2.c[1] = 0x00; u2.c[2] = 0xc4; u2.c[3] = 0x6d;
+	u2.c[4] = 0x7c; u2.c[5] = 0xc1; u2.c[6] = 0x37; u2.c[7] = 0x42;
+#elif defined(DUK_USE_DOUBLE_ME)
+	u2.c[0] = 0x7c; u2.c[1] = 0xc1; u2.c[2] = 0x37; u2.c[3] = 0x42;
+	u2.c[4] = 0x00; u2.c[5] = 0x00; u2.c[6] = 0xc4; u2.c[7] = 0x6d;
+#elif defined(DUK_USE_DOUBLE_BE)
+	u2.c[0] = 0x42; u2.c[1] = 0x37; u2.c[2] = 0xc1; u2.c[3] = 0x7c;
+	u2.c[4] = 0x6d; u2.c[5] = 0xc4; u2.c[6] = 0x00; u2.c[7] = 0x00;
+#else
+#error unknown double endianness
+#endif
 
-		while (n--) {
-			start_i = (duk_codepoint_t) duk_bd_decode(bd_ctx, 16);
-			start_o = (duk_codepoint_t) duk_bd_decode(bd_ctx, 16);
-			count = (duk_small_int_t) duk_bd_decode(bd_ctx, 7);
-			DUK_DDD(DUK_DDDPRINT("range: start_i=%ld, start_o=%ld, count=%ld, skip=%ld",
-			                     (long) start_i, (long) start_o, (long) count, (long) skip));
+	if (u1.i != (duk_uint32_t) 0xdeadbeefUL) {
+		DUK_PANIC(DUK_ERR_INTERNAL_ERROR, "self test failed: duk_uint32_t byte order");
+	}
 
-			if (cp >= start_i) {
-				tmp_cp = cp - start_i;  /* always >= 0 */
-				if (tmp_cp < (duk_codepoint_t) count * (duk_codepoint_t) skip &&
-				    (tmp_cp % (duk_codepoint_t) skip) == 0) {
-					DUK_DDD(DUK_DDDPRINT("range matches input codepoint"));
-					cp = start_o + tmp_cp;
-					goto single;
-				}
-			}
-		}
+	if (u2.d != (double) 102030405060.0) {
+		DUK_PANIC(DUK_ERR_INTERNAL_ERROR, "self test failed: double byte order");
 	}
+}
 
-	/* 1:1 conversion */
-	n = (duk_small_int_t) duk_bd_decode(bd_ctx, 6);
-	DUK_DDD(DUK_DDDPRINT("checking 1:1 conversions (count %ld)", (long) n));
-	while (n--) {
-		start_i = (duk_codepoint_t) duk_bd_decode(bd_ctx, 16);
-		start_o = (duk_codepoint_t) duk_bd_decode(bd_ctx, 16);
-		DUK_DDD(DUK_DDDPRINT("1:1 conversion %ld -> %ld", (long) start_i, (long) start_o));
-		if (cp == start_i) {
-			DUK_DDD(DUK_DDDPRINT("1:1 matches input codepoint"));
-			cp = start_o;
-			goto single;
-		}
+/*
+ *  DUK_BSWAP macros
+ */
+
+DUK_LOCAL void duk__selftest_bswap_macros(void) {
+	duk_uint32_t x32;
+	duk_uint16_t x16;
+	duk_double_union du;
+	duk_double_t du_diff;
+
+	x16 = 0xbeefUL;
+	x16 = DUK_BSWAP16(x16);
+	if (x16 != (duk_uint16_t) 0xefbeUL) {
+		DUK_PANIC(DUK_ERR_INTERNAL_ERROR, "self test failed: DUK_BSWAP16");
 	}
 
-	/* complex, multicharacter conversion */
-	n = (duk_small_int_t) duk_bd_decode(bd_ctx, 7);
-	DUK_DDD(DUK_DDDPRINT("checking 1:n conversions (count %ld)", (long) n));
-	while (n--) {
-		start_i = (duk_codepoint_t) duk_bd_decode(bd_ctx, 16);
-		t = (duk_small_int_t) duk_bd_decode(bd_ctx, 2);
-		DUK_DDD(DUK_DDDPRINT("1:n conversion %ld -> %ld chars", (long) start_i, (long) t));
-		if (cp == start_i) {
-			DUK_DDD(DUK_DDDPRINT("1:n matches input codepoint"));
-			if (buf) {
-				while (t--) {
-					tmp_cp = (duk_codepoint_t) duk_bd_decode(bd_ctx, 16);
-					DUK_ASSERT(buf != NULL);
-					duk_hbuffer_append_xutf8(thr, buf, (duk_uint32_t) tmp_cp);  /* FIXME: duk_codepoint_t */
-				}
-			}
-			return -1;
-		} else {
-			while (t--) {
-				(void) duk_bd_decode(bd_ctx, 16);
-			}
-		}
+	x32 = 0xdeadbeefUL;
+	x32 = DUK_BSWAP32(x32);
+	if (x32 != (duk_uint32_t) 0xefbeaddeUL) {
+		DUK_PANIC(DUK_ERR_INTERNAL_ERROR, "self test failed: DUK_BSWAP32");
 	}
 
-	/* default: no change */
-	DUK_DDD(DUK_DDDPRINT("no rule matches, output is same as input"));
-	/* fall through */
+	/* >>> struct.unpack('>d', '4000112233445566'.decode('hex'))
+	 * (2.008366013071895,)
+	 */
 
- single:
-	if (buf) {
-		duk_hbuffer_append_xutf8(thr, buf, cp);
+	du.uc[0] = 0x40; du.uc[1] = 0x00; du.uc[2] = 0x11; du.uc[3] = 0x22;
+	du.uc[4] = 0x33; du.uc[5] = 0x44; du.uc[6] = 0x55; du.uc[7] = 0x66;
+	DUK_DBLUNION_DOUBLE_NTOH(&du);
+	du_diff = du.d - 2.008366013071895;
+#if 0
+	DUK_FPRINTF(DUK_STDERR, "du_diff: %lg\n", (double) du_diff);
+#endif
+	if (du_diff > 1e-15) {
+		/* Allow very small lenience because some compilers won't parse
+		 * exact IEEE double constants (happened in matrix testing with
+		 * Linux gcc-4.8 -m32 at least).
+		 */
+#if 0
+		DUK_FPRINTF(DUK_STDERR, "Result of DUK_DBLUNION_DOUBLE_NTOH: %02x %02x %02x %02x %02x %02x %02x %02x\n",
+		            (unsigned int) du.uc[0], (unsigned int) du.uc[1],
+		            (unsigned int) du.uc[2], (unsigned int) du.uc[3],
+		            (unsigned int) du.uc[4], (unsigned int) du.uc[5],
+		            (unsigned int) du.uc[6], (unsigned int) du.uc[7]);
+#endif
+		DUK_PANIC(DUK_ERR_INTERNAL_ERROR, "self test failed: DUK_DBLUNION_DOUBLE_NTOH");
 	}
-	return cp;
 }
 
 /*
- *  Case conversion helper, with context/local sensitivity.
- *  For proper case conversion, one needs to know the character
- *  and the preceding and following characters, as well as
- *  locale/language.
+ *  Basic double / byte union memory layout.
  */
 
-/* XXX: add 'language' argument when locale/language sensitive rule
- * support added.
+DUK_LOCAL void duk__selftest_double_union_size(void) {
+	if (sizeof(duk__test_double_union) != 8) {
+		DUK_PANIC(DUK_ERR_INTERNAL_ERROR, "self test failed: invalid union size");
+	}
+}
+
+/*
+ *  Union aliasing, see misc/clang_aliasing.c.
  */
-static duk_codepoint_t duk__case_transform_helper(duk_hthread *thr,
-                                                  duk_hbuffer_dynamic *buf,
-                                                  duk_codepoint_t cp,
-                                                  duk_codepoint_t prev,
-                                                  duk_codepoint_t next,
-                                                  duk_bool_t uppercase) {
-	duk_bitdecoder_ctx bd_ctx;
 
-	/* fast path for ASCII */
-	if (cp < 0x80L) {
-		/* XXX: there are language sensitive rules for the ASCII range.
-		 * If/when language/locale support is implemented, they need to
-		 * be implemented here for the fast path.  There are no context
-		 * sensitive rules for ASCII range.
-		 */
+DUK_LOCAL void duk__selftest_double_aliasing(void) {
+	duk__test_double_union a, b;
 
-		if (uppercase) {
-			if (cp >= 'a' && cp <= 'z') {
-				cp = cp - 'a' + 'A';
-			}
-		} else {
-			if (cp >= 'A' && cp <= 'Z') {
-				cp = cp - 'A' + 'a';
-			}
-		}
-		goto singlechar;
-	}
+	/* This testcase fails when Emscripten-generated code runs on Firefox.
+	 * It's not an issue because the failure should only affect packed
+	 * duk_tval representation, which is not used with Emscripten.
+	 */
+#if !defined(DUK_USE_PACKED_TVAL)
+	DUK_D(DUK_DPRINT("skip double aliasing self test when duk_tval is not packed"));
+	return;
+#endif
 
-	/* context and locale specific rules which cannot currently be represented
-	 * in the caseconv bitstream: hardcoded rules in C
+	/* Test signaling NaN and alias assignment in all endianness combinations.
 	 */
-	if (uppercase) {
-		/* XXX: turkish / azeri not implemented */
-	} else {
-		/*
-		 *  Final sigma context specific rule.  This is a rather tricky rule
-		 *  and this handling is probably not 100% correct now.
-		 */
 
-		if (cp == 0x03a3L &&    /* U+03A3 = GREEK CAPITAL LETTER SIGMA */
-		    duk_unicode_is_letter(prev) &&        /* prev exists and is not a letter */
-		    !duk_unicode_is_letter(next)) {       /* next does not exist or next is not a letter */
-			/* Capital sigma occurred at "end of word", lowercase to
-			 * U+03C2 = GREEK SMALL LETTER FINAL SIGMA.  Otherwise
-			 * fall through and let the normal rules lowercase it to
-			 * U+03C3 = GREEK SMALL LETTER SIGMA.
-			 */
-			cp = 0x03c2L;
-			goto singlechar;
-		}
+	/* little endian */
+	a.c[0] = 0x11; a.c[1] = 0x22; a.c[2] = 0x33; a.c[3] = 0x44;
+	a.c[4] = 0x00; a.c[5] = 0x00; a.c[6] = 0xf1; a.c[7] = 0xff;
+	b = a;
+	DUK__DBLUNION_CMP_TRUE(&a, &b);
 
-		/* XXX: lithuanian not implemented */
-		/* XXX: lithuanian, explicit dot rules */
-		/* XXX: turkish / azeri, lowercase rules */
-#if 0
-		if (0 /* language == 'lt' */ &&
-		    cp == 0x0307L) {               /* U+0307 = COMBINING DOT ABOVE */
-			goto nochar;
-		}
-#endif
-	}
+	/* big endian */
+	a.c[0] = 0xff; a.c[1] = 0xf1; a.c[2] = 0x00; a.c[3] = 0x00;
+	a.c[4] = 0x44; a.c[5] = 0x33; a.c[6] = 0x22; a.c[7] = 0x11;
+	b = a;
+	DUK__DBLUNION_CMP_TRUE(&a, &b);
 
-	/* 1:1 or special conversions, but not locale/context specific: script generated rules */
-	DUK_MEMZERO(&bd_ctx, sizeof(bd_ctx));
-	if (uppercase) {
-		bd_ctx.data = (duk_uint8_t *) duk_unicode_caseconv_uc;
-		bd_ctx.length = (duk_size_t) sizeof(duk_unicode_caseconv_uc);
-	} else {
-		bd_ctx.data = (duk_uint8_t *) duk_unicode_caseconv_lc;
-		bd_ctx.length = (duk_size_t) sizeof(duk_unicode_caseconv_lc);
-	}
-	return duk__slow_case_conversion(thr, buf, cp, &bd_ctx);
+	/* mixed endian */
+	a.c[0] = 0x00; a.c[1] = 0x00; a.c[2] = 0xf1; a.c[3] = 0xff;
+	a.c[4] = 0x11; a.c[5] = 0x22; a.c[6] = 0x33; a.c[7] = 0x44;
+	b = a;
+	DUK__DBLUNION_CMP_TRUE(&a, &b);
+}
 
- singlechar:
-	if (buf) {
-		duk_hbuffer_append_xutf8(thr, buf, cp);
-	}
-	return cp;
+/*
+ *  Zero sign, see misc/tcc_zerosign2.c.
+ */
 
- /* unused now, not needed until Turkish/Azeri */
-#if 0
- nochar:
-	return -1;
+DUK_LOCAL void duk__selftest_double_zero_sign(void) {
+	duk__test_double_union a, b;
+
+	a.d = 0.0;
+	b.d = -a.d;
+	DUK__DBLUNION_CMP_FALSE(&a, &b);
+}
+
+/*
+ *  Struct size/alignment if platform requires it
+ *
+ *  There are some compiler specific struct padding pragmas etc in use, this
+ *  selftest ensures they're correctly detected and used.
+ */
+
+DUK_LOCAL void duk__selftest_struct_align(void) {
+#if (DUK_USE_ALIGN_BY == 4)
+	if ((sizeof(duk_hbuffer_fixed) % 4) != 0) {
+		DUK_PANIC(DUK_ERR_INTERNAL_ERROR, "self test failed: sizeof(duk_hbuffer_fixed) not aligned to 4");
+	}
+#elif (DUK_USE_ALIGN_BY == 8)
+	if ((sizeof(duk_hbuffer_fixed) % 8) != 0) {
+		DUK_PANIC(DUK_ERR_INTERNAL_ERROR, "self test failed: sizeof(duk_hbuffer_fixed) not aligned to 8");
+	}
+#elif (DUK_USE_ALIGN_BY == 1)
+	/* no check */
+#else
+#error invalid DUK_USE_ALIGN_BY
 #endif
 }
 
 /*
- *  Replace valstack top with case converted version.
+ *  64-bit arithmetic
+ *
+ *  There are some platforms/compilers where 64-bit types are available
+ *  but don't work correctly.  Test for known cases.
  */
 
-void duk_unicode_case_convert_string(duk_hthread *thr, duk_small_int_t uppercase) {
-	duk_context *ctx = (duk_context *) thr;
-	duk_hstring *h_input;
-	duk_hbuffer_dynamic *h_buf;
-	duk_uint8_t *p, *p_start, *p_end;
-	duk_codepoint_t prev, curr, next;
+DUK_LOCAL void duk__selftest_64bit_arithmetic(void) {
+#if defined(DUK_USE_64BIT_OPS)
+	volatile duk_int64_t i;
+	volatile duk_double_t d;
 
-	h_input = duk_require_hstring(ctx, -1);
-	DUK_ASSERT(h_input != NULL);
+	/* Catch a double-to-int64 cast issue encountered in practice. */
+	d = 2147483648.0;
+	i = (duk_int64_t) d;
+	if (i != 0x80000000LL) {
+		DUK_PANIC(DUK_ERR_INTERNAL_ERROR, "self test failed: casting 2147483648.0 to duk_int64_t failed");
+	}
+#else
+	/* nop */
+#endif
+}
+
+/*
+ *  Casting
+ */
 
-	/* XXX: should init the buffer with a spare of at least h_input->blen
-	 * to avoid unnecessary growth steps.
+DUK_LOCAL void duk__selftest_cast_double_to_small_uint(void) {
+	/*
+	 *  https://github.com/svaarala/duktape/issues/127#issuecomment-77863473
 	 */
-	duk_push_dynamic_buffer(ctx, 0);
-	h_buf = (duk_hbuffer_dynamic *) duk_get_hbuffer(ctx, -1);
-	DUK_ASSERT(h_buf != NULL);
-	DUK_ASSERT(DUK_HBUFFER_HAS_DYNAMIC(h_buf));
 
-	/* [ ... input buffer ] */
+	duk_double_t d1, d2;
+	duk_small_uint_t u;
 
-	p_start = (duk_uint8_t *) DUK_HSTRING_GET_DATA(h_input);
-	p_end = p_start + DUK_HSTRING_GET_BYTELEN(h_input);
-	p = p_start;
+	duk_double_t d1v, d2v;
+	duk_small_uint_t uv;
 
-	prev = -1; DUK_UNREF(prev);
-	curr = -1;
-	next = -1;
-	for (;;) {
-		prev = curr;
-		curr = next;
-		next = -1;
-		if (p < p_end) {
-			next = (int) duk_unicode_decode_xutf8_checked(thr, &p, p_start, p_end);
-		} else {
-			/* end of input and last char has been processed */
-			if (curr < 0) {
-				break;
-			}
-		}
+	/* Test without volatiles */
 
-		/* on first round, skip */
-		if (curr >= 0) {
-			/* may generate any number of output codepoints */
-			duk__case_transform_helper(thr,
-			                           h_buf,
-			                           (duk_codepoint_t) curr,
-			                           prev,
-			                           next,
-			                           uppercase);
-		}
+	d1 = 1.0;
+	u = (duk_small_uint_t) d1;
+	d2 = (duk_double_t) u;
+
+	if (!(d1 == 1.0 && u == 1 && d2 == 1.0 && d1 == d2)) {
+		DUK_PANIC(DUK_ERR_INTERNAL_ERROR, "self test failed: double to duk_small_uint_t cast failed");
 	}
 
-	duk_to_string(ctx, -1);  /* invalidates h_buf pointer */
-	duk_remove(ctx, -2);
+	/* Same test with volatiles */
+
+	d1v = 1.0;
+	uv = (duk_small_uint_t) d1v;
+	d2v = (duk_double_t) uv;
+
+	if (!(d1v == 1.0 && uv == 1 && d2v == 1.0 && d1v == d2v)) {
+		DUK_PANIC(DUK_ERR_INTERNAL_ERROR, "self test failed: double to duk_small_uint_t cast failed");
+	}
 }
 
-#ifdef DUK_USE_REGEXP_SUPPORT
+DUK_LOCAL void duk__selftest_cast_double_to_uint32(void) {
+	/*
+	 *  This test fails on an exotic ARM target; double-to-uint
+	 *  cast is incorrectly clamped to -signed- int highest value.
+	 *
+	 *  https://github.com/svaarala/duktape/issues/336
+	 */
+
+	duk_double_t dv;
+	duk_uint32_t uv;
+
+	dv = 3735928559.0;  /* 0xdeadbeef in decimal */
+	uv = (duk_uint32_t) dv;
+
+	if (uv != 0xdeadbeefUL) {
+		DUK_PANIC(DUK_ERR_INTERNAL_ERROR, "self test failed: double to duk_uint32_t cast failed");
+	}
+}
 
 /*
- *  Canonicalize() abstract operation needed for canonicalization of individual
- *  codepoints during regexp compilation and execution, see E5 Section 15.10.2.8.
- *  Note that codepoints are canonicalized one character at a time, so no context
- *  specific rules can apply.  Locale specific rules can apply, though.
+ *  Self test main
  */
 
-duk_codepoint_t duk_unicode_re_canonicalize_char(duk_hthread *thr, duk_codepoint_t cp) {
-	duk_codepoint_t y;
+DUK_INTERNAL void duk_selftest_run_tests(void) {
+	duk__selftest_types();
+	duk__selftest_packed_tval();
+	duk__selftest_twos_complement();
+	duk__selftest_byte_order();
+	duk__selftest_bswap_macros();
+	duk__selftest_double_union_size();
+	duk__selftest_double_aliasing();
+	duk__selftest_double_zero_sign();
+	duk__selftest_struct_align();
+	duk__selftest_64bit_arithmetic();
+	duk__selftest_cast_double_to_small_uint();
+	duk__selftest_cast_double_to_uint32();
+}
 
-	y = duk__case_transform_helper(thr,
-	                               NULL,    /* buf */
-	                               cp,      /* curr char */
-	                               -1,      /* prev char */
-	                               -1,      /* next char */
-	                               1);      /* uppercase */
+#undef DUK__DBLUNION_CMP_TRUE
+#undef DUK__DBLUNION_CMP_FALSE
 
-	if ((y < 0) || (cp >= 0x80 && y < 0x80)) {
-		/* multiple codepoint conversion or non-ASCII mapped to ASCII
-		 * --> leave as is.
-		 */
-		return cp;
-	}
+#endif  /* DUK_USE_SELF_TESTS */
+/* include removed: duk_internal.h */
+#line 2 "duk_tval.c"
 
-	return y;
-}
+#if defined(DUK_USE_FASTINT)
 
 /*
- *  E5 Section 15.10.2.6 "IsWordChar" abstract operation.  Assume
- *  x < 0 for characters read outside the string.
+ *  Manually optimized double-to-fastint downgrade check.
+ *
+ *  This check has a large impact on performance, especially for fastint
+ *  slow paths, so must be changed carefully.  The code should probably be
+ *  optimized for the case where the result does not fit into a fastint,
+ *  to minimize the penalty for "slow path code" dealing with fractions etc.
+ *
+ *  At least on one tested soft float ARM platform double-to-int64 coercion
+ *  is very slow (and sometimes produces incorrect results, see self tests).
+ *  This algorithm combines a fastint compatibility check and extracting the
+ *  integer value from an IEEE double for setting the tagged fastint.  For
+ *  other platforms a more naive approach might be better.
+ *
+ *  See doc/fastint.rst for details.
  */
 
-duk_small_int_t duk_unicode_re_is_wordchar(duk_codepoint_t x) {
-	/*
-	 *  Note: the description in E5 Section 15.10.2.6 has a typo, it
-	 *  contains 'A' twice and lacks 'a'; the intent is [0-9a-zA-Z_].
-	 */
-	if ((x >= '0' && x <= '9') ||
-	    (x >= 'a' && x <= 'z') ||
-	    (x >= 'A' && x <= 'Z') ||
-	    (x == '_')) {
-		return 1;
+DUK_INTERNAL DUK_ALWAYS_INLINE void duk_tval_set_number_chkfast(duk_tval *tv, duk_double_t x) {
+	duk_double_union du;
+	duk_int64_t i;
+	duk_small_int_t expt;
+	duk_small_int_t shift;
+
+	/* XXX: optimize for packed duk_tval directly? */
+
+	du.d = x;
+	i = (duk_int64_t) DUK_DBLUNION_GET_INT64(&du);
+	expt = (duk_small_int_t) ((i >> 52) & 0x07ff);
+	shift = expt - 1023;
+
+	if (shift >= 0 && shift <= 46) {  /* exponents 1023 to 1069 */
+		duk_int64_t t;
+
+		if (((0x000fffffffffffffLL >> shift) & i) == 0) {
+			t = i | 0x0010000000000000LL;  /* implicit leading one */
+			t = t & 0x001fffffffffffffLL;
+			t = t >> (52 - shift);
+			if (i < 0) {
+				t = -t;
+			}
+			DUK_TVAL_SET_FASTINT(tv, t);
+			return;
+		}
+	} else if (shift == -1023) {  /* exponent 0 */
+		if (i >= 0 && (i & 0x000fffffffffffffLL) == 0) {
+			/* Note: reject negative zero. */
+			DUK_TVAL_SET_FASTINT(tv, (duk_int64_t) 0);
+			return;
+		}
+	} else if (shift == 47) {  /* exponent 1070 */
+		if (i < 0 && (i & 0x000fffffffffffffLL) == 0) {
+			DUK_TVAL_SET_FASTINT(tv, (duk_int64_t) DUK_FASTINT_MIN);
+			return;
+		}
 	}
-	return 0;
+
+	DUK_TVAL_SET_DOUBLE(tv, x);
+	return;
 }
 
 /*
- *  Regexp range tables
+ *  Manually optimized number-to-double conversion
  */
 
-/* exposed because lexer needs these too */
-duk_uint16_t duk_unicode_re_ranges_digit[2] = {
-	(duk_uint16_t) 0x0030UL, (duk_uint16_t) 0x0039UL,
-};
-duk_uint16_t duk_unicode_re_ranges_white[22] = {
-	(duk_uint16_t) 0x0009UL, (duk_uint16_t) 0x000DUL,
-	(duk_uint16_t) 0x0020UL, (duk_uint16_t) 0x0020UL,
-	(duk_uint16_t) 0x00A0UL, (duk_uint16_t) 0x00A0UL,
-	(duk_uint16_t) 0x1680UL, (duk_uint16_t) 0x1680UL,
-	(duk_uint16_t) 0x180EUL, (duk_uint16_t) 0x180EUL,
-	(duk_uint16_t) 0x2000UL, (duk_uint16_t) 0x200AUL,
-	(duk_uint16_t) 0x2028UL, (duk_uint16_t) 0x2029UL,
-	(duk_uint16_t) 0x202FUL, (duk_uint16_t) 0x202FUL,
-	(duk_uint16_t) 0x205FUL, (duk_uint16_t) 0x205FUL,
-	(duk_uint16_t) 0x3000UL, (duk_uint16_t) 0x3000UL,
-	(duk_uint16_t) 0xFEFFUL, (duk_uint16_t) 0xFEFFUL,
-};
-duk_uint16_t duk_unicode_re_ranges_wordchar[8] = {
-	(duk_uint16_t) 0x0030UL, (duk_uint16_t) 0x0039UL,
-	(duk_uint16_t) 0x0041UL, (duk_uint16_t) 0x005AUL,
-	(duk_uint16_t) 0x005FUL, (duk_uint16_t) 0x005FUL,
-	(duk_uint16_t) 0x0061UL, (duk_uint16_t) 0x007AUL,
-};
-duk_uint16_t duk_unicode_re_ranges_not_digit[4] = {
-	(duk_uint16_t) 0x0000UL, (duk_uint16_t) 0x002FUL,
-	(duk_uint16_t) 0x003AUL, (duk_uint16_t) 0xFFFFUL,
-};
-duk_uint16_t duk_unicode_re_ranges_not_white[24] = {
-	(duk_uint16_t) 0x0000UL, (duk_uint16_t) 0x0008UL,
-	(duk_uint16_t) 0x000EUL, (duk_uint16_t) 0x001FUL,
-	(duk_uint16_t) 0x0021UL, (duk_uint16_t) 0x009FUL,
-	(duk_uint16_t) 0x00A1UL, (duk_uint16_t) 0x167FUL,
-	(duk_uint16_t) 0x1681UL, (duk_uint16_t) 0x180DUL,
-	(duk_uint16_t) 0x180FUL, (duk_uint16_t) 0x1FFFUL,
-	(duk_uint16_t) 0x200BUL, (duk_uint16_t) 0x2027UL,
-	(duk_uint16_t) 0x202AUL, (duk_uint16_t) 0x202EUL,
-	(duk_uint16_t) 0x2030UL, (duk_uint16_t) 0x205EUL,
-	(duk_uint16_t) 0x2060UL, (duk_uint16_t) 0x2FFFUL,
-	(duk_uint16_t) 0x3001UL, (duk_uint16_t) 0xFEFEUL,
-	(duk_uint16_t) 0xFF00UL, (duk_uint16_t) 0xFFFFUL,
-};
-duk_uint16_t duk_unicode_re_ranges_not_wordchar[10] = {
-	(duk_uint16_t) 0x0000UL, (duk_uint16_t) 0x002FUL,
-	(duk_uint16_t) 0x003AUL, (duk_uint16_t) 0x0040UL,
-	(duk_uint16_t) 0x005BUL, (duk_uint16_t) 0x005EUL,
-	(duk_uint16_t) 0x0060UL, (duk_uint16_t) 0x0060UL,
-	(duk_uint16_t) 0x007BUL, (duk_uint16_t) 0xFFFFUL,
-};
+#if defined(DUK_USE_FASTINT) && defined(DUK_USE_PACKED_TVAL)
+DUK_INTERNAL DUK_ALWAYS_INLINE duk_double_t duk_tval_get_number_packed(duk_tval *tv) {
+	duk_double_union du;
+	duk_uint64_t t;
+
+	t = (duk_uint64_t) DUK_DBLUNION_GET_UINT64(tv);
+	if ((t >> 48) != DUK_TAG_FASTINT) {
+		return tv->d;
+	} else if (t & 0x0000800000000000ULL) {
+		t = (duk_uint64_t) (-((duk_int64_t) t));  /* avoid unary minus on unsigned */
+		t = t & 0x0000ffffffffffffULL;  /* negative */
+		t |= 0xc330000000000000ULL;
+		DUK_DBLUNION_SET_UINT64(&du, t);
+		return du.d + 4503599627370496.0;  /* 1 << 52 */
+	} else if (t != 0) {
+		t &= 0x0000ffffffffffffULL;  /* positive */
+		t |= 0x4330000000000000ULL;
+		DUK_DBLUNION_SET_UINT64(&du, t);
+		return du.d - 4503599627370496.0;  /* 1 << 52 */
+	} else {
+		return 0.0;  /* zero */
+	}
+}
+#endif  /* DUK_USE_FASTINT && DUK_USE_PACKED_TVAL */
 
-#endif  /* DUK_USE_REGEXP_SUPPORT */
+#if 0  /* unused */
+#if defined(DUK_USE_FASTINT) && !defined(DUK_USE_PACKED_TVAL)
+DUK_INTERNAL DUK_ALWAYS_INLINE duk_double_t duk_tval_get_number_unpacked(duk_tval *tv) {
+	duk_double_union du;
+	duk_uint64_t t;
+
+	DUK_ASSERT(tv->t == DUK__TAG_NUMBER || tv->t == DUK_TAG_FASTINT);
+
+	if (tv->t == DUK_TAG_FASTINT) {
+		if (tv->v.fi >= 0) {
+			t = 0x4330000000000000ULL | (duk_uint64_t) tv->v.fi;
+			DUK_DBLUNION_SET_UINT64(&du, t);
+			return du.d - 4503599627370496.0;  /* 1 << 52 */
+		} else {
+			t = 0xc330000000000000ULL | (duk_uint64_t) (-tv->v.fi);
+			DUK_DBLUNION_SET_UINT64(&du, t);
+			return du.d + 4503599627370496.0;  /* 1 << 52 */
+		}
+	} else {
+		return tv->v.d;
+	}
+}
+#endif  /* DUK_USE_FASTINT && DUK_USE_PACKED_TVAL */
+#endif  /* 0 */
+
+#if defined(DUK_USE_FASTINT) && !defined(DUK_USE_PACKED_TVAL)
+DUK_INTERNAL DUK_ALWAYS_INLINE duk_double_t duk_tval_get_number_unpacked_fastint(duk_tval *tv) {
+	duk_double_union du;
+	duk_uint64_t t;
+
+	DUK_ASSERT(tv->t == DUK_TAG_FASTINT);
+
+	if (tv->v.fi >= 0) {
+		t = 0x4330000000000000ULL | (duk_uint64_t) tv->v.fi;
+		DUK_DBLUNION_SET_UINT64(&du, t);
+		return du.d - 4503599627370496.0;  /* 1 << 52 */
+	} else {
+		t = 0xc330000000000000ULL | (duk_uint64_t) (-tv->v.fi);
+		DUK_DBLUNION_SET_UINT64(&du, t);
+		return du.d + 4503599627370496.0;  /* 1 << 52 */
+	}
+}
+#endif  /* DUK_USE_FASTINT && DUK_USE_PACKED_TVAL */
 
+#endif  /* DUK_USE_FASTINT */
 #line 1 "duk_unicode_tables.c"
 /*
  *  Unicode support tables automatically generated during build.
@@ -64409,7 +81974,7 @@ duk_uint16_t duk_unicode_re_ranges_not_wordchar[10] = {
  *  Automatically generated by extract_chars.py, do not edit!
  */
 
-const duk_uint8_t duk_unicode_ids_noa[797] = {
+const duk_uint8_t duk_unicode_ids_noa[791] = {
 249,176,176,80,111,7,47,15,47,254,11,197,191,0,72,2,15,115,66,19,57,2,34,2,
 240,66,244,50,247,185,248,234,241,99,8,241,127,58,240,182,47,31,241,191,21,
 18,245,50,15,1,24,27,35,15,2,2,240,239,15,244,156,15,10,241,26,21,6,240,
@@ -64429,23 +81994,23 @@ const duk_uint8_t duk_unicode_ids_noa[797] = {
 92,98,38,246,96,224,240,44,245,112,80,57,32,68,112,32,32,35,42,51,100,80,
 240,63,25,255,233,107,241,242,241,242,247,87,63,3,241,107,242,106,15,2,240,
 122,98,98,98,98,98,98,98,111,66,15,254,12,146,240,184,132,52,95,70,114,47,
-74,35,111,25,79,78,240,63,11,242,127,0,255,224,244,15,255,0,8,168,15,60,15,
-255,0,64,190,15,38,255,227,127,243,95,30,63,253,79,0,177,240,111,31,240,47,
-9,159,64,241,152,63,87,51,33,240,9,244,39,34,35,47,7,240,255,36,240,15,34,
-243,5,64,240,15,12,191,7,240,191,13,143,31,240,224,242,47,25,240,146,39,
+74,35,111,25,79,78,240,63,11,242,127,0,255,224,244,255,240,0,138,143,60,
+255,240,4,11,239,38,255,227,127,243,95,30,63,253,79,0,177,240,111,31,240,
+47,9,159,64,241,152,63,87,51,33,240,9,244,39,34,35,47,7,240,255,36,240,15,
+34,243,5,64,240,15,12,191,7,240,191,13,143,31,240,224,242,47,25,240,146,39,
 240,111,7,64,111,32,32,65,52,48,32,240,162,241,85,53,53,166,38,248,63,19,
-240,240,255,240,1,169,96,223,7,95,33,255,240,0,255,143,254,2,3,242,227,245,
-175,24,109,70,2,146,194,66,2,18,18,245,207,19,255,224,93,240,79,48,63,38,
-241,171,246,100,47,119,241,111,10,127,10,207,73,69,53,53,50,241,91,47,10,
-47,3,33,46,61,241,79,107,243,127,37,255,223,13,79,33,242,31,15,240,63,11,
-242,127,14,63,20,87,36,241,207,142,255,226,86,83,2,241,194,20,3,240,127,
-156,240,107,240,175,184,15,1,50,34,240,191,30,240,223,117,242,107,240,107,
-240,63,127,243,159,254,42,239,37,243,223,29,255,238,68,255,226,97,248,63,
-83,255,234,145,255,227,33,255,240,2,44,95,254,18,191,255,0,52,187,31,255,0,
-18,242,244,82,243,114,19,3,19,50,178,2,98,243,18,51,114,98,240,194,50,66,4,
-98,255,224,70,63,9,47,9,47,15,47,9,47,15,47,9,47,15,47,9,47,15,47,9,39,255,
-240,1,114,128,255,240,9,92,144,241,176,255,239,39,12,15,206,15,255,0,46,
-214,255,225,16,0,
+240,255,255,0,26,150,223,7,95,33,255,240,0,255,143,254,2,3,242,227,245,175,
+24,109,70,2,146,194,66,2,18,18,245,207,19,255,224,93,240,79,48,63,38,241,
+171,246,100,47,119,241,111,10,127,10,207,73,69,53,53,50,241,91,47,10,47,3,
+33,46,61,241,79,107,243,127,37,255,223,13,79,33,242,31,15,240,63,11,242,
+127,14,63,20,87,36,241,207,142,255,226,86,83,2,241,194,20,3,240,127,156,
+240,107,240,175,184,15,1,50,34,240,191,30,240,223,117,242,107,240,107,240,
+63,127,243,159,254,42,239,37,243,223,29,255,238,68,255,226,97,248,63,83,
+255,234,145,255,227,33,255,240,2,44,95,254,18,191,255,0,52,187,31,255,0,18,
+242,244,82,243,114,19,3,19,50,178,2,98,243,18,51,114,98,240,194,50,66,4,98,
+255,224,70,63,9,47,9,47,15,47,9,47,15,47,9,47,15,47,9,47,15,47,9,39,255,
+240,1,114,143,255,0,149,201,241,191,254,242,124,252,239,255,0,46,214,255,
+225,16,0,
 };
 #else
 /* IdentifierStart production with ASCII and non-BMP excluded */
@@ -64454,7 +82019,7 @@ const duk_uint8_t duk_unicode_ids_noa[797] = {
  *  Automatically generated by extract_chars.py, do not edit!
  */
 
-const duk_uint8_t duk_unicode_ids_noabmp[614] = {
+const duk_uint8_t duk_unicode_ids_noabmp[611] = {
 249,176,176,80,111,7,47,15,47,254,11,197,191,0,72,2,15,115,66,19,57,2,34,2,
 240,66,244,50,247,185,248,234,241,99,8,241,127,58,240,182,47,31,241,191,21,
 18,245,50,15,1,24,27,35,15,2,2,240,239,15,244,156,15,10,241,26,21,6,240,
@@ -64474,14 +82039,14 @@ const duk_uint8_t duk_unicode_ids_noabmp[614] = {
 92,98,38,246,96,224,240,44,245,112,80,57,32,68,112,32,32,35,42,51,100,80,
 240,63,25,255,233,107,241,242,241,242,247,87,63,3,241,107,242,106,15,2,240,
 122,98,98,98,98,98,98,98,111,66,15,254,12,146,240,184,132,52,95,70,114,47,
-74,35,111,25,79,78,240,63,11,242,127,0,255,224,244,15,255,0,8,168,15,60,15,
-255,0,64,190,15,38,255,227,127,243,95,30,63,253,79,0,177,240,111,31,240,47,
-9,159,64,241,152,63,87,51,33,240,9,244,39,34,35,47,7,240,255,36,240,15,34,
-243,5,64,240,15,12,191,7,240,191,13,143,31,240,224,242,47,25,240,146,39,
+74,35,111,25,79,78,240,63,11,242,127,0,255,224,244,255,240,0,138,143,60,
+255,240,4,11,239,38,255,227,127,243,95,30,63,253,79,0,177,240,111,31,240,
+47,9,159,64,241,152,63,87,51,33,240,9,244,39,34,35,47,7,240,255,36,240,15,
+34,243,5,64,240,15,12,191,7,240,191,13,143,31,240,224,242,47,25,240,146,39,
 240,111,7,64,111,32,32,65,52,48,32,240,162,241,85,53,53,166,38,248,63,19,
-240,240,255,240,1,169,96,223,7,95,33,255,240,0,255,143,254,2,3,242,227,245,
-175,24,109,70,2,146,194,66,2,18,18,245,207,19,255,224,93,240,79,48,63,38,
-241,171,246,100,47,119,241,111,10,127,10,207,73,69,53,53,50,0,
+240,255,255,0,26,150,223,7,95,33,255,240,0,255,143,254,2,3,242,227,245,175,
+24,109,70,2,146,194,66,2,18,18,245,207,19,255,224,93,240,79,48,63,38,241,
+171,246,100,47,119,241,111,10,127,10,207,73,69,53,53,50,0,
 };
 #endif
 
@@ -64667,6 +82232,5296 @@ const duk_uint8_t duk_unicode_caseconv_lc[616] = {
 141,2,101,2,2,97,0,52,129,131,128,
 };
 
+#if defined(DUK_USE_REGEXP_CANON_WORKAROUND)
+/*
+ *  Automatically generated by extract_caseconv.py, do not edit!
+ */
+
+const duk_uint16_t duk_unicode_re_canon_lookup[65536] = {
+0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,
+28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,
+53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,
+78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,65,66,67,68,69,70,
+71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,123,124,125,
+126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,
+144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,
+162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,
+180,924,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,
+198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,
+216,217,218,219,220,221,222,223,192,193,194,195,196,197,198,199,200,201,
+202,203,204,205,206,207,208,209,210,211,212,213,214,247,216,217,218,219,
+220,221,222,376,256,256,258,258,260,260,262,262,264,264,266,266,268,268,
+270,270,272,272,274,274,276,276,278,278,280,280,282,282,284,284,286,286,
+288,288,290,290,292,292,294,294,296,296,298,298,300,300,302,302,304,305,
+306,306,308,308,310,310,312,313,313,315,315,317,317,319,319,321,321,323,
+323,325,325,327,327,329,330,330,332,332,334,334,336,336,338,338,340,340,
+342,342,344,344,346,346,348,348,350,350,352,352,354,354,356,356,358,358,
+360,360,362,362,364,364,366,366,368,368,370,370,372,372,374,374,376,377,
+377,379,379,381,381,383,579,385,386,386,388,388,390,391,391,393,394,395,
+395,397,398,399,400,401,401,403,404,502,406,407,408,408,573,411,412,413,
+544,415,416,416,418,418,420,420,422,423,423,425,426,427,428,428,430,431,
+431,433,434,435,435,437,437,439,440,440,442,443,444,444,446,503,448,449,
+450,451,452,452,452,455,455,455,458,458,458,461,461,463,463,465,465,467,
+467,469,469,471,471,473,473,475,475,398,478,478,480,480,482,482,484,484,
+486,486,488,488,490,490,492,492,494,494,496,497,497,497,500,500,502,503,
+504,504,506,506,508,508,510,510,512,512,514,514,516,516,518,518,520,520,
+522,522,524,524,526,526,528,528,530,530,532,532,534,534,536,536,538,538,
+540,540,542,542,544,545,546,546,548,548,550,550,552,552,554,554,556,556,
+558,558,560,560,562,562,564,565,566,567,568,569,570,571,571,573,574,11390,
+11391,577,577,579,580,581,582,582,584,584,586,586,588,588,590,590,11375,
+11373,11376,385,390,597,393,394,600,399,602,400,604,605,606,607,403,609,
+610,404,612,42893,614,615,407,406,618,11362,620,621,622,412,624,11374,413,
+627,628,415,630,631,632,633,634,635,636,11364,638,639,422,641,642,425,644,
+645,646,647,430,580,433,434,581,653,654,655,656,657,439,659,660,661,662,
+663,664,665,666,667,668,669,670,671,672,673,674,675,676,677,678,679,680,
+681,682,683,684,685,686,687,688,689,690,691,692,693,694,695,696,697,698,
+699,700,701,702,703,704,705,706,707,708,709,710,711,712,713,714,715,716,
+717,718,719,720,721,722,723,724,725,726,727,728,729,730,731,732,733,734,
+735,736,737,738,739,740,741,742,743,744,745,746,747,748,749,750,751,752,
+753,754,755,756,757,758,759,760,761,762,763,764,765,766,767,768,769,770,
+771,772,773,774,775,776,777,778,779,780,781,782,783,784,785,786,787,788,
+789,790,791,792,793,794,795,796,797,798,799,800,801,802,803,804,805,806,
+807,808,809,810,811,812,813,814,815,816,817,818,819,820,821,822,823,824,
+825,826,827,828,829,830,831,832,833,834,835,836,921,838,839,840,841,842,
+843,844,845,846,847,848,849,850,851,852,853,854,855,856,857,858,859,860,
+861,862,863,864,865,866,867,868,869,870,871,872,873,874,875,876,877,878,
+879,880,880,882,882,884,885,886,886,888,889,890,1021,1022,1023,894,895,896,
+897,898,899,900,901,902,903,904,905,906,907,908,909,910,911,912,913,914,
+915,916,917,918,919,920,921,922,923,924,925,926,927,928,929,930,931,932,
+933,934,935,936,937,938,939,902,904,905,906,944,913,914,915,916,917,918,
+919,920,921,922,923,924,925,926,927,928,929,931,931,932,933,934,935,936,
+937,938,939,908,910,911,975,914,920,978,979,980,934,928,975,984,984,986,
+986,988,988,990,990,992,992,994,994,996,996,998,998,1000,1000,1002,1002,
+1004,1004,1006,1006,922,929,1017,1011,1012,917,1014,1015,1015,1017,1018,
+1018,1020,1021,1022,1023,1024,1025,1026,1027,1028,1029,1030,1031,1032,1033,
+1034,1035,1036,1037,1038,1039,1040,1041,1042,1043,1044,1045,1046,1047,1048,
+1049,1050,1051,1052,1053,1054,1055,1056,1057,1058,1059,1060,1061,1062,1063,
+1064,1065,1066,1067,1068,1069,1070,1071,1040,1041,1042,1043,1044,1045,1046,
+1047,1048,1049,1050,1051,1052,1053,1054,1055,1056,1057,1058,1059,1060,1061,
+1062,1063,1064,1065,1066,1067,1068,1069,1070,1071,1024,1025,1026,1027,1028,
+1029,1030,1031,1032,1033,1034,1035,1036,1037,1038,1039,1120,1120,1122,1122,
+1124,1124,1126,1126,1128,1128,1130,1130,1132,1132,1134,1134,1136,1136,1138,
+1138,1140,1140,1142,1142,1144,1144,1146,1146,1148,1148,1150,1150,1152,1152,
+1154,1155,1156,1157,1158,1159,1160,1161,1162,1162,1164,1164,1166,1166,1168,
+1168,1170,1170,1172,1172,1174,1174,1176,1176,1178,1178,1180,1180,1182,1182,
+1184,1184,1186,1186,1188,1188,1190,1190,1192,1192,1194,1194,1196,1196,1198,
+1198,1200,1200,1202,1202,1204,1204,1206,1206,1208,1208,1210,1210,1212,1212,
+1214,1214,1216,1217,1217,1219,1219,1221,1221,1223,1223,1225,1225,1227,1227,
+1229,1229,1216,1232,1232,1234,1234,1236,1236,1238,1238,1240,1240,1242,1242,
+1244,1244,1246,1246,1248,1248,1250,1250,1252,1252,1254,1254,1256,1256,1258,
+1258,1260,1260,1262,1262,1264,1264,1266,1266,1268,1268,1270,1270,1272,1272,
+1274,1274,1276,1276,1278,1278,1280,1280,1282,1282,1284,1284,1286,1286,1288,
+1288,1290,1290,1292,1292,1294,1294,1296,1296,1298,1298,1300,1300,1302,1302,
+1304,1304,1306,1306,1308,1308,1310,1310,1312,1312,1314,1314,1316,1316,1318,
+1318,1320,1321,1322,1323,1324,1325,1326,1327,1328,1329,1330,1331,1332,1333,
+1334,1335,1336,1337,1338,1339,1340,1341,1342,1343,1344,1345,1346,1347,1348,
+1349,1350,1351,1352,1353,1354,1355,1356,1357,1358,1359,1360,1361,1362,1363,
+1364,1365,1366,1367,1368,1369,1370,1371,1372,1373,1374,1375,1376,1329,1330,
+1331,1332,1333,1334,1335,1336,1337,1338,1339,1340,1341,1342,1343,1344,1345,
+1346,1347,1348,1349,1350,1351,1352,1353,1354,1355,1356,1357,1358,1359,1360,
+1361,1362,1363,1364,1365,1366,1415,1416,1417,1418,1419,1420,1421,1422,1423,
+1424,1425,1426,1427,1428,1429,1430,1431,1432,1433,1434,1435,1436,1437,1438,
+1439,1440,1441,1442,1443,1444,1445,1446,1447,1448,1449,1450,1451,1452,1453,
+1454,1455,1456,1457,1458,1459,1460,1461,1462,1463,1464,1465,1466,1467,1468,
+1469,1470,1471,1472,1473,1474,1475,1476,1477,1478,1479,1480,1481,1482,1483,
+1484,1485,1486,1487,1488,1489,1490,1491,1492,1493,1494,1495,1496,1497,1498,
+1499,1500,1501,1502,1503,1504,1505,1506,1507,1508,1509,1510,1511,1512,1513,
+1514,1515,1516,1517,1518,1519,1520,1521,1522,1523,1524,1525,1526,1527,1528,
+1529,1530,1531,1532,1533,1534,1535,1536,1537,1538,1539,1540,1541,1542,1543,
+1544,1545,1546,1547,1548,1549,1550,1551,1552,1553,1554,1555,1556,1557,1558,
+1559,1560,1561,1562,1563,1564,1565,1566,1567,1568,1569,1570,1571,1572,1573,
+1574,1575,1576,1577,1578,1579,1580,1581,1582,1583,1584,1585,1586,1587,1588,
+1589,1590,1591,1592,1593,1594,1595,1596,1597,1598,1599,1600,1601,1602,1603,
+1604,1605,1606,1607,1608,1609,1610,1611,1612,1613,1614,1615,1616,1617,1618,
+1619,1620,1621,1622,1623,1624,1625,1626,1627,1628,1629,1630,1631,1632,1633,
+1634,1635,1636,1637,1638,1639,1640,1641,1642,1643,1644,1645,1646,1647,1648,
+1649,1650,1651,1652,1653,1654,1655,1656,1657,1658,1659,1660,1661,1662,1663,
+1664,1665,1666,1667,1668,1669,1670,1671,1672,1673,1674,1675,1676,1677,1678,
+1679,1680,1681,1682,1683,1684,1685,1686,1687,1688,1689,1690,1691,1692,1693,
+1694,1695,1696,1697,1698,1699,1700,1701,1702,1703,1704,1705,1706,1707,1708,
+1709,1710,1711,1712,1713,1714,1715,1716,1717,1718,1719,1720,1721,1722,1723,
+1724,1725,1726,1727,1728,1729,1730,1731,1732,1733,1734,1735,1736,1737,1738,
+1739,1740,1741,1742,1743,1744,1745,1746,1747,1748,1749,1750,1751,1752,1753,
+1754,1755,1756,1757,1758,1759,1760,1761,1762,1763,1764,1765,1766,1767,1768,
+1769,1770,1771,1772,1773,1774,1775,1776,1777,1778,1779,1780,1781,1782,1783,
+1784,1785,1786,1787,1788,1789,1790,1791,1792,1793,1794,1795,1796,1797,1798,
+1799,1800,1801,1802,1803,1804,1805,1806,1807,1808,1809,1810,1811,1812,1813,
+1814,1815,1816,1817,1818,1819,1820,1821,1822,1823,1824,1825,1826,1827,1828,
+1829,1830,1831,1832,1833,1834,1835,1836,1837,1838,1839,1840,1841,1842,1843,
+1844,1845,1846,1847,1848,1849,1850,1851,1852,1853,1854,1855,1856,1857,1858,
+1859,1860,1861,1862,1863,1864,1865,1866,1867,1868,1869,1870,1871,1872,1873,
+1874,1875,1876,1877,1878,1879,1880,1881,1882,1883,1884,1885,1886,1887,1888,
+1889,1890,1891,1892,1893,1894,1895,1896,1897,1898,1899,1900,1901,1902,1903,
+1904,1905,1906,1907,1908,1909,1910,1911,1912,1913,1914,1915,1916,1917,1918,
+1919,1920,1921,1922,1923,1924,1925,1926,1927,1928,1929,1930,1931,1932,1933,
+1934,1935,1936,1937,1938,1939,1940,1941,1942,1943,1944,1945,1946,1947,1948,
+1949,1950,1951,1952,1953,1954,1955,1956,1957,1958,1959,1960,1961,1962,1963,
+1964,1965,1966,1967,1968,1969,1970,1971,1972,1973,1974,1975,1976,1977,1978,
+1979,1980,1981,1982,1983,1984,1985,1986,1987,1988,1989,1990,1991,1992,1993,
+1994,1995,1996,1997,1998,1999,2000,2001,2002,2003,2004,2005,2006,2007,2008,
+2009,2010,2011,2012,2013,2014,2015,2016,2017,2018,2019,2020,2021,2022,2023,
+2024,2025,2026,2027,2028,2029,2030,2031,2032,2033,2034,2035,2036,2037,2038,
+2039,2040,2041,2042,2043,2044,2045,2046,2047,2048,2049,2050,2051,2052,2053,
+2054,2055,2056,2057,2058,2059,2060,2061,2062,2063,2064,2065,2066,2067,2068,
+2069,2070,2071,2072,2073,2074,2075,2076,2077,2078,2079,2080,2081,2082,2083,
+2084,2085,2086,2087,2088,2089,2090,2091,2092,2093,2094,2095,2096,2097,2098,
+2099,2100,2101,2102,2103,2104,2105,2106,2107,2108,2109,2110,2111,2112,2113,
+2114,2115,2116,2117,2118,2119,2120,2121,2122,2123,2124,2125,2126,2127,2128,
+2129,2130,2131,2132,2133,2134,2135,2136,2137,2138,2139,2140,2141,2142,2143,
+2144,2145,2146,2147,2148,2149,2150,2151,2152,2153,2154,2155,2156,2157,2158,
+2159,2160,2161,2162,2163,2164,2165,2166,2167,2168,2169,2170,2171,2172,2173,
+2174,2175,2176,2177,2178,2179,2180,2181,2182,2183,2184,2185,2186,2187,2188,
+2189,2190,2191,2192,2193,2194,2195,2196,2197,2198,2199,2200,2201,2202,2203,
+2204,2205,2206,2207,2208,2209,2210,2211,2212,2213,2214,2215,2216,2217,2218,
+2219,2220,2221,2222,2223,2224,2225,2226,2227,2228,2229,2230,2231,2232,2233,
+2234,2235,2236,2237,2238,2239,2240,2241,2242,2243,2244,2245,2246,2247,2248,
+2249,2250,2251,2252,2253,2254,2255,2256,2257,2258,2259,2260,2261,2262,2263,
+2264,2265,2266,2267,2268,2269,2270,2271,2272,2273,2274,2275,2276,2277,2278,
+2279,2280,2281,2282,2283,2284,2285,2286,2287,2288,2289,2290,2291,2292,2293,
+2294,2295,2296,2297,2298,2299,2300,2301,2302,2303,2304,2305,2306,2307,2308,
+2309,2310,2311,2312,2313,2314,2315,2316,2317,2318,2319,2320,2321,2322,2323,
+2324,2325,2326,2327,2328,2329,2330,2331,2332,2333,2334,2335,2336,2337,2338,
+2339,2340,2341,2342,2343,2344,2345,2346,2347,2348,2349,2350,2351,2352,2353,
+2354,2355,2356,2357,2358,2359,2360,2361,2362,2363,2364,2365,2366,2367,2368,
+2369,2370,2371,2372,2373,2374,2375,2376,2377,2378,2379,2380,2381,2382,2383,
+2384,2385,2386,2387,2388,2389,2390,2391,2392,2393,2394,2395,2396,2397,2398,
+2399,2400,2401,2402,2403,2404,2405,2406,2407,2408,2409,2410,2411,2412,2413,
+2414,2415,2416,2417,2418,2419,2420,2421,2422,2423,2424,2425,2426,2427,2428,
+2429,2430,2431,2432,2433,2434,2435,2436,2437,2438,2439,2440,2441,2442,2443,
+2444,2445,2446,2447,2448,2449,2450,2451,2452,2453,2454,2455,2456,2457,2458,
+2459,2460,2461,2462,2463,2464,2465,2466,2467,2468,2469,2470,2471,2472,2473,
+2474,2475,2476,2477,2478,2479,2480,2481,2482,2483,2484,2485,2486,2487,2488,
+2489,2490,2491,2492,2493,2494,2495,2496,2497,2498,2499,2500,2501,2502,2503,
+2504,2505,2506,2507,2508,2509,2510,2511,2512,2513,2514,2515,2516,2517,2518,
+2519,2520,2521,2522,2523,2524,2525,2526,2527,2528,2529,2530,2531,2532,2533,
+2534,2535,2536,2537,2538,2539,2540,2541,2542,2543,2544,2545,2546,2547,2548,
+2549,2550,2551,2552,2553,2554,2555,2556,2557,2558,2559,2560,2561,2562,2563,
+2564,2565,2566,2567,2568,2569,2570,2571,2572,2573,2574,2575,2576,2577,2578,
+2579,2580,2581,2582,2583,2584,2585,2586,2587,2588,2589,2590,2591,2592,2593,
+2594,2595,2596,2597,2598,2599,2600,2601,2602,2603,2604,2605,2606,2607,2608,
+2609,2610,2611,2612,2613,2614,2615,2616,2617,2618,2619,2620,2621,2622,2623,
+2624,2625,2626,2627,2628,2629,2630,2631,2632,2633,2634,2635,2636,2637,2638,
+2639,2640,2641,2642,2643,2644,2645,2646,2647,2648,2649,2650,2651,2652,2653,
+2654,2655,2656,2657,2658,2659,2660,2661,2662,2663,2664,2665,2666,2667,2668,
+2669,2670,2671,2672,2673,2674,2675,2676,2677,2678,2679,2680,2681,2682,2683,
+2684,2685,2686,2687,2688,2689,2690,2691,2692,2693,2694,2695,2696,2697,2698,
+2699,2700,2701,2702,2703,2704,2705,2706,2707,2708,2709,2710,2711,2712,2713,
+2714,2715,2716,2717,2718,2719,2720,2721,2722,2723,2724,2725,2726,2727,2728,
+2729,2730,2731,2732,2733,2734,2735,2736,2737,2738,2739,2740,2741,2742,2743,
+2744,2745,2746,2747,2748,2749,2750,2751,2752,2753,2754,2755,2756,2757,2758,
+2759,2760,2761,2762,2763,2764,2765,2766,2767,2768,2769,2770,2771,2772,2773,
+2774,2775,2776,2777,2778,2779,2780,2781,2782,2783,2784,2785,2786,2787,2788,
+2789,2790,2791,2792,2793,2794,2795,2796,2797,2798,2799,2800,2801,2802,2803,
+2804,2805,2806,2807,2808,2809,2810,2811,2812,2813,2814,2815,2816,2817,2818,
+2819,2820,2821,2822,2823,2824,2825,2826,2827,2828,2829,2830,2831,2832,2833,
+2834,2835,2836,2837,2838,2839,2840,2841,2842,2843,2844,2845,2846,2847,2848,
+2849,2850,2851,2852,2853,2854,2855,2856,2857,2858,2859,2860,2861,2862,2863,
+2864,2865,2866,2867,2868,2869,2870,2871,2872,2873,2874,2875,2876,2877,2878,
+2879,2880,2881,2882,2883,2884,2885,2886,2887,2888,2889,2890,2891,2892,2893,
+2894,2895,2896,2897,2898,2899,2900,2901,2902,2903,2904,2905,2906,2907,2908,
+2909,2910,2911,2912,2913,2914,2915,2916,2917,2918,2919,2920,2921,2922,2923,
+2924,2925,2926,2927,2928,2929,2930,2931,2932,2933,2934,2935,2936,2937,2938,
+2939,2940,2941,2942,2943,2944,2945,2946,2947,2948,2949,2950,2951,2952,2953,
+2954,2955,2956,2957,2958,2959,2960,2961,2962,2963,2964,2965,2966,2967,2968,
+2969,2970,2971,2972,2973,2974,2975,2976,2977,2978,2979,2980,2981,2982,2983,
+2984,2985,2986,2987,2988,2989,2990,2991,2992,2993,2994,2995,2996,2997,2998,
+2999,3000,3001,3002,3003,3004,3005,3006,3007,3008,3009,3010,3011,3012,3013,
+3014,3015,3016,3017,3018,3019,3020,3021,3022,3023,3024,3025,3026,3027,3028,
+3029,3030,3031,3032,3033,3034,3035,3036,3037,3038,3039,3040,3041,3042,3043,
+3044,3045,3046,3047,3048,3049,3050,3051,3052,3053,3054,3055,3056,3057,3058,
+3059,3060,3061,3062,3063,3064,3065,3066,3067,3068,3069,3070,3071,3072,3073,
+3074,3075,3076,3077,3078,3079,3080,3081,3082,3083,3084,3085,3086,3087,3088,
+3089,3090,3091,3092,3093,3094,3095,3096,3097,3098,3099,3100,3101,3102,3103,
+3104,3105,3106,3107,3108,3109,3110,3111,3112,3113,3114,3115,3116,3117,3118,
+3119,3120,3121,3122,3123,3124,3125,3126,3127,3128,3129,3130,3131,3132,3133,
+3134,3135,3136,3137,3138,3139,3140,3141,3142,3143,3144,3145,3146,3147,3148,
+3149,3150,3151,3152,3153,3154,3155,3156,3157,3158,3159,3160,3161,3162,3163,
+3164,3165,3166,3167,3168,3169,3170,3171,3172,3173,3174,3175,3176,3177,3178,
+3179,3180,3181,3182,3183,3184,3185,3186,3187,3188,3189,3190,3191,3192,3193,
+3194,3195,3196,3197,3198,3199,3200,3201,3202,3203,3204,3205,3206,3207,3208,
+3209,3210,3211,3212,3213,3214,3215,3216,3217,3218,3219,3220,3221,3222,3223,
+3224,3225,3226,3227,3228,3229,3230,3231,3232,3233,3234,3235,3236,3237,3238,
+3239,3240,3241,3242,3243,3244,3245,3246,3247,3248,3249,3250,3251,3252,3253,
+3254,3255,3256,3257,3258,3259,3260,3261,3262,3263,3264,3265,3266,3267,3268,
+3269,3270,3271,3272,3273,3274,3275,3276,3277,3278,3279,3280,3281,3282,3283,
+3284,3285,3286,3287,3288,3289,3290,3291,3292,3293,3294,3295,3296,3297,3298,
+3299,3300,3301,3302,3303,3304,3305,3306,3307,3308,3309,3310,3311,3312,3313,
+3314,3315,3316,3317,3318,3319,3320,3321,3322,3323,3324,3325,3326,3327,3328,
+3329,3330,3331,3332,3333,3334,3335,3336,3337,3338,3339,3340,3341,3342,3343,
+3344,3345,3346,3347,3348,3349,3350,3351,3352,3353,3354,3355,3356,3357,3358,
+3359,3360,3361,3362,3363,3364,3365,3366,3367,3368,3369,3370,3371,3372,3373,
+3374,3375,3376,3377,3378,3379,3380,3381,3382,3383,3384,3385,3386,3387,3388,
+3389,3390,3391,3392,3393,3394,3395,3396,3397,3398,3399,3400,3401,3402,3403,
+3404,3405,3406,3407,3408,3409,3410,3411,3412,3413,3414,3415,3416,3417,3418,
+3419,3420,3421,3422,3423,3424,3425,3426,3427,3428,3429,3430,3431,3432,3433,
+3434,3435,3436,3437,3438,3439,3440,3441,3442,3443,3444,3445,3446,3447,3448,
+3449,3450,3451,3452,3453,3454,3455,3456,3457,3458,3459,3460,3461,3462,3463,
+3464,3465,3466,3467,3468,3469,3470,3471,3472,3473,3474,3475,3476,3477,3478,
+3479,3480,3481,3482,3483,3484,3485,3486,3487,3488,3489,3490,3491,3492,3493,
+3494,3495,3496,3497,3498,3499,3500,3501,3502,3503,3504,3505,3506,3507,3508,
+3509,3510,3511,3512,3513,3514,3515,3516,3517,3518,3519,3520,3521,3522,3523,
+3524,3525,3526,3527,3528,3529,3530,3531,3532,3533,3534,3535,3536,3537,3538,
+3539,3540,3541,3542,3543,3544,3545,3546,3547,3548,3549,3550,3551,3552,3553,
+3554,3555,3556,3557,3558,3559,3560,3561,3562,3563,3564,3565,3566,3567,3568,
+3569,3570,3571,3572,3573,3574,3575,3576,3577,3578,3579,3580,3581,3582,3583,
+3584,3585,3586,3587,3588,3589,3590,3591,3592,3593,3594,3595,3596,3597,3598,
+3599,3600,3601,3602,3603,3604,3605,3606,3607,3608,3609,3610,3611,3612,3613,
+3614,3615,3616,3617,3618,3619,3620,3621,3622,3623,3624,3625,3626,3627,3628,
+3629,3630,3631,3632,3633,3634,3635,3636,3637,3638,3639,3640,3641,3642,3643,
+3644,3645,3646,3647,3648,3649,3650,3651,3652,3653,3654,3655,3656,3657,3658,
+3659,3660,3661,3662,3663,3664,3665,3666,3667,3668,3669,3670,3671,3672,3673,
+3674,3675,3676,3677,3678,3679,3680,3681,3682,3683,3684,3685,3686,3687,3688,
+3689,3690,3691,3692,3693,3694,3695,3696,3697,3698,3699,3700,3701,3702,3703,
+3704,3705,3706,3707,3708,3709,3710,3711,3712,3713,3714,3715,3716,3717,3718,
+3719,3720,3721,3722,3723,3724,3725,3726,3727,3728,3729,3730,3731,3732,3733,
+3734,3735,3736,3737,3738,3739,3740,3741,3742,3743,3744,3745,3746,3747,3748,
+3749,3750,3751,3752,3753,3754,3755,3756,3757,3758,3759,3760,3761,3762,3763,
+3764,3765,3766,3767,3768,3769,3770,3771,3772,3773,3774,3775,3776,3777,3778,
+3779,3780,3781,3782,3783,3784,3785,3786,3787,3788,3789,3790,3791,3792,3793,
+3794,3795,3796,3797,3798,3799,3800,3801,3802,3803,3804,3805,3806,3807,3808,
+3809,3810,3811,3812,3813,3814,3815,3816,3817,3818,3819,3820,3821,3822,3823,
+3824,3825,3826,3827,3828,3829,3830,3831,3832,3833,3834,3835,3836,3837,3838,
+3839,3840,3841,3842,3843,3844,3845,3846,3847,3848,3849,3850,3851,3852,3853,
+3854,3855,3856,3857,3858,3859,3860,3861,3862,3863,3864,3865,3866,3867,3868,
+3869,3870,3871,3872,3873,3874,3875,3876,3877,3878,3879,3880,3881,3882,3883,
+3884,3885,3886,3887,3888,3889,3890,3891,3892,3893,3894,3895,3896,3897,3898,
+3899,3900,3901,3902,3903,3904,3905,3906,3907,3908,3909,3910,3911,3912,3913,
+3914,3915,3916,3917,3918,3919,3920,3921,3922,3923,3924,3925,3926,3927,3928,
+3929,3930,3931,3932,3933,3934,3935,3936,3937,3938,3939,3940,3941,3942,3943,
+3944,3945,3946,3947,3948,3949,3950,3951,3952,3953,3954,3955,3956,3957,3958,
+3959,3960,3961,3962,3963,3964,3965,3966,3967,3968,3969,3970,3971,3972,3973,
+3974,3975,3976,3977,3978,3979,3980,3981,3982,3983,3984,3985,3986,3987,3988,
+3989,3990,3991,3992,3993,3994,3995,3996,3997,3998,3999,4000,4001,4002,4003,
+4004,4005,4006,4007,4008,4009,4010,4011,4012,4013,4014,4015,4016,4017,4018,
+4019,4020,4021,4022,4023,4024,4025,4026,4027,4028,4029,4030,4031,4032,4033,
+4034,4035,4036,4037,4038,4039,4040,4041,4042,4043,4044,4045,4046,4047,4048,
+4049,4050,4051,4052,4053,4054,4055,4056,4057,4058,4059,4060,4061,4062,4063,
+4064,4065,4066,4067,4068,4069,4070,4071,4072,4073,4074,4075,4076,4077,4078,
+4079,4080,4081,4082,4083,4084,4085,4086,4087,4088,4089,4090,4091,4092,4093,
+4094,4095,4096,4097,4098,4099,4100,4101,4102,4103,4104,4105,4106,4107,4108,
+4109,4110,4111,4112,4113,4114,4115,4116,4117,4118,4119,4120,4121,4122,4123,
+4124,4125,4126,4127,4128,4129,4130,4131,4132,4133,4134,4135,4136,4137,4138,
+4139,4140,4141,4142,4143,4144,4145,4146,4147,4148,4149,4150,4151,4152,4153,
+4154,4155,4156,4157,4158,4159,4160,4161,4162,4163,4164,4165,4166,4167,4168,
+4169,4170,4171,4172,4173,4174,4175,4176,4177,4178,4179,4180,4181,4182,4183,
+4184,4185,4186,4187,4188,4189,4190,4191,4192,4193,4194,4195,4196,4197,4198,
+4199,4200,4201,4202,4203,4204,4205,4206,4207,4208,4209,4210,4211,4212,4213,
+4214,4215,4216,4217,4218,4219,4220,4221,4222,4223,4224,4225,4226,4227,4228,
+4229,4230,4231,4232,4233,4234,4235,4236,4237,4238,4239,4240,4241,4242,4243,
+4244,4245,4246,4247,4248,4249,4250,4251,4252,4253,4254,4255,4256,4257,4258,
+4259,4260,4261,4262,4263,4264,4265,4266,4267,4268,4269,4270,4271,4272,4273,
+4274,4275,4276,4277,4278,4279,4280,4281,4282,4283,4284,4285,4286,4287,4288,
+4289,4290,4291,4292,4293,4294,4295,4296,4297,4298,4299,4300,4301,4302,4303,
+4304,4305,4306,4307,4308,4309,4310,4311,4312,4313,4314,4315,4316,4317,4318,
+4319,4320,4321,4322,4323,4324,4325,4326,4327,4328,4329,4330,4331,4332,4333,
+4334,4335,4336,4337,4338,4339,4340,4341,4342,4343,4344,4345,4346,4347,4348,
+4349,4350,4351,4352,4353,4354,4355,4356,4357,4358,4359,4360,4361,4362,4363,
+4364,4365,4366,4367,4368,4369,4370,4371,4372,4373,4374,4375,4376,4377,4378,
+4379,4380,4381,4382,4383,4384,4385,4386,4387,4388,4389,4390,4391,4392,4393,
+4394,4395,4396,4397,4398,4399,4400,4401,4402,4403,4404,4405,4406,4407,4408,
+4409,4410,4411,4412,4413,4414,4415,4416,4417,4418,4419,4420,4421,4422,4423,
+4424,4425,4426,4427,4428,4429,4430,4431,4432,4433,4434,4435,4436,4437,4438,
+4439,4440,4441,4442,4443,4444,4445,4446,4447,4448,4449,4450,4451,4452,4453,
+4454,4455,4456,4457,4458,4459,4460,4461,4462,4463,4464,4465,4466,4467,4468,
+4469,4470,4471,4472,4473,4474,4475,4476,4477,4478,4479,4480,4481,4482,4483,
+4484,4485,4486,4487,4488,4489,4490,4491,4492,4493,4494,4495,4496,4497,4498,
+4499,4500,4501,4502,4503,4504,4505,4506,4507,4508,4509,4510,4511,4512,4513,
+4514,4515,4516,4517,4518,4519,4520,4521,4522,4523,4524,4525,4526,4527,4528,
+4529,4530,4531,4532,4533,4534,4535,4536,4537,4538,4539,4540,4541,4542,4543,
+4544,4545,4546,4547,4548,4549,4550,4551,4552,4553,4554,4555,4556,4557,4558,
+4559,4560,4561,4562,4563,4564,4565,4566,4567,4568,4569,4570,4571,4572,4573,
+4574,4575,4576,4577,4578,4579,4580,4581,4582,4583,4584,4585,4586,4587,4588,
+4589,4590,4591,4592,4593,4594,4595,4596,4597,4598,4599,4600,4601,4602,4603,
+4604,4605,4606,4607,4608,4609,4610,4611,4612,4613,4614,4615,4616,4617,4618,
+4619,4620,4621,4622,4623,4624,4625,4626,4627,4628,4629,4630,4631,4632,4633,
+4634,4635,4636,4637,4638,4639,4640,4641,4642,4643,4644,4645,4646,4647,4648,
+4649,4650,4651,4652,4653,4654,4655,4656,4657,4658,4659,4660,4661,4662,4663,
+4664,4665,4666,4667,4668,4669,4670,4671,4672,4673,4674,4675,4676,4677,4678,
+4679,4680,4681,4682,4683,4684,4685,4686,4687,4688,4689,4690,4691,4692,4693,
+4694,4695,4696,4697,4698,4699,4700,4701,4702,4703,4704,4705,4706,4707,4708,
+4709,4710,4711,4712,4713,4714,4715,4716,4717,4718,4719,4720,4721,4722,4723,
+4724,4725,4726,4727,4728,4729,4730,4731,4732,4733,4734,4735,4736,4737,4738,
+4739,4740,4741,4742,4743,4744,4745,4746,4747,4748,4749,4750,4751,4752,4753,
+4754,4755,4756,4757,4758,4759,4760,4761,4762,4763,4764,4765,4766,4767,4768,
+4769,4770,4771,4772,4773,4774,4775,4776,4777,4778,4779,4780,4781,4782,4783,
+4784,4785,4786,4787,4788,4789,4790,4791,4792,4793,4794,4795,4796,4797,4798,
+4799,4800,4801,4802,4803,4804,4805,4806,4807,4808,4809,4810,4811,4812,4813,
+4814,4815,4816,4817,4818,4819,4820,4821,4822,4823,4824,4825,4826,4827,4828,
+4829,4830,4831,4832,4833,4834,4835,4836,4837,4838,4839,4840,4841,4842,4843,
+4844,4845,4846,4847,4848,4849,4850,4851,4852,4853,4854,4855,4856,4857,4858,
+4859,4860,4861,4862,4863,4864,4865,4866,4867,4868,4869,4870,4871,4872,4873,
+4874,4875,4876,4877,4878,4879,4880,4881,4882,4883,4884,4885,4886,4887,4888,
+4889,4890,4891,4892,4893,4894,4895,4896,4897,4898,4899,4900,4901,4902,4903,
+4904,4905,4906,4907,4908,4909,4910,4911,4912,4913,4914,4915,4916,4917,4918,
+4919,4920,4921,4922,4923,4924,4925,4926,4927,4928,4929,4930,4931,4932,4933,
+4934,4935,4936,4937,4938,4939,4940,4941,4942,4943,4944,4945,4946,4947,4948,
+4949,4950,4951,4952,4953,4954,4955,4956,4957,4958,4959,4960,4961,4962,4963,
+4964,4965,4966,4967,4968,4969,4970,4971,4972,4973,4974,4975,4976,4977,4978,
+4979,4980,4981,4982,4983,4984,4985,4986,4987,4988,4989,4990,4991,4992,4993,
+4994,4995,4996,4997,4998,4999,5000,5001,5002,5003,5004,5005,5006,5007,5008,
+5009,5010,5011,5012,5013,5014,5015,5016,5017,5018,5019,5020,5021,5022,5023,
+5024,5025,5026,5027,5028,5029,5030,5031,5032,5033,5034,5035,5036,5037,5038,
+5039,5040,5041,5042,5043,5044,5045,5046,5047,5048,5049,5050,5051,5052,5053,
+5054,5055,5056,5057,5058,5059,5060,5061,5062,5063,5064,5065,5066,5067,5068,
+5069,5070,5071,5072,5073,5074,5075,5076,5077,5078,5079,5080,5081,5082,5083,
+5084,5085,5086,5087,5088,5089,5090,5091,5092,5093,5094,5095,5096,5097,5098,
+5099,5100,5101,5102,5103,5104,5105,5106,5107,5108,5109,5110,5111,5112,5113,
+5114,5115,5116,5117,5118,5119,5120,5121,5122,5123,5124,5125,5126,5127,5128,
+5129,5130,5131,5132,5133,5134,5135,5136,5137,5138,5139,5140,5141,5142,5143,
+5144,5145,5146,5147,5148,5149,5150,5151,5152,5153,5154,5155,5156,5157,5158,
+5159,5160,5161,5162,5163,5164,5165,5166,5167,5168,5169,5170,5171,5172,5173,
+5174,5175,5176,5177,5178,5179,5180,5181,5182,5183,5184,5185,5186,5187,5188,
+5189,5190,5191,5192,5193,5194,5195,5196,5197,5198,5199,5200,5201,5202,5203,
+5204,5205,5206,5207,5208,5209,5210,5211,5212,5213,5214,5215,5216,5217,5218,
+5219,5220,5221,5222,5223,5224,5225,5226,5227,5228,5229,5230,5231,5232,5233,
+5234,5235,5236,5237,5238,5239,5240,5241,5242,5243,5244,5245,5246,5247,5248,
+5249,5250,5251,5252,5253,5254,5255,5256,5257,5258,5259,5260,5261,5262,5263,
+5264,5265,5266,5267,5268,5269,5270,5271,5272,5273,5274,5275,5276,5277,5278,
+5279,5280,5281,5282,5283,5284,5285,5286,5287,5288,5289,5290,5291,5292,5293,
+5294,5295,5296,5297,5298,5299,5300,5301,5302,5303,5304,5305,5306,5307,5308,
+5309,5310,5311,5312,5313,5314,5315,5316,5317,5318,5319,5320,5321,5322,5323,
+5324,5325,5326,5327,5328,5329,5330,5331,5332,5333,5334,5335,5336,5337,5338,
+5339,5340,5341,5342,5343,5344,5345,5346,5347,5348,5349,5350,5351,5352,5353,
+5354,5355,5356,5357,5358,5359,5360,5361,5362,5363,5364,5365,5366,5367,5368,
+5369,5370,5371,5372,5373,5374,5375,5376,5377,5378,5379,5380,5381,5382,5383,
+5384,5385,5386,5387,5388,5389,5390,5391,5392,5393,5394,5395,5396,5397,5398,
+5399,5400,5401,5402,5403,5404,5405,5406,5407,5408,5409,5410,5411,5412,5413,
+5414,5415,5416,5417,5418,5419,5420,5421,5422,5423,5424,5425,5426,5427,5428,
+5429,5430,5431,5432,5433,5434,5435,5436,5437,5438,5439,5440,5441,5442,5443,
+5444,5445,5446,5447,5448,5449,5450,5451,5452,5453,5454,5455,5456,5457,5458,
+5459,5460,5461,5462,5463,5464,5465,5466,5467,5468,5469,5470,5471,5472,5473,
+5474,5475,5476,5477,5478,5479,5480,5481,5482,5483,5484,5485,5486,5487,5488,
+5489,5490,5491,5492,5493,5494,5495,5496,5497,5498,5499,5500,5501,5502,5503,
+5504,5505,5506,5507,5508,5509,5510,5511,5512,5513,5514,5515,5516,5517,5518,
+5519,5520,5521,5522,5523,5524,5525,5526,5527,5528,5529,5530,5531,5532,5533,
+5534,5535,5536,5537,5538,5539,5540,5541,5542,5543,5544,5545,5546,5547,5548,
+5549,5550,5551,5552,5553,5554,5555,5556,5557,5558,5559,5560,5561,5562,5563,
+5564,5565,5566,5567,5568,5569,5570,5571,5572,5573,5574,5575,5576,5577,5578,
+5579,5580,5581,5582,5583,5584,5585,5586,5587,5588,5589,5590,5591,5592,5593,
+5594,5595,5596,5597,5598,5599,5600,5601,5602,5603,5604,5605,5606,5607,5608,
+5609,5610,5611,5612,5613,5614,5615,5616,5617,5618,5619,5620,5621,5622,5623,
+5624,5625,5626,5627,5628,5629,5630,5631,5632,5633,5634,5635,5636,5637,5638,
+5639,5640,5641,5642,5643,5644,5645,5646,5647,5648,5649,5650,5651,5652,5653,
+5654,5655,5656,5657,5658,5659,5660,5661,5662,5663,5664,5665,5666,5667,5668,
+5669,5670,5671,5672,5673,5674,5675,5676,5677,5678,5679,5680,5681,5682,5683,
+5684,5685,5686,5687,5688,5689,5690,5691,5692,5693,5694,5695,5696,5697,5698,
+5699,5700,5701,5702,5703,5704,5705,5706,5707,5708,5709,5710,5711,5712,5713,
+5714,5715,5716,5717,5718,5719,5720,5721,5722,5723,5724,5725,5726,5727,5728,
+5729,5730,5731,5732,5733,5734,5735,5736,5737,5738,5739,5740,5741,5742,5743,
+5744,5745,5746,5747,5748,5749,5750,5751,5752,5753,5754,5755,5756,5757,5758,
+5759,5760,5761,5762,5763,5764,5765,5766,5767,5768,5769,5770,5771,5772,5773,
+5774,5775,5776,5777,5778,5779,5780,5781,5782,5783,5784,5785,5786,5787,5788,
+5789,5790,5791,5792,5793,5794,5795,5796,5797,5798,5799,5800,5801,5802,5803,
+5804,5805,5806,5807,5808,5809,5810,5811,5812,5813,5814,5815,5816,5817,5818,
+5819,5820,5821,5822,5823,5824,5825,5826,5827,5828,5829,5830,5831,5832,5833,
+5834,5835,5836,5837,5838,5839,5840,5841,5842,5843,5844,5845,5846,5847,5848,
+5849,5850,5851,5852,5853,5854,5855,5856,5857,5858,5859,5860,5861,5862,5863,
+5864,5865,5866,5867,5868,5869,5870,5871,5872,5873,5874,5875,5876,5877,5878,
+5879,5880,5881,5882,5883,5884,5885,5886,5887,5888,5889,5890,5891,5892,5893,
+5894,5895,5896,5897,5898,5899,5900,5901,5902,5903,5904,5905,5906,5907,5908,
+5909,5910,5911,5912,5913,5914,5915,5916,5917,5918,5919,5920,5921,5922,5923,
+5924,5925,5926,5927,5928,5929,5930,5931,5932,5933,5934,5935,5936,5937,5938,
+5939,5940,5941,5942,5943,5944,5945,5946,5947,5948,5949,5950,5951,5952,5953,
+5954,5955,5956,5957,5958,5959,5960,5961,5962,5963,5964,5965,5966,5967,5968,
+5969,5970,5971,5972,5973,5974,5975,5976,5977,5978,5979,5980,5981,5982,5983,
+5984,5985,5986,5987,5988,5989,5990,5991,5992,5993,5994,5995,5996,5997,5998,
+5999,6000,6001,6002,6003,6004,6005,6006,6007,6008,6009,6010,6011,6012,6013,
+6014,6015,6016,6017,6018,6019,6020,6021,6022,6023,6024,6025,6026,6027,6028,
+6029,6030,6031,6032,6033,6034,6035,6036,6037,6038,6039,6040,6041,6042,6043,
+6044,6045,6046,6047,6048,6049,6050,6051,6052,6053,6054,6055,6056,6057,6058,
+6059,6060,6061,6062,6063,6064,6065,6066,6067,6068,6069,6070,6071,6072,6073,
+6074,6075,6076,6077,6078,6079,6080,6081,6082,6083,6084,6085,6086,6087,6088,
+6089,6090,6091,6092,6093,6094,6095,6096,6097,6098,6099,6100,6101,6102,6103,
+6104,6105,6106,6107,6108,6109,6110,6111,6112,6113,6114,6115,6116,6117,6118,
+6119,6120,6121,6122,6123,6124,6125,6126,6127,6128,6129,6130,6131,6132,6133,
+6134,6135,6136,6137,6138,6139,6140,6141,6142,6143,6144,6145,6146,6147,6148,
+6149,6150,6151,6152,6153,6154,6155,6156,6157,6158,6159,6160,6161,6162,6163,
+6164,6165,6166,6167,6168,6169,6170,6171,6172,6173,6174,6175,6176,6177,6178,
+6179,6180,6181,6182,6183,6184,6185,6186,6187,6188,6189,6190,6191,6192,6193,
+6194,6195,6196,6197,6198,6199,6200,6201,6202,6203,6204,6205,6206,6207,6208,
+6209,6210,6211,6212,6213,6214,6215,6216,6217,6218,6219,6220,6221,6222,6223,
+6224,6225,6226,6227,6228,6229,6230,6231,6232,6233,6234,6235,6236,6237,6238,
+6239,6240,6241,6242,6243,6244,6245,6246,6247,6248,6249,6250,6251,6252,6253,
+6254,6255,6256,6257,6258,6259,6260,6261,6262,6263,6264,6265,6266,6267,6268,
+6269,6270,6271,6272,6273,6274,6275,6276,6277,6278,6279,6280,6281,6282,6283,
+6284,6285,6286,6287,6288,6289,6290,6291,6292,6293,6294,6295,6296,6297,6298,
+6299,6300,6301,6302,6303,6304,6305,6306,6307,6308,6309,6310,6311,6312,6313,
+6314,6315,6316,6317,6318,6319,6320,6321,6322,6323,6324,6325,6326,6327,6328,
+6329,6330,6331,6332,6333,6334,6335,6336,6337,6338,6339,6340,6341,6342,6343,
+6344,6345,6346,6347,6348,6349,6350,6351,6352,6353,6354,6355,6356,6357,6358,
+6359,6360,6361,6362,6363,6364,6365,6366,6367,6368,6369,6370,6371,6372,6373,
+6374,6375,6376,6377,6378,6379,6380,6381,6382,6383,6384,6385,6386,6387,6388,
+6389,6390,6391,6392,6393,6394,6395,6396,6397,6398,6399,6400,6401,6402,6403,
+6404,6405,6406,6407,6408,6409,6410,6411,6412,6413,6414,6415,6416,6417,6418,
+6419,6420,6421,6422,6423,6424,6425,6426,6427,6428,6429,6430,6431,6432,6433,
+6434,6435,6436,6437,6438,6439,6440,6441,6442,6443,6444,6445,6446,6447,6448,
+6449,6450,6451,6452,6453,6454,6455,6456,6457,6458,6459,6460,6461,6462,6463,
+6464,6465,6466,6467,6468,6469,6470,6471,6472,6473,6474,6475,6476,6477,6478,
+6479,6480,6481,6482,6483,6484,6485,6486,6487,6488,6489,6490,6491,6492,6493,
+6494,6495,6496,6497,6498,6499,6500,6501,6502,6503,6504,6505,6506,6507,6508,
+6509,6510,6511,6512,6513,6514,6515,6516,6517,6518,6519,6520,6521,6522,6523,
+6524,6525,6526,6527,6528,6529,6530,6531,6532,6533,6534,6535,6536,6537,6538,
+6539,6540,6541,6542,6543,6544,6545,6546,6547,6548,6549,6550,6551,6552,6553,
+6554,6555,6556,6557,6558,6559,6560,6561,6562,6563,6564,6565,6566,6567,6568,
+6569,6570,6571,6572,6573,6574,6575,6576,6577,6578,6579,6580,6581,6582,6583,
+6584,6585,6586,6587,6588,6589,6590,6591,6592,6593,6594,6595,6596,6597,6598,
+6599,6600,6601,6602,6603,6604,6605,6606,6607,6608,6609,6610,6611,6612,6613,
+6614,6615,6616,6617,6618,6619,6620,6621,6622,6623,6624,6625,6626,6627,6628,
+6629,6630,6631,6632,6633,6634,6635,6636,6637,6638,6639,6640,6641,6642,6643,
+6644,6645,6646,6647,6648,6649,6650,6651,6652,6653,6654,6655,6656,6657,6658,
+6659,6660,6661,6662,6663,6664,6665,6666,6667,6668,6669,6670,6671,6672,6673,
+6674,6675,6676,6677,6678,6679,6680,6681,6682,6683,6684,6685,6686,6687,6688,
+6689,6690,6691,6692,6693,6694,6695,6696,6697,6698,6699,6700,6701,6702,6703,
+6704,6705,6706,6707,6708,6709,6710,6711,6712,6713,6714,6715,6716,6717,6718,
+6719,6720,6721,6722,6723,6724,6725,6726,6727,6728,6729,6730,6731,6732,6733,
+6734,6735,6736,6737,6738,6739,6740,6741,6742,6743,6744,6745,6746,6747,6748,
+6749,6750,6751,6752,6753,6754,6755,6756,6757,6758,6759,6760,6761,6762,6763,
+6764,6765,6766,6767,6768,6769,6770,6771,6772,6773,6774,6775,6776,6777,6778,
+6779,6780,6781,6782,6783,6784,6785,6786,6787,6788,6789,6790,6791,6792,6793,
+6794,6795,6796,6797,6798,6799,6800,6801,6802,6803,6804,6805,6806,6807,6808,
+6809,6810,6811,6812,6813,6814,6815,6816,6817,6818,6819,6820,6821,6822,6823,
+6824,6825,6826,6827,6828,6829,6830,6831,6832,6833,6834,6835,6836,6837,6838,
+6839,6840,6841,6842,6843,6844,6845,6846,6847,6848,6849,6850,6851,6852,6853,
+6854,6855,6856,6857,6858,6859,6860,6861,6862,6863,6864,6865,6866,6867,6868,
+6869,6870,6871,6872,6873,6874,6875,6876,6877,6878,6879,6880,6881,6882,6883,
+6884,6885,6886,6887,6888,6889,6890,6891,6892,6893,6894,6895,6896,6897,6898,
+6899,6900,6901,6902,6903,6904,6905,6906,6907,6908,6909,6910,6911,6912,6913,
+6914,6915,6916,6917,6918,6919,6920,6921,6922,6923,6924,6925,6926,6927,6928,
+6929,6930,6931,6932,6933,6934,6935,6936,6937,6938,6939,6940,6941,6942,6943,
+6944,6945,6946,6947,6948,6949,6950,6951,6952,6953,6954,6955,6956,6957,6958,
+6959,6960,6961,6962,6963,6964,6965,6966,6967,6968,6969,6970,6971,6972,6973,
+6974,6975,6976,6977,6978,6979,6980,6981,6982,6983,6984,6985,6986,6987,6988,
+6989,6990,6991,6992,6993,6994,6995,6996,6997,6998,6999,7000,7001,7002,7003,
+7004,7005,7006,7007,7008,7009,7010,7011,7012,7013,7014,7015,7016,7017,7018,
+7019,7020,7021,7022,7023,7024,7025,7026,7027,7028,7029,7030,7031,7032,7033,
+7034,7035,7036,7037,7038,7039,7040,7041,7042,7043,7044,7045,7046,7047,7048,
+7049,7050,7051,7052,7053,7054,7055,7056,7057,7058,7059,7060,7061,7062,7063,
+7064,7065,7066,7067,7068,7069,7070,7071,7072,7073,7074,7075,7076,7077,7078,
+7079,7080,7081,7082,7083,7084,7085,7086,7087,7088,7089,7090,7091,7092,7093,
+7094,7095,7096,7097,7098,7099,7100,7101,7102,7103,7104,7105,7106,7107,7108,
+7109,7110,7111,7112,7113,7114,7115,7116,7117,7118,7119,7120,7121,7122,7123,
+7124,7125,7126,7127,7128,7129,7130,7131,7132,7133,7134,7135,7136,7137,7138,
+7139,7140,7141,7142,7143,7144,7145,7146,7147,7148,7149,7150,7151,7152,7153,
+7154,7155,7156,7157,7158,7159,7160,7161,7162,7163,7164,7165,7166,7167,7168,
+7169,7170,7171,7172,7173,7174,7175,7176,7177,7178,7179,7180,7181,7182,7183,
+7184,7185,7186,7187,7188,7189,7190,7191,7192,7193,7194,7195,7196,7197,7198,
+7199,7200,7201,7202,7203,7204,7205,7206,7207,7208,7209,7210,7211,7212,7213,
+7214,7215,7216,7217,7218,7219,7220,7221,7222,7223,7224,7225,7226,7227,7228,
+7229,7230,7231,7232,7233,7234,7235,7236,7237,7238,7239,7240,7241,7242,7243,
+7244,7245,7246,7247,7248,7249,7250,7251,7252,7253,7254,7255,7256,7257,7258,
+7259,7260,7261,7262,7263,7264,7265,7266,7267,7268,7269,7270,7271,7272,7273,
+7274,7275,7276,7277,7278,7279,7280,7281,7282,7283,7284,7285,7286,7287,7288,
+7289,7290,7291,7292,7293,7294,7295,7296,7297,7298,7299,7300,7301,7302,7303,
+7304,7305,7306,7307,7308,7309,7310,7311,7312,7313,7314,7315,7316,7317,7318,
+7319,7320,7321,7322,7323,7324,7325,7326,7327,7328,7329,7330,7331,7332,7333,
+7334,7335,7336,7337,7338,7339,7340,7341,7342,7343,7344,7345,7346,7347,7348,
+7349,7350,7351,7352,7353,7354,7355,7356,7357,7358,7359,7360,7361,7362,7363,
+7364,7365,7366,7367,7368,7369,7370,7371,7372,7373,7374,7375,7376,7377,7378,
+7379,7380,7381,7382,7383,7384,7385,7386,7387,7388,7389,7390,7391,7392,7393,
+7394,7395,7396,7397,7398,7399,7400,7401,7402,7403,7404,7405,7406,7407,7408,
+7409,7410,7411,7412,7413,7414,7415,7416,7417,7418,7419,7420,7421,7422,7423,
+7424,7425,7426,7427,7428,7429,7430,7431,7432,7433,7434,7435,7436,7437,7438,
+7439,7440,7441,7442,7443,7444,7445,7446,7447,7448,7449,7450,7451,7452,7453,
+7454,7455,7456,7457,7458,7459,7460,7461,7462,7463,7464,7465,7466,7467,7468,
+7469,7470,7471,7472,7473,7474,7475,7476,7477,7478,7479,7480,7481,7482,7483,
+7484,7485,7486,7487,7488,7489,7490,7491,7492,7493,7494,7495,7496,7497,7498,
+7499,7500,7501,7502,7503,7504,7505,7506,7507,7508,7509,7510,7511,7512,7513,
+7514,7515,7516,7517,7518,7519,7520,7521,7522,7523,7524,7525,7526,7527,7528,
+7529,7530,7531,7532,7533,7534,7535,7536,7537,7538,7539,7540,7541,7542,7543,
+7544,42877,7546,7547,7548,11363,7550,7551,7552,7553,7554,7555,7556,7557,
+7558,7559,7560,7561,7562,7563,7564,7565,7566,7567,7568,7569,7570,7571,7572,
+7573,7574,7575,7576,7577,7578,7579,7580,7581,7582,7583,7584,7585,7586,7587,
+7588,7589,7590,7591,7592,7593,7594,7595,7596,7597,7598,7599,7600,7601,7602,
+7603,7604,7605,7606,7607,7608,7609,7610,7611,7612,7613,7614,7615,7616,7617,
+7618,7619,7620,7621,7622,7623,7624,7625,7626,7627,7628,7629,7630,7631,7632,
+7633,7634,7635,7636,7637,7638,7639,7640,7641,7642,7643,7644,7645,7646,7647,
+7648,7649,7650,7651,7652,7653,7654,7655,7656,7657,7658,7659,7660,7661,7662,
+7663,7664,7665,7666,7667,7668,7669,7670,7671,7672,7673,7674,7675,7676,7677,
+7678,7679,7680,7680,7682,7682,7684,7684,7686,7686,7688,7688,7690,7690,7692,
+7692,7694,7694,7696,7696,7698,7698,7700,7700,7702,7702,7704,7704,7706,7706,
+7708,7708,7710,7710,7712,7712,7714,7714,7716,7716,7718,7718,7720,7720,7722,
+7722,7724,7724,7726,7726,7728,7728,7730,7730,7732,7732,7734,7734,7736,7736,
+7738,7738,7740,7740,7742,7742,7744,7744,7746,7746,7748,7748,7750,7750,7752,
+7752,7754,7754,7756,7756,7758,7758,7760,7760,7762,7762,7764,7764,7766,7766,
+7768,7768,7770,7770,7772,7772,7774,7774,7776,7776,7778,7778,7780,7780,7782,
+7782,7784,7784,7786,7786,7788,7788,7790,7790,7792,7792,7794,7794,7796,7796,
+7798,7798,7800,7800,7802,7802,7804,7804,7806,7806,7808,7808,7810,7810,7812,
+7812,7814,7814,7816,7816,7818,7818,7820,7820,7822,7822,7824,7824,7826,7826,
+7828,7828,7830,7831,7832,7833,7834,7776,7836,7837,7838,7839,7840,7840,7842,
+7842,7844,7844,7846,7846,7848,7848,7850,7850,7852,7852,7854,7854,7856,7856,
+7858,7858,7860,7860,7862,7862,7864,7864,7866,7866,7868,7868,7870,7870,7872,
+7872,7874,7874,7876,7876,7878,7878,7880,7880,7882,7882,7884,7884,7886,7886,
+7888,7888,7890,7890,7892,7892,7894,7894,7896,7896,7898,7898,7900,7900,7902,
+7902,7904,7904,7906,7906,7908,7908,7910,7910,7912,7912,7914,7914,7916,7916,
+7918,7918,7920,7920,7922,7922,7924,7924,7926,7926,7928,7928,7930,7930,7932,
+7932,7934,7934,7944,7945,7946,7947,7948,7949,7950,7951,7944,7945,7946,7947,
+7948,7949,7950,7951,7960,7961,7962,7963,7964,7965,7958,7959,7960,7961,7962,
+7963,7964,7965,7966,7967,7976,7977,7978,7979,7980,7981,7982,7983,7976,7977,
+7978,7979,7980,7981,7982,7983,7992,7993,7994,7995,7996,7997,7998,7999,7992,
+7993,7994,7995,7996,7997,7998,7999,8008,8009,8010,8011,8012,8013,8006,8007,
+8008,8009,8010,8011,8012,8013,8014,8015,8016,8025,8018,8027,8020,8029,8022,
+8031,8024,8025,8026,8027,8028,8029,8030,8031,8040,8041,8042,8043,8044,8045,
+8046,8047,8040,8041,8042,8043,8044,8045,8046,8047,8122,8123,8136,8137,8138,
+8139,8154,8155,8184,8185,8170,8171,8186,8187,8062,8063,8064,8065,8066,8067,
+8068,8069,8070,8071,8072,8073,8074,8075,8076,8077,8078,8079,8080,8081,8082,
+8083,8084,8085,8086,8087,8088,8089,8090,8091,8092,8093,8094,8095,8096,8097,
+8098,8099,8100,8101,8102,8103,8104,8105,8106,8107,8108,8109,8110,8111,8120,
+8121,8114,8115,8116,8117,8118,8119,8120,8121,8122,8123,8124,8125,921,8127,
+8128,8129,8130,8131,8132,8133,8134,8135,8136,8137,8138,8139,8140,8141,8142,
+8143,8152,8153,8146,8147,8148,8149,8150,8151,8152,8153,8154,8155,8156,8157,
+8158,8159,8168,8169,8162,8163,8164,8172,8166,8167,8168,8169,8170,8171,8172,
+8173,8174,8175,8176,8177,8178,8179,8180,8181,8182,8183,8184,8185,8186,8187,
+8188,8189,8190,8191,8192,8193,8194,8195,8196,8197,8198,8199,8200,8201,8202,
+8203,8204,8205,8206,8207,8208,8209,8210,8211,8212,8213,8214,8215,8216,8217,
+8218,8219,8220,8221,8222,8223,8224,8225,8226,8227,8228,8229,8230,8231,8232,
+8233,8234,8235,8236,8237,8238,8239,8240,8241,8242,8243,8244,8245,8246,8247,
+8248,8249,8250,8251,8252,8253,8254,8255,8256,8257,8258,8259,8260,8261,8262,
+8263,8264,8265,8266,8267,8268,8269,8270,8271,8272,8273,8274,8275,8276,8277,
+8278,8279,8280,8281,8282,8283,8284,8285,8286,8287,8288,8289,8290,8291,8292,
+8293,8294,8295,8296,8297,8298,8299,8300,8301,8302,8303,8304,8305,8306,8307,
+8308,8309,8310,8311,8312,8313,8314,8315,8316,8317,8318,8319,8320,8321,8322,
+8323,8324,8325,8326,8327,8328,8329,8330,8331,8332,8333,8334,8335,8336,8337,
+8338,8339,8340,8341,8342,8343,8344,8345,8346,8347,8348,8349,8350,8351,8352,
+8353,8354,8355,8356,8357,8358,8359,8360,8361,8362,8363,8364,8365,8366,8367,
+8368,8369,8370,8371,8372,8373,8374,8375,8376,8377,8378,8379,8380,8381,8382,
+8383,8384,8385,8386,8387,8388,8389,8390,8391,8392,8393,8394,8395,8396,8397,
+8398,8399,8400,8401,8402,8403,8404,8405,8406,8407,8408,8409,8410,8411,8412,
+8413,8414,8415,8416,8417,8418,8419,8420,8421,8422,8423,8424,8425,8426,8427,
+8428,8429,8430,8431,8432,8433,8434,8435,8436,8437,8438,8439,8440,8441,8442,
+8443,8444,8445,8446,8447,8448,8449,8450,8451,8452,8453,8454,8455,8456,8457,
+8458,8459,8460,8461,8462,8463,8464,8465,8466,8467,8468,8469,8470,8471,8472,
+8473,8474,8475,8476,8477,8478,8479,8480,8481,8482,8483,8484,8485,8486,8487,
+8488,8489,8490,8491,8492,8493,8494,8495,8496,8497,8498,8499,8500,8501,8502,
+8503,8504,8505,8506,8507,8508,8509,8510,8511,8512,8513,8514,8515,8516,8517,
+8518,8519,8520,8521,8522,8523,8524,8525,8498,8527,8528,8529,8530,8531,8532,
+8533,8534,8535,8536,8537,8538,8539,8540,8541,8542,8543,8544,8545,8546,8547,
+8548,8549,8550,8551,8552,8553,8554,8555,8556,8557,8558,8559,8544,8545,8546,
+8547,8548,8549,8550,8551,8552,8553,8554,8555,8556,8557,8558,8559,8576,8577,
+8578,8579,8579,8581,8582,8583,8584,8585,8586,8587,8588,8589,8590,8591,8592,
+8593,8594,8595,8596,8597,8598,8599,8600,8601,8602,8603,8604,8605,8606,8607,
+8608,8609,8610,8611,8612,8613,8614,8615,8616,8617,8618,8619,8620,8621,8622,
+8623,8624,8625,8626,8627,8628,8629,8630,8631,8632,8633,8634,8635,8636,8637,
+8638,8639,8640,8641,8642,8643,8644,8645,8646,8647,8648,8649,8650,8651,8652,
+8653,8654,8655,8656,8657,8658,8659,8660,8661,8662,8663,8664,8665,8666,8667,
+8668,8669,8670,8671,8672,8673,8674,8675,8676,8677,8678,8679,8680,8681,8682,
+8683,8684,8685,8686,8687,8688,8689,8690,8691,8692,8693,8694,8695,8696,8697,
+8698,8699,8700,8701,8702,8703,8704,8705,8706,8707,8708,8709,8710,8711,8712,
+8713,8714,8715,8716,8717,8718,8719,8720,8721,8722,8723,8724,8725,8726,8727,
+8728,8729,8730,8731,8732,8733,8734,8735,8736,8737,8738,8739,8740,8741,8742,
+8743,8744,8745,8746,8747,8748,8749,8750,8751,8752,8753,8754,8755,8756,8757,
+8758,8759,8760,8761,8762,8763,8764,8765,8766,8767,8768,8769,8770,8771,8772,
+8773,8774,8775,8776,8777,8778,8779,8780,8781,8782,8783,8784,8785,8786,8787,
+8788,8789,8790,8791,8792,8793,8794,8795,8796,8797,8798,8799,8800,8801,8802,
+8803,8804,8805,8806,8807,8808,8809,8810,8811,8812,8813,8814,8815,8816,8817,
+8818,8819,8820,8821,8822,8823,8824,8825,8826,8827,8828,8829,8830,8831,8832,
+8833,8834,8835,8836,8837,8838,8839,8840,8841,8842,8843,8844,8845,8846,8847,
+8848,8849,8850,8851,8852,8853,8854,8855,8856,8857,8858,8859,8860,8861,8862,
+8863,8864,8865,8866,8867,8868,8869,8870,8871,8872,8873,8874,8875,8876,8877,
+8878,8879,8880,8881,8882,8883,8884,8885,8886,8887,8888,8889,8890,8891,8892,
+8893,8894,8895,8896,8897,8898,8899,8900,8901,8902,8903,8904,8905,8906,8907,
+8908,8909,8910,8911,8912,8913,8914,8915,8916,8917,8918,8919,8920,8921,8922,
+8923,8924,8925,8926,8927,8928,8929,8930,8931,8932,8933,8934,8935,8936,8937,
+8938,8939,8940,8941,8942,8943,8944,8945,8946,8947,8948,8949,8950,8951,8952,
+8953,8954,8955,8956,8957,8958,8959,8960,8961,8962,8963,8964,8965,8966,8967,
+8968,8969,8970,8971,8972,8973,8974,8975,8976,8977,8978,8979,8980,8981,8982,
+8983,8984,8985,8986,8987,8988,8989,8990,8991,8992,8993,8994,8995,8996,8997,
+8998,8999,9000,9001,9002,9003,9004,9005,9006,9007,9008,9009,9010,9011,9012,
+9013,9014,9015,9016,9017,9018,9019,9020,9021,9022,9023,9024,9025,9026,9027,
+9028,9029,9030,9031,9032,9033,9034,9035,9036,9037,9038,9039,9040,9041,9042,
+9043,9044,9045,9046,9047,9048,9049,9050,9051,9052,9053,9054,9055,9056,9057,
+9058,9059,9060,9061,9062,9063,9064,9065,9066,9067,9068,9069,9070,9071,9072,
+9073,9074,9075,9076,9077,9078,9079,9080,9081,9082,9083,9084,9085,9086,9087,
+9088,9089,9090,9091,9092,9093,9094,9095,9096,9097,9098,9099,9100,9101,9102,
+9103,9104,9105,9106,9107,9108,9109,9110,9111,9112,9113,9114,9115,9116,9117,
+9118,9119,9120,9121,9122,9123,9124,9125,9126,9127,9128,9129,9130,9131,9132,
+9133,9134,9135,9136,9137,9138,9139,9140,9141,9142,9143,9144,9145,9146,9147,
+9148,9149,9150,9151,9152,9153,9154,9155,9156,9157,9158,9159,9160,9161,9162,
+9163,9164,9165,9166,9167,9168,9169,9170,9171,9172,9173,9174,9175,9176,9177,
+9178,9179,9180,9181,9182,9183,9184,9185,9186,9187,9188,9189,9190,9191,9192,
+9193,9194,9195,9196,9197,9198,9199,9200,9201,9202,9203,9204,9205,9206,9207,
+9208,9209,9210,9211,9212,9213,9214,9215,9216,9217,9218,9219,9220,9221,9222,
+9223,9224,9225,9226,9227,9228,9229,9230,9231,9232,9233,9234,9235,9236,9237,
+9238,9239,9240,9241,9242,9243,9244,9245,9246,9247,9248,9249,9250,9251,9252,
+9253,9254,9255,9256,9257,9258,9259,9260,9261,9262,9263,9264,9265,9266,9267,
+9268,9269,9270,9271,9272,9273,9274,9275,9276,9277,9278,9279,9280,9281,9282,
+9283,9284,9285,9286,9287,9288,9289,9290,9291,9292,9293,9294,9295,9296,9297,
+9298,9299,9300,9301,9302,9303,9304,9305,9306,9307,9308,9309,9310,9311,9312,
+9313,9314,9315,9316,9317,9318,9319,9320,9321,9322,9323,9324,9325,9326,9327,
+9328,9329,9330,9331,9332,9333,9334,9335,9336,9337,9338,9339,9340,9341,9342,
+9343,9344,9345,9346,9347,9348,9349,9350,9351,9352,9353,9354,9355,9356,9357,
+9358,9359,9360,9361,9362,9363,9364,9365,9366,9367,9368,9369,9370,9371,9372,
+9373,9374,9375,9376,9377,9378,9379,9380,9381,9382,9383,9384,9385,9386,9387,
+9388,9389,9390,9391,9392,9393,9394,9395,9396,9397,9398,9399,9400,9401,9402,
+9403,9404,9405,9406,9407,9408,9409,9410,9411,9412,9413,9414,9415,9416,9417,
+9418,9419,9420,9421,9422,9423,9398,9399,9400,9401,9402,9403,9404,9405,9406,
+9407,9408,9409,9410,9411,9412,9413,9414,9415,9416,9417,9418,9419,9420,9421,
+9422,9423,9450,9451,9452,9453,9454,9455,9456,9457,9458,9459,9460,9461,9462,
+9463,9464,9465,9466,9467,9468,9469,9470,9471,9472,9473,9474,9475,9476,9477,
+9478,9479,9480,9481,9482,9483,9484,9485,9486,9487,9488,9489,9490,9491,9492,
+9493,9494,9495,9496,9497,9498,9499,9500,9501,9502,9503,9504,9505,9506,9507,
+9508,9509,9510,9511,9512,9513,9514,9515,9516,9517,9518,9519,9520,9521,9522,
+9523,9524,9525,9526,9527,9528,9529,9530,9531,9532,9533,9534,9535,9536,9537,
+9538,9539,9540,9541,9542,9543,9544,9545,9546,9547,9548,9549,9550,9551,9552,
+9553,9554,9555,9556,9557,9558,9559,9560,9561,9562,9563,9564,9565,9566,9567,
+9568,9569,9570,9571,9572,9573,9574,9575,9576,9577,9578,9579,9580,9581,9582,
+9583,9584,9585,9586,9587,9588,9589,9590,9591,9592,9593,9594,9595,9596,9597,
+9598,9599,9600,9601,9602,9603,9604,9605,9606,9607,9608,9609,9610,9611,9612,
+9613,9614,9615,9616,9617,9618,9619,9620,9621,9622,9623,9624,9625,9626,9627,
+9628,9629,9630,9631,9632,9633,9634,9635,9636,9637,9638,9639,9640,9641,9642,
+9643,9644,9645,9646,9647,9648,9649,9650,9651,9652,9653,9654,9655,9656,9657,
+9658,9659,9660,9661,9662,9663,9664,9665,9666,9667,9668,9669,9670,9671,9672,
+9673,9674,9675,9676,9677,9678,9679,9680,9681,9682,9683,9684,9685,9686,9687,
+9688,9689,9690,9691,9692,9693,9694,9695,9696,9697,9698,9699,9700,9701,9702,
+9703,9704,9705,9706,9707,9708,9709,9710,9711,9712,9713,9714,9715,9716,9717,
+9718,9719,9720,9721,9722,9723,9724,9725,9726,9727,9728,9729,9730,9731,9732,
+9733,9734,9735,9736,9737,9738,9739,9740,9741,9742,9743,9744,9745,9746,9747,
+9748,9749,9750,9751,9752,9753,9754,9755,9756,9757,9758,9759,9760,9761,9762,
+9763,9764,9765,9766,9767,9768,9769,9770,9771,9772,9773,9774,9775,9776,9777,
+9778,9779,9780,9781,9782,9783,9784,9785,9786,9787,9788,9789,9790,9791,9792,
+9793,9794,9795,9796,9797,9798,9799,9800,9801,9802,9803,9804,9805,9806,9807,
+9808,9809,9810,9811,9812,9813,9814,9815,9816,9817,9818,9819,9820,9821,9822,
+9823,9824,9825,9826,9827,9828,9829,9830,9831,9832,9833,9834,9835,9836,9837,
+9838,9839,9840,9841,9842,9843,9844,9845,9846,9847,9848,9849,9850,9851,9852,
+9853,9854,9855,9856,9857,9858,9859,9860,9861,9862,9863,9864,9865,9866,9867,
+9868,9869,9870,9871,9872,9873,9874,9875,9876,9877,9878,9879,9880,9881,9882,
+9883,9884,9885,9886,9887,9888,9889,9890,9891,9892,9893,9894,9895,9896,9897,
+9898,9899,9900,9901,9902,9903,9904,9905,9906,9907,9908,9909,9910,9911,9912,
+9913,9914,9915,9916,9917,9918,9919,9920,9921,9922,9923,9924,9925,9926,9927,
+9928,9929,9930,9931,9932,9933,9934,9935,9936,9937,9938,9939,9940,9941,9942,
+9943,9944,9945,9946,9947,9948,9949,9950,9951,9952,9953,9954,9955,9956,9957,
+9958,9959,9960,9961,9962,9963,9964,9965,9966,9967,9968,9969,9970,9971,9972,
+9973,9974,9975,9976,9977,9978,9979,9980,9981,9982,9983,9984,9985,9986,9987,
+9988,9989,9990,9991,9992,9993,9994,9995,9996,9997,9998,9999,10000,10001,
+10002,10003,10004,10005,10006,10007,10008,10009,10010,10011,10012,10013,
+10014,10015,10016,10017,10018,10019,10020,10021,10022,10023,10024,10025,
+10026,10027,10028,10029,10030,10031,10032,10033,10034,10035,10036,10037,
+10038,10039,10040,10041,10042,10043,10044,10045,10046,10047,10048,10049,
+10050,10051,10052,10053,10054,10055,10056,10057,10058,10059,10060,10061,
+10062,10063,10064,10065,10066,10067,10068,10069,10070,10071,10072,10073,
+10074,10075,10076,10077,10078,10079,10080,10081,10082,10083,10084,10085,
+10086,10087,10088,10089,10090,10091,10092,10093,10094,10095,10096,10097,
+10098,10099,10100,10101,10102,10103,10104,10105,10106,10107,10108,10109,
+10110,10111,10112,10113,10114,10115,10116,10117,10118,10119,10120,10121,
+10122,10123,10124,10125,10126,10127,10128,10129,10130,10131,10132,10133,
+10134,10135,10136,10137,10138,10139,10140,10141,10142,10143,10144,10145,
+10146,10147,10148,10149,10150,10151,10152,10153,10154,10155,10156,10157,
+10158,10159,10160,10161,10162,10163,10164,10165,10166,10167,10168,10169,
+10170,10171,10172,10173,10174,10175,10176,10177,10178,10179,10180,10181,
+10182,10183,10184,10185,10186,10187,10188,10189,10190,10191,10192,10193,
+10194,10195,10196,10197,10198,10199,10200,10201,10202,10203,10204,10205,
+10206,10207,10208,10209,10210,10211,10212,10213,10214,10215,10216,10217,
+10218,10219,10220,10221,10222,10223,10224,10225,10226,10227,10228,10229,
+10230,10231,10232,10233,10234,10235,10236,10237,10238,10239,10240,10241,
+10242,10243,10244,10245,10246,10247,10248,10249,10250,10251,10252,10253,
+10254,10255,10256,10257,10258,10259,10260,10261,10262,10263,10264,10265,
+10266,10267,10268,10269,10270,10271,10272,10273,10274,10275,10276,10277,
+10278,10279,10280,10281,10282,10283,10284,10285,10286,10287,10288,10289,
+10290,10291,10292,10293,10294,10295,10296,10297,10298,10299,10300,10301,
+10302,10303,10304,10305,10306,10307,10308,10309,10310,10311,10312,10313,
+10314,10315,10316,10317,10318,10319,10320,10321,10322,10323,10324,10325,
+10326,10327,10328,10329,10330,10331,10332,10333,10334,10335,10336,10337,
+10338,10339,10340,10341,10342,10343,10344,10345,10346,10347,10348,10349,
+10350,10351,10352,10353,10354,10355,10356,10357,10358,10359,10360,10361,
+10362,10363,10364,10365,10366,10367,10368,10369,10370,10371,10372,10373,
+10374,10375,10376,10377,10378,10379,10380,10381,10382,10383,10384,10385,
+10386,10387,10388,10389,10390,10391,10392,10393,10394,10395,10396,10397,
+10398,10399,10400,10401,10402,10403,10404,10405,10406,10407,10408,10409,
+10410,10411,10412,10413,10414,10415,10416,10417,10418,10419,10420,10421,
+10422,10423,10424,10425,10426,10427,10428,10429,10430,10431,10432,10433,
+10434,10435,10436,10437,10438,10439,10440,10441,10442,10443,10444,10445,
+10446,10447,10448,10449,10450,10451,10452,10453,10454,10455,10456,10457,
+10458,10459,10460,10461,10462,10463,10464,10465,10466,10467,10468,10469,
+10470,10471,10472,10473,10474,10475,10476,10477,10478,10479,10480,10481,
+10482,10483,10484,10485,10486,10487,10488,10489,10490,10491,10492,10493,
+10494,10495,10496,10497,10498,10499,10500,10501,10502,10503,10504,10505,
+10506,10507,10508,10509,10510,10511,10512,10513,10514,10515,10516,10517,
+10518,10519,10520,10521,10522,10523,10524,10525,10526,10527,10528,10529,
+10530,10531,10532,10533,10534,10535,10536,10537,10538,10539,10540,10541,
+10542,10543,10544,10545,10546,10547,10548,10549,10550,10551,10552,10553,
+10554,10555,10556,10557,10558,10559,10560,10561,10562,10563,10564,10565,
+10566,10567,10568,10569,10570,10571,10572,10573,10574,10575,10576,10577,
+10578,10579,10580,10581,10582,10583,10584,10585,10586,10587,10588,10589,
+10590,10591,10592,10593,10594,10595,10596,10597,10598,10599,10600,10601,
+10602,10603,10604,10605,10606,10607,10608,10609,10610,10611,10612,10613,
+10614,10615,10616,10617,10618,10619,10620,10621,10622,10623,10624,10625,
+10626,10627,10628,10629,10630,10631,10632,10633,10634,10635,10636,10637,
+10638,10639,10640,10641,10642,10643,10644,10645,10646,10647,10648,10649,
+10650,10651,10652,10653,10654,10655,10656,10657,10658,10659,10660,10661,
+10662,10663,10664,10665,10666,10667,10668,10669,10670,10671,10672,10673,
+10674,10675,10676,10677,10678,10679,10680,10681,10682,10683,10684,10685,
+10686,10687,10688,10689,10690,10691,10692,10693,10694,10695,10696,10697,
+10698,10699,10700,10701,10702,10703,10704,10705,10706,10707,10708,10709,
+10710,10711,10712,10713,10714,10715,10716,10717,10718,10719,10720,10721,
+10722,10723,10724,10725,10726,10727,10728,10729,10730,10731,10732,10733,
+10734,10735,10736,10737,10738,10739,10740,10741,10742,10743,10744,10745,
+10746,10747,10748,10749,10750,10751,10752,10753,10754,10755,10756,10757,
+10758,10759,10760,10761,10762,10763,10764,10765,10766,10767,10768,10769,
+10770,10771,10772,10773,10774,10775,10776,10777,10778,10779,10780,10781,
+10782,10783,10784,10785,10786,10787,10788,10789,10790,10791,10792,10793,
+10794,10795,10796,10797,10798,10799,10800,10801,10802,10803,10804,10805,
+10806,10807,10808,10809,10810,10811,10812,10813,10814,10815,10816,10817,
+10818,10819,10820,10821,10822,10823,10824,10825,10826,10827,10828,10829,
+10830,10831,10832,10833,10834,10835,10836,10837,10838,10839,10840,10841,
+10842,10843,10844,10845,10846,10847,10848,10849,10850,10851,10852,10853,
+10854,10855,10856,10857,10858,10859,10860,10861,10862,10863,10864,10865,
+10866,10867,10868,10869,10870,10871,10872,10873,10874,10875,10876,10877,
+10878,10879,10880,10881,10882,10883,10884,10885,10886,10887,10888,10889,
+10890,10891,10892,10893,10894,10895,10896,10897,10898,10899,10900,10901,
+10902,10903,10904,10905,10906,10907,10908,10909,10910,10911,10912,10913,
+10914,10915,10916,10917,10918,10919,10920,10921,10922,10923,10924,10925,
+10926,10927,10928,10929,10930,10931,10932,10933,10934,10935,10936,10937,
+10938,10939,10940,10941,10942,10943,10944,10945,10946,10947,10948,10949,
+10950,10951,10952,10953,10954,10955,10956,10957,10958,10959,10960,10961,
+10962,10963,10964,10965,10966,10967,10968,10969,10970,10971,10972,10973,
+10974,10975,10976,10977,10978,10979,10980,10981,10982,10983,10984,10985,
+10986,10987,10988,10989,10990,10991,10992,10993,10994,10995,10996,10997,
+10998,10999,11000,11001,11002,11003,11004,11005,11006,11007,11008,11009,
+11010,11011,11012,11013,11014,11015,11016,11017,11018,11019,11020,11021,
+11022,11023,11024,11025,11026,11027,11028,11029,11030,11031,11032,11033,
+11034,11035,11036,11037,11038,11039,11040,11041,11042,11043,11044,11045,
+11046,11047,11048,11049,11050,11051,11052,11053,11054,11055,11056,11057,
+11058,11059,11060,11061,11062,11063,11064,11065,11066,11067,11068,11069,
+11070,11071,11072,11073,11074,11075,11076,11077,11078,11079,11080,11081,
+11082,11083,11084,11085,11086,11087,11088,11089,11090,11091,11092,11093,
+11094,11095,11096,11097,11098,11099,11100,11101,11102,11103,11104,11105,
+11106,11107,11108,11109,11110,11111,11112,11113,11114,11115,11116,11117,
+11118,11119,11120,11121,11122,11123,11124,11125,11126,11127,11128,11129,
+11130,11131,11132,11133,11134,11135,11136,11137,11138,11139,11140,11141,
+11142,11143,11144,11145,11146,11147,11148,11149,11150,11151,11152,11153,
+11154,11155,11156,11157,11158,11159,11160,11161,11162,11163,11164,11165,
+11166,11167,11168,11169,11170,11171,11172,11173,11174,11175,11176,11177,
+11178,11179,11180,11181,11182,11183,11184,11185,11186,11187,11188,11189,
+11190,11191,11192,11193,11194,11195,11196,11197,11198,11199,11200,11201,
+11202,11203,11204,11205,11206,11207,11208,11209,11210,11211,11212,11213,
+11214,11215,11216,11217,11218,11219,11220,11221,11222,11223,11224,11225,
+11226,11227,11228,11229,11230,11231,11232,11233,11234,11235,11236,11237,
+11238,11239,11240,11241,11242,11243,11244,11245,11246,11247,11248,11249,
+11250,11251,11252,11253,11254,11255,11256,11257,11258,11259,11260,11261,
+11262,11263,11264,11265,11266,11267,11268,11269,11270,11271,11272,11273,
+11274,11275,11276,11277,11278,11279,11280,11281,11282,11283,11284,11285,
+11286,11287,11288,11289,11290,11291,11292,11293,11294,11295,11296,11297,
+11298,11299,11300,11301,11302,11303,11304,11305,11306,11307,11308,11309,
+11310,11311,11264,11265,11266,11267,11268,11269,11270,11271,11272,11273,
+11274,11275,11276,11277,11278,11279,11280,11281,11282,11283,11284,11285,
+11286,11287,11288,11289,11290,11291,11292,11293,11294,11295,11296,11297,
+11298,11299,11300,11301,11302,11303,11304,11305,11306,11307,11308,11309,
+11310,11359,11360,11360,11362,11363,11364,570,574,11367,11367,11369,11369,
+11371,11371,11373,11374,11375,11376,11377,11378,11378,11380,11381,11381,
+11383,11384,11385,11386,11387,11388,11389,11390,11391,11392,11392,11394,
+11394,11396,11396,11398,11398,11400,11400,11402,11402,11404,11404,11406,
+11406,11408,11408,11410,11410,11412,11412,11414,11414,11416,11416,11418,
+11418,11420,11420,11422,11422,11424,11424,11426,11426,11428,11428,11430,
+11430,11432,11432,11434,11434,11436,11436,11438,11438,11440,11440,11442,
+11442,11444,11444,11446,11446,11448,11448,11450,11450,11452,11452,11454,
+11454,11456,11456,11458,11458,11460,11460,11462,11462,11464,11464,11466,
+11466,11468,11468,11470,11470,11472,11472,11474,11474,11476,11476,11478,
+11478,11480,11480,11482,11482,11484,11484,11486,11486,11488,11488,11490,
+11490,11492,11493,11494,11495,11496,11497,11498,11499,11499,11501,11501,
+11503,11504,11505,11506,11507,11508,11509,11510,11511,11512,11513,11514,
+11515,11516,11517,11518,11519,4256,4257,4258,4259,4260,4261,4262,4263,4264,
+4265,4266,4267,4268,4269,4270,4271,4272,4273,4274,4275,4276,4277,4278,4279,
+4280,4281,4282,4283,4284,4285,4286,4287,4288,4289,4290,4291,4292,4293,
+11558,11559,11560,11561,11562,11563,11564,11565,11566,11567,11568,11569,
+11570,11571,11572,11573,11574,11575,11576,11577,11578,11579,11580,11581,
+11582,11583,11584,11585,11586,11587,11588,11589,11590,11591,11592,11593,
+11594,11595,11596,11597,11598,11599,11600,11601,11602,11603,11604,11605,
+11606,11607,11608,11609,11610,11611,11612,11613,11614,11615,11616,11617,
+11618,11619,11620,11621,11622,11623,11624,11625,11626,11627,11628,11629,
+11630,11631,11632,11633,11634,11635,11636,11637,11638,11639,11640,11641,
+11642,11643,11644,11645,11646,11647,11648,11649,11650,11651,11652,11653,
+11654,11655,11656,11657,11658,11659,11660,11661,11662,11663,11664,11665,
+11666,11667,11668,11669,11670,11671,11672,11673,11674,11675,11676,11677,
+11678,11679,11680,11681,11682,11683,11684,11685,11686,11687,11688,11689,
+11690,11691,11692,11693,11694,11695,11696,11697,11698,11699,11700,11701,
+11702,11703,11704,11705,11706,11707,11708,11709,11710,11711,11712,11713,
+11714,11715,11716,11717,11718,11719,11720,11721,11722,11723,11724,11725,
+11726,11727,11728,11729,11730,11731,11732,11733,11734,11735,11736,11737,
+11738,11739,11740,11741,11742,11743,11744,11745,11746,11747,11748,11749,
+11750,11751,11752,11753,11754,11755,11756,11757,11758,11759,11760,11761,
+11762,11763,11764,11765,11766,11767,11768,11769,11770,11771,11772,11773,
+11774,11775,11776,11777,11778,11779,11780,11781,11782,11783,11784,11785,
+11786,11787,11788,11789,11790,11791,11792,11793,11794,11795,11796,11797,
+11798,11799,11800,11801,11802,11803,11804,11805,11806,11807,11808,11809,
+11810,11811,11812,11813,11814,11815,11816,11817,11818,11819,11820,11821,
+11822,11823,11824,11825,11826,11827,11828,11829,11830,11831,11832,11833,
+11834,11835,11836,11837,11838,11839,11840,11841,11842,11843,11844,11845,
+11846,11847,11848,11849,11850,11851,11852,11853,11854,11855,11856,11857,
+11858,11859,11860,11861,11862,11863,11864,11865,11866,11867,11868,11869,
+11870,11871,11872,11873,11874,11875,11876,11877,11878,11879,11880,11881,
+11882,11883,11884,11885,11886,11887,11888,11889,11890,11891,11892,11893,
+11894,11895,11896,11897,11898,11899,11900,11901,11902,11903,11904,11905,
+11906,11907,11908,11909,11910,11911,11912,11913,11914,11915,11916,11917,
+11918,11919,11920,11921,11922,11923,11924,11925,11926,11927,11928,11929,
+11930,11931,11932,11933,11934,11935,11936,11937,11938,11939,11940,11941,
+11942,11943,11944,11945,11946,11947,11948,11949,11950,11951,11952,11953,
+11954,11955,11956,11957,11958,11959,11960,11961,11962,11963,11964,11965,
+11966,11967,11968,11969,11970,11971,11972,11973,11974,11975,11976,11977,
+11978,11979,11980,11981,11982,11983,11984,11985,11986,11987,11988,11989,
+11990,11991,11992,11993,11994,11995,11996,11997,11998,11999,12000,12001,
+12002,12003,12004,12005,12006,12007,12008,12009,12010,12011,12012,12013,
+12014,12015,12016,12017,12018,12019,12020,12021,12022,12023,12024,12025,
+12026,12027,12028,12029,12030,12031,12032,12033,12034,12035,12036,12037,
+12038,12039,12040,12041,12042,12043,12044,12045,12046,12047,12048,12049,
+12050,12051,12052,12053,12054,12055,12056,12057,12058,12059,12060,12061,
+12062,12063,12064,12065,12066,12067,12068,12069,12070,12071,12072,12073,
+12074,12075,12076,12077,12078,12079,12080,12081,12082,12083,12084,12085,
+12086,12087,12088,12089,12090,12091,12092,12093,12094,12095,12096,12097,
+12098,12099,12100,12101,12102,12103,12104,12105,12106,12107,12108,12109,
+12110,12111,12112,12113,12114,12115,12116,12117,12118,12119,12120,12121,
+12122,12123,12124,12125,12126,12127,12128,12129,12130,12131,12132,12133,
+12134,12135,12136,12137,12138,12139,12140,12141,12142,12143,12144,12145,
+12146,12147,12148,12149,12150,12151,12152,12153,12154,12155,12156,12157,
+12158,12159,12160,12161,12162,12163,12164,12165,12166,12167,12168,12169,
+12170,12171,12172,12173,12174,12175,12176,12177,12178,12179,12180,12181,
+12182,12183,12184,12185,12186,12187,12188,12189,12190,12191,12192,12193,
+12194,12195,12196,12197,12198,12199,12200,12201,12202,12203,12204,12205,
+12206,12207,12208,12209,12210,12211,12212,12213,12214,12215,12216,12217,
+12218,12219,12220,12221,12222,12223,12224,12225,12226,12227,12228,12229,
+12230,12231,12232,12233,12234,12235,12236,12237,12238,12239,12240,12241,
+12242,12243,12244,12245,12246,12247,12248,12249,12250,12251,12252,12253,
+12254,12255,12256,12257,12258,12259,12260,12261,12262,12263,12264,12265,
+12266,12267,12268,12269,12270,12271,12272,12273,12274,12275,12276,12277,
+12278,12279,12280,12281,12282,12283,12284,12285,12286,12287,12288,12289,
+12290,12291,12292,12293,12294,12295,12296,12297,12298,12299,12300,12301,
+12302,12303,12304,12305,12306,12307,12308,12309,12310,12311,12312,12313,
+12314,12315,12316,12317,12318,12319,12320,12321,12322,12323,12324,12325,
+12326,12327,12328,12329,12330,12331,12332,12333,12334,12335,12336,12337,
+12338,12339,12340,12341,12342,12343,12344,12345,12346,12347,12348,12349,
+12350,12351,12352,12353,12354,12355,12356,12357,12358,12359,12360,12361,
+12362,12363,12364,12365,12366,12367,12368,12369,12370,12371,12372,12373,
+12374,12375,12376,12377,12378,12379,12380,12381,12382,12383,12384,12385,
+12386,12387,12388,12389,12390,12391,12392,12393,12394,12395,12396,12397,
+12398,12399,12400,12401,12402,12403,12404,12405,12406,12407,12408,12409,
+12410,12411,12412,12413,12414,12415,12416,12417,12418,12419,12420,12421,
+12422,12423,12424,12425,12426,12427,12428,12429,12430,12431,12432,12433,
+12434,12435,12436,12437,12438,12439,12440,12441,12442,12443,12444,12445,
+12446,12447,12448,12449,12450,12451,12452,12453,12454,12455,12456,12457,
+12458,12459,12460,12461,12462,12463,12464,12465,12466,12467,12468,12469,
+12470,12471,12472,12473,12474,12475,12476,12477,12478,12479,12480,12481,
+12482,12483,12484,12485,12486,12487,12488,12489,12490,12491,12492,12493,
+12494,12495,12496,12497,12498,12499,12500,12501,12502,12503,12504,12505,
+12506,12507,12508,12509,12510,12511,12512,12513,12514,12515,12516,12517,
+12518,12519,12520,12521,12522,12523,12524,12525,12526,12527,12528,12529,
+12530,12531,12532,12533,12534,12535,12536,12537,12538,12539,12540,12541,
+12542,12543,12544,12545,12546,12547,12548,12549,12550,12551,12552,12553,
+12554,12555,12556,12557,12558,12559,12560,12561,12562,12563,12564,12565,
+12566,12567,12568,12569,12570,12571,12572,12573,12574,12575,12576,12577,
+12578,12579,12580,12581,12582,12583,12584,12585,12586,12587,12588,12589,
+12590,12591,12592,12593,12594,12595,12596,12597,12598,12599,12600,12601,
+12602,12603,12604,12605,12606,12607,12608,12609,12610,12611,12612,12613,
+12614,12615,12616,12617,12618,12619,12620,12621,12622,12623,12624,12625,
+12626,12627,12628,12629,12630,12631,12632,12633,12634,12635,12636,12637,
+12638,12639,12640,12641,12642,12643,12644,12645,12646,12647,12648,12649,
+12650,12651,12652,12653,12654,12655,12656,12657,12658,12659,12660,12661,
+12662,12663,12664,12665,12666,12667,12668,12669,12670,12671,12672,12673,
+12674,12675,12676,12677,12678,12679,12680,12681,12682,12683,12684,12685,
+12686,12687,12688,12689,12690,12691,12692,12693,12694,12695,12696,12697,
+12698,12699,12700,12701,12702,12703,12704,12705,12706,12707,12708,12709,
+12710,12711,12712,12713,12714,12715,12716,12717,12718,12719,12720,12721,
+12722,12723,12724,12725,12726,12727,12728,12729,12730,12731,12732,12733,
+12734,12735,12736,12737,12738,12739,12740,12741,12742,12743,12744,12745,
+12746,12747,12748,12749,12750,12751,12752,12753,12754,12755,12756,12757,
+12758,12759,12760,12761,12762,12763,12764,12765,12766,12767,12768,12769,
+12770,12771,12772,12773,12774,12775,12776,12777,12778,12779,12780,12781,
+12782,12783,12784,12785,12786,12787,12788,12789,12790,12791,12792,12793,
+12794,12795,12796,12797,12798,12799,12800,12801,12802,12803,12804,12805,
+12806,12807,12808,12809,12810,12811,12812,12813,12814,12815,12816,12817,
+12818,12819,12820,12821,12822,12823,12824,12825,12826,12827,12828,12829,
+12830,12831,12832,12833,12834,12835,12836,12837,12838,12839,12840,12841,
+12842,12843,12844,12845,12846,12847,12848,12849,12850,12851,12852,12853,
+12854,12855,12856,12857,12858,12859,12860,12861,12862,12863,12864,12865,
+12866,12867,12868,12869,12870,12871,12872,12873,12874,12875,12876,12877,
+12878,12879,12880,12881,12882,12883,12884,12885,12886,12887,12888,12889,
+12890,12891,12892,12893,12894,12895,12896,12897,12898,12899,12900,12901,
+12902,12903,12904,12905,12906,12907,12908,12909,12910,12911,12912,12913,
+12914,12915,12916,12917,12918,12919,12920,12921,12922,12923,12924,12925,
+12926,12927,12928,12929,12930,12931,12932,12933,12934,12935,12936,12937,
+12938,12939,12940,12941,12942,12943,12944,12945,12946,12947,12948,12949,
+12950,12951,12952,12953,12954,12955,12956,12957,12958,12959,12960,12961,
+12962,12963,12964,12965,12966,12967,12968,12969,12970,12971,12972,12973,
+12974,12975,12976,12977,12978,12979,12980,12981,12982,12983,12984,12985,
+12986,12987,12988,12989,12990,12991,12992,12993,12994,12995,12996,12997,
+12998,12999,13000,13001,13002,13003,13004,13005,13006,13007,13008,13009,
+13010,13011,13012,13013,13014,13015,13016,13017,13018,13019,13020,13021,
+13022,13023,13024,13025,13026,13027,13028,13029,13030,13031,13032,13033,
+13034,13035,13036,13037,13038,13039,13040,13041,13042,13043,13044,13045,
+13046,13047,13048,13049,13050,13051,13052,13053,13054,13055,13056,13057,
+13058,13059,13060,13061,13062,13063,13064,13065,13066,13067,13068,13069,
+13070,13071,13072,13073,13074,13075,13076,13077,13078,13079,13080,13081,
+13082,13083,13084,13085,13086,13087,13088,13089,13090,13091,13092,13093,
+13094,13095,13096,13097,13098,13099,13100,13101,13102,13103,13104,13105,
+13106,13107,13108,13109,13110,13111,13112,13113,13114,13115,13116,13117,
+13118,13119,13120,13121,13122,13123,13124,13125,13126,13127,13128,13129,
+13130,13131,13132,13133,13134,13135,13136,13137,13138,13139,13140,13141,
+13142,13143,13144,13145,13146,13147,13148,13149,13150,13151,13152,13153,
+13154,13155,13156,13157,13158,13159,13160,13161,13162,13163,13164,13165,
+13166,13167,13168,13169,13170,13171,13172,13173,13174,13175,13176,13177,
+13178,13179,13180,13181,13182,13183,13184,13185,13186,13187,13188,13189,
+13190,13191,13192,13193,13194,13195,13196,13197,13198,13199,13200,13201,
+13202,13203,13204,13205,13206,13207,13208,13209,13210,13211,13212,13213,
+13214,13215,13216,13217,13218,13219,13220,13221,13222,13223,13224,13225,
+13226,13227,13228,13229,13230,13231,13232,13233,13234,13235,13236,13237,
+13238,13239,13240,13241,13242,13243,13244,13245,13246,13247,13248,13249,
+13250,13251,13252,13253,13254,13255,13256,13257,13258,13259,13260,13261,
+13262,13263,13264,13265,13266,13267,13268,13269,13270,13271,13272,13273,
+13274,13275,13276,13277,13278,13279,13280,13281,13282,13283,13284,13285,
+13286,13287,13288,13289,13290,13291,13292,13293,13294,13295,13296,13297,
+13298,13299,13300,13301,13302,13303,13304,13305,13306,13307,13308,13309,
+13310,13311,13312,13313,13314,13315,13316,13317,13318,13319,13320,13321,
+13322,13323,13324,13325,13326,13327,13328,13329,13330,13331,13332,13333,
+13334,13335,13336,13337,13338,13339,13340,13341,13342,13343,13344,13345,
+13346,13347,13348,13349,13350,13351,13352,13353,13354,13355,13356,13357,
+13358,13359,13360,13361,13362,13363,13364,13365,13366,13367,13368,13369,
+13370,13371,13372,13373,13374,13375,13376,13377,13378,13379,13380,13381,
+13382,13383,13384,13385,13386,13387,13388,13389,13390,13391,13392,13393,
+13394,13395,13396,13397,13398,13399,13400,13401,13402,13403,13404,13405,
+13406,13407,13408,13409,13410,13411,13412,13413,13414,13415,13416,13417,
+13418,13419,13420,13421,13422,13423,13424,13425,13426,13427,13428,13429,
+13430,13431,13432,13433,13434,13435,13436,13437,13438,13439,13440,13441,
+13442,13443,13444,13445,13446,13447,13448,13449,13450,13451,13452,13453,
+13454,13455,13456,13457,13458,13459,13460,13461,13462,13463,13464,13465,
+13466,13467,13468,13469,13470,13471,13472,13473,13474,13475,13476,13477,
+13478,13479,13480,13481,13482,13483,13484,13485,13486,13487,13488,13489,
+13490,13491,13492,13493,13494,13495,13496,13497,13498,13499,13500,13501,
+13502,13503,13504,13505,13506,13507,13508,13509,13510,13511,13512,13513,
+13514,13515,13516,13517,13518,13519,13520,13521,13522,13523,13524,13525,
+13526,13527,13528,13529,13530,13531,13532,13533,13534,13535,13536,13537,
+13538,13539,13540,13541,13542,13543,13544,13545,13546,13547,13548,13549,
+13550,13551,13552,13553,13554,13555,13556,13557,13558,13559,13560,13561,
+13562,13563,13564,13565,13566,13567,13568,13569,13570,13571,13572,13573,
+13574,13575,13576,13577,13578,13579,13580,13581,13582,13583,13584,13585,
+13586,13587,13588,13589,13590,13591,13592,13593,13594,13595,13596,13597,
+13598,13599,13600,13601,13602,13603,13604,13605,13606,13607,13608,13609,
+13610,13611,13612,13613,13614,13615,13616,13617,13618,13619,13620,13621,
+13622,13623,13624,13625,13626,13627,13628,13629,13630,13631,13632,13633,
+13634,13635,13636,13637,13638,13639,13640,13641,13642,13643,13644,13645,
+13646,13647,13648,13649,13650,13651,13652,13653,13654,13655,13656,13657,
+13658,13659,13660,13661,13662,13663,13664,13665,13666,13667,13668,13669,
+13670,13671,13672,13673,13674,13675,13676,13677,13678,13679,13680,13681,
+13682,13683,13684,13685,13686,13687,13688,13689,13690,13691,13692,13693,
+13694,13695,13696,13697,13698,13699,13700,13701,13702,13703,13704,13705,
+13706,13707,13708,13709,13710,13711,13712,13713,13714,13715,13716,13717,
+13718,13719,13720,13721,13722,13723,13724,13725,13726,13727,13728,13729,
+13730,13731,13732,13733,13734,13735,13736,13737,13738,13739,13740,13741,
+13742,13743,13744,13745,13746,13747,13748,13749,13750,13751,13752,13753,
+13754,13755,13756,13757,13758,13759,13760,13761,13762,13763,13764,13765,
+13766,13767,13768,13769,13770,13771,13772,13773,13774,13775,13776,13777,
+13778,13779,13780,13781,13782,13783,13784,13785,13786,13787,13788,13789,
+13790,13791,13792,13793,13794,13795,13796,13797,13798,13799,13800,13801,
+13802,13803,13804,13805,13806,13807,13808,13809,13810,13811,13812,13813,
+13814,13815,13816,13817,13818,13819,13820,13821,13822,13823,13824,13825,
+13826,13827,13828,13829,13830,13831,13832,13833,13834,13835,13836,13837,
+13838,13839,13840,13841,13842,13843,13844,13845,13846,13847,13848,13849,
+13850,13851,13852,13853,13854,13855,13856,13857,13858,13859,13860,13861,
+13862,13863,13864,13865,13866,13867,13868,13869,13870,13871,13872,13873,
+13874,13875,13876,13877,13878,13879,13880,13881,13882,13883,13884,13885,
+13886,13887,13888,13889,13890,13891,13892,13893,13894,13895,13896,13897,
+13898,13899,13900,13901,13902,13903,13904,13905,13906,13907,13908,13909,
+13910,13911,13912,13913,13914,13915,13916,13917,13918,13919,13920,13921,
+13922,13923,13924,13925,13926,13927,13928,13929,13930,13931,13932,13933,
+13934,13935,13936,13937,13938,13939,13940,13941,13942,13943,13944,13945,
+13946,13947,13948,13949,13950,13951,13952,13953,13954,13955,13956,13957,
+13958,13959,13960,13961,13962,13963,13964,13965,13966,13967,13968,13969,
+13970,13971,13972,13973,13974,13975,13976,13977,13978,13979,13980,13981,
+13982,13983,13984,13985,13986,13987,13988,13989,13990,13991,13992,13993,
+13994,13995,13996,13997,13998,13999,14000,14001,14002,14003,14004,14005,
+14006,14007,14008,14009,14010,14011,14012,14013,14014,14015,14016,14017,
+14018,14019,14020,14021,14022,14023,14024,14025,14026,14027,14028,14029,
+14030,14031,14032,14033,14034,14035,14036,14037,14038,14039,14040,14041,
+14042,14043,14044,14045,14046,14047,14048,14049,14050,14051,14052,14053,
+14054,14055,14056,14057,14058,14059,14060,14061,14062,14063,14064,14065,
+14066,14067,14068,14069,14070,14071,14072,14073,14074,14075,14076,14077,
+14078,14079,14080,14081,14082,14083,14084,14085,14086,14087,14088,14089,
+14090,14091,14092,14093,14094,14095,14096,14097,14098,14099,14100,14101,
+14102,14103,14104,14105,14106,14107,14108,14109,14110,14111,14112,14113,
+14114,14115,14116,14117,14118,14119,14120,14121,14122,14123,14124,14125,
+14126,14127,14128,14129,14130,14131,14132,14133,14134,14135,14136,14137,
+14138,14139,14140,14141,14142,14143,14144,14145,14146,14147,14148,14149,
+14150,14151,14152,14153,14154,14155,14156,14157,14158,14159,14160,14161,
+14162,14163,14164,14165,14166,14167,14168,14169,14170,14171,14172,14173,
+14174,14175,14176,14177,14178,14179,14180,14181,14182,14183,14184,14185,
+14186,14187,14188,14189,14190,14191,14192,14193,14194,14195,14196,14197,
+14198,14199,14200,14201,14202,14203,14204,14205,14206,14207,14208,14209,
+14210,14211,14212,14213,14214,14215,14216,14217,14218,14219,14220,14221,
+14222,14223,14224,14225,14226,14227,14228,14229,14230,14231,14232,14233,
+14234,14235,14236,14237,14238,14239,14240,14241,14242,14243,14244,14245,
+14246,14247,14248,14249,14250,14251,14252,14253,14254,14255,14256,14257,
+14258,14259,14260,14261,14262,14263,14264,14265,14266,14267,14268,14269,
+14270,14271,14272,14273,14274,14275,14276,14277,14278,14279,14280,14281,
+14282,14283,14284,14285,14286,14287,14288,14289,14290,14291,14292,14293,
+14294,14295,14296,14297,14298,14299,14300,14301,14302,14303,14304,14305,
+14306,14307,14308,14309,14310,14311,14312,14313,14314,14315,14316,14317,
+14318,14319,14320,14321,14322,14323,14324,14325,14326,14327,14328,14329,
+14330,14331,14332,14333,14334,14335,14336,14337,14338,14339,14340,14341,
+14342,14343,14344,14345,14346,14347,14348,14349,14350,14351,14352,14353,
+14354,14355,14356,14357,14358,14359,14360,14361,14362,14363,14364,14365,
+14366,14367,14368,14369,14370,14371,14372,14373,14374,14375,14376,14377,
+14378,14379,14380,14381,14382,14383,14384,14385,14386,14387,14388,14389,
+14390,14391,14392,14393,14394,14395,14396,14397,14398,14399,14400,14401,
+14402,14403,14404,14405,14406,14407,14408,14409,14410,14411,14412,14413,
+14414,14415,14416,14417,14418,14419,14420,14421,14422,14423,14424,14425,
+14426,14427,14428,14429,14430,14431,14432,14433,14434,14435,14436,14437,
+14438,14439,14440,14441,14442,14443,14444,14445,14446,14447,14448,14449,
+14450,14451,14452,14453,14454,14455,14456,14457,14458,14459,14460,14461,
+14462,14463,14464,14465,14466,14467,14468,14469,14470,14471,14472,14473,
+14474,14475,14476,14477,14478,14479,14480,14481,14482,14483,14484,14485,
+14486,14487,14488,14489,14490,14491,14492,14493,14494,14495,14496,14497,
+14498,14499,14500,14501,14502,14503,14504,14505,14506,14507,14508,14509,
+14510,14511,14512,14513,14514,14515,14516,14517,14518,14519,14520,14521,
+14522,14523,14524,14525,14526,14527,14528,14529,14530,14531,14532,14533,
+14534,14535,14536,14537,14538,14539,14540,14541,14542,14543,14544,14545,
+14546,14547,14548,14549,14550,14551,14552,14553,14554,14555,14556,14557,
+14558,14559,14560,14561,14562,14563,14564,14565,14566,14567,14568,14569,
+14570,14571,14572,14573,14574,14575,14576,14577,14578,14579,14580,14581,
+14582,14583,14584,14585,14586,14587,14588,14589,14590,14591,14592,14593,
+14594,14595,14596,14597,14598,14599,14600,14601,14602,14603,14604,14605,
+14606,14607,14608,14609,14610,14611,14612,14613,14614,14615,14616,14617,
+14618,14619,14620,14621,14622,14623,14624,14625,14626,14627,14628,14629,
+14630,14631,14632,14633,14634,14635,14636,14637,14638,14639,14640,14641,
+14642,14643,14644,14645,14646,14647,14648,14649,14650,14651,14652,14653,
+14654,14655,14656,14657,14658,14659,14660,14661,14662,14663,14664,14665,
+14666,14667,14668,14669,14670,14671,14672,14673,14674,14675,14676,14677,
+14678,14679,14680,14681,14682,14683,14684,14685,14686,14687,14688,14689,
+14690,14691,14692,14693,14694,14695,14696,14697,14698,14699,14700,14701,
+14702,14703,14704,14705,14706,14707,14708,14709,14710,14711,14712,14713,
+14714,14715,14716,14717,14718,14719,14720,14721,14722,14723,14724,14725,
+14726,14727,14728,14729,14730,14731,14732,14733,14734,14735,14736,14737,
+14738,14739,14740,14741,14742,14743,14744,14745,14746,14747,14748,14749,
+14750,14751,14752,14753,14754,14755,14756,14757,14758,14759,14760,14761,
+14762,14763,14764,14765,14766,14767,14768,14769,14770,14771,14772,14773,
+14774,14775,14776,14777,14778,14779,14780,14781,14782,14783,14784,14785,
+14786,14787,14788,14789,14790,14791,14792,14793,14794,14795,14796,14797,
+14798,14799,14800,14801,14802,14803,14804,14805,14806,14807,14808,14809,
+14810,14811,14812,14813,14814,14815,14816,14817,14818,14819,14820,14821,
+14822,14823,14824,14825,14826,14827,14828,14829,14830,14831,14832,14833,
+14834,14835,14836,14837,14838,14839,14840,14841,14842,14843,14844,14845,
+14846,14847,14848,14849,14850,14851,14852,14853,14854,14855,14856,14857,
+14858,14859,14860,14861,14862,14863,14864,14865,14866,14867,14868,14869,
+14870,14871,14872,14873,14874,14875,14876,14877,14878,14879,14880,14881,
+14882,14883,14884,14885,14886,14887,14888,14889,14890,14891,14892,14893,
+14894,14895,14896,14897,14898,14899,14900,14901,14902,14903,14904,14905,
+14906,14907,14908,14909,14910,14911,14912,14913,14914,14915,14916,14917,
+14918,14919,14920,14921,14922,14923,14924,14925,14926,14927,14928,14929,
+14930,14931,14932,14933,14934,14935,14936,14937,14938,14939,14940,14941,
+14942,14943,14944,14945,14946,14947,14948,14949,14950,14951,14952,14953,
+14954,14955,14956,14957,14958,14959,14960,14961,14962,14963,14964,14965,
+14966,14967,14968,14969,14970,14971,14972,14973,14974,14975,14976,14977,
+14978,14979,14980,14981,14982,14983,14984,14985,14986,14987,14988,14989,
+14990,14991,14992,14993,14994,14995,14996,14997,14998,14999,15000,15001,
+15002,15003,15004,15005,15006,15007,15008,15009,15010,15011,15012,15013,
+15014,15015,15016,15017,15018,15019,15020,15021,15022,15023,15024,15025,
+15026,15027,15028,15029,15030,15031,15032,15033,15034,15035,15036,15037,
+15038,15039,15040,15041,15042,15043,15044,15045,15046,15047,15048,15049,
+15050,15051,15052,15053,15054,15055,15056,15057,15058,15059,15060,15061,
+15062,15063,15064,15065,15066,15067,15068,15069,15070,15071,15072,15073,
+15074,15075,15076,15077,15078,15079,15080,15081,15082,15083,15084,15085,
+15086,15087,15088,15089,15090,15091,15092,15093,15094,15095,15096,15097,
+15098,15099,15100,15101,15102,15103,15104,15105,15106,15107,15108,15109,
+15110,15111,15112,15113,15114,15115,15116,15117,15118,15119,15120,15121,
+15122,15123,15124,15125,15126,15127,15128,15129,15130,15131,15132,15133,
+15134,15135,15136,15137,15138,15139,15140,15141,15142,15143,15144,15145,
+15146,15147,15148,15149,15150,15151,15152,15153,15154,15155,15156,15157,
+15158,15159,15160,15161,15162,15163,15164,15165,15166,15167,15168,15169,
+15170,15171,15172,15173,15174,15175,15176,15177,15178,15179,15180,15181,
+15182,15183,15184,15185,15186,15187,15188,15189,15190,15191,15192,15193,
+15194,15195,15196,15197,15198,15199,15200,15201,15202,15203,15204,15205,
+15206,15207,15208,15209,15210,15211,15212,15213,15214,15215,15216,15217,
+15218,15219,15220,15221,15222,15223,15224,15225,15226,15227,15228,15229,
+15230,15231,15232,15233,15234,15235,15236,15237,15238,15239,15240,15241,
+15242,15243,15244,15245,15246,15247,15248,15249,15250,15251,15252,15253,
+15254,15255,15256,15257,15258,15259,15260,15261,15262,15263,15264,15265,
+15266,15267,15268,15269,15270,15271,15272,15273,15274,15275,15276,15277,
+15278,15279,15280,15281,15282,15283,15284,15285,15286,15287,15288,15289,
+15290,15291,15292,15293,15294,15295,15296,15297,15298,15299,15300,15301,
+15302,15303,15304,15305,15306,15307,15308,15309,15310,15311,15312,15313,
+15314,15315,15316,15317,15318,15319,15320,15321,15322,15323,15324,15325,
+15326,15327,15328,15329,15330,15331,15332,15333,15334,15335,15336,15337,
+15338,15339,15340,15341,15342,15343,15344,15345,15346,15347,15348,15349,
+15350,15351,15352,15353,15354,15355,15356,15357,15358,15359,15360,15361,
+15362,15363,15364,15365,15366,15367,15368,15369,15370,15371,15372,15373,
+15374,15375,15376,15377,15378,15379,15380,15381,15382,15383,15384,15385,
+15386,15387,15388,15389,15390,15391,15392,15393,15394,15395,15396,15397,
+15398,15399,15400,15401,15402,15403,15404,15405,15406,15407,15408,15409,
+15410,15411,15412,15413,15414,15415,15416,15417,15418,15419,15420,15421,
+15422,15423,15424,15425,15426,15427,15428,15429,15430,15431,15432,15433,
+15434,15435,15436,15437,15438,15439,15440,15441,15442,15443,15444,15445,
+15446,15447,15448,15449,15450,15451,15452,15453,15454,15455,15456,15457,
+15458,15459,15460,15461,15462,15463,15464,15465,15466,15467,15468,15469,
+15470,15471,15472,15473,15474,15475,15476,15477,15478,15479,15480,15481,
+15482,15483,15484,15485,15486,15487,15488,15489,15490,15491,15492,15493,
+15494,15495,15496,15497,15498,15499,15500,15501,15502,15503,15504,15505,
+15506,15507,15508,15509,15510,15511,15512,15513,15514,15515,15516,15517,
+15518,15519,15520,15521,15522,15523,15524,15525,15526,15527,15528,15529,
+15530,15531,15532,15533,15534,15535,15536,15537,15538,15539,15540,15541,
+15542,15543,15544,15545,15546,15547,15548,15549,15550,15551,15552,15553,
+15554,15555,15556,15557,15558,15559,15560,15561,15562,15563,15564,15565,
+15566,15567,15568,15569,15570,15571,15572,15573,15574,15575,15576,15577,
+15578,15579,15580,15581,15582,15583,15584,15585,15586,15587,15588,15589,
+15590,15591,15592,15593,15594,15595,15596,15597,15598,15599,15600,15601,
+15602,15603,15604,15605,15606,15607,15608,15609,15610,15611,15612,15613,
+15614,15615,15616,15617,15618,15619,15620,15621,15622,15623,15624,15625,
+15626,15627,15628,15629,15630,15631,15632,15633,15634,15635,15636,15637,
+15638,15639,15640,15641,15642,15643,15644,15645,15646,15647,15648,15649,
+15650,15651,15652,15653,15654,15655,15656,15657,15658,15659,15660,15661,
+15662,15663,15664,15665,15666,15667,15668,15669,15670,15671,15672,15673,
+15674,15675,15676,15677,15678,15679,15680,15681,15682,15683,15684,15685,
+15686,15687,15688,15689,15690,15691,15692,15693,15694,15695,15696,15697,
+15698,15699,15700,15701,15702,15703,15704,15705,15706,15707,15708,15709,
+15710,15711,15712,15713,15714,15715,15716,15717,15718,15719,15720,15721,
+15722,15723,15724,15725,15726,15727,15728,15729,15730,15731,15732,15733,
+15734,15735,15736,15737,15738,15739,15740,15741,15742,15743,15744,15745,
+15746,15747,15748,15749,15750,15751,15752,15753,15754,15755,15756,15757,
+15758,15759,15760,15761,15762,15763,15764,15765,15766,15767,15768,15769,
+15770,15771,15772,15773,15774,15775,15776,15777,15778,15779,15780,15781,
+15782,15783,15784,15785,15786,15787,15788,15789,15790,15791,15792,15793,
+15794,15795,15796,15797,15798,15799,15800,15801,15802,15803,15804,15805,
+15806,15807,15808,15809,15810,15811,15812,15813,15814,15815,15816,15817,
+15818,15819,15820,15821,15822,15823,15824,15825,15826,15827,15828,15829,
+15830,15831,15832,15833,15834,15835,15836,15837,15838,15839,15840,15841,
+15842,15843,15844,15845,15846,15847,15848,15849,15850,15851,15852,15853,
+15854,15855,15856,15857,15858,15859,15860,15861,15862,15863,15864,15865,
+15866,15867,15868,15869,15870,15871,15872,15873,15874,15875,15876,15877,
+15878,15879,15880,15881,15882,15883,15884,15885,15886,15887,15888,15889,
+15890,15891,15892,15893,15894,15895,15896,15897,15898,15899,15900,15901,
+15902,15903,15904,15905,15906,15907,15908,15909,15910,15911,15912,15913,
+15914,15915,15916,15917,15918,15919,15920,15921,15922,15923,15924,15925,
+15926,15927,15928,15929,15930,15931,15932,15933,15934,15935,15936,15937,
+15938,15939,15940,15941,15942,15943,15944,15945,15946,15947,15948,15949,
+15950,15951,15952,15953,15954,15955,15956,15957,15958,15959,15960,15961,
+15962,15963,15964,15965,15966,15967,15968,15969,15970,15971,15972,15973,
+15974,15975,15976,15977,15978,15979,15980,15981,15982,15983,15984,15985,
+15986,15987,15988,15989,15990,15991,15992,15993,15994,15995,15996,15997,
+15998,15999,16000,16001,16002,16003,16004,16005,16006,16007,16008,16009,
+16010,16011,16012,16013,16014,16015,16016,16017,16018,16019,16020,16021,
+16022,16023,16024,16025,16026,16027,16028,16029,16030,16031,16032,16033,
+16034,16035,16036,16037,16038,16039,16040,16041,16042,16043,16044,16045,
+16046,16047,16048,16049,16050,16051,16052,16053,16054,16055,16056,16057,
+16058,16059,16060,16061,16062,16063,16064,16065,16066,16067,16068,16069,
+16070,16071,16072,16073,16074,16075,16076,16077,16078,16079,16080,16081,
+16082,16083,16084,16085,16086,16087,16088,16089,16090,16091,16092,16093,
+16094,16095,16096,16097,16098,16099,16100,16101,16102,16103,16104,16105,
+16106,16107,16108,16109,16110,16111,16112,16113,16114,16115,16116,16117,
+16118,16119,16120,16121,16122,16123,16124,16125,16126,16127,16128,16129,
+16130,16131,16132,16133,16134,16135,16136,16137,16138,16139,16140,16141,
+16142,16143,16144,16145,16146,16147,16148,16149,16150,16151,16152,16153,
+16154,16155,16156,16157,16158,16159,16160,16161,16162,16163,16164,16165,
+16166,16167,16168,16169,16170,16171,16172,16173,16174,16175,16176,16177,
+16178,16179,16180,16181,16182,16183,16184,16185,16186,16187,16188,16189,
+16190,16191,16192,16193,16194,16195,16196,16197,16198,16199,16200,16201,
+16202,16203,16204,16205,16206,16207,16208,16209,16210,16211,16212,16213,
+16214,16215,16216,16217,16218,16219,16220,16221,16222,16223,16224,16225,
+16226,16227,16228,16229,16230,16231,16232,16233,16234,16235,16236,16237,
+16238,16239,16240,16241,16242,16243,16244,16245,16246,16247,16248,16249,
+16250,16251,16252,16253,16254,16255,16256,16257,16258,16259,16260,16261,
+16262,16263,16264,16265,16266,16267,16268,16269,16270,16271,16272,16273,
+16274,16275,16276,16277,16278,16279,16280,16281,16282,16283,16284,16285,
+16286,16287,16288,16289,16290,16291,16292,16293,16294,16295,16296,16297,
+16298,16299,16300,16301,16302,16303,16304,16305,16306,16307,16308,16309,
+16310,16311,16312,16313,16314,16315,16316,16317,16318,16319,16320,16321,
+16322,16323,16324,16325,16326,16327,16328,16329,16330,16331,16332,16333,
+16334,16335,16336,16337,16338,16339,16340,16341,16342,16343,16344,16345,
+16346,16347,16348,16349,16350,16351,16352,16353,16354,16355,16356,16357,
+16358,16359,16360,16361,16362,16363,16364,16365,16366,16367,16368,16369,
+16370,16371,16372,16373,16374,16375,16376,16377,16378,16379,16380,16381,
+16382,16383,16384,16385,16386,16387,16388,16389,16390,16391,16392,16393,
+16394,16395,16396,16397,16398,16399,16400,16401,16402,16403,16404,16405,
+16406,16407,16408,16409,16410,16411,16412,16413,16414,16415,16416,16417,
+16418,16419,16420,16421,16422,16423,16424,16425,16426,16427,16428,16429,
+16430,16431,16432,16433,16434,16435,16436,16437,16438,16439,16440,16441,
+16442,16443,16444,16445,16446,16447,16448,16449,16450,16451,16452,16453,
+16454,16455,16456,16457,16458,16459,16460,16461,16462,16463,16464,16465,
+16466,16467,16468,16469,16470,16471,16472,16473,16474,16475,16476,16477,
+16478,16479,16480,16481,16482,16483,16484,16485,16486,16487,16488,16489,
+16490,16491,16492,16493,16494,16495,16496,16497,16498,16499,16500,16501,
+16502,16503,16504,16505,16506,16507,16508,16509,16510,16511,16512,16513,
+16514,16515,16516,16517,16518,16519,16520,16521,16522,16523,16524,16525,
+16526,16527,16528,16529,16530,16531,16532,16533,16534,16535,16536,16537,
+16538,16539,16540,16541,16542,16543,16544,16545,16546,16547,16548,16549,
+16550,16551,16552,16553,16554,16555,16556,16557,16558,16559,16560,16561,
+16562,16563,16564,16565,16566,16567,16568,16569,16570,16571,16572,16573,
+16574,16575,16576,16577,16578,16579,16580,16581,16582,16583,16584,16585,
+16586,16587,16588,16589,16590,16591,16592,16593,16594,16595,16596,16597,
+16598,16599,16600,16601,16602,16603,16604,16605,16606,16607,16608,16609,
+16610,16611,16612,16613,16614,16615,16616,16617,16618,16619,16620,16621,
+16622,16623,16624,16625,16626,16627,16628,16629,16630,16631,16632,16633,
+16634,16635,16636,16637,16638,16639,16640,16641,16642,16643,16644,16645,
+16646,16647,16648,16649,16650,16651,16652,16653,16654,16655,16656,16657,
+16658,16659,16660,16661,16662,16663,16664,16665,16666,16667,16668,16669,
+16670,16671,16672,16673,16674,16675,16676,16677,16678,16679,16680,16681,
+16682,16683,16684,16685,16686,16687,16688,16689,16690,16691,16692,16693,
+16694,16695,16696,16697,16698,16699,16700,16701,16702,16703,16704,16705,
+16706,16707,16708,16709,16710,16711,16712,16713,16714,16715,16716,16717,
+16718,16719,16720,16721,16722,16723,16724,16725,16726,16727,16728,16729,
+16730,16731,16732,16733,16734,16735,16736,16737,16738,16739,16740,16741,
+16742,16743,16744,16745,16746,16747,16748,16749,16750,16751,16752,16753,
+16754,16755,16756,16757,16758,16759,16760,16761,16762,16763,16764,16765,
+16766,16767,16768,16769,16770,16771,16772,16773,16774,16775,16776,16777,
+16778,16779,16780,16781,16782,16783,16784,16785,16786,16787,16788,16789,
+16790,16791,16792,16793,16794,16795,16796,16797,16798,16799,16800,16801,
+16802,16803,16804,16805,16806,16807,16808,16809,16810,16811,16812,16813,
+16814,16815,16816,16817,16818,16819,16820,16821,16822,16823,16824,16825,
+16826,16827,16828,16829,16830,16831,16832,16833,16834,16835,16836,16837,
+16838,16839,16840,16841,16842,16843,16844,16845,16846,16847,16848,16849,
+16850,16851,16852,16853,16854,16855,16856,16857,16858,16859,16860,16861,
+16862,16863,16864,16865,16866,16867,16868,16869,16870,16871,16872,16873,
+16874,16875,16876,16877,16878,16879,16880,16881,16882,16883,16884,16885,
+16886,16887,16888,16889,16890,16891,16892,16893,16894,16895,16896,16897,
+16898,16899,16900,16901,16902,16903,16904,16905,16906,16907,16908,16909,
+16910,16911,16912,16913,16914,16915,16916,16917,16918,16919,16920,16921,
+16922,16923,16924,16925,16926,16927,16928,16929,16930,16931,16932,16933,
+16934,16935,16936,16937,16938,16939,16940,16941,16942,16943,16944,16945,
+16946,16947,16948,16949,16950,16951,16952,16953,16954,16955,16956,16957,
+16958,16959,16960,16961,16962,16963,16964,16965,16966,16967,16968,16969,
+16970,16971,16972,16973,16974,16975,16976,16977,16978,16979,16980,16981,
+16982,16983,16984,16985,16986,16987,16988,16989,16990,16991,16992,16993,
+16994,16995,16996,16997,16998,16999,17000,17001,17002,17003,17004,17005,
+17006,17007,17008,17009,17010,17011,17012,17013,17014,17015,17016,17017,
+17018,17019,17020,17021,17022,17023,17024,17025,17026,17027,17028,17029,
+17030,17031,17032,17033,17034,17035,17036,17037,17038,17039,17040,17041,
+17042,17043,17044,17045,17046,17047,17048,17049,17050,17051,17052,17053,
+17054,17055,17056,17057,17058,17059,17060,17061,17062,17063,17064,17065,
+17066,17067,17068,17069,17070,17071,17072,17073,17074,17075,17076,17077,
+17078,17079,17080,17081,17082,17083,17084,17085,17086,17087,17088,17089,
+17090,17091,17092,17093,17094,17095,17096,17097,17098,17099,17100,17101,
+17102,17103,17104,17105,17106,17107,17108,17109,17110,17111,17112,17113,
+17114,17115,17116,17117,17118,17119,17120,17121,17122,17123,17124,17125,
+17126,17127,17128,17129,17130,17131,17132,17133,17134,17135,17136,17137,
+17138,17139,17140,17141,17142,17143,17144,17145,17146,17147,17148,17149,
+17150,17151,17152,17153,17154,17155,17156,17157,17158,17159,17160,17161,
+17162,17163,17164,17165,17166,17167,17168,17169,17170,17171,17172,17173,
+17174,17175,17176,17177,17178,17179,17180,17181,17182,17183,17184,17185,
+17186,17187,17188,17189,17190,17191,17192,17193,17194,17195,17196,17197,
+17198,17199,17200,17201,17202,17203,17204,17205,17206,17207,17208,17209,
+17210,17211,17212,17213,17214,17215,17216,17217,17218,17219,17220,17221,
+17222,17223,17224,17225,17226,17227,17228,17229,17230,17231,17232,17233,
+17234,17235,17236,17237,17238,17239,17240,17241,17242,17243,17244,17245,
+17246,17247,17248,17249,17250,17251,17252,17253,17254,17255,17256,17257,
+17258,17259,17260,17261,17262,17263,17264,17265,17266,17267,17268,17269,
+17270,17271,17272,17273,17274,17275,17276,17277,17278,17279,17280,17281,
+17282,17283,17284,17285,17286,17287,17288,17289,17290,17291,17292,17293,
+17294,17295,17296,17297,17298,17299,17300,17301,17302,17303,17304,17305,
+17306,17307,17308,17309,17310,17311,17312,17313,17314,17315,17316,17317,
+17318,17319,17320,17321,17322,17323,17324,17325,17326,17327,17328,17329,
+17330,17331,17332,17333,17334,17335,17336,17337,17338,17339,17340,17341,
+17342,17343,17344,17345,17346,17347,17348,17349,17350,17351,17352,17353,
+17354,17355,17356,17357,17358,17359,17360,17361,17362,17363,17364,17365,
+17366,17367,17368,17369,17370,17371,17372,17373,17374,17375,17376,17377,
+17378,17379,17380,17381,17382,17383,17384,17385,17386,17387,17388,17389,
+17390,17391,17392,17393,17394,17395,17396,17397,17398,17399,17400,17401,
+17402,17403,17404,17405,17406,17407,17408,17409,17410,17411,17412,17413,
+17414,17415,17416,17417,17418,17419,17420,17421,17422,17423,17424,17425,
+17426,17427,17428,17429,17430,17431,17432,17433,17434,17435,17436,17437,
+17438,17439,17440,17441,17442,17443,17444,17445,17446,17447,17448,17449,
+17450,17451,17452,17453,17454,17455,17456,17457,17458,17459,17460,17461,
+17462,17463,17464,17465,17466,17467,17468,17469,17470,17471,17472,17473,
+17474,17475,17476,17477,17478,17479,17480,17481,17482,17483,17484,17485,
+17486,17487,17488,17489,17490,17491,17492,17493,17494,17495,17496,17497,
+17498,17499,17500,17501,17502,17503,17504,17505,17506,17507,17508,17509,
+17510,17511,17512,17513,17514,17515,17516,17517,17518,17519,17520,17521,
+17522,17523,17524,17525,17526,17527,17528,17529,17530,17531,17532,17533,
+17534,17535,17536,17537,17538,17539,17540,17541,17542,17543,17544,17545,
+17546,17547,17548,17549,17550,17551,17552,17553,17554,17555,17556,17557,
+17558,17559,17560,17561,17562,17563,17564,17565,17566,17567,17568,17569,
+17570,17571,17572,17573,17574,17575,17576,17577,17578,17579,17580,17581,
+17582,17583,17584,17585,17586,17587,17588,17589,17590,17591,17592,17593,
+17594,17595,17596,17597,17598,17599,17600,17601,17602,17603,17604,17605,
+17606,17607,17608,17609,17610,17611,17612,17613,17614,17615,17616,17617,
+17618,17619,17620,17621,17622,17623,17624,17625,17626,17627,17628,17629,
+17630,17631,17632,17633,17634,17635,17636,17637,17638,17639,17640,17641,
+17642,17643,17644,17645,17646,17647,17648,17649,17650,17651,17652,17653,
+17654,17655,17656,17657,17658,17659,17660,17661,17662,17663,17664,17665,
+17666,17667,17668,17669,17670,17671,17672,17673,17674,17675,17676,17677,
+17678,17679,17680,17681,17682,17683,17684,17685,17686,17687,17688,17689,
+17690,17691,17692,17693,17694,17695,17696,17697,17698,17699,17700,17701,
+17702,17703,17704,17705,17706,17707,17708,17709,17710,17711,17712,17713,
+17714,17715,17716,17717,17718,17719,17720,17721,17722,17723,17724,17725,
+17726,17727,17728,17729,17730,17731,17732,17733,17734,17735,17736,17737,
+17738,17739,17740,17741,17742,17743,17744,17745,17746,17747,17748,17749,
+17750,17751,17752,17753,17754,17755,17756,17757,17758,17759,17760,17761,
+17762,17763,17764,17765,17766,17767,17768,17769,17770,17771,17772,17773,
+17774,17775,17776,17777,17778,17779,17780,17781,17782,17783,17784,17785,
+17786,17787,17788,17789,17790,17791,17792,17793,17794,17795,17796,17797,
+17798,17799,17800,17801,17802,17803,17804,17805,17806,17807,17808,17809,
+17810,17811,17812,17813,17814,17815,17816,17817,17818,17819,17820,17821,
+17822,17823,17824,17825,17826,17827,17828,17829,17830,17831,17832,17833,
+17834,17835,17836,17837,17838,17839,17840,17841,17842,17843,17844,17845,
+17846,17847,17848,17849,17850,17851,17852,17853,17854,17855,17856,17857,
+17858,17859,17860,17861,17862,17863,17864,17865,17866,17867,17868,17869,
+17870,17871,17872,17873,17874,17875,17876,17877,17878,17879,17880,17881,
+17882,17883,17884,17885,17886,17887,17888,17889,17890,17891,17892,17893,
+17894,17895,17896,17897,17898,17899,17900,17901,17902,17903,17904,17905,
+17906,17907,17908,17909,17910,17911,17912,17913,17914,17915,17916,17917,
+17918,17919,17920,17921,17922,17923,17924,17925,17926,17927,17928,17929,
+17930,17931,17932,17933,17934,17935,17936,17937,17938,17939,17940,17941,
+17942,17943,17944,17945,17946,17947,17948,17949,17950,17951,17952,17953,
+17954,17955,17956,17957,17958,17959,17960,17961,17962,17963,17964,17965,
+17966,17967,17968,17969,17970,17971,17972,17973,17974,17975,17976,17977,
+17978,17979,17980,17981,17982,17983,17984,17985,17986,17987,17988,17989,
+17990,17991,17992,17993,17994,17995,17996,17997,17998,17999,18000,18001,
+18002,18003,18004,18005,18006,18007,18008,18009,18010,18011,18012,18013,
+18014,18015,18016,18017,18018,18019,18020,18021,18022,18023,18024,18025,
+18026,18027,18028,18029,18030,18031,18032,18033,18034,18035,18036,18037,
+18038,18039,18040,18041,18042,18043,18044,18045,18046,18047,18048,18049,
+18050,18051,18052,18053,18054,18055,18056,18057,18058,18059,18060,18061,
+18062,18063,18064,18065,18066,18067,18068,18069,18070,18071,18072,18073,
+18074,18075,18076,18077,18078,18079,18080,18081,18082,18083,18084,18085,
+18086,18087,18088,18089,18090,18091,18092,18093,18094,18095,18096,18097,
+18098,18099,18100,18101,18102,18103,18104,18105,18106,18107,18108,18109,
+18110,18111,18112,18113,18114,18115,18116,18117,18118,18119,18120,18121,
+18122,18123,18124,18125,18126,18127,18128,18129,18130,18131,18132,18133,
+18134,18135,18136,18137,18138,18139,18140,18141,18142,18143,18144,18145,
+18146,18147,18148,18149,18150,18151,18152,18153,18154,18155,18156,18157,
+18158,18159,18160,18161,18162,18163,18164,18165,18166,18167,18168,18169,
+18170,18171,18172,18173,18174,18175,18176,18177,18178,18179,18180,18181,
+18182,18183,18184,18185,18186,18187,18188,18189,18190,18191,18192,18193,
+18194,18195,18196,18197,18198,18199,18200,18201,18202,18203,18204,18205,
+18206,18207,18208,18209,18210,18211,18212,18213,18214,18215,18216,18217,
+18218,18219,18220,18221,18222,18223,18224,18225,18226,18227,18228,18229,
+18230,18231,18232,18233,18234,18235,18236,18237,18238,18239,18240,18241,
+18242,18243,18244,18245,18246,18247,18248,18249,18250,18251,18252,18253,
+18254,18255,18256,18257,18258,18259,18260,18261,18262,18263,18264,18265,
+18266,18267,18268,18269,18270,18271,18272,18273,18274,18275,18276,18277,
+18278,18279,18280,18281,18282,18283,18284,18285,18286,18287,18288,18289,
+18290,18291,18292,18293,18294,18295,18296,18297,18298,18299,18300,18301,
+18302,18303,18304,18305,18306,18307,18308,18309,18310,18311,18312,18313,
+18314,18315,18316,18317,18318,18319,18320,18321,18322,18323,18324,18325,
+18326,18327,18328,18329,18330,18331,18332,18333,18334,18335,18336,18337,
+18338,18339,18340,18341,18342,18343,18344,18345,18346,18347,18348,18349,
+18350,18351,18352,18353,18354,18355,18356,18357,18358,18359,18360,18361,
+18362,18363,18364,18365,18366,18367,18368,18369,18370,18371,18372,18373,
+18374,18375,18376,18377,18378,18379,18380,18381,18382,18383,18384,18385,
+18386,18387,18388,18389,18390,18391,18392,18393,18394,18395,18396,18397,
+18398,18399,18400,18401,18402,18403,18404,18405,18406,18407,18408,18409,
+18410,18411,18412,18413,18414,18415,18416,18417,18418,18419,18420,18421,
+18422,18423,18424,18425,18426,18427,18428,18429,18430,18431,18432,18433,
+18434,18435,18436,18437,18438,18439,18440,18441,18442,18443,18444,18445,
+18446,18447,18448,18449,18450,18451,18452,18453,18454,18455,18456,18457,
+18458,18459,18460,18461,18462,18463,18464,18465,18466,18467,18468,18469,
+18470,18471,18472,18473,18474,18475,18476,18477,18478,18479,18480,18481,
+18482,18483,18484,18485,18486,18487,18488,18489,18490,18491,18492,18493,
+18494,18495,18496,18497,18498,18499,18500,18501,18502,18503,18504,18505,
+18506,18507,18508,18509,18510,18511,18512,18513,18514,18515,18516,18517,
+18518,18519,18520,18521,18522,18523,18524,18525,18526,18527,18528,18529,
+18530,18531,18532,18533,18534,18535,18536,18537,18538,18539,18540,18541,
+18542,18543,18544,18545,18546,18547,18548,18549,18550,18551,18552,18553,
+18554,18555,18556,18557,18558,18559,18560,18561,18562,18563,18564,18565,
+18566,18567,18568,18569,18570,18571,18572,18573,18574,18575,18576,18577,
+18578,18579,18580,18581,18582,18583,18584,18585,18586,18587,18588,18589,
+18590,18591,18592,18593,18594,18595,18596,18597,18598,18599,18600,18601,
+18602,18603,18604,18605,18606,18607,18608,18609,18610,18611,18612,18613,
+18614,18615,18616,18617,18618,18619,18620,18621,18622,18623,18624,18625,
+18626,18627,18628,18629,18630,18631,18632,18633,18634,18635,18636,18637,
+18638,18639,18640,18641,18642,18643,18644,18645,18646,18647,18648,18649,
+18650,18651,18652,18653,18654,18655,18656,18657,18658,18659,18660,18661,
+18662,18663,18664,18665,18666,18667,18668,18669,18670,18671,18672,18673,
+18674,18675,18676,18677,18678,18679,18680,18681,18682,18683,18684,18685,
+18686,18687,18688,18689,18690,18691,18692,18693,18694,18695,18696,18697,
+18698,18699,18700,18701,18702,18703,18704,18705,18706,18707,18708,18709,
+18710,18711,18712,18713,18714,18715,18716,18717,18718,18719,18720,18721,
+18722,18723,18724,18725,18726,18727,18728,18729,18730,18731,18732,18733,
+18734,18735,18736,18737,18738,18739,18740,18741,18742,18743,18744,18745,
+18746,18747,18748,18749,18750,18751,18752,18753,18754,18755,18756,18757,
+18758,18759,18760,18761,18762,18763,18764,18765,18766,18767,18768,18769,
+18770,18771,18772,18773,18774,18775,18776,18777,18778,18779,18780,18781,
+18782,18783,18784,18785,18786,18787,18788,18789,18790,18791,18792,18793,
+18794,18795,18796,18797,18798,18799,18800,18801,18802,18803,18804,18805,
+18806,18807,18808,18809,18810,18811,18812,18813,18814,18815,18816,18817,
+18818,18819,18820,18821,18822,18823,18824,18825,18826,18827,18828,18829,
+18830,18831,18832,18833,18834,18835,18836,18837,18838,18839,18840,18841,
+18842,18843,18844,18845,18846,18847,18848,18849,18850,18851,18852,18853,
+18854,18855,18856,18857,18858,18859,18860,18861,18862,18863,18864,18865,
+18866,18867,18868,18869,18870,18871,18872,18873,18874,18875,18876,18877,
+18878,18879,18880,18881,18882,18883,18884,18885,18886,18887,18888,18889,
+18890,18891,18892,18893,18894,18895,18896,18897,18898,18899,18900,18901,
+18902,18903,18904,18905,18906,18907,18908,18909,18910,18911,18912,18913,
+18914,18915,18916,18917,18918,18919,18920,18921,18922,18923,18924,18925,
+18926,18927,18928,18929,18930,18931,18932,18933,18934,18935,18936,18937,
+18938,18939,18940,18941,18942,18943,18944,18945,18946,18947,18948,18949,
+18950,18951,18952,18953,18954,18955,18956,18957,18958,18959,18960,18961,
+18962,18963,18964,18965,18966,18967,18968,18969,18970,18971,18972,18973,
+18974,18975,18976,18977,18978,18979,18980,18981,18982,18983,18984,18985,
+18986,18987,18988,18989,18990,18991,18992,18993,18994,18995,18996,18997,
+18998,18999,19000,19001,19002,19003,19004,19005,19006,19007,19008,19009,
+19010,19011,19012,19013,19014,19015,19016,19017,19018,19019,19020,19021,
+19022,19023,19024,19025,19026,19027,19028,19029,19030,19031,19032,19033,
+19034,19035,19036,19037,19038,19039,19040,19041,19042,19043,19044,19045,
+19046,19047,19048,19049,19050,19051,19052,19053,19054,19055,19056,19057,
+19058,19059,19060,19061,19062,19063,19064,19065,19066,19067,19068,19069,
+19070,19071,19072,19073,19074,19075,19076,19077,19078,19079,19080,19081,
+19082,19083,19084,19085,19086,19087,19088,19089,19090,19091,19092,19093,
+19094,19095,19096,19097,19098,19099,19100,19101,19102,19103,19104,19105,
+19106,19107,19108,19109,19110,19111,19112,19113,19114,19115,19116,19117,
+19118,19119,19120,19121,19122,19123,19124,19125,19126,19127,19128,19129,
+19130,19131,19132,19133,19134,19135,19136,19137,19138,19139,19140,19141,
+19142,19143,19144,19145,19146,19147,19148,19149,19150,19151,19152,19153,
+19154,19155,19156,19157,19158,19159,19160,19161,19162,19163,19164,19165,
+19166,19167,19168,19169,19170,19171,19172,19173,19174,19175,19176,19177,
+19178,19179,19180,19181,19182,19183,19184,19185,19186,19187,19188,19189,
+19190,19191,19192,19193,19194,19195,19196,19197,19198,19199,19200,19201,
+19202,19203,19204,19205,19206,19207,19208,19209,19210,19211,19212,19213,
+19214,19215,19216,19217,19218,19219,19220,19221,19222,19223,19224,19225,
+19226,19227,19228,19229,19230,19231,19232,19233,19234,19235,19236,19237,
+19238,19239,19240,19241,19242,19243,19244,19245,19246,19247,19248,19249,
+19250,19251,19252,19253,19254,19255,19256,19257,19258,19259,19260,19261,
+19262,19263,19264,19265,19266,19267,19268,19269,19270,19271,19272,19273,
+19274,19275,19276,19277,19278,19279,19280,19281,19282,19283,19284,19285,
+19286,19287,19288,19289,19290,19291,19292,19293,19294,19295,19296,19297,
+19298,19299,19300,19301,19302,19303,19304,19305,19306,19307,19308,19309,
+19310,19311,19312,19313,19314,19315,19316,19317,19318,19319,19320,19321,
+19322,19323,19324,19325,19326,19327,19328,19329,19330,19331,19332,19333,
+19334,19335,19336,19337,19338,19339,19340,19341,19342,19343,19344,19345,
+19346,19347,19348,19349,19350,19351,19352,19353,19354,19355,19356,19357,
+19358,19359,19360,19361,19362,19363,19364,19365,19366,19367,19368,19369,
+19370,19371,19372,19373,19374,19375,19376,19377,19378,19379,19380,19381,
+19382,19383,19384,19385,19386,19387,19388,19389,19390,19391,19392,19393,
+19394,19395,19396,19397,19398,19399,19400,19401,19402,19403,19404,19405,
+19406,19407,19408,19409,19410,19411,19412,19413,19414,19415,19416,19417,
+19418,19419,19420,19421,19422,19423,19424,19425,19426,19427,19428,19429,
+19430,19431,19432,19433,19434,19435,19436,19437,19438,19439,19440,19441,
+19442,19443,19444,19445,19446,19447,19448,19449,19450,19451,19452,19453,
+19454,19455,19456,19457,19458,19459,19460,19461,19462,19463,19464,19465,
+19466,19467,19468,19469,19470,19471,19472,19473,19474,19475,19476,19477,
+19478,19479,19480,19481,19482,19483,19484,19485,19486,19487,19488,19489,
+19490,19491,19492,19493,19494,19495,19496,19497,19498,19499,19500,19501,
+19502,19503,19504,19505,19506,19507,19508,19509,19510,19511,19512,19513,
+19514,19515,19516,19517,19518,19519,19520,19521,19522,19523,19524,19525,
+19526,19527,19528,19529,19530,19531,19532,19533,19534,19535,19536,19537,
+19538,19539,19540,19541,19542,19543,19544,19545,19546,19547,19548,19549,
+19550,19551,19552,19553,19554,19555,19556,19557,19558,19559,19560,19561,
+19562,19563,19564,19565,19566,19567,19568,19569,19570,19571,19572,19573,
+19574,19575,19576,19577,19578,19579,19580,19581,19582,19583,19584,19585,
+19586,19587,19588,19589,19590,19591,19592,19593,19594,19595,19596,19597,
+19598,19599,19600,19601,19602,19603,19604,19605,19606,19607,19608,19609,
+19610,19611,19612,19613,19614,19615,19616,19617,19618,19619,19620,19621,
+19622,19623,19624,19625,19626,19627,19628,19629,19630,19631,19632,19633,
+19634,19635,19636,19637,19638,19639,19640,19641,19642,19643,19644,19645,
+19646,19647,19648,19649,19650,19651,19652,19653,19654,19655,19656,19657,
+19658,19659,19660,19661,19662,19663,19664,19665,19666,19667,19668,19669,
+19670,19671,19672,19673,19674,19675,19676,19677,19678,19679,19680,19681,
+19682,19683,19684,19685,19686,19687,19688,19689,19690,19691,19692,19693,
+19694,19695,19696,19697,19698,19699,19700,19701,19702,19703,19704,19705,
+19706,19707,19708,19709,19710,19711,19712,19713,19714,19715,19716,19717,
+19718,19719,19720,19721,19722,19723,19724,19725,19726,19727,19728,19729,
+19730,19731,19732,19733,19734,19735,19736,19737,19738,19739,19740,19741,
+19742,19743,19744,19745,19746,19747,19748,19749,19750,19751,19752,19753,
+19754,19755,19756,19757,19758,19759,19760,19761,19762,19763,19764,19765,
+19766,19767,19768,19769,19770,19771,19772,19773,19774,19775,19776,19777,
+19778,19779,19780,19781,19782,19783,19784,19785,19786,19787,19788,19789,
+19790,19791,19792,19793,19794,19795,19796,19797,19798,19799,19800,19801,
+19802,19803,19804,19805,19806,19807,19808,19809,19810,19811,19812,19813,
+19814,19815,19816,19817,19818,19819,19820,19821,19822,19823,19824,19825,
+19826,19827,19828,19829,19830,19831,19832,19833,19834,19835,19836,19837,
+19838,19839,19840,19841,19842,19843,19844,19845,19846,19847,19848,19849,
+19850,19851,19852,19853,19854,19855,19856,19857,19858,19859,19860,19861,
+19862,19863,19864,19865,19866,19867,19868,19869,19870,19871,19872,19873,
+19874,19875,19876,19877,19878,19879,19880,19881,19882,19883,19884,19885,
+19886,19887,19888,19889,19890,19891,19892,19893,19894,19895,19896,19897,
+19898,19899,19900,19901,19902,19903,19904,19905,19906,19907,19908,19909,
+19910,19911,19912,19913,19914,19915,19916,19917,19918,19919,19920,19921,
+19922,19923,19924,19925,19926,19927,19928,19929,19930,19931,19932,19933,
+19934,19935,19936,19937,19938,19939,19940,19941,19942,19943,19944,19945,
+19946,19947,19948,19949,19950,19951,19952,19953,19954,19955,19956,19957,
+19958,19959,19960,19961,19962,19963,19964,19965,19966,19967,19968,19969,
+19970,19971,19972,19973,19974,19975,19976,19977,19978,19979,19980,19981,
+19982,19983,19984,19985,19986,19987,19988,19989,19990,19991,19992,19993,
+19994,19995,19996,19997,19998,19999,20000,20001,20002,20003,20004,20005,
+20006,20007,20008,20009,20010,20011,20012,20013,20014,20015,20016,20017,
+20018,20019,20020,20021,20022,20023,20024,20025,20026,20027,20028,20029,
+20030,20031,20032,20033,20034,20035,20036,20037,20038,20039,20040,20041,
+20042,20043,20044,20045,20046,20047,20048,20049,20050,20051,20052,20053,
+20054,20055,20056,20057,20058,20059,20060,20061,20062,20063,20064,20065,
+20066,20067,20068,20069,20070,20071,20072,20073,20074,20075,20076,20077,
+20078,20079,20080,20081,20082,20083,20084,20085,20086,20087,20088,20089,
+20090,20091,20092,20093,20094,20095,20096,20097,20098,20099,20100,20101,
+20102,20103,20104,20105,20106,20107,20108,20109,20110,20111,20112,20113,
+20114,20115,20116,20117,20118,20119,20120,20121,20122,20123,20124,20125,
+20126,20127,20128,20129,20130,20131,20132,20133,20134,20135,20136,20137,
+20138,20139,20140,20141,20142,20143,20144,20145,20146,20147,20148,20149,
+20150,20151,20152,20153,20154,20155,20156,20157,20158,20159,20160,20161,
+20162,20163,20164,20165,20166,20167,20168,20169,20170,20171,20172,20173,
+20174,20175,20176,20177,20178,20179,20180,20181,20182,20183,20184,20185,
+20186,20187,20188,20189,20190,20191,20192,20193,20194,20195,20196,20197,
+20198,20199,20200,20201,20202,20203,20204,20205,20206,20207,20208,20209,
+20210,20211,20212,20213,20214,20215,20216,20217,20218,20219,20220,20221,
+20222,20223,20224,20225,20226,20227,20228,20229,20230,20231,20232,20233,
+20234,20235,20236,20237,20238,20239,20240,20241,20242,20243,20244,20245,
+20246,20247,20248,20249,20250,20251,20252,20253,20254,20255,20256,20257,
+20258,20259,20260,20261,20262,20263,20264,20265,20266,20267,20268,20269,
+20270,20271,20272,20273,20274,20275,20276,20277,20278,20279,20280,20281,
+20282,20283,20284,20285,20286,20287,20288,20289,20290,20291,20292,20293,
+20294,20295,20296,20297,20298,20299,20300,20301,20302,20303,20304,20305,
+20306,20307,20308,20309,20310,20311,20312,20313,20314,20315,20316,20317,
+20318,20319,20320,20321,20322,20323,20324,20325,20326,20327,20328,20329,
+20330,20331,20332,20333,20334,20335,20336,20337,20338,20339,20340,20341,
+20342,20343,20344,20345,20346,20347,20348,20349,20350,20351,20352,20353,
+20354,20355,20356,20357,20358,20359,20360,20361,20362,20363,20364,20365,
+20366,20367,20368,20369,20370,20371,20372,20373,20374,20375,20376,20377,
+20378,20379,20380,20381,20382,20383,20384,20385,20386,20387,20388,20389,
+20390,20391,20392,20393,20394,20395,20396,20397,20398,20399,20400,20401,
+20402,20403,20404,20405,20406,20407,20408,20409,20410,20411,20412,20413,
+20414,20415,20416,20417,20418,20419,20420,20421,20422,20423,20424,20425,
+20426,20427,20428,20429,20430,20431,20432,20433,20434,20435,20436,20437,
+20438,20439,20440,20441,20442,20443,20444,20445,20446,20447,20448,20449,
+20450,20451,20452,20453,20454,20455,20456,20457,20458,20459,20460,20461,
+20462,20463,20464,20465,20466,20467,20468,20469,20470,20471,20472,20473,
+20474,20475,20476,20477,20478,20479,20480,20481,20482,20483,20484,20485,
+20486,20487,20488,20489,20490,20491,20492,20493,20494,20495,20496,20497,
+20498,20499,20500,20501,20502,20503,20504,20505,20506,20507,20508,20509,
+20510,20511,20512,20513,20514,20515,20516,20517,20518,20519,20520,20521,
+20522,20523,20524,20525,20526,20527,20528,20529,20530,20531,20532,20533,
+20534,20535,20536,20537,20538,20539,20540,20541,20542,20543,20544,20545,
+20546,20547,20548,20549,20550,20551,20552,20553,20554,20555,20556,20557,
+20558,20559,20560,20561,20562,20563,20564,20565,20566,20567,20568,20569,
+20570,20571,20572,20573,20574,20575,20576,20577,20578,20579,20580,20581,
+20582,20583,20584,20585,20586,20587,20588,20589,20590,20591,20592,20593,
+20594,20595,20596,20597,20598,20599,20600,20601,20602,20603,20604,20605,
+20606,20607,20608,20609,20610,20611,20612,20613,20614,20615,20616,20617,
+20618,20619,20620,20621,20622,20623,20624,20625,20626,20627,20628,20629,
+20630,20631,20632,20633,20634,20635,20636,20637,20638,20639,20640,20641,
+20642,20643,20644,20645,20646,20647,20648,20649,20650,20651,20652,20653,
+20654,20655,20656,20657,20658,20659,20660,20661,20662,20663,20664,20665,
+20666,20667,20668,20669,20670,20671,20672,20673,20674,20675,20676,20677,
+20678,20679,20680,20681,20682,20683,20684,20685,20686,20687,20688,20689,
+20690,20691,20692,20693,20694,20695,20696,20697,20698,20699,20700,20701,
+20702,20703,20704,20705,20706,20707,20708,20709,20710,20711,20712,20713,
+20714,20715,20716,20717,20718,20719,20720,20721,20722,20723,20724,20725,
+20726,20727,20728,20729,20730,20731,20732,20733,20734,20735,20736,20737,
+20738,20739,20740,20741,20742,20743,20744,20745,20746,20747,20748,20749,
+20750,20751,20752,20753,20754,20755,20756,20757,20758,20759,20760,20761,
+20762,20763,20764,20765,20766,20767,20768,20769,20770,20771,20772,20773,
+20774,20775,20776,20777,20778,20779,20780,20781,20782,20783,20784,20785,
+20786,20787,20788,20789,20790,20791,20792,20793,20794,20795,20796,20797,
+20798,20799,20800,20801,20802,20803,20804,20805,20806,20807,20808,20809,
+20810,20811,20812,20813,20814,20815,20816,20817,20818,20819,20820,20821,
+20822,20823,20824,20825,20826,20827,20828,20829,20830,20831,20832,20833,
+20834,20835,20836,20837,20838,20839,20840,20841,20842,20843,20844,20845,
+20846,20847,20848,20849,20850,20851,20852,20853,20854,20855,20856,20857,
+20858,20859,20860,20861,20862,20863,20864,20865,20866,20867,20868,20869,
+20870,20871,20872,20873,20874,20875,20876,20877,20878,20879,20880,20881,
+20882,20883,20884,20885,20886,20887,20888,20889,20890,20891,20892,20893,
+20894,20895,20896,20897,20898,20899,20900,20901,20902,20903,20904,20905,
+20906,20907,20908,20909,20910,20911,20912,20913,20914,20915,20916,20917,
+20918,20919,20920,20921,20922,20923,20924,20925,20926,20927,20928,20929,
+20930,20931,20932,20933,20934,20935,20936,20937,20938,20939,20940,20941,
+20942,20943,20944,20945,20946,20947,20948,20949,20950,20951,20952,20953,
+20954,20955,20956,20957,20958,20959,20960,20961,20962,20963,20964,20965,
+20966,20967,20968,20969,20970,20971,20972,20973,20974,20975,20976,20977,
+20978,20979,20980,20981,20982,20983,20984,20985,20986,20987,20988,20989,
+20990,20991,20992,20993,20994,20995,20996,20997,20998,20999,21000,21001,
+21002,21003,21004,21005,21006,21007,21008,21009,21010,21011,21012,21013,
+21014,21015,21016,21017,21018,21019,21020,21021,21022,21023,21024,21025,
+21026,21027,21028,21029,21030,21031,21032,21033,21034,21035,21036,21037,
+21038,21039,21040,21041,21042,21043,21044,21045,21046,21047,21048,21049,
+21050,21051,21052,21053,21054,21055,21056,21057,21058,21059,21060,21061,
+21062,21063,21064,21065,21066,21067,21068,21069,21070,21071,21072,21073,
+21074,21075,21076,21077,21078,21079,21080,21081,21082,21083,21084,21085,
+21086,21087,21088,21089,21090,21091,21092,21093,21094,21095,21096,21097,
+21098,21099,21100,21101,21102,21103,21104,21105,21106,21107,21108,21109,
+21110,21111,21112,21113,21114,21115,21116,21117,21118,21119,21120,21121,
+21122,21123,21124,21125,21126,21127,21128,21129,21130,21131,21132,21133,
+21134,21135,21136,21137,21138,21139,21140,21141,21142,21143,21144,21145,
+21146,21147,21148,21149,21150,21151,21152,21153,21154,21155,21156,21157,
+21158,21159,21160,21161,21162,21163,21164,21165,21166,21167,21168,21169,
+21170,21171,21172,21173,21174,21175,21176,21177,21178,21179,21180,21181,
+21182,21183,21184,21185,21186,21187,21188,21189,21190,21191,21192,21193,
+21194,21195,21196,21197,21198,21199,21200,21201,21202,21203,21204,21205,
+21206,21207,21208,21209,21210,21211,21212,21213,21214,21215,21216,21217,
+21218,21219,21220,21221,21222,21223,21224,21225,21226,21227,21228,21229,
+21230,21231,21232,21233,21234,21235,21236,21237,21238,21239,21240,21241,
+21242,21243,21244,21245,21246,21247,21248,21249,21250,21251,21252,21253,
+21254,21255,21256,21257,21258,21259,21260,21261,21262,21263,21264,21265,
+21266,21267,21268,21269,21270,21271,21272,21273,21274,21275,21276,21277,
+21278,21279,21280,21281,21282,21283,21284,21285,21286,21287,21288,21289,
+21290,21291,21292,21293,21294,21295,21296,21297,21298,21299,21300,21301,
+21302,21303,21304,21305,21306,21307,21308,21309,21310,21311,21312,21313,
+21314,21315,21316,21317,21318,21319,21320,21321,21322,21323,21324,21325,
+21326,21327,21328,21329,21330,21331,21332,21333,21334,21335,21336,21337,
+21338,21339,21340,21341,21342,21343,21344,21345,21346,21347,21348,21349,
+21350,21351,21352,21353,21354,21355,21356,21357,21358,21359,21360,21361,
+21362,21363,21364,21365,21366,21367,21368,21369,21370,21371,21372,21373,
+21374,21375,21376,21377,21378,21379,21380,21381,21382,21383,21384,21385,
+21386,21387,21388,21389,21390,21391,21392,21393,21394,21395,21396,21397,
+21398,21399,21400,21401,21402,21403,21404,21405,21406,21407,21408,21409,
+21410,21411,21412,21413,21414,21415,21416,21417,21418,21419,21420,21421,
+21422,21423,21424,21425,21426,21427,21428,21429,21430,21431,21432,21433,
+21434,21435,21436,21437,21438,21439,21440,21441,21442,21443,21444,21445,
+21446,21447,21448,21449,21450,21451,21452,21453,21454,21455,21456,21457,
+21458,21459,21460,21461,21462,21463,21464,21465,21466,21467,21468,21469,
+21470,21471,21472,21473,21474,21475,21476,21477,21478,21479,21480,21481,
+21482,21483,21484,21485,21486,21487,21488,21489,21490,21491,21492,21493,
+21494,21495,21496,21497,21498,21499,21500,21501,21502,21503,21504,21505,
+21506,21507,21508,21509,21510,21511,21512,21513,21514,21515,21516,21517,
+21518,21519,21520,21521,21522,21523,21524,21525,21526,21527,21528,21529,
+21530,21531,21532,21533,21534,21535,21536,21537,21538,21539,21540,21541,
+21542,21543,21544,21545,21546,21547,21548,21549,21550,21551,21552,21553,
+21554,21555,21556,21557,21558,21559,21560,21561,21562,21563,21564,21565,
+21566,21567,21568,21569,21570,21571,21572,21573,21574,21575,21576,21577,
+21578,21579,21580,21581,21582,21583,21584,21585,21586,21587,21588,21589,
+21590,21591,21592,21593,21594,21595,21596,21597,21598,21599,21600,21601,
+21602,21603,21604,21605,21606,21607,21608,21609,21610,21611,21612,21613,
+21614,21615,21616,21617,21618,21619,21620,21621,21622,21623,21624,21625,
+21626,21627,21628,21629,21630,21631,21632,21633,21634,21635,21636,21637,
+21638,21639,21640,21641,21642,21643,21644,21645,21646,21647,21648,21649,
+21650,21651,21652,21653,21654,21655,21656,21657,21658,21659,21660,21661,
+21662,21663,21664,21665,21666,21667,21668,21669,21670,21671,21672,21673,
+21674,21675,21676,21677,21678,21679,21680,21681,21682,21683,21684,21685,
+21686,21687,21688,21689,21690,21691,21692,21693,21694,21695,21696,21697,
+21698,21699,21700,21701,21702,21703,21704,21705,21706,21707,21708,21709,
+21710,21711,21712,21713,21714,21715,21716,21717,21718,21719,21720,21721,
+21722,21723,21724,21725,21726,21727,21728,21729,21730,21731,21732,21733,
+21734,21735,21736,21737,21738,21739,21740,21741,21742,21743,21744,21745,
+21746,21747,21748,21749,21750,21751,21752,21753,21754,21755,21756,21757,
+21758,21759,21760,21761,21762,21763,21764,21765,21766,21767,21768,21769,
+21770,21771,21772,21773,21774,21775,21776,21777,21778,21779,21780,21781,
+21782,21783,21784,21785,21786,21787,21788,21789,21790,21791,21792,21793,
+21794,21795,21796,21797,21798,21799,21800,21801,21802,21803,21804,21805,
+21806,21807,21808,21809,21810,21811,21812,21813,21814,21815,21816,21817,
+21818,21819,21820,21821,21822,21823,21824,21825,21826,21827,21828,21829,
+21830,21831,21832,21833,21834,21835,21836,21837,21838,21839,21840,21841,
+21842,21843,21844,21845,21846,21847,21848,21849,21850,21851,21852,21853,
+21854,21855,21856,21857,21858,21859,21860,21861,21862,21863,21864,21865,
+21866,21867,21868,21869,21870,21871,21872,21873,21874,21875,21876,21877,
+21878,21879,21880,21881,21882,21883,21884,21885,21886,21887,21888,21889,
+21890,21891,21892,21893,21894,21895,21896,21897,21898,21899,21900,21901,
+21902,21903,21904,21905,21906,21907,21908,21909,21910,21911,21912,21913,
+21914,21915,21916,21917,21918,21919,21920,21921,21922,21923,21924,21925,
+21926,21927,21928,21929,21930,21931,21932,21933,21934,21935,21936,21937,
+21938,21939,21940,21941,21942,21943,21944,21945,21946,21947,21948,21949,
+21950,21951,21952,21953,21954,21955,21956,21957,21958,21959,21960,21961,
+21962,21963,21964,21965,21966,21967,21968,21969,21970,21971,21972,21973,
+21974,21975,21976,21977,21978,21979,21980,21981,21982,21983,21984,21985,
+21986,21987,21988,21989,21990,21991,21992,21993,21994,21995,21996,21997,
+21998,21999,22000,22001,22002,22003,22004,22005,22006,22007,22008,22009,
+22010,22011,22012,22013,22014,22015,22016,22017,22018,22019,22020,22021,
+22022,22023,22024,22025,22026,22027,22028,22029,22030,22031,22032,22033,
+22034,22035,22036,22037,22038,22039,22040,22041,22042,22043,22044,22045,
+22046,22047,22048,22049,22050,22051,22052,22053,22054,22055,22056,22057,
+22058,22059,22060,22061,22062,22063,22064,22065,22066,22067,22068,22069,
+22070,22071,22072,22073,22074,22075,22076,22077,22078,22079,22080,22081,
+22082,22083,22084,22085,22086,22087,22088,22089,22090,22091,22092,22093,
+22094,22095,22096,22097,22098,22099,22100,22101,22102,22103,22104,22105,
+22106,22107,22108,22109,22110,22111,22112,22113,22114,22115,22116,22117,
+22118,22119,22120,22121,22122,22123,22124,22125,22126,22127,22128,22129,
+22130,22131,22132,22133,22134,22135,22136,22137,22138,22139,22140,22141,
+22142,22143,22144,22145,22146,22147,22148,22149,22150,22151,22152,22153,
+22154,22155,22156,22157,22158,22159,22160,22161,22162,22163,22164,22165,
+22166,22167,22168,22169,22170,22171,22172,22173,22174,22175,22176,22177,
+22178,22179,22180,22181,22182,22183,22184,22185,22186,22187,22188,22189,
+22190,22191,22192,22193,22194,22195,22196,22197,22198,22199,22200,22201,
+22202,22203,22204,22205,22206,22207,22208,22209,22210,22211,22212,22213,
+22214,22215,22216,22217,22218,22219,22220,22221,22222,22223,22224,22225,
+22226,22227,22228,22229,22230,22231,22232,22233,22234,22235,22236,22237,
+22238,22239,22240,22241,22242,22243,22244,22245,22246,22247,22248,22249,
+22250,22251,22252,22253,22254,22255,22256,22257,22258,22259,22260,22261,
+22262,22263,22264,22265,22266,22267,22268,22269,22270,22271,22272,22273,
+22274,22275,22276,22277,22278,22279,22280,22281,22282,22283,22284,22285,
+22286,22287,22288,22289,22290,22291,22292,22293,22294,22295,22296,22297,
+22298,22299,22300,22301,22302,22303,22304,22305,22306,22307,22308,22309,
+22310,22311,22312,22313,22314,22315,22316,22317,22318,22319,22320,22321,
+22322,22323,22324,22325,22326,22327,22328,22329,22330,22331,22332,22333,
+22334,22335,22336,22337,22338,22339,22340,22341,22342,22343,22344,22345,
+22346,22347,22348,22349,22350,22351,22352,22353,22354,22355,22356,22357,
+22358,22359,22360,22361,22362,22363,22364,22365,22366,22367,22368,22369,
+22370,22371,22372,22373,22374,22375,22376,22377,22378,22379,22380,22381,
+22382,22383,22384,22385,22386,22387,22388,22389,22390,22391,22392,22393,
+22394,22395,22396,22397,22398,22399,22400,22401,22402,22403,22404,22405,
+22406,22407,22408,22409,22410,22411,22412,22413,22414,22415,22416,22417,
+22418,22419,22420,22421,22422,22423,22424,22425,22426,22427,22428,22429,
+22430,22431,22432,22433,22434,22435,22436,22437,22438,22439,22440,22441,
+22442,22443,22444,22445,22446,22447,22448,22449,22450,22451,22452,22453,
+22454,22455,22456,22457,22458,22459,22460,22461,22462,22463,22464,22465,
+22466,22467,22468,22469,22470,22471,22472,22473,22474,22475,22476,22477,
+22478,22479,22480,22481,22482,22483,22484,22485,22486,22487,22488,22489,
+22490,22491,22492,22493,22494,22495,22496,22497,22498,22499,22500,22501,
+22502,22503,22504,22505,22506,22507,22508,22509,22510,22511,22512,22513,
+22514,22515,22516,22517,22518,22519,22520,22521,22522,22523,22524,22525,
+22526,22527,22528,22529,22530,22531,22532,22533,22534,22535,22536,22537,
+22538,22539,22540,22541,22542,22543,22544,22545,22546,22547,22548,22549,
+22550,22551,22552,22553,22554,22555,22556,22557,22558,22559,22560,22561,
+22562,22563,22564,22565,22566,22567,22568,22569,22570,22571,22572,22573,
+22574,22575,22576,22577,22578,22579,22580,22581,22582,22583,22584,22585,
+22586,22587,22588,22589,22590,22591,22592,22593,22594,22595,22596,22597,
+22598,22599,22600,22601,22602,22603,22604,22605,22606,22607,22608,22609,
+22610,22611,22612,22613,22614,22615,22616,22617,22618,22619,22620,22621,
+22622,22623,22624,22625,22626,22627,22628,22629,22630,22631,22632,22633,
+22634,22635,22636,22637,22638,22639,22640,22641,22642,22643,22644,22645,
+22646,22647,22648,22649,22650,22651,22652,22653,22654,22655,22656,22657,
+22658,22659,22660,22661,22662,22663,22664,22665,22666,22667,22668,22669,
+22670,22671,22672,22673,22674,22675,22676,22677,22678,22679,22680,22681,
+22682,22683,22684,22685,22686,22687,22688,22689,22690,22691,22692,22693,
+22694,22695,22696,22697,22698,22699,22700,22701,22702,22703,22704,22705,
+22706,22707,22708,22709,22710,22711,22712,22713,22714,22715,22716,22717,
+22718,22719,22720,22721,22722,22723,22724,22725,22726,22727,22728,22729,
+22730,22731,22732,22733,22734,22735,22736,22737,22738,22739,22740,22741,
+22742,22743,22744,22745,22746,22747,22748,22749,22750,22751,22752,22753,
+22754,22755,22756,22757,22758,22759,22760,22761,22762,22763,22764,22765,
+22766,22767,22768,22769,22770,22771,22772,22773,22774,22775,22776,22777,
+22778,22779,22780,22781,22782,22783,22784,22785,22786,22787,22788,22789,
+22790,22791,22792,22793,22794,22795,22796,22797,22798,22799,22800,22801,
+22802,22803,22804,22805,22806,22807,22808,22809,22810,22811,22812,22813,
+22814,22815,22816,22817,22818,22819,22820,22821,22822,22823,22824,22825,
+22826,22827,22828,22829,22830,22831,22832,22833,22834,22835,22836,22837,
+22838,22839,22840,22841,22842,22843,22844,22845,22846,22847,22848,22849,
+22850,22851,22852,22853,22854,22855,22856,22857,22858,22859,22860,22861,
+22862,22863,22864,22865,22866,22867,22868,22869,22870,22871,22872,22873,
+22874,22875,22876,22877,22878,22879,22880,22881,22882,22883,22884,22885,
+22886,22887,22888,22889,22890,22891,22892,22893,22894,22895,22896,22897,
+22898,22899,22900,22901,22902,22903,22904,22905,22906,22907,22908,22909,
+22910,22911,22912,22913,22914,22915,22916,22917,22918,22919,22920,22921,
+22922,22923,22924,22925,22926,22927,22928,22929,22930,22931,22932,22933,
+22934,22935,22936,22937,22938,22939,22940,22941,22942,22943,22944,22945,
+22946,22947,22948,22949,22950,22951,22952,22953,22954,22955,22956,22957,
+22958,22959,22960,22961,22962,22963,22964,22965,22966,22967,22968,22969,
+22970,22971,22972,22973,22974,22975,22976,22977,22978,22979,22980,22981,
+22982,22983,22984,22985,22986,22987,22988,22989,22990,22991,22992,22993,
+22994,22995,22996,22997,22998,22999,23000,23001,23002,23003,23004,23005,
+23006,23007,23008,23009,23010,23011,23012,23013,23014,23015,23016,23017,
+23018,23019,23020,23021,23022,23023,23024,23025,23026,23027,23028,23029,
+23030,23031,23032,23033,23034,23035,23036,23037,23038,23039,23040,23041,
+23042,23043,23044,23045,23046,23047,23048,23049,23050,23051,23052,23053,
+23054,23055,23056,23057,23058,23059,23060,23061,23062,23063,23064,23065,
+23066,23067,23068,23069,23070,23071,23072,23073,23074,23075,23076,23077,
+23078,23079,23080,23081,23082,23083,23084,23085,23086,23087,23088,23089,
+23090,23091,23092,23093,23094,23095,23096,23097,23098,23099,23100,23101,
+23102,23103,23104,23105,23106,23107,23108,23109,23110,23111,23112,23113,
+23114,23115,23116,23117,23118,23119,23120,23121,23122,23123,23124,23125,
+23126,23127,23128,23129,23130,23131,23132,23133,23134,23135,23136,23137,
+23138,23139,23140,23141,23142,23143,23144,23145,23146,23147,23148,23149,
+23150,23151,23152,23153,23154,23155,23156,23157,23158,23159,23160,23161,
+23162,23163,23164,23165,23166,23167,23168,23169,23170,23171,23172,23173,
+23174,23175,23176,23177,23178,23179,23180,23181,23182,23183,23184,23185,
+23186,23187,23188,23189,23190,23191,23192,23193,23194,23195,23196,23197,
+23198,23199,23200,23201,23202,23203,23204,23205,23206,23207,23208,23209,
+23210,23211,23212,23213,23214,23215,23216,23217,23218,23219,23220,23221,
+23222,23223,23224,23225,23226,23227,23228,23229,23230,23231,23232,23233,
+23234,23235,23236,23237,23238,23239,23240,23241,23242,23243,23244,23245,
+23246,23247,23248,23249,23250,23251,23252,23253,23254,23255,23256,23257,
+23258,23259,23260,23261,23262,23263,23264,23265,23266,23267,23268,23269,
+23270,23271,23272,23273,23274,23275,23276,23277,23278,23279,23280,23281,
+23282,23283,23284,23285,23286,23287,23288,23289,23290,23291,23292,23293,
+23294,23295,23296,23297,23298,23299,23300,23301,23302,23303,23304,23305,
+23306,23307,23308,23309,23310,23311,23312,23313,23314,23315,23316,23317,
+23318,23319,23320,23321,23322,23323,23324,23325,23326,23327,23328,23329,
+23330,23331,23332,23333,23334,23335,23336,23337,23338,23339,23340,23341,
+23342,23343,23344,23345,23346,23347,23348,23349,23350,23351,23352,23353,
+23354,23355,23356,23357,23358,23359,23360,23361,23362,23363,23364,23365,
+23366,23367,23368,23369,23370,23371,23372,23373,23374,23375,23376,23377,
+23378,23379,23380,23381,23382,23383,23384,23385,23386,23387,23388,23389,
+23390,23391,23392,23393,23394,23395,23396,23397,23398,23399,23400,23401,
+23402,23403,23404,23405,23406,23407,23408,23409,23410,23411,23412,23413,
+23414,23415,23416,23417,23418,23419,23420,23421,23422,23423,23424,23425,
+23426,23427,23428,23429,23430,23431,23432,23433,23434,23435,23436,23437,
+23438,23439,23440,23441,23442,23443,23444,23445,23446,23447,23448,23449,
+23450,23451,23452,23453,23454,23455,23456,23457,23458,23459,23460,23461,
+23462,23463,23464,23465,23466,23467,23468,23469,23470,23471,23472,23473,
+23474,23475,23476,23477,23478,23479,23480,23481,23482,23483,23484,23485,
+23486,23487,23488,23489,23490,23491,23492,23493,23494,23495,23496,23497,
+23498,23499,23500,23501,23502,23503,23504,23505,23506,23507,23508,23509,
+23510,23511,23512,23513,23514,23515,23516,23517,23518,23519,23520,23521,
+23522,23523,23524,23525,23526,23527,23528,23529,23530,23531,23532,23533,
+23534,23535,23536,23537,23538,23539,23540,23541,23542,23543,23544,23545,
+23546,23547,23548,23549,23550,23551,23552,23553,23554,23555,23556,23557,
+23558,23559,23560,23561,23562,23563,23564,23565,23566,23567,23568,23569,
+23570,23571,23572,23573,23574,23575,23576,23577,23578,23579,23580,23581,
+23582,23583,23584,23585,23586,23587,23588,23589,23590,23591,23592,23593,
+23594,23595,23596,23597,23598,23599,23600,23601,23602,23603,23604,23605,
+23606,23607,23608,23609,23610,23611,23612,23613,23614,23615,23616,23617,
+23618,23619,23620,23621,23622,23623,23624,23625,23626,23627,23628,23629,
+23630,23631,23632,23633,23634,23635,23636,23637,23638,23639,23640,23641,
+23642,23643,23644,23645,23646,23647,23648,23649,23650,23651,23652,23653,
+23654,23655,23656,23657,23658,23659,23660,23661,23662,23663,23664,23665,
+23666,23667,23668,23669,23670,23671,23672,23673,23674,23675,23676,23677,
+23678,23679,23680,23681,23682,23683,23684,23685,23686,23687,23688,23689,
+23690,23691,23692,23693,23694,23695,23696,23697,23698,23699,23700,23701,
+23702,23703,23704,23705,23706,23707,23708,23709,23710,23711,23712,23713,
+23714,23715,23716,23717,23718,23719,23720,23721,23722,23723,23724,23725,
+23726,23727,23728,23729,23730,23731,23732,23733,23734,23735,23736,23737,
+23738,23739,23740,23741,23742,23743,23744,23745,23746,23747,23748,23749,
+23750,23751,23752,23753,23754,23755,23756,23757,23758,23759,23760,23761,
+23762,23763,23764,23765,23766,23767,23768,23769,23770,23771,23772,23773,
+23774,23775,23776,23777,23778,23779,23780,23781,23782,23783,23784,23785,
+23786,23787,23788,23789,23790,23791,23792,23793,23794,23795,23796,23797,
+23798,23799,23800,23801,23802,23803,23804,23805,23806,23807,23808,23809,
+23810,23811,23812,23813,23814,23815,23816,23817,23818,23819,23820,23821,
+23822,23823,23824,23825,23826,23827,23828,23829,23830,23831,23832,23833,
+23834,23835,23836,23837,23838,23839,23840,23841,23842,23843,23844,23845,
+23846,23847,23848,23849,23850,23851,23852,23853,23854,23855,23856,23857,
+23858,23859,23860,23861,23862,23863,23864,23865,23866,23867,23868,23869,
+23870,23871,23872,23873,23874,23875,23876,23877,23878,23879,23880,23881,
+23882,23883,23884,23885,23886,23887,23888,23889,23890,23891,23892,23893,
+23894,23895,23896,23897,23898,23899,23900,23901,23902,23903,23904,23905,
+23906,23907,23908,23909,23910,23911,23912,23913,23914,23915,23916,23917,
+23918,23919,23920,23921,23922,23923,23924,23925,23926,23927,23928,23929,
+23930,23931,23932,23933,23934,23935,23936,23937,23938,23939,23940,23941,
+23942,23943,23944,23945,23946,23947,23948,23949,23950,23951,23952,23953,
+23954,23955,23956,23957,23958,23959,23960,23961,23962,23963,23964,23965,
+23966,23967,23968,23969,23970,23971,23972,23973,23974,23975,23976,23977,
+23978,23979,23980,23981,23982,23983,23984,23985,23986,23987,23988,23989,
+23990,23991,23992,23993,23994,23995,23996,23997,23998,23999,24000,24001,
+24002,24003,24004,24005,24006,24007,24008,24009,24010,24011,24012,24013,
+24014,24015,24016,24017,24018,24019,24020,24021,24022,24023,24024,24025,
+24026,24027,24028,24029,24030,24031,24032,24033,24034,24035,24036,24037,
+24038,24039,24040,24041,24042,24043,24044,24045,24046,24047,24048,24049,
+24050,24051,24052,24053,24054,24055,24056,24057,24058,24059,24060,24061,
+24062,24063,24064,24065,24066,24067,24068,24069,24070,24071,24072,24073,
+24074,24075,24076,24077,24078,24079,24080,24081,24082,24083,24084,24085,
+24086,24087,24088,24089,24090,24091,24092,24093,24094,24095,24096,24097,
+24098,24099,24100,24101,24102,24103,24104,24105,24106,24107,24108,24109,
+24110,24111,24112,24113,24114,24115,24116,24117,24118,24119,24120,24121,
+24122,24123,24124,24125,24126,24127,24128,24129,24130,24131,24132,24133,
+24134,24135,24136,24137,24138,24139,24140,24141,24142,24143,24144,24145,
+24146,24147,24148,24149,24150,24151,24152,24153,24154,24155,24156,24157,
+24158,24159,24160,24161,24162,24163,24164,24165,24166,24167,24168,24169,
+24170,24171,24172,24173,24174,24175,24176,24177,24178,24179,24180,24181,
+24182,24183,24184,24185,24186,24187,24188,24189,24190,24191,24192,24193,
+24194,24195,24196,24197,24198,24199,24200,24201,24202,24203,24204,24205,
+24206,24207,24208,24209,24210,24211,24212,24213,24214,24215,24216,24217,
+24218,24219,24220,24221,24222,24223,24224,24225,24226,24227,24228,24229,
+24230,24231,24232,24233,24234,24235,24236,24237,24238,24239,24240,24241,
+24242,24243,24244,24245,24246,24247,24248,24249,24250,24251,24252,24253,
+24254,24255,24256,24257,24258,24259,24260,24261,24262,24263,24264,24265,
+24266,24267,24268,24269,24270,24271,24272,24273,24274,24275,24276,24277,
+24278,24279,24280,24281,24282,24283,24284,24285,24286,24287,24288,24289,
+24290,24291,24292,24293,24294,24295,24296,24297,24298,24299,24300,24301,
+24302,24303,24304,24305,24306,24307,24308,24309,24310,24311,24312,24313,
+24314,24315,24316,24317,24318,24319,24320,24321,24322,24323,24324,24325,
+24326,24327,24328,24329,24330,24331,24332,24333,24334,24335,24336,24337,
+24338,24339,24340,24341,24342,24343,24344,24345,24346,24347,24348,24349,
+24350,24351,24352,24353,24354,24355,24356,24357,24358,24359,24360,24361,
+24362,24363,24364,24365,24366,24367,24368,24369,24370,24371,24372,24373,
+24374,24375,24376,24377,24378,24379,24380,24381,24382,24383,24384,24385,
+24386,24387,24388,24389,24390,24391,24392,24393,24394,24395,24396,24397,
+24398,24399,24400,24401,24402,24403,24404,24405,24406,24407,24408,24409,
+24410,24411,24412,24413,24414,24415,24416,24417,24418,24419,24420,24421,
+24422,24423,24424,24425,24426,24427,24428,24429,24430,24431,24432,24433,
+24434,24435,24436,24437,24438,24439,24440,24441,24442,24443,24444,24445,
+24446,24447,24448,24449,24450,24451,24452,24453,24454,24455,24456,24457,
+24458,24459,24460,24461,24462,24463,24464,24465,24466,24467,24468,24469,
+24470,24471,24472,24473,24474,24475,24476,24477,24478,24479,24480,24481,
+24482,24483,24484,24485,24486,24487,24488,24489,24490,24491,24492,24493,
+24494,24495,24496,24497,24498,24499,24500,24501,24502,24503,24504,24505,
+24506,24507,24508,24509,24510,24511,24512,24513,24514,24515,24516,24517,
+24518,24519,24520,24521,24522,24523,24524,24525,24526,24527,24528,24529,
+24530,24531,24532,24533,24534,24535,24536,24537,24538,24539,24540,24541,
+24542,24543,24544,24545,24546,24547,24548,24549,24550,24551,24552,24553,
+24554,24555,24556,24557,24558,24559,24560,24561,24562,24563,24564,24565,
+24566,24567,24568,24569,24570,24571,24572,24573,24574,24575,24576,24577,
+24578,24579,24580,24581,24582,24583,24584,24585,24586,24587,24588,24589,
+24590,24591,24592,24593,24594,24595,24596,24597,24598,24599,24600,24601,
+24602,24603,24604,24605,24606,24607,24608,24609,24610,24611,24612,24613,
+24614,24615,24616,24617,24618,24619,24620,24621,24622,24623,24624,24625,
+24626,24627,24628,24629,24630,24631,24632,24633,24634,24635,24636,24637,
+24638,24639,24640,24641,24642,24643,24644,24645,24646,24647,24648,24649,
+24650,24651,24652,24653,24654,24655,24656,24657,24658,24659,24660,24661,
+24662,24663,24664,24665,24666,24667,24668,24669,24670,24671,24672,24673,
+24674,24675,24676,24677,24678,24679,24680,24681,24682,24683,24684,24685,
+24686,24687,24688,24689,24690,24691,24692,24693,24694,24695,24696,24697,
+24698,24699,24700,24701,24702,24703,24704,24705,24706,24707,24708,24709,
+24710,24711,24712,24713,24714,24715,24716,24717,24718,24719,24720,24721,
+24722,24723,24724,24725,24726,24727,24728,24729,24730,24731,24732,24733,
+24734,24735,24736,24737,24738,24739,24740,24741,24742,24743,24744,24745,
+24746,24747,24748,24749,24750,24751,24752,24753,24754,24755,24756,24757,
+24758,24759,24760,24761,24762,24763,24764,24765,24766,24767,24768,24769,
+24770,24771,24772,24773,24774,24775,24776,24777,24778,24779,24780,24781,
+24782,24783,24784,24785,24786,24787,24788,24789,24790,24791,24792,24793,
+24794,24795,24796,24797,24798,24799,24800,24801,24802,24803,24804,24805,
+24806,24807,24808,24809,24810,24811,24812,24813,24814,24815,24816,24817,
+24818,24819,24820,24821,24822,24823,24824,24825,24826,24827,24828,24829,
+24830,24831,24832,24833,24834,24835,24836,24837,24838,24839,24840,24841,
+24842,24843,24844,24845,24846,24847,24848,24849,24850,24851,24852,24853,
+24854,24855,24856,24857,24858,24859,24860,24861,24862,24863,24864,24865,
+24866,24867,24868,24869,24870,24871,24872,24873,24874,24875,24876,24877,
+24878,24879,24880,24881,24882,24883,24884,24885,24886,24887,24888,24889,
+24890,24891,24892,24893,24894,24895,24896,24897,24898,24899,24900,24901,
+24902,24903,24904,24905,24906,24907,24908,24909,24910,24911,24912,24913,
+24914,24915,24916,24917,24918,24919,24920,24921,24922,24923,24924,24925,
+24926,24927,24928,24929,24930,24931,24932,24933,24934,24935,24936,24937,
+24938,24939,24940,24941,24942,24943,24944,24945,24946,24947,24948,24949,
+24950,24951,24952,24953,24954,24955,24956,24957,24958,24959,24960,24961,
+24962,24963,24964,24965,24966,24967,24968,24969,24970,24971,24972,24973,
+24974,24975,24976,24977,24978,24979,24980,24981,24982,24983,24984,24985,
+24986,24987,24988,24989,24990,24991,24992,24993,24994,24995,24996,24997,
+24998,24999,25000,25001,25002,25003,25004,25005,25006,25007,25008,25009,
+25010,25011,25012,25013,25014,25015,25016,25017,25018,25019,25020,25021,
+25022,25023,25024,25025,25026,25027,25028,25029,25030,25031,25032,25033,
+25034,25035,25036,25037,25038,25039,25040,25041,25042,25043,25044,25045,
+25046,25047,25048,25049,25050,25051,25052,25053,25054,25055,25056,25057,
+25058,25059,25060,25061,25062,25063,25064,25065,25066,25067,25068,25069,
+25070,25071,25072,25073,25074,25075,25076,25077,25078,25079,25080,25081,
+25082,25083,25084,25085,25086,25087,25088,25089,25090,25091,25092,25093,
+25094,25095,25096,25097,25098,25099,25100,25101,25102,25103,25104,25105,
+25106,25107,25108,25109,25110,25111,25112,25113,25114,25115,25116,25117,
+25118,25119,25120,25121,25122,25123,25124,25125,25126,25127,25128,25129,
+25130,25131,25132,25133,25134,25135,25136,25137,25138,25139,25140,25141,
+25142,25143,25144,25145,25146,25147,25148,25149,25150,25151,25152,25153,
+25154,25155,25156,25157,25158,25159,25160,25161,25162,25163,25164,25165,
+25166,25167,25168,25169,25170,25171,25172,25173,25174,25175,25176,25177,
+25178,25179,25180,25181,25182,25183,25184,25185,25186,25187,25188,25189,
+25190,25191,25192,25193,25194,25195,25196,25197,25198,25199,25200,25201,
+25202,25203,25204,25205,25206,25207,25208,25209,25210,25211,25212,25213,
+25214,25215,25216,25217,25218,25219,25220,25221,25222,25223,25224,25225,
+25226,25227,25228,25229,25230,25231,25232,25233,25234,25235,25236,25237,
+25238,25239,25240,25241,25242,25243,25244,25245,25246,25247,25248,25249,
+25250,25251,25252,25253,25254,25255,25256,25257,25258,25259,25260,25261,
+25262,25263,25264,25265,25266,25267,25268,25269,25270,25271,25272,25273,
+25274,25275,25276,25277,25278,25279,25280,25281,25282,25283,25284,25285,
+25286,25287,25288,25289,25290,25291,25292,25293,25294,25295,25296,25297,
+25298,25299,25300,25301,25302,25303,25304,25305,25306,25307,25308,25309,
+25310,25311,25312,25313,25314,25315,25316,25317,25318,25319,25320,25321,
+25322,25323,25324,25325,25326,25327,25328,25329,25330,25331,25332,25333,
+25334,25335,25336,25337,25338,25339,25340,25341,25342,25343,25344,25345,
+25346,25347,25348,25349,25350,25351,25352,25353,25354,25355,25356,25357,
+25358,25359,25360,25361,25362,25363,25364,25365,25366,25367,25368,25369,
+25370,25371,25372,25373,25374,25375,25376,25377,25378,25379,25380,25381,
+25382,25383,25384,25385,25386,25387,25388,25389,25390,25391,25392,25393,
+25394,25395,25396,25397,25398,25399,25400,25401,25402,25403,25404,25405,
+25406,25407,25408,25409,25410,25411,25412,25413,25414,25415,25416,25417,
+25418,25419,25420,25421,25422,25423,25424,25425,25426,25427,25428,25429,
+25430,25431,25432,25433,25434,25435,25436,25437,25438,25439,25440,25441,
+25442,25443,25444,25445,25446,25447,25448,25449,25450,25451,25452,25453,
+25454,25455,25456,25457,25458,25459,25460,25461,25462,25463,25464,25465,
+25466,25467,25468,25469,25470,25471,25472,25473,25474,25475,25476,25477,
+25478,25479,25480,25481,25482,25483,25484,25485,25486,25487,25488,25489,
+25490,25491,25492,25493,25494,25495,25496,25497,25498,25499,25500,25501,
+25502,25503,25504,25505,25506,25507,25508,25509,25510,25511,25512,25513,
+25514,25515,25516,25517,25518,25519,25520,25521,25522,25523,25524,25525,
+25526,25527,25528,25529,25530,25531,25532,25533,25534,25535,25536,25537,
+25538,25539,25540,25541,25542,25543,25544,25545,25546,25547,25548,25549,
+25550,25551,25552,25553,25554,25555,25556,25557,25558,25559,25560,25561,
+25562,25563,25564,25565,25566,25567,25568,25569,25570,25571,25572,25573,
+25574,25575,25576,25577,25578,25579,25580,25581,25582,25583,25584,25585,
+25586,25587,25588,25589,25590,25591,25592,25593,25594,25595,25596,25597,
+25598,25599,25600,25601,25602,25603,25604,25605,25606,25607,25608,25609,
+25610,25611,25612,25613,25614,25615,25616,25617,25618,25619,25620,25621,
+25622,25623,25624,25625,25626,25627,25628,25629,25630,25631,25632,25633,
+25634,25635,25636,25637,25638,25639,25640,25641,25642,25643,25644,25645,
+25646,25647,25648,25649,25650,25651,25652,25653,25654,25655,25656,25657,
+25658,25659,25660,25661,25662,25663,25664,25665,25666,25667,25668,25669,
+25670,25671,25672,25673,25674,25675,25676,25677,25678,25679,25680,25681,
+25682,25683,25684,25685,25686,25687,25688,25689,25690,25691,25692,25693,
+25694,25695,25696,25697,25698,25699,25700,25701,25702,25703,25704,25705,
+25706,25707,25708,25709,25710,25711,25712,25713,25714,25715,25716,25717,
+25718,25719,25720,25721,25722,25723,25724,25725,25726,25727,25728,25729,
+25730,25731,25732,25733,25734,25735,25736,25737,25738,25739,25740,25741,
+25742,25743,25744,25745,25746,25747,25748,25749,25750,25751,25752,25753,
+25754,25755,25756,25757,25758,25759,25760,25761,25762,25763,25764,25765,
+25766,25767,25768,25769,25770,25771,25772,25773,25774,25775,25776,25777,
+25778,25779,25780,25781,25782,25783,25784,25785,25786,25787,25788,25789,
+25790,25791,25792,25793,25794,25795,25796,25797,25798,25799,25800,25801,
+25802,25803,25804,25805,25806,25807,25808,25809,25810,25811,25812,25813,
+25814,25815,25816,25817,25818,25819,25820,25821,25822,25823,25824,25825,
+25826,25827,25828,25829,25830,25831,25832,25833,25834,25835,25836,25837,
+25838,25839,25840,25841,25842,25843,25844,25845,25846,25847,25848,25849,
+25850,25851,25852,25853,25854,25855,25856,25857,25858,25859,25860,25861,
+25862,25863,25864,25865,25866,25867,25868,25869,25870,25871,25872,25873,
+25874,25875,25876,25877,25878,25879,25880,25881,25882,25883,25884,25885,
+25886,25887,25888,25889,25890,25891,25892,25893,25894,25895,25896,25897,
+25898,25899,25900,25901,25902,25903,25904,25905,25906,25907,25908,25909,
+25910,25911,25912,25913,25914,25915,25916,25917,25918,25919,25920,25921,
+25922,25923,25924,25925,25926,25927,25928,25929,25930,25931,25932,25933,
+25934,25935,25936,25937,25938,25939,25940,25941,25942,25943,25944,25945,
+25946,25947,25948,25949,25950,25951,25952,25953,25954,25955,25956,25957,
+25958,25959,25960,25961,25962,25963,25964,25965,25966,25967,25968,25969,
+25970,25971,25972,25973,25974,25975,25976,25977,25978,25979,25980,25981,
+25982,25983,25984,25985,25986,25987,25988,25989,25990,25991,25992,25993,
+25994,25995,25996,25997,25998,25999,26000,26001,26002,26003,26004,26005,
+26006,26007,26008,26009,26010,26011,26012,26013,26014,26015,26016,26017,
+26018,26019,26020,26021,26022,26023,26024,26025,26026,26027,26028,26029,
+26030,26031,26032,26033,26034,26035,26036,26037,26038,26039,26040,26041,
+26042,26043,26044,26045,26046,26047,26048,26049,26050,26051,26052,26053,
+26054,26055,26056,26057,26058,26059,26060,26061,26062,26063,26064,26065,
+26066,26067,26068,26069,26070,26071,26072,26073,26074,26075,26076,26077,
+26078,26079,26080,26081,26082,26083,26084,26085,26086,26087,26088,26089,
+26090,26091,26092,26093,26094,26095,26096,26097,26098,26099,26100,26101,
+26102,26103,26104,26105,26106,26107,26108,26109,26110,26111,26112,26113,
+26114,26115,26116,26117,26118,26119,26120,26121,26122,26123,26124,26125,
+26126,26127,26128,26129,26130,26131,26132,26133,26134,26135,26136,26137,
+26138,26139,26140,26141,26142,26143,26144,26145,26146,26147,26148,26149,
+26150,26151,26152,26153,26154,26155,26156,26157,26158,26159,26160,26161,
+26162,26163,26164,26165,26166,26167,26168,26169,26170,26171,26172,26173,
+26174,26175,26176,26177,26178,26179,26180,26181,26182,26183,26184,26185,
+26186,26187,26188,26189,26190,26191,26192,26193,26194,26195,26196,26197,
+26198,26199,26200,26201,26202,26203,26204,26205,26206,26207,26208,26209,
+26210,26211,26212,26213,26214,26215,26216,26217,26218,26219,26220,26221,
+26222,26223,26224,26225,26226,26227,26228,26229,26230,26231,26232,26233,
+26234,26235,26236,26237,26238,26239,26240,26241,26242,26243,26244,26245,
+26246,26247,26248,26249,26250,26251,26252,26253,26254,26255,26256,26257,
+26258,26259,26260,26261,26262,26263,26264,26265,26266,26267,26268,26269,
+26270,26271,26272,26273,26274,26275,26276,26277,26278,26279,26280,26281,
+26282,26283,26284,26285,26286,26287,26288,26289,26290,26291,26292,26293,
+26294,26295,26296,26297,26298,26299,26300,26301,26302,26303,26304,26305,
+26306,26307,26308,26309,26310,26311,26312,26313,26314,26315,26316,26317,
+26318,26319,26320,26321,26322,26323,26324,26325,26326,26327,26328,26329,
+26330,26331,26332,26333,26334,26335,26336,26337,26338,26339,26340,26341,
+26342,26343,26344,26345,26346,26347,26348,26349,26350,26351,26352,26353,
+26354,26355,26356,26357,26358,26359,26360,26361,26362,26363,26364,26365,
+26366,26367,26368,26369,26370,26371,26372,26373,26374,26375,26376,26377,
+26378,26379,26380,26381,26382,26383,26384,26385,26386,26387,26388,26389,
+26390,26391,26392,26393,26394,26395,26396,26397,26398,26399,26400,26401,
+26402,26403,26404,26405,26406,26407,26408,26409,26410,26411,26412,26413,
+26414,26415,26416,26417,26418,26419,26420,26421,26422,26423,26424,26425,
+26426,26427,26428,26429,26430,26431,26432,26433,26434,26435,26436,26437,
+26438,26439,26440,26441,26442,26443,26444,26445,26446,26447,26448,26449,
+26450,26451,26452,26453,26454,26455,26456,26457,26458,26459,26460,26461,
+26462,26463,26464,26465,26466,26467,26468,26469,26470,26471,26472,26473,
+26474,26475,26476,26477,26478,26479,26480,26481,26482,26483,26484,26485,
+26486,26487,26488,26489,26490,26491,26492,26493,26494,26495,26496,26497,
+26498,26499,26500,26501,26502,26503,26504,26505,26506,26507,26508,26509,
+26510,26511,26512,26513,26514,26515,26516,26517,26518,26519,26520,26521,
+26522,26523,26524,26525,26526,26527,26528,26529,26530,26531,26532,26533,
+26534,26535,26536,26537,26538,26539,26540,26541,26542,26543,26544,26545,
+26546,26547,26548,26549,26550,26551,26552,26553,26554,26555,26556,26557,
+26558,26559,26560,26561,26562,26563,26564,26565,26566,26567,26568,26569,
+26570,26571,26572,26573,26574,26575,26576,26577,26578,26579,26580,26581,
+26582,26583,26584,26585,26586,26587,26588,26589,26590,26591,26592,26593,
+26594,26595,26596,26597,26598,26599,26600,26601,26602,26603,26604,26605,
+26606,26607,26608,26609,26610,26611,26612,26613,26614,26615,26616,26617,
+26618,26619,26620,26621,26622,26623,26624,26625,26626,26627,26628,26629,
+26630,26631,26632,26633,26634,26635,26636,26637,26638,26639,26640,26641,
+26642,26643,26644,26645,26646,26647,26648,26649,26650,26651,26652,26653,
+26654,26655,26656,26657,26658,26659,26660,26661,26662,26663,26664,26665,
+26666,26667,26668,26669,26670,26671,26672,26673,26674,26675,26676,26677,
+26678,26679,26680,26681,26682,26683,26684,26685,26686,26687,26688,26689,
+26690,26691,26692,26693,26694,26695,26696,26697,26698,26699,26700,26701,
+26702,26703,26704,26705,26706,26707,26708,26709,26710,26711,26712,26713,
+26714,26715,26716,26717,26718,26719,26720,26721,26722,26723,26724,26725,
+26726,26727,26728,26729,26730,26731,26732,26733,26734,26735,26736,26737,
+26738,26739,26740,26741,26742,26743,26744,26745,26746,26747,26748,26749,
+26750,26751,26752,26753,26754,26755,26756,26757,26758,26759,26760,26761,
+26762,26763,26764,26765,26766,26767,26768,26769,26770,26771,26772,26773,
+26774,26775,26776,26777,26778,26779,26780,26781,26782,26783,26784,26785,
+26786,26787,26788,26789,26790,26791,26792,26793,26794,26795,26796,26797,
+26798,26799,26800,26801,26802,26803,26804,26805,26806,26807,26808,26809,
+26810,26811,26812,26813,26814,26815,26816,26817,26818,26819,26820,26821,
+26822,26823,26824,26825,26826,26827,26828,26829,26830,26831,26832,26833,
+26834,26835,26836,26837,26838,26839,26840,26841,26842,26843,26844,26845,
+26846,26847,26848,26849,26850,26851,26852,26853,26854,26855,26856,26857,
+26858,26859,26860,26861,26862,26863,26864,26865,26866,26867,26868,26869,
+26870,26871,26872,26873,26874,26875,26876,26877,26878,26879,26880,26881,
+26882,26883,26884,26885,26886,26887,26888,26889,26890,26891,26892,26893,
+26894,26895,26896,26897,26898,26899,26900,26901,26902,26903,26904,26905,
+26906,26907,26908,26909,26910,26911,26912,26913,26914,26915,26916,26917,
+26918,26919,26920,26921,26922,26923,26924,26925,26926,26927,26928,26929,
+26930,26931,26932,26933,26934,26935,26936,26937,26938,26939,26940,26941,
+26942,26943,26944,26945,26946,26947,26948,26949,26950,26951,26952,26953,
+26954,26955,26956,26957,26958,26959,26960,26961,26962,26963,26964,26965,
+26966,26967,26968,26969,26970,26971,26972,26973,26974,26975,26976,26977,
+26978,26979,26980,26981,26982,26983,26984,26985,26986,26987,26988,26989,
+26990,26991,26992,26993,26994,26995,26996,26997,26998,26999,27000,27001,
+27002,27003,27004,27005,27006,27007,27008,27009,27010,27011,27012,27013,
+27014,27015,27016,27017,27018,27019,27020,27021,27022,27023,27024,27025,
+27026,27027,27028,27029,27030,27031,27032,27033,27034,27035,27036,27037,
+27038,27039,27040,27041,27042,27043,27044,27045,27046,27047,27048,27049,
+27050,27051,27052,27053,27054,27055,27056,27057,27058,27059,27060,27061,
+27062,27063,27064,27065,27066,27067,27068,27069,27070,27071,27072,27073,
+27074,27075,27076,27077,27078,27079,27080,27081,27082,27083,27084,27085,
+27086,27087,27088,27089,27090,27091,27092,27093,27094,27095,27096,27097,
+27098,27099,27100,27101,27102,27103,27104,27105,27106,27107,27108,27109,
+27110,27111,27112,27113,27114,27115,27116,27117,27118,27119,27120,27121,
+27122,27123,27124,27125,27126,27127,27128,27129,27130,27131,27132,27133,
+27134,27135,27136,27137,27138,27139,27140,27141,27142,27143,27144,27145,
+27146,27147,27148,27149,27150,27151,27152,27153,27154,27155,27156,27157,
+27158,27159,27160,27161,27162,27163,27164,27165,27166,27167,27168,27169,
+27170,27171,27172,27173,27174,27175,27176,27177,27178,27179,27180,27181,
+27182,27183,27184,27185,27186,27187,27188,27189,27190,27191,27192,27193,
+27194,27195,27196,27197,27198,27199,27200,27201,27202,27203,27204,27205,
+27206,27207,27208,27209,27210,27211,27212,27213,27214,27215,27216,27217,
+27218,27219,27220,27221,27222,27223,27224,27225,27226,27227,27228,27229,
+27230,27231,27232,27233,27234,27235,27236,27237,27238,27239,27240,27241,
+27242,27243,27244,27245,27246,27247,27248,27249,27250,27251,27252,27253,
+27254,27255,27256,27257,27258,27259,27260,27261,27262,27263,27264,27265,
+27266,27267,27268,27269,27270,27271,27272,27273,27274,27275,27276,27277,
+27278,27279,27280,27281,27282,27283,27284,27285,27286,27287,27288,27289,
+27290,27291,27292,27293,27294,27295,27296,27297,27298,27299,27300,27301,
+27302,27303,27304,27305,27306,27307,27308,27309,27310,27311,27312,27313,
+27314,27315,27316,27317,27318,27319,27320,27321,27322,27323,27324,27325,
+27326,27327,27328,27329,27330,27331,27332,27333,27334,27335,27336,27337,
+27338,27339,27340,27341,27342,27343,27344,27345,27346,27347,27348,27349,
+27350,27351,27352,27353,27354,27355,27356,27357,27358,27359,27360,27361,
+27362,27363,27364,27365,27366,27367,27368,27369,27370,27371,27372,27373,
+27374,27375,27376,27377,27378,27379,27380,27381,27382,27383,27384,27385,
+27386,27387,27388,27389,27390,27391,27392,27393,27394,27395,27396,27397,
+27398,27399,27400,27401,27402,27403,27404,27405,27406,27407,27408,27409,
+27410,27411,27412,27413,27414,27415,27416,27417,27418,27419,27420,27421,
+27422,27423,27424,27425,27426,27427,27428,27429,27430,27431,27432,27433,
+27434,27435,27436,27437,27438,27439,27440,27441,27442,27443,27444,27445,
+27446,27447,27448,27449,27450,27451,27452,27453,27454,27455,27456,27457,
+27458,27459,27460,27461,27462,27463,27464,27465,27466,27467,27468,27469,
+27470,27471,27472,27473,27474,27475,27476,27477,27478,27479,27480,27481,
+27482,27483,27484,27485,27486,27487,27488,27489,27490,27491,27492,27493,
+27494,27495,27496,27497,27498,27499,27500,27501,27502,27503,27504,27505,
+27506,27507,27508,27509,27510,27511,27512,27513,27514,27515,27516,27517,
+27518,27519,27520,27521,27522,27523,27524,27525,27526,27527,27528,27529,
+27530,27531,27532,27533,27534,27535,27536,27537,27538,27539,27540,27541,
+27542,27543,27544,27545,27546,27547,27548,27549,27550,27551,27552,27553,
+27554,27555,27556,27557,27558,27559,27560,27561,27562,27563,27564,27565,
+27566,27567,27568,27569,27570,27571,27572,27573,27574,27575,27576,27577,
+27578,27579,27580,27581,27582,27583,27584,27585,27586,27587,27588,27589,
+27590,27591,27592,27593,27594,27595,27596,27597,27598,27599,27600,27601,
+27602,27603,27604,27605,27606,27607,27608,27609,27610,27611,27612,27613,
+27614,27615,27616,27617,27618,27619,27620,27621,27622,27623,27624,27625,
+27626,27627,27628,27629,27630,27631,27632,27633,27634,27635,27636,27637,
+27638,27639,27640,27641,27642,27643,27644,27645,27646,27647,27648,27649,
+27650,27651,27652,27653,27654,27655,27656,27657,27658,27659,27660,27661,
+27662,27663,27664,27665,27666,27667,27668,27669,27670,27671,27672,27673,
+27674,27675,27676,27677,27678,27679,27680,27681,27682,27683,27684,27685,
+27686,27687,27688,27689,27690,27691,27692,27693,27694,27695,27696,27697,
+27698,27699,27700,27701,27702,27703,27704,27705,27706,27707,27708,27709,
+27710,27711,27712,27713,27714,27715,27716,27717,27718,27719,27720,27721,
+27722,27723,27724,27725,27726,27727,27728,27729,27730,27731,27732,27733,
+27734,27735,27736,27737,27738,27739,27740,27741,27742,27743,27744,27745,
+27746,27747,27748,27749,27750,27751,27752,27753,27754,27755,27756,27757,
+27758,27759,27760,27761,27762,27763,27764,27765,27766,27767,27768,27769,
+27770,27771,27772,27773,27774,27775,27776,27777,27778,27779,27780,27781,
+27782,27783,27784,27785,27786,27787,27788,27789,27790,27791,27792,27793,
+27794,27795,27796,27797,27798,27799,27800,27801,27802,27803,27804,27805,
+27806,27807,27808,27809,27810,27811,27812,27813,27814,27815,27816,27817,
+27818,27819,27820,27821,27822,27823,27824,27825,27826,27827,27828,27829,
+27830,27831,27832,27833,27834,27835,27836,27837,27838,27839,27840,27841,
+27842,27843,27844,27845,27846,27847,27848,27849,27850,27851,27852,27853,
+27854,27855,27856,27857,27858,27859,27860,27861,27862,27863,27864,27865,
+27866,27867,27868,27869,27870,27871,27872,27873,27874,27875,27876,27877,
+27878,27879,27880,27881,27882,27883,27884,27885,27886,27887,27888,27889,
+27890,27891,27892,27893,27894,27895,27896,27897,27898,27899,27900,27901,
+27902,27903,27904,27905,27906,27907,27908,27909,27910,27911,27912,27913,
+27914,27915,27916,27917,27918,27919,27920,27921,27922,27923,27924,27925,
+27926,27927,27928,27929,27930,27931,27932,27933,27934,27935,27936,27937,
+27938,27939,27940,27941,27942,27943,27944,27945,27946,27947,27948,27949,
+27950,27951,27952,27953,27954,27955,27956,27957,27958,27959,27960,27961,
+27962,27963,27964,27965,27966,27967,27968,27969,27970,27971,27972,27973,
+27974,27975,27976,27977,27978,27979,27980,27981,27982,27983,27984,27985,
+27986,27987,27988,27989,27990,27991,27992,27993,27994,27995,27996,27997,
+27998,27999,28000,28001,28002,28003,28004,28005,28006,28007,28008,28009,
+28010,28011,28012,28013,28014,28015,28016,28017,28018,28019,28020,28021,
+28022,28023,28024,28025,28026,28027,28028,28029,28030,28031,28032,28033,
+28034,28035,28036,28037,28038,28039,28040,28041,28042,28043,28044,28045,
+28046,28047,28048,28049,28050,28051,28052,28053,28054,28055,28056,28057,
+28058,28059,28060,28061,28062,28063,28064,28065,28066,28067,28068,28069,
+28070,28071,28072,28073,28074,28075,28076,28077,28078,28079,28080,28081,
+28082,28083,28084,28085,28086,28087,28088,28089,28090,28091,28092,28093,
+28094,28095,28096,28097,28098,28099,28100,28101,28102,28103,28104,28105,
+28106,28107,28108,28109,28110,28111,28112,28113,28114,28115,28116,28117,
+28118,28119,28120,28121,28122,28123,28124,28125,28126,28127,28128,28129,
+28130,28131,28132,28133,28134,28135,28136,28137,28138,28139,28140,28141,
+28142,28143,28144,28145,28146,28147,28148,28149,28150,28151,28152,28153,
+28154,28155,28156,28157,28158,28159,28160,28161,28162,28163,28164,28165,
+28166,28167,28168,28169,28170,28171,28172,28173,28174,28175,28176,28177,
+28178,28179,28180,28181,28182,28183,28184,28185,28186,28187,28188,28189,
+28190,28191,28192,28193,28194,28195,28196,28197,28198,28199,28200,28201,
+28202,28203,28204,28205,28206,28207,28208,28209,28210,28211,28212,28213,
+28214,28215,28216,28217,28218,28219,28220,28221,28222,28223,28224,28225,
+28226,28227,28228,28229,28230,28231,28232,28233,28234,28235,28236,28237,
+28238,28239,28240,28241,28242,28243,28244,28245,28246,28247,28248,28249,
+28250,28251,28252,28253,28254,28255,28256,28257,28258,28259,28260,28261,
+28262,28263,28264,28265,28266,28267,28268,28269,28270,28271,28272,28273,
+28274,28275,28276,28277,28278,28279,28280,28281,28282,28283,28284,28285,
+28286,28287,28288,28289,28290,28291,28292,28293,28294,28295,28296,28297,
+28298,28299,28300,28301,28302,28303,28304,28305,28306,28307,28308,28309,
+28310,28311,28312,28313,28314,28315,28316,28317,28318,28319,28320,28321,
+28322,28323,28324,28325,28326,28327,28328,28329,28330,28331,28332,28333,
+28334,28335,28336,28337,28338,28339,28340,28341,28342,28343,28344,28345,
+28346,28347,28348,28349,28350,28351,28352,28353,28354,28355,28356,28357,
+28358,28359,28360,28361,28362,28363,28364,28365,28366,28367,28368,28369,
+28370,28371,28372,28373,28374,28375,28376,28377,28378,28379,28380,28381,
+28382,28383,28384,28385,28386,28387,28388,28389,28390,28391,28392,28393,
+28394,28395,28396,28397,28398,28399,28400,28401,28402,28403,28404,28405,
+28406,28407,28408,28409,28410,28411,28412,28413,28414,28415,28416,28417,
+28418,28419,28420,28421,28422,28423,28424,28425,28426,28427,28428,28429,
+28430,28431,28432,28433,28434,28435,28436,28437,28438,28439,28440,28441,
+28442,28443,28444,28445,28446,28447,28448,28449,28450,28451,28452,28453,
+28454,28455,28456,28457,28458,28459,28460,28461,28462,28463,28464,28465,
+28466,28467,28468,28469,28470,28471,28472,28473,28474,28475,28476,28477,
+28478,28479,28480,28481,28482,28483,28484,28485,28486,28487,28488,28489,
+28490,28491,28492,28493,28494,28495,28496,28497,28498,28499,28500,28501,
+28502,28503,28504,28505,28506,28507,28508,28509,28510,28511,28512,28513,
+28514,28515,28516,28517,28518,28519,28520,28521,28522,28523,28524,28525,
+28526,28527,28528,28529,28530,28531,28532,28533,28534,28535,28536,28537,
+28538,28539,28540,28541,28542,28543,28544,28545,28546,28547,28548,28549,
+28550,28551,28552,28553,28554,28555,28556,28557,28558,28559,28560,28561,
+28562,28563,28564,28565,28566,28567,28568,28569,28570,28571,28572,28573,
+28574,28575,28576,28577,28578,28579,28580,28581,28582,28583,28584,28585,
+28586,28587,28588,28589,28590,28591,28592,28593,28594,28595,28596,28597,
+28598,28599,28600,28601,28602,28603,28604,28605,28606,28607,28608,28609,
+28610,28611,28612,28613,28614,28615,28616,28617,28618,28619,28620,28621,
+28622,28623,28624,28625,28626,28627,28628,28629,28630,28631,28632,28633,
+28634,28635,28636,28637,28638,28639,28640,28641,28642,28643,28644,28645,
+28646,28647,28648,28649,28650,28651,28652,28653,28654,28655,28656,28657,
+28658,28659,28660,28661,28662,28663,28664,28665,28666,28667,28668,28669,
+28670,28671,28672,28673,28674,28675,28676,28677,28678,28679,28680,28681,
+28682,28683,28684,28685,28686,28687,28688,28689,28690,28691,28692,28693,
+28694,28695,28696,28697,28698,28699,28700,28701,28702,28703,28704,28705,
+28706,28707,28708,28709,28710,28711,28712,28713,28714,28715,28716,28717,
+28718,28719,28720,28721,28722,28723,28724,28725,28726,28727,28728,28729,
+28730,28731,28732,28733,28734,28735,28736,28737,28738,28739,28740,28741,
+28742,28743,28744,28745,28746,28747,28748,28749,28750,28751,28752,28753,
+28754,28755,28756,28757,28758,28759,28760,28761,28762,28763,28764,28765,
+28766,28767,28768,28769,28770,28771,28772,28773,28774,28775,28776,28777,
+28778,28779,28780,28781,28782,28783,28784,28785,28786,28787,28788,28789,
+28790,28791,28792,28793,28794,28795,28796,28797,28798,28799,28800,28801,
+28802,28803,28804,28805,28806,28807,28808,28809,28810,28811,28812,28813,
+28814,28815,28816,28817,28818,28819,28820,28821,28822,28823,28824,28825,
+28826,28827,28828,28829,28830,28831,28832,28833,28834,28835,28836,28837,
+28838,28839,28840,28841,28842,28843,28844,28845,28846,28847,28848,28849,
+28850,28851,28852,28853,28854,28855,28856,28857,28858,28859,28860,28861,
+28862,28863,28864,28865,28866,28867,28868,28869,28870,28871,28872,28873,
+28874,28875,28876,28877,28878,28879,28880,28881,28882,28883,28884,28885,
+28886,28887,28888,28889,28890,28891,28892,28893,28894,28895,28896,28897,
+28898,28899,28900,28901,28902,28903,28904,28905,28906,28907,28908,28909,
+28910,28911,28912,28913,28914,28915,28916,28917,28918,28919,28920,28921,
+28922,28923,28924,28925,28926,28927,28928,28929,28930,28931,28932,28933,
+28934,28935,28936,28937,28938,28939,28940,28941,28942,28943,28944,28945,
+28946,28947,28948,28949,28950,28951,28952,28953,28954,28955,28956,28957,
+28958,28959,28960,28961,28962,28963,28964,28965,28966,28967,28968,28969,
+28970,28971,28972,28973,28974,28975,28976,28977,28978,28979,28980,28981,
+28982,28983,28984,28985,28986,28987,28988,28989,28990,28991,28992,28993,
+28994,28995,28996,28997,28998,28999,29000,29001,29002,29003,29004,29005,
+29006,29007,29008,29009,29010,29011,29012,29013,29014,29015,29016,29017,
+29018,29019,29020,29021,29022,29023,29024,29025,29026,29027,29028,29029,
+29030,29031,29032,29033,29034,29035,29036,29037,29038,29039,29040,29041,
+29042,29043,29044,29045,29046,29047,29048,29049,29050,29051,29052,29053,
+29054,29055,29056,29057,29058,29059,29060,29061,29062,29063,29064,29065,
+29066,29067,29068,29069,29070,29071,29072,29073,29074,29075,29076,29077,
+29078,29079,29080,29081,29082,29083,29084,29085,29086,29087,29088,29089,
+29090,29091,29092,29093,29094,29095,29096,29097,29098,29099,29100,29101,
+29102,29103,29104,29105,29106,29107,29108,29109,29110,29111,29112,29113,
+29114,29115,29116,29117,29118,29119,29120,29121,29122,29123,29124,29125,
+29126,29127,29128,29129,29130,29131,29132,29133,29134,29135,29136,29137,
+29138,29139,29140,29141,29142,29143,29144,29145,29146,29147,29148,29149,
+29150,29151,29152,29153,29154,29155,29156,29157,29158,29159,29160,29161,
+29162,29163,29164,29165,29166,29167,29168,29169,29170,29171,29172,29173,
+29174,29175,29176,29177,29178,29179,29180,29181,29182,29183,29184,29185,
+29186,29187,29188,29189,29190,29191,29192,29193,29194,29195,29196,29197,
+29198,29199,29200,29201,29202,29203,29204,29205,29206,29207,29208,29209,
+29210,29211,29212,29213,29214,29215,29216,29217,29218,29219,29220,29221,
+29222,29223,29224,29225,29226,29227,29228,29229,29230,29231,29232,29233,
+29234,29235,29236,29237,29238,29239,29240,29241,29242,29243,29244,29245,
+29246,29247,29248,29249,29250,29251,29252,29253,29254,29255,29256,29257,
+29258,29259,29260,29261,29262,29263,29264,29265,29266,29267,29268,29269,
+29270,29271,29272,29273,29274,29275,29276,29277,29278,29279,29280,29281,
+29282,29283,29284,29285,29286,29287,29288,29289,29290,29291,29292,29293,
+29294,29295,29296,29297,29298,29299,29300,29301,29302,29303,29304,29305,
+29306,29307,29308,29309,29310,29311,29312,29313,29314,29315,29316,29317,
+29318,29319,29320,29321,29322,29323,29324,29325,29326,29327,29328,29329,
+29330,29331,29332,29333,29334,29335,29336,29337,29338,29339,29340,29341,
+29342,29343,29344,29345,29346,29347,29348,29349,29350,29351,29352,29353,
+29354,29355,29356,29357,29358,29359,29360,29361,29362,29363,29364,29365,
+29366,29367,29368,29369,29370,29371,29372,29373,29374,29375,29376,29377,
+29378,29379,29380,29381,29382,29383,29384,29385,29386,29387,29388,29389,
+29390,29391,29392,29393,29394,29395,29396,29397,29398,29399,29400,29401,
+29402,29403,29404,29405,29406,29407,29408,29409,29410,29411,29412,29413,
+29414,29415,29416,29417,29418,29419,29420,29421,29422,29423,29424,29425,
+29426,29427,29428,29429,29430,29431,29432,29433,29434,29435,29436,29437,
+29438,29439,29440,29441,29442,29443,29444,29445,29446,29447,29448,29449,
+29450,29451,29452,29453,29454,29455,29456,29457,29458,29459,29460,29461,
+29462,29463,29464,29465,29466,29467,29468,29469,29470,29471,29472,29473,
+29474,29475,29476,29477,29478,29479,29480,29481,29482,29483,29484,29485,
+29486,29487,29488,29489,29490,29491,29492,29493,29494,29495,29496,29497,
+29498,29499,29500,29501,29502,29503,29504,29505,29506,29507,29508,29509,
+29510,29511,29512,29513,29514,29515,29516,29517,29518,29519,29520,29521,
+29522,29523,29524,29525,29526,29527,29528,29529,29530,29531,29532,29533,
+29534,29535,29536,29537,29538,29539,29540,29541,29542,29543,29544,29545,
+29546,29547,29548,29549,29550,29551,29552,29553,29554,29555,29556,29557,
+29558,29559,29560,29561,29562,29563,29564,29565,29566,29567,29568,29569,
+29570,29571,29572,29573,29574,29575,29576,29577,29578,29579,29580,29581,
+29582,29583,29584,29585,29586,29587,29588,29589,29590,29591,29592,29593,
+29594,29595,29596,29597,29598,29599,29600,29601,29602,29603,29604,29605,
+29606,29607,29608,29609,29610,29611,29612,29613,29614,29615,29616,29617,
+29618,29619,29620,29621,29622,29623,29624,29625,29626,29627,29628,29629,
+29630,29631,29632,29633,29634,29635,29636,29637,29638,29639,29640,29641,
+29642,29643,29644,29645,29646,29647,29648,29649,29650,29651,29652,29653,
+29654,29655,29656,29657,29658,29659,29660,29661,29662,29663,29664,29665,
+29666,29667,29668,29669,29670,29671,29672,29673,29674,29675,29676,29677,
+29678,29679,29680,29681,29682,29683,29684,29685,29686,29687,29688,29689,
+29690,29691,29692,29693,29694,29695,29696,29697,29698,29699,29700,29701,
+29702,29703,29704,29705,29706,29707,29708,29709,29710,29711,29712,29713,
+29714,29715,29716,29717,29718,29719,29720,29721,29722,29723,29724,29725,
+29726,29727,29728,29729,29730,29731,29732,29733,29734,29735,29736,29737,
+29738,29739,29740,29741,29742,29743,29744,29745,29746,29747,29748,29749,
+29750,29751,29752,29753,29754,29755,29756,29757,29758,29759,29760,29761,
+29762,29763,29764,29765,29766,29767,29768,29769,29770,29771,29772,29773,
+29774,29775,29776,29777,29778,29779,29780,29781,29782,29783,29784,29785,
+29786,29787,29788,29789,29790,29791,29792,29793,29794,29795,29796,29797,
+29798,29799,29800,29801,29802,29803,29804,29805,29806,29807,29808,29809,
+29810,29811,29812,29813,29814,29815,29816,29817,29818,29819,29820,29821,
+29822,29823,29824,29825,29826,29827,29828,29829,29830,29831,29832,29833,
+29834,29835,29836,29837,29838,29839,29840,29841,29842,29843,29844,29845,
+29846,29847,29848,29849,29850,29851,29852,29853,29854,29855,29856,29857,
+29858,29859,29860,29861,29862,29863,29864,29865,29866,29867,29868,29869,
+29870,29871,29872,29873,29874,29875,29876,29877,29878,29879,29880,29881,
+29882,29883,29884,29885,29886,29887,29888,29889,29890,29891,29892,29893,
+29894,29895,29896,29897,29898,29899,29900,29901,29902,29903,29904,29905,
+29906,29907,29908,29909,29910,29911,29912,29913,29914,29915,29916,29917,
+29918,29919,29920,29921,29922,29923,29924,29925,29926,29927,29928,29929,
+29930,29931,29932,29933,29934,29935,29936,29937,29938,29939,29940,29941,
+29942,29943,29944,29945,29946,29947,29948,29949,29950,29951,29952,29953,
+29954,29955,29956,29957,29958,29959,29960,29961,29962,29963,29964,29965,
+29966,29967,29968,29969,29970,29971,29972,29973,29974,29975,29976,29977,
+29978,29979,29980,29981,29982,29983,29984,29985,29986,29987,29988,29989,
+29990,29991,29992,29993,29994,29995,29996,29997,29998,29999,30000,30001,
+30002,30003,30004,30005,30006,30007,30008,30009,30010,30011,30012,30013,
+30014,30015,30016,30017,30018,30019,30020,30021,30022,30023,30024,30025,
+30026,30027,30028,30029,30030,30031,30032,30033,30034,30035,30036,30037,
+30038,30039,30040,30041,30042,30043,30044,30045,30046,30047,30048,30049,
+30050,30051,30052,30053,30054,30055,30056,30057,30058,30059,30060,30061,
+30062,30063,30064,30065,30066,30067,30068,30069,30070,30071,30072,30073,
+30074,30075,30076,30077,30078,30079,30080,30081,30082,30083,30084,30085,
+30086,30087,30088,30089,30090,30091,30092,30093,30094,30095,30096,30097,
+30098,30099,30100,30101,30102,30103,30104,30105,30106,30107,30108,30109,
+30110,30111,30112,30113,30114,30115,30116,30117,30118,30119,30120,30121,
+30122,30123,30124,30125,30126,30127,30128,30129,30130,30131,30132,30133,
+30134,30135,30136,30137,30138,30139,30140,30141,30142,30143,30144,30145,
+30146,30147,30148,30149,30150,30151,30152,30153,30154,30155,30156,30157,
+30158,30159,30160,30161,30162,30163,30164,30165,30166,30167,30168,30169,
+30170,30171,30172,30173,30174,30175,30176,30177,30178,30179,30180,30181,
+30182,30183,30184,30185,30186,30187,30188,30189,30190,30191,30192,30193,
+30194,30195,30196,30197,30198,30199,30200,30201,30202,30203,30204,30205,
+30206,30207,30208,30209,30210,30211,30212,30213,30214,30215,30216,30217,
+30218,30219,30220,30221,30222,30223,30224,30225,30226,30227,30228,30229,
+30230,30231,30232,30233,30234,30235,30236,30237,30238,30239,30240,30241,
+30242,30243,30244,30245,30246,30247,30248,30249,30250,30251,30252,30253,
+30254,30255,30256,30257,30258,30259,30260,30261,30262,30263,30264,30265,
+30266,30267,30268,30269,30270,30271,30272,30273,30274,30275,30276,30277,
+30278,30279,30280,30281,30282,30283,30284,30285,30286,30287,30288,30289,
+30290,30291,30292,30293,30294,30295,30296,30297,30298,30299,30300,30301,
+30302,30303,30304,30305,30306,30307,30308,30309,30310,30311,30312,30313,
+30314,30315,30316,30317,30318,30319,30320,30321,30322,30323,30324,30325,
+30326,30327,30328,30329,30330,30331,30332,30333,30334,30335,30336,30337,
+30338,30339,30340,30341,30342,30343,30344,30345,30346,30347,30348,30349,
+30350,30351,30352,30353,30354,30355,30356,30357,30358,30359,30360,30361,
+30362,30363,30364,30365,30366,30367,30368,30369,30370,30371,30372,30373,
+30374,30375,30376,30377,30378,30379,30380,30381,30382,30383,30384,30385,
+30386,30387,30388,30389,30390,30391,30392,30393,30394,30395,30396,30397,
+30398,30399,30400,30401,30402,30403,30404,30405,30406,30407,30408,30409,
+30410,30411,30412,30413,30414,30415,30416,30417,30418,30419,30420,30421,
+30422,30423,30424,30425,30426,30427,30428,30429,30430,30431,30432,30433,
+30434,30435,30436,30437,30438,30439,30440,30441,30442,30443,30444,30445,
+30446,30447,30448,30449,30450,30451,30452,30453,30454,30455,30456,30457,
+30458,30459,30460,30461,30462,30463,30464,30465,30466,30467,30468,30469,
+30470,30471,30472,30473,30474,30475,30476,30477,30478,30479,30480,30481,
+30482,30483,30484,30485,30486,30487,30488,30489,30490,30491,30492,30493,
+30494,30495,30496,30497,30498,30499,30500,30501,30502,30503,30504,30505,
+30506,30507,30508,30509,30510,30511,30512,30513,30514,30515,30516,30517,
+30518,30519,30520,30521,30522,30523,30524,30525,30526,30527,30528,30529,
+30530,30531,30532,30533,30534,30535,30536,30537,30538,30539,30540,30541,
+30542,30543,30544,30545,30546,30547,30548,30549,30550,30551,30552,30553,
+30554,30555,30556,30557,30558,30559,30560,30561,30562,30563,30564,30565,
+30566,30567,30568,30569,30570,30571,30572,30573,30574,30575,30576,30577,
+30578,30579,30580,30581,30582,30583,30584,30585,30586,30587,30588,30589,
+30590,30591,30592,30593,30594,30595,30596,30597,30598,30599,30600,30601,
+30602,30603,30604,30605,30606,30607,30608,30609,30610,30611,30612,30613,
+30614,30615,30616,30617,30618,30619,30620,30621,30622,30623,30624,30625,
+30626,30627,30628,30629,30630,30631,30632,30633,30634,30635,30636,30637,
+30638,30639,30640,30641,30642,30643,30644,30645,30646,30647,30648,30649,
+30650,30651,30652,30653,30654,30655,30656,30657,30658,30659,30660,30661,
+30662,30663,30664,30665,30666,30667,30668,30669,30670,30671,30672,30673,
+30674,30675,30676,30677,30678,30679,30680,30681,30682,30683,30684,30685,
+30686,30687,30688,30689,30690,30691,30692,30693,30694,30695,30696,30697,
+30698,30699,30700,30701,30702,30703,30704,30705,30706,30707,30708,30709,
+30710,30711,30712,30713,30714,30715,30716,30717,30718,30719,30720,30721,
+30722,30723,30724,30725,30726,30727,30728,30729,30730,30731,30732,30733,
+30734,30735,30736,30737,30738,30739,30740,30741,30742,30743,30744,30745,
+30746,30747,30748,30749,30750,30751,30752,30753,30754,30755,30756,30757,
+30758,30759,30760,30761,30762,30763,30764,30765,30766,30767,30768,30769,
+30770,30771,30772,30773,30774,30775,30776,30777,30778,30779,30780,30781,
+30782,30783,30784,30785,30786,30787,30788,30789,30790,30791,30792,30793,
+30794,30795,30796,30797,30798,30799,30800,30801,30802,30803,30804,30805,
+30806,30807,30808,30809,30810,30811,30812,30813,30814,30815,30816,30817,
+30818,30819,30820,30821,30822,30823,30824,30825,30826,30827,30828,30829,
+30830,30831,30832,30833,30834,30835,30836,30837,30838,30839,30840,30841,
+30842,30843,30844,30845,30846,30847,30848,30849,30850,30851,30852,30853,
+30854,30855,30856,30857,30858,30859,30860,30861,30862,30863,30864,30865,
+30866,30867,30868,30869,30870,30871,30872,30873,30874,30875,30876,30877,
+30878,30879,30880,30881,30882,30883,30884,30885,30886,30887,30888,30889,
+30890,30891,30892,30893,30894,30895,30896,30897,30898,30899,30900,30901,
+30902,30903,30904,30905,30906,30907,30908,30909,30910,30911,30912,30913,
+30914,30915,30916,30917,30918,30919,30920,30921,30922,30923,30924,30925,
+30926,30927,30928,30929,30930,30931,30932,30933,30934,30935,30936,30937,
+30938,30939,30940,30941,30942,30943,30944,30945,30946,30947,30948,30949,
+30950,30951,30952,30953,30954,30955,30956,30957,30958,30959,30960,30961,
+30962,30963,30964,30965,30966,30967,30968,30969,30970,30971,30972,30973,
+30974,30975,30976,30977,30978,30979,30980,30981,30982,30983,30984,30985,
+30986,30987,30988,30989,30990,30991,30992,30993,30994,30995,30996,30997,
+30998,30999,31000,31001,31002,31003,31004,31005,31006,31007,31008,31009,
+31010,31011,31012,31013,31014,31015,31016,31017,31018,31019,31020,31021,
+31022,31023,31024,31025,31026,31027,31028,31029,31030,31031,31032,31033,
+31034,31035,31036,31037,31038,31039,31040,31041,31042,31043,31044,31045,
+31046,31047,31048,31049,31050,31051,31052,31053,31054,31055,31056,31057,
+31058,31059,31060,31061,31062,31063,31064,31065,31066,31067,31068,31069,
+31070,31071,31072,31073,31074,31075,31076,31077,31078,31079,31080,31081,
+31082,31083,31084,31085,31086,31087,31088,31089,31090,31091,31092,31093,
+31094,31095,31096,31097,31098,31099,31100,31101,31102,31103,31104,31105,
+31106,31107,31108,31109,31110,31111,31112,31113,31114,31115,31116,31117,
+31118,31119,31120,31121,31122,31123,31124,31125,31126,31127,31128,31129,
+31130,31131,31132,31133,31134,31135,31136,31137,31138,31139,31140,31141,
+31142,31143,31144,31145,31146,31147,31148,31149,31150,31151,31152,31153,
+31154,31155,31156,31157,31158,31159,31160,31161,31162,31163,31164,31165,
+31166,31167,31168,31169,31170,31171,31172,31173,31174,31175,31176,31177,
+31178,31179,31180,31181,31182,31183,31184,31185,31186,31187,31188,31189,
+31190,31191,31192,31193,31194,31195,31196,31197,31198,31199,31200,31201,
+31202,31203,31204,31205,31206,31207,31208,31209,31210,31211,31212,31213,
+31214,31215,31216,31217,31218,31219,31220,31221,31222,31223,31224,31225,
+31226,31227,31228,31229,31230,31231,31232,31233,31234,31235,31236,31237,
+31238,31239,31240,31241,31242,31243,31244,31245,31246,31247,31248,31249,
+31250,31251,31252,31253,31254,31255,31256,31257,31258,31259,31260,31261,
+31262,31263,31264,31265,31266,31267,31268,31269,31270,31271,31272,31273,
+31274,31275,31276,31277,31278,31279,31280,31281,31282,31283,31284,31285,
+31286,31287,31288,31289,31290,31291,31292,31293,31294,31295,31296,31297,
+31298,31299,31300,31301,31302,31303,31304,31305,31306,31307,31308,31309,
+31310,31311,31312,31313,31314,31315,31316,31317,31318,31319,31320,31321,
+31322,31323,31324,31325,31326,31327,31328,31329,31330,31331,31332,31333,
+31334,31335,31336,31337,31338,31339,31340,31341,31342,31343,31344,31345,
+31346,31347,31348,31349,31350,31351,31352,31353,31354,31355,31356,31357,
+31358,31359,31360,31361,31362,31363,31364,31365,31366,31367,31368,31369,
+31370,31371,31372,31373,31374,31375,31376,31377,31378,31379,31380,31381,
+31382,31383,31384,31385,31386,31387,31388,31389,31390,31391,31392,31393,
+31394,31395,31396,31397,31398,31399,31400,31401,31402,31403,31404,31405,
+31406,31407,31408,31409,31410,31411,31412,31413,31414,31415,31416,31417,
+31418,31419,31420,31421,31422,31423,31424,31425,31426,31427,31428,31429,
+31430,31431,31432,31433,31434,31435,31436,31437,31438,31439,31440,31441,
+31442,31443,31444,31445,31446,31447,31448,31449,31450,31451,31452,31453,
+31454,31455,31456,31457,31458,31459,31460,31461,31462,31463,31464,31465,
+31466,31467,31468,31469,31470,31471,31472,31473,31474,31475,31476,31477,
+31478,31479,31480,31481,31482,31483,31484,31485,31486,31487,31488,31489,
+31490,31491,31492,31493,31494,31495,31496,31497,31498,31499,31500,31501,
+31502,31503,31504,31505,31506,31507,31508,31509,31510,31511,31512,31513,
+31514,31515,31516,31517,31518,31519,31520,31521,31522,31523,31524,31525,
+31526,31527,31528,31529,31530,31531,31532,31533,31534,31535,31536,31537,
+31538,31539,31540,31541,31542,31543,31544,31545,31546,31547,31548,31549,
+31550,31551,31552,31553,31554,31555,31556,31557,31558,31559,31560,31561,
+31562,31563,31564,31565,31566,31567,31568,31569,31570,31571,31572,31573,
+31574,31575,31576,31577,31578,31579,31580,31581,31582,31583,31584,31585,
+31586,31587,31588,31589,31590,31591,31592,31593,31594,31595,31596,31597,
+31598,31599,31600,31601,31602,31603,31604,31605,31606,31607,31608,31609,
+31610,31611,31612,31613,31614,31615,31616,31617,31618,31619,31620,31621,
+31622,31623,31624,31625,31626,31627,31628,31629,31630,31631,31632,31633,
+31634,31635,31636,31637,31638,31639,31640,31641,31642,31643,31644,31645,
+31646,31647,31648,31649,31650,31651,31652,31653,31654,31655,31656,31657,
+31658,31659,31660,31661,31662,31663,31664,31665,31666,31667,31668,31669,
+31670,31671,31672,31673,31674,31675,31676,31677,31678,31679,31680,31681,
+31682,31683,31684,31685,31686,31687,31688,31689,31690,31691,31692,31693,
+31694,31695,31696,31697,31698,31699,31700,31701,31702,31703,31704,31705,
+31706,31707,31708,31709,31710,31711,31712,31713,31714,31715,31716,31717,
+31718,31719,31720,31721,31722,31723,31724,31725,31726,31727,31728,31729,
+31730,31731,31732,31733,31734,31735,31736,31737,31738,31739,31740,31741,
+31742,31743,31744,31745,31746,31747,31748,31749,31750,31751,31752,31753,
+31754,31755,31756,31757,31758,31759,31760,31761,31762,31763,31764,31765,
+31766,31767,31768,31769,31770,31771,31772,31773,31774,31775,31776,31777,
+31778,31779,31780,31781,31782,31783,31784,31785,31786,31787,31788,31789,
+31790,31791,31792,31793,31794,31795,31796,31797,31798,31799,31800,31801,
+31802,31803,31804,31805,31806,31807,31808,31809,31810,31811,31812,31813,
+31814,31815,31816,31817,31818,31819,31820,31821,31822,31823,31824,31825,
+31826,31827,31828,31829,31830,31831,31832,31833,31834,31835,31836,31837,
+31838,31839,31840,31841,31842,31843,31844,31845,31846,31847,31848,31849,
+31850,31851,31852,31853,31854,31855,31856,31857,31858,31859,31860,31861,
+31862,31863,31864,31865,31866,31867,31868,31869,31870,31871,31872,31873,
+31874,31875,31876,31877,31878,31879,31880,31881,31882,31883,31884,31885,
+31886,31887,31888,31889,31890,31891,31892,31893,31894,31895,31896,31897,
+31898,31899,31900,31901,31902,31903,31904,31905,31906,31907,31908,31909,
+31910,31911,31912,31913,31914,31915,31916,31917,31918,31919,31920,31921,
+31922,31923,31924,31925,31926,31927,31928,31929,31930,31931,31932,31933,
+31934,31935,31936,31937,31938,31939,31940,31941,31942,31943,31944,31945,
+31946,31947,31948,31949,31950,31951,31952,31953,31954,31955,31956,31957,
+31958,31959,31960,31961,31962,31963,31964,31965,31966,31967,31968,31969,
+31970,31971,31972,31973,31974,31975,31976,31977,31978,31979,31980,31981,
+31982,31983,31984,31985,31986,31987,31988,31989,31990,31991,31992,31993,
+31994,31995,31996,31997,31998,31999,32000,32001,32002,32003,32004,32005,
+32006,32007,32008,32009,32010,32011,32012,32013,32014,32015,32016,32017,
+32018,32019,32020,32021,32022,32023,32024,32025,32026,32027,32028,32029,
+32030,32031,32032,32033,32034,32035,32036,32037,32038,32039,32040,32041,
+32042,32043,32044,32045,32046,32047,32048,32049,32050,32051,32052,32053,
+32054,32055,32056,32057,32058,32059,32060,32061,32062,32063,32064,32065,
+32066,32067,32068,32069,32070,32071,32072,32073,32074,32075,32076,32077,
+32078,32079,32080,32081,32082,32083,32084,32085,32086,32087,32088,32089,
+32090,32091,32092,32093,32094,32095,32096,32097,32098,32099,32100,32101,
+32102,32103,32104,32105,32106,32107,32108,32109,32110,32111,32112,32113,
+32114,32115,32116,32117,32118,32119,32120,32121,32122,32123,32124,32125,
+32126,32127,32128,32129,32130,32131,32132,32133,32134,32135,32136,32137,
+32138,32139,32140,32141,32142,32143,32144,32145,32146,32147,32148,32149,
+32150,32151,32152,32153,32154,32155,32156,32157,32158,32159,32160,32161,
+32162,32163,32164,32165,32166,32167,32168,32169,32170,32171,32172,32173,
+32174,32175,32176,32177,32178,32179,32180,32181,32182,32183,32184,32185,
+32186,32187,32188,32189,32190,32191,32192,32193,32194,32195,32196,32197,
+32198,32199,32200,32201,32202,32203,32204,32205,32206,32207,32208,32209,
+32210,32211,32212,32213,32214,32215,32216,32217,32218,32219,32220,32221,
+32222,32223,32224,32225,32226,32227,32228,32229,32230,32231,32232,32233,
+32234,32235,32236,32237,32238,32239,32240,32241,32242,32243,32244,32245,
+32246,32247,32248,32249,32250,32251,32252,32253,32254,32255,32256,32257,
+32258,32259,32260,32261,32262,32263,32264,32265,32266,32267,32268,32269,
+32270,32271,32272,32273,32274,32275,32276,32277,32278,32279,32280,32281,
+32282,32283,32284,32285,32286,32287,32288,32289,32290,32291,32292,32293,
+32294,32295,32296,32297,32298,32299,32300,32301,32302,32303,32304,32305,
+32306,32307,32308,32309,32310,32311,32312,32313,32314,32315,32316,32317,
+32318,32319,32320,32321,32322,32323,32324,32325,32326,32327,32328,32329,
+32330,32331,32332,32333,32334,32335,32336,32337,32338,32339,32340,32341,
+32342,32343,32344,32345,32346,32347,32348,32349,32350,32351,32352,32353,
+32354,32355,32356,32357,32358,32359,32360,32361,32362,32363,32364,32365,
+32366,32367,32368,32369,32370,32371,32372,32373,32374,32375,32376,32377,
+32378,32379,32380,32381,32382,32383,32384,32385,32386,32387,32388,32389,
+32390,32391,32392,32393,32394,32395,32396,32397,32398,32399,32400,32401,
+32402,32403,32404,32405,32406,32407,32408,32409,32410,32411,32412,32413,
+32414,32415,32416,32417,32418,32419,32420,32421,32422,32423,32424,32425,
+32426,32427,32428,32429,32430,32431,32432,32433,32434,32435,32436,32437,
+32438,32439,32440,32441,32442,32443,32444,32445,32446,32447,32448,32449,
+32450,32451,32452,32453,32454,32455,32456,32457,32458,32459,32460,32461,
+32462,32463,32464,32465,32466,32467,32468,32469,32470,32471,32472,32473,
+32474,32475,32476,32477,32478,32479,32480,32481,32482,32483,32484,32485,
+32486,32487,32488,32489,32490,32491,32492,32493,32494,32495,32496,32497,
+32498,32499,32500,32501,32502,32503,32504,32505,32506,32507,32508,32509,
+32510,32511,32512,32513,32514,32515,32516,32517,32518,32519,32520,32521,
+32522,32523,32524,32525,32526,32527,32528,32529,32530,32531,32532,32533,
+32534,32535,32536,32537,32538,32539,32540,32541,32542,32543,32544,32545,
+32546,32547,32548,32549,32550,32551,32552,32553,32554,32555,32556,32557,
+32558,32559,32560,32561,32562,32563,32564,32565,32566,32567,32568,32569,
+32570,32571,32572,32573,32574,32575,32576,32577,32578,32579,32580,32581,
+32582,32583,32584,32585,32586,32587,32588,32589,32590,32591,32592,32593,
+32594,32595,32596,32597,32598,32599,32600,32601,32602,32603,32604,32605,
+32606,32607,32608,32609,32610,32611,32612,32613,32614,32615,32616,32617,
+32618,32619,32620,32621,32622,32623,32624,32625,32626,32627,32628,32629,
+32630,32631,32632,32633,32634,32635,32636,32637,32638,32639,32640,32641,
+32642,32643,32644,32645,32646,32647,32648,32649,32650,32651,32652,32653,
+32654,32655,32656,32657,32658,32659,32660,32661,32662,32663,32664,32665,
+32666,32667,32668,32669,32670,32671,32672,32673,32674,32675,32676,32677,
+32678,32679,32680,32681,32682,32683,32684,32685,32686,32687,32688,32689,
+32690,32691,32692,32693,32694,32695,32696,32697,32698,32699,32700,32701,
+32702,32703,32704,32705,32706,32707,32708,32709,32710,32711,32712,32713,
+32714,32715,32716,32717,32718,32719,32720,32721,32722,32723,32724,32725,
+32726,32727,32728,32729,32730,32731,32732,32733,32734,32735,32736,32737,
+32738,32739,32740,32741,32742,32743,32744,32745,32746,32747,32748,32749,
+32750,32751,32752,32753,32754,32755,32756,32757,32758,32759,32760,32761,
+32762,32763,32764,32765,32766,32767,32768,32769,32770,32771,32772,32773,
+32774,32775,32776,32777,32778,32779,32780,32781,32782,32783,32784,32785,
+32786,32787,32788,32789,32790,32791,32792,32793,32794,32795,32796,32797,
+32798,32799,32800,32801,32802,32803,32804,32805,32806,32807,32808,32809,
+32810,32811,32812,32813,32814,32815,32816,32817,32818,32819,32820,32821,
+32822,32823,32824,32825,32826,32827,32828,32829,32830,32831,32832,32833,
+32834,32835,32836,32837,32838,32839,32840,32841,32842,32843,32844,32845,
+32846,32847,32848,32849,32850,32851,32852,32853,32854,32855,32856,32857,
+32858,32859,32860,32861,32862,32863,32864,32865,32866,32867,32868,32869,
+32870,32871,32872,32873,32874,32875,32876,32877,32878,32879,32880,32881,
+32882,32883,32884,32885,32886,32887,32888,32889,32890,32891,32892,32893,
+32894,32895,32896,32897,32898,32899,32900,32901,32902,32903,32904,32905,
+32906,32907,32908,32909,32910,32911,32912,32913,32914,32915,32916,32917,
+32918,32919,32920,32921,32922,32923,32924,32925,32926,32927,32928,32929,
+32930,32931,32932,32933,32934,32935,32936,32937,32938,32939,32940,32941,
+32942,32943,32944,32945,32946,32947,32948,32949,32950,32951,32952,32953,
+32954,32955,32956,32957,32958,32959,32960,32961,32962,32963,32964,32965,
+32966,32967,32968,32969,32970,32971,32972,32973,32974,32975,32976,32977,
+32978,32979,32980,32981,32982,32983,32984,32985,32986,32987,32988,32989,
+32990,32991,32992,32993,32994,32995,32996,32997,32998,32999,33000,33001,
+33002,33003,33004,33005,33006,33007,33008,33009,33010,33011,33012,33013,
+33014,33015,33016,33017,33018,33019,33020,33021,33022,33023,33024,33025,
+33026,33027,33028,33029,33030,33031,33032,33033,33034,33035,33036,33037,
+33038,33039,33040,33041,33042,33043,33044,33045,33046,33047,33048,33049,
+33050,33051,33052,33053,33054,33055,33056,33057,33058,33059,33060,33061,
+33062,33063,33064,33065,33066,33067,33068,33069,33070,33071,33072,33073,
+33074,33075,33076,33077,33078,33079,33080,33081,33082,33083,33084,33085,
+33086,33087,33088,33089,33090,33091,33092,33093,33094,33095,33096,33097,
+33098,33099,33100,33101,33102,33103,33104,33105,33106,33107,33108,33109,
+33110,33111,33112,33113,33114,33115,33116,33117,33118,33119,33120,33121,
+33122,33123,33124,33125,33126,33127,33128,33129,33130,33131,33132,33133,
+33134,33135,33136,33137,33138,33139,33140,33141,33142,33143,33144,33145,
+33146,33147,33148,33149,33150,33151,33152,33153,33154,33155,33156,33157,
+33158,33159,33160,33161,33162,33163,33164,33165,33166,33167,33168,33169,
+33170,33171,33172,33173,33174,33175,33176,33177,33178,33179,33180,33181,
+33182,33183,33184,33185,33186,33187,33188,33189,33190,33191,33192,33193,
+33194,33195,33196,33197,33198,33199,33200,33201,33202,33203,33204,33205,
+33206,33207,33208,33209,33210,33211,33212,33213,33214,33215,33216,33217,
+33218,33219,33220,33221,33222,33223,33224,33225,33226,33227,33228,33229,
+33230,33231,33232,33233,33234,33235,33236,33237,33238,33239,33240,33241,
+33242,33243,33244,33245,33246,33247,33248,33249,33250,33251,33252,33253,
+33254,33255,33256,33257,33258,33259,33260,33261,33262,33263,33264,33265,
+33266,33267,33268,33269,33270,33271,33272,33273,33274,33275,33276,33277,
+33278,33279,33280,33281,33282,33283,33284,33285,33286,33287,33288,33289,
+33290,33291,33292,33293,33294,33295,33296,33297,33298,33299,33300,33301,
+33302,33303,33304,33305,33306,33307,33308,33309,33310,33311,33312,33313,
+33314,33315,33316,33317,33318,33319,33320,33321,33322,33323,33324,33325,
+33326,33327,33328,33329,33330,33331,33332,33333,33334,33335,33336,33337,
+33338,33339,33340,33341,33342,33343,33344,33345,33346,33347,33348,33349,
+33350,33351,33352,33353,33354,33355,33356,33357,33358,33359,33360,33361,
+33362,33363,33364,33365,33366,33367,33368,33369,33370,33371,33372,33373,
+33374,33375,33376,33377,33378,33379,33380,33381,33382,33383,33384,33385,
+33386,33387,33388,33389,33390,33391,33392,33393,33394,33395,33396,33397,
+33398,33399,33400,33401,33402,33403,33404,33405,33406,33407,33408,33409,
+33410,33411,33412,33413,33414,33415,33416,33417,33418,33419,33420,33421,
+33422,33423,33424,33425,33426,33427,33428,33429,33430,33431,33432,33433,
+33434,33435,33436,33437,33438,33439,33440,33441,33442,33443,33444,33445,
+33446,33447,33448,33449,33450,33451,33452,33453,33454,33455,33456,33457,
+33458,33459,33460,33461,33462,33463,33464,33465,33466,33467,33468,33469,
+33470,33471,33472,33473,33474,33475,33476,33477,33478,33479,33480,33481,
+33482,33483,33484,33485,33486,33487,33488,33489,33490,33491,33492,33493,
+33494,33495,33496,33497,33498,33499,33500,33501,33502,33503,33504,33505,
+33506,33507,33508,33509,33510,33511,33512,33513,33514,33515,33516,33517,
+33518,33519,33520,33521,33522,33523,33524,33525,33526,33527,33528,33529,
+33530,33531,33532,33533,33534,33535,33536,33537,33538,33539,33540,33541,
+33542,33543,33544,33545,33546,33547,33548,33549,33550,33551,33552,33553,
+33554,33555,33556,33557,33558,33559,33560,33561,33562,33563,33564,33565,
+33566,33567,33568,33569,33570,33571,33572,33573,33574,33575,33576,33577,
+33578,33579,33580,33581,33582,33583,33584,33585,33586,33587,33588,33589,
+33590,33591,33592,33593,33594,33595,33596,33597,33598,33599,33600,33601,
+33602,33603,33604,33605,33606,33607,33608,33609,33610,33611,33612,33613,
+33614,33615,33616,33617,33618,33619,33620,33621,33622,33623,33624,33625,
+33626,33627,33628,33629,33630,33631,33632,33633,33634,33635,33636,33637,
+33638,33639,33640,33641,33642,33643,33644,33645,33646,33647,33648,33649,
+33650,33651,33652,33653,33654,33655,33656,33657,33658,33659,33660,33661,
+33662,33663,33664,33665,33666,33667,33668,33669,33670,33671,33672,33673,
+33674,33675,33676,33677,33678,33679,33680,33681,33682,33683,33684,33685,
+33686,33687,33688,33689,33690,33691,33692,33693,33694,33695,33696,33697,
+33698,33699,33700,33701,33702,33703,33704,33705,33706,33707,33708,33709,
+33710,33711,33712,33713,33714,33715,33716,33717,33718,33719,33720,33721,
+33722,33723,33724,33725,33726,33727,33728,33729,33730,33731,33732,33733,
+33734,33735,33736,33737,33738,33739,33740,33741,33742,33743,33744,33745,
+33746,33747,33748,33749,33750,33751,33752,33753,33754,33755,33756,33757,
+33758,33759,33760,33761,33762,33763,33764,33765,33766,33767,33768,33769,
+33770,33771,33772,33773,33774,33775,33776,33777,33778,33779,33780,33781,
+33782,33783,33784,33785,33786,33787,33788,33789,33790,33791,33792,33793,
+33794,33795,33796,33797,33798,33799,33800,33801,33802,33803,33804,33805,
+33806,33807,33808,33809,33810,33811,33812,33813,33814,33815,33816,33817,
+33818,33819,33820,33821,33822,33823,33824,33825,33826,33827,33828,33829,
+33830,33831,33832,33833,33834,33835,33836,33837,33838,33839,33840,33841,
+33842,33843,33844,33845,33846,33847,33848,33849,33850,33851,33852,33853,
+33854,33855,33856,33857,33858,33859,33860,33861,33862,33863,33864,33865,
+33866,33867,33868,33869,33870,33871,33872,33873,33874,33875,33876,33877,
+33878,33879,33880,33881,33882,33883,33884,33885,33886,33887,33888,33889,
+33890,33891,33892,33893,33894,33895,33896,33897,33898,33899,33900,33901,
+33902,33903,33904,33905,33906,33907,33908,33909,33910,33911,33912,33913,
+33914,33915,33916,33917,33918,33919,33920,33921,33922,33923,33924,33925,
+33926,33927,33928,33929,33930,33931,33932,33933,33934,33935,33936,33937,
+33938,33939,33940,33941,33942,33943,33944,33945,33946,33947,33948,33949,
+33950,33951,33952,33953,33954,33955,33956,33957,33958,33959,33960,33961,
+33962,33963,33964,33965,33966,33967,33968,33969,33970,33971,33972,33973,
+33974,33975,33976,33977,33978,33979,33980,33981,33982,33983,33984,33985,
+33986,33987,33988,33989,33990,33991,33992,33993,33994,33995,33996,33997,
+33998,33999,34000,34001,34002,34003,34004,34005,34006,34007,34008,34009,
+34010,34011,34012,34013,34014,34015,34016,34017,34018,34019,34020,34021,
+34022,34023,34024,34025,34026,34027,34028,34029,34030,34031,34032,34033,
+34034,34035,34036,34037,34038,34039,34040,34041,34042,34043,34044,34045,
+34046,34047,34048,34049,34050,34051,34052,34053,34054,34055,34056,34057,
+34058,34059,34060,34061,34062,34063,34064,34065,34066,34067,34068,34069,
+34070,34071,34072,34073,34074,34075,34076,34077,34078,34079,34080,34081,
+34082,34083,34084,34085,34086,34087,34088,34089,34090,34091,34092,34093,
+34094,34095,34096,34097,34098,34099,34100,34101,34102,34103,34104,34105,
+34106,34107,34108,34109,34110,34111,34112,34113,34114,34115,34116,34117,
+34118,34119,34120,34121,34122,34123,34124,34125,34126,34127,34128,34129,
+34130,34131,34132,34133,34134,34135,34136,34137,34138,34139,34140,34141,
+34142,34143,34144,34145,34146,34147,34148,34149,34150,34151,34152,34153,
+34154,34155,34156,34157,34158,34159,34160,34161,34162,34163,34164,34165,
+34166,34167,34168,34169,34170,34171,34172,34173,34174,34175,34176,34177,
+34178,34179,34180,34181,34182,34183,34184,34185,34186,34187,34188,34189,
+34190,34191,34192,34193,34194,34195,34196,34197,34198,34199,34200,34201,
+34202,34203,34204,34205,34206,34207,34208,34209,34210,34211,34212,34213,
+34214,34215,34216,34217,34218,34219,34220,34221,34222,34223,34224,34225,
+34226,34227,34228,34229,34230,34231,34232,34233,34234,34235,34236,34237,
+34238,34239,34240,34241,34242,34243,34244,34245,34246,34247,34248,34249,
+34250,34251,34252,34253,34254,34255,34256,34257,34258,34259,34260,34261,
+34262,34263,34264,34265,34266,34267,34268,34269,34270,34271,34272,34273,
+34274,34275,34276,34277,34278,34279,34280,34281,34282,34283,34284,34285,
+34286,34287,34288,34289,34290,34291,34292,34293,34294,34295,34296,34297,
+34298,34299,34300,34301,34302,34303,34304,34305,34306,34307,34308,34309,
+34310,34311,34312,34313,34314,34315,34316,34317,34318,34319,34320,34321,
+34322,34323,34324,34325,34326,34327,34328,34329,34330,34331,34332,34333,
+34334,34335,34336,34337,34338,34339,34340,34341,34342,34343,34344,34345,
+34346,34347,34348,34349,34350,34351,34352,34353,34354,34355,34356,34357,
+34358,34359,34360,34361,34362,34363,34364,34365,34366,34367,34368,34369,
+34370,34371,34372,34373,34374,34375,34376,34377,34378,34379,34380,34381,
+34382,34383,34384,34385,34386,34387,34388,34389,34390,34391,34392,34393,
+34394,34395,34396,34397,34398,34399,34400,34401,34402,34403,34404,34405,
+34406,34407,34408,34409,34410,34411,34412,34413,34414,34415,34416,34417,
+34418,34419,34420,34421,34422,34423,34424,34425,34426,34427,34428,34429,
+34430,34431,34432,34433,34434,34435,34436,34437,34438,34439,34440,34441,
+34442,34443,34444,34445,34446,34447,34448,34449,34450,34451,34452,34453,
+34454,34455,34456,34457,34458,34459,34460,34461,34462,34463,34464,34465,
+34466,34467,34468,34469,34470,34471,34472,34473,34474,34475,34476,34477,
+34478,34479,34480,34481,34482,34483,34484,34485,34486,34487,34488,34489,
+34490,34491,34492,34493,34494,34495,34496,34497,34498,34499,34500,34501,
+34502,34503,34504,34505,34506,34507,34508,34509,34510,34511,34512,34513,
+34514,34515,34516,34517,34518,34519,34520,34521,34522,34523,34524,34525,
+34526,34527,34528,34529,34530,34531,34532,34533,34534,34535,34536,34537,
+34538,34539,34540,34541,34542,34543,34544,34545,34546,34547,34548,34549,
+34550,34551,34552,34553,34554,34555,34556,34557,34558,34559,34560,34561,
+34562,34563,34564,34565,34566,34567,34568,34569,34570,34571,34572,34573,
+34574,34575,34576,34577,34578,34579,34580,34581,34582,34583,34584,34585,
+34586,34587,34588,34589,34590,34591,34592,34593,34594,34595,34596,34597,
+34598,34599,34600,34601,34602,34603,34604,34605,34606,34607,34608,34609,
+34610,34611,34612,34613,34614,34615,34616,34617,34618,34619,34620,34621,
+34622,34623,34624,34625,34626,34627,34628,34629,34630,34631,34632,34633,
+34634,34635,34636,34637,34638,34639,34640,34641,34642,34643,34644,34645,
+34646,34647,34648,34649,34650,34651,34652,34653,34654,34655,34656,34657,
+34658,34659,34660,34661,34662,34663,34664,34665,34666,34667,34668,34669,
+34670,34671,34672,34673,34674,34675,34676,34677,34678,34679,34680,34681,
+34682,34683,34684,34685,34686,34687,34688,34689,34690,34691,34692,34693,
+34694,34695,34696,34697,34698,34699,34700,34701,34702,34703,34704,34705,
+34706,34707,34708,34709,34710,34711,34712,34713,34714,34715,34716,34717,
+34718,34719,34720,34721,34722,34723,34724,34725,34726,34727,34728,34729,
+34730,34731,34732,34733,34734,34735,34736,34737,34738,34739,34740,34741,
+34742,34743,34744,34745,34746,34747,34748,34749,34750,34751,34752,34753,
+34754,34755,34756,34757,34758,34759,34760,34761,34762,34763,34764,34765,
+34766,34767,34768,34769,34770,34771,34772,34773,34774,34775,34776,34777,
+34778,34779,34780,34781,34782,34783,34784,34785,34786,34787,34788,34789,
+34790,34791,34792,34793,34794,34795,34796,34797,34798,34799,34800,34801,
+34802,34803,34804,34805,34806,34807,34808,34809,34810,34811,34812,34813,
+34814,34815,34816,34817,34818,34819,34820,34821,34822,34823,34824,34825,
+34826,34827,34828,34829,34830,34831,34832,34833,34834,34835,34836,34837,
+34838,34839,34840,34841,34842,34843,34844,34845,34846,34847,34848,34849,
+34850,34851,34852,34853,34854,34855,34856,34857,34858,34859,34860,34861,
+34862,34863,34864,34865,34866,34867,34868,34869,34870,34871,34872,34873,
+34874,34875,34876,34877,34878,34879,34880,34881,34882,34883,34884,34885,
+34886,34887,34888,34889,34890,34891,34892,34893,34894,34895,34896,34897,
+34898,34899,34900,34901,34902,34903,34904,34905,34906,34907,34908,34909,
+34910,34911,34912,34913,34914,34915,34916,34917,34918,34919,34920,34921,
+34922,34923,34924,34925,34926,34927,34928,34929,34930,34931,34932,34933,
+34934,34935,34936,34937,34938,34939,34940,34941,34942,34943,34944,34945,
+34946,34947,34948,34949,34950,34951,34952,34953,34954,34955,34956,34957,
+34958,34959,34960,34961,34962,34963,34964,34965,34966,34967,34968,34969,
+34970,34971,34972,34973,34974,34975,34976,34977,34978,34979,34980,34981,
+34982,34983,34984,34985,34986,34987,34988,34989,34990,34991,34992,34993,
+34994,34995,34996,34997,34998,34999,35000,35001,35002,35003,35004,35005,
+35006,35007,35008,35009,35010,35011,35012,35013,35014,35015,35016,35017,
+35018,35019,35020,35021,35022,35023,35024,35025,35026,35027,35028,35029,
+35030,35031,35032,35033,35034,35035,35036,35037,35038,35039,35040,35041,
+35042,35043,35044,35045,35046,35047,35048,35049,35050,35051,35052,35053,
+35054,35055,35056,35057,35058,35059,35060,35061,35062,35063,35064,35065,
+35066,35067,35068,35069,35070,35071,35072,35073,35074,35075,35076,35077,
+35078,35079,35080,35081,35082,35083,35084,35085,35086,35087,35088,35089,
+35090,35091,35092,35093,35094,35095,35096,35097,35098,35099,35100,35101,
+35102,35103,35104,35105,35106,35107,35108,35109,35110,35111,35112,35113,
+35114,35115,35116,35117,35118,35119,35120,35121,35122,35123,35124,35125,
+35126,35127,35128,35129,35130,35131,35132,35133,35134,35135,35136,35137,
+35138,35139,35140,35141,35142,35143,35144,35145,35146,35147,35148,35149,
+35150,35151,35152,35153,35154,35155,35156,35157,35158,35159,35160,35161,
+35162,35163,35164,35165,35166,35167,35168,35169,35170,35171,35172,35173,
+35174,35175,35176,35177,35178,35179,35180,35181,35182,35183,35184,35185,
+35186,35187,35188,35189,35190,35191,35192,35193,35194,35195,35196,35197,
+35198,35199,35200,35201,35202,35203,35204,35205,35206,35207,35208,35209,
+35210,35211,35212,35213,35214,35215,35216,35217,35218,35219,35220,35221,
+35222,35223,35224,35225,35226,35227,35228,35229,35230,35231,35232,35233,
+35234,35235,35236,35237,35238,35239,35240,35241,35242,35243,35244,35245,
+35246,35247,35248,35249,35250,35251,35252,35253,35254,35255,35256,35257,
+35258,35259,35260,35261,35262,35263,35264,35265,35266,35267,35268,35269,
+35270,35271,35272,35273,35274,35275,35276,35277,35278,35279,35280,35281,
+35282,35283,35284,35285,35286,35287,35288,35289,35290,35291,35292,35293,
+35294,35295,35296,35297,35298,35299,35300,35301,35302,35303,35304,35305,
+35306,35307,35308,35309,35310,35311,35312,35313,35314,35315,35316,35317,
+35318,35319,35320,35321,35322,35323,35324,35325,35326,35327,35328,35329,
+35330,35331,35332,35333,35334,35335,35336,35337,35338,35339,35340,35341,
+35342,35343,35344,35345,35346,35347,35348,35349,35350,35351,35352,35353,
+35354,35355,35356,35357,35358,35359,35360,35361,35362,35363,35364,35365,
+35366,35367,35368,35369,35370,35371,35372,35373,35374,35375,35376,35377,
+35378,35379,35380,35381,35382,35383,35384,35385,35386,35387,35388,35389,
+35390,35391,35392,35393,35394,35395,35396,35397,35398,35399,35400,35401,
+35402,35403,35404,35405,35406,35407,35408,35409,35410,35411,35412,35413,
+35414,35415,35416,35417,35418,35419,35420,35421,35422,35423,35424,35425,
+35426,35427,35428,35429,35430,35431,35432,35433,35434,35435,35436,35437,
+35438,35439,35440,35441,35442,35443,35444,35445,35446,35447,35448,35449,
+35450,35451,35452,35453,35454,35455,35456,35457,35458,35459,35460,35461,
+35462,35463,35464,35465,35466,35467,35468,35469,35470,35471,35472,35473,
+35474,35475,35476,35477,35478,35479,35480,35481,35482,35483,35484,35485,
+35486,35487,35488,35489,35490,35491,35492,35493,35494,35495,35496,35497,
+35498,35499,35500,35501,35502,35503,35504,35505,35506,35507,35508,35509,
+35510,35511,35512,35513,35514,35515,35516,35517,35518,35519,35520,35521,
+35522,35523,35524,35525,35526,35527,35528,35529,35530,35531,35532,35533,
+35534,35535,35536,35537,35538,35539,35540,35541,35542,35543,35544,35545,
+35546,35547,35548,35549,35550,35551,35552,35553,35554,35555,35556,35557,
+35558,35559,35560,35561,35562,35563,35564,35565,35566,35567,35568,35569,
+35570,35571,35572,35573,35574,35575,35576,35577,35578,35579,35580,35581,
+35582,35583,35584,35585,35586,35587,35588,35589,35590,35591,35592,35593,
+35594,35595,35596,35597,35598,35599,35600,35601,35602,35603,35604,35605,
+35606,35607,35608,35609,35610,35611,35612,35613,35614,35615,35616,35617,
+35618,35619,35620,35621,35622,35623,35624,35625,35626,35627,35628,35629,
+35630,35631,35632,35633,35634,35635,35636,35637,35638,35639,35640,35641,
+35642,35643,35644,35645,35646,35647,35648,35649,35650,35651,35652,35653,
+35654,35655,35656,35657,35658,35659,35660,35661,35662,35663,35664,35665,
+35666,35667,35668,35669,35670,35671,35672,35673,35674,35675,35676,35677,
+35678,35679,35680,35681,35682,35683,35684,35685,35686,35687,35688,35689,
+35690,35691,35692,35693,35694,35695,35696,35697,35698,35699,35700,35701,
+35702,35703,35704,35705,35706,35707,35708,35709,35710,35711,35712,35713,
+35714,35715,35716,35717,35718,35719,35720,35721,35722,35723,35724,35725,
+35726,35727,35728,35729,35730,35731,35732,35733,35734,35735,35736,35737,
+35738,35739,35740,35741,35742,35743,35744,35745,35746,35747,35748,35749,
+35750,35751,35752,35753,35754,35755,35756,35757,35758,35759,35760,35761,
+35762,35763,35764,35765,35766,35767,35768,35769,35770,35771,35772,35773,
+35774,35775,35776,35777,35778,35779,35780,35781,35782,35783,35784,35785,
+35786,35787,35788,35789,35790,35791,35792,35793,35794,35795,35796,35797,
+35798,35799,35800,35801,35802,35803,35804,35805,35806,35807,35808,35809,
+35810,35811,35812,35813,35814,35815,35816,35817,35818,35819,35820,35821,
+35822,35823,35824,35825,35826,35827,35828,35829,35830,35831,35832,35833,
+35834,35835,35836,35837,35838,35839,35840,35841,35842,35843,35844,35845,
+35846,35847,35848,35849,35850,35851,35852,35853,35854,35855,35856,35857,
+35858,35859,35860,35861,35862,35863,35864,35865,35866,35867,35868,35869,
+35870,35871,35872,35873,35874,35875,35876,35877,35878,35879,35880,35881,
+35882,35883,35884,35885,35886,35887,35888,35889,35890,35891,35892,35893,
+35894,35895,35896,35897,35898,35899,35900,35901,35902,35903,35904,35905,
+35906,35907,35908,35909,35910,35911,35912,35913,35914,35915,35916,35917,
+35918,35919,35920,35921,35922,35923,35924,35925,35926,35927,35928,35929,
+35930,35931,35932,35933,35934,35935,35936,35937,35938,35939,35940,35941,
+35942,35943,35944,35945,35946,35947,35948,35949,35950,35951,35952,35953,
+35954,35955,35956,35957,35958,35959,35960,35961,35962,35963,35964,35965,
+35966,35967,35968,35969,35970,35971,35972,35973,35974,35975,35976,35977,
+35978,35979,35980,35981,35982,35983,35984,35985,35986,35987,35988,35989,
+35990,35991,35992,35993,35994,35995,35996,35997,35998,35999,36000,36001,
+36002,36003,36004,36005,36006,36007,36008,36009,36010,36011,36012,36013,
+36014,36015,36016,36017,36018,36019,36020,36021,36022,36023,36024,36025,
+36026,36027,36028,36029,36030,36031,36032,36033,36034,36035,36036,36037,
+36038,36039,36040,36041,36042,36043,36044,36045,36046,36047,36048,36049,
+36050,36051,36052,36053,36054,36055,36056,36057,36058,36059,36060,36061,
+36062,36063,36064,36065,36066,36067,36068,36069,36070,36071,36072,36073,
+36074,36075,36076,36077,36078,36079,36080,36081,36082,36083,36084,36085,
+36086,36087,36088,36089,36090,36091,36092,36093,36094,36095,36096,36097,
+36098,36099,36100,36101,36102,36103,36104,36105,36106,36107,36108,36109,
+36110,36111,36112,36113,36114,36115,36116,36117,36118,36119,36120,36121,
+36122,36123,36124,36125,36126,36127,36128,36129,36130,36131,36132,36133,
+36134,36135,36136,36137,36138,36139,36140,36141,36142,36143,36144,36145,
+36146,36147,36148,36149,36150,36151,36152,36153,36154,36155,36156,36157,
+36158,36159,36160,36161,36162,36163,36164,36165,36166,36167,36168,36169,
+36170,36171,36172,36173,36174,36175,36176,36177,36178,36179,36180,36181,
+36182,36183,36184,36185,36186,36187,36188,36189,36190,36191,36192,36193,
+36194,36195,36196,36197,36198,36199,36200,36201,36202,36203,36204,36205,
+36206,36207,36208,36209,36210,36211,36212,36213,36214,36215,36216,36217,
+36218,36219,36220,36221,36222,36223,36224,36225,36226,36227,36228,36229,
+36230,36231,36232,36233,36234,36235,36236,36237,36238,36239,36240,36241,
+36242,36243,36244,36245,36246,36247,36248,36249,36250,36251,36252,36253,
+36254,36255,36256,36257,36258,36259,36260,36261,36262,36263,36264,36265,
+36266,36267,36268,36269,36270,36271,36272,36273,36274,36275,36276,36277,
+36278,36279,36280,36281,36282,36283,36284,36285,36286,36287,36288,36289,
+36290,36291,36292,36293,36294,36295,36296,36297,36298,36299,36300,36301,
+36302,36303,36304,36305,36306,36307,36308,36309,36310,36311,36312,36313,
+36314,36315,36316,36317,36318,36319,36320,36321,36322,36323,36324,36325,
+36326,36327,36328,36329,36330,36331,36332,36333,36334,36335,36336,36337,
+36338,36339,36340,36341,36342,36343,36344,36345,36346,36347,36348,36349,
+36350,36351,36352,36353,36354,36355,36356,36357,36358,36359,36360,36361,
+36362,36363,36364,36365,36366,36367,36368,36369,36370,36371,36372,36373,
+36374,36375,36376,36377,36378,36379,36380,36381,36382,36383,36384,36385,
+36386,36387,36388,36389,36390,36391,36392,36393,36394,36395,36396,36397,
+36398,36399,36400,36401,36402,36403,36404,36405,36406,36407,36408,36409,
+36410,36411,36412,36413,36414,36415,36416,36417,36418,36419,36420,36421,
+36422,36423,36424,36425,36426,36427,36428,36429,36430,36431,36432,36433,
+36434,36435,36436,36437,36438,36439,36440,36441,36442,36443,36444,36445,
+36446,36447,36448,36449,36450,36451,36452,36453,36454,36455,36456,36457,
+36458,36459,36460,36461,36462,36463,36464,36465,36466,36467,36468,36469,
+36470,36471,36472,36473,36474,36475,36476,36477,36478,36479,36480,36481,
+36482,36483,36484,36485,36486,36487,36488,36489,36490,36491,36492,36493,
+36494,36495,36496,36497,36498,36499,36500,36501,36502,36503,36504,36505,
+36506,36507,36508,36509,36510,36511,36512,36513,36514,36515,36516,36517,
+36518,36519,36520,36521,36522,36523,36524,36525,36526,36527,36528,36529,
+36530,36531,36532,36533,36534,36535,36536,36537,36538,36539,36540,36541,
+36542,36543,36544,36545,36546,36547,36548,36549,36550,36551,36552,36553,
+36554,36555,36556,36557,36558,36559,36560,36561,36562,36563,36564,36565,
+36566,36567,36568,36569,36570,36571,36572,36573,36574,36575,36576,36577,
+36578,36579,36580,36581,36582,36583,36584,36585,36586,36587,36588,36589,
+36590,36591,36592,36593,36594,36595,36596,36597,36598,36599,36600,36601,
+36602,36603,36604,36605,36606,36607,36608,36609,36610,36611,36612,36613,
+36614,36615,36616,36617,36618,36619,36620,36621,36622,36623,36624,36625,
+36626,36627,36628,36629,36630,36631,36632,36633,36634,36635,36636,36637,
+36638,36639,36640,36641,36642,36643,36644,36645,36646,36647,36648,36649,
+36650,36651,36652,36653,36654,36655,36656,36657,36658,36659,36660,36661,
+36662,36663,36664,36665,36666,36667,36668,36669,36670,36671,36672,36673,
+36674,36675,36676,36677,36678,36679,36680,36681,36682,36683,36684,36685,
+36686,36687,36688,36689,36690,36691,36692,36693,36694,36695,36696,36697,
+36698,36699,36700,36701,36702,36703,36704,36705,36706,36707,36708,36709,
+36710,36711,36712,36713,36714,36715,36716,36717,36718,36719,36720,36721,
+36722,36723,36724,36725,36726,36727,36728,36729,36730,36731,36732,36733,
+36734,36735,36736,36737,36738,36739,36740,36741,36742,36743,36744,36745,
+36746,36747,36748,36749,36750,36751,36752,36753,36754,36755,36756,36757,
+36758,36759,36760,36761,36762,36763,36764,36765,36766,36767,36768,36769,
+36770,36771,36772,36773,36774,36775,36776,36777,36778,36779,36780,36781,
+36782,36783,36784,36785,36786,36787,36788,36789,36790,36791,36792,36793,
+36794,36795,36796,36797,36798,36799,36800,36801,36802,36803,36804,36805,
+36806,36807,36808,36809,36810,36811,36812,36813,36814,36815,36816,36817,
+36818,36819,36820,36821,36822,36823,36824,36825,36826,36827,36828,36829,
+36830,36831,36832,36833,36834,36835,36836,36837,36838,36839,36840,36841,
+36842,36843,36844,36845,36846,36847,36848,36849,36850,36851,36852,36853,
+36854,36855,36856,36857,36858,36859,36860,36861,36862,36863,36864,36865,
+36866,36867,36868,36869,36870,36871,36872,36873,36874,36875,36876,36877,
+36878,36879,36880,36881,36882,36883,36884,36885,36886,36887,36888,36889,
+36890,36891,36892,36893,36894,36895,36896,36897,36898,36899,36900,36901,
+36902,36903,36904,36905,36906,36907,36908,36909,36910,36911,36912,36913,
+36914,36915,36916,36917,36918,36919,36920,36921,36922,36923,36924,36925,
+36926,36927,36928,36929,36930,36931,36932,36933,36934,36935,36936,36937,
+36938,36939,36940,36941,36942,36943,36944,36945,36946,36947,36948,36949,
+36950,36951,36952,36953,36954,36955,36956,36957,36958,36959,36960,36961,
+36962,36963,36964,36965,36966,36967,36968,36969,36970,36971,36972,36973,
+36974,36975,36976,36977,36978,36979,36980,36981,36982,36983,36984,36985,
+36986,36987,36988,36989,36990,36991,36992,36993,36994,36995,36996,36997,
+36998,36999,37000,37001,37002,37003,37004,37005,37006,37007,37008,37009,
+37010,37011,37012,37013,37014,37015,37016,37017,37018,37019,37020,37021,
+37022,37023,37024,37025,37026,37027,37028,37029,37030,37031,37032,37033,
+37034,37035,37036,37037,37038,37039,37040,37041,37042,37043,37044,37045,
+37046,37047,37048,37049,37050,37051,37052,37053,37054,37055,37056,37057,
+37058,37059,37060,37061,37062,37063,37064,37065,37066,37067,37068,37069,
+37070,37071,37072,37073,37074,37075,37076,37077,37078,37079,37080,37081,
+37082,37083,37084,37085,37086,37087,37088,37089,37090,37091,37092,37093,
+37094,37095,37096,37097,37098,37099,37100,37101,37102,37103,37104,37105,
+37106,37107,37108,37109,37110,37111,37112,37113,37114,37115,37116,37117,
+37118,37119,37120,37121,37122,37123,37124,37125,37126,37127,37128,37129,
+37130,37131,37132,37133,37134,37135,37136,37137,37138,37139,37140,37141,
+37142,37143,37144,37145,37146,37147,37148,37149,37150,37151,37152,37153,
+37154,37155,37156,37157,37158,37159,37160,37161,37162,37163,37164,37165,
+37166,37167,37168,37169,37170,37171,37172,37173,37174,37175,37176,37177,
+37178,37179,37180,37181,37182,37183,37184,37185,37186,37187,37188,37189,
+37190,37191,37192,37193,37194,37195,37196,37197,37198,37199,37200,37201,
+37202,37203,37204,37205,37206,37207,37208,37209,37210,37211,37212,37213,
+37214,37215,37216,37217,37218,37219,37220,37221,37222,37223,37224,37225,
+37226,37227,37228,37229,37230,37231,37232,37233,37234,37235,37236,37237,
+37238,37239,37240,37241,37242,37243,37244,37245,37246,37247,37248,37249,
+37250,37251,37252,37253,37254,37255,37256,37257,37258,37259,37260,37261,
+37262,37263,37264,37265,37266,37267,37268,37269,37270,37271,37272,37273,
+37274,37275,37276,37277,37278,37279,37280,37281,37282,37283,37284,37285,
+37286,37287,37288,37289,37290,37291,37292,37293,37294,37295,37296,37297,
+37298,37299,37300,37301,37302,37303,37304,37305,37306,37307,37308,37309,
+37310,37311,37312,37313,37314,37315,37316,37317,37318,37319,37320,37321,
+37322,37323,37324,37325,37326,37327,37328,37329,37330,37331,37332,37333,
+37334,37335,37336,37337,37338,37339,37340,37341,37342,37343,37344,37345,
+37346,37347,37348,37349,37350,37351,37352,37353,37354,37355,37356,37357,
+37358,37359,37360,37361,37362,37363,37364,37365,37366,37367,37368,37369,
+37370,37371,37372,37373,37374,37375,37376,37377,37378,37379,37380,37381,
+37382,37383,37384,37385,37386,37387,37388,37389,37390,37391,37392,37393,
+37394,37395,37396,37397,37398,37399,37400,37401,37402,37403,37404,37405,
+37406,37407,37408,37409,37410,37411,37412,37413,37414,37415,37416,37417,
+37418,37419,37420,37421,37422,37423,37424,37425,37426,37427,37428,37429,
+37430,37431,37432,37433,37434,37435,37436,37437,37438,37439,37440,37441,
+37442,37443,37444,37445,37446,37447,37448,37449,37450,37451,37452,37453,
+37454,37455,37456,37457,37458,37459,37460,37461,37462,37463,37464,37465,
+37466,37467,37468,37469,37470,37471,37472,37473,37474,37475,37476,37477,
+37478,37479,37480,37481,37482,37483,37484,37485,37486,37487,37488,37489,
+37490,37491,37492,37493,37494,37495,37496,37497,37498,37499,37500,37501,
+37502,37503,37504,37505,37506,37507,37508,37509,37510,37511,37512,37513,
+37514,37515,37516,37517,37518,37519,37520,37521,37522,37523,37524,37525,
+37526,37527,37528,37529,37530,37531,37532,37533,37534,37535,37536,37537,
+37538,37539,37540,37541,37542,37543,37544,37545,37546,37547,37548,37549,
+37550,37551,37552,37553,37554,37555,37556,37557,37558,37559,37560,37561,
+37562,37563,37564,37565,37566,37567,37568,37569,37570,37571,37572,37573,
+37574,37575,37576,37577,37578,37579,37580,37581,37582,37583,37584,37585,
+37586,37587,37588,37589,37590,37591,37592,37593,37594,37595,37596,37597,
+37598,37599,37600,37601,37602,37603,37604,37605,37606,37607,37608,37609,
+37610,37611,37612,37613,37614,37615,37616,37617,37618,37619,37620,37621,
+37622,37623,37624,37625,37626,37627,37628,37629,37630,37631,37632,37633,
+37634,37635,37636,37637,37638,37639,37640,37641,37642,37643,37644,37645,
+37646,37647,37648,37649,37650,37651,37652,37653,37654,37655,37656,37657,
+37658,37659,37660,37661,37662,37663,37664,37665,37666,37667,37668,37669,
+37670,37671,37672,37673,37674,37675,37676,37677,37678,37679,37680,37681,
+37682,37683,37684,37685,37686,37687,37688,37689,37690,37691,37692,37693,
+37694,37695,37696,37697,37698,37699,37700,37701,37702,37703,37704,37705,
+37706,37707,37708,37709,37710,37711,37712,37713,37714,37715,37716,37717,
+37718,37719,37720,37721,37722,37723,37724,37725,37726,37727,37728,37729,
+37730,37731,37732,37733,37734,37735,37736,37737,37738,37739,37740,37741,
+37742,37743,37744,37745,37746,37747,37748,37749,37750,37751,37752,37753,
+37754,37755,37756,37757,37758,37759,37760,37761,37762,37763,37764,37765,
+37766,37767,37768,37769,37770,37771,37772,37773,37774,37775,37776,37777,
+37778,37779,37780,37781,37782,37783,37784,37785,37786,37787,37788,37789,
+37790,37791,37792,37793,37794,37795,37796,37797,37798,37799,37800,37801,
+37802,37803,37804,37805,37806,37807,37808,37809,37810,37811,37812,37813,
+37814,37815,37816,37817,37818,37819,37820,37821,37822,37823,37824,37825,
+37826,37827,37828,37829,37830,37831,37832,37833,37834,37835,37836,37837,
+37838,37839,37840,37841,37842,37843,37844,37845,37846,37847,37848,37849,
+37850,37851,37852,37853,37854,37855,37856,37857,37858,37859,37860,37861,
+37862,37863,37864,37865,37866,37867,37868,37869,37870,37871,37872,37873,
+37874,37875,37876,37877,37878,37879,37880,37881,37882,37883,37884,37885,
+37886,37887,37888,37889,37890,37891,37892,37893,37894,37895,37896,37897,
+37898,37899,37900,37901,37902,37903,37904,37905,37906,37907,37908,37909,
+37910,37911,37912,37913,37914,37915,37916,37917,37918,37919,37920,37921,
+37922,37923,37924,37925,37926,37927,37928,37929,37930,37931,37932,37933,
+37934,37935,37936,37937,37938,37939,37940,37941,37942,37943,37944,37945,
+37946,37947,37948,37949,37950,37951,37952,37953,37954,37955,37956,37957,
+37958,37959,37960,37961,37962,37963,37964,37965,37966,37967,37968,37969,
+37970,37971,37972,37973,37974,37975,37976,37977,37978,37979,37980,37981,
+37982,37983,37984,37985,37986,37987,37988,37989,37990,37991,37992,37993,
+37994,37995,37996,37997,37998,37999,38000,38001,38002,38003,38004,38005,
+38006,38007,38008,38009,38010,38011,38012,38013,38014,38015,38016,38017,
+38018,38019,38020,38021,38022,38023,38024,38025,38026,38027,38028,38029,
+38030,38031,38032,38033,38034,38035,38036,38037,38038,38039,38040,38041,
+38042,38043,38044,38045,38046,38047,38048,38049,38050,38051,38052,38053,
+38054,38055,38056,38057,38058,38059,38060,38061,38062,38063,38064,38065,
+38066,38067,38068,38069,38070,38071,38072,38073,38074,38075,38076,38077,
+38078,38079,38080,38081,38082,38083,38084,38085,38086,38087,38088,38089,
+38090,38091,38092,38093,38094,38095,38096,38097,38098,38099,38100,38101,
+38102,38103,38104,38105,38106,38107,38108,38109,38110,38111,38112,38113,
+38114,38115,38116,38117,38118,38119,38120,38121,38122,38123,38124,38125,
+38126,38127,38128,38129,38130,38131,38132,38133,38134,38135,38136,38137,
+38138,38139,38140,38141,38142,38143,38144,38145,38146,38147,38148,38149,
+38150,38151,38152,38153,38154,38155,38156,38157,38158,38159,38160,38161,
+38162,38163,38164,38165,38166,38167,38168,38169,38170,38171,38172,38173,
+38174,38175,38176,38177,38178,38179,38180,38181,38182,38183,38184,38185,
+38186,38187,38188,38189,38190,38191,38192,38193,38194,38195,38196,38197,
+38198,38199,38200,38201,38202,38203,38204,38205,38206,38207,38208,38209,
+38210,38211,38212,38213,38214,38215,38216,38217,38218,38219,38220,38221,
+38222,38223,38224,38225,38226,38227,38228,38229,38230,38231,38232,38233,
+38234,38235,38236,38237,38238,38239,38240,38241,38242,38243,38244,38245,
+38246,38247,38248,38249,38250,38251,38252,38253,38254,38255,38256,38257,
+38258,38259,38260,38261,38262,38263,38264,38265,38266,38267,38268,38269,
+38270,38271,38272,38273,38274,38275,38276,38277,38278,38279,38280,38281,
+38282,38283,38284,38285,38286,38287,38288,38289,38290,38291,38292,38293,
+38294,38295,38296,38297,38298,38299,38300,38301,38302,38303,38304,38305,
+38306,38307,38308,38309,38310,38311,38312,38313,38314,38315,38316,38317,
+38318,38319,38320,38321,38322,38323,38324,38325,38326,38327,38328,38329,
+38330,38331,38332,38333,38334,38335,38336,38337,38338,38339,38340,38341,
+38342,38343,38344,38345,38346,38347,38348,38349,38350,38351,38352,38353,
+38354,38355,38356,38357,38358,38359,38360,38361,38362,38363,38364,38365,
+38366,38367,38368,38369,38370,38371,38372,38373,38374,38375,38376,38377,
+38378,38379,38380,38381,38382,38383,38384,38385,38386,38387,38388,38389,
+38390,38391,38392,38393,38394,38395,38396,38397,38398,38399,38400,38401,
+38402,38403,38404,38405,38406,38407,38408,38409,38410,38411,38412,38413,
+38414,38415,38416,38417,38418,38419,38420,38421,38422,38423,38424,38425,
+38426,38427,38428,38429,38430,38431,38432,38433,38434,38435,38436,38437,
+38438,38439,38440,38441,38442,38443,38444,38445,38446,38447,38448,38449,
+38450,38451,38452,38453,38454,38455,38456,38457,38458,38459,38460,38461,
+38462,38463,38464,38465,38466,38467,38468,38469,38470,38471,38472,38473,
+38474,38475,38476,38477,38478,38479,38480,38481,38482,38483,38484,38485,
+38486,38487,38488,38489,38490,38491,38492,38493,38494,38495,38496,38497,
+38498,38499,38500,38501,38502,38503,38504,38505,38506,38507,38508,38509,
+38510,38511,38512,38513,38514,38515,38516,38517,38518,38519,38520,38521,
+38522,38523,38524,38525,38526,38527,38528,38529,38530,38531,38532,38533,
+38534,38535,38536,38537,38538,38539,38540,38541,38542,38543,38544,38545,
+38546,38547,38548,38549,38550,38551,38552,38553,38554,38555,38556,38557,
+38558,38559,38560,38561,38562,38563,38564,38565,38566,38567,38568,38569,
+38570,38571,38572,38573,38574,38575,38576,38577,38578,38579,38580,38581,
+38582,38583,38584,38585,38586,38587,38588,38589,38590,38591,38592,38593,
+38594,38595,38596,38597,38598,38599,38600,38601,38602,38603,38604,38605,
+38606,38607,38608,38609,38610,38611,38612,38613,38614,38615,38616,38617,
+38618,38619,38620,38621,38622,38623,38624,38625,38626,38627,38628,38629,
+38630,38631,38632,38633,38634,38635,38636,38637,38638,38639,38640,38641,
+38642,38643,38644,38645,38646,38647,38648,38649,38650,38651,38652,38653,
+38654,38655,38656,38657,38658,38659,38660,38661,38662,38663,38664,38665,
+38666,38667,38668,38669,38670,38671,38672,38673,38674,38675,38676,38677,
+38678,38679,38680,38681,38682,38683,38684,38685,38686,38687,38688,38689,
+38690,38691,38692,38693,38694,38695,38696,38697,38698,38699,38700,38701,
+38702,38703,38704,38705,38706,38707,38708,38709,38710,38711,38712,38713,
+38714,38715,38716,38717,38718,38719,38720,38721,38722,38723,38724,38725,
+38726,38727,38728,38729,38730,38731,38732,38733,38734,38735,38736,38737,
+38738,38739,38740,38741,38742,38743,38744,38745,38746,38747,38748,38749,
+38750,38751,38752,38753,38754,38755,38756,38757,38758,38759,38760,38761,
+38762,38763,38764,38765,38766,38767,38768,38769,38770,38771,38772,38773,
+38774,38775,38776,38777,38778,38779,38780,38781,38782,38783,38784,38785,
+38786,38787,38788,38789,38790,38791,38792,38793,38794,38795,38796,38797,
+38798,38799,38800,38801,38802,38803,38804,38805,38806,38807,38808,38809,
+38810,38811,38812,38813,38814,38815,38816,38817,38818,38819,38820,38821,
+38822,38823,38824,38825,38826,38827,38828,38829,38830,38831,38832,38833,
+38834,38835,38836,38837,38838,38839,38840,38841,38842,38843,38844,38845,
+38846,38847,38848,38849,38850,38851,38852,38853,38854,38855,38856,38857,
+38858,38859,38860,38861,38862,38863,38864,38865,38866,38867,38868,38869,
+38870,38871,38872,38873,38874,38875,38876,38877,38878,38879,38880,38881,
+38882,38883,38884,38885,38886,38887,38888,38889,38890,38891,38892,38893,
+38894,38895,38896,38897,38898,38899,38900,38901,38902,38903,38904,38905,
+38906,38907,38908,38909,38910,38911,38912,38913,38914,38915,38916,38917,
+38918,38919,38920,38921,38922,38923,38924,38925,38926,38927,38928,38929,
+38930,38931,38932,38933,38934,38935,38936,38937,38938,38939,38940,38941,
+38942,38943,38944,38945,38946,38947,38948,38949,38950,38951,38952,38953,
+38954,38955,38956,38957,38958,38959,38960,38961,38962,38963,38964,38965,
+38966,38967,38968,38969,38970,38971,38972,38973,38974,38975,38976,38977,
+38978,38979,38980,38981,38982,38983,38984,38985,38986,38987,38988,38989,
+38990,38991,38992,38993,38994,38995,38996,38997,38998,38999,39000,39001,
+39002,39003,39004,39005,39006,39007,39008,39009,39010,39011,39012,39013,
+39014,39015,39016,39017,39018,39019,39020,39021,39022,39023,39024,39025,
+39026,39027,39028,39029,39030,39031,39032,39033,39034,39035,39036,39037,
+39038,39039,39040,39041,39042,39043,39044,39045,39046,39047,39048,39049,
+39050,39051,39052,39053,39054,39055,39056,39057,39058,39059,39060,39061,
+39062,39063,39064,39065,39066,39067,39068,39069,39070,39071,39072,39073,
+39074,39075,39076,39077,39078,39079,39080,39081,39082,39083,39084,39085,
+39086,39087,39088,39089,39090,39091,39092,39093,39094,39095,39096,39097,
+39098,39099,39100,39101,39102,39103,39104,39105,39106,39107,39108,39109,
+39110,39111,39112,39113,39114,39115,39116,39117,39118,39119,39120,39121,
+39122,39123,39124,39125,39126,39127,39128,39129,39130,39131,39132,39133,
+39134,39135,39136,39137,39138,39139,39140,39141,39142,39143,39144,39145,
+39146,39147,39148,39149,39150,39151,39152,39153,39154,39155,39156,39157,
+39158,39159,39160,39161,39162,39163,39164,39165,39166,39167,39168,39169,
+39170,39171,39172,39173,39174,39175,39176,39177,39178,39179,39180,39181,
+39182,39183,39184,39185,39186,39187,39188,39189,39190,39191,39192,39193,
+39194,39195,39196,39197,39198,39199,39200,39201,39202,39203,39204,39205,
+39206,39207,39208,39209,39210,39211,39212,39213,39214,39215,39216,39217,
+39218,39219,39220,39221,39222,39223,39224,39225,39226,39227,39228,39229,
+39230,39231,39232,39233,39234,39235,39236,39237,39238,39239,39240,39241,
+39242,39243,39244,39245,39246,39247,39248,39249,39250,39251,39252,39253,
+39254,39255,39256,39257,39258,39259,39260,39261,39262,39263,39264,39265,
+39266,39267,39268,39269,39270,39271,39272,39273,39274,39275,39276,39277,
+39278,39279,39280,39281,39282,39283,39284,39285,39286,39287,39288,39289,
+39290,39291,39292,39293,39294,39295,39296,39297,39298,39299,39300,39301,
+39302,39303,39304,39305,39306,39307,39308,39309,39310,39311,39312,39313,
+39314,39315,39316,39317,39318,39319,39320,39321,39322,39323,39324,39325,
+39326,39327,39328,39329,39330,39331,39332,39333,39334,39335,39336,39337,
+39338,39339,39340,39341,39342,39343,39344,39345,39346,39347,39348,39349,
+39350,39351,39352,39353,39354,39355,39356,39357,39358,39359,39360,39361,
+39362,39363,39364,39365,39366,39367,39368,39369,39370,39371,39372,39373,
+39374,39375,39376,39377,39378,39379,39380,39381,39382,39383,39384,39385,
+39386,39387,39388,39389,39390,39391,39392,39393,39394,39395,39396,39397,
+39398,39399,39400,39401,39402,39403,39404,39405,39406,39407,39408,39409,
+39410,39411,39412,39413,39414,39415,39416,39417,39418,39419,39420,39421,
+39422,39423,39424,39425,39426,39427,39428,39429,39430,39431,39432,39433,
+39434,39435,39436,39437,39438,39439,39440,39441,39442,39443,39444,39445,
+39446,39447,39448,39449,39450,39451,39452,39453,39454,39455,39456,39457,
+39458,39459,39460,39461,39462,39463,39464,39465,39466,39467,39468,39469,
+39470,39471,39472,39473,39474,39475,39476,39477,39478,39479,39480,39481,
+39482,39483,39484,39485,39486,39487,39488,39489,39490,39491,39492,39493,
+39494,39495,39496,39497,39498,39499,39500,39501,39502,39503,39504,39505,
+39506,39507,39508,39509,39510,39511,39512,39513,39514,39515,39516,39517,
+39518,39519,39520,39521,39522,39523,39524,39525,39526,39527,39528,39529,
+39530,39531,39532,39533,39534,39535,39536,39537,39538,39539,39540,39541,
+39542,39543,39544,39545,39546,39547,39548,39549,39550,39551,39552,39553,
+39554,39555,39556,39557,39558,39559,39560,39561,39562,39563,39564,39565,
+39566,39567,39568,39569,39570,39571,39572,39573,39574,39575,39576,39577,
+39578,39579,39580,39581,39582,39583,39584,39585,39586,39587,39588,39589,
+39590,39591,39592,39593,39594,39595,39596,39597,39598,39599,39600,39601,
+39602,39603,39604,39605,39606,39607,39608,39609,39610,39611,39612,39613,
+39614,39615,39616,39617,39618,39619,39620,39621,39622,39623,39624,39625,
+39626,39627,39628,39629,39630,39631,39632,39633,39634,39635,39636,39637,
+39638,39639,39640,39641,39642,39643,39644,39645,39646,39647,39648,39649,
+39650,39651,39652,39653,39654,39655,39656,39657,39658,39659,39660,39661,
+39662,39663,39664,39665,39666,39667,39668,39669,39670,39671,39672,39673,
+39674,39675,39676,39677,39678,39679,39680,39681,39682,39683,39684,39685,
+39686,39687,39688,39689,39690,39691,39692,39693,39694,39695,39696,39697,
+39698,39699,39700,39701,39702,39703,39704,39705,39706,39707,39708,39709,
+39710,39711,39712,39713,39714,39715,39716,39717,39718,39719,39720,39721,
+39722,39723,39724,39725,39726,39727,39728,39729,39730,39731,39732,39733,
+39734,39735,39736,39737,39738,39739,39740,39741,39742,39743,39744,39745,
+39746,39747,39748,39749,39750,39751,39752,39753,39754,39755,39756,39757,
+39758,39759,39760,39761,39762,39763,39764,39765,39766,39767,39768,39769,
+39770,39771,39772,39773,39774,39775,39776,39777,39778,39779,39780,39781,
+39782,39783,39784,39785,39786,39787,39788,39789,39790,39791,39792,39793,
+39794,39795,39796,39797,39798,39799,39800,39801,39802,39803,39804,39805,
+39806,39807,39808,39809,39810,39811,39812,39813,39814,39815,39816,39817,
+39818,39819,39820,39821,39822,39823,39824,39825,39826,39827,39828,39829,
+39830,39831,39832,39833,39834,39835,39836,39837,39838,39839,39840,39841,
+39842,39843,39844,39845,39846,39847,39848,39849,39850,39851,39852,39853,
+39854,39855,39856,39857,39858,39859,39860,39861,39862,39863,39864,39865,
+39866,39867,39868,39869,39870,39871,39872,39873,39874,39875,39876,39877,
+39878,39879,39880,39881,39882,39883,39884,39885,39886,39887,39888,39889,
+39890,39891,39892,39893,39894,39895,39896,39897,39898,39899,39900,39901,
+39902,39903,39904,39905,39906,39907,39908,39909,39910,39911,39912,39913,
+39914,39915,39916,39917,39918,39919,39920,39921,39922,39923,39924,39925,
+39926,39927,39928,39929,39930,39931,39932,39933,39934,39935,39936,39937,
+39938,39939,39940,39941,39942,39943,39944,39945,39946,39947,39948,39949,
+39950,39951,39952,39953,39954,39955,39956,39957,39958,39959,39960,39961,
+39962,39963,39964,39965,39966,39967,39968,39969,39970,39971,39972,39973,
+39974,39975,39976,39977,39978,39979,39980,39981,39982,39983,39984,39985,
+39986,39987,39988,39989,39990,39991,39992,39993,39994,39995,39996,39997,
+39998,39999,40000,40001,40002,40003,40004,40005,40006,40007,40008,40009,
+40010,40011,40012,40013,40014,40015,40016,40017,40018,40019,40020,40021,
+40022,40023,40024,40025,40026,40027,40028,40029,40030,40031,40032,40033,
+40034,40035,40036,40037,40038,40039,40040,40041,40042,40043,40044,40045,
+40046,40047,40048,40049,40050,40051,40052,40053,40054,40055,40056,40057,
+40058,40059,40060,40061,40062,40063,40064,40065,40066,40067,40068,40069,
+40070,40071,40072,40073,40074,40075,40076,40077,40078,40079,40080,40081,
+40082,40083,40084,40085,40086,40087,40088,40089,40090,40091,40092,40093,
+40094,40095,40096,40097,40098,40099,40100,40101,40102,40103,40104,40105,
+40106,40107,40108,40109,40110,40111,40112,40113,40114,40115,40116,40117,
+40118,40119,40120,40121,40122,40123,40124,40125,40126,40127,40128,40129,
+40130,40131,40132,40133,40134,40135,40136,40137,40138,40139,40140,40141,
+40142,40143,40144,40145,40146,40147,40148,40149,40150,40151,40152,40153,
+40154,40155,40156,40157,40158,40159,40160,40161,40162,40163,40164,40165,
+40166,40167,40168,40169,40170,40171,40172,40173,40174,40175,40176,40177,
+40178,40179,40180,40181,40182,40183,40184,40185,40186,40187,40188,40189,
+40190,40191,40192,40193,40194,40195,40196,40197,40198,40199,40200,40201,
+40202,40203,40204,40205,40206,40207,40208,40209,40210,40211,40212,40213,
+40214,40215,40216,40217,40218,40219,40220,40221,40222,40223,40224,40225,
+40226,40227,40228,40229,40230,40231,40232,40233,40234,40235,40236,40237,
+40238,40239,40240,40241,40242,40243,40244,40245,40246,40247,40248,40249,
+40250,40251,40252,40253,40254,40255,40256,40257,40258,40259,40260,40261,
+40262,40263,40264,40265,40266,40267,40268,40269,40270,40271,40272,40273,
+40274,40275,40276,40277,40278,40279,40280,40281,40282,40283,40284,40285,
+40286,40287,40288,40289,40290,40291,40292,40293,40294,40295,40296,40297,
+40298,40299,40300,40301,40302,40303,40304,40305,40306,40307,40308,40309,
+40310,40311,40312,40313,40314,40315,40316,40317,40318,40319,40320,40321,
+40322,40323,40324,40325,40326,40327,40328,40329,40330,40331,40332,40333,
+40334,40335,40336,40337,40338,40339,40340,40341,40342,40343,40344,40345,
+40346,40347,40348,40349,40350,40351,40352,40353,40354,40355,40356,40357,
+40358,40359,40360,40361,40362,40363,40364,40365,40366,40367,40368,40369,
+40370,40371,40372,40373,40374,40375,40376,40377,40378,40379,40380,40381,
+40382,40383,40384,40385,40386,40387,40388,40389,40390,40391,40392,40393,
+40394,40395,40396,40397,40398,40399,40400,40401,40402,40403,40404,40405,
+40406,40407,40408,40409,40410,40411,40412,40413,40414,40415,40416,40417,
+40418,40419,40420,40421,40422,40423,40424,40425,40426,40427,40428,40429,
+40430,40431,40432,40433,40434,40435,40436,40437,40438,40439,40440,40441,
+40442,40443,40444,40445,40446,40447,40448,40449,40450,40451,40452,40453,
+40454,40455,40456,40457,40458,40459,40460,40461,40462,40463,40464,40465,
+40466,40467,40468,40469,40470,40471,40472,40473,40474,40475,40476,40477,
+40478,40479,40480,40481,40482,40483,40484,40485,40486,40487,40488,40489,
+40490,40491,40492,40493,40494,40495,40496,40497,40498,40499,40500,40501,
+40502,40503,40504,40505,40506,40507,40508,40509,40510,40511,40512,40513,
+40514,40515,40516,40517,40518,40519,40520,40521,40522,40523,40524,40525,
+40526,40527,40528,40529,40530,40531,40532,40533,40534,40535,40536,40537,
+40538,40539,40540,40541,40542,40543,40544,40545,40546,40547,40548,40549,
+40550,40551,40552,40553,40554,40555,40556,40557,40558,40559,40560,40561,
+40562,40563,40564,40565,40566,40567,40568,40569,40570,40571,40572,40573,
+40574,40575,40576,40577,40578,40579,40580,40581,40582,40583,40584,40585,
+40586,40587,40588,40589,40590,40591,40592,40593,40594,40595,40596,40597,
+40598,40599,40600,40601,40602,40603,40604,40605,40606,40607,40608,40609,
+40610,40611,40612,40613,40614,40615,40616,40617,40618,40619,40620,40621,
+40622,40623,40624,40625,40626,40627,40628,40629,40630,40631,40632,40633,
+40634,40635,40636,40637,40638,40639,40640,40641,40642,40643,40644,40645,
+40646,40647,40648,40649,40650,40651,40652,40653,40654,40655,40656,40657,
+40658,40659,40660,40661,40662,40663,40664,40665,40666,40667,40668,40669,
+40670,40671,40672,40673,40674,40675,40676,40677,40678,40679,40680,40681,
+40682,40683,40684,40685,40686,40687,40688,40689,40690,40691,40692,40693,
+40694,40695,40696,40697,40698,40699,40700,40701,40702,40703,40704,40705,
+40706,40707,40708,40709,40710,40711,40712,40713,40714,40715,40716,40717,
+40718,40719,40720,40721,40722,40723,40724,40725,40726,40727,40728,40729,
+40730,40731,40732,40733,40734,40735,40736,40737,40738,40739,40740,40741,
+40742,40743,40744,40745,40746,40747,40748,40749,40750,40751,40752,40753,
+40754,40755,40756,40757,40758,40759,40760,40761,40762,40763,40764,40765,
+40766,40767,40768,40769,40770,40771,40772,40773,40774,40775,40776,40777,
+40778,40779,40780,40781,40782,40783,40784,40785,40786,40787,40788,40789,
+40790,40791,40792,40793,40794,40795,40796,40797,40798,40799,40800,40801,
+40802,40803,40804,40805,40806,40807,40808,40809,40810,40811,40812,40813,
+40814,40815,40816,40817,40818,40819,40820,40821,40822,40823,40824,40825,
+40826,40827,40828,40829,40830,40831,40832,40833,40834,40835,40836,40837,
+40838,40839,40840,40841,40842,40843,40844,40845,40846,40847,40848,40849,
+40850,40851,40852,40853,40854,40855,40856,40857,40858,40859,40860,40861,
+40862,40863,40864,40865,40866,40867,40868,40869,40870,40871,40872,40873,
+40874,40875,40876,40877,40878,40879,40880,40881,40882,40883,40884,40885,
+40886,40887,40888,40889,40890,40891,40892,40893,40894,40895,40896,40897,
+40898,40899,40900,40901,40902,40903,40904,40905,40906,40907,40908,40909,
+40910,40911,40912,40913,40914,40915,40916,40917,40918,40919,40920,40921,
+40922,40923,40924,40925,40926,40927,40928,40929,40930,40931,40932,40933,
+40934,40935,40936,40937,40938,40939,40940,40941,40942,40943,40944,40945,
+40946,40947,40948,40949,40950,40951,40952,40953,40954,40955,40956,40957,
+40958,40959,40960,40961,40962,40963,40964,40965,40966,40967,40968,40969,
+40970,40971,40972,40973,40974,40975,40976,40977,40978,40979,40980,40981,
+40982,40983,40984,40985,40986,40987,40988,40989,40990,40991,40992,40993,
+40994,40995,40996,40997,40998,40999,41000,41001,41002,41003,41004,41005,
+41006,41007,41008,41009,41010,41011,41012,41013,41014,41015,41016,41017,
+41018,41019,41020,41021,41022,41023,41024,41025,41026,41027,41028,41029,
+41030,41031,41032,41033,41034,41035,41036,41037,41038,41039,41040,41041,
+41042,41043,41044,41045,41046,41047,41048,41049,41050,41051,41052,41053,
+41054,41055,41056,41057,41058,41059,41060,41061,41062,41063,41064,41065,
+41066,41067,41068,41069,41070,41071,41072,41073,41074,41075,41076,41077,
+41078,41079,41080,41081,41082,41083,41084,41085,41086,41087,41088,41089,
+41090,41091,41092,41093,41094,41095,41096,41097,41098,41099,41100,41101,
+41102,41103,41104,41105,41106,41107,41108,41109,41110,41111,41112,41113,
+41114,41115,41116,41117,41118,41119,41120,41121,41122,41123,41124,41125,
+41126,41127,41128,41129,41130,41131,41132,41133,41134,41135,41136,41137,
+41138,41139,41140,41141,41142,41143,41144,41145,41146,41147,41148,41149,
+41150,41151,41152,41153,41154,41155,41156,41157,41158,41159,41160,41161,
+41162,41163,41164,41165,41166,41167,41168,41169,41170,41171,41172,41173,
+41174,41175,41176,41177,41178,41179,41180,41181,41182,41183,41184,41185,
+41186,41187,41188,41189,41190,41191,41192,41193,41194,41195,41196,41197,
+41198,41199,41200,41201,41202,41203,41204,41205,41206,41207,41208,41209,
+41210,41211,41212,41213,41214,41215,41216,41217,41218,41219,41220,41221,
+41222,41223,41224,41225,41226,41227,41228,41229,41230,41231,41232,41233,
+41234,41235,41236,41237,41238,41239,41240,41241,41242,41243,41244,41245,
+41246,41247,41248,41249,41250,41251,41252,41253,41254,41255,41256,41257,
+41258,41259,41260,41261,41262,41263,41264,41265,41266,41267,41268,41269,
+41270,41271,41272,41273,41274,41275,41276,41277,41278,41279,41280,41281,
+41282,41283,41284,41285,41286,41287,41288,41289,41290,41291,41292,41293,
+41294,41295,41296,41297,41298,41299,41300,41301,41302,41303,41304,41305,
+41306,41307,41308,41309,41310,41311,41312,41313,41314,41315,41316,41317,
+41318,41319,41320,41321,41322,41323,41324,41325,41326,41327,41328,41329,
+41330,41331,41332,41333,41334,41335,41336,41337,41338,41339,41340,41341,
+41342,41343,41344,41345,41346,41347,41348,41349,41350,41351,41352,41353,
+41354,41355,41356,41357,41358,41359,41360,41361,41362,41363,41364,41365,
+41366,41367,41368,41369,41370,41371,41372,41373,41374,41375,41376,41377,
+41378,41379,41380,41381,41382,41383,41384,41385,41386,41387,41388,41389,
+41390,41391,41392,41393,41394,41395,41396,41397,41398,41399,41400,41401,
+41402,41403,41404,41405,41406,41407,41408,41409,41410,41411,41412,41413,
+41414,41415,41416,41417,41418,41419,41420,41421,41422,41423,41424,41425,
+41426,41427,41428,41429,41430,41431,41432,41433,41434,41435,41436,41437,
+41438,41439,41440,41441,41442,41443,41444,41445,41446,41447,41448,41449,
+41450,41451,41452,41453,41454,41455,41456,41457,41458,41459,41460,41461,
+41462,41463,41464,41465,41466,41467,41468,41469,41470,41471,41472,41473,
+41474,41475,41476,41477,41478,41479,41480,41481,41482,41483,41484,41485,
+41486,41487,41488,41489,41490,41491,41492,41493,41494,41495,41496,41497,
+41498,41499,41500,41501,41502,41503,41504,41505,41506,41507,41508,41509,
+41510,41511,41512,41513,41514,41515,41516,41517,41518,41519,41520,41521,
+41522,41523,41524,41525,41526,41527,41528,41529,41530,41531,41532,41533,
+41534,41535,41536,41537,41538,41539,41540,41541,41542,41543,41544,41545,
+41546,41547,41548,41549,41550,41551,41552,41553,41554,41555,41556,41557,
+41558,41559,41560,41561,41562,41563,41564,41565,41566,41567,41568,41569,
+41570,41571,41572,41573,41574,41575,41576,41577,41578,41579,41580,41581,
+41582,41583,41584,41585,41586,41587,41588,41589,41590,41591,41592,41593,
+41594,41595,41596,41597,41598,41599,41600,41601,41602,41603,41604,41605,
+41606,41607,41608,41609,41610,41611,41612,41613,41614,41615,41616,41617,
+41618,41619,41620,41621,41622,41623,41624,41625,41626,41627,41628,41629,
+41630,41631,41632,41633,41634,41635,41636,41637,41638,41639,41640,41641,
+41642,41643,41644,41645,41646,41647,41648,41649,41650,41651,41652,41653,
+41654,41655,41656,41657,41658,41659,41660,41661,41662,41663,41664,41665,
+41666,41667,41668,41669,41670,41671,41672,41673,41674,41675,41676,41677,
+41678,41679,41680,41681,41682,41683,41684,41685,41686,41687,41688,41689,
+41690,41691,41692,41693,41694,41695,41696,41697,41698,41699,41700,41701,
+41702,41703,41704,41705,41706,41707,41708,41709,41710,41711,41712,41713,
+41714,41715,41716,41717,41718,41719,41720,41721,41722,41723,41724,41725,
+41726,41727,41728,41729,41730,41731,41732,41733,41734,41735,41736,41737,
+41738,41739,41740,41741,41742,41743,41744,41745,41746,41747,41748,41749,
+41750,41751,41752,41753,41754,41755,41756,41757,41758,41759,41760,41761,
+41762,41763,41764,41765,41766,41767,41768,41769,41770,41771,41772,41773,
+41774,41775,41776,41777,41778,41779,41780,41781,41782,41783,41784,41785,
+41786,41787,41788,41789,41790,41791,41792,41793,41794,41795,41796,41797,
+41798,41799,41800,41801,41802,41803,41804,41805,41806,41807,41808,41809,
+41810,41811,41812,41813,41814,41815,41816,41817,41818,41819,41820,41821,
+41822,41823,41824,41825,41826,41827,41828,41829,41830,41831,41832,41833,
+41834,41835,41836,41837,41838,41839,41840,41841,41842,41843,41844,41845,
+41846,41847,41848,41849,41850,41851,41852,41853,41854,41855,41856,41857,
+41858,41859,41860,41861,41862,41863,41864,41865,41866,41867,41868,41869,
+41870,41871,41872,41873,41874,41875,41876,41877,41878,41879,41880,41881,
+41882,41883,41884,41885,41886,41887,41888,41889,41890,41891,41892,41893,
+41894,41895,41896,41897,41898,41899,41900,41901,41902,41903,41904,41905,
+41906,41907,41908,41909,41910,41911,41912,41913,41914,41915,41916,41917,
+41918,41919,41920,41921,41922,41923,41924,41925,41926,41927,41928,41929,
+41930,41931,41932,41933,41934,41935,41936,41937,41938,41939,41940,41941,
+41942,41943,41944,41945,41946,41947,41948,41949,41950,41951,41952,41953,
+41954,41955,41956,41957,41958,41959,41960,41961,41962,41963,41964,41965,
+41966,41967,41968,41969,41970,41971,41972,41973,41974,41975,41976,41977,
+41978,41979,41980,41981,41982,41983,41984,41985,41986,41987,41988,41989,
+41990,41991,41992,41993,41994,41995,41996,41997,41998,41999,42000,42001,
+42002,42003,42004,42005,42006,42007,42008,42009,42010,42011,42012,42013,
+42014,42015,42016,42017,42018,42019,42020,42021,42022,42023,42024,42025,
+42026,42027,42028,42029,42030,42031,42032,42033,42034,42035,42036,42037,
+42038,42039,42040,42041,42042,42043,42044,42045,42046,42047,42048,42049,
+42050,42051,42052,42053,42054,42055,42056,42057,42058,42059,42060,42061,
+42062,42063,42064,42065,42066,42067,42068,42069,42070,42071,42072,42073,
+42074,42075,42076,42077,42078,42079,42080,42081,42082,42083,42084,42085,
+42086,42087,42088,42089,42090,42091,42092,42093,42094,42095,42096,42097,
+42098,42099,42100,42101,42102,42103,42104,42105,42106,42107,42108,42109,
+42110,42111,42112,42113,42114,42115,42116,42117,42118,42119,42120,42121,
+42122,42123,42124,42125,42126,42127,42128,42129,42130,42131,42132,42133,
+42134,42135,42136,42137,42138,42139,42140,42141,42142,42143,42144,42145,
+42146,42147,42148,42149,42150,42151,42152,42153,42154,42155,42156,42157,
+42158,42159,42160,42161,42162,42163,42164,42165,42166,42167,42168,42169,
+42170,42171,42172,42173,42174,42175,42176,42177,42178,42179,42180,42181,
+42182,42183,42184,42185,42186,42187,42188,42189,42190,42191,42192,42193,
+42194,42195,42196,42197,42198,42199,42200,42201,42202,42203,42204,42205,
+42206,42207,42208,42209,42210,42211,42212,42213,42214,42215,42216,42217,
+42218,42219,42220,42221,42222,42223,42224,42225,42226,42227,42228,42229,
+42230,42231,42232,42233,42234,42235,42236,42237,42238,42239,42240,42241,
+42242,42243,42244,42245,42246,42247,42248,42249,42250,42251,42252,42253,
+42254,42255,42256,42257,42258,42259,42260,42261,42262,42263,42264,42265,
+42266,42267,42268,42269,42270,42271,42272,42273,42274,42275,42276,42277,
+42278,42279,42280,42281,42282,42283,42284,42285,42286,42287,42288,42289,
+42290,42291,42292,42293,42294,42295,42296,42297,42298,42299,42300,42301,
+42302,42303,42304,42305,42306,42307,42308,42309,42310,42311,42312,42313,
+42314,42315,42316,42317,42318,42319,42320,42321,42322,42323,42324,42325,
+42326,42327,42328,42329,42330,42331,42332,42333,42334,42335,42336,42337,
+42338,42339,42340,42341,42342,42343,42344,42345,42346,42347,42348,42349,
+42350,42351,42352,42353,42354,42355,42356,42357,42358,42359,42360,42361,
+42362,42363,42364,42365,42366,42367,42368,42369,42370,42371,42372,42373,
+42374,42375,42376,42377,42378,42379,42380,42381,42382,42383,42384,42385,
+42386,42387,42388,42389,42390,42391,42392,42393,42394,42395,42396,42397,
+42398,42399,42400,42401,42402,42403,42404,42405,42406,42407,42408,42409,
+42410,42411,42412,42413,42414,42415,42416,42417,42418,42419,42420,42421,
+42422,42423,42424,42425,42426,42427,42428,42429,42430,42431,42432,42433,
+42434,42435,42436,42437,42438,42439,42440,42441,42442,42443,42444,42445,
+42446,42447,42448,42449,42450,42451,42452,42453,42454,42455,42456,42457,
+42458,42459,42460,42461,42462,42463,42464,42465,42466,42467,42468,42469,
+42470,42471,42472,42473,42474,42475,42476,42477,42478,42479,42480,42481,
+42482,42483,42484,42485,42486,42487,42488,42489,42490,42491,42492,42493,
+42494,42495,42496,42497,42498,42499,42500,42501,42502,42503,42504,42505,
+42506,42507,42508,42509,42510,42511,42512,42513,42514,42515,42516,42517,
+42518,42519,42520,42521,42522,42523,42524,42525,42526,42527,42528,42529,
+42530,42531,42532,42533,42534,42535,42536,42537,42538,42539,42540,42541,
+42542,42543,42544,42545,42546,42547,42548,42549,42550,42551,42552,42553,
+42554,42555,42556,42557,42558,42559,42560,42560,42562,42562,42564,42564,
+42566,42566,42568,42568,42570,42570,42572,42572,42574,42574,42576,42576,
+42578,42578,42580,42580,42582,42582,42584,42584,42586,42586,42588,42588,
+42590,42590,42592,42592,42594,42594,42596,42596,42598,42598,42600,42600,
+42602,42602,42604,42604,42606,42607,42608,42609,42610,42611,42612,42613,
+42614,42615,42616,42617,42618,42619,42620,42621,42622,42623,42624,42624,
+42626,42626,42628,42628,42630,42630,42632,42632,42634,42634,42636,42636,
+42638,42638,42640,42640,42642,42642,42644,42644,42646,42646,42648,42649,
+42650,42651,42652,42653,42654,42655,42656,42657,42658,42659,42660,42661,
+42662,42663,42664,42665,42666,42667,42668,42669,42670,42671,42672,42673,
+42674,42675,42676,42677,42678,42679,42680,42681,42682,42683,42684,42685,
+42686,42687,42688,42689,42690,42691,42692,42693,42694,42695,42696,42697,
+42698,42699,42700,42701,42702,42703,42704,42705,42706,42707,42708,42709,
+42710,42711,42712,42713,42714,42715,42716,42717,42718,42719,42720,42721,
+42722,42723,42724,42725,42726,42727,42728,42729,42730,42731,42732,42733,
+42734,42735,42736,42737,42738,42739,42740,42741,42742,42743,42744,42745,
+42746,42747,42748,42749,42750,42751,42752,42753,42754,42755,42756,42757,
+42758,42759,42760,42761,42762,42763,42764,42765,42766,42767,42768,42769,
+42770,42771,42772,42773,42774,42775,42776,42777,42778,42779,42780,42781,
+42782,42783,42784,42785,42786,42786,42788,42788,42790,42790,42792,42792,
+42794,42794,42796,42796,42798,42798,42800,42801,42802,42802,42804,42804,
+42806,42806,42808,42808,42810,42810,42812,42812,42814,42814,42816,42816,
+42818,42818,42820,42820,42822,42822,42824,42824,42826,42826,42828,42828,
+42830,42830,42832,42832,42834,42834,42836,42836,42838,42838,42840,42840,
+42842,42842,42844,42844,42846,42846,42848,42848,42850,42850,42852,42852,
+42854,42854,42856,42856,42858,42858,42860,42860,42862,42862,42864,42865,
+42866,42867,42868,42869,42870,42871,42872,42873,42873,42875,42875,42877,
+42878,42878,42880,42880,42882,42882,42884,42884,42886,42886,42888,42889,
+42890,42891,42891,42893,42894,42895,42896,42896,42898,42899,42900,42901,
+42902,42903,42904,42905,42906,42907,42908,42909,42910,42911,42912,42912,
+42914,42914,42916,42916,42918,42918,42920,42920,42922,42923,42924,42925,
+42926,42927,42928,42929,42930,42931,42932,42933,42934,42935,42936,42937,
+42938,42939,42940,42941,42942,42943,42944,42945,42946,42947,42948,42949,
+42950,42951,42952,42953,42954,42955,42956,42957,42958,42959,42960,42961,
+42962,42963,42964,42965,42966,42967,42968,42969,42970,42971,42972,42973,
+42974,42975,42976,42977,42978,42979,42980,42981,42982,42983,42984,42985,
+42986,42987,42988,42989,42990,42991,42992,42993,42994,42995,42996,42997,
+42998,42999,43000,43001,43002,43003,43004,43005,43006,43007,43008,43009,
+43010,43011,43012,43013,43014,43015,43016,43017,43018,43019,43020,43021,
+43022,43023,43024,43025,43026,43027,43028,43029,43030,43031,43032,43033,
+43034,43035,43036,43037,43038,43039,43040,43041,43042,43043,43044,43045,
+43046,43047,43048,43049,43050,43051,43052,43053,43054,43055,43056,43057,
+43058,43059,43060,43061,43062,43063,43064,43065,43066,43067,43068,43069,
+43070,43071,43072,43073,43074,43075,43076,43077,43078,43079,43080,43081,
+43082,43083,43084,43085,43086,43087,43088,43089,43090,43091,43092,43093,
+43094,43095,43096,43097,43098,43099,43100,43101,43102,43103,43104,43105,
+43106,43107,43108,43109,43110,43111,43112,43113,43114,43115,43116,43117,
+43118,43119,43120,43121,43122,43123,43124,43125,43126,43127,43128,43129,
+43130,43131,43132,43133,43134,43135,43136,43137,43138,43139,43140,43141,
+43142,43143,43144,43145,43146,43147,43148,43149,43150,43151,43152,43153,
+43154,43155,43156,43157,43158,43159,43160,43161,43162,43163,43164,43165,
+43166,43167,43168,43169,43170,43171,43172,43173,43174,43175,43176,43177,
+43178,43179,43180,43181,43182,43183,43184,43185,43186,43187,43188,43189,
+43190,43191,43192,43193,43194,43195,43196,43197,43198,43199,43200,43201,
+43202,43203,43204,43205,43206,43207,43208,43209,43210,43211,43212,43213,
+43214,43215,43216,43217,43218,43219,43220,43221,43222,43223,43224,43225,
+43226,43227,43228,43229,43230,43231,43232,43233,43234,43235,43236,43237,
+43238,43239,43240,43241,43242,43243,43244,43245,43246,43247,43248,43249,
+43250,43251,43252,43253,43254,43255,43256,43257,43258,43259,43260,43261,
+43262,43263,43264,43265,43266,43267,43268,43269,43270,43271,43272,43273,
+43274,43275,43276,43277,43278,43279,43280,43281,43282,43283,43284,43285,
+43286,43287,43288,43289,43290,43291,43292,43293,43294,43295,43296,43297,
+43298,43299,43300,43301,43302,43303,43304,43305,43306,43307,43308,43309,
+43310,43311,43312,43313,43314,43315,43316,43317,43318,43319,43320,43321,
+43322,43323,43324,43325,43326,43327,43328,43329,43330,43331,43332,43333,
+43334,43335,43336,43337,43338,43339,43340,43341,43342,43343,43344,43345,
+43346,43347,43348,43349,43350,43351,43352,43353,43354,43355,43356,43357,
+43358,43359,43360,43361,43362,43363,43364,43365,43366,43367,43368,43369,
+43370,43371,43372,43373,43374,43375,43376,43377,43378,43379,43380,43381,
+43382,43383,43384,43385,43386,43387,43388,43389,43390,43391,43392,43393,
+43394,43395,43396,43397,43398,43399,43400,43401,43402,43403,43404,43405,
+43406,43407,43408,43409,43410,43411,43412,43413,43414,43415,43416,43417,
+43418,43419,43420,43421,43422,43423,43424,43425,43426,43427,43428,43429,
+43430,43431,43432,43433,43434,43435,43436,43437,43438,43439,43440,43441,
+43442,43443,43444,43445,43446,43447,43448,43449,43450,43451,43452,43453,
+43454,43455,43456,43457,43458,43459,43460,43461,43462,43463,43464,43465,
+43466,43467,43468,43469,43470,43471,43472,43473,43474,43475,43476,43477,
+43478,43479,43480,43481,43482,43483,43484,43485,43486,43487,43488,43489,
+43490,43491,43492,43493,43494,43495,43496,43497,43498,43499,43500,43501,
+43502,43503,43504,43505,43506,43507,43508,43509,43510,43511,43512,43513,
+43514,43515,43516,43517,43518,43519,43520,43521,43522,43523,43524,43525,
+43526,43527,43528,43529,43530,43531,43532,43533,43534,43535,43536,43537,
+43538,43539,43540,43541,43542,43543,43544,43545,43546,43547,43548,43549,
+43550,43551,43552,43553,43554,43555,43556,43557,43558,43559,43560,43561,
+43562,43563,43564,43565,43566,43567,43568,43569,43570,43571,43572,43573,
+43574,43575,43576,43577,43578,43579,43580,43581,43582,43583,43584,43585,
+43586,43587,43588,43589,43590,43591,43592,43593,43594,43595,43596,43597,
+43598,43599,43600,43601,43602,43603,43604,43605,43606,43607,43608,43609,
+43610,43611,43612,43613,43614,43615,43616,43617,43618,43619,43620,43621,
+43622,43623,43624,43625,43626,43627,43628,43629,43630,43631,43632,43633,
+43634,43635,43636,43637,43638,43639,43640,43641,43642,43643,43644,43645,
+43646,43647,43648,43649,43650,43651,43652,43653,43654,43655,43656,43657,
+43658,43659,43660,43661,43662,43663,43664,43665,43666,43667,43668,43669,
+43670,43671,43672,43673,43674,43675,43676,43677,43678,43679,43680,43681,
+43682,43683,43684,43685,43686,43687,43688,43689,43690,43691,43692,43693,
+43694,43695,43696,43697,43698,43699,43700,43701,43702,43703,43704,43705,
+43706,43707,43708,43709,43710,43711,43712,43713,43714,43715,43716,43717,
+43718,43719,43720,43721,43722,43723,43724,43725,43726,43727,43728,43729,
+43730,43731,43732,43733,43734,43735,43736,43737,43738,43739,43740,43741,
+43742,43743,43744,43745,43746,43747,43748,43749,43750,43751,43752,43753,
+43754,43755,43756,43757,43758,43759,43760,43761,43762,43763,43764,43765,
+43766,43767,43768,43769,43770,43771,43772,43773,43774,43775,43776,43777,
+43778,43779,43780,43781,43782,43783,43784,43785,43786,43787,43788,43789,
+43790,43791,43792,43793,43794,43795,43796,43797,43798,43799,43800,43801,
+43802,43803,43804,43805,43806,43807,43808,43809,43810,43811,43812,43813,
+43814,43815,43816,43817,43818,43819,43820,43821,43822,43823,43824,43825,
+43826,43827,43828,43829,43830,43831,43832,43833,43834,43835,43836,43837,
+43838,43839,43840,43841,43842,43843,43844,43845,43846,43847,43848,43849,
+43850,43851,43852,43853,43854,43855,43856,43857,43858,43859,43860,43861,
+43862,43863,43864,43865,43866,43867,43868,43869,43870,43871,43872,43873,
+43874,43875,43876,43877,43878,43879,43880,43881,43882,43883,43884,43885,
+43886,43887,43888,43889,43890,43891,43892,43893,43894,43895,43896,43897,
+43898,43899,43900,43901,43902,43903,43904,43905,43906,43907,43908,43909,
+43910,43911,43912,43913,43914,43915,43916,43917,43918,43919,43920,43921,
+43922,43923,43924,43925,43926,43927,43928,43929,43930,43931,43932,43933,
+43934,43935,43936,43937,43938,43939,43940,43941,43942,43943,43944,43945,
+43946,43947,43948,43949,43950,43951,43952,43953,43954,43955,43956,43957,
+43958,43959,43960,43961,43962,43963,43964,43965,43966,43967,43968,43969,
+43970,43971,43972,43973,43974,43975,43976,43977,43978,43979,43980,43981,
+43982,43983,43984,43985,43986,43987,43988,43989,43990,43991,43992,43993,
+43994,43995,43996,43997,43998,43999,44000,44001,44002,44003,44004,44005,
+44006,44007,44008,44009,44010,44011,44012,44013,44014,44015,44016,44017,
+44018,44019,44020,44021,44022,44023,44024,44025,44026,44027,44028,44029,
+44030,44031,44032,44033,44034,44035,44036,44037,44038,44039,44040,44041,
+44042,44043,44044,44045,44046,44047,44048,44049,44050,44051,44052,44053,
+44054,44055,44056,44057,44058,44059,44060,44061,44062,44063,44064,44065,
+44066,44067,44068,44069,44070,44071,44072,44073,44074,44075,44076,44077,
+44078,44079,44080,44081,44082,44083,44084,44085,44086,44087,44088,44089,
+44090,44091,44092,44093,44094,44095,44096,44097,44098,44099,44100,44101,
+44102,44103,44104,44105,44106,44107,44108,44109,44110,44111,44112,44113,
+44114,44115,44116,44117,44118,44119,44120,44121,44122,44123,44124,44125,
+44126,44127,44128,44129,44130,44131,44132,44133,44134,44135,44136,44137,
+44138,44139,44140,44141,44142,44143,44144,44145,44146,44147,44148,44149,
+44150,44151,44152,44153,44154,44155,44156,44157,44158,44159,44160,44161,
+44162,44163,44164,44165,44166,44167,44168,44169,44170,44171,44172,44173,
+44174,44175,44176,44177,44178,44179,44180,44181,44182,44183,44184,44185,
+44186,44187,44188,44189,44190,44191,44192,44193,44194,44195,44196,44197,
+44198,44199,44200,44201,44202,44203,44204,44205,44206,44207,44208,44209,
+44210,44211,44212,44213,44214,44215,44216,44217,44218,44219,44220,44221,
+44222,44223,44224,44225,44226,44227,44228,44229,44230,44231,44232,44233,
+44234,44235,44236,44237,44238,44239,44240,44241,44242,44243,44244,44245,
+44246,44247,44248,44249,44250,44251,44252,44253,44254,44255,44256,44257,
+44258,44259,44260,44261,44262,44263,44264,44265,44266,44267,44268,44269,
+44270,44271,44272,44273,44274,44275,44276,44277,44278,44279,44280,44281,
+44282,44283,44284,44285,44286,44287,44288,44289,44290,44291,44292,44293,
+44294,44295,44296,44297,44298,44299,44300,44301,44302,44303,44304,44305,
+44306,44307,44308,44309,44310,44311,44312,44313,44314,44315,44316,44317,
+44318,44319,44320,44321,44322,44323,44324,44325,44326,44327,44328,44329,
+44330,44331,44332,44333,44334,44335,44336,44337,44338,44339,44340,44341,
+44342,44343,44344,44345,44346,44347,44348,44349,44350,44351,44352,44353,
+44354,44355,44356,44357,44358,44359,44360,44361,44362,44363,44364,44365,
+44366,44367,44368,44369,44370,44371,44372,44373,44374,44375,44376,44377,
+44378,44379,44380,44381,44382,44383,44384,44385,44386,44387,44388,44389,
+44390,44391,44392,44393,44394,44395,44396,44397,44398,44399,44400,44401,
+44402,44403,44404,44405,44406,44407,44408,44409,44410,44411,44412,44413,
+44414,44415,44416,44417,44418,44419,44420,44421,44422,44423,44424,44425,
+44426,44427,44428,44429,44430,44431,44432,44433,44434,44435,44436,44437,
+44438,44439,44440,44441,44442,44443,44444,44445,44446,44447,44448,44449,
+44450,44451,44452,44453,44454,44455,44456,44457,44458,44459,44460,44461,
+44462,44463,44464,44465,44466,44467,44468,44469,44470,44471,44472,44473,
+44474,44475,44476,44477,44478,44479,44480,44481,44482,44483,44484,44485,
+44486,44487,44488,44489,44490,44491,44492,44493,44494,44495,44496,44497,
+44498,44499,44500,44501,44502,44503,44504,44505,44506,44507,44508,44509,
+44510,44511,44512,44513,44514,44515,44516,44517,44518,44519,44520,44521,
+44522,44523,44524,44525,44526,44527,44528,44529,44530,44531,44532,44533,
+44534,44535,44536,44537,44538,44539,44540,44541,44542,44543,44544,44545,
+44546,44547,44548,44549,44550,44551,44552,44553,44554,44555,44556,44557,
+44558,44559,44560,44561,44562,44563,44564,44565,44566,44567,44568,44569,
+44570,44571,44572,44573,44574,44575,44576,44577,44578,44579,44580,44581,
+44582,44583,44584,44585,44586,44587,44588,44589,44590,44591,44592,44593,
+44594,44595,44596,44597,44598,44599,44600,44601,44602,44603,44604,44605,
+44606,44607,44608,44609,44610,44611,44612,44613,44614,44615,44616,44617,
+44618,44619,44620,44621,44622,44623,44624,44625,44626,44627,44628,44629,
+44630,44631,44632,44633,44634,44635,44636,44637,44638,44639,44640,44641,
+44642,44643,44644,44645,44646,44647,44648,44649,44650,44651,44652,44653,
+44654,44655,44656,44657,44658,44659,44660,44661,44662,44663,44664,44665,
+44666,44667,44668,44669,44670,44671,44672,44673,44674,44675,44676,44677,
+44678,44679,44680,44681,44682,44683,44684,44685,44686,44687,44688,44689,
+44690,44691,44692,44693,44694,44695,44696,44697,44698,44699,44700,44701,
+44702,44703,44704,44705,44706,44707,44708,44709,44710,44711,44712,44713,
+44714,44715,44716,44717,44718,44719,44720,44721,44722,44723,44724,44725,
+44726,44727,44728,44729,44730,44731,44732,44733,44734,44735,44736,44737,
+44738,44739,44740,44741,44742,44743,44744,44745,44746,44747,44748,44749,
+44750,44751,44752,44753,44754,44755,44756,44757,44758,44759,44760,44761,
+44762,44763,44764,44765,44766,44767,44768,44769,44770,44771,44772,44773,
+44774,44775,44776,44777,44778,44779,44780,44781,44782,44783,44784,44785,
+44786,44787,44788,44789,44790,44791,44792,44793,44794,44795,44796,44797,
+44798,44799,44800,44801,44802,44803,44804,44805,44806,44807,44808,44809,
+44810,44811,44812,44813,44814,44815,44816,44817,44818,44819,44820,44821,
+44822,44823,44824,44825,44826,44827,44828,44829,44830,44831,44832,44833,
+44834,44835,44836,44837,44838,44839,44840,44841,44842,44843,44844,44845,
+44846,44847,44848,44849,44850,44851,44852,44853,44854,44855,44856,44857,
+44858,44859,44860,44861,44862,44863,44864,44865,44866,44867,44868,44869,
+44870,44871,44872,44873,44874,44875,44876,44877,44878,44879,44880,44881,
+44882,44883,44884,44885,44886,44887,44888,44889,44890,44891,44892,44893,
+44894,44895,44896,44897,44898,44899,44900,44901,44902,44903,44904,44905,
+44906,44907,44908,44909,44910,44911,44912,44913,44914,44915,44916,44917,
+44918,44919,44920,44921,44922,44923,44924,44925,44926,44927,44928,44929,
+44930,44931,44932,44933,44934,44935,44936,44937,44938,44939,44940,44941,
+44942,44943,44944,44945,44946,44947,44948,44949,44950,44951,44952,44953,
+44954,44955,44956,44957,44958,44959,44960,44961,44962,44963,44964,44965,
+44966,44967,44968,44969,44970,44971,44972,44973,44974,44975,44976,44977,
+44978,44979,44980,44981,44982,44983,44984,44985,44986,44987,44988,44989,
+44990,44991,44992,44993,44994,44995,44996,44997,44998,44999,45000,45001,
+45002,45003,45004,45005,45006,45007,45008,45009,45010,45011,45012,45013,
+45014,45015,45016,45017,45018,45019,45020,45021,45022,45023,45024,45025,
+45026,45027,45028,45029,45030,45031,45032,45033,45034,45035,45036,45037,
+45038,45039,45040,45041,45042,45043,45044,45045,45046,45047,45048,45049,
+45050,45051,45052,45053,45054,45055,45056,45057,45058,45059,45060,45061,
+45062,45063,45064,45065,45066,45067,45068,45069,45070,45071,45072,45073,
+45074,45075,45076,45077,45078,45079,45080,45081,45082,45083,45084,45085,
+45086,45087,45088,45089,45090,45091,45092,45093,45094,45095,45096,45097,
+45098,45099,45100,45101,45102,45103,45104,45105,45106,45107,45108,45109,
+45110,45111,45112,45113,45114,45115,45116,45117,45118,45119,45120,45121,
+45122,45123,45124,45125,45126,45127,45128,45129,45130,45131,45132,45133,
+45134,45135,45136,45137,45138,45139,45140,45141,45142,45143,45144,45145,
+45146,45147,45148,45149,45150,45151,45152,45153,45154,45155,45156,45157,
+45158,45159,45160,45161,45162,45163,45164,45165,45166,45167,45168,45169,
+45170,45171,45172,45173,45174,45175,45176,45177,45178,45179,45180,45181,
+45182,45183,45184,45185,45186,45187,45188,45189,45190,45191,45192,45193,
+45194,45195,45196,45197,45198,45199,45200,45201,45202,45203,45204,45205,
+45206,45207,45208,45209,45210,45211,45212,45213,45214,45215,45216,45217,
+45218,45219,45220,45221,45222,45223,45224,45225,45226,45227,45228,45229,
+45230,45231,45232,45233,45234,45235,45236,45237,45238,45239,45240,45241,
+45242,45243,45244,45245,45246,45247,45248,45249,45250,45251,45252,45253,
+45254,45255,45256,45257,45258,45259,45260,45261,45262,45263,45264,45265,
+45266,45267,45268,45269,45270,45271,45272,45273,45274,45275,45276,45277,
+45278,45279,45280,45281,45282,45283,45284,45285,45286,45287,45288,45289,
+45290,45291,45292,45293,45294,45295,45296,45297,45298,45299,45300,45301,
+45302,45303,45304,45305,45306,45307,45308,45309,45310,45311,45312,45313,
+45314,45315,45316,45317,45318,45319,45320,45321,45322,45323,45324,45325,
+45326,45327,45328,45329,45330,45331,45332,45333,45334,45335,45336,45337,
+45338,45339,45340,45341,45342,45343,45344,45345,45346,45347,45348,45349,
+45350,45351,45352,45353,45354,45355,45356,45357,45358,45359,45360,45361,
+45362,45363,45364,45365,45366,45367,45368,45369,45370,45371,45372,45373,
+45374,45375,45376,45377,45378,45379,45380,45381,45382,45383,45384,45385,
+45386,45387,45388,45389,45390,45391,45392,45393,45394,45395,45396,45397,
+45398,45399,45400,45401,45402,45403,45404,45405,45406,45407,45408,45409,
+45410,45411,45412,45413,45414,45415,45416,45417,45418,45419,45420,45421,
+45422,45423,45424,45425,45426,45427,45428,45429,45430,45431,45432,45433,
+45434,45435,45436,45437,45438,45439,45440,45441,45442,45443,45444,45445,
+45446,45447,45448,45449,45450,45451,45452,45453,45454,45455,45456,45457,
+45458,45459,45460,45461,45462,45463,45464,45465,45466,45467,45468,45469,
+45470,45471,45472,45473,45474,45475,45476,45477,45478,45479,45480,45481,
+45482,45483,45484,45485,45486,45487,45488,45489,45490,45491,45492,45493,
+45494,45495,45496,45497,45498,45499,45500,45501,45502,45503,45504,45505,
+45506,45507,45508,45509,45510,45511,45512,45513,45514,45515,45516,45517,
+45518,45519,45520,45521,45522,45523,45524,45525,45526,45527,45528,45529,
+45530,45531,45532,45533,45534,45535,45536,45537,45538,45539,45540,45541,
+45542,45543,45544,45545,45546,45547,45548,45549,45550,45551,45552,45553,
+45554,45555,45556,45557,45558,45559,45560,45561,45562,45563,45564,45565,
+45566,45567,45568,45569,45570,45571,45572,45573,45574,45575,45576,45577,
+45578,45579,45580,45581,45582,45583,45584,45585,45586,45587,45588,45589,
+45590,45591,45592,45593,45594,45595,45596,45597,45598,45599,45600,45601,
+45602,45603,45604,45605,45606,45607,45608,45609,45610,45611,45612,45613,
+45614,45615,45616,45617,45618,45619,45620,45621,45622,45623,45624,45625,
+45626,45627,45628,45629,45630,45631,45632,45633,45634,45635,45636,45637,
+45638,45639,45640,45641,45642,45643,45644,45645,45646,45647,45648,45649,
+45650,45651,45652,45653,45654,45655,45656,45657,45658,45659,45660,45661,
+45662,45663,45664,45665,45666,45667,45668,45669,45670,45671,45672,45673,
+45674,45675,45676,45677,45678,45679,45680,45681,45682,45683,45684,45685,
+45686,45687,45688,45689,45690,45691,45692,45693,45694,45695,45696,45697,
+45698,45699,45700,45701,45702,45703,45704,45705,45706,45707,45708,45709,
+45710,45711,45712,45713,45714,45715,45716,45717,45718,45719,45720,45721,
+45722,45723,45724,45725,45726,45727,45728,45729,45730,45731,45732,45733,
+45734,45735,45736,45737,45738,45739,45740,45741,45742,45743,45744,45745,
+45746,45747,45748,45749,45750,45751,45752,45753,45754,45755,45756,45757,
+45758,45759,45760,45761,45762,45763,45764,45765,45766,45767,45768,45769,
+45770,45771,45772,45773,45774,45775,45776,45777,45778,45779,45780,45781,
+45782,45783,45784,45785,45786,45787,45788,45789,45790,45791,45792,45793,
+45794,45795,45796,45797,45798,45799,45800,45801,45802,45803,45804,45805,
+45806,45807,45808,45809,45810,45811,45812,45813,45814,45815,45816,45817,
+45818,45819,45820,45821,45822,45823,45824,45825,45826,45827,45828,45829,
+45830,45831,45832,45833,45834,45835,45836,45837,45838,45839,45840,45841,
+45842,45843,45844,45845,45846,45847,45848,45849,45850,45851,45852,45853,
+45854,45855,45856,45857,45858,45859,45860,45861,45862,45863,45864,45865,
+45866,45867,45868,45869,45870,45871,45872,45873,45874,45875,45876,45877,
+45878,45879,45880,45881,45882,45883,45884,45885,45886,45887,45888,45889,
+45890,45891,45892,45893,45894,45895,45896,45897,45898,45899,45900,45901,
+45902,45903,45904,45905,45906,45907,45908,45909,45910,45911,45912,45913,
+45914,45915,45916,45917,45918,45919,45920,45921,45922,45923,45924,45925,
+45926,45927,45928,45929,45930,45931,45932,45933,45934,45935,45936,45937,
+45938,45939,45940,45941,45942,45943,45944,45945,45946,45947,45948,45949,
+45950,45951,45952,45953,45954,45955,45956,45957,45958,45959,45960,45961,
+45962,45963,45964,45965,45966,45967,45968,45969,45970,45971,45972,45973,
+45974,45975,45976,45977,45978,45979,45980,45981,45982,45983,45984,45985,
+45986,45987,45988,45989,45990,45991,45992,45993,45994,45995,45996,45997,
+45998,45999,46000,46001,46002,46003,46004,46005,46006,46007,46008,46009,
+46010,46011,46012,46013,46014,46015,46016,46017,46018,46019,46020,46021,
+46022,46023,46024,46025,46026,46027,46028,46029,46030,46031,46032,46033,
+46034,46035,46036,46037,46038,46039,46040,46041,46042,46043,46044,46045,
+46046,46047,46048,46049,46050,46051,46052,46053,46054,46055,46056,46057,
+46058,46059,46060,46061,46062,46063,46064,46065,46066,46067,46068,46069,
+46070,46071,46072,46073,46074,46075,46076,46077,46078,46079,46080,46081,
+46082,46083,46084,46085,46086,46087,46088,46089,46090,46091,46092,46093,
+46094,46095,46096,46097,46098,46099,46100,46101,46102,46103,46104,46105,
+46106,46107,46108,46109,46110,46111,46112,46113,46114,46115,46116,46117,
+46118,46119,46120,46121,46122,46123,46124,46125,46126,46127,46128,46129,
+46130,46131,46132,46133,46134,46135,46136,46137,46138,46139,46140,46141,
+46142,46143,46144,46145,46146,46147,46148,46149,46150,46151,46152,46153,
+46154,46155,46156,46157,46158,46159,46160,46161,46162,46163,46164,46165,
+46166,46167,46168,46169,46170,46171,46172,46173,46174,46175,46176,46177,
+46178,46179,46180,46181,46182,46183,46184,46185,46186,46187,46188,46189,
+46190,46191,46192,46193,46194,46195,46196,46197,46198,46199,46200,46201,
+46202,46203,46204,46205,46206,46207,46208,46209,46210,46211,46212,46213,
+46214,46215,46216,46217,46218,46219,46220,46221,46222,46223,46224,46225,
+46226,46227,46228,46229,46230,46231,46232,46233,46234,46235,46236,46237,
+46238,46239,46240,46241,46242,46243,46244,46245,46246,46247,46248,46249,
+46250,46251,46252,46253,46254,46255,46256,46257,46258,46259,46260,46261,
+46262,46263,46264,46265,46266,46267,46268,46269,46270,46271,46272,46273,
+46274,46275,46276,46277,46278,46279,46280,46281,46282,46283,46284,46285,
+46286,46287,46288,46289,46290,46291,46292,46293,46294,46295,46296,46297,
+46298,46299,46300,46301,46302,46303,46304,46305,46306,46307,46308,46309,
+46310,46311,46312,46313,46314,46315,46316,46317,46318,46319,46320,46321,
+46322,46323,46324,46325,46326,46327,46328,46329,46330,46331,46332,46333,
+46334,46335,46336,46337,46338,46339,46340,46341,46342,46343,46344,46345,
+46346,46347,46348,46349,46350,46351,46352,46353,46354,46355,46356,46357,
+46358,46359,46360,46361,46362,46363,46364,46365,46366,46367,46368,46369,
+46370,46371,46372,46373,46374,46375,46376,46377,46378,46379,46380,46381,
+46382,46383,46384,46385,46386,46387,46388,46389,46390,46391,46392,46393,
+46394,46395,46396,46397,46398,46399,46400,46401,46402,46403,46404,46405,
+46406,46407,46408,46409,46410,46411,46412,46413,46414,46415,46416,46417,
+46418,46419,46420,46421,46422,46423,46424,46425,46426,46427,46428,46429,
+46430,46431,46432,46433,46434,46435,46436,46437,46438,46439,46440,46441,
+46442,46443,46444,46445,46446,46447,46448,46449,46450,46451,46452,46453,
+46454,46455,46456,46457,46458,46459,46460,46461,46462,46463,46464,46465,
+46466,46467,46468,46469,46470,46471,46472,46473,46474,46475,46476,46477,
+46478,46479,46480,46481,46482,46483,46484,46485,46486,46487,46488,46489,
+46490,46491,46492,46493,46494,46495,46496,46497,46498,46499,46500,46501,
+46502,46503,46504,46505,46506,46507,46508,46509,46510,46511,46512,46513,
+46514,46515,46516,46517,46518,46519,46520,46521,46522,46523,46524,46525,
+46526,46527,46528,46529,46530,46531,46532,46533,46534,46535,46536,46537,
+46538,46539,46540,46541,46542,46543,46544,46545,46546,46547,46548,46549,
+46550,46551,46552,46553,46554,46555,46556,46557,46558,46559,46560,46561,
+46562,46563,46564,46565,46566,46567,46568,46569,46570,46571,46572,46573,
+46574,46575,46576,46577,46578,46579,46580,46581,46582,46583,46584,46585,
+46586,46587,46588,46589,46590,46591,46592,46593,46594,46595,46596,46597,
+46598,46599,46600,46601,46602,46603,46604,46605,46606,46607,46608,46609,
+46610,46611,46612,46613,46614,46615,46616,46617,46618,46619,46620,46621,
+46622,46623,46624,46625,46626,46627,46628,46629,46630,46631,46632,46633,
+46634,46635,46636,46637,46638,46639,46640,46641,46642,46643,46644,46645,
+46646,46647,46648,46649,46650,46651,46652,46653,46654,46655,46656,46657,
+46658,46659,46660,46661,46662,46663,46664,46665,46666,46667,46668,46669,
+46670,46671,46672,46673,46674,46675,46676,46677,46678,46679,46680,46681,
+46682,46683,46684,46685,46686,46687,46688,46689,46690,46691,46692,46693,
+46694,46695,46696,46697,46698,46699,46700,46701,46702,46703,46704,46705,
+46706,46707,46708,46709,46710,46711,46712,46713,46714,46715,46716,46717,
+46718,46719,46720,46721,46722,46723,46724,46725,46726,46727,46728,46729,
+46730,46731,46732,46733,46734,46735,46736,46737,46738,46739,46740,46741,
+46742,46743,46744,46745,46746,46747,46748,46749,46750,46751,46752,46753,
+46754,46755,46756,46757,46758,46759,46760,46761,46762,46763,46764,46765,
+46766,46767,46768,46769,46770,46771,46772,46773,46774,46775,46776,46777,
+46778,46779,46780,46781,46782,46783,46784,46785,46786,46787,46788,46789,
+46790,46791,46792,46793,46794,46795,46796,46797,46798,46799,46800,46801,
+46802,46803,46804,46805,46806,46807,46808,46809,46810,46811,46812,46813,
+46814,46815,46816,46817,46818,46819,46820,46821,46822,46823,46824,46825,
+46826,46827,46828,46829,46830,46831,46832,46833,46834,46835,46836,46837,
+46838,46839,46840,46841,46842,46843,46844,46845,46846,46847,46848,46849,
+46850,46851,46852,46853,46854,46855,46856,46857,46858,46859,46860,46861,
+46862,46863,46864,46865,46866,46867,46868,46869,46870,46871,46872,46873,
+46874,46875,46876,46877,46878,46879,46880,46881,46882,46883,46884,46885,
+46886,46887,46888,46889,46890,46891,46892,46893,46894,46895,46896,46897,
+46898,46899,46900,46901,46902,46903,46904,46905,46906,46907,46908,46909,
+46910,46911,46912,46913,46914,46915,46916,46917,46918,46919,46920,46921,
+46922,46923,46924,46925,46926,46927,46928,46929,46930,46931,46932,46933,
+46934,46935,46936,46937,46938,46939,46940,46941,46942,46943,46944,46945,
+46946,46947,46948,46949,46950,46951,46952,46953,46954,46955,46956,46957,
+46958,46959,46960,46961,46962,46963,46964,46965,46966,46967,46968,46969,
+46970,46971,46972,46973,46974,46975,46976,46977,46978,46979,46980,46981,
+46982,46983,46984,46985,46986,46987,46988,46989,46990,46991,46992,46993,
+46994,46995,46996,46997,46998,46999,47000,47001,47002,47003,47004,47005,
+47006,47007,47008,47009,47010,47011,47012,47013,47014,47015,47016,47017,
+47018,47019,47020,47021,47022,47023,47024,47025,47026,47027,47028,47029,
+47030,47031,47032,47033,47034,47035,47036,47037,47038,47039,47040,47041,
+47042,47043,47044,47045,47046,47047,47048,47049,47050,47051,47052,47053,
+47054,47055,47056,47057,47058,47059,47060,47061,47062,47063,47064,47065,
+47066,47067,47068,47069,47070,47071,47072,47073,47074,47075,47076,47077,
+47078,47079,47080,47081,47082,47083,47084,47085,47086,47087,47088,47089,
+47090,47091,47092,47093,47094,47095,47096,47097,47098,47099,47100,47101,
+47102,47103,47104,47105,47106,47107,47108,47109,47110,47111,47112,47113,
+47114,47115,47116,47117,47118,47119,47120,47121,47122,47123,47124,47125,
+47126,47127,47128,47129,47130,47131,47132,47133,47134,47135,47136,47137,
+47138,47139,47140,47141,47142,47143,47144,47145,47146,47147,47148,47149,
+47150,47151,47152,47153,47154,47155,47156,47157,47158,47159,47160,47161,
+47162,47163,47164,47165,47166,47167,47168,47169,47170,47171,47172,47173,
+47174,47175,47176,47177,47178,47179,47180,47181,47182,47183,47184,47185,
+47186,47187,47188,47189,47190,47191,47192,47193,47194,47195,47196,47197,
+47198,47199,47200,47201,47202,47203,47204,47205,47206,47207,47208,47209,
+47210,47211,47212,47213,47214,47215,47216,47217,47218,47219,47220,47221,
+47222,47223,47224,47225,47226,47227,47228,47229,47230,47231,47232,47233,
+47234,47235,47236,47237,47238,47239,47240,47241,47242,47243,47244,47245,
+47246,47247,47248,47249,47250,47251,47252,47253,47254,47255,47256,47257,
+47258,47259,47260,47261,47262,47263,47264,47265,47266,47267,47268,47269,
+47270,47271,47272,47273,47274,47275,47276,47277,47278,47279,47280,47281,
+47282,47283,47284,47285,47286,47287,47288,47289,47290,47291,47292,47293,
+47294,47295,47296,47297,47298,47299,47300,47301,47302,47303,47304,47305,
+47306,47307,47308,47309,47310,47311,47312,47313,47314,47315,47316,47317,
+47318,47319,47320,47321,47322,47323,47324,47325,47326,47327,47328,47329,
+47330,47331,47332,47333,47334,47335,47336,47337,47338,47339,47340,47341,
+47342,47343,47344,47345,47346,47347,47348,47349,47350,47351,47352,47353,
+47354,47355,47356,47357,47358,47359,47360,47361,47362,47363,47364,47365,
+47366,47367,47368,47369,47370,47371,47372,47373,47374,47375,47376,47377,
+47378,47379,47380,47381,47382,47383,47384,47385,47386,47387,47388,47389,
+47390,47391,47392,47393,47394,47395,47396,47397,47398,47399,47400,47401,
+47402,47403,47404,47405,47406,47407,47408,47409,47410,47411,47412,47413,
+47414,47415,47416,47417,47418,47419,47420,47421,47422,47423,47424,47425,
+47426,47427,47428,47429,47430,47431,47432,47433,47434,47435,47436,47437,
+47438,47439,47440,47441,47442,47443,47444,47445,47446,47447,47448,47449,
+47450,47451,47452,47453,47454,47455,47456,47457,47458,47459,47460,47461,
+47462,47463,47464,47465,47466,47467,47468,47469,47470,47471,47472,47473,
+47474,47475,47476,47477,47478,47479,47480,47481,47482,47483,47484,47485,
+47486,47487,47488,47489,47490,47491,47492,47493,47494,47495,47496,47497,
+47498,47499,47500,47501,47502,47503,47504,47505,47506,47507,47508,47509,
+47510,47511,47512,47513,47514,47515,47516,47517,47518,47519,47520,47521,
+47522,47523,47524,47525,47526,47527,47528,47529,47530,47531,47532,47533,
+47534,47535,47536,47537,47538,47539,47540,47541,47542,47543,47544,47545,
+47546,47547,47548,47549,47550,47551,47552,47553,47554,47555,47556,47557,
+47558,47559,47560,47561,47562,47563,47564,47565,47566,47567,47568,47569,
+47570,47571,47572,47573,47574,47575,47576,47577,47578,47579,47580,47581,
+47582,47583,47584,47585,47586,47587,47588,47589,47590,47591,47592,47593,
+47594,47595,47596,47597,47598,47599,47600,47601,47602,47603,47604,47605,
+47606,47607,47608,47609,47610,47611,47612,47613,47614,47615,47616,47617,
+47618,47619,47620,47621,47622,47623,47624,47625,47626,47627,47628,47629,
+47630,47631,47632,47633,47634,47635,47636,47637,47638,47639,47640,47641,
+47642,47643,47644,47645,47646,47647,47648,47649,47650,47651,47652,47653,
+47654,47655,47656,47657,47658,47659,47660,47661,47662,47663,47664,47665,
+47666,47667,47668,47669,47670,47671,47672,47673,47674,47675,47676,47677,
+47678,47679,47680,47681,47682,47683,47684,47685,47686,47687,47688,47689,
+47690,47691,47692,47693,47694,47695,47696,47697,47698,47699,47700,47701,
+47702,47703,47704,47705,47706,47707,47708,47709,47710,47711,47712,47713,
+47714,47715,47716,47717,47718,47719,47720,47721,47722,47723,47724,47725,
+47726,47727,47728,47729,47730,47731,47732,47733,47734,47735,47736,47737,
+47738,47739,47740,47741,47742,47743,47744,47745,47746,47747,47748,47749,
+47750,47751,47752,47753,47754,47755,47756,47757,47758,47759,47760,47761,
+47762,47763,47764,47765,47766,47767,47768,47769,47770,47771,47772,47773,
+47774,47775,47776,47777,47778,47779,47780,47781,47782,47783,47784,47785,
+47786,47787,47788,47789,47790,47791,47792,47793,47794,47795,47796,47797,
+47798,47799,47800,47801,47802,47803,47804,47805,47806,47807,47808,47809,
+47810,47811,47812,47813,47814,47815,47816,47817,47818,47819,47820,47821,
+47822,47823,47824,47825,47826,47827,47828,47829,47830,47831,47832,47833,
+47834,47835,47836,47837,47838,47839,47840,47841,47842,47843,47844,47845,
+47846,47847,47848,47849,47850,47851,47852,47853,47854,47855,47856,47857,
+47858,47859,47860,47861,47862,47863,47864,47865,47866,47867,47868,47869,
+47870,47871,47872,47873,47874,47875,47876,47877,47878,47879,47880,47881,
+47882,47883,47884,47885,47886,47887,47888,47889,47890,47891,47892,47893,
+47894,47895,47896,47897,47898,47899,47900,47901,47902,47903,47904,47905,
+47906,47907,47908,47909,47910,47911,47912,47913,47914,47915,47916,47917,
+47918,47919,47920,47921,47922,47923,47924,47925,47926,47927,47928,47929,
+47930,47931,47932,47933,47934,47935,47936,47937,47938,47939,47940,47941,
+47942,47943,47944,47945,47946,47947,47948,47949,47950,47951,47952,47953,
+47954,47955,47956,47957,47958,47959,47960,47961,47962,47963,47964,47965,
+47966,47967,47968,47969,47970,47971,47972,47973,47974,47975,47976,47977,
+47978,47979,47980,47981,47982,47983,47984,47985,47986,47987,47988,47989,
+47990,47991,47992,47993,47994,47995,47996,47997,47998,47999,48000,48001,
+48002,48003,48004,48005,48006,48007,48008,48009,48010,48011,48012,48013,
+48014,48015,48016,48017,48018,48019,48020,48021,48022,48023,48024,48025,
+48026,48027,48028,48029,48030,48031,48032,48033,48034,48035,48036,48037,
+48038,48039,48040,48041,48042,48043,48044,48045,48046,48047,48048,48049,
+48050,48051,48052,48053,48054,48055,48056,48057,48058,48059,48060,48061,
+48062,48063,48064,48065,48066,48067,48068,48069,48070,48071,48072,48073,
+48074,48075,48076,48077,48078,48079,48080,48081,48082,48083,48084,48085,
+48086,48087,48088,48089,48090,48091,48092,48093,48094,48095,48096,48097,
+48098,48099,48100,48101,48102,48103,48104,48105,48106,48107,48108,48109,
+48110,48111,48112,48113,48114,48115,48116,48117,48118,48119,48120,48121,
+48122,48123,48124,48125,48126,48127,48128,48129,48130,48131,48132,48133,
+48134,48135,48136,48137,48138,48139,48140,48141,48142,48143,48144,48145,
+48146,48147,48148,48149,48150,48151,48152,48153,48154,48155,48156,48157,
+48158,48159,48160,48161,48162,48163,48164,48165,48166,48167,48168,48169,
+48170,48171,48172,48173,48174,48175,48176,48177,48178,48179,48180,48181,
+48182,48183,48184,48185,48186,48187,48188,48189,48190,48191,48192,48193,
+48194,48195,48196,48197,48198,48199,48200,48201,48202,48203,48204,48205,
+48206,48207,48208,48209,48210,48211,48212,48213,48214,48215,48216,48217,
+48218,48219,48220,48221,48222,48223,48224,48225,48226,48227,48228,48229,
+48230,48231,48232,48233,48234,48235,48236,48237,48238,48239,48240,48241,
+48242,48243,48244,48245,48246,48247,48248,48249,48250,48251,48252,48253,
+48254,48255,48256,48257,48258,48259,48260,48261,48262,48263,48264,48265,
+48266,48267,48268,48269,48270,48271,48272,48273,48274,48275,48276,48277,
+48278,48279,48280,48281,48282,48283,48284,48285,48286,48287,48288,48289,
+48290,48291,48292,48293,48294,48295,48296,48297,48298,48299,48300,48301,
+48302,48303,48304,48305,48306,48307,48308,48309,48310,48311,48312,48313,
+48314,48315,48316,48317,48318,48319,48320,48321,48322,48323,48324,48325,
+48326,48327,48328,48329,48330,48331,48332,48333,48334,48335,48336,48337,
+48338,48339,48340,48341,48342,48343,48344,48345,48346,48347,48348,48349,
+48350,48351,48352,48353,48354,48355,48356,48357,48358,48359,48360,48361,
+48362,48363,48364,48365,48366,48367,48368,48369,48370,48371,48372,48373,
+48374,48375,48376,48377,48378,48379,48380,48381,48382,48383,48384,48385,
+48386,48387,48388,48389,48390,48391,48392,48393,48394,48395,48396,48397,
+48398,48399,48400,48401,48402,48403,48404,48405,48406,48407,48408,48409,
+48410,48411,48412,48413,48414,48415,48416,48417,48418,48419,48420,48421,
+48422,48423,48424,48425,48426,48427,48428,48429,48430,48431,48432,48433,
+48434,48435,48436,48437,48438,48439,48440,48441,48442,48443,48444,48445,
+48446,48447,48448,48449,48450,48451,48452,48453,48454,48455,48456,48457,
+48458,48459,48460,48461,48462,48463,48464,48465,48466,48467,48468,48469,
+48470,48471,48472,48473,48474,48475,48476,48477,48478,48479,48480,48481,
+48482,48483,48484,48485,48486,48487,48488,48489,48490,48491,48492,48493,
+48494,48495,48496,48497,48498,48499,48500,48501,48502,48503,48504,48505,
+48506,48507,48508,48509,48510,48511,48512,48513,48514,48515,48516,48517,
+48518,48519,48520,48521,48522,48523,48524,48525,48526,48527,48528,48529,
+48530,48531,48532,48533,48534,48535,48536,48537,48538,48539,48540,48541,
+48542,48543,48544,48545,48546,48547,48548,48549,48550,48551,48552,48553,
+48554,48555,48556,48557,48558,48559,48560,48561,48562,48563,48564,48565,
+48566,48567,48568,48569,48570,48571,48572,48573,48574,48575,48576,48577,
+48578,48579,48580,48581,48582,48583,48584,48585,48586,48587,48588,48589,
+48590,48591,48592,48593,48594,48595,48596,48597,48598,48599,48600,48601,
+48602,48603,48604,48605,48606,48607,48608,48609,48610,48611,48612,48613,
+48614,48615,48616,48617,48618,48619,48620,48621,48622,48623,48624,48625,
+48626,48627,48628,48629,48630,48631,48632,48633,48634,48635,48636,48637,
+48638,48639,48640,48641,48642,48643,48644,48645,48646,48647,48648,48649,
+48650,48651,48652,48653,48654,48655,48656,48657,48658,48659,48660,48661,
+48662,48663,48664,48665,48666,48667,48668,48669,48670,48671,48672,48673,
+48674,48675,48676,48677,48678,48679,48680,48681,48682,48683,48684,48685,
+48686,48687,48688,48689,48690,48691,48692,48693,48694,48695,48696,48697,
+48698,48699,48700,48701,48702,48703,48704,48705,48706,48707,48708,48709,
+48710,48711,48712,48713,48714,48715,48716,48717,48718,48719,48720,48721,
+48722,48723,48724,48725,48726,48727,48728,48729,48730,48731,48732,48733,
+48734,48735,48736,48737,48738,48739,48740,48741,48742,48743,48744,48745,
+48746,48747,48748,48749,48750,48751,48752,48753,48754,48755,48756,48757,
+48758,48759,48760,48761,48762,48763,48764,48765,48766,48767,48768,48769,
+48770,48771,48772,48773,48774,48775,48776,48777,48778,48779,48780,48781,
+48782,48783,48784,48785,48786,48787,48788,48789,48790,48791,48792,48793,
+48794,48795,48796,48797,48798,48799,48800,48801,48802,48803,48804,48805,
+48806,48807,48808,48809,48810,48811,48812,48813,48814,48815,48816,48817,
+48818,48819,48820,48821,48822,48823,48824,48825,48826,48827,48828,48829,
+48830,48831,48832,48833,48834,48835,48836,48837,48838,48839,48840,48841,
+48842,48843,48844,48845,48846,48847,48848,48849,48850,48851,48852,48853,
+48854,48855,48856,48857,48858,48859,48860,48861,48862,48863,48864,48865,
+48866,48867,48868,48869,48870,48871,48872,48873,48874,48875,48876,48877,
+48878,48879,48880,48881,48882,48883,48884,48885,48886,48887,48888,48889,
+48890,48891,48892,48893,48894,48895,48896,48897,48898,48899,48900,48901,
+48902,48903,48904,48905,48906,48907,48908,48909,48910,48911,48912,48913,
+48914,48915,48916,48917,48918,48919,48920,48921,48922,48923,48924,48925,
+48926,48927,48928,48929,48930,48931,48932,48933,48934,48935,48936,48937,
+48938,48939,48940,48941,48942,48943,48944,48945,48946,48947,48948,48949,
+48950,48951,48952,48953,48954,48955,48956,48957,48958,48959,48960,48961,
+48962,48963,48964,48965,48966,48967,48968,48969,48970,48971,48972,48973,
+48974,48975,48976,48977,48978,48979,48980,48981,48982,48983,48984,48985,
+48986,48987,48988,48989,48990,48991,48992,48993,48994,48995,48996,48997,
+48998,48999,49000,49001,49002,49003,49004,49005,49006,49007,49008,49009,
+49010,49011,49012,49013,49014,49015,49016,49017,49018,49019,49020,49021,
+49022,49023,49024,49025,49026,49027,49028,49029,49030,49031,49032,49033,
+49034,49035,49036,49037,49038,49039,49040,49041,49042,49043,49044,49045,
+49046,49047,49048,49049,49050,49051,49052,49053,49054,49055,49056,49057,
+49058,49059,49060,49061,49062,49063,49064,49065,49066,49067,49068,49069,
+49070,49071,49072,49073,49074,49075,49076,49077,49078,49079,49080,49081,
+49082,49083,49084,49085,49086,49087,49088,49089,49090,49091,49092,49093,
+49094,49095,49096,49097,49098,49099,49100,49101,49102,49103,49104,49105,
+49106,49107,49108,49109,49110,49111,49112,49113,49114,49115,49116,49117,
+49118,49119,49120,49121,49122,49123,49124,49125,49126,49127,49128,49129,
+49130,49131,49132,49133,49134,49135,49136,49137,49138,49139,49140,49141,
+49142,49143,49144,49145,49146,49147,49148,49149,49150,49151,49152,49153,
+49154,49155,49156,49157,49158,49159,49160,49161,49162,49163,49164,49165,
+49166,49167,49168,49169,49170,49171,49172,49173,49174,49175,49176,49177,
+49178,49179,49180,49181,49182,49183,49184,49185,49186,49187,49188,49189,
+49190,49191,49192,49193,49194,49195,49196,49197,49198,49199,49200,49201,
+49202,49203,49204,49205,49206,49207,49208,49209,49210,49211,49212,49213,
+49214,49215,49216,49217,49218,49219,49220,49221,49222,49223,49224,49225,
+49226,49227,49228,49229,49230,49231,49232,49233,49234,49235,49236,49237,
+49238,49239,49240,49241,49242,49243,49244,49245,49246,49247,49248,49249,
+49250,49251,49252,49253,49254,49255,49256,49257,49258,49259,49260,49261,
+49262,49263,49264,49265,49266,49267,49268,49269,49270,49271,49272,49273,
+49274,49275,49276,49277,49278,49279,49280,49281,49282,49283,49284,49285,
+49286,49287,49288,49289,49290,49291,49292,49293,49294,49295,49296,49297,
+49298,49299,49300,49301,49302,49303,49304,49305,49306,49307,49308,49309,
+49310,49311,49312,49313,49314,49315,49316,49317,49318,49319,49320,49321,
+49322,49323,49324,49325,49326,49327,49328,49329,49330,49331,49332,49333,
+49334,49335,49336,49337,49338,49339,49340,49341,49342,49343,49344,49345,
+49346,49347,49348,49349,49350,49351,49352,49353,49354,49355,49356,49357,
+49358,49359,49360,49361,49362,49363,49364,49365,49366,49367,49368,49369,
+49370,49371,49372,49373,49374,49375,49376,49377,49378,49379,49380,49381,
+49382,49383,49384,49385,49386,49387,49388,49389,49390,49391,49392,49393,
+49394,49395,49396,49397,49398,49399,49400,49401,49402,49403,49404,49405,
+49406,49407,49408,49409,49410,49411,49412,49413,49414,49415,49416,49417,
+49418,49419,49420,49421,49422,49423,49424,49425,49426,49427,49428,49429,
+49430,49431,49432,49433,49434,49435,49436,49437,49438,49439,49440,49441,
+49442,49443,49444,49445,49446,49447,49448,49449,49450,49451,49452,49453,
+49454,49455,49456,49457,49458,49459,49460,49461,49462,49463,49464,49465,
+49466,49467,49468,49469,49470,49471,49472,49473,49474,49475,49476,49477,
+49478,49479,49480,49481,49482,49483,49484,49485,49486,49487,49488,49489,
+49490,49491,49492,49493,49494,49495,49496,49497,49498,49499,49500,49501,
+49502,49503,49504,49505,49506,49507,49508,49509,49510,49511,49512,49513,
+49514,49515,49516,49517,49518,49519,49520,49521,49522,49523,49524,49525,
+49526,49527,49528,49529,49530,49531,49532,49533,49534,49535,49536,49537,
+49538,49539,49540,49541,49542,49543,49544,49545,49546,49547,49548,49549,
+49550,49551,49552,49553,49554,49555,49556,49557,49558,49559,49560,49561,
+49562,49563,49564,49565,49566,49567,49568,49569,49570,49571,49572,49573,
+49574,49575,49576,49577,49578,49579,49580,49581,49582,49583,49584,49585,
+49586,49587,49588,49589,49590,49591,49592,49593,49594,49595,49596,49597,
+49598,49599,49600,49601,49602,49603,49604,49605,49606,49607,49608,49609,
+49610,49611,49612,49613,49614,49615,49616,49617,49618,49619,49620,49621,
+49622,49623,49624,49625,49626,49627,49628,49629,49630,49631,49632,49633,
+49634,49635,49636,49637,49638,49639,49640,49641,49642,49643,49644,49645,
+49646,49647,49648,49649,49650,49651,49652,49653,49654,49655,49656,49657,
+49658,49659,49660,49661,49662,49663,49664,49665,49666,49667,49668,49669,
+49670,49671,49672,49673,49674,49675,49676,49677,49678,49679,49680,49681,
+49682,49683,49684,49685,49686,49687,49688,49689,49690,49691,49692,49693,
+49694,49695,49696,49697,49698,49699,49700,49701,49702,49703,49704,49705,
+49706,49707,49708,49709,49710,49711,49712,49713,49714,49715,49716,49717,
+49718,49719,49720,49721,49722,49723,49724,49725,49726,49727,49728,49729,
+49730,49731,49732,49733,49734,49735,49736,49737,49738,49739,49740,49741,
+49742,49743,49744,49745,49746,49747,49748,49749,49750,49751,49752,49753,
+49754,49755,49756,49757,49758,49759,49760,49761,49762,49763,49764,49765,
+49766,49767,49768,49769,49770,49771,49772,49773,49774,49775,49776,49777,
+49778,49779,49780,49781,49782,49783,49784,49785,49786,49787,49788,49789,
+49790,49791,49792,49793,49794,49795,49796,49797,49798,49799,49800,49801,
+49802,49803,49804,49805,49806,49807,49808,49809,49810,49811,49812,49813,
+49814,49815,49816,49817,49818,49819,49820,49821,49822,49823,49824,49825,
+49826,49827,49828,49829,49830,49831,49832,49833,49834,49835,49836,49837,
+49838,49839,49840,49841,49842,49843,49844,49845,49846,49847,49848,49849,
+49850,49851,49852,49853,49854,49855,49856,49857,49858,49859,49860,49861,
+49862,49863,49864,49865,49866,49867,49868,49869,49870,49871,49872,49873,
+49874,49875,49876,49877,49878,49879,49880,49881,49882,49883,49884,49885,
+49886,49887,49888,49889,49890,49891,49892,49893,49894,49895,49896,49897,
+49898,49899,49900,49901,49902,49903,49904,49905,49906,49907,49908,49909,
+49910,49911,49912,49913,49914,49915,49916,49917,49918,49919,49920,49921,
+49922,49923,49924,49925,49926,49927,49928,49929,49930,49931,49932,49933,
+49934,49935,49936,49937,49938,49939,49940,49941,49942,49943,49944,49945,
+49946,49947,49948,49949,49950,49951,49952,49953,49954,49955,49956,49957,
+49958,49959,49960,49961,49962,49963,49964,49965,49966,49967,49968,49969,
+49970,49971,49972,49973,49974,49975,49976,49977,49978,49979,49980,49981,
+49982,49983,49984,49985,49986,49987,49988,49989,49990,49991,49992,49993,
+49994,49995,49996,49997,49998,49999,50000,50001,50002,50003,50004,50005,
+50006,50007,50008,50009,50010,50011,50012,50013,50014,50015,50016,50017,
+50018,50019,50020,50021,50022,50023,50024,50025,50026,50027,50028,50029,
+50030,50031,50032,50033,50034,50035,50036,50037,50038,50039,50040,50041,
+50042,50043,50044,50045,50046,50047,50048,50049,50050,50051,50052,50053,
+50054,50055,50056,50057,50058,50059,50060,50061,50062,50063,50064,50065,
+50066,50067,50068,50069,50070,50071,50072,50073,50074,50075,50076,50077,
+50078,50079,50080,50081,50082,50083,50084,50085,50086,50087,50088,50089,
+50090,50091,50092,50093,50094,50095,50096,50097,50098,50099,50100,50101,
+50102,50103,50104,50105,50106,50107,50108,50109,50110,50111,50112,50113,
+50114,50115,50116,50117,50118,50119,50120,50121,50122,50123,50124,50125,
+50126,50127,50128,50129,50130,50131,50132,50133,50134,50135,50136,50137,
+50138,50139,50140,50141,50142,50143,50144,50145,50146,50147,50148,50149,
+50150,50151,50152,50153,50154,50155,50156,50157,50158,50159,50160,50161,
+50162,50163,50164,50165,50166,50167,50168,50169,50170,50171,50172,50173,
+50174,50175,50176,50177,50178,50179,50180,50181,50182,50183,50184,50185,
+50186,50187,50188,50189,50190,50191,50192,50193,50194,50195,50196,50197,
+50198,50199,50200,50201,50202,50203,50204,50205,50206,50207,50208,50209,
+50210,50211,50212,50213,50214,50215,50216,50217,50218,50219,50220,50221,
+50222,50223,50224,50225,50226,50227,50228,50229,50230,50231,50232,50233,
+50234,50235,50236,50237,50238,50239,50240,50241,50242,50243,50244,50245,
+50246,50247,50248,50249,50250,50251,50252,50253,50254,50255,50256,50257,
+50258,50259,50260,50261,50262,50263,50264,50265,50266,50267,50268,50269,
+50270,50271,50272,50273,50274,50275,50276,50277,50278,50279,50280,50281,
+50282,50283,50284,50285,50286,50287,50288,50289,50290,50291,50292,50293,
+50294,50295,50296,50297,50298,50299,50300,50301,50302,50303,50304,50305,
+50306,50307,50308,50309,50310,50311,50312,50313,50314,50315,50316,50317,
+50318,50319,50320,50321,50322,50323,50324,50325,50326,50327,50328,50329,
+50330,50331,50332,50333,50334,50335,50336,50337,50338,50339,50340,50341,
+50342,50343,50344,50345,50346,50347,50348,50349,50350,50351,50352,50353,
+50354,50355,50356,50357,50358,50359,50360,50361,50362,50363,50364,50365,
+50366,50367,50368,50369,50370,50371,50372,50373,50374,50375,50376,50377,
+50378,50379,50380,50381,50382,50383,50384,50385,50386,50387,50388,50389,
+50390,50391,50392,50393,50394,50395,50396,50397,50398,50399,50400,50401,
+50402,50403,50404,50405,50406,50407,50408,50409,50410,50411,50412,50413,
+50414,50415,50416,50417,50418,50419,50420,50421,50422,50423,50424,50425,
+50426,50427,50428,50429,50430,50431,50432,50433,50434,50435,50436,50437,
+50438,50439,50440,50441,50442,50443,50444,50445,50446,50447,50448,50449,
+50450,50451,50452,50453,50454,50455,50456,50457,50458,50459,50460,50461,
+50462,50463,50464,50465,50466,50467,50468,50469,50470,50471,50472,50473,
+50474,50475,50476,50477,50478,50479,50480,50481,50482,50483,50484,50485,
+50486,50487,50488,50489,50490,50491,50492,50493,50494,50495,50496,50497,
+50498,50499,50500,50501,50502,50503,50504,50505,50506,50507,50508,50509,
+50510,50511,50512,50513,50514,50515,50516,50517,50518,50519,50520,50521,
+50522,50523,50524,50525,50526,50527,50528,50529,50530,50531,50532,50533,
+50534,50535,50536,50537,50538,50539,50540,50541,50542,50543,50544,50545,
+50546,50547,50548,50549,50550,50551,50552,50553,50554,50555,50556,50557,
+50558,50559,50560,50561,50562,50563,50564,50565,50566,50567,50568,50569,
+50570,50571,50572,50573,50574,50575,50576,50577,50578,50579,50580,50581,
+50582,50583,50584,50585,50586,50587,50588,50589,50590,50591,50592,50593,
+50594,50595,50596,50597,50598,50599,50600,50601,50602,50603,50604,50605,
+50606,50607,50608,50609,50610,50611,50612,50613,50614,50615,50616,50617,
+50618,50619,50620,50621,50622,50623,50624,50625,50626,50627,50628,50629,
+50630,50631,50632,50633,50634,50635,50636,50637,50638,50639,50640,50641,
+50642,50643,50644,50645,50646,50647,50648,50649,50650,50651,50652,50653,
+50654,50655,50656,50657,50658,50659,50660,50661,50662,50663,50664,50665,
+50666,50667,50668,50669,50670,50671,50672,50673,50674,50675,50676,50677,
+50678,50679,50680,50681,50682,50683,50684,50685,50686,50687,50688,50689,
+50690,50691,50692,50693,50694,50695,50696,50697,50698,50699,50700,50701,
+50702,50703,50704,50705,50706,50707,50708,50709,50710,50711,50712,50713,
+50714,50715,50716,50717,50718,50719,50720,50721,50722,50723,50724,50725,
+50726,50727,50728,50729,50730,50731,50732,50733,50734,50735,50736,50737,
+50738,50739,50740,50741,50742,50743,50744,50745,50746,50747,50748,50749,
+50750,50751,50752,50753,50754,50755,50756,50757,50758,50759,50760,50761,
+50762,50763,50764,50765,50766,50767,50768,50769,50770,50771,50772,50773,
+50774,50775,50776,50777,50778,50779,50780,50781,50782,50783,50784,50785,
+50786,50787,50788,50789,50790,50791,50792,50793,50794,50795,50796,50797,
+50798,50799,50800,50801,50802,50803,50804,50805,50806,50807,50808,50809,
+50810,50811,50812,50813,50814,50815,50816,50817,50818,50819,50820,50821,
+50822,50823,50824,50825,50826,50827,50828,50829,50830,50831,50832,50833,
+50834,50835,50836,50837,50838,50839,50840,50841,50842,50843,50844,50845,
+50846,50847,50848,50849,50850,50851,50852,50853,50854,50855,50856,50857,
+50858,50859,50860,50861,50862,50863,50864,50865,50866,50867,50868,50869,
+50870,50871,50872,50873,50874,50875,50876,50877,50878,50879,50880,50881,
+50882,50883,50884,50885,50886,50887,50888,50889,50890,50891,50892,50893,
+50894,50895,50896,50897,50898,50899,50900,50901,50902,50903,50904,50905,
+50906,50907,50908,50909,50910,50911,50912,50913,50914,50915,50916,50917,
+50918,50919,50920,50921,50922,50923,50924,50925,50926,50927,50928,50929,
+50930,50931,50932,50933,50934,50935,50936,50937,50938,50939,50940,50941,
+50942,50943,50944,50945,50946,50947,50948,50949,50950,50951,50952,50953,
+50954,50955,50956,50957,50958,50959,50960,50961,50962,50963,50964,50965,
+50966,50967,50968,50969,50970,50971,50972,50973,50974,50975,50976,50977,
+50978,50979,50980,50981,50982,50983,50984,50985,50986,50987,50988,50989,
+50990,50991,50992,50993,50994,50995,50996,50997,50998,50999,51000,51001,
+51002,51003,51004,51005,51006,51007,51008,51009,51010,51011,51012,51013,
+51014,51015,51016,51017,51018,51019,51020,51021,51022,51023,51024,51025,
+51026,51027,51028,51029,51030,51031,51032,51033,51034,51035,51036,51037,
+51038,51039,51040,51041,51042,51043,51044,51045,51046,51047,51048,51049,
+51050,51051,51052,51053,51054,51055,51056,51057,51058,51059,51060,51061,
+51062,51063,51064,51065,51066,51067,51068,51069,51070,51071,51072,51073,
+51074,51075,51076,51077,51078,51079,51080,51081,51082,51083,51084,51085,
+51086,51087,51088,51089,51090,51091,51092,51093,51094,51095,51096,51097,
+51098,51099,51100,51101,51102,51103,51104,51105,51106,51107,51108,51109,
+51110,51111,51112,51113,51114,51115,51116,51117,51118,51119,51120,51121,
+51122,51123,51124,51125,51126,51127,51128,51129,51130,51131,51132,51133,
+51134,51135,51136,51137,51138,51139,51140,51141,51142,51143,51144,51145,
+51146,51147,51148,51149,51150,51151,51152,51153,51154,51155,51156,51157,
+51158,51159,51160,51161,51162,51163,51164,51165,51166,51167,51168,51169,
+51170,51171,51172,51173,51174,51175,51176,51177,51178,51179,51180,51181,
+51182,51183,51184,51185,51186,51187,51188,51189,51190,51191,51192,51193,
+51194,51195,51196,51197,51198,51199,51200,51201,51202,51203,51204,51205,
+51206,51207,51208,51209,51210,51211,51212,51213,51214,51215,51216,51217,
+51218,51219,51220,51221,51222,51223,51224,51225,51226,51227,51228,51229,
+51230,51231,51232,51233,51234,51235,51236,51237,51238,51239,51240,51241,
+51242,51243,51244,51245,51246,51247,51248,51249,51250,51251,51252,51253,
+51254,51255,51256,51257,51258,51259,51260,51261,51262,51263,51264,51265,
+51266,51267,51268,51269,51270,51271,51272,51273,51274,51275,51276,51277,
+51278,51279,51280,51281,51282,51283,51284,51285,51286,51287,51288,51289,
+51290,51291,51292,51293,51294,51295,51296,51297,51298,51299,51300,51301,
+51302,51303,51304,51305,51306,51307,51308,51309,51310,51311,51312,51313,
+51314,51315,51316,51317,51318,51319,51320,51321,51322,51323,51324,51325,
+51326,51327,51328,51329,51330,51331,51332,51333,51334,51335,51336,51337,
+51338,51339,51340,51341,51342,51343,51344,51345,51346,51347,51348,51349,
+51350,51351,51352,51353,51354,51355,51356,51357,51358,51359,51360,51361,
+51362,51363,51364,51365,51366,51367,51368,51369,51370,51371,51372,51373,
+51374,51375,51376,51377,51378,51379,51380,51381,51382,51383,51384,51385,
+51386,51387,51388,51389,51390,51391,51392,51393,51394,51395,51396,51397,
+51398,51399,51400,51401,51402,51403,51404,51405,51406,51407,51408,51409,
+51410,51411,51412,51413,51414,51415,51416,51417,51418,51419,51420,51421,
+51422,51423,51424,51425,51426,51427,51428,51429,51430,51431,51432,51433,
+51434,51435,51436,51437,51438,51439,51440,51441,51442,51443,51444,51445,
+51446,51447,51448,51449,51450,51451,51452,51453,51454,51455,51456,51457,
+51458,51459,51460,51461,51462,51463,51464,51465,51466,51467,51468,51469,
+51470,51471,51472,51473,51474,51475,51476,51477,51478,51479,51480,51481,
+51482,51483,51484,51485,51486,51487,51488,51489,51490,51491,51492,51493,
+51494,51495,51496,51497,51498,51499,51500,51501,51502,51503,51504,51505,
+51506,51507,51508,51509,51510,51511,51512,51513,51514,51515,51516,51517,
+51518,51519,51520,51521,51522,51523,51524,51525,51526,51527,51528,51529,
+51530,51531,51532,51533,51534,51535,51536,51537,51538,51539,51540,51541,
+51542,51543,51544,51545,51546,51547,51548,51549,51550,51551,51552,51553,
+51554,51555,51556,51557,51558,51559,51560,51561,51562,51563,51564,51565,
+51566,51567,51568,51569,51570,51571,51572,51573,51574,51575,51576,51577,
+51578,51579,51580,51581,51582,51583,51584,51585,51586,51587,51588,51589,
+51590,51591,51592,51593,51594,51595,51596,51597,51598,51599,51600,51601,
+51602,51603,51604,51605,51606,51607,51608,51609,51610,51611,51612,51613,
+51614,51615,51616,51617,51618,51619,51620,51621,51622,51623,51624,51625,
+51626,51627,51628,51629,51630,51631,51632,51633,51634,51635,51636,51637,
+51638,51639,51640,51641,51642,51643,51644,51645,51646,51647,51648,51649,
+51650,51651,51652,51653,51654,51655,51656,51657,51658,51659,51660,51661,
+51662,51663,51664,51665,51666,51667,51668,51669,51670,51671,51672,51673,
+51674,51675,51676,51677,51678,51679,51680,51681,51682,51683,51684,51685,
+51686,51687,51688,51689,51690,51691,51692,51693,51694,51695,51696,51697,
+51698,51699,51700,51701,51702,51703,51704,51705,51706,51707,51708,51709,
+51710,51711,51712,51713,51714,51715,51716,51717,51718,51719,51720,51721,
+51722,51723,51724,51725,51726,51727,51728,51729,51730,51731,51732,51733,
+51734,51735,51736,51737,51738,51739,51740,51741,51742,51743,51744,51745,
+51746,51747,51748,51749,51750,51751,51752,51753,51754,51755,51756,51757,
+51758,51759,51760,51761,51762,51763,51764,51765,51766,51767,51768,51769,
+51770,51771,51772,51773,51774,51775,51776,51777,51778,51779,51780,51781,
+51782,51783,51784,51785,51786,51787,51788,51789,51790,51791,51792,51793,
+51794,51795,51796,51797,51798,51799,51800,51801,51802,51803,51804,51805,
+51806,51807,51808,51809,51810,51811,51812,51813,51814,51815,51816,51817,
+51818,51819,51820,51821,51822,51823,51824,51825,51826,51827,51828,51829,
+51830,51831,51832,51833,51834,51835,51836,51837,51838,51839,51840,51841,
+51842,51843,51844,51845,51846,51847,51848,51849,51850,51851,51852,51853,
+51854,51855,51856,51857,51858,51859,51860,51861,51862,51863,51864,51865,
+51866,51867,51868,51869,51870,51871,51872,51873,51874,51875,51876,51877,
+51878,51879,51880,51881,51882,51883,51884,51885,51886,51887,51888,51889,
+51890,51891,51892,51893,51894,51895,51896,51897,51898,51899,51900,51901,
+51902,51903,51904,51905,51906,51907,51908,51909,51910,51911,51912,51913,
+51914,51915,51916,51917,51918,51919,51920,51921,51922,51923,51924,51925,
+51926,51927,51928,51929,51930,51931,51932,51933,51934,51935,51936,51937,
+51938,51939,51940,51941,51942,51943,51944,51945,51946,51947,51948,51949,
+51950,51951,51952,51953,51954,51955,51956,51957,51958,51959,51960,51961,
+51962,51963,51964,51965,51966,51967,51968,51969,51970,51971,51972,51973,
+51974,51975,51976,51977,51978,51979,51980,51981,51982,51983,51984,51985,
+51986,51987,51988,51989,51990,51991,51992,51993,51994,51995,51996,51997,
+51998,51999,52000,52001,52002,52003,52004,52005,52006,52007,52008,52009,
+52010,52011,52012,52013,52014,52015,52016,52017,52018,52019,52020,52021,
+52022,52023,52024,52025,52026,52027,52028,52029,52030,52031,52032,52033,
+52034,52035,52036,52037,52038,52039,52040,52041,52042,52043,52044,52045,
+52046,52047,52048,52049,52050,52051,52052,52053,52054,52055,52056,52057,
+52058,52059,52060,52061,52062,52063,52064,52065,52066,52067,52068,52069,
+52070,52071,52072,52073,52074,52075,52076,52077,52078,52079,52080,52081,
+52082,52083,52084,52085,52086,52087,52088,52089,52090,52091,52092,52093,
+52094,52095,52096,52097,52098,52099,52100,52101,52102,52103,52104,52105,
+52106,52107,52108,52109,52110,52111,52112,52113,52114,52115,52116,52117,
+52118,52119,52120,52121,52122,52123,52124,52125,52126,52127,52128,52129,
+52130,52131,52132,52133,52134,52135,52136,52137,52138,52139,52140,52141,
+52142,52143,52144,52145,52146,52147,52148,52149,52150,52151,52152,52153,
+52154,52155,52156,52157,52158,52159,52160,52161,52162,52163,52164,52165,
+52166,52167,52168,52169,52170,52171,52172,52173,52174,52175,52176,52177,
+52178,52179,52180,52181,52182,52183,52184,52185,52186,52187,52188,52189,
+52190,52191,52192,52193,52194,52195,52196,52197,52198,52199,52200,52201,
+52202,52203,52204,52205,52206,52207,52208,52209,52210,52211,52212,52213,
+52214,52215,52216,52217,52218,52219,52220,52221,52222,52223,52224,52225,
+52226,52227,52228,52229,52230,52231,52232,52233,52234,52235,52236,52237,
+52238,52239,52240,52241,52242,52243,52244,52245,52246,52247,52248,52249,
+52250,52251,52252,52253,52254,52255,52256,52257,52258,52259,52260,52261,
+52262,52263,52264,52265,52266,52267,52268,52269,52270,52271,52272,52273,
+52274,52275,52276,52277,52278,52279,52280,52281,52282,52283,52284,52285,
+52286,52287,52288,52289,52290,52291,52292,52293,52294,52295,52296,52297,
+52298,52299,52300,52301,52302,52303,52304,52305,52306,52307,52308,52309,
+52310,52311,52312,52313,52314,52315,52316,52317,52318,52319,52320,52321,
+52322,52323,52324,52325,52326,52327,52328,52329,52330,52331,52332,52333,
+52334,52335,52336,52337,52338,52339,52340,52341,52342,52343,52344,52345,
+52346,52347,52348,52349,52350,52351,52352,52353,52354,52355,52356,52357,
+52358,52359,52360,52361,52362,52363,52364,52365,52366,52367,52368,52369,
+52370,52371,52372,52373,52374,52375,52376,52377,52378,52379,52380,52381,
+52382,52383,52384,52385,52386,52387,52388,52389,52390,52391,52392,52393,
+52394,52395,52396,52397,52398,52399,52400,52401,52402,52403,52404,52405,
+52406,52407,52408,52409,52410,52411,52412,52413,52414,52415,52416,52417,
+52418,52419,52420,52421,52422,52423,52424,52425,52426,52427,52428,52429,
+52430,52431,52432,52433,52434,52435,52436,52437,52438,52439,52440,52441,
+52442,52443,52444,52445,52446,52447,52448,52449,52450,52451,52452,52453,
+52454,52455,52456,52457,52458,52459,52460,52461,52462,52463,52464,52465,
+52466,52467,52468,52469,52470,52471,52472,52473,52474,52475,52476,52477,
+52478,52479,52480,52481,52482,52483,52484,52485,52486,52487,52488,52489,
+52490,52491,52492,52493,52494,52495,52496,52497,52498,52499,52500,52501,
+52502,52503,52504,52505,52506,52507,52508,52509,52510,52511,52512,52513,
+52514,52515,52516,52517,52518,52519,52520,52521,52522,52523,52524,52525,
+52526,52527,52528,52529,52530,52531,52532,52533,52534,52535,52536,52537,
+52538,52539,52540,52541,52542,52543,52544,52545,52546,52547,52548,52549,
+52550,52551,52552,52553,52554,52555,52556,52557,52558,52559,52560,52561,
+52562,52563,52564,52565,52566,52567,52568,52569,52570,52571,52572,52573,
+52574,52575,52576,52577,52578,52579,52580,52581,52582,52583,52584,52585,
+52586,52587,52588,52589,52590,52591,52592,52593,52594,52595,52596,52597,
+52598,52599,52600,52601,52602,52603,52604,52605,52606,52607,52608,52609,
+52610,52611,52612,52613,52614,52615,52616,52617,52618,52619,52620,52621,
+52622,52623,52624,52625,52626,52627,52628,52629,52630,52631,52632,52633,
+52634,52635,52636,52637,52638,52639,52640,52641,52642,52643,52644,52645,
+52646,52647,52648,52649,52650,52651,52652,52653,52654,52655,52656,52657,
+52658,52659,52660,52661,52662,52663,52664,52665,52666,52667,52668,52669,
+52670,52671,52672,52673,52674,52675,52676,52677,52678,52679,52680,52681,
+52682,52683,52684,52685,52686,52687,52688,52689,52690,52691,52692,52693,
+52694,52695,52696,52697,52698,52699,52700,52701,52702,52703,52704,52705,
+52706,52707,52708,52709,52710,52711,52712,52713,52714,52715,52716,52717,
+52718,52719,52720,52721,52722,52723,52724,52725,52726,52727,52728,52729,
+52730,52731,52732,52733,52734,52735,52736,52737,52738,52739,52740,52741,
+52742,52743,52744,52745,52746,52747,52748,52749,52750,52751,52752,52753,
+52754,52755,52756,52757,52758,52759,52760,52761,52762,52763,52764,52765,
+52766,52767,52768,52769,52770,52771,52772,52773,52774,52775,52776,52777,
+52778,52779,52780,52781,52782,52783,52784,52785,52786,52787,52788,52789,
+52790,52791,52792,52793,52794,52795,52796,52797,52798,52799,52800,52801,
+52802,52803,52804,52805,52806,52807,52808,52809,52810,52811,52812,52813,
+52814,52815,52816,52817,52818,52819,52820,52821,52822,52823,52824,52825,
+52826,52827,52828,52829,52830,52831,52832,52833,52834,52835,52836,52837,
+52838,52839,52840,52841,52842,52843,52844,52845,52846,52847,52848,52849,
+52850,52851,52852,52853,52854,52855,52856,52857,52858,52859,52860,52861,
+52862,52863,52864,52865,52866,52867,52868,52869,52870,52871,52872,52873,
+52874,52875,52876,52877,52878,52879,52880,52881,52882,52883,52884,52885,
+52886,52887,52888,52889,52890,52891,52892,52893,52894,52895,52896,52897,
+52898,52899,52900,52901,52902,52903,52904,52905,52906,52907,52908,52909,
+52910,52911,52912,52913,52914,52915,52916,52917,52918,52919,52920,52921,
+52922,52923,52924,52925,52926,52927,52928,52929,52930,52931,52932,52933,
+52934,52935,52936,52937,52938,52939,52940,52941,52942,52943,52944,52945,
+52946,52947,52948,52949,52950,52951,52952,52953,52954,52955,52956,52957,
+52958,52959,52960,52961,52962,52963,52964,52965,52966,52967,52968,52969,
+52970,52971,52972,52973,52974,52975,52976,52977,52978,52979,52980,52981,
+52982,52983,52984,52985,52986,52987,52988,52989,52990,52991,52992,52993,
+52994,52995,52996,52997,52998,52999,53000,53001,53002,53003,53004,53005,
+53006,53007,53008,53009,53010,53011,53012,53013,53014,53015,53016,53017,
+53018,53019,53020,53021,53022,53023,53024,53025,53026,53027,53028,53029,
+53030,53031,53032,53033,53034,53035,53036,53037,53038,53039,53040,53041,
+53042,53043,53044,53045,53046,53047,53048,53049,53050,53051,53052,53053,
+53054,53055,53056,53057,53058,53059,53060,53061,53062,53063,53064,53065,
+53066,53067,53068,53069,53070,53071,53072,53073,53074,53075,53076,53077,
+53078,53079,53080,53081,53082,53083,53084,53085,53086,53087,53088,53089,
+53090,53091,53092,53093,53094,53095,53096,53097,53098,53099,53100,53101,
+53102,53103,53104,53105,53106,53107,53108,53109,53110,53111,53112,53113,
+53114,53115,53116,53117,53118,53119,53120,53121,53122,53123,53124,53125,
+53126,53127,53128,53129,53130,53131,53132,53133,53134,53135,53136,53137,
+53138,53139,53140,53141,53142,53143,53144,53145,53146,53147,53148,53149,
+53150,53151,53152,53153,53154,53155,53156,53157,53158,53159,53160,53161,
+53162,53163,53164,53165,53166,53167,53168,53169,53170,53171,53172,53173,
+53174,53175,53176,53177,53178,53179,53180,53181,53182,53183,53184,53185,
+53186,53187,53188,53189,53190,53191,53192,53193,53194,53195,53196,53197,
+53198,53199,53200,53201,53202,53203,53204,53205,53206,53207,53208,53209,
+53210,53211,53212,53213,53214,53215,53216,53217,53218,53219,53220,53221,
+53222,53223,53224,53225,53226,53227,53228,53229,53230,53231,53232,53233,
+53234,53235,53236,53237,53238,53239,53240,53241,53242,53243,53244,53245,
+53246,53247,53248,53249,53250,53251,53252,53253,53254,53255,53256,53257,
+53258,53259,53260,53261,53262,53263,53264,53265,53266,53267,53268,53269,
+53270,53271,53272,53273,53274,53275,53276,53277,53278,53279,53280,53281,
+53282,53283,53284,53285,53286,53287,53288,53289,53290,53291,53292,53293,
+53294,53295,53296,53297,53298,53299,53300,53301,53302,53303,53304,53305,
+53306,53307,53308,53309,53310,53311,53312,53313,53314,53315,53316,53317,
+53318,53319,53320,53321,53322,53323,53324,53325,53326,53327,53328,53329,
+53330,53331,53332,53333,53334,53335,53336,53337,53338,53339,53340,53341,
+53342,53343,53344,53345,53346,53347,53348,53349,53350,53351,53352,53353,
+53354,53355,53356,53357,53358,53359,53360,53361,53362,53363,53364,53365,
+53366,53367,53368,53369,53370,53371,53372,53373,53374,53375,53376,53377,
+53378,53379,53380,53381,53382,53383,53384,53385,53386,53387,53388,53389,
+53390,53391,53392,53393,53394,53395,53396,53397,53398,53399,53400,53401,
+53402,53403,53404,53405,53406,53407,53408,53409,53410,53411,53412,53413,
+53414,53415,53416,53417,53418,53419,53420,53421,53422,53423,53424,53425,
+53426,53427,53428,53429,53430,53431,53432,53433,53434,53435,53436,53437,
+53438,53439,53440,53441,53442,53443,53444,53445,53446,53447,53448,53449,
+53450,53451,53452,53453,53454,53455,53456,53457,53458,53459,53460,53461,
+53462,53463,53464,53465,53466,53467,53468,53469,53470,53471,53472,53473,
+53474,53475,53476,53477,53478,53479,53480,53481,53482,53483,53484,53485,
+53486,53487,53488,53489,53490,53491,53492,53493,53494,53495,53496,53497,
+53498,53499,53500,53501,53502,53503,53504,53505,53506,53507,53508,53509,
+53510,53511,53512,53513,53514,53515,53516,53517,53518,53519,53520,53521,
+53522,53523,53524,53525,53526,53527,53528,53529,53530,53531,53532,53533,
+53534,53535,53536,53537,53538,53539,53540,53541,53542,53543,53544,53545,
+53546,53547,53548,53549,53550,53551,53552,53553,53554,53555,53556,53557,
+53558,53559,53560,53561,53562,53563,53564,53565,53566,53567,53568,53569,
+53570,53571,53572,53573,53574,53575,53576,53577,53578,53579,53580,53581,
+53582,53583,53584,53585,53586,53587,53588,53589,53590,53591,53592,53593,
+53594,53595,53596,53597,53598,53599,53600,53601,53602,53603,53604,53605,
+53606,53607,53608,53609,53610,53611,53612,53613,53614,53615,53616,53617,
+53618,53619,53620,53621,53622,53623,53624,53625,53626,53627,53628,53629,
+53630,53631,53632,53633,53634,53635,53636,53637,53638,53639,53640,53641,
+53642,53643,53644,53645,53646,53647,53648,53649,53650,53651,53652,53653,
+53654,53655,53656,53657,53658,53659,53660,53661,53662,53663,53664,53665,
+53666,53667,53668,53669,53670,53671,53672,53673,53674,53675,53676,53677,
+53678,53679,53680,53681,53682,53683,53684,53685,53686,53687,53688,53689,
+53690,53691,53692,53693,53694,53695,53696,53697,53698,53699,53700,53701,
+53702,53703,53704,53705,53706,53707,53708,53709,53710,53711,53712,53713,
+53714,53715,53716,53717,53718,53719,53720,53721,53722,53723,53724,53725,
+53726,53727,53728,53729,53730,53731,53732,53733,53734,53735,53736,53737,
+53738,53739,53740,53741,53742,53743,53744,53745,53746,53747,53748,53749,
+53750,53751,53752,53753,53754,53755,53756,53757,53758,53759,53760,53761,
+53762,53763,53764,53765,53766,53767,53768,53769,53770,53771,53772,53773,
+53774,53775,53776,53777,53778,53779,53780,53781,53782,53783,53784,53785,
+53786,53787,53788,53789,53790,53791,53792,53793,53794,53795,53796,53797,
+53798,53799,53800,53801,53802,53803,53804,53805,53806,53807,53808,53809,
+53810,53811,53812,53813,53814,53815,53816,53817,53818,53819,53820,53821,
+53822,53823,53824,53825,53826,53827,53828,53829,53830,53831,53832,53833,
+53834,53835,53836,53837,53838,53839,53840,53841,53842,53843,53844,53845,
+53846,53847,53848,53849,53850,53851,53852,53853,53854,53855,53856,53857,
+53858,53859,53860,53861,53862,53863,53864,53865,53866,53867,53868,53869,
+53870,53871,53872,53873,53874,53875,53876,53877,53878,53879,53880,53881,
+53882,53883,53884,53885,53886,53887,53888,53889,53890,53891,53892,53893,
+53894,53895,53896,53897,53898,53899,53900,53901,53902,53903,53904,53905,
+53906,53907,53908,53909,53910,53911,53912,53913,53914,53915,53916,53917,
+53918,53919,53920,53921,53922,53923,53924,53925,53926,53927,53928,53929,
+53930,53931,53932,53933,53934,53935,53936,53937,53938,53939,53940,53941,
+53942,53943,53944,53945,53946,53947,53948,53949,53950,53951,53952,53953,
+53954,53955,53956,53957,53958,53959,53960,53961,53962,53963,53964,53965,
+53966,53967,53968,53969,53970,53971,53972,53973,53974,53975,53976,53977,
+53978,53979,53980,53981,53982,53983,53984,53985,53986,53987,53988,53989,
+53990,53991,53992,53993,53994,53995,53996,53997,53998,53999,54000,54001,
+54002,54003,54004,54005,54006,54007,54008,54009,54010,54011,54012,54013,
+54014,54015,54016,54017,54018,54019,54020,54021,54022,54023,54024,54025,
+54026,54027,54028,54029,54030,54031,54032,54033,54034,54035,54036,54037,
+54038,54039,54040,54041,54042,54043,54044,54045,54046,54047,54048,54049,
+54050,54051,54052,54053,54054,54055,54056,54057,54058,54059,54060,54061,
+54062,54063,54064,54065,54066,54067,54068,54069,54070,54071,54072,54073,
+54074,54075,54076,54077,54078,54079,54080,54081,54082,54083,54084,54085,
+54086,54087,54088,54089,54090,54091,54092,54093,54094,54095,54096,54097,
+54098,54099,54100,54101,54102,54103,54104,54105,54106,54107,54108,54109,
+54110,54111,54112,54113,54114,54115,54116,54117,54118,54119,54120,54121,
+54122,54123,54124,54125,54126,54127,54128,54129,54130,54131,54132,54133,
+54134,54135,54136,54137,54138,54139,54140,54141,54142,54143,54144,54145,
+54146,54147,54148,54149,54150,54151,54152,54153,54154,54155,54156,54157,
+54158,54159,54160,54161,54162,54163,54164,54165,54166,54167,54168,54169,
+54170,54171,54172,54173,54174,54175,54176,54177,54178,54179,54180,54181,
+54182,54183,54184,54185,54186,54187,54188,54189,54190,54191,54192,54193,
+54194,54195,54196,54197,54198,54199,54200,54201,54202,54203,54204,54205,
+54206,54207,54208,54209,54210,54211,54212,54213,54214,54215,54216,54217,
+54218,54219,54220,54221,54222,54223,54224,54225,54226,54227,54228,54229,
+54230,54231,54232,54233,54234,54235,54236,54237,54238,54239,54240,54241,
+54242,54243,54244,54245,54246,54247,54248,54249,54250,54251,54252,54253,
+54254,54255,54256,54257,54258,54259,54260,54261,54262,54263,54264,54265,
+54266,54267,54268,54269,54270,54271,54272,54273,54274,54275,54276,54277,
+54278,54279,54280,54281,54282,54283,54284,54285,54286,54287,54288,54289,
+54290,54291,54292,54293,54294,54295,54296,54297,54298,54299,54300,54301,
+54302,54303,54304,54305,54306,54307,54308,54309,54310,54311,54312,54313,
+54314,54315,54316,54317,54318,54319,54320,54321,54322,54323,54324,54325,
+54326,54327,54328,54329,54330,54331,54332,54333,54334,54335,54336,54337,
+54338,54339,54340,54341,54342,54343,54344,54345,54346,54347,54348,54349,
+54350,54351,54352,54353,54354,54355,54356,54357,54358,54359,54360,54361,
+54362,54363,54364,54365,54366,54367,54368,54369,54370,54371,54372,54373,
+54374,54375,54376,54377,54378,54379,54380,54381,54382,54383,54384,54385,
+54386,54387,54388,54389,54390,54391,54392,54393,54394,54395,54396,54397,
+54398,54399,54400,54401,54402,54403,54404,54405,54406,54407,54408,54409,
+54410,54411,54412,54413,54414,54415,54416,54417,54418,54419,54420,54421,
+54422,54423,54424,54425,54426,54427,54428,54429,54430,54431,54432,54433,
+54434,54435,54436,54437,54438,54439,54440,54441,54442,54443,54444,54445,
+54446,54447,54448,54449,54450,54451,54452,54453,54454,54455,54456,54457,
+54458,54459,54460,54461,54462,54463,54464,54465,54466,54467,54468,54469,
+54470,54471,54472,54473,54474,54475,54476,54477,54478,54479,54480,54481,
+54482,54483,54484,54485,54486,54487,54488,54489,54490,54491,54492,54493,
+54494,54495,54496,54497,54498,54499,54500,54501,54502,54503,54504,54505,
+54506,54507,54508,54509,54510,54511,54512,54513,54514,54515,54516,54517,
+54518,54519,54520,54521,54522,54523,54524,54525,54526,54527,54528,54529,
+54530,54531,54532,54533,54534,54535,54536,54537,54538,54539,54540,54541,
+54542,54543,54544,54545,54546,54547,54548,54549,54550,54551,54552,54553,
+54554,54555,54556,54557,54558,54559,54560,54561,54562,54563,54564,54565,
+54566,54567,54568,54569,54570,54571,54572,54573,54574,54575,54576,54577,
+54578,54579,54580,54581,54582,54583,54584,54585,54586,54587,54588,54589,
+54590,54591,54592,54593,54594,54595,54596,54597,54598,54599,54600,54601,
+54602,54603,54604,54605,54606,54607,54608,54609,54610,54611,54612,54613,
+54614,54615,54616,54617,54618,54619,54620,54621,54622,54623,54624,54625,
+54626,54627,54628,54629,54630,54631,54632,54633,54634,54635,54636,54637,
+54638,54639,54640,54641,54642,54643,54644,54645,54646,54647,54648,54649,
+54650,54651,54652,54653,54654,54655,54656,54657,54658,54659,54660,54661,
+54662,54663,54664,54665,54666,54667,54668,54669,54670,54671,54672,54673,
+54674,54675,54676,54677,54678,54679,54680,54681,54682,54683,54684,54685,
+54686,54687,54688,54689,54690,54691,54692,54693,54694,54695,54696,54697,
+54698,54699,54700,54701,54702,54703,54704,54705,54706,54707,54708,54709,
+54710,54711,54712,54713,54714,54715,54716,54717,54718,54719,54720,54721,
+54722,54723,54724,54725,54726,54727,54728,54729,54730,54731,54732,54733,
+54734,54735,54736,54737,54738,54739,54740,54741,54742,54743,54744,54745,
+54746,54747,54748,54749,54750,54751,54752,54753,54754,54755,54756,54757,
+54758,54759,54760,54761,54762,54763,54764,54765,54766,54767,54768,54769,
+54770,54771,54772,54773,54774,54775,54776,54777,54778,54779,54780,54781,
+54782,54783,54784,54785,54786,54787,54788,54789,54790,54791,54792,54793,
+54794,54795,54796,54797,54798,54799,54800,54801,54802,54803,54804,54805,
+54806,54807,54808,54809,54810,54811,54812,54813,54814,54815,54816,54817,
+54818,54819,54820,54821,54822,54823,54824,54825,54826,54827,54828,54829,
+54830,54831,54832,54833,54834,54835,54836,54837,54838,54839,54840,54841,
+54842,54843,54844,54845,54846,54847,54848,54849,54850,54851,54852,54853,
+54854,54855,54856,54857,54858,54859,54860,54861,54862,54863,54864,54865,
+54866,54867,54868,54869,54870,54871,54872,54873,54874,54875,54876,54877,
+54878,54879,54880,54881,54882,54883,54884,54885,54886,54887,54888,54889,
+54890,54891,54892,54893,54894,54895,54896,54897,54898,54899,54900,54901,
+54902,54903,54904,54905,54906,54907,54908,54909,54910,54911,54912,54913,
+54914,54915,54916,54917,54918,54919,54920,54921,54922,54923,54924,54925,
+54926,54927,54928,54929,54930,54931,54932,54933,54934,54935,54936,54937,
+54938,54939,54940,54941,54942,54943,54944,54945,54946,54947,54948,54949,
+54950,54951,54952,54953,54954,54955,54956,54957,54958,54959,54960,54961,
+54962,54963,54964,54965,54966,54967,54968,54969,54970,54971,54972,54973,
+54974,54975,54976,54977,54978,54979,54980,54981,54982,54983,54984,54985,
+54986,54987,54988,54989,54990,54991,54992,54993,54994,54995,54996,54997,
+54998,54999,55000,55001,55002,55003,55004,55005,55006,55007,55008,55009,
+55010,55011,55012,55013,55014,55015,55016,55017,55018,55019,55020,55021,
+55022,55023,55024,55025,55026,55027,55028,55029,55030,55031,55032,55033,
+55034,55035,55036,55037,55038,55039,55040,55041,55042,55043,55044,55045,
+55046,55047,55048,55049,55050,55051,55052,55053,55054,55055,55056,55057,
+55058,55059,55060,55061,55062,55063,55064,55065,55066,55067,55068,55069,
+55070,55071,55072,55073,55074,55075,55076,55077,55078,55079,55080,55081,
+55082,55083,55084,55085,55086,55087,55088,55089,55090,55091,55092,55093,
+55094,55095,55096,55097,55098,55099,55100,55101,55102,55103,55104,55105,
+55106,55107,55108,55109,55110,55111,55112,55113,55114,55115,55116,55117,
+55118,55119,55120,55121,55122,55123,55124,55125,55126,55127,55128,55129,
+55130,55131,55132,55133,55134,55135,55136,55137,55138,55139,55140,55141,
+55142,55143,55144,55145,55146,55147,55148,55149,55150,55151,55152,55153,
+55154,55155,55156,55157,55158,55159,55160,55161,55162,55163,55164,55165,
+55166,55167,55168,55169,55170,55171,55172,55173,55174,55175,55176,55177,
+55178,55179,55180,55181,55182,55183,55184,55185,55186,55187,55188,55189,
+55190,55191,55192,55193,55194,55195,55196,55197,55198,55199,55200,55201,
+55202,55203,55204,55205,55206,55207,55208,55209,55210,55211,55212,55213,
+55214,55215,55216,55217,55218,55219,55220,55221,55222,55223,55224,55225,
+55226,55227,55228,55229,55230,55231,55232,55233,55234,55235,55236,55237,
+55238,55239,55240,55241,55242,55243,55244,55245,55246,55247,55248,55249,
+55250,55251,55252,55253,55254,55255,55256,55257,55258,55259,55260,55261,
+55262,55263,55264,55265,55266,55267,55268,55269,55270,55271,55272,55273,
+55274,55275,55276,55277,55278,55279,55280,55281,55282,55283,55284,55285,
+55286,55287,55288,55289,55290,55291,55292,55293,55294,55295,55296,55297,
+55298,55299,55300,55301,55302,55303,55304,55305,55306,55307,55308,55309,
+55310,55311,55312,55313,55314,55315,55316,55317,55318,55319,55320,55321,
+55322,55323,55324,55325,55326,55327,55328,55329,55330,55331,55332,55333,
+55334,55335,55336,55337,55338,55339,55340,55341,55342,55343,55344,55345,
+55346,55347,55348,55349,55350,55351,55352,55353,55354,55355,55356,55357,
+55358,55359,55360,55361,55362,55363,55364,55365,55366,55367,55368,55369,
+55370,55371,55372,55373,55374,55375,55376,55377,55378,55379,55380,55381,
+55382,55383,55384,55385,55386,55387,55388,55389,55390,55391,55392,55393,
+55394,55395,55396,55397,55398,55399,55400,55401,55402,55403,55404,55405,
+55406,55407,55408,55409,55410,55411,55412,55413,55414,55415,55416,55417,
+55418,55419,55420,55421,55422,55423,55424,55425,55426,55427,55428,55429,
+55430,55431,55432,55433,55434,55435,55436,55437,55438,55439,55440,55441,
+55442,55443,55444,55445,55446,55447,55448,55449,55450,55451,55452,55453,
+55454,55455,55456,55457,55458,55459,55460,55461,55462,55463,55464,55465,
+55466,55467,55468,55469,55470,55471,55472,55473,55474,55475,55476,55477,
+55478,55479,55480,55481,55482,55483,55484,55485,55486,55487,55488,55489,
+55490,55491,55492,55493,55494,55495,55496,55497,55498,55499,55500,55501,
+55502,55503,55504,55505,55506,55507,55508,55509,55510,55511,55512,55513,
+55514,55515,55516,55517,55518,55519,55520,55521,55522,55523,55524,55525,
+55526,55527,55528,55529,55530,55531,55532,55533,55534,55535,55536,55537,
+55538,55539,55540,55541,55542,55543,55544,55545,55546,55547,55548,55549,
+55550,55551,55552,55553,55554,55555,55556,55557,55558,55559,55560,55561,
+55562,55563,55564,55565,55566,55567,55568,55569,55570,55571,55572,55573,
+55574,55575,55576,55577,55578,55579,55580,55581,55582,55583,55584,55585,
+55586,55587,55588,55589,55590,55591,55592,55593,55594,55595,55596,55597,
+55598,55599,55600,55601,55602,55603,55604,55605,55606,55607,55608,55609,
+55610,55611,55612,55613,55614,55615,55616,55617,55618,55619,55620,55621,
+55622,55623,55624,55625,55626,55627,55628,55629,55630,55631,55632,55633,
+55634,55635,55636,55637,55638,55639,55640,55641,55642,55643,55644,55645,
+55646,55647,55648,55649,55650,55651,55652,55653,55654,55655,55656,55657,
+55658,55659,55660,55661,55662,55663,55664,55665,55666,55667,55668,55669,
+55670,55671,55672,55673,55674,55675,55676,55677,55678,55679,55680,55681,
+55682,55683,55684,55685,55686,55687,55688,55689,55690,55691,55692,55693,
+55694,55695,55696,55697,55698,55699,55700,55701,55702,55703,55704,55705,
+55706,55707,55708,55709,55710,55711,55712,55713,55714,55715,55716,55717,
+55718,55719,55720,55721,55722,55723,55724,55725,55726,55727,55728,55729,
+55730,55731,55732,55733,55734,55735,55736,55737,55738,55739,55740,55741,
+55742,55743,55744,55745,55746,55747,55748,55749,55750,55751,55752,55753,
+55754,55755,55756,55757,55758,55759,55760,55761,55762,55763,55764,55765,
+55766,55767,55768,55769,55770,55771,55772,55773,55774,55775,55776,55777,
+55778,55779,55780,55781,55782,55783,55784,55785,55786,55787,55788,55789,
+55790,55791,55792,55793,55794,55795,55796,55797,55798,55799,55800,55801,
+55802,55803,55804,55805,55806,55807,55808,55809,55810,55811,55812,55813,
+55814,55815,55816,55817,55818,55819,55820,55821,55822,55823,55824,55825,
+55826,55827,55828,55829,55830,55831,55832,55833,55834,55835,55836,55837,
+55838,55839,55840,55841,55842,55843,55844,55845,55846,55847,55848,55849,
+55850,55851,55852,55853,55854,55855,55856,55857,55858,55859,55860,55861,
+55862,55863,55864,55865,55866,55867,55868,55869,55870,55871,55872,55873,
+55874,55875,55876,55877,55878,55879,55880,55881,55882,55883,55884,55885,
+55886,55887,55888,55889,55890,55891,55892,55893,55894,55895,55896,55897,
+55898,55899,55900,55901,55902,55903,55904,55905,55906,55907,55908,55909,
+55910,55911,55912,55913,55914,55915,55916,55917,55918,55919,55920,55921,
+55922,55923,55924,55925,55926,55927,55928,55929,55930,55931,55932,55933,
+55934,55935,55936,55937,55938,55939,55940,55941,55942,55943,55944,55945,
+55946,55947,55948,55949,55950,55951,55952,55953,55954,55955,55956,55957,
+55958,55959,55960,55961,55962,55963,55964,55965,55966,55967,55968,55969,
+55970,55971,55972,55973,55974,55975,55976,55977,55978,55979,55980,55981,
+55982,55983,55984,55985,55986,55987,55988,55989,55990,55991,55992,55993,
+55994,55995,55996,55997,55998,55999,56000,56001,56002,56003,56004,56005,
+56006,56007,56008,56009,56010,56011,56012,56013,56014,56015,56016,56017,
+56018,56019,56020,56021,56022,56023,56024,56025,56026,56027,56028,56029,
+56030,56031,56032,56033,56034,56035,56036,56037,56038,56039,56040,56041,
+56042,56043,56044,56045,56046,56047,56048,56049,56050,56051,56052,56053,
+56054,56055,56056,56057,56058,56059,56060,56061,56062,56063,56064,56065,
+56066,56067,56068,56069,56070,56071,56072,56073,56074,56075,56076,56077,
+56078,56079,56080,56081,56082,56083,56084,56085,56086,56087,56088,56089,
+56090,56091,56092,56093,56094,56095,56096,56097,56098,56099,56100,56101,
+56102,56103,56104,56105,56106,56107,56108,56109,56110,56111,56112,56113,
+56114,56115,56116,56117,56118,56119,56120,56121,56122,56123,56124,56125,
+56126,56127,56128,56129,56130,56131,56132,56133,56134,56135,56136,56137,
+56138,56139,56140,56141,56142,56143,56144,56145,56146,56147,56148,56149,
+56150,56151,56152,56153,56154,56155,56156,56157,56158,56159,56160,56161,
+56162,56163,56164,56165,56166,56167,56168,56169,56170,56171,56172,56173,
+56174,56175,56176,56177,56178,56179,56180,56181,56182,56183,56184,56185,
+56186,56187,56188,56189,56190,56191,56192,56193,56194,56195,56196,56197,
+56198,56199,56200,56201,56202,56203,56204,56205,56206,56207,56208,56209,
+56210,56211,56212,56213,56214,56215,56216,56217,56218,56219,56220,56221,
+56222,56223,56224,56225,56226,56227,56228,56229,56230,56231,56232,56233,
+56234,56235,56236,56237,56238,56239,56240,56241,56242,56243,56244,56245,
+56246,56247,56248,56249,56250,56251,56252,56253,56254,56255,56256,56257,
+56258,56259,56260,56261,56262,56263,56264,56265,56266,56267,56268,56269,
+56270,56271,56272,56273,56274,56275,56276,56277,56278,56279,56280,56281,
+56282,56283,56284,56285,56286,56287,56288,56289,56290,56291,56292,56293,
+56294,56295,56296,56297,56298,56299,56300,56301,56302,56303,56304,56305,
+56306,56307,56308,56309,56310,56311,56312,56313,56314,56315,56316,56317,
+56318,56319,56320,56321,56322,56323,56324,56325,56326,56327,56328,56329,
+56330,56331,56332,56333,56334,56335,56336,56337,56338,56339,56340,56341,
+56342,56343,56344,56345,56346,56347,56348,56349,56350,56351,56352,56353,
+56354,56355,56356,56357,56358,56359,56360,56361,56362,56363,56364,56365,
+56366,56367,56368,56369,56370,56371,56372,56373,56374,56375,56376,56377,
+56378,56379,56380,56381,56382,56383,56384,56385,56386,56387,56388,56389,
+56390,56391,56392,56393,56394,56395,56396,56397,56398,56399,56400,56401,
+56402,56403,56404,56405,56406,56407,56408,56409,56410,56411,56412,56413,
+56414,56415,56416,56417,56418,56419,56420,56421,56422,56423,56424,56425,
+56426,56427,56428,56429,56430,56431,56432,56433,56434,56435,56436,56437,
+56438,56439,56440,56441,56442,56443,56444,56445,56446,56447,56448,56449,
+56450,56451,56452,56453,56454,56455,56456,56457,56458,56459,56460,56461,
+56462,56463,56464,56465,56466,56467,56468,56469,56470,56471,56472,56473,
+56474,56475,56476,56477,56478,56479,56480,56481,56482,56483,56484,56485,
+56486,56487,56488,56489,56490,56491,56492,56493,56494,56495,56496,56497,
+56498,56499,56500,56501,56502,56503,56504,56505,56506,56507,56508,56509,
+56510,56511,56512,56513,56514,56515,56516,56517,56518,56519,56520,56521,
+56522,56523,56524,56525,56526,56527,56528,56529,56530,56531,56532,56533,
+56534,56535,56536,56537,56538,56539,56540,56541,56542,56543,56544,56545,
+56546,56547,56548,56549,56550,56551,56552,56553,56554,56555,56556,56557,
+56558,56559,56560,56561,56562,56563,56564,56565,56566,56567,56568,56569,
+56570,56571,56572,56573,56574,56575,56576,56577,56578,56579,56580,56581,
+56582,56583,56584,56585,56586,56587,56588,56589,56590,56591,56592,56593,
+56594,56595,56596,56597,56598,56599,56600,56601,56602,56603,56604,56605,
+56606,56607,56608,56609,56610,56611,56612,56613,56614,56615,56616,56617,
+56618,56619,56620,56621,56622,56623,56624,56625,56626,56627,56628,56629,
+56630,56631,56632,56633,56634,56635,56636,56637,56638,56639,56640,56641,
+56642,56643,56644,56645,56646,56647,56648,56649,56650,56651,56652,56653,
+56654,56655,56656,56657,56658,56659,56660,56661,56662,56663,56664,56665,
+56666,56667,56668,56669,56670,56671,56672,56673,56674,56675,56676,56677,
+56678,56679,56680,56681,56682,56683,56684,56685,56686,56687,56688,56689,
+56690,56691,56692,56693,56694,56695,56696,56697,56698,56699,56700,56701,
+56702,56703,56704,56705,56706,56707,56708,56709,56710,56711,56712,56713,
+56714,56715,56716,56717,56718,56719,56720,56721,56722,56723,56724,56725,
+56726,56727,56728,56729,56730,56731,56732,56733,56734,56735,56736,56737,
+56738,56739,56740,56741,56742,56743,56744,56745,56746,56747,56748,56749,
+56750,56751,56752,56753,56754,56755,56756,56757,56758,56759,56760,56761,
+56762,56763,56764,56765,56766,56767,56768,56769,56770,56771,56772,56773,
+56774,56775,56776,56777,56778,56779,56780,56781,56782,56783,56784,56785,
+56786,56787,56788,56789,56790,56791,56792,56793,56794,56795,56796,56797,
+56798,56799,56800,56801,56802,56803,56804,56805,56806,56807,56808,56809,
+56810,56811,56812,56813,56814,56815,56816,56817,56818,56819,56820,56821,
+56822,56823,56824,56825,56826,56827,56828,56829,56830,56831,56832,56833,
+56834,56835,56836,56837,56838,56839,56840,56841,56842,56843,56844,56845,
+56846,56847,56848,56849,56850,56851,56852,56853,56854,56855,56856,56857,
+56858,56859,56860,56861,56862,56863,56864,56865,56866,56867,56868,56869,
+56870,56871,56872,56873,56874,56875,56876,56877,56878,56879,56880,56881,
+56882,56883,56884,56885,56886,56887,56888,56889,56890,56891,56892,56893,
+56894,56895,56896,56897,56898,56899,56900,56901,56902,56903,56904,56905,
+56906,56907,56908,56909,56910,56911,56912,56913,56914,56915,56916,56917,
+56918,56919,56920,56921,56922,56923,56924,56925,56926,56927,56928,56929,
+56930,56931,56932,56933,56934,56935,56936,56937,56938,56939,56940,56941,
+56942,56943,56944,56945,56946,56947,56948,56949,56950,56951,56952,56953,
+56954,56955,56956,56957,56958,56959,56960,56961,56962,56963,56964,56965,
+56966,56967,56968,56969,56970,56971,56972,56973,56974,56975,56976,56977,
+56978,56979,56980,56981,56982,56983,56984,56985,56986,56987,56988,56989,
+56990,56991,56992,56993,56994,56995,56996,56997,56998,56999,57000,57001,
+57002,57003,57004,57005,57006,57007,57008,57009,57010,57011,57012,57013,
+57014,57015,57016,57017,57018,57019,57020,57021,57022,57023,57024,57025,
+57026,57027,57028,57029,57030,57031,57032,57033,57034,57035,57036,57037,
+57038,57039,57040,57041,57042,57043,57044,57045,57046,57047,57048,57049,
+57050,57051,57052,57053,57054,57055,57056,57057,57058,57059,57060,57061,
+57062,57063,57064,57065,57066,57067,57068,57069,57070,57071,57072,57073,
+57074,57075,57076,57077,57078,57079,57080,57081,57082,57083,57084,57085,
+57086,57087,57088,57089,57090,57091,57092,57093,57094,57095,57096,57097,
+57098,57099,57100,57101,57102,57103,57104,57105,57106,57107,57108,57109,
+57110,57111,57112,57113,57114,57115,57116,57117,57118,57119,57120,57121,
+57122,57123,57124,57125,57126,57127,57128,57129,57130,57131,57132,57133,
+57134,57135,57136,57137,57138,57139,57140,57141,57142,57143,57144,57145,
+57146,57147,57148,57149,57150,57151,57152,57153,57154,57155,57156,57157,
+57158,57159,57160,57161,57162,57163,57164,57165,57166,57167,57168,57169,
+57170,57171,57172,57173,57174,57175,57176,57177,57178,57179,57180,57181,
+57182,57183,57184,57185,57186,57187,57188,57189,57190,57191,57192,57193,
+57194,57195,57196,57197,57198,57199,57200,57201,57202,57203,57204,57205,
+57206,57207,57208,57209,57210,57211,57212,57213,57214,57215,57216,57217,
+57218,57219,57220,57221,57222,57223,57224,57225,57226,57227,57228,57229,
+57230,57231,57232,57233,57234,57235,57236,57237,57238,57239,57240,57241,
+57242,57243,57244,57245,57246,57247,57248,57249,57250,57251,57252,57253,
+57254,57255,57256,57257,57258,57259,57260,57261,57262,57263,57264,57265,
+57266,57267,57268,57269,57270,57271,57272,57273,57274,57275,57276,57277,
+57278,57279,57280,57281,57282,57283,57284,57285,57286,57287,57288,57289,
+57290,57291,57292,57293,57294,57295,57296,57297,57298,57299,57300,57301,
+57302,57303,57304,57305,57306,57307,57308,57309,57310,57311,57312,57313,
+57314,57315,57316,57317,57318,57319,57320,57321,57322,57323,57324,57325,
+57326,57327,57328,57329,57330,57331,57332,57333,57334,57335,57336,57337,
+57338,57339,57340,57341,57342,57343,57344,57345,57346,57347,57348,57349,
+57350,57351,57352,57353,57354,57355,57356,57357,57358,57359,57360,57361,
+57362,57363,57364,57365,57366,57367,57368,57369,57370,57371,57372,57373,
+57374,57375,57376,57377,57378,57379,57380,57381,57382,57383,57384,57385,
+57386,57387,57388,57389,57390,57391,57392,57393,57394,57395,57396,57397,
+57398,57399,57400,57401,57402,57403,57404,57405,57406,57407,57408,57409,
+57410,57411,57412,57413,57414,57415,57416,57417,57418,57419,57420,57421,
+57422,57423,57424,57425,57426,57427,57428,57429,57430,57431,57432,57433,
+57434,57435,57436,57437,57438,57439,57440,57441,57442,57443,57444,57445,
+57446,57447,57448,57449,57450,57451,57452,57453,57454,57455,57456,57457,
+57458,57459,57460,57461,57462,57463,57464,57465,57466,57467,57468,57469,
+57470,57471,57472,57473,57474,57475,57476,57477,57478,57479,57480,57481,
+57482,57483,57484,57485,57486,57487,57488,57489,57490,57491,57492,57493,
+57494,57495,57496,57497,57498,57499,57500,57501,57502,57503,57504,57505,
+57506,57507,57508,57509,57510,57511,57512,57513,57514,57515,57516,57517,
+57518,57519,57520,57521,57522,57523,57524,57525,57526,57527,57528,57529,
+57530,57531,57532,57533,57534,57535,57536,57537,57538,57539,57540,57541,
+57542,57543,57544,57545,57546,57547,57548,57549,57550,57551,57552,57553,
+57554,57555,57556,57557,57558,57559,57560,57561,57562,57563,57564,57565,
+57566,57567,57568,57569,57570,57571,57572,57573,57574,57575,57576,57577,
+57578,57579,57580,57581,57582,57583,57584,57585,57586,57587,57588,57589,
+57590,57591,57592,57593,57594,57595,57596,57597,57598,57599,57600,57601,
+57602,57603,57604,57605,57606,57607,57608,57609,57610,57611,57612,57613,
+57614,57615,57616,57617,57618,57619,57620,57621,57622,57623,57624,57625,
+57626,57627,57628,57629,57630,57631,57632,57633,57634,57635,57636,57637,
+57638,57639,57640,57641,57642,57643,57644,57645,57646,57647,57648,57649,
+57650,57651,57652,57653,57654,57655,57656,57657,57658,57659,57660,57661,
+57662,57663,57664,57665,57666,57667,57668,57669,57670,57671,57672,57673,
+57674,57675,57676,57677,57678,57679,57680,57681,57682,57683,57684,57685,
+57686,57687,57688,57689,57690,57691,57692,57693,57694,57695,57696,57697,
+57698,57699,57700,57701,57702,57703,57704,57705,57706,57707,57708,57709,
+57710,57711,57712,57713,57714,57715,57716,57717,57718,57719,57720,57721,
+57722,57723,57724,57725,57726,57727,57728,57729,57730,57731,57732,57733,
+57734,57735,57736,57737,57738,57739,57740,57741,57742,57743,57744,57745,
+57746,57747,57748,57749,57750,57751,57752,57753,57754,57755,57756,57757,
+57758,57759,57760,57761,57762,57763,57764,57765,57766,57767,57768,57769,
+57770,57771,57772,57773,57774,57775,57776,57777,57778,57779,57780,57781,
+57782,57783,57784,57785,57786,57787,57788,57789,57790,57791,57792,57793,
+57794,57795,57796,57797,57798,57799,57800,57801,57802,57803,57804,57805,
+57806,57807,57808,57809,57810,57811,57812,57813,57814,57815,57816,57817,
+57818,57819,57820,57821,57822,57823,57824,57825,57826,57827,57828,57829,
+57830,57831,57832,57833,57834,57835,57836,57837,57838,57839,57840,57841,
+57842,57843,57844,57845,57846,57847,57848,57849,57850,57851,57852,57853,
+57854,57855,57856,57857,57858,57859,57860,57861,57862,57863,57864,57865,
+57866,57867,57868,57869,57870,57871,57872,57873,57874,57875,57876,57877,
+57878,57879,57880,57881,57882,57883,57884,57885,57886,57887,57888,57889,
+57890,57891,57892,57893,57894,57895,57896,57897,57898,57899,57900,57901,
+57902,57903,57904,57905,57906,57907,57908,57909,57910,57911,57912,57913,
+57914,57915,57916,57917,57918,57919,57920,57921,57922,57923,57924,57925,
+57926,57927,57928,57929,57930,57931,57932,57933,57934,57935,57936,57937,
+57938,57939,57940,57941,57942,57943,57944,57945,57946,57947,57948,57949,
+57950,57951,57952,57953,57954,57955,57956,57957,57958,57959,57960,57961,
+57962,57963,57964,57965,57966,57967,57968,57969,57970,57971,57972,57973,
+57974,57975,57976,57977,57978,57979,57980,57981,57982,57983,57984,57985,
+57986,57987,57988,57989,57990,57991,57992,57993,57994,57995,57996,57997,
+57998,57999,58000,58001,58002,58003,58004,58005,58006,58007,58008,58009,
+58010,58011,58012,58013,58014,58015,58016,58017,58018,58019,58020,58021,
+58022,58023,58024,58025,58026,58027,58028,58029,58030,58031,58032,58033,
+58034,58035,58036,58037,58038,58039,58040,58041,58042,58043,58044,58045,
+58046,58047,58048,58049,58050,58051,58052,58053,58054,58055,58056,58057,
+58058,58059,58060,58061,58062,58063,58064,58065,58066,58067,58068,58069,
+58070,58071,58072,58073,58074,58075,58076,58077,58078,58079,58080,58081,
+58082,58083,58084,58085,58086,58087,58088,58089,58090,58091,58092,58093,
+58094,58095,58096,58097,58098,58099,58100,58101,58102,58103,58104,58105,
+58106,58107,58108,58109,58110,58111,58112,58113,58114,58115,58116,58117,
+58118,58119,58120,58121,58122,58123,58124,58125,58126,58127,58128,58129,
+58130,58131,58132,58133,58134,58135,58136,58137,58138,58139,58140,58141,
+58142,58143,58144,58145,58146,58147,58148,58149,58150,58151,58152,58153,
+58154,58155,58156,58157,58158,58159,58160,58161,58162,58163,58164,58165,
+58166,58167,58168,58169,58170,58171,58172,58173,58174,58175,58176,58177,
+58178,58179,58180,58181,58182,58183,58184,58185,58186,58187,58188,58189,
+58190,58191,58192,58193,58194,58195,58196,58197,58198,58199,58200,58201,
+58202,58203,58204,58205,58206,58207,58208,58209,58210,58211,58212,58213,
+58214,58215,58216,58217,58218,58219,58220,58221,58222,58223,58224,58225,
+58226,58227,58228,58229,58230,58231,58232,58233,58234,58235,58236,58237,
+58238,58239,58240,58241,58242,58243,58244,58245,58246,58247,58248,58249,
+58250,58251,58252,58253,58254,58255,58256,58257,58258,58259,58260,58261,
+58262,58263,58264,58265,58266,58267,58268,58269,58270,58271,58272,58273,
+58274,58275,58276,58277,58278,58279,58280,58281,58282,58283,58284,58285,
+58286,58287,58288,58289,58290,58291,58292,58293,58294,58295,58296,58297,
+58298,58299,58300,58301,58302,58303,58304,58305,58306,58307,58308,58309,
+58310,58311,58312,58313,58314,58315,58316,58317,58318,58319,58320,58321,
+58322,58323,58324,58325,58326,58327,58328,58329,58330,58331,58332,58333,
+58334,58335,58336,58337,58338,58339,58340,58341,58342,58343,58344,58345,
+58346,58347,58348,58349,58350,58351,58352,58353,58354,58355,58356,58357,
+58358,58359,58360,58361,58362,58363,58364,58365,58366,58367,58368,58369,
+58370,58371,58372,58373,58374,58375,58376,58377,58378,58379,58380,58381,
+58382,58383,58384,58385,58386,58387,58388,58389,58390,58391,58392,58393,
+58394,58395,58396,58397,58398,58399,58400,58401,58402,58403,58404,58405,
+58406,58407,58408,58409,58410,58411,58412,58413,58414,58415,58416,58417,
+58418,58419,58420,58421,58422,58423,58424,58425,58426,58427,58428,58429,
+58430,58431,58432,58433,58434,58435,58436,58437,58438,58439,58440,58441,
+58442,58443,58444,58445,58446,58447,58448,58449,58450,58451,58452,58453,
+58454,58455,58456,58457,58458,58459,58460,58461,58462,58463,58464,58465,
+58466,58467,58468,58469,58470,58471,58472,58473,58474,58475,58476,58477,
+58478,58479,58480,58481,58482,58483,58484,58485,58486,58487,58488,58489,
+58490,58491,58492,58493,58494,58495,58496,58497,58498,58499,58500,58501,
+58502,58503,58504,58505,58506,58507,58508,58509,58510,58511,58512,58513,
+58514,58515,58516,58517,58518,58519,58520,58521,58522,58523,58524,58525,
+58526,58527,58528,58529,58530,58531,58532,58533,58534,58535,58536,58537,
+58538,58539,58540,58541,58542,58543,58544,58545,58546,58547,58548,58549,
+58550,58551,58552,58553,58554,58555,58556,58557,58558,58559,58560,58561,
+58562,58563,58564,58565,58566,58567,58568,58569,58570,58571,58572,58573,
+58574,58575,58576,58577,58578,58579,58580,58581,58582,58583,58584,58585,
+58586,58587,58588,58589,58590,58591,58592,58593,58594,58595,58596,58597,
+58598,58599,58600,58601,58602,58603,58604,58605,58606,58607,58608,58609,
+58610,58611,58612,58613,58614,58615,58616,58617,58618,58619,58620,58621,
+58622,58623,58624,58625,58626,58627,58628,58629,58630,58631,58632,58633,
+58634,58635,58636,58637,58638,58639,58640,58641,58642,58643,58644,58645,
+58646,58647,58648,58649,58650,58651,58652,58653,58654,58655,58656,58657,
+58658,58659,58660,58661,58662,58663,58664,58665,58666,58667,58668,58669,
+58670,58671,58672,58673,58674,58675,58676,58677,58678,58679,58680,58681,
+58682,58683,58684,58685,58686,58687,58688,58689,58690,58691,58692,58693,
+58694,58695,58696,58697,58698,58699,58700,58701,58702,58703,58704,58705,
+58706,58707,58708,58709,58710,58711,58712,58713,58714,58715,58716,58717,
+58718,58719,58720,58721,58722,58723,58724,58725,58726,58727,58728,58729,
+58730,58731,58732,58733,58734,58735,58736,58737,58738,58739,58740,58741,
+58742,58743,58744,58745,58746,58747,58748,58749,58750,58751,58752,58753,
+58754,58755,58756,58757,58758,58759,58760,58761,58762,58763,58764,58765,
+58766,58767,58768,58769,58770,58771,58772,58773,58774,58775,58776,58777,
+58778,58779,58780,58781,58782,58783,58784,58785,58786,58787,58788,58789,
+58790,58791,58792,58793,58794,58795,58796,58797,58798,58799,58800,58801,
+58802,58803,58804,58805,58806,58807,58808,58809,58810,58811,58812,58813,
+58814,58815,58816,58817,58818,58819,58820,58821,58822,58823,58824,58825,
+58826,58827,58828,58829,58830,58831,58832,58833,58834,58835,58836,58837,
+58838,58839,58840,58841,58842,58843,58844,58845,58846,58847,58848,58849,
+58850,58851,58852,58853,58854,58855,58856,58857,58858,58859,58860,58861,
+58862,58863,58864,58865,58866,58867,58868,58869,58870,58871,58872,58873,
+58874,58875,58876,58877,58878,58879,58880,58881,58882,58883,58884,58885,
+58886,58887,58888,58889,58890,58891,58892,58893,58894,58895,58896,58897,
+58898,58899,58900,58901,58902,58903,58904,58905,58906,58907,58908,58909,
+58910,58911,58912,58913,58914,58915,58916,58917,58918,58919,58920,58921,
+58922,58923,58924,58925,58926,58927,58928,58929,58930,58931,58932,58933,
+58934,58935,58936,58937,58938,58939,58940,58941,58942,58943,58944,58945,
+58946,58947,58948,58949,58950,58951,58952,58953,58954,58955,58956,58957,
+58958,58959,58960,58961,58962,58963,58964,58965,58966,58967,58968,58969,
+58970,58971,58972,58973,58974,58975,58976,58977,58978,58979,58980,58981,
+58982,58983,58984,58985,58986,58987,58988,58989,58990,58991,58992,58993,
+58994,58995,58996,58997,58998,58999,59000,59001,59002,59003,59004,59005,
+59006,59007,59008,59009,59010,59011,59012,59013,59014,59015,59016,59017,
+59018,59019,59020,59021,59022,59023,59024,59025,59026,59027,59028,59029,
+59030,59031,59032,59033,59034,59035,59036,59037,59038,59039,59040,59041,
+59042,59043,59044,59045,59046,59047,59048,59049,59050,59051,59052,59053,
+59054,59055,59056,59057,59058,59059,59060,59061,59062,59063,59064,59065,
+59066,59067,59068,59069,59070,59071,59072,59073,59074,59075,59076,59077,
+59078,59079,59080,59081,59082,59083,59084,59085,59086,59087,59088,59089,
+59090,59091,59092,59093,59094,59095,59096,59097,59098,59099,59100,59101,
+59102,59103,59104,59105,59106,59107,59108,59109,59110,59111,59112,59113,
+59114,59115,59116,59117,59118,59119,59120,59121,59122,59123,59124,59125,
+59126,59127,59128,59129,59130,59131,59132,59133,59134,59135,59136,59137,
+59138,59139,59140,59141,59142,59143,59144,59145,59146,59147,59148,59149,
+59150,59151,59152,59153,59154,59155,59156,59157,59158,59159,59160,59161,
+59162,59163,59164,59165,59166,59167,59168,59169,59170,59171,59172,59173,
+59174,59175,59176,59177,59178,59179,59180,59181,59182,59183,59184,59185,
+59186,59187,59188,59189,59190,59191,59192,59193,59194,59195,59196,59197,
+59198,59199,59200,59201,59202,59203,59204,59205,59206,59207,59208,59209,
+59210,59211,59212,59213,59214,59215,59216,59217,59218,59219,59220,59221,
+59222,59223,59224,59225,59226,59227,59228,59229,59230,59231,59232,59233,
+59234,59235,59236,59237,59238,59239,59240,59241,59242,59243,59244,59245,
+59246,59247,59248,59249,59250,59251,59252,59253,59254,59255,59256,59257,
+59258,59259,59260,59261,59262,59263,59264,59265,59266,59267,59268,59269,
+59270,59271,59272,59273,59274,59275,59276,59277,59278,59279,59280,59281,
+59282,59283,59284,59285,59286,59287,59288,59289,59290,59291,59292,59293,
+59294,59295,59296,59297,59298,59299,59300,59301,59302,59303,59304,59305,
+59306,59307,59308,59309,59310,59311,59312,59313,59314,59315,59316,59317,
+59318,59319,59320,59321,59322,59323,59324,59325,59326,59327,59328,59329,
+59330,59331,59332,59333,59334,59335,59336,59337,59338,59339,59340,59341,
+59342,59343,59344,59345,59346,59347,59348,59349,59350,59351,59352,59353,
+59354,59355,59356,59357,59358,59359,59360,59361,59362,59363,59364,59365,
+59366,59367,59368,59369,59370,59371,59372,59373,59374,59375,59376,59377,
+59378,59379,59380,59381,59382,59383,59384,59385,59386,59387,59388,59389,
+59390,59391,59392,59393,59394,59395,59396,59397,59398,59399,59400,59401,
+59402,59403,59404,59405,59406,59407,59408,59409,59410,59411,59412,59413,
+59414,59415,59416,59417,59418,59419,59420,59421,59422,59423,59424,59425,
+59426,59427,59428,59429,59430,59431,59432,59433,59434,59435,59436,59437,
+59438,59439,59440,59441,59442,59443,59444,59445,59446,59447,59448,59449,
+59450,59451,59452,59453,59454,59455,59456,59457,59458,59459,59460,59461,
+59462,59463,59464,59465,59466,59467,59468,59469,59470,59471,59472,59473,
+59474,59475,59476,59477,59478,59479,59480,59481,59482,59483,59484,59485,
+59486,59487,59488,59489,59490,59491,59492,59493,59494,59495,59496,59497,
+59498,59499,59500,59501,59502,59503,59504,59505,59506,59507,59508,59509,
+59510,59511,59512,59513,59514,59515,59516,59517,59518,59519,59520,59521,
+59522,59523,59524,59525,59526,59527,59528,59529,59530,59531,59532,59533,
+59534,59535,59536,59537,59538,59539,59540,59541,59542,59543,59544,59545,
+59546,59547,59548,59549,59550,59551,59552,59553,59554,59555,59556,59557,
+59558,59559,59560,59561,59562,59563,59564,59565,59566,59567,59568,59569,
+59570,59571,59572,59573,59574,59575,59576,59577,59578,59579,59580,59581,
+59582,59583,59584,59585,59586,59587,59588,59589,59590,59591,59592,59593,
+59594,59595,59596,59597,59598,59599,59600,59601,59602,59603,59604,59605,
+59606,59607,59608,59609,59610,59611,59612,59613,59614,59615,59616,59617,
+59618,59619,59620,59621,59622,59623,59624,59625,59626,59627,59628,59629,
+59630,59631,59632,59633,59634,59635,59636,59637,59638,59639,59640,59641,
+59642,59643,59644,59645,59646,59647,59648,59649,59650,59651,59652,59653,
+59654,59655,59656,59657,59658,59659,59660,59661,59662,59663,59664,59665,
+59666,59667,59668,59669,59670,59671,59672,59673,59674,59675,59676,59677,
+59678,59679,59680,59681,59682,59683,59684,59685,59686,59687,59688,59689,
+59690,59691,59692,59693,59694,59695,59696,59697,59698,59699,59700,59701,
+59702,59703,59704,59705,59706,59707,59708,59709,59710,59711,59712,59713,
+59714,59715,59716,59717,59718,59719,59720,59721,59722,59723,59724,59725,
+59726,59727,59728,59729,59730,59731,59732,59733,59734,59735,59736,59737,
+59738,59739,59740,59741,59742,59743,59744,59745,59746,59747,59748,59749,
+59750,59751,59752,59753,59754,59755,59756,59757,59758,59759,59760,59761,
+59762,59763,59764,59765,59766,59767,59768,59769,59770,59771,59772,59773,
+59774,59775,59776,59777,59778,59779,59780,59781,59782,59783,59784,59785,
+59786,59787,59788,59789,59790,59791,59792,59793,59794,59795,59796,59797,
+59798,59799,59800,59801,59802,59803,59804,59805,59806,59807,59808,59809,
+59810,59811,59812,59813,59814,59815,59816,59817,59818,59819,59820,59821,
+59822,59823,59824,59825,59826,59827,59828,59829,59830,59831,59832,59833,
+59834,59835,59836,59837,59838,59839,59840,59841,59842,59843,59844,59845,
+59846,59847,59848,59849,59850,59851,59852,59853,59854,59855,59856,59857,
+59858,59859,59860,59861,59862,59863,59864,59865,59866,59867,59868,59869,
+59870,59871,59872,59873,59874,59875,59876,59877,59878,59879,59880,59881,
+59882,59883,59884,59885,59886,59887,59888,59889,59890,59891,59892,59893,
+59894,59895,59896,59897,59898,59899,59900,59901,59902,59903,59904,59905,
+59906,59907,59908,59909,59910,59911,59912,59913,59914,59915,59916,59917,
+59918,59919,59920,59921,59922,59923,59924,59925,59926,59927,59928,59929,
+59930,59931,59932,59933,59934,59935,59936,59937,59938,59939,59940,59941,
+59942,59943,59944,59945,59946,59947,59948,59949,59950,59951,59952,59953,
+59954,59955,59956,59957,59958,59959,59960,59961,59962,59963,59964,59965,
+59966,59967,59968,59969,59970,59971,59972,59973,59974,59975,59976,59977,
+59978,59979,59980,59981,59982,59983,59984,59985,59986,59987,59988,59989,
+59990,59991,59992,59993,59994,59995,59996,59997,59998,59999,60000,60001,
+60002,60003,60004,60005,60006,60007,60008,60009,60010,60011,60012,60013,
+60014,60015,60016,60017,60018,60019,60020,60021,60022,60023,60024,60025,
+60026,60027,60028,60029,60030,60031,60032,60033,60034,60035,60036,60037,
+60038,60039,60040,60041,60042,60043,60044,60045,60046,60047,60048,60049,
+60050,60051,60052,60053,60054,60055,60056,60057,60058,60059,60060,60061,
+60062,60063,60064,60065,60066,60067,60068,60069,60070,60071,60072,60073,
+60074,60075,60076,60077,60078,60079,60080,60081,60082,60083,60084,60085,
+60086,60087,60088,60089,60090,60091,60092,60093,60094,60095,60096,60097,
+60098,60099,60100,60101,60102,60103,60104,60105,60106,60107,60108,60109,
+60110,60111,60112,60113,60114,60115,60116,60117,60118,60119,60120,60121,
+60122,60123,60124,60125,60126,60127,60128,60129,60130,60131,60132,60133,
+60134,60135,60136,60137,60138,60139,60140,60141,60142,60143,60144,60145,
+60146,60147,60148,60149,60150,60151,60152,60153,60154,60155,60156,60157,
+60158,60159,60160,60161,60162,60163,60164,60165,60166,60167,60168,60169,
+60170,60171,60172,60173,60174,60175,60176,60177,60178,60179,60180,60181,
+60182,60183,60184,60185,60186,60187,60188,60189,60190,60191,60192,60193,
+60194,60195,60196,60197,60198,60199,60200,60201,60202,60203,60204,60205,
+60206,60207,60208,60209,60210,60211,60212,60213,60214,60215,60216,60217,
+60218,60219,60220,60221,60222,60223,60224,60225,60226,60227,60228,60229,
+60230,60231,60232,60233,60234,60235,60236,60237,60238,60239,60240,60241,
+60242,60243,60244,60245,60246,60247,60248,60249,60250,60251,60252,60253,
+60254,60255,60256,60257,60258,60259,60260,60261,60262,60263,60264,60265,
+60266,60267,60268,60269,60270,60271,60272,60273,60274,60275,60276,60277,
+60278,60279,60280,60281,60282,60283,60284,60285,60286,60287,60288,60289,
+60290,60291,60292,60293,60294,60295,60296,60297,60298,60299,60300,60301,
+60302,60303,60304,60305,60306,60307,60308,60309,60310,60311,60312,60313,
+60314,60315,60316,60317,60318,60319,60320,60321,60322,60323,60324,60325,
+60326,60327,60328,60329,60330,60331,60332,60333,60334,60335,60336,60337,
+60338,60339,60340,60341,60342,60343,60344,60345,60346,60347,60348,60349,
+60350,60351,60352,60353,60354,60355,60356,60357,60358,60359,60360,60361,
+60362,60363,60364,60365,60366,60367,60368,60369,60370,60371,60372,60373,
+60374,60375,60376,60377,60378,60379,60380,60381,60382,60383,60384,60385,
+60386,60387,60388,60389,60390,60391,60392,60393,60394,60395,60396,60397,
+60398,60399,60400,60401,60402,60403,60404,60405,60406,60407,60408,60409,
+60410,60411,60412,60413,60414,60415,60416,60417,60418,60419,60420,60421,
+60422,60423,60424,60425,60426,60427,60428,60429,60430,60431,60432,60433,
+60434,60435,60436,60437,60438,60439,60440,60441,60442,60443,60444,60445,
+60446,60447,60448,60449,60450,60451,60452,60453,60454,60455,60456,60457,
+60458,60459,60460,60461,60462,60463,60464,60465,60466,60467,60468,60469,
+60470,60471,60472,60473,60474,60475,60476,60477,60478,60479,60480,60481,
+60482,60483,60484,60485,60486,60487,60488,60489,60490,60491,60492,60493,
+60494,60495,60496,60497,60498,60499,60500,60501,60502,60503,60504,60505,
+60506,60507,60508,60509,60510,60511,60512,60513,60514,60515,60516,60517,
+60518,60519,60520,60521,60522,60523,60524,60525,60526,60527,60528,60529,
+60530,60531,60532,60533,60534,60535,60536,60537,60538,60539,60540,60541,
+60542,60543,60544,60545,60546,60547,60548,60549,60550,60551,60552,60553,
+60554,60555,60556,60557,60558,60559,60560,60561,60562,60563,60564,60565,
+60566,60567,60568,60569,60570,60571,60572,60573,60574,60575,60576,60577,
+60578,60579,60580,60581,60582,60583,60584,60585,60586,60587,60588,60589,
+60590,60591,60592,60593,60594,60595,60596,60597,60598,60599,60600,60601,
+60602,60603,60604,60605,60606,60607,60608,60609,60610,60611,60612,60613,
+60614,60615,60616,60617,60618,60619,60620,60621,60622,60623,60624,60625,
+60626,60627,60628,60629,60630,60631,60632,60633,60634,60635,60636,60637,
+60638,60639,60640,60641,60642,60643,60644,60645,60646,60647,60648,60649,
+60650,60651,60652,60653,60654,60655,60656,60657,60658,60659,60660,60661,
+60662,60663,60664,60665,60666,60667,60668,60669,60670,60671,60672,60673,
+60674,60675,60676,60677,60678,60679,60680,60681,60682,60683,60684,60685,
+60686,60687,60688,60689,60690,60691,60692,60693,60694,60695,60696,60697,
+60698,60699,60700,60701,60702,60703,60704,60705,60706,60707,60708,60709,
+60710,60711,60712,60713,60714,60715,60716,60717,60718,60719,60720,60721,
+60722,60723,60724,60725,60726,60727,60728,60729,60730,60731,60732,60733,
+60734,60735,60736,60737,60738,60739,60740,60741,60742,60743,60744,60745,
+60746,60747,60748,60749,60750,60751,60752,60753,60754,60755,60756,60757,
+60758,60759,60760,60761,60762,60763,60764,60765,60766,60767,60768,60769,
+60770,60771,60772,60773,60774,60775,60776,60777,60778,60779,60780,60781,
+60782,60783,60784,60785,60786,60787,60788,60789,60790,60791,60792,60793,
+60794,60795,60796,60797,60798,60799,60800,60801,60802,60803,60804,60805,
+60806,60807,60808,60809,60810,60811,60812,60813,60814,60815,60816,60817,
+60818,60819,60820,60821,60822,60823,60824,60825,60826,60827,60828,60829,
+60830,60831,60832,60833,60834,60835,60836,60837,60838,60839,60840,60841,
+60842,60843,60844,60845,60846,60847,60848,60849,60850,60851,60852,60853,
+60854,60855,60856,60857,60858,60859,60860,60861,60862,60863,60864,60865,
+60866,60867,60868,60869,60870,60871,60872,60873,60874,60875,60876,60877,
+60878,60879,60880,60881,60882,60883,60884,60885,60886,60887,60888,60889,
+60890,60891,60892,60893,60894,60895,60896,60897,60898,60899,60900,60901,
+60902,60903,60904,60905,60906,60907,60908,60909,60910,60911,60912,60913,
+60914,60915,60916,60917,60918,60919,60920,60921,60922,60923,60924,60925,
+60926,60927,60928,60929,60930,60931,60932,60933,60934,60935,60936,60937,
+60938,60939,60940,60941,60942,60943,60944,60945,60946,60947,60948,60949,
+60950,60951,60952,60953,60954,60955,60956,60957,60958,60959,60960,60961,
+60962,60963,60964,60965,60966,60967,60968,60969,60970,60971,60972,60973,
+60974,60975,60976,60977,60978,60979,60980,60981,60982,60983,60984,60985,
+60986,60987,60988,60989,60990,60991,60992,60993,60994,60995,60996,60997,
+60998,60999,61000,61001,61002,61003,61004,61005,61006,61007,61008,61009,
+61010,61011,61012,61013,61014,61015,61016,61017,61018,61019,61020,61021,
+61022,61023,61024,61025,61026,61027,61028,61029,61030,61031,61032,61033,
+61034,61035,61036,61037,61038,61039,61040,61041,61042,61043,61044,61045,
+61046,61047,61048,61049,61050,61051,61052,61053,61054,61055,61056,61057,
+61058,61059,61060,61061,61062,61063,61064,61065,61066,61067,61068,61069,
+61070,61071,61072,61073,61074,61075,61076,61077,61078,61079,61080,61081,
+61082,61083,61084,61085,61086,61087,61088,61089,61090,61091,61092,61093,
+61094,61095,61096,61097,61098,61099,61100,61101,61102,61103,61104,61105,
+61106,61107,61108,61109,61110,61111,61112,61113,61114,61115,61116,61117,
+61118,61119,61120,61121,61122,61123,61124,61125,61126,61127,61128,61129,
+61130,61131,61132,61133,61134,61135,61136,61137,61138,61139,61140,61141,
+61142,61143,61144,61145,61146,61147,61148,61149,61150,61151,61152,61153,
+61154,61155,61156,61157,61158,61159,61160,61161,61162,61163,61164,61165,
+61166,61167,61168,61169,61170,61171,61172,61173,61174,61175,61176,61177,
+61178,61179,61180,61181,61182,61183,61184,61185,61186,61187,61188,61189,
+61190,61191,61192,61193,61194,61195,61196,61197,61198,61199,61200,61201,
+61202,61203,61204,61205,61206,61207,61208,61209,61210,61211,61212,61213,
+61214,61215,61216,61217,61218,61219,61220,61221,61222,61223,61224,61225,
+61226,61227,61228,61229,61230,61231,61232,61233,61234,61235,61236,61237,
+61238,61239,61240,61241,61242,61243,61244,61245,61246,61247,61248,61249,
+61250,61251,61252,61253,61254,61255,61256,61257,61258,61259,61260,61261,
+61262,61263,61264,61265,61266,61267,61268,61269,61270,61271,61272,61273,
+61274,61275,61276,61277,61278,61279,61280,61281,61282,61283,61284,61285,
+61286,61287,61288,61289,61290,61291,61292,61293,61294,61295,61296,61297,
+61298,61299,61300,61301,61302,61303,61304,61305,61306,61307,61308,61309,
+61310,61311,61312,61313,61314,61315,61316,61317,61318,61319,61320,61321,
+61322,61323,61324,61325,61326,61327,61328,61329,61330,61331,61332,61333,
+61334,61335,61336,61337,61338,61339,61340,61341,61342,61343,61344,61345,
+61346,61347,61348,61349,61350,61351,61352,61353,61354,61355,61356,61357,
+61358,61359,61360,61361,61362,61363,61364,61365,61366,61367,61368,61369,
+61370,61371,61372,61373,61374,61375,61376,61377,61378,61379,61380,61381,
+61382,61383,61384,61385,61386,61387,61388,61389,61390,61391,61392,61393,
+61394,61395,61396,61397,61398,61399,61400,61401,61402,61403,61404,61405,
+61406,61407,61408,61409,61410,61411,61412,61413,61414,61415,61416,61417,
+61418,61419,61420,61421,61422,61423,61424,61425,61426,61427,61428,61429,
+61430,61431,61432,61433,61434,61435,61436,61437,61438,61439,61440,61441,
+61442,61443,61444,61445,61446,61447,61448,61449,61450,61451,61452,61453,
+61454,61455,61456,61457,61458,61459,61460,61461,61462,61463,61464,61465,
+61466,61467,61468,61469,61470,61471,61472,61473,61474,61475,61476,61477,
+61478,61479,61480,61481,61482,61483,61484,61485,61486,61487,61488,61489,
+61490,61491,61492,61493,61494,61495,61496,61497,61498,61499,61500,61501,
+61502,61503,61504,61505,61506,61507,61508,61509,61510,61511,61512,61513,
+61514,61515,61516,61517,61518,61519,61520,61521,61522,61523,61524,61525,
+61526,61527,61528,61529,61530,61531,61532,61533,61534,61535,61536,61537,
+61538,61539,61540,61541,61542,61543,61544,61545,61546,61547,61548,61549,
+61550,61551,61552,61553,61554,61555,61556,61557,61558,61559,61560,61561,
+61562,61563,61564,61565,61566,61567,61568,61569,61570,61571,61572,61573,
+61574,61575,61576,61577,61578,61579,61580,61581,61582,61583,61584,61585,
+61586,61587,61588,61589,61590,61591,61592,61593,61594,61595,61596,61597,
+61598,61599,61600,61601,61602,61603,61604,61605,61606,61607,61608,61609,
+61610,61611,61612,61613,61614,61615,61616,61617,61618,61619,61620,61621,
+61622,61623,61624,61625,61626,61627,61628,61629,61630,61631,61632,61633,
+61634,61635,61636,61637,61638,61639,61640,61641,61642,61643,61644,61645,
+61646,61647,61648,61649,61650,61651,61652,61653,61654,61655,61656,61657,
+61658,61659,61660,61661,61662,61663,61664,61665,61666,61667,61668,61669,
+61670,61671,61672,61673,61674,61675,61676,61677,61678,61679,61680,61681,
+61682,61683,61684,61685,61686,61687,61688,61689,61690,61691,61692,61693,
+61694,61695,61696,61697,61698,61699,61700,61701,61702,61703,61704,61705,
+61706,61707,61708,61709,61710,61711,61712,61713,61714,61715,61716,61717,
+61718,61719,61720,61721,61722,61723,61724,61725,61726,61727,61728,61729,
+61730,61731,61732,61733,61734,61735,61736,61737,61738,61739,61740,61741,
+61742,61743,61744,61745,61746,61747,61748,61749,61750,61751,61752,61753,
+61754,61755,61756,61757,61758,61759,61760,61761,61762,61763,61764,61765,
+61766,61767,61768,61769,61770,61771,61772,61773,61774,61775,61776,61777,
+61778,61779,61780,61781,61782,61783,61784,61785,61786,61787,61788,61789,
+61790,61791,61792,61793,61794,61795,61796,61797,61798,61799,61800,61801,
+61802,61803,61804,61805,61806,61807,61808,61809,61810,61811,61812,61813,
+61814,61815,61816,61817,61818,61819,61820,61821,61822,61823,61824,61825,
+61826,61827,61828,61829,61830,61831,61832,61833,61834,61835,61836,61837,
+61838,61839,61840,61841,61842,61843,61844,61845,61846,61847,61848,61849,
+61850,61851,61852,61853,61854,61855,61856,61857,61858,61859,61860,61861,
+61862,61863,61864,61865,61866,61867,61868,61869,61870,61871,61872,61873,
+61874,61875,61876,61877,61878,61879,61880,61881,61882,61883,61884,61885,
+61886,61887,61888,61889,61890,61891,61892,61893,61894,61895,61896,61897,
+61898,61899,61900,61901,61902,61903,61904,61905,61906,61907,61908,61909,
+61910,61911,61912,61913,61914,61915,61916,61917,61918,61919,61920,61921,
+61922,61923,61924,61925,61926,61927,61928,61929,61930,61931,61932,61933,
+61934,61935,61936,61937,61938,61939,61940,61941,61942,61943,61944,61945,
+61946,61947,61948,61949,61950,61951,61952,61953,61954,61955,61956,61957,
+61958,61959,61960,61961,61962,61963,61964,61965,61966,61967,61968,61969,
+61970,61971,61972,61973,61974,61975,61976,61977,61978,61979,61980,61981,
+61982,61983,61984,61985,61986,61987,61988,61989,61990,61991,61992,61993,
+61994,61995,61996,61997,61998,61999,62000,62001,62002,62003,62004,62005,
+62006,62007,62008,62009,62010,62011,62012,62013,62014,62015,62016,62017,
+62018,62019,62020,62021,62022,62023,62024,62025,62026,62027,62028,62029,
+62030,62031,62032,62033,62034,62035,62036,62037,62038,62039,62040,62041,
+62042,62043,62044,62045,62046,62047,62048,62049,62050,62051,62052,62053,
+62054,62055,62056,62057,62058,62059,62060,62061,62062,62063,62064,62065,
+62066,62067,62068,62069,62070,62071,62072,62073,62074,62075,62076,62077,
+62078,62079,62080,62081,62082,62083,62084,62085,62086,62087,62088,62089,
+62090,62091,62092,62093,62094,62095,62096,62097,62098,62099,62100,62101,
+62102,62103,62104,62105,62106,62107,62108,62109,62110,62111,62112,62113,
+62114,62115,62116,62117,62118,62119,62120,62121,62122,62123,62124,62125,
+62126,62127,62128,62129,62130,62131,62132,62133,62134,62135,62136,62137,
+62138,62139,62140,62141,62142,62143,62144,62145,62146,62147,62148,62149,
+62150,62151,62152,62153,62154,62155,62156,62157,62158,62159,62160,62161,
+62162,62163,62164,62165,62166,62167,62168,62169,62170,62171,62172,62173,
+62174,62175,62176,62177,62178,62179,62180,62181,62182,62183,62184,62185,
+62186,62187,62188,62189,62190,62191,62192,62193,62194,62195,62196,62197,
+62198,62199,62200,62201,62202,62203,62204,62205,62206,62207,62208,62209,
+62210,62211,62212,62213,62214,62215,62216,62217,62218,62219,62220,62221,
+62222,62223,62224,62225,62226,62227,62228,62229,62230,62231,62232,62233,
+62234,62235,62236,62237,62238,62239,62240,62241,62242,62243,62244,62245,
+62246,62247,62248,62249,62250,62251,62252,62253,62254,62255,62256,62257,
+62258,62259,62260,62261,62262,62263,62264,62265,62266,62267,62268,62269,
+62270,62271,62272,62273,62274,62275,62276,62277,62278,62279,62280,62281,
+62282,62283,62284,62285,62286,62287,62288,62289,62290,62291,62292,62293,
+62294,62295,62296,62297,62298,62299,62300,62301,62302,62303,62304,62305,
+62306,62307,62308,62309,62310,62311,62312,62313,62314,62315,62316,62317,
+62318,62319,62320,62321,62322,62323,62324,62325,62326,62327,62328,62329,
+62330,62331,62332,62333,62334,62335,62336,62337,62338,62339,62340,62341,
+62342,62343,62344,62345,62346,62347,62348,62349,62350,62351,62352,62353,
+62354,62355,62356,62357,62358,62359,62360,62361,62362,62363,62364,62365,
+62366,62367,62368,62369,62370,62371,62372,62373,62374,62375,62376,62377,
+62378,62379,62380,62381,62382,62383,62384,62385,62386,62387,62388,62389,
+62390,62391,62392,62393,62394,62395,62396,62397,62398,62399,62400,62401,
+62402,62403,62404,62405,62406,62407,62408,62409,62410,62411,62412,62413,
+62414,62415,62416,62417,62418,62419,62420,62421,62422,62423,62424,62425,
+62426,62427,62428,62429,62430,62431,62432,62433,62434,62435,62436,62437,
+62438,62439,62440,62441,62442,62443,62444,62445,62446,62447,62448,62449,
+62450,62451,62452,62453,62454,62455,62456,62457,62458,62459,62460,62461,
+62462,62463,62464,62465,62466,62467,62468,62469,62470,62471,62472,62473,
+62474,62475,62476,62477,62478,62479,62480,62481,62482,62483,62484,62485,
+62486,62487,62488,62489,62490,62491,62492,62493,62494,62495,62496,62497,
+62498,62499,62500,62501,62502,62503,62504,62505,62506,62507,62508,62509,
+62510,62511,62512,62513,62514,62515,62516,62517,62518,62519,62520,62521,
+62522,62523,62524,62525,62526,62527,62528,62529,62530,62531,62532,62533,
+62534,62535,62536,62537,62538,62539,62540,62541,62542,62543,62544,62545,
+62546,62547,62548,62549,62550,62551,62552,62553,62554,62555,62556,62557,
+62558,62559,62560,62561,62562,62563,62564,62565,62566,62567,62568,62569,
+62570,62571,62572,62573,62574,62575,62576,62577,62578,62579,62580,62581,
+62582,62583,62584,62585,62586,62587,62588,62589,62590,62591,62592,62593,
+62594,62595,62596,62597,62598,62599,62600,62601,62602,62603,62604,62605,
+62606,62607,62608,62609,62610,62611,62612,62613,62614,62615,62616,62617,
+62618,62619,62620,62621,62622,62623,62624,62625,62626,62627,62628,62629,
+62630,62631,62632,62633,62634,62635,62636,62637,62638,62639,62640,62641,
+62642,62643,62644,62645,62646,62647,62648,62649,62650,62651,62652,62653,
+62654,62655,62656,62657,62658,62659,62660,62661,62662,62663,62664,62665,
+62666,62667,62668,62669,62670,62671,62672,62673,62674,62675,62676,62677,
+62678,62679,62680,62681,62682,62683,62684,62685,62686,62687,62688,62689,
+62690,62691,62692,62693,62694,62695,62696,62697,62698,62699,62700,62701,
+62702,62703,62704,62705,62706,62707,62708,62709,62710,62711,62712,62713,
+62714,62715,62716,62717,62718,62719,62720,62721,62722,62723,62724,62725,
+62726,62727,62728,62729,62730,62731,62732,62733,62734,62735,62736,62737,
+62738,62739,62740,62741,62742,62743,62744,62745,62746,62747,62748,62749,
+62750,62751,62752,62753,62754,62755,62756,62757,62758,62759,62760,62761,
+62762,62763,62764,62765,62766,62767,62768,62769,62770,62771,62772,62773,
+62774,62775,62776,62777,62778,62779,62780,62781,62782,62783,62784,62785,
+62786,62787,62788,62789,62790,62791,62792,62793,62794,62795,62796,62797,
+62798,62799,62800,62801,62802,62803,62804,62805,62806,62807,62808,62809,
+62810,62811,62812,62813,62814,62815,62816,62817,62818,62819,62820,62821,
+62822,62823,62824,62825,62826,62827,62828,62829,62830,62831,62832,62833,
+62834,62835,62836,62837,62838,62839,62840,62841,62842,62843,62844,62845,
+62846,62847,62848,62849,62850,62851,62852,62853,62854,62855,62856,62857,
+62858,62859,62860,62861,62862,62863,62864,62865,62866,62867,62868,62869,
+62870,62871,62872,62873,62874,62875,62876,62877,62878,62879,62880,62881,
+62882,62883,62884,62885,62886,62887,62888,62889,62890,62891,62892,62893,
+62894,62895,62896,62897,62898,62899,62900,62901,62902,62903,62904,62905,
+62906,62907,62908,62909,62910,62911,62912,62913,62914,62915,62916,62917,
+62918,62919,62920,62921,62922,62923,62924,62925,62926,62927,62928,62929,
+62930,62931,62932,62933,62934,62935,62936,62937,62938,62939,62940,62941,
+62942,62943,62944,62945,62946,62947,62948,62949,62950,62951,62952,62953,
+62954,62955,62956,62957,62958,62959,62960,62961,62962,62963,62964,62965,
+62966,62967,62968,62969,62970,62971,62972,62973,62974,62975,62976,62977,
+62978,62979,62980,62981,62982,62983,62984,62985,62986,62987,62988,62989,
+62990,62991,62992,62993,62994,62995,62996,62997,62998,62999,63000,63001,
+63002,63003,63004,63005,63006,63007,63008,63009,63010,63011,63012,63013,
+63014,63015,63016,63017,63018,63019,63020,63021,63022,63023,63024,63025,
+63026,63027,63028,63029,63030,63031,63032,63033,63034,63035,63036,63037,
+63038,63039,63040,63041,63042,63043,63044,63045,63046,63047,63048,63049,
+63050,63051,63052,63053,63054,63055,63056,63057,63058,63059,63060,63061,
+63062,63063,63064,63065,63066,63067,63068,63069,63070,63071,63072,63073,
+63074,63075,63076,63077,63078,63079,63080,63081,63082,63083,63084,63085,
+63086,63087,63088,63089,63090,63091,63092,63093,63094,63095,63096,63097,
+63098,63099,63100,63101,63102,63103,63104,63105,63106,63107,63108,63109,
+63110,63111,63112,63113,63114,63115,63116,63117,63118,63119,63120,63121,
+63122,63123,63124,63125,63126,63127,63128,63129,63130,63131,63132,63133,
+63134,63135,63136,63137,63138,63139,63140,63141,63142,63143,63144,63145,
+63146,63147,63148,63149,63150,63151,63152,63153,63154,63155,63156,63157,
+63158,63159,63160,63161,63162,63163,63164,63165,63166,63167,63168,63169,
+63170,63171,63172,63173,63174,63175,63176,63177,63178,63179,63180,63181,
+63182,63183,63184,63185,63186,63187,63188,63189,63190,63191,63192,63193,
+63194,63195,63196,63197,63198,63199,63200,63201,63202,63203,63204,63205,
+63206,63207,63208,63209,63210,63211,63212,63213,63214,63215,63216,63217,
+63218,63219,63220,63221,63222,63223,63224,63225,63226,63227,63228,63229,
+63230,63231,63232,63233,63234,63235,63236,63237,63238,63239,63240,63241,
+63242,63243,63244,63245,63246,63247,63248,63249,63250,63251,63252,63253,
+63254,63255,63256,63257,63258,63259,63260,63261,63262,63263,63264,63265,
+63266,63267,63268,63269,63270,63271,63272,63273,63274,63275,63276,63277,
+63278,63279,63280,63281,63282,63283,63284,63285,63286,63287,63288,63289,
+63290,63291,63292,63293,63294,63295,63296,63297,63298,63299,63300,63301,
+63302,63303,63304,63305,63306,63307,63308,63309,63310,63311,63312,63313,
+63314,63315,63316,63317,63318,63319,63320,63321,63322,63323,63324,63325,
+63326,63327,63328,63329,63330,63331,63332,63333,63334,63335,63336,63337,
+63338,63339,63340,63341,63342,63343,63344,63345,63346,63347,63348,63349,
+63350,63351,63352,63353,63354,63355,63356,63357,63358,63359,63360,63361,
+63362,63363,63364,63365,63366,63367,63368,63369,63370,63371,63372,63373,
+63374,63375,63376,63377,63378,63379,63380,63381,63382,63383,63384,63385,
+63386,63387,63388,63389,63390,63391,63392,63393,63394,63395,63396,63397,
+63398,63399,63400,63401,63402,63403,63404,63405,63406,63407,63408,63409,
+63410,63411,63412,63413,63414,63415,63416,63417,63418,63419,63420,63421,
+63422,63423,63424,63425,63426,63427,63428,63429,63430,63431,63432,63433,
+63434,63435,63436,63437,63438,63439,63440,63441,63442,63443,63444,63445,
+63446,63447,63448,63449,63450,63451,63452,63453,63454,63455,63456,63457,
+63458,63459,63460,63461,63462,63463,63464,63465,63466,63467,63468,63469,
+63470,63471,63472,63473,63474,63475,63476,63477,63478,63479,63480,63481,
+63482,63483,63484,63485,63486,63487,63488,63489,63490,63491,63492,63493,
+63494,63495,63496,63497,63498,63499,63500,63501,63502,63503,63504,63505,
+63506,63507,63508,63509,63510,63511,63512,63513,63514,63515,63516,63517,
+63518,63519,63520,63521,63522,63523,63524,63525,63526,63527,63528,63529,
+63530,63531,63532,63533,63534,63535,63536,63537,63538,63539,63540,63541,
+63542,63543,63544,63545,63546,63547,63548,63549,63550,63551,63552,63553,
+63554,63555,63556,63557,63558,63559,63560,63561,63562,63563,63564,63565,
+63566,63567,63568,63569,63570,63571,63572,63573,63574,63575,63576,63577,
+63578,63579,63580,63581,63582,63583,63584,63585,63586,63587,63588,63589,
+63590,63591,63592,63593,63594,63595,63596,63597,63598,63599,63600,63601,
+63602,63603,63604,63605,63606,63607,63608,63609,63610,63611,63612,63613,
+63614,63615,63616,63617,63618,63619,63620,63621,63622,63623,63624,63625,
+63626,63627,63628,63629,63630,63631,63632,63633,63634,63635,63636,63637,
+63638,63639,63640,63641,63642,63643,63644,63645,63646,63647,63648,63649,
+63650,63651,63652,63653,63654,63655,63656,63657,63658,63659,63660,63661,
+63662,63663,63664,63665,63666,63667,63668,63669,63670,63671,63672,63673,
+63674,63675,63676,63677,63678,63679,63680,63681,63682,63683,63684,63685,
+63686,63687,63688,63689,63690,63691,63692,63693,63694,63695,63696,63697,
+63698,63699,63700,63701,63702,63703,63704,63705,63706,63707,63708,63709,
+63710,63711,63712,63713,63714,63715,63716,63717,63718,63719,63720,63721,
+63722,63723,63724,63725,63726,63727,63728,63729,63730,63731,63732,63733,
+63734,63735,63736,63737,63738,63739,63740,63741,63742,63743,63744,63745,
+63746,63747,63748,63749,63750,63751,63752,63753,63754,63755,63756,63757,
+63758,63759,63760,63761,63762,63763,63764,63765,63766,63767,63768,63769,
+63770,63771,63772,63773,63774,63775,63776,63777,63778,63779,63780,63781,
+63782,63783,63784,63785,63786,63787,63788,63789,63790,63791,63792,63793,
+63794,63795,63796,63797,63798,63799,63800,63801,63802,63803,63804,63805,
+63806,63807,63808,63809,63810,63811,63812,63813,63814,63815,63816,63817,
+63818,63819,63820,63821,63822,63823,63824,63825,63826,63827,63828,63829,
+63830,63831,63832,63833,63834,63835,63836,63837,63838,63839,63840,63841,
+63842,63843,63844,63845,63846,63847,63848,63849,63850,63851,63852,63853,
+63854,63855,63856,63857,63858,63859,63860,63861,63862,63863,63864,63865,
+63866,63867,63868,63869,63870,63871,63872,63873,63874,63875,63876,63877,
+63878,63879,63880,63881,63882,63883,63884,63885,63886,63887,63888,63889,
+63890,63891,63892,63893,63894,63895,63896,63897,63898,63899,63900,63901,
+63902,63903,63904,63905,63906,63907,63908,63909,63910,63911,63912,63913,
+63914,63915,63916,63917,63918,63919,63920,63921,63922,63923,63924,63925,
+63926,63927,63928,63929,63930,63931,63932,63933,63934,63935,63936,63937,
+63938,63939,63940,63941,63942,63943,63944,63945,63946,63947,63948,63949,
+63950,63951,63952,63953,63954,63955,63956,63957,63958,63959,63960,63961,
+63962,63963,63964,63965,63966,63967,63968,63969,63970,63971,63972,63973,
+63974,63975,63976,63977,63978,63979,63980,63981,63982,63983,63984,63985,
+63986,63987,63988,63989,63990,63991,63992,63993,63994,63995,63996,63997,
+63998,63999,64000,64001,64002,64003,64004,64005,64006,64007,64008,64009,
+64010,64011,64012,64013,64014,64015,64016,64017,64018,64019,64020,64021,
+64022,64023,64024,64025,64026,64027,64028,64029,64030,64031,64032,64033,
+64034,64035,64036,64037,64038,64039,64040,64041,64042,64043,64044,64045,
+64046,64047,64048,64049,64050,64051,64052,64053,64054,64055,64056,64057,
+64058,64059,64060,64061,64062,64063,64064,64065,64066,64067,64068,64069,
+64070,64071,64072,64073,64074,64075,64076,64077,64078,64079,64080,64081,
+64082,64083,64084,64085,64086,64087,64088,64089,64090,64091,64092,64093,
+64094,64095,64096,64097,64098,64099,64100,64101,64102,64103,64104,64105,
+64106,64107,64108,64109,64110,64111,64112,64113,64114,64115,64116,64117,
+64118,64119,64120,64121,64122,64123,64124,64125,64126,64127,64128,64129,
+64130,64131,64132,64133,64134,64135,64136,64137,64138,64139,64140,64141,
+64142,64143,64144,64145,64146,64147,64148,64149,64150,64151,64152,64153,
+64154,64155,64156,64157,64158,64159,64160,64161,64162,64163,64164,64165,
+64166,64167,64168,64169,64170,64171,64172,64173,64174,64175,64176,64177,
+64178,64179,64180,64181,64182,64183,64184,64185,64186,64187,64188,64189,
+64190,64191,64192,64193,64194,64195,64196,64197,64198,64199,64200,64201,
+64202,64203,64204,64205,64206,64207,64208,64209,64210,64211,64212,64213,
+64214,64215,64216,64217,64218,64219,64220,64221,64222,64223,64224,64225,
+64226,64227,64228,64229,64230,64231,64232,64233,64234,64235,64236,64237,
+64238,64239,64240,64241,64242,64243,64244,64245,64246,64247,64248,64249,
+64250,64251,64252,64253,64254,64255,64256,64257,64258,64259,64260,64261,
+64262,64263,64264,64265,64266,64267,64268,64269,64270,64271,64272,64273,
+64274,64275,64276,64277,64278,64279,64280,64281,64282,64283,64284,64285,
+64286,64287,64288,64289,64290,64291,64292,64293,64294,64295,64296,64297,
+64298,64299,64300,64301,64302,64303,64304,64305,64306,64307,64308,64309,
+64310,64311,64312,64313,64314,64315,64316,64317,64318,64319,64320,64321,
+64322,64323,64324,64325,64326,64327,64328,64329,64330,64331,64332,64333,
+64334,64335,64336,64337,64338,64339,64340,64341,64342,64343,64344,64345,
+64346,64347,64348,64349,64350,64351,64352,64353,64354,64355,64356,64357,
+64358,64359,64360,64361,64362,64363,64364,64365,64366,64367,64368,64369,
+64370,64371,64372,64373,64374,64375,64376,64377,64378,64379,64380,64381,
+64382,64383,64384,64385,64386,64387,64388,64389,64390,64391,64392,64393,
+64394,64395,64396,64397,64398,64399,64400,64401,64402,64403,64404,64405,
+64406,64407,64408,64409,64410,64411,64412,64413,64414,64415,64416,64417,
+64418,64419,64420,64421,64422,64423,64424,64425,64426,64427,64428,64429,
+64430,64431,64432,64433,64434,64435,64436,64437,64438,64439,64440,64441,
+64442,64443,64444,64445,64446,64447,64448,64449,64450,64451,64452,64453,
+64454,64455,64456,64457,64458,64459,64460,64461,64462,64463,64464,64465,
+64466,64467,64468,64469,64470,64471,64472,64473,64474,64475,64476,64477,
+64478,64479,64480,64481,64482,64483,64484,64485,64486,64487,64488,64489,
+64490,64491,64492,64493,64494,64495,64496,64497,64498,64499,64500,64501,
+64502,64503,64504,64505,64506,64507,64508,64509,64510,64511,64512,64513,
+64514,64515,64516,64517,64518,64519,64520,64521,64522,64523,64524,64525,
+64526,64527,64528,64529,64530,64531,64532,64533,64534,64535,64536,64537,
+64538,64539,64540,64541,64542,64543,64544,64545,64546,64547,64548,64549,
+64550,64551,64552,64553,64554,64555,64556,64557,64558,64559,64560,64561,
+64562,64563,64564,64565,64566,64567,64568,64569,64570,64571,64572,64573,
+64574,64575,64576,64577,64578,64579,64580,64581,64582,64583,64584,64585,
+64586,64587,64588,64589,64590,64591,64592,64593,64594,64595,64596,64597,
+64598,64599,64600,64601,64602,64603,64604,64605,64606,64607,64608,64609,
+64610,64611,64612,64613,64614,64615,64616,64617,64618,64619,64620,64621,
+64622,64623,64624,64625,64626,64627,64628,64629,64630,64631,64632,64633,
+64634,64635,64636,64637,64638,64639,64640,64641,64642,64643,64644,64645,
+64646,64647,64648,64649,64650,64651,64652,64653,64654,64655,64656,64657,
+64658,64659,64660,64661,64662,64663,64664,64665,64666,64667,64668,64669,
+64670,64671,64672,64673,64674,64675,64676,64677,64678,64679,64680,64681,
+64682,64683,64684,64685,64686,64687,64688,64689,64690,64691,64692,64693,
+64694,64695,64696,64697,64698,64699,64700,64701,64702,64703,64704,64705,
+64706,64707,64708,64709,64710,64711,64712,64713,64714,64715,64716,64717,
+64718,64719,64720,64721,64722,64723,64724,64725,64726,64727,64728,64729,
+64730,64731,64732,64733,64734,64735,64736,64737,64738,64739,64740,64741,
+64742,64743,64744,64745,64746,64747,64748,64749,64750,64751,64752,64753,
+64754,64755,64756,64757,64758,64759,64760,64761,64762,64763,64764,64765,
+64766,64767,64768,64769,64770,64771,64772,64773,64774,64775,64776,64777,
+64778,64779,64780,64781,64782,64783,64784,64785,64786,64787,64788,64789,
+64790,64791,64792,64793,64794,64795,64796,64797,64798,64799,64800,64801,
+64802,64803,64804,64805,64806,64807,64808,64809,64810,64811,64812,64813,
+64814,64815,64816,64817,64818,64819,64820,64821,64822,64823,64824,64825,
+64826,64827,64828,64829,64830,64831,64832,64833,64834,64835,64836,64837,
+64838,64839,64840,64841,64842,64843,64844,64845,64846,64847,64848,64849,
+64850,64851,64852,64853,64854,64855,64856,64857,64858,64859,64860,64861,
+64862,64863,64864,64865,64866,64867,64868,64869,64870,64871,64872,64873,
+64874,64875,64876,64877,64878,64879,64880,64881,64882,64883,64884,64885,
+64886,64887,64888,64889,64890,64891,64892,64893,64894,64895,64896,64897,
+64898,64899,64900,64901,64902,64903,64904,64905,64906,64907,64908,64909,
+64910,64911,64912,64913,64914,64915,64916,64917,64918,64919,64920,64921,
+64922,64923,64924,64925,64926,64927,64928,64929,64930,64931,64932,64933,
+64934,64935,64936,64937,64938,64939,64940,64941,64942,64943,64944,64945,
+64946,64947,64948,64949,64950,64951,64952,64953,64954,64955,64956,64957,
+64958,64959,64960,64961,64962,64963,64964,64965,64966,64967,64968,64969,
+64970,64971,64972,64973,64974,64975,64976,64977,64978,64979,64980,64981,
+64982,64983,64984,64985,64986,64987,64988,64989,64990,64991,64992,64993,
+64994,64995,64996,64997,64998,64999,65000,65001,65002,65003,65004,65005,
+65006,65007,65008,65009,65010,65011,65012,65013,65014,65015,65016,65017,
+65018,65019,65020,65021,65022,65023,65024,65025,65026,65027,65028,65029,
+65030,65031,65032,65033,65034,65035,65036,65037,65038,65039,65040,65041,
+65042,65043,65044,65045,65046,65047,65048,65049,65050,65051,65052,65053,
+65054,65055,65056,65057,65058,65059,65060,65061,65062,65063,65064,65065,
+65066,65067,65068,65069,65070,65071,65072,65073,65074,65075,65076,65077,
+65078,65079,65080,65081,65082,65083,65084,65085,65086,65087,65088,65089,
+65090,65091,65092,65093,65094,65095,65096,65097,65098,65099,65100,65101,
+65102,65103,65104,65105,65106,65107,65108,65109,65110,65111,65112,65113,
+65114,65115,65116,65117,65118,65119,65120,65121,65122,65123,65124,65125,
+65126,65127,65128,65129,65130,65131,65132,65133,65134,65135,65136,65137,
+65138,65139,65140,65141,65142,65143,65144,65145,65146,65147,65148,65149,
+65150,65151,65152,65153,65154,65155,65156,65157,65158,65159,65160,65161,
+65162,65163,65164,65165,65166,65167,65168,65169,65170,65171,65172,65173,
+65174,65175,65176,65177,65178,65179,65180,65181,65182,65183,65184,65185,
+65186,65187,65188,65189,65190,65191,65192,65193,65194,65195,65196,65197,
+65198,65199,65200,65201,65202,65203,65204,65205,65206,65207,65208,65209,
+65210,65211,65212,65213,65214,65215,65216,65217,65218,65219,65220,65221,
+65222,65223,65224,65225,65226,65227,65228,65229,65230,65231,65232,65233,
+65234,65235,65236,65237,65238,65239,65240,65241,65242,65243,65244,65245,
+65246,65247,65248,65249,65250,65251,65252,65253,65254,65255,65256,65257,
+65258,65259,65260,65261,65262,65263,65264,65265,65266,65267,65268,65269,
+65270,65271,65272,65273,65274,65275,65276,65277,65278,65279,65280,65281,
+65282,65283,65284,65285,65286,65287,65288,65289,65290,65291,65292,65293,
+65294,65295,65296,65297,65298,65299,65300,65301,65302,65303,65304,65305,
+65306,65307,65308,65309,65310,65311,65312,65313,65314,65315,65316,65317,
+65318,65319,65320,65321,65322,65323,65324,65325,65326,65327,65328,65329,
+65330,65331,65332,65333,65334,65335,65336,65337,65338,65339,65340,65341,
+65342,65343,65344,65313,65314,65315,65316,65317,65318,65319,65320,65321,
+65322,65323,65324,65325,65326,65327,65328,65329,65330,65331,65332,65333,
+65334,65335,65336,65337,65338,65371,65372,65373,65374,65375,65376,65377,
+65378,65379,65380,65381,65382,65383,65384,65385,65386,65387,65388,65389,
+65390,65391,65392,65393,65394,65395,65396,65397,65398,65399,65400,65401,
+65402,65403,65404,65405,65406,65407,65408,65409,65410,65411,65412,65413,
+65414,65415,65416,65417,65418,65419,65420,65421,65422,65423,65424,65425,
+65426,65427,65428,65429,65430,65431,65432,65433,65434,65435,65436,65437,
+65438,65439,65440,65441,65442,65443,65444,65445,65446,65447,65448,65449,
+65450,65451,65452,65453,65454,65455,65456,65457,65458,65459,65460,65461,
+65462,65463,65464,65465,65466,65467,65468,65469,65470,65471,65472,65473,
+65474,65475,65476,65477,65478,65479,65480,65481,65482,65483,65484,65485,
+65486,65487,65488,65489,65490,65491,65492,65493,65494,65495,65496,65497,
+65498,65499,65500,65501,65502,65503,65504,65505,65506,65507,65508,65509,
+65510,65511,65512,65513,65514,65515,65516,65517,65518,65519,65520,65521,
+65522,65523,65524,65525,65526,65527,65528,65529,65530,65531,65532,65533,
+65534,65535,
+};
+#endif
 #line 1 "duk_util_bitdecoder.c"
 /*
  *  Bitstream decoder.
@@ -64678,7 +87533,7 @@ const duk_uint8_t duk_unicode_caseconv_lc[616] = {
  * When reading past bitstream end, zeroes are shifted in.  The result
  * is signed to match duk_bd_decode_flagged.
  */
-duk_int32_t duk_bd_decode(duk_bitdecoder_ctx *ctx, duk_small_int_t bits) {
+DUK_INTERNAL duk_int32_t duk_bd_decode(duk_bitdecoder_ctx *ctx, duk_small_int_t bits) {
 	duk_small_int_t shift;
 	duk_uint32_t mask;
 	duk_uint32_t tmp;
@@ -64723,7 +87578,7 @@ duk_int32_t duk_bd_decode(duk_bitdecoder_ctx *ctx, duk_small_int_t bits) {
 	return tmp;
 }
 
-duk_small_int_t duk_bd_decode_flag(duk_bitdecoder_ctx *ctx) {
+DUK_INTERNAL duk_small_int_t duk_bd_decode_flag(duk_bitdecoder_ctx *ctx) {
 	return (duk_small_int_t) duk_bd_decode(ctx, 1);
 }
 
@@ -64731,14 +87586,13 @@ duk_small_int_t duk_bd_decode_flag(duk_bitdecoder_ctx *ctx) {
  * default value.  Return value is signed so that negative marker value can be
  * used by caller as a "not present" value.
  */
-duk_int32_t duk_bd_decode_flagged(duk_bitdecoder_ctx *ctx, duk_small_int_t bits, duk_int32_t def_value) {
+DUK_INTERNAL duk_int32_t duk_bd_decode_flagged(duk_bitdecoder_ctx *ctx, duk_small_int_t bits, duk_int32_t def_value) {
 	if (duk_bd_decode_flag(ctx)) {
 		return (duk_int32_t) duk_bd_decode(ctx, bits);
 	} else {
 		return def_value;
 	}
 }
-
 #line 1 "duk_util_bitencoder.c"
 /*
  *  Bitstream encoder.
@@ -64746,7 +87600,7 @@ duk_int32_t duk_bd_decode_flagged(duk_bitdecoder_ctx *ctx, duk_small_int_t bits,
 
 /* include removed: duk_internal.h */
 
-void duk_be_encode(duk_bitencoder_ctx *ctx, duk_uint32_t data, duk_small_int_t bits) {
+DUK_INTERNAL void duk_be_encode(duk_bitencoder_ctx *ctx, duk_uint32_t data, duk_small_int_t bits) {
 	duk_uint8_t tmp;
 
 	DUK_ASSERT(ctx != NULL);
@@ -64771,7 +87625,7 @@ void duk_be_encode(duk_bitencoder_ctx *ctx, duk_uint32_t data, duk_small_int_t b
 	}
 }
 
-void duk_be_finish(duk_bitencoder_ctx *ctx) {
+DUK_INTERNAL void duk_be_finish(duk_bitencoder_ctx *ctx) {
 	duk_small_int_t npad;
 
 	DUK_ASSERT(ctx != NULL);
@@ -64783,7 +87637,367 @@ void duk_be_finish(duk_bitencoder_ctx *ctx) {
 	}
 	DUK_ASSERT(ctx->currbits == 0);
 }
+#line 1 "duk_util_bufwriter.c"
+/*
+ *  Fast buffer writer with spare management.
+ */
+
+/* include removed: duk_internal.h */
+
+/*
+ *  Macro support functions (use only macros in calling code)
+ */
+
+DUK_LOCAL void duk__bw_update_ptrs(duk_hthread *thr, duk_bufwriter_ctx *bw_ctx, duk_size_t curr_offset, duk_size_t new_length) {
+	duk_uint8_t *p;
+
+	DUK_ASSERT(thr != NULL);
+	DUK_ASSERT(bw_ctx != NULL);
+	DUK_UNREF(thr);
+
+	p = (duk_uint8_t *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(thr->heap, bw_ctx->buf);
+	DUK_ASSERT(p != NULL || (DUK_HBUFFER_DYNAMIC_GET_SIZE(bw_ctx->buf) == 0 && curr_offset == 0 && new_length == 0));
+	bw_ctx->p = p + curr_offset;
+	bw_ctx->p_base = p;
+	bw_ctx->p_limit = p + new_length;
+}
+
+DUK_INTERNAL void duk_bw_init(duk_hthread *thr, duk_bufwriter_ctx *bw_ctx, duk_hbuffer_dynamic *h_buf) {
+
+	DUK_ASSERT(thr != NULL);
+	DUK_ASSERT(bw_ctx != NULL);
+	DUK_ASSERT(h_buf != NULL);
+	DUK_UNREF(thr);
+
+	bw_ctx->buf = h_buf;
+	duk__bw_update_ptrs(thr, bw_ctx, 0, DUK_HBUFFER_DYNAMIC_GET_SIZE(h_buf));
+}
+
+DUK_INTERNAL void duk_bw_init_pushbuf(duk_hthread *thr, duk_bufwriter_ctx *bw_ctx, duk_size_t buf_size) {
+	duk_context *ctx;
+
+	DUK_ASSERT(thr != NULL);
+	DUK_ASSERT(bw_ctx != NULL);
+	ctx = (duk_context *) thr;
+
+	(void) duk_push_dynamic_buffer(ctx, buf_size);
+	bw_ctx->buf = (duk_hbuffer_dynamic *) duk_get_hbuffer(ctx, -1);
+	duk__bw_update_ptrs(thr, bw_ctx, 0, buf_size);
+}
+
+/* Resize target buffer for requested size.  Called by the macro only when the
+ * fast path test (= there is space) fails.
+ */
+DUK_INTERNAL duk_uint8_t *duk_bw_resize(duk_hthread *thr, duk_bufwriter_ctx *bw_ctx, duk_size_t sz) {
+	duk_size_t curr_off;
+	duk_size_t add_sz;
+	duk_size_t new_sz;
+
+	DUK_ASSERT(thr != NULL);
+	DUK_ASSERT(bw_ctx != NULL);
+
+	/* We could do this operation without caller updating bw_ctx->ptr,
+	 * but by writing it back here we can share code better.
+	 */
+
+	curr_off = (duk_size_t) (bw_ctx->p - bw_ctx->p_base);
+	add_sz = (curr_off >> DUK_BW_SPARE_SHIFT) + DUK_BW_SPARE_ADD;
+	new_sz = curr_off + sz + add_sz;
+	if (new_sz < curr_off) {
+		/* overflow */
+		DUK_ERROR(thr, DUK_ERR_TYPE_ERROR, DUK_STR_BUFFER_TOO_LONG);
+		return NULL;  /* not reachable */
+	}
+#if 0  /* for manual torture testing: tight allocation, useful with valgrind */
+	new_sz = curr_off + sz;
+#endif
+
+	/* This is important to ensure dynamic buffer data pointer is not
+	 * NULL (which is possible if buffer size is zero), which in turn
+	 * causes portability issues with e.g. memmove() and memcpy().
+	 */
+	DUK_ASSERT(new_sz >= 1);
+
+	DUK_DD(DUK_DDPRINT("resize bufferwriter from %ld to %ld (add_sz=%ld)", (long) curr_off, (long) new_sz, (long) add_sz));
+
+	duk_hbuffer_resize(thr, bw_ctx->buf, new_sz);
+	duk__bw_update_ptrs(thr, bw_ctx, curr_off, new_sz);
+	return bw_ctx->p;
+}
+
+/* Make buffer compact, matching current written size. */
+DUK_INTERNAL void duk_bw_compact(duk_hthread *thr, duk_bufwriter_ctx *bw_ctx) {
+	duk_size_t len;
+
+	DUK_ASSERT(thr != NULL);
+	DUK_ASSERT(bw_ctx != NULL);
+	DUK_UNREF(thr);
+
+	len = (duk_size_t) (bw_ctx->p - bw_ctx->p_base);
+	duk_hbuffer_resize(thr, bw_ctx->buf, len);
+	duk__bw_update_ptrs(thr, bw_ctx, len, len);
+}
+
+DUK_INTERNAL void duk_bw_write_raw_slice(duk_hthread *thr, duk_bufwriter_ctx *bw, duk_size_t src_off, duk_size_t len) {
+	duk_uint8_t *p_base;
+
+	DUK_ASSERT(thr != NULL);
+	DUK_ASSERT(bw != NULL);
+	DUK_ASSERT(src_off <= DUK_BW_GET_SIZE(thr, bw));
+	DUK_ASSERT(len <= DUK_BW_GET_SIZE(thr, bw));
+	DUK_ASSERT(src_off + len <= DUK_BW_GET_SIZE(thr, bw));
+	DUK_UNREF(thr);
+
+	p_base = bw->p_base;
+	DUK_MEMCPY((void *) bw->p,
+	           (const void *) (p_base + src_off),
+	           (size_t) len);
+	bw->p += len;
+}
+
+DUK_INTERNAL void duk_bw_write_ensure_slice(duk_hthread *thr, duk_bufwriter_ctx *bw, duk_size_t src_off, duk_size_t len) {
+	DUK_ASSERT(thr != NULL);
+	DUK_ASSERT(bw != NULL);
+	DUK_ASSERT(src_off <= DUK_BW_GET_SIZE(thr, bw));
+	DUK_ASSERT(len <= DUK_BW_GET_SIZE(thr, bw));
+	DUK_ASSERT(src_off + len <= DUK_BW_GET_SIZE(thr, bw));
+	DUK_UNREF(thr);
+
+	DUK_BW_ENSURE(thr, bw, len);
+	duk_bw_write_raw_slice(thr, bw, src_off, len);
+}
+
+DUK_INTERNAL void duk_bw_insert_raw_bytes(duk_hthread *thr, duk_bufwriter_ctx *bw, duk_size_t dst_off, const duk_uint8_t *buf, duk_size_t len) {
+	duk_uint8_t *p_base;
+	duk_size_t buf_sz, move_sz;
+
+	DUK_ASSERT(thr != NULL);
+	DUK_ASSERT(bw != NULL);
+	DUK_ASSERT(dst_off <= DUK_BW_GET_SIZE(thr, bw));
+	DUK_ASSERT(buf != NULL);
+	DUK_UNREF(thr);
+
+	p_base = bw->p_base;
+	buf_sz = bw->p - p_base;
+	move_sz = buf_sz - dst_off;
+
+	DUK_ASSERT(p_base != NULL);  /* buffer size is >= 1 */
+	DUK_MEMMOVE((void *) (p_base + dst_off + len),
+	            (const void *) (p_base + dst_off),
+	            (size_t) move_sz);
+	DUK_MEMCPY((void *) (p_base + dst_off),
+	           (const void *) buf,
+	           (size_t) len);
+	bw->p += len;
+}
+
+DUK_INTERNAL void duk_bw_insert_ensure_bytes(duk_hthread *thr, duk_bufwriter_ctx *bw, duk_size_t dst_off, const duk_uint8_t *buf, duk_size_t len) {
+	DUK_ASSERT(thr != NULL);
+	DUK_ASSERT(bw != NULL);
+	DUK_ASSERT(dst_off <= DUK_BW_GET_SIZE(thr, bw));
+	DUK_ASSERT(buf != NULL);
+	DUK_UNREF(thr);
+
+	DUK_BW_ENSURE(thr, bw, len);
+	duk_bw_insert_raw_bytes(thr, bw, dst_off, buf, len);
+}
+
+DUK_INTERNAL void duk_bw_insert_raw_slice(duk_hthread *thr, duk_bufwriter_ctx *bw, duk_size_t dst_off, duk_size_t src_off, duk_size_t len) {
+	duk_uint8_t *p_base;
+	duk_size_t buf_sz, move_sz;
+
+	DUK_ASSERT(thr != NULL);
+	DUK_ASSERT(bw != NULL);
+	DUK_ASSERT(dst_off <= DUK_BW_GET_SIZE(thr, bw));
+	DUK_ASSERT(src_off <= DUK_BW_GET_SIZE(thr, bw));
+	DUK_ASSERT(len <= DUK_BW_GET_SIZE(thr, bw));
+	DUK_ASSERT(src_off + len <= DUK_BW_GET_SIZE(thr, bw));
+	DUK_UNREF(thr);
+
+	p_base = bw->p_base;
+
+	/* Don't support "straddled" source now. */
+	DUK_ASSERT(dst_off <= src_off || dst_off >= src_off + len);
+
+	if (dst_off <= src_off) {
+		/* Target is before source.  Source offset is expressed as
+		 * a "before change" offset.  Account for the memmove.
+		 */
+		src_off += len;
+	}
+
+	buf_sz = bw->p - p_base;
+	move_sz = buf_sz - dst_off;
+
+	DUK_ASSERT(p_base != NULL);  /* buffer size is >= 1 */
+	DUK_MEMMOVE((void *) (p_base + dst_off + len),
+	            (const void *) (p_base + dst_off),
+	            (size_t) move_sz);
+	DUK_MEMCPY((void *) (p_base + dst_off),
+	           (const void *) (p_base + src_off),
+	           (size_t) len);
+	bw->p += len;
+}
+
+DUK_INTERNAL void duk_bw_insert_ensure_slice(duk_hthread *thr, duk_bufwriter_ctx *bw, duk_size_t dst_off, duk_size_t src_off, duk_size_t len) {
+	DUK_ASSERT(thr != NULL);
+	DUK_ASSERT(bw != NULL);
+	DUK_ASSERT(dst_off <= DUK_BW_GET_SIZE(thr, bw));
+	DUK_ASSERT(src_off <= DUK_BW_GET_SIZE(thr, bw));
+	DUK_ASSERT(len <= DUK_BW_GET_SIZE(thr, bw));
+	DUK_ASSERT(src_off + len <= DUK_BW_GET_SIZE(thr, bw));
+	DUK_UNREF(thr);
+
+	/* Don't support "straddled" source now. */
+	DUK_ASSERT(dst_off <= src_off || dst_off >= src_off + len);
+
+	DUK_BW_ENSURE(thr, bw, len);
+	duk_bw_insert_raw_slice(thr, bw, dst_off, src_off, len);
+}
 
+DUK_INTERNAL duk_uint8_t *duk_bw_insert_raw_area(duk_hthread *thr, duk_bufwriter_ctx *bw, duk_size_t off, duk_size_t len) {
+	duk_uint8_t *p_base, *p_dst, *p_src;
+	duk_size_t buf_sz, move_sz;
+
+	DUK_ASSERT(thr != NULL);
+	DUK_ASSERT(bw != NULL);
+	DUK_ASSERT(off <= DUK_BW_GET_SIZE(thr, bw));
+	DUK_UNREF(thr);
+
+	p_base = bw->p_base;
+	buf_sz = bw->p - p_base;
+	move_sz = buf_sz - off;
+	p_dst = p_base + off + len;
+	p_src = p_base + off;
+	DUK_MEMMOVE((void *) p_dst, (const void *) p_src, (size_t) move_sz);
+	return p_src;  /* point to start of 'reserved area' */
+}
+
+DUK_INTERNAL duk_uint8_t *duk_bw_insert_ensure_area(duk_hthread *thr, duk_bufwriter_ctx *bw, duk_size_t off, duk_size_t len) {
+	DUK_ASSERT(thr != NULL);
+	DUK_ASSERT(bw != NULL);
+	DUK_ASSERT(off <= DUK_BW_GET_SIZE(thr, bw));
+	DUK_UNREF(thr);
+
+	DUK_BW_ENSURE(thr, bw, len);
+	return duk_bw_insert_raw_area(thr, bw, off, len);
+}
+
+DUK_INTERNAL void duk_bw_remove_raw_slice(duk_hthread *thr, duk_bufwriter_ctx *bw, duk_size_t off, duk_size_t len) {
+	duk_size_t move_sz;
+
+	duk_uint8_t *p_base;
+	duk_uint8_t *p_src;
+	duk_uint8_t *p_dst;
+
+	DUK_ASSERT(thr != NULL);
+	DUK_ASSERT(bw != NULL);
+	DUK_ASSERT(off <= DUK_BW_GET_SIZE(thr, bw));
+	DUK_ASSERT(len <= DUK_BW_GET_SIZE(thr, bw));
+	DUK_ASSERT(off + len <= DUK_BW_GET_SIZE(thr, bw));
+	DUK_UNREF(thr);
+
+	p_base = bw->p_base;
+	p_dst = p_base + off;
+	p_src = p_dst + len;
+	move_sz = (duk_size_t) (bw->p - p_src);
+	DUK_MEMMOVE((void *) p_dst,
+	            (const void *) p_src,
+	            (size_t) move_sz);
+	bw->p -= len;
+}
+
+/*
+ *  Macro support functions for reading/writing raw data.
+ *
+ *  These are done using mempcy to ensure they're valid even for unaligned
+ *  reads/writes on platforms where alignment counts.  On x86 at least gcc
+ *  is able to compile these into a bswap+mov.  "Always inline" is used to
+ *  ensure these macros compile to minimal code.
+ *
+ *  Not really bufwriter related, but currently used together.
+ */
+
+DUK_INTERNAL DUK_ALWAYS_INLINE duk_uint16_t duk_raw_read_u16_be(duk_uint8_t **p) {
+	union {
+		duk_uint8_t b[2];
+		duk_uint16_t x;
+	} u;
+
+	DUK_MEMCPY((void *) u.b, (const void *) (*p), (size_t) 2);
+	u.x = DUK_NTOH16(u.x);
+	*p += 2;
+	return u.x;
+}
+
+DUK_INTERNAL DUK_ALWAYS_INLINE duk_uint32_t duk_raw_read_u32_be(duk_uint8_t **p) {
+	union {
+		duk_uint8_t b[4];
+		duk_uint32_t x;
+	} u;
+
+	DUK_MEMCPY((void *) u.b, (const void *) (*p), (size_t) 4);
+	u.x = DUK_NTOH32(u.x);
+	*p += 4;
+	return u.x;
+}
+
+DUK_INTERNAL DUK_ALWAYS_INLINE duk_double_t duk_raw_read_double_be(duk_uint8_t **p) {
+	duk_double_union du;
+	union {
+		duk_uint8_t b[4];
+		duk_uint32_t x;
+	} u;
+
+	DUK_MEMCPY((void *) u.b, (const void *) (*p), (size_t) 4);
+	u.x = DUK_NTOH32(u.x);
+	du.ui[DUK_DBL_IDX_UI0] = u.x;
+	DUK_MEMCPY((void *) u.b, (const void *) (*p + 4), (size_t) 4);
+	u.x = DUK_NTOH32(u.x);
+	du.ui[DUK_DBL_IDX_UI1] = u.x;
+	*p += 8;
+
+	return du.d;
+}
+
+DUK_INTERNAL DUK_ALWAYS_INLINE void duk_raw_write_u16_be(duk_uint8_t **p, duk_uint16_t val) {
+	union {
+		duk_uint8_t b[2];
+		duk_uint16_t x;
+	} u;
+
+	u.x = DUK_HTON16(val);
+	DUK_MEMCPY((void *) (*p), (const void *) u.b, (size_t) 2);
+	*p += 2;
+}
+
+DUK_INTERNAL DUK_ALWAYS_INLINE void duk_raw_write_u32_be(duk_uint8_t **p, duk_uint32_t val) {
+	union {
+		duk_uint8_t b[4];
+		duk_uint32_t x;
+	} u;
+
+	u.x = DUK_HTON32(val);
+	DUK_MEMCPY((void *) (*p), (const void *) u.b, (size_t) 4);
+	*p += 4;
+}
+
+DUK_INTERNAL DUK_ALWAYS_INLINE void duk_raw_write_double_be(duk_uint8_t **p, duk_double_t val) {
+	duk_double_union du;
+	union {
+		duk_uint8_t b[4];
+		duk_uint32_t x;
+	} u;
+
+	du.d = val;
+	u.x = du.ui[DUK_DBL_IDX_UI0];
+	u.x = DUK_HTON32(u.x);
+	DUK_MEMCPY((void *) (*p), (const void *) u.b, (size_t) 4);
+	u.x = du.ui[DUK_DBL_IDX_UI1];
+	u.x = DUK_HTON32(u.x);
+	DUK_MEMCPY((void *) (*p + 4), (const void *) u.b, (size_t) 4);
+	*p += 8;
+}
 #line 1 "duk_util_hashbytes.c"
 /*
  *  Hash function duk_util_hashbytes().
@@ -64796,12 +88010,13 @@ void duk_be_finish(duk_bitencoder_ctx *ctx) {
 
 /* include removed: duk_internal.h */
 
+#if defined(DUK_USE_STRHASH_DENSE)
 /* 'magic' constants for Murmurhash2 */
 #define DUK__MAGIC_M  ((duk_uint32_t) 0x5bd1e995UL)
 #define DUK__MAGIC_R  24
 
-duk_uint32_t duk_util_hashbytes(duk_uint8_t *data, duk_size_t len, duk_uint32_t seed) {
-	duk_uint32_t h = seed ^ len;
+DUK_INTERNAL duk_uint32_t duk_util_hashbytes(const duk_uint8_t *data, duk_size_t len, duk_uint32_t seed) {
+	duk_uint32_t h = seed ^ ((duk_uint32_t) len);
 
 	while (len >= 4) {
 		/* Portability workaround is required for platforms without
@@ -64810,7 +88025,7 @@ duk_uint32_t duk_util_hashbytes(duk_uint8_t *data, duk_size_t len, duk_uint32_t
 		 * OK as long as it is consistent for a build.
 		 */
 #ifdef DUK_USE_HASHBYTES_UNALIGNED_U32_ACCESS
-		duk_uint32_t k = *((duk_uint32_t *) data);
+		duk_uint32_t k = *((const duk_uint32_t *) (const void *) data);
 #else
 		duk_uint32_t k = ((duk_uint32_t) data[0]) |
 		                 (((duk_uint32_t) data[1]) << 8) |
@@ -64828,10 +88043,10 @@ duk_uint32_t duk_util_hashbytes(duk_uint8_t *data, duk_size_t len, duk_uint32_t
 	}
 
 	switch (len) {
-		case 3:	h ^= data[2] << 16;
-		case 2:	h ^= data[1] << 8;
-		case 1:	h ^= data[0];
-			h *= DUK__MAGIC_M;
+	case 3: h ^= data[2] << 16;
+	case 2: h ^= data[1] << 8;
+	case 1: h ^= data[0];
+	        h *= DUK__MAGIC_M;
         }
 
 	h ^= h >> 13;
@@ -64840,122 +88055,7 @@ duk_uint32_t duk_util_hashbytes(duk_uint8_t *data, duk_size_t len, duk_uint32_t
 
 	return h;
 }
-
-#line 1 "duk_util_hashprime.c"
-/*
- *  Round a number upwards to a prime (not usually the nearest one).
- *
- *  Uses a table of successive 32-bit primes whose ratio is roughly
- *  constant.  This keeps the relative upwards 'rounding error' bounded
- *  and the data size small.  A simple 'predict-correct' compression is
- *  used to compress primes to one byte per prime.  See genhashsizes.py
- *  for details.
- *
- *  The minimum prime returned here must be coordinated with the possible
- *  probe sequence steps in duk_hobject and duk_heap stringtable.
- */
-
-/* include removed: duk_internal.h */
-
-/* hash size ratio goal, must match genhashsizes.py */
-#define DUK__HASH_SIZE_RATIO   1177  /* floor(1.15 * (1 << 10)) */
-
-/* prediction corrections for prime list (see genhashsizes.py) */
-static const duk_int8_t duk__hash_size_corrections[] = {
-	17,  /* minimum prime */
-	4, 3, 4, 1, 4, 1, 1, 2, 2, 2, 2, 1, 6, 6, 9, 5, 1, 2, 2, 5, 1, 3, 3, 3,
-	5, 4, 4, 2, 4, 8, 3, 4, 23, 2, 4, 7, 8, 11, 2, 12, 15, 10, 1, 1, 5, 1, 5,
-	8, 9, 17, 14, 10, 7, 5, 2, 46, 21, 1, 9, 9, 4, 4, 10, 23, 36, 6, 20, 29,
-	18, 6, 19, 21, 16, 11, 5, 5, 48, 9, 1, 39, 14, 8, 4, 29, 9, 1, 15, 48, 12,
-	22, 6, 15, 27, 4, 2, 17, 28, 8, 9, 4, 5, 8, 3, 3, 8, 37, 11, 15, 8, 30,
-	43, 6, 33, 41, 5, 20, 32, 41, 38, 24, 77, 14, 19, 11, 4, 35, 18, 19, 41,
-	10, 23, 16, 9, 2,
-	-1
-};
-
-/* probe steps (see genhashsizes.py), currently assumed to be 32 entries long
- * (DUK_UTIL_GET_HASH_PROBE_STEP macro).
- */
-duk_uint8_t duk_util_probe_steps[32] = {
-	2, 3, 5, 7, 11, 13, 19, 31, 41, 47, 59, 67, 73, 79, 89, 101, 103, 107,
-	109, 127, 137, 139, 149, 157, 163, 167, 173, 181, 191, 193, 197, 199
-};
-
-duk_uint32_t duk_util_get_hash_prime(duk_uint32_t size) {
-	const duk_int8_t *p = duk__hash_size_corrections;
-	duk_uint32_t curr;
-
-	curr = (duk_uint32_t) *p++;
-	for (;;) {
-		duk_small_int_t t = (duk_small_int_t) *p++;
-		if (t < 0) {
-			/* may happen if size is very close to 2^32-1 */
-			break;
-		}
-
-		/* prediction: portable variant using doubles if 64-bit values not available */
-#ifdef DUK_USE_64BIT_OPS
-		curr = (duk_uint32_t) ((((duk_uint64_t) curr) * ((duk_uint64_t) DUK__HASH_SIZE_RATIO)) >> 10);
-#else
-		/* 32-bit x 11-bit = 43-bit, fits accurately into a double */
-		curr = (duk_uint32_t) DUK_FLOOR(((double) curr) * ((double) DUK__HASH_SIZE_RATIO) / 1024.0);
-#endif
-
-		/* correction */
-		curr += t;
-
-		DUK_DDD(DUK_DDDPRINT("size=%ld, curr=%ld", (long) size, (long) curr));
-
-		if (curr >= size) {
-			return curr;
-		}
-	}
-	return 0;
-}
-
-#line 1 "duk_util_misc.c"
-/*
- *  Misc util stuff
- */
-
-/* include removed: duk_internal.h */
-
-/*
- *  Lowercase digits for radix values 2 to 36.  Also doubles as lowercase
- *  hex nybble table.
- */
-
-duk_uint8_t duk_lc_digits[36] = { '0', '1', '2', '3', '4', '5', '6', '7',
-                                  '8', '9', 'a', 'b', 'c', 'd', 'e', 'f',
-                                  'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
-                                  'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
-                                  'w', 'x', 'y', 'z' };
-
-duk_uint8_t duk_uc_nybbles[16] = { '0', '1', '2', '3', '4', '5', '6', '7',
-                                   '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
-
-/*
- *  Table for decoding ASCII hex digits, -1 if invalid.
- */
-
-duk_int8_t duk_hex_dectab[256] = {
-	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* 0x00-0x0f */
-	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* 0x10-0x1f */
-	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* 0x20-0x2f */
-	 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, -1, -1, -1, -1, -1, -1,  /* 0x30-0x3f */
-	-1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* 0x40-0x4f */
-	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* 0x50-0x5f */
-	-1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* 0x60-0x6f */
-	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* 0x70-0x7f */
-	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* 0x80-0x8f */
-	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* 0x90-0x9f */
-	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* 0xa0-0xaf */
-	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* 0xb0-0xbf */
-	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* 0xc0-0xcf */
-	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* 0xd0-0xdf */
-	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* 0xe0-0xef */
-	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1   /* 0xf0-0xff */
-};
+#endif  /* DUK_USE_STRHASH_DENSE */
 #line 1 "duk_util_tinyrandom.c"
 /*
  *  A tiny random number generator.
@@ -64974,7 +88074,7 @@ duk_int8_t duk_hex_dectab[256] = {
 
 #define DUK__RND_BIT(rnd)  ((rnd) >> 31)  /* only use the highest bit */
 
-duk_uint32_t duk_util_tinyrandom_get_bits(duk_hthread *thr, duk_small_int_t n) {
+DUK_INTERNAL duk_uint32_t duk_util_tinyrandom_get_bits(duk_hthread *thr, duk_small_int_t n) {
 	duk_small_int_t i;
 	duk_uint32_t res = 0;
 	duk_uint32_t rnd;
@@ -64992,7 +88092,7 @@ duk_uint32_t duk_util_tinyrandom_get_bits(duk_hthread *thr, duk_small_int_t n) {
 	return res;
 }
 
-duk_double_t duk_util_tinyrandom_get_double(duk_hthread *thr) {
+DUK_INTERNAL duk_double_t duk_util_tinyrandom_get_double(duk_hthread *thr) {
 	duk_double_t t;
 	duk_small_int_t n;
 	duk_uint32_t rnd;
@@ -65020,4 +88120,3 @@ duk_double_t duk_util_tinyrandom_get_double(duk_hthread *thr) {
 
 	return t;
 }
-
diff --git a/src/osgEarthDrivers/script_engine_duktape/duktape.h b/src/osgEarthDrivers/script_engine_duktape/duktape.h
index 5151736..7f7a7c3 100644
--- a/src/osgEarthDrivers/script_engine_duktape/duktape.h
+++ b/src/osgEarthDrivers/script_engine_duktape/duktape.h
@@ -1,13 +1,14 @@
 /*
- *  Duktape public API for Duktape 0.11.0.
+ *  Duktape public API for Duktape 1.4.0.
  *  See the API reference for documentation on call semantics.
  *  The exposed API is inside the DUK_API_PUBLIC_H_INCLUDED
  *  include guard.  Other parts of the header are Duktape
  *  internal and related to platform/compiler/feature detection.
  *
- *  Git commit 621b545c474dd7a3def7aefed0557b1a825a4578 (v0.10.0-827-g621b545).
+ *  Git commit cad6f595382a0cc1a7e4207794ade5be11b3e397 (v1.4.0).
+ *  Git branch master.
  *
- *  See Duktape AUTHORS.txt and LICENSE.txt for copyright and
+ *  See Duktape AUTHORS.rst and LICENSE.txt for copyright and
  *  licensing information.
  */
 
@@ -19,7 +20,7 @@
  *  
  *  (http://opensource.org/licenses/MIT)
  *  
- *  Copyright (c) 2013-2014 by Duktape authors (see AUTHORS.txt)
+ *  Copyright (c) 2013-2016 by Duktape authors (see AUTHORS.rst)
  *  
  *  Permission is hereby granted, free of charge, to any person obtaining a copy
  *  of this software and associated documentation files (the "Software"), to deal
@@ -38,2470 +39,91 @@
  *  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.
- *  
- */
-
-/* AUTHORS.txt */
-/*
- *  ===============
- *  Duktape authors
- *  ===============
- *  
- *  Copyright
- *  =========
- *  
- *  Duktape copyrights are held by its authors.  Each author has a copyright
- *  to their contribution, and agrees to irrevocably license the contribution
- *  under the Duktape ``LICENSE.txt``.
- *  
- *  Authors
- *  =======
- *  
- *  Please include an e-mail address, a link to your GitHub profile, or something
- *  similar to allow your contribution to be identified accurately.
- *  
- *  The following people have contributed code and agreed to irrevocably license
- *  their contributions under the Duktape ``LICENSE.txt`` (in order of appearance):
- *  
- *  * Sami Vaarala <sami.vaarala at iki.fi>
- *  * Niki Dobrev
- *  * Andreas \u00d6man <andreas at lonelycoder.com>
- *  
- *  Other contributions
- *  ===================
- *  
- *  The following people have contributed something other than code (e.g. reported
- *  bugs, provided ideas, etc; in order of appearance):
- *  
- *  * Greg Burns
- *  * Anthony Rabine
- *  * Carlos Costa
- *  * Aur\u00e9lien Bouilland
- *  * Preet Desai (Pris Matic)
- *  * judofyr (http://www.reddit.com/user/judofyr)
- *  * Jason Woofenden
- *  * Micha\u0142 Przyby\u015b
- *  * Anthony Howe
- *  * Conrad Pankoff
- *  * Jim Schimpf
- *  * Rajaran Gaunker (https://github.com/zimbabao)
- *  * Andreas \u00d6man
- *  * Doug Sanden
- *  * Remo Eichenberger (https://github.com/remoe)
- */
-
-#ifndef DUKTAPE_H_INCLUDED
-#define DUKTAPE_H_INCLUDED
-
-/*
- *  Determine platform features, select feature selection defines
- *  (e.g. _XOPEN_SOURCE), include system headers, and define DUK_USE_XXX
- *  defines which are (only) checked in Duktape internal code for
- *  activated features.  Duktape feature selection is based on automatic
- *  feature detection, user supplied DUK_OPT_xxx defines, and optionally
- *  a "duk_custom.h" user header (if DUK_OPT_HAVE_CUSTOM_H is defined).
- *
- *  When compiling Duktape, DUK_COMPILING_DUKTAPE is set, and this file
- *  is included before any system headers are included.  Feature selection
- *  defines (e.g. _XOPEN_SOURCE) are defined here before any system headers
- *  are included (which is a requirement for system headers to work correctly).
- *  This file is responsible for including all system headers and contains
- *  all platform dependent cruft in general.  When compiling user code,
- *  DUK_COMPILING_DUKTAPE is not defined, and we must avoid e.g. defining
- *  unnecessary feature selection defines.
- *
- *  The general order of handling:
- *    - Compiler feature detection (require no includes)
- *    - Intermediate platform detection (-> easier platform defines)
- *    - Platform detection, system includes, byte order detection, etc
- *    - ANSI C wrappers (e.g. DUK_MEMCMP), wrappers for constants, etc
- *    - DUK_USE_xxx defines are resolved based on input defines
- *    - Duktape Date provider settings
- *    - Final sanity checks
- *
- *  DUK_F_XXX are internal feature detection macros which should not be
- *  used outside this header.
- *
- *  Useful resources:
- *
- *    http://sourceforge.net/p/predef/wiki/Home/
- *    http://sourceforge.net/p/predef/wiki/Architectures/
- *    http://stackoverflow.com/questions/5919996/how-to-detect-reliably-mac-os-x-ios-linux-windows-in-c-preprocessor
- *    http://en.wikipedia.org/wiki/C_data_types#Fixed-width_integer_types
- *
- *  Preprocessor defines available in a particular GCC:
- *
- *    gcc -dM -E - </dev/null   # http://www.brain-dump.org/blog/entry/107
- */
-
-#ifndef DUK_FEATURES_H_INCLUDED
-#define DUK_FEATURES_H_INCLUDED
-
-/*
- *  Compiler features
- */
-
-#undef DUK_F_C99
-#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
-#define DUK_F_C99
-#endif
-
-#undef DUK_F_CPP
-#if defined(__cplusplus)
-#define DUK_F_CPP
-#endif
-
-#undef DUK_F_CPP11
-#if defined(__cplusplus) && (__cplusplus >= 201103L)
-#define DUK_F_CPP11
-#endif
-
-/*
- *  Provides the duk_rdtsc() inline function (if available), limited to
- *  GCC C99.
- *
- *  See: http://www.mcs.anl.gov/~kazutomo/rdtsc.html
- */
-
-/* XXX: more accurate detection of what gcc versions work; more inline
- * asm versions for other compilers.
- */
-#if defined(__GNUC__) && defined(__i386__) && defined(DUK_F_C99) && \
-    !defined(__cplusplus) /* unsigned long long not standard */
-static __inline__ unsigned long long duk_rdtsc(void) {
-	unsigned long long int x;
-	__asm__ volatile (".byte 0x0f, 0x31" : "=A" (x));
-	return x;
-}
-#define DUK_RDTSC_AVAILABLE 1
-#elif defined(__GNUC__) && defined(__x86_64__) && defined(DUK_F_C99) && \
-    !defined(__cplusplus) /* unsigned long long not standard */
-static __inline__ unsigned long long duk_rdtsc(void) {
-	unsigned hi, lo;
-	__asm__ __volatile__ ("rdtsc" : "=a"(lo), "=d"(hi));
-	return ((unsigned long long) lo) | (((unsigned long long) hi) << 32);
-}
-#define DUK_RDTSC_AVAILABLE 1
-#else
-/* not available */
-#undef DUK_RDTSC_AVAILABLE
-#endif
-
-/*
- *  Intermediate platform, architecture, and compiler detection.  These are
- *  hopelessly intertwined - e.g. architecture defines depend on compiler etc.
- *
- *  Provide easier defines for platforms and compilers which are often tricky
- *  or verbose to detect.  The intent is not to provide intermediate defines for
- *  all features; only if existing feature defines are inconvenient.
- */
-
-/* Intel x86 (32-bit) */
-#if defined(i386) || defined(__i386) || defined(__i386__) || \
-    defined(__i486__) || defined(__i586__) || defined(__i686__) || \
-    defined(__IA32__) || defined(_M_IX86) || defined(__X86__) || \
-    defined(_X86_) || defined(__THW_INTEL__) || defined(__I86__) || \
-    defined(__ANDROID__)
-#define DUK_F_X86
-#endif
-
-/* AMD64 (64-bit) */
-#if defined(__amd64__) || defined(__amd64) || \
-    defined(__x86_64__) || defined(__x86_64) || \
-    defined(_M_X64) || defined(_M_AMD64)
-#define DUK_F_X64
-#endif
-
-/* X32: 64-bit with 32-bit pointers (allows packed tvals).  X32 support is
- * not very mature yet.
- *
- * https://sites.google.com/site/x32abi/
- */
-#if defined(DUK_F_X64) && \
-    (defined(_ILP32) || defined(__ILP32__))
-#define DUK_F_X32
-/* define only one of: DUK_F_X86, DUK_F_X32, or DUK_F_X64 */
-#undef DUK_F_X64
-#undef DUK_F_X86
-#endif
-
-/* ARM */
-#if defined(__arm__) || defined(__thumb__) || defined(_ARM) || defined(_M_ARM)
-#define DUK_F_ARM
-#endif
-
-/* MIPS */
-/* FIXME: 32-bit vs. 64-bit MIPS */
-#if defined(__mips__) || defined(mips) || defined(_MIPS_ISA) || \
-    defined(_R3000) || defined(_R4000) || defined(_R5900) || \
-    defined(_MIPS_ISA_MIPS1) || defined(_MIPS_ISA_MIPS2) || \
-    defined(_MIPS_ISA_MIPS3) || defined(_MIPS_ISA_MIPS4) || \
-    defined(__mips) || defined(__MIPS__)
-#define DUK_F_MIPS
-#endif
-
-/* Motorola 68K.  Not defined by VBCC, so user must define one of these
- * manually when using VBCC.
- */
-#if defined(__m68k__) || defined(M68000) || defined(__MC68K__)
-#define DUK_F_M68K
-#endif
-
-/* Linux */
-#if defined(__linux) || defined(__linux__) || defined(linux)
-#define DUK_F_LINUX
-#endif
-
-/* FreeBSD */
-#if defined(__FreeBSD__) || defined(__FreeBSD)
-#define DUK_F_FREEBSD
-#endif
-
-/* NetBSD */
-#if defined(__NetBSD__) || defined(__NetBSD)
-#define DUK_F_NETBSD
-#endif
-
-/* OpenBSD */
-#if defined(__OpenBSD__) || defined(__OpenBSD)
-#define DUK_F_OPENBSD
-#endif
-
-/* BSD variant */
-#if defined(DUK_F_FREEBSD) || defined(DUK_F_NETBSD) || defined(DUK_F_OPENBSD) || \
-    defined(__bsdi__) || defined(__DragonFly__)
-#define DUK_F_BSD
-#endif
-
-/* Generic Unix */
-#if defined(__unix) || defined(__unix__) || defined(unix) || \
-    defined(DUK_F_LINUX) || defined(DUK_F_BSD)
-#define DUK_F_UNIX
-#endif
-
-/* Windows (32-bit or above) */
-#if defined(_WIN32) || defined(WIN32) || defined(_WIN64) || defined(WIN64) || \
-    defined(__WIN32__) || defined(__TOS_WIN__) || defined(__WINDOWS__)
-#define DUK_F_WINDOWS
-#endif
-
-/* Atari ST TOS. __TOS__ defined by PureC (which doesn't work as a target now
- * because int is 16-bit, to be fixed).  No platform define in VBCC apparently,
- * so to use with VBCC, user must define '__TOS__' manually.
-  */
-#if defined(__TOS__)
-#define DUK_F_TOS
-#endif
-
-/* AmigaOS.  Neither AMIGA nor __amigaos__ is defined on VBCC, so user must
- * define 'AMIGA' manually.
- */
-#if defined(AMIGA) || defined(__amigaos__)
-#define DUK_F_AMIGAOS
-#endif
-
-/* Flash player (e.g. Crossbridge) */
-#if defined(__FLASHPLAYER__)
-#define DUK_F_FLASHPLAYER
-#endif
-
-/* Emscripten (provided explicitly by user), improve if possible */
-#if defined(EMSCRIPTEN)
-#define DUK_F_EMSCRIPTEN
-#endif
-
-/* QNX */
-#if defined(__QNX__)
-#define DUK_F_QNX
-#endif
-
-/* GCC and GCC version convenience define. */
-#if defined(__GNUC__)
-#define DUK_F_GCC
-#if defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__GNUC_PATCHLEVEL__)
-/* Convenience, e.g. gcc 4.5.1 == 40501; http://stackoverflow.com/questions/6031819/emulating-gccs-builtin-unreachable */
-#define DUK_F_GCC_VERSION  (__GNUC__ * 10000L + __GNUC_MINOR__ * 100L + __GNUC_PATCHLEVEL__)
-#else
-#error cannot figure out gcc version
-#endif
-#endif
-
-/* Clang */
-#if defined(__clang__)
-#define DUK_F_CLANG
-#endif
-
-/* MSVC */
-#if defined(_MSC_VER)
-/* MSVC preprocessor defines: http://msdn.microsoft.com/en-us/library/b0084kay.aspx
- * _MSC_FULL_VER includes the build number, but it has at least two formats, see e.g.
- * BOOST_MSVC_FULL_VER in http://www.boost.org/doc/libs/1_52_0/boost/config/compiler/visualc.hpp
- */
-#define DUK_F_MSVC
-#endif
-
-/* MinGW */
-#if defined(__MINGW32__) || defined(__MINGW64__)
-#define DUK_F_MINGW
-#endif
-
-/* BCC (Bruce's C compiler): this is a "torture target" for compilation */
-#if defined(__BCC__) || defined(__BCC_VERSION__)
-#define DUK_F_BCC
-#endif
-
-#if defined(__VBCC__)
-#define DUK_F_VBCC
-#endif
-
-#if (defined(DUK_F_C99) || defined(DUK_F_CPP11)) && \
-    !defined(DUK_F_BCC)
-/* ULL / LL preprocessor constants should be avoided because they're not
- * always available.  With suitable options, some compilers will support
- * 64-bit integer types but won't support ULL / LL preprocessor constants.
- * Assume C99/C++11 environments have these.  However, BCC is nominally
- * C99 but doesn't support these constants.
- */
-#define DUK_F_ULL_CONSTS
-#endif
-
-/*
- *  Platform detection, system includes, Date provider selection.
- *
- *  Feature selection (e.g. _XOPEN_SOURCE) must happen before any system
- *  headers are included.  This header should avoid providing any feature
- *  selection defines when compiling user code (only when compiling Duktape
- *  itself).  If a feature selection option is required for user code to
- *  compile correctly (e.g. it is needed for type detection), it should
- *  probably be -checked- here, not defined here.
- *
- *  Date provider selection seems a bit out-of-place here, but since
- *  the date headers and provider functions are heavily platform
- *  specific, there's little point in duplicating the platform if-else
- *  ladder.  All platform specific Date provider functions are in
- *  duk_bi_date.c; here we provide appropriate #defines to enable them,
- *  and include all the necessary system headers so that duk_bi_date.c
- *  compiles.  Date "providers" are:
- *
- *    NOW = getting current time (required)
- *    TZO = getting local time offset (required)
- *    PRS = parse datetime (optional)
- *    FMT = format datetime (optional)
- *
- *  There's a lot of duplication here, unfortunately, because many
- *  platforms have similar (but not identical) headers, Date providers,
- *  etc.  The duplication could be removed by more complicated nested
- *  #ifdefs, but it would then be more difficult to make fixes which
- *  affect only a specific platform.
- *
- *  FIXME: add a way to provide custom functions to provide the critical
- *  primitives; this would be convenient when porting to unknown platforms
- *  (rather than muck with Duktape internals).
- */
-
-#if defined(DUK_COMPILING_DUKTAPE) && \
- (defined(DUK_F_LINUX) || defined(DUK_F_EMSCRIPTEN))
-/* A more recent Emscripten (2014-05) seems to lack "linux" environment
- * defines, so check for Emscripten explicitly.
- */
-#ifndef _POSIX_C_SOURCE
-#define _POSIX_C_SOURCE  200809L
-#endif
-#ifndef _GNU_SOURCE
-#define _GNU_SOURCE      /* e.g. getdate_r */
-#endif
-#ifndef _XOPEN_SOURCE
-#define _XOPEN_SOURCE    /* e.g. strptime */
-#endif
-#endif
-
-#if defined(DUK_F_QNX) && defined(DUK_COMPILING_DUKTAPE)
-/* See: /opt/qnx650/target/qnx6/usr/include/sys/platform.h */
-#define _XOPEN_SOURCE    600
-#define _POSIX_C_SOURCE  200112L
-#endif
-
-#undef DUK_F_MSVC_CRT_SECURE
-#if defined(DUK_F_WINDOWS) && defined(_MSC_VER)
-/* http://msdn.microsoft.com/en-us/library/8ef0s5kh.aspx
- * http://msdn.microsoft.com/en-us/library/wd3wzwts.aspx
- * Seem to be available since VS2005.
- */
-#if (_MSC_VER >= 1400)
-/* VS2005+, secure CRT functions are preferred.  Windows Store applications
- * (and probably others) should use these.
- */
-#define DUK_F_MSVC_CRT_SECURE
-#endif
-#if (_MSC_VER < 1700)
-/* VS2012+ has stdint.h, < VS2012 does not (but it's available for download). */
-#define DUK_F_NO_STDINT_H
-#endif
-/* Initial fix: disable secure CRT related warnings when compiling Duktape
- * itself (must be defined before including Windows headers).  Don't define
- * for user code including duktape.h.
- */
-#if defined(DUK_COMPILING_DUKTAPE) && !defined(_CRT_SECURE_NO_WARNINGS)
-#define _CRT_SECURE_NO_WARNINGS
-#endif
-#endif  /* DUK_F_WINDOWS && _MSC_VER */
-
-#if defined(DUK_F_TOS) || defined(DUK_F_BCC)
-#define DUK_F_NO_STDINT_H
-#endif
-
-#if defined(__APPLE__)
-/* Mac OSX, iPhone, Darwin */
-#define DUK_USE_DATE_NOW_GETTIMEOFDAY
-#define DUK_USE_DATE_TZO_GMTIME_R
-#define DUK_USE_DATE_PRS_STRPTIME
-#define DUK_USE_DATE_FMT_STRFTIME
-#include <architecture/byte_order.h>
-#include <limits.h>
-#include <sys/param.h>
-#include <sys/time.h>
-#include <time.h>
-#elif defined(DUK_F_OPENBSD)
-/* http://www.monkey.org/openbsd/archive/ports/0401/msg00089.html */
-#define DUK_USE_DATE_NOW_GETTIMEOFDAY
-#define DUK_USE_DATE_TZO_GMTIME_R
-#define DUK_USE_DATE_PRS_STRPTIME
-#define DUK_USE_DATE_FMT_STRFTIME
-#include <sys/types.h>
-#include <sys/endian.h>
-#include <limits.h>
-#include <sys/param.h>
-#include <sys/time.h>
-#include <time.h>
-#elif defined(DUK_F_BSD)
-/* other BSD */
-#define DUK_USE_DATE_NOW_GETTIMEOFDAY
-#define DUK_USE_DATE_TZO_GMTIME_R
-#define DUK_USE_DATE_PRS_STRPTIME
-#define DUK_USE_DATE_FMT_STRFTIME
-#include <sys/types.h>
-#include <sys/endian.h>
-#include <limits.h>
-#include <sys/param.h>
-#include <sys/time.h>
-#include <time.h>
-#elif defined(DUK_F_TOS)
-/* Atari ST TOS */
-#define DUK_USE_DATE_NOW_TIME
-#define DUK_USE_DATE_TZO_GMTIME
-/* no parsing (not an error) */
-#define DUK_USE_DATE_FMT_STRFTIME
-#include <limits.h>
-#include <time.h>
-#elif defined(DUK_F_AMIGAOS)
-#if defined(DUK_F_M68K)
-/* AmigaOS on M68k */
-#define DUK_USE_DATE_NOW_TIME
-#define DUK_USE_DATE_TZO_GMTIME
-/* no parsing (not an error) */
-#define DUK_USE_DATE_FMT_STRFTIME
-#include <limits.h>
-#include <time.h>
-#else
-#error AmigaOS but not M68K, not supported now
-#endif
-#elif defined(DUK_F_WINDOWS)
-/* Windows 32-bit and 64-bit are currently the same. */
-/* MSVC does not have sys/param.h */
-#define DUK_USE_DATE_NOW_WINDOWS
-#define DUK_USE_DATE_TZO_WINDOWS
-/* Note: PRS and FMT are intentionally left undefined for now.  This means
- * there is no platform specific date parsing/formatting but there is still
- * the ISO 8601 standard format.
- */
-#include <windows.h>
-#include <limits.h>
-#elif defined(DUK_F_FLASHPLAYER)
-/* Crossbridge */
-#define DUK_USE_DATE_NOW_GETTIMEOFDAY
-#define DUK_USE_DATE_TZO_GMTIME_R
-#define DUK_USE_DATE_PRS_STRPTIME
-#define DUK_USE_DATE_FMT_STRFTIME
-#include <endian.h>
-#include <limits.h>
-#include <sys/param.h>
-#include <sys/time.h>
-#include <time.h>
-#elif defined(DUK_F_QNX)
-#define DUK_USE_DATE_NOW_GETTIMEOFDAY
-#define DUK_USE_DATE_TZO_GMTIME_R
-#define DUK_USE_DATE_PRS_STRPTIME
-#define DUK_USE_DATE_FMT_STRFTIME
-#include <sys/types.h>
-#include <limits.h>
-#include <sys/param.h>
-#include <sys/time.h>
-#include <time.h>
-#elif defined(DUK_F_LINUX)
-#define DUK_USE_DATE_NOW_GETTIMEOFDAY
-#define DUK_USE_DATE_TZO_GMTIME_R
-#define DUK_USE_DATE_PRS_STRPTIME
-#define DUK_USE_DATE_FMT_STRFTIME
-#include <sys/types.h>
-#if defined(DUK_F_BCC)
-/* no endian.h */
-#else
-#include <endian.h>
-#endif  /* DUK_F_BCC */
-#include <limits.h>
-#include <sys/param.h>
-#include <sys/time.h>
-#include <time.h>
-#elif defined(__posix)
-/* POSIX */
-#define DUK_USE_DATE_NOW_GETTIMEOFDAY
-#define DUK_USE_DATE_TZO_GMTIME_R
-#define DUK_USE_DATE_PRS_STRPTIME
-#define DUK_USE_DATE_FMT_STRFTIME
-#include <sys/types.h>
-#include <endian.h>
-#include <limits.h>
-#include <sys/param.h>
-#include <sys/time.h>
-#include <time.h>
-#else
-/* Other UNIX, hopefully others */
-#define DUK_USE_DATE_NOW_GETTIMEOFDAY
-#define DUK_USE_DATE_TZO_GMTIME_R
-#define DUK_USE_DATE_PRS_STRPTIME
-#define DUK_USE_DATE_FMT_STRFTIME
-#include <sys/types.h>
-#if defined(DUK_F_BCC)
-/* no endian.h */
-#else
-#include <endian.h>
-#endif  /* DUK_F_BCC */
-#include <limits.h>
-#include <sys/param.h>
-#include <sys/time.h>
-#include <time.h>
-#endif
-
-/* Shared includes */
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <stdarg.h>  /* varargs */
-#include <setjmp.h>
-#include <stddef.h>  /* e.g. ptrdiff_t */
-#if defined(DUK_F_NO_STDINT_H)
-/* stdint.h not available */
-#else
-/* technically C99 (C++11) but found in many systems */
-#include <stdint.h>
-#endif
-#include <math.h>
-
-/*
- *  Detection for specific libc variants (like uclibc) and other libc specific
- *  features.  Potentially depends on the #includes above.
- */
-
-#if defined(__UCLIBC__)
-#define DUK_F_UCLIBC
-#endif
-
-/*
- *  Wrapper typedefs and constants for integer types, also sanity check types.
- *
- *  C99 typedefs are quite good but not always available, and we want to avoid
- *  forcibly redefining the C99 typedefs.  So, there are Duktape wrappers for
- *  all C99 typedefs and Duktape code should only use these typedefs.  Type
- *  detection when C99 is not supported is best effort and may end up detecting
- *  some types incorrectly.
- *
- *  Pointer sizes are a portability problem: pointers to different types may
- *  have a different size and function pointers are very difficult to manage
- *  portably.
- *
- *  http://en.wikipedia.org/wiki/C_data_types#Fixed-width_integer_types
- *
- *  Note: there's an interesting corner case when trying to define minimum
- *  signed integer value constants which leads to the current workaround of
- *  defining e.g. -0x80000000 as (-0x7fffffffL - 1L).  See doc/code-issues.txt
- *  for a longer discussion.
- *
- *  Note: avoid typecasts and computations in macro integer constants as they
- *  can then no longer be used in macro relational expressions (such as
- *  #if DUK_SIZE_MAX < 0xffffffffUL).  There is internal code which relies on
- *  being able to compare DUK_SIZE_MAX against a limit.
- */
-
-/* FIXME: add feature options to force basic types from outside? */
-
-#if !defined(INT_MAX)
-#error INT_MAX not defined
-#endif
-
-/* Check that architecture is two's complement, standard C allows e.g.
- * INT_MIN to be -2**31+1 (instead of -2**31).
- */
-#if defined(INT_MAX) && defined(INT_MIN)
-#if INT_MAX != -(INT_MIN + 1)
-#error platform does not seem complement of two
-#endif
-#else
-#error cannot check complement of two
-#endif
-
-/* Pointer size determination based on architecture.
- * XXX: unsure about BCC correctness.
- */
-#if defined(DUK_F_X86) || defined(DUK_F_X32) || \
-    defined(DUK_F_BCC) || \
-    (defined(__WORDSIZE) && (__WORDSIZE == 32))
-#define DUK_F_32BIT_PTRS
-#elif defined(DUK_F_X64) || \
-      (defined(__WORDSIZE) && (__WORDSIZE == 64))
-#define DUK_F_64BIT_PTRS
-#else
-/* not sure, not needed with C99 anyway */
-#endif
-
-/* Intermediate define for 'have inttypes.h' */
-#undef DUK_F_HAVE_INTTYPES
-#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && \
-    !(defined(DUK_F_AMIGAOS) && defined(DUK_F_VBCC))
-/* vbcc + AmigaOS has C99 but no inttypes.h */
-#define DUK_F_HAVE_INTTYPES
-#elif defined(__cplusplus) && (__cplusplus >= 201103L)
-/* C++11 apparently ratified stdint.h */
-#define DUK_F_HAVE_INTTYPES
-#endif
-
-/* Basic integer typedefs and limits, preferably from inttypes.h, otherwise
- * through automatic detection.
- */
-#if defined(DUK_F_HAVE_INTTYPES)
-/* C99 */
-#define DUK_F_HAVE_64BIT
-#include <inttypes.h>
-
-typedef uint8_t duk_uint8_t;
-typedef int8_t duk_int8_t;
-typedef uint16_t duk_uint16_t;
-typedef int16_t duk_int16_t;
-typedef uint32_t duk_uint32_t;
-typedef int32_t duk_int32_t;
-typedef uint64_t duk_uint64_t;
-typedef int64_t duk_int64_t;
-typedef uint_least8_t duk_uint_least8_t;
-typedef int_least8_t duk_int_least8_t;
-typedef uint_least16_t duk_uint_least16_t;
-typedef int_least16_t duk_int_least16_t;
-typedef uint_least32_t duk_uint_least32_t;
-typedef int_least32_t duk_int_least32_t;
-typedef uint_least64_t duk_uint_least64_t;
-typedef int_least64_t duk_int_least64_t;
-typedef uint_fast8_t duk_uint_fast8_t;
-typedef int_fast8_t duk_int_fast8_t;
-typedef uint_fast16_t duk_uint_fast16_t;
-typedef int_fast16_t duk_int_fast16_t;
-typedef uint_fast32_t duk_uint_fast32_t;
-typedef int_fast32_t duk_int_fast32_t;
-typedef uint_fast64_t duk_uint_fast64_t;
-typedef int_fast64_t duk_int_fast64_t;
-typedef uintptr_t duk_uintptr_t;
-typedef intptr_t duk_intptr_t;
-typedef uintmax_t duk_uintmax_t;
-typedef intmax_t duk_intmax_t;
-
-#define DUK_UINT8_MIN         0
-#define DUK_UINT8_MAX         UINT8_MAX
-#define DUK_INT8_MIN          INT8_MIN
-#define DUK_INT8_MAX          INT8_MAX
-#define DUK_UINT_LEAST8_MIN   0
-#define DUK_UINT_LEAST8_MAX   UINT_LEAST8_MAX
-#define DUK_INT_LEAST8_MIN    INT_LEAST8_MIN
-#define DUK_INT_LEAST8_MAX    INT_LEAST8_MAX
-#define DUK_UINT_FAST8_MIN    0
-#define DUK_UINT_FAST8_MAX    UINT_FAST8_MAX
-#define DUK_INT_FAST8_MIN     INT_FAST8_MIN
-#define DUK_INT_FAST8_MAX     INT_FAST8_MAX
-#define DUK_UINT16_MIN        0
-#define DUK_UINT16_MAX        UINT16_MAX
-#define DUK_INT16_MIN         INT16_MIN
-#define DUK_INT16_MAX         INT16_MAX
-#define DUK_UINT_LEAST16_MIN  0
-#define DUK_UINT_LEAST16_MAX  UINT_LEAST16_MAX
-#define DUK_INT_LEAST16_MIN   INT_LEAST16_MIN
-#define DUK_INT_LEAST16_MAX   INT_LEAST16_MAX
-#define DUK_UINT_FAST16_MIN   0
-#define DUK_UINT_FAST16_MAX   UINT_FAST16_MAX
-#define DUK_INT_FAST16_MIN    INT_FAST16_MIN
-#define DUK_INT_FAST16_MAX    INT_FAST16_MAX
-#define DUK_UINT32_MIN        0
-#define DUK_UINT32_MAX        UINT32_MAX
-#define DUK_INT32_MIN         INT32_MIN
-#define DUK_INT32_MAX         INT32_MAX
-#define DUK_UINT_LEAST32_MIN  0
-#define DUK_UINT_LEAST32_MAX  UINT_LEAST32_MAX
-#define DUK_INT_LEAST32_MIN   INT_LEAST32_MIN
-#define DUK_INT_LEAST32_MAX   INT_LEAST32_MAX
-#define DUK_UINT_FAST32_MIN   0
-#define DUK_UINT_FAST32_MAX   UINT_FAST32_MAX
-#define DUK_INT_FAST32_MIN    INT_FAST32_MIN
-#define DUK_INT_FAST32_MAX    INT_FAST32_MAX
-#define DUK_UINT64_MIN        0
-#define DUK_UINT64_MAX        UINT64_MAX
-#define DUK_INT64_MIN         INT64_MIN
-#define DUK_INT64_MAX         INT64_MAX
-#define DUK_UINT_LEAST64_MIN  0
-#define DUK_UINT_LEAST64_MAX  UINT_LEAST64_MAX
-#define DUK_INT_LEAST64_MIN   INT_LEAST64_MIN
-#define DUK_INT_LEAST64_MAX   INT_LEAST64_MAX
-#define DUK_UINT_FAST64_MIN   0
-#define DUK_UINT_FAST64_MAX   UINT_FAST64_MAX
-#define DUK_INT_FAST64_MIN    INT_FAST64_MIN
-#define DUK_INT_FAST64_MAX    INT_FAST64_MAX
-
-#define DUK_UINTPTR_MIN       0
-#define DUK_UINTPTR_MAX       UINTPTR_MAX
-#define DUK_INTPTR_MIN        INTPTR_MIN
-#define DUK_INTPTR_MAX        INTPTR_MAX
-
-#define DUK_UINTMAX_MIN       0
-#define DUK_UINTMAX_MAX       UINTMAX_MAX
-#define DUK_INTMAX_MIN        INTMAX_MIN
-#define DUK_INTMAX_MAX        INTMAX_MAX
-
-#define DUK_SIZE_MIN          0
-#define DUK_SIZE_MAX          SIZE_MAX
-
-#else  /* C99 types */
-
-/* When C99 types are not available, we use heuristic detection to get
- * the basic 8, 16, 32, and (possibly) 64 bit types.  The fast/least
- * types are then assumed to be exactly the same for now: these could
- * be improved per platform but C99 types are very often now available.
- * 64-bit types are not available on all platforms; this is OK at least
- * on 32-bit platforms.
- *
- * This detection code is necessarily a bit hacky and can provide typedefs
- * and defines that won't work correctly on some exotic platform.
- */
-
-#if (defined(CHAR_BIT) && (CHAR_BIT == 8)) || \
-    (defined(UCHAR_MAX) && (UCHAR_MAX == 255))
-typedef unsigned char duk_uint8_t;
-typedef signed char duk_int8_t;
-#else
-#error cannot detect 8-bit type
-#endif
-
-#if defined(USHRT_MAX) && (USHRT_MAX == 65535UL)
-typedef unsigned short duk_uint16_t;
-typedef signed short duk_int16_t;
-#elif defined(UINT_MAX) && (UINT_MAX == 65535UL)
-/* On some platforms int is 16-bit but long is 32-bit (e.g. PureC) */
-typedef unsigned int duk_uint16_t;
-typedef signed int duk_int16_t;
-#else
-#error cannot detect 16-bit type
-#endif
-
-#if defined(UINT_MAX) && (UINT_MAX == 4294967295UL)
-typedef unsigned int duk_uint32_t;
-typedef signed int duk_int32_t;
-#elif defined(ULONG_MAX) && (ULONG_MAX == 4294967295UL)
-/* On some platforms int is 16-bit but long is 32-bit (e.g. PureC) */
-typedef unsigned long duk_uint32_t;
-typedef signed long duk_int32_t;
-#else
-#error cannot detect 32-bit type
-#endif
-
-/* 64-bit type detection is a bit tricky.
- *
- * ULLONG_MAX is a standard define.  __LONG_LONG_MAX__ and __ULONG_LONG_MAX__
- * are used by at least GCC (even if system headers don't provide ULLONG_MAX).
- * Some GCC variants may provide __LONG_LONG_MAX__ but not __ULONG_LONG_MAX__.
- *
- * ULL / LL constants are rejected / warned about by some compilers, even if
- * the compiler has a 64-bit type and the compiler/system headers provide an
- * unsupported constant (ULL/LL)!  Try to avoid using ULL / LL constants.
- * As a side effect we can only check that e.g. ULONG_MAX is larger than 32
- * bits but can't be sure it is exactly 64 bits.  Self tests will catch such
- * cases.
- */
-#undef DUK_F_HAVE_64BIT
-#if !defined(DUK_F_HAVE_64BIT) && defined(ULONG_MAX)
-#if (ULONG_MAX > 4294967295UL)
-#define DUK_F_HAVE_64BIT
-typedef unsigned long duk_uint64_t;
-typedef signed long duk_int64_t;
-#endif
-#endif
-#if !defined(DUK_F_HAVE_64BIT) && defined(ULLONG_MAX)
-#if (ULLONG_MAX > 4294967295UL)
-#define DUK_F_HAVE_64BIT
-typedef unsigned long long duk_uint64_t;
-typedef signed long long duk_int64_t;
-#endif
-#endif
-#if !defined(DUK_F_HAVE_64BIT) && defined(__ULONG_LONG_MAX__)
-#if (__ULONG_LONG_MAX__ > 4294967295UL)
-#define DUK_F_HAVE_64BIT
-typedef unsigned long long duk_uint64_t;
-typedef signed long long duk_int64_t;
-#endif
-#endif
-#if !defined(DUK_F_HAVE_64BIT) && defined(__LONG_LONG_MAX__)
-#if (__LONG_LONG_MAX__ > 2147483647L)
-#define DUK_F_HAVE_64BIT
-typedef unsigned long long duk_uint64_t;
-typedef signed long long duk_int64_t;
-#endif
-#endif
-#if !defined(DUK_F_HAVE_64BIT) && \
-    (defined(DUK_F_MINGW) || defined(DUK_F_MSVC))
-/* Both MinGW and MSVC have a 64-bit type. */
-#define DUK_F_HAVE_64BIT
-typedef unsigned long duk_uint64_t;
-typedef signed long duk_int64_t;
-#endif
-#if !defined(DUK_F_HAVE64BIT)
-/* cannot detect 64-bit type, not always needed so don't error */
-#endif
-
-typedef duk_uint8_t duk_uint_least8_t;
-typedef duk_int8_t duk_int_least8_t;
-typedef duk_uint16_t duk_uint_least16_t;
-typedef duk_int16_t duk_int_least16_t;
-typedef duk_uint32_t duk_uint_least32_t;
-typedef duk_int32_t duk_int_least32_t;
-typedef duk_uint8_t duk_uint_fast8_t;
-typedef duk_int8_t duk_int_fast8_t;
-typedef duk_uint16_t duk_uint_fast16_t;
-typedef duk_int16_t duk_int_fast16_t;
-typedef duk_uint32_t duk_uint_fast32_t;
-typedef duk_int32_t duk_int_fast32_t;
-#if defined(DUK_F_HAVE_64BIT)
-typedef duk_uint64_t duk_uint_least64_t;
-typedef duk_int64_t duk_int_least64_t;
-typedef duk_uint64_t duk_uint_fast64_t;
-typedef duk_int64_t duk_int_fast64_t;
-#endif
-#if defined(DUK_F_HAVE_64BIT)
-typedef duk_uint64_t duk_uintmax_t;
-typedef duk_int64_t duk_intmax_t;
-#else
-typedef duk_uint32_t duk_uintmax_t;
-typedef duk_int32_t duk_intmax_t;
-#endif
-
-/* Note: the funny looking computations for signed minimum 16-bit, 32-bit, and
- * 64-bit values are intentional as the obvious forms (e.g. -0x80000000L) are
- * -not- portable.  See code-issues.txt for a detailed discussion.
- */
-#define DUK_UINT8_MIN         0UL
-#define DUK_UINT8_MAX         0xffUL
-#define DUK_INT8_MIN          (-0x80L)
-#define DUK_INT8_MAX          0x7fL
-#define DUK_UINT_LEAST8_MIN   0UL
-#define DUK_UINT_LEAST8_MAX   0xffUL
-#define DUK_INT_LEAST8_MIN    (-0x80L)
-#define DUK_INT_LEAST8_MAX    0x7fL
-#define DUK_UINT_FAST8_MIN    0UL
-#define DUK_UINT_FAST8_MAX    0xffUL
-#define DUK_INT_FAST8_MIN     (-0x80L)
-#define DUK_INT_FAST8_MAX     0x7fL
-#define DUK_UINT16_MIN        0UL
-#define DUK_UINT16_MAX        0xffffUL
-#define DUK_INT16_MIN         (-0x7fffL - 1L)
-#define DUK_INT16_MAX         0x7fffL
-#define DUK_UINT_LEAST16_MIN  0UL
-#define DUK_UINT_LEAST16_MAX  0xffffUL
-#define DUK_INT_LEAST16_MIN   (-0x7fffL - 1L)
-#define DUK_INT_LEAST16_MAX   0x7fffL
-#define DUK_UINT_FAST16_MIN   0UL
-#define DUK_UINT_FAST16_MAX   0xffffUL
-#define DUK_INT_FAST16_MIN    (-0x7fffL - 1L)
-#define DUK_INT_FAST16_MAX    0x7fffL
-#define DUK_UINT32_MIN        0UL
-#define DUK_UINT32_MAX        0xffffffffUL
-#define DUK_INT32_MIN         (-0x7fffffffL - 1L)
-#define DUK_INT32_MAX         0x7fffffffL
-#define DUK_UINT_LEAST32_MIN  0UL
-#define DUK_UINT_LEAST32_MAX  0xffffffffUL
-#define DUK_INT_LEAST32_MIN   (-0x7fffffffL - 1L)
-#define DUK_INT_LEAST32_MAX   0x7fffffffL
-#define DUK_UINT_FAST32_MIN   0UL
-#define DUK_UINT_FAST32_MAX   0xffffffffUL
-#define DUK_INT_FAST32_MIN    (-0x7fffffffL - 1L)
-#define DUK_INT_FAST32_MAX    0x7fffffffL
-
-/* 64-bit constants.  Since LL / ULL constants are not always available,
- * use computed values.  These values can't be used in preprocessor
- * comparisons; flag them as such.
- */
-#if defined(DUK_F_HAVE_64BIT)
-#define DUK_UINT64_MIN        ((duk_uint64_t) 0)
-#define DUK_UINT64_MAX        ((duk_uint64_t) -1)
-#define DUK_INT64_MIN         ((duk_int64_t) (~(DUK_UINT64_MAX >> 1)))
-#define DUK_INT64_MAX         ((duk_int64_t) (DUK_UINT64_MAX >> 1))
-#define DUK_UINT_LEAST64_MIN  DUK_UINT64_MIN
-#define DUK_UINT_LEAST64_MAX  DUK_UINT64_MAX
-#define DUK_INT_LEAST64_MIN   DUK_INT64_MIN
-#define DUK_INT_LEAST64_MAX   DUK_INT64_MAX
-#define DUK_UINT_FAST64_MIN   DUK_UINT64_MIN
-#define DUK_UINT_FAST64_MAX   DUK_UINT64_MAX
-#define DUK_INT_FAST64_MIN    DUK_INT64_MIN
-#define DUK_INT_FAST64_MAX    DUK_INT64_MAX
-#define DUK_UINT64_MIN_COMPUTED
-#define DUK_UINT64_MAX_COMPUTED
-#define DUK_INT64_MIN_COMPUTED
-#define DUK_INT64_MAX_COMPUTED
-#define DUK_UINT_LEAST64_MIN_COMPUTED
-#define DUK_UINT_LEAST64_MAX_COMPUTED
-#define DUK_INT_LEAST64_MIN_COMPUTED
-#define DUK_INT_LEAST64_MAX_COMPUTED
-#define DUK_UINT_FAST64_MIN_COMPUTED
-#define DUK_UINT_FAST64_MAX_COMPUTED
-#define DUK_INT_FAST64_MIN_COMPUTED
-#define DUK_INT_FAST64_MAX_COMPUTED
-#endif
-
-#if defined(DUK_F_HAVE_64BIT)
-#define DUK_UINTMAX_MIN       DUK_UINT64_MIN
-#define DUK_UINTMAX_MAX       DUK_UINT64_MAX
-#define DUK_INTMAX_MIN        DUK_INT64_MIN
-#define DUK_INTMAX_MAX        DUK_INT64_MAX
-#define DUK_UINTMAX_MIN_COMPUTED
-#define DUK_UINTMAX_MAX_COMPUTED
-#define DUK_INTMAX_MIN_COMPUTED
-#define DUK_INTMAX_MAX_COMPUTED
-#else
-#define DUK_UINTMAX_MIN       0UL
-#define DUK_UINTMAX_MAX       0xffffffffUL
-#define DUK_INTMAX_MIN        (-0x7fffffffL - 1L)
-#define DUK_INTMAX_MAX        0x7fffffffL
-#endif
-
-/* This detection is not very reliable. */
-#if defined(DUK_F_32BIT_PTRS)
-typedef duk_int32_t duk_intptr_t;
-typedef duk_uint32_t duk_uintptr_t;
-#define DUK_UINTPTR_MIN       DUK_UINT32_MIN
-#define DUK_UINTPTR_MAX       DUK_UINT32_MAX
-#define DUK_INTPTR_MIN        DUK_INT32_MIN
-#define DUK_INTPTR_MAX        DUK_INT32_MAX
-#elif defined(DUK_F_64BIT_PTRS) && defined(DUK_F_HAVE_64BIT)
-typedef duk_int64_t duk_intptr_t;
-typedef duk_uint64_t duk_uintptr_t;
-#define DUK_UINTPTR_MIN       DUK_UINT64_MIN
-#define DUK_UINTPTR_MAX       DUK_UINT64_MAX
-#define DUK_INTPTR_MIN        DUK_INT64_MIN
-#define DUK_INTPTR_MAX        DUK_INT64_MAX
-#define DUK_UINTPTR_MIN_COMPUTED
-#define DUK_UINTPTR_MAX_COMPUTED
-#define DUK_INTPTR_MIN_COMPUTED
-#define DUK_INTPTR_MAX_COMPUTED
-#else
-#error cannot determine intptr type
-#endif
-
-/* SIZE_MAX may be missing so use an approximate value for it. */
-#undef DUK_SIZE_MAX_COMPUTED
-#if !defined(SIZE_MAX)
-#define DUK_SIZE_MAX_COMPUTED
-#define SIZE_MAX              ((size_t) (-1))
-#endif
-#define DUK_SIZE_MIN          0
-#define DUK_SIZE_MAX          SIZE_MAX
-
-#endif  /* C99 types */
-
-/* A few types are assumed to always exist. */
-typedef size_t duk_size_t;
-typedef ptrdiff_t duk_ptrdiff_t;
-
-/* The best type for an "all around int" in Duktape internals is "at least
- * 32 bit signed integer" which is most convenient.  Same for unsigned type.
- * Prefer 'int' when large enough, as it is almost always a convenient type.
- */
-#if defined(UINT_MAX) && (UINT_MAX >= 0xffffffffUL)
-typedef int duk_int_t;
-typedef unsigned int duk_uint_t;
-#define DUK_INT_MIN           INT_MIN
-#define DUK_INT_MAX           INT_MAX
-#define DUK_UINT_MIN          0
-#define DUK_UINT_MAX          UINT_MAX
-#else
-typedef duk_int_fast32_t duk_int_t;
-typedef duk_uint_fast32_t duk_uint_t;
-#define DUK_INT_MIN           DUK_INT_FAST32_MIN
-#define DUK_INT_MAX           DUK_INT_FAST32_MAX
-#define DUK_UINT_MIN          DUK_UINT_FAST32_MIN
-#define DUK_UINT_MAX          DUK_UINT_FAST32_MAX
-#endif
-
-/* Same as 'duk_int_t' but guaranteed to be a 'fast' variant if this
- * distinction matters for the CPU.  These types are used mainly in the
- * executor where it might really matter.
- */
-typedef duk_int_fast32_t duk_int_fast_t;
-typedef duk_uint_fast32_t duk_uint_fast_t;
-#define DUK_INT_FAST_MIN      DUK_INT_FAST32_MIN
-#define DUK_INT_FAST_MAX      DUK_INT_FAST32_MAX
-#define DUK_UINT_FAST_MIN     DUK_UINT_FAST32_MIN
-#define DUK_UINT_FAST_MAX     DUK_UINT_FAST32_MAX
-
-/* Small integers (16 bits or more) can fall back to the 'int' type, but
- * have a typedef so they are marked "small" explicitly.
- */
-typedef int duk_small_int_t;
-typedef unsigned int duk_small_uint_t;
-#define DUK_SMALL_INT_MIN     INT_MIN
-#define DUK_SMALL_INT_MAX     INT_MAX
-#define DUK_SMALL_UINT_MIN    0
-#define DUK_SMALL_UINT_MAX    UINT_MAX
-
-/* Fast variants of small integers, again for really fast paths like the
- * executor.
- */
-typedef duk_int_fast16_t duk_small_int_fast_t;
-typedef duk_uint_fast16_t duk_small_uint_fast_t;
-#define DUK_SMALL_INT_FAST_MIN    DUK_INT_FAST16_MIN
-#define DUK_SMALL_INT_FAST_MAX    DUK_INT_FAST16_MAX
-#define DUK_SMALL_UINT_FAST_MIN   DUK_UINT_FAST16_MIN
-#define DUK_SMALL_UINT_FAST_MAX   DUK_UINT_FAST16_MAX
-
-/* Boolean values are represented with the platform 'int'. */
-typedef duk_small_int_t duk_bool_t;
-#define DUK_BOOL_MIN              DUK_SMALL_INT_MIN
-#define DUK_BOOL_MAX              DUK_SMALL_INT_MAX
-
-/* Index values must have at least 32-bit signed range. */
-typedef duk_int_t duk_idx_t;
-#define DUK_IDX_MIN               DUK_INT_MIN
-#define DUK_IDX_MAX               DUK_INT_MAX
-
-/* Array index values, could be exact 32 bits.
- * Currently no need for signed duk_arridx_t.
- */
-typedef duk_uint_t duk_uarridx_t;
-#define DUK_UARRIDX_MIN           DUK_UINT_MIN
-#define DUK_UARRIDX_MAX           DUK_UINT_MAX
-
-/* Duktape/C function return value, platform int is enough for now to
- * represent 0, 1, or negative error code.  Must be compatible with
- * assigning truth values (e.g. duk_ret_t rc = (foo == bar);).
- */
-typedef duk_small_int_t duk_ret_t;
-#define DUK_RET_MIN               DUK_SMALL_INT_MIN
-#define DUK_RET_MAX               DUK_SMALL_INT_MAX
-
-/* Error codes are represented with platform int.  High bits are used
- * for flags and such, so 32 bits are needed.
- */
-typedef duk_int_t duk_errcode_t;
-#define DUK_ERRCODE_MIN           DUK_INT_MIN
-#define DUK_ERRCODE_MAX           DUK_INT_MAX
-
-/* Codepoint type.  Must be 32 bits or more because it is used also for
- * internal codepoints.  The type is signed because negative codepoints
- * are used as internal markers (e.g. to mark EOF or missing argument).
- * (X)UTF-8/CESU-8 encode/decode take and return an unsigned variant to
- * ensure duk_uint32_t casts back and forth nicely.  Almost everything
- * else uses the signed one.
- */
-typedef duk_int_t duk_codepoint_t;
-typedef duk_uint_t duk_ucodepoint_t;
-#define DUK_CODEPOINT_MIN         DUK_INT_MIN
-#define DUK_CODEPOINT_MAX         DUK_INT_MAX
-#define DUK_UCODEPOINT_MIN        DUK_UINT_MIN
-#define DUK_UCODEPOINT_MAX        DUK_UINT_MAX
-
-/* IEEE double typedef. */
-typedef double duk_double_t;
-
-/* We're generally assuming that we're working on a platform with a 32-bit
- * address space.  If DUK_SIZE_MAX is a typecast value (which is necessary
- * if SIZE_MAX is missing), the check must be avoided because the
- * preprocessor can't do a comparison.
- */
-#if !defined(DUK_SIZE_MAX)
-#error DUK_SIZE_MAX is undefined, probably missing SIZE_MAX
-#elif !defined(DUK_SIZE_MAX_COMPUTED)
-#if DUK_SIZE_MAX < 0xffffffffUL
-/* XXX: compare against a lower value; can SIZE_MAX realistically be
- * e.g. 0x7fffffffUL on a 32-bit system?
- */
-#error size_t is too small
-#endif
-#endif
-
-/* Convenience define: 32-bit pointers.  32-bit platforms are an important
- * footprint optimization target, and this define allows e.g. struct sizes
- * to be organized for compactness.
- */
-
-#undef DUK_USE_32BIT_PTRS
-#if defined(DUK_UINTPTR_MAX) && !defined(DUK_UINTPTR_MAX_COMPUTED)
-#if DUK_UINTPTR_MAX <= 0xffffffffUL
-#define DUK_USE_32BIT_PTRS
-#endif
-#endif
-
-/*
- *  Check whether we should use 64-bit integers
- */
-
-/* Quite incomplete now.  Use 64-bit types if detected (C99 or other detection)
- * unless they are known to be unreliable.  For instance, 64-bit types are
- * available on VBCC but seem to misbehave.
- */
-#if defined(DUK_F_HAVE_64BIT) && !defined(DUK_F_VBCC)
-#define DUK_USE_64BIT_OPS
-#else
-#undef DUK_USE_64BIT_OPS
-#endif
-
-/*
- *  Alignment requirement and support for unaligned accesses
- *
- *  Assume unaligned accesses are not supported unless specifically allowed
- *  in the target platform.  Some platforms may support unaligned accesses
- *  but alignment to 4 or 8 may still be desirable.
- */
-
-#undef DUK_USE_UNALIGNED_ACCESSES_POSSIBLE
-#undef DUK_USE_ALIGN_4
-#undef DUK_USE_ALIGN_8
-
-#if defined(DUK_F_EMSCRIPTEN)
-/* Required on at least some targets, so use whenever Emscripten used,
- * regardless of compilation target.
- */
-#define DUK_USE_ALIGN_8
-#elif defined(DUK_F_ARM)
-#define DUK_USE_ALIGN_4
-#elif defined(DUK_F_MIPS)
-#define DUK_USE_ALIGN_4
-#elif defined(DUK_F_X86) || defined(DUK_F_X32) || defined(DUK_F_X64) || \
-      defined(DUK_F_BCC)
-#define DUK_USE_UNALIGNED_ACCESSES_POSSIBLE
-#else
-/* unknown, use safe default */
-#define DUK_USE_ALIGN_8
-#endif
-
-/* User forced alignment to 4 or 8. */
-#if defined(DUK_OPT_FORCE_ALIGN)
-#undef DUK_USE_UNALIGNED_ACCESSES_POSSIBLE
-#undef DUK_USE_ALIGN_4
-#undef DUK_USE_ALIGN_8
-#if (DUK_OPT_FORCE_ALIGN == 4)
-#define DUK_USE_ALIGN_4
-#elif (DUK_OPT_FORCE_ALIGN == 8)
-#define DUK_USE_ALIGN_8
-#else
-#error invalid DUK_OPT_FORCE_ALIGN value
-#endif
-#endif
-
-/* Compiler specific hackery needed to force struct size to match aligment,
- * see e.g. duk_hbuffer.h.
- *
- * http://stackoverflow.com/questions/11130109/c-struct-size-alignment
- * http://stackoverflow.com/questions/10951039/specifying-64-bit-alignment
- */
-#if defined(DUK_F_MSVC)
-#define DUK_USE_PACK_MSVC_PRAGMA
-#elif defined(DUK_F_GCC)
-#define DUK_USE_PACK_GCC_ATTR
-#elif defined(DUK_F_CLANG)
-#define DUK_USE_PACK_CLANG_ATTR
-#else
-#define DUK_USE_PACK_DUMMY_MEMBER
-#endif
-
-#ifdef DUK_USE_UNALIGNED_ACCESSES_POSSIBLE
-#define DUK_USE_HASHBYTES_UNALIGNED_U32_ACCESS
-#else
-#undef DUK_USE_HASHBYTES_UNALIGNED_U32_ACCESS
-#endif
-
-/* Object property allocation layout has implications for memory and code
- * footprint and generated code size/speed.  The best layout also depends
- * on whether the platform has alignment requirements or benefits from
- * having mostly aligned accesses.
- */
-#undef DUK_USE_HOBJECT_LAYOUT_1
-#undef DUK_USE_HOBJECT_LAYOUT_2
-#undef DUK_USE_HOBJECT_LAYOUT_3
-#if defined(DUK_USE_UNALIGNED_ACCESSES_POSSIBLE) && \
-    !defined(DUK_USE_ALIGN_4) && !defined(DUK_USE_ALIGN_8)
-/* On platforms without any alignment issues, layout 1 is preferable
- * because it compiles to slightly less code and provides direct access
- * to property keys.
- */
-#define DUK_USE_HOBJECT_LAYOUT_1
-#else
-/* On other platforms use layout 2, which requires some padding but
- * is a bit more natural than layout 3 in ordering the entries.  Layout
- * 3 is currently not used.
- */
-#define DUK_USE_HOBJECT_LAYOUT_2
-#endif
-
-/*
- *  Byte order and double memory layout detection
- *
- *  Endianness detection is a major portability hassle because the macros
- *  and headers are not standardized.  There's even variance across UNIX
- *  platforms.  Even with "standard" headers, details like underscore count
- *  varies between platforms, e.g. both __BYTE_ORDER and _BYTE_ORDER are used
- *  (Crossbridge has a single underscore, for instance).
- *
- *  The checks below are structured with this in mind: several approaches are
- *  used, and at the end we check if any of them worked.  This allows generic
- *  approaches to be tried first, and platform/compiler specific hacks tried
- *  last.  As a last resort, the user can force a specific endianness, as it's
- *  not likely that automatic detection will work on the most exotic platforms.
- *
- *  Duktape supports little and big endian machines.  There's also support
- *  for a hybrid used by some ARM machines where integers are little endian
- *  but IEEE double values use a mixed order (12345678 -> 43218765).  This
- *  byte order for doubles is referred to as "mixed endian".
- */
-
-#undef DUK_F_BYTEORDER
-#undef DUK_USE_BYTEORDER_FORCED
-
-/* DUK_F_BYTEORDER is set as an intermediate value when detection
- * succeeds, to one of:
- *   1 = little endian
- *   2 = mixed (arm hybrid) endian
- *   3 = big endian
- */
-
-/* For custom platforms allow user to define byteorder explicitly.
- * Since endianness headers are not standardized, this is a useful
- * workaround for custom platforms for which endianness detection
- * is not directly supported.  Perhaps custom hardware is used and
- * user cannot submit upstream patches.
- */
-#if defined(DUK_OPT_FORCE_BYTEORDER)
-#if (DUK_OPT_FORCE_BYTEORDER == 1)
-#define DUK_F_BYTEORDER 1
-#elif (DUK_OPT_FORCE_BYTEORDER == 2)
-#define DUK_F_BYTEORDER 2
-#elif (DUK_OPT_FORCE_BYTEORDER == 3)
-#define DUK_F_BYTEORDER 3
-#else
-#error invalid DUK_OPT_FORCE_BYTEORDER value
-#endif
-#define DUK_USE_BYTEORDER_FORCED
-#endif  /* DUK_OPT_FORCE_BYTEORDER */
-
-/* More or less standard endianness predefines provided by header files.
- * The ARM hybrid case is detected by assuming that __FLOAT_WORD_ORDER
- * will be big endian, see: http://lists.mysql.com/internals/443.
- */
-#if !defined(DUK_F_BYTEORDER)
-#if defined(__BYTE_ORDER) && defined(__LITTLE_ENDIAN) && (__BYTE_ORDER == __LITTLE_ENDIAN) || \
-    defined(_BYTE_ORDER) && defined(_LITTLE_ENDIAN) && (_BYTE_ORDER == _LITTLE_ENDIAN) || \
-    defined(__LITTLE_ENDIAN__)
-/* Integer little endian */
-#if defined(__FLOAT_WORD_ORDER) && defined(__LITTLE_ENDIAN) && (__FLOAT_WORD_ORDER == __LITTLE_ENDIAN) || \
-    defined(_FLOAT_WORD_ORDER) && defined(_LITTLE_ENDIAN) && (_FLOAT_WORD_ORDER == _LITTLE_ENDIAN)
-#define DUK_F_BYTEORDER 1
-#elif defined(__FLOAT_WORD_ORDER) && defined(__BIG_ENDIAN) && (__FLOAT_WORD_ORDER == __BIG_ENDIAN) || \
-      defined(_FLOAT_WORD_ORDER) && defined(_BIG_ENDIAN) && (_FLOAT_WORD_ORDER == _BIG_ENDIAN)
-#define DUK_F_BYTEORDER 2
-#elif !defined(__FLOAT_WORD_ORDER) && !defined(_FLOAT_WORD_ORDER)
-/* Float word order not known, assume not a hybrid. */
-#define DUK_F_BYTEORDER 1
-#else
-/* byte order is little endian but cannot determine IEEE double word order */
-#endif  /* float word order */
-#elif defined(__BYTE_ORDER) && defined(__BIG_ENDIAN) && (__BYTE_ORDER == __BIG_ENDIAN) || \
-      defined(_BYTE_ORDER) && defined(_BIG_ENDIAN) && (_BYTE_ORDER == _BIG_ENDIAN) || \
-      defined(__BIG_ENDIAN__)
-/* Integer big endian */
-#if defined(__FLOAT_WORD_ORDER) && defined(__BIG_ENDIAN) && (__FLOAT_WORD_ORDER == __BIG_ENDIAN) || \
-    defined(_FLOAT_WORD_ORDER) && defined(_BIG_ENDIAN) && (_FLOAT_WORD_ORDER == _BIG_ENDIAN)
-#define DUK_F_BYTEORDER 3
-#elif !defined(__FLOAT_WORD_ORDER) && !defined(_FLOAT_WORD_ORDER)
-/* Float word order not known, assume not a hybrid. */
-#define DUK_F_BYTEORDER 3
-#else
-/* byte order is big endian but cannot determine IEEE double word order */
-#endif  /* float word order */
-#else
-/* cannot determine byte order */
-#endif  /* integer byte order */
-#endif  /* !defined(DUK_F_BYTEORDER) */
-
-/* GCC and Clang provide endianness defines as built-in predefines, with
- * leading and trailing double underscores (e.g. __BYTE_ORDER__).  See
- * output of "make gccpredefs" and "make clangpredefs".  Clang doesn't
- * seem to provide __FLOAT_WORD_ORDER__.
- * http://gcc.gnu.org/onlinedocs/cpp/Common-Predefined-Macros.html
- */
-#if !defined(DUK_F_BYTEORDER) && defined(__BYTE_ORDER__)
-#if defined(__ORDER_LITTLE_ENDIAN__) && (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
-/* Integer little endian */
-#if defined(__FLOAT_WORD_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) && \
-    (__FLOAT_WORD_ORDER__ == __ORDER_LITTLE_ENDIAN__)
-#define DUK_F_BYTEORDER 1
-#elif defined(__FLOAT_WORD_ORDER__) && defined(__ORDER_BIG_ENDIAN__) && \
-      (__FLOAT_WORD_ORDER__ == __ORDER_BIG_ENDIAN__)
-#define DUK_F_BYTEORDER 2
-#elif !defined(__FLOAT_WORD_ORDER__)
-/* Float word order not known, assume not a hybrid. */
-#define DUK_F_BYTEORDER 1
-#else
-/* byte order is little endian but cannot determine IEEE double word order */
-#endif  /* float word order */
-#elif defined(__ORDER_BIG_ENDIAN__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)
-/* Integer big endian */
-#if defined(__FLOAT_WORD_ORDER__) && defined(__ORDER_BIG_ENDIAN__) && \
-    (__FLOAT_WORD_ORDER__ == __ORDER_BIG_ENDIAN__)
-#define DUK_F_BYTEORDER 3
-#elif !defined(__FLOAT_WORD_ORDER__)
-/* Float word order not known, assume not a hybrid. */
-#define DUK_F_BYTEORDER 3
-#else
-/* byte order is big endian but cannot determine IEEE double word order */
-#endif  /* float word order */
-#else
-/* cannot determine byte order; __ORDER_PDP_ENDIAN__ is related to 32-bit
- * integer ordering and is not relevant
- */
-#endif  /* integer byte order */
-#endif  /* !defined(DUK_F_BYTEORDER) && defined(__BYTE_ORDER__) */
-
-/* Atari ST TOS */
-#if !defined(DUK_F_BYTEORDER) && defined(DUK_F_TOS)
-#define DUK_F_BYTEORDER 3
-#endif
-
-/* AmigaOS on M68k */
-#if !defined(DUK_F_BYTEORDER) && defined(DUK_F_AMIGAOS)
-#if defined(DUK_F_M68K)
-#define DUK_F_BYTEORDER 3
-#endif
-#endif
-
-/* On Windows, assume we're little endian.  Even Itanium which has a
- * configurable endianness runs little endian in Windows.
- */
-#if !defined(DUK_F_BYTEORDER) && defined(DUK_F_WINDOWS)
-/* XXX: verify that Windows on ARM is little endian for floating point
- * values too.
- */
-#define DUK_F_BYTEORDER 1
-#endif  /* Windows */
-
-/* Crossbridge should work with the standard byteorder #ifdefs.  It doesn't
- * provide _FLOAT_WORD_ORDER but the standard approach now covers that case
- * too.  This has been left here just in case.
- */
-#if !defined(DUK_F_BYTEORDER) && defined(DUK_F_FLASHPLAYER)
-#define DUK_F_BYTEORDER 1
-#endif
-
-/* QNX gcc cross compiler seems to define e.g. __LITTLEENDIAN__ or __BIGENDIAN__:
- *  $ /opt/qnx650/host/linux/x86/usr/bin/i486-pc-nto-qnx6.5.0-gcc -dM -E - </dev/null | grep -ni endian
- *  67:#define __LITTLEENDIAN__ 1
- *  $ /opt/qnx650/host/linux/x86/usr/bin/mips-unknown-nto-qnx6.5.0-gcc -dM -E - </dev/null | grep -ni endian
- *  81:#define __BIGENDIAN__ 1
- *  $ /opt/qnx650/host/linux/x86/usr/bin/arm-unknown-nto-qnx6.5.0-gcc -dM -E - </dev/null | grep -ni endian
- *  70:#define __LITTLEENDIAN__ 1
- */
-#if !defined(DUK_F_BYTEORDER) && defined(DUK_F_QNX)
-/* XXX: ARM hybrid? */
-#if defined(__LITTLEENDIAN__)
-#define DUK_F_BYTEORDER 1
-#elif defined(__BIGENDIAN__)
-#define DUK_F_BYTEORDER 3
-#endif
-#endif
-
-/* Bruce's C Compiler (BCC), assume we're on x86. */
-#if !defined(DUK_F_BYTEORDER) && defined(DUK_F_BCC)
-#define DUK_F_BYTEORDER 1
-#endif
-
-/* Check whether or not byte order detection worked based on the intermediate
- * define, and define final values.  If detection failed, #error out.
- */
-#if defined(DUK_F_BYTEORDER)
-#if (DUK_F_BYTEORDER == 1)
-#define DUK_USE_INTEGER_LE
-#define DUK_USE_DOUBLE_LE
-#elif (DUK_F_BYTEORDER == 2)
-#define DUK_USE_INTEGER_LE  /* integer endianness is little on purpose */
-#define DUK_USE_DOUBLE_ME
-#elif (DUK_F_BYTEORDER == 3)
-#define DUK_USE_INTEGER_BE
-#define DUK_USE_DOUBLE_BE
-#else
-#error unsupported: byte order detection failed (internal error, should not happen)
-#endif  /* byte order */
-#else
-#error unsupported: byte order detection failed
-#endif  /* defined(DUK_F_BYTEORDER) */
-
-/*
- *  Check whether or not a packed duk_tval representation is possible.
- *  What's basically required is that pointers are 32-bit values
- *  (sizeof(void *) == 4).  Best effort check, not always accurate.
- *  If guess goes wrong, crashes may result; self tests also verify
- *  the guess.
- */
-
-#undef DUK_USE_PACKED_TVAL_POSSIBLE
-
-/* Strict C99 case: DUK_UINTPTR_MAX (= UINTPTR_MAX) should be very reliable */
-#if !defined(DUK_USE_PACKED_TVAL_POSSIBLE) && defined(DUK_F_HAVE_INTTYPES) && defined(DUK_UINTPTR_MAX)
-#if (DUK_UINTPTR_MAX <= 0xffffffffUL)
-#define DUK_USE_PACKED_TVAL_POSSIBLE
-#endif
-#endif
-
-/* Non-C99 case, still relying on DUK_UINTPTR_MAX, as long as it is not a computed value */
-#if !defined(DUK_USE_PACKED_TVAL_POSSIBLE) && defined(DUK_UINTPTR_MAX) && !defined(DUK_UINTPTR_MAX_COMPUTED)
-#if (DUK_UINTPTR_MAX <= 0xffffffffUL)
-#define DUK_USE_PACKED_TVAL_POSSIBLE
-#endif
-#endif
-
-/* DUK_SIZE_MAX (= SIZE_MAX) is often reliable */
-#if !defined(DUK_USE_PACKED_TVAL_POSSIBLE) && defined(DUK_SIZE_MAX) && !defined(DUK_SIZE_MAX_COMPUTED)
-#if DUK_SIZE_MAX <= 0xffffffffUL
-#define DUK_USE_PACKED_TVAL_POSSIBLE
-#endif
-#endif
-
-/* M68K: packed always possible */
-#if !defined(DUK_USE_PACKED_TVAL_POSSIBLE) && defined(DUK_F_M68K)
-#define DUK_USE_PACKED_TVAL_POSSIBLE
-#endif
-
-/* With Emscripten, force unpacked duk_tval just to be safe, as it seems to
- * break at least on Firefox (probably IEEE double arithmetic is not 100%
- * supported, especially for NaNs).
- */
-#if defined(DUK_USE_PACKED_TVAL_POSSIBLE) && defined(DUK_F_EMSCRIPTEN)
-#undef DUK_USE_PACKED_TVAL_POSSIBLE
-#endif
-
-/* Microsoft Visual Studio 2010 on x64 fails the above rules and tries to
- * use a packed type.  Force unpacked on x64 in general.
- */
-#if defined(DUK_USE_PACKED_TVAL_POSSIBLE) && defined(DUK_F_X64)
-#undef DUK_USE_PACKED_TVAL_POSSIBLE
-#endif
-
-/* GCC/clang inaccurate math would break compliance and probably duk_tval,
- * so refuse to compile.  Relax this if -ffast-math is tested to work.
- */
-#if defined(__FAST_MATH__)
-#error __FAST_MATH__ defined, refusing to compile
-#endif
-
-/*
- *  Detection of double constants and math related functions.  Availability
- *  of constants and math functions is a significant porting concern.
- *
- *  INFINITY/HUGE_VAL is problematic on GCC-3.3: it causes an overflow warning
- *  and there is no pragma in GCC-3.3 to disable it.  Using __builtin_inf()
- *  avoids this problem for some reason.
- */
-
-#define DUK_DOUBLE_2TO32     4294967296.0
-#define DUK_DOUBLE_2TO31     2147483648.0
-
-#undef DUK_USE_COMPUTED_INFINITY
-#if defined(DUK_F_GCC_VERSION) && (DUK_F_GCC_VERSION < 40600)
-/* GCC older than 4.6: avoid overflow warnings related to using INFINITY */
-#define DUK_DOUBLE_INFINITY  (__builtin_inf())
-#elif defined(INFINITY)
-#define DUK_DOUBLE_INFINITY  ((double) INFINITY)
-#elif !defined(DUK_F_VBCC) && !defined(DUK_F_MSVC) && !defined(DUK_F_BCC)
-#define DUK_DOUBLE_INFINITY  (1.0 / 0.0)
-#else
-/* In VBCC (1.0 / 0.0) results in a warning and 0.0 instead of infinity.
- * Use a computed infinity (initialized when a heap is created at the
- * latest).
- */
-extern double duk_computed_infinity;
-#define DUK_USE_COMPUTED_INFINITY
-#define DUK_DOUBLE_INFINITY  duk_computed_infinity
-#endif
-
-#undef DUK_USE_COMPUTED_NAN
-#if defined(NAN)
-#define DUK_DOUBLE_NAN       NAN
-#elif !defined(DUK_F_VBCC) && !defined(DUK_F_MSVC) && !defined(DUK_F_BCC)
-#define DUK_DOUBLE_NAN       (0.0 / 0.0)
-#else
-/* In VBCC (0.0 / 0.0) results in a warning and 0.0 instead of NaN.
- * In MSVC (VS2010 Express) (0.0 / 0.0) results in a compile error.
- * Use a computed NaN (initialized when a heap is created at the
- * latest).
- */
-extern double duk_computed_nan;
-#define DUK_USE_COMPUTED_NAN
-#define DUK_DOUBLE_NAN       duk_computed_nan
-#endif
-
-/* Many platforms are missing fpclassify() and friends, so use replacements
- * if necessary.  The replacement constants (FP_NAN etc) can be anything but
- * match Linux constants now.
- */
-#undef DUK_USE_REPL_FPCLASSIFY
-#undef DUK_USE_REPL_SIGNBIT
-#undef DUK_USE_REPL_ISFINITE
-#undef DUK_USE_REPL_ISNAN
-#undef DUK_USE_REPL_ISINF
-
-/* Complex condition broken into separate parts. */
-#undef DUK_F_USE_REPL_ALL
-#if !(defined(FP_NAN) && defined(FP_INFINITE) && defined(FP_ZERO) && \
-      defined(FP_SUBNORMAL) && defined(FP_NORMAL))
-/* Missing some obvious constants. */
-#define DUK_F_USE_REPL_ALL
-#elif defined(DUK_F_AMIGAOS) && defined(DUK_F_VBCC)
-/* VBCC is missing the built-ins even in C99 mode (perhaps a header issue) */
-#define DUK_F_USE_REPL_ALL
-#elif defined(DUK_F_FREEBSD) && defined(DUK_F_CLANG)
-/* Placeholder fix for (detection is wider than necessary):
- * http://llvm.org/bugs/show_bug.cgi?id=17788
- */
-#define DUK_F_USE_REPL_ALL
-#elif defined(DUK_F_UCLIBC)
-/* At least some uclibc versions have broken floating point math.  For
- * example, fpclassify() can incorrectly classify certain NaN formats.
- * To be safe, use replacements.
- */
-#define DUK_F_USE_REPL_ALL
-#endif
-
-#if defined(DUK_F_USE_REPL_ALL)
-#define DUK_USE_REPL_FPCLASSIFY
-#define DUK_USE_REPL_SIGNBIT
-#define DUK_USE_REPL_ISFINITE
-#define DUK_USE_REPL_ISNAN
-#define DUK_USE_REPL_ISINF
-#define DUK_FPCLASSIFY       duk_repl_fpclassify
-#define DUK_SIGNBIT          duk_repl_signbit
-#define DUK_ISFINITE         duk_repl_isfinite
-#define DUK_ISNAN            duk_repl_isnan
-#define DUK_ISINF            duk_repl_isinf
-#define DUK_FP_NAN           0
-#define DUK_FP_INFINITE      1
-#define DUK_FP_ZERO          2
-#define DUK_FP_SUBNORMAL     3
-#define DUK_FP_NORMAL        4
-#else
-#define DUK_FPCLASSIFY       fpclassify
-#define DUK_SIGNBIT          signbit
-#define DUK_ISFINITE         isfinite
-#define DUK_ISNAN            isnan
-#define DUK_ISINF            isinf
-#define DUK_FP_NAN           FP_NAN
-#define DUK_FP_INFINITE      FP_INFINITE
-#define DUK_FP_ZERO          FP_ZERO
-#define DUK_FP_SUBNORMAL     FP_SUBNORMAL
-#define DUK_FP_NORMAL        FP_NORMAL
-#endif
-
-#if defined(DUK_F_USE_REPL_ALL)
-#undef DUK_F_USE_REPL_ALL
-#endif
-
-/* Some math functions are C99 only.  This is also an issue with some
- * embedded environments using uclibc where uclibc has been configured
- * not to provide some functions.  For now, use replacements whenever
- * using uclibc.
- */
-#undef DUK_USE_MATH_FMIN
-#undef DUK_USE_MATH_FMAX
-#undef DUK_USE_MATH_ROUND
-#if defined(DUK_F_UCLIBC)
-/* uclibc may be missing these */
-#elif defined(DUK_F_AMIGAOS) && defined(DUK_F_VBCC)
-/* vbcc + AmigaOS may be missing these */
-#elif !defined(DUK_F_C99) && !defined(DUK_F_CPP11)
-/* build is not C99 or C++11, play it safe */
-#else
-/* C99 or C++11, no known issues */
-#define DUK_USE_MATH_FMIN
-#define DUK_USE_MATH_FMAX
-#define DUK_USE_MATH_ROUND
-#endif
-
-/* These functions don't currently need replacement but are wrapped for
- * completeness.  Because these are used as function pointers, they need
- * to be defined as concrete C functions (not macros).
- */
-#define DUK_FABS             fabs
-#define DUK_FMIN             fmin
-#define DUK_FMAX             fmax
-#define DUK_FLOOR            floor
-#define DUK_CEIL             ceil
-#define DUK_FMOD             fmod
-#define DUK_POW              pow
-#define DUK_ACOS             acos
-#define DUK_ASIN             asin
-#define DUK_ATAN             atan
-#define DUK_ATAN2            atan2
-#define DUK_SIN              sin
-#define DUK_COS              cos
-#define DUK_TAN              tan
-#define DUK_EXP              exp
-#define DUK_LOG              log
-#define DUK_SQRT             sqrt
-
-/* NetBSD 6.0 x86 (at least) has a few problems with pow() semantics,
- * see test-bug-netbsd-math-pow.js.  Use NetBSD specific workaround.
- * (This might be a wider problem; if so, generalize the define name.)
- */
-#undef DUK_USE_POW_NETBSD_WORKAROUND
-#if defined(DUK_F_NETBSD)
-#define DUK_USE_POW_NETBSD_WORKAROUND
-#endif
-
-/* Rely as little as possible on compiler behavior for NaN comparison,
- * signed zero handling, etc.  Currently never activated but may be needed
- * for broken compilers.
- */
-#undef DUK_USE_PARANOID_MATH
-
-/* There was a curious bug where test-bi-date-canceling.js would fail e.g.
- * on 64-bit Ubuntu, gcc-4.8.1, -m32, and no -std=c99.  Some date computations
- * using doubles would be optimized which then broke some corner case tests.
- * The problem goes away by adding 'volatile' to the datetime computations.
- * Not sure what the actual triggering conditions are, but using this on
- * non-C99 systems solves the known issues and has relatively little cost
- * on other platforms.  See bugs/issue-2e9d9c2d761dabaf8136c0897b91a270d1a47147.yaml.
- */
-#undef DUK_USE_PARANOID_DATE_COMPUTATION
-#if !defined(DUK_F_C99)
-#define DUK_USE_PARANOID_DATE_COMPUTATION
-#endif
-
-/*
- *  ANSI C string/memory function wrapper defines to allow easier workarounds.
- *  Also convenience macros like DUK_MEMZERO which may be mapped to existing
- *  platform function to zero memory (like the deprecated bzero).
- *
- *  For instance, some platforms don't support zero-size memcpy correctly,
- *  some arcane uclibc versions have a buggy memcpy (but working memmove)
- *  and so on.  Such broken platforms can be dealt with here.
- *
- *  NOTE: ANSI C (various versions) and some implementations require that the
- *  pointer arguments to memset(), memcpy(), and memmove() be valid values
- *  even when byte size is 0 (even a NULL pointer is considered invalid in
- *  this context).  Zero-size operations as such are allowed, as long as their
- *  pointer arguments point to a valid memory area.  The DUK_MEMSET(),
- *  DUK_MEMCPY(), and DUK_MEMMOVE() macros require this same behavior, i.e.:
- *  (1) pointers must be valid and non-NULL, (2) zero size must otherwise be
- *  allowed.  If these are not fulfilled, a macro wrapper is needed.
- *
- *    http://stackoverflow.com/questions/5243012/is-it-guaranteed-to-be-safe-to-perform-memcpy0-0-0
- *    http://lists.cs.uiuc.edu/pipermail/llvmdev/2007-October/011065.html
- *
- *  Not sure what's the required behavior when a pointer points just past the
- *  end of a buffer, which often happens in practice (e.g. zero size memmoves).
- *  For example, if allocation size is 3, the following pointer would not
- *  technically point to a valid memory byte:
- *
- *    <-- alloc -->
- *    | 0 | 1 | 2 | .....
- *                  ^-- p=3, points after last valid byte (2)
- *
- *  If this is a practical issue, wrappers are again needed.
- */
-
-typedef FILE duk_file;
-#define DUK_STDIN       stdin
-#define DUK_STDOUT      stdout
-#define DUK_STDERR      stderr
-
-/* Special naming to avoid conflict with e.g. DUK_FREE() in duk_heap.h
- * (which is unfortunately named).
- */
-#define DUK_ANSI_MALLOC      malloc
-#define DUK_ANSI_REALLOC     realloc
-#define DUK_ANSI_CALLOC      calloc
-#define DUK_ANSI_FREE        free
-
-/* Old uclibcs have a broken memcpy so use memmove instead (this is overly
- * wide now on purpose):
- * http://lists.uclibc.org/pipermail/uclibc-cvs/2008-October/025511.html
- */
-#if defined(DUK_F_UCLIBC)
-#define DUK_MEMCPY       memmove
-#else
-#define DUK_MEMCPY       memcpy
-#endif
-
-#define DUK_MEMMOVE      memmove
-#define DUK_MEMCMP       memcmp
-#define DUK_MEMSET       memset
-#define DUK_STRLEN       strlen
-#define DUK_STRCMP       strcmp
-#define DUK_STRNCMP      strncmp
-#define DUK_PRINTF       printf
-#define DUK_FPRINTF      fprintf
-#define DUK_SPRINTF      sprintf
-
-#if defined(DUK_F_MSVC)
-/* _snprintf() does NOT NUL terminate on truncation, but Duktape code never
- * assumes that.
- * http://stackoverflow.com/questions/2915672/snprintf-and-visual-studio-2010
- */
-#define DUK_SNPRINTF     _snprintf
-#else
-#define DUK_SNPRINTF     snprintf
-#endif
-
-#define DUK_VSPRINTF     vsprintf
-
-#if defined(DUK_F_MSVC)
-#if (_MSC_VER < 1600)
-/* Older MSVC version are missing vsnprintf() but have _vsnprintf(). */
-#define DUK_VSNPRINTF    _vsnprintf
-#else
-#define DUK_VSNPRINTF    vsnprintf
-#endif
-#else
-#define DUK_VSNPRINTF    vsnprintf
-#endif  /* DUK_F_MSVC */
-
-#define DUK_SSCANF       sscanf
-#define DUK_VSSCANF      vsscanf
-#define DUK_FOPEN        fopen
-#define DUK_FCLOSE       fclose
-#define DUK_FREAD        fread
-#define DUK_FWRITE       fwrite
-#define DUK_FSEEK        fseek
-#define DUK_FTELL        ftell
-#define DUK_FFLUSH       fflush
-#define DUK_FPUTC        fputc
-
-#define DUK_MEMZERO(p,n) \
-	DUK_MEMSET((p), 0, (n))
-
-/*
- *  Avoiding platform function pointers.
- *
- *  On some platforms built-in functions may be implemented as macros or
- *  inline functions, so they can't be necessarily addressed by function
- *  pointers.  This is certainly the case with some platform "polyfills"
- *  which provide missing C99/C++11 functions through macros, and may be
- *  the case with VS2013 (see GH-17).
- */
-
-/* This is now the default: the cost in footprint is negligible. */
-#define DUK_USE_AVOID_PLATFORM_FUNCPTRS
-
-/*
- *  Vararg macro wrappers.  We need va_copy() which is defined in C99 / C++11,
- *  so an awkward replacement is needed for pre-C99 / pre-C++11 environments.
- *  This will quite likely need portability hacks for some non-C99 environments.
- */
-
-#if defined(DUK_F_C99) || defined(DUK_F_CPP11)
-/* C99 / C++11 and above: rely on va_copy() which is required.
- * Omit parenthesis on macro right side on purpose to minimize differences
- * to direct use.
- */
-#define DUK_VA_COPY(dest,src) va_copy(dest,src)
-#elif defined(DUK_F_GCC) || defined(DUK_F_CLANG)
-/* GCC: assume we have __va_copy() in non-C99 mode, which should be correct
- * for even quite old GCC versions.  Clang matches GCC behavior.
- */
-#define DUK_VA_COPY(dest,src) __va_copy(dest,src)
-#else
-/* Pre-C99: va_list type is implementation dependent.  This replacement
- * assumes it is a plain value so that a simple assignment will work.
- * This is not the case on all platforms (it may be a single-array element,
- * for instance).
- */
-#define DUK_VA_COPY(dest,src) do { (dest) = (src); } while (0)
-#endif
-
-/*
- *  Miscellaneous ANSI C or other platform wrappers.
- */
-
-#define DUK_ABORT        abort
-#define DUK_EXIT         exit
-#define DUK_SETJMP       setjmp
-#define DUK_LONGJMP      longjmp
-
-/*
- *  Macro hackery to convert e.g. __LINE__ to a string without formatting,
- *  see: http://stackoverflow.com/questions/240353/convert-a-preprocessor-token-to-a-string
- */
-
-#define DUK_F_STRINGIFY_HELPER(x)  #x
-#define DUK_MACRO_STRINGIFY(x)  DUK_F_STRINGIFY_HELPER(x)
-
-/*
- *  Cause segfault macro.
- *
- *  This is optionally used by panic handling to cause the program to segfault
- *  (instead of e.g. abort()) on panic.  Valgrind will then indicate the C
- *  call stack leading to the panic.
- */
-
-#define DUK_CAUSE_SEGFAULT()  do { \
-		*((duk_uint32_t *) NULL) = (duk_uint32_t) 0xdeadbeefUL; \
-	} while (0)
-
-/*
- *  Macro for suppressing warnings for potentially unreferenced variables.
- *  The variables can be actually unreferenced or unreferenced in some
- *  specific cases only; for instance, if a variable is only debug printed,
- *  it is unreferenced when debug printing is disabled.
- *
- *  (Introduced here because it's potentially compiler specific.)
- */
-
-#define DUK_UNREF(x)  do { \
-		(void) (x); \
-	} while (0)
-
-/*
- *  DUK_NORETURN: macro for declaring a 'noreturn' function.
- *  Unfortunately the noreturn declaration may appear in various
- *  places of a function declaration, so the solution is to wrap
- *  the entire declaration inside the macro.  Compiler support
- *  for using a noreturn declaration on function pointers varies;
- *  this macro must only be used for actual function declarations.
- *
- *  http://gcc.gnu.org/onlinedocs/gcc-4.3.2//gcc/Function-Attributes.html
- *  http://clang.llvm.org/docs/LanguageExtensions.html
- */
-
-#if defined(DUK_F_GCC_VERSION) && (DUK_F_GCC_VERSION >= 20500L)
-/* since gcc-2.5 */
-#define DUK_NORETURN(decl)  decl __attribute__((noreturn))
-#elif defined(__clang__)
-/* syntax same as gcc */
-#define DUK_NORETURN(decl)  decl __attribute__((noreturn))
-#elif defined(DUK_F_MSVC)
-/* http://msdn.microsoft.com/en-us/library/aa235362(VS.60).aspx */
-#define DUK_NORETURN(decl)  __declspec(noreturn) decl
-#else
-/* Don't know how to declare a noreturn function, so don't do it; this
- * may cause some spurious compilation warnings (e.g. "variable used
- * uninitialized").
- */
-#define DUK_NORETURN(decl)  decl
-#endif
-
-/*
- *  Macro for stating that a certain line cannot be reached.
- *
- *  http://gcc.gnu.org/onlinedocs/gcc-4.5.0/gcc/Other-Builtins.html#Other-Builtins
- *  http://clang.llvm.org/docs/LanguageExtensions.html
- */
-
-#if defined(DUK_F_GCC_VERSION) && (DUK_F_GCC_VERSION >= 40500L)
-/* since gcc-4.5 */
-#define DUK_UNREACHABLE()  do { __builtin_unreachable(); } while(0)
-#elif defined(__clang__) && defined(__has_builtin)
-#if __has_builtin(__builtin_unreachable)
-/* same as gcc */
-#define DUK_UNREACHABLE()  do { __builtin_unreachable(); } while(0)
-#endif
-#else
-/* unknown */
-#endif
-
-#if !defined(DUK_UNREACHABLE)
-/* Don't know how to declare unreachable point, so don't do it; this
- * may cause some spurious compilation warnings (e.g. "variable used
- * uninitialized").
- */
-#define DUK_UNREACHABLE()  /* unreachable */
-#endif
-
-/*
- *  Likely and unlikely branches.  Using these is not at all a clear cut case,
- *  so the selection is a two-step process: (1) DUK_USE_BRANCH_HINTS is set
- *  if the architecture, compiler etc make it useful to use the hints, and (2)
- *  a separate check determines how to do them.
- *
- *  These macros expect the argument to be a relational expression with an
- *  integer value.  If used with pointers, you should use an explicit check
- *  like:
- *
- *    if (DUK_LIKELY(ptr != NULL)) { ... }
- *
- *  instead of:
- *
- *    if (DUK_LIKELY(ptr)) { ... }
- *
- *  http://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html  (__builtin_expect)
- */
-
-/* pretty much a placeholder now */
-#if defined(DUK_F_GCC)
-#define DUK_USE_BRANCH_HINTS
-#elif defined(DUK_F_CLANG)
-#define DUK_USE_BRANCH_HINTS
-#else
-#undef DUK_USE_BRANCH_HINTS
-#endif
-
-#if defined(DUK_USE_BRANCH_HINTS)
-#if defined(DUK_F_GCC_VERSION) && (DUK_F_GCC_VERISON >= 40500L)
-/* GCC: test not very accurate; enable only in relatively recent builds
- * because of bugs in gcc-4.4 (http://lists.debian.org/debian-gcc/2010/04/msg00000.html)
- */
-#define DUK_LIKELY(x)    __builtin_expect((x), 1)
-#define DUK_UNLIKELY(x)  __builtin_expect((x), 0)
-#elif defined(DUK_F_CLANG)
-#define DUK_LIKELY(x)    __builtin_expect((x), 1)
-#define DUK_UNLIKELY(x)  __builtin_expect((x), 0)
-#endif
-#endif  /* DUK_USE_BRANCH_HINTS */
-
-#if !defined(DUK_LIKELY)
-#define DUK_LIKELY(x)    (x)
-#endif
-#if !defined(DUK_UNLIKELY)
-#define DUK_UNLIKELY(x)  (x)
-#endif
-
-/*
- *  __FILE__, __LINE__, __func__ are wrapped.  Especially __func__ is a
- *  problem because it is not available even in some compilers which try
- *  to be C99 compatible (e.g. VBCC with -c99 option).
- */
-
-#define DUK_FILE_MACRO  __FILE__
-
-#define DUK_LINE_MACRO  __LINE__
-
-#if !defined(DUK_F_VBCC) && !defined(DUK_F_MSVC)
-#define DUK_FUNC_MACRO  __func__
-#else
-#define DUK_FUNC_MACRO  "unknown"
-#endif
-
-/*
- *  Architecture string, human readable value exposed in Duktape.env
- */
-
-#if defined(DUK_F_X86)
-#define DUK_USE_ARCH_STRING "x86"
-#elif defined(DUK_F_X32)
-#define DUK_USE_ARCH_STRING "x32"
-#elif defined(DUK_F_X64)
-#define DUK_USE_ARCH_STRING "x64"
-#elif defined(DUK_F_ARM)
-#define DUK_USE_ARCH_STRING "arm"
-#elif defined(DUK_F_MIPS)
-#define DUK_USE_ARCH_STRING "mips"
-#elif defined(DUK_F_M68K)
-#define DUK_USE_ARCH_STRING "m68k"
-#elif defined(DUK_F_FLASHPLAYER)
-#define DUK_USE_ARCH_STRING "flashplayer"
-#elif defined(DUK_F_EMSCRIPTEN)
-#define DUK_USE_ARCH_STRING "emscripten"
-#else
-#define DUK_USE_ARCH_STRING "unknown"
-#endif
-
-/* 
- *  Tagged type representation (duk_tval)
- */
-
-#undef DUK_USE_PACKED_TVAL
-#undef DUK_USE_FULL_TVAL
-
-#if defined(DUK_USE_PACKED_TVAL_POSSIBLE) && !defined(DUK_OPT_NO_PACKED_TVAL)
-#define DUK_USE_PACKED_TVAL
-#undef DUK_USE_FULL_TVAL
-#endif
-
-/*
- *  Memory management options
- */
-
-#define DUK_USE_REFERENCE_COUNTING
-#define DUK_USE_DOUBLE_LINKED_HEAP
-#define DUK_USE_MARK_AND_SWEEP
-#define DUK_USE_MS_STRINGTABLE_RESIZE
-#undef DUK_USE_GC_TORTURE
-
-#if defined(DUK_OPT_NO_REFERENCE_COUNTING)
-#undef DUK_USE_REFERENCE_COUNTING
-#undef DUK_USE_DOUBLE_LINKED_HEAP
-/* XXX: undef DUK_USE_MS_STRINGTABLE_RESIZE as it is more expensive
- * with more frequent mark-and-sweeps?
- */
-#endif
-
-#if defined(DUK_OPT_NO_MARK_AND_SWEEP)
-#undef DUK_USE_MARK_AND_SWEEP
-#endif
-
-#if defined(DUK_USE_MARK_AND_SWEEP)
-#define DUK_USE_VOLUNTARY_GC
-#if defined(DUK_OPT_NO_VOLUNTARY_GC)
-#undef DUK_USE_VOLUNTARY_GC
-#endif
-#endif
-
-#if !defined(DUK_USE_MARK_AND_SWEEP) && !defined(DUK_USE_REFERENCE_COUNTING)
-#error must have either mark-and-sweep or reference counting enabled
-#endif
-
-#if defined(DUK_OPT_NO_MS_STRINGTABLE_RESIZE)
-#undef DUK_USE_MS_STRINGTABLE_RESIZE
-#endif
-
-#if defined(DUK_OPT_GC_TORTURE)
-#define DUK_USE_GC_TORTURE
-#endif
-
-/*
- *  Error handling options
- */
-
-#define DUK_USE_AUGMENT_ERROR_CREATE
-#define DUK_USE_AUGMENT_ERROR_THROW
-#define DUK_USE_TRACEBACKS
-#define DUK_USE_ERRCREATE
-#define DUK_USE_ERRTHROW
-
-#define DUK_USE_VERBOSE_ERRORS
-
-#if defined(DUK_OPT_NO_AUGMENT_ERRORS)
-#undef DUK_USE_AUGMENT_ERROR_CREATE
-#undef DUK_USE_AUGMENT_ERROR_THROW
-#undef DUK_USE_TRACEBACKS
-#undef DUK_USE_ERRCREATE
-#undef DUK_USE_ERRTHROW
-#elif defined(DUK_OPT_NO_TRACEBACKS)
-#undef DUK_USE_TRACEBACKS
-#endif
-
-#if defined(DUK_OPT_NO_VERBOSE_ERRORS)
-#undef DUK_USE_VERBOSE_ERRORS
-#endif
-
-#if defined(DUK_USE_TRACEBACKS)
-#if defined(DUK_OPT_TRACEBACK_DEPTH)
-#define DUK_USE_TRACEBACK_DEPTH  DUK_OPT_TRACEBACK_DEPTH
-#else
-#define DUK_USE_TRACEBACK_DEPTH  10
-#endif
-#endif
-
-/* Include messages in executor internal errors. */
-#define DUK_USE_VERBOSE_EXECUTOR_ERRORS
-
-/*
- *  Execution and debugger options
- */
-
-#define DUK_USE_INTERRUPT_COUNTER
-#if defined(DUK_OPT_NO_INTERRUPT_COUNTER)
-#undef DUK_USE_INTERRUPT_COUNTER
-#endif
-
-/* For opcodes with indirect indices, check final index against stack size.
- * This should not be necessary because the compiler is trusted, and we don't
- * bound check non-indirect indices either.
- */
-#undef DUK_USE_EXEC_INDIRECT_BOUND_CHECK
-#if defined(DUK_OPT_DEBUG) || defined(DUK_OPT_ASSERTIONS)
-/* Enabled with debug/assertions just so that any issues can be caught. */
-#define DUK_USE_EXEC_INDIRECT_BOUND_CHECK
-#endif
-
-/*
- *  Debug printing and assertion options
- */
-
-#undef DUK_USE_DEBUG
-#undef DUK_USE_DPRINT
-#undef DUK_USE_DDPRINT
-#undef DUK_USE_DDDPRINT
-#undef DUK_USE_DPRINT_RDTSC
-#undef DUK_USE_ASSERTIONS
-
-/* Global debug enable.  Compile must be clean on C99 regardless of whether or
- * not debugging is enabled.  On non-C99 platforms compile should be clean with
- * debugging disabled but may produce warnings with debugging enabled (related
- * to debug macro hackery and such).
- */
-#if defined(DUK_OPT_DEBUG)
-#define DUK_USE_DEBUG
-#endif
-
-#if defined(DUK_OPT_DEBUG) && defined(DUK_OPT_DPRINT)
-#define DUK_USE_DPRINT
-#endif
-#if defined(DUK_OPT_DEBUG) && defined(DUK_OPT_DDPRINT)
-#define DUK_USE_DDPRINT
-#endif
-#if defined(DUK_OPT_DEBUG) && defined(DUK_OPT_DDDPRINT)
-#define DUK_USE_DDDPRINT
-#endif
-
-#undef DUK_USE_DPRINT_COLORS
-#if defined(DUK_OPT_DPRINT_COLORS)
-#define DUK_USE_DPRINT_COLORS
-#endif
-
-#if defined(DUK_RDTSC_AVAILABLE) && defined(DUK_OPT_DPRINT_RDTSC)
-#define DUK_USE_DPRINT_RDTSC
-#else
-#undef DUK_USE_DPRINT_RDTSC
-#endif
-
-#if defined(DUK_OPT_ASSERTIONS)
-#define DUK_USE_ASSERTIONS
-#endif
-
-/* The static buffer for debug printing is quite large by default, so there
- * is an option to shrink it manually for constrained builds.
- */
-#if defined(DUK_OPT_DEBUG_BUFSIZE)
-#define DUK_USE_DEBUG_BUFSIZE  DUK_OPT_DEBUG_BUFSIZE
-#else
-#define DUK_USE_DEBUG_BUFSIZE  65536L
-#endif
-
-/*
- *  Ecmascript features / compliance options
- */
-
-#if defined(DUK_F_BCC)
-/* Math built-in is stubbed out on BCC to allow compiler torture testing. */
-#else
-#define DUK_USE_MATH_BUILTIN
-#endif
-
-#define DUK_USE_REGEXP_SUPPORT
-#if defined(DUK_OPT_NO_REGEXP_SUPPORT)
-#undef DUK_USE_REGEXP_SUPPORT
-#endif
-
-#undef DUK_USE_STRICT_UTF8_SOURCE
-#if defined(DUK_OPT_STRICT_UTF8_SOURCE)
-#define DUK_USE_STRICT_UTF8_SOURCE
-#endif
-
-#define DUK_USE_OCTAL_SUPPORT
-#if defined(DUK_OPT_NO_OCTAL_SUPPORT)
-#undef DUK_USE_OCTAL_SUPPORT
-#endif
-
-#define DUK_USE_SOURCE_NONBMP
-#if defined(DUK_OPT_NO_SOURCE_NONBMP)
-#undef DUK_USE_SOURCE_NONBMP
-#endif
-
-#define DUK_USE_BROWSER_LIKE
-#if defined(DUK_OPT_NO_BROWSER_LIKE)
-#undef DUK_USE_BROWSER_LIKE
-#endif
-
-/* E5/E5.1 Section B features. */
-#define DUK_USE_SECTION_B
-#if defined(DUK_OPT_NO_SECTION_B)
-#undef DUK_USE_SECTION_B
-#endif
-
-/* Non-standard regexp parsing features. */
-#define DUK_USE_NONSTD_REGEXP_DOLLAR_ESCAPE
-
-/* Treat function statements (function declarations outside top level of
- * Program or FunctionBody) same as normal function declarations.  This is
- * also V8 behavior.  See test-dev-func-decl-outside-top.js.
- */ 
-#define DUK_USE_NONSTD_FUNC_STMT
-#if defined(DUK_OPT_NO_NONSTD_FUNC_STMT)
-#undef DUK_USE_NONSTD_FUNC_STMT
-#endif
-
-/* Array.prototype.splice() non-standard but real world compatible behavior
- * when deleteCount is omitted.
- */
-#define DUK_USE_NONSTD_ARRAY_SPLICE_DELCOUNT
-#if defined(DUK_OPT_NO_NONSTD_ARRAY_SPLICE_DELCOUNT)
-#undef DUK_USE_NONSTD_ARRAY_SPLICE_DELCOUNT
-#endif
-
-/* Non-standard 'caller' property for function instances, see
- * test-bi-function-nonstd-caller-prop.js.
- */
-#undef DUK_USE_NONSTD_FUNC_CALLER_PROPERTY
-#if defined(DUK_OPT_NONSTD_FUNC_CALLER_PROPERTY)
-#define DUK_USE_NONSTD_FUNC_CALLER_PROPERTY
-#endif
-
-/* Non-standard Object.prototype.__proto__ (ES6 draft), see
- * test-bi-object-proto-__proto__.js.
- */
-#define DUK_USE_ES6_OBJECT_PROTO_PROPERTY
-#if defined(DUK_OPT_NO_ES6_OBJECT_PROTO_PROPERTY)
-#undef DUK_USE_ES6_OBJECT_PROTO_PROPERTY
-#endif
-
-/* Non-standard Object.setPrototypeOf (ES6 draft), see
- * test-bi-object-setprototypeof.js.
- */
-#define DUK_USE_ES6_OBJECT_SETPROTOTYPEOF
-#if defined(DUK_OPT_NO_ES6_OBJECT_SETPROTOTYPEOF)
-#undef DUK_USE_ES6_OBJECT_SETPROTOTYPEOF
-#endif
-
-/* ES6 Proxy object (subset for now). */
-#define DUK_USE_ES6_PROXY
-#if defined(DUK_OPT_NO_ES6_PROXY)
-#undef DUK_USE_ES6_PROXY
-#endif
-
-/* Record pc-to-line information. */
-#define DUK_USE_PC2LINE
-#if defined(DUK_OPT_NO_PC2LINE)
-#undef DUK_USE_PC2LINE
-#endif
-
-/* Non-standard function 'source' property. */
-#undef DUK_USE_NONSTD_FUNC_SOURCE_PROPERTY
-#if defined(DUK_OPT_NONSTD_FUNC_SOURCE_PROPERTY)
-#define DUK_USE_NONSTD_FUNC_SOURCE_PROPERTY
-#endif
-
-/* CommonJS modules */
-#define DUK_USE_COMMONJS_MODULES
-#if defined(DUK_OPT_NO_COMMONJS_MODULES)
-#undef DUK_USE_COMMONJS_MODULES
-#endif
-
-/* Additional key argument to setter/getter calls when triggered by property
- * accesses.
- */
-
-#define DUK_USE_NONSTD_GETTER_KEY_ARGUMENT
-#define DUK_USE_NONSTD_SETTER_KEY_ARGUMENT
-#if defined(DUK_OPT_NO_NONSTD_ACCESSOR_KEY_ARGUMENT)
-#undef DUK_USE_NONSTD_GETTER_KEY_ARGUMENT
-#undef DUK_USE_NONSTD_SETTER_KEY_ARGUMENT
-#endif
-
-/*
- *  Tailcalls
- */
-
-/* Tailcalls are enabled by default.  The non-standard function 'caller'
- * property feature conflicts with tailcalls quite severely so tailcalls
- * are disabled if the 'caller' property is enabled.
- */
-#define DUK_USE_TAILCALL
-#if defined(DUK_USE_NONSTD_FUNC_CALLER_PROPERTY)
-#undef DUK_USE_TAILCALL
-#endif
-
-/*
- *  Deep vs. shallow stack.
- *
- *  Some embedded platforms have very shallow stack (e.g. 64kB); default to
- *  a shallow stack on unknown platforms or known embedded platforms.
- */
-
-#if defined(DUK_F_LINUX) || defined(DUK_F_BSD) || defined(DUK_F_WINDOWS) || \
-    defined(DUK_OPT_DEEP_C_STACK)
-#define DUK_USE_DEEP_C_STACK
-#else
-#undef DUK_USE_DEEP_C_STACK
-#endif
-
-/*
- *  Ecmascript compiler
- */
-
-/* Ensure final bytecode never exceeds a certain byte size and never uses
- * line numbers above a certain limit.  This ensures that there is no need
- * to deal with unbounded ranges in e.g. pc2line data structures.  For now,
- * limits are set so that signed 32-bit values can represent line number
- * and byte offset with room to spare.
- */
-#define DUK_USE_ESBC_LIMITS
-#define DUK_USE_ESBC_MAX_LINENUMBER  0x7fff0000L
-#define DUK_USE_ESBC_MAX_BYTES       0x7fff0000L
-
-/*
- *  User panic handler, panic exit behavior for default panic handler
- */
-
-#undef DUK_USE_PANIC_HANDLER
-#if defined(DUK_OPT_PANIC_HANDLER)
-#define DUK_USE_PANIC_HANDLER(code,msg) DUK_OPT_PANIC_HANDLER((code),(msg))
-#endif
-
-#undef DUK_USE_PANIC_ABORT
-#undef DUK_USE_PANIC_EXIT
-#undef DUK_USE_PANIC_SEGFAULT
-
-#if defined(DUK_OPT_SEGFAULT_ON_PANIC)
-#define DUK_USE_PANIC_SEGFAULT
-#else
-#define DUK_USE_PANIC_ABORT
-#endif
-
-/*
- *  File I/O support.  This is now used in a few API calls to e.g. push
- *  a string from file contents or eval a file.  For portability it must
- *  be possible to disable I/O altogether.
- */
-
-#undef DUK_USE_FILE_IO
-#if !defined(DUK_OPT_NO_FILE_IO)
-#define DUK_USE_FILE_IO
-#endif
-
-/*
- *  Optional run-time self tests executed when a heap is created.  Some
- *  platform/compiler issues cannot be determined at compile time.  One
- *  particular example is the bug described in misc/clang_aliasing.c.
- */
-
-#undef DUK_USE_SELF_TESTS
-#if defined(DUK_OPT_SELF_TESTS)
-#define DUK_USE_SELF_TESTS
-#endif
-
-/* Double aliasing testcase fails when Emscripten-generated code is run
- * on Firefox.  This is not fatal because it only affects packed duk_tval
- * which we avoid with Emscripten.
- */
-#undef DUK_USE_NO_DOUBLE_ALIASING_SELFTEST
-#if defined(DUK_F_EMSCRIPTEN)
-#define DUK_USE_NO_DOUBLE_ALIASING_SELFTEST
-#endif
-
-/*
- *  Codecs
  */
 
-#define DUK_USE_JX
-#if defined(DUK_OPT_NO_JX)
-#undef DUK_USE_JX
-#endif
-
-#define DUK_USE_JC
-#if defined(DUK_OPT_NO_JC)
-#undef DUK_USE_JC
-#endif
-
-/*
- *  InitJS code
- */
-
-/* Always use the built-in InitJS code for now. */
-#define DUK_USE_BUILTIN_INITJS
-
-/* User provided InitJS. */
-#undef DUK_USE_USER_INITJS
-#if defined(DUK_OPT_USER_INITJS)
-#define DUK_USE_USER_INITJS (DUK_OPT_USER_INITJS)
-#endif
-
-/*
- *  Miscellaneous
- */
-
-#define DUK_USE_PROVIDE_DEFAULT_ALLOC_FUNCTIONS
-#undef DUK_USE_EXPLICIT_NULL_INIT
-
-#if !defined(DUK_USE_PACKED_TVAL)
-#define DUK_USE_EXPLICIT_NULL_INIT
-#endif
-
-#define DUK_USE_ZERO_BUFFER_DATA
-#if defined(DUK_OPT_NO_ZERO_BUFFER_DATA)
-#undef DUK_USE_ZERO_BUFFER_DATA
-#endif
-
-#if defined(DUK_F_C99) || (defined(DUK_F_CPP11) && defined(__GNUC__))
-#define DUK_USE_VARIADIC_MACROS
-#else
-#undef DUK_USE_VARIADIC_MACROS
-#endif
-
-/*
- *  Variable size array initialization.
- *
- *  Variable size array at the end of a structure is nonportable. 
- *  There are three alternatives:
- *
- *    1) C99 (flexible array member): char buf[]
- *    2) Compiler specific (e.g. GCC): char buf[0]
- *    3) Portable but wastes memory / complicates allocation: char buf[1]
- */
-
-/* XXX: Currently unused, only hbuffer.h needed this at some point. */
-#undef DUK_USE_FLEX_C99
-#undef DUK_USE_FLEX_ZEROSIZE
-#undef DUK_USE_FLEX_ONESIZE
-#if defined(DUK_F_C99)
-#define DUK_USE_FLEX_C99
-#elif defined(__GNUC__)
-#define DUK_USE_FLEX_ZEROSIZE
-#else
-#define DUK_USE_FLEX_ONESIZE
-#endif
-
+/* AUTHORS.rst */
 /*
- *  GCC pragmas
- */
-
-/* XXX: GCC pragma inside a function fails in some earlier GCC versions (e.g. gcc 4.5).
- * This is very approximate but allows clean builds for development right now.
+ *  ===============
+ *  Duktape authors
+ *  ===============
+ *  
+ *  Copyright
+ *  =========
+ *  
+ *  Duktape copyrights are held by its authors.  Each author has a copyright
+ *  to their contribution, and agrees to irrevocably license the contribution
+ *  under the Duktape ``LICENSE.txt``.
+ *  
+ *  Authors
+ *  =======
+ *  
+ *  Please include an e-mail address, a link to your GitHub profile, or something
+ *  similar to allow your contribution to be identified accurately.
+ *  
+ *  The following people have contributed code, website contents, or Wiki contents,
+ *  and agreed to irrevocably license their contributions under the Duktape
+ *  ``LICENSE.txt`` (in order of appearance):
+ *  
+ *  * Sami Vaarala <sami.vaarala at iki.fi>
+ *  * Niki Dobrev
+ *  * Andreas \u00d6man <andreas at lonelycoder.com>
+ *  * L\u00e1szl\u00f3 Lang\u00f3 <llango.u-szeged at partner.samsung.com>
+ *  * Legimet <legimet.calc at gmail.com>
+ *  * Karl Skomski <karl at skomski.com>
+ *  * Bruce Pascoe <fatcerberus1 at gmail.com>
+ *  * Ren\u00e9 Hollander <rene at rene8888.at>
+ *  
+ *  Other contributions
+ *  ===================
+ *  
+ *  The following people have contributed something other than code (e.g. reported
+ *  bugs, provided ideas, etc; roughly in order of appearance):
+ *  
+ *  * Greg Burns
+ *  * Anthony Rabine
+ *  * Carlos Costa
+ *  * Aur\u00e9lien Bouilland
+ *  * Preet Desai (Pris Matic)
+ *  * judofyr (http://www.reddit.com/user/judofyr)
+ *  * Jason Woofenden
+ *  * Micha\u0142 Przyby\u015b
+ *  * Anthony Howe
+ *  * Conrad Pankoff
+ *  * Jim Schimpf
+ *  * Rajaran Gaunker (https://github.com/zimbabao)
+ *  * Andreas \u00d6man
+ *  * Doug Sanden
+ *  * Josh Engebretson (https://github.com/JoshEngebretson)
+ *  * Remo Eichenberger (https://github.com/remoe)
+ *  * Mamod Mehyar (https://github.com/mamod)
+ *  * David Demelier (https://github.com/markand)
+ *  * Tim Caswell (https://github.com/creationix)
+ *  * Mitchell Blank Jr (https://github.com/mitchblank)
+ *  * https://github.com/yushli
+ *  * Seo Sanghyeon (https://github.com/sanxiyn)
+ *  * Han ChoongWoo (https://github.com/tunz)
+ *  * Joshua Peek (https://github.com/josh)
+ *  * Bruce E. Pascoe (https://github.com/fatcerberus)
+ *  * https://github.com/Kelledin
+ *  * https://github.com/sstruchtrup
+ *  * Michael Drake (https://github.com/tlsa)
+ *  * https://github.com/chris-y
+ *  * Laurent Zubiaur (https://github.com/lzubiaur)
+ *  
+ *  If you are accidentally missing from this list, send me an e-mail
+ *  (``sami.vaarala at iki.fi``) and I'll fix the omission.
  */
-/* http://gcc.gnu.org/onlinedocs/cpp/Common-Predefined-Macros.html */
-#if defined(__GNUC__) && defined(__GNUC_MINOR__) && (__GNUC__ == 4) && (__GNUC_MINOR__ >= 6)
-#define DUK_USE_GCC_PRAGMAS
-#else
-#undef DUK_USE_GCC_PRAGMAS
-#endif
 
-/*
- *  User declarations
- */
+#ifndef DUKTAPE_H_INCLUDED
+#define DUKTAPE_H_INCLUDED
 
-#if defined(DUK_OPT_DECLARE)
-#define DUK_USE_USER_DECLARE() DUK_OPT_DECLARE
-#else
-#define DUK_USE_USER_DECLARE() /* no user declarations */
-#endif
+#define DUK_SINGLE_FILE
 
-/*
- *  Alternative customization header
- *
- *  If you want to modify the final DUK_USE_xxx flags directly (without
- *  using the available DUK_OPT_Xxx flags), define DUK_OPT_HAVE_CUSTOM_H
- *  and tweak the final flags there.
+/* External duk_config.h provides platform/compiler/OS dependent
+ * typedefs and macros, and DUK_USE_xxx config options so that
+ * the rest of Duktape doesn't need to do any feature detection.
  */
-
-#if defined(DUK_OPT_HAVE_CUSTOM_H)
-#include "duk_custom.h"
-#endif
-
-#endif  /* DUK_FEATURES_H_INCLUDED */
+#include "duk_config.h"
 
 /*
  *  BEGIN PUBLIC API
@@ -2532,9 +154,6 @@ extern "C" {
 /*
  *  Public API specific typedefs
  *
- *  (duk_context *) maps directly to internal type (duk_hthread *).
- *  Currently only primitive typedefs have a '_t' suffix.
- *
  *  Many types are wrapped by Duktape for portability to rare platforms
  *  where e.g. 'int' is a 16-bit type.  See practical typing discussion
  *  in Duktape web documentation.
@@ -2544,7 +163,9 @@ struct duk_memory_functions;
 struct duk_function_list_entry;
 struct duk_number_list_entry;
 
-typedef void duk_context;
+/* duk_context is now defined in duk_config.h because it may also be
+ * referenced there by prototypes.
+ */
 typedef struct duk_memory_functions duk_memory_functions;
 typedef struct duk_function_list_entry duk_function_list_entry;
 typedef struct duk_number_list_entry duk_number_list_entry;
@@ -2557,18 +178,24 @@ typedef void (*duk_fatal_function) (duk_context *ctx, duk_errcode_t code, const
 typedef void (*duk_decode_char_function) (void *udata, duk_codepoint_t codepoint);
 typedef duk_codepoint_t (*duk_map_char_function) (void *udata, duk_codepoint_t codepoint);
 typedef duk_ret_t (*duk_safe_call_function) (duk_context *ctx);
+typedef duk_size_t (*duk_debug_read_function) (void *udata, char *buffer, duk_size_t length);
+typedef duk_size_t (*duk_debug_write_function) (void *udata, const char *buffer, duk_size_t length);
+typedef duk_size_t (*duk_debug_peek_function) (void *udata);
+typedef void (*duk_debug_read_flush_function) (void *udata);
+typedef void (*duk_debug_write_flush_function) (void *udata);
+typedef void (*duk_debug_detached_function) (void *udata);
 
 struct duk_memory_functions {
-	duk_alloc_function alloc;
-	duk_realloc_function realloc;
-	duk_free_function free;
+	duk_alloc_function alloc_func;
+	duk_realloc_function realloc_func;
+	duk_free_function free_func;
 	void *udata;
 };
 
 struct duk_function_list_entry {
 	const char *key;
 	duk_c_function value;
-	duk_int_t nargs;
+	duk_idx_t nargs;
 };
 
 struct duk_number_list_entry {
@@ -2586,13 +213,25 @@ struct duk_number_list_entry {
  * have 99 for patch level (e.g. 0.10.99 would be a development version
  * after 0.10.0 but before the next official release).
  */
-#define DUK_VERSION                       1100L
+#define DUK_VERSION                       10400L
+
+/* Git commit, describe, and branch for Duktape build.  Useful for
+ * non-official snapshot builds so that application code can easily log
+ * which Duktape snapshot was used.  Not available in the Ecmascript
+ * environment.
+ */
+#define DUK_GIT_COMMIT                    "cad6f595382a0cc1a7e4207794ade5be11b3e397"
+#define DUK_GIT_DESCRIBE                  "v1.4.0"
+#define DUK_GIT_BRANCH                    "master"
+
+/* Duktape debug protocol version used by this build. */
+#define DUK_DEBUG_PROTOCOL_VERSION        1
 
 /* Used to represent invalid index; if caller uses this without checking,
  * this index will map to a non-existent stack entry.  Also used in some
  * API calls as a marker to denote "no value".
  */
-#define DUK_INVALID_INDEX                 INT_MIN 
+#define DUK_INVALID_INDEX                 DUK_IDX_MIN
 
 /* Indicates that a native function does not have a fixed number of args,
  * and the argument stack should not be capped/extended at all.
@@ -2605,6 +244,7 @@ struct duk_number_list_entry {
 #define DUK_API_ENTRY_STACK               64
 
 /* Value types, used by e.g. duk_get_type() */
+#define DUK_TYPE_MIN                      0
 #define DUK_TYPE_NONE                     0    /* no value, e.g. invalid index */
 #define DUK_TYPE_UNDEFINED                1    /* Ecmascript undefined */
 #define DUK_TYPE_NULL                     2    /* Ecmascript null */
@@ -2614,6 +254,8 @@ struct duk_number_list_entry {
 #define DUK_TYPE_OBJECT                   6    /* Ecmascript object: includes objects, arrays, functions, threads */
 #define DUK_TYPE_BUFFER                   7    /* fixed or dynamic, garbage collected byte buffer */
 #define DUK_TYPE_POINTER                  8    /* raw void pointer */
+#define DUK_TYPE_LIGHTFUNC                9    /* lightweight function pointer */
+#define DUK_TYPE_MAX                      9
 
 /* Value mask types, used by e.g. duk_get_type_mask() */
 #define DUK_TYPE_MASK_NONE                (1 << DUK_TYPE_NONE)
@@ -2625,6 +267,7 @@ struct duk_number_list_entry {
 #define DUK_TYPE_MASK_OBJECT              (1 << DUK_TYPE_OBJECT)
 #define DUK_TYPE_MASK_BUFFER              (1 << DUK_TYPE_BUFFER)
 #define DUK_TYPE_MASK_POINTER             (1 << DUK_TYPE_POINTER)
+#define DUK_TYPE_MASK_LIGHTFUNC           (1 << DUK_TYPE_LIGHTFUNC)
 #define DUK_TYPE_MASK_THROW               (1 << 10)  /* internal flag value: throw if mask doesn't match */
 
 /* Coercion hints */
@@ -2643,18 +286,40 @@ struct duk_number_list_entry {
 #define DUK_ENUM_NO_PROXY_BEHAVIOR        (1 << 5)    /* enumerate a proxy object itself without invoking proxy behavior */
 
 /* Compilation flags for duk_compile() and duk_eval() */
-#define DUK_COMPILE_EVAL                  (1 << 0)    /* compile eval code (instead of program) */
-#define DUK_COMPILE_FUNCTION              (1 << 1)    /* compile function code (instead of program) */
-#define DUK_COMPILE_STRICT                (1 << 2)    /* use strict (outer) context for program, eval, or function */
+#define DUK_COMPILE_EVAL                  (1 << 0)    /* compile eval code (instead of global code) */
+#define DUK_COMPILE_FUNCTION              (1 << 1)    /* compile function code (instead of global code) */
+#define DUK_COMPILE_STRICT                (1 << 2)    /* use strict (outer) context for global, eval, or function code */
 #define DUK_COMPILE_SAFE                  (1 << 3)    /* (internal) catch compilation errors */
 #define DUK_COMPILE_NORESULT              (1 << 4)    /* (internal) omit eval result */
 #define DUK_COMPILE_NOSOURCE              (1 << 5)    /* (internal) no source string on stack */
 #define DUK_COMPILE_STRLEN                (1 << 6)    /* (internal) take strlen() of src_buffer (avoids double evaluation in macro) */
 
+/* Flags for duk_def_prop() and its variants */
+#define DUK_DEFPROP_WRITABLE              (1 << 0)    /* set writable (effective if DUK_DEFPROP_HAVE_WRITABLE set) */
+#define DUK_DEFPROP_ENUMERABLE            (1 << 1)    /* set enumerable (effective if DUK_DEFPROP_HAVE_ENUMERABLE set) */
+#define DUK_DEFPROP_CONFIGURABLE          (1 << 2)    /* set configurable (effective if DUK_DEFPROP_HAVE_CONFIGURABLE set) */
+#define DUK_DEFPROP_HAVE_WRITABLE         (1 << 3)    /* set/clear writable */
+#define DUK_DEFPROP_HAVE_ENUMERABLE       (1 << 4)    /* set/clear enumerable */
+#define DUK_DEFPROP_HAVE_CONFIGURABLE     (1 << 5)    /* set/clear configurable */
+#define DUK_DEFPROP_HAVE_VALUE            (1 << 6)    /* set value (given on value stack) */
+#define DUK_DEFPROP_HAVE_GETTER           (1 << 7)    /* set getter (given on value stack) */
+#define DUK_DEFPROP_HAVE_SETTER           (1 << 8)    /* set setter (given on value stack) */
+#define DUK_DEFPROP_FORCE                 (1 << 9)    /* force change if possible, may still fail for e.g. virtual properties */
+#define DUK_DEFPROP_SET_WRITABLE          (DUK_DEFPROP_HAVE_WRITABLE | DUK_DEFPROP_WRITABLE)
+#define DUK_DEFPROP_CLEAR_WRITABLE        DUK_DEFPROP_HAVE_WRITABLE
+#define DUK_DEFPROP_SET_ENUMERABLE        (DUK_DEFPROP_HAVE_ENUMERABLE | DUK_DEFPROP_ENUMERABLE)
+#define DUK_DEFPROP_CLEAR_ENUMERABLE      DUK_DEFPROP_HAVE_ENUMERABLE
+#define DUK_DEFPROP_SET_CONFIGURABLE      (DUK_DEFPROP_HAVE_CONFIGURABLE | DUK_DEFPROP_CONFIGURABLE)
+#define DUK_DEFPROP_CLEAR_CONFIGURABLE    DUK_DEFPROP_HAVE_CONFIGURABLE
+
 /* Flags for duk_push_thread_raw() */
 #define DUK_THREAD_NEW_GLOBAL_ENV         (1 << 0)    /* create a new global environment */
 
+/* Flags for duk_push_string_file_raw() */
+#define DUK_STRING_PUSH_SAFE              (1 << 0)    /* no error if file does not exist */
+
 /* Duktape specific error codes */
+#define DUK_ERR_NONE                      0    /* no error (e.g. from duk_get_error_code()) */
 #define DUK_ERR_UNIMPLEMENTED_ERROR       50   /* UnimplementedError */
 #define DUK_ERR_UNSUPPORTED_ERROR         51   /* UnsupportedError */
 #define DUK_ERR_INTERNAL_ERROR            52   /* InternalError */
@@ -2693,12 +358,12 @@ struct duk_number_list_entry {
 #define DUK_EXEC_ERROR                    1
 
 /* Log levels */
-#define  DUK_LOG_TRACE                    0
-#define  DUK_LOG_DEBUG                    1
-#define  DUK_LOG_INFO                     2
-#define  DUK_LOG_WARN                     3
-#define  DUK_LOG_ERROR                    4
-#define  DUK_LOG_FATAL                    5
+#define DUK_LOG_TRACE                     0
+#define DUK_LOG_DEBUG                     1
+#define DUK_LOG_INFO                      2
+#define DUK_LOG_WARN                      3
+#define DUK_LOG_ERROR                     4
+#define DUK_LOG_FATAL                     5
 
 /*
  *  If no variadic macros, __FILE__ and __LINE__ are passed through globals
@@ -2706,20 +371,21 @@ struct duk_number_list_entry {
  */
 
 #ifndef DUK_API_VARIADIC_MACROS
-extern const char *duk_api_global_filename;
-extern duk_int_t duk_api_global_line;
+DUK_EXTERNAL_DECL const char *duk_api_global_filename;
+DUK_EXTERNAL_DECL duk_int_t duk_api_global_line;
 #endif
 
 /*
  *  Context management
  */
 
+DUK_EXTERNAL_DECL
 duk_context *duk_create_heap(duk_alloc_function alloc_func,
                              duk_realloc_function realloc_func,
                              duk_free_function free_func,
-                             void *alloc_udata,
+                             void *heap_udata,
                              duk_fatal_function fatal_handler);
-void duk_destroy_heap(duk_context *ctx);
+DUK_EXTERNAL_DECL void duk_destroy_heap(duk_context *ctx);
 
 #define duk_create_heap_default() \
 	duk_create_heap(NULL, NULL, NULL, NULL, NULL)
@@ -2730,56 +396,63 @@ void duk_destroy_heap(duk_context *ctx);
  *  Raw functions have no side effects (cannot trigger GC).
  */
 
-void *duk_alloc_raw(duk_context *ctx, duk_size_t size);
-void duk_free_raw(duk_context *ctx, void *ptr);
-void *duk_realloc_raw(duk_context *ctx, void *ptr, duk_size_t size);
-void *duk_alloc(duk_context *ctx, duk_size_t size);
-void duk_free(duk_context *ctx, void *ptr);
-void *duk_realloc(duk_context *ctx, void *ptr, duk_size_t size);
-void duk_get_memory_functions(duk_context *ctx, duk_memory_functions *out_funcs);
-void duk_gc(duk_context *ctx, duk_uint_t flags);
+DUK_EXTERNAL_DECL void *duk_alloc_raw(duk_context *ctx, duk_size_t size);
+DUK_EXTERNAL_DECL void duk_free_raw(duk_context *ctx, void *ptr);
+DUK_EXTERNAL_DECL void *duk_realloc_raw(duk_context *ctx, void *ptr, duk_size_t size);
+DUK_EXTERNAL_DECL void *duk_alloc(duk_context *ctx, duk_size_t size);
+DUK_EXTERNAL_DECL void duk_free(duk_context *ctx, void *ptr);
+DUK_EXTERNAL_DECL void *duk_realloc(duk_context *ctx, void *ptr, duk_size_t size);
+DUK_EXTERNAL_DECL void duk_get_memory_functions(duk_context *ctx, duk_memory_functions *out_funcs);
+DUK_EXTERNAL_DECL void duk_gc(duk_context *ctx, duk_uint_t flags);
 
 /*
  *  Error handling
  */
 
-DUK_API_NORETURN(void duk_throw(duk_context *ctx));
+DUK_API_NORETURN(DUK_EXTERNAL_DECL void duk_throw(duk_context *ctx));
+DUK_API_NORETURN(DUK_EXTERNAL_DECL void duk_fatal(duk_context *ctx, duk_errcode_t err_code, const char *err_msg));
+
+DUK_API_NORETURN(DUK_EXTERNAL_DECL void duk_error_raw(duk_context *ctx, duk_errcode_t err_code, const char *filename, duk_int_t line, const char *fmt, ...));
 
-DUK_API_NORETURN(void duk_error_raw(duk_context *ctx, duk_errcode_t err_code, const char *filename, duk_int_t line, const char *fmt, ...));
 #ifdef DUK_API_VARIADIC_MACROS
 #define duk_error(ctx,err_code,...)  \
-	duk_error_raw((ctx), (duk_errcode_t) (err_code), __FILE__, (duk_int_t) __LINE__, __VA_ARGS__)
+	duk_error_raw((ctx), (duk_errcode_t) (err_code), (const char *) (__FILE__), (duk_int_t) (__LINE__), __VA_ARGS__)
 #else
-DUK_API_NORETURN(void duk_error_stash(duk_context *ctx, duk_errcode_t err_code, const char *fmt, ...));
+DUK_API_NORETURN(DUK_EXTERNAL_DECL void duk_error_stash(duk_context *ctx, duk_errcode_t err_code, const char *fmt, ...));
+/* One problem with this macro is that expressions like the following fail
+ * to compile: "(void) duk_error(...)".  But because duk_error() is noreturn,
+ * they make little sense anyway.
+ */
 #define duk_error  \
-	duk_api_global_filename = __FILE__, \
-	duk_api_global_line = (duk_int_t) __LINE__, \
-	duk_error_stash  /* arguments follow */
+	(duk_api_global_filename = (const char *) (__FILE__), \
+	 duk_api_global_line = (duk_int_t) (__LINE__), \
+	 duk_error_stash)  /* last value is func pointer, arguments follow in parens */
 #endif
 
-DUK_API_NORETURN(void duk_fatal(duk_context *ctx, duk_errcode_t err_code, const char *err_msg));
+DUK_API_NORETURN(DUK_EXTERNAL_DECL void duk_error_va_raw(duk_context *ctx, duk_errcode_t err_code, const char *filename, duk_int_t line, const char *fmt, va_list ap));
+#define duk_error_va(ctx,err_code,fmt,ap)  \
+	duk_error_va_raw((ctx), (duk_errcode_t) (err_code), (const char *) (__FILE__), (duk_int_t) (__LINE__), (fmt), (ap))
 
 /*
  *  Other state related functions
  */
 
-duk_bool_t duk_is_strict_call(duk_context *ctx);
-duk_bool_t duk_is_constructor_call(duk_context *ctx);
-duk_int_t duk_get_magic(duk_context *ctx);
+DUK_EXTERNAL_DECL duk_bool_t duk_is_strict_call(duk_context *ctx);
+DUK_EXTERNAL_DECL duk_bool_t duk_is_constructor_call(duk_context *ctx);
 
 /*
  *  Stack management
  */
 
-duk_idx_t duk_normalize_index(duk_context *ctx, duk_idx_t index);
-duk_idx_t duk_require_normalize_index(duk_context *ctx, duk_idx_t index);
-duk_bool_t duk_is_valid_index(duk_context *ctx, duk_idx_t index);
-void duk_require_valid_index(duk_context *ctx, duk_idx_t index);
+DUK_EXTERNAL_DECL duk_idx_t duk_normalize_index(duk_context *ctx, duk_idx_t index);
+DUK_EXTERNAL_DECL duk_idx_t duk_require_normalize_index(duk_context *ctx, duk_idx_t index);
+DUK_EXTERNAL_DECL duk_bool_t duk_is_valid_index(duk_context *ctx, duk_idx_t index);
+DUK_EXTERNAL_DECL void duk_require_valid_index(duk_context *ctx, duk_idx_t index);
 
-duk_idx_t duk_get_top(duk_context *ctx);
-void duk_set_top(duk_context *ctx, duk_idx_t index);
-duk_idx_t duk_get_top_index(duk_context *ctx);
-duk_idx_t duk_require_top_index(duk_context *ctx);
+DUK_EXTERNAL_DECL duk_idx_t duk_get_top(duk_context *ctx);
+DUK_EXTERNAL_DECL void duk_set_top(duk_context *ctx, duk_idx_t index);
+DUK_EXTERNAL_DECL duk_idx_t duk_get_top_index(duk_context *ctx);
+DUK_EXTERNAL_DECL duk_idx_t duk_require_top_index(duk_context *ctx);
 
 /* Although extra/top could be an unsigned type here, using a signed type
  * makes the API more robust to calling code calculation errors or corner
@@ -2788,25 +461,29 @@ duk_idx_t duk_require_top_index(duk_context *ctx);
  * to a large unsigned number.  (This principle is used elsewhere in the
  * API too.)
  */
-duk_bool_t duk_check_stack(duk_context *ctx, duk_idx_t extra);
-void duk_require_stack(duk_context *ctx, duk_idx_t extra);
-duk_bool_t duk_check_stack_top(duk_context *ctx, duk_idx_t top);
-void duk_require_stack_top(duk_context *ctx, duk_idx_t top);
+DUK_EXTERNAL_DECL duk_bool_t duk_check_stack(duk_context *ctx, duk_idx_t extra);
+DUK_EXTERNAL_DECL void duk_require_stack(duk_context *ctx, duk_idx_t extra);
+DUK_EXTERNAL_DECL duk_bool_t duk_check_stack_top(duk_context *ctx, duk_idx_t top);
+DUK_EXTERNAL_DECL void duk_require_stack_top(duk_context *ctx, duk_idx_t top);
 
 /*
  *  Stack manipulation (other than push/pop)
  */
 
-void duk_swap(duk_context *ctx, duk_idx_t index1, duk_idx_t index2);
-void duk_swap_top(duk_context *ctx, duk_idx_t index);
-void duk_dup(duk_context *ctx, duk_idx_t from_index);
-void duk_dup_top(duk_context *ctx);
-void duk_insert(duk_context *ctx, duk_idx_t to_index);
-void duk_replace(duk_context *ctx, duk_idx_t to_index);
-void duk_copy(duk_context *ctx, duk_idx_t from_index, duk_idx_t to_index);
-void duk_remove(duk_context *ctx, duk_idx_t index);
-/* FIXME: undocumented */
-void duk_xmove(duk_context *from_ctx, duk_context *to_ctx, duk_idx_t count);
+DUK_EXTERNAL_DECL void duk_swap(duk_context *ctx, duk_idx_t index1, duk_idx_t index2);
+DUK_EXTERNAL_DECL void duk_swap_top(duk_context *ctx, duk_idx_t index);
+DUK_EXTERNAL_DECL void duk_dup(duk_context *ctx, duk_idx_t from_index);
+DUK_EXTERNAL_DECL void duk_dup_top(duk_context *ctx);
+DUK_EXTERNAL_DECL void duk_insert(duk_context *ctx, duk_idx_t to_index);
+DUK_EXTERNAL_DECL void duk_replace(duk_context *ctx, duk_idx_t to_index);
+DUK_EXTERNAL_DECL void duk_copy(duk_context *ctx, duk_idx_t from_index, duk_idx_t to_index);
+DUK_EXTERNAL_DECL void duk_remove(duk_context *ctx, duk_idx_t index);
+DUK_EXTERNAL_DECL void duk_xcopymove_raw(duk_context *to_ctx, duk_context *from_ctx, duk_idx_t count, duk_bool_t is_copy);
+
+#define duk_xmove_top(to_ctx,from_ctx,count) \
+	duk_xcopymove_raw((to_ctx), (from_ctx), (count), 0 /*is_copy*/)
+#define duk_xcopy_top(to_ctx,from_ctx,count) \
+	duk_xcopymove_raw((to_ctx), (from_ctx), (count), 1 /*is_copy*/)
 
 /*
  *  Push operations
@@ -2817,34 +494,38 @@ void duk_xmove(duk_context *from_ctx, duk_context *to_ctx, duk_idx_t count);
  *  Note: duk_dup() is technically a push.
  */
 
-void duk_push_undefined(duk_context *ctx);
-void duk_push_null(duk_context *ctx);
-void duk_push_boolean(duk_context *ctx, duk_bool_t val);
-void duk_push_true(duk_context *ctx);
-void duk_push_false(duk_context *ctx);
-void duk_push_number(duk_context *ctx, duk_double_t val);
-void duk_push_nan(duk_context *ctx);
-void duk_push_int(duk_context *ctx, duk_int_t val);
-void duk_push_uint(duk_context *ctx, duk_uint_t val);
-const char *duk_push_string(duk_context *ctx, const char *str);
-const char *duk_push_string_file(duk_context *ctx, const char *path);
-const char *duk_push_lstring(duk_context *ctx, const char *str, duk_size_t len);
-void duk_push_pointer(duk_context *ctx, void *p);
-const char *duk_push_sprintf(duk_context *ctx, const char *fmt, ...);
-const char *duk_push_vsprintf(duk_context *ctx, const char *fmt, va_list ap);
-
-void duk_push_this(duk_context *ctx);
-void duk_push_current_function(duk_context *ctx);
-void duk_push_current_thread(duk_context *ctx);
-void duk_push_global_object(duk_context *ctx);
-void duk_push_heap_stash(duk_context *ctx);
-void duk_push_global_stash(duk_context *ctx);
-void duk_push_thread_stash(duk_context *ctx, duk_context *target_ctx);
-
-duk_idx_t duk_push_object(duk_context *ctx);
-duk_idx_t duk_push_array(duk_context *ctx);
-duk_idx_t duk_push_c_function(duk_context *ctx, duk_c_function func, duk_idx_t nargs);
-duk_idx_t duk_push_thread_raw(duk_context *ctx, duk_uint_t flags);
+DUK_EXTERNAL_DECL void duk_push_undefined(duk_context *ctx);
+DUK_EXTERNAL_DECL void duk_push_null(duk_context *ctx);
+DUK_EXTERNAL_DECL void duk_push_boolean(duk_context *ctx, duk_bool_t val);
+DUK_EXTERNAL_DECL void duk_push_true(duk_context *ctx);
+DUK_EXTERNAL_DECL void duk_push_false(duk_context *ctx);
+DUK_EXTERNAL_DECL void duk_push_number(duk_context *ctx, duk_double_t val);
+DUK_EXTERNAL_DECL void duk_push_nan(duk_context *ctx);
+DUK_EXTERNAL_DECL void duk_push_int(duk_context *ctx, duk_int_t val);
+DUK_EXTERNAL_DECL void duk_push_uint(duk_context *ctx, duk_uint_t val);
+DUK_EXTERNAL_DECL const char *duk_push_string(duk_context *ctx, const char *str);
+DUK_EXTERNAL_DECL const char *duk_push_lstring(duk_context *ctx, const char *str, duk_size_t len);
+DUK_EXTERNAL_DECL void duk_push_pointer(duk_context *ctx, void *p);
+DUK_EXTERNAL_DECL const char *duk_push_sprintf(duk_context *ctx, const char *fmt, ...);
+DUK_EXTERNAL_DECL const char *duk_push_vsprintf(duk_context *ctx, const char *fmt, va_list ap);
+
+DUK_EXTERNAL_DECL const char *duk_push_string_file_raw(duk_context *ctx, const char *path, duk_uint_t flags);
+#define duk_push_string_file(ctx,path) \
+	duk_push_string_file_raw((ctx), (path), 0)
+
+DUK_EXTERNAL_DECL void duk_push_this(duk_context *ctx);
+DUK_EXTERNAL_DECL void duk_push_current_function(duk_context *ctx);
+DUK_EXTERNAL_DECL void duk_push_current_thread(duk_context *ctx);
+DUK_EXTERNAL_DECL void duk_push_global_object(duk_context *ctx);
+DUK_EXTERNAL_DECL void duk_push_heap_stash(duk_context *ctx);
+DUK_EXTERNAL_DECL void duk_push_global_stash(duk_context *ctx);
+DUK_EXTERNAL_DECL void duk_push_thread_stash(duk_context *ctx, duk_context *target_ctx);
+
+DUK_EXTERNAL_DECL duk_idx_t duk_push_object(duk_context *ctx);
+DUK_EXTERNAL_DECL duk_idx_t duk_push_array(duk_context *ctx);
+DUK_EXTERNAL_DECL duk_idx_t duk_push_c_function(duk_context *ctx, duk_c_function func, duk_idx_t nargs);
+DUK_EXTERNAL_DECL duk_idx_t duk_push_c_lightfunc(duk_context *ctx, duk_c_function func, duk_idx_t nargs, duk_idx_t length, duk_int_t magic);
+DUK_EXTERNAL_DECL duk_idx_t duk_push_thread_raw(duk_context *ctx, duk_uint_t flags);
 
 #define duk_push_thread(ctx) \
 	duk_push_thread_raw((ctx), 0 /*flags*/)
@@ -2852,30 +533,66 @@ duk_idx_t duk_push_thread_raw(duk_context *ctx, duk_uint_t flags);
 #define duk_push_thread_new_globalenv(ctx) \
 	duk_push_thread_raw((ctx), DUK_THREAD_NEW_GLOBAL_ENV /*flags*/)
 
-duk_idx_t duk_push_error_object_raw(duk_context *ctx, duk_errcode_t err_code, const char *filename, duk_int_t line, const char *fmt, ...);
+DUK_EXTERNAL_DECL duk_idx_t duk_push_error_object_raw(duk_context *ctx, duk_errcode_t err_code, const char *filename, duk_int_t line, const char *fmt, ...);
+
 #ifdef DUK_API_VARIADIC_MACROS
 #define duk_push_error_object(ctx,err_code,...)  \
-	duk_push_error_object_raw((ctx),(err_code),__FILE__,__LINE__,__VA_ARGS__)
+	duk_push_error_object_raw((ctx), (err_code), (const char *) (__FILE__), (duk_int_t) (__LINE__), __VA_ARGS__)
 #else
-duk_idx_t duk_push_error_object_stash(duk_context *ctx, duk_errcode_t err_code, const char *fmt, ...);
+DUK_EXTERNAL_DECL duk_idx_t duk_push_error_object_stash(duk_context *ctx, duk_errcode_t err_code, const char *fmt, ...);
+/* Note: parentheses are required so that the comma expression works in assignments. */
 #define duk_push_error_object  \
-	duk_api_global_filename = __FILE__, \
-	duk_api_global_line = __LINE__, \
-	duk_push_error_object_stash  /* arguments follow */
-#endif
-
-void *duk_push_buffer(duk_context *ctx, duk_size_t size, duk_bool_t dynamic);
-void *duk_push_fixed_buffer(duk_context *ctx, duk_size_t size);
-void *duk_push_dynamic_buffer(duk_context *ctx, duk_size_t size);
+	(duk_api_global_filename = (const char *) (__FILE__), \
+	 duk_api_global_line = (duk_int_t) (__LINE__), \
+	 duk_push_error_object_stash)  /* last value is func pointer, arguments follow in parens */
+#endif
+
+DUK_EXTERNAL_DECL duk_idx_t duk_push_error_object_va_raw(duk_context *ctx, duk_errcode_t err_code, const char *filename, duk_int_t line, const char *fmt, va_list ap);
+#define duk_push_error_object_va(ctx,err_code,fmt,ap)  \
+	duk_push_error_object_va_raw((ctx), (err_code), (const char *) (__FILE__), (duk_int_t) (__LINE__), (fmt), (ap))
+
+#define DUK_BUF_FLAG_DYNAMIC   (1 << 0)    /* internal flag: dynamic buffer */
+#define DUK_BUF_FLAG_EXTERNAL  (1 << 1)    /* internal flag: external buffer */
+#define DUK_BUF_FLAG_NOZERO    (1 << 2)    /* internal flag: don't zero allocated buffer */
+
+DUK_EXTERNAL_DECL void *duk_push_buffer_raw(duk_context *ctx, duk_size_t size, duk_small_uint_t flags);
+
+#define duk_push_buffer(ctx,size,dynamic) \
+	duk_push_buffer_raw((ctx), (size), (dynamic) ? DUK_BUF_FLAG_DYNAMIC : 0)
+#define duk_push_fixed_buffer(ctx,size) \
+	duk_push_buffer_raw((ctx), (size), 0 /*flags*/)
+#define duk_push_dynamic_buffer(ctx,size) \
+	duk_push_buffer_raw((ctx), (size), DUK_BUF_FLAG_DYNAMIC /*flags*/)
+#define duk_push_external_buffer(ctx) \
+	((void) duk_push_buffer_raw((ctx), 0, DUK_BUF_FLAG_DYNAMIC | DUK_BUF_FLAG_EXTERNAL))
+
+#define DUK_BUFOBJ_CREATE_ARRBUF       (1 << 4)  /* internal flag: create backing ArrayBuffer; keep in one byte */
+#define DUK_BUFOBJ_DUKTAPE_BUFFER      0
+#define DUK_BUFOBJ_NODEJS_BUFFER       1
+#define DUK_BUFOBJ_ARRAYBUFFER         2
+#define DUK_BUFOBJ_DATAVIEW            (3 | DUK_BUFOBJ_CREATE_ARRBUF)
+#define DUK_BUFOBJ_INT8ARRAY           (4 | DUK_BUFOBJ_CREATE_ARRBUF)
+#define DUK_BUFOBJ_UINT8ARRAY          (5 | DUK_BUFOBJ_CREATE_ARRBUF)
+#define DUK_BUFOBJ_UINT8CLAMPEDARRAY   (6 | DUK_BUFOBJ_CREATE_ARRBUF)
+#define DUK_BUFOBJ_INT16ARRAY          (7 | DUK_BUFOBJ_CREATE_ARRBUF)
+#define DUK_BUFOBJ_UINT16ARRAY         (8 | DUK_BUFOBJ_CREATE_ARRBUF)
+#define DUK_BUFOBJ_INT32ARRAY          (9 | DUK_BUFOBJ_CREATE_ARRBUF)
+#define DUK_BUFOBJ_UINT32ARRAY         (10 | DUK_BUFOBJ_CREATE_ARRBUF)
+#define DUK_BUFOBJ_FLOAT32ARRAY        (11 | DUK_BUFOBJ_CREATE_ARRBUF)
+#define DUK_BUFOBJ_FLOAT64ARRAY        (12 | DUK_BUFOBJ_CREATE_ARRBUF)
+
+DUK_EXTERNAL_DECL void duk_push_buffer_object(duk_context *ctx, duk_idx_t idx_buffer, duk_size_t byte_offset, duk_size_t byte_length, duk_uint_t flags);
+
+DUK_EXTERNAL_DECL duk_idx_t duk_push_heapptr(duk_context *ctx, void *ptr);
 
 /*
  *  Pop operations
  */
 
-void duk_pop(duk_context *ctx);
-void duk_pop_n(duk_context *ctx, duk_idx_t count);
-void duk_pop_2(duk_context *ctx);
-void duk_pop_3(duk_context *ctx);
+DUK_EXTERNAL_DECL void duk_pop(duk_context *ctx);
+DUK_EXTERNAL_DECL void duk_pop_n(duk_context *ctx, duk_idx_t count);
+DUK_EXTERNAL_DECL void duk_pop_2(duk_context *ctx);
+DUK_EXTERNAL_DECL void duk_pop_3(duk_context *ctx);
 
 /*
  *  Type checks
@@ -2884,42 +601,70 @@ void duk_pop_3(duk_context *ctx);
  *  is not needed; duk_is_valid_index() gives the same information.
  */
 
-/* FIXME: a duk_small_int_t suffices to represent type and type mask (at least now). */
-duk_int_t duk_get_type(duk_context *ctx, duk_idx_t index);
-duk_bool_t duk_check_type(duk_context *ctx, duk_idx_t index, duk_int_t type);
-duk_uint_t duk_get_type_mask(duk_context *ctx, duk_idx_t index);
-duk_bool_t duk_check_type_mask(duk_context *ctx, duk_idx_t index, duk_uint_t mask);
-
-duk_bool_t duk_is_undefined(duk_context *ctx, duk_idx_t index);
-duk_bool_t duk_is_null(duk_context *ctx, duk_idx_t index);
-duk_bool_t duk_is_null_or_undefined(duk_context *ctx, duk_idx_t index);
-duk_bool_t duk_is_boolean(duk_context *ctx, duk_idx_t index);
-duk_bool_t duk_is_number(duk_context *ctx, duk_idx_t index);
-duk_bool_t duk_is_nan(duk_context *ctx, duk_idx_t index);
-duk_bool_t duk_is_string(duk_context *ctx, duk_idx_t index);
-duk_bool_t duk_is_object(duk_context *ctx, duk_idx_t index);
-duk_bool_t duk_is_buffer(duk_context *ctx, duk_idx_t index);
-duk_bool_t duk_is_pointer(duk_context *ctx, duk_idx_t index);
-
-duk_bool_t duk_is_array(duk_context *ctx, duk_idx_t index);
-duk_bool_t duk_is_function(duk_context *ctx, duk_idx_t index);
-duk_bool_t duk_is_c_function(duk_context *ctx, duk_idx_t index);
-duk_bool_t duk_is_ecmascript_function(duk_context *ctx, duk_idx_t index);
-duk_bool_t duk_is_bound_function(duk_context *ctx, duk_idx_t index);
-duk_bool_t duk_is_thread(duk_context *ctx, duk_idx_t index);
-
-duk_bool_t duk_is_callable(duk_context *ctx, duk_idx_t index);
-duk_bool_t duk_is_dynamic(duk_context *ctx, duk_idx_t index);
-duk_bool_t duk_is_fixed(duk_context *ctx, duk_idx_t index);
-
-duk_bool_t duk_is_primitive(duk_context *ctx, duk_idx_t index);
+DUK_EXTERNAL_DECL duk_int_t duk_get_type(duk_context *ctx, duk_idx_t index);
+DUK_EXTERNAL_DECL duk_bool_t duk_check_type(duk_context *ctx, duk_idx_t index, duk_int_t type);
+DUK_EXTERNAL_DECL duk_uint_t duk_get_type_mask(duk_context *ctx, duk_idx_t index);
+DUK_EXTERNAL_DECL duk_bool_t duk_check_type_mask(duk_context *ctx, duk_idx_t index, duk_uint_t mask);
+
+DUK_EXTERNAL_DECL duk_bool_t duk_is_undefined(duk_context *ctx, duk_idx_t index);
+DUK_EXTERNAL_DECL duk_bool_t duk_is_null(duk_context *ctx, duk_idx_t index);
+DUK_EXTERNAL_DECL duk_bool_t duk_is_null_or_undefined(duk_context *ctx, duk_idx_t index);
+DUK_EXTERNAL_DECL duk_bool_t duk_is_boolean(duk_context *ctx, duk_idx_t index);
+DUK_EXTERNAL_DECL duk_bool_t duk_is_number(duk_context *ctx, duk_idx_t index);
+DUK_EXTERNAL_DECL duk_bool_t duk_is_nan(duk_context *ctx, duk_idx_t index);
+DUK_EXTERNAL_DECL duk_bool_t duk_is_string(duk_context *ctx, duk_idx_t index);
+DUK_EXTERNAL_DECL duk_bool_t duk_is_object(duk_context *ctx, duk_idx_t index);
+DUK_EXTERNAL_DECL duk_bool_t duk_is_buffer(duk_context *ctx, duk_idx_t index);
+DUK_EXTERNAL_DECL duk_bool_t duk_is_pointer(duk_context *ctx, duk_idx_t index);
+DUK_EXTERNAL_DECL duk_bool_t duk_is_lightfunc(duk_context *ctx, duk_idx_t index);
+
+DUK_EXTERNAL_DECL duk_bool_t duk_is_array(duk_context *ctx, duk_idx_t index);
+DUK_EXTERNAL_DECL duk_bool_t duk_is_function(duk_context *ctx, duk_idx_t index);
+DUK_EXTERNAL_DECL duk_bool_t duk_is_c_function(duk_context *ctx, duk_idx_t index);
+DUK_EXTERNAL_DECL duk_bool_t duk_is_ecmascript_function(duk_context *ctx, duk_idx_t index);
+DUK_EXTERNAL_DECL duk_bool_t duk_is_bound_function(duk_context *ctx, duk_idx_t index);
+DUK_EXTERNAL_DECL duk_bool_t duk_is_thread(duk_context *ctx, duk_idx_t index);
+
+#define duk_is_callable(ctx,index) \
+	duk_is_function((ctx), (index))
+DUK_EXTERNAL_DECL duk_bool_t duk_is_dynamic_buffer(duk_context *ctx, duk_idx_t index);
+DUK_EXTERNAL_DECL duk_bool_t duk_is_fixed_buffer(duk_context *ctx, duk_idx_t index);
+DUK_EXTERNAL_DECL duk_bool_t duk_is_external_buffer(duk_context *ctx, duk_idx_t index);
+
+#define duk_is_primitive(ctx,index) \
+	duk_check_type_mask((ctx), (index), DUK_TYPE_MASK_UNDEFINED | \
+	                                    DUK_TYPE_MASK_NULL | \
+	                                    DUK_TYPE_MASK_BOOLEAN | \
+	                                    DUK_TYPE_MASK_NUMBER | \
+	                                    DUK_TYPE_MASK_STRING | \
+	                                    DUK_TYPE_MASK_BUFFER | \
+	                                    DUK_TYPE_MASK_POINTER | \
+	                                    DUK_TYPE_MASK_LIGHTFUNC)
+
 #define duk_is_object_coercible(ctx,index) \
 	duk_check_type_mask((ctx), (index), DUK_TYPE_MASK_BOOLEAN | \
 	                                    DUK_TYPE_MASK_NUMBER | \
 	                                    DUK_TYPE_MASK_STRING | \
 	                                    DUK_TYPE_MASK_OBJECT | \
 	                                    DUK_TYPE_MASK_BUFFER | \
-	                                    DUK_TYPE_MASK_POINTER)
+	                                    DUK_TYPE_MASK_POINTER | \
+	                                    DUK_TYPE_MASK_LIGHTFUNC)
+
+DUK_EXTERNAL_DECL duk_errcode_t duk_get_error_code(duk_context *ctx, duk_idx_t index);
+#define duk_is_error(ctx,index) \
+	(duk_get_error_code((ctx), (index)) != 0)
+#define duk_is_eval_error(ctx,index) \
+	(duk_get_error_code((ctx), (index)) == DUK_ERR_EVAL_ERROR)
+#define duk_is_range_error(ctx,index) \
+	(duk_get_error_code((ctx), (index)) == DUK_ERR_RANGE_ERROR)
+#define duk_is_reference_error(ctx,index) \
+	(duk_get_error_code((ctx), (index)) == DUK_ERR_REFERENCE_ERROR)
+#define duk_is_syntax_error(ctx,index) \
+	(duk_get_error_code((ctx), (index)) == DUK_ERR_SYNTAX_ERROR)
+#define duk_is_type_error(ctx,index) \
+	(duk_get_error_code((ctx), (index)) == DUK_ERR_TYPE_ERROR)
+#define duk_is_uri_error(ctx,index) \
+	(duk_get_error_code((ctx), (index)) == DUK_ERR_URI_ERROR)
 
 /*
  *  Get operations: no coercion, returns default value for invalid
@@ -2929,17 +674,19 @@ duk_bool_t duk_is_primitive(duk_context *ctx, duk_idx_t index);
  *  are not included.
  */
 
-duk_bool_t duk_get_boolean(duk_context *ctx, duk_idx_t index);
-duk_double_t duk_get_number(duk_context *ctx, duk_idx_t index);
-duk_int_t duk_get_int(duk_context *ctx, duk_idx_t index);
-duk_uint_t duk_get_uint(duk_context *ctx, duk_idx_t index);
-const char *duk_get_string(duk_context *ctx, duk_idx_t index);
-const char *duk_get_lstring(duk_context *ctx, duk_idx_t index, duk_size_t *out_len);
-void *duk_get_buffer(duk_context *ctx, duk_idx_t index, duk_size_t *out_size);
-void *duk_get_pointer(duk_context *ctx, duk_idx_t index);
-duk_c_function duk_get_c_function(duk_context *ctx, duk_idx_t index);
-duk_context *duk_get_context(duk_context *ctx, duk_idx_t index);
-duk_size_t duk_get_length(duk_context *ctx, duk_idx_t index);
+DUK_EXTERNAL_DECL duk_bool_t duk_get_boolean(duk_context *ctx, duk_idx_t index);
+DUK_EXTERNAL_DECL duk_double_t duk_get_number(duk_context *ctx, duk_idx_t index);
+DUK_EXTERNAL_DECL duk_int_t duk_get_int(duk_context *ctx, duk_idx_t index);
+DUK_EXTERNAL_DECL duk_uint_t duk_get_uint(duk_context *ctx, duk_idx_t index);
+DUK_EXTERNAL_DECL const char *duk_get_string(duk_context *ctx, duk_idx_t index);
+DUK_EXTERNAL_DECL const char *duk_get_lstring(duk_context *ctx, duk_idx_t index, duk_size_t *out_len);
+DUK_EXTERNAL_DECL void *duk_get_buffer(duk_context *ctx, duk_idx_t index, duk_size_t *out_size);
+DUK_EXTERNAL_DECL void *duk_get_buffer_data(duk_context *ctx, duk_idx_t index, duk_size_t *out_size);
+DUK_EXTERNAL_DECL void *duk_get_pointer(duk_context *ctx, duk_idx_t index);
+DUK_EXTERNAL_DECL duk_c_function duk_get_c_function(duk_context *ctx, duk_idx_t index);
+DUK_EXTERNAL_DECL duk_context *duk_get_context(duk_context *ctx, duk_idx_t index);
+DUK_EXTERNAL_DECL void *duk_get_heapptr(duk_context *ctx, duk_idx_t index);
+DUK_EXTERNAL_DECL duk_size_t duk_get_length(duk_context *ctx, duk_idx_t index);
 
 /*
  *  Require operations: no coercion, throw error if index or type
@@ -2949,18 +696,23 @@ duk_size_t duk_get_length(duk_context *ctx, duk_idx_t index);
 #define duk_require_type_mask(ctx,index,mask) \
 	((void) duk_check_type_mask((ctx), (index), (mask) | DUK_TYPE_MASK_THROW))
 
-void duk_require_undefined(duk_context *ctx, duk_idx_t index);
-void duk_require_null(duk_context *ctx, duk_idx_t index);
-duk_bool_t duk_require_boolean(duk_context *ctx, duk_idx_t index);
-duk_double_t duk_require_number(duk_context *ctx, duk_idx_t index);
-duk_int_t duk_require_int(duk_context *ctx, duk_idx_t index);
-duk_uint_t duk_require_uint(duk_context *ctx, duk_idx_t index);
-const char *duk_require_string(duk_context *ctx, duk_idx_t index);
-const char *duk_require_lstring(duk_context *ctx, duk_idx_t index, duk_size_t *out_len);
-void *duk_require_buffer(duk_context *ctx, duk_idx_t index, duk_size_t *out_size);
-void *duk_require_pointer(duk_context *ctx, duk_idx_t index);
-duk_c_function duk_require_c_function(duk_context *ctx, duk_idx_t index);
-duk_context *duk_require_context(duk_context *ctx, duk_idx_t index);
+DUK_EXTERNAL_DECL void duk_require_undefined(duk_context *ctx, duk_idx_t index);
+DUK_EXTERNAL_DECL void duk_require_null(duk_context *ctx, duk_idx_t index);
+DUK_EXTERNAL_DECL duk_bool_t duk_require_boolean(duk_context *ctx, duk_idx_t index);
+DUK_EXTERNAL_DECL duk_double_t duk_require_number(duk_context *ctx, duk_idx_t index);
+DUK_EXTERNAL_DECL duk_int_t duk_require_int(duk_context *ctx, duk_idx_t index);
+DUK_EXTERNAL_DECL duk_uint_t duk_require_uint(duk_context *ctx, duk_idx_t index);
+DUK_EXTERNAL_DECL const char *duk_require_string(duk_context *ctx, duk_idx_t index);
+DUK_EXTERNAL_DECL const char *duk_require_lstring(duk_context *ctx, duk_idx_t index, duk_size_t *out_len);
+DUK_EXTERNAL_DECL void *duk_require_buffer(duk_context *ctx, duk_idx_t index, duk_size_t *out_size);
+DUK_EXTERNAL_DECL void *duk_require_buffer_data(duk_context *ctx, duk_idx_t index, duk_size_t *out_size);
+DUK_EXTERNAL_DECL void *duk_require_pointer(duk_context *ctx, duk_idx_t index);
+DUK_EXTERNAL_DECL duk_c_function duk_require_c_function(duk_context *ctx, duk_idx_t index);
+DUK_EXTERNAL_DECL duk_context *duk_require_context(duk_context *ctx, duk_idx_t index);
+DUK_EXTERNAL_DECL void duk_require_function(duk_context *ctx, duk_idx_t index);
+#define duk_require_callable(ctx,index) \
+	duk_require_function((ctx), (index))
+DUK_EXTERNAL_DECL void *duk_require_heapptr(duk_context *ctx, duk_idx_t index);
 
 #define duk_require_object_coercible(ctx,index) \
 	((void) duk_check_type_mask((ctx), (index), DUK_TYPE_MASK_BOOLEAN | \
@@ -2969,6 +721,7 @@ duk_context *duk_require_context(duk_context *ctx, duk_idx_t index);
 	                                            DUK_TYPE_MASK_OBJECT | \
 	                                            DUK_TYPE_MASK_BUFFER | \
 	                                            DUK_TYPE_MASK_POINTER | \
+	                                            DUK_TYPE_MASK_LIGHTFUNC | \
 	                                            DUK_TYPE_MASK_THROW))
 
 /*
@@ -2978,27 +731,36 @@ duk_context *duk_require_context(duk_context *ctx, duk_idx_t index);
  *  or an internal error (e.g. from out of memory).
  */
 
-void duk_to_undefined(duk_context *ctx, duk_idx_t index);
-void duk_to_null(duk_context *ctx, duk_idx_t index);
-duk_bool_t duk_to_boolean(duk_context *ctx, duk_idx_t index);
-duk_double_t duk_to_number(duk_context *ctx, duk_idx_t index);
-duk_int_t duk_to_int(duk_context *ctx, duk_idx_t index);
-duk_uint_t duk_to_uint(duk_context *ctx, duk_idx_t index);
-duk_int32_t duk_to_int32(duk_context *ctx, duk_idx_t index);
-duk_uint32_t duk_to_uint32(duk_context *ctx, duk_idx_t index);
-duk_uint16_t duk_to_uint16(duk_context *ctx, duk_idx_t index);
-const char *duk_to_string(duk_context *ctx, duk_idx_t index);
-const char *duk_to_lstring(duk_context *ctx, duk_idx_t index, duk_size_t *out_len);
-void *duk_to_buffer(duk_context *ctx, duk_idx_t index, duk_size_t *out_size);
-void *duk_to_fixed_buffer(duk_context *ctx, duk_idx_t index, duk_size_t *out_size);
-void *duk_to_dynamic_buffer(duk_context *ctx, duk_idx_t index, duk_size_t *out_size);
-void *duk_to_pointer(duk_context *ctx, duk_idx_t index);
-void duk_to_object(duk_context *ctx, duk_idx_t index);
-void duk_to_defaultvalue(duk_context *ctx, duk_idx_t index, duk_int_t hint);  /* FIXME: small int? */
-void duk_to_primitive(duk_context *ctx, duk_idx_t index, duk_int_t hint);  /* FIXME: small int? */
+DUK_EXTERNAL_DECL void duk_to_undefined(duk_context *ctx, duk_idx_t index);
+DUK_EXTERNAL_DECL void duk_to_null(duk_context *ctx, duk_idx_t index);
+DUK_EXTERNAL_DECL duk_bool_t duk_to_boolean(duk_context *ctx, duk_idx_t index);
+DUK_EXTERNAL_DECL duk_double_t duk_to_number(duk_context *ctx, duk_idx_t index);
+DUK_EXTERNAL_DECL duk_int_t duk_to_int(duk_context *ctx, duk_idx_t index);
+DUK_EXTERNAL_DECL duk_uint_t duk_to_uint(duk_context *ctx, duk_idx_t index);
+DUK_EXTERNAL_DECL duk_int32_t duk_to_int32(duk_context *ctx, duk_idx_t index);
+DUK_EXTERNAL_DECL duk_uint32_t duk_to_uint32(duk_context *ctx, duk_idx_t index);
+DUK_EXTERNAL_DECL duk_uint16_t duk_to_uint16(duk_context *ctx, duk_idx_t index);
+DUK_EXTERNAL_DECL const char *duk_to_string(duk_context *ctx, duk_idx_t index);
+DUK_EXTERNAL_DECL const char *duk_to_lstring(duk_context *ctx, duk_idx_t index, duk_size_t *out_len);
+DUK_EXTERNAL_DECL void *duk_to_buffer_raw(duk_context *ctx, duk_idx_t index, duk_size_t *out_size, duk_uint_t flags);
+DUK_EXTERNAL_DECL void *duk_to_pointer(duk_context *ctx, duk_idx_t index);
+DUK_EXTERNAL_DECL void duk_to_object(duk_context *ctx, duk_idx_t index);
+DUK_EXTERNAL_DECL void duk_to_defaultvalue(duk_context *ctx, duk_idx_t index, duk_int_t hint);
+DUK_EXTERNAL_DECL void duk_to_primitive(duk_context *ctx, duk_idx_t index, duk_int_t hint);
+
+#define DUK_BUF_MODE_FIXED      0   /* internal: request fixed buffer result */
+#define DUK_BUF_MODE_DYNAMIC    1   /* internal: request dynamic buffer result */
+#define DUK_BUF_MODE_DONTCARE   2   /* internal: don't care about fixed/dynamic nature */
+
+#define duk_to_buffer(ctx,index,out_size) \
+	duk_to_buffer_raw((ctx), (index), (out_size), DUK_BUF_MODE_DONTCARE)
+#define duk_to_fixed_buffer(ctx,index,out_size) \
+	duk_to_buffer_raw((ctx), (index), (out_size), DUK_BUF_MODE_FIXED)
+#define duk_to_dynamic_buffer(ctx,index,out_size) \
+	duk_to_buffer_raw((ctx), (index), (out_size), DUK_BUF_MODE_DYNAMIC)
 
 /* safe variants of a few coercion operations */
-const char *duk_safe_to_lstring(duk_context *ctx, duk_idx_t index, duk_size_t *out_len);
+DUK_EXTERNAL_DECL const char *duk_safe_to_lstring(duk_context *ctx, duk_idx_t index, duk_size_t *out_len);
 #define duk_safe_to_string(ctx,index) \
 	duk_safe_to_lstring((ctx), (index), NULL)
 
@@ -3006,18 +768,20 @@ const char *duk_safe_to_lstring(duk_context *ctx, duk_idx_t index, duk_size_t *o
  *  Misc conversion
  */
 
-const char *duk_base64_encode(duk_context *ctx, duk_idx_t index);
-void duk_base64_decode(duk_context *ctx, duk_idx_t index);
-const char *duk_hex_encode(duk_context *ctx, duk_idx_t index);
-void duk_hex_decode(duk_context *ctx, duk_idx_t index);
-const char *duk_json_encode(duk_context *ctx, duk_idx_t index);
-void duk_json_decode(duk_context *ctx, duk_idx_t index);
+DUK_EXTERNAL_DECL const char *duk_base64_encode(duk_context *ctx, duk_idx_t index);
+DUK_EXTERNAL_DECL void duk_base64_decode(duk_context *ctx, duk_idx_t index);
+DUK_EXTERNAL_DECL const char *duk_hex_encode(duk_context *ctx, duk_idx_t index);
+DUK_EXTERNAL_DECL void duk_hex_decode(duk_context *ctx, duk_idx_t index);
+DUK_EXTERNAL_DECL const char *duk_json_encode(duk_context *ctx, duk_idx_t index);
+DUK_EXTERNAL_DECL void duk_json_decode(duk_context *ctx, duk_idx_t index);
 
 /*
  *  Buffer
  */
 
-void *duk_resize_buffer(duk_context *ctx, duk_idx_t index, duk_size_t new_size);
+DUK_EXTERNAL_DECL void *duk_resize_buffer(duk_context *ctx, duk_idx_t index, duk_size_t new_size);
+DUK_EXTERNAL_DECL void *duk_steal_buffer(duk_context *ctx, duk_idx_t index, duk_size_t *out_size);
+DUK_EXTERNAL_DECL void duk_config_buffer(duk_context *ctx, duk_idx_t index, void *ptr, duk_size_t len);
 
 /*
  *  Property access
@@ -3027,77 +791,111 @@ void *duk_resize_buffer(duk_context *ctx, duk_idx_t index, duk_size_t new_size);
  *  index as a property name (e.g. 123 is equivalent to the key "123").
  */
 
-duk_bool_t duk_get_prop(duk_context *ctx, duk_idx_t obj_index);
-duk_bool_t duk_get_prop_string(duk_context *ctx, duk_idx_t obj_index, const char *key);
-duk_bool_t duk_get_prop_index(duk_context *ctx, duk_idx_t obj_index, duk_uarridx_t arr_index);
-duk_bool_t duk_put_prop(duk_context *ctx, duk_idx_t obj_index);
-duk_bool_t duk_put_prop_string(duk_context *ctx, duk_idx_t obj_index, const char *key);
-duk_bool_t duk_put_prop_index(duk_context *ctx, duk_idx_t obj_index, duk_uarridx_t arr_index);
-duk_bool_t duk_del_prop(duk_context *ctx, duk_idx_t obj_index);
-duk_bool_t duk_del_prop_string(duk_context *ctx, duk_idx_t obj_index, const char *key);
-duk_bool_t duk_del_prop_index(duk_context *ctx, duk_idx_t obj_index, duk_uarridx_t arr_index);
-duk_bool_t duk_has_prop(duk_context *ctx, duk_idx_t obj_index);
-duk_bool_t duk_has_prop_string(duk_context *ctx, duk_idx_t obj_index, const char *key);
-duk_bool_t duk_has_prop_index(duk_context *ctx, duk_idx_t obj_index, duk_uarridx_t arr_index);
+DUK_EXTERNAL_DECL duk_bool_t duk_get_prop(duk_context *ctx, duk_idx_t obj_index);
+DUK_EXTERNAL_DECL duk_bool_t duk_get_prop_string(duk_context *ctx, duk_idx_t obj_index, const char *key);
+DUK_EXTERNAL_DECL duk_bool_t duk_get_prop_index(duk_context *ctx, duk_idx_t obj_index, duk_uarridx_t arr_index);
+DUK_EXTERNAL_DECL duk_bool_t duk_put_prop(duk_context *ctx, duk_idx_t obj_index);
+DUK_EXTERNAL_DECL duk_bool_t duk_put_prop_string(duk_context *ctx, duk_idx_t obj_index, const char *key);
+DUK_EXTERNAL_DECL duk_bool_t duk_put_prop_index(duk_context *ctx, duk_idx_t obj_index, duk_uarridx_t arr_index);
+DUK_EXTERNAL_DECL duk_bool_t duk_del_prop(duk_context *ctx, duk_idx_t obj_index);
+DUK_EXTERNAL_DECL duk_bool_t duk_del_prop_string(duk_context *ctx, duk_idx_t obj_index, const char *key);
+DUK_EXTERNAL_DECL duk_bool_t duk_del_prop_index(duk_context *ctx, duk_idx_t obj_index, duk_uarridx_t arr_index);
+DUK_EXTERNAL_DECL duk_bool_t duk_has_prop(duk_context *ctx, duk_idx_t obj_index);
+DUK_EXTERNAL_DECL duk_bool_t duk_has_prop_string(duk_context *ctx, duk_idx_t obj_index, const char *key);
+DUK_EXTERNAL_DECL duk_bool_t duk_has_prop_index(duk_context *ctx, duk_idx_t obj_index, duk_uarridx_t arr_index);
+DUK_EXTERNAL_DECL void duk_def_prop(duk_context *ctx, duk_idx_t obj_index, duk_uint_t flags);
+
+DUK_EXTERNAL_DECL duk_bool_t duk_get_global_string(duk_context *ctx, const char *key);
+DUK_EXTERNAL_DECL duk_bool_t duk_put_global_string(duk_context *ctx, const char *key);
+
+/*
+ *  Object prototype
+ */
+
+DUK_EXTERNAL_DECL void duk_get_prototype(duk_context *ctx, duk_idx_t index);
+DUK_EXTERNAL_DECL void duk_set_prototype(duk_context *ctx, duk_idx_t index);
+
+/*
+ *  Object finalizer
+ */
+
+DUK_EXTERNAL_DECL void duk_get_finalizer(duk_context *ctx, duk_idx_t index);
+DUK_EXTERNAL_DECL void duk_set_finalizer(duk_context *ctx, duk_idx_t index);
+
+/*
+ *  Global object
+ */
+
+DUK_EXTERNAL_DECL void duk_set_global_object(duk_context *ctx);
+
+/*
+ *  Duktape/C function magic value
+ */
 
-duk_bool_t duk_get_global_string(duk_context *ctx, const char *key);
+DUK_EXTERNAL_DECL duk_int_t duk_get_magic(duk_context *ctx, duk_idx_t index);
+DUK_EXTERNAL_DECL void duk_set_magic(duk_context *ctx, duk_idx_t index, duk_int_t magic);
+DUK_EXTERNAL_DECL duk_int_t duk_get_current_magic(duk_context *ctx);
 
 /*
  *  Module helpers: put multiple function or constant properties
  */
 
-void duk_put_function_list(duk_context *ctx, duk_idx_t obj_index, const duk_function_list_entry *funcs);
-void duk_put_number_list(duk_context *ctx, duk_idx_t obj_index, const duk_number_list_entry *numbers);
+DUK_EXTERNAL_DECL void duk_put_function_list(duk_context *ctx, duk_idx_t obj_index, const duk_function_list_entry *funcs);
+DUK_EXTERNAL_DECL void duk_put_number_list(duk_context *ctx, duk_idx_t obj_index, const duk_number_list_entry *numbers);
 
 /*
  *  Variable access
  */
 
-/* FIXME: incomplete, not usable now */
-void duk_get_var(duk_context *ctx);
-void duk_put_var(duk_context *ctx);
-duk_bool_t duk_del_var(duk_context *ctx);
-duk_bool_t duk_has_var(duk_context *ctx);
+/* XXX: These calls are incomplete and not usable now.  They are not (yet)
+ * part of the public API.
+ */
+DUK_EXTERNAL_DECL void duk_get_var(duk_context *ctx);
+DUK_EXTERNAL_DECL void duk_put_var(duk_context *ctx);
+DUK_EXTERNAL_DECL duk_bool_t duk_del_var(duk_context *ctx);
+DUK_EXTERNAL_DECL duk_bool_t duk_has_var(duk_context *ctx);
 
 /*
  *  Object operations
  */
 
-void duk_compact(duk_context *ctx, duk_idx_t obj_index);
-void duk_enum(duk_context *ctx, duk_idx_t obj_index, duk_uint_t enum_flags);
-duk_bool_t duk_next(duk_context *ctx, duk_idx_t enum_index, duk_bool_t get_value);
+DUK_EXTERNAL_DECL void duk_compact(duk_context *ctx, duk_idx_t obj_index);
+DUK_EXTERNAL_DECL void duk_enum(duk_context *ctx, duk_idx_t obj_index, duk_uint_t enum_flags);
+DUK_EXTERNAL_DECL duk_bool_t duk_next(duk_context *ctx, duk_idx_t enum_index, duk_bool_t get_value);
 
 /*
  *  String manipulation
  */
 
-void duk_concat(duk_context *ctx, duk_idx_t count);
-void duk_join(duk_context *ctx, duk_idx_t count);
-void duk_decode_string(duk_context *ctx, duk_idx_t index, duk_decode_char_function callback, void *udata);
-void duk_map_string(duk_context *ctx, duk_idx_t index, duk_map_char_function callback, void *udata);
-void duk_substring(duk_context *ctx, duk_idx_t index, duk_size_t start_char_offset, duk_size_t end_char_offset);
-void duk_trim(duk_context *ctx, duk_idx_t index);
-duk_codepoint_t duk_char_code_at(duk_context *ctx, duk_idx_t index, duk_size_t char_offset);
+DUK_EXTERNAL_DECL void duk_concat(duk_context *ctx, duk_idx_t count);
+DUK_EXTERNAL_DECL void duk_join(duk_context *ctx, duk_idx_t count);
+DUK_EXTERNAL_DECL void duk_decode_string(duk_context *ctx, duk_idx_t index, duk_decode_char_function callback, void *udata);
+DUK_EXTERNAL_DECL void duk_map_string(duk_context *ctx, duk_idx_t index, duk_map_char_function callback, void *udata);
+DUK_EXTERNAL_DECL void duk_substring(duk_context *ctx, duk_idx_t index, duk_size_t start_char_offset, duk_size_t end_char_offset);
+DUK_EXTERNAL_DECL void duk_trim(duk_context *ctx, duk_idx_t index);
+DUK_EXTERNAL_DECL duk_codepoint_t duk_char_code_at(duk_context *ctx, duk_idx_t index, duk_size_t char_offset);
 
 /*
  *  Ecmascript operators
  */
 
-duk_bool_t duk_equals(duk_context *ctx, duk_idx_t index1, duk_idx_t index2);
-duk_bool_t duk_strict_equals(duk_context *ctx, duk_idx_t index1, duk_idx_t index2);
+DUK_EXTERNAL_DECL duk_bool_t duk_equals(duk_context *ctx, duk_idx_t index1, duk_idx_t index2);
+DUK_EXTERNAL_DECL duk_bool_t duk_strict_equals(duk_context *ctx, duk_idx_t index1, duk_idx_t index2);
+DUK_EXTERNAL_DECL duk_bool_t duk_instanceof(duk_context *ctx, duk_idx_t index1, duk_idx_t index2);
 
 /*
  *  Function (method) calls
  */
 
-void duk_call(duk_context *ctx, duk_idx_t nargs);
-void duk_call_method(duk_context *ctx, duk_idx_t nargs);
-void duk_call_prop(duk_context *ctx, duk_idx_t obj_index, duk_idx_t nargs);
-duk_int_t duk_pcall(duk_context *ctx, duk_idx_t nargs);
-duk_int_t duk_pcall_method(duk_context *ctx, duk_idx_t nargs);
-duk_int_t duk_pcall_prop(duk_context *ctx, duk_idx_t obj_index, duk_idx_t nargs);
-void duk_new(duk_context *ctx, duk_idx_t nargs);
-duk_int_t duk_safe_call(duk_context *ctx, duk_safe_call_function func, duk_idx_t nargs, duk_idx_t nrets);
+DUK_EXTERNAL_DECL void duk_call(duk_context *ctx, duk_idx_t nargs);
+DUK_EXTERNAL_DECL void duk_call_method(duk_context *ctx, duk_idx_t nargs);
+DUK_EXTERNAL_DECL void duk_call_prop(duk_context *ctx, duk_idx_t obj_index, duk_idx_t nargs);
+DUK_EXTERNAL_DECL duk_int_t duk_pcall(duk_context *ctx, duk_idx_t nargs);
+DUK_EXTERNAL_DECL duk_int_t duk_pcall_method(duk_context *ctx, duk_idx_t nargs);
+DUK_EXTERNAL_DECL duk_int_t duk_pcall_prop(duk_context *ctx, duk_idx_t obj_index, duk_idx_t nargs);
+DUK_EXTERNAL_DECL void duk_new(duk_context *ctx, duk_idx_t nargs);
+DUK_EXTERNAL_DECL duk_int_t duk_pnew(duk_context *ctx, duk_idx_t nargs);
+DUK_EXTERNAL_DECL duk_int_t duk_safe_call(duk_context *ctx, duk_safe_call_function func, duk_idx_t nargs, duk_idx_t nrets);
 
 /*
  *  Thread management
@@ -3111,24 +909,24 @@ duk_int_t duk_safe_call(duk_context *ctx, duk_safe_call_function func, duk_idx_t
  *  Compilation and evaluation
  */
 
-duk_int_t duk_eval_raw(duk_context *ctx, const char *src_buffer, duk_size_t src_length, duk_uint_t flags);
-duk_int_t duk_compile_raw(duk_context *ctx, const char *src_buffer, duk_size_t src_length, duk_uint_t flags);
+DUK_EXTERNAL_DECL duk_int_t duk_eval_raw(duk_context *ctx, const char *src_buffer, duk_size_t src_length, duk_uint_t flags);
+DUK_EXTERNAL_DECL duk_int_t duk_compile_raw(duk_context *ctx, const char *src_buffer, duk_size_t src_length, duk_uint_t flags);
 
 /* plain */
 #define duk_eval(ctx)  \
-	((void) duk_push_string((ctx), __FILE__), \
+	((void) duk_push_string((ctx), (const char *) (__FILE__)), \
 	 (void) duk_eval_raw((ctx), NULL, 0, DUK_COMPILE_EVAL))
 
 #define duk_eval_noresult(ctx)  \
-	((void) duk_push_string((ctx), __FILE__), \
+	((void) duk_push_string((ctx), (const char *) (__FILE__)), \
 	 (void) duk_eval_raw((ctx), NULL, 0, DUK_COMPILE_EVAL | DUK_COMPILE_NORESULT))
 
 #define duk_peval(ctx)  \
-	((void) duk_push_string((ctx), __FILE__), \
+	((void) duk_push_string((ctx), (const char *) (__FILE__)), \
 	 duk_eval_raw((ctx), NULL, 0, DUK_COMPILE_EVAL | DUK_COMPILE_SAFE))
 
 #define duk_peval_noresult(ctx)  \
-	((void) duk_push_string((ctx), __FILE__), \
+	((void) duk_push_string((ctx), (const char *) (__FILE__)), \
 	 duk_eval_raw((ctx), NULL, 0, DUK_COMPILE_EVAL | DUK_COMPILE_SAFE | DUK_COMPILE_NORESULT))
 
 #define duk_compile(ctx,flags)  \
@@ -3139,30 +937,30 @@ duk_int_t duk_compile_raw(duk_context *ctx, const char *src_buffer, duk_size_t s
 
 /* string */
 #define duk_eval_string(ctx,src)  \
-	((void) duk_push_string((ctx), __FILE__), \
+	((void) duk_push_string((ctx), (const char *) (__FILE__)), \
 	 (void) duk_eval_raw((ctx), (src), 0, DUK_COMPILE_EVAL | DUK_COMPILE_NOSOURCE | DUK_COMPILE_STRLEN))
 
 #define duk_eval_string_noresult(ctx,src)  \
-	((void) duk_push_string((ctx), __FILE__), \
+	((void) duk_push_string((ctx), (const char *) (__FILE__)), \
 	 (void) duk_eval_raw((ctx), (src), 0, DUK_COMPILE_EVAL | DUK_COMPILE_NOSOURCE | DUK_COMPILE_STRLEN | DUK_COMPILE_NORESULT))
 
 #define duk_peval_string(ctx,src)  \
-	((void) duk_push_string((ctx), __FILE__), \
+	((void) duk_push_string((ctx), (const char *) (__FILE__)), \
 	 duk_eval_raw((ctx), (src), 0, DUK_COMPILE_EVAL | DUK_COMPILE_SAFE | DUK_COMPILE_NOSOURCE | DUK_COMPILE_STRLEN))
 
 #define duk_peval_string_noresult(ctx,src)  \
-	((void) duk_push_string((ctx), __FILE__), \
+	((void) duk_push_string((ctx), (const char *) (__FILE__)), \
 	 duk_eval_raw((ctx), (src), 0, DUK_COMPILE_EVAL | DUK_COMPILE_SAFE | DUK_COMPILE_NOSOURCE | DUK_COMPILE_STRLEN | DUK_COMPILE_NORESULT))
 
 #define duk_compile_string(ctx,flags,src)  \
-	((void) duk_push_string((ctx), __FILE__), \
+	((void) duk_push_string((ctx), (const char *) (__FILE__)), \
 	 (void) duk_compile_raw((ctx), (src), 0, (flags) | DUK_COMPILE_NOSOURCE | DUK_COMPILE_STRLEN))
 
 #define duk_compile_string_filename(ctx,flags,src)  \
 	((void) duk_compile_raw((ctx), (src), 0, (flags) | DUK_COMPILE_NOSOURCE | DUK_COMPILE_STRLEN))
 
 #define duk_pcompile_string(ctx,flags,src)  \
-	((void) duk_push_string((ctx), __FILE__), \
+	((void) duk_push_string((ctx), (const char *) (__FILE__)), \
 	 duk_compile_raw((ctx), (src), 0, (flags) | DUK_COMPILE_SAFE | DUK_COMPILE_NOSOURCE | DUK_COMPILE_STRLEN))
 
 #define duk_pcompile_string_filename(ctx,flags,src)  \
@@ -3170,30 +968,30 @@ duk_int_t duk_compile_raw(duk_context *ctx, const char *src_buffer, duk_size_t s
 
 /* lstring */
 #define duk_eval_lstring(ctx,buf,len)  \
-	((void) duk_push_string((ctx), __FILE__), \
+	((void) duk_push_string((ctx), (const char *) (__FILE__)), \
 	 (void) duk_eval_raw((ctx), buf, len, DUK_COMPILE_EVAL | DUK_COMPILE_NOSOURCE))
 
 #define duk_eval_lstring_noresult(ctx,buf,len)  \
-	((void) duk_push_string((ctx), __FILE__), \
+	((void) duk_push_string((ctx), (const char *) (__FILE__)), \
 	 (void) duk_eval_raw((ctx), buf, len, DUK_COMPILE_EVAL | DUK_COMPILE_NOSOURCE | DUK_COMPILE_NORESULT))
 
 #define duk_peval_lstring(ctx,buf,len)  \
-	((void) duk_push_string((ctx), __FILE__), \
+	((void) duk_push_string((ctx), (const char *) (__FILE__)), \
 	 duk_eval_raw((ctx), buf, len, DUK_COMPILE_EVAL | DUK_COMPILE_NOSOURCE | DUK_COMPILE_SAFE))
 
 #define duk_peval_lstring_noresult(ctx,buf,len)  \
-	((void) duk_push_string((ctx), __FILE__), \
+	((void) duk_push_string((ctx), (const char *) (__FILE__)), \
 	 duk_eval_raw((ctx), buf, len, DUK_COMPILE_EVAL | DUK_COMPILE_SAFE | DUK_COMPILE_NOSOURCE | DUK_COMPILE_NORESULT))
 
 #define duk_compile_lstring(ctx,flags,buf,len)  \
-	((void) duk_push_string((ctx), __FILE__), \
+	((void) duk_push_string((ctx), (const char *) (__FILE__)), \
 	 (void) duk_compile_raw((ctx), buf, len, (flags) | DUK_COMPILE_NOSOURCE))
 
 #define duk_compile_lstring_filename(ctx,flags,buf,len)  \
 	((void) duk_compile_raw((ctx), buf, len, (flags) | DUK_COMPILE_NOSOURCE))
 
 #define duk_pcompile_lstring(ctx,flags,buf,len)  \
-	((void) duk_push_string((ctx), __FILE__), \
+	((void) duk_push_string((ctx), (const char *) (__FILE__)), \
 	 duk_compile_raw((ctx), buf, len, (flags) | DUK_COMPILE_SAFE | DUK_COMPILE_NOSOURCE))
 
 #define duk_pcompile_lstring_filename(ctx,flags,buf,len)  \
@@ -3201,158 +999,180 @@ duk_int_t duk_compile_raw(duk_context *ctx, const char *src_buffer, duk_size_t s
 
 /* file */
 #define duk_eval_file(ctx,path)  \
-	((void) duk_push_string_file((ctx), (path)), \
+	((void) duk_push_string_file_raw((ctx), (path), 0), \
 	 (void) duk_push_string((ctx), (path)), \
 	 (void) duk_eval_raw((ctx), NULL, 0, DUK_COMPILE_EVAL))
 
 #define duk_eval_file_noresult(ctx,path)  \
-	((void) duk_push_string_file((ctx), (path)), \
+	((void) duk_push_string_file_raw((ctx), (path), 0), \
 	 (void) duk_push_string((ctx), (path)), \
 	 (void) duk_eval_raw((ctx), NULL, 0, DUK_COMPILE_EVAL | DUK_COMPILE_NORESULT))
 
 #define duk_peval_file(ctx,path)  \
-	((void) duk_push_string_file((ctx), (path)), \
+	((void) duk_push_string_file_raw((ctx), (path), DUK_STRING_PUSH_SAFE), \
 	 (void) duk_push_string((ctx), (path)), \
 	 duk_eval_raw((ctx), NULL, 0, DUK_COMPILE_EVAL | DUK_COMPILE_SAFE))
 
 #define duk_peval_file_noresult(ctx,path)  \
-	((void) duk_push_string_file((ctx), (path)), \
+	((void) duk_push_string_file_raw((ctx), (path), DUK_STRING_PUSH_SAFE), \
 	 (void) duk_push_string((ctx), (path)), \
 	 duk_eval_raw((ctx), NULL, 0, DUK_COMPILE_EVAL | DUK_COMPILE_SAFE | DUK_COMPILE_NORESULT))
 
 #define duk_compile_file(ctx,flags,path)  \
-	((void) duk_push_string_file((ctx), (path)), \
+	((void) duk_push_string_file_raw((ctx), (path), 0), \
 	 (void) duk_push_string((ctx), (path)), \
 	 (void) duk_compile_raw((ctx), NULL, 0, (flags)))
 
 #define duk_pcompile_file(ctx,flags,path)  \
-	((void) duk_push_string_file((ctx), (path)), \
+	((void) duk_push_string_file_raw((ctx), (path), DUK_STRING_PUSH_SAFE), \
 	 (void) duk_push_string((ctx), (path)), \
 	 duk_compile_raw((ctx), NULL, 0, (flags) | DUK_COMPILE_SAFE))
 
 /*
+ *  Bytecode load/dump
+ */
+
+DUK_EXTERNAL_DECL void duk_dump_function(duk_context *ctx);
+DUK_EXTERNAL_DECL void duk_load_function(duk_context *ctx);
+
+/*
  *  Logging
  */
 
-/* FIXME: here a small integer type would be proper */
-void duk_log(duk_context *ctx, duk_int_t level, const char *fmt, ...);
+DUK_EXTERNAL_DECL void duk_log(duk_context *ctx, duk_int_t level, const char *fmt, ...);
+DUK_EXTERNAL_DECL void duk_log_va(duk_context *ctx, duk_int_t level, const char *fmt, va_list ap);
 
 /*
  *  Debugging
  */
 
-void duk_push_context_dump(duk_context *ctx);
+DUK_EXTERNAL_DECL void duk_push_context_dump(duk_context *ctx);
 
 #if defined(DUK_USE_FILE_IO)
 /* internal use */
 #define duk_dump_context_filehandle(ctx,fh) \
-	do { \
-		duk_push_context_dump((ctx)); \
-		fprintf(stdout, "%s\n", duk_safe_to_string(ctx, -1)); \
-		duk_pop(ctx); \
-	} while (0)
+	(duk_push_context_dump((ctx)), \
+	 DUK_FPRINTF((fh), "%s\n", duk_safe_to_string(ctx, -1)), \
+	 duk_pop(ctx))
 
 /* external use */
 #define duk_dump_context_stdout(ctx) \
-	duk_dump_context_filehandle(ctx,stdout)
+	duk_dump_context_filehandle((ctx), DUK_STDOUT)
 #define duk_dump_context_stderr(ctx) \
-	duk_dump_context_filehandle(ctx,stderr)
+	duk_dump_context_filehandle((ctx), DUK_STDERR)
 #else  /* DUK_USE_FILE_IO */
-#define duk_dump_context_stdout(ctx)  do {} while (0)
-#define duk_dump_context_stderr(ctx)  do {} while (0)
+#define duk_dump_context_stdout(ctx)  ((void) 0)
+#define duk_dump_context_stderr(ctx)  ((void) 0)
 #endif  /* DUK_USE_FILE_IO */
 
 /*
- *  C++ name mangling
+ *  Debugger (debug protocol)
  */
 
-#ifdef __cplusplus
-/* end 'extern "C"' wrapper */
-}
-#endif
-
-#endif  /* DUK_API_PUBLIC_H_INCLUDED */
+DUK_EXTERNAL_DECL void duk_debugger_attach(duk_context *ctx,
+                                           duk_debug_read_function read_cb,
+                                           duk_debug_write_function write_cb,
+                                           duk_debug_peek_function peek_cb,
+                                           duk_debug_read_flush_function read_flush_cb,
+                                           duk_debug_write_flush_function write_flush_cb,
+                                           duk_debug_detached_function detached_cb,
+                                           void *udata);
+DUK_EXTERNAL_DECL void duk_debugger_detach(duk_context *ctx);
+DUK_EXTERNAL_DECL void duk_debugger_cooperate(duk_context *ctx);
 
 /*
- *  END PUBLIC API
+ *  Date provider related constants
+ *
+ *  NOTE: These are "semi public" - you should only use these if you write
+ *  your own platform specific Date provider, see doc/datetime.rst.
  */
 
-/*
- *  Sanity check for the final effective internal defines.  This file also
- *  double checks user tweaks made by an optional duk_custom.h header.
+/* Millisecond count constants. */
+#define DUK_DATE_MSEC_SECOND          1000L
+#define DUK_DATE_MSEC_MINUTE          (60L * 1000L)
+#define DUK_DATE_MSEC_HOUR            (60L * 60L * 1000L)
+#define DUK_DATE_MSEC_DAY             (24L * 60L * 60L * 1000L)
+
+/* Ecmascript date range is 100 million days from Epoch:
+ * > 100e6 * 24 * 60 * 60 * 1000  // 100M days in millisecs
+ * 8640000000000000
+ * (= 8.64e15)
  */
+#define DUK_DATE_MSEC_100M_DAYS         (8.64e15)
+#define DUK_DATE_MSEC_100M_DAYS_LEEWAY  (8.64e15 + 24 * 3600e3)
 
-#ifndef DUK_FEATURES_SANITY_H_INCLUDED
-#define DUK_FEATURES_SANITY_H_INCLUDED
+/* Ecmascript year range:
+ * > new Date(100e6 * 24 * 3600e3).toISOString()
+ * '+275760-09-13T00:00:00.000Z'
+ * > new Date(-100e6 * 24 * 3600e3).toISOString()
+ * '-271821-04-20T00:00:00.000Z'
+ */
+#define DUK_DATE_MIN_ECMA_YEAR     (-271821L)
+#define DUK_DATE_MAX_ECMA_YEAR     275760L
 
-/*
- *  Deprecated feature options.
+/* Part indices for internal breakdowns.  Part order from DUK_DATE_IDX_YEAR
+ * to DUK_DATE_IDX_MILLISECOND matches argument ordering of Ecmascript API
+ * calls (like Date constructor call).  Some functions in duk_bi_date.c
+ * depend on the specific ordering, so change with care.  16 bits are not
+ * enough for all parts (year, specifically).
  *
- *  Catch so that user more easily notices and updates build.
+ * (Must be in-sync with genbuiltins.py.)
  */
+#define DUK_DATE_IDX_YEAR           0  /* year */
+#define DUK_DATE_IDX_MONTH          1  /* month: 0 to 11 */
+#define DUK_DATE_IDX_DAY            2  /* day within month: 0 to 30 */
+#define DUK_DATE_IDX_HOUR           3
+#define DUK_DATE_IDX_MINUTE         4
+#define DUK_DATE_IDX_SECOND         5
+#define DUK_DATE_IDX_MILLISECOND    6
+#define DUK_DATE_IDX_WEEKDAY        7  /* weekday: 0 to 6, 0=sunday, 1=monday, etc */
+#define DUK_DATE_IDX_NUM_PARTS      8
 
-#if defined(DUK_OPT_NO_FUNC_STMT)
-#error DUK_OPT_NO_FUNC_STMT is deprecated, use DUK_OPT_NO_NONSTD_FUNC_STMT
-#endif
-
-#if defined(DUK_OPT_FUNC_NONSTD_CALLER_PROPERTY)
-#error DUK_OPT_FUNC_NONSTD_CALLER_PROPERTY is deprecated, use DUK_OPT_NONSTD_FUNC_CALLER_PROPERTY
-#endif
-
-#if defined(DUK_OPT_FUNC_NONSTD_SOURCE_PROPERTY)
-#error DUK_OPT_FUNC_NONSTD_SOURCE_PROPERTY is deprecated, use DUK_OPT_NONSTD_FUNC_SOURCE_PROPERTY
-#endif
-
-#if defined(DUK_OPT_NO_ARRAY_SPLICE_NONSTD_DELCOUNT)
-#error DUK_OPT_NO_ARRAY_SPLICE_NONSTD_DELCOUNT is deprecated, use DUK_OPT_NO_NONSTD_ARRAY_SPLICE_DELCOUNT
-#endif
-
-#if defined(DUK_OPT_NO_OBJECT_ES6_PROTO_PROPERTY)
-#error DUK_OPT_NO_OBJECT_ES6_PROTO_PROPERTY is deprecated, use DUK_OPT_NO_ES6_OBJECT_PROTO_PROPERTY
-#endif
-
-#if defined(DUK_OPT_NO_OBJECT_ES6_SETPROTOTYPEOF)
-#error DUK_OPT_NO_OBJECT_ES6_SETPROTOTYPEOF is deprecated, use DUK_OPT_NO_ES6_OBJECT_SETPROTOTYPEOF
-#endif
+/* Internal API call flags, used for various functions in this file.
+ * Certain flags are used by only certain functions, but since the flags
+ * don't overlap, a single flags value can be passed around to multiple
+ * functions.
+ *
+ * The unused top bits of the flags field are also used to pass values
+ * to helpers (duk__get_part_helper() and duk__set_part_helper()).
+ *
+ * (Must be in-sync with genbuiltins.py.)
+ */
 
-#if defined(DUK_OPT_NO_JSONX)
-#error DUK_OPT_NO_JSONX is deprecated, use DUK_OPT_NO_JX
-#endif
+/* NOTE: when writing a Date provider you only need a few specific
+ * flags from here, the rest are internal.  Avoid using anything you
+ * don't need.
+ */
 
-#if defined(DUK_OPT_NO_JSONC)
-#error DUK_OPT_NO_JSONC is deprecated, use DUK_OPT_NO_JC
-#endif
+#define DUK_DATE_FLAG_NAN_TO_ZERO          (1 << 0)  /* timeval breakdown: internal time value NaN -> zero */
+#define DUK_DATE_FLAG_NAN_TO_RANGE_ERROR   (1 << 1)  /* timeval breakdown: internal time value NaN -> RangeError (toISOString) */
+#define DUK_DATE_FLAG_ONEBASED             (1 << 2)  /* timeval breakdown: convert month and day-of-month parts to one-based (default is zero-based) */
+#define DUK_DATE_FLAG_EQUIVYEAR            (1 << 3)  /* timeval breakdown: replace year with equivalent year in the [1971,2037] range for DST calculations */
+#define DUK_DATE_FLAG_LOCALTIME            (1 << 4)  /* convert time value to local time */
+#define DUK_DATE_FLAG_SUB1900              (1 << 5)  /* getter: subtract 1900 from year when getting year part */
+#define DUK_DATE_FLAG_TOSTRING_DATE        (1 << 6)  /* include date part in string conversion result */
+#define DUK_DATE_FLAG_TOSTRING_TIME        (1 << 7)  /* include time part in string conversion result */
+#define DUK_DATE_FLAG_TOSTRING_LOCALE      (1 << 8)  /* use locale specific formatting if available */
+#define DUK_DATE_FLAG_TIMESETTER           (1 << 9)  /* setter: call is a time setter (affects hour, min, sec, ms); otherwise date setter (affects year, month, day-in-month) */
+#define DUK_DATE_FLAG_YEAR_FIXUP           (1 << 10) /* setter: perform 2-digit year fixup (00...99 -> 1900...1999) */
+#define DUK_DATE_FLAG_SEP_T                (1 << 11) /* string conversion: use 'T' instead of ' ' as a separator */
+#define DUK_DATE_FLAG_VALUE_SHIFT          12        /* additional values begin at bit 12 */
 
 /*
- *  Debug print consistency
+ *  C++ name mangling
  */
 
-#if defined(DUK_USE_DPRINT) && !defined(DUK_USE_DEBUG)
-#error DUK_USE_DPRINT without DUK_USE_DEBUG
-#endif
-
-#if defined(DUK_USE_DDPRINT) && !defined(DUK_USE_DEBUG)
-#error DUK_USE_DDPRINT without DUK_USE_DEBUG
+#ifdef __cplusplus
+/* end 'extern "C"' wrapper */
+}
 #endif
 
-#if defined(DUK_USE_DDDPRINT) && !defined(DUK_USE_DEBUG)
-#error DUK_USE_DDDPRINT without DUK_USE_DEBUG
-#endif
+#endif  /* DUK_API_PUBLIC_H_INCLUDED */
 
 /*
- *  Garbage collection consistency
+ *  END PUBLIC API
  */
 
-#if defined(DUK_USE_REFERENCE_COUNTING) && !defined(DUK_USE_DOUBLE_LINKED_HEAP)
-#error DUK_USE_REFERENCE_COUNTING defined without DUK_USE_DOUBLE_LINKED_HEAP
-#endif
-
-#if defined(DUK_USE_GC_TORTURE) && !defined(DUK_USE_MARK_AND_SWEEP)
-#error DUK_USE_GC_TORTURE defined without DUK_USE_MARK_AND_SWEEP
-#endif
-
-#endif  /* DUK_FEATURES_SANITY_H_INCLUDED */
-
 /*
  *  Union to access IEEE double memory representation, indexes for double
  *  memory representation, and some macros for double manipulation.
@@ -3392,7 +1212,7 @@ void duk_push_context_dump(duk_context *ctx);
  *  Indexes of various types (8-bit, 16-bit, 32-bit) in memory relative to
  *  the logical (big endian) order:
  *
- *  byte order      duk_uint8_t    duk_uint16_t     duk_uint32_t    
+ *  byte order      duk_uint8_t    duk_uint16_t     duk_uint32_t
  *    BE             01234567         0123               01
  *    LE             76543210         3210               10
  *    ME (ARM)       32107654         1032               01
@@ -3412,13 +1232,14 @@ void duk_push_context_dump(duk_context *ctx);
 
 union duk_double_union {
 	double d;
-#ifdef DUK_USE_64BIT_OPS
+	float f[2];
+#if defined(DUK_USE_64BIT_OPS)
 	duk_uint64_t ull[1];
 #endif
 	duk_uint32_t ui[2];
 	duk_uint16_t us[4];
 	duk_uint8_t uc[8];
-#ifdef DUK_USE_PACKED_TVAL_POSSIBLE
+#if defined(DUK_USE_PACKED_TVAL)
 	void *vp[2];  /* used by packed duk_tval, assumes sizeof(void *) == 4 */
 #endif
 };
@@ -3531,6 +1352,25 @@ typedef union duk_double_union duk_double_union;
 #define DUK_DBLUNION_GET_HIGH32(u)  ((u)->ui[DUK_DBL_IDX_UI0])
 #define DUK_DBLUNION_GET_LOW32(u)   ((u)->ui[DUK_DBL_IDX_UI1])
 
+#ifdef DUK_USE_64BIT_OPS
+#ifdef DUK_USE_DOUBLE_ME
+#define DUK_DBLUNION_SET_UINT64(u,v)  do { \
+		(u)->ui[DUK_DBL_IDX_UI0] = (duk_uint32_t) ((v) >> 32); \
+		(u)->ui[DUK_DBL_IDX_UI1] = (duk_uint32_t) (v); \
+	} while (0)
+#define DUK_DBLUNION_GET_UINT64(u) \
+	((((duk_uint64_t) (u)->ui[DUK_DBL_IDX_UI0]) << 32) | \
+	 ((duk_uint64_t) (u)->ui[DUK_DBL_IDX_UI1]))
+#else
+#define DUK_DBLUNION_SET_UINT64(u,v)  do { \
+		(u)->ull[DUK_DBL_IDX_ULL0] = (duk_uint64_t) (v); \
+	} while (0)
+#define DUK_DBLUNION_GET_UINT64(u)  ((u)->ull[DUK_DBL_IDX_ULL0])
+#endif
+#define DUK_DBLUNION_SET_INT64(u,v) DUK_DBLUNION_SET_UINT64((u), (duk_uint64_t) (v))
+#define DUK_DBLUNION_GET_INT64(u)   ((duk_int64_t) DUK_DBLUNION_GET_UINT64((u)))
+#endif  /* DUK_USE_64BIT_OPS */
+
 /*
  *  Double NaN manipulation macros related to NaN normalization needed when
  *  using the packed duk_tval representation.  NaN normalization is necessary
@@ -3538,7 +1378,7 @@ typedef union duk_double_union duk_double_union;
  *
  *  When packed duk_tval is used, the NaN space is used to store pointers
  *  and other tagged values in addition to NaNs.  Actual NaNs are normalized
- *  to a specific format.  The macros below are used by the implementation
+ *  to a specific quiet NaN.  The macros below are used by the implementation
  *  to check and normalize NaN values when they might be created.  The macros
  *  are essentially NOPs when the non-packed duk_tval representation is used.
  *
@@ -3546,7 +1386,8 @@ typedef union duk_double_union duk_double_union;
  *  the packed duk_tval and works correctly for all NaNs except those that
  *  begin with 0x7ff0.  Since the 'normalized NaN' values used with packed
  *  duk_tval begin with 0x7ff8, the partial check is reliable when packed
- *  duk_tval is used.
+ *  duk_tval is used.  The 0x7ff8 prefix means the normalized NaN will be a
+ *  quiet NaN regardless of its remaining lower bits.
  *
  *  The ME variant below is specifically for ARM byte order, which has the
  *  feature that while doubles have a mixed byte order (32107654), unsigned
@@ -3664,6 +1505,51 @@ typedef union duk_double_union duk_double_union;
 	} while (0)
 #endif  /* DUK_USE_PACKED_TVAL */
 
+/* XXX: native 64-bit byteswaps when available */
+
+/* 64-bit byteswap, same operation independent of target endianness. */
+#define DUK_DBLUNION_BSWAP64(u) do { \
+		duk_uint32_t duk__bswaptmp1, duk__bswaptmp2; \
+		duk__bswaptmp1 = (u)->ui[0]; \
+		duk__bswaptmp2 = (u)->ui[1]; \
+		duk__bswaptmp1 = DUK_BSWAP32(duk__bswaptmp1); \
+		duk__bswaptmp2 = DUK_BSWAP32(duk__bswaptmp2); \
+		(u)->ui[0] = duk__bswaptmp2; \
+		(u)->ui[1] = duk__bswaptmp1; \
+	} while (0)
+
+/* Byteswap an IEEE double in the duk_double_union from host to network
+ * order.  For a big endian target this is a no-op.
+ */
+#if defined(DUK_USE_DOUBLE_LE)
+#define DUK_DBLUNION_DOUBLE_HTON(u) do { \
+		duk_uint32_t duk__bswaptmp1, duk__bswaptmp2; \
+		duk__bswaptmp1 = (u)->ui[0]; \
+		duk__bswaptmp2 = (u)->ui[1]; \
+		duk__bswaptmp1 = DUK_BSWAP32(duk__bswaptmp1); \
+		duk__bswaptmp2 = DUK_BSWAP32(duk__bswaptmp2); \
+		(u)->ui[0] = duk__bswaptmp2; \
+		(u)->ui[1] = duk__bswaptmp1; \
+	} while (0)
+#elif defined(DUK_USE_DOUBLE_ME)
+#define DUK_DBLUNION_DOUBLE_HTON(u) do { \
+		duk_uint32_t duk__bswaptmp1, duk__bswaptmp2; \
+		duk__bswaptmp1 = (u)->ui[0]; \
+		duk__bswaptmp2 = (u)->ui[1]; \
+		duk__bswaptmp1 = DUK_BSWAP32(duk__bswaptmp1); \
+		duk__bswaptmp2 = DUK_BSWAP32(duk__bswaptmp2); \
+		(u)->ui[0] = duk__bswaptmp1; \
+		(u)->ui[1] = duk__bswaptmp2; \
+	} while (0)
+#elif defined(DUK_USE_DOUBLE_BE)
+#define DUK_DBLUNION_DOUBLE_HTON(u) do { } while (0)
+#else
+#error internal error, double endianness insane
+#endif
+
+/* Reverse operation is the same. */
+#define DUK_DBLUNION_DOUBLE_NTOH(u) DUK_DBLUNION_DOUBLE_HTON((u))
+
 #endif  /* DUK_DBLUNION_H_INCLUDED */
 
 #endif  /* DUKTAPE_H_INCLUDED */
diff --git a/src/osgEarthDrivers/sky_gl/CMakeLists.txt b/src/osgEarthDrivers/sky_gl/CMakeLists.txt
index 6c56850..ea14c74 100644
--- a/src/osgEarthDrivers/sky_gl/CMakeLists.txt
+++ b/src/osgEarthDrivers/sky_gl/CMakeLists.txt
@@ -1,6 +1,7 @@
 SET(TARGET_SRC 
     GLSkyDriver.cpp
     GLSkyNode.cpp
+    GLSkyExtension.cpp
 )
 SET(TARGET_H
     GLSkyOptions
diff --git a/src/osgEarthDrivers/sky_gl/GLSkyDriver.cpp b/src/osgEarthDrivers/sky_gl/GLSkyDriver.cpp
index 6459641..e69de29 100644
--- a/src/osgEarthDrivers/sky_gl/GLSkyDriver.cpp
+++ b/src/osgEarthDrivers/sky_gl/GLSkyDriver.cpp
@@ -1,62 +0,0 @@
-/* -*-c++-*- */
-/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
- * http://osgearth.org
- *
- * osgEarth is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>
- */
-#include "GLSkyOptions"
-#include "GLSkyNode"
-#include <osgDB/FileNameUtils>
-#include <osgEarth/Map>
-#include <osgEarth/MapNode>
-
-#define LC "[GLSkyDriver] "
-
-using namespace osgEarth::Util;
-
-namespace osgEarth { namespace Drivers { namespace GLSky
-{
-    class GLSkyDriver : public SkyDriver
-    {
-    public:
-        GLSkyDriver()
-        {
-            supportsExtension(
-                "osgearth_sky_gl",
-                "osgEarth GL Sky Plugin" );
-        }
-
-        const char* className()
-        {
-            return "osgEarth GL Sky Plugin";
-        }
-
-        ReadResult readNode(const std::string& file_name, const osgDB::Options* options) const
-        {
-            if ( !acceptsExtension(osgDB::getLowerCaseFileExtension( file_name )))
-                return ReadResult::FILE_NOT_HANDLED;
-
-            MapNode* mapNode = getMapNode(options);
-            const Profile* profile = mapNode ? mapNode->getMap()->getProfile() : 0L;
-            return new GLSkyNode(profile, getSkyOptions(options));
-        }
-
-    protected:
-        virtual ~GLSkyDriver() { }
-    };
-
-    REGISTER_OSGPLUGIN(osgearth_sky_gl, GLSkyDriver)
-
-} } } // namespace osgEarth::Drivers::GLSky
diff --git a/src/osgEarthDrivers/sky_gl/GLSkyExtension.cpp b/src/osgEarthDrivers/sky_gl/GLSkyExtension.cpp
new file mode 100644
index 0000000..a607847
--- /dev/null
+++ b/src/osgEarthDrivers/sky_gl/GLSkyExtension.cpp
@@ -0,0 +1,153 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+ * Copyright 2016 Pelican Mapping
+ * http://osgearth.org
+ *
+ * osgEarth is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ */
+#include "GLSkyOptions"
+#include "GLSkyNode"
+#include <osg/Camera>
+#include <osg/View>
+#include <osgDB/FileNameUtils>
+#include <osgEarth/Map>
+#include <osgEarth/MapNode>
+#include <osgEarthUtil/Sky>
+#include <osgEarthUtil/Controls>
+#include <osgEarthUtil/ExampleResources>
+
+#define LC "[GLSkyDriver] "
+
+using namespace osgEarth;
+using namespace osgEarth::Util;
+namespace ui = osgEarth::Util::Controls;
+
+namespace osgEarth { namespace GLSky
+{
+    class GLSkyExtension : public Extension,
+                           public ExtensionInterface<MapNode>,
+                           public ExtensionInterface<osg::View>,
+                           public ExtensionInterface<ui::Control>,
+                           public SkyNodeFactory,
+                           public GLSkyOptions
+    {
+    public:
+        META_Object( osgEarth, GLSkyExtension );
+
+        GLSkyExtension() { }
+        GLSkyExtension(const GLSkyOptions& options);
+
+    public: // ExtensionInterface<MapNode>
+
+        bool connect( MapNode* );
+        bool disconnect( MapNode* );
+
+    public: // ExtensionInterface<osg::View>
+
+        bool connect( osg::View* );
+        bool disconnect( osg::View* ) { return true; }
+
+    public: // ExtensionInterface<ui::Control>
+
+        bool connect( ui::Control* );
+        bool disconnect( ui::Control* ) { return true; }
+
+    public: // SkyNodeFactory
+
+        SkyNode* createSkyNode(const Profile* profile);
+
+    protected:
+        GLSkyExtension(const GLSkyExtension&, const osg::CopyOp&) { }
+        virtual ~GLSkyExtension() { }
+
+        osg::ref_ptr<SkyNode> _skyNode;
+    };
+
+    REGISTER_OSGEARTH_EXTENSION( osgearth_sky_gl, GLSkyExtension );
+    
+} } // namespace
+
+
+#undef  LC
+#define LC "[GLSky] "
+
+using namespace osgEarth::GLSky;
+
+
+GLSkyExtension::GLSkyExtension(const GLSkyOptions& options) :
+GLSkyOptions(options)
+{
+    //nop
+}
+
+bool
+GLSkyExtension::connect(MapNode* mapNode)
+{
+    OE_INFO << LC << "Hello world.\n";
+    
+    // find the tip top of the tree that MapNode is in:
+    osg::Node* top = mapNode;
+    while (top->getNumParents() > 0 && std::string(top->getParent(0)->className()) != "Camera")
+        top = top->getParent(0);
+
+    osg::Group* topParent = top->getNumParents() > 0 ? top->getParent(0) : 0L;
+
+    // make the sky node
+    if ( !_skyNode.valid() )
+    {
+        _skyNode = createSkyNode( mapNode->getMap()->getProfile() );
+    }
+     
+    // insert the new sky node at the top of the tree.
+    _skyNode->addChild( top );
+
+    if ( topParent )
+    {
+        topParent->addChild( _skyNode.get() );
+        topParent->removeChild( top );
+    }
+
+    return true;
+}
+
+bool
+GLSkyExtension::disconnect(MapNode* mapNode)
+{
+    return true;
+}
+
+bool
+GLSkyExtension::connect(osg::View* view)
+{
+    if ( view && _skyNode.valid() )
+    {
+        _skyNode->attach( view, 0 );
+    }
+    return true;
+}
+
+bool
+GLSkyExtension::connect(ui::Control* control)
+{
+    ui::Container* container = dynamic_cast<ui::Container*>(control);
+    if (container && _skyNode.valid())
+        container->addControl(SkyControlFactory::create(_skyNode.get()));
+    return true;
+}
+
+SkyNode*
+GLSkyExtension::createSkyNode(const Profile* profile)
+{
+    return new GLSkyNode(profile, *this);
+}
diff --git a/src/osgEarthDrivers/sky_gl/GLSkyNode b/src/osgEarthDrivers/sky_gl/GLSkyNode
index 5a8c128..68e5430 100644
--- a/src/osgEarthDrivers/sky_gl/GLSkyNode
+++ b/src/osgEarthDrivers/sky_gl/GLSkyNode
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -29,7 +29,7 @@ namespace osg {
     class LightSource;
 }
 
-namespace osgEarth { namespace Drivers { namespace GLSky
+namespace osgEarth { namespace GLSky
 {
     using namespace osgEarth;
     using namespace osgEarth::Util;
@@ -70,4 +70,4 @@ namespace osgEarth { namespace Drivers { namespace GLSky
         GLSkyOptions                      _options;
     };
 
-} } } // namespace osgEarth::Drivers::GLSky
+} } // namespace osgEarth::Drivers::GLSky
diff --git a/src/osgEarthDrivers/sky_gl/GLSkyNode.cpp b/src/osgEarthDrivers/sky_gl/GLSkyNode.cpp
index c54e99e..9c434a5 100644
--- a/src/osgEarthDrivers/sky_gl/GLSkyNode.cpp
+++ b/src/osgEarthDrivers/sky_gl/GLSkyNode.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
@@ -33,7 +33,7 @@
 
 using namespace osgEarth;
 using namespace osgEarth::Util;
-using namespace osgEarth::Drivers::GLSky;
+using namespace osgEarth::GLSky;
 
 //---------------------------------------------------------------------------
 
diff --git a/src/osgEarthDrivers/sky_gl/GLSkyOptions b/src/osgEarthDrivers/sky_gl/GLSkyOptions
index 67a9f6b..89413da 100644
--- a/src/osgEarthDrivers/sky_gl/GLSkyOptions
+++ b/src/osgEarthDrivers/sky_gl/GLSkyOptions
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -21,7 +21,7 @@
 
 #include <osgEarthUtil/Sky>
 
-namespace osgEarth { namespace Drivers { namespace GLSky
+namespace osgEarth { namespace GLSky
 {
     using namespace osgEarth;
     using namespace osgEarth::Util;
@@ -61,6 +61,6 @@ namespace osgEarth { namespace Drivers { namespace GLSky
         }
     };
 
-} } } // namespace osgEarth::Drivers::GLSky
+} } // namespace osgEarth::Drivers::GLSky
 
 #endif // OSGEARTH_DRIVER_GL_SKY_OPTIONS
diff --git a/src/osgEarthDrivers/sky_gl/GLSkyShaders b/src/osgEarthDrivers/sky_gl/GLSkyShaders
index 92ceade..6e94cab 100644
--- a/src/osgEarthDrivers/sky_gl/GLSkyShaders
+++ b/src/osgEarthDrivers/sky_gl/GLSkyShaders
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -21,7 +21,7 @@
 
 #include <osgEarth/VirtualProgram>
 
-namespace osgEarth { namespace Drivers { namespace GLSky
+namespace osgEarth { namespace GLSky
 {
 #ifdef OSG_GLES2_AVAILABLE
     static const char* Phong_Vertex =
@@ -32,13 +32,13 @@ namespace osgEarth { namespace Drivers { namespace GLSky
         "varying vec4 oe_lighting_adjustment; \n"
         "varying vec4 oe_lighting_zero_vec; \n"
 
-        "vec3 oe_global_Normal; \n"
+        "vec3 vp_Normal; \n"
 
         "void oe_sky_vertex_main(inout vec4 VertexVIEW) \n"
         "{ \n"
         "    if ( oe_mode_GL_LIGHTING == false ) return; \n"
         "    oe_lighting_adjustment = vec4(1.0); \n"
-        "    vec3 N = oe_global_Normal; \n"
+        "    vec3 N = vp_Normal; \n"
         "    float NdotL = dot( N, normalize(gl_LightSource[0].position.xyz) ); \n"
         "    NdotL = max( 0.0, NdotL ); \n"
 
@@ -97,7 +97,7 @@ namespace osgEarth { namespace Drivers { namespace GLSky
         "uniform bool oe_mode_GL_LIGHTING; \n"
         "varying vec3 oe_glsky_vertexView3; \n"
         
-        "vec3 oe_global_Normal; \n"
+        "vec3 vp_Normal; \n"
 
         "void oe_sky_fragment_main(inout vec4 color) \n"
         "{ \n"        
@@ -105,7 +105,7 @@ namespace osgEarth { namespace Drivers { namespace GLSky
 
         "    vec3 L = normalize(gl_LightSource[0].position.xyz); \n"
         "    vec3 V = normalize(oe_glsky_vertexView3); \n"
-        "    vec3 N = normalize(oe_global_Normal); \n"
+        "    vec3 N = normalize(vp_Normal); \n"
         "    vec3 R = normalize(-reflect(L,N)); \n"
 
         "    float NdotL = max(dot(N,L), 0.0); \n"
@@ -125,6 +125,6 @@ namespace osgEarth { namespace Drivers { namespace GLSky
         "} \n";
 #endif
 
-} } } // namespace osgEarth::Drivers::GLSky
+} } // namespace osgEarth::Drivers::GLSky
 
 #endif //OSGEARTH_DRIVER_GL_SKY_SHADERS
diff --git a/src/osgEarthDrivers/sky_silverlining/CMakeLists.txt b/src/osgEarthDrivers/sky_silverlining/CMakeLists.txt
index a8f27ee..719ba30 100644
--- a/src/osgEarthDrivers/sky_silverlining/CMakeLists.txt
+++ b/src/osgEarthDrivers/sky_silverlining/CMakeLists.txt
@@ -2,26 +2,16 @@ IF(SILVERLINING_FOUND)
 
 SET(TARGET_SRC 
     SilverLiningDriver.cpp
-    SilverLiningNode.cpp
-    SilverLiningContext.cpp
-    SilverLiningSkyDrawable.cpp
-    SilverLiningCloudsDrawable.cpp
 )
 SET(TARGET_H
-    SilverLiningOptions
-    SilverLiningNode
-    SilverLiningContext
-    SilverLiningSkyDrawable
-    SilverLiningCloudsDrawable
 )
 
 INCLUDE_DIRECTORIES( 
-    ${SILVERLINING_INCLUDE_DIR}
 )
 
 SET(TARGET_COMMON_LIBRARIES ${TARGET_COMMON_LIBRARIES}
-	${SILVERLINING_LIBRARY}
     osgEarthUtil
+    osgEarthSilverLining
 )
 
 SETUP_PLUGIN(osgearth_sky_silverlining)
@@ -29,7 +19,6 @@ SETUP_PLUGIN(osgearth_sky_silverlining)
 
 # to install public driver includes:
 SET(LIB_NAME sky_silverlining)
-SET(LIB_PUBLIC_HEADERS SilverLiningOptions)
 
 INCLUDE(ModuleInstallOsgEarthDriverIncludes OPTIONAL)
 
diff --git a/src/osgEarthDrivers/sky_silverlining/SilverLiningCloudsDrawable b/src/osgEarthDrivers/sky_silverlining/SilverLiningCloudsDrawable
deleted file mode 100644
index 2ac1db3..0000000
--- a/src/osgEarthDrivers/sky_silverlining/SilverLiningCloudsDrawable
+++ /dev/null
@@ -1,64 +0,0 @@
-/* -*-c++-*- */
-/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
- * http://osgearth.org
- *
- * osgEarth is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>
- */
-#include <osg/Drawable>
-#include <osg/RenderInfo>
-#include <osg/Version>
-#include <osgEarth/NativeProgramAdapter>
-#include <vector>
-#include <map>
-
-namespace osgEarth { namespace SilverLining
-{
-    class SilverLiningContext;
-
-    /**
-     * Custom drawable for rendering the SilverLining clouds
-     */
-    class CloudsDrawable : public osg::Drawable
-    {
-    public:
-        CloudsDrawable(SilverLiningContext* SL =0L);
-        META_Object(SilverLining, CloudsDrawable);
-
-		/* Sets whether to draw this item */
-		void setDraw(bool draw);
-     
-    public: // osg::Drawable
-
-        // custom draw (called with an active GC)
-        void drawImplementation(osg::RenderInfo& ri) const;
-        
-        // custom bounds computation
-#if OSG_VERSION_GREATER_THAN(3,3,1)
-        osg::BoundingBox computeBoundingBox() const;
-#else
-        osg::BoundingBox computeBound() const;
-#endif
-
-    protected:
-        virtual ~CloudsDrawable() { }
-
-        osg::observer_ptr<SilverLiningContext> _SL;
-
-        mutable osg::buffered_object<osgEarth::NativeProgramAdapterCollection> _adapters;
-        
-        CloudsDrawable(const CloudsDrawable& copy, const osg::CopyOp& op=osg::CopyOp::SHALLOW_COPY) { }
-    };
-
-} } // namespace osgEarth::SilverLining
diff --git a/src/osgEarthDrivers/sky_silverlining/SilverLiningCloudsDrawable.cpp b/src/osgEarthDrivers/sky_silverlining/SilverLiningCloudsDrawable.cpp
deleted file mode 100644
index 2556fc9..0000000
--- a/src/osgEarthDrivers/sky_silverlining/SilverLiningCloudsDrawable.cpp
+++ /dev/null
@@ -1,83 +0,0 @@
-/* -*-c++-*- */
-/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
- * http://osgearth.org
- *
- * osgEarth is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>
- */
-#include <SilverLining.h>
-#include "SilverLiningCloudsDrawable"
-#include "SilverLiningContext"
-#include <osgEarth/SpatialReference>
-
-#undef  LC
-#define LC "[SilverLining:SkyDrawable] "
-
-using namespace osgEarth::SilverLining;
-
-
-CloudsDrawable::CloudsDrawable(SilverLiningContext* SL) :
-_SL( SL )
-{
-    // call this to ensure draw() gets called every frame.
-    setSupportsDisplayList( false );
-    
-    // not MT-safe (camera updates, etc)
-    this->setDataVariance(osg::Object::DYNAMIC);
-}
-
-void
-CloudsDrawable::drawImplementation(osg::RenderInfo& renderInfo) const
-{
-    if( _SL->ready() )
-    {
-        const osg::State* state = renderInfo.getState();
-
-        osgEarth::NativeProgramAdapterCollection& adapters = _adapters[ state->getContextID() ]; // thread safe.
-        if ( adapters.empty() )
-        {
-            adapters.push_back( new osgEarth::NativeProgramAdapter(state, _SL->getAtmosphere()->GetSkyShader()) );
-            adapters.push_back( new osgEarth::NativeProgramAdapter(state, _SL->getAtmosphere()->GetBillboardShader()) );
-            adapters.push_back( new osgEarth::NativeProgramAdapter(state, _SL->getAtmosphere()->GetStarShader()) );
-            adapters.push_back( new osgEarth::NativeProgramAdapter(state, _SL->getAtmosphere()->GetPrecipitationShader()) );
-
-            SL_VECTOR(unsigned) handles = _SL->getAtmosphere()->GetActivePlanarCloudShaders();
-            for(int i=0; i<handles.size(); ++i)          
-                adapters.push_back( new osgEarth::NativeProgramAdapter(state, handles[i]) );
-        }
-
-        adapters.apply( state );
-
-        renderInfo.getState()->disableAllVertexArrays();
-        _SL->getAtmosphere()->DrawObjects( true, true, true );
-        renderInfo.getState()->dirtyAllVertexArrays();
-    }
-}
-
-osg::BoundingBox
-#if OSG_VERSION_GREATER_THAN(3,3,1)
-CloudsDrawable::computeBoundingBox() const
-#else
-CloudsDrawable::computeBound() const
-#endif
-{
-    osg::BoundingBox cloudBoundBox;
-    if ( !_SL->ready() )
-        return cloudBoundBox;
-    
-    double minX, minY, minZ, maxX, maxY, maxZ;
-    _SL->getAtmosphere()->GetCloudBounds( minX, minY, minZ, maxX, maxY, maxZ );
-    cloudBoundBox.set( osg::Vec3d(minX, minY, minZ), osg::Vec3d(maxX, maxY, maxZ) );
-    return cloudBoundBox;
-}
diff --git a/src/osgEarthDrivers/sky_silverlining/SilverLiningContext b/src/osgEarthDrivers/sky_silverlining/SilverLiningContext
deleted file mode 100644
index 2fffbfd..0000000
--- a/src/osgEarthDrivers/sky_silverlining/SilverLiningContext
+++ /dev/null
@@ -1,108 +0,0 @@
-/* -*-c++-*- */
-/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
- * http://osgearth.org
- *
- * osgEarth is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>
- */
-#include "SilverLiningOptions"
-#include <osg/Referenced>
-#include <osg/Light>
-#include <osg/Camera>
-#include <osgEarth/ThreadingUtils>
-
-namespace SilverLining {
-    class Atmosphere;
-    class CloudLayer;
-}
-namespace osgEarth {
-    class SpatialReference;
-}
-
-namespace osgEarth { namespace SilverLining
-{
-    /**
-     * Contains all the SilverLining SDK pointers.
-     */
-    class SilverLiningContext : public osg::Referenced
-    {
-    public:
-        SilverLiningContext(const SilverLiningOptions& options);
-        
-        /** Sets the light source that will represent the sun */
-        void setLight(osg::Light* light);
-
-        /** Sets the spatial reference system of the map */
-        void setSRS(const SpatialReference* srs);
-
-        /** Sets the minimum ambient lighting value */
-        void setMinimumAmbient(const osg::Vec4f& value);
-
-    public: // accessors
-
-        bool ready() const { return _initAttempted && !_initFailed; }
-
-        ::SilverLining::Atmosphere* getAtmosphere() { return _atmosphere; }
-
-        /** Spatial reference of the map */
-        const SpatialReference* getSRS() const { return _srs.get(); }
-
-        void setSkyBoxSize(double size) { _skyBoxSize = size; }
-        double getSkyBoxSize() const { return _skyBoxSize; }
-
-        void initialize(osg::RenderInfo& renderInfo);
-
-        void updateLocation();
-
-        void updateLight();
-
-        /** Set/get the cached camers. NOT THREAD/MULTI-CAM SAFE. */
-        /** TODO */
-        void setCamera(osg::Camera* camera) { _camera = camera; }
-        osg::Camera* getCamera() { return _camera.get(); }
-
-        void setCameraPosition(const osg::Vec3d& pos) { _cameraPos = pos; }
-        const osg::Vec3d& getCameraPosition() const { return _cameraPos; }
-
-    protected:
-
-        virtual ~SilverLiningContext();
-
-    private:
-
-        void setupClouds();
-
-    private:
-        ::SilverLining::Atmosphere* _atmosphere;
-        ::SilverLining::CloudLayer* _clouds;
-
-        double _skyBoxSize;
-
-        osg::observer_ptr<osg::Light>                  _light;
-        osg::ref_ptr<const osgEarth::SpatialReference> _srs;
-
-        bool                       _initAttempted;
-        bool                       _initFailed;
-        osgEarth::Threading::Mutex _initMutex;
-
-        double _maxAmbientLightingAlt;
-
-        osg::observer_ptr<osg::Camera> _camera;
-        osg::Vec3d                     _cameraPos; // eye point
-        osg::Vec4f                     _minAmbient;
-
-        SilverLiningOptions _options;
-    };
-
-} } // namespace osgEarth::SilverLining
diff --git a/src/osgEarthDrivers/sky_silverlining/SilverLiningContext.cpp b/src/osgEarthDrivers/sky_silverlining/SilverLiningContext.cpp
deleted file mode 100644
index 33860f6..0000000
--- a/src/osgEarthDrivers/sky_silverlining/SilverLiningContext.cpp
+++ /dev/null
@@ -1,242 +0,0 @@
-/* -*-c++-*- */
-/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
- * http://osgearth.org
- *
- * osgEarth is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>
- */
-#include <SilverLining.h> // SilverLinking SDK
-#include "SilverLiningContext"
-#include <osg/Light>
-#include <osgEarth/SpatialReference>
-
-#define LC "[SilverLiningContext] "
-
-using namespace osgEarth::SilverLining;
-
-
-SilverLiningContext::SilverLiningContext(const SilverLiningOptions& options) :
-_options              ( options ),
-_initAttempted        ( false ),
-_initFailed           ( false ),
-_maxAmbientLightingAlt( -1.0 ),
-_atmosphere           ( 0L ),
-_clouds               ( 0L ),
-_minAmbient           ( 0,0,0,0 )
-{
-    // Create a SL atmosphere (the main SL object).
-    // TODO: plug in the username + license key.
-    _atmosphere = new ::SilverLining::Atmosphere(
-        options.user()->c_str(),
-        options.licenseCode()->c_str() );
-}
-
-SilverLiningContext::~SilverLiningContext()
-{
-    if ( _atmosphere )
-        delete _atmosphere;
-
-    OE_INFO << LC << "Destroyed\n";
-}
-
-void
-SilverLiningContext::setLight(osg::Light* light)
-{
-    _light = light;
-}
-
-void
-SilverLiningContext::setSRS(const osgEarth::SpatialReference* srs)
-{
-    _srs = srs;
-}
-
-void
-SilverLiningContext::setMinimumAmbient(const osg::Vec4f& value)
-{
-    _minAmbient = value;
-}
-
-void
-SilverLiningContext::initialize(osg::RenderInfo& renderInfo)
-{
-    if ( !_initAttempted && !_initFailed )
-    {
-        // lock/double-check:
-        Threading::ScopedMutexLock excl(_initMutex);
-        if ( !_initAttempted && !_initFailed )
-        {
-            _initAttempted = true;
-
-            // constant random seed ensures consistent clouds across windows
-            // TODO: replace this with something else since this is global! -gw
-            ::srand(1234);
-
-            int result = _atmosphere->Initialize(
-                ::SilverLining::Atmosphere::OPENGL,
-                _options.resourcePath()->c_str(),
-                true,
-                0 );
-
-            if ( result != ::SilverLining::Atmosphere::E_NOERROR )
-            {
-                _initFailed = true;
-                OE_WARN << LC << "SilverLining failed to initialize: " << result << std::endl;
-            }
-            else
-            {
-                OE_INFO << LC << "SilverLining initialized OK!" << std::endl;
-
-                // Defaults for a projected terrain. ECEF terrain vectors are set
-                // in updateLocation().
-                _atmosphere->SetUpVector( 0.0, 0.0, 1.0 );
-                _atmosphere->SetRightVector( 1.0, 0.0, 0.0 );
-
-#if 0 // todo: review this
-                _maxAmbientLightingAlt = 
-                    _atmosphere->GetConfigOptionDouble("atmosphere-height");
-#endif
-
-                if ( _options.drawClouds() == true )
-                {
-                    OE_INFO << LC << "Initializing clouds\n";
-                    setupClouds();
-                }
-            }
-        }
-    }
-}
-
-void
-SilverLiningContext::setupClouds()
-{
-    _clouds = ::SilverLining::CloudLayerFactory::Create( CUMULUS_CONGESTUS );
-    _clouds->SetIsInfinite( true );
-    _clouds->SetFadeTowardEdges(true);
-    _clouds->SetBaseAltitude( 2000 );
-    _clouds->SetThickness( 200 );
-    _clouds->SetBaseLength( 100000 );
-    _clouds->SetBaseWidth( 100000 );
-    _clouds->SetDensity( 0.6 );
-    _clouds->SetAlpha( 0.8 );
-
-    _clouds->SeedClouds( *_atmosphere );
-    _clouds->GenerateShadowMaps( false );
-    
-    _clouds->SetLayerPosition(0, 0);
-
-    _atmosphere->GetConditions()->AddCloudLayer( _clouds );
-}
-
-void
-SilverLiningContext::updateLight()
-{
-    if ( !ready() || !_light.valid() || !_srs.valid() )
-        return;
-
-    float ra, ga, ba, rd, gd, bd, x, y, z;
-
-    // Clamp the camera's altitude while fetching the colors so the
-    // lighting's ambient component doesn't fade to black at high altitude.
-    ::SilverLining::Location savedLoc = _atmosphere->GetConditions()->GetLocation();
-    ::SilverLining::Location clampedLoc = savedLoc;
-    if ( _maxAmbientLightingAlt > 0.0 )
-    {
-        clampedLoc.SetAltitude( std::min(clampedLoc.GetAltitude(), _maxAmbientLightingAlt) );
-        _atmosphere->GetConditions()->SetLocation( clampedLoc );
-    }
-
-    _atmosphere->GetAmbientColor( &ra, &ga, &ba );
-    _atmosphere->GetSunColor( &rd, &gd, &bd );
-
-    // Restore the actual altitude.
-    if ( _maxAmbientLightingAlt > 0.0 )
-    {
-        _atmosphere->GetConditions()->SetLocation( savedLoc );
-    }
-
-    if ( _srs->isGeographic() )
-    {
-        _atmosphere->GetSunPositionGeographic( &x, &y, &z );
-    }
-    else
-    {
-        _atmosphere->GetSunPosition(&x, &y, &z);
-    }
-
-    osg::Vec3 direction(x, y, z);
-    direction.normalize();
-
-    osg::Vec4 ambient(
-        osg::clampAbove(ra, _minAmbient.r()),
-        osg::clampAbove(ba, _minAmbient.g()),
-        osg::clampAbove(ga, _minAmbient.b()),
-        1.0);
-
-    _light->setAmbient( ambient );
-    _light->setDiffuse( osg::Vec4(rd, gd, bd, 1.0f) );
-    _light->setPosition( osg::Vec4(direction, 0.0f) ); //w=0 means "at infinity"
-}
-
-void
-SilverLiningContext::updateLocation()
-{
-    if ( !ready() || !_srs.valid() )
-        return;
-
-    if ( _srs->isGeographic() )
-    {
-        // Get new local orientation
-        osg::Vec3d up = _cameraPos;
-        up.normalize();
-        osg::Vec3d north = osg::Vec3d(0, 1, 0);
-        osg::Vec3d east = north ^ up;
-
-        // Check for edge case of north or south pole
-        if (east.length2() == 0)
-        {
-            east = osg::Vec3d(1, 0, 0);
-        }
-
-        east.normalize();
-
-        _atmosphere->SetUpVector(up.x(), up.y(), up.z());
-        _atmosphere->SetRightVector(east.x(), east.y(), east.z());
-
-        // Get new lat / lon / altitude
-        osg::Vec3d latLonAlt;
-        _srs->transformFromWorld(_cameraPos, latLonAlt);
-
-        ::SilverLining::Location loc;
-        loc.SetAltitude ( latLonAlt.z() );
-        loc.SetLongitude( latLonAlt.x() ); //osg::DegreesToRadians(latLonAlt.x()) );
-        loc.SetLatitude ( latLonAlt.y() ); //osg::DegreesToRadians(latLonAlt.y()) );
-
-        _atmosphere->GetConditions()->SetLocation( loc );
-
-#if 0
-        if ( _clouds )
-        {
-#if 1 //TODO: figure out why we need to call this a couple times before
-      //      it takes effect. -gw
-            static int c = 2;
-            if ( c > 0 ) {
-                --c;
-                _clouds->SetLayerPosition(0, 0);
-            }
-        }
-#endif
-#endif
-    }
-}
diff --git a/src/osgEarthDrivers/sky_silverlining/SilverLiningDriver.cpp b/src/osgEarthDrivers/sky_silverlining/SilverLiningDriver.cpp
index 1005bb5..63912d5 100644
--- a/src/osgEarthDrivers/sky_silverlining/SilverLiningDriver.cpp
+++ b/src/osgEarthDrivers/sky_silverlining/SilverLiningDriver.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -16,67 +16,109 @@
  * You should have received a copy of the GNU Lesser General Public License
  * along with this program.  If not, see <http://www.gnu.org/licenses/>
  */
-#include "SilverLiningOptions"
-#include "SilverLiningNode"
-#include <osgEarth/MapNode>
-#include <osgEarthUtil/Sky>
+#include <osgEarthSilverLining/SilverLiningOptions>
+#include <osgEarthSilverLining/SilverLiningNode>
 #include <osgDB/FileNameUtils>
+#include <osgEarth/Map>
+#include <osgEarth/MapNode>
+#include <osgEarthUtil/Controls>
+#include <osgEarthUtil/ExampleResources>
 
-#define LC "[SilverLiningDriver] "
+#define LC "[SilverLiningExtension] "
+
+using namespace osgEarth::Util;
+namespace ui = osgEarth::Util::Controls;
 
 namespace osgEarth { namespace SilverLining
 {
-    class SilverLiningDriver : public osgEarth::Util::SkyDriver
+    class SilverLiningExtension : public Extension,
+                                  public ExtensionInterface<MapNode>,
+                                  public ExtensionInterface<osg::View>,
+                                  public ExtensionInterface<ui::Control>,
+                                  public SilverLiningOptions,
+                                  public SkyNodeFactory
     {
     public:
-        SilverLiningDriver()
-        {
-            supportsExtension(
-                "osgearth_sky_silverlining",
-                "osgEarth SilverLining Plugin" );
-        }
+        META_Object(osgearth_sky_silverlining, SilverLiningExtension);
+
+        // CTORs
+        SilverLiningExtension() { }
+
+        SilverLiningExtension(const ConfigOptions& options) :
+            SilverLiningOptions(options) { }
+
+    public: // Extension
 
-        const char* className()
+        const ConfigOptions& getConfigOptions() const { return *this; }
+
+
+    public: // ExtensionInterface<MapNode>
+
+        bool connect(MapNode* mapNode)
         {
-            return "osgEarth SilverLining Plugin";
+            _skynode = createSkyNode(mapNode->getMap()->getProfile());
+            osgEarth::insertParent(_skynode.get(), mapNode);
+            return true;
         }
 
-        ReadResult readNode(const std::string& file_name, const osgDB::Options* options) const
+        bool disconnect(MapNode* mapNode)
         {
-            if ( !acceptsExtension(osgDB::getLowerCaseFileExtension( file_name )))
-                return ReadResult::FILE_NOT_HANDLED;
+            //todo
+            return true;
+        }
 
-            SilverLiningOptions slOptions = getSkyOptions(options);
+    public: // ExtensionInterface<osg::View>
 
-            // if the Resource Path isn't set, attempt to set it from 
-            // the SL environment variable.
-            if ( !slOptions.resourcePath().isSet() )
+        bool connect(osg::View* view)
+        {
+            if (view && _skynode.valid())
             {
-                const char* ev = ::getenv("SILVERLINING_PATH");
-                if ( ev )
-                {
-                    slOptions.resourcePath() = osgDB::concatPaths(
-                        std::string(ev),
-                        "Resources" );
-                }
-                else
-                {
-                    OE_WARN << LC
-                        << "No resource path! SilverLining might not initialize properly. "
-                        << "Consider setting the SILVERLINING_PATH environment variable."
-                        << std::endl;
-                }
+                _skynode->attach(view, 0);
             }
+            return true;
+        }
 
-            osgEarth::MapNode* mapnode = getMapNode(options);
-            const Map* map = mapnode ? mapnode->getMap() : 0L;
-            return new SilverLiningNode( map, slOptions );
+        bool disconnect(osg::View* view)
+        {
+            //todo
+            return true;
         }
 
-    protected:
-        virtual ~SilverLiningDriver() { }
-    };
 
-    REGISTER_OSGPLUGIN(osgearth_sky_silverlining, SilverLiningDriver)
+    public: // ExtensionInterface<Control>
+
+        bool connect(ui::Control* control)
+        {
+            ui::Container* container = dynamic_cast<ui::Container*>(control);
+            if (container)
+                container->addControl(SkyControlFactory::create(_skynode.get()));
+            return true;
+        }
+
+        bool disconnect(ui::Control* control)
+        {
+            //todo
+            return false;
+        }
+
+    public: // SkyNodeFactory
+
+        SkyNode* createSkyNode(const Profile* profile) {
+            return new SilverLiningNode(profile->getSRS(), *this);
+        }
+
+
+    protected: // Object
+
+        SilverLiningExtension(const SilverLiningExtension& rhs, const osg::CopyOp& op) { }
+
+        // DTOR
+        virtual ~SilverLiningExtension() { }
+
+
+    private:
+        osg::ref_ptr<SkyNode> _skynode;
+    };
 
-} } // namespace osgEarth::Drivers::SilverLining
+    REGISTER_OSGEARTH_EXTENSION(osgearth_sky_silverlining, SilverLiningExtension)
+} }
diff --git a/src/osgEarthDrivers/sky_silverlining/SilverLiningNode b/src/osgEarthDrivers/sky_silverlining/SilverLiningNode
deleted file mode 100644
index 3f697e4..0000000
--- a/src/osgEarthDrivers/sky_silverlining/SilverLiningNode
+++ /dev/null
@@ -1,69 +0,0 @@
-/* -*-c++-*- */
-/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
- * http://osgearth.org
- *
- * osgEarth is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>
- */
-
-#include "SilverLiningOptions"
-#include <osgEarthUtil/Sky>
-#include <osgEarth/Map>
-#include <osgEarth/PhongLightingEffect>
-#include <osg/Light>
-#include <osg/LightSource>
-
-namespace osgEarth { namespace SilverLining
-{
-    class SilverLiningContext;
-
-    /**
-     * Node that roots the silverlining adapter.
-     */
-    class SilverLiningNode : public osgEarth::Util::SkyNode
-    {
-    public:
-        SilverLiningNode(
-            const osgEarth::Map*       map,
-            const SilverLiningOptions& options );
-
-    public: // SkyNode
-
-        osg::Light* getSunLight() { return _light.get(); }
-
-        void attach(osg::View* view, int lightNum);
-
-        // callbacks from base class.
-        void onSetDateTime();
-        void onSetMinimumAmbient();
-
-    public: // osg::Node
-
-        void traverse(osg::NodeVisitor&);
-
-    protected:
-        virtual ~SilverLiningNode();
-
-        osg::ref_ptr<SilverLiningContext> _SL;
-		osg::ref_ptr<osg::Geode> _geode;
-        osg::ref_ptr<osg::LightSource> _lightSource;
-        osg::Drawable* _skyDrawable;
-		osg::ref_ptr<osg::Drawable> _cloudsDrawable;
-        osg::ref_ptr<osg::Light> _light;
-		double _lastAltitude;
-		const SilverLiningOptions _options;
-        osg::ref_ptr<osgEarth::PhongLightingEffect> _lighting;
-    };
-
-} } // namespace osgEarth::SilverLining
diff --git a/src/osgEarthDrivers/sky_silverlining/SilverLiningNode.cpp b/src/osgEarthDrivers/sky_silverlining/SilverLiningNode.cpp
deleted file mode 100644
index 383f076..0000000
--- a/src/osgEarthDrivers/sky_silverlining/SilverLiningNode.cpp
+++ /dev/null
@@ -1,176 +0,0 @@
-/* -*-c++-*- */
-/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
- * http://osgearth.org
- *
- * osgEarth is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>
- */
-#include <SilverLining.h>
-
-#include "SilverLiningNode"
-#include "SilverLiningContext"
-#include "SilverLiningSkyDrawable"
-#include "SilverLiningCloudsDrawable"
-
-#include <osg/Light>
-#include <osg/LightSource>
-#include <osgEarth/CullingUtils>
-
-#undef  LC
-#define LC "[SilverLiningNode] "
-
-using namespace osgEarth::SilverLining;
-
-SilverLiningNode::SilverLiningNode(const osgEarth::Map*       map,
-                                   const SilverLiningOptions& options) :
-_options     (options),
-_lastAltitude(DBL_MAX)
-{
-    // Create a new Light for the Sun.
-    _light = new osg::Light();
-    _light->setLightNum( 0 );
-    _light->setDiffuse( osg::Vec4(1,1,1,1) );
-    _light->setAmbient( osg::Vec4(0.2f, 0.2f, 0.2f, 1) );
-    _light->setPosition( osg::Vec4(1, 0, 0, 0) ); // w=0 means infinity
-    _light->setDirection( osg::Vec3(-1,0,0) );
-
-    _lightSource = new osg::LightSource();
-    _lightSource->setLight( _light.get() );
-    _lightSource->setReferenceFrame(osg::LightSource::RELATIVE_RF);
-
-    // The main silver lining data:
-    _SL = new SilverLiningContext( options );
-    _SL->setLight( _light.get() );
-    _SL->setSRS  ( map->getSRS() );
-
-    // Geode to hold each of the SL drawables:
-    _geode = new osg::Geode();
-    _geode->setCullingActive( false );
-
-    // Draws the sky before everything else
-    _skyDrawable = new SkyDrawable( _SL.get() );
-    _skyDrawable->getOrCreateStateSet()->setRenderBinDetails( -99, "RenderBin" );
-    _geode->addDrawable( _skyDrawable );
-
-    // Clouds draw after everything else
-    _cloudsDrawable = new CloudsDrawable( _SL.get() );
-    _cloudsDrawable->getOrCreateStateSet()->setRenderBinDetails( 99, "DepthSortedBin" );
-    _geode->addDrawable( _cloudsDrawable.get() );
-
-    // scene lighting
-    osg::StateSet* stateset = this->getOrCreateStateSet();
-    _lighting = new PhongLightingEffect();
-    _lighting->setCreateLightingUniform( false );
-    _lighting->attach( stateset );
-
-    // ensure it's depth sorted and draws after the terrain
-    //stateset->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
-    //getOrCreateStateSet()->setRenderBinDetails( 100, "DepthSortedBin" );
-
-    // SL requires an update pass.
-    ADJUST_UPDATE_TRAV_COUNT(this, +1);
-
-    // initialize date/time
-    onSetDateTime();
-}
-
-
-SilverLiningNode::~SilverLiningNode()
-{
-    if ( _lighting.valid() )
-        _lighting->detach();
-}
-
-void
-SilverLiningNode::attach(osg::View* view, int lightNum)
-{
-    _light->setLightNum( lightNum );
-    view->setLight( _light.get() );
-    view->setLightingMode( osg::View::SKY_LIGHT );
-}
-
-void
-SilverLiningNode::onSetDateTime()
-{
-    // set the SL local time to UTC/epoch.
-    ::SilverLining::LocalTime utcTime;
-    utcTime.SetFromEpochSeconds( getDateTime().asTimeStamp() );
-    _SL->getAtmosphere()->GetConditions()->SetTime( utcTime );
-}
-
-void
-SilverLiningNode::onSetMinimumAmbient()
-{
-    _SL->setMinimumAmbient( getMinimumAmbient() );
-}
-
-void
-SilverLiningNode::traverse(osg::NodeVisitor& nv)
-{
-    if ( _SL && _SL->ready() )
-    {
-        if ( nv.getVisitorType() == nv.UPDATE_VISITOR )
-        {
-			int frameNumber = nv.getFrameStamp()->getFrameNumber();
-            _skyDrawable->dirtyBound();
-
-            if( _cloudsDrawable )
-            {
-                if ( _lastAltitude <= *_options.cloudsMaxAltitude() )
-                {
-                    if ( _cloudsDrawable->getNumParents() == 0 )
-                        _geode->addDrawable( _cloudsDrawable.get() );
-
-                    _cloudsDrawable->dirtyBound();
-                }
-                else
-                {
-                    if ( _cloudsDrawable->getNumParents() > 0 )
-                        _geode->removeDrawable( _cloudsDrawable.get() );
-                }
-            }
-        }
-
-        else if ( nv.getVisitorType() == nv.CULL_VISITOR )
-        {
-
-            // TODO: make this multi-camera safe
-            _SL->setCameraPosition( nv.getEyePoint() );
-            osgUtil::CullVisitor* cv = Culling::asCullVisitor(nv);
-            _SL->getAtmosphere()->SetCameraMatrix( cv->getModelViewMatrix()->ptr() );
-            _SL->getAtmosphere()->SetProjectionMatrix( cv->getProjectionMatrix()->ptr() );
-
-			_lastAltitude = _SL->getSRS()->isGeographic() ?
-				cv->getEyePoint().length() - _SL->getSRS()->getEllipsoid()->getRadiusEquator() :
-				cv->getEyePoint().z();
-
-            _SL->updateLocation();
-            _SL->updateLight();
-            _SL->getAtmosphere()->UpdateSkyAndClouds();
-			_SL->getAtmosphere()->CullObjects();
-        }
-    }
-
-    osgEarth::Util::SkyNode::traverse( nv );
-
-    if ( _geode.valid() )
-    {
-        _geode->accept(nv);
-    }
-
-    if ( _lightSource.valid() )
-    {
-        _lightSource->accept(nv);
-    }
-}
diff --git a/src/osgEarthDrivers/sky_silverlining/SilverLiningOptions b/src/osgEarthDrivers/sky_silverlining/SilverLiningOptions
deleted file mode 100644
index c469296..0000000
--- a/src/osgEarthDrivers/sky_silverlining/SilverLiningOptions
+++ /dev/null
@@ -1,101 +0,0 @@
-/* -*-c++-*- */
-/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
- * http://osgearth.org
- *
- * osgEarth is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>
- */
-#ifndef OSGEARTH_DRIVER_SILVERLINING_OPTIONS
-#define OSGEARTH_DRIVER_SILVERLINING_OPTIONS 1
-
-#include <osgEarthUtil/Sky>
-
-namespace osgEarth { namespace SilverLining
-{
-    /**
-     * Options for creating a SilverLining environment node
-     */
-    class SilverLiningOptions : public osgEarth::Util::SkyOptions
-    {
-    public:
-        SilverLiningOptions(const osgEarth::Util::SkyOptions& options =osgEarth::Util::SkyOptions()) :
-          osgEarth::Util::SkyOptions(options),
-          _drawClouds(false),
-          _cloudsMaxAltitude(20000)
-        {
-            setDriver( "silverlining" );
-            fromConfig( _conf );
-        }
-        virtual ~SilverLiningOptions() { }
-
-    public: // properties
-
-        /* User name for license activation */
-        optional<std::string>& user() { return _user; }
-        const optional<std::string>& user() const { return _user; }
-
-        /* License code string */
-        optional<std::string>& licenseCode() { return _licenseCode; }
-        const optional<std::string>& licenseCode() const { return _licenseCode; }
-
-        /* SilverLining resource path */
-        optional<std::string>& resourcePath() { return _resourcePath; }
-        const optional<std::string>& resourcePath() const { return _resourcePath; }
-
-        /* Whether to draw clouds */
-        optional<bool>& drawClouds() { return _drawClouds; }
-        const optional<bool>& drawClouds() const { return _drawClouds; }
-
-		/* Max altitude at which to draw/update clouds */
-		optional<double>& cloudsMaxAltitude() { return _cloudsMaxAltitude; }
-		const optional<double>& cloudsMaxAltitude() const { return _cloudsMaxAltitude; }
-
-    public:
-        osgEarth::Config getConfig() const {
-            osgEarth::Config conf = osgEarth::Util::SkyOptions::getConfig();
-            conf.addIfSet("user", _user);
-            conf.addIfSet("license_code", _licenseCode);
-            conf.addIfSet("resource_path", _resourcePath);
-            conf.addIfSet("clouds", _drawClouds);
-			conf.addIfSet("clouds_max_altitude", _cloudsMaxAltitude);
-            return conf;
-        }
-
-    protected:
-        void mergeConfig( const osgEarth::Config& conf ) {
-            osgEarth::Util::SkyOptions::mergeConfig( conf );
-            fromConfig(conf);
-        }
-
-    private:
-        void fromConfig( const osgEarth::Config& conf ) {
-            conf.getIfSet("user", _user);
-            conf.getIfSet("license_code", _licenseCode);
-            conf.getIfSet("resource_path", _resourcePath);
-            conf.getIfSet("clouds", _drawClouds);
-			conf.getIfSet("clouds_max_altitude", _cloudsMaxAltitude);
-        }
-
-        osgEarth::optional<std::string> _user;
-        osgEarth::optional<std::string> _licenseCode;
-        osgEarth::optional<std::string> _resourcePath;
-        osgEarth::optional<bool>        _drawClouds;
-		osgEarth::optional<double>      _cloudsMaxAltitude;
-		int                             _lastCullFrameNumber;
-    };
-
-} } // namespace osgEarth::SilverLiningPlugin
-
-#endif // OSGEARTH_DRIVER_SILVERLINING_OPTIONS
-
diff --git a/src/osgEarthDrivers/sky_silverlining/SilverLiningSkyDrawable b/src/osgEarthDrivers/sky_silverlining/SilverLiningSkyDrawable
deleted file mode 100644
index 5b68270..0000000
--- a/src/osgEarthDrivers/sky_silverlining/SilverLiningSkyDrawable
+++ /dev/null
@@ -1,56 +0,0 @@
-/* -*-c++-*- */
-/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
- * http://osgearth.org
- *
- * osgEarth is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>
- */
-#include <osg/Drawable>
-#include <osg/RenderInfo>
-#include <osg/Version>
-
-namespace osgEarth { namespace SilverLining
-{
-    class SilverLiningContext;
-
-    /**
-     * Custom drawable for rendering the SilverLining effects
-     */
-    class SkyDrawable : public osg::Drawable
-    {
-    public:
-        SkyDrawable(SilverLiningContext* SL =0L);
-        META_Object(SilverLining, SkyDrawable);
-     
-    public: // osg::Drawable
-
-        // custom draw (called with an active GC)
-        void drawImplementation(osg::RenderInfo& ri) const;
-
-        // custom bounds computation
-#if OSG_VERSION_GREATER_THAN(3,3,1)
-        osg::BoundingBox computeBoundingBox() const;
-#else
-        osg::BoundingBox computeBound() const;
-#endif
-
-    protected:
-        virtual ~SkyDrawable() { }
-
-        osg::observer_ptr<SilverLiningContext> _SL;
-        
-        SkyDrawable(const SkyDrawable& copy, const osg::CopyOp& op=osg::CopyOp::SHALLOW_COPY) { }
-    };
-
-} } // namespace osgEarth::SilverLining
diff --git a/src/osgEarthDrivers/sky_silverlining/SilverLiningSkyDrawable.cpp b/src/osgEarthDrivers/sky_silverlining/SilverLiningSkyDrawable.cpp
deleted file mode 100644
index 201f618..0000000
--- a/src/osgEarthDrivers/sky_silverlining/SilverLiningSkyDrawable.cpp
+++ /dev/null
@@ -1,110 +0,0 @@
-/* -*-c++-*- */
-/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
- * http://osgearth.org
- *
- * osgEarth is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>
- */
-#include <SilverLining.h>
-#include "SilverLiningSkyDrawable"
-#include "SilverLiningContext"
-#include <osgEarth/SpatialReference>
-
-#define LC "[SilverLining:SkyDrawable] "
-
-using namespace osgEarth::SilverLining;
-
-
-SkyDrawable::SkyDrawable(SilverLiningContext* SL) :
-_SL( SL )
-{
-    // call this to ensure draw() gets called every frame.
-    setSupportsDisplayList( false );
-
-    // not MT-safe (camera updates, etc)
-    this->setDataVariance( osg::Object::DYNAMIC );
-}
-
-void
-SkyDrawable::drawImplementation(osg::RenderInfo& renderInfo) const
-{
-    osg::Camera* camera = renderInfo.getCurrentCamera();
-    if ( camera )
-    {
-        renderInfo.getState()->disableAllVertexArrays();
-        _SL->initialize( renderInfo );
-
-        double fovy, ar, znear, zfar;
-        _SL->setCamera(camera);
-
-        //renderInfo.getCurrentCamera()->setNearFarRatio(.00000001);
-
-        camera->getProjectionMatrixAsPerspective(fovy, ar, znear, zfar);
-        _SL->setSkyBoxSize( zfar < 100000.0 ? zfar : 100000.0 );
-
-        _SL->getAtmosphere()->DrawSky(
-            true, 
-            _SL->getSRS()->isGeographic(),
-            _SL->getSkyBoxSize(),
-            true,
-            false );
-
-        renderInfo.getState()->dirtyAllVertexArrays();
-    }
-}
-
-osg::BoundingBox
-#if OSG_VERSION_GREATER_THAN(3,3,1)
-SkyDrawable::computeBoundingBox() const
-#else
-SkyDrawable::computeBound() const
-#endif
-{
-    osg::BoundingBox skyBoundBox;
-    if ( !_SL->ready() )
-        return skyBoundBox;
-    
-    ::SilverLining::Atmosphere* atmosphere = _SL->getAtmosphere();
-    double skyboxSize = _SL->getSkyBoxSize();
-    if ( skyboxSize == 0.0 )
-        skyboxSize = 1000.0;
-    
-    osg::Vec3d radiusVec = osg::Vec3d(skyboxSize, skyboxSize, skyboxSize) * 0.5;
-    osg::Vec3d camPos = _SL->getCameraPosition();
-    if (_SL->getCamera())
-    {
-        osg::Vec3f eye, center, up;
-        _SL->getCamera()->getViewMatrixAsLookAt(eye, center, up);
-        camPos = osg::Vec3d(eye.x(), eye.y(), eye.z());
-    }
-
-    skyBoundBox.set( camPos-radiusVec, camPos+radiusVec );
-    
-    // this enables the "blue ring" around the earth when viewing from space.
-    bool hasLimb = atmosphere->GetConfigOptionBoolean("enable-atmosphere-from-space");
-    if ( hasLimb )
-    {
-        // Compute bounds of atmospheric limb centered at (0,0,0)
-        double earthRadius = atmosphere->GetConfigOptionDouble("earth-radius-meters");
-        double atmosphereHeight = earthRadius + atmosphere->GetConfigOptionDouble("atmosphere-height");
-        double atmosphereThickness = atmosphere->GetConfigOptionDouble("atmosphere-scale-height-meters") + earthRadius;
-        
-        osg::BoundingBox atmosphereBox;
-        osg::Vec3d atmMin(-atmosphereThickness, -atmosphereThickness, -atmosphereThickness);
-        osg::Vec3d atmMax(atmosphereThickness, atmosphereThickness, atmosphereThickness);
-        atmosphereBox.set( atmMin, atmMax );
-        skyBoundBox.expandBy( atmosphereBox );
-    }
-    return skyBoundBox;
-}
diff --git a/src/osgEarthDrivers/sky_simple/CMakeLists.txt b/src/osgEarthDrivers/sky_simple/CMakeLists.txt
index 4e7dd63..a79f212 100644
--- a/src/osgEarthDrivers/sky_simple/CMakeLists.txt
+++ b/src/osgEarthDrivers/sky_simple/CMakeLists.txt
@@ -27,7 +27,7 @@ configure_shaders(
     ${TARGET_GLSL} )
     
 set(TARGET_SRC 
-    SimpleSkyDriver.cpp
+    SimpleSkyExtension.cpp
     SimpleSkyNode.cpp
     ${SHADERS_CPP} )
 
diff --git a/src/osgEarthDrivers/sky_simple/SimpleSky.Atmosphere.frag.glsl b/src/osgEarthDrivers/sky_simple/SimpleSky.Atmosphere.frag.glsl
index 66a75d4..6092654 100644
--- a/src/osgEarthDrivers/sky_simple/SimpleSky.Atmosphere.frag.glsl
+++ b/src/osgEarthDrivers/sky_simple/SimpleSky.Atmosphere.frag.glsl
@@ -1,9 +1,9 @@
 #version $GLSL_VERSION_STR
 $GLSL_DEFAULT_PRECISION_FLOAT
 
-#pragma vp_entryPoint "atmos_fragment_main"
-#pragma vp_location   "fragment_coloring"
-#pragma vp_order      "0.8"
+#pragma vp_entryPoint atmos_fragment_main
+#pragma vp_location   fragment_coloring
+#pragma vp_order      0.8
 
 uniform vec3 atmos_v3LightDir; 
 
diff --git a/src/osgEarthDrivers/sky_simple/SimpleSky.Atmosphere.vert.glsl b/src/osgEarthDrivers/sky_simple/SimpleSky.Atmosphere.vert.glsl
index 57f59d4..b001807 100644
--- a/src/osgEarthDrivers/sky_simple/SimpleSky.Atmosphere.vert.glsl
+++ b/src/osgEarthDrivers/sky_simple/SimpleSky.Atmosphere.vert.glsl
@@ -1,9 +1,9 @@
 #version $GLSL_VERSION_STR
 $GLSL_DEFAULT_PRECISION_FLOAT
 
-#pragma vp_entryPoint "atmos_vertex_main"
-#pragma vp_location   "vertex_view"
-#pragma vp_order      "0.5"
+#pragma vp_entryPoint atmos_vertex_main
+#pragma vp_location   vertex_view
+#pragma vp_order      0.5
 
 // Atmospheric Scattering and Sun Shaders
 // Adapted from code that is Copyright (c) 2004 Sean ONeil
diff --git a/src/osgEarthDrivers/sky_simple/SimpleSky.Ground.ONeil.frag.glsl b/src/osgEarthDrivers/sky_simple/SimpleSky.Ground.ONeil.frag.glsl
index b7fba37..4c8635a 100644
--- a/src/osgEarthDrivers/sky_simple/SimpleSky.Ground.ONeil.frag.glsl
+++ b/src/osgEarthDrivers/sky_simple/SimpleSky.Ground.ONeil.frag.glsl
@@ -1,9 +1,9 @@
 #version $GLSL_VERSION_STR
 $GLSL_DEFAULT_PRECISION_FLOAT
 
-#pragma vp_entryPoint "atmos_fragment_main"
-#pragma vp_location   "fragment_lighting"
-#pragma vp_order      "0.8"
+#pragma vp_entryPoint atmos_fragment_main
+#pragma vp_location   fragment_lighting
+#pragma vp_order      0.8
 
 uniform bool oe_mode_GL_LIGHTING; 
 uniform float atmos_exposure;   // scene exposure (ground level)
@@ -14,7 +14,7 @@ varying vec3 atmos_up;          // earth up vector at fragment (in view coords)
 varying float atmos_space;      // camera altitude (0=ground, 1=atmos outer radius)
 varying vec3 atmos_vert; 
         
-vec3 oe_global_Normal;          // surface normal (from osgEarth)
+vec3 vp_Normal;          // surface normal (from osgEarth)
 
 void atmos_fragment_main(inout vec4 color) 
 { 
@@ -26,20 +26,20 @@ void atmos_fragment_main(inout vec4 color)
     vec3 ambient = gl_LightSource[0].ambient.rgb;
     float minAmbient = ambient.r;
 
-    vec3 N = normalize(oe_global_Normal); 
+    vec3 N = normalize(vp_Normal); 
     vec3 L = normalize(atmos_lightDir); //normalize(gl_LightSource[0].position.xyz); 
     vec3 U = normalize(atmos_up); 
 
     const float maxAmbient = 0.5;
     float daytime = max(0.0, dot(U,L));
-    float brightness = clamp(daytime, minAmbient, maxAmbient);
+    float ambientLightLevel = clamp(daytime, minAmbient, maxAmbient);
 
     float NdotL = max(dot(N,L), 0.0);
 
     const float lowAlt  = 1.0;
-    const float highAlt = 4.0;
+    const float highAlt = 14.0;
     float altitudeInfluence = 1.0 - clamp( (atmos_space-lowAlt)/(highAlt-lowAlt), 0.0, 1.0);
-    float useNormals = altitudeInfluence * (1.0-brightness);
+    float useNormals = altitudeInfluence * (1.0-ambientLightLevel);
 
     // try to brighten up surfaces the sun is shining on
     float overExposure = 1.0;
@@ -50,7 +50,7 @@ void atmos_fragment_main(inout vec4 color)
 
     if (NdotL > 0.0 ) { 
         vec3 V = normalize(atmos_vert); 
-        vec3 H = normalize(L-V); 
+        vec3 H = reflect(-L, N);
         float HdotN = max(dot(H,N), 0.0); 
         float shine = clamp(gl_FrontMaterial.shininess, 1.0, 128.0); 
         sceneColor += gl_FrontLightProduct[0].specular * pow(HdotN, shine); 
diff --git a/src/osgEarthDrivers/sky_simple/SimpleSky.Ground.ONeil.vert.glsl b/src/osgEarthDrivers/sky_simple/SimpleSky.Ground.ONeil.vert.glsl
index 08ef66c..a1acf31 100644
--- a/src/osgEarthDrivers/sky_simple/SimpleSky.Ground.ONeil.vert.glsl
+++ b/src/osgEarthDrivers/sky_simple/SimpleSky.Ground.ONeil.vert.glsl
@@ -1,9 +1,9 @@
 #version $GLSL_VERSION_STR
 $GLSL_DEFAULT_PRECISION_FLOAT
 
-#pragma vp_entryPoint "atmos_vertex_main"
-#pragma vp_location   "vertex_view"
-#pragma vp_order      "0.5"
+#pragma vp_entryPoint atmos_vertex_main
+#pragma vp_location   vertex_view
+#pragma vp_order      0.5
 
 uniform bool oe_mode_GL_LIGHTING; 
 
@@ -36,7 +36,7 @@ varying vec3 atmos_up;             // earth up vector at vertex location (not th
 varying float atmos_space;         // [0..1]: camera: 0=inner radius (ground); 1.0=outer radius
 varying vec3 atmos_vert; 
 
-vec3 oe_global_Normal;             // surface normal (from osgEarth)
+vec3 vp_Normal;             // surface normal (from osgEarth)
 
 float atmos_scale(float fCos) 	
 { 
@@ -68,7 +68,7 @@ void atmos_GroundFromSpace(in vec4 vertexVIEW)
     vec3 v3Start = v3Ray * fNear; 			
     fFar -= fNear; 
     float fDepth = exp((atmos_fInnerRadius - atmos_fOuterRadius) / atmos_fScaleDepth);
-    float fCameraAngle = dot(-v3Ray, normal); 
+    float fCameraAngle = dot(-v3Ray, normal);  // try max(0, ...) to get rid of yellowing building tops
     float fLightAngle = dot(atmos_lightDir, normal); 
     float fCameraScale = atmos_scale(fCameraAngle); 
     float fLightScale = atmos_scale(fLightAngle); 
diff --git a/src/osgEarthDrivers/sky_simple/SimpleSky.Stars.frag.glsl b/src/osgEarthDrivers/sky_simple/SimpleSky.Stars.frag.glsl
index 183d4d7..4fe4b8e 100644
--- a/src/osgEarthDrivers/sky_simple/SimpleSky.Stars.frag.glsl
+++ b/src/osgEarthDrivers/sky_simple/SimpleSky.Stars.frag.glsl
@@ -1,7 +1,7 @@
-#version 120
+#version $GLSL_VERSION_STR
 
-varying float visibility; 
-varying vec4 osg_FrontColor; 
+in float visibility; 
+in vec4 osg_FrontColor; 
 
 void main( void ) 
 { 
diff --git a/src/osgEarthDrivers/sky_simple/SimpleSky.Stars.vert.glsl b/src/osgEarthDrivers/sky_simple/SimpleSky.Stars.vert.glsl
index 74a8ba0..3652426 100644
--- a/src/osgEarthDrivers/sky_simple/SimpleSky.Stars.vert.glsl
+++ b/src/osgEarthDrivers/sky_simple/SimpleSky.Stars.vert.glsl
@@ -1,9 +1,9 @@
-#version 120
+#version $GLSL_VERSION_STR
 
 uniform vec3 atmos_v3LightDir; 
 uniform mat4 osg_ViewMatrixInverse; 
-varying float visibility; 
-varying vec4 osg_FrontColor; 
+out float visibility; 
+out vec4 osg_FrontColor; 
 
 float remap( float val, float vmin, float vmax, float r0, float r1 ) 
 { 
diff --git a/src/osgEarthDrivers/sky_simple/SimpleSkyDriver.cpp b/src/osgEarthDrivers/sky_simple/SimpleSkyDriver.cpp
deleted file mode 100644
index d363128..0000000
--- a/src/osgEarthDrivers/sky_simple/SimpleSkyDriver.cpp
+++ /dev/null
@@ -1,63 +0,0 @@
-/* -*-c++-*- */
-/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
- * http://osgearth.org
- *
- * osgEarth is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>
- */
-#include "SimpleSkyOptions"
-#include "SimpleSkyNode"
-#include <osgDB/FileNameUtils>
-#include <osgEarth/Map>
-#include <osgEarth/MapNode>
-
-#define LC "[SimpleSkyDriver] "
-
-using namespace osgEarth::Util;
-
-namespace osgEarth { namespace Drivers { namespace SimpleSky
-{
-    class SimpleSkyDriver : public SkyDriver
-    {
-    public:
-        SimpleSkyDriver()
-        {
-            supportsExtension(
-                "osgearth_sky_simple",
-                "osgEarth Simple Sky Plugin" );
-        }
-
-        const char* className()
-        {
-            return "osgEarth Simple Sky Plugin";
-        }
-
-        ReadResult readNode(const std::string& file_name, const osgDB::Options* options) const
-        {
-            if ( !acceptsExtension(osgDB::getLowerCaseFileExtension( file_name )))
-                return ReadResult::FILE_NOT_HANDLED;
-
-            MapNode* mapNode = getMapNode(options);
-            const SpatialReference* srs = mapNode ? mapNode->getMapSRS() : 0L;
-
-            return new SimpleSkyNode(srs, getSkyOptions(options));
-        }
-
-    protected:
-        virtual ~SimpleSkyDriver() { }
-    };
-
-    REGISTER_OSGPLUGIN(osgearth_sky_simple, SimpleSkyDriver)
-
-} } } // namespace osgEarth::Drivers::SimpleSky
diff --git a/src/osgEarthDrivers/sky_simple/SimpleSkyExtension.cpp b/src/osgEarthDrivers/sky_simple/SimpleSkyExtension.cpp
new file mode 100644
index 0000000..e8bb059
--- /dev/null
+++ b/src/osgEarthDrivers/sky_simple/SimpleSkyExtension.cpp
@@ -0,0 +1,124 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+ * Copyright 2016 Pelican Mapping
+ * http://osgearth.org
+ *
+ * osgEarth is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ */
+#include "SimpleSkyOptions"
+#include "SimpleSkyNode"
+#include <osgDB/FileNameUtils>
+#include <osgEarth/Map>
+#include <osgEarth/MapNode>
+#include <osgEarthUtil/Controls>
+#include <osgEarthUtil/ExampleResources>
+
+#define LC "[SimpleSkyDriver] "
+
+using namespace osgEarth::Util;
+namespace ui = osgEarth::Util::Controls;
+
+namespace osgEarth { namespace SimpleSky
+{
+    class SimpleSkyExtension : public Extension,
+                               public ExtensionInterface<MapNode>,
+                               public ExtensionInterface<osg::View>,
+                               public ExtensionInterface<ui::Control>,
+                               public SimpleSkyOptions,
+                               public SkyNodeFactory
+    {
+    public:
+        META_Object(osgearth_sky_simple, SimpleSkyExtension);
+
+        // CTORs
+        SimpleSkyExtension() { }
+
+        SimpleSkyExtension(const ConfigOptions& options) :
+            SimpleSkyOptions(options) { }
+
+    public: // Extension
+
+        const ConfigOptions& getConfigOptions() const { return *this; }
+
+
+    public: // ExtensionInterface<MapNode>
+
+        bool connect(MapNode* mapNode)
+        {
+            _skynode = createSkyNode(mapNode->getMap()->getProfile());
+            osgEarth::insertParent(_skynode.get(), mapNode);
+            return true;
+        }
+
+        bool disconnect(MapNode* mapNode)
+        {
+            //todo
+            return true;
+        }
+
+    public: // ExtensionInterface<osg::View>
+
+        bool connect(osg::View* view)
+        {
+            if (view && _skynode.valid())
+            {
+                _skynode->attach(view, 0);
+            }
+            return true;
+        }
+
+        bool disconnect(osg::View* view)
+        {
+            //todo
+            return true;
+        }
+
+
+    public: // ExtensionInterface<Control>
+
+        bool connect(ui::Control* control)
+        {
+            ui::Container* container = dynamic_cast<ui::Container*>(control);
+            if (container)
+                container->addControl(SkyControlFactory::create(_skynode.get()));
+            return true;
+        }
+
+        bool disconnect(ui::Control* control)
+        {
+            return true;
+        }
+
+    public: // SkyNodeFactory
+
+        SkyNode* createSkyNode(const Profile* profile) {
+            return new SimpleSkyNode(profile->getSRS(), *this);
+        }
+
+
+    protected: // Object
+
+        SimpleSkyExtension(const SimpleSkyExtension& rhs, const osg::CopyOp& op) { }
+
+        // DTOR
+        virtual ~SimpleSkyExtension() { }
+
+
+    private:
+        osg::ref_ptr<SkyNode> _skynode;
+    };
+
+    REGISTER_OSGEARTH_EXTENSION(osgearth_sky_simple, SimpleSkyExtension)
+
+} } // namespace osgEarth::SimpleSky
diff --git a/src/osgEarthDrivers/sky_simple/SimpleSkyNode b/src/osgEarthDrivers/sky_simple/SimpleSkyNode
index 88a59fa..8711e0f 100644
--- a/src/osgEarthDrivers/sky_simple/SimpleSkyNode
+++ b/src/osgEarthDrivers/sky_simple/SimpleSkyNode
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -28,7 +28,7 @@ namespace osg {
     class Light;
 }
 
-namespace osgEarth { namespace Drivers { namespace SimpleSky
+namespace osgEarth { namespace SimpleSky
 {
     using namespace osgEarth;
     using namespace osgEarth::Util;
@@ -57,6 +57,7 @@ namespace osgEarth { namespace Drivers { namespace SimpleSky
         void onSetSunVisible();
         void onSetMoonVisible();
         void onSetStarsVisible();
+        void onSetAtmosphereVisible();
         void onSetMinimumAmbient();
 
     public: // osg::Node
@@ -120,4 +121,4 @@ namespace osgEarth { namespace Drivers { namespace SimpleSky
         void setMoonPosition(const osg::Vec3d& pos);
     };
 
-} } } // namespace osgEarth::Drivers::SimpleSky
+} } // namespace osgEarth::SimpleSky
diff --git a/src/osgEarthDrivers/sky_simple/SimpleSkyNode.cpp b/src/osgEarthDrivers/sky_simple/SimpleSkyNode.cpp
index 13fb103..f68a0c1 100644
--- a/src/osgEarthDrivers/sky_simple/SimpleSkyNode.cpp
+++ b/src/osgEarthDrivers/sky_simple/SimpleSkyNode.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
@@ -59,7 +59,7 @@
 
 using namespace osgEarth;
 using namespace osgEarth::Util;
-using namespace osgEarth::Drivers::SimpleSky;
+using namespace osgEarth::SimpleSky;
 
 //---------------------------------------------------------------------------
 
@@ -237,7 +237,7 @@ SimpleSkyNode::initialize(const SpatialReference* srs)
     _cullContainer = new osg::Group();
     
     // set up the astronomical parameters:
-    _ellipsoidModel = srs->getEllipsoid();
+    _ellipsoidModel = srs ? srs->getEllipsoid() : new osg::EllipsoidModel();
     _innerRadius = osg::minimum(
         _ellipsoidModel->getRadiusPolar(),
         _ellipsoidModel->getRadiusEquator() );
@@ -411,6 +411,13 @@ SimpleSkyNode::onSetSunVisible()
 }
 
 void
+SimpleSkyNode::onSetAtmosphereVisible()
+{
+    if (_atmosphere.valid())
+        _atmosphere->setNodeMask( getAtmosphereVisible() ? ~0 : 0 );
+}
+
+void
 SimpleSkyNode::makeSceneLighting()
 {
     // installs the main uniforms and the shaders that will light the subgraph (terrain).
@@ -419,11 +426,12 @@ SimpleSkyNode::makeSceneLighting()
     VirtualProgram* vp = VirtualProgram::getOrCreate( stateset );
     vp->setName( "SimpleSky Scene Lighting" );
 
-    if (_options.atmosphericLighting() == true && !Registry::capabilities().isGLES() )
+    if (_options.atmosphericLighting() == true)// && !Registry::capabilities().isGLES() )
     {
         Shaders pkg;
         pkg.load( vp, pkg.Ground_ONeil_Vert );
         pkg.load( vp, pkg.Ground_ONeil_Frag );
+        OE_INFO << LC << "Using O'Neil atmospheric lighting\n";
     }
 
     else
@@ -431,6 +439,7 @@ SimpleSkyNode::makeSceneLighting()
         _phong = new PhongLightingEffect();
         _phong->setCreateLightingUniform( false );
         _phong->attach( stateset );
+        OE_INFO << LC << "Using Phong lighting\n";
     }
 
     // calculate and apply the uniforms:
@@ -655,7 +664,10 @@ SimpleSkyNode::makeMoon()
     }
 }
 
-SimpleSkyNode::StarData::StarData(std::stringstream &ss)
+SimpleSkyNode::StarData::StarData(std::stringstream &ss) :
+right_ascension(0.0),
+declination(0.0),
+magnitude(0.0)
 {
     std::getline( ss, name, ',' );
     std::string buff;
diff --git a/src/osgEarthDrivers/sky_simple/SimpleSkyOptions b/src/osgEarthDrivers/sky_simple/SimpleSkyOptions
index 8152540..00827f7 100644
--- a/src/osgEarthDrivers/sky_simple/SimpleSkyOptions
+++ b/src/osgEarthDrivers/sky_simple/SimpleSkyOptions
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -21,7 +21,7 @@
 
 #include <osgEarthUtil/Sky>
 
-namespace osgEarth { namespace Drivers { namespace SimpleSky
+namespace osgEarth { namespace SimpleSky
 {
     using namespace osgEarth;
     using namespace osgEarth::Util;
@@ -35,7 +35,7 @@ namespace osgEarth { namespace Drivers { namespace SimpleSky
         SimpleSkyOptions(const ConfigOptions& options =ConfigOptions()) :
           SkyOptions(options),
           _atmosphericLighting(true),
-          _exposure           (3.0f),
+          _exposure           (3.8f),
           _allowWireframe     (false)
         {
             setDriver( "simple" );
@@ -92,7 +92,7 @@ namespace osgEarth { namespace Drivers { namespace SimpleSky
         optional<bool>        _allowWireframe;
     };
 
-} } } // namespace osgEarth::Drivers::SimpleSky
+} } // namespace osgEarth::SimpleSky
 
 #endif // OSGEARTH_DRIVER_SIMPLE_SKY_OPTIONS
 
diff --git a/src/osgEarthDrivers/sky_simple/SimpleSkyShaders b/src/osgEarthDrivers/sky_simple/SimpleSkyShaders
index a6405fc..d2dad45 100644
--- a/src/osgEarthDrivers/sky_simple/SimpleSkyShaders
+++ b/src/osgEarthDrivers/sky_simple/SimpleSkyShaders
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -21,7 +21,7 @@
 
 #include <osgEarth/ShaderLoader>
 
-namespace osgEarth { namespace Drivers { namespace SimpleSky
+namespace osgEarth { namespace SimpleSky
 {
     struct Shaders : public osgEarth::ShaderPackage
 	{
@@ -40,6 +40,6 @@ namespace osgEarth { namespace Drivers { namespace SimpleSky
         std::string Sun_Frag;
 	};
 
-} } } // namespace osgEarth::Drivers::SimpleSky
+} } // namespace osgEarth::SimpleSky
 
 #endif //OSGEARTH_DRIVER_SIMPLE_SKY_SHADERS
\ No newline at end of file
diff --git a/src/osgEarthDrivers/sky_simple/SimpleSkyShaders.cpp.in b/src/osgEarthDrivers/sky_simple/SimpleSkyShaders.cpp.in
index c234184..39e3197 100644
--- a/src/osgEarthDrivers/sky_simple/SimpleSkyShaders.cpp.in
+++ b/src/osgEarthDrivers/sky_simple/SimpleSkyShaders.cpp.in
@@ -3,43 +3,43 @@
 #include <osgEarthDrivers/sky_simple/SimpleSkyShaders>
 
 
-using namespace osgEarth::Drivers::SimpleSky;
+using namespace osgEarth::SimpleSky;
 
 Shaders::Shaders()
 {
     Atmosphere_Vert = "SimpleSky.Atmosphere.vert.glsl";
-    _sources[Atmosphere_Vert] = OE_MULTILINE(@SimpleSky.Atmosphere.vert.glsl@);
+    _sources[Atmosphere_Vert] = "@SimpleSky.Atmosphere.vert.glsl@";
 
     Atmosphere_Frag = "SimpleSky.Atmosphere.frag.glsl";
-    _sources[Atmosphere_Frag] = OE_MULTILINE(@SimpleSky.Atmosphere.frag.glsl@);
+    _sources[Atmosphere_Frag] = "@SimpleSky.Atmosphere.frag.glsl@";
 
     Ground_ONeil_Vert = "SimpleSky.Ground.ONeil.vert.glsl";
-    _sources[Ground_ONeil_Vert] = OE_MULTILINE(@SimpleSky.Ground.ONeil.vert.glsl@);
+    _sources[Ground_ONeil_Vert] = "@SimpleSky.Ground.ONeil.vert.glsl@";
 
     Ground_ONeil_Frag = "SimpleSky.Ground.ONeil.frag.glsl";
-    _sources[Ground_ONeil_Frag] = OE_MULTILINE(@SimpleSky.Ground.ONeil.frag.glsl@);
+    _sources[Ground_ONeil_Frag] = "@SimpleSky.Ground.ONeil.frag.glsl@";
 
     Moon_Vert = "SimpleSky.Moon.vert.glsl";
-    _sources[Moon_Vert] = OE_MULTILINE(@SimpleSky.Moon.vert.glsl@);
+    _sources[Moon_Vert] = "@SimpleSky.Moon.vert.glsl@";
 
     Moon_Frag = "SimpleSky.Moon.frag.glsl";
-    _sources[Moon_Frag] = OE_MULTILINE(@SimpleSky.Moon.frag.glsl@);
+    _sources[Moon_Frag] = "@SimpleSky.Moon.frag.glsl@";
 
     Stars_Vert = "SimpleSky.Stars.vert.glsl";
-    _sources[Stars_Vert] = OE_MULTILINE(@SimpleSky.Stars.vert.glsl@);
+    _sources[Stars_Vert] = "@SimpleSky.Stars.vert.glsl@";
 
     Stars_Frag = "SimpleSky.Stars.frag.glsl";
-    _sources[Stars_Frag] = OE_MULTILINE(@SimpleSky.Stars.frag.glsl@);
+    _sources[Stars_Frag] = "@SimpleSky.Stars.frag.glsl@";
     
     Stars_GLES_Vert = "SimpleSky.Stars.GLES.vert.glsl";
-    _sources[Stars_GLES_Vert] = OE_MULTILINE(@SimpleSky.Stars.GLES.vert.glsl@);
+    _sources[Stars_GLES_Vert] = "@SimpleSky.Stars.GLES.vert.glsl@";
 
     Stars_GLES_Frag = "SimpleSky.Stars.GLES.frag.glsl";
-    _sources[Stars_GLES_Frag] = OE_MULTILINE(@SimpleSky.Stars.GLES.frag.glsl@);
+    _sources[Stars_GLES_Frag] = "@SimpleSky.Stars.GLES.frag.glsl@";
 
     Sun_Vert = "SimpleSky.Sun.vert.glsl";
-    _sources[Sun_Vert] = OE_MULTILINE(@SimpleSky.Sun.vert.glsl@);
+    _sources[Sun_Vert] = "@SimpleSky.Sun.vert.glsl@";
 
     Sun_Frag = "SimpleSky.Sun.frag.glsl";
-    _sources[Sun_Frag] = OE_MULTILINE(@SimpleSky.Sun.frag.glsl@);
+    _sources[Sun_Frag] = "@SimpleSky.Sun.frag.glsl@";
 }
diff --git a/src/osgEarthDrivers/skyview/CMakeLists.txt b/src/osgEarthDrivers/skyview/CMakeLists.txt
new file mode 100644
index 0000000..50dcf2e
--- /dev/null
+++ b/src/osgEarthDrivers/skyview/CMakeLists.txt
@@ -0,0 +1,15 @@
+SET(TARGET_H
+    SkyViewOptions
+)
+SET(TARGET_SRC 
+    SkyViewTileSource.cpp
+)
+
+SETUP_PLUGIN(osgearth_skyview)
+
+
+# to install public driver includes:
+SET(LIB_NAME skyview)
+SET(LIB_PUBLIC_HEADERS SkyViewOptions)
+INCLUDE(ModuleInstallOsgEarthDriverIncludes OPTIONAL)
+
diff --git a/src/osgEarthDrivers/skyview/SkyViewOptions b/src/osgEarthDrivers/skyview/SkyViewOptions
new file mode 100644
index 0000000..58dc354
--- /dev/null
+++ b/src/osgEarthDrivers/skyview/SkyViewOptions
@@ -0,0 +1,71 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+ * Copyright 2016 Pelican Mapping
+ * http://osgearth.org
+ *
+ * osgEarth is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ */
+#ifndef OSGEARTH_DRIVER_SKYVIEW_DRIVEROPTIONS
+#define OSGEARTH_DRIVER_SKYVIEW_DRIVEROPTIONS 1
+
+#include <osgEarth/Common>
+#include <osgEarth/TileSource>
+#include <osgEarth/URI>
+
+namespace osgEarth { namespace Drivers
+{
+    using namespace osgEarth;
+
+    class SkyViewOptions : public TileSourceOptions // NO EXPORT; header only
+    {
+    public:            
+        optional<TileSourceOptions>& options() { return _imageOptions; }
+        const optional<TileSourceOptions>& options() const { return _imageOptions; }
+
+    public:
+        SkyViewOptions( const TileSourceOptions& opt =TileSourceOptions() ) :
+            TileSourceOptions( opt )      
+        {
+            setDriver( "skyview" );
+            fromConfig( _conf );
+        }
+
+        /** dtor */
+        virtual ~SkyViewOptions() { }
+
+    public:
+        Config getConfig() const {
+            Config conf = TileSourceOptions::getConfig();
+            conf.updateObjIfSet("image", _imageOptions );
+            return conf;
+        }
+
+    protected:
+        void mergeConfig( const Config& conf ) {
+            TileSourceOptions::mergeConfig( conf );
+            fromConfig( conf );
+        }
+
+    private:
+        void fromConfig( const Config& conf ) {
+            conf.getObjIfSet("image", _imageOptions );
+        }
+
+        optional<TileSourceOptions> _imageOptions;
+    };
+
+} } // namespace osgEarth::Drivers
+
+#endif // OSGEARTH_DRIVER_SKYVIEW_DRIVEROPTIONS
+
diff --git a/src/osgEarthDrivers/skyview/SkyViewTileSource.cpp b/src/osgEarthDrivers/skyview/SkyViewTileSource.cpp
new file mode 100644
index 0000000..9293569
--- /dev/null
+++ b/src/osgEarthDrivers/skyview/SkyViewTileSource.cpp
@@ -0,0 +1,130 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+ * Copyright 2016 Pelican Mapping
+ * http://osgearth.org
+ *
+ * osgEarth is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ */
+#include "SkyViewOptions"
+
+#include <osgEarth/Registry>
+#include <osgEarth/ImageUtils>
+#include <osgDB/FileNameUtils>
+#include <osgDB/FileUtils>
+
+#include <cstring>
+
+#define LC "[SkyView Driver] "
+
+using namespace osgEarth;
+using namespace osgEarth::Drivers;
+
+
+class SkyViewTileSource : public TileSource
+{
+public:
+    SkyViewTileSource( const TileSourceOptions& options ) :
+      TileSource( options ),            
+      _options( options )
+    {
+        //nop
+    }
+
+    Status initialize( const osgDB::Options* dbOptions )
+    {
+        _dbOptions = Registry::instance()->cloneOrCreateOptions(dbOptions);        
+
+        if (!_options.options().isSet())
+        {
+            return Status::Error(Status::ConfigurationError, "Please specify a image layer for the skyview driver.");
+        }
+
+        _source = TileSourceFactory::create( *_options.options());
+
+        if (!_source.valid())
+        {
+            return Status::Error(Status::ServiceUnavailable, "Failed to load image layer for skyview driver");
+        }
+
+         // Open the tile source (if it hasn't already been started)
+        Status status = _source->getStatus();
+        if (status.isError())
+        {
+            status = _source->open(TileSource::MODE_READ, _dbOptions.get());
+        }
+
+        if (status.isError())
+        {
+            return status;
+        }
+        
+        setProfile(_source->getProfile());           
+
+        return osgEarth::STATUS_OK;
+    }
+
+    osg::Image*
+    createImage( const TileKey& key, ProgressCallback* progress )
+    {
+        // We need to flip the image horizontally so that it's viewable from inside the globe.
+        
+        // Create a new key with the x coordinate flipped.
+        unsigned int numRows, numCols;
+
+        key.getProfile()->getNumTiles(key.getLevelOfDetail(), numCols, numRows);        
+        unsigned int tileX = numCols - key.getTileX() -1;
+        unsigned int tileY = key.getTileY();
+        unsigned int level = key.getLevelOfDetail();
+
+        osg::ref_ptr< osg::Image > image = _source->createImage(TileKey(level, tileX, tileY, key.getProfile()), 0, progress);
+        if (image)
+        {
+            // If an image was read successfully, we still need to flip it horizontally
+            image->flipHorizontal();
+        }
+        return image.release();      
+    }
+    
+
+private:
+    const SkyViewOptions _options;
+    osg::ref_ptr< TileSource > _source;
+    osg::ref_ptr<osgDB::Options>   _dbOptions;
+};
+
+
+class SkyViewTileSourceFactory : public TileSourceDriver
+{
+public:
+    SkyViewTileSourceFactory()
+    {
+        supportsExtension( "osgearth_skyview", "SkyView driver for osgEarth" );
+    }
+
+    const char* className() const
+    {
+        return "SkyView Image Driver";
+    }
+
+    ReadResult readObject(const std::string& file_name, const Options* options) const
+    {
+        if ( !acceptsExtension(osgDB::getLowerCaseFileExtension( file_name )))
+            return ReadResult::FILE_NOT_HANDLED;
+
+        return new SkyViewTileSource( getTileSourceOptions(options) );
+    }
+};
+
+REGISTER_OSGPLUGIN(osgearth_skyview, SkyViewTileSourceFactory)
+
diff --git a/src/osgEarthDrivers/splat_mask/SplatMaskDriver.cpp b/src/osgEarthDrivers/splat_mask/SplatMaskDriver.cpp
index 69c7392..f4f9cdd 100644
--- a/src/osgEarthDrivers/splat_mask/SplatMaskDriver.cpp
+++ b/src/osgEarthDrivers/splat_mask/SplatMaskDriver.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -186,12 +186,12 @@ namespace osgEarth { namespace Drivers { namespace SplatMask
                 supportsExtension( "osgearth_splat_mask", "Detail texture splat mask generator" );
             }
 
-            virtual const char* className()
+            const char* className() const
             {
                 return "Detail Splat Mask Driver";
             }
 
-            virtual ReadResult readObject(const std::string& file_name, const Options* options) const
+            ReadResult readObject(const std::string& file_name, const Options* options) const
             {
                 if ( !acceptsExtension(osgDB::getLowerCaseFileExtension( file_name )))
                     return ReadResult::FILE_NOT_HANDLED;
diff --git a/src/osgEarthDrivers/splat_mask/SplatMaskOptions b/src/osgEarthDrivers/splat_mask/SplatMaskOptions
index 95e06d8..f4723b8 100644
--- a/src/osgEarthDrivers/splat_mask/SplatMaskOptions
+++ b/src/osgEarthDrivers/splat_mask/SplatMaskOptions
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthDrivers/template/CMakeLists.txt b/src/osgEarthDrivers/template/CMakeLists.txt
new file mode 100644
index 0000000..a0a2f74
--- /dev/null
+++ b/src/osgEarthDrivers/template/CMakeLists.txt
@@ -0,0 +1,11 @@
+SET(TARGET_H
+    NLTemplate.h
+)
+
+SET(TARGET_SRC
+    ReaderWriterTemplate.cpp
+    NLTemplate.cpp
+)
+
+    
+SETUP_PLUGIN(template)
\ No newline at end of file
diff --git a/src/osgEarthDrivers/template/NLTemplate.cpp b/src/osgEarthDrivers/template/NLTemplate.cpp
new file mode 100644
index 0000000..834ba87
--- /dev/null
+++ b/src/osgEarthDrivers/template/NLTemplate.cpp
@@ -0,0 +1,491 @@
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "NLTemplate.h"
+
+#include <osgEarth/FileUtils>
+
+
+using namespace std;
+using namespace NL::Template;
+
+
+
+enum {
+    TOKEN_END,
+    TOKEN_TEXT,
+    TOKEN_BLOCK,
+    TOKEN_ENDBLOCK,
+    TOKEN_INCLUDE,
+    TOKEN_VAR
+};
+
+
+static inline bool alphanum( const char c ) {
+    return
+    ( c >= 'a' && c <= 'z' ) ||
+    ( c >= 'A' && c <= 'Z' ) ||
+    ( c >= '0' && c <= '9' ) ||    
+    ( c == '_' ) ||
+    ( c == '.' ) ||
+
+    // JB:  Added these to enable matching of paths as well
+    ( c == ' ' ) ||
+    ( c == ':' ) ||
+    ( c == '-' ) ||
+    ( c == '@' ) ||
+    ( c == '/' ) ||
+    ( c == '\\' );
+}
+
+
+static inline long match_var( const char *text, string & result ) {
+    if (text[ 0 ] != '{' ||
+        text[ 1 ] != '{' ||
+        text[ 2 ] != ' ' )
+    {
+        return -1;
+    }
+    
+    const char *var = text + 3;
+    const char *cursor = var;
+    
+    while ( *cursor ) {
+        if (cursor[ 0 ] == ' ' &&
+            cursor[ 1 ] == '}' &&
+            cursor[ 2 ] == '}' )
+        {
+            result = string( var, cursor - var );
+            return cursor + 3 - text;
+        }
+        
+        if ( !alphanum( *cursor ) ) {
+            return -1;
+        }
+        
+        cursor++;
+    }
+    
+    return -1;
+}
+
+
+static inline long match_tag_with_param( const char *tag, const char *text, string & result ) {
+    if (text[ 0 ] != '{' ||
+        text[ 1 ] != '%' ||
+        text[ 2 ] != ' ')
+    {
+        return -1;
+    }
+
+    long taglen = strlen( tag );
+    if ( strncmp( text + 3, tag, taglen ) ) {
+        return -1;
+    }
+
+    const char *param = text + 3 + taglen;
+    
+    if ( *param != ' ' ) {
+        return -1;
+    }
+    
+    param++;
+
+    const char *cursor = param;
+
+    while ( *cursor ) {
+        if (cursor[ 0 ] == ' ' &&
+            cursor[ 1 ] == '%' &&
+            cursor[ 2 ] == '}' )
+        {
+            result = string( param, cursor - param );
+            return cursor + 3 - text;
+        }
+
+        if ( !alphanum( *cursor ) ) {
+            return -1;
+        }
+        
+        cursor++;
+    }
+    
+    return -1;
+}
+
+
+Tokenizer::Tokenizer( const char *text ) :
+text( text ),
+len( strlen( text ) ),
+pos( 0 ),
+peeking( false )
+{
+}
+
+
+Tokenizer::~Tokenizer() {
+    free( (void*) text );
+}
+
+
+Token Tokenizer::next() {
+    static const char * s_endblock = "{% endblock %}";
+    static const char * s_block = "block";
+    static const char * s_include = "include";
+    static const long s_endblock_len = strlen( s_endblock );
+    
+    if ( peeking ) {
+        peeking = false;
+        return peek;
+    }
+    
+    Token token;
+    token.value.clear();
+    peek.value.clear();
+    token.type = TOKEN_END;
+    peek.type = TOKEN_END;
+    
+    long textpos = pos;
+    long textlen = 0;
+    
+a:
+    if ( pos < len ) {
+        long m = match_tag_with_param( s_block, text + pos, peek.value );
+        if ( m > 0 ) {
+            peek.type = TOKEN_BLOCK;
+            pos += m;
+        } else if ( !strncmp( s_endblock, text + pos, s_endblock_len ) ) {
+            peek.type = TOKEN_ENDBLOCK;
+            pos += s_endblock_len;
+        } else if ( ( m = match_tag_with_param( s_include, text + pos, peek.value ) ) > 0 ) {
+            peek.type = TOKEN_INCLUDE;
+            pos += m;
+        } else if ( ( m = match_var( text + pos, peek.value ) ) > 0 ) {
+            peek.type = TOKEN_VAR;
+            pos += m;
+        } else {
+            textlen ++;
+            pos ++;
+            peeking = true;
+            goto a;
+        }
+    }
+
+    if ( peeking ) {
+        token.type = TOKEN_TEXT;
+        token.value = string( text + textpos, textlen );
+        return token;
+    }
+
+    return peek;
+}
+
+
+const string Dictionary::find( const string & name ) const {
+    for ( size_t i=0; i < properties.size(); i++ ) {
+        if ( properties[ i ].first == name ) {
+            return properties[ i ].second;
+        }
+    }
+    return "";
+}
+
+
+void Dictionary::set( const string & name, const string & value ) {
+    for ( size_t i=0; i < properties.size(); i++ ) {
+        if ( properties[ i ].first == name ) {
+            properties[ i ].second = value;
+            return;
+        }
+    }
+    properties.push_back( pair<string, string>( name, value ) );
+}
+
+
+Fragment::~Fragment() {
+}
+
+
+bool Fragment::isBlockNamed( const string & ) const {
+    return false;
+}
+
+
+
+Text::Text( const string & text ) : text( text ) {
+}
+
+
+void Text::render( Output & output, const Dictionary & ) const {
+    output.print( text );
+}
+
+
+Fragment *Text::copy() const {
+    return new Text( text );
+}
+
+
+Property::Property( const string & name ) : name( name ) {
+}
+
+
+void Property::render( Output & output, const Dictionary & dictionary ) const {
+    output.print( dictionary.find( name ) );
+}
+
+
+Fragment *Property::copy() const {
+    return new Property( name );
+}
+
+
+Node::~Node() {
+    for ( size_t i=0; i < fragments.size(); i++ ) {
+        delete fragments[ i ];
+    }
+}
+
+
+Fragment *Node::copy() const {
+    Node *node = new Node();
+    node->properties = properties;
+    for ( size_t i=0; i < fragments.size(); i++ ) {
+        node->fragments.push_back( fragments[ i ]->copy() );
+    }
+    return node;
+}
+
+
+void Node::render( Output & output, const Dictionary & ) const {
+    for ( size_t i=0; i < fragments.size(); i++ ) {
+        fragments[ i ]->render( output, *this );
+    }
+}
+
+
+
+Block & Node::block( const string & name ) const {
+    for ( size_t i=0; i < fragments.size(); i++ ) {
+        if ( fragments[ i ]->isBlockNamed( name ) ) {
+            return *dynamic_cast<Block*>( fragments[ i ] );
+        }
+    }
+    throw 0;
+}
+
+
+Block::Block( const string & name ) : name( name ), enabled( true ), resized( false ) {
+}
+
+
+Fragment *Block::copy() const {
+    Block *block = new Block( name );
+    block->properties = properties;
+    for ( size_t i=0; i < fragments.size(); i++ ) {
+        block->fragments.push_back( fragments[ i ]->copy() );
+    }
+    return block;
+}
+
+
+Block::~Block() {
+    for ( size_t i=0; i < nodes.size(); i++ ) {
+        delete nodes[ i ];
+    }
+}
+
+
+bool Block::isBlockNamed( const string & name ) const {
+    return this->name == name;
+}
+
+
+void Block::enable() {
+    enabled = true;
+}
+
+
+void Block::disable() {
+    enabled = false;
+}
+
+void Block::repeat( size_t n ) {
+    resized = true;
+    for ( size_t i=0; i < nodes.size(); i++ ) {
+        delete nodes[ i ];
+    }
+    nodes.clear();
+    for ( size_t i=0; i < n; i++ ) {
+        nodes.push_back( static_cast<Node*>( copy() ) );
+    }
+}
+
+
+Node & Block::operator[]( size_t index ) {
+    return *nodes.at( index );
+}
+
+
+void Block::render( Output & output, const Dictionary & ) const {
+    if ( enabled ) {
+        if ( resized ) {
+            for ( size_t i=0; i < nodes.size(); i++ ) {
+                nodes[ i ]->render( output, *nodes[ i ] );
+            }
+        } else {
+            Node::render( output, *this );
+        }
+    }
+}
+
+
+Output::~Output() {
+}
+
+
+void OutputString::print( const string & text ) {
+    buf << text;
+}
+
+
+void OutputStdout::print( const std::string &text ) {
+    cout << text;
+}
+
+
+Loader::~Loader() {
+}
+
+
+const std::string& Loader::getReferrer() const
+{
+    return _referrer;
+}
+
+void Loader::setReferrer(const std::string& referrer)
+{
+    _referrer = referrer; 
+}
+
+
+const char * LoaderFile::load( const char *name ) {
+
+    std::string fullPath = osgEarth::getFullPath(_referrer, std::string(name));
+
+    FILE *f = fopen( fullPath.c_str(), "rb" );
+    if (!f) {
+        std::cout << "NLTemplate error:  Failed to open " << fullPath << std::endl;
+        return 0;
+    }
+    fseek( f, 0, SEEK_END );
+    long len = ftell( f );
+    if (len > 0)
+    {
+        fseek( f, 0, SEEK_SET );
+        char *buffer = (char*) malloc( len + 1 );
+        fread( (void*) buffer, (size_t)len, 1, f );
+        fclose( f );
+        buffer[ len ] = 0;
+        return buffer;
+    }
+    else
+    {
+        fclose(f);
+        return 0L;
+    }
+}
+
+
+Template::Template( Loader & loader ) : Block( "main" ), loader( loader ) {
+}
+
+
+void Template::load_recursive( const char *name, vector<Tokenizer*> & files, vector<Node*> & nodes ) {
+        
+    const char* loaded = loader.load( name );
+    if (!loaded)
+    {
+        return;
+    }
+
+    Tokenizer *tokenizer = new Tokenizer( loaded );
+    files.push_back( tokenizer );
+
+    std::string referrer = osgEarth::getFullPath(loader.getReferrer(), std::string(name));
+    _referrerStack.push_back( referrer );
+    loader.setReferrer( referrer );      
+
+    bool done = false;
+    while( !done ) {
+        Token token = files.back()->next();
+        switch ( token.type ) {
+            case TOKEN_END:
+                done = true;
+                break;
+            case TOKEN_BLOCK: {
+                Block *block = new Block( token.value );
+                nodes.back()->fragments.push_back( block );
+                nodes.push_back( block );
+            }
+                break;
+            case TOKEN_ENDBLOCK:
+                nodes.pop_back();
+                break;
+            case TOKEN_VAR:
+                nodes.back()->fragments.push_back( new Property( token.value ) );
+                break;
+            case TOKEN_TEXT:
+                nodes.back()->fragments.push_back( new Text( token.value ) );
+                break;
+            case TOKEN_INCLUDE:
+                load_recursive( token.value.c_str(), files, nodes );
+                break;
+        }
+    }
+
+    _referrerStack.pop_back();
+    if (!_referrerStack.empty())
+    {
+        loader.setReferrer( _referrerStack.back() );
+    }
+    else
+    {
+        loader.setReferrer("");
+    }
+    
+    delete files.back();
+    files.pop_back();
+}
+
+
+void Template::clear() {
+    for ( size_t i=0; i < fragments.size(); i++ ) {
+        delete fragments[ i ];
+    }
+    for ( size_t i=0; i < nodes.size(); i++ ) {
+        delete nodes[ i ];
+    }
+    nodes.clear();
+    fragments.clear();
+    properties.clear();
+}
+
+
+void Template::load( const char *name ) {
+    clear();
+    
+    vector<Node*> stack;
+    stack.push_back( this );
+    
+    vector<Tokenizer*> file_stack;
+   
+    load_recursive( name, file_stack, stack );
+
+}
+
+
+void Template::render( Output & output ) const {
+    Node::render( output, *this );
+}
+
diff --git a/src/osgEarthDrivers/template/NLTemplate.h b/src/osgEarthDrivers/template/NLTemplate.h
new file mode 100644
index 0000000..2f87b2c
--- /dev/null
+++ b/src/osgEarthDrivers/template/NLTemplate.h
@@ -0,0 +1,179 @@
+#ifndef __Template_H__
+#define __Template_H__
+
+
+#include <string>
+#include <sstream>
+#include <vector>
+#include <iostream>
+
+
+namespace NL {
+
+namespace Template {
+
+
+
+struct Token {
+    int type;
+    std::string value;
+};
+
+
+class Tokenizer {
+private:
+    const char *text;
+    long len;
+    long pos;
+    Token peek;
+    bool peeking;
+public:
+    // Tokenizer will free() the text on exit
+    Tokenizer( const char *text );
+    ~Tokenizer();
+    Token next();
+};
+
+
+class Dictionary {
+public:
+    std::vector<std::pair<std::string, std::string> > properties;
+    
+public:
+    const std::string find( const std::string & name ) const;
+    void set( const std::string & name, const std::string & value );
+};
+
+
+class Output {
+public:
+    virtual ~Output();
+    virtual void print( const std::string & text ) = 0;
+};
+
+
+class Fragment {
+public:
+    virtual void render( Output & output, const Dictionary & dictionary ) const = 0;
+    virtual ~Fragment();
+    virtual Fragment *copy() const = 0;
+    virtual bool isBlockNamed( const std::string & name ) const;
+};
+
+
+class Text : public Fragment {
+private:
+    const std::string text;
+    
+public:
+    Text( const std::string & text );
+    void render( Output & output, const Dictionary & dictionary ) const;
+    Fragment *copy() const;
+};
+
+
+class Property : public Fragment {
+private:
+    const std::string name;
+    
+public:
+    Property( const std::string & name );
+    void render( Output & output, const Dictionary & dictionary ) const;
+    Fragment *copy() const;
+};
+
+
+class Block;
+
+
+class Node : public Fragment, public Dictionary {
+public:
+    std::vector<Fragment*> fragments;
+    
+public:
+    ~Node();
+    Fragment *copy() const;
+    void render( Output & output, const Dictionary & dictionary ) const;
+    Block & block( const std::string & name ) const;
+};
+
+
+class Block : public Node {
+protected:
+    const std::string name;
+    bool enabled;
+    bool resized;
+    std::vector<Node*> nodes;
+    
+public:
+    Block( const std::string & name );
+    Fragment *copy() const;
+    ~Block();
+    bool isBlockNamed( const std::string & name ) const;
+    void enable();
+    void disable();
+    void repeat( size_t n );
+    Node & operator[]( size_t index );
+    void render( Output & output, const Dictionary & dictionary ) const;
+};
+
+
+
+class OutputStdout : public Output {
+public:
+    void print( const std::string & text );
+};
+
+
+class OutputString : public Output {
+public:
+    std::stringstream buf;
+    
+public:
+    void print( const std::string & text );
+};
+
+
+class Loader {
+public:
+    virtual ~Loader();
+    // Returns mallocated memory that the consumer must free()
+    virtual const char * load( const char *name ) = 0;
+
+    const std::string& getReferrer() const;
+    void setReferrer(const std::string& referrer);
+
+    std::string _referrer;
+};
+
+
+class LoaderFile : public Loader {
+public:
+    const char * load( const char *name );
+};
+
+
+
+class Template : public Block {
+protected:
+    Loader & loader;
+
+    std::vector< std::string > _referrerStack;
+    
+public:
+    Template( Loader & loader );
+    void clear();
+    void load( const char *name );
+    void render( Output & output ) const;
+    
+protected:
+    void load_recursive( const char *name, std::vector<Tokenizer*> & files, std::vector<Node*> & nodes );
+};
+
+
+    
+} // namespace Template
+    
+} // namespace NL
+
+#endif
diff --git a/src/osgEarthDrivers/template/NL_Template_LICENSE.txt b/src/osgEarthDrivers/template/NL_Template_LICENSE.txt
new file mode 100644
index 0000000..14e65be
--- /dev/null
+++ b/src/osgEarthDrivers/template/NL_Template_LICENSE.txt
@@ -0,0 +1,20 @@
+The MIT License (MIT)
+
+Copyright (c) 2013 Tomas Andrle
+
+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.
diff --git a/src/osgEarthDrivers/template/ReaderWriterTemplate.cpp b/src/osgEarthDrivers/template/ReaderWriterTemplate.cpp
new file mode 100644
index 0000000..466cfbe
--- /dev/null
+++ b/src/osgEarthDrivers/template/ReaderWriterTemplate.cpp
@@ -0,0 +1,101 @@
+#include <osg/Notify>
+#include <osgDB/ReaderWriter>
+#include <osgDB/FileUtils>
+#include <osgDB/FileNameUtils>
+#include <osgDB/Registry>
+
+#include <osgEarth/URI>
+#include <osgEarth/Registry>
+
+#include "NLTemplate.h"
+
+using namespace NL::Template;
+
+/**
+* OpenSceneGraph psuedoloader that runs a node through the NLTemplate (https://github.com/catnapgames/NLTemplate)
+* templating library before actually loading it. The original goal of this plugin was to simplify 
+* the management of complicated earth files but it can be used to process any text based format.
+* 
+* To run your file through the template processor, simply append .template to your filename.
+* osgviewer map.earth.template
+* 
+* This will process any {% include file.xml %} snippits in the text.
+*
+* To provide context variables to the templating engine provide an Options string with a list of key value pairs
+* separated by the equal sign.
+* osgviewer map.earth.template -O "layer=123 max_range=1e6 shapefile=world.shp"
+*/
+class TemplateReaderWriter: public osgDB::ReaderWriter
+{
+    public:
+        TemplateReaderWriter()
+        {
+            supportsExtension("template","Template");
+        }
+
+        virtual const char* className() const { return "TemplateReaderWriter"; }
+
+        virtual bool acceptsExtension(const std::string& extension) const
+        {
+            return osgDB::equalCaseInsensitive(extension,"template");
+        }
+
+        virtual ReadResult readObject(const std::string& file_name, const osgDB::Options* options) const
+        {
+            return readNode( file_name, options );
+        }
+
+        virtual ReadResult readNode(const std::string& fileName, const osgDB::Options* options) const
+        {         
+            std::string ext = osgDB::getFileExtension( fileName );
+            if ( !acceptsExtension( ext ) )
+                return ReadResult::FILE_NOT_HANDLED;
+
+            std::string realName = osgDB::getNameLessExtension( fileName );
+            if (!osgDB::fileExists(realName))
+            {
+                return ReadResult::FILE_NOT_FOUND;
+            }
+
+            std::string realExt = osgDB::getFileExtension( realName );
+            osg::ref_ptr< osgDB::ReaderWriter > driver = osgDB::Registry::instance()->getReaderWriterForExtension(realExt);
+            if (!driver.valid())
+            {
+                return ReadResult::FILE_NOT_HANDLED;
+            }
+
+            LoaderFile loader;
+            Template t(loader);            
+            t.load( realName.c_str() );
+            
+
+            // Populate a list of key value pairs from the options string.
+            if (options)
+            {
+                std::istringstream iss(options->getOptionString());
+                std::string opt;
+                while (iss >> opt) {
+                    opt = osgDB::convertToLowerCase(opt);
+                    std::size_t eqInd = opt.find("=");
+                    std::string key = opt.substr(0, eqInd);
+                    std::string value = opt.substr(eqInd + 1);
+                    t.set(key, value);
+                }
+            }
+
+            OutputString output;
+            t.render( output );
+
+            OE_DEBUG << "Processed template " << std::endl << output.buf.str() << std::endl;
+
+            // Set the osgEarth URIContext so that relative paths will work.  We have to do this manually here
+            // since we are using the stream based readNode function and the Earth driver won't know 
+            // where the original earth file came frame.
+            osg::ref_ptr< osgDB::Options > opt = osgEarth::Registry::instance()->cloneOrCreateOptions(options);
+            osgEarth::URIContext( realName ).store( opt.get() );
+
+            return driver->readNode( output.buf, opt.get() );                       
+        }        
+};
+
+REGISTER_OSGPLUGIN(template, TemplateReaderWriter)
diff --git a/src/osgEarthDrivers/template_matclass/TemplateMatClassDriver.cpp b/src/osgEarthDrivers/template_matclass/TemplateMatClassDriver.cpp
index f60f51b..9b9a130 100644
--- a/src/osgEarthDrivers/template_matclass/TemplateMatClassDriver.cpp
+++ b/src/osgEarthDrivers/template_matclass/TemplateMatClassDriver.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -86,12 +86,16 @@ public: // TileSource interface
         if ( _options.featureSourceOptions().isSet() )
         {
             _featureSource = FeatureSourceFactory::create( _options.featureSourceOptions().get() );
-            _featureSource->initialize( _dbOptions.get() );
+            _featureSource->open( _dbOptions.get() );
         }
 
-        // set up the IO options so that we do not cache input data:
-        CachePolicy::NO_CACHE.apply( _dbOptions.get() );
-        return STATUS_OK;
+        return Status::OK();
+    }
+
+    // Tells the layer not to cache data from this tile source.
+    CachePolicy getCachePolicyHint(const Profile* profile) const 
+    {
+        return CachePolicy::NO_CACHE;
     }
 
     // override
@@ -137,7 +141,7 @@ class TemplateMatClassDriver : public TileSourceDriver
     public:
         TemplateMatClassDriver() {}
 
-        virtual const char* className()
+        virtual const char* className() const
         {
             return "Template mat class driver";
         }
diff --git a/src/osgEarthDrivers/template_matclass/TemplateMatClassOptions b/src/osgEarthDrivers/template_matclass/TemplateMatClassOptions
index 070593b..dcbc90e 100644
--- a/src/osgEarthDrivers/template_matclass/TemplateMatClassOptions
+++ b/src/osgEarthDrivers/template_matclass/TemplateMatClassOptions
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthDrivers/terrainshader/CMakeLists.txt b/src/osgEarthDrivers/terrainshader/CMakeLists.txt
new file mode 100644
index 0000000..784066a
--- /dev/null
+++ b/src/osgEarthDrivers/terrainshader/CMakeLists.txt
@@ -0,0 +1,23 @@
+#
+# terrain shader plugin
+#
+set(TARGET_SRC
+	TerrainShaderExtension.cpp
+	${SHADERS_CPP} )
+	
+set(LIB_PUBLIC_HEADERS
+	TerrainShaderExtension
+	TerrainShaderOptions)
+	
+set(TARGET_H
+	${LIB_PUBLIC_HEADERS})
+
+
+set(TARGET_COMMON_LIBRARIES ${TARGET_COMMON_LIBRARIES}
+    osgEarthUtil)
+	
+setup_plugin(osgearth_terrainshader)
+
+# to install public driver includes:
+set(LIB_NAME terrainshader)
+
diff --git a/src/osgEarthDrivers/terrainshader/TerrainShaderExtension b/src/osgEarthDrivers/terrainshader/TerrainShaderExtension
new file mode 100644
index 0000000..9a41d67
--- /dev/null
+++ b/src/osgEarthDrivers/terrainshader/TerrainShaderExtension
@@ -0,0 +1,70 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+ * Copyright 2016 Pelican Mapping
+ * http://osgearth.org
+ *
+ * osgEarth is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ */
+#ifndef OSGEARTH_EXT_TERRAIN_SHADER_H
+#define OSGEARTH_EXT_TERRAIN_SHADER_H 1
+
+#include "TerrainShaderOptions"
+#include <osgEarth/Extension>
+#include <osgEarth/MapNode>
+#include <osgEarth/TerrainEffect>
+#include <osgEarthUtil/Controls>
+
+namespace osgEarth { namespace TerrainShader
+{
+    using namespace osgEarth;
+
+    class TerrainShaderExtension : public Extension,
+                                   public ExtensionInterface<MapNode>,
+                                   public TerrainShaderOptions
+    {
+    public:
+        META_Object(osgearth_ext_terrainshader, TerrainShaderExtension);
+
+        // CTORs
+        TerrainShaderExtension();
+        TerrainShaderExtension(const TerrainShaderOptions& options);
+
+        // DTOR
+        virtual ~TerrainShaderExtension();
+
+
+    public: // Extension
+
+        virtual void setDBOptions(const osgDB::Options* dbOptions);
+
+        virtual const ConfigOptions& getConfigOptions() const { return *this; }
+
+    public: // ExtensionInterface<MapNode>
+
+        bool connect(MapNode* mapNode);
+
+        bool disconnect(MapNode* mapNode);
+
+
+    protected: // Object
+        TerrainShaderExtension(const TerrainShaderExtension& rhs, const osg::CopyOp& op) { }
+
+    private:
+        osg::ref_ptr<const osgDB::Options> _dbOptions;
+        osg::ref_ptr<TerrainEffect>        _effect;
+    };
+
+} } // namespace osgEarth::TerrainShader
+
+#endif // OSGEARTH_EXT_TERRAIN_SHADER_H
diff --git a/src/osgEarthDrivers/terrainshader/TerrainShaderExtension.cpp b/src/osgEarthDrivers/terrainshader/TerrainShaderExtension.cpp
new file mode 100644
index 0000000..be4da5a
--- /dev/null
+++ b/src/osgEarthDrivers/terrainshader/TerrainShaderExtension.cpp
@@ -0,0 +1,228 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+ * Copyright 2016 Pelican Mapping
+ * http://osgearth.org
+ *
+ * osgEarth is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ */
+#include "TerrainShaderExtension"
+
+#include <osgEarth/TerrainEffect>
+#include <osgEarth/TerrainEngineNode>
+#include <osgEarth/MapNode>
+#include <osgEarth/VirtualProgram>
+#include <osgEarth/ShaderLoader>
+#include <osgEarth/ImageUtils>
+
+#include <osg/Texture2D>
+#include <osg/Texture2DArray>
+
+using namespace osgEarth;
+using namespace osgEarth::TerrainShader;
+
+#define LC "[TerrainShaderExtension] "
+
+namespace
+{
+    class GLSLEffect : public osgEarth::TerrainEffect
+    {
+    public:
+        GLSLEffect(const TerrainShaderOptions& options,
+                   const osgDB::Options*       dbOptions ) :
+            _options(options), _dbOptions(dbOptions)
+        {
+            const std::vector<TerrainShaderOptions::Code>& code = _options.code();
+
+            for(unsigned i=0; i<code.size(); ++i)
+            {
+		std::ostringstream oss;
+		oss << i;
+                std::string fn = code[i]._uri.isSet() ? code[i]._uri->full() : "$code." + oss.str();
+                _package.add( fn, code[i]._source );
+            }
+        }
+
+        void onInstall(TerrainEngineNode* engine)
+        {
+            if ( !engine ) return;
+
+            osg::StateSet* stateSet = engine->getSurfaceStateSet();
+            
+            VirtualProgram* vp = VirtualProgram::getOrCreate(stateSet);
+            _package.loadAll( vp, _dbOptions.get() );
+
+
+            const std::vector<TerrainShaderOptions::Sampler>& samplers = _options.samplers();
+            for(int i=0; i<samplers.size(); ++i)
+            {
+                if ( !samplers[i]._name.empty() )
+                {
+                    if ( samplers[i]._uris.size() == 1 ) // Texture2D
+                    {
+                        int unit;    
+                        engine->getResources()->reserveTextureImageUnit(unit, "TerrainShader sampler");
+                        if ( unit >= 0 )
+                        {
+                            osg::Image* image = samplers[i]._uris[0].getImage(_dbOptions.get());
+                            if ( image )
+                            {
+                                osg::Texture2D* tex = new osg::Texture2D(image);
+                                tex->setFilter(tex->MIN_FILTER, tex->NEAREST_MIPMAP_LINEAR);
+                                tex->setFilter(tex->MAG_FILTER, tex->LINEAR);
+                                tex->setWrap  (tex->WRAP_S, tex->REPEAT);
+                                tex->setWrap  (tex->WRAP_T, tex->REPEAT);
+                                tex->setUnRefImageDataAfterApply( true );
+                                tex->setMaxAnisotropy( 4.0 );
+                                tex->setResizeNonPowerOfTwoHint( false );
+
+                                stateSet->setTextureAttribute(unit, tex);
+                                stateSet->addUniform(new osg::Uniform(samplers[i]._name.c_str(), unit));
+                            }
+                        }
+                        else
+                        {
+                            OE_WARN << LC << "Failed to allocate a texture image unit for this terrain shader sampler!\n";
+                        }
+                    }
+
+                    else if ( samplers[i]._uris.size() > 1 ) // Texture2DArray
+                    {
+                        int unit;    
+                        engine->getResources()->reserveTextureImageUnit(unit, "TerrainShader sampler array");
+                        if ( unit >= 0 )
+                        {
+                            osg::Texture2DArray* tex = new osg::Texture2DArray();
+                            tex->setTextureSize(512, 512, samplers[i]._uris.size());
+                            tex->setTextureDepth( samplers[i]._uris.size() );
+
+                            for( int j=0; j<samplers[i]._uris.size(); ++j )
+                            {
+                                const URI& uri = samplers[i]._uris[j];
+
+                                osg::ref_ptr<osg::Image> image = uri.getImage(_dbOptions.get());
+                                if ( image )
+                                {
+                                    if ( image->s() != 512 || image->t() != 512 )
+                                    {
+                                        osg::ref_ptr<osg::Image> resizedImage;
+                                        ImageUtils::resizeImage(image.get(), 512, 512, resizedImage);
+                                        image = resizedImage.get();
+                                    }
+
+                                    OE_INFO << LC << "   Added image from \"" << uri.full() << "\"\n";
+                                    tex->setImage(i, image);
+                                    tex->setFilter(tex->MIN_FILTER, tex->NEAREST_MIPMAP_LINEAR);
+                                    tex->setFilter(tex->MAG_FILTER, tex->LINEAR);
+                                    tex->setWrap  (tex->WRAP_S, tex->CLAMP_TO_EDGE);
+                                    tex->setWrap  (tex->WRAP_T, tex->CLAMP_TO_EDGE);
+                                    tex->setUnRefImageDataAfterApply( true );
+                                    //tex->setMaxAnisotropy( 4.0 );
+                                    tex->setResizeNonPowerOfTwoHint( false );
+
+                                    stateSet->setTextureAttribute(unit, tex);
+                                    stateSet->addUniform(new osg::Uniform(samplers[i]._name.c_str(), unit));
+                                }
+                            }
+                        }
+                        else
+                        {
+                            OE_WARN << LC << "Failed to allocate a texture image unit for this terrain shader sampler!\n";
+                        }
+                    }
+                }
+            }
+
+            const std::vector<TerrainShaderOptions::Uniform>& uniforms = _options.uniforms();
+            for(int i=0; i<uniforms.size(); ++i)
+            {
+                if ( !uniforms[i]._name.empty() && uniforms[i]._value.isSet() )
+                {
+                    osg::Uniform* u = new osg::Uniform(uniforms[i]._name.c_str(), (float)uniforms[i]._value.get());
+                    stateSet->addUniform( u );
+                }
+            }
+        }
+
+        void onUninstall(TerrainEngineNode* engine)
+        {
+            if ( engine )
+            {
+                if ( _options.landCoverGroup().isSet() )
+                {
+                    //TODO
+                    //engine->removeLandCoverGroup( _options.landCoverGroup().get() );
+                }
+            }
+        }
+
+        const TerrainShaderOptions              _options;
+        ShaderPackage                           _package;
+        osg::ref_ptr<const osgDB::Options>      _dbOptions;
+    };
+}
+
+
+REGISTER_OSGEARTH_EXTENSION( osgearth_terrainshader, TerrainShaderExtension )
+
+
+TerrainShaderExtension::TerrainShaderExtension()
+{
+    //nop
+}
+
+TerrainShaderExtension::TerrainShaderExtension(const TerrainShaderOptions& options) :
+TerrainShaderOptions( options )
+{
+    //nop
+}
+
+TerrainShaderExtension::~TerrainShaderExtension()
+{
+    //nop
+}
+
+void
+TerrainShaderExtension::setDBOptions(const osgDB::Options* dbOptions)
+{
+    _dbOptions = dbOptions;
+}
+
+bool
+TerrainShaderExtension::connect(MapNode* mapNode)
+{
+    if ( !mapNode )
+    {
+        OE_WARN << LC << "Illegal: MapNode cannot be null." << std::endl;
+        return false;
+    }
+    _effect = new GLSLEffect( *this, _dbOptions.get() );
+    mapNode->getTerrainEngine()->addEffect( _effect.get() );
+    
+    OE_INFO << LC << "Installed.\n";
+
+    return true;
+}
+
+bool
+TerrainShaderExtension::disconnect(MapNode* mapNode)
+{
+    if ( mapNode && _effect.valid() )
+    {
+        mapNode->getTerrainEngine()->removeEffect( _effect.get() );
+        _effect = 0L;
+    }
+
+    return true;
+}
+
diff --git a/src/osgEarthDrivers/terrainshader/TerrainShaderOptions b/src/osgEarthDrivers/terrainshader/TerrainShaderOptions
new file mode 100644
index 0000000..e7be0de
--- /dev/null
+++ b/src/osgEarthDrivers/terrainshader/TerrainShaderOptions
@@ -0,0 +1,177 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+ * Copyright 2016 Pelican Mapping
+ * http://osgearth.org
+ *
+ * osgEarth is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ */
+#ifndef OSGEARTH_EXT_TERRAIN_SHADER_OPTIONS
+#define OSGEARTH_EXT_TERRAIN_SHADER_OPTIONS 1
+
+#include <osgEarth/Config>
+#include <osgEarth/URI>
+#include <vector>
+
+namespace osgEarth { namespace TerrainShader
+{
+    using namespace osgEarth;
+
+    /**
+     * Options for applying an inline shader to the terrain.
+     */
+    class TerrainShaderOptions : public DriverConfigOptions // NO EXPORT; header only
+    {
+    public:
+        struct Code
+        {
+            std::string   _source;
+            optional<URI> _uri;
+        };
+
+        struct Sampler
+        {
+            std::string      _name;
+            std::vector<URI> _uris;
+        };
+
+        struct Uniform
+        {
+            std::string     _name;
+            optional<float> _value;
+        };
+
+        std::vector<Code>& code() { return _code; }
+        const std::vector<Code>& code() const { return _code; }
+
+        std::vector<Sampler>& samplers() { return _samplers; }
+        const std::vector<Sampler>& samplers() const { return _samplers; }
+
+        std::vector<Uniform>& uniforms() { return _uniforms; }
+        const std::vector<Uniform>& uniforms() const { return _uniforms; }
+
+        optional<std::string>& landCoverGroup() { return _landCoverGroup; }
+        const optional<std::string>& landCoverGroup() const { return _landCoverGroup; }
+
+        optional<unsigned>& landCoverLOD() { return _landCoverLOD; }
+        const optional<unsigned>& landCoverLOD() const { return _landCoverLOD; }
+
+    public:
+        TerrainShaderOptions( const ConfigOptions& opt =ConfigOptions() ) : DriverConfigOptions( opt )
+        {
+            setDriver( "terrainshader" );
+            _landCoverLOD.init(15);
+            fromConfig( _conf );
+        }
+
+        virtual ~TerrainShaderOptions() { }
+
+    public:
+        Config getConfig() const
+        {
+            Config conf = DriverConfigOptions::getConfig();
+
+            for(unsigned i=0; i<_code.size(); ++i) {
+                Config c("code", _code[i]._source);
+                c.addIfSet("url", _code[i]._uri);
+                conf.add( c );
+            }
+
+            for(unsigned i=0; i<_samplers.size(); ++i) {
+                Config c("sampler");
+                c.add("name", _samplers[i]._name);
+                if ( _samplers[i]._uris.size() > 1 ) {
+                    Config urlarray("array");
+                    c.add( urlarray );
+                    for( std::vector<URI>::const_iterator j = _samplers[i]._uris.begin(); j != _samplers[i]._uris.end(); ++j) {
+                        urlarray.add( j->getConfig() );
+                    }
+                }
+                else if ( _samplers[i]._uris.size() == 1 ) {
+                    c.add( _samplers[i]._uris.back().getConfig() );
+                }
+                conf.add( c );
+            }
+
+            for(unsigned i=0; i<_uniforms.size(); ++i) {
+                Config c("uniform");
+                c.add("name", _uniforms[i]._name);
+                c.addIfSet("value", _uniforms[i]._value);
+                conf.add( c );
+            }
+
+            //conf.addIfSet("land_cover", _landCover);
+            conf.addIfSet("land_cover_group", _landCoverGroup);
+            conf.addIfSet("land_cover_lod",   _landCoverLOD);
+            return conf;
+        }
+
+    protected:
+        void mergeConfig( const Config& conf ) {
+            DriverConfigOptions::mergeConfig( conf );
+            fromConfig( conf );
+        }
+
+    private:
+        void fromConfig( const Config& conf ) {
+
+            ConfigSet s = conf.children("code");
+            for(ConfigSet::const_iterator i = s.begin(); i != s.end(); ++i) {
+                _code.push_back(Code());
+                _code.back()._source = i->value();
+                i->getIfSet("url", _code.back()._uri);
+            }
+
+            s = conf.children("sampler");
+            for(ConfigSet::const_iterator i = s.begin(); i != s.end(); ++i) {
+                _samplers.push_back(Sampler());
+                _samplers.back()._name = i->value("name");
+                const Config* urlarray = i->find("array");
+                if ( urlarray ) {
+                    ConfigSet uris = urlarray->children("url");
+                    for(ConfigSet::const_iterator j = uris.begin(); j != uris.end(); ++j) {
+                        URI uri( j->value(), URIContext(conf.referrer()) );
+                        _samplers.back()._uris.push_back( uri );
+                    }
+                }
+                else {
+                   optional<URI> uri;
+                   i->getIfSet("url", uri);
+                   if ( uri.isSet() )
+                       _samplers.back()._uris.push_back( uri.get() );
+                }
+            }
+
+            s = conf.children("uniform");
+            for(ConfigSet::const_iterator i = s.begin(); i != s.end(); ++i) {
+                _uniforms.push_back(Uniform());
+                _uniforms.back()._name = i->value("name");
+                i->getIfSet("value", _uniforms.back()._value);
+            }
+            
+            //conf.getIfSet("land_cover", _landCover);
+            conf.getIfSet("land_cover_group", _landCoverGroup);
+            conf.getIfSet("land_cover_lod",   _landCoverLOD);
+        }
+
+        std::vector<Code>     _code;
+        std::vector<Sampler>  _samplers;
+        std::vector<Uniform>  _uniforms;
+        optional<std::string> _landCoverGroup;
+        optional<unsigned>    _landCoverLOD;
+    };
+
+} } // namespace osgEarth::TerrainShader
+
+#endif // OSGEARTH_EXT_TERRAIN_SHADER_OPTIONS
+
diff --git a/src/osgEarthDrivers/tilecache/ReaderWriterTileCache.cpp b/src/osgEarthDrivers/tilecache/ReaderWriterTileCache.cpp
index 9289596..01329f5 100644
--- a/src/osgEarthDrivers/tilecache/ReaderWriterTileCache.cpp
+++ b/src/osgEarthDrivers/tilecache/ReaderWriterTileCache.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -105,7 +105,7 @@ class TileCacheSourceFactory : public TileSourceDriver
     public:
         TileCacheSourceFactory() {}
 
-        virtual const char* className()
+        virtual const char* className() const
         {
             return "TileCache disk cache ReaderWriter";
         }
diff --git a/src/osgEarthDrivers/tilecache/TileCacheOptions b/src/osgEarthDrivers/tilecache/TileCacheOptions
index f276eab..8c78438 100644
--- a/src/osgEarthDrivers/tilecache/TileCacheOptions
+++ b/src/osgEarthDrivers/tilecache/TileCacheOptions
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthDrivers/tileindex/ReaderWriterTileIndex.cpp b/src/osgEarthDrivers/tileindex/ReaderWriterTileIndex.cpp
index e6c2b63..2528782 100644
--- a/src/osgEarthDrivers/tileindex/ReaderWriterTileIndex.cpp
+++ b/src/osgEarthDrivers/tileindex/ReaderWriterTileIndex.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
@@ -108,7 +108,7 @@ public:
 
                     start = osg::Timer::instance()->tick();
                     source = osgEarth::TileSourceFactory::create( opt );                               
-                    TileSource::Status compStatus = source->open();
+                    Status compStatus = source->open();
                     if (compStatus.isOK())
                     {
                         _tileSourceCache.insert( files[i], source.get() );                                                
@@ -165,7 +165,7 @@ class ReaderWriterTileIndex : public TileSourceDriver
 public:
     ReaderWriterTileIndex() {}
 
-    virtual const char* className()
+    virtual const char* className() const
     {
         return "TileIndex Reader";
     }
diff --git a/src/osgEarthDrivers/tileindex/TileIndexOptions b/src/osgEarthDrivers/tileindex/TileIndexOptions
index f1d8deb..9257ec5 100644
--- a/src/osgEarthDrivers/tileindex/TileIndexOptions
+++ b/src/osgEarthDrivers/tileindex/TileIndexOptions
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthDrivers/tileservice/ReaderWriterTileService.cpp b/src/osgEarthDrivers/tileservice/ReaderWriterTileService.cpp
index ab029b2..e6afb48 100644
--- a/src/osgEarthDrivers/tileservice/ReaderWriterTileService.cpp
+++ b/src/osgEarthDrivers/tileservice/ReaderWriterTileService.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -112,7 +112,7 @@ class TileServiceSourceFactory : public TileSourceDriver
     public:
         TileServiceSourceFactory() {}
 
-        virtual const char* className()
+        virtual const char* className() const
         {
             return "TileService Reader";
         }
diff --git a/src/osgEarthDrivers/tileservice/TileServiceOptions b/src/osgEarthDrivers/tileservice/TileServiceOptions
index 5cffb96..68915ec 100644
--- a/src/osgEarthDrivers/tileservice/TileServiceOptions
+++ b/src/osgEarthDrivers/tileservice/TileServiceOptions
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthDrivers/tms/TMSOptions b/src/osgEarthDrivers/tms/TMSOptions
index 9de1f7b..cbfd75d 100644
--- a/src/osgEarthDrivers/tms/TMSOptions
+++ b/src/osgEarthDrivers/tms/TMSOptions
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -57,6 +57,18 @@ namespace osgEarth { namespace Drivers
         virtual ~TMSOptions() { }
 
     public:
+        static Config getMetadata() {
+            return Config::readJSON( OE_MULTILINE(
+                { "name" : "TMS (Tile Map Service)",
+                  "properties": [
+                    { "name": "url",      "description": "Location of the TMS repository", "type": "string", "default": "" },
+                    { "name": "tms_type", "description": "Set to 'google' to invert the Y index", "type": "string", "default": "" },
+                    { "name": "format",   "description": "Image format to assume (e.g. jpeg, png)", "type": "string", "default": "" }
+                  ]
+                }
+            ) );
+        }
+
         Config getConfig() const {
             Config conf = TileSourceOptions::getConfig();
             conf.updateIfSet("url", _url);
diff --git a/src/osgEarthDrivers/tms/TMSPlugin.cpp b/src/osgEarthDrivers/tms/TMSPlugin.cpp
index 8e29479..cb6920a 100644
--- a/src/osgEarthDrivers/tms/TMSPlugin.cpp
+++ b/src/osgEarthDrivers/tms/TMSPlugin.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
@@ -49,7 +49,7 @@ namespace osgEarth { namespace Drivers { namespace TileMapService
             supportsExtension( "osgearth_tms", "Tile Map Service Driver" );
         }
 
-        virtual const char* className()
+        virtual const char* className() const
         {
             return "Tile Map Service Driver";
         }
diff --git a/src/osgEarthDrivers/tms/TMSTileSource b/src/osgEarthDrivers/tms/TMSTileSource
index 6f514ad..bea42a0 100644
--- a/src/osgEarthDrivers/tms/TMSTileSource
+++ b/src/osgEarthDrivers/tms/TMSTileSource
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthDrivers/tms/TMSTileSource.cpp b/src/osgEarthDrivers/tms/TMSTileSource.cpp
index e4bb374..79fe7ac 100644
--- a/src/osgEarthDrivers/tms/TMSTileSource.cpp
+++ b/src/osgEarthDrivers/tms/TMSTileSource.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
@@ -41,7 +41,7 @@ _forceRGB (false)
 }
 
 
-TileSource::Status
+Status
 TMSTileSource::initialize(const osgDB::Options* dbOptions)
 {
     // local copy of options we can modify if necessary.
@@ -54,13 +54,13 @@ TMSTileSource::initialize(const osgDB::Options* dbOptions)
     URI tmsURI = _options.url().value();
     if ( tmsURI.empty() )
     {
-        return Status::Error( "Fail: TMS driver requires a valid \"url\" property" );
+        return Status::Error( Status::ConfigurationError, "Fail: TMS driver requires a valid \"url\" property" );
     }
 
     // A repo is writable only if it's local.
     if ( tmsURI.isRemote() )
     {
-        OE_INFO << LC << "Repo is remote; opening in read-only mode" << std::endl;
+        OE_DEBUG << LC << "Repo is remote; opening in read-only mode" << std::endl;
     }
 
     // Is this a new repo? (You can only create a new repo at a local non-archive URI.)
@@ -75,7 +75,7 @@ TMSTileSource::initialize(const osgDB::Options* dbOptions)
         // new repo REQUIRES a profile:
         if ( !profile )
         {
-            return Status::Error("Fail: profile required to create new TMS repo");
+            return Status::Error(Status::ConfigurationError, "Fail: profile required to create new TMS repo");
         }
     }
 
@@ -87,9 +87,12 @@ TMSTileSource::initialize(const osgDB::Options* dbOptions)
             << "\" for URI \"" << tmsURI.base() << "\"" 
             << std::endl;
 
+        DataExtentList extents;
+
         _tileMap = TMS::TileMap::create( 
             _options.url()->full(),
             profile,
+            extents,
             _options.format().value(),
             _options.tileSize().value(), 
             _options.tileSize().value() );
@@ -99,7 +102,7 @@ TMSTileSource::initialize(const osgDB::Options* dbOptions)
         {
             if ( !_options.format().isSet() )
             {
-                return Status::Error("Cannot create new repo with required [format] property");
+                return Status::Error(Status::ConfigurationError, "Cannot create new repo with required [format] property");
             }
 
             TMS::TileMapReaderWriter::write( _tileMap.get(), tmsURI.full() );
@@ -114,7 +117,7 @@ TMSTileSource::initialize(const osgDB::Options* dbOptions)
 
         if (!_tileMap.valid())
         {
-            return Status::Error( Stringify() << "Failed to read tilemap from " << tmsURI.full() );
+            return Status::Error( Status::ResourceUnavailable, Stringify() << "Failed to read tilemap from " << tmsURI.full() );
         }
 
         OE_INFO << LC
@@ -157,6 +160,7 @@ TMSTileSource::initialize(const osgDB::Options* dbOptions)
             this->getDataExtents().push_back(DataExtent(profile->getExtent(), 0, _tileMap->getMaxLevel()));
         }
     }
+ 
     return STATUS_OK;
 }
 
@@ -215,6 +219,13 @@ TMSTileSource::createImage(const TileKey&    key,
                 }
             }
         }
+        
+        if (image.valid() && _options.coverage() == true)
+        {
+            image->setInternalTextureFormat(GL_LUMINANCE32F_ARB);
+            ImageUtils::markAsUnNormalized(image, true);
+        }
+
         return image.release();
     }
     return 0;
diff --git a/src/osgEarthDrivers/vdatum_egm2008/EGM2008.cpp b/src/osgEarthDrivers/vdatum_egm2008/EGM2008.cpp
index 7cc085b..35cd21d 100644
--- a/src/osgEarthDrivers/vdatum_egm2008/EGM2008.cpp
+++ b/src/osgEarthDrivers/vdatum_egm2008/EGM2008.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -88,7 +88,7 @@ public:
         supportsExtension( "osgearth_vdatum_egm2008", "osgEarth EGM2008 vertical datum" );
     }
 
-    virtual const char* className()
+    virtual const char* className() const
     {
         return "osgEarth EGM2008 vertical datum";
     }
diff --git a/src/osgEarthDrivers/vdatum_egm2008/EGM2008Grid.h b/src/osgEarthDrivers/vdatum_egm2008/EGM2008Grid.h
index 5068cd8..4ed52c3 100644
--- a/src/osgEarthDrivers/vdatum_egm2008/EGM2008Grid.h
+++ b/src/osgEarthDrivers/vdatum_egm2008/EGM2008Grid.h
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthDrivers/vdatum_egm84/EGM84.cpp b/src/osgEarthDrivers/vdatum_egm84/EGM84.cpp
index 4184902..9fd604b 100644
--- a/src/osgEarthDrivers/vdatum_egm84/EGM84.cpp
+++ b/src/osgEarthDrivers/vdatum_egm84/EGM84.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -88,7 +88,7 @@ public:
         supportsExtension( "osgearth_vdatum_egm84", "osgEarth EGM84 vertical datum" );
     }
 
-    virtual const char* className()
+    virtual const char* className() const
     {
         return "osgEarth EGM84 vertical datum";
     }
diff --git a/src/osgEarthDrivers/vdatum_egm84/EGM84Grid.h b/src/osgEarthDrivers/vdatum_egm84/EGM84Grid.h
index fda23fa..e239fa7 100644
--- a/src/osgEarthDrivers/vdatum_egm84/EGM84Grid.h
+++ b/src/osgEarthDrivers/vdatum_egm84/EGM84Grid.h
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthDrivers/vdatum_egm96/EGM96.cpp b/src/osgEarthDrivers/vdatum_egm96/EGM96.cpp
index 4838895..a935195 100644
--- a/src/osgEarthDrivers/vdatum_egm96/EGM96.cpp
+++ b/src/osgEarthDrivers/vdatum_egm96/EGM96.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -90,7 +90,7 @@ public:
         supportsExtension( "osgearth_vdatum_egm96", "osgEarth EGM96 vertical datum" );
     }
 
-    virtual const char* className()
+    virtual const char* className() const
     {
         return "osgEarth EGM96 vertical datum";
     }
diff --git a/src/osgEarthDrivers/vdatum_egm96/EGM96Grid.h b/src/osgEarthDrivers/vdatum_egm96/EGM96Grid.h
index e7090d2..ff7c566 100644
--- a/src/osgEarthDrivers/vdatum_egm96/EGM96Grid.h
+++ b/src/osgEarthDrivers/vdatum_egm96/EGM96Grid.h
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -22621,8 +22621,7 @@ static short s_egm96grid[] = {
 -7750,-7848,-7933,-8007,-8079,-8160,-8252,-8344,-8425,-8497,-8574,-8657,-8738,-8811,-8879,-8947,-9011,-9076,-9147,-9222,-9288,
 -9343,-9397,-9456,-9507,-9543,-9572,-9605,-9632,-9639,-9636,-9642,-9664,-9700,-9754,-9827,-9893,-9928,-9940,-9961,-9993,-10010,
 -10009,-10017,-10039,-10035,-9973,-9876,-9800,-9770,-9789,-9848,-9934,-10013,-10066,-10105,-10133,-10110,-10001,-9840,-9701,-9611,-9534,
--9458,
--9411-9404,-9403,-9387,-9403,-9485,-9583,-9613,-9561,-9489,-9443,-9404,-9347,-9279,-9210,-9126,-9009,-8874,-8750,-8651,
+-9458,-9411,-9404,-9403,-9387,-9403,-9485,-9583,-9613,-9561,-9489,-9443,-9404,-9347,-9279,-9210,-9126,-9009,-8874,-8750,-8651,
 -8559,-8455,-8324,-8168,-8002,-7853,-7730,-7616,-7484,-7325,-7150,-6977,-6818,-6678,-6549,-6418,-6280,-6142,-6018,-5909,-5815,
 -5751,-5736,-5761,-5788,-5797,-5819,-5891,-5987,-6002,-5854,-5560,-5222,-4923,-4685,-4497,-4356,-4241,-4104,-3916,-3711,-3554,
 -3461,-3389,-3292,-3164,-3027,-2895,-2778,-2683,-2603,-2510,-2384,-2238,-2102,-1987,-1889,-1808,-1748,-1703,-1662,-1620,-1578,
@@ -22759,1408 +22758,1379 @@ static short s_egm96grid[] = {
 -7245,-7345,-7440,-7538,-7642,-7746,-7841,-7928,-8012,-8098,-8187,-8274,-8358,-8442,-8530,-8622,-8711,-8790,-8863,-8932,-8997,
 -9055,-9112,-9174,-9239,-9299,-9354,-9412,-9469,-9514,-9548,-9587,-9631,-9662,-9663,-9648,-9643,-9658,-9696,-9763,-9853,-9932,
 -9966,-9966,-9970,-9993,-10019,-10036,-10052,-10068,-10072,-10056,-10028,-9987,-9936,-9912,-9968,-10100,-10228,-10284,-10286,-10274,-10231,
--10114,
--9944,-9786,-9652,-9506,-9358,-9283,-9305,-9351,-9361,-9381,-9479,-9617,-9682,-9639,-9562,-9515,-9483,-9425,-9347,-9272,-9190,
--9076,-8934,-8799,-8685,-8582,-8474,-8351,-8209,-8050,-7895,-7762,-7642,-7508,-7350,-7184,-7027,-6875,-6717,-6550,-6381,-6216,
--6063,-5931,-5822,-5730,-5661,-5630,-5652,-5718,-5798,-5874,-5949,-6008,-6001,-5867,-5597,-5258,-4937,-4688,-4506,-4356,-4199,
--4012,-3806,-3622,-3493,-3406,-3320,-3210,-3085,-2963,-2840,-2711,-2584,-2471,-2370,-2270,-2164,-2053,-1936,-1817,-1713,-1636,
--1583,-1532,-1476,-1421,-1371,-1312,-1235,-1147,-1065,-991,-916,-834,-749,-664,-575,-479,-381,-285,-184,-73,41,
-146,240,332,431,529,619,708,802,900,998,1101,1218,1337,1436,1507,1564,1627,1707,1804,1913,2025,
-2132,2243,2360,2473,2574,2676,2796,2929,3046,3138,3229,3326,3402,3428,3428,3455,3543,3691,3878,4067,4216,
-4317,4419,4574,4768,4937,5042,5106,5161,5214,5257,5286,5305,5326,5370,5445,5516,5542,5544,5585,5688,5825,
-5999,6248,6554,6802,6892,6855,6781,6712,6667,6710,6887,7109,7219,7192,7137,7084,6921,6603,6288,6126,6015,
-5747,5357,5156,5354,5803,6193,6392,6484,6562,6618,6628,6621,6625,6620,6585,6545,6532,6541,6548,6551,6558,
-6562,6561,6568,6581,6572,6545,6569,6691,6830,6826,6624,6359,6213,6222,6269,6246,6159,6078,6043,6040,6048,
-6072,6131,6225,6321,6373,6376,6368,6382,6399,6384,6342,6313,6311,6308,6288,6280,6303,6324,6306,6263,6234,
-6228,6222,6211,6213,6223,6213,6178,6145,6126,6094,6038,5988,5983,6012,6037,6040,6025,5994,5942,5888,5864,
-5868,5861,5820,5782,5788,5810,5757,5579,5352,5208,5189,5209,5192,5191,5314,5534,5668,5587,5375,5212,5154,
-5114,5032,4960,4946,4941,4896,4867,4947,5104,5193,5122,4954,4804,4711,4636,4557,4501,4499,4550,4624,4677,
-4664,4566,4423,4302,4232,4184,4124,4047,3974,3914,3860,3812,3778,3755,3728,3683,3623,3564,3516,3474,3429,
-3375,3320,3275,3239,3203,3156,3101,3051,3020,3009,3005,2983,2932,2864,2796,2730,2663,2627,2673,2804,2928,
-2943,2844,2724,2658,2632,2593,2538,2516,2558,2642,2714,2730,2678,2584,2494,2433,2383,2323,2266,2238,2232,
-2216,2176,2137,2115,2096,2062,2014,1965,1909,1843,1783,1752,1751,1758,1755,1738,1708,1673,1645,1628,1618,
-1602,1580,1558,1540,1521,1502,1485,1466,1441,1419,1412,1422,1441,1459,1475,1480,1467,1434,1391,1342,1282,
-1214,1151,1109,1087,1079,1078,1077,1069,1053,1041,1045,1062,1081,1095,1100,1096,1090,1089,1094,1097,1096,
-1101,1122,1150,1169,1182,1199,1214,1215,1206,1208,1231,1262,1286,1304,1319,1331,1337,1343,1353,1361,1371,
-1390,1413,1418,1399,1389,1414,1455,1461,1424,1384,1379,1406,1449,1500,1545,1548,1500,1443,1431,1457,1470,
-1445,1412,1398,1391,1365,1328,1302,1293,1285,1274,1266,1258,1236,1197,1158,1131,1114,1097,1076,1055,1035,
-1016,997,977,950,917,883,854,828,801,775,751,727,704,684,665,645,624,604,587,568,543,
-513,482,451,418,382,345,310,277,246,217,187,157,127,98,69,38,4,-31,-67,-102,-136,
--173,-210,-248,-286,-326,-368,-411,-452,-495,-536,-576,-615,-658,-705,-753,-797,-841,-888,-936,-978,-1013,
--1045,-1078,-1113,-1150,-1193,-1237,-1278,-1316,-1354,-1397,-1443,-1488,-1534,-1583,-1633,-1680,-1723,-1762,-1796,-1828,-1863,
--1908,-1959,-2007,-2049,-2087,-2124,-2163,-2202,-2241,-2279,-2315,-2350,-2382,-2413,-2443,-2474,-2509,-2546,-2582,-2617,-2653,
--2688,-2720,-2748,-2774,-2801,-2830,-2860,-2890,-2920,-2949,-2978,-3007,-3037,-3066,-3092,-3117,-3142,-3167,-3190,-3209,-3224,
--3240,-3257,-3274,-3287,-3295,-3304,-3317,-3333,-3346,-3357,-3365,-3371,-3377,-3383,-3391,-3401,-3409,-3411,-3406,-3396,-3387,
--3384,-3386,-3389,-3388,-3385,-3378,-3368,-3357,-3347,-3339,-3329,-3315,-3300,-3284,-3263,-3236,-3210,-3188,-3166,-3141,-3113,
--3087,-3061,-3032,-2997,-2958,-2918,-2881,-2848,-2815,-2779,-2740,-2703,-2668,-2632,-2596,-2565,-2537,-2507,-2470,-2432,-2396,
--2360,-2321,-2282,-2244,-2205,-2162,-2118,-2077,-2035,-1989,-1944,-1902,-1861,-1818,-1772,-1728,-1686,-1644,-1603,-1561,-1518,
--1472,-1429,-1393,-1357,-1317,-1277,-1243,-1212,-1178,-1142,-1108,-1075,-1041,-1009,-983,-955,-920,-882,-851,-826,-800,
--769,-741,-718,-693,-664,-635,-607,-577,-544,-512,-482,-451,-420,-389,-356,-319,-285,-259,-236,-207,-180,
--159,-139,-107,-66,-31,-5,23,60,96,128,165,206,242,276,318,370,416,453,495,543,585,
-620,667,725,773,809,861,944,1027,1080,1113,1151,1178,1157,1092,1040,1048,1112,1192,1251,1281,1305,
-1356,1433,1489,1473,1385,1281,1210,1182,1170,1159,1183,1300,1512,1720,1795,1722,1626,1632,1734,1836,1867,
-1808,1645,1393,1143,978,852,643,350,162,260,604,963,1111,955,555,72,-304,-483,-523,-540,-585,
--640,-692,-748,-799,-826,-835,-855,-892,-928,-964,-1016,-1083,-1139,-1175,-1197,-1201,-1179,-1152,-1162,-1209,-1251,
--1269,-1287,-1336,-1418,-1529,-1673,-1837,-1985,-2099,-2196,-2291,-2371,-2432,-2494,-2569,-2634,-2668,-2691,-2730,-2776,-2800,
--2800,-2803,-2826,-2864,-2904,-2940,-2970,-2995,-3019,-3042,-3057,-3069,-3100,-3157,-3216,-3250,-3268,-3297,-3339,-3374,-3394,
--3406,-3413,-3411,-3410,-3427,-3461,-3503,-3561,-3665,-3813,-3958,-4049,-4080,-4084,-4088,-4095,-4099,-4097,-4090,-4082,-4078,
--4077,-4077,-4071,-4055,-4028,-3989,-3947,-3910,-3876,-3831,-3772,-3705,-3636,-3565,-3490,-3421,-3359,-3300,-3235,-3165,-3098,
--3038,-2987,-2942,-2898,-2846,-2782,-2713,-2640,-2565,-2488,-2416,-2349,-2281,-2208,-2134,-2061,-1985,-1904,-1825,-1752,-1681,
--1604,-1524,-1447,-1367,-1281,-1189,-1104,-1029,-961,-897,-837,-777,-710,-636,-565,-506,-455,-400,-333,-263,-199,
--142,-89,-35,17,64,109,158,209,256,293,328,367,410,449,482,514,549,588,624,655,685,
-720,762,808,854,898,935,966,996,1034,1079,1122,1159,1194,1233,1271,1300,1324,1356,1397,1435,1465,
-1490,1522,1567,1623,1682,1726,1741,1731,1725,1744,1781,1817,1841,1854,1864,1874,1889,1911,1935,1951,1959,
-1969,1987,2010,2034,2059,2087,2115,2136,2150,2160,2177,2202,2230,2256,2290,2353,2454,2573,2685,2783,2884,
-2997,3109,3188,3216,3198,3162,3136,3130,3142,3161,3184,3208,3233,3260,3286,3297,3277,3235,3196,3179,3169,
-3142,3099,3064,3048,3041,3027,3005,2977,2938,2887,2836,2800,2779,2767,2759,2753,2749,2752,2767,2791,2806,
-2808,2803,2788,2753,2698,2653,2642,2655,2659,2645,2623,2625,2637,2650,2655,2653,2645,2626,2595,2558,2523,
-2493,2470,2455,2446,2431,2402,2369,2345,2334,2324,2306,2283,2259,2232,2199,2168,2156,2171,2200,2219,2213,
-2190,2168,2155,2145,2133,2115,2089,2055,2017,1988,1979,1988,2002,2004,1983,1944,1900,1864,1826,1766,1680,
-1594,1542,1525,1510,1462,1379,1283,1194,1114,1030,933,826,728,658,619,588,535,452,353,262,185,
-113,36,-36,-92,-128,-156,-189,-222,-247,-260,-268,-273,-283,-305,-347,-399,-442,-471,-498,-532,-561,
--581,-611,-672,-755,-823,-857,-870,-877,-879,-867,-851,-841,-835,-824,-811,-811,-826,-845,-859,-878,-910,
--950,-989,-1022,-1045,-1055,-1054,-1058,-1084,-1129,-1168,-1180,-1170,-1166,-1188,-1232,-1271,-1290,-1294,-1290,-1276,-1248,
--1220,-1206,-1199,-1180,-1147,-1119,-1105,-1091,-1067,-1050,-1057,-1072,-1069,-1058,-1079,-1139,-1192,-1187,-1138,-1102,-1121,
--1192,-1293,-1410,-1538,-1672,-1806,-1933,-2044,-2136,-2225,-2331,-2444,-2524,-2548,-2535,-2532,-2556,-2592,-2621,-2650,-2695,
--2762,-2840,-2918,-2990,-3054,-3108,-3155,-3203,-3255,-3311,-3368,-3428,-3494,-3569,-3655,-3748,-3836,-3907,-3966,-4045,-4172,
--4352,-4560,-4768,-4956,-5112,-5221,-5282,-5314,-5335,-5356,-5373,-5392,-5419,-5457,-5505,-5557,-5606,-5631,-5605,-5532,-5444,
--5376,-5337,-5319,-5316,-5330,-5356,-5380,-5401,-5433,-5479,-5530,-5573,-5607,-5637,-5666,-5697,-5736,-5788,-5847,-5906,-5967,
--6042,-6135,-6238,-6341,-6440,-6540,-6644,-6749,-6848,-6943,-7037,-7136,-7238,-7338,-7436,-7534,-7637,-7738,-7833,-7922,-8013,
--8105,-8194,-8276,-8354,-8439,-8534,-8631,-8719,-8797,-8870,-8941,-9006,-9065,-9125,-9188,-9250,-9305,-9358,-9417,-9474,-9518,
--9553,-9597,-9647,-9680,-9680,-9661,-9648,-9655,-9685,-9750,-9846,-9937,-9983,-9988,-9990,-10011,-10041,-10065,-10083,-10096,-10099,
--10096,-10097,-10091,-10067,-10056,-10112,-10230,-10332,-10358,-10336,-10313,-10273,-10162,-9992,-9824,-9674,-9509,-9343,-9253,-9272,-9331,
--9365,
--9410-9525,-9671,-9736,-9689,-9604,-9551,-9515,-9455,-9374,-9295,-9210,-9096,-8955,-8818,-8698,-8586,-8472,-8351,-8214,
--8061,-7910,-7781,-7663,-7529,-7367,-7198,-7041,-6888,-6725,-6548,-6369,-6197,-6038,-5900,-5786,-5691,-5616,-5577,-5595,-5670,
--5773,-5870,-5940,-5968,-5932,-5801,-5570,-5277,-4984,-4737,-4540,-4365,-4180,-3971,-3756,-3576,-3453,-3371,-3286,-3176,-3051,
--2926,-2802,-2669,-2532,-2404,-2295,-2199,-2106,-2010,-1902,-1785,-1673,-1583,-1516,-1456,-1393,-1333,-1283,-1231,-1161,-1077,
--995,-925,-856,-779,-697,-619,-541,-454,-358,-257,-151,-32,95,214,314,405,499,597,692,787,889,
-995,1094,1189,1292,1402,1498,1567,1619,1680,1767,1875,1987,2087,2176,2270,2380,2496,2605,2719,2853,2992,
-3103,3177,3237,3295,3331,3343,3369,3458,3618,3817,4025,4214,4354,4443,4529,4663,4828,4961,5033,5083,5152,
-5233,5293,5323,5339,5364,5409,5466,5512,5535,5571,5674,5854,6070,6291,6511,6706,6819,6821,6747,6645,6548,
-6515,6639,6925,7211,7317,7245,7131,7022,6823,6503,6192,5990,5796,5471,5115,5018,5309,5798,6197,6411,6523,
-6609,6662,6672,6671,6678,6670,6634,6595,6579,6579,6577,6575,6582,6590,6598,6615,6640,6650,6640,6655,6719,
-6765,6687,6490,6311,6278,6361,6423,6378,6266,6171,6128,6125,6149,6203,6280,6352,6392,6395,6386,6392,6411,
-6418,6394,6358,6339,6333,6312,6274,6253,6266,6284,6275,6254,6253,6270,6276,6261,6244,6234,6219,6197,6182,
-6170,6140,6085,6038,6025,6037,6042,6032,6014,5984,5934,5880,5852,5850,5842,5812,5791,5814,5845,5796,5624,
-5402,5258,5233,5251,5236,5229,5321,5488,5589,5528,5379,5276,5242,5195,5099,5019,4999,4989,4937,4890,4930,
-5038,5102,5053,4940,4841,4771,4699,4621,4577,4604,4699,4823,4905,4876,4720,4508,4345,4275,4252,4206,4121,
-4032,3966,3918,3873,3829,3793,3762,3721,3662,3594,3538,3500,3468,3425,3365,3307,3266,3238,3204,3152,3091,
-3046,3028,3024,3002,2950,2889,2841,2797,2736,2669,2650,2701,2771,2781,2718,2640,2602,2594,2573,2530,2500,
-2516,2578,2647,2678,2652,2586,2519,2467,2412,2345,2284,2250,2236,2215,2181,2146,2117,2087,2056,2024,1978,
-1901,1811,1753,1750,1774,1786,1775,1754,1729,1697,1666,1646,1634,1618,1595,1574,1558,1542,1526,1514,1502,
-1486,1470,1464,1475,1495,1517,1532,1533,1510,1468,1421,1375,1320,1253,1188,1142,1122,1122,1129,1129,1112,
-1084,1063,1063,1079,1097,1109,1115,1114,1107,1101,1098,1095,1090,1093,1112,1139,1158,1168,1179,1193,1203,
-1207,1216,1241,1275,1306,1327,1339,1344,1346,1349,1355,1361,1373,1401,1436,1457,1453,1440,1437,1433,1411,
-1380,1372,1399,1443,1489,1541,1585,1582,1525,1465,1460,1499,1525,1507,1476,1461,1451,1421,1382,1358,1349,
-1338,1318,1302,1292,1277,1246,1211,1184,1162,1139,1114,1093,1074,1056,1036,1014,989,960,928,897,867,
-838,811,784,759,737,719,702,682,657,633,613,596,575,549,520,489,458,424,387,348,313,
-281,253,225,196,167,139,108,73,36,0,-35,-70,-105,-142,-179,-215,-252,-291,-333,-376,-418,
--460,-501,-541,-580,-622,-667,-712,-753,-796,-845,-896,-941,-977,-1012,-1048,-1083,-1119,-1160,-1204,-1246,-1282,
--1319,-1362,-1409,-1455,-1502,-1551,-1599,-1644,-1687,-1730,-1770,-1803,-1836,-1875,-1919,-1962,-1999,-2036,-2074,-2114,-2154,
--2191,-2225,-2258,-2289,-2321,-2353,-2383,-2415,-2450,-2486,-2520,-2552,-2584,-2618,-2652,-2684,-2712,-2738,-2766,-2797,-2830,
--2861,-2890,-2918,-2946,-2977,-3008,-3038,-3065,-3090,-3115,-3140,-3162,-3179,-3193,-3209,-3226,-3240,-3248,-3256,-3269,-3286,
--3300,-3309,-3316,-3322,-3326,-3331,-3337,-3345,-3353,-3356,-3354,-3347,-3340,-3340,-3346,-3352,-3352,-3346,-3337,-3325,-3313,
--3305,-3299,-3290,-3278,-3264,-3250,-3233,-3211,-3189,-3168,-3148,-3121,-3090,-3059,-3032,-3004,-2973,-2937,-2898,-2860,-2823,
--2786,-2747,-2708,-2671,-2636,-2600,-2567,-2540,-2516,-2488,-2454,-2419,-2385,-2350,-2313,-2277,-2243,-2205,-2161,-2116,-2074,
--2032,-1985,-1940,-1900,-1861,-1817,-1770,-1726,-1685,-1644,-1603,-1564,-1523,-1480,-1436,-1398,-1362,-1325,-1286,-1251,-1218,
--1183,-1147,-1113,-1081,-1048,-1016,-990,-964,-931,-896,-867,-842,-814,-782,-754,-732,-710,-684,-655,-626,-591,
--554,-520,-491,-462,-433,-403,-368,-330,-298,-275,-254,-224,-192,-171,-154,-127,-90,-55,-26,5,40,
-71,104,147,197,237,271,313,364,410,448,490,535,569,596,641,705,760,797,847,925,1001,
-1045,1072,1109,1141,1133,1089,1055,1062,1104,1157,1196,1203,1184,1175,1200,1235,1234,1196,1167,1175,1194,
-1181,1132,1106,1185,1395,1645,1789,1771,1702,1735,1897,2079,2166,2122,1959,1705,1415,1149,910,663,435,
-344,480,798,1138,1324,1235,854,318,-143,-382,-445,-478,-551,-630,-675,-701,-734,-774,-810,-837,-854,
--872,-913,-989,-1075,-1137,-1162,-1155,-1111,-1045,-1008,-1046,-1132,-1192,-1196,-1185,-1205,-1272,-1389,-1557,-1748,-1905,
--2010,-2091,-2172,-2241,-2295,-2361,-2452,-2533,-2571,-2589,-2626,-2679,-2716,-2730,-2744,-2775,-2816,-2858,-2898,-2929,-2948,
--2963,-2985,-3007,-3024,-3051,-3097,-3144,-3167,-3172,-3185,-3215,-3248,-3276,-3304,-3326,-3329,-3322,-3327,-3351,-3383,-3432,
--3528,-3675,-3824,-3922,-3961,-3972,-3984,-3999,-4013,-4023,-4029,-4031,-4030,-4029,-4029,-4025,-4012,-3986,-3947,-3907,-3872,
--3842,-3804,-3753,-3696,-3636,-3572,-3505,-3439,-3377,-3315,-3247,-3177,-3110,-3049,-2995,-2945,-2891,-2828,-2757,-2686,-2617,
--2546,-2472,-2400,-2333,-2261,-2184,-2108,-2036,-1962,-1883,-1807,-1739,-1672,-1595,-1512,-1432,-1355,-1275,-1192,-1111,-1032,
--952,-875,-810,-754,-694,-620,-541,-470,-405,-338,-262,-187,-124,-70,-16,40,92,135,176,224,281,
-336,379,412,444,479,513,544,575,610,645,677,705,736,774,819,865,911,953,986,1011,1034,
-1068,1112,1153,1184,1211,1245,1279,1302,1319,1347,1392,1441,1480,1511,1545,1589,1644,1702,1742,1747,1721,
-1696,1703,1743,1792,1828,1848,1859,1867,1880,1898,1914,1924,1931,1944,1963,1983,2001,2019,2043,2068,2089,
-2102,2111,2126,2153,2184,2206,2218,2244,2305,2397,2494,2582,2673,2785,2915,3038,3124,3159,3150,3118,3088,
-3073,3078,3101,3134,3168,3194,3207,3206,3188,3160,3136,3127,3122,3105,3074,3045,3030,3023,3012,2995,2967,
-2925,2871,2818,2783,2769,2768,2770,2768,2764,2764,2775,2794,2808,2808,2800,2786,2760,2719,2676,2648,2637,
-2630,2623,2615,2615,2630,2649,2661,2661,2643,2607,2556,2503,2458,2427,2405,2390,2378,2365,2344,2313,2277,
-2240,2208,2184,2168,2155,2136,2111,2091,2097,2135,2185,2217,2216,2190,2159,2136,2127,2130,2135,2128,2100,
-2067,2049,2051,2058,2054,2034,1997,1945,1883,1825,1776,1724,1660,1591,1533,1484,1429,1360,1288,1227,1175,
-1114,1029,926,822,735,672,626,578,511,421,318,219,132,50,-33,-112,-173,-213,-245,-285,-328,
--361,-376,-376,-371,-368,-379,-409,-449,-482,-505,-532,-566,-595,-609,-627,-676,-758,-847,-918,-964,-986,
--982,-961,-942,-930,-913,-882,-851,-839,-845,-856,-867,-889,-924,-965,-1004,-1043,-1079,-1099,-1097,-1090,-1099,
--1132,-1171,-1194,-1190,-1176,-1182,-1218,-1266,-1301,-1314,-1313,-1297,-1260,-1220,-1199,-1202,-1199,-1176,-1152,-1148,-1152,
--1139,-1114,-1108,-1121,-1134,-1143,-1174,-1223,-1244,-1208,-1153,-1142,-1193,-1276,-1374,-1497,-1651,-1809,-1945,-2054,-2149,
--2241,-2341,-2461,-2589,-2681,-2704,-2678,-2655,-2667,-2700,-2735,-2770,-2815,-2870,-2928,-2989,-3057,-3126,-3189,-3245,-3300,
--3355,-3405,-3455,-3515,-3591,-3676,-3761,-3845,-3925,-3995,-4059,-4144,-4270,-4435,-4618,-4807,-4995,-5162,-5273,-5317,-5326,
--5340,-5368,-5392,-5407,-5435,-5487,-5550,-5595,-5606,-5579,-5515,-5437,-5377,-5357,-5358,-5352,-5338,-5339,-5368,-5406,-5437,
--5467,-5509,-5561,-5606,-5640,-5670,-5704,-5743,-5782,-5822,-5867,-5919,-5983,-6060,-6147,-6239,-6333,-6433,-6538,-6643,-6744,
--6840,-6934,-7030,-7129,-7229,-7330,-7428,-7525,-7624,-7723,-7821,-7917,-8013,-8107,-8195,-8275,-8354,-8443,-8542,-8638,-8722,
--8797,-8870,-8940,-9004,-9065,-9131,-9203,-9268,-9320,-9369,-9425,-9483,-9530,-9570,-9616,-9665,-9696,-9694,-9675,-9659,-9655,
--9674,-9733,-9833,-9936,-9995,-10007,-10009,-10029,-10058,-10084,-10105,-10118,-10121,-10124,-10140,-10163,-10174,-10189,-10243,-10332,-10397,
--10397,
--10365,-10345,-10310,-10204,-10032,-9855,-9699,-9539,-9382,-9294,-9305,-9363,-9415,-9486,-9614,-9754,-9807,-9753,-9664,-9604,-9559,
--9492,-9406,-9323,-9233,-9118,-8980,-8842,-8714,-8590,-8468,-8343,-8206,-8056,-7910,-7788,-7675,-7538,-7370,-7195,-7035,-6882,
--6721,-6546,-6366,-6190,-6023,-5873,-5743,-5635,-5552,-5512,-5533,-5612,-5723,-5827,-5889,-5891,-5833,-5718,-5549,-5330,-5076,
--4817,-4579,-4366,-4159,-3943,-3728,-3549,-3426,-3345,-3268,-3165,-3038,-2900,-2762,-2622,-2484,-2355,-2242,-2140,-2045,-1950,
--1850,-1742,-1631,-1531,-1448,-1376,-1308,-1247,-1197,-1148,-1082,-998,-915,-848,-787,-716,-637,-563,-497,-423,-330,
--225,-112,11,147,280,390,481,569,661,756,857,968,1082,1183,1273,1365,1464,1555,1624,1680,1749,
-1847,1963,2074,2165,2242,2326,2431,2546,2660,2780,2917,3051,3146,3193,3220,3249,3279,3317,3399,3550,3752,
-3961,4155,4322,4448,4535,4624,4756,4905,5006,5042,5070,5141,5236,5310,5348,5375,5410,5447,5477,5507,5560,
-5669,5857,6108,6371,6591,6733,6783,6756,6693,6618,6527,6432,6430,6635,7013,7352,7459,7355,7182,7001,6764,
-6469,6198,5959,5639,5202,4853,4863,5258,5785,6186,6413,6550,6652,6704,6712,6711,6715,6705,6672,6639,6622,
-6612,6602,6598,6608,6622,6636,6660,6696,6722,6722,6705,6675,6606,6475,6330,6268,6334,6456,6524,6497,6429,
-6381,6362,6356,6361,6384,6416,6432,6425,6411,6408,6418,6425,6415,6388,6360,6345,6336,6314,6284,6265,6267,
-6274,6273,6277,6303,6337,6348,6328,6294,6261,6231,6208,6199,6194,6172,6128,6083,6056,6042,6030,6016,6004,
-5982,5941,5895,5865,5854,5844,5826,5817,5831,5844,5802,5677,5510,5379,5322,5303,5279,5264,5304,5385,5427,
-5385,5310,5274,5267,5223,5135,5063,5044,5033,4983,4924,4917,4961,4991,4967,4912,4862,4815,4759,4705,4687,
-4728,4824,4942,5015,4966,4777,4536,4365,4313,4314,4280,4189,4092,4029,3990,3944,3885,3832,3793,3753,3694,
-3620,3557,3523,3507,3477,3420,3349,3291,3256,3230,3188,3130,3075,3041,3024,2999,2953,2901,2862,2831,2784,
-2714,2649,2620,2620,2621,2614,2610,2617,2617,2589,2535,2479,2453,2473,2528,2585,2605,2576,2515,2448,2389,
-2341,2305,2280,2255,2225,2192,2154,2110,2073,2065,2076,2050,1950,1816,1738,1749,1797,1816,1797,1769,1744,
-1715,1681,1654,1636,1616,1593,1574,1564,1554,1543,1534,1529,1522,1514,1513,1524,1543,1563,1574,1569,1540,
-1493,1447,1406,1359,1297,1231,1181,1161,1165,1178,1179,1157,1120,1093,1090,1105,1120,1128,1133,1135,1131,
-1121,1111,1102,1095,1095,1110,1134,1153,1164,1174,1189,1205,1217,1231,1254,1284,1313,1333,1345,1350,1351,
-1354,1357,1361,1371,1396,1434,1468,1480,1468,1444,1416,1393,1393,1421,1463,1495,1523,1563,1600,1594,1532,
-1469,1461,1501,1534,1529,1512,1506,1498,1469,1432,1414,1411,1398,1368,1340,1325,1312,1290,1260,1231,1206,
-1180,1155,1135,1118,1098,1075,1051,1030,1006,979,949,919,889,859,828,796,768,747,730,711,685,
-658,635,618,602,581,556,528,499,466,428,385,345,311,282,256,230,204,176,143,106,67,
-29,-6,-41,-77,-112,-146,-178,-213,-251,-292,-334,-377,-419,-462,-504,-545,-588,-633,-673,-710,-750,
--797,-846,-890,-928,-968,-1010,-1050,-1088,-1130,-1174,-1217,-1253,-1289,-1330,-1375,-1420,-1466,-1515,-1561,-1604,-1646,
--1691,-1734,-1771,-1805,-1840,-1879,-1916,-1949,-1983,-2021,-2060,-2098,-2134,-2167,-2198,-2229,-2261,-2293,-2324,-2354,-2386,
--2419,-2449,-2476,-2505,-2539,-2578,-2615,-2647,-2674,-2702,-2732,-2765,-2798,-2829,-2859,-2889,-2921,-2954,-2985,-3012,-3036,
--3060,-3087,-3113,-3132,-3147,-3163,-3181,-3197,-3207,-3216,-3229,-3244,-3257,-3267,-3274,-3279,-3282,-3284,-3287,-3292,-3299,
--3305,-3307,-3305,-3303,-3305,-3313,-3319,-3319,-3312,-3301,-3288,-3276,-3267,-3260,-3251,-3239,-3225,-3213,-3199,-3182,-3163,
--3145,-3123,-3095,-3062,-3030,-3003,-2976,-2947,-2914,-2878,-2839,-2799,-2758,-2718,-2681,-2647,-2613,-2579,-2547,-2521,-2496,
--2467,-2433,-2401,-2371,-2338,-2302,-2267,-2234,-2196,-2152,-2108,-2069,-2028,-1982,-1937,-1898,-1859,-1814,-1767,-1725,-1686,
--1645,-1604,-1566,-1529,-1488,-1445,-1406,-1371,-1334,-1296,-1260,-1225,-1188,-1152,-1121,-1093,-1060,-1027,-998,-971,-940,
--907,-879,-856,-829,-799,-771,-747,-722,-694,-668,-641,-607,-569,-534,-503,-472,-442,-413,-382,-348,-318,
--297,-276,-248,-215,-189,-167,-140,-108,-78,-48,-12,24,53,82,127,182,229,265,308,358,400,
-433,474,521,558,587,630,692,748,791,845,918,981,1009,1027,1061,1095,1100,1086,1088,1113,1150,
-1188,1216,1205,1150,1093,1079,1095,1104,1108,1147,1222,1280,1272,1200,1117,1110,1250,1504,1730,1809,1794,
-1848,2040,2262,2368,2325,2181,1967,1678,1329,975,688,535,559,747,1030,1318,1506,1474,1144,596,61,
--268,-397,-460,-540,-610,-633,-635,-663,-724,-784,-819,-831,-851,-907,-997,-1081,-1126,-1127,-1086,-1003,-911,
--880,-948,-1058,-1116,-1106,-1091,-1121,-1198,-1320,-1491,-1680,-1826,-1909,-1968,-2037,-2102,-2159,-2235,-2339,-2429,-2469,
--2486,-2526,-2589,-2639,-2667,-2691,-2726,-2769,-2818,-2868,-2900,-2907,-2909,-2930,-2961,-2985,-3006,-3042,-3086,-3114,-3125,
--3140,-3167,-3193,-3215,-3239,-3260,-3265,-3257,-3256,-3268,-3283,-3311,-3385,-3512,-3653,-3759,-3818,-3849,-3874,-3898,-3923,
--3949,-3972,-3987,-3993,-3993,-3989,-3979,-3964,-3941,-3910,-3874,-3840,-3807,-3770,-3725,-3675,-3623,-3568,-3509,-3449,-3389,
--3324,-3254,-3184,-3115,-3051,-2990,-2931,-2870,-2803,-2733,-2666,-2602,-2534,-2464,-2395,-2329,-2256,-2176,-2099,-2030,-1960,
--1884,-1808,-1741,-1676,-1601,-1518,-1435,-1355,-1275,-1194,-1115,-1035,-950,-865,-790,-730,-669,-595,-514,-436,-363,
--287,-206,-131,-70,-19,33,91,143,183,217,260,317,377,427,464,493,522,552,585,621,657,
-689,715,739,770,810,858,905,948,983,1009,1026,1043,1074,1117,1157,1184,1206,1236,1267,1285,1292,
-1312,1357,1418,1477,1526,1568,1607,1649,1693,1729,1738,1721,1701,1709,1747,1795,1830,1850,1860,1869,1878,
-1887,1894,1897,1904,1919,1937,1951,1961,1974,1995,2019,2041,2057,2068,2082,2109,2145,2175,2190,2201,2232,
-2285,2347,2407,2474,2564,2682,2813,2934,3021,3062,3064,3045,3025,3018,3031,3064,3103,3131,3141,3135,3125,
-3115,3109,3107,3104,3087,3054,3018,2996,2989,2987,2977,2952,2910,2856,2805,2773,2763,2767,2771,2770,2765,
-2764,2773,2789,2800,2800,2793,2783,2769,2745,2714,2682,2654,2630,2615,2621,2611,2619,2635,2646,2638,2605,
-2550,2484,2420,2368,2328,2297,2275,2265,2263,2260,2241,2201,2148,2097,2062,2043,2035,2029,2024,2028,2054,
-2106,2164,2200,2200,2175,2144,2124,2124,2145,2173,2183,2170,2154,2154,2157,2134,2077,2007,1949,1899,1843,
-1781,1721,1667,1615,1561,1504,1437,1357,1274,1208,1164,1128,1075,995,902,812,738,677,620,558,483,
-392,290,186,91,5,-80,-166,-240,-295,-340,-389,-441,-480,-491,-481,-463,-450,-451,-468,-496,-523,
--547,-575,-608,-636,-651,-665,-702,-770,-859,-950,-1023,-1060,-1055,-1031,-1014,-1004,-979,-932,-886,-866,-869,
--877,-886,-907,-944,-986,-1026,-1069,-1114,-1145,-1150,-1140,-1137,-1155,-1187,-1212,-1215,-1201,-1197,-1221,-1264,-1301,
--1321,-1327,-1316,-1278,-1229,-1204,-1211,-1218,-1201,-1181,-1185,-1197,-1180,-1142,-1127,-1154,-1195,-1228,-1257,-1280,-1270,
--1219,-1179,-1207,-1296,-1400,-1501,-1623,-1776,-1929,-2051,-2148,-2242,-2340,-2445,-2567,-2698,-2797,-2827,-2801,-2771,-2771,
--2796,-2829,-2867,-2913,-2961,-3006,-3058,-3125,-3202,-3274,-3336,-3395,-3447,-3491,-3536,-3601,-3687,-3778,-3858,-3927,-3993,
--4060,-4137,-4243,-4387,-4550,-4709,-4864,-5031,-5190,-5296,-5328,-5326,-5340,-5375,-5401,-5414,-5446,-5514,-5583,-5603,-5561,
--5484,-5410,-5360,-5345,-5357,-5370,-5362,-5342,-5344,-5383,-5437,-5479,-5507,-5540,-5584,-5627,-5660,-5693,-5735,-5782,-5823,
--5857,-5893,-5942,-6007,-6080,-6156,-6235,-6325,-6428,-6536,-6638,-6733,-6829,-6929,-7028,-7125,-7223,-7323,-7422,-7517,-7610,
--7708,-7809,-7910,-8008,-8101,-8188,-8271,-8356,-8450,-8549,-8641,-8721,-8794,-8867,-8935,-8996,-9058,-9132,-9214,-9285,-9335,
--9380,-9434,-9496,-9550,-9594,-9639,-9680,-9703,-9702,-9689,-9674,-9663,-9669,-9723,-9828,-9941,-10007,-10020,-10021,-10039,-10068,
--10093,-10114,-10132,-10141,-10145,-10160,-10192,-10225,-10255,-10303,-10369,-10418,-10423,-10406,-10393,-10359,-10253,-10082,-9904,-9752,-9612,
--9483,
--9409,-9413,-9466,-9530,-9619,-9745,-9857,-9884,-9821,-9734,-9670,-9611,-9532,-9441,-9352,-9258,-9141,-9005,-8867,-8733,-8602,
--8474,-8344,-8202,-8049,-7906,-7787,-7671,-7529,-7358,-7183,-7023,-6873,-6716,-6548,-6369,-6185,-6008,-5845,-5702,-5578,-5488,
--5452,-5478,-5556,-5662,-5761,-5812,-5792,-5715,-5621,-5524,-5389,-5176,-4894,-4602,-4347,-4130,-3923,-3719,-3539,-3407,-3320,
--3247,-3155,-3030,-2879,-2722,-2572,-2435,-2312,-2200,-2094,-1990,-1888,-1790,-1691,-1587,-1480,-1380,-1293,-1218,-1153,-1099,
--1048,-984,-903,-824,-763,-713,-650,-573,-501,-441,-377,-288,-179,-62,62,200,340,461,555,638,724,
-820,927,1045,1163,1267,1354,1437,1525,1612,1686,1755,1837,1939,2051,2153,2236,2308,2389,2489,2603,2722,
-2846,2976,3089,3157,3180,3189,3221,3284,3384,3529,3716,3911,4087,4244,4389,4510,4607,4716,4865,5017,5102,
-5107,5104,5158,5255,5339,5389,5430,5476,5512,5533,5572,5677,5865,6116,6389,6637,6804,6844,6760,6630,6548,
-6525,6495,6435,6450,6666,7042,7373,7494,7417,7244,7021,6759,6512,6311,6057,5608,5034,4653,4729,5199,5754,
-6159,6401,6564,6680,6738,6752,6755,6756,6742,6713,6687,6669,6650,6630,6622,6630,6647,6668,6700,6743,6777,
-6778,6732,6636,6500,6361,6281,6301,6400,6505,6559,6562,6554,6553,6548,6528,6508,6500,6496,6484,6465,6455,
-6457,6457,6444,6422,6398,6376,6354,6336,6324,6321,6322,6323,6322,6325,6343,6374,6400,6402,6377,6337,6297,
-6264,6242,6235,6231,6213,6175,6127,6083,6050,6031,6023,6015,5996,5965,5932,5908,5890,5872,5852,5833,5816,
-5801,5779,5732,5648,5541,5440,5366,5320,5297,5300,5314,5313,5284,5251,5235,5222,5183,5125,5087,5080,5071,
-5029,4971,4935,4930,4932,4924,4906,4881,4845,4811,4798,4811,4841,4887,4946,4978,4918,4743,4524,4376,4340,
-4351,4322,4239,4154,4107,4075,4021,3942,3869,3818,3776,3718,3645,3581,3546,3533,3513,3468,3400,3333,3283,
-3248,3211,3160,3105,3060,3029,3000,2962,2915,2873,2840,2809,2762,2694,2620,2571,2573,2630,2706,2748,2725,
-2649,2556,2476,2424,2419,2473,2565,2636,2627,2539,2425,2348,2324,2325,2312,2277,2238,2207,2166,2107,2063,
-2082,2142,2150,2041,1868,1755,1757,1814,1844,1825,1791,1760,1727,1688,1655,1632,1609,1586,1569,1561,1557,
-1551,1545,1543,1542,1543,1551,1567,1583,1594,1596,1584,1552,1508,1466,1431,1391,1336,1273,1220,1194,1195,
-1208,1211,1188,1147,1117,1116,1133,1147,1152,1153,1155,1152,1141,1127,1117,1111,1112,1122,1140,1158,1172,
-1185,1202,1219,1233,1246,1264,1285,1306,1325,1341,1355,1365,1369,1371,1371,1375,1391,1423,1462,1487,1483,
-1455,1426,1424,1457,1507,1540,1544,1542,1564,1600,1605,1561,1505,1488,1511,1537,1543,1541,1544,1538,1511,
-1478,1465,1466,1454,1420,1383,1360,1345,1324,1296,1268,1243,1219,1197,1179,1162,1141,1117,1093,1073,1052,
-1029,1002,974,946,916,880,841,803,775,755,736,713,687,662,642,626,610,590,564,535,502,
-462,417,374,337,307,282,258,233,207,176,140,101,61,22,-13,-47,-79,-109,-139,-171,-207,
--247,-287,-328,-371,-416,-461,-507,-553,-598,-638,-673,-710,-752,-798,-840,-879,-923,-969,-1013,-1053,-1097,
--1143,-1185,-1222,-1259,-1300,-1343,-1385,-1429,-1475,-1521,-1562,-1601,-1645,-1689,-1729,-1764,-1798,-1833,-1865,-1896,-1928,
--1962,-1998,-2032,-2067,-2101,-2135,-2168,-2203,-2237,-2269,-2298,-2328,-2357,-2384,-2410,-2439,-2475,-2516,-2555,-2588,-2616,
--2642,-2670,-2701,-2734,-2768,-2802,-2835,-2867,-2899,-2929,-2955,-2977,-3000,-3027,-3055,-3078,-3096,-3113,-3133,-3152,-3167,
--3179,-3190,-3203,-3215,-3226,-3236,-3243,-3246,-3246,-3247,-3250,-3255,-3262,-3268,-3271,-3271,-3275,-3282,-3287,-3286,-3280,
--3270,-3257,-3245,-3234,-3225,-3215,-3202,-3189,-3177,-3163,-3146,-3128,-3110,-3088,-3060,-3029,-3001,-2976,-2949,-2920,-2889,
--2855,-2816,-2773,-2730,-2691,-2659,-2629,-2598,-2565,-2534,-2507,-2479,-2447,-2413,-2383,-2356,-2325,-2289,-2254,-2220,-2182,
--2138,-2098,-2063,-2026,-1980,-1935,-1895,-1855,-1811,-1765,-1727,-1692,-1652,-1609,-1571,-1535,-1495,-1452,-1414,-1379,-1342,
--1303,-1267,-1233,-1197,-1162,-1132,-1106,-1075,-1041,-1010,-981,-950,-918,-890,-867,-842,-816,-789,-762,-731,-699,
--673,-648,-619,-584,-552,-522,-489,-455,-426,-400,-370,-340,-316,-298,-276,-249,-222,-192,-158,-124,-96,
--68,-29,11,42,70,112,167,214,252,296,346,384,412,448,500,548,586,629,683,732,775,
-831,901,952,973,988,1019,1048,1057,1064,1093,1139,1186,1235,1274,1266,1204,1142,1128,1146,1157,1174,
-1233,1319,1374,1368,1305,1200,1112,1153,1378,1669,1844,1884,1952,2155,2388,2485,2423,2294,2131,1869,1484,
-1071,782,707,826,1053,1308,1539,1689,1649,1320,753,168,-219,-380,-436,-489,-540,-561,-571,-610,-679,
--746,-791,-822,-868,-941,-1022,-1075,-1086,-1057,-989,-880,-778,-762,-847,-946,-972,-949,-968,-1058,-1179,-1303,
--1451,-1615,-1743,-1810,-1851,-1905,-1965,-2022,-2097,-2196,-2283,-2329,-2357,-2411,-2484,-2545,-2586,-2621,-2659,-2704,-2761,
--2823,-2861,-2861,-2853,-2872,-2907,-2930,-2943,-2976,-3030,-3079,-3109,-3135,-3165,-3187,-3196,-3204,-3213,-3216,-3212,-3214,
--3223,-3228,-3236,-3276,-3363,-3473,-3573,-3648,-3704,-3750,-3792,-3836,-3880,-3918,-3941,-3954,-3959,-3952,-3934,-3912,-3893,
--3871,-3842,-3809,-3773,-3734,-3691,-3645,-3597,-3549,-3499,-3448,-3393,-3329,-3258,-3185,-3115,-3048,-2980,-2915,-2850,-2783,
--2716,-2653,-2590,-2522,-2452,-2387,-2325,-2254,-2175,-2101,-2035,-1969,-1894,-1818,-1753,-1692,-1623,-1544,-1460,-1376,-1290,
--1204,-1124,-1046,-963,-876,-795,-724,-658,-585,-508,-432,-356,-276,-192,-116,-54,-1,55,117,173,215,
-248,285,334,390,441,481,510,534,561,596,636,674,704,728,753,785,827,877,923,959,984,
-1001,1013,1029,1057,1098,1138,1167,1191,1223,1256,1274,1276,1286,1323,1387,1459,1522,1572,1606,1629,1653,
-1679,1697,1701,1705,1726,1766,1809,1839,1854,1860,1863,1863,1863,1862,1863,1871,1886,1901,1911,1920,1936,
-1961,1987,2009,2026,2039,2052,2074,2110,2149,2175,2190,2207,2234,2268,2305,2352,2418,2505,2611,2726,2836,
-2922,2974,2995,2997,2989,2990,3013,3053,3088,3100,3096,3091,3092,3095,3095,3088,3067,3029,2985,2958,2954,
-2961,2956,2929,2884,2831,2786,2760,2755,2760,2763,2761,2759,2763,2773,2783,2786,2783,2776,2771,2766,2757,
-2740,2714,2681,2647,2621,2623,2605,2600,2599,2586,2548,2484,2405,2328,2261,2201,2147,2102,2074,2071,2091,
-2115,2122,2100,2057,2007,1964,1933,1922,1929,1948,1975,2018,2079,2137,2167,2164,2146,2134,2132,2141,2163,
-2192,2211,2218,2228,2246,2240,2174,2057,1942,1872,1836,1799,1741,1670,1601,1542,1490,1437,1372,1295,1218,
-1157,1111,1067,1014,948,875,801,729,661,595,529,457,370,266,156,54,-35,-122,-215,-304,-377,
--433,-487,-541,-578,-583,-563,-538,-522,-519,-528,-548,-575,-607,-639,-668,-690,-703,-715,-738,-784,-856,
--950,-1040,-1095,-1101,-1083,-1073,-1068,-1041,-986,-934,-915,-918,-919,-916,-927,-962,-1008,-1053,-1096,-1136,-1162,
--1169,-1165,-1167,-1184,-1212,-1237,-1245,-1236,-1230,-1245,-1275,-1302,-1320,-1333,-1333,-1305,-1259,-1232,-1236,-1245,-1234,
--1224,-1238,-1253,-1227,-1175,-1157,-1202,-1269,-1310,-1318,-1308,-1281,-1245,-1241,-1306,-1420,-1535,-1635,-1745,-1877,-2007,
--2118,-2220,-2324,-2424,-2516,-2618,-2736,-2839,-2884,-2875,-2853,-2853,-2878,-2917,-2967,-3022,-3071,-3109,-3152,-3214,-3289,
--3363,-3428,-3486,-3535,-3577,-3626,-3697,-3787,-3873,-3942,-3997,-4054,-4124,-4220,-4358,-4531,-4702,-4838,-4950,-5070,-5201,
--5297,-5330,-5328,-5341,-5375,-5400,-5416,-5457,-5533,-5592,-5576,-5487,-5386,-5329,-5324,-5345,-5366,-5371,-5357,-5342,-5353,
--5400,-5462,-5511,-5540,-5567,-5603,-5643,-5681,-5719,-5766,-5816,-5860,-5895,-5930,-5977,-6037,-6101,-6163,-6233,-6322,-6429,
--6535,-6632,-6724,-6823,-6929,-7030,-7124,-7219,-7322,-7424,-7518,-7606,-7700,-7799,-7899,-7994,-8084,-8173,-8261,-8351,-8447,
--8544,-8634,-8712,-8786,-8859,-8926,-8985,-9048,-9127,-9215,-9290,-9341,-9385,-9441,-9506,-9566,-9614,-9655,-9686,-9703,-9707,
--9704,-9693,-9673,-9667,-9717,-9829,-9949,-10017,-10027,-10026,-10045,-10076,-10102,-10123,-10147,-10164,-10169,-10176,-10199,-10231,-10260,
--10299,
--10358-10422,-10463,-10476,-10469,-10426,-10323,-10167,-10004,-9864,-9743,-9641,-9582,-9583,-9628,-9700,-9793,-9895,-9960,-9948,
--9877,-9797,-9730,-9659,-9570,-9475,-9382,-9280,-9158,-9022,-8887,-8756,-8627,-8500,-8366,-8216,-8057,-7912,-7789,-7663,-7513,
--7343,-7176,-7021,-6872,-6717,-6551,-6369,-6176,-5990,-5826,-5681,-5552,-5458,-5423,-5448,-5514,-5602,-5687,-5726,-5680,-5577,
--5492,-5457,-5404,-5236,-4940,-4603,-4312,-4086,-3889,-3698,-3524,-3386,-3288,-3211,-3125,-3007,-2853,-2683,-2521,-2382,-2261,
--2151,-2044,-1939,-1834,-1734,-1637,-1535,-1424,-1313,-1212,-1123,-1044,-978,-923,-865,-795,-724,-669,-627,-575,-505,
--435,-378,-319,-235,-125,-7,115,251,394,521,621,703,789,888,1001,1124,1244,1348,1432,1509,1589,
-1671,1753,1838,1933,2035,2133,2218,2292,2361,2439,2536,2653,2781,2907,3019,3100,3139,3151,3174,3239,3357,
-3522,3714,3901,4054,4175,4297,4436,4573,4695,4829,5000,5166,5245,5225,5187,5217,5311,5407,5470,5520,5575,
-5623,5664,5741,5900,6133,6382,6598,6759,6840,6803,6656,6498,6443,6492,6539,6523,6528,6670,6933,7180,7308,
-7312,7210,7001,6740,6541,6414,6173,5648,4975,4548,4633,5121,5687,6113,6386,6571,6693,6756,6787,6806,6807,
-6784,6755,6735,6719,6694,6667,6651,6654,6672,6704,6748,6793,6823,6819,6765,6658,6522,6411,6374,6411,6482,
-6541,6576,6599,6619,6626,6608,6575,6550,6541,6537,6527,6516,6512,6509,6494,6468,6447,6435,6418,6387,6358,
-6352,6368,6384,6385,6381,6388,6409,6428,6431,6415,6385,6349,6317,6294,6283,6280,6275,6258,6227,6182,6133,
-6092,6069,6057,6041,6017,5992,5975,5960,5938,5911,5881,5843,5797,5761,5757,5770,5747,5656,5523,5407,5344,
-5321,5312,5303,5293,5276,5248,5208,5167,5136,5127,5135,5139,5121,5077,5026,4984,4957,4945,4942,4934,4906,
-4871,4861,4890,4930,4939,4918,4898,4884,4831,4703,4536,4413,4372,4366,4332,4265,4208,4183,4156,4092,3996,
-3907,3845,3797,3741,3677,3618,3576,3549,3527,3497,3450,3390,3327,3272,3225,3181,3136,3092,3054,3021,2988,
-2946,2901,2868,2854,2841,2794,2707,2630,2633,2736,2870,2927,2862,2723,2588,2498,2445,2431,2480,2593,2701,
-2710,2598,2441,2341,2329,2349,2339,2293,2248,2220,2181,2114,2062,2087,2171,2209,2118,1940,1802,1777,1827,
-1865,1857,1823,1785,1743,1699,1661,1635,1612,1588,1568,1558,1557,1557,1556,1555,1556,1564,1581,1600,1613,
-1614,1604,1582,1548,1511,1477,1448,1414,1368,1311,1258,1222,1212,1221,1226,1206,1164,1131,1128,1150,1171,
-1177,1175,1174,1169,1158,1144,1134,1132,1134,1142,1155,1170,1184,1199,1217,1235,1251,1263,1276,1289,1303,
-1318,1340,1365,1385,1395,1396,1394,1393,1401,1426,1466,1500,1504,1479,1455,1465,1510,1561,1582,1571,1557,
-1570,1608,1634,1621,1583,1553,1551,1563,1575,1584,1590,1582,1554,1525,1511,1508,1495,1461,1423,1395,1375,
-1352,1325,1298,1276,1256,1236,1217,1199,1179,1157,1136,1115,1092,1067,1042,1018,994,966,931,890,847,
-811,785,764,743,718,691,667,649,635,619,595,564,529,489,445,402,365,333,306,281,257,
-233,207,176,141,102,61,22,-10,-39,-67,-98,-131,-167,-204,-241,-278,-319,-364,-412,-460,-508,
--555,-599,-638,-675,-715,-759,-802,-844,-888,-933,-975,-1016,-1060,-1106,-1148,-1185,-1223,-1267,-1310,-1350,-1390,
--1434,-1479,-1519,-1558,-1599,-1641,-1681,-1716,-1750,-1781,-1811,-1841,-1873,-1905,-1936,-1966,-1997,-2032,-2070,-2109,-2148,
--2185,-2218,-2249,-2279,-2308,-2334,-2361,-2393,-2430,-2470,-2507,-2538,-2564,-2589,-2616,-2645,-2676,-2710,-2746,-2781,-2813,
--2842,-2869,-2894,-2915,-2938,-2964,-2993,-3020,-3041,-3061,-3083,-3106,-3126,-3140,-3152,-3162,-3173,-3186,-3200,-3210,-3214,
--3216,-3216,-3218,-3221,-3228,-3235,-3240,-3243,-3245,-3249,-3252,-3251,-3245,-3236,-3225,-3211,-3199,-3190,-3180,-3169,-3156,
--3144,-3128,-3108,-3088,-3068,-3048,-3023,-2998,-2974,-2951,-2923,-2892,-2862,-2831,-2794,-2750,-2706,-2668,-2637,-2610,-2581,
--2549,-2518,-2490,-2461,-2429,-2396,-2367,-2340,-2310,-2275,-2240,-2206,-2168,-2127,-2091,-2059,-2022,-1976,-1929,-1888,-1849,
--1806,-1763,-1728,-1696,-1658,-1616,-1577,-1540,-1499,-1458,-1421,-1386,-1348,-1308,-1273,-1242,-1208,-1173,-1143,-1117,-1087,
--1054,-1021,-992,-963,-933,-906,-880,-853,-827,-803,-776,-743,-708,-680,-656,-627,-595,-567,-541,-509,-475,
--446,-423,-395,-362,-334,-316,-299,-279,-255,-222,-181,-141,-112,-86,-48,-5,30,61,102,151,195,
-231,277,329,370,396,430,480,533,579,625,673,714,750,799,858,900,919,941,975,1003,1013,
-1029,1069,1125,1189,1265,1330,1335,1282,1240,1254,1286,1293,1303,1352,1410,1428,1414,1386,1308,1185,1149,
-1332,1649,1873,1935,2006,2223,2474,2565,2480,2350,2212,1968,1583,1191,973,991,1171,1408,1630,1798,1857,
-1720,1322,731,152,-220,-358,-380,-403,-446,-485,-520,-567,-630,-693,-752,-816,-889,-963,-1014,-1028,-1012,
--968,-881,-753,-647,-641,-728,-797,-782,-755,-829,-1003,-1173,-1289,-1397,-1534,-1663,-1734,-1763,-1788,-1819,-1852,
--1900,-1969,-2039,-2096,-2155,-2232,-2315,-2387,-2451,-2516,-2575,-2627,-2688,-2758,-2802,-2803,-2795,-2815,-2850,-2866,-2874,
--2916,-2993,-3068,-3116,-3150,-3181,-3198,-3195,-3186,-3182,-3182,-3184,-3194,-3210,-3221,-3224,-3238,-3277,-3337,-3405,-3476,
--3545,-3612,-3680,-3752,-3820,-3868,-3892,-3905,-3911,-3905,-3884,-3860,-3842,-3826,-3803,-3771,-3736,-3698,-3654,-3609,-3564,
--3520,-3478,-3436,-3389,-3329,-3256,-3180,-3109,-3041,-2973,-2905,-2839,-2774,-2710,-2646,-2579,-2506,-2432,-2367,-2307,-2242,
--2168,-2096,-2033,-1969,-1895,-1821,-1757,-1700,-1638,-1564,-1482,-1396,-1306,-1218,-1136,-1060,-982,-898,-815,-738,-667,
--596,-524,-451,-375,-294,-209,-129,-60,0,63,129,191,238,275,310,350,395,440,480,512,536,
-562,598,639,676,706,734,764,800,841,887,929,958,974,986,999,1016,1039,1073,1110,1143,1174,
-1212,1250,1275,1280,1286,1316,1371,1438,1501,1552,1583,1596,1606,1623,1645,1667,1693,1729,1774,1815,1841,
-1852,1851,1841,1828,1818,1815,1819,1831,1846,1861,1871,1884,1908,1938,1966,1988,2007,2024,2039,2059,2089,
-2125,2155,2175,2193,2214,2240,2270,2308,2355,2410,2478,2563,2663,2764,2854,2922,2961,2973,2976,2997,3038,
-3076,3089,3082,3075,3077,3079,3074,3062,3037,2997,2953,2927,2927,2937,2931,2898,2849,2798,2759,2740,2739,
-2746,2749,2749,2754,2765,2773,2771,2760,2750,2746,2747,2747,2743,2732,2712,2683,2651,2623,2591,2569,2548,
-2519,2470,2389,2286,2183,2098,2030,1966,1904,1852,1828,1839,1881,1934,1974,1993,1988,1961,1916,1870,1846,
-1854,1883,1920,1971,2037,2095,2119,2113,2112,2134,2163,2175,2173,2173,2186,2214,2253,2283,2261,2160,2010,
-1879,1807,1780,1754,1701,1624,1541,1467,1407,1354,1299,1241,1184,1130,1072,1011,956,908,858,792,711,
-632,563,502,435,348,239,120,9,-86,-178,-275,-371,-451,-511,-563,-611,-640,-637,-611,-586,-575,
--577,-585,-602,-632,-670,-706,-728,-738,-743,-750,-762,-788,-841,-931,-1036,-1112,-1138,-1134,-1133,-1135,-1112,
--1060,-1011,-994,-992,-976,-950,-946,-979,-1034,-1084,-1120,-1140,-1145,-1140,-1141,-1157,-1188,-1222,-1250,-1265,-1267,
--1268,-1280,-1301,-1319,-1332,-1346,-1353,-1337,-1301,-1273,-1269,-1271,-1265,-1270,-1300,-1322,-1294,-1235,-1216,-1268,-1341,
--1369,-1347,-1312,-1292,-1295,-1334,-1419,-1529,-1633,-1725,-1822,-1933,-2047,-2162,-2286,-2410,-2507,-2574,-2644,-2740,-2838,
--2895,-2905,-2901,-2915,-2955,-3015,-3088,-3159,-3209,-3239,-3267,-3313,-3375,-3442,-3505,-3564,-3614,-3661,-3718,-3794,-3879,
--3950,-4001,-4050,-4115,-4202,-4321,-4482,-4673,-4850,-4970,-5042,-5114,-5208,-5295,-5337,-5343,-5349,-5370,-5394,-5421,-5472,
--5543,-5579,-5531,-5421,-5325,-5298,-5326,-5360,-5374,-5370,-5363,-5364,-5384,-5429,-5487,-5537,-5569,-5593,-5623,-5662,-5705,
--5751,-5799,-5848,-5895,-5935,-5975,-6022,-6075,-6128,-6181,-6245,-6332,-6434,-6535,-6625,-6715,-6818,-6928,-7030,-7121,-7217,
--7323,-7429,-7523,-7609,-7697,-7791,-7883,-7971,-8060,-8151,-8243,-8334,-8428,-8523,-8612,-8694,-8770,-8845,-8913,-8974,-9040,
--9120,-9206,-9280,-9333,-9382,-9442,-9510,-9571,-9619,-9656,-9682,-9701,-9715,-9723,-9713,-9680,-9660,-9704,-9820,-9946,-10016,
--10026,-10027,-10051,-10088,-10115,-10137,-10165,-10190,-10198,-10200,-10212,-10233,-10252,-10282,-10345,-10439,-10524,-10565,-10554,-10500,-10409,
--10290,
--10162,-10042,-9936,-9850,-9796,-9787,-9822,-9888,-9969,-10033,-10043,-9995,-9918,-9845,-9776,-9696,-9602,-9508,-9411,-9299,-9168,
--9034,-8907,-8787,-8667,-8542,-8403,-8245,-8082,-7934,-7802,-7661,-7501,-7334,-7178,-7028,-6873,-6714,-6547,-6361,-6162,-5978,
--5826,-5695,-5572,-5475,-5432,-5442,-5481,-5541,-5610,-5637,-5565,-5425,-5330,-5335,-5354,-5243,-4963,-4609,-4292,-4040,-3827,
--3639,-3485,-3367,-3273,-3188,-3096,-2977,-2821,-2644,-2477,-2333,-2208,-2093,-1986,-1885,-1785,-1685,-1584,-1478,-1365,-1249,
--1140,-1037,-938,-852,-789,-742,-690,-626,-568,-523,-479,-422,-361,-309,-256,-179,-73,44,166,299,441,
-573,677,762,849,951,1069,1197,1319,1423,1506,1578,1652,1730,1814,1909,2016,2119,2207,2278,2343,2412,
-2491,2589,2712,2849,2974,3061,3106,3125,3149,3209,3322,3488,3691,3895,4056,4155,4226,4330,4487,4660,4815,
-4968,5145,5309,5381,5344,5284,5302,5404,5518,5591,5638,5692,5759,5839,5960,6151,6375,6556,6652,6687,6689,
-6638,6525,6416,6406,6497,6584,6598,6584,6625,6725,6832,6927,7007,7012,6874,6651,6492,6408,6191,5664,4977,
-4524,4565,5003,5557,6025,6360,6577,6697,6760,6811,6851,6853,6819,6784,6770,6761,6739,6710,6691,6691,6714,
-6760,6817,6859,6872,6855,6809,6730,6632,6552,6520,6530,6555,6584,6617,6650,6666,6651,6616,6586,6574,6575,
-6574,6564,6551,6539,6525,6502,6477,6466,6467,6458,6429,6400,6394,6410,6420,6416,6412,6424,6445,6453,6439,
-6410,6376,6342,6315,6301,6299,6296,6288,6276,6258,6230,6191,6153,6124,6099,6068,6034,6013,6007,5999,5977,
-5946,5911,5866,5811,5770,5766,5783,5764,5672,5535,5417,5355,5334,5325,5316,5313,5308,5279,5220,5166,5159,
-5201,5250,5253,5202,5130,5071,5032,5007,4995,4991,4978,4942,4906,4911,4966,5021,5017,4952,4879,4837,4801,
-4725,4606,4495,4427,4385,4335,4276,4239,4227,4205,4142,4048,3957,3887,3833,3785,3741,3696,3645,3591,3548,
-3519,3491,3444,3375,3301,3240,3199,3168,3133,3090,3048,3010,2973,2935,2914,2924,2942,2917,2826,2726,2712,
-2820,2969,3028,2939,2768,2621,2540,2494,2461,2476,2572,2695,2738,2648,2493,2384,2364,2379,2362,2310,2262,
-2233,2197,2133,2075,2078,2142,2189,2138,1997,1857,1802,1828,1873,1884,1857,1814,1766,1718,1677,1648,1625,
-1600,1574,1558,1559,1570,1577,1575,1573,1581,1598,1617,1625,1620,1603,1575,1541,1511,1488,1466,1437,1397,
-1349,1297,1253,1230,1234,1244,1234,1196,1155,1141,1159,1185,1200,1201,1197,1190,1178,1164,1153,1151,1154,
-1161,1172,1183,1194,1207,1226,1248,1269,1284,1295,1303,1309,1318,1338,1368,1396,1413,1419,1420,1419,1424,
-1443,1480,1515,1525,1504,1481,1483,1514,1551,1575,1583,1586,1600,1633,1667,1675,1647,1603,1576,1581,1604,
-1625,1632,1620,1593,1564,1543,1528,1509,1478,1446,1420,1402,1382,1358,1333,1312,1293,1274,1253,1232,1212,
-1194,1174,1152,1126,1099,1073,1050,1027,1002,971,934,892,852,818,792,768,742,715,690,673,661,
-645,621,589,553,516,477,438,400,366,334,305,280,258,237,212,183,147,107,68,34,4,
--25,-59,-95,-132,-168,-202,-236,-273,-317,-364,-411,-457,-504,-552,-596,-637,-679,-723,-770,-816,-860,
--900,-937,-975,-1018,-1063,-1104,-1141,-1182,-1228,-1272,-1312,-1350,-1393,-1436,-1477,-1515,-1555,-1596,-1635,-1670,-1701,
--1731,-1760,-1790,-1823,-1856,-1885,-1911,-1939,-1973,-2012,-2053,-2095,-2133,-2168,-2201,-2234,-2265,-2293,-2323,-2356,-2393,
--2429,-2461,-2490,-2517,-2543,-2570,-2598,-2627,-2660,-2695,-2730,-2761,-2787,-2812,-2836,-2861,-2884,-2910,-2939,-2967,-2992,
--3015,-3038,-3062,-3084,-3102,-3115,-3124,-3133,-3145,-3160,-3172,-3180,-3184,-3187,-3189,-3192,-3198,-3206,-3211,-3214,-3215,
--3217,-3217,-3214,-3208,-3200,-3189,-3176,-3164,-3157,-3148,-3137,-3124,-3110,-3094,-3071,-3049,-3029,-3011,-2991,-2970,-2949,
--2926,-2897,-2866,-2838,-2810,-2776,-2735,-2692,-2654,-2622,-2593,-2563,-2532,-2499,-2469,-2441,-2411,-2380,-2350,-2323,-2294,
--2261,-2227,-2194,-2158,-2119,-2084,-2052,-2014,-1967,-1919,-1878,-1841,-1800,-1760,-1726,-1695,-1659,-1619,-1582,-1545,-1504,
--1463,-1428,-1395,-1356,-1314,-1280,-1251,-1219,-1185,-1153,-1125,-1095,-1062,-1030,-1002,-975,-949,-923,-895,-864,-834,
--810,-787,-757,-723,-695,-669,-639,-606,-579,-555,-525,-493,-467,-446,-420,-387,-358,-336,-316,-295,-273,
--245,-205,-163,-130,-104,-69,-26,13,47,88,134,173,208,253,310,357,390,425,470,519,563,
-611,660,698,725,759,800,831,852,883,926,960,978,1002,1044,1101,1179,1280,1363,1368,1315,1289,
-1327,1367,1367,1371,1417,1454,1435,1410,1420,1394,1280,1209,1357,1664,1880,1925,1993,2237,2521,2621,2530,
-2398,2259,2006,1632,1312,1217,1339,1552,1762,1932,2013,1935,1644,1156,578,79,-214,-309,-313,-327,-371,
--420,-463,-511,-569,-636,-713,-800,-881,-937,-954,-944,-921,-879,-788,-650,-541,-541,-621,-665,-625,-606,
--729,-960,-1152,-1243,-1315,-1448,-1606,-1705,-1721,-1697,-1670,-1651,-1648,-1670,-1717,-1789,-1884,-1986,-2077,-2164,-2271,
--2392,-2490,-2554,-2613,-2680,-2726,-2735,-2737,-2766,-2802,-2813,-2823,-2881,-2989,-3094,-3162,-3199,-3223,-3228,-3211,-3188,
--3176,-3174,-3178,-3192,-3218,-3244,-3262,-3273,-3281,-3290,-3309,-3346,-3401,-3472,-3561,-3666,-3763,-3825,-3849,-3854,-3853,
--3843,-3823,-3804,-3791,-3778,-3756,-3729,-3699,-3662,-3617,-3570,-3527,-3486,-3448,-3412,-3371,-3316,-3243,-3165,-3093,-3026,
--2960,-2894,-2830,-2768,-2705,-2639,-2569,-2492,-2414,-2346,-2285,-2223,-2155,-2087,-2023,-1957,-1885,-1813,-1750,-1693,-1632,
--1559,-1479,-1395,-1309,-1224,-1143,-1066,-989,-909,-829,-752,-678,-607,-536,-464,-388,-307,-222,-139,-62,7,
-74,139,199,250,293,330,365,401,440,481,516,544,575,613,653,686,716,749,787,823,858,
-895,929,952,964,978,998,1019,1036,1057,1088,1124,1161,1201,1241,1271,1287,1301,1331,1376,1428,1479,
-1523,1554,1570,1580,1596,1620,1649,1683,1725,1771,1809,1835,1844,1838,1817,1793,1777,1776,1785,1800,1815,
-1828,1839,1855,1881,1911,1937,1958,1979,2005,2030,2055,2081,2108,2131,2149,2166,2189,2215,2243,2275,2311,
-2349,2393,2450,2524,2612,2709,2805,2883,2934,2967,3004,3051,3087,3092,3075,3063,3065,3068,3058,3035,3003,
-2964,2924,2901,2900,2908,2900,2866,2817,2770,2736,2718,2716,2719,2722,2725,2737,2751,2754,2737,2715,2707,
-2716,2728,2729,2716,2693,2667,2640,2614,2591,2502,2473,2437,2388,2314,2209,2087,1973,1885,1816,1753,1695,
-1655,1647,1675,1730,1798,1867,1928,1967,1967,1925,1864,1823,1817,1833,1861,1909,1976,2036,2058,2059,2085,
-2150,2211,2221,2184,2144,2143,2184,2243,2274,2233,2116,1965,1840,1769,1733,1700,1650,1579,1498,1419,1353,
-1297,1247,1203,1163,1114,1046,968,907,872,835,771,683,600,538,486,419,323,203,75,-45,-152,
--251,-348,-437,-511,-567,-614,-653,-671,-662,-637,-619,-619,-628,-636,-648,-674,-714,-751,-768,-766,-761,
--762,-771,-789,-834,-922,-1033,-1124,-1167,-1179,-1189,-1197,-1181,-1139,-1098,-1079,-1064,-1027,-981,-965,-1000,-1062,
--1116,-1141,-1140,-1121,-1100,-1096,-1119,-1162,-1207,-1244,-1271,-1287,-1297,-1312,-1330,-1346,-1358,-1369,-1376,-1367,-1340,
--1314,-1301,-1293,-1289,-1305,-1347,-1378,-1357,-1303,-1281,-1324,-1383,-1395,-1355,-1314,-1312,-1357,-1431,-1520,-1608,-1690,
--1775,-1868,-1968,-2072,-2196,-2347,-2494,-2595,-2647,-2692,-2764,-2844,-2898,-2917,-2930,-2963,-3024,-3110,-3205,-3286,-3332,
--3349,-3360,-3388,-3436,-3497,-3563,-3627,-3682,-3735,-3800,-3877,-3950,-4001,-4040,-4098,-4190,-4309,-4444,-4600,-4777,-4942,
--5054,-5111,-5155,-5223,-5302,-5354,-5365,-5359,-5366,-5393,-5438,-5496,-5548,-5551,-5485,-5385,-5317,-5312,-5345,-5370,-5374,
--5375,-5389,-5414,-5443,-5479,-5525,-5570,-5602,-5621,-5642,-5678,-5727,-5780,-5830,-5879,-5928,-5974,-6019,-6067,-6117,-6167,
--6216,-6275,-6353,-6444,-6535,-6619,-6708,-6812,-6921,-7023,-7116,-7214,-7320,-7426,-7519,-7605,-7693,-7781,-7865,-7948,-8036,
--8129,-8221,-8310,-8400,-8494,-8585,-8670,-8749,-8825,-8898,-8966,-9036,-9114,-9192,-9260,-9317,-9374,-9439,-9506,-9563,-9609,
--9645,-9675,-9702,-9728,-9744,-9730,-9683,-9647,-9682,-9796,-9927,-10004,-10022,-10028,-10057,-10097,-10127,-10150,-10179,-10208,-10222,
--10227,
--10238-10254,-10266,-10289,-10356,-10470,-10583,-10638,-10620,-10561,-10492,-10423,-10344,-10256,-10167,-10088,-10032,-10005,-10015,-10058,
--10110,
--10131-10101,-10030,-9953,-9883,-9808,-9718,-9624,-9532,-9432,-9308,-9170,-9042,-8931,-8824,-8710,-8581,-8433,-8269,-8105,
--7959,-7820,-7666,-7496,-7333,-7183,-7031,-6868,-6700,-6529,-6344,-6149,-5976,-5844,-5730,-5613,-5512,-5457,-5442,-5446,-5474,
--5527,-5546,-5454,-5278,-5159,-5181,-5256,-5213,-4988,-4657,-4323,-4017,-3745,-3534,-3409,-3341,-3278,-3192,-3083,-2947,-2780,
--2597,-2431,-2293,-2168,-2046,-1930,-1828,-1732,-1635,-1532,-1424,-1310,-1196,-1083,-969,-849,-740,-668,-631,-596,-537,
--468,-411,-367,-322,-275,-231,-186,-117,-19,94,215,345,484,616,725,813,902,1004,1125,1257,1383,
-1489,1571,1641,1711,1785,1864,1960,2070,2180,2270,2340,2406,2479,2565,2670,2799,2940,3057,3121,3141,3156,
-3206,3310,3461,3649,3854,4038,4162,4218,4261,4364,4547,4759,4942,5095,5249,5387,5449,5416,5366,5395,5514,
-5643,5719,5754,5802,5884,5994,6139,6320,6491,6577,6554,6488,6452,6445,6426,6402,6426,6508,6588,6616,6605,
-6585,6551,6509,6518,6608,6697,6671,6538,6418,6331,6116,5635,5014,4574,4537,4863,5366,5875,6292,6562,6695,
-6760,6824,6879,6885,6846,6808,6798,6798,6783,6757,6739,6742,6774,6833,6895,6926,6916,6884,6848,6804,6745,
-6683,6636,6611,6609,6634,6678,6713,6714,6685,6653,6636,6634,6630,6615,6590,6562,6538,6517,6498,6482,6476,
-6478,6475,6459,6442,6438,6442,6438,6425,6423,6441,6464,6470,6456,6427,6392,6352,6319,6301,6292,6281,6267,
-6259,6255,6244,6218,6187,6158,6128,6091,6056,6035,6028,6021,6005,5980,5947,5903,5857,5823,5803,5777,5715,
-5613,5502,5417,5372,5351,5335,5322,5320,5319,5297,5250,5215,5241,5324,5399,5393,5302,5183,5096,5054,5041,
-5039,5036,5020,4987,4956,4963,5012,5061,5054,4984,4902,4854,4834,4792,4702,4590,4495,4423,4356,4291,4247,
-4229,4213,4171,4100,4018,3945,3891,3862,3849,3827,3769,3683,3603,3554,3524,3482,3414,3334,3269,3231,3208,
-3178,3130,3071,3017,2974,2947,2948,2981,3016,3001,2910,2795,2751,2822,2944,2996,2919,2771,2652,2596,2555,
-2492,2448,2490,2601,2679,2645,2531,2429,2389,2385,2367,2325,2281,2248,2215,2167,2111,2075,2085,2117,2114,
-2034,1910,1822,1817,1862,1892,1876,1833,1786,1739,1694,1659,1634,1610,1582,1562,1566,1587,1601,1598,1590,
-1592,1602,1612,1615,1612,1599,1573,1543,1521,1506,1490,1463,1427,1385,1336,1288,1256,1256,1275,1283,1257,
-1211,1177,1176,1198,1220,1228,1226,1218,1206,1191,1177,1170,1170,1177,1186,1195,1201,1211,1229,1256,1283,
-1301,1311,1315,1315,1317,1329,1357,1390,1416,1431,1438,1441,1443,1456,1485,1517,1532,1523,1504,1494,1498,
-1518,1554,1595,1626,1642,1656,1677,1685,1654,1595,1554,1562,1603,1639,1649,1638,1616,1588,1559,1532,1507,
-1482,1460,1443,1432,1420,1401,1377,1353,1331,1312,1292,1270,1248,1227,1207,1185,1160,1133,1106,1079,1054,
-1029,1001,968,929,889,850,818,789,763,737,716,701,689,673,647,614,580,548,515,480,443,
-406,370,338,311,287,265,243,219,189,152,113,76,43,10,-24,-62,-101,-138,-173,-206,-241,
--282,-326,-370,-411,-454,-501,-548,-592,-634,-680,-728,-777,-823,-861,-895,-930,-970,-1015,-1056,-1096,-1138,
--1185,-1231,-1272,-1311,-1353,-1396,-1435,-1474,-1513,-1554,-1593,-1627,-1658,-1687,-1716,-1748,-1783,-1816,-1846,-1872,-1899,
--1930,-1967,-2007,-2049,-2086,-2120,-2154,-2190,-2223,-2253,-2284,-2317,-2352,-2383,-2412,-2441,-2471,-2500,-2529,-2557,-2586,
--2617,-2651,-2686,-2717,-2741,-2764,-2790,-2817,-2844,-2869,-2897,-2925,-2952,-2976,-2999,-3022,-3044,-3064,-3078,-3086,-3092,
--3101,-3114,-3127,-3137,-3146,-3152,-3156,-3160,-3166,-3174,-3180,-3183,-3184,-3185,-3183,-3178,-3173,-3167,-3157,-3145,-3135,
--3129,-3121,-3107,-3091,-3076,-3059,-3037,-3014,-2995,-2979,-2962,-2942,-2921,-2898,-2870,-2842,-2817,-2792,-2761,-2723,-2684,
--2647,-2613,-2580,-2549,-2517,-2483,-2451,-2422,-2394,-2364,-2333,-2304,-2276,-2245,-2212,-2179,-2145,-2109,-2075,-2042,-2004,
--1958,-1911,-1871,-1835,-1797,-1759,-1726,-1694,-1658,-1621,-1585,-1549,-1509,-1469,-1435,-1403,-1366,-1325,-1290,-1260,-1228,
--1194,-1162,-1134,-1104,-1070,-1039,-1012,-986,-961,-937,-909,-875,-842,-818,-797,-769,-737,-710,-686,-657,-623,
--592,-565,-537,-508,-484,-464,-440,-411,-387,-365,-338,-307,-282,-259,-227,-187,-151,-122,-88,-45,-6,
-29,69,113,152,186,231,288,342,385,424,468,509,548,596,647,683,702,720,746,769,793,
-831,881,924,954,986,1028,1081,1161,1268,1347,1339,1279,1265,1316,1353,1340,1348,1411,1454,1422,1393,
-1429,1442,1348,1271,1397,1671,1847,1863,1938,2215,2524,2630,2550,2443,2313,2042,1668,1422,1450,1658,1869,
-2016,2100,2070,1844,1417,888,391,27,-170,-237,-254,-280,-319,-353,-386,-434,-503,-586,-677,-766,-838,
--874,-872,-851,-827,-791,-711,-592,-501,-507,-579,-611,-570,-563,-700,-931,-1106,-1171,-1231,-1383,-1586,-1717,
--1720,-1641,-1550,-1477,-1427,-1405,-1429,-1510,-1630,-1747,-1840,-1946,-2100,-2279,-2415,-2489,-2541,-2601,-2648,-2665,-2680,
--2721,-2763,-2775,-2789,-2863,-2998,-3136,-3230,-3281,-3299,-3287,-3252,-3218,-3201,-3197,-3197,-3206,-3233,-3274,-3316,-3345,
--3350,-3330,-3305,-3295,-3312,-3361,-3450,-3575,-3700,-3785,-3818,-3817,-3801,-3776,-3752,-3739,-3735,-3726,-3706,-3683,-3659,
--3624,-3576,-3527,-3486,-3449,-3411,-3375,-3338,-3288,-3219,-3141,-3068,-3000,-2935,-2871,-2811,-2754,-2693,-2628,-2558,-2483,
--2406,-2335,-2271,-2209,-2145,-2080,-2014,-1945,-1873,-1803,-1739,-1678,-1613,-1541,-1462,-1381,-1299,-1219,-1141,-1062,-982,
--903,-827,-754,-682,-609,-535,-459,-381,-303,-223,-140,-58,17,86,148,204,255,300,339,374,408,
-446,489,528,562,597,637,676,705,734,770,811,844,869,896,922,939,950,970,1000,1027,1040,
-1051,1075,1113,1153,1190,1227,1259,1286,1313,1348,1390,1430,1466,1500,1530,1554,1574,1598,1626,1656,1689,
-1728,1768,1800,1821,1829,1822,1799,1772,1756,1757,1768,1782,1796,1808,1819,1833,1855,1881,1904,1923,1946,
-1977,2010,2041,2068,2090,2105,2114,2125,2143,2166,2190,2217,2250,2287,2327,2371,2421,2480,2556,2652,2757,
-2851,2928,2997,3058,3091,3085,3059,3047,3057,3066,3051,3014,2972,2932,2897,2874,2869,2873,2866,2841,2801,
-2759,2721,2694,2677,2669,2667,2674,2689,2704,2701,2680,2661,2666,2692,2712,2705,2671,2627,2586,2554,2528,
-2502,2360,2317,2274,2225,2158,2065,1957,1855,1770,1702,1644,1601,1585,1599,1637,1692,1762,1845,1931,1997,
-2012,1971,1901,1844,1817,1810,1819,1854,1916,1973,1999,2015,2069,2163,2243,2253,2198,2138,2122,2160,2215,
-2234,2181,2064,1930,1821,1745,1690,1640,1591,1535,1471,1403,1340,1283,1231,1187,1150,1101,1024,933,862,
-823,787,722,638,567,521,477,402,291,157,20,-108,-225,-329,-419,-496,-560,-613,-654,-682,-691,
--683,-669,-664,-670,-677,-678,-681,-700,-740,-780,-798,-792,-779,-777,-787,-810,-855,-935,-1037,-1123,-1172,
--1195,-1213,-1226,-1218,-1187,-1153,-1131,-1105,-1056,-1003,-987,-1024,-1086,-1134,-1152,-1144,-1118,-1089,-1077,-1097,-1141,
--1192,-1237,-1272,-1296,-1311,-1324,-1339,-1355,-1368,-1378,-1385,-1382,-1368,-1348,-1331,-1319,-1317,-1336,-1378,-1411,-1402,
--1360,-1335,-1358,-1399,-1409,-1376,-1341,-1350,-1415,-1511,-1602,-1675,-1744,-1829,-1926,-2016,-2104,-2222,-2382,-2548,-2667,
--2730,-2771,-2823,-2878,-2914,-2931,-2950,-2992,-3065,-3167,-3273,-3355,-3393,-3401,-3405,-3427,-3473,-3538,-3613,-3683,-3743,
--3798,-3863,-3936,-3997,-4038,-4080,-4161,-4291,-4440,-4578,-4702,-4830,-4961,-5071,-5140,-5187,-5245,-5316,-5369,-5381,-5369,
--5371,-5406,-5465,-5517,-5536,-5506,-5439,-5371,-5337,-5342,-5360,-5368,-5370,-5386,-5423,-5467,-5502,-5533,-5570,-5609,-5634,
--5644,-5655,-5688,-5742,-5803,-5858,-5909,-5959,-6009,-6056,-6105,-6157,-6211,-6264,-6318,-6382,-6458,-6538,-6619,-6707,-6806,
--6912,-7014,-7112,-7213,-7316,-7414,-7504,-7592,-7682,-7770,-7852,-7932,-8019,-8112,-8201,-8287,-8375,-8469,-8563,-8648,-8727,
--8804,-8881,-8957,-9032,-9106,-9176,-9239,-9300,-9367,-9437,-9500,-9551,-9596,-9636,-9672,-9705,-9739,-9759,-9742,-9686,-9640,
--9666,-9774,-9905,-9991,-10021,-10033,-10061,-10099,-10132,-10159,-10188,-10217,-10236,-10250,-10268,-10287,-10297,-10314,-10375,-10490,-10610,
--10671,
--10654,-10599,-10554,-10527,-10496,-10444,-10379,-10313,-10254,-10208,-10186,-10191,-10203,-10189,-10134,-10059,-9985,-9910,-9822,-9721,-9623,
--9532,
--9426,-9295,-9159,-9042,-8946,-8848,-8732,-8594,-8437,-8272,-8115,-7975,-7834,-7672,-7497,-7334,-7185,-7028,-6855,-6680,-6508,
--6328,-6144,-5986,-5866,-5756,-5636,-5527,-5458,-5421,-5395,-5396,-5440,-5459,-5358,-5157,-5007,-5022,-5130,-5156,-5014,-4743,
--4407,-4034,-3669,-3403,-3287,-3267,-3243,-3165,-3043,-2891,-2710,-2522,-2364,-2244,-2137,-2018,-1892,-1776,-1673,-1575,-1476,
--1372,-1262,-1148,-1034,-911,-774,-644,-559,-523,-500,-448,-373,-304,-257,-218,-179,-141,-99,-38,49,155,
-268,392,527,659,774,868,957,1057,1176,1311,1441,1547,1628,1698,1769,1841,1912,1998,2104,2219,2319,
-2399,2475,2559,2655,2767,2896,3031,3138,3193,3211,3238,3313,3442,3609,3793,3975,4128,4224,4267,4308,4418,
-4613,4839,5028,5167,5285,5394,5459,5462,5451,5500,5619,5743,5811,5840,5889,5981,6098,6226,6357,6457,6472,
-6395,6299,6272,6322,6388,6432,6468,6517,6571,6612,6632,6611,6518,6372,6269,6294,6413,6504,6499,6425,6296,
-6046,5622,5115,4724,4607,4787,5188,5692,6166,6500,6676,6763,6836,6896,6910,6880,6850,6843,6844,6831,6806,
-6788,6794,6835,6902,6962,6979,6951,6909,6879,6855,6818,6766,6713,6675,6668,6693,6732,6756,6749,6726,6709,
-6702,6691,6669,6639,6607,6575,6548,6531,6523,6515,6506,6496,6487,6479,6474,6473,6469,6456,6442,6444,6464,
-6488,6496,6489,6467,6433,6391,6351,6323,6299,6274,6254,6246,6245,6234,6209,6184,6165,6146,6119,6090,6065,
-6047,6038,6033,6022,5991,5945,5904,5877,5837,5756,5644,5539,5468,5426,5395,5369,5346,5327,5313,5304,5292,
-5270,5259,5300,5396,5485,5484,5377,5226,5112,5066,5064,5071,5071,5060,5039,5019,5015,5033,5054,5045,4993,
-4926,4885,4871,4843,4764,4650,4546,4469,4401,4325,4256,4219,4207,4190,4145,4073,3998,3951,3950,3974,3975,
-3913,3797,3680,3599,3551,3505,3444,3376,3319,3284,3261,3230,3176,3102,3028,2973,2950,2964,3005,3038,3020,
-2937,2831,2769,2788,2854,2890,2848,2758,2689,2661,2627,2545,2454,2433,2501,2582,2592,2522,2431,2371,2346,
-2339,2326,2297,2260,2230,2205,2159,2088,2037,2049,2090,2071,1962,1841,1801,1841,1883,1875,1833,1790,1750,
-1703,1660,1634,1614,1590,1572,1578,1602,1616,1609,1597,1595,1598,1596,1594,1597,1596,1580,1557,1540,1532,
-1518,1491,1456,1418,1374,1324,1286,1280,1305,1331,1325,1283,1233,1209,1218,1241,1256,1257,1249,1237,1222,
-1206,1193,1188,1189,1197,1205,1210,1216,1232,1259,1289,1309,1316,1317,1314,1312,1320,1343,1379,1413,1437,
-1449,1451,1450,1456,1475,1504,1529,1540,1540,1529,1515,1515,1549,1606,1649,1656,1650,1656,1662,1633,1572,
-1528,1539,1588,1632,1648,1643,1630,1607,1575,1542,1516,1498,1484,1474,1469,1464,1450,1425,1396,1372,1354,
-1338,1316,1290,1263,1238,1216,1194,1169,1140,1109,1079,1052,1025,994,958,920,883,849,819,792,770,
-753,739,724,703,673,639,608,580,552,520,485,449,413,379,349,322,296,272,249,224,191,
-150,110,73,38,2,-34,-72,-111,-147,-182,-217,-257,-300,-340,-376,-411,-452,-497,-540,-581,-624,
--671,-720,-769,-810,-846,-881,-921,-966,-1011,-1053,-1097,-1144,-1190,-1234,-1275,-1317,-1358,-1396,-1433,-1472,-1512,
--1551,-1587,-1619,-1648,-1679,-1712,-1746,-1781,-1813,-1842,-1869,-1898,-1931,-1971,-2011,-2046,-2078,-2112,-2148,-2182,-2213,
--2243,-2276,-2308,-2336,-2363,-2393,-2426,-2458,-2488,-2517,-2547,-2579,-2612,-2647,-2677,-2702,-2725,-2752,-2782,-2810,-2836,
--2861,-2887,-2913,-2937,-2960,-2982,-3003,-3023,-3039,-3047,-3050,-3055,-3064,-3078,-3092,-3103,-3111,-3117,-3122,-3130,-3140,
--3147,-3150,-3151,-3152,-3151,-3146,-3142,-3138,-3130,-3120,-3112,-3106,-3096,-3078,-3057,-3041,-3025,-3004,-2982,-2963,-2947,
--2929,-2909,-2887,-2865,-2841,-2816,-2793,-2768,-2738,-2705,-2670,-2636,-2600,-2566,-2535,-2504,-2470,-2437,-2408,-2380,-2349,
--2315,-2285,-2258,-2229,-2195,-2162,-2129,-2096,-2063,-2030,-1994,-1953,-1910,-1870,-1833,-1797,-1761,-1730,-1698,-1662,-1625,
--1590,-1555,-1515,-1474,-1440,-1409,-1374,-1335,-1301,-1269,-1236,-1202,-1171,-1144,-1115,-1083,-1053,-1025,-997,-969,-946,
--921,-889,-856,-831,-809,-780,-746,-719,-698,-674,-641,-609,-580,-552,-524,-501,-480,-455,-430,-413,-395,
--366,-328,-298,-276,-247,-208,-170,-138,-103,-60,-20,13,50,92,131,167,212,268,323,371,417,
-464,505,542,586,631,658,669,681,704,730,760,801,853,898,933,970,1011,1055,1119,1207,1266,
-1248,1201,1213,1281,1313,1290,1299,1381,1443,1422,1398,1442,1462,1371,1291,1399,1636,1773,1784,1894,2204,
-2511,2600,2541,2493,2403,2123,1737,1536,1648,1899,2065,2107,2072,1924,1589,1107,622,255,27,-95,-157,
--196,-231,-258,-274,-300,-358,-446,-543,-632,-708,-769,-800,-795,-763,-722,-681,-632,-573,-537,-562,-625,
--653,-627,-627,-735,-910,-1038,-1087,-1158,-1334,-1565,-1714,-1712,-1605,-1480,-1383,-1313,-1270,-1278,-1356,-1478,-1592,
--1683,-1803,-1988,-2196,-2346,-2420,-2471,-2534,-2584,-2604,-2625,-2673,-2721,-2739,-2759,-2840,-2987,-3149,-3275,-3352,-3379,
--3358,-3310,-3271,-3253,-3243,-3233,-3229,-3249,-3295,-3355,-3406,-3424,-3402,-3358,-3317,-3298,-3312,-3374,-3486,-3619,-3728,
--3786,-3794,-3763,-3714,-3674,-3662,-3666,-3662,-3645,-3627,-3608,-3574,-3525,-3478,-3443,-3410,-3370,-3329,-3293,-3249,-3187,
--3115,-3043,-2973,-2904,-2838,-2783,-2732,-2676,-2610,-2541,-2471,-2400,-2329,-2261,-2198,-2136,-2074,-2006,-1934,-1861,-1791,
--1725,-1661,-1595,-1526,-1450,-1369,-1288,-1213,-1138,-1059,-975,-896,-823,-754,-682,-608,-532,-452,-374,-300,-227,
--150,-67,13,88,153,211,262,307,345,379,412,453,500,544,580,614,653,689,716,743,780,
-821,850,867,886,907,922,932,954,990,1021,1036,1045,1070,1109,1149,1183,1216,1250,1281,1314,1353,
-1393,1428,1455,1482,1510,1537,1566,1598,1633,1666,1699,1734,1766,1787,1794,1795,1789,1775,1757,1746,1747,
-1755,1765,1778,1791,1804,1817,1836,1860,1883,1902,1924,1952,1984,2014,2041,2063,2075,2079,2082,2092,2111,
-2133,2161,2196,2238,2282,2321,2353,2382,2427,2503,2610,2728,2840,2940,3019,3061,3058,3036,3031,3048,3060,
-3038,2989,2941,2906,2880,2857,2842,2836,2830,2814,2784,2744,2698,2652,2613,2591,2588,2601,2621,2635,2633,
-2618,2610,2625,2652,2662,2636,2581,2522,2474,2436,2400,2360,2194,2141,2103,2074,2035,1975,1898,1819,1744,
-1677,1625,1599,1604,1633,1675,1726,1793,1878,1971,2042,2062,2026,1960,1897,1852,1824,1814,1835,1882,1930,
-1960,1992,2054,2142,2210,2224,2189,2140,2114,2121,2147,2151,2102,2003,1891,1795,1719,1652,1594,1546,1502,
-1453,1401,1352,1300,1243,1189,1143,1090,1009,909,824,767,719,653,580,528,499,461,379,252,103,
--43,-178,-297,-396,-476,-545,-609,-664,-700,-714,-716,-716,-719,-724,-726,-721,-711,-706,-724,-769,-818,
--844,-840,-824,-819,-832,-859,-901,-964,-1037,-1100,-1140,-1166,-1189,-1206,-1206,-1187,-1165,-1147,-1118,-1070,-1022,
--1009,-1041,-1091,-1127,-1143,-1145,-1133,-1113,-1102,-1120,-1165,-1215,-1256,-1285,-1304,-1310,-1309,-1311,-1321,-1332,-1341,
--1350,-1359,-1362,-1356,-1346,-1341,-1350,-1375,-1413,-1445,-1450,-1423,-1392,-1390,-1416,-1439,-1430,-1402,-1401,-1461,-1567,
--1672,-1750,-1821,-1910,-2009,-2089,-2152,-2244,-2390,-2563,-2707,-2798,-2854,-2895,-2926,-2943,-2952,-2967,-3001,-3068,-3168,
--3275,-3355,-3392,-3404,-3419,-3453,-3508,-3581,-3663,-3738,-3797,-3847,-3904,-3968,-4024,-4069,-4131,-4239,-4397,-4564,-4692,
--4771,-4837,-4924,-5030,-5127,-5200,-5263,-5323,-5369,-5384,-5380,-5391,-5432,-5482,-5505,-5484,-5433,-5383,-5357,-5354,-5360,
--5363,-5364,-5374,-5402,-5446,-5491,-5530,-5564,-5599,-5631,-5650,-5655,-5665,-5699,-5759,-5825,-5883,-5935,-5987,-6039,-6087,
--6136,-6192,-6252,-6309,-6359,-6412,-6476,-6550,-6629,-6714,-6806,-6904,-7006,-7111,-7214,-7312,-7401,-7486,-7575,-7668,-7759,
--7843,-7924,-8009,-8097,-8183,-8268,-8358,-8453,-8546,-8629,-8706,-8782,-8861,-8940,-9017,-9090,-9157,-9222,-9293,-9371,-9444,
--9502,-9549,-9593,-9637,-9675,-9709,-9742,-9763,-9747,-9692,-9645,-9666,-9765,-9894,-9987,-10027,-10041,-10062,-10095,-10132,-10165,
--10197,-10226,-10250,-10273,-10297,-10316,-10323,-10334,-10383,-10485,-10601,-10671,-10668,-10627,-10595,-10587,-10582,-10559,-10519,-10471,-10418,
--10364,
--10318,-10289,-10264,-10222,-10157,-10082,-10007,-9922,-9818,-9703,-9598,-9502,-9393,-9263,-9134,-9028,-8939,-8842,-8721,-8577,-8419,
--8261,-8116,-7983,-7843,-7680,-7504,-7339,-7185,-7022,-6845,-6668,-6499,-6327,-6155,-6006,-5884,-5760,-5621,-5497,-5418,-5368,
--5326,-5315,-5356,-5382,-5286,-5071,-4889,-4872,-4980,-5060,-5010,-4822,-4512,-4091,-3638,-3294,-3140,-3114,-3094,-3020,-2905,
--2763,-2594,-2414,-2268,-2173,-2096,-1998,-1873,-1741,-1619,-1512,-1415,-1318,-1212,-1098,-980,-852,-706,-561,-459,-412,
--387,-343,-275,-209,-161,-122,-82,-43,-1,55,135,229,332,446,575,708,829,931,1021,1118,1234,
-1368,1499,1605,1684,1755,1829,1900,1966,2040,2136,2250,2358,2449,2534,2628,2733,2846,2967,3088,3188,3252,
-3293,3342,3429,3558,3715,3880,4036,4167,4262,4327,4396,4514,4691,4892,5063,5186,5289,5394,5485,5539,5568,
-5617,5704,5793,5850,5890,5954,6051,6151,6232,6293,6330,6321,6264,6208,6216,6292,6388,6456,6495,6529,6572,
-6625,6675,6685,6606,6436,6262,6200,6294,6466,6581,6551,6366,6059,5685,5304,4995,4835,4880,5141,5558,6014,
-6388,6630,6766,6850,6906,6933,6932,6920,6913,6905,6886,6858,6838,6847,6897,6968,7021,7027,6992,6947,6914,
-6891,6860,6820,6779,6753,6748,6758,6771,6773,6765,6756,6749,6734,6706,6673,6647,6629,6609,6589,6579,6579,
-6577,6564,6542,6522,6510,6504,6500,6494,6484,6477,6482,6500,6518,6525,6519,6501,6470,6432,6396,6364,6331,
-6299,6278,6272,6262,6234,6198,6175,6170,6166,6153,6128,6097,6068,6056,6063,6064,6032,5976,5932,5903,5843,
-5724,5585,5493,5461,5443,5408,5372,5351,5337,5317,5297,5286,5276,5266,5288,5363,5454,5477,5394,5253,5139,
-5097,5104,5116,5112,5100,5089,5079,5064,5051,5042,5027,4989,4937,4899,4881,4851,4774,4663,4567,4509,4459,
-4386,4303,4247,4231,4221,4180,4103,4023,3988,4013,4064,4076,4007,3876,3739,3639,3575,3525,3473,3423,3381,
-3349,3322,3286,3228,3151,3067,3002,2975,2988,3017,3027,2995,2932,2863,2812,2793,2799,2807,2793,2757,2729,
-2718,2692,2616,2512,2448,2460,2511,2535,2501,2427,2350,2304,2300,2314,2307,2272,2245,2235,2197,2103,2014,
-2018,2096,2121,2018,1865,1793,1824,1869,1860,1819,1783,1751,1706,1660,1635,1623,1605,1589,1595,1615,1622,
-1609,1597,1596,1596,1586,1578,1585,1594,1589,1575,1565,1560,1547,1520,1487,1452,1412,1362,1318,1301,1316,
-1346,1356,1328,1280,1246,1244,1264,1283,1287,1280,1267,1251,1235,1220,1209,1204,1207,1214,1222,1227,1239,
-1261,1289,1309,1315,1315,1312,1310,1315,1337,1373,1413,1441,1453,1453,1449,1451,1465,1492,1526,1559,1583,
-1583,1560,1542,1556,1599,1629,1626,1614,1625,1649,1645,1603,1563,1564,1598,1632,1647,1651,1649,1634,1605,
-1573,1549,1534,1522,1512,1507,1504,1493,1469,1439,1413,1397,1383,1363,1334,1301,1269,1244,1223,1199,1169,
-1135,1103,1076,1050,1020,987,952,920,890,862,837,816,798,781,760,732,698,664,633,606,579,
-550,519,487,453,419,388,358,330,303,280,256,223,180,135,94,58,24,-10,-46,-82,-118,
--153,-189,-228,-270,-309,-341,-371,-405,-444,-485,-524,-564,-607,-655,-705,-752,-795,-835,-877,-923,-970,
--1016,-1061,-1107,-1153,-1199,-1242,-1283,-1322,-1358,-1395,-1433,-1472,-1511,-1547,-1581,-1612,-1643,-1675,-1709,-1742,-1776,
--1808,-1838,-1866,-1898,-1935,-1974,-2007,-2037,-2070,-2107,-2142,-2172,-2202,-2235,-2267,-2294,-2319,-2350,-2383,-2415,-2446,
--2477,-2510,-2542,-2574,-2607,-2637,-2663,-2687,-2715,-2745,-2775,-2800,-2823,-2846,-2869,-2894,-2918,-2940,-2960,-2978,-2995,
--3005,-3008,-3011,-3020,-3036,-3053,-3065,-3073,-3078,-3083,-3093,-3104,-3111,-3114,-3116,-3119,-3119,-3116,-3112,-3108,-3102,
--3092,-3083,-3076,-3065,-3045,-3024,-3008,-2994,-2975,-2952,-2932,-2914,-2895,-2872,-2850,-2829,-2808,-2786,-2763,-2737,-2706,
--2675,-2645,-2613,-2578,-2543,-2514,-2485,-2453,-2422,-2395,-2369,-2336,-2300,-2270,-2245,-2216,-2181,-2147,-2116,-2085,-2051,
--2018,-1985,-1949,-1910,-1871,-1833,-1797,-1762,-1731,-1701,-1667,-1630,-1595,-1559,-1520,-1480,-1445,-1413,-1379,-1344,-1310,
--1278,-1244,-1210,-1182,-1156,-1127,-1097,-1069,-1041,-1010,-980,-955,-932,-904,-874,-849,-825,-793,-756,-726,-706,
--685,-657,-627,-599,-573,-546,-522,-499,-472,-446,-429,-414,-389,-354,-322,-295,-263,-222,-185,-154,-118,
--74,-33,0,34,74,111,148,193,248,303,352,403,457,503,542,578,609,622,626,640,672,
-708,742,784,833,877,913,951,990,1021,1058,1112,1151,1145,1136,1188,1279,1317,1289,1294,1374,1441,
-1435,1423,1459,1458,1350,1261,1350,1550,1667,1712,1893,2248,2541,2608,2574,2588,2533,2236,1831,1657,1818,
-2067,2148,2052,1882,1637,1265,825,451,214,77,-13,-78,-121,-152,-172,-188,-222,-295,-395,-490,-564,
--626,-684,-725,-725,-674,-598,-543,-537,-569,-619,-677,-733,-763,-758,-757,-804,-887,-953,-995,-1081,-1262,
--1483,-1632,-1644,-1556,-1446,-1362,-1302,-1262,-1262,-1323,-1425,-1522,-1610,-1739,-1932,-2135,-2273,-2344,-2409,-2490,-2549,
--2566,-2578,-2619,-2670,-2701,-2735,-2819,-2963,-3128,-3275,-3380,-3424,-3409,-3366,-3333,-3318,-3303,-3278,-3261,-3270,-3310,
--3369,-3427,-3456,-3446,-3410,-3370,-3341,-3329,-3350,-3419,-3526,-3641,-3727,-3757,-3723,-3653,-3593,-3573,-3579,-3579,-3564,
--3549,-3533,-3503,-3461,-3425,-3400,-3370,-3327,-3282,-3245,-3206,-3154,-3092,-3026,-2954,-2876,-2806,-2754,-2711,-2660,-2593,
--2521,-2454,-2388,-2320,-2251,-2186,-2124,-2062,-1995,-1922,-1849,-1779,-1710,-1643,-1580,-1518,-1448,-1367,-1284,-1210,-1139,
--1062,-979,-899,-827,-757,-685,-612,-536,-458,-380,-309,-243,-173,-93,-7,75,151,218,272,316,350,
-379,411,453,505,553,589,618,650,682,708,735,772,812,839,853,869,891,908,918,937,971,
-1004,1024,1041,1070,1109,1145,1177,1212,1249,1281,1310,1342,1378,1411,1438,1463,1489,1514,1542,1576,1615,
-1654,1692,1730,1757,1763,1753,1740,1736,1735,1732,1730,1730,1733,1741,1755,1772,1788,1801,1820,1845,1870,
-1891,1913,1938,1964,1988,2011,2031,2044,2048,2048,2056,2076,2104,2137,2175,2216,2257,2290,2311,2323,2343,
-2393,2480,2592,2711,2828,2931,3001,3028,3026,3027,3039,3039,3006,2952,2910,2892,2879,2854,2821,2796,2780,
-2764,2737,2697,2644,2583,2529,2500,2503,2527,2553,2571,2574,2569,2564,2566,2566,2547,2499,2437,2383,2343,
-2305,2254,2194,2045,1994,1975,1969,1954,1917,1862,1799,1732,1669,1623,1605,1618,1650,1691,1743,1813,1900,
-1991,2060,2089,2072,2024,1965,1909,1867,1846,1852,1878,1911,1945,1982,2025,2065,2095,2119,2132,2120,2078,
-2033,2014,2013,1991,1925,1833,1748,1680,1625,1576,1533,1491,1448,1409,1374,1330,1270,1204,1146,1085,1003,
-902,804,728,663,593,528,485,463,430,348,213,49,-112,-253,-365,-450,-519,-586,-659,-721,-752,
--754,-750,-757,-772,-777,-764,-743,-728,-732,-761,-816,-873,-907,-909,-894,-887,-896,-919,-950,-988,-1027,
--1061,-1088,-1112,-1135,-1154,-1162,-1162,-1160,-1155,-1133,-1088,-1043,-1028,-1048,-1081,-1104,-1119,-1134,-1146,-1147,-1151,
--1179,-1228,-1275,-1302,-1312,-1312,-1300,-1279,-1260,-1252,-1249,-1250,-1259,-1283,-1309,-1322,-1325,-1337,-1367,-1411,-1458,
--1498,-1518,-1506,-1467,-1439,-1449,-1483,-1495,-1468,-1446,-1489,-1601,-1729,-1824,-1900,-1989,-2088,-2164,-2214,-2282,-2405,
--2568,-2725,-2842,-2916,-2957,-2976,-2982,-2985,-2989,-3003,-3047,-3132,-3234,-3316,-3363,-3394,-3431,-3482,-3547,-3625,-3708,
--3782,-3836,-3878,-3923,-3975,-4030,-4093,-4180,-4310,-4476,-4640,-4754,-4801,-4819,-4865,-4961,-5082,-5189,-5266,-5320,-5359,
--5383,-5400,-5423,-5451,-5463,-5440,-5389,-5342,-5326,-5339,-5356,-5359,-5357,-5364,-5387,-5418,-5449,-5483,-5521,-5562,-5600,
--5628,-5646,-5660,-5682,-5726,-5787,-5849,-5904,-5955,-6009,-6064,-6115,-6165,-6222,-6285,-6344,-6393,-6440,-6497,-6566,-6643,
--6723,-6807,-6897,-6996,-7102,-7206,-7302,-7388,-7472,-7562,-7657,-7750,-7835,-7915,-7997,-8080,-8165,-8252,-8345,-8440,-8530,
--8610,-8684,-8759,-8837,-8914,-8990,-9063,-9136,-9214,-9300,-9388,-9462,-9515,-9557,-9601,-9645,-9681,-9711,-9741,-9759,-9743,
--9692,-9649,-9668,-9762,-9887,-9985,-10033,-10047,-10062,-10093,-10135,-10176,-10210,-10240,-10271,-10301,-10328,-10342,-10342,-10346,-10382,
--10468,
--10579,-10662,-10684,-10659,-10627,-10613,-10610,-10599,-10575,-10543,-10503,-10455,-10406,-10360,-10314,-10256,-10184,-10105,-10020,-9923,-9807,
--9685,
--9572,-9469,-9360,-9237,-9115,-9009,-8916,-8815,-8693,-8552,-8402,-8257,-8122,-7993,-7851,-7686,-7510,-7342,-7182,-7016,-6842,
--6671,-6508,-6345,-6184,-6038,-5903,-5754,-5589,-5447,-5356,-5299,-5252,-5240,-5284,-5321,-5239,-5024,-4812,-4744,-4822,-4927,
--4953,-4852,-4594,-4177,-3686,-3277,-3042,-2940,-2865,-2771,-2671,-2569,-2443,-2297,-2172,-2094,-2042,-1971,-1860,-1723,-1583,
--1459,-1355,-1260,-1158,-1045,-927,-798,-653,-504,-386,-317,-275,-230,-175,-123,-80,-38,7,49,92,149,
-225,313,405,508,630,762,886,993,1087,1186,1301,1433,1563,1668,1747,1817,1891,1963,2026,2093,2179,
-2285,2391,2487,2579,2679,2787,2897,3006,3110,3206,3289,3363,3438,3527,3641,3777,3923,4061,4184,4298,4413,
-4530,4656,4794,4940,5076,5196,5314,5442,5564,5649,5688,5710,5745,5796,5851,5915,5997,6086,6152,6182,6187,
-6188,6188,6187,6198,6236,6305,6382,6447,6495,6539,6590,6648,6704,6734,6705,6592,6428,6318,6369,6566,6751,
-6744,6507,6154,5823,5559,5346,5196,5162,5287,5552,5899,6259,6561,6760,6860,6911,6953,6989,7000,6988,6969,
-6947,6919,6898,6913,6973,7048,7093,7090,7054,7010,6971,6935,6898,6865,6843,6834,6829,6819,6802,6788,6784,
-6785,6774,6744,6705,6678,6668,6663,6651,6636,6628,6630,6629,6615,6593,6570,6551,6536,6526,6521,6520,6522,
-6530,6542,6552,6553,6542,6518,6486,6454,6426,6398,6365,6334,6321,6318,6301,6259,6213,6191,6191,6192,6180,
-6158,6127,6095,6081,6089,6093,6058,5996,5947,5909,5830,5692,5555,5492,5488,5470,5412,5359,5345,5345,5329,
-5306,5296,5287,5261,5245,5281,5357,5403,5364,5267,5183,5155,5167,5175,5159,5134,5118,5111,5101,5084,5065,
-5043,5005,4952,4906,4878,4841,4763,4659,4579,4546,4525,4474,4399,4337,4304,4273,4209,4113,4028,4000,4037,
-4090,4096,4022,3894,3765,3670,3605,3553,3506,3465,3432,3405,3375,3334,3276,3203,3124,3060,3029,3031,3036,
-3016,2971,2931,2910,2891,2856,2813,2786,2777,2769,2757,2745,2722,2663,2572,2492,2462,2484,2522,2534,2494,
-2411,2331,2300,2313,2317,2290,2265,2258,2219,2114,2014,2024,2127,2173,2064,1888,1794,1815,1855,1845,1806,
-1779,1756,1716,1672,1651,1643,1627,1610,1613,1629,1630,1612,1599,1599,1597,1583,1573,1578,1589,1593,1590,
-1590,1590,1580,1556,1526,1492,1453,1405,1358,1326,1318,1330,1341,1331,1303,1277,1273,1289,1306,1312,1307,
-1294,1278,1261,1247,1234,1223,1219,1226,1237,1245,1253,1269,1292,1311,1318,1317,1314,1311,1313,1330,1365,
-1407,1437,1450,1449,1446,1449,1462,1488,1526,1569,1605,1614,1592,1563,1557,1575,1588,1579,1573,1601,1653,
-1687,1678,1650,1633,1636,1644,1652,1662,1671,1667,1646,1617,1590,1570,1553,1540,1533,1528,1517,1498,1473,
-1452,1435,1420,1400,1370,1334,1300,1270,1246,1220,1190,1158,1128,1102,1077,1047,1015,985,959,934,910,
-886,863,842,820,794,762,726,691,659,630,602,575,548,521,488,453,419,389,361,335,311,
-286,250,205,158,116,81,48,15,-16,-48,-80,-113,-147,-184,-224,-262,-294,-323,-355,-392,-431,
--471,-510,-551,-596,-645,-696,-744,-790,-835,-882,-930,-977,-1024,-1071,-1118,-1165,-1208,-1247,-1284,-1321,-1359,
--1397,-1435,-1472,-1508,-1543,-1575,-1605,-1635,-1667,-1700,-1734,-1768,-1801,-1832,-1863,-1899,-1934,-1965,-1993,-2026,-2063,
--2098,-2129,-2160,-2195,-2228,-2255,-2280,-2309,-2341,-2373,-2404,-2438,-2473,-2505,-2534,-2563,-2591,-2619,-2646,-2675,-2706,
--2734,-2759,-2780,-2800,-2823,-2848,-2875,-2897,-2914,-2931,-2948,-2961,-2967,-2973,-2985,-3004,-3023,-3035,-3041,-3043,-3048,
--3058,-3070,-3076,-3078,-3079,-3083,-3085,-3082,-3077,-3071,-3064,-3054,-3044,-3036,-3025,-3008,-2990,-2977,-2965,-2947,-2924,
--2902,-2882,-2860,-2836,-2815,-2795,-2774,-2752,-2729,-2701,-2671,-2641,-2615,-2586,-2553,-2520,-2492,-2464,-2434,-2404,-2380,
--2356,-2324,-2288,-2259,-2235,-2206,-2170,-2135,-2105,-2075,-2041,-2007,-1975,-1942,-1906,-1868,-1830,-1794,-1758,-1727,-1699,
--1668,-1632,-1597,-1562,-1526,-1488,-1453,-1420,-1386,-1351,-1319,-1287,-1254,-1222,-1194,-1167,-1137,-1107,-1079,-1053,-1024,
--994,-969,-947,-919,-888,-862,-838,-807,-770,-739,-717,-695,-669,-642,-619,-594,-568,-544,-522,-496,-467,
--443,-422,-399,-370,-340,-309,-269,-227,-195,-170,-137,-93,-49,-13,23,61,95,128,171,227,282,
-333,387,446,496,532,559,576,580,584,606,648,688,721,761,810,856,894,935,975,998,1012,
-1040,1076,1101,1134,1214,1315,1360,1339,1335,1390,1441,1441,1438,1459,1424,1294,1197,1264,1428,1539,1646,
-1923,2339,2641,2707,2696,2729,2651,2306,1887,1751,1951,2172,2146,1908,1619,1321,983,651,409,266,162,
-68,4,-25,-44,-70,-105,-156,-235,-331,-417,-479,-535,-596,-646,-649,-586,-485,-422,-454,-568,-695,
--785,-840,-878,-898,-893,-873,-859,-863,-901,-995,-1152,-1333,-1470,-1517,-1486,-1427,-1376,-1338,-1312,-1309,-1346,
--1412,-1482,-1565,-1701,-1891,-2075,-2196,-2273,-2364,-2472,-2542,-2551,-2544,-2568,-2618,-2670,-2733,-2831,-2965,-3115,-3258,
--3372,-3431,-3432,-3408,-3395,-3390,-3369,-3332,-3303,-3303,-3329,-3371,-3413,-3440,-3440,-3426,-3411,-3398,-3381,-3369,-3384,
--3441,-3533,-3626,-3674,-3649,-3572,-3500,-3472,-3475,-3474,-3461,-3449,-3437,-3416,-3390,-3371,-3358,-3331,-3288,-3241,-3202,
--3164,-3117,-3067,-3012,-2941,-2855,-2777,-2725,-2690,-2646,-2581,-2506,-2437,-2373,-2309,-2242,-2176,-2112,-2049,-1981,-1910,
--1839,-1770,-1699,-1630,-1569,-1512,-1447,-1367,-1283,-1208,-1139,-1065,-984,-905,-831,-756,-682,-609,-537,-463,-387,
--318,-256,-193,-118,-31,59,145,219,278,321,353,377,403,443,497,550,587,611,635,662,689,
-718,756,794,819,832,850,877,900,915,932,961,993,1020,1046,1080,1115,1144,1172,1210,1252,1284,
-1305,1327,1355,1385,1415,1443,1468,1488,1509,1539,1577,1619,1663,1704,1731,1729,1705,1684,1680,1690,1702,
-1708,1710,1712,1721,1738,1756,1770,1780,1795,1817,1841,1864,1889,1918,1947,1970,1989,2006,2018,2023,2025,
-2034,2057,2090,2127,2163,2197,2229,2256,2275,2285,2296,2326,2385,2469,2572,2690,2816,2928,3000,3028,3030,
-3024,3003,2961,2912,2886,2883,2874,2837,2780,2731,2701,2679,2652,2613,2561,2497,2438,2411,2423,2456,2486,
-2506,2517,2518,2505,2479,2444,2397,2339,2285,2247,2220,2180,2116,2045,1935,1901,1902,1911,1900,1865,1814,
-1755,1693,1634,1591,1574,1582,1610,1653,1713,1791,1881,1969,2040,2086,2101,2081,2033,1973,1922,1894,1885,
-1889,1906,1938,1969,1976,1956,1948,1991,2060,2082,2015,1909,1848,1853,1869,1838,1762,1683,1631,1600,1573,
-1539,1497,1457,1426,1397,1354,1289,1215,1147,1082,1002,906,806,717,638,562,494,447,422,393,321,
-186,6,-176,-326,-428,-496,-555,-624,-705,-771,-800,-796,-791,-804,-817,-806,-773,-744,-743,-770,-818,
--877,-932,-967,-974,-964,-956,-957,-968,-985,-1003,-1018,-1032,-1047,-1066,-1086,-1104,-1121,-1142,-1165,-1176,-1160,
--1114,-1064,-1041,-1051,-1072,-1086,-1099,-1121,-1149,-1170,-1194,-1235,-1289,-1329,-1341,-1332,-1316,-1291,-1253,-1214,-1184,
--1160,-1142,-1145,-1180,-1230,-1266,-1283,-1307,-1356,-1423,-1491,-1550,-1589,-1588,-1544,-1495,-1486,-1519,-1539,-1511,-1475,
--1506,-1622,-1763,-1869,-1945,-2033,-2137,-2225,-2284,-2347,-2451,-2594,-2744,-2869,-2955,-3002,-3020,-3025,-3025,-3017,-3010,
--3030,-3095,-3187,-3272,-3336,-3391,-3448,-3510,-3577,-3653,-3734,-3807,-3860,-3897,-3929,-3969,-4027,-4109,-4220,-4359,-4514,
--4661,-4762,-4799,-4799,-4820,-4903,-5034,-5165,-5260,-5317,-5356,-5392,-5428,-5452,-5447,-5405,-5342,-5289,-5274,-5299,-5335,
--5352,-5348,-5346,-5365,-5399,-5427,-5444,-5465,-5503,-5548,-5587,-5616,-5642,-5674,-5715,-5766,-5823,-5878,-5925,-5973,-6028,
--6088,-6143,-6195,-6252,-6315,-6375,-6425,-6469,-6520,-6584,-6655,-6730,-6806,-6889,-6981,-7080,-7181,-7278,-7368,-7456,-7548,
--7644,-7738,-7823,-7901,-7978,-8060,-8147,-8238,-8331,-8422,-8507,-8585,-8661,-8738,-8814,-8889,-8963,-9040,-9124,-9217,-9315,
--9406,-9476,-9524,-9564,-9607,-9650,-9685,-9716,-9745,-9757,-9732,-9676,-9634,-9657,-9751,-9875,-9975,-10027,-10045,-10061,-10097,
--10148,-10193,-10226,-10256,-10293,-10332,-10359,-10367,-10362,-10359,-10384,-10453,-10556,-10652,-10699,-10688,-10652,-10623,-10610,-10599,-10582,
--10556,
--10527,-10493,-10453,-10407,-10354,-10290,-10214,-10127,-10031,-9925,-9807,-9684,-9568,-9462,-9356,-9240,-9116,-8999,-8894,-8791,-8676,
--8544,-8404,-8268,-8138,-8004,-7854,-7684,-7508,-7337,-7173,-7007,-6841,-6680,-6525,-6372,-6219,-6071,-5920,-5751,-5569,-5414,
--5310,-5244,-5195,-5183,-5227,-5273,-5213,-5014,-4782,-4658,-4683,-4782,-4852,-4818,-4628,-4269,-3813,-3387,-3075,-2862,-2693,
--2549,-2445,-2372,-2296,-2201,-2111,-2047,-1998,-1935,-1838,-1707,-1560,-1419,-1302,-1202,-1103,-997,-885,-763,-625,-482,
--359,-268,-199,-139,-87,-48,-11,34,85,129,172,230,308,394,481,577,691,815,936,1044,1147,
-1254,1375,1506,1632,1735,1814,1885,1957,2027,2090,2155,2235,2331,2431,2527,2623,2725,2833,2939,3038,3130,
-3221,3317,3417,3513,3605,3707,3830,3965,4093,4216,4354,4517,4680,4812,4911,5000,5104,5230,5373,5522,5646,
-5718,5733,5724,5728,5766,5834,5917,5999,6061,6091,6093,6083,6081,6101,6148,6206,6260,6308,6360,6421,6484,
-6546,6607,6664,6708,6737,6750,6720,6626,6528,6554,6744,6945,6936,6664,6291,6000,5819,5684,5576,5537,5582,
-5695,5882,6164,6487,6738,6861,6912,6971,7036,7063,7048,7027,7012,6990,6971,6991,7060,7136,7170,7159,7126,
-7088,7045,6996,6948,6913,6896,6892,6886,6863,6833,6815,6815,6816,6796,6759,6727,6714,6709,6700,6683,6669,
-6662,6658,6649,6636,6620,6603,6585,6567,6555,6554,6560,6569,6577,6586,6591,6585,6565,6533,6497,6467,6443,
-6416,6383,6356,6347,6350,6335,6293,6249,6228,6223,6214,6195,6176,6158,6137,6120,6118,6111,6075,6018,5968,
-5917,5818,5673,5558,5531,5547,5519,5434,5360,5340,5343,5330,5311,5307,5304,5273,5235,5239,5290,5334,5326,
-5276,5231,5219,5226,5223,5194,5151,5119,5113,5122,5129,5120,5091,5039,4973,4918,4881,4839,4765,4673,4606,
-4589,4590,4568,4516,4456,4401,4333,4237,4124,4039,4013,4041,4076,4066,3993,3885,3783,3707,3649,3596,3544,
-3500,3468,3444,3416,3373,3313,3244,3176,3122,3092,3082,3068,3028,2979,2956,2968,2974,2936,2866,2810,2790,
-2783,2770,2749,2721,2672,2596,2518,2475,2493,2558,2626,2633,2553,2432,2350,2332,2333,2315,2294,2282,2238,
-2135,2041,2056,2158,2197,2082,1900,1799,1811,1847,1839,1808,1791,1775,1739,1700,1681,1671,1651,1628,1627,
-1641,1642,1625,1609,1603,1596,1582,1572,1575,1584,1593,1603,1617,1625,1618,1598,1572,1538,1496,1450,1405,
-1366,1336,1321,1320,1321,1314,1305,1304,1312,1323,1331,1331,1322,1305,1285,1270,1258,1245,1237,1242,1255,
-1267,1274,1286,1303,1320,1326,1324,1318,1312,1308,1318,1346,1386,1419,1436,1440,1441,1445,1458,1483,1519,
-1562,1598,1610,1594,1569,1558,1565,1570,1560,1556,1585,1644,1699,1723,1715,1693,1674,1662,1660,1670,1684,
-1691,1682,1658,1626,1594,1569,1555,1547,1538,1526,1511,1495,1479,1462,1443,1420,1393,1361,1328,1297,1268,
-1240,1212,1183,1156,1130,1101,1069,1038,1010,988,968,947,925,902,877,852,825,795,761,725,691,
-659,629,602,577,550,517,479,443,411,384,358,334,306,270,226,184,148,116,85,55,26,
--1,-31,-63,-97,-132,-170,-207,-241,-273,-307,-345,-385,-427,-468,-509,-551,-595,-644,-694,-744,-791,
--838,-885,-932,-979,-1028,-1078,-1127,-1170,-1207,-1243,-1282,-1324,-1364,-1401,-1436,-1471,-1505,-1535,-1564,-1593,-1624,
--1657,-1691,-1728,-1764,-1798,-1831,-1866,-1899,-1926,-1952,-1984,-2021,-2055,-2085,-2118,-2155,-2191,-2219,-2243,-2270,-2300,
--2331,-2363,-2399,-2435,-2465,-2491,-2516,-2544,-2574,-2604,-2635,-2665,-2693,-2717,-2738,-2758,-2782,-2809,-2837,-2859,-2874,
--2887,-2904,-2920,-2931,-2942,-2958,-2978,-2996,-3006,-3009,-3012,-3017,-3027,-3037,-3043,-3042,-3041,-3044,-3047,-3044,-3036,
--3027,-3019,-3009,-3001,-2993,-2983,-2970,-2956,-2945,-2934,-2916,-2893,-2871,-2849,-2826,-2802,-2781,-2762,-2741,-2718,-2695,
--2669,-2641,-2613,-2589,-2563,-2534,-2505,-2478,-2449,-2417,-2386,-2362,-2339,-2308,-2274,-2246,-2223,-2194,-2157,-2123,-2095,
--2066,-2032,-1997,-1965,-1933,-1898,-1862,-1828,-1792,-1755,-1723,-1695,-1667,-1634,-1600,-1566,-1533,-1498,-1465,-1431,-1396,
--1360,-1328,-1299,-1268,-1236,-1206,-1178,-1147,-1115,-1086,-1060,-1034,-1007,-984,-961,-932,-899,-869,-844,-817,-786,
--759,-737,-713,-686,-661,-640,-616,-587,-562,-543,-522,-493,-460,-429,-401,-375,-348,-314,-271,-229,-201,
--181,-153,-111,-68,-27,14,55,87,114,153,206,261,313,369,429,476,504,520,531,538,548,
-579,625,663,691,728,782,834,877,923,968,991,997,1022,1077,1138,1195,1270,1354,1399,1390,1380,
-1403,1428,1428,1427,1426,1359,1217,1120,1168,1297,1412,1588,1955,2431,2758,2842,2836,2825,2660,2255,1858,
-1796,2032,2204,2067,1718,1363,1067,804,590,455,365,262,158,99,85,69,27,-26,-85,-159,-246,
--327,-394,-454,-515,-564,-573,-521,-432,-380,-433,-580,-738,-836,-885,-930,-975,-973,-908,-825,-788,-826,
--921,-1044,-1177,-1299,-1385,-1421,-1416,-1396,-1380,-1371,-1372,-1387,-1412,-1449,-1521,-1657,-1842,-2010,-2124,-2215,-2331,
--2459,-2537,-2543,-2523,-2529,-2574,-2648,-2750,-2874,-3004,-3128,-3249,-3353,-3415,-3430,-3429,-3440,-3448,-3427,-3383,-3348,
--3340,-3350,-3366,-3385,-3399,-3406,-3411,-3422,-3432,-3426,-3402,-3381,-3386,-3432,-3499,-3542,-3522,-3449,-3378,-3350,-3352,
--3353,-3345,-3336,-3331,-3324,-3318,-3320,-3319,-3296,-3255,-3210,-3168,-3123,-3076,-3035,-2993,-2928,-2837,-2750,-2694,-2662,
--2626,-2568,-2496,-2424,-2359,-2298,-2236,-2172,-2106,-2039,-1972,-1903,-1836,-1767,-1696,-1625,-1561,-1503,-1439,-1361,-1279,
--1204,-1133,-1058,-978,-901,-826,-748,-668,-594,-526,-455,-382,-314,-255,-197,-127,-43,50,139,215,274,
-319,353,377,397,430,481,536,574,597,618,645,675,707,743,778,802,816,835,866,897,919,
-939,966,997,1028,1061,1096,1125,1145,1168,1204,1246,1278,1296,1312,1333,1358,1387,1418,1445,1464,1479,
-1503,1536,1575,1617,1658,1686,1687,1665,1644,1642,1656,1672,1681,1686,1693,1708,1727,1742,1749,1753,1763,
-1779,1799,1820,1848,1886,1923,1952,1970,1984,1994,1998,2002,2012,2035,2066,2100,2131,2158,2184,2209,2231,
-2248,2261,2282,2320,2376,2453,2558,2691,2832,2941,2993,2998,2978,2946,2907,2873,2857,2851,2825,2763,2687,
-2629,2598,2577,2552,2518,2472,2412,2356,2332,2344,2372,2393,2409,2426,2434,2417,2375,2324,2274,2227,2185,
-2153,2123,2074,2002,1935,1860,1847,1861,1869,1852,1812,1760,1703,1644,1589,1548,1526,1527,1552,1599,1668,
-1752,1839,1922,1995,2058,2103,2113,2083,2029,1976,1940,1917,1902,1904,1925,1942,1919,1867,1854,1923,2029,
-2058,1959,1804,1713,1721,1760,1751,1687,1616,1577,1565,1553,1526,1488,1453,1425,1392,1340,1268,1191,1122,
-1057,984,899,808,717,630,548,475,419,387,361,300,169,-23,-226,-386,-483,-540,-591,-657,-735,
--799,-829,-833,-839,-855,-858,-827,-781,-760,-784,-838,-895,-944,-983,-1009,-1019,-1017,-1009,-1002,-1002,-1009,
--1017,-1022,-1025,-1034,-1049,-1063,-1076,-1098,-1133,-1172,-1193,-1178,-1131,-1078,-1052,-1059,-1076,-1085,-1094,-1117,-1152,
--1186,-1220,-1261,-1307,-1336,-1339,-1328,-1312,-1285,-1240,-1189,-1146,-1107,-1071,-1063,-1104,-1177,-1239,-1270,-1293,-1342,
--1420,-1505,-1579,-1628,-1635,-1596,-1546,-1530,-1552,-1565,-1537,-1503,-1532,-1641,-1774,-1876,-1954,-2048,-2165,-2272,-2352,
--2424,-2518,-2640,-2770,-2887,-2976,-3029,-3050,-3056,-3054,-3040,-3022,-3026,-3073,-3153,-3241,-3321,-3395,-3463,-3525,-3588,
--3663,-3747,-3822,-3875,-3906,-3931,-3967,-4032,-4133,-4262,-4399,-4533,-4654,-4743,-4786,-4794,-4814,-4887,-5012,-5149,-5257,
--5325,-5371,-5415,-5454,-5460,-5414,-5331,-5258,-5235,-5265,-5315,-5348,-5349,-5334,-5333,-5360,-5400,-5428,-5442,-5462,-5501,
--5549,-5589,-5623,-5661,-5708,-5758,-5809,-5859,-5907,-5951,-5996,-6050,-6111,-6170,-6224,-6282,-6344,-6405,-6457,-6501,-6548,
--6604,-6667,-6735,-6808,-6885,-6968,-7057,-7151,-7247,-7341,-7433,-7526,-7623,-7719,-7805,-7881,-7957,-8040,-8131,-8224,-8313,
--8397,-8478,-8558,-8639,-8719,-8797,-8873,-8950,-9033,-9125,-9223,-9320,-9404,-9466,-9513,-9556,-9603,-9647,-9687,-9724,-9755,
--9759,-9717,-9647,-9605,-9635,-9736,-9862,-9961,-10014,-10035,-10060,-10108,-10168,-10216,-10244,-10269,-10308,-10353,-10383,-10390,-10383,
--10377,
--10391-10440,-10529,-10629,-10692,-10697,-10662,-10626,-10605,-10594,-10577,-10553,-10527,-10500,-10468,-10424,-10370,-10306,-10230,-10139,
--10037,
--9929,-9817,-9702,-9587,-9480,-9376,-9260,-9128,-8995,-8883,-8786,-8683,-8557,-8418,-8283,-8152,-8010,-7848,-7671,-7494,-7325,
--7160,-6998,-6838,-6684,-6537,-6390,-6239,-6082,-5916,-5741,-5566,-5416,-5307,-5229,-5171,-5150,-5183,-5229,-5194,-5028,-4794,
--4620,-4582,-4650,-4729,-4731,-4601,-4331,-3965,-3580,-3234,-2939,-2687,-2483,-2336,-2241,-2177,-2128,-2086,-2041,-1981,-1899,
--1795,-1668,-1525,-1381,-1254,-1147,-1050,-954,-852,-738,-609,-476,-359,-259,-168,-87,-28,7,43,93,148,
-194,237,298,382,471,558,649,754,869,984,1095,1206,1326,1455,1584,1701,1797,1875,1947,2019,2089,
-2156,2225,2303,2390,2484,2580,2679,2780,2884,2987,3083,3170,3254,3350,3458,3566,3668,3776,3903,4038,4163,
-4284,4432,4613,4793,4928,5009,5072,5159,5286,5435,5573,5662,5688,5672,5656,5670,5721,5799,5881,5941,5969,
-5978,5988,6004,6026,6064,6130,6206,6263,6299,6344,6412,6485,6549,6613,6677,6720,6740,6764,6784,6759,6705,
-6738,6922,7119,7100,6812,6442,6181,6039,5937,5869,5876,5924,5949,5989,6151,6437,6706,6851,6917,6991,7071,
-7104,7091,7081,7082,7066,7042,7062,7134,7204,7226,7208,7182,7156,7115,7060,7005,6963,6938,6928,6917,6893,
-6862,6844,6844,6837,6811,6779,6764,6761,6749,6724,6703,6697,6697,6688,6666,6643,6629,6620,6610,6596,6587,
-6588,6599,6612,6622,6628,6628,6616,6591,6556,6520,6489,6463,6434,6399,6371,6361,6364,6355,6324,6289,6266,
-6252,6230,6206,6194,6194,6190,6175,6159,6136,6097,6047,5997,5930,5817,5678,5592,5594,5622,5587,5488,5398,
-5361,5348,5325,5305,5307,5311,5292,5264,5261,5288,5311,5310,5297,5286,5280,5273,5254,5216,5163,5119,5113,
-5141,5174,5175,5133,5060,4983,4926,4890,4850,4787,4709,4653,4638,4644,4639,4607,4552,4479,4384,4268,4154,
-4073,4044,4053,4065,4044,3983,3901,3823,3760,3704,3649,3591,3538,3501,3478,3454,3410,3347,3280,3224,3183,
-3154,3133,3108,3066,3021,3003,3018,3027,2991,2918,2852,2816,2798,2780,2758,2729,2682,2614,2541,2497,2512,
-2591,2693,2735,2667,2524,2402,2353,2347,2335,2318,2305,2265,2175,2090,2093,2166,2185,2074,1909,1816,1820,
-1849,1847,1829,1820,1805,1770,1734,1715,1700,1672,1644,1638,1650,1655,1644,1626,1610,1595,1581,1576,1578,
-1584,1595,1618,1644,1659,1656,1640,1616,1581,1536,1491,1454,1418,1379,1346,1331,1332,1336,1336,1334,1333,
-1336,1344,1353,1351,1333,1309,1292,1280,1268,1258,1259,1274,1290,1300,1310,1322,1332,1334,1328,1322,1315,
-1310,1312,1331,1361,1392,1413,1423,1428,1433,1445,1468,1504,1546,1580,1596,1592,1582,1582,1592,1597,1586,
-1571,1574,1605,1653,1693,1712,1709,1697,1685,1678,1679,1686,1698,1706,1695,1661,1618,1585,1569,1560,1548,
-1532,1517,1505,1493,1475,1453,1429,1404,1379,1353,1324,1293,1263,1235,1209,1183,1153,1119,1085,1054,1029,
-1010,993,976,957,935,909,882,857,831,799,763,726,691,658,627,599,571,538,501,465,432,
-404,377,350,321,287,251,219,193,167,140,110,82,53,20,-15,-51,-87,-123,-160,-195,-230,
--268,-308,-350,-392,-434,-475,-515,-555,-598,-646,-696,-744,-790,-835,-880,-928,-978,-1030,-1080,-1125,-1164,
--1201,-1242,-1286,-1328,-1365,-1400,-1435,-1468,-1497,-1524,-1554,-1588,-1622,-1657,-1693,-1731,-1768,-1805,-1841,-1872,-1898,
--1922,-1951,-1987,-2020,-2049,-2081,-2118,-2154,-2182,-2206,-2232,-2260,-2289,-2320,-2356,-2392,-2423,-2448,-2472,-2501,-2532,
--2565,-2597,-2626,-2653,-2678,-2702,-2725,-2751,-2780,-2808,-2829,-2841,-2852,-2868,-2885,-2900,-2915,-2932,-2950,-2963,-2969,
--2974,-2980,-2987,-2996,-3005,-3009,-3007,-3003,-3003,-3005,-3002,-2993,-2983,-2975,-2968,-2961,-2954,-2945,-2932,-2920,-2909,
--2896,-2879,-2857,-2835,-2814,-2790,-2767,-2748,-2731,-2710,-2687,-2664,-2641,-2615,-2589,-2565,-2543,-2518,-2493,-2467,-2438,
--2403,-2370,-2344,-2319,-2289,-2255,-2229,-2206,-2177,-2141,-2108,-2082,-2055,-2023,-1989,-1958,-1926,-1892,-1859,-1827,-1793,
--1757,-1724,-1697,-1670,-1639,-1604,-1572,-1540,-1507,-1474,-1440,-1405,-1370,-1338,-1311,-1281,-1249,-1218,-1189,-1159,-1127,
--1096,-1069,-1043,-1017,-994,-972,-943,-909,-877,-852,-828,-803,-782,-763,-740,-711,-685,-664,-639,-608,-579,
--558,-539,-511,-475,-438,-405,-378,-351,-318,-275,-235,-207,-185,-157,-119,-80,-39,6,51,85,111,
-145,193,243,293,348,405,443,458,465,478,493,512,547,594,633,662,702,759,815,860,906,
-953,982,996,1035,1118,1207,1268,1315,1368,1408,1412,1399,1398,1406,1408,1402,1372,1279,1139,1052,1086,
-1192,1325,1564,1992,2486,2810,2892,2856,2759,2502,2090,1787,1827,2074,2161,1922,1520,1173,928,739,603,
-526,461,364,265,215,204,180,124,61,0,-71,-154,-236,-309,-376,-436,-480,-501,-487,-447,-427,
--484,-617,-753,-825,-850,-887,-943,-956,-888,-787,-741,-787,-885,-984,-1079,-1185,-1295,-1376,-1409,-1412,-1416,
--1430,-1444,-1448,-1443,-1450,-1505,-1631,-1803,-1959,-2072,-2171,-2295,-2425,-2507,-2521,-2504,-2502,-2538,-2624,-2754,-2901,
--3029,-3133,-3229,-3320,-3379,-3400,-3414,-3440,-3459,-3443,-3400,-3365,-3352,-3349,-3345,-3343,-3348,-3360,-3379,-3404,-3426,
--3433,-3420,-3392,-3367,-3364,-3381,-3389,-3355,-3287,-3227,-3206,-3214,-3223,-3225,-3226,-3228,-3234,-3248,-3269,-3280,-3264,
--3229,-3189,-3143,-3087,-3033,-2998,-2968,-2913,-2825,-2734,-2670,-2633,-2598,-2547,-2481,-2409,-2342,-2283,-2227,-2167,-2100,
--2031,-1964,-1898,-1832,-1766,-1695,-1622,-1553,-1490,-1423,-1349,-1273,-1199,-1126,-1046,-966,-893,-822,-743,-660,-583,
--515,-447,-375,-308,-249,-194,-128,-46,44,131,204,262,312,353,382,400,424,467,518,558,583,
-607,639,674,707,741,774,798,815,835,864,897,923,947,974,1004,1034,1066,1098,1123,1141,1161,
-1193,1229,1256,1274,1289,1306,1325,1351,1383,1413,1435,1451,1473,1501,1532,1565,1599,1627,1637,1629,1619,
-1620,1629,1638,1643,1650,1665,1686,1708,1720,1724,1727,1738,1755,1773,1791,1819,1858,1897,1928,1947,1959,
-1966,1970,1975,1988,2009,2036,2065,2093,2120,2144,2166,2186,2204,2220,2242,2273,2313,2366,2442,2552,2684,
-2800,2865,2877,2862,2842,2824,2809,2795,2769,2712,2628,2549,2506,2493,2485,2466,2436,2393,2338,2285,2257,
-2255,2259,2257,2263,2287,2309,2302,2267,2230,2200,2169,2131,2088,2040,1979,1910,1860,1807,1809,1821,1820,
-1797,1761,1716,1663,1607,1557,1518,1494,1492,1516,1566,1635,1713,1791,1864,1934,2005,2069,2107,2105,2070,
-2025,1984,1949,1920,1905,1906,1900,1868,1832,1851,1944,2044,2046,1919,1745,1637,1627,1653,1648,1602,1550,
-1522,1510,1492,1461,1424,1393,1363,1319,1254,1179,1108,1047,989,927,861,786,701,611,525,449,390,
-355,331,277,149,-49,-261,-424,-521,-575,-621,-678,-743,-799,-834,-855,-880,-904,-902,-864,-821,-818,
--865,-931,-981,-1008,-1024,-1037,-1048,-1050,-1044,-1034,-1029,-1032,-1036,-1035,-1034,-1040,-1052,-1061,-1069,-1088,-1121,
--1159,-1179,-1167,-1128,-1085,-1065,-1071,-1085,-1089,-1095,-1120,-1162,-1201,-1230,-1256,-1282,-1300,-1306,-1308,-1307,-1285,
--1237,-1184,-1143,-1105,-1065,-1048,-1089,-1178,-1264,-1308,-1325,-1359,-1427,-1514,-1591,-1638,-1646,-1625,-1602,-1599,-1611,
--1607,-1576,-1553,-1585,-1676,-1782,-1870,-1955,-2066,-2198,-2316,-2405,-2483,-2574,-2683,-2796,-2900,-2985,-3039,-3061,-3064,
--3058,-3044,-3027,-3027,-3063,-3134,-3223,-3316,-3403,-3475,-3533,-3592,-3670,-3758,-3833,-3878,-3903,-3928,-3976,-4063,-4187,
--4327,-4455,-4564,-4655,-4729,-4777,-4808,-4848,-4921,-5029,-5152,-5262,-5341,-5397,-5438,-5460,-5436,-5360,-5268,-5220,-5241,
--5301,-5347,-5355,-5337,-5319,-5324,-5354,-5395,-5428,-5452,-5480,-5522,-5570,-5615,-5658,-5706,-5756,-5800,-5841,-5886,-5936,
--5983,-6027,-6076,-6132,-6191,-6248,-6308,-6373,-6434,-6487,-6532,-6579,-6630,-6687,-6749,-6817,-6890,-6967,-7048,-7135,-7226,
--7316,-7405,-7495,-7592,-7690,-7779,-7857,-7934,-8022,-8116,-8207,-8291,-8369,-8450,-8533,-8618,-8702,-8783,-8864,-8947,-9037,
--9130,-9222,-9303,-9370,-9427,-9482,-9538,-9592,-9641,-9685,-9730,-9764,-9759,-9701,-9620,-9580,-9622,-9735,-9863,-9956,-10002,
--10023,-10055,-10114,-10184,-10236,-10261,-10281,-10316,-10361,-10394,-10406,-10404,-10398,-10400,-10428,-10496,-10587,-10658,-10677,-10654,-10620,
--10599,
--10587,-10571,-10548,-10523,-10495,-10460,-10412,-10355,-10292,-10220,-10133,-10034,-9932,-9829,-9722,-9610,-9500,-9392,-9271,-9131,-8992,
--8882,
--8797-8702,-8573,-8427,-8288,-8155,-8007,-7835,-7652,-7477,-7313,-7153,-6994,-6836,-6684,-6539,-6394,-6236,-6060,-5879,
--5710,-5564,-5443,-5341,-5252,-5179,-5139,-5148,-5183,-5171,-5047,-4829,-4621,-4520,-4537,-4594,-4601,-4514,-4331,-4071,-3759,
--3426,-3107,-2825,-2582,-2372,-2200,-2091,-2053,-2056,-2043,-1976,-1865,-1736,-1604,-1470,-1335,-1209,-1096,-997,-906,-812,
--703,-577,-453,-346,-250,-154,-62,3,44,83,137,196,245,294,362,451,546,635,725,826,936,
-1049,1163,1282,1409,1539,1662,1766,1849,1921,1993,2069,2145,2221,2297,2377,2460,2548,2643,2741,2837,2934,
-3034,3134,3224,3306,3393,3495,3607,3724,3852,3995,4137,4262,4380,4516,4679,4842,4974,5069,5148,5237,5350,
-5474,5573,5613,5598,5571,5575,5616,5676,5739,5795,5831,5843,5858,5901,5961,6014,6063,6128,6201,6255,6291,
-6344,6424,6497,6548,6607,6688,6754,6778,6791,6816,6820,6802,6856,7050,7250,7228,6938,6578,6337,6204,6097,
-6048,6119,6233,6253,6199,6234,6430,6672,6833,6926,7016,7097,7125,7123,7138,7155,7134,7096,7109,7179,7240,
-7247,7228,7216,7204,7166,7107,7048,7002,6972,6956,6944,6920,6889,6869,6861,6847,6818,6795,6791,6789,6768,
-6736,6722,6731,6741,6729,6698,6667,6648,6641,6635,6627,6620,6621,6633,6649,6661,6666,6659,6639,6609,6578,
-6549,6520,6491,6460,6428,6399,6385,6382,6375,6353,6321,6296,6275,6251,6228,6219,6226,6232,6225,6206,6175,
-6129,6075,6017,5940,5827,5710,5649,5662,5683,5641,5545,5457,5408,5373,5334,5308,5304,5305,5295,5289,5302,
-5320,5325,5325,5338,5356,5355,5329,5292,5248,5196,5152,5147,5184,5224,5216,5150,5056,4976,4929,4904,4875,
-4825,4761,4709,4685,4681,4676,4651,4601,4523,4423,4311,4205,4129,4092,4085,4083,4061,4013,3950,3883,3817,
-3757,3700,3644,3590,3547,3519,3494,3450,3387,3324,3279,3246,3216,3184,3151,3114,3077,3051,3043,3036,3007,
-2954,2897,2850,2816,2794,2780,2762,2723,2660,2588,2531,2519,2571,2662,2716,2669,2541,2421,2368,2360,2349,
-2333,2324,2297,2225,2144,2120,2152,2154,2066,1937,1857,1851,1867,1868,1860,1854,1838,1805,1771,1750,1730,
-1699,1669,1657,1661,1668,1666,1653,1631,1608,1593,1591,1592,1593,1604,1634,1668,1687,1684,1672,1653,1620,
-1575,1531,1499,1468,1430,1394,1373,1368,1368,1365,1357,1350,1348,1358,1372,1377,1361,1336,1315,1301,1288,
-1276,1274,1288,1307,1323,1335,1343,1346,1341,1333,1328,1328,1329,1332,1340,1355,1374,1391,1403,1411,1419,
-1431,1455,1493,1537,1574,1597,1607,1615,1628,1643,1647,1634,1606,1580,1573,1592,1629,1669,1698,1715,1722,
-1718,1703,1692,1698,1716,1723,1699,1654,1613,1590,1577,1561,1542,1524,1510,1496,1478,1455,1432,1410,1392,
-1373,1348,1317,1284,1253,1226,1200,1170,1135,1101,1074,1053,1036,1020,1005,988,967,940,913,888,862,
-830,791,752,714,677,641,609,582,554,524,493,462,433,404,376,347,317,289,266,246,224,
-198,169,138,104,65,24,-15,-51,-88,-124,-160,-197,-237,-279,-321,-362,-403,-443,-481,-519,-559,
--605,-653,-700,-745,-788,-832,-879,-928,-978,-1027,-1074,-1118,-1158,-1198,-1242,-1285,-1326,-1363,-1398,-1430,-1460,
--1489,-1522,-1558,-1594,-1630,-1665,-1702,-1739,-1776,-1814,-1848,-1875,-1899,-1927,-1961,-1993,-2021,-2050,-2084,-2117,-2145,
--2170,-2196,-2223,-2249,-2277,-2311,-2348,-2381,-2408,-2434,-2463,-2495,-2527,-2559,-2588,-2616,-2643,-2671,-2698,-2726,-2754,
--2781,-2801,-2813,-2824,-2839,-2857,-2873,-2889,-2906,-2920,-2926,-2929,-2936,-2947,-2957,-2965,-2972,-2975,-2971,-2964,-2962,
--2964,-2963,-2956,-2946,-2939,-2934,-2927,-2919,-2907,-2893,-2879,-2866,-2854,-2837,-2817,-2796,-2775,-2754,-2734,-2718,-2702,
--2683,-2660,-2637,-2614,-2589,-2563,-2539,-2517,-2495,-2472,-2448,-2420,-2387,-2354,-2326,-2300,-2269,-2237,-2211,-2188,-2159,
--2125,-2093,-2067,-2042,-2012,-1983,-1954,-1922,-1889,-1857,-1828,-1796,-1761,-1729,-1703,-1676,-1643,-1609,-1577,-1546,-1512,
--1478,-1446,-1413,-1378,-1347,-1320,-1292,-1259,-1227,-1199,-1172,-1142,-1112,-1084,-1057,-1029,-1003,-979,-953,-923,-894,
--871,-848,-826,-807,-789,-765,-735,-707,-683,-657,-626,-595,-568,-544,-515,-479,-443,-410,-382,-356,-324,
--285,-245,-214,-186,-155,-119,-86,-53,-12,34,73,107,145,190,232,273,323,373,402,407,411,
-428,449,471,505,554,602,642,688,746,800,839,880,927,964,990,1045,1144,1246,1302,1326,1356,
-1393,1404,1389,1379,1386,1390,1367,1304,1197,1076,1011,1041,1144,1314,1612,2057,2511,2777,2808,2703,2518,
-2224,1896,1751,1887,2089,2055,1738,1356,1087,920,781,667,598,541,463,385,345,329,294,234,165,
-92,9,-74,-147,-213,-280,-341,-389,-426,-455,-474,-499,-562,-665,-754,-779,-762,-770,-820,-856,-823,
--751,-723,-777,-876,-965,-1039,-1127,-1236,-1333,-1389,-1413,-1437,-1472,-1503,-1513,-1503,-1500,-1543,-1652,-1801,-1939,
--2044,-2139,-2250,-2364,-2443,-2475,-2477,-2480,-2510,-2592,-2726,-2876,-2998,-3088,-3174,-3260,-3318,-3339,-3352,-3377,-3398,
--3388,-3355,-3328,-3317,-3308,-3293,-3279,-3280,-3298,-3328,-3361,-3387,-3403,-3407,-3394,-3363,-3326,-3292,-3253,-3194,-3123,
--3071,-3059,-3074,-3095,-3112,-3125,-3135,-3150,-3180,-3218,-3240,-3234,-3207,-3171,-3122,-3057,-2996,-2961,-2940,-2896,-2821,
--2737,-2668,-2617,-2572,-2522,-2462,-2391,-2320,-2259,-2206,-2150,-2085,-2016,-1951,-1887,-1823,-1757,-1687,-1615,-1542,-1474,
--1406,-1336,-1265,-1196,-1122,-1041,-963,-893,-827,-751,-667,-588,-518,-451,-381,-313,-253,-196,-132,-55,30,
-114,185,242,294,344,383,406,428,464,510,548,574,602,640,680,714,746,778,805,826,846,
-871,898,922,946,972,999,1024,1050,1077,1103,1127,1151,1178,1203,1221,1236,1252,1267,1284,1307,1339,
-1372,1399,1420,1444,1470,1493,1515,1540,1566,1584,1593,1596,1598,1600,1599,1600,1608,1628,1655,1679,1693,
-1699,1707,1725,1748,1768,1786,1811,1843,1876,1903,1921,1934,1940,1945,1953,1969,1992,2018,2045,2074,2102,
-2123,2135,2144,2154,2171,2198,2233,2268,2299,2337,2400,2491,2585,2649,2674,2679,2683,2690,2691,2675,2631,
-2556,2469,2407,2390,2400,2404,2388,2359,2320,2270,2219,2182,2155,2126,2098,2096,2129,2166,2175,2157,2138,
-2126,2105,2063,2007,1948,1887,1835,1807,1767,1772,1775,1764,1742,1716,1680,1633,1581,1535,1502,1482,1480,
-1501,1543,1596,1655,1718,1783,1850,1923,1998,2059,2090,2086,2057,2017,1975,1937,1905,1876,1846,1823,1835,
-1900,1993,2048,2005,1871,1715,1601,1548,1530,1518,1502,1484,1464,1435,1395,1347,1303,1268,1229,1174,1104,
-1035,980,931,882,834,787,731,655,564,476,402,348,315,290,237,113,-77,-279,-434,-528,-584,
--631,-679,-730,-778,-820,-859,-900,-935,-942,-919,-896,-910,-962,-1019,-1051,-1059,-1057,-1059,-1066,-1069,-1065,
--1057,-1053,-1054,-1054,-1048,-1044,-1050,-1062,-1070,-1073,-1083,-1104,-1127,-1141,-1136,-1117,-1094,-1083,-1084,-1087,-1085,
--1091,-1124,-1172,-1209,-1226,-1236,-1250,-1267,-1285,-1305,-1316,-1295,-1244,-1192,-1162,-1140,-1109,-1087,-1117,-1206,-1305,
--1363,-1381,-1401,-1457,-1537,-1608,-1643,-1648,-1649,-1666,-1690,-1698,-1675,-1640,-1631,-1669,-1739,-1813,-1885,-1978,-2105,
--2242,-2356,-2439,-2516,-2607,-2711,-2814,-2909,-2988,-3041,-3063,-3062,-3049,-3032,-3018,-3021,-3056,-3124,-3214,-3314,-3409,
--3485,-3543,-3605,-3685,-3769,-3830,-3859,-3878,-3920,-4004,-4130,-4280,-4423,-4539,-4623,-4686,-4737,-4785,-4839,-4906,-4987,
--5075,-5169,-5266,-5353,-5415,-5443,-5431,-5377,-5292,-5225,-5221,-5278,-5340,-5359,-5338,-5313,-5309,-5327,-5358,-5398,-5437,
--5473,-5509,-5551,-5600,-5651,-5704,-5757,-5801,-5832,-5861,-5905,-5960,-6013,-6057,-6100,-6150,-6207,-6266,-6329,-6394,-6456,
--6510,-6559,-6610,-6663,-6716,-6772,-6834,-6904,-6977,-7055,-7137,-7221,-7303,-7381,-7463,-7556,-7653,-7744,-7827,-7909,-8000,
--8095,-8184,-8266,-8345,-8427,-8513,-8598,-8682,-8766,-8853,-8943,-9037,-9127,-9205,-9267,-9319,-9377,-9447,-9521,-9585,-9635,
--9680,-9728,-9763,-9755,-9691,-9608,-9574,-9626,-9746,-9875,-9961,-9997,-10012,-10045,-10110,-10186,-10244,-10273,-10292,-10322,-10361,
--10395,-10415,-10422,-10418,-10410,-10419,-10465,-10539,-10607,-10637,-10629,-10605,-10584,-10569,-10554,-10534,-10510,-10479,-10437,-10385,-10325,
--10264,
--10197,-10119,-10028,-9933,-9838,-9734,-9620,-9504,-9390,-9268,-9131,-8999,-8896,-8815,-8716,-8579,-8425,-8284,-8152,-8000,-7822,
--7637,-7466,-7309,-7154,-6997,-6837,-6683,-6537,-6391,-6223,-6026,-5828,-5669,-5560,-5476,-5387,-5291,-5201,-5139,-5119,-5135,
--5139,-5057,-4869,-4644,-4488,-4441,-4452,-4442,-4381,-4268,-4099,-3858,-3561,-3263,-3002,-2761,-2504,-2245,-2053,-1981,-1996,
--2008,-1950,-1827,-1683,-1545,-1415,-1289,-1167,-1051,-945,-851,-759,-653,-531,-409,-306,-217,-128,-42,25,72,
-119,176,236,290,347,423,519,620,715,809,911,1021,1138,1257,1376,1498,1619,1732,1825,1895,1956,
-2025,2105,2191,2276,2360,2442,2524,2609,2701,2794,2884,2975,3074,3178,3275,3360,3444,3539,3652,3786,3939,
-4100,4249,4373,4483,4597,4718,4842,4968,5099,5222,5326,5415,5495,5552,5561,5531,5515,5544,5598,5639,5662,
-5688,5716,5741,5779,5852,5943,6014,6063,6119,6186,6238,6279,6342,6432,6504,6540,6591,6685,6777,6816,6826,
-6847,6856,6848,6911,7113,7324,7308,7016,6657,6423,6291,6178,6138,6259,6451,6519,6434,6369,6458,6644,6812,
-6937,7042,7113,7134,7147,7189,7219,7186,7134,7143,7211,7261,7258,7242,7247,7245,7202,7131,7065,7019,6991,
-6980,6971,6948,6915,6890,6880,6864,6837,6815,6811,6805,6781,6754,6747,6759,6767,6754,6728,6701,6680,6668,
-6663,6658,6653,6654,6666,6684,6699,6701,6687,6659,6626,6598,6575,6548,6516,6485,6459,6436,6417,6406,6398,
-6379,6348,6319,6300,6284,6266,6251,6246,6249,6250,6240,6208,6154,6087,6020,5946,5854,5764,5715,5712,5705,
-5652,5569,5498,5451,5407,5361,5332,5319,5305,5288,5293,5325,5350,5353,5359,5393,5435,5441,5405,5352,5303,
-5256,5223,5225,5261,5287,5257,5166,5057,4976,4940,4930,4915,4877,4820,4764,4727,4708,4694,4669,4622,4552,
-4465,4368,4272,4192,4144,4125,4117,4096,4057,4003,3937,3866,3798,3742,3695,3647,3601,3564,3530,3484,3424,
-3370,3333,3306,3271,3227,3185,3150,3115,3078,3043,3017,2998,2976,2939,2886,2835,2807,2803,2799,2772,2718,
-2644,2565,2512,2520,2585,2642,2619,2523,2430,2390,2385,2371,2351,2343,2329,2272,2189,2136,2135,2133,2081,
-1992,1923,1898,1896,1894,1891,1885,1869,1841,1811,1787,1763,1735,1708,1691,1685,1689,1695,1691,1670,1641,
-1622,1616,1611,1607,1617,1648,1685,1704,1703,1694,1680,1653,1614,1573,1540,1509,1476,1444,1423,1409,1397,
-1383,1370,1362,1363,1374,1391,1398,1387,1364,1341,1324,1308,1293,1288,1298,1317,1336,1351,1361,1363,1356,
-1346,1343,1349,1361,1370,1372,1372,1372,1379,1389,1402,1416,1432,1458,1494,1537,1576,1604,1627,1648,1669,
-1684,1686,1675,1650,1616,1586,1579,1600,1641,1688,1732,1764,1771,1748,1715,1701,1713,1729,1722,1687,1645,
-1612,1590,1572,1554,1534,1516,1497,1477,1455,1433,1414,1399,1386,1367,1338,1303,1269,1241,1216,1188,1157,
-1128,1105,1088,1071,1052,1031,1011,989,962,934,908,880,846,807,766,727,688,650,618,594,575,
-555,531,504,477,449,422,394,365,338,316,296,273,244,213,180,141,98,55,16,-19,-55,
--91,-127,-164,-206,-250,-292,-330,-369,-409,-448,-487,-527,-572,-620,-666,-709,-751,-796,-842,-887,-932,
--977,-1025,-1071,-1112,-1151,-1192,-1237,-1281,-1321,-1357,-1391,-1423,-1456,-1491,-1529,-1567,-1603,-1637,-1670,-1703,-1739,
--1778,-1815,-1845,-1871,-1900,-1932,-1963,-1991,-2019,-2049,-2079,-2106,-2133,-2162,-2190,-2214,-2240,-2272,-2310,-2344,-2373,
--2400,-2430,-2461,-2492,-2522,-2552,-2582,-2612,-2642,-2670,-2697,-2723,-2748,-2768,-2782,-2796,-2812,-2830,-2846,-2862,-2879,
--2891,-2895,-2896,-2903,-2916,-2926,-2932,-2937,-2940,-2937,-2928,-2924,-2926,-2928,-2925,-2917,-2909,-2902,-2894,-2882,-2868,
--2851,-2836,-2823,-2811,-2796,-2777,-2757,-2738,-2720,-2703,-2689,-2675,-2655,-2632,-2609,-2588,-2564,-2537,-2512,-2489,-2465,
--2441,-2417,-2392,-2364,-2336,-2310,-2284,-2254,-2222,-2194,-2170,-2142,-2110,-2079,-2052,-2027,-1999,-1972,-1945,-1915,-1884,
--1854,-1827,-1796,-1763,-1733,-1707,-1678,-1644,-1611,-1582,-1551,-1516,-1483,-1452,-1421,-1387,-1355,-1329,-1301,-1269,-1236,
--1209,-1184,-1157,-1130,-1105,-1079,-1048,-1017,-991,-968,-943,-919,-898,-877,-853,-829,-806,-778,-745,-712,-685,
--660,-634,-605,-574,-542,-507,-472,-440,-411,-384,-357,-328,-292,-254,-220,-190,-157,-122,-94,-70,-41,
--2,41,86,136,183,219,251,290,333,357,360,366,387,412,434,466,518,576,626,676,733,
-781,814,850,900,949,988,1046,1142,1238,1290,1307,1330,1364,1376,1363,1357,1367,1361,1308,1219,1121,
-1043,1013,1051,1169,1388,1734,2166,2543,2718,2667,2476,2220,1947,1757,1772,1949,2052,1895,1554,1258,1108,
-1021,906,780,690,628,565,507,472,449,413,358,284,186,78,-9,-62,-106,-165,-233,-289,-336,
--388,-449,-517,-601,-692,-749,-735,-678,-649,-685,-742,-757,-731,-720,-769,-858,-943,-1008,-1081,-1177,-1275,
--1348,-1393,-1432,-1476,-1517,-1541,-1549,-1562,-1611,-1707,-1829,-1942,-2031,-2112,-2201,-2292,-2364,-2411,-2438,-2458,-2491,
--2566,-2688,-2822,-2929,-3012,-3099,-3188,-3247,-3261,-3259,-3268,-3282,-3279,-3262,-3251,-3247,-3238,-3216,-3192,-3186,-3209,
--3252,-3295,-3327,-3348,-3363,-3364,-3339,-3290,-3229,-3159,-3078,-2999,-2949,-2940,-2958,-2986,-3014,-3038,-3056,-3079,-3120,
--3170,-3202,-3201,-3179,-3147,-3097,-3030,-2967,-2929,-2907,-2873,-2817,-2751,-2686,-2621,-2561,-2506,-2447,-2375,-2299,-2232,
--2178,-2124,-2061,-1995,-1932,-1871,-1808,-1743,-1675,-1603,-1529,-1458,-1390,-1323,-1256,-1189,-1118,-1042,-967,-900,-835,
--762,-681,-603,-532,-464,-394,-325,-261,-201,-140,-70,8,87,155,210,263,321,373,409,438,474,
-515,549,573,602,642,685,720,751,782,811,834,853,874,894,914,935,959,984,1004,1023,1046,
-1074,1106,1136,1161,1177,1187,1197,1211,1226,1243,1267,1299,1332,1360,1386,1412,1438,1458,1475,1495,1518,
-1539,1556,1568,1573,1573,1570,1571,1582,1603,1631,1655,1671,1680,1692,1711,1732,1751,1771,1797,1826,1855,
-1880,1900,1913,1919,1923,1934,1955,1980,2005,2031,2060,2086,2102,2104,2102,2105,2122,2154,2193,2224,2236,
-2238,2256,2303,2370,2429,2465,2486,2502,2517,2522,2506,2462,2394,2326,2288,2290,2307,2312,2297,2272,2239,
-2197,2149,2101,2050,1993,1948,1946,1990,2039,2055,2042,2025,2011,1988,1946,1896,1848,1806,1776,1767,1736,
-1739,1732,1717,1699,1680,1650,1605,1558,1522,1498,1484,1481,1490,1507,1530,1565,1614,1675,1742,1817,1898,
-1977,2035,2058,2047,2014,1973,1930,1882,1826,1778,1772,1828,1922,1989,1983,1907,1800,1690,1581,1480,1410,
-1390,1407,1421,1402,1351,1286,1223,1169,1120,1070,1010,946,892,851,811,765,721,687,647,581,492,
-404,335,287,256,230,176,62,-106,-282,-417,-506,-568,-620,-667,-714,-762,-812,-861,-910,-953,-978,
--984,-986,-1006,-1044,-1079,-1097,-1097,-1090,-1084,-1083,-1083,-1081,-1076,-1074,-1074,-1069,-1060,-1055,-1062,-1074,-1081,
--1082,-1086,-1096,-1106,-1113,-1116,-1115,-1108,-1101,-1094,-1083,-1074,-1084,-1125,-1176,-1206,-1212,-1218,-1242,-1276,-1308,
--1335,-1344,-1319,-1264,-1213,-1193,-1187,-1168,-1144,-1159,-1232,-1329,-1399,-1428,-1447,-1494,-1569,-1635,-1659,-1657,-1672,
--1721,-1773,-1783,-1750,-1718,-1727,-1777,-1835,-1883,-1939,-2029,-2156,-2286,-2389,-2464,-2538,-2628,-2727,-2822,-2908,-2985,
--3042,-3068,-3065,-3043,-3018,-3002,-3010,-3049,-3118,-3208,-3308,-3405,-3489,-3559,-3628,-3703,-3769,-3808,-3823,-3851,-3926,
--4060,-4231,-4402,-4542,-4643,-4709,-4752,-4785,-4823,-4887,-4972,-5056,-5121,-5181,-5257,-5343,-5403,-5409,-5364,-5289,-5221,
--5197,-5236,-5307,-5350,-5338,-5304,-5291,-5309,-5340,-5372,-5409,-5454,-5497,-5536,-5576,-5623,-5678,-5735,-5788,-5826,-5850,
--5877,-5920,-5977,-6031,-6076,-6119,-6168,-6223,-6281,-6343,-6407,-6469,-6525,-6581,-6639,-6696,-6749,-6800,-6856,-6921,-6991,
--7067,-7145,-7223,-7296,-7365,-7439,-7524,-7617,-7708,-7794,-7881,-7971,-8063,-8152,-8238,-8323,-8408,-8493,-8576,-8660,-8749,
--8841,-8935,-9028,-9112,-9179,-9228,-9276,-9341,-9425,-9511,-9579,-9627,-9670,-9719,-9757,-9754,-9695,-9616,-9581,-9631,-9750,
--9878,-9963,-9995,-10006,-10035,-10098,-10175,-10238,-10275,-10298,-10325,-10360,-10395,-10422,-10436,-10433,-10418,-10412,-10436,-10489,-10547,
--10583,
--10590,-10576,-10555,-10535,-10520,-10504,-10482,-10450,-10408,-10358,-10301,-10241,-10178,-10106,-10022,-9932,-9838,-9733,-9615,-9494,-9380,
--9269,
--9150,-9030,-8927,-8833,-8720,-8575,-8422,-8286,-8154,-7998,-7816,-7633,-7467,-7313,-7158,-7000,-6840,-6685,-6541,-6395,-6221,
--6010,-5799,-5644,-5560,-5503,-5425,-5321,-5217,-5136,-5092,-5088,-5095,-5048,-4898,-4680,-4485,-4370,-4316,-4273,-4222,-4158,
--4053,-3865,-3609,-3351,-3139,-2936,-2679,-2372,-2108,-1969,-1942,-1939,-1885,-1775,-1642,-1510,-1381,-1254,-1129,-1009,-898,
--798,-706,-605,-490,-371,-265,-176,-94,-19,46,104,162,223,282,339,404,489,590,695,798,899,
-1003,1117,1239,1361,1475,1581,1688,1794,1884,1949,2002,2064,2142,2229,2319,2406,2492,2576,2660,2747,2836,
-2924,3016,3116,3219,3317,3406,3495,3594,3714,3864,4040,4215,4363,4480,4581,4675,4756,4837,4954,5117,5285,
-5405,5471,5516,5546,5543,5516,5512,5554,5601,5610,5598,5609,5649,5696,5750,5830,5926,5997,6039,6086,6150,
-6207,6254,6323,6418,6495,6531,6575,6663,6757,6808,6837,6876,6896,6885,6934,7127,7341,7327,7023,6639,6388,
-6260,6162,6137,6278,6511,6631,6570,6473,6494,6629,6795,6948,7070,7132,7143,7165,7225,7262,7226,7173,7188,
-7255,7293,7279,7266,7283,7287,7237,7151,7074,7025,7002,6997,6993,6971,6936,6912,6906,6896,6873,6851,6841,
-6831,6810,6790,6781,6778,6769,6756,6744,6730,6710,6693,6686,6687,6687,6691,6704,6723,6738,6739,6721,6689,
-6653,6625,6601,6570,6533,6502,6482,6463,6441,6424,6414,6399,6371,6342,6328,6323,6310,6285,6262,6253,6256,
-6253,6224,6162,6087,6021,5965,5898,5824,5765,5732,5696,5634,5562,5507,5467,5423,5381,5361,5352,5330,5301,
-5302,5341,5378,5390,5400,5439,5489,5505,5472,5416,5364,5325,5307,5319,5347,5352,5300,5197,5083,5000,4964,
-4961,4959,4931,4875,4812,4763,4733,4712,4684,4639,4580,4512,4432,4340,4251,4187,4157,4141,4117,4077,4029,
-3971,3904,3836,3782,3740,3700,3653,3605,3560,3510,3455,3408,3375,3347,3306,3253,3202,3164,3129,3086,3036,
-3001,2991,2990,2969,2916,2856,2823,2820,2819,2798,2752,2681,2591,2518,2513,2582,2651,2638,2546,2456,2421,
-2418,2403,2380,2371,2362,2313,2226,2155,2134,2138,2116,2056,1991,1947,1928,1922,1919,1913,1898,1877,1853,
-1827,1800,1774,1752,1733,1721,1721,1732,1735,1716,1685,1659,1644,1632,1623,1631,1662,1696,1715,1716,1708,
-1694,1672,1642,1610,1579,1546,1514,1488,1467,1445,1419,1394,1377,1372,1378,1390,1404,1411,1404,1388,1367,
-1347,1327,1312,1306,1311,1323,1339,1355,1369,1378,1376,1369,1364,1371,1387,1402,1403,1394,1384,1382,1390,
-1406,1424,1445,1470,1501,1538,1572,1600,1627,1655,1681,1696,1698,1695,1685,1665,1637,1616,1617,1642,1683,
-1734,1782,1809,1797,1755,1715,1702,1711,1716,1700,1666,1629,1600,1581,1565,1547,1525,1501,1478,1455,1434,
-1417,1405,1396,1382,1358,1327,1295,1267,1241,1214,1185,1158,1138,1122,1103,1076,1046,1020,995,969,941,
-915,888,856,819,780,744,709,674,646,626,612,598,577,552,527,502,476,447,414,384,358,
-334,306,274,241,206,166,122,80,43,10,-22,-56,-92,-131,-175,-219,-260,-298,-337,-377,-418,
--458,-499,-544,-592,-638,-681,-724,-768,-814,-857,-898,-939,-984,-1029,-1068,-1104,-1142,-1187,-1233,-1275,-1311,
--1346,-1383,-1419,-1455,-1493,-1532,-1570,-1605,-1635,-1665,-1698,-1736,-1773,-1805,-1832,-1862,-1894,-1926,-1954,-1981,-2011,
--2040,-2068,-2097,-2130,-2160,-2186,-2211,-2243,-2279,-2314,-2343,-2371,-2400,-2430,-2460,-2490,-2521,-2551,-2581,-2610,-2636,
--2661,-2684,-2707,-2728,-2745,-2762,-2781,-2799,-2815,-2832,-2851,-2865,-2870,-2871,-2876,-2885,-2893,-2897,-2902,-2906,-2904,
--2897,-2892,-2893,-2896,-2894,-2887,-2879,-2870,-2858,-2844,-2829,-2812,-2796,-2784,-2772,-2758,-2739,-2720,-2704,-2688,-2674,
--2659,-2644,-2624,-2601,-2581,-2562,-2540,-2514,-2488,-2463,-2436,-2410,-2385,-2363,-2339,-2315,-2292,-2269,-2240,-2208,-2178,
--2152,-2125,-2094,-2064,-2036,-2010,-1983,-1956,-1929,-1902,-1874,-1848,-1823,-1793,-1762,-1734,-1708,-1678,-1643,-1612,-1586,
--1557,-1523,-1491,-1462,-1432,-1398,-1365,-1338,-1312,-1282,-1252,-1225,-1200,-1173,-1147,-1126,-1102,-1071,-1039,-1012,-990,
--966,-943,-922,-901,-874,-843,-810,-778,-742,-706,-675,-649,-626,-603,-574,-538,-499,-465,-436,-409,-382,
--355,-327,-294,-258,-226,-199,-169,-135,-106,-87,-69,-40,2,55,111,159,192,216,247,284,308,
-316,328,354,383,409,445,498,556,605,653,707,755,786,821,878,943,997,1051,1126,1204,1253,
-1275,1298,1327,1340,1335,1335,1336,1301,1218,1128,1076,1065,1079,1130,1266,1526,1898,2302,2608,2708,2589,
-2323,2017,1777,1702,1805,1950,1938,1708,1414,1240,1203,1176,1075,937,825,747,681,624,584,554,523,
-478,400,280,149,59,23,-3,-56,-129,-188,-232,-284,-361,-462,-575,-678,-731,-708,-639,-592,-614,
--678,-725,-727,-715,-739,-807,-888,-957,-1028,-1117,-1219,-1306,-1365,-1405,-1442,-1480,-1516,-1550,-1594,-1660,-1751,
--1851,-1939,-2011,-2079,-2153,-2227,-2292,-2346,-2392,-2431,-2477,-2554,-2665,-2780,-2871,-2949,-3037,-3128,-3184,-3188,-3167,
--3158,-3163,-3167,-3169,-3173,-3177,-3168,-3140,-3105,-3089,-3111,-3164,-3221,-3261,-3284,-3299,-3300,-3278,-3235,-3179,-3107,
--3020,-2934,-2881,-2869,-2885,-2912,-2944,-2974,-2999,-3028,-3075,-3131,-3166,-3166,-3142,-3110,-3064,-3002,-2942,-2900,-2871,
--2838,-2798,-2753,-2697,-2628,-2559,-2500,-2443,-2372,-2290,-2217,-2159,-2103,-2041,-1977,-1917,-1857,-1796,-1732,-1666,-1594,
--1518,-1447,-1380,-1312,-1243,-1175,-1108,-1039,-969,-902,-834,-763,-686,-611,-540,-470,-400,-329,-263,-201,-142,
--80,-10,61,125,176,229,294,361,414,454,491,529,558,578,602,639,683,721,752,780,806,
-827,845,863,882,900,921,944,966,985,1002,1023,1053,1087,1119,1141,1153,1160,1169,1182,1197,1215,
-1240,1269,1298,1324,1350,1378,1405,1426,1444,1464,1486,1507,1526,1541,1550,1553,1555,1560,1573,1592,1616,
-1639,1656,1667,1676,1687,1698,1712,1732,1761,1795,1827,1855,1877,1890,1894,1896,1907,1929,1953,1975,1998,
-2026,2052,2068,2071,2069,2074,2092,2122,2154,2173,2169,2152,2146,2172,2227,2283,2322,2340,2347,2347,2341,
-2324,2294,2251,2210,2190,2193,2203,2202,2189,2172,2151,2118,2071,2013,1945,1874,1828,1835,1888,1940,1954,
-1934,1904,1878,1850,1820,1791,1768,1748,1736,1736,1708,1707,1699,1686,1673,1657,1626,1586,1550,1526,1511,
-1500,1490,1480,1466,1458,1471,1511,1568,1632,1706,1789,1872,1938,1975,1981,1961,1925,1879,1821,1752,1700,
-1708,1782,1870,1898,1850,1776,1720,1665,1568,1435,1335,1314,1349,1370,1338,1270,1197,1132,1070,1007,944,
-882,828,787,753,711,659,610,575,539,480,398,316,252,207,177,149,99,2,-135,-278,-393,
--480,-550,-613,-669,-722,-779,-838,-893,-944,-993,-1036,-1069,-1089,-1105,-1119,-1132,-1141,-1144,-1137,-1125,-1116,
--1113,-1111,-1107,-1103,-1098,-1092,-1083,-1080,-1085,-1093,-1095,-1096,-1101,-1108,-1111,-1114,-1119,-1123,-1120,-1113,-1100,
--1080,-1063,-1074,-1120,-1173,-1194,-1193,-1208,-1259,-1320,-1364,-1382,-1378,-1347,-1295,-1250,-1233,-1232,-1220,-1202,-1210,
--1266,-1353,-1428,-1467,-1489,-1528,-1595,-1656,-1677,-1669,-1685,-1748,-1818,-1840,-1816,-1800,-1830,-1892,-1947,-1983,-2025,
--2101,-2208,-2321,-2414,-2490,-2564,-2647,-2732,-2812,-2890,-2968,-3035,-3070,-3068,-3040,-3008,-2989,-3002,-3050,-3125,-3211,
--3304,-3400,-3495,-3581,-3655,-3717,-3760,-3783,-3804,-3861,-3981,-4157,-4353,-4527,-4657,-4744,-4804,-4843,-4867,-4894,-4947,
--5026,-5099,-5142,-5176,-5234,-5309,-5353,-5334,-5266,-5194,-5160,-5183,-5248,-5311,-5330,-5303,-5275,-5282,-5317,-5353,-5383,
--5420,-5469,-5518,-5557,-5594,-5637,-5688,-5741,-5789,-5828,-5860,-5893,-5937,-5988,-6038,-6086,-6135,-6188,-6241,-6295,-6352,
--6415,-6477,-6537,-6599,-6663,-6724,-6778,-6828,-6881,-6941,-7007,-7078,-7152,-7224,-7291,-7358,-7429,-7508,-7592,-7678,-7765,
--7851,-7938,-8025,-8114,-8206,-8298,-8387,-8470,-8552,-8641,-8736,-8832,-8925,-9012,-9089,-9151,-9200,-9254,-9326,-9416,-9502,
--9568,-9614,-9658,-9710,-9756,-9763,-9714,-9636,-9589,-9622,-9732,-9861,-9952,-9989,-10002,-10032,-10092,-10167,-10230,-10271,-10299,
--10326,-10360,-10396,-10427,-10442,-10435,-10412,-10396,-10404,-10436,-10478,-10514,-10533,-10530,-10512,-10492,-10479,-10467,-10446,-10414,-10375,
--10332,
--10281,-10222,-10159,-10090,-10011,-9922,-9823,-9715,-9597,-9481,-9378,-9286,-9188,-9076,-8960,-8840,-8707,-8563,-8422,-8295,-8162,
--8002,-7821,-7644,-7481,-7325,-7166,-7004,-6845,-6693,-6550,-6406,-6233,-6018,-5800,-5643,-5565,-5518,-5443,-5332,-5216,-5124,
--5063,-5039,-5039,-5012,-4905,-4718,-4512,-4340,-4213,-4118,-4053,-4007,-3931,-3780,-3566,-3361,-3207,-3062,-2851,-2564,-2278,
--2074,-1960,-1880,-1791,-1688,-1583,-1473,-1348,-1212,-1082,-965,-859,-760,-665,-569,-463,-350,-241,-145,-66,2,
-69,138,211,279,339,401,477,569,671,775,880,985,1091,1206,1331,1455,1562,1653,1746,1847,1943,
-2016,2071,2126,2196,2277,2363,2450,2537,2624,2709,2794,2882,2974,3073,3174,3267,3355,3445,3545,3658,3789,
-3951,4138,4316,4456,4564,4661,4749,4811,4866,4967,5137,5322,5451,5512,5544,5564,5555,5522,5513,5547,5583,
-5578,5557,5574,5630,5688,5738,5806,5892,5958,5996,6037,6102,6168,6222,6290,6385,6471,6522,6567,6637,6712,
-6764,6817,6888,6930,6919,6951,7121,7321,7297,6964,6527,6227,6091,6025,6024,6158,6379,6527,6531,6489,6517,
-6632,6792,6963,7104,7170,7174,7190,7249,7289,7264,7230,7258,7320,7340,7309,7291,7312,7320,7272,7186,7104,
-7048,7021,7015,7012,6990,6957,6937,6934,6927,6907,6888,6879,6869,6851,6834,6821,6802,6780,6768,6767,6758,
-6735,6714,6710,6717,6724,6732,6748,6765,6775,6773,6757,6727,6689,6655,6628,6594,6554,6521,6502,6484,6458,
-6436,6426,6417,6395,6370,6357,6354,6343,6318,6289,6271,6268,6263,6232,6167,6094,6042,6005,5950,5866,5782,
-5726,5683,5627,5563,5510,5465,5419,5383,5378,5389,5379,5348,5337,5369,5414,5436,5443,5465,5499,5515,5497,
-5453,5409,5380,5378,5396,5409,5389,5324,5227,5122,5036,4989,4980,4984,4965,4912,4845,4790,4756,4732,4699,
-4654,4603,4549,4483,4396,4299,4222,4178,4149,4115,4073,4032,3990,3940,3881,3827,3783,3743,3696,3643,3591,
-3538,3488,3445,3411,3377,3331,3272,3215,3171,3136,3095,3048,3010,2999,3003,2988,2943,2890,2857,2845,2832,
-2806,2766,2704,2618,2556,2578,2682,2766,2736,2606,2483,2434,2433,2424,2405,2397,2389,2345,2262,2185,2155,
-2157,2146,2101,2038,1986,1959,1951,1948,1940,1927,1912,1893,1869,1839,1812,1791,1773,1760,1760,1770,1773,
-1756,1726,1698,1677,1659,1647,1651,1675,1702,1719,1721,1711,1694,1671,1649,1629,1606,1578,1549,1525,1502,
-1474,1441,1409,1387,1380,1385,1398,1409,1413,1411,1402,1385,1363,1343,1331,1327,1328,1332,1339,1351,1367,
-1383,1392,1390,1382,1384,1397,1412,1414,1405,1397,1398,1408,1421,1435,1452,1474,1501,1532,1560,1583,1606,
-1634,1663,1683,1691,1695,1700,1696,1678,1656,1645,1653,1677,1715,1766,1811,1824,1795,1743,1701,1688,1693,
-1695,1680,1650,1620,1598,1580,1560,1537,1511,1484,1458,1435,1419,1411,1404,1394,1378,1357,1332,1304,1274,
-1242,1208,1179,1158,1141,1120,1088,1052,1020,995,971,945,920,897,871,842,810,779,750,722,698,
-680,665,648,624,595,568,543,516,484,448,414,385,359,329,295,260,223,184,141,99,63,
-32,3,-28,-63,-103,-147,-191,-231,-269,-309,-351,-392,-432,-472,-516,-563,-611,-656,-699,-743,-788,
--833,-874,-913,-953,-993,-1030,-1063,-1099,-1142,-1187,-1228,-1264,-1301,-1340,-1378,-1413,-1450,-1489,-1530,-1567,-1599,
--1629,-1661,-1696,-1730,-1762,-1791,-1822,-1854,-1884,-1912,-1941,-1972,-2003,-2032,-2063,-2098,-2131,-2158,-2184,-2216,-2252,
--2285,-2314,-2342,-2372,-2401,-2430,-2460,-2491,-2521,-2548,-2573,-2597,-2620,-2642,-2664,-2685,-2705,-2724,-2744,-2764,-2781,
--2798,-2817,-2833,-2843,-2845,-2847,-2852,-2857,-2863,-2870,-2876,-2876,-2869,-2864,-2863,-2862,-2859,-2853,-2845,-2835,-2822,
--2808,-2793,-2778,-2762,-2748,-2736,-2721,-2703,-2685,-2670,-2657,-2642,-2626,-2608,-2588,-2567,-2550,-2534,-2514,-2489,-2462,
--2437,-2411,-2385,-2360,-2338,-2315,-2292,-2271,-2250,-2224,-2193,-2162,-2135,-2109,-2079,-2047,-2018,-1991,-1965,-1939,-1913,
--1887,-1862,-1839,-1815,-1787,-1758,-1732,-1707,-1677,-1645,-1615,-1590,-1562,-1530,-1500,-1474,-1445,-1410,-1376,-1349,-1325,
--1299,-1272,-1246,-1219,-1189,-1162,-1142,-1121,-1093,-1063,-1038,-1015,-988,-959,-934,-910,-880,-844,-807,-772,-738,
--703,-670,-641,-616,-593,-569,-537,-500,-466,-438,-411,-382,-354,-327,-295,-261,-233,-211,-186,-152,-119,
--98,-82,-56,-17,31,80,120,148,169,197,231,258,273,290,319,354,390,434,486,533,572,
-616,674,727,759,793,856,938,1005,1053,1104,1163,1211,1240,1264,1292,1310,1315,1311,1285,1215,1126,
-1078,1105,1166,1214,1272,1417,1695,2069,2441,2703,2770,2618,2303,1960,1738,1713,1822,1895,1801,1577,1379,
-1314,1338,1333,1245,1114,992,894,810,740,687,648,618,578,499,375,241,152,115,89,36,-30,
--83,-120,-167,-249,-367,-504,-625,-694,-694,-647,-607,-619,-674,-721,-723,-695,-688,-733,-813,-895,-977,
--1075,-1185,-1281,-1341,-1373,-1398,-1429,-1471,-1521,-1585,-1664,-1753,-1840,-1912,-1973,-2036,-2105,-2174,-2236,-2294,-2349,
--2401,-2461,-2544,-2649,-2751,-2831,-2901,-2985,-3071,-3120,-3118,-3091,-3074,-3078,-3092,-3109,-3122,-3128,-3116,-3084,-3044,
--3022,-3041,-3095,-3156,-3199,-3219,-3225,-3217,-3195,-3166,-3135,-3085,-3007,-2921,-2865,-2850,-2859,-2879,-2907,-2940,-2971,
--3004,-3050,-3104,-3136,-3132,-3103,-3067,-3024,-2972,-2918,-2872,-2834,-2796,-2762,-2729,-2681,-2616,-2548,-2493,-2442,-2374,
--2293,-2218,-2157,-2099,-2037,-1974,-1913,-1851,-1790,-1729,-1664,-1591,-1513,-1441,-1374,-1306,-1233,-1162,-1095,-1031,-965,
--896,-825,-754,-682,-612,-541,-469,-397,-326,-259,-196,-138,-80,-15,51,111,159,211,281,360,425,
-470,506,539,564,581,602,635,677,717,750,775,796,813,829,848,868,888,909,930,950,969,
-988,1011,1040,1070,1097,1116,1129,1140,1151,1165,1179,1198,1220,1244,1266,1290,1317,1346,1372,1392,1412,
-1434,1457,1480,1501,1519,1530,1534,1536,1542,1553,1568,1590,1614,1635,1650,1660,1667,1672,1681,1700,1730,
-1764,1796,1823,1844,1855,1855,1856,1867,1889,1913,1934,1958,1987,2018,2041,2054,2063,2073,2089,2107,2121,
-2124,2108,2084,2076,2103,2157,2211,2243,2247,2233,2213,2193,2175,2157,2136,2115,2102,2100,2100,2096,2088,
-2079,2063,2033,1985,1925,1855,1789,1754,1772,1825,1869,1876,1851,1815,1782,1757,1741,1733,1725,1714,1707,
-1708,1681,1680,1673,1666,1660,1646,1619,1588,1566,1552,1538,1522,1503,1476,1442,1418,1423,1455,1500,1551,
-1614,1689,1762,1818,1857,1878,1876,1846,1796,1733,1668,1628,1640,1700,1751,1743,1688,1646,1640,1621,1535,
-1405,1311,1298,1328,1330,1279,1209,1148,1094,1028,949,870,803,750,710,673,625,565,505,459,415,
-358,286,214,157,114,81,53,11,-63,-171,-288,-391,-479,-560,-636,-706,-772,-841,-910,-973,-1030,
--1086,-1143,-1194,-1225,-1232,-1222,-1214,-1215,-1217,-1209,-1191,-1177,-1172,-1167,-1158,-1145,-1136,-1129,-1123,-1120,-1121,
--1119,-1116,-1118,-1126,-1133,-1135,-1135,-1136,-1135,-1130,-1124,-1111,-1082,-1050,-1052,-1102,-1161,-1182,-1178,-1204,-1282,
--1370,-1419,-1422,-1399,-1365,-1326,-1293,-1276,-1268,-1258,-1252,-1270,-1323,-1399,-1470,-1512,-1530,-1555,-1606,-1661,-1682,
--1674,-1687,-1753,-1835,-1878,-1878,-1884,-1929,-1995,-2048,-2081,-2117,-2176,-2259,-2350,-2436,-2515,-2590,-2662,-2728,-2791,
--2861,-2941,-3014,-3054,-3053,-3027,-2996,-2984,-3008,-3068,-3151,-3236,-3321,-3414,-3517,-3611,-3682,-3726,-3754,-3784,-3837,
--3937,-4092,-4283,-4474,-4629,-4739,-4814,-4874,-4920,-4949,-4967,-4996,-5045,-5094,-5127,-5156,-5203,-5257,-5274,-5233,-5162,
--5116,-5126,-5183,-5253,-5296,-5296,-5271,-5261,-5283,-5322,-5354,-5383,-5425,-5479,-5531,-5572,-5608,-5647,-5688,-5730,-5772,
--5818,-5865,-5911,-5955,-5999,-6044,-6095,-6152,-6208,-6259,-6307,-6361,-6422,-6485,-6548,-6613,-6680,-6744,-6801,-6855,-6909,
--6967,-7030,-7097,-7164,-7228,-7291,-7357,-7431,-7507,-7583,-7661,-7743,-7825,-7905,-7987,-8075,-8172,-8268,-8358,-8442,-8528,
--8624,-8726,-8825,-8915,-8995,-9065,-9126,-9184,-9249,-9327,-9414,-9492,-9554,-9603,-9651,-9706,-9758,-9777,-9739,-9657,-9591,
--9604,-9704,-9836,-9934,-9975,-9993,-10031,-10097,-10172,-10231,-10271,-10299,-10328,-10361,-10397,-10426,-10437,-10422,-10393,-10369,-10365,
--10382,
--10410,-10443,-10468,-10474,-10462,-10448,-10440,-10433,-10413,-10380,-10342,-10303,-10255,-10195,-10131,-10065,-9988,-9897,-9796,-9689,-9581,
--9479,
--9389,-9309,-9218,-9102,-8964,-8820,-8677,-8541,-8417,-8299,-8169,-8012,-7840,-7673,-7512,-7350,-7181,-7016,-6856,-6702,-6554,
--6407,-6239,-6031,-5813,-5648,-5562,-5514,-5442,-5330,-5209,-5109,-5038,-4995,-4975,-4951,-4881,-4745,-4562,-4363,-4175,-4017,
--3906,-3826,-3734,-3593,-3423,-3281,-3189,-3105,-2966,-2754,-2511,-2281,-2073,-1877,-1699,-1560,-1464,-1378,-1269,-1137,-1013,
--915,-830,-740,-640,-539,-439,-334,-226,-125,-43,23,91,171,256,334,403,475,563,662,761,858,
-958,1059,1163,1277,1405,1532,1637,1720,1802,1898,1999,2085,2151,2209,2272,2344,2424,2509,2596,2683,2769,
-2853,2942,3040,3146,3245,3327,3403,3495,3610,3737,3873,4030,4207,4372,4499,4602,4710,4816,4892,4945,5028,
-5174,5341,5466,5538,5583,5607,5586,5531,5496,5509,5533,5528,5515,5540,5601,5658,5701,5760,5840,5907,5946,
-5986,6053,6126,6185,6248,6334,6423,6491,6548,6612,6675,6728,6795,6882,6938,6940,6972,7120,7286,7232,6864,
-6365,5996,5834,5800,5839,5963,6144,6297,6385,6453,6546,6665,6809,6981,7142,7225,7228,7229,7271,7311,7309,
-7303,7341,7390,7387,7339,7311,7326,7335,7299,7228,7153,7092,7054,7041,7035,7016,6988,6970,6962,6948,6927,
-6914,6909,6899,6880,6865,6855,6840,6822,6813,6810,6795,6765,6744,6745,6757,6765,6773,6788,6802,6805,6800,
-6786,6757,6716,6678,6648,6618,6582,6551,6531,6510,6482,6458,6446,6439,6423,6402,6384,6374,6364,6349,6330,
-6312,6299,6285,6250,6186,6118,6079,6056,5998,5888,5777,5715,5692,5658,5598,5533,5477,5425,5390,5394,5425,
-5436,5410,5387,5404,5450,5484,5491,5488,5491,5496,5488,5463,5432,5415,5423,5441,5435,5390,5316,5232,5145,
-5063,5005,4986,4989,4976,4931,4868,4811,4772,4740,4703,4657,4611,4566,4512,4435,4341,4256,4196,4155,4115,
-4074,4039,4010,3974,3926,3872,3824,3780,3733,3681,3626,3572,3527,3488,3453,3412,3360,3300,3240,3192,3156,
-3120,3078,3040,3020,3015,3004,2974,2938,2911,2888,2858,2824,2791,2737,2658,2606,2651,2779,2866,2808,2637,
-2484,2426,2430,2430,2415,2406,2399,2363,2292,2222,2185,2173,2156,2116,2064,2019,1993,1984,1979,1969,1954,
-1940,1926,1907,1880,1853,1830,1811,1800,1798,1802,1800,1787,1765,1742,1718,1695,1678,1676,1686,1701,1713,
-1715,1705,1684,1660,1642,1631,1619,1600,1577,1550,1523,1494,1464,1434,1406,1388,1385,1395,1404,1408,1408,
-1403,1391,1371,1353,1346,1346,1345,1343,1343,1348,1360,1377,1392,1396,1391,1389,1397,1407,1406,1400,1405,
-1423,1440,1448,1448,1452,1466,1490,1520,1547,1564,1578,1598,1627,1653,1670,1681,1690,1692,1682,1665,1656,
-1659,1672,1695,1733,1782,1819,1819,1779,1725,1689,1681,1687,1687,1673,1651,1627,1603,1577,1552,1526,1498,
-1466,1439,1424,1417,1411,1401,1391,1379,1362,1335,1299,1260,1221,1189,1165,1148,1128,1098,1064,1033,1008,
-986,962,939,920,901,879,853,827,802,778,756,736,716,692,662,628,596,567,539,506,468,
-433,404,379,350,315,277,238,198,156,114,77,47,19,-8,-41,-80,-121,-162,-201,-241,-284,
--328,-370,-409,-446,-486,-532,-581,-629,-672,-714,-759,-806,-851,-890,-926,-963,-998,-1031,-1066,-1105,-1146,
--1185,-1221,-1260,-1300,-1337,-1370,-1405,-1444,-1485,-1524,-1559,-1592,-1626,-1660,-1693,-1724,-1755,-1787,-1819,-1848,-1874,
--1904,-1937,-1969,-1999,-2030,-2063,-2096,-2124,-2152,-2184,-2220,-2253,-2282,-2311,-2342,-2371,-2400,-2430,-2461,-2488,-2511,
--2534,-2557,-2582,-2604,-2625,-2646,-2666,-2685,-2705,-2726,-2744,-2759,-2776,-2793,-2805,-2810,-2811,-2814,-2821,-2830,-2840,
--2848,-2849,-2845,-2839,-2834,-2828,-2821,-2815,-2810,-2802,-2789,-2774,-2759,-2744,-2728,-2713,-2700,-2684,-2667,-2650,-2637,
--2624,-2607,-2589,-2571,-2552,-2534,-2518,-2503,-2483,-2456,-2430,-2406,-2384,-2361,-2338,-2316,-2293,-2269,-2247,-2227,-2204,
--2176,-2146,-2120,-2094,-2063,-2030,-1999,-1972,-1948,-1923,-1899,-1875,-1852,-1828,-1804,-1779,-1753,-1728,-1704,-1677,-1647,
--1620,-1594,-1566,-1535,-1508,-1483,-1455,-1422,-1389,-1362,-1339,-1313,-1288,-1263,-1236,-1205,-1176,-1154,-1132,-1107,-1081,
--1059,-1036,-1006,-971,-937,-907,-875,-839,-802,-769,-739,-709,-679,-647,-617,-590,-566,-539,-506,-475,-447,
--419,-389,-360,-333,-304,-271,-245,-225,-203,-169,-133,-106,-85,-56,-16,23,54,78,98,120,148,
-183,214,237,256,284,322,366,416,465,502,533,579,644,704,737,768,831,922,997,1039,1073,
-1119,1169,1207,1235,1265,1292,1299,1275,1213,1129,1077,1110,1218,1325,1385,1443,1596,1878,2233,2569,2801,
-2854,2684,2341,1982,1775,1768,1850,1864,1754,1593,1491,1479,1497,1475,1397,1285,1163,1046,943,862,801,
-754,714,665,586,473,358,275,227,187,136,83,39,0,-55,-146,-272,-416,-547,-635,-669,-660,
--642,-649,-684,-716,-707,-663,-636,-666,-746,-841,-939,-1048,-1163,-1256,-1309,-1333,-1355,-1389,-1434,-1487,-1552,
--1632,-1719,-1800,-1867,-1926,-1989,-2060,-2131,-2197,-2258,-2316,-2372,-2434,-2517,-2616,-2707,-2775,-2837,-2910,-2985,-3030,
--3034,-3018,-3011,-3024,-3049,-3075,-3092,-3094,-3080,-3053,-3021,-3004,-3019,-3061,-3108,-3139,-3153,-3153,-3137,-3113,-3099,
--3096,-3076,-3018,-2940,-2886,-2869,-2871,-2878,-2897,-2930,-2968,-3006,-3050,-3096,-3119,-3108,-3073,-3033,-2991,-2941,-2891,
--2844,-2800,-2758,-2722,-2687,-2642,-2581,-2521,-2472,-2426,-2367,-2296,-2227,-2167,-2108,-2047,-1984,-1920,-1854,-1790,-1730,
--1667,-1595,-1516,-1442,-1375,-1307,-1232,-1158,-1089,-1025,-959,-890,-818,-748,-680,-613,-544,-471,-399,-330,-263,
--199,-138,-77,-12,54,112,159,211,283,365,434,479,511,540,565,585,605,635,674,712,744,
-769,787,804,821,841,862,881,900,918,935,953,974,1000,1028,1054,1075,1091,1106,1121,1137,1151,
-1164,1180,1199,1219,1239,1262,1291,1319,1339,1354,1371,1392,1417,1444,1472,1495,1506,1506,1501,1501,1507,
-1522,1547,1577,1605,1627,1642,1654,1663,1674,1691,1714,1739,1763,1785,1802,1811,1812,1816,1830,1855,1883,
-1909,1938,1972,2006,2034,2053,2067,2078,2088,2095,2097,2090,2069,2046,2041,2068,2118,2162,2179,2169,2145,
-2118,2096,2081,2069,2057,2042,2028,2021,2018,2015,2009,2000,1980,1948,1906,1857,1806,1762,1745,1764,1800,
-1824,1822,1801,1773,1746,1726,1718,1715,1706,1692,1682,1681,1661,1661,1657,1656,1655,1645,1626,1608,1595,
-1580,1557,1532,1507,1477,1442,1423,1433,1459,1484,1510,1554,1613,1666,1704,1740,1773,1786,1759,1703,1641,
-1593,1572,1582,1605,1607,1573,1532,1525,1544,1531,1456,1358,1302,1304,1316,1289,1228,1172,1134,1091,1020,
-923,825,744,682,633,589,538,476,410,349,292,232,169,109,58,15,-18,-47,-80,-138,-225,
--327,-425,-515,-603,-691,-776,-856,-935,-1013,-1086,-1154,-1220,-1289,-1353,-1392,-1392,-1362,-1330,-1315,-1307,-1293,
--1273,-1257,-1248,-1235,-1214,-1192,-1179,-1173,-1167,-1161,-1155,-1150,-1146,-1150,-1158,-1161,-1160,-1160,-1160,-1156,-1148,
--1144,-1130,-1087,-1032,-1018,-1072,-1143,-1170,-1165,-1196,-1293,-1404,-1460,-1448,-1406,-1369,-1346,-1332,-1316,-1296,-1281,
--1288,-1325,-1383,-1447,-1504,-1540,-1555,-1568,-1604,-1650,-1673,-1669,-1683,-1751,-1843,-1908,-1935,-1961,-2010,-2067,-2112,
--2145,-2184,-2238,-2303,-2376,-2455,-2533,-2606,-2670,-2726,-2780,-2846,-2922,-2990,-3024,-3021,-3001,-2985,-2991,-3030,-3103,
--3194,-3283,-3368,-3460,-3559,-3646,-3703,-3736,-3770,-3830,-3927,-4064,-4231,-4410,-4573,-4700,-4786,-4845,-4898,-4950,-4991,
--5007,-5010,-5020,-5046,-5082,-5125,-5169,-5197,-5186,-5135,-5084,-5077,-5123,-5195,-5251,-5270,-5260,-5246,-5254,-5284,-5319,
--5348,-5381,-5429,-5486,-5538,-5579,-5615,-5651,-5683,-5714,-5752,-5803,-5863,-5921,-5969,-6011,-6054,-6106,-6165,-6221,-6270,
--6318,-6372,-6432,-6494,-6558,-6624,-6691,-6757,-6820,-6880,-6938,-6996,-7059,-7126,-7191,-7247,-7301,-7364,-7438,-7513,-7583,
--7653,-7727,-7803,-7877,-7954,-8041,-8137,-8234,-8325,-8413,-8506,-8608,-8713,-8812,-8900,-8975,-9042,-9106,-9174,-9251,-9334,
--9414,-9486,-9546,-9599,-9650,-9703,-9754,-9782,-9753,-9672,-9594,-9593,-9689,-9825,-9922,-9958,-9976,-10023,-10101,-10181,-10238,
--10273,-10301,-10329,-10361,-10394,-10420,-10426,-10407,-10374,-10347,-10337,-10343,-10363,-10392,-10417,-10426,-10418,-10408,-10407,-10406,-10390,
--10357,
--10318,-10278,-10228,-10167,-10104,-10040,-9968,-9878,-9779,-9682,-9590,-9501,-9414,-9323,-9216,-9083,-8932,-8780,-8638,-8510,-8396,
--8287,-8167,-8026,-7870,-7710,-7549,-7378,-7202,-7030,-6862,-6697,-6538,-6386,-6225,-6032,-5822,-5650,-5551,-5497,-5431,-5327,
--5209,-5107,-5029,-4970,-4923,-4883,-4831,-4746,-4612,-4428,-4215,-4008,-3832,-3679,-3521,-3353,-3208,-3119,-3080,-3047,-2978,
--2861,-2702,-2497,-2236,-1932,-1639,-1421,-1296,-1220,-1134,-1026,-927,-861,-808,-732,-626,-512,-409,-311,-208,-106,
--20,49,119,202,295,382,463,548,647,751,847,935,1024,1117,1219,1334,1464,1594,1702,1785,1861,
-1947,2043,2138,2220,2290,2354,2422,2498,2582,2666,2750,2834,2921,3011,3110,3215,3314,3395,3475,3577,3708,
-3842,3968,4098,4240,4377,4490,4599,4733,4880,4995,5068,5139,5244,5367,5474,5558,5627,5661,5633,5558,5496,
-5481,5485,5471,5450,5462,5511,5569,5623,5688,5766,5832,5875,5920,5987,6062,6124,6183,6258,6342,6417,6486,
-6563,6642,6712,6783,6859,6918,6949,7005,7130,7234,7127,6732,6201,5779,5586,5583,5684,5835,5999,6155,6311,
-6478,6631,6743,6849,7000,7170,7273,7283,7270,7295,7335,7355,7371,7409,7442,7424,7370,7337,7339,7341,7312,
-7256,7192,7131,7086,7067,7060,7048,7029,7013,6997,6974,6950,6941,6938,6921,6895,6878,6876,6875,6868,6862,
-6853,6829,6800,6786,6793,6802,6802,6805,6817,6829,6831,6824,6810,6779,6733,6691,6663,6639,6611,6583,6562,
-6541,6516,6493,6478,6467,6453,6436,6417,6397,6384,6379,6374,6359,6338,6316,6281,6215,6143,6108,6098,6046,
-5923,5794,5733,5730,5713,5651,5574,5513,5463,5428,5428,5463,5486,5467,5434,5435,5477,5524,5542,5530,5510,
-5497,5486,5469,5444,5432,5443,5458,5440,5378,5297,5221,5152,5082,5027,5001,4997,4986,4948,4892,4833,4780,
-4734,4692,4651,4611,4572,4527,4464,4380,4293,4224,4176,4138,4101,4066,4032,3996,3954,3906,3859,3815,3770,
-3718,3660,3606,3565,3533,3499,3453,3395,3334,3277,3228,3190,3154,3112,3068,3038,3028,3023,3008,2988,2968,
-2938,2898,2861,2834,2786,2702,2635,2662,2772,2847,2785,2622,2484,2441,2452,2452,2431,2413,2398,2366,2311,
-2255,2216,2187,2155,2118,2081,2050,2027,2015,2007,1995,1977,1961,1948,1937,1920,1898,1874,1855,1841,1834,
-1830,1825,1817,1805,1788,1762,1732,1707,1695,1693,1697,1703,1706,1699,1680,1659,1643,1634,1627,1614,1592,
-1562,1529,1503,1486,1465,1432,1400,1385,1389,1397,1400,1400,1399,1391,1375,1362,1360,1362,1361,1356,1353,
-1353,1358,1367,1380,1388,1389,1390,1397,1399,1392,1389,1408,1445,1477,1486,1477,1467,1467,1481,1506,1532,
-1547,1552,1562,1585,1614,1639,1656,1668,1672,1667,1657,1655,1665,1678,1692,1712,1748,1792,1819,1808,1764,
-1715,1685,1677,1678,1676,1667,1650,1625,1596,1570,1545,1515,1479,1448,1430,1423,1415,1403,1393,1385,1371,
-1345,1308,1270,1234,1202,1178,1160,1143,1119,1092,1065,1042,1019,996,974,957,940,920,896,871,847,
-824,800,774,748,721,689,654,620,588,558,526,491,456,426,399,369,333,293,252,212,172,
-132,95,64,37,10,-20,-55,-92,-130,-169,-212,-258,-304,-347,-385,-420,-457,-501,-550,-600,-643,
--683,-726,-774,-822,-862,-897,-933,-970,-1005,-1040,-1076,-1113,-1149,-1187,-1227,-1266,-1300,-1330,-1363,-1402,-1441,
--1478,-1512,-1547,-1584,-1620,-1654,-1687,-1721,-1756,-1787,-1815,-1841,-1871,-1904,-1937,-1967,-1994,-2024,-2055,-2084,-2114,
--2148,-2184,-2217,-2247,-2278,-2310,-2339,-2367,-2396,-2427,-2453,-2474,-2496,-2522,-2548,-2570,-2591,-2611,-2631,-2650,-2669,
--2689,-2707,-2721,-2732,-2746,-2758,-2765,-2769,-2775,-2785,-2799,-2812,-2820,-2821,-2818,-2812,-2804,-2795,-2787,-2782,-2779,
--2773,-2759,-2741,-2723,-2707,-2692,-2678,-2664,-2650,-2633,-2618,-2604,-2590,-2572,-2554,-2537,-2520,-2503,-2487,-2470,-2447,
--2420,-2393,-2373,-2355,-2335,-2314,-2293,-2271,-2247,-2224,-2203,-2182,-2157,-2130,-2105,-2079,-2048,-2013,-1981,-1954,-1930,
--1908,-1887,-1867,-1843,-1818,-1793,-1770,-1747,-1723,-1699,-1674,-1649,-1624,-1598,-1570,-1540,-1514,-1489,-1462,-1431,-1401,
--1375,-1350,-1323,-1295,-1270,-1243,-1213,-1185,-1161,-1138,-1113,-1089,-1068,-1045,-1014,-976,-938,-903,-869,-836,-804,
--773,-744,-716,-690,-661,-629,-599,-573,-546,-515,-484,-457,-432,-403,-373,-346,-318,-289,-262,-242,-220,
--187,-151,-123,-98,-64,-22,11,29,40,55,77,107,143,180,209,231,257,292,337,387,432,
-467,500,549,617,678,713,744,807,898,975,1014,1039,1082,1137,1183,1216,1247,1272,1265,1212,1130,
-1072,1094,1209,1364,1480,1539,1613,1786,2065,2386,2673,2864,2885,2688,2330,1987,1820,1838,1907,1907,1831,
-1750,1709,1690,1660,1608,1537,1440,1315,1182,1070,991,932,881,829,766,682,582,488,415,357,305,
-257,216,175,123,48,-54,-183,-325,-454,-552,-610,-631,-632,-641,-669,-695,-684,-637,-604,-629,-706,
--804,-906,-1016,-1124,-1206,-1247,-1268,-1297,-1340,-1391,-1443,-1503,-1578,-1664,-1748,-1821,-1887,-1954,-2026,-2098,-2167,
--2233,-2293,-2346,-2402,-2475,-2560,-2637,-2694,-2745,-2806,-2870,-2916,-2935,-2941,-2952,-2977,-3012,-3044,-3062,-3063,-3053,
--3039,-3025,-3018,-3025,-3044,-3063,-3077,-3086,-3085,-3067,-3041,-3036,-3056,-3066,-3033,-2973,-2928,-2912,-2904,-2893,-2897,
--2929,-2978,-3028,-3076,-3115,-3128,-3107,-3065,-3019,-2972,-2921,-2868,-2820,-2775,-2730,-2688,-2647,-2600,-2542,-2486,-2438,
--2393,-2342,-2285,-2229,-2173,-2115,-2055,-1994,-1930,-1861,-1794,-1732,-1670,-1600,-1524,-1451,-1382,-1312,-1239,-1164,-1092,
--1023,-954,-885,-816,-747,-681,-618,-554,-486,-416,-349,-285,-219,-154,-87,-18,51,111,159,211,280,
-359,428,474,506,536,566,592,616,643,674,707,735,757,777,798,821,842,860,877,894,912,
-928,945,967,992,1019,1044,1063,1079,1094,1110,1127,1139,1149,1161,1178,1197,1219,1245,1273,1295,1307,
-1314,1324,1343,1370,1403,1438,1465,1475,1469,1458,1454,1460,1479,1509,1544,1575,1598,1613,1625,1635,1645,
-1658,1675,1693,1713,1733,1753,1767,1776,1786,1805,1834,1866,1899,1933,1965,1994,2014,2029,2040,2049,2057,
-2066,2074,2075,2063,2043,2036,2054,2087,2110,2109,2091,2068,2050,2037,2028,2019,2006,1987,1969,1957,1953,
-1951,1945,1931,1907,1879,1854,1832,1814,1799,1795,1802,1808,1804,1792,1776,1760,1741,1723,1713,1704,1689,
-1671,1662,1661,1654,1656,1656,1659,1661,1655,1641,1629,1615,1590,1557,1526,1504,1481,1459,1454,1471,1489,
-1495,1499,1525,1565,1597,1619,1648,1684,1699,1671,1614,1560,1532,1527,1532,1522,1485,1434,1405,1415,1430,
-1408,1348,1296,1286,1297,1286,1238,1181,1145,1125,1087,1008,898,786,691,616,557,506,454,394,324,
-251,182,121,66,18,-26,-68,-105,-134,-165,-216,-296,-393,-488,-575,-663,-760,-862,-958,-1044,-1124,
--1201,-1275,-1349,-1428,-1504,-1553,-1551,-1505,-1450,-1412,-1390,-1371,-1353,-1339,-1323,-1296,-1261,-1234,-1221,-1214,-1204,
--1193,-1187,-1185,-1188,-1194,-1196,-1190,-1184,-1187,-1192,-1187,-1176,-1170,-1151,-1096,-1023,-998,-1051,-1125,-1149,-1135,
--1168,-1286,-1424,-1493,-1473,-1412,-1367,-1356,-1359,-1348,-1319,-1297,-1312,-1362,-1419,-1464,-1500,-1529,-1549,-1566,-1597,
--1637,-1657,-1655,-1671,-1740,-1838,-1917,-1962,-2004,-2057,-2108,-2143,-2171,-2213,-2269,-2332,-2400,-2471,-2544,-2615,-2680,
--2740,-2796,-2858,-2925,-2979,-3001,-2994,-2981,-2984,-3009,-3061,-3143,-3241,-3337,-3426,-3514,-3601,-3671,-3717,-3757,-3822,
--3923,-4055,-4206,-4364,-4518,-4654,-4760,-4828,-4868,-4903,-4952,-5003,-5023,-5005,-4979,-4985,-5030,-5091,-5133,-5138,-5109,
--5068,-5050,-5076,-5138,-5203,-5240,-5244,-5234,-5232,-5250,-5281,-5313,-5345,-5386,-5437,-5490,-5535,-5574,-5611,-5645,-5672,
--5697,-5732,-5784,-5849,-5914,-5969,-6017,-6063,-6115,-6172,-6227,-6278,-6329,-6385,-6444,-6504,-6566,-6632,-6701,-6768,-6834,
--6897,-6957,-7017,-7083,-7156,-7223,-7276,-7322,-7378,-7447,-7518,-7584,-7650,-7718,-7787,-7856,-7930,-8014,-8106,-8200,-8293,
--8388,-8488,-8592,-8694,-8791,-8878,-8953,-9021,-9089,-9166,-9252,-9338,-9416,-9485,-9546,-9600,-9647,-9692,-9739,-9772,-9755,
--9680,-9601,-9597,-9694,-9829,-9918,-9941,-9952,-10002,-10091,-10177,-10234,-10268,-10295,-10325,-10356,-10386,-10409,-10416,-10400,-10370,
--10342,
--10327-10328,-10344,-10370,-10393,-10401,-10391,-10381,-10381,-10384,-10372,-10344,-10307,-10266,-10215,-10156,-10097,-10039,-9971,-9887,
--9794,
--9710-9632,-9546,-9442,-9321,-9184,-9037,-8887,-8743,-8607,-8480,-8364,-8261,-8157,-8037,-7895,-7736,-7567,-7391,-7211,
--7030,-6849,-6668,-6498,-6348,-6202,-6033,-5840,-5667,-5555,-5491,-5427,-5331,-5218,-5119,-5042,-4972,-4898,-4826,-4767,-4712,
--4632,-4497,-4307,-4090,-3870,-3646,-3412,-3192,-3034,-2957,-2935,-2923,-2899,-2858,-2782,-2632,-2370,-2011,-1632,-1330,-1152,
--1062,-990,-909,-841,-807,-782,-720,-612,-489,-381,-287,-190,-90,1,79,154,239,333,427,517,610,
-713,819,916,1001,1081,1167,1267,1385,1516,1645,1757,1846,1921,1997,2081,2175,2269,2351,2420,2489,2566,
-2649,2728,2806,2893,2987,3081,3175,3274,3374,3468,3566,3685,3824,3953,4057,4151,4252,4358,4464,4590,4760,
-4951,5110,5209,5275,5340,5414,5491,5574,5656,5701,5681,5609,5540,5503,5479,5439,5387,5360,5380,5441,5519,
-5598,5668,5724,5772,5829,5899,5969,6031,6094,6167,6244,6313,6381,6469,6575,6674,6751,6814,6879,6953,7045,
-7135,7146,6970,6572,6062,5631,5421,5450,5636,5868,6071,6247,6436,6636,6786,6856,6906,7020,7181,7294,7316,
-7304,7320,7359,7386,7407,7438,7459,7442,7400,7372,7366,7355,7319,7267,7209,7153,7111,7090,7083,7075,7065,
-7054,7037,7011,6988,6981,6975,6952,6920,6900,6898,6898,6893,6885,6873,6852,6832,6828,6837,6838,6830,6828,
-6839,6852,6857,6854,6840,6807,6759,6715,6686,6663,6637,6609,6586,6565,6547,6530,6512,6493,6477,6468,6456,
-6433,6414,6413,6415,6398,6369,6347,6315,6239,6148,6110,6127,6113,6007,5868,5794,5786,5765,5694,5613,5560,
-5522,5487,5475,5499,5524,5512,5478,5469,5502,5551,5582,5582,5561,5536,5513,5487,5456,5435,5439,5454,5442,
-5384,5300,5224,5161,5106,5061,5036,5025,5009,4975,4923,4856,4783,4718,4673,4643,4614,4580,4539,4486,4414,
-4332,4260,4210,4177,4144,4102,4053,4007,3965,3926,3887,3849,3806,3755,3695,3640,3601,3576,3543,3491,3428,
-3368,3315,3270,3231,3191,3142,3090,3054,3044,3046,3041,3028,3012,2985,2944,2906,2878,2830,2738,2644,2626,
-2691,2751,2718,2613,2530,2512,2523,2513,2479,2443,2409,2366,2320,2282,2250,2210,2163,2123,2097,2077,2056,
-2039,2027,2015,1998,1977,1962,1953,1944,1932,1916,1899,1883,1869,1857,1850,1846,1839,1822,1791,1754,1725,
-1708,1700,1699,1703,1707,1704,1693,1677,1663,1651,1638,1622,1599,1565,1530,1510,1507,1496,1463,1420,1393,
-1388,1392,1392,1393,1395,1391,1382,1375,1377,1381,1378,1371,1367,1364,1361,1362,1370,1380,1386,1391,1397,
-1395,1383,1380,1405,1454,1500,1520,1516,1503,1490,1486,1496,1516,1533,1539,1541,1554,1577,1603,1626,1645,
-1657,1661,1658,1660,1673,1692,1704,1711,1727,1761,1800,1817,1796,1750,1704,1674,1660,1655,1653,1648,1633,
-1610,1585,1560,1530,1493,1458,1436,1423,1412,1398,1388,1380,1367,1344,1314,1286,1260,1234,1209,1188,1170,
-1151,1129,1105,1081,1057,1034,1013,995,977,954,928,902,879,855,828,798,767,739,709,678,646,
-615,587,556,522,486,452,420,388,352,311,270,231,194,158,123,89,59,30,1,-30,-64,
--99,-140,-185,-233,-279,-322,-360,-394,-430,-470,-518,-568,-612,-651,-693,-740,-788,-829,-865,-902,-943,
--981,-1016,-1050,-1084,-1121,-1160,-1199,-1235,-1265,-1293,-1326,-1364,-1401,-1433,-1464,-1499,-1537,-1575,-1612,-1648,-1685,
--1720,-1751,-1779,-1806,-1836,-1870,-1904,-1932,-1957,-1983,-2013,-2045,-2079,-2114,-2149,-2181,-2211,-2243,-2275,-2305,-2332,
--2361,-2391,-2418,-2440,-2463,-2490,-2517,-2539,-2558,-2578,-2599,-2618,-2635,-2654,-2671,-2683,-2691,-2699,-2710,-2719,-2727,
--2737,-2751,-2767,-2779,-2786,-2787,-2785,-2780,-2773,-2764,-2757,-2753,-2752,-2746,-2731,-2710,-2690,-2673,-2659,-2646,-2633,
--2618,-2601,-2585,-2572,-2556,-2538,-2520,-2504,-2489,-2472,-2453,-2433,-2410,-2384,-2361,-2344,-2328,-2310,-2289,-2270,-2251,
--2228,-2204,-2182,-2161,-2138,-2114,-2089,-2062,-2030,-1995,-1964,-1937,-1912,-1891,-1874,-1857,-1836,-1811,-1787,-1766,-1745,
--1721,-1695,-1672,-1650,-1628,-1603,-1576,-1548,-1521,-1495,-1466,-1437,-1409,-1384,-1358,-1328,-1298,-1269,-1241,-1213,-1185,
--1160,-1137,-1113,-1089,-1065,-1039,-1008,-973,-937,-902,-869,-840,-813,-784,-751,-721,-697,-673,-644,-614,-587,
--559,-526,-493,-468,-447,-421,-390,-360,-334,-308,-283,-262,-238,-207,-174,-149,-126,-94,-53,-20,-4,
-4,18,41,70,107,148,184,211,238,272,313,356,398,437,477,526,586,642,682,720,783,
-870,945,986,1016,1062,1123,1173,1205,1227,1234,1202,1129,1059,1057,1152,1312,1467,1572,1652,1776,1985,
-2251,2518,2739,2868,2836,2605,2252,1956,1847,1893,1963,1973,1947,1930,1914,1867,1795,1728,1668,1579,1447,
-1304,1192,1117,1062,1013,960,891,801,705,622,554,491,431,382,340,292,226,141,33,-94,-232,
--358,-454,-515,-542,-552,-573,-618,-662,-667,-630,-602,-625,-695,-780,-869,-967,-1064,-1133,-1166,-1185,-1215,
--1262,-1316,-1372,-1435,-1513,-1603,-1696,-1781,-1859,-1933,-2005,-2074,-2142,-2209,-2271,-2323,-2373,-2434,-2505,-2568,-2614,
--2656,-2708,-2766,-2814,-2846,-2869,-2896,-2930,-2969,-3004,-3024,-3030,-3030,-3031,-3032,-3029,-3024,-3018,-3011,-3009,-3017,
--3020,-3003,-2975,-2973,-3007,-3042,-3038,-3001,-2970,-2956,-2936,-2906,-2894,-2922,-2983,-3055,-3118,-3160,-3165,-3132,-3080,
--3026,-2974,-2919,-2864,-2812,-2764,-2715,-2667,-2619,-2569,-2514,-2457,-2403,-2353,-2306,-2260,-2213,-2161,-2105,-2049,-1994,
--1934,-1865,-1795,-1729,-1666,-1601,-1532,-1462,-1391,-1318,-1246,-1174,-1099,-1023,-950,-882,-816,-748,-684,-627,-571,
--511,-446,-381,-317,-251,-183,-112,-40,30,92,144,197,263,337,406,459,500,537,573,605,632,
-654,677,702,725,746,767,791,818,840,857,874,893,915,935,954,974,997,1021,1046,1067,1082,
-1095,1107,1120,1130,1139,1150,1165,1183,1204,1228,1251,1267,1272,1274,1282,1301,1330,1366,1401,1424,1428,
-1420,1412,1413,1425,1448,1480,1513,1539,1555,1561,1560,1557,1558,1568,1586,1611,1637,1665,1693,1717,1736,
-1753,1773,1801,1835,1870,1904,1932,1952,1965,1974,1983,1993,2007,2027,2052,2072,2077,2067,2056,2058,2066,
-2063,2044,2019,2000,1991,1987,1982,1973,1956,1931,1906,1890,1885,1885,1883,1875,1861,1849,1846,1852,1859,
-1862,1860,1850,1829,1802,1780,1766,1752,1733,1713,1698,1684,1668,1654,1650,1654,1659,1665,1669,1675,1678,
-1669,1654,1639,1620,1589,1553,1527,1513,1501,1490,1492,1506,1514,1506,1500,1515,1539,1553,1561,1579,1603,
-1608,1582,1542,1507,1488,1483,1482,1462,1414,1358,1329,1332,1333,1306,1269,1259,1277,1281,1243,1180,1129,
-1105,1088,1048,971,866,755,656,576,510,452,394,326,246,163,90,36,-5,-42,-83,-126,-164,
--197,-233,-290,-374,-472,-565,-645,-728,-832,-952,-1067,-1160,-1234,-1300,-1366,-1437,-1520,-1606,-1665,-1668,-1616,
--1546,-1491,-1459,-1440,-1429,-1418,-1396,-1357,-1314,-1288,-1277,-1267,-1250,-1235,-1231,-1235,-1241,-1244,-1239,-1226,-1217,
--1222,-1229,-1220,-1200,-1183,-1161,-1109,-1041,-1017,-1059,-1110,-1105,-1076,-1117,-1263,-1432,-1519,-1497,-1423,-1370,-1363,
--1378,-1377,-1351,-1331,-1352,-1405,-1451,-1472,-1485,-1508,-1537,-1566,-1600,-1634,-1645,-1636,-1646,-1710,-1804,-1885,-1943,
--2004,-2078,-2140,-2171,-2187,-2217,-2272,-2343,-2419,-2493,-2563,-2631,-2702,-2769,-2830,-2887,-2942,-2983,-2997,-2990,-2985,
--2999,-3036,-3096,-3182,-3284,-3382,-3469,-3550,-3624,-3686,-3739,-3810,-3917,-4054,-4199,-4340,-4477,-4611,-4735,-4835,-4898,
--4924,-4942,-4981,-5033,-5054,-5018,-4960,-4944,-4990,-5057,-5094,-5085,-5057,-5041,-5054,-5097,-5153,-5201,-5225,-5229,-5226,
--5233,-5253,-5280,-5312,-5350,-5395,-5443,-5487,-5525,-5561,-5597,-5630,-5656,-5680,-5712,-5760,-5822,-5890,-5955,-6012,-6066,
--6120,-6177,-6233,-6286,-6340,-6396,-6452,-6511,-6575,-6644,-6713,-6778,-6842,-6904,-6964,-7023,-7092,-7170,-7243,-7300,-7346,
--7398,-7459,-7525,-7588,-7653,-7720,-7783,-7846,-7916,-7996,-8083,-8171,-8265,-8368,-8474,-8577,-8675,-8768,-8855,-8932,-9003,
--9077,-9159,-9249,-9336,-9414,-9481,-9542,-9595,-9637,-9675,-9719,-9756,-9752,-9689,-9616,-9611,-9703,-9831,-9910,-9924,-9928,
--9979,-10069,-10156,-10213,-10248,-10279,-10312,-10344,-10373,-10396,-10407,-10400,-10377,-10349,-10328,-10323,-10337,-10363,-10388,-10395,-10384,
--10370,
--10366,-10366,-10358,-10336,-10303,-10264,-10218,-10165,-10113,-10060,-9996,-9916,-9829,-9750,-9675,-9581,-9454,-9303,-9145,-8995,-8858,
--8728,
--8596-8462,-8338,-8238,-8148,-8042,-7900,-7731,-7554,-7379,-7202,-7016,-6821,-6629,-6458,-6318,-6190,-6046,-5878,-5718,
--5599,-5518,-5440,-5339,-5228,-5133,-5060,-4988,-4895,-4788,-4698,-4643,-4597,-4517,-4378,-4193,-3979,-3738,-3473,-3219,-3025,
--2912,-2857,-2825,-2805,-2795,-2767,-2661,-2429,-2076,-1676,-1332,-1105,-977,-891,-818,-768,-752,-738,-685,-584,-465,
--357,-264,-172,-77,17,106,193,283,378,474,568,662,763,870,972,1060,1137,1218,1317,1436,1564,
-1689,1801,1898,1980,2051,2124,2210,2304,2392,2467,2539,2620,2703,2778,2854,2947,3054,3156,3246,3336,3438,
-3546,3657,3780,3910,4024,4107,4176,4252,4343,4454,4607,4811,5033,5213,5325,5388,5433,5476,5528,5595,5668,
-5716,5714,5670,5612,5564,5519,5459,5378,5302,5278,5327,5421,5509,5567,5615,5679,5757,5830,5887,5940,6004,
-6079,6149,6203,6257,6339,6456,6575,6664,6731,6821,6949,7071,7113,7021,6780,6407,5961,5562,5354,5413,5685,
-6020,6297,6507,6697,6863,6951,6953,6951,7034,7179,7291,7327,7329,7348,7378,7393,7403,7425,7445,7439,7417,
-7402,7397,7377,7333,7276,7222,7177,7144,7123,7109,7096,7085,7078,7066,7045,7028,7021,7012,6990,6964,6946,
-6938,6926,6911,6900,6890,6877,6865,6862,6865,6863,6856,6857,6867,6878,6884,6885,6873,6841,6797,6758,6728,
-6699,6666,6635,6608,6586,6572,6562,6544,6517,6498,6498,6495,6473,6451,6450,6453,6431,6396,6377,6345,6251,
-6130,6089,6151,6202,6134,5986,5877,5837,5798,5720,5642,5600,5572,5536,5512,5525,5550,5551,5531,5522,5539,
-5572,5600,5615,5609,5586,5554,5519,5477,5440,5428,5442,5446,5408,5333,5252,5185,5137,5103,5080,5062,5038,
-5003,4952,4876,4786,4705,4658,4637,4617,4586,4546,4500,4441,4369,4299,4247,4211,4176,4129,4073,4019,3977,
-3943,3913,3881,3844,3797,3740,3686,3650,3626,3591,3534,3466,3406,3358,3317,3279,3237,3183,3123,3081,3068,
-3069,3064,3054,3045,3029,2993,2948,2907,2853,2763,2661,2612,2642,2694,2697,2649,2605,2593,2594,2579,2544,
-2495,2434,2370,2324,2304,2286,2243,2183,2133,2109,2097,2080,2060,2044,2031,2014,1992,1971,1954,1945,1940,
-1937,1929,1914,1895,1880,1873,1868,1858,1836,1805,1771,1743,1724,1716,1715,1720,1724,1721,1712,1702,1688,
-1670,1648,1626,1600,1568,1537,1524,1527,1523,1492,1446,1412,1398,1391,1385,1385,1391,1392,1387,1387,1396,
-1404,1401,1390,1381,1374,1366,1363,1370,1381,1389,1393,1397,1396,1387,1383,1402,1445,1491,1522,1537,1537,
-1524,1504,1496,1509,1532,1546,1547,1545,1552,1570,1593,1619,1643,1659,1664,1666,1677,1696,1713,1718,1721,
-1741,1779,1810,1811,1783,1746,1710,1678,1651,1635,1631,1629,1617,1594,1567,1538,1505,1471,1442,1420,1403,
-1389,1380,1374,1365,1350,1333,1317,1301,1280,1254,1228,1206,1186,1165,1139,1112,1085,1062,1042,1023,1002,
-976,947,921,899,877,850,819,786,756,727,700,673,647,619,589,555,518,480,445,411,376,
-337,297,258,223,188,151,114,78,45,14,-15,-46,-82,-123,-168,-214,-257,-296,-334,-369,-404,
--442,-487,-535,-580,-621,-662,-708,-755,-798,-837,-877,-920,-959,-993,-1025,-1059,-1097,-1136,-1173,-1204,-1231,
--1258,-1290,-1328,-1364,-1395,-1425,-1458,-1494,-1532,-1570,-1608,-1644,-1677,-1707,-1736,-1766,-1799,-1834,-1868,-1897,-1920,
--1945,-1976,-2012,-2050,-2085,-2117,-2146,-2175,-2207,-2240,-2271,-2298,-2326,-2356,-2383,-2408,-2433,-2461,-2487,-2506,-2524,
--2545,-2567,-2586,-2601,-2617,-2634,-2646,-2652,-2659,-2668,-2679,-2690,-2703,-2717,-2731,-2741,-2746,-2748,-2746,-2742,-2737,
--2732,-2727,-2724,-2723,-2717,-2702,-2682,-2661,-2645,-2631,-2619,-2605,-2588,-2569,-2552,-2537,-2522,-2504,-2487,-2471,-2455,
--2436,-2416,-2396,-2375,-2353,-2334,-2320,-2306,-2287,-2266,-2247,-2230,-2209,-2184,-2160,-2140,-2119,-2096,-2070,-2041,-2009,
--1977,-1949,-1924,-1899,-1876,-1859,-1846,-1829,-1807,-1785,-1767,-1747,-1723,-1697,-1673,-1653,-1632,-1608,-1582,-1556,-1529,
--1501,-1471,-1441,-1412,-1386,-1361,-1333,-1303,-1272,-1242,-1213,-1184,-1157,-1132,-1110,-1086,-1058,-1028,-997,-967,-937,
--905,-874,-849,-828,-801,-767,-733,-707,-684,-657,-630,-604,-576,-542,-508,-483,-464,-439,-406,-375,-350,
--327,-303,-280,-256,-226,-195,-172,-154,-129,-95,-63,-43,-28,-10,12,39,74,115,154,187,220,
-257,295,332,371,415,461,505,551,600,647,694,755,832,906,959,1002,1057,1120,1168,1192,1196,
-1178,1128,1059,1026,1079,1210,1363,1491,1601,1739,1937,2176,2410,2609,2761,2830,2751,2504,2182,1946,1881,
-1928,1978,1990,1999,2021,2017,1959,1883,1830,1788,1706,1574,1432,1320,1240,1178,1130,1086,1024,936,837,
-752,681,613,547,489,433,371,298,215,113,-11,-147,-267,-351,-396,-411,-419,-457,-534,-615,-647,
--630,-613,-639,-700,-767,-836,-918,-1004,-1069,-1098,-1109,-1126,-1163,-1219,-1287,-1363,-1450,-1544,-1642,-1738,-1828,
--1911,-1985,-2051,-2114,-2179,-2243,-2298,-2348,-2403,-2465,-2519,-2560,-2600,-2649,-2704,-2751,-2787,-2819,-2852,-2889,-2928,
--2962,-2984,-2995,-3004,-3015,-3021,-3015,-2997,-2972,-2949,-2941,-2950,-2958,-2943,-2915,-2912,-2953,-3003,-3021,-3007,-2990,
--2979,-2952,-2909,-2881,-2900,-2966,-3056,-3143,-3201,-3210,-3171,-3108,-3047,-2992,-2939,-2884,-2829,-2773,-2714,-2656,-2602,
--2551,-2497,-2440,-2382,-2325,-2275,-2229,-2184,-2133,-2079,-2029,-1979,-1923,-1856,-1785,-1716,-1651,-1591,-1533,-1471,-1401,
--1326,-1254,-1184,-1109,-1029,-953,-886,-824,-760,-699,-647,-599,-543,-480,-415,-350,-283,-212,-141,-69,0,
-63,120,177,241,311,381,444,495,540,580,615,642,662,679,700,723,745,766,789,815,838,
-857,875,899,924,947,966,983,1003,1024,1046,1068,1083,1093,1100,1109,1120,1132,1144,1157,1169,1183,
-1199,1216,1228,1233,1237,1247,1268,1298,1330,1354,1362,1356,1349,1350,1362,1382,1406,1433,1458,1477,1487,
-1488,1479,1465,1459,1469,1495,1527,1560,1591,1620,1646,1669,1689,1711,1739,1773,1811,1849,1881,1907,1928,
-1946,1962,1975,1990,2009,2037,2065,2082,2080,2067,2054,2040,2016,1983,1954,1937,1931,1927,1921,1911,1892,
-1865,1838,1820,1818,1827,1840,1851,1858,1865,1878,1893,1903,1903,1891,1868,1834,1800,1775,1758,1739,1714,
-1691,1676,1665,1654,1647,1651,1659,1672,1680,1688,1694,1692,1678,1658,1640,1619,1590,1563,1549,1546,1541,
-1533,1532,1534,1527,1512,1508,1517,1525,1523,1522,1529,1534,1529,1524,1526,1519,1490,1454,1436,1427,1400,
-1352,1315,1300,1288,1266,1252,1265,1282,1264,1201,1127,1074,1044,1018,978,917,835,742,652,573,504,
-437,363,277,179,85,17,-21,-44,-73,-114,-162,-206,-247,-297,-366,-458,-559,-649,-725,-805,-913,
--1046,-1174,-1271,-1334,-1381,-1427,-1485,-1564,-1654,-1722,-1737,-1694,-1625,-1565,-1528,-1512,-1509,-1505,-1484,-1445,-1405,
--1382,-1370,-1353,-1330,-1313,-1306,-1302,-1295,-1287,-1279,-1267,-1259,-1262,-1263,-1245,-1212,-1182,-1160,-1125,-1083,-1069,
--1089,-1096,-1053,-1014,-1073,-1245,-1432,-1526,-1504,-1431,-1379,-1376,-1398,-1409,-1400,-1398,-1431,-1483,-1514,-1512,-1505,
--1517,-1545,-1578,-1614,-1644,-1646,-1621,-1614,-1662,-1747,-1827,-1897,-1984,-2092,-2181,-2219,-2220,-2226,-2268,-2344,-2437,
--2524,-2597,-2664,-2733,-2802,-2859,-2907,-2952,-2990,-3007,-3006,-3007,-3025,-3067,-3133,-3224,-3325,-3419,-3500,-3575,-3649,
--3720,-3799,-3906,-4047,-4198,-4336,-4458,-4577,-4700,-4820,-4922,-4989,-5015,-5027,-5055,-5098,-5107,-5050,-4966,-4928,-4964,
--5026,-5056,-5047,-5033,-5042,-5074,-5115,-5155,-5190,-5213,-5225,-5233,-5243,-5259,-5282,-5314,-5353,-5397,-5438,-5474,-5509,
--5546,-5582,-5613,-5639,-5664,-5694,-5737,-5793,-5862,-5933,-5999,-6060,-6122,-6185,-6245,-6298,-6347,-6396,-6451,-6513,-6582,
--6654,-6720,-6781,-6841,-6902,-6962,-7022,-7090,-7167,-7244,-7309,-7365,-7419,-7476,-7535,-7599,-7667,-7733,-7790,-7846,-7912,
--7989,-8070,-8152,-8243,-8348,-8459,-8564,-8659,-8749,-8834,-8912,-8988,-9067,-9152,-9241,-9327,-9403,-9469,-9526,-9577,-9619,
--9658,-9701,-9741,-9747,-9700,-9636,-9627,-9705,-9818,-9890,-9904,-9913,-9964,-10050,-10132,-10187,-10223,-10257,-10293,-10327,-10357,
--10381,-10396,-10398,-10384,-10358,-10332,-10320,-10330,-10357,-10383,-10393,-10385,-10371,-10362,-10356,-10347,-10327,-10296,-10260,-10219,-10176,
--10130,
+-10114,-9944,-9786,-9652,-9506,-9358,-9283,-9305,-9351,-9361,-9381,-9479,-9617,-9682,-9639,-9562,-9515,-9483,-9425,-9347,-9272,
+-9190,-9076,-8934,-8799,-8685,-8582,-8474,-8351,-8209,-8050,-7895,-7762,-7642,-7508,-7350,-7184,-7027,-6875,-6717,-6550,-6381,
+-6216,-6063,-5931,-5822,-5730,-5661,-5630,-5652,-5718,-5798,-5874,-5949,-6008,-6001,-5867,-5597,-5258,-4937,-4688,-4506,-4356,
+-4199,-4012,-3806,-3622,-3493,-3406,-3320,-3210,-3085,-2963,-2840,-2711,-2584,-2471,-2370,-2270,-2164,-2053,-1936,-1817,-1713,
+-1636,-1583,-1532,-1476,-1421,-1371,-1312,-1235,-1147,-1065,-991,-916,-834,-749,-664,-575,-479,-381,-285,-184,-73,
+41,146,240,332,431,529,619,708,802,900,998,1101,1218,1337,1436,1507,1564,1627,1707,1804,1913,
+2025,2132,2243,2360,2473,2574,2676,2796,2929,3046,3138,3229,3326,3402,3428,3428,3455,3543,3691,3878,4067,
+4216,4317,4419,4574,4768,4937,5042,5106,5161,5214,5257,5286,5305,5326,5370,5445,5516,5542,5544,5585,5688,
+5825,5999,6248,6554,6802,6892,6855,6781,6712,6667,6710,6887,7109,7219,7192,7137,7084,6921,6603,6288,6126,
+6015,5747,5357,5156,5354,5803,6193,6392,6484,6562,6618,6628,6621,6625,6620,6585,6545,6532,6541,6548,6551,
+6558,6562,6561,6568,6581,6572,6545,6569,6691,6830,6826,6624,6359,6213,6222,6269,6246,6159,6078,6043,6040,
+6048,6072,6131,6225,6321,6373,6376,6368,6382,6399,6384,6342,6313,6311,6308,6288,6280,6303,6324,6306,6263,
+6234,6228,6222,6211,6213,6223,6213,6178,6145,6126,6094,6038,5988,5983,6012,6037,6040,6025,5994,5942,5888,
+5864,5868,5861,5820,5782,5788,5810,5757,5579,5352,5208,5189,5209,5192,5191,5314,5534,5668,5587,5375,5212,
+5154,5114,5032,4960,4946,4941,4896,4867,4947,5104,5193,5122,4954,4804,4711,4636,4557,4501,4499,4550,4624,
+4677,4664,4566,4423,4302,4232,4184,4124,4047,3974,3914,3860,3812,3778,3755,3728,3683,3623,3564,3516,3474,
+3429,3375,3320,3275,3239,3203,3156,3101,3051,3020,3009,3005,2983,2932,2864,2796,2730,2663,2627,2673,2804,
+2928,2943,2844,2724,2658,2632,2593,2538,2516,2558,2642,2714,2730,2678,2584,2494,2433,2383,2323,2266,2238,
+2232,2216,2176,2137,2115,2096,2062,2014,1965,1909,1843,1783,1752,1751,1758,1755,1738,1708,1673,1645,1628,
+1618,1602,1580,1558,1540,1521,1502,1485,1466,1441,1419,1412,1422,1441,1459,1475,1480,1467,1434,1391,1342,
+1282,1214,1151,1109,1087,1079,1078,1077,1069,1053,1041,1045,1062,1081,1095,1100,1096,1090,1089,1094,1097,
+1096,1101,1122,1150,1169,1182,1199,1214,1215,1206,1208,1231,1262,1286,1304,1319,1331,1337,1343,1353,1361,
+1371,1390,1413,1418,1399,1389,1414,1455,1461,1424,1384,1379,1406,1449,1500,1545,1548,1500,1443,1431,1457,
+1470,1445,1412,1398,1391,1365,1328,1302,1293,1285,1274,1266,1258,1236,1197,1158,1131,1114,1097,1076,1055,
+1035,1016,997,977,950,917,883,854,828,801,775,751,727,704,684,665,645,624,604,587,568,
+543,513,482,451,418,382,345,310,277,246,217,187,157,127,98,69,38,4,-31,-67,-102,
+-136,-173,-210,-248,-286,-326,-368,-411,-452,-495,-536,-576,-615,-658,-705,-753,-797,-841,-888,-936,-978,
+-1013,-1045,-1078,-1113,-1150,-1193,-1237,-1278,-1316,-1354,-1397,-1443,-1488,-1534,-1583,-1633,-1680,-1723,-1762,-1796,-1828,
+-1863,-1908,-1959,-2007,-2049,-2087,-2124,-2163,-2202,-2241,-2279,-2315,-2350,-2382,-2413,-2443,-2474,-2509,-2546,-2582,-2617,
+-2653,-2688,-2720,-2748,-2774,-2801,-2830,-2860,-2890,-2920,-2949,-2978,-3007,-3037,-3066,-3092,-3117,-3142,-3167,-3190,-3209,
+-3224,-3240,-3257,-3274,-3287,-3295,-3304,-3317,-3333,-3346,-3357,-3365,-3371,-3377,-3383,-3391,-3401,-3409,-3411,-3406,-3396,
+-3387,-3384,-3386,-3389,-3388,-3385,-3378,-3368,-3357,-3347,-3339,-3329,-3315,-3300,-3284,-3263,-3236,-3210,-3188,-3166,-3141,
+-3113,-3087,-3061,-3032,-2997,-2958,-2918,-2881,-2848,-2815,-2779,-2740,-2703,-2668,-2632,-2596,-2565,-2537,-2507,-2470,-2432,
+-2396,-2360,-2321,-2282,-2244,-2205,-2162,-2118,-2077,-2035,-1989,-1944,-1902,-1861,-1818,-1772,-1728,-1686,-1644,-1603,-1561,
+-1518,-1472,-1429,-1393,-1357,-1317,-1277,-1243,-1212,-1178,-1142,-1108,-1075,-1041,-1009,-983,-955,-920,-882,-851,-826,
+-800,-769,-741,-718,-693,-664,-635,-607,-577,-544,-512,-482,-451,-420,-389,-356,-319,-285,-259,-236,-207,
+-180,-159,-139,-107,-66,-31,-5,23,60,96,128,165,206,242,276,318,370,416,453,495,543,
+585,620,667,725,773,809,861,944,1027,1080,1113,1151,1178,1157,1092,1040,1048,1112,1192,1251,1281,
+1305,1356,1433,1489,1473,1385,1281,1210,1182,1170,1159,1183,1300,1512,1720,1795,1722,1626,1632,1734,1836,
+1867,1808,1645,1393,1143,978,852,643,350,162,260,604,963,1111,955,555,72,-304,-483,-523,-540,
+-585,-640,-692,-748,-799,-826,-835,-855,-892,-928,-964,-1016,-1083,-1139,-1175,-1197,-1201,-1179,-1152,-1162,-1209,
+-1251,-1269,-1287,-1336,-1418,-1529,-1673,-1837,-1985,-2099,-2196,-2291,-2371,-2432,-2494,-2569,-2634,-2668,-2691,-2730,-2776,
+-2800,-2800,-2803,-2826,-2864,-2904,-2940,-2970,-2995,-3019,-3042,-3057,-3069,-3100,-3157,-3216,-3250,-3268,-3297,-3339,-3374,
+-3394,-3406,-3413,-3411,-3410,-3427,-3461,-3503,-3561,-3665,-3813,-3958,-4049,-4080,-4084,-4088,-4095,-4099,-4097,-4090,-4082,
+-4078,-4077,-4077,-4071,-4055,-4028,-3989,-3947,-3910,-3876,-3831,-3772,-3705,-3636,-3565,-3490,-3421,-3359,-3300,-3235,-3165,
+-3098,-3038,-2987,-2942,-2898,-2846,-2782,-2713,-2640,-2565,-2488,-2416,-2349,-2281,-2208,-2134,-2061,-1985,-1904,-1825,-1752,
+-1681,-1604,-1524,-1447,-1367,-1281,-1189,-1104,-1029,-961,-897,-837,-777,-710,-636,-565,-506,-455,-400,-333,-263,
+-199,-142,-89,-35,17,64,109,158,209,256,293,328,367,410,449,482,514,549,588,624,655,
+685,720,762,808,854,898,935,966,996,1034,1079,1122,1159,1194,1233,1271,1300,1324,1356,1397,1435,
+1465,1490,1522,1567,1623,1682,1726,1741,1731,1725,1744,1781,1817,1841,1854,1864,1874,1889,1911,1935,1951,
+1959,1969,1987,2010,2034,2059,2087,2115,2136,2150,2160,2177,2202,2230,2256,2290,2353,2454,2573,2685,2783,
+2884,2997,3109,3188,3216,3198,3162,3136,3130,3142,3161,3184,3208,3233,3260,3286,3297,3277,3235,3196,3179,
+3169,3142,3099,3064,3048,3041,3027,3005,2977,2938,2887,2836,2800,2779,2767,2759,2753,2749,2752,2767,2791,
+2806,2808,2803,2788,2753,2698,2653,2642,2655,2659,2645,2623,2625,2637,2650,2655,2653,2645,2626,2595,2558,
+2523,2493,2470,2455,2446,2431,2402,2369,2345,2334,2324,2306,2283,2259,2232,2199,2168,2156,2171,2200,2219,
+2213,2190,2168,2155,2145,2133,2115,2089,2055,2017,1988,1979,1988,2002,2004,1983,1944,1900,1864,1826,1766,
+1680,1594,1542,1525,1510,1462,1379,1283,1194,1114,1030,933,826,728,658,619,588,535,452,353,262,
+185,113,36,-36,-92,-128,-156,-189,-222,-247,-260,-268,-273,-283,-305,-347,-399,-442,-471,-498,-532,
+-561,-581,-611,-672,-755,-823,-857,-870,-877,-879,-867,-851,-841,-835,-824,-811,-811,-826,-845,-859,-878,
+-910,-950,-989,-1022,-1045,-1055,-1054,-1058,-1084,-1129,-1168,-1180,-1170,-1166,-1188,-1232,-1271,-1290,-1294,-1290,-1276,
+-1248,-1220,-1206,-1199,-1180,-1147,-1119,-1105,-1091,-1067,-1050,-1057,-1072,-1069,-1058,-1079,-1139,-1192,-1187,-1138,-1102,
+-1121,-1192,-1293,-1410,-1538,-1672,-1806,-1933,-2044,-2136,-2225,-2331,-2444,-2524,-2548,-2535,-2532,-2556,-2592,-2621,-2650,
+-2695,-2762,-2840,-2918,-2990,-3054,-3108,-3155,-3203,-3255,-3311,-3368,-3428,-3494,-3569,-3655,-3748,-3836,-3907,-3966,-4045,
+-4172,-4352,-4560,-4768,-4956,-5112,-5221,-5282,-5314,-5335,-5356,-5373,-5392,-5419,-5457,-5505,-5557,-5606,-5631,-5605,-5532,
+-5444,-5376,-5337,-5319,-5316,-5330,-5356,-5380,-5401,-5433,-5479,-5530,-5573,-5607,-5637,-5666,-5697,-5736,-5788,-5847,-5906,
+-5967,-6042,-6135,-6238,-6341,-6440,-6540,-6644,-6749,-6848,-6943,-7037,-7136,-7238,-7338,-7436,-7534,-7637,-7738,-7833,-7922,
+-8013,-8105,-8194,-8276,-8354,-8439,-8534,-8631,-8719,-8797,-8870,-8941,-9006,-9065,-9125,-9188,-9250,-9305,-9358,-9417,-9474,
+-9518,-9553,-9597,-9647,-9680,-9680,-9661,-9648,-9655,-9685,-9750,-9846,-9937,-9983,-9988,-9990,-10011,-10041,-10065,-10083,-10096,
+-10099,-10096,-10097,-10091,-10067,-10056,-10112,-10230,-10332,-10358,-10336,-10313,-10273,-10162,-9992,-9824,-9674,-9509,-9343,-9253,-9272,
+-9331,-9365,-9410,-9525,-9671,-9736,-9689,-9604,-9551,-9515,-9455,-9374,-9295,-9210,-9096,-8955,-8818,-8698,-8586,-8472,-8351,
+-8214,-8061,-7910,-7781,-7663,-7529,-7367,-7198,-7041,-6888,-6725,-6548,-6369,-6197,-6038,-5900,-5786,-5691,-5616,-5577,-5595,
+-5670,-5773,-5870,-5940,-5968,-5932,-5801,-5570,-5277,-4984,-4737,-4540,-4365,-4180,-3971,-3756,-3576,-3453,-3371,-3286,-3176,
+-3051,-2926,-2802,-2669,-2532,-2404,-2295,-2199,-2106,-2010,-1902,-1785,-1673,-1583,-1516,-1456,-1393,-1333,-1283,-1231,-1161,
+-1077,-995,-925,-856,-779,-697,-619,-541,-454,-358,-257,-151,-32,95,214,314,405,499,597,692,787,
+889,995,1094,1189,1292,1402,1498,1567,1619,1680,1767,1875,1987,2087,2176,2270,2380,2496,2605,2719,2853,
+2992,3103,3177,3237,3295,3331,3343,3369,3458,3618,3817,4025,4214,4354,4443,4529,4663,4828,4961,5033,5083,
+5152,5233,5293,5323,5339,5364,5409,5466,5512,5535,5571,5674,5854,6070,6291,6511,6706,6819,6821,6747,6645,
+6548,6515,6639,6925,7211,7317,7245,7131,7022,6823,6503,6192,5990,5796,5471,5115,5018,5309,5798,6197,6411,
+6523,6609,6662,6672,6671,6678,6670,6634,6595,6579,6579,6577,6575,6582,6590,6598,6615,6640,6650,6640,6655,
+6719,6765,6687,6490,6311,6278,6361,6423,6378,6266,6171,6128,6125,6149,6203,6280,6352,6392,6395,6386,6392,
+6411,6418,6394,6358,6339,6333,6312,6274,6253,6266,6284,6275,6254,6253,6270,6276,6261,6244,6234,6219,6197,
+6182,6170,6140,6085,6038,6025,6037,6042,6032,6014,5984,5934,5880,5852,5850,5842,5812,5791,5814,5845,5796,
+5624,5402,5258,5233,5251,5236,5229,5321,5488,5589,5528,5379,5276,5242,5195,5099,5019,4999,4989,4937,4890,
+4930,5038,5102,5053,4940,4841,4771,4699,4621,4577,4604,4699,4823,4905,4876,4720,4508,4345,4275,4252,4206,
+4121,4032,3966,3918,3873,3829,3793,3762,3721,3662,3594,3538,3500,3468,3425,3365,3307,3266,3238,3204,3152,
+3091,3046,3028,3024,3002,2950,2889,2841,2797,2736,2669,2650,2701,2771,2781,2718,2640,2602,2594,2573,2530,
+2500,2516,2578,2647,2678,2652,2586,2519,2467,2412,2345,2284,2250,2236,2215,2181,2146,2117,2087,2056,2024,
+1978,1901,1811,1753,1750,1774,1786,1775,1754,1729,1697,1666,1646,1634,1618,1595,1574,1558,1542,1526,1514,
+1502,1486,1470,1464,1475,1495,1517,1532,1533,1510,1468,1421,1375,1320,1253,1188,1142,1122,1122,1129,1129,
+1112,1084,1063,1063,1079,1097,1109,1115,1114,1107,1101,1098,1095,1090,1093,1112,1139,1158,1168,1179,1193,
+1203,1207,1216,1241,1275,1306,1327,1339,1344,1346,1349,1355,1361,1373,1401,1436,1457,1453,1440,1437,1433,
+1411,1380,1372,1399,1443,1489,1541,1585,1582,1525,1465,1460,1499,1525,1507,1476,1461,1451,1421,1382,1358,
+1349,1338,1318,1302,1292,1277,1246,1211,1184,1162,1139,1114,1093,1074,1056,1036,1014,989,960,928,897,
+867,838,811,784,759,737,719,702,682,657,633,613,596,575,549,520,489,458,424,387,348,
+313,281,253,225,196,167,139,108,73,36,0,-35,-70,-105,-142,-179,-215,-252,-291,-333,-376,
+-418,-460,-501,-541,-580,-622,-667,-712,-753,-796,-845,-896,-941,-977,-1012,-1048,-1083,-1119,-1160,-1204,-1246,
+-1282,-1319,-1362,-1409,-1455,-1502,-1551,-1599,-1644,-1687,-1730,-1770,-1803,-1836,-1875,-1919,-1962,-1999,-2036,-2074,-2114,
+-2154,-2191,-2225,-2258,-2289,-2321,-2353,-2383,-2415,-2450,-2486,-2520,-2552,-2584,-2618,-2652,-2684,-2712,-2738,-2766,-2797,
+-2830,-2861,-2890,-2918,-2946,-2977,-3008,-3038,-3065,-3090,-3115,-3140,-3162,-3179,-3193,-3209,-3226,-3240,-3248,-3256,-3269,
+-3286,-3300,-3309,-3316,-3322,-3326,-3331,-3337,-3345,-3353,-3356,-3354,-3347,-3340,-3340,-3346,-3352,-3352,-3346,-3337,-3325,
+-3313,-3305,-3299,-3290,-3278,-3264,-3250,-3233,-3211,-3189,-3168,-3148,-3121,-3090,-3059,-3032,-3004,-2973,-2937,-2898,-2860,
+-2823,-2786,-2747,-2708,-2671,-2636,-2600,-2567,-2540,-2516,-2488,-2454,-2419,-2385,-2350,-2313,-2277,-2243,-2205,-2161,-2116,
+-2074,-2032,-1985,-1940,-1900,-1861,-1817,-1770,-1726,-1685,-1644,-1603,-1564,-1523,-1480,-1436,-1398,-1362,-1325,-1286,-1251,
+-1218,-1183,-1147,-1113,-1081,-1048,-1016,-990,-964,-931,-896,-867,-842,-814,-782,-754,-732,-710,-684,-655,-626,
+-591,-554,-520,-491,-462,-433,-403,-368,-330,-298,-275,-254,-224,-192,-171,-154,-127,-90,-55,-26,5,
+40,71,104,147,197,237,271,313,364,410,448,490,535,569,596,641,705,760,797,847,925,
+1001,1045,1072,1109,1141,1133,1089,1055,1062,1104,1157,1196,1203,1184,1175,1200,1235,1234,1196,1167,1175,
+1194,1181,1132,1106,1185,1395,1645,1789,1771,1702,1735,1897,2079,2166,2122,1959,1705,1415,1149,910,663,
+435,344,480,798,1138,1324,1235,854,318,-143,-382,-445,-478,-551,-630,-675,-701,-734,-774,-810,-837,
+-854,-872,-913,-989,-1075,-1137,-1162,-1155,-1111,-1045,-1008,-1046,-1132,-1192,-1196,-1185,-1205,-1272,-1389,-1557,-1748,
+-1905,-2010,-2091,-2172,-2241,-2295,-2361,-2452,-2533,-2571,-2589,-2626,-2679,-2716,-2730,-2744,-2775,-2816,-2858,-2898,-2929,
+-2948,-2963,-2985,-3007,-3024,-3051,-3097,-3144,-3167,-3172,-3185,-3215,-3248,-3276,-3304,-3326,-3329,-3322,-3327,-3351,-3383,
+-3432,-3528,-3675,-3824,-3922,-3961,-3972,-3984,-3999,-4013,-4023,-4029,-4031,-4030,-4029,-4029,-4025,-4012,-3986,-3947,-3907,
+-3872,-3842,-3804,-3753,-3696,-3636,-3572,-3505,-3439,-3377,-3315,-3247,-3177,-3110,-3049,-2995,-2945,-2891,-2828,-2757,-2686,
+-2617,-2546,-2472,-2400,-2333,-2261,-2184,-2108,-2036,-1962,-1883,-1807,-1739,-1672,-1595,-1512,-1432,-1355,-1275,-1192,-1111,
+-1032,-952,-875,-810,-754,-694,-620,-541,-470,-405,-338,-262,-187,-124,-70,-16,40,92,135,176,224,
+281,336,379,412,444,479,513,544,575,610,645,677,705,736,774,819,865,911,953,986,1011,
+1034,1068,1112,1153,1184,1211,1245,1279,1302,1319,1347,1392,1441,1480,1511,1545,1589,1644,1702,1742,1747,
+1721,1696,1703,1743,1792,1828,1848,1859,1867,1880,1898,1914,1924,1931,1944,1963,1983,2001,2019,2043,2068,
+2089,2102,2111,2126,2153,2184,2206,2218,2244,2305,2397,2494,2582,2673,2785,2915,3038,3124,3159,3150,3118,
+3088,3073,3078,3101,3134,3168,3194,3207,3206,3188,3160,3136,3127,3122,3105,3074,3045,3030,3023,3012,2995,
+2967,2925,2871,2818,2783,2769,2768,2770,2768,2764,2764,2775,2794,2808,2808,2800,2786,2760,2719,2676,2648,
+2637,2630,2623,2615,2615,2630,2649,2661,2661,2643,2607,2556,2503,2458,2427,2405,2390,2378,2365,2344,2313,
+2277,2240,2208,2184,2168,2155,2136,2111,2091,2097,2135,2185,2217,2216,2190,2159,2136,2127,2130,2135,2128,
+2100,2067,2049,2051,2058,2054,2034,1997,1945,1883,1825,1776,1724,1660,1591,1533,1484,1429,1360,1288,1227,
+1175,1114,1029,926,822,735,672,626,578,511,421,318,219,132,50,-33,-112,-173,-213,-245,-285,
+-328,-361,-376,-376,-371,-368,-379,-409,-449,-482,-505,-532,-566,-595,-609,-627,-676,-758,-847,-918,-964,
+-986,-982,-961,-942,-930,-913,-882,-851,-839,-845,-856,-867,-889,-924,-965,-1004,-1043,-1079,-1099,-1097,-1090,
+-1099,-1132,-1171,-1194,-1190,-1176,-1182,-1218,-1266,-1301,-1314,-1313,-1297,-1260,-1220,-1199,-1202,-1199,-1176,-1152,-1148,
+-1152,-1139,-1114,-1108,-1121,-1134,-1143,-1174,-1223,-1244,-1208,-1153,-1142,-1193,-1276,-1374,-1497,-1651,-1809,-1945,-2054,
+-2149,-2241,-2341,-2461,-2589,-2681,-2704,-2678,-2655,-2667,-2700,-2735,-2770,-2815,-2870,-2928,-2989,-3057,-3126,-3189,-3245,
+-3300,-3355,-3405,-3455,-3515,-3591,-3676,-3761,-3845,-3925,-3995,-4059,-4144,-4270,-4435,-4618,-4807,-4995,-5162,-5273,-5317,
+-5326,-5340,-5368,-5392,-5407,-5435,-5487,-5550,-5595,-5606,-5579,-5515,-5437,-5377,-5357,-5358,-5352,-5338,-5339,-5368,-5406,
+-5437,-5467,-5509,-5561,-5606,-5640,-5670,-5704,-5743,-5782,-5822,-5867,-5919,-5983,-6060,-6147,-6239,-6333,-6433,-6538,-6643,
+-6744,-6840,-6934,-7030,-7129,-7229,-7330,-7428,-7525,-7624,-7723,-7821,-7917,-8013,-8107,-8195,-8275,-8354,-8443,-8542,-8638,
+-8722,-8797,-8870,-8940,-9004,-9065,-9131,-9203,-9268,-9320,-9369,-9425,-9483,-9530,-9570,-9616,-9665,-9696,-9694,-9675,-9659,
+-9655,-9674,-9733,-9833,-9936,-9995,-10007,-10009,-10029,-10058,-10084,-10105,-10118,-10121,-10124,-10140,-10163,-10174,-10189,-10243,-10332,
+-10397,-10397,-10365,-10345,-10310,-10204,-10032,-9855,-9699,-9539,-9382,-9294,-9305,-9363,-9415,-9486,-9614,-9754,-9807,-9753,-9664,
+-9604,-9559,-9492,-9406,-9323,-9233,-9118,-8980,-8842,-8714,-8590,-8468,-8343,-8206,-8056,-7910,-7788,-7675,-7538,-7370,-7195,
+-7035,-6882,-6721,-6546,-6366,-6190,-6023,-5873,-5743,-5635,-5552,-5512,-5533,-5612,-5723,-5827,-5889,-5891,-5833,-5718,-5549,
+-5330,-5076,-4817,-4579,-4366,-4159,-3943,-3728,-3549,-3426,-3345,-3268,-3165,-3038,-2900,-2762,-2622,-2484,-2355,-2242,-2140,
+-2045,-1950,-1850,-1742,-1631,-1531,-1448,-1376,-1308,-1247,-1197,-1148,-1082,-998,-915,-848,-787,-716,-637,-563,-497,
+-423,-330,-225,-112,11,147,280,390,481,569,661,756,857,968,1082,1183,1273,1365,1464,1555,1624,
+1680,1749,1847,1963,2074,2165,2242,2326,2431,2546,2660,2780,2917,3051,3146,3193,3220,3249,3279,3317,3399,
+3550,3752,3961,4155,4322,4448,4535,4624,4756,4905,5006,5042,5070,5141,5236,5310,5348,5375,5410,5447,5477,
+5507,5560,5669,5857,6108,6371,6591,6733,6783,6756,6693,6618,6527,6432,6430,6635,7013,7352,7459,7355,7182,
+7001,6764,6469,6198,5959,5639,5202,4853,4863,5258,5785,6186,6413,6550,6652,6704,6712,6711,6715,6705,6672,
+6639,6622,6612,6602,6598,6608,6622,6636,6660,6696,6722,6722,6705,6675,6606,6475,6330,6268,6334,6456,6524,
+6497,6429,6381,6362,6356,6361,6384,6416,6432,6425,6411,6408,6418,6425,6415,6388,6360,6345,6336,6314,6284,
+6265,6267,6274,6273,6277,6303,6337,6348,6328,6294,6261,6231,6208,6199,6194,6172,6128,6083,6056,6042,6030,
+6016,6004,5982,5941,5895,5865,5854,5844,5826,5817,5831,5844,5802,5677,5510,5379,5322,5303,5279,5264,5304,
+5385,5427,5385,5310,5274,5267,5223,5135,5063,5044,5033,4983,4924,4917,4961,4991,4967,4912,4862,4815,4759,
+4705,4687,4728,4824,4942,5015,4966,4777,4536,4365,4313,4314,4280,4189,4092,4029,3990,3944,3885,3832,3793,
+3753,3694,3620,3557,3523,3507,3477,3420,3349,3291,3256,3230,3188,3130,3075,3041,3024,2999,2953,2901,2862,
+2831,2784,2714,2649,2620,2620,2621,2614,2610,2617,2617,2589,2535,2479,2453,2473,2528,2585,2605,2576,2515,
+2448,2389,2341,2305,2280,2255,2225,2192,2154,2110,2073,2065,2076,2050,1950,1816,1738,1749,1797,1816,1797,
+1769,1744,1715,1681,1654,1636,1616,1593,1574,1564,1554,1543,1534,1529,1522,1514,1513,1524,1543,1563,1574,
+1569,1540,1493,1447,1406,1359,1297,1231,1181,1161,1165,1178,1179,1157,1120,1093,1090,1105,1120,1128,1133,
+1135,1131,1121,1111,1102,1095,1095,1110,1134,1153,1164,1174,1189,1205,1217,1231,1254,1284,1313,1333,1345,
+1350,1351,1354,1357,1361,1371,1396,1434,1468,1480,1468,1444,1416,1393,1393,1421,1463,1495,1523,1563,1600,
+1594,1532,1469,1461,1501,1534,1529,1512,1506,1498,1469,1432,1414,1411,1398,1368,1340,1325,1312,1290,1260,
+1231,1206,1180,1155,1135,1118,1098,1075,1051,1030,1006,979,949,919,889,859,828,796,768,747,730,
+711,685,658,635,618,602,581,556,528,499,466,428,385,345,311,282,256,230,204,176,143,
+106,67,29,-6,-41,-77,-112,-146,-178,-213,-251,-292,-334,-377,-419,-462,-504,-545,-588,-633,-673,
+-710,-750,-797,-846,-890,-928,-968,-1010,-1050,-1088,-1130,-1174,-1217,-1253,-1289,-1330,-1375,-1420,-1466,-1515,-1561,
+-1604,-1646,-1691,-1734,-1771,-1805,-1840,-1879,-1916,-1949,-1983,-2021,-2060,-2098,-2134,-2167,-2198,-2229,-2261,-2293,-2324,
+-2354,-2386,-2419,-2449,-2476,-2505,-2539,-2578,-2615,-2647,-2674,-2702,-2732,-2765,-2798,-2829,-2859,-2889,-2921,-2954,-2985,
+-3012,-3036,-3060,-3087,-3113,-3132,-3147,-3163,-3181,-3197,-3207,-3216,-3229,-3244,-3257,-3267,-3274,-3279,-3282,-3284,-3287,
+-3292,-3299,-3305,-3307,-3305,-3303,-3305,-3313,-3319,-3319,-3312,-3301,-3288,-3276,-3267,-3260,-3251,-3239,-3225,-3213,-3199,
+-3182,-3163,-3145,-3123,-3095,-3062,-3030,-3003,-2976,-2947,-2914,-2878,-2839,-2799,-2758,-2718,-2681,-2647,-2613,-2579,-2547,
+-2521,-2496,-2467,-2433,-2401,-2371,-2338,-2302,-2267,-2234,-2196,-2152,-2108,-2069,-2028,-1982,-1937,-1898,-1859,-1814,-1767,
+-1725,-1686,-1645,-1604,-1566,-1529,-1488,-1445,-1406,-1371,-1334,-1296,-1260,-1225,-1188,-1152,-1121,-1093,-1060,-1027,-998,
+-971,-940,-907,-879,-856,-829,-799,-771,-747,-722,-694,-668,-641,-607,-569,-534,-503,-472,-442,-413,-382,
+-348,-318,-297,-276,-248,-215,-189,-167,-140,-108,-78,-48,-12,24,53,82,127,182,229,265,308,
+358,400,433,474,521,558,587,630,692,748,791,845,918,981,1009,1027,1061,1095,1100,1086,1088,
+1113,1150,1188,1216,1205,1150,1093,1079,1095,1104,1108,1147,1222,1280,1272,1200,1117,1110,1250,1504,1730,
+1809,1794,1848,2040,2262,2368,2325,2181,1967,1678,1329,975,688,535,559,747,1030,1318,1506,1474,1144,
+596,61,-268,-397,-460,-540,-610,-633,-635,-663,-724,-784,-819,-831,-851,-907,-997,-1081,-1126,-1127,-1086,
+-1003,-911,-880,-948,-1058,-1116,-1106,-1091,-1121,-1198,-1320,-1491,-1680,-1826,-1909,-1968,-2037,-2102,-2159,-2235,-2339,
+-2429,-2469,-2486,-2526,-2589,-2639,-2667,-2691,-2726,-2769,-2818,-2868,-2900,-2907,-2909,-2930,-2961,-2985,-3006,-3042,-3086,
+-3114,-3125,-3140,-3167,-3193,-3215,-3239,-3260,-3265,-3257,-3256,-3268,-3283,-3311,-3385,-3512,-3653,-3759,-3818,-3849,-3874,
+-3898,-3923,-3949,-3972,-3987,-3993,-3993,-3989,-3979,-3964,-3941,-3910,-3874,-3840,-3807,-3770,-3725,-3675,-3623,-3568,-3509,
+-3449,-3389,-3324,-3254,-3184,-3115,-3051,-2990,-2931,-2870,-2803,-2733,-2666,-2602,-2534,-2464,-2395,-2329,-2256,-2176,-2099,
+-2030,-1960,-1884,-1808,-1741,-1676,-1601,-1518,-1435,-1355,-1275,-1194,-1115,-1035,-950,-865,-790,-730,-669,-595,-514,
+-436,-363,-287,-206,-131,-70,-19,33,91,143,183,217,260,317,377,427,464,493,522,552,585,
+621,657,689,715,739,770,810,858,905,948,983,1009,1026,1043,1074,1117,1157,1184,1206,1236,1267,
+1285,1292,1312,1357,1418,1477,1526,1568,1607,1649,1693,1729,1738,1721,1701,1709,1747,1795,1830,1850,1860,
+1869,1878,1887,1894,1897,1904,1919,1937,1951,1961,1974,1995,2019,2041,2057,2068,2082,2109,2145,2175,2190,
+2201,2232,2285,2347,2407,2474,2564,2682,2813,2934,3021,3062,3064,3045,3025,3018,3031,3064,3103,3131,3141,
+3135,3125,3115,3109,3107,3104,3087,3054,3018,2996,2989,2987,2977,2952,2910,2856,2805,2773,2763,2767,2771,
+2770,2765,2764,2773,2789,2800,2800,2793,2783,2769,2745,2714,2682,2654,2630,2615,2621,2611,2619,2635,2646,
+2638,2605,2550,2484,2420,2368,2328,2297,2275,2265,2263,2260,2241,2201,2148,2097,2062,2043,2035,2029,2024,
+2028,2054,2106,2164,2200,2200,2175,2144,2124,2124,2145,2173,2183,2170,2154,2154,2157,2134,2077,2007,1949,
+1899,1843,1781,1721,1667,1615,1561,1504,1437,1357,1274,1208,1164,1128,1075,995,902,812,738,677,620,
+558,483,392,290,186,91,5,-80,-166,-240,-295,-340,-389,-441,-480,-491,-481,-463,-450,-451,-468,
+-496,-523,-547,-575,-608,-636,-651,-665,-702,-770,-859,-950,-1023,-1060,-1055,-1031,-1014,-1004,-979,-932,-886,
+-866,-869,-877,-886,-907,-944,-986,-1026,-1069,-1114,-1145,-1150,-1140,-1137,-1155,-1187,-1212,-1215,-1201,-1197,-1221,
+-1264,-1301,-1321,-1327,-1316,-1278,-1229,-1204,-1211,-1218,-1201,-1181,-1185,-1197,-1180,-1142,-1127,-1154,-1195,-1228,-1257,
+-1280,-1270,-1219,-1179,-1207,-1296,-1400,-1501,-1623,-1776,-1929,-2051,-2148,-2242,-2340,-2445,-2567,-2698,-2797,-2827,-2801,
+-2771,-2771,-2796,-2829,-2867,-2913,-2961,-3006,-3058,-3125,-3202,-3274,-3336,-3395,-3447,-3491,-3536,-3601,-3687,-3778,-3858,
+-3927,-3993,-4060,-4137,-4243,-4387,-4550,-4709,-4864,-5031,-5190,-5296,-5328,-5326,-5340,-5375,-5401,-5414,-5446,-5514,-5583,
+-5603,-5561,-5484,-5410,-5360,-5345,-5357,-5370,-5362,-5342,-5344,-5383,-5437,-5479,-5507,-5540,-5584,-5627,-5660,-5693,-5735,
+-5782,-5823,-5857,-5893,-5942,-6007,-6080,-6156,-6235,-6325,-6428,-6536,-6638,-6733,-6829,-6929,-7028,-7125,-7223,-7323,-7422,
+-7517,-7610,-7708,-7809,-7910,-8008,-8101,-8188,-8271,-8356,-8450,-8549,-8641,-8721,-8794,-8867,-8935,-8996,-9058,-9132,-9214,
+-9285,-9335,-9380,-9434,-9496,-9550,-9594,-9639,-9680,-9703,-9702,-9689,-9674,-9663,-9669,-9723,-9828,-9941,-10007,-10020,-10021,
+-10039,-10068,-10093,-10114,-10132,-10141,-10145,-10160,-10192,-10225,-10255,-10303,-10369,-10418,-10423,-10406,-10393,-10359,-10253,-10082,-9904,
+-9752,-9612,-9483,-9409,-9413,-9466,-9530,-9619,-9745,-9857,-9884,-9821,-9734,-9670,-9611,-9532,-9441,-9352,-9258,-9141,-9005,
+-8867,-8733,-8602,-8474,-8344,-8202,-8049,-7906,-7787,-7671,-7529,-7358,-7183,-7023,-6873,-6716,-6548,-6369,-6185,-6008,-5845,
+-5702,-5578,-5488,-5452,-5478,-5556,-5662,-5761,-5812,-5792,-5715,-5621,-5524,-5389,-5176,-4894,-4602,-4347,-4130,-3923,-3719,
+-3539,-3407,-3320,-3247,-3155,-3030,-2879,-2722,-2572,-2435,-2312,-2200,-2094,-1990,-1888,-1790,-1691,-1587,-1480,-1380,-1293,
+-1218,-1153,-1099,-1048,-984,-903,-824,-763,-713,-650,-573,-501,-441,-377,-288,-179,-62,62,200,340,461,
+555,638,724,820,927,1045,1163,1267,1354,1437,1525,1612,1686,1755,1837,1939,2051,2153,2236,2308,2389,
+2489,2603,2722,2846,2976,3089,3157,3180,3189,3221,3284,3384,3529,3716,3911,4087,4244,4389,4510,4607,4716,
+4865,5017,5102,5107,5104,5158,5255,5339,5389,5430,5476,5512,5533,5572,5677,5865,6116,6389,6637,6804,6844,
+6760,6630,6548,6525,6495,6435,6450,6666,7042,7373,7494,7417,7244,7021,6759,6512,6311,6057,5608,5034,4653,
+4729,5199,5754,6159,6401,6564,6680,6738,6752,6755,6756,6742,6713,6687,6669,6650,6630,6622,6630,6647,6668,
+6700,6743,6777,6778,6732,6636,6500,6361,6281,6301,6400,6505,6559,6562,6554,6553,6548,6528,6508,6500,6496,
+6484,6465,6455,6457,6457,6444,6422,6398,6376,6354,6336,6324,6321,6322,6323,6322,6325,6343,6374,6400,6402,
+6377,6337,6297,6264,6242,6235,6231,6213,6175,6127,6083,6050,6031,6023,6015,5996,5965,5932,5908,5890,5872,
+5852,5833,5816,5801,5779,5732,5648,5541,5440,5366,5320,5297,5300,5314,5313,5284,5251,5235,5222,5183,5125,
+5087,5080,5071,5029,4971,4935,4930,4932,4924,4906,4881,4845,4811,4798,4811,4841,4887,4946,4978,4918,4743,
+4524,4376,4340,4351,4322,4239,4154,4107,4075,4021,3942,3869,3818,3776,3718,3645,3581,3546,3533,3513,3468,
+3400,3333,3283,3248,3211,3160,3105,3060,3029,3000,2962,2915,2873,2840,2809,2762,2694,2620,2571,2573,2630,
+2706,2748,2725,2649,2556,2476,2424,2419,2473,2565,2636,2627,2539,2425,2348,2324,2325,2312,2277,2238,2207,
+2166,2107,2063,2082,2142,2150,2041,1868,1755,1757,1814,1844,1825,1791,1760,1727,1688,1655,1632,1609,1586,
+1569,1561,1557,1551,1545,1543,1542,1543,1551,1567,1583,1594,1596,1584,1552,1508,1466,1431,1391,1336,1273,
+1220,1194,1195,1208,1211,1188,1147,1117,1116,1133,1147,1152,1153,1155,1152,1141,1127,1117,1111,1112,1122,
+1140,1158,1172,1185,1202,1219,1233,1246,1264,1285,1306,1325,1341,1355,1365,1369,1371,1371,1375,1391,1423,
+1462,1487,1483,1455,1426,1424,1457,1507,1540,1544,1542,1564,1600,1605,1561,1505,1488,1511,1537,1543,1541,
+1544,1538,1511,1478,1465,1466,1454,1420,1383,1360,1345,1324,1296,1268,1243,1219,1197,1179,1162,1141,1117,
+1093,1073,1052,1029,1002,974,946,916,880,841,803,775,755,736,713,687,662,642,626,610,590,
+564,535,502,462,417,374,337,307,282,258,233,207,176,140,101,61,22,-13,-47,-79,-109,
+-139,-171,-207,-247,-287,-328,-371,-416,-461,-507,-553,-598,-638,-673,-710,-752,-798,-840,-879,-923,-969,
+-1013,-1053,-1097,-1143,-1185,-1222,-1259,-1300,-1343,-1385,-1429,-1475,-1521,-1562,-1601,-1645,-1689,-1729,-1764,-1798,-1833,
+-1865,-1896,-1928,-1962,-1998,-2032,-2067,-2101,-2135,-2168,-2203,-2237,-2269,-2298,-2328,-2357,-2384,-2410,-2439,-2475,-2516,
+-2555,-2588,-2616,-2642,-2670,-2701,-2734,-2768,-2802,-2835,-2867,-2899,-2929,-2955,-2977,-3000,-3027,-3055,-3078,-3096,-3113,
+-3133,-3152,-3167,-3179,-3190,-3203,-3215,-3226,-3236,-3243,-3246,-3246,-3247,-3250,-3255,-3262,-3268,-3271,-3271,-3275,-3282,
+-3287,-3286,-3280,-3270,-3257,-3245,-3234,-3225,-3215,-3202,-3189,-3177,-3163,-3146,-3128,-3110,-3088,-3060,-3029,-3001,-2976,
+-2949,-2920,-2889,-2855,-2816,-2773,-2730,-2691,-2659,-2629,-2598,-2565,-2534,-2507,-2479,-2447,-2413,-2383,-2356,-2325,-2289,
+-2254,-2220,-2182,-2138,-2098,-2063,-2026,-1980,-1935,-1895,-1855,-1811,-1765,-1727,-1692,-1652,-1609,-1571,-1535,-1495,-1452,
+-1414,-1379,-1342,-1303,-1267,-1233,-1197,-1162,-1132,-1106,-1075,-1041,-1010,-981,-950,-918,-890,-867,-842,-816,-789,
+-762,-731,-699,-673,-648,-619,-584,-552,-522,-489,-455,-426,-400,-370,-340,-316,-298,-276,-249,-222,-192,
+-158,-124,-96,-68,-29,11,42,70,112,167,214,252,296,346,384,412,448,500,548,586,629,
+683,732,775,831,901,952,973,988,1019,1048,1057,1064,1093,1139,1186,1235,1274,1266,1204,1142,1128,
+1146,1157,1174,1233,1319,1374,1368,1305,1200,1112,1153,1378,1669,1844,1884,1952,2155,2388,2485,2423,2294,
+2131,1869,1484,1071,782,707,826,1053,1308,1539,1689,1649,1320,753,168,-219,-380,-436,-489,-540,-561,
+-571,-610,-679,-746,-791,-822,-868,-941,-1022,-1075,-1086,-1057,-989,-880,-778,-762,-847,-946,-972,-949,-968,
+-1058,-1179,-1303,-1451,-1615,-1743,-1810,-1851,-1905,-1965,-2022,-2097,-2196,-2283,-2329,-2357,-2411,-2484,-2545,-2586,-2621,
+-2659,-2704,-2761,-2823,-2861,-2861,-2853,-2872,-2907,-2930,-2943,-2976,-3030,-3079,-3109,-3135,-3165,-3187,-3196,-3204,-3213,
+-3216,-3212,-3214,-3223,-3228,-3236,-3276,-3363,-3473,-3573,-3648,-3704,-3750,-3792,-3836,-3880,-3918,-3941,-3954,-3959,-3952,
+-3934,-3912,-3893,-3871,-3842,-3809,-3773,-3734,-3691,-3645,-3597,-3549,-3499,-3448,-3393,-3329,-3258,-3185,-3115,-3048,-2980,
+-2915,-2850,-2783,-2716,-2653,-2590,-2522,-2452,-2387,-2325,-2254,-2175,-2101,-2035,-1969,-1894,-1818,-1753,-1692,-1623,-1544,
+-1460,-1376,-1290,-1204,-1124,-1046,-963,-876,-795,-724,-658,-585,-508,-432,-356,-276,-192,-116,-54,-1,55,
+117,173,215,248,285,334,390,441,481,510,534,561,596,636,674,704,728,753,785,827,877,
+923,959,984,1001,1013,1029,1057,1098,1138,1167,1191,1223,1256,1274,1276,1286,1323,1387,1459,1522,1572,
+1606,1629,1653,1679,1697,1701,1705,1726,1766,1809,1839,1854,1860,1863,1863,1863,1862,1863,1871,1886,1901,
+1911,1920,1936,1961,1987,2009,2026,2039,2052,2074,2110,2149,2175,2190,2207,2234,2268,2305,2352,2418,2505,
+2611,2726,2836,2922,2974,2995,2997,2989,2990,3013,3053,3088,3100,3096,3091,3092,3095,3095,3088,3067,3029,
+2985,2958,2954,2961,2956,2929,2884,2831,2786,2760,2755,2760,2763,2761,2759,2763,2773,2783,2786,2783,2776,
+2771,2766,2757,2740,2714,2681,2647,2621,2623,2605,2600,2599,2586,2548,2484,2405,2328,2261,2201,2147,2102,
+2074,2071,2091,2115,2122,2100,2057,2007,1964,1933,1922,1929,1948,1975,2018,2079,2137,2167,2164,2146,2134,
+2132,2141,2163,2192,2211,2218,2228,2246,2240,2174,2057,1942,1872,1836,1799,1741,1670,1601,1542,1490,1437,
+1372,1295,1218,1157,1111,1067,1014,948,875,801,729,661,595,529,457,370,266,156,54,-35,-122,
+-215,-304,-377,-433,-487,-541,-578,-583,-563,-538,-522,-519,-528,-548,-575,-607,-639,-668,-690,-703,-715,
+-738,-784,-856,-950,-1040,-1095,-1101,-1083,-1073,-1068,-1041,-986,-934,-915,-918,-919,-916,-927,-962,-1008,-1053,
+-1096,-1136,-1162,-1169,-1165,-1167,-1184,-1212,-1237,-1245,-1236,-1230,-1245,-1275,-1302,-1320,-1333,-1333,-1305,-1259,-1232,
+-1236,-1245,-1234,-1224,-1238,-1253,-1227,-1175,-1157,-1202,-1269,-1310,-1318,-1308,-1281,-1245,-1241,-1306,-1420,-1535,-1635,
+-1745,-1877,-2007,-2118,-2220,-2324,-2424,-2516,-2618,-2736,-2839,-2884,-2875,-2853,-2853,-2878,-2917,-2967,-3022,-3071,-3109,
+-3152,-3214,-3289,-3363,-3428,-3486,-3535,-3577,-3626,-3697,-3787,-3873,-3942,-3997,-4054,-4124,-4220,-4358,-4531,-4702,-4838,
+-4950,-5070,-5201,-5297,-5330,-5328,-5341,-5375,-5400,-5416,-5457,-5533,-5592,-5576,-5487,-5386,-5329,-5324,-5345,-5366,-5371,
+-5357,-5342,-5353,-5400,-5462,-5511,-5540,-5567,-5603,-5643,-5681,-5719,-5766,-5816,-5860,-5895,-5930,-5977,-6037,-6101,-6163,
+-6233,-6322,-6429,-6535,-6632,-6724,-6823,-6929,-7030,-7124,-7219,-7322,-7424,-7518,-7606,-7700,-7799,-7899,-7994,-8084,-8173,
+-8261,-8351,-8447,-8544,-8634,-8712,-8786,-8859,-8926,-8985,-9048,-9127,-9215,-9290,-9341,-9385,-9441,-9506,-9566,-9614,-9655,
+-9686,-9703,-9707,-9704,-9693,-9673,-9667,-9717,-9829,-9949,-10017,-10027,-10026,-10045,-10076,-10102,-10123,-10147,-10164,-10169,-10176,
+-10199,-10231,-10260,-10299,-10358,-10422,-10463,-10476,-10469,-10426,-10323,-10167,-10004,-9864,-9743,-9641,-9582,-9583,-9628,-9700,-9793,
+-9895,-9960,-9948,-9877,-9797,-9730,-9659,-9570,-9475,-9382,-9280,-9158,-9022,-8887,-8756,-8627,-8500,-8366,-8216,-8057,-7912,
+-7789,-7663,-7513,-7343,-7176,-7021,-6872,-6717,-6551,-6369,-6176,-5990,-5826,-5681,-5552,-5458,-5423,-5448,-5514,-5602,-5687,
+-5726,-5680,-5577,-5492,-5457,-5404,-5236,-4940,-4603,-4312,-4086,-3889,-3698,-3524,-3386,-3288,-3211,-3125,-3007,-2853,-2683,
+-2521,-2382,-2261,-2151,-2044,-1939,-1834,-1734,-1637,-1535,-1424,-1313,-1212,-1123,-1044,-978,-923,-865,-795,-724,-669,
+-627,-575,-505,-435,-378,-319,-235,-125,-7,115,251,394,521,621,703,789,888,1001,1124,1244,1348,
+1432,1509,1589,1671,1753,1838,1933,2035,2133,2218,2292,2361,2439,2536,2653,2781,2907,3019,3100,3139,3151,
+3174,3239,3357,3522,3714,3901,4054,4175,4297,4436,4573,4695,4829,5000,5166,5245,5225,5187,5217,5311,5407,
+5470,5520,5575,5623,5664,5741,5900,6133,6382,6598,6759,6840,6803,6656,6498,6443,6492,6539,6523,6528,6670,
+6933,7180,7308,7312,7210,7001,6740,6541,6414,6173,5648,4975,4548,4633,5121,5687,6113,6386,6571,6693,6756,
+6787,6806,6807,6784,6755,6735,6719,6694,6667,6651,6654,6672,6704,6748,6793,6823,6819,6765,6658,6522,6411,
+6374,6411,6482,6541,6576,6599,6619,6626,6608,6575,6550,6541,6537,6527,6516,6512,6509,6494,6468,6447,6435,
+6418,6387,6358,6352,6368,6384,6385,6381,6388,6409,6428,6431,6415,6385,6349,6317,6294,6283,6280,6275,6258,
+6227,6182,6133,6092,6069,6057,6041,6017,5992,5975,5960,5938,5911,5881,5843,5797,5761,5757,5770,5747,5656,
+5523,5407,5344,5321,5312,5303,5293,5276,5248,5208,5167,5136,5127,5135,5139,5121,5077,5026,4984,4957,4945,
+4942,4934,4906,4871,4861,4890,4930,4939,4918,4898,4884,4831,4703,4536,4413,4372,4366,4332,4265,4208,4183,
+4156,4092,3996,3907,3845,3797,3741,3677,3618,3576,3549,3527,3497,3450,3390,3327,3272,3225,3181,3136,3092,
+3054,3021,2988,2946,2901,2868,2854,2841,2794,2707,2630,2633,2736,2870,2927,2862,2723,2588,2498,2445,2431,
+2480,2593,2701,2710,2598,2441,2341,2329,2349,2339,2293,2248,2220,2181,2114,2062,2087,2171,2209,2118,1940,
+1802,1777,1827,1865,1857,1823,1785,1743,1699,1661,1635,1612,1588,1568,1558,1557,1557,1556,1555,1556,1564,
+1581,1600,1613,1614,1604,1582,1548,1511,1477,1448,1414,1368,1311,1258,1222,1212,1221,1226,1206,1164,1131,
+1128,1150,1171,1177,1175,1174,1169,1158,1144,1134,1132,1134,1142,1155,1170,1184,1199,1217,1235,1251,1263,
+1276,1289,1303,1318,1340,1365,1385,1395,1396,1394,1393,1401,1426,1466,1500,1504,1479,1455,1465,1510,1561,
+1582,1571,1557,1570,1608,1634,1621,1583,1553,1551,1563,1575,1584,1590,1582,1554,1525,1511,1508,1495,1461,
+1423,1395,1375,1352,1325,1298,1276,1256,1236,1217,1199,1179,1157,1136,1115,1092,1067,1042,1018,994,966,
+931,890,847,811,785,764,743,718,691,667,649,635,619,595,564,529,489,445,402,365,333,
+306,281,257,233,207,176,141,102,61,22,-10,-39,-67,-98,-131,-167,-204,-241,-278,-319,-364,
+-412,-460,-508,-555,-599,-638,-675,-715,-759,-802,-844,-888,-933,-975,-1016,-1060,-1106,-1148,-1185,-1223,-1267,
+-1310,-1350,-1390,-1434,-1479,-1519,-1558,-1599,-1641,-1681,-1716,-1750,-1781,-1811,-1841,-1873,-1905,-1936,-1966,-1997,-2032,
+-2070,-2109,-2148,-2185,-2218,-2249,-2279,-2308,-2334,-2361,-2393,-2430,-2470,-2507,-2538,-2564,-2589,-2616,-2645,-2676,-2710,
+-2746,-2781,-2813,-2842,-2869,-2894,-2915,-2938,-2964,-2993,-3020,-3041,-3061,-3083,-3106,-3126,-3140,-3152,-3162,-3173,-3186,
+-3200,-3210,-3214,-3216,-3216,-3218,-3221,-3228,-3235,-3240,-3243,-3245,-3249,-3252,-3251,-3245,-3236,-3225,-3211,-3199,-3190,
+-3180,-3169,-3156,-3144,-3128,-3108,-3088,-3068,-3048,-3023,-2998,-2974,-2951,-2923,-2892,-2862,-2831,-2794,-2750,-2706,-2668,
+-2637,-2610,-2581,-2549,-2518,-2490,-2461,-2429,-2396,-2367,-2340,-2310,-2275,-2240,-2206,-2168,-2127,-2091,-2059,-2022,-1976,
+-1929,-1888,-1849,-1806,-1763,-1728,-1696,-1658,-1616,-1577,-1540,-1499,-1458,-1421,-1386,-1348,-1308,-1273,-1242,-1208,-1173,
+-1143,-1117,-1087,-1054,-1021,-992,-963,-933,-906,-880,-853,-827,-803,-776,-743,-708,-680,-656,-627,-595,-567,
+-541,-509,-475,-446,-423,-395,-362,-334,-316,-299,-279,-255,-222,-181,-141,-112,-86,-48,-5,30,61,
+102,151,195,231,277,329,370,396,430,480,533,579,625,673,714,750,799,858,900,919,941,
+975,1003,1013,1029,1069,1125,1189,1265,1330,1335,1282,1240,1254,1286,1293,1303,1352,1410,1428,1414,1386,
+1308,1185,1149,1332,1649,1873,1935,2006,2223,2474,2565,2480,2350,2212,1968,1583,1191,973,991,1171,1408,
+1630,1798,1857,1720,1322,731,152,-220,-358,-380,-403,-446,-485,-520,-567,-630,-693,-752,-816,-889,-963,
+-1014,-1028,-1012,-968,-881,-753,-647,-641,-728,-797,-782,-755,-829,-1003,-1173,-1289,-1397,-1534,-1663,-1734,-1763,
+-1788,-1819,-1852,-1900,-1969,-2039,-2096,-2155,-2232,-2315,-2387,-2451,-2516,-2575,-2627,-2688,-2758,-2802,-2803,-2795,-2815,
+-2850,-2866,-2874,-2916,-2993,-3068,-3116,-3150,-3181,-3198,-3195,-3186,-3182,-3182,-3184,-3194,-3210,-3221,-3224,-3238,-3277,
+-3337,-3405,-3476,-3545,-3612,-3680,-3752,-3820,-3868,-3892,-3905,-3911,-3905,-3884,-3860,-3842,-3826,-3803,-3771,-3736,-3698,
+-3654,-3609,-3564,-3520,-3478,-3436,-3389,-3329,-3256,-3180,-3109,-3041,-2973,-2905,-2839,-2774,-2710,-2646,-2579,-2506,-2432,
+-2367,-2307,-2242,-2168,-2096,-2033,-1969,-1895,-1821,-1757,-1700,-1638,-1564,-1482,-1396,-1306,-1218,-1136,-1060,-982,-898,
+-815,-738,-667,-596,-524,-451,-375,-294,-209,-129,-60,0,63,129,191,238,275,310,350,395,440,
+480,512,536,562,598,639,676,706,734,764,800,841,887,929,958,974,986,999,1016,1039,1073,
+1110,1143,1174,1212,1250,1275,1280,1286,1316,1371,1438,1501,1552,1583,1596,1606,1623,1645,1667,1693,1729,
+1774,1815,1841,1852,1851,1841,1828,1818,1815,1819,1831,1846,1861,1871,1884,1908,1938,1966,1988,2007,2024,
+2039,2059,2089,2125,2155,2175,2193,2214,2240,2270,2308,2355,2410,2478,2563,2663,2764,2854,2922,2961,2973,
+2976,2997,3038,3076,3089,3082,3075,3077,3079,3074,3062,3037,2997,2953,2927,2927,2937,2931,2898,2849,2798,
+2759,2740,2739,2746,2749,2749,2754,2765,2773,2771,2760,2750,2746,2747,2747,2743,2732,2712,2683,2651,2623,
+2591,2569,2548,2519,2470,2389,2286,2183,2098,2030,1966,1904,1852,1828,1839,1881,1934,1974,1993,1988,1961,
+1916,1870,1846,1854,1883,1920,1971,2037,2095,2119,2113,2112,2134,2163,2175,2173,2173,2186,2214,2253,2283,
+2261,2160,2010,1879,1807,1780,1754,1701,1624,1541,1467,1407,1354,1299,1241,1184,1130,1072,1011,956,908,
+858,792,711,632,563,502,435,348,239,120,9,-86,-178,-275,-371,-451,-511,-563,-611,-640,-637,
+-611,-586,-575,-577,-585,-602,-632,-670,-706,-728,-738,-743,-750,-762,-788,-841,-931,-1036,-1112,-1138,-1134,
+-1133,-1135,-1112,-1060,-1011,-994,-992,-976,-950,-946,-979,-1034,-1084,-1120,-1140,-1145,-1140,-1141,-1157,-1188,-1222,
+-1250,-1265,-1267,-1268,-1280,-1301,-1319,-1332,-1346,-1353,-1337,-1301,-1273,-1269,-1271,-1265,-1270,-1300,-1322,-1294,-1235,
+-1216,-1268,-1341,-1369,-1347,-1312,-1292,-1295,-1334,-1419,-1529,-1633,-1725,-1822,-1933,-2047,-2162,-2286,-2410,-2507,-2574,
+-2644,-2740,-2838,-2895,-2905,-2901,-2915,-2955,-3015,-3088,-3159,-3209,-3239,-3267,-3313,-3375,-3442,-3505,-3564,-3614,-3661,
+-3718,-3794,-3879,-3950,-4001,-4050,-4115,-4202,-4321,-4482,-4673,-4850,-4970,-5042,-5114,-5208,-5295,-5337,-5343,-5349,-5370,
+-5394,-5421,-5472,-5543,-5579,-5531,-5421,-5325,-5298,-5326,-5360,-5374,-5370,-5363,-5364,-5384,-5429,-5487,-5537,-5569,-5593,
+-5623,-5662,-5705,-5751,-5799,-5848,-5895,-5935,-5975,-6022,-6075,-6128,-6181,-6245,-6332,-6434,-6535,-6625,-6715,-6818,-6928,
+-7030,-7121,-7217,-7323,-7429,-7523,-7609,-7697,-7791,-7883,-7971,-8060,-8151,-8243,-8334,-8428,-8523,-8612,-8694,-8770,-8845,
+-8913,-8974,-9040,-9120,-9206,-9280,-9333,-9382,-9442,-9510,-9571,-9619,-9656,-9682,-9701,-9715,-9723,-9713,-9680,-9660,-9704,
+-9820,-9946,-10016,-10026,-10027,-10051,-10088,-10115,-10137,-10165,-10190,-10198,-10200,-10212,-10233,-10252,-10282,-10345,-10439,-10524,-10565,
+-10554,-10500,-10409,-10290,-10162,-10042,-9936,-9850,-9796,-9787,-9822,-9888,-9969,-10033,-10043,-9995,-9918,-9845,-9776,-9696,-9602,
+-9508,-9411,-9299,-9168,-9034,-8907,-8787,-8667,-8542,-8403,-8245,-8082,-7934,-7802,-7661,-7501,-7334,-7178,-7028,-6873,-6714,
+-6547,-6361,-6162,-5978,-5826,-5695,-5572,-5475,-5432,-5442,-5481,-5541,-5610,-5637,-5565,-5425,-5330,-5335,-5354,-5243,-4963,
+-4609,-4292,-4040,-3827,-3639,-3485,-3367,-3273,-3188,-3096,-2977,-2821,-2644,-2477,-2333,-2208,-2093,-1986,-1885,-1785,-1685,
+-1584,-1478,-1365,-1249,-1140,-1037,-938,-852,-789,-742,-690,-626,-568,-523,-479,-422,-361,-309,-256,-179,-73,
+44,166,299,441,573,677,762,849,951,1069,1197,1319,1423,1506,1578,1652,1730,1814,1909,2016,2119,
+2207,2278,2343,2412,2491,2589,2712,2849,2974,3061,3106,3125,3149,3209,3322,3488,3691,3895,4056,4155,4226,
+4330,4487,4660,4815,4968,5145,5309,5381,5344,5284,5302,5404,5518,5591,5638,5692,5759,5839,5960,6151,6375,
+6556,6652,6687,6689,6638,6525,6416,6406,6497,6584,6598,6584,6625,6725,6832,6927,7007,7012,6874,6651,6492,
+6408,6191,5664,4977,4524,4565,5003,5557,6025,6360,6577,6697,6760,6811,6851,6853,6819,6784,6770,6761,6739,
+6710,6691,6691,6714,6760,6817,6859,6872,6855,6809,6730,6632,6552,6520,6530,6555,6584,6617,6650,6666,6651,
+6616,6586,6574,6575,6574,6564,6551,6539,6525,6502,6477,6466,6467,6458,6429,6400,6394,6410,6420,6416,6412,
+6424,6445,6453,6439,6410,6376,6342,6315,6301,6299,6296,6288,6276,6258,6230,6191,6153,6124,6099,6068,6034,
+6013,6007,5999,5977,5946,5911,5866,5811,5770,5766,5783,5764,5672,5535,5417,5355,5334,5325,5316,5313,5308,
+5279,5220,5166,5159,5201,5250,5253,5202,5130,5071,5032,5007,4995,4991,4978,4942,4906,4911,4966,5021,5017,
+4952,4879,4837,4801,4725,4606,4495,4427,4385,4335,4276,4239,4227,4205,4142,4048,3957,3887,3833,3785,3741,
+3696,3645,3591,3548,3519,3491,3444,3375,3301,3240,3199,3168,3133,3090,3048,3010,2973,2935,2914,2924,2942,
+2917,2826,2726,2712,2820,2969,3028,2939,2768,2621,2540,2494,2461,2476,2572,2695,2738,2648,2493,2384,2364,
+2379,2362,2310,2262,2233,2197,2133,2075,2078,2142,2189,2138,1997,1857,1802,1828,1873,1884,1857,1814,1766,
+1718,1677,1648,1625,1600,1574,1558,1559,1570,1577,1575,1573,1581,1598,1617,1625,1620,1603,1575,1541,1511,
+1488,1466,1437,1397,1349,1297,1253,1230,1234,1244,1234,1196,1155,1141,1159,1185,1200,1201,1197,1190,1178,
+1164,1153,1151,1154,1161,1172,1183,1194,1207,1226,1248,1269,1284,1295,1303,1309,1318,1338,1368,1396,1413,
+1419,1420,1419,1424,1443,1480,1515,1525,1504,1481,1483,1514,1551,1575,1583,1586,1600,1633,1667,1675,1647,
+1603,1576,1581,1604,1625,1632,1620,1593,1564,1543,1528,1509,1478,1446,1420,1402,1382,1358,1333,1312,1293,
+1274,1253,1232,1212,1194,1174,1152,1126,1099,1073,1050,1027,1002,971,934,892,852,818,792,768,742,
+715,690,673,661,645,621,589,553,516,477,438,400,366,334,305,280,258,237,212,183,147,
+107,68,34,4,-25,-59,-95,-132,-168,-202,-236,-273,-317,-364,-411,-457,-504,-552,-596,-637,-679,
+-723,-770,-816,-860,-900,-937,-975,-1018,-1063,-1104,-1141,-1182,-1228,-1272,-1312,-1350,-1393,-1436,-1477,-1515,-1555,
+-1596,-1635,-1670,-1701,-1731,-1760,-1790,-1823,-1856,-1885,-1911,-1939,-1973,-2012,-2053,-2095,-2133,-2168,-2201,-2234,-2265,
+-2293,-2323,-2356,-2393,-2429,-2461,-2490,-2517,-2543,-2570,-2598,-2627,-2660,-2695,-2730,-2761,-2787,-2812,-2836,-2861,-2884,
+-2910,-2939,-2967,-2992,-3015,-3038,-3062,-3084,-3102,-3115,-3124,-3133,-3145,-3160,-3172,-3180,-3184,-3187,-3189,-3192,-3198,
+-3206,-3211,-3214,-3215,-3217,-3217,-3214,-3208,-3200,-3189,-3176,-3164,-3157,-3148,-3137,-3124,-3110,-3094,-3071,-3049,-3029,
+-3011,-2991,-2970,-2949,-2926,-2897,-2866,-2838,-2810,-2776,-2735,-2692,-2654,-2622,-2593,-2563,-2532,-2499,-2469,-2441,-2411,
+-2380,-2350,-2323,-2294,-2261,-2227,-2194,-2158,-2119,-2084,-2052,-2014,-1967,-1919,-1878,-1841,-1800,-1760,-1726,-1695,-1659,
+-1619,-1582,-1545,-1504,-1463,-1428,-1395,-1356,-1314,-1280,-1251,-1219,-1185,-1153,-1125,-1095,-1062,-1030,-1002,-975,-949,
+-923,-895,-864,-834,-810,-787,-757,-723,-695,-669,-639,-606,-579,-555,-525,-493,-467,-446,-420,-387,-358,
+-336,-316,-295,-273,-245,-205,-163,-130,-104,-69,-26,13,47,88,134,173,208,253,310,357,390,
+425,470,519,563,611,660,698,725,759,800,831,852,883,926,960,978,1002,1044,1101,1179,1280,
+1363,1368,1315,1289,1327,1367,1367,1371,1417,1454,1435,1410,1420,1394,1280,1209,1357,1664,1880,1925,1993,
+2237,2521,2621,2530,2398,2259,2006,1632,1312,1217,1339,1552,1762,1932,2013,1935,1644,1156,578,79,-214,
+-309,-313,-327,-371,-420,-463,-511,-569,-636,-713,-800,-881,-937,-954,-944,-921,-879,-788,-650,-541,-541,
+-621,-665,-625,-606,-729,-960,-1152,-1243,-1315,-1448,-1606,-1705,-1721,-1697,-1670,-1651,-1648,-1670,-1717,-1789,-1884,
+-1986,-2077,-2164,-2271,-2392,-2490,-2554,-2613,-2680,-2726,-2735,-2737,-2766,-2802,-2813,-2823,-2881,-2989,-3094,-3162,-3199,
+-3223,-3228,-3211,-3188,-3176,-3174,-3178,-3192,-3218,-3244,-3262,-3273,-3281,-3290,-3309,-3346,-3401,-3472,-3561,-3666,-3763,
+-3825,-3849,-3854,-3853,-3843,-3823,-3804,-3791,-3778,-3756,-3729,-3699,-3662,-3617,-3570,-3527,-3486,-3448,-3412,-3371,-3316,
+-3243,-3165,-3093,-3026,-2960,-2894,-2830,-2768,-2705,-2639,-2569,-2492,-2414,-2346,-2285,-2223,-2155,-2087,-2023,-1957,-1885,
+-1813,-1750,-1693,-1632,-1559,-1479,-1395,-1309,-1224,-1143,-1066,-989,-909,-829,-752,-678,-607,-536,-464,-388,-307,
+-222,-139,-62,7,74,139,199,250,293,330,365,401,440,481,516,544,575,613,653,686,716,
+749,787,823,858,895,929,952,964,978,998,1019,1036,1057,1088,1124,1161,1201,1241,1271,1287,1301,
+1331,1376,1428,1479,1523,1554,1570,1580,1596,1620,1649,1683,1725,1771,1809,1835,1844,1838,1817,1793,1777,
+1776,1785,1800,1815,1828,1839,1855,1881,1911,1937,1958,1979,2005,2030,2055,2081,2108,2131,2149,2166,2189,
+2215,2243,2275,2311,2349,2393,2450,2524,2612,2709,2805,2883,2934,2967,3004,3051,3087,3092,3075,3063,3065,
+3068,3058,3035,3003,2964,2924,2901,2900,2908,2900,2866,2817,2770,2736,2718,2716,2719,2722,2725,2737,2751,
+2754,2737,2715,2707,2716,2728,2729,2716,2693,2667,2640,2614,2591,2502,2473,2437,2388,2314,2209,2087,1973,
+1885,1816,1753,1695,1655,1647,1675,1730,1798,1867,1928,1967,1967,1925,1864,1823,1817,1833,1861,1909,1976,
+2036,2058,2059,2085,2150,2211,2221,2184,2144,2143,2184,2243,2274,2233,2116,1965,1840,1769,1733,1700,1650,
+1579,1498,1419,1353,1297,1247,1203,1163,1114,1046,968,907,872,835,771,683,600,538,486,419,323,
+203,75,-45,-152,-251,-348,-437,-511,-567,-614,-653,-671,-662,-637,-619,-619,-628,-636,-648,-674,-714,
+-751,-768,-766,-761,-762,-771,-789,-834,-922,-1033,-1124,-1167,-1179,-1189,-1197,-1181,-1139,-1098,-1079,-1064,-1027,
+-981,-965,-1000,-1062,-1116,-1141,-1140,-1121,-1100,-1096,-1119,-1162,-1207,-1244,-1271,-1287,-1297,-1312,-1330,-1346,-1358,
+-1369,-1376,-1367,-1340,-1314,-1301,-1293,-1289,-1305,-1347,-1378,-1357,-1303,-1281,-1324,-1383,-1395,-1355,-1314,-1312,-1357,
+-1431,-1520,-1608,-1690,-1775,-1868,-1968,-2072,-2196,-2347,-2494,-2595,-2647,-2692,-2764,-2844,-2898,-2917,-2930,-2963,-3024,
+-3110,-3205,-3286,-3332,-3349,-3360,-3388,-3436,-3497,-3563,-3627,-3682,-3735,-3800,-3877,-3950,-4001,-4040,-4098,-4190,-4309,
+-4444,-4600,-4777,-4942,-5054,-5111,-5155,-5223,-5302,-5354,-5365,-5359,-5366,-5393,-5438,-5496,-5548,-5551,-5485,-5385,-5317,
+-5312,-5345,-5370,-5374,-5375,-5389,-5414,-5443,-5479,-5525,-5570,-5602,-5621,-5642,-5678,-5727,-5780,-5830,-5879,-5928,-5974,
+-6019,-6067,-6117,-6167,-6216,-6275,-6353,-6444,-6535,-6619,-6708,-6812,-6921,-7023,-7116,-7214,-7320,-7426,-7519,-7605,-7693,
+-7781,-7865,-7948,-8036,-8129,-8221,-8310,-8400,-8494,-8585,-8670,-8749,-8825,-8898,-8966,-9036,-9114,-9192,-9260,-9317,-9374,
+-9439,-9506,-9563,-9609,-9645,-9675,-9702,-9728,-9744,-9730,-9683,-9647,-9682,-9796,-9927,-10004,-10022,-10028,-10057,-10097,-10127,
+-10150,-10179,-10208,-10222,-10227,-10238,-10254,-10266,-10289,-10356,-10470,-10583,-10638,-10620,-10561,-10492,-10423,-10344,-10256,-10167,-10088,
+-10032,-10005,-10015,-10058,-10110,-10131,-10101,-10030,-9953,-9883,-9808,-9718,-9624,-9532,-9432,-9308,-9170,-9042,-8931,-8824,-8710,
+-8581,-8433,-8269,-8105,-7959,-7820,-7666,-7496,-7333,-7183,-7031,-6868,-6700,-6529,-6344,-6149,-5976,-5844,-5730,-5613,-5512,
+-5457,-5442,-5446,-5474,-5527,-5546,-5454,-5278,-5159,-5181,-5256,-5213,-4988,-4657,-4323,-4017,-3745,-3534,-3409,-3341,-3278,
+-3192,-3083,-2947,-2780,-2597,-2431,-2293,-2168,-2046,-1930,-1828,-1732,-1635,-1532,-1424,-1310,-1196,-1083,-969,-849,-740,
+-668,-631,-596,-537,-468,-411,-367,-322,-275,-231,-186,-117,-19,94,215,345,484,616,725,813,902,
+1004,1125,1257,1383,1489,1571,1641,1711,1785,1864,1960,2070,2180,2270,2340,2406,2479,2565,2670,2799,2940,
+3057,3121,3141,3156,3206,3310,3461,3649,3854,4038,4162,4218,4261,4364,4547,4759,4942,5095,5249,5387,5449,
+5416,5366,5395,5514,5643,5719,5754,5802,5884,5994,6139,6320,6491,6577,6554,6488,6452,6445,6426,6402,6426,
+6508,6588,6616,6605,6585,6551,6509,6518,6608,6697,6671,6538,6418,6331,6116,5635,5014,4574,4537,4863,5366,
+5875,6292,6562,6695,6760,6824,6879,6885,6846,6808,6798,6798,6783,6757,6739,6742,6774,6833,6895,6926,6916,
+6884,6848,6804,6745,6683,6636,6611,6609,6634,6678,6713,6714,6685,6653,6636,6634,6630,6615,6590,6562,6538,
+6517,6498,6482,6476,6478,6475,6459,6442,6438,6442,6438,6425,6423,6441,6464,6470,6456,6427,6392,6352,6319,
+6301,6292,6281,6267,6259,6255,6244,6218,6187,6158,6128,6091,6056,6035,6028,6021,6005,5980,5947,5903,5857,
+5823,5803,5777,5715,5613,5502,5417,5372,5351,5335,5322,5320,5319,5297,5250,5215,5241,5324,5399,5393,5302,
+5183,5096,5054,5041,5039,5036,5020,4987,4956,4963,5012,5061,5054,4984,4902,4854,4834,4792,4702,4590,4495,
+4423,4356,4291,4247,4229,4213,4171,4100,4018,3945,3891,3862,3849,3827,3769,3683,3603,3554,3524,3482,3414,
+3334,3269,3231,3208,3178,3130,3071,3017,2974,2947,2948,2981,3016,3001,2910,2795,2751,2822,2944,2996,2919,
+2771,2652,2596,2555,2492,2448,2490,2601,2679,2645,2531,2429,2389,2385,2367,2325,2281,2248,2215,2167,2111,
+2075,2085,2117,2114,2034,1910,1822,1817,1862,1892,1876,1833,1786,1739,1694,1659,1634,1610,1582,1562,1566,
+1587,1601,1598,1590,1592,1602,1612,1615,1612,1599,1573,1543,1521,1506,1490,1463,1427,1385,1336,1288,1256,
+1256,1275,1283,1257,1211,1177,1176,1198,1220,1228,1226,1218,1206,1191,1177,1170,1170,1177,1186,1195,1201,
+1211,1229,1256,1283,1301,1311,1315,1315,1317,1329,1357,1390,1416,1431,1438,1441,1443,1456,1485,1517,1532,
+1523,1504,1494,1498,1518,1554,1595,1626,1642,1656,1677,1685,1654,1595,1554,1562,1603,1639,1649,1638,1616,
+1588,1559,1532,1507,1482,1460,1443,1432,1420,1401,1377,1353,1331,1312,1292,1270,1248,1227,1207,1185,1160,
+1133,1106,1079,1054,1029,1001,968,929,889,850,818,789,763,737,716,701,689,673,647,614,580,
+548,515,480,443,406,370,338,311,287,265,243,219,189,152,113,76,43,10,-24,-62,-101,
+-138,-173,-206,-241,-282,-326,-370,-411,-454,-501,-548,-592,-634,-680,-728,-777,-823,-861,-895,-930,-970,
+-1015,-1056,-1096,-1138,-1185,-1231,-1272,-1311,-1353,-1396,-1435,-1474,-1513,-1554,-1593,-1627,-1658,-1687,-1716,-1748,-1783,
+-1816,-1846,-1872,-1899,-1930,-1967,-2007,-2049,-2086,-2120,-2154,-2190,-2223,-2253,-2284,-2317,-2352,-2383,-2412,-2441,-2471,
+-2500,-2529,-2557,-2586,-2617,-2651,-2686,-2717,-2741,-2764,-2790,-2817,-2844,-2869,-2897,-2925,-2952,-2976,-2999,-3022,-3044,
+-3064,-3078,-3086,-3092,-3101,-3114,-3127,-3137,-3146,-3152,-3156,-3160,-3166,-3174,-3180,-3183,-3184,-3185,-3183,-3178,-3173,
+-3167,-3157,-3145,-3135,-3129,-3121,-3107,-3091,-3076,-3059,-3037,-3014,-2995,-2979,-2962,-2942,-2921,-2898,-2870,-2842,-2817,
+-2792,-2761,-2723,-2684,-2647,-2613,-2580,-2549,-2517,-2483,-2451,-2422,-2394,-2364,-2333,-2304,-2276,-2245,-2212,-2179,-2145,
+-2109,-2075,-2042,-2004,-1958,-1911,-1871,-1835,-1797,-1759,-1726,-1694,-1658,-1621,-1585,-1549,-1509,-1469,-1435,-1403,-1366,
+-1325,-1290,-1260,-1228,-1194,-1162,-1134,-1104,-1070,-1039,-1012,-986,-961,-937,-909,-875,-842,-818,-797,-769,-737,
+-710,-686,-657,-623,-592,-565,-537,-508,-484,-464,-440,-411,-387,-365,-338,-307,-282,-259,-227,-187,-151,
+-122,-88,-45,-6,29,69,113,152,186,231,288,342,385,424,468,509,548,596,647,683,702,
+720,746,769,793,831,881,924,954,986,1028,1081,1161,1268,1347,1339,1279,1265,1316,1353,1340,1348,
+1411,1454,1422,1393,1429,1442,1348,1271,1397,1671,1847,1863,1938,2215,2524,2630,2550,2443,2313,2042,1668,
+1422,1450,1658,1869,2016,2100,2070,1844,1417,888,391,27,-170,-237,-254,-280,-319,-353,-386,-434,-503,
+-586,-677,-766,-838,-874,-872,-851,-827,-791,-711,-592,-501,-507,-579,-611,-570,-563,-700,-931,-1106,-1171,
+-1231,-1383,-1586,-1717,-1720,-1641,-1550,-1477,-1427,-1405,-1429,-1510,-1630,-1747,-1840,-1946,-2100,-2279,-2415,-2489,-2541,
+-2601,-2648,-2665,-2680,-2721,-2763,-2775,-2789,-2863,-2998,-3136,-3230,-3281,-3299,-3287,-3252,-3218,-3201,-3197,-3197,-3206,
+-3233,-3274,-3316,-3345,-3350,-3330,-3305,-3295,-3312,-3361,-3450,-3575,-3700,-3785,-3818,-3817,-3801,-3776,-3752,-3739,-3735,
+-3726,-3706,-3683,-3659,-3624,-3576,-3527,-3486,-3449,-3411,-3375,-3338,-3288,-3219,-3141,-3068,-3000,-2935,-2871,-2811,-2754,
+-2693,-2628,-2558,-2483,-2406,-2335,-2271,-2209,-2145,-2080,-2014,-1945,-1873,-1803,-1739,-1678,-1613,-1541,-1462,-1381,-1299,
+-1219,-1141,-1062,-982,-903,-827,-754,-682,-609,-535,-459,-381,-303,-223,-140,-58,17,86,148,204,255,
+300,339,374,408,446,489,528,562,597,637,676,705,734,770,811,844,869,896,922,939,950,
+970,1000,1027,1040,1051,1075,1113,1153,1190,1227,1259,1286,1313,1348,1390,1430,1466,1500,1530,1554,1574,
+1598,1626,1656,1689,1728,1768,1800,1821,1829,1822,1799,1772,1756,1757,1768,1782,1796,1808,1819,1833,1855,
+1881,1904,1923,1946,1977,2010,2041,2068,2090,2105,2114,2125,2143,2166,2190,2217,2250,2287,2327,2371,2421,
+2480,2556,2652,2757,2851,2928,2997,3058,3091,3085,3059,3047,3057,3066,3051,3014,2972,2932,2897,2874,2869,
+2873,2866,2841,2801,2759,2721,2694,2677,2669,2667,2674,2689,2704,2701,2680,2661,2666,2692,2712,2705,2671,
+2627,2586,2554,2528,2502,2360,2317,2274,2225,2158,2065,1957,1855,1770,1702,1644,1601,1585,1599,1637,1692,
+1762,1845,1931,1997,2012,1971,1901,1844,1817,1810,1819,1854,1916,1973,1999,2015,2069,2163,2243,2253,2198,
+2138,2122,2160,2215,2234,2181,2064,1930,1821,1745,1690,1640,1591,1535,1471,1403,1340,1283,1231,1187,1150,
+1101,1024,933,862,823,787,722,638,567,521,477,402,291,157,20,-108,-225,-329,-419,-496,-560,
+-613,-654,-682,-691,-683,-669,-664,-670,-677,-678,-681,-700,-740,-780,-798,-792,-779,-777,-787,-810,-855,
+-935,-1037,-1123,-1172,-1195,-1213,-1226,-1218,-1187,-1153,-1131,-1105,-1056,-1003,-987,-1024,-1086,-1134,-1152,-1144,-1118,
+-1089,-1077,-1097,-1141,-1192,-1237,-1272,-1296,-1311,-1324,-1339,-1355,-1368,-1378,-1385,-1382,-1368,-1348,-1331,-1319,-1317,
+-1336,-1378,-1411,-1402,-1360,-1335,-1358,-1399,-1409,-1376,-1341,-1350,-1415,-1511,-1602,-1675,-1744,-1829,-1926,-2016,-2104,
+-2222,-2382,-2548,-2667,-2730,-2771,-2823,-2878,-2914,-2931,-2950,-2992,-3065,-3167,-3273,-3355,-3393,-3401,-3405,-3427,-3473,
+-3538,-3613,-3683,-3743,-3798,-3863,-3936,-3997,-4038,-4080,-4161,-4291,-4440,-4578,-4702,-4830,-4961,-5071,-5140,-5187,-5245,
+-5316,-5369,-5381,-5369,-5371,-5406,-5465,-5517,-5536,-5506,-5439,-5371,-5337,-5342,-5360,-5368,-5370,-5386,-5423,-5467,-5502,
+-5533,-5570,-5609,-5634,-5644,-5655,-5688,-5742,-5803,-5858,-5909,-5959,-6009,-6056,-6105,-6157,-6211,-6264,-6318,-6382,-6458,
+-6538,-6619,-6707,-6806,-6912,-7014,-7112,-7213,-7316,-7414,-7504,-7592,-7682,-7770,-7852,-7932,-8019,-8112,-8201,-8287,-8375,
+-8469,-8563,-8648,-8727,-8804,-8881,-8957,-9032,-9106,-9176,-9239,-9300,-9367,-9437,-9500,-9551,-9596,-9636,-9672,-9705,-9739,
+-9759,-9742,-9686,-9640,-9666,-9774,-9905,-9991,-10021,-10033,-10061,-10099,-10132,-10159,-10188,-10217,-10236,-10250,-10268,-10287,-10297,
+-10314,-10375,-10490,-10610,-10671,-10654,-10599,-10554,-10527,-10496,-10444,-10379,-10313,-10254,-10208,-10186,-10191,-10203,-10189,-10134,-10059,
+-9985,-9910,-9822,-9721,-9623,-9532,-9426,-9295,-9159,-9042,-8946,-8848,-8732,-8594,-8437,-8272,-8115,-7975,-7834,-7672,-7497,
+-7334,-7185,-7028,-6855,-6680,-6508,-6328,-6144,-5986,-5866,-5756,-5636,-5527,-5458,-5421,-5395,-5396,-5440,-5459,-5358,-5157,
+-5007,-5022,-5130,-5156,-5014,-4743,-4407,-4034,-3669,-3403,-3287,-3267,-3243,-3165,-3043,-2891,-2710,-2522,-2364,-2244,-2137,
+-2018,-1892,-1776,-1673,-1575,-1476,-1372,-1262,-1148,-1034,-911,-774,-644,-559,-523,-500,-448,-373,-304,-257,-218,
+-179,-141,-99,-38,49,155,268,392,527,659,774,868,957,1057,1176,1311,1441,1547,1628,1698,1769,
+1841,1912,1998,2104,2219,2319,2399,2475,2559,2655,2767,2896,3031,3138,3193,3211,3238,3313,3442,3609,3793,
+3975,4128,4224,4267,4308,4418,4613,4839,5028,5167,5285,5394,5459,5462,5451,5500,5619,5743,5811,5840,5889,
+5981,6098,6226,6357,6457,6472,6395,6299,6272,6322,6388,6432,6468,6517,6571,6612,6632,6611,6518,6372,6269,
+6294,6413,6504,6499,6425,6296,6046,5622,5115,4724,4607,4787,5188,5692,6166,6500,6676,6763,6836,6896,6910,
+6880,6850,6843,6844,6831,6806,6788,6794,6835,6902,6962,6979,6951,6909,6879,6855,6818,6766,6713,6675,6668,
+6693,6732,6756,6749,6726,6709,6702,6691,6669,6639,6607,6575,6548,6531,6523,6515,6506,6496,6487,6479,6474,
+6473,6469,6456,6442,6444,6464,6488,6496,6489,6467,6433,6391,6351,6323,6299,6274,6254,6246,6245,6234,6209,
+6184,6165,6146,6119,6090,6065,6047,6038,6033,6022,5991,5945,5904,5877,5837,5756,5644,5539,5468,5426,5395,
+5369,5346,5327,5313,5304,5292,5270,5259,5300,5396,5485,5484,5377,5226,5112,5066,5064,5071,5071,5060,5039,
+5019,5015,5033,5054,5045,4993,4926,4885,4871,4843,4764,4650,4546,4469,4401,4325,4256,4219,4207,4190,4145,
+4073,3998,3951,3950,3974,3975,3913,3797,3680,3599,3551,3505,3444,3376,3319,3284,3261,3230,3176,3102,3028,
+2973,2950,2964,3005,3038,3020,2937,2831,2769,2788,2854,2890,2848,2758,2689,2661,2627,2545,2454,2433,2501,
+2582,2592,2522,2431,2371,2346,2339,2326,2297,2260,2230,2205,2159,2088,2037,2049,2090,2071,1962,1841,1801,
+1841,1883,1875,1833,1790,1750,1703,1660,1634,1614,1590,1572,1578,1602,1616,1609,1597,1595,1598,1596,1594,
+1597,1596,1580,1557,1540,1532,1518,1491,1456,1418,1374,1324,1286,1280,1305,1331,1325,1283,1233,1209,1218,
+1241,1256,1257,1249,1237,1222,1206,1193,1188,1189,1197,1205,1210,1216,1232,1259,1289,1309,1316,1317,1314,
+1312,1320,1343,1379,1413,1437,1449,1451,1450,1456,1475,1504,1529,1540,1540,1529,1515,1515,1549,1606,1649,
+1656,1650,1656,1662,1633,1572,1528,1539,1588,1632,1648,1643,1630,1607,1575,1542,1516,1498,1484,1474,1469,
+1464,1450,1425,1396,1372,1354,1338,1316,1290,1263,1238,1216,1194,1169,1140,1109,1079,1052,1025,994,958,
+920,883,849,819,792,770,753,739,724,703,673,639,608,580,552,520,485,449,413,379,349,
+322,296,272,249,224,191,150,110,73,38,2,-34,-72,-111,-147,-182,-217,-257,-300,-340,-376,
+-411,-452,-497,-540,-581,-624,-671,-720,-769,-810,-846,-881,-921,-966,-1011,-1053,-1097,-1144,-1190,-1234,-1275,
+-1317,-1358,-1396,-1433,-1472,-1512,-1551,-1587,-1619,-1648,-1679,-1712,-1746,-1781,-1813,-1842,-1869,-1898,-1931,-1971,-2011,
+-2046,-2078,-2112,-2148,-2182,-2213,-2243,-2276,-2308,-2336,-2363,-2393,-2426,-2458,-2488,-2517,-2547,-2579,-2612,-2647,-2677,
+-2702,-2725,-2752,-2782,-2810,-2836,-2861,-2887,-2913,-2937,-2960,-2982,-3003,-3023,-3039,-3047,-3050,-3055,-3064,-3078,-3092,
+-3103,-3111,-3117,-3122,-3130,-3140,-3147,-3150,-3151,-3152,-3151,-3146,-3142,-3138,-3130,-3120,-3112,-3106,-3096,-3078,-3057,
+-3041,-3025,-3004,-2982,-2963,-2947,-2929,-2909,-2887,-2865,-2841,-2816,-2793,-2768,-2738,-2705,-2670,-2636,-2600,-2566,-2535,
+-2504,-2470,-2437,-2408,-2380,-2349,-2315,-2285,-2258,-2229,-2195,-2162,-2129,-2096,-2063,-2030,-1994,-1953,-1910,-1870,-1833,
+-1797,-1761,-1730,-1698,-1662,-1625,-1590,-1555,-1515,-1474,-1440,-1409,-1374,-1335,-1301,-1269,-1236,-1202,-1171,-1144,-1115,
+-1083,-1053,-1025,-997,-969,-946,-921,-889,-856,-831,-809,-780,-746,-719,-698,-674,-641,-609,-580,-552,-524,
+-501,-480,-455,-430,-413,-395,-366,-328,-298,-276,-247,-208,-170,-138,-103,-60,-20,13,50,92,131,
+167,212,268,323,371,417,464,505,542,586,631,658,669,681,704,730,760,801,853,898,933,
+970,1011,1055,1119,1207,1266,1248,1201,1213,1281,1313,1290,1299,1381,1443,1422,1398,1442,1462,1371,1291,
+1399,1636,1773,1784,1894,2204,2511,2600,2541,2493,2403,2123,1737,1536,1648,1899,2065,2107,2072,1924,1589,
+1107,622,255,27,-95,-157,-196,-231,-258,-274,-300,-358,-446,-543,-632,-708,-769,-800,-795,-763,-722,
+-681,-632,-573,-537,-562,-625,-653,-627,-627,-735,-910,-1038,-1087,-1158,-1334,-1565,-1714,-1712,-1605,-1480,-1383,
+-1313,-1270,-1278,-1356,-1478,-1592,-1683,-1803,-1988,-2196,-2346,-2420,-2471,-2534,-2584,-2604,-2625,-2673,-2721,-2739,-2759,
+-2840,-2987,-3149,-3275,-3352,-3379,-3358,-3310,-3271,-3253,-3243,-3233,-3229,-3249,-3295,-3355,-3406,-3424,-3402,-3358,-3317,
+-3298,-3312,-3374,-3486,-3619,-3728,-3786,-3794,-3763,-3714,-3674,-3662,-3666,-3662,-3645,-3627,-3608,-3574,-3525,-3478,-3443,
+-3410,-3370,-3329,-3293,-3249,-3187,-3115,-3043,-2973,-2904,-2838,-2783,-2732,-2676,-2610,-2541,-2471,-2400,-2329,-2261,-2198,
+-2136,-2074,-2006,-1934,-1861,-1791,-1725,-1661,-1595,-1526,-1450,-1369,-1288,-1213,-1138,-1059,-975,-896,-823,-754,-682,
+-608,-532,-452,-374,-300,-227,-150,-67,13,88,153,211,262,307,345,379,412,453,500,544,580,
+614,653,689,716,743,780,821,850,867,886,907,922,932,954,990,1021,1036,1045,1070,1109,1149,
+1183,1216,1250,1281,1314,1353,1393,1428,1455,1482,1510,1537,1566,1598,1633,1666,1699,1734,1766,1787,1794,
+1795,1789,1775,1757,1746,1747,1755,1765,1778,1791,1804,1817,1836,1860,1883,1902,1924,1952,1984,2014,2041,
+2063,2075,2079,2082,2092,2111,2133,2161,2196,2238,2282,2321,2353,2382,2427,2503,2610,2728,2840,2940,3019,
+3061,3058,3036,3031,3048,3060,3038,2989,2941,2906,2880,2857,2842,2836,2830,2814,2784,2744,2698,2652,2613,
+2591,2588,2601,2621,2635,2633,2618,2610,2625,2652,2662,2636,2581,2522,2474,2436,2400,2360,2194,2141,2103,
+2074,2035,1975,1898,1819,1744,1677,1625,1599,1604,1633,1675,1726,1793,1878,1971,2042,2062,2026,1960,1897,
+1852,1824,1814,1835,1882,1930,1960,1992,2054,2142,2210,2224,2189,2140,2114,2121,2147,2151,2102,2003,1891,
+1795,1719,1652,1594,1546,1502,1453,1401,1352,1300,1243,1189,1143,1090,1009,909,824,767,719,653,580,
+528,499,461,379,252,103,-43,-178,-297,-396,-476,-545,-609,-664,-700,-714,-716,-716,-719,-724,-726,
+-721,-711,-706,-724,-769,-818,-844,-840,-824,-819,-832,-859,-901,-964,-1037,-1100,-1140,-1166,-1189,-1206,-1206,
+-1187,-1165,-1147,-1118,-1070,-1022,-1009,-1041,-1091,-1127,-1143,-1145,-1133,-1113,-1102,-1120,-1165,-1215,-1256,-1285,-1304,
+-1310,-1309,-1311,-1321,-1332,-1341,-1350,-1359,-1362,-1356,-1346,-1341,-1350,-1375,-1413,-1445,-1450,-1423,-1392,-1390,-1416,
+-1439,-1430,-1402,-1401,-1461,-1567,-1672,-1750,-1821,-1910,-2009,-2089,-2152,-2244,-2390,-2563,-2707,-2798,-2854,-2895,-2926,
+-2943,-2952,-2967,-3001,-3068,-3168,-3275,-3355,-3392,-3404,-3419,-3453,-3508,-3581,-3663,-3738,-3797,-3847,-3904,-3968,-4024,
+-4069,-4131,-4239,-4397,-4564,-4692,-4771,-4837,-4924,-5030,-5127,-5200,-5263,-5323,-5369,-5384,-5380,-5391,-5432,-5482,-5505,
+-5484,-5433,-5383,-5357,-5354,-5360,-5363,-5364,-5374,-5402,-5446,-5491,-5530,-5564,-5599,-5631,-5650,-5655,-5665,-5699,-5759,
+-5825,-5883,-5935,-5987,-6039,-6087,-6136,-6192,-6252,-6309,-6359,-6412,-6476,-6550,-6629,-6714,-6806,-6904,-7006,-7111,-7214,
+-7312,-7401,-7486,-7575,-7668,-7759,-7843,-7924,-8009,-8097,-8183,-8268,-8358,-8453,-8546,-8629,-8706,-8782,-8861,-8940,-9017,
+-9090,-9157,-9222,-9293,-9371,-9444,-9502,-9549,-9593,-9637,-9675,-9709,-9742,-9763,-9747,-9692,-9645,-9666,-9765,-9894,-9987,
+-10027,-10041,-10062,-10095,-10132,-10165,-10197,-10226,-10250,-10273,-10297,-10316,-10323,-10334,-10383,-10485,-10601,-10671,-10668,-10627,-10595,
+-10587,-10582,-10559,-10519,-10471,-10418,-10364,-10318,-10289,-10264,-10222,-10157,-10082,-10007,-9922,-9818,-9703,-9598,-9502,-9393,-9263,
+-9134,-9028,-8939,-8842,-8721,-8577,-8419,-8261,-8116,-7983,-7843,-7680,-7504,-7339,-7185,-7022,-6845,-6668,-6499,-6327,-6155,
+-6006,-5884,-5760,-5621,-5497,-5418,-5368,-5326,-5315,-5356,-5382,-5286,-5071,-4889,-4872,-4980,-5060,-5010,-4822,-4512,-4091,
+-3638,-3294,-3140,-3114,-3094,-3020,-2905,-2763,-2594,-2414,-2268,-2173,-2096,-1998,-1873,-1741,-1619,-1512,-1415,-1318,-1212,
+-1098,-980,-852,-706,-561,-459,-412,-387,-343,-275,-209,-161,-122,-82,-43,-1,55,135,229,332,446,
+575,708,829,931,1021,1118,1234,1368,1499,1605,1684,1755,1829,1900,1966,2040,2136,2250,2358,2449,2534,
+2628,2733,2846,2967,3088,3188,3252,3293,3342,3429,3558,3715,3880,4036,4167,4262,4327,4396,4514,4691,4892,
+5063,5186,5289,5394,5485,5539,5568,5617,5704,5793,5850,5890,5954,6051,6151,6232,6293,6330,6321,6264,6208,
+6216,6292,6388,6456,6495,6529,6572,6625,6675,6685,6606,6436,6262,6200,6294,6466,6581,6551,6366,6059,5685,
+5304,4995,4835,4880,5141,5558,6014,6388,6630,6766,6850,6906,6933,6932,6920,6913,6905,6886,6858,6838,6847,
+6897,6968,7021,7027,6992,6947,6914,6891,6860,6820,6779,6753,6748,6758,6771,6773,6765,6756,6749,6734,6706,
+6673,6647,6629,6609,6589,6579,6579,6577,6564,6542,6522,6510,6504,6500,6494,6484,6477,6482,6500,6518,6525,
+6519,6501,6470,6432,6396,6364,6331,6299,6278,6272,6262,6234,6198,6175,6170,6166,6153,6128,6097,6068,6056,
+6063,6064,6032,5976,5932,5903,5843,5724,5585,5493,5461,5443,5408,5372,5351,5337,5317,5297,5286,5276,5266,
+5288,5363,5454,5477,5394,5253,5139,5097,5104,5116,5112,5100,5089,5079,5064,5051,5042,5027,4989,4937,4899,
+4881,4851,4774,4663,4567,4509,4459,4386,4303,4247,4231,4221,4180,4103,4023,3988,4013,4064,4076,4007,3876,
+3739,3639,3575,3525,3473,3423,3381,3349,3322,3286,3228,3151,3067,3002,2975,2988,3017,3027,2995,2932,2863,
+2812,2793,2799,2807,2793,2757,2729,2718,2692,2616,2512,2448,2460,2511,2535,2501,2427,2350,2304,2300,2314,
+2307,2272,2245,2235,2197,2103,2014,2018,2096,2121,2018,1865,1793,1824,1869,1860,1819,1783,1751,1706,1660,
+1635,1623,1605,1589,1595,1615,1622,1609,1597,1596,1596,1586,1578,1585,1594,1589,1575,1565,1560,1547,1520,
+1487,1452,1412,1362,1318,1301,1316,1346,1356,1328,1280,1246,1244,1264,1283,1287,1280,1267,1251,1235,1220,
+1209,1204,1207,1214,1222,1227,1239,1261,1289,1309,1315,1315,1312,1310,1315,1337,1373,1413,1441,1453,1453,
+1449,1451,1465,1492,1526,1559,1583,1583,1560,1542,1556,1599,1629,1626,1614,1625,1649,1645,1603,1563,1564,
+1598,1632,1647,1651,1649,1634,1605,1573,1549,1534,1522,1512,1507,1504,1493,1469,1439,1413,1397,1383,1363,
+1334,1301,1269,1244,1223,1199,1169,1135,1103,1076,1050,1020,987,952,920,890,862,837,816,798,781,
+760,732,698,664,633,606,579,550,519,487,453,419,388,358,330,303,280,256,223,180,135,
+94,58,24,-10,-46,-82,-118,-153,-189,-228,-270,-309,-341,-371,-405,-444,-485,-524,-564,-607,-655,
+-705,-752,-795,-835,-877,-923,-970,-1016,-1061,-1107,-1153,-1199,-1242,-1283,-1322,-1358,-1395,-1433,-1472,-1511,-1547,
+-1581,-1612,-1643,-1675,-1709,-1742,-1776,-1808,-1838,-1866,-1898,-1935,-1974,-2007,-2037,-2070,-2107,-2142,-2172,-2202,-2235,
+-2267,-2294,-2319,-2350,-2383,-2415,-2446,-2477,-2510,-2542,-2574,-2607,-2637,-2663,-2687,-2715,-2745,-2775,-2800,-2823,-2846,
+-2869,-2894,-2918,-2940,-2960,-2978,-2995,-3005,-3008,-3011,-3020,-3036,-3053,-3065,-3073,-3078,-3083,-3093,-3104,-3111,-3114,
+-3116,-3119,-3119,-3116,-3112,-3108,-3102,-3092,-3083,-3076,-3065,-3045,-3024,-3008,-2994,-2975,-2952,-2932,-2914,-2895,-2872,
+-2850,-2829,-2808,-2786,-2763,-2737,-2706,-2675,-2645,-2613,-2578,-2543,-2514,-2485,-2453,-2422,-2395,-2369,-2336,-2300,-2270,
+-2245,-2216,-2181,-2147,-2116,-2085,-2051,-2018,-1985,-1949,-1910,-1871,-1833,-1797,-1762,-1731,-1701,-1667,-1630,-1595,-1559,
+-1520,-1480,-1445,-1413,-1379,-1344,-1310,-1278,-1244,-1210,-1182,-1156,-1127,-1097,-1069,-1041,-1010,-980,-955,-932,-904,
+-874,-849,-825,-793,-756,-726,-706,-685,-657,-627,-599,-573,-546,-522,-499,-472,-446,-429,-414,-389,-354,
+-322,-295,-263,-222,-185,-154,-118,-74,-33,0,34,74,111,148,193,248,303,352,403,457,503,
+542,578,609,622,626,640,672,708,742,784,833,877,913,951,990,1021,1058,1112,1151,1145,1136,
+1188,1279,1317,1289,1294,1374,1441,1435,1423,1459,1458,1350,1261,1350,1550,1667,1712,1893,2248,2541,2608,
+2574,2588,2533,2236,1831,1657,1818,2067,2148,2052,1882,1637,1265,825,451,214,77,-13,-78,-121,-152,
+-172,-188,-222,-295,-395,-490,-564,-626,-684,-725,-725,-674,-598,-543,-537,-569,-619,-677,-733,-763,-758,
+-757,-804,-887,-953,-995,-1081,-1262,-1483,-1632,-1644,-1556,-1446,-1362,-1302,-1262,-1262,-1323,-1425,-1522,-1610,-1739,
+-1932,-2135,-2273,-2344,-2409,-2490,-2549,-2566,-2578,-2619,-2670,-2701,-2735,-2819,-2963,-3128,-3275,-3380,-3424,-3409,-3366,
+-3333,-3318,-3303,-3278,-3261,-3270,-3310,-3369,-3427,-3456,-3446,-3410,-3370,-3341,-3329,-3350,-3419,-3526,-3641,-3727,-3757,
+-3723,-3653,-3593,-3573,-3579,-3579,-3564,-3549,-3533,-3503,-3461,-3425,-3400,-3370,-3327,-3282,-3245,-3206,-3154,-3092,-3026,
+-2954,-2876,-2806,-2754,-2711,-2660,-2593,-2521,-2454,-2388,-2320,-2251,-2186,-2124,-2062,-1995,-1922,-1849,-1779,-1710,-1643,
+-1580,-1518,-1448,-1367,-1284,-1210,-1139,-1062,-979,-899,-827,-757,-685,-612,-536,-458,-380,-309,-243,-173,-93,
+-7,75,151,218,272,316,350,379,411,453,505,553,589,618,650,682,708,735,772,812,839,
+853,869,891,908,918,937,971,1004,1024,1041,1070,1109,1145,1177,1212,1249,1281,1310,1342,1378,1411,
+1438,1463,1489,1514,1542,1576,1615,1654,1692,1730,1757,1763,1753,1740,1736,1735,1732,1730,1730,1733,1741,
+1755,1772,1788,1801,1820,1845,1870,1891,1913,1938,1964,1988,2011,2031,2044,2048,2048,2056,2076,2104,2137,
+2175,2216,2257,2290,2311,2323,2343,2393,2480,2592,2711,2828,2931,3001,3028,3026,3027,3039,3039,3006,2952,
+2910,2892,2879,2854,2821,2796,2780,2764,2737,2697,2644,2583,2529,2500,2503,2527,2553,2571,2574,2569,2564,
+2566,2566,2547,2499,2437,2383,2343,2305,2254,2194,2045,1994,1975,1969,1954,1917,1862,1799,1732,1669,1623,
+1605,1618,1650,1691,1743,1813,1900,1991,2060,2089,2072,2024,1965,1909,1867,1846,1852,1878,1911,1945,1982,
+2025,2065,2095,2119,2132,2120,2078,2033,2014,2013,1991,1925,1833,1748,1680,1625,1576,1533,1491,1448,1409,
+1374,1330,1270,1204,1146,1085,1003,902,804,728,663,593,528,485,463,430,348,213,49,-112,-253,
+-365,-450,-519,-586,-659,-721,-752,-754,-750,-757,-772,-777,-764,-743,-728,-732,-761,-816,-873,-907,-909,
+-894,-887,-896,-919,-950,-988,-1027,-1061,-1088,-1112,-1135,-1154,-1162,-1162,-1160,-1155,-1133,-1088,-1043,-1028,-1048,
+-1081,-1104,-1119,-1134,-1146,-1147,-1151,-1179,-1228,-1275,-1302,-1312,-1312,-1300,-1279,-1260,-1252,-1249,-1250,-1259,-1283,
+-1309,-1322,-1325,-1337,-1367,-1411,-1458,-1498,-1518,-1506,-1467,-1439,-1449,-1483,-1495,-1468,-1446,-1489,-1601,-1729,-1824,
+-1900,-1989,-2088,-2164,-2214,-2282,-2405,-2568,-2725,-2842,-2916,-2957,-2976,-2982,-2985,-2989,-3003,-3047,-3132,-3234,-3316,
+-3363,-3394,-3431,-3482,-3547,-3625,-3708,-3782,-3836,-3878,-3923,-3975,-4030,-4093,-4180,-4310,-4476,-4640,-4754,-4801,-4819,
+-4865,-4961,-5082,-5189,-5266,-5320,-5359,-5383,-5400,-5423,-5451,-5463,-5440,-5389,-5342,-5326,-5339,-5356,-5359,-5357,-5364,
+-5387,-5418,-5449,-5483,-5521,-5562,-5600,-5628,-5646,-5660,-5682,-5726,-5787,-5849,-5904,-5955,-6009,-6064,-6115,-6165,-6222,
+-6285,-6344,-6393,-6440,-6497,-6566,-6643,-6723,-6807,-6897,-6996,-7102,-7206,-7302,-7388,-7472,-7562,-7657,-7750,-7835,-7915,
+-7997,-8080,-8165,-8252,-8345,-8440,-8530,-8610,-8684,-8759,-8837,-8914,-8990,-9063,-9136,-9214,-9300,-9388,-9462,-9515,-9557,
+-9601,-9645,-9681,-9711,-9741,-9759,-9743,-9692,-9649,-9668,-9762,-9887,-9985,-10033,-10047,-10062,-10093,-10135,-10176,-10210,-10240,
+-10271,-10301,-10328,-10342,-10342,-10346,-10382,-10468,-10579,-10662,-10684,-10659,-10627,-10613,-10610,-10599,-10575,-10543,-10503,-10455,-10406,
+-10360,-10314,-10256,-10184,-10105,-10020,-9923,-9807,-9685,-9572,-9469,-9360,-9237,-9115,-9009,-8916,-8815,-8693,-8552,-8402,-8257,
+-8122,-7993,-7851,-7686,-7510,-7342,-7182,-7016,-6842,-6671,-6508,-6345,-6184,-6038,-5903,-5754,-5589,-5447,-5356,-5299,-5252,
+-5240,-5284,-5321,-5239,-5024,-4812,-4744,-4822,-4927,-4953,-4852,-4594,-4177,-3686,-3277,-3042,-2940,-2865,-2771,-2671,-2569,
+-2443,-2297,-2172,-2094,-2042,-1971,-1860,-1723,-1583,-1459,-1355,-1260,-1158,-1045,-927,-798,-653,-504,-386,-317,-275,
+-230,-175,-123,-80,-38,7,49,92,149,225,313,405,508,630,762,886,993,1087,1186,1301,1433,
+1563,1668,1747,1817,1891,1963,2026,2093,2179,2285,2391,2487,2579,2679,2787,2897,3006,3110,3206,3289,3363,
+3438,3527,3641,3777,3923,4061,4184,4298,4413,4530,4656,4794,4940,5076,5196,5314,5442,5564,5649,5688,5710,
+5745,5796,5851,5915,5997,6086,6152,6182,6187,6188,6188,6187,6198,6236,6305,6382,6447,6495,6539,6590,6648,
+6704,6734,6705,6592,6428,6318,6369,6566,6751,6744,6507,6154,5823,5559,5346,5196,5162,5287,5552,5899,6259,
+6561,6760,6860,6911,6953,6989,7000,6988,6969,6947,6919,6898,6913,6973,7048,7093,7090,7054,7010,6971,6935,
+6898,6865,6843,6834,6829,6819,6802,6788,6784,6785,6774,6744,6705,6678,6668,6663,6651,6636,6628,6630,6629,
+6615,6593,6570,6551,6536,6526,6521,6520,6522,6530,6542,6552,6553,6542,6518,6486,6454,6426,6398,6365,6334,
+6321,6318,6301,6259,6213,6191,6191,6192,6180,6158,6127,6095,6081,6089,6093,6058,5996,5947,5909,5830,5692,
+5555,5492,5488,5470,5412,5359,5345,5345,5329,5306,5296,5287,5261,5245,5281,5357,5403,5364,5267,5183,5155,
+5167,5175,5159,5134,5118,5111,5101,5084,5065,5043,5005,4952,4906,4878,4841,4763,4659,4579,4546,4525,4474,
+4399,4337,4304,4273,4209,4113,4028,4000,4037,4090,4096,4022,3894,3765,3670,3605,3553,3506,3465,3432,3405,
+3375,3334,3276,3203,3124,3060,3029,3031,3036,3016,2971,2931,2910,2891,2856,2813,2786,2777,2769,2757,2745,
+2722,2663,2572,2492,2462,2484,2522,2534,2494,2411,2331,2300,2313,2317,2290,2265,2258,2219,2114,2014,2024,
+2127,2173,2064,1888,1794,1815,1855,1845,1806,1779,1756,1716,1672,1651,1643,1627,1610,1613,1629,1630,1612,
+1599,1599,1597,1583,1573,1578,1589,1593,1590,1590,1590,1580,1556,1526,1492,1453,1405,1358,1326,1318,1330,
+1341,1331,1303,1277,1273,1289,1306,1312,1307,1294,1278,1261,1247,1234,1223,1219,1226,1237,1245,1253,1269,
+1292,1311,1318,1317,1314,1311,1313,1330,1365,1407,1437,1450,1449,1446,1449,1462,1488,1526,1569,1605,1614,
+1592,1563,1557,1575,1588,1579,1573,1601,1653,1687,1678,1650,1633,1636,1644,1652,1662,1671,1667,1646,1617,
+1590,1570,1553,1540,1533,1528,1517,1498,1473,1452,1435,1420,1400,1370,1334,1300,1270,1246,1220,1190,1158,
+1128,1102,1077,1047,1015,985,959,934,910,886,863,842,820,794,762,726,691,659,630,602,575,
+548,521,488,453,419,389,361,335,311,286,250,205,158,116,81,48,15,-16,-48,-80,-113,
+-147,-184,-224,-262,-294,-323,-355,-392,-431,-471,-510,-551,-596,-645,-696,-744,-790,-835,-882,-930,-977,
+-1024,-1071,-1118,-1165,-1208,-1247,-1284,-1321,-1359,-1397,-1435,-1472,-1508,-1543,-1575,-1605,-1635,-1667,-1700,-1734,-1768,
+-1801,-1832,-1863,-1899,-1934,-1965,-1993,-2026,-2063,-2098,-2129,-2160,-2195,-2228,-2255,-2280,-2309,-2341,-2373,-2404,-2438,
+-2473,-2505,-2534,-2563,-2591,-2619,-2646,-2675,-2706,-2734,-2759,-2780,-2800,-2823,-2848,-2875,-2897,-2914,-2931,-2948,-2961,
+-2967,-2973,-2985,-3004,-3023,-3035,-3041,-3043,-3048,-3058,-3070,-3076,-3078,-3079,-3083,-3085,-3082,-3077,-3071,-3064,-3054,
+-3044,-3036,-3025,-3008,-2990,-2977,-2965,-2947,-2924,-2902,-2882,-2860,-2836,-2815,-2795,-2774,-2752,-2729,-2701,-2671,-2641,
+-2615,-2586,-2553,-2520,-2492,-2464,-2434,-2404,-2380,-2356,-2324,-2288,-2259,-2235,-2206,-2170,-2135,-2105,-2075,-2041,-2007,
+-1975,-1942,-1906,-1868,-1830,-1794,-1758,-1727,-1699,-1668,-1632,-1597,-1562,-1526,-1488,-1453,-1420,-1386,-1351,-1319,-1287,
+-1254,-1222,-1194,-1167,-1137,-1107,-1079,-1053,-1024,-994,-969,-947,-919,-888,-862,-838,-807,-770,-739,-717,-695,
+-669,-642,-619,-594,-568,-544,-522,-496,-467,-443,-422,-399,-370,-340,-309,-269,-227,-195,-170,-137,-93,
+-49,-13,23,61,95,128,171,227,282,333,387,446,496,532,559,576,580,584,606,648,688,
+721,761,810,856,894,935,975,998,1012,1040,1076,1101,1134,1214,1315,1360,1339,1335,1390,1441,1441,
+1438,1459,1424,1294,1197,1264,1428,1539,1646,1923,2339,2641,2707,2696,2729,2651,2306,1887,1751,1951,2172,
+2146,1908,1619,1321,983,651,409,266,162,68,4,-25,-44,-70,-105,-156,-235,-331,-417,-479,-535,
+-596,-646,-649,-586,-485,-422,-454,-568,-695,-785,-840,-878,-898,-893,-873,-859,-863,-901,-995,-1152,-1333,
+-1470,-1517,-1486,-1427,-1376,-1338,-1312,-1309,-1346,-1412,-1482,-1565,-1701,-1891,-2075,-2196,-2273,-2364,-2472,-2542,-2551,
+-2544,-2568,-2618,-2670,-2733,-2831,-2965,-3115,-3258,-3372,-3431,-3432,-3408,-3395,-3390,-3369,-3332,-3303,-3303,-3329,-3371,
+-3413,-3440,-3440,-3426,-3411,-3398,-3381,-3369,-3384,-3441,-3533,-3626,-3674,-3649,-3572,-3500,-3472,-3475,-3474,-3461,-3449,
+-3437,-3416,-3390,-3371,-3358,-3331,-3288,-3241,-3202,-3164,-3117,-3067,-3012,-2941,-2855,-2777,-2725,-2690,-2646,-2581,-2506,
+-2437,-2373,-2309,-2242,-2176,-2112,-2049,-1981,-1910,-1839,-1770,-1699,-1630,-1569,-1512,-1447,-1367,-1283,-1208,-1139,-1065,
+-984,-905,-831,-756,-682,-609,-537,-463,-387,-318,-256,-193,-118,-31,59,145,219,278,321,353,377,
+403,443,497,550,587,611,635,662,689,718,756,794,819,832,850,877,900,915,932,961,993,
+1020,1046,1080,1115,1144,1172,1210,1252,1284,1305,1327,1355,1385,1415,1443,1468,1488,1509,1539,1577,1619,
+1663,1704,1731,1729,1705,1684,1680,1690,1702,1708,1710,1712,1721,1738,1756,1770,1780,1795,1817,1841,1864,
+1889,1918,1947,1970,1989,2006,2018,2023,2025,2034,2057,2090,2127,2163,2197,2229,2256,2275,2285,2296,2326,
+2385,2469,2572,2690,2816,2928,3000,3028,3030,3024,3003,2961,2912,2886,2883,2874,2837,2780,2731,2701,2679,
+2652,2613,2561,2497,2438,2411,2423,2456,2486,2506,2517,2518,2505,2479,2444,2397,2339,2285,2247,2220,2180,
+2116,2045,1935,1901,1902,1911,1900,1865,1814,1755,1693,1634,1591,1574,1582,1610,1653,1713,1791,1881,1969,
+2040,2086,2101,2081,2033,1973,1922,1894,1885,1889,1906,1938,1969,1976,1956,1948,1991,2060,2082,2015,1909,
+1848,1853,1869,1838,1762,1683,1631,1600,1573,1539,1497,1457,1426,1397,1354,1289,1215,1147,1082,1002,906,
+806,717,638,562,494,447,422,393,321,186,6,-176,-326,-428,-496,-555,-624,-705,-771,-800,-796,
+-791,-804,-817,-806,-773,-744,-743,-770,-818,-877,-932,-967,-974,-964,-956,-957,-968,-985,-1003,-1018,-1032,
+-1047,-1066,-1086,-1104,-1121,-1142,-1165,-1176,-1160,-1114,-1064,-1041,-1051,-1072,-1086,-1099,-1121,-1149,-1170,-1194,-1235,
+-1289,-1329,-1341,-1332,-1316,-1291,-1253,-1214,-1184,-1160,-1142,-1145,-1180,-1230,-1266,-1283,-1307,-1356,-1423,-1491,-1550,
+-1589,-1588,-1544,-1495,-1486,-1519,-1539,-1511,-1475,-1506,-1622,-1763,-1869,-1945,-2033,-2137,-2225,-2284,-2347,-2451,-2594,
+-2744,-2869,-2955,-3002,-3020,-3025,-3025,-3017,-3010,-3030,-3095,-3187,-3272,-3336,-3391,-3448,-3510,-3577,-3653,-3734,-3807,
+-3860,-3897,-3929,-3969,-4027,-4109,-4220,-4359,-4514,-4661,-4762,-4799,-4799,-4820,-4903,-5034,-5165,-5260,-5317,-5356,-5392,
+-5428,-5452,-5447,-5405,-5342,-5289,-5274,-5299,-5335,-5352,-5348,-5346,-5365,-5399,-5427,-5444,-5465,-5503,-5548,-5587,-5616,
+-5642,-5674,-5715,-5766,-5823,-5878,-5925,-5973,-6028,-6088,-6143,-6195,-6252,-6315,-6375,-6425,-6469,-6520,-6584,-6655,-6730,
+-6806,-6889,-6981,-7080,-7181,-7278,-7368,-7456,-7548,-7644,-7738,-7823,-7901,-7978,-8060,-8147,-8238,-8331,-8422,-8507,-8585,
+-8661,-8738,-8814,-8889,-8963,-9040,-9124,-9217,-9315,-9406,-9476,-9524,-9564,-9607,-9650,-9685,-9716,-9745,-9757,-9732,-9676,
+-9634,-9657,-9751,-9875,-9975,-10027,-10045,-10061,-10097,-10148,-10193,-10226,-10256,-10293,-10332,-10359,-10367,-10362,-10359,-10384,-10453,
+-10556,-10652,-10699,-10688,-10652,-10623,-10610,-10599,-10582,-10556,-10527,-10493,-10453,-10407,-10354,-10290,-10214,-10127,-10031,-9925,-9807,
+-9684,-9568,-9462,-9356,-9240,-9116,-8999,-8894,-8791,-8676,-8544,-8404,-8268,-8138,-8004,-7854,-7684,-7508,-7337,-7173,-7007,
+-6841,-6680,-6525,-6372,-6219,-6071,-5920,-5751,-5569,-5414,-5310,-5244,-5195,-5183,-5227,-5273,-5213,-5014,-4782,-4658,-4683,
+-4782,-4852,-4818,-4628,-4269,-3813,-3387,-3075,-2862,-2693,-2549,-2445,-2372,-2296,-2201,-2111,-2047,-1998,-1935,-1838,-1707,
+-1560,-1419,-1302,-1202,-1103,-997,-885,-763,-625,-482,-359,-268,-199,-139,-87,-48,-11,34,85,129,172,
+230,308,394,481,577,691,815,936,1044,1147,1254,1375,1506,1632,1735,1814,1885,1957,2027,2090,2155,
+2235,2331,2431,2527,2623,2725,2833,2939,3038,3130,3221,3317,3417,3513,3605,3707,3830,3965,4093,4216,4354,
+4517,4680,4812,4911,5000,5104,5230,5373,5522,5646,5718,5733,5724,5728,5766,5834,5917,5999,6061,6091,6093,
+6083,6081,6101,6148,6206,6260,6308,6360,6421,6484,6546,6607,6664,6708,6737,6750,6720,6626,6528,6554,6744,
+6945,6936,6664,6291,6000,5819,5684,5576,5537,5582,5695,5882,6164,6487,6738,6861,6912,6971,7036,7063,7048,
+7027,7012,6990,6971,6991,7060,7136,7170,7159,7126,7088,7045,6996,6948,6913,6896,6892,6886,6863,6833,6815,
+6815,6816,6796,6759,6727,6714,6709,6700,6683,6669,6662,6658,6649,6636,6620,6603,6585,6567,6555,6554,6560,
+6569,6577,6586,6591,6585,6565,6533,6497,6467,6443,6416,6383,6356,6347,6350,6335,6293,6249,6228,6223,6214,
+6195,6176,6158,6137,6120,6118,6111,6075,6018,5968,5917,5818,5673,5558,5531,5547,5519,5434,5360,5340,5343,
+5330,5311,5307,5304,5273,5235,5239,5290,5334,5326,5276,5231,5219,5226,5223,5194,5151,5119,5113,5122,5129,
+5120,5091,5039,4973,4918,4881,4839,4765,4673,4606,4589,4590,4568,4516,4456,4401,4333,4237,4124,4039,4013,
+4041,4076,4066,3993,3885,3783,3707,3649,3596,3544,3500,3468,3444,3416,3373,3313,3244,3176,3122,3092,3082,
+3068,3028,2979,2956,2968,2974,2936,2866,2810,2790,2783,2770,2749,2721,2672,2596,2518,2475,2493,2558,2626,
+2633,2553,2432,2350,2332,2333,2315,2294,2282,2238,2135,2041,2056,2158,2197,2082,1900,1799,1811,1847,1839,
+1808,1791,1775,1739,1700,1681,1671,1651,1628,1627,1641,1642,1625,1609,1603,1596,1582,1572,1575,1584,1593,
+1603,1617,1625,1618,1598,1572,1538,1496,1450,1405,1366,1336,1321,1320,1321,1314,1305,1304,1312,1323,1331,
+1331,1322,1305,1285,1270,1258,1245,1237,1242,1255,1267,1274,1286,1303,1320,1326,1324,1318,1312,1308,1318,
+1346,1386,1419,1436,1440,1441,1445,1458,1483,1519,1562,1598,1610,1594,1569,1558,1565,1570,1560,1556,1585,
+1644,1699,1723,1715,1693,1674,1662,1660,1670,1684,1691,1682,1658,1626,1594,1569,1555,1547,1538,1526,1511,
+1495,1479,1462,1443,1420,1393,1361,1328,1297,1268,1240,1212,1183,1156,1130,1101,1069,1038,1010,988,968,
+947,925,902,877,852,825,795,761,725,691,659,629,602,577,550,517,479,443,411,384,358,
+334,306,270,226,184,148,116,85,55,26,-1,-31,-63,-97,-132,-170,-207,-241,-273,-307,-345,
+-385,-427,-468,-509,-551,-595,-644,-694,-744,-791,-838,-885,-932,-979,-1028,-1078,-1127,-1170,-1207,-1243,-1282,
+-1324,-1364,-1401,-1436,-1471,-1505,-1535,-1564,-1593,-1624,-1657,-1691,-1728,-1764,-1798,-1831,-1866,-1899,-1926,-1952,-1984,
+-2021,-2055,-2085,-2118,-2155,-2191,-2219,-2243,-2270,-2300,-2331,-2363,-2399,-2435,-2465,-2491,-2516,-2544,-2574,-2604,-2635,
+-2665,-2693,-2717,-2738,-2758,-2782,-2809,-2837,-2859,-2874,-2887,-2904,-2920,-2931,-2942,-2958,-2978,-2996,-3006,-3009,-3012,
+-3017,-3027,-3037,-3043,-3042,-3041,-3044,-3047,-3044,-3036,-3027,-3019,-3009,-3001,-2993,-2983,-2970,-2956,-2945,-2934,-2916,
+-2893,-2871,-2849,-2826,-2802,-2781,-2762,-2741,-2718,-2695,-2669,-2641,-2613,-2589,-2563,-2534,-2505,-2478,-2449,-2417,-2386,
+-2362,-2339,-2308,-2274,-2246,-2223,-2194,-2157,-2123,-2095,-2066,-2032,-1997,-1965,-1933,-1898,-1862,-1828,-1792,-1755,-1723,
+-1695,-1667,-1634,-1600,-1566,-1533,-1498,-1465,-1431,-1396,-1360,-1328,-1299,-1268,-1236,-1206,-1178,-1147,-1115,-1086,-1060,
+-1034,-1007,-984,-961,-932,-899,-869,-844,-817,-786,-759,-737,-713,-686,-661,-640,-616,-587,-562,-543,-522,
+-493,-460,-429,-401,-375,-348,-314,-271,-229,-201,-181,-153,-111,-68,-27,14,55,87,114,153,206,
+261,313,369,429,476,504,520,531,538,548,579,625,663,691,728,782,834,877,923,968,991,
+997,1022,1077,1138,1195,1270,1354,1399,1390,1380,1403,1428,1428,1427,1426,1359,1217,1120,1168,1297,1412,
+1588,1955,2431,2758,2842,2836,2825,2660,2255,1858,1796,2032,2204,2067,1718,1363,1067,804,590,455,365,
+262,158,99,85,69,27,-26,-85,-159,-246,-327,-394,-454,-515,-564,-573,-521,-432,-380,-433,-580,
+-738,-836,-885,-930,-975,-973,-908,-825,-788,-826,-921,-1044,-1177,-1299,-1385,-1421,-1416,-1396,-1380,-1371,-1372,
+-1387,-1412,-1449,-1521,-1657,-1842,-2010,-2124,-2215,-2331,-2459,-2537,-2543,-2523,-2529,-2574,-2648,-2750,-2874,-3004,-3128,
+-3249,-3353,-3415,-3430,-3429,-3440,-3448,-3427,-3383,-3348,-3340,-3350,-3366,-3385,-3399,-3406,-3411,-3422,-3432,-3426,-3402,
+-3381,-3386,-3432,-3499,-3542,-3522,-3449,-3378,-3350,-3352,-3353,-3345,-3336,-3331,-3324,-3318,-3320,-3319,-3296,-3255,-3210,
+-3168,-3123,-3076,-3035,-2993,-2928,-2837,-2750,-2694,-2662,-2626,-2568,-2496,-2424,-2359,-2298,-2236,-2172,-2106,-2039,-1972,
+-1903,-1836,-1767,-1696,-1625,-1561,-1503,-1439,-1361,-1279,-1204,-1133,-1058,-978,-901,-826,-748,-668,-594,-526,-455,
+-382,-314,-255,-197,-127,-43,50,139,215,274,319,353,377,397,430,481,536,574,597,618,645,
+675,707,743,778,802,816,835,866,897,919,939,966,997,1028,1061,1096,1125,1145,1168,1204,1246,
+1278,1296,1312,1333,1358,1387,1418,1445,1464,1479,1503,1536,1575,1617,1658,1686,1687,1665,1644,1642,1656,
+1672,1681,1686,1693,1708,1727,1742,1749,1753,1763,1779,1799,1820,1848,1886,1923,1952,1970,1984,1994,1998,
+2002,2012,2035,2066,2100,2131,2158,2184,2209,2231,2248,2261,2282,2320,2376,2453,2558,2691,2832,2941,2993,
+2998,2978,2946,2907,2873,2857,2851,2825,2763,2687,2629,2598,2577,2552,2518,2472,2412,2356,2332,2344,2372,
+2393,2409,2426,2434,2417,2375,2324,2274,2227,2185,2153,2123,2074,2002,1935,1860,1847,1861,1869,1852,1812,
+1760,1703,1644,1589,1548,1526,1527,1552,1599,1668,1752,1839,1922,1995,2058,2103,2113,2083,2029,1976,1940,
+1917,1902,1904,1925,1942,1919,1867,1854,1923,2029,2058,1959,1804,1713,1721,1760,1751,1687,1616,1577,1565,
+1553,1526,1488,1453,1425,1392,1340,1268,1191,1122,1057,984,899,808,717,630,548,475,419,387,361,
+300,169,-23,-226,-386,-483,-540,-591,-657,-735,-799,-829,-833,-839,-855,-858,-827,-781,-760,-784,-838,
+-895,-944,-983,-1009,-1019,-1017,-1009,-1002,-1002,-1009,-1017,-1022,-1025,-1034,-1049,-1063,-1076,-1098,-1133,-1172,-1193,
+-1178,-1131,-1078,-1052,-1059,-1076,-1085,-1094,-1117,-1152,-1186,-1220,-1261,-1307,-1336,-1339,-1328,-1312,-1285,-1240,-1189,
+-1146,-1107,-1071,-1063,-1104,-1177,-1239,-1270,-1293,-1342,-1420,-1505,-1579,-1628,-1635,-1596,-1546,-1530,-1552,-1565,-1537,
+-1503,-1532,-1641,-1774,-1876,-1954,-2048,-2165,-2272,-2352,-2424,-2518,-2640,-2770,-2887,-2976,-3029,-3050,-3056,-3054,-3040,
+-3022,-3026,-3073,-3153,-3241,-3321,-3395,-3463,-3525,-3588,-3663,-3747,-3822,-3875,-3906,-3931,-3967,-4032,-4133,-4262,-4399,
+-4533,-4654,-4743,-4786,-4794,-4814,-4887,-5012,-5149,-5257,-5325,-5371,-5415,-5454,-5460,-5414,-5331,-5258,-5235,-5265,-5315,
+-5348,-5349,-5334,-5333,-5360,-5400,-5428,-5442,-5462,-5501,-5549,-5589,-5623,-5661,-5708,-5758,-5809,-5859,-5907,-5951,-5996,
+-6050,-6111,-6170,-6224,-6282,-6344,-6405,-6457,-6501,-6548,-6604,-6667,-6735,-6808,-6885,-6968,-7057,-7151,-7247,-7341,-7433,
+-7526,-7623,-7719,-7805,-7881,-7957,-8040,-8131,-8224,-8313,-8397,-8478,-8558,-8639,-8719,-8797,-8873,-8950,-9033,-9125,-9223,
+-9320,-9404,-9466,-9513,-9556,-9603,-9647,-9687,-9724,-9755,-9759,-9717,-9647,-9605,-9635,-9736,-9862,-9961,-10014,-10035,-10060,
+-10108,-10168,-10216,-10244,-10269,-10308,-10353,-10383,-10390,-10383,-10377,-10391,-10440,-10529,-10629,-10692,-10697,-10662,-10626,-10605,-10594,
+-10577,-10553,-10527,-10500,-10468,-10424,-10370,-10306,-10230,-10139,-10037,-9929,-9817,-9702,-9587,-9480,-9376,-9260,-9128,-8995,-8883,
+-8786,-8683,-8557,-8418,-8283,-8152,-8010,-7848,-7671,-7494,-7325,-7160,-6998,-6838,-6684,-6537,-6390,-6239,-6082,-5916,-5741,
+-5566,-5416,-5307,-5229,-5171,-5150,-5183,-5229,-5194,-5028,-4794,-4620,-4582,-4650,-4729,-4731,-4601,-4331,-3965,-3580,-3234,
+-2939,-2687,-2483,-2336,-2241,-2177,-2128,-2086,-2041,-1981,-1899,-1795,-1668,-1525,-1381,-1254,-1147,-1050,-954,-852,-738,
+-609,-476,-359,-259,-168,-87,-28,7,43,93,148,194,237,298,382,471,558,649,754,869,984,
+1095,1206,1326,1455,1584,1701,1797,1875,1947,2019,2089,2156,2225,2303,2390,2484,2580,2679,2780,2884,2987,
+3083,3170,3254,3350,3458,3566,3668,3776,3903,4038,4163,4284,4432,4613,4793,4928,5009,5072,5159,5286,5435,
+5573,5662,5688,5672,5656,5670,5721,5799,5881,5941,5969,5978,5988,6004,6026,6064,6130,6206,6263,6299,6344,
+6412,6485,6549,6613,6677,6720,6740,6764,6784,6759,6705,6738,6922,7119,7100,6812,6442,6181,6039,5937,5869,
+5876,5924,5949,5989,6151,6437,6706,6851,6917,6991,7071,7104,7091,7081,7082,7066,7042,7062,7134,7204,7226,
+7208,7182,7156,7115,7060,7005,6963,6938,6928,6917,6893,6862,6844,6844,6837,6811,6779,6764,6761,6749,6724,
+6703,6697,6697,6688,6666,6643,6629,6620,6610,6596,6587,6588,6599,6612,6622,6628,6628,6616,6591,6556,6520,
+6489,6463,6434,6399,6371,6361,6364,6355,6324,6289,6266,6252,6230,6206,6194,6194,6190,6175,6159,6136,6097,
+6047,5997,5930,5817,5678,5592,5594,5622,5587,5488,5398,5361,5348,5325,5305,5307,5311,5292,5264,5261,5288,
+5311,5310,5297,5286,5280,5273,5254,5216,5163,5119,5113,5141,5174,5175,5133,5060,4983,4926,4890,4850,4787,
+4709,4653,4638,4644,4639,4607,4552,4479,4384,4268,4154,4073,4044,4053,4065,4044,3983,3901,3823,3760,3704,
+3649,3591,3538,3501,3478,3454,3410,3347,3280,3224,3183,3154,3133,3108,3066,3021,3003,3018,3027,2991,2918,
+2852,2816,2798,2780,2758,2729,2682,2614,2541,2497,2512,2591,2693,2735,2667,2524,2402,2353,2347,2335,2318,
+2305,2265,2175,2090,2093,2166,2185,2074,1909,1816,1820,1849,1847,1829,1820,1805,1770,1734,1715,1700,1672,
+1644,1638,1650,1655,1644,1626,1610,1595,1581,1576,1578,1584,1595,1618,1644,1659,1656,1640,1616,1581,1536,
+1491,1454,1418,1379,1346,1331,1332,1336,1336,1334,1333,1336,1344,1353,1351,1333,1309,1292,1280,1268,1258,
+1259,1274,1290,1300,1310,1322,1332,1334,1328,1322,1315,1310,1312,1331,1361,1392,1413,1423,1428,1433,1445,
+1468,1504,1546,1580,1596,1592,1582,1582,1592,1597,1586,1571,1574,1605,1653,1693,1712,1709,1697,1685,1678,
+1679,1686,1698,1706,1695,1661,1618,1585,1569,1560,1548,1532,1517,1505,1493,1475,1453,1429,1404,1379,1353,
+1324,1293,1263,1235,1209,1183,1153,1119,1085,1054,1029,1010,993,976,957,935,909,882,857,831,799,
+763,726,691,658,627,599,571,538,501,465,432,404,377,350,321,287,251,219,193,167,140,
+110,82,53,20,-15,-51,-87,-123,-160,-195,-230,-268,-308,-350,-392,-434,-475,-515,-555,-598,-646,
+-696,-744,-790,-835,-880,-928,-978,-1030,-1080,-1125,-1164,-1201,-1242,-1286,-1328,-1365,-1400,-1435,-1468,-1497,-1524,
+-1554,-1588,-1622,-1657,-1693,-1731,-1768,-1805,-1841,-1872,-1898,-1922,-1951,-1987,-2020,-2049,-2081,-2118,-2154,-2182,-2206,
+-2232,-2260,-2289,-2320,-2356,-2392,-2423,-2448,-2472,-2501,-2532,-2565,-2597,-2626,-2653,-2678,-2702,-2725,-2751,-2780,-2808,
+-2829,-2841,-2852,-2868,-2885,-2900,-2915,-2932,-2950,-2963,-2969,-2974,-2980,-2987,-2996,-3005,-3009,-3007,-3003,-3003,-3005,
+-3002,-2993,-2983,-2975,-2968,-2961,-2954,-2945,-2932,-2920,-2909,-2896,-2879,-2857,-2835,-2814,-2790,-2767,-2748,-2731,-2710,
+-2687,-2664,-2641,-2615,-2589,-2565,-2543,-2518,-2493,-2467,-2438,-2403,-2370,-2344,-2319,-2289,-2255,-2229,-2206,-2177,-2141,
+-2108,-2082,-2055,-2023,-1989,-1958,-1926,-1892,-1859,-1827,-1793,-1757,-1724,-1697,-1670,-1639,-1604,-1572,-1540,-1507,-1474,
+-1440,-1405,-1370,-1338,-1311,-1281,-1249,-1218,-1189,-1159,-1127,-1096,-1069,-1043,-1017,-994,-972,-943,-909,-877,-852,
+-828,-803,-782,-763,-740,-711,-685,-664,-639,-608,-579,-558,-539,-511,-475,-438,-405,-378,-351,-318,-275,
+-235,-207,-185,-157,-119,-80,-39,6,51,85,111,145,193,243,293,348,405,443,458,465,478,
+493,512,547,594,633,662,702,759,815,860,906,953,982,996,1035,1118,1207,1268,1315,1368,1408,
+1412,1399,1398,1406,1408,1402,1372,1279,1139,1052,1086,1192,1325,1564,1992,2486,2810,2892,2856,2759,2502,
+2090,1787,1827,2074,2161,1922,1520,1173,928,739,603,526,461,364,265,215,204,180,124,61,0,
+-71,-154,-236,-309,-376,-436,-480,-501,-487,-447,-427,-484,-617,-753,-825,-850,-887,-943,-956,-888,-787,
+-741,-787,-885,-984,-1079,-1185,-1295,-1376,-1409,-1412,-1416,-1430,-1444,-1448,-1443,-1450,-1505,-1631,-1803,-1959,-2072,
+-2171,-2295,-2425,-2507,-2521,-2504,-2502,-2538,-2624,-2754,-2901,-3029,-3133,-3229,-3320,-3379,-3400,-3414,-3440,-3459,-3443,
+-3400,-3365,-3352,-3349,-3345,-3343,-3348,-3360,-3379,-3404,-3426,-3433,-3420,-3392,-3367,-3364,-3381,-3389,-3355,-3287,-3227,
+-3206,-3214,-3223,-3225,-3226,-3228,-3234,-3248,-3269,-3280,-3264,-3229,-3189,-3143,-3087,-3033,-2998,-2968,-2913,-2825,-2734,
+-2670,-2633,-2598,-2547,-2481,-2409,-2342,-2283,-2227,-2167,-2100,-2031,-1964,-1898,-1832,-1766,-1695,-1622,-1553,-1490,-1423,
+-1349,-1273,-1199,-1126,-1046,-966,-893,-822,-743,-660,-583,-515,-447,-375,-308,-249,-194,-128,-46,44,131,
+204,262,312,353,382,400,424,467,518,558,583,607,639,674,707,741,774,798,815,835,864,
+897,923,947,974,1004,1034,1066,1098,1123,1141,1161,1193,1229,1256,1274,1289,1306,1325,1351,1383,1413,
+1435,1451,1473,1501,1532,1565,1599,1627,1637,1629,1619,1620,1629,1638,1643,1650,1665,1686,1708,1720,1724,
+1727,1738,1755,1773,1791,1819,1858,1897,1928,1947,1959,1966,1970,1975,1988,2009,2036,2065,2093,2120,2144,
+2166,2186,2204,2220,2242,2273,2313,2366,2442,2552,2684,2800,2865,2877,2862,2842,2824,2809,2795,2769,2712,
+2628,2549,2506,2493,2485,2466,2436,2393,2338,2285,2257,2255,2259,2257,2263,2287,2309,2302,2267,2230,2200,
+2169,2131,2088,2040,1979,1910,1860,1807,1809,1821,1820,1797,1761,1716,1663,1607,1557,1518,1494,1492,1516,
+1566,1635,1713,1791,1864,1934,2005,2069,2107,2105,2070,2025,1984,1949,1920,1905,1906,1900,1868,1832,1851,
+1944,2044,2046,1919,1745,1637,1627,1653,1648,1602,1550,1522,1510,1492,1461,1424,1393,1363,1319,1254,1179,
+1108,1047,989,927,861,786,701,611,525,449,390,355,331,277,149,-49,-261,-424,-521,-575,-621,
+-678,-743,-799,-834,-855,-880,-904,-902,-864,-821,-818,-865,-931,-981,-1008,-1024,-1037,-1048,-1050,-1044,-1034,
+-1029,-1032,-1036,-1035,-1034,-1040,-1052,-1061,-1069,-1088,-1121,-1159,-1179,-1167,-1128,-1085,-1065,-1071,-1085,-1089,-1095,
+-1120,-1162,-1201,-1230,-1256,-1282,-1300,-1306,-1308,-1307,-1285,-1237,-1184,-1143,-1105,-1065,-1048,-1089,-1178,-1264,-1308,
+-1325,-1359,-1427,-1514,-1591,-1638,-1646,-1625,-1602,-1599,-1611,-1607,-1576,-1553,-1585,-1676,-1782,-1870,-1955,-2066,-2198,
+-2316,-2405,-2483,-2574,-2683,-2796,-2900,-2985,-3039,-3061,-3064,-3058,-3044,-3027,-3027,-3063,-3134,-3223,-3316,-3403,-3475,
+-3533,-3592,-3670,-3758,-3833,-3878,-3903,-3928,-3976,-4063,-4187,-4327,-4455,-4564,-4655,-4729,-4777,-4808,-4848,-4921,-5029,
+-5152,-5262,-5341,-5397,-5438,-5460,-5436,-5360,-5268,-5220,-5241,-5301,-5347,-5355,-5337,-5319,-5324,-5354,-5395,-5428,-5452,
+-5480,-5522,-5570,-5615,-5658,-5706,-5756,-5800,-5841,-5886,-5936,-5983,-6027,-6076,-6132,-6191,-6248,-6308,-6373,-6434,-6487,
+-6532,-6579,-6630,-6687,-6749,-6817,-6890,-6967,-7048,-7135,-7226,-7316,-7405,-7495,-7592,-7690,-7779,-7857,-7934,-8022,-8116,
+-8207,-8291,-8369,-8450,-8533,-8618,-8702,-8783,-8864,-8947,-9037,-9130,-9222,-9303,-9370,-9427,-9482,-9538,-9592,-9641,-9685,
+-9730,-9764,-9759,-9701,-9620,-9580,-9622,-9735,-9863,-9956,-10002,-10023,-10055,-10114,-10184,-10236,-10261,-10281,-10316,-10361,-10394,
+-10406,-10404,-10398,-10400,-10428,-10496,-10587,-10658,-10677,-10654,-10620,-10599,-10587,-10571,-10548,-10523,-10495,-10460,-10412,-10355,-10292,
+-10220,-10133,-10034,-9932,-9829,-9722,-9610,-9500,-9392,-9271,-9131,-8992,-8882,-8797,-8702,-8573,-8427,-8288,-8155,-8007,-7835,
+-7652,-7477,-7313,-7153,-6994,-6836,-6684,-6539,-6394,-6236,-6060,-5879,-5710,-5564,-5443,-5341,-5252,-5179,-5139,-5148,-5183,
+-5171,-5047,-4829,-4621,-4520,-4537,-4594,-4601,-4514,-4331,-4071,-3759,-3426,-3107,-2825,-2582,-2372,-2200,-2091,-2053,-2056,
+-2043,-1976,-1865,-1736,-1604,-1470,-1335,-1209,-1096,-997,-906,-812,-703,-577,-453,-346,-250,-154,-62,3,44,
+83,137,196,245,294,362,451,546,635,725,826,936,1049,1163,1282,1409,1539,1662,1766,1849,1921,
+1993,2069,2145,2221,2297,2377,2460,2548,2643,2741,2837,2934,3034,3134,3224,3306,3393,3495,3607,3724,3852,
+3995,4137,4262,4380,4516,4679,4842,4974,5069,5148,5237,5350,5474,5573,5613,5598,5571,5575,5616,5676,5739,
+5795,5831,5843,5858,5901,5961,6014,6063,6128,6201,6255,6291,6344,6424,6497,6548,6607,6688,6754,6778,6791,
+6816,6820,6802,6856,7050,7250,7228,6938,6578,6337,6204,6097,6048,6119,6233,6253,6199,6234,6430,6672,6833,
+6926,7016,7097,7125,7123,7138,7155,7134,7096,7109,7179,7240,7247,7228,7216,7204,7166,7107,7048,7002,6972,
+6956,6944,6920,6889,6869,6861,6847,6818,6795,6791,6789,6768,6736,6722,6731,6741,6729,6698,6667,6648,6641,
+6635,6627,6620,6621,6633,6649,6661,6666,6659,6639,6609,6578,6549,6520,6491,6460,6428,6399,6385,6382,6375,
+6353,6321,6296,6275,6251,6228,6219,6226,6232,6225,6206,6175,6129,6075,6017,5940,5827,5710,5649,5662,5683,
+5641,5545,5457,5408,5373,5334,5308,5304,5305,5295,5289,5302,5320,5325,5325,5338,5356,5355,5329,5292,5248,
+5196,5152,5147,5184,5224,5216,5150,5056,4976,4929,4904,4875,4825,4761,4709,4685,4681,4676,4651,4601,4523,
+4423,4311,4205,4129,4092,4085,4083,4061,4013,3950,3883,3817,3757,3700,3644,3590,3547,3519,3494,3450,3387,
+3324,3279,3246,3216,3184,3151,3114,3077,3051,3043,3036,3007,2954,2897,2850,2816,2794,2780,2762,2723,2660,
+2588,2531,2519,2571,2662,2716,2669,2541,2421,2368,2360,2349,2333,2324,2297,2225,2144,2120,2152,2154,2066,
+1937,1857,1851,1867,1868,1860,1854,1838,1805,1771,1750,1730,1699,1669,1657,1661,1668,1666,1653,1631,1608,
+1593,1591,1592,1593,1604,1634,1668,1687,1684,1672,1653,1620,1575,1531,1499,1468,1430,1394,1373,1368,1368,
+1365,1357,1350,1348,1358,1372,1377,1361,1336,1315,1301,1288,1276,1274,1288,1307,1323,1335,1343,1346,1341,
+1333,1328,1328,1329,1332,1340,1355,1374,1391,1403,1411,1419,1431,1455,1493,1537,1574,1597,1607,1615,1628,
+1643,1647,1634,1606,1580,1573,1592,1629,1669,1698,1715,1722,1718,1703,1692,1698,1716,1723,1699,1654,1613,
+1590,1577,1561,1542,1524,1510,1496,1478,1455,1432,1410,1392,1373,1348,1317,1284,1253,1226,1200,1170,1135,
+1101,1074,1053,1036,1020,1005,988,967,940,913,888,862,830,791,752,714,677,641,609,582,554,
+524,493,462,433,404,376,347,317,289,266,246,224,198,169,138,104,65,24,-15,-51,-88,
+-124,-160,-197,-237,-279,-321,-362,-403,-443,-481,-519,-559,-605,-653,-700,-745,-788,-832,-879,-928,-978,
+-1027,-1074,-1118,-1158,-1198,-1242,-1285,-1326,-1363,-1398,-1430,-1460,-1489,-1522,-1558,-1594,-1630,-1665,-1702,-1739,-1776,
+-1814,-1848,-1875,-1899,-1927,-1961,-1993,-2021,-2050,-2084,-2117,-2145,-2170,-2196,-2223,-2249,-2277,-2311,-2348,-2381,-2408,
+-2434,-2463,-2495,-2527,-2559,-2588,-2616,-2643,-2671,-2698,-2726,-2754,-2781,-2801,-2813,-2824,-2839,-2857,-2873,-2889,-2906,
+-2920,-2926,-2929,-2936,-2947,-2957,-2965,-2972,-2975,-2971,-2964,-2962,-2964,-2963,-2956,-2946,-2939,-2934,-2927,-2919,-2907,
+-2893,-2879,-2866,-2854,-2837,-2817,-2796,-2775,-2754,-2734,-2718,-2702,-2683,-2660,-2637,-2614,-2589,-2563,-2539,-2517,-2495,
+-2472,-2448,-2420,-2387,-2354,-2326,-2300,-2269,-2237,-2211,-2188,-2159,-2125,-2093,-2067,-2042,-2012,-1983,-1954,-1922,-1889,
+-1857,-1828,-1796,-1761,-1729,-1703,-1676,-1643,-1609,-1577,-1546,-1512,-1478,-1446,-1413,-1378,-1347,-1320,-1292,-1259,-1227,
+-1199,-1172,-1142,-1112,-1084,-1057,-1029,-1003,-979,-953,-923,-894,-871,-848,-826,-807,-789,-765,-735,-707,-683,
+-657,-626,-595,-568,-544,-515,-479,-443,-410,-382,-356,-324,-285,-245,-214,-186,-155,-119,-86,-53,-12,
+34,73,107,145,190,232,273,323,373,402,407,411,428,449,471,505,554,602,642,688,746,
+800,839,880,927,964,990,1045,1144,1246,1302,1326,1356,1393,1404,1389,1379,1386,1390,1367,1304,1197,
+1076,1011,1041,1144,1314,1612,2057,2511,2777,2808,2703,2518,2224,1896,1751,1887,2089,2055,1738,1356,1087,
+920,781,667,598,541,463,385,345,329,294,234,165,92,9,-74,-147,-213,-280,-341,-389,-426,
+-455,-474,-499,-562,-665,-754,-779,-762,-770,-820,-856,-823,-751,-723,-777,-876,-965,-1039,-1127,-1236,-1333,
+-1389,-1413,-1437,-1472,-1503,-1513,-1503,-1500,-1543,-1652,-1801,-1939,-2044,-2139,-2250,-2364,-2443,-2475,-2477,-2480,-2510,
+-2592,-2726,-2876,-2998,-3088,-3174,-3260,-3318,-3339,-3352,-3377,-3398,-3388,-3355,-3328,-3317,-3308,-3293,-3279,-3280,-3298,
+-3328,-3361,-3387,-3403,-3407,-3394,-3363,-3326,-3292,-3253,-3194,-3123,-3071,-3059,-3074,-3095,-3112,-3125,-3135,-3150,-3180,
+-3218,-3240,-3234,-3207,-3171,-3122,-3057,-2996,-2961,-2940,-2896,-2821,-2737,-2668,-2617,-2572,-2522,-2462,-2391,-2320,-2259,
+-2206,-2150,-2085,-2016,-1951,-1887,-1823,-1757,-1687,-1615,-1542,-1474,-1406,-1336,-1265,-1196,-1122,-1041,-963,-893,-827,
+-751,-667,-588,-518,-451,-381,-313,-253,-196,-132,-55,30,114,185,242,294,344,383,406,428,464,
+510,548,574,602,640,680,714,746,778,805,826,846,871,898,922,946,972,999,1024,1050,1077,
+1103,1127,1151,1178,1203,1221,1236,1252,1267,1284,1307,1339,1372,1399,1420,1444,1470,1493,1515,1540,1566,
+1584,1593,1596,1598,1600,1599,1600,1608,1628,1655,1679,1693,1699,1707,1725,1748,1768,1786,1811,1843,1876,
+1903,1921,1934,1940,1945,1953,1969,1992,2018,2045,2074,2102,2123,2135,2144,2154,2171,2198,2233,2268,2299,
+2337,2400,2491,2585,2649,2674,2679,2683,2690,2691,2675,2631,2556,2469,2407,2390,2400,2404,2388,2359,2320,
+2270,2219,2182,2155,2126,2098,2096,2129,2166,2175,2157,2138,2126,2105,2063,2007,1948,1887,1835,1807,1767,
+1772,1775,1764,1742,1716,1680,1633,1581,1535,1502,1482,1480,1501,1543,1596,1655,1718,1783,1850,1923,1998,
+2059,2090,2086,2057,2017,1975,1937,1905,1876,1846,1823,1835,1900,1993,2048,2005,1871,1715,1601,1548,1530,
+1518,1502,1484,1464,1435,1395,1347,1303,1268,1229,1174,1104,1035,980,931,882,834,787,731,655,564,
+476,402,348,315,290,237,113,-77,-279,-434,-528,-584,-631,-679,-730,-778,-820,-859,-900,-935,-942,
+-919,-896,-910,-962,-1019,-1051,-1059,-1057,-1059,-1066,-1069,-1065,-1057,-1053,-1054,-1054,-1048,-1044,-1050,-1062,-1070,
+-1073,-1083,-1104,-1127,-1141,-1136,-1117,-1094,-1083,-1084,-1087,-1085,-1091,-1124,-1172,-1209,-1226,-1236,-1250,-1267,-1285,
+-1305,-1316,-1295,-1244,-1192,-1162,-1140,-1109,-1087,-1117,-1206,-1305,-1363,-1381,-1401,-1457,-1537,-1608,-1643,-1648,-1649,
+-1666,-1690,-1698,-1675,-1640,-1631,-1669,-1739,-1813,-1885,-1978,-2105,-2242,-2356,-2439,-2516,-2607,-2711,-2814,-2909,-2988,
+-3041,-3063,-3062,-3049,-3032,-3018,-3021,-3056,-3124,-3214,-3314,-3409,-3485,-3543,-3605,-3685,-3769,-3830,-3859,-3878,-3920,
+-4004,-4130,-4280,-4423,-4539,-4623,-4686,-4737,-4785,-4839,-4906,-4987,-5075,-5169,-5266,-5353,-5415,-5443,-5431,-5377,-5292,
+-5225,-5221,-5278,-5340,-5359,-5338,-5313,-5309,-5327,-5358,-5398,-5437,-5473,-5509,-5551,-5600,-5651,-5704,-5757,-5801,-5832,
+-5861,-5905,-5960,-6013,-6057,-6100,-6150,-6207,-6266,-6329,-6394,-6456,-6510,-6559,-6610,-6663,-6716,-6772,-6834,-6904,-6977,
+-7055,-7137,-7221,-7303,-7381,-7463,-7556,-7653,-7744,-7827,-7909,-8000,-8095,-8184,-8266,-8345,-8427,-8513,-8598,-8682,-8766,
+-8853,-8943,-9037,-9127,-9205,-9267,-9319,-9377,-9447,-9521,-9585,-9635,-9680,-9728,-9763,-9755,-9691,-9608,-9574,-9626,-9746,
+-9875,-9961,-9997,-10012,-10045,-10110,-10186,-10244,-10273,-10292,-10322,-10361,-10395,-10415,-10422,-10418,-10410,-10419,-10465,-10539,-10607,
+-10637,-10629,-10605,-10584,-10569,-10554,-10534,-10510,-10479,-10437,-10385,-10325,-10264,-10197,-10119,-10028,-9933,-9838,-9734,-9620,-9504,
+-9390,-9268,-9131,-8999,-8896,-8815,-8716,-8579,-8425,-8284,-8152,-8000,-7822,-7637,-7466,-7309,-7154,-6997,-6837,-6683,-6537,
+-6391,-6223,-6026,-5828,-5669,-5560,-5476,-5387,-5291,-5201,-5139,-5119,-5135,-5139,-5057,-4869,-4644,-4488,-4441,-4452,-4442,
+-4381,-4268,-4099,-3858,-3561,-3263,-3002,-2761,-2504,-2245,-2053,-1981,-1996,-2008,-1950,-1827,-1683,-1545,-1415,-1289,-1167,
+-1051,-945,-851,-759,-653,-531,-409,-306,-217,-128,-42,25,72,119,176,236,290,347,423,519,620,
+715,809,911,1021,1138,1257,1376,1498,1619,1732,1825,1895,1956,2025,2105,2191,2276,2360,2442,2524,2609,
+2701,2794,2884,2975,3074,3178,3275,3360,3444,3539,3652,3786,3939,4100,4249,4373,4483,4597,4718,4842,4968,
+5099,5222,5326,5415,5495,5552,5561,5531,5515,5544,5598,5639,5662,5688,5716,5741,5779,5852,5943,6014,6063,
+6119,6186,6238,6279,6342,6432,6504,6540,6591,6685,6777,6816,6826,6847,6856,6848,6911,7113,7324,7308,7016,
+6657,6423,6291,6178,6138,6259,6451,6519,6434,6369,6458,6644,6812,6937,7042,7113,7134,7147,7189,7219,7186,
+7134,7143,7211,7261,7258,7242,7247,7245,7202,7131,7065,7019,6991,6980,6971,6948,6915,6890,6880,6864,6837,
+6815,6811,6805,6781,6754,6747,6759,6767,6754,6728,6701,6680,6668,6663,6658,6653,6654,6666,6684,6699,6701,
+6687,6659,6626,6598,6575,6548,6516,6485,6459,6436,6417,6406,6398,6379,6348,6319,6300,6284,6266,6251,6246,
+6249,6250,6240,6208,6154,6087,6020,5946,5854,5764,5715,5712,5705,5652,5569,5498,5451,5407,5361,5332,5319,
+5305,5288,5293,5325,5350,5353,5359,5393,5435,5441,5405,5352,5303,5256,5223,5225,5261,5287,5257,5166,5057,
+4976,4940,4930,4915,4877,4820,4764,4727,4708,4694,4669,4622,4552,4465,4368,4272,4192,4144,4125,4117,4096,
+4057,4003,3937,3866,3798,3742,3695,3647,3601,3564,3530,3484,3424,3370,3333,3306,3271,3227,3185,3150,3115,
+3078,3043,3017,2998,2976,2939,2886,2835,2807,2803,2799,2772,2718,2644,2565,2512,2520,2585,2642,2619,2523,
+2430,2390,2385,2371,2351,2343,2329,2272,2189,2136,2135,2133,2081,1992,1923,1898,1896,1894,1891,1885,1869,
+1841,1811,1787,1763,1735,1708,1691,1685,1689,1695,1691,1670,1641,1622,1616,1611,1607,1617,1648,1685,1704,
+1703,1694,1680,1653,1614,1573,1540,1509,1476,1444,1423,1409,1397,1383,1370,1362,1363,1374,1391,1398,1387,
+1364,1341,1324,1308,1293,1288,1298,1317,1336,1351,1361,1363,1356,1346,1343,1349,1361,1370,1372,1372,1372,
+1379,1389,1402,1416,1432,1458,1494,1537,1576,1604,1627,1648,1669,1684,1686,1675,1650,1616,1586,1579,1600,
+1641,1688,1732,1764,1771,1748,1715,1701,1713,1729,1722,1687,1645,1612,1590,1572,1554,1534,1516,1497,1477,
+1455,1433,1414,1399,1386,1367,1338,1303,1269,1241,1216,1188,1157,1128,1105,1088,1071,1052,1031,1011,989,
+962,934,908,880,846,807,766,727,688,650,618,594,575,555,531,504,477,449,422,394,365,
+338,316,296,273,244,213,180,141,98,55,16,-19,-55,-91,-127,-164,-206,-250,-292,-330,-369,
+-409,-448,-487,-527,-572,-620,-666,-709,-751,-796,-842,-887,-932,-977,-1025,-1071,-1112,-1151,-1192,-1237,-1281,
+-1321,-1357,-1391,-1423,-1456,-1491,-1529,-1567,-1603,-1637,-1670,-1703,-1739,-1778,-1815,-1845,-1871,-1900,-1932,-1963,-1991,
+-2019,-2049,-2079,-2106,-2133,-2162,-2190,-2214,-2240,-2272,-2310,-2344,-2373,-2400,-2430,-2461,-2492,-2522,-2552,-2582,-2612,
+-2642,-2670,-2697,-2723,-2748,-2768,-2782,-2796,-2812,-2830,-2846,-2862,-2879,-2891,-2895,-2896,-2903,-2916,-2926,-2932,-2937,
+-2940,-2937,-2928,-2924,-2926,-2928,-2925,-2917,-2909,-2902,-2894,-2882,-2868,-2851,-2836,-2823,-2811,-2796,-2777,-2757,-2738,
+-2720,-2703,-2689,-2675,-2655,-2632,-2609,-2588,-2564,-2537,-2512,-2489,-2465,-2441,-2417,-2392,-2364,-2336,-2310,-2284,-2254,
+-2222,-2194,-2170,-2142,-2110,-2079,-2052,-2027,-1999,-1972,-1945,-1915,-1884,-1854,-1827,-1796,-1763,-1733,-1707,-1678,-1644,
+-1611,-1582,-1551,-1516,-1483,-1452,-1421,-1387,-1355,-1329,-1301,-1269,-1236,-1209,-1184,-1157,-1130,-1105,-1079,-1048,-1017,
+-991,-968,-943,-919,-898,-877,-853,-829,-806,-778,-745,-712,-685,-660,-634,-605,-574,-542,-507,-472,-440,
+-411,-384,-357,-328,-292,-254,-220,-190,-157,-122,-94,-70,-41,-2,41,86,136,183,219,251,290,
+333,357,360,366,387,412,434,466,518,576,626,676,733,781,814,850,900,949,988,1046,1142,
+1238,1290,1307,1330,1364,1376,1363,1357,1367,1361,1308,1219,1121,1043,1013,1051,1169,1388,1734,2166,2543,
+2718,2667,2476,2220,1947,1757,1772,1949,2052,1895,1554,1258,1108,1021,906,780,690,628,565,507,472,
+449,413,358,284,186,78,-9,-62,-106,-165,-233,-289,-336,-388,-449,-517,-601,-692,-749,-735,-678,
+-649,-685,-742,-757,-731,-720,-769,-858,-943,-1008,-1081,-1177,-1275,-1348,-1393,-1432,-1476,-1517,-1541,-1549,-1562,
+-1611,-1707,-1829,-1942,-2031,-2112,-2201,-2292,-2364,-2411,-2438,-2458,-2491,-2566,-2688,-2822,-2929,-3012,-3099,-3188,-3247,
+-3261,-3259,-3268,-3282,-3279,-3262,-3251,-3247,-3238,-3216,-3192,-3186,-3209,-3252,-3295,-3327,-3348,-3363,-3364,-3339,-3290,
+-3229,-3159,-3078,-2999,-2949,-2940,-2958,-2986,-3014,-3038,-3056,-3079,-3120,-3170,-3202,-3201,-3179,-3147,-3097,-3030,-2967,
+-2929,-2907,-2873,-2817,-2751,-2686,-2621,-2561,-2506,-2447,-2375,-2299,-2232,-2178,-2124,-2061,-1995,-1932,-1871,-1808,-1743,
+-1675,-1603,-1529,-1458,-1390,-1323,-1256,-1189,-1118,-1042,-967,-900,-835,-762,-681,-603,-532,-464,-394,-325,-261,
+-201,-140,-70,8,87,155,210,263,321,373,409,438,474,515,549,573,602,642,685,720,751,
+782,811,834,853,874,894,914,935,959,984,1004,1023,1046,1074,1106,1136,1161,1177,1187,1197,1211,
+1226,1243,1267,1299,1332,1360,1386,1412,1438,1458,1475,1495,1518,1539,1556,1568,1573,1573,1570,1571,1582,
+1603,1631,1655,1671,1680,1692,1711,1732,1751,1771,1797,1826,1855,1880,1900,1913,1919,1923,1934,1955,1980,
+2005,2031,2060,2086,2102,2104,2102,2105,2122,2154,2193,2224,2236,2238,2256,2303,2370,2429,2465,2486,2502,
+2517,2522,2506,2462,2394,2326,2288,2290,2307,2312,2297,2272,2239,2197,2149,2101,2050,1993,1948,1946,1990,
+2039,2055,2042,2025,2011,1988,1946,1896,1848,1806,1776,1767,1736,1739,1732,1717,1699,1680,1650,1605,1558,
+1522,1498,1484,1481,1490,1507,1530,1565,1614,1675,1742,1817,1898,1977,2035,2058,2047,2014,1973,1930,1882,
+1826,1778,1772,1828,1922,1989,1983,1907,1800,1690,1581,1480,1410,1390,1407,1421,1402,1351,1286,1223,1169,
+1120,1070,1010,946,892,851,811,765,721,687,647,581,492,404,335,287,256,230,176,62,-106,
+-282,-417,-506,-568,-620,-667,-714,-762,-812,-861,-910,-953,-978,-984,-986,-1006,-1044,-1079,-1097,-1097,-1090,
+-1084,-1083,-1083,-1081,-1076,-1074,-1074,-1069,-1060,-1055,-1062,-1074,-1081,-1082,-1086,-1096,-1106,-1113,-1116,-1115,-1108,
+-1101,-1094,-1083,-1074,-1084,-1125,-1176,-1206,-1212,-1218,-1242,-1276,-1308,-1335,-1344,-1319,-1264,-1213,-1193,-1187,-1168,
+-1144,-1159,-1232,-1329,-1399,-1428,-1447,-1494,-1569,-1635,-1659,-1657,-1672,-1721,-1773,-1783,-1750,-1718,-1727,-1777,-1835,
+-1883,-1939,-2029,-2156,-2286,-2389,-2464,-2538,-2628,-2727,-2822,-2908,-2985,-3042,-3068,-3065,-3043,-3018,-3002,-3010,-3049,
+-3118,-3208,-3308,-3405,-3489,-3559,-3628,-3703,-3769,-3808,-3823,-3851,-3926,-4060,-4231,-4402,-4542,-4643,-4709,-4752,-4785,
+-4823,-4887,-4972,-5056,-5121,-5181,-5257,-5343,-5403,-5409,-5364,-5289,-5221,-5197,-5236,-5307,-5350,-5338,-5304,-5291,-5309,
+-5340,-5372,-5409,-5454,-5497,-5536,-5576,-5623,-5678,-5735,-5788,-5826,-5850,-5877,-5920,-5977,-6031,-6076,-6119,-6168,-6223,
+-6281,-6343,-6407,-6469,-6525,-6581,-6639,-6696,-6749,-6800,-6856,-6921,-6991,-7067,-7145,-7223,-7296,-7365,-7439,-7524,-7617,
+-7708,-7794,-7881,-7971,-8063,-8152,-8238,-8323,-8408,-8493,-8576,-8660,-8749,-8841,-8935,-9028,-9112,-9179,-9228,-9276,-9341,
+-9425,-9511,-9579,-9627,-9670,-9719,-9757,-9754,-9695,-9616,-9581,-9631,-9750,-9878,-9963,-9995,-10006,-10035,-10098,-10175,-10238,
+-10275,-10298,-10325,-10360,-10395,-10422,-10436,-10433,-10418,-10412,-10436,-10489,-10547,-10583,-10590,-10576,-10555,-10535,-10520,-10504,-10482,
+-10450,-10408,-10358,-10301,-10241,-10178,-10106,-10022,-9932,-9838,-9733,-9615,-9494,-9380,-9269,-9150,-9030,-8927,-8833,-8720,-8575,
+-8422,-8286,-8154,-7998,-7816,-7633,-7467,-7313,-7158,-7000,-6840,-6685,-6541,-6395,-6221,-6010,-5799,-5644,-5560,-5503,-5425,
+-5321,-5217,-5136,-5092,-5088,-5095,-5048,-4898,-4680,-4485,-4370,-4316,-4273,-4222,-4158,-4053,-3865,-3609,-3351,-3139,-2936,
+-2679,-2372,-2108,-1969,-1942,-1939,-1885,-1775,-1642,-1510,-1381,-1254,-1129,-1009,-898,-798,-706,-605,-490,-371,-265,
+-176,-94,-19,46,104,162,223,282,339,404,489,590,695,798,899,1003,1117,1239,1361,1475,1581,
+1688,1794,1884,1949,2002,2064,2142,2229,2319,2406,2492,2576,2660,2747,2836,2924,3016,3116,3219,3317,3406,
+3495,3594,3714,3864,4040,4215,4363,4480,4581,4675,4756,4837,4954,5117,5285,5405,5471,5516,5546,5543,5516,
+5512,5554,5601,5610,5598,5609,5649,5696,5750,5830,5926,5997,6039,6086,6150,6207,6254,6323,6418,6495,6531,
+6575,6663,6757,6808,6837,6876,6896,6885,6934,7127,7341,7327,7023,6639,6388,6260,6162,6137,6278,6511,6631,
+6570,6473,6494,6629,6795,6948,7070,7132,7143,7165,7225,7262,7226,7173,7188,7255,7293,7279,7266,7283,7287,
+7237,7151,7074,7025,7002,6997,6993,6971,6936,6912,6906,6896,6873,6851,6841,6831,6810,6790,6781,6778,6769,
+6756,6744,6730,6710,6693,6686,6687,6687,6691,6704,6723,6738,6739,6721,6689,6653,6625,6601,6570,6533,6502,
+6482,6463,6441,6424,6414,6399,6371,6342,6328,6323,6310,6285,6262,6253,6256,6253,6224,6162,6087,6021,5965,
+5898,5824,5765,5732,5696,5634,5562,5507,5467,5423,5381,5361,5352,5330,5301,5302,5341,5378,5390,5400,5439,
+5489,5505,5472,5416,5364,5325,5307,5319,5347,5352,5300,5197,5083,5000,4964,4961,4959,4931,4875,4812,4763,
+4733,4712,4684,4639,4580,4512,4432,4340,4251,4187,4157,4141,4117,4077,4029,3971,3904,3836,3782,3740,3700,
+3653,3605,3560,3510,3455,3408,3375,3347,3306,3253,3202,3164,3129,3086,3036,3001,2991,2990,2969,2916,2856,
+2823,2820,2819,2798,2752,2681,2591,2518,2513,2582,2651,2638,2546,2456,2421,2418,2403,2380,2371,2362,2313,
+2226,2155,2134,2138,2116,2056,1991,1947,1928,1922,1919,1913,1898,1877,1853,1827,1800,1774,1752,1733,1721,
+1721,1732,1735,1716,1685,1659,1644,1632,1623,1631,1662,1696,1715,1716,1708,1694,1672,1642,1610,1579,1546,
+1514,1488,1467,1445,1419,1394,1377,1372,1378,1390,1404,1411,1404,1388,1367,1347,1327,1312,1306,1311,1323,
+1339,1355,1369,1378,1376,1369,1364,1371,1387,1402,1403,1394,1384,1382,1390,1406,1424,1445,1470,1501,1538,
+1572,1600,1627,1655,1681,1696,1698,1695,1685,1665,1637,1616,1617,1642,1683,1734,1782,1809,1797,1755,1715,
+1702,1711,1716,1700,1666,1629,1600,1581,1565,1547,1525,1501,1478,1455,1434,1417,1405,1396,1382,1358,1327,
+1295,1267,1241,1214,1185,1158,1138,1122,1103,1076,1046,1020,995,969,941,915,888,856,819,780,744,
+709,674,646,626,612,598,577,552,527,502,476,447,414,384,358,334,306,274,241,206,166,
+122,80,43,10,-22,-56,-92,-131,-175,-219,-260,-298,-337,-377,-418,-458,-499,-544,-592,-638,-681,
+-724,-768,-814,-857,-898,-939,-984,-1029,-1068,-1104,-1142,-1187,-1233,-1275,-1311,-1346,-1383,-1419,-1455,-1493,-1532,
+-1570,-1605,-1635,-1665,-1698,-1736,-1773,-1805,-1832,-1862,-1894,-1926,-1954,-1981,-2011,-2040,-2068,-2097,-2130,-2160,-2186,
+-2211,-2243,-2279,-2314,-2343,-2371,-2400,-2430,-2460,-2490,-2521,-2551,-2581,-2610,-2636,-2661,-2684,-2707,-2728,-2745,-2762,
+-2781,-2799,-2815,-2832,-2851,-2865,-2870,-2871,-2876,-2885,-2893,-2897,-2902,-2906,-2904,-2897,-2892,-2893,-2896,-2894,-2887,
+-2879,-2870,-2858,-2844,-2829,-2812,-2796,-2784,-2772,-2758,-2739,-2720,-2704,-2688,-2674,-2659,-2644,-2624,-2601,-2581,-2562,
+-2540,-2514,-2488,-2463,-2436,-2410,-2385,-2363,-2339,-2315,-2292,-2269,-2240,-2208,-2178,-2152,-2125,-2094,-2064,-2036,-2010,
+-1983,-1956,-1929,-1902,-1874,-1848,-1823,-1793,-1762,-1734,-1708,-1678,-1643,-1612,-1586,-1557,-1523,-1491,-1462,-1432,-1398,
+-1365,-1338,-1312,-1282,-1252,-1225,-1200,-1173,-1147,-1126,-1102,-1071,-1039,-1012,-990,-966,-943,-922,-901,-874,-843,
+-810,-778,-742,-706,-675,-649,-626,-603,-574,-538,-499,-465,-436,-409,-382,-355,-327,-294,-258,-226,-199,
+-169,-135,-106,-87,-69,-40,2,55,111,159,192,216,247,284,308,316,328,354,383,409,445,
+498,556,605,653,707,755,786,821,878,943,997,1051,1126,1204,1253,1275,1298,1327,1340,1335,1335,
+1336,1301,1218,1128,1076,1065,1079,1130,1266,1526,1898,2302,2608,2708,2589,2323,2017,1777,1702,1805,1950,
+1938,1708,1414,1240,1203,1176,1075,937,825,747,681,624,584,554,523,478,400,280,149,59,23,
+-3,-56,-129,-188,-232,-284,-361,-462,-575,-678,-731,-708,-639,-592,-614,-678,-725,-727,-715,-739,-807,
+-888,-957,-1028,-1117,-1219,-1306,-1365,-1405,-1442,-1480,-1516,-1550,-1594,-1660,-1751,-1851,-1939,-2011,-2079,-2153,-2227,
+-2292,-2346,-2392,-2431,-2477,-2554,-2665,-2780,-2871,-2949,-3037,-3128,-3184,-3188,-3167,-3158,-3163,-3167,-3169,-3173,-3177,
+-3168,-3140,-3105,-3089,-3111,-3164,-3221,-3261,-3284,-3299,-3300,-3278,-3235,-3179,-3107,-3020,-2934,-2881,-2869,-2885,-2912,
+-2944,-2974,-2999,-3028,-3075,-3131,-3166,-3166,-3142,-3110,-3064,-3002,-2942,-2900,-2871,-2838,-2798,-2753,-2697,-2628,-2559,
+-2500,-2443,-2372,-2290,-2217,-2159,-2103,-2041,-1977,-1917,-1857,-1796,-1732,-1666,-1594,-1518,-1447,-1380,-1312,-1243,-1175,
+-1108,-1039,-969,-902,-834,-763,-686,-611,-540,-470,-400,-329,-263,-201,-142,-80,-10,61,125,176,229,
+294,361,414,454,491,529,558,578,602,639,683,721,752,780,806,827,845,863,882,900,921,
+944,966,985,1002,1023,1053,1087,1119,1141,1153,1160,1169,1182,1197,1215,1240,1269,1298,1324,1350,1378,
+1405,1426,1444,1464,1486,1507,1526,1541,1550,1553,1555,1560,1573,1592,1616,1639,1656,1667,1676,1687,1698,
+1712,1732,1761,1795,1827,1855,1877,1890,1894,1896,1907,1929,1953,1975,1998,2026,2052,2068,2071,2069,2074,
+2092,2122,2154,2173,2169,2152,2146,2172,2227,2283,2322,2340,2347,2347,2341,2324,2294,2251,2210,2190,2193,
+2203,2202,2189,2172,2151,2118,2071,2013,1945,1874,1828,1835,1888,1940,1954,1934,1904,1878,1850,1820,1791,
+1768,1748,1736,1736,1708,1707,1699,1686,1673,1657,1626,1586,1550,1526,1511,1500,1490,1480,1466,1458,1471,
+1511,1568,1632,1706,1789,1872,1938,1975,1981,1961,1925,1879,1821,1752,1700,1708,1782,1870,1898,1850,1776,
+1720,1665,1568,1435,1335,1314,1349,1370,1338,1270,1197,1132,1070,1007,944,882,828,787,753,711,659,
+610,575,539,480,398,316,252,207,177,149,99,2,-135,-278,-393,-480,-550,-613,-669,-722,-779,
+-838,-893,-944,-993,-1036,-1069,-1089,-1105,-1119,-1132,-1141,-1144,-1137,-1125,-1116,-1113,-1111,-1107,-1103,-1098,-1092,
+-1083,-1080,-1085,-1093,-1095,-1096,-1101,-1108,-1111,-1114,-1119,-1123,-1120,-1113,-1100,-1080,-1063,-1074,-1120,-1173,-1194,
+-1193,-1208,-1259,-1320,-1364,-1382,-1378,-1347,-1295,-1250,-1233,-1232,-1220,-1202,-1210,-1266,-1353,-1428,-1467,-1489,-1528,
+-1595,-1656,-1677,-1669,-1685,-1748,-1818,-1840,-1816,-1800,-1830,-1892,-1947,-1983,-2025,-2101,-2208,-2321,-2414,-2490,-2564,
+-2647,-2732,-2812,-2890,-2968,-3035,-3070,-3068,-3040,-3008,-2989,-3002,-3050,-3125,-3211,-3304,-3400,-3495,-3581,-3655,-3717,
+-3760,-3783,-3804,-3861,-3981,-4157,-4353,-4527,-4657,-4744,-4804,-4843,-4867,-4894,-4947,-5026,-5099,-5142,-5176,-5234,-5309,
+-5353,-5334,-5266,-5194,-5160,-5183,-5248,-5311,-5330,-5303,-5275,-5282,-5317,-5353,-5383,-5420,-5469,-5518,-5557,-5594,-5637,
+-5688,-5741,-5789,-5828,-5860,-5893,-5937,-5988,-6038,-6086,-6135,-6188,-6241,-6295,-6352,-6415,-6477,-6537,-6599,-6663,-6724,
+-6778,-6828,-6881,-6941,-7007,-7078,-7152,-7224,-7291,-7358,-7429,-7508,-7592,-7678,-7765,-7851,-7938,-8025,-8114,-8206,-8298,
+-8387,-8470,-8552,-8641,-8736,-8832,-8925,-9012,-9089,-9151,-9200,-9254,-9326,-9416,-9502,-9568,-9614,-9658,-9710,-9756,-9763,
+-9714,-9636,-9589,-9622,-9732,-9861,-9952,-9989,-10002,-10032,-10092,-10167,-10230,-10271,-10299,-10326,-10360,-10396,-10427,-10442,-10435,
+-10412,-10396,-10404,-10436,-10478,-10514,-10533,-10530,-10512,-10492,-10479,-10467,-10446,-10414,-10375,-10332,-10281,-10222,-10159,-10090,-10011,
+-9922,-9823,-9715,-9597,-9481,-9378,-9286,-9188,-9076,-8960,-8840,-8707,-8563,-8422,-8295,-8162,-8002,-7821,-7644,-7481,-7325,
+-7166,-7004,-6845,-6693,-6550,-6406,-6233,-6018,-5800,-5643,-5565,-5518,-5443,-5332,-5216,-5124,-5063,-5039,-5039,-5012,-4905,
+-4718,-4512,-4340,-4213,-4118,-4053,-4007,-3931,-3780,-3566,-3361,-3207,-3062,-2851,-2564,-2278,-2074,-1960,-1880,-1791,-1688,
+-1583,-1473,-1348,-1212,-1082,-965,-859,-760,-665,-569,-463,-350,-241,-145,-66,2,69,138,211,279,339,
+401,477,569,671,775,880,985,1091,1206,1331,1455,1562,1653,1746,1847,1943,2016,2071,2126,2196,2277,
+2363,2450,2537,2624,2709,2794,2882,2974,3073,3174,3267,3355,3445,3545,3658,3789,3951,4138,4316,4456,4564,
+4661,4749,4811,4866,4967,5137,5322,5451,5512,5544,5564,5555,5522,5513,5547,5583,5578,5557,5574,5630,5688,
+5738,5806,5892,5958,5996,6037,6102,6168,6222,6290,6385,6471,6522,6567,6637,6712,6764,6817,6888,6930,6919,
+6951,7121,7321,7297,6964,6527,6227,6091,6025,6024,6158,6379,6527,6531,6489,6517,6632,6792,6963,7104,7170,
+7174,7190,7249,7289,7264,7230,7258,7320,7340,7309,7291,7312,7320,7272,7186,7104,7048,7021,7015,7012,6990,
+6957,6937,6934,6927,6907,6888,6879,6869,6851,6834,6821,6802,6780,6768,6767,6758,6735,6714,6710,6717,6724,
+6732,6748,6765,6775,6773,6757,6727,6689,6655,6628,6594,6554,6521,6502,6484,6458,6436,6426,6417,6395,6370,
+6357,6354,6343,6318,6289,6271,6268,6263,6232,6167,6094,6042,6005,5950,5866,5782,5726,5683,5627,5563,5510,
+5465,5419,5383,5378,5389,5379,5348,5337,5369,5414,5436,5443,5465,5499,5515,5497,5453,5409,5380,5378,5396,
+5409,5389,5324,5227,5122,5036,4989,4980,4984,4965,4912,4845,4790,4756,4732,4699,4654,4603,4549,4483,4396,
+4299,4222,4178,4149,4115,4073,4032,3990,3940,3881,3827,3783,3743,3696,3643,3591,3538,3488,3445,3411,3377,
+3331,3272,3215,3171,3136,3095,3048,3010,2999,3003,2988,2943,2890,2857,2845,2832,2806,2766,2704,2618,2556,
+2578,2682,2766,2736,2606,2483,2434,2433,2424,2405,2397,2389,2345,2262,2185,2155,2157,2146,2101,2038,1986,
+1959,1951,1948,1940,1927,1912,1893,1869,1839,1812,1791,1773,1760,1760,1770,1773,1756,1726,1698,1677,1659,
+1647,1651,1675,1702,1719,1721,1711,1694,1671,1649,1629,1606,1578,1549,1525,1502,1474,1441,1409,1387,1380,
+1385,1398,1409,1413,1411,1402,1385,1363,1343,1331,1327,1328,1332,1339,1351,1367,1383,1392,1390,1382,1384,
+1397,1412,1414,1405,1397,1398,1408,1421,1435,1452,1474,1501,1532,1560,1583,1606,1634,1663,1683,1691,1695,
+1700,1696,1678,1656,1645,1653,1677,1715,1766,1811,1824,1795,1743,1701,1688,1693,1695,1680,1650,1620,1598,
+1580,1560,1537,1511,1484,1458,1435,1419,1411,1404,1394,1378,1357,1332,1304,1274,1242,1208,1179,1158,1141,
+1120,1088,1052,1020,995,971,945,920,897,871,842,810,779,750,722,698,680,665,648,624,595,
+568,543,516,484,448,414,385,359,329,295,260,223,184,141,99,63,32,3,-28,-63,-103,
+-147,-191,-231,-269,-309,-351,-392,-432,-472,-516,-563,-611,-656,-699,-743,-788,-833,-874,-913,-953,-993,
+-1030,-1063,-1099,-1142,-1187,-1228,-1264,-1301,-1340,-1378,-1413,-1450,-1489,-1530,-1567,-1599,-1629,-1661,-1696,-1730,-1762,
+-1791,-1822,-1854,-1884,-1912,-1941,-1972,-2003,-2032,-2063,-2098,-2131,-2158,-2184,-2216,-2252,-2285,-2314,-2342,-2372,-2401,
+-2430,-2460,-2491,-2521,-2548,-2573,-2597,-2620,-2642,-2664,-2685,-2705,-2724,-2744,-2764,-2781,-2798,-2817,-2833,-2843,-2845,
+-2847,-2852,-2857,-2863,-2870,-2876,-2876,-2869,-2864,-2863,-2862,-2859,-2853,-2845,-2835,-2822,-2808,-2793,-2778,-2762,-2748,
+-2736,-2721,-2703,-2685,-2670,-2657,-2642,-2626,-2608,-2588,-2567,-2550,-2534,-2514,-2489,-2462,-2437,-2411,-2385,-2360,-2338,
+-2315,-2292,-2271,-2250,-2224,-2193,-2162,-2135,-2109,-2079,-2047,-2018,-1991,-1965,-1939,-1913,-1887,-1862,-1839,-1815,-1787,
+-1758,-1732,-1707,-1677,-1645,-1615,-1590,-1562,-1530,-1500,-1474,-1445,-1410,-1376,-1349,-1325,-1299,-1272,-1246,-1219,-1189,
+-1162,-1142,-1121,-1093,-1063,-1038,-1015,-988,-959,-934,-910,-880,-844,-807,-772,-738,-703,-670,-641,-616,-593,
+-569,-537,-500,-466,-438,-411,-382,-354,-327,-295,-261,-233,-211,-186,-152,-119,-98,-82,-56,-17,31,
+80,120,148,169,197,231,258,273,290,319,354,390,434,486,533,572,616,674,727,759,793,
+856,938,1005,1053,1104,1163,1211,1240,1264,1292,1310,1315,1311,1285,1215,1126,1078,1105,1166,1214,1272,
+1417,1695,2069,2441,2703,2770,2618,2303,1960,1738,1713,1822,1895,1801,1577,1379,1314,1338,1333,1245,1114,
+992,894,810,740,687,648,618,578,499,375,241,152,115,89,36,-30,-83,-120,-167,-249,-367,
+-504,-625,-694,-694,-647,-607,-619,-674,-721,-723,-695,-688,-733,-813,-895,-977,-1075,-1185,-1281,-1341,-1373,
+-1398,-1429,-1471,-1521,-1585,-1664,-1753,-1840,-1912,-1973,-2036,-2105,-2174,-2236,-2294,-2349,-2401,-2461,-2544,-2649,-2751,
+-2831,-2901,-2985,-3071,-3120,-3118,-3091,-3074,-3078,-3092,-3109,-3122,-3128,-3116,-3084,-3044,-3022,-3041,-3095,-3156,-3199,
+-3219,-3225,-3217,-3195,-3166,-3135,-3085,-3007,-2921,-2865,-2850,-2859,-2879,-2907,-2940,-2971,-3004,-3050,-3104,-3136,-3132,
+-3103,-3067,-3024,-2972,-2918,-2872,-2834,-2796,-2762,-2729,-2681,-2616,-2548,-2493,-2442,-2374,-2293,-2218,-2157,-2099,-2037,
+-1974,-1913,-1851,-1790,-1729,-1664,-1591,-1513,-1441,-1374,-1306,-1233,-1162,-1095,-1031,-965,-896,-825,-754,-682,-612,
+-541,-469,-397,-326,-259,-196,-138,-80,-15,51,111,159,211,281,360,425,470,506,539,564,581,
+602,635,677,717,750,775,796,813,829,848,868,888,909,930,950,969,988,1011,1040,1070,1097,
+1116,1129,1140,1151,1165,1179,1198,1220,1244,1266,1290,1317,1346,1372,1392,1412,1434,1457,1480,1501,1519,
+1530,1534,1536,1542,1553,1568,1590,1614,1635,1650,1660,1667,1672,1681,1700,1730,1764,1796,1823,1844,1855,
+1855,1856,1867,1889,1913,1934,1958,1987,2018,2041,2054,2063,2073,2089,2107,2121,2124,2108,2084,2076,2103,
+2157,2211,2243,2247,2233,2213,2193,2175,2157,2136,2115,2102,2100,2100,2096,2088,2079,2063,2033,1985,1925,
+1855,1789,1754,1772,1825,1869,1876,1851,1815,1782,1757,1741,1733,1725,1714,1707,1708,1681,1680,1673,1666,
+1660,1646,1619,1588,1566,1552,1538,1522,1503,1476,1442,1418,1423,1455,1500,1551,1614,1689,1762,1818,1857,
+1878,1876,1846,1796,1733,1668,1628,1640,1700,1751,1743,1688,1646,1640,1621,1535,1405,1311,1298,1328,1330,
+1279,1209,1148,1094,1028,949,870,803,750,710,673,625,565,505,459,415,358,286,214,157,114,
+81,53,11,-63,-171,-288,-391,-479,-560,-636,-706,-772,-841,-910,-973,-1030,-1086,-1143,-1194,-1225,-1232,
+-1222,-1214,-1215,-1217,-1209,-1191,-1177,-1172,-1167,-1158,-1145,-1136,-1129,-1123,-1120,-1121,-1119,-1116,-1118,-1126,-1133,
+-1135,-1135,-1136,-1135,-1130,-1124,-1111,-1082,-1050,-1052,-1102,-1161,-1182,-1178,-1204,-1282,-1370,-1419,-1422,-1399,-1365,
+-1326,-1293,-1276,-1268,-1258,-1252,-1270,-1323,-1399,-1470,-1512,-1530,-1555,-1606,-1661,-1682,-1674,-1687,-1753,-1835,-1878,
+-1878,-1884,-1929,-1995,-2048,-2081,-2117,-2176,-2259,-2350,-2436,-2515,-2590,-2662,-2728,-2791,-2861,-2941,-3014,-3054,-3053,
+-3027,-2996,-2984,-3008,-3068,-3151,-3236,-3321,-3414,-3517,-3611,-3682,-3726,-3754,-3784,-3837,-3937,-4092,-4283,-4474,-4629,
+-4739,-4814,-4874,-4920,-4949,-4967,-4996,-5045,-5094,-5127,-5156,-5203,-5257,-5274,-5233,-5162,-5116,-5126,-5183,-5253,-5296,
+-5296,-5271,-5261,-5283,-5322,-5354,-5383,-5425,-5479,-5531,-5572,-5608,-5647,-5688,-5730,-5772,-5818,-5865,-5911,-5955,-5999,
+-6044,-6095,-6152,-6208,-6259,-6307,-6361,-6422,-6485,-6548,-6613,-6680,-6744,-6801,-6855,-6909,-6967,-7030,-7097,-7164,-7228,
+-7291,-7357,-7431,-7507,-7583,-7661,-7743,-7825,-7905,-7987,-8075,-8172,-8268,-8358,-8442,-8528,-8624,-8726,-8825,-8915,-8995,
+-9065,-9126,-9184,-9249,-9327,-9414,-9492,-9554,-9603,-9651,-9706,-9758,-9777,-9739,-9657,-9591,-9604,-9704,-9836,-9934,-9975,
+-9993,-10031,-10097,-10172,-10231,-10271,-10299,-10328,-10361,-10397,-10426,-10437,-10422,-10393,-10369,-10365,-10382,-10410,-10443,-10468,-10474,
+-10462,-10448,-10440,-10433,-10413,-10380,-10342,-10303,-10255,-10195,-10131,-10065,-9988,-9897,-9796,-9689,-9581,-9479,-9389,-9309,-9218,
+-9102,-8964,-8820,-8677,-8541,-8417,-8299,-8169,-8012,-7840,-7673,-7512,-7350,-7181,-7016,-6856,-6702,-6554,-6407,-6239,-6031,
+-5813,-5648,-5562,-5514,-5442,-5330,-5209,-5109,-5038,-4995,-4975,-4951,-4881,-4745,-4562,-4363,-4175,-4017,-3906,-3826,-3734,
+-3593,-3423,-3281,-3189,-3105,-2966,-2754,-2511,-2281,-2073,-1877,-1699,-1560,-1464,-1378,-1269,-1137,-1013,-915,-830,-740,
+-640,-539,-439,-334,-226,-125,-43,23,91,171,256,334,403,475,563,662,761,858,958,1059,1163,
+1277,1405,1532,1637,1720,1802,1898,1999,2085,2151,2209,2272,2344,2424,2509,2596,2683,2769,2853,2942,3040,
+3146,3245,3327,3403,3495,3610,3737,3873,4030,4207,4372,4499,4602,4710,4816,4892,4945,5028,5174,5341,5466,
+5538,5583,5607,5586,5531,5496,5509,5533,5528,5515,5540,5601,5658,5701,5760,5840,5907,5946,5986,6053,6126,
+6185,6248,6334,6423,6491,6548,6612,6675,6728,6795,6882,6938,6940,6972,7120,7286,7232,6864,6365,5996,5834,
+5800,5839,5963,6144,6297,6385,6453,6546,6665,6809,6981,7142,7225,7228,7229,7271,7311,7309,7303,7341,7390,
+7387,7339,7311,7326,7335,7299,7228,7153,7092,7054,7041,7035,7016,6988,6970,6962,6948,6927,6914,6909,6899,
+6880,6865,6855,6840,6822,6813,6810,6795,6765,6744,6745,6757,6765,6773,6788,6802,6805,6800,6786,6757,6716,
+6678,6648,6618,6582,6551,6531,6510,6482,6458,6446,6439,6423,6402,6384,6374,6364,6349,6330,6312,6299,6285,
+6250,6186,6118,6079,6056,5998,5888,5777,5715,5692,5658,5598,5533,5477,5425,5390,5394,5425,5436,5410,5387,
+5404,5450,5484,5491,5488,5491,5496,5488,5463,5432,5415,5423,5441,5435,5390,5316,5232,5145,5063,5005,4986,
+4989,4976,4931,4868,4811,4772,4740,4703,4657,4611,4566,4512,4435,4341,4256,4196,4155,4115,4074,4039,4010,
+3974,3926,3872,3824,3780,3733,3681,3626,3572,3527,3488,3453,3412,3360,3300,3240,3192,3156,3120,3078,3040,
+3020,3015,3004,2974,2938,2911,2888,2858,2824,2791,2737,2658,2606,2651,2779,2866,2808,2637,2484,2426,2430,
+2430,2415,2406,2399,2363,2292,2222,2185,2173,2156,2116,2064,2019,1993,1984,1979,1969,1954,1940,1926,1907,
+1880,1853,1830,1811,1800,1798,1802,1800,1787,1765,1742,1718,1695,1678,1676,1686,1701,1713,1715,1705,1684,
+1660,1642,1631,1619,1600,1577,1550,1523,1494,1464,1434,1406,1388,1385,1395,1404,1408,1408,1403,1391,1371,
+1353,1346,1346,1345,1343,1343,1348,1360,1377,1392,1396,1391,1389,1397,1407,1406,1400,1405,1423,1440,1448,
+1448,1452,1466,1490,1520,1547,1564,1578,1598,1627,1653,1670,1681,1690,1692,1682,1665,1656,1659,1672,1695,
+1733,1782,1819,1819,1779,1725,1689,1681,1687,1687,1673,1651,1627,1603,1577,1552,1526,1498,1466,1439,1424,
+1417,1411,1401,1391,1379,1362,1335,1299,1260,1221,1189,1165,1148,1128,1098,1064,1033,1008,986,962,939,
+920,901,879,853,827,802,778,756,736,716,692,662,628,596,567,539,506,468,433,404,379,
+350,315,277,238,198,156,114,77,47,19,-8,-41,-80,-121,-162,-201,-241,-284,-328,-370,-409,
+-446,-486,-532,-581,-629,-672,-714,-759,-806,-851,-890,-926,-963,-998,-1031,-1066,-1105,-1146,-1185,-1221,-1260,
+-1300,-1337,-1370,-1405,-1444,-1485,-1524,-1559,-1592,-1626,-1660,-1693,-1724,-1755,-1787,-1819,-1848,-1874,-1904,-1937,-1969,
+-1999,-2030,-2063,-2096,-2124,-2152,-2184,-2220,-2253,-2282,-2311,-2342,-2371,-2400,-2430,-2461,-2488,-2511,-2534,-2557,-2582,
+-2604,-2625,-2646,-2666,-2685,-2705,-2726,-2744,-2759,-2776,-2793,-2805,-2810,-2811,-2814,-2821,-2830,-2840,-2848,-2849,-2845,
+-2839,-2834,-2828,-2821,-2815,-2810,-2802,-2789,-2774,-2759,-2744,-2728,-2713,-2700,-2684,-2667,-2650,-2637,-2624,-2607,-2589,
+-2571,-2552,-2534,-2518,-2503,-2483,-2456,-2430,-2406,-2384,-2361,-2338,-2316,-2293,-2269,-2247,-2227,-2204,-2176,-2146,-2120,
+-2094,-2063,-2030,-1999,-1972,-1948,-1923,-1899,-1875,-1852,-1828,-1804,-1779,-1753,-1728,-1704,-1677,-1647,-1620,-1594,-1566,
+-1535,-1508,-1483,-1455,-1422,-1389,-1362,-1339,-1313,-1288,-1263,-1236,-1205,-1176,-1154,-1132,-1107,-1081,-1059,-1036,-1006,
+-971,-937,-907,-875,-839,-802,-769,-739,-709,-679,-647,-617,-590,-566,-539,-506,-475,-447,-419,-389,-360,
+-333,-304,-271,-245,-225,-203,-169,-133,-106,-85,-56,-16,23,54,78,98,120,148,183,214,237,
+256,284,322,366,416,465,502,533,579,644,704,737,768,831,922,997,1039,1073,1119,1169,1207,
+1235,1265,1292,1299,1275,1213,1129,1077,1110,1218,1325,1385,1443,1596,1878,2233,2569,2801,2854,2684,2341,
+1982,1775,1768,1850,1864,1754,1593,1491,1479,1497,1475,1397,1285,1163,1046,943,862,801,754,714,665,
+586,473,358,275,227,187,136,83,39,0,-55,-146,-272,-416,-547,-635,-669,-660,-642,-649,-684,
+-716,-707,-663,-636,-666,-746,-841,-939,-1048,-1163,-1256,-1309,-1333,-1355,-1389,-1434,-1487,-1552,-1632,-1719,-1800,
+-1867,-1926,-1989,-2060,-2131,-2197,-2258,-2316,-2372,-2434,-2517,-2616,-2707,-2775,-2837,-2910,-2985,-3030,-3034,-3018,-3011,
+-3024,-3049,-3075,-3092,-3094,-3080,-3053,-3021,-3004,-3019,-3061,-3108,-3139,-3153,-3153,-3137,-3113,-3099,-3096,-3076,-3018,
+-2940,-2886,-2869,-2871,-2878,-2897,-2930,-2968,-3006,-3050,-3096,-3119,-3108,-3073,-3033,-2991,-2941,-2891,-2844,-2800,-2758,
+-2722,-2687,-2642,-2581,-2521,-2472,-2426,-2367,-2296,-2227,-2167,-2108,-2047,-1984,-1920,-1854,-1790,-1730,-1667,-1595,-1516,
+-1442,-1375,-1307,-1232,-1158,-1089,-1025,-959,-890,-818,-748,-680,-613,-544,-471,-399,-330,-263,-199,-138,-77,
+-12,54,112,159,211,283,365,434,479,511,540,565,585,605,635,674,712,744,769,787,804,
+821,841,862,881,900,918,935,953,974,1000,1028,1054,1075,1091,1106,1121,1137,1151,1164,1180,1199,
+1219,1239,1262,1291,1319,1339,1354,1371,1392,1417,1444,1472,1495,1506,1506,1501,1501,1507,1522,1547,1577,
+1605,1627,1642,1654,1663,1674,1691,1714,1739,1763,1785,1802,1811,1812,1816,1830,1855,1883,1909,1938,1972,
+2006,2034,2053,2067,2078,2088,2095,2097,2090,2069,2046,2041,2068,2118,2162,2179,2169,2145,2118,2096,2081,
+2069,2057,2042,2028,2021,2018,2015,2009,2000,1980,1948,1906,1857,1806,1762,1745,1764,1800,1824,1822,1801,
+1773,1746,1726,1718,1715,1706,1692,1682,1681,1661,1661,1657,1656,1655,1645,1626,1608,1595,1580,1557,1532,
+1507,1477,1442,1423,1433,1459,1484,1510,1554,1613,1666,1704,1740,1773,1786,1759,1703,1641,1593,1572,1582,
+1605,1607,1573,1532,1525,1544,1531,1456,1358,1302,1304,1316,1289,1228,1172,1134,1091,1020,923,825,744,
+682,633,589,538,476,410,349,292,232,169,109,58,15,-18,-47,-80,-138,-225,-327,-425,-515,
+-603,-691,-776,-856,-935,-1013,-1086,-1154,-1220,-1289,-1353,-1392,-1392,-1362,-1330,-1315,-1307,-1293,-1273,-1257,-1248,
+-1235,-1214,-1192,-1179,-1173,-1167,-1161,-1155,-1150,-1146,-1150,-1158,-1161,-1160,-1160,-1160,-1156,-1148,-1144,-1130,-1087,
+-1032,-1018,-1072,-1143,-1170,-1165,-1196,-1293,-1404,-1460,-1448,-1406,-1369,-1346,-1332,-1316,-1296,-1281,-1288,-1325,-1383,
+-1447,-1504,-1540,-1555,-1568,-1604,-1650,-1673,-1669,-1683,-1751,-1843,-1908,-1935,-1961,-2010,-2067,-2112,-2145,-2184,-2238,
+-2303,-2376,-2455,-2533,-2606,-2670,-2726,-2780,-2846,-2922,-2990,-3024,-3021,-3001,-2985,-2991,-3030,-3103,-3194,-3283,-3368,
+-3460,-3559,-3646,-3703,-3736,-3770,-3830,-3927,-4064,-4231,-4410,-4573,-4700,-4786,-4845,-4898,-4950,-4991,-5007,-5010,-5020,
+-5046,-5082,-5125,-5169,-5197,-5186,-5135,-5084,-5077,-5123,-5195,-5251,-5270,-5260,-5246,-5254,-5284,-5319,-5348,-5381,-5429,
+-5486,-5538,-5579,-5615,-5651,-5683,-5714,-5752,-5803,-5863,-5921,-5969,-6011,-6054,-6106,-6165,-6221,-6270,-6318,-6372,-6432,
+-6494,-6558,-6624,-6691,-6757,-6820,-6880,-6938,-6996,-7059,-7126,-7191,-7247,-7301,-7364,-7438,-7513,-7583,-7653,-7727,-7803,
+-7877,-7954,-8041,-8137,-8234,-8325,-8413,-8506,-8608,-8713,-8812,-8900,-8975,-9042,-9106,-9174,-9251,-9334,-9414,-9486,-9546,
+-9599,-9650,-9703,-9754,-9782,-9753,-9672,-9594,-9593,-9689,-9825,-9922,-9958,-9976,-10023,-10101,-10181,-10238,-10273,-10301,-10329,
+-10361,-10394,-10420,-10426,-10407,-10374,-10347,-10337,-10343,-10363,-10392,-10417,-10426,-10418,-10408,-10407,-10406,-10390,-10357,-10318,-10278,
+-10228,-10167,-10104,-10040,-9968,-9878,-9779,-9682,-9590,-9501,-9414,-9323,-9216,-9083,-8932,-8780,-8638,-8510,-8396,-8287,-8167,
+-8026,-7870,-7710,-7549,-7378,-7202,-7030,-6862,-6697,-6538,-6386,-6225,-6032,-5822,-5650,-5551,-5497,-5431,-5327,-5209,-5107,
+-5029,-4970,-4923,-4883,-4831,-4746,-4612,-4428,-4215,-4008,-3832,-3679,-3521,-3353,-3208,-3119,-3080,-3047,-2978,-2861,-2702,
+-2497,-2236,-1932,-1639,-1421,-1296,-1220,-1134,-1026,-927,-861,-808,-732,-626,-512,-409,-311,-208,-106,-20,49,
+119,202,295,382,463,548,647,751,847,935,1024,1117,1219,1334,1464,1594,1702,1785,1861,1947,2043,
+2138,2220,2290,2354,2422,2498,2582,2666,2750,2834,2921,3011,3110,3215,3314,3395,3475,3577,3708,3842,3968,
+4098,4240,4377,4490,4599,4733,4880,4995,5068,5139,5244,5367,5474,5558,5627,5661,5633,5558,5496,5481,5485,
+5471,5450,5462,5511,5569,5623,5688,5766,5832,5875,5920,5987,6062,6124,6183,6258,6342,6417,6486,6563,6642,
+6712,6783,6859,6918,6949,7005,7130,7234,7127,6732,6201,5779,5586,5583,5684,5835,5999,6155,6311,6478,6631,
+6743,6849,7000,7170,7273,7283,7270,7295,7335,7355,7371,7409,7442,7424,7370,7337,7339,7341,7312,7256,7192,
+7131,7086,7067,7060,7048,7029,7013,6997,6974,6950,6941,6938,6921,6895,6878,6876,6875,6868,6862,6853,6829,
+6800,6786,6793,6802,6802,6805,6817,6829,6831,6824,6810,6779,6733,6691,6663,6639,6611,6583,6562,6541,6516,
+6493,6478,6467,6453,6436,6417,6397,6384,6379,6374,6359,6338,6316,6281,6215,6143,6108,6098,6046,5923,5794,
+5733,5730,5713,5651,5574,5513,5463,5428,5428,5463,5486,5467,5434,5435,5477,5524,5542,5530,5510,5497,5486,
+5469,5444,5432,5443,5458,5440,5378,5297,5221,5152,5082,5027,5001,4997,4986,4948,4892,4833,4780,4734,4692,
+4651,4611,4572,4527,4464,4380,4293,4224,4176,4138,4101,4066,4032,3996,3954,3906,3859,3815,3770,3718,3660,
+3606,3565,3533,3499,3453,3395,3334,3277,3228,3190,3154,3112,3068,3038,3028,3023,3008,2988,2968,2938,2898,
+2861,2834,2786,2702,2635,2662,2772,2847,2785,2622,2484,2441,2452,2452,2431,2413,2398,2366,2311,2255,2216,
+2187,2155,2118,2081,2050,2027,2015,2007,1995,1977,1961,1948,1937,1920,1898,1874,1855,1841,1834,1830,1825,
+1817,1805,1788,1762,1732,1707,1695,1693,1697,1703,1706,1699,1680,1659,1643,1634,1627,1614,1592,1562,1529,
+1503,1486,1465,1432,1400,1385,1389,1397,1400,1400,1399,1391,1375,1362,1360,1362,1361,1356,1353,1353,1358,
+1367,1380,1388,1389,1390,1397,1399,1392,1389,1408,1445,1477,1486,1477,1467,1467,1481,1506,1532,1547,1552,
+1562,1585,1614,1639,1656,1668,1672,1667,1657,1655,1665,1678,1692,1712,1748,1792,1819,1808,1764,1715,1685,
+1677,1678,1676,1667,1650,1625,1596,1570,1545,1515,1479,1448,1430,1423,1415,1403,1393,1385,1371,1345,1308,
+1270,1234,1202,1178,1160,1143,1119,1092,1065,1042,1019,996,974,957,940,920,896,871,847,824,800,
+774,748,721,689,654,620,588,558,526,491,456,426,399,369,333,293,252,212,172,132,95,
+64,37,10,-20,-55,-92,-130,-169,-212,-258,-304,-347,-385,-420,-457,-501,-550,-600,-643,-683,-726,
+-774,-822,-862,-897,-933,-970,-1005,-1040,-1076,-1113,-1149,-1187,-1227,-1266,-1300,-1330,-1363,-1402,-1441,-1478,-1512,
+-1547,-1584,-1620,-1654,-1687,-1721,-1756,-1787,-1815,-1841,-1871,-1904,-1937,-1967,-1994,-2024,-2055,-2084,-2114,-2148,-2184,
+-2217,-2247,-2278,-2310,-2339,-2367,-2396,-2427,-2453,-2474,-2496,-2522,-2548,-2570,-2591,-2611,-2631,-2650,-2669,-2689,-2707,
+-2721,-2732,-2746,-2758,-2765,-2769,-2775,-2785,-2799,-2812,-2820,-2821,-2818,-2812,-2804,-2795,-2787,-2782,-2779,-2773,-2759,
+-2741,-2723,-2707,-2692,-2678,-2664,-2650,-2633,-2618,-2604,-2590,-2572,-2554,-2537,-2520,-2503,-2487,-2470,-2447,-2420,-2393,
+-2373,-2355,-2335,-2314,-2293,-2271,-2247,-2224,-2203,-2182,-2157,-2130,-2105,-2079,-2048,-2013,-1981,-1954,-1930,-1908,-1887,
+-1867,-1843,-1818,-1793,-1770,-1747,-1723,-1699,-1674,-1649,-1624,-1598,-1570,-1540,-1514,-1489,-1462,-1431,-1401,-1375,-1350,
+-1323,-1295,-1270,-1243,-1213,-1185,-1161,-1138,-1113,-1089,-1068,-1045,-1014,-976,-938,-903,-869,-836,-804,-773,-744,
+-716,-690,-661,-629,-599,-573,-546,-515,-484,-457,-432,-403,-373,-346,-318,-289,-262,-242,-220,-187,-151,
+-123,-98,-64,-22,11,29,40,55,77,107,143,180,209,231,257,292,337,387,432,467,500,
+549,617,678,713,744,807,898,975,1014,1039,1082,1137,1183,1216,1247,1272,1265,1212,1130,1072,1094,
+1209,1364,1480,1539,1613,1786,2065,2386,2673,2864,2885,2688,2330,1987,1820,1838,1907,1907,1831,1750,1709,
+1690,1660,1608,1537,1440,1315,1182,1070,991,932,881,829,766,682,582,488,415,357,305,257,216,
+175,123,48,-54,-183,-325,-454,-552,-610,-631,-632,-641,-669,-695,-684,-637,-604,-629,-706,-804,-906,
+-1016,-1124,-1206,-1247,-1268,-1297,-1340,-1391,-1443,-1503,-1578,-1664,-1748,-1821,-1887,-1954,-2026,-2098,-2167,-2233,-2293,
+-2346,-2402,-2475,-2560,-2637,-2694,-2745,-2806,-2870,-2916,-2935,-2941,-2952,-2977,-3012,-3044,-3062,-3063,-3053,-3039,-3025,
+-3018,-3025,-3044,-3063,-3077,-3086,-3085,-3067,-3041,-3036,-3056,-3066,-3033,-2973,-2928,-2912,-2904,-2893,-2897,-2929,-2978,
+-3028,-3076,-3115,-3128,-3107,-3065,-3019,-2972,-2921,-2868,-2820,-2775,-2730,-2688,-2647,-2600,-2542,-2486,-2438,-2393,-2342,
+-2285,-2229,-2173,-2115,-2055,-1994,-1930,-1861,-1794,-1732,-1670,-1600,-1524,-1451,-1382,-1312,-1239,-1164,-1092,-1023,-954,
+-885,-816,-747,-681,-618,-554,-486,-416,-349,-285,-219,-154,-87,-18,51,111,159,211,280,359,428,
+474,506,536,566,592,616,643,674,707,735,757,777,798,821,842,860,877,894,912,928,945,
+967,992,1019,1044,1063,1079,1094,1110,1127,1139,1149,1161,1178,1197,1219,1245,1273,1295,1307,1314,1324,
+1343,1370,1403,1438,1465,1475,1469,1458,1454,1460,1479,1509,1544,1575,1598,1613,1625,1635,1645,1658,1675,
+1693,1713,1733,1753,1767,1776,1786,1805,1834,1866,1899,1933,1965,1994,2014,2029,2040,2049,2057,2066,2074,
+2075,2063,2043,2036,2054,2087,2110,2109,2091,2068,2050,2037,2028,2019,2006,1987,1969,1957,1953,1951,1945,
+1931,1907,1879,1854,1832,1814,1799,1795,1802,1808,1804,1792,1776,1760,1741,1723,1713,1704,1689,1671,1662,
+1661,1654,1656,1656,1659,1661,1655,1641,1629,1615,1590,1557,1526,1504,1481,1459,1454,1471,1489,1495,1499,
+1525,1565,1597,1619,1648,1684,1699,1671,1614,1560,1532,1527,1532,1522,1485,1434,1405,1415,1430,1408,1348,
+1296,1286,1297,1286,1238,1181,1145,1125,1087,1008,898,786,691,616,557,506,454,394,324,251,182,
+121,66,18,-26,-68,-105,-134,-165,-216,-296,-393,-488,-575,-663,-760,-862,-958,-1044,-1124,-1201,-1275,
+-1349,-1428,-1504,-1553,-1551,-1505,-1450,-1412,-1390,-1371,-1353,-1339,-1323,-1296,-1261,-1234,-1221,-1214,-1204,-1193,-1187,
+-1185,-1188,-1194,-1196,-1190,-1184,-1187,-1192,-1187,-1176,-1170,-1151,-1096,-1023,-998,-1051,-1125,-1149,-1135,-1168,-1286,
+-1424,-1493,-1473,-1412,-1367,-1356,-1359,-1348,-1319,-1297,-1312,-1362,-1419,-1464,-1500,-1529,-1549,-1566,-1597,-1637,-1657,
+-1655,-1671,-1740,-1838,-1917,-1962,-2004,-2057,-2108,-2143,-2171,-2213,-2269,-2332,-2400,-2471,-2544,-2615,-2680,-2740,-2796,
+-2858,-2925,-2979,-3001,-2994,-2981,-2984,-3009,-3061,-3143,-3241,-3337,-3426,-3514,-3601,-3671,-3717,-3757,-3822,-3923,-4055,
+-4206,-4364,-4518,-4654,-4760,-4828,-4868,-4903,-4952,-5003,-5023,-5005,-4979,-4985,-5030,-5091,-5133,-5138,-5109,-5068,-5050,
+-5076,-5138,-5203,-5240,-5244,-5234,-5232,-5250,-5281,-5313,-5345,-5386,-5437,-5490,-5535,-5574,-5611,-5645,-5672,-5697,-5732,
+-5784,-5849,-5914,-5969,-6017,-6063,-6115,-6172,-6227,-6278,-6329,-6385,-6444,-6504,-6566,-6632,-6701,-6768,-6834,-6897,-6957,
+-7017,-7083,-7156,-7223,-7276,-7322,-7378,-7447,-7518,-7584,-7650,-7718,-7787,-7856,-7930,-8014,-8106,-8200,-8293,-8388,-8488,
+-8592,-8694,-8791,-8878,-8953,-9021,-9089,-9166,-9252,-9338,-9416,-9485,-9546,-9600,-9647,-9692,-9739,-9772,-9755,-9680,-9601,
+-9597,-9694,-9829,-9918,-9941,-9952,-10002,-10091,-10177,-10234,-10268,-10295,-10325,-10356,-10386,-10409,-10416,-10400,-10370,-10342,-10327,
+-10328,-10344,-10370,-10393,-10401,-10391,-10381,-10381,-10384,-10372,-10344,-10307,-10266,-10215,-10156,-10097,-10039,-9971,-9887,-9794,-9710,
+-9632,-9546,-9442,-9321,-9184,-9037,-8887,-8743,-8607,-8480,-8364,-8261,-8157,-8037,-7895,-7736,-7567,-7391,-7211,-7030,-6849,
+-6668,-6498,-6348,-6202,-6033,-5840,-5667,-5555,-5491,-5427,-5331,-5218,-5119,-5042,-4972,-4898,-4826,-4767,-4712,-4632,-4497,
+-4307,-4090,-3870,-3646,-3412,-3192,-3034,-2957,-2935,-2923,-2899,-2858,-2782,-2632,-2370,-2011,-1632,-1330,-1152,-1062,-990,
+-909,-841,-807,-782,-720,-612,-489,-381,-287,-190,-90,1,79,154,239,333,427,517,610,713,819,
+916,1001,1081,1167,1267,1385,1516,1645,1757,1846,1921,1997,2081,2175,2269,2351,2420,2489,2566,2649,2728,
+2806,2893,2987,3081,3175,3274,3374,3468,3566,3685,3824,3953,4057,4151,4252,4358,4464,4590,4760,4951,5110,
+5209,5275,5340,5414,5491,5574,5656,5701,5681,5609,5540,5503,5479,5439,5387,5360,5380,5441,5519,5598,5668,
+5724,5772,5829,5899,5969,6031,6094,6167,6244,6313,6381,6469,6575,6674,6751,6814,6879,6953,7045,7135,7146,
+6970,6572,6062,5631,5421,5450,5636,5868,6071,6247,6436,6636,6786,6856,6906,7020,7181,7294,7316,7304,7320,
+7359,7386,7407,7438,7459,7442,7400,7372,7366,7355,7319,7267,7209,7153,7111,7090,7083,7075,7065,7054,7037,
+7011,6988,6981,6975,6952,6920,6900,6898,6898,6893,6885,6873,6852,6832,6828,6837,6838,6830,6828,6839,6852,
+6857,6854,6840,6807,6759,6715,6686,6663,6637,6609,6586,6565,6547,6530,6512,6493,6477,6468,6456,6433,6414,
+6413,6415,6398,6369,6347,6315,6239,6148,6110,6127,6113,6007,5868,5794,5786,5765,5694,5613,5560,5522,5487,
+5475,5499,5524,5512,5478,5469,5502,5551,5582,5582,5561,5536,5513,5487,5456,5435,5439,5454,5442,5384,5300,
+5224,5161,5106,5061,5036,5025,5009,4975,4923,4856,4783,4718,4673,4643,4614,4580,4539,4486,4414,4332,4260,
+4210,4177,4144,4102,4053,4007,3965,3926,3887,3849,3806,3755,3695,3640,3601,3576,3543,3491,3428,3368,3315,
+3270,3231,3191,3142,3090,3054,3044,3046,3041,3028,3012,2985,2944,2906,2878,2830,2738,2644,2626,2691,2751,
+2718,2613,2530,2512,2523,2513,2479,2443,2409,2366,2320,2282,2250,2210,2163,2123,2097,2077,2056,2039,2027,
+2015,1998,1977,1962,1953,1944,1932,1916,1899,1883,1869,1857,1850,1846,1839,1822,1791,1754,1725,1708,1700,
+1699,1703,1707,1704,1693,1677,1663,1651,1638,1622,1599,1565,1530,1510,1507,1496,1463,1420,1393,1388,1392,
+1392,1393,1395,1391,1382,1375,1377,1381,1378,1371,1367,1364,1361,1362,1370,1380,1386,1391,1397,1395,1383,
+1380,1405,1454,1500,1520,1516,1503,1490,1486,1496,1516,1533,1539,1541,1554,1577,1603,1626,1645,1657,1661,
+1658,1660,1673,1692,1704,1711,1727,1761,1800,1817,1796,1750,1704,1674,1660,1655,1653,1648,1633,1610,1585,
+1560,1530,1493,1458,1436,1423,1412,1398,1388,1380,1367,1344,1314,1286,1260,1234,1209,1188,1170,1151,1129,
+1105,1081,1057,1034,1013,995,977,954,928,902,879,855,828,798,767,739,709,678,646,615,587,
+556,522,486,452,420,388,352,311,270,231,194,158,123,89,59,30,1,-30,-64,-99,-140,
+-185,-233,-279,-322,-360,-394,-430,-470,-518,-568,-612,-651,-693,-740,-788,-829,-865,-902,-943,-981,-1016,
+-1050,-1084,-1121,-1160,-1199,-1235,-1265,-1293,-1326,-1364,-1401,-1433,-1464,-1499,-1537,-1575,-1612,-1648,-1685,-1720,-1751,
+-1779,-1806,-1836,-1870,-1904,-1932,-1957,-1983,-2013,-2045,-2079,-2114,-2149,-2181,-2211,-2243,-2275,-2305,-2332,-2361,-2391,
+-2418,-2440,-2463,-2490,-2517,-2539,-2558,-2578,-2599,-2618,-2635,-2654,-2671,-2683,-2691,-2699,-2710,-2719,-2727,-2737,-2751,
+-2767,-2779,-2786,-2787,-2785,-2780,-2773,-2764,-2757,-2753,-2752,-2746,-2731,-2710,-2690,-2673,-2659,-2646,-2633,-2618,-2601,
+-2585,-2572,-2556,-2538,-2520,-2504,-2489,-2472,-2453,-2433,-2410,-2384,-2361,-2344,-2328,-2310,-2289,-2270,-2251,-2228,-2204,
+-2182,-2161,-2138,-2114,-2089,-2062,-2030,-1995,-1964,-1937,-1912,-1891,-1874,-1857,-1836,-1811,-1787,-1766,-1745,-1721,-1695,
+-1672,-1650,-1628,-1603,-1576,-1548,-1521,-1495,-1466,-1437,-1409,-1384,-1358,-1328,-1298,-1269,-1241,-1213,-1185,-1160,-1137,
+-1113,-1089,-1065,-1039,-1008,-973,-937,-902,-869,-840,-813,-784,-751,-721,-697,-673,-644,-614,-587,-559,-526,
+-493,-468,-447,-421,-390,-360,-334,-308,-283,-262,-238,-207,-174,-149,-126,-94,-53,-20,-4,4,18,
+41,70,107,148,184,211,238,272,313,356,398,437,477,526,586,642,682,720,783,870,945,
+986,1016,1062,1123,1173,1205,1227,1234,1202,1129,1059,1057,1152,1312,1467,1572,1652,1776,1985,2251,2518,
+2739,2868,2836,2605,2252,1956,1847,1893,1963,1973,1947,1930,1914,1867,1795,1728,1668,1579,1447,1304,1192,
+1117,1062,1013,960,891,801,705,622,554,491,431,382,340,292,226,141,33,-94,-232,-358,-454,
+-515,-542,-552,-573,-618,-662,-667,-630,-602,-625,-695,-780,-869,-967,-1064,-1133,-1166,-1185,-1215,-1262,-1316,
+-1372,-1435,-1513,-1603,-1696,-1781,-1859,-1933,-2005,-2074,-2142,-2209,-2271,-2323,-2373,-2434,-2505,-2568,-2614,-2656,-2708,
+-2766,-2814,-2846,-2869,-2896,-2930,-2969,-3004,-3024,-3030,-3030,-3031,-3032,-3029,-3024,-3018,-3011,-3009,-3017,-3020,-3003,
+-2975,-2973,-3007,-3042,-3038,-3001,-2970,-2956,-2936,-2906,-2894,-2922,-2983,-3055,-3118,-3160,-3165,-3132,-3080,-3026,-2974,
+-2919,-2864,-2812,-2764,-2715,-2667,-2619,-2569,-2514,-2457,-2403,-2353,-2306,-2260,-2213,-2161,-2105,-2049,-1994,-1934,-1865,
+-1795,-1729,-1666,-1601,-1532,-1462,-1391,-1318,-1246,-1174,-1099,-1023,-950,-882,-816,-748,-684,-627,-571,-511,-446,
+-381,-317,-251,-183,-112,-40,30,92,144,197,263,337,406,459,500,537,573,605,632,654,677,
+702,725,746,767,791,818,840,857,874,893,915,935,954,974,997,1021,1046,1067,1082,1095,1107,
+1120,1130,1139,1150,1165,1183,1204,1228,1251,1267,1272,1274,1282,1301,1330,1366,1401,1424,1428,1420,1412,
+1413,1425,1448,1480,1513,1539,1555,1561,1560,1557,1558,1568,1586,1611,1637,1665,1693,1717,1736,1753,1773,
+1801,1835,1870,1904,1932,1952,1965,1974,1983,1993,2007,2027,2052,2072,2077,2067,2056,2058,2066,2063,2044,
+2019,2000,1991,1987,1982,1973,1956,1931,1906,1890,1885,1885,1883,1875,1861,1849,1846,1852,1859,1862,1860,
+1850,1829,1802,1780,1766,1752,1733,1713,1698,1684,1668,1654,1650,1654,1659,1665,1669,1675,1678,1669,1654,
+1639,1620,1589,1553,1527,1513,1501,1490,1492,1506,1514,1506,1500,1515,1539,1553,1561,1579,1603,1608,1582,
+1542,1507,1488,1483,1482,1462,1414,1358,1329,1332,1333,1306,1269,1259,1277,1281,1243,1180,1129,1105,1088,
+1048,971,866,755,656,576,510,452,394,326,246,163,90,36,-5,-42,-83,-126,-164,-197,-233,
+-290,-374,-472,-565,-645,-728,-832,-952,-1067,-1160,-1234,-1300,-1366,-1437,-1520,-1606,-1665,-1668,-1616,-1546,-1491,
+-1459,-1440,-1429,-1418,-1396,-1357,-1314,-1288,-1277,-1267,-1250,-1235,-1231,-1235,-1241,-1244,-1239,-1226,-1217,-1222,-1229,
+-1220,-1200,-1183,-1161,-1109,-1041,-1017,-1059,-1110,-1105,-1076,-1117,-1263,-1432,-1519,-1497,-1423,-1370,-1363,-1378,-1377,
+-1351,-1331,-1352,-1405,-1451,-1472,-1485,-1508,-1537,-1566,-1600,-1634,-1645,-1636,-1646,-1710,-1804,-1885,-1943,-2004,-2078,
+-2140,-2171,-2187,-2217,-2272,-2343,-2419,-2493,-2563,-2631,-2702,-2769,-2830,-2887,-2942,-2983,-2997,-2990,-2985,-2999,-3036,
+-3096,-3182,-3284,-3382,-3469,-3550,-3624,-3686,-3739,-3810,-3917,-4054,-4199,-4340,-4477,-4611,-4735,-4835,-4898,-4924,-4942,
+-4981,-5033,-5054,-5018,-4960,-4944,-4990,-5057,-5094,-5085,-5057,-5041,-5054,-5097,-5153,-5201,-5225,-5229,-5226,-5233,-5253,
+-5280,-5312,-5350,-5395,-5443,-5487,-5525,-5561,-5597,-5630,-5656,-5680,-5712,-5760,-5822,-5890,-5955,-6012,-6066,-6120,-6177,
+-6233,-6286,-6340,-6396,-6452,-6511,-6575,-6644,-6713,-6778,-6842,-6904,-6964,-7023,-7092,-7170,-7243,-7300,-7346,-7398,-7459,
+-7525,-7588,-7653,-7720,-7783,-7846,-7916,-7996,-8083,-8171,-8265,-8368,-8474,-8577,-8675,-8768,-8855,-8932,-9003,-9077,-9159,
+-9249,-9336,-9414,-9481,-9542,-9595,-9637,-9675,-9719,-9756,-9752,-9689,-9616,-9611,-9703,-9831,-9910,-9924,-9928,-9979,-10069,
+-10156,-10213,-10248,-10279,-10312,-10344,-10373,-10396,-10407,-10400,-10377,-10349,-10328,-10323,-10337,-10363,-10388,-10395,-10384,-10370,-10366,
+-10366,-10358,-10336,-10303,-10264,-10218,-10165,-10113,-10060,-9996,-9916,-9829,-9750,-9675,-9581,-9454,-9303,-9145,-8995,-8858,-8728,
+-8596,-8462,-8338,-8238,-8148,-8042,-7900,-7731,-7554,-7379,-7202,-7016,-6821,-6629,-6458,-6318,-6190,-6046,-5878,-5718,-5599,
+-5518,-5440,-5339,-5228,-5133,-5060,-4988,-4895,-4788,-4698,-4643,-4597,-4517,-4378,-4193,-3979,-3738,-3473,-3219,-3025,-2912,
+-2857,-2825,-2805,-2795,-2767,-2661,-2429,-2076,-1676,-1332,-1105,-977,-891,-818,-768,-752,-738,-685,-584,-465,-357,
+-264,-172,-77,17,106,193,283,378,474,568,662,763,870,972,1060,1137,1218,1317,1436,1564,1689,
+1801,1898,1980,2051,2124,2210,2304,2392,2467,2539,2620,2703,2778,2854,2947,3054,3156,3246,3336,3438,3546,
+3657,3780,3910,4024,4107,4176,4252,4343,4454,4607,4811,5033,5213,5325,5388,5433,5476,5528,5595,5668,5716,
+5714,5670,5612,5564,5519,5459,5378,5302,5278,5327,5421,5509,5567,5615,5679,5757,5830,5887,5940,6004,6079,
+6149,6203,6257,6339,6456,6575,6664,6731,6821,6949,7071,7113,7021,6780,6407,5961,5562,5354,5413,5685,6020,
+6297,6507,6697,6863,6951,6953,6951,7034,7179,7291,7327,7329,7348,7378,7393,7403,7425,7445,7439,7417,7402,
+7397,7377,7333,7276,7222,7177,7144,7123,7109,7096,7085,7078,7066,7045,7028,7021,7012,6990,6964,6946,6938,
+6926,6911,6900,6890,6877,6865,6862,6865,6863,6856,6857,6867,6878,6884,6885,6873,6841,6797,6758,6728,6699,
+6666,6635,6608,6586,6572,6562,6544,6517,6498,6498,6495,6473,6451,6450,6453,6431,6396,6377,6345,6251,6130,
+6089,6151,6202,6134,5986,5877,5837,5798,5720,5642,5600,5572,5536,5512,5525,5550,5551,5531,5522,5539,5572,
+5600,5615,5609,5586,5554,5519,5477,5440,5428,5442,5446,5408,5333,5252,5185,5137,5103,5080,5062,5038,5003,
+4952,4876,4786,4705,4658,4637,4617,4586,4546,4500,4441,4369,4299,4247,4211,4176,4129,4073,4019,3977,3943,
+3913,3881,3844,3797,3740,3686,3650,3626,3591,3534,3466,3406,3358,3317,3279,3237,3183,3123,3081,3068,3069,
+3064,3054,3045,3029,2993,2948,2907,2853,2763,2661,2612,2642,2694,2697,2649,2605,2593,2594,2579,2544,2495,
+2434,2370,2324,2304,2286,2243,2183,2133,2109,2097,2080,2060,2044,2031,2014,1992,1971,1954,1945,1940,1937,
+1929,1914,1895,1880,1873,1868,1858,1836,1805,1771,1743,1724,1716,1715,1720,1724,1721,1712,1702,1688,1670,
+1648,1626,1600,1568,1537,1524,1527,1523,1492,1446,1412,1398,1391,1385,1385,1391,1392,1387,1387,1396,1404,
+1401,1390,1381,1374,1366,1363,1370,1381,1389,1393,1397,1396,1387,1383,1402,1445,1491,1522,1537,1537,1524,
+1504,1496,1509,1532,1546,1547,1545,1552,1570,1593,1619,1643,1659,1664,1666,1677,1696,1713,1718,1721,1741,
+1779,1810,1811,1783,1746,1710,1678,1651,1635,1631,1629,1617,1594,1567,1538,1505,1471,1442,1420,1403,1389,
+1380,1374,1365,1350,1333,1317,1301,1280,1254,1228,1206,1186,1165,1139,1112,1085,1062,1042,1023,1002,976,
+947,921,899,877,850,819,786,756,727,700,673,647,619,589,555,518,480,445,411,376,337,
+297,258,223,188,151,114,78,45,14,-15,-46,-82,-123,-168,-214,-257,-296,-334,-369,-404,-442,
+-487,-535,-580,-621,-662,-708,-755,-798,-837,-877,-920,-959,-993,-1025,-1059,-1097,-1136,-1173,-1204,-1231,-1258,
+-1290,-1328,-1364,-1395,-1425,-1458,-1494,-1532,-1570,-1608,-1644,-1677,-1707,-1736,-1766,-1799,-1834,-1868,-1897,-1920,-1945,
+-1976,-2012,-2050,-2085,-2117,-2146,-2175,-2207,-2240,-2271,-2298,-2326,-2356,-2383,-2408,-2433,-2461,-2487,-2506,-2524,-2545,
+-2567,-2586,-2601,-2617,-2634,-2646,-2652,-2659,-2668,-2679,-2690,-2703,-2717,-2731,-2741,-2746,-2748,-2746,-2742,-2737,-2732,
+-2727,-2724,-2723,-2717,-2702,-2682,-2661,-2645,-2631,-2619,-2605,-2588,-2569,-2552,-2537,-2522,-2504,-2487,-2471,-2455,-2436,
+-2416,-2396,-2375,-2353,-2334,-2320,-2306,-2287,-2266,-2247,-2230,-2209,-2184,-2160,-2140,-2119,-2096,-2070,-2041,-2009,-1977,
+-1949,-1924,-1899,-1876,-1859,-1846,-1829,-1807,-1785,-1767,-1747,-1723,-1697,-1673,-1653,-1632,-1608,-1582,-1556,-1529,-1501,
+-1471,-1441,-1412,-1386,-1361,-1333,-1303,-1272,-1242,-1213,-1184,-1157,-1132,-1110,-1086,-1058,-1028,-997,-967,-937,-905,
+-874,-849,-828,-801,-767,-733,-707,-684,-657,-630,-604,-576,-542,-508,-483,-464,-439,-406,-375,-350,-327,
+-303,-280,-256,-226,-195,-172,-154,-129,-95,-63,-43,-28,-10,12,39,74,115,154,187,220,257,
+295,332,371,415,461,505,551,600,647,694,755,832,906,959,1002,1057,1120,1168,1192,1196,1178,
+1128,1059,1026,1079,1210,1363,1491,1601,1739,1937,2176,2410,2609,2761,2830,2751,2504,2182,1946,1881,1928,
+1978,1990,1999,2021,2017,1959,1883,1830,1788,1706,1574,1432,1320,1240,1178,1130,1086,1024,936,837,752,
+681,613,547,489,433,371,298,215,113,-11,-147,-267,-351,-396,-411,-419,-457,-534,-615,-647,-630,
+-613,-639,-700,-767,-836,-918,-1004,-1069,-1098,-1109,-1126,-1163,-1219,-1287,-1363,-1450,-1544,-1642,-1738,-1828,-1911,
+-1985,-2051,-2114,-2179,-2243,-2298,-2348,-2403,-2465,-2519,-2560,-2600,-2649,-2704,-2751,-2787,-2819,-2852,-2889,-2928,-2962,
+-2984,-2995,-3004,-3015,-3021,-3015,-2997,-2972,-2949,-2941,-2950,-2958,-2943,-2915,-2912,-2953,-3003,-3021,-3007,-2990,-2979,
+-2952,-2909,-2881,-2900,-2966,-3056,-3143,-3201,-3210,-3171,-3108,-3047,-2992,-2939,-2884,-2829,-2773,-2714,-2656,-2602,-2551,
+-2497,-2440,-2382,-2325,-2275,-2229,-2184,-2133,-2079,-2029,-1979,-1923,-1856,-1785,-1716,-1651,-1591,-1533,-1471,-1401,-1326,
+-1254,-1184,-1109,-1029,-953,-886,-824,-760,-699,-647,-599,-543,-480,-415,-350,-283,-212,-141,-69,0,63,
+120,177,241,311,381,444,495,540,580,615,642,662,679,700,723,745,766,789,815,838,857,
+875,899,924,947,966,983,1003,1024,1046,1068,1083,1093,1100,1109,1120,1132,1144,1157,1169,1183,1199,
+1216,1228,1233,1237,1247,1268,1298,1330,1354,1362,1356,1349,1350,1362,1382,1406,1433,1458,1477,1487,1488,
+1479,1465,1459,1469,1495,1527,1560,1591,1620,1646,1669,1689,1711,1739,1773,1811,1849,1881,1907,1928,1946,
+1962,1975,1990,2009,2037,2065,2082,2080,2067,2054,2040,2016,1983,1954,1937,1931,1927,1921,1911,1892,1865,
+1838,1820,1818,1827,1840,1851,1858,1865,1878,1893,1903,1903,1891,1868,1834,1800,1775,1758,1739,1714,1691,
+1676,1665,1654,1647,1651,1659,1672,1680,1688,1694,1692,1678,1658,1640,1619,1590,1563,1549,1546,1541,1533,
+1532,1534,1527,1512,1508,1517,1525,1523,1522,1529,1534,1529,1524,1526,1519,1490,1454,1436,1427,1400,1352,
+1315,1300,1288,1266,1252,1265,1282,1264,1201,1127,1074,1044,1018,978,917,835,742,652,573,504,437,
+363,277,179,85,17,-21,-44,-73,-114,-162,-206,-247,-297,-366,-458,-559,-649,-725,-805,-913,-1046,
+-1174,-1271,-1334,-1381,-1427,-1485,-1564,-1654,-1722,-1737,-1694,-1625,-1565,-1528,-1512,-1509,-1505,-1484,-1445,-1405,-1382,
+-1370,-1353,-1330,-1313,-1306,-1302,-1295,-1287,-1279,-1267,-1259,-1262,-1263,-1245,-1212,-1182,-1160,-1125,-1083,-1069,-1089,
+-1096,-1053,-1014,-1073,-1245,-1432,-1526,-1504,-1431,-1379,-1376,-1398,-1409,-1400,-1398,-1431,-1483,-1514,-1512,-1505,-1517,
+-1545,-1578,-1614,-1644,-1646,-1621,-1614,-1662,-1747,-1827,-1897,-1984,-2092,-2181,-2219,-2220,-2226,-2268,-2344,-2437,-2524,
+-2597,-2664,-2733,-2802,-2859,-2907,-2952,-2990,-3007,-3006,-3007,-3025,-3067,-3133,-3224,-3325,-3419,-3500,-3575,-3649,-3720,
+-3799,-3906,-4047,-4198,-4336,-4458,-4577,-4700,-4820,-4922,-4989,-5015,-5027,-5055,-5098,-5107,-5050,-4966,-4928,-4964,-5026,
+-5056,-5047,-5033,-5042,-5074,-5115,-5155,-5190,-5213,-5225,-5233,-5243,-5259,-5282,-5314,-5353,-5397,-5438,-5474,-5509,-5546,
+-5582,-5613,-5639,-5664,-5694,-5737,-5793,-5862,-5933,-5999,-6060,-6122,-6185,-6245,-6298,-6347,-6396,-6451,-6513,-6582,-6654,
+-6720,-6781,-6841,-6902,-6962,-7022,-7090,-7167,-7244,-7309,-7365,-7419,-7476,-7535,-7599,-7667,-7733,-7790,-7846,-7912,-7989,
+-8070,-8152,-8243,-8348,-8459,-8564,-8659,-8749,-8834,-8912,-8988,-9067,-9152,-9241,-9327,-9403,-9469,-9526,-9577,-9619,-9658,
+-9701,-9741,-9747,-9700,-9636,-9627,-9705,-9818,-9890,-9904,-9913,-9964,-10050,-10132,-10187,-10223,-10257,-10293,-10327,-10357,-10381,
+-10396,-10398,-10384,-10358,-10332,-10320,-10330,-10357,-10383,-10393,-10385,-10371,-10362,-10356,-10347,-10327,-10296,-10260,-10219,-10176,-10130,
 -10080,-10016,-9935,-9848,-9766,-9682,-9577,-9439,-9278,-9120,-8980,-8855,-8732,-8599,-8460,-8334,-8235,-8148,-8037,-7883,-7700,
 -7520,-7356,-7191,-7007,-6807,-6615,-6451,-6320,-6200,-6068,-5922,-5785,-5673,-5577,-5473,-5351,-5230,-5136,-5067,-4996,-4893,
 -4760,-4635,-4553,-4510,-4459,-4364,-4221,-4051,-3857,-3634,-3397,-3185,-3022,-2905,-2819,-2765,-2739,-2709,-2617,-2416,-2106,
@@ -24229,25261 +24199,25244 @@ static short s_egm96grid[] = {
 -7235,-7308,-7374,-7434,-7489,-7545,-7611,-7685,-7751,-7802,-7851,-7913,-7989,-8066,-8141,-8227,-8329,-8441,-8548,-8645,-8732,
 -8813,-8892,-8974,-9059,-9144,-9230,-9312,-9387,-9449,-9503,-9554,-9602,-9644,-9684,-9721,-9735,-9708,-9660,-9649,-9705,-9795,
 -9858,-9880,-9901,-9957,-10040,-10116,-10168,-10205,-10239,-10275,-10310,-10340,-10365,-10381,-10389,-10385,-10367,-10341,-10325,-10330,-10352,
--10374,
--10384,-10382,-10373,-10363,-10354,-10340,-10317,-10284,-10247,-10211,-10174,-10132,-10079,-10009,-9924,-9833,-9745,-9655,-9547,-9414,-9265,
--9122,
--8993,-8871,-8744,-8609,-8475,-8356,-8255,-8155,-8025,-7855,-7666,-7492,-7343,-7193,-7020,-6829,-6647,-6492,-6357,-6220,-6076,
--5941,-5832,-5743,-5646,-5518,-5370,-5233,-5132,-5059,-4985,-4878,-4735,-4584,-4470,-4401,-4344,-4258,-4140,-4013,-3887,-3745,
--3574,-3387,-3207,-3043,-2898,-2782,-2703,-2637,-2537,-2359,-2102,-1804,-1517,-1264,-1045,-863,-740,-688,-677,-656,-593,
--498,-393,-287,-185,-95,-16,65,164,273,377,472,565,659,755,855,964,1074,1171,1252,1333,1429,
-1541,1656,1767,1876,1984,2084,2166,2235,2307,2389,2475,2560,2649,2745,2837,2917,2999,3106,3231,3344,3432,
-3516,3613,3716,3807,3890,3974,4054,4125,4192,4270,4372,4514,4713,4956,5182,5332,5408,5462,5535,5620,5690,
-5733,5758,5783,5810,5817,5779,5708,5643,5592,5513,5388,5277,5262,5342,5446,5536,5640,5768,5871,5905,5892,
-5886,5899,5916,5938,5980,6042,6114,6199,6299,6407,6529,6698,6901,7040,7004,6795,6509,6214,5909,5626,5494,
-5618,5947,6316,6609,6826,6988,7062,7022,6930,6899,6980,7119,7235,7309,7362,7401,7411,7393,7383,7402,7432,
-7442,7433,7428,7430,7416,7371,7312,7265,7237,7214,7186,7158,7139,7129,7120,7108,7097,7086,7069,7047,7027,
-7019,7016,7009,6995,6983,6979,6973,6962,6947,6932,6925,6929,6943,6955,6954,6945,6943,6941,6923,6889,6859,
-6838,6812,6773,6738,6716,6694,6664,6644,6638,6622,6588,6562,6562,6561,6534,6510,6518,6530,6506,6469,6455,
-6415,6277,6100,6055,6195,6356,6346,6174,5997,5900,5839,5765,5700,5668,5641,5601,5576,5587,5614,5626,5629,
-5635,5635,5624,5618,5633,5651,5648,5627,5603,5573,5528,5485,5467,5467,5453,5407,5342,5280,5230,5190,5155,
-5119,5078,5030,4972,4899,4812,4732,4676,4642,4615,4585,4553,4518,4476,4425,4371,4316,4261,4209,4164,4125,
-4084,4041,4000,3966,3939,3912,3881,3844,3807,3776,3747,3706,3647,3581,3522,3469,3424,3389,3356,3309,3240,
-3169,3118,3088,3070,3068,3083,3091,3059,2988,2908,2838,2773,2718,2703,2749,2816,2834,2773,2671,2591,2568,
-2584,2588,2543,2454,2369,2331,2334,2331,2286,2212,2150,2122,2121,2121,2108,2081,2051,2026,2007,1984,1952,
-1924,1914,1920,1924,1918,1907,1903,1903,1897,1885,1878,1877,1869,1842,1803,1772,1759,1758,1757,1750,1736,
-1721,1704,1680,1651,1619,1591,1568,1550,1540,1536,1531,1519,1501,1479,1452,1421,1396,1385,1385,1382,1378,
-1385,1410,1434,1441,1432,1417,1406,1397,1393,1398,1404,1404,1399,1401,1410,1419,1420,1418,1422,1435,1463,
-1500,1532,1542,1529,1515,1525,1554,1576,1573,1552,1534,1532,1541,1555,1574,1595,1617,1634,1652,1673,1694,
-1706,1716,1735,1763,1789,1808,1836,1877,1905,1878,1796,1705,1652,1637,1630,1609,1580,1557,1539,1514,1478,
-1440,1410,1391,1381,1378,1380,1385,1388,1386,1378,1364,1342,1315,1288,1259,1227,1191,1155,1123,1097,1074,
-1053,1033,1010,983,956,932,911,889,861,829,795,764,739,717,695,669,638,605,572,537,501,
-467,434,400,363,324,283,240,194,147,102,62,28,-3,-34,-68,-103,-140,-176,-213,-251,-288,
--325,-364,-404,-446,-488,-528,-568,-610,-655,-703,-751,-797,-841,-882,-916,-947,-977,-1011,-1050,-1088,-1123,
--1151,-1174,-1198,-1228,-1262,-1297,-1332,-1366,-1401,-1435,-1466,-1499,-1534,-1566,-1595,-1624,-1656,-1691,-1725,-1759,-1793,
--1824,-1849,-1877,-1912,-1953,-1991,-2023,-2050,-2079,-2110,-2144,-2179,-2211,-2238,-2264,-2291,-2320,-2347,-2374,-2401,-2425,
--2445,-2464,-2484,-2506,-2522,-2534,-2546,-2561,-2576,-2588,-2597,-2607,-2618,-2630,-2643,-2654,-2660,-2662,-2663,-2665,-2666,
--2665,-2664,-2663,-2661,-2655,-2649,-2643,-2634,-2621,-2605,-2590,-2575,-2559,-2542,-2525,-2506,-2489,-2475,-2461,-2444,-2425,
--2409,-2392,-2374,-2352,-2332,-2315,-2297,-2281,-2266,-2252,-2235,-2214,-2195,-2177,-2157,-2134,-2114,-2097,-2080,-2059,-2033,
--2005,-1976,-1950,-1928,-1907,-1884,-1858,-1838,-1823,-1808,-1791,-1774,-1759,-1741,-1719,-1697,-1678,-1658,-1634,-1608,-1585,
--1562,-1539,-1515,-1489,-1458,-1425,-1397,-1375,-1355,-1332,-1306,-1280,-1253,-1221,-1186,-1153,-1126,-1100,-1072,-1044,-1017,
--995,-974,-950,-924,-899,-877,-853,-825,-796,-766,-735,-701,-669,-644,-620,-590,-555,-522,-495,-468,-439,
--413,-392,-369,-339,-309,-285,-264,-241,-217,-195,-174,-150,-124,-99,-73,-46,-19,9,40,73,103,
-135,175,220,259,288,324,373,423,463,500,548,603,650,693,751,828,904,967,1025,1084,1127,
-1137,1117,1084,1055,1046,1078,1156,1258,1368,1504,1701,1954,2205,2396,2528,2636,2727,2748,2645,2436,2214,
-2065,2001,1969,1941,1938,1980,2039,2063,2043,2017,2008,1992,1939,1852,1754,1653,1548,1453,1382,1324,1254,
-1164,1070,986,909,838,775,713,634,531,422,317,211,97,-14,-102,-154,-163,-136,-110,-143,-257,
--406,-518,-571,-602,-648,-704,-754,-800,-860,-932,-991,-1015,-1006,-995,-1019,-1091,-1192,-1291,-1377,-1462,-1552,
--1641,-1727,-1812,-1897,-1973,-2038,-2102,-2170,-2236,-2296,-2351,-2406,-2456,-2500,-2544,-2594,-2645,-2690,-2728,-2765,-2801,
--2838,-2872,-2900,-2917,-2924,-2928,-2933,-2936,-2928,-2904,-2865,-2824,-2803,-2813,-2839,-2849,-2840,-2838,-2863,-2901,-2926,
--2935,-2940,-2941,-2923,-2885,-2844,-2823,-2839,-2899,-2996,-3099,-3168,-3182,-3151,-3097,-3039,-2982,-2927,-2871,-2807,-2737,
--2667,-2604,-2546,-2491,-2436,-2380,-2323,-2261,-2195,-2130,-2073,-2025,-1980,-1928,-1867,-1802,-1739,-1677,-1616,-1561,-1516,
--1468,-1407,-1336,-1269,-1205,-1137,-1063,-990,-928,-873,-821,-773,-725,-667,-596,-517,-441,-372,-307,-240,-171,
--104,-42,18,80,143,205,265,326,391,454,512,564,608,638,651,658,676,710,747,777,801,
-822,842,863,884,903,916,920,926,942,966,989,1008,1025,1044,1059,1068,1074,1083,1099,1116,1124,
-1123,1122,1129,1142,1154,1157,1155,1155,1166,1189,1211,1219,1214,1211,1224,1251,1279,1298,1309,1314,1314,
-1316,1328,1347,1366,1380,1397,1418,1439,1452,1460,1469,1484,1504,1528,1558,1595,1641,1692,1744,1797,1854,
-1915,1971,2012,2033,2036,2021,1996,1971,1959,1958,1955,1943,1921,1892,1862,1838,1828,1831,1836,1836,1834,
-1833,1828,1818,1807,1806,1818,1843,1876,1907,1928,1935,1931,1921,1902,1875,1843,1811,1782,1758,1739,1721,
-1700,1678,1665,1664,1667,1668,1671,1679,1689,1705,1705,1703,1698,1686,1667,1645,1627,1612,1601,1600,1607,
-1613,1610,1605,1599,1584,1564,1552,1553,1546,1525,1511,1519,1522,1501,1499,1578,1710,1773,1693,1533,1423,
-1406,1424,1415,1380,1345,1315,1287,1269,1264,1250,1204,1135,1065,1005,948,895,853,818,778,728,670,
-606,529,438,336,221,102,4,-43,-49,-54,-95,-170,-249,-319,-389,-472,-564,-656,-743,-824,-905,
--994,-1101,-1218,-1327,-1409,-1461,-1493,-1522,-1562,-1622,-1698,-1769,-1809,-1808,-1772,-1721,-1678,-1661,-1672,-1692,-1701,
--1691,-1674,-1655,-1628,-1593,-1563,-1539,-1504,-1446,-1382,-1345,-1340,-1344,-1340,-1332,-1323,-1303,-1263,-1217,-1181,-1155,
--1137,-1129,-1131,-1124,-1108,-1120,-1198,-1322,-1424,-1459,-1442,-1418,-1410,-1418,-1437,-1464,-1501,-1549,-1598,-1624,-1607,
--1558,-1511,-1486,-1486,-1516,-1578,-1640,-1649,-1595,-1540,-1555,-1639,-1746,-1851,-1972,-2115,-2245,-2320,-2337,-2330,-2340,
--2392,-2481,-2580,-2666,-2736,-2798,-2854,-2896,-2929,-2963,-3002,-3035,-3057,-3074,-3099,-3143,-3214,-3315,-3432,-3542,-3641,
--3740,-3843,-3945,-4049,-4164,-4292,-4416,-4525,-4630,-4740,-4850,-4946,-5026,-5092,-5138,-5160,-5167,-5159,-5117,-5032,-4943,
--4906,-4934,-4989,-5024,-5036,-5044,-5061,-5083,-5106,-5136,-5169,-5195,-5209,-5217,-5228,-5247,-5275,-5306,-5338,-5368,-5396,
--5429,-5466,-5504,-5536,-5563,-5591,-5623,-5661,-5707,-5765,-5834,-5904,-5969,-6035,-6109,-6190,-6262,-6314,-6351,-6391,-6446,
--6512,-6581,-6643,-6700,-6756,-6815,-6879,-6944,-7010,-7081,-7156,-7231,-7304,-7374,-7436,-7490,-7547,-7617,-7695,-7762,-7810,
--7855,-7915,-7988,-8061,-8132,-8213,-8312,-8421,-8529,-8627,-8712,-8790,-8870,-8958,-9049,-9134,-9214,-9293,-9368,-9429,-9481,
--9535,-9589,-9631,-9661,-9687,-9707,-9704,-9680,-9671,-9709,-9775,-9827,-9853,-9885,-9949,-10032,-10105,-10155,-10190,-10222,-10255,
--10290,-10322,-10346,-10362,-10374,-10381,-10375,-10358,-10342,-10342,-10354,-10366,-10370,-10370,-10367,-10361,-10350,-10332,-10305,-10269,-10232,
--10197,
--10162,-10116,-10052,-9971,-9880,-9790,-9707,-9625,-9528,-9410,-9280,-9153,-9029,-8901,-8765,-8631,-8508,-8396,-8286,-8162,-8011,
--7832,-7648,-7483,-7343,-7202,-7043,-6870,-6705,-6555,-6403,-6235,-6065,-5928,-5843,-5784,-5700,-5564,-5400,-5251,-5139,-5052,
--4965,-4853,-4710,-4552,-4413,-4310,-4222,-4118,-3998,-3891,-3807,-3725,-3620,-3491,-3347,-3185,-3001,-2814,-2657,-2539,-2427,
--2276,-2072,-1838,-1600,-1360,-1118,-899,-753,-696,-686,-655,-579,-475,-367,-255,-143,-46,32,110,208,319,
-422,513,602,697,794,896,1004,1112,1209,1294,1382,1480,1588,1697,1805,1914,2023,2125,2215,2292,2366,
-2447,2535,2625,2720,2820,2917,3004,3091,3195,3314,3424,3515,3604,3703,3801,3885,3963,4045,4129,4204,4274,
-4353,4456,4600,4801,5037,5244,5367,5421,5477,5581,5707,5800,5834,5835,5845,5880,5903,5869,5785,5707,5655,
-5582,5453,5324,5291,5367,5493,5628,5779,5928,6013,6009,5972,5956,5947,5919,5901,5939,6022,6101,6168,6254,
-6376,6530,6718,6910,7015,6945,6720,6444,6182,5930,5725,5684,5870,6185,6465,6656,6812,6957,7028,6984,6893,
-6871,6956,7090,7206,7291,7360,7410,7428,7419,7412,7426,7449,7459,7454,7448,7446,7430,7384,7322,7272,7240,
-7212,7181,7157,7150,7149,7140,7125,7116,7112,7099,7073,7046,7029,7020,7014,7011,7012,7010,6999,6986,6979,
-6975,6971,6975,6988,6998,6991,6980,6979,6980,6960,6922,6892,6873,6845,6803,6773,6761,6746,6716,6691,6682,
-6667,6632,6604,6600,6596,6568,6545,6555,6566,6541,6507,6499,6460,6309,6113,6061,6217,6401,6406,6235,6051,
-5946,5878,5800,5736,5709,5690,5658,5638,5650,5665,5657,5644,5649,5660,5658,5655,5668,5686,5684,5667,5650,
-5629,5590,5541,5505,5487,5467,5431,5388,5343,5295,5244,5193,5145,5094,5038,4977,4910,4840,4772,4713,4664,
-4624,4593,4565,4530,4484,4435,4390,4343,4290,4235,4191,4155,4118,4075,4033,3997,3968,3941,3911,3877,3843,
-3811,3778,3737,3684,3625,3567,3512,3465,3430,3402,3361,3290,3204,3131,3084,3063,3066,3083,3088,3054,2983,
-2904,2834,2773,2730,2739,2814,2903,2921,2832,2686,2574,2544,2568,2579,2537,2460,2397,2376,2374,2351,2294,
-2225,2172,2146,2137,2131,2116,2089,2055,2026,2008,1991,1963,1931,1912,1908,1910,1908,1908,1914,1917,1913,
-1907,1914,1927,1924,1892,1843,1800,1775,1766,1761,1754,1741,1724,1705,1684,1657,1626,1596,1574,1557,1540,
-1525,1517,1517,1518,1509,1484,1449,1417,1398,1391,1386,1382,1390,1413,1435,1444,1439,1432,1430,1428,1423,
-1417,1412,1405,1398,1399,1410,1423,1430,1433,1437,1448,1467,1494,1519,1529,1522,1515,1523,1545,1560,1556,
-1541,1533,1539,1546,1549,1551,1562,1583,1611,1639,1665,1683,1694,1707,1732,1760,1778,1789,1822,1885,1940,
-1933,1852,1747,1674,1646,1635,1616,1591,1571,1556,1536,1507,1474,1446,1423,1406,1396,1395,1401,1405,1403,
-1398,1388,1371,1347,1318,1287,1253,1215,1179,1147,1120,1095,1074,1055,1034,1008,979,952,929,905,877,
-845,813,782,755,733,711,685,655,625,594,561,525,490,456,422,387,350,311,269,223,175,
-130,88,51,17,-16,-51,-86,-120,-155,-193,-232,-270,-307,-347,-389,-430,-469,-508,-548,-591,-636,
--683,-730,-775,-817,-854,-887,-917,-947,-983,-1023,-1063,-1098,-1126,-1150,-1173,-1200,-1231,-1265,-1299,-1335,-1370,
--1404,-1435,-1468,-1503,-1537,-1567,-1596,-1629,-1662,-1694,-1724,-1754,-1784,-1811,-1841,-1877,-1917,-1953,-1982,-2011,-2044,
--2079,-2114,-2148,-2180,-2208,-2234,-2262,-2291,-2319,-2345,-2370,-2394,-2416,-2435,-2455,-2475,-2492,-2504,-2516,-2530,-2546,
--2560,-2571,-2582,-2592,-2602,-2614,-2623,-2627,-2625,-2624,-2626,-2628,-2629,-2630,-2630,-2628,-2621,-2615,-2608,-2600,-2588,
--2573,-2558,-2542,-2525,-2510,-2496,-2481,-2466,-2452,-2437,-2420,-2401,-2384,-2369,-2350,-2328,-2308,-2291,-2275,-2257,-2240,
--2223,-2206,-2187,-2168,-2149,-2129,-2110,-2093,-2077,-2059,-2036,-2012,-1989,-1966,-1941,-1917,-1895,-1872,-1850,-1829,-1812,
--1797,-1782,-1766,-1751,-1733,-1713,-1693,-1676,-1657,-1633,-1607,-1584,-1562,-1542,-1521,-1498,-1470,-1440,-1414,-1394,-1375,
--1352,-1328,-1306,-1283,-1254,-1220,-1187,-1156,-1127,-1100,-1076,-1055,-1033,-1011,-989,-966,-940,-913,-885,-858,-829,
--799,-767,-734,-701,-672,-647,-618,-584,-547,-514,-485,-458,-435,-415,-392,-360,-327,-301,-285,-270,-250,
--225,-199,-173,-148,-123,-96,-66,-34,-3,26,56,85,116,155,198,236,267,302,347,395,436,
-476,525,579,627,675,739,817,889,945,998,1054,1094,1095,1069,1049,1054,1083,1131,1202,1303,1445,
-1641,1888,2139,2334,2454,2534,2615,2682,2674,2557,2370,2194,2077,2012,1967,1941,1958,2021,2091,2123,2115,
-2097,2086,2070,2033,1977,1906,1818,1717,1620,1535,1448,1347,1243,1156,1084,1012,942,889,840,764,643,
-498,360,240,135,47,-20,-62,-63,-19,34,25,-88,-267,-427,-528,-587,-639,-693,-744,-793,-848,
--906,-952,-969,-959,-952,-986,-1074,-1183,-1278,-1356,-1436,-1522,-1601,-1671,-1744,-1829,-1914,-1988,-2056,-2129,-2203,
--2267,-2324,-2379,-2431,-2479,-2523,-2569,-2617,-2662,-2703,-2742,-2779,-2814,-2848,-2875,-2890,-2894,-2892,-2892,-2893,-2887,
--2862,-2814,-2758,-2724,-2734,-2773,-2804,-2809,-2807,-2819,-2845,-2870,-2888,-2901,-2904,-2890,-2859,-2822,-2785,-2764,-2779,
--2846,-2950,-3050,-3111,-3124,-3097,-3045,-2983,-2921,-2862,-2801,-2739,-2678,-2620,-2562,-2501,-2442,-2384,-2325,-2261,-2191,
--2122,-2061,-2009,-1959,-1903,-1841,-1781,-1726,-1671,-1613,-1557,-1505,-1451,-1390,-1322,-1256,-1193,-1128,-1059,-992,-931,
--876,-829,-785,-736,-671,-591,-506,-429,-363,-304,-246,-184,-121,-60,0,62,124,183,237,292,355,
-423,490,549,599,629,637,635,645,674,712,749,778,801,819,837,859,880,892,893,897,916,
-949,979,999,1016,1037,1059,1072,1072,1070,1077,1090,1099,1101,1104,1115,1130,1139,1140,1134,1129,1133,
-1152,1175,1191,1199,1214,1245,1282,1309,1319,1318,1309,1295,1284,1287,1304,1326,1345,1363,1380,1390,1394,
-1404,1428,1463,1499,1534,1571,1615,1664,1710,1748,1781,1820,1866,1909,1936,1947,1947,1935,1912,1885,1867,
-1864,1866,1864,1855,1841,1828,1822,1827,1839,1850,1856,1860,1866,1868,1865,1862,1864,1873,1888,1907,1923,
-1928,1920,1906,1889,1868,1841,1812,1784,1757,1734,1714,1700,1688,1678,1676,1680,1685,1688,1692,1699,1705,
-1710,1704,1697,1689,1677,1660,1641,1624,1610,1604,1610,1621,1625,1619,1613,1610,1601,1588,1583,1583,1568,
-1539,1528,1542,1542,1507,1500,1596,1761,1849,1767,1583,1439,1398,1409,1412,1395,1368,1329,1283,1249,1234,
-1218,1176,1116,1056,1002,945,885,831,786,745,704,661,604,524,424,317,204,93,4,-38,-45,
--63,-126,-222,-316,-396,-476,-571,-670,-756,-829,-899,-979,-1073,-1176,-1276,-1363,-1433,-1487,-1532,-1574,-1620,
--1674,-1735,-1793,-1836,-1850,-1830,-1788,-1746,-1729,-1743,-1768,-1785,-1786,-1777,-1756,-1723,-1684,-1653,-1626,-1580,-1505,
--1429,-1384,-1375,-1376,-1368,-1359,-1350,-1330,-1289,-1238,-1195,-1162,-1138,-1132,-1153,-1194,-1237,-1282,-1334,-1384,-1409,
--1408,-1400,-1404,-1413,-1419,-1430,-1459,-1509,-1567,-1609,-1612,-1563,-1484,-1407,-1363,-1365,-1424,-1525,-1612,-1619,-1545,
--1474,-1489,-1594,-1729,-1850,-1965,-2092,-2221,-2324,-2387,-2415,-2431,-2462,-2520,-2599,-2683,-2761,-2828,-2883,-2923,-2956,
--2992,-3035,-3075,-3108,-3135,-3164,-3203,-3270,-3376,-3510,-3650,-3780,-3900,-4007,-4098,-4179,-4270,-4375,-4482,-4581,-4680,
--4784,-4883,-4964,-5027,-5084,-5131,-5155,-5151,-5120,-5061,-4984,-4921,-4905,-4938,-4989,-5025,-5042,-5050,-5058,-5070,-5091,
--5123,-5154,-5172,-5177,-5183,-5201,-5230,-5263,-5293,-5318,-5342,-5368,-5399,-5434,-5465,-5493,-5521,-5555,-5595,-5641,-5695,
--5758,-5829,-5898,-5960,-6022,-6094,-6176,-6252,-6312,-6358,-6403,-6457,-6517,-6576,-6632,-6688,-6747,-6809,-6871,-6932,-6999,
--7076,-7157,-7233,-7302,-7366,-7423,-7479,-7540,-7615,-7694,-7760,-7810,-7856,-7912,-7976,-8043,-8114,-8198,-8296,-8402,-8506,
--8602,-8687,-8764,-8847,-8940,-9033,-9114,-9189,-9268,-9345,-9408,-9462,-9520,-9577,-9614,-9630,-9645,-9670,-9684,-9678,-9675,
--9704,-9756,-9799,-9826,-9866,-9937,-10022,-10092,-10139,-10172,-10202,-10233,-10266,-10299,-10324,-10341,-10356,-10371,-10376,-10367,-10355,
--10353,
--10358,-10359,-10357,-10357,-10358,-10353,-10339,-10317,-10289,-10254,-10216,-10178,-10137,-10079,-9998,-9903,-9807,-9727,-9664,-9605,-9530,
--9428,
--9312,-9194,-9073,-8942,-8803,-8672,-8553,-8437,-8308,-8160,-7997,-7823,-7649,-7489,-7345,-7204,-7055,-6900,-6748,-6596,-6428,
--6237,-6050,-5911,-5839,-5800,-5732,-5603,-5440,-5287,-5164,-5058,-4950,-4827,-4686,-4531,-4382,-4250,-4127,-3999,-3872,-3766,
--3686,-3613,-3533,-3457,-3382,-3270,-3081,-2832,-2590,-2411,-2288,-2170,-2020,-1839,-1639,-1418,-1175,-947,-789,-723,-702,
--660,-574,-464,-351,-235,-116,-10,75,158,254,357,451,538,628,726,825,925,1031,1136,1234,1326,
-1422,1524,1628,1734,1842,1951,2056,2157,2253,2343,2427,2512,2601,2692,2784,2880,2978,3072,3164,3264,3374,
-3480,3575,3669,3771,3872,3962,4050,4146,4243,4325,4399,4482,4588,4729,4914,5124,5302,5402,5449,5516,5642,
-5786,5877,5890,5866,5864,5902,5938,5921,5852,5784,5733,5652,5511,5370,5326,5405,5555,5733,5925,6087,6153,
-6130,6101,6112,6114,6064,6015,6040,6119,6182,6225,6308,6460,6645,6823,6959,6991,6867,6623,6359,6128,5932,
-5818,5887,6154,6468,6665,6746,6823,6940,7019,7003,6943,6937,7010,7117,7210,7284,7348,7402,7438,7452,7449,
-7446,7452,7462,7467,7465,7458,7436,7391,7332,7280,7242,7206,7170,7148,7146,7148,7134,7115,7109,7117,7119,
-7103,7079,7057,7039,7030,7033,7040,7035,7015,7003,7009,7020,7019,7014,7019,7024,7017,7008,7012,7019,7005,
-6972,6944,6925,6894,6851,6822,6814,6800,6767,6738,6726,6708,6672,6642,6637,6633,6608,6586,6593,6597,6567,
-6538,6540,6505,6347,6138,6079,6237,6432,6452,6297,6123,6019,5941,5851,5783,5760,5749,5722,5702,5706,5706,
-5675,5640,5640,5667,5689,5702,5716,5727,5722,5706,5692,5673,5634,5583,5542,5513,5484,5453,5425,5395,5350,
-5289,5223,5163,5104,5043,4980,4920,4863,4806,4748,4691,4641,4605,4576,4538,4487,4434,4393,4358,4314,4264,
-4219,4181,4144,4105,4067,4036,4005,3972,3937,3901,3864,3828,3793,3754,3706,3649,3591,3537,3493,3461,3436,
-3395,3324,3230,3143,3085,3063,3071,3089,3089,3053,2992,2925,2860,2794,2747,2763,2852,2955,2975,2874,2711,
-2586,2551,2572,2581,2547,2496,2467,2459,2439,2382,2307,2247,2213,2190,2164,2137,2114,2090,2062,2034,2014,
-1998,1975,1945,1917,1902,1901,1910,1924,1936,1936,1927,1923,1933,1946,1939,1909,1870,1834,1805,1780,1763,
-1753,1743,1726,1706,1689,1668,1641,1614,1593,1576,1551,1524,1509,1511,1519,1518,1500,1471,1440,1417,1404,
-1400,1402,1410,1423,1433,1435,1433,1435,1445,1452,1448,1435,1420,1407,1399,1398,1406,1418,1431,1446,1463,
-1481,1494,1505,1512,1514,1509,1507,1515,1529,1538,1536,1534,1544,1561,1570,1566,1558,1560,1574,1600,1629,
-1656,1673,1681,1695,1722,1752,1764,1763,1779,1830,1885,1893,1836,1749,1680,1647,1632,1619,1600,1581,1563,
-1545,1526,1508,1489,1467,1444,1427,1419,1418,1416,1412,1407,1400,1385,1361,1332,1303,1271,1235,1201,1173,
-1148,1123,1100,1080,1060,1034,1005,980,956,930,898,865,833,802,772,746,722,697,669,640,610,
-578,543,508,474,441,407,372,336,298,255,210,165,121,81,44,6,-33,-71,-107,-142,-180,
--220,-257,-294,-333,-374,-414,-452,-491,-533,-576,-620,-664,-708,-749,-786,-820,-852,-882,-913,-949,-992,
--1033,-1069,-1098,-1123,-1146,-1173,-1203,-1236,-1268,-1301,-1336,-1371,-1405,-1439,-1476,-1512,-1544,-1574,-1605,-1636,-1664,
--1690,-1717,-1746,-1775,-1807,-1842,-1879,-1911,-1939,-1971,-2007,-2044,-2077,-2109,-2141,-2172,-2201,-2230,-2260,-2288,-2312,
--2335,-2359,-2381,-2401,-2421,-2441,-2458,-2471,-2484,-2499,-2516,-2531,-2544,-2554,-2563,-2571,-2581,-2590,-2593,-2590,-2587,
--2588,-2592,-2596,-2598,-2598,-2595,-2590,-2585,-2579,-2570,-2557,-2542,-2528,-2513,-2496,-2482,-2471,-2459,-2444,-2429,-2413,
--2396,-2377,-2360,-2344,-2325,-2302,-2282,-2267,-2253,-2235,-2215,-2197,-2180,-2161,-2140,-2119,-2101,-2087,-2074,-2060,-2039,
--2013,-1990,-1973,-1955,-1932,-1905,-1880,-1859,-1839,-1821,-1805,-1790,-1775,-1761,-1746,-1729,-1709,-1690,-1673,-1654,-1632,
--1607,-1584,-1563,-1543,-1523,-1502,-1478,-1453,-1432,-1414,-1394,-1369,-1345,-1325,-1304,-1278,-1249,-1221,-1191,-1160,-1133,
--1113,-1095,-1072,-1047,-1025,-1006,-983,-955,-926,-897,-866,-833,-802,-772,-739,-705,-675,-646,-614,-579,-543,
--511,-482,-454,-431,-408,-381,-350,-323,-306,-293,-276,-252,-225,-197,-171,-148,-121,-90,-56,-26,1,
-31,64,98,134,173,211,246,281,319,361,402,444,492,545,601,665,742,820,881,928,978,
-1032,1058,1041,1011,1015,1068,1140,1209,1286,1411,1611,1877,2159,2389,2520,2567,2585,2603,2596,2520,2377,
-2219,2099,2027,1982,1952,1951,1998,2081,2158,2192,2182,2153,2128,2108,2086,2054,2002,1926,1835,1746,1657,
-1549,1424,1311,1232,1170,1098,1024,969,929,857,727,558,395,268,176,107,52,13,15,72,145,
-151,37,-163,-364,-502,-579,-629,-678,-731,-785,-836,-882,-917,-931,-926,-929,-974,-1067,-1173,-1259,-1331,
--1411,-1498,-1569,-1622,-1682,-1765,-1855,-1933,-2008,-2089,-2170,-2240,-2298,-2355,-2412,-2462,-2505,-2545,-2588,-2632,-2675,
--2714,-2750,-2784,-2816,-2843,-2860,-2866,-2864,-2860,-2856,-2847,-2819,-2763,-2693,-2648,-2656,-2702,-2744,-2758,-2758,-2767,
--2792,-2823,-2851,-2869,-2868,-2849,-2822,-2794,-2758,-2717,-2695,-2720,-2794,-2890,-2974,-3027,-3040,-3016,-2968,-2910,-2849,
--2790,-2735,-2684,-2634,-2577,-2513,-2447,-2382,-2317,-2253,-2189,-2126,-2064,-2004,-1947,-1891,-1835,-1781,-1728,-1674,-1617,
--1557,-1496,-1433,-1366,-1299,-1234,-1170,-1106,-1042,-980,-919,-861,-812,-770,-720,-653,-574,-495,-425,-366,-314,
--265,-211,-151,-87,-22,40,103,161,212,266,329,400,470,532,581,610,615,611,614,634,665,
-701,735,761,776,789,812,843,866,874,881,904,943,980,1001,1016,1037,1064,1079,1074,1059,1053,
-1060,1071,1081,1094,1112,1130,1142,1149,1154,1158,1165,1181,1202,1221,1234,1255,1287,1320,1336,1332,1318,
-1301,1283,1272,1276,1293,1312,1325,1335,1343,1346,1355,1382,1432,1490,1541,1580,1618,1660,1702,1730,1738,
-1735,1737,1752,1770,1780,1785,1794,1806,1812,1810,1810,1820,1835,1850,1861,1870,1877,1883,1892,1901,1906,
-1906,1909,1913,1913,1909,1904,1902,1902,1902,1903,1903,1895,1879,1861,1845,1828,1809,1788,1768,1747,1726,
-1709,1700,1698,1700,1704,1708,1709,1707,1707,1710,1710,1704,1697,1690,1685,1674,1657,1639,1624,1613,1610,
-1620,1633,1635,1624,1614,1612,1612,1609,1610,1607,1586,1555,1543,1553,1545,1500,1480,1556,1698,1779,1716,
-1563,1434,1382,1377,1383,1381,1361,1311,1249,1211,1208,1205,1169,1107,1049,1003,955,897,833,770,717,
-676,640,588,506,401,292,185,83,0,-47,-69,-107,-185,-290,-388,-469,-554,-654,-759,-848,-914,
--973,-1044,-1132,-1227,-1313,-1387,-1452,-1513,-1573,-1632,-1686,-1735,-1778,-1819,-1857,-1881,-1879,-1849,-1815,-1800,-1811,
--1830,-1843,-1846,-1838,-1817,-1781,-1742,-1711,-1682,-1633,-1561,-1489,-1441,-1419,-1406,-1393,-1382,-1365,-1326,-1268,-1213,
--1180,-1160,-1143,-1142,-1181,-1257,-1335,-1383,-1393,-1382,-1365,-1358,-1368,-1385,-1393,-1389,-1393,-1422,-1478,-1541,-1584,
--1581,-1521,-1418,-1310,-1247,-1262,-1360,-1498,-1591,-1576,-1478,-1401,-1433,-1567,-1725,-1851,-1947,-2047,-2165,-2290,-2400,
--2477,-2518,-2541,-2572,-2629,-2707,-2789,-2862,-2917,-2958,-2997,-3045,-3099,-3148,-3190,-3224,-3256,-3294,-3360,-3472,-3626,
--3791,-3943,-4067,-4159,-4223,-4278,-4349,-4444,-4544,-4632,-4713,-4797,-4880,-4951,-5007,-5058,-5100,-5123,-5114,-5074,-5015,
--4955,-4920,-4922,-4953,-4990,-5018,-5034,-5042,-5046,-5055,-5076,-5106,-5127,-5134,-5136,-5147,-5173,-5209,-5243,-5269,-5289,
--5310,-5336,-5366,-5395,-5421,-5447,-5481,-5525,-5575,-5629,-5686,-5751,-5823,-5895,-5959,-6019,-6084,-6159,-6237,-6305,-6362,
--6414,-6467,-6523,-6578,-6633,-6691,-6754,-6816,-6872,-6926,-6991,-7071,-7158,-7235,-7298,-7351,-7405,-7465,-7533,-7609,-7684,
--7750,-7804,-7853,-7903,-7954,-8012,-8087,-8179,-8280,-8380,-8478,-8571,-8657,-8737,-8822,-8916,-9005,-9082,-9154,-9235,-9315,
--9381,-9437,-9497,-9555,-9589,-9599,-9613,-9638,-9651,-9640,-9634,-9665,-9722,-9769,-9801,-9849,-9929,-10016,-10080,-10119,-10149,
--10178,-10208,-10241,-10275,-10301,-10320,-10337,-10355,-10364,-10359,-10350,-10348,-10351,-10350,-10346,-10347,-10348,-10340,-10320,-10296,-10268,
--10234,
--10194,-10149,-10095,-10019,-9919,-9808,-9710,-9643,-9605,-9576,-9523,-9437,-9329,-9218,-9106,-8982,-8847,-8715,-8588,-8456,-8307,
--8146,-7985,-7824,-7663,-7502,-7348,-7202,-7059,-6914,-6764,-6605,-6429,-6241,-6063,-5930,-5857,-5813,-5747,-5628,-5476,-5329,
--5201,-5078,-4947,-4807,-4663,-4514,-4362,-4212,-4064,-3920,-3791,-3687,-3592,-3489,-3391,-3337,-3324,-3280,-3124,-2850,-2543,
--2299,-2150,-2054,-1953,-1814,-1637,-1428,-1201,-987,-828,-741,-695,-641,-554,-448,-334,-215,-94,17,112,202,
-292,378,455,538,636,742,843,942,1048,1157,1260,1358,1457,1559,1662,1768,1879,1988,2087,2183,2284,
-2385,2479,2568,2658,2748,2833,2921,3019,3121,3222,3322,3426,3528,3624,3719,3822,3925,4021,4117,4221,4325,
-4415,4499,4598,4720,4864,5029,5202,5346,5431,5484,5566,5697,5827,5891,5877,5836,5824,5852,5884,5885,5862,
-5844,5821,5736,5569,5403,5346,5427,5599,5814,6042,6221,6288,6272,6269,6314,6334,6281,6218,6223,6269,6291,
-6309,6408,6600,6805,6946,6995,6929,6734,6462,6208,6019,5894,5874,6043,6384,6723,6896,6920,6933,6999,7068,
-7086,7081,7101,7153,7211,7259,7299,7338,7384,7437,7475,7477,7453,7440,7453,7470,7470,7453,7428,7393,7347,
-7300,7258,7216,7170,7137,7127,7123,7108,7087,7082,7095,7108,7109,7100,7087,7071,7060,7066,7076,7070,7048,
-7037,7049,7063,7059,7047,7046,7051,7045,7034,7035,7044,7040,7021,7003,6988,6959,6919,6890,6877,6857,6821,
-6789,6774,6752,6713,6680,6671,6665,6640,6619,6621,6618,6587,6566,6578,6547,6388,6173,6102,6247,6439,6472,
-6341,6190,6096,6018,5921,5846,5819,5805,5772,5740,5730,5720,5682,5640,5636,5671,5710,5735,5746,5749,5742,
-5733,5727,5710,5671,5621,5579,5545,5510,5475,5449,5421,5377,5312,5240,5172,5106,5041,4981,4926,4875,4824,
-4773,4718,4663,4617,4580,4541,4492,4441,4402,4369,4332,4288,4243,4203,4167,4134,4105,4077,4043,4003,3964,
-3926,3886,3847,3812,3778,3732,3673,3611,3558,3518,3490,3463,3422,3353,3258,3163,3096,3073,3088,3114,3118,
-3087,3033,2974,2910,2837,2781,2786,2862,2953,2969,2876,2724,2604,2563,2576,2587,2572,2551,2543,2534,2489,
-2405,2320,2271,2255,2237,2201,2156,2122,2101,2080,2054,2030,2012,1991,1961,1926,1903,1905,1928,1955,1966,
-1954,1936,1928,1932,1934,1923,1908,1898,1886,1855,1809,1772,1753,1743,1727,1708,1693,1678,1657,1635,1619,
-1602,1574,1539,1514,1508,1510,1509,1499,1483,1462,1439,1424,1423,1429,1435,1436,1433,1428,1424,1429,1442,
-1453,1454,1444,1430,1417,1409,1407,1413,1424,1440,1460,1482,1499,1507,1507,1505,1502,1500,1504,1517,1531,
-1538,1539,1545,1563,1581,1586,1580,1576,1580,1588,1599,1615,1637,1654,1664,1678,1706,1737,1748,1741,1739,
-1762,1796,1808,1783,1733,1683,1647,1628,1617,1605,1587,1562,1541,1529,1523,1515,1499,1478,1459,1447,1438,
-1427,1416,1408,1400,1385,1361,1337,1313,1285,1252,1220,1194,1172,1148,1124,1103,1082,1056,1031,1010,990,
-965,931,896,862,828,793,760,731,705,678,651,622,591,559,527,496,464,428,393,358,321,
-281,238,193,149,106,66,25,-18,-61,-100,-137,-174,-212,-248,-284,-323,-363,-401,-438,-478,-521,
--564,-605,-646,-686,-723,-755,-785,-816,-845,-877,-914,-957,-999,-1035,-1065,-1092,-1118,-1145,-1176,-1208,-1240,
--1270,-1303,-1338,-1374,-1411,-1449,-1486,-1519,-1548,-1577,-1607,-1634,-1658,-1683,-1713,-1746,-1778,-1811,-1842,-1871,-1900,
--1932,-1968,-2002,-2032,-2063,-2097,-2131,-2162,-2193,-2222,-2248,-2270,-2293,-2317,-2340,-2361,-2380,-2400,-2417,-2432,-2447,
--2464,-2482,-2497,-2510,-2521,-2530,-2537,-2546,-2554,-2557,-2554,-2551,-2554,-2560,-2564,-2565,-2564,-2562,-2559,-2556,-2550,
--2540,-2526,-2513,-2501,-2487,-2470,-2455,-2444,-2433,-2417,-2400,-2384,-2368,-2351,-2334,-2318,-2299,-2275,-2254,-2240,-2227,
--2210,-2189,-2170,-2153,-2133,-2111,-2091,-2075,-2064,-2056,-2043,-2021,-1993,-1970,-1955,-1941,-1920,-1892,-1868,-1848,-1832,
--1815,-1799,-1785,-1771,-1757,-1742,-1725,-1706,-1686,-1668,-1650,-1630,-1607,-1585,-1563,-1543,-1523,-1502,-1479,-1458,-1442,
--1426,-1404,-1379,-1355,-1336,-1314,-1287,-1263,-1242,-1219,-1190,-1163,-1145,-1129,-1104,-1077,-1056,-1041,-1022,-997,-973,
--947,-913,-875,-842,-813,-780,-740,-703,-674,-647,-615,-580,-546,-511,-473,-439,-415,-395,-372,-348,-327,
--308,-289,-266,-240,-214,-189,-166,-141,-112,-80,-52,-26,4,42,80,112,144,182,222,257,289,
-326,369,415,463,515,580,659,742,814,866,913,966,1010,1013,977,955,1003,1116,1237,1332,1426,
-1577,1819,2124,2421,2635,2728,2720,2658,2569,2446,2292,2141,2037,1992,1977,1962,1949,1964,2026,2121,2204,
-2237,2215,2166,2123,2101,2092,2076,2036,1968,1886,1804,1717,1610,1488,1380,1306,1244,1164,1076,1010,962,
-890,760,589,424,299,215,152,98,60,63,119,190,195,82,-121,-333,-485,-568,-614,-658,-711,
--768,-817,-859,-893,-914,-919,-930,-976,-1062,-1156,-1231,-1301,-1385,-1473,-1538,-1583,-1639,-1720,-1809,-1888,-1965,
--2053,-2141,-2214,-2272,-2329,-2388,-2441,-2483,-2521,-2561,-2603,-2643,-2680,-2714,-2746,-2776,-2802,-2820,-2829,-2828,-2819,
--2808,-2794,-2766,-2709,-2636,-2586,-2589,-2630,-2670,-2687,-2697,-2718,-2752,-2791,-2825,-2842,-2833,-2806,-2779,-2760,-2735,
--2697,-2658,-2645,-2670,-2723,-2788,-2852,-2902,-2926,-2921,-2889,-2839,-2782,-2729,-2683,-2637,-2582,-2518,-2449,-2378,-2308,
--2246,-2193,-2142,-2083,-2018,-1957,-1907,-1860,-1806,-1744,-1681,-1621,-1563,-1500,-1431,-1362,-1299,-1236,-1171,-1107,-1048,
--992,-932,-869,-814,-766,-715,-651,-580,-514,-455,-402,-353,-308,-257,-196,-127,-57,8,71,129,184,
-239,302,369,433,489,533,561,574,581,592,610,633,663,696,723,736,746,770,809,844,861,
-869,889,927,965,987,1000,1019,1047,1066,1061,1042,1032,1038,1053,1071,1092,1118,1142,1162,1184,1209,
-1230,1241,1250,1262,1269,1269,1269,1280,1295,1296,1283,1263,1248,1242,1254,1285,1326,1361,1385,1402,1413,
-1419,1432,1464,1514,1565,1602,1627,1656,1692,1725,1738,1724,1697,1677,1676,1684,1691,1700,1722,1757,1791,
-1814,1832,1853,1876,1900,1923,1944,1958,1965,1968,1966,1957,1946,1939,1934,1926,1914,1904,1896,1888,1880,
-1873,1868,1859,1844,1830,1817,1804,1789,1776,1765,1753,1739,1729,1726,1729,1733,1737,1737,1730,1719,1712,
-1708,1704,1699,1694,1690,1686,1674,1654,1636,1626,1621,1620,1630,1643,1646,1634,1620,1617,1623,1628,1630,
-1623,1600,1569,1551,1552,1543,1512,1494,1530,1595,1620,1569,1479,1405,1365,1346,1343,1344,1317,1247,1171,
-1143,1167,1187,1159,1095,1036,997,964,916,850,777,709,656,613,559,478,374,263,156,54,-31,
--91,-134,-187,-266,-363,-455,-535,-620,-721,-831,-928,-1002,-1058,-1117,-1188,-1266,-1342,-1412,-1479,-1549,-1619,
--1686,-1745,-1787,-1814,-1838,-1872,-1907,-1924,-1912,-1887,-1873,-1876,-1884,-1888,-1888,-1880,-1859,-1823,-1785,-1753,-1720,
--1672,-1612,-1552,-1503,-1465,-1436,-1419,-1404,-1364,-1286,-1196,-1140,-1131,-1141,-1139,-1139,-1174,-1247,-1315,-1341,-1325,
--1302,-1298,-1316,-1342,-1358,-1353,-1339,-1339,-1370,-1429,-1497,-1554,-1572,-1530,-1425,-1296,-1213,-1233,-1353,-1503,-1582,
--1538,-1426,-1359,-1413,-1564,-1729,-1850,-1929,-2004,-2104,-2231,-2367,-2483,-2557,-2594,-2623,-2670,-2743,-2826,-2901,-2957,
--3001,-3052,-3116,-3183,-3240,-3285,-3324,-3364,-3415,-3494,-3618,-3780,-3948,-4093,-4199,-4267,-4307,-4345,-4410,-4506,-4605,
--4680,-4735,-4790,-4854,-4920,-4977,-5024,-5062,-5084,-5077,-5041,-4987,-4943,-4926,-4937,-4961,-4982,-4999,-5011,-5019,-5026,
--5038,-5059,-5081,-5091,-5092,-5097,-5116,-5146,-5180,-5209,-5232,-5252,-5275,-5302,-5330,-5355,-5380,-5412,-5458,-5514,-5572,
--5629,-5686,-5749,-5820,-5893,-5961,-6021,-6082,-6150,-6224,-6296,-6357,-6410,-6463,-6521,-6583,-6644,-6705,-6766,-6824,-6877,
--6929,-6991,-7069,-7154,-7228,-7285,-7333,-7387,-7454,-7529,-7603,-7670,-7733,-7793,-7847,-7891,-7930,-7982,-8062,-8162,-8262,
--8353,-8443,-8535,-8624,-8707,-8792,-8882,-8967,-9041,-9115,-9199,-9281,-9346,-9402,-9462,-9520,-9556,-9574,-9597,-9619,-9609,
--9569,-9549,-9591,-9671,-9735,-9779,-9839,-9930,-10019,-10074,-10102,-10126,-10156,-10188,-10221,-10255,-10284,-10304,-10322,-10340,-10349,
--10344,
--10335-10333,-10337,-10338,-10336,-10338,-10337,-10325,-10301,-10275,-10247,-10212,-10166,-10111,-10044,-9952,-9833,-9709,-9608,-9551,
--9532,-9521,-9486,-9411,-9312,-9211,-9109,-8996,-8866,-8730,-8590,-8442,-8284,-8124,-7974,-7828,-7677,-7518,-7360,-7213,-7074,
--6934,-6782,-6615,-6441,-6273,-6122,-6001,-5912,-5841,-5757,-5641,-5502,-5365,-5237,-5104,-4957,-4803,-4651,-4502,-4350,-4190,
--4025,-3870,-3744,-3641,-3531,-3393,-3261,-3197,-3214,-3230,-3137,-2896,-2572,-2275,-2077,-1970,-1890,-1773,-1601,-1396,-1193,
--1010,-860,-749,-671,-603,-525,-429,-316,-193,-70,42,143,237,322,389,448,526,632,748,855,956,
-1067,1185,1295,1393,1490,1588,1691,1802,1919,2027,2120,2210,2312,2418,2515,2606,2699,2791,2875,2959,3059,
-3172,3282,3383,3482,3580,3672,3763,3863,3969,4068,4158,4253,4354,4452,4552,4670,4810,4960,5111,5254,5371,
-5450,5513,5601,5717,5814,5845,5819,5784,5770,5770,5762,5752,5768,5820,5852,5782,5599,5411,5346,5438,5635,
-5879,6129,6321,6400,6397,6405,6447,6453,6386,6314,6303,6317,6306,6321,6452,6681,6882,6962,6920,6768,6515,
-6217,5977,5845,5812,5892,6142,6538,6918,7121,7149,7121,7121,7149,7189,7240,7294,7327,7333,7332,7335,7344,
-7374,7432,7488,7495,7462,7442,7460,7481,7470,7439,7414,7394,7359,7311,7261,7206,7146,7096,7075,7075,7073,
-7064,7061,7069,7079,7085,7090,7092,7085,7079,7087,7102,7105,7092,7084,7091,7100,7093,7083,7086,7095,7089,
-7070,7060,7063,7066,7062,7055,7044,7021,6987,6960,6940,6912,6873,6842,6826,6803,6765,6730,6715,6699,6668,
-6642,6639,6634,6609,6596,6614,6590,6441,6229,6137,6243,6408,6448,6346,6222,6147,6082,5994,5917,5880,5854,
-5809,5763,5739,5724,5691,5655,5649,5680,5721,5749,5759,5754,5746,5746,5754,5751,5722,5676,5632,5589,5542,
-5497,5461,5427,5384,5327,5260,5187,5111,5042,4984,4935,4886,4840,4798,4753,4697,4637,4586,4545,4508,4469,
-4431,4393,4352,4308,4266,4226,4190,4161,4137,4110,4071,4026,3985,3946,3905,3865,3834,3806,3763,3703,3637,
-3585,3547,3517,3486,3444,3381,3292,3194,3118,3090,3111,3150,3168,3144,3089,3024,2953,2876,2814,2799,2841,
-2900,2915,2854,2743,2639,2584,2577,2589,2593,2589,2578,2550,2489,2402,2324,2284,2277,2269,2240,2195,2156,
-2130,2109,2084,2058,2038,2019,1989,1948,1919,1923,1955,1985,1988,1966,1941,1931,1929,1920,1909,1914,1935,
-1944,1911,1847,1790,1763,1752,1737,1718,1704,1692,1674,1654,1639,1624,1596,1559,1528,1513,1505,1498,1495,
-1493,1483,1465,1449,1448,1454,1455,1448,1438,1431,1427,1426,1431,1438,1442,1442,1439,1433,1428,1428,1436,
-1451,1465,1477,1486,1492,1496,1503,1509,1511,1511,1518,1535,1554,1560,1559,1565,1578,1584,1577,1570,1578,
-1593,1599,1595,1596,1611,1629,1643,1659,1685,1715,1729,1726,1720,1724,1736,1745,1744,1727,1695,1657,1629,
-1617,1610,1591,1562,1536,1523,1520,1515,1505,1491,1479,1467,1453,1436,1419,1406,1395,1379,1360,1341,1323,
-1299,1267,1234,1208,1187,1163,1139,1119,1100,1077,1055,1038,1023,1001,970,937,903,865,822,781,748,
-719,693,666,638,608,578,550,521,488,450,412,375,337,298,257,214,169,126,86,45,1,
--45,-88,-126,-162,-198,-233,-271,-312,-354,-391,-428,-467,-509,-549,-585,-623,-662,-697,-727,-756,-785,
--813,-844,-881,-923,-963,-997,-1028,-1058,-1087,-1116,-1147,-1180,-1211,-1239,-1270,-1305,-1341,-1378,-1415,-1452,-1486,
--1515,-1543,-1573,-1601,-1626,-1653,-1684,-1719,-1752,-1781,-1809,-1837,-1867,-1900,-1932,-1962,-1990,-2022,-2057,-2092,-2123,
--2151,-2178,-2201,-2222,-2245,-2270,-2295,-2315,-2335,-2355,-2373,-2389,-2406,-2425,-2444,-2459,-2471,-2483,-2492,-2500,-2507,
--2515,-2519,-2519,-2520,-2524,-2530,-2533,-2532,-2531,-2530,-2528,-2524,-2518,-2507,-2494,-2482,-2472,-2458,-2442,-2426,-2414,
--2400,-2383,-2365,-2350,-2337,-2322,-2307,-2292,-2274,-2251,-2230,-2215,-2201,-2183,-2162,-2143,-2126,-2106,-2084,-2065,-2051,
--2042,-2034,-2022,-2002,-1976,-1954,-1939,-1925,-1905,-1881,-1860,-1843,-1827,-1810,-1794,-1779,-1765,-1750,-1735,-1718,-1699,
--1679,-1662,-1645,-1627,-1606,-1584,-1562,-1543,-1524,-1503,-1480,-1459,-1443,-1427,-1405,-1379,-1358,-1341,-1319,-1292,-1269,
--1253,-1236,-1210,-1185,-1169,-1154,-1131,-1104,-1085,-1071,-1053,-1032,-1014,-993,-961,-921,-886,-856,-819,-774,-734,
--706,-682,-653,-620,-587,-548,-501,-456,-423,-402,-385,-368,-348,-325,-300,-275,-252,-229,-203,-179,-156,
--131,-101,-73,-46,-14,24,61,88,116,153,194,227,256,293,345,400,451,504,572,653,730,
-793,845,900,953,977,954,914,929,1039,1211,1374,1493,1603,1764,2004,2295,2572,2765,2835,2782,2641,
-2449,2239,2053,1937,1909,1938,1972,1977,1966,1976,2034,2131,2221,2253,2215,2143,2086,2063,2064,2061,2035,
-1981,1906,1824,1742,1651,1549,1451,1368,1290,1200,1105,1028,968,892,768,610,455,335,249,180,121,
-80,77,115,159,149,45,-130,-318,-459,-542,-589,-632,-685,-740,-789,-834,-877,-909,-923,-936,-978,
--1053,-1132,-1200,-1270,-1356,-1443,-1506,-1553,-1614,-1697,-1783,-1858,-1936,-2027,-2118,-2189,-2245,-2300,-2359,-2412,-2455,
--2493,-2534,-2574,-2610,-2643,-2676,-2707,-2734,-2755,-2772,-2781,-2777,-2757,-2734,-2717,-2696,-2651,-2587,-2537,-2530,-2556,
--2585,-2608,-2638,-2682,-2732,-2773,-2803,-2814,-2801,-2770,-2741,-2725,-2710,-2680,-2641,-2608,-2591,-2589,-2606,-2648,-2709,
--2773,-2816,-2825,-2800,-2756,-2712,-2674,-2631,-2578,-2515,-2450,-2382,-2314,-2256,-2211,-2167,-2110,-2045,-1988,-1947,-1906,
--1845,-1768,-1695,-1637,-1586,-1528,-1461,-1395,-1338,-1282,-1219,-1154,-1099,-1050,-995,-932,-870,-814,-759,-697,-635,
--579,-528,-477,-427,-379,-324,-258,-186,-116,-52,7,66,122,180,239,299,355,405,446,477,504,
-533,565,593,615,639,670,697,712,723,749,791,830,848,852,865,897,934,959,971,989,1015,
-1037,1038,1027,1026,1041,1064,1087,1114,1143,1170,1193,1221,1252,1273,1278,1275,1275,1272,1255,1233,1221,
-1221,1222,1218,1211,1211,1226,1263,1324,1396,1463,1519,1568,1604,1622,1630,1641,1656,1666,1665,1668,1687,
-1720,1750,1760,1747,1723,1712,1721,1742,1758,1773,1798,1835,1872,1898,1916,1931,1947,1963,1978,1989,1993,
-1992,1988,1980,1967,1952,1939,1928,1914,1897,1884,1875,1866,1857,1851,1848,1844,1836,1828,1819,1806,1791,
-1781,1776,1771,1764,1760,1759,1758,1756,1754,1750,1738,1722,1709,1703,1699,1704,1701,1697,1691,1675,1653,
-1637,1632,1632,1632,1637,1648,1655,1647,1633,1629,1637,1644,1644,1634,1612,1583,1561,1557,1569,1587,1601,
-1599,1564,1497,1430,1392,1375,1353,1323,1307,1299,1254,1158,1062,1036,1081,1126,1117,1066,1016,987,965,
-928,870,795,715,643,582,521,445,346,234,120,12,-81,-155,-215,-274,-343,-426,-513,-598,-685,
--781,-888,-993,-1082,-1149,-1202,-1256,-1314,-1376,-1442,-1514,-1590,-1665,-1733,-1788,-1823,-1839,-1853,-1886,-1932,-1966,
--1968,-1950,-1935,-1932,-1934,-1934,-1932,-1921,-1897,-1860,-1823,-1789,-1750,-1703,-1653,-1605,-1557,-1507,-1468,-1448,-1424,
--1356,-1236,-1115,-1053,-1058,-1080,-1080,-1072,-1093,-1143,-1187,-1198,-1193,-1204,-1241,-1285,-1315,-1320,-1306,-1291,-1294,
--1329,-1389,-1462,-1532,-1577,-1569,-1488,-1361,-1261,-1261,-1366,-1500,-1560,-1509,-1406,-1354,-1412,-1556,-1714,-1835,-1914,
--1979,-2060,-2172,-2306,-2437,-2538,-2605,-2653,-2707,-2779,-2863,-2941,-3002,-3056,-3118,-3192,-3262,-3314,-3355,-3402,-3466,
--3548,-3655,-3791,-3943,-4085,-4198,-4278,-4328,-4359,-4393,-4455,-4549,-4646,-4714,-4751,-4784,-4832,-4893,-4950,-4994,-5027,
--5046,-5041,-5009,-4961,-4925,-4918,-4934,-4954,-4967,-4975,-4983,-4991,-5001,-5017,-5037,-5051,-5056,-5059,-5070,-5091,-5116,
--5141,-5167,-5194,-5220,-5245,-5269,-5293,-5315,-5344,-5388,-5448,-5513,-5576,-5633,-5690,-5750,-5817,-5888,-5957,-6019,-6079,
--6145,-6215,-6283,-6340,-6392,-6448,-6513,-6584,-6650,-6708,-6763,-6820,-6877,-6935,-6998,-7070,-7145,-7213,-7267,-7316,-7373,
--7444,-7521,-7591,-7652,-7713,-7777,-7835,-7877,-7912,-7964,-8047,-8146,-8237,-8317,-8401,-8496,-8590,-8674,-8756,-8842,-8924,
--9000,-9078,-9164,-9244,-9305,-9358,-9418,-9477,-9519,-9552,-9589,-9607,-9569,-9493,-9460,-9515,-9620,-9705,-9762,-9836,-9939,
--10030,-10075,-10088,-10105,-10136,-10171,-10207,-10242,-10273,-10295,-10313,-10330,-10339,-10335,-10326,-10325,-10328,-10327,-10325,-10325,-10322,
--10309,
--10287,-10263,-10235,-10193,-10138,-10075,-9999,-9896,-9766,-9634,-9533,-9480,-9465,-9458,-9427,-9360,-9270,-9175,-9078,-8969,-8842,
--8701,-8554,-8401,-8247,-8099,-7960,-7825,-7682,-7531,-7378,-7235,-7102,-6970,-6823,-6658,-6492,-6344,-6217,-6103,-5992,-5883,
--5770,-5647,-5518,-5390,-5265,-5130,-4979,-4818,-4658,-4504,-4348,-4182,-4009,-3846,-3715,-3606,-3482,-3321,-3164,-3081,-3095,
--3145,-3124,-2967,-2687,-2368,-2109,-1954,-1857,-1734,-1549,-1341,-1165,-1026,-897,-768,-655,-571,-499,-414,-305,-180,
--57,53,157,259,348,411,463,536,644,766,878,984,1100,1222,1335,1430,1520,1615,1721,1839,1960,
-2066,2155,2242,2342,2445,2539,2630,2729,2830,2920,3005,3108,3227,3340,3438,3530,3621,3706,3792,3894,4007,
-4107,4188,4270,4369,4480,4595,4720,4862,5010,5152,5281,5387,5467,5533,5610,5693,5749,5757,5741,5733,5729,
-5696,5627,5567,5578,5669,5753,5722,5564,5398,5360,5482,5699,5943,6176,6352,6429,6431,6430,6436,6395,6291,
-6198,6170,6168,6154,6190,6355,6597,6764,6778,6668,6471,6195,5889,5668,5602,5680,5883,6224,6669,7078,7313,
-7360,7310,7253,7234,7275,7364,7445,7466,7439,7412,7397,7388,7399,7446,7500,7507,7472,7452,7472,7488,7464,
-7425,7406,7396,7361,7297,7227,7155,7077,7009,6980,6992,7017,7033,7041,7048,7053,7055,7061,7071,7076,7078,
-7087,7105,7119,7120,7118,7122,7128,7128,7129,7138,7145,7138,7117,7101,7099,7103,7104,7100,7090,7070,7042,
-7016,6991,6958,6920,6893,6877,6856,6822,6791,6771,6746,6705,6669,6657,6651,6632,6623,6642,6630,6510,6314,
-6191,6230,6348,6392,6327,6231,6168,6117,6047,5977,5931,5896,5850,5802,5768,5744,5714,5683,5673,5692,5727,
-5761,5780,5777,5763,5760,5774,5788,5780,5747,5699,5643,5582,5524,5475,5434,5393,5349,5294,5220,5134,5057,
-5000,4954,4908,4865,4833,4800,4745,4671,4601,4555,4526,4500,4466,4423,4376,4332,4292,4252,4213,4180,4154,
-4125,4085,4038,3995,3957,3915,3874,3844,3817,3779,3723,3664,3615,3578,3543,3504,3461,3403,3324,3231,3152,
-3118,3136,3179,3205,3186,3126,3048,2969,2893,2830,2795,2800,2833,2867,2868,2819,2734,2648,2598,2589,2599,
-2595,2567,2517,2456,2391,2333,2297,2284,2281,2271,2243,2207,2174,2146,2121,2098,2081,2065,2036,1993,1960,
-1958,1982,2001,1992,1966,1947,1943,1938,1922,1911,1927,1964,1981,1948,1877,1814,1783,1771,1757,1739,1725,
-1713,1695,1673,1655,1638,1611,1575,1544,1523,1509,1499,1499,1503,1501,1487,1474,1473,1477,1475,1464,1453,
-1445,1439,1432,1426,1425,1430,1438,1446,1449,1447,1450,1463,1480,1490,1489,1481,1478,1493,1522,1549,1556,
-1546,1542,1556,1575,1579,1573,1573,1581,1578,1561,1551,1563,1585,1591,1581,1578,1594,1616,1632,1646,1668,
-1690,1703,1705,1706,1709,1712,1715,1723,1726,1708,1671,1637,1622,1614,1596,1565,1536,1519,1509,1502,1494,
-1487,1480,1471,1459,1443,1425,1408,1394,1378,1362,1347,1332,1309,1278,1245,1218,1195,1170,1148,1133,1119,
-1101,1079,1061,1046,1028,1004,978,947,907,860,814,778,747,718,690,661,630,598,568,538,504,
-466,427,390,353,314,275,235,193,150,111,72,30,-15,-60,-100,-136,-171,-206,-247,-291,-335,
--374,-411,-450,-491,-527,-561,-597,-636,-671,-702,-730,-757,-785,-816,-853,-893,-930,-961,-993,-1026,-1058,
--1085,-1114,-1147,-1179,-1208,-1237,-1270,-1305,-1339,-1375,-1413,-1449,-1480,-1509,-1540,-1570,-1596,-1622,-1655,-1690,-1722,
--1750,-1778,-1809,-1842,-1873,-1903,-1931,-1961,-1994,-2029,-2061,-2088,-2113,-2136,-2157,-2176,-2199,-2225,-2250,-2271,-2291,
--2311,-2330,-2347,-2366,-2386,-2404,-2416,-2427,-2439,-2451,-2460,-2467,-2475,-2481,-2485,-2489,-2496,-2501,-2502,-2500,-2501,
--2501,-2498,-2492,-2484,-2474,-2462,-2451,-2440,-2427,-2410,-2395,-2381,-2366,-2347,-2329,-2316,-2303,-2290,-2277,-2264,-2250,
--2231,-2211,-2194,-2178,-2159,-2138,-2120,-2103,-2082,-2061,-2044,-2032,-2020,-2008,-1995,-1978,-1958,-1939,-1923,-1907,-1888,
--1868,-1852,-1838,-1821,-1802,-1784,-1770,-1756,-1740,-1724,-1708,-1690,-1672,-1656,-1641,-1624,-1604,-1582,-1561,-1542,-1524,
--1504,-1481,-1460,-1443,-1425,-1401,-1376,-1357,-1344,-1325,-1300,-1277,-1261,-1245,-1221,-1199,-1184,-1170,-1149,-1126,-1109,
--1094,-1074,-1053,-1036,-1020,-993,-956,-922,-891,-854,-810,-772,-745,-721,-692,-662,-633,-598,-551,-498,-450,
--413,-389,-377,-368,-350,-321,-294,-274,-253,-226,-198,-176,-153,-123,-90,-60,-29,6,39,65,91,
-127,166,196,224,267,330,395,451,506,573,647,713,772,834,898,939,933,892,873,944,1113,
-1325,1509,1646,1773,1936,2146,2380,2591,2730,2753,2652,2458,2227,2017,1875,1826,1861,1933,1987,1997,1980,
-1978,2025,2121,2214,2245,2193,2103,2036,2013,2018,2026,2023,1994,1933,1850,1769,1693,1610,1508,1398,1292,
-1197,1112,1041,979,901,785,638,494,375,283,206,141,94,74,78,80,49,-35,-165,-307,-425,
--505,-558,-605,-657,-708,-758,-808,-858,-895,-912,-927,-967,-1034,-1104,-1167,-1235,-1320,-1405,-1470,-1526,-1597,
--1682,-1763,-1834,-1913,-2005,-2095,-2164,-2219,-2274,-2332,-2383,-2426,-2466,-2507,-2545,-2578,-2609,-2641,-2671,-2693,-2710,
--2723,-2730,-2717,-2682,-2644,-2623,-2613,-2587,-2537,-2489,-2471,-2480,-2501,-2533,-2587,-2657,-2719,-2759,-2780,-2786,-2773,
--2744,-2716,-2697,-2680,-2654,-2620,-2587,-2556,-2523,-2499,-2499,-2534,-2595,-2655,-2691,-2694,-2679,-2666,-2655,-2629,-2579,
--2516,-2454,-2397,-2341,-2288,-2240,-2189,-2127,-2062,-2013,-1980,-1940,-1875,-1794,-1723,-1674,-1633,-1580,-1514,-1452,-1402,
--1351,-1291,-1227,-1176,-1136,-1090,-1031,-967,-906,-848,-787,-728,-675,-626,-577,-526,-472,-410,-339,-266,-201,
--145,-92,-36,20,77,135,190,244,295,340,378,415,460,513,558,588,612,640,670,693,713,
-743,785,823,840,842,851,878,916,945,963,979,1002,1023,1029,1029,1041,1068,1099,1126,1151,1178,
-1199,1213,1225,1238,1239,1226,1214,1214,1217,1207,1188,1178,1187,1208,1232,1257,1281,1311,1352,1411,1480,
-1556,1636,1718,1783,1817,1818,1803,1782,1756,1732,1725,1744,1778,1806,1819,1816,1811,1819,1844,1875,1897,
-1910,1925,1950,1975,1991,1996,1995,1993,1990,1986,1979,1968,1958,1952,1949,1942,1933,1926,1917,1905,1891,
-1881,1876,1870,1862,1857,1855,1852,1847,1842,1836,1825,1811,1801,1795,1789,1783,1779,1775,1767,1756,1748,
-1743,1733,1718,1708,1705,1704,1715,1710,1703,1695,1681,1660,1646,1644,1647,1646,1645,1654,1663,1661,1650,
-1645,1649,1654,1651,1640,1624,1602,1581,1583,1627,1704,1761,1738,1620,1469,1371,1351,1361,1342,1301,1276,
-1264,1212,1098,980,933,968,1023,1042,1023,994,971,949,917,867,799,716,629,554,490,420,328,
-212,89,-25,-121,-202,-269,-328,-389,-463,-555,-654,-749,-839,-934,-1035,-1133,-1215,-1279,-1332,-1380,-1427,
--1483,-1553,-1633,-1709,-1774,-1823,-1853,-1865,-1876,-1907,-1956,-1997,-2007,-1996,-1984,-1984,-1989,-1991,-1985,-1967,-1934,
--1893,-1856,-1820,-1776,-1727,-1683,-1646,-1602,-1548,-1501,-1473,-1435,-1343,-1196,-1054,-975,-959,-957,-943,-936,-963,
--1011,-1050,-1072,-1103,-1158,-1220,-1262,-1276,-1272,-1263,-1259,-1274,-1319,-1387,-1460,-1526,-1580,-1602,-1564,-1464,-1357,
--1315,-1365,-1457,-1508,-1478,-1399,-1347,-1378,-1492,-1647,-1792,-1900,-1975,-2047,-2141,-2262,-2390,-2504,-2592,-2662,-2729,
--2804,-2890,-2975,-3049,-3117,-3188,-3257,-3309,-3342,-3379,-3446,-3549,-3675,-3810,-3947,-4074,-4176,-4252,-4312,-4361,-4397,
--4431,-4484,-4566,-4658,-4727,-4766,-4793,-4832,-4883,-4935,-4977,-5005,-5019,-5009,-4974,-4929,-4900,-4901,-4921,-4942,-4953,
--4958,-4960,-4963,-4972,-4989,-5009,-5024,-5031,-5039,-5053,-5070,-5086,-5105,-5133,-5167,-5198,-5221,-5238,-5253,-5275,-5314,
--5372,-5441,-5509,-5571,-5628,-5686,-5747,-5811,-5877,-5941,-6003,-6066,-6134,-6203,-6266,-6320,-6372,-6433,-6504,-6577,-6641,
--6694,-6745,-6803,-6868,-6935,-7002,-7070,-7138,-7201,-7256,-7306,-7362,-7431,-7503,-7570,-7631,-7692,-7757,-7816,-7860,-7899,
--7955,-8037,-8125,-8200,-8272,-8358,-8460,-8557,-8640,-8719,-8802,-8883,-8960,-9041,-9126,-9200,-9258,-9311,-9374,-9435,-9483,
--9529,-9580,-9597,-9543,-9450,-9411,-9477,-9593,-9686,-9751,-9836,-9950,-10040,-10073,-10073,-10084,-10115,-10154,-10192,-10231,-10264,
--10285,-10300,-10315,-10326,-10326,-10322,-10321,-10322,-10318,-10312,-10308,-10304,-10292,-10276,-10256,-10225,-10175,-10112,-10044,-9963,-9852,
--9714,
--9583,-9489,-9443,-9425,-9408,-9370,-9303,-9215,-9120,-9019,-8908,-8781,-8641,-8497,-8351,-8208,-8071,-7941,-7811,-7676,-7534,
--7388,-7246,-7119,-7000,-6871,-6722,-6566,-6427,-6310,-6194,-6064,-5924,-5786,-5654,-5527,-5404,-5283,-5153,-5005,-4843,-4677,
--4514,-4351,-4181,-4005,-3842,-3704,-3582,-3440,-3269,-3106,-3010,-3006,-3057,-3089,-3027,-2828,-2525,-2219,-2000,-1858,-1707,
--1504,-1296,-1150,-1055,-949,-805,-658,-548,-470,-391,-292,-176,-60,48,155,265,371,454,518,590,692,
-813,928,1036,1150,1268,1375,1466,1552,1645,1753,1871,1991,2096,2186,2274,2373,2472,2561,2653,2760,2871,
-2968,3054,3153,3267,3374,3466,3552,3636,3715,3798,3902,4021,4124,4202,4283,4392,4521,4648,4769,4895,5029,
-5166,5293,5402,5483,5542,5593,5634,5653,5648,5647,5664,5673,5628,5520,5409,5375,5444,5542,5561,5478,5393,
-5421,5580,5792,5991,6161,6287,6348,6358,6359,6347,6270,6125,5991,5925,5900,5884,5933,6102,6319,6436,6395,
-6251,6048,5782,5491,5294,5293,5492,5844,6308,6808,7216,7432,7468,7411,7339,7304,7339,7434,7521,7544,7521,
-7502,7497,7485,7477,7496,7519,7500,7447,7418,7433,7447,7426,7400,7398,7397,7356,7279,7195,7114,7023,6937,
-6890,6894,6922,6948,6971,6994,7012,7019,7027,7043,7063,7078,7088,7102,7118,7129,7135,7142,7155,7168,7178,
-7182,7180,7172,7161,7153,7153,7155,7154,7148,7136,7118,7093,7066,7036,7002,6967,6939,6918,6894,6865,6839,
-6819,6790,6744,6699,6672,6656,6634,6622,6638,6645,6570,6405,6253,6217,6284,6345,6328,6257,6187,6131,6075,
-6019,5973,5936,5898,5857,5818,5781,5746,5717,5702,5709,5738,5784,5825,5835,5815,5792,5793,5811,5822,5807,
-5763,5697,5625,5558,5501,5452,5412,5376,5331,5260,5170,5087,5028,4983,4937,4895,4866,4839,4787,4708,4625,
-4566,4532,4508,4477,4436,4391,4352,4317,4277,4232,4191,4161,4132,4093,4046,4002,3962,3921,3879,3844,3814,
-3777,3732,3687,3648,3611,3569,3522,3474,3418,3347,3267,3195,3157,3160,3190,3209,3190,3130,3050,2971,2898,
-2834,2785,2766,2792,2857,2923,2935,2863,2737,2627,2580,2582,2582,2549,2494,2444,2406,2369,2330,2300,2290,
-2291,2281,2252,2217,2187,2165,2147,2133,2119,2093,2054,2019,2006,2010,2007,1985,1963,1956,1958,1950,1929,
-1914,1927,1959,1975,1950,1893,1837,1805,1789,1773,1755,1742,1732,1717,1696,1675,1654,1626,1591,1557,1532,
-1515,1506,1506,1510,1507,1496,1488,1491,1499,1500,1490,1476,1462,1451,1441,1434,1431,1434,1444,1456,1461,
-1460,1462,1472,1485,1489,1481,1470,1476,1513,1571,1616,1619,1589,1564,1565,1579,1579,1569,1568,1579,1580,
-1564,1550,1554,1566,1567,1561,1571,1600,1627,1640,1649,1663,1673,1674,1672,1680,1691,1693,1690,1697,1708,
-1705,1679,1648,1628,1615,1595,1567,1539,1518,1502,1491,1484,1478,1470,1462,1455,1446,1432,1414,1396,1381,
-1366,1350,1333,1311,1284,1255,1228,1202,1175,1155,1145,1138,1124,1100,1076,1056,1040,1023,1003,977,938,
-892,847,810,778,747,717,685,651,614,580,547,512,474,437,403,367,330,293,256,217,176,
-138,101,63,19,-24,-65,-102,-137,-173,-214,-258,-302,-343,-382,-423,-465,-503,-537,-573,-611,-646,
--675,-703,-731,-760,-793,-832,-871,-903,-930,-961,-997,-1030,-1056,-1082,-1114,-1147,-1176,-1205,-1236,-1270,-1303,
--1337,-1376,-1414,-1448,-1479,-1510,-1541,-1567,-1593,-1624,-1659,-1691,-1719,-1750,-1784,-1818,-1849,-1878,-1908,-1941,-1976,
--2008,-2035,-2058,-2081,-2103,-2122,-2141,-2162,-2187,-2210,-2231,-2252,-2273,-2293,-2310,-2329,-2349,-2364,-2373,-2382,-2394,
--2407,-2417,-2425,-2435,-2443,-2450,-2456,-2464,-2469,-2468,-2467,-2470,-2472,-2467,-2459,-2451,-2443,-2434,-2422,-2409,-2394,
--2378,-2363,-2348,-2331,-2313,-2296,-2282,-2269,-2255,-2242,-2233,-2222,-2207,-2190,-2173,-2156,-2137,-2117,-2100,-2082,-2061,
--2042,-2027,-2014,-1998,-1980,-1963,-1949,-1935,-1921,-1906,-1890,-1872,-1855,-1842,-1830,-1811,-1790,-1771,-1758,-1746,-1730,
--1714,-1699,-1684,-1669,-1654,-1639,-1622,-1601,-1579,-1559,-1540,-1522,-1503,-1482,-1461,-1443,-1424,-1402,-1377,-1358,-1345,
--1329,-1308,-1286,-1268,-1249,-1226,-1205,-1191,-1176,-1156,-1136,-1120,-1106,-1084,-1061,-1044,-1029,-1006,-976,-947,-919,
--884,-845,-812,-788,-764,-736,-710,-686,-656,-615,-563,-502,-440,-395,-381,-385,-377,-350,-321,-302,-285,
--256,-225,-202,-181,-150,-112,-80,-52,-21,11,39,68,103,138,167,199,250,319,388,449,510,
-579,647,709,775,852,917,935,899,852,867,984,1184,1403,1589,1744,1899,2074,2258,2426,2551,2599,
-2541,2383,2174,1979,1843,1780,1790,1853,1930,1982,1993,1976,1969,2007,2095,2183,2209,2151,2055,1983,1957,
-1960,1975,1993,1995,1954,1874,1792,1725,1649,1534,1391,1260,1167,1103,1051,995,919,808,670,532,416,
-324,245,174,118,76,41,4,-45,-113,-202,-303,-397,-471,-529,-581,-632,-683,-733,-786,-836,-870,
--884,-901,-942,-1006,-1071,-1130,-1196,-1277,-1358,-1427,-1493,-1571,-1656,-1734,-1804,-1884,-1975,-2062,-2132,-2190,-2248,
--2304,-2353,-2394,-2432,-2471,-2507,-2541,-2575,-2608,-2636,-2653,-2665,-2677,-2680,-2658,-2608,-2557,-2533,-2531,-2520,-2484,
--2440,-2415,-2414,-2432,-2474,-2543,-2627,-2695,-2734,-2752,-2757,-2746,-2721,-2696,-2678,-2659,-2633,-2605,-2581,-2559,-2529,
--2491,-2455,-2440,-2455,-2489,-2520,-2537,-2553,-2585,-2622,-2630,-2593,-2528,-2466,-2417,-2375,-2329,-2275,-2206,-2128,-2058,
--2012,-1982,-1943,-1884,-1817,-1764,-1726,-1687,-1631,-1563,-1501,-1452,-1405,-1347,-1287,-1239,-1206,-1170,-1119,-1057,-996,
--938,-881,-824,-770,-720,-672,-624,-568,-501,-426,-354,-293,-241,-192,-142,-87,-31,26,82,140,198,
-250,290,328,377,439,496,536,566,597,632,665,696,733,776,814,835,844,857,884,922,957,
-981,999,1018,1034,1038,1040,1054,1084,1116,1140,1160,1179,1192,1192,1186,1176,1160,1140,1131,1143,1166,
-1184,1192,1204,1229,1268,1317,1372,1422,1462,1492,1519,1552,1600,1670,1758,1836,1878,1881,1863,1839,1814,
-1798,1804,1829,1860,1882,1892,1896,1900,1912,1933,1955,1966,1968,1973,1986,2004,2016,2016,2007,1993,1979,
-1965,1950,1934,1923,1919,1919,1917,1916,1917,1917,1912,1906,1904,1904,1901,1893,1885,1878,1869,1859,1852,
-1845,1834,1822,1812,1804,1793,1783,1777,1771,1758,1742,1733,1731,1726,1717,1712,1714,1715,1719,1711,1702,
-1698,1689,1674,1660,1658,1662,1662,1661,1668,1678,1679,1669,1660,1657,1656,1650,1640,1630,1616,1602,1613,
-1677,1782,1857,1822,1669,1485,1375,1356,1360,1327,1274,1249,1246,1208,1103,971,887,881,922,961,973,
-959,930,898,865,826,772,697,615,542,482,416,322,198,68,-44,-132,-206,-274,-334,-393,-468,
--570,-687,-798,-891,-974,-1058,-1146,-1234,-1320,-1395,-1452,-1495,-1539,-1602,-1680,-1755,-1817,-1861,-1890,-1905,-1916,
--1939,-1977,-2013,-2030,-2030,-2032,-2042,-2054,-2056,-2043,-2012,-1967,-1922,-1882,-1844,-1797,-1748,-1711,-1683,-1644,-1586,
--1528,-1486,-1432,-1326,-1169,-1011,-900,-836,-796,-779,-806,-874,-946,-995,-1034,-1093,-1168,-1224,-1238,-1230,-1226,
--1234,-1250,-1284,-1348,-1430,-1502,-1552,-1595,-1636,-1647,-1594,-1490,-1396,-1369,-1404,-1446,-1441,-1378,-1305,-1291,-1377,
--1549,-1743,-1897,-1994,-2065,-2150,-2261,-2383,-2496,-2592,-2672,-2746,-2824,-2911,-3004,-3092,-3172,-3242,-3292,-3317,-3331,
--3375,-3476,-3626,-3790,-3938,-4060,-4153,-4220,-4274,-4327,-4382,-4425,-4458,-4499,-4566,-4651,-4726,-4776,-4810,-4844,-4886,
--4930,-4969,-4996,-5002,-4982,-4942,-4902,-4884,-4892,-4914,-4932,-4940,-4940,-4937,-4934,-4940,-4958,-4981,-4999,-5012,-5024,
--5037,-5049,-5061,-5082,-5114,-5151,-5180,-5198,-5206,-5216,-5242,-5293,-5364,-5436,-5500,-5555,-5611,-5671,-5733,-5796,-5857,
--5917,-5976,-6040,-6112,-6183,-6244,-6299,-6358,-6425,-6497,-6565,-6623,-6675,-6729,-6789,-6857,-6928,-6999,-7069,-7138,-7202,
--7257,-7306,-7356,-7414,-7480,-7547,-7609,-7673,-7737,-7794,-7840,-7885,-7943,-8016,-8089,-8153,-8225,-8319,-8427,-8525,-8606,
--8683,-8765,-8844,-8919,-8997,-9078,-9149,-9206,-9265,-9334,-9400,-9452,-9506,-9564,-9587,-9536,-9449,-9417,-9482,-9588,-9671,
--9737,-9833,-9954,-10041,-10064,-10055,-10061,-10091,-10131,-10171,-10212,-10245,-10262,-10272,-10285,-10299,-10305,-10305,-10307,-10310,-10306,
--10299,
--10292,-10286,-10276,-10261,-10240,-10204,-10146,-10078,-10007,-9919,-9799,-9657,-9533,-9457,-9425,-9407,-9377,-9324,-9248,-9154,-9052,
--8946,-8833,-8710,-8579,-8443,-8307,-8172,-8043,-7919,-7795,-7668,-7531,-7382,-7234,-7104,-6997,-6889,-6759,-6612,-6472,-6351,
--6232,-6097,-5948,-5800,-5661,-5532,-5412,-5294,-5167,-5022,-4861,-4692,-4522,-4348,-4172,-3998,-3841,-3705,-3572,-3416,-3239,
--3084,-2990,-2966,-2993,-3036,-3033,-2912,-2653,-2335,-2068,-1876,-1694,-1484,-1291,-1175,-1108,-1010,-851,-675,-531,-427,
--341,-255,-159,-54,53,160,270,388,498,588,668,763,876,992,1101,1208,1314,1413,1501,1587,1680,
-1782,1891,2002,2107,2203,2297,2397,2495,2585,2678,2790,2909,3011,3096,3186,3287,3384,3469,3552,3634,3711,
-3791,3889,4004,4105,4185,4273,4397,4544,4681,4797,4909,5031,5161,5289,5398,5477,5524,5549,5560,5557,5545,
-5544,5563,5579,5551,5461,5344,5264,5268,5333,5388,5398,5417,5512,5681,5852,5981,6079,6160,6216,6252,6289,
-6306,6241,6079,5895,5765,5683,5626,5636,5753,5911,5979,5909,5754,5559,5320,5064,4907,4964,5262,5753,6346,
-6903,7279,7423,7414,7369,7341,7335,7362,7433,7512,7560,7579,7599,7618,7614,7591,7571,7538,7465,7375,7329,
-7342,7367,7367,7364,7378,7383,7347,7283,7222,7165,7087,6991,6912,6865,6841,6832,6846,6883,6923,6948,6966,
-6995,7037,7072,7091,7100,7114,7131,7147,7162,7182,7205,7217,7213,7202,7195,7197,7199,7199,7199,7198,7194,
-7185,7170,7149,7119,7084,7048,7014,6979,6945,6912,6881,6855,6831,6802,6759,6707,6664,6631,6601,6581,6589,
-6611,6584,6463,6299,6205,6234,6320,6356,6306,6217,6144,6100,6064,6022,5979,5939,5901,5859,5814,5778,5755,
-5745,5747,5772,5823,5878,5902,5884,5847,5827,5832,5845,5842,5807,5743,5668,5598,5536,5481,5433,5395,5353,
-5290,5207,5126,5063,5012,4961,4914,4880,4850,4802,4731,4650,4579,4527,4491,4459,4424,4388,4358,4332,4296,
-4249,4203,4171,4144,4105,4056,4009,3969,3931,3892,3855,3820,3785,3749,3715,3682,3643,3596,3544,3490,3430,
-3364,3296,3237,3197,3181,3185,3188,3167,3118,3052,2981,2911,2843,2784,2754,2775,2848,2937,2976,2918,2778,
-2632,2552,2545,2561,2550,2510,2470,2444,2418,2378,2335,2311,2307,2301,2279,2250,2226,2208,2191,2175,2160,
-2139,2108,2078,2057,2041,2016,1987,1971,1972,1975,1960,1931,1908,1906,1920,1935,1930,1899,1857,1819,1794,
-1775,1759,1747,1739,1729,1713,1693,1673,1646,1610,1570,1536,1517,1511,1513,1515,1509,1499,1493,1498,1511,
-1520,1516,1498,1474,1455,1448,1450,1453,1455,1460,1466,1468,1464,1460,1461,1465,1463,1457,1456,1477,1531,
-1603,1653,1651,1608,1569,1561,1568,1566,1556,1560,1579,1591,1585,1571,1563,1557,1547,1549,1578,1620,1648,
-1654,1657,1667,1670,1658,1646,1652,1667,1671,1662,1662,1676,1688,1680,1657,1633,1613,1591,1565,1541,1519,
-1501,1488,1482,1474,1460,1448,1444,1442,1432,1413,1395,1381,1366,1349,1330,1311,1290,1265,1238,1210,1183,
-1163,1154,1149,1136,1111,1082,1057,1037,1020,1003,979,945,903,863,828,796,764,732,700,664,625,
-589,554,518,480,442,409,376,340,305,271,235,196,159,124,88,48,6,-34,-72,-109,-145,
--184,-225,-267,-307,-347,-390,-436,-479,-518,-556,-592,-623,-651,-677,-706,-738,-774,-816,-854,-883,-906,
--934,-970,-1003,-1028,-1053,-1084,-1117,-1146,-1174,-1206,-1240,-1273,-1307,-1345,-1383,-1418,-1449,-1481,-1512,-1540,-1566,
--1595,-1628,-1660,-1691,-1723,-1758,-1792,-1823,-1853,-1886,-1921,-1954,-1982,-2005,-2027,-2050,-2074,-2095,-2114,-2134,-2156,
--2178,-2198,-2219,-2241,-2260,-2277,-2295,-2313,-2325,-2332,-2339,-2351,-2363,-2373,-2383,-2395,-2407,-2415,-2422,-2429,-2434,
--2433,-2433,-2436,-2438,-2432,-2423,-2416,-2413,-2406,-2392,-2376,-2361,-2347,-2331,-2314,-2297,-2279,-2263,-2249,-2234,-2219,
--2207,-2199,-2190,-2176,-2159,-2144,-2129,-2111,-2092,-2074,-2056,-2037,-2019,-2006,-1993,-1975,-1953,-1935,-1922,-1911,-1900,
--1889,-1875,-1858,-1843,-1831,-1819,-1800,-1778,-1761,-1748,-1737,-1722,-1706,-1692,-1679,-1666,-1652,-1637,-1618,-1597,-1576,
--1556,-1536,-1517,-1499,-1480,-1460,-1442,-1424,-1406,-1384,-1363,-1345,-1330,-1312,-1293,-1273,-1252,-1230,-1210,-1195,-1178,
--1158,-1138,-1123,-1108,-1089,-1069,-1052,-1037,-1018,-994,-969,-943,-911,-877,-849,-826,-806,-786,-765,-736,-696,
--654,-610,-554,-482,-420,-397,-404,-402,-375,-343,-325,-309,-281,-248,-226,-207,-176,-138,-107,-82,-54,
--20,13,44,77,111,143,182,239,309,377,442,515,592,662,729,809,899,958,949,892,853,
-895,1030,1224,1428,1612,1786,1969,2162,2341,2472,2529,2487,2344,2137,1938,1805,1747,1742,1775,1836,1908,
-1959,1975,1965,1960,1989,2058,2130,2150,2096,2006,1933,1899,1892,1905,1934,1953,1926,1850,1771,1711,1643,
-1525,1372,1236,1150,1099,1055,1000,924,818,689,561,456,371,293,217,150,89,29,-33,-95,-157,
--226,-303,-378,-443,-500,-555,-609,-660,-712,-766,-814,-844,-856,-873,-915,-975,-1035,-1090,-1154,-1231,-1309,
--1379,-1450,-1532,-1618,-1696,-1769,-1847,-1933,-2014,-2084,-2146,-2204,-2256,-2301,-2341,-2380,-2417,-2453,-2492,-2535,-2575,
--2600,-2610,-2614,-2620,-2619,-2593,-2540,-2489,-2465,-2466,-2462,-2434,-2398,-2376,-2377,-2398,-2444,-2515,-2593,-2654,-2692,
--2714,-2722,-2711,-2689,-2672,-2663,-2654,-2635,-2611,-2592,-2580,-2563,-2530,-2478,-2421,-2383,-2374,-2381,-2394,-2423,-2485,
--2564,-2613,-2602,-2544,-2478,-2428,-2393,-2358,-2305,-2226,-2133,-2054,-2003,-1970,-1933,-1886,-1839,-1800,-1764,-1717,-1654,
--1585,-1524,-1474,-1427,-1374,-1318,-1271,-1239,-1208,-1163,-1105,-1044,-988,-936,-884,-831,-781,-735,-690,-636,-568,
--493,-420,-358,-304,-254,-205,-155,-100,-43,15,75,135,189,227,260,306,367,429,476,513,550,
-591,631,669,711,754,793,821,841,859,886,924,963,994,1016,1033,1044,1043,1036,1039,1057,1079,
-1095,1106,1120,1131,1132,1127,1122,1118,1115,1121,1143,1178,1215,1245,1269,1289,1313,1354,1415,1484,1540,
-1575,1591,1600,1619,1664,1733,1801,1842,1853,1850,1848,1848,1854,1872,1899,1921,1933,1939,1944,1946,1946,
-1946,1945,1939,1931,1929,1939,1959,1976,1983,1977,1966,1955,1947,1940,1933,1928,1925,1921,1916,1914,1920,
-1926,1927,1928,1933,1937,1934,1923,1911,1898,1882,1866,1851,1839,1825,1813,1804,1796,1783,1770,1764,1759,
-1747,1733,1727,1728,1726,1718,1715,1718,1719,1716,1707,1701,1701,1699,1687,1672,1669,1675,1681,1683,1687,
-1694,1695,1686,1672,1661,1653,1644,1634,1625,1614,1607,1622,1680,1767,1819,1773,1633,1479,1393,1377,1366,
-1317,1256,1229,1234,1219,1141,1015,900,844,853,892,915,899,855,812,783,760,724,670,607,550,
-496,427,324,192,61,-40,-115,-180,-247,-311,-374,-451,-556,-687,-820,-933,-1018,-1081,-1141,-1217,-1316,
--1422,-1507,-1563,-1605,-1661,-1733,-1805,-1862,-1904,-1936,-1957,-1967,-1977,-1995,-2020,-2044,-2063,-2082,-2100,-2112,-2111,
--2090,-2051,-1998,-1947,-1902,-1860,-1813,-1768,-1739,-1717,-1680,-1617,-1548,-1490,-1424,-1313,-1152,-977,-828,-722,-669,
--685,-773,-893,-981,-1022,-1054,-1115,-1186,-1221,-1213,-1198,-1208,-1237,-1272,-1323,-1406,-1504,-1576,-1611,-1641,-1691,
--1737,-1723,-1629,-1499,-1405,-1383,-1405,-1404,-1342,-1249,-1210,-1296,-1500,-1740,-1925,-2031,-2099,-2181,-2292,-2412,-2521,
--2615,-2698,-2774,-2853,-2939,-3034,-3127,-3208,-3267,-3298,-3305,-3321,-3391,-3534,-3721,-3900,-4037,-4131,-4193,-4240,-4284,
--4337,-4392,-4435,-4465,-4501,-4562,-4641,-4717,-4775,-4816,-4850,-4885,-4922,-4959,-4984,-4984,-4954,-4912,-4881,-4877,-4893,
--4911,-4921,-4921,-4916,-4909,-4903,-4908,-4927,-4952,-4974,-4990,-5003,-5014,-5024,-5040,-5066,-5099,-5132,-5156,-5170,-5178,
--5191,-5226,-5289,-5366,-5436,-5491,-5539,-5592,-5651,-5711,-5772,-5831,-5888,-5944,-6008,-6081,-6153,-6216,-6274,-6340,-6415,
--6488,-6552,-6609,-6667,-6728,-6789,-6851,-6918,-6990,-7065,-7140,-7206,-7261,-7306,-7349,-7399,-7459,-7525,-7590,-7654,-7716,
--7771,-7818,-7863,-7917,-7980,-8042,-8105,-8183,-8285,-8395,-8489,-8568,-8646,-8728,-8804,-8874,-8947,-9026,-9097,-9158,-9222,
--9298,-9370,-9427,-9483,-9541,-9568,-9530,-9464,-9445,-9500,-9581,-9644,-9710,-9819,-9947,-10031,-10046,-10033,-10037,-10065,-10101,
--10140,-10181,-10211,-10224,-10231,-10244,-10260,-10270,-10275,-10282,-10289,-10290,-10284,-10277,-10268,-10255,-10236,-10209,-10165,-10104,-10035,
--9960,
--9865,-9734,-9591,-9482,-9431,-9417,-9399,-9356,-9286,-9197,-9094,-8986,-8879,-8770,-8657,-8536,-8408,-8277,-8146,-8021,-7903,
--7789,-7668,-7530,-7373,-7212,-7075,-6967,-6866,-6742,-6594,-6449,-6323,-6208,-6086,-5951,-5809,-5669,-5538,-5418,-5302,-5174,
--5026,-4862,-4694,-4523,-4344,-4159,-3982,-3832,-3704,-3572,-3408,-3230,-3084,-2999,-2962,-2953,-2967,-2975,-2907,-2708,-2417,
--2132,-1901,-1698,-1499,-1341,-1251,-1187,-1077,-906,-716,-543,-398,-282,-196,-116,-18,94,198,292,398,520,
-635,729,820,926,1041,1150,1251,1349,1441,1530,1619,1712,1805,1898,1998,2102,2204,2305,2408,2509,2601,
-2694,2806,2929,3041,3132,3216,3303,3390,3471,3553,3638,3718,3796,3884,3984,4079,4165,4262,4390,4536,4671,
-4787,4899,5017,5139,5255,5353,5423,5461,5478,5485,5484,5475,5464,5464,5474,5480,5454,5380,5281,5215,5222,
-5284,5363,5455,5578,5719,5834,5909,5974,6050,6124,6193,6272,6336,6312,6164,5952,5764,5613,5480,5394,5406,
-5481,5509,5429,5270,5079,4871,4677,4581,4684,5030,5593,6264,6855,7195,7267,7222,7215,7266,7309,7322,7350,
-7419,7508,7592,7660,7704,7710,7684,7633,7548,7426,7314,7274,7309,7359,7378,7376,7373,7362,7332,7301,7294,
-7295,7268,7198,7099,6989,6880,6796,6763,6779,6813,6839,6861,6899,6956,7010,7042,7061,7085,7119,7150,7174,
-7198,7222,7238,7237,7230,7230,7234,7234,7229,7228,7231,7230,7224,7212,7190,7155,7114,7075,7038,6997,6954,
-6920,6892,6862,6827,6792,6753,6703,6649,6604,6569,6542,6535,6554,6557,6481,6330,6206,6203,6297,6366,6332,
-6235,6161,6140,6130,6092,6030,5971,5925,5884,5843,5814,5804,5805,5814,5835,5873,5917,5940,5932,5905,5881,
-5871,5868,5860,5832,5779,5710,5640,5575,5514,5459,5410,5364,5309,5241,5169,5103,5041,4980,4925,4882,4845,
-4801,4744,4674,4599,4530,4476,4438,4406,4377,4354,4333,4304,4262,4219,4186,4157,4115,4062,4011,3971,3938,
-3907,3878,3849,3820,3788,3753,3713,3666,3615,3563,3509,3447,3383,3324,3272,3228,3194,3176,3165,3147,3113,
-3065,3006,2937,2862,2797,2760,2760,2794,2845,2877,2850,2754,2630,2540,2516,2534,2547,2531,2497,2465,2438,
-2404,2366,2338,2323,2312,2295,2275,2257,2238,2214,2191,2173,2157,2137,2115,2094,2069,2036,2005,1991,1993,
-1990,1969,1936,1905,1881,1874,1888,1907,1906,1871,1822,1786,1769,1759,1749,1740,1731,1717,1701,1684,1665,
-1633,1589,1547,1524,1521,1527,1531,1528,1518,1509,1505,1511,1521,1523,1508,1482,1462,1460,1469,1476,1475,
-1471,1470,1467,1461,1452,1445,1440,1437,1437,1444,1467,1514,1575,1620,1622,1590,1559,1551,1555,1552,1545,
-1551,1572,1591,1595,1590,1578,1560,1544,1551,1588,1631,1649,1646,1648,1664,1672,1659,1641,1641,1654,1657,
-1645,1638,1651,1671,1676,1662,1639,1615,1591,1569,1548,1526,1506,1493,1485,1473,1454,1436,1430,1430,1420,
-1401,1384,1373,1361,1345,1329,1314,1296,1272,1245,1217,1191,1171,1159,1151,1136,1111,1082,1054,1029,1006,
-983,960,930,895,860,827,795,763,733,703,670,633,598,566,529,488,447,411,378,343,309,
-276,243,208,173,139,105,67,27,-12,-51,-89,-127,-164,-203,-242,-280,-319,-363,-411,-459,-503,
--542,-576,-605,-631,-657,-686,-718,-756,-798,-836,-863,-883,-909,-943,-975,-1000,-1026,-1057,-1089,-1117,-1143,
--1175,-1211,-1246,-1280,-1315,-1351,-1385,-1417,-1449,-1481,-1510,-1538,-1567,-1600,-1632,-1664,-1696,-1729,-1761,-1793,-1826,
--1860,-1893,-1922,-1946,-1968,-1992,-2018,-2045,-2070,-2090,-2110,-2130,-2149,-2168,-2190,-2212,-2230,-2246,-2262,-2278,-2288,
--2294,-2303,-2314,-2325,-2333,-2344,-2359,-2373,-2381,-2387,-2394,-2399,-2399,-2397,-2399,-2400,-2394,-2385,-2381,-2380,-2373,
--2358,-2341,-2327,-2314,-2298,-2280,-2262,-2244,-2230,-2216,-2201,-2187,-2176,-2168,-2158,-2142,-2124,-2109,-2096,-2079,-2060,
--2042,-2025,-2008,-1993,-1980,-1967,-1950,-1932,-1917,-1904,-1893,-1882,-1871,-1859,-1844,-1829,-1819,-1807,-1791,-1771,-1755,
--1743,-1729,-1713,-1698,-1685,-1672,-1660,-1646,-1630,-1610,-1590,-1572,-1554,-1534,-1514,-1497,-1480,-1460,-1440,-1423,-1409,
--1391,-1369,-1348,-1329,-1313,-1295,-1277,-1256,-1236,-1218,-1202,-1186,-1167,-1147,-1129,-1114,-1099,-1085,-1073,-1058,-1040,
--1019,-996,-969,-937,-906,-879,-858,-845,-838,-820,-770,-695,-631,-595,-566,-514,-457,-428,-429,-423,-392,
--359,-340,-325,-295,-263,-242,-224,-195,-159,-131,-109,-80,-43,-7,23,55,89,126,173,234,302,
-369,442,528,616,691,766,861,956,998,966,904,886,949,1081,1253,1439,1623,1808,2000,2203,2390,
-2520,2548,2453,2252,2015,1827,1731,1707,1716,1746,1804,1881,1941,1963,1959,1955,1973,2018,2068,2086,2048,
-1972,1898,1850,1829,1832,1856,1871,1843,1771,1697,1648,1596,1500,1371,1255,1178,1123,1063,992,910,810,
-696,585,495,417,337,255,180,112,44,-26,-95,-159,-226,-294,-358,-413,-467,-525,-582,-634,-685,
--741,-791,-822,-836,-852,-889,-942,-996,-1051,-1115,-1189,-1262,-1331,-1405,-1490,-1581,-1666,-1741,-1814,-1887,-1957,
--2022,-2080,-2130,-2174,-2218,-2263,-2306,-2346,-2386,-2435,-2491,-2540,-2565,-2565,-2555,-2547,-2538,-2515,-2476,-2438,-2421,
--2421,-2415,-2394,-2368,-2356,-2365,-2396,-2447,-2511,-2569,-2611,-2641,-2666,-2678,-2669,-2649,-2639,-2644,-2652,-2647,-2629,
--2606,-2586,-2568,-2539,-2487,-2416,-2355,-2323,-2315,-2316,-2334,-2390,-2479,-2555,-2577,-2541,-2476,-2416,-2375,-2348,-2313,
--2249,-2160,-2076,-2017,-1976,-1937,-1895,-1856,-1818,-1770,-1711,-1648,-1589,-1533,-1483,-1435,-1387,-1335,-1285,-1244,-1208,
--1164,-1109,-1047,-990,-939,-891,-843,-795,-751,-706,-654,-589,-518,-450,-387,-328,-274,-226,-179,-127,-71,
--14,42,97,145,182,215,260,320,380,428,468,511,558,602,643,683,723,759,790,813,834,
-860,898,942,981,1009,1028,1038,1034,1019,1006,1006,1012,1018,1023,1035,1050,1065,1080,1103,1132,1159,
-1180,1201,1227,1260,1291,1307,1300,1285,1291,1335,1407,1483,1547,1594,1625,1651,1688,1740,1793,1826,1840,
-1849,1862,1876,1889,1904,1920,1931,1936,1941,1947,1947,1938,1924,1911,1900,1890,1886,1894,1912,1932,1945,
-1948,1945,1943,1944,1949,1954,1956,1953,1944,1933,1929,1933,1940,1942,1944,1950,1953,1946,1931,1916,1901,
-1885,1865,1847,1828,1810,1796,1789,1784,1773,1763,1758,1755,1746,1735,1731,1733,1730,1721,1715,1717,1716,
-1719,1714,1710,1711,1708,1697,1684,1682,1692,1700,1701,1699,1700,1701,1696,1682,1666,1652,1640,1628,1613,
-1601,1597,1610,1644,1684,1693,1641,1543,1451,1406,1398,1381,1331,1269,1229,1217,1205,1154,1051,926,835,
-812,838,855,828,773,729,711,703,684,649,608,567,517,440,328,195,72,-18,-85,-152,-227,
--300,-364,-432,-528,-660,-815,-960,-1065,-1121,-1153,-1202,-1294,-1414,-1527,-1607,-1664,-1722,-1789,-1855,-1907,-1947,
--1982,-2007,-2017,-2014,-2013,-2029,-2059,-2093,-2120,-2135,-2141,-2136,-2117,-2080,-2027,-1969,-1916,-1868,-1823,-1785,-1761,
--1742,-1705,-1638,-1562,-1497,-1428,-1319,-1156,-964,-789,-671,-639,-706,-845,-982,-1052,-1060,-1068,-1117,-1179,-1209,
--1206,-1208,-1241,-1288,-1335,-1394,-1481,-1577,-1644,-1674,-1696,-1739,-1782,-1778,-1697,-1566,-1449,-1392,-1386,-1374,-1312,
--1231,-1215,-1332,-1559,-1804,-1980,-2072,-2130,-2210,-2321,-2442,-2552,-2648,-2734,-2812,-2890,-2975,-3066,-3153,-3222,-3266,
--3288,-3304,-3351,-3462,-3639,-3838,-4003,-4110,-4170,-4208,-4244,-4285,-4334,-4381,-4418,-4449,-4492,-4558,-4636,-4707,-4763,
--4808,-4846,-4880,-4913,-4944,-4963,-4955,-4920,-4880,-4862,-4870,-4889,-4901,-4901,-4896,-4888,-4879,-4874,-4880,-4898,-4924,
--4947,-4965,-4978,-4986,-4997,-5017,-5045,-5075,-5102,-5125,-5145,-5162,-5186,-5229,-5297,-5371,-5433,-5480,-5526,-5578,-5631,
--5683,-5739,-5798,-5855,-5910,-5972,-6044,-6118,-6183,-6244,-6313,-6391,-6468,-6537,-6601,-6667,-6733,-6793,-6848,-6908,-6979,
--7057,-7134,-7199,-7252,-7297,-7340,-7388,-7444,-7506,-7569,-7631,-7691,-7746,-7793,-7836,-7882,-7937,-7997,-8065,-8149,-8251,
--8355,-8445,-8524,-8605,-8688,-8762,-8828,-8901,-8982,-9056,-9119,-9183,-9260,-9337,-9400,-9457,-9509,-9530,-9502,-9457,-9452,
--9498,-9555,-9601,-9671,-9793,-9929,-10009,-10019,-10004,-10009,-10034,-10066,-10101,-10138,-10167,-10178,-10186,-10202,-10222,-10235,-10244,
--10253,
--10264,-10268,-10264,-10255,-10241,-10220,-10195,-10163,-10120,-10061,-9994,-9917,-9815,-9682,-9549,-9459,-9427,-9420,-9396,-9338,-9255,
--9157,
--9051-8943,-8840,-8739,-8633,-8519,-8395,-8265,-8135,-8013,-7901,-7795,-7678,-7537,-7371,-7203,-7057,-6939,-6823,-6686,
--6530,-6381,-6257,-6153,-6053,-5944,-5819,-5682,-5548,-5427,-5312,-5181,-5024,-4854,-4689,-4527,-4353,-4163,-3977,-3823,-3700,
--3573,-3411,-3233,-3090,-3008,-2960,-2916,-2887,-2882,-2850,-2720,-2484,-2206,-1948,-1727,-1551,-1435,-1369,-1295,-1166,-993,
--808,-616,-419,-251,-141,-63,34,156,259,331,410,524,651,758,851,950,1059,1166,1268,1366,1458,
-1547,1639,1734,1823,1907,1995,2094,2197,2300,2405,2510,2606,2696,2800,2926,3053,3160,3247,3328,3406,3482,
-3560,3645,3733,3817,3902,3995,4093,4195,4304,4421,4539,4650,4761,4877,4994,5102,5194,5268,5321,5356,5384,
-5412,5433,5437,5423,5406,5410,5446,5483,5463,5365,5249,5203,5259,5372,5495,5610,5713,5790,5848,5916,6006,
-6097,6178,6269,6353,6360,6243,6047,5853,5671,5469,5270,5150,5123,5105,5014,4847,4658,4491,4378,4361,4494,
-4824,5360,6020,6611,6944,7010,6988,7045,7172,7249,7238,7221,7281,7409,7542,7640,7697,7719,7705,7647,7541,
-7414,7334,7351,7441,7524,7544,7507,7452,7396,7348,7329,7352,7404,7445,7439,7368,7235,7073,6927,6833,6790,
-6773,6764,6767,6792,6836,6882,6919,6957,7008,7071,7127,7164,7190,7214,7238,7255,7267,7276,7277,7268,7260,
-7262,7267,7261,7246,7226,7197,7153,7105,7066,7033,6996,6962,6948,6942,6917,6872,6829,6795,6755,6702,6654,
-6621,6593,6567,6561,6564,6519,6396,6261,6216,6271,6323,6292,6209,6163,6179,6199,6164,6085,6008,5959,5927,
-5897,5870,5856,5860,5878,5903,5925,5937,5938,5937,5936,5933,5919,5897,5874,5847,5806,5748,5680,5614,5553,
-5495,5438,5384,5331,5275,5214,5147,5074,5002,4943,4896,4854,4809,4759,4698,4624,4547,4483,4438,4404,4374,
-4350,4330,4305,4268,4228,4193,4159,4114,4060,4010,3969,3936,3911,3896,3886,3870,3838,3791,3735,3677,3624,
-3576,3527,3472,3414,3361,3309,3256,3209,3179,3164,3149,3123,3087,3037,2970,2892,2826,2781,2748,2720,2705,
-2719,2746,2746,2694,2611,2545,2521,2523,2518,2490,2453,2421,2396,2373,2352,2338,2329,2319,2305,2284,2253,
-2215,2185,2167,2155,2138,2121,2104,2082,2052,2024,2011,2009,2001,1981,1953,1915,1872,1844,1858,1899,1917,
-1880,1815,1769,1758,1759,1754,1742,1731,1718,1700,1686,1676,1656,1618,1575,1548,1544,1553,1562,1566,1563,
-1549,1529,1514,1512,1514,1507,1491,1479,1479,1486,1486,1477,1469,1467,1467,1463,1455,1444,1435,1434,1438,
-1442,1449,1469,1505,1541,1557,1553,1544,1542,1542,1537,1532,1538,1553,1568,1578,1584,1581,1565,1551,1559,
-1589,1615,1616,1605,1610,1639,1665,1664,1648,1641,1647,1648,1637,1629,1637,1655,1664,1656,1639,1619,1600,
-1581,1562,1540,1517,1500,1489,1475,1452,1430,1418,1412,1400,1382,1369,1362,1353,1340,1328,1316,1297,1270,
-1241,1216,1196,1178,1163,1150,1134,1111,1085,1057,1028,997,968,942,917,888,856,823,790,758,730,
-704,673,639,607,576,541,498,454,416,382,347,311,278,246,213,181,149,116,80,41,4,
--33,-73,-112,-150,-188,-226,-264,-302,-344,-391,-438,-484,-524,-560,-589,-615,-642,-669,-700,-736,-776,
--813,-839,-860,-884,-915,-945,-972,-999,-1032,-1064,-1089,-1113,-1144,-1180,-1216,-1250,-1284,-1319,-1352,-1385,-1418,
--1450,-1479,-1508,-1538,-1571,-1604,-1636,-1668,-1699,-1729,-1762,-1798,-1832,-1860,-1884,-1906,-1930,-1957,-1985,-2014,-2040,
--2064,-2084,-2103,-2120,-2139,-2161,-2182,-2199,-2214,-2230,-2245,-2255,-2263,-2273,-2285,-2294,-2300,-2311,-2326,-2340,-2347,
--2352,-2360,-2366,-2366,-2363,-2363,-2362,-2357,-2351,-2348,-2346,-2337,-2321,-2305,-2292,-2280,-2265,-2247,-2229,-2211,-2196,
--2183,-2171,-2159,-2150,-2141,-2128,-2110,-2091,-2077,-2064,-2049,-2030,-2012,-1996,-1981,-1967,-1953,-1940,-1926,-1913,-1903,
--1891,-1878,-1864,-1853,-1841,-1826,-1812,-1802,-1792,-1779,-1764,-1751,-1737,-1722,-1705,-1689,-1676,-1664,-1650,-1636,-1620,
--1602,-1584,-1569,-1553,-1534,-1514,-1498,-1482,-1463,-1440,-1422,-1410,-1395,-1375,-1352,-1332,-1315,-1300,-1283,-1265,-1247,
--1229,-1214,-1200,-1185,-1167,-1148,-1131,-1118,-1109,-1099,-1084,-1066,-1047,-1023,-994,-962,-932,-906,-885,-880,-886,
--869,-789,-663,-558,-520,-521,-508,-473,-447,-441,-428,-398,-369,-353,-336,-304,-271,-251,-233,-205,-172,
--148,-126,-95,-56,-21,9,42,80,121,172,235,301,369,451,549,644,721,801,902,989,1007,
-953,900,919,1012,1147,1302,1474,1653,1832,2018,2225,2432,2578,2600,2474,2240,1982,1790,1696,1672,1677,
-1708,1775,1860,1923,1943,1939,1939,1953,1980,2014,2034,2018,1960,1886,1825,1791,1782,1788,1785,1748,1681,
-1617,1579,1544,1480,1392,1309,1241,1170,1082,987,896,804,707,616,537,461,376,289,212,145,77,
-6,-64,-132,-200,-267,-326,-378,-434,-496,-555,-605,-655,-711,-766,-803,-819,-833,-861,-907,-959,-1015,
--1080,-1152,-1223,-1291,-1367,-1457,-1556,-1648,-1726,-1789,-1847,-1906,-1962,-2010,-2048,-2084,-2128,-2180,-2232,-2277,-2323,
--2379,-2446,-2504,-2532,-2526,-2501,-2475,-2456,-2439,-2419,-2402,-2393,-2388,-2377,-2358,-2341,-2339,-2358,-2402,-2464,-2525,
--2562,-2577,-2591,-2615,-2632,-2630,-2614,-2607,-2616,-2630,-2636,-2626,-2599,-2563,-2527,-2491,-2443,-2382,-2328,-2302,-2298,
--2295,-2293,-2318,-2380,-2455,-2504,-2502,-2452,-2380,-2320,-2292,-2281,-2252,-2190,-2114,-2049,-1996,-1948,-1902,-1859,-1811,
--1751,-1689,-1638,-1595,-1549,-1496,-1445,-1400,-1352,-1295,-1239,-1190,-1143,-1089,-1026,-963,-908,-860,-815,-770,-725,
--680,-629,-571,-510,-451,-395,-339,-285,-237,-190,-140,-86,-33,17,65,111,150,191,241,301,357,
-401,441,487,536,582,623,660,696,727,754,776,795,821,860,911,957,989,1010,1022,1022,1006,
-986,975,973,974,976,983,997,1017,1046,1086,1134,1177,1203,1216,1229,1255,1283,1294,1275,1241,1226,
-1252,1313,1393,1478,1561,1632,1688,1738,1790,1836,1864,1875,1882,1891,1898,1901,1904,1907,1908,1908,1913,
-1921,1925,1922,1915,1910,1907,1905,1904,1908,1916,1927,1938,1945,1948,1949,1953,1959,1965,1969,1968,1960,
-1951,1949,1953,1956,1953,1950,1950,1948,1934,1914,1897,1884,1870,1855,1839,1822,1804,1790,1784,1781,1775,
-1767,1764,1762,1754,1743,1737,1736,1732,1723,1717,1718,1719,1735,1736,1733,1727,1719,1708,1702,1707,1717,
-1720,1712,1701,1697,1701,1701,1690,1670,1653,1640,1626,1608,1593,1591,1598,1605,1599,1575,1530,1477,1436,
-1418,1415,1406,1374,1320,1257,1204,1168,1128,1051,936,831,787,798,812,789,742,707,693,686,668,
-641,611,578,527,447,336,213,104,20,-55,-141,-237,-320,-379,-430,-505,-629,-796,-969,-1103,-1173,
--1199,-1228,-1295,-1400,-1516,-1618,-1699,-1771,-1839,-1900,-1948,-1986,-2019,-2047,-2058,-2051,-2041,-2050,-2081,-2115,-2135,
--2138,-2134,-2133,-2127,-2102,-2053,-1989,-1926,-1874,-1832,-1800,-1779,-1759,-1721,-1656,-1578,-1508,-1438,-1334,-1176,-983,
--806,-698,-691,-780,-917,-1025,-1059,-1048,-1055,-1107,-1172,-1211,-1230,-1260,-1314,-1373,-1427,-1485,-1556,-1627,-1679,
--1708,-1726,-1738,-1738,-1710,-1645,-1552,-1461,-1404,-1382,-1360,-1316,-1281,-1322,-1471,-1686,-1887,-2020,-2094,-2152,-2232,
--2341,-2462,-2578,-2679,-2766,-2843,-2921,-3007,-3097,-3174,-3227,-3256,-3282,-3331,-3427,-3581,-3771,-3952,-4082,-4152,-4183,
--4204,-4231,-4269,-4314,-4355,-4388,-4423,-4480,-4559,-4640,-4704,-4751,-4794,-4839,-4879,-4910,-4931,-4939,-4923,-4887,-4854,
--4846,-4860,-4877,-4882,-4877,-4871,-4864,-4855,-4851,-4857,-4875,-4900,-4923,-4943,-4956,-4964,-4973,-4992,-5018,-5043,-5067,
--5095,-5126,-5157,-5191,-5238,-5302,-5367,-5417,-5458,-5506,-5559,-5608,-5650,-5699,-5759,-5819,-5875,-5935,-6006,-6084,-6153,
--6215,-6279,-6354,-6433,-6511,-6584,-6655,-6723,-6784,-6840,-6899,-6968,-7042,-7113,-7173,-7225,-7275,-7327,-7379,-7432,-7487,
--7543,-7601,-7661,-7719,-7767,-7806,-7846,-7897,-7960,-8033,-8117,-8211,-8306,-8393,-8476,-8562,-8646,-8719,-8786,-8863,-8949,
--9026,-9086,-9146,-9220,-9299,-9370,-9428,-9470,-9478,-9448,-9417,-9426,-9471,-9513,-9550,-9627,-9763,-9905,-9981,-9985,-9969,
--9974,-9999,-10026,-10057,-10092,-10120,-10133,-10143,-10162,-10185,-10202,-10213,-10225,-10236,-10241,-10235,-10221,-10199,-10171,-10142,-10113,
--10077,
--10026,-9962,-9884,-9784,-9664,-9551,-9480,-9451,-9431,-9387,-9316,-9228,-9133,-9032,-8930,-8832,-8735,-8631,-8519,-8397,-8270,
--8141,-8019,-7911,-7809,-7692,-7547,-7378,-7208,-7059,-6925,-6786,-6629,-6466,-6321,-6205,-6113,-6031,-5944,-5834,-5701,-5566,
--5444,-5328,-5190,-5022,-4845,-4684,-4535,-4374,-4188,-3996,-3833,-3705,-3579,-3422,-3247,-3103,-3013,-2946,-2871,-2807,-2790,
--2793,-2737,-2569,-2313,-2032,-1788,-1623,-1544,-1504,-1430,-1292,-1123,-944,-733,-481,-250,-103,-21,72,198,307,
-373,437,540,668,781,874,965,1062,1163,1267,1372,1470,1558,1649,1749,1845,1928,2009,2098,2193,2291,
-2396,2506,2606,2691,2784,2906,3046,3171,3266,3344,3418,3487,3557,3638,3735,3835,3930,4028,4142,4272,4397,
-4498,4575,4649,4742,4853,4962,5051,5116,5165,5203,5241,5292,5349,5396,5414,5403,5385,5393,5448,5515,5521,
-5425,5285,5216,5274,5412,5555,5670,5763,5834,5888,5944,6015,6091,6166,6250,6328,6340,6249,6100,5954,5794,
-5564,5278,5035,4894,4807,4685,4510,4337,4225,4195,4247,4387,4650,5079,5649,6208,6578,6725,6795,6931,7105,
-7193,7163,7123,7177,7313,7450,7540,7595,7634,7645,7603,7514,7430,7427,7529,7682,7792,7806,7740,7644,7551,
-7470,7411,7396,7437,7513,7573,7561,7462,7313,7166,7046,6948,6869,6813,6786,6776,6773,6779,6800,6845,6914,
-6997,7074,7131,7170,7200,7229,7258,7285,7302,7305,7299,7300,7309,7309,7288,7256,7224,7186,7137,7091,7064,
-7047,7025,7012,7028,7056,7052,7007,6963,6941,6919,6875,6828,6801,6777,6737,6697,6677,6642,6547,6415,6321,
-6295,6282,6227,6158,6142,6185,6221,6194,6118,6049,6018,6007,5986,5943,5895,5872,5888,5926,5952,5945,5923,
-5917,5936,5956,5950,5919,5883,5856,5826,5780,5718,5653,5594,5538,5480,5419,5361,5307,5253,5188,5111,5034,
-4973,4926,4883,4834,4778,4714,4642,4566,4501,4453,4415,4383,4356,4333,4305,4266,4225,4187,4151,4109,4063,
-4018,3975,3936,3909,3905,3914,3909,3875,3817,3750,3688,3635,3589,3544,3499,3456,3413,3360,3297,3241,3207,
-3190,3173,3147,3115,3072,3012,2940,2875,2822,2764,2690,2630,2633,2712,2809,2841,2776,2656,2552,2503,2491,
-2480,2455,2423,2394,2370,2354,2347,2349,2351,2342,2313,2266,2215,2179,2160,2145,2125,2105,2090,2076,2053,
-2030,2017,2013,2006,1993,1972,1932,1876,1836,1852,1907,1932,1884,1795,1735,1727,1739,1741,1736,1730,1721,
-1704,1689,1683,1674,1648,1612,1583,1573,1576,1584,1596,1604,1594,1567,1536,1516,1510,1506,1499,1494,1490,
-1484,1472,1462,1460,1469,1481,1487,1482,1469,1457,1452,1452,1448,1439,1436,1451,1480,1508,1525,1532,1532,
-1525,1517,1515,1520,1526,1533,1545,1559,1566,1561,1554,1560,1575,1580,1565,1550,1562,1600,1640,1654,1644,
-1631,1626,1624,1620,1617,1621,1629,1635,1634,1628,1618,1604,1588,1572,1552,1529,1508,1492,1477,1454,1430,
-1410,1396,1381,1366,1356,1349,1339,1328,1319,1308,1287,1256,1228,1209,1194,1179,1163,1150,1135,1116,1093,
-1069,1040,1007,975,948,923,896,865,831,797,764,736,709,678,644,611,581,547,505,463,425,
-389,352,314,278,245,212,181,151,120,88,54,20,-16,-55,-96,-135,-173,-211,-249,-287,-327,
--370,-415,-460,-501,-538,-571,-600,-626,-652,-680,-713,-750,-786,-815,-838,-862,-890,-918,-945,-975,-1010,
--1042,-1068,-1089,-1116,-1150,-1186,-1221,-1255,-1290,-1327,-1362,-1394,-1423,-1450,-1478,-1509,-1541,-1574,-1606,-1638,-1668,
--1699,-1733,-1769,-1802,-1826,-1847,-1870,-1896,-1923,-1951,-1978,-2006,-2032,-2054,-2072,-2089,-2107,-2128,-2148,-2165,-2181,
--2197,-2213,-2224,-2234,-2245,-2258,-2267,-2272,-2281,-2295,-2306,-2311,-2316,-2324,-2330,-2330,-2327,-2327,-2327,-2324,-2320,
--2317,-2313,-2303,-2288,-2273,-2261,-2249,-2235,-2219,-2201,-2182,-2165,-2153,-2143,-2134,-2124,-2114,-2100,-2081,-2062,-2049,
--2038,-2025,-2007,-1990,-1975,-1961,-1946,-1930,-1916,-1903,-1894,-1885,-1873,-1859,-1845,-1832,-1820,-1805,-1792,-1782,-1773,
--1763,-1751,-1740,-1727,-1711,-1695,-1681,-1669,-1655,-1640,-1626,-1612,-1595,-1579,-1565,-1550,-1532,-1513,-1497,-1483,-1465,
--1443,-1424,-1410,-1397,-1378,-1357,-1338,-1323,-1308,-1293,-1276,-1258,-1241,-1226,-1213,-1201,-1187,-1170,-1154,-1142,-1133,
--1122,-1105,-1086,-1067,-1044,-1015,-986,-960,-934,-912,-909,-925,-909,-812,-648,-504,-448,-456,-463,-444,-423,
--415,-403,-383,-367,-359,-343,-310,-277,-258,-240,-213,-183,-162,-139,-106,-68,-35,-1,40,84,129,
-180,244,311,381,467,569,663,738,817,914,983,968,896,864,934,1076,1228,1372,1520,1675,1837,
-2030,2269,2511,2666,2661,2494,2226,1949,1741,1636,1611,1632,1682,1758,1838,1887,1899,1898,1909,1929,1951,
-1977,2002,2002,1961,1893,1829,1785,1760,1743,1721,1681,1625,1574,1540,1511,1468,1413,1359,1299,1217,1112,
-1004,909,822,737,657,583,504,417,330,256,189,120,46,-24,-91,-159,-226,-287,-344,-405,-470,
--529,-579,-629,-687,-743,-782,-799,-811,-836,-877,-929,-986,-1050,-1121,-1193,-1266,-1345,-1437,-1539,-1635,-1712,
--1770,-1819,-1871,-1923,-1967,-1998,-2029,-2072,-2125,-2179,-2227,-2276,-2335,-2405,-2468,-2501,-2496,-2464,-2425,-2398,-2385,
--2379,-2377,-2373,-2364,-2348,-2329,-2315,-2314,-2338,-2392,-2467,-2531,-2557,-2552,-2550,-2569,-2592,-2600,-2593,-2586,-2585,
--2588,-2592,-2591,-2573,-2532,-2480,-2431,-2384,-2334,-2293,-2278,-2284,-2286,-2277,-2273,-2297,-2347,-2401,-2430,-2409,-2339,
--2261,-2219,-2218,-2218,-2187,-2125,-2057,-1994,-1936,-1884,-1839,-1788,-1729,-1675,-1639,-1610,-1568,-1510,-1454,-1409,-1362,
--1301,-1233,-1171,-1118,-1064,-1001,-935,-873,-821,-774,-730,-685,-640,-591,-541,-492,-446,-401,-353,-303,-254,
--206,-155,-103,-53,-4,43,91,136,184,239,300,355,397,435,478,523,567,606,643,677,705,
-727,745,760,783,821,871,918,950,970,984,990,982,969,963,967,973,973,969,968,975,993,
-1023,1061,1096,1119,1131,1149,1182,1224,1253,1258,1251,1258,1289,1339,1398,1469,1551,1630,1699,1759,1818,
-1867,1896,1903,1901,1897,1894,1890,1888,1887,1885,1883,1885,1892,1903,1913,1923,1932,1940,1947,1952,1955,
-1956,1957,1961,1966,1969,1969,1968,1968,1967,1967,1966,1963,1961,1963,1967,1964,1955,1946,1939,1929,1911,
-1888,1869,1857,1847,1837,1826,1815,1802,1791,1786,1784,1780,1774,1771,1769,1762,1750,1740,1736,1733,1729,
-1727,1731,1735,1760,1763,1759,1746,1731,1724,1727,1737,1744,1738,1722,1706,1700,1704,1706,1694,1672,1654,
-1643,1630,1614,1603,1603,1602,1583,1546,1506,1476,1456,1439,1426,1423,1428,1423,1381,1298,1205,1139,1098,
-1038,936,828,771,778,805,811,793,768,742,710,674,642,613,579,528,454,356,248,151,66,
--24,-138,-260,-356,-409,-442,-499,-612,-778,-960,-1112,-1210,-1263,-1297,-1341,-1409,-1501,-1607,-1710,-1798,-1871,
--1932,-1980,-2017,-2047,-2074,-2090,-2090,-2083,-2087,-2107,-2130,-2136,-2127,-2119,-2123,-2130,-2118,-2075,-2010,-1944,-1892,
--1854,-1826,-1804,-1781,-1744,-1681,-1599,-1515,-1434,-1333,-1191,-1016,-855,-756,-742,-799,-881,-941,-966,-988,-1041,
--1121,-1194,-1240,-1275,-1325,-1391,-1456,-1515,-1569,-1616,-1654,-1687,-1718,-1730,-1703,-1647,-1591,-1548,-1505,-1457,-1419,
--1403,-1392,-1376,-1387,-1466,-1614,-1780,-1915,-2012,-2091,-2171,-2261,-2368,-2488,-2606,-2708,-2789,-2862,-2942,-3031,-3120,
--3190,-3231,-3256,-3299,-3389,-3533,-3712,-3890,-4032,-4121,-4161,-4176,-4189,-4210,-4245,-4290,-4333,-4369,-4411,-4478,-4569,
--4656,-4713,-4747,-4782,-4828,-4874,-4905,-4918,-4914,-4893,-4863,-4842,-4842,-4856,-4865,-4863,-4855,-4847,-4839,-4831,-4829,
--4838,-4858,-4881,-4904,-4925,-4937,-4943,-4949,-4964,-4986,-5008,-5032,-5065,-5105,-5144,-5184,-5234,-5295,-5350,-5390,-5427,
--5475,-5529,-5575,-5614,-5660,-5721,-5785,-5843,-5901,-5971,-6052,-6129,-6193,-6252,-6317,-6392,-6471,-6547,-6619,-6688,-6755,
--6821,-6886,-6952,-7020,-7084,-7141,-7196,-7253,-7311,-7366,-7415,-7463,-7513,-7568,-7629,-7690,-7740,-7776,-7811,-7861,-7926,
--8000,-8077,-8161,-8251,-8340,-8428,-8515,-8598,-8673,-8744,-8826,-8915,-8993,-9052,-9109,-9181,-9262,-9338,-9398,-9432,-9426,
--9390,-9366,-9386,-9433,-9468,-9504,-9590,-9738,-9884,-9954,-9949,-9929,-9935,-9960,-9987,-10015,-10048,-10076,-10092,-10104,-10123,
--10146,-10164,-10178,-10192,-10207,-10212,-10204,-10184,-10154,-10120,-10091,-10069,-10041,-9994,-9929,-9850,-9760,-9663,-9576,-9515,-9473,
--9427,
--9361-9283,-9202,-9118,-9026,-8929,-8833,-8737,-8633,-8520,-8400,-8276,-8149,-8030,-7925,-7825,-7708,-7558,-7387,-7219,
--7067,-6920,-6762,-6593,-6433,-6299,-6194,-6110,-6036,-5958,-5856,-5726,-5589,-5464,-5343,-5198,-5021,-4838,-4677,-4537,-4390,
--4216,-4029,-3861,-3724,-3594,-3443,-3277,-3134,-3030,-2936,-2828,-2738,-2715,-2751,-2761,-2661,-2438,-2145,-1869,-1688,-1623,
--1615,-1567,-1443,-1273,-1080,-834,-531,-247,-68,17,95,209,323,407,483,586,706,814,904,988,1073,
-1165,1270,1382,1484,1571,1661,1766,1871,1959,2034,2112,2195,2285,2388,2502,2607,2689,2772,2886,3027,3157,
-3254,3333,3406,3473,3536,3613,3717,3831,3937,4040,4165,4314,4453,4543,4590,4636,4714,4814,4908,4978,5027,
-5063,5098,5149,5227,5314,5375,5393,5379,5369,5391,5454,5522,5524,5424,5284,5224,5304,5473,5646,5789,5910,
-6000,6040,6039,6042,6083,6166,6269,6346,6345,6260,6148,6054,5937,5715,5393,5074,4841,4674,4509,4337,4202,
-4148,4175,4258,4377,4550,4837,5269,5767,6188,6462,6656,6858,7049,7139,7119,7092,7144,7255,7346,7394,7432,
-7486,7525,7514,7465,7442,7509,7663,7837,7951,7975,7934,7873,7802,7709,7591,7486,7450,7497,7575,7602,7551,
-7459,7369,7281,7178,7073,6998,6955,6914,6859,6812,6799,6824,6873,6937,7012,7089,7155,7200,7229,7251,7274,
-7295,7308,7318,7331,7342,7331,7300,7264,7237,7206,7168,7142,7146,7157,7150,7141,7165,7208,7219,7186,7152,
-7148,7145,7110,7062,7036,7020,6980,6920,6871,6831,6761,6651,6536,6442,6352,6249,6164,6141,6169,6190,6163,
-6106,6064,6060,6075,6066,6010,5923,5856,5846,5888,5932,5941,5921,5911,5931,5958,5961,5932,5895,5867,5843,
-5807,5755,5694,5634,5578,5520,5458,5394,5335,5281,5221,5148,5070,5004,4954,4909,4854,4790,4720,4651,4583,
-4522,4471,4431,4399,4376,4352,4316,4269,4222,4183,4150,4117,4081,4044,4000,3953,3920,3916,3929,3926,3890,
-3831,3769,3715,3665,3614,3564,3524,3494,3464,3417,3352,3290,3252,3230,3207,3176,3145,3110,3063,3001,2937,
-2877,2808,2722,2651,2646,2734,2872,2966,2940,2804,2639,2532,2505,2518,2522,2495,2447,2396,2360,2349,2358,
-2372,2368,2337,2284,2228,2188,2163,2142,2115,2091,2078,2068,2049,2028,2015,2013,2011,2003,1984,1943,1884,
-1844,1864,1924,1947,1883,1773,1696,1682,1698,1707,1711,1718,1723,1716,1703,1695,1688,1669,1639,1612,1595,
-1585,1584,1594,1608,1611,1594,1568,1544,1527,1515,1504,1492,1476,1456,1441,1440,1458,1487,1515,1532,1531,
-1513,1490,1474,1464,1453,1439,1434,1445,1468,1493,1512,1520,1516,1504,1495,1496,1500,1500,1502,1514,1532,
-1543,1545,1545,1551,1554,1545,1528,1518,1531,1566,1604,1626,1622,1605,1591,1589,1592,1595,1596,1596,1597,
-1602,1606,1604,1593,1578,1565,1553,1535,1513,1494,1477,1458,1433,1408,1388,1373,1360,1349,1336,1321,1307,
-1298,1288,1268,1239,1214,1198,1185,1170,1156,1146,1136,1120,1101,1081,1059,1030,999,970,943,914,883,
-849,815,780,749,719,686,650,614,581,547,509,470,433,396,357,315,276,241,208,176,148,
-121,93,64,34,0,-39,-79,-118,-154,-191,-229,-267,-306,-347,-391,-434,-474,-512,-548,-580,-608,
--633,-659,-689,-724,-760,-792,-819,-845,-872,-899,-927,-957,-992,-1026,-1052,-1073,-1098,-1129,-1164,-1199,-1234,
--1270,-1308,-1344,-1374,-1398,-1421,-1448,-1480,-1512,-1545,-1577,-1610,-1641,-1672,-1705,-1739,-1769,-1792,-1813,-1837,-1863,
--1889,-1913,-1939,-1967,-1994,-2018,-2038,-2055,-2073,-2091,-2109,-2126,-2143,-2160,-2177,-2190,-2202,-2215,-2228,-2237,-2243,
--2250,-2261,-2269,-2273,-2278,-2285,-2290,-2290,-2288,-2289,-2291,-2290,-2287,-2284,-2278,-2268,-2256,-2244,-2233,-2220,-2206,
--2192,-2174,-2154,-2135,-2124,-2116,-2107,-2095,-2083,-2069,-2052,-2035,-2023,-2013,-2002,-1987,-1972,-1957,-1943,-1927,-1911,
--1896,-1884,-1873,-1861,-1848,-1834,-1821,-1811,-1800,-1786,-1773,-1763,-1753,-1743,-1731,-1720,-1708,-1694,-1681,-1670,-1659,
--1646,-1630,-1617,-1604,-1590,-1573,-1558,-1543,-1526,-1508,-1492,-1478,-1462,-1444,-1427,-1413,-1398,-1380,-1362,-1346,-1332,
--1317,-1301,-1284,-1268,-1252,-1238,-1224,-1212,-1200,-1186,-1173,-1162,-1151,-1137,-1118,-1099,-1081,-1060,-1033,-1008,-986,
--961,-935,-930,-947,-941,-854,-694,-540,-460,-439,-424,-394,-371,-366,-363,-356,-355,-356,-343,-313,-286,
--269,-252,-227,-200,-180,-156,-123,-87,-54,-13,38,91,139,194,263,333,401,483,582,672,742,
-814,898,943,902,823,821,950,1148,1323,1447,1547,1654,1801,2028,2332,2618,2756,2684,2450,2151,1869,
-1661,1555,1545,1595,1668,1742,1803,1838,1851,1863,1888,1916,1940,1963,1984,1988,1959,1905,1847,1796,1751,
-1711,1675,1640,1601,1562,1526,1492,1455,1418,1380,1331,1253,1153,1049,955,869,785,705,628,547,461,
-380,309,239,165,89,19,-45,-113,-182,-248,-311,-376,-442,-501,-555,-609,-670,-725,-760,-775,-789,
--817,-861,-914,-968,-1028,-1099,-1179,-1260,-1340,-1427,-1523,-1616,-1692,-1749,-1800,-1857,-1916,-1964,-1999,-2028,-2061,
--2102,-2146,-2193,-2245,-2305,-2373,-2434,-2471,-2471,-2438,-2397,-2367,-2355,-2353,-2356,-2357,-2352,-2339,-2321,-2303,-2296,
--2313,-2366,-2445,-2512,-2535,-2524,-2514,-2529,-2553,-2567,-2569,-2566,-2558,-2544,-2539,-2547,-2549,-2522,-2468,-2411,-2360,
--2314,-2274,-2253,-2252,-2258,-2256,-2249,-2248,-2263,-2299,-2341,-2353,-2312,-2238,-2184,-2170,-2172,-2150,-2095,-2025,-1957,
--1895,-1846,-1807,-1766,-1716,-1669,-1635,-1607,-1564,-1504,-1445,-1398,-1352,-1295,-1227,-1160,-1098,-1039,-978,-915,-855,
--800,-751,-704,-659,-613,-569,-526,-484,-445,-407,-366,-320,-270,-220,-170,-120,-71,-22,28,79,127,
-175,230,291,351,399,437,471,505,539,573,609,642,668,685,697,706,720,745,782,820,848,
-868,884,895,898,899,909,929,947,950,937,921,911,911,921,940,961,983,1008,1043,1094,1154,
-1208,1253,1297,1348,1402,1447,1483,1523,1573,1628,1682,1737,1796,1848,1878,1882,1870,1858,1851,1851,1856,
-1863,1870,1874,1879,1889,1905,1925,1943,1955,1961,1968,1978,1987,1990,1989,1988,1989,1989,1988,1985,1982,
-1976,1969,1964,1961,1961,1963,1962,1956,1944,1932,1921,1909,1890,1869,1853,1841,1830,1820,1811,1802,1794,
-1786,1783,1781,1776,1771,1768,1769,1765,1756,1746,1742,1742,1744,1748,1754,1760,1784,1785,1779,1762,1744,
-1739,1748,1758,1759,1748,1734,1722,1715,1713,1708,1692,1671,1654,1644,1634,1623,1620,1623,1610,1567,1507,
-1462,1444,1439,1428,1414,1415,1432,1441,1406,1318,1211,1131,1084,1027,930,821,757,764,814,864,886,
-872,824,759,701,658,623,581,529,464,382,287,196,110,8,-125,-267,-373,-425,-453,-506,-615,
--768,-935,-1086,-1210,-1306,-1370,-1408,-1441,-1499,-1593,-1703,-1800,-1876,-1938,-1992,-2032,-2062,-2088,-2111,-2124,-2123,
--2121,-2128,-2137,-2135,-2123,-2115,-2120,-2130,-2124,-2091,-2036,-1978,-1931,-1898,-1870,-1843,-1816,-1780,-1718,-1625,-1518,
--1415,-1312,-1188,-1039,-892,-785,-734,-727,-742,-771,-825,-919,-1044,-1161,-1237,-1279,-1319,-1377,-1446,-1512,-1574,
--1626,-1656,-1671,-1695,-1732,-1742,-1692,-1608,-1549,-1528,-1511,-1479,-1459,-1472,-1493,-1497,-1508,-1568,-1674,-1783,-1876,
--1971,-2083,-2198,-2302,-2407,-2526,-2644,-2737,-2808,-2877,-2962,-3054,-3136,-3197,-3237,-3279,-3353,-3480,-3648,-3823,-3968,
--4067,-4122,-4148,-4162,-4175,-4197,-4234,-4283,-4332,-4374,-4420,-4492,-4591,-4684,-4736,-4753,-4767,-4801,-4847,-4881,-4892,
--4883,-4863,-4842,-4833,-4839,-4850,-4850,-4840,-4827,-4815,-4805,-4798,-4801,-4819,-4844,-4867,-4885,-4900,-4909,-4912,-4917,
--4930,-4950,-4971,-4995,-5026,-5065,-5106,-5150,-5207,-5270,-5325,-5363,-5397,-5441,-5492,-5538,-5579,-5628,-5691,-5756,-5815,
--5873,-5940,-6018,-6100,-6173,-6235,-6293,-6357,-6428,-6500,-6569,-6640,-6716,-6792,-6862,-6929,-6994,-7058,-7118,-7175,-7233,
--7288,-7339,-7384,-7430,-7480,-7535,-7597,-7659,-7709,-7743,-7776,-7824,-7889,-7958,-8028,-8106,-8196,-8289,-8377,-8463,-8545,
--8623,-8700,-8784,-8872,-8950,-9013,-9075,-9148,-9228,-9304,-9364,-9395,-9383,-9346,-9327,-9352,-9395,-9423,-9458,-9554,-9716,
--9867,-9929,-9912,-9886,-9893,-9921,-9948,-9974,-10006,-10036,-10055,-10068,-10085,-10106,-10124,-10141,-10161,-10182,-10192,-10185,-10161,
--10125,
--10085-10056,-10036,-10009,-9959,-9885,-9803,-9721,-9645,-9577,-9518,-9459,-9392,-9318,-9246,-9179,-9104,-9015,-8917,-8819,
--8722,-8618,-8504,-8385,-8263,-8143,-8031,-7934,-7837,-7718,-7565,-7394,-7227,-7071,-6914,-6745,-6577,-6430,-6314,-6221,-6140,
--6064,-5983,-5880,-5750,-5612,-5482,-5353,-5200,-5019,-4834,-4672,-4532,-4390,-4229,-4056,-3893,-3749,-3612,-3465,-3314,-3179,
--3064,-2943,-2804,-2689,-2656,-2704,-2755,-2714,-2538,-2257,-1954,-1732,-1649,-1664,-1667,-1582,-1413,-1186,-900,-563,-248,
--38,63,132,223,331,433,534,643,750,842,926,1011,1095,1181,1282,1397,1502,1589,1677,1782,1892,
-1983,2056,2127,2203,2284,2380,2494,2603,2689,2768,2874,3005,3126,3219,3297,3375,3446,3510,3586,3693,3812,
-3916,4010,4125,4269,4405,4488,4528,4572,4649,4744,4824,4881,4926,4970,5019,5092,5198,5308,5374,5377,5351,
-5344,5378,5441,5492,5478,5380,5263,5233,5340,5531,5724,5898,6062,6186,6217,6157,6093,6114,6232,6381,6465,
-6437,6329,6220,6147,6056,5865,5573,5264,5005,4796,4610,4459,4375,4364,4406,4473,4546,4629,4774,5048,5452,
-5891,6264,6548,6779,6957,7049,7066,7080,7137,7207,7238,7236,7253,7309,7370,7394,7394,7423,7514,7651,7780,
-7868,7914,7949,7983,7992,7932,7789,7614,7497,7479,7519,7537,7509,7475,7460,7440,7380,7300,7242,7205,7152,
-7071,6995,6957,6944,6934,6932,6968,7050,7144,7210,7239,7247,7258,7279,7303,7325,7339,7338,7320,7297,7286,
-7287,7282,7271,7285,7333,7376,7371,7338,7327,7344,7347,7318,7296,7306,7315,7284,7231,7202,7197,7173,7114,
-7048,6997,6951,6889,6809,6711,6585,6440,6315,6242,6211,6182,6135,6082,6049,6048,6069,6082,6056,5982,5896,
-5847,5854,5895,5928,5939,5942,5956,5974,5976,5955,5922,5892,5866,5835,5793,5738,5676,5612,5553,5493,5430,
-5366,5307,5249,5182,5103,5028,4968,4915,4857,4791,4727,4671,4617,4559,4500,4452,4425,4410,4389,4346,4289,
-4236,4198,4168,4138,4108,4074,4031,3982,3945,3933,3935,3924,3886,3837,3793,3755,3710,3653,3593,3548,3520,
-3496,3457,3397,3337,3292,3262,3234,3202,3173,3144,3109,3059,2998,2929,2853,2775,2710,2685,2728,2836,2952,
-2990,2907,2750,2619,2579,2607,2636,2614,2542,2453,2384,2351,2351,2363,2363,2340,2297,2247,2205,2174,2148,
-2120,2098,2086,2075,2056,2032,2020,2020,2021,2012,1988,1945,1892,1859,1880,1935,1951,1884,1771,1693,1679,
-1695,1700,1697,1704,1719,1726,1722,1713,1701,1681,1656,1633,1612,1593,1578,1575,1583,1591,1591,1585,1574,
-1557,1536,1512,1485,1455,1428,1417,1431,1467,1511,1550,1574,1574,1551,1518,1489,1468,1452,1444,1448,1464,
-1481,1493,1501,1504,1500,1489,1482,1482,1481,1477,1479,1492,1511,1522,1526,1532,1539,1539,1531,1522,1521,
-1529,1547,1571,1592,1595,1582,1567,1565,1572,1576,1573,1568,1568,1575,1583,1581,1569,1554,1547,1544,1534,
-1514,1492,1474,1456,1434,1410,1391,1377,1364,1348,1327,1305,1287,1276,1266,1250,1227,1206,1190,1174,1157,
-1143,1135,1126,1112,1096,1081,1065,1043,1015,985,955,923,892,861,829,794,760,727,694,656,618,
-582,548,511,474,439,403,363,321,281,244,210,178,150,125,101,74,44,11,-26,-65,-101,
--135,-170,-207,-245,-284,-327,-369,-409,-446,-483,-521,-557,-588,-615,-641,-670,-703,-739,-773,-803,-832,
--860,-888,-916,-947,-979,-1011,-1038,-1061,-1086,-1117,-1152,-1186,-1220,-1255,-1291,-1324,-1349,-1369,-1390,-1418,-1452,
--1486,-1520,-1553,-1586,-1618,-1648,-1678,-1708,-1734,-1757,-1780,-1805,-1829,-1851,-1873,-1898,-1925,-1953,-1978,-2001,-2020,
--2037,-2052,-2067,-2083,-2100,-2117,-2135,-2150,-2164,-2178,-2192,-2202,-2208,-2215,-2224,-2232,-2237,-2242,-2246,-2248,-2247,
--2247,-2250,-2253,-2253,-2250,-2246,-2238,-2229,-2220,-2212,-2202,-2188,-2174,-2161,-2145,-2125,-2107,-2096,-2089,-2078,-2064,
--2051,-2038,-2024,-2009,-1996,-1985,-1974,-1961,-1948,-1935,-1921,-1906,-1892,-1879,-1866,-1853,-1838,-1823,-1810,-1799,-1790,
--1780,-1769,-1757,-1746,-1736,-1723,-1710,-1698,-1687,-1676,-1665,-1655,-1645,-1633,-1619,-1607,-1596,-1583,-1567,-1550,-1534,
--1518,-1503,-1487,-1472,-1457,-1443,-1430,-1416,-1399,-1382,-1366,-1353,-1339,-1324,-1308,-1292,-1278,-1266,-1253,-1239,-1224,
--1210,-1198,-1187,-1176,-1165,-1149,-1130,-1112,-1095,-1076,-1052,-1030,-1010,-985,-954,-940,-953,-959,-908,-794,-669,
--580,-517,-452,-391,-359,-357,-362,-361,-360,-361,-352,-330,-311,-298,-280,-253,-227,-204,-177,-143,-109,
--75,-28,30,87,140,203,280,353,417,492,585,674,740,801,865,889,838,774,815,1003,1251,
-1444,1544,1586,1632,1755,2013,2374,2684,2777,2616,2314,2007,1758,1584,1498,1505,1573,1651,1712,1758,1799,
-1835,1867,1895,1921,1945,1965,1977,1971,1945,1905,1859,1803,1739,1679,1636,1607,1581,1547,1510,1474,1441,
-1415,1390,1352,1289,1205,1114,1024,933,840,752,669,587,505,428,358,287,212,138,71,5,-65,
--138,-206,-271,-338,-406,-469,-528,-590,-654,-706,-737,-753,-770,-804,-854,-907,-958,-1015,-1090,-1180,-1271,
--1352,-1429,-1512,-1595,-1666,-1726,-1786,-1855,-1925,-1982,-2020,-2044,-2061,-2081,-2115,-2166,-2229,-2294,-2358,-2413,-2445,
--2441,-2408,-2368,-2341,-2330,-2328,-2333,-2345,-2357,-2357,-2342,-2317,-2298,-2301,-2342,-2410,-2471,-2495,-2488,-2480,-2488,
--2503,-2512,-2521,-2531,-2532,-2517,-2505,-2518,-2538,-2533,-2491,-2433,-2380,-2335,-2290,-2251,-2226,-2217,-2221,-2225,-2219,
--2206,-2210,-2243,-2283,-2292,-2257,-2209,-2175,-2149,-2108,-2047,-1979,-1914,-1859,-1818,-1786,-1752,-1705,-1650,-1600,-1559,
--1514,-1461,-1407,-1358,-1313,-1266,-1213,-1152,-1085,-1018,-959,-908,-860,-810,-760,-712,-666,-621,-580,-541,-502,
--462,-424,-385,-341,-293,-245,-199,-153,-105,-56,-7,39,83,125,174,235,300,358,399,425,443,
-463,490,522,552,574,585,590,591,593,601,620,646,673,698,720,737,748,761,785,819,849,
-859,852,838,830,832,840,854,875,904,943,992,1049,1110,1171,1235,1307,1383,1450,1496,1527,1554,
-1587,1621,1656,1698,1748,1796,1823,1823,1806,1789,1782,1787,1802,1824,1850,1877,1901,1924,1947,1969,1982,
-1981,1972,1968,1976,1990,2000,2004,2004,2002,1999,1996,1995,1994,1989,1979,1968,1961,1956,1951,1944,1934,
-1923,1913,1903,1891,1876,1862,1849,1837,1825,1812,1800,1790,1782,1776,1773,1771,1766,1761,1759,1761,1763,
-1761,1758,1757,1762,1770,1777,1781,1784,1802,1798,1790,1775,1759,1756,1763,1767,1760,1750,1744,1739,1729,
-1716,1701,1684,1668,1656,1645,1630,1619,1620,1624,1603,1542,1467,1416,1399,1395,1387,1381,1390,1407,1408,
-1368,1287,1195,1120,1063,993,894,790,727,733,795,878,937,940,886,807,741,695,648,592,533,
-474,402,315,228,145,45,-91,-241,-355,-413,-449,-514,-625,-764,-904,-1036,-1169,-1297,-1396,-1447,-1469,
--1507,-1585,-1687,-1780,-1852,-1916,-1977,-2026,-2060,-2089,-2117,-2136,-2137,-2130,-2129,-2134,-2134,-2127,-2118,-2117,-2120,
--2117,-2099,-2065,-2022,-1982,-1950,-1920,-1886,-1852,-1814,-1756,-1660,-1537,-1415,-1308,-1195,-1057,-906,-774,-682,-629,
--609,-635,-727,-880,-1051,-1185,-1261,-1305,-1355,-1422,-1489,-1549,-1607,-1656,-1680,-1689,-1715,-1758,-1771,-1724,-1653,
--1616,-1605,-1573,-1523,-1518,-1580,-1645,-1645,-1604,-1596,-1646,-1726,-1821,-1945,-2095,-2233,-2340,-2442,-2561,-2676,-2759,
--2821,-2894,-2986,-3074,-3140,-3190,-3247,-3328,-3445,-3596,-3761,-3905,-4008,-4071,-4107,-4130,-4149,-4170,-4199,-4242,-4294,
--4347,-4391,-4438,-4512,-4615,-4712,-4761,-4761,-4751,-4766,-4804,-4840,-4854,-4846,-4829,-4815,-4813,-4819,-4824,-4819,-4804,
--4787,-4771,-4758,-4754,-4767,-4795,-4827,-4849,-4861,-4867,-4869,-4869,-4875,-4889,-4910,-4931,-4953,-4980,-5013,-5052,-5100,
--5162,-5232,-5293,-5337,-5372,-5411,-5457,-5504,-5552,-5604,-5663,-5725,-5786,-5845,-5907,-5977,-6059,-6143,-6217,-6277,-6334,
--6395,-6461,-6528,-6600,-6677,-6755,-6827,-6895,-6964,-7033,-7097,-7152,-7203,-7251,-7294,-7338,-7386,-7440,-7499,-7561,-7622,
--7671,-7706,-7740,-7787,-7849,-7912,-7977,-8053,-8142,-8235,-8321,-8405,-8490,-8572,-8653,-8735,-8820,-8900,-8973,-9045,-9119,
--9193,-9260,-9315,-9346,-9340,-9312,-9301,-9326,-9358,-9373,-9405,-9513,-9689,-9843,-9896,-9868,-9836,-9845,-9878,-9906,-9930,
--9962,-9996,-10021,-10038,-10055,-10074,-10094,-10115,-10141,-10168,-10184,-10180,-10154,-10115,-10073,-10040,-10016,-9981,-9920,-9834,-9743,
--9662,
--9594,-9534,-9473,-9408,-9340,-9276,-9222,-9167,-9092,-8995,-8888,-8786,-8688,-8583,-8468,-8348,-8230,-8120,-8021,-7931,-7832,
--7706,-7551,-7386,-7228,-7073,-6909,-6736,-6576,-6448,-6352,-6269,-6188,-6103,-6011,-5900,-5769,-5630,-5496,-5358,-5199,-5018,
--4836,-4675,-4532,-4390,-4237,-4077,-3920,-3772,-3626,-3480,-3341,-3218,-3100,-2961,-2800,-2664,-2611,-2646,-2705,-2703,-2588,
--2352,-2044,-1773,-1641,-1653,-1705,-1678,-1530,-1288,-982,-636,-302,-47,106,196,271,356,457,570,682,776,
-852,932,1024,1117,1203,1299,1408,1514,1604,1692,1795,1900,1990,2065,2140,2216,2291,2376,2480,2588,2681,
-2765,2867,2987,3097,3183,3259,3339,3417,3487,3567,3673,3789,3885,3964,4059,4181,4299,4376,4422,4479,4568,
-4661,4728,4775,4825,4887,4962,5058,5182,5302,5364,5355,5320,5315,5352,5402,5426,5394,5312,5235,5246,5372,
-5558,5739,5914,6104,6273,6335,6276,6195,6217,6362,6527,6592,6521,6379,6261,6195,6126,5989,5785,5569,5372,
-5189,5027,4918,4881,4891,4915,4943,4966,4973,4993,5112,5393,5790,6178,6472,6672,6807,6896,6954,7012,7079,
-7125,7124,7098,7100,7146,7208,7258,7303,7365,7445,7521,7576,7619,7676,7767,7874,7950,7940,7827,7662,7527,
-7469,7460,7447,7424,7428,7473,7515,7511,7474,7442,7418,7374,7306,7247,7213,7171,7091,7004,6972,7023,7117,
-7195,7229,7235,7244,7268,7299,7323,7330,7323,7314,7320,7345,7375,7390,7406,7459,7547,7614,7606,7541,7480,
-7449,7422,7386,7366,7377,7384,7353,7301,7274,7278,7271,7225,7156,7097,7065,7056,7046,7004,6903,6757,6607,
-6484,6387,6300,6216,6140,6074,6027,6015,6044,6088,6100,6055,5977,5917,5905,5933,5971,6000,6013,6017,6012,
-5996,5971,5937,5901,5868,5834,5787,5722,5649,5583,5528,5473,5408,5340,5276,5209,5130,5046,4973,4911,4853,
-4795,4749,4715,4678,4619,4548,4491,4465,4457,4437,4390,4328,4272,4231,4197,4162,4127,4092,4052,4008,3971,
-3949,3936,3913,3879,3843,3815,3787,3748,3694,3634,3582,3544,3513,3474,3422,3365,3317,3280,3251,3225,3198,
-3171,3142,3105,3050,2973,2888,2816,2759,2710,2684,2718,2817,2915,2923,2831,2720,2673,2695,2721,2693,2609,
-2502,2413,2360,2341,2339,2336,2323,2296,2259,2220,2188,2162,2140,2122,2110,2096,2072,2046,2031,2032,2031,
-2017,1987,1947,1903,1875,1887,1926,1938,1888,1807,1759,1766,1785,1775,1741,1716,1716,1726,1733,1730,1718,
-1698,1674,1654,1634,1612,1589,1572,1564,1565,1571,1579,1584,1578,1559,1533,1504,1471,1442,1433,1449,1483,
-1522,1556,1579,1583,1563,1531,1499,1475,1458,1453,1461,1477,1487,1488,1489,1492,1493,1488,1481,1476,1467,
-1458,1458,1473,1492,1505,1513,1524,1534,1537,1536,1540,1546,1546,1543,1550,1566,1576,1572,1564,1561,1563,
-1562,1556,1553,1555,1561,1563,1557,1545,1533,1531,1534,1529,1512,1489,1468,1450,1431,1412,1399,1387,1372,
-1350,1324,1299,1277,1262,1251,1239,1222,1204,1187,1169,1149,1132,1121,1110,1094,1078,1064,1051,1032,1007,
-979,949,916,886,858,830,797,763,730,697,660,622,586,552,517,482,450,418,382,340,300,
-262,227,193,164,138,112,82,51,16,-19,-54,-88,-120,-154,-191,-229,-270,-313,-354,-390,-422,
--455,-495,-535,-571,-602,-630,-659,-689,-720,-752,-784,-815,-846,-877,-907,-936,-965,-993,-1020,-1046,-1075,
--1108,-1144,-1178,-1210,-1242,-1273,-1299,-1319,-1336,-1358,-1389,-1426,-1463,-1499,-1533,-1566,-1597,-1626,-1654,-1679,-1702,
--1725,-1750,-1774,-1796,-1816,-1837,-1861,-1887,-1912,-1938,-1963,-1985,-2001,-2014,-2027,-2042,-2058,-2075,-2093,-2110,-2125,
--2139,-2152,-2162,-2169,-2178,-2187,-2197,-2205,-2211,-2213,-2212,-2210,-2211,-2215,-2217,-2216,-2212,-2207,-2198,-2188,-2180,
--2174,-2166,-2153,-2140,-2127,-2113,-2095,-2079,-2069,-2061,-2048,-2033,-2020,-2009,-1998,-1984,-1970,-1957,-1944,-1931,-1919,
--1906,-1893,-1880,-1869,-1859,-1848,-1834,-1819,-1804,-1791,-1779,-1770,-1760,-1750,-1739,-1729,-1718,-1706,-1692,-1680,-1670,
--1661,-1651,-1641,-1629,-1617,-1606,-1596,-1587,-1576,-1561,-1543,-1527,-1513,-1501,-1487,-1471,-1454,-1441,-1429,-1416,-1400,
--1385,-1373,-1361,-1347,-1333,-1318,-1303,-1291,-1281,-1271,-1257,-1240,-1226,-1214,-1202,-1190,-1176,-1162,-1145,-1128,-1112,
--1094,-1072,-1050,-1030,-1005,-972,-949,-950,-961,-947,-895,-826,-754,-668,-567,-480,-441,-443,-447,-435,-419,
--408,-397,-381,-365,-351,-327,-295,-262,-233,-200,-163,-128,-92,-43,16,73,128,198,281,354,413,
-481,571,659,723,773,819,830,787,757,848,1087,1377,1595,1692,1701,1694,1772,2012,2376,2678,2725,
-2496,2148,1848,1652,1535,1481,1495,1557,1621,1668,1716,1781,1850,1896,1914,1927,1948,1969,1971,1950,1921,
-1892,1857,1800,1725,1657,1613,1585,1558,1523,1487,1457,1437,1424,1411,1384,1335,1264,1182,1093,995,894,
-798,710,626,544,468,399,334,267,200,133,61,-17,-92,-160,-227,-298,-370,-438,-502,-567,-632,
--686,-718,-736,-756,-794,-846,-900,-951,-1010,-1090,-1188,-1285,-1367,-1439,-1510,-1580,-1642,-1700,-1768,-1847,-1924,
--1981,-2012,-2022,-2022,-2034,-2075,-2145,-2227,-2301,-2360,-2403,-2420,-2403,-2361,-2322,-2303,-2298,-2298,-2308,-2335,-2369,
--2385,-2372,-2341,-2313,-2307,-2332,-2381,-2430,-2453,-2452,-2448,-2448,-2445,-2438,-2447,-2476,-2501,-2500,-2489,-2500,-2531,
--2544,-2516,-2464,-2418,-2384,-2347,-2298,-2243,-2203,-2187,-2189,-2185,-2160,-2133,-2140,-2187,-2239,-2258,-2237,-2194,-2139,
--2072,-2001,-1936,-1884,-1842,-1807,-1777,-1740,-1685,-1614,-1541,-1479,-1429,-1387,-1343,-1296,-1250,-1213,-1181,-1138,-1077,
--1011,-959,-924,-892,-852,-807,-761,-715,-671,-631,-592,-554,-515,-478,-441,-401,-360,-319,-279,-235,-186,
--138,-96,-59,-26,8,49,103,168,227,269,291,301,314,337,367,397,417,426,428,429,429,
-432,444,467,500,537,569,591,607,624,651,688,722,743,753,762,777,796,818,842,871,909,
-954,1003,1053,1100,1151,1210,1277,1343,1397,1439,1477,1517,1557,1590,1618,1648,1685,1721,1744,1746,1735,
-1722,1717,1725,1746,1781,1829,1884,1935,1974,2003,2020,2024,2011,1989,1975,1976,1986,1996,2004,2007,2005,
-1998,1991,1989,1991,1989,1980,1968,1957,1948,1939,1928,1917,1907,1897,1887,1875,1864,1854,1842,1830,1817,
-1806,1795,1784,1775,1770,1767,1764,1759,1754,1752,1753,1758,1766,1773,1779,1788,1800,1807,1807,1802,1814,
-1804,1797,1789,1782,1782,1784,1777,1763,1752,1748,1743,1726,1703,1684,1672,1666,1658,1642,1616,1593,1589,
-1590,1566,1503,1428,1375,1351,1339,1333,1338,1350,1350,1322,1269,1208,1149,1086,1011,918,815,726,675,
-677,728,811,888,916,886,829,780,739,682,608,536,477,413,334,252,176,83,-46,-195,-314,
--383,-434,-514,-630,-757,-872,-982,-1105,-1239,-1354,-1425,-1463,-1507,-1581,-1672,-1754,-1818,-1879,-1942,-1999,-2044,
--2080,-2108,-2123,-2121,-2112,-2112,-2120,-2126,-2122,-2112,-2104,-2100,-2100,-2096,-2081,-2052,-2017,-1984,-1950,-1909,-1867,
--1827,-1779,-1697,-1582,-1463,-1355,-1241,-1092,-915,-754,-644,-588,-576,-616,-721,-880,-1045,-1171,-1251,-1316,-1393,
--1474,-1538,-1586,-1632,-1676,-1700,-1712,-1739,-1782,-1798,-1766,-1723,-1706,-1686,-1621,-1551,-1573,-1694,-1793,-1765,-1650,
--1572,-1591,-1679,-1802,-1958,-2127,-2267,-2365,-2461,-2580,-2693,-2770,-2830,-2909,-3005,-3080,-3125,-3175,-3265,-3400,-3560,
--3721,-3860,-3962,-4028,-4069,-4097,-4118,-4137,-4164,-4206,-4259,-4317,-4368,-4411,-4458,-4528,-4626,-4720,-4768,-4762,-4738,
--4738,-4768,-4801,-4815,-4810,-4799,-4789,-4785,-4782,-4778,-4770,-4758,-4742,-4725,-4710,-4709,-4729,-4765,-4801,-4824,-4833,
--4834,-4833,-4833,-4838,-4851,-4871,-4892,-4915,-4941,-4972,-5009,-5057,-5118,-5188,-5252,-5304,-5345,-5383,-5425,-5473,-5527,
--5579,-5629,-5682,-5743,-5808,-5869,-5931,-6008,-6098,-6186,-6257,-6316,-6375,-6438,-6504,-6572,-6643,-6714,-6784,-6854,-6929,
--7001,-7062,-7112,-7156,-7198,-7239,-7283,-7335,-7394,-7457,-7519,-7577,-7626,-7664,-7702,-7752,-7810,-7868,-7929,-8003,-8089,
--8178,-8262,-8348,-8439,-8527,-8607,-8685,-8768,-8852,-8933,-9010,-9082,-9145,-9198,-9246,-9279,-9284,-9272,-9273,-9296,-9316,
--9320,-9353,-9471,-9656,-9806,-9850,-9813,-9780,-9793,-9830,-9861,-9887,-9922,-9960,-9991,-10012,-10032,-10053,-10073,-10096,-10127,
--10158,-10176,-10172,-10146,-10107,-10067,-10031,-9996,-9948,-9874,-9778,-9678,-9590,-9520,-9460,-9404,-9346,-9292,-9246,-9205,-9154,
--9075,-8968,-8854,-8749,-8650,-8544,-8426,-8304,-8192,-8094,-8006,-7913,-7797,-7653,-7497,-7349,-7215,-7073,-6911,-6740,-6593,
--6486,-6405,-6327,-6237,-6139,-6033,-5913,-5780,-5642,-5506,-5363,-5201,-5022,-4846,-4688,-4546,-4406,-4259,-4105,-3950,-3797,
--3643,-3493,-3358,-3239,-3121,-2977,-2810,-2666,-2595,-2601,-2639,-2653,-2595,-2426,-2150,-1849,-1653,-1624,-1692,-1719,-1621,
--1410,-1125,-792,-440,-117,124,270,346,400,473,578,690,780,852,933,1032,1135,1227,1317,1416,1517,
-1610,1702,1801,1899,1986,2066,2149,2231,2304,2380,2470,2571,2666,2756,2857,2970,3075,3159,3234,3310,3386,
-3460,3545,3649,3758,3850,3928,4015,4120,4221,4291,4343,4410,4503,4591,4648,4687,4740,4819,4912,5019,5141,
-5252,5308,5301,5279,5290,5329,5354,5338,5285,5223,5198,5256,5399,5571,5723,5872,6065,6273,6401,6399,6344,
-6361,6473,6584,6586,6467,6316,6221,6189,6163,6095,5996,5897,5800,5691,5588,5533,5534,5555,5564,5568,5562,
-5519,5449,5444,5599,5894,6200,6410,6522,6599,6681,6769,6859,6941,6996,7013,7008,7012,7037,7078,7130,7196,
-7270,7329,7358,7363,7374,7416,7494,7586,7654,7665,7613,7529,7457,7415,7390,7362,7347,7374,7445,7519,7553,
-7550,7536,7521,7498,7473,7464,7461,7413,7295,7144,7040,7027,7079,7140,7175,7188,7202,7229,7262,7290,7309,
-7327,7356,7402,7452,7483,7495,7517,7585,7688,7763,7759,7692,7614,7555,7504,7459,7434,7436,7434,7407,7368,
-7351,7355,7351,7314,7250,7185,7149,7156,7188,7202,7157,7055,6928,6800,6673,6551,6439,6337,6226,6107,6024,
-6030,6125,6235,6268,6197,6078,5992,5980,6018,6059,6076,6070,6057,6043,6024,5992,5950,5909,5875,5835,5772,
-5691,5616,5562,5513,5451,5376,5301,5227,5148,5064,4986,4920,4863,4816,4789,4776,4750,4690,4609,4544,4516,
-4508,4486,4436,4373,4316,4270,4226,4181,4140,4105,4069,4031,3994,3966,3942,3915,3885,3858,3832,3804,3770,
-3729,3683,3633,3583,3534,3487,3438,3387,3337,3297,3270,3250,3228,3200,3173,3146,3099,3019,2925,2852,2804,
-2746,2672,2636,2689,2797,2867,2849,2786,2747,2744,2736,2687,2601,2507,2428,2377,2350,2337,2327,2314,2295,
-2267,2234,2205,2185,2168,2149,2130,2110,2084,2056,2036,2030,2024,2007,1980,1948,1914,1889,1885,1902,1911,
-1889,1857,1859,1899,1928,1901,1829,1759,1724,1723,1734,1742,1737,1719,1695,1673,1651,1628,1603,1583,1569,
-1563,1564,1571,1580,1583,1578,1570,1558,1537,1511,1492,1488,1499,1516,1535,1552,1559,1550,1531,1511,1493,
-1479,1470,1473,1481,1485,1484,1486,1494,1499,1496,1487,1477,1463,1449,1444,1455,1472,1487,1501,1519,1534,
-1541,1546,1558,1568,1563,1548,1542,1553,1565,1567,1563,1558,1551,1541,1536,1541,1548,1549,1542,1533,1525,
-1519,1519,1522,1520,1506,1484,1462,1443,1425,1412,1404,1395,1377,1352,1326,1301,1278,1258,1244,1234,1221,
-1205,1188,1170,1150,1131,1113,1094,1075,1057,1042,1026,1006,984,960,932,901,871,844,819,791,760,
-729,696,660,623,590,559,528,497,469,443,411,371,329,289,251,215,182,152,122,89,53,
-18,-15,-47,-79,-111,-147,-185,-225,-266,-309,-348,-380,-407,-438,-478,-520,-560,-595,-626,-654,-678,
--702,-728,-757,-788,-822,-857,-891,-921,-948,-973,-1000,-1030,-1062,-1098,-1134,-1167,-1199,-1229,-1257,-1278,-1293,
--1311,-1335,-1368,-1405,-1443,-1478,-1512,-1544,-1573,-1602,-1630,-1654,-1676,-1698,-1723,-1747,-1769,-1789,-1810,-1833,-1855,
--1877,-1901,-1926,-1948,-1966,-1980,-1993,-2008,-2024,-2041,-2058,-2074,-2089,-2102,-2113,-2121,-2130,-2139,-2151,-2163,-2174,
--2182,-2184,-2182,-2180,-2182,-2185,-2185,-2181,-2177,-2172,-2163,-2151,-2142,-2136,-2129,-2118,-2105,-2093,-2080,-2064,-2051,
--2040,-2030,-2016,-2001,-1989,-1981,-1971,-1959,-1944,-1930,-1916,-1902,-1889,-1877,-1864,-1853,-1843,-1835,-1824,-1813,-1800,
--1788,-1775,-1761,-1749,-1739,-1729,-1718,-1708,-1698,-1688,-1677,-1666,-1657,-1649,-1641,-1629,-1616,-1604,-1594,-1586,-1576,
--1565,-1553,-1538,-1522,-1509,-1499,-1487,-1471,-1454,-1440,-1428,-1414,-1400,-1389,-1380,-1368,-1354,-1341,-1329,-1317,-1304,
--1294,-1284,-1271,-1256,-1243,-1232,-1219,-1203,-1188,-1175,-1161,-1145,-1129,-1112,-1091,-1068,-1047,-1023,-992,-963,-951,
--954,-956,-947,-928,-892,-819,-718,-631,-594,-595,-589,-559,-523,-496,-477,-459,-438,-415,-382,-341,-300,
--263,-224,-183,-145,-104,-54,2,55,110,179,260,329,385,449,535,618,678,723,757,761,732,
-738,874,1153,1476,1728,1855,1873,1840,1861,2038,2360,2653,2703,2461,2081,1760,1577,1497,1471,1488,1536,
-1587,1630,1688,1774,1862,1912,1921,1923,1941,1962,1957,1927,1896,1875,1848,1793,1721,1658,1616,1584,1548,
-1510,1479,1460,1451,1447,1442,1422,1378,1313,1234,1145,1045,941,844,754,668,585,509,446,391,336,
-274,201,115,27,-51,-119,-188,-265,-345,-415,-478,-542,-609,-667,-706,-729,-752,-789,-840,-895,-949,
--1011,-1092,-1190,-1288,-1374,-1447,-1512,-1568,-1615,-1665,-1733,-1815,-1890,-1935,-1945,-1934,-1928,-1951,-2020,-2122,-2226,
--2306,-2358,-2385,-2384,-2349,-2299,-2264,-2258,-2263,-2267,-2280,-2316,-2362,-2387,-2376,-2345,-2321,-2316,-2333,-2367,-2403,
--2425,-2429,-2427,-2421,-2404,-2383,-2388,-2428,-2474,-2487,-2476,-2482,-2514,-2539,-2527,-2489,-2461,-2453,-2442,-2403,-2333,
--2254,-2196,-2168,-2154,-2125,-2082,-2056,-2075,-2129,-2174,-2182,-2149,-2087,-2012,-1938,-1878,-1837,-1807,-1779,-1749,-1711,
--1659,-1589,-1505,-1423,-1358,-1315,-1281,-1241,-1198,-1167,-1149,-1128,-1086,-1035,-996,-973,-950,-917,-876,-836,-795,
--752,-710,-671,-636,-604,-575,-546,-513,-478,-445,-410,-366,-314,-265,-229,-203,-178,-150,-116,-75,-25,
-25,64,88,104,122,150,185,221,249,266,276,288,304,322,345,378,421,467,507,533,549,
-564,585,614,645,674,704,737,773,806,835,864,896,934,977,1021,1062,1101,1144,1197,1252,1297,
-1329,1358,1397,1446,1492,1528,1553,1574,1597,1621,1643,1659,1668,1675,1684,1700,1724,1763,1820,1888,1951,
-1997,2023,2035,2034,2023,2007,1995,1991,1990,1993,1998,2004,2003,1993,1982,1977,1976,1974,1965,1955,1946,
-1939,1932,1921,1910,1899,1887,1873,1859,1848,1838,1825,1810,1799,1792,1787,1780,1773,1769,1765,1761,1757,
-1755,1753,1753,1760,1774,1790,1802,1813,1824,1830,1825,1814,1818,1806,1804,1807,1812,1815,1812,1796,1774,
-1756,1746,1732,1709,1684,1667,1660,1656,1648,1626,1590,1553,1533,1525,1503,1455,1395,1348,1315,1292,1282,
-1288,1288,1257,1197,1142,1112,1092,1043,949,829,721,649,613,606,630,687,759,811,823,810,793,
-764,703,617,536,478,423,355,280,207,120,-2,-145,-266,-348,-418,-511,-628,-744,-844,-939,-1045,
--1163,-1271,-1356,-1422,-1490,-1571,-1657,-1732,-1790,-1842,-1898,-1957,-2012,-2058,-2088,-2097,-2090,-2085,-2092,-2104,-2108,
--2101,-2090,-2082,-2078,-2079,-2081,-2075,-2053,-2019,-1985,-1950,-1905,-1855,-1814,-1778,-1721,-1633,-1533,-1434,-1315,-1143,
--934,-750,-643,-612,-630,-684,-779,-904,-1030,-1136,-1228,-1326,-1435,-1531,-1591,-1626,-1660,-1698,-1725,-1740,-1764,
--1800,-1816,-1795,-1763,-1743,-1703,-1623,-1568,-1634,-1795,-1896,-1826,-1654,-1542,-1565,-1677,-1823,-1989,-2158,-2291,-2382,
--2474,-2591,-2705,-2784,-2845,-2922,-3004,-3058,-3095,-3165,-3303,-3489,-3674,-3827,-3934,-4000,-4041,-4073,-4097,-4110,-4122,
--4152,-4209,-4278,-4344,-4396,-4437,-4479,-4537,-4617,-4696,-4741,-4740,-4721,-4719,-4740,-4765,-4776,-4775,-4772,-4769,-4760,
--4746,-4731,-4721,-4713,-4701,-4684,-4669,-4670,-4693,-4730,-4767,-4792,-4805,-4810,-4813,-4814,-4817,-4822,-4834,-4856,-4884,
--4916,-4948,-4984,-5029,-5085,-5147,-5207,-5262,-5309,-5349,-5390,-5440,-5497,-5547,-5588,-5630,-5688,-5760,-5828,-5890,-5962,
--6050,-6143,-6224,-6291,-6354,-6419,-6484,-6547,-6609,-6674,-6742,-6815,-6890,-6957,-7011,-7055,-7099,-7144,-7188,-7233,-7284,
--7344,-7408,-7470,-7526,-7576,-7619,-7665,-7717,-7773,-7827,-7884,-7954,-8036,-8120,-8205,-8297,-8394,-8485,-8562,-8637,-8719,
--8805,-8888,-8963,-9028,-9081,-9129,-9174,-9208,-9222,-9221,-9232,-9256,-9270,-9272,-9312,-9439,-9622,-9761,-9793,-9754,-9726,
--9744,-9786,-9823,-9856,-9897,-9938,-9968,-9989,-10009,-10029,-10048,-10071,-10101,-10132,-10150,-10144,-10118,-10083,-10046,-10006,-9957,
--9893,
--9809-9709,-9607,-9514,-9439,-9379,-9330,-9286,-9244,-9206,-9167,-9115,-9035,-8931,-8823,-8723,-8625,-8517,-8397,-8277,
--8171,-8079,-7989,-7879,-7735,-7568,-7411,-7288,-7186,-7068,-6916,-6755,-6626,-6537,-6463,-6376,-6270,-6155,-6037,-5912,-5780,
--5647,-5512,-5368,-5207,-5032,-4859,-4703,-4565,-4433,-4294,-4145,-3989,-3831,-3673,-3518,-3378,-3255,-3133,-2991,-2831,-2694,
--2616,-2593,-2597,-2599,-2572,-2470,-2257,-1971,-1732,-1639,-1671,-1716,-1675,-1527,-1294,-987,-614,-223,108,323,419,
-452,491,570,677,776,859,944,1044,1152,1252,1343,1431,1520,1609,1702,1800,1895,1981,2064,2152,2238,
-2316,2390,2472,2563,2654,2744,2842,2949,3053,3142,3215,3283,3352,3426,3511,3609,3710,3805,3893,3986,4086,
-4178,4246,4299,4362,4445,4526,4582,4621,4674,4755,4850,4951,5056,5152,5207,5220,5232,5274,5322,5325,5268,
-5191,5141,5157,5257,5427,5614,5767,5905,6082,6296,6463,6511,6476,6457,6487,6504,6433,6290,6165,6125,6153,
-6182,6173,6141,6112,6084,6043,6004,6001,6036,6075,6098,6111,6108,6051,5943,5870,5921,6077,6224,6282,6284,
-6314,6404,6523,6639,6740,6828,6897,6944,6969,6978,6988,7017,7073,7136,7181,7200,7206,7214,7229,7245,7256,
-7258,7255,7259,7276,7299,7310,7298,7275,7269,7300,7363,7432,7481,7501,7500,7494,7495,7518,7558,7588,7560,
-7452,7293,7150,7072,7062,7087,7111,7123,7131,7148,7177,7218,7272,7343,7428,7510,7566,7584,7580,7594,7653,
-7738,7800,7809,7777,7733,7687,7639,7596,7576,7574,7569,7550,7530,7522,7516,7495,7453,7396,7332,7276,7251,
-7260,7276,7268,7226,7159,7069,6952,6825,6715,6621,6503,6340,6182,6116,6182,6312,6389,6346,6221,6106,6060,
-6076,6107,6121,6113,6097,6082,6069,6046,6007,5959,5916,5874,5814,5733,5651,5589,5540,5481,5405,5324,5246,
-5168,5088,5014,4951,4898,4860,4843,4837,4812,4748,4665,4600,4570,4555,4526,4475,4415,4360,4307,4253,4204,
-4166,4136,4103,4064,4026,3996,3970,3944,3916,3887,3855,3820,3788,3761,3732,3689,3633,3573,3517,3467,3419,
-3370,3327,3297,3280,3263,3239,3214,3191,3150,3071,2973,2898,2857,2810,2729,2655,2651,2715,2785,2810,2802,
-2788,2766,2715,2638,2556,2485,2432,2398,2382,2373,2358,2336,2311,2282,2253,2229,2213,2195,2168,2139,2113,
-2087,2057,2030,2013,2001,1985,1966,1947,1927,1904,1887,1884,1887,1882,1882,1913,1969,2001,1968,1882,1792,
-1739,1725,1734,1746,1748,1732,1706,1678,1651,1623,1597,1581,1578,1581,1584,1586,1587,1589,1594,1605,1617,
-1614,1590,1556,1527,1513,1511,1517,1527,1534,1535,1528,1520,1512,1502,1492,1487,1488,1489,1491,1497,1505,
-1508,1502,1493,1483,1470,1452,1440,1440,1451,1466,1485,1507,1525,1535,1545,1559,1569,1563,1549,1542,1547,
-1554,1555,1551,1541,1525,1510,1510,1524,1535,1530,1515,1506,1505,1506,1505,1505,1502,1494,1479,1460,1439,
-1421,1410,1404,1396,1377,1353,1329,1306,1281,1257,1241,1231,1220,1204,1187,1172,1155,1133,1109,1084,1062,
-1042,1023,1003,982,961,940,915,885,855,829,805,780,752,723,691,655,621,592,566,538,510,
-486,463,434,395,352,309,269,230,194,163,130,95,57,21,-11,-43,-75,-110,-148,-190,-232,
--274,-314,-351,-381,-406,-436,-473,-513,-551,-587,-620,-648,-670,-687,-706,-729,-758,-792,-829,-866,-899,
--926,-953,-981,-1012,-1046,-1081,-1116,-1148,-1179,-1211,-1239,-1260,-1277,-1297,-1325,-1357,-1391,-1425,-1458,-1489,-1517,
--1544,-1573,-1602,-1628,-1651,-1674,-1700,-1725,-1747,-1768,-1789,-1810,-1829,-1847,-1868,-1890,-1911,-1931,-1948,-1964,-1980,
--1997,-2014,-2031,-2044,-2056,-2066,-2076,-2084,-2092,-2102,-2114,-2127,-2140,-2150,-2154,-2153,-2152,-2154,-2155,-2152,-2147,
--2142,-2138,-2130,-2119,-2110,-2103,-2095,-2085,-2072,-2060,-2046,-2032,-2019,-2008,-1996,-1982,-1969,-1958,-1949,-1939,-1928,
--1916,-1904,-1891,-1877,-1864,-1850,-1837,-1825,-1816,-1806,-1796,-1786,-1777,-1767,-1755,-1741,-1728,-1718,-1708,-1697,-1686,
--1676,-1669,-1660,-1650,-1641,-1635,-1629,-1618,-1604,-1592,-1584,-1575,-1564,-1552,-1542,-1530,-1516,-1502,-1491,-1481,-1468,
--1453,-1439,-1428,-1414,-1402,-1393,-1386,-1374,-1359,-1347,-1338,-1328,-1316,-1304,-1292,-1279,-1266,-1256,-1247,-1233,-1215,
--1200,-1190,-1178,-1162,-1145,-1128,-1108,-1084,-1062,-1040,-1014,-985,-964,-953,-948,-948,-950,-943,-903,-832,-765,
--734,-726,-707,-664,-616,-580,-554,-526,-496,-461,-422,-376,-331,-288,-247,-205,-162,-116,-64,-9,41,
-94,157,229,293,350,413,487,557,614,660,691,688,664,693,856,1151,1485,1755,1915,1965,1941,
-1933,2058,2350,2672,2791,2591,2182,1783,1540,1447,1434,1457,1501,1555,1611,1678,1765,1852,1904,1918,1923,
-1939,1951,1938,1907,1883,1870,1845,1794,1731,1678,1638,1599,1557,1523,1501,1489,1480,1474,1469,1450,1408,
-1343,1266,1179,1082,983,888,801,716,634,564,509,465,414,347,261,161,63,-20,-92,-164,-242,
--321,-390,-451,-517,-589,-654,-701,-732,-761,-802,-853,-909,-963,-1023,-1100,-1190,-1285,-1374,-1451,-1513,-1556,
--1586,-1623,-1684,-1761,-1824,-1848,-1834,-1806,-1801,-1847,-1949,-2079,-2196,-2276,-2319,-2335,-2321,-2279,-2231,-2207,-2212,
--2225,-2230,-2240,-2273,-2318,-2344,-2339,-2320,-2311,-2317,-2334,-2359,-2387,-2409,-2418,-2421,-2420,-2407,-2388,-2391,-2429,
--2474,-2488,-2472,-2468,-2494,-2523,-2524,-2509,-2514,-2544,-2568,-2551,-2483,-2381,-2277,-2203,-2163,-2133,-2088,-2034,-2002,
--2007,-2030,-2040,-2023,-1980,-1918,-1848,-1786,-1743,-1717,-1698,-1678,-1657,-1633,-1597,-1531,-1439,-1348,-1288,-1259,-1237,
--1207,-1178,-1162,-1151,-1130,-1098,-1069,-1044,-1014,-975,-935,-900,-866,-827,-785,-748,-716,-691,-671,-651,-624,
--591,-560,-528,-487,-434,-385,-352,-332,-311,-285,-257,-228,-195,-158,-123,-91,-61,-30,5,47,92,
-132,163,189,217,253,294,335,378,424,471,511,539,554,565,579,599,625,658,699,745,786,
-815,837,860,887,920,958,998,1038,1078,1125,1182,1238,1277,1298,1316,1347,1387,1425,1453,1475,1493,
-1510,1530,1558,1591,1625,1657,1686,1714,1741,1776,1824,1882,1936,1974,1995,2003,2006,2007,2009,2010,2007,
-1999,1992,1991,1994,1994,1986,1976,1968,1963,1957,1948,1939,1933,1929,1924,1916,1905,1893,1878,1860,1843,
-1832,1821,1807,1789,1778,1776,1775,1771,1767,1765,1761,1756,1754,1757,1760,1761,1769,1788,1810,1823,1830,
-1837,1841,1834,1818,1819,1809,1812,1825,1836,1838,1828,1807,1781,1757,1738,1716,1690,1668,1653,1641,1628,
-1614,1592,1555,1510,1472,1449,1427,1396,1358,1318,1279,1245,1228,1222,1198,1137,1060,1019,1029,1048,1016,
-913,773,652,579,546,534,535,562,617,681,730,758,769,753,698,614,537,484,440,383,314,
-241,153,38,-94,-215,-312,-403,-509,-624,-730,-822,-911,-1005,-1101,-1192,-1280,-1367,-1455,-1545,-1633,-1709,
--1766,-1805,-1842,-1890,-1952,-2012,-2050,-2061,-2058,-2060,-2075,-2087,-2083,-2069,-2059,-2058,-2058,-2055,-2053,-2047,-2028,
--1997,-1964,-1929,-1883,-1830,-1787,-1757,-1717,-1651,-1570,-1486,-1370,-1184,-953,-758,-661,-654,-694,-755,-835,-930,
--1023,-1113,-1216,-1341,-1472,-1573,-1629,-1656,-1686,-1723,-1753,-1770,-1791,-1822,-1840,-1823,-1783,-1741,-1691,-1632,-1625,
--1728,-1887,-1950,-1837,-1646,-1543,-1585,-1707,-1848,-2002,-2166,-2305,-2403,-2495,-2608,-2723,-2811,-2878,-2940,-2989,-3019,
--3064,-3178,-3367,-3580,-3764,-3895,-3977,-4023,-4051,-4076,-4094,-4100,-4107,-4141,-4210,-4295,-4370,-4425,-4465,-4500,-4538,
--4589,-4644,-4682,-4692,-4686,-4688,-4702,-4717,-4723,-4727,-4735,-4742,-4735,-4715,-4693,-4681,-4674,-4663,-4645,-4631,-4634,
--4658,-4695,-4730,-4756,-4774,-4788,-4798,-4802,-4798,-4792,-4796,-4817,-4851,-4887,-4919,-4953,-4998,-5054,-5112,-5167,-5220,
--5268,-5311,-5351,-5399,-5456,-5508,-5547,-5583,-5637,-5711,-5789,-5859,-5930,-6011,-6097,-6179,-6252,-6321,-6389,-6453,-6514,
--6575,-6639,-6707,-6779,-6850,-6910,-6958,-7002,-7051,-7103,-7150,-7192,-7238,-7294,-7356,-7418,-7475,-7527,-7576,-7627,-7681,
--7733,-7782,-7837,-7905,-7984,-8066,-8153,-8250,-8349,-8437,-8513,-8589,-8673,-8759,-8835,-8900,-8957,-9011,-9065,-9117,-9156,
--9171,-9173,-9185,-9207,-9220,-9230,-9286,-9421,-9593,-9711,-9733,-9699,-9683,-9708,-9753,-9797,-9840,-9885,-9924,-9949,-9964,
--9979,-9995,-10009,-10027,-10054,-10084,-10100,-10093,-10068,-10037,-10000,-9953,-9888,-9809,-9719,-9625,-9530,-9439,-9360,-9299,-9254,
--9215,-9176,-9133,-9088,-9035,-8967,-8885,-8797,-8710,-8616,-8508,-8386,-8268,-8162,-8066,-7963,-7832,-7668,-7489,-7336,-7232,
--7155,-7057,-6918,-6770,-6656,-6577,-6498,-6394,-6268,-6142,-6020,-5898,-5773,-5645,-5514,-5373,-5215,-5044,-4872,-4716,-4582,
--4460,-4332,-4187,-4030,-3871,-3712,-3557,-3411,-3281,-3154,-3013,-2864,-2738,-2660,-2617,-2584,-2551,-2520,-2463,-2331,-2115,
--1885,-1736,-1694,-1702,-1683,-1593,-1418,-1143,-767,-340,52,330,471,514,531,577,663,767,864,954,1052,
-1164,1277,1375,1456,1526,1601,1688,1786,1884,1973,2056,2140,2229,2317,2401,2483,2565,2649,2736,2828,2928,
-3028,3120,3196,3259,3321,3392,3474,3561,3652,3746,3842,3937,4031,4117,4187,4242,4296,4366,4446,4514,4565,
-4616,4681,4759,4847,4946,5043,5112,5152,5198,5270,5335,5334,5261,5168,5117,5138,5249,5446,5686,5901,6066,
-6217,6379,6510,6550,6508,6449,6412,6363,6259,6122,6027,6023,6085,6145,6161,6143,6125,6118,6115,6123,6159,
-6222,6288,6341,6380,6393,6349,6254,6171,6152,6164,6125,6021,5934,5953,6077,6236,6376,6493,6607,6719,6812,
-6866,6878,6874,6886,6927,6979,7021,7055,7088,7112,7106,7068,7011,6959,6937,6971,7058,7154,7210,7212,7189,
-7175,7183,7210,7255,7309,7350,7364,7366,7383,7428,7487,7532,7536,7480,7370,7241,7145,7109,7121,7140,7140,
-7124,7113,7124,7166,7242,7347,7465,7566,7628,7648,7650,7666,7707,7756,7791,7809,7822,7830,7819,7790,7765,
-7763,7775,7778,7768,7759,7751,7726,7678,7622,7571,7516,7448,7380,7333,7309,7301,7298,7284,7232,7130,7009,
-6918,6862,6788,6644,6457,6316,6282,6326,6358,6321,6237,6164,6134,6136,6145,6150,6147,6136,6121,6108,6093,
-6062,6013,5958,5906,5848,5773,5688,5616,5559,5502,5433,5356,5279,5202,5126,5056,4997,4952,4921,4906,4894,
-4860,4791,4708,4645,4613,4591,4554,4503,4450,4399,4344,4288,4242,4213,4187,4150,4103,4063,4037,4017,3992,
-3959,3923,3886,3850,3820,3797,3773,3735,3682,3622,3565,3514,3466,3416,3366,3326,3303,3291,3277,3257,3231,
-3189,3116,3025,2953,2913,2874,2807,2727,2681,2685,2715,2750,2784,2803,2779,2708,2622,2551,2497,2451,2423,
-2418,2421,2409,2377,2340,2306,2278,2256,2240,2220,2188,2150,2118,2092,2061,2026,1999,1982,1970,1958,1949,
-1941,1926,1906,1890,1880,1871,1870,1893,1932,1948,1914,1844,1780,1745,1737,1742,1750,1749,1730,1701,1674,
-1651,1623,1592,1573,1577,1595,1611,1616,1614,1611,1612,1623,1641,1648,1629,1588,1549,1528,1523,1526,1529,
-1532,1532,1528,1522,1518,1514,1508,1503,1500,1501,1504,1509,1512,1511,1504,1495,1489,1478,1460,1441,1431,
-1435,1448,1468,1489,1506,1517,1526,1537,1545,1543,1538,1537,1540,1541,1538,1532,1521,1501,1484,1485,1502,
-1512,1504,1488,1482,1486,1490,1487,1483,1481,1477,1470,1457,1440,1422,1409,1402,1394,1376,1353,1329,1306,
-1280,1256,1240,1229,1217,1199,1182,1168,1151,1129,1102,1076,1052,1029,1007,986,965,945,924,899,869,
-839,813,790,766,739,711,680,648,617,591,566,539,512,486,463,434,397,357,316,275,236,
-200,169,138,103,65,27,-8,-42,-77,-114,-156,-201,-244,-284,-322,-356,-385,-412,-441,-474,-508,
--540,-573,-608,-639,-662,-678,-692,-708,-731,-762,-800,-838,-872,-903,-932,-962,-993,-1025,-1058,-1089,-1118,
--1149,-1181,-1212,-1237,-1259,-1285,-1317,-1349,-1379,-1407,-1436,-1463,-1486,-1510,-1539,-1571,-1600,-1625,-1651,-1678,-1705,
--1727,-1747,-1765,-1783,-1800,-1817,-1835,-1854,-1874,-1895,-1916,-1935,-1952,-1969,-1987,-2002,-2013,-2021,-2030,-2040,-2050,
--2059,-2068,-2078,-2090,-2102,-2112,-2119,-2121,-2121,-2121,-2120,-2116,-2108,-2103,-2099,-2094,-2087,-2079,-2071,-2062,-2051,
--2038,-2024,-2010,-1997,-1984,-1973,-1961,-1949,-1938,-1926,-1915,-1903,-1893,-1884,-1874,-1863,-1851,-1839,-1826,-1812,-1799,
--1789,-1779,-1768,-1757,-1748,-1740,-1730,-1718,-1706,-1697,-1688,-1678,-1666,-1656,-1650,-1643,-1632,-1622,-1616,-1612,-1604,
--1592,-1580,-1573,-1563,-1550,-1538,-1529,-1521,-1509,-1495,-1482,-1472,-1460,-1448,-1439,-1430,-1418,-1406,-1398,-1391,-1380,
--1364,-1352,-1344,-1337,-1326,-1314,-1301,-1288,-1274,-1265,-1256,-1244,-1228,-1216,-1208,-1197,-1180,-1162,-1146,-1126,-1102,
--1079,-1058,-1036,-1011,-987,-967,-949,-933,-926,-924,-909,-871,-827,-797,-777,-747,-702,-657,-622,-591,-556,
--516,-478,-439,-396,-351,-307,-267,-224,-178,-127,-74,-21,29,83,140,202,264,327,388,446,499,
-555,609,639,626,598,635,805,1086,1389,1629,1778,1849,1870,1901,2041,2343,2710,2912,2773,2341,1850,
-1517,1386,1375,1403,1450,1518,1598,1675,1752,1826,1887,1925,1946,1956,1952,1930,1904,1891,1882,1855,1804,
-1748,1702,1660,1616,1576,1552,1541,1529,1513,1499,1489,1468,1425,1360,1284,1199,1107,1013,924,842,763,
-688,628,583,542,486,406,305,195,89,-1,-78,-148,-217,-285,-350,-416,-492,-572,-643,-697,-739,
--783,-835,-892,-946,-996,-1052,-1120,-1202,-1292,-1382,-1459,-1514,-1545,-1563,-1590,-1638,-1697,-1740,-1747,-1719,-1686,
--1688,-1751,-1868,-2002,-2116,-2192,-2234,-2247,-2232,-2198,-2164,-2151,-2159,-2167,-2168,-2175,-2203,-2244,-2271,-2276,-2276,
--2287,-2305,-2322,-2342,-2368,-2394,-2411,-2425,-2442,-2453,-2456,-2464,-2491,-2520,-2520,-2494,-2476,-2487,-2506,-2513,-2525,
--2570,-2640,-2692,-2692,-2635,-2533,-2409,-2298,-2229,-2197,-2162,-2101,-2026,-1968,-1935,-1918,-1903,-1880,-1836,-1768,-1689,
--1627,-1594,-1582,-1575,-1577,-1593,-1608,-1585,-1504,-1396,-1316,-1290,-1293,-1287,-1262,-1236,-1216,-1197,-1170,-1136,-1094,
--1046,-995,-953,-920,-890,-855,-819,-785,-754,-727,-708,-690,-664,-631,-598,-569,-535,-491,-448,-418,-399,
--379,-352,-325,-300,-275,-245,-210,-170,-128,-89,-52,-13,31,78,119,155,191,235,285,333,378,
-418,456,489,515,531,542,554,572,598,632,675,720,755,777,792,811,836,866,900,941,983,
-1025,1071,1128,1187,1233,1259,1279,1305,1336,1364,1391,1420,1448,1473,1500,1534,1576,1620,1661,1700,1735,
-1763,1790,1823,1864,1903,1935,1956,1967,1974,1984,1998,2010,2010,1999,1987,1982,1980,1977,1972,1967,1962,
-1956,1948,1939,1930,1922,1916,1911,1903,1893,1881,1867,1850,1834,1822,1813,1801,1784,1772,1768,1766,1762,
-1759,1759,1757,1752,1751,1758,1767,1773,1783,1805,1827,1838,1839,1839,1841,1834,1819,1819,1813,1822,1836,
-1842,1834,1816,1794,1772,1750,1727,1701,1675,1654,1632,1607,1579,1559,1541,1512,1466,1416,1376,1350,1328,
-1301,1264,1221,1183,1161,1142,1095,1014,939,921,964,1013,1003,911,767,625,525,476,462,462,476,
-515,575,639,689,715,708,666,601,538,493,456,407,342,267,182,79,-39,-158,-272,-387,-509,
--625,-722,-807,-894,-985,-1069,-1146,-1227,-1319,-1412,-1502,-1589,-1669,-1727,-1753,-1765,-1793,-1851,-1923,-1980,-2009,
--2019,-2030,-2049,-2060,-2051,-2032,-2024,-2028,-2030,-2023,-2016,-2012,-2000,-1975,-1942,-1906,-1861,-1808,-1762,-1729,-1689,
--1626,-1557,-1488,-1383,-1199,-964,-772,-688,-692,-732,-785,-859,-946,-1030,-1113,-1219,-1353,-1489,-1589,-1643,-1672,
--1704,-1744,-1777,-1796,-1814,-1844,-1866,-1853,-1805,-1748,-1703,-1684,-1723,-1833,-1952,-1965,-1832,-1655,-1572,-1620,-1730,
--1850,-1989,-2154,-2310,-2426,-2519,-2623,-2740,-2845,-2924,-2968,-2979,-2986,-3051,-3214,-3439,-3653,-3813,-3920,-3990,-4031,
--4052,-4067,-4078,-4083,-4094,-4135,-4212,-4302,-4379,-4436,-4478,-4507,-4529,-4555,-4590,-4619,-4633,-4636,-4642,-4654,-4663,
--4666,-4672,-4686,-4698,-4695,-4676,-4656,-4644,-4636,-4622,-4603,-4591,-4598,-4625,-4661,-4693,-4718,-4738,-4757,-4772,-4775,
--4765,-4750,-4749,-4771,-4807,-4842,-4868,-4899,-4948,-5012,-5076,-5130,-5179,-5227,-5271,-5311,-5355,-5409,-5464,-5510,-5549,
--5599,-5668,-5749,-5828,-5902,-5976,-6053,-6132,-6207,-6279,-6346,-6411,-6475,-6540,-6606,-6673,-6741,-6808,-6867,-6916,-6963,
--7014,-7068,-7115,-7155,-7196,-7247,-7306,-7368,-7428,-7485,-7539,-7591,-7641,-7687,-7734,-7790,-7859,-7936,-8016,-8102,-8198,
--8295,-8381,-8460,-8542,-8629,-8711,-8776,-8829,-8881,-8941,-9008,-9072,-9116,-9132,-9134,-9142,-9156,-9166,-9189,-9264,-9405,
--9562,-9658,-9673,-9652,-9652,-9684,-9729,-9774,-9821,-9867,-9900,-9918,-9928,-9939,-9949,-9956,-9967,-9988,-10015,-10031,-10026,
--10004,-9974,-9936,-9881,-9805,-9716,-9627,-9545,-9463,-9376,-9290,-9216,-9162,-9120,-9078,-9033,-8989,-8947,-8900,-8844,-8779,
--8706,-8617,-8506,-8382,-8261,-8148,-8039,-7921,-7784,-7623,-7455,-7312,-7214,-7141,-7047,-6915,-6776,-6667,-6584,-6491,-6370,
--6236,-6111,-5996,-5881,-5763,-5642,-5514,-5374,-5220,-5056,-4889,-4734,-4602,-4486,-4365,-4223,-4065,-3905,-3749,-3595,-3450,
--3317,-3187,-3045,-2899,-2778,-2700,-2644,-2578,-2501,-2438,-2397,-2342,-2231,-2069,-1906,-1786,-1714,-1663,-1593,-1465,-1238,
--898,-484,-69,266,482,580,605,619,667,754,854,951,1052,1168,1292,1400,1476,1530,1586,1662,1758,
-1861,1955,2038,2118,2209,2309,2406,2490,2567,2647,2734,2823,2912,3003,3093,3172,3236,3296,3364,3438,3515,
-3596,3687,3781,3868,3948,4027,4102,4163,4214,4277,4361,4448,4514,4557,4596,4648,4729,4843,4969,5067,5128,
-5186,5270,5348,5366,5313,5232,5171,5158,5231,5430,5732,6040,6257,6372,6433,6467,6459,6410,6355,6316,6267,
-6175,6050,5951,5923,5956,6000,6013,5996,5979,5984,6008,6044,6098,6173,6254,6324,6370,6383,6356,6298,6238,
-6180,6078,5899,5693,5576,5618,5780,5966,6116,6231,6337,6447,6548,6616,6644,6654,6682,6742,6813,6875,6934,
-6994,7031,7020,6963,6890,6830,6807,6848,6953,7072,7141,7140,7102,7065,7039,7031,7061,7128,7196,7228,7235,
-7252,7289,7333,7372,7405,7413,7372,7293,7233,7235,7284,7324,7319,7280,7239,7221,7232,7280,7359,7457,7550,
-7622,7672,7709,7744,7774,7793,7801,7818,7853,7889,7901,7888,7883,7906,7940,7955,7950,7940,7925,7884,7816,
-7747,7698,7656,7599,7525,7452,7400,7377,7380,7380,7337,7233,7109,7025,6996,6970,6883,6732,6573,6452,6364,
-6278,6196,6147,6149,6175,6188,6179,6172,6178,6182,6171,6149,6128,6102,6058,5998,5937,5879,5813,5735,5657,
-5591,5531,5469,5403,5334,5260,5182,5110,5052,5012,4986,4969,4946,4899,4824,4741,4679,4644,4616,4576,4526,
-4477,4430,4378,4326,4288,4264,4235,4187,4130,4089,4071,4057,4029,3988,3948,3916,3890,3866,3841,3810,3770,
-3724,3675,3623,3571,3521,3468,3410,3353,3316,3304,3299,3284,3253,3208,3148,3078,3017,2971,2926,2863,2788,
-2725,2688,2680,2704,2752,2786,2771,2714,2655,2612,2565,2501,2449,2437,2448,2442,2408,2366,2332,2305,2282,
-2264,2246,2216,2177,2141,2109,2073,2034,2003,1986,1976,1967,1962,1959,1951,1933,1912,1890,1870,1856,1857,
-1863,1849,1807,1761,1740,1743,1752,1758,1759,1750,1726,1698,1687,1688,1676,1640,1600,1584,1595,1616,1633,
-1642,1642,1635,1629,1633,1637,1624,1592,1560,1548,1551,1554,1550,1542,1535,1527,1519,1515,1514,1513,1511,
-1510,1509,1509,1509,1510,1509,1506,1500,1493,1482,1464,1443,1430,1430,1443,1461,1475,1485,1491,1497,1502,
-1506,1508,1512,1519,1524,1525,1523,1520,1511,1491,1471,1467,1478,1485,1479,1468,1466,1470,1472,1468,1465,
-1462,1459,1454,1448,1439,1426,1414,1406,1397,1379,1354,1328,1302,1277,1255,1239,1227,1212,1192,1174,1158,
-1140,1117,1092,1067,1042,1016,992,971,952,932,908,879,850,822,797,774,750,722,693,664,636,
-608,581,555,526,497,470,444,416,383,348,313,275,237,201,171,141,108,70,32,-5,-41,
--79,-119,-162,-206,-249,-287,-321,-352,-381,-410,-441,-472,-500,-527,-557,-592,-626,-655,-675,-689,-701,
--717,-742,-776,-813,-847,-879,-910,-941,-970,-1000,-1032,-1062,-1089,-1116,-1146,-1177,-1206,-1233,-1264,-1298,-1331,
--1360,-1387,-1413,-1436,-1458,-1481,-1510,-1542,-1572,-1599,-1626,-1655,-1682,-1705,-1722,-1737,-1751,-1767,-1784,-1801,-1818,
--1837,-1859,-1882,-1901,-1916,-1932,-1951,-1966,-1975,-1982,-1992,-2005,-2017,-2027,-2036,-2044,-2053,-2061,-2070,-2078,-2082,
--2083,-2083,-2081,-2076,-2069,-2061,-2056,-2053,-2050,-2045,-2038,-2028,-2015,-2001,-1986,-1972,-1960,-1949,-1939,-1928,-1918,
--1907,-1894,-1880,-1868,-1858,-1849,-1840,-1830,-1821,-1812,-1800,-1787,-1775,-1764,-1753,-1741,-1729,-1719,-1711,-1702,-1692,
--1681,-1673,-1666,-1658,-1648,-1639,-1632,-1625,-1614,-1602,-1596,-1593,-1588,-1578,-1567,-1560,-1552,-1540,-1526,-1518,-1512,
--1503,-1490,-1477,-1466,-1455,-1445,-1438,-1432,-1422,-1410,-1402,-1396,-1386,-1372,-1360,-1352,-1345,-1335,-1326,-1316,-1304,
--1290,-1278,-1268,-1257,-1244,-1234,-1227,-1216,-1199,-1181,-1165,-1147,-1123,-1100,-1080,-1059,-1037,-1015,-994,-968,-935,
--906,-891,-881,-860,-829,-797,-767,-733,-694,-658,-628,-597,-558,-518,-483,-450,-412,-368,-324,-284,-240,
--190,-137,-86,-36,17,74,128,182,243,310,369,414,457,518,581,606,577,543,586,749,991,
-1225,1387,1482,1557,1654,1797,2016,2333,2688,2900,2790,2363,1837,1463,1320,1316,1344,1387,1465,1569,1662,
-1733,1799,1870,1936,1976,1985,1968,1941,1922,1916,1906,1873,1822,1772,1729,1685,1638,1603,1587,1580,1565,
-1544,1527,1513,1489,1441,1372,1292,1206,1115,1025,943,869,801,740,690,650,604,536,444,334,220,
-111,14,-67,-133,-189,-243,-305,-380,-467,-555,-629,-688,-742,-804,-872,-935,-986,-1032,-1084,-1147,-1223,
--1310,-1397,-1470,-1517,-1541,-1557,-1578,-1607,-1635,-1652,-1649,-1627,-1610,-1626,-1692,-1795,-1904,-1997,-2067,-2113,-2133,
--2128,-2110,-2093,-2086,-2085,-2082,-2082,-2096,-2132,-2175,-2205,-2219,-2231,-2254,-2277,-2295,-2313,-2340,-2373,-2402,-2430,
--2467,-2508,-2540,-2561,-2580,-2591,-2576,-2541,-2512,-2503,-2499,-2499,-2528,-2607,-2706,-2768,-2768,-2718,-2634,-2520,-2401,
--2315,-2280,-2262,-2219,-2142,-2053,-1976,-1922,-1888,-1863,-1819,-1738,-1633,-1544,-1496,-1480,-1474,-1478,-1507,-1555,-1578,
--1535,-1440,-1357,-1333,-1354,-1370,-1353,-1315,-1277,-1242,-1201,-1149,-1090,-1031,-977,-935,-901,-870,-839,-810,-781,
--746,-710,-680,-658,-634,-602,-568,-541,-517,-488,-457,-432,-414,-393,-365,-335,-306,-278,-246,-209,-169,
--126,-88,-57,-28,5,47,89,127,161,198,240,283,319,347,372,398,421,440,453,468,491,
-521,556,595,634,665,687,708,736,768,800,835,877,922,960,996,1040,1092,1138,1172,1202,1236,
-1271,1306,1345,1392,1441,1484,1522,1561,1598,1632,1663,1696,1729,1757,1782,1808,1839,1873,1909,1940,1960,
-1968,1975,1989,2001,2000,1988,1976,1970,1965,1959,1955,1954,1952,1947,1940,1934,1925,1914,1903,1896,1887,
-1878,1868,1860,1847,1832,1821,1814,1805,1792,1779,1772,1765,1758,1755,1756,1757,1754,1754,1762,1773,1781,
-1793,1813,1833,1841,1837,1835,1836,1831,1819,1819,1818,1829,1840,1834,1813,1788,1769,1755,1737,1712,1681,
-1651,1623,1592,1555,1519,1497,1484,1462,1418,1362,1313,1280,1256,1229,1190,1145,1110,1088,1060,998,912,
-847,845,900,962,975,915,789,632,495,419,403,417,433,455,498,557,610,639,640,616,576,
-533,497,462,415,351,280,204,117,12,-107,-237,-374,-511,-631,-724,-803,-888,-978,-1061,-1133,-1206,
--1289,-1373,-1453,-1533,-1611,-1668,-1684,-1674,-1676,-1719,-1795,-1874,-1932,-1964,-1985,-2007,-2021,-2016,-1998,-1986,-1986,
--1986,-1980,-1978,-1985,-1985,-1963,-1926,-1886,-1843,-1793,-1747,-1706,-1658,-1593,-1530,-1473,-1377,-1197,-971,-801,-742,
--753,-773,-801,-866,-960,-1050,-1129,-1227,-1356,-1487,-1585,-1643,-1680,-1717,-1757,-1791,-1811,-1826,-1849,-1870,-1862,
--1817,-1762,-1731,-1739,-1790,-1875,-1950,-1943,-1828,-1678,-1600,-1629,-1719,-1829,-1964,-2134,-2304,-2436,-2532,-2627,-2742,
--2864,-2961,-3001,-2987,-2980,-3061,-3254,-3491,-3688,-3819,-3909,-3979,-4022,-4038,-4042,-4049,-4061,-4083,-4131,-4207,-4290,
--4362,-4420,-4465,-4496,-4513,-4531,-4555,-4576,-4586,-4590,-4601,-4618,-4629,-4633,-4637,-4645,-4650,-4643,-4627,-4612,-4604,
--4596,-4581,-4563,-4553,-4562,-4589,-4623,-4653,-4676,-4696,-4715,-4729,-4730,-4716,-4700,-4699,-4723,-4759,-4789,-4812,-4843,
--4897,-4967,-5034,-5088,-5133,-5179,-5226,-5270,-5312,-5360,-5416,-5470,-5518,-5567,-5628,-5703,-5782,-5857,-5930,-6006,-6086,
--6164,-6235,-6300,-6364,-6431,-6500,-6565,-6628,-6692,-6759,-6822,-6876,-6925,-6974,-7025,-7074,-7118,-7161,-7207,-7262,-7323,
--7387,-7448,-7504,-7553,-7597,-7638,-7685,-7745,-7815,-7889,-7964,-8046,-8138,-8232,-8321,-8407,-8496,-8582,-8656,-8712,-8761,
--8814,-8878,-8951,-9020,-9067,-9087,-9093,-9101,-9107,-9113,-9146,-9239,-9387,-9527,-9601,-9612,-9608,-9625,-9661,-9701,-9740,
--9782,-9821,-9848,-9863,-9873,-9882,-9887,-9889,-9894,-9909,-9932,-9949,-9948,-9932,-9904,-9866,-9810,-9733,-9645,-9562,-9490,
--9419,-9332,-9229,-9130,-9053,-9003,-8968,-8938,-8913,-8892,-8866,-8827,-8773,-8705,-8615,-8501,-8372,-8243,-8121,-8001,-7876,
--7747,-7611,-7470,-7339,-7234,-7147,-7044,-6911,-6772,-6657,-6560,-6453,-6328,-6204,-6094,-5988,-5876,-5760,-5642,-5517,-5376,
--5222,-5062,-4904,-4756,-4627,-4513,-4392,-4249,-4088,-3926,-3772,-3624,-3483,-3352,-3220,-3074,-2925,-2801,-2719,-2653,-2564,
--2447,-2344,-2296,-2294,-2286,-2221,-2091,-1926,-1769,-1647,-1555,-1456,-1294,-1032,-674,-268,119,426,612,681,687,
-698,755,847,951,1058,1175,1298,1404,1477,1524,1571,1639,1731,1837,1936,2020,2100,2193,2302,2405,2489,
-2560,2638,2728,2816,2896,2976,3061,3142,3211,3272,3334,3400,3470,3548,3639,3732,3812,3882,3956,4035,4104,
-4159,4221,4306,4399,4468,4503,4521,4556,4640,4778,4936,5058,5126,5176,5250,5334,5382,5374,5331,5268,5206,
-5211,5377,5714,6093,6348,6417,6369,6299,6254,6236,6242,6259,6249,6179,6055,5924,5836,5804,5804,5804,5798,
-5809,5851,5909,5962,6013,6074,6144,6199,6222,6216,6197,6172,6134,6056,5903,5685,5484,5405,5479,5646,5816,
-5943,6030,6097,6162,6227,6282,6314,6338,6393,6497,6619,6729,6825,6911,6966,6962,6911,6852,6811,6800,6834,
-6920,7018,7069,7050,6995,6942,6905,6898,6946,7050,7158,7222,7244,7260,7279,7291,7310,7353,7396,7395,7354,
-7340,7407,7518,7593,7593,7549,7501,7463,7434,7420,7432,7473,7534,7607,7684,7752,7801,7827,7835,7836,7848,
-7876,7908,7920,7915,7922,7959,8005,8028,8023,8009,7988,7947,7881,7811,7759,7725,7691,7647,7598,7553,7524,
-7515,7505,7455,7349,7221,7127,7084,7058,7003,6912,6800,6666,6493,6295,6135,6077,6123,6201,6236,6221,6201,
-6208,6226,6222,6191,6154,6122,6085,6033,5972,5912,5851,5784,5712,5641,5575,5514,5456,5397,5329,5251,5173,
-5111,5069,5043,5020,4987,4932,4855,4775,4713,4677,4647,4605,4551,4496,4447,4400,4357,4325,4300,4263,4205,
-4145,4108,4096,4081,4045,3997,3959,3938,3926,3910,3883,3847,3807,3768,3730,3685,3632,3577,3522,3457,3387,
-3334,3311,3306,3292,3259,3217,3174,3133,3091,3044,2986,2913,2837,2768,2716,2686,2689,2717,2738,2725,2697,
-2687,2686,2647,2560,2475,2445,2454,2454,2426,2391,2363,2337,2309,2289,2275,2253,2217,2176,2135,2092,2049,
-2018,2003,1995,1987,1980,1976,1970,1954,1930,1903,1879,1866,1863,1853,1816,1761,1722,1723,1747,1767,1774,
-1773,1762,1735,1712,1723,1759,1777,1744,1678,1622,1596,1598,1617,1644,1662,1657,1637,1623,1621,1616,1598,
-1580,1577,1582,1579,1564,1547,1536,1528,1522,1519,1518,1518,1516,1514,1513,1510,1506,1505,1509,1512,1509,
-1499,1485,1468,1451,1440,1441,1452,1463,1469,1469,1469,1469,1469,1471,1475,1484,1495,1503,1508,1511,1511,
-1504,1486,1465,1454,1455,1459,1460,1459,1457,1454,1451,1449,1450,1446,1437,1429,1428,1429,1426,1419,1412,
-1402,1384,1357,1325,1297,1274,1255,1240,1224,1205,1185,1167,1149,1128,1105,1082,1060,1033,1003,976,956,
-939,918,890,860,832,806,783,760,734,705,674,645,617,589,560,531,502,474,448,422,394,
-364,335,305,271,234,198,166,135,102,65,29,-6,-40,-76,-115,-157,-200,-240,-276,-307,-336,
--364,-395,-428,-460,-489,-516,-545,-579,-615,-649,-677,-695,-705,-715,-734,-764,-797,-829,-860,-892,-923,
--951,-980,-1011,-1042,-1070,-1094,-1120,-1148,-1176,-1204,-1235,-1269,-1303,-1334,-1362,-1389,-1413,-1435,-1459,-1488,-1520,
--1548,-1575,-1602,-1630,-1656,-1679,-1697,-1710,-1721,-1734,-1751,-1768,-1784,-1801,-1822,-1844,-1861,-1873,-1888,-1906,-1922,
--1932,-1940,-1952,-1968,-1982,-1993,-2003,-2012,-2018,-2022,-2026,-2033,-2038,-2040,-2040,-2039,-2037,-2031,-2022,-2015,-2012,
--2012,-2010,-2003,-1993,-1979,-1965,-1950,-1936,-1926,-1917,-1907,-1896,-1885,-1873,-1860,-1847,-1835,-1826,-1816,-1805,-1794,
--1787,-1780,-1771,-1761,-1750,-1739,-1726,-1713,-1701,-1691,-1683,-1676,-1667,-1656,-1646,-1639,-1635,-1629,-1622,-1614,-1606,
--1596,-1585,-1578,-1576,-1572,-1563,-1553,-1547,-1541,-1531,-1518,-1509,-1504,-1496,-1485,-1475,-1465,-1454,-1444,-1437,-1432,
--1424,-1414,-1406,-1401,-1393,-1383,-1373,-1364,-1355,-1345,-1337,-1331,-1322,-1309,-1296,-1285,-1274,-1263,-1254,-1245,-1233,
--1216,-1200,-1185,-1168,-1146,-1125,-1106,-1087,-1064,-1042,-1023,-997,-958,-917,-886,-867,-848,-821,-788,-755,-723,
--692,-664,-636,-604,-567,-531,-500,-469,-433,-389,-345,-303,-258,-205,-150,-101,-54,1,61,114,162,
-218,284,340,381,427,497,560,566,518,481,529,676,868,1030,1120,1167,1254,1445,1727,2036,2329,
-2574,2690,2559,2167,1684,1343,1229,1249,1284,1320,1399,1519,1630,1707,1773,1851,1931,1986,2002,1990,1969,
-1956,1947,1928,1891,1846,1807,1773,1733,1688,1651,1630,1615,1596,1577,1563,1549,1518,1461,1382,1291,1197,
-1106,1021,946,882,828,782,741,699,643,565,467,357,244,135,34,-51,-117,-168,-218,-279,-359,
--451,-539,-614,-677,-740,-811,-885,-949,-999,-1047,-1100,-1162,-1233,-1314,-1398,-1469,-1515,-1543,-1564,-1580,-1583,
--1574,-1562,-1558,-1562,-1580,-1621,-1686,-1758,-1822,-1878,-1933,-1980,-2008,-2015,-2014,-2014,-2010,-2000,-1993,-2006,-2046,
--2100,-2149,-2177,-2187,-2197,-2217,-2241,-2260,-2282,-2315,-2358,-2396,-2431,-2476,-2533,-2585,-2620,-2639,-2640,-2621,-2588,
--2558,-2539,-2518,-2504,-2532,-2619,-2722,-2777,-2764,-2714,-2649,-2562,-2456,-2367,-2326,-2319,-2305,-2259,-2189,-2109,-2032,
--1969,-1916,-1850,-1747,-1620,-1511,-1449,-1421,-1396,-1369,-1368,-1407,-1456,-1463,-1413,-1349,-1322,-1339,-1360,-1351,-1314,
--1266,-1218,-1166,-1108,-1049,-996,-952,-916,-883,-850,-819,-794,-768,-731,-684,-644,-617,-596,-569,-536,-508,
--488,-470,-451,-433,-415,-392,-364,-332,-299,-265,-233,-201,-168,-133,-100,-74,-52,-27,5,44,80,
-111,140,171,204,232,251,266,285,307,328,345,365,393,426,460,494,528,558,586,619,660,
-702,739,776,822,871,909,937,968,1006,1044,1079,1116,1161,1209,1256,1307,1365,1425,1478,1525,1566,
-1599,1621,1640,1666,1698,1728,1757,1787,1817,1852,1894,1936,1964,1974,1977,1985,1991,1986,1971,1960,1957,
-1952,1944,1939,1938,1935,1928,1923,1922,1917,1905,1894,1887,1879,1870,1862,1858,1850,1836,1823,1816,1809,
-1798,1785,1776,1768,1760,1755,1758,1761,1761,1762,1769,1779,1785,1794,1809,1825,1831,1828,1828,1831,1828,
-1819,1819,1820,1834,1842,1827,1797,1770,1754,1742,1719,1684,1644,1607,1571,1534,1495,1461,1439,1425,1401,
-1359,1305,1256,1219,1190,1158,1116,1074,1043,1022,987,919,834,776,774,819,874,907,891,807,663,
-509,410,388,406,419,419,432,469,511,540,550,548,538,518,489,453,404,343,278,214,142,
-43,-83,-226,-374,-516,-640,-735,-812,-893,-983,-1068,-1138,-1203,-1273,-1344,-1411,-1478,-1546,-1595,-1606,-1586,
--1569,-1591,-1658,-1752,-1839,-1897,-1931,-1958,-1980,-1985,-1969,-1948,-1938,-1936,-1936,-1946,-1964,-1971,-1948,-1907,-1865,
--1825,-1780,-1734,-1692,-1643,-1584,-1531,-1480,-1380,-1195,-980,-848,-832,-856,-848,-834,-881,-983,-1084,-1159,-1243,
--1357,-1479,-1575,-1640,-1688,-1730,-1769,-1803,-1824,-1834,-1842,-1851,-1844,-1810,-1769,-1748,-1755,-1783,-1831,-1887,-1901,
--1830,-1701,-1604,-1604,-1688,-1810,-1950,-2109,-2274,-2416,-2525,-2621,-2733,-2864,-2978,-3030,-3017,-3009,-3094,-3285,-3509,
--3684,-3798,-3884,-3956,-4000,-4013,-4014,-4022,-4042,-4074,-4126,-4194,-4266,-4333,-4394,-4446,-4480,-4501,-4519,-4539,-4552,
--4553,-4555,-4573,-4600,-4619,-4625,-4625,-4623,-4615,-4600,-4582,-4572,-4567,-4560,-4545,-4529,-4520,-4525,-4545,-4573,-4602,
--4628,-4650,-4669,-4681,-4679,-4664,-4649,-4654,-4681,-4716,-4745,-4771,-4809,-4866,-4932,-4993,-5040,-5081,-5125,-5175,-5224,
--5269,-5313,-5363,-5419,-5475,-5528,-5584,-5648,-5718,-5789,-5864,-5947,-6035,-6117,-6187,-6250,-6314,-6382,-6449,-6510,-6569,
--6632,-6701,-6768,-6827,-6876,-6922,-6974,-7030,-7084,-7132,-7176,-7224,-7282,-7345,-7406,-7462,-7507,-7545,-7584,-7636,-7701,
--7770,-7836,-7903,-7981,-8071,-8167,-8261,-8354,-8444,-8524,-8590,-8648,-8705,-8764,-8827,-8892,-8952,-8995,-9021,-9041,-9057,
--9062,-9065,-9106,-9216,-9367,-9489,-9542,-9550,-9562,-9593,-9631,-9662,-9691,-9722,-9751,-9774,-9791,-9804,-9810,-9810,-9808,
--9810,-9822,-9841,-9859,-9867,-9858,-9835,-9800,-9752,-9686,-9607,-9530,-9463,-9394,-9301,-9178,-9048,-8946,-8892,-8877,-8879,
--8884,-8883,-8866,-8828,-8770,-8697,-8603,-8485,-8349,-8215,-8090,-7967,-7845,-7730,-7620,-7505,-7383,-7267,-7160,-7044,-6906,
--6763,-6638,-6528,-6416,-6302,-6198,-6105,-6004,-5886,-5766,-5651,-5528,-5384,-5224,-5064,-4912,-4773,-4649,-4533,-4408,-4259,
--4095,-3935,-3789,-3651,-3520,-3390,-3253,-3097,-2940,-2812,-2728,-2654,-2548,-2403,-2268,-2201,-2218,-2273,-2291,-2222,-2062,
--1854,-1657,-1513,-1415,-1313,-1142,-866,-498,-90,285,560,704,745,752,787,867,973,1085,1195,1299,1388,
-1454,1507,1561,1631,1723,1828,1928,2012,2092,2186,2294,2394,2473,2539,2615,2704,2788,2862,2936,3020,3106,
-3180,3242,3300,3360,3428,3508,3603,3698,3781,3854,3929,4009,4081,4141,4205,4283,4361,4418,4448,4470,4515,
-4610,4758,4921,5044,5108,5150,5213,5294,5362,5398,5399,5350,5256,5205,5328,5660,6058,6315,6341,6215,6081,
-6029,6070,6162,6249,6275,6216,6089,5943,5822,5747,5706,5684,5683,5721,5800,5887,5946,5981,6016,6057,6082,
-6079,6063,6054,6046,6011,5923,5781,5624,5519,5517,5607,5732,5838,5911,5957,5980,5995,6019,6045,6051,6048,
-6086,6199,6356,6510,6650,6782,6883,6916,6885,6838,6813,6816,6846,6904,6963,6978,6937,6876,6831,6818,6850,
-6950,7111,7276,7394,7461,7498,7507,7486,7470,7491,7522,7508,7458,7456,7553,7693,7778,7780,7747,7719,7692,
-7650,7602,7572,7568,7592,7644,7712,7775,7814,7833,7846,7860,7875,7890,7903,7910,7911,7923,7955,7995,8017,
-8015,8002,7987,7963,7919,7865,7816,7779,7755,7738,7719,7692,7663,7642,7625,7582,7498,7390,7291,7212,7138,
-7059,6989,6926,6830,6656,6418,6204,6106,6141,6234,6294,6288,6255,6243,6257,6261,6231,6181,6137,6104,6067,
-6012,5948,5884,5824,5763,5696,5627,5562,5505,5452,5392,5318,5240,5173,5127,5095,5063,5022,4967,4898,4826,
-4768,4730,4700,4654,4587,4515,4457,4413,4380,4352,4324,4283,4227,4174,4143,4127,4102,4056,4007,3976,3963,
-3952,3936,3912,3881,3847,3815,3782,3741,3688,3630,3570,3504,3430,3367,3331,3315,3296,3264,3228,3199,3178,
-3155,3119,3062,2982,2895,2818,2758,2717,2699,2695,2686,2661,2648,2671,2702,2679,2591,2499,2462,2470,2474,
-2455,2430,2409,2381,2345,2317,2302,2285,2252,2208,2161,2112,2065,2030,2015,2009,2002,1994,1988,1981,1965,
-1940,1912,1890,1885,1892,1888,1853,1797,1757,1752,1767,1779,1784,1788,1781,1755,1734,1753,1810,1852,1834,
-1764,1681,1618,1587,1591,1623,1659,1667,1648,1628,1625,1628,1621,1609,1604,1604,1594,1572,1550,1539,1539,
-1541,1542,1539,1532,1525,1523,1523,1519,1510,1506,1511,1518,1516,1506,1493,1481,1470,1461,1459,1462,1464,
-1461,1457,1452,1448,1447,1448,1454,1463,1473,1483,1491,1496,1495,1488,1475,1458,1443,1437,1440,1450,1455,
-1448,1434,1424,1424,1429,1425,1410,1395,1394,1403,1411,1411,1407,1399,1382,1354,1322,1294,1273,1257,1241,
-1222,1201,1182,1165,1144,1120,1096,1075,1054,1025,992,963,942,925,902,874,844,817,792,769,746,
-721,692,660,627,595,564,533,503,476,452,428,403,375,346,319,292,262,227,191,156,123,
-90,56,22,-8,-38,-70,-106,-144,-184,-223,-258,-289,-317,-344,-375,-411,-446,-479,-509,-539,-571,
--607,-645,-681,-705,-717,-724,-739,-764,-795,-823,-852,-883,-914,-942,-968,-999,-1033,-1063,-1087,-1109,-1133,
--1158,-1183,-1209,-1239,-1271,-1303,-1335,-1365,-1391,-1415,-1442,-1472,-1503,-1529,-1553,-1577,-1602,-1626,-1650,-1672,-1687,
--1698,-1707,-1720,-1736,-1751,-1768,-1787,-1806,-1820,-1830,-1842,-1859,-1875,-1886,-1897,-1911,-1927,-1940,-1952,-1965,-1976,
--1983,-1984,-1985,-1989,-1994,-1997,-1997,-1997,-1997,-1994,-1988,-1980,-1977,-1976,-1974,-1968,-1957,-1946,-1932,-1918,-1905,
--1894,-1886,-1875,-1863,-1851,-1839,-1826,-1814,-1804,-1796,-1785,-1771,-1760,-1753,-1746,-1738,-1730,-1723,-1711,-1696,-1682,
--1673,-1665,-1658,-1652,-1644,-1633,-1620,-1612,-1610,-1608,-1600,-1591,-1583,-1576,-1568,-1561,-1557,-1554,-1546,-1536,-1530,
--1526,-1519,-1509,-1501,-1495,-1488,-1477,-1469,-1462,-1454,-1444,-1436,-1430,-1425,-1417,-1410,-1404,-1398,-1392,-1385,-1377,
--1366,-1354,-1346,-1341,-1334,-1325,-1314,-1304,-1293,-1282,-1273,-1262,-1249,-1233,-1219,-1205,-1186,-1166,-1148,-1132,-1114,
--1091,-1068,-1047,-1023,-989,-950,-914,-885,-861,-834,-804,-773,-745,-719,-692,-662,-629,-596,-562,-530,-495,
--455,-411,-367,-324,-279,-225,-170,-121,-75,-19,40,92,135,185,246,302,346,402,475,523,499,
-427,388,436,555,695,814,888,945,1071,1343,1725,2083,2309,2401,2380,2209,1865,1453,1163,1085,1139,
-1205,1258,1342,1466,1586,1675,1748,1828,1910,1972,2004,2012,2007,1996,1978,1948,1910,1878,1857,1840,1811,
-1772,1731,1695,1663,1636,1620,1610,1592,1552,1486,1397,1294,1190,1097,1017,949,892,848,814,778,730,
-665,583,487,381,273,165,61,-31,-106,-165,-221,-283,-358,-442,-527,-603,-669,-733,-799,-865,-923,
--976,-1032,-1093,-1155,-1218,-1291,-1372,-1445,-1499,-1536,-1563,-1570,-1546,-1501,-1470,-1476,-1516,-1578,-1653,-1725,-1773,
--1791,-1800,-1824,-1860,-1887,-1901,-1913,-1927,-1932,-1929,-1939,-1984,-2056,-2129,-2177,-2192,-2186,-2181,-2191,-2214,-2241,
--2271,-2312,-2360,-2402,-2434,-2470,-2520,-2574,-2615,-2638,-2641,-2627,-2608,-2596,-2590,-2573,-2553,-2565,-2631,-2713,-2750,
--2725,-2671,-2616,-2548,-2459,-2370,-2316,-2300,-2298,-2287,-2258,-2204,-2128,-2043,-1959,-1864,-1745,-1611,-1499,-1431,-1390,
--1341,-1274,-1221,-1217,-1258,-1298,-1299,-1264,-1232,-1225,-1235,-1233,-1210,-1174,-1135,-1094,-1052,-1010,-972,-938,-908,
--882,-855,-827,-799,-770,-732,-686,-643,-613,-593,-571,-543,-513,-490,-472,-457,-442,-424,-398,-368,-337,
--305,-275,-249,-227,-206,-180,-149,-120,-96,-72,-43,-8,28,60,87,113,141,166,182,194,211,
-234,258,280,304,335,369,400,430,460,491,521,558,604,650,689,728,777,831,875,907,936,
-969,1003,1036,1077,1127,1180,1230,1279,1329,1379,1427,1475,1520,1556,1580,1602,1632,1668,1704,1739,1772,
-1800,1829,1868,1913,1949,1964,1971,1980,1985,1974,1954,1942,1941,1939,1932,1927,1924,1918,1909,1905,1906,
-1905,1896,1888,1885,1880,1870,1861,1857,1852,1839,1824,1815,1808,1796,1784,1775,1769,1762,1757,1758,1762,
-1765,1768,1775,1782,1787,1792,1803,1814,1819,1821,1826,1831,1827,1819,1821,1822,1835,1840,1823,1791,1764,
-1746,1723,1686,1637,1589,1548,1512,1475,1439,1408,1383,1358,1327,1288,1244,1202,1165,1132,1097,1058,1020,
-991,966,926,856,774,715,699,718,756,800,827,801,704,570,466,428,429,422,394,371,376,
-399,424,447,473,495,497,475,435,383,323,266,214,149,46,-92,-243,-388,-524,-648,-750,-830,
--907,-992,-1073,-1139,-1194,-1252,-1313,-1371,-1425,-1477,-1516,-1528,-1512,-1492,-1496,-1547,-1641,-1748,-1830,-1879,-1912,
--1942,-1955,-1940,-1912,-1894,-1893,-1901,-1917,-1937,-1939,-1914,-1873,-1838,-1805,-1763,-1717,-1679,-1641,-1598,-1556,-1505,
--1395,-1199,-997,-908,-940,-976,-932,-871,-898,-1014,-1133,-1208,-1276,-1373,-1482,-1574,-1643,-1701,-1750,-1791,-1827,
--1854,-1862,-1857,-1851,-1841,-1820,-1794,-1775,-1764,-1759,-1779,-1833,-1879,-1845,-1725,-1607,-1591,-1684,-1821,-1950,-2075,
--2215,-2364,-2498,-2612,-2728,-2861,-2986,-3059,-3068,-3071,-3146,-3309,-3503,-3663,-3776,-3863,-3932,-3973,-3988,-3995,-4011,
--4036,-4074,-4125,-4189,-4255,-4322,-4387,-4440,-4473,-4492,-4509,-4524,-4526,-4518,-4520,-4546,-4580,-4600,-4604,-4601,-4596,
--4584,-4566,-4550,-4542,-4537,-4527,-4512,-4496,-4486,-4485,-4495,-4518,-4548,-4577,-4602,-4622,-4632,-4628,-4612,-4601,-4611,
--4638,-4667,-4694,-4726,-4774,-4834,-4893,-4943,-4987,-5029,-5072,-5119,-5170,-5219,-5264,-5310,-5361,-5419,-5478,-5535,-5591,
--5648,-5711,-5787,-5878,-5972,-6056,-6127,-6192,-6258,-6325,-6387,-6445,-6506,-6572,-6641,-6707,-6766,-6817,-6868,-6926,-6991,
--7053,-7103,-7144,-7187,-7238,-7295,-7352,-7405,-7450,-7488,-7531,-7586,-7651,-7713,-7770,-7832,-7911,-8003,-8101,-8199,-8294,
--8379,-8452,-8518,-8588,-8660,-8727,-8784,-8836,-8881,-8916,-8947,-8981,-9008,-9015,-9019,-9071,-9195,-9346,-9449,-9483,-9488,
--9511,-9551,-9587,-9611,-9632,-9656,-9679,-9700,-9720,-9733,-9734,-9726,-9721,-9726,-9739,-9758,-9779,-9793,-9790,-9770,-9739,
--9701,-9651,-9585,-9513,-9446,-9376,-9277,-9140,-8990,-8874,-8824,-8832,-8862,-8887,-8892,-8868,-8817,-8748,-8668,-8573,-8454,
--8317,-8184,-8063,-7947,-7832,-7725,-7628,-7527,-7411,-7289,-7168,-7039,-6895,-6747,-6617,-6504,-6398,-6299,-6213,-6130,-6027,
--5903,-5780,-5669,-5551,-5404,-5235,-5068,-4916,-4780,-4657,-4540,-4411,-4260,-4097,-3946,-3816,-3697,-3578,-3449,-3299,-3130,
--2963,-2834,-2748,-2667,-2546,-2382,-2228,-2144,-2152,-2217,-2274,-2261,-2146,-1943,-1707,-1503,-1367,-1278,-1169,-976,-678,
--305,82,416,644,760,803,836,901,999,1108,1208,1289,1356,1418,1480,1548,1627,1723,1828,1927,2010,
-2088,2177,2276,2367,2440,2506,2580,2662,2740,2811,2886,2972,3061,3139,3204,3264,3325,3396,3478,3571,3665,
-3754,3837,3917,3992,4060,4126,4195,4261,4313,4349,4383,4434,4511,4623,4764,4905,5010,5070,5117,5181,5255,
-5323,5375,5402,5370,5276,5208,5304,5604,5974,6209,6218,6071,5920,5876,5961,6122,6265,6314,6256,6136,6012,
-5916,5846,5786,5728,5693,5712,5787,5877,5937,5961,5976,5992,5999,5997,6004,6023,6021,5971,5878,5782,5725,
-5731,5793,5875,5934,5961,5971,5975,5972,5973,5990,6005,5974,5902,5858,5904,6027,6177,6345,6540,6729,6841,
-6854,6820,6805,6826,6867,6911,6935,6918,6866,6817,6803,6832,6912,7060,7270,7490,7670,7797,7868,7869,7807,
-7737,7709,7697,7642,7556,7529,7607,7723,7783,7774,7754,7757,7763,7748,7725,7710,7704,7702,7717,7750,7783,
-7797,7802,7818,7847,7872,7881,7884,7891,7903,7919,7940,7964,7982,7987,7986,7987,7984,7971,7944,7908,7870,
-7838,7816,7797,7770,7736,7709,7692,7668,7620,7550,7470,7376,7255,7122,7013,6941,6865,6730,6528,6324,6197,
-6189,6265,6348,6374,6341,6299,6288,6292,6274,6224,6170,6134,6104,6057,5988,5918,5857,5803,5745,5681,5615,
-5556,5502,5445,5377,5304,5239,5192,5156,5117,5071,5020,4965,4906,4852,4810,4770,4712,4629,4541,4476,4440,
-4415,4388,4354,4313,4267,4227,4201,4176,4136,4084,4041,4018,4002,3977,3948,3925,3904,3879,3849,3818,3782,
-3732,3670,3603,3534,3466,3407,3364,3335,3307,3276,3245,3218,3196,3179,3160,3121,3048,2955,2867,2802,2757,
-2726,2702,2671,2632,2609,2624,2654,2645,2586,2522,2500,2511,2514,2499,2481,2462,2431,2386,2348,2325,2302,
-2269,2228,2184,2135,2083,2041,2021,2016,2011,2003,1997,1989,1974,1951,1922,1895,1883,1887,1891,1878,1846,
-1817,1804,1800,1794,1794,1802,1799,1773,1745,1753,1801,1846,1848,1803,1735,1666,1611,1588,1605,1640,1658,
-1649,1636,1637,1645,1643,1629,1618,1611,1602,1584,1567,1561,1567,1578,1582,1574,1560,1549,1547,1547,1539,
-1524,1512,1512,1517,1517,1512,1506,1500,1493,1485,1476,1466,1456,1448,1444,1441,1437,1434,1435,1441,1447,
-1453,1463,1472,1475,1471,1466,1464,1458,1444,1432,1432,1444,1450,1438,1414,1397,1396,1401,1395,1377,1360,
-1356,1366,1378,1385,1386,1381,1367,1344,1316,1292,1273,1257,1240,1220,1201,1183,1164,1142,1116,1092,1070,
-1047,1018,985,955,931,910,885,858,831,804,777,752,731,709,683,650,614,577,543,510,481,
-456,433,410,385,357,329,303,278,251,220,186,151,118,86,54,23,-6,-35,-65,-98,-134,
--171,-209,-245,-277,-305,-333,-364,-400,-438,-473,-505,-535,-565,-599,-639,-680,-712,-730,-740,-753,-775,
--802,-828,-855,-885,-915,-940,-964,-992,-1026,-1058,-1083,-1104,-1124,-1145,-1166,-1187,-1211,-1239,-1273,-1309,-1342,
--1369,-1394,-1421,-1451,-1481,-1508,-1531,-1552,-1573,-1594,-1619,-1644,-1664,-1676,-1683,-1693,-1706,-1721,-1736,-1753,-1769,
--1781,-1790,-1801,-1815,-1830,-1843,-1855,-1869,-1884,-1896,-1908,-1922,-1936,-1944,-1945,-1944,-1947,-1953,-1957,-1957,-1957,
--1956,-1955,-1951,-1945,-1942,-1940,-1937,-1930,-1921,-1911,-1900,-1887,-1874,-1863,-1853,-1841,-1828,-1816,-1805,-1794,-1783,
--1775,-1766,-1754,-1741,-1730,-1720,-1711,-1702,-1698,-1693,-1682,-1667,-1654,-1647,-1641,-1634,-1628,-1622,-1613,-1599,-1589,
--1586,-1584,-1576,-1566,-1559,-1555,-1549,-1542,-1536,-1532,-1526,-1517,-1512,-1509,-1504,-1497,-1491,-1486,-1478,-1468,-1459,
--1455,-1450,-1442,-1434,-1428,-1424,-1419,-1414,-1407,-1400,-1395,-1390,-1385,-1376,-1365,-1357,-1350,-1344,-1337,-1328,-1320,
--1310,-1301,-1291,-1279,-1265,-1251,-1238,-1223,-1203,-1182,-1165,-1152,-1136,-1115,-1092,-1068,-1044,-1017,-986,-953,-921,
--892,-865,-837,-808,-782,-758,-731,-697,-663,-631,-598,-559,-517,-474,-431,-387,-344,-300,-250,-196,-145,
--98,-46,10,61,103,153,214,271,320,377,440,460,405,315,274,314,398,496,604,719,840,
-1018,1322,1723,2066,2223,2206,2103,1923,1623,1255,979,908,992,1111,1206,1301,1417,1534,1633,1721,1807,
-1888,1953,2001,2034,2049,2042,2016,1979,1944,1925,1921,1918,1902,1870,1826,1778,1733,1700,1681,1664,1635,
-1589,1522,1431,1319,1208,1114,1037,967,906,863,835,801,748,679,600,512,414,308,200,93,-8,
--97,-172,-239,-302,-368,-442,-522,-600,-668,-722,-771,-820,-873,-932,-1000,-1071,-1133,-1188,-1252,-1328,-1404,
--1465,-1507,-1530,-1521,-1473,-1412,-1383,-1411,-1488,-1589,-1697,-1786,-1827,-1816,-1786,-1774,-1787,-1803,-1815,-1832,-1854,
--1871,-1888,-1931,-2011,-2110,-2189,-2227,-2227,-2206,-2188,-2191,-2217,-2252,-2289,-2331,-2380,-2422,-2448,-2467,-2495,-2534,
--2572,-2597,-2606,-2603,-2604,-2619,-2643,-2651,-2639,-2633,-2662,-2709,-2730,-2705,-2655,-2599,-2533,-2446,-2352,-2276,-2231,
--2215,-2215,-2213,-2187,-2124,-2036,-1938,-1829,-1706,-1581,-1481,-1416,-1369,-1308,-1221,-1130,-1075,-1078,-1116,-1144,-1135,
--1102,-1077,-1074,-1081,-1079,-1063,-1041,-1022,-1004,-980,-945,-907,-881,-872,-866,-844,-806,-765,-727,-693,-659,
--628,-603,-583,-563,-540,-516,-494,-475,-458,-436,-406,-373,-342,-316,-294,-278,-266,-252,-231,-200,-167,
--135,-108,-80,-49,-15,17,45,71,97,121,140,156,176,203,233,261,290,322,354,383,411,
-443,475,505,540,582,626,665,702,748,800,846,884,921,961,1000,1038,1081,1131,1183,1228,1268,
-1305,1341,1379,1423,1470,1512,1544,1577,1615,1655,1694,1729,1760,1782,1801,1832,1876,1917,1941,1955,1970,
-1978,1965,1940,1923,1922,1922,1918,1915,1914,1909,1900,1896,1898,1896,1887,1881,1880,1877,1867,1856,1851,
-1846,1834,1821,1813,1806,1794,1781,1773,1770,1765,1760,1759,1761,1764,1767,1774,1782,1788,1795,1805,1815,
-1821,1827,1835,1839,1832,1821,1825,1820,1827,1826,1806,1774,1745,1718,1682,1630,1574,1528,1495,1463,1428,
-1390,1355,1321,1286,1249,1215,1182,1149,1114,1079,1045,1011,977,948,919,877,812,736,670,630,618,
-632,674,728,757,727,644,555,497,467,432,379,328,303,303,320,355,407,457,477,458,413,
-356,298,247,203,141,34,-113,-267,-401,-525,-645,-752,-836,-908,-984,-1058,-1114,-1156,-1201,-1256,-1312,
--1361,-1402,-1433,-1450,-1450,-1443,-1445,-1480,-1561,-1669,-1763,-1824,-1862,-1894,-1910,-1898,-1872,-1857,-1861,-1873,-1886,
--1895,-1889,-1863,-1832,-1809,-1784,-1742,-1695,-1662,-1638,-1609,-1574,-1523,-1409,-1215,-1031,-975,-1037,-1071,-990,-888,
--906,-1047,-1192,-1273,-1329,-1409,-1506,-1587,-1655,-1720,-1780,-1829,-1871,-1907,-1922,-1916,-1904,-1896,-1885,-1867,-1846,
--1822,-1799,-1803,-1848,-1895,-1870,-1758,-1648,-1641,-1743,-1871,-1963,-2038,-2144,-2295,-2456,-2600,-2733,-2872,-3005,-3097,
--3132,-3147,-3204,-3328,-3489,-3640,-3762,-3853,-3916,-3950,-3970,-3990,-4015,-4046,-4086,-4140,-4202,-4265,-4330,-4392,-4440,
--4464,-4475,-4487,-4496,-4490,-4478,-4484,-4515,-4545,-4554,-4548,-4544,-4544,-4538,-4527,-4519,-4517,-4510,-4493,-4474,-4459,
--4450,-4447,-4455,-4476,-4504,-4531,-4552,-4568,-4577,-4572,-4558,-4552,-4565,-4585,-4596,-4603,-4628,-4679,-4743,-4801,-4855,
--4914,-4973,-5024,-5065,-5108,-5158,-5210,-5258,-5306,-5362,-5425,-5486,-5540,-5589,-5645,-5719,-5810,-5902,-5983,-6056,-6128,
--6200,-6264,-6320,-6379,-6448,-6519,-6586,-6645,-6703,-6761,-6822,-6887,-6954,-7013,-7059,-7098,-7140,-7185,-7234,-7285,-7338,
--7388,-7434,-7481,-7536,-7594,-7647,-7697,-7759,-7842,-7937,-8035,-8131,-8223,-8304,-8376,-8450,-8534,-8618,-8685,-8737,-8780,
--8817,-8847,-8879,-8919,-8952,-8959,-8966,-9030,-9167,-9316,-9401,-9418,-9422,-9453,-9497,-9529,-9548,-9568,-9591,-9611,-9632,
--9654,-9668,-9664,-9652,-9648,-9660,-9679,-9699,-9719,-9730,-9724,-9701,-9673,-9646,-9612,-9559,-9493,-9426,-9353,-9255,-9118,
--8966,-8852,-8811,-8831,-8871,-8892,-8881,-8839,-8774,-8697,-8616,-8525,-8411,-8278,-8149,-8034,-7926,-7815,-7710,-7617,-7523,
--7416,-7294,-7166,-7027,-6873,-6720,-6589,-6482,-6386,-6298,-6219,-6141,-6042,-5923,-5805,-5697,-5580,-5431,-5259,-5088,-4932,
--4792,-4666,-4547,-4417,-4268,-4112,-3973,-3862,-3763,-3656,-3526,-3365,-3183,-3009,-2878,-2788,-2696,-2559,-2383,-2222,-2128,
--2115,-2153,-2199,-2212,-2157,-2012,-1794,-1554,-1355,-1221,-1118,-983,-771,-477,-126,229,527,724,819,862,911,
-993,1094,1186,1258,1318,1380,1446,1517,1600,1700,1811,1914,2000,2079,2163,2250,2328,2396,2466,2543,2620,
-2693,2765,2844,2929,3013,3089,3158,3224,3293,3370,3453,3538,3624,3714,3807,3890,3957,4017,4088,4166,4227,
-4257,4275,4316,4396,4506,4630,4757,4873,4963,5029,5092,5161,5225,5275,5314,5334,5305,5223,5171,5261,5521,
-5838,6052,6084,5977,5846,5800,5894,6089,6275,6348,6295,6183,6092,6043,6009,5949,5854,5760,5719,5754,5829,
-5892,5923,5932,5935,5938,5960,6011,6062,6062,5996,5911,5865,5881,5942,6018,6074,6085,6053,6008,5974,5961,
-5979,6028,6064,6022,5894,5756,5695,5723,5810,5966,6212,6501,6722,6809,6808,6808,6847,6903,6944,6952,6930,
-6900,6894,6929,6997,7101,7260,7478,7718,7934,8094,8175,8151,8038,7909,7830,7781,7702,7597,7542,7579,7650,
-7677,7661,7655,7682,7714,7733,7752,7777,7790,7777,7761,7766,7780,7778,7766,7771,7800,7829,7840,7841,7851,
-7873,7895,7914,7932,7950,7968,7985,8002,8015,8022,8019,8003,7973,7933,7893,7858,7822,7784,7752,7731,7709,
-7674,7629,7577,7501,7375,7208,7041,6909,6802,6686,6547,6398,6277,6226,6264,6358,6429,6426,6372,6331,6326,
-6322,6284,6226,6180,6147,6103,6039,5967,5904,5849,5794,5736,5677,5617,5558,5498,5433,5365,5306,5263,5230,
-5190,5141,5092,5047,5000,4948,4894,4835,4758,4663,4575,4521,4497,4479,4446,4401,4355,4315,4284,4257,4223,
-4176,4126,4093,4075,4051,4009,3965,3936,3919,3897,3866,3835,3804,3760,3696,3619,3545,3483,3435,3396,3360,
-3325,3295,3265,3231,3194,3170,3160,3140,3083,2996,2910,2846,2801,2768,2743,2714,2671,2625,2600,2599,2597,
-2575,2551,2549,2557,2553,2535,2517,2500,2468,2421,2377,2344,2312,2274,2236,2201,2158,2105,2058,2033,2027,
-2022,2013,2003,1993,1981,1962,1934,1897,1862,1841,1841,1851,1859,1857,1848,1834,1820,1818,1823,1814,1783,
-1747,1738,1759,1789,1803,1798,1773,1725,1663,1616,1607,1625,1642,1641,1636,1640,1649,1647,1632,1615,1607,
-1605,1601,1596,1596,1607,1621,1626,1617,1600,1589,1588,1585,1571,1548,1527,1517,1517,1519,1521,1520,1516,
-1509,1499,1485,1466,1446,1435,1433,1434,1431,1427,1426,1427,1426,1428,1436,1446,1449,1446,1448,1459,1465,
-1453,1434,1427,1433,1438,1426,1403,1384,1376,1372,1362,1346,1331,1325,1329,1339,1350,1357,1355,1344,1325,
-1305,1286,1269,1252,1235,1218,1201,1183,1163,1139,1115,1091,1067,1041,1011,980,950,923,896,870,843,
-816,788,761,737,718,699,675,644,607,569,532,499,470,443,417,391,365,339,314,290,268,
-245,216,183,149,118,89,61,30,-1,-33,-66,-99,-133,-169,-205,-242,-275,-305,-333,-364,-400,
--437,-471,-501,-529,-557,-589,-627,-668,-706,-733,-751,-766,-786,-811,-837,-864,-891,-917,-939,-959,-983,
--1014,-1046,-1072,-1092,-1111,-1131,-1150,-1168,-1187,-1212,-1245,-1282,-1316,-1344,-1368,-1392,-1420,-1450,-1478,-1504,-1525,
--1544,-1562,-1584,-1609,-1631,-1646,-1654,-1663,-1675,-1690,-1705,-1721,-1735,-1747,-1756,-1767,-1780,-1793,-1805,-1817,-1830,
--1843,-1855,-1867,-1880,-1893,-1902,-1905,-1905,-1907,-1913,-1919,-1921,-1919,-1916,-1914,-1912,-1908,-1904,-1901,-1896,-1888,
--1880,-1873,-1866,-1855,-1843,-1831,-1819,-1805,-1793,-1782,-1774,-1764,-1755,-1746,-1736,-1725,-1714,-1703,-1692,-1679,-1669,
--1666,-1664,-1656,-1642,-1631,-1625,-1618,-1608,-1600,-1597,-1591,-1578,-1566,-1560,-1557,-1550,-1542,-1537,-1535,-1530,-1521,
--1515,-1511,-1505,-1499,-1495,-1492,-1488,-1483,-1480,-1479,-1473,-1462,-1453,-1448,-1445,-1439,-1431,-1425,-1422,-1420,-1416,
--1410,-1403,-1397,-1393,-1390,-1385,-1378,-1371,-1364,-1357,-1350,-1342,-1334,-1325,-1316,-1306,-1294,-1281,-1268,-1255,-1239,
--1219,-1199,-1182,-1167,-1152,-1135,-1115,-1091,-1065,-1041,-1017,-988,-955,-925,-899,-870,-840,-813,-790,-763,-728,
--693,-662,-628,-585,-538,-494,-452,-405,-360,-317,-273,-222,-171,-124,-76,-23,27,76,132,197,255,
-298,341,382,378,304,210,176,216,285,364,483,652,842,1055,1338,1679,1957,2058,2010,1908,1761,
-1503,1153,868,784,882,1039,1166,1265,1361,1464,1571,1679,1779,1862,1930,1993,2048,2085,2091,2068,2029,
-1996,1983,1987,1990,1979,1952,1912,1864,1817,1781,1751,1716,1672,1623,1565,1482,1371,1257,1164,1085,1006,
-931,879,849,817,763,695,624,546,454,349,238,125,15,-86,-176,-253,-321,-385,-455,-533,-609,
--667,-702,-730,-767,-820,-886,-959,-1031,-1095,-1149,-1208,-1276,-1346,-1403,-1440,-1450,-1424,-1367,-1314,-1312,-1377,
--1487,-1612,-1737,-1841,-1892,-1879,-1833,-1799,-1789,-1791,-1794,-1804,-1822,-1844,-1879,-1947,-2049,-2156,-2228,-2256,-2249,
--2226,-2207,-2211,-2241,-2281,-2318,-2355,-2402,-2447,-2473,-2481,-2489,-2510,-2536,-2556,-2566,-2573,-2590,-2626,-2675,-2711,
--2715,-2704,-2704,-2723,-2734,-2718,-2676,-2617,-2541,-2445,-2340,-2241,-2166,-2124,-2114,-2117,-2101,-2052,-1974,-1879,-1772,
--1655,-1546,-1464,-1408,-1360,-1298,-1213,-1113,-1024,-977,-980,-1004,-1011,-991,-969,-970,-988,-1001,-993,-974,-960,
--948,-923,-878,-830,-812,-830,-852,-837,-782,-719,-679,-662,-647,-618,-586,-565,-560,-558,-545,-522,-495,
--470,-443,-409,-372,-340,-317,-302,-294,-288,-277,-257,-228,-194,-161,-130,-104,-79,-53,-24,2,26,
-49,73,97,120,146,180,216,250,284,316,346,375,407,445,482,514,545,584,626,662,696,
-734,777,818,858,902,951,998,1042,1088,1138,1186,1230,1269,1306,1339,1374,1415,1461,1503,1538,1574,
-1613,1650,1684,1715,1744,1763,1779,1808,1854,1898,1924,1940,1955,1963,1951,1926,1908,1904,1904,1902,1903,
-1906,1905,1900,1897,1897,1890,1877,1868,1865,1862,1853,1844,1839,1833,1823,1812,1807,1802,1793,1783,1778,
-1777,1774,1770,1767,1765,1763,1764,1770,1781,1791,1803,1816,1829,1836,1842,1850,1852,1841,1825,1821,1808,
-1801,1789,1764,1730,1697,1663,1620,1567,1517,1481,1454,1424,1384,1340,1297,1259,1220,1183,1152,1124,1094,
-1060,1027,998,968,937,907,878,844,794,728,655,590,544,529,552,609,671,702,681,621,554,
-496,440,375,311,268,251,262,302,366,428,453,431,380,322,267,222,182,122,17,-126,-270,
--390,-499,-613,-720,-804,-872,-940,-1005,-1052,-1083,-1120,-1174,-1233,-1285,-1325,-1356,-1380,-1399,-1415,-1428,-1454,
--1512,-1600,-1687,-1748,-1788,-1820,-1841,-1840,-1828,-1825,-1834,-1844,-1850,-1852,-1843,-1820,-1799,-1788,-1768,-1725,-1677,
--1649,-1634,-1608,-1574,-1528,-1428,-1254,-1088,-1048,-1117,-1141,-1036,-912,-931,-1092,-1256,-1341,-1387,-1456,-1540,-1610,
--1671,-1739,-1809,-1868,-1918,-1961,-1987,-1989,-1985,-1985,-1981,-1962,-1933,-1905,-1885,-1884,-1905,-1920,-1881,-1790,-1721,
--1745,-1845,-1940,-1988,-2023,-2103,-2244,-2414,-2584,-2745,-2902,-3042,-3142,-3191,-3211,-3249,-3335,-3467,-3614,-3748,-3847,
--3906,-3937,-3962,-3993,-4025,-4061,-4107,-4165,-4224,-4278,-4332,-4384,-4421,-4436,-4441,-4452,-4461,-4455,-4447,-4460,-4490,
--4509,-4502,-4485,-4479,-4482,-4483,-4481,-4484,-4488,-4480,-4458,-4437,-4424,-4420,-4421,-4432,-4453,-4476,-4490,-4499,-4508,
--4517,-4516,-4507,-4504,-4513,-4517,-4498,-4468,-4465,-4504,-4568,-4635,-4708,-4799,-4896,-4969,-5011,-5043,-5089,-5148,-5206,
--5258,-5314,-5378,-5441,-5496,-5543,-5598,-5669,-5753,-5835,-5910,-5986,-6067,-6143,-6204,-6256,-6319,-6397,-6472,-6534,-6587,
--6645,-6712,-6780,-6844,-6903,-6952,-6995,-7036,-7081,-7125,-7168,-7216,-7273,-7334,-7389,-7439,-7489,-7538,-7583,-7630,-7694,
--7780,-7874,-7968,-8060,-8150,-8233,-8309,-8392,-8482,-8563,-8623,-8670,-8715,-8755,-8783,-8811,-8849,-8880,-8887,-8901,-8979,
--9127,-9272,-9341,-9346,-9351,-9386,-9431,-9458,-9476,-9499,-9523,-9540,-9558,-9582,-9599,-9598,-9589,-9591,-9611,-9635,-9655,
--9665,-9662,-9642,-9613,-9590,-9578,-9561,-9523,-9464,-9396,-9322,-9225,-9096,-8955,-8852,-8818,-8839,-8869,-8870,-8836,-8777,
--8705,-8629,-8554,-8470,-8364,-8236,-8109,-7996,-7890,-7782,-7678,-7589,-7504,-7406,-7288,-7156,-7007,-6843,-6683,-6551,-6451,
--6366,-6285,-6211,-6139,-6053,-5949,-5839,-5729,-5607,-5459,-5294,-5129,-4974,-4828,-4694,-4570,-4443,-4301,-4154,-4024,-3921,
--3830,-3726,-3594,-3428,-3242,-3069,-2936,-2835,-2726,-2573,-2392,-2233,-2138,-2104,-2101,-2104,-2106,-2095,-2034,-1889,-1666,
--1419,-1212,-1068,-955,-816,-602,-299,56,394,644,784,849,897,967,1056,1142,1217,1286,1354,1417,1477,
-1550,1651,1770,1883,1979,2067,2154,2233,2298,2359,2432,2514,2594,2667,2742,2820,2897,2966,3034,3103,3174,
-3248,3329,3414,3495,3574,3664,3762,3849,3913,3970,4046,4132,4196,4221,4234,4276,4361,4474,4594,4713,4822,
-4912,4988,5060,5126,5175,5203,5216,5206,5157,5085,5059,5154,5374,5635,5837,5924,5895,5803,5745,5817,6021,
-6244,6353,6313,6202,6118,6094,6087,6039,5928,5792,5703,5703,5770,5847,5892,5901,5893,5895,5935,6010,6070,
-6064,6000,5946,5947,5987,6033,6076,6110,6110,6059,5976,5906,5881,5913,5989,6054,6035,5910,5743,5613,5548,
-5549,5657,5913,6269,6585,6755,6805,6824,6866,6916,6948,6958,6966,6999,7072,7172,7273,7373,7503,7687,7908,
-8117,8271,8331,8274,8127,7972,7874,7818,7742,7638,7565,7563,7594,7607,7604,7621,7662,7698,7719,7744,7780,
-7796,7777,7749,7747,7762,7759,7734,7716,7726,7749,7762,7767,7778,7804,7835,7862,7887,7915,7946,7980,8012,
-8036,8050,8056,8054,8037,8003,7964,7930,7900,7869,7834,7799,7756,7703,7652,7611,7557,7455,7293,7102,6918,
-6755,6618,6508,6416,6326,6251,6236,6305,6404,6450,6424,6381,6366,6365,6341,6291,6240,6199,6154,6098,6036,
-5975,5913,5852,5797,5745,5688,5624,5558,5491,5426,5369,5330,5301,5262,5208,5155,5113,5075,5025,4957,4876,
-4784,4692,4623,4591,4581,4560,4514,4455,4400,4356,4322,4291,4256,4215,4175,4147,4127,4096,4046,3995,3962,
-3941,3916,3883,3853,3825,3784,3717,3634,3554,3494,3455,3424,3389,3352,3320,3290,3250,3203,3169,3155,3139,
-3092,3018,2947,2894,2852,2819,2802,2793,2763,2701,2634,2595,2587,2589,2591,2595,2592,2575,2550,2532,2517,
-2491,2450,2407,2368,2326,2280,2241,2208,2171,2122,2078,2053,2044,2035,2019,2002,1987,1974,1961,1939,1901,
-1849,1806,1796,1821,1858,1877,1871,1855,1847,1851,1851,1829,1790,1755,1740,1739,1747,1763,1785,1795,1767,
-1706,1646,1618,1621,1633,1637,1636,1640,1647,1647,1632,1612,1601,1604,1611,1617,1624,1639,1657,1664,1657,
-1646,1640,1639,1631,1610,1583,1558,1540,1532,1533,1537,1535,1524,1512,1502,1489,1468,1441,1424,1422,1427,
-1427,1425,1423,1419,1410,1402,1406,1416,1421,1423,1433,1453,1465,1454,1429,1412,1411,1414,1410,1399,1386,
-1370,1350,1333,1320,1311,1303,1299,1304,1318,1330,1331,1319,1302,1285,1270,1255,1240,1225,1211,1198,1179,
-1157,1135,1115,1093,1067,1037,1007,978,948,917,888,861,834,805,775,749,729,712,693,668,637,
-603,567,531,497,466,437,407,377,349,324,302,281,261,238,209,176,142,113,87,60,30,
--3,-38,-73,-107,-140,-174,-209,-245,-279,-310,-338,-369,-403,-439,-471,-498,-523,-548,-577,-609,-645,
--684,-719,-746,-767,-788,-814,-842,-869,-894,-915,-933,-951,-973,-1000,-1031,-1058,-1079,-1098,-1118,-1138,-1155,
--1172,-1194,-1223,-1258,-1290,-1316,-1337,-1358,-1383,-1413,-1443,-1471,-1494,-1514,-1530,-1548,-1569,-1590,-1607,-1619,-1629,
--1641,-1656,-1672,-1688,-1702,-1715,-1727,-1741,-1754,-1766,-1775,-1785,-1796,-1809,-1822,-1834,-1844,-1853,-1860,-1864,-1866,
--1868,-1874,-1881,-1884,-1883,-1879,-1876,-1873,-1870,-1866,-1862,-1855,-1847,-1839,-1834,-1829,-1821,-1810,-1797,-1785,-1771,
--1759,-1750,-1743,-1734,-1725,-1716,-1708,-1698,-1687,-1676,-1664,-1650,-1639,-1636,-1635,-1629,-1617,-1608,-1603,-1594,-1580,
--1569,-1565,-1562,-1553,-1540,-1532,-1528,-1523,-1517,-1514,-1513,-1509,-1501,-1495,-1491,-1487,-1483,-1481,-1479,-1476,-1472,
--1470,-1471,-1468,-1461,-1453,-1447,-1442,-1437,-1429,-1423,-1420,-1418,-1416,-1413,-1407,-1402,-1398,-1395,-1391,-1388,-1383,
--1377,-1370,-1363,-1356,-1348,-1338,-1328,-1318,-1306,-1293,-1281,-1268,-1253,-1235,-1218,-1202,-1185,-1167,-1152,-1136,-1115,
--1090,-1066,-1043,-1015,-982,-953,-928,-899,-864,-835,-814,-789,-755,-719,-688,-655,-611,-563,-521,-478,-427,
--376,-334,-294,-246,-195,-149,-105,-53,2,56,115,181,236,265,286,305,290,216,129,112,183,
-286,391,533,734,957,1175,1408,1654,1838,1890,1842,1770,1664,1448,1135,870,790,880,1025,1139,1217,
-1292,1383,1493,1614,1726,1817,1894,1970,2045,2102,2128,2118,2086,2053,2038,2041,2044,2032,2008,1975,1936,
-1894,1855,1812,1759,1703,1655,1607,1534,1429,1318,1227,1147,1058,969,907,873,839,787,724,659,588,
-498,392,276,157,37,-74,-173,-261,-340,-414,-488,-562,-624,-658,-667,-677,-712,-769,-833,-894,-954,
--1015,-1076,-1136,-1193,-1247,-1292,-1322,-1327,-1299,-1254,-1233,-1277,-1384,-1519,-1652,-1774,-1878,-1942,-1948,-1915,-1880,
--1860,-1850,-1843,-1842,-1850,-1866,-1901,-1971,-2070,-2165,-2225,-2246,-2243,-2229,-2218,-2228,-2261,-2301,-2333,-2365,-2412,
--2466,-2503,-2512,-2510,-2514,-2524,-2531,-2535,-2545,-2571,-2616,-2674,-2723,-2745,-2743,-2737,-2739,-2743,-2732,-2695,-2634,
--2550,-2448,-2336,-2227,-2136,-2080,-2061,-2058,-2039,-1992,-1922,-1835,-1730,-1618,-1522,-1460,-1419,-1371,-1307,-1227,-1133,
--1032,-947,-907,-909,-922,-921,-918,-934,-965,-985,-971,-934,-897,-866,-829,-780,-739,-741,-787,-827,-810,
--731,-643,-597,-597,-604,-584,-549,-531,-543,-567,-573,-551,-515,-479,-445,-409,-372,-339,-317,-306,-302,
--301,-292,-274,-248,-219,-187,-156,-129,-108,-89,-65,-39,-16,4,27,53,83,114,151,190,228,
-263,295,326,358,396,440,482,516,547,583,623,658,690,723,762,802,843,892,945,996,1042,
-1086,1132,1177,1221,1266,1310,1350,1388,1428,1471,1510,1543,1575,1609,1639,1666,1696,1726,1751,1773,1806,
-1852,1894,1917,1926,1936,1942,1933,1914,1900,1896,1894,1891,1892,1897,1898,1896,1894,1890,1880,1864,1851,
-1844,1839,1833,1829,1828,1823,1812,1802,1798,1796,1792,1786,1785,1785,1784,1781,1777,1771,1764,1762,1769,
-1781,1795,1811,1828,1841,1847,1851,1855,1853,1840,1821,1800,1780,1760,1737,1706,1671,1637,1603,1564,1521,
-1481,1447,1416,1378,1331,1281,1238,1204,1172,1139,1106,1073,1039,1007,980,956,928,897,867,844,824,
-794,744,672,588,512,466,460,496,562,627,656,634,578,513,448,379,311,264,248,260,297,
-349,397,411,384,335,282,234,191,147,87,-7,-128,-245,-341,-435,-541,-647,-731,-797,-863,-926,
--970,-1000,-1037,-1095,-1162,-1222,-1268,-1303,-1334,-1367,-1403,-1432,-1454,-1486,-1539,-1600,-1650,-1688,-1725,-1759,-1780,
--1789,-1796,-1803,-1809,-1816,-1822,-1818,-1800,-1783,-1776,-1759,-1718,-1673,-1651,-1637,-1608,-1570,-1534,-1460,-1314,-1160,
--1118,-1184,-1217,-1125,-1008,-1022,-1173,-1326,-1398,-1433,-1492,-1566,-1625,-1678,-1747,-1823,-1886,-1939,-1986,-2019,-2032,
--2039,-2048,-2044,-2012,-1966,-1933,-1925,-1932,-1934,-1913,-1859,-1798,-1782,-1838,-1929,-1995,-2025,-2054,-2123,-2243,-2399,
--2577,-2763,-2938,-3082,-3179,-3227,-3245,-3267,-3329,-3440,-3585,-3727,-3833,-3896,-3933,-3965,-4000,-4034,-4071,-4122,-4182,
--4234,-4274,-4314,-4356,-4386,-4396,-4400,-4414,-4429,-4432,-4432,-4447,-4471,-4478,-4464,-4448,-4443,-4444,-4442,-4443,-4452,
--4459,-4450,-4428,-4410,-4402,-4399,-4402,-4415,-4435,-4449,-4449,-4445,-4449,-4460,-4465,-4460,-4453,-4449,-4431,-4381,-4318,
--4287,-4311,-4371,-4442,-4529,-4648,-4785,-4895,-4954,-4984,-5022,-5081,-5148,-5211,-5272,-5336,-5398,-5454,-5504,-5560,-5628,
--5703,-5775,-5846,-5925,-6011,-6087,-6144,-6194,-6261,-6344,-6420,-6478,-6529,-6590,-6660,-6727,-6784,-6834,-6879,-6922,-6969,
--7018,-7064,-7106,-7155,-7219,-7289,-7350,-7399,-7444,-7488,-7529,-7576,-7640,-7722,-7811,-7900,-7992,-8085,-8171,-8252,-8337,
--8423,-8492,-8543,-8592,-8646,-8689,-8709,-8726,-8757,-8789,-8803,-8830,-8926,-9083,-9222,-9278,-9275,-9280,-9318,-9359,-9382,
--9399,-9426,-9450,-9464,-9476,-9497,-9519,-9526,-9523,-9531,-9555,-9582,-9596,-9592,-9568,-9532,-9501,-9493,-9501,-9503,-9477,
--9421,-9348,-9266,-9167,-9045,-8919,-8827,-8797,-8813,-8830,-8815,-8769,-8707,-8641,-8574,-8506,-8426,-8323,-8198,-8068,-7952,
--7845,-7742,-7645,-7563,-7486,-7393,-7275,-7138,-6982,-6813,-6648,-6516,-6420,-6345,-6274,-6207,-6145,-6074,-5982,-5875,-5757,
--5629,-5485,-5334,-5185,-5036,-4884,-4737,-4605,-4482,-4353,-4217,-4088,-3977,-3875,-3763,-3624,-3459,-3285,-3124,-2991,-2875,
--2745,-2581,-2401,-2249,-2154,-2104,-2061,-2012,-1976,-1975,-1987,-1943,-1791,-1547,-1288,-1091,-970,-869,-708,-443,-101,
-242,516,696,808,892,972,1048,1119,1191,1269,1348,1409,1456,1515,1610,1732,1851,1955,2054,2151,2232,
-2288,2338,2407,2493,2578,2654,2728,2801,2866,2922,2981,3047,3116,3186,3264,3351,3434,3515,3604,3705,3797,
-3866,3928,4007,4100,4173,4212,4235,4275,4340,4427,4530,4646,4762,4860,4938,5002,5055,5089,5101,5088,5044,
-4972,4907,4911,5018,5205,5415,5606,5742,5785,5732,5664,5704,5897,6142,6287,6271,6165,6075,6049,6050,6010,
-5899,5754,5654,5654,5733,5825,5878,5884,5867,5863,5898,5960,5998,5978,5935,5932,5974,6010,6011,6011,6040,
-6063,6024,5930,5837,5797,5816,5872,5925,5927,5856,5737,5615,5510,5449,5501,5728,6090,6444,6673,6770,6805,
-6830,6849,6860,6883,6942,7054,7208,7368,7493,7578,7666,7804,7993,8185,8325,8371,8313,8188,8068,7999,7958,
-7890,7785,7689,7641,7631,7635,7653,7699,7755,7785,7784,7777,7780,7777,7751,7718,7704,7708,7700,7668,7632,
-7620,7630,7646,7660,7682,7715,7755,7794,7831,7868,7909,7953,7997,8032,8054,8063,8065,8057,8038,8016,8001,
-7989,7968,7933,7888,7831,7763,7699,7649,7595,7504,7361,7185,6993,6790,6598,6463,6398,6358,6296,6235,6238,
-6312,6396,6431,6424,6411,6404,6388,6356,6316,6270,6218,6163,6110,6053,5986,5918,5861,5814,5759,5693,5622,
-5554,5489,5431,5390,5359,5316,5255,5192,5148,5116,5073,5003,4912,4818,4741,4695,4681,4670,4635,4572,4501,
-4441,4393,4352,4318,4290,4262,4232,4201,4171,4133,4086,4039,4002,3975,3948,3919,3890,3860,3815,3750,3668,
-3588,3526,3487,3461,3432,3395,3357,3320,3278,3231,3194,3171,3143,3093,3031,2979,2939,2898,2863,2857,2872,
-2864,2801,2710,2642,2620,2624,2632,2633,2623,2596,2564,2543,2532,2513,2479,2439,2398,2352,2298,2249,2209,
-2171,2129,2092,2070,2056,2039,2015,1992,1973,1958,1945,1930,1903,1858,1813,1803,1834,1878,1893,1872,1848,
-1850,1867,1866,1834,1795,1775,1769,1758,1745,1753,1781,1797,1770,1707,1647,1621,1624,1637,1645,1647,1650,
-1656,1658,1647,1625,1608,1605,1614,1623,1634,1654,1677,1690,1689,1685,1686,1685,1672,1650,1625,1600,1576,
-1558,1553,1556,1552,1533,1511,1498,1488,1467,1437,1413,1405,1409,1416,1425,1432,1429,1411,1392,1384,1388,
-1395,1400,1411,1430,1441,1432,1410,1390,1382,1382,1387,1391,1386,1364,1333,1309,1300,1297,1287,1274,1273,
-1287,1303,1307,1296,1278,1260,1246,1235,1223,1211,1200,1187,1168,1145,1125,1108,1089,1063,1032,1003,976,
-948,917,889,862,833,798,765,741,725,709,687,660,630,600,566,530,495,463,434,404,372,
-342,316,294,273,252,227,198,163,130,100,73,46,16,-15,-49,-83,-116,-149,-181,-215,-251,
--285,-315,-343,-372,-406,-441,-473,-499,-520,-543,-566,-592,-620,-654,-692,-728,-755,-779,-806,-839,-869,
--891,-908,-924,-942,-964,-991,-1020,-1048,-1072,-1095,-1117,-1138,-1156,-1171,-1190,-1214,-1242,-1269,-1290,-1308,-1327,
--1351,-1379,-1409,-1436,-1460,-1481,-1499,-1515,-1531,-1549,-1567,-1581,-1592,-1604,-1620,-1636,-1652,-1666,-1681,-1697,-1714,
--1730,-1743,-1751,-1757,-1766,-1779,-1795,-1807,-1814,-1818,-1823,-1827,-1829,-1830,-1834,-1841,-1846,-1846,-1843,-1840,-1837,
--1833,-1828,-1823,-1817,-1810,-1802,-1797,-1792,-1785,-1776,-1765,-1754,-1740,-1728,-1718,-1710,-1700,-1691,-1683,-1677,-1669,
--1657,-1646,-1634,-1622,-1611,-1605,-1602,-1595,-1586,-1579,-1574,-1564,-1549,-1537,-1533,-1530,-1522,-1512,-1504,-1499,-1494,
--1489,-1488,-1487,-1483,-1478,-1474,-1472,-1469,-1466,-1465,-1464,-1463,-1460,-1459,-1460,-1459,-1456,-1451,-1447,-1443,-1437,
--1431,-1424,-1420,-1417,-1415,-1413,-1411,-1409,-1406,-1401,-1395,-1391,-1388,-1383,-1377,-1372,-1368,-1360,-1349,-1338,-1327,
--1316,-1304,-1293,-1281,-1265,-1249,-1236,-1225,-1207,-1186,-1167,-1152,-1134,-1112,-1089,-1066,-1038,-1005,-977,-954,-925,
--888,-857,-838,-815,-779,-742,-711,-679,-636,-589,-548,-504,-450,-395,-355,-318,-270,-217,-172,-128,-72,
--12,40,91,149,196,216,222,232,218,147,65,70,200,391,574,752,956,1174,1373,1551,1704,
-1793,1786,1721,1653,1562,1385,1139,944,894,959,1048,1111,1161,1227,1317,1425,1543,1657,1756,1846,1937,
-2024,2096,2138,2145,2123,2092,2074,2074,2075,2064,2044,2020,1989,1949,1903,1850,1791,1734,1690,1647,1578,
-1478,1372,1286,1207,1115,1023,956,917,879,827,768,708,637,546,436,315,187,57,-63,-170,-269,
--363,-451,-529,-594,-633,-637,-619,-616,-651,-711,-763,-795,-825,-876,-943,-1007,-1056,-1093,-1130,-1168,-1192,
--1192,-1184,-1208,-1294,-1432,-1579,-1706,-1812,-1903,-1973,-2003,-1998,-1975,-1951,-1931,-1919,-1916,-1922,-1934,-1960,-2012,
--2086,-2156,-2201,-2219,-2222,-2219,-2217,-2230,-2262,-2299,-2329,-2361,-2414,-2481,-2530,-2544,-2536,-2527,-2521,-2512,-2505,
--2513,-2545,-2595,-2652,-2703,-2737,-2751,-2751,-2746,-2738,-2720,-2682,-2622,-2540,-2443,-2337,-2231,-2142,-2089,-2070,-2062,
--2035,-1981,-1909,-1819,-1708,-1593,-1507,-1465,-1440,-1393,-1318,-1232,-1142,-1045,-948,-882,-863,-871,-879,-886,-911,
--952,-979,-963,-909,-845,-792,-750,-718,-709,-740,-798,-832,-796,-696,-592,-542,-551,-574,-569,-540,-525,
--546,-585,-602,-580,-535,-488,-449,-413,-379,-350,-330,-319,-319,-322,-318,-302,-280,-256,-226,-192,-161,
--139,-120,-97,-69,-43,-21,2,30,59,89,123,162,201,236,268,302,340,384,430,471,504,
-532,565,602,637,670,708,752,800,850,903,959,1009,1051,1090,1128,1167,1208,1252,1298,1341,1381,
-1421,1463,1501,1533,1565,1596,1624,1650,1680,1713,1743,1770,1805,1848,1886,1904,1911,1917,1923,1920,1909,
-1900,1897,1893,1887,1884,1885,1885,1881,1877,1871,1862,1848,1835,1827,1822,1820,1822,1824,1819,1808,1798,
-1793,1790,1787,1786,1786,1785,1783,1781,1778,1770,1762,1762,1773,1788,1800,1813,1827,1838,1840,1837,1835,
-1832,1819,1800,1766,1745,1720,1690,1656,1622,1590,1559,1528,1494,1455,1411,1365,1317,1266,1219,1184,1160,
-1137,1108,1070,1028,990,961,940,919,892,861,834,817,807,793,762,701,615,525,455,419,422,
-463,528,583,598,575,529,468,391,315,271,271,296,324,347,362,356,327,286,246,207,161,
-106,39,-41,-129,-204,-267,-341,-442,-550,-641,-715,-786,-850,-896,-932,-980,-1048,-1121,-1185,-1237,-1279,
--1313,-1351,-1396,-1436,-1458,-1469,-1488,-1518,-1550,-1585,-1632,-1687,-1733,-1758,-1766,-1766,-1770,-1786,-1806,-1809,-1790,
--1770,-1763,-1752,-1718,-1681,-1663,-1649,-1614,-1574,-1548,-1499,-1373,-1220,-1163,-1234,-1308,-1274,-1190,-1188,-1289,-1395,
--1441,-1462,-1508,-1569,-1620,-1672,-1743,-1818,-1877,-1925,-1974,-2012,-2031,-2043,-2055,-2046,-1994,-1923,-1878,-1882,-1907,
--1914,-1880,-1822,-1782,-1797,-1868,-1955,-2023,-2072,-2122,-2190,-2285,-2420,-2597,-2793,-2970,-3104,-3192,-3240,-3260,-3278,
--3328,-3429,-3567,-3706,-3814,-3885,-3935,-3976,-4012,-4041,-4075,-4126,-4183,-4228,-4258,-4290,-4328,-4354,-4360,-4362,-4377,
--4398,-4411,-4418,-4428,-4437,-4435,-4427,-4426,-4430,-4429,-4422,-4422,-4431,-4432,-4419,-4401,-4391,-4385,-4378,-4376,-4388,
--4404,-4410,-4401,-4389,-4391,-4404,-4413,-4408,-4389,-4361,-4316,-4251,-4186,-4157,-4180,-4236,-4300,-4380,-4500,-4656,-4799,
--4890,-4934,-4968,-5019,-5086,-5156,-5225,-5291,-5354,-5411,-5465,-5521,-5584,-5650,-5717,-5788,-5869,-5953,-6024,-6079,-6131,
--6201,-6283,-6356,-6413,-6468,-6533,-6601,-6660,-6712,-6762,-6813,-6860,-6908,-6958,-7006,-7054,-7107,-7173,-7243,-7304,-7352,
--7396,-7439,-7481,-7527,-7588,-7662,-7745,-7834,-7929,-8026,-8113,-8194,-8275,-8353,-8417,-8471,-8531,-8590,-8623,-8621,-8617,
--8640,-8679,-8713,-8764,-8879,-9042,-9174,-9220,-9212,-9217,-9254,-9291,-9310,-9328,-9356,-9379,-9388,-9394,-9411,-9433,-9443,
--9445,-9455,-9479,-9506,-9516,-9499,-9459,-9416,-9394,-9405,-9432,-9443,-9416,-9352,-9268,-9176,-9074,-8960,-8846,-8764,-8737,
--8750,-8764,-8748,-8706,-8655,-8604,-8548,-8483,-8400,-8292,-8162,-8031,-7914,-7812,-7717,-7631,-7556,-7479,-7383,-7259,-7117,
--6961,-6795,-6633,-6502,-6411,-6346,-6287,-6230,-6172,-6103,-6012,-5900,-5777,-5648,-5514,-5378,-5240,-5094,-4934,-4772,-4630,
--4511,-4399,-4278,-4150,-4025,-3906,-3778,-3629,-3467,-3310,-3170,-3045,-2915,-2766,-2596,-2423,-2277,-2175,-2104,-2030,-1939,
--1862,-1845,-1892,-1932,-1873,-1681,-1416,-1183,-1037,-944,-816,-590,-283,38,318,546,736,893,1009,1082,1130,
-1184,1262,1348,1418,1464,1517,1603,1718,1833,1934,2033,2136,2223,2279,2325,2388,2471,2553,2626,2696,2765,
-2826,2879,2936,3001,3064,3126,3196,3279,3363,3444,3531,3629,3722,3798,3869,3954,4051,4136,4198,4244,4286,
-4331,4389,4476,4593,4714,4811,4879,4928,4967,4992,4990,4955,4887,4808,4766,4808,4932,5100,5274,5446,5595,
-5668,5637,5565,5578,5739,5970,6130,6151,6080,6008,5983,5978,5932,5815,5668,5579,5599,5697,5795,5843,5845,
-5831,5830,5854,5887,5892,5861,5842,5880,5947,5969,5935,5913,5952,6005,5993,5914,5832,5793,5784,5776,5761,
-5741,5712,5664,5593,5502,5427,5447,5627,5939,6271,6515,6644,6690,6693,6681,6686,6736,6844,7002,7188,7365,
-7491,7559,7615,7719,7887,8077,8226,8292,8280,8233,8196,8184,8165,8102,7993,7877,7786,7730,7707,7728,7794,
-7873,7917,7906,7864,7826,7800,7766,7713,7654,7606,7570,7534,7499,7475,7469,7484,7518,7568,7625,7678,7726,
-7771,7815,7858,7902,7950,7998,8034,8056,8066,8067,8061,8053,8047,8037,8015,7980,7942,7898,7844,7786,7730,
-7663,7559,7417,7255,7072,6840,6578,6374,6305,6332,6346,6293,6230,6239,6322,6416,6465,6468,6450,6434,6426,
-6411,6371,6306,6236,6176,6119,6051,5982,5928,5884,5832,5764,5691,5622,5557,5497,5450,5413,5365,5295,5223,
-5174,5145,5111,5049,4966,4884,4825,4795,4780,4751,4693,4613,4539,4482,4438,4397,4362,4338,4319,4295,4260,
-4216,4171,4126,4083,4045,4013,3989,3968,3943,3906,3856,3795,3724,3649,3582,3537,3513,3490,3454,3406,3355,
-3306,3262,3225,3192,3150,3094,3039,3000,2967,2925,2890,2893,2927,2935,2879,2784,2705,2668,2660,2663,2668,
-2663,2636,2597,2567,2554,2538,2507,2466,2425,2380,2324,2265,2214,2170,2132,2101,2078,2058,2034,2007,1986,
-1969,1952,1936,1922,1903,1871,1838,1835,1871,1910,1906,1858,1815,1817,1844,1849,1822,1799,1803,1812,1794,
-1762,1753,1772,1777,1737,1673,1626,1616,1630,1647,1658,1664,1667,1672,1676,1670,1650,1629,1620,1623,1628,
-1636,1656,1684,1703,1706,1705,1710,1711,1699,1678,1657,1632,1600,1570,1560,1565,1562,1541,1513,1493,1478,
-1456,1425,1397,1382,1382,1395,1418,1441,1447,1428,1396,1373,1368,1371,1375,1382,1392,1399,1397,1386,1371,
-1358,1352,1356,1368,1370,1349,1315,1291,1285,1284,1272,1252,1242,1249,1265,1275,1271,1255,1236,1222,1213,
-1204,1193,1180,1164,1144,1121,1101,1085,1067,1044,1017,993,972,947,919,892,865,832,791,754,729,
-713,697,674,646,619,591,558,523,488,459,433,405,374,342,314,290,268,246,220,190,157,
-124,92,61,30,1,-27,-57,-89,-121,-153,-185,-219,-254,-288,-318,-346,-375,-407,-443,-476,-503,
--523,-543,-563,-583,-603,-631,-668,-706,-738,-764,-793,-828,-861,-884,-901,-917,-936,-959,-984,-1013,-1043,
--1071,-1098,-1124,-1147,-1164,-1179,-1195,-1215,-1236,-1254,-1269,-1285,-1304,-1327,-1354,-1380,-1403,-1425,-1447,-1468,-1485,
--1499,-1514,-1531,-1546,-1558,-1570,-1585,-1601,-1615,-1628,-1642,-1661,-1681,-1701,-1715,-1724,-1729,-1737,-1751,-1769,-1782,
--1787,-1788,-1790,-1795,-1797,-1797,-1799,-1803,-1807,-1808,-1805,-1803,-1800,-1796,-1790,-1786,-1781,-1776,-1769,-1763,-1757,
--1750,-1742,-1733,-1723,-1711,-1698,-1688,-1678,-1666,-1656,-1648,-1643,-1635,-1623,-1610,-1599,-1589,-1578,-1569,-1562,-1554,
--1547,-1541,-1537,-1529,-1518,-1508,-1503,-1498,-1491,-1483,-1478,-1472,-1466,-1461,-1458,-1456,-1453,-1451,-1451,-1451,-1449,
--1446,-1445,-1445,-1445,-1444,-1444,-1444,-1443,-1443,-1443,-1444,-1443,-1440,-1436,-1430,-1425,-1421,-1416,-1413,-1411,-1413,
--1413,-1407,-1398,-1392,-1388,-1383,-1378,-1376,-1375,-1369,-1358,-1346,-1336,-1327,-1316,-1307,-1295,-1279,-1261,-1249,-1242,
--1227,-1205,-1182,-1165,-1148,-1128,-1107,-1086,-1058,-1026,-1000,-978,-949,-912,-881,-861,-838,-801,-762,-731,-698,
--654,-606,-566,-523,-469,-418,-380,-343,-293,-237,-192,-148,-88,-26,18,53,100,146,168,174,185,
-172,97,7,31,232,533,813,1032,1226,1417,1585,1711,1784,1787,1717,1618,1529,1432,1287,1116,1001,
-983,1019,1049,1070,1116,1195,1289,1387,1489,1595,1701,1805,1906,1996,2068,2116,2138,2131,2108,2089,2085,
-2084,2079,2069,2055,2027,1980,1924,1869,1820,1777,1741,1697,1626,1527,1426,1341,1263,1177,1091,1026,980,
-934,879,823,766,695,601,488,360,222,79,-53,-170,-278,-381,-474,-549,-602,-622,-605,-569,-555,
--589,-646,-682,-681,-678,-711,-781,-853,-899,-929,-971,-1033,-1099,-1150,-1193,-1258,-1367,-1509,-1648,-1761,-1847,
--1923,-1991,-2040,-2058,-2044,-2014,-1985,-1972,-1980,-2001,-2023,-2045,-2076,-2119,-2161,-2189,-2202,-2209,-2211,-2214,-2227,
--2253,-2285,-2315,-2355,-2418,-2495,-2549,-2560,-2542,-2521,-2504,-2483,-2468,-2477,-2519,-2580,-2641,-2692,-2728,-2747,-2748,
--2734,-2713,-2685,-2646,-2590,-2519,-2434,-2342,-2250,-2172,-2125,-2105,-2090,-2054,-1992,-1911,-1812,-1692,-1572,-1493,-1466,
--1454,-1407,-1317,-1216,-1127,-1042,-954,-883,-851,-847,-847,-848,-867,-909,-945,-942,-894,-827,-771,-740,-737,
--764,-817,-866,-872,-813,-708,-608,-560,-568,-595,-601,-583,-569,-583,-615,-628,-604,-553,-500,-456,-422,
--394,-372,-355,-346,-346,-350,-348,-335,-314,-292,-264,-228,-193,-165,-144,-118,-87,-57,-31,-7,18,
-43,67,97,135,174,210,244,282,326,374,419,456,484,510,540,575,611,649,694,747,803,
-859,916,971,1020,1059,1094,1129,1164,1200,1240,1282,1323,1362,1403,1445,1484,1519,1551,1584,1614,1642,
-1671,1702,1730,1757,1790,1829,1862,1883,1895,1906,1914,1912,1905,1898,1894,1888,1879,1873,1870,1867,1862,
-1855,1849,1841,1834,1827,1821,1817,1816,1820,1822,1817,1807,1799,1792,1785,1780,1780,1780,1777,1773,1772,
-1770,1763,1759,1766,1782,1796,1801,1804,1811,1816,1813,1805,1798,1792,1782,1766,1733,1716,1691,1659,1624,
-1591,1557,1525,1495,1462,1417,1361,1303,1251,1205,1166,1138,1118,1099,1071,1032,989,951,925,907,888,
-861,832,809,794,786,779,763,724,656,571,495,439,410,412,445,493,533,553,547,502,416,
-324,278,296,338,361,355,338,315,285,253,225,193,143,77,3,-67,-123,-158,-187,-243,-340,
--457,-564,-654,-731,-794,-838,-881,-944,-1022,-1096,-1155,-1206,-1252,-1291,-1328,-1373,-1416,-1440,-1445,-1448,-1458,
--1476,-1507,-1562,-1635,-1698,-1728,-1728,-1720,-1726,-1753,-1785,-1793,-1771,-1747,-1742,-1738,-1713,-1683,-1668,-1655,-1617,
--1574,-1555,-1524,-1413,-1255,-1181,-1256,-1383,-1427,-1386,-1360,-1395,-1446,-1468,-1481,-1512,-1554,-1598,-1661,-1744,-1817,
--1863,-1900,-1948,-1992,-2015,-2024,-2029,-2009,-1943,-1858,-1808,-1820,-1864,-1885,-1860,-1807,-1768,-1781,-1848,-1944,-2043,
--2128,-2193,-2252,-2333,-2467,-2648,-2834,-2985,-3098,-3185,-3248,-3284,-3308,-3355,-3448,-3575,-3701,-3801,-3876,-3937,-3988,
--4025,-4049,-4076,-4119,-4170,-4210,-4240,-4272,-4307,-4326,-4325,-4321,-4335,-4361,-4384,-4396,-4397,-4389,-4378,-4380,-4398,
--4412,-4409,-4402,-4405,-4411,-4403,-4383,-4370,-4367,-4359,-4343,-4336,-4346,-4361,-4361,-4346,-4332,-4328,-4335,-4344,-4343,
--4316,-4261,-4190,-4124,-4086,-4088,-4126,-4179,-4228,-4286,-4383,-4528,-4687,-4810,-4880,-4922,-4967,-5028,-5099,-5171,-5240,
--5305,-5366,-5424,-5479,-5535,-5594,-5659,-5732,-5812,-5889,-5955,-6010,-6068,-6139,-6215,-6282,-6342,-6405,-6474,-6538,-6593,
--6646,-6705,-6763,-6812,-6855,-6902,-6955,-7009,-7066,-7128,-7191,-7247,-7296,-7342,-7385,-7425,-7469,-7525,-7595,-7675,-7766,
--7867,-7966,-8052,-8128,-8204,-8281,-8350,-8417,-8487,-8542,-8552,-8521,-8498,-8518,-8569,-8625,-8704,-8837,-9001,-9123,-9161,
--9153,-9160,-9195,-9227,-9246,-9264,-9290,-9311,-9318,-9321,-9334,-9350,-9358,-9361,-9372,-9397,-9425,-9436,-9417,-9375,-9336,
--9327,-9351,-9381,-9383,-9340,-9260,-9164,-9068,-8971,-8869,-8769,-8698,-8675,-8692,-8710,-8702,-8669,-8629,-8588,-8539,-8471,
--8378,-8259,-8124,-7994,-7884,-7793,-7712,-7636,-7564,-7482,-7376,-7247,-7104,-6953,-6797,-6646,-6522,-6438,-6381,-6330,-6274,
--6208,-6127,-6025,-5908,-5787,-5669,-5549,-5422,-5285,-5134,-4965,-4791,-4639,-4523,-4428,-4325,-4203,-4073,-3946,-3808,-3650,
--3485,-3340,-3222,-3109,-2971,-2807,-2635,-2473,-2331,-2212,-2112,-2013,-1903,-1803,-1765,-1811,-1890,-1904,-1782,-1550,-1303,
--1128,-1024,-922,-750,-504,-226,50,321,585,819,989,1085,1132,1176,1246,1337,1419,1479,1532,1609,1712,
-1817,1908,1997,2094,2185,2252,2306,2370,2447,2519,2582,2645,2715,2782,2839,2896,2957,3018,3079,3145,3220,
-3297,3373,3454,3541,3628,3708,3788,3880,3980,4074,4155,4221,4271,4311,4362,4449,4568,4682,4761,4811,4852,
-4891,4912,4895,4838,4759,4698,4696,4776,4918,5083,5244,5398,5525,5583,5553,5490,5490,5602,5779,5924,5982,
-5972,5949,5944,5936,5873,5736,5580,5497,5532,5637,5729,5768,5775,5780,5796,5820,5837,5829,5802,5794,5834,
-5889,5896,5854,5832,5874,5933,5938,5890,5849,5838,5814,5739,5630,5538,5491,5473,5450,5406,5364,5387,5527,
-5770,6045,6275,6417,6469,6460,6446,6484,6590,6737,6890,7035,7166,7261,7311,7348,7428,7578,7763,7920,8011,
-8052,8083,8127,8170,8178,8136,8060,7971,7882,7802,7751,7759,7835,7946,8028,8037,7985,7921,7878,7833,7747,
-7618,7492,7412,7376,7352,7318,7286,7284,7331,7415,7506,7577,7631,7683,7738,7789,7834,7880,7934,7987,8029,
-8058,8076,8084,8082,8071,8050,8018,7985,7959,7934,7898,7854,7811,7750,7638,7473,7284,7072,6797,6459,6174,
-6081,6183,6327,6365,6301,6251,6298,6412,6506,6532,6512,6493,6501,6512,6485,6411,6320,6241,6174,6106,6042,
-5995,5957,5909,5841,5766,5696,5630,5569,5519,5476,5425,5354,5279,5222,5187,5152,5098,5030,4967,4923,4897,
-4869,4819,4741,4653,4578,4526,4488,4452,4416,4388,4367,4343,4308,4262,4213,4167,4123,4082,4047,4026,4013,
-3991,3951,3899,3842,3782,3713,3643,3592,3565,3546,3511,3455,3390,3332,3283,3243,3203,3155,3102,3056,3022,
-2988,2946,2914,2920,2950,2956,2908,2828,2761,2719,2695,2688,2699,2707,2685,2635,2591,2570,2556,2526,2481,
-2438,2397,2347,2287,2229,2181,2143,2113,2088,2064,2037,2014,1999,1988,1972,1951,1931,1909,1878,1849,1851,
-1890,1927,1911,1844,1781,1771,1795,1808,1801,1808,1841,1861,1833,1780,1752,1756,1746,1698,1639,1612,1619,
-1638,1652,1662,1670,1675,1678,1682,1681,1668,1654,1648,1647,1643,1642,1658,1687,1707,1709,1707,1713,1718,
-1708,1689,1667,1640,1603,1568,1553,1556,1557,1541,1514,1488,1465,1441,1414,1389,1370,1362,1371,1400,1433,
-1448,1431,1395,1364,1350,1349,1351,1352,1352,1356,1361,1363,1356,1340,1325,1324,1334,1339,1325,1298,1279,
-1275,1275,1262,1237,1215,1207,1215,1229,1235,1229,1214,1199,1188,1178,1164,1146,1127,1106,1084,1063,1045,
-1027,1008,988,971,955,936,913,889,860,821,776,734,705,686,669,648,624,600,572,542,509,
-478,451,427,403,375,346,318,293,270,247,221,192,160,127,93,59,27,-1,-28,-55,-85,
--118,-150,-183,-218,-252,-285,-316,-345,-374,-407,-442,-478,-507,-528,-546,-565,-584,-601,-624,-655,-692,
--725,-751,-780,-814,-848,-874,-894,-912,-932,-953,-977,-1005,-1035,-1066,-1096,-1124,-1146,-1162,-1177,-1195,-1214,
--1231,-1243,-1253,-1266,-1286,-1310,-1336,-1358,-1376,-1394,-1416,-1439,-1459,-1474,-1488,-1502,-1516,-1529,-1542,-1556,-1569,
--1580,-1590,-1602,-1620,-1641,-1663,-1680,-1690,-1698,-1707,-1722,-1740,-1753,-1758,-1759,-1761,-1766,-1768,-1768,-1768,-1770,
--1771,-1770,-1767,-1764,-1761,-1757,-1752,-1749,-1746,-1742,-1737,-1731,-1724,-1716,-1708,-1700,-1691,-1679,-1666,-1657,-1649,
--1638,-1626,-1616,-1608,-1598,-1584,-1571,-1560,-1551,-1541,-1530,-1520,-1512,-1506,-1500,-1495,-1490,-1485,-1481,-1474,-1467,
--1459,-1454,-1451,-1446,-1440,-1434,-1431,-1427,-1425,-1425,-1428,-1431,-1431,-1430,-1428,-1427,-1427,-1429,-1430,-1428,-1425,
--1425,-1429,-1434,-1439,-1441,-1441,-1438,-1433,-1428,-1421,-1413,-1409,-1410,-1413,-1409,-1400,-1394,-1391,-1387,-1381,-1379,
--1379,-1374,-1363,-1353,-1346,-1339,-1330,-1321,-1310,-1294,-1273,-1259,-1252,-1241,-1221,-1198,-1180,-1162,-1141,-1122,-1102,
--1077,-1047,-1020,-998,-970,-935,-905,-883,-857,-820,-780,-748,-713,-666,-618,-578,-538,-488,-441,-404,-365,
--310,-253,-211,-170,-111,-50,-14,11,53,106,139,152,162,140,50,-47,0,267,657,1005,1246,
-1426,1592,1731,1813,1823,1757,1635,1499,1388,1291,1179,1067,1001,994,1005,1009,1030,1097,1193,1284,1365,
-1450,1549,1659,1771,1877,1963,2028,2076,2110,2123,2112,2094,2082,2079,2080,2085,2082,2057,2001,1935,1882,
-1849,1829,1806,1765,1692,1593,1491,1403,1323,1243,1168,1106,1052,995,935,882,829,762,669,555,422,
-270,111,-36,-163,-275,-376,-462,-528,-572,-589,-570,-531,-512,-539,-590,-615,-597,-574,-598,-671,-753,
--807,-841,-892,-978,-1084,-1183,-1269,-1359,-1465,-1585,-1699,-1793,-1867,-1932,-1998,-2057,-2087,-2077,-2038,-2001,-1991,
--2014,-2055,-2094,-2120,-2139,-2159,-2179,-2192,-2199,-2205,-2211,-2218,-2228,-2246,-2270,-2302,-2350,-2425,-2506,-2556,-2555,
--2523,-2491,-2470,-2451,-2437,-2452,-2506,-2583,-2654,-2704,-2732,-2739,-2726,-2700,-2671,-2645,-2612,-2563,-2498,-2423,-2348,
--2275,-2211,-2164,-2134,-2105,-2061,-1994,-1909,-1804,-1683,-1566,-1491,-1467,-1453,-1400,-1300,-1191,-1104,-1031,-956,-889,
--849,-834,-823,-810,-814,-847,-887,-901,-877,-833,-794,-775,-789,-833,-889,-921,-905,-840,-754,-681,-643,
--642,-659,-667,-654,-637,-635,-646,-647,-619,-569,-517,-472,-438,-413,-396,-384,-376,-372,-372,-367,-353,
--334,-313,-288,-254,-218,-188,-164,-137,-107,-78,-52,-27,-3,16,35,62,100,141,178,215,258,
-306,354,396,429,458,487,520,557,596,639,688,742,797,850,903,956,1002,1042,1079,1116,1155,
-1195,1235,1277,1320,1362,1405,1446,1482,1514,1543,1573,1603,1631,1659,1684,1708,1735,1769,1807,1839,1864,
-1884,1899,1906,1900,1890,1881,1876,1870,1863,1858,1855,1853,1850,1844,1835,1827,1823,1822,1820,1816,1813,
-1813,1811,1804,1797,1792,1784,1774,1768,1768,1768,1763,1760,1761,1763,1759,1758,1769,1786,1793,1789,1783,
-1785,1786,1780,1770,1760,1751,1743,1733,1708,1696,1671,1637,1600,1564,1524,1484,1448,1410,1361,1301,1244,
-1198,1161,1126,1097,1073,1050,1023,990,955,923,898,879,860,835,810,791,778,767,758,753,737,
-696,634,570,514,466,429,413,426,465,518,556,540,457,351,296,317,368,391,373,342,312,
-282,251,225,196,149,83,9,-53,-92,-106,-118,-163,-258,-382,-503,-604,-684,-740,-779,-826,-899,
--984,-1051,-1097,-1140,-1188,-1233,-1274,-1317,-1360,-1391,-1405,-1413,-1423,-1436,-1463,-1518,-1594,-1657,-1683,-1678,-1669,
--1680,-1713,-1748,-1757,-1738,-1717,-1714,-1713,-1693,-1668,-1659,-1647,-1609,-1563,-1546,-1528,-1437,-1286,-1198,-1264,-1417,
--1514,-1507,-1460,-1443,-1458,-1477,-1494,-1510,-1529,-1571,-1655,-1759,-1835,-1868,-1892,-1935,-1984,-2010,-2014,-2003,-1968,
--1901,-1829,-1797,-1819,-1862,-1884,-1865,-1817,-1772,-1767,-1826,-1942,-2078,-2185,-2241,-2281,-2365,-2524,-2715,-2872,-2976,
--3064,-3167,-3266,-3329,-3361,-3406,-3492,-3605,-3713,-3800,-3871,-3935,-3991,-4030,-4053,-4074,-4107,-4149,-4188,-4220,-4250,
--4274,-4282,-4274,-4271,-4288,-4320,-4351,-4369,-4367,-4348,-4335,-4346,-4373,-4387,-4378,-4371,-4379,-4384,-4368,-4344,-4335,
--4335,-4320,-4296,-4289,-4303,-4315,-4307,-4292,-4279,-4265,-4256,-4263,-4279,-4267,-4204,-4115,-4050,-4035,-4061,-4105,-4149,
--4185,-4222,-4288,-4405,-4557,-4700,-4803,-4867,-4920,-4979,-5047,-5117,-5185,-5250,-5316,-5379,-5436,-5488,-5542,-5605,-5678,
--5753,-5823,-5884,-5944,-6008,-6077,-6145,-6207,-6271,-6342,-6415,-6479,-6535,-6595,-6660,-6720,-6764,-6801,-6848,-6906,-6966,
--7023,-7078,-7133,-7187,-7238,-7284,-7322,-7356,-7398,-7455,-7526,-7606,-7697,-7798,-7898,-7985,-8060,-8136,-8214,-8288,-8360,
--8424,-8461,-8450,-8409,-8388,-8415,-8475,-8549,-8649,-8793,-8950,-9057,-9092,-9091,-9104,-9138,-9169,-9187,-9205,-9227,-9243,
--9250,-9254,-9264,-9275,-9280,-9286,-9303,-9334,-9368,-9383,-9369,-9335,-9309,-9310,-9333,-9349,-9329,-9265,-9171,-9071,-8980,
--8896,-8810,-8724,-8664,-8651,-8675,-8699,-8692,-8657,-8613,-8570,-8519,-8445,-8342,-8214,-8077,-7953,-7854,-7777,-7709,-7641,
--7567,-7479,-7370,-7241,-7102,-6960,-6815,-6678,-6567,-6491,-6437,-6384,-6318,-6236,-6139,-6026,-5907,-5793,-5688,-5579,-5456,
--5315,-5160,-4988,-4810,-4653,-4537,-4453,-4365,-4255,-4132,-4009,-3872,-3707,-3532,-3389,-3287,-3185,-3043,-2869,-2698,-2548,
--2409,-2271,-2140,-2019,-1907,-1811,-1765,-1792,-1866,-1912,-1853,-1674,-1437,-1232,-1101,-1009,-891,-715,-491,-240,31,
-318,591,815,973,1074,1147,1221,1309,1399,1470,1525,1591,1683,1785,1873,1952,2037,2128,2209,2279,2349,
-2422,2486,2542,2603,2677,2749,2806,2853,2904,2967,3036,3107,3177,3244,3313,3389,3470,3550,3628,3713,3809,
-3911,4006,4092,4166,4224,4272,4335,4432,4547,4641,4694,4727,4770,4820,4844,4814,4743,4671,4644,4682,4780,
-4923,5092,5265,5416,5510,5529,5493,5451,5455,5522,5630,5740,5821,5867,5891,5909,5902,5832,5688,5530,5452,
-5488,5582,5656,5687,5706,5736,5771,5800,5820,5826,5817,5806,5815,5832,5827,5797,5782,5804,5832,5827,5801,
-5800,5824,5809,5701,5515,5325,5197,5151,5157,5178,5206,5267,5391,5584,5816,6029,6167,6204,6179,6187,6297,
-6490,6679,6800,6864,6913,6963,7002,7034,7094,7208,7353,7479,7553,7598,7656,7736,7809,7848,7859,7866,7867,
-7845,7795,7750,7762,7854,8001,8132,8179,8134,8055,7993,7934,7822,7644,7464,7352,7312,7287,7231,7155,7109,
-7130,7211,7308,7386,7445,7509,7589,7671,7739,7798,7859,7920,7973,8019,8057,8085,8096,8090,8071,8047,8023,
-8000,7965,7916,7872,7853,7827,7728,7526,7258,6964,6624,6234,5895,5775,5924,6196,6379,6393,6333,6327,6410,
-6516,6572,6571,6558,6568,6587,6571,6501,6403,6309,6230,6158,6097,6055,6025,5984,5923,5848,5775,5708,5646,
-5593,5546,5494,5428,5357,5293,5241,5192,5137,5079,5029,4993,4963,4924,4865,4788,4704,4629,4572,4531,4496,
-4459,4419,4385,4358,4330,4294,4250,4203,4157,4114,4080,4059,4045,4024,3985,3936,3885,3829,3761,3691,3637,
-3607,3584,3545,3486,3420,3360,3311,3268,3226,3183,3141,3104,3072,3035,2993,2960,2951,2953,2936,2894,2849,
-2816,2784,2746,2721,2725,2737,2715,2655,2597,2571,2560,2533,2487,2442,2404,2363,2311,2254,2204,2164,2133,
-2107,2085,2061,2041,2027,2017,2003,1982,1957,1927,1887,1852,1850,1888,1926,1912,1845,1775,1750,1762,1777,
-1790,1826,1880,1903,1866,1799,1758,1747,1726,1677,1630,1620,1635,1648,1653,1659,1668,1673,1673,1676,1679,
-1677,1674,1676,1674,1663,1653,1663,1689,1707,1705,1700,1707,1717,1711,1688,1661,1636,1609,1580,1559,1549,
-1542,1528,1508,1483,1457,1434,1417,1403,1385,1368,1364,1381,1407,1420,1407,1376,1345,1329,1327,1329,1326,
-1320,1320,1327,1333,1329,1314,1298,1293,1298,1302,1294,1278,1266,1263,1262,1253,1231,1200,1175,1165,1173,
-1186,1192,1184,1170,1156,1142,1124,1102,1081,1062,1041,1020,1001,982,964,947,933,919,905,888,868,
-839,799,753,709,676,652,634,617,598,575,548,519,491,464,439,416,394,371,348,323,299,
-275,250,222,191,158,126,93,60,29,3,-19,-44,-74,-107,-140,-174,-209,-242,-274,-305,-337,
--370,-403,-440,-476,-507,-530,-549,-570,-591,-609,-628,-655,-687,-718,-743,-769,-799,-832,-861,-885,-907,
--927,-946,-968,-994,-1023,-1052,-1081,-1107,-1127,-1142,-1157,-1178,-1202,-1220,-1230,-1239,-1251,-1271,-1296,-1320,-1341,
--1357,-1372,-1391,-1415,-1436,-1453,-1465,-1477,-1490,-1505,-1520,-1533,-1543,-1549,-1556,-1567,-1583,-1602,-1622,-1639,-1653,
--1664,-1676,-1691,-1708,-1721,-1728,-1730,-1733,-1736,-1739,-1739,-1738,-1737,-1736,-1733,-1730,-1728,-1726,-1723,-1719,-1716,
--1713,-1709,-1704,-1699,-1692,-1684,-1675,-1667,-1657,-1644,-1632,-1625,-1621,-1614,-1602,-1587,-1573,-1559,-1544,-1530,-1519,
--1510,-1501,-1490,-1480,-1472,-1467,-1462,-1456,-1452,-1451,-1450,-1444,-1434,-1425,-1421,-1419,-1416,-1412,-1410,-1408,-1405,
--1403,-1404,-1409,-1414,-1417,-1418,-1417,-1415,-1414,-1417,-1420,-1418,-1413,-1412,-1415,-1422,-1430,-1438,-1442,-1440,-1436,
--1431,-1424,-1414,-1406,-1406,-1409,-1406,-1399,-1396,-1398,-1395,-1388,-1383,-1382,-1378,-1367,-1359,-1355,-1350,-1340,-1330,
--1321,-1307,-1287,-1270,-1261,-1252,-1234,-1214,-1197,-1179,-1158,-1137,-1118,-1095,-1066,-1038,-1015,-988,-956,-926,-902,
--875,-838,-800,-767,-729,-682,-636,-599,-559,-509,-461,-423,-380,-322,-266,-228,-193,-139,-83,-49,-23,
-24,85,124,138,138,98,-8,-99,-13,313,751,1112,1337,1495,1650,1785,1858,1848,1750,1582,1399,
-1260,1173,1106,1041,995,975,968,974,1015,1098,1191,1264,1328,1407,1508,1619,1731,1837,1923,1986,2035,
-2079,2108,2111,2094,2077,2072,2080,2096,2105,2085,2027,1955,1901,1878,1875,1868,1835,1765,1666,1562,1468,
-1386,1312,1245,1186,1124,1056,991,938,890,828,742,632,495,332,159,0,-133,-245,-339,-414,-470,
--513,-537,-532,-506,-492,-514,-559,-583,-569,-552,-580,-662,-756,-822,-865,-922,-1014,-1131,-1246,-1349,-1442,
--1531,-1619,-1705,-1784,-1852,-1915,-1980,-2044,-2081,-2076,-2039,-2003,-1998,-2028,-2078,-2124,-2154,-2169,-2179,-2188,-2194,
--2196,-2200,-2209,-2220,-2231,-2241,-2258,-2288,-2342,-2421,-2503,-2548,-2536,-2492,-2456,-2440,-2432,-2429,-2450,-2509,-2592,
--2668,-2715,-2732,-2720,-2688,-2651,-2624,-2608,-2587,-2542,-2475,-2403,-2341,-2289,-2241,-2193,-2148,-2105,-2056,-1991,-1906,
--1803,-1688,-1582,-1510,-1474,-1443,-1377,-1273,-1167,-1086,-1022,-953,-885,-841,-822,-807,-789,-781,-796,-823,-837,
--831,-813,-792,-776,-781,-818,-871,-904,-894,-852,-805,-768,-742,-730,-729,-729,-717,-695,-677,-670,-659,
--631,-588,-543,-501,-465,-438,-423,-415,-409,-401,-392,-382,-366,-348,-328,-306,-278,-246,-215,-188,-159,
--132,-108,-86,-63,-40,-20,-2,24,62,102,139,178,223,272,316,353,387,422,459,499,541,
-585,630,678,728,778,826,873,921,967,1010,1049,1091,1136,1182,1227,1274,1323,1370,1414,1452,1483,
-1509,1531,1555,1581,1609,1635,1658,1683,1716,1756,1795,1826,1849,1869,1884,1886,1876,1863,1855,1853,1850,
-1847,1845,1845,1846,1846,1840,1829,1817,1812,1812,1811,1806,1802,1797,1790,1780,1774,1770,1762,1752,1747,
-1748,1747,1742,1741,1747,1753,1751,1750,1757,1767,1766,1757,1752,1755,1758,1754,1745,1734,1723,1714,1708,
-1692,1678,1651,1613,1575,1537,1492,1441,1393,1349,1301,1247,1199,1161,1127,1091,1057,1030,1005,977,951,
-926,901,878,858,839,816,794,777,765,754,744,742,740,724,691,651,612,566,509,453,422,
-434,489,553,572,513,412,344,348,389,410,398,372,345,312,275,244,216,180,129,71,16,
--22,-43,-61,-107,-197,-314,-432,-532,-610,-664,-704,-757,-834,-915,-971,-1002,-1036,-1086,-1138,-1185,-1230,
--1276,-1316,-1347,-1374,-1398,-1415,-1439,-1486,-1551,-1604,-1625,-1623,-1623,-1638,-1667,-1696,-1708,-1701,-1689,-1685,-1679,
--1660,-1642,-1641,-1637,-1602,-1552,-1530,-1520,-1456,-1331,-1242,-1285,-1423,-1530,-1537,-1481,-1437,-1436,-1465,-1492,-1498,
--1499,-1538,-1640,-1769,-1857,-1888,-1903,-1939,-1987,-2016,-2016,-1990,-1940,-1880,-1843,-1850,-1881,-1899,-1890,-1861,-1822,
--1782,-1769,-1826,-1962,-2125,-2237,-2275,-2303,-2407,-2596,-2786,-2898,-2949,-3021,-3151,-3290,-3375,-3413,-3456,-3536,-3639,
--3733,-3807,-3869,-3927,-3980,-4022,-4048,-4067,-4091,-4124,-4160,-4191,-4213,-4224,-4222,-4218,-4226,-4251,-4284,-4316,-4336,
--4338,-4325,-4320,-4339,-4367,-4370,-4350,-4338,-4348,-4352,-4332,-4309,-4304,-4301,-4277,-4249,-4247,-4263,-4264,-4248,-4240,
--4240,-4220,-4187,-4187,-4233,-4268,-4233,-4147,-4077,-4058,-4071,-4091,-4112,-4136,-4162,-4205,-4288,-4419,-4566,-4694,-4789,
--4863,-4931,-4998,-5064,-5128,-5191,-5257,-5325,-5389,-5444,-5497,-5556,-5623,-5692,-5757,-5820,-5884,-5951,-6015,-6075,-6136,
--6206,-6283,-6358,-6424,-6484,-6547,-6612,-6667,-6708,-6746,-6796,-6858,-6919,-6973,-7023,-7076,-7131,-7181,-7222,-7251,-7280,
--7325,-7388,-7463,-7542,-7629,-7725,-7824,-7914,-7995,-8074,-8151,-8218,-8272,-8309,-8318,-8302,-8284,-8295,-8342,-8408,-8489,
--8603,-8750,-8892,-8980,-9012,-9025,-9050,-9085,-9115,-9137,-9155,-9171,-9180,-9184,-9190,-9198,-9206,-9214,-9228,-9255,-9295,
--9332,-9351,-9343,-9320,-9306,-9311,-9324,-9320,-9282,-9208,-9112,-9017,-8934,-8860,-8783,-8707,-8659,-8659,-8693,-8718,-8702,
--8651,-8589,-8532,-8472,-8393,-8288,-8159,-8027,-7911,-7822,-7754,-7693,-7627,-7551,-7461,-7355,-7235,-7105,-6971,-6835,-6710,
--6611,-6541,-6485,-6423,-6345,-6252,-6146,-6030,-5909,-5796,-5694,-5590,-5469,-5328,-5176,-5014,-4847,-4695,-4579,-4496,-4416,
--4315,-4201,-4084,-3947,-3772,-3587,-3444,-3350,-3254,-3108,-2926,-2758,-2622,-2491,-2343,-2189,-2052,-1942,-1860,-1815,-1818,
--1863,-1908,-1897,-1784,-1581,-1359,-1186,-1074,-976,-846,-677,-483,-272,-38,218,485,738,946,1093,1193,1278,
-1364,1440,1495,1551,1634,1738,1835,1915,1993,2081,2170,2250,2323,2393,2456,2515,2581,2658,2730,2779,2811,
-2851,2914,2994,3073,3139,3199,3264,3341,3423,3501,3577,3660,3754,3851,3942,4025,4100,4165,4227,4303,4400,
-4500,4570,4603,4630,4678,4738,4769,4744,4685,4642,4650,4705,4790,4908,5072,5264,5423,5492,5476,5430,5409,
-5424,5464,5527,5615,5709,5782,5822,5841,5837,5782,5665,5538,5477,5506,5571,5613,5632,5662,5709,5750,5776,
-5801,5829,5843,5830,5809,5798,5794,5783,5766,5750,5729,5698,5673,5679,5711,5710,5607,5383,5096,4852,4736,
-4754,4853,4971,5092,5240,5437,5673,5887,5997,5979,5913,5940,6134,6426,6664,6763,6759,6741,6761,6805,6851,
-6903,6974,7058,7117,7135,7139,7171,7241,7317,7378,7442,7530,7628,7693,7711,7717,7767,7892,8074,8245,8329,
-8300,8214,8136,8069,7960,7791,7616,7501,7446,7395,7305,7180,7064,7001,7002,7043,7093,7146,7221,7331,7461,
-7584,7691,7780,7850,7904,7952,8003,8047,8076,8091,8103,8114,8112,8083,8022,7945,7893,7891,7893,7793,7531,
-7152,6752,6366,5986,5664,5537,5689,6026,6333,6459,6425,6363,6374,6459,6552,6601,6613,6615,6618,6599,6540,
-6451,6359,6277,6204,6143,6102,6077,6048,5999,5932,5859,5791,5729,5671,5614,5559,5500,5435,5367,5299,5233,
-5170,5113,5066,5028,4990,4945,4889,4827,4759,4687,4621,4570,4531,4490,4439,4390,4356,4334,4309,4273,4228,
-4185,4147,4117,4092,4069,4042,4007,3967,3920,3863,3795,3728,3675,3637,3601,3554,3497,3442,3397,3358,3321,
-3284,3249,3217,3187,3154,3115,3074,3035,2999,2959,2915,2881,2872,2876,2857,2808,2760,2745,2746,2721,2658,
-2595,2565,2557,2538,2498,2452,2414,2379,2336,2287,2238,2194,2159,2135,2117,2098,2077,2056,2039,2021,2001,
-1978,1947,1906,1869,1859,1884,1914,1906,1855,1796,1766,1764,1773,1793,1837,1891,1910,1871,1809,1768,1748,
-1720,1675,1643,1643,1656,1658,1654,1658,1669,1673,1671,1672,1680,1686,1689,1693,1691,1677,1663,1667,1688,
-1701,1695,1690,1702,1718,1713,1685,1654,1639,1634,1621,1594,1558,1527,1509,1497,1479,1455,1436,1429,1426,
-1414,1394,1380,1378,1383,1382,1369,1347,1324,1309,1306,1307,1304,1297,1291,1292,1293,1289,1279,1269,1264,
-1263,1260,1255,1245,1237,1232,1233,1233,1222,1194,1158,1129,1120,1128,1139,1141,1132,1117,1099,1080,1059,
-1041,1023,1006,986,965,943,921,899,880,864,852,841,828,805,770,728,687,652,625,606,591,
-575,552,525,498,473,448,422,398,378,360,343,321,296,269,242,212,180,148,116,86,57,
-30,7,-14,-37,-65,-96,-129,-162,-197,-229,-260,-292,-326,-361,-397,-433,-469,-502,-528,-551,-574,
--598,-618,-637,-659,-687,-714,-738,-761,-788,-817,-848,-876,-900,-919,-937,-957,-982,-1009,-1034,-1059,-1081,
--1099,-1112,-1128,-1153,-1181,-1204,-1217,-1227,-1240,-1259,-1283,-1307,-1328,-1344,-1357,-1374,-1395,-1417,-1435,-1447,-1456,
--1467,-1481,-1497,-1509,-1516,-1521,-1528,-1539,-1554,-1570,-1587,-1603,-1617,-1630,-1644,-1660,-1676,-1689,-1697,-1702,-1705,
--1706,-1707,-1707,-1705,-1702,-1698,-1697,-1698,-1698,-1697,-1695,-1692,-1689,-1683,-1677,-1671,-1666,-1660,-1653,-1645,-1636,
--1624,-1611,-1599,-1593,-1592,-1587,-1575,-1558,-1539,-1523,-1506,-1490,-1478,-1469,-1461,-1453,-1443,-1436,-1432,-1427,-1420,
--1416,-1415,-1415,-1410,-1400,-1391,-1386,-1384,-1383,-1383,-1386,-1387,-1385,-1384,-1387,-1393,-1397,-1401,-1404,-1406,-1405,
--1405,-1409,-1412,-1412,-1408,-1406,-1407,-1411,-1418,-1429,-1436,-1436,-1430,-1426,-1422,-1412,-1403,-1402,-1404,-1401,-1394,
--1394,-1401,-1401,-1393,-1386,-1384,-1380,-1371,-1364,-1362,-1358,-1346,-1334,-1327,-1317,-1301,-1284,-1273,-1262,-1245,-1227,
--1212,-1196,-1175,-1152,-1133,-1112,-1085,-1056,-1031,-1005,-975,-946,-920,-893,-858,-822,-787,-747,-702,-660,-625,
--584,-530,-477,-436,-393,-337,-283,-246,-213,-164,-112,-75,-39,14,73,106,113,101,41,-76,-149,
--13,363,815,1145,1321,1446,1598,1761,1888,1936,1861,1656,1394,1193,1108,1095,1083,1048,1007,979,982,
-1028,1101,1169,1220,1279,1368,1475,1580,1683,1789,1883,1952,2001,2047,2085,2100,2092,2079,2079,2093,2115,
-2130,2116,2068,1998,1938,1910,1909,1913,1891,1826,1727,1621,1528,1449,1380,1318,1258,1192,1119,1050,993,
-943,884,803,698,561,397,224,64,-71,-184,-277,-346,-398,-440,-471,-484,-480,-483,-510,-552,-583,
--587,-591,-631,-717,-816,-892,-945,-1004,-1088,-1189,-1287,-1375,-1454,-1525,-1593,-1660,-1729,-1795,-1859,-1926,-1994,
--2041,-2051,-2030,-2011,-2015,-2044,-2085,-2124,-2150,-2163,-2172,-2181,-2187,-2188,-2190,-2200,-2214,-2226,-2235,-2248,-2275,
--2327,-2402,-2479,-2522,-2510,-2469,-2439,-2435,-2443,-2448,-2468,-2518,-2590,-2659,-2702,-2714,-2695,-2653,-2610,-2586,-2578,
--2562,-2515,-2444,-2372,-2319,-2285,-2251,-2206,-2155,-2107,-2060,-1999,-1914,-1810,-1701,-1605,-1534,-1484,-1431,-1351,-1248,
--1152,-1080,-1020,-951,-880,-832,-812,-801,-783,-767,-763,-763,-758,-749,-741,-727,-701,-684,-707,-767,-826,
--852,-847,-836,-827,-812,-792,-778,-770,-755,-729,-705,-690,-674,-647,-610,-574,-539,-504,-473,-455,-448,
--445,-436,-424,-410,-394,-376,-356,-335,-310,-281,-250,-217,-184,-156,-136,-119,-98,-74,-51,-30,-3,
-31,67,103,143,190,236,274,306,341,382,426,471,515,560,605,652,701,751,799,847,895,
-943,988,1030,1073,1118,1165,1212,1259,1308,1356,1398,1432,1460,1484,1506,1527,1552,1580,1608,1634,1663,
-1700,1743,1780,1805,1823,1840,1855,1858,1851,1843,1839,1840,1841,1840,1839,1839,1840,1840,1833,1820,1806,
-1798,1796,1792,1787,1781,1776,1767,1755,1746,1739,1730,1722,1719,1720,1716,1707,1706,1714,1720,1718,1714,
-1715,1718,1716,1714,1721,1733,1740,1739,1735,1726,1713,1700,1692,1683,1661,1625,1586,1554,1521,1472,1409,
-1349,1301,1255,1209,1168,1131,1091,1050,1019,998,977,950,924,904,886,864,844,825,803,780,762,
-753,745,737,734,736,734,724,712,698,672,621,553,493,470,500,562,606,587,513,441,413,
-421,428,423,409,387,351,309,276,253,231,202,164,121,73,29,-11,-65,-142,-236,-331,-417,
--494,-560,-618,-684,-761,-831,-871,-892,-922,-973,-1029,-1080,-1129,-1179,-1228,-1274,-1318,-1355,-1380,-1405,-1446,
--1500,-1544,-1566,-1577,-1589,-1604,-1618,-1633,-1650,-1660,-1661,-1655,-1642,-1624,-1616,-1626,-1632,-1604,-1554,-1522,-1509,
--1465,-1375,-1304,-1328,-1432,-1523,-1532,-1478,-1422,-1409,-1435,-1466,-1470,-1462,-1498,-1607,-1750,-1855,-1899,-1916,-1943,
--1981,-2010,-2015,-1985,-1927,-1877,-1877,-1922,-1956,-1936,-1880,-1833,-1807,-1786,-1781,-1840,-1984,-2158,-2275,-2315,-2358,
--2489,-2690,-2854,-2913,-2924,-2993,-3145,-3305,-3400,-3442,-3491,-3574,-3671,-3753,-3815,-3866,-3914,-3960,-4001,-4031,-4051,
--4071,-4098,-4131,-4159,-4175,-4178,-4177,-4183,-4203,-4230,-4254,-4273,-4289,-4296,-4295,-4302,-4328,-4353,-4349,-4323,-4309,
--4315,-4314,-4293,-4276,-4276,-4269,-4237,-4208,-4208,-4215,-4197,-4177,-4195,-4224,-4202,-4136,-4116,-4189,-4287,-4312,-4259,
--4191,-4149,-4122,-4102,-4099,-4114,-4130,-4148,-4198,-4301,-4440,-4578,-4694,-4789,-4870,-4942,-5008,-5069,-5128,-5190,-5259,
--5330,-5394,-5449,-5502,-5561,-5627,-5694,-5762,-5829,-5892,-5950,-6006,-6070,-6144,-6223,-6297,-6364,-6428,-6493,-6554,-6605,
--6648,-6694,-6748,-6807,-6863,-6915,-6966,-7019,-7073,-7119,-7152,-7176,-7206,-7257,-7328,-7405,-7480,-7561,-7652,-7750,-7845,
--7932,-8014,-8084,-8134,-8158,-8156,-8138,-8129,-8152,-8212,-8285,-8358,-8446,-8571,-8718,-8838,-8903,-8933,-8962,-9001,-9038,
--9066,-9091,-9112,-9124,-9126,-9127,-9132,-9139,-9146,-9159,-9183,-9218,-9260,-9296,-9312,-9306,-9292,-9287,-9292,-9295,-9278,
--9236,-9168,-9081,-8992,-8914,-8842,-8766,-8695,-8657,-8670,-8710,-8731,-8702,-8633,-8553,-8479,-8410,-8329,-8224,-8102,-7979,
--7873,-7790,-7724,-7663,-7597,-7521,-7431,-7330,-7220,-7100,-6972,-6842,-6723,-6628,-6558,-6499,-6433,-6353,-6260,-6158,-6045,
--5922,-5799,-5688,-5581,-5461,-5325,-5182,-5041,-4901,-4766,-4652,-4564,-4481,-4384,-4273,-4150,-3999,-3812,-3623,-3486,-3401,
--3306,-3153,-2965,-2803,-2680,-2561,-2415,-2254,-2109,-1997,-1917,-1865,-1841,-1846,-1875,-1895,-1850,-1706,-1493,-1286,-1130,
--1009,-889,-763,-647,-537,-399,-194,93,435,762,1005,1150,1239,1322,1403,1467,1521,1595,1695,1799,1887,
-1967,2053,2141,2219,2287,2353,2420,2489,2561,2637,2705,2752,2784,2823,2887,2968,3046,3108,3162,3223,3298,
-3380,3458,3532,3610,3695,3782,3867,3950,4032,4112,4187,4265,4347,4422,4475,4507,4538,4589,4650,4691,4695,
-4679,4679,4711,4757,4805,4883,5027,5219,5377,5432,5397,5342,5320,5330,5360,5419,5519,5632,5711,5739,5741,
-5735,5707,5645,5579,5557,5579,5602,5600,5598,5629,5680,5716,5730,5750,5788,5818,5815,5794,5786,5794,5795,
-5766,5715,5661,5616,5578,5556,5558,5559,5481,5250,4885,4520,4315,4326,4486,4689,4885,5100,5363,5652,5873,
-5929,5824,5700,5741,6008,6377,6656,6752,6722,6680,6692,6751,6823,6889,6945,6988,6999,6972,6932,6925,6964,
-7023,7084,7160,7272,7400,7506,7578,7645,7749,7909,8111,8304,8421,8427,8362,8293,8237,8163,8050,7927,7829,
-7753,7669,7554,7403,7223,7040,6894,6815,6799,6827,6895,7011,7171,7351,7523,7662,7758,7823,7883,7947,8003,
-8037,8066,8110,8159,8182,8158,8095,8025,7981,7970,7933,7762,7400,6914,6443,6069,5779,5559,5475,5614,5951,
-6318,6526,6520,6398,6318,6357,6478,6591,6641,6639,6615,6578,6519,6442,6361,6287,6223,6169,6133,6114,6096,
-6061,6003,5936,5871,5811,5748,5681,5619,5563,5506,5439,5364,5290,5222,5161,5107,5059,5011,4957,4903,4854,
-4804,4743,4675,4617,4573,4529,4475,4417,4374,4347,4321,4288,4248,4211,4181,4155,4125,4090,4055,4022,3988,
-3945,3888,3822,3762,3711,3665,3613,3557,3504,3464,3436,3413,3387,3357,3328,3300,3270,3233,3194,3155,3114,
-3061,2999,2944,2916,2918,2925,2902,2844,2786,2756,2746,2718,2661,2601,2567,2559,2550,2521,2478,2435,2398,
-2363,2324,2278,2231,2191,2165,2148,2128,2103,2076,2049,2025,2002,1981,1957,1926,1894,1878,1882,1891,1884,
-1857,1825,1803,1790,1784,1794,1824,1858,1864,1835,1793,1765,1745,1716,1682,1666,1670,1675,1667,1660,1668,
-1680,1681,1674,1677,1690,1700,1702,1703,1700,1689,1676,1673,1681,1684,1676,1676,1696,1718,1713,1679,1646,
-1639,1655,1659,1628,1572,1520,1494,1486,1475,1454,1436,1434,1436,1431,1415,1400,1388,1375,1358,1340,1323,
-1305,1291,1286,1287,1285,1278,1268,1260,1254,1252,1252,1251,1244,1230,1216,1207,1199,1191,1185,1187,1196,
-1199,1183,1149,1110,1082,1076,1084,1093,1090,1077,1059,1043,1027,1011,993,974,953,930,903,875,847,
-823,804,791,784,778,764,738,704,668,636,609,589,575,558,536,509,482,456,429,401,377,
-358,343,327,306,280,251,224,197,170,142,113,86,59,33,9,-13,-38,-65,-94,-123,-154,
--188,-221,-252,-284,-319,-354,-388,-422,-457,-492,-523,-550,-576,-601,-623,-642,-664,-688,-712,-735,-757,
--781,-808,-837,-865,-890,-909,-925,-944,-968,-992,-1015,-1036,-1057,-1073,-1086,-1104,-1131,-1162,-1188,-1205,-1217,
--1232,-1250,-1273,-1298,-1319,-1334,-1346,-1361,-1380,-1402,-1421,-1434,-1441,-1448,-1458,-1472,-1483,-1489,-1494,-1503,-1516,
--1530,-1544,-1558,-1572,-1585,-1598,-1612,-1628,-1643,-1656,-1667,-1674,-1675,-1675,-1676,-1676,-1673,-1666,-1661,-1662,-1666,
--1669,-1668,-1667,-1665,-1662,-1656,-1647,-1638,-1632,-1627,-1621,-1614,-1606,-1595,-1582,-1569,-1561,-1558,-1553,-1541,-1523,
--1504,-1487,-1470,-1454,-1440,-1429,-1423,-1417,-1409,-1402,-1398,-1394,-1390,-1384,-1381,-1380,-1376,-1369,-1361,-1355,-1352,
--1353,-1356,-1361,-1364,-1363,-1364,-1369,-1374,-1377,-1378,-1381,-1385,-1389,-1393,-1399,-1405,-1408,-1409,-1409,-1407,-1404,
--1407,-1418,-1427,-1427,-1421,-1417,-1414,-1408,-1401,-1400,-1402,-1397,-1390,-1390,-1399,-1402,-1394,-1385,-1384,-1382,-1374,
--1368,-1367,-1362,-1350,-1337,-1331,-1324,-1311,-1297,-1285,-1273,-1255,-1235,-1221,-1207,-1187,-1165,-1146,-1126,-1101,-1072,
--1046,-1020,-990,-961,-935,-908,-875,-839,-803,-763,-719,-679,-644,-600,-544,-490,-449,-409,-358,-305,-264,
--227,-178,-128,-86,-43,11,59,79,80,66,-2,-129,-195,-29,376,827,1123,1248,1328,1462,1660,
-1882,2052,2056,1832,1477,1194,1102,1143,1185,1162,1097,1040,1020,1045,1094,1141,1186,1254,1353,1461,1555,
-1648,1754,1855,1927,1970,2008,2050,2081,2094,2099,2110,2128,2147,2158,2153,2120,2062,2000,1960,1952,1957,
-1939,1873,1773,1671,1586,1514,1448,1383,1320,1253,1180,1110,1048,991,925,842,737,606,455,298,150,
-15,-103,-200,-273,-325,-364,-395,-418,-436,-463,-503,-552,-592,-617,-640,-685,-763,-853,-931,-994,-1061,
--1140,-1220,-1286,-1343,-1400,-1459,-1518,-1577,-1640,-1705,-1773,-1846,-1922,-1981,-2009,-2016,-2021,-2038,-2064,-2093,-2119,
--2138,-2149,-2158,-2170,-2180,-2184,-2185,-2192,-2205,-2218,-2229,-2244,-2270,-2312,-2373,-2439,-2481,-2480,-2456,-2446,-2459,
--2477,-2484,-2493,-2523,-2575,-2630,-2670,-2688,-2677,-2640,-2598,-2570,-2555,-2531,-2480,-2410,-2345,-2300,-2271,-2241,-2201,
--2156,-2116,-2076,-2017,-1927,-1816,-1705,-1613,-1541,-1482,-1416,-1330,-1233,-1148,-1086,-1032,-964,-892,-840,-816,-801,
--779,-755,-736,-716,-690,-665,-651,-631,-594,-561,-576,-652,-748,-812,-837,-843,-843,-834,-816,-800,-789,
--774,-749,-724,-708,-691,-665,-632,-603,-577,-548,-516,-493,-485,-483,-478,-467,-453,-437,-418,-395,-371,
--347,-321,-290,-252,-213,-180,-159,-143,-122,-97,-71,-46,-20,10,43,79,121,168,212,246,276,
-312,354,399,443,486,528,571,616,666,721,775,827,878,929,978,1023,1067,1112,1156,1199,1240,
-1282,1323,1360,1391,1420,1449,1476,1501,1527,1556,1586,1614,1643,1678,1715,1746,1766,1782,1802,1823,1838,
-1842,1842,1841,1840,1838,1836,1833,1831,1829,1826,1818,1806,1794,1784,1778,1770,1762,1757,1752,1743,1730,
-1717,1706,1696,1690,1687,1683,1672,1657,1653,1658,1662,1659,1655,1657,1660,1666,1680,1703,1724,1734,1737,
-1739,1734,1718,1700,1683,1679,1643,1599,1562,1543,1518,1463,1385,1315,1265,1225,1185,1146,1105,1057,1011,
-985,977,964,937,907,887,873,853,832,814,793,767,747,739,737,733,727,726,729,733,739,
-747,745,719,668,609,566,564,607,663,686,654,588,529,491,469,455,442,419,384,346,319,
-304,292,278,259,225,171,106,42,-17,-79,-144,-208,-276,-356,-444,-532,-614,-688,-742,-770,-789,
--823,-875,-929,-976,-1024,-1077,-1131,-1183,-1233,-1276,-1305,-1334,-1379,-1436,-1485,-1518,-1544,-1566,-1574,-1569,-1569,
--1586,-1609,-1621,-1618,-1605,-1593,-1593,-1608,-1619,-1603,-1562,-1523,-1493,-1450,-1387,-1344,-1367,-1445,-1517,-1531,-1487,
--1426,-1391,-1398,-1422,-1431,-1431,-1468,-1572,-1713,-1829,-1892,-1919,-1937,-1957,-1980,-1994,-1977,-1930,-1895,-1919,-1983,
--2009,-1955,-1866,-1810,-1797,-1793,-1796,-1855,-1995,-2168,-2294,-2362,-2443,-2596,-2783,-2905,-2927,-2928,-3006,-3161,-3311,
--3399,-3451,-3519,-3613,-3703,-3770,-3819,-3860,-3898,-3937,-3975,-4006,-4026,-4044,-4069,-4101,-4130,-4148,-4155,-4160,-4173,
--4194,-4212,-4221,-4226,-4235,-4246,-4250,-4256,-4275,-4296,-4297,-4283,-4276,-4277,-4266,-4243,-4232,-4238,-4229,-4195,-4169,
--4169,-4160,-4123,-4110,-4162,-4223,-4192,-4083,-4028,-4109,-4257,-4347,-4345,-4299,-4247,-4194,-4155,-4149,-4163,-4161,-4145,
--4162,-4241,-4363,-4488,-4600,-4700,-4790,-4870,-4941,-5006,-5065,-5121,-5185,-5260,-5333,-5391,-5439,-5494,-5561,-5635,-5707,
--5773,-5831,-5883,-5939,-6007,-6084,-6160,-6229,-6295,-6362,-6428,-6489,-6542,-6593,-6646,-6698,-6750,-6801,-6852,-6905,-6956,
--7003,-7043,-7073,-7101,-7138,-7194,-7265,-7339,-7413,-7493,-7584,-7683,-7779,-7867,-7946,-8008,-8043,-8042,-8010,-7972,-7970,
--8026,-8122,-8218,-8303,-8407,-8549,-8694,-8790,-8831,-8859,-8904,-8954,-8988,-9012,-9039,-9064,-9076,-9075,-9076,-9081,-9087,
--9094,-9111,-9140,-9176,-9212,-9240,-9251,-9244,-9234,-9233,-9238,-9234,-9215,-9178,-9123,-9048,-8965,-8888,-8818,-8746,-8682,
--8653,-8671,-8707,-8716,-8676,-8600,-8515,-8435,-8358,-8271,-8164,-8044,-7929,-7832,-7755,-7690,-7628,-7563,-7489,-7401,-7303,
--7197,-7083,-6959,-6831,-6710,-6611,-6535,-6474,-6414,-6344,-6263,-6170,-6063,-5939,-5808,-5685,-5571,-5449,-5313,-5177,-5059,
--4953,-4847,-4740,-4641,-4549,-4451,-4339,-4202,-4030,-3829,-3646,-3524,-3448,-3349,-3187,-2999,-2847,-2738,-2627,-2487,-2330,
--2187,-2068,-1974,-1898,-1840,-1806,-1809,-1839,-1847,-1770,-1602,-1395,-1204,-1042,-903,-801,-753,-738,-693,-550,-274,
-110,520,852,1054,1162,1247,1341,1430,1502,1576,1668,1768,1859,1942,2027,2112,2186,2248,2311,2381,2456,
-2529,2599,2664,2721,2770,2823,2887,2957,3025,3083,3136,3191,3255,3327,3401,3475,3549,3623,3699,3779,3865,
-3959,4054,4141,4215,4276,4328,4376,4423,4470,4519,4569,4617,4658,4696,4737,4776,4801,4816,4861,4970,5129,
-5265,5321,5298,5244,5197,5174,5191,5272,5409,5545,5622,5635,5620,5608,5599,5588,5594,5626,5656,5648,5605,
-5577,5596,5639,5665,5666,5673,5701,5733,5747,5751,5762,5779,5774,5731,5667,5616,5580,5533,5471,5430,5421,
-5367,5145,4729,4266,3973,3951,4135,4395,4671,4982,5340,5684,5888,5869,5686,5539,5619,5946,6352,6637,6733,
-6712,6680,6697,6762,6851,6940,7012,7057,7065,7032,6980,6947,6953,6986,7029,7085,7166,7260,7349,7434,7537,
-7671,7837,8028,8219,8365,8430,8427,8405,8386,8356,8304,8239,8167,8083,7985,7881,7750,7547,7264,6972,6761,
-6664,6649,6683,6766,6908,7098,7298,7469,7598,7704,7813,7921,7995,8026,8049,8102,8172,8212,8204,8172,8142,
-8110,8037,7867,7548,7074,6536,6074,5774,5613,5531,5531,5681,6003,6388,6645,6661,6495,6325,6295,6402,6541,
-6619,6622,6583,6530,6463,6385,6310,6249,6201,6165,6144,6137,6128,6099,6047,5985,5929,5876,5814,5743,5676,
-5621,5568,5505,5434,5363,5297,5231,5167,5109,5053,4991,4929,4877,4833,4786,4730,4674,4626,4580,4527,4472,
-4422,4382,4347,4311,4277,4245,4217,4189,4155,4114,4072,4037,4004,3961,3906,3848,3796,3747,3695,3637,3581,
-3535,3502,3480,3462,3442,3415,3386,3355,3320,3279,3240,3207,3171,3125,3075,3036,3011,2990,2955,2904,2848,
-2802,2773,2752,2720,2671,2616,2578,2566,2567,2554,2517,2465,2418,2385,2355,2318,2272,2229,2198,2173,2147,
-2119,2090,2062,2031,2002,1979,1959,1936,1911,1889,1873,1862,1856,1857,1857,1846,1820,1793,1784,1794,1806,
-1803,1787,1770,1755,1737,1713,1696,1697,1703,1696,1679,1672,1682,1692,1687,1677,1681,1698,1711,1712,1712,
-1714,1710,1698,1685,1673,1660,1650,1657,1684,1710,1704,1666,1628,1619,1634,1643,1617,1565,1517,1494,1487,
-1473,1451,1434,1430,1431,1424,1412,1401,1387,1366,1340,1317,1299,1282,1268,1262,1263,1264,1259,1248,1236,
-1230,1236,1247,1250,1234,1205,1180,1167,1159,1149,1141,1142,1153,1162,1158,1138,1104,1068,1047,1046,1055,
-1056,1042,1024,1011,1000,983,959,933,909,884,854,824,798,778,759,742,731,726,718,702,676,
-646,618,594,575,560,544,523,497,470,441,411,382,358,340,324,307,286,262,236,211,190,
-168,145,121,96,71,44,16,-10,-38,-69,-99,-127,-154,-185,-218,-253,-287,-319,-350,-379,-409,
--443,-480,-516,-548,-576,-601,-624,-646,-667,-690,-711,-733,-755,-778,-802,-829,-856,-881,-899,-914,-932,
--952,-973,-994,-1015,-1036,-1053,-1069,-1089,-1116,-1147,-1173,-1193,-1208,-1223,-1242,-1265,-1289,-1310,-1325,-1337,-1351,
--1369,-1391,-1412,-1426,-1433,-1436,-1441,-1450,-1459,-1465,-1471,-1481,-1494,-1507,-1520,-1533,-1545,-1556,-1568,-1582,-1596,
--1610,-1623,-1635,-1643,-1644,-1645,-1648,-1651,-1648,-1638,-1630,-1630,-1635,-1637,-1636,-1634,-1634,-1632,-1626,-1617,-1607,
--1599,-1593,-1587,-1581,-1574,-1566,-1555,-1543,-1533,-1524,-1514,-1500,-1483,-1465,-1450,-1436,-1422,-1407,-1395,-1388,-1383,
--1377,-1371,-1367,-1366,-1363,-1356,-1350,-1347,-1344,-1339,-1333,-1329,-1327,-1328,-1332,-1337,-1339,-1340,-1342,-1348,-1354,
--1355,-1353,-1355,-1360,-1367,-1376,-1386,-1396,-1403,-1410,-1414,-1411,-1403,-1399,-1407,-1418,-1419,-1412,-1407,-1406,-1403,
--1399,-1399,-1400,-1396,-1388,-1389,-1397,-1401,-1393,-1386,-1385,-1385,-1378,-1370,-1367,-1363,-1353,-1343,-1336,-1329,-1316,
--1303,-1293,-1282,-1263,-1243,-1227,-1213,-1194,-1173,-1156,-1138,-1114,-1085,-1058,-1031,-1001,-972,-946,-920,-887,-851,
--815,-776,-733,-691,-652,-607,-553,-503,-465,-427,-379,-326,-281,-237,-187,-138,-96,-50,2,38,48,
-52,49,-15,-153,-234,-80,321,771,1060,1162,1196,1281,1474,1767,2058,2157,1947,1547,1226,1149,1239,
-1317,1292,1200,1111,1064,1063,1096,1142,1194,1266,1362,1460,1546,1635,1739,1838,1900,1930,1962,2013,2070,
-2111,2136,2156,2171,2181,2188,2189,2174,2135,2080,2038,2024,2024,1998,1925,1824,1729,1654,1586,1512,1438,
-1369,1302,1234,1167,1104,1038,959,865,755,633,504,372,239,107,-17,-122,-199,-252,-289,-315,-338,
--370,-417,-475,-535,-587,-630,-665,-706,-763,-834,-908,-981,-1062,-1147,-1218,-1262,-1291,-1327,-1376,-1431,-1486,
--1542,-1607,-1682,-1768,-1854,-1924,-1968,-1996,-2023,-2053,-2079,-2101,-2120,-2136,-2147,-2154,-2165,-2177,-2184,-2186,-2190,
--2199,-2211,-2225,-2243,-2269,-2302,-2347,-2398,-2436,-2448,-2448,-2461,-2491,-2513,-2515,-2512,-2527,-2562,-2604,-2642,-2666,
--2667,-2641,-2602,-2567,-2537,-2497,-2440,-2381,-2331,-2294,-2261,-2225,-2186,-2151,-2122,-2087,-2028,-1934,-1817,-1702,-1604,
--1527,-1462,-1395,-1313,-1226,-1152,-1102,-1056,-994,-921,-862,-826,-799,-767,-736,-712,-687,-652,-618,-594,-568,
--526,-489,-505,-590,-704,-789,-825,-831,-827,-819,-808,-800,-796,-785,-764,-741,-726,-710,-685,-655,-630,
--613,-592,-564,-539,-526,-524,-520,-510,-496,-479,-458,-432,-407,-383,-360,-332,-294,-252,-216,-190,-168,
--145,-117,-89,-62,-35,-5,27,65,108,154,195,229,263,300,341,382,423,465,507,547,588,
-636,692,749,802,854,906,959,1010,1059,1108,1154,1196,1233,1269,1303,1334,1362,1391,1422,1453,1480,
-1504,1531,1561,1591,1618,1647,1676,1702,1722,1743,1771,1803,1830,1846,1851,1848,1839,1828,1820,1817,1815,
-1812,1807,1801,1792,1783,1772,1759,1746,1734,1727,1719,1707,1692,1678,1666,1658,1653,1648,1638,1621,1605,
-1599,1602,1604,1604,1609,1619,1631,1648,1674,1705,1727,1737,1744,1752,1749,1730,1705,1679,1669,1624,1573,
-1543,1537,1517,1449,1351,1273,1229,1199,1166,1130,1089,1037,986,960,958,951,924,891,872,861,842,
-818,797,778,755,735,728,730,729,723,720,724,731,743,760,774,773,752,716,679,664,692,
-753,809,816,766,686,608,550,514,488,459,423,392,376,368,361,353,342,314,259,184,110,
-48,-2,-45,-87,-141,-223,-329,-436,-528,-597,-641,-669,-698,-743,-796,-843,-881,-920,-967,-1020,-1074,
--1125,-1166,-1197,-1233,-1291,-1364,-1429,-1476,-1514,-1542,-1547,-1531,-1518,-1529,-1555,-1574,-1576,-1571,-1567,-1569,-1579,
--1590,-1588,-1566,-1529,-1480,-1420,-1364,-1341,-1368,-1429,-1485,-1505,-1481,-1425,-1374,-1359,-1378,-1402,-1423,-1468,-1562,
--1687,-1800,-1875,-1912,-1922,-1921,-1928,-1946,-1951,-1933,-1927,-1968,-2029,-2038,-1971,-1880,-1828,-1815,-1809,-1813,-1872,
--2005,-2166,-2296,-2395,-2512,-2673,-2833,-2923,-2943,-2969,-3064,-3204,-3320,-3388,-3451,-3544,-3649,-3729,-3777,-3810,-3843,
--3878,-3914,-3949,-3975,-3991,-4008,-4035,-4068,-4098,-4118,-4131,-4141,-4154,-4169,-4181,-4186,-4191,-4205,-4218,-4218,-4207,
--4204,-4216,-4229,-4236,-4237,-4229,-4206,-4181,-4177,-4186,-4176,-4146,-4129,-4130,-4110,-4068,-4068,-4145,-4212,-4157,-4011,
--3929,-4004,-4167,-4291,-4332,-4320,-4284,-4242,-4226,-4249,-4270,-4242,-4188,-4181,-4249,-4351,-4441,-4521,-4607,-4697,-4781,
--4860,-4937,-5003,-5056,-5114,-5188,-5265,-5327,-5375,-5430,-5502,-5581,-5653,-5714,-5767,-5818,-5875,-5946,-6021,-6092,-6156,
--6220,-6290,-6359,-6422,-6481,-6538,-6592,-6640,-6686,-6734,-6788,-6840,-6884,-6921,-6957,-6993,-7030,-7073,-7128,-7191,-7260,
--7336,-7425,-7524,-7622,-7715,-7799,-7872,-7924,-7946,-7931,-7886,-7839,-7836,-7901,-8010,-8120,-8225,-8357,-8520,-8661,-8732,
--8753,-8783,-8842,-8899,-8927,-8944,-8970,-8996,-9007,-9008,-9012,-9021,-9028,-9036,-9056,-9086,-9118,-9144,-9164,-9171,-9163,
--9154,-9156,-9161,-9154,-9132,-9099,-9053,-8988,-8912,-8843,-8785,-8727,-8675,-8653,-8665,-8683,-8673,-8625,-8556,-8480,-8403,
--8321,-8224,-8108,-7983,-7870,-7781,-7712,-7651,-7591,-7531,-7462,-7378,-7281,-7176,-7062,-6936,-6804,-6678,-6571,-6487,-6427,
--6379,-6327,-6259,-6175,-6074,-5956,-5826,-5699,-5579,-5450,-5306,-5168,-5066,-4994,-4919,-4820,-4707,-4600,-4500,-4391,-4250,
--4068,-3864,-3689,-3579,-3505,-3395,-3224,-3042,-2907,-2812,-2705,-2563,-2410,-2273,-2152,-2037,-1930,-1837,-1768,-1741,-1758,
--1784,-1761,-1661,-1501,-1316,-1128,-962,-859,-842,-878,-892,-810,-585,-219,219,616,881,1021,1115,1224,1346,
-1455,1548,1642,1740,1830,1910,1991,2073,2148,2214,2280,2352,2426,2495,2557,2619,2684,2752,2817,2876,2931,
-2987,3047,3106,3160,3213,3274,3344,3419,3490,3558,3629,3706,3793,3886,3984,4075,4146,4195,4237,4287,4351,
-4412,4458,4494,4540,4606,4680,4743,4778,4787,4791,4820,4891,4992,5094,5168,5196,5168,5095,5025,5025,5125,
-5285,5422,5488,5495,5481,5466,5456,5472,5533,5623,5685,5676,5620,5577,5578,5600,5608,5596,5587,5596,5618,
-5642,5667,5691,5700,5679,5627,5573,5542,5523,5478,5397,5331,5311,5264,5046,4606,4091,3737,3675,3851,4145,
-4492,4890,5310,5652,5797,5710,5513,5422,5586,5961,6356,6608,6696,6699,6696,6719,6773,6858,6955,7041,7100,
-7126,7114,7071,7024,7002,7010,7039,7082,7136,7193,7252,7328,7432,7555,7686,7830,7992,8150,8270,8346,8392,
-8420,8424,8408,8384,8344,8279,8206,8146,8069,7894,7587,7227,6939,6778,6710,6690,6716,6806,6951,7109,7247,
-7370,7513,7692,7870,7985,8026,8051,8116,8205,8260,8260,8240,8214,8139,7944,7600,7134,6615,6132,5770,5569,
-5499,5498,5554,5723,6047,6456,6775,6852,6697,6476,6357,6382,6469,6529,6537,6508,6458,6388,6306,6234,6181,
-6146,6126,6123,6132,6133,6107,6056,5999,5951,5907,5852,5784,5718,5662,5609,5549,5486,5427,5369,5304,5234,
-5170,5112,5050,4980,4915,4863,4820,4777,4730,4680,4629,4577,4527,4478,4429,4384,4350,4323,4295,4261,4223,
-4186,4146,4104,4064,4024,3978,3926,3875,3829,3781,3729,3677,3633,3596,3564,3536,3513,3486,3453,3417,3382,
-3345,3304,3265,3233,3204,3174,3153,3145,3130,3077,2991,2911,2866,2846,2822,2782,2734,2685,2636,2598,2585,
-2595,2599,2567,2502,2438,2397,2372,2345,2306,2266,2232,2198,2164,2133,2107,2081,2049,2015,1987,1966,1945,
-1922,1895,1868,1847,1848,1874,1899,1890,1845,1796,1774,1778,1787,1787,1784,1779,1766,1741,1720,1718,1731,
-1736,1719,1693,1683,1690,1696,1688,1677,1680,1696,1709,1715,1721,1732,1738,1727,1700,1667,1638,1625,1636,
-1666,1689,1684,1648,1606,1581,1576,1575,1562,1540,1520,1508,1497,1476,1451,1436,1432,1426,1409,1390,1374,
-1358,1336,1309,1285,1264,1246,1232,1227,1230,1235,1233,1225,1215,1216,1232,1251,1253,1225,1185,1157,1148,
-1142,1130,1119,1117,1121,1124,1124,1119,1101,1071,1041,1031,1034,1031,1013,990,975,964,944,913,879,
-852,827,801,776,760,748,732,710,689,676,669,659,641,617,593,572,555,541,526,507,484,
-456,426,395,369,348,328,309,291,274,254,230,205,182,161,139,117,96,75,51,25,-2,
--32,-67,-102,-132,-157,-184,-217,-255,-291,-322,-348,-373,-400,-432,-470,-508,-545,-576,-603,-626,-649,
--672,-693,-713,-733,-754,-776,-799,-824,-850,-875,-894,-910,-925,-942,-959,-977,-998,-1019,-1039,-1057,-1079,
--1105,-1133,-1157,-1176,-1193,-1211,-1232,-1256,-1279,-1299,-1313,-1327,-1344,-1362,-1383,-1404,-1420,-1428,-1430,-1432,-1438,
--1447,-1453,-1458,-1466,-1476,-1486,-1498,-1509,-1520,-1530,-1542,-1555,-1567,-1577,-1588,-1600,-1608,-1610,-1613,-1620,-1629,
--1628,-1617,-1606,-1603,-1605,-1604,-1601,-1598,-1599,-1598,-1594,-1586,-1577,-1568,-1560,-1553,-1548,-1542,-1536,-1528,-1518,
--1506,-1493,-1478,-1461,-1442,-1424,-1411,-1401,-1392,-1379,-1366,-1357,-1353,-1348,-1343,-1340,-1339,-1337,-1331,-1323,-1316,
--1313,-1309,-1305,-1303,-1303,-1305,-1309,-1314,-1318,-1319,-1323,-1329,-1335,-1337,-1337,-1339,-1344,-1351,-1361,-1373,-1385,
--1396,-1405,-1412,-1411,-1401,-1394,-1398,-1406,-1408,-1402,-1397,-1397,-1397,-1394,-1395,-1397,-1394,-1387,-1388,-1396,-1399,
--1393,-1387,-1387,-1387,-1380,-1371,-1365,-1361,-1354,-1347,-1341,-1333,-1318,-1304,-1296,-1287,-1270,-1250,-1234,-1219,-1201,
--1182,-1164,-1147,-1123,-1095,-1067,-1040,-1009,-981,-956,-929,-895,-858,-824,-788,-746,-701,-658,-614,-566,-521,
--482,-442,-392,-341,-296,-250,-200,-154,-113,-68,-18,13,21,32,41,-13,-156,-264,-151,218,666,
-979,1096,1099,1115,1250,1543,1887,2052,1894,1539,1278,1267,1400,1478,1427,1306,1196,1129,1111,1135,1181,
-1232,1291,1365,1450,1538,1631,1731,1816,1862,1883,1919,1989,2072,2137,2175,2194,2204,2209,2215,2222,2221,
-2200,2163,2131,2119,2110,2072,1991,1891,1805,1735,1659,1571,1483,1408,1345,1283,1221,1159,1087,997,890,
-775,661,550,437,314,183,58,-42,-114,-166,-204,-230,-254,-293,-353,-425,-495,-558,-613,-656,-691,
--730,-785,-853,-932,-1021,-1114,-1187,-1226,-1244,-1269,-1313,-1364,-1412,-1463,-1528,-1614,-1713,-1810,-1885,-1936,-1975,
--2014,-2051,-2079,-2099,-2119,-2137,-2148,-2153,-2160,-2170,-2177,-2181,-2186,-2195,-2204,-2217,-2237,-2261,-2290,-2326,-2367,
--2401,-2418,-2432,-2461,-2499,-2522,-2521,-2516,-2529,-2559,-2593,-2623,-2646,-2649,-2628,-2592,-2555,-2514,-2460,-2399,-2351,
--2319,-2293,-2257,-2214,-2175,-2146,-2120,-2084,-2021,-1929,-1816,-1701,-1595,-1507,-1433,-1365,-1292,-1215,-1155,-1117,-1082,
--1024,-947,-875,-824,-785,-747,-715,-692,-671,-639,-604,-575,-548,-512,-482,-497,-574,-684,-773,-814,-818,
--808,-797,-791,-792,-796,-794,-780,-761,-746,-732,-711,-685,-664,-650,-634,-612,-589,-574,-568,-563,-552,
--535,-514,-490,-464,-440,-419,-398,-371,-337,-299,-264,-232,-203,-173,-141,-110,-81,-54,-23,12,51,
-92,133,172,212,251,290,328,366,406,450,493,532,570,614,666,723,776,827,878,931,986,
-1040,1094,1146,1192,1230,1264,1294,1323,1349,1375,1402,1431,1455,1476,1499,1528,1560,1590,1617,1644,1671,
-1696,1721,1753,1789,1823,1846,1852,1844,1827,1808,1796,1792,1793,1792,1788,1782,1775,1764,1748,1729,1710,
-1695,1684,1671,1655,1640,1629,1622,1618,1613,1606,1592,1576,1566,1567,1573,1578,1587,1604,1625,1644,1665,
-1692,1718,1732,1738,1748,1757,1751,1728,1700,1669,1652,1606,1552,1528,1533,1510,1421,1302,1221,1192,1176,
-1149,1115,1079,1032,979,947,940,933,905,874,858,850,829,800,776,760,743,726,719,722,724,
-722,721,725,730,738,753,773,787,790,780,767,766,797,864,937,969,935,851,753,672,615,
-574,535,495,464,447,439,434,431,425,399,345,270,196,134,87,51,19,-27,-106,-209,-315,
--403,-469,-519,-562,-610,-667,-722,-764,-793,-821,-858,-903,-956,-1010,-1057,-1095,-1141,-1214,-1303,-1381,-1435,
--1476,-1508,-1520,-1509,-1493,-1497,-1517,-1535,-1541,-1542,-1543,-1545,-1551,-1561,-1570,-1568,-1542,-1485,-1408,-1341,-1312,
--1324,-1358,-1393,-1419,-1419,-1387,-1343,-1327,-1352,-1394,-1433,-1484,-1566,-1673,-1774,-1848,-1888,-1895,-1881,-1872,-1882,
--1901,-1921,-1955,-2012,-2061,-2054,-1992,-1923,-1881,-1853,-1826,-1828,-1898,-2030,-2173,-2294,-2406,-2542,-2697,-2829,-2908,
--2956,-3026,-3139,-3256,-3333,-3382,-3451,-3556,-3664,-3734,-3768,-3790,-3817,-3852,-3890,-3922,-3942,-3952,-3969,-3996,-4026,
--4048,-4065,-4080,-4096,-4110,-4126,-4143,-4159,-4176,-4199,-4219,-4214,-4186,-4161,-4163,-4186,-4206,-4206,-4182,-4146,-4122,
--4124,-4133,-4122,-4096,-4086,-4089,-4070,-4037,-4052,-4126,-4167,-4086,-3938,-3870,-3945,-4084,-4190,-4240,-4257,-4251,-4242,
--4271,-4337,-4369,-4316,-4236,-4227,-4302,-4385,-4427,-4457,-4517,-4601,-4686,-4771,-4860,-4937,-4993,-5047,-5119,-5199,-5263,
--5314,-5373,-5450,-5529,-5595,-5650,-5700,-5753,-5814,-5883,-5956,-6022,-6081,-6144,-6215,-6287,-6352,-6413,-6471,-6525,-6571,
--6617,-6668,-6721,-6768,-6803,-6837,-6876,-6920,-6964,-7007,-7054,-7106,-7172,-7258,-7359,-7464,-7560,-7649,-7732,-7799,-7836,
--7838,-7810,-7761,-7715,-7709,-7768,-7877,-8001,-8132,-8292,-8467,-8599,-8651,-8662,-8699,-8770,-8829,-8852,-8863,-8887,-8911,
--8918,-8918,-8928,-8942,-8950,-8958,-8981,-9013,-9040,-9060,-9076,-9082,-9075,-9067,-9070,-9075,-9065,-9038,-9004,-8962,-8904,
--8838,-8781,-8738,-8698,-8661,-8642,-8640,-8634,-8604,-8554,-8497,-8436,-8365,-8279,-8173,-8048,-7918,-7806,-7727,-7668,-7613,
--7556,-7498,-7435,-7357,-7265,-7161,-7041,-6906,-6766,-6635,-6525,-6439,-6382,-6346,-6310,-6255,-6178,-6083,-5973,-5852,-5730,
--5608,-5473,-5319,-5173,-5074,-5019,-4964,-4871,-4746,-4626,-4526,-4428,-4302,-4131,-3937,-3769,-3657,-3568,-3442,-3263,-3090,
--2975,-2896,-2790,-2640,-2482,-2348,-2229,-2100,-1964,-1840,-1748,-1697,-1689,-1704,-1709,-1676,-1591,-1453,-1272,-1088,-964,
--933,-969,-1005,-977,-829,-528,-107,323,646,829,943,1067,1216,1361,1486,1602,1714,1809,1882,1947,2020,
-2100,2177,2249,2319,2390,2457,2517,2575,2639,2707,2771,2824,2868,2918,2980,3049,3112,3168,3229,3300,3375,
-3446,3513,3586,3666,3746,3826,3909,3993,4066,4120,4163,4216,4283,4348,4394,4424,4465,4534,4618,4683,4711,
-4716,4728,4758,4793,4832,4897,4998,5094,5112,5035,4940,4931,5033,5177,5277,5318,5333,5343,5334,5311,5321,
-5401,5527,5623,5643,5609,5575,5564,5560,5546,5521,5501,5493,5501,5523,5552,5570,5563,5529,5482,5441,5419,
-5406,5372,5310,5252,5220,5147,4907,4459,3943,3583,3508,3680,3996,4387,4816,5217,5488,5554,5452,5332,5370,
-5636,6030,6377,6574,6649,6680,6709,6741,6783,6851,6936,7012,7064,7095,7101,7074,7024,6981,6973,7001,7054,
-7114,7169,7221,7287,7371,7456,7530,7612,7726,7865,8004,8124,8224,8293,8321,8324,8326,8325,8306,8278,8264,
-8240,8127,7881,7563,7280,7082,6949,6861,6837,6889,6984,7062,7104,7149,7263,7458,7672,7823,7897,7962,8077,
-8215,8296,8288,8219,8112,7923,7595,7138,6644,6212,5895,5692,5574,5507,5468,5479,5608,5916,6361,6782,6996,
-6950,6753,6563,6458,6422,6413,6408,6394,6356,6290,6215,6152,6105,6070,6052,6060,6087,6103,6086,6043,5995,
-5956,5920,5870,5805,5739,5679,5623,5565,5512,5469,5425,5368,5299,5233,5174,5115,5047,4974,4909,4859,4819,
-4780,4732,4675,4621,4574,4527,4475,4428,4398,4380,4353,4310,4262,4223,4187,4147,4102,4055,4004,3952,3906,
-3864,3819,3770,3728,3696,3667,3634,3601,3570,3534,3488,3441,3404,3371,3333,3296,3263,3231,3200,3192,3209,
-3213,3159,3056,2971,2945,2945,2914,2844,2769,2714,2672,2638,2625,2641,2655,2626,2551,2468,2414,2386,2361,
-2327,2292,2259,2225,2187,2154,2129,2101,2068,2034,2009,1989,1966,1940,1913,1884,1862,1866,1902,1937,1926,
-1865,1800,1776,1790,1813,1825,1830,1826,1803,1765,1737,1737,1752,1754,1733,1705,1690,1689,1689,1684,1678,
-1680,1690,1701,1713,1729,1747,1757,1746,1712,1667,1627,1610,1618,1641,1657,1654,1630,1593,1555,1524,1509,
-1509,1517,1523,1519,1500,1473,1451,1442,1438,1424,1396,1362,1333,1310,1288,1267,1246,1225,1205,1192,1189,
-1195,1201,1203,1199,1193,1196,1215,1234,1231,1198,1158,1139,1139,1137,1123,1111,1106,1101,1092,1086,1091,
-1091,1072,1042,1022,1017,1010,986,957,937,923,901,865,828,800,778,757,740,729,723,708,680,
-650,628,618,610,598,580,560,542,527,515,502,486,465,440,412,386,365,346,325,304,286,
-269,250,223,193,164,138,115,94,77,62,46,28,7,-20,-57,-96,-131,-157,-182,-213,-251,
--290,-322,-348,-372,-398,-429,-466,-505,-543,-576,-605,-629,-653,-676,-698,-718,-737,-756,-776,-797,-821,
--847,-873,-894,-911,-926,-940,-954,-969,-989,-1011,-1031,-1050,-1071,-1095,-1118,-1139,-1158,-1175,-1195,-1218,-1243,
--1266,-1284,-1299,-1316,-1337,-1358,-1377,-1395,-1411,-1421,-1424,-1427,-1435,-1444,-1451,-1454,-1458,-1465,-1474,-1483,-1492,
--1501,-1510,-1521,-1534,-1542,-1548,-1554,-1564,-1572,-1574,-1577,-1588,-1601,-1604,-1595,-1583,-1578,-1577,-1574,-1570,-1567,
--1567,-1565,-1561,-1555,-1548,-1539,-1529,-1522,-1516,-1511,-1506,-1499,-1490,-1478,-1464,-1446,-1426,-1404,-1385,-1372,-1364,
--1358,-1349,-1337,-1328,-1324,-1320,-1316,-1313,-1312,-1310,-1305,-1297,-1290,-1284,-1279,-1276,-1276,-1279,-1282,-1286,-1292,
--1299,-1304,-1307,-1312,-1317,-1323,-1327,-1332,-1337,-1342,-1351,-1362,-1374,-1384,-1393,-1399,-1400,-1394,-1387,-1388,-1393,
--1394,-1389,-1386,-1387,-1388,-1388,-1389,-1390,-1388,-1384,-1385,-1391,-1394,-1391,-1387,-1387,-1386,-1379,-1370,-1363,-1357,
--1351,-1347,-1343,-1335,-1319,-1304,-1296,-1288,-1273,-1256,-1241,-1226,-1209,-1190,-1173,-1154,-1129,-1101,-1075,-1048,-1019,
--991,-966,-937,-901,-864,-831,-799,-759,-714,-670,-627,-583,-540,-498,-451,-399,-350,-308,-265,-217,-173,
--136,-93,-42,-6,3,13,24,-22,-159,-282,-211,114,556,905,1059,1055,1014,1076,1316,1643,1833,
-1752,1521,1396,1478,1632,1677,1581,1434,1313,1234,1196,1200,1231,1267,1303,1358,1437,1532,1630,1721,1787,
-1821,1844,1891,1977,2075,2151,2193,2212,2223,2233,2247,2261,2266,2254,2231,2213,2207,2193,2145,2061,1968,
-1888,1814,1725,1620,1523,1448,1389,1330,1270,1208,1132,1036,924,811,706,604,495,372,245,131,47,
--9,-55,-97,-133,-169,-221,-294,-374,-446,-509,-565,-611,-646,-682,-732,-797,-872,-957,-1049,-1127,-1174,
--1198,-1226,-1272,-1325,-1374,-1423,-1490,-1581,-1686,-1784,-1857,-1909,-1952,-1996,-2036,-2064,-2084,-2104,-2125,-2138,-2144,
--2149,-2155,-2161,-2167,-2175,-2185,-2194,-2205,-2222,-2245,-2273,-2307,-2346,-2376,-2391,-2403,-2429,-2463,-2486,-2491,-2498,
--2522,-2554,-2581,-2602,-2615,-2612,-2588,-2554,-2521,-2479,-2420,-2356,-2312,-2294,-2280,-2251,-2211,-2174,-2145,-2114,-2068,
--2000,-1914,-1813,-1703,-1592,-1489,-1405,-1333,-1264,-1198,-1151,-1127,-1102,-1045,-956,-867,-803,-763,-732,-706,-683,
--659,-625,-588,-558,-535,-512,-493,-504,-564,-660,-752,-809,-824,-814,-797,-786,-787,-796,-802,-797,-785,
--771,-759,-744,-724,-705,-689,-674,-656,-637,-623,-615,-608,-595,-575,-551,-525,-499,-477,-457,-434,-406,
--374,-341,-310,-278,-243,-207,-170,-135,-102,-73,-42,-7,30,67,103,142,187,233,272,306,342,
-384,429,472,510,547,591,645,706,764,817,866,916,969,1022,1075,1126,1172,1210,1241,1269,1298,
-1325,1351,1376,1401,1424,1444,1465,1494,1531,1567,1598,1628,1658,1686,1711,1738,1772,1806,1829,1835,1825,
-1807,1787,1772,1766,1767,1766,1760,1751,1739,1724,1703,1680,1660,1646,1634,1620,1605,1596,1593,1593,1592,
-1587,1577,1563,1552,1552,1563,1575,1586,1603,1629,1655,1676,1693,1711,1723,1726,1728,1738,1743,1727,1699,
-1677,1652,1641,1597,1540,1519,1529,1500,1392,1257,1178,1164,1158,1127,1088,1058,1022,976,941,927,918,
-893,864,851,843,820,786,760,745,733,718,711,714,718,720,723,726,727,730,743,765,785,
-798,807,820,848,898,972,1047,1086,1065,992,897,811,747,699,654,606,559,524,508,508,517,
-518,493,438,366,297,237,187,148,114,70,2,-85,-171,-247,-316,-386,-456,-523,-586,-642,-686,
--716,-738,-762,-796,-846,-910,-974,-1031,-1094,-1176,-1267,-1340,-1387,-1422,-1458,-1485,-1492,-1488,-1489,-1499,-1507,
--1509,-1509,-1514,-1527,-1543,-1560,-1574,-1580,-1564,-1512,-1429,-1344,-1285,-1256,-1249,-1260,-1289,-1317,-1320,-1307,-1311,
--1349,-1398,-1436,-1477,-1547,-1640,-1730,-1797,-1836,-1847,-1836,-1821,-1822,-1846,-1892,-1961,-2034,-2074,-2059,-2013,-1973,
--1939,-1891,-1846,-1855,-1944,-2075,-2198,-2303,-2421,-2560,-2698,-2804,-2881,-2959,-3063,-3184,-3283,-3340,-3381,-3449,-3550,
--3651,-3717,-3749,-3769,-3793,-3826,-3863,-3894,-3909,-3918,-3933,-3959,-3979,-3989,-3999,-4018,-4044,-4070,-4096,-4122,-4144,
--4164,-4188,-4211,-4212,-4183,-4152,-4148,-4171,-4188,-4176,-4136,-4095,-4077,-4083,-4088,-4072,-4046,-4036,-4036,-4023,-4010,
--4036,-4088,-4088,-4000,-3903,-3900,-3985,-4073,-4117,-4145,-4177,-4196,-4213,-4276,-4371,-4409,-4342,-4259,-4273,-4368,-4435,
--4426,-4406,-4438,-4514,-4596,-4683,-4780,-4868,-4930,-4982,-5053,-5134,-5199,-5252,-5316,-5395,-5471,-5529,-5579,-5631,-5688,
--5750,-5818,-5888,-5952,-6012,-6073,-6142,-6212,-6276,-6336,-6394,-6448,-6497,-6545,-6597,-6647,-6688,-6722,-6761,-6807,-6855,
--6897,-6934,-6972,-7020,-7088,-7182,-7292,-7397,-7488,-7575,-7662,-7729,-7748,-7722,-7674,-7625,-7589,-7588,-7646,-7756,-7893,
--8045,-8217,-8389,-8508,-8551,-8565,-8612,-8691,-8749,-8769,-8780,-8805,-8826,-8828,-8827,-8840,-8857,-8863,-8869,-8892,-8925,
--8950,-8965,-8979,-8986,-8982,-8975,-8979,-8985,-8972,-8939,-8902,-8863,-8812,-8752,-8700,-8664,-8633,-8605,-8586,-8575,-8553,
--8514,-8466,-8419,-8367,-8299,-8212,-8107,-7986,-7859,-7754,-7684,-7635,-7585,-7527,-7466,-7403,-7330,-7246,-7145,-7018,-6869,
--6717,-6585,-6481,-6403,-6352,-6325,-6303,-6260,-6188,-6095,-5991,-5880,-5765,-5649,-5516,-5359,-5205,-5094,-5033,-4979,-4887,
--4761,-4638,-4542,-4459,-4355,-4208,-4028,-3859,-3732,-3625,-3484,-3302,-3134,-3031,-2965,-2864,-2707,-2538,-2401,-2284,-2147,
--1988,-1840,-1734,-1673,-1647,-1643,-1654,-1666,-1652,-1577,-1431,-1249,-1099,-1026,-1022,-1048,-1055,-980,-762,-399,17,
-367,599,761,919,1091,1254,1402,1549,1689,1798,1862,1904,1958,2034,2115,2188,2253,2320,2389,2455,2513,
-2569,2629,2690,2745,2791,2839,2898,2968,3040,3110,3181,3255,3327,3395,3467,3547,3632,3709,3775,3841,3915,
-3993,4060,4115,4167,4225,4284,4333,4370,4412,4476,4553,4612,4637,4647,4673,4709,4721,4711,4737,4844,4979,
-5036,4980,4899,4901,4992,5086,5126,5142,5184,5237,5246,5207,5185,5239,5354,5459,5508,5515,5512,5507,5491,
-5463,5435,5416,5406,5406,5419,5436,5438,5418,5385,5349,5313,5283,5265,5254,5235,5203,5146,5010,4720,4274,
-3803,3494,3451,3642,3970,4356,4739,5048,5219,5250,5218,5247,5429,5754,6116,6392,6541,6613,6667,6719,6760,
-6802,6863,6931,6981,7010,7032,7050,7044,7006,6961,6943,6970,7033,7106,7171,7227,7285,7346,7392,7420,7457,
-7528,7629,7738,7851,7967,8064,8118,8140,8166,8204,8231,8238,8243,8241,8189,8051,7853,7638,7423,7209,7038,
-6973,7024,7112,7136,7071,6987,6982,7087,7248,7389,7495,7622,7810,8013,8132,8112,7971,7750,7453,7072,6651,
-6284,6048,5942,5893,5825,5704,5545,5411,5403,5616,6052,6572,6972,7122,7043,6849,6644,6483,6384,6338,6306,
-6250,6172,6102,6056,6019,5978,5952,5963,6004,6039,6043,6021,5994,5970,5940,5894,5832,5764,5698,5637,5582,
-5537,5504,5472,5428,5367,5299,5233,5173,5113,5048,4978,4915,4869,4832,4788,4731,4675,4629,4585,4533,4483,
-4453,4434,4405,4357,4306,4265,4229,4188,4141,4092,4040,3988,3943,3905,3864,3820,3781,3751,3720,3684,3652,
-3623,3583,3527,3473,3435,3407,3376,3343,3311,3269,3218,3190,3207,3233,3208,3130,3064,3051,3055,3014,2921,
-2829,2770,2733,2699,2680,2688,2701,2676,2603,2516,2452,2414,2381,2342,2305,2274,2245,2214,2183,2152,2117,
-2080,2050,2033,2017,1994,1968,1944,1917,1889,1880,1905,1939,1932,1873,1809,1789,1814,1847,1867,1874,1867,
-1837,1791,1755,1745,1749,1747,1732,1712,1694,1682,1677,1678,1681,1684,1687,1695,1711,1732,1750,1756,1744,
-1714,1670,1628,1605,1603,1610,1616,1617,1611,1591,1553,1510,1485,1487,1505,1514,1502,1475,1450,1437,1433,
-1427,1409,1377,1338,1302,1273,1253,1237,1221,1201,1181,1167,1163,1166,1171,1176,1177,1171,1169,1177,1187,
-1178,1147,1117,1110,1119,1119,1106,1093,1089,1080,1062,1049,1055,1067,1059,1031,1004,992,983,962,932,
-907,888,866,832,795,765,744,726,710,697,685,667,639,606,580,566,558,550,538,521,504,
-492,483,473,459,441,420,399,380,363,345,326,305,285,264,238,205,172,142,118,97,77,
-62,52,43,32,15,-9,-44,-84,-120,-150,-176,-207,-244,-283,-317,-346,-372,-401,-433,-469,-505,
--541,-575,-605,-631,-656,-680,-704,-727,-747,-765,-781,-799,-821,-847,-872,-893,-910,-926,-940,-953,-969,
--987,-1008,-1028,-1047,-1067,-1088,-1108,-1126,-1143,-1160,-1180,-1204,-1230,-1252,-1268,-1282,-1303,-1330,-1353,-1370,-1383,
--1397,-1407,-1413,-1420,-1430,-1441,-1447,-1450,-1453,-1460,-1468,-1477,-1483,-1488,-1495,-1507,-1518,-1523,-1524,-1527,-1535,
--1540,-1541,-1543,-1553,-1566,-1570,-1564,-1555,-1551,-1550,-1548,-1545,-1543,-1541,-1536,-1530,-1524,-1517,-1508,-1498,-1490,
--1485,-1481,-1477,-1469,-1459,-1447,-1432,-1414,-1393,-1372,-1351,-1336,-1328,-1322,-1315,-1306,-1298,-1293,-1291,-1287,-1283,
--1282,-1280,-1277,-1271,-1264,-1258,-1252,-1249,-1251,-1256,-1261,-1265,-1271,-1281,-1288,-1291,-1293,-1298,-1306,-1314,-1321,
--1327,-1333,-1341,-1353,-1364,-1372,-1376,-1379,-1381,-1381,-1379,-1379,-1382,-1382,-1378,-1375,-1375,-1378,-1379,-1381,-1382,
--1382,-1379,-1379,-1382,-1386,-1385,-1384,-1383,-1381,-1375,-1368,-1363,-1357,-1350,-1345,-1342,-1334,-1320,-1306,-1296,-1285,
--1272,-1257,-1245,-1231,-1214,-1196,-1180,-1160,-1133,-1105,-1080,-1055,-1028,-1000,-974,-944,-906,-869,-837,-805,-766,
--723,-681,-640,-596,-551,-507,-459,-407,-360,-322,-281,-233,-188,-152,-113,-62,-21,-7,-2,0,-43,
--164,-285,-244,40,466,841,1033,1043,977,989,1173,1461,1663,1672,1588,1600,1746,1881,1870,1727,1558,
-1426,1330,1268,1247,1260,1284,1316,1372,1456,1555,1648,1724,1776,1806,1835,1887,1970,2062,2138,2189,2220,
-2244,2268,2292,2311,2314,2299,2277,2265,2263,2252,2206,2127,2039,1959,1876,1775,1663,1567,1495,1437,1376,
-1312,1245,1165,1067,962,861,767,666,553,430,312,216,153,114,79,37,-13,-76,-158,-255,-343,
--406,-451,-493,-535,-575,-617,-670,-733,-801,-875,-959,-1039,-1100,-1142,-1185,-1243,-1307,-1366,-1423,-1491,-1579,
--1675,-1763,-1830,-1881,-1928,-1975,-2015,-2044,-2064,-2084,-2104,-2119,-2129,-2137,-2143,-2146,-2151,-2161,-2173,-2183,-2193,
--2208,-2229,-2255,-2287,-2325,-2353,-2361,-2360,-2369,-2391,-2413,-2433,-2461,-2499,-2532,-2551,-2564,-2572,-2565,-2538,-2503,
--2472,-2436,-2381,-2319,-2277,-2264,-2262,-2245,-2214,-2181,-2150,-2111,-2053,-1979,-1895,-1802,-1698,-1584,-1474,-1381,-1307,
--1242,-1184,-1148,-1135,-1119,-1061,-963,-860,-789,-754,-737,-718,-690,-651,-602,-553,-518,-501,-492,-487,-496,
--539,-623,-726,-809,-846,-841,-819,-803,-798,-803,-810,-814,-810,-800,-789,-778,-765,-748,-729,-711,-694,
--678,-665,-657,-649,-636,-617,-593,-565,-538,-514,-492,-467,-435,-403,-373,-346,-317,-284,-247,-208,-167,
--129,-96,-65,-32,3,36,70,112,161,209,248,280,316,359,403,442,477,516,564,625,694,
-761,819,868,915,963,1012,1058,1101,1140,1172,1197,1223,1253,1287,1317,1344,1371,1398,1421,1444,1475,
-1515,1555,1588,1617,1645,1671,1692,1715,1746,1778,1798,1802,1793,1780,1765,1750,1739,1733,1727,1717,1701,
-1685,1668,1647,1626,1611,1604,1596,1586,1579,1580,1587,1592,1590,1583,1572,1559,1552,1558,1573,1590,1605,
-1626,1652,1675,1689,1701,1711,1712,1706,1706,1715,1712,1688,1661,1652,1641,1644,1598,1532,1505,1514,1483,
-1368,1231,1157,1149,1140,1096,1045,1017,997,966,936,922,914,892,867,851,840,817,783,756,740,
-727,713,706,708,713,717,721,722,720,721,734,759,781,797,816,851,906,978,1058,1129,1165,
-1153,1096,1017,939,877,831,787,730,662,601,570,576,603,616,592,536,467,403,345,291,244,
-206,163,105,36,-28,-94,-171,-264,-357,-435,-497,-551,-600,-642,-670,-687,-708,-751,-824,-913,-1000,
--1082,-1166,-1243,-1297,-1326,-1351,-1386,-1424,-1452,-1463,-1467,-1469,-1467,-1461,-1460,-1476,-1513,-1557,-1589,-1600,-1599,
--1585,-1544,-1465,-1361,-1262,-1186,-1142,-1137,-1174,-1228,-1265,-1283,-1310,-1356,-1399,-1419,-1438,-1490,-1574,-1660,-1724,
--1760,-1774,-1774,-1771,-1778,-1806,-1863,-1945,-2025,-2065,-2056,-2031,-2014,-1987,-1935,-1893,-1921,-2021,-2140,-2237,-2333,
--2458,-2597,-2711,-2788,-2858,-2949,-3061,-3174,-3262,-3323,-3375,-3444,-3535,-3626,-3693,-3733,-3756,-3775,-3800,-3831,-3860,
--3877,-3888,-3905,-3927,-3940,-3943,-3953,-3982,-4021,-4059,-4093,-4122,-4140,-4151,-4169,-4195,-4207,-4189,-4157,-4142,-4147,
--4145,-4117,-4074,-4043,-4036,-4043,-4040,-4019,-3993,-3976,-3965,-3956,-3963,-4001,-4032,-4004,-3935,-3918,-3992,-4083,-4105,
--4078,-4081,-4125,-4158,-4181,-4250,-4353,-4391,-4323,-4256,-4302,-4418,-4473,-4428,-4372,-4383,-4446,-4518,-4600,-4701,-4797,
--4863,-4917,-4987,-5067,-5131,-5185,-5251,-5331,-5403,-5456,-5503,-5559,-5620,-5682,-5748,-5818,-5885,-5946,-6006,-6071,-6136,
--6197,-6257,-6316,-6373,-6423,-6472,-6520,-6565,-6606,-6647,-6694,-6743,-6784,-6817,-6849,-6888,-6940,-7012,-7110,-7221,-7320,
--7404,-7491,-7584,-7653,-7659,-7608,-7546,-7505,-7490,-7506,-7568,-7681,-7824,-7979,-8141,-8296,-8404,-8449,-8473,-8528,-8607,
--8664,-8685,-8701,-8730,-8752,-8753,-8752,-8767,-8784,-8787,-8788,-8807,-8837,-8857,-8868,-8880,-8890,-8888,-8880,-8881,-8883,
--8866,-8830,-8794,-8760,-8714,-8654,-8596,-8554,-8522,-8496,-8479,-8467,-8447,-8411,-8370,-8329,-8279,-8209,-8124,-8030,-7925,
--7815,-7722,-7661,-7616,-7566,-7503,-7435,-7366,-7295,-7216,-7119,-6989,-6827,-6664,-6534,-6443,-6378,-6336,-6316,-6306,-6274,
--6205,-6110,-6006,-5901,-5796,-5689,-5565,-5414,-5254,-5125,-5041,-4972,-4881,-4767,-4657,-4569,-4492,-4399,-4267,-4098,-3927,
--3790,-3676,-3538,-3358,-3186,-3077,-3014,-2921,-2763,-2585,-2442,-2325,-2185,-2008,-1838,-1722,-1662,-1633,-1619,-1624,-1652,
--1675,-1648,-1547,-1393,-1237,-1121,-1059,-1047,-1054,-1020,-880,-617,-286,31,303,547,780,989,1162,1322,1494,
-1666,1794,1855,1880,1913,1973,2043,2105,2159,2217,2284,2353,2413,2468,2528,2597,2669,2729,2778,2827,2887,
-2961,3042,3121,3193,3261,3329,3405,3490,3575,3649,3714,3779,3851,3930,4009,4078,4133,4179,4226,4276,4327,
-4377,4435,4502,4558,4589,4611,4651,4696,4702,4664,4653,4729,4854,4923,4902,4864,4891,4960,4994,4979,4988,
-5066,5163,5193,5143,5087,5093,5159,5237,5296,5337,5370,5386,5378,5357,5341,5336,5337,5339,5344,5344,5329,
-5302,5275,5248,5214,5178,5162,5178,5199,5177,5076,4866,4533,4113,3720,3497,3513,3726,4041,4370,4653,4851,
-4963,5037,5144,5333,5604,5913,6195,6401,6528,6610,6675,6727,6768,6817,6883,6946,6979,6990,7008,7038,7055,
-7040,7006,6986,7001,7050,7113,7173,7226,7276,7320,7345,7355,7379,7432,7498,7562,7635,7736,7845,7925,7971,
-8016,8075,8123,8141,8136,8127,8110,8075,8011,7892,7683,7397,7135,7020,7071,7175,7184,7047,6838,6677,6628,
-6674,6762,6876,7042,7269,7502,7645,7632,7471,7214,6914,6615,6361,6203,6164,6207,6249,6209,6053,5799,5516,
-5322,5355,5680,6211,6748,7102,7206,7105,6899,6683,6523,6421,6330,6210,6082,5994,5955,5926,5885,5854,5865,
-5908,5949,5968,5975,5980,5979,5965,5930,5877,5812,5745,5684,5631,5585,5545,5509,5472,5423,5358,5286,5221,
-5171,5123,5060,4989,4930,4889,4849,4797,4743,4701,4662,4613,4559,4516,4484,4447,4399,4351,4310,4269,4221,
-4174,4130,4081,4029,3982,3946,3910,3870,3830,3792,3752,3711,3679,3655,3619,3566,3515,3480,3454,3424,3395,
-3368,3322,3249,3187,3178,3206,3209,3162,3113,3102,3103,3063,2976,2890,2835,2797,2756,2722,2712,2713,2693,
-2637,2565,2504,2458,2413,2362,2316,2283,2261,2240,2213,2178,2135,2094,2066,2053,2039,2017,1994,1976,1951,
-1909,1874,1877,1906,1914,1876,1824,1807,1830,1862,1879,1882,1873,1849,1812,1778,1757,1745,1736,1728,1718,
-1700,1677,1665,1670,1681,1686,1685,1692,1710,1729,1738,1738,1729,1708,1674,1637,1609,1593,1583,1576,1580,
-1588,1584,1554,1512,1485,1483,1488,1479,1452,1425,1411,1408,1403,1390,1370,1345,1316,1287,1262,1244,1231,
-1215,1194,1173,1158,1149,1145,1146,1152,1157,1152,1141,1133,1130,1118,1093,1072,1071,1081,1082,1070,1061,
-1058,1050,1030,1014,1018,1034,1033,1006,973,954,947,936,913,885,862,839,809,773,739,713,694,
-676,656,634,612,588,561,535,516,506,500,491,476,460,449,444,438,427,411,396,382,369,
-354,337,321,303,281,252,218,183,153,132,114,96,78,62,53,48,39,21,-5,-37,-71,
--105,-137,-167,-199,-235,-273,-309,-341,-370,-401,-436,-472,-505,-536,-568,-599,-628,-655,-682,-709,-736,
--760,-779,-794,-808,-827,-849,-871,-889,-906,-922,-937,-951,-967,-987,-1009,-1029,-1047,-1066,-1086,-1105,-1121,
--1137,-1152,-1170,-1194,-1219,-1240,-1252,-1264,-1287,-1317,-1344,-1360,-1370,-1379,-1388,-1395,-1404,-1416,-1427,-1433,-1437,
--1442,-1452,-1463,-1472,-1476,-1479,-1484,-1494,-1504,-1508,-1508,-1511,-1516,-1519,-1516,-1514,-1521,-1530,-1532,-1526,-1521,
--1520,-1521,-1521,-1520,-1518,-1515,-1508,-1500,-1492,-1485,-1476,-1466,-1457,-1452,-1450,-1448,-1440,-1427,-1411,-1394,-1376,
--1357,-1339,-1322,-1307,-1296,-1287,-1281,-1273,-1267,-1262,-1259,-1255,-1251,-1249,-1248,-1247,-1243,-1237,-1230,-1225,-1224,
--1229,-1236,-1242,-1245,-1251,-1261,-1269,-1271,-1272,-1277,-1285,-1293,-1300,-1307,-1317,-1329,-1343,-1356,-1362,-1361,-1359,
--1362,-1367,-1370,-1371,-1372,-1373,-1371,-1367,-1366,-1367,-1369,-1372,-1374,-1375,-1375,-1374,-1375,-1378,-1381,-1382,-1381,
--1376,-1371,-1366,-1363,-1358,-1351,-1344,-1339,-1330,-1319,-1306,-1295,-1283,-1269,-1258,-1247,-1234,-1216,-1199,-1183,-1163,
--1135,-1107,-1083,-1061,-1035,-1007,-979,-947,-911,-875,-843,-807,-766,-725,-688,-647,-600,-554,-514,-472,-422,
--375,-336,-296,-247,-198,-162,-127,-79,-35,-15,-11,-14,-53,-160,-276,-261,-22,377,763,988,1024,
-960,950,1095,1357,1588,1694,1734,1823,1964,2043,1975,1799,1608,1454,1339,1267,1245,1264,1302,1354,1430,
-1524,1617,1696,1758,1804,1837,1868,1912,1973,2045,2117,2184,2238,2280,2312,2341,2360,2359,2334,2302,2283,
-2284,2284,2254,2185,2097,2006,1914,1811,1705,1616,1546,1483,1416,1347,1274,1190,1095,1001,916,831,729,
-614,499,399,320,267,236,212,176,116,23,-99,-228,-326,-374,-392,-413,-448,-492,-539,-593,-654,
--719,-788,-866,-949,-1022,-1083,-1143,-1214,-1291,-1364,-1432,-1503,-1582,-1663,-1738,-1801,-1854,-1905,-1952,-1993,-2025,
--2049,-2070,-2087,-2102,-2115,-2128,-2136,-2138,-2142,-2150,-2162,-2172,-2184,-2202,-2221,-2240,-2265,-2297,-2323,-2326,-2313,
--2304,-2313,-2338,-2377,-2425,-2470,-2496,-2506,-2515,-2527,-2526,-2498,-2457,-2424,-2394,-2352,-2302,-2266,-2256,-2256,-2245,
--2219,-2187,-2153,-2109,-2047,-1967,-1879,-1785,-1681,-1567,-1455,-1361,-1288,-1227,-1177,-1149,-1143,-1130,-1076,-979,-876,
--805,-776,-765,-748,-710,-651,-582,-517,-473,-457,-461,-469,-478,-507,-583,-697,-804,-862,-866,-847,-832,
--826,-823,-824,-830,-834,-829,-819,-810,-802,-789,-770,-750,-731,-714,-699,-688,-678,-668,-653,-632,-604,
--573,-545,-520,-492,-461,-429,-402,-378,-352,-324,-292,-255,-212,-169,-132,-99,-66,-30,4,39,81,
-132,180,219,253,293,339,381,416,448,488,541,605,677,748,809,858,905,955,1003,1044,1079,
-1110,1138,1161,1186,1220,1259,1294,1324,1353,1383,1410,1437,1470,1511,1550,1578,1599,1619,1639,1659,1682,
-1713,1743,1757,1753,1743,1736,1730,1717,1703,1692,1682,1670,1653,1638,1624,1610,1596,1589,1585,1581,1574,
-1573,1581,1592,1596,1591,1583,1573,1563,1559,1566,1582,1600,1617,1637,1655,1668,1675,1684,1691,1688,1680,
-1682,1691,1685,1659,1640,1646,1644,1642,1582,1500,1461,1465,1437,1334,1210,1145,1135,1116,1059,1000,974,
-966,950,929,918,912,896,873,854,839,815,785,761,744,729,715,709,712,716,717,718,717,
-715,717,731,755,777,795,821,871,945,1030,1113,1180,1217,1214,1173,1108,1038,980,939,900,843,
-762,682,638,647,687,710,688,630,563,503,444,385,333,292,251,200,143,89,29,-53,-159,
--262,-340,-397,-448,-505,-563,-604,-624,-636,-670,-745,-850,-960,-1056,-1133,-1191,-1227,-1246,-1263,-1291,-1327,
--1360,-1383,-1393,-1394,-1388,-1385,-1395,-1432,-1499,-1571,-1616,-1623,-1610,-1594,-1561,-1486,-1367,-1237,-1127,-1061,-1054,
--1103,-1178,-1239,-1275,-1309,-1352,-1387,-1396,-1401,-1435,-1506,-1588,-1650,-1681,-1689,-1693,-1708,-1738,-1778,-1833,-1909,
--1989,-2041,-2053,-2050,-2046,-2027,-1990,-1977,-2029,-2127,-2215,-2282,-2373,-2506,-2637,-2721,-2771,-2835,-2928,-3031,-3124,
--3206,-3283,-3358,-3435,-3519,-3604,-3673,-3718,-3742,-3755,-3770,-3793,-3820,-3842,-3860,-3880,-3900,-3912,-3919,-3938,-3974,
--4017,-4056,-4090,-4121,-4145,-4164,-4191,-4228,-4251,-4236,-4190,-4141,-4101,-4061,-4019,-3988,-3978,-3983,-3986,-3976,-3959,
--3940,-3917,-3889,-3873,-3898,-3953,-3981,-3946,-3906,-3947,-4063,-4137,-4103,-4034,-4036,-4097,-4136,-4147,-4203,-4301,-4340,
--4281,-4232,-4296,-4421,-4472,-4421,-4361,-4361,-4403,-4452,-4522,-4623,-4724,-4793,-4849,-4921,-5000,-5061,-5113,-5180,-5260,
--5329,-5380,-5429,-5488,-5551,-5610,-5675,-5746,-5816,-5878,-5937,-5999,-6062,-6123,-6184,-6246,-6303,-6351,-6394,-6437,-6482,
--6529,-6578,-6629,-6672,-6701,-6726,-6760,-6807,-6866,-6942,-7040,-7149,-7244,-7323,-7405,-7498,-7563,-7560,-7501,-7444,-7427,
--7442,-7477,-7543,-7653,-7788,-7927,-8066,-8201,-8304,-8358,-8390,-8444,-8518,-8575,-8601,-8623,-8655,-8681,-8685,-8688,-8705,
--8722,-8722,-8718,-8733,-8757,-8771,-8777,-8788,-8800,-8797,-8783,-8775,-8768,-8747,-8711,-8677,-8648,-8604,-8540,-8474,-8424,
--8389,-8363,-8348,-8342,-8330,-8305,-8273,-8236,-8184,-8113,-8034,-7955,-7871,-7781,-7702,-7646,-7601,-7546,-7477,-7403,-7330,
--7255,-7178,-7085,-6957,-6793,-6626,-6499,-6421,-6370,-6335,-6320,-6316,-6291,-6222,-6121,-6015,-5917,-5823,-5724,-5605,-5459,
--5300,-5159,-5053,-4966,-4878,-4783,-4694,-4613,-4529,-4427,-4292,-4128,-3966,-3838,-3739,-3617,-3443,-3259,-3131,-3059,-2970,
--2816,-2633,-2485,-2369,-2229,-2043,-1858,-1735,-1680,-1657,-1639,-1634,-1648,-1666,-1652,-1590,-1485,-1355,-1221,-1111,-1045,
--1017,-984,-902,-762,-581,-360,-85,240,566,833,1038,1229,1443,1654,1807,1881,1908,1933,1973,2017,2057,
-2096,2142,2195,2253,2309,2368,2434,2513,2595,2664,2714,2757,2814,2889,2973,3050,3118,3186,3263,3345,3424,
-3496,3564,3636,3713,3789,3865,3944,4024,4088,4130,4161,4204,4258,4313,4366,4423,4481,4528,4570,4624,4680,
-4693,4649,4610,4644,4736,4810,4833,4851,4899,4937,4914,4865,4876,4973,5081,5113,5064,5001,4980,5004,5050,
-5103,5160,5211,5241,5248,5244,5244,5252,5264,5272,5273,5260,5232,5198,5174,5158,5138,5116,5115,5144,5164,
-5116,4967,4721,4402,4056,3769,3635,3696,3905,4170,4412,4594,4723,4845,5016,5262,5553,5834,6070,6261,6418,
-6546,6643,6704,6738,6768,6819,6890,6953,6983,6994,7013,7046,7072,7070,7050,7032,7035,7062,7104,7150,7199,
-7248,7288,7308,7320,7351,7404,7456,7489,7527,7602,7704,7793,7851,7900,7956,8000,8013,7995,7970,7961,7982,
-8016,7995,7837,7539,7221,7044,7053,7134,7119,6931,6633,6354,6185,6139,6187,6301,6470,6679,6881,7015,7032,
-6930,6753,6570,6437,6378,6388,6449,6526,6576,6553,6423,6175,5838,5511,5350,5477,5882,6414,6882,7159,7218,
-7110,6931,6766,6631,6484,6296,6106,5978,5920,5884,5842,5810,5809,5826,5839,5849,5873,5908,5937,5949,5941,
-5914,5867,5809,5753,5702,5648,5587,5528,5480,5439,5387,5321,5259,5218,5186,5138,5068,4999,4948,4905,4857,
-4808,4771,4740,4699,4644,4589,4539,4490,4442,4400,4360,4312,4257,4209,4170,4125,4070,4020,3982,3949,3910,
-3870,3829,3783,3736,3700,3677,3649,3609,3570,3543,3517,3482,3449,3426,3385,3305,3218,3176,3179,3178,3143,
-3100,3084,3081,3051,2989,2925,2880,2843,2798,2754,2724,2706,2682,2642,2591,2542,2497,2449,2395,2342,2305,
-2285,2270,2246,2209,2162,2118,2090,2073,2056,2032,2014,2004,1981,1931,1877,1861,1888,1912,1893,1851,1830,
-1845,1871,1884,1882,1873,1860,1841,1819,1795,1769,1748,1736,1727,1705,1675,1656,1662,1677,1682,1680,1687,
-1703,1716,1717,1714,1711,1702,1679,1649,1622,1598,1575,1558,1556,1563,1558,1530,1494,1473,1468,1457,1429,
-1396,1379,1381,1382,1370,1347,1327,1313,1299,1282,1264,1247,1229,1208,1184,1163,1147,1133,1120,1114,1120,
-1131,1131,1118,1102,1091,1079,1061,1043,1037,1041,1041,1034,1027,1024,1018,1000,984,985,999,1002,977,
-936,906,897,895,883,858,830,805,778,743,705,674,653,635,612,585,561,541,520,495,472,
-458,452,444,428,412,402,400,398,388,375,365,357,347,332,317,305,292,269,236,199,165,
-139,119,100,81,61,45,39,39,35,17,-11,-41,-67,-92,-122,-155,-190,-225,-263,-300,-333,
--364,-396,-433,-469,-500,-527,-557,-589,-620,-650,-678,-708,-740,-769,-792,-809,-822,-838,-856,-874,-890,
--904,-919,-934,-949,-968,-990,-1012,-1031,-1048,-1066,-1086,-1105,-1123,-1137,-1150,-1165,-1187,-1211,-1229,-1238,-1247,
--1268,-1300,-1330,-1348,-1357,-1362,-1367,-1374,-1383,-1394,-1404,-1411,-1417,-1425,-1437,-1450,-1460,-1465,-1467,-1472,-1481,
--1490,-1495,-1498,-1503,-1507,-1505,-1498,-1495,-1498,-1502,-1499,-1493,-1489,-1489,-1490,-1490,-1489,-1488,-1485,-1478,-1470,
--1461,-1453,-1444,-1435,-1426,-1420,-1419,-1418,-1410,-1394,-1372,-1352,-1333,-1317,-1304,-1292,-1281,-1268,-1257,-1249,-1242,
--1237,-1232,-1228,-1223,-1218,-1216,-1217,-1216,-1212,-1205,-1200,-1197,-1200,-1206,-1215,-1221,-1224,-1230,-1239,-1245,-1248,
--1251,-1258,-1266,-1271,-1275,-1284,-1299,-1315,-1331,-1344,-1349,-1347,-1343,-1345,-1353,-1358,-1359,-1361,-1363,-1364,-1361,
--1358,-1358,-1360,-1362,-1364,-1366,-1367,-1367,-1367,-1370,-1375,-1379,-1378,-1372,-1366,-1361,-1359,-1356,-1351,-1344,-1335,
--1324,-1313,-1302,-1293,-1282,-1271,-1261,-1251,-1236,-1217,-1200,-1184,-1163,-1136,-1109,-1086,-1065,-1040,-1012,-982,-950,
--916,-883,-850,-811,-767,-727,-693,-653,-603,-557,-521,-487,-440,-390,-348,-309,-262,-212,-173,-140,-97,
--54,-27,-16,-15,-45,-139,-259,-282,-102,254,642,904,980,935,913,1027,1274,1544,1740,1862,1966,
-2053,2066,1964,1776,1562,1372,1239,1186,1205,1262,1331,1410,1503,1602,1689,1762,1823,1872,1908,1936,1968,
-2008,2060,2125,2201,2271,2318,2346,2367,2383,2380,2350,2306,2276,2277,2292,2282,2225,2133,2032,1935,1840,
-1747,1664,1592,1523,1453,1382,1307,1221,1128,1042,966,884,783,675,580,502,431,371,332,311,285,
-225,115,-34,-185,-288,-327,-329,-338,-372,-419,-467,-518,-577,-644,-716,-795,-878,-959,-1033,-1103,-1179,
--1259,-1339,-1416,-1491,-1566,-1639,-1708,-1772,-1831,-1884,-1929,-1968,-2003,-2034,-2058,-2075,-2086,-2099,-2113,-2123,-2128,
--2132,-2140,-2148,-2158,-2172,-2193,-2212,-2226,-2243,-2269,-2293,-2297,-2279,-2261,-2265,-2296,-2349,-2408,-2451,-2466,-2464,
--2472,-2491,-2497,-2471,-2426,-2387,-2362,-2339,-2311,-2289,-2278,-2271,-2252,-2222,-2187,-2151,-2109,-2047,-1964,-1868,-1767,
--1661,-1547,-1435,-1339,-1266,-1209,-1168,-1146,-1141,-1127,-1079,-997,-910,-847,-817,-800,-774,-724,-653,-572,-496,
--443,-424,-436,-455,-465,-485,-551,-670,-793,-865,-878,-869,-866,-867,-862,-854,-856,-863,-864,-856,-846,
--840,-831,-814,-793,-770,-749,-730,-714,-701,-690,-679,-664,-639,-606,-572,-542,-515,-487,-459,-433,-409,
--384,-358,-332,-301,-262,-219,-179,-143,-106,-66,-29,6,47,95,142,182,222,269,320,364,399,
-434,478,530,591,658,725,783,832,882,936,988,1029,1060,1088,1117,1145,1175,1212,1253,1289,1316,
-1340,1367,1395,1422,1456,1497,1534,1557,1570,1583,1599,1619,1642,1671,1695,1701,1690,1679,1679,1682,1676,
-1664,1655,1650,1643,1631,1621,1614,1606,1599,1593,1588,1579,1569,1565,1570,1577,1577,1570,1564,1561,1557,
-1557,1565,1582,1602,1620,1637,1646,1648,1649,1655,1663,1662,1656,1661,1672,1667,1646,1636,1648,1642,1602,
-1524,1430,1381,1376,1352,1272,1177,1125,1110,1082,1023,970,951,950,939,920,909,904,893,873,854,
-834,811,786,767,754,740,729,727,730,731,726,721,721,722,726,737,755,774,795,830,889,
-969,1057,1140,1208,1250,1258,1229,1173,1108,1053,1017,986,940,866,784,736,741,779,802,780,721,
-653,590,527,462,406,364,327,283,233,183,125,45,-55,-154,-231,-288,-341,-403,-471,-526,-556,
--571,-600,-667,-770,-880,-973,-1040,-1086,-1119,-1142,-1159,-1174,-1192,-1217,-1244,-1265,-1276,-1284,-1302,-1339,-1402,
--1487,-1568,-1614,-1617,-1601,-1586,-1557,-1482,-1358,-1215,-1091,-1012,-998,-1051,-1145,-1229,-1277,-1301,-1328,-1358,-1381,
--1397,-1423,-1471,-1534,-1590,-1618,-1617,-1613,-1637,-1687,-1739,-1788,-1852,-1935,-2012,-2054,-2065,-2061,-2046,-2034,-2060,
--2135,-2223,-2281,-2327,-2413,-2539,-2644,-2695,-2731,-2803,-2905,-2998,-3071,-3148,-3239,-3333,-3420,-3503,-3583,-3649,-3691,
--3713,-3726,-3739,-3757,-3780,-3805,-3829,-3854,-3875,-3892,-3907,-3931,-3964,-3997,-4027,-4062,-4110,-4163,-4215,-4268,-4320,
--4348,-4329,-4262,-4169,-4069,-3977,-3915,-3897,-3910,-3925,-3920,-3907,-3899,-3892,-3865,-3818,-3791,-3824,-3899,-3941,-3917,
--3893,-3948,-4055,-4098,-4037,-3971,-3997,-4076,-4110,-4102,-4139,-4230,-4274,-4227,-4185,-4243,-4356,-4413,-4392,-4363,-4368,
--4383,-4398,-4447,-4541,-4640,-4713,-4776,-4854,-4934,-4992,-5041,-5106,-5185,-5251,-5303,-5355,-5417,-5477,-5535,-5599,-5672,
--5741,-5802,-5862,-5925,-5989,-6051,-6114,-6176,-6230,-6274,-6313,-6358,-6407,-6459,-6509,-6553,-6587,-6611,-6637,-6678,-6734,
--6799,-6876,-6974,-7083,-7179,-7255,-7329,-7408,-7458,-7445,-7391,-7356,-7371,-7417,-7467,-7532,-7631,-7752,-7872,-7990,-8111,
--8214,-8276,-8310,-8356,-8425,-8485,-8518,-8543,-8575,-8603,-8613,-8619,-8636,-8652,-8653,-8651,-8663,-8683,-8693,-8697,-8709,
--8723,-8717,-8694,-8672,-8655,-8628,-8591,-8557,-8528,-8484,-8418,-8353,-8307,-8276,-8252,-8233,-8224,-8217,-8201,-8178,-8146,
--8096,-8027,-7955,-7888,-7821,-7749,-7681,-7627,-7578,-7518,-7447,-7372,-7298,-7220,-7142,-7054,-6937,-6782,-6621,-6499,-6428,
--6386,-6357,-6343,-6338,-6310,-6233,-6125,-6021,-5934,-5850,-5749,-5623,-5477,-5325,-5188,-5076,-4981,-4893,-4811,-4736,-4656,
--4560,-4439,-4295,-4141,-4001,-3898,-3816,-3704,-3529,-3335,-3193,-3111,-3019,-2864,-2676,-2525,-2413,-2282,-2101,-1917,-1794,
--1743,-1721,-1698,-1676,-1661,-1642,-1609,-1567,-1514,-1434,-1318,-1190,-1087,-1015,-954,-898,-860,-830,-740,-518,-174,
-198,515,783,1059,1363,1645,1844,1954,2010,2045,2066,2075,2086,2110,2145,2182,2221,2269,2329,2396,2461,
-2520,2569,2612,2661,2729,2811,2893,2964,3030,3108,3198,3286,3354,3406,3464,3543,3635,3718,3785,3854,3935,
-4010,4056,4078,4106,4151,4200,4244,4293,4355,4420,4483,4546,4601,4614,4572,4524,4537,4619,4717,4797,4868,
-4929,4940,4884,4820,4825,4898,4963,4966,4926,4893,4889,4907,4942,4993,5050,5097,5123,5133,5138,5143,5149,
-5157,5165,5164,5146,5111,5075,5056,5057,5064,5070,5079,5087,5063,4971,4806,4593,4361,4134,3958,3890,3961,
-4132,4327,4489,4614,4738,4912,5169,5485,5794,6033,6196,6327,6460,6590,6687,6735,6750,6769,6815,6882,6941,
-6975,6992,7010,7029,7038,7031,7018,7010,7017,7037,7071,7116,7171,7227,7269,7291,7307,7342,7398,7448,7475,
-7500,7552,7628,7698,7747,7787,7827,7861,7872,7858,7827,7805,7828,7902,7965,7909,7690,7401,7193,7134,7134,
-7041,6783,6419,6081,5866,5799,5850,5978,6145,6319,6473,6584,6636,6626,6577,6538,6550,6611,6690,6752,6787,
-6795,6770,6691,6521,6243,5904,5629,5557,5744,6125,6565,6931,7132,7154,7059,6938,6826,6688,6497,6290,6132,
-6039,5977,5921,5877,5843,5799,5744,5709,5722,5772,5825,5867,5897,5910,5896,5858,5814,5768,5710,5632,5548,
-5481,5435,5393,5342,5289,5252,5227,5193,5135,5069,5013,4965,4915,4867,4831,4803,4768,4718,4660,4600,4542,
-4491,4450,4411,4360,4302,4253,4213,4166,4110,4057,4018,3982,3942,3903,3866,3824,3776,3736,3711,3689,3661,
-3636,3619,3594,3555,3516,3488,3451,3379,3288,3221,3189,3164,3126,3091,3075,3063,3032,2983,2939,2910,2886,
-2855,2817,2773,2728,2685,2643,2602,2561,2521,2482,2438,2392,2353,2329,2311,2284,2244,2196,2154,2124,2102,
-2079,2056,2042,2037,2020,1974,1921,1904,1931,1957,1940,1891,1857,1865,1893,1911,1910,1900,1890,1881,1871,
-1851,1819,1782,1755,1732,1704,1672,1654,1659,1672,1677,1677,1682,1691,1694,1691,1691,1697,1696,1682,1663,
-1644,1622,1593,1567,1554,1546,1524,1487,1456,1447,1447,1430,1395,1368,1366,1377,1374,1351,1324,1306,1297,
-1287,1272,1255,1236,1213,1187,1162,1143,1127,1109,1089,1076,1079,1092,1102,1098,1085,1074,1066,1053,1034,
-1018,1011,1010,1008,1002,997,989,975,959,955,965,970,949,902,856,834,835,833,815,786,757,
-730,697,660,627,606,591,572,548,525,506,486,460,435,419,411,402,385,367,357,356,354,
-345,335,328,324,315,302,291,283,272,250,218,182,148,115,83,53,28,8,-4,-5,2,
-8,-1,-26,-53,-72,-88,-112,-146,-183,-220,-257,-295,-327,-356,-388,-425,-461,-493,-520,-549,-581,
--613,-643,-671,-702,-735,-768,-797,-819,-835,-850,-867,-885,-900,-913,-926,-940,-957,-977,-999,-1020,-1037,
--1051,-1066,-1085,-1105,-1124,-1138,-1150,-1163,-1182,-1203,-1218,-1224,-1230,-1249,-1281,-1313,-1334,-1343,-1345,-1348,-1354,
--1363,-1373,-1382,-1389,-1396,-1407,-1419,-1432,-1443,-1449,-1453,-1456,-1463,-1472,-1478,-1485,-1492,-1495,-1490,-1482,-1479,
--1481,-1481,-1475,-1467,-1462,-1460,-1459,-1456,-1453,-1451,-1448,-1444,-1438,-1430,-1421,-1412,-1404,-1396,-1391,-1389,-1387,
--1378,-1358,-1334,-1312,-1293,-1278,-1267,-1259,-1251,-1240,-1229,-1220,-1213,-1207,-1201,-1197,-1193,-1188,-1185,-1185,-1185,
--1180,-1174,-1170,-1171,-1175,-1182,-1190,-1195,-1199,-1206,-1214,-1220,-1224,-1229,-1240,-1249,-1254,-1257,-1266,-1283,-1301,
--1315,-1325,-1330,-1328,-1325,-1327,-1335,-1342,-1344,-1345,-1349,-1352,-1351,-1348,-1348,-1350,-1350,-1349,-1349,-1351,-1352,
--1353,-1357,-1364,-1370,-1371,-1366,-1359,-1354,-1351,-1349,-1346,-1340,-1330,-1318,-1306,-1298,-1290,-1282,-1272,-1264,-1253,
--1237,-1216,-1198,-1181,-1161,-1136,-1112,-1091,-1069,-1044,-1014,-983,-951,-919,-889,-857,-816,-771,-732,-700,-661,
--611,-565,-531,-499,-453,-400,-356,-321,-280,-233,-191,-154,-113,-71,-41,-24,-14,-30,-108,-232,-299,
--195,98,474,776,911,905,882,967,1195,1490,1746,1913,2000,2029,2002,1902,1722,1481,1241,1086,1064,
-1144,1254,1351,1441,1539,1639,1731,1817,1895,1956,1992,2016,2044,2079,2121,2176,2242,2303,2339,2353,2362,
-2374,2373,2345,2299,2264,2261,2280,2281,2234,2145,2042,1949,1864,1781,1702,1631,1564,1498,1430,1352,1261,
-1165,1079,1003,920,824,734,665,606,536,458,401,374,353,298,189,40,-105,-204,-243,-251,-270,
--313,-365,-412,-458,-517,-588,-665,-744,-826,-910,-989,-1063,-1135,-1209,-1287,-1368,-1449,-1528,-1603,-1674,-1743,
--1807,-1861,-1904,-1939,-1974,-2008,-2036,-2055,-2066,-2077,-2089,-2099,-2106,-2114,-2123,-2130,-2138,-2152,-2174,-2195,-2209,
--2226,-2252,-2278,-2285,-2271,-2256,-2261,-2295,-2351,-2408,-2444,-2450,-2444,-2450,-2469,-2478,-2456,-2412,-2373,-2355,-2349,
--2345,-2335,-2318,-2293,-2258,-2218,-2180,-2145,-2105,-2045,-1959,-1858,-1755,-1649,-1535,-1418,-1313,-1234,-1182,-1151,-1135,
--1126,-1107,-1065,-1003,-939,-888,-851,-817,-773,-713,-639,-561,-486,-430,-407,-418,-441,-451,-466,-530,-656,
--794,-878,-897,-893,-901,-914,-913,-902,-898,-903,-905,-899,-889,-882,-872,-856,-833,-808,-783,-761,-741,
--724,-710,-702,-692,-673,-640,-602,-568,-541,-516,-492,-467,-441,-413,-385,-360,-334,-303,-266,-228,-190,
--147,-103,-62,-26,12,56,102,145,190,243,298,346,388,430,478,530,585,646,708,764,813,
-863,918,970,1008,1035,1061,1092,1127,1164,1205,1245,1277,1298,1314,1334,1357,1384,1419,1459,1496,1518,
-1531,1544,1561,1579,1599,1621,1639,1642,1632,1625,1633,1645,1648,1642,1639,1641,1641,1636,1629,1623,1616,
-1607,1598,1588,1574,1557,1546,1544,1543,1539,1533,1533,1537,1542,1548,1560,1578,1597,1615,1628,1633,1630,
-1627,1631,1637,1637,1635,1641,1650,1645,1629,1622,1625,1602,1522,1439,1351,1299,1282,1255,1196,1133,1098,
-1080,1046,996,959,949,946,932,911,896,890,883,869,851,830,807,787,775,767,758,752,752,
-754,751,741,734,734,738,744,752,764,780,804,846,909,986,1068,1145,1214,1262,1279,1259,1212,
-1156,1109,1080,1059,1028,976,912,868,865,888,901,874,812,739,668,598,528,467,423,390,353,
-311,264,210,140,55,-33,-110,-176,-236,-301,-370,-432,-476,-504,-536,-594,-678,-767,-842,-898,-944,
--987,-1023,-1043,-1043,-1038,-1049,-1080,-1118,-1154,-1193,-1247,-1318,-1400,-1483,-1550,-1585,-1586,-1574,-1561,-1532,-1461,
--1348,-1218,-1094,-995,-950,-989,-1102,-1225,-1296,-1305,-1294,-1309,-1357,-1410,-1445,-1466,-1495,-1538,-1570,-1572,-1564,
--1584,-1633,-1682,-1720,-1777,-1873,-1977,-2040,-2052,-2038,-2026,-2039,-2094,-2185,-2271,-2324,-2371,-2453,-2552,-2616,-2637,
--2675,-2769,-2886,-2974,-3036,-3110,-3210,-3312,-3403,-3485,-3561,-3616,-3649,-3671,-3693,-3713,-3730,-3746,-3768,-3795,-3823,
--3849,-3871,-3890,-3911,-3936,-3961,-3990,-4034,-4101,-4178,-4248,-4305,-4350,-4376,-4367,-4313,-4211,-4076,-3940,-3850,-3829,
--3853,-3872,-3864,-3850,-3850,-3850,-3818,-3756,-3715,-3746,-3832,-3893,-3890,-3871,-3909,-3981,-4001,-3952,-3921,-3973,-4054,
--4072,-4049,-4073,-4155,-4201,-4164,-4121,-4156,-4243,-4307,-4334,-4357,-4380,-4375,-4358,-4379,-4456,-4545,-4619,-4693,-4782,
--4864,-4919,-4965,-5029,-5103,-5168,-5221,-5277,-5339,-5397,-5455,-5522,-5596,-5663,-5721,-5781,-5847,-5913,-5975,-6037,-6097,
--6148,-6190,-6232,-6283,-6337,-6387,-6428,-6464,-6495,-6524,-6558,-6605,-6664,-6732,-6813,-6913,-7023,-7119,-7194,-7261,-7322,
--7350,-7324,-7274,-7259,-7301,-7369,-7428,-7491,-7583,-7696,-7807,-7915,-8030,-8135,-8200,-8230,-8269,-8334,-8398,-8436,-8460,
--8490,-8519,-8532,-8537,-8551,-8568,-8574,-8577,-8590,-8609,-8619,-8626,-8642,-8658,-8652,-8623,-8591,-8566,-8534,-8492,-8452,
--8416,-8370,-8310,-8258,-8228,-8207,-8180,-8148,-8127,-8116,-8106,-8091,-8066,-8022,-7959,-7892,-7833,-7776,-7714,-7653,-7601,
--7549,-7486,-7413,-7342,-7270,-7193,-7114,-7033,-6931,-6795,-6647,-6531,-6466,-6429,-6403,-6386,-6373,-6332,-6243,-6128,-6028,
--5953,-5873,-5762,-5622,-5474,-5335,-5213,-5109,-5015,-4927,-4845,-4767,-4682,-4575,-4445,-4302,-4168,-4058,-3974,-3888,-3757,
--3569,-3375,-3240,-3161,-3064,-2899,-2705,-2552,-2448,-2332,-2169,-2000,-1888,-1838,-1809,-1772,-1731,-1684,-1622,-1554,-1509,
--1493,-1468,-1395,-1288,-1183,-1091,-1002,-935,-935,-989,-1002,-872,-601,-279,34,366,761,1193,1573,1842,2012,
-2124,2187,2196,2168,2146,2158,2192,2225,2260,2310,2377,2437,2469,2475,2477,2498,2552,2631,2716,2791,2855,
-2926,3013,3108,3191,3252,3298,3354,3437,3536,3623,3684,3739,3809,3888,3947,3977,4001,4039,4081,4115,4155,
-4214,4286,4351,4402,4431,4420,4370,4323,4342,4440,4576,4708,4820,4896,4909,4864,4815,4811,4831,4823,4782,
-4751,4761,4793,4825,4861,4912,4966,5002,5019,5029,5039,5041,5033,5025,5024,5022,5005,4973,4941,4932,4951,
-4980,4996,4988,4952,4884,4781,4656,4531,4414,4302,4211,4179,4235,4356,4490,4607,4724,4881,5105,5390,5695,
-5962,6156,6290,6405,6525,6637,6712,6743,6752,6770,6811,6869,6923,6961,6984,6994,6992,6979,6963,6957,6965,
-6984,7012,7051,7102,7162,7221,7262,7282,7298,7331,7383,7433,7467,7495,7531,7573,7609,7637,7665,7695,7723,
-7742,7746,7723,7682,7671,7736,7848,7904,7826,7651,7491,7406,7331,7143,6794,6360,5979,5746,5676,5733,5870,
-6047,6223,6371,6483,6562,6612,6644,6683,6753,6845,6928,6973,6976,6948,6902,6838,6733,6555,6302,6035,5854,
-5838,6006,6307,6645,6902,7006,6985,6929,6888,6835,6724,6569,6420,6303,6212,6137,6071,5991,5872,5732,5631,
-5605,5638,5695,5756,5819,5872,5896,5890,5867,5833,5781,5707,5619,5536,5470,5418,5368,5316,5271,5240,5213,
-5179,5137,5095,5052,5004,4951,4905,4864,4822,4772,4717,4659,4598,4541,4496,4456,4410,4355,4303,4255,4202,
-4144,4094,4056,4018,3974,3934,3901,3865,3822,3783,3759,3741,3719,3698,3684,3667,3634,3594,3559,3519,3458,
-3379,3305,3245,3197,3163,3152,3147,3120,3062,3002,2969,2964,2967,2961,2934,2878,2803,2729,2672,2627,2585,
-2547,2518,2489,2455,2417,2386,2359,2326,2282,2237,2198,2169,2144,2120,2098,2087,2082,2068,2033,1995,1987,
-2012,2030,1999,1933,1884,1883,1915,1944,1952,1944,1930,1920,1912,1896,1864,1819,1774,1735,1700,1671,1658,
-1662,1672,1677,1681,1685,1685,1675,1667,1671,1684,1689,1684,1677,1670,1654,1623,1591,1568,1543,1501,1455,
-1431,1435,1440,1420,1385,1369,1378,1387,1371,1338,1313,1303,1293,1274,1249,1226,1205,1182,1159,1140,1125,
-1108,1087,1064,1048,1045,1057,1074,1082,1077,1066,1056,1045,1026,1004,990,988,988,982,972,964,953,
-939,928,930,937,924,877,818,778,769,772,764,738,707,679,650,618,589,567,551,537,519,
-499,477,454,428,404,388,377,364,346,328,318,315,312,305,297,292,288,281,271,263,257,
-245,222,192,159,125,87,48,17,-2,-17,-30,-38,-36,-28,-30,-47,-69,-84,-95,-113,-144,
--182,-221,-260,-296,-327,-355,-385,-420,-457,-490,-520,-552,-584,-613,-640,-667,-696,-727,-760,-792,-819,
--840,-857,-876,-896,-914,-929,-942,-955,-972,-993,-1015,-1034,-1048,-1059,-1071,-1087,-1105,-1123,-1138,-1151,-1163,
--1178,-1194,-1206,-1211,-1217,-1236,-1266,-1297,-1319,-1327,-1329,-1331,-1337,-1346,-1356,-1363,-1370,-1380,-1391,-1402,-1414,
--1425,-1432,-1435,-1437,-1441,-1447,-1453,-1461,-1469,-1473,-1468,-1461,-1460,-1463,-1462,-1455,-1446,-1440,-1435,-1428,-1422,
--1417,-1413,-1409,-1405,-1401,-1394,-1385,-1376,-1370,-1365,-1362,-1359,-1354,-1342,-1320,-1297,-1277,-1260,-1244,-1231,-1223,
--1216,-1207,-1197,-1188,-1181,-1174,-1169,-1167,-1165,-1159,-1155,-1154,-1154,-1151,-1146,-1144,-1147,-1152,-1157,-1162,-1167,
--1172,-1179,-1188,-1196,-1201,-1207,-1218,-1229,-1236,-1242,-1253,-1270,-1286,-1297,-1304,-1308,-1308,-1306,-1310,-1319,-1326,
--1330,-1332,-1335,-1338,-1337,-1337,-1338,-1340,-1337,-1332,-1330,-1331,-1334,-1337,-1343,-1351,-1357,-1359,-1356,-1351,-1346,
--1342,-1339,-1336,-1332,-1324,-1313,-1303,-1294,-1287,-1278,-1268,-1259,-1247,-1230,-1211,-1193,-1175,-1156,-1135,-1113,-1093,
--1069,-1042,-1012,-982,-951,-920,-890,-858,-820,-776,-738,-706,-669,-622,-577,-541,-508,-462,-409,-365,-332,
--297,-254,-210,-167,-122,-79,-50,-33,-20,-22,-76,-188,-287,-262,-55,281,610,811,867,871,948,
-1154,1444,1718,1901,1978,1982,1948,1870,1705,1436,1138,944,934,1060,1213,1329,1422,1518,1622,1729,1841,
-1947,2024,2061,2082,2114,2159,2204,2247,2290,2326,2344,2348,2352,2360,2361,2340,2303,2270,2257,2262,2256,
-2214,2137,2048,1964,1884,1802,1726,1664,1612,1559,1492,1406,1303,1196,1102,1022,943,862,794,748,703,
-633,544,473,434,404,347,248,122,2,-84,-132,-164,-204,-258,-312,-358,-404,-463,-538,-617,-696,
--776,-860,-943,-1019,-1088,-1156,-1230,-1312,-1400,-1486,-1565,-1639,-1709,-1773,-1829,-1873,-1909,-1942,-1974,-2003,-2025,
--2041,-2054,-2064,-2072,-2080,-2091,-2103,-2112,-2118,-2129,-2147,-2168,-2188,-2212,-2243,-2272,-2285,-2281,-2275,-2284,-2315,
--2360,-2405,-2434,-2442,-2442,-2449,-2466,-2473,-2456,-2420,-2387,-2374,-2382,-2393,-2388,-2359,-2311,-2256,-2207,-2167,-2132,
--2091,-2029,-1942,-1843,-1744,-1644,-1531,-1405,-1289,-1204,-1156,-1133,-1122,-1110,-1086,-1047,-1000,-955,-911,-863,-806,
--742,-675,-608,-543,-481,-428,-399,-401,-417,-425,-442,-515,-659,-821,-923,-944,-932,-934,-952,-962,-956,
--949,-948,-947,-941,-932,-921,-907,-888,-865,-840,-815,-791,-768,-748,-732,-724,-718,-704,-674,-635,-599,
--571,-547,-524,-500,-472,-441,-408,-381,-357,-333,-304,-271,-232,-187,-139,-94,-53,-12,32,78,123,
-171,224,278,329,376,425,476,528,582,640,701,757,807,854,903,947,979,1000,1020,1049,1085,
-1125,1169,1211,1243,1261,1272,1285,1305,1333,1368,1409,1446,1471,1489,1509,1531,1549,1563,1577,1591,1599,
-1600,1604,1619,1635,1642,1640,1639,1643,1644,1638,1629,1619,1607,1594,1581,1570,1557,1542,1529,1522,1518,
-1514,1511,1516,1526,1537,1548,1561,1576,1589,1600,1609,1614,1613,1609,1609,1612,1613,1614,1617,1619,1610,
-1593,1581,1566,1522,1440,1369,1308,1268,1236,1191,1139,1101,1080,1059,1022,981,956,950,943,925,903,
-889,882,876,866,851,830,809,793,787,784,780,776,776,775,770,760,753,753,757,763,771,
-782,798,825,868,929,1000,1070,1138,1200,1247,1267,1256,1225,1189,1161,1144,1130,1111,1081,1043,1011,
-1000,1004,1002,969,904,824,743,665,592,529,481,446,413,377,337,290,232,163,87,7,-68,
--138,-204,-269,-333,-388,-432,-474,-526,-587,-650,-705,-754,-806,-860,-904,-924,-914,-894,-894,-929,-989,
--1059,-1137,-1227,-1322,-1410,-1480,-1527,-1547,-1543,-1527,-1508,-1476,-1419,-1340,-1245,-1133,-1008,-915,-926,-1058,-1237,
--1349,-1344,-1277,-1245,-1297,-1394,-1463,-1478,-1475,-1494,-1529,-1549,-1554,-1569,-1601,-1626,-1645,-1697,-1801,-1914,-1976,
--1979,-1965,-1973,-2015,-2088,-2182,-2273,-2347,-2417,-2496,-2562,-2587,-2593,-2643,-2751,-2867,-2946,-3005,-3089,-3199,-3306,
--3394,-3473,-3542,-3587,-3611,-3636,-3669,-3698,-3711,-3718,-3732,-3758,-3789,-3819,-3842,-3861,-3882,-3908,-3942,-3986,-4042,
--4106,-4158,-4184,-4189,-4193,-4213,-4243,-4252,-4205,-4090,-3942,-3827,-3786,-3801,-3819,-3813,-3798,-3798,-3799,-3769,-3704,
--3655,-3673,-3753,-3827,-3845,-3834,-3848,-3889,-3909,-3894,-3900,-3958,-4020,-4024,-4000,-4022,-4090,-4128,-4101,-4064,-4081,
--4141,-4201,-4260,-4325,-4370,-4362,-4328,-4329,-4380,-4449,-4518,-4600,-4696,-4779,-4834,-4881,-4944,-5015,-5077,-5134,-5195,
--5256,-5310,-5368,-5442,-5520,-5586,-5641,-5700,-5767,-5832,-5891,-5950,-6008,-6059,-6104,-6152,-6208,-6262,-6302,-6334,-6367,
--6405,-6444,-6484,-6530,-6587,-6659,-6750,-6855,-6961,-7051,-7123,-7186,-7237,-7250,-7214,-7165,-7159,-7212,-7289,-7355,-7422,
--7517,-7632,-7744,-7848,-7958,-8060,-8124,-8153,-8187,-8249,-8313,-8351,-8373,-8401,-8430,-8445,-8449,-8461,-8479,-8492,-8501,
--8517,-8537,-8551,-8563,-8584,-8604,-8601,-8573,-8540,-8511,-8475,-8425,-8374,-8329,-8284,-8236,-8203,-8189,-8175,-8141,-8093,
--8057,-8041,-8035,-8028,-8009,-7970,-7910,-7845,-7788,-7736,-7679,-7622,-7570,-7518,-7454,-7383,-7313,-7245,-7170,-7093,-7018,
--6929,-6810,-6676,-6569,-6510,-6479,-6454,-6433,-6409,-6354,-6252,-6129,-6032,-5964,-5885,-5766,-5620,-5477,-5351,-5241,-5145,
--5056,-4970,-4881,-4788,-4690,-4579,-4453,-4327,-4219,-4135,-4054,-3939,-3765,-3557,-3375,-3267,-3203,-3103,-2928,-2728,-2578,
--2483,-2382,-2239,-2092,-1994,-1943,-1899,-1843,-1781,-1712,-1619,-1518,-1458,-1454,-1465,-1439,-1375,-1303,-1225,-1128,-1038,
--1014,-1064,-1108,-1060,-912,-713,-468,-121,349,871,1327,1663,1905,2089,2203,2225,2183,2145,2153,2197,2246,
-2297,2368,2454,2518,2528,2490,2449,2445,2490,2561,2630,2689,2753,2833,2920,2997,3060,3120,3184,3254,3332,
-3418,3500,3559,3599,3647,3716,3790,3849,3895,3940,3981,4010,4039,4084,4139,4181,4194,4178,4134,4070,4025,
-4050,4157,4306,4451,4574,4668,4718,4729,4732,4743,4737,4685,4619,4596,4630,4681,4714,4742,4785,4834,4867,
-4889,4914,4942,4951,4936,4915,4902,4897,4883,4857,4830,4826,4846,4868,4860,4813,4745,4681,4632,4596,4565,
-4528,4477,4425,4409,4451,4538,4640,4746,4882,5072,5317,5582,5832,6043,6214,6358,6483,6588,6665,6709,6729,
-6741,6760,6796,6847,6902,6945,6968,6971,6959,6944,6936,6942,6960,6985,7016,7054,7102,7156,7205,7238,7256,
-7274,7307,7355,7404,7445,7481,7511,7528,7534,7542,7562,7587,7612,7638,7659,7647,7594,7548,7581,7699,7823,
-7868,7835,7793,7774,7708,7486,7076,6577,6137,5853,5731,5737,5842,6020,6226,6414,6556,6653,6716,6757,6794,
-6847,6922,7003,7068,7096,7076,7014,6928,6834,6723,6575,6395,6218,6102,6100,6235,6460,6673,6782,6797,6798,
-6840,6888,6881,6803,6690,6575,6473,6389,6313,6209,6049,5860,5702,5619,5602,5628,5683,5754,5825,5880,5915,
-5928,5913,5870,5809,5734,5648,5559,5478,5410,5346,5285,5238,5214,5205,5199,5187,5163,5124,5071,5011,4948,
-4884,4821,4764,4710,4653,4593,4542,4501,4460,4410,4355,4296,4235,4176,4130,4095,4058,4012,3969,3934,3899,
-3860,3828,3809,3793,3769,3743,3728,3718,3700,3669,3631,3587,3534,3473,3404,3330,3267,3243,3260,3272,3228,
-3136,3060,3040,3063,3088,3089,3057,2986,2887,2793,2726,2679,2634,2592,2563,2542,2514,2476,2439,2406,2370,
-2327,2286,2253,2227,2203,2179,2159,2144,2132,2113,2084,2057,2054,2072,2077,2038,1967,1911,1899,1922,1952,
-1970,1974,1964,1948,1932,1914,1887,1845,1795,1748,1710,1685,1674,1672,1675,1680,1691,1698,1692,1671,1655,
-1657,1671,1680,1684,1690,1693,1679,1646,1612,1585,1550,1498,1449,1434,1447,1449,1416,1378,1371,1390,1393,
-1359,1314,1292,1292,1284,1257,1221,1193,1171,1153,1138,1127,1114,1093,1069,1048,1034,1030,1038,1055,1068,
-1064,1047,1033,1022,1007,986,971,967,967,959,948,940,934,922,906,900,906,901,866,807,753,
-726,721,718,700,671,640,613,588,562,538,518,504,490,472,448,421,395,374,358,343,326,
-307,291,283,279,276,272,266,262,256,249,242,235,227,210,185,155,128,104,85,73,69,
-69,59,29,-10,-41,-54,-60,-70,-86,-99,-110,-126,-153,-189,-229,-268,-303,-332,-360,-390,-425,
--461,-495,-530,-565,-596,-622,-645,-670,-698,-725,-753,-782,-811,-835,-855,-876,-899,-922,-940,-954,-968,
--985,-1005,-1026,-1044,-1057,-1068,-1080,-1093,-1108,-1124,-1139,-1153,-1165,-1176,-1186,-1194,-1200,-1210,-1229,-1257,-1284,
--1302,-1310,-1313,-1315,-1322,-1331,-1339,-1345,-1353,-1364,-1375,-1387,-1398,-1408,-1414,-1414,-1414,-1415,-1419,-1423,-1428,
--1436,-1440,-1438,-1434,-1435,-1438,-1437,-1432,-1425,-1420,-1412,-1402,-1393,-1387,-1380,-1373,-1367,-1363,-1357,-1345,-1335,
--1330,-1328,-1326,-1323,-1315,-1301,-1279,-1259,-1243,-1229,-1213,-1197,-1186,-1178,-1169,-1160,-1154,-1147,-1140,-1136,-1136,
--1136,-1130,-1123,-1121,-1123,-1122,-1120,-1120,-1123,-1127,-1130,-1134,-1140,-1145,-1152,-1162,-1173,-1180,-1186,-1194,-1205,
--1215,-1224,-1237,-1255,-1272,-1284,-1292,-1297,-1298,-1298,-1302,-1311,-1319,-1324,-1327,-1328,-1328,-1326,-1326,-1329,-1330,
--1327,-1321,-1318,-1319,-1322,-1326,-1334,-1342,-1347,-1347,-1344,-1341,-1338,-1335,-1332,-1327,-1321,-1315,-1308,-1300,-1291,
--1281,-1270,-1258,-1247,-1234,-1218,-1201,-1184,-1167,-1148,-1128,-1108,-1087,-1061,-1032,-1003,-976,-949,-919,-888,-856,
--820,-781,-742,-709,-674,-633,-590,-551,-514,-471,-424,-382,-346,-309,-268,-223,-177,-127,-81,-50,-36,
--25,-20,-46,-129,-239,-282,-171,97,422,674,802,864,963,1154,1414,1672,1863,1960,1977,1952,1886,
-1729,1445,1102,861,829,964,1140,1272,1370,1466,1573,1691,1824,1957,2055,2103,2126,2162,2216,2269,2306,
-2328,2341,2350,2359,2369,2376,2372,2354,2329,2303,2280,2258,2231,2187,2127,2058,1985,1904,1818,1744,1696,
-1665,1626,1558,1459,1339,1218,1114,1032,965,906,862,832,795,730,645,571,519,470,399,303,201,
-109,33,-27,-81,-137,-194,-247,-294,-343,-406,-480,-560,-640,-723,-811,-897,-975,-1045,-1112,-1185,-1267,
--1356,-1445,-1527,-1602,-1670,-1732,-1789,-1839,-1880,-1913,-1942,-1967,-1991,-2013,-2032,-2044,-2051,-2058,-2068,-2082,-2094,
--2102,-2110,-2121,-2139,-2162,-2194,-2230,-2262,-2279,-2287,-2294,-2308,-2329,-2356,-2384,-2409,-2426,-2439,-2454,-2469,-2476,
--2465,-2438,-2411,-2402,-2415,-2433,-2427,-2384,-2315,-2245,-2187,-2143,-2103,-2057,-1992,-1908,-1815,-1723,-1628,-1515,-1388,
--1270,-1189,-1145,-1126,-1114,-1098,-1072,-1037,-1000,-961,-914,-851,-776,-699,-632,-578,-533,-489,-443,-408,-396,
--397,-399,-420,-505,-670,-857,-979,-1004,-978,-962,-974,-992,-998,-992,-986,-981,-976,-967,-951,-930,-907,
--887,-868,-844,-818,-791,-769,-753,-745,-740,-727,-699,-663,-629,-602,-579,-556,-532,-505,-473,-440,-409,
--383,-360,-337,-308,-270,-224,-174,-125,-76,-27,22,71,117,164,214,265,315,365,414,465,515,
-568,625,685,741,789,833,874,911,939,958,975,999,1032,1072,1115,1159,1194,1216,1228,1241,1263,
-1297,1337,1378,1413,1439,1463,1490,1515,1533,1542,1551,1566,1583,1596,1607,1622,1635,1640,1637,1632,1630,
-1626,1616,1602,1587,1572,1557,1545,1540,1536,1530,1523,1517,1512,1510,1510,1516,1528,1543,1556,1567,1573,
-1575,1576,1580,1586,1590,1588,1585,1585,1588,1592,1592,1585,1570,1552,1531,1497,1440,1384,1337,1314,1294,
-1247,1176,1114,1085,1073,1050,1010,975,957,947,934,915,899,890,883,876,867,854,837,819,809,
-806,804,801,797,796,794,790,784,780,778,779,783,792,805,823,848,888,942,1004,1064,1119,
-1167,1204,1223,1225,1218,1213,1213,1213,1205,1189,1169,1147,1126,1111,1102,1088,1051,986,900,810,728,
-657,598,549,506,469,435,401,362,314,256,188,111,30,-45,-113,-177,-241,-302,-356,-407,-456,
--504,-549,-594,-645,-701,-756,-799,-819,-811,-790,-785,-818,-892,-992,-1103,-1215,-1315,-1396,-1457,-1495,-1504,
--1484,-1448,-1412,-1379,-1346,-1313,-1266,-1177,-1039,-911,-896,-1042,-1271,-1429,-1421,-1293,-1186,-1204,-1329,-1457,-1509,
--1500,-1489,-1505,-1534,-1561,-1586,-1603,-1599,-1590,-1621,-1706,-1795,-1835,-1838,-1858,-1921,-2007,-2092,-2176,-2266,-2360,
--2452,-2530,-2573,-2580,-2590,-2649,-2750,-2842,-2903,-2967,-3070,-3196,-3308,-3394,-3469,-3532,-3570,-3590,-3615,-3653,-3683,
--3691,-3689,-3697,-3720,-3749,-3778,-3803,-3824,-3850,-3889,-3945,-4008,-4065,-4096,-4081,-4019,-3942,-3900,-3926,-4010,-4100,
--4131,-4071,-3943,-3816,-3748,-3740,-3750,-3747,-3736,-3733,-3738,-3724,-3680,-3633,-3630,-3686,-3760,-3798,-3795,-3789,-3807,
--3835,-3856,-3883,-3926,-3960,-3962,-3956,-3983,-4032,-4054,-4039,-4027,-4050,-4092,-4135,-4192,-4268,-4326,-4333,-4309,-4303,
--4328,-4368,-4421,-4500,-4596,-4678,-4735,-4789,-4855,-4923,-4986,-5049,-5115,-5171,-5219,-5277,-5357,-5442,-5508,-5561,-5620,
--5686,-5749,-5806,-5863,-5921,-5974,-6022,-6074,-6128,-6175,-6209,-6238,-6275,-6319,-6362,-6400,-6442,-6500,-6583,-6685,-6793,
--6890,-6969,-7035,-7096,-7143,-7155,-7123,-7081,-7079,-7132,-7210,-7284,-7360,-7462,-7580,-7691,-7790,-7890,-7984,-8046,-8077,
--8112,-8168,-8225,-8258,-8278,-8307,-8338,-8353,-8358,-8372,-8396,-8415,-8428,-8446,-8469,-8488,-8504,-8528,-8553,-8556,-8533,
--8503,-8474,-8435,-8377,-8316,-8267,-8227,-8195,-8177,-8172,-8158,-8116,-8059,-8017,-8000,-7997,-7994,-7977,-7937,-7875,-7807,
--7750,-7700,-7645,-7587,-7535,-7484,-7424,-7354,-7285,-7218,-7147,-7073,-7002,-6918,-6807,-6684,-6587,-6537,-6512,-6489,-6463,
--6431,-6365,-6251,-6122,-6025,-5962,-5887,-5771,-5633,-5503,-5386,-5276,-5178,-5095,-5016,-4922,-4810,-4692,-4577,-4464,-4360,
--4276,-4209,-4123,-3976,-3767,-3545,-3382,-3299,-3246,-3141,-2962,-2766,-2625,-2539,-2449,-2322,-2192,-2104,-2049,-1989,-1913,
--1833,-1748,-1640,-1521,-1443,-1431,-1450,-1448,-1420,-1386,-1341,-1264,-1169,-1111,-1113,-1132,-1117,-1064,-981,-828,-534,
--92,407,854,1210,1506,1763,1951,2034,2036,2028,2060,2126,2198,2272,2366,2474,2555,2574,2536,2488,2476,
-2506,2551,2591,2637,2712,2811,2894,2939,2971,3032,3124,3207,3264,3314,3376,3431,3457,3472,3513,3590,3677,
-3752,3810,3853,3881,3903,3930,3957,3965,3943,3901,3846,3788,3749,3768,3851,3965,4072,4167,4259,4346,4422,
-4491,4553,4581,4554,4504,4489,4526,4575,4600,4612,4637,4674,4708,4742,4790,4844,4877,4874,4850,4829,4817,
-4800,4770,4737,4718,4716,4706,4659,4582,4521,4514,4559,4615,4642,4628,4587,4548,4543,4586,4667,4764,4879,
-5034,5242,5483,5715,5911,6078,6236,6388,6518,6609,6663,6693,6714,6728,6741,6767,6813,6870,6915,6934,6932,
-6925,6926,6937,6953,6971,6992,7018,7049,7086,7127,7164,7190,7210,7237,7277,7326,7374,7419,7462,7493,7501,
-7493,7489,7500,7516,7532,7556,7582,7577,7524,7466,7475,7572,7700,7795,7860,7947,8058,8096,7934,7541,7019,
-6529,6173,5965,5882,5916,6058,6269,6484,6654,6765,6823,6839,6834,6837,6870,6941,7034,7112,7140,7100,7014,
-6916,6826,6741,6648,6540,6431,6360,6370,6464,6577,6643,6663,6700,6791,6892,6937,6904,6818,6713,6613,6532,
-6465,6383,6255,6091,5927,5794,5709,5677,5693,5730,5771,5824,5897,5965,5985,5949,5888,5821,5740,5641,5542,
-5459,5387,5317,5261,5234,5235,5246,5251,5243,5216,5170,5107,5035,4958,4882,4816,4763,4711,4656,4604,4560,
-4519,4470,4410,4345,4279,4219,4169,4130,4092,4051,4012,3975,3936,3897,3870,3856,3841,3815,3786,3767,3759,
-3748,3727,3692,3647,3600,3553,3497,3420,3344,3317,3345,3366,3316,3213,3139,3139,3178,3197,3175,3119,3034,
-2933,2840,2778,2737,2693,2646,2611,2589,2562,2525,2486,2453,2420,2383,2346,2317,2294,2271,2248,2224,2202,
-2178,2151,2121,2095,2084,2086,2080,2049,2000,1959,1940,1942,1953,1972,1991,1996,1980,1954,1927,1899,1865,
-1822,1780,1746,1723,1707,1694,1685,1687,1701,1713,1708,1683,1659,1652,1659,1669,1680,1696,1704,1689,1655,
-1621,1594,1558,1505,1461,1454,1467,1454,1402,1357,1360,1393,1397,1349,1288,1260,1264,1265,1242,1207,1175,
-1150,1131,1118,1108,1091,1063,1036,1022,1018,1018,1023,1036,1044,1034,1012,995,988,981,966,952,945,
-943,935,925,921,919,911,896,883,882,882,865,823,767,718,691,681,670,646,615,587,566,
-542,515,490,473,460,442,417,389,364,344,326,306,286,267,254,249,246,245,243,241,237,
-228,218,210,202,189,167,139,112,94,98,125,167,204,216,191,129,48,-25,-71,-90,-96,
--105,-116,-128,-142,-165,-198,-237,-277,-311,-340,-369,-402,-437,-471,-506,-543,-581,-611,-632,-652,-677,
--705,-731,-754,-777,-802,-825,-846,-869,-894,-920,-940,-957,-972,-989,-1008,-1026,-1044,-1059,-1072,-1085,-1099,
--1112,-1126,-1141,-1155,-1166,-1173,-1179,-1185,-1194,-1208,-1228,-1250,-1270,-1284,-1292,-1297,-1301,-1308,-1315,-1321,-1326,
--1333,-1345,-1357,-1369,-1380,-1390,-1394,-1393,-1391,-1391,-1392,-1393,-1395,-1400,-1405,-1406,-1404,-1405,-1407,-1406,-1403,
--1401,-1399,-1391,-1379,-1369,-1362,-1353,-1343,-1335,-1330,-1323,-1310,-1296,-1288,-1286,-1283,-1278,-1269,-1254,-1234,-1217,
--1204,-1191,-1177,-1162,-1151,-1141,-1132,-1123,-1118,-1114,-1107,-1103,-1104,-1105,-1099,-1091,-1088,-1090,-1092,-1091,-1092,
--1094,-1097,-1100,-1105,-1113,-1120,-1126,-1136,-1149,-1160,-1167,-1173,-1182,-1192,-1203,-1218,-1240,-1263,-1281,-1293,-1299,
--1302,-1304,-1308,-1315,-1321,-1325,-1327,-1327,-1324,-1321,-1321,-1323,-1323,-1319,-1314,-1312,-1314,-1317,-1321,-1329,-1335,
--1338,-1335,-1332,-1329,-1329,-1328,-1324,-1318,-1311,-1305,-1301,-1294,-1283,-1271,-1260,-1248,-1236,-1221,-1206,-1191,-1175,
--1157,-1138,-1118,-1097,-1074,-1047,-1019,-991,-968,-945,-918,-887,-854,-822,-787,-749,-713,-679,-644,-603,-561,
--521,-484,-445,-403,-359,-315,-272,-230,-185,-137,-88,-51,-31,-22,-14,-22,-76,-180,-270,-241,-46,
-251,530,717,843,979,1159,1374,1602,1813,1961,2016,1992,1912,1756,1484,1142,873,803,917,1091,1230,
-1328,1417,1516,1632,1771,1925,2054,2128,2161,2192,2241,2295,2332,2348,2353,2365,2391,2419,2428,2413,2387,
-2368,2350,2323,2281,2231,2181,2130,2075,2011,1931,1843,1772,1734,1715,1684,1615,1508,1377,1245,1132,1051,
-998,961,934,911,879,826,757,689,627,556,467,367,275,196,125,55,-11,-72,-127,-178,-229,
--286,-350,-422,-501,-587,-677,-767,-852,-931,-1003,-1073,-1145,-1222,-1306,-1393,-1478,-1556,-1626,-1687,-1743,-1795,
--1842,-1879,-1908,-1932,-1957,-1981,-2002,-2016,-2025,-2030,-2038,-2051,-2066,-2079,-2087,-2094,-2107,-2134,-2174,-2215,-2247,
--2268,-2286,-2303,-2318,-2328,-2336,-2350,-2371,-2395,-2417,-2437,-2454,-2463,-2457,-2435,-2409,-2399,-2412,-2430,-2422,-2372,
--2295,-2218,-2156,-2103,-2052,-1997,-1933,-1856,-1770,-1680,-1583,-1471,-1353,-1252,-1185,-1148,-1124,-1103,-1082,-1058,-1029,
--995,-954,-898,-824,-742,-667,-610,-573,-547,-518,-480,-442,-418,-408,-405,-425,-509,-674,-868,-1005,-1043,
--1016,-987,-989,-1009,-1022,-1021,-1014,-1010,-1008,-1001,-980,-951,-925,-908,-894,-872,-842,-809,-785,-771,-764,
--758,-742,-715,-683,-655,-632,-611,-588,-564,-538,-508,-476,-444,-416,-391,-368,-341,-306,-262,-213,-161,
--106,-50,5,56,103,149,195,242,292,343,393,441,490,541,594,648,701,749,791,830,866,
-897,921,941,966,997,1034,1074,1115,1152,1179,1197,1216,1249,1295,1345,1387,1418,1442,1466,1492,1515,
-1529,1535,1541,1556,1575,1590,1600,1608,1614,1615,1608,1599,1591,1583,1572,1558,1544,1531,1518,1511,1511,
-1515,1518,1515,1510,1505,1503,1504,1510,1523,1540,1554,1560,1559,1554,1550,1552,1558,1564,1565,1561,1559,
-1563,1569,1567,1554,1537,1520,1493,1445,1384,1346,1319,1329,1327,1271,1177,1101,1071,1063,1040,1004,975,
-960,947,928,909,899,892,884,877,869,860,848,835,828,826,823,819,816,815,815,813,812,
-811,809,809,812,821,833,849,870,903,947,997,1047,1089,1121,1145,1164,1182,1204,1234,1266,1288,
-1289,1269,1242,1218,1198,1182,1166,1146,1110,1047,959,862,775,711,664,620,573,528,492,462,430,
-387,333,269,197,119,43,-27,-94,-160,-222,-277,-329,-378,-423,-465,-512,-567,-623,-671,-709,-735,
--744,-735,-727,-752,-826,-940,-1068,-1182,-1273,-1346,-1406,-1445,-1444,-1397,-1331,-1278,-1254,-1250,-1254,-1245,-1188,
--1070,-946,-926,-1070,-1314,-1500,-1502,-1341,-1162,-1119,-1242,-1432,-1560,-1582,-1544,-1515,-1524,-1563,-1609,-1629,-1608,
--1569,-1559,-1592,-1630,-1648,-1676,-1760,-1898,-2032,-2125,-2191,-2267,-2360,-2454,-2526,-2563,-2579,-2607,-2671,-2752,-2816,
--2864,-2935,-3052,-3188,-3303,-3390,-3462,-3518,-3551,-3570,-3596,-3630,-3655,-3661,-3660,-3667,-3683,-3704,-3726,-3750,-3778,
--3814,-3865,-3930,-3998,-4044,-4036,-3957,-3824,-3703,-3662,-3726,-3857,-3986,-4049,-4020,-3916,-3793,-3706,-3672,-3671,-3673,
--3668,-3670,-3686,-3701,-3690,-3652,-3626,-3651,-3718,-3771,-3772,-3741,-3730,-3758,-3805,-3845,-3869,-3880,-3886,-3904,-3936,
--3965,-3970,-3969,-3993,-4041,-4083,-4105,-4137,-4196,-4258,-4290,-4295,-4295,-4299,-4307,-4336,-4401,-4486,-4564,-4629,-4695,
--4766,-4832,-4895,-4964,-5034,-5086,-5126,-5183,-5268,-5357,-5425,-5478,-5538,-5604,-5667,-5725,-5784,-5844,-5898,-5947,-5995,
--6043,-6084,-6117,-6153,-6194,-6236,-6272,-6306,-6351,-6419,-6513,-6622,-6726,-6812,-6880,-6938,-6992,-7035,-7050,-7035,-7015,
--7024,-7076,-7154,-7234,-7322,-7426,-7541,-7645,-7734,-7822,-7904,-7964,-7999,-8034,-8082,-8127,-8156,-8179,-8211,-8243,-8259,
--8267,-8288,-8319,-8342,-8356,-8376,-8403,-8424,-8441,-8465,-8492,-8499,-8480,-8450,-8420,-8379,-8320,-8258,-8213,-8184,-8163,
--8152,-8146,-8128,-8085,-8031,-7993,-7978,-7974,-7969,-7950,-7907,-7841,-7770,-7712,-7664,-7610,-7551,-7497,-7448,-7392,-7325,
--7257,-7192,-7124,-7054,-6982,-6896,-6784,-6665,-6579,-6541,-6524,-6501,-6472,-6433,-6359,-6237,-6104,-6010,-5956,-5891,-5785,
--5660,-5543,-5431,-5316,-5210,-5131,-5061,-4962,-4830,-4692,-4572,-4472,-4386,-4317,-4258,-4172,-4018,-3804,-3589,-3436,-3356,
--3292,-3177,-3003,-2823,-2697,-2620,-2538,-2423,-2305,-2220,-2159,-2088,-1996,-1900,-1803,-1688,-1563,-1471,-1437,-1437,-1429,
--1407,-1388,-1368,-1322,-1254,-1196,-1172,-1162,-1145,-1122,-1087,-993,-782,-457,-87,256,562,860,1158,1419,1601,
-1711,1793,1887,1993,2093,2186,2288,2402,2498,2545,2543,2528,2532,2557,2581,2600,2644,2743,2869,2957,2978,
-2987,3051,3162,3246,3268,3272,3310,3363,3378,3357,3356,3410,3497,3574,3632,3675,3709,3733,3753,3767,3761,
-3738,3710,3688,3664,3644,3653,3700,3760,3804,3840,3895,3977,4074,4182,4299,4397,4438,4426,4415,4444,4496,
-4533,4547,4558,4578,4601,4633,4684,4750,4804,4821,4803,4773,4744,4709,4658,4597,4548,4515,4480,4421,4353,
-4328,4385,4500,4606,4654,4645,4614,4596,4612,4666,4753,4862,4993,5163,5376,5607,5814,5976,6107,6236,6369,
-6486,6570,6627,6673,6709,6724,6725,6737,6777,6833,6874,6884,6877,6878,6893,6913,6931,6947,6968,6995,7026,
-7058,7091,7121,7146,7170,7203,7248,7300,7349,7397,7444,7481,7493,7485,7476,7474,7473,7476,7492,7513,7508,
-7462,7412,7419,7493,7587,7666,7762,7934,8170,8343,8302,7995,7516,7026,6640,6384,6250,6230,6319,6482,6667,
-6831,6951,7014,7013,6964,6900,6859,6868,6926,7012,7083,7106,7075,7009,6933,6867,6819,6781,6733,6674,6631,
-6627,6645,6657,6668,6717,6811,6904,6942,6910,6828,6719,6602,6503,6440,6404,6369,6308,6204,6062,5923,5834,
-5795,5760,5712,5701,5777,5902,5982,5973,5911,5842,5770,5683,5595,5525,5465,5402,5342,5303,5285,5273,5259,
-5241,5215,5175,5126,5073,5013,4945,4880,4827,4782,4735,4686,4640,4595,4541,4476,4408,4343,4281,4221,4168,
-4125,4090,4059,4026,3989,3952,3924,3906,3888,3865,3842,3824,3808,3790,3766,3733,3690,3644,3608,3568,3501,
-3419,3373,3385,3403,3361,3275,3221,3235,3267,3255,3195,3119,3040,2953,2873,2818,2781,2741,2694,2655,2631,
-2608,2576,2543,2514,2485,2450,2413,2382,2358,2335,2310,2281,2250,2217,2185,2155,2127,2104,2085,2069,2054,
-2045,2042,2034,2014,1994,1994,2013,2030,2022,1992,1955,1921,1889,1855,1822,1794,1772,1752,1731,1711,1703,
-1710,1721,1719,1698,1673,1657,1653,1658,1672,1690,1698,1682,1648,1617,1590,1554,1505,1472,1471,1479,1451,
-1386,1338,1352,1401,1414,1360,1281,1237,1238,1248,1238,1211,1178,1144,1111,1086,1066,1041,1011,985,976,
-980,987,994,1001,1001,987,966,954,956,957,947,932,922,917,912,907,905,905,902,892,877,
-865,860,859,844,800,734,678,650,641,626,598,569,546,523,494,465,444,428,409,384,358,
-335,314,293,271,248,229,217,213,212,212,213,213,209,198,186,174,162,143,119,93,70,
-66,101,177,263,313,304,242,154,57,-31,-94,-122,-127,-127,-134,-146,-160,-178,-206,-244,-284,
--318,-348,-380,-416,-452,-485,-518,-555,-592,-620,-639,-657,-683,-715,-742,-763,-780,-800,-821,-841,-864,
--889,-914,-936,-955,-972,-989,-1006,-1022,-1037,-1052,-1067,-1082,-1096,-1110,-1124,-1140,-1156,-1167,-1173,-1176,-1181,
--1192,-1208,-1226,-1241,-1253,-1264,-1274,-1281,-1288,-1293,-1299,-1303,-1307,-1313,-1324,-1336,-1348,-1359,-1369,-1373,-1372,
--1369,-1369,-1369,-1366,-1365,-1369,-1374,-1375,-1373,-1372,-1372,-1372,-1371,-1372,-1373,-1367,-1355,-1344,-1337,-1329,-1318,
--1310,-1306,-1298,-1283,-1266,-1254,-1247,-1239,-1229,-1218,-1204,-1188,-1173,-1161,-1150,-1137,-1127,-1119,-1111,-1100,-1090,
--1085,-1082,-1077,-1072,-1072,-1073,-1067,-1059,-1055,-1057,-1059,-1059,-1061,-1065,-1068,-1070,-1077,-1087,-1096,-1101,-1108,
--1122,-1136,-1147,-1154,-1162,-1171,-1182,-1199,-1225,-1254,-1279,-1294,-1302,-1307,-1312,-1317,-1320,-1321,-1321,-1322,-1323,
--1320,-1317,-1317,-1319,-1317,-1312,-1307,-1307,-1309,-1311,-1313,-1318,-1322,-1323,-1321,-1318,-1316,-1315,-1316,-1314,-1308,
--1299,-1294,-1290,-1283,-1271,-1258,-1250,-1241,-1229,-1214,-1198,-1183,-1167,-1150,-1131,-1109,-1085,-1060,-1035,-1009,-983,
--960,-940,-917,-887,-854,-824,-794,-758,-720,-685,-653,-616,-572,-530,-495,-461,-421,-372,-322,-276,-233,
--192,-150,-105,-60,-27,-9,-2,-4,-42,-138,-251,-277,-137,134,425,655,832,996,1157,1323,1520,
-1756,1965,2058,2016,1901,1747,1526,1238,984,889,968,1117,1239,1319,1389,1472,1575,1713,1883,2048,2159,
-2209,2229,2254,2292,2327,2347,2357,2380,2428,2478,2496,2471,2431,2405,2391,2368,2322,2263,2203,2148,2095,
-2038,1968,1890,1823,1781,1757,1724,1656,1551,1419,1282,1166,1086,1042,1017,996,975,949,911,859,798,
-729,648,550,447,353,274,200,127,56,-7,-63,-119,-179,-242,-306,-375,-454,-543,-636,-724,-805,
--882,-955,-1027,-1096,-1167,-1243,-1326,-1413,-1498,-1574,-1637,-1691,-1740,-1787,-1829,-1863,-1891,-1917,-1940,-1957,-1970,
--1980,-1987,-1994,-2005,-2022,-2040,-2051,-2058,-2073,-2110,-2165,-2218,-2255,-2278,-2296,-2313,-2321,-2319,-2314,-2319,-2333,
--2351,-2369,-2386,-2401,-2410,-2406,-2386,-2360,-2347,-2354,-2367,-2358,-2312,-2243,-2176,-2116,-2054,-1987,-1919,-1854,-1784,
--1703,-1610,-1507,-1399,-1301,-1226,-1180,-1147,-1115,-1085,-1060,-1037,-1010,-974,-926,-867,-797,-724,-662,-620,-595,
--579,-557,-524,-489,-465,-456,-454,-468,-533,-669,-843,-986,-1049,-1044,-1022,-1017,-1029,-1040,-1042,-1040,-1042,
--1046,-1041,-1016,-979,-947,-927,-914,-891,-857,-821,-797,-786,-781,-772,-753,-728,-703,-681,-663,-644,-622,
--596,-568,-538,-508,-477,-448,-422,-400,-374,-341,-300,-254,-204,-149,-92,-36,15,63,109,153,199,
-251,305,358,408,457,508,559,609,660,709,755,795,834,871,903,931,959,993,1027,1059,1091,
-1124,1154,1179,1209,1256,1316,1375,1418,1447,1469,1488,1505,1519,1526,1528,1531,1540,1554,1564,1567,1567,
-1566,1564,1556,1546,1539,1533,1526,1516,1507,1498,1490,1486,1488,1495,1500,1497,1490,1484,1481,1483,1489,
-1503,1520,1533,1536,1531,1527,1526,1529,1533,1539,1544,1543,1540,1541,1544,1538,1521,1503,1488,1461,1406,
-1346,1305,1287,1307,1312,1254,1156,1079,1051,1042,1022,993,973,964,951,930,911,900,892,884,878,
-876,871,862,853,848,844,839,835,836,839,841,841,841,843,844,847,852,860,870,882,900,
-924,954,990,1028,1058,1078,1093,1113,1148,1197,1258,1321,1369,1382,1359,1315,1271,1241,1222,1204,1182,
-1148,1089,1001,896,802,742,711,683,642,593,552,525,497,457,403,341,273,200,126,53,-17,
--85,-145,-197,-247,-296,-342,-389,-441,-497,-547,-587,-624,-664,-696,-705,-700,-715,-781,-895,-1022,-1129,
--1209,-1277,-1341,-1379,-1358,-1280,-1191,-1139,-1136,-1158,-1181,-1190,-1167,-1100,-1025,-1018,-1139,-1350,-1528,-1552,-1403,
--1192,-1085,-1169,-1385,-1585,-1660,-1618,-1545,-1519,-1556,-1619,-1657,-1638,-1579,-1522,-1493,-1486,-1503,-1575,-1720,-1903,
--2055,-2144,-2197,-2255,-2332,-2412,-2477,-2523,-2562,-2610,-2675,-2744,-2801,-2857,-2937,-3052,-3176,-3283,-3368,-3437,-3486,
--3514,-3534,-3562,-3595,-3618,-3627,-3632,-3640,-3647,-3654,-3667,-3692,-3726,-3767,-3816,-3872,-3929,-3963,-3936,-3823,-3663,
--3551,-3567,-3703,-3874,-3989,-4012,-3960,-3862,-3752,-3663,-3616,-3609,-3619,-3627,-3637,-3661,-3692,-3699,-3664,-3619,-3626,
--3695,-3765,-3768,-3709,-3661,-3677,-3738,-3789,-3806,-3803,-3811,-3839,-3872,-3885,-3878,-3885,-3934,-4007,-4059,-4074,-4085,
--4124,-4185,-4240,-4273,-4282,-4272,-4257,-4265,-4309,-4375,-4445,-4518,-4598,-4676,-4740,-4800,-4870,-4940,-4991,-5031,-5091,
--5179,-5269,-5336,-5391,-5452,-5520,-5587,-5649,-5713,-5774,-5826,-5871,-5915,-5955,-5993,-6032,-6077,-6120,-6152,-6179,-6217,
--6278,-6361,-6458,-6557,-6648,-6727,-6792,-6844,-6884,-6912,-6928,-6936,-6945,-6972,-7026,-7101,-7188,-7281,-7385,-7491,-7588,
--7671,-7750,-7823,-7877,-7913,-7945,-7984,-8023,-8052,-8082,-8119,-8151,-8168,-8182,-8211,-8245,-8267,-8282,-8305,-8334,-8354,
--8366,-8385,-8408,-8415,-8393,-8359,-8327,-8289,-8237,-8185,-8150,-8129,-8113,-8099,-8087,-8067,-8031,-7990,-7961,-7946,-7936,
--7923,-7901,-7857,-7791,-7721,-7665,-7619,-7569,-7511,-7458,-7411,-7357,-7294,-7229,-7166,-7101,-7034,-6960,-6869,-6752,-6634,
--6559,-6533,-6524,-6503,-6471,-6428,-6346,-6216,-6081,-5997,-5959,-5906,-5806,-5685,-5575,-5470,-5355,-5246,-5166,-5092,-4984,
--4836,-4686,-4569,-4480,-4402,-4336,-4279,-4201,-4067,-3879,-3684,-3531,-3426,-3330,-3203,-3041,-2885,-2775,-2704,-2628,-2526,
--2418,-2333,-2266,-2187,-2087,-1980,-1872,-1753,-1628,-1526,-1467,-1431,-1392,-1350,-1321,-1303,-1278,-1242,-1215,-1206,-1203,
--1192,-1168,-1125,-1037,-884,-680,-463,-256,-47,190,463,749,1012,1236,1427,1602,1764,1905,2023,2133,2246,
-2352,2428,2472,2500,2534,2567,2587,2602,2654,2773,2922,3021,3044,3053,3124,3242,3320,3318,3301,3336,3399,
-3415,3371,3331,3346,3400,3452,3497,3547,3597,3635,3661,3679,3690,3694,3705,3727,3744,3748,3758,3789,3819,
-3818,3796,3793,3829,3896,3993,4126,4266,4351,4356,4331,4347,4414,4485,4525,4540,4551,4565,4582,4615,4671,
-4731,4761,4747,4700,4637,4558,4460,4352,4265,4217,4194,4171,4152,4172,4255,4378,4488,4550,4575,4593,4622,
-4667,4733,4828,4952,5104,5284,5492,5709,5899,6038,6136,6224,6317,6410,6494,6571,6644,6699,6719,6715,6720,
-6754,6802,6832,6835,6829,6834,6851,6868,6884,6906,6940,6981,7019,7049,7074,7099,7122,7145,7175,7217,7268,
-7320,7372,7423,7465,7486,7487,7477,7464,7449,7442,7453,7469,7460,7418,7379,7390,7447,7503,7544,7629,7833,
-8143,8422,8501,8307,7917,7484,7129,6899,6787,6770,6824,6921,7041,7172,7295,7369,7364,7281,7152,7019,6917,
-6873,6893,6957,7025,7062,7054,7012,6964,6942,6950,6959,6938,6892,6843,6804,6776,6770,6806,6874,6934,6951,
-6917,6836,6708,6547,6391,6292,6277,6334,6402,6399,6294,6145,6035,5966,5862,5695,5560,5572,5718,5869,5926,
-5904,5855,5801,5741,5685,5643,5600,5541,5472,5410,5353,5292,5233,5186,5145,5105,5072,5052,5033,4997,4949,
-4902,4862,4818,4769,4723,4676,4619,4550,4480,4417,4357,4293,4229,4175,4137,4109,4082,4052,4021,3992,3965,
-3940,3919,3906,3891,3864,3830,3798,3767,3724,3676,3640,3616,3572,3498,3435,3420,3425,3396,3335,3299,3308,
-3316,3274,3198,3130,3073,3005,2925,2860,2820,2785,2743,2706,2683,2666,2642,2614,2589,2561,2524,2480,2442,
-2412,2387,2358,2325,2287,2250,2219,2194,2171,2144,2111,2084,2079,2105,2144,2159,2131,2078,2041,2038,2051,
-2050,2027,1992,1956,1921,1888,1858,1834,1812,1792,1770,1748,1728,1719,1718,1716,1705,1686,1667,1654,1651,
-1657,1669,1673,1658,1629,1597,1567,1530,1493,1475,1483,1488,1456,1391,1347,1364,1416,1433,1381,1296,1239,
-1229,1241,1240,1219,1184,1139,1089,1044,1012,992,974,958,947,942,944,951,957,952,935,920,919,
-929,933,923,905,891,885,886,887,886,882,881,880,869,845,827,832,843,822,756,677,629,
-615,606,584,556,532,507,478,447,421,399,376,352,331,310,288,265,241,217,194,178,172,
-172,173,174,176,172,162,150,136,119,97,73,51,34,38,89,188,284,315,263,170,83,
-12,-54,-113,-148,-156,-152,-155,-167,-180,-195,-219,-254,-292,-327,-360,-394,-430,-466,-497,-528,-561,
--596,-624,-643,-662,-690,-724,-754,-776,-793,-810,-828,-848,-868,-889,-911,-932,-952,-971,-988,-1005,-1019,
--1032,-1044,-1056,-1070,-1084,-1099,-1114,-1133,-1152,-1167,-1176,-1179,-1183,-1192,-1207,-1220,-1228,-1234,-1242,-1254,-1265,
--1272,-1276,-1279,-1283,-1286,-1292,-1300,-1311,-1323,-1335,-1346,-1351,-1351,-1349,-1349,-1347,-1343,-1341,-1343,-1347,-1347,
--1343,-1340,-1339,-1338,-1337,-1339,-1341,-1337,-1327,-1316,-1308,-1301,-1293,-1287,-1283,-1275,-1259,-1241,-1226,-1214,-1199,
--1184,-1170,-1157,-1144,-1132,-1121,-1111,-1101,-1094,-1090,-1084,-1072,-1061,-1055,-1052,-1047,-1042,-1040,-1040,-1036,-1029,
--1025,-1025,-1026,-1028,-1033,-1040,-1044,-1046,-1051,-1062,-1072,-1077,-1082,-1093,-1108,-1122,-1133,-1142,-1151,-1162,-1180,
--1209,-1241,-1268,-1283,-1291,-1297,-1305,-1313,-1315,-1312,-1309,-1310,-1312,-1311,-1310,-1311,-1312,-1310,-1303,-1299,-1298,
--1299,-1300,-1299,-1300,-1301,-1302,-1303,-1304,-1302,-1300,-1300,-1299,-1294,-1287,-1281,-1277,-1269,-1256,-1246,-1240,-1234,
--1221,-1205,-1189,-1174,-1159,-1144,-1127,-1105,-1078,-1052,-1030,-1007,-981,-955,-935,-915,-887,-854,-825,-797,-763,
--723,-687,-658,-625,-581,-537,-501,-469,-430,-383,-335,-288,-239,-195,-157,-119,-73,-26,3,12,10,
--20,-107,-229,-288,-185,67,370,637,854,1034,1175,1295,1460,1705,1945,2046,1977,1830,1691,1540,1336,
-1129,1031,1078,1192,1282,1335,1387,1460,1558,1691,1867,2056,2203,2273,2283,2278,2289,2313,2336,2356,2392,
-2458,2529,2561,2536,2482,2442,2424,2407,2369,2310,2242,2174,2114,2063,2012,1953,1889,1835,1794,1751,1684,
-1583,1454,1320,1207,1133,1093,1067,1043,1020,1001,978,940,882,811,731,640,540,442,354,277,204,
-131,61,-3,-67,-133,-201,-268,-336,-413,-499,-588,-670,-748,-826,-902,-975,-1044,-1113,-1187,-1266,-1351,
--1436,-1515,-1581,-1634,-1680,-1723,-1765,-1804,-1840,-1871,-1893,-1906,-1915,-1925,-1935,-1943,-1955,-1973,-1994,-2008,-2016,
--2040,-2096,-2176,-2253,-2301,-2321,-2327,-2328,-2320,-2306,-2295,-2294,-2299,-2303,-2305,-2310,-2318,-2322,-2317,-2299,-2278,
--2263,-2262,-2264,-2252,-2218,-2173,-2128,-2076,-2006,-1919,-1832,-1759,-1693,-1617,-1525,-1424,-1329,-1253,-1203,-1171,-1141,
--1107,-1074,-1049,-1025,-991,-946,-895,-844,-793,-741,-694,-656,-631,-612,-589,-560,-531,-514,-511,-515,-527,
--571,-671,-814,-954,-1043,-1075,-1074,-1068,-1066,-1065,-1062,-1063,-1072,-1081,-1077,-1051,-1010,-971,-943,-922,-896,
--862,-828,-805,-796,-792,-782,-765,-746,-728,-712,-694,-673,-650,-623,-591,-559,-529,-501,-474,-449,-429,
--405,-372,-331,-287,-243,-195,-143,-90,-37,13,62,107,153,205,263,320,375,430,485,538,589,
-642,696,747,790,831,871,908,939,970,1005,1037,1062,1085,1112,1143,1173,1211,1265,1331,1391,1433,
-1461,1483,1499,1507,1509,1508,1509,1510,1513,1519,1523,1522,1517,1512,1508,1501,1494,1490,1490,1488,1482,
-1476,1471,1468,1467,1470,1477,1481,1478,1469,1463,1462,1465,1472,1485,1501,1509,1507,1500,1499,1504,1508,
-1511,1516,1525,1528,1525,1520,1516,1503,1480,1459,1444,1417,1363,1305,1262,1238,1247,1243,1189,1106,1047,
-1028,1021,1000,975,963,960,950,931,914,902,893,887,888,891,890,881,874,869,866,860,857,
-861,867,869,870,870,873,878,886,897,906,916,928,945,962,978,997,1022,1047,1063,1075,1096,
-1141,1210,1294,1379,1445,1471,1446,1386,1323,1280,1258,1240,1216,1180,1124,1038,928,825,762,743,734,
-705,659,617,589,564,527,473,411,345,275,203,130,58,-8,-67,-119,-168,-217,-266,-316,-368,
--420,-465,-502,-542,-594,-642,-667,-672,-690,-752,-858,-976,-1072,-1146,-1213,-1274,-1298,-1252,-1149,-1054,-1021,
--1048,-1090,-1121,-1140,-1152,-1149,-1138,-1153,-1234,-1376,-1513,-1553,-1452,-1260,-1110,-1124,-1305,-1525,-1645,-1627,-1548,
--1507,-1537,-1605,-1654,-1648,-1589,-1509,-1446,-1429,-1478,-1594,-1757,-1920,-2039,-2110,-2162,-2219,-2285,-2350,-2414,-2475,
--2533,-2589,-2652,-2724,-2803,-2889,-2982,-3079,-3173,-3260,-3337,-3400,-3440,-3462,-3485,-3518,-3552,-3577,-3591,-3602,-3607,
--3606,-3603,-3612,-3636,-3672,-3711,-3752,-3797,-3849,-3885,-3854,-3721,-3539,-3439,-3517,-3734,-3947,-4036,-3994,-3888,-3779,
--3688,-3619,-3580,-3577,-3598,-3621,-3636,-3650,-3662,-3653,-3607,-3558,-3569,-3657,-3752,-3767,-3695,-3620,-3617,-3677,-3735,
--3750,-3741,-3744,-3771,-3802,-3810,-3800,-3806,-3854,-3931,-3992,-4015,-4025,-4058,-4119,-4187,-4233,-4246,-4231,-4209,-4206,
--4230,-4271,-4325,-4400,-4494,-4582,-4647,-4702,-4766,-4833,-4887,-4935,-5004,-5095,-5181,-5247,-5303,-5366,-5436,-5505,-5573,
--5639,-5698,-5746,-5789,-5829,-5866,-5902,-5946,-5998,-6043,-6072,-6100,-6150,-6229,-6319,-6404,-6482,-6557,-6631,-6699,-6748,
--6773,-6783,-6797,-6825,-6863,-6905,-6959,-7031,-7118,-7214,-7313,-7414,-7509,-7596,-7673,-7740,-7788,-7819,-7847,-7881,-7918,
--7953,-7990,-8030,-8063,-8084,-8106,-8138,-8171,-8191,-8206,-8230,-8259,-8274,-8278,-8288,-8304,-8304,-8276,-8238,-8205,-8174,
--8135,-8097,-8070,-8051,-8029,-8007,-7990,-7974,-7953,-7928,-7908,-7891,-7871,-7849,-7822,-7780,-7719,-7655,-7603,-7562,-7518,
--7466,-7417,-7370,-7317,-7255,-7193,-7133,-7073,-7009,-6936,-6840,-6718,-6602,-6536,-6523,-6524,-6507,-6473,-6424,-6333,-6195,
--6061,-5990,-5968,-5924,-5822,-5695,-5587,-5494,-5392,-5287,-5195,-5104,-4980,-4828,-4686,-4581,-4498,-4416,-4340,-4280,-4216,
--4113,-3961,-3786,-3625,-3486,-3357,-3219,-3074,-2942,-2845,-2776,-2706,-2615,-2515,-2428,-2353,-2269,-2168,-2055,-1938,-1815,
--1692,-1588,-1508,-1437,-1361,-1291,-1243,-1213,-1185,-1159,-1151,-1167,-1196,-1217,-1209,-1158,-1056,-919,-777,-652,-540,
--421,-273,-83,153,419,683,926,1150,1360,1550,1711,1849,1981,2110,2221,2306,2371,2427,2471,2498,2522,
-2584,2707,2857,2963,3003,3032,3116,3237,3316,3325,3327,3387,3475,3508,3469,3418,3407,3427,3456,3505,3580,
-3657,3703,3722,3740,3768,3798,3831,3870,3904,3927,3953,3995,4028,4017,3965,3918,3908,3933,3989,4084,4197,
-4261,4240,4183,4180,4256,4357,4426,4461,4492,4525,4550,4575,4618,4674,4708,4689,4614,4499,4354,4186,4020,
-3899,3853,3872,3922,3975,4035,4114,4210,4307,4400,4492,4586,4673,4747,4824,4927,5066,5230,5409,5598,5790,
-5958,6078,6153,6209,6271,6345,6426,6514,6601,6668,6698,6702,6711,6739,6772,6791,6795,6798,6808,6821,6835,
-6857,6895,6948,7001,7040,7061,7073,7085,7100,7119,7144,7180,7228,7283,7340,7395,7441,7470,7480,7475,7458,
-7438,7429,7440,7456,7450,7413,7377,7377,7407,7427,7434,7499,7704,8038,8372,8539,8454,8171,7820,7522,7339,
-7271,7287,7338,7397,7471,7574,7690,7765,7752,7654,7499,7317,7134,6991,6919,6920,6958,6995,7013,7015,7018,
-7038,7075,7105,7102,7064,7010,6956,6910,6884,6888,6917,6950,6966,6952,6889,6755,6554,6336,6173,6130,6218,
-6363,6443,6389,6262,6174,6130,6020,5779,5516,5406,5499,5682,5828,5897,5913,5898,5866,5837,5811,5766,5688,
-5596,5508,5420,5325,5238,5172,5120,5072,5040,5037,5049,5047,5022,4985,4942,4889,4831,4784,4747,4700,4633,
-4558,4492,4435,4377,4314,4254,4204,4165,4134,4110,4086,4060,4026,3992,3969,3958,3943,3911,3869,3836,3812,
-3774,3719,3675,3656,3634,3580,3514,3478,3469,3446,3400,3366,3359,3345,3295,3232,3192,3161,3099,3004,2920,
-2872,2843,2809,2772,2746,2729,2709,2684,2660,2632,2593,2546,2501,2464,2433,2400,2362,2323,2285,2256,2237,
-2224,2205,2173,2139,2132,2169,2229,2263,2235,2162,2091,2056,2050,2051,2042,2023,1995,1961,1925,1894,1866,
-1840,1817,1797,1776,1751,1727,1710,1703,1697,1688,1674,1658,1646,1640,1638,1635,1622,1597,1563,1525,1492,
-1474,1478,1496,1502,1474,1421,1380,1383,1413,1423,1381,1309,1253,1235,1238,1233,1209,1171,1121,1061,1006,
-978,985,1006,1009,983,943,919,918,924,915,894,882,888,900,901,888,869,855,849,853,860,
-857,847,843,850,847,819,787,788,816,821,768,686,624,599,588,570,546,523,497,466,434,
-405,377,349,325,307,288,265,239,215,189,161,139,130,128,129,131,133,130,121,110,97,
-80,56,34,16,1,2,47,139,227,245,181,94,36,2,-42,-106,-158,-178,-178,-179,-189,
--201,-216,-238,-268,-304,-339,-373,-408,-443,-476,-506,-534,-564,-596,-625,-649,-672,-701,-736,-767,-791,
--808,-825,-842,-861,-878,-895,-911,-929,-948,-968,-986,-1003,-1017,-1028,-1037,-1046,-1057,-1069,-1082,-1098,-1119,
--1143,-1165,-1177,-1183,-1186,-1191,-1201,-1209,-1212,-1214,-1219,-1231,-1242,-1248,-1250,-1252,-1256,-1261,-1265,-1273,-1283,
--1294,-1306,-1318,-1326,-1328,-1328,-1328,-1326,-1323,-1321,-1322,-1324,-1321,-1315,-1311,-1310,-1307,-1303,-1303,-1305,-1303,
--1295,-1285,-1276,-1269,-1263,-1259,-1255,-1245,-1228,-1210,-1195,-1181,-1164,-1145,-1128,-1115,-1104,-1094,-1086,-1078,-1069,
--1063,-1060,-1055,-1044,-1032,-1024,-1021,-1017,-1011,-1009,-1009,-1007,-1002,-998,-997,-997,-1000,-1008,-1017,-1023,-1025,
--1030,-1040,-1051,-1057,-1062,-1070,-1082,-1097,-1110,-1120,-1129,-1142,-1162,-1191,-1222,-1248,-1261,-1267,-1273,-1282,-1290,
--1294,-1293,-1293,-1296,-1299,-1299,-1297,-1299,-1302,-1301,-1296,-1291,-1290,-1291,-1291,-1289,-1286,-1283,-1283,-1287,-1291,
--1290,-1285,-1282,-1281,-1277,-1271,-1266,-1262,-1255,-1243,-1234,-1229,-1222,-1208,-1191,-1176,-1162,-1148,-1135,-1123,-1103,
--1075,-1047,-1027,-1008,-982,-954,-931,-911,-885,-852,-821,-794,-761,-721,-684,-655,-625,-585,-542,-506,-472,
--434,-392,-352,-306,-250,-196,-156,-123,-79,-27,9,22,22,3,-68,-189,-273,-213,9,315,616,
-875,1078,1213,1307,1440,1655,1871,1953,1869,1724,1616,1526,1391,1236,1152,1179,1260,1324,1367,1422,1501,
-1594,1711,1874,2067,2237,2331,2346,2325,2311,2320,2341,2368,2413,2486,2567,2612,2597,2543,2493,2466,2447,
-2413,2356,2282,2204,2138,2093,2059,2014,1954,1889,1833,1781,1712,1610,1483,1354,1252,1188,1149,1117,1082,
-1056,1044,1035,1006,950,880,808,729,636,533,437,356,283,208,130,56,-10,-77,-147,-219,-293,
--371,-453,-533,-609,-686,-769,-850,-927,-999,-1074,-1153,-1230,-1304,-1378,-1451,-1517,-1573,-1621,-1664,-1703,-1742,
--1782,-1818,-1844,-1859,-1867,-1876,-1887,-1896,-1909,-1929,-1952,-1968,-1979,-2010,-2083,-2190,-2292,-2353,-2367,-2353,-2329,
--2304,-2281,-2268,-2264,-2260,-2251,-2240,-2234,-2233,-2230,-2221,-2207,-2192,-2178,-2168,-2159,-2146,-2126,-2104,-2077,-2031,
--1951,-1844,-1737,-1652,-1588,-1524,-1449,-1367,-1294,-1239,-1203,-1175,-1146,-1115,-1086,-1062,-1034,-992,-940,-890,-853,
--824,-792,-751,-706,-667,-638,-615,-591,-568,-553,-548,-553,-570,-613,-698,-822,-953,-1056,-1111,-1127,-1122,
--1108,-1092,-1080,-1078,-1085,-1093,-1089,-1067,-1032,-991,-955,-924,-894,-864,-836,-815,-805,-798,-788,-775,-763,
--753,-739,-717,-692,-667,-639,-606,-572,-543,-518,-492,-468,-447,-424,-390,-347,-303,-264,-225,-182,-132,
--76,-17,38,87,135,187,243,301,358,418,479,535,588,644,701,753,796,838,879,918,950,
-982,1016,1047,1069,1088,1113,1144,1177,1215,1266,1325,1376,1413,1443,1468,1485,1487,1480,1477,1479,1481,
-1481,1483,1484,1481,1474,1467,1463,1459,1457,1457,1458,1457,1452,1447,1446,1447,1451,1456,1464,1469,1466,
-1458,1454,1455,1460,1468,1479,1493,1497,1490,1478,1476,1481,1485,1485,1491,1502,1510,1506,1497,1484,1464,
-1435,1408,1389,1364,1316,1262,1224,1189,1175,1155,1106,1049,1017,1013,1008,985,960,949,946,937,923,
-911,904,899,898,904,913,912,903,896,893,891,887,886,891,897,900,902,904,907,913,924,
-939,953,966,981,999,1013,1018,1023,1040,1067,1089,1103,1125,1174,1254,1348,1438,1506,1534,1510,1447,
-1380,1336,1314,1296,1266,1225,1170,1089,981,875,808,789,786,765,722,680,652,627,590,539,479,
-414,344,271,200,133,69,10,-42,-93,-144,-194,-244,-294,-343,-389,-433,-480,-533,-583,-615,-638,
--672,-739,-835,-938,-1024,-1091,-1149,-1192,-1193,-1129,-1022,-939,-929,-980,-1041,-1086,-1125,-1173,-1221,-1256,-1285,
--1328,-1397,-1473,-1511,-1460,-1315,-1158,-1105,-1207,-1384,-1509,-1524,-1481,-1460,-1492,-1548,-1589,-1591,-1550,-1484,-1438,
--1458,-1559,-1706,-1843,-1936,-1994,-2048,-2115,-2188,-2253,-2313,-2377,-2445,-2507,-2558,-2614,-2696,-2809,-2935,-3046,-3130,
--3193,-3254,-3318,-3371,-3400,-3415,-3437,-3473,-3509,-3533,-3548,-3556,-3559,-3555,-3555,-3564,-3584,-3613,-3647,-3687,-3738,
--3802,-3854,-3825,-3670,-3450,-3326,-3420,-3681,-3930,-4017,-3936,-3788,-3669,-3602,-3568,-3552,-3554,-3578,-3609,-3627,-3618,
--3588,-3540,-3482,-3447,-3481,-3589,-3706,-3744,-3688,-3613,-3595,-3634,-3678,-3690,-3681,-3683,-3707,-3739,-3754,-3751,-3751,
--3784,-3845,-3905,-3940,-3961,-3999,-4061,-4129,-4175,-4188,-4178,-4165,-4162,-4168,-4179,-4209,-4279,-4384,-4488,-4563,-4617,
--4671,-4729,-4785,-4845,-4922,-5012,-5095,-5160,-5220,-5286,-5355,-5423,-5491,-5557,-5613,-5656,-5696,-5737,-5774,-5809,-5853,
--5909,-5960,-5998,-6038,-6100,-6183,-6264,-6330,-6389,-6454,-6527,-6595,-6639,-6654,-6656,-6673,-6716,-6772,-6824,-6877,-6944,
--7028,-7120,-7215,-7313,-7413,-7508,-7590,-7653,-7695,-7722,-7748,-7780,-7817,-7856,-7897,-7938,-7972,-8000,-8029,-8064,-8093,
--8110,-8126,-8151,-8176,-8183,-8180,-8183,-8193,-8185,-8152,-8113,-8084,-8060,-8032,-8003,-7978,-7953,-7921,-7891,-7876,-7870,
--7864,-7853,-7838,-7818,-7792,-7762,-7729,-7687,-7633,-7576,-7531,-7494,-7455,-7410,-7365,-7318,-7262,-7201,-7142,-7088,-7031,
--6972,-6902,-6806,-6683,-6570,-6512,-6511,-6522,-6510,-6477,-6421,-6321,-6175,-6042,-5980,-5967,-5926,-5820,-5691,-5589,-5511,
--5425,-5322,-5213,-5098,-4965,-4828,-4712,-4620,-4527,-4423,-4330,-4270,-4223,-4148,-4023,-3861,-3691,-3531,-3384,-3245,-3114,
--3000,-2914,-2848,-2782,-2697,-2601,-2507,-2421,-2331,-2227,-2111,-1988,-1862,-1744,-1644,-1556,-1461,-1358,-1269,-1209,-1167,
--1123,-1080,-1057,-1069,-1113,-1166,-1195,-1168,-1077,-947,-819,-715,-630,-553,-474,-370,-221,-29,177,377,579,
-794,1012,1210,1386,1557,1729,1886,2010,2098,2164,2213,2253,2299,2377,2497,2633,2737,2796,2851,2947,3067,
-3153,3191,3234,3328,3438,3494,3485,3461,3459,3476,3513,3593,3711,3808,3834,3813,3801,3822,3856,3886,3919,
-3959,3999,4047,4107,4151,4143,4085,4027,4003,4005,4017,4042,4075,4074,4012,3932,3918,3992,4101,4187,4254,
-4331,4418,4486,4529,4571,4619,4646,4612,4508,4344,4136,3907,3696,3555,3521,3586,3704,3830,3934,4020,4103,
-4205,4335,4487,4638,4764,4863,4958,5075,5221,5379,5532,5684,5837,5977,6081,6147,6194,6247,6310,6382,6464,
-6549,6620,6663,6684,6700,6719,6734,6741,6749,6763,6779,6794,6813,6849,6902,6961,7011,7044,7058,7060,7061,
-7070,7089,7115,7149,7194,7248,7307,7366,7416,7451,7468,7468,7455,7437,7428,7439,7461,7468,7446,7408,7381,
-7365,7341,7319,7364,7550,7873,8221,8446,8462,8293,8033,7782,7611,7548,7568,7622,7677,7742,7836,7936,7986,
-7955,7863,7742,7598,7433,7275,7158,7086,7032,6986,6967,6994,7061,7134,7184,7195,7171,7130,7089,7050,7006,
-6963,6934,6924,6932,6949,6957,6923,6813,6626,6398,6199,6104,6149,6283,6376,6341,6233,6177,6193,6153,5943,
-5630,5402,5373,5507,5698,5865,5970,6005,5995,5976,5950,5888,5782,5664,5565,5479,5394,5318,5265,5220,5167,
-5120,5105,5115,5122,5108,5075,5024,4952,4877,4828,4807,4783,4729,4650,4572,4510,4458,4406,4348,4286,4229,
-4186,4158,4137,4113,4081,4044,4015,3997,3981,3952,3917,3891,3875,3844,3788,3733,3705,3688,3647,3586,3540,
-3518,3493,3451,3413,3394,3372,3330,3289,3271,3254,3194,3090,2995,2943,2918,2885,2842,2806,2782,2761,2737,
-2713,2687,2652,2608,2564,2524,2487,2447,2406,2368,2334,2307,2291,2284,2277,2254,2221,2205,2229,2281,2314,
-2289,2217,2139,2088,2066,2059,2056,2049,2031,2003,1969,1936,1903,1867,1834,1807,1785,1759,1730,1705,1691,
-1685,1681,1671,1656,1639,1622,1608,1596,1583,1561,1524,1483,1458,1462,1487,1511,1514,1490,1449,1410,1385,
-1378,1370,1345,1302,1262,1241,1231,1211,1176,1132,1084,1027,980,974,1027,1101,1129,1079,988,920,903,
-906,894,867,852,859,869,864,849,834,823,818,821,828,823,806,798,809,816,793,757,749,
-778,797,765,694,628,591,569,550,531,513,488,457,425,397,366,333,308,289,267,239,211,
-187,161,131,106,94,90,88,89,91,88,78,66,56,42,22,2,-12,-29,-41,-19,53,
-142,187,170,131,104,76,13,-80,-161,-200,-207,-206,-212,-222,-235,-256,-284,-317,-351,-386,-420,
--452,-483,-512,-539,-567,-597,-627,-657,-685,-716,-748,-779,-802,-820,-836,-853,-871,-887,-900,-912,-926,
--944,-963,-982,-999,-1013,-1024,-1033,-1040,-1049,-1058,-1067,-1080,-1101,-1128,-1154,-1171,-1179,-1181,-1183,-1187,-1192,
--1193,-1193,-1196,-1204,-1213,-1215,-1215,-1216,-1221,-1227,-1232,-1239,-1249,-1261,-1272,-1284,-1293,-1299,-1302,-1305,-1306,
--1306,-1304,-1303,-1302,-1298,-1292,-1289,-1286,-1280,-1272,-1268,-1268,-1267,-1262,-1253,-1244,-1236,-1229,-1223,-1217,-1205,
--1188,-1170,-1156,-1143,-1127,-1109,-1092,-1077,-1065,-1055,-1050,-1044,-1036,-1028,-1024,-1020,-1012,-1001,-992,-988,-984,
--980,-978,-979,-978,-975,-972,-971,-972,-975,-981,-990,-997,-1002,-1008,-1018,-1030,-1039,-1046,-1053,-1064,-1076,
--1089,-1099,-1110,-1125,-1147,-1175,-1203,-1226,-1239,-1245,-1249,-1254,-1260,-1266,-1270,-1277,-1285,-1289,-1287,-1283,-1283,
--1287,-1289,-1288,-1286,-1286,-1287,-1287,-1286,-1281,-1274,-1271,-1274,-1278,-1276,-1269,-1263,-1261,-1258,-1253,-1248,-1245,
--1240,-1231,-1225,-1219,-1209,-1191,-1174,-1162,-1150,-1135,-1123,-1113,-1097,-1071,-1042,-1021,-1004,-981,-951,-926,-906,
--880,-848,-816,-788,-756,-718,-682,-652,-622,-585,-547,-512,-477,-436,-396,-361,-320,-263,-202,-156,-122,
--79,-28,9,22,27,24,-22,-129,-234,-232,-69,213,535,836,1075,1231,1327,1435,1595,1753,1814,
-1761,1672,1610,1552,1455,1340,1277,1289,1337,1383,1435,1511,1596,1670,1751,1880,2060,2242,2365,2407,2392,
-2367,2360,2376,2406,2450,2513,2586,2636,2638,2601,2557,2525,2498,2457,2396,2320,2243,2181,2141,2112,2070,
-2009,1941,1882,1830,1760,1655,1528,1406,1316,1260,1218,1173,1126,1096,1091,1092,1071,1018,950,883,813,
-724,617,514,428,354,275,193,118,53,-10,-83,-165,-249,-331,-410,-484,-554,-632,-717,-802,-878,
--950,-1026,-1106,-1183,-1253,-1319,-1384,-1447,-1504,-1555,-1602,-1642,-1679,-1716,-1753,-1782,-1799,-1809,-1819,-1829,-1839,
--1852,-1874,-1901,-1922,-1939,-1976,-2057,-2177,-2293,-2361,-2369,-2338,-2296,-2261,-2237,-2225,-2218,-2209,-2194,-2179,-2170,
--2165,-2155,-2139,-2123,-2109,-2097,-2083,-2069,-2058,-2045,-2029,-2003,-1953,-1866,-1749,-1632,-1545,-1491,-1452,-1406,-1355,
--1306,-1266,-1233,-1204,-1174,-1144,-1114,-1085,-1054,-1015,-968,-924,-894,-876,-852,-810,-753,-699,-662,-642,-629,
--612,-590,-572,-573,-601,-665,-763,-882,-998,-1086,-1136,-1152,-1147,-1130,-1110,-1092,-1083,-1082,-1081,-1075,-1060,
--1037,-1006,-969,-933,-903,-877,-852,-831,-816,-805,-794,-783,-775,-769,-753,-726,-696,-669,-642,-611,-579,
--553,-529,-503,-475,-450,-423,-387,-342,-299,-263,-230,-192,-145,-88,-24,40,98,150,201,253,306,
-362,423,486,542,593,644,698,747,788,829,873,914,948,980,1013,1044,1069,1090,1118,1150,1182,
-1215,1256,1302,1344,1377,1410,1442,1459,1457,1448,1445,1450,1452,1451,1449,1448,1444,1435,1427,1426,1430,
-1434,1436,1436,1431,1425,1422,1426,1433,1441,1449,1456,1460,1456,1448,1442,1443,1448,1455,1467,1481,1486,
-1477,1462,1455,1457,1459,1459,1462,1472,1479,1476,1466,1450,1426,1392,1361,1341,1319,1277,1224,1191,1148,
-1118,1085,1041,1003,993,1002,1000,979,956,944,936,925,913,908,908,908,911,920,930,929,921,
-916,917,918,916,916,921,927,932,937,944,949,954,964,982,1001,1018,1034,1051,1062,1062,1063,
-1082,1117,1150,1170,1193,1243,1326,1419,1499,1551,1568,1547,1499,1449,1417,1402,1384,1349,1301,1242,1166,
-1068,968,899,870,855,827,783,741,710,681,643,595,539,476,406,333,265,202,143,86,32,
--20,-71,-122,-172,-223,-279,-339,-400,-458,-509,-550,-585,-623,-674,-743,-826,-912,-985,-1034,-1063,-1074,
--1058,-999,-914,-851,-852,-911,-991,-1064,-1136,-1213,-1282,-1332,-1362,-1383,-1404,-1426,-1438,-1408,-1313,-1184,-1106,
--1137,-1243,-1332,-1356,-1351,-1367,-1409,-1449,-1465,-1459,-1434,-1406,-1413,-1499,-1657,-1818,-1914,-1941,-1957,-2012,-2105,
--2197,-2265,-2318,-2374,-2433,-2482,-2521,-2571,-2661,-2800,-2960,-3098,-3184,-3233,-3274,-3321,-3358,-3372,-3376,-3394,-3427,
--3460,-3482,-3493,-3498,-3500,-3502,-3511,-3522,-3533,-3546,-3575,-3623,-3686,-3761,-3819,-3797,-3646,-3421,-3279,-3347,-3590,
--3834,-3921,-3834,-3675,-3556,-3514,-3518,-3522,-3516,-3522,-3550,-3572,-3552,-3487,-3410,-3357,-3351,-3405,-3511,-3623,-3679,
--3662,-3616,-3591,-3598,-3611,-3612,-3611,-3623,-3652,-3685,-3708,-3714,-3716,-3736,-3783,-3836,-3874,-3903,-3944,-4006,-4069,
--4111,-4126,-4128,-4132,-4133,-4122,-4103,-4107,-4168,-4282,-4404,-4495,-4553,-4599,-4648,-4703,-4767,-4844,-4929,-5006,-5074,
--5142,-5210,-5275,-5339,-5406,-5471,-5522,-5560,-5600,-5643,-5682,-5716,-5758,-5815,-5875,-5928,-5980,-6043,-6113,-6176,-6229,
--6284,-6350,-6421,-6483,-6520,-6532,-6539,-6565,-6618,-6681,-6738,-6793,-6858,-6937,-7022,-7109,-7206,-7311,-7413,-7498,-7558,
--7598,-7625,-7651,-7684,-7721,-7760,-7800,-7840,-7877,-7911,-7944,-7977,-8004,-8022,-8041,-8065,-8082,-8084,-8079,-8081,-8086,
--8073,-8041,-8006,-7983,-7965,-7942,-7915,-7887,-7854,-7815,-7784,-7774,-7780,-7783,-7778,-7764,-7741,-7712,-7677,-7640,-7595,
--7544,-7496,-7458,-7424,-7386,-7343,-7298,-7250,-7192,-7133,-7080,-7031,-6980,-6924,-6858,-6766,-6646,-6538,-6489,-6498,-6517,
--6508,-6473,-6411,-6304,-6157,-6026,-5965,-5950,-5907,-5807,-5689,-5599,-5531,-5449,-5340,-5217,-5089,-4964,-4855,-4766,-4675,
--4554,-4416,-4307,-4255,-4231,-4177,-4062,-3900,-3726,-3566,-3422,-3290,-3168,-3066,-2991,-2932,-2867,-2781,-2680,-2579,-2481,
--2381,-2272,-2154,-2026,-1898,-1785,-1696,-1611,-1509,-1393,-1295,-1231,-1183,-1127,-1059,-1002,-979,-997,-1046,-1095,-1107,
--1059,-967,-862,-763,-673,-594,-528,-461,-372,-262,-151,-44,85,257,455,646,826,1015,1221,1414,1562,
-1655,1712,1761,1822,1907,2019,2151,2281,2387,2466,2544,2644,2752,2835,2889,2956,3064,3182,3260,3294,3318,
-3353,3394,3457,3573,3720,3815,3800,3720,3664,3670,3706,3743,3789,3855,3931,4001,4059,4091,4072,4010,3950,
-3922,3911,3883,3836,3785,3726,3651,3589,3596,3681,3799,3907,4012,4136,4267,4369,4428,4464,4490,4490,4436,
-4317,4143,3926,3693,3487,3361,3347,3441,3603,3783,3938,4057,4161,4281,4431,4598,4757,4892,5010,5129,5261,
-5397,5523,5633,5742,5860,5975,6067,6129,6177,6226,6282,6342,6414,6498,6578,6636,6668,6685,6692,6690,6688,
-6695,6713,6732,6751,6781,6828,6881,6928,6964,6996,7022,7036,7042,7051,7071,7101,7137,7178,7227,7283,7344,
-7401,7442,7462,7463,7452,7437,7428,7437,7464,7489,7486,7446,7384,7315,7248,7200,7222,7373,7654,7984,8244,
-8355,8312,8159,7959,7783,7683,7667,7699,7745,7807,7892,7970,7987,7933,7856,7793,7736,7661,7572,7488,7395,
-7268,7126,7040,7060,7156,7248,7277,7241,7178,7129,7104,7087,7056,7010,6961,6922,6900,6895,6897,6877,6811,
-6687,6521,6346,6220,6196,6260,6315,6271,6163,6109,6154,6192,6088,5835,5562,5407,5422,5574,5781,5948,6021,
-6022,6005,5983,5919,5804,5685,5601,5546,5498,5458,5434,5406,5355,5295,5255,5241,5231,5210,5176,5120,5034,
-4941,4881,4866,4863,4831,4760,4675,4599,4541,4490,4434,4367,4300,4248,4212,4183,4157,4129,4098,4066,4042,
-4026,4008,3982,3955,3934,3907,3860,3805,3765,3737,3696,3638,3586,3554,3524,3482,3443,3421,3401,3367,3333,
-3318,3307,3260,3173,3085,3027,2990,2946,2894,2851,2826,2807,2786,2762,2736,2703,2664,2625,2588,2549,2504,
-2460,2425,2398,2377,2363,2358,2356,2343,2314,2289,2290,2313,2328,2307,2257,2206,2170,2144,2120,2098,2079,
-2059,2034,2006,1977,1943,1901,1856,1816,1785,1759,1732,1709,1691,1681,1673,1662,1646,1627,1606,1586,1569,
-1554,1533,1499,1463,1449,1470,1507,1526,1515,1488,1457,1420,1373,1330,1306,1293,1277,1255,1236,1218,1186,
-1138,1087,1041,994,960,979,1070,1187,1234,1165,1030,924,890,889,873,841,825,833,841,834,819,
-809,802,795,794,798,793,773,759,768,782,772,741,726,742,759,741,688,630,582,547,522,
-509,498,475,443,414,389,360,326,295,271,243,210,180,157,133,106,83,71,62,54,51,
-53,50,37,22,15,6,-8,-25,-39,-58,-84,-91,-42,53,151,210,230,217,161,56,-68,
--167,-217,-233,-235,-237,-241,-253,-273,-299,-328,-360,-395,-429,-460,-489,-519,-547,-572,-599,-629,-661,
--694,-726,-757,-785,-807,-824,-839,-854,-872,-888,-902,-913,-926,-942,-959,-976,-992,-1006,-1018,-1028,-1037,
--1044,-1049,-1053,-1062,-1081,-1107,-1133,-1151,-1160,-1163,-1163,-1165,-1169,-1171,-1170,-1171,-1175,-1179,-1179,-1177,-1178,
--1183,-1188,-1193,-1201,-1213,-1225,-1235,-1246,-1256,-1264,-1271,-1277,-1283,-1286,-1285,-1282,-1279,-1276,-1272,-1269,-1264,
--1256,-1245,-1236,-1232,-1230,-1226,-1218,-1210,-1201,-1192,-1183,-1173,-1160,-1143,-1125,-1112,-1101,-1087,-1071,-1056,-1042,
--1027,-1016,-1010,-1006,-997,-987,-981,-980,-976,-967,-958,-953,-950,-948,-947,-948,-948,-947,-945,-947,-950,
--953,-955,-959,-966,-974,-983,-994,-1006,-1018,-1028,-1038,-1049,-1060,-1072,-1083,-1097,-1116,-1140,-1166,-1191,-1210,
--1224,-1230,-1231,-1231,-1235,-1242,-1251,-1262,-1273,-1277,-1273,-1268,-1267,-1271,-1275,-1277,-1278,-1280,-1281,-1281,-1280,
--1275,-1267,-1261,-1261,-1261,-1257,-1248,-1242,-1240,-1238,-1233,-1228,-1225,-1221,-1216,-1212,-1207,-1196,-1178,-1161,-1150,
--1138,-1121,-1106,-1097,-1085,-1061,-1032,-1010,-994,-973,-944,-917,-895,-871,-841,-810,-783,-752,-717,-682,-652,
--620,-584,-549,-517,-482,-438,-395,-358,-320,-269,-212,-164,-125,-80,-29,6,19,26,33,11,-71,
--184,-239,-157,72,393,726,1005,1196,1317,1416,1528,1641,1720,1758,1770,1759,1711,1631,1557,1519,1505,
-1499,1512,1571,1664,1740,1772,1801,1887,2047,2236,2386,2459,2462,2435,2417,2425,2453,2489,2533,2585,2629,
-2648,2638,2614,2590,2558,2509,2441,2367,2302,2251,2214,2179,2132,2069,2003,1949,1900,1835,1735,1614,1501,
-1416,1356,1298,1234,1175,1143,1144,1154,1140,1091,1025,960,891,803,694,586,497,420,340,256,180,
-115,48,-30,-119,-208,-295,-374,-445,-511,-584,-668,-751,-819,-872,-927,-996,-1077,-1164,-1247,-1319,-1374,
--1418,-1462,-1510,-1558,-1597,-1631,-1661,-1685,-1699,-1708,-1719,-1733,-1746,-1760,-1782,-1815,-1848,-1880,-1925,-2008,-2125,
--2240,-2308,-2313,-2279,-2238,-2207,-2186,-2172,-2161,-2150,-2135,-2122,-2114,-2107,-2092,-2066,-2038,-2018,-2003,-1991,-1981,
--1970,-1951,-1920,-1879,-1823,-1744,-1641,-1538,-1466,-1434,-1423,-1409,-1383,-1351,-1317,-1282,-1249,-1218,-1181,-1137,-1095,
--1066,-1047,-1023,-986,-946,-917,-890,-850,-789,-726,-684,-671,-671,-663,-639,-613,-612,-656,-745,-860,-974,
--1062,-1115,-1137,-1139,-1133,-1123,-1111,-1097,-1086,-1077,-1067,-1055,-1044,-1033,-1014,-984,-950,-922,-899,-874,-849,
--830,-817,-803,-790,-779,-770,-753,-723,-690,-662,-637,-610,-581,-558,-535,-506,-473,-441,-409,-372,-328,
--285,-250,-218,-182,-138,-84,-20,48,114,173,224,271,318,371,432,494,546,591,637,685,729,
-767,805,849,894,932,964,996,1026,1052,1078,1109,1142,1172,1202,1237,1276,1313,1348,1387,1423,1441,
-1436,1423,1420,1423,1424,1420,1416,1413,1407,1396,1388,1392,1405,1416,1421,1418,1411,1406,1408,1417,1429,
-1438,1443,1444,1442,1436,1427,1420,1417,1418,1424,1435,1449,1456,1451,1439,1432,1432,1435,1435,1434,1436,
-1439,1436,1426,1409,1383,1350,1322,1304,1283,1243,1191,1160,1121,1093,1057,1012,979,975,987,990,977,
-962,951,940,924,912,911,915,917,921,929,938,940,936,935,938,940,939,941,948,955,962,
-971,984,994,1000,1009,1028,1052,1071,1084,1096,1106,1112,1119,1144,1186,1227,1253,1278,1329,1412,1502,
-1566,1596,1598,1582,1555,1528,1513,1507,1495,1462,1411,1346,1268,1177,1089,1022,978,940,892,840,798,
-764,729,687,641,591,532,464,392,326,267,211,158,106,55,3,-48,-100,-158,-229,-313,-400,
--473,-525,-562,-598,-644,-697,-755,-820,-889,-945,-965,-952,-931,-913,-887,-838,-790,-785,-839,-931,-1033,
--1133,-1222,-1290,-1332,-1359,-1380,-1390,-1381,-1357,-1316,-1250,-1168,-1115,-1125,-1177,-1212,-1213,-1218,-1262,-1326,-1365,
--1359,-1325,-1289,-1281,-1342,-1494,-1697,-1863,-1930,-1929,-1944,-2021,-2135,-2234,-2298,-2341,-2380,-2417,-2446,-2475,-2524,
--2617,-2767,-2948,-3112,-3219,-3272,-3305,-3334,-3349,-3341,-3329,-3338,-3370,-3403,-3425,-3438,-3444,-3448,-3456,-3470,-3480,
--3478,-3479,-3504,-3556,-3615,-3668,-3701,-3687,-3596,-3454,-3361,-3405,-3572,-3745,-3806,-3727,-3581,-3474,-3456,-3491,-3504,
--3472,-3438,-3449,-3481,-3469,-3397,-3316,-3286,-3315,-3377,-3450,-3519,-3571,-3592,-3588,-3574,-3558,-3542,-3535,-3546,-3573,
--3606,-3634,-3655,-3666,-3676,-3699,-3742,-3790,-3825,-3853,-3893,-3952,-4013,-4055,-4078,-4093,-4108,-4109,-4083,-4042,-4030,
--4085,-4200,-4330,-4428,-4488,-4532,-4579,-4635,-4698,-4769,-4843,-4916,-4989,-5064,-5134,-5196,-5256,-5320,-5383,-5432,-5468,
--5506,-5551,-5594,-5631,-5672,-5727,-5790,-5849,-5904,-5959,-6012,-6063,-6118,-6184,-6257,-6325,-6376,-6405,-6421,-6439,-6474,
--6529,-6592,-6650,-6709,-6778,-6852,-6927,-7008,-7103,-7212,-7317,-7400,-7459,-7498,-7527,-7556,-7591,-7630,-7668,-7706,-7744,
--7782,-7818,-7851,-7881,-7907,-7928,-7949,-7970,-7982,-7982,-7980,-7985,-7989,-7975,-7948,-7922,-7906,-7891,-7868,-7839,-7809,
--7772,-7733,-7707,-7704,-7713,-7718,-7709,-7690,-7665,-7636,-7602,-7562,-7513,-7463,-7421,-7391,-7361,-7322,-7277,-7229,-7176,
--7119,-7065,-7021,-6980,-6933,-6881,-6818,-6728,-6613,-6513,-6473,-6487,-6508,-6500,-6462,-6396,-6288,-6145,-6020,-5956,-5932,
--5887,-5800,-5703,-5622,-5548,-5454,-5337,-5212,-5092,-4987,-4905,-4830,-4725,-4571,-4405,-4289,-4251,-4246,-4202,-4084,-3913,
--3739,-3593,-3469,-3350,-3233,-3136,-3070,-3018,-2951,-2857,-2750,-2642,-2535,-2423,-2308,-2190,-2064,-1938,-1832,-1754,-1680,
--1579,-1459,-1355,-1286,-1233,-1168,-1085,-1002,-938,-905,-909,-939,-968,-969,-941,-895,-834,-756,-669,-585,-505,
--420,-338,-277,-229,-159,-41,102,238,370,528,722,910,1044,1110,1140,1181,1267,1398,1553,1708,1847,
-1968,2076,2178,2276,2358,2415,2460,2525,2629,2748,2847,2923,2996,3068,3134,3212,3334,3475,3547,3502,3393,
-3327,3347,3416,3499,3599,3724,3848,3933,3971,3967,3919,3835,3748,3684,3633,3562,3463,3363,3283,3232,3227,
-3288,3418,3578,3733,3874,4008,4123,4198,4230,4233,4218,4178,4106,4007,3884,3741,3589,3459,3392,3413,3524,
-3701,3905,4095,4248,4377,4506,4646,4789,4921,5046,5174,5307,5435,5543,5627,5699,5780,5881,5984,6066,6119,
-6158,6196,6238,6288,6358,6451,6548,6620,6656,6666,6661,6650,6642,6647,6663,6683,6710,6749,6796,6837,6863,
-6888,6929,6982,7025,7047,7058,7074,7101,7136,7174,7216,7267,7328,7391,7438,7460,7461,7451,7441,7433,7438,
-7462,7492,7492,7440,7345,7240,7149,7088,7089,7194,7415,7701,7973,8163,8246,8218,8101,7948,7827,7772,7759,
-7762,7785,7841,7899,7902,7839,7765,7726,7719,7716,7711,7702,7654,7530,7360,7240,7229,7294,7343,7320,7242,
-7164,7121,7109,7100,7074,7032,6984,6936,6890,6851,6822,6793,6754,6695,6607,6491,6373,6306,6315,6346,6321,
-6230,6154,6151,6184,6153,6005,5775,5556,5449,5508,5689,5872,5960,5961,5944,5933,5892,5803,5709,5654,5632,
-5614,5595,5584,5567,5524,5465,5415,5381,5350,5317,5281,5232,5150,5048,4966,4930,4925,4913,4870,4798,4716,
-4642,4577,4512,4442,4375,4322,4280,4240,4204,4178,4154,4125,4098,4085,4077,4054,4013,3973,3943,3910,3868,
-3825,3787,3743,3687,3633,3592,3555,3513,3474,3450,3430,3397,3355,3332,3328,3312,3262,3189,3116,3051,2990,
-2936,2901,2883,2871,2853,2827,2795,2756,2715,2679,2648,2612,2566,2518,2482,2462,2452,2446,2444,2443,2433,
-2409,2378,2358,2351,2342,2323,2303,2292,2286,2265,2220,2164,2114,2079,2051,2026,2000,1970,1932,1885,1837,
-1795,1764,1742,1723,1705,1690,1675,1657,1635,1614,1594,1575,1557,1539,1520,1495,1471,1469,1498,1533,1539,
-1512,1478,1453,1422,1368,1307,1269,1255,1246,1230,1215,1202,1172,1119,1061,1012,973,948,970,1065,1186,
-1238,1166,1022,908,868,864,843,808,795,809,822,814,797,786,780,771,766,769,766,749,731,
-733,749,750,729,710,709,712,699,666,623,576,530,499,488,481,460,427,397,374,348,314,
-281,252,221,186,154,130,108,85,67,55,41,25,16,17,14,0,-16,-22,-26,-39,-55,
--66,-83,-118,-149,-132,-47,77,187,245,235,160,45,-68,-151,-202,-236,-257,-265,-267,-275,-293,
--316,-342,-372,-406,-439,-468,-497,-528,-555,-579,-602,-629,-661,-695,-727,-757,-782,-803,-819,-834,-849,
--866,-884,-899,-912,-925,-938,-953,-968,-982,-995,-1009,-1021,-1031,-1038,-1040,-1040,-1045,-1061,-1083,-1105,-1122,
--1132,-1135,-1134,-1135,-1139,-1144,-1145,-1144,-1145,-1146,-1145,-1143,-1144,-1148,-1152,-1156,-1164,-1176,-1189,-1199,-1208,
--1218,-1227,-1235,-1243,-1251,-1257,-1256,-1253,-1251,-1251,-1250,-1247,-1241,-1232,-1221,-1210,-1201,-1194,-1186,-1179,-1173,
--1164,-1153,-1140,-1129,-1115,-1099,-1082,-1068,-1056,-1043,-1029,-1017,-1005,-992,-980,-972,-967,-958,-947,-940,-938,
--937,-932,-923,-918,-916,-915,-915,-916,-917,-917,-918,-923,-930,-935,-936,-936,-940,-949,-960,-969,-979,
--991,-1005,-1018,-1030,-1043,-1055,-1070,-1088,-1112,-1139,-1164,-1183,-1198,-1210,-1215,-1216,-1215,-1219,-1228,-1238,-1248,
--1256,-1259,-1257,-1254,-1254,-1257,-1259,-1261,-1263,-1265,-1265,-1263,-1260,-1257,-1250,-1244,-1241,-1239,-1233,-1224,-1219,
--1219,-1219,-1214,-1208,-1204,-1200,-1196,-1194,-1190,-1180,-1164,-1148,-1138,-1126,-1108,-1090,-1079,-1067,-1047,-1020,-997,
--980,-960,-932,-903,-879,-856,-829,-801,-773,-743,-711,-681,-652,-618,-581,-546,-516,-482,-439,-391,-349,
--310,-266,-218,-174,-131,-82,-30,7,23,29,34,24,-31,-133,-225,-220,-60,234,581,890,1117,
-1268,1375,1471,1584,1730,1892,2011,2036,1985,1927,1909,1901,1850,1766,1725,1774,1869,1921,1905,1880,1927,
-2067,2252,2411,2500,2513,2485,2459,2464,2491,2523,2551,2582,2617,2643,2653,2651,2640,2615,2566,2501,2435,
-2382,2340,2302,2260,2211,2151,2088,2033,1983,1923,1836,1730,1626,1540,1462,1377,1290,1221,1193,1203,1218,
-1208,1162,1098,1035,969,881,772,662,570,491,410,325,245,172,94,8,-81,-167,-252,-334,-405,
--467,-535,-618,-699,-751,-769,-782,-825,-917,-1044,-1171,-1263,-1306,-1318,-1337,-1379,-1436,-1488,-1525,-1547,-1557,
--1559,-1561,-1575,-1598,-1621,-1638,-1660,-1696,-1744,-1796,-1857,-1942,-2053,-2159,-2222,-2230,-2207,-2183,-2166,-2148,-2127,
--2110,-2096,-2083,-2068,-2057,-2046,-2025,-1988,-1946,-1914,-1897,-1890,-1884,-1865,-1826,-1771,-1718,-1674,-1627,-1564,-1495,
--1450,-1440,-1449,-1451,-1437,-1410,-1375,-1335,-1298,-1261,-1213,-1150,-1095,-1076,-1089,-1095,-1060,-995,-938,-903,-872,
--821,-758,-709,-694,-702,-707,-697,-683,-696,-757,-858,-970,-1061,-1114,-1130,-1124,-1111,-1105,-1104,-1104,-1100,
--1092,-1082,-1067,-1049,-1036,-1028,-1015,-991,-961,-936,-914,-889,-862,-841,-827,-813,-794,-776,-761,-743,-716,
--685,-659,-637,-612,-587,-564,-542,-512,-475,-438,-403,-365,-323,-281,-243,-207,-169,-126,-78,-21,44,
-114,178,231,276,320,372,433,492,541,582,625,672,716,751,785,825,869,909,943,973,999,
-1023,1049,1079,1111,1143,1176,1213,1251,1287,1325,1369,1408,1427,1421,1408,1400,1399,1395,1389,1385,1382,
-1375,1364,1357,1363,1379,1395,1402,1401,1396,1395,1402,1413,1425,1431,1430,1424,1417,1411,1406,1400,1395,
-1393,1395,1401,1408,1412,1411,1407,1405,1409,1413,1413,1408,1401,1396,1391,1381,1362,1333,1304,1285,1273,
-1251,1209,1160,1147,1125,1109,1074,1021,976,963,972,979,977,971,964,952,935,923,922,927,929,
-932,938,946,950,951,954,958,959,959,964,973,982,989,1000,1017,1032,1043,1055,1076,1103,1123,
-1133,1143,1157,1174,1193,1222,1265,1306,1334,1361,1412,1493,1577,1631,1648,1644,1631,1615,1598,1589,1591,
-1593,1579,1538,1470,1381,1287,1205,1142,1086,1025,958,899,856,818,776,729,685,639,586,521,454,
-390,332,278,228,179,129,75,22,-32,-97,-186,-294,-403,-490,-547,-588,-630,-675,-716,-750,-792,
--845,-884,-877,-832,-796,-800,-815,-797,-750,-728,-771,-868,-981,-1086,-1174,-1237,-1278,-1310,-1342,-1361,-1345,
--1294,-1229,-1169,-1127,-1120,-1147,-1178,-1177,-1147,-1142,-1201,-1301,-1372,-1369,-1300,-1217,-1188,-1269,-1462,-1692,-1853,
--1905,-1906,-1942,-2041,-2161,-2253,-2311,-2348,-2373,-2388,-2402,-2428,-2477,-2567,-2710,-2895,-3075,-3202,-3271,-3311,-3334,
--3328,-3292,-3258,-3260,-3298,-3341,-3373,-3392,-3404,-3410,-3415,-3424,-3430,-3424,-3422,-3448,-3496,-3531,-3531,-3510,-3494,
--3490,-3491,-3500,-3535,-3600,-3665,-3683,-3624,-3515,-3433,-3436,-3490,-3506,-3443,-3367,-3354,-3390,-3390,-3321,-3249,-3247,
--3310,-3375,-3406,-3420,-3446,-3485,-3518,-3526,-3510,-3486,-3481,-3501,-3536,-3567,-3586,-3598,-3608,-3623,-3653,-3699,-3746,
--3779,-3804,-3844,-3904,-3967,-4013,-4043,-4065,-4080,-4074,-4038,-3991,-3977,-4027,-4132,-4247,-4331,-4384,-4430,-4489,-4557,
--4625,-4691,-4758,-4830,-4907,-4985,-5056,-5118,-5175,-5236,-5295,-5342,-5379,-5417,-5464,-5511,-5553,-5595,-5644,-5698,-5751,
--5802,-5851,-5900,-5952,-6016,-6093,-6170,-6233,-6278,-6307,-6331,-6358,-6398,-6449,-6505,-6562,-6625,-6695,-6766,-6833,-6909,
--7005,-7116,-7221,-7302,-7359,-7398,-7429,-7460,-7497,-7539,-7579,-7617,-7655,-7692,-7727,-7757,-7784,-7810,-7834,-7855,-7871,
--7880,-7883,-7887,-7895,-7898,-7886,-7866,-7850,-7840,-7826,-7803,-7774,-7742,-7708,-7676,-7659,-7660,-7666,-7662,-7645,-7621,
--7595,-7568,-7538,-7500,-7449,-7396,-7355,-7329,-7304,-7266,-7219,-7168,-7112,-7057,-7011,-6978,-6946,-6907,-6859,-6797,-6707,
--6595,-6502,-6467,-6481,-6497,-6487,-6452,-6388,-6282,-6145,-6027,-5962,-5929,-5882,-5808,-5725,-5642,-5549,-5438,-5323,-5214,
--5116,-5030,-4959,-4882,-4762,-4591,-4416,-4302,-4269,-4267,-4220,-4093,-3913,-3741,-3614,-3518,-3418,-3306,-3209,-3145,-3094,
--3020,-2917,-2802,-2690,-2574,-2452,-2334,-2222,-2109,-1996,-1902,-1835,-1768,-1669,-1547,-1436,-1357,-1291,-1213,-1121,-1025,
--933,-853,-802,-787,-798,-817,-840,-864,-872,-842,-776,-692,-601,-498,-396,-314,-256,-192,-102,-5,71,
-139,238,381,524,611,629,624,656,758,915,1087,1244,1388,1532,1676,1803,1892,1941,1961,1982,2036,
-2136,2261,2381,2489,2591,2684,2760,2832,2928,3033,3086,3048,2973,2954,3031,3167,3320,3489,3674,3839,3936,
-3957,3923,3847,3729,3584,3443,3320,3201,3077,2965,2893,2879,2932,3056,3247,3472,3685,3846,3941,3975,3967,
-3940,3903,3855,3791,3727,3681,3658,3644,3628,3616,3633,3697,3818,3989,4184,4369,4522,4648,4764,4880,4990,
-5095,5206,5329,5452,5557,5631,5684,5737,5814,5914,6014,6087,6125,6146,6167,6193,6232,6302,6406,6518,6600,
-6634,6632,6619,6606,6601,6606,6623,6651,6688,6733,6776,6804,6818,6841,6891,6962,7025,7059,7068,7074,7092,
-7126,7167,7209,7254,7310,7375,7429,7456,7458,7452,7447,7444,7447,7459,7469,7442,7361,7243,7129,7043,6986,
-6972,7033,7192,7428,7690,7929,8109,8195,8175,8084,7993,7935,7888,7826,7775,7779,7824,7843,7796,7714,7650,
-7622,7625,7656,7704,7718,7652,7528,7423,7386,7387,7363,7293,7214,7162,7143,7131,7107,7069,7030,6997,6959,
-6908,6849,6792,6744,6700,6656,6604,6531,6440,6373,6374,6434,6486,6474,6400,6311,6239,6176,6084,5923,5709,
-5533,5507,5642,5822,5920,5922,5900,5897,5882,5830,5770,5738,5726,5708,5683,5664,5645,5610,5566,5527,5493,
-5454,5411,5377,5344,5285,5190,5086,5008,4970,4961,4949,4912,4848,4769,4690,4609,4528,4458,4405,4359,4311,
-4266,4237,4216,4187,4156,4140,4133,4109,4057,4003,3970,3948,3916,3875,3836,3798,3750,3695,3647,3605,3560,
-3517,3487,3464,3428,3380,3347,3347,3360,3345,3285,3197,3111,3044,3002,2979,2965,2950,2930,2900,2861,2815,
-2770,2734,2706,2675,2631,2580,2538,2517,2515,2521,2529,2531,2525,2504,2473,2440,2410,2380,2357,2349,2362,
-2375,2358,2300,2219,2147,2099,2069,2043,2014,1984,1953,1915,1868,1821,1784,1759,1741,1723,1707,1690,1666,
-1637,1609,1590,1576,1558,1537,1519,1504,1494,1502,1531,1559,1554,1516,1477,1457,1436,1386,1319,1269,1243,
-1222,1199,1186,1185,1169,1120,1057,1006,972,947,951,1008,1094,1134,1078,965,877,847,840,814,778,
-766,785,802,794,772,755,744,736,732,736,738,725,708,705,715,720,708,689,675,665,653,
-637,613,575,527,489,473,465,444,410,377,351,324,292,261,234,206,173,141,113,87,63,
-48,36,19,-2,-16,-18,-22,-35,-50,-54,-56,-69,-87,-97,-109,-141,-185,-200,-152,-50,57,
-124,125,75,11,-38,-76,-127,-195,-255,-287,-296,-304,-320,-340,-362,-388,-420,-451,-479,-508,-537,
--564,-585,-605,-629,-659,-691,-723,-751,-774,-792,-810,-827,-843,-860,-878,-895,-908,-918,-928,-941,-954,
--967,-980,-994,-1008,-1019,-1026,-1027,-1027,-1031,-1043,-1060,-1077,-1091,-1100,-1104,-1102,-1102,-1107,-1114,-1118,-1118,
--1118,-1120,-1120,-1118,-1117,-1118,-1120,-1123,-1130,-1142,-1155,-1164,-1173,-1183,-1192,-1198,-1203,-1210,-1216,-1216,-1215,
--1216,-1219,-1222,-1220,-1215,-1208,-1199,-1187,-1174,-1161,-1148,-1139,-1133,-1125,-1113,-1099,-1085,-1071,-1054,-1038,-1023,
--1011,-997,-983,-974,-966,-958,-947,-938,-932,-924,-913,-904,-901,-900,-895,-887,-882,-882,-882,-882,-883,
--886,-889,-892,-898,-907,-916,-920,-921,-924,-931,-941,-948,-956,-966,-980,-994,-1008,-1022,-1038,-1056,-1079,
--1107,-1136,-1160,-1176,-1186,-1193,-1197,-1199,-1203,-1211,-1222,-1230,-1234,-1237,-1239,-1239,-1241,-1243,-1244,-1243,-1241,
--1242,-1243,-1242,-1238,-1234,-1230,-1225,-1220,-1217,-1214,-1208,-1200,-1196,-1197,-1197,-1194,-1188,-1183,-1179,-1175,-1171,
--1167,-1159,-1145,-1131,-1122,-1111,-1095,-1077,-1063,-1049,-1030,-1006,-984,-965,-944,-917,-888,-862,-838,-814,-788,
--759,-728,-698,-671,-644,-613,-577,-541,-509,-476,-437,-393,-348,-305,-263,-221,-178,-134,-86,-36,7,
-35,44,41,30,-3,-80,-185,-242,-158,88,425,750,1002,1182,1310,1421,1571,1802,2071,2260,2294,
-2234,2207,2252,2281,2204,2062,1979,2013,2095,2116,2058,1995,2010,2123,2287,2437,2525,2540,2510,2485,2493,
-2529,2565,2588,2608,2632,2654,2667,2670,2667,2651,2616,2566,2516,2471,2429,2384,2339,2296,2248,2190,2127,
-2067,2005,1930,1840,1747,1657,1563,1456,1349,1274,1252,1269,1285,1271,1224,1165,1110,1049,965,855,744,
-650,568,486,399,314,231,143,51,-35,-116,-200,-286,-360,-420,-486,-570,-650,-686,-665,-633,-654,
--763,-936,-1109,-1219,-1248,-1227,-1215,-1244,-1305,-1370,-1416,-1436,-1434,-1421,-1415,-1431,-1466,-1500,-1523,-1542,-1577,
--1634,-1705,-1783,-1876,-1984,-2083,-2141,-2154,-2147,-2144,-2141,-2123,-2093,-2068,-2054,-2041,-2021,-2000,-1982,-1955,-1909,
--1855,-1817,-1802,-1801,-1791,-1755,-1692,-1623,-1578,-1568,-1571,-1557,-1525,-1502,-1503,-1514,-1514,-1497,-1469,-1431,-1385,
--1338,-1291,-1234,-1162,-1105,-1102,-1145,-1175,-1136,-1043,-956,-912,-892,-858,-800,-745,-720,-728,-746,-758,-774,
--813,-886,-978,-1062,-1116,-1138,-1136,-1121,-1104,-1096,-1097,-1101,-1101,-1097,-1089,-1074,-1055,-1037,-1024,-1010,-987,
--960,-936,-916,-893,-868,-848,-834,-819,-796,-771,-751,-733,-712,-688,-667,-648,-628,-605,-582,-558,-529,
--492,-454,-417,-378,-335,-293,-251,-209,-165,-121,-76,-27,32,99,165,222,270,316,367,423,477,
-522,562,607,658,705,742,773,808,849,889,924,951,973,993,1014,1041,1072,1106,1144,1184,1222,
-1256,1294,1338,1380,1404,1404,1392,1382,1374,1367,1362,1360,1360,1354,1343,1336,1338,1351,1367,1378,1382,
-1385,1388,1395,1403,1410,1411,1406,1397,1391,1393,1397,1398,1393,1388,1387,1384,1379,1373,1372,1377,1383,
-1388,1390,1389,1381,1370,1358,1349,1337,1315,1288,1268,1262,1255,1230,1187,1147,1161,1159,1152,1111,1043,
-985,962,967,977,980,979,974,963,948,938,939,943,946,947,953,961,965,968,973,979,981,
-982,989,1001,1012,1019,1029,1046,1067,1083,1097,1119,1147,1170,1182,1195,1218,1247,1276,1306,1343,1379,
-1406,1431,1477,1550,1629,1682,1702,1700,1687,1663,1635,1620,1628,1653,1668,1649,1585,1487,1383,1299,1236,
-1176,1104,1027,964,917,873,823,774,731,690,640,579,516,456,398,344,296,248,195,138,82,
-28,-40,-139,-262,-382,-474,-534,-580,-627,-671,-697,-706,-723,-757,-782,-764,-718,-701,-739,-786,-777,
--716,-678,-715,-810,-911,-1000,-1084,-1164,-1226,-1271,-1307,-1331,-1318,-1260,-1182,-1121,-1098,-1116,-1157,-1187,-1180,
--1143,-1132,-1199,-1335,-1464,-1502,-1425,-1292,-1211,-1271,-1467,-1695,-1842,-1882,-1887,-1939,-2044,-2156,-2238,-2295,-2334,
--2355,-2360,-2368,-2393,-2439,-2513,-2635,-2803,-2977,-3109,-3195,-3259,-3298,-3287,-3225,-3166,-3165,-3216,-3276,-3317,-3344,
--3362,-3370,-3368,-3368,-3372,-3372,-3377,-3403,-3444,-3460,-3422,-3353,-3322,-3369,-3470,-3552,-3571,-3544,-3522,-3524,-3513,
--3463,-3413,-3424,-3482,-3499,-3425,-3324,-3288,-3310,-3304,-3233,-3168,-3189,-3280,-3354,-3365,-3343,-3344,-3380,-3426,-3453,
--3453,-3442,-3443,-3464,-3497,-3526,-3543,-3552,-3558,-3571,-3598,-3642,-3689,-3725,-3756,-3800,-3862,-3927,-3976,-4009,-4030,
--4039,-4025,-3986,-3942,-3930,-3972,-4055,-4138,-4192,-4228,-4278,-4354,-4446,-4531,-4606,-4677,-4749,-4825,-4902,-4976,-5041,
--5098,-5152,-5203,-5248,-5289,-5332,-5380,-5429,-5473,-5514,-5553,-5593,-5637,-5685,-5739,-5796,-5858,-5928,-6002,-6072,-6132,
--6181,-6220,-6253,-6288,-6329,-6377,-6426,-6478,-6540,-6609,-6675,-6737,-6811,-6909,-7021,-7125,-7205,-7260,-7300,-7332,-7365,
--7405,-7448,-7490,-7528,-7565,-7600,-7633,-7662,-7690,-7718,-7741,-7759,-7773,-7783,-7790,-7797,-7806,-7808,-7801,-7787,-7776,
--7769,-7757,-7735,-7706,-7676,-7648,-7628,-7622,-7623,-7621,-7609,-7588,-7563,-7538,-7514,-7489,-7453,-7400,-7341,-7294,-7265,
--7240,-7207,-7164,-7115,-7063,-7012,-6975,-6952,-6932,-6903,-6861,-6800,-6708,-6597,-6508,-6472,-6477,-6484,-6474,-6448,-6392,
--6287,-6151,-6036,-5973,-5937,-5889,-5818,-5735,-5639,-5528,-5414,-5317,-5239,-5163,-5084,-5006,-4917,-4791,-4626,-4462,-4351,
--4306,-4286,-4227,-4097,-3918,-3754,-3647,-3577,-3496,-3388,-3287,-3218,-3162,-3079,-2966,-2845,-2726,-2602,-2473,-2355,-2256,
--2164,-2075,-2000,-1942,-1875,-1772,-1646,-1530,-1440,-1356,-1260,-1154,-1045,-933,-825,-737,-681,-653,-648,-680,-748,
--822,-856,-839,-794,-731,-640,-520,-397,-296,-209,-122,-42,8,43,98,192,287,332,322,306,343,
-452,601,743,867,997,1158,1335,1478,1551,1560,1543,1542,1587,1680,1803,1929,2044,2152,2249,2327,2388,
-2454,2526,2575,2579,2574,2631,2778,2979,3188,3400,3619,3812,3935,3973,3947,3865,3720,3518,3299,3109,2955,
-2822,2711,2649,2661,2752,2919,3150,3414,3652,3800,3832,3777,3695,3632,3592,3556,3518,3499,3527,3607,3712,
-3814,3902,3985,4081,4203,4352,4512,4655,4770,4866,4959,5056,5150,5243,5342,5448,5546,5623,5675,5718,5772,
-5850,5948,6042,6105,6132,6142,6152,6169,6199,6260,6361,6478,6565,6595,6583,6560,6546,6543,6553,6578,6616,
-6663,6710,6749,6776,6796,6825,6875,6942,7005,7040,7047,7044,7058,7099,7153,7201,7240,7287,7347,7405,7441,
-7453,7452,7451,7448,7445,7441,7418,7351,7238,7113,7016,6954,6907,6877,6899,7007,7197,7436,7688,7913,8063,
-8111,8086,8055,8042,8005,7909,7794,7742,7769,7808,7785,7701,7602,7531,7504,7524,7576,7612,7593,7527,7463,
-7423,7381,7314,7237,7190,7180,7177,7151,7099,7046,7012,6992,6966,6917,6853,6788,6728,6665,6599,6535,6469,
-6399,6346,6355,6449,6589,6689,6679,6552,6372,6218,6110,5986,5796,5596,5516,5617,5805,5935,5957,5935,5924,
-5917,5888,5849,5822,5801,5768,5730,5701,5680,5653,5624,5602,5580,5541,5493,5458,5438,5407,5335,5225,5111,
-5030,4998,4995,4988,4954,4895,4821,4735,4641,4558,4497,4447,4393,4342,4308,4285,4254,4215,4185,4167,4139,
-4093,4050,4024,4001,3961,3913,3878,3851,3811,3755,3702,3660,3617,3570,3531,3505,3474,3425,3381,3371,3390,
-3396,3351,3267,3184,3131,3104,3084,3057,3026,2994,2960,2922,2879,2838,2803,2774,2744,2704,2654,2607,2579,
-2577,2593,2609,2616,2612,2597,2571,2533,2488,2442,2405,2389,2393,2400,2381,2322,2242,2171,2128,2105,2079,
-2044,2007,1975,1942,1900,1851,1810,1782,1760,1740,1723,1708,1684,1649,1613,1592,1580,1563,1539,1520,1512,
-1514,1526,1551,1574,1567,1528,1490,1474,1459,1415,1349,1292,1254,1219,1185,1168,1173,1166,1122,1059,1010,
-983,958,936,940,971,989,958,895,849,835,827,798,759,743,757,772,765,742,719,705,698,
-697,700,702,694,683,680,686,688,678,660,641,625,613,607,600,574,529,483,456,442,423,
-392,358,326,295,264,239,219,197,168,135,101,67,39,22,12,-3,-26,-45,-53,-61,-73,
--84,-86,-88,-101,-120,-131,-139,-163,-204,-238,-231,-179,-106,-50,-27,-21,-3,28,38,-13,-116,
--221,-284,-310,-326,-345,-364,-382,-405,-434,-463,-492,-520,-549,-574,-593,-610,-632,-658,-688,-718,-743,
--763,-780,-800,-820,-837,-853,-871,-889,-901,-908,-914,-924,-936,-948,-961,-975,-990,-1001,-1009,-1013,-1015,
--1020,-1028,-1040,-1052,-1063,-1071,-1073,-1072,-1071,-1076,-1085,-1090,-1092,-1094,-1098,-1101,-1100,-1097,-1095,-1095,-1096,
--1102,-1113,-1124,-1132,-1140,-1149,-1157,-1161,-1163,-1168,-1172,-1174,-1174,-1176,-1181,-1185,-1185,-1184,-1180,-1174,-1163,
--1149,-1133,-1117,-1105,-1096,-1089,-1077,-1062,-1045,-1029,-1011,-993,-979,-966,-952,-937,-928,-925,-920,-913,-904,
--899,-893,-883,-873,-868,-865,-860,-852,-847,-848,-850,-851,-853,-858,-863,-867,-871,-879,-890,-899,-904,
--909,-916,-923,-930,-937,-946,-959,-974,-988,-1004,-1023,-1044,-1069,-1098,-1127,-1150,-1163,-1170,-1174,-1177,-1182,
--1191,-1203,-1215,-1221,-1222,-1222,-1223,-1225,-1228,-1231,-1231,-1227,-1221,-1220,-1222,-1221,-1216,-1211,-1208,-1203,-1198,
--1195,-1192,-1186,-1178,-1173,-1172,-1172,-1169,-1165,-1161,-1159,-1154,-1148,-1141,-1133,-1123,-1112,-1103,-1095,-1083,-1066,
--1049,-1032,-1012,-990,-968,-947,-926,-901,-874,-847,-824,-800,-774,-745,-713,-683,-657,-632,-604,-572,-538,
--503,-468,-434,-398,-358,-313,-268,-225,-180,-135,-90,-47,-1,40,61,56,42,25,-22,-122,-224,
--219,-44,253,571,840,1049,1209,1355,1552,1844,2168,2379,2404,2342,2346,2441,2506,2446,2317,2247,2276,
-2322,2295,2200,2114,2104,2182,2314,2449,2537,2558,2536,2518,2536,2579,2621,2645,2659,2675,2690,2696,2691,
-2679,2663,2640,2612,2581,2544,2498,2445,2399,2365,2332,2284,2219,2149,2082,2011,1930,1847,1764,1669,1554,
-1438,1358,1336,1353,1364,1340,1289,1234,1188,1135,1051,940,826,730,646,560,469,381,295,204,110,
-21,-62,-152,-245,-324,-384,-448,-531,-605,-622,-572,-514,-531,-658,-858,-1048,-1163,-1185,-1156,-1134,-1153,
--1210,-1275,-1324,-1347,-1345,-1328,-1318,-1333,-1372,-1411,-1434,-1450,-1485,-1549,-1632,-1723,-1823,-1931,-2024,-2077,-2089,
--2090,-2100,-2105,-2086,-2050,-2022,-2010,-1998,-1973,-1946,-1923,-1891,-1838,-1778,-1739,-1731,-1732,-1712,-1660,-1586,-1525,
--1509,-1541,-1588,-1609,-1600,-1587,-1587,-1586,-1570,-1542,-1511,-1473,-1419,-1357,-1296,-1234,-1169,-1126,-1140,-1201,-1242,
--1202,-1093,-985,-929,-913,-893,-847,-796,-769,-773,-797,-829,-871,-932,-1007,-1076,-1120,-1138,-1142,-1141,-1135,
--1123,-1113,-1108,-1106,-1102,-1095,-1086,-1073,-1054,-1035,-1019,-1003,-980,-954,-932,-914,-896,-874,-855,-841,-824,
--800,-772,-749,-732,-716,-698,-682,-668,-653,-633,-609,-583,-555,-521,-484,-444,-402,-358,-313,-269,-223,
--175,-129,-85,-38,16,79,145,207,263,313,363,412,457,495,534,580,632,681,721,755,789,
-826,864,898,925,946,965,986,1011,1039,1073,1112,1153,1189,1221,1255,1298,1342,1372,1380,1373,1361,
-1350,1342,1339,1340,1339,1334,1326,1318,1316,1322,1336,1350,1362,1370,1376,1381,1383,1382,1379,1372,1366,
-1365,1376,1389,1394,1392,1389,1387,1380,1363,1346,1344,1355,1367,1369,1365,1359,1351,1339,1325,1313,1300,
-1282,1265,1260,1263,1256,1226,1185,1161,1174,1185,1178,1127,1050,990,969,977,988,990,988,982,973,
-963,956,957,961,963,966,972,977,981,984,990,1000,1007,1011,1019,1033,1046,1055,1065,1082,1104,
-1123,1138,1157,1183,1209,1228,1250,1280,1316,1349,1379,1412,1444,1466,1486,1523,1586,1657,1715,1748,1756,
-1738,1694,1645,1621,1638,1682,1721,1722,1670,1574,1465,1375,1310,1249,1177,1101,1037,985,930,872,821,
-783,744,695,636,576,519,461,407,358,311,255,193,135,82,14,-87,-215,-337,-425,-479,-521,
--569,-613,-632,-625,-616,-626,-638,-629,-616,-642,-716,-774,-754,-677,-633,-671,-757,-835,-904,-994,-1108,
--1206,-1262,-1289,-1301,-1290,-1241,-1172,-1120,-1103,-1117,-1144,-1171,-1180,-1166,-1158,-1212,-1353,-1533,-1647,-1620,-1484,
--1362,-1374,-1529,-1723,-1843,-1871,-1879,-1936,-2039,-2142,-2222,-2282,-2324,-2342,-2344,-2353,-2376,-2407,-2456,-2548,-2686,
--2829,-2942,-3036,-3136,-3220,-3228,-3155,-3076,-3068,-3128,-3197,-3242,-3272,-3299,-3313,-3309,-3304,-3311,-3321,-3327,-3344,
--3378,-3402,-3377,-3311,-3267,-3305,-3406,-3482,-3466,-3387,-3336,-3363,-3415,-3422,-3390,-3386,-3428,-3447,-3388,-3289,-3234,
--3225,-3195,-3120,-3068,-3109,-3217,-3302,-3317,-3293,-3284,-3308,-3345,-3373,-3387,-3392,-3400,-3418,-3445,-3474,-3500,-3517,
--3524,-3529,-3544,-3578,-3624,-3668,-3709,-3759,-3821,-3884,-3933,-3966,-3985,-3991,-3975,-3937,-3893,-3874,-3898,-3954,-4006,
--4034,-4055,-4103,-4191,-4302,-4411,-4508,-4593,-4669,-4740,-4813,-4890,-4962,-5021,-5065,-5104,-5148,-5197,-5247,-5295,-5340,
--5379,-5412,-5444,-5478,-5522,-5576,-5639,-5706,-5774,-5841,-5903,-5963,-6022,-6080,-6132,-6174,-6213,-6257,-6304,-6349,-6397,
--6454,-6520,-6584,-6646,-6721,-6818,-6929,-7029,-7107,-7164,-7206,-7240,-7276,-7316,-7359,-7399,-7435,-7469,-7502,-7533,-7563,
--7595,-7625,-7646,-7661,-7675,-7688,-7698,-7705,-7712,-7716,-7713,-7704,-7694,-7686,-7676,-7656,-7628,-7599,-7579,-7572,-7576,
--7576,-7567,-7549,-7531,-7513,-7493,-7471,-7447,-7410,-7353,-7286,-7230,-7192,-7164,-7133,-7099,-7063,-7023,-6984,-6954,-6938,
--6925,-6905,-6872,-6814,-6722,-6612,-6524,-6483,-6474,-6469,-6462,-6449,-6401,-6291,-6147,-6031,-5974,-5943,-5896,-5819,-5724,
--5614,-5498,-5399,-5333,-5286,-5224,-5141,-5046,-4942,-4814,-4664,-4519,-4408,-4339,-4292,-4224,-4105,-3945,-3797,-3705,-3651,
--3581,-3474,-3365,-3289,-3226,-3138,-3018,-2889,-2763,-2632,-2501,-2389,-2304,-2233,-2168,-2113,-2061,-1986,-1873,-1742,-1624,
--1525,-1428,-1319,-1200,-1073,-938,-809,-705,-625,-555,-504,-510,-591,-706,-790,-821,-823,-813,-768,-669,-542,
--426,-335,-253,-177,-122,-89,-51,13,87,134,147,164,230,346,469,565,642,751,919,1111,1253,
-1300,1272,1227,1213,1244,1314,1405,1502,1595,1689,1782,1862,1923,1976,2034,2091,2135,2187,2295,2480,2709,
-2936,3154,3380,3605,3786,3888,3907,3844,3695,3474,3232,3023,2861,2722,2602,2537,2563,2681,2867,3093,3332,
-3532,3636,3622,3535,3448,3411,3418,3444,3475,3529,3628,3771,3936,4091,4220,4326,4428,4539,4659,4773,4865,
-4933,4997,5073,5162,5253,5340,5426,5512,5589,5653,5705,5753,5809,5880,5966,6047,6102,6125,6133,6145,6162,
-6186,6233,6319,6430,6519,6551,6532,6498,6476,6472,6484,6514,6557,6604,6646,6683,6718,6757,6799,6846,6900,
-6952,6985,6990,6986,7004,7059,7129,7184,7219,7255,7307,7368,7416,7443,7451,7446,7432,7416,7394,7348,7257,
-7136,7029,6965,6927,6881,6827,6811,6875,7020,7222,7450,7669,7827,7896,7909,7936,7995,8026,7968,7848,7760,
-7751,7774,7757,7679,7577,7494,7448,7443,7460,7469,7449,7411,7383,7362,7324,7265,7212,7193,7192,7175,7125,
-7062,7015,6993,6976,6940,6879,6810,6753,6703,6640,6559,6478,6407,6343,6287,6270,6331,6474,6633,6708,6636,
-6456,6272,6148,6039,5868,5655,5531,5593,5784,5954,6018,6007,5984,5965,5935,5899,5867,5838,5803,5772,5754,
-5742,5721,5697,5680,5663,5628,5576,5530,5508,5491,5448,5361,5247,5141,5072,5040,5026,5009,4979,4933,4862,
-4772,4682,4612,4554,4492,4431,4386,4358,4329,4287,4241,4200,4163,4131,4111,4097,4065,4004,3942,3906,3886,
-3849,3791,3739,3704,3669,3623,3579,3552,3528,3484,3433,3410,3424,3438,3410,3342,3277,3240,3218,3186,3139,
-3091,3049,3010,2973,2940,2911,2880,2847,2814,2781,2741,2697,2663,2657,2671,2686,2690,2684,2674,2654,2620,
-2571,2517,2467,2432,2412,2396,2366,2311,2242,2185,2154,2142,2125,2090,2046,2005,1966,1922,1874,1834,1806,
-1782,1757,1737,1721,1697,1657,1616,1590,1576,1557,1531,1513,1513,1522,1535,1555,1574,1570,1539,1506,1493,
-1481,1440,1377,1322,1286,1251,1208,1177,1167,1153,1110,1051,1009,990,968,930,894,880,877,865,842,
-825,822,815,789,754,731,730,736,733,716,697,683,676,671,667,661,655,653,658,663,659,
-644,625,607,591,580,576,574,558,518,467,428,407,392,369,337,301,265,236,216,202,183,
-156,122,86,49,17,-2,-14,-27,-47,-69,-86,-100,-114,-122,-124,-126,-136,-151,-163,-173,-192,
--222,-254,-270,-259,-225,-187,-152,-106,-30,60,109,70,-41,-164,-249,-297,-330,-359,-381,-397,-418,
--444,-474,-504,-536,-565,-587,-605,-621,-641,-663,-689,-715,-737,-753,-769,-789,-810,-828,-843,-861,-880,
--893,-898,-904,-914,-925,-935,-944,-956,-969,-981,-991,-1000,-1007,-1011,-1015,-1020,-1029,-1037,-1044,-1047,-1046,
--1047,-1052,-1059,-1064,-1067,-1072,-1080,-1086,-1085,-1081,-1077,-1076,-1077,-1082,-1090,-1098,-1102,-1106,-1113,-1119,-1123,
--1126,-1130,-1135,-1137,-1138,-1138,-1140,-1142,-1144,-1145,-1144,-1139,-1130,-1119,-1105,-1091,-1077,-1066,-1057,-1044,-1028,
--1010,-991,-972,-953,-938,-926,-913,-898,-889,-885,-882,-876,-869,-864,-860,-852,-843,-836,-832,-826,-818,
--814,-815,-819,-822,-825,-831,-837,-841,-843,-847,-856,-868,-877,-886,-893,-902,-910,-919,-930,-942,-956,
--972,-990,-1010,-1032,-1057,-1085,-1113,-1134,-1146,-1152,-1155,-1160,-1168,-1179,-1190,-1199,-1204,-1206,-1209,-1211,-1213,
--1214,-1216,-1215,-1211,-1204,-1202,-1202,-1202,-1198,-1194,-1192,-1189,-1183,-1176,-1171,-1164,-1155,-1147,-1145,-1146,-1144,
--1140,-1137,-1137,-1134,-1126,-1117,-1109,-1102,-1094,-1086,-1079,-1069,-1055,-1037,-1016,-994,-973,-951,-929,-908,-886,
--861,-835,-811,-787,-761,-733,-704,-676,-649,-621,-593,-567,-537,-499,-460,-428,-399,-366,-323,-278,-234,
--186,-137,-94,-59,-17,31,66,68,57,56,38,-43,-168,-234,-151,70,350,624,867,1074,1264,
-1495,1807,2136,2345,2381,2345,2379,2495,2588,2592,2559,2562,2589,2565,2461,2327,2228,2197,2235,2333,2456,
-2553,2590,2581,2569,2586,2625,2660,2681,2695,2715,2736,2743,2728,2697,2665,2642,2628,2614,2588,2543,2488,
-2439,2409,2386,2349,2293,2227,2162,2095,2023,1953,1884,1801,1691,1572,1485,1455,1463,1465,1432,1377,1325,
-1282,1228,1139,1024,911,816,730,636,537,445,361,271,172,75,-19,-118,-218,-301,-363,-424,-498,
--555,-549,-479,-418,-448,-589,-786,-959,-1062,-1095,-1092,-1093,-1117,-1160,-1208,-1250,-1278,-1287,-1280,-1272,-1284,
--1314,-1344,-1359,-1375,-1419,-1498,-1595,-1695,-1796,-1898,-1983,-2025,-2027,-2020,-2025,-2027,-2010,-1979,-1958,-1952,-1941,
--1917,-1892,-1871,-1836,-1777,-1712,-1675,-1670,-1668,-1639,-1582,-1520,-1486,-1502,-1562,-1628,-1662,-1662,-1652,-1648,-1635,
--1598,-1551,-1511,-1473,-1419,-1347,-1275,-1212,-1162,-1137,-1163,-1230,-1279,-1249,-1142,-1022,-946,-920,-908,-885,-854,
--838,-844,-870,-911,-967,-1034,-1098,-1139,-1150,-1144,-1141,-1145,-1148,-1142,-1130,-1119,-1110,-1100,-1088,-1075,-1061,
--1044,-1026,-1011,-996,-976,-953,-933,-918,-904,-885,-866,-850,-833,-810,-783,-760,-743,-728,-713,-699,-687,
--674,-655,-631,-605,-578,-547,-511,-468,-423,-378,-334,-289,-243,-196,-150,-104,-56,-4,55,120,186,
-250,307,358,402,438,472,509,551,598,643,684,722,758,793,826,855,882,905,930,957,986,
-1014,1044,1080,1120,1156,1189,1223,1265,1309,1341,1354,1350,1336,1322,1315,1314,1314,1312,1307,1301,1295,
-1291,1294,1306,1322,1335,1345,1351,1353,1351,1346,1340,1335,1332,1336,1349,1363,1370,1369,1371,1376,1371,
-1351,1328,1325,1339,1352,1349,1334,1321,1314,1306,1295,1284,1276,1269,1266,1271,1272,1254,1216,1182,1174,
-1147,1163,1152,1100,1032,988,980,993,1003,1004,1000,995,989,981,977,976,977,979,982,987,992,
-994,998,1007,1021,1034,1042,1052,1067,1084,1097,1110,1127,1147,1164,1177,1193,1216,1243,1270,1298,1331,
-1365,1398,1432,1467,1498,1517,1532,1562,1615,1680,1742,1789,1807,1783,1723,1661,1640,1669,1720,1758,1762,
-1722,1640,1537,1444,1373,1311,1244,1174,1113,1056,992,927,874,837,799,748,690,633,577,520,464,
-416,369,313,250,191,138,70,-30,-159,-280,-363,-407,-438,-478,-520,-538,-523,-495,-481,-485,-497,
--528,-599,-693,-748,-718,-640,-600,-638,-710,-768,-827,-932,-1077,-1200,-1257,-1265,-1260,-1247,-1213,-1168,-1139,
--1134,-1135,-1138,-1156,-1187,-1203,-1189,-1191,-1282,-1474,-1674,-1759,-1694,-1574,-1531,-1611,-1741,-1829,-1854,-1873,-1938,
--2044,-2152,-2239,-2303,-2338,-2345,-2340,-2347,-2364,-2379,-2403,-2468,-2571,-2671,-2744,-2829,-2963,-3105,-3158,-3095,-3002,
--2979,-3034,-3103,-3146,-3180,-3217,-3243,-3245,-3240,-3251,-3266,-3266,-3263,-3287,-3332,-3358,-3338,-3304,-3310,-3358,-3388,
--3346,-3262,-3225,-3278,-3363,-3391,-3353,-3319,-3333,-3355,-3325,-3247,-3177,-3130,-3079,-3019,-3000,-3060,-3165,-3243,-3262,
--3251,-3249,-3265,-3286,-3305,-3321,-3336,-3350,-3365,-3388,-3418,-3451,-3477,-3488,-3489,-3494,-3521,-3565,-3614,-3660,-3710,
--3768,-3828,-3878,-3913,-3935,-3947,-3940,-3906,-3853,-3809,-3803,-3833,-3872,-3897,-3916,-3958,-4040,-4154,-4279,-4400,-4503,
--4584,-4649,-4717,-4797,-4876,-4935,-4973,-5006,-5051,-5106,-5161,-5204,-5237,-5263,-5287,-5317,-5360,-5417,-5484,-5553,-5622,
--5686,-5746,-5800,-5855,-5918,-5985,-6042,-6086,-6125,-6170,-6217,-6261,-6306,-6362,-6430,-6498,-6564,-6642,-6738,-6843,-6939,
--7014,-7070,-7114,-7152,-7191,-7231,-7271,-7306,-7339,-7371,-7402,-7431,-7463,-7498,-7528,-7548,-7562,-7577,-7593,-7603,-7607,
--7612,-7619,-7620,-7613,-7602,-7594,-7585,-7568,-7541,-7515,-7501,-7504,-7512,-7511,-7497,-7479,-7467,-7459,-7446,-7426,-7398,
--7354,-7291,-7220,-7160,-7118,-7084,-7053,-7030,-7013,-6992,-6967,-6944,-6929,-6916,-6899,-6871,-6816,-6726,-6620,-6535,-6491,
--6471,-6457,-6454,-6451,-6404,-6283,-6127,-6012,-5967,-5946,-5899,-5813,-5705,-5589,-5481,-5405,-5367,-5338,-5280,-5187,-5076,
--4956,-4824,-4686,-4556,-4447,-4360,-4289,-4218,-4118,-3985,-3859,-3779,-3729,-3657,-3543,-3428,-3349,-3286,-3196,-3071,-2933,
--2799,-2669,-2547,-2447,-2373,-2315,-2265,-2221,-2168,-2080,-1955,-1820,-1701,-1598,-1496,-1386,-1266,-1126,-967,-817,-700,
--604,-501,-408,-385,-467,-604,-711,-757,-777,-798,-799,-748,-658,-571,-505,-443,-374,-316,-284,-262,-217,
--143,-63,8,85,188,308,413,480,534,628,788,970,1095,1118,1071,1021,1009,1029,1063,1100,1147,
-1208,1285,1371,1452,1515,1569,1627,1691,1752,1819,1930,2105,2317,2523,2717,2936,3196,3452,3636,3708,3670,
-3542,3358,3169,3008,2868,2723,2583,2509,2550,2692,2875,3053,3208,3326,3382,3371,3328,3309,3342,3416,3510,
-3613,3734,3876,4038,4202,4352,4475,4575,4666,4758,4850,4925,4978,5018,5067,5138,5222,5307,5383,5454,5526,
-5596,5663,5723,5778,5832,5892,5963,6034,6084,6104,6110,6122,6144,6169,6206,6276,6377,6470,6511,6493,6449,
-6417,6408,6420,6448,6487,6526,6560,6594,6638,6694,6751,6802,6850,6894,6920,6919,6912,6935,7002,7083,7142,
-7175,7207,7259,7324,7384,7429,7449,7438,7404,7366,7330,7278,7193,7092,7020,6991,6971,6920,6845,6798,6817,
-6907,7048,7222,7399,7532,7595,7624,7690,7817,7939,7977,7923,7844,7795,7771,7732,7664,7584,7515,7466,7434,
-7411,7381,7340,7306,7295,7298,7288,7259,7227,7202,7172,7121,7060,7013,6992,6979,6946,6880,6799,6736,6708,
-6693,6659,6592,6512,6440,6374,6299,6224,6186,6221,6323,6423,6445,6372,6272,6211,6164,6045,5842,5669,5655,
-5796,5967,6058,6061,6026,5982,5932,5882,5845,5823,5813,5816,5829,5833,5814,5781,5757,5741,5712,5659,5602,
-5564,5544,5521,5472,5394,5298,5201,5120,5062,5029,5013,4995,4956,4892,4821,4757,4695,4621,4540,4474,4434,
-4408,4374,4322,4260,4204,4171,4160,4149,4107,4035,3968,3932,3910,3872,3818,3773,3746,3716,3669,3621,3593,
-3574,3543,3507,3497,3522,3543,3521,3457,3393,3350,3314,3266,3211,3164,3121,3075,3028,2994,2972,2945,2908,
-2874,2851,2827,2792,2757,2742,2747,2752,2743,2729,2718,2707,2681,2638,2587,2537,2492,2451,2412,2366,2308,
-2243,2188,2160,2152,2145,2120,2079,2033,1987,1939,1891,1854,1830,1807,1779,1750,1724,1695,1653,1612,1584,
-1565,1539,1508,1493,1503,1521,1536,1550,1564,1563,1540,1516,1506,1495,1456,1398,1353,1331,1305,1257,1203,
-1164,1131,1086,1036,1003,987,967,925,877,842,826,818,810,802,798,793,780,756,730,712,706,
-705,701,691,681,671,657,639,621,613,620,633,639,629,605,582,566,555,546,540,536,524,
-491,441,396,368,355,339,311,274,237,208,190,176,157,129,96,63,31,0,-24,-41,-55,
--72,-94,-117,-137,-152,-162,-166,-169,-173,-179,-191,-207,-228,-249,-271,-289,-298,-292,-277,-254,-208,
--122,-10,70,68,-12,-118,-206,-270,-321,-363,-390,-409,-428,-452,-481,-515,-550,-581,-604,-621,-639,
--657,-675,-695,-717,-735,-749,-762,-780,-800,-816,-829,-847,-868,-883,-892,-901,-913,-924,-929,-934,-943,
--953,-963,-975,-989,-999,-1002,-1000,-1002,-1008,-1016,-1023,-1026,-1029,-1031,-1035,-1038,-1040,-1043,-1050,-1061,-1070,
--1071,-1066,-1062,-1061,-1061,-1065,-1071,-1076,-1076,-1075,-1076,-1080,-1085,-1090,-1096,-1102,-1105,-1105,-1103,-1101,-1099,
--1100,-1101,-1101,-1096,-1088,-1079,-1071,-1060,-1047,-1036,-1026,-1012,-995,-976,-958,-939,-921,-906,-894,-882,-868,
--857,-852,-847,-841,-834,-830,-826,-820,-811,-805,-800,-794,-787,-783,-785,-790,-794,-798,-803,-809,-814,
--816,-818,-824,-834,-844,-854,-864,-876,-887,-899,-910,-922,-936,-954,-975,-996,-1019,-1044,-1071,-1097,-1116,
--1126,-1130,-1135,-1144,-1154,-1164,-1171,-1176,-1179,-1184,-1190,-1196,-1198,-1197,-1197,-1196,-1193,-1188,-1186,-1185,-1182,
--1179,-1176,-1176,-1174,-1168,-1159,-1150,-1141,-1131,-1123,-1121,-1122,-1121,-1115,-1111,-1111,-1109,-1103,-1093,-1086,-1082,
--1078,-1070,-1061,-1052,-1041,-1024,-1002,-979,-958,-936,-914,-892,-870,-846,-821,-797,-773,-748,-721,-696,-674,
--647,-614,-581,-556,-530,-496,-455,-422,-395,-364,-323,-281,-242,-196,-143,-95,-62,-27,21,63,75,
-72,82,89,38,-79,-189,-197,-78,130,386,659,919,1157,1409,1710,2017,2232,2318,2350,2422,2537,
-2644,2731,2833,2933,2950,2838,2651,2486,2385,2333,2326,2378,2483,2585,2634,2632,2615,2615,2631,2649,2665,
-2688,2726,2772,2799,2787,2740,2686,2651,2637,2627,2608,2574,2527,2479,2442,2415,2385,2344,2293,2242,2192,
-2139,2085,2029,1954,1849,1728,1634,1593,1591,1585,1551,1497,1445,1397,1330,1230,1112,1005,917,828,723,
-611,512,425,332,226,120,19,-81,-183,-270,-338,-400,-464,-501,-473,-394,-342,-389,-533,-707,-847,
--933,-984,-1023,-1062,-1097,-1126,-1152,-1182,-1213,-1235,-1242,-1240,-1247,-1262,-1275,-1281,-1303,-1368,-1475,-1595,-1703,
--1798,-1886,-1954,-1982,-1968,-1940,-1922,-1913,-1899,-1886,-1883,-1883,-1872,-1851,-1834,-1820,-1786,-1721,-1651,-1614,-1607,
--1600,-1569,-1523,-1487,-1481,-1515,-1579,-1644,-1677,-1679,-1673,-1671,-1652,-1597,-1523,-1463,-1423,-1379,-1315,-1245,-1187,
--1149,-1138,-1167,-1234,-1293,-1283,-1189,-1058,-955,-910,-904,-906,-901,-897,-907,-937,-985,-1046,-1108,-1155,-1173,
--1166,-1150,-1143,-1144,-1144,-1135,-1121,-1110,-1102,-1093,-1079,-1064,-1050,-1034,-1018,-1002,-988,-972,-954,-938,-924,
--910,-893,-873,-855,-839,-821,-799,-777,-759,-745,-730,-714,-699,-684,-665,-642,-618,-593,-565,-528,-484,
--440,-397,-353,-308,-263,-219,-174,-127,-78,-26,29,90,156,223,286,341,387,423,457,492,530,
-568,606,645,686,723,753,778,802,825,852,885,922,958,988,1015,1047,1084,1123,1161,1199,1240,
-1280,1311,1325,1321,1306,1290,1283,1283,1283,1280,1275,1272,1269,1265,1265,1273,1284,1293,1298,1304,1310,
-1310,1306,1301,1300,1302,1308,1319,1329,1334,1335,1343,1355,1356,1338,1316,1311,1326,1336,1326,1301,1282,
-1274,1271,1268,1264,1262,1264,1267,1266,1251,1215,1170,1143,1147,1089,1102,1091,1054,1014,995,999,1010,
-1016,1015,1014,1012,1008,1003,997,994,992,993,996,1001,1006,1011,1019,1030,1046,1061,1073,1085,1102,
-1121,1139,1155,1171,1188,1203,1215,1229,1250,1277,1307,1337,1366,1396,1427,1466,1509,1544,1563,1577,1605,
-1653,1712,1773,1828,1852,1825,1757,1700,1699,1743,1788,1803,1791,1758,1697,1609,1514,1433,1366,1301,1236,
-1178,1120,1055,988,933,893,853,802,744,689,634,576,519,470,424,371,311,252,196,128,28,
--96,-217,-301,-341,-361,-386,-417,-430,-411,-375,-352,-360,-396,-458,-548,-643,-694,-672,-614,-587,-619,
--675,-725,-791,-908,-1057,-1173,-1216,-1211,-1201,-1191,-1171,-1148,-1147,-1163,-1168,-1162,-1178,-1228,-1263,-1225,-1148,
--1149,-1311,-1577,-1788,-1835,-1753,-1667,-1663,-1723,-1785,-1822,-1865,-1946,-2060,-2179,-2280,-2348,-2375,-2365,-2348,-2347,
--2355,-2357,-2367,-2414,-2489,-2544,-2569,-2629,-2781,-2975,-3081,-3043,-2942,-2898,-2940,-3008,-3056,-3095,-3139,-3172,-3176,
--3171,-3181,-3200,-3200,-3188,-3200,-3251,-3309,-3333,-3324,-3317,-3330,-3335,-3304,-3252,-3234,-3276,-3336,-3347,-3296,-3243,
--3237,-3261,-3260,-3209,-3132,-3058,-3002,-2979,-3006,-3077,-3153,-3194,-3199,-3197,-3209,-3228,-3243,-3256,-3272,-3291,-3309,
--3326,-3345,-3369,-3397,-3422,-3437,-3442,-3450,-3474,-3516,-3563,-3606,-3648,-3700,-3759,-3813,-3854,-3885,-3909,-3919,-3895,
--3832,-3758,-3714,-3719,-3759,-3800,-3830,-3865,-3928,-4028,-4158,-4295,-4413,-4497,-4558,-4622,-4700,-4779,-4838,-4877,-4914,
--4963,-5019,-5068,-5100,-5119,-5133,-5151,-5187,-5246,-5322,-5400,-5469,-5530,-5587,-5644,-5701,-5763,-5831,-5898,-5953,-5992,
--6027,-6068,-6112,-6153,-6200,-6263,-6339,-6415,-6488,-6569,-6665,-6767,-6857,-6928,-6981,-7023,-7062,-7101,-7141,-7177,-7209,
--7243,-7276,-7307,-7334,-7365,-7401,-7432,-7451,-7465,-7481,-7497,-7505,-7505,-7509,-7518,-7521,-7514,-7503,-7497,-7490,-7476,
--7451,-7428,-7419,-7426,-7435,-7432,-7417,-7402,-7396,-7395,-7388,-7368,-7333,-7278,-7210,-7143,-7092,-7054,-7018,-6988,-6974,
--6973,-6971,-6956,-6935,-6914,-6895,-6876,-6848,-6792,-6702,-6599,-6520,-6480,-6460,-6448,-6450,-6450,-6396,-6263,-6102,-5996,
--5966,-5953,-5902,-5808,-5695,-5583,-5488,-5429,-5403,-5374,-5310,-5208,-5088,-4959,-4823,-4692,-4579,-4480,-4385,-4296,-4214,
--4122,-4013,-3911,-3843,-3791,-3708,-3586,-3470,-3394,-3336,-3246,-3114,-2966,-2828,-2707,-2603,-2520,-2455,-2400,-2354,-2311,
--2249,-2145,-2010,-1876,-1761,-1657,-1555,-1454,-1343,-1199,-1023,-853,-723,-613,-490,-375,-343,-430,-575,-679,-709,
--707,-720,-736,-722,-677,-628,-586,-537,-476,-425,-408,-409,-386,-313,-205,-87,26,139,249,341,405,
-459,540,666,807,902,915,880,855,870,901,918,922,939,988,1064,1148,1223,1282,1334,1394,1461,
-1522,1580,1665,1800,1965,2119,2264,2456,2726,3027,3261,3365,3348,3261,3158,3072,3001,2910,2774,2626,2552,
-2607,2755,2906,3006,3062,3107,3150,3191,3239,3313,3415,3535,3666,3807,3958,4111,4260,4400,4526,4632,4720,
-4799,4873,4938,4987,5021,5054,5103,5174,5255,5330,5393,5451,5514,5583,5654,5718,5774,5826,5883,5952,6020,
-6066,6078,6072,6075,6097,6128,6164,6222,6313,6409,6462,6452,6407,6370,6361,6376,6402,6434,6467,6498,6533,
-6580,6642,6706,6763,6812,6850,6863,6846,6829,6852,6923,7007,7066,7104,7145,7205,7275,7345,7406,7440,7430,
-7379,7320,7273,7226,7161,7091,7050,7043,7034,6987,6915,6857,6841,6868,6931,7031,7148,7244,7296,7333,7416,
-7570,7750,7879,7921,7897,7847,7793,7741,7689,7635,7575,7509,7446,7394,7349,7307,7275,7264,7269,7272,7259,
-7231,7188,7130,7067,7019,6996,6984,6950,6879,6789,6721,6706,6740,6778,6774,6720,6638,6559,6486,6405,6300,
-6180,6079,6041,6069,6120,6151,6177,6242,6326,6335,6206,6010,5889,5909,6005,6071,6067,6014,5938,5853,5777,
-5736,5736,5768,5818,5865,5885,5866,5825,5795,5785,5772,5734,5677,5626,5594,5575,5554,5519,5454,5357,5241,
-5138,5072,5043,5030,5010,4977,4942,4905,4854,4777,4680,4589,4525,4487,4455,4407,4341,4272,4223,4196,4170,
-4123,4059,4002,3967,3940,3904,3863,3830,3801,3760,3706,3655,3622,3604,3592,3600,3642,3703,3733,3696,3611,
-3524,3457,3398,3335,3280,3244,3209,3155,3091,3046,3024,3000,2963,2930,2914,2901,2871,2831,2806,2800,2792,
-2771,2749,2738,2731,2714,2681,2642,2602,2558,2509,2456,2396,2328,2256,2192,2153,2140,2136,2123,2092,2050,
-2003,1955,1910,1875,1851,1828,1797,1759,1721,1682,1642,1610,1589,1564,1523,1480,1466,1487,1517,1534,1542,
-1550,1551,1536,1519,1513,1504,1469,1416,1378,1364,1344,1292,1219,1155,1107,1067,1030,1003,983,957,917,
-872,837,816,805,796,785,774,769,767,758,733,703,684,680,684,684,678,666,644,613,585,
-576,585,600,603,586,556,530,519,517,514,506,497,483,457,416,372,342,324,308,282,246,
-211,182,163,148,128,100,67,37,10,-16,-44,-69,-88,-104,-124,-147,-167,-182,-193,-204,-212,
--213,-211,-219,-239,-263,-280,-293,-308,-322,-331,-335,-337,-319,-256,-150,-50,-13,-48,-121,-197,-263,
--322,-369,-401,-422,-440,-462,-488,-522,-559,-591,-615,-636,-657,-677,-693,-708,-725,-741,-752,-763,-779,
--796,-808,-819,-836,-856,-873,-884,-898,-912,-923,-926,-928,-935,-943,-951,-961,-976,-987,-989,-985,-985,
--992,-1001,-1009,-1014,-1018,-1022,-1024,-1022,-1020,-1021,-1029,-1041,-1051,-1053,-1050,-1045,-1042,-1042,-1044,-1049,-1053,
--1052,-1047,-1044,-1043,-1047,-1054,-1063,-1070,-1072,-1071,-1069,-1066,-1062,-1059,-1058,-1056,-1051,-1043,-1036,-1029,-1020,
--1009,-1000,-990,-976,-958,-940,-923,-907,-891,-877,-865,-853,-841,-830,-822,-817,-810,-804,-799,-795,-788,
--780,-774,-770,-764,-758,-755,-757,-762,-768,-772,-776,-781,-787,-791,-795,-799,-805,-814,-824,-835,-849,
--863,-876,-887,-898,-914,-934,-956,-979,-1002,-1027,-1056,-1081,-1099,-1105,-1107,-1112,-1123,-1136,-1145,-1149,-1149,
--1150,-1155,-1162,-1170,-1174,-1175,-1174,-1173,-1172,-1170,-1169,-1167,-1163,-1158,-1155,-1155,-1155,-1150,-1140,-1129,-1119,
--1109,-1102,-1101,-1103,-1102,-1094,-1085,-1082,-1081,-1077,-1069,-1064,-1062,-1058,-1050,-1039,-1031,-1022,-1007,-986,-965,
--944,-923,-901,-878,-855,-831,-805,-782,-759,-734,-707,-684,-666,-643,-608,-570,-541,-518,-488,-453,-420,
--392,-358,-316,-276,-243,-204,-149,-94,-55,-21,22,66,88,92,106,126,106,21,-93,-166,-151,
--37,171,452,752,1031,1298,1581,1866,2099,2261,2387,2511,2624,2731,2879,3085,3255,3263,3093,2868,2708,
-2619,2545,2480,2473,2539,2626,2671,2663,2633,2610,2600,2604,2622,2660,2722,2795,2847,2846,2797,2736,2693,
-2669,2648,2624,2599,2571,2533,2489,2449,2416,2383,2348,2314,2287,2259,2224,2172,2093,1984,1864,1770,1725,
-1716,1708,1677,1629,1575,1513,1428,1318,1202,1105,1024,932,817,693,586,492,392,281,172,74,-21,
--122,-218,-297,-368,-432,-461,-427,-352,-315,-373,-512,-663,-773,-843,-900,-962,-1020,-1062,-1084,-1098,-1120,
--1152,-1181,-1195,-1198,-1201,-1207,-1211,-1217,-1252,-1341,-1477,-1618,-1732,-1814,-1879,-1927,-1942,-1916,-1867,-1822,-1793,
--1784,-1793,-1811,-1821,-1809,-1788,-1778,-1772,-1738,-1672,-1604,-1569,-1563,-1555,-1532,-1506,-1494,-1501,-1529,-1580,-1634,
--1664,-1666,-1663,-1668,-1654,-1590,-1488,-1398,-1348,-1320,-1282,-1229,-1181,-1151,-1146,-1177,-1246,-1317,-1327,-1239,-1090,
--959,-899,-902,-922,-926,-920,-927,-963,-1024,-1093,-1148,-1178,-1181,-1168,-1154,-1145,-1137,-1125,-1109,-1095,-1087,
--1083,-1077,-1067,-1055,-1044,-1030,-1014,-995,-978,-962,-948,-935,-922,-907,-889,-869,-850,-835,-822,-807,-789,
--774,-761,-747,-728,-707,-687,-667,-646,-625,-603,-576,-540,-497,-456,-416,-374,-327,-280,-236,-193,-146,
--94,-42,9,65,125,188,250,309,361,404,441,478,514,547,579,615,654,690,717,737,757,
-779,807,843,886,927,960,987,1016,1050,1089,1129,1168,1208,1246,1275,1291,1290,1275,1259,1250,1250,
-1251,1250,1248,1246,1241,1234,1230,1232,1234,1234,1235,1244,1258,1266,1267,1267,1273,1282,1291,1300,1307,
-1311,1314,1323,1335,1338,1324,1307,1304,1316,1321,1305,1274,1249,1239,1240,1244,1247,1248,1246,1240,1224,
-1193,1147,1103,1082,1089,1054,1055,1047,1031,1020,1020,1026,1028,1026,1026,1027,1027,1025,1020,1015,1010,
-1009,1011,1015,1019,1026,1035,1047,1060,1074,1088,1102,1117,1135,1156,1177,1195,1210,1224,1237,1250,1266,
-1287,1314,1343,1371,1395,1418,1447,1490,1540,1581,1603,1620,1651,1697,1748,1803,1857,1883,1854,1787,1745,
-1770,1832,1868,1857,1827,1802,1764,1691,1593,1500,1422,1352,1286,1227,1173,1112,1048,991,946,904,854,
-799,746,691,631,573,522,475,424,367,310,252,184,91,-25,-142,-229,-274,-289,-300,-313,-312,
--289,-259,-250,-277,-332,-402,-483,-562,-612,-616,-592,-581,-606,-654,-715,-798,-914,-1036,-1116,-1139,-1134,
--1132,-1134,-1127,-1122,-1140,-1174,-1195,-1203,-1234,-1300,-1341,-1280,-1140,-1061,-1175,-1459,-1748,-1881,-1839,-1730,-1667,
--1681,-1736,-1798,-1870,-1964,-2081,-2201,-2308,-2382,-2410,-2399,-2376,-2366,-2364,-2356,-2357,-2392,-2445,-2467,-2451,-2480,
--2631,-2855,-3005,-2990,-2883,-2820,-2854,-2933,-2994,-3033,-3068,-3093,-3094,-3085,-3092,-3116,-3133,-3138,-3150,-3186,-3231,
--3261,-3268,-3267,-3273,-3282,-3282,-3271,-3264,-3269,-3276,-3260,-3217,-3174,-3165,-3188,-3206,-3181,-3111,-3033,-2992,-3008,
--3065,-3126,-3156,-3149,-3134,-3136,-3158,-3187,-3210,-3227,-3244,-3263,-3282,-3300,-3315,-3328,-3342,-3359,-3378,-3394,-3411,
--3437,-3473,-3511,-3546,-3581,-3627,-3685,-3744,-3791,-3829,-3865,-3894,-3892,-3837,-3747,-3669,-3644,-3676,-3731,-3778,-3810,
--3853,-3934,-4060,-4205,-4329,-4413,-4471,-4532,-4606,-4679,-4736,-4782,-4830,-4883,-4930,-4962,-4980,-4991,-5003,-5026,-5071,
--5143,-5229,-5310,-5375,-5427,-5481,-5542,-5608,-5679,-5750,-5813,-5861,-5894,-5926,-5961,-5998,-6038,-6091,-6165,-6251,-6334,
--6412,-6496,-6592,-6691,-6777,-6843,-6891,-6928,-6964,-7001,-7039,-7072,-7105,-7142,-7180,-7213,-7240,-7270,-7306,-7337,-7356,
--7371,-7388,-7401,-7404,-7403,-7407,-7416,-7418,-7411,-7402,-7399,-7394,-7379,-7357,-7341,-7337,-7344,-7351,-7349,-7339,-7329,
--7327,-7327,-7321,-7299,-7255,-7190,-7120,-7065,-7033,-7009,-6980,-6953,-6945,-6954,-6957,-6941,-6913,-6886,-6865,-6844,-6812,
--6749,-6649,-6541,-6466,-6436,-6431,-6437,-6450,-6450,-6387,-6245,-6087,-5993,-5971,-5956,-5896,-5798,-5693,-5595,-5513,-5457,
--5424,-5382,-5306,-5200,-5080,-4954,-4825,-4708,-4615,-4529,-4431,-4321,-4213,-4111,-4012,-3934,-3884,-3834,-3743,-3614,-3501,
--3434,-3378,-3284,-3143,-2988,-2852,-2742,-2656,-2588,-2530,-2478,-2433,-2384,-2307,-2188,-2049,-1923,-1820,-1720,-1620,-1525,
--1420,-1273,-1087,-906,-769,-655,-531,-422,-399,-488,-622,-704,-705,-671,-653,-654,-648,-624,-590,-547,-489,
--423,-376,-367,-377,-364,-297,-186,-64,40,126,203,280,350,406,458,521,593,647,661,653,669,
-724,790,827,841,868,935,1029,1120,1189,1240,1288,1347,1414,1475,1526,1589,1684,1794,1885,1968,2104,
-2338,2624,2858,2970,2979,2950,2938,2956,2973,2941,2840,2718,2662,2718,2836,2925,2947,2941,2966,3043,3155,
-3286,3424,3562,3696,3831,3974,4120,4261,4390,4508,4615,4707,4786,4855,4913,4956,4986,5013,5050,5106,5180,
-5262,5336,5395,5444,5499,5565,5634,5695,5749,5803,5866,5937,6002,6042,6042,6020,6009,6028,6065,6104,6154,
-6232,6324,6386,6389,6351,6319,6317,6337,6365,6394,6428,6465,6507,6557,6614,6672,6726,6773,6803,6800,6767,
-6741,6763,6834,6915,6975,7021,7077,7148,7223,7295,7365,7412,7410,7355,7284,7228,7184,7136,7090,7066,7064,
-7058,7029,6985,6944,6913,6890,6885,6912,6967,7022,7061,7099,7173,7301,7465,7621,7731,7780,7778,7754,7733,
-7721,7696,7634,7541,7448,7384,7350,7326,7298,7270,7248,7233,7217,7191,7150,7102,7061,7035,7009,6957,6867,
-6758,6681,6679,6759,6873,6950,6945,6868,6759,6658,6579,6518,6449,6338,6179,6020,5924,5905,5936,6010,6160,
-6375,6545,6544,6373,6161,6036,6009,6011,5984,5917,5818,5701,5600,5552,5570,5635,5716,5791,5833,5831,5799,
-5778,5787,5802,5793,5753,5706,5667,5640,5622,5607,5574,5501,5389,5271,5180,5125,5087,5053,5026,5012,5003,
-4980,4926,4841,4740,4645,4571,4520,4476,4425,4366,4309,4261,4215,4168,4119,4070,4021,3978,3947,3929,3908,
-3865,3805,3746,3703,3672,3647,3646,3696,3794,3890,3918,3858,3750,3651,3575,3500,3417,3346,3304,3271,3218,
-3153,3109,3091,3072,3035,2998,2979,2965,2932,2885,2849,2831,2814,2788,2766,2756,2750,2735,2709,2680,2649,
-2612,2563,2505,2439,2365,2287,2217,2167,2143,2134,2122,2097,2060,2018,1976,1934,1895,1862,1832,1799,1759,
-1712,1667,1634,1622,1618,1591,1531,1468,1446,1472,1511,1529,1531,1534,1537,1530,1521,1518,1511,1481,1433,
-1393,1371,1342,1285,1208,1139,1092,1062,1038,1013,983,945,904,867,838,818,806,797,785,769,758,
-757,752,729,692,662,651,653,657,658,648,624,588,557,545,550,557,554,535,507,484,477,
-483,488,482,466,447,423,392,358,330,308,286,257,225,193,165,143,127,108,81,47,15,
--9,-34,-63,-94,-118,-135,-152,-172,-190,-203,-216,-234,-250,-256,-253,-256,-272,-292,-305,-312,-323,
--338,-350,-361,-377,-385,-352,-272,-180,-129,-139,-187,-243,-297,-345,-387,-417,-439,-458,-476,-499,-530,
--566,-597,-621,-645,-672,-695,-712,-725,-740,-753,-762,-771,-785,-800,-811,-820,-833,-850,-864,-876,-889,
--904,-914,-917,-921,-929,-937,-942,-949,-961,-971,-973,-969,-971,-980,-991,-998,-1004,-1009,-1012,-1011,-1007,
--1003,-1003,-1010,-1019,-1027,-1030,-1027,-1022,-1017,-1014,-1014,-1019,-1025,-1026,-1024,-1018,-1014,-1015,-1022,-1032,-1038,
--1038,-1037,-1036,-1036,-1032,-1025,-1019,-1016,-1011,-1005,-997,-987,-976,-966,-958,-950,-936,-918,-900,-885,-872,
--857,-843,-830,-820,-809,-800,-791,-785,-780,-775,-770,-764,-757,-751,-745,-740,-734,-730,-729,-731,-736,
--742,-747,-752,-756,-760,-766,-771,-775,-781,-788,-797,-809,-822,-837,-852,-864,-876,-892,-914,-937,-960,
--982,-1007,-1035,-1061,-1077,-1082,-1083,-1087,-1098,-1112,-1121,-1123,-1121,-1119,-1121,-1126,-1135,-1142,-1147,-1147,-1147,
--1146,-1147,-1147,-1147,-1144,-1139,-1136,-1135,-1135,-1130,-1120,-1109,-1100,-1092,-1087,-1085,-1086,-1082,-1072,-1060,-1054,
--1053,-1051,-1047,-1043,-1040,-1035,-1025,-1014,-1006,-998,-986,-967,-947,-928,-909,-888,-865,-840,-815,-789,-768,
--747,-722,-693,-668,-652,-633,-602,-562,-529,-505,-479,-449,-420,-393,-358,-313,-271,-239,-204,-153,-95,
--49,-13,29,77,110,124,136,154,153,106,16,-84,-149,-130,6,258,567,873,1158,1437,1711,
-1963,2192,2407,2590,2717,2820,2981,3211,3394,3398,3233,3044,2933,2869,2773,2654,2589,2611,2668,2695,2677,
-2637,2601,2579,2578,2601,2649,2720,2802,2863,2874,2838,2791,2756,2724,2684,2645,2626,2619,2598,2555,2508,
-2472,2442,2411,2384,2367,2353,2323,2264,2174,2064,1954,1873,1833,1821,1810,1780,1734,1678,1605,1509,1395,
-1285,1198,1121,1027,905,778,668,571,467,354,246,152,56,-50,-157,-251,-334,-405,-445,-428,-377,
--360,-427,-562,-700,-796,-851,-892,-939,-988,-1025,-1044,-1057,-1077,-1106,-1133,-1148,-1152,-1157,-1168,-1180,-1200,
--1252,-1356,-1502,-1647,-1756,-1823,-1866,-1895,-1901,-1870,-1810,-1743,-1696,-1687,-1712,-1748,-1765,-1756,-1739,-1732,-1726,
--1695,-1637,-1583,-1563,-1568,-1571,-1564,-1557,-1556,-1554,-1560,-1589,-1632,-1657,-1652,-1643,-1652,-1650,-1590,-1471,-1354,
--1292,-1276,-1261,-1229,-1192,-1170,-1171,-1206,-1282,-1366,-1386,-1293,-1121,-968,-906,-922,-947,-940,-914,-914,-958,
--1034,-1109,-1157,-1171,-1164,-1153,-1147,-1141,-1127,-1107,-1088,-1075,-1067,-1061,-1055,-1048,-1040,-1032,-1023,-1009,-989,
--967,-949,-936,-925,-912,-897,-880,-860,-840,-825,-815,-805,-793,-781,-772,-760,-740,-716,-692,-670,-649,
--629,-608,-581,-546,-506,-469,-434,-393,-344,-295,-251,-208,-159,-107,-54,-4,46,99,153,210,269,
-327,376,417,454,491,525,556,589,625,659,687,710,733,757,786,820,861,903,938,967,994,
-1025,1057,1091,1127,1166,1205,1237,1258,1261,1249,1231,1219,1217,1218,1219,1218,1214,1206,1195,1187,1184,
-1181,1177,1179,1193,1215,1231,1238,1245,1256,1271,1284,1292,1297,1299,1300,1304,1310,1311,1303,1296,1298,
-1308,1309,1290,1258,1230,1216,1216,1222,1226,1221,1207,1187,1166,1141,1108,1076,1057,1054,1071,1053,1043,
-1042,1048,1053,1051,1044,1040,1040,1041,1039,1036,1033,1030,1028,1028,1033,1039,1043,1048,1060,1075,1090,
-1102,1115,1131,1148,1166,1187,1208,1229,1245,1259,1273,1288,1307,1330,1355,1382,1406,1426,1443,1467,1507,
-1558,1602,1629,1653,1687,1729,1772,1819,1871,1900,1873,1810,1781,1826,1901,1935,1911,1878,1866,1850,1792,
-1694,1589,1497,1415,1338,1273,1218,1161,1100,1042,994,950,902,851,797,740,680,622,570,520,469,
-414,359,303,239,156,53,-54,-140,-189,-207,-211,-207,-192,-167,-154,-175,-227,-290,-349,-405,-464,
--515,-544,-551,-558,-586,-645,-729,-829,-929,-1007,-1048,-1057,-1057,-1067,-1082,-1094,-1107,-1132,-1168,-1198,-1229,
--1286,-1368,-1412,-1348,-1194,-1086,-1160,-1417,-1707,-1860,-1834,-1718,-1637,-1642,-1710,-1800,-1897,-2001,-2110,-2215,-2309,
--2383,-2426,-2434,-2424,-2414,-2403,-2385,-2373,-2390,-2423,-2425,-2389,-2397,-2535,-2763,-2930,-2928,-2817,-2744,-2784,-2881,
--2950,-2970,-2976,-2987,-2995,-2994,-2999,-3024,-3061,-3095,-3121,-3141,-3158,-3173,-3183,-3184,-3177,-3173,-3185,-3206,-3215,
--3201,-3174,-3150,-3130,-3111,-3102,-3114,-3135,-3132,-3090,-3036,-3019,-3054,-3111,-3141,-3129,-3097,-3080,-3089,-3118,-3152,
--3183,-3207,-3224,-3237,-3249,-3263,-3275,-3282,-3288,-3301,-3325,-3352,-3377,-3401,-3428,-3459,-3490,-3522,-3564,-3619,-3678,
--3727,-3765,-3805,-3850,-3878,-3855,-3777,-3681,-3622,-3625,-3672,-3724,-3757,-3790,-3860,-3981,-4125,-4248,-4329,-4385,-4445,
--4515,-4580,-4636,-4690,-4746,-4797,-4829,-4843,-4852,-4865,-4887,-4924,-4979,-5053,-5134,-5208,-5267,-5319,-5375,-5440,-5514,
--5589,-5659,-5716,-5758,-5790,-5820,-5853,-5887,-5930,-5992,-6075,-6167,-6252,-6332,-6418,-6512,-6606,-6687,-6749,-6793,-6826,
--6857,-6892,-6928,-6962,-6996,-7037,-7079,-7114,-7144,-7175,-7211,-7242,-7262,-7277,-7293,-7303,-7303,-7301,-7306,-7314,-7315,
--7308,-7302,-7300,-7292,-7275,-7257,-7249,-7253,-7263,-7270,-7272,-7269,-7265,-7262,-7258,-7247,-7219,-7168,-7099,-7035,-6999,
--6989,-6984,-6967,-6948,-6945,-6952,-6945,-6913,-6873,-6844,-6829,-6815,-6780,-6704,-6584,-6459,-6380,-6362,-6385,-6420,-6453,
--6456,-6384,-6237,-6081,-5988,-5959,-5929,-5860,-5769,-5685,-5611,-5538,-5477,-5428,-5370,-5284,-5175,-5063,-4951,-4840,-4742,
--4664,-4587,-4483,-4352,-4213,-4089,-3992,-3934,-3906,-3865,-3771,-3643,-3536,-3473,-3414,-3311,-3165,-3014,-2887,-2787,-2710,
--2647,-2591,-2541,-2496,-2443,-2354,-2225,-2087,-1975,-1886,-1798,-1702,-1605,-1491,-1332,-1139,-962,-833,-732,-629,-550,
--546,-624,-720,-763,-739,-687,-643,-615,-591,-563,-523,-464,-387,-309,-253,-229,-218,-190,-123,-26,71,
-146,197,245,308,379,431,448,442,440,448,453,461,496,573,666,736,781,834,922,1033,1135,
-1209,1260,1308,1366,1432,1494,1547,1604,1677,1749,1795,1824,1900,2070,2302,2510,2631,2683,2719,2778,2857,
-2922,2936,2887,2819,2796,2844,2913,2939,2917,2908,2968,3099,3261,3420,3567,3702,3831,3961,4092,4222,4344,
-4457,4561,4651,4726,4792,4851,4896,4924,4942,4966,5007,5069,5150,5243,5328,5391,5436,5485,5547,5614,5674,
-5727,5783,5845,5909,5962,5991,5984,5955,5936,5951,5991,6034,6080,6145,6228,6293,6307,6281,6258,6266,6294,
-6323,6349,6384,6430,6481,6532,6579,6624,6666,6704,6727,6721,6688,6664,6685,6750,6825,6886,6941,7009,7088,
-7165,7236,7305,7357,7362,7314,7241,7175,7127,7089,7061,7049,7048,7044,7033,7021,7006,6974,6927,6884,6868,
-6877,6894,6913,6940,6988,7060,7156,7272,7389,7482,7540,7578,7622,7667,7681,7634,7538,7442,7385,7370,7366,
-7341,7290,7231,7186,7160,7142,7121,7097,7074,7041,6972,6856,6717,6609,6590,6681,6848,7009,7079,7031,6907,
-6769,6651,6572,6540,6542,6517,6404,6214,6026,5902,5844,5854,5972,6210,6461,6558,6433,6186,5969,5853,5809,
-5780,5732,5648,5533,5425,5368,5375,5425,5496,5584,5670,5723,5737,5744,5775,5819,5839,5823,5792,5760,5728,
-5697,5676,5660,5622,5543,5441,5346,5268,5193,5119,5061,5034,5032,5035,5023,4981,4900,4789,4677,4594,4546,
-4516,4485,4442,4389,4338,4296,4255,4196,4112,4037,4004,4004,3989,3932,3864,3827,3820,3802,3760,3739,3787,
-3894,3988,3999,3926,3827,3754,3704,3635,3531,3424,3349,3301,3255,3211,3188,3184,3168,3125,3075,3041,3018,
-2983,2935,2893,2861,2832,2804,2787,2782,2775,2755,2729,2705,2680,2647,2602,2549,2488,2416,2339,2268,2213,
-2179,2159,2142,2114,2074,2032,1993,1954,1909,1862,1820,1785,1746,1698,1652,1628,1637,1653,1633,1562,1480,
-1444,1465,1502,1515,1509,1508,1515,1518,1515,1514,1512,1493,1451,1403,1359,1311,1250,1184,1128,1092,1068,
-1048,1021,981,934,891,859,834,814,803,801,796,781,762,750,737,711,673,639,620,615,618,
-622,619,598,566,536,521,516,511,503,493,478,461,452,456,463,459,440,413,385,359,336,
-315,293,267,237,209,182,153,128,109,93,69,34,0,-28,-52,-79,-110,-137,-157,-175,-195,
--213,-225,-239,-260,-283,-297,-299,-300,-309,-319,-324,-327,-336,-348,-356,-362,-376,-392,-384,-340,-283,
--250,-258,-291,-325,-354,-383,-412,-439,-462,-482,-500,-521,-549,-581,-610,-633,-657,-685,-710,-728,-743,
--757,-768,-775,-782,-794,-808,-819,-828,-839,-852,-862,-870,-881,-894,-903,-908,-914,-924,-932,-936,-940,
--948,-956,-958,-956,-960,-970,-979,-986,-990,-994,-995,-993,-989,-988,-990,-994,-998,-1002,-1003,-1001,-996,
--988,-983,-981,-985,-992,-998,-1000,-997,-992,-991,-997,-1006,-1010,-1009,-1006,-1008,-1010,-1006,-996,-986,-980,
--976,-971,-962,-949,-936,-924,-916,-908,-896,-880,-862,-847,-833,-818,-804,-792,-782,-774,-765,-757,-750,
--746,-743,-738,-732,-725,-721,-717,-711,-705,-702,-704,-706,-708,-712,-720,-728,-732,-735,-738,-744,-750,
--756,-764,-774,-785,-797,-811,-827,-842,-856,-873,-895,-919,-942,-963,-985,-1008,-1031,-1047,-1054,-1057,-1063,
--1074,-1085,-1091,-1091,-1090,-1089,-1088,-1091,-1098,-1108,-1116,-1118,-1117,-1117,-1118,-1120,-1122,-1122,-1121,-1118,-1116,
--1113,-1107,-1097,-1088,-1081,-1077,-1074,-1070,-1066,-1060,-1049,-1037,-1030,-1029,-1029,-1028,-1024,-1019,-1012,-1002,-991,
--982,-973,-960,-942,-924,-908,-891,-870,-847,-822,-797,-773,-751,-732,-709,-680,-653,-634,-618,-593,-558,
--524,-497,-471,-442,-414,-388,-356,-314,-270,-233,-198,-153,-99,-51,-12,30,81,129,159,175,186,
-190,168,109,11,-94,-150,-94,94,377,691,1001,1299,1581,1848,2117,2390,2632,2796,2902,3030,3204,
-3339,3337,3222,3111,3066,3027,2923,2784,2696,2693,2723,2727,2696,2653,2617,2593,2591,2613,2656,2717,2785,
-2839,2858,2846,2826,2809,2779,2726,2676,2660,2667,2661,2628,2587,2558,2537,2508,2472,2440,2408,2360,2286,
-2191,2090,2000,1937,1907,1896,1880,1847,1798,1741,1669,1576,1469,1370,1290,1214,1117,994,870,763,668,
-564,450,341,240,135,18,-98,-200,-289,-369,-427,-442,-430,-444,-526,-664,-804,-897,-937,-950,-965,
--990,-1017,-1033,-1042,-1054,-1074,-1097,-1111,-1119,-1133,-1156,-1186,-1229,-1298,-1404,-1537,-1666,-1762,-1820,-1851,-1866,
--1862,-1827,-1761,-1684,-1627,-1613,-1639,-1678,-1702,-1702,-1694,-1690,-1684,-1659,-1620,-1594,-1597,-1618,-1639,-1652,-1660,
--1655,-1633,-1611,-1618,-1647,-1660,-1640,-1616,-1622,-1631,-1583,-1465,-1340,-1271,-1259,-1253,-1227,-1194,-1179,-1191,-1237,
--1323,-1419,-1442,-1337,-1145,-982,-930,-960,-985,-960,-919,-918,-972,-1054,-1123,-1157,-1157,-1141,-1130,-1130,-1130,
--1118,-1099,-1082,-1070,-1059,-1047,-1036,-1028,-1020,-1013,-1007,-998,-982,-961,-940,-926,-914,-902,-889,-875,-857,
--837,-819,-808,-801,-793,-785,-777,-766,-749,-725,-700,-675,-651,-628,-605,-578,-544,-508,-474,-443,-405,
--358,-311,-267,-224,-175,-122,-70,-20,28,77,124,173,229,288,341,384,422,461,498,531,563,
-597,630,662,691,722,752,781,813,849,889,925,957,984,1010,1034,1059,1090,1129,1170,1205,1227,
-1232,1220,1201,1186,1180,1180,1180,1178,1170,1160,1150,1146,1145,1144,1143,1149,1167,1190,1210,1222,1231,
-1244,1260,1272,1281,1284,1283,1279,1276,1276,1277,1277,1279,1287,1295,1293,1275,1248,1222,1207,1202,1203,
-1199,1185,1162,1142,1138,1143,1142,1125,1097,1071,1109,1075,1063,1066,1073,1073,1066,1058,1056,1057,1055,
-1050,1047,1048,1049,1048,1049,1055,1062,1066,1070,1081,1098,1115,1129,1143,1160,1177,1194,1213,1235,1259,
-1280,1297,1312,1330,1351,1376,1402,1426,1448,1464,1476,1492,1523,1565,1605,1636,1666,1702,1740,1776,1822,
-1881,1921,1904,1849,1827,1876,1953,1986,1963,1939,1944,1948,1906,1815,1705,1599,1499,1405,1327,1264,1205,
-1144,1086,1036,992,946,894,837,778,720,666,615,563,511,458,407,353,294,220,131,36,-42,
--90,-112,-116,-108,-87,-69,-79,-128,-196,-254,-295,-331,-374,-421,-457,-481,-507,-557,-642,-750,-851,
--923,-963,-984,-996,-1004,-1017,-1040,-1072,-1104,-1128,-1145,-1171,-1222,-1307,-1404,-1452,-1400,-1271,-1180,-1239,-1454,
--1700,-1828,-1795,-1682,-1605,-1619,-1703,-1816,-1935,-2052,-2157,-2242,-2308,-2367,-2419,-2456,-2474,-2476,-2460,-2428,-2396,
--2391,-2406,-2401,-2367,-2371,-2493,-2703,-2860,-2858,-2747,-2680,-2732,-2837,-2888,-2866,-2835,-2848,-2890,-2922,-2935,-2950,
--2984,-3030,-3068,-3089,-3103,-3122,-3141,-3134,-3092,-3043,-3035,-3073,-3115,-3119,-3092,-3067,-3057,-3045,-3024,-3011,-3021,
--3034,-3030,-3018,-3029,-3068,-3101,-3098,-3067,-3041,-3044,-3068,-3097,-3126,-3155,-3180,-3194,-3196,-3196,-3203,-3213,-3223,
--3231,-3248,-3277,-3312,-3340,-3359,-3379,-3408,-3442,-3477,-3516,-3565,-3620,-3666,-3698,-3733,-3785,-3841,-3861,-3819,-3729,
--3642,-3603,-3618,-3654,-3685,-3717,-3786,-3906,-4049,-4167,-4243,-4298,-4359,-4426,-4488,-4543,-4598,-4653,-4693,-4712,-4719,
--4729,-4753,-4791,-4843,-4905,-4973,-5038,-5098,-5155,-5212,-5273,-5341,-5414,-5488,-5555,-5607,-5646,-5677,-5709,-5744,-5783,
--5833,-5904,-5992,-6083,-6168,-6250,-6336,-6425,-6509,-6582,-6640,-6684,-6716,-6746,-6781,-6820,-6856,-6893,-6933,-6976,-7015,
--7048,-7083,-7119,-7148,-7166,-7181,-7195,-7203,-7202,-7201,-7207,-7215,-7214,-7208,-7203,-7199,-7186,-7167,-7155,-7158,-7172,
--7186,-7196,-7203,-7204,-7199,-7191,-7180,-7161,-7124,-7070,-7009,-6964,-6951,-6962,-6972,-6968,-6962,-6963,-6960,-6931,-6877,
--6825,-6800,-6798,-6793,-6758,-6667,-6525,-6378,-6290,-6285,-6337,-6404,-6454,-6457,-6379,-6226,-6065,-5962,-5914,-5868,-5800,
--5731,-5678,-5627,-5560,-5489,-5427,-5358,-5266,-5159,-5055,-4959,-4866,-4778,-4701,-4619,-4510,-4368,-4213,-4071,-3971,-3927,
--3916,-3883,-3792,-3669,-3571,-3510,-3444,-3335,-3194,-3061,-2952,-2862,-2784,-2714,-2650,-2593,-2542,-2483,-2392,-2265,-2134,
--2031,-1952,-1872,-1783,-1682,-1552,-1378,-1183,-1021,-914,-836,-766,-725,-742,-798,-840,-834,-789,-732,-674,-619,
--570,-527,-478,-411,-328,-244,-175,-121,-72,-16,54,133,208,269,316,363,426,497,547,549,509,
-460,427,410,407,431,495,582,662,721,782,868,975,1080,1165,1230,1284,1339,1398,1457,1513,1573,
-1643,1708,1745,1759,1801,1919,2100,2282,2421,2521,2611,2707,2798,2868,2901,2898,2889,2906,2955,2996,2998,
-2983,3012,3120,3280,3440,3570,3679,3787,3904,4031,4155,4272,4381,4484,4574,4644,4697,4746,4796,4837,4858,
-4871,4894,4938,5003,5092,5199,5300,5370,5413,5456,5518,5589,5651,5704,5756,5809,5857,5894,5913,5908,5884,
-5866,5879,5921,5968,6015,6075,6149,6210,6227,6212,6204,6224,6257,6284,6304,6335,6382,6436,6484,6523,6552,
-6577,6603,6626,6632,6619,6606,6622,6672,6738,6800,6862,6936,7020,7100,7172,7235,7280,7288,7249,7180,7107,
-7048,7014,7006,7016,7024,7023,7021,7023,7017,6984,6929,6880,6854,6845,6837,6835,6847,6872,6900,6934,6990,
-7070,7154,7229,7301,7386,7473,7526,7517,7459,7395,7364,7370,7384,7371,7318,7247,7188,7157,7137,7108,7067,
-7013,6933,6813,6666,6543,6499,6562,6716,6902,7034,7047,6947,6799,6666,6563,6490,6470,6518,6579,6558,6420,
-6224,6045,5905,5810,5809,5937,6124,6214,6117,5893,5682,5565,5535,5546,5553,5524,5450,5361,5291,5244,5208,
-5206,5282,5433,5590,5690,5740,5788,5845,5881,5880,5863,5847,5820,5780,5748,5738,5729,5685,5606,5516,5429,
-5333,5223,5123,5061,5042,5052,5068,5063,5013,4916,4804,4716,4669,4647,4627,4595,4552,4515,4491,4460,4384,
-4263,4151,4102,4098,4075,4010,3961,3979,4030,4034,3967,3894,3888,3946,3998,3987,3924,3863,3837,3826,3779,
-3677,3550,3442,3367,3312,3275,3262,3263,3246,3194,3129,3081,3050,3019,2979,2935,2889,2843,2808,2796,2798,
-2790,2766,2740,2720,2700,2670,2632,2592,2544,2479,2403,2328,2266,2222,2193,2170,2139,2092,2040,1994,1953,
-1907,1854,1805,1766,1728,1683,1638,1618,1635,1664,1655,1590,1505,1460,1467,1490,1491,1476,1472,1484,1496,
-1498,1499,1504,1498,1468,1416,1353,1287,1225,1172,1132,1102,1076,1049,1016,972,923,881,851,825,802,
-791,793,797,788,765,741,719,690,655,623,601,588,584,586,586,572,545,519,501,486,471,
-464,468,471,458,438,425,425,425,410,380,347,319,298,282,262,236,210,188,166,139,110,
-88,72,50,17,-20,-49,-72,-96,-125,-153,-177,-199,-222,-242,-255,-267,-284,-305,-323,-332,-337,
--342,-346,-348,-351,-359,-371,-377,-378,-383,-395,-402,-390,-370,-361,-371,-388,-400,-408,-420,-441,-467,
--492,-514,-534,-557,-584,-613,-639,-659,-680,-703,-725,-743,-758,-772,-782,-788,-793,-803,-815,-826,-836,
--846,-856,-863,-868,-877,-889,-899,-905,-912,-920,-927,-930,-932,-938,-944,-947,-948,-952,-959,-965,-969,
--972,-973,-973,-971,-971,-975,-979,-981,-981,-980,-979,-976,-971,-964,-958,-955,-956,-962,-969,-974,-975,
--972,-971,-977,-985,-988,-985,-981,-983,-985,-981,-969,-956,-948,-943,-937,-928,-915,-900,-887,-876,-868,
--857,-844,-829,-812,-796,-780,-766,-755,-748,-741,-733,-724,-715,-711,-708,-704,-697,-692,-690,-689,-682,
--675,-673,-676,-679,-678,-680,-689,-700,-707,-710,-713,-718,-726,-733,-742,-752,-761,-772,-786,-803,-819,
--835,-852,-874,-900,-925,-945,-961,-977,-994,-1009,-1021,-1029,-1038,-1048,-1055,-1056,-1055,-1056,-1060,-1062,-1064,
--1070,-1079,-1088,-1090,-1089,-1089,-1090,-1091,-1092,-1095,-1097,-1095,-1091,-1086,-1080,-1072,-1064,-1060,-1061,-1061,-1057,
--1047,-1035,-1024,-1015,-1009,-1008,-1009,-1008,-1004,-998,-990,-981,-971,-961,-949,-934,-917,-901,-887,-871,-850,
--825,-801,-777,-754,-731,-710,-689,-665,-640,-619,-602,-581,-552,-521,-493,-466,-434,-401,-373,-346,-312,
--270,-228,-190,-149,-103,-57,-15,26,77,132,180,209,223,227,219,184,107,-5,-105,-120,-7,
-224,527,858,1188,1497,1782,2069,2375,2667,2884,3006,3086,3167,3224,3209,3142,3095,3090,3069,2983,2869,
-2803,2800,2808,2783,2732,2684,2648,2623,2613,2625,2657,2702,2754,2800,2828,2839,2845,2844,2819,2769,2721,
-2706,2716,2715,2690,2663,2653,2651,2632,2586,2521,2443,2355,2262,2172,2089,2018,1968,1947,1939,1922,1885,
-1837,1787,1730,1653,1562,1475,1400,1324,1225,1105,984,880,783,677,560,444,336,228,114,4,-96,
--190,-282,-361,-410,-441,-492,-597,-747,-897,-995,-1026,-1017,-1009,-1022,-1043,-1051,-1042,-1033,-1040,-1059,-1078,
--1098,-1123,-1158,-1202,-1261,-1342,-1445,-1559,-1667,-1755,-1816,-1850,-1857,-1836,-1785,-1711,-1633,-1578,-1560,-1573,-1600,
--1625,-1641,-1649,-1651,-1644,-1631,-1620,-1624,-1645,-1677,-1709,-1737,-1752,-1740,-1701,-1660,-1647,-1654,-1647,-1610,-1574,
--1573,-1581,-1540,-1434,-1323,-1266,-1259,-1249,-1213,-1175,-1164,-1186,-1243,-1341,-1444,-1470,-1357,-1156,-998,-962,-1006,
--1031,-1002,-965,-978,-1040,-1112,-1160,-1174,-1161,-1137,-1121,-1118,-1118,-1109,-1092,-1077,-1064,-1048,-1032,-1021,-1015,
--1007,-996,-986,-981,-972,-955,-935,-918,-905,-893,-883,-874,-861,-841,-820,-806,-799,-793,-785,-777,-767,
--753,-732,-707,-680,-652,-624,-599,-572,-539,-504,-473,-445,-411,-369,-327,-287,-246,-197,-144,-93,-44,
-5,54,97,139,190,249,303,349,390,432,472,508,540,573,608,642,675,710,743,774,806,
-841,878,915,948,975,998,1017,1037,1066,1103,1142,1172,1187,1187,1174,1158,1144,1138,1137,1136,1132,
-1124,1116,1113,1116,1122,1129,1135,1145,1160,1179,1196,1209,1219,1229,1239,1252,1264,1271,1269,1262,1258,
-1262,1268,1271,1271,1271,1272,1269,1257,1240,1223,1210,1200,1190,1177,1157,1138,1134,1156,1193,1215,1202,
-1158,1109,1121,1088,1078,1081,1084,1080,1073,1069,1071,1072,1068,1062,1062,1069,1072,1070,1069,1074,1083,
-1088,1092,1103,1120,1139,1155,1172,1189,1206,1220,1238,1261,1286,1311,1332,1351,1371,1395,1422,1449,1473,
-1494,1510,1521,1530,1546,1573,1604,1633,1664,1699,1735,1774,1830,1904,1963,1964,1923,1904,1945,2010,2036,
-2017,2000,2014,2031,2007,1932,1827,1711,1592,1482,1390,1315,1248,1184,1127,1079,1034,985,931,872,812,
-756,706,657,607,554,504,455,404,347,278,197,112,43,1,-19,-27,-24,-13,-13,-49,-115,
--181,-223,-247,-275,-311,-346,-373,-402,-451,-534,-645,-758,-841,-881,-901,-927,-958,-977,-985,-1008,-1055,
--1099,-1112,-1104,-1121,-1194,-1309,-1417,-1462,-1416,-1314,-1250,-1316,-1512,-1730,-1839,-1798,-1681,-1600,-1612,-1699,-1823,
--1958,-2094,-2210,-2285,-2326,-2360,-2406,-2460,-2502,-2517,-2499,-2454,-2406,-2383,-2388,-2390,-2373,-2387,-2492,-2668,-2797,
--2788,-2690,-2641,-2701,-2789,-2796,-2719,-2658,-2686,-2778,-2861,-2895,-2902,-2918,-2951,-2989,-3021,-3053,-3094,-3128,-3119,
--3051,-2966,-2930,-2969,-3037,-3070,-3054,-3019,-2989,-2960,-2921,-2890,-2886,-2906,-2933,-2961,-2999,-3036,-3049,-3027,-2997,
--2992,-3016,-3050,-3076,-3096,-3117,-3138,-3146,-3141,-3133,-3133,-3143,-3158,-3172,-3193,-3224,-3260,-3290,-3308,-3326,-3355,
--3395,-3436,-3474,-3518,-3567,-3609,-3636,-3662,-3710,-3778,-3833,-3834,-3771,-3677,-3601,-3571,-3578,-3599,-3636,-3712,-3835,
--3975,-4088,-4161,-4216,-4275,-4340,-4400,-4453,-4503,-4545,-4573,-4589,-4603,-4624,-4658,-4705,-4765,-4831,-4890,-4940,-4990,
--5048,-5112,-5178,-5243,-5312,-5383,-5446,-5495,-5531,-5563,-5597,-5636,-5684,-5744,-5819,-5905,-5993,-6079,-6166,-6252,-6333,
--6404,-6467,-6522,-6567,-6602,-6634,-6673,-6716,-6757,-6795,-6836,-6878,-6919,-6957,-6994,-7029,-7054,-7070,-7084,-7099,-7106,
--7105,-7104,-7110,-7117,-7118,-7113,-7108,-7099,-7082,-7066,-7063,-7076,-7097,-7116,-7129,-7134,-7131,-7120,-7107,-7090,-7062,
--7019,-6967,-6926,-6909,-6921,-6947,-6966,-6974,-6979,-6982,-6965,-6912,-6839,-6784,-6767,-6774,-6774,-6734,-6632,-6474,-6313,
--6221,-6229,-6304,-6389,-6443,-6438,-6351,-6195,-6028,-5913,-5852,-5805,-5755,-5716,-5693,-5656,-5587,-5505,-5432,-5360,-5269,
--5164,-5066,-4981,-4895,-4802,-4708,-4613,-4504,-4371,-4217,-4067,-3958,-3914,-3911,-3886,-3801,-3687,-3599,-3544,-3478,-3372,
--3247,-3139,-3054,-2974,-2890,-2805,-2721,-2642,-2571,-2502,-2416,-2304,-2186,-2086,-2003,-1924,-1840,-1739,-1602,-1425,-1243,
--1103,-1017,-957,-910,-899,-930,-964,-957,-903,-836,-774,-711,-640,-572,-517,-464,-399,-320,-239,-160,-83,
--6,68,136,200,265,334,407,478,548,616,670,688,662,608,553,516,499,507,544,605,670,
-724,775,839,924,1020,1111,1187,1246,1296,1347,1400,1456,1521,1599,1679,1735,1767,1808,1900,2044,2202,
-2342,2463,2575,2678,2762,2822,2863,2895,2933,2992,3063,3116,3139,3160,3225,3347,3487,3603,3682,3746,3826,
-3930,4049,4166,4272,4371,4464,4540,4591,4624,4662,4713,4758,4783,4796,4816,4856,4920,5016,5136,5251,5327,
-5368,5407,5466,5536,5597,5646,5694,5742,5783,5814,5835,5838,5823,5810,5822,5863,5918,5974,6037,6105,6154,
-6167,6159,6164,6196,6233,6256,6272,6300,6344,6391,6429,6455,6471,6482,6496,6519,6543,6555,6554,6558,6587,
-6642,6709,6779,6856,6943,7030,7106,7162,7195,7201,7173,7111,7031,6960,6926,6937,6970,6995,7001,6997,6996,
-6983,6943,6886,6841,6822,6813,6799,6784,6784,6796,6809,6822,6846,6884,6926,6967,7018,7093,7178,7244,7270,
-7261,7244,7243,7270,7312,7336,7321,7275,7227,7191,7146,7070,6962,6838,6706,6573,6466,6429,6485,6615,6771,
-6898,6947,6895,6772,6646,6558,6491,6421,6383,6428,6532,6593,6540,6398,6236,6080,5931,5822,5797,5833,5835,
-5738,5578,5446,5394,5414,5470,5527,5546,5517,5454,5368,5238,5064,4930,4957,5171,5453,5663,5767,5828,5886,
-5924,5925,5913,5909,5898,5862,5825,5816,5821,5798,5732,5649,5568,5477,5363,5247,5162,5121,5114,5116,5104,
-5062,4997,4934,4891,4862,4826,4776,4723,4685,4672,4681,4673,4603,4472,4342,4270,4238,4187,4116,4098,4176,
-4281,4303,4210,4082,4005,3992,3997,3983,3953,3931,3926,3924,3898,3831,3736,3632,3530,3431,3350,3304,3288,
-3267,3218,3154,3102,3067,3037,3001,2956,2900,2841,2800,2790,2795,2788,2764,2740,2726,2710,2683,2651,2623,
-2589,2532,2455,2375,2305,2250,2213,2186,2154,2104,2039,1978,1930,1888,1842,1796,1754,1717,1675,1632,1607,
-1614,1636,1636,1591,1526,1483,1477,1481,1468,1445,1439,1452,1468,1474,1478,1488,1493,1477,1430,1363,1290,
-1226,1179,1142,1109,1075,1042,1006,962,915,875,846,818,790,772,771,778,774,756,732,706,678,
-648,621,597,577,562,557,554,543,524,504,484,461,439,434,451,465,451,415,383,374,377,
-374,352,317,280,252,231,211,190,170,155,139,116,88,65,46,22,-11,-47,-78,-102,-125,
--152,-181,-208,-234,-256,-274,-286,-293,-302,-316,-333,-347,-358,-367,-376,-383,-390,-400,-414,-426,-430,
--431,-436,-443,-446,-444,-442,-445,-447,-446,-447,-457,-478,-504,-528,-552,-576,-601,-627,-653,-676,-696,
--713,-729,-745,-759,-773,-786,-796,-802,-806,-814,-823,-831,-839,-848,-856,-861,-866,-875,-888,-900,-908,
--913,-918,-923,-925,-928,-932,-937,-941,-944,-948,-951,-953,-956,-957,-958,-956,-954,-956,-962,-968,-970,
--967,-963,-960,-957,-953,-949,-944,-940,-938,-939,-944,-949,-950,-949,-949,-955,-963,-966,-962,-958,-958,
--958,-954,-943,-930,-920,-912,-903,-892,-880,-867,-853,-839,-828,-818,-808,-796,-780,-762,-746,-734,-726,
--720,-715,-707,-696,-686,-680,-677,-673,-666,-660,-660,-660,-654,-645,-643,-648,-652,-650,-650,-657,-670,
--679,-685,-691,-699,-706,-713,-721,-730,-738,-747,-761,-778,-795,-811,-829,-852,-879,-905,-925,-939,-949,
--960,-974,-987,-999,-1010,-1019,-1023,-1021,-1021,-1027,-1037,-1044,-1047,-1050,-1057,-1064,-1066,-1065,-1065,-1066,-1064,
--1064,-1066,-1068,-1067,-1062,-1056,-1052,-1046,-1039,-1037,-1042,-1047,-1043,-1030,-1014,-1002,-995,-991,-990,-989,-986,
--982,-975,-968,-960,-951,-939,-926,-911,-894,-880,-867,-852,-830,-803,-778,-757,-735,-710,-685,-665,-647,
--628,-607,-587,-565,-540,-514,-489,-462,-429,-391,-357,-329,-301,-265,-223,-184,-147,-106,-59,-12,31,
-76,129,183,228,254,265,267,251,200,104,-7,-72,-29,139,410,742,1095,1434,1744,2045,2368,
-2697,2961,3109,3160,3172,3175,3157,3120,3094,3090,3074,3020,2957,2929,2930,2913,2854,2782,2726,2689,2654,
-2627,2626,2653,2693,2734,2774,2811,2842,2864,2870,2852,2814,2778,2763,2763,2757,2739,2725,2732,2747,2745,
-2702,2611,2484,2351,2241,2160,2094,2030,1981,1960,1958,1947,1913,1872,1838,1805,1754,1680,1603,1531,1454,
-1356,1238,1120,1013,909,793,669,552,453,371,294,212,117,7,-110,-216,-298,-365,-449,-577,-744,
--910,-1022,-1056,-1039,-1026,-1043,-1069,-1068,-1036,-1003,-996,-1014,-1042,-1074,-1110,-1149,-1195,-1256,-1342,-1446,-1553,
--1653,-1743,-1816,-1857,-1856,-1813,-1739,-1653,-1582,-1541,-1528,-1530,-1540,-1562,-1594,-1619,-1624,-1616,-1613,-1626,-1650,
--1676,-1703,-1736,-1768,-1784,-1769,-1727,-1682,-1653,-1637,-1608,-1560,-1521,-1510,-1503,-1455,-1362,-1277,-1247,-1254,-1243,
--1197,-1150,-1136,-1161,-1223,-1324,-1428,-1453,-1342,-1150,-1011,-999,-1058,-1089,-1068,-1051,-1080,-1141,-1189,-1208,-1205,
--1186,-1158,-1132,-1118,-1109,-1096,-1077,-1057,-1038,-1018,-1003,-1001,-1007,-1004,-989,-973,-965,-959,-947,-930,-914,
--900,-887,-877,-872,-862,-844,-821,-805,-797,-791,-782,-773,-764,-752,-735,-711,-683,-653,-624,-598,-571,
--539,-505,-474,-446,-414,-377,-340,-305,-266,-219,-167,-117,-68,-18,29,71,111,158,213,269,317,
-362,407,449,487,522,557,593,627,660,693,725,757,790,826,863,899,930,956,977,995,1015,
-1043,1076,1105,1123,1126,1120,1112,1103,1098,1096,1098,1099,1097,1091,1088,1090,1098,1109,1121,1132,1144,
-1156,1167,1180,1193,1202,1208,1215,1232,1254,1269,1270,1266,1271,1287,1301,1297,1279,1260,1250,1247,1244,
-1239,1233,1222,1206,1187,1168,1152,1144,1155,1189,1231,1251,1229,1176,1121,1106,1089,1089,1091,1090,1085,
-1081,1081,1083,1083,1079,1076,1081,1090,1093,1090,1088,1094,1104,1112,1119,1131,1147,1164,1181,1199,1217,
-1232,1247,1265,1288,1313,1337,1361,1383,1405,1431,1460,1488,1513,1536,1557,1572,1579,1584,1596,1616,1640,
-1667,1697,1733,1781,1852,1943,2016,2035,2009,1993,2022,2070,2089,2070,2053,2061,2080,2072,2020,1927,1806,
-1675,1555,1454,1368,1290,1223,1169,1123,1075,1022,966,909,850,794,742,692,641,590,542,495,445,
-387,319,241,162,100,66,51,42,35,27,0,-56,-127,-179,-200,-213,-241,-276,-298,-314,-348,
--420,-528,-647,-747,-801,-818,-834,-876,-929,-957,-964,-986,-1036,-1077,-1075,-1055,-1081,-1183,-1323,-1432,-1459,
--1400,-1302,-1255,-1339,-1553,-1788,-1910,-1870,-1738,-1634,-1625,-1702,-1826,-1968,-2113,-2237,-2316,-2349,-2367,-2399,-2450,
--2498,-2517,-2496,-2445,-2390,-2362,-2369,-2385,-2393,-2421,-2512,-2648,-2740,-2726,-2654,-2633,-2694,-2751,-2708,-2586,-2499,
--2527,-2640,-2754,-2818,-2843,-2861,-2889,-2925,-2963,-3002,-3038,-3064,-3060,-3013,-2943,-2896,-2909,-2961,-2998,-2986,-2936,
--2879,-2832,-2795,-2772,-2772,-2796,-2837,-2888,-2941,-2981,-2988,-2967,-2947,-2952,-2982,-3015,-3038,-3053,-3068,-3082,-3088,
--3085,-3078,-3076,-3084,-3098,-3114,-3133,-3162,-3199,-3231,-3253,-3271,-3300,-3343,-3388,-3428,-3469,-3515,-3554,-3578,-3598,
--3636,-3700,-3769,-3802,-3774,-3694,-3601,-3535,-3510,-3522,-3569,-3657,-3780,-3912,-4018,-4089,-4143,-4198,-4256,-4311,-4359,
--4399,-4429,-4451,-4473,-4502,-4536,-4571,-4615,-4674,-4739,-4795,-4839,-4887,-4949,-5019,-5086,-5149,-5213,-5279,-5338,-5385,
--5422,-5456,-5494,-5539,-5592,-5658,-5734,-5816,-5900,-5987,-6078,-6166,-6240,-6300,-6353,-6406,-6452,-6489,-6524,-6566,-6613,
--6657,-6697,-6738,-6781,-6824,-6866,-6904,-6937,-6959,-6975,-6991,-7006,-7014,-7012,-7010,-7015,-7023,-7026,-7023,-7015,-7002,
--6987,-6978,-6986,-7005,-7027,-7045,-7057,-7059,-7047,-7029,-7013,-6996,-6964,-6917,-6875,-6858,-6872,-6903,-6935,-6957,-6972,
--6983,-6981,-6948,-6878,-6800,-6752,-6746,-6756,-6748,-6698,-6588,-6425,-6263,-6176,-6197,-6285,-6372,-6412,-6388,-6293,-6141,
--5981,-5868,-5810,-5780,-5757,-5746,-5736,-5699,-5620,-5527,-5448,-5376,-5289,-5188,-5093,-5011,-4922,-4814,-4699,-4591,-4490,
--4375,-4230,-4072,-3947,-3897,-3898,-3884,-3809,-3705,-3630,-3587,-3532,-3437,-3330,-3245,-3180,-3109,-3020,-2917,-2807,-2697,
--2597,-2512,-2430,-2337,-2237,-2139,-2049,-1964,-1880,-1784,-1656,-1495,-1338,-1223,-1148,-1090,-1046,-1042,-1074,-1092,-1052,
--966,-878,-807,-741,-667,-595,-533,-474,-407,-330,-248,-162,-73,13,89,151,204,265,348,448,541,
-608,656,705,751,765,734,678,637,629,648,682,726,777,828,874,924,989,1071,1157,1230,1286,
-1331,1378,1431,1488,1556,1643,1738,1817,1871,1922,2002,2114,2232,2337,2432,2529,2625,2711,2782,2844,2907,
-2986,3085,3191,3276,3331,3378,3445,3535,3625,3692,3740,3789,3858,3949,4052,4152,4243,4328,4408,4471,4508,
-4534,4571,4627,4680,4711,4725,4739,4769,4828,4928,5061,5189,5273,5314,5347,5394,5449,5498,5543,5596,5654,
-5706,5747,5776,5786,5777,5767,5779,5821,5883,5953,6026,6089,6123,6123,6115,6129,6166,6202,6223,6240,6272,
-6314,6350,6371,6382,6389,6393,6398,6416,6448,6477,6485,6482,6496,6547,6621,6701,6780,6866,6958,7036,7085,
-7108,7111,7090,7034,6949,6869,6836,6857,6905,6940,6950,6945,6937,6917,6874,6821,6782,6766,6760,6746,6726,
-6714,6714,6723,6739,6758,6775,6780,6780,6793,6831,6884,6932,6964,6980,6987,7001,7041,7109,7179,7216,7212,
-7187,7149,7078,6951,6785,6620,6487,6401,6378,6438,6566,6712,6821,6866,6842,6762,6660,6581,6538,6490,6408,
-6334,6350,6465,6587,6617,6545,6426,6295,6155,6013,5901,5822,5747,5653,5565,5522,5532,5577,5637,5687,5703,
-5678,5626,5530,5334,5031,4751,4694,4927,5303,5614,5779,5862,5929,5973,5973,5958,5959,5962,5939,5902,5888,
-5892,5876,5818,5744,5679,5612,5524,5426,5348,5303,5272,5229,5165,5094,5048,5046,5070,5068,5007,4905,4811,
-4765,4774,4812,4833,4792,4689,4572,4485,4416,4329,4248,4249,4354,4475,4494,4386,4229,4108,4047,4033,4045,
-4065,4067,4042,4003,3972,3953,3924,3859,3742,3584,3429,3325,3280,3263,3235,3194,3151,3111,3066,3016,2965,
-2913,2863,2826,2812,2807,2792,2763,2740,2730,2716,2687,2654,2628,2599,2549,2478,2403,2335,2276,2229,2193,
-2158,2107,2036,1962,1904,1865,1832,1793,1752,1713,1678,1642,1611,1593,1590,1585,1564,1529,1501,1489,1479,
-1458,1433,1423,1431,1444,1452,1460,1473,1483,1474,1437,1378,1310,1246,1191,1145,1103,1066,1033,1000,959,
-915,877,846,816,784,759,751,752,749,738,721,700,675,649,624,601,574,550,533,524,515,
-504,490,471,443,415,407,422,434,416,373,334,322,331,339,328,296,252,211,180,158,142,
-129,119,106,89,69,49,26,-3,-41,-80,-113,-140,-164,-188,-215,-244,-270,-289,-302,-309,-314,
--319,-328,-343,-361,-378,-394,-409,-422,-432,-440,-455,-473,-485,-486,-481,-479,-481,-480,-477,-473,-471,
--473,-481,-499,-523,-547,-568,-590,-615,-640,-664,-686,-707,-727,-743,-755,-767,-780,-792,-803,-811,-818,
--823,-829,-834,-839,-844,-850,-855,-858,-862,-871,-885,-899,-908,-913,-917,-921,-925,-927,-929,-932,-937,
--943,-946,-947,-947,-948,-951,-951,-949,-946,-947,-951,-955,-957,-954,-949,-945,-943,-942,-941,-938,-933,
--928,-925,-925,-926,-926,-924,-925,-930,-936,-938,-934,-931,-929,-927,-921,-913,-905,-896,-885,-873,-860,
--848,-835,-820,-804,-789,-778,-770,-760,-746,-729,-715,-706,-699,-694,-688,-681,-671,-659,-652,-650,-646,
--638,-631,-630,-631,-626,-617,-615,-621,-627,-627,-626,-630,-640,-650,-659,-669,-679,-686,-690,-696,-705,
--714,-724,-736,-753,-770,-787,-807,-831,-858,-884,-904,-917,-927,-938,-949,-959,-969,-979,-988,-992,-991,
--992,-1002,-1017,-1026,-1029,-1030,-1035,-1041,-1043,-1042,-1043,-1043,-1042,-1041,-1042,-1044,-1041,-1034,-1027,-1024,-1021,
--1015,-1013,-1019,-1027,-1026,-1012,-995,-982,-976,-973,-970,-967,-963,-958,-951,-944,-937,-927,-916,-904,-890,
--875,-861,-848,-834,-812,-784,-758,-738,-719,-695,-667,-646,-631,-616,-597,-573,-550,-527,-502,-479,-455,
--427,-389,-350,-317,-289,-258,-221,-186,-152,-113,-62,-8,40,84,129,180,231,271,296,308,308,
-282,214,112,23,12,118,336,636,982,1336,1672,1993,2325,2666,2957,3127,3179,3182,3192,3202,3187,
-3152,3122,3100,3074,3050,3045,3045,3010,2935,2857,2809,2774,2726,2673,2653,2675,2711,2739,2761,2796,2839,
-2873,2885,2877,2857,2835,2817,2805,2798,2792,2791,2800,2816,2825,2795,2698,2544,2381,2260,2188,2131,2064,
-2004,1977,1976,1968,1938,1905,1890,1880,1849,1791,1723,1654,1577,1479,1365,1252,1144,1030,902,769,659,
-593,570,559,522,430,291,136,-1,-111,-206,-313,-456,-638,-825,-959,-1005,-992,-985,-1016,-1054,-1054,
--1013,-972,-961,-977,-1003,-1038,-1080,-1120,-1159,-1211,-1294,-1403,-1517,-1624,-1720,-1797,-1836,-1823,-1762,-1672,-1583,
--1525,-1508,-1515,-1519,-1523,-1545,-1588,-1623,-1624,-1606,-1602,-1624,-1652,-1670,-1686,-1712,-1741,-1755,-1742,-1711,-1674,
--1641,-1607,-1564,-1515,-1475,-1450,-1421,-1360,-1277,-1217,-1213,-1235,-1231,-1186,-1135,-1114,-1131,-1187,-1280,-1376,-1395,
--1290,-1124,-1022,-1041,-1117,-1156,-1145,-1141,-1176,-1223,-1244,-1239,-1228,-1212,-1185,-1149,-1120,-1099,-1079,-1054,-1027,
--998,-971,-956,-963,-982,-992,-982,-965,-953,-946,-936,-924,-912,-899,-886,-875,-868,-859,-842,-820,-804,
--794,-787,-778,-769,-762,-752,-736,-713,-686,-656,-629,-604,-579,-548,-512,-480,-451,-419,-384,-348,-316,
--281,-237,-186,-136,-88,-39,8,51,91,136,187,239,288,334,379,421,460,498,537,576,612,
-643,672,701,732,765,802,839,872,900,924,945,965,986,1011,1037,1055,1061,1057,1053,1053,1056,
-1060,1063,1068,1073,1076,1074,1073,1076,1083,1094,1106,1121,1135,1146,1154,1165,1178,1187,1191,1199,1222,
-1252,1270,1270,1267,1283,1316,1338,1328,1291,1256,1240,1242,1248,1249,1245,1233,1211,1186,1168,1162,1166,
-1177,1196,1214,1214,1186,1142,1106,1097,1098,1101,1101,1098,1097,1096,1095,1095,1094,1093,1095,1101,1107,
-1110,1109,1111,1119,1129,1137,1147,1160,1173,1187,1201,1219,1237,1253,1271,1293,1317,1339,1360,1384,1408,
-1431,1457,1485,1514,1540,1565,1593,1617,1628,1629,1634,1648,1668,1687,1711,1747,1805,1888,1984,2059,2084,
-2067,2054,2075,2114,2132,2118,2097,2094,2106,2108,2076,1995,1875,1740,1617,1513,1418,1331,1261,1210,1164,
-1111,1053,999,946,890,831,770,711,653,601,556,512,461,404,338,263,187,129,99,89,80,
-64,36,-10,-79,-147,-181,-185,-192,-222,-257,-275,-288,-333,-421,-534,-639,-715,-750,-762,-784,-834,
--892,-925,-938,-966,-1014,-1045,-1037,-1032,-1092,-1225,-1368,-1452,-1446,-1366,-1265,-1230,-1337,-1584,-1855,-2003,-1968,
--1820,-1689,-1658,-1726,-1848,-1984,-2114,-2226,-2306,-2349,-2371,-2395,-2432,-2469,-2482,-2458,-2406,-2355,-2335,-2348,-2375,
--2404,-2449,-2531,-2630,-2688,-2675,-2636,-2646,-2709,-2745,-2678,-2537,-2421,-2402,-2471,-2569,-2657,-2724,-2776,-2823,-2874,
--2922,-2945,-2932,-2909,-2907,-2922,-2915,-2870,-2817,-2796,-2803,-2797,-2753,-2689,-2643,-2633,-2651,-2680,-2717,-2764,-2822,
--2879,-2919,-2930,-2920,-2910,-2914,-2934,-2960,-2985,-3004,-3017,-3026,-3033,-3038,-3039,-3037,-3038,-3045,-3059,-3077,-3104,
--3139,-3173,-3197,-3216,-3244,-3285,-3331,-3373,-3414,-3455,-3492,-3518,-3538,-3569,-3622,-3686,-3733,-3733,-3676,-3582,-3496,
--3454,-3470,-3535,-3635,-3752,-3864,-3953,-4019,-4072,-4121,-4168,-4212,-4253,-4287,-4314,-4339,-4372,-4413,-4450,-4480,-4515,
--4568,-4630,-4686,-4734,-4788,-4856,-4929,-4996,-5056,-5116,-5175,-5228,-5274,-5317,-5360,-5405,-5453,-5509,-5577,-5653,-5732,
--5814,-5900,-5990,-6075,-6143,-6197,-6246,-6296,-6342,-6381,-6419,-6461,-6508,-6552,-6592,-6634,-6679,-6725,-6768,-6806,-6838,
--6863,-6882,-6899,-6914,-6920,-6919,-6918,-6923,-6931,-6936,-6933,-6923,-6909,-6897,-6898,-6914,-6933,-6949,-6963,-6973,-6972,
--6954,-6933,-6920,-6905,-6874,-6830,-6801,-6808,-6844,-6886,-6918,-6940,-6956,-6964,-6951,-6901,-6822,-6752,-6724,-6733,-6742,
--6720,-6653,-6536,-6376,-6222,-6145,-6176,-6271,-6351,-6370,-6325,-6227,-6090,-5953,-5857,-5815,-5804,-5801,-5799,-5786,-5739,
--5652,-5552,-5470,-5397,-5311,-5213,-5119,-5032,-4935,-4815,-4687,-4575,-4483,-4383,-4246,-4081,-3945,-3890,-3901,-3900,-3836,
--3739,-3672,-3643,-3604,-3523,-3427,-3354,-3302,-3239,-3145,-3027,-2894,-2759,-2635,-2534,-2449,-2369,-2284,-2197,-2109,-2022,
--1937,-1845,-1731,-1597,-1469,-1371,-1298,-1232,-1180,-1166,-1183,-1185,-1131,-1033,-932,-851,-783,-716,-649,-580,-506,
--427,-344,-257,-165,-73,10,83,146,200,261,348,461,560,610,624,653,712,762,755,707,677,
-699,754,808,853,903,965,1026,1082,1143,1214,1289,1349,1392,1431,1479,1536,1596,1665,1754,1853,1941,
-2005,2063,2136,2221,2295,2347,2393,2457,2544,2643,2741,2835,2935,3051,3186,3320,3425,3492,3537,3581,3628,
-3673,3715,3763,3824,3897,3976,4057,4134,4207,4278,4344,4397,4430,4455,4493,4549,4603,4640,4656,4665,4682,
-4734,4838,4983,5124,5217,5262,5288,5318,5351,5386,5432,5497,5573,5642,5695,5729,5740,5732,5725,5739,5783,
-5849,5931,6016,6080,6102,6088,6073,6085,6116,6144,6160,6182,6221,6264,6288,6291,6291,6297,6302,6305,6315,
-6344,6380,6399,6401,6415,6467,6550,6635,6714,6797,6887,6963,7006,7020,7018,6993,6931,6842,6767,6744,6774,
-6822,6855,6866,6865,6856,6837,6803,6765,6735,6718,6706,6689,6664,6639,6621,6616,6625,6641,6650,6645,6634,
-6632,6647,6671,6693,6712,6725,6731,6737,6766,6833,6915,6973,6990,6980,6951,6882,6758,6604,6475,6408,6403,
-6455,6557,6686,6795,6845,6836,6791,6729,6668,6624,6592,6534,6428,6322,6307,6418,6581,6680,6667,6576,6460,
-6345,6233,6128,6031,5941,5870,5833,5835,5858,5883,5904,5907,5875,5818,5758,5670,5464,5101,4717,4555,4737,
-5134,5506,5733,5861,5957,6021,6032,6015,6014,6025,6012,5976,5950,5946,5931,5886,5828,5780,5735,5675,5608,
-5556,5524,5483,5405,5291,5180,5122,5139,5190,5199,5123,4993,4883,4840,4858,4901,4926,4907,4842,4758,4677,
-4588,4482,4396,4392,4476,4564,4561,4453,4302,4172,4095,4082,4132,4204,4228,4176,4085,4022,4015,4027,3998,
-3886,3705,3517,3386,3334,3323,3314,3292,3262,3217,3147,3070,3013,2983,2962,2938,2909,2874,2828,2779,2745,
-2730,2717,2688,2650,2615,2581,2533,2474,2417,2367,2316,2261,2208,2161,2109,2040,1963,1898,1857,1828,1795,
-1753,1713,1685,1663,1633,1593,1555,1532,1521,1512,1501,1492,1481,1462,1439,1422,1418,1423,1434,1449,1465,
-1472,1462,1431,1384,1327,1263,1196,1135,1085,1050,1025,999,963,922,884,852,821,788,762,747,740,
-733,722,709,693,671,647,625,602,573,542,518,502,493,486,478,460,430,398,381,380,377,
-354,318,290,284,295,305,299,273,231,184,146,122,111,103,92,77,62,50,37,14,-21,
--64,-107,-145,-173,-193,-211,-234,-266,-296,-315,-325,-333,-341,-349,-358,-375,-397,-417,-432,-446,-457,
--461,-461,-468,-485,-500,-501,-490,-481,-480,-481,-480,-482,-490,-504,-523,-546,-570,-589,-605,-624,-648,
--671,-691,-708,-728,-747,-762,-774,-787,-802,-815,-823,-829,-835,-841,-845,-848,-851,-855,-858,-860,-861,
--864,-871,-882,-894,-903,-909,-914,-922,-928,-931,-929,-929,-934,-941,-944,-944,-943,-945,-948,-949,-947,
--944,-941,-940,-942,-943,-941,-936,-932,-933,-935,-937,-934,-928,-921,-915,-911,-907,-905,-903,-904,-907,
--908,-906,-902,-899,-896,-891,-884,-878,-875,-869,-859,-846,-832,-818,-804,-788,-771,-755,-741,-731,-722,
--709,-695,-683,-675,-669,-664,-657,-651,-642,-631,-623,-621,-618,-611,-603,-600,-600,-597,-590,-589,-595,
--603,-607,-607,-609,-615,-622,-630,-640,-651,-657,-661,-667,-677,-688,-699,-711,-727,-745,-764,-785,-811,
--837,-860,-879,-894,-908,-922,-933,-940,-945,-951,-959,-964,-966,-969,-980,-994,-1002,-1003,-1003,-1009,-1016,
--1018,-1017,-1017,-1018,-1019,-1020,-1022,-1023,-1019,-1011,-1002,-999,-997,-992,-989,-992,-999,-1000,-989,-973,-961,
--957,-954,-950,-945,-940,-935,-928,-920,-911,-902,-892,-881,-869,-856,-841,-828,-814,-796,-769,-742,-721,
--705,-685,-659,-636,-620,-605,-585,-562,-539,-516,-490,-463,-440,-418,-388,-350,-314,-284,-254,-223,-191,
--160,-122,-72,-14,39,87,131,179,231,281,319,341,351,345,307,229,138,91,138,288,527,
-836,1186,1542,1881,2216,2553,2848,3037,3117,3159,3220,3276,3276,3221,3161,3128,3111,3100,3102,3108,3086,
-3031,2980,2961,2942,2880,2792,2736,2736,2751,2746,2734,2753,2802,2848,2870,2877,2881,2877,2861,2847,2852,
-2871,2885,2886,2886,2890,2869,2780,2619,2446,2323,2259,2207,2136,2065,2026,2016,2001,1966,1934,1923,1920,
-1898,1854,1801,1744,1669,1569,1458,1355,1254,1139,999,857,756,728,769,828,835,747,585,403,245,
-116,0,-123,-272,-459,-661,-817,-882,-880,-884,-932,-991,-1008,-982,-956,-953,-961,-970,-991,-1031,-1076,
--1112,-1155,-1230,-1340,-1463,-1579,-1674,-1738,-1757,-1729,-1662,-1576,-1497,-1457,-1468,-1503,-1529,-1543,-1572,-1622,-1657,
--1646,-1609,-1589,-1601,-1620,-1627,-1633,-1654,-1679,-1689,-1681,-1666,-1649,-1626,-1591,-1549,-1501,-1453,-1407,-1356,-1294,
--1229,-1187,-1188,-1211,-1216,-1184,-1137,-1106,-1107,-1147,-1225,-1303,-1311,-1218,-1089,-1031,-1082,-1170,-1211,-1202,-1199,
--1226,-1255,-1256,-1240,-1229,-1219,-1192,-1151,-1111,-1082,-1057,-1030,-998,-962,-927,-905,-908,-930,-951,-955,-949,
--940,-933,-924,-917,-911,-903,-890,-877,-867,-857,-841,-820,-804,-794,-786,-777,-770,-763,-753,-737,-715,
--688,-660,-635,-612,-588,-557,-521,-487,-457,-425,-389,-353,-322,-291,-251,-204,-155,-107,-59,-11,33,
-77,122,169,216,261,304,346,386,424,464,506,547,584,616,645,673,703,735,771,806,838,
-865,890,913,936,958,980,998,1008,1009,1008,1011,1021,1032,1038,1040,1044,1051,1057,1059,1059,1061,
-1066,1074,1086,1102,1120,1134,1145,1158,1172,1182,1187,1197,1219,1243,1251,1239,1231,1252,1297,1330,1323,
-1286,1254,1247,1256,1262,1258,1248,1232,1209,1183,1169,1171,1179,1180,1173,1161,1146,1126,1107,1097,1114,
-1118,1116,1110,1108,1109,1111,1110,1109,1110,1113,1117,1121,1124,1127,1131,1138,1147,1153,1160,1169,1182,
-1193,1203,1214,1232,1251,1270,1291,1316,1341,1361,1380,1403,1428,1451,1474,1501,1529,1554,1580,1612,1642,
-1658,1662,1669,1687,1708,1723,1742,1781,1849,1939,2028,2089,2104,2088,2078,2098,2138,2165,2163,2145,2133,
-2137,2142,2119,2045,1925,1789,1668,1563,1462,1369,1296,1245,1197,1140,1080,1029,982,927,863,791,718,
-648,591,548,508,459,403,342,275,204,147,115,102,88,62,23,-30,-96,-153,-174,-170,-176,
--208,-245,-267,-290,-346,-437,-534,-613,-668,-700,-722,-751,-795,-839,-868,-894,-938,-992,-1024,-1034,-1072,
--1179,-1323,-1433,-1462,-1417,-1328,-1242,-1228,-1356,-1618,-1899,-2055,-2026,-1881,-1744,-1703,-1766,-1887,-2013,-2116,-2196,
--2263,-2317,-2355,-2381,-2406,-2429,-2434,-2409,-2363,-2322,-2307,-2317,-2343,-2384,-2448,-2533,-2612,-2650,-2645,-2637,-2672,
--2739,-2775,-2723,-2593,-2445,-2345,-2323,-2372,-2465,-2559,-2629,-2689,-2765,-2844,-2867,-2805,-2724,-2718,-2797,-2857,-2800,
--2652,-2526,-2491,-2504,-2492,-2441,-2405,-2425,-2491,-2565,-2631,-2694,-2759,-2816,-2852,-2867,-2869,-2868,-2870,-2879,-2901,
--2930,-2956,-2971,-2979,-2988,-3000,-3007,-3002,-2994,-2994,-3007,-3027,-3052,-3082,-3112,-3137,-3158,-3184,-3222,-3266,-3307,
--3345,-3381,-3416,-3447,-3476,-3510,-3554,-3607,-3654,-3665,-3621,-3531,-3442,-3405,-3441,-3531,-3640,-3740,-3819,-3882,-3937,
--3989,-4035,-4072,-4105,-4140,-4175,-4208,-4241,-4279,-4320,-4351,-4375,-4406,-4455,-4515,-4573,-4628,-4691,-4763,-4837,-4903,
--4962,-5019,-5071,-5117,-5163,-5214,-5269,-5321,-5371,-5427,-5495,-5574,-5655,-5735,-5817,-5901,-5979,-6043,-6095,-6142,-6190,
--6236,-6277,-6317,-6361,-6405,-6447,-6486,-6529,-6576,-6623,-6666,-6703,-6737,-6766,-6790,-6808,-6819,-6824,-6824,-6825,-6830,
--6837,-6841,-6839,-6828,-6814,-6806,-6814,-6832,-6848,-6858,-6869,-6878,-6876,-6858,-6839,-6828,-6815,-6786,-6750,-6740,-6767,
--6815,-6859,-6890,-6910,-6924,-6923,-6893,-6831,-6753,-6699,-6694,-6720,-6729,-6693,-6610,-6486,-6330,-6185,-6116,-6156,-6255,
--6329,-6332,-6273,-6178,-6065,-5957,-5884,-5857,-5854,-5850,-5838,-5813,-5759,-5673,-5577,-5493,-5416,-5329,-5229,-5128,-5029,
--4919,-4793,-4666,-4559,-4475,-4385,-4258,-4100,-3967,-3916,-3935,-3944,-3885,-3787,-3720,-3699,-3672,-3600,-3507,-3438,-3397,
--3343,-3248,-3116,-2970,-2825,-2695,-2585,-2490,-2406,-2330,-2260,-2188,-2109,-2021,-1929,-1829,-1721,-1616,-1526,-1449,-1379,
--1324,-1298,-1292,-1273,-1213,-1118,-1017,-930,-858,-796,-730,-651,-561,-469,-381,-291,-197,-110,-34,37,110,
-177,242,329,442,541,577,565,572,634,703,713,672,652,698,782,853,903,958,1034,1115,1186,
-1252,1321,1387,1433,1462,1493,1538,1593,1652,1719,1803,1899,1987,2057,2126,2206,2285,2338,2361,2378,2420,
-2498,2600,2712,2826,2950,3094,3251,3394,3498,3557,3591,3621,3651,3681,3718,3774,3843,3912,3975,4033,4093,
-4156,4219,4279,4328,4363,4391,4426,4472,4522,4563,4587,4595,4605,4651,4758,4911,5057,5155,5204,5229,5249,
-5270,5301,5354,5430,5512,5585,5642,5678,5688,5681,5676,5692,5734,5800,5887,5981,6051,6070,6047,6024,6027,
-6049,6066,6076,6099,6139,6178,6193,6188,6185,6196,6211,6217,6222,6243,6279,6309,6324,6346,6402,6486,6573,
-6653,6735,6820,6892,6932,6943,6929,6884,6800,6705,6648,6652,6694,6738,6764,6780,6787,6782,6762,6739,6720,
-6708,6695,6677,6653,6623,6589,6556,6533,6524,6524,6526,6524,6524,6530,6543,6555,6565,6575,6583,6582,6572,
-6572,6600,6644,6675,6681,6675,6667,6637,6570,6493,6455,6480,6549,6631,6714,6789,6838,6844,6819,6786,6756,
-6726,6691,6646,6575,6462,6343,6295,6372,6535,6679,6718,6649,6532,6426,6353,6298,6238,6173,6122,6099,6096,
-6093,6084,6073,6043,5976,5886,5814,5745,5578,5235,4814,4554,4626,4962,5348,5635,5824,5964,6058,6088,6077,
-6073,6084,6079,6046,6013,5997,5983,5953,5912,5874,5837,5790,5742,5710,5690,5655,5580,5463,5339,5252,5229,
-5242,5232,5161,5057,4980,4959,4975,4989,4984,4956,4912,4859,4799,4723,4631,4554,4533,4566,4593,4559,4462,
-4340,4225,4142,4122,4182,4281,4334,4291,4183,4085,4039,4029,4002,3917,3778,3634,3538,3499,3482,3457,3427,
-3398,3352,3270,3175,3117,3113,3126,3110,3054,2971,2879,2795,2739,2715,2706,2686,2649,2608,2564,2514,2462,
-2419,2388,2354,2301,2235,2170,2111,2049,1980,1916,1868,1835,1799,1754,1712,1689,1680,1658,1607,1541,1492,
-1474,1475,1478,1477,1474,1464,1443,1418,1399,1397,1413,1438,1458,1461,1443,1412,1374,1326,1264,1190,1118,
-1063,1031,1012,993,964,929,894,863,831,801,777,760,747,731,714,699,683,665,644,623,601,
-573,541,512,490,477,471,464,447,419,387,363,343,319,290,266,257,260,266,268,261,241,
-209,169,132,108,97,88,71,47,28,19,12,-7,-42,-85,-127,-163,-191,-205,-215,-235,-272,
--312,-339,-354,-368,-384,-397,-408,-425,-448,-466,-474,-476,-477,-472,-463,-461,-473,-486,-487,-478,-473,
--476,-484,-492,-505,-523,-544,-565,-588,-610,-628,-641,-658,-679,-701,-717,-732,-749,-765,-777,-787,-802,
--821,-836,-843,-846,-850,-855,-858,-860,-865,-871,-874,-874,-873,-874,-878,-885,-893,-900,-905,-913,-923,
--932,-933,-929,-927,-931,-937,-941,-940,-940,-941,-944,-946,-946,-943,-937,-933,-931,-930,-928,-923,-921,
--925,-929,-930,-926,-919,-911,-905,-898,-891,-886,-885,-886,-887,-884,-877,-871,-866,-862,-855,-847,-842,
--839,-835,-826,-815,-803,-788,-770,-753,-738,-724,-709,-696,-686,-674,-661,-649,-641,-636,-630,-623,-617,
--610,-601,-593,-590,-588,-582,-575,-570,-570,-568,-565,-565,-570,-578,-583,-585,-589,-592,-596,-601,-608,
--616,-623,-629,-639,-652,-664,-674,-685,-701,-719,-738,-761,-786,-811,-833,-850,-867,-886,-903,-916,-922,
--925,-930,-936,-942,-945,-948,-957,-967,-973,-973,-973,-979,-988,-992,-990,-988,-989,-993,-996,-999,-1000,
--997,-989,-981,-976,-974,-971,-966,-964,-967,-968,-961,-949,-940,-936,-934,-929,-923,-918,-914,-906,-896,
--886,-876,-866,-856,-847,-835,-821,-807,-795,-780,-756,-727,-703,-688,-673,-651,-628,-609,-592,-571,-548,
--526,-505,-478,-447,-420,-400,-378,-347,-314,-283,-256,-227,-196,-164,-126,-81,-30,22,76,128,180,
-235,292,341,370,385,392,382,336,259,196,193,272,437,692,1023,1386,1736,2071,2402,2706,2927,
-3058,3157,3265,3343,3334,3254,3177,3140,3119,3098,3099,3128,3150,3144,3137,3156,3161,3095,2970,2864,2816,
-2786,2736,2690,2694,2747,2800,2828,2851,2881,2904,2904,2904,2932,2979,3007,3001,2982,2974,2950,2860,2699,
-2525,2405,2344,2297,2228,2155,2108,2083,2052,2006,1964,1940,1922,1895,1863,1837,1803,1737,1635,1524,1429,
-1341,1229,1084,934,835,830,914,1018,1054,975,812,635,480,342,202,60,-89,-264,-460,-626,-708,
--726,-752,-828,-914,-956,-955,-953,-963,-962,-943,-938,-971,-1024,-1068,-1109,-1174,-1277,-1399,-1516,-1603,-1644,
--1634,-1589,-1527,-1462,-1404,-1381,-1413,-1479,-1539,-1576,-1615,-1664,-1692,-1667,-1609,-1567,-1558,-1562,-1559,-1560,-1577,
--1596,-1602,-1600,-1602,-1608,-1606,-1593,-1569,-1525,-1458,-1379,-1313,-1268,-1234,-1207,-1197,-1206,-1212,-1195,-1157,-1117,
--1100,-1122,-1178,-1232,-1229,-1153,-1065,-1048,-1116,-1199,-1232,-1219,-1214,-1234,-1251,-1244,-1226,-1217,-1208,-1182,-1137,
--1092,-1059,-1032,-1006,-975,-939,-899,-866,-855,-866,-888,-907,-918,-921,-916,-910,-907,-906,-901,-889,-876,
--866,-856,-841,-822,-806,-796,-788,-780,-773,-766,-757,-741,-720,-694,-665,-639,-616,-592,-562,-527,-494,
--463,-430,-393,-357,-326,-296,-261,-218,-173,-128,-84,-37,11,59,107,152,194,236,277,315,351,
-387,426,467,508,545,578,611,642,672,705,738,772,805,836,868,897,924,946,963,974,980,
-982,986,996,1011,1023,1026,1023,1022,1027,1034,1038,1040,1044,1051,1059,1069,1085,1105,1125,1142,1157,
-1172,1185,1195,1204,1218,1228,1220,1198,1186,1207,1255,1293,1296,1274,1259,1263,1272,1268,1253,1239,1228,
-1213,1193,1179,1179,1182,1171,1148,1124,1109,1106,1108,1114,1141,1137,1128,1120,1118,1122,1124,1125,1126,
-1130,1135,1138,1140,1142,1147,1155,1165,1172,1175,1178,1186,1199,1209,1217,1228,1246,1266,1286,1307,1331,
-1355,1375,1395,1419,1443,1464,1486,1512,1539,1561,1585,1616,1646,1664,1672,1687,1716,1744,1762,1784,1833,
-1915,2008,2083,2119,2117,2095,2088,2112,2157,2195,2207,2196,2183,2181,2182,2157,2079,1955,1820,1701,1597,
-1496,1403,1331,1278,1226,1167,1109,1060,1014,959,892,815,729,645,579,538,503,458,403,347,288,
-226,171,134,111,84,48,7,-38,-88,-130,-147,-147,-158,-193,-234,-266,-304,-367,-449,-523,-576,
--613,-645,-676,-708,-740,-767,-791,-832,-899,-972,-1025,-1077,-1172,-1315,-1441,-1485,-1447,-1373,-1300,-1252,-1269,
--1403,-1646,-1898,-2039,-2026,-1911,-1791,-1742,-1789,-1905,-2030,-2120,-2175,-2222,-2275,-2323,-2353,-2370,-2383,-2385,-2365,
--2330,-2298,-2281,-2275,-2287,-2334,-2420,-2522,-2599,-2634,-2643,-2660,-2706,-2771,-2817,-2801,-2702,-2537,-2371,-2278,-2290,
--2370,-2436,-2453,-2468,-2550,-2683,-2759,-2711,-2610,-2600,-2709,-2796,-2711,-2476,-2262,-2193,-2228,-2246,-2206,-2168,-2199,
--2294,-2405,-2505,-2596,-2680,-2743,-2778,-2794,-2804,-2813,-2818,-2825,-2845,-2876,-2906,-2925,-2937,-2951,-2965,-2969,-2959,
--2943,-2939,-2951,-2972,-2994,-3015,-3037,-3061,-3087,-3118,-3153,-3192,-3228,-3261,-3292,-3327,-3367,-3408,-3451,-3496,-3546,
--3587,-3593,-3543,-3453,-3375,-3361,-3425,-3533,-3638,-3714,-3761,-3799,-3843,-3894,-3940,-3973,-4001,-4034,-4073,-4112,-4149,
--4184,-4214,-4237,-4259,-4292,-4342,-4402,-4463,-4526,-4596,-4669,-4739,-4802,-4862,-4917,-4965,-5008,-5056,-5116,-5178,-5234,
--5283,-5338,-5406,-5488,-5572,-5653,-5731,-5807,-5879,-5941,-5992,-6038,-6084,-6130,-6174,-6217,-6262,-6306,-6347,-6387,-6431,
--6479,-6526,-6567,-6604,-6639,-6672,-6698,-6714,-6722,-6724,-6726,-6729,-6733,-6736,-6738,-6736,-6728,-6715,-6710,-6719,-6738,
--6752,-6761,-6772,-6783,-6781,-6765,-6747,-6734,-6718,-6692,-6671,-6683,-6726,-6779,-6821,-6850,-6869,-6876,-6861,-6818,-6752,
--6684,-6648,-6662,-6699,-6710,-6666,-6573,-6443,-6289,-6150,-6087,-6132,-6235,-6309,-6305,-6239,-6148,-6055,-5975,-5926,-5908,
--5898,-5877,-5844,-5805,-5753,-5681,-5597,-5513,-5431,-5340,-5237,-5124,-5004,-4876,-4746,-4629,-4533,-4456,-4375,-4268,-4137,
--4024,-3979,-3994,-3999,-3937,-3835,-3764,-3744,-3721,-3651,-3556,-3492,-3464,-3426,-3333,-3192,-3037,-2896,-2773,-2661,-2553,
--2455,-2377,-2320,-2267,-2197,-2108,-2014,-1926,-1843,-1759,-1673,-1592,-1524,-1476,-1445,-1417,-1374,-1307,-1220,-1125,-1035,
--957,-889,-817,-729,-630,-537,-450,-358,-265,-187,-126,-64,12,91,164,249,361,463,502,488,492,
-558,637,659,625,610,660,747,818,867,924,1008,1099,1179,1250,1319,1381,1421,1444,1467,1504,1549,
-1599,1663,1746,1839,1927,2007,2095,2196,2291,2356,2389,2415,2459,2527,2614,2709,2815,2940,3088,3246,3384,
-3476,3526,3563,3606,3651,3690,3727,3771,3822,3869,3910,3952,4003,4064,4128,4191,4246,4290,4326,4358,4395,
-4439,4486,4521,4534,4540,4583,4689,4840,4981,5075,5128,5162,5190,5217,5254,5311,5383,5455,5520,5578,5621,
-5637,5632,5626,5640,5675,5732,5814,5911,5986,6007,5983,5956,5954,5972,5988,5999,6018,6050,6079,6090,6088,
-6089,6105,6127,6139,6145,6161,6192,6224,6248,6277,6333,6415,6503,6587,6671,6758,6831,6874,6884,6858,6783,
-6669,6567,6531,6566,6624,6664,6688,6713,6735,6732,6705,6677,6668,6672,6672,6659,6635,6604,6569,6537,6511,
-6492,6477,6468,6467,6474,6484,6493,6500,6508,6521,6534,6535,6519,6495,6479,6471,6460,6444,6440,6455,6473,
-6478,6484,6526,6613,6714,6791,6833,6854,6857,6842,6815,6791,6773,6748,6707,6657,6599,6517,6410,6323,6323,
-6432,6584,6674,6650,6547,6446,6392,6368,6335,6283,6232,6197,6170,6142,6119,6108,6087,6027,5932,5850,5788,
-5665,5382,4978,4648,4589,4824,5196,5537,5785,5959,6072,6121,6123,6119,6126,6127,6107,6077,6056,6040,6018,
-5988,5952,5911,5865,5823,5794,5775,5748,5698,5621,5521,5417,5334,5280,5239,5189,5138,5113,5114,5116,5091,
-5043,4992,4949,4912,4874,4827,4768,4711,4674,4654,4625,4569,4490,4404,4312,4221,4166,4185,4264,4338,4344,
-4276,4173,4077,4009,3959,3907,3840,3773,3729,3700,3655,3587,3525,3488,3450,3373,3276,3221,3232,3260,3242,
-3157,3033,2904,2791,2716,2685,2681,2672,2645,2605,2562,2516,2466,2424,2397,2373,2332,2267,2191,2122,2061,
-2002,1943,1893,1851,1810,1760,1714,1689,1685,1671,1618,1538,1467,1433,1429,1437,1445,1450,1446,1427,1395,
-1369,1366,1387,1419,1441,1441,1419,1386,1349,1306,1248,1175,1103,1046,1013,994,978,957,931,902,873,
-843,815,794,776,758,736,713,694,678,662,644,624,602,575,544,511,483,465,456,448,432,
-409,384,358,327,287,252,234,234,239,238,229,219,206,186,158,125,97,80,66,44,13,
--12,-24,-29,-43,-73,-109,-144,-176,-202,-215,-223,-244,-287,-336,-372,-393,-412,-431,-443,-451,-463,
--482,-494,-493,-485,-477,-470,-463,-461,-470,-484,-490,-491,-495,-505,-517,-529,-544,-563,-582,-600,-621,
--645,-666,-681,-696,-716,-735,-750,-764,-779,-791,-797,-803,-818,-839,-855,-860,-861,-863,-865,-866,-869,
--876,-885,-890,-890,-889,-890,-893,-896,-900,-902,-905,-911,-921,-930,-931,-927,-925,-929,-934,-937,-937,
--938,-940,-941,-943,-943,-941,-934,-927,-923,-921,-917,-911,-910,-915,-919,-917,-911,-904,-898,-890,-882,
--873,-869,-868,-869,-869,-864,-855,-846,-839,-834,-826,-817,-811,-805,-798,-788,-779,-770,-755,-736,-718,
--705,-693,-679,-665,-654,-643,-631,-617,-608,-603,-597,-591,-585,-580,-573,-565,-560,-557,-554,-549,-545,
--543,-542,-540,-540,-544,-550,-554,-559,-564,-570,-573,-575,-579,-585,-594,-604,-617,-631,-641,-650,-660,
--674,-692,-711,-732,-756,-781,-803,-821,-839,-857,-876,-890,-899,-905,-911,-919,-924,-926,-928,-935,-943,
--948,-948,-947,-952,-959,-964,-963,-961,-962,-965,-969,-970,-970,-969,-965,-961,-958,-956,-952,-945,-939,
--936,-936,-933,-926,-919,-915,-912,-906,-898,-894,-890,-883,-872,-860,-850,-840,-829,-821,-812,-801,-788,
--776,-762,-740,-711,-685,-668,-654,-635,-614,-594,-575,-553,-528,-507,-488,-463,-433,-406,-385,-366,-341,
--313,-286,-261,-234,-201,-163,-122,-82,-42,3,58,120,180,241,303,360,396,416,433,446,434,
-385,322,285,301,394,590,888,1241,1587,1916,2252,2587,2871,3080,3242,3372,3432,3387,3287,3217,3193,
-3164,3115,3097,3143,3211,3251,3281,3332,3368,3316,3176,3024,2915,2826,2733,2667,2672,2729,2779,2802,2828,
-2878,2927,2953,2977,3026,3088,3122,3113,3090,3074,3037,2937,2771,2600,2481,2419,2373,2312,2246,2195,2158,
-2115,2062,2011,1966,1920,1875,1851,1852,1848,1797,1697,1585,1493,1409,1302,1157,1004,902,902,999,1121,
-1169,1101,956,804,668,521,350,179,28,-121,-288,-440,-532,-576,-637,-745,-856,-915,-930,-946,-966,
--957,-916,-888,-910,-967,-1022,-1068,-1127,-1215,-1325,-1434,-1513,-1538,-1506,-1449,-1397,-1355,-1319,-1309,-1356,-1450,
--1545,-1609,-1654,-1696,-1712,-1674,-1601,-1540,-1512,-1501,-1490,-1484,-1491,-1501,-1505,-1512,-1531,-1556,-1578,-1596,-1603,
--1571,-1482,-1366,-1283,-1257,-1260,-1254,-1236,-1225,-1226,-1219,-1190,-1149,-1120,-1123,-1154,-1182,-1172,-1120,-1072,-1079,
--1141,-1202,-1220,-1209,-1210,-1229,-1243,-1234,-1216,-1205,-1195,-1168,-1123,-1075,-1037,-1009,-984,-956,-923,-885,-847,
--822,-817,-832,-857,-881,-894,-893,-888,-887,-889,-887,-877,-867,-860,-852,-839,-822,-807,-796,-786,-778,
--772,-767,-759,-747,-729,-704,-673,-643,-618,-593,-565,-533,-499,-468,-434,-398,-363,-331,-300,-266,-227,
--187,-148,-108,-63,-14,36,84,128,169,211,251,289,324,359,397,436,473,509,543,579,614,
-648,681,715,748,783,821,862,899,928,947,958,964,967,970,977,989,1003,1013,1014,1008,1004,
-1005,1011,1017,1023,1030,1041,1051,1059,1072,1092,1116,1137,1155,1171,1187,1202,1212,1219,1220,1213,1204,
-1207,1232,1270,1296,1297,1284,1279,1284,1282,1263,1240,1234,1243,1246,1231,1210,1196,1186,1170,1147,1128,
-1123,1130,1138,1141,1162,1154,1145,1138,1137,1138,1139,1140,1145,1150,1152,1153,1155,1161,1168,1176,1183,
-1190,1193,1196,1205,1216,1227,1235,1247,1266,1285,1303,1321,1342,1364,1384,1404,1428,1451,1472,1495,1522,
-1547,1566,1586,1612,1639,1655,1667,1691,1730,1767,1793,1829,1899,1997,2089,2142,2149,2125,2099,2097,2127,
-2178,2222,2240,2234,2221,2215,2207,2168,2080,1953,1820,1705,1607,1515,1430,1363,1310,1255,1197,1143,1095,
-1044,987,922,846,752,653,577,535,507,467,414,360,307,254,204,165,133,95,51,15,-13,
--42,-72,-93,-106,-128,-171,-221,-266,-315,-378,-450,-507,-542,-562,-580,-604,-632,-661,-685,-713,-767,
--853,-947,-1032,-1133,-1275,-1430,-1517,-1493,-1405,-1328,-1289,-1280,-1318,-1442,-1647,-1855,-1982,-1996,-1927,-1829,-1760,
--1769,-1866,-2000,-2105,-2161,-2199,-2244,-2288,-2314,-2323,-2329,-2329,-2316,-2292,-2268,-2244,-2223,-2224,-2279,-2389,-2510,
--2593,-2635,-2662,-2697,-2739,-2787,-2833,-2847,-2785,-2635,-2461,-2364,-2382,-2442,-2432,-2330,-2245,-2301,-2487,-2655,-2683,
--2614,-2600,-2691,-2760,-2649,-2378,-2127,-2036,-2067,-2087,-2041,-1992,-2014,-2110,-2230,-2350,-2469,-2580,-2661,-2703,-2720,
--2733,-2747,-2759,-2770,-2789,-2816,-2846,-2872,-2893,-2911,-2921,-2917,-2900,-2882,-2876,-2885,-2901,-2915,-2927,-2945,-2974,
--3008,-3044,-3078,-3112,-3142,-3170,-3198,-3236,-3283,-3333,-3383,-3438,-3496,-3535,-3523,-3453,-3359,-3304,-3324,-3408,-3512,
--3597,-3648,-3678,-3708,-3749,-3798,-3844,-3879,-3910,-3944,-3985,-4024,-4056,-4080,-4098,-4116,-4140,-4178,-4231,-4293,-4359,
--4429,-4501,-4570,-4633,-4692,-4751,-4806,-4854,-4900,-4954,-5019,-5084,-5141,-5190,-5245,-5313,-5393,-5478,-5560,-5636,-5708,
--5776,-5836,-5887,-5933,-5979,-6026,-6071,-6116,-6161,-6206,-6249,-6291,-6336,-6383,-6430,-6471,-6508,-6544,-6576,-6601,-6616,
--6622,-6623,-6624,-6627,-6629,-6628,-6627,-6626,-6621,-6613,-6610,-6620,-6638,-6656,-6670,-6684,-6695,-6694,-6678,-6659,-6641,
--6620,-6599,-6598,-6631,-6686,-6736,-6772,-6798,-6814,-6810,-6780,-6732,-6675,-6625,-6605,-6626,-6665,-6674,-6627,-6529,-6397,
--6246,-6111,-6054,-6103,-6211,-6286,-6278,-6205,-6113,-6033,-5976,-5949,-5939,-5920,-5876,-5819,-5768,-5725,-5674,-5606,-5524,
--5436,-5345,-5245,-5126,-4987,-4838,-4703,-4595,-4509,-4431,-4354,-4273,-4185,-4105,-4064,-4062,-4049,-3982,-3880,-3808,-3786,
--3762,-3691,-3596,-3539,-3527,-3505,-3418,-3271,-3111,-2972,-2854,-2741,-2624,-2513,-2429,-2373,-2327,-2263,-2175,-2085,-2013,
--1957,-1895,-1817,-1733,-1664,-1619,-1586,-1542,-1478,-1399,-1314,-1224,-1134,-1050,-974,-894,-803,-707,-619,-532,-436,
--340,-272,-233,-192,-128,-51,20,102,208,312,364,370,392,466,550,579,557,549,596,674,737,
-785,846,932,1025,1107,1179,1247,1305,1345,1371,1398,1430,1467,1511,1575,1660,1753,1842,1932,2038,2157,
-2269,2354,2416,2470,2528,2590,2654,2725,2811,2920,3053,3195,3317,3398,3449,3500,3567,3638,3691,3722,3743,
-3762,3782,3804,3836,3883,3941,4006,4072,4139,4200,4251,4291,4327,4371,4424,4467,4481,4481,4516,4616,4760,
-4890,4978,5035,5087,5136,5178,5220,5272,5329,5384,5442,5508,5567,5595,5592,5584,5591,5615,5657,5725,5814,
-5887,5910,5889,5864,5865,5888,5914,5932,5949,5969,5989,6003,6009,6015,6029,6049,6067,6081,6096,6120,6146,
-6170,6203,6261,6343,6431,6515,6602,6691,6769,6821,6837,6804,6709,6574,6467,6445,6498,6561,6597,6620,6657,
-6693,6695,6658,6617,6600,6607,6619,6621,6607,6581,6551,6530,6517,6504,6487,6473,6468,6469,6468,6466,6466,
-6474,6489,6503,6508,6497,6470,6439,6411,6386,6368,6370,6400,6446,6494,6545,6619,6716,6809,6867,6883,6879,
-6867,6846,6814,6783,6756,6722,6675,6631,6605,6577,6506,6391,6306,6329,6454,6583,6621,6564,6483,6434,6409,
-6372,6314,6254,6210,6174,6140,6117,6114,6115,6084,6010,5922,5844,5735,5507,5145,4779,4613,4751,5108,5496,
-5785,5961,6067,6127,6150,6153,6153,6157,6154,6138,6117,6095,6072,6045,6010,5968,5923,5883,5853,5825,5795,
-5763,5724,5661,5565,5456,5366,5312,5282,5264,5257,5253,5233,5184,5120,5061,5016,4980,4947,4917,4883,4842,
-4793,4739,4678,4613,4553,4498,4428,4330,4226,4168,4185,4255,4319,4327,4263,4155,4051,3984,3947,3914,3874,
-3835,3793,3728,3640,3563,3522,3490,3422,3329,3271,3278,3303,3276,3177,3038,2901,2787,2712,2679,2674,2663,
-2631,2589,2555,2527,2492,2451,2417,2392,2361,2307,2231,2151,2083,2026,1974,1923,1875,1826,1773,1722,1691,
-1681,1667,1619,1539,1458,1408,1393,1398,1408,1415,1411,1392,1365,1347,1349,1369,1394,1410,1408,1388,1357,
-1319,1276,1222,1156,1088,1033,995,973,958,942,923,900,874,848,824,802,782,761,739,717,698,
-682,667,648,625,600,572,542,507,474,452,441,433,420,402,385,364,330,286,247,226,219,
-215,205,193,181,169,154,133,105,74,50,34,13,-17,-48,-63,-68,-81,-107,-139,-168,-195,
--222,-242,-255,-278,-321,-370,-405,-425,-440,-454,-460,-460,-464,-477,-486,-483,-473,-468,-468,-471,-477,
--492,-509,-522,-531,-541,-553,-562,-570,-582,-598,-614,-630,-653,-680,-703,-720,-736,-755,-772,-786,-800,
--813,-823,-826,-830,-843,-861,-874,-877,-876,-876,-876,-875,-877,-886,-896,-902,-903,-903,-904,-906,-907,
--909,-909,-909,-911,-918,-924,-926,-926,-927,-930,-933,-934,-936,-939,-941,-941,-942,-942,-938,-930,-922,
--918,-915,-908,-900,-898,-901,-901,-896,-889,-885,-880,-872,-862,-854,-850,-849,-849,-848,-843,-835,-826,
--818,-811,-804,-797,-791,-781,-767,-753,-744,-737,-724,-704,-686,-673,-663,-649,-635,-625,-616,-603,-589,
--579,-574,-569,-563,-557,-553,-548,-542,-535,-532,-529,-526,-522,-519,-517,-515,-516,-518,-522,-525,-530,
--538,-545,-549,-551,-555,-562,-572,-583,-596,-609,-620,-628,-637,-651,-667,-684,-703,-725,-750,-774,-794,
--812,-828,-844,-858,-870,-881,-891,-900,-905,-906,-908,-914,-924,-930,-931,-929,-928,-932,-937,-938,-936,
--936,-939,-941,-939,-936,-936,-939,-941,-942,-941,-936,-926,-915,-909,-909,-909,-904,-898,-894,-891,-883,
--873,-867,-863,-855,-844,-833,-824,-814,-802,-792,-786,-780,-768,-754,-739,-720,-695,-669,-649,-632,-614,
--594,-575,-557,-535,-509,-485,-465,-446,-424,-404,-385,-364,-340,-315,-292,-268,-241,-207,-167,-123,-82,
--46,-5,50,116,182,243,306,367,412,440,467,499,517,498,452,401,374,403,536,786,1106,
-1430,1743,2082,2455,2817,3120,3357,3514,3553,3477,3373,3331,3334,3298,3206,3146,3181,3269,3342,3403,3485,
-3558,3544,3424,3255,3093,2940,2801,2719,2727,2786,2827,2836,2854,2900,2951,2988,3031,3096,3161,3189,3178,
-3161,3145,3101,2992,2831,2671,2558,2492,2443,2389,2331,2277,2227,2175,2121,2066,2006,1937,1875,1851,1865,
-1877,1839,1750,1643,1551,1465,1359,1219,1072,970,966,1060,1181,1232,1171,1043,915,791,630,422,215,
-53,-73,-200,-323,-411,-476,-566,-695,-814,-876,-898,-922,-948,-939,-890,-849,-858,-908,-964,-1015,-1074,
--1151,-1243,-1338,-1412,-1433,-1396,-1335,-1291,-1268,-1252,-1257,-1318,-1435,-1559,-1646,-1697,-1727,-1728,-1678,-1593,-1517,
--1474,-1452,-1433,-1417,-1409,-1410,-1419,-1442,-1476,-1511,-1544,-1587,-1625,-1611,-1513,-1369,-1262,-1237,-1261,-1276,-1264,
--1245,-1236,-1228,-1208,-1178,-1153,-1144,-1148,-1151,-1138,-1111,-1096,-1116,-1159,-1194,-1205,-1206,-1219,-1239,-1245,-1231,
--1210,-1195,-1183,-1157,-1114,-1066,-1026,-995,-969,-940,-907,-873,-841,-814,-799,-804,-826,-852,-866,-865,-861,
--863,-868,-868,-862,-855,-851,-846,-835,-819,-803,-789,-778,-769,-764,-761,-756,-748,-734,-712,-682,-651,
--623,-597,-570,-539,-505,-472,-438,-405,-374,-343,-311,-274,-235,-198,-163,-126,-85,-38,10,57,100,
-141,184,226,266,303,341,380,418,454,488,523,560,597,634,670,703,736,774,819,867,907,
-934,948,953,954,954,958,966,977,988,996,998,995,991,992,999,1007,1015,1024,1036,1046,1054,
-1063,1081,1106,1131,1149,1164,1182,1201,1215,1222,1229,1245,1273,1309,1342,1360,1356,1336,1315,1306,1303,
-1290,1263,1244,1253,1282,1301,1288,1255,1222,1200,1183,1168,1160,1159,1163,1165,1162,1176,1173,1168,1164,
-1161,1157,1155,1158,1163,1167,1165,1164,1169,1179,1186,1189,1194,1201,1209,1216,1224,1235,1245,1255,1268,
-1285,1302,1318,1334,1353,1373,1391,1412,1435,1457,1477,1501,1529,1553,1569,1585,1608,1632,1648,1663,1693,
-1737,1778,1815,1873,1968,2079,2160,2181,2155,2115,2090,2096,2135,2189,2233,2250,2243,2226,2208,2183,2128,
-2033,1910,1789,1686,1600,1521,1451,1393,1339,1283,1228,1177,1128,1073,1014,953,878,776,662,575,534,
-513,481,431,378,328,281,238,203,170,129,85,57,46,33,9,-19,-47,-83,-137,-200,-257,
--311,-371,-436,-491,-520,-525,-519,-522,-543,-577,-611,-649,-712,-806,-914,-1025,-1159,-1324,-1467,-1510,-1443,
--1341,-1285,-1278,-1290,-1328,-1434,-1609,-1793,-1918,-1960,-1927,-1841,-1747,-1715,-1786,-1924,-2052,-2129,-2174,-2216,-2252,
--2266,-2261,-2254,-2250,-2241,-2227,-2210,-2188,-2166,-2175,-2250,-2379,-2503,-2581,-2623,-2664,-2712,-2748,-2772,-2804,-2832,
--2804,-2696,-2570,-2521,-2569,-2609,-2523,-2317,-2144,-2160,-2367,-2602,-2708,-2685,-2659,-2702,-2733,-2625,-2379,-2139,-2024,
--2014,-2002,-1944,-1891,-1903,-1977,-2079,-2197,-2333,-2470,-2574,-2628,-2650,-2663,-2677,-2693,-2710,-2730,-2754,-2781,-2812,
--2843,-2862,-2861,-2846,-2826,-2811,-2806,-2809,-2816,-2822,-2832,-2854,-2890,-2932,-2969,-3002,-3034,-3062,-3087,-3114,-3153,
--3201,-3251,-3305,-3371,-3442,-3480,-3445,-3347,-3251,-3226,-3282,-3377,-3459,-3510,-3544,-3577,-3618,-3663,-3709,-3751,-3789,
--3825,-3863,-3900,-3932,-3954,-3969,-3982,-4002,-4031,-4073,-4126,-4188,-4258,-4333,-4403,-4464,-4518,-4572,-4630,-4686,-4737,
--4790,-4852,-4920,-4986,-5044,-5098,-5155,-5221,-5297,-5378,-5459,-5535,-5605,-5670,-5729,-5781,-5829,-5876,-5924,-5970,-6014,
--6059,-6105,-6150,-6193,-6236,-6282,-6327,-6370,-6410,-6445,-6474,-6497,-6511,-6517,-6517,-6517,-6518,-6518,-6516,-6514,-6514,
--6513,-6511,-6513,-6525,-6546,-6568,-6588,-6604,-6615,-6612,-6598,-6578,-6555,-6532,-6521,-6539,-6589,-6646,-6687,-6714,-6735,
--6745,-6730,-6690,-6643,-6603,-6575,-6567,-6586,-6615,-6618,-6568,-6472,-6341,-6192,-6064,-6014,-6070,-6181,-6255,-6240,-6157,
--6059,-5986,-5949,-5943,-5943,-5916,-5851,-5771,-5711,-5677,-5648,-5595,-5515,-5424,-5340,-5258,-5153,-5009,-4845,-4702,-4596,
--4506,-4413,-4327,-4266,-4223,-4182,-4147,-4123,-4093,-4024,-3930,-3861,-3836,-3810,-3741,-3651,-3600,-3599,-3587,-3507,-3361,
--3197,-3052,-2928,-2809,-2689,-2577,-2487,-2424,-2373,-2313,-2237,-2161,-2106,-2072,-2034,-1968,-1881,-1799,-1741,-1698,-1646,
--1570,-1480,-1387,-1296,-1208,-1124,-1045,-963,-873,-783,-697,-606,-502,-405,-347,-330,-315,-273,-211,-149,-78,
-14,113,180,216,262,341,418,448,443,455,509,581,641,692,758,844,936,1019,1093,1158,1209,
-1248,1283,1321,1361,1399,1447,1516,1604,1696,1785,1880,1997,2125,2243,2336,2412,2484,2552,2611,2665,2728,
-2809,2910,3025,3142,3242,3315,3371,3433,3513,3597,3657,3684,3688,3689,3697,3715,3744,3783,3829,3884,3947,
-4020,4097,4167,4222,4267,4317,4377,4425,4436,4424,4443,4533,4668,4792,4875,4938,5006,5076,5132,5176,5216,
-5258,5304,5364,5443,5516,5553,5551,5539,5540,5556,5584,5636,5710,5774,5796,5781,5764,5771,5801,5835,5860,
-5877,5891,5907,5925,5938,5945,5950,5965,5989,6014,6036,6056,6076,6101,6141,6206,6288,6370,6445,6525,6612,
-6694,6755,6781,6754,6660,6526,6419,6396,6443,6499,6530,6554,6595,6637,6645,6611,6564,6533,6527,6538,6552,
-6554,6539,6516,6503,6502,6500,6490,6476,6468,6463,6455,6445,6443,6449,6457,6462,6461,6453,6438,6420,6408,
-6402,6402,6412,6442,6492,6552,6614,6683,6760,6828,6867,6875,6868,6858,6837,6801,6759,6720,6679,6628,6587,
-6581,6596,6568,6461,6332,6288,6373,6511,6591,6580,6527,6484,6452,6405,6344,6290,6254,6225,6195,6167,6153,
-6153,6147,6108,6032,5936,5817,5623,5304,4928,4687,4751,5098,5525,5834,5987,6062,6126,6176,6192,6186,6185,
-6192,6191,6173,6145,6117,6090,6059,6022,5982,5947,5916,5883,5846,5813,5783,5738,5665,5576,5502,5460,5436,
-5410,5378,5344,5305,5257,5206,5160,5119,5076,5034,4999,4967,4927,4872,4807,4739,4675,4625,4584,4526,4424,
-4283,4158,4111,4162,4262,4335,4328,4251,4158,4091,4043,3978,3887,3797,3733,3687,3639,3593,3558,3518,3447,
-3358,3298,3294,3305,3268,3165,3031,2911,2826,2778,2758,2746,2713,2651,2583,2540,2525,2516,2494,2461,2430,
-2398,2351,2279,2194,2117,2057,2008,1958,1905,1847,1789,1735,1696,1676,1656,1613,1542,1463,1405,1379,1375,
-1379,1378,1370,1356,1347,1349,1360,1369,1371,1370,1365,1353,1329,1292,1247,1195,1135,1072,1016,976,950,
-935,922,906,885,862,840,819,796,772,751,734,718,702,687,670,649,621,590,562,533,500,
-466,441,430,422,410,397,385,367,337,299,263,236,212,188,171,160,146,125,103,84,64,
-40,19,6,-8,-36,-69,-90,-97,-110,-139,-172,-200,-224,-251,-276,-295,-316,-350,-390,-417,-428,
--433,-440,-444,-443,-446,-458,-468,-470,-468,-471,-480,-491,-504,-522,-543,-560,-570,-578,-584,-590,-597,
--610,-627,-644,-663,-687,-713,-735,-752,-770,-789,-807,-819,-830,-843,-853,-858,-863,-874,-888,-895,-895,
--893,-892,-890,-887,-888,-895,-904,-910,-913,-914,-914,-913,-914,-916,-916,-915,-915,-917,-921,-924,-927,
--930,-933,-933,-932,-935,-939,-941,-941,-941,-940,-935,-925,-916,-912,-908,-900,-890,-886,-885,-880,-872,
--867,-865,-861,-851,-840,-833,-831,-829,-825,-821,-818,-814,-807,-799,-791,-784,-781,-776,-764,-746,-727,
--716,-710,-697,-677,-657,-643,-632,-619,-605,-595,-587,-576,-563,-553,-548,-544,-537,-531,-528,-525,-520,
--514,-509,-507,-504,-501,-497,-494,-492,-492,-494,-497,-500,-505,-511,-519,-524,-528,-533,-542,-551,-560,
--571,-583,-597,-608,-619,-632,-647,-661,-677,-696,-720,-746,-769,-786,-800,-813,-827,-841,-856,-868,-877,
--881,-882,-886,-893,-903,-911,-914,-911,-907,-907,-910,-911,-909,-908,-910,-912,-909,-904,-904,-910,-917,
--921,-922,-916,-904,-890,-883,-884,-886,-882,-876,-872,-869,-861,-849,-841,-835,-827,-815,-805,-798,-788,
--774,-763,-758,-754,-743,-726,-709,-693,-674,-652,-631,-613,-595,-575,-558,-541,-520,-495,-469,-448,-432,
--420,-409,-394,-372,-346,-322,-298,-272,-243,-212,-177,-135,-91,-50,-5,52,121,186,243,301,362,
-415,455,494,538,575,584,563,520,471,453,522,709,976,1262,1551,1878,2261,2665,3043,3363,3581,
-3648,3581,3490,3474,3500,3461,3338,3237,3248,3347,3458,3562,3682,3792,3826,3753,3605,3420,3212,3016,2895,
-2875,2911,2935,2936,2940,2953,2961,2973,3020,3103,3177,3200,3183,3163,3146,3102,3008,2880,2757,2662,2595,
-2543,2493,2438,2374,2300,2228,2165,2108,2043,1964,1896,1866,1873,1878,1846,1773,1685,1600,1511,1406,1277,
-1143,1047,1034,1114,1222,1268,1210,1094,979,859,685,446,204,22,-98,-199,-293,-369,-437,-529,-652,
--760,-821,-852,-887,-919,-913,-867,-824,-821,-851,-895,-948,-1015,-1090,-1166,-1243,-1307,-1330,-1300,-1245,-1209,
--1202,-1206,-1230,-1304,-1436,-1579,-1684,-1744,-1770,-1759,-1695,-1593,-1499,-1440,-1409,-1383,-1357,-1339,-1337,-1359,-1402,
--1449,-1483,-1513,-1560,-1615,-1621,-1535,-1386,-1256,-1206,-1221,-1247,-1250,-1231,-1206,-1185,-1172,-1166,-1161,-1153,-1140,
--1124,-1110,-1104,-1113,-1137,-1167,-1192,-1210,-1229,-1249,-1261,-1252,-1228,-1203,-1186,-1171,-1146,-1106,-1060,-1022,-992,
--964,-928,-890,-859,-837,-819,-804,-802,-815,-833,-841,-838,-835,-842,-852,-855,-852,-849,-846,-841,-830,
--815,-798,-781,-766,-757,-752,-748,-744,-737,-727,-710,-685,-657,-630,-604,-576,-545,-513,-479,-446,-415,
--389,-362,-330,-292,-251,-213,-177,-141,-101,-56,-9,36,77,118,160,204,247,287,328,370,410,
-446,480,515,552,590,627,662,695,730,772,822,871,909,931,941,942,941,941,946,954,963,
-971,978,983,984,984,988,997,1008,1017,1025,1035,1045,1053,1061,1077,1101,1126,1144,1159,1177,1199,
-1215,1225,1242,1283,1346,1410,1446,1441,1405,1361,1328,1317,1315,1306,1287,1277,1292,1322,1340,1325,1284,
-1243,1215,1201,1195,1191,1188,1184,1180,1176,1194,1194,1192,1186,1179,1174,1172,1175,1182,1185,1181,1178,
-1184,1194,1199,1200,1202,1212,1224,1233,1239,1248,1259,1271,1284,1298,1313,1329,1347,1366,1384,1401,1420,
-1441,1462,1482,1506,1532,1554,1570,1586,1609,1632,1648,1666,1700,1745,1786,1832,1910,2026,2140,2198,2184,
-2131,2085,2070,2090,2136,2189,2230,2244,2232,2202,2163,2112,2043,1951,1847,1748,1664,1592,1527,1469,1417,
-1363,1307,1253,1205,1155,1100,1042,983,902,786,658,564,525,513,490,446,397,351,308,271,243,
-215,175,136,117,117,113,89,54,16,-30,-95,-168,-233,-286,-341,-405,-464,-498,-499,-479,-467,
--482,-519,-561,-608,-679,-780,-895,-1017,-1158,-1315,-1427,-1433,-1346,-1256,-1227,-1239,-1250,-1274,-1366,-1537,-1724,
--1859,-1912,-1888,-1805,-1706,-1663,-1719,-1845,-1972,-2060,-2120,-2170,-2203,-2204,-2181,-2157,-2145,-2140,-2136,-2131,-2121,
--2119,-2159,-2260,-2395,-2498,-2544,-2567,-2610,-2670,-2709,-2725,-2745,-2775,-2775,-2720,-2656,-2655,-2714,-2732,-2616,-2393,
--2210,-2206,-2383,-2606,-2732,-2730,-2689,-2685,-2689,-2609,-2422,-2209,-2062,-1988,-1934,-1873,-1831,-1835,-1879,-1950,-2056,
--2201,-2358,-2481,-2550,-2578,-2591,-2602,-2620,-2644,-2671,-2695,-2720,-2751,-2783,-2798,-2787,-2763,-2745,-2738,-2737,-2737,
--2736,-2739,-2753,-2782,-2822,-2862,-2896,-2928,-2961,-2992,-3016,-3041,-3076,-3121,-3167,-3221,-3297,-3378,-3408,-3343,-3216,
--3121,-3128,-3219,-3319,-3378,-3403,-3430,-3475,-3530,-3579,-3620,-3657,-3695,-3736,-3774,-3806,-3830,-3845,-3858,-3877,-3904,
--3940,-3982,-4031,-4091,-4162,-4234,-4298,-4350,-4399,-4453,-4512,-4569,-4624,-4684,-4752,-4821,-4886,-4947,-5007,-5069,-5133,
--5204,-5281,-5360,-5435,-5503,-5566,-5623,-5675,-5725,-5775,-5824,-5871,-5915,-5960,-6005,-6049,-6091,-6132,-6174,-6219,-6264,
--6306,-6340,-6367,-6386,-6399,-6406,-6407,-6405,-6405,-6405,-6404,-6403,-6405,-6409,-6414,-6422,-6440,-6465,-6490,-6512,-6528,
--6535,-6532,-6519,-6499,-6477,-6458,-6458,-6491,-6549,-6603,-6636,-6655,-6670,-6675,-6652,-6609,-6569,-6545,-6533,-6531,-6542,
--6556,-6546,-6496,-6403,-6276,-6131,-6011,-5973,-6038,-6150,-6217,-6192,-6101,-6001,-5934,-5913,-5924,-5932,-5897,-5812,-5712,
--5644,-5619,-5607,-5568,-5490,-5397,-5325,-5275,-5204,-5076,-4908,-4755,-4638,-4530,-4408,-4301,-4248,-4242,-4237,-4210,-4174,
--4132,-4068,-3985,-3920,-3891,-3864,-3802,-3721,-3672,-3669,-3657,-3583,-3446,-3287,-3136,-2998,-2868,-2751,-2647,-2557,-2484,
--2427,-2379,-2329,-2275,-2230,-2202,-2176,-2122,-2033,-1930,-1845,-1786,-1731,-1657,-1561,-1459,-1363,-1279,-1202,-1127,-1044,
--952,-857,-761,-661,-559,-475,-437,-436,-437,-412,-366,-316,-258,-178,-86,-5,61,131,208,267,295,
-312,353,422,492,546,595,659,741,829,915,992,1053,1097,1132,1174,1225,1275,1322,1376,1451,1540,
-1629,1717,1819,1947,2086,2208,2302,2378,2447,2511,2565,2621,2696,2794,2902,3007,3101,3179,3243,3300,3367,
-3450,3534,3594,3620,3623,3624,3637,3663,3694,3724,3754,3791,3842,3911,3993,4074,4140,4196,4258,4332,4391,
-4401,4375,4373,4445,4572,4693,4775,4839,4914,4997,5066,5114,5151,5188,5234,5299,5383,5458,5493,5491,5480,
-5481,5492,5512,5551,5612,5669,5693,5687,5680,5694,5725,5758,5784,5801,5813,5828,5844,5855,5857,5858,5872,
-5904,5940,5971,5993,6015,6047,6098,6171,6250,6319,6378,6441,6520,6603,6673,6712,6703,6631,6513,6407,6365,
-6389,6433,6467,6496,6533,6567,6577,6559,6527,6493,6468,6460,6472,6486,6484,6470,6461,6464,6467,6460,6449,
-6443,6440,6434,6429,6433,6440,6441,6433,6422,6412,6404,6401,6409,6424,6439,6451,6474,6516,6575,6636,6695,
-6752,6801,6831,6838,6833,6823,6802,6765,6718,6673,6629,6578,6536,6531,6559,6563,6490,6373,6313,6363,6475,
-6551,6556,6523,6492,6464,6425,6380,6343,6317,6294,6265,6229,6195,6182,6193,6199,6158,6067,5946,5775,5490,
-5105,4798,4790,5118,5570,5897,6031,6079,6143,6215,6245,6234,6223,6232,6238,6223,6193,6163,6138,6112,6079,
-6044,6009,5978,5946,5910,5870,5828,5780,5725,5673,5636,5611,5578,5524,5458,5401,5359,5324,5289,5254,5215,
-5168,5117,5070,5029,4984,4930,4870,4809,4750,4698,4651,4590,4484,4330,4183,4115,4155,4261,4353,4376,4334,
-4269,4211,4140,4020,3858,3712,3642,3645,3668,3665,3628,3566,3490,3415,3370,3362,3356,3302,3188,3055,2956,
-2914,2916,2930,2922,2870,2773,2658,2568,2524,2517,2518,2503,2470,2428,2376,2307,2225,2146,2084,2038,1992,
-1934,1868,1803,1747,1704,1673,1646,1606,1545,1476,1418,1383,1369,1361,1350,1336,1331,1345,1371,1387,1377,
-1350,1328,1321,1317,1300,1265,1220,1169,1112,1052,995,952,926,910,898,881,859,837,819,800,777,
-751,731,719,709,696,682,667,646,615,581,551,525,496,464,439,424,412,400,388,378,361,
-335,308,284,254,211,168,145,137,120,84,47,27,20,10,0,-5,-17,-48,-91,-120,-129,
--140,-170,-207,-234,-252,-273,-296,-313,-327,-349,-378,-398,-402,-403,-410,-422,-434,-447,-463,-478,-487,
--494,-502,-513,-522,-534,-552,-573,-589,-595,-596,-598,-604,-616,-635,-657,-678,-698,-720,-741,-758,-774,
--794,-816,-834,-845,-855,-867,-878,-887,-896,-906,-915,-917,-915,-912,-910,-906,-902,-901,-905,-911,-917,
--921,-924,-923,-919,-919,-921,-923,-923,-922,-923,-925,-927,-930,-934,-934,-931,-928,-931,-934,-936,-935,
--936,-937,-931,-920,-910,-906,-902,-893,-883,-877,-872,-864,-855,-851,-850,-845,-832,-819,-814,-812,-806,
--797,-791,-789,-788,-784,-775,-766,-759,-757,-754,-745,-727,-708,-695,-686,-673,-652,-631,-615,-603,-590,
--576,-566,-558,-548,-536,-528,-523,-518,-512,-506,-503,-502,-498,-493,-488,-484,-480,-477,-474,-472,-471,
--471,-473,-476,-479,-482,-488,-494,-499,-504,-511,-521,-529,-534,-541,-556,-575,-591,-603,-613,-626,-640,
--653,-669,-690,-716,-739,-757,-771,-785,-800,-817,-833,-845,-852,-854,-855,-860,-868,-878,-886,-890,-889,
--885,-883,-885,-884,-879,-875,-877,-880,-879,-874,-872,-877,-886,-892,-894,-890,-880,-866,-859,-861,-864,
--860,-853,-849,-846,-839,-827,-817,-811,-802,-789,-777,-771,-763,-749,-735,-728,-724,-713,-695,-677,-663,
--649,-631,-612,-595,-579,-561,-542,-524,-506,-486,-465,-444,-428,-419,-413,-401,-378,-352,-327,-303,-272,
--238,-209,-181,-146,-102,-55,-3,57,125,189,242,295,355,415,468,518,570,615,642,646,625,
-579,535,549,664,868,1113,1380,1684,2036,2417,2811,3196,3510,3666,3652,3576,3550,3569,3538,3433,3342,
-3360,3480,3639,3799,3957,4087,4148,4128,4038,3882,3663,3423,3238,3142,3104,3083,3068,3054,3017,2952,2908,
-2946,3054,3153,3181,3152,3112,3080,3041,2984,2919,2854,2792,2733,2683,2639,2583,2498,2389,2283,2198,2130,
-2060,1982,1916,1880,1869,1855,1820,1766,1704,1633,1550,1451,1339,1223,1131,1103,1151,1229,1258,1204,1106,
-1009,897,720,469,206,2,-134,-233,-314,-375,-428,-498,-590,-679,-746,-801,-857,-894,-888,-846,-808,
--797,-807,-834,-887,-966,-1047,-1112,-1166,-1214,-1236,-1215,-1171,-1144,-1150,-1174,-1216,-1302,-1437,-1585,-1703,-1777,
--1810,-1795,-1718,-1597,-1480,-1403,-1362,-1333,-1303,-1281,-1283,-1317,-1373,-1426,-1458,-1479,-1516,-1567,-1585,-1527,-1403,
--1270,-1188,-1170,-1187,-1199,-1180,-1135,-1094,-1085,-1105,-1128,-1130,-1112,-1092,-1085,-1092,-1110,-1135,-1165,-1197,-1231,
--1263,-1281,-1277,-1252,-1222,-1197,-1180,-1160,-1130,-1091,-1050,-1018,-993,-963,-921,-877,-847,-835,-826,-815,-808,
--813,-821,-822,-815,-814,-824,-836,-842,-842,-841,-839,-833,-822,-809,-792,-773,-756,-747,-741,-734,-725,
--716,-707,-695,-678,-659,-637,-611,-582,-552,-523,-491,-458,-428,-404,-381,-351,-313,-273,-232,-193,-153,
--111,-67,-20,24,65,105,147,191,235,277,320,363,403,439,473,509,545,581,616,649,683,
-722,768,820,866,899,918,927,931,931,932,937,945,953,961,969,975,979,982,989,1002,1016,
-1025,1031,1039,1050,1059,1067,1079,1100,1125,1146,1163,1183,1204,1221,1230,1248,1293,1361,1426,1453,1433,
-1385,1337,1310,1308,1320,1328,1326,1321,1323,1332,1333,1314,1279,1246,1226,1218,1215,1211,1204,1197,1193,
-1194,1214,1212,1205,1197,1191,1189,1189,1194,1200,1203,1200,1197,1200,1208,1212,1212,1216,1227,1238,1245,
-1249,1256,1269,1283,1296,1309,1323,1340,1359,1379,1396,1411,1427,1446,1465,1485,1507,1531,1552,1570,1589,
-1613,1635,1652,1676,1713,1755,1793,1845,1937,2063,2168,2200,2158,2094,2059,2066,2103,2149,2193,2226,2237,
-2221,2176,2110,2033,1953,1872,1795,1724,1659,1598,1541,1488,1436,1383,1328,1275,1227,1177,1124,1073,1013,
-922,790,650,553,518,511,496,463,424,385,346,313,288,260,220,183,169,173,171,146,108,
-67,16,-52,-128,-192,-242,-293,-354,-416,-458,-468,-458,-451,-464,-495,-537,-596,-687,-806,-928,-1044,
--1166,-1289,-1360,-1334,-1241,-1165,-1152,-1167,-1168,-1178,-1265,-1443,-1649,-1796,-1844,-1806,-1725,-1654,-1643,-1704,-1804,
--1897,-1971,-2039,-2105,-2143,-2136,-2096,-2056,-2039,-2043,-2055,-2064,-2071,-2097,-2172,-2295,-2419,-2485,-2485,-2474,-2504,
--2569,-2625,-2655,-2678,-2710,-2728,-2716,-2698,-2714,-2752,-2747,-2653,-2501,-2384,-2379,-2486,-2625,-2706,-2700,-2654,-2629,
--2623,-2573,-2433,-2237,-2055,-1927,-1844,-1791,-1765,-1762,-1777,-1822,-1919,-2073,-2245,-2382,-2461,-2497,-2513,-2525,-2544,
--2575,-2610,-2638,-2660,-2686,-2712,-2723,-2709,-2686,-2674,-2675,-2679,-2679,-2678,-2683,-2698,-2726,-2761,-2792,-2819,-2849,
--2886,-2919,-2943,-2965,-2998,-3041,-3086,-3145,-3228,-3307,-3315,-3215,-3063,-2973,-3007,-3123,-3231,-3284,-3304,-3334,-3388,
--3447,-3493,-3529,-3563,-3602,-3641,-3675,-3702,-3721,-3738,-3757,-3784,-3819,-3859,-3900,-3945,-4001,-4066,-4132,-4187,-4234,
--4284,-4344,-4406,-4465,-4524,-4589,-4659,-4726,-4787,-4849,-4913,-4978,-5043,-5112,-5188,-5267,-5341,-5406,-5465,-5521,-5573,
--5624,-5674,-5724,-5771,-5818,-5864,-5908,-5950,-5989,-6028,-6068,-6111,-6157,-6200,-6234,-6256,-6271,-6283,-6290,-6293,-6292,
--6292,-6294,-6296,-6299,-6305,-6315,-6326,-6341,-6363,-6391,-6418,-6438,-6449,-6453,-6449,-6437,-6420,-6402,-6390,-6400,-6441,
--6502,-6556,-6587,-6603,-6614,-6614,-6591,-6554,-6522,-6505,-6497,-6491,-6489,-6485,-6464,-6414,-6328,-6207,-6069,-5961,-5941,
--6016,-6123,-6178,-6144,-6051,-5957,-5900,-5892,-5914,-5922,-5876,-5774,-5661,-5589,-5571,-5571,-5540,-5460,-5365,-5306,-5289,
--5260,-5161,-4999,-4835,-4702,-4574,-4430,-4305,-4252,-4263,-4274,-4250,-4206,-4161,-4106,-4036,-3975,-3944,-3919,-3865,-3792,
--3740,-3722,-3701,-3632,-3515,-3372,-3221,-3070,-2931,-2818,-2727,-2641,-2561,-2504,-2477,-2461,-2429,-2381,-2340,-2309,-2265,
--2179,-2061,-1951,-1876,-1821,-1754,-1660,-1554,-1459,-1381,-1314,-1244,-1160,-1057,-941,-822,-711,-623,-573,-563,-573,
--574,-551,-512,-469,-418,-346,-256,-161,-69,19,93,140,170,211,279,356,415,454,493,550,623,
-704,787,865,927,969,1003,1047,1102,1157,1209,1267,1341,1426,1513,1605,1720,1863,2018,2153,2254,2327,
-2385,2433,2479,2539,2631,2752,2875,2977,3053,3112,3166,3226,3298,3382,3463,3522,3550,3559,3568,3590,3625,
-3659,3686,3707,3731,3771,3830,3903,3977,4040,4100,4177,4274,4356,4377,4340,4315,4364,4480,4598,4676,4731,
-4802,4893,4978,5039,5083,5123,5173,5240,5320,5386,5416,5414,5407,5410,5418,5432,5464,5519,5574,5603,5609,
-5616,5637,5668,5695,5716,5732,5745,5754,5760,5761,5758,5762,5784,5823,5865,5900,5927,5957,5998,6057,6131,
-6206,6265,6310,6361,6431,6512,6589,6645,6663,6624,6530,6423,6354,6343,6373,6415,6454,6483,6500,6508,6512,
-6510,6488,6449,6416,6409,6420,6425,6420,6416,6420,6423,6416,6408,6406,6407,6408,6412,6420,6430,6431,6423,
-6412,6402,6392,6389,6398,6415,6430,6439,6454,6490,6544,6603,6656,6706,6750,6782,6794,6790,6777,6753,6712,
-6659,6606,6561,6521,6491,6490,6515,6525,6481,6403,6361,6393,6462,6502,6497,6474,6458,6444,6425,6403,6380,
-6352,6319,6289,6258,6225,6209,6233,6278,6281,6217,6113,5968,5707,5303,4916,4812,5087,5550,5913,6072,6127,
-6196,6272,6301,6283,6268,6276,6284,6271,6244,6218,6195,6167,6135,6100,6064,6029,5999,5968,5930,5880,5825,
-5778,5746,5726,5700,5652,5582,5511,5461,5429,5399,5361,5319,5277,5232,5184,5136,5090,5043,4994,4947,4897,
-4842,4785,4727,4656,4546,4404,4280,4233,4278,4364,4426,4433,4397,4348,4294,4214,4078,3899,3744,3683,3715,
-3767,3763,3693,3599,3529,3494,3483,3479,3451,3370,3235,3092,3007,3009,3069,3129,3146,3105,3007,2863,2704,
-2580,2522,2517,2521,2500,2451,2389,2319,2239,2159,2096,2052,2009,1952,1881,1812,1755,1710,1674,1640,1600,
-1549,1490,1437,1399,1375,1357,1335,1316,1316,1344,1381,1394,1368,1321,1287,1278,1277,1260,1225,1184,1139,
-1087,1030,975,932,904,888,874,856,833,811,793,775,752,728,711,701,691,678,667,659,645,
-616,580,548,524,499,472,446,424,404,388,377,369,352,329,311,299,271,216,161,137,138,
-124,78,28,5,3,0,-9,-16,-30,-69,-124,-163,-174,-178,-202,-236,-259,-270,-282,-297,-308,
--314,-328,-352,-370,-376,-379,-394,-423,-454,-480,-500,-516,-528,-537,-546,-551,-556,-564,-581,-603,-618,
--621,-617,-616,-624,-641,-663,-685,-705,-726,-746,-764,-778,-794,-814,-836,-853,-865,-876,-888,-899,-910,
--921,-931,-936,-936,-934,-933,-930,-924,-919,-917,-918,-919,-923,-929,-933,-931,-926,-924,-927,-930,-931,
--931,-931,-931,-930,-932,-935,-935,-930,-926,-926,-928,-927,-925,-927,-929,-924,-913,-903,-899,-896,-888,
--880,-873,-866,-856,-846,-841,-839,-831,-817,-804,-797,-794,-785,-773,-764,-761,-760,-755,-746,-736,-728,
--724,-722,-714,-701,-684,-671,-661,-646,-626,-605,-589,-576,-564,-551,-539,-528,-518,-509,-501,-496,-490,
--485,-481,-480,-478,-474,-470,-465,-461,-457,-454,-453,-453,-453,-454,-455,-458,-460,-463,-468,-474,-479,
--483,-490,-500,-507,-511,-516,-531,-552,-571,-581,-590,-602,-617,-630,-643,-661,-684,-706,-723,-738,-756,
--776,-796,-814,-826,-830,-829,-828,-833,-842,-851,-858,-863,-864,-862,-861,-860,-857,-849,-843,-843,-848,
--849,-844,-842,-846,-853,-857,-861,-861,-857,-847,-840,-841,-843,-840,-831,-826,-824,-817,-806,-797,-791,
--782,-767,-753,-745,-738,-725,-710,-700,-693,-681,-665,-650,-638,-625,-608,-590,-576,-563,-547,-528,-508,
--491,-479,-466,-450,-433,-422,-415,-402,-379,-353,-331,-307,-274,-235,-201,-174,-142,-99,-49,3,61,
-125,186,238,291,352,418,481,542,599,649,686,709,712,686,639,615,663,798,1003,1257,1548,
-1858,2178,2533,2944,3349,3622,3691,3623,3548,3523,3508,3473,3457,3516,3658,3847,4047,4223,4344,4404,4426,
-4422,4359,4207,3985,3754,3554,3389,3267,3198,3151,3067,2940,2849,2877,3001,3120,3155,3113,3048,2994,2959,
-2944,2944,2938,2908,2861,2817,2780,2721,2617,2478,2342,2235,2151,2072,1991,1926,1886,1861,1831,1793,1752,
-1710,1654,1580,1493,1401,1305,1217,1167,1170,1195,1194,1148,1083,1018,924,752,505,240,22,-134,-246,
--327,-380,-418,-463,-525,-597,-675,-757,-832,-870,-859,-822,-795,-787,-789,-807,-861,-947,-1029,-1082,-1113,
--1140,-1156,-1144,-1112,-1094,-1108,-1144,-1200,-1291,-1421,-1565,-1688,-1774,-1818,-1806,-1725,-1593,-1461,-1370,-1321,-1290,
--1262,-1240,-1242,-1276,-1330,-1381,-1414,-1435,-1461,-1492,-1508,-1481,-1405,-1299,-1202,-1149,-1144,-1154,-1133,-1073,-1016,
--1007,-1040,-1075,-1080,-1067,-1060,-1069,-1085,-1102,-1126,-1161,-1205,-1251,-1285,-1294,-1277,-1246,-1219,-1199,-1180,-1153,
--1116,-1076,-1041,-1014,-991,-958,-913,-869,-844,-837,-833,-821,-810,-807,-808,-804,-798,-797,-805,-812,-814,
--815,-817,-817,-810,-801,-791,-778,-761,-746,-738,-731,-720,-706,-693,-684,-676,-667,-655,-638,-613,-584,
--557,-532,-503,-471,-440,-414,-389,-360,-324,-285,-244,-201,-159,-116,-72,-25,20,61,100,141,185,
-229,271,313,354,393,427,461,496,532,567,599,631,667,710,759,809,850,878,897,911,921,
-924,926,930,937,945,953,963,973,980,986,995,1010,1024,1033,1038,1047,1059,1069,1076,1084,1102,
-1127,1153,1176,1198,1220,1235,1242,1253,1282,1329,1370,1382,1360,1324,1298,1291,1304,1326,1347,1355,1348,
-1331,1312,1294,1277,1259,1246,1237,1234,1232,1227,1219,1213,1212,1214,1232,1225,1215,1208,1208,1211,1212,
-1213,1216,1219,1219,1217,1217,1221,1226,1231,1237,1245,1252,1255,1259,1267,1280,1295,1309,1323,1337,1354,
-1373,1392,1408,1421,1434,1450,1467,1485,1505,1524,1544,1564,1587,1612,1634,1657,1688,1729,1768,1804,1859,
-1957,2080,2169,2178,2123,2065,2054,2090,2143,2185,2211,2228,2235,2218,2164,2079,1982,1898,1830,1775,1722,
-1669,1614,1559,1506,1454,1402,1349,1298,1248,1197,1149,1105,1047,949,809,665,569,531,522,509,487,
-463,434,401,369,341,306,260,220,206,209,203,174,135,96,49,-13,-81,-138,-184,-234,-294,
--352,-396,-423,-439,-453,-468,-490,-531,-613,-740,-887,-1014,-1111,-1194,-1269,-1298,-1254,-1166,-1104,-1096,-1107,
--1098,-1096,-1167,-1337,-1550,-1709,-1758,-1712,-1640,-1611,-1651,-1729,-1801,-1850,-1897,-1964,-2041,-2088,-2081,-2033,-1985,
--1969,-1989,-2019,-2040,-2059,-2104,-2198,-2322,-2424,-2458,-2429,-2391,-2396,-2449,-2516,-2570,-2608,-2641,-2666,-2680,-2691,
--2708,-2718,-2701,-2654,-2598,-2561,-2558,-2584,-2620,-2638,-2621,-2585,-2562,-2553,-2507,-2379,-2182,-1980,-1828,-1739,-1698,
--1683,-1677,-1675,-1702,-1794,-1953,-2133,-2278,-2365,-2411,-2437,-2455,-2476,-2507,-2543,-2572,-2591,-2609,-2630,-2643,-2638,
--2624,-2617,-2622,-2631,-2636,-2639,-2644,-2654,-2671,-2692,-2713,-2733,-2761,-2797,-2831,-2857,-2882,-2917,-2963,-3015,-3084,
--3171,-3233,-3203,-3066,-2902,-2825,-2881,-3010,-3124,-3186,-3221,-3262,-3315,-3365,-3404,-3439,-3476,-3515,-3550,-3577,-3599,
--3620,-3643,-3670,-3702,-3738,-3776,-3815,-3856,-3906,-3965,-4025,-4077,-4125,-4181,-4245,-4311,-4374,-4437,-4505,-4572,-4633,
--4689,-4747,-4811,-4878,-4945,-5018,-5096,-5175,-5248,-5312,-5370,-5424,-5475,-5524,-5573,-5621,-5668,-5718,-5766,-5809,-5848,
--5887,-5926,-5967,-6007,-6049,-6090,-6122,-6142,-6155,-6165,-6173,-6178,-6180,-6183,-6188,-6193,-6201,-6213,-6230,-6246,-6263,
--6286,-6315,-6341,-6358,-6366,-6369,-6366,-6355,-6340,-6327,-6325,-6344,-6388,-6448,-6504,-6542,-6560,-6566,-6559,-6538,-6509,
--6485,-6467,-6449,-6429,-6409,-6390,-6363,-6318,-6242,-6131,-6005,-5919,-5922,-6006,-6103,-6140,-6097,-6010,-5926,-5881,-5884,
--5913,-5920,-5864,-5752,-5636,-5567,-5552,-5553,-5520,-5437,-5339,-5287,-5293,-5297,-5226,-5076,-4908,-4766,-4634,-4492,-4370,
--4316,-4316,-4310,-4266,-4208,-4166,-4129,-4078,-4029,-4000,-3979,-3931,-3859,-3797,-3762,-3728,-3665,-3569,-3449,-3306,-3148,
--3004,-2896,-2815,-2737,-2657,-2605,-2597,-2605,-2585,-2529,-2468,-2428,-2389,-2314,-2197,-2077,-1991,-1932,-1865,-1773,-1670,
--1582,-1513,-1453,-1387,-1304,-1193,-1052,-902,-777,-707,-693,-711,-725,-715,-682,-642,-600,-549,-479,-391,-292,
--188,-89,-10,42,85,145,223,292,330,352,384,439,508,582,657,732,796,844,883,928,981,
-1036,1090,1150,1220,1301,1388,1487,1609,1760,1923,2070,2181,2255,2303,2337,2376,2441,2549,2687,2820,2920,
-2983,3029,3077,3140,3218,3307,3389,3448,3479,3494,3511,3540,3577,3615,3646,3670,3696,3732,3784,3844,3900,
-3946,3997,4079,4197,4306,4345,4307,4263,4290,4393,4507,4578,4621,4681,4775,4875,4953,5005,5049,5100,5166,
-5240,5300,5330,5332,5329,5331,5335,5345,5374,5425,5479,5513,5531,5552,5586,5619,5642,5656,5669,5679,5681,
-5675,5666,5664,5678,5710,5753,5793,5826,5857,5894,5940,6000,6071,6144,6204,6252,6300,6361,6436,6514,6587,
-6635,6635,6574,6476,6385,6341,6347,6385,6426,6449,6452,6456,6477,6502,6500,6461,6411,6378,6368,6364,6358,
-6357,6362,6364,6360,6356,6359,6366,6371,6376,6384,6392,6397,6399,6399,6396,6388,6380,6381,6389,6395,6400,
-6414,6446,6493,6542,6588,6634,6684,6726,6749,6748,6730,6699,6651,6587,6525,6481,6464,6469,6487,6505,6501,
-6464,6418,6403,6430,6463,6468,6453,6440,6436,6431,6425,6421,6408,6370,6321,6290,6278,6262,6249,6272,6324,
-6349,6312,6240,6135,5905,5483,5013,4791,4981,5433,5852,6087,6199,6283,6345,6350,6319,6306,6320,6327,6314,
-6293,6276,6253,6219,6184,6154,6121,6082,6046,6017,5984,5939,5886,5840,5807,5777,5737,5679,5615,5563,5531,
-5508,5472,5421,5366,5320,5282,5243,5199,5153,5108,5066,5028,4987,4937,4881,4824,4753,4653,4536,4449,4434,
-4477,4524,4533,4503,4457,4409,4356,4287,4186,4058,3943,3890,3900,3908,3844,3711,3584,3529,3538,3560,3554,
-3503,3398,3249,3104,3036,3074,3177,3270,3314,3309,3256,3132,2938,2733,2598,2560,2572,2569,2527,2458,2377,
-2282,2183,2102,2049,2007,1953,1884,1814,1757,1713,1675,1637,1597,1553,1505,1458,1421,1393,1367,1337,1309,
-1303,1327,1360,1366,1332,1283,1251,1243,1234,1207,1169,1134,1102,1061,1011,961,922,894,873,856,837,
-814,791,772,754,734,715,701,689,674,657,648,649,645,622,586,553,528,506,482,458,432,
-405,383,373,368,352,329,315,310,284,225,168,153,172,172,131,79,50,36,12,-20,-42,
--60,-98,-155,-199,-209,-208,-221,-248,-267,-275,-284,-296,-304,-307,-317,-339,-360,-370,-380,-406,-447,
--490,-521,-540,-552,-561,-567,-571,-573,-576,-587,-607,-631,-649,-654,-650,-648,-655,-671,-690,-706,-722,
--742,-765,-786,-803,-818,-835,-852,-866,-879,-892,-904,-914,-924,-936,-947,-951,-951,-951,-951,-948,-942,
--936,-935,-934,-932,-932,-936,-940,-938,-933,-931,-934,-936,-938,-938,-938,-935,-931,-931,-934,-934,-931,
--927,-927,-926,-922,-918,-918,-919,-914,-904,-895,-890,-886,-882,-877,-872,-864,-852,-841,-834,-828,-819,
--806,-794,-786,-779,-769,-757,-748,-742,-736,-729,-719,-708,-698,-690,-684,-676,-666,-653,-641,-629,-615,
--598,-580,-564,-551,-539,-527,-514,-501,-491,-482,-475,-468,-462,-457,-456,-455,-453,-448,-444,-441,-437,
--434,-432,-433,-435,-437,-438,-440,-442,-443,-446,-451,-458,-462,-465,-471,-481,-490,-494,-498,-510,-528,
--544,-554,-562,-576,-592,-607,-620,-637,-658,-676,-692,-707,-728,-753,-776,-795,-806,-809,-805,-803,-807,
--816,-824,-830,-834,-837,-836,-834,-832,-828,-822,-816,-816,-819,-820,-817,-816,-820,-825,-827,-829,-834,
--836,-830,-823,-821,-822,-819,-812,-806,-802,-795,-785,-778,-774,-766,-750,-733,-722,-714,-703,-690,-677,
--665,-652,-638,-627,-618,-606,-589,-571,-557,-547,-534,-516,-496,-480,-471,-465,-454,-439,-426,-416,-402,
--379,-353,-332,-312,-280,-238,-198,-164,-129,-83,-33,16,67,122,178,231,286,349,419,488,556,
-621,677,721,754,776,776,746,709,703,766,918,1156,1447,1741,2018,2326,2726,3184,3558,3720,3680,
-3561,3479,3470,3512,3582,3679,3812,3987,4185,4356,4458,4505,4558,4639,4701,4677,4548,4334,4058,3758,3497,
-3326,3221,3107,2967,2872,2892,3000,3096,3115,3067,2996,2936,2907,2917,2954,2979,2967,2927,2887,2852,2790,
-2678,2529,2385,2272,2182,2093,2004,1933,1890,1861,1829,1791,1756,1718,1666,1596,1521,1449,1374,1295,1228,
-1185,1153,1116,1078,1052,1021,938,765,522,270,57,-104,-224,-309,-363,-401,-439,-486,-547,-626,-720,
--801,-836,-823,-796,-785,-791,-802,-824,-877,-956,-1024,-1057,-1066,-1076,-1087,-1083,-1064,-1055,-1071,-1111,-1173,
--1266,-1392,-1529,-1649,-1736,-1784,-1779,-1707,-1585,-1455,-1359,-1305,-1273,-1246,-1226,-1223,-1245,-1283,-1325,-1361,-1388,
--1406,-1414,-1416,-1412,-1388,-1330,-1245,-1174,-1148,-1148,-1125,-1063,-1003,-990,-1013,-1028,-1019,-1011,-1030,-1064,-1090,
--1106,-1129,-1170,-1220,-1265,-1291,-1292,-1272,-1244,-1222,-1205,-1182,-1149,-1110,-1073,-1041,-1013,-984,-947,-904,-868,
--848,-842,-835,-820,-805,-796,-791,-785,-780,-781,-783,-780,-775,-774,-779,-779,-773,-767,-762,-754,-743,
--732,-727,-720,-707,-691,-678,-671,-664,-655,-646,-631,-609,-581,-555,-532,-506,-476,-444,-415,-386,-355,
--319,-282,-243,-200,-157,-116,-74,-29,15,56,95,135,178,222,262,302,341,379,413,446,480,
-515,550,583,615,653,697,745,790,824,851,874,894,908,914,917,921,927,935,944,956,970,
-983,992,1003,1017,1028,1034,1040,1052,1067,1078,1085,1092,1108,1134,1163,1190,1215,1236,1251,1258,1263,
-1277,1300,1317,1317,1303,1291,1292,1302,1317,1332,1348,1355,1346,1320,1289,1267,1257,1257,1258,1257,1254,
-1249,1244,1239,1235,1234,1232,1249,1241,1233,1231,1235,1239,1238,1233,1231,1233,1235,1234,1234,1237,1244,
-1252,1259,1263,1266,1269,1275,1284,1294,1306,1320,1336,1352,1369,1387,1405,1422,1434,1445,1458,1472,1487,
-1500,1513,1528,1548,1573,1601,1629,1662,1704,1748,1783,1817,1876,1975,2087,2156,2151,2096,2053,2065,2123,
-2189,2227,2236,2233,2230,2214,2161,2071,1970,1887,1828,1781,1733,1682,1630,1577,1524,1471,1420,1372,1322,
-1270,1218,1173,1134,1080,986,853,717,622,574,552,535,521,509,492,463,429,394,350,298,257,
-241,238,222,184,142,107,70,23,-27,-73,-121,-177,-238,-290,-332,-372,-416,-454,-475,-494,-543,
--653,-813,-977,-1095,-1160,-1200,-1230,-1234,-1197,-1138,-1101,-1101,-1107,-1088,-1063,-1091,-1213,-1403,-1576,-1655,-1632,
--1579,-1580,-1651,-1742,-1799,-1823,-1853,-1917,-1997,-2051,-2051,-2008,-1961,-1951,-1982,-2027,-2057,-2079,-2126,-2213,-2314,
--2390,-2417,-2400,-2363,-2340,-2354,-2405,-2472,-2527,-2561,-2584,-2610,-2643,-2669,-2675,-2664,-2654,-2656,-2660,-2649,-2623,
--2596,-2574,-2552,-2528,-2510,-2488,-2422,-2283,-2086,-1888,-1738,-1650,-1614,-1611,-1615,-1614,-1627,-1698,-1844,-2024,-2175,
--2271,-2328,-2367,-2397,-2420,-2445,-2474,-2500,-2515,-2529,-2548,-2566,-2572,-2569,-2565,-2569,-2578,-2588,-2595,-2599,-2601,
--2605,-2614,-2627,-2645,-2670,-2701,-2734,-2766,-2803,-2846,-2895,-2954,-3034,-3118,-3148,-3068,-2899,-2741,-2695,-2774,-2906,
--3017,-3090,-3142,-3192,-3239,-3279,-3315,-3355,-3397,-3435,-3465,-3486,-3505,-3529,-3559,-3590,-3619,-3648,-3680,-3715,-3753,
--3799,-3854,-3914,-3971,-4027,-4086,-4149,-4214,-4278,-4345,-4415,-4480,-4536,-4587,-4644,-4706,-4774,-4845,-4921,-5001,-5078,
--5150,-5216,-5275,-5328,-5376,-5423,-5469,-5514,-5561,-5611,-5660,-5702,-5740,-5779,-5821,-5863,-5900,-5936,-5972,-6002,-6022,
--6034,-6046,-6057,-6065,-6071,-6079,-6087,-6096,-6108,-6128,-6150,-6169,-6183,-6203,-6231,-6256,-6271,-6278,-6283,-6284,-6276,
--6265,-6259,-6267,-6292,-6335,-6392,-6451,-6495,-6515,-6512,-6492,-6466,-6442,-6421,-6395,-6361,-6321,-6285,-6258,-6237,-6205,
--6143,-6044,-5937,-5879,-5909,-6002,-6085,-6104,-6055,-5974,-5899,-5861,-5871,-5908,-5918,-5861,-5749,-5639,-5575,-5558,-5547,
--5503,-5416,-5320,-5271,-5284,-5302,-5249,-5111,-4948,-4811,-4697,-4585,-4489,-4434,-4401,-4344,-4259,-4185,-4152,-4138,-4113,
--4084,-4067,-4047,-3997,-3920,-3848,-3798,-3755,-3697,-3619,-3518,-3386,-3230,-3084,-2979,-2906,-2837,-2765,-2718,-2714,-2725,
--2707,-2648,-2582,-2540,-2506,-2441,-2335,-2219,-2127,-2053,-1971,-1874,-1779,-1702,-1639,-1577,-1512,-1437,-1333,-1184,-1013,
--875,-813,-822,-855,-866,-841,-797,-753,-711,-659,-589,-506,-414,-314,-212,-121,-47,16,84,152,198,
-218,233,271,335,409,479,545,611,674,730,778,826,877,934,993,1056,1126,1205,1295,1398,1520,
-1661,1814,1957,2071,2146,2190,2221,2264,2342,2466,2616,2753,2847,2902,2943,2992,3058,3139,3227,3309,3368,
-3404,3428,3453,3487,3526,3567,3606,3641,3676,3718,3769,3824,3866,3892,3922,3992,4110,4230,4284,4254,4206,
-4221,4314,4423,4489,4521,4569,4658,4763,4847,4903,4947,5000,5066,5139,5201,5235,5244,5243,5244,5248,5258,
-5286,5333,5383,5419,5447,5482,5527,5564,5582,5586,5589,5594,5593,5584,5575,5578,5601,5639,5682,5721,5755,
-5789,5829,5876,5933,6002,6078,6148,6206,6258,6312,6373,6444,6525,6599,6639,6623,6556,6471,6407,6381,6390,
-6411,6421,6418,6423,6451,6490,6504,6478,6428,6381,6346,6319,6297,6287,6285,6283,6282,6284,6292,6302,6310,
-6318,6325,6330,6336,6345,6356,6361,6360,6359,6361,6364,6364,6368,6383,6411,6445,6480,6517,6562,6614,6662,
-6690,6689,6664,6623,6571,6508,6448,6416,6427,6469,6507,6513,6484,6442,6419,6431,6459,6471,6459,6446,6445,
-6443,6428,6416,6421,6421,6386,6330,6297,6294,6287,6263,6256,6280,6299,6282,6255,6208,6028,5619,5100,4781,
-4875,5289,5748,6072,6263,6377,6418,6390,6345,6339,6360,6366,6348,6333,6326,6306,6266,6229,6208,6186,6148,
-6102,6063,6029,5991,5946,5903,5863,5821,5770,5714,5663,5623,5595,5567,5525,5470,5416,5373,5338,5300,5255,
-5207,5163,5127,5094,5057,5012,4964,4919,4865,4787,4698,4636,4627,4647,4648,4613,4564,4520,4477,4426,4372,
-4319,4259,4193,4142,4108,4049,3916,3728,3572,3518,3541,3568,3548,3478,3368,3227,3097,3045,3099,3211,3305,
-3352,3376,3381,3320,3158,2942,2776,2716,2728,2739,2709,2639,2535,2400,2254,2132,2053,2001,1946,1877,1808,
-1752,1709,1672,1635,1598,1560,1519,1479,1443,1413,1384,1347,1310,1290,1298,1318,1318,1288,1251,1230,1220,
-1197,1154,1112,1085,1066,1036,994,953,919,892,867,846,825,802,778,759,744,730,716,703,688,
-667,645,637,641,641,622,590,560,537,515,494,473,450,420,394,383,379,363,338,325,320,
-293,235,183,184,223,242,215,171,141,108,48,-22,-70,-90,-113,-155,-193,-207,-208,-218,-239,
--256,-268,-283,-300,-308,-311,-320,-341,-365,-383,-403,-434,-476,-513,-537,-551,-561,-567,-569,-569,-571,
--580,-598,-623,-650,-671,-682,-682,-681,-687,-699,-712,-723,-737,-758,-785,-810,-830,-844,-857,-869,-880,
--893,-906,-916,-923,-933,-946,-957,-961,-960,-961,-963,-960,-955,-951,-951,-950,-946,-943,-944,-945,-942,
--939,-939,-942,-943,-942,-942,-941,-936,-930,-928,-931,-934,-932,-931,-931,-929,-923,-917,-912,-909,-902,
--893,-885,-879,-875,-873,-871,-868,-860,-848,-835,-826,-817,-808,-798,-788,-779,-770,-761,-753,-744,-734,
--722,-712,-702,-690,-677,-664,-651,-641,-631,-620,-608,-594,-582,-569,-555,-540,-526,-513,-502,-490,-477,
--466,-458,-451,-443,-435,-431,-430,-430,-427,-422,-418,-415,-414,-412,-412,-414,-417,-419,-421,-423,-425,
--427,-430,-436,-443,-446,-447,-452,-462,-473,-480,-483,-490,-503,-516,-526,-537,-552,-569,-585,-600,-618,
--639,-656,-668,-683,-705,-730,-753,-770,-780,-782,-779,-777,-782,-790,-796,-800,-803,-806,-806,-802,-798,
--795,-792,-791,-792,-795,-794,-791,-793,-799,-803,-802,-802,-808,-813,-810,-801,-797,-798,-798,-792,-785,
--781,-775,-768,-762,-758,-750,-735,-718,-704,-694,-684,-671,-658,-643,-628,-616,-608,-601,-591,-575,-558,
--544,-532,-522,-510,-494,-478,-467,-460,-452,-439,-426,-415,-401,-379,-352,-330,-311,-282,-242,-200,-161,
--120,-71,-19,29,74,122,173,226,283,347,416,486,558,629,694,746,785,819,841,840,812,
-776,772,851,1042,1322,1626,1910,2204,2576,3029,3453,3709,3752,3657,3552,3528,3593,3698,3797,3891,4020,
-4193,4354,4449,4493,4560,4687,4833,4923,4909,4770,4497,4131,3768,3496,3321,3187,3070,3004,3011,3053,3068,
-3039,2991,2948,2916,2902,2917,2952,2973,2960,2921,2883,2843,2776,2664,2523,2389,2286,2202,2115,2023,1946,
-1899,1870,1842,1810,1776,1736,1677,1605,1536,1475,1414,1347,1277,1208,1136,1071,1036,1033,1016,920,729,
-488,260,73,-73,-186,-270,-332,-383,-431,-476,-525,-593,-679,-755,-790,-787,-775,-780,-802,-828,-863,
--913,-971,-1009,-1015,-1005,-1004,-1014,-1020,-1018,-1019,-1038,-1078,-1143,-1240,-1364,-1494,-1603,-1680,-1723,-1726,-1677,
--1582,-1470,-1375,-1315,-1280,-1256,-1240,-1236,-1247,-1269,-1297,-1328,-1355,-1364,-1353,-1339,-1345,-1362,-1352,-1297,-1228,
--1187,-1173,-1145,-1088,-1034,-1015,-1012,-990,-957,-956,-1004,-1068,-1107,-1127,-1154,-1198,-1244,-1276,-1291,-1288,-1272,
--1247,-1223,-1201,-1174,-1140,-1105,-1075,-1046,-1012,-973,-932,-893,-864,-847,-837,-825,-808,-792,-779,-769,-761,
--759,-762,-762,-753,-743,-742,-745,-744,-738,-733,-733,-731,-724,-717,-714,-708,-696,-681,-671,-665,-656,
--644,-632,-618,-597,-571,-546,-523,-498,-470,-440,-411,-380,-346,-311,-275,-238,-196,-155,-116,-77,-35,
-7,47,85,126,169,211,249,286,325,365,401,434,467,501,536,569,602,641,684,729,767,
-798,825,853,877,893,901,907,916,924,930,937,949,965,981,995,1008,1018,1025,1029,1038,1053,
-1072,1087,1097,1108,1124,1147,1173,1199,1223,1243,1257,1266,1273,1284,1297,1304,1301,1297,1302,1315,1327,
-1330,1328,1329,1331,1325,1307,1284,1271,1270,1278,1283,1281,1273,1267,1263,1261,1258,1255,1249,1268,1262,
-1259,1259,1263,1265,1261,1253,1248,1248,1251,1253,1253,1257,1265,1273,1278,1279,1281,1286,1293,1299,1305,
-1313,1326,1344,1363,1382,1400,1419,1437,1450,1459,1469,1481,1490,1496,1499,1508,1527,1555,1588,1626,1672,
-1723,1767,1798,1833,1897,1993,2088,2140,2132,2092,2068,2091,2155,2225,2263,2261,2241,2225,2205,2156,2072,
-1976,1898,1843,1795,1744,1692,1643,1594,1542,1488,1438,1391,1344,1293,1241,1195,1156,1107,1026,912,793,
-701,642,602,575,561,556,542,513,476,436,390,341,303,285,271,239,188,141,110,87,61,
-29,-8,-60,-126,-190,-239,-281,-334,-400,-458,-491,-518,-582,-707,-872,-1018,-1104,-1134,-1141,-1147,-1151,
--1147,-1140,-1144,-1156,-1156,-1124,-1069,-1034,-1074,-1211,-1392,-1523,-1555,-1535,-1545,-1617,-1706,-1764,-1793,-1828,-1890,
--1964,-2019,-2033,-2005,-1966,-1959,-1996,-2047,-2080,-2103,-2143,-2205,-2268,-2320,-2366,-2400,-2396,-2347,-2299,-2305,-2367,
--2437,-2479,-2500,-2530,-2575,-2617,-2638,-2645,-2650,-2658,-2657,-2638,-2606,-2574,-2548,-2523,-2497,-2470,-2426,-2338,-2193,
--2014,-1840,-1697,-1599,-1556,-1568,-1602,-1613,-1603,-1631,-1745,-1919,-2083,-2190,-2253,-2303,-2345,-2374,-2392,-2411,-2430,
--2446,-2459,-2476,-2496,-2508,-2509,-2503,-2503,-2511,-2522,-2530,-2532,-2529,-2528,-2533,-2546,-2565,-2589,-2615,-2646,-2689,
--2741,-2792,-2841,-2903,-2988,-3061,-3047,-2911,-2715,-2580,-2582,-2691,-2824,-2926,-2998,-3057,-3106,-3147,-3185,-3228,-3274,
--3316,-3350,-3377,-3396,-3415,-3439,-3471,-3501,-3525,-3546,-3571,-3602,-3638,-3682,-3738,-3803,-3870,-3933,-3992,-4048,-4106,
--4169,-4239,-4310,-4374,-4429,-4482,-4540,-4603,-4672,-4745,-4823,-4901,-4975,-5047,-5116,-5178,-5230,-5275,-5320,-5365,-5408,
--5452,-5500,-5548,-5589,-5625,-5665,-5710,-5752,-5786,-5817,-5849,-5878,-5898,-5913,-5928,-5942,-5953,-5964,-5977,-5991,-6003,
--6020,-6044,-6071,-6090,-6101,-6117,-6141,-6164,-6177,-6185,-6195,-6203,-6202,-6197,-6200,-6218,-6247,-6286,-6335,-6391,-6438,
--6456,-6441,-6405,-6366,-6336,-6308,-6272,-6221,-6165,-6120,-6098,-6093,-6083,-6037,-5950,-5862,-5835,-5894,-5995,-6069,-6075,
--6026,-5949,-5876,-5835,-5846,-5890,-5907,-5854,-5747,-5645,-5588,-5565,-5539,-5481,-5391,-5302,-5256,-5266,-5281,-5233,-5106,
--4951,-4826,-4737,-4667,-4607,-4554,-4481,-4369,-4244,-4161,-4141,-4148,-4146,-4137,-4129,-4107,-4049,-3965,-3889,-3835,-3789,
--3733,-3663,-3576,-3457,-3311,-3169,-3065,-2997,-2937,-2876,-2831,-2817,-2814,-2793,-2745,-2694,-2658,-2624,-2561,-2464,-2358,
--2260,-2166,-2061,-1955,-1869,-1804,-1738,-1663,-1591,-1527,-1442,-1306,-1137,-998,-941,-956,-989,-992,-958,-908,-862,
--820,-768,-699,-619,-533,-442,-340,-233,-134,-50,15,62,88,101,120,165,236,313,383,442,499,
-557,614,668,719,771,830,897,966,1038,1117,1210,1316,1433,1560,1694,1825,1936,2015,2065,2106,2164,
-2264,2406,2563,2695,2779,2831,2878,2935,3002,3078,3159,3235,3295,3335,3367,3401,3439,3481,3526,3574,3619,
-3661,3707,3766,3828,3872,3886,3892,3931,4022,4128,4187,4176,4143,4161,4248,4349,4409,4434,4471,4546,4640,
-4718,4773,4821,4878,4948,5021,5083,5122,5137,5141,5147,5159,5177,5205,5246,5291,5330,5367,5413,5464,5501,
-5511,5502,5492,5490,5491,5489,5489,5498,5523,5560,5603,5646,5687,5725,5765,5811,5870,5942,6020,6093,6158,
-6214,6265,6314,6373,6450,6536,6607,6636,6619,6571,6514,6465,6432,6413,6400,6391,6396,6423,6461,6484,6477,
-6447,6406,6362,6317,6278,6249,6230,6218,6212,6214,6221,6228,6237,6249,6260,6268,6275,6285,6296,6305,6314,
-6326,6338,6342,6339,6341,6355,6375,6397,6422,6457,6503,6553,6593,6610,6598,6561,6515,6471,6429,6395,6388,
-6423,6479,6513,6497,6447,6406,6409,6443,6472,6469,6451,6445,6449,6432,6388,6355,6362,6381,6362,6307,6267,
-6259,6244,6200,6156,6142,6145,6149,6171,6188,6073,5717,5216,4864,4888,5237,5675,6031,6275,6420,6460,6416,
-6367,6371,6402,6404,6378,6363,6366,6352,6312,6274,6258,6245,6209,6157,6108,6068,6029,5988,5948,5910,5868,
-5821,5775,5730,5686,5643,5602,5561,5518,5476,5438,5399,5354,5301,5251,5210,5178,5149,5114,5070,5025,4989,
-4951,4897,4828,4772,4745,4730,4697,4646,4605,4579,4547,4497,4447,4417,4394,4358,4309,4256,4174,4026,3826,
-3653,3574,3571,3576,3540,3464,3360,3230,3103,3037,3065,3147,3218,3256,3289,3326,3322,3234,3094,2981,2942,
-2954,2962,2936,2863,2734,2553,2355,2191,2085,2014,1947,1871,1800,1743,1701,1665,1631,1598,1564,1527,1489,
-1453,1421,1389,1351,1310,1280,1274,1282,1279,1258,1234,1221,1207,1171,1117,1072,1051,1039,1015,977,941,
-913,888,863,839,816,791,768,751,742,734,722,708,692,670,647,636,636,631,614,590,570,
-552,530,508,491,474,447,419,404,397,379,351,333,324,296,240,197,208,255,282,265,235,
-215,181,104,6,-62,-82,-88,-109,-143,-170,-186,-201,-217,-233,-250,-272,-291,-300,-303,-313,-337,
--366,-394,-425,-459,-492,-513,-525,-536,-549,-560,-561,-559,-563,-579,-604,-632,-658,-682,-699,-707,-710,
--714,-724,-738,-751,-765,-786,-810,-833,-851,-866,-880,-891,-902,-913,-923,-929,-933,-942,-955,-966,-969,
--966,-966,-966,-965,-961,-961,-962,-960,-955,-952,-951,-949,-946,-945,-947,-950,-948,-944,-943,-942,-937,
--930,-927,-929,-932,-931,-931,-930,-928,-923,-915,-908,-901,-893,-885,-878,-871,-866,-863,-863,-860,-852,
--840,-828,-818,-808,-798,-791,-782,-771,-762,-755,-751,-744,-731,-716,-704,-694,-683,-668,-650,-632,-617,
--604,-592,-578,-563,-551,-541,-530,-515,-498,-484,-475,-466,-454,-444,-436,-429,-421,-413,-409,-407,-406,
--403,-399,-395,-392,-391,-392,-394,-396,-398,-399,-401,-403,-406,-408,-412,-418,-424,-427,-428,-432,-442,
--454,-462,-466,-472,-483,-496,-508,-519,-533,-548,-563,-580,-602,-624,-640,-650,-663,-683,-706,-726,-739,
--747,-750,-751,-753,-760,-767,-769,-769,-771,-774,-774,-769,-763,-760,-760,-761,-765,-768,-767,-766,-769,
--776,-780,-778,-776,-780,-786,-783,-775,-771,-772,-774,-770,-764,-760,-757,-752,-747,-742,-734,-721,-706,
--692,-680,-668,-655,-642,-628,-613,-600,-593,-586,-577,-565,-550,-534,-521,-512,-505,-495,-480,-465,-454,
--444,-432,-418,-406,-393,-374,-348,-323,-299,-270,-233,-195,-158,-117,-68,-15,33,79,127,177,229,
-286,350,417,486,557,631,703,762,809,850,888,915,913,876,831,832,938,1166,1469,1787,2101,
-2446,2842,3251,3584,3765,3788,3725,3680,3710,3790,3866,3932,4030,4181,4337,4434,4480,4539,4651,4792,4912,
-4966,4914,4724,4415,4068,3767,3539,3372,3260,3204,3173,3113,3014,2920,2877,2883,2899,2910,2921,2935,2936,
-2914,2877,2837,2790,2717,2610,2480,2357,2260,2185,2113,2034,1962,1912,1880,1854,1828,1802,1764,1703,1628,
-1554,1490,1429,1366,1301,1228,1142,1064,1023,1016,981,855,642,409,215,67,-53,-153,-233,-300,-363,
--419,-462,-500,-553,-626,-698,-742,-756,-759,-771,-797,-834,-879,-926,-960,-968,-953,-933,-927,-938,-956,
--971,-989,-1017,-1063,-1133,-1229,-1344,-1460,-1554,-1619,-1659,-1675,-1655,-1594,-1501,-1405,-1333,-1293,-1274,-1268,-1271,
--1282,-1296,-1312,-1328,-1341,-1337,-1313,-1291,-1300,-1336,-1356,-1330,-1275,-1228,-1195,-1151,-1093,-1047,-1026,-1002,-953,
--908,-922,-999,-1087,-1140,-1165,-1196,-1238,-1273,-1288,-1291,-1286,-1272,-1247,-1216,-1186,-1155,-1123,-1096,-1071,-1042,
--1002,-955,-913,-879,-853,-832,-814,-799,-786,-773,-759,-744,-734,-736,-744,-747,-741,-732,-730,-729,-724,
--715,-712,-715,-717,-713,-708,-705,-699,-687,-674,-666,-660,-648,-632,-616,-602,-584,-561,-537,-513,-487,
--460,-433,-406,-377,-343,-308,-274,-237,-197,-156,-119,-83,-44,-3,37,76,117,160,201,237,273,
-312,353,391,425,457,490,523,555,588,626,669,711,746,776,807,840,866,883,894,907,922,
-933,936,937,944,959,976,993,1008,1018,1023,1028,1040,1059,1081,1100,1116,1132,1147,1162,1179,1200,
-1222,1240,1251,1259,1271,1287,1303,1311,1311,1311,1318,1328,1331,1321,1309,1303,1303,1303,1297,1289,1287,
-1293,1300,1303,1298,1290,1284,1282,1282,1280,1274,1268,1287,1284,1284,1283,1282,1281,1279,1275,1271,1270,
-1272,1274,1276,1280,1286,1292,1295,1296,1298,1302,1307,1311,1313,1320,1334,1353,1374,1394,1414,1434,1450,
-1462,1470,1478,1488,1493,1491,1488,1496,1518,1551,1589,1633,1688,1742,1783,1812,1851,1921,2011,2087,2125,
-2130,2123,2126,2153,2205,2265,2300,2294,2262,2229,2199,2149,2069,1980,1907,1854,1804,1752,1700,1655,1610,
-1562,1509,1458,1410,1363,1316,1266,1219,1178,1131,1063,970,870,785,719,667,629,609,600,583,550,
-508,466,426,387,357,335,307,258,196,146,119,108,98,80,48,-6,-75,-140,-190,-238,-305,
--390,-467,-520,-567,-645,-767,-901,-1000,-1041,-1044,-1040,-1046,-1066,-1100,-1144,-1183,-1202,-1193,-1152,-1078,-991,
--952,-1023,-1194,-1371,-1467,-1487,-1502,-1557,-1632,-1694,-1743,-1796,-1858,-1922,-1975,-2000,-1989,-1960,-1955,-1992,-2044,
--2078,-2103,-2139,-2178,-2203,-2235,-2311,-2411,-2451,-2385,-2274,-2225,-2273,-2359,-2418,-2445,-2471,-2512,-2556,-2591,-2613,
--2622,-2615,-2595,-2575,-2564,-2555,-2536,-2503,-2462,-2416,-2355,-2261,-2135,-1994,-1849,-1705,-1581,-1520,-1544,-1609,-1634,
--1599,-1577,-1654,-1826,-2006,-2124,-2187,-2238,-2291,-2329,-2346,-2357,-2372,-2388,-2400,-2413,-2429,-2442,-2441,-2432,-2427,
--2431,-2439,-2444,-2445,-2445,-2446,-2453,-2468,-2492,-2518,-2543,-2575,-2626,-2689,-2745,-2791,-2855,-2943,-3000,-2940,-2750,
--2534,-2430,-2482,-2621,-2755,-2850,-2917,-2972,-3013,-3048,-3091,-3144,-3193,-3227,-3254,-3279,-3301,-3320,-3342,-3371,-3399,
--3419,-3435,-3457,-3488,-3524,-3567,-3624,-3694,-3767,-3833,-3890,-3942,-3994,-4055,-4124,-4195,-4259,-4317,-4376,-4439,-4504,
--4572,-4646,-4723,-4796,-4868,-4941,-5016,-5082,-5134,-5178,-5222,-5267,-5306,-5345,-5389,-5435,-5476,-5512,-5551,-5596,-5637,
--5669,-5698,-5728,-5756,-5777,-5796,-5815,-5832,-5844,-5858,-5877,-5898,-5915,-5933,-5959,-5987,-6006,-6016,-6031,-6053,-6074,
--6085,-6093,-6107,-6122,-6130,-6134,-6146,-6171,-6202,-6235,-6275,-6324,-6367,-6382,-6361,-6313,-6259,-6212,-6168,-6117,-6055,
--5991,-5946,-5936,-5954,-5966,-5934,-5857,-5786,-5787,-5872,-5985,-6057,-6060,-6011,-5937,-5858,-5808,-5815,-5861,-5882,-5830,
--5727,-5634,-5584,-5558,-5519,-5451,-5364,-5285,-5245,-5250,-5256,-5204,-5080,-4928,-4807,-4738,-4704,-4678,-4629,-4530,-4385,
--4245,-4168,-4159,-4174,-4179,-4177,-4170,-4141,-4074,-3988,-3919,-3872,-3826,-3767,-3699,-3621,-3520,-3392,-3263,-3161,-3092,
--3036,-2983,-2939,-2911,-2893,-2870,-2839,-2810,-2782,-2740,-2668,-2573,-2472,-2371,-2260,-2139,-2032,-1960,-1904,-1831,-1737,
--1650,-1589,-1522,-1408,-1259,-1134,-1084,-1097,-1121,-1117,-1079,-1029,-983,-942,-892,-822,-736,-644,-551,-448,-331,
--212,-114,-51,-17,1,16,39,77,134,203,273,335,390,442,495,549,601,653,712,782,856,
-929,1006,1096,1201,1319,1444,1573,1698,1809,1899,1968,2032,2113,2230,2381,2536,2656,2729,2781,2838,2907,
-2977,3044,3115,3186,3245,3287,3318,3352,3392,3438,3492,3550,3600,3642,3687,3751,3827,3884,3900,3887,3889,
-3935,4009,4065,4077,4075,4108,4187,4273,4324,4345,4374,4433,4507,4574,4629,4687,4753,4824,4894,4952,4992,
-5012,5024,5042,5068,5096,5126,5161,5203,5249,5297,5351,5404,5438,5442,5424,5404,5397,5399,5404,5410,5422,
-5441,5473,5517,5569,5617,5657,5693,5741,5808,5887,5961,6024,6083,6144,6203,6254,6306,6374,6458,6538,6595,
-6620,6619,6594,6548,6491,6435,6391,6366,6365,6385,6417,6443,6453,6449,6432,6401,6360,6318,6278,6243,6215,
-6199,6193,6189,6183,6181,6189,6203,6215,6225,6237,6249,6259,6273,6293,6311,6316,6310,6309,6319,6331,6341,
-6362,6403,6455,6499,6521,6519,6491,6448,6406,6378,6365,6367,6391,6441,6492,6504,6461,6398,6371,6397,6445,
-6466,6448,6423,6416,6411,6370,6296,6244,6251,6282,6275,6225,6183,6173,6162,6117,6056,6018,6009,6025,6073,
-6121,6052,5766,5350,5056,5071,5347,5694,5987,6214,6376,6441,6419,6386,6403,6444,6447,6416,6396,6399,6392,
-6357,6319,6298,6282,6246,6196,6147,6104,6061,6017,5979,5945,5911,5874,5835,5791,5740,5685,5639,5603,5570,
-5535,5495,5451,5401,5349,5302,5265,5235,5207,5171,5126,5078,5036,5000,4957,4901,4843,4799,4761,4718,4673,
-4644,4629,4601,4550,4497,4466,4447,4417,4374,4334,4281,4177,4012,3841,3731,3690,3672,3634,3562,3453,3304,
-3138,3006,2953,2970,3015,3063,3113,3157,3170,3143,3104,3089,3099,3106,3090,3051,2975,2837,2636,2419,2245,
-2132,2049,1964,1875,1798,1740,1696,1659,1625,1593,1559,1522,1483,1444,1407,1373,1340,1306,1278,1266,1265,
-1259,1241,1222,1210,1191,1148,1092,1049,1032,1021,994,957,924,900,878,855,832,810,784,760,746,
-741,735,723,709,694,676,656,642,634,623,606,592,584,572,549,524,507,494,472,444,426,
-415,393,361,336,321,291,240,203,213,249,263,242,223,227,219,161,71,3,-16,-15,-30,
--69,-116,-156,-181,-194,-205,-222,-244,-261,-268,-273,-289,-318,-353,-390,-429,-465,-489,-497,-502,-516,
--538,-554,-558,-556,-563,-585,-613,-639,-663,-688,-713,-730,-737,-742,-754,-773,-791,-807,-823,-840,-856,
--870,-886,-904,-919,-931,-940,-946,-949,-952,-958,-968,-975,-975,-971,-969,-968,-966,-965,-967,-968,-965,
--959,-954,-953,-951,-949,-951,-955,-957,-952,-946,-944,-943,-940,-934,-930,-929,-929,-927,-926,-923,-919,
--915,-909,-903,-895,-888,-882,-876,-869,-861,-857,-855,-850,-840,-830,-821,-811,-800,-790,-781,-771,-759,
--748,-744,-742,-736,-723,-708,-698,-690,-678,-662,-644,-624,-606,-589,-574,-557,-539,-524,-514,-504,-489,
--472,-458,-450,-443,-433,-423,-415,-408,-402,-396,-392,-389,-386,-384,-381,-377,-373,-372,-373,-377,-379,
--379,-379,-380,-381,-383,-385,-389,-394,-400,-404,-409,-414,-422,-432,-442,-449,-458,-471,-485,-497,-508,
--519,-531,-545,-564,-587,-609,-624,-631,-641,-659,-680,-696,-707,-714,-719,-726,-734,-744,-750,-748,-742,
--741,-744,-745,-741,-735,-731,-728,-729,-734,-740,-742,-741,-742,-748,-752,-751,-750,-752,-755,-754,-750,
--748,-750,-752,-749,-744,-741,-739,-737,-733,-726,-718,-707,-695,-683,-670,-656,-643,-630,-617,-604,-592,
--582,-573,-563,-552,-541,-527,-512,-502,-498,-492,-479,-461,-447,-438,-426,-410,-393,-378,-361,-339,-312,
--283,-248,-212,-177,-144,-107,-62,-12,36,83,133,186,241,298,362,430,499,569,641,713,779,
-836,886,933,975,998,986,938,889,903,1035,1290,1619,1961,2284,2606,2959,3333,3658,3847,3882,3841,
-3822,3862,3931,4009,4114,4256,4395,4481,4518,4552,4612,4689,4763,4817,4822,4747,4586,4373,4138,3896,3673,
-3509,3404,3301,3139,2941,2795,2755,2794,2847,2880,2895,2896,2883,2856,2823,2783,2729,2656,2558,2441,2321,
-2221,2150,2094,2037,1979,1929,1889,1859,1838,1824,1800,1747,1672,1591,1516,1442,1371,1304,1235,1151,1066,
-1009,975,905,751,533,326,172,59,-39,-130,-205,-269,-331,-384,-421,-452,-500,-570,-642,-693,-719,
--726,-731,-749,-789,-841,-887,-908,-902,-883,-865,-863,-878,-906,-938,-972,-1015,-1075,-1151,-1240,-1333,-1422,
--1500,-1562,-1607,-1638,-1644,-1608,-1529,-1429,-1345,-1297,-1282,-1286,-1298,-1315,-1332,-1342,-1344,-1338,-1319,-1290,-1268,
--1273,-1303,-1328,-1319,-1282,-1236,-1184,-1120,-1057,-1021,-1009,-983,-928,-888,-919,-1019,-1125,-1188,-1218,-1248,-1283,
--1303,-1302,-1292,-1281,-1264,-1235,-1201,-1169,-1138,-1108,-1081,-1056,-1024,-981,-933,-894,-864,-836,-808,-785,-772,
--765,-757,-742,-724,-713,-715,-727,-735,-736,-733,-730,-726,-716,-706,-705,-710,-713,-710,-705,-701,-694,
--682,-670,-662,-654,-640,-622,-605,-591,-575,-556,-534,-510,-483,-455,-428,-403,-375,-342,-309,-275,-239,
--199,-159,-123,-88,-51,-12,28,68,109,151,192,229,264,302,341,378,414,448,481,512,541,
-572,610,653,695,730,762,796,832,861,880,896,916,936,947,945,942,945,957,974,993,1011,
-1024,1030,1038,1053,1074,1097,1118,1138,1155,1164,1169,1176,1193,1214,1230,1238,1245,1259,1280,1299,1311,
-1314,1315,1319,1320,1313,1302,1293,1293,1296,1296,1293,1293,1298,1305,1310,1312,1309,1304,1300,1300,1301,
-1298,1292,1287,1305,1304,1304,1302,1299,1298,1299,1299,1297,1293,1293,1295,1298,1303,1307,1311,1314,1316,
-1318,1320,1321,1322,1326,1336,1350,1368,1388,1408,1429,1446,1458,1466,1472,1480,1488,1492,1488,1486,1499,
-1529,1568,1607,1650,1703,1757,1797,1830,1879,1955,2036,2090,2118,2147,2188,2229,2261,2289,2322,2341,2327,
-2285,2238,2195,2139,2060,1975,1904,1852,1804,1755,1708,1666,1625,1581,1531,1480,1430,1383,1339,1294,1249,
-1204,1157,1096,1017,931,856,795,742,696,665,644,619,579,534,494,462,435,411,384,345,289,
-227,178,151,140,134,121,92,41,-21,-80,-130,-187,-267,-363,-454,-530,-606,-701,-814,-911,-963,
--970,-960,-960,-975,-1008,-1061,-1126,-1177,-1191,-1176,-1141,-1078,-980,-897,-912,-1051,-1239,-1375,-1432,-1458,-1498,
--1552,-1607,-1667,-1735,-1802,-1860,-1909,-1940,-1939,-1920,-1919,-1957,-2008,-2043,-2072,-2109,-2136,-2138,-2157,-2257,-2407,
--2485,-2413,-2260,-2172,-2207,-2305,-2380,-2415,-2437,-2464,-2495,-2530,-2567,-2589,-2581,-2555,-2536,-2533,-2528,-2499,-2447,
--2386,-2324,-2255,-2174,-2085,-1989,-1873,-1725,-1573,-1486,-1508,-1589,-1627,-1579,-1527,-1580,-1751,-1944,-2069,-2127,-2174,
--2232,-2280,-2302,-2309,-2321,-2335,-2343,-2350,-2363,-2375,-2373,-2360,-2350,-2351,-2355,-2356,-2355,-2359,-2365,-2374,-2391,
--2420,-2453,-2481,-2512,-2562,-2627,-2687,-2739,-2808,-2897,-2934,-2834,-2607,-2387,-2311,-2396,-2548,-2680,-2773,-2844,-2897,
--2930,-2960,-3008,-3068,-3112,-3135,-3153,-3179,-3204,-3222,-3241,-3267,-3293,-3311,-3327,-3350,-3382,-3418,-3461,-3517,-3586,
--3657,-3724,-3782,-3836,-3890,-3950,-4015,-4082,-4145,-4208,-4274,-4342,-4408,-4473,-4544,-4619,-4691,-4762,-4838,-4919,-4990,
--5045,-5091,-5136,-5178,-5213,-5247,-5287,-5330,-5369,-5403,-5441,-5483,-5522,-5553,-5582,-5612,-5638,-5661,-5683,-5706,-5725,
--5738,-5753,-5778,-5804,-5824,-5843,-5868,-5896,-5916,-5929,-5946,-5970,-5989,-5997,-6004,-6020,-6042,-6059,-6073,-6094,-6122,
--6151,-6179,-6212,-6252,-6288,-6302,-6283,-6237,-6174,-6109,-6044,-5978,-5908,-5841,-5800,-5800,-5835,-5864,-5842,-5774,-5718,
--5741,-5849,-5975,-6048,-6047,-5995,-5916,-5833,-5779,-5783,-5826,-5843,-5790,-5689,-5604,-5562,-5538,-5495,-5423,-5339,-5270,
--5240,-5246,-5245,-5185,-5054,-4897,-4777,-4722,-4714,-4711,-4666,-4556,-4406,-4279,-4219,-4215,-4222,-4218,-4211,-4199,-4159,
--4084,-4004,-3950,-3914,-3868,-3801,-3730,-3660,-3578,-3475,-3364,-3269,-3196,-3137,-3086,-3042,-3008,-2982,-2960,-2943,-2925,
--2896,-2842,-2761,-2665,-2566,-2464,-2348,-2227,-2129,-2068,-2019,-1942,-1836,-1739,-1671,-1607,-1508,-1381,-1279,-1235,-1238,
--1248,-1236,-1200,-1151,-1105,-1065,-1018,-947,-849,-740,-638,-537,-422,-299,-194,-125,-87,-62,-39,-19,0,
-28,81,151,223,283,334,384,439,492,542,598,665,742,817,888,967,1066,1188,1325,1463,1593,
-1710,1815,1914,2009,2112,2237,2384,2525,2629,2693,2745,2813,2890,2959,3019,3082,3151,3211,3249,3273,3300,
-3339,3393,3460,3529,3584,3622,3662,3724,3805,3870,3890,3871,3848,3852,3887,3930,3965,3996,4045,4115,4180,
-4219,4239,4267,4317,4377,4433,4490,4555,4627,4697,4761,4817,4860,4888,4908,4935,4971,5007,5038,5071,5115,
-5169,5227,5286,5340,5376,5382,5366,5345,5334,5333,5336,5341,5349,5363,5389,5432,5487,5539,5576,5608,5660,
-5740,5825,5891,5935,5984,6052,6129,6194,6248,6310,6386,6462,6520,6559,6587,6600,6584,6535,6464,6393,6342,
-6324,6337,6368,6399,6422,6436,6440,6432,6413,6386,6350,6308,6270,6245,6232,6215,6191,6168,6157,6157,6162,
-6172,6190,6210,6225,6240,6260,6277,6280,6274,6275,6285,6292,6293,6309,6351,6405,6443,6451,6435,6404,6369,
-6341,6330,6335,6355,6396,6454,6500,6494,6436,6371,6354,6391,6435,6444,6417,6385,6366,6341,6279,6197,6147,
-6157,6188,6184,6144,6119,6134,6154,6134,6079,6025,5992,5984,6006,6027,5955,5729,5435,5271,5351,5586,5814,
-5975,6121,6274,6382,6409,6404,6429,6475,6490,6464,6438,6431,6422,6394,6360,6334,6307,6268,6223,6183,6143,
-6097,6049,6011,5981,5950,5915,5876,5834,5786,5737,5696,5661,5624,5580,5535,5491,5448,5405,5365,5329,5294,
-5258,5219,5174,5123,5074,5032,4990,4940,4884,4834,4796,4763,4729,4699,4672,4635,4585,4535,4502,4478,4445,
-4404,4375,4356,4307,4198,4054,3935,3876,3857,3831,3761,3631,3442,3215,2993,2822,2736,2741,2815,2914,2980,
-2992,2982,3002,3054,3093,3079,3026,2966,2892,2768,2586,2397,2256,2164,2082,1987,1889,1809,1749,1701,1659,
-1622,1586,1549,1511,1471,1427,1384,1349,1325,1304,1284,1269,1259,1246,1224,1200,1182,1158,1116,1066,1030,
-1015,1002,975,939,910,888,867,847,829,809,783,757,743,737,729,715,703,694,681,661,644,
-632,619,604,596,594,586,563,536,520,509,488,461,441,428,405,369,339,317,287,241,205,
-204,218,208,174,158,179,203,188,139,98,86,87,66,15,-54,-116,-155,-169,-177,-192,-214,
--229,-237,-248,-272,-304,-337,-373,-413,-449,-471,-480,-488,-508,-533,-549,-553,-554,-566,-590,-619,-642,
--664,-693,-725,-750,-761,-768,-784,-810,-834,-851,-862,-872,-882,-895,-912,-932,-948,-957,-961,-967,-972,
--976,-979,-982,-983,-982,-979,-977,-974,-972,-972,-975,-975,-970,-961,-956,-954,-952,-951,-954,-960,-962,
--956,-948,-945,-945,-945,-941,-936,-932,-927,-924,-921,-916,-909,-903,-900,-897,-891,-883,-878,-874,-867,
--859,-852,-847,-839,-828,-819,-812,-804,-792,-780,-770,-758,-743,-730,-726,-724,-717,-705,-693,-686,-678,
--666,-652,-637,-620,-601,-582,-565,-545,-523,-505,-492,-482,-468,-452,-440,-432,-425,-415,-405,-396,-389,
--384,-381,-378,-374,-370,-367,-366,-363,-358,-356,-357,-360,-361,-360,-360,-361,-361,-361,-363,-367,-370,
--375,-382,-390,-397,-404,-413,-422,-432,-443,-456,-471,-485,-497,-509,-522,-537,-555,-576,-596,-607,-612,
--619,-633,-652,-668,-679,-687,-694,-704,-717,-730,-735,-730,-720,-715,-717,-720,-719,-716,-711,-706,-703,
--707,-715,-721,-721,-719,-720,-723,-724,-724,-725,-727,-728,-728,-731,-734,-733,-730,-726,-724,-723,-720,
--717,-712,-705,-696,-687,-677,-664,-649,-634,-621,-609,-596,-585,-574,-562,-550,-539,-530,-519,-506,-495,
--488,-481,-468,-452,-440,-433,-423,-405,-383,-363,-345,-326,-301,-270,-232,-193,-157,-123,-86,-43,1,
-45,90,141,197,255,314,378,448,521,592,661,730,800,868,928,979,1022,1057,1075,1056,1002,
-952,980,1139,1423,1762,2077,2356,2662,3045,3461,3783,3923,3920,3892,3921,4010,4127,4259,4392,4497,4550,
-4567,4577,4596,4618,4641,4668,4690,4692,4673,4622,4504,4289,4016,3765,3570,3380,3144,2897,2730,2683,2714,
-2760,2797,2823,2832,2820,2793,2762,2723,2672,2607,2529,2432,2321,2220,2148,2098,2051,2000,1950,1907,1872,
-1853,1848,1837,1796,1723,1640,1556,1470,1384,1308,1236,1153,1059,978,907,806,642,446,277,161,70,
--20,-107,-177,-232,-282,-325,-359,-396,-452,-522,-587,-633,-655,-657,-652,-660,-698,-755,-804,-827,-826,
--819,-816,-824,-849,-887,-930,-974,-1029,-1103,-1188,-1266,-1330,-1390,-1454,-1519,-1572,-1609,-1622,-1599,-1531,-1434,
--1345,-1293,-1280,-1289,-1303,-1320,-1339,-1353,-1355,-1340,-1312,-1280,-1254,-1245,-1251,-1259,-1253,-1232,-1194,-1137,-1068,
--1013,-997,-1003,-985,-930,-889,-924,-1034,-1154,-1232,-1271,-1299,-1324,-1333,-1322,-1301,-1278,-1250,-1218,-1187,-1161,
--1133,-1100,-1066,-1035,-1002,-961,-919,-884,-854,-823,-792,-769,-760,-758,-749,-732,-713,-702,-704,-713,-722,
--728,-731,-729,-722,-713,-707,-708,-713,-715,-713,-709,-705,-697,-686,-674,-665,-655,-640,-623,-606,-590,
--573,-554,-535,-514,-488,-458,-429,-402,-374,-343,-310,-276,-240,-201,-162,-127,-93,-58,-19,19,59,
-98,139,179,218,255,291,327,363,400,438,474,505,533,562,599,641,683,718,750,784,821,
-855,880,902,926,946,953,950,945,949,963,981,1001,1020,1034,1044,1054,1070,1091,1112,1132,1151,
-1165,1170,1169,1173,1188,1207,1220,1226,1234,1249,1271,1289,1301,1307,1312,1314,1311,1303,1297,1300,1309,
-1314,1308,1300,1299,1306,1315,1319,1321,1320,1318,1316,1314,1315,1313,1309,1305,1323,1323,1324,1322,1319,
-1320,1323,1324,1321,1315,1313,1315,1319,1323,1328,1332,1335,1338,1341,1341,1339,1340,1346,1358,1370,1384,
-1401,1421,1439,1451,1458,1461,1467,1476,1485,1490,1490,1495,1517,1556,1597,1630,1666,1715,1771,1819,1864,
-1928,2013,2085,2118,2136,2182,2265,2343,2381,2383,2376,2365,2334,2283,2230,2180,2122,2046,1966,1898,1846,
-1802,1758,1715,1674,1634,1594,1550,1503,1452,1405,1363,1322,1278,1233,1186,1127,1054,976,912,861,814,
-765,723,689,655,610,562,523,498,478,456,427,390,344,296,250,214,188,172,155,127,83,
-31,-18,-67,-127,-205,-298,-394,-492,-597,-712,-826,-909,-943,-936,-920,-919,-938,-972,-1022,-1080,-1122,
--1132,-1125,-1117,-1089,-1016,-928,-908,-1003,-1162,-1296,-1368,-1406,-1439,-1471,-1507,-1563,-1639,-1718,-1781,-1830,-1861,
--1865,-1852,-1858,-1900,-1951,-1988,-2020,-2060,-2083,-2074,-2090,-2202,-2378,-2477,-2407,-2244,-2142,-2168,-2261,-2339,-2381,
--2406,-2426,-2446,-2479,-2531,-2578,-2594,-2580,-2556,-2529,-2485,-2417,-2338,-2261,-2190,-2122,-2060,-2006,-1949,-1860,-1719,
--1556,-1447,-1448,-1523,-1571,-1540,-1491,-1533,-1692,-1884,-2012,-2071,-2114,-2173,-2227,-2253,-2262,-2272,-2281,-2283,-2284,
--2297,-2313,-2312,-2293,-2276,-2273,-2277,-2277,-2276,-2283,-2292,-2301,-2317,-2352,-2395,-2428,-2454,-2494,-2555,-2622,-2686,
--2764,-2844,-2855,-2725,-2488,-2284,-2233,-2327,-2467,-2585,-2681,-2767,-2829,-2860,-2885,-2933,-2990,-3027,-3042,-3058,-3086,
--3113,-3130,-3148,-3174,-3200,-3216,-3230,-3253,-3286,-3321,-3361,-3413,-3477,-3543,-3608,-3672,-3735,-3796,-3855,-3915,-3975,
--4037,-4103,-4175,-4247,-4312,-4374,-4442,-4515,-4588,-4661,-4740,-4824,-4901,-4961,-5011,-5055,-5095,-5126,-5158,-5196,-5237,
--5271,-5300,-5334,-5373,-5408,-5438,-5466,-5494,-5521,-5544,-5569,-5596,-5617,-5632,-5651,-5678,-5707,-5728,-5746,-5771,-5799,
--5821,-5838,-5860,-5886,-5906,-5914,-5920,-5937,-5963,-5989,-6014,-6041,-6068,-6094,-6119,-6150,-6183,-6209,-6219,-6208,-6175,
--6118,-6044,-5965,-5887,-5813,-5746,-5704,-5705,-5741,-5774,-5760,-5703,-5662,-5703,-5826,-5962,-6033,-6019,-5948,-5861,-5782,
--5739,-5748,-5787,-5797,-5742,-5648,-5571,-5534,-5513,-5473,-5403,-5322,-5261,-5242,-5254,-5251,-5179,-5035,-4873,-4763,-4729,
--4744,-4750,-4697,-4580,-4439,-4337,-4298,-4294,-4287,-4270,-4256,-4236,-4186,-4107,-4035,-3995,-3966,-3915,-3840,-3765,-3701,
--3634,-3552,-3462,-3377,-3304,-3241,-3188,-3145,-3111,-3085,-3065,-3047,-3024,-2986,-2925,-2843,-2751,-2656,-2557,-2448,-2337,
--2248,-2190,-2139,-2062,-1960,-1864,-1790,-1719,-1623,-1515,-1429,-1386,-1370,-1359,-1340,-1307,-1261,-1209,-1166,-1124,-1055,
--949,-826,-718,-628,-534,-428,-326,-249,-197,-155,-119,-97,-90,-77,-36,34,114,180,232,283,340,
-398,448,499,566,647,728,795,859,946,1070,1219,1369,1503,1624,1747,1875,2004,2128,2255,2389,2511,
-2601,2660,2714,2784,2861,2925,2978,3035,3101,3159,3196,3217,3243,3285,3349,3428,3507,3568,3607,3642,3695,
-3763,3819,3839,3824,3793,3772,3772,3797,3841,3896,3958,4019,4066,4096,4121,4157,4209,4264,4314,4365,4426,
-4493,4558,4620,4682,4735,4772,4799,4830,4870,4908,4940,4975,5025,5086,5151,5212,5269,5310,5326,5318,5301,
-5288,5279,5274,5273,5279,5293,5316,5353,5403,5453,5488,5522,5578,5664,5752,5810,5843,5888,5965,6057,6134,
-6191,6252,6327,6399,6448,6480,6511,6547,6566,6546,6481,6392,6315,6277,6285,6323,6365,6397,6417,6431,6439,
-6442,6434,6411,6372,6333,6307,6293,6276,6245,6208,6174,6146,6127,6124,6140,6166,6187,6202,6217,6230,6235,
-6235,6244,6260,6268,6264,6271,6304,6353,6385,6388,6371,6349,6331,6322,6322,6329,6346,6383,6438,6481,6473,
-6416,6357,6343,6373,6406,6410,6385,6349,6311,6260,6192,6128,6103,6123,6151,6150,6134,6147,6203,6259,6263,
-6212,6136,6061,5997,5951,5901,5794,5608,5436,5426,5615,5862,6005,6036,6077,6200,6343,6421,6437,6453,6490,
-6517,6509,6484,6462,6443,6420,6396,6372,6341,6299,6257,6221,6183,6136,6087,6051,6023,5992,5952,5909,5867,
-5828,5791,5757,5719,5670,5618,5571,5533,5497,5460,5421,5381,5335,5286,5240,5199,5156,5110,5066,5024,4978,
-4924,4875,4843,4821,4794,4754,4709,4664,4620,4581,4552,4528,4495,4449,4411,4392,4372,4314,4213,4113,4058,
-4048,4034,3962,3817,3614,3372,3100,2821,2597,2503,2563,2712,2835,2875,2870,2892,2947,2973,2927,2839,2763,
-2697,2598,2457,2320,2227,2166,2093,1997,1900,1825,1766,1715,1667,1625,1585,1543,1503,1464,1419,1373,1336,
-1318,1307,1292,1271,1250,1228,1200,1170,1144,1116,1078,1037,1009,997,984,960,932,909,888,866,846,
-831,815,789,761,742,732,721,709,702,698,683,658,636,625,618,607,599,596,589,569,548,
-537,528,505,473,448,433,410,375,343,321,293,252,217,203,195,166,123,102,119,150,164,
-161,164,177,182,157,99,21,-55,-110,-139,-156,-177,-202,-220,-233,-253,-283,-312,-335,-359,-392,
--427,-455,-474,-493,-514,-530,-537,-538,-542,-559,-586,-613,-634,-656,-687,-726,-759,-775,-786,-807,-839,
--869,-887,-897,-904,-915,-928,-946,-964,-975,-976,-975,-980,-989,-997,-999,-996,-994,-994,-994,-991,-987,
--983,-983,-986,-986,-978,-969,-961,-957,-953,-951,-955,-961,-963,-958,-951,-947,-947,-948,-947,-941,-934,
--927,-924,-921,-914,-903,-895,-893,-891,-884,-876,-871,-867,-861,-852,-845,-838,-828,-816,-807,-801,-793,
--782,-770,-759,-746,-730,-716,-709,-705,-696,-684,-674,-666,-657,-644,-632,-621,-608,-591,-573,-555,-536,
--513,-493,-478,-467,-455,-441,-430,-421,-412,-401,-392,-383,-374,-368,-366,-364,-359,-353,-349,-348,-347,
--344,-342,-344,-345,-343,-342,-343,-346,-346,-345,-347,-349,-352,-354,-361,-370,-379,-386,-394,-403,-413,
--421,-433,-448,-466,-484,-500,-515,-530,-545,-561,-577,-589,-596,-601,-611,-626,-642,-656,-665,-673,-682,
--696,-709,-714,-708,-697,-689,-689,-692,-695,-696,-694,-689,-685,-688,-697,-705,-705,-700,-697,-697,-699,
--700,-700,-701,-703,-708,-715,-718,-716,-713,-711,-711,-708,-703,-700,-699,-696,-689,-680,-671,-659,-644,
--628,-614,-600,-587,-574,-563,-552,-539,-528,-519,-510,-499,-487,-477,-467,-455,-440,-430,-424,-416,-398,
--374,-349,-329,-310,-287,-258,-223,-184,-146,-107,-65,-21,22,61,102,151,209,270,330,393,462,
-538,612,681,747,818,894,966,1020,1059,1093,1128,1145,1120,1057,1009,1054,1235,1518,1824,2114,2426,
-2813,3249,3618,3824,3882,3897,3955,4071,4216,4362,4483,4557,4582,4584,4588,4597,4607,4621,4639,4651,4663,
-4696,4739,4720,4565,4292,3993,3725,3463,3182,2925,2763,2701,2687,2681,2691,2721,2747,2743,2718,2689,2660,
-2624,2582,2532,2463,2375,2285,2213,2153,2090,2028,1979,1943,1914,1894,1886,1873,1834,1765,1683,1599,1510,
-1415,1328,1245,1152,1045,940,840,722,569,407,279,187,104,12,-71,-132,-176,-217,-259,-301,-353,
--418,-481,-529,-557,-570,-568,-558,-562,-600,-661,-715,-744,-756,-766,-779,-802,-843,-898,-952,-997,-1052,
--1130,-1220,-1289,-1332,-1371,-1428,-1494,-1545,-1568,-1567,-1544,-1491,-1411,-1331,-1282,-1272,-1282,-1292,-1301,-1318,-1341,
--1356,-1348,-1319,-1278,-1239,-1206,-1180,-1159,-1145,-1132,-1110,-1069,-1022,-999,-1015,-1039,-1019,-947,-881,-896,-1003,
--1141,-1248,-1307,-1340,-1360,-1364,-1349,-1320,-1283,-1242,-1204,-1176,-1154,-1127,-1089,-1050,-1016,-985,-951,-915,-882,
--853,-822,-793,-774,-767,-762,-748,-728,-710,-701,-699,-701,-708,-717,-724,-724,-718,-713,-713,-717,-720,
--720,-719,-718,-716,-709,-699,-690,-682,-672,-657,-640,-621,-601,-578,-557,-538,-520,-497,-468,-438,-408,
--379,-348,-315,-281,-246,-209,-172,-137,-103,-68,-31,7,45,83,121,160,201,242,278,312,348,
-387,429,468,502,531,562,596,636,674,707,736,768,805,843,877,906,931,949,953,949,947,
-955,971,989,1008,1027,1041,1053,1064,1080,1099,1117,1134,1149,1162,1168,1171,1179,1192,1204,1212,1218,
-1230,1248,1265,1277,1287,1297,1306,1312,1311,1306,1307,1318,1334,1339,1330,1317,1315,1324,1334,1337,1336,
-1335,1332,1329,1326,1326,1327,1325,1323,1342,1341,1342,1342,1340,1341,1344,1345,1341,1336,1334,1336,1339,
-1343,1348,1352,1357,1360,1363,1363,1361,1361,1367,1377,1386,1394,1408,1425,1440,1447,1450,1455,1463,1473,
-1482,1490,1498,1513,1541,1582,1619,1645,1675,1726,1793,1860,1926,2005,2097,2165,2187,2194,2239,2333,2424,
-2461,2441,2397,2351,2300,2245,2194,2149,2097,2030,1959,1897,1847,1803,1762,1722,1681,1641,1603,1565,1522,
-1474,1427,1386,1346,1303,1259,1213,1157,1087,1014,957,916,875,826,776,733,692,644,594,555,532,
-515,494,469,445,420,387,341,288,241,208,182,151,111,68,27,-14,-66,-131,-212,-309,-424,
--551,-679,-798,-889,-933,-931,-905,-890,-898,-927,-967,-1010,-1043,-1063,-1087,-1118,-1128,-1083,-1007,-973,-1026,
--1132,-1224,-1277,-1313,-1346,-1371,-1392,-1439,-1521,-1614,-1693,-1750,-1783,-1788,-1778,-1788,-1832,-1888,-1931,-1967,-2002,
--2015,-2001,-2023,-2147,-2331,-2433,-2371,-2220,-2124,-2139,-2213,-2280,-2329,-2371,-2401,-2418,-2445,-2499,-2562,-2604,-2608,
--2577,-2511,-2413,-2301,-2197,-2112,-2040,-1979,-1935,-1907,-1873,-1804,-1682,-1529,-1406,-1372,-1425,-1490,-1500,-1476,-1506,
--1635,-1809,-1942,-2013,-2061,-2117,-2168,-2196,-2210,-2223,-2231,-2228,-2225,-2239,-2257,-2253,-2224,-2198,-2196,-2205,-2210,
--2211,-2219,-2232,-2243,-2259,-2297,-2348,-2385,-2405,-2433,-2490,-2564,-2640,-2715,-2773,-2751,-2603,-2378,-2207,-2178,-2263,
--2375,-2474,-2575,-2680,-2755,-2788,-2810,-2851,-2902,-2933,-2948,-2970,-3003,-3029,-3044,-3064,-3094,-3120,-3133,-3144,-3167,
--3198,-3229,-3263,-3311,-3370,-3432,-3496,-3566,-3638,-3703,-3760,-3813,-3869,-3931,-4000,-4075,-4149,-4214,-4275,-4340,-4415,
--4491,-4566,-4645,-4729,-4808,-4873,-4925,-4969,-5005,-5037,-5071,-5111,-5149,-5177,-5201,-5231,-5268,-5300,-5326,-5350,-5378,
--5404,-5429,-5455,-5484,-5509,-5528,-5551,-5580,-5607,-5627,-5647,-5674,-5704,-5727,-5747,-5771,-5799,-5820,-5830,-5839,-5860,
--5891,-5926,-5960,-5991,-6015,-6036,-6060,-6090,-6116,-6129,-6132,-6129,-6115,-6074,-6005,-5925,-5847,-5775,-5709,-5661,-5649,
--5671,-5696,-5687,-5643,-5617,-5669,-5801,-5940,-6002,-5965,-5871,-5777,-5715,-5697,-5716,-5748,-5751,-5700,-5617,-5546,-5510,
--5491,-5456,-5393,-5317,-5262,-5249,-5265,-5253,-5166,-5011,-4858,-4777,-4778,-4812,-4809,-4733,-4601,-4473,-4398,-4378,-4373,
--4354,-4328,-4310,-4284,-4227,-4147,-4083,-4048,-4016,-3959,-3882,-3810,-3752,-3692,-3621,-3546,-3474,-3407,-3344,-3291,-3249,
--3219,-3193,-3169,-3140,-3101,-3052,-2991,-2919,-2836,-2748,-2657,-2561,-2464,-2377,-2307,-2243,-2167,-2077,-1991,-1916,-1837,
--1744,-1649,-1576,-1527,-1488,-1457,-1433,-1406,-1361,-1302,-1250,-1206,-1143,-1036,-908,-802,-731,-672,-601,-519,-444,
--379,-319,-264,-223,-198,-175,-131,-62,14,80,130,181,240,301,353,403,470,558,644,711,769,
-851,977,1132,1285,1419,1543,1680,1834,1990,2132,2260,2379,2484,2563,2619,2674,2742,2813,2872,2918,2967,
-3023,3075,3115,3146,3184,3237,3309,3393,3476,3541,3584,3620,3661,3706,3739,3753,3747,3726,3698,3678,3683,
-3722,3785,3853,3908,3946,3973,4004,4050,4110,4167,4213,4254,4300,4352,4409,4475,4548,4614,4662,4695,4730,
-4771,4810,4844,4883,4939,5006,5073,5136,5196,5244,5267,5264,5249,5234,5221,5211,5208,5217,5234,5256,5286,
-5328,5373,5412,5449,5506,5589,5672,5728,5764,5816,5901,5997,6071,6125,6187,6270,6350,6399,6420,6442,6482,
-6521,6526,6474,6379,6283,6227,6231,6278,6334,6375,6398,6414,6429,6443,6449,6436,6407,6374,6354,6349,6342,
-6322,6288,6245,6196,6149,6120,6121,6139,6154,6161,6167,6177,6185,6193,6208,6229,6241,6239,6241,6265,6306,
-6337,6341,6326,6309,6303,6307,6316,6321,6327,6350,6391,6424,6417,6369,6321,6307,6327,6352,6361,6348,6311,
-6251,6176,6110,6077,6083,6111,6137,6150,6170,6223,6302,6362,6361,6301,6209,6107,6002,5902,5798,5666,5512,
-5430,5532,5812,6097,6214,6168,6124,6201,6356,6467,6492,6483,6496,6526,6538,6523,6493,6464,6442,6427,6411,
-6382,6341,6298,6259,6217,6169,6123,6089,6063,6031,5991,5947,5905,5867,5834,5801,5760,5710,5660,5619,5583,
-5544,5500,5456,5412,5361,5305,5254,5217,5185,5147,5105,5063,5018,4964,4912,4877,4855,4828,4784,4737,4699,
-4668,4635,4604,4579,4551,4505,4451,4413,4396,4371,4313,4239,4191,4180,4162,4089,3957,3797,3619,3380,3047,
-2679,2414,2366,2505,2692,2804,2834,2848,2869,2859,2786,2683,2600,2538,2458,2350,2252,2191,2146,2079,1989,
-1902,1834,1777,1722,1673,1631,1589,1543,1501,1463,1421,1374,1337,1318,1308,1289,1260,1232,1208,1182,1150,
-1118,1085,1050,1018,998,988,976,957,936,919,900,875,854,839,823,796,766,745,730,717,708,
-708,708,689,655,630,623,623,616,606,600,594,582,572,570,563,533,489,451,427,402,370,
-344,328,309,276,241,220,200,166,124,97,91,96,104,128,169,208,221,200,154,90,17,
--50,-103,-142,-177,-206,-228,-248,-276,-310,-338,-354,-370,-395,-426,-457,-485,-509,-524,-526,-521,-519,
--528,-548,-573,-597,-617,-639,-672,-715,-753,-778,-795,-822,-858,-892,-912,-921,-930,-942,-959,-977,-993,
--999,-993,-987,-990,-1001,-1011,-1014,-1012,-1010,-1011,-1011,-1009,-1002,-996,-995,-996,-995,-988,-977,-969,-962,
--956,-953,-955,-961,-963,-959,-953,-949,-948,-949,-948,-942,-934,-927,-925,-924,-916,-904,-894,-890,-887,
--878,-867,-860,-856,-850,-840,-832,-826,-817,-805,-796,-789,-781,-769,-758,-749,-737,-722,-708,-699,-692,
--681,-667,-656,-646,-634,-619,-607,-597,-585,-570,-555,-540,-523,-501,-482,-468,-457,-446,-434,-423,-412,
--399,-388,-380,-372,-362,-354,-351,-350,-345,-335,-330,-329,-330,-328,-329,-332,-333,-329,-326,-328,-332,
--333,-333,-335,-338,-338,-338,-342,-349,-357,-365,-375,-386,-394,-400,-409,-427,-450,-471,-487,-498,-506,
--514,-526,-543,-563,-578,-586,-593,-604,-618,-632,-642,-649,-656,-665,-675,-679,-674,-665,-660,-659,-661,
--666,-670,-673,-672,-670,-672,-680,-688,-689,-683,-678,-675,-676,-676,-677,-677,-680,-688,-697,-700,-698,
--696,-697,-699,-695,-688,-685,-686,-686,-681,-673,-663,-652,-637,-621,-606,-591,-576,-562,-551,-541,-530,
--518,-508,-497,-485,-473,-463,-454,-443,-430,-418,-408,-397,-380,-358,-334,-311,-289,-266,-239,-208,-172,
--135,-96,-52,-7,35,75,116,165,224,288,350,410,476,549,625,695,760,829,907,985,1046,
-1088,1123,1165,1205,1216,1177,1103,1056,1106,1278,1545,1862,2220,2622,3037,3387,3618,3749,3845,3955,4084,
-4224,4363,4479,4549,4574,4582,4592,4605,4623,4653,4681,4681,4657,4658,4705,4734,4654,4452,4189,3912,3610,
-3293,3028,2872,2797,2729,2653,2611,2624,2650,2649,2625,2608,2604,2602,2595,2574,2531,2465,2392,2320,2240,
-2148,2064,2015,1998,1985,1964,1939,1911,1866,1798,1720,1640,1552,1457,1360,1263,1153,1030,910,797,678,
-545,416,317,238,154,62,-15,-66,-103,-145,-195,-254,-321,-387,-435,-462,-478,-494,-500,-494,-498,
--534,-593,-646,-679,-701,-723,-747,-782,-843,-923,-993,-1040,-1084,-1152,-1233,-1292,-1323,-1354,-1408,-1470,-1505,
--1503,-1480,-1454,-1418,-1364,-1303,-1263,-1259,-1275,-1285,-1285,-1294,-1323,-1354,-1360,-1330,-1278,-1221,-1165,-1111,-1064,
--1032,-1017,-1008,-995,-989,-1010,-1057,-1089,-1056,-956,-857,-842,-938,-1095,-1236,-1325,-1369,-1388,-1389,-1371,-1336,
--1289,-1239,-1194,-1161,-1134,-1102,-1063,-1024,-994,-969,-941,-910,-881,-853,-827,-803,-788,-778,-766,-747,-727,
--713,-705,-698,-692,-695,-705,-715,-717,-714,-714,-720,-725,-726,-725,-727,-731,-732,-727,-720,-714,-709,
--700,-686,-669,-648,-622,-594,-569,-549,-531,-509,-482,-452,-422,-392,-360,-327,-293,-259,-225,-190,-155,
--119,-83,-46,-7,32,70,106,144,187,230,269,304,341,381,423,462,498,532,565,598,632,
-667,698,726,755,790,830,870,904,931,948,953,951,951,958,972,989,1006,1024,1040,1053,1066,
-1081,1097,1112,1126,1138,1150,1163,1177,1191,1200,1203,1207,1220,1239,1254,1261,1266,1275,1289,1301,1305,
-1304,1304,1310,1326,1343,1349,1341,1329,1329,1340,1351,1354,1351,1347,1344,1340,1338,1340,1343,1344,1342,
-1360,1358,1357,1357,1356,1357,1360,1362,1361,1359,1359,1358,1359,1362,1367,1373,1376,1378,1381,1383,1383,
-1383,1386,1392,1397,1403,1413,1426,1436,1439,1444,1453,1464,1472,1479,1491,1507,1529,1557,1592,1623,1649,
-1682,1744,1831,1921,2006,2095,2188,2258,2281,2281,2310,2383,2457,2481,2447,2382,2312,2248,2194,2153,2118,
-2074,2016,1954,1900,1853,1809,1769,1731,1692,1652,1615,1579,1539,1493,1450,1411,1372,1329,1284,1239,1187,
-1121,1052,997,959,921,874,822,775,730,680,631,595,573,555,537,520,508,496,466,412,344,
-282,237,202,163,121,84,55,27,-11,-65,-144,-254,-387,-521,-641,-751,-851,-918,-930,-898,-861,
--852,-871,-902,-933,-965,-1010,-1074,-1142,-1175,-1146,-1083,-1049,-1073,-1120,-1143,-1144,-1161,-1202,-1242,-1273,-1323,
--1409,-1515,-1609,-1677,-1716,-1723,-1713,-1721,-1765,-1827,-1880,-1917,-1935,-1927,-1909,-1948,-2091,-2280,-2378,-2320,-2187,
--2103,-2111,-2165,-2221,-2281,-2345,-2389,-2400,-2400,-2423,-2467,-2510,-2525,-2496,-2414,-2290,-2160,-2054,-1975,-1912,-1865,
--1839,-1821,-1790,-1727,-1623,-1488,-1358,-1293,-1326,-1412,-1469,-1472,-1483,-1572,-1724,-1866,-1955,-2010,-2059,-2103,-2132,
--2152,-2171,-2183,-2180,-2175,-2186,-2201,-2191,-2152,-2119,-2118,-2136,-2148,-2152,-2164,-2183,-2199,-2217,-2253,-2303,-2341,
--2358,-2381,-2435,-2510,-2582,-2638,-2660,-2609,-2461,-2269,-2135,-2119,-2187,-2274,-2365,-2477,-2596,-2678,-2709,-2727,-2764,
--2809,-2839,-2861,-2891,-2924,-2944,-2955,-2976,-3010,-3037,-3048,-3059,-3083,-3114,-3140,-3168,-3212,-3269,-3330,-3394,-3466,
--3541,-3606,-3658,-3708,-3763,-3826,-3897,-3973,-4048,-4115,-4175,-4241,-4317,-4396,-4473,-4550,-4630,-4707,-4772,-4824,-4866,
--4902,-4937,-4976,-5020,-5056,-5080,-5100,-5130,-5167,-5200,-5223,-5245,-5271,-5296,-5321,-5347,-5375,-5402,-5427,-5454,-5484,
--5508,-5526,-5549,-5581,-5613,-5638,-5658,-5684,-5712,-5733,-5745,-5760,-5789,-5828,-5871,-5912,-5944,-5964,-5980,-6002,-6031,
--6050,-6052,-6048,-6052,-6053,-6029,-5974,-5904,-5837,-5775,-5713,-5660,-5630,-5629,-5637,-5626,-5591,-5575,-5632,-5765,-5903,
--5957,-5900,-5790,-5702,-5667,-5674,-5697,-5715,-5709,-5665,-5595,-5528,-5488,-5467,-5441,-5390,-5323,-5271,-5257,-5262,-5233,
--5128,-4973,-4849,-4813,-4851,-4890,-4862,-4753,-4610,-4499,-4452,-4448,-4442,-4414,-4381,-4355,-4323,-4265,-4192,-4133,-4093,
--4049,-3986,-3919,-3864,-3815,-3757,-3687,-3620,-3559,-3500,-3442,-3391,-3352,-3322,-3294,-3261,-3218,-3164,-3105,-3046,-2984,
--2910,-2829,-2749,-2670,-2587,-2498,-2413,-2333,-2255,-2173,-2094,-2016,-1934,-1846,-1766,-1704,-1651,-1599,-1556,-1530,-1508,
--1463,-1396,-1333,-1283,-1219,-1116,-990,-887,-831,-803,-772,-723,-662,-595,-522,-447,-377,-319,-268,-213,-148,
--78,-17,32,80,135,194,248,301,369,454,538,605,671,766,903,1062,1211,1343,1476,1630,1802,
-1973,2123,2248,2353,2439,2507,2561,2614,2677,2745,2804,2851,2893,2936,2979,3022,3070,3126,3191,3268,3351,
-3431,3495,3541,3578,3611,3636,3648,3653,3657,3653,3633,3606,3598,3627,3684,3747,3799,3835,3864,3897,3945,
-4007,4069,4117,4153,4185,4223,4274,4341,4420,4495,4551,4595,4640,4687,4727,4761,4802,4861,4929,4995,5059,
-5122,5175,5199,5195,5179,5168,5160,5155,5155,5167,5188,5210,5236,5271,5315,5356,5395,5446,5516,5589,5646,
-5694,5760,5851,5943,6008,6056,6120,6213,6306,6362,6382,6396,6429,6469,6483,6442,6351,6246,6177,6173,6223,
-6289,6340,6370,6390,6410,6428,6438,6433,6417,6399,6393,6397,6400,6394,6374,6339,6289,6229,6183,6164,6161,
-6155,6138,6125,6127,6137,6149,6163,6181,6195,6199,6205,6230,6269,6301,6308,6291,6270,6261,6270,6287,6299,
-6305,6315,6334,6346,6332,6295,6262,6254,6269,6289,6304,6300,6262,6186,6100,6044,6034,6054,6079,6101,6131,
-6180,6245,6301,6321,6294,6235,6165,6091,6005,5910,5808,5692,5573,5530,5658,5952,6251,6375,6309,6214,6243,
-6384,6512,6547,6523,6511,6531,6554,6551,6525,6494,6471,6457,6442,6415,6377,6333,6289,6244,6198,6157,6122,
-6092,6060,6025,5987,5947,5905,5865,5829,5793,5751,5710,5674,5634,5584,5528,5480,5441,5397,5342,5291,5254,
-5225,5187,5141,5094,5048,4997,4945,4902,4871,4838,4796,4759,4736,4717,4682,4638,4606,4584,4550,4496,4447,
-4426,4417,4386,4328,4277,4250,4221,4153,4053,3963,3882,3728,3409,2944,2500,2272,2318,2523,2717,2818,2848,
-2848,2816,2737,2634,2547,2480,2405,2312,2229,2173,2124,2056,1972,1896,1833,1773,1716,1670,1635,1595,1546,
-1497,1458,1419,1376,1339,1316,1299,1272,1238,1211,1194,1176,1146,1109,1073,1041,1016,1003,995,983,963,
-944,928,911,888,867,850,830,801,771,748,730,714,706,711,714,695,661,638,636,639,631,
-620,616,615,610,607,610,603,566,508,455,417,387,358,339,332,321,297,268,246,224,195,
-162,135,106,72,52,72,123,165,173,158,141,120,78,13,-57,-119,-167,-200,-223,-247,-283,
--327,-365,-392,-412,-434,-458,-483,-507,-526,-530,-520,-510,-511,-522,-538,-557,-577,-598,-621,-654,-699,
--744,-777,-801,-830,-867,-901,-921,-931,-941,-955,-973,-993,-1010,-1018,-1013,-1006,-1006,-1014,-1022,-1027,-1029,
--1030,-1030,-1028,-1023,-1016,-1010,-1007,-1005,-1001,-993,-983,-974,-967,-961,-957,-957,-960,-962,-959,-954,-950,
--948,-947,-945,-941,-933,-927,-925,-924,-917,-906,-896,-891,-886,-876,-864,-855,-849,-840,-828,-819,-813,
--805,-795,-785,-777,-767,-755,-744,-735,-726,-714,-702,-693,-684,-671,-657,-644,-631,-616,-600,-585,-573,
--559,-544,-532,-520,-504,-485,-468,-455,-445,-433,-422,-412,-399,-384,-373,-366,-359,-349,-340,-337,-337,
--331,-321,-314,-313,-314,-314,-315,-319,-321,-318,-314,-315,-318,-321,-322,-324,-328,-328,-327,-327,-331,
--337,-345,-358,-371,-380,-385,-396,-417,-439,-455,-460,-462,-463,-468,-479,-500,-528,-554,-569,-577,-585,
--595,-607,-616,-622,-628,-633,-638,-639,-636,-632,-630,-632,-635,-638,-642,-646,-648,-648,-652,-658,-664,
--667,-665,-660,-657,-656,-657,-659,-660,-663,-670,-679,-683,-682,-681,-684,-686,-683,-675,-671,-673,-674,
--670,-662,-652,-640,-625,-610,-596,-583,-569,-554,-541,-531,-520,-507,-494,-480,-466,-454,-445,-439,-430,
--418,-401,-384,-368,-351,-333,-313,-291,-267,-242,-215,-185,-151,-116,-80,-42,-1,41,85,131,184,
-244,309,372,432,493,559,630,700,766,834,907,983,1051,1107,1156,1205,1255,1291,1290,1235,1147,
-1086,1124,1295,1589,1966,2376,2763,3090,3350,3571,3768,3935,4065,4179,4299,4416,4502,4548,4575,4596,4609,
-4625,4658,4694,4689,4635,4589,4600,4636,4623,4528,4368,4143,3832,3472,3172,3004,2920,2823,2692,2591,2559,
-2562,2550,2528,2527,2556,2592,2618,2622,2597,2545,2482,2411,2320,2207,2107,2060,2060,2063,2041,2000,1954,
-1902,1836,1760,1677,1589,1494,1393,1281,1154,1021,896,785,674,557,450,368,294,209,119,48,4,
--31,-78,-139,-210,-283,-342,-376,-392,-415,-449,-473,-476,-479,-507,-556,-599,-629,-656,-686,-718,-761,
--837,-939,-1031,-1087,-1122,-1168,-1224,-1268,-1292,-1320,-1369,-1421,-1442,-1425,-1394,-1371,-1352,-1320,-1278,-1250,-1254,
--1277,-1289,-1285,-1285,-1311,-1349,-1361,-1331,-1271,-1203,-1138,-1071,-1008,-959,-932,-926,-936,-966,-1017,-1075,-1103,
--1061,-955,-846,-813,-893,-1048,-1206,-1318,-1379,-1403,-1400,-1373,-1330,-1280,-1230,-1182,-1139,-1097,-1057,-1019,-988,
--964,-944,-920,-895,-871,-849,-828,-810,-795,-782,-765,-744,-729,-720,-712,-699,-687,-686,-696,-706,-709,
--708,-713,-721,-727,-726,-726,-732,-740,-744,-741,-737,-734,-731,-724,-712,-696,-674,-646,-616,-590,-568,
--547,-523,-497,-467,-435,-402,-369,-335,-302,-270,-240,-208,-172,-134,-97,-59,-19,24,65,102,140,
-182,227,269,306,344,383,421,457,494,532,569,601,631,663,696,725,752,782,820,861,898,
-927,946,955,956,954,956,964,979,996,1015,1033,1050,1065,1079,1093,1105,1116,1125,1135,1152,1175,
-1193,1199,1198,1208,1234,1260,1269,1263,1265,1285,1307,1312,1302,1290,1289,1300,1316,1330,1336,1333,1328,
-1330,1341,1353,1358,1356,1354,1352,1350,1351,1355,1360,1362,1360,1376,1375,1375,1373,1370,1371,1375,1380,
-1382,1383,1382,1380,1377,1380,1386,1392,1394,1394,1398,1402,1404,1403,1405,1410,1414,1419,1427,1435,1438,
-1439,1445,1457,1467,1470,1474,1488,1511,1535,1559,1587,1617,1649,1695,1773,1879,1989,2085,2172,2256,2322,
-2352,2357,2372,2412,2454,2462,2425,2358,2283,2214,2165,2134,2106,2064,2008,1952,1903,1859,1816,1776,1741,
-1706,1669,1633,1597,1557,1515,1475,1440,1403,1359,1312,1266,1216,1154,1089,1035,994,955,908,859,812,
-767,720,677,646,626,608,591,580,573,555,514,449,376,314,266,223,174,128,99,87,75,
-44,-16,-116,-253,-401,-527,-620,-705,-805,-898,-940,-917,-869,-842,-845,-860,-875,-904,-969,-1066,-1160,
--1204,-1183,-1133,-1110,-1121,-1119,-1068,-1005,-993,-1044,-1117,-1179,-1243,-1333,-1442,-1543,-1618,-1661,-1670,-1660,-1662,
--1699,-1761,-1819,-1849,-1844,-1811,-1795,-1864,-2039,-2236,-2326,-2267,-2145,-2073,-2080,-2125,-2181,-2252,-2326,-2366,-2350,
--2303,-2267,-2262,-2279,-2295,-2282,-2219,-2116,-2009,-1927,-1869,-1825,-1795,-1780,-1758,-1707,-1628,-1528,-1409,-1285,-1212,
--1242,-1351,-1444,-1463,-1457,-1515,-1655,-1806,-1905,-1957,-1998,-2037,-2067,-2088,-2111,-2127,-2126,-2120,-2126,-2136,-2122,
--2081,-2047,-2049,-2072,-2087,-2093,-2108,-2136,-2159,-2176,-2203,-2243,-2278,-2298,-2323,-2373,-2435,-2480,-2495,-2479,-2418,
--2300,-2160,-2066,-2056,-2107,-2184,-2283,-2410,-2533,-2606,-2627,-2641,-2680,-2726,-2759,-2785,-2817,-2846,-2856,-2858,-2877,
--2911,-2938,-2950,-2967,-2999,-3033,-3056,-3079,-3120,-3177,-3237,-3300,-3371,-3443,-3503,-3551,-3599,-3659,-3727,-3799,-3874,
--3948,-4015,-4076,-4142,-4220,-4301,-4377,-4451,-4526,-4597,-4660,-4711,-4753,-4790,-4827,-4869,-4912,-4947,-4971,-4994,-5027,
--5068,-5105,-5131,-5153,-5176,-5199,-5221,-5244,-5271,-5299,-5329,-5360,-5389,-5410,-5427,-5452,-5488,-5523,-5549,-5572,-5600,
--5629,-5647,-5660,-5682,-5721,-5771,-5822,-5867,-5898,-5914,-5926,-5946,-5973,-5989,-5986,-5982,-5991,-5999,-5984,-5940,-5887,
--5837,-5791,-5740,-5685,-5639,-5612,-5596,-5574,-5541,-5529,-5586,-5718,-5855,-5905,-5843,-5734,-5665,-5658,-5679,-5690,-5685,
--5668,-5630,-5569,-5504,-5457,-5436,-5417,-5380,-5325,-5278,-5256,-5239,-5184,-5070,-4935,-4856,-4866,-4925,-4950,-4885,-4750,
--4609,-4525,-4505,-4512,-4500,-4462,-4419,-4384,-4345,-4291,-4231,-4177,-4126,-4065,-4001,-3954,-3925,-3889,-3831,-3760,-3695,
--3639,-3584,-3528,-3480,-3444,-3412,-3378,-3337,-3285,-3222,-3157,-3097,-3037,-2967,-2891,-2821,-2756,-2685,-2598,-2506,-2421,
--2343,-2264,-2182,-2099,-2014,-1932,-1863,-1809,-1758,-1705,-1658,-1629,-1605,-1559,-1489,-1417,-1357,-1288,-1188,-1068,-967,
--913,-897,-888,-864,-820,-760,-688,-610,-527,-447,-376,-314,-253,-187,-121,-66,-18,30,86,144,205,
-273,348,418,484,568,693,851,1012,1154,1287,1435,1606,1788,1959,2104,2219,2308,2376,2431,2481,2532,
-2590,2656,2722,2779,2822,2856,2891,2937,2997,3065,3139,3221,3306,3384,3443,3484,3518,3546,3561,3563,3566,
-3576,3582,3569,3545,3534,3553,3596,3647,3696,3737,3769,3801,3842,3898,3961,4017,4060,4093,4127,4171,4233,
-4307,4379,4442,4499,4559,4616,4659,4691,4731,4787,4851,4912,4972,5036,5090,5115,5112,5099,5097,5102,5108,
-5113,5127,5149,5174,5202,5238,5280,5319,5353,5394,5450,5513,5571,5629,5703,5796,5885,5949,5997,6063,6160,
-6258,6320,6342,6352,6376,6410,6426,6396,6316,6213,6134,6115,6157,6226,6285,6325,6354,6379,6397,6406,6406,
-6406,6411,6422,6432,6437,6433,6423,6403,6368,6319,6274,6246,6226,6194,6147,6106,6090,6098,6112,6125,6138,
-6149,6156,6167,6194,6234,6267,6273,6256,6232,6224,6236,6260,6282,6291,6292,6288,6278,6257,6233,6220,6222,
-6231,6239,6247,6243,6208,6136,6058,6015,6014,6029,6042,6062,6101,6149,6180,6174,6137,6093,6066,6061,6061,
-6041,5998,5940,5867,5782,5736,5815,6039,6298,6426,6377,6272,6267,6384,6518,6573,6558,6539,6552,6573,6574,
-6555,6531,6510,6489,6465,6436,6400,6360,6316,6273,6234,6198,6160,6120,6083,6052,6023,5986,5942,5899,5864,
-5832,5796,5758,5718,5673,5617,5560,5514,5480,5442,5392,5343,5305,5270,5223,5166,5114,5074,5035,4992,4948,
-4908,4864,4817,4780,4764,4750,4715,4664,4623,4603,4581,4538,4492,4470,4463,4441,4390,4335,4298,4264,4207,
-4133,4080,4050,3961,3695,3222,2678,2289,2199,2362,2601,2770,2840,2849,2822,2756,2660,2565,2484,2405,2319,
-2238,2173,2114,2044,1965,1892,1827,1762,1704,1665,1640,1605,1551,1494,1448,1410,1371,1335,1309,1285,1253,
-1217,1194,1185,1174,1146,1108,1071,1043,1025,1017,1011,997,973,950,932,915,897,878,860,835,804,
-774,751,729,707,696,700,705,694,671,659,660,657,641,630,634,641,638,631,628,616,579,
-519,463,421,389,362,348,343,333,311,285,265,244,220,197,175,138,81,35,34,63,76,
-57,40,59,100,115,78,7,-66,-123,-160,-185,-214,-260,-320,-380,-429,-464,-486,-499,-509,-520,
--527,-523,-512,-508,-516,-526,-532,-540,-558,-582,-608,-640,-685,-735,-776,-804,-831,-862,-892,-912,-925,
--938,-954,-972,-993,-1013,-1027,-1030,-1028,-1027,-1030,-1034,-1040,-1045,-1048,-1046,-1039,-1033,-1029,-1025,-1021,-1015,
--1009,-999,-988,-977,-971,-966,-962,-960,-961,-961,-958,-955,-952,-949,-947,-944,-940,-934,-928,-925,-921,
--914,-905,-897,-892,-886,-876,-865,-857,-848,-835,-821,-810,-803,-795,-786,-776,-766,-754,-740,-728,-718,
--709,-699,-691,-683,-674,-661,-646,-633,-620,-605,-589,-572,-555,-537,-523,-512,-501,-484,-465,-449,-438,
--428,-416,-406,-397,-385,-369,-356,-349,-343,-333,-324,-323,-324,-319,-309,-302,-301,-301,-300,-300,-304,
--308,-307,-303,-302,-304,-307,-309,-312,-317,-319,-319,-320,-322,-325,-331,-343,-357,-367,-375,-390,-409,
--424,-426,-422,-421,-428,-440,-455,-476,-502,-527,-544,-555,-563,-572,-581,-589,-595,-601,-605,-607,-606,
--604,-604,-608,-613,-616,-617,-619,-620,-622,-625,-629,-635,-640,-644,-646,-645,-643,-643,-646,-651,-654,
--655,-657,-664,-669,-670,-669,-670,-673,-671,-665,-660,-660,-661,-658,-650,-639,-626,-610,-594,-582,-573,
--563,-548,-533,-518,-504,-490,-476,-460,-446,-436,-428,-422,-412,-398,-378,-357,-339,-323,-309,-292,-273,
--250,-225,-197,-164,-128,-93,-60,-28,6,48,96,149,204,263,326,389,449,507,566,628,695,
-763,833,903,973,1042,1112,1183,1246,1300,1346,1375,1361,1288,1181,1111,1154,1343,1653,2020,2383,2717,
-3039,3363,3662,3885,4019,4111,4215,4331,4424,4483,4529,4569,4590,4599,4618,4647,4646,4597,4542,4533,4560,
-4579,4569,4519,4377,4086,3687,3330,3128,3037,2935,2778,2628,2542,2503,2471,2447,2453,2490,2534,2571,2592,
-2588,2556,2507,2448,2368,2264,2166,2118,2120,2129,2108,2057,1999,1941,1875,1795,1705,1611,1517,1416,1298,
-1162,1025,904,798,691,581,485,413,343,258,168,99,57,21,-27,-92,-166,-236,-286,-310,-330,
--371,-429,-471,-481,-482,-500,-531,-557,-578,-611,-654,-695,-741,-818,-927,-1035,-1103,-1137,-1164,-1196,-1226,
--1248,-1276,-1316,-1354,-1370,-1361,-1345,-1335,-1329,-1313,-1288,-1271,-1278,-1299,-1307,-1296,-1287,-1304,-1334,-1343,-1310,
--1251,-1190,-1131,-1070,-1003,-943,-903,-891,-909,-951,-1004,-1049,-1064,-1031,-955,-872,-835,-880,-995,-1133,-1254,
--1342,-1392,-1399,-1366,-1311,-1258,-1215,-1170,-1115,-1058,-1009,-974,-949,-929,-910,-891,-874,-858,-843,-827,-811,
--797,-780,-761,-744,-734,-729,-721,-705,-690,-685,-690,-697,-698,-699,-705,-713,-718,-719,-722,-729,-738,
--742,-742,-741,-740,-737,-732,-724,-710,-688,-661,-632,-606,-582,-558,-532,-504,-472,-436,-400,-365,-333,
--301,-272,-243,-212,-176,-137,-99,-62,-21,23,67,105,143,185,231,275,314,352,390,426,460,
-496,536,574,605,634,666,701,732,756,781,814,853,890,918,938,952,956,954,951,955,969,
-990,1011,1031,1049,1065,1078,1090,1102,1112,1118,1124,1139,1163,1182,1186,1190,1213,1254,1284,1283,1271,
-1283,1326,1362,1357,1320,1286,1279,1291,1305,1314,1319,1320,1320,1323,1331,1343,1353,1357,1359,1359,1361,
-1364,1370,1375,1376,1376,1391,1394,1396,1395,1391,1391,1395,1400,1402,1403,1401,1397,1395,1397,1404,1410,
-1411,1411,1415,1420,1422,1423,1426,1433,1439,1443,1448,1452,1452,1451,1456,1467,1474,1473,1474,1489,1513,
-1536,1555,1580,1614,1657,1717,1807,1926,2048,2147,2219,2280,2332,2366,2382,2396,2418,2438,2436,2406,2349,
-2278,2210,2161,2134,2109,2067,2010,1954,1909,1867,1826,1786,1752,1720,1687,1654,1619,1579,1537,1498,1464,
-1429,1386,1339,1290,1239,1180,1119,1066,1023,982,937,890,845,801,760,727,704,684,664,649,641,
-629,598,542,474,410,359,316,268,214,166,142,139,131,91,6,-120,-272,-415,-517,-578,-641,
--744,-867,-949,-958,-919,-878,-858,-847,-844,-867,-939,-1050,-1156,-1208,-1197,-1166,-1159,-1168,-1135,-1036,-926,
--888,-943,-1040,-1127,-1203,-1294,-1400,-1499,-1570,-1608,-1616,-1607,-1605,-1630,-1679,-1723,-1737,-1713,-1673,-1677,-1787,
--1995,-2198,-2277,-2211,-2094,-2030,-2041,-2090,-2150,-2219,-2277,-2286,-2231,-2140,-2057,-2009,-1998,-2011,-2018,-1992,-1933,
--1871,-1827,-1794,-1765,-1741,-1719,-1675,-1590,-1482,-1375,-1271,-1171,-1121,-1174,-1305,-1415,-1439,-1428,-1483,-1623,-1773,
--1863,-1903,-1939,-1980,-2011,-2025,-2039,-2053,-2055,-2050,-2052,-2062,-2053,-2020,-1990,-1991,-2011,-2025,-2032,-2051,-2085,
--2113,-2125,-2138,-2167,-2199,-2225,-2254,-2296,-2329,-2323,-2279,-2224,-2173,-2114,-2050,-2008,-2011,-2055,-2131,-2241,-2374,
--2487,-2538,-2543,-2556,-2600,-2653,-2687,-2710,-2738,-2759,-2761,-2757,-2772,-2804,-2831,-2848,-2873,-2913,-2950,-2973,-2995,
--3035,-3090,-3148,-3208,-3275,-3343,-3397,-3440,-3492,-3558,-3633,-3708,-3782,-3854,-3920,-3980,-4046,-4122,-4201,-4275,-4344,
--4413,-4480,-4540,-4593,-4639,-4678,-4715,-4753,-4793,-4827,-4855,-4884,-4923,-4969,-5011,-5043,-5066,-5086,-5103,-5119,-5140,
--5167,-5198,-5230,-5264,-5291,-5310,-5327,-5355,-5393,-5429,-5457,-5484,-5517,-5547,-5564,-5576,-5604,-5654,-5716,-5775,-5821,
--5850,-5863,-5873,-5893,-5918,-5933,-5934,-5937,-5950,-5957,-5939,-5901,-5863,-5835,-5808,-5769,-5717,-5660,-5608,-5565,-5524,
--5485,-5473,-5532,-5665,-5804,-5853,-5793,-5698,-5652,-5664,-5684,-5675,-5648,-5621,-5587,-5530,-5462,-5411,-5389,-5374,-5346,
--5304,-5266,-5238,-5199,-5123,-5015,-4921,-4895,-4939,-4993,-4984,-4884,-4738,-4618,-4566,-4565,-4569,-4546,-4498,-4449,-4405,
--4361,-4315,-4269,-4222,-4159,-4083,-4020,-3994,-3990,-3967,-3908,-3835,-3772,-3717,-3660,-3602,-3554,-3518,-3484,-3444,-3397,
--3341,-3276,-3209,-3147,-3086,-3017,-2944,-2879,-2822,-2756,-2674,-2588,-2509,-2437,-2359,-2273,-2186,-2102,-2023,-1956,-1902,
--1855,-1805,-1757,-1720,-1685,-1635,-1567,-1492,-1422,-1346,-1251,-1143,-1048,-984,-952,-934,-910,-872,-823,-772,-720,
--657,-582,-509,-447,-390,-325,-252,-186,-134,-86,-30,35,108,181,248,309,379,488,645,823,985,
-1119,1253,1412,1592,1771,1929,2060,2163,2238,2292,2339,2388,2441,2497,2561,2632,2698,2747,2779,2812,2860,
-2924,2996,3077,3168,3264,3346,3399,3430,3454,3477,3493,3500,3505,3513,3514,3499,3477,3467,3478,3507,3547,
-3596,3646,3688,3720,3751,3796,3857,3921,3977,4022,4059,4097,4146,4206,4269,4331,4397,4470,4537,4586,4622,
-4662,4716,4772,4823,4873,4930,4982,5011,5015,5013,5023,5043,5061,5074,5089,5112,5143,5180,5221,5260,5291,
-5318,5352,5401,5459,5515,5573,5645,5734,5821,5889,5943,6012,6104,6198,6261,6286,6295,6312,6342,6363,6351,
-6291,6198,6111,6075,6099,6160,6222,6270,6307,6336,6353,6356,6358,6372,6398,6426,6441,6440,6431,6422,6414,
-6396,6368,6337,6314,6288,6240,6169,6103,6070,6074,6094,6114,6126,6132,6132,6138,6159,6192,6218,6221,6208,
-6200,6209,6234,6262,6281,6285,6274,6253,6230,6211,6204,6210,6217,6212,6198,6187,6180,6158,6110,6054,6020,
-6013,6020,6035,6065,6104,6120,6084,6006,5930,5897,5921,5985,6052,6091,6094,6074,6037,5979,5920,5928,6050,
-6234,6356,6348,6280,6279,6383,6511,6577,6577,6569,6581,6598,6596,6581,6565,6548,6522,6488,6456,6424,6387,
-6345,6306,6275,6245,6207,6159,6116,6082,6054,6020,5980,5941,5909,5876,5836,5790,5745,5701,5653,5603,5558,
-5517,5473,5423,5377,5342,5305,5254,5196,5151,5123,5100,5067,5024,4978,4923,4861,4807,4777,4761,4737,4697,
-4658,4631,4605,4568,4528,4504,4493,4472,4431,4385,4351,4323,4279,4217,4154,4101,4014,3795,3381,2841,2375,
-2172,2261,2496,2702,2809,2844,2840,2793,2701,2592,2497,2416,2336,2256,2184,2119,2050,1973,1896,1824,1755,
-1699,1667,1649,1618,1562,1496,1442,1402,1365,1332,1304,1276,1241,1206,1185,1177,1166,1141,1106,1074,1051,
-1037,1031,1025,1010,985,958,935,917,900,883,864,837,805,776,752,728,700,682,681,684,679,
-672,673,674,658,631,621,637,653,646,625,607,590,558,513,474,447,426,409,401,397,378,
-341,302,273,249,225,206,191,157,99,45,25,22,-6,-62,-87,-40,54,123,125,73,4,
--55,-97,-130,-166,-219,-291,-367,-432,-477,-498,-504,-505,-509,-511,-506,-502,-510,-524,-530,-526,-527,
--546,-575,-601,-630,-672,-724,-769,-800,-824,-850,-875,-894,-912,-932,-952,-971,-991,-1011,-1029,-1039,-1043,
--1045,-1046,-1048,-1053,-1059,-1062,-1056,-1047,-1042,-1042,-1041,-1036,-1029,-1022,-1012,-998,-986,-978,-975,-970,-966,
--963,-961,-958,-956,-954,-953,-951,-947,-942,-937,-932,-926,-919,-911,-904,-898,-892,-885,-876,-866,-857,
--846,-833,-819,-807,-798,-789,-779,-768,-757,-743,-729,-715,-703,-691,-681,-674,-668,-659,-645,-631,-618,
--606,-593,-579,-563,-544,-525,-509,-499,-486,-468,-448,-433,-423,-411,-398,-389,-383,-372,-356,-342,-334,
--327,-317,-309,-308,-310,-305,-295,-289,-288,-288,-284,-283,-287,-292,-292,-289,-289,-291,-294,-297,-303,
--308,-312,-315,-317,-320,-321,-325,-332,-341,-350,-361,-376,-389,-393,-387,-387,-402,-430,-456,-474,-486,
--496,-505,-515,-526,-538,-549,-557,-562,-567,-573,-578,-580,-581,-582,-585,-592,-599,-603,-605,-605,-606,
--607,-610,-614,-619,-624,-629,-633,-635,-635,-636,-642,-650,-654,-651,-648,-651,-657,-659,-658,-657,-658,
--658,-654,-650,-648,-648,-644,-636,-624,-610,-594,-578,-567,-558,-550,-538,-521,-502,-485,-470,-456,-442,
--430,-420,-412,-402,-388,-369,-349,-331,-316,-302,-288,-272,-254,-233,-209,-181,-148,-112,-77,-45,-13,
-20,62,113,168,223,277,334,394,454,510,563,619,681,751,827,901,968,1034,1110,1196,1275,
-1336,1382,1421,1442,1415,1330,1222,1158,1199,1362,1621,1934,2281,2665,3073,3449,3722,3880,3982,4088,4201,
-4288,4348,4410,4481,4533,4552,4563,4582,4589,4567,4538,4533,4546,4560,4583,4610,4554,4312,3905,3504,3259,
-3150,3048,2883,2699,2563,2480,2424,2388,2376,2376,2374,2382,2414,2454,2473,2463,2435,2389,2320,2243,2191,
-2181,2185,2165,2113,2047,1978,1902,1810,1709,1611,1522,1428,1314,1181,1049,934,827,715,603,514,451,
-388,303,211,140,95,58,9,-53,-124,-190,-234,-256,-281,-334,-406,-459,-477,-482,-493,-508,-515,
--528,-567,-625,-677,-722,-785,-881,-985,-1060,-1100,-1125,-1154,-1188,-1221,-1252,-1279,-1302,-1318,-1330,-1337,-1343,
--1346,-1345,-1342,-1340,-1344,-1347,-1335,-1310,-1292,-1296,-1311,-1307,-1272,-1223,-1179,-1139,-1092,-1034,-975,-929,-908,
--917,-950,-983,-1000,-1000,-985,-954,-907,-863,-852,-893,-983,-1105,-1239,-1349,-1398,-1374,-1309,-1247,-1202,-1156,
--1093,-1024,-971,-938,-915,-894,-876,-864,-858,-849,-838,-824,-810,-795,-778,-760,-745,-736,-732,-726,-713,
--699,-690,-687,-688,-688,-691,-696,-703,-708,-712,-717,-724,-729,-733,-736,-739,-739,-736,-732,-726,-713,
--692,-664,-635,-609,-583,-556,-531,-503,-469,-429,-389,-354,-323,-294,-265,-236,-204,-167,-127,-89,-54,
--15,27,70,109,147,189,236,282,322,362,402,440,473,507,545,582,612,639,671,707,736,
-756,776,807,846,881,905,922,937,948,949,947,952,970,994,1016,1035,1052,1067,1078,1089,1102,
-1114,1120,1122,1133,1153,1171,1177,1185,1216,1263,1290,1282,1272,1305,1376,1426,1412,1351,1298,1286,1298,
-1308,1310,1312,1317,1321,1323,1328,1339,1351,1360,1365,1367,1370,1375,1381,1386,1389,1391,1406,1411,1416,
-1416,1413,1411,1414,1418,1419,1418,1416,1415,1415,1417,1422,1427,1429,1430,1433,1436,1439,1441,1448,1457,
-1463,1466,1469,1472,1474,1473,1476,1483,1487,1487,1490,1504,1525,1544,1561,1587,1627,1678,1746,1842,1967,
-2092,2187,2242,2275,2305,2335,2361,2385,2407,2420,2418,2397,2353,2288,2218,2163,2131,2106,2068,2016,1965,
-1922,1882,1842,1803,1768,1737,1705,1674,1641,1602,1558,1514,1476,1441,1402,1359,1311,1257,1198,1140,1091,
-1049,1009,967,923,878,833,797,773,753,730,706,691,684,668,628,569,511,465,431,396,354,
-304,256,223,200,166,97,-10,-140,-265,-362,-421,-459,-520,-633,-777,-894,-939,-923,-882,-846,-822,
--815,-844,-922,-1035,-1140,-1196,-1198,-1183,-1185,-1193,-1155,-1053,-941,-896,-941,-1028,-1106,-1177,-1264,-1368,-1461,
--1521,-1547,-1549,-1543,-1540,-1552,-1573,-1588,-1584,-1560,-1545,-1589,-1736,-1959,-2155,-2218,-2145,-2030,-1969,-1984,-2037,
--2095,-2143,-2160,-2126,-2043,-1941,-1853,-1796,-1776,-1788,-1808,-1809,-1789,-1766,-1752,-1735,-1705,-1665,-1615,-1538,-1422,
--1292,-1178,-1089,-1028,-1028,-1120,-1268,-1379,-1404,-1404,-1475,-1621,-1758,-1826,-1851,-1886,-1935,-1965,-1967,-1964,-1972,
--1977,-1975,-1979,-1991,-1992,-1969,-1943,-1938,-1951,-1961,-1970,-1994,-2030,-2055,-2062,-2070,-2095,-2129,-2158,-2189,-2218,
--2218,-2155,-2046,-1948,-1906,-1911,-1934,-1961,-1998,-2051,-2125,-2228,-2346,-2433,-2459,-2450,-2462,-2513,-2570,-2601,-2617,
--2637,-2656,-2661,-2660,-2675,-2705,-2731,-2752,-2782,-2824,-2861,-2883,-2907,-2948,-3003,-3058,-3116,-3179,-3240,-3289,-3332,
--3387,-3460,-3542,-3620,-3694,-3764,-3828,-3887,-3950,-4023,-4098,-4167,-4231,-4294,-4358,-4418,-4474,-4524,-4568,-4604,-4638,
--4675,-4711,-4745,-4781,-4824,-4872,-4917,-4952,-4975,-4988,-4997,-5008,-5030,-5061,-5095,-5129,-5161,-5188,-5208,-5229,-5260,
--5301,-5338,-5367,-5397,-5433,-5464,-5481,-5496,-5531,-5592,-5662,-5725,-5770,-5796,-5809,-5820,-5840,-5863,-5878,-5886,-5899,
--5915,-5916,-5892,-5857,-5833,-5822,-5810,-5782,-5734,-5670,-5598,-5529,-5468,-5418,-5405,-5468,-5608,-5749,-5798,-5740,-5655,
--5626,-5648,-5660,-5635,-5598,-5572,-5539,-5479,-5407,-5354,-5330,-5313,-5288,-5260,-5238,-5209,-5152,-5066,-4981,-4940,-4964,
--5023,-5053,-5002,-4877,-4737,-4646,-4620,-4625,-4614,-4576,-4524,-4475,-4429,-4381,-4340,-4307,-4266,-4196,-4109,-4049,-4040,
--4052,-4035,-3976,-3903,-3843,-3789,-3729,-3668,-3619,-3581,-3542,-3495,-3444,-3387,-3322,-3256,-3195,-3137,-3074,-3006,-2943,
--2884,-2818,-2740,-2661,-2592,-2524,-2447,-2361,-2277,-2199,-2123,-2051,-1992,-1943,-1897,-1848,-1799,-1751,-1697,-1633,-1559,
--1480,-1396,-1308,-1220,-1137,-1063,-999,-943,-892,-844,-808,-792,-783,-756,-697,-625,-565,-517,-464,-397,-330,
--274,-225,-167,-96,-16,63,139,213,304,438,618,807,968,1099,1232,1390,1563,1726,1866,1984,2079,
-2147,2196,2244,2300,2361,2419,2482,2553,2621,2671,2703,2733,2779,2842,2917,3005,3108,3216,3304,3354,3377,
-3394,3415,3437,3453,3462,3461,3446,3418,3391,3381,3389,3411,3447,3503,3567,3621,3655,3680,3715,3770,3838,
-3904,3960,4001,4034,4069,4111,4160,4215,4281,4357,4432,4492,4540,4590,4646,4698,4739,4777,4821,4866,4897,
-4912,4925,4946,4977,5009,5035,5058,5085,5122,5167,5212,5245,5267,5287,5320,5370,5426,5478,5530,5593,5673,
-5757,5826,5884,5948,6030,6118,6183,6214,6228,6246,6277,6309,6318,6283,6205,6116,6061,6062,6104,6158,6208,
-6253,6288,6304,6304,6306,6327,6365,6402,6420,6417,6406,6399,6396,6390,6375,6356,6338,6312,6261,6184,6109,
-6068,6070,6096,6125,6141,6141,6129,6121,6129,6148,6160,6155,6150,6166,6205,6248,6275,6281,6271,6248,6218,
-6190,6175,6179,6193,6198,6180,6144,6117,6110,6110,6093,6056,6016,5995,6003,6043,6102,6139,6109,6007,5883,
-5802,5799,5861,5953,6041,6095,6107,6094,6069,6030,5975,5942,5985,6100,6215,6266,6278,6330,6442,6551,6595,
-6587,6582,6602,6619,6615,6599,6589,6577,6550,6514,6483,6455,6419,6375,6335,6307,6282,6248,6204,6160,6122,
-6087,6050,6013,5980,5946,5907,5861,5812,5769,5731,5692,5647,5597,5543,5487,5435,5396,5370,5343,5304,5263,
-5236,5222,5201,5158,5102,5045,4986,4916,4843,4789,4763,4751,4734,4705,4669,4628,4586,4551,4527,4511,4493,
-4469,4441,4414,4389,4357,4305,4225,4124,3995,3787,3431,2941,2464,2200,2227,2437,2652,2782,2842,2863,2832,
-2738,2615,2510,2430,2355,2274,2200,2136,2068,1988,1903,1823,1754,1703,1674,1657,1628,1572,1503,1443,1400,
-1365,1332,1303,1273,1239,1205,1182,1171,1158,1136,1110,1086,1067,1052,1042,1033,1019,995,968,942,918,
-897,880,862,836,806,778,754,728,700,679,671,668,663,661,667,664,639,607,603,629,650,
-638,605,575,552,525,497,483,483,487,494,508,516,491,428,354,294,251,218,197,183,156,
-107,57,31,8,-47,-126,-165,-116,-9,80,107,81,35,-10,-52,-89,-128,-177,-242,-314,-377,
--420,-443,-453,-463,-477,-486,-490,-496,-513,-532,-537,-531,-534,-557,-587,-609,-630,-664,-712,-757,-791,
--817,-842,-865,-886,-907,-933,-958,-979,-999,-1020,-1037,-1048,-1055,-1059,-1061,-1062,-1065,-1070,-1071,-1065,-1057,
--1054,-1056,-1055,-1049,-1044,-1040,-1032,-1017,-1002,-994,-989,-983,-974,-967,-963,-961,-959,-959,-959,-958,-952,
--946,-942,-936,-928,-919,-911,-905,-900,-892,-882,-871,-861,-851,-841,-829,-818,-808,-798,-786,-775,-763,
--751,-737,-722,-708,-694,-680,-667,-659,-651,-641,-627,-612,-599,-588,-577,-565,-550,-533,-515,-500,-488,
--473,-454,-436,-423,-411,-398,-384,-375,-369,-359,-344,-331,-323,-316,-306,-298,-296,-296,-290,-280,-274,
--273,-273,-270,-268,-272,-276,-277,-276,-277,-280,-284,-289,-296,-301,-306,-309,-313,-318,-320,-321,-323,
--327,-332,-342,-352,-358,-357,-357,-375,-413,-458,-490,-504,-504,-497,-490,-489,-498,-514,-528,-536,-538,
--540,-544,-549,-554,-560,-566,-573,-581,-588,-594,-598,-602,-604,-606,-607,-610,-614,-618,-623,-626,-628,
--629,-631,-638,-646,-649,-645,-640,-639,-644,-646,-645,-643,-643,-642,-639,-635,-632,-631,-627,-618,-605,
--592,-578,-564,-550,-540,-531,-520,-505,-485,-466,-449,-435,-422,-409,-399,-391,-379,-362,-340,-320,-305,
--294,-282,-268,-250,-229,-207,-183,-156,-127,-97,-67,-35,0,38,82,132,185,238,290,342,396,
-452,506,558,611,670,739,820,901,975,1041,1116,1205,1295,1365,1411,1445,1475,1485,1452,1371,1267,
-1192,1197,1307,1524,1831,2214,2640,3043,3355,3561,3709,3848,3977,4072,4147,4236,4345,4436,4482,4505,4527,
-4546,4548,4545,4549,4546,4538,4560,4625,4639,4468,4100,3693,3418,3282,3167,2993,2788,2614,2488,2396,2331,
-2279,2216,2137,2092,2129,2230,2329,2381,2394,2389,2364,2315,2265,2241,2239,2226,2180,2107,2020,1924,1816,
-1703,1600,1515,1430,1326,1204,1084,975,863,740,624,541,491,437,356,263,189,139,97,45,-18,
--88,-153,-197,-220,-247,-300,-371,-428,-458,-473,-487,-493,-489,-499,-542,-607,-662,-701,-749,-824,-909,
--978,-1024,-1062,-1111,-1169,-1225,-1262,-1278,-1285,-1298,-1322,-1345,-1358,-1369,-1388,-1413,-1430,-1428,-1405,-1366,-1324,
--1295,-1286,-1281,-1260,-1226,-1195,-1175,-1154,-1123,-1080,-1032,-986,-954,-945,-955,-964,-958,-947,-943,-937,-907,
--847,-787,-765,-811,-933,-1111,-1290,-1396,-1397,-1327,-1248,-1187,-1131,-1062,-992,-942,-913,-890,-865,-847,-842,
--843,-839,-826,-812,-801,-789,-774,-757,-741,-730,-723,-719,-714,-706,-695,-685,-681,-682,-687,-693,-698,
--703,-710,-718,-724,-727,-731,-738,-744,-746,-744,-740,-734,-721,-697,-666,-636,-606,-578,-551,-526,-499,
--464,-422,-380,-344,-314,-285,-256,-227,-195,-156,-114,-76,-41,-6,33,75,113,151,194,242,289,
-331,373,416,456,490,522,555,589,618,644,674,706,731,747,765,797,838,871,889,900,915,
-933,943,947,957,979,1006,1028,1045,1059,1072,1081,1089,1101,1116,1126,1130,1139,1158,1176,1184,1191,
-1216,1253,1271,1261,1258,1305,1389,1444,1426,1359,1305,1295,1309,1317,1314,1314,1322,1330,1332,1335,1344,
-1356,1366,1371,1375,1380,1387,1394,1399,1402,1406,1420,1423,1427,1428,1425,1425,1428,1432,1433,1433,1434,
-1437,1439,1440,1442,1445,1448,1450,1451,1452,1454,1459,1469,1478,1483,1485,1488,1494,1498,1500,1501,1505,
-1511,1516,1523,1536,1553,1569,1589,1618,1660,1712,1782,1881,2005,2126,2209,2248,2263,2277,2302,2333,2365,
-2392,2407,2407,2391,2356,2298,2224,2159,2117,2090,2061,2022,1980,1941,1903,1863,1826,1791,1759,1726,1695,
-1662,1624,1578,1529,1485,1448,1414,1378,1333,1276,1212,1154,1109,1074,1041,1005,964,918,871,835,812,
-791,762,732,715,706,686,643,594,557,534,515,494,469,434,381,313,236,148,43,-70,-165,
--221,-239,-245,-270,-337,-451,-587,-703,-768,-780,-761,-739,-732,-754,-814,-910,-1022,-1120,-1175,-1183,-1170,
--1165,-1168,-1146,-1086,-1018,-990,-1014,-1057,-1096,-1144,-1223,-1326,-1415,-1463,-1476,-1473,-1469,-1468,-1465,-1456,-1443,
--1434,-1438,-1470,-1556,-1717,-1925,-2096,-2146,-2072,-1957,-1892,-1902,-1952,-1999,-2014,-1987,-1920,-1834,-1754,-1693,-1652,
--1634,-1642,-1663,-1677,-1678,-1678,-1682,-1670,-1626,-1555,-1468,-1363,-1237,-1105,-994,-920,-899,-951,-1082,-1237,-1338,
--1364,-1385,-1479,-1627,-1746,-1792,-1806,-1841,-1893,-1918,-1910,-1898,-1903,-1912,-1915,-1922,-1936,-1942,-1924,-1896,-1883,
--1888,-1897,-1909,-1934,-1967,-1988,-1995,-2009,-2043,-2082,-2110,-2133,-2151,-2131,-2034,-1880,-1745,-1696,-1737,-1823,-1917,
--2002,-2076,-2143,-2218,-2297,-2352,-2362,-2349,-2362,-2414,-2470,-2497,-2505,-2519,-2543,-2562,-2574,-2594,-2621,-2645,-2665,
--2692,-2729,-2762,-2786,-2814,-2858,-2913,-2968,-3023,-3081,-3137,-3184,-3229,-3289,-3368,-3453,-3532,-3605,-3672,-3733,-3790,
--3852,-3921,-3991,-4056,-4116,-4177,-4238,-4297,-4354,-4408,-4455,-4494,-4529,-4567,-4608,-4648,-4689,-4733,-4780,-4822,-4855,
--4874,-4881,-4884,-4895,-4920,-4956,-4991,-5025,-5056,-5085,-5110,-5137,-5174,-5216,-5254,-5285,-5315,-5350,-5380,-5401,-5423,
--5467,-5535,-5608,-5669,-5710,-5733,-5747,-5761,-5782,-5802,-5817,-5831,-5852,-5870,-5867,-5839,-5809,-5795,-5795,-5789,-5764,
--5718,-5649,-5566,-5479,-5401,-5341,-5326,-5394,-5542,-5687,-5735,-5676,-5596,-5574,-5597,-5605,-5577,-5545,-5526,-5494,-5429,
--5354,-5303,-5278,-5255,-5230,-5217,-5212,-5182,-5108,-5018,-4964,-4976,-5038,-5095,-5092,-5008,-4872,-4746,-4681,-4672,-4673,
--4645,-4594,-4542,-4499,-4453,-4402,-4361,-4335,-4302,-4232,-4143,-4085,-4082,-4101,-4088,-4033,-3965,-3908,-3856,-3797,-3737,
--3688,-3645,-3597,-3543,-3486,-3427,-3361,-3295,-3238,-3188,-3135,-3075,-3013,-2953,-2886,-2811,-2736,-2668,-2598,-2519,-2434,
--2357,-2287,-2216,-2142,-2076,-2024,-1979,-1929,-1874,-1817,-1762,-1702,-1629,-1542,-1451,-1369,-1300,-1233,-1153,-1060,-963,
--875,-810,-783,-795,-818,-808,-744,-657,-592,-561,-540,-503,-452,-399,-348,-293,-233,-165,-85,10,122,
-252,413,599,787,950,1086,1220,1367,1517,1655,1777,1889,1984,2055,2108,2163,2228,2298,2365,2431,2502,
-2567,2610,2633,2655,2693,2752,2829,2925,3035,3145,3230,3281,3307,3328,3354,3381,3404,3416,3407,3375,3332,
-3298,3288,3298,3323,3367,3434,3509,3568,3601,3622,3652,3703,3769,3838,3897,3940,3969,3994,4022,4056,4099,
-4158,4234,4313,4385,4448,4511,4575,4628,4666,4697,4727,4760,4789,4815,4842,4875,4915,4960,5003,5042,5077,
-5116,5160,5200,5226,5241,5260,5294,5341,5392,5440,5489,5548,5622,5701,5769,5822,5874,5941,6021,6091,6136,
-6162,6187,6225,6268,6295,6282,6223,6139,6069,6041,6054,6092,6140,6191,6234,6257,6259,6262,6286,6326,6364,
-6384,6385,6379,6375,6376,6373,6364,6348,6330,6303,6255,6186,6121,6084,6084,6108,6135,6152,6148,6128,6109,
-6108,6119,6121,6108,6103,6131,6183,6231,6252,6250,6236,6212,6180,6147,6128,6129,6141,6144,6123,6082,6047,
-6042,6058,6063,6033,5980,5943,5961,6036,6124,6157,6093,5958,5830,5776,5800,5867,5941,6005,6044,6045,6019,
-5990,5966,5935,5904,5909,5974,6074,6173,6274,6403,6545,6635,6639,6597,6581,6604,6628,6627,6613,6605,6597,
-6572,6538,6509,6484,6448,6401,6357,6327,6302,6272,6237,6202,6164,6121,6077,6039,6005,5966,5921,5878,5842,
-5808,5770,5725,5677,5626,5571,5514,5465,5434,5419,5406,5387,5369,5359,5347,5309,5236,5149,5076,5021,4962,
-4890,4821,4778,4765,4762,4744,4702,4652,4609,4580,4560,4544,4531,4521,4505,4477,4444,4418,4385,4316,4198,
-4034,3806,3460,2987,2511,2225,2224,2418,2633,2773,2851,2891,2872,2778,2647,2536,2456,2380,2296,2220,2156,
-2087,1999,1903,1820,1756,1709,1679,1657,1625,1571,1505,1447,1404,1369,1333,1299,1268,1236,1205,1182,1168,
-1157,1143,1126,1108,1089,1069,1051,1036,1019,999,974,947,918,892,872,855,835,809,783,757,730,
-705,687,679,671,658,652,653,645,618,592,597,629,649,633,599,570,545,515,490,487,506,
-534,573,626,669,656,573,454,346,270,220,191,173,146,102,59,36,13,-45,-130,-186,-169,
--101,-38,-11,-9,-17,-32,-57,-87,-117,-149,-190,-239,-285,-322,-351,-377,-408,-440,-466,-483,-500,
--523,-544,-554,-556,-569,-596,-621,-634,-645,-670,-709,-748,-781,-812,-843,-869,-891,-913,-940,-966,-991,
--1015,-1038,-1056,-1064,-1068,-1072,-1076,-1077,-1077,-1080,-1080,-1075,-1069,-1067,-1068,-1064,-1058,-1056,-1057,-1053,-1038,
--1022,-1014,-1008,-999,-986,-976,-972,-969,-965,-965,-966,-964,-958,-951,-945,-940,-932,-921,-913,-908,-902,
--892,-879,-867,-856,-845,-834,-826,-818,-808,-797,-784,-773,-762,-749,-735,-721,-707,-693,-676,-660,-648,
--638,-626,-611,-595,-581,-570,-558,-547,-534,-520,-505,-490,-476,-460,-442,-427,-415,-402,-386,-371,-361,
--354,-344,-331,-320,-313,-307,-298,-289,-285,-282,-275,-266,-261,-260,-260,-258,-258,-261,-264,-264,-265,
--268,-272,-276,-281,-288,-293,-296,-299,-303,-309,-314,-316,-317,-317,-320,-327,-334,-338,-340,-355,-389,
--432,-467,-484,-488,-488,-484,-477,-473,-480,-495,-510,-518,-518,-517,-519,-525,-535,-546,-558,-567,-576,
--583,-590,-596,-603,-609,-612,-612,-612,-614,-618,-620,-621,-622,-622,-624,-627,-632,-635,-634,-630,-628,
--629,-631,-631,-629,-627,-624,-619,-612,-608,-607,-602,-593,-580,-568,-558,-548,-534,-521,-510,-500,-488,
--470,-450,-432,-415,-398,-382,-370,-362,-352,-336,-316,-296,-281,-269,-258,-243,-224,-202,-177,-150,-123,
--97,-74,-50,-20,16,58,103,151,200,252,303,355,406,456,507,561,617,676,741,817,902,
-984,1058,1133,1217,1308,1387,1440,1470,1492,1511,1514,1482,1401,1288,1192,1172,1258,1452,1740,2093,2462,
-2790,3052,3265,3460,3634,3777,3901,4038,4184,4303,4376,4424,4471,4509,4528,4533,4536,4522,4499,4514,4590,
-4646,4541,4242,3881,3613,3459,3325,3142,2928,2728,2551,2395,2272,2173,2063,1930,1842,1877,2027,2197,2304,
-2348,2368,2373,2352,2311,2284,2284,2283,2249,2176,2079,1970,1847,1721,1609,1519,1434,1335,1223,1115,1013,
-899,768,650,575,536,492,419,330,254,197,144,84,16,-56,-122,-168,-195,-223,-271,-336,-395,
--435,-463,-482,-489,-490,-507,-552,-608,-650,-682,-727,-795,-867,-924,-969,-1021,-1090,-1171,-1241,-1282,-1290,
--1286,-1293,-1317,-1343,-1360,-1380,-1418,-1465,-1494,-1488,-1449,-1393,-1338,-1298,-1271,-1244,-1212,-1186,-1180,-1186,-1182,
--1161,-1129,-1093,-1051,-1005,-971,-956,-949,-935,-921,-915,-906,-871,-808,-747,-723,-760,-870,-1045,-1236,-1367,
--1387,-1319,-1228,-1153,-1088,-1021,-959,-920,-898,-875,-848,-829,-825,-826,-819,-804,-791,-783,-775,-763,-747,
--731,-716,-707,-704,-705,-702,-692,-681,-676,-680,-688,-694,-697,-703,-713,-723,-729,-734,-741,-752,-760,
--763,-762,-759,-752,-736,-710,-679,-647,-615,-584,-555,-528,-499,-463,-419,-376,-337,-304,-273,-244,-215,
--184,-146,-104,-66,-31,3,42,83,122,160,203,251,299,343,385,428,468,501,530,561,594,
-621,645,670,698,722,738,757,790,831,862,874,880,895,920,941,953,967,992,1020,1042,1057,
-1070,1082,1087,1089,1096,1112,1128,1139,1151,1171,1193,1203,1206,1217,1237,1246,1238,1240,1284,1355,1399,
-1382,1330,1294,1296,1313,1319,1314,1314,1324,1333,1336,1339,1349,1362,1373,1379,1385,1394,1403,1412,1417,
-1418,1420,1434,1433,1435,1436,1436,1437,1441,1447,1451,1453,1456,1460,1464,1464,1463,1466,1469,1471,1470,
-1469,1472,1480,1492,1502,1507,1510,1514,1521,1526,1529,1530,1534,1542,1551,1561,1573,1589,1608,1633,1664,
-1704,1753,1824,1927,2049,2155,2218,2240,2247,2263,2289,2321,2354,2383,2398,2396,2379,2349,2299,2231,2161,
-2109,2078,2056,2028,1994,1957,1919,1881,1847,1815,1784,1751,1717,1682,1644,1600,1553,1509,1471,1439,1407,
-1363,1302,1230,1166,1121,1094,1072,1045,1009,964,917,879,852,826,793,761,740,722,690,645,608,
-593,594,594,593,589,563,490,369,225,84,-40,-137,-181,-162,-107,-68,-80,-142,-229,-319,-399,
--462,-503,-526,-546,-584,-655,-759,-880,-997,-1090,-1142,-1150,-1129,-1107,-1098,-1099,-1097,-1094,-1098,-1102,-1098,
--1092,-1115,-1182,-1275,-1354,-1394,-1404,-1404,-1404,-1402,-1386,-1356,-1332,-1338,-1382,-1460,-1567,-1711,-1881,-2022,-2068,
--2004,-1890,-1810,-1801,-1840,-1872,-1860,-1803,-1724,-1657,-1611,-1576,-1540,-1513,-1509,-1525,-1544,-1558,-1574,-1590,-1580,
--1522,-1423,-1309,-1196,-1084,-973,-875,-816,-823,-912,-1063,-1212,-1297,-1328,-1373,-1486,-1631,-1733,-1766,-1774,-1804,
--1845,-1862,-1851,-1841,-1850,-1863,-1871,-1879,-1893,-1896,-1876,-1845,-1828,-1829,-1837,-1848,-1870,-1897,-1916,-1929,-1958,
--2006,-2047,-2064,-2070,-2078,-2058,-1964,-1806,-1661,-1603,-1646,-1752,-1876,-1995,-2086,-2143,-2182,-2219,-2250,-2258,-2254,
--2272,-2321,-2372,-2396,-2401,-2415,-2446,-2479,-2504,-2524,-2545,-2563,-2578,-2599,-2629,-2659,-2686,-2720,-2767,-2823,-2877,
--2928,-2981,-3032,-3081,-3133,-3202,-3284,-3367,-3442,-3509,-3572,-3630,-3685,-3745,-3812,-3881,-3946,-4007,-4067,-4126,-4182,
--4236,-4288,-4337,-4381,-4424,-4468,-4514,-4558,-4600,-4644,-4686,-4721,-4746,-4760,-4767,-4773,-4789,-4819,-4856,-4891,-4922,
--4955,-4989,-5022,-5055,-5094,-5137,-5176,-5207,-5238,-5270,-5299,-5324,-5356,-5408,-5478,-5548,-5602,-5637,-5657,-5673,-5692,
--5713,-5732,-5747,-5766,-5793,-5814,-5810,-5783,-5756,-5746,-5746,-5737,-5711,-5664,-5595,-5507,-5412,-5325,-5258,-5241,-5313,
--5467,-5617,-5667,-5610,-5534,-5515,-5537,-5543,-5518,-5496,-5486,-5455,-5388,-5315,-5271,-5248,-5224,-5202,-5200,-5199,-5155,
--5061,-4970,-4949,-5007,-5091,-5136,-5105,-5003,-4869,-4761,-4714,-4714,-4710,-4671,-4611,-4559,-4520,-4474,-4419,-4376,-4357,
--4333,-4271,-4184,-4124,-4118,-4137,-4132,-4087,-4028,-3974,-3923,-3866,-3809,-3760,-3711,-3654,-3591,-3530,-3467,-3399,-3332,
--3278,-3235,-3190,-3135,-3076,-3017,-2955,-2886,-2813,-2742,-2666,-2583,-2500,-2426,-2361,-2294,-2222,-2156,-2101,-2053,-2002,
--1945,-1887,-1831,-1771,-1698,-1607,-1513,-1433,-1373,-1316,-1239,-1134,-1013,-900,-819,-790,-810,-836,-811,-718,-602,
--530,-522,-542,-544,-515,-465,-410,-361,-322,-282,-218,-108,44,220,403,586,763,927,1075,1211,1341,
-1462,1574,1683,1792,1892,1971,2035,2097,2165,2237,2311,2387,2463,2526,2561,2573,2581,2607,2660,2740,2840,
-2948,3046,3122,3175,3216,3253,3286,3318,3347,3364,3353,3311,3255,3216,3207,3225,3262,3319,3394,3469,3522,
-3548,3566,3595,3644,3708,3775,3834,3878,3907,3926,3942,3963,3998,4054,4131,4215,4293,4364,4433,4500,4557,
-4599,4629,4651,4670,4695,4729,4771,4816,4863,4918,4978,5033,5077,5115,5151,5182,5202,5215,5235,5267,5306,
-5346,5388,5439,5502,5577,5655,5723,5773,5812,5860,5926,5997,6055,6098,6136,6182,6231,6266,6270,6231,6159,
-6081,6025,6005,6020,6063,6121,6173,6202,6209,6217,6243,6283,6320,6342,6350,6350,6348,6347,6346,6343,6334,
-6318,6290,6244,6187,6137,6109,6106,6118,6135,6146,6140,6119,6101,6105,6122,6126,6109,6094,6107,6141,6169,
-6179,6179,6178,6167,6137,6099,6070,6061,6068,6076,6066,6035,5999,5986,6001,6013,5987,5929,5892,5924,6018,
-6111,6128,6049,5926,5838,5825,5861,5905,5939,5972,5997,5993,5960,5927,5916,5912,5899,5889,5907,5964,6058,
-6197,6384,6571,6677,6672,6613,6584,6604,6632,6634,6625,6621,6614,6590,6556,6528,6503,6468,6424,6384,6353,
-6322,6288,6258,6231,6197,6150,6101,6062,6027,5983,5937,5904,5883,5854,5802,5741,5691,5656,5621,5575,5526,
-5492,5480,5477,5471,5462,5450,5424,5363,5265,5156,5075,5030,4996,4944,4875,4817,4789,4781,4766,4730,4684,
-4649,4631,4616,4598,4586,4581,4568,4534,4490,4462,4447,4406,4308,4143,3892,3512,3011,2518,2229,2232,2427,
-2638,2774,2856,2909,2903,2817,2688,2576,2493,2412,2323,2244,2178,2102,2002,1899,1817,1760,1716,1680,1650,
-1614,1563,1503,1452,1414,1378,1336,1294,1259,1228,1201,1179,1167,1161,1155,1145,1130,1108,1082,1056,1033,
-1012,992,972,949,919,888,864,848,832,812,787,760,731,707,694,689,681,667,654,647,634,
-611,595,608,636,646,628,604,589,570,535,497,485,503,539,598,686,770,788,707,561,413,
-304,237,202,180,149,102,58,35,17,-28,-106,-178,-209,-206,-195,-184,-162,-132,-109,-109,-125,
--143,-159,-176,-196,-221,-251,-286,-326,-370,-415,-455,-487,-515,-541,-564,-580,-596,-620,-648,-664,-667,
--671,-691,-720,-747,-774,-807,-844,-875,-898,-920,-946,-971,-997,-1025,-1054,-1074,-1082,-1082,-1085,-1089,-1090,
--1090,-1090,-1090,-1086,-1082,-1080,-1078,-1072,-1066,-1068,-1074,-1071,-1057,-1041,-1033,-1028,-1017,-1002,-992,-988,-983,
--977,-973,-973,-971,-964,-956,-950,-945,-936,-925,-917,-910,-903,-891,-879,-868,-857,-844,-833,-824,-815,
--805,-792,-780,-769,-759,-746,-732,-719,-707,-693,-675,-657,-642,-630,-618,-602,-585,-569,-556,-544,-532,
--520,-508,-495,-481,-465,-448,-432,-419,-406,-392,-376,-361,-350,-340,-328,-316,-307,-302,-297,-289,-281,
--274,-268,-261,-255,-251,-250,-250,-250,-251,-253,-253,-254,-256,-261,-264,-266,-269,-275,-280,-283,-285,
--289,-295,-301,-306,-309,-311,-316,-323,-330,-336,-348,-374,-408,-431,-432,-420,-418,-433,-454,-464,-466,
--470,-482,-493,-500,-500,-501,-505,-515,-530,-546,-559,-568,-576,-584,-590,-597,-604,-611,-614,-613,-611,
--613,-616,-617,-616,-615,-615,-614,-613,-613,-615,-618,-619,-617,-614,-613,-613,-613,-610,-605,-596,-588,
--582,-579,-575,-566,-554,-543,-534,-526,-516,-503,-492,-482,-470,-453,-433,-414,-395,-374,-354,-339,-331,
--324,-313,-297,-278,-261,-246,-232,-217,-199,-177,-152,-125,-97,-72,-50,-26,3,40,82,126,170,
-216,265,318,372,423,470,518,573,635,697,758,824,902,989,1073,1151,1230,1312,1392,1456,1495,
-1515,1526,1537,1536,1498,1413,1301,1211,1182,1232,1364,1579,1858,2160,2446,2708,2954,3184,3395,3596,3795,
-3981,4124,4222,4304,4390,4462,4501,4512,4510,4493,4468,4478,4547,4609,4546,4327,4053,3842,3706,3571,3392,
-3188,2977,2743,2494,2280,2131,2008,1872,1769,1788,1940,2130,2256,2307,2330,2346,2341,2312,2289,2290,2297,
-2277,2221,2141,2041,1918,1782,1658,1556,1460,1352,1238,1135,1042,935,810,697,625,587,546,478,396,
-320,252,185,114,43,-25,-88,-136,-170,-203,-252,-313,-371,-415,-447,-469,-484,-504,-541,-589,-624,
--642,-668,-728,-814,-893,-946,-986,-1037,-1107,-1183,-1247,-1280,-1284,-1279,-1285,-1308,-1335,-1360,-1392,-1439,-1487,
--1513,-1506,-1469,-1415,-1356,-1303,-1255,-1210,-1174,-1165,-1188,-1217,-1222,-1199,-1168,-1140,-1102,-1045,-987,-949,-932,
--924,-917,-908,-883,-839,-799,-797,-839,-903,-978,-1075,-1190,-1279,-1296,-1243,-1166,-1100,-1044,-988,-940,-911,
--894,-873,-846,-827,-819,-812,-799,-783,-771,-765,-757,-745,-733,-720,-706,-694,-688,-689,-688,-682,-673,
--670,-676,-686,-692,-697,-704,-714,-725,-734,-743,-755,-766,-773,-776,-776,-775,-767,-749,-724,-696,-667,
--636,-603,-570,-537,-502,-462,-418,-373,-330,-290,-254,-224,-197,-168,-132,-94,-57,-24,11,51,94,
-135,174,217,264,311,355,396,435,471,501,531,563,596,622,642,664,692,720,743,765,797,
-834,862,871,874,890,920,949,967,983,1006,1033,1053,1066,1079,1091,1095,1091,1092,1105,1125,1142,
-1157,1178,1202,1218,1222,1225,1233,1239,1237,1241,1267,1308,1332,1322,1296,1285,1296,1311,1314,1309,1310,
-1318,1326,1330,1338,1352,1367,1380,1390,1400,1410,1421,1429,1434,1435,1434,1451,1448,1449,1453,1456,1459,
-1465,1471,1475,1476,1478,1482,1486,1486,1486,1488,1491,1491,1489,1488,1493,1505,1518,1530,1539,1545,1550,
-1554,1557,1559,1562,1568,1576,1585,1595,1609,1627,1650,1678,1709,1742,1787,1862,1973,2094,2182,2215,2215,
-2220,2246,2282,2316,2347,2374,2389,2383,2361,2333,2296,2244,2183,2130,2094,2069,2043,2009,1970,1930,1893,
-1861,1832,1803,1771,1735,1698,1661,1624,1586,1549,1514,1482,1449,1401,1331,1250,1178,1132,1109,1095,1076,
-1046,1006,961,924,894,866,834,803,775,743,696,645,616,622,646,669,686,689,651,541,366,
-176,19,-92,-156,-162,-106,-19,42,46,9,-31,-62,-97,-151,-217,-284,-352,-436,-549,-685,-825,
--950,-1045,-1101,-1114,-1090,-1053,-1033,-1046,-1087,-1135,-1164,-1160,-1129,-1103,-1112,-1161,-1225,-1278,-1311,-1331,-1348,
--1358,-1354,-1330,-1296,-1278,-1306,-1382,-1480,-1580,-1687,-1814,-1937,-1994,-1949,-1835,-1732,-1698,-1720,-1740,-1712,-1641,
--1569,-1528,-1509,-1481,-1431,-1379,-1355,-1365,-1390,-1415,-1444,-1470,-1462,-1396,-1280,-1155,-1052,-973,-897,-824,-780,
--804,-909,-1057,-1186,-1257,-1298,-1370,-1495,-1631,-1720,-1748,-1755,-1772,-1794,-1800,-1791,-1790,-1803,-1816,-1823,-1833,
--1844,-1842,-1820,-1792,-1779,-1780,-1785,-1791,-1806,-1829,-1849,-1873,-1914,-1968,-2005,-2005,-1992,-1988,-1972,-1897,-1765,
--1642,-1598,-1641,-1735,-1848,-1961,-2051,-2097,-2110,-2122,-2144,-2163,-2174,-2195,-2239,-2287,-2313,-2322,-2339,-2374,-2414,
--2440,-2456,-2467,-2477,-2487,-2504,-2531,-2563,-2594,-2630,-2677,-2731,-2783,-2830,-2876,-2925,-2978,-3042,-3118,-3201,-3277,
--3345,-3407,-3467,-3522,-3576,-3635,-3701,-3769,-3836,-3899,-3959,-4017,-4070,-4121,-4172,-4222,-4270,-4320,-4370,-4418,-4463,
--4506,-4548,-4584,-4609,-4625,-4638,-4652,-4670,-4694,-4726,-4761,-4793,-4825,-4861,-4903,-4943,-4979,-5015,-5053,-5090,-5124,
--5157,-5190,-5220,-5249,-5288,-5344,-5412,-5474,-5519,-5548,-5567,-5586,-5609,-5634,-5655,-5673,-5697,-5728,-5750,-5744,-5717,
--5691,-5680,-5674,-5660,-5632,-5588,-5520,-5430,-5332,-5243,-5176,-5160,-5235,-5393,-5548,-5603,-5555,-5487,-5472,-5491,-5490,
--5465,-5449,-5446,-5419,-5355,-5290,-5256,-5241,-5220,-5202,-5199,-5185,-5114,-4999,-4919,-4935,-5028,-5118,-5145,-5096,-4993,
--4874,-4782,-4747,-4749,-4742,-4697,-4631,-4578,-4540,-4495,-4439,-4398,-4384,-4369,-4316,-4233,-4167,-4151,-4166,-4169,-4140,
--4093,-4041,-3986,-3928,-3874,-3824,-3770,-3705,-3637,-3573,-3510,-3441,-3374,-3319,-3278,-3234,-3180,-3122,-3067,-3012,-2950,
--2881,-2807,-2730,-2650,-2570,-2498,-2432,-2366,-2299,-2234,-2176,-2122,-2067,-2010,-1952,-1892,-1828,-1754,-1668,-1578,-1497,
--1434,-1378,-1308,-1209,-1085,-960,-865,-826,-836,-847,-800,-685,-558,-490,-501,-546,-569,-547,-492,-426,-373,
--346,-333,-293,-186,-9,200,400,577,742,903,1056,1189,1298,1392,1485,1585,1691,1793,1883,1960,2029,
-2092,2156,2229,2312,2395,2460,2497,2509,2513,2531,2577,2655,2754,2853,2935,3000,3059,3118,3172,3216,3257,
-3297,3324,3314,3262,3194,3149,3144,3174,3225,3292,3367,3434,3475,3493,3507,3537,3587,3649,3714,3771,3817,
-3847,3863,3870,3881,3913,3977,4064,4154,4233,4303,4369,4432,4487,4531,4562,4580,4591,4612,4654,4709,4762,
-4813,4871,4941,5008,5061,5102,5136,5161,5177,5190,5212,5240,5268,5295,5331,5383,5449,5524,5604,5679,5734,
-5770,5803,5853,5916,5980,6035,6088,6143,6194,6230,6239,6217,6163,6087,6012,5962,5955,5991,6052,6107,6137,
-6146,6155,6182,6222,6263,6294,6311,6316,6310,6302,6302,6311,6319,6315,6290,6246,6194,6152,6129,6122,6124,
-6129,6134,6128,6110,6099,6115,6149,6167,6152,6122,6103,6098,6093,6089,6097,6112,6112,6085,6043,6011,5998,
-6003,6016,6022,6006,5970,5941,5937,5942,5922,5882,5868,5918,6009,6073,6059,5981,5901,5875,5902,5938,5952,
-5953,5967,5992,5996,5971,5943,5941,5953,5951,5925,5891,5872,5895,5998,6195,6433,6607,6659,6631,6607,6619,
-6639,6641,6634,6634,6628,6605,6572,6545,6521,6488,6450,6419,6391,6354,6311,6277,6253,6222,6173,6123,6087,
-6056,6015,5971,5941,5922,5885,5816,5745,5708,5704,5694,5650,5584,5529,5506,5504,5499,5478,5441,5390,5319,
-5228,5133,5065,5035,5022,4992,4933,4867,4822,4801,4786,4760,4728,4704,4691,4676,4656,4640,4631,4618,4585,
-4542,4514,4500,4472,4398,4252,3995,3580,3036,2523,2246,2272,2475,2671,2783,2848,2899,2906,2837,2724,2619,
-2534,2448,2355,2272,2200,2114,2005,1899,1820,1768,1725,1684,1647,1609,1560,1508,1466,1433,1394,1344,1292,
-1249,1217,1191,1173,1164,1162,1161,1155,1142,1120,1092,1059,1027,1001,982,969,952,925,890,860,839,
-823,806,784,758,728,702,688,684,681,673,662,649,631,607,596,607,623,618,596,583,588,
-582,546,499,473,478,503,557,648,749,793,736,602,451,334,265,236,222,193,138,76,37,
-16,-17,-81,-157,-221,-266,-295,-302,-277,-231,-190,-176,-186,-206,-222,-228,-230,-237,-257,-288,-325,
--365,-408,-455,-499,-537,-566,-589,-610,-636,-667,-692,-700,-696,-700,-717,-738,-753,-769,-797,-836,-870,
--897,-921,-948,-972,-995,-1023,-1054,-1077,-1086,-1089,-1093,-1099,-1102,-1100,-1099,-1098,-1095,-1091,-1089,-1086,-1081,
--1078,-1083,-1090,-1087,-1073,-1059,-1053,-1049,-1037,-1023,-1014,-1010,-1005,-994,-986,-983,-981,-974,-966,-960,-954,
--944,-932,-922,-913,-903,-892,-882,-873,-863,-849,-834,-822,-811,-797,-783,-772,-763,-753,-740,-726,-713,
--702,-689,-672,-654,-638,-626,-614,-599,-581,-564,-550,-537,-525,-512,-499,-487,-473,-456,-438,-423,-410,
--397,-383,-367,-354,-343,-331,-317,-305,-295,-289,-282,-276,-269,-261,-254,-247,-243,-242,-240,-239,-239,
--241,-241,-240,-242,-247,-252,-254,-253,-255,-260,-265,-269,-272,-275,-279,-284,-291,-297,-305,-314,-323,
--331,-339,-356,-383,-407,-405,-377,-348,-349,-384,-426,-452,-459,-461,-466,-474,-480,-486,-493,-502,-517,
--534,-551,-562,-568,-574,-581,-587,-592,-598,-604,-607,-607,-606,-608,-610,-609,-606,-604,-605,-605,-600,
--595,-595,-599,-603,-601,-596,-592,-591,-591,-588,-582,-575,-567,-560,-554,-550,-544,-534,-521,-510,-500,
--492,-483,-473,-462,-448,-430,-411,-392,-374,-354,-335,-319,-308,-300,-290,-277,-261,-244,-227,-211,-194,
--175,-154,-131,-108,-84,-58,-30,0,32,69,109,150,193,235,281,332,385,438,486,532,586,
-651,719,781,841,911,994,1082,1165,1238,1307,1375,1441,1497,1531,1545,1551,1557,1552,1515,1441,1349,
-1263,1203,1192,1254,1403,1621,1873,2135,2402,2671,2937,3201,3460,3696,3882,4021,4144,4269,4382,4456,4492,
-4502,4488,4463,4464,4512,4560,4523,4382,4217,4102,4021,3912,3759,3589,3392,3121,2783,2470,2265,2140,2022,
-1912,1887,1981,2129,2234,2274,2290,2305,2305,2282,2258,2252,2254,2241,2212,2169,2101,1995,1860,1729,1618,
-1511,1388,1261,1154,1070,981,876,773,697,645,593,524,446,366,286,206,130,63,3,-52,-101,
--144,-189,-242,-300,-352,-392,-421,-443,-467,-509,-570,-623,-641,-638,-664,-747,-863,-963,-1024,-1062,-1103,
--1152,-1202,-1240,-1259,-1261,-1260,-1271,-1297,-1333,-1373,-1417,-1459,-1487,-1497,-1492,-1472,-1433,-1374,-1307,-1244,-1192,
--1162,-1170,-1212,-1250,-1250,-1214,-1177,-1155,-1128,-1074,-1002,-944,-916,-914,-923,-918,-882,-832,-821,-892,-1018,
--1120,-1149,-1133,-1127,-1140,-1143,-1119,-1082,-1049,-1017,-979,-942,-915,-898,-878,-856,-838,-826,-811,-792,-775,
--764,-755,-742,-727,-717,-711,-701,-688,-678,-673,-670,-666,-662,-663,-670,-679,-688,-696,-705,-714,-722,
--731,-744,-759,-768,-770,-770,-772,-773,-767,-751,-729,-707,-683,-655,-623,-587,-548,-505,-460,-415,-370,
--323,-277,-238,-207,-181,-152,-119,-84,-52,-20,15,56,101,146,187,230,276,322,365,403,438,
-470,499,530,564,598,623,640,659,691,729,763,790,819,852,877,886,888,903,934,965,985,
-1001,1021,1042,1057,1066,1078,1092,1098,1094,1092,1103,1126,1147,1162,1180,1202,1223,1234,1239,1245,1252,
-1256,1259,1267,1281,1291,1291,1288,1293,1302,1308,1306,1305,1308,1315,1320,1327,1341,1360,1377,1391,1403,
-1415,1427,1435,1442,1449,1452,1451,1471,1469,1471,1477,1484,1489,1493,1497,1499,1499,1499,1503,1507,1508,
-1507,1508,1509,1508,1505,1507,1516,1531,1546,1560,1573,1584,1590,1589,1588,1590,1596,1603,1609,1616,1628,
-1645,1664,1687,1713,1738,1764,1806,1885,2005,2128,2201,2207,2184,2184,2220,2268,2306,2338,2368,2388,2382,
-2355,2326,2301,2271,2228,2179,2138,2103,2068,2029,1987,1947,1909,1874,1842,1813,1783,1750,1714,1681,1650,
-1621,1592,1561,1529,1491,1436,1361,1273,1196,1148,1125,1113,1096,1070,1035,998,965,935,906,874,840,
-806,764,710,660,639,659,702,742,762,748,672,518,315,125,-4,-73,-104,-100,-52,23,85,
-108,104,103,109,99,52,-26,-118,-218,-329,-461,-608,-756,-890,-996,-1064,-1087,-1070,-1034,-1011,-1025,
--1077,-1140,-1178,-1174,-1145,-1125,-1133,-1156,-1174,-1184,-1203,-1241,-1287,-1319,-1324,-1304,-1277,-1271,-1312,-1395,-1488,
--1564,-1635,-1731,-1845,-1918,-1894,-1783,-1663,-1607,-1614,-1626,-1589,-1512,-1446,-1424,-1422,-1395,-1328,-1254,-1214,-1218,
--1245,-1277,-1312,-1339,-1328,-1252,-1127,-1003,-921,-878,-842,-797,-772,-809,-914,-1045,-1150,-1215,-1277,-1375,-1507,
--1629,-1701,-1726,-1733,-1741,-1747,-1745,-1739,-1742,-1751,-1759,-1764,-1774,-1782,-1777,-1757,-1739,-1736,-1742,-1742,-1739,
--1750,-1774,-1802,-1832,-1876,-1928,-1958,-1951,-1928,-1913,-1885,-1807,-1687,-1593,-1585,-1652,-1743,-1829,-1907,-1971,-2004,
--2009,-2017,-2043,-2075,-2097,-2119,-2157,-2202,-2233,-2250,-2271,-2306,-2341,-2363,-2373,-2380,-2389,-2400,-2416,-2443,-2475,
--2508,-2544,-2587,-2637,-2685,-2727,-2769,-2817,-2877,-2951,-3031,-3110,-3180,-3243,-3304,-3363,-3418,-3471,-3528,-3591,-3658,
--3724,-3787,-3847,-3903,-3958,-4011,-4063,-4115,-4165,-4218,-4270,-4318,-4362,-4405,-4445,-4474,-4489,-4498,-4515,-4542,-4574,
--4606,-4637,-4668,-4698,-4731,-4774,-4823,-4868,-4902,-4930,-4959,-4993,-5031,-5071,-5109,-5143,-5175,-5215,-5270,-5332,-5386,
--5424,-5448,-5468,-5492,-5520,-5549,-5574,-5599,-5628,-5659,-5674,-5662,-5630,-5604,-5593,-5587,-5575,-5551,-5509,-5442,-5350,
--5250,-5161,-5099,-5091,-5173,-5333,-5488,-5548,-5510,-5456,-5445,-5457,-5445,-5413,-5400,-5404,-5386,-5331,-5274,-5248,-5240,
--5225,-5206,-5188,-5145,-5049,-4933,-4882,-4939,-5052,-5133,-5137,-5077,-4985,-4888,-4813,-4781,-4781,-4768,-4717,-4648,-4595,
--4560,-4520,-4469,-4430,-4418,-4407,-4361,-4282,-4213,-4185,-4191,-4197,-4182,-4148,-4100,-4041,-3980,-3924,-3871,-3813,-3745,
--3677,-3613,-3551,-3484,-3418,-3363,-3319,-3273,-3218,-3161,-3108,-3056,-2996,-2928,-2856,-2783,-2712,-2641,-2572,-2504,-2437,
--2372,-2310,-2249,-2189,-2130,-2071,-2009,-1941,-1871,-1800,-1726,-1646,-1565,-1493,-1433,-1370,-1282,-1162,-1031,-923,-870,
--867,-868,-822,-722,-618,-570,-588,-627,-638,-603,-534,-454,-387,-352,-344,-320,-227,-49,173,385,562,
-718,871,1018,1137,1224,1298,1380,1476,1576,1674,1770,1860,1935,1993,2045,2110,2193,2278,2349,2399,2429,
-2448,2469,2509,2578,2664,2747,2814,2875,2944,3019,3087,3144,3201,3261,3300,3287,3219,3135,3084,3088,3134,
-3200,3271,3340,3396,3427,3440,3452,3480,3527,3586,3647,3702,3749,3782,3797,3798,3802,3836,3913,4014,4111,
-4191,4258,4321,4377,4423,4462,4492,4510,4520,4540,4584,4644,4702,4753,4810,4882,4955,5019,5069,5110,5137,
-5150,5162,5183,5210,5231,5250,5281,5330,5392,5460,5537,5617,5682,5724,5755,5796,5853,5917,5980,6046,6111,
-6163,6192,6197,6183,6146,6082,6002,5933,5906,5931,5990,6047,6077,6084,6091,6114,6153,6200,6244,6275,6284,
-6271,6256,6257,6277,6302,6312,6295,6253,6201,6157,6131,6120,6119,6122,6125,6116,6098,6092,6120,6169,6200,
-6188,6147,6105,6069,6040,6027,6038,6055,6048,6014,5979,5961,5956,5954,5958,5969,5968,5941,5901,5874,5861,
-5844,5830,5851,5922,6000,6023,5974,5903,5871,5898,5952,5984,5982,5971,5981,6006,6019,6009,5995,5999,6013,
-6007,5965,5887,5787,5711,5734,5911,6199,6470,6620,6652,6643,6644,6650,6646,6640,6641,6637,6615,6587,6565,
-6544,6510,6473,6446,6422,6385,6338,6300,6277,6246,6195,6142,6109,6088,6056,6012,5974,5942,5892,5819,5758,
-5746,5768,5769,5712,5615,5531,5491,5484,5470,5424,5351,5272,5203,5143,5093,5060,5048,5043,5022,4971,4906,
-4853,4824,4810,4795,4775,4756,4741,4725,4706,4687,4671,4655,4634,4611,4590,4566,4527,4461,4335,4081,3639,
-3062,2545,2297,2359,2573,2743,2811,2836,2866,2876,2829,2742,2654,2573,2484,2386,2299,2220,2127,2017,1912,
-1837,1784,1738,1694,1654,1615,1569,1524,1487,1455,1411,1351,1290,1241,1208,1185,1171,1167,1167,1165,1158,
-1148,1132,1104,1066,1026,995,979,972,961,935,895,856,826,805,788,769,748,722,695,675,668,
-668,667,661,646,621,592,575,575,574,556,531,524,539,542,512,467,439,436,446,475,536,
-615,662,636,547,436,348,303,302,316,302,235,139,60,17,-11,-56,-120,-188,-246,-287,-306,
--298,-270,-242,-233,-249,-282,-314,-330,-327,-321,-327,-344,-366,-389,-423,-469,-518,-559,-591,-616,-640,
--670,-700,-723,-729,-727,-731,-746,-759,-765,-772,-793,-826,-859,-887,-916,-946,-971,-992,-1015,-1042,-1064,
--1077,-1084,-1094,-1104,-1108,-1106,-1104,-1103,-1101,-1099,-1097,-1095,-1092,-1091,-1096,-1102,-1099,-1086,-1075,-1071,-1068,
--1058,-1045,-1038,-1035,-1028,-1016,-1005,-1000,-997,-991,-982,-974,-966,-956,-943,-931,-919,-906,-896,-889,-882,
--870,-853,-837,-822,-807,-792,-778,-768,-759,-748,-733,-718,-706,-695,-681,-666,-649,-634,-621,-610,-597,
--580,-562,-547,-534,-520,-506,-492,-480,-466,-449,-431,-415,-401,-389,-375,-362,-351,-338,-324,-311,-299,
--288,-278,-268,-262,-257,-249,-241,-234,-231,-230,-228,-226,-226,-227,-226,-225,-228,-234,-240,-241,-240,
--243,-248,-253,-258,-262,-265,-267,-269,-275,-285,-298,-310,-320,-326,-331,-344,-364,-380,-372,-345,-325,
--336,-376,-417,-438,-442,-443,-447,-454,-462,-474,-488,-502,-517,-534,-549,-556,-558,-561,-568,-575,-581,
--585,-591,-595,-598,-598,-599,-599,-596,-591,-590,-593,-595,-591,-583,-578,-580,-582,-580,-574,-569,-566,
--565,-561,-557,-553,-549,-543,-535,-529,-525,-518,-505,-488,-475,-466,-459,-450,-438,-422,-404,-385,-368,
--352,-336,-321,-307,-294,-281,-268,-254,-240,-225,-208,-190,-171,-150,-128,-108,-91,-71,-45,-12,24,
-61,97,135,175,217,259,301,346,396,450,501,548,599,661,732,801,865,931,1008,1093,1176,
-1247,1302,1352,1407,1469,1523,1553,1563,1569,1577,1577,1550,1492,1412,1318,1228,1173,1183,1271,1428,1642,
-1898,2178,2464,2752,3043,3327,3575,3772,3935,4088,4234,4359,4450,4499,4500,4470,4455,4483,4521,4507,4438,
-4373,4354,4340,4272,4153,4025,3869,3612,3247,2882,2631,2488,2363,2218,2114,2108,2170,2227,2250,2260,2271,
-2271,2252,2227,2210,2195,2177,2164,2155,2121,2036,1909,1784,1678,1571,1439,1298,1184,1107,1041,962,873,
-788,712,638,561,481,397,307,217,141,82,31,-20,-73,-128,-185,-241,-290,-331,-366,-394,-418,
--448,-503,-577,-636,-651,-645,-677,-776,-911,-1028,-1101,-1145,-1178,-1207,-1230,-1244,-1249,-1246,-1245,-1256,-1285,
--1331,-1385,-1434,-1462,-1466,-1460,-1460,-1458,-1433,-1374,-1301,-1236,-1191,-1171,-1184,-1222,-1250,-1232,-1181,-1139,-1128,
--1124,-1089,-1022,-952,-909,-905,-926,-933,-896,-836,-827,-926,-1089,-1205,-1201,-1113,-1030,-1002,-1010,-1018,-1016,
--1006,-990,-965,-938,-916,-898,-880,-863,-849,-836,-816,-793,-775,-762,-748,-729,-710,-702,-700,-694,-681,
--667,-657,-652,-648,-647,-651,-659,-668,-680,-693,-704,-711,-716,-723,-738,-752,-758,-755,-751,-754,-759,
--756,-745,-729,-712,-691,-665,-634,-600,-559,-512,-465,-419,-373,-323,-274,-234,-203,-177,-147,-115,-84,
--55,-24,11,54,101,149,195,239,284,329,370,407,440,471,501,534,569,601,625,640,659,
-694,741,784,815,841,870,895,907,911,924,949,978,999,1013,1028,1043,1053,1059,1068,1084,1096,
-1099,1101,1114,1138,1161,1177,1190,1207,1228,1244,1254,1261,1268,1273,1275,1274,1276,1281,1289,1298,1304,
-1305,1301,1298,1301,1309,1316,1322,1333,1352,1374,1392,1404,1417,1432,1444,1450,1456,1463,1470,1471,1491,
-1489,1490,1497,1506,1512,1516,1518,1519,1519,1520,1524,1528,1528,1525,1522,1522,1521,1521,1527,1541,1558,
-1574,1589,1605,1620,1626,1625,1623,1627,1634,1639,1641,1648,1662,1681,1698,1714,1732,1753,1776,1814,1891,
-2012,2136,2204,2198,2162,2158,2202,2261,2307,2343,2380,2409,2409,2382,2351,2332,2314,2283,2238,2189,2142,
-2097,2051,2009,1971,1933,1893,1856,1824,1797,1770,1742,1713,1684,1655,1627,1598,1567,1528,1470,1393,1305,
-1228,1177,1152,1136,1116,1089,1058,1028,1000,972,938,898,854,812,772,732,699,688,709,750,786,
-790,741,623,448,257,109,29,0,-13,-18,0,46,101,141,165,183,195,189,151,82,-8,
--116,-239,-375,-522,-676,-825,-950,-1030,-1061,-1053,-1029,-1015,-1028,-1072,-1124,-1154,-1152,-1137,-1136,-1147,-1143,
--1110,-1073,-1072,-1124,-1203,-1269,-1300,-1299,-1286,-1289,-1327,-1397,-1472,-1528,-1575,-1648,-1750,-1830,-1822,-1723,-1600,
--1533,-1534,-1543,-1501,-1416,-1344,-1322,-1328,-1308,-1243,-1167,-1121,-1117,-1137,-1163,-1190,-1206,-1181,-1093,-963,-848,
--791,-783,-779,-758,-750,-793,-893,-1008,-1101,-1176,-1267,-1391,-1522,-1621,-1671,-1689,-1698,-1706,-1708,-1703,-1697,
--1695,-1697,-1699,-1704,-1714,-1720,-1712,-1697,-1689,-1696,-1705,-1702,-1695,-1705,-1734,-1769,-1802,-1840,-1883,-1912,-1916,
--1906,-1891,-1844,-1735,-1591,-1498,-1519,-1624,-1734,-1804,-1843,-1870,-1888,-1897,-1914,-1948,-1986,-2013,-2034,-2065,-2105,
--2137,-2158,-2180,-2212,-2242,-2259,-2268,-2281,-2299,-2317,-2335,-2360,-2390,-2421,-2454,-2493,-2539,-2584,-2624,-2664,-2714,
--2781,-2858,-2937,-3010,-3077,-3141,-3204,-3264,-3320,-3372,-3426,-3485,-3548,-3610,-3669,-3727,-3785,-3844,-3903,-3959,-4012,
--4064,-4116,-4168,-4215,-4258,-4300,-4336,-4359,-4368,-4378,-4403,-4442,-4484,-4519,-4548,-4575,-4603,-4638,-4686,-4741,-4788,
--4819,-4839,-4861,-4894,-4937,-4984,-5029,-5067,-5101,-5140,-5190,-5244,-5291,-5323,-5347,-5371,-5399,-5431,-5464,-5494,-5524,
--5554,-5579,-5582,-5558,-5522,-5500,-5499,-5504,-5501,-5483,-5444,-5375,-5278,-5173,-5083,-5027,-5033,-5126,-5288,-5439,-5498,
--5469,-5426,-5419,-5421,-5395,-5357,-5349,-5366,-5362,-5315,-5263,-5240,-5236,-5223,-5193,-5151,-5081,-4979,-4892,-4888,-4978,
--5091,-5144,-5120,-5055,-4980,-4906,-4844,-4813,-4804,-4781,-4724,-4655,-4607,-4581,-4550,-4505,-4465,-4448,-4434,-4392,-4321,
--4254,-4218,-4212,-4213,-4206,-4184,-4144,-4088,-4024,-3963,-3906,-3847,-3780,-3713,-3650,-3588,-3522,-3459,-3404,-3358,-3310,
--3257,-3202,-3150,-3096,-3034,-2964,-2892,-2824,-2760,-2699,-2635,-2567,-2500,-2437,-2376,-2314,-2251,-2190,-2130,-2065,-1991,
--1915,-1848,-1787,-1719,-1640,-1563,-1500,-1440,-1360,-1243,-1106,-989,-925,-912,-913,-887,-825,-763,-735,-743,-751,
--730,-675,-599,-515,-438,-386,-362,-334,-250,-83,138,355,535,685,827,957,1055,1123,1185,1265,1358,
-1451,1540,1633,1728,1808,1866,1914,1976,2056,2139,2214,2280,2337,2381,2414,2450,2502,2565,2625,2679,2741,
-2822,2909,2989,3062,3141,3221,3264,3238,3150,3055,3009,3031,3100,3180,3253,3313,3356,3381,3391,3400,3421,
-3461,3513,3570,3623,3671,3709,3728,3728,3730,3767,3850,3958,4058,4137,4205,4268,4319,4355,4386,4417,4444,
-4461,4482,4522,4578,4635,4687,4746,4817,4892,4960,5022,5073,5105,5116,5121,5138,5162,5183,5200,5229,5276,
-5332,5392,5460,5535,5604,5653,5692,5740,5802,5868,5935,6008,6082,6136,6157,6150,6134,6109,6064,5992,5914,
-5868,5876,5927,5986,6026,6041,6048,6064,6098,6148,6203,6245,6258,6245,6228,6229,6249,6273,6284,6273,6239,
-6190,6143,6111,6095,6094,6100,6102,6090,6068,6062,6096,6152,6187,6176,6134,6088,6048,6016,6003,6008,6007,
-5978,5934,5915,5929,5940,5923,5897,5895,5910,5908,5878,5838,5803,5775,5769,5811,5897,5969,5970,5908,5848,
-5845,5895,5952,5982,5984,5981,5991,6009,6022,6024,6026,6034,6038,6024,5977,5879,5730,5578,5535,5692,6021,
-6372,6597,6669,6666,6658,6658,6654,6649,6648,6641,6620,6597,6582,6565,6531,6488,6456,6433,6401,6359,6325,
-6304,6273,6219,6161,6127,6110,6084,6040,5992,5945,5891,5828,5788,5794,5823,5821,5754,5643,5543,5488,5466,
-5437,5369,5269,5166,5093,5057,5047,5050,5058,5057,5034,4986,4925,4875,4847,4835,4827,4814,4796,4780,4768,
-4757,4739,4716,4693,4682,4682,4675,4645,4595,4531,4413,4148,3671,3063,2552,2348,2457,2686,2838,2864,2842,
-2835,2831,2798,2738,2674,2602,2512,2410,2318,2236,2144,2039,1939,1862,1803,1751,1704,1664,1626,1583,1541,
-1506,1469,1417,1351,1287,1239,1209,1195,1194,1198,1195,1182,1168,1158,1147,1121,1078,1031,998,983,978,
-966,937,894,850,815,789,769,752,736,717,693,671,659,657,656,650,633,605,570,543,528,
-516,494,471,464,471,469,441,406,386,383,384,390,413,452,483,481,445,393,352,350,394,
-454,467,391,251,118,40,5,-26,-76,-134,-184,-220,-245,-264,-274,-276,-279,-298,-339,-388,-420,
--425,-419,-416,-420,-426,-438,-463,-500,-540,-575,-608,-641,-673,-699,-724,-745,-759,-766,-772,-780,-784,
--784,-787,-802,-827,-853,-879,-908,-940,-966,-986,-1005,-1027,-1047,-1062,-1074,-1089,-1102,-1107,-1106,-1104,-1106,
--1108,-1108,-1108,-1107,-1103,-1102,-1105,-1109,-1105,-1095,-1086,-1085,-1083,-1075,-1064,-1058,-1054,-1047,-1036,-1027,-1022,
--1019,-1013,-1003,-992,-980,-969,-958,-946,-932,-918,-908,-902,-894,-879,-861,-843,-828,-812,-796,-783,-773,
--762,-746,-729,-714,-701,-688,-675,-661,-646,-629,-614,-603,-592,-577,-560,-543,-528,-514,-498,-484,-471,
--458,-442,-423,-407,-393,-381,-368,-357,-346,-332,-317,-305,-295,-285,-271,-259,-252,-248,-241,-231,-224,
--221,-219,-216,-214,-215,-216,-214,-213,-216,-223,-227,-229,-231,-236,-242,-246,-250,-255,-259,-260,-261,
--266,-278,-292,-305,-314,-317,-316,-319,-331,-344,-349,-347,-350,-369,-395,-412,-417,-417,-421,-429,-438,
--449,-466,-483,-497,-510,-523,-535,-540,-540,-541,-548,-558,-567,-574,-579,-583,-586,-588,-587,-585,-579,
--574,-573,-578,-583,-583,-576,-568,-563,-561,-558,-553,-547,-544,-540,-535,-531,-530,-529,-524,-515,-507,
--504,-499,-487,-468,-451,-441,-434,-425,-411,-396,-381,-365,-348,-331,-316,-304,-293,-280,-264,-247,-231,
--217,-201,-185,-167,-148,-126,-104,-85,-68,-49,-22,12,50,88,123,158,196,239,283,325,366,
-410,462,516,567,616,673,742,815,887,957,1028,1105,1181,1249,1300,1339,1380,1434,1493,1539,1562,
-1576,1592,1607,1609,1589,1547,1481,1387,1277,1183,1139,1177,1309,1527,1793,2068,2341,2629,2935,3231,3476,
-3664,3825,3994,4177,4349,4467,4501,4472,4442,4456,4495,4508,4488,4485,4524,4557,4522,4429,4329,4218,4024,
-3723,3395,3144,2974,2807,2602,2411,2298,2260,2249,2238,2232,2237,2239,2231,2220,2207,2182,2151,2134,2135,
-2117,2045,1929,1813,1718,1618,1488,1346,1230,1158,1106,1047,970,879,783,688,601,518,430,333,239,
-163,107,58,4,-57,-126,-192,-247,-285,-315,-349,-387,-420,-454,-507,-578,-639,-664,-672,-713,-810,
--939,-1056,-1140,-1196,-1235,-1259,-1271,-1275,-1269,-1253,-1237,-1239,-1266,-1316,-1371,-1412,-1425,-1414,-1404,-1411,-1418,
--1395,-1336,-1268,-1217,-1187,-1172,-1176,-1193,-1199,-1166,-1107,-1068,-1072,-1092,-1086,-1038,-969,-915,-901,-922,-938,
--907,-838,-804,-866,-994,-1084,-1069,-986,-923,-926,-964,-987,-976,-944,-912,-894,-890,-893,-890,-878,-863,
--849,-833,-810,-784,-764,-750,-733,-712,-695,-688,-686,-679,-667,-653,-641,-633,-629,-629,-635,-644,-655,
--667,-682,-696,-704,-708,-715,-729,-743,-746,-741,-737,-740,-746,-746,-739,-728,-714,-693,-667,-639,-610,
--573,-528,-479,-432,-383,-330,-280,-240,-211,-184,-154,-123,-95,-68,-36,2,46,95,146,196,243,
-288,331,372,408,441,473,505,538,571,602,627,644,665,700,747,791,823,846,871,895,912,
-921,932,952,977,997,1010,1023,1037,1046,1053,1063,1080,1098,1111,1121,1136,1159,1182,1200,1212,1225,
-1242,1257,1267,1272,1275,1276,1277,1276,1276,1281,1289,1297,1300,1297,1291,1291,1298,1308,1317,1326,1341,
-1364,1388,1405,1417,1433,1451,1465,1471,1474,1481,1489,1491,1509,1507,1506,1511,1519,1526,1530,1533,1535,
-1536,1539,1544,1547,1545,1538,1534,1533,1536,1541,1551,1567,1586,1604,1621,1639,1655,1664,1667,1668,1672,
-1676,1675,1674,1679,1693,1710,1721,1730,1745,1768,1792,1825,1889,1996,2114,2187,2187,2158,2160,2215,2286,
-2340,2377,2416,2452,2462,2442,2412,2391,2371,2335,2282,2223,2166,2112,2064,2023,1989,1956,1918,1881,1849,
-1826,1806,1786,1762,1731,1696,1663,1635,1607,1567,1508,1430,1344,1268,1215,1186,1166,1142,1112,1082,1056,
-1033,1005,966,914,856,808,780,767,760,754,756,767,771,742,661,528,373,237,149,111,96,
-77,54,49,76,126,177,214,235,243,239,222,181,110,6,-118,-252,-397,-561,-733,-882,-974,
--1005,-1002,-994,-999,-1021,-1056,-1090,-1108,-1108,-1106,-1117,-1126,-1103,-1038,-971,-955,-1012,-1115,-1213,-1277,-1304,
--1309,-1315,-1344,-1397,-1455,-1498,-1532,-1582,-1660,-1729,-1731,-1650,-1539,-1472,-1472,-1486,-1448,-1356,-1267,-1229,-1229,
--1218,-1170,-1107,-1061,-1044,-1043,-1050,-1059,-1058,-1015,-918,-793,-699,-669,-685,-701,-696,-695,-740,-834,-947,
--1052,-1156,-1280,-1418,-1535,-1604,-1629,-1639,-1651,-1665,-1671,-1665,-1656,-1650,-1648,-1651,-1659,-1667,-1669,-1660,-1647,
--1645,-1655,-1664,-1660,-1655,-1667,-1700,-1738,-1767,-1794,-1827,-1857,-1878,-1893,-1896,-1852,-1726,-1557,-1443,-1461,-1580,
--1705,-1768,-1779,-1776,-1780,-1796,-1823,-1861,-1899,-1926,-1947,-1975,-2007,-2034,-2052,-2074,-2103,-2128,-2142,-2154,-2175,
--2202,-2228,-2248,-2270,-2296,-2325,-2357,-2396,-2440,-2483,-2522,-2563,-2618,-2688,-2764,-2837,-2906,-2973,-3040,-3106,-3167,
--3220,-3271,-3324,-3381,-3439,-3496,-3552,-3610,-3670,-3732,-3794,-3853,-3908,-3962,-4016,-4068,-4114,-4154,-4191,-4222,-4241,
--4252,-4269,-4303,-4349,-4393,-4429,-4457,-4482,-4509,-4545,-4595,-4653,-4700,-4729,-4745,-4767,-4803,-4850,-4901,-4949,-4989,
--5024,-5062,-5107,-5155,-5196,-5228,-5255,-5283,-5315,-5349,-5384,-5417,-5449,-5476,-5489,-5476,-5441,-5407,-5399,-5417,-5441,
--5448,-5433,-5391,-5318,-5215,-5103,-5007,-4955,-4975,-5082,-5248,-5393,-5448,-5424,-5390,-5381,-5373,-5337,-5299,-5302,-5335,
--5344,-5304,-5252,-5229,-5226,-5209,-5162,-5094,-5013,-4935,-4900,-4943,-5045,-5130,-5143,-5095,-5031,-4975,-4920,-4869,-4836,
--4818,-4786,-4726,-4661,-4623,-4606,-4582,-4539,-4496,-4471,-4452,-4413,-4352,-4291,-4250,-4232,-4224,-4219,-4207,-4179,-4130,
--4068,-4003,-3941,-3881,-3817,-3752,-3687,-3622,-3557,-3496,-3441,-3392,-3344,-3294,-3243,-3191,-3135,-3071,-3002,-2933,-2866,
--2803,-2744,-2683,-2620,-2556,-2496,-2437,-2375,-2310,-2247,-2185,-2119,-2043,-1967,-1902,-1848,-1787,-1713,-1637,-1576,-1522,
--1447,-1334,-1198,-1081,-1012,-991,-986,-969,-935,-898,-874,-857,-829,-779,-713,-642,-570,-499,-438,-392,-342,
--248,-86,125,335,509,649,773,882,960,1014,1071,1151,1246,1334,1413,1495,1584,1664,1725,1782,1853,
-1936,2016,2089,2162,2235,2299,2344,2380,2418,2457,2494,2538,2603,2693,2788,2877,2964,3061,3147,3181,3136,
-3038,2950,2927,2977,3069,3163,3237,3286,3317,3334,3341,3344,3356,3386,3432,3485,3537,3587,3632,3660,3667,
-3675,3713,3793,3893,3984,4057,4124,4186,4233,4263,4294,4337,4381,4414,4437,4470,4518,4574,4632,4695,4765,
-4834,4900,4966,5025,5061,5068,5065,5075,5098,5117,5134,5163,5212,5271,5330,5392,5456,5515,5564,5614,5679,
-5755,5828,5897,5970,6046,6101,6115,6097,6074,6059,6034,5979,5901,5835,5816,5851,5913,5968,5999,6013,6026,
-6055,6102,6159,6201,6215,6205,6194,6197,6207,6213,6211,6201,6179,6145,6104,6069,6050,6046,6052,6056,6045,
-6023,6018,6051,6104,6135,6122,6085,6049,6021,5999,5988,5982,5958,5904,5857,5867,5923,5954,5916,5849,5825,
-5853,5886,5883,5847,5797,5749,5727,5763,5848,5926,5940,5900,5865,5873,5910,5943,5961,5974,5989,5999,6002,
-6006,6017,6032,6040,6033,6012,5970,5879,5718,5532,5454,5602,5953,6337,6583,6658,6650,6648,6662,6669,6664,
-6657,6645,6623,6600,6588,6575,6544,6499,6462,6438,6411,6375,6343,6323,6295,6244,6185,6145,6122,6094,6049,
-5997,5948,5899,5848,5815,5814,5831,5827,5777,5689,5597,5526,5477,5426,5349,5244,5133,5049,5008,5006,5027,
-5051,5061,5042,4996,4940,4894,4869,4859,4853,4844,4830,4818,4813,4811,4797,4768,4739,4730,4739,4738,4707,
-4659,4601,4477,4174,3640,3000,2509,2357,2513,2761,2909,2919,2870,2829,2799,2763,2722,2680,2621,2532,2428,
-2334,2252,2166,2068,1971,1887,1818,1759,1711,1670,1630,1589,1550,1513,1470,1413,1351,1296,1256,1234,1235,
-1253,1267,1255,1219,1185,1169,1160,1135,1090,1041,1007,989,977,956,922,879,839,809,786,766,747,
-731,715,697,679,667,661,654,641,620,591,557,522,496,479,466,457,449,438,415,382,351,
-337,333,330,326,328,341,356,368,370,361,355,383,467,572,616,539,367,191,80,33,0,
--50,-110,-156,-184,-210,-248,-288,-315,-325,-336,-368,-417,-459,-480,-485,-487,-489,-492,-503,-525,-548,
--563,-581,-617,-666,-707,-726,-734,-751,-779,-802,-814,-815,-812,-810,-811,-821,-837,-857,-879,-904,-932,
--956,-976,-995,-1015,-1034,-1048,-1063,-1079,-1093,-1099,-1100,-1103,-1108,-1114,-1118,-1119,-1117,-1114,-1111,-1113,-1114,
--1109,-1099,-1091,-1090,-1089,-1083,-1075,-1069,-1066,-1060,-1052,-1045,-1043,-1041,-1035,-1024,-1010,-995,-984,-975,-966,
--952,-937,-927,-922,-912,-895,-875,-858,-843,-826,-808,-796,-785,-770,-750,-730,-714,-700,-685,-671,-658,
--645,-628,-610,-596,-586,-574,-556,-538,-521,-506,-491,-476,-463,-450,-434,-416,-400,-386,-372,-359,-348,
--336,-322,-308,-298,-290,-281,-267,-254,-247,-242,-235,-225,-218,-215,-212,-210,-209,-210,-210,-208,-207,
--211,-216,-219,-221,-226,-234,-240,-242,-245,-251,-258,-260,-260,-266,-277,-290,-301,-308,-310,-308,-306,
--311,-324,-341,-358,-377,-393,-401,-398,-393,-396,-407,-419,-430,-442,-459,-476,-488,-497,-508,-518,-524,
--524,-525,-532,-544,-557,-564,-567,-569,-571,-573,-572,-568,-563,-559,-560,-564,-569,-572,-567,-558,-549,
--543,-539,-535,-530,-526,-521,-515,-509,-505,-504,-499,-490,-481,-476,-472,-461,-444,-428,-417,-409,-398,
--385,-373,-362,-350,-333,-313,-295,-282,-271,-259,-244,-228,-213,-196,-179,-161,-144,-127,-108,-88,-69,
--49,-24,5,39,75,111,146,180,215,256,302,347,388,428,476,530,585,638,693,757,828,
-902,974,1042,1106,1169,1231,1285,1328,1367,1411,1462,1510,1545,1572,1598,1621,1634,1637,1632,1614,1562,
-1465,1335,1212,1149,1185,1328,1544,1784,2028,2292,2590,2895,3153,3343,3502,3688,3929,4189,4391,4480,4469,
-4433,4436,4476,4503,4501,4511,4560,4611,4599,4520,4422,4331,4209,4024,3807,3609,3429,3222,2973,2732,2551,
-2428,2330,2251,2202,2188,2192,2205,2224,2235,2219,2181,2153,2145,2127,2062,1955,1843,1747,1647,1526,1398,
-1294,1225,1173,1117,1045,956,852,746,652,566,475,374,276,197,137,82,21,-48,-126,-200,-254,
--286,-312,-353,-408,-457,-497,-543,-604,-661,-695,-716,-760,-841,-946,-1050,-1142,-1219,-1275,-1307,-1322,-1322,
--1303,-1266,-1227,-1215,-1237,-1280,-1323,-1346,-1347,-1337,-1335,-1346,-1350,-1321,-1264,-1210,-1178,-1160,-1144,-1134,-1134,
--1125,-1089,-1036,-1003,-1013,-1044,-1058,-1036,-985,-932,-905,-912,-925,-903,-839,-783,-785,-834,-867,-850,-822,
--843,-922,-999,-1012,-948,-851,-779,-765,-803,-855,-884,-881,-861,-839,-818,-792,-765,-743,-727,-710,-693,
--681,-676,-671,-661,-648,-635,-625,-616,-609,-608,-615,-627,-639,-651,-665,-679,-690,-699,-708,-721,-733,
--738,-736,-733,-736,-739,-738,-733,-725,-711,-690,-663,-638,-615,-585,-544,-497,-447,-394,-338,-287,-247,
--218,-191,-162,-135,-110,-83,-49,-8,37,86,138,189,238,283,327,368,404,437,470,504,536,
-568,598,627,650,673,703,743,783,812,831,850,873,895,912,928,947,969,987,1001,1014,1029,
-1045,1058,1071,1088,1108,1128,1145,1161,1179,1200,1221,1237,1250,1260,1270,1277,1278,1275,1273,1273,1274,
-1276,1278,1281,1284,1285,1284,1285,1288,1296,1305,1314,1326,1344,1370,1396,1416,1432,1451,1471,1486,1492,
-1494,1499,1506,1509,1527,1529,1529,1531,1536,1540,1544,1546,1549,1551,1555,1559,1561,1558,1552,1549,1551,
-1559,1568,1580,1597,1617,1638,1657,1676,1691,1703,1710,1716,1719,1718,1713,1709,1710,1717,1726,1733,1743,
-1763,1791,1817,1840,1883,1967,2075,2155,2176,2167,2186,2253,2335,2393,2427,2460,2497,2516,2508,2483,2455,
-2420,2367,2300,2231,2168,2111,2062,2023,1994,1968,1940,1913,1889,1870,1854,1839,1820,1790,1751,1715,1687,
-1660,1618,1553,1470,1382,1305,1250,1219,1199,1176,1143,1110,1083,1061,1036,998,943,881,833,817,828,
-839,828,796,757,713,648,552,438,338,273,240,219,192,156,122,111,131,174,224,261,281,
-292,303,311,299,248,155,42,-76,-211,-382,-582,-762,-871,-905,-905,-915,-945,-983,-1016,-1039,-1052,
--1056,-1061,-1070,-1072,-1041,-975,-909,-895,-955,-1064,-1178,-1262,-1309,-1329,-1341,-1364,-1403,-1447,-1481,-1502,-1529,
--1576,-1626,-1633,-1572,-1474,-1409,-1408,-1432,-1412,-1327,-1226,-1164,-1148,-1138,-1105,-1054,-1005,-966,-933,-910,-897,
--879,-827,-732,-627,-560,-554,-585,-610,-615,-622,-667,-759,-883,-1019,-1162,-1311,-1445,-1535,-1574,-1581,-1587,
--1604,-1622,-1630,-1624,-1612,-1605,-1606,-1614,-1624,-1630,-1627,-1618,-1606,-1603,-1609,-1615,-1616,-1617,-1634,-1667,-1701,
--1724,-1741,-1761,-1782,-1801,-1822,-1843,-1829,-1743,-1601,-1489,-1484,-1574,-1678,-1726,-1719,-1700,-1700,-1720,-1751,-1785,
--1814,-1837,-1861,-1890,-1920,-1941,-1957,-1978,-2007,-2030,-2040,-2048,-2066,-2092,-2119,-2143,-2166,-2192,-2221,-2255,-2296,
--2340,-2382,-2421,-2466,-2524,-2593,-2664,-2733,-2800,-2870,-2940,-3006,-3063,-3113,-3163,-3218,-3275,-3332,-3387,-3442,-3501,
--3563,-3625,-3685,-3743,-3801,-3859,-3917,-3969,-4012,-4047,-4077,-4102,-4121,-4141,-4169,-4210,-4255,-4297,-4333,-4364,-4391,
--4418,-4453,-4505,-4564,-4611,-4636,-4653,-4679,-4720,-4771,-4820,-4865,-4905,-4942,-4981,-5023,-5067,-5106,-5140,-5173,-5207,
--5242,-5276,-5309,-5343,-5373,-5392,-5391,-5366,-5330,-5308,-5320,-5360,-5399,-5412,-5391,-5341,-5261,-5153,-5033,-4931,-4880,
--4913,-5035,-5206,-5345,-5397,-5377,-5347,-5335,-5318,-5277,-5244,-5259,-5305,-5323,-5287,-5237,-5213,-5208,-5180,-5114,-5031,
--4962,-4928,-4947,-5018,-5103,-5146,-5121,-5062,-5009,-4970,-4929,-4884,-4852,-4829,-4793,-4734,-4676,-4645,-4633,-4612,-4571,
--4527,-4497,-4475,-4441,-4389,-4332,-4286,-4256,-4241,-4234,-4227,-4206,-4166,-4108,-4042,-3978,-3915,-3853,-3790,-3725,-3658,
--3594,-3534,-3479,-3427,-3375,-3325,-3275,-3223,-3167,-3107,-3046,-2983,-2919,-2853,-2790,-2730,-2672,-2615,-2560,-2503,-2440,
--2370,-2299,-2231,-2163,-2088,-2015,-1951,-1897,-1840,-1771,-1702,-1646,-1598,-1532,-1430,-1307,-1200,-1132,-1098,-1075,-1048,
--1015,-979,-943,-899,-845,-781,-715,-654,-597,-542,-481,-413,-327,-206,-39,156,344,495,613,714,802,
-868,916,971,1052,1147,1234,1306,1378,1454,1527,1594,1665,1750,1839,1915,1980,2045,2116,2180,2231,2273,
-2313,2347,2377,2419,2487,2577,2669,2757,2851,2952,3029,3043,2986,2899,2843,2854,2928,3033,3133,3206,3249,
-3270,3279,3282,3281,3285,3305,3344,3395,3448,3501,3551,3588,3611,3631,3672,3744,3827,3900,3961,4020,4077,
-4119,4151,4192,4254,4321,4369,4398,4428,4472,4528,4590,4654,4717,4776,4836,4902,4966,5006,5015,5010,5016,
-5034,5049,5060,5087,5139,5208,5277,5338,5392,5440,5486,5543,5622,5711,5792,5860,5928,6000,6052,6063,6040,
-6014,6005,6000,5967,5897,5817,5770,5779,5832,5891,5932,5951,5965,5991,6035,6084,6118,6126,6120,6117,6123,
-6124,6113,6097,6087,6079,6062,6036,6008,5987,5981,5987,5997,5998,5990,5993,6022,6061,6078,6062,6032,6007,
-5988,5967,5951,5934,5892,5826,5787,5831,5928,5978,5924,5824,5780,5816,5875,5897,5873,5824,5767,5725,5735,
-5804,5889,5940,5956,5967,5985,5989,5973,5961,5974,6000,6010,5999,5991,6006,6032,6040,6024,5999,5967,5892,
-5734,5533,5430,5559,5900,6278,6517,6590,6597,6625,6669,6688,6677,6661,6648,6628,6603,6585,6573,6550,6513,
-6478,6454,6429,6392,6356,6329,6304,6264,6213,6167,6131,6094,6049,6003,5961,5917,5865,5816,5788,5783,5784,
-5767,5721,5646,5558,5474,5399,5323,5234,5137,5052,4997,4981,4998,5032,5058,5054,5017,4965,4922,4897,4886,
-4880,4875,4867,4861,4859,4858,4845,4816,4789,4780,4783,4771,4732,4685,4626,4473,4111,3525,2883,2442,2352,
-2535,2780,2924,2948,2910,2857,2801,2748,2711,2685,2639,2556,2453,2359,2278,2194,2098,1997,1904,1826,1763,
-1712,1667,1624,1583,1546,1510,1465,1416,1371,1333,1302,1284,1293,1325,1344,1318,1256,1198,1170,1159,1137,
-1097,1054,1020,994,968,935,897,858,826,804,789,774,756,739,723,708,694,683,673,658,635,
-609,583,553,517,482,463,465,474,472,447,404,363,337,323,312,301,292,289,292,301,318,
-335,340,338,366,456,579,644,581,413,230,110,53,7,-59,-134,-188,-212,-230,-266,-316,-354,
--369,-373,-390,-425,-464,-495,-518,-532,-540,-550,-570,-594,-604,-592,-588,-625,-691,-741,-746,-731,-737,
--775,-817,-838,-841,-838,-838,-839,-842,-851,-867,-888,-910,-931,-950,-967,-985,-1004,-1022,-1037,-1052,-1067,
--1081,-1090,-1096,-1102,-1111,-1118,-1123,-1124,-1123,-1120,-1119,-1120,-1119,-1111,-1100,-1092,-1089,-1088,-1083,-1076,-1072,
--1069,-1065,-1060,-1057,-1056,-1055,-1051,-1041,-1026,-1009,-998,-992,-985,-972,-956,-946,-941,-932,-914,-895,-878,
--861,-840,-821,-807,-796,-780,-757,-736,-719,-704,-686,-670,-659,-647,-631,-611,-595,-584,-571,-554,-534,
--517,-502,-486,-471,-457,-443,-428,-411,-396,-381,-365,-351,-338,-326,-313,-300,-291,-284,-274,-262,-251,
--244,-238,-230,-220,-213,-211,-208,-206,-206,-207,-206,-204,-204,-208,-212,-214,-216,-223,-232,-237,-237,
--240,-249,-257,-261,-264,-270,-279,-287,-294,-300,-306,-310,-312,-316,-325,-340,-357,-374,-383,-383,-378,
--379,-390,-406,-418,-427,-437,-452,-467,-478,-487,-497,-508,-516,-517,-518,-524,-535,-547,-552,-551,-548,
--550,-554,-556,-555,-552,-551,-550,-551,-553,-554,-551,-542,-531,-524,-520,-516,-510,-506,-504,-499,-490,
--481,-475,-470,-463,-455,-448,-441,-431,-416,-402,-392,-382,-371,-359,-349,-340,-330,-314,-295,-276,-260,
--247,-234,-223,-211,-197,-180,-160,-142,-125,-109,-92,-74,-55,-32,-3,29,62,94,130,166,200,
-233,269,314,362,405,444,486,538,596,654,712,773,838,907,977,1041,1095,1142,1191,1246,1303,
-1354,1400,1444,1486,1524,1561,1597,1627,1646,1659,1675,1691,1689,1645,1552,1427,1310,1249,1280,1399,1577,
-1788,2032,2312,2599,2842,3021,3178,3384,3672,4002,4283,4438,4465,4434,4424,4452,4476,4471,4465,4496,4549,
-4560,4496,4389,4285,4196,4104,3996,3866,3698,3483,3243,3020,2830,2650,2462,2291,2176,2130,2131,2160,2204,
-2242,2246,2217,2186,2173,2158,2105,2009,1895,1783,1671,1556,1452,1372,1309,1247,1180,1106,1020,920,813,
-715,625,531,427,326,239,168,102,35,-37,-118,-197,-256,-290,-321,-372,-442,-507,-558,-606,-661,
--712,-744,-764,-797,-854,-932,-1025,-1129,-1230,-1307,-1351,-1367,-1361,-1325,-1263,-1205,-1181,-1198,-1230,-1251,-1255,
--1252,-1253,-1264,-1277,-1273,-1241,-1194,-1154,-1130,-1112,-1092,-1079,-1079,-1076,-1050,-1009,-982,-985,-1005,-1022,-1020,
--997,-959,-923,-903,-896,-876,-831,-777,-741,-720,-695,-673,-697,-800,-946,-1053,-1049,-934,-778,-668,-659,
--735,-831,-887,-887,-858,-826,-801,-775,-749,-727,-709,-691,-676,-666,-662,-655,-642,-627,-616,-608,-599,
--589,-586,-593,-607,-622,-633,-645,-658,-674,-687,-699,-711,-723,-731,-735,-736,-737,-736,-731,-724,-715,
--702,-681,-656,-633,-612,-586,-551,-508,-459,-405,-347,-293,-250,-219,-191,-164,-140,-118,-91,-56,-15,
-29,76,126,177,224,269,313,356,394,427,460,494,527,558,590,622,651,675,700,732,768,
-796,814,829,850,878,906,931,953,973,989,1002,1015,1032,1052,1072,1089,1104,1123,1146,1168,1184,
-1197,1213,1234,1254,1266,1273,1276,1279,1278,1274,1270,1270,1272,1275,1275,1274,1274,1276,1281,1288,1294,
-1299,1305,1314,1329,1349,1375,1403,1428,1449,1469,1487,1499,1503,1505,1510,1519,1527,1550,1559,1562,1562,
-1563,1563,1563,1563,1565,1567,1570,1573,1575,1574,1572,1572,1577,1586,1598,1611,1627,1646,1669,1691,1710,
-1724,1735,1746,1755,1758,1756,1752,1748,1744,1741,1742,1748,1765,1791,1819,1838,1850,1876,1944,2046,2137,
-2181,2193,2224,2295,2377,2433,2461,2490,2527,2556,2557,2535,2498,2446,2376,2297,2224,2161,2105,2057,2020,
-1995,1976,1960,1947,1933,1917,1900,1887,1872,1849,1816,1784,1758,1727,1675,1599,1509,1418,1338,1280,1249,
-1235,1217,1184,1144,1110,1086,1066,1038,996,946,906,897,914,927,903,840,758,673,583,487,405,
-360,350,347,325,283,237,206,200,216,247,281,309,329,351,378,403,402,359,283,197,111,
-1,-167,-388,-597,-730,-778,-792,-821,-875,-926,-959,-978,-993,-1006,-1014,-1014,-1002,-971,-925,-890,-898,
--964,-1067,-1173,-1254,-1305,-1334,-1357,-1382,-1410,-1438,-1457,-1466,-1475,-1498,-1530,-1537,-1489,-1401,-1331,-1325,-1359,
--1365,-1306,-1211,-1136,-1102,-1084,-1055,-1009,-951,-883,-811,-752,-715,-685,-633,-554,-476,-435,-440,-472,-504,
--528,-555,-609,-703,-838,-1003,-1179,-1338,-1452,-1510,-1527,-1530,-1540,-1559,-1576,-1582,-1576,-1566,-1561,-1565,-1574,
--1581,-1582,-1578,-1570,-1562,-1556,-1557,-1563,-1571,-1584,-1608,-1641,-1669,-1683,-1688,-1694,-1696,-1687,-1676,-1682,-1697,
--1685,-1631,-1570,-1555,-1596,-1649,-1670,-1659,-1644,-1648,-1670,-1696,-1716,-1729,-1742,-1764,-1798,-1831,-1855,-1874,-1898,
--1928,-1951,-1958,-1955,-1957,-1970,-1993,-2021,-2053,-2085,-2117,-2153,-2195,-2239,-2281,-2322,-2370,-2428,-2492,-2557,-2622,
--2690,-2762,-2833,-2897,-2951,-3002,-3054,-3112,-3173,-3232,-3286,-3341,-3400,-3460,-3519,-3574,-3631,-3694,-3759,-3820,-3869,
--3907,-3936,-3961,-3983,-4007,-4036,-4074,-4117,-4159,-4198,-4236,-4273,-4304,-4333,-4369,-4422,-4482,-4525,-4547,-4563,-4594,
--4642,-4693,-4739,-4778,-4816,-4854,-4894,-4937,-4980,-5020,-5058,-5097,-5137,-5173,-5204,-5236,-5267,-5292,-5300,-5289,-5262,
--5237,-5235,-5268,-5323,-5368,-5378,-5347,-5285,-5195,-5082,-4959,-4855,-4811,-4858,-4993,-5166,-5299,-5346,-5329,-5301,-5285,
--5263,-5222,-5196,-5220,-5272,-5293,-5261,-5213,-5189,-5176,-5133,-5052,-4970,-4929,-4942,-4999,-5072,-5123,-5124,-5079,-5025,
--4989,-4965,-4933,-4893,-4861,-4836,-4800,-4745,-4693,-4666,-4657,-4640,-4604,-4562,-4531,-4509,-4480,-4435,-4379,-4326,-4288,
--4266,-4256,-4246,-4224,-4185,-4133,-4073,-4008,-3944,-3882,-3821,-3758,-3694,-3632,-3575,-3520,-3465,-3408,-3354,-3301,-3248,
--3192,-3137,-3084,-3031,-2972,-2907,-2843,-2784,-2730,-2680,-2629,-2574,-2510,-2433,-2352,-2274,-2200,-2126,-2054,-1991,-1938,
--1885,-1824,-1762,-1710,-1665,-1606,-1518,-1412,-1317,-1250,-1204,-1165,-1125,-1087,-1049,-1001,-941,-874,-805,-737,-675,
--620,-567,-502,-411,-289,-140,29,202,355,475,569,651,729,794,846,903,980,1070,1153,1222,1285,
-1350,1417,1487,1568,1660,1748,1817,1870,1923,1978,2031,2079,2130,2183,2233,2280,2335,2407,2487,2561,2636,
-2726,2821,2884,2881,2826,2770,2758,2801,2881,2978,3072,3145,3187,3204,3208,3210,3209,3209,3219,3249,3296,
-3351,3406,3458,3503,3541,3578,3627,3690,3756,3813,3863,3916,3967,4008,4047,4102,4179,4257,4313,4350,4385,
-4433,4489,4545,4598,4650,4701,4761,4831,4901,4949,4964,4966,4974,4987,4992,4994,5015,5069,5145,5220,5284,
-5337,5383,5431,5494,5578,5673,5758,5828,5891,5953,5999,6010,5991,5966,5959,5965,5955,5905,5827,5763,5745,
-5773,5816,5846,5860,5873,5900,5940,5980,6002,6004,5998,5999,6005,6003,5990,5977,5972,5973,5966,5950,5932,
-5917,5911,5918,5938,5961,5979,5997,6021,6042,6042,6019,5994,5973,5949,5918,5891,5864,5815,5747,5721,5792,
-5916,5976,5912,5794,5741,5781,5848,5878,5866,5832,5786,5740,5727,5773,5856,5942,6017,6085,6125,6107,6038,
-5978,5972,6001,6015,5998,5983,5998,6028,6039,6021,5994,5970,5905,5747,5528,5386,5466,5766,6124,6370,6475,
-6530,6606,6679,6699,6674,6649,6643,6636,6613,6587,6570,6551,6524,6495,6472,6447,6408,6363,6326,6300,6272,
-6232,6186,6139,6092,6048,6012,5979,5934,5871,5800,5745,5720,5720,5722,5700,5634,5533,5424,5330,5253,5182,
-5112,5049,5002,4979,4985,5018,5056,5071,5049,5004,4961,4932,4917,4911,4910,4909,4907,4902,4894,4878,4856,
-4839,4836,4829,4797,4739,4677,4586,4373,3946,3344,2766,2434,2416,2592,2784,2899,2942,2943,2905,2833,2760,
-2720,2703,2668,2591,2491,2395,2310,2220,2116,2007,1908,1828,1765,1712,1659,1610,1568,1534,1499,1458,1423,
-1401,1383,1355,1329,1332,1363,1379,1341,1262,1193,1160,1149,1132,1101,1068,1037,1003,965,926,889,852,
-818,795,784,778,769,757,742,725,708,694,679,657,626,595,570,546,511,469,445,454,479,
-486,455,405,367,351,344,329,305,285,274,267,268,280,297,298,282,285,347,448,512,473,
-344,198,98,42,-14,-94,-180,-240,-262,-270,-292,-334,-376,-403,-416,-428,-448,-474,-504,-534,-557,
--570,-586,-618,-653,-660,-631,-609,-642,-715,-767,-761,-726,-721,-760,-812,-843,-853,-860,-868,-871,-867,
--869,-883,-905,-925,-941,-953,-965,-979,-995,-1012,-1029,-1046,-1061,-1074,-1085,-1095,-1104,-1113,-1119,-1122,-1123,
--1122,-1122,-1123,-1124,-1121,-1112,-1101,-1093,-1090,-1087,-1082,-1075,-1070,-1067,-1065,-1062,-1060,-1058,-1057,-1056,-1050,
--1036,-1020,-1009,-1003,-996,-982,-966,-955,-950,-943,-928,-910,-893,-873,-848,-826,-813,-803,-787,-764,-743,
--726,-709,-690,-672,-660,-650,-635,-616,-599,-586,-571,-552,-533,-517,-502,-487,-471,-456,-441,-425,-411,
--396,-381,-364,-347,-334,-323,-310,-298,-287,-278,-267,-255,-246,-241,-235,-225,-216,-209,-206,-204,-202,
--204,-204,-202,-198,-199,-205,-209,-210,-212,-220,-228,-231,-231,-235,-245,-255,-261,-266,-273,-281,-285,
--287,-292,-302,-312,-321,-328,-334,-341,-347,-354,-360,-364,-371,-382,-397,-409,-417,-423,-432,-444,-456,
--467,-478,-491,-503,-510,-513,-514,-517,-525,-533,-535,-529,-525,-528,-536,-542,-544,-543,-542,-540,-535,
--532,-530,-526,-515,-504,-498,-497,-493,-485,-480,-481,-480,-472,-458,-447,-442,-438,-432,-424,-415,-403,
--389,-374,-363,-353,-342,-331,-322,-312,-300,-286,-272,-258,-242,-226,-212,-202,-192,-179,-162,-143,-126,
--109,-90,-69,-49,-28,-5,23,54,83,112,146,184,220,251,283,323,370,415,454,495,544,
-600,660,721,781,842,904,969,1030,1080,1117,1155,1205,1268,1332,1389,1435,1474,1510,1548,1588,1625,
-1653,1674,1697,1726,1753,1764,1739,1669,1555,1430,1344,1337,1421,1582,1807,2076,2348,2575,2748,2912,3139,
-3458,3829,4163,4377,4453,4440,4416,4422,4437,4431,4413,4424,4471,4504,4469,4366,4241,4142,4074,4010,3909,
-3752,3556,3364,3200,3040,2835,2580,2331,2161,2088,2084,2114,2160,2203,2220,2206,2185,2178,2174,2142,2066,
-1955,1829,1701,1589,1507,1450,1395,1327,1248,1169,1086,992,889,788,693,595,488,383,288,202,122,
-46,-29,-110,-191,-256,-299,-338,-397,-473,-548,-610,-669,-728,-773,-794,-799,-812,-846,-905,-994,-1110,
--1232,-1325,-1375,-1387,-1368,-1317,-1240,-1170,-1140,-1147,-1164,-1165,-1158,-1160,-1178,-1201,-1215,-1210,-1186,-1155,-1125,
--1096,-1066,-1042,-1038,-1054,-1067,-1058,-1034,-1013,-1004,-1003,-1007,-1013,-1013,-992,-950,-902,-862,-830,-796,-756,
--711,-659,-607,-590,-649,-792,-963,-1077,-1070,-949,-783,-667,-659,-741,-839,-888,-878,-840,-808,-785,-763,
--740,-718,-698,-676,-657,-644,-637,-629,-617,-603,-593,-586,-578,-571,-568,-573,-586,-602,-615,-627,-641,
--658,-675,-689,-701,-714,-726,-735,-740,-740,-737,-729,-720,-709,-696,-678,-656,-632,-609,-584,-551,-511,
--467,-417,-362,-307,-261,-224,-193,-166,-142,-119,-92,-57,-18,22,65,112,161,206,250,296,341,
-380,414,447,483,519,550,581,613,643,667,690,719,753,785,806,823,846,880,919,952,977,
-996,1011,1024,1035,1048,1066,1088,1106,1120,1137,1159,1184,1202,1214,1226,1243,1261,1271,1272,1271,1271,
-1271,1269,1266,1265,1266,1269,1272,1273,1273,1276,1283,1292,1300,1305,1312,1324,1340,1361,1386,1415,1444,
-1467,1484,1496,1505,1509,1513,1521,1535,1550,1577,1589,1593,1593,1589,1586,1582,1582,1583,1585,1588,1591,
-1593,1596,1598,1600,1605,1613,1625,1640,1655,1673,1695,1719,1739,1753,1764,1776,1786,1790,1791,1792,1792,
-1786,1776,1772,1782,1802,1823,1837,1843,1848,1875,1946,2055,2162,2227,2251,2275,2328,2394,2441,2470,2502,
-2547,2584,2591,2566,2519,2453,2374,2293,2222,2162,2110,2066,2034,2014,2001,1991,1984,1977,1963,1946,1931,
-1920,1905,1882,1858,1834,1796,1732,1647,1554,1463,1380,1317,1285,1276,1267,1236,1189,1145,1117,1100,1084,
-1063,1034,1007,995,1001,1002,969,895,798,698,601,514,454,433,436,433,405,362,326,308,308,
-318,333,349,364,383,411,444,464,455,410,348,292,241,157,0,-223,-445,-594,-660,-693,-742,
--810,-865,-895,-913,-935,-957,-966,-953,-925,-893,-872,-877,-921,-1000,-1094,-1178,-1241,-1285,-1322,-1357,-1386,
--1405,-1414,-1419,-1419,-1418,-1422,-1435,-1437,-1398,-1317,-1243,-1227,-1264,-1293,-1268,-1198,-1129,-1084,-1054,-1022,-977,
--910,-816,-705,-608,-547,-510,-467,-408,-354,-326,-327,-352,-394,-452,-518,-589,-682,-817,-995,-1185,-1338,
--1426,-1458,-1466,-1476,-1495,-1513,-1523,-1526,-1524,-1521,-1518,-1518,-1521,-1521,-1519,-1515,-1512,-1507,-1503,-1503,-1511,
--1529,-1556,-1591,-1623,-1639,-1636,-1623,-1612,-1595,-1557,-1504,-1470,-1479,-1517,-1549,-1560,-1562,-1572,-1584,-1591,-1591,
--1597,-1613,-1633,-1648,-1651,-1648,-1648,-1665,-1698,-1736,-1766,-1788,-1811,-1840,-1863,-1870,-1861,-1849,-1848,-1866,-1900,
--1943,-1982,-2017,-2053,-2095,-2139,-2182,-2227,-2277,-2332,-2388,-2445,-2509,-2579,-2651,-2720,-2782,-2839,-2893,-2950,-3013,
--3078,-3138,-3191,-3242,-3297,-3353,-3407,-3461,-3521,-3590,-3660,-3720,-3763,-3796,-3823,-3849,-3875,-3905,-3942,-3985,-4028,
--4066,-4103,-4145,-4189,-4226,-4258,-4297,-4350,-4406,-4444,-4461,-4477,-4512,-4563,-4615,-4657,-4692,-4727,-4765,-4807,-4853,
--4897,-4940,-4981,-5023,-5064,-5099,-5129,-5157,-5183,-5198,-5197,-5182,-5166,-5163,-5185,-5232,-5289,-5330,-5332,-5291,-5217,
--5119,-5001,-4880,-4786,-4761,-4826,-4968,-5133,-5252,-5291,-5274,-5249,-5234,-5213,-5179,-5161,-5187,-5237,-5257,-5229,-5184,
--5155,-5129,-5072,-4987,-4921,-4913,-4962,-5032,-5086,-5101,-5075,-5027,-4987,-4968,-4955,-4929,-4892,-4860,-4834,-4799,-4748,
--4701,-4677,-4674,-4666,-4638,-4597,-4562,-4539,-4516,-4480,-4426,-4368,-4322,-4296,-4282,-4263,-4231,-4190,-4144,-4092,-4032,
--3968,-3905,-3846,-3787,-3725,-3665,-3610,-3557,-3501,-3442,-3384,-3330,-3276,-3221,-3167,-3117,-3068,-3013,-2953,-2892,-2836,
--2785,-2737,-2688,-2635,-2571,-2493,-2407,-2322,-2242,-2166,-2094,-2033,-1986,-1945,-1896,-1838,-1783,-1734,-1676,-1593,-1493,
--1400,-1332,-1284,-1244,-1209,-1181,-1151,-1105,-1038,-959,-877,-796,-717,-644,-575,-494,-384,-244,-88,66,208,
-329,429,511,591,673,750,816,878,948,1025,1097,1158,1214,1272,1334,1404,1485,1572,1649,1707,1755,
-1802,1851,1894,1934,1983,2045,2113,2184,2261,2340,2406,2457,2512,2592,2679,2730,2722,2684,2667,2697,2759,
-2831,2908,2988,3060,3105,3121,3123,3125,3126,3124,3123,3140,3182,3240,3299,3354,3404,3455,3509,3567,3626,
-3680,3728,3774,3824,3873,3918,3966,4028,4103,4175,4231,4277,4327,4385,4437,4478,4514,4556,4609,4678,4758,
-4834,4886,4911,4923,4936,4946,4943,4937,4953,5004,5079,5155,5221,5280,5337,5397,5465,5547,5639,5728,5805,
-5868,5920,5956,5969,5956,5933,5921,5928,5933,5909,5853,5790,5756,5757,5773,5784,5787,5796,5819,5853,5882,
-5896,5894,5887,5885,5887,5886,5884,5888,5898,5901,5890,5871,5857,5849,5846,5852,5876,5916,5958,5993,6018,
-6025,6011,5984,5959,5938,5906,5865,5830,5800,5749,5683,5666,5750,5883,5938,5859,5733,5682,5729,5799,5826,
-5816,5797,5772,5738,5721,5748,5817,5905,6006,6117,6194,6182,6086,5985,5951,5980,6010,6006,5991,5999,6025,
-6036,6017,5990,5967,5906,5750,5513,5324,5338,5583,5925,6203,6368,6483,6597,6681,6693,6655,6626,6631,6640,
-6625,6596,6572,6553,6526,6496,6471,6448,6414,6369,6328,6297,6271,6236,6191,6140,6090,6049,6021,5991,5944,
-5875,5797,5734,5696,5681,5669,5640,5575,5478,5366,5262,5174,5103,5053,5025,5011,5001,5000,5021,5059,5088,
-5083,5045,4998,4962,4944,4941,4945,4949,4949,4943,4931,4913,4895,4888,4889,4879,4836,4765,4672,4516,4210,
-3717,3142,2692,2516,2578,2720,2821,2872,2918,2955,2942,2870,2788,2747,2735,2704,2627,2525,2425,2330,2228,
-2113,1999,1901,1826,1767,1712,1654,1597,1552,1517,1479,1440,1416,1411,1404,1374,1334,1321,1338,1343,1303,
-1231,1173,1149,1141,1125,1102,1080,1054,1018,978,948,921,884,836,795,776,774,777,774,764,744,
-719,695,672,644,609,573,548,528,498,454,423,425,451,460,431,383,353,354,363,355,328,
-296,267,240,221,219,227,224,199,180,201,258,300,279,200,109,42,-6,-62,-136,-214,-270,
--295,-302,-313,-342,-382,-423,-455,-479,-493,-505,-523,-548,-568,-580,-598,-640,-690,-707,-680,-650,-670,
--732,-780,-775,-742,-737,-772,-818,-846,-862,-881,-900,-906,-900,-899,-910,-930,-946,-956,-964,-971,-979,
--990,-1006,-1026,-1047,-1063,-1075,-1084,-1093,-1102,-1110,-1115,-1118,-1121,-1122,-1123,-1124,-1124,-1120,-1112,-1104,-1099,
--1096,-1092,-1085,-1077,-1070,-1066,-1063,-1060,-1056,-1053,-1050,-1050,-1048,-1040,-1027,-1014,-1006,-997,-982,-965,-953,
--948,-941,-930,-915,-897,-876,-850,-828,-815,-805,-790,-768,-748,-732,-715,-694,-675,-661,-650,-635,-618,
--601,-586,-569,-550,-533,-519,-506,-491,-474,-457,-441,-426,-412,-399,-383,-366,-350,-337,-325,-312,-299,
--286,-274,-261,-250,-243,-239,-234,-224,-214,-208,-203,-200,-199,-202,-202,-198,-194,-195,-201,-205,-206,
--209,-215,-221,-223,-225,-230,-240,-249,-255,-262,-272,-280,-283,-285,-289,-298,-308,-319,-329,-336,-339,
--340,-343,-351,-362,-376,-390,-400,-405,-410,-419,-430,-439,-446,-456,-470,-484,-495,-500,-503,-504,-506,
--510,-515,-515,-510,-507,-512,-523,-531,-532,-530,-527,-522,-515,-509,-506,-500,-486,-473,-469,-471,-468,
--459,-451,-452,-454,-448,-435,-424,-419,-416,-411,-403,-393,-380,-364,-348,-335,-323,-314,-305,-296,-284,
--270,-255,-244,-234,-222,-208,-194,-184,-173,-158,-141,-123,-107,-89,-67,-41,-15,6,28,54,81,
-108,134,165,201,237,269,301,337,379,422,464,509,558,609,662,720,780,841,900,958,1015,
-1066,1106,1142,1188,1247,1312,1372,1422,1464,1499,1534,1571,1613,1653,1687,1715,1743,1775,1811,1841,1838,
-1773,1647,1499,1386,1356,1429,1604,1851,2117,2347,2531,2716,2968,3307,3695,4053,4308,4428,4438,4406,4392,
-4403,4410,4400,4399,4430,4474,4473,4399,4277,4158,4067,3983,3867,3705,3526,3373,3251,3111,2897,2612,2335,
-2149,2076,2075,2100,2130,2156,2167,2159,2146,2145,2149,2135,2082,1990,1869,1740,1631,1560,1515,1468,1400,
-1319,1237,1155,1063,963,862,763,659,550,444,344,245,145,51,-35,-119,-200,-269,-321,-368,-428,
--501,-573,-640,-707,-774,-818,-828,-817,-812,-831,-881,-967,-1087,-1215,-1314,-1361,-1365,-1336,-1278,-1199,-1127,
--1089,-1082,-1081,-1071,-1065,-1079,-1113,-1147,-1165,-1166,-1158,-1143,-1117,-1078,-1036,-1013,-1022,-1052,-1079,-1086,-1080,
--1071,-1058,-1039,-1023,-1022,-1027,-1014,-969,-902,-837,-784,-741,-699,-652,-603,-572,-594,-688,-837,-986,-1074,
--1069,-980,-857,-767,-755,-806,-862,-875,-847,-809,-783,-767,-748,-725,-702,-680,-655,-632,-615,-605,-598,
--588,-577,-567,-559,-555,-554,-554,-557,-567,-581,-597,-612,-627,-644,-662,-677,-690,-706,-723,-736,-742,
--743,-742,-737,-728,-718,-706,-691,-670,-645,-618,-589,-555,-516,-476,-432,-383,-331,-281,-240,-205,-176,
--148,-120,-89,-54,-18,17,57,102,149,194,238,285,331,371,406,442,481,518,550,578,606,
-633,657,680,707,742,776,804,827,854,894,938,977,1004,1023,1040,1055,1064,1071,1083,1102,1122,
-1138,1153,1173,1196,1215,1227,1238,1250,1261,1265,1263,1261,1261,1262,1261,1258,1256,1256,1259,1265,1271,
-1275,1278,1282,1291,1300,1309,1320,1336,1355,1376,1400,1428,1458,1482,1498,1508,1517,1526,1534,1546,1561,
-1577,1604,1611,1613,1611,1606,1601,1598,1598,1601,1605,1609,1612,1615,1619,1624,1628,1630,1637,1650,1668,
-1684,1700,1720,1745,1770,1788,1803,1815,1825,1828,1829,1834,1838,1834,1821,1816,1827,1843,1850,1846,1843,
-1856,1899,1985,2107,2230,2310,2337,2341,2359,2394,2429,2461,2505,2560,2603,2611,2583,2531,2463,2386,2309,
-2242,2185,2136,2097,2074,2062,2052,2041,2033,2027,2018,2004,1990,1979,1965,1946,1925,1901,1858,1788,1701,
-1613,1525,1438,1364,1325,1320,1318,1291,1241,1193,1163,1148,1138,1127,1113,1095,1077,1065,1049,1013,948,
-863,772,685,611,561,535,518,494,459,427,410,406,408,413,418,424,431,446,470,494,497,
-468,413,351,303,262,191,51,-152,-357,-501,-573,-619,-679,-748,-799,-823,-843,-871,-898,-902,-876,
--836,-806,-806,-847,-925,-1018,-1104,-1167,-1211,-1250,-1295,-1340,-1372,-1383,-1381,-1378,-1375,-1364,-1348,-1339,-1332,
--1301,-1234,-1163,-1136,-1164,-1205,-1209,-1170,-1114,-1063,-1022,-986,-947,-881,-768,-625,-498,-419,-380,-346,-303,
--262,-234,-225,-242,-302,-400,-506,-597,-687,-814,-991,-1179,-1318,-1384,-1399,-1407,-1426,-1448,-1461,-1465,-1467,
--1472,-1473,-1469,-1462,-1457,-1456,-1454,-1451,-1450,-1450,-1450,-1453,-1465,-1492,-1531,-1573,-1599,-1594,-1559,-1510,-1468,
--1435,-1396,-1345,-1302,-1294,-1328,-1385,-1433,-1459,-1469,-1476,-1492,-1519,-1548,-1571,-1583,-1587,-1587,-1585,-1586,-1599,
--1625,-1658,-1684,-1699,-1711,-1728,-1746,-1758,-1755,-1744,-1738,-1754,-1794,-1844,-1888,-1923,-1959,-1999,-2042,-2087,-2135,
--2186,-2237,-2286,-2338,-2401,-2472,-2542,-2608,-2669,-2730,-2791,-2853,-2918,-2985,-3045,-3096,-3142,-3189,-3240,-3292,-3348,
--3413,-3486,-3555,-3608,-3645,-3677,-3710,-3745,-3779,-3814,-3854,-3898,-3941,-3980,-4019,-4064,-4111,-4152,-4189,-4230,-4281,
--4328,-4359,-4375,-4395,-4434,-4486,-4535,-4575,-4609,-4642,-4680,-4724,-4773,-4823,-4868,-4908,-4948,-4987,-5021,-5048,-5071,
--5088,-5093,-5086,-5077,-5080,-5103,-5146,-5199,-5249,-5276,-5267,-5218,-5137,-5032,-4914,-4803,-4732,-4733,-4816,-4957,-5102,
--5198,-5224,-5207,-5187,-5179,-5166,-5142,-5132,-5158,-5201,-5218,-5190,-5145,-5107,-5069,-5007,-4933,-4893,-4913,-4977,-5039,
--5067,-5057,-5022,-4981,-4952,-4942,-4935,-4915,-4883,-4851,-4822,-4787,-4742,-4702,-4685,-4690,-4693,-4672,-4629,-4586,-4558,
--4541,-4516,-4468,-4407,-4356,-4326,-4307,-4280,-4239,-4194,-4152,-4109,-4054,-3991,-3929,-3872,-3815,-3754,-3693,-3636,-3582,
--3526,-3468,-3410,-3357,-3307,-3257,-3205,-3152,-3098,-3044,-2989,-2934,-2881,-2830,-2780,-2730,-2676,-2615,-2543,-2460,-2375,
--2292,-2212,-2141,-2087,-2054,-2030,-1995,-1940,-1877,-1816,-1749,-1661,-1555,-1456,-1386,-1343,-1315,-1295,-1283,-1269,-1230,
--1155,-1053,-943,-835,-731,-635,-545,-450,-336,-204,-70,52,163,266,362,453,544,639,733,816,887,
-951,1011,1065,1114,1160,1210,1267,1333,1407,1482,1545,1596,1645,1702,1759,1805,1839,1876,1926,1992,2072,
-2163,2248,2308,2345,2388,2459,2537,2580,2575,2560,2581,2642,2715,2778,2839,2910,2979,3022,3033,3030,3031,
-3034,3029,3020,3028,3066,3128,3194,3252,3307,3368,3436,3503,3560,3607,3649,3693,3740,3788,3836,3887,3946,
-4007,4063,4115,4175,4246,4315,4362,4388,4412,4452,4517,4600,4687,4762,4814,4845,4868,4888,4896,4888,4878,
-4892,4941,5013,5087,5157,5227,5302,5377,5449,5524,5608,5700,5785,5852,5896,5922,5934,5929,5907,5886,5883,
-5895,5895,5866,5819,5781,5768,5769,5769,5767,5771,5786,5808,5825,5831,5829,5823,5817,5814,5814,5825,5850,
-5874,5876,5852,5820,5800,5794,5791,5790,5805,5840,5889,5935,5965,5970,5953,5927,5906,5887,5855,5817,5789,
-5762,5710,5642,5631,5724,5858,5899,5802,5666,5622,5684,5761,5784,5769,5753,5741,5722,5714,5737,5780,5833,
-5911,6030,6145,6175,6093,5976,5923,5953,6008,6032,6027,6025,6035,6034,6011,5982,5957,5901,5754,5517,5299,
-5256,5450,5783,6098,6317,6468,6587,6663,6671,6635,6611,6621,6635,6625,6600,6577,6557,6527,6491,6462,6440,
-6415,6380,6341,6306,6272,6233,6188,6138,6090,6051,6022,5992,5945,5881,5815,5759,5716,5678,5639,5594,5535,
-5456,5358,5249,5141,5054,5009,5009,5028,5035,5028,5030,5059,5097,5108,5077,5025,4982,4965,4968,4979,4986,
-4987,4984,4977,4962,4944,4931,4926,4915,4881,4814,4690,4450,4033,3473,2939,2634,2618,2758,2869,2882,2866,
-2895,2946,2948,2886,2818,2789,2780,2738,2647,2534,2428,2327,2217,2097,1983,1890,1823,1771,1719,1658,1597,
-1547,1505,1459,1413,1386,1382,1376,1344,1297,1271,1271,1266,1230,1181,1151,1142,1134,1115,1095,1081,1061,
-1030,1002,993,986,953,892,831,796,786,784,780,770,749,719,685,654,625,589,552,525,510,
-488,450,413,400,411,414,385,339,313,320,341,347,330,300,265,225,188,167,162,156,134,
-109,103,117,127,109,66,17,-28,-73,-123,-178,-231,-278,-312,-332,-345,-363,-393,-437,-484,-522,
--541,-546,-551,-564,-577,-585,-601,-643,-701,-736,-728,-703,-705,-744,-781,-788,-781,-790,-821,-850,-866,
--879,-901,-922,-932,-931,-934,-946,-958,-965,-968,-973,-979,-983,-989,-1003,-1025,-1048,-1064,-1073,-1078,-1084,
--1092,-1101,-1108,-1115,-1121,-1125,-1128,-1128,-1126,-1121,-1114,-1110,-1108,-1106,-1101,-1093,-1086,-1079,-1071,-1064,-1058,
--1053,-1047,-1042,-1040,-1041,-1038,-1030,-1017,-1005,-992,-977,-961,-948,-939,-931,-921,-909,-893,-873,-850,-832,
--818,-806,-789,-767,-748,-733,-717,-697,-678,-660,-645,-629,-613,-598,-582,-564,-547,-533,-520,-508,-493,
--477,-461,-444,-428,-414,-400,-385,-368,-353,-341,-327,-313,-299,-287,-275,-261,-249,-243,-240,-235,-226,
--217,-210,-203,-199,-198,-201,-202,-198,-193,-194,-199,-202,-203,-206,-212,-217,-219,-222,-229,-237,-243,
--249,-256,-266,-274,-280,-285,-292,-297,-301,-307,-316,-326,-333,-338,-345,-354,-366,-379,-389,-393,-396,
--403,-416,-430,-435,-437,-444,-458,-472,-479,-482,-484,-487,-489,-491,-496,-498,-497,-497,-504,-513,-518,
--516,-511,-506,-500,-492,-488,-487,-480,-464,-448,-444,-449,-449,-438,-427,-424,-425,-420,-410,-402,-398,
--393,-387,-379,-370,-358,-343,-326,-310,-298,-288,-281,-275,-264,-249,-232,-218,-207,-197,-187,-179,-169,
--157,-140,-120,-101,-83,-64,-42,-16,8,31,52,76,103,131,158,186,218,253,288,322,357,
-394,434,478,529,581,627,670,718,777,841,900,952,1000,1049,1096,1143,1193,1247,1300,1351,1399,
-1444,1483,1518,1554,1598,1647,1693,1730,1759,1787,1823,1869,1909,1909,1844,1717,1562,1430,1378,1448,1636,
-1888,2133,2348,2570,2855,3216,3610,3972,4245,4395,4427,4392,4362,4370,4395,4404,4400,4413,4450,4473,4440,
-4350,4234,4118,4002,3864,3700,3529,3376,3239,3075,2845,2563,2302,2139,2087,2104,2134,2153,2158,2149,2130,
-2112,2103,2099,2084,2044,1976,1882,1777,1682,1614,1569,1522,1459,1382,1301,1216,1124,1027,929,826,714,
-601,497,397,290,172,54,-50,-143,-228,-301,-359,-410,-467,-531,-592,-652,-718,-787,-833,-842,-826,
--813,-824,-865,-941,-1051,-1171,-1263,-1305,-1303,-1270,-1217,-1148,-1081,-1034,-1010,-994,-982,-985,-1013,-1059,-1101,
--1124,-1131,-1130,-1122,-1098,-1059,-1021,-1007,-1027,-1064,-1095,-1111,-1118,-1117,-1100,-1066,-1033,-1018,-1013,-997,-953,
--888,-820,-758,-701,-643,-586,-552,-571,-662,-805,-948,-1041,-1071,-1048,-992,-924,-873,-859,-871,-877,-855,
--816,-785,-767,-750,-726,-698,-673,-650,-627,-605,-589,-579,-572,-565,-557,-547,-539,-537,-541,-546,-548,
--552,-563,-580,-597,-614,-631,-649,-665,-681,-699,-718,-732,-739,-742,-744,-745,-740,-732,-722,-709,-689,
--663,-634,-602,-565,-525,-484,-444,-401,-354,-306,-263,-226,-193,-160,-125,-89,-52,-17,18,56,98,
-144,190,236,283,328,370,407,445,486,526,558,583,606,630,654,678,704,735,767,797,825,
-857,898,943,984,1014,1038,1060,1079,1089,1093,1100,1116,1138,1158,1174,1189,1206,1222,1234,1244,1252,
-1256,1255,1252,1252,1254,1255,1254,1252,1251,1251,1253,1260,1269,1275,1276,1278,1287,1300,1312,1326,1343,
-1364,1387,1412,1440,1470,1496,1515,1530,1544,1559,1572,1584,1595,1604,1625,1626,1625,1621,1616,1612,1610,
-1611,1616,1622,1627,1631,1634,1639,1646,1651,1655,1661,1677,1699,1719,1735,1754,1780,1810,1835,1853,1867,
-1876,1876,1875,1878,1883,1879,1867,1860,1867,1876,1874,1867,1874,1906,1966,2055,2176,2302,2391,2418,2405,
-2391,2396,2417,2448,2494,2550,2594,2605,2583,2540,2484,2419,2353,2293,2239,2191,2157,2140,2134,2127,2115,
-2104,2100,2095,2085,2070,2052,2029,2004,1980,1953,1910,1843,1764,1684,1597,1499,1410,1361,1357,1361,1338,
-1291,1245,1218,1204,1192,1180,1167,1149,1125,1099,1072,1037,987,920,847,779,722,679,640,597,549,
-509,490,487,488,488,490,497,504,510,519,533,541,525,476,401,318,248,192,123,6,-158,
--326,-446,-510,-557,-615,-675,-715,-736,-760,-793,-814,-803,-766,-728,-716,-746,-820,-922,-1023,-1098,-1141,
--1170,-1207,-1257,-1306,-1336,-1344,-1342,-1342,-1338,-1315,-1279,-1251,-1238,-1219,-1171,-1105,-1065,-1075,-1112,-1136,-1123,
--1078,-1020,-968,-934,-908,-850,-730,-567,-421,-334,-296,-267,-227,-184,-150,-134,-156,-236,-364,-497,-601,
--694,-824,-1001,-1180,-1300,-1345,-1350,-1358,-1379,-1400,-1407,-1406,-1410,-1418,-1420,-1411,-1400,-1396,-1398,-1398,-1395,
--1393,-1399,-1406,-1413,-1426,-1456,-1501,-1543,-1558,-1530,-1456,-1353,-1249,-1179,-1157,-1175,-1205,-1229,-1247,-1268,-1296,
--1323,-1345,-1368,-1404,-1450,-1488,-1502,-1498,-1498,-1513,-1538,-1563,-1581,-1597,-1612,-1620,-1619,-1612,-1610,-1619,-1636,
--1646,-1646,-1645,-1662,-1702,-1752,-1796,-1833,-1869,-1909,-1952,-1995,-2043,-2094,-2143,-2188,-2239,-2302,-2372,-2439,-2499,
--2560,-2624,-2690,-2754,-2820,-2886,-2947,-2995,-3037,-3080,-3128,-3180,-3238,-3306,-3378,-3441,-3485,-3519,-3557,-3602,-3648,
--3689,-3726,-3765,-3809,-3853,-3896,-3939,-3985,-4031,-4074,-4116,-4160,-4205,-4243,-4268,-4288,-4316,-4359,-4408,-4454,-4493,
--4528,-4562,-4598,-4644,-4698,-4755,-4803,-4840,-4873,-4907,-4939,-4964,-4979,-4986,-4984,-4979,-4982,-5007,-5053,-5108,-5159,
--5194,-5204,-5182,-5127,-5044,-4939,-4828,-4735,-4691,-4718,-4811,-4941,-5061,-5132,-5147,-5131,-5118,-5118,-5115,-5103,-5099,
--5122,-5155,-5163,-5131,-5081,-5038,-4998,-4947,-4898,-4886,-4924,-4984,-5026,-5032,-5010,-4977,-4944,-4921,-4911,-4908,-4897,
--4871,-4837,-4806,-4773,-4737,-4707,-4698,-4710,-4721,-4706,-4661,-4609,-4576,-4564,-4547,-4506,-4444,-4388,-4354,-4332,-4301,
--4256,-4208,-4167,-4125,-4072,-4011,-3951,-3896,-3841,-3781,-3717,-3657,-3600,-3543,-3485,-3428,-3377,-3333,-3289,-3241,-3188,
--3132,-3077,-3025,-2974,-2923,-2871,-2817,-2763,-2707,-2647,-2579,-2503,-2420,-2337,-2258,-2193,-2151,-2135,-2126,-2101,-2046,
--1973,-1898,-1819,-1723,-1610,-1506,-1437,-1402,-1384,-1373,-1371,-1365,-1326,-1233,-1095,-944,-804,-683,-576,-479,-386,
--287,-183,-82,11,104,203,305,406,507,612,717,813,893,957,1007,1049,1084,1119,1158,1204,1261,
-1326,1390,1443,1489,1542,1611,1686,1747,1787,1814,1843,1887,1952,2035,2119,2182,2225,2270,2335,2400,2435,
-2438,2448,2498,2582,2664,2727,2783,2848,2909,2942,2943,2933,2931,2936,2932,2923,2929,2968,3033,3102,3163,
-3222,3291,3369,3442,3499,3541,3578,3615,3654,3696,3741,3791,3842,3887,3930,3985,4062,4152,4228,4270,4288,
-4311,4361,4443,4538,4625,4692,4740,4777,4810,4835,4841,4828,4817,4830,4877,4946,5022,5100,5186,5278,5365,
-5439,5506,5581,5670,5759,5827,5864,5882,5894,5896,5880,5855,5843,5852,5865,5856,5825,5792,5778,5780,5784,
-5786,5787,5793,5801,5807,5807,5804,5800,5798,5798,5804,5821,5853,5883,5883,5847,5797,5763,5751,5747,5739,
-5736,5751,5785,5826,5857,5866,5854,5839,5830,5821,5802,5778,5763,5742,5686,5617,5614,5723,5866,5903,5792,
-5649,5610,5682,5763,5780,5754,5730,5718,5709,5714,5739,5760,5761,5784,5881,6024,6112,6079,5975,5909,5932,
-6003,6058,6073,6069,6059,6038,6003,5969,5942,5894,5767,5548,5324,5243,5391,5707,6044,6297,6456,6559,6620,
-6636,6623,6614,6619,6621,6608,6589,6576,6561,6534,6499,6467,6444,6420,6390,6356,6320,6280,6236,6192,6147,
-6100,6055,6018,5982,5937,5882,5827,5779,5731,5680,5629,5586,5540,5474,5378,5260,5141,5049,5008,5018,5047,
-5056,5039,5026,5048,5092,5117,5096,5043,4998,4986,5000,5017,5022,5020,5020,5023,5018,4997,4968,4946,4933,
-4914,4857,4704,4381,3858,3237,2736,2539,2639,2840,2944,2921,2875,2886,2925,2926,2884,2850,2845,2831,2761,
-2641,2514,2406,2308,2203,2088,1978,1889,1825,1778,1731,1674,1613,1559,1510,1454,1396,1355,1339,1327,1296,
-1254,1228,1219,1205,1175,1146,1137,1136,1122,1097,1079,1071,1057,1030,1015,1026,1040,1021,965,901,857,
-831,808,782,759,735,703,666,633,606,575,540,512,498,486,458,420,393,386,379,351,307,
-273,267,280,289,286,276,260,235,201,170,148,129,107,85,70,60,45,21,-8,-42,-83,
--132,-178,-215,-247,-285,-330,-368,-390,-403,-422,-457,-504,-549,-576,-584,-585,-589,-596,-601,-612,-644,
--696,-743,-761,-754,-750,-761,-781,-798,-818,-845,-873,-889,-894,-902,-917,-929,-935,-942,-958,-977,-986,
--984,-981,-985,-991,-994,-997,-1006,-1024,-1044,-1057,-1064,-1067,-1072,-1079,-1089,-1100,-1112,-1122,-1130,-1135,-1135,
--1132,-1128,-1122,-1119,-1116,-1113,-1109,-1105,-1102,-1096,-1086,-1074,-1064,-1056,-1049,-1042,-1037,-1038,-1039,-1034,-1022,
--1007,-993,-979,-964,-947,-932,-921,-910,-898,-884,-867,-849,-834,-820,-804,-783,-763,-746,-732,-716,-697,
--678,-659,-641,-624,-608,-592,-576,-559,-543,-530,-517,-504,-490,-477,-462,-445,-429,-414,-399,-383,-366,
--353,-340,-326,-310,-298,-289,-280,-266,-254,-246,-243,-238,-230,-222,-215,-207,-201,-199,-201,-202,-198,
--195,-196,-199,-202,-202,-206,-213,-218,-222,-226,-233,-239,-243,-247,-254,-261,-266,-272,-282,-292,-297,
--297,-298,-304,-314,-325,-335,-345,-353,-362,-371,-380,-386,-390,-399,-413,-425,-427,-426,-430,-443,-455,
--460,-462,-464,-468,-469,-471,-477,-484,-488,-491,-495,-500,-500,-494,-488,-483,-478,-473,-473,-475,-468,
--450,-431,-425,-430,-431,-422,-410,-401,-396,-389,-382,-377,-375,-370,-361,-353,-345,-334,-320,-305,-290,
--276,-264,-257,-252,-247,-234,-216,-196,-180,-170,-165,-162,-155,-142,-124,-102,-79,-56,-35,-17,0,
-19,39,60,84,113,145,176,204,235,269,306,344,381,417,454,498,549,602,646,681,720,
-776,842,904,951,989,1030,1079,1136,1193,1245,1288,1327,1368,1413,1459,1500,1542,1588,1640,1690,1735,
-1771,1803,1835,1874,1921,1966,1980,1930,1800,1613,1439,1371,1457,1667,1926,2183,2458,2787,3173,3569,3921,
-4191,4352,4399,4367,4327,4327,4361,4387,4389,4393,4421,4454,4453,4398,4300,4183,4060,3930,3787,3627,3449,
-3252,3028,2772,2507,2282,2148,2117,2153,2201,2225,2217,2187,2150,2115,2088,2059,2020,1969,1912,1850,1786,
-1723,1669,1621,1572,1512,1440,1359,1271,1180,1089,994,885,760,637,533,438,331,201,66,-55,-159,
--252,-334,-400,-455,-508,-561,-609,-656,-713,-777,-826,-843,-833,-821,-824,-851,-907,-994,-1096,-1180,-1222,
--1223,-1196,-1153,-1098,-1039,-988,-950,-926,-915,-926,-963,-1016,-1064,-1089,-1092,-1084,-1069,-1048,-1022,-1005,-1013,
--1048,-1092,-1123,-1137,-1137,-1121,-1085,-1034,-988,-963,-950,-930,-891,-841,-792,-746,-696,-630,-561,-530,-589,
--744,-936,-1076,-1116,-1079,-1022,-977,-944,-919,-904,-892,-871,-839,-807,-785,-766,-739,-705,-671,-644,-622,
--601,-584,-573,-563,-555,-549,-546,-540,-532,-529,-535,-543,-545,-546,-554,-569,-586,-603,-620,-639,-657,
--673,-689,-707,-720,-728,-731,-735,-738,-737,-731,-722,-709,-689,-665,-639,-609,-572,-530,-489,-451,-413,
--370,-326,-285,-248,-212,-174,-134,-93,-53,-14,23,59,98,142,188,236,283,327,369,409,449,
-491,530,562,587,608,631,657,683,709,734,761,789,817,850,890,934,977,1013,1045,1074,1097,
-1110,1113,1117,1131,1153,1176,1193,1205,1215,1225,1235,1244,1249,1248,1244,1243,1246,1249,1250,1249,1250,
-1253,1255,1258,1263,1271,1275,1277,1281,1292,1308,1321,1333,1349,1372,1399,1426,1454,1483,1511,1535,1555,
-1572,1590,1605,1616,1622,1625,1637,1637,1635,1631,1627,1623,1621,1623,1627,1634,1642,1648,1651,1656,1665,
-1674,1682,1691,1709,1735,1760,1780,1800,1826,1856,1882,1900,1915,1924,1926,1922,1923,1925,1921,1909,1901,
-1903,1910,1915,1927,1960,2012,2070,2138,2229,2339,2428,2461,2446,2419,2409,2417,2436,2469,2511,2548,2566,
-2562,2543,2511,2466,2415,2365,2320,2278,2245,2229,2224,2220,2212,2206,2202,2196,2181,2156,2124,2087,2052,
-2022,1993,1953,1896,1827,1752,1661,1552,1452,1397,1394,1402,1381,1334,1289,1265,1251,1234,1214,1195,1175,
-1149,1118,1088,1055,1013,958,899,847,808,774,732,675,616,576,565,569,571,568,570,581,592,
-595,595,595,588,558,493,393,277,175,104,46,-36,-161,-296,-394,-447,-487,-537,-585,-615,-636,
--666,-697,-703,-672,-630,-615,-647,-724,-834,-954,-1051,-1105,-1123,-1134,-1163,-1208,-1250,-1276,-1287,-1293,-1298,
--1291,-1259,-1214,-1181,-1173,-1169,-1134,-1067,-1007,-993,-1023,-1061,-1065,-1023,-955,-897,-873,-866,-822,-701,-528,
--374,-287,-248,-213,-160,-101,-58,-47,-88,-191,-332,-468,-576,-686,-838,-1026,-1193,-1287,-1310,-1305,-1311,
--1331,-1348,-1353,-1352,-1357,-1363,-1361,-1350,-1340,-1341,-1345,-1342,-1334,-1333,-1347,-1364,-1373,-1384,-1412,-1458,-1498,
--1508,-1474,-1385,-1232,-1039,-883,-852,-963,-1138,-1268,-1301,-1275,-1250,-1253,-1275,-1306,-1345,-1387,-1413,-1408,-1386,
--1383,-1417,-1476,-1531,-1559,-1562,-1552,-1540,-1528,-1516,-1507,-1510,-1528,-1548,-1559,-1565,-1580,-1614,-1659,-1702,-1741,
--1781,-1824,-1864,-1905,-1950,-2000,-2048,-2094,-2145,-2208,-2275,-2337,-2392,-2451,-2518,-2586,-2651,-2716,-2782,-2842,-2889,
--2930,-2972,-3020,-3072,-3132,-3199,-3265,-3320,-3361,-3398,-3446,-3502,-3556,-3599,-3636,-3674,-3716,-3763,-3810,-3856,-3901,
--3943,-3986,-4032,-4078,-4119,-4151,-4176,-4204,-4241,-4285,-4330,-4372,-4410,-4447,-4481,-4517,-4563,-4624,-4687,-4738,-4771,
--4798,-4827,-4857,-4878,-4885,-4883,-4881,-4885,-4907,-4949,-5005,-5061,-5102,-5121,-5114,-5080,-5021,-4940,-4843,-4745,-4671,
--4650,-4693,-4788,-4903,-5002,-5058,-5069,-5058,-5050,-5054,-5059,-5054,-5053,-5069,-5090,-5085,-5044,-4989,-4948,-4921,-4895,
--4877,-4888,-4931,-4979,-5000,-4990,-4967,-4941,-4915,-4894,-4884,-4885,-4880,-4858,-4825,-4792,-4765,-4740,-4720,-4716,-4730,
--4743,-4733,-4691,-4640,-4605,-4591,-4577,-4538,-4477,-4418,-4379,-4353,-4321,-4277,-4229,-4183,-4136,-4081,-4021,-3964,-3910,
--3856,-3796,-3734,-3674,-3617,-3560,-3502,-3446,-3394,-3349,-3309,-3267,-3219,-3166,-3115,-3066,-3016,-2964,-2909,-2854,-2799,
--2739,-2675,-2606,-2531,-2450,-2369,-2297,-2246,-2221,-2217,-2214,-2189,-2129,-2046,-1958,-1868,-1768,-1658,-1559,-1495,-1466,
--1453,-1445,-1443,-1434,-1383,-1261,-1081,-891,-730,-610,-515,-432,-354,-278,-200,-117,-30,62,162,263,364,
-465,569,675,775,862,934,989,1029,1059,1083,1109,1142,1186,1241,1297,1343,1382,1430,1500,1586,1667,
-1725,1759,1781,1804,1842,1899,1970,2038,2096,2154,2214,2265,2295,2313,2350,2424,2519,2606,2672,2729,2787,
-2833,2852,2844,2831,2829,2836,2839,2838,2850,2890,2953,3019,3078,3139,3212,3294,3371,3429,3471,3505,3536,
-3567,3601,3643,3692,3737,3774,3814,3875,3965,4065,4140,4178,4195,4225,4291,4388,4492,4577,4638,4685,4728,
-4769,4794,4794,4775,4759,4769,4810,4874,4952,5041,5140,5244,5339,5419,5485,5554,5636,5721,5785,5817,5831,
-5844,5855,5852,5833,5819,5823,5835,5833,5811,5786,5776,5783,5796,5803,5804,5804,5806,5808,5804,5797,5794,
-5803,5821,5839,5858,5881,5901,5896,5853,5788,5736,5713,5707,5698,5685,5680,5692,5716,5738,5744,5740,5739,
-5750,5758,5751,5738,5730,5713,5658,5593,5605,5737,5902,5950,5841,5695,5652,5716,5783,5784,5744,5712,5698,
-5693,5705,5733,5741,5709,5685,5750,5900,6034,6056,5982,5910,5909,5969,6037,6079,6092,6079,6044,5995,5952,
-5924,5884,5780,5588,5368,5250,5333,5600,5934,6213,6393,6496,6555,6588,6605,6615,6616,6604,6585,6571,6565,
-6556,6537,6511,6486,6457,6423,6388,6356,6326,6289,6247,6205,6163,6113,6060,6012,5971,5926,5872,5815,5760,
-5708,5659,5619,5590,5549,5470,5352,5222,5114,5048,5026,5035,5051,5048,5025,5009,5030,5079,5116,5106,5060,
-5020,5015,5038,5060,5062,5052,5050,5061,5066,5047,5008,4971,4952,4938,4876,4682,4280,3678,3023,2550,2416,
-2569,2797,2917,2914,2883,2888,2907,2898,2877,2878,2890,2860,2755,2608,2474,2375,2291,2199,2097,1993,1903,
-1834,1786,1743,1692,1635,1582,1531,1473,1409,1354,1321,1299,1272,1242,1224,1213,1193,1163,1140,1133,1126,
-1104,1076,1062,1059,1046,1019,1005,1020,1044,1040,1004,961,929,898,853,801,758,724,688,649,616,
-592,569,538,508,491,482,463,429,395,374,360,337,298,258,232,219,213,211,219,235,244,
-235,207,169,130,97,73,55,36,10,-18,-44,-73,-114,-167,-213,-243,-267,-301,-348,-393,-424,
--442,-460,-488,-525,-565,-597,-614,-619,-622,-629,-635,-642,-657,-691,-736,-777,-798,-800,-796,-798,-811,
--837,-866,-888,-900,-910,-922,-931,-929,-924,-934,-962,-992,-1006,-1005,-1003,-1007,-1014,-1017,-1018,-1022,-1032,
--1043,-1052,-1058,-1063,-1069,-1075,-1084,-1096,-1108,-1121,-1131,-1138,-1140,-1139,-1136,-1133,-1129,-1124,-1120,-1118,-1118,
--1120,-1117,-1106,-1091,-1077,-1067,-1059,-1051,-1043,-1041,-1043,-1041,-1031,-1016,-1002,-989,-974,-955,-935,-917,-904,
--890,-875,-859,-845,-834,-819,-800,-779,-761,-748,-734,-717,-697,-678,-660,-642,-625,-609,-591,-572,-554,
--539,-524,-509,-494,-482,-471,-458,-441,-425,-411,-396,-379,-362,-349,-337,-323,-308,-297,-292,-285,-272,
--260,-252,-248,-242,-234,-226,-220,-213,-205,-201,-201,-200,-198,-196,-199,-203,-205,-206,-211,-218,-224,
--228,-233,-240,-245,-248,-252,-258,-262,-262,-265,-275,-288,-295,-296,-297,-301,-309,-319,-330,-339,-345,
--350,-358,-372,-384,-391,-396,-404,-412,-414,-413,-418,-428,-438,-443,-444,-447,-450,-451,-454,-462,-471,
--477,-479,-481,-481,-478,-471,-466,-462,-459,-457,-460,-462,-455,-435,-415,-406,-409,-410,-402,-391,-379,
--368,-357,-350,-349,-349,-344,-337,-330,-322,-311,-297,-283,-271,-257,-243,-232,-228,-224,-215,-198,-176,
--158,-148,-144,-141,-132,-119,-102,-83,-58,-31,-7,7,18,32,51,71,94,122,154,188,220,
-252,288,325,364,403,443,481,521,566,614,658,693,730,780,843,905,953,988,1021,1064,1118,
-1176,1227,1266,1300,1337,1384,1434,1484,1533,1584,1633,1679,1721,1765,1809,1849,1882,1920,1974,2034,2058,
-1992,1813,1573,1386,1351,1487,1737,2038,2373,2749,3153,3543,3875,4129,4290,4351,4332,4293,4286,4316,4350,
-4364,4376,4405,4442,4452,4412,4329,4223,4118,4019,3914,3772,3568,3308,3025,2751,2509,2316,2198,2169,2210,
-2271,2305,2293,2248,2195,2150,2108,2052,1975,1889,1817,1772,1749,1733,1710,1677,1631,1573,1503,1422,1334,
-1248,1164,1070,949,806,667,557,465,362,231,89,-39,-150,-253,-350,-432,-494,-543,-584,-620,-656,
--703,-761,-813,-841,-842,-831,-825,-832,-861,-919,-998,-1077,-1130,-1148,-1137,-1108,-1065,-1013,-959,-913,-882,
--869,-881,-921,-977,-1029,-1053,-1045,-1019,-993,-975,-968,-976,-1011,-1069,-1131,-1169,-1171,-1140,-1084,-1012,-942,
--890,-863,-851,-834,-803,-765,-738,-725,-709,-661,-584,-535,-590,-767,-989,-1137,-1158,-1092,-1019,-976,-954,
--932,-907,-882,-856,-830,-808,-789,-762,-724,-685,-654,-630,-604,-580,-565,-557,-548,-537,-532,-536,-540,
--537,-532,-535,-542,-546,-548,-555,-569,-584,-600,-617,-638,-657,-669,-680,-692,-705,-713,-715,-717,-718,
--717,-711,-702,-687,-667,-645,-624,-600,-569,-530,-491,-454,-419,-380,-340,-302,-266,-228,-187,-144,-102,
--60,-16,24,60,96,136,182,229,275,318,360,402,444,483,520,553,580,603,626,654,684,
-712,737,761,787,815,848,885,928,974,1018,1056,1090,1115,1130,1134,1137,1145,1163,1184,1202,1214,
-1221,1227,1234,1242,1245,1242,1238,1237,1242,1245,1244,1244,1249,1257,1264,1268,1272,1277,1280,1283,1291,
-1305,1322,1335,1346,1361,1386,1416,1445,1471,1497,1524,1549,1568,1583,1597,1612,1625,1633,1637,1637,1640,
-1642,1641,1637,1633,1632,1633,1637,1646,1657,1668,1674,1679,1688,1702,1715,1728,1748,1777,1809,1834,1855,
-1877,1900,1919,1933,1946,1959,1964,1964,1964,1967,1966,1958,1953,1957,1972,1995,2032,2088,2145,2184,2212,
-2260,2340,2421,2464,2463,2446,2437,2436,2437,2447,2470,2499,2523,2536,2540,2531,2508,2475,2442,2411,2382,
-2354,2336,2329,2329,2330,2330,2324,2304,2269,2224,2177,2132,2092,2059,2030,1995,1945,1882,1807,1712,1600,
-1502,1453,1452,1458,1432,1379,1330,1303,1285,1262,1234,1208,1186,1163,1138,1111,1080,1038,986,935,895,
-868,843,806,752,696,664,661,672,677,674,673,678,680,672,656,640,621,583,507,388,245,
-125,63,39,-4,-104,-229,-323,-370,-403,-448,-492,-520,-542,-572,-596,-583,-537,-504,-530,-622,-756,
--901,-1031,-1116,-1142,-1128,-1112,-1119,-1148,-1179,-1203,-1221,-1233,-1235,-1219,-1186,-1149,-1131,-1137,-1142,-1109,-1032,
--951,-916,-942,-990,-1004,-960,-881,-821,-813,-828,-800,-685,-513,-360,-269,-222,-170,-95,-15,36,35,
--33,-158,-301,-425,-533,-667,-852,-1053,-1202,-1264,-1264,-1252,-1258,-1275,-1289,-1296,-1300,-1304,-1305,-1300,-1290,
--1286,-1289,-1287,-1272,-1255,-1257,-1283,-1311,-1322,-1328,-1352,-1397,-1437,-1458,-1455,-1396,-1228,-946,-671,-581,-751,
--1067,-1325,-1406,-1352,-1279,-1251,-1259,-1276,-1296,-1320,-1330,-1313,-1280,-1269,-1304,-1373,-1438,-1465,-1451,-1421,-1400,
--1400,-1408,-1415,-1424,-1441,-1464,-1480,-1487,-1499,-1526,-1564,-1605,-1647,-1692,-1737,-1778,-1816,-1860,-1909,-1957,-2003,
--2054,-2115,-2178,-2234,-2286,-2344,-2410,-2479,-2545,-2612,-2678,-2735,-2782,-2823,-2868,-2918,-2971,-3028,-3091,-3152,-3202,
--3244,-3290,-3349,-3411,-3465,-3506,-3543,-3582,-3625,-3672,-3721,-3769,-3812,-3850,-3891,-3938,-3986,-4027,-4059,-4088,-4124,
--4167,-4210,-4251,-4289,-4328,-4365,-4400,-4435,-4483,-4548,-4615,-4667,-4698,-4721,-4747,-4774,-4790,-4792,-4788,-4792,-4811,
--4848,-4897,-4948,-4992,-5019,-5024,-5005,-4963,-4904,-4830,-4744,-4661,-4603,-4597,-4647,-4737,-4840,-4928,-4983,-4999,-4993,
--4987,-4992,-4999,-4999,-4997,-5004,-5011,-4993,-4945,-4891,-4860,-4853,-4855,-4863,-4887,-4927,-4961,-4968,-4951,-4929,-4909,
--4890,-4872,-4864,-4866,-4863,-4842,-4809,-4779,-4759,-4744,-4733,-4731,-4742,-4753,-4746,-4714,-4671,-4636,-4616,-4597,-4561,
--4507,-4449,-4403,-4367,-4332,-4290,-4244,-4196,-4142,-4084,-4024,-3967,-3911,-3854,-3795,-3737,-3682,-3629,-3575,-3521,-3467,
--3415,-3367,-3325,-3285,-3243,-3196,-3150,-3104,-3054,-2998,-2940,-2884,-2829,-2768,-2699,-2627,-2551,-2473,-2398,-2337,-2302,
--2290,-2289,-2281,-2249,-2183,-2092,-1993,-1894,-1795,-1695,-1608,-1552,-1527,-1519,-1517,-1513,-1490,-1411,-1251,-1036,-825,
--670,-573,-509,-450,-390,-327,-256,-169,-72,28,124,216,309,406,506,606,702,794,879,950,1001,
-1031,1049,1062,1082,1114,1158,1204,1241,1270,1305,1364,1447,1537,1615,1673,1707,1727,1744,1775,1825,1890,
-1961,2028,2086,2130,2165,2207,2272,2361,2457,2539,2604,2659,2706,2738,2746,2737,2728,2727,2733,2740,2748,
-2769,2809,2866,2926,2985,3047,3121,3203,3281,3342,3388,3425,3458,3488,3523,3566,3616,3661,3697,3739,3805,
-3897,3992,4061,4094,4113,4152,4233,4344,4457,4545,4606,4654,4702,4742,4759,4747,4719,4699,4704,4735,4790,
-4866,4961,5067,5175,5278,5368,5446,5518,5594,5669,5727,5760,5775,5791,5811,5822,5817,5805,5802,5806,5804,
-5789,5771,5763,5771,5786,5798,5800,5799,5803,5809,5806,5794,5789,5808,5846,5880,5896,5902,5905,5894,5849,
-5777,5710,5673,5662,5656,5644,5633,5633,5643,5652,5650,5647,5660,5689,5709,5703,5682,5671,5659,5619,5574,
-5606,5756,5936,5998,5898,5753,5698,5738,5777,5756,5706,5678,5671,5668,5674,5695,5703,5669,5634,5672,5801,
-5943,6005,5977,5918,5891,5909,5958,6018,6067,6084,6057,6001,5945,5905,5865,5781,5621,5411,5245,5226,5392,
-5682,5991,6235,6390,6475,6524,6561,6589,6598,6586,6568,6557,6551,6539,6521,6506,6491,6462,6419,6375,6346,
-6324,6294,6253,6211,6168,6118,6062,6012,5970,5923,5861,5791,5725,5671,5629,5601,5573,5515,5404,5257,5126,
-5052,5031,5033,5035,5030,5019,5004,5000,5025,5074,5114,5114,5080,5047,5045,5071,5096,5100,5089,5085,5096,
-5105,5091,5055,5017,4994,4969,4873,4616,4141,3495,2852,2427,2334,2495,2715,2849,2884,2889,2898,2897,2875,
-2861,2875,2881,2823,2694,2544,2425,2344,2277,2202,2116,2022,1928,1849,1793,1750,1703,1649,1598,1553,1504,
-1445,1385,1339,1307,1280,1258,1246,1237,1217,1184,1154,1136,1118,1091,1066,1055,1053,1036,1004,981,985,
-999,999,982,968,961,947,908,853,800,753,703,652,610,585,566,541,511,488,475,458,429,
-393,363,343,324,296,261,226,194,166,149,155,182,212,224,206,164,114,71,40,19,-2,
--29,-55,-76,-99,-135,-184,-231,-264,-290,-322,-361,-401,-436,-468,-498,-525,-547,-571,-600,-627,-645,
--656,-666,-677,-684,-689,-703,-736,-783,-824,-842,-840,-833,-835,-848,-861,-868,-879,-903,-932,-947,-940,
--928,-934,-962,-993,-1013,-1021,-1026,-1034,-1040,-1044,-1047,-1051,-1055,-1059,-1065,-1071,-1078,-1083,-1086,-1092,-1100,
--1111,-1122,-1132,-1138,-1141,-1141,-1140,-1139,-1136,-1133,-1130,-1129,-1133,-1136,-1135,-1125,-1109,-1093,-1080,-1071,-1062,
--1053,-1049,-1048,-1048,-1041,-1028,-1015,-1003,-988,-968,-946,-926,-910,-893,-873,-854,-841,-832,-819,-800,-781,
--768,-757,-743,-722,-699,-679,-662,-647,-632,-614,-594,-572,-553,-536,-520,-502,-486,-474,-464,-451,-433,
--418,-406,-393,-377,-361,-349,-338,-324,-309,-300,-295,-288,-276,-265,-258,-254,-248,-238,-231,-225,-218,
--211,-206,-203,-202,-200,-201,-205,-210,-212,-213,-217,-223,-228,-233,-239,-246,-250,-252,-258,-265,-268,
--266,-266,-274,-285,-292,-296,-300,-305,-311,-318,-326,-334,-339,-342,-352,-369,-384,-388,-388,-390,-397,
--402,-405,-409,-417,-424,-428,-430,-433,-436,-438,-442,-449,-457,-460,-461,-461,-460,-454,-448,-444,-443,
--443,-443,-445,-445,-436,-416,-396,-387,-386,-384,-377,-367,-355,-342,-328,-321,-320,-321,-318,-314,-309,
--301,-288,-273,-261,-251,-238,-223,-210,-203,-198,-188,-173,-155,-139,-128,-121,-113,-100,-84,-71,-56,
--36,-10,14,30,42,57,78,98,117,140,168,201,234,270,307,343,380,421,467,511,549,
-584,624,669,710,748,790,842,899,949,989,1024,1061,1104,1150,1195,1235,1272,1312,1360,1414,1469,
-1523,1575,1623,1662,1696,1737,1789,1842,1885,1919,1962,2026,2086,2084,1966,1738,1486,1336,1369,1579,1909,
-2300,2719,3132,3506,3816,4055,4216,4293,4298,4276,4272,4295,4325,4346,4369,4406,4442,4449,4411,4337,4248,
-4167,4098,4018,3883,3657,3356,3040,2766,2551,2386,2273,2232,2262,2323,2359,2343,2290,2233,2190,2146,2073,
-1962,1835,1732,1683,1685,1711,1731,1725,1692,1637,1567,1489,1408,1330,1250,1151,1016,855,701,581,486,
-382,252,112,-14,-127,-240,-355,-455,-526,-570,-600,-626,-655,-695,-748,-802,-838,-848,-840,-827,-818,
--821,-845,-899,-971,-1039,-1082,-1095,-1082,-1048,-999,-942,-888,-847,-828,-838,-878,-937,-988,-1005,-984,-945,
--914,-900,-901,-921,-974,-1061,-1153,-1205,-1190,-1117,-1015,-916,-838,-788,-764,-755,-745,-722,-692,-678,-696,
--725,-712,-633,-547,-557,-709,-932,-1096,-1137,-1094,-1043,-1014,-991,-956,-916,-881,-853,-828,-805,-780,-744,
--701,-666,-643,-622,-592,-561,-543,-538,-531,-520,-517,-528,-542,-545,-541,-540,-545,-551,-557,-566,-580,
--594,-606,-623,-644,-663,-672,-676,-683,-695,-703,-705,-702,-699,-695,-689,-677,-661,-640,-620,-603,-584,
--560,-528,-493,-459,-423,-385,-347,-312,-277,-238,-195,-153,-113,-72,-27,15,52,85,124,168,215,
-258,299,341,384,426,463,499,532,561,587,612,641,674,707,736,763,791,821,854,891,934,
-981,1028,1071,1107,1133,1149,1155,1156,1160,1170,1185,1202,1216,1225,1230,1234,1239,1242,1241,1238,1238,
-1241,1243,1243,1244,1250,1260,1270,1276,1281,1285,1288,1294,1304,1320,1336,1349,1362,1381,1407,1437,1464,
-1486,1507,1531,1553,1569,1579,1589,1603,1618,1630,1637,1631,1636,1641,1646,1646,1644,1643,1646,1652,1663,
-1678,1693,1703,1709,1718,1735,1753,1770,1792,1823,1859,1889,1910,1928,1943,1954,1963,1974,1989,1998,2002,
-2004,2012,2020,2026,2033,2048,2073,2107,2154,2210,2255,2271,2269,2284,2337,2407,2456,2475,2478,2477,2469,
-2454,2447,2461,2488,2513,2530,2542,2546,2538,2522,2504,2490,2476,2461,2448,2443,2445,2451,2452,2435,2395,
-2337,2275,2221,2179,2142,2110,2078,2041,1992,1929,1852,1757,1655,1573,1534,1532,1529,1493,1435,1383,1350,
-1325,1294,1258,1225,1200,1180,1162,1141,1110,1067,1018,974,944,924,904,874,831,791,772,779,797,
-806,801,788,772,749,718,681,647,616,575,500,374,222,108,75,96,84,-8,-140,-238,-280,
--308,-357,-414,-451,-472,-494,-505,-482,-439,-432,-507,-653,-826,-986,-1111,-1180,-1184,-1142,-1096,-1075,-1083,
--1107,-1137,-1162,-1172,-1161,-1135,-1105,-1087,-1087,-1103,-1109,-1073,-989,-894,-849,-875,-932,-950,-896,-804,-742,
--746,-781,-771,-673,-516,-366,-265,-199,-129,-39,52,108,96,4,-139,-281,-391,-499,-654,-863,-1066,
--1189,-1221,-1206,-1196,-1204,-1218,-1229,-1238,-1245,-1247,-1244,-1237,-1233,-1234,-1234,-1222,-1193,-1168,-1174,-1211,-1246,
--1257,-1258,-1279,-1319,-1361,-1404,-1451,-1453,-1306,-974,-602,-442,-622,-1013,-1346,-1456,-1389,-1290,-1242,-1234,-1229,
--1225,-1234,-1246,-1238,-1211,-1193,-1209,-1255,-1300,-1311,-1282,-1241,-1225,-1249,-1292,-1326,-1344,-1361,-1382,-1400,-1409,
--1419,-1441,-1475,-1513,-1554,-1599,-1646,-1689,-1730,-1775,-1825,-1873,-1918,-1967,-2023,-2082,-2135,-2187,-2244,-2308,-2374,
--2442,-2511,-2577,-2633,-2678,-2721,-2769,-2821,-2873,-2927,-2985,-3041,-3090,-3136,-3192,-3258,-3320,-3369,-3409,-3448,-3491,
--3535,-3582,-3631,-3680,-3723,-3759,-3796,-3841,-3890,-3933,-3969,-4005,-4046,-4089,-4130,-4168,-4207,-4246,-4285,-4319,-4354,
--4403,-4468,-4535,-4587,-4617,-4638,-4661,-4686,-4702,-4705,-4705,-4719,-4751,-4795,-4839,-4875,-4900,-4910,-4904,-4879,-4839,
--4786,-4721,-4646,-4574,-4530,-4534,-4585,-4669,-4764,-4851,-4912,-4937,-4935,-4928,-4932,-4942,-4944,-4940,-4937,-4932,-4908,
--4863,-4819,-4802,-4811,-4831,-4852,-4880,-4914,-4937,-4936,-4917,-4897,-4881,-4868,-4856,-4850,-4849,-4841,-4818,-4788,-4766,
--4754,-4746,-4740,-4740,-4749,-4757,-4753,-4729,-4692,-4656,-4630,-4608,-4579,-4536,-4483,-4427,-4375,-4330,-4290,-4251,-4206,
--4151,-4091,-4030,-3972,-3911,-3847,-3785,-3727,-3675,-3624,-3575,-3529,-3483,-3436,-3389,-3346,-3307,-3266,-3223,-3180,-3136,
--3084,-3023,-2959,-2901,-2846,-2785,-2716,-2645,-2575,-2505,-2439,-2388,-2359,-2348,-2340,-2322,-2285,-2222,-2131,-2025,-1918,
--1821,-1734,-1659,-1608,-1585,-1583,-1585,-1571,-1518,-1396,-1200,-968,-768,-645,-590,-560,-522,-470,-407,-329,-231,
--123,-23,63,145,236,338,438,529,617,710,809,900,967,1003,1016,1021,1030,1050,1081,1115,1143,
-1163,1189,1234,1303,1388,1474,1549,1603,1634,1651,1669,1705,1761,1831,1900,1958,2007,2057,2124,2209,2302,
-2387,2457,2517,2570,2610,2633,2639,2636,2630,2626,2624,2626,2638,2662,2702,2755,2816,2881,2950,3028,3110,
-3188,3253,3304,3347,3385,3422,3462,3508,3557,3602,3643,3690,3756,3840,3922,3982,4014,4039,4089,4181,4302,
-4423,4516,4580,4631,4677,4709,4712,4684,4648,4627,4629,4653,4699,4770,4863,4965,5069,5173,5274,5369,5454,
-5531,5601,5658,5695,5716,5735,5759,5781,5790,5784,5774,5768,5765,5757,5745,5736,5739,5755,5772,5781,5784,
-5791,5801,5800,5784,5774,5794,5840,5882,5895,5887,5877,5862,5823,5755,5683,5634,5611,5598,5585,5578,5583,
-5596,5601,5593,5588,5609,5648,5669,5650,5611,5592,5592,5583,5569,5618,5768,5942,6003,5906,5760,5693,5714,
-5738,5710,5666,5652,5659,5656,5644,5644,5651,5639,5619,5638,5719,5827,5911,5946,5941,5914,5884,5880,5927,
-6008,6072,6082,6037,5968,5904,5846,5771,5649,5465,5259,5119,5134,5333,5656,5992,6246,6388,6455,6498,6536,
-6559,6562,6554,6548,6540,6520,6496,6482,6474,6453,6413,6372,6346,6327,6294,6246,6197,6154,6110,6062,6019,
-5979,5928,5858,5780,5713,5662,5619,5576,5521,5433,5301,5155,5049,5015,5025,5033,5018,4999,4994,5002,5017,
-5045,5085,5119,5126,5102,5074,5068,5089,5117,5132,5132,5131,5137,5142,5131,5105,5078,5057,5010,4861,4524,
-3979,3318,2727,2385,2343,2501,2694,2818,2874,2901,2912,2894,2857,2833,2827,2799,2712,2583,2460,2374,2313,
-2257,2195,2128,2047,1953,1864,1798,1752,1705,1649,1599,1562,1527,1478,1421,1370,1332,1302,1279,1267,1259,
-1241,1209,1173,1144,1119,1093,1071,1059,1050,1029,995,966,953,950,940,927,927,941,955,951,925,
-882,826,757,683,622,585,563,543,517,492,472,454,428,393,356,326,302,281,259,233,200,
-162,128,114,122,139,147,135,104,65,28,-1,-26,-51,-77,-99,-116,-135,-165,-206,-249,-285,
--315,-345,-376,-408,-445,-490,-533,-558,-562,-564,-584,-621,-659,-683,-698,-711,-723,-730,-737,-755,-789,
--828,-855,-864,-864,-866,-868,-863,-854,-859,-887,-927,-955,-961,-958,-962,-977,-994,-1008,-1021,-1035,-1046,
--1052,-1057,-1067,-1079,-1086,-1089,-1093,-1100,-1105,-1106,-1105,-1107,-1113,-1122,-1131,-1138,-1143,-1143,-1140,-1139,-1140,
--1141,-1142,-1143,-1145,-1147,-1147,-1144,-1136,-1123,-1107,-1091,-1080,-1071,-1063,-1056,-1053,-1051,-1047,-1037,-1024,-1012,
--999,-982,-962,-945,-929,-910,-885,-860,-844,-835,-824,-808,-792,-780,-769,-752,-729,-704,-682,-664,-650,
--636,-619,-598,-575,-554,-538,-522,-503,-485,-472,-461,-446,-428,-413,-403,-392,-378,-363,-352,-342,-329,
--314,-304,-299,-291,-279,-269,-264,-261,-254,-245,-237,-231,-225,-218,-213,-210,-208,-207,-209,-214,-218,
--220,-220,-222,-226,-230,-234,-241,-248,-252,-255,-261,-269,-274,-274,-276,-282,-289,-293,-296,-302,-309,
--313,-317,-324,-332,-337,-342,-351,-365,-375,-376,-374,-378,-389,-399,-404,-406,-409,-413,-415,-417,-420,
--424,-427,-432,-438,-441,-440,-438,-438,-438,-433,-426,-423,-424,-427,-428,-429,-425,-413,-394,-377,-368,
--364,-359,-351,-342,-332,-319,-305,-298,-296,-296,-293,-291,-288,-280,-266,-251,-240,-229,-217,-203,-192,
--183,-173,-159,-146,-133,-120,-107,-95,-82,-66,-50,-37,-26,-12,8,29,46,62,82,105,125,
-142,162,188,218,250,285,322,358,393,435,486,537,576,606,641,686,732,770,804,843,887,
-934,980,1021,1058,1093,1128,1165,1203,1244,1289,1341,1397,1452,1504,1557,1605,1644,1674,1707,1754,1813,
-1871,1917,1956,2003,2063,2105,2066,1899,1634,1391,1306,1448,1782,2221,2676,3095,3455,3751,3983,4149,4245,
-4280,4285,4290,4306,4323,4336,4358,4393,4424,4426,4395,4343,4286,4231,4175,4090,3935,3682,3356,3029,2766,
-2576,2433,2327,2277,2295,2347,2378,2358,2304,2253,2219,2180,2103,1978,1831,1707,1644,1648,1693,1738,1754,
-1731,1678,1610,1538,1466,1394,1315,1208,1063,893,732,605,501,391,260,123,0,-113,-232,-360,-474,
--551,-591,-611,-628,-653,-691,-740,-792,-830,-847,-846,-835,-819,-804,-801,-825,-882,-955,-1018,-1052,-1052,
--1026,-980,-921,-860,-811,-788,-799,-841,-897,-937,-939,-905,-864,-838,-827,-820,-832,-892,-1005,-1127,-1189,
--1153,-1043,-917,-822,-761,-721,-692,-677,-673,-665,-650,-650,-694,-762,-784,-708,-585,-540,-644,-842,-1009,
--1075,-1069,-1049,-1035,-1008,-966,-927,-900,-876,-844,-809,-774,-735,-692,-658,-636,-615,-581,-547,-529,-528,
--526,-518,-517,-531,-548,-555,-552,-552,-559,-565,-571,-581,-596,-610,-621,-633,-652,-670,-678,-679,-683,
--692,-699,-699,-693,-688,-683,-676,-663,-645,-624,-605,-588,-571,-550,-524,-494,-461,-424,-385,-348,-314,
--280,-242,-200,-160,-123,-85,-44,-2,35,70,110,154,198,238,277,318,361,403,440,475,509,
-542,571,597,626,660,696,730,762,792,825,861,899,940,985,1032,1077,1116,1144,1161,1170,1174,
-1176,1180,1189,1202,1216,1227,1231,1232,1234,1239,1242,1243,1244,1246,1249,1253,1256,1262,1270,1278,1286,
-1291,1296,1301,1309,1321,1336,1350,1364,1381,1403,1428,1453,1476,1494,1513,1533,1553,1569,1579,1588,1600,
-1615,1626,1631,1628,1631,1641,1653,1659,1659,1660,1665,1673,1684,1701,1718,1732,1741,1753,1773,1795,1815,
-1836,1867,1903,1935,1958,1976,1991,2002,2011,2019,2030,2037,2040,2045,2060,2085,2111,2137,2163,2190,2217,
-2248,2284,2312,2318,2311,2316,2353,2410,2460,2493,2511,2514,2498,2471,2460,2477,2509,2533,2544,2550,2558,
-2563,2560,2554,2551,2551,2551,2551,2551,2552,2552,2543,2513,2460,2393,2330,2283,2248,2215,2180,2141,2097,
-2043,1975,1895,1805,1717,1650,1616,1603,1583,1543,1493,1452,1422,1392,1352,1307,1265,1232,1211,1197,1179,
-1146,1101,1057,1025,1006,991,975,954,930,909,902,913,929,934,917,882,836,785,728,671,619,
-576,533,464,346,203,104,99,152,160,71,-63,-155,-184,-209,-273,-356,-411,-431,-437,-434,-414,
--397,-433,-552,-725,-898,-1038,-1138,-1189,-1181,-1128,-1064,-1022,-1016,-1040,-1079,-1112,-1115,-1089,-1054,-1032,-1026,
--1032,-1043,-1046,-1015,-937,-844,-797,-825,-887,-905,-838,-730,-658,-663,-707,-717,-647,-515,-372,-254,-161,
--77,9,91,139,118,16,-131,-268,-373,-486,-656,-872,-1060,-1156,-1168,-1153,-1152,-1162,-1170,-1174,-1180,
--1187,-1188,-1181,-1174,-1173,-1178,-1177,-1161,-1129,-1103,-1109,-1144,-1175,-1181,-1177,-1193,-1230,-1274,-1333,-1414,-1457,
--1336,-1003,-611,-434,-613,-1006,-1330,-1421,-1337,-1233,-1184,-1166,-1144,-1125,-1132,-1158,-1174,-1168,-1154,-1152,-1168,
--1187,-1184,-1151,-1111,-1103,-1141,-1201,-1246,-1266,-1278,-1298,-1320,-1334,-1346,-1365,-1396,-1432,-1469,-1509,-1555,-1601,
--1646,-1692,-1741,-1787,-1831,-1878,-1932,-1987,-2041,-2094,-2151,-2212,-2275,-2343,-2414,-2481,-2536,-2580,-2625,-2676,-2728,
--2778,-2828,-2882,-2935,-2985,-3036,-3097,-3164,-3223,-3266,-3304,-3347,-3395,-3443,-3490,-3540,-3591,-3634,-3669,-3704,-3746,
--3793,-3837,-3879,-3920,-3963,-4005,-4044,-4082,-4122,-4164,-4201,-4235,-4272,-4321,-4382,-4446,-4495,-4526,-4546,-4568,-4592,
--4611,-4622,-4632,-4654,-4691,-4732,-4764,-4782,-4788,-4785,-4771,-4747,-4714,-4674,-4620,-4555,-4494,-4462,-4474,-4527,-4604,
--4692,-4779,-4847,-4880,-4879,-4870,-4873,-4886,-4891,-4883,-4872,-4861,-4842,-4810,-4782,-4777,-4795,-4820,-4844,-4869,-4896,
--4911,-4905,-4886,-4868,-4858,-4850,-4843,-4838,-4830,-4813,-4789,-4767,-4757,-4754,-4752,-4749,-4752,-4760,-4767,-4762,-4741,
--4707,-4668,-4636,-4614,-4595,-4566,-4517,-4451,-4382,-4326,-4285,-4253,-4215,-4164,-4104,-4044,-3984,-3919,-3849,-3779,-3718,
--3662,-3610,-3562,-3520,-3482,-3443,-3404,-3368,-3333,-3295,-3251,-3206,-3161,-3110,-3046,-2978,-2916,-2860,-2800,-2734,-2670,
--2612,-2556,-2500,-2451,-2416,-2391,-2366,-2338,-2304,-2254,-2175,-2070,-1962,-1868,-1792,-1728,-1679,-1653,-1647,-1637,-1593,
--1494,-1329,-1117,-900,-738,-659,-641,-634,-605,-552,-483,-398,-297,-192,-102,-26,53,154,268,372,456,
-531,621,729,837,921,968,984,986,987,995,1011,1031,1052,1073,1100,1139,1195,1264,1340,1414,1478,
-1524,1556,1583,1618,1666,1727,1792,1852,1910,1975,2054,2143,2228,2298,2358,2416,2469,2508,2531,2541,2545,
-2542,2530,2515,2507,2514,2537,2575,2628,2696,2773,2853,2937,3023,3106,3178,3235,3281,3323,3364,3404,3443,
-3484,3528,3577,3634,3700,3774,3843,3896,3934,3970,4032,4131,4256,4379,4475,4543,4596,4640,4664,4654,4616,
-4575,4554,4556,4576,4616,4681,4766,4856,4946,5040,5143,5252,5353,5439,5513,5574,5618,5646,5667,5691,5719,
-5737,5739,5727,5717,5714,5715,5708,5694,5690,5706,5736,5759,5769,5773,5779,5777,5761,5747,5759,5796,5830,
-5839,5828,5817,5806,5777,5722,5658,5604,5562,5528,5503,5498,5516,5542,5553,5546,5541,5562,5601,5618,5589,
-5542,5524,5542,5560,5568,5618,5748,5899,5947,5849,5701,5629,5654,5695,5694,5675,5679,5695,5685,5648,5616,
-5610,5616,5617,5620,5643,5697,5787,5897,5984,6002,5946,5878,5872,5944,6040,6097,6088,6028,5942,5853,5770,
-5677,5535,5321,5083,4943,5014,5310,5718,6079,6299,6394,6439,6481,6515,6528,6528,6529,6528,6511,6483,6464,
-6456,6442,6413,6381,6358,6333,6288,6229,6175,6137,6104,6066,6027,5985,5928,5855,5782,5726,5679,5617,5534,
-5435,5325,5208,5105,5047,5041,5050,5037,5001,4977,4987,5017,5047,5073,5103,5131,5139,5122,5096,5084,5099,
-5129,5157,5173,5178,5178,5176,5166,5151,5139,5122,5052,4841,4419,3808,3147,2631,2392,2420,2586,2749,2847,
-2895,2921,2924,2894,2845,2801,2758,2689,2585,2475,2392,2337,2287,2230,2176,2125,2057,1965,1869,1797,1749,
-1701,1642,1591,1558,1533,1495,1445,1395,1356,1323,1295,1278,1269,1254,1224,1186,1153,1129,1108,1086,1065,
-1046,1023,996,969,948,929,909,890,886,903,935,965,975,955,900,818,727,648,593,561,541,
-522,501,479,457,432,399,359,318,283,257,240,226,204,172,135,104,85,72,59,43,27,
-11,-7,-31,-58,-86,-112,-135,-157,-181,-212,-250,-286,-317,-344,-372,-399,-429,-469,-518,-563,-582,
--570,-555,-567,-614,-670,-708,-724,-732,-744,-760,-774,-786,-801,-821,-842,-859,-874,-887,-894,-887,-873,
--866,-881,-911,-944,-969,-988,-1002,-1006,-1002,-1002,-1012,-1030,-1042,-1046,-1052,-1069,-1089,-1103,-1111,-1118,-1126,
--1129,-1126,-1123,-1123,-1128,-1135,-1143,-1150,-1154,-1152,-1146,-1142,-1143,-1146,-1151,-1156,-1159,-1157,-1151,-1145,-1140,
--1132,-1117,-1100,-1087,-1080,-1074,-1066,-1058,-1054,-1050,-1042,-1029,-1016,-1003,-991,-978,-965,-952,-933,-905,-877,
--856,-844,-834,-821,-807,-792,-776,-756,-733,-709,-688,-668,-652,-637,-621,-601,-579,-560,-545,-530,-511,
--493,-478,-464,-447,-429,-414,-404,-393,-379,-366,-357,-347,-333,-319,-309,-304,-297,-286,-277,-273,-269,
--262,-252,-245,-239,-232,-225,-221,-219,-217,-215,-216,-220,-224,-224,-223,-225,-227,-230,-234,-241,-250,
--256,-259,-264,-270,-276,-279,-284,-290,-295,-296,-298,-303,-309,-313,-316,-321,-329,-336,-341,-347,-355,
--360,-360,-363,-373,-387,-398,-401,-401,-402,-403,-404,-405,-407,-411,-416,-421,-425,-423,-418,-416,-418,
--418,-413,-406,-404,-406,-408,-409,-409,-404,-391,-373,-358,-350,-345,-338,-329,-320,-310,-298,-286,-280,
--278,-275,-271,-269,-267,-260,-247,-233,-221,-208,-193,-180,-171,-163,-150,-134,-123,-113,-100,-83,-66,
--53,-41,-26,-11,1,14,29,44,59,75,96,119,137,156,180,210,239,266,297,333,371,
-408,451,503,556,596,628,663,707,750,786,816,847,881,917,957,1000,1041,1076,1108,1141,1179,
-1220,1267,1321,1379,1433,1482,1530,1580,1626,1663,1693,1730,1783,1848,1912,1960,1996,2039,2096,2117,2021,
-1778,1475,1285,1345,1663,2130,2618,3049,3403,3690,3920,4095,4213,4279,4308,4318,4322,4321,4321,4333,4355,
-4374,4375,4362,4350,4340,4316,4259,4146,3953,3668,3325,2995,2740,2564,2434,2334,2284,2298,2347,2375,2352,
-2299,2255,2229,2198,2130,2017,1884,1766,1697,1685,1714,1750,1762,1736,1680,1611,1542,1478,1412,1331,1220,
-1072,905,747,617,505,389,257,123,1,-111,-232,-362,-479,-559,-598,-615,-630,-654,-690,-735,-781,
--816,-835,-839,-835,-825,-807,-789,-791,-826,-888,-951,-989,-994,-973,-933,-881,-825,-780,-762,-778,-821,
--864,-878,-853,-807,-771,-756,-745,-726,-726,-788,-919,-1056,-1110,-1045,-909,-784,-718,-692,-667,-630,-605,
--610,-630,-646,-673,-743,-841,-890,-824,-685,-600,-654,-805,-942,-999,-998,-982,-958,-921,-889,-886,-901,
--899,-865,-820,-784,-753,-715,-672,-637,-609,-579,-551,-536,-535,-537,-535,-538,-549,-560,-563,-563,-570,
--581,-585,-581,-584,-600,-620,-634,-645,-660,-675,-683,-683,-684,-689,-692,-690,-684,-679,-674,-665,-651,
--633,-614,-595,-577,-558,-538,-515,-488,-457,-421,-383,-346,-313,-280,-244,-204,-166,-130,-94,-57,-18,
-19,58,100,143,185,224,261,301,343,385,424,461,496,531,563,592,621,653,688,724,758,
-791,824,862,901,941,983,1027,1075,1118,1149,1168,1179,1186,1191,1194,1197,1205,1217,1226,1230,1229,
-1231,1237,1244,1250,1252,1255,1261,1270,1278,1284,1288,1293,1300,1306,1312,1319,1330,1343,1356,1368,1382,
-1401,1422,1443,1463,1482,1500,1518,1536,1557,1576,1590,1601,1612,1622,1627,1628,1633,1636,1650,1667,1678,
-1680,1682,1688,1698,1708,1722,1739,1757,1773,1790,1813,1837,1857,1878,1907,1942,1975,2001,2024,2047,2066,
-2074,2077,2079,2080,2083,2093,2119,2161,2206,2244,2269,2282,2287,2292,2306,2325,2337,2342,2351,2378,2420,
-2467,2508,2534,2535,2508,2472,2459,2483,2521,2545,2550,2553,2567,2587,2600,2605,2610,2620,2633,2643,2644,
-2637,2621,2595,2558,2509,2457,2411,2377,2345,2307,2260,2210,2157,2096,2023,1939,1852,1773,1713,1672,1639,
-1603,1567,1541,1528,1513,1484,1437,1382,1331,1290,1265,1250,1232,1197,1152,1113,1092,1083,1074,1062,1051,
-1044,1039,1038,1041,1043,1031,996,939,869,797,725,652,582,522,473,410,308,183,99,106,169,
-190,116,0,-74,-91,-118,-202,-311,-384,-403,-395,-385,-380,-402,-485,-632,-798,-934,-1024,-1082,-1113,
--1104,-1057,-994,-948,-938,-967,-1016,-1051,-1048,-1013,-978,-963,-961,-956,-954,-956,-940,-882,-799,-754,-783,
--848,-865,-790,-670,-585,-578,-619,-641,-599,-496,-359,-220,-101,-9,61,115,141,110,13,-120,-245,
--351,-479,-664,-876,-1042,-1115,-1120,-1113,-1119,-1127,-1125,-1121,-1126,-1133,-1130,-1120,-1112,-1111,-1117,-1121,-1113,
--1092,-1070,-1066,-1081,-1090,-1076,-1059,-1069,-1111,-1168,-1240,-1323,-1360,-1242,-942,-613,-496,-687,-1036,-1289,-1327,
--1231,-1138,-1098,-1077,-1045,-1021,-1029,-1062,-1095,-1111,-1113,-1114,-1121,-1132,-1133,-1113,-1083,-1076,-1106,-1153,-1183,
--1190,-1197,-1218,-1247,-1266,-1279,-1298,-1328,-1361,-1394,-1428,-1469,-1514,-1559,-1603,-1648,-1691,-1734,-1782,-1836,-1891,
--1946,-2001,-2059,-2119,-2180,-2246,-2317,-2385,-2440,-2485,-2532,-2584,-2635,-2682,-2728,-2779,-2833,-2886,-2942,-3004,-3068,
--3120,-3160,-3197,-3244,-3296,-3347,-3397,-3449,-3499,-3543,-3578,-3614,-3654,-3698,-3742,-3786,-3832,-3877,-3917,-3955,-3994,
--4036,-4078,-4115,-4149,-4187,-4234,-4291,-4350,-4398,-4430,-4451,-4472,-4497,-4520,-4539,-4558,-4584,-4617,-4647,-4667,-4673,
--4669,-4659,-4643,-4623,-4603,-4576,-4536,-4481,-4430,-4410,-4431,-4485,-4555,-4635,-4720,-4791,-4826,-4824,-4812,-4815,-4830,
--4836,-4824,-4807,-4796,-4788,-4775,-4765,-4768,-4787,-4812,-4836,-4859,-4877,-4882,-4871,-4853,-4840,-4835,-4833,-4830,-4823,
--4808,-4784,-4761,-4750,-4753,-4760,-4762,-4761,-4765,-4774,-4781,-4775,-4755,-4721,-4680,-4644,-4621,-4607,-4584,-4539,-4471,
--4396,-4330,-4285,-4253,-4218,-4170,-4111,-4051,-3992,-3929,-3858,-3785,-3718,-3659,-3604,-3554,-3511,-3475,-3441,-3410,-3383,
--3358,-3324,-3278,-3229,-3183,-3133,-3072,-3005,-2942,-2887,-2829,-2766,-2708,-2663,-2622,-2577,-2527,-2479,-2434,-2388,-2348,
--2316,-2280,-2219,-2126,-2025,-1939,-1873,-1816,-1767,-1734,-1709,-1663,-1568,-1422,-1240,-1051,-885,-771,-721,-712,-706,
--675,-621,-553,-470,-376,-282,-202,-132,-48,65,190,297,374,440,524,634,750,848,911,940,947,
-945,943,945,953,969,996,1030,1071,1117,1169,1229,1293,1355,1411,1462,1509,1553,1598,1649,1708,1772,
-1835,1903,1978,2056,2128,2189,2244,2299,2351,2392,2419,2438,2452,2454,2442,2423,2410,2411,2428,2459,2510,
-2582,2666,2751,2836,2926,3019,3104,3172,3224,3269,3308,3338,3361,3388,3431,3494,3565,3636,3701,3759,3810,
-3856,3908,3981,4083,4203,4320,4418,4493,4553,4599,4619,4604,4566,4526,4503,4500,4514,4548,4604,4678,4754,
-4826,4903,4998,5107,5218,5318,5402,5472,5524,5558,5581,5603,5632,5660,5672,5668,5660,5662,5669,5667,5650,
-5638,5654,5694,5734,5752,5752,5747,5740,5727,5715,5716,5734,5752,5757,5754,5751,5746,5726,5686,5636,5581,
-5522,5464,5424,5417,5440,5472,5488,5483,5479,5496,5529,5546,5527,5497,5496,5526,5547,5546,5572,5672,5803,
-5851,5762,5618,5546,5585,5666,5717,5736,5754,5768,5747,5686,5621,5588,5591,5599,5591,5571,5579,5663,5829,
-6009,6104,6070,5966,5894,5909,5986,6066,6108,6093,6022,5916,5810,5719,5606,5409,5131,4882,4827,5050,5471,
-5903,6197,6336,6396,6442,6479,6492,6489,6492,6504,6503,6482,6458,6443,6430,6409,6382,6356,6321,6270,6211,
-6165,6138,6111,6072,6024,5971,5910,5842,5782,5734,5679,5589,5464,5334,5226,5151,5108,5093,5092,5079,5039,
-4992,4974,4996,5035,5066,5090,5118,5145,5154,5139,5115,5104,5117,5148,5182,5204,5211,5208,5203,5197,5195,
-5196,5181,5084,4810,4305,3636,2984,2547,2411,2510,2690,2829,2897,2924,2935,2926,2891,2839,2782,2714,2620,
-2513,2423,2367,2323,2268,2204,2152,2109,2047,1954,1855,1784,1737,1691,1632,1581,1550,1530,1499,1454,1410,
-1374,1343,1313,1290,1277,1260,1230,1192,1162,1143,1126,1102,1071,1044,1022,1003,980,956,932,909,888,
-875,880,907,945,970,962,917,846,763,682,613,563,535,521,506,484,458,431,402,366,323,
-279,243,218,202,186,164,138,109,79,47,18,-1,-10,-16,-30,-56,-86,-114,-139,-164,-195,
--230,-269,-305,-335,-356,-374,-395,-423,-457,-499,-546,-585,-598,-584,-566,-577,-626,-691,-735,-746,-738,
--740,-761,-791,-812,-821,-825,-833,-847,-866,-888,-906,-914,-911,-903,-897,-901,-917,-948,-985,-1014,-1020,
--1009,-1000,-1008,-1028,-1043,-1047,-1053,-1069,-1089,-1105,-1116,-1127,-1138,-1143,-1140,-1137,-1138,-1141,-1144,-1149,-1157,
--1163,-1164,-1158,-1153,-1152,-1155,-1158,-1162,-1165,-1161,-1152,-1144,-1140,-1137,-1126,-1110,-1096,-1090,-1086,-1078,-1067,
--1059,-1054,-1046,-1031,-1015,-1003,-994,-986,-977,-966,-950,-925,-897,-873,-857,-845,-832,-817,-799,-778,-756,
--734,-715,-696,-676,-656,-639,-623,-605,-585,-567,-552,-538,-520,-501,-485,-470,-452,-434,-420,-408,-395,
--381,-369,-360,-350,-336,-322,-314,-310,-305,-296,-287,-282,-277,-270,-261,-254,-248,-240,-233,-228,-226,
--223,-220,-219,-222,-224,-224,-224,-227,-231,-233,-236,-243,-252,-260,-265,-270,-274,-277,-280,-284,-290,
--295,-297,-299,-304,-310,-313,-315,-319,-325,-331,-336,-342,-347,-350,-352,-359,-372,-384,-389,-390,-390,
--392,-393,-392,-391,-393,-396,-400,-405,-406,-403,-398,-397,-400,-401,-396,-389,-386,-386,-386,-384,-383,
--380,-369,-352,-338,-329,-322,-314,-306,-297,-287,-275,-264,-259,-258,-255,-252,-250,-247,-239,-227,-215,
--203,-187,-169,-154,-146,-138,-124,-110,-101,-94,-79,-58,-40,-30,-23,-10,8,25,39,51,63,
-76,91,111,130,148,169,200,234,262,283,309,345,387,430,474,523,570,611,648,687,726,
-759,786,816,851,883,910,937,972,1013,1053,1089,1126,1165,1205,1250,1303,1362,1417,1463,1506,1553,
-1603,1649,1687,1723,1767,1828,1899,1960,1994,2019,2065,2114,2077,1878,1560,1303,1291,1576,2053,2566,3009,
-3357,3627,3845,4028,4178,4281,4331,4336,4320,4304,4299,4306,4316,4322,4324,4333,4359,4388,4385,4320,4176,
-3949,3644,3299,2975,2724,2548,2417,2316,2264,2279,2330,2357,2330,2273,2229,2211,2194,2148,2067,1970,1881,
-1815,1780,1770,1768,1754,1713,1649,1576,1509,1449,1389,1311,1200,1056,897,746,616,500,382,256,128,
-7,-108,-228,-352,-462,-540,-582,-605,-626,-655,-693,-734,-773,-802,-817,-819,-817,-811,-801,-788,-785,
--805,-846,-889,-912,-908,-886,-856,-822,-787,-760,-755,-777,-812,-830,-809,-753,-695,-663,-656,-648,-628,
--630,-702,-839,-967,-995,-900,-747,-631,-593,-599,-593,-562,-541,-561,-612,-667,-729,-825,-944,-1012,-964,
--829,-721,-723,-807,-885,-908,-890,-853,-799,-739,-718,-762,-833,-863,-831,-780,-757,-752,-730,-683,-635,
--605,-588,-571,-554,-541,-536,-539,-551,-565,-571,-568,-572,-588,-602,-594,-571,-558,-575,-609,-638,-656,
--668,-678,-683,-681,-679,-678,-678,-674,-669,-665,-660,-651,-636,-619,-602,-584,-564,-543,-521,-499,-475,
--447,-416,-383,-348,-315,-281,-247,-210,-173,-135,-98,-62,-26,12,54,97,138,178,218,257,297,
-338,379,420,459,494,529,562,594,624,655,688,724,759,791,824,862,903,943,982,1025,1075,
-1122,1156,1176,1187,1196,1203,1206,1206,1209,1217,1227,1232,1234,1237,1243,1252,1258,1262,1264,1272,1283,
-1295,1301,1303,1307,1314,1321,1326,1334,1347,1363,1375,1384,1398,1417,1436,1453,1468,1487,1507,1525,1541,
-1560,1582,1600,1613,1623,1631,1635,1633,1648,1653,1667,1686,1697,1699,1701,1710,1723,1735,1746,1762,1784,
-1806,1829,1853,1877,1898,1921,1953,1990,2025,2053,2080,2108,2129,2134,2127,2121,2123,2134,2155,2193,2245,
-2296,2329,2337,2325,2305,2293,2299,2319,2342,2357,2369,2387,2418,2462,2508,2541,2542,2510,2467,2448,2467,
-2504,2530,2541,2551,2576,2609,2640,2661,2679,2698,2716,2725,2719,2697,2665,2630,2598,2570,2545,2523,2495,
-2454,2399,2337,2276,2216,2150,2073,1987,1901,1824,1761,1707,1657,1612,1586,1587,1601,1602,1575,1524,1465,
-1409,1363,1335,1320,1301,1267,1223,1192,1179,1174,1163,1150,1145,1148,1152,1147,1136,1117,1085,1034,965,
-887,808,730,646,558,477,413,352,272,175,108,115,174,204,156,69,11,-9,-50,-149,-270,
--349,-368,-359,-354,-373,-432,-544,-693,-827,-908,-941,-956,-965,-958,-926,-880,-848,-848,-884,-935,-967,
--957,-921,-894,-887,-881,-864,-852,-860,-863,-823,-750,-704,-732,-796,-813,-741,-622,-534,-515,-541,-561,
--534,-448,-316,-165,-30,67,124,149,143,95,7,-98,-201,-311,-462,-664,-870,-1013,-1070,-1076,-1077,
--1084,-1083,-1073,-1068,-1075,-1081,-1076,-1063,-1053,-1051,-1056,-1065,-1071,-1065,-1045,-1021,-997,-957,-897,-845,-845,
--909,-1010,-1118,-1203,-1213,-1089,-845,-623,-593,-790,-1062,-1220,-1208,-1116,-1048,-1020,-996,-960,-936,-941,-966,
--993,-1017,-1039,-1057,-1073,-1093,-1109,-1109,-1093,-1082,-1092,-1112,-1122,-1119,-1124,-1149,-1181,-1201,-1213,-1232,-1262,
--1296,-1327,-1357,-1391,-1430,-1470,-1509,-1548,-1588,-1632,-1682,-1737,-1793,-1848,-1905,-1965,-2025,-2086,-2151,-2221,-2288,
--2344,-2391,-2439,-2491,-2539,-2581,-2624,-2675,-2733,-2793,-2852,-2913,-2970,-3017,-3056,-3097,-3147,-3202,-3255,-3307,-3359,
--3408,-3449,-3485,-3523,-3566,-3609,-3651,-3696,-3745,-3792,-3833,-3870,-3909,-3951,-3992,-4028,-4063,-4101,-4146,-4199,-4254,
--4303,-4338,-4361,-4381,-4404,-4428,-4451,-4474,-4498,-4524,-4544,-4554,-4556,-4552,-4543,-4530,-4518,-4508,-4495,-4466,-4421,
--4382,-4372,-4400,-4453,-4517,-4591,-4674,-4745,-4779,-4774,-4759,-4760,-4775,-4780,-4766,-4747,-4740,-4744,-4748,-4750,-4757,
--4775,-4800,-4826,-4848,-4858,-4852,-4835,-4819,-4812,-4811,-4810,-4807,-4799,-4782,-4757,-4736,-4733,-4747,-4762,-4769,-4769,
--4773,-4781,-4786,-4782,-4764,-4732,-4690,-4650,-4621,-4602,-4579,-4541,-4484,-4416,-4350,-4296,-4254,-4213,-4163,-4103,-4043,
--3987,-3930,-3863,-3791,-3724,-3665,-3612,-3564,-3521,-3485,-3451,-3421,-3398,-3378,-3348,-3302,-3250,-3200,-3152,-3097,-3036,
--2979,-2928,-2873,-2812,-2757,-2717,-2688,-2654,-2611,-2559,-2501,-2437,-2378,-2336,-2302,-2254,-2180,-2096,-2021,-1961,-1907,
--1856,-1812,-1757,-1662,-1514,-1339,-1178,-1048,-947,-869,-817,-787,-763,-729,-682,-624,-553,-469,-385,-311,-242,
--154,-38,89,198,276,343,423,524,636,740,818,866,887,891,887,881,880,893,921,960,1000,
-1038,1079,1130,1187,1245,1304,1366,1428,1481,1525,1571,1628,1693,1757,1816,1878,1944,2009,2065,2115,2162,
-2208,2248,2283,2315,2346,2366,2369,2362,2354,2354,2362,2384,2427,2493,2571,2648,2725,2812,2912,3011,3096,
-3161,3213,3251,3271,3278,3294,3340,3414,3498,3572,3631,3680,3729,3783,3848,3931,4031,4141,4250,4351,4441,
-4514,4562,4579,4565,4533,4500,4475,4462,4464,4486,4531,4591,4653,4714,4779,4859,4958,5067,5174,5270,5350,
-5412,5454,5481,5505,5534,5568,5593,5601,5601,5607,5621,5628,5617,5603,5612,5652,5699,5726,5726,5713,5700,
-5689,5680,5677,5679,5683,5688,5697,5706,5706,5688,5656,5613,5556,5486,5415,5370,5363,5382,5405,5415,5414,
-5414,5427,5450,5467,5471,5476,5500,5532,5533,5499,5488,5562,5690,5762,5704,5571,5489,5522,5628,5727,5787,
-5818,5828,5799,5728,5643,5582,5561,5559,5545,5511,5494,5558,5730,5954,6125,6168,6100,6002,5944,5948,5998,
-6066,6113,6103,6025,5911,5799,5680,5498,5222,4928,4780,4906,5278,5727,6074,6263,6352,6410,6453,6466,6457,
-6455,6470,6481,6469,6444,6423,6406,6385,6357,6326,6289,6244,6200,6170,6148,6116,6064,6003,5945,5889,5831,
-5774,5715,5637,5524,5387,5264,5183,5146,5134,5128,5113,5078,5028,4990,4987,5014,5047,5072,5098,5134,5167,
-5174,5156,5134,5130,5149,5180,5209,5226,5230,5226,5223,5226,5237,5250,5231,5098,4756,4176,3468,2844,2488,
-2442,2590,2772,2887,2930,2938,2934,2915,2877,2829,2774,2702,2607,2506,2425,2369,2317,2252,2183,2130,2086,
-2020,1924,1826,1757,1714,1671,1618,1571,1543,1524,1495,1454,1416,1387,1361,1335,1311,1290,1267,1233,1196,
-1171,1157,1142,1115,1081,1052,1033,1016,992,965,941,922,903,884,874,881,898,908,896,865,824,
-775,713,640,573,531,513,500,477,446,416,391,365,329,286,242,206,178,156,138,122,106,
-84,55,28,8,-3,-21,-53,-94,-130,-154,-171,-195,-229,-270,-311,-347,-373,-390,-402,-418,-445,
--482,-522,-562,-594,-612,-612,-607,-618,-657,-714,-755,-760,-738,-724,-741,-783,-823,-844,-849,-850,-855,
--865,-879,-899,-923,-943,-947,-934,-914,-903,-917,-951,-986,-1002,-1000,-999,-1014,-1041,-1063,-1074,-1080,-1091,
--1102,-1110,-1118,-1129,-1141,-1148,-1148,-1148,-1150,-1150,-1147,-1148,-1156,-1167,-1172,-1170,-1167,-1166,-1165,-1164,-1164,
--1165,-1163,-1155,-1146,-1143,-1141,-1134,-1121,-1108,-1102,-1098,-1090,-1078,-1067,-1060,-1050,-1033,-1015,-1002,-995,-988,
--980,-969,-956,-938,-915,-891,-869,-852,-837,-821,-802,-780,-756,-735,-720,-704,-685,-663,-643,-625,-608,
--589,-572,-556,-542,-525,-507,-490,-473,-456,-440,-426,-413,-400,-385,-373,-363,-352,-338,-326,-319,-316,
--311,-304,-297,-292,-286,-279,-271,-265,-257,-248,-241,-237,-234,-229,-224,-222,-224,-225,-226,-227,-233,
--239,-242,-243,-247,-254,-263,-270,-276,-279,-281,-283,-285,-289,-293,-297,-302,-307,-311,-314,-316,-319,
--322,-325,-331,-339,-345,-348,-352,-360,-371,-376,-374,-373,-376,-380,-380,-377,-377,-379,-382,-383,-384,
--385,-382,-380,-381,-385,-385,-379,-372,-367,-363,-358,-355,-354,-354,-346,-332,-318,-307,-297,-289,-281,
--273,-262,-248,-236,-232,-232,-231,-230,-229,-226,-216,-204,-193,-182,-166,-147,-132,-123,-112,-96,-82,
--76,-70,-56,-34,-17,-9,-3,10,29,46,58,69,83,97,115,135,155,174,195,225,257,
-283,303,328,364,409,455,500,544,586,628,672,715,748,764,777,805,847,885,910,930,958,
-996,1036,1076,1118,1161,1200,1241,1291,1349,1404,1450,1489,1530,1574,1622,1671,1718,1762,1812,1877,1941,
-1978,1991,2018,2070,2076,1934,1645,1364,1300,1543,2013,2539,2989,3317,3546,3732,3919,4113,4272,4349,4345,
-4306,4281,4283,4294,4298,4296,4300,4325,4368,4405,4398,4316,4152,3911,3612,3285,2979,2735,2556,2416,2304,
-2245,2258,2310,2333,2292,2218,2170,2166,2175,2159,2112,2049,1987,1928,1872,1823,1780,1736,1682,1613,1538,
-1470,1413,1359,1288,1182,1043,888,742,613,496,381,264,144,24,-96,-217,-332,-429,-500,-547,-580,
--612,-649,-690,-731,-765,-789,-799,-794,-783,-774,-771,-772,-780,-797,-822,-841,-840,-818,-788,-765,-752,
--745,-743,-751,-770,-786,-776,-725,-650,-585,-554,-550,-546,-539,-561,-645,-773,-873,-873,-767,-619,-513,
--484,-503,-518,-512,-513,-551,-622,-703,-791,-902,-1028,-1107,-1077,-953,-825,-766,-773,-796,-803,-794,-758,
--681,-589,-553,-609,-701,-735,-690,-632,-627,-661,-676,-647,-608,-593,-597,-590,-559,-519,-496,-502,-532,
--561,-573,-572,-579,-600,-611,-587,-538,-508,-525,-578,-631,-662,-674,-678,-678,-672,-666,-662,-660,-657,
--653,-650,-645,-636,-622,-606,-590,-573,-552,-529,-507,-484,-461,-435,-409,-382,-351,-316,-280,-247,-213,
--177,-137,-98,-61,-25,14,57,100,139,178,220,262,303,342,382,424,462,496,528,561,595,
-627,657,690,727,763,795,827,866,909,949,986,1028,1080,1130,1166,1185,1197,1207,1215,1215,1212,
-1212,1220,1231,1241,1247,1252,1257,1263,1267,1270,1272,1277,1288,1299,1305,1309,1313,1321,1329,1334,1342,
-1355,1370,1382,1391,1405,1424,1443,1457,1470,1489,1511,1528,1542,1560,1581,1599,1611,1621,1634,1643,1648,
-1663,1671,1682,1698,1708,1711,1717,1732,1751,1766,1778,1795,1819,1846,1871,1896,1920,1946,1977,2017,2060,
-2094,2119,2140,2164,2180,2179,2166,2160,2171,2197,2230,2271,2317,2357,2372,2357,2321,2287,2273,2282,2307,
-2334,2351,2361,2373,2400,2443,2495,2537,2549,2526,2486,2458,2460,2483,2510,2532,2556,2589,2629,2671,2711,
-2747,2777,2793,2791,2771,2740,2705,2677,2661,2659,2661,2654,2623,2564,2487,2410,2342,2277,2205,2124,2037,
-1953,1877,1809,1746,1687,1644,1629,1645,1670,1673,1643,1591,1534,1479,1434,1403,1386,1368,1338,1303,1282,
-1276,1269,1249,1226,1215,1217,1218,1206,1181,1145,1100,1042,975,901,825,743,651,550,451,372,314,
-261,202,161,167,212,241,215,150,91,48,-14,-114,-222,-292,-316,-321,-339,-384,-463,-576,-699,
--787,-818,-810,-796,-789,-780,-762,-743,-740,-760,-803,-850,-873,-858,-826,-805,-801,-792,-770,-758,-774,
--787,-756,-686,-641,-661,-716,-729,-667,-566,-490,-467,-477,-481,-447,-365,-242,-102,28,128,185,196,
-158,82,-3,-79,-152,-261,-434,-651,-847,-968,-1014,-1027,-1036,-1040,-1030,-1017,-1016,-1026,-1029,-1018,-1004,
--998,-997,-999,-1007,-1018,-1017,-994,-946,-871,-761,-624,-510,-489,-587,-767,-952,-1077,-1094,-994,-827,-708,
--734,-890,-1054,-1117,-1076,-1009,-971,-950,-920,-887,-872,-876,-884,-892,-911,-943,-973,-997,-1021,-1046,-1058,
--1051,-1037,-1035,-1042,-1046,-1046,-1058,-1086,-1116,-1135,-1146,-1166,-1198,-1232,-1261,-1288,-1317,-1350,-1384,-1419,-1455,
--1494,-1538,-1589,-1645,-1700,-1753,-1809,-1869,-1932,-1993,-2057,-2124,-2190,-2247,-2297,-2347,-2396,-2441,-2479,-2520,-2572,
--2636,-2701,-2764,-2820,-2870,-2913,-2955,-3004,-3059,-3115,-3168,-3221,-3273,-3319,-3357,-3393,-3434,-3479,-3523,-3564,-3610,
--3661,-3711,-3753,-3789,-3827,-3868,-3909,-3946,-3980,-4017,-4060,-4110,-4164,-4215,-4253,-4278,-4297,-4316,-4337,-4358,-4379,
--4401,-4420,-4433,-4438,-4440,-4440,-4438,-4433,-4429,-4428,-4424,-4403,-4368,-4338,-4335,-4365,-4416,-4479,-4553,-4635,-4703,
--4732,-4724,-4709,-4711,-4724,-4727,-4713,-4698,-4699,-4714,-4727,-4734,-4740,-4756,-4783,-4814,-4837,-4841,-4825,-4804,-4790,
--4787,-4786,-4780,-4772,-4763,-4748,-4727,-4711,-4712,-4732,-4753,-4765,-4770,-4774,-4780,-4782,-4777,-4762,-4734,-4693,-4648,
--4611,-4582,-4556,-4526,-4487,-4437,-4376,-4313,-4257,-4207,-4153,-4091,-4029,-3975,-3920,-3857,-3787,-3721,-3666,-3620,-3579,
--3544,-3515,-3485,-3452,-3423,-3398,-3368,-3323,-3267,-3213,-3165,-3117,-3066,-3019,-2974,-2922,-2863,-2807,-2768,-2743,-2719,
--2687,-2646,-2591,-2520,-2444,-2380,-2332,-2287,-2232,-2168,-2105,-2045,-1985,-1928,-1870,-1786,-1647,-1461,-1281,-1156,-1087,
--1033,-964,-889,-830,-792,-762,-728,-685,-629,-558,-482,-412,-345,-261,-150,-25,87,177,253,329,416,
-512,609,695,760,798,816,821,818,814,822,846,881,915,944,979,1028,1084,1141,1199,1261,1326,
-1383,1428,1473,1531,1596,1655,1704,1755,1816,1880,1934,1974,2009,2048,2092,2140,2191,2242,2286,2314,2328,
-2334,2338,2344,2360,2395,2452,2517,2580,2642,2717,2810,2912,3006,3088,3153,3197,3213,3214,3227,3273,3350,
-3434,3503,3556,3601,3648,3707,3781,3871,3968,4069,4174,4285,4393,4477,4522,4529,4514,4492,4470,4446,4426,
-4418,4428,4458,4501,4553,4609,4671,4740,4822,4918,5022,5122,5209,5279,5333,5373,5404,5436,5472,5506,5525,
-5532,5541,5562,5585,5592,5585,5585,5609,5649,5682,5691,5679,5661,5647,5639,5635,5632,5633,5642,5661,5680,
-5683,5667,5637,5592,5526,5445,5373,5337,5335,5345,5349,5352,5363,5380,5395,5402,5409,5423,5452,5493,5520,
-5503,5447,5417,5479,5617,5724,5706,5586,5476,5469,5558,5676,5768,5820,5837,5815,5755,5674,5600,5551,5524,
-5501,5468,5444,5475,5599,5802,6015,6161,6204,6160,6073,5993,5961,5992,6063,6117,6109,6034,5921,5786,5604,
-5344,5044,4833,4853,5133,5551,5929,6169,6294,6369,6423,6447,6443,6436,6442,6448,6436,6411,6389,6371,6349,
-6320,6288,6256,6222,6191,6165,6138,6094,6035,5975,5930,5890,5838,5764,5670,5562,5446,5340,5263,5219,5193,
-5167,5135,5095,5050,5009,4991,5005,5035,5061,5082,5117,5165,5201,5201,5175,5154,5159,5185,5215,5237,5246,
-5247,5244,5243,5251,5270,5287,5252,5071,4654,4012,3298,2735,2477,2504,2674,2833,2917,2941,2940,2927,2898,
-2854,2807,2757,2694,2610,2517,2433,2366,2302,2233,2166,2112,2059,1987,1892,1800,1733,1689,1647,1601,1562,
-1537,1517,1486,1446,1411,1388,1371,1352,1330,1303,1271,1233,1201,1181,1171,1156,1128,1097,1072,1054,1034,
-1009,983,964,948,926,897,870,853,841,823,797,775,766,756,722,658,584,530,504,488,464,
-430,396,372,350,322,284,241,199,163,134,116,105,94,78,57,37,24,9,-24,-79,-139,
--179,-196,-204,-223,-255,-292,-327,-360,-390,-414,-431,-447,-471,-504,-539,-571,-599,-624,-643,-654,-663,
--685,-723,-758,-766,-744,-721,-728,-770,-823,-859,-875,-881,-883,-883,-883,-893,-920,-954,-978,-977,-953,
--927,-917,-929,-953,-973,-984,-996,-1019,-1052,-1081,-1101,-1114,-1123,-1128,-1128,-1129,-1134,-1143,-1149,-1151,-1152,
--1155,-1154,-1149,-1149,-1158,-1170,-1177,-1177,-1176,-1176,-1175,-1171,-1168,-1168,-1169,-1165,-1156,-1151,-1149,-1145,-1134,
--1122,-1113,-1108,-1100,-1089,-1078,-1069,-1056,-1038,-1020,-1006,-999,-991,-981,-969,-958,-945,-929,-907,-882,-857,
--837,-821,-804,-782,-758,-737,-721,-707,-689,-667,-645,-625,-607,-590,-573,-558,-543,-528,-511,-493,-477,
--461,-446,-433,-421,-407,-393,-381,-369,-357,-344,-335,-328,-323,-317,-310,-305,-301,-296,-289,-282,-275,
--267,-259,-253,-249,-246,-240,-235,-233,-233,-234,-234,-237,-243,-249,-252,-252,-254,-258,-264,-270,-277,
--283,-287,-291,-293,-293,-295,-299,-304,-309,-311,-312,-315,-319,-320,-321,-326,-336,-344,-347,-351,-358,
--365,-366,-361,-360,-364,-366,-363,-359,-360,-365,-367,-366,-365,-365,-364,-364,-365,-367,-366,-359,-351,
--345,-339,-332,-327,-328,-330,-324,-312,-298,-286,-275,-264,-256,-248,-236,-221,-208,-203,-203,-204,-203,
--203,-199,-189,-176,-164,-153,-140,-126,-114,-104,-90,-70,-54,-46,-41,-28,-11,2,11,22,39,
-55,63,69,80,97,116,136,160,184,205,224,247,273,299,324,353,390,432,477,522,566,
-609,654,703,748,774,777,777,798,838,877,904,928,959,996,1032,1069,1111,1156,1197,1236,1282,
-1336,1388,1436,1478,1516,1551,1592,1647,1709,1760,1802,1853,1913,1955,1964,1976,2022,2056,1969,1723,1443,
-1344,1550,2005,2536,2981,3274,3444,3581,3769,4014,4237,4351,4347,4295,4269,4278,4290,4285,4278,4290,4325,
-4366,4384,4352,4251,4079,3847,3568,3267,2982,2747,2566,2418,2297,2233,2247,2298,2311,2248,2152,2101,2117,
-2157,2168,2138,2089,2040,1986,1920,1845,1774,1713,1656,1594,1526,1459,1402,1351,1285,1183,1044,890,746,
-620,504,391,278,163,42,-83,-206,-313,-397,-460,-509,-550,-590,-632,-675,-715,-747,-770,-779,-771,
--752,-735,-730,-740,-758,-780,-799,-805,-788,-750,-710,-685,-683,-693,-705,-717,-728,-727,-699,-638,-562,
--500,-469,-461,-461,-470,-512,-595,-696,-760,-751,-672,-566,-483,-451,-463,-491,-514,-538,-582,-655,-744,
--844,-957,-1076,-1152,-1134,-1022,-874,-761,-706,-701,-732,-776,-782,-711,-593,-516,-533,-588,-586,-509,-434,
--439,-507,-562,-569,-559,-573,-600,-599,-550,-481,-439,-448,-495,-546,-574,-580,-589,-608,-613,-576,-511,
--469,-487,-553,-622,-663,-675,-675,-669,-660,-651,-646,-645,-645,-642,-639,-634,-625,-613,-598,-582,-563,
--541,-517,-494,-471,-447,-421,-397,-373,-344,-308,-270,-237,-207,-173,-134,-93,-56,-20,20,64,106,
-143,182,225,270,310,346,385,425,463,495,524,557,592,625,657,692,731,767,798,831,871,
-915,954,988,1029,1080,1132,1169,1191,1206,1219,1226,1225,1220,1220,1227,1239,1249,1259,1266,1270,1272,
-1274,1277,1280,1284,1291,1300,1306,1309,1315,1323,1332,1338,1344,1355,1368,1379,1388,1404,1425,1444,1456,
-1468,1487,1510,1528,1541,1557,1577,1593,1603,1614,1632,1651,1663,1673,1682,1692,1706,1718,1726,1737,1758,
-1782,1801,1815,1834,1860,1889,1917,1945,1974,2007,2048,2095,2139,2167,2179,2188,2204,2218,2218,2208,2209,
-2232,2266,2296,2320,2344,2363,2364,2336,2293,2259,2248,2261,2285,2307,2323,2335,2351,2378,2419,2473,2526,
-2559,2560,2535,2503,2485,2490,2512,2544,2578,2614,2654,2700,2752,2802,2839,2851,2838,2809,2778,2756,2746,
-2751,2767,2785,2782,2743,2666,2574,2487,2413,2341,2262,2175,2088,2006,1929,1856,1789,1732,1696,1690,1708,
-1726,1720,1685,1635,1584,1534,1489,1455,1433,1415,1391,1368,1359,1360,1352,1323,1287,1263,1255,1245,1223,
-1188,1143,1092,1036,976,911,838,756,662,560,459,378,329,304,287,273,274,293,304,279,218,
-146,77,2,-82,-162,-216,-249,-281,-328,-394,-475,-566,-644,-686,-686,-663,-641,-625,-612,-606,-617,
--647,-689,-735,-773,-787,-772,-745,-727,-720,-706,-686,-680,-699,-710,-677,-612,-567,-575,-607,-605,-552,
--478,-426,-409,-408,-392,-342,-256,-149,-41,59,153,224,237,174,65,-28,-77,-120,-223,-410,-631,
--808,-904,-945,-970,-990,-994,-980,-967,-970,-976,-969,-951,-939,-941,-947,-948,-947,-947,-940,-910,-844,
--728,-547,-320,-128,-72,-201,-463,-743,-940,-1012,-977,-901,-857,-885,-957,-1005,-992,-946,-909,-890,-868,
--836,-815,-817,-825,-822,-816,-829,-860,-891,-911,-928,-947,-958,-952,-941,-940,-952,-966,-979,-997,-1023,
--1049,-1066,-1080,-1103,-1134,-1165,-1190,-1214,-1241,-1271,-1304,-1339,-1376,-1414,-1456,-1506,-1561,-1614,-1665,-1720,-1780,
--1842,-1903,-1964,-2027,-2091,-2150,-2203,-2253,-2300,-2341,-2378,-2420,-2475,-2542,-2610,-2672,-2724,-2768,-2809,-2857,-2914,
--2974,-3030,-3082,-3135,-3187,-3232,-3267,-3303,-3346,-3393,-3438,-3480,-3528,-3580,-3630,-3671,-3706,-3743,-3784,-3826,-3864,
--3899,-3935,-3975,-4023,-4076,-4128,-4168,-4196,-4215,-4232,-4249,-4266,-4284,-4304,-4320,-4329,-4330,-4332,-4336,-4342,-4347,
--4351,-4357,-4356,-4341,-4313,-4291,-4291,-4318,-4367,-4432,-4511,-4594,-4655,-4677,-4669,-4658,-4664,-4678,-4680,-4668,-4660,
--4671,-4693,-4712,-4719,-4722,-4735,-4762,-4795,-4818,-4818,-4799,-4777,-4766,-4763,-4757,-4744,-4729,-4718,-4708,-4693,-4683,
--4688,-4709,-4734,-4753,-4766,-4775,-4779,-4778,-4771,-4756,-4729,-4689,-4643,-4600,-4563,-4532,-4505,-4480,-4444,-4392,-4328,
--4265,-4210,-4151,-4085,-4020,-3962,-3907,-3842,-3769,-3703,-3649,-3607,-3573,-3552,-3542,-3526,-3496,-3457,-3421,-3385,-3340,
--3282,-3224,-3175,-3135,-3097,-3058,-3017,-2968,-2912,-2859,-2820,-2792,-2768,-2743,-2716,-2677,-2614,-2532,-2448,-2382,-2332,
--2287,-2241,-2187,-2124,-2053,-1982,-1907,-1799,-1633,-1430,-1255,-1155,-1111,-1063,-983,-894,-830,-800,-780,-754,-719,
--675,-620,-559,-498,-436,-357,-251,-127,-7,94,177,250,321,397,481,565,637,690,728,751,760,
-757,758,773,800,826,848,877,923,978,1033,1087,1146,1209,1266,1315,1365,1425,1488,1540,1582,1631,
-1693,1758,1805,1834,1862,1904,1963,2028,2094,2160,2219,2264,2295,2315,2332,2349,2373,2409,2460,2517,2572,
-2624,2683,2755,2838,2927,3014,3090,3142,3162,3166,3181,3227,3295,3365,3422,3469,3513,3562,3625,3704,3798,
-3895,3992,4097,4217,4339,4428,4464,4458,4441,4430,4421,4403,4383,4373,4379,4396,4421,4460,4515,4580,4643,
-4708,4783,4874,4969,5056,5133,5201,5259,5305,5342,5380,5418,5446,5458,5468,5491,5527,5557,5565,5561,5565,
-5588,5619,5638,5635,5616,5597,5585,5581,5581,5587,5602,5627,5649,5658,5650,5625,5576,5497,5404,5334,5307,
-5307,5303,5288,5291,5326,5374,5401,5395,5379,5379,5403,5440,5464,5453,5414,5396,5458,5595,5720,5737,5633,
-5496,5428,5466,5571,5681,5758,5792,5789,5758,5707,5646,5583,5527,5481,5443,5414,5411,5466,5601,5804,6026,
-6199,6273,6237,6130,6018,5959,5974,6034,6087,6090,6031,5918,5751,5514,5218,4953,4861,5023,5380,5772,6063,
-6226,6315,6375,6413,6426,6426,6425,6419,6401,6376,6354,6336,6315,6287,6260,6233,6204,6171,6135,6095,6047,
-5997,5960,5937,5908,5844,5737,5603,5476,5382,5332,5313,5296,5257,5196,5130,5072,5027,4997,4994,5017,5050,
-5078,5105,5149,5202,5234,5225,5192,5171,5182,5212,5241,5259,5268,5270,5268,5264,5266,5279,5284,5215,4968,
-4475,3793,3112,2651,2505,2597,2764,2885,2936,2948,2945,2926,2886,2833,2780,2730,2672,2599,2514,2429,2353,
-2286,2222,2160,2100,2038,1964,1880,1798,1730,1677,1629,1588,1556,1533,1508,1471,1429,1396,1378,1368,1358,
-1339,1309,1270,1231,1204,1191,1183,1166,1140,1115,1094,1076,1055,1037,1028,1024,1009,971,918,867,829,
-795,755,715,693,697,707,694,645,580,527,498,479,455,420,384,354,328,298,262,223,184,
-149,122,107,97,84,61,33,14,6,-4,-39,-101,-166,-207,-221,-227,-244,-275,-306,-333,-361,
--396,-433,-462,-483,-503,-530,-558,-584,-607,-633,-661,-681,-689,-695,-717,-749,-771,-766,-747,-746,-776,
--821,-859,-881,-895,-907,-911,-909,-908,-923,-953,-985,-1002,-998,-980,-961,-952,-958,-971,-985,-1000,-1019,
--1044,-1070,-1092,-1112,-1127,-1137,-1139,-1137,-1139,-1144,-1147,-1149,-1149,-1151,-1152,-1151,-1154,-1164,-1176,-1181,-1180,
--1179,-1180,-1181,-1178,-1174,-1173,-1176,-1175,-1168,-1161,-1158,-1156,-1149,-1137,-1126,-1118,-1112,-1103,-1093,-1082,-1067,
--1049,-1031,-1017,-1008,-999,-987,-974,-961,-950,-937,-918,-892,-863,-837,-818,-802,-784,-761,-737,-719,-703,
--687,-666,-642,-621,-604,-589,-574,-560,-547,-532,-516,-500,-483,-468,-455,-441,-428,-415,-402,-390,-377,
--364,-354,-347,-340,-332,-323,-316,-312,-309,-304,-297,-290,-283,-276,-270,-267,-264,-260,-255,-250,-249,
--249,-248,-247,-249,-254,-258,-261,-262,-263,-265,-267,-270,-275,-281,-289,-297,-301,-302,-301,-303,-307,
--308,-307,-307,-311,-316,-317,-316,-321,-331,-338,-341,-343,-349,-355,-356,-353,-352,-353,-351,-344,-341,
--344,-351,-353,-351,-349,-349,-348,-346,-345,-345,-342,-337,-330,-324,-318,-310,-307,-308,-309,-302,-289,
--277,-266,-254,-242,-232,-223,-211,-197,-185,-181,-180,-178,-175,-173,-169,-161,-147,-135,-123,-112,-102,
--95,-88,-73,-51,-31,-19,-12,-2,9,20,31,48,67,77,78,80,92,112,132,152,175,
-202,224,241,259,283,313,346,382,418,455,495,541,592,642,689,734,771,790,790,790,806,
-834,862,888,920,961,999,1030,1061,1102,1146,1185,1224,1270,1321,1368,1414,1462,1508,1543,1578,1633,
-1703,1762,1798,1834,1889,1939,1956,1962,2002,2047,1992,1776,1501,1381,1561,2003,2532,2966,3221,3335,3428,
-3612,3895,4171,4322,4332,4286,4268,4280,4280,4259,4247,4270,4312,4340,4332,4277,4170,4006,3790,3529,3243,
-2965,2729,2544,2394,2276,2219,2239,2293,2297,2216,2105,2055,2092,2155,2178,2146,2095,2048,1998,1927,1839,
-1752,1685,1636,1592,1539,1478,1420,1365,1297,1192,1052,900,761,640,525,408,290,173,50,-77,-198,
--296,-370,-428,-477,-522,-565,-607,-648,-683,-711,-734,-750,-751,-736,-715,-702,-707,-725,-748,-767,-773,
--755,-715,-668,-635,-623,-626,-633,-640,-644,-640,-615,-566,-504,-453,-421,-406,-403,-419,-464,-530,-594,
--631,-635,-614,-575,-530,-498,-497,-524,-557,-585,-620,-683,-777,-886,-995,-1095,-1159,-1150,-1058,-915,-781,
--701,-696,-761,-857,-910,-864,-741,-631,-594,-593,-547,-442,-353,-350,-420,-488,-517,-534,-570,-610,-610,
--554,-476,-426,-435,-488,-548,-584,-595,-602,-615,-616,-581,-521,-482,-499,-561,-626,-662,-670,-667,-660,
--650,-639,-634,-634,-635,-632,-627,-621,-614,-603,-587,-569,-547,-523,-499,-477,-455,-431,-404,-378,-354,
--325,-289,-252,-219,-190,-158,-120,-80,-45,-10,28,71,113,151,189,231,274,313,347,383,422,
-459,490,520,555,591,627,661,698,736,770,800,834,876,919,955,986,1025,1076,1128,1166,1191,
-1210,1227,1235,1233,1230,1232,1239,1246,1252,1260,1270,1274,1275,1276,1281,1288,1293,1299,1305,1310,1313,
-1316,1324,1334,1342,1348,1356,1367,1377,1389,1406,1428,1446,1457,1468,1487,1511,1531,1547,1563,1582,1595,
-1601,1611,1632,1657,1673,1680,1691,1703,1720,1737,1751,1767,1789,1813,1833,1850,1872,1902,1935,1967,2000,
-2036,2074,2116,2160,2197,2213,2212,2212,2228,2252,2265,2265,2272,2296,2323,2332,2322,2313,2313,2312,2295,
-2265,2239,2232,2240,2254,2268,2286,2308,2334,2363,2400,2451,2511,2563,2591,2586,2559,2531,2521,2537,2573,
-2615,2657,2699,2746,2799,2850,2885,2893,2876,2849,2828,2821,2827,2843,2864,2882,2878,2834,2751,2653,2564,
-2485,2405,2315,2221,2133,2050,1970,1890,1819,1766,1739,1738,1754,1763,1748,1710,1665,1622,1579,1534,1493,
-1465,1443,1423,1409,1410,1418,1410,1377,1334,1301,1279,1257,1223,1180,1132,1080,1029,977,922,856,779,
-696,612,532,465,427,420,427,425,409,388,361,317,252,174,97,27,-34,-86,-130,-176,-233,
--302,-377,-450,-510,-547,-556,-545,-528,-512,-496,-483,-489,-523,-574,-621,-657,-682,-695,-692,-678,-663,
--649,-632,-615,-614,-628,-629,-595,-538,-496,-485,-483,-460,-413,-365,-337,-330,-327,-303,-240,-146,-55,
-12,72,153,236,258,178,41,-60,-88,-105,-203,-396,-609,-758,-829,-867,-908,-941,-947,-931,-919,
--920,-918,-900,-877,-871,-884,-896,-895,-882,-866,-847,-814,-748,-618,-396,-108,146,237,100,-204,-542,
--796,-927,-964,-961,-956,-958,-949,-918,-873,-838,-821,-806,-777,-749,-744,-760,-772,-767,-759,-773,-802,
--828,-841,-851,-863,-870,-864,-858,-865,-884,-906,-923,-939,-959,-979,-998,-1019,-1045,-1071,-1094,-1115,-1138,
--1165,-1196,-1230,-1267,-1305,-1341,-1379,-1426,-1479,-1533,-1584,-1637,-1696,-1757,-1815,-1872,-1930,-1992,-2053,-2108,-2157,
--2200,-2239,-2278,-2326,-2384,-2451,-2518,-2577,-2627,-2669,-2711,-2763,-2824,-2886,-2941,-2993,-3046,-3099,-3144,-3180,-3216,
--3260,-3308,-3354,-3400,-3449,-3501,-3546,-3582,-3614,-3652,-3695,-3738,-3778,-3815,-3850,-3889,-3934,-3985,-4036,-4077,-4107,
--4129,-4148,-4164,-4180,-4197,-4214,-4228,-4233,-4233,-4235,-4242,-4254,-4267,-4281,-4291,-4291,-4279,-4258,-4242,-4242,-4263,
--4307,-4374,-4458,-4541,-4595,-4611,-4605,-4604,-4618,-4633,-4632,-4622,-4622,-4643,-4674,-4696,-4703,-4704,-4713,-4736,-4766,
--4787,-4787,-4769,-4748,-4738,-4734,-4724,-4705,-4686,-4675,-4667,-4659,-4657,-4667,-4689,-4716,-4740,-4760,-4776,-4782,-4777,
--4766,-4749,-4723,-4685,-4642,-4599,-4559,-4521,-4489,-4461,-4431,-4387,-4331,-4273,-4216,-4152,-4081,-4010,-3947,-3886,-3813,
--3734,-3664,-3611,-3570,-3541,-3534,-3545,-3552,-3531,-3487,-3440,-3400,-3355,-3296,-3234,-3185,-3152,-3125,-3094,-3054,-3008,
--2960,-2918,-2883,-2850,-2815,-2783,-2759,-2735,-2690,-2617,-2530,-2452,-2394,-2351,-2311,-2260,-2191,-2106,-2015,-1920,-1795,
--1621,-1421,-1254,-1154,-1095,-1025,-933,-855,-821,-817,-806,-774,-732,-695,-658,-617,-569,-513,-435,-329,-203,
--79,25,109,176,236,299,371,447,519,583,640,686,708,707,699,703,721,743,761,785,822,
-871,921,971,1026,1088,1148,1204,1262,1327,1387,1434,1475,1526,1593,1655,1695,1718,1748,1803,1878,1954,
-2023,2085,2142,2189,2226,2259,2297,2340,2385,2430,2479,2533,2589,2643,2693,2742,2797,2865,2944,3022,3079,
-3106,3118,3141,3185,3242,3295,3340,3382,3428,3480,3544,3627,3724,3824,3919,4022,4144,4268,4358,4389,4380,
-4367,4365,4364,4353,4337,4333,4340,4348,4356,4382,4435,4502,4562,4612,4668,4742,4826,4908,4985,5063,5140,
-5205,5254,5296,5337,5373,5393,5405,5425,5463,5504,5527,5527,5522,5529,5551,5572,5577,5563,5542,5526,5520,
-5524,5536,5556,5580,5603,5618,5621,5606,5558,5472,5374,5304,5276,5265,5239,5208,5214,5273,5350,5392,5386,
-5358,5342,5346,5363,5382,5395,5397,5406,5458,5566,5681,5724,5655,5520,5410,5392,5464,5571,5661,5709,5723,
-5721,5712,5685,5631,5557,5483,5427,5388,5364,5364,5423,5569,5793,6037,6222,6297,6259,6147,6019,5930,5914,
-5962,6023,6047,6008,5901,5714,5441,5135,4930,4957,5225,5608,5943,6151,6256,6313,6352,6377,6392,6399,6394,
-6375,6347,6319,6295,6271,6246,6223,6202,6174,6136,6094,6051,6011,5979,5958,5940,5898,5807,5668,5516,5396,
-5337,5334,5349,5336,5277,5193,5116,5061,5023,4998,4994,5017,5056,5093,5130,5177,5226,5249,5233,5199,5184,
-5199,5231,5259,5276,5286,5291,5288,5278,5267,5258,5225,5092,4762,4202,3515,2914,2584,2553,2693,2843,2925,
-2952,2961,2959,2934,2883,2822,2764,2710,2652,2586,2510,2431,2358,2293,2233,2168,2099,2029,1961,1894,1823,
-1750,1680,1623,1582,1554,1529,1495,1453,1410,1379,1363,1357,1351,1337,1308,1267,1228,1204,1194,1186,1171,
-1149,1130,1112,1090,1071,1067,1085,1103,1090,1033,950,874,818,774,728,681,650,641,641,630,598,
-555,516,491,471,449,419,383,345,307,269,230,192,157,126,105,95,90,76,42,0,-29,
--38,-41,-65,-116,-175,-215,-233,-245,-268,-300,-330,-353,-377,-411,-452,-489,-514,-532,-552,-576,-599,
--619,-640,-665,-688,-698,-702,-715,-746,-780,-795,-790,-786,-800,-827,-851,-869,-888,-914,-936,-943,-937,
--934,-944,-968,-997,-1019,-1025,-1017,-1004,-998,-1003,-1013,-1021,-1025,-1027,-1033,-1044,-1062,-1085,-1106,-1119,-1124,
--1128,-1136,-1143,-1147,-1146,-1146,-1147,-1150,-1156,-1166,-1177,-1181,-1178,-1174,-1175,-1177,-1176,-1173,-1172,-1174,-1174,
--1170,-1165,-1163,-1164,-1161,-1151,-1139,-1130,-1126,-1120,-1111,-1099,-1084,-1067,-1050,-1034,-1021,-1010,-998,-983,-967,
--953,-941,-925,-901,-871,-842,-819,-801,-784,-762,-738,-718,-701,-684,-664,-642,-621,-604,-591,-579,-566,
--553,-539,-523,-506,-491,-477,-463,-447,-432,-418,-407,-395,-382,-371,-363,-358,-351,-341,-331,-324,-320,
--315,-308,-300,-293,-287,-282,-280,-279,-278,-273,-268,-265,-264,-263,-261,-261,-262,-264,-266,-268,-271,
--274,-277,-277,-277,-278,-281,-288,-296,-303,-305,-304,-305,-307,-307,-304,-302,-306,-311,-312,-311,-315,
--323,-330,-331,-331,-335,-342,-346,-344,-343,-341,-336,-329,-327,-333,-339,-340,-338,-336,-336,-333,-328,
--324,-322,-320,-317,-313,-309,-302,-295,-291,-291,-288,-277,-262,-250,-241,-231,-218,-207,-198,-188,-176,
--166,-163,-161,-157,-151,-146,-143,-137,-126,-113,-99,-86,-77,-73,-68,-55,-35,-14,0,10,20,
-29,39,52,71,88,94,93,98,116,138,156,171,192,216,236,253,274,301,335,371,408,
-445,480,520,570,628,685,728,755,768,773,780,798,824,844,855,871,907,954,992,1019,1048,
-1090,1132,1167,1205,1255,1308,1349,1387,1437,1493,1539,1577,1632,1705,1765,1795,1820,1871,1929,1957,1966,
-2002,2049,2004,1797,1521,1388,1555,1988,2509,2929,3161,3247,3316,3493,3788,4088,4264,4298,4277,4277,4291,
-4276,4239,4222,4247,4283,4291,4263,4205,4111,3966,3763,3509,3224,2938,2690,2495,2347,2240,2195,2224,2280,
-2281,2195,2086,2046,2096,2167,2186,2145,2090,2045,1998,1922,1821,1721,1650,1612,1588,1557,1509,1450,1386,
-1307,1198,1059,914,783,667,549,424,297,174,51,-72,-185,-274,-341,-397,-449,-497,-539,-579,-616,
--645,-667,-688,-711,-728,-728,-712,-694,-688,-695,-712,-731,-743,-736,-706,-661,-617,-582,-557,-539,-532,
--536,-543,-538,-511,-469,-428,-397,-377,-369,-380,-413,-457,-495,-521,-547,-575,-590,-579,-556,-551,-573,
--598,-609,-625,-684,-792,-916,-1020,-1096,-1142,-1145,-1091,-990,-885,-822,-825,-890,-981,-1038,-1011,-912,-810,
--754,-726,-668,-567,-479,-457,-492,-532,-551,-568,-603,-638,-637,-590,-527,-487,-491,-528,-573,-600,-607,
--608,-616,-621,-605,-569,-545,-558,-602,-643,-661,-661,-657,-652,-643,-633,-626,-626,-626,-621,-614,-607,
--599,-586,-568,-546,-523,-499,-475,-454,-434,-412,-386,-359,-333,-303,-269,-233,-200,-169,-137,-99,-61,
--28,3,39,80,122,160,198,238,277,312,345,380,417,453,487,521,559,598,634,671,708,
-745,776,804,839,882,923,956,985,1026,1080,1132,1168,1191,1212,1230,1238,1236,1235,1241,1247,1248,
-1247,1253,1264,1272,1273,1274,1281,1291,1298,1303,1308,1313,1315,1316,1322,1332,1342,1350,1359,1371,1384,
-1399,1417,1437,1454,1465,1477,1496,1522,1545,1562,1577,1594,1605,1611,1619,1638,1662,1680,1691,1705,1721,
-1740,1761,1780,1799,1819,1840,1860,1881,1909,1943,1980,2017,2055,2091,2123,2155,2187,2215,2226,2224,2227,
-2253,2291,2317,2325,2331,2347,2359,2344,2302,2262,2248,2254,2258,2249,2236,2229,2228,2231,2241,2262,2295,
-2328,2356,2387,2433,2495,2559,2603,2615,2599,2576,2566,2579,2614,2662,2715,2769,2820,2866,2901,2923,2928,
-2918,2904,2895,2896,2903,2910,2918,2923,2913,2871,2796,2707,2624,2544,2457,2358,2258,2166,2081,1994,1908,
-1835,1785,1764,1767,1781,1787,1770,1735,1696,1659,1620,1575,1530,1496,1471,1451,1441,1444,1452,1444,1411,
-1367,1330,1298,1263,1218,1171,1124,1078,1034,992,947,894,834,777,726,679,634,602,592,592,575,
-529,462,393,327,261,195,136,87,44,2,-43,-101,-169,-245,-317,-377,-415,-430,-426,-419,-416,
--413,-404,-398,-415,-458,-505,-532,-539,-547,-565,-585,-595,-592,-578,-561,-548,-548,-555,-550,-520,-475,
--432,-397,-363,-324,-286,-259,-246,-247,-252,-232,-164,-60,28,70,97,160,245,268,173,19,-81,
--90,-93,-192,-389,-588,-706,-755,-792,-844,-884,-889,-871,-859,-857,-849,-827,-807,-809,-826,-838,-831,
--810,-783,-756,-726,-676,-564,-355,-68,196,302,185,-101,-427,-680,-827,-895,-922,-924,-902,-859,-812,
--778,-762,-749,-724,-692,-674,-682,-702,-711,-705,-705,-723,-752,-773,-786,-798,-811,-818,-816,-816,-827,
--846,-863,-873,-882,-895,-913,-935,-961,-985,-1004,-1021,-1040,-1065,-1094,-1127,-1162,-1199,-1235,-1267,-1300,-1343,
--1395,-1450,-1503,-1556,-1614,-1674,-1730,-1784,-1839,-1898,-1958,-2013,-2060,-2100,-2137,-2180,-2234,-2297,-2362,-2425,-2482,
--2532,-2578,-2623,-2676,-2736,-2796,-2850,-2902,-2957,-3011,-3057,-3094,-3131,-3176,-3226,-3275,-3325,-3374,-3420,-3457,-3487,
--3518,-3557,-3603,-3648,-3690,-3729,-3766,-3803,-3844,-3891,-3939,-3982,-4015,-4042,-4064,-4083,-4100,-4115,-4129,-4137,-4140,
--4140,-4146,-4158,-4175,-4195,-4214,-4228,-4229,-4218,-4202,-4191,-4189,-4201,-4237,-4303,-4392,-4476,-4527,-4541,-4541,-4552,
--4574,-4589,-4586,-4577,-4584,-4613,-4649,-4675,-4683,-4684,-4691,-4709,-4734,-4751,-4751,-4734,-4716,-4705,-4699,-4687,-4668,
--4650,-4638,-4632,-4629,-4634,-4651,-4675,-4701,-4726,-4750,-4770,-4777,-4770,-4756,-4737,-4712,-4678,-4639,-4602,-4563,-4520,
--4476,-4438,-4404,-4367,-4322,-4271,-4214,-4145,-4067,-3993,-3926,-3855,-3768,-3676,-3601,-3550,-3516,-3497,-3503,-3533,-3558,
--3550,-3508,-3458,-3416,-3371,-3309,-3240,-3187,-3158,-3140,-3116,-3079,-3038,-3003,-2978,-2955,-2921,-2875,-2828,-2797,-2775,
--2743,-2686,-2609,-2533,-2469,-2417,-2370,-2313,-2234,-2132,-2016,-1895,-1756,-1589,-1412,-1263,-1156,-1068,-971,-878,-828,
--834,-856,-844,-795,-740,-705,-686,-664,-630,-578,-501,-395,-270,-149,-47,32,97,154,212,276,344,
-414,487,562,626,660,658,641,634,645,664,680,700,730,770,814,860,912,969,1028,1090,1159,
-1233,1297,1345,1389,1445,1513,1574,1610,1633,1671,1735,1812,1882,1936,1981,2022,2060,2096,2141,2203,2277,
-2346,2401,2448,2500,2563,2628,2683,2722,2757,2804,2870,2942,3000,3035,3061,3096,3145,3198,3241,3277,3316,
-3362,3414,3478,3560,3659,3760,3854,3952,4065,4183,4271,4308,4310,4307,4312,4313,4302,4290,4290,4298,4300,
-4299,4317,4367,4432,4488,4529,4573,4634,4706,4778,4851,4934,5026,5109,5171,5218,5263,5307,5340,5358,5374,
-5401,5436,5466,5480,5482,5485,5495,5509,5516,5510,5494,5477,5467,5470,5484,5505,5529,5550,5567,5576,5567,
-5524,5445,5356,5290,5252,5217,5166,5122,5128,5194,5276,5326,5334,5326,5322,5317,5312,5320,5347,5377,5393,
-5411,5466,5557,5632,5625,5531,5417,5361,5393,5479,5559,5603,5620,5636,5659,5669,5643,5574,5488,5414,5365,
-5333,5310,5315,5384,5536,5750,5974,6154,6250,6243,6140,5993,5878,5848,5892,5957,5992,5973,5876,5667,5363,
-5075,4962,5104,5428,5779,6036,6177,6244,6278,6301,6322,6340,6347,6335,6305,6269,6235,6206,6183,6165,6148,
-6125,6097,6067,6037,6006,5973,5938,5892,5817,5702,5560,5427,5341,5314,5325,5331,5297,5225,5146,5088,5054,
-5027,5001,4994,5016,5059,5103,5145,5189,5228,5243,5226,5200,5193,5214,5248,5275,5291,5297,5296,5289,5275,
-5253,5208,5103,4869,4446,3846,3208,2732,2546,2613,2777,2900,2951,2968,2979,2974,2939,2880,2819,2763,2708,
-2649,2587,2522,2452,2382,2317,2254,2183,2106,2034,1974,1919,1854,1773,1690,1624,1581,1551,1519,1479,1434,
-1394,1365,1347,1339,1334,1323,1299,1262,1223,1197,1185,1178,1167,1153,1140,1123,1099,1077,1081,1113,1146,
-1137,1073,976,886,822,778,737,693,650,613,583,558,538,518,497,478,460,442,420,387,345,
-298,250,208,169,132,99,75,67,66,57,25,-22,-61,-79,-83,-98,-136,-185,-226,-252,-272,
--298,-330,-363,-389,-412,-439,-473,-508,-534,-550,-564,-585,-609,-630,-647,-667,-690,-707,-716,-727,-752,
--787,-814,-822,-822,-827,-840,-851,-861,-882,-917,-951,-963,-952,-933,-926,-941,-974,-1011,-1035,-1039,-1029,
--1024,-1031,-1044,-1048,-1040,-1023,-1008,-1001,-1009,-1029,-1055,-1075,-1087,-1098,-1115,-1133,-1144,-1145,-1143,-1143,-1147,
--1152,-1159,-1167,-1171,-1169,-1164,-1161,-1162,-1162,-1160,-1158,-1158,-1159,-1159,-1157,-1158,-1161,-1162,-1155,-1145,-1138,
--1136,-1133,-1125,-1114,-1101,-1087,-1070,-1052,-1035,-1021,-1009,-994,-977,-960,-946,-931,-911,-884,-854,-828,-808,
--789,-769,-746,-725,-707,-690,-671,-649,-629,-613,-600,-587,-573,-559,-545,-528,-511,-496,-483,-469,-451,
--433,-418,-407,-397,-386,-376,-369,-364,-356,-346,-337,-331,-327,-319,-309,-301,-294,-290,-288,-289,-290,
--288,-283,-278,-276,-276,-274,-271,-271,-274,-275,-275,-276,-279,-284,-286,-287,-288,-289,-290,-291,-296,
--301,-303,-303,-304,-307,-308,-305,-304,-306,-310,-309,-307,-310,-318,-324,-324,-322,-325,-330,-333,-333,
--332,-330,-326,-322,-322,-326,-329,-328,-326,-325,-324,-318,-311,-307,-305,-304,-302,-299,-296,-288,-278,
--271,-269,-264,-251,-235,-223,-215,-205,-193,-182,-174,-166,-155,-147,-143,-141,-136,-130,-125,-122,-118,
--109,-97,-82,-68,-56,-50,-45,-34,-16,1,14,25,37,48,61,76,94,106,110,113,126,
-148,170,186,202,223,244,260,277,303,335,367,396,429,470,513,557,608,669,728,762,763,
-742,728,744,789,837,859,858,864,897,943,976,999,1033,1080,1121,1149,1184,1240,1299,1337,1363,
-1406,1468,1526,1574,1630,1702,1759,1782,1800,1848,1912,1949,1966,2005,2051,2006,1798,1518,1380,1539,1963,
-2474,2889,3121,3210,3277,3443,3726,4022,4210,4272,4282,4303,4319,4297,4253,4234,4247,4256,4235,4196,4151,
-4081,3949,3746,3490,3203,2914,2657,2457,2313,2218,2180,2203,2248,2244,2166,2074,2051,2108,2176,2186,2143,
-2091,2053,2003,1916,1801,1690,1614,1579,1571,1562,1532,1476,1401,1308,1194,1062,929,808,692,567,431,
-297,171,51,-64,-166,-245,-308,-366,-424,-474,-514,-550,-585,-613,-631,-649,-675,-701,-714,-706,-689,
--677,-677,-688,-704,-717,-719,-702,-667,-621,-566,-508,-457,-429,-431,-452,-467,-459,-433,-401,-375,-356,
--346,-349,-370,-402,-435,-467,-504,-543,-568,-569,-562,-571,-596,-611,-601,-604,-666,-792,-928,-1024,-1076,
--1106,-1123,-1112,-1072,-1025,-1000,-1006,-1033,-1065,-1080,-1059,-1004,-945,-909,-888,-849,-781,-711,-672,-661,-655,
--644,-643,-659,-674,-668,-637,-602,-580,-575,-585,-601,-610,-608,-604,-610,-622,-628,-620,-613,-621,-642,
--658,-658,-652,-650,-648,-641,-630,-624,-624,-623,-616,-606,-597,-586,-570,-548,-526,-503,-480,-456,-433,
--414,-394,-371,-344,-316,-285,-252,-217,-184,-151,-116,-78,-41,-8,21,54,92,132,171,208,244,
-280,314,347,381,417,453,490,528,569,608,645,682,720,755,785,813,849,892,931,962,995,
-1042,1099,1149,1179,1197,1214,1230,1236,1233,1232,1239,1246,1244,1239,1243,1256,1267,1269,1270,1277,1285,
-1290,1293,1298,1306,1310,1312,1318,1328,1340,1350,1361,1377,1395,1413,1429,1447,1465,1478,1492,1511,1536,
-1559,1577,1591,1606,1619,1627,1636,1651,1672,1691,1707,1723,1739,1759,1780,1801,1822,1843,1865,1887,1914,
-1947,1983,2021,2059,2095,2125,2145,2160,2182,2211,2234,2249,2266,2300,2341,2368,2373,2374,2384,2390,2364,
-2306,2247,2221,2228,2244,2248,2242,2235,2232,2231,2239,2261,2295,2329,2355,2383,2427,2491,2559,2609,2629,
-2627,2622,2625,2642,2672,2718,2780,2846,2901,2934,2946,2951,2956,2961,2964,2965,2965,2959,2944,2924,2904,
-2882,2846,2790,2723,2653,2579,2491,2388,2284,2189,2100,2010,1924,1855,1813,1797,1801,1814,1819,1803,1770,
-1732,1697,1659,1615,1571,1535,1510,1490,1478,1477,1478,1464,1430,1386,1347,1309,1264,1213,1165,1124,1088,
-1053,1020,988,952,916,888,870,853,826,794,765,735,685,603,501,404,327,271,231,201,174,
-141,98,43,-19,-87,-156,-220,-270,-300,-310,-312,-316,-326,-333,-334,-342,-369,-407,-429,-417,-388,
--378,-402,-444,-479,-493,-489,-479,-470,-469,-472,-470,-454,-421,-373,-314,-256,-214,-189,-176,-167,-171,
--186,-177,-106,12,112,150,159,204,275,282,172,12,-79,-76,-79,-189,-388,-569,-662,-696,-731,
--783,-818,-816,-797,-787,-785,-777,-760,-750,-756,-767,-767,-753,-730,-702,-674,-648,-615,-542,-391,-170,
-43,137,53,-167,-422,-620,-736,-789,-806,-797,-769,-735,-714,-708,-702,-680,-644,-616,-614,-632,-648,
--649,-646,-654,-676,-698,-715,-728,-744,-759,-769,-774,-782,-794,-806,-812,-816,-821,-833,-851,-875,-899,
--919,-933,-948,-971,-1001,-1032,-1063,-1098,-1133,-1165,-1193,-1223,-1263,-1314,-1368,-1420,-1474,-1532,-1591,-1647,-1701,
--1754,-1811,-1868,-1921,-1966,-2003,-2040,-2087,-2147,-2213,-2276,-2333,-2387,-2440,-2491,-2541,-2593,-2649,-2705,-2760,-2815,
--2872,-2926,-2970,-3007,-3047,-3094,-3147,-3200,-3251,-3298,-3337,-3366,-3392,-3425,-3467,-3513,-3559,-3602,-3644,-3683,-3719,
--3756,-3799,-3845,-3889,-3926,-3956,-3980,-4000,-4017,-4031,-4041,-4044,-4045,-4051,-4064,-4082,-4103,-4126,-4150,-4165,-4165,
--4154,-4140,-4132,-4127,-4129,-4155,-4221,-4316,-4406,-4460,-4478,-4485,-4505,-4533,-4550,-4547,-4541,-4552,-4585,-4624,-4651,
--4661,-4663,-4668,-4683,-4704,-4719,-4718,-4704,-4686,-4674,-4666,-4655,-4638,-4621,-4609,-4603,-4604,-4616,-4638,-4664,-4688,
--4710,-4734,-4754,-4760,-4751,-4736,-4718,-4695,-4664,-4627,-4593,-4556,-4513,-4465,-4420,-4382,-4346,-4307,-4260,-4202,-4131,
--4054,-3982,-3913,-3829,-3723,-3611,-3525,-3475,-3452,-3448,-3470,-3516,-3557,-3561,-3527,-3479,-3436,-3388,-3319,-3240,-3178,
--3146,-3133,-3117,-3089,-3059,-3038,-3029,-3019,-2993,-2946,-2893,-2851,-2820,-2786,-2737,-2674,-2608,-2544,-2480,-2415,-2341,
--2246,-2123,-1978,-1827,-1676,-1527,-1387,-1267,-1164,-1060,-948,-859,-831,-857,-884,-864,-801,-740,-710,-704,-697,
--676,-634,-566,-469,-353,-238,-137,-53,16,76,130,185,245,315,398,487,565,607,607,585,569,
-572,585,599,617,644,680,720,762,806,853,903,964,1042,1129,1206,1264,1313,1371,1439,1498,1537,
-1567,1609,1668,1729,1775,1805,1828,1851,1877,1911,1965,2045,2139,2223,2285,2331,2384,2456,2538,2609,2658,
-2692,2732,2787,2851,2909,2953,2993,3042,3102,3158,3199,3232,3266,3309,3359,3420,3499,3595,3695,3789,3882,
-3984,4090,4176,4225,4243,4250,4256,4255,4245,4235,4234,4237,4235,4235,4255,4305,4366,4417,4453,4491,4544,
-4607,4672,4741,4825,4923,5017,5089,5142,5189,5238,5281,5309,5325,5339,5360,5390,5419,5441,5452,5455,5457,
-5460,5460,5451,5435,5421,5417,5429,5452,5477,5499,5513,5518,5506,5467,5406,5340,5284,5236,5178,5111,5066,
-5072,5125,5186,5224,5249,5280,5310,5316,5298,5289,5309,5336,5330,5301,5306,5385,5501,5566,5528,5427,5350,
-5350,5408,5468,5498,5508,5525,5558,5589,5590,5551,5482,5410,5355,5319,5292,5275,5284,5342,5462,5640,5852,
-6060,6200,6222,6125,5979,5868,5832,5853,5897,5937,5935,5829,5591,5285,5061,5042,5235,5535,5821,6027,6147,
-6204,6227,6242,6258,6270,6263,6235,6198,6165,6142,6125,6108,6089,6070,6056,6047,6029,5990,5928,5851,5767,
-5671,5562,5453,5368,5324,5311,5304,5275,5215,5143,5087,5057,5040,5020,4998,4996,5023,5068,5113,5153,5193,
-5226,5237,5222,5202,5201,5226,5261,5291,5304,5300,5287,5273,5260,5226,5128,4917,4554,4040,3445,2917,2607,
-2563,2697,2855,2944,2971,2985,2997,2984,2935,2871,2816,2767,2712,2652,2591,2532,2467,2397,2326,2258,2187,
-2113,2045,1990,1938,1870,1785,1698,1629,1582,1545,1505,1460,1416,1380,1352,1330,1314,1305,1297,1282,1254,
-1218,1188,1170,1161,1155,1149,1143,1128,1103,1078,1072,1093,1117,1109,1054,970,888,830,793,764,728,
-678,614,552,509,491,484,475,458,442,430,416,391,350,301,251,206,165,125,85,53,35,
-31,25,4,-31,-69,-97,-115,-137,-168,-207,-244,-275,-299,-322,-350,-384,-418,-446,-468,-493,-524,
--551,-566,-575,-588,-611,-634,-652,-670,-692,-713,-727,-735,-753,-784,-815,-833,-839,-845,-853,-861,-871,
--893,-927,-958,-963,-942,-916,-907,-925,-961,-998,-1018,-1015,-1002,-1000,-1018,-1044,-1058,-1053,-1035,-1016,-1003,
--1001,-1010,-1026,-1040,-1049,-1062,-1084,-1111,-1130,-1136,-1135,-1138,-1144,-1148,-1150,-1152,-1155,-1156,-1151,-1146,-1144,
--1143,-1142,-1138,-1137,-1139,-1141,-1141,-1142,-1146,-1147,-1144,-1138,-1134,-1133,-1133,-1127,-1118,-1108,-1098,-1083,-1065,
--1046,-1030,-1017,-1003,-987,-971,-955,-941,-923,-900,-874,-847,-824,-804,-783,-762,-741,-722,-704,-685,-665,
--646,-630,-614,-598,-581,-566,-551,-534,-516,-501,-488,-475,-457,-437,-421,-411,-402,-392,-382,-375,-368,
--359,-349,-342,-337,-331,-322,-312,-305,-301,-298,-297,-299,-301,-300,-295,-290,-289,-288,-284,-281,-282,
--286,-287,-287,-287,-289,-290,-290,-292,-297,-302,-304,-303,-302,-304,-306,-306,-306,-309,-311,-310,-309,
--310,-310,-308,-306,-309,-315,-320,-320,-318,-320,-323,-324,-323,-323,-323,-322,-321,-321,-322,-320,-317,
--314,-312,-309,-302,-296,-294,-294,-292,-288,-285,-281,-271,-258,-248,-245,-241,-230,-216,-203,-194,-185,
--173,-164,-157,-149,-138,-127,-121,-117,-113,-108,-105,-102,-97,-89,-78,-64,-50,-38,-30,-23,-12,
-3,19,30,40,52,67,84,102,117,126,129,137,154,174,192,209,233,260,279,289,305,
-335,370,395,414,446,497,552,598,640,692,747,777,762,716,686,708,775,841,866,860,861,
-892,933,959,978,1015,1069,1111,1133,1164,1223,1289,1329,1349,1384,1446,1510,1564,1622,1690,1742,1760,
-1774,1822,1888,1933,1957,2002,2050,2003,1790,1506,1364,1519,1940,2455,2885,3141,3247,3313,3458,3712,3992,
-4188,4274,4311,4344,4362,4338,4297,4275,4268,4243,4195,4156,4134,4077,3935,3708,3438,3159,2886,2639,2447,
-2315,2232,2192,2192,2207,2188,2120,2050,2046,2106,2166,2171,2133,2092,2058,2003,1905,1782,1668,1590,1554,
-1551,1557,1545,1495,1409,1300,1179,1056,940,828,710,575,429,290,165,49,-59,-151,-221,-279,-340,
--402,-452,-486,-516,-550,-582,-605,-624,-649,-675,-689,-685,-671,-663,-665,-676,-688,-695,-695,-686,-665,
--629,-571,-494,-418,-368,-358,-377,-397,-399,-380,-356,-341,-335,-333,-335,-347,-375,-417,-460,-494,-512,
--515,-514,-528,-564,-602,-610,-588,-583,-651,-785,-922,-1007,-1042,-1064,-1090,-1106,-1104,-1098,-1103,-1108,-1096,
--1067,-1040,-1024,-1011,-995,-980,-967,-948,-913,-869,-827,-790,-755,-726,-710,-705,-699,-683,-664,-651,-641,
--630,-617,-610,-608,-605,-601,-605,-620,-636,-643,-645,-649,-656,-657,-651,-646,-647,-648,-641,-630,-625,
--625,-624,-615,-602,-589,-576,-557,-535,-515,-497,-476,-451,-425,-402,-380,-357,-329,-299,-267,-234,-200,
--166,-133,-97,-60,-22,10,41,73,109,146,183,218,252,286,318,352,387,423,459,499,540,
-582,619,654,690,728,764,796,827,864,905,943,975,1012,1063,1120,1163,1184,1196,1211,1228,1233,
-1227,1223,1229,1237,1237,1233,1237,1250,1261,1264,1264,1268,1273,1275,1276,1283,1295,1305,1311,1318,1330,
-1341,1351,1363,1382,1403,1421,1435,1451,1470,1489,1505,1521,1542,1563,1582,1598,1616,1634,1648,1659,1672,
-1689,1707,1722,1738,1755,1772,1793,1817,1842,1866,1890,1918,1951,1986,2021,2054,2087,2118,2140,2150,2156,
-2177,2218,2266,2306,2338,2369,2397,2412,2411,2409,2419,2426,2403,2344,2278,2240,2238,2248,2251,2244,2238,
-2239,2243,2253,2272,2301,2331,2356,2385,2432,2499,2571,2623,2649,2660,2673,2694,2718,2744,2781,2836,2902,
-2954,2974,2970,2964,2973,2994,3013,3021,3017,2996,2955,2901,2850,2811,2780,2746,2704,2654,2589,2503,2401,
-2298,2203,2112,2025,1948,1895,1866,1856,1858,1867,1870,1855,1819,1776,1735,1695,1653,1613,1581,1557,1537,
-1522,1514,1508,1487,1449,1404,1362,1322,1274,1220,1172,1136,1107,1077,1048,1023,1003,989,983,983,979,
-961,928,884,823,738,628,510,408,336,296,278,271,259,232,188,133,73,11,-52,-110,-155,
--183,-199,-213,-230,-249,-263,-275,-297,-330,-358,-353,-308,-256,-235,-259,-306,-348,-372,-382,-384,-381,
--377,-379,-388,-391,-370,-314,-235,-162,-120,-105,-95,-83,-86,-108,-105,-29,103,215,253,254,282,
-327,308,183,28,-52,-51,-72,-199,-395,-553,-625,-650,-683,-727,-749,-739,-723,-719,-721,-714,-704,
--702,-707,-703,-686,-665,-646,-627,-601,-574,-549,-511,-431,-305,-176,-115,-165,-304,-468,-595,-665,-689,
--687,-670,-650,-640,-644,-651,-640,-605,-565,-548,-562,-587,-601,-604,-608,-621,-639,-651,-657,-665,-677,
--688,-698,-710,-724,-737,-743,-745,-749,-759,-773,-792,-814,-835,-852,-866,-885,-913,-944,-972,-1001,-1033,
--1068,-1098,-1124,-1152,-1191,-1239,-1290,-1340,-1394,-1450,-1508,-1565,-1619,-1673,-1727,-1780,-1831,-1876,-1914,-1953,-2002,
--2065,-2132,-2192,-2245,-2296,-2349,-2402,-2453,-2506,-2560,-2616,-2673,-2731,-2789,-2840,-2882,-2920,-2963,-3015,-3070,-3124,
--3173,-3216,-3249,-3274,-3301,-3338,-3383,-3429,-3473,-3516,-3560,-3600,-3635,-3670,-3711,-3757,-3803,-3841,-3871,-3894,-3912,
--3928,-3942,-3950,-3953,-3958,-3971,-3992,-4015,-4037,-4060,-4084,-4099,-4096,-4082,-4069,-4060,-4051,-4046,-4067,-4136,-4241,
--4342,-4403,-4424,-4436,-4461,-4495,-4517,-4520,-4519,-4531,-4562,-4599,-4625,-4636,-4638,-4643,-4656,-4674,-4688,-4688,-4675,
--4659,-4648,-4641,-4629,-4612,-4595,-4584,-4582,-4588,-4604,-4628,-4652,-4674,-4695,-4718,-4736,-4739,-4728,-4712,-4696,-4675,
--4643,-4605,-4569,-4535,-4496,-4452,-4409,-4369,-4331,-4289,-4241,-4186,-4125,-4060,-3995,-3925,-3831,-3709,-3579,-3476,-3416,
--3392,-3397,-3434,-3494,-3552,-3572,-3550,-3505,-3455,-3395,-3316,-3230,-3162,-3128,-3116,-3108,-3094,-3078,-3068,-3066,-3065,
--3049,-3015,-2968,-2922,-2879,-2832,-2779,-2724,-2669,-2607,-2532,-2445,-2349,-2235,-2090,-1917,-1740,-1583,-1454,-1352,-1264,
--1175,-1070,-957,-872,-842,-858,-869,-839,-778,-725,-705,-708,-710,-699,-672,-623,-546,-448,-341,-237,-143,
--62,0,48,91,144,216,308,409,497,547,554,535,515,508,511,520,537,562,595,632,670,
-707,741,778,832,913,1013,1108,1181,1236,1291,1352,1409,1453,1490,1531,1576,1613,1633,1641,1647,1658,
-1678,1713,1773,1858,1953,2036,2099,2150,2212,2296,2394,2485,2555,2606,2651,2702,2759,2814,2864,2916,2978,
-3046,3106,3149,3180,3211,3251,3300,3358,3431,3521,3619,3715,3807,3901,3996,4079,4137,4168,4181,4183,4181,
-4175,4170,4165,4159,4152,4158,4189,4241,4297,4341,4375,4413,4464,4523,4584,4652,4735,4831,4926,5004,5064,
-5114,5163,5210,5245,5263,5271,5282,5307,5347,5389,5414,5418,5411,5406,5405,5400,5386,5367,5357,5366,5390,
-5419,5443,5457,5454,5432,5395,5352,5312,5272,5218,5147,5079,5048,5066,5107,5135,5146,5169,5222,5278,5295,
-5272,5249,5255,5264,5232,5171,5157,5246,5402,5513,5504,5404,5312,5295,5341,5392,5416,5421,5432,5457,5484,
-5498,5492,5461,5411,5356,5312,5285,5267,5254,5253,5287,5379,5544,5768,5997,6157,6196,6126,6010,5905,5839,
-5821,5849,5892,5884,5756,5510,5237,5065,5069,5236,5494,5761,5971,6098,6154,6172,6180,6184,6175,6152,6125,
-6105,6095,6082,6058,6023,5991,5973,5965,5942,5883,5790,5687,5595,5517,5449,5390,5350,5328,5310,5275,5218,
-5149,5092,5058,5041,5024,5002,4988,5000,5037,5081,5119,5157,5199,5235,5246,5230,5209,5206,5228,5264,5298,
-5312,5301,5274,5254,5240,5185,5014,4674,4176,3597,3060,2691,2560,2635,2799,2928,2982,2994,3007,3014,2988,
-2928,2863,2812,2765,2707,2640,2579,2522,2458,2384,2308,2240,2176,2114,2054,1999,1940,1869,1787,1707,1641,
-1588,1540,1494,1447,1405,1369,1339,1313,1290,1274,1265,1258,1243,1215,1183,1158,1145,1139,1134,1129,1119,
-1101,1077,1058,1051,1048,1031,991,934,875,830,802,783,756,705,628,546,490,467,462,452,433,
-415,407,401,384,351,306,257,211,169,132,96,61,30,8,-6,-18,-35,-58,-90,-129,-168,
--202,-230,-256,-284,-310,-332,-355,-389,-430,-467,-491,-514,-543,-574,-591,-594,-596,-611,-634,-653,-670,
--689,-709,-722,-729,-744,-775,-810,-834,-846,-853,-862,-870,-882,-905,-936,-958,-953,-927,-904,-907,-937,
--977,-1005,-1006,-983,-958,-955,-982,-1021,-1049,-1056,-1052,-1048,-1045,-1041,-1038,-1037,-1039,-1041,-1048,-1065,-1087,
--1106,-1113,-1118,-1128,-1141,-1149,-1148,-1145,-1144,-1145,-1142,-1136,-1133,-1132,-1131,-1128,-1126,-1126,-1128,-1127,-1125,
--1125,-1126,-1125,-1122,-1119,-1119,-1120,-1117,-1110,-1102,-1093,-1081,-1066,-1049,-1034,-1019,-1006,-992,-978,-965,-950,
--933,-913,-891,-867,-844,-822,-801,-779,-758,-738,-718,-699,-681,-664,-647,-630,-610,-591,-575,-559,-543,
--525,-509,-497,-484,-467,-448,-432,-422,-412,-402,-392,-383,-375,-365,-356,-349,-345,-338,-329,-320,-315,
--313,-311,-309,-311,-314,-313,-310,-306,-305,-303,-299,-295,-295,-297,-299,-299,-299,-300,-298,-293,-293,
--300,-310,-315,-314,-313,-314,-316,-314,-313,-313,-314,-313,-312,-311,-310,-307,-306,-309,-313,-315,-315,
--315,-318,-320,-319,-316,-316,-318,-318,-317,-316,-315,-311,-306,-302,-298,-292,-285,-282,-284,-284,-279,
--271,-267,-263,-254,-241,-230,-225,-223,-215,-202,-191,-181,-171,-160,-150,-143,-133,-121,-110,-101,-94,
--88,-84,-82,-80,-74,-64,-54,-42,-29,-17,-9,-2,8,23,38,50,59,70,86,105,124,
-137,145,150,161,178,193,205,223,252,284,301,307,321,354,389,411,429,470,533,593,625,
-644,679,731,766,754,705,673,699,773,841,863,852,853,885,925,945,959,995,1051,1095,1116,
-1145,1205,1274,1319,1343,1380,1443,1508,1561,1616,1678,1723,1738,1752,1801,1871,1920,1950,1996,2041,1986,
-1767,1478,1335,1492,1925,2468,2937,3225,3340,3385,3492,3710,3972,4173,4281,4339,4383,4401,4377,4337,4311,
-4287,4239,4183,4162,4162,4100,3916,3637,3342,3075,2833,2616,2447,2339,2276,2235,2207,2185,2144,2080,2027,
-2030,2083,2130,2131,2100,2070,2040,1983,1886,1772,1669,1595,1553,1544,1554,1553,1508,1412,1284,1153,1037,
-938,839,721,578,426,286,162,46,-59,-144,-205,-256,-317,-380,-428,-455,-477,-507,-544,-576,-601,
--625,-646,-656,-651,-642,-641,-652,-667,-677,-677,-668,-658,-646,-624,-579,-505,-420,-353,-322,-323,-335,
--335,-322,-307,-306,-321,-339,-348,-355,-376,-419,-465,-491,-490,-479,-485,-522,-578,-617,-612,-578,-572,
--641,-773,-903,-982,-1015,-1039,-1066,-1081,-1077,-1072,-1079,-1083,-1061,-1016,-981,-975,-984,-984,-969,-949,-932,
--915,-891,-860,-826,-792,-764,-746,-730,-709,-684,-667,-660,-653,-637,-617,-605,-605,-607,-607,-609,-620,
--634,-642,-643,-645,-647,-647,-644,-644,-647,-648,-640,-629,-624,-624,-621,-609,-594,-578,-563,-543,-523,
--505,-491,-474,-450,-422,-393,-366,-338,-309,-277,-244,-210,-175,-142,-110,-76,-40,-4,30,63,96,
-130,164,198,231,263,295,327,361,396,432,470,511,554,594,630,663,699,739,777,813,847,
-885,925,962,994,1031,1077,1123,1154,1168,1178,1196,1217,1226,1221,1215,1219,1229,1234,1234,1238,1248,
-1257,1260,1260,1262,1265,1266,1268,1277,1292,1307,1317,1326,1337,1348,1357,1369,1388,1409,1425,1437,1452,
-1474,1497,1514,1526,1540,1559,1581,1603,1626,1650,1669,1683,1694,1706,1722,1733,1751,1769,1789,1813,1840,
-1867,1893,1920,1951,1986,2021,2051,2079,2108,2135,2155,2164,2172,2199,2253,2320,2378,2415,2435,2447,2453,
-2452,2451,2455,2453,2427,2373,2309,2265,2251,2251,2246,2237,2232,2238,2250,2262,2278,2301,2328,2355,2386,
-2434,2505,2583,2644,2677,2695,2716,2749,2783,2809,2835,2875,2928,2972,2990,2984,2982,2998,3029,3054,3065,
-3056,3023,2961,2879,2799,2741,2709,2691,2670,2635,2577,2494,2398,2301,2211,2125,2046,1983,1946,1929,1922,
-1920,1924,1925,1910,1872,1821,1773,1730,1691,1657,1631,1609,1588,1568,1555,1544,1522,1482,1436,1393,1353,
-1308,1255,1205,1165,1131,1096,1064,1043,1036,1039,1043,1043,1034,1016,985,937,862,755,630,510,418,
-361,334,327,328,323,302,267,225,176,118,53,-6,-50,-78,-99,-123,-151,-176,-196,-218,-250,
--285,-303,-283,-231,-180,-162,-180,-212,-238,-257,-274,-288,-289,-282,-282,-302,-326,-319,-260,-167,-82,
--32,-10,8,26,22,0,8,92,227,334,365,355,362,378,333,205,64,-7,-25,-80,-224,
--404,-531,-581,-602,-635,-669,-678,-666,-659,-666,-670,-662,-653,-653,-651,-633,-602,-578,-567,-557,-536,
--506,-480,-459,-431,-384,-333,-306,-331,-402,-489,-557,-591,-598,-592,-585,-581,-585,-594,-595,-574,-534,
--500,-495,-517,-545,-564,-574,-586,-600,-609,-609,-607,-608,-610,-611,-619,-636,-656,-668,-672,-676,-686,
--701,-716,-734,-754,-775,-792,-809,-833,-862,-888,-910,-934,-966,-1002,-1032,-1056,-1084,-1122,-1167,-1214,-1263,
--1316,-1371,-1426,-1480,-1536,-1591,-1642,-1692,-1741,-1789,-1831,-1872,-1922,-1985,-2052,-2112,-2162,-2209,-2258,-2309,-2361,
--2415,-2472,-2530,-2587,-2644,-2700,-2749,-2791,-2832,-2881,-2937,-2994,-3046,-3091,-3128,-3157,-3184,-3215,-3257,-3304,-3349,
--3390,-3431,-3474,-3513,-3549,-3585,-3627,-3673,-3718,-3756,-3784,-3805,-3820,-3836,-3851,-3865,-3875,-3888,-3908,-3933,-3955,
--3975,-3997,-4019,-4031,-4025,-4008,-3994,-3983,-3969,-3961,-3984,-4063,-4180,-4288,-4351,-4372,-4385,-4414,-4455,-4486,-4498,
--4500,-4511,-4537,-4568,-4593,-4604,-4606,-4609,-4620,-4638,-4651,-4652,-4641,-4628,-4621,-4616,-4605,-4588,-4571,-4564,-4567,
--4579,-4597,-4617,-4638,-4659,-4681,-4704,-4719,-4719,-4705,-4688,-4673,-4652,-4621,-4581,-4542,-4507,-4471,-4432,-4394,-4356,
--4314,-4267,-4219,-4174,-4129,-4079,-4022,-3953,-3861,-3741,-3610,-3494,-3412,-3368,-3364,-3400,-3468,-3540,-3580,-3573,-3531,
--3466,-3386,-3297,-3213,-3152,-3121,-3111,-3109,-3107,-3103,-3099,-3098,-3097,-3090,-3068,-3034,-2991,-2941,-2885,-2826,-2772,
--2720,-2655,-2564,-2455,-2339,-2210,-2053,-1866,-1676,-1520,-1410,-1334,-1266,-1187,-1090,-986,-902,-857,-843,-830,-795,
--747,-712,-701,-705,-708,-701,-684,-651,-596,-520,-428,-330,-232,-145,-79,-34,2,50,123,219,326,
-420,479,497,488,471,456,449,450,462,484,511,542,577,611,641,669,714,792,898,1009,1096,
-1157,1205,1252,1300,1344,1384,1422,1455,1475,1481,1479,1479,1488,1513,1558,1624,1705,1785,1852,1909,1966,
-2040,2134,2242,2347,2438,2511,2571,2624,2675,2725,2776,2833,2900,2972,3033,3077,3107,3140,3183,3235,3292,
-3357,3437,3532,3631,3726,3814,3898,3978,4044,4085,4101,4101,4098,4099,4100,4091,4075,4065,4077,4115,4165,
-4212,4251,4287,4332,4386,4446,4509,4579,4659,4746,4833,4912,4980,5040,5093,5140,5177,5198,5206,5211,5230,
-5271,5322,5360,5372,5363,5350,5343,5337,5323,5304,5292,5298,5319,5349,5375,5388,5381,5354,5318,5288,5268,
-5242,5190,5116,5055,5041,5075,5114,5122,5106,5107,5147,5196,5212,5189,5166,5167,5167,5127,5066,5063,5174,
-5350,5466,5444,5325,5221,5207,5265,5328,5360,5370,5378,5387,5395,5405,5418,5420,5394,5344,5294,5266,5254,
-5244,5232,5231,5261,5346,5499,5710,5932,6099,6165,6131,6032,5918,5829,5794,5815,5847,5819,5679,5439,5177,
-4999,4981,5136,5402,5681,5896,6020,6076,6096,6098,6085,6061,6038,6021,6007,5983,5941,5884,5828,5789,5763,
-5728,5664,5578,5498,5446,5419,5399,5375,5349,5322,5287,5236,5176,5121,5085,5064,5042,5012,4985,4980,5006,
-5047,5085,5118,5158,5209,5250,5260,5240,5215,5207,5223,5256,5291,5310,5298,5267,5241,5215,5118,4855,4386,
-3780,3186,2753,2558,2583,2733,2893,2986,3014,3020,3029,3026,2988,2923,2861,2810,2758,2690,2618,2556,2502,
-2440,2365,2288,2222,2165,2111,2054,1995,1930,1860,1789,1721,1658,1599,1544,1494,1448,1404,1364,1331,1303,
-1278,1255,1240,1236,1232,1216,1188,1159,1139,1126,1113,1101,1092,1084,1072,1050,1023,995,966,933,895,
-856,821,796,779,756,706,629,545,486,458,447,429,404,381,371,367,356,333,298,253,205,
-165,139,122,99,61,15,-23,-40,-38,-38,-64,-118,-181,-225,-246,-261,-287,-320,-348,-371,-401,
--444,-485,-514,-537,-565,-597,-616,-616,-611,-619,-638,-657,-674,-690,-706,-716,-723,-741,-774,-813,-841,
--853,-858,-863,-869,-879,-900,-930,-953,-952,-935,-924,-939,-976,-1014,-1031,-1018,-984,-951,-946,-974,-1016,
--1046,-1058,-1065,-1078,-1090,-1091,-1081,-1072,-1071,-1074,-1078,-1085,-1093,-1099,-1101,-1103,-1115,-1134,-1149,-1151,-1145,
--1140,-1139,-1139,-1136,-1134,-1132,-1132,-1130,-1128,-1127,-1125,-1121,-1115,-1111,-1111,-1110,-1108,-1105,-1104,-1103,-1101,
--1095,-1086,-1075,-1065,-1054,-1043,-1030,-1014,-999,-985,-974,-963,-949,-932,-914,-897,-878,-857,-835,-813,-791,
--769,-747,-727,-708,-691,-675,-659,-642,-622,-602,-584,-568,-552,-535,-520,-507,-494,-479,-462,-448,-436,
--425,-414,-403,-395,-387,-377,-368,-362,-357,-350,-340,-332,-327,-326,-324,-322,-323,-326,-327,-325,-322,
--321,-319,-315,-312,-310,-309,-308,-308,-311,-313,-310,-303,-301,-307,-315,-320,-320,-321,-324,-326,-324,
--320,-318,-318,-316,-314,-311,-308,-306,-307,-310,-312,-312,-310,-312,-317,-319,-316,-312,-310,-310,-310,
--309,-308,-308,-304,-299,-292,-285,-277,-270,-269,-272,-271,-264,-255,-250,-247,-240,-229,-219,-214,-209,
--200,-188,-176,-166,-156,-145,-135,-125,-113,-101,-92,-85,-77,-68,-61,-59,-57,-51,-43,-34,-23,
--9,3,12,18,27,41,56,69,79,90,105,122,139,152,160,169,183,201,215,224,240,
-268,296,311,316,333,367,403,426,452,505,574,622,630,625,646,698,742,740,703,682,713,
-783,841,854,840,842,876,916,936,947,979,1031,1075,1100,1132,1192,1260,1308,1342,1389,1456,1520,
-1569,1619,1673,1711,1723,1740,1793,1866,1918,1949,1989,2020,1950,1722,1432,1291,1459,1920,2506,3020,3330,
-3432,3440,3501,3683,3922,4119,4241,4325,4394,4423,4400,4357,4326,4295,4243,4200,4203,4217,4133,3888,3542,
-3212,2954,2749,2570,2434,2358,2322,2290,2247,2198,2141,2076,2027,2021,2051,2076,2067,2040,2018,1996,1948,
-1867,1774,1691,1623,1575,1554,1559,1559,1515,1410,1267,1124,1011,925,840,729,586,433,292,167,50,
--56,-136,-187,-229,-284,-347,-396,-422,-439,-466,-503,-539,-569,-594,-614,-622,-619,-615,-619,-633,-650,
--661,-660,-646,-629,-617,-603,-572,-511,-430,-353,-302,-283,-283,-285,-279,-273,-285,-320,-362,-388,-395,
--403,-428,-463,-484,-486,-491,-522,-576,-626,-637,-604,-559,-559,-635,-765,-889,-969,-1010,-1039,-1062,-1061,
--1032,-1002,-993,-997,-989,-964,-945,-947,-957,-952,-927,-900,-881,-870,-857,-840,-819,-798,-779,-761,-741,
--716,-688,-667,-654,-642,-624,-607,-600,-606,-614,-617,-619,-625,-632,-635,-634,-635,-639,-641,-641,-641,
--644,-644,-636,-626,-620,-617,-609,-595,-578,-561,-544,-524,-503,-486,-472,-457,-437,-411,-381,-348,-316,
--284,-252,-219,-183,-149,-117,-85,-52,-17,17,51,85,118,151,183,216,248,280,311,343,376,
-411,447,484,525,567,607,642,677,715,756,798,836,873,910,948,983,1014,1045,1078,1108,1129,
-1141,1155,1178,1203,1217,1216,1212,1217,1229,1238,1242,1245,1252,1260,1262,1261,1263,1266,1270,1274,1284,
-1299,1312,1322,1330,1340,1352,1364,1377,1396,1417,1433,1444,1460,1485,1511,1528,1536,1546,1565,1590,1616,
-1641,1666,1687,1700,1709,1718,1733,1745,1766,1790,1816,1844,1873,1900,1925,1952,1984,2018,2050,2078,2103,
-2130,2157,2182,2200,2219,2252,2308,2378,2438,2471,2481,2484,2493,2500,2495,2475,2444,2404,2355,2303,2263,
-2243,2237,2233,2227,2224,2232,2246,2260,2274,2294,2321,2349,2379,2425,2497,2585,2662,2706,2725,2744,2777,
-2817,2847,2869,2898,2940,2983,3010,3020,3032,3057,3088,3110,3112,3095,3052,2978,2879,2779,2705,2666,2650,
-2635,2605,2549,2472,2385,2302,2224,2149,2079,2026,1998,1984,1974,1967,1965,1965,1952,1914,1861,1809,1766,
-1732,1706,1687,1667,1642,1615,1596,1584,1564,1527,1481,1438,1400,1361,1313,1261,1212,1166,1123,1088,1073,
-1079,1093,1099,1087,1062,1035,1008,967,891,774,641,524,445,402,383,376,375,371,359,341,317,
-282,226,155,89,43,16,-6,-36,-70,-102,-129,-159,-193,-224,-233,-213,-174,-145,-141,-154,-162,
--161,-165,-184,-205,-209,-197,-195,-222,-262,-271,-220,-125,-28,42,91,130,153,145,124,143,234,
-360,448,463,438,422,403,338,222,110,46,0,-95,-251,-403,-489,-517,-536,-571,-598,-601,-594,
--602,-618,-623,-611,-599,-595,-586,-558,-522,-498,-493,-491,-475,-447,-420,-404,-397,-393,-387,-385,-395,
--423,-459,-488,-500,-503,-508,-520,-533,-541,-543,-535,-513,-483,-460,-461,-483,-509,-530,-545,-557,-565,
--564,-560,-557,-554,-548,-543,-552,-573,-596,-606,-608,-615,-630,-646,-659,-675,-697,-721,-742,-762,-787,
--812,-831,-846,-868,-901,-937,-964,-986,-1014,-1050,-1092,-1137,-1186,-1240,-1294,-1345,-1396,-1451,-1507,-1558,-1605,
--1652,-1700,-1746,-1790,-1842,-1904,-1971,-2031,-2081,-2126,-2171,-2218,-2269,-2327,-2388,-2447,-2502,-2554,-2606,-2654,-2699,
--2746,-2801,-2861,-2918,-2967,-3006,-3039,-3067,-3096,-3133,-3178,-3226,-3268,-3308,-3349,-3389,-3427,-3463,-3502,-3545,-3590,
--3630,-3665,-3694,-3715,-3730,-3746,-3766,-3790,-3813,-3835,-3858,-3881,-3900,-3917,-3936,-3956,-3965,-3958,-3942,-3927,-3913,
--3896,-3887,-3919,-4009,-4133,-4240,-4295,-4311,-4325,-4361,-4411,-4451,-4468,-4472,-4479,-4500,-4528,-4552,-4563,-4566,-4568,
--4578,-4595,-4608,-4609,-4600,-4590,-4586,-4585,-4578,-4563,-4549,-4545,-4554,-4569,-4586,-4604,-4623,-4643,-4666,-4686,-4697,
--4694,-4679,-4661,-4645,-4625,-4595,-4558,-4519,-4480,-4440,-4402,-4367,-4333,-4293,-4246,-4201,-4165,-4131,-4089,-4033,-3965,
--3886,-3793,-3686,-3577,-3481,-3412,-3384,-3404,-3464,-3537,-3588,-3595,-3553,-3474,-3375,-3276,-3200,-3154,-3133,-3126,-3125,
--3127,-3129,-3129,-3129,-3130,-3126,-3111,-3082,-3043,-2996,-2942,-2885,-2830,-2769,-2686,-2573,-2442,-2311,-2179,-2025,-1843,
--1658,-1509,-1412,-1346,-1283,-1206,-1118,-1029,-949,-888,-845,-811,-777,-746,-725,-717,-714,-706,-689,-666,-635,
--593,-541,-478,-403,-319,-235,-164,-111,-69,-21,45,135,238,333,401,434,439,427,409,394,389,
-397,412,431,454,484,521,555,582,620,688,792,910,1010,1077,1119,1150,1182,1216,1252,1285,1314,
-1333,1344,1349,1356,1376,1416,1477,1552,1626,1688,1736,1782,1840,1917,2013,2118,2226,2328,2418,2493,2552,
-2601,2645,2692,2750,2818,2888,2948,2990,3023,3062,3114,3172,3229,3286,3356,3446,3546,3639,3718,3791,3868,
-3943,3998,4022,4022,4018,4022,4025,4016,3995,3982,3994,4029,4070,4107,4142,4186,4242,4304,4370,4439,4512,
-4589,4666,4742,4819,4896,4968,5032,5084,5122,5145,5152,5153,5163,5196,5245,5290,5312,5309,5296,5284,5274,
-5261,5244,5234,5238,5255,5278,5299,5310,5303,5277,5243,5220,5211,5197,5156,5088,5027,5012,5044,5082,5087,
-5059,5037,5048,5075,5085,5071,5058,5063,5061,5027,4984,5004,5128,5299,5396,5351,5217,5112,5112,5188,5269,
-5314,5332,5341,5341,5335,5335,5349,5361,5345,5302,5257,5233,5227,5222,5216,5218,5234,5266,5333,5460,5652,
-5867,6035,6107,6082,5995,5891,5807,5770,5778,5794,5753,5601,5342,5062,4882,4885,5062,5326,5578,5764,5879,
-5939,5958,5945,5913,5872,5827,5780,5728,5672,5613,5557,5512,5481,5453,5420,5387,5370,5376,5393,5397,5376,
-5337,5291,5242,5192,5147,5114,5093,5074,5045,5010,4985,4988,5015,5050,5078,5109,5157,5216,5257,5261,5237,
-5212,5207,5220,5247,5276,5295,5288,5261,5229,5171,5004,4636,4061,3404,2857,2559,2520,2651,2827,2959,3021,
-3039,3046,3048,3031,2983,2919,2860,2807,2745,2671,2598,2540,2490,2431,2360,2286,2219,2159,2102,2043,1980,
-1915,1850,1789,1731,1671,1609,1552,1504,1460,1413,1367,1330,1305,1281,1252,1228,1219,1220,1215,1195,1168,
-1144,1122,1097,1072,1057,1055,1053,1040,1011,974,937,903,871,837,804,776,752,724,676,608,537,
-485,457,438,412,379,350,332,321,312,297,273,234,187,151,138,142,138,102,36,-27,-56,
--43,-19,-28,-88,-173,-238,-266,-280,-307,-349,-386,-410,-433,-468,-508,-539,-560,-582,-608,-625,-630,
--630,-639,-658,-678,-696,-713,-728,-737,-743,-759,-790,-825,-849,-858,-860,-861,-861,-864,-879,-910,-942,
--959,-963,-969,-988,-1017,-1044,-1056,-1046,-1020,-994,-992,-1017,-1051,-1071,-1074,-1078,-1095,-1115,-1121,-1113,-1109,
--1118,-1134,-1142,-1141,-1136,-1130,-1123,-1116,-1118,-1129,-1143,-1148,-1144,-1137,-1136,-1138,-1140,-1140,-1139,-1139,-1140,
--1138,-1135,-1129,-1121,-1113,-1108,-1107,-1106,-1103,-1098,-1093,-1090,-1086,-1079,-1068,-1056,-1046,-1039,-1033,-1023,-1006,
--988,-972,-961,-951,-938,-922,-906,-891,-876,-859,-839,-818,-796,-774,-752,-732,-715,-698,-681,-665,-649,
--631,-611,-592,-574,-558,-543,-528,-515,-502,-488,-474,-461,-449,-437,-425,-414,-406,-399,-390,-382,-375,
--370,-362,-351,-342,-336,-335,-334,-334,-336,-338,-339,-338,-335,-332,-331,-330,-328,-326,-323,-319,-318,
--321,-323,-322,-319,-318,-322,-325,-326,-325,-328,-332,-333,-331,-327,-326,-325,-324,-320,-314,-310,-308,
--310,-314,-316,-313,-310,-313,-317,-318,-312,-306,-302,-301,-300,-301,-303,-305,-301,-293,-283,-275,-266,
--260,-258,-258,-257,-251,-243,-238,-234,-228,-219,-211,-204,-195,-183,-170,-158,-148,-137,-127,-117,-105,
--90,-78,-72,-69,-62,-51,-41,-36,-34,-32,-28,-22,-13,2,19,31,37,44,56,70,84,
-96,109,123,138,152,164,175,185,202,222,240,253,268,289,309,322,334,357,391,423,447,
-480,537,598,627,616,603,627,682,725,726,700,693,729,790,834,841,829,835,867,905,928,
-944,974,1019,1059,1089,1130,1193,1259,1308,1348,1402,1470,1532,1578,1624,1672,1706,1718,1740,1798,1875,
-1928,1956,1986,1998,1910,1674,1387,1257,1442,1930,2552,3091,3400,3476,3452,3486,3641,3849,4021,4144,4259,
-4371,4430,4416,4370,4338,4311,4266,4231,4245,4259,4148,3845,3435,3067,2817,2647,2510,2408,2361,2349,2331,
-2288,2232,2171,2108,2055,2029,2027,2023,2001,1974,1960,1950,1918,1857,1783,1714,1652,1600,1569,1561,1553,
-1505,1400,1253,1106,993,914,840,739,602,451,309,181,60,-45,-121,-162,-194,-241,-301,-352,-383,
--406,-435,-471,-507,-537,-563,-583,-594,-598,-597,-599,-606,-620,-635,-641,-631,-610,-591,-575,-549,-496,
--418,-335,-273,-243,-243,-255,-261,-263,-278,-322,-383,-430,-448,-448,-455,-472,-488,-506,-539,-593,-647,
--665,-634,-577,-539,-562,-653,-783,-902,-980,-1023,-1050,-1063,-1047,-1003,-957,-936,-939,-944,-940,-933,-932,
--929,-915,-893,-874,-863,-854,-843,-831,-819,-804,-786,-767,-747,-725,-700,-676,-655,-635,-618,-606,-605,
--612,-618,-621,-624,-629,-634,-634,-634,-635,-639,-639,-637,-635,-636,-636,-631,-622,-614,-606,-594,-578,
--562,-545,-526,-504,-482,-462,-444,-427,-408,-386,-359,-325,-291,-258,-227,-194,-159,-125,-95,-63,-28,
-7,42,74,106,139,171,203,236,270,304,337,368,401,436,470,506,543,582,621,658,694,
-734,778,820,859,894,927,962,996,1027,1052,1074,1094,1114,1133,1153,1177,1199,1214,1218,1218,1224,
-1236,1248,1254,1256,1261,1267,1269,1268,1268,1273,1280,1287,1296,1305,1313,1319,1325,1336,1350,1366,1383,
-1405,1428,1446,1461,1479,1506,1534,1552,1562,1572,1591,1616,1640,1662,1682,1700,1712,1719,1729,1745,1766,
-1790,1817,1846,1876,1906,1932,1957,1985,2018,2050,2080,2107,2132,2158,2186,2216,2248,2280,2318,2368,2427,
-2480,2509,2515,2519,2534,2544,2522,2465,2399,2350,2320,2290,2255,2226,2215,2217,2222,2225,2230,2242,2255,
-2268,2288,2314,2342,2370,2411,2482,2580,2674,2734,2758,2773,2801,2840,2872,2893,2917,2957,3007,3049,3079,
-3108,3142,3171,3182,3170,3139,3087,3008,2905,2797,2711,2659,2633,2612,2579,2525,2456,2383,2315,2252,2189,
-2130,2084,2055,2036,2019,2004,1997,1995,1981,1946,1896,1846,1805,1777,1758,1745,1728,1701,1668,1642,1624,
-1604,1569,1524,1479,1444,1413,1376,1330,1280,1231,1189,1162,1157,1170,1185,1182,1153,1110,1073,1048,1013,
-940,820,682,566,494,457,439,428,424,423,421,416,406,379,327,254,183,131,99,73,43,
-7,-28,-62,-94,-124,-143,-144,-127,-107,-103,-116,-131,-127,-108,-99,-113,-136,-141,-127,-124,-155,
--205,-231,-200,-118,-13,88,177,240,264,249,231,260,352,464,534,539,505,460,401,317,222,
-150,100,26,-106,-266,-384,-429,-437,-457,-494,-521,-526,-530,-548,-568,-568,-553,-539,-532,-515,-482,
--445,-425,-421,-420,-409,-389,-368,-353,-350,-359,-373,-382,-387,-394,-404,-410,-409,-410,-426,-453,-477,
--488,-487,-480,-468,-451,-437,-438,-454,-476,-493,-503,-507,-505,-501,-498,-499,-495,-485,-480,-491,-515,
--536,-542,-543,-554,-572,-588,-600,-617,-644,-672,-694,-714,-737,-759,-774,-787,-809,-842,-876,-899,-917,
--944,-979,-1018,-1060,-1108,-1162,-1216,-1265,-1314,-1369,-1425,-1475,-1519,-1563,-1611,-1658,-1706,-1761,-1826,-1891,-1949,
--1996,-2039,-2083,-2129,-2181,-2242,-2305,-2364,-2415,-2461,-2510,-2559,-2609,-2662,-2721,-2784,-2840,-2884,-2919,-2948,-2977,
--3011,-3052,-3099,-3145,-3186,-3227,-3269,-3310,-3347,-3383,-3423,-3465,-3505,-3539,-3571,-3602,-3628,-3646,-3663,-3688,-3721,
--3757,-3787,-3810,-3828,-3842,-3857,-3874,-3892,-3901,-3897,-3885,-3873,-3857,-3836,-3830,-3870,-3967,-4090,-4186,-4229,-4240,
--4259,-4305,-4363,-4408,-4426,-4429,-4436,-4456,-4483,-4506,-4519,-4522,-4526,-4537,-4554,-4566,-4568,-4560,-4552,-4549,-4550,
--4548,-4538,-4529,-4527,-4536,-4551,-4567,-4585,-4605,-4627,-4647,-4662,-4667,-4660,-4646,-4630,-4613,-4592,-4566,-4534,-4498,
--4455,-4409,-4366,-4333,-4307,-4276,-4235,-4192,-4155,-4120,-4075,-4014,-3947,-3883,-3821,-3752,-3672,-3587,-3516,-3477,-3478,
--3513,-3564,-3605,-3613,-3574,-3491,-3383,-3280,-3210,-3174,-3159,-3150,-3143,-3140,-3141,-3146,-3154,-3164,-3166,-3151,-3119,
--3079,-3039,-2997,-2948,-2888,-2810,-2701,-2563,-2414,-2278,-2152,-2012,-1846,-1676,-1540,-1448,-1380,-1310,-1231,-1152,-1079,
--1008,-938,-875,-828,-798,-780,-768,-756,-737,-707,-668,-625,-586,-553,-525,-497,-458,-401,-327,-249,-177,
--120,-70,-15,57,145,234,307,352,370,367,352,337,331,337,351,365,381,407,442,478,507,
-540,599,694,811,918,991,1029,1049,1065,1086,1112,1143,1177,1209,1238,1263,1290,1326,1380,1450,1527,
-1597,1652,1695,1738,1795,1868,1954,2047,2144,2242,2336,2419,2484,2533,2573,2616,2671,2739,2807,2863,2902,
-2936,2983,3045,3111,3167,3217,3279,3361,3456,3541,3610,3672,3745,3828,3900,3937,3943,3936,3936,3939,3932,
-3915,3903,3909,3932,3960,3987,4023,4075,4140,4211,4283,4358,4437,4516,4590,4662,4737,4816,4895,4969,5031,
-5075,5100,5105,5101,5103,5125,5166,5211,5241,5251,5244,5234,5223,5209,5193,5183,5187,5201,5217,5227,5229,
-5222,5201,5172,5149,5143,5144,5124,5070,5003,4961,4964,4989,4998,4978,4951,4943,4958,4974,4978,4977,4979,
-4970,4940,4912,4942,5059,5211,5296,5256,5136,5046,5050,5128,5212,5265,5288,5299,5299,5292,5291,5301,5305,
-5284,5244,5212,5204,5206,5199,5190,5198,5224,5251,5274,5328,5451,5634,5821,5951,6001,5986,5929,5851,5777,
-5738,5742,5749,5683,5495,5219,4963,4833,4867,5021,5219,5406,5554,5652,5694,5686,5644,5580,5500,5416,5345,
-5300,5279,5268,5257,5250,5255,5273,5303,5341,5379,5402,5396,5359,5305,5250,5201,5161,5131,5108,5090,5068,
-5041,5015,5003,5011,5032,5051,5071,5104,5160,5221,5255,5248,5219,5200,5204,5223,5242,5259,5269,5266,5248,
-5205,5092,4824,4342,3696,3058,2621,2474,2561,2743,2906,3003,3047,3065,3073,3064,3030,2975,2915,2857,2798,
-2729,2653,2585,2530,2482,2426,2360,2290,2220,2151,2085,2022,1962,1901,1841,1785,1732,1674,1614,1559,1516,
-1475,1427,1378,1339,1315,1292,1258,1224,1206,1206,1207,1196,1176,1153,1127,1094,1058,1032,1023,1022,1015,
-993,960,923,886,851,816,781,747,714,676,630,575,523,484,458,435,404,367,333,305,285,
-272,262,245,214,172,139,131,145,151,119,46,-33,-73,-57,-16,-6,-60,-157,-245,-293,-314,
--340,-380,-417,-439,-457,-485,-523,-556,-578,-596,-613,-628,-639,-652,-671,-694,-714,-732,-750,-767,-776,
--780,-789,-810,-835,-851,-857,-860,-862,-860,-858,-866,-892,-928,-961,-985,-1004,-1022,-1039,-1053,-1063,-1067,
--1061,-1053,-1056,-1077,-1102,-1109,-1098,-1089,-1099,-1119,-1131,-1132,-1139,-1161,-1184,-1191,-1181,-1170,-1167,-1165,-1157,
--1145,-1139,-1142,-1145,-1142,-1136,-1134,-1137,-1141,-1142,-1142,-1144,-1146,-1146,-1141,-1132,-1123,-1116,-1112,-1109,-1106,
--1101,-1095,-1088,-1082,-1076,-1066,-1055,-1043,-1034,-1029,-1026,-1018,-1003,-984,-967,-953,-942,-929,-915,-900,-885,
--871,-855,-837,-819,-798,-778,-759,-742,-725,-707,-687,-669,-653,-637,-619,-599,-580,-564,-550,-536,-522,
--508,-494,-482,-470,-460,-448,-436,-426,-417,-410,-402,-393,-386,-380,-372,-361,-349,-343,-343,-345,-348,
--350,-352,-353,-351,-346,-341,-339,-342,-344,-344,-339,-334,-332,-332,-333,-332,-333,-336,-340,-341,-338,
--336,-339,-342,-340,-337,-334,-334,-336,-334,-330,-323,-316,-312,-314,-319,-321,-317,-314,-315,-317,-315,
--308,-301,-297,-295,-294,-296,-301,-302,-296,-284,-272,-264,-257,-250,-245,-242,-241,-239,-234,-228,-221,
--212,-204,-197,-191,-180,-167,-154,-143,-132,-119,-109,-102,-90,-74,-58,-51,-50,-46,-36,-24,-16,
--12,-10,-10,-9,-2,12,31,44,51,59,70,83,96,109,124,139,153,166,180,192,202,
-216,235,256,274,289,304,321,339,360,389,419,442,464,498,548,591,604,595,600,641,696,
-725,717,698,704,742,788,818,824,823,833,860,892,919,946,981,1020,1054,1088,1138,1207,1274,
-1324,1365,1417,1480,1536,1581,1625,1672,1705,1723,1755,1821,1898,1949,1974,1995,1991,1886,1642,1362,1246,
-1452,1962,2598,3131,3416,3470,3441,3483,3628,3798,3924,4031,4173,4330,4424,4423,4385,4366,4353,4311,4267,
-4269,4270,4137,3795,3335,2935,2689,2555,2462,2390,2358,2355,2344,2307,2257,2205,2151,2097,2052,2023,1996,
-1964,1938,1929,1926,1905,1855,1788,1723,1664,1614,1578,1554,1528,1473,1374,1241,1103,991,911,840,747,
-617,468,324,192,70,-34,-107,-144,-169,-205,-254,-301,-336,-368,-406,-448,-485,-516,-541,-561,-574,
--580,-579,-573,-569,-576,-595,-612,-611,-593,-571,-552,-523,-469,-388,-302,-237,-209,-219,-245,-265,-271,
--280,-318,-382,-445,-482,-494,-498,-503,-514,-536,-580,-636,-670,-655,-601,-554,-554,-617,-727,-850,-953,
--1017,-1047,-1056,-1052,-1030,-991,-952,-933,-935,-942,-941,-929,-914,-897,-881,-870,-866,-862,-852,-836,-823,
--813,-799,-780,-760,-744,-730,-711,-686,-660,-638,-624,-617,-617,-620,-621,-621,-624,-630,-635,-636,-636,
--637,-638,-634,-628,-623,-624,-625,-622,-615,-606,-593,-579,-563,-548,-530,-509,-486,-463,-442,-418,-394,
--373,-352,-327,-295,-262,-231,-202,-169,-134,-101,-73,-43,-6,32,67,98,128,160,192,225,260,
-297,335,368,400,432,466,499,532,566,602,638,674,710,750,793,835,871,901,929,961,998,
-1032,1057,1075,1097,1126,1158,1183,1201,1215,1225,1230,1232,1237,1247,1258,1263,1265,1267,1271,1272,1271,
-1272,1279,1289,1296,1301,1306,1312,1318,1324,1335,1351,1370,1391,1414,1438,1460,1479,1500,1526,1555,1578,
-1592,1607,1626,1649,1669,1686,1702,1717,1729,1737,1748,1766,1793,1817,1843,1870,1899,1929,1957,1986,2018,
-2053,2085,2113,2140,2165,2190,2216,2250,2293,2338,2381,2423,2471,2516,2544,2550,2555,2567,2565,2517,2427,
-2345,2316,2325,2325,2285,2230,2198,2202,2220,2231,2236,2244,2256,2270,2289,2315,2345,2374,2413,2481,2581,
-2686,2762,2800,2822,2849,2882,2905,2919,2939,2980,3034,3084,3125,3165,3208,3239,3244,3219,3175,3119,3043,
-2945,2838,2743,2677,2636,2605,2569,2522,2465,2405,2349,2296,2245,2197,2157,2127,2102,2078,2057,2044,2034,
-2015,1981,1935,1888,1850,1823,1806,1796,1784,1760,1726,1693,1665,1638,1602,1556,1512,1480,1458,1437,1411,
-1376,1341,1314,1303,1304,1310,1304,1276,1226,1169,1126,1102,1074,1006,887,747,631,559,521,498,483,
-480,487,494,497,490,468,422,353,277,212,167,136,108,77,42,6,-24,-44,-49,-41,-27,
--19,-31,-57,-81,-82,-64,-50,-56,-73,-78,-68,-68,-99,-153,-194,-190,-132,-28,101,225,309,
-332,312,299,337,425,523,586,598,565,493,392,287,217,186,151,56,-100,-256,-343,-359,-359,
--385,-429,-460,-473,-485,-505,-517,-508,-489,-476,-467,-445,-407,-372,-354,-350,-346,-337,-325,-312,-302,
--301,-312,-330,-340,-342,-340,-341,-340,-336,-338,-358,-390,-418,-432,-435,-435,-431,-420,-408,-408,-422,
--440,-449,-449,-443,-438,-436,-439,-441,-435,-423,-417,-428,-449,-463,-466,-469,-485,-508,-527,-542,-563,
--593,-620,-640,-658,-682,-706,-721,-734,-756,-787,-816,-834,-852,-879,-914,-950,-987,-1031,-1084,-1137,-1186,
--1236,-1291,-1345,-1391,-1432,-1476,-1524,-1574,-1628,-1688,-1753,-1814,-1862,-1902,-1942,-1987,-2037,-2093,-2154,-2218,-2274,
--2321,-2366,-2414,-2466,-2520,-2578,-2640,-2701,-2754,-2795,-2826,-2854,-2886,-2924,-2971,-3019,-3063,-3103,-3144,-3190,-3233,
--3270,-3304,-3342,-3382,-3416,-3446,-3477,-3513,-3545,-3567,-3586,-3614,-3654,-3697,-3732,-3754,-3767,-3778,-3791,-3808,-3825,
--3835,-3837,-3833,-3825,-3808,-3786,-3783,-3830,-3929,-4043,-4124,-4156,-4167,-4193,-4248,-4311,-4356,-4374,-4379,-4388,-4410,
--4437,-4459,-4472,-4478,-4487,-4501,-4517,-4528,-4530,-4524,-4516,-4513,-4515,-4517,-4514,-4509,-4506,-4511,-4523,-4540,-4560,
--4584,-4608,-4626,-4634,-4633,-4625,-4614,-4600,-4582,-4560,-4534,-4506,-4472,-4429,-4379,-4333,-4304,-4287,-4267,-4232,-4187,
--4141,-4098,-4049,-3989,-3925,-3867,-3819,-3775,-3727,-3676,-3632,-3605,-3599,-3607,-3620,-3629,-3623,-3588,-3517,-3418,-3320,
--3249,-3209,-3188,-3170,-3153,-3141,-3139,-3148,-3168,-3192,-3203,-3189,-3152,-3110,-3075,-3042,-2994,-2923,-2823,-2693,-2541,
--2388,-2255,-2137,-2011,-1864,-1712,-1586,-1496,-1422,-1344,-1262,-1191,-1129,-1065,-990,-916,-862,-836,-827,-820,-802,
--766,-710,-644,-583,-539,-517,-512,-511,-501,-469,-406,-320,-231,-159,-109,-68,-18,47,123,191,240,
-266,273,268,259,259,272,293,314,331,352,379,407,432,462,516,604,714,817,889,926,940,
-949,963,986,1019,1062,1112,1162,1210,1256,1303,1355,1412,1473,1536,1599,1661,1724,1792,1866,1945,2025,
-2105,2185,2267,2344,2409,2459,2499,2540,2595,2663,2729,2779,2813,2846,2897,2965,3035,3091,3137,3192,3267,
-3353,3431,3494,3552,3622,3707,3786,3836,3851,3845,3838,3838,3835,3826,3818,3818,3828,3845,3868,3904,3959,
-4028,4103,4180,4259,4341,4427,4512,4595,4672,4745,4818,4893,4964,5019,5047,5051,5043,5040,5053,5083,5123,
-5159,5181,5190,5190,5182,5165,5142,5129,5134,5152,5164,5161,5149,5138,5123,5101,5076,5069,5082,5091,5059,
-4987,4911,4874,4880,4898,4896,4878,4867,4881,4910,4930,4933,4921,4899,4868,4848,4875,4969,5097,5186,5184,
-5110,5040,5033,5086,5156,5209,5238,5251,5253,5252,5261,5275,5273,5241,5196,5173,5183,5199,5195,5179,5182,
-5214,5251,5273,5300,5370,5494,5641,5764,5844,5885,5894,5866,5806,5743,5713,5713,5689,5582,5381,5147,4959,
-4870,4877,4953,5066,5186,5279,5325,5323,5288,5232,5159,5080,5027,5022,5061,5113,5153,5181,5215,5266,5325,
-5374,5400,5396,5367,5320,5268,5219,5179,5148,5122,5099,5074,5050,5031,5022,5024,5034,5044,5052,5067,5105,
-5165,5223,5249,5233,5201,5187,5201,5226,5239,5238,5234,5235,5226,5164,4971,4575,3979,3304,2749,2469,2477,
-2652,2847,2978,3045,3079,3099,3101,3077,3030,2973,2915,2856,2789,2713,2637,2572,2517,2464,2407,2346,2281,
-2210,2135,2064,2002,1947,1889,1830,1775,1723,1670,1615,1565,1524,1486,1442,1395,1356,1328,1300,1262,1223,
-1199,1193,1193,1188,1174,1157,1132,1096,1056,1023,1002,991,979,960,932,897,858,821,786,752,716,
-676,632,588,545,508,478,453,427,395,361,327,297,272,254,242,229,203,168,136,123,128,
-129,98,31,-46,-95,-88,-45,-19,-55,-145,-242,-304,-329,-343,-367,-398,-425,-451,-482,-519,-554,
--584,-608,-627,-642,-656,-674,-699,-723,-741,-754,-770,-785,-794,-798,-804,-818,-836,-849,-856,-863,-870,
--872,-871,-876,-894,-922,-952,-982,-1008,-1027,-1038,-1046,-1058,-1073,-1083,-1086,-1093,-1110,-1129,-1130,-1111,-1093,
--1095,-1114,-1134,-1148,-1164,-1185,-1195,-1182,-1154,-1140,-1154,-1180,-1193,-1185,-1170,-1161,-1157,-1152,-1145,-1139,-1139,
--1140,-1139,-1139,-1142,-1146,-1146,-1140,-1130,-1122,-1117,-1113,-1108,-1103,-1098,-1092,-1086,-1078,-1068,-1058,-1047,-1037,
--1031,-1027,-1023,-1017,-1006,-991,-975,-960,-947,-934,-919,-904,-887,-869,-852,-835,-819,-802,-785,-770,-757,
--742,-721,-698,-677,-660,-646,-629,-610,-592,-577,-563,-549,-534,-518,-504,-492,-481,-471,-461,-450,-439,
--430,-422,-414,-405,-397,-390,-382,-372,-361,-356,-358,-363,-367,-368,-368,-368,-366,-360,-353,-350,-354,
--359,-360,-356,-351,-350,-349,-345,-342,-343,-349,-355,-354,-351,-350,-353,-353,-349,-344,-342,-343,-345,
--343,-339,-331,-323,-318,-318,-321,-322,-319,-315,-314,-314,-312,-306,-300,-296,-292,-289,-291,-294,-293,
--284,-269,-256,-249,-243,-236,-228,-224,-224,-224,-223,-216,-205,-193,-185,-181,-174,-164,-152,-142,-133,
--119,-104,-95,-92,-84,-68,-48,-36,-31,-27,-19,-9,0,7,12,13,11,15,27,43,54,
-62,73,86,98,109,121,136,152,166,179,194,209,219,227,240,259,277,292,306,325,350,
-377,404,427,447,470,502,540,569,580,589,622,674,716,722,706,701,726,764,792,804,809,
-820,838,860,884,914,953,995,1032,1060,1094,1150,1225,1297,1349,1389,1435,1488,1538,1583,1628,1674,
-1711,1740,1785,1856,1929,1974,1995,2010,1992,1869,1617,1342,1247,1478,2006,2640,3144,3391,3429,3421,3495,
-3645,3778,3855,3939,4097,4285,4400,4412,4391,4399,4409,4369,4307,4285,4270,4124,3758,3265,2840,2596,2494,
-2440,2392,2362,2352,2337,2305,2265,2229,2191,2143,2093,2050,2012,1975,1947,1932,1923,1899,1850,1785,1722,
-1668,1623,1583,1542,1492,1426,1337,1226,1106,997,912,837,746,622,475,329,196,75,-26,-97,-137,
--161,-189,-222,-254,-283,-318,-364,-413,-457,-493,-521,-540,-550,-552,-547,-535,-524,-526,-546,-569,-576,
--563,-546,-528,-499,-441,-358,-275,-217,-199,-218,-254,-282,-290,-292,-313,-363,-426,-479,-513,-533,-541,
--544,-556,-587,-623,-632,-604,-567,-570,-633,-740,-855,-955,-1028,-1068,-1077,-1063,-1040,-1012,-985,-963,-954,
--955,-956,-947,-926,-900,-875,-858,-851,-848,-841,-824,-805,-792,-784,-774,-760,-746,-738,-730,-715,-690,
--664,-644,-634,-631,-631,-630,-627,-626,-628,-632,-635,-634,-632,-631,-629,-622,-615,-610,-609,-608,-605,
--600,-591,-578,-562,-545,-528,-508,-484,-460,-440,-420,-394,-364,-336,-312,-287,-257,-227,-200,-172,-140,
--105,-74,-48,-19,17,56,92,122,154,187,221,254,289,328,365,397,426,458,491,524,555,
-588,622,656,688,721,758,801,842,877,904,930,963,1004,1043,1072,1092,1117,1154,1192,1219,1230,
-1235,1241,1246,1247,1248,1254,1263,1268,1267,1265,1267,1268,1268,1271,1280,1292,1299,1303,1308,1318,1329,
-1338,1349,1365,1384,1404,1425,1448,1472,1493,1514,1539,1568,1594,1614,1632,1652,1673,1691,1706,1721,1738,
-1751,1762,1775,1793,1814,1837,1861,1886,1914,1945,1976,2009,2046,2082,2114,2142,2169,2197,2222,2248,2283,
-2334,2388,2433,2469,2509,2550,2578,2585,2583,2581,2558,2485,2379,2308,2318,2378,2404,2352,2258,2195,2191,
-2217,2236,2242,2248,2262,2278,2299,2328,2364,2400,2439,2500,2591,2694,2780,2836,2874,2908,2934,2945,2947,
-2962,3001,3053,3098,3135,3178,3229,3268,3272,3240,3189,3133,3066,2979,2875,2776,2700,2650,2614,2579,2540,
-2496,2448,2399,2351,2308,2271,2240,2211,2182,2153,2129,2111,2092,2066,2029,1986,1943,1903,1868,1845,1833,
-1825,1810,1783,1747,1709,1671,1631,1589,1550,1522,1510,1508,1506,1497,1484,1478,1478,1476,1454,1407,1337,
-1260,1193,1152,1137,1119,1063,954,820,706,633,590,559,539,539,556,574,581,573,554,516,453,
-370,288,225,188,166,142,111,76,51,42,48,60,70,68,50,17,-15,-28,-20,-7,-5,
--14,-19,-17,-22,-50,-100,-150,-172,-142,-48,94,240,333,354,337,338,388,471,555,616,644,
-621,533,401,285,235,235,210,101,-66,-213,-281,-288,-296,-334,-385,-421,-441,-457,-469,-464,-441,
--419,-409,-401,-377,-340,-308,-292,-286,-278,-267,-256,-248,-243,-247,-262,-278,-283,-275,-266,-266,-270,
--274,-282,-303,-334,-363,-380,-389,-392,-388,-374,-363,-367,-384,-397,-396,-385,-376,-376,-382,-388,-388,
--380,-368,-363,-371,-385,-392,-393,-400,-420,-446,-467,-485,-510,-539,-563,-581,-601,-628,-653,-668,-680,
--700,-728,-752,-769,-787,-816,-850,-883,-916,-956,-1006,-1058,-1108,-1160,-1215,-1264,-1305,-1344,-1389,-1443,-1499,
--1558,-1621,-1683,-1734,-1770,-1800,-1837,-1887,-1944,-2003,-2065,-2125,-2178,-2224,-2269,-2319,-2375,-2433,-2494,-2556,-2615,
--2662,-2698,-2727,-2758,-2794,-2840,-2890,-2940,-2982,-3019,-3060,-3108,-3153,-3190,-3221,-3255,-3291,-3323,-3352,-3385,-3424,
--3461,-3489,-3511,-3542,-3585,-3630,-3665,-3686,-3699,-3711,-3725,-3741,-3757,-3769,-3776,-3779,-3773,-3757,-3738,-3743,-3796,
--3892,-3993,-4058,-4083,-4097,-4131,-4190,-4253,-4298,-4319,-4328,-4341,-4363,-4389,-4410,-4423,-4434,-4447,-4464,-4478,-4485,
--4485,-4482,-4477,-4476,-4479,-4483,-4486,-4485,-4483,-4486,-4496,-4513,-4536,-4561,-4583,-4598,-4604,-4601,-4595,-4587,-4575,
--4557,-4532,-4504,-4475,-4442,-4400,-4352,-4310,-4284,-4272,-4257,-4226,-4178,-4125,-4077,-4034,-3986,-3931,-3873,-3820,-3777,
--3743,-3719,-3705,-3700,-3699,-3692,-3676,-3653,-3628,-3594,-3540,-3464,-3378,-3303,-3249,-3211,-3182,-3157,-3140,-3136,-3148,
--3176,-3210,-3231,-3222,-3188,-3147,-3113,-3074,-3013,-2919,-2797,-2657,-2510,-2367,-2242,-2131,-2016,-1885,-1751,-1638,-1551,
--1474,-1391,-1309,-1238,-1179,-1115,-1037,-959,-903,-878,-873,-869,-848,-799,-724,-640,-571,-532,-522,-528,-536,
--534,-512,-457,-373,-279,-202,-153,-124,-93,-48,4,55,95,122,138,144,148,160,186,222,260,
-289,310,326,339,356,385,438,521,618,707,769,802,817,830,847,874,912,963,1022,1082,1140,
-1191,1234,1265,1290,1322,1374,1453,1549,1648,1742,1832,1915,1989,2054,2113,2174,2237,2299,2352,2398,2446,
-2508,2581,2648,2694,2722,2752,2801,2867,2936,2992,3038,3090,3156,3234,3312,3382,3447,3515,3592,3667,3722,
-3746,3744,3734,3728,3727,3724,3717,3713,3717,3730,3754,3790,3842,3910,3987,4068,4147,4229,4319,4421,4522,
-4609,4676,4736,4805,4882,4946,4980,4984,4975,4972,4981,5002,5033,5068,5102,5130,5146,5146,5125,5093,5072,
-5079,5101,5111,5093,5064,5045,5038,5024,4999,4988,5008,5038,5029,4958,4862,4800,4799,4833,4853,4845,4833,
-4843,4873,4895,4892,4867,4837,4813,4804,4824,4888,4988,5081,5121,5098,5050,5025,5045,5096,5151,5190,5205,
-5203,5202,5219,5245,5251,5220,5170,5142,5154,5182,5194,5188,5188,5210,5243,5271,5297,5346,5429,5529,5620,
-5691,5749,5796,5819,5806,5762,5714,5682,5655,5596,5484,5327,5160,5016,4916,4871,4879,4923,4970,4995,4998,
-4994,4988,4973,4951,4947,4987,5067,5152,5213,5252,5288,5334,5378,5400,5391,5358,5317,5277,5238,5201,5166,
-5136,5110,5084,5057,5033,5020,5021,5029,5037,5042,5048,5066,5106,5164,5219,5243,5227,5195,5180,5197,5223,
-5231,5214,5197,5200,5197,5102,4810,4276,3584,2926,2505,2404,2547,2775,2955,3051,3095,3121,3134,3123,3086,
-3033,2978,2923,2860,2785,2704,2627,2561,2501,2441,2381,2324,2264,2196,2121,2050,1989,1936,1879,1818,1761,
-1712,1666,1617,1569,1528,1492,1454,1414,1374,1338,1301,1261,1225,1199,1186,1179,1173,1166,1153,1130,1095,
-1055,1020,994,973,951,927,896,861,822,785,753,721,686,645,602,562,525,491,462,435,407,
-378,348,318,292,268,250,236,221,198,167,136,112,98,83,54,2,-63,-115,-126,-99,-69,
--80,-144,-227,-287,-305,-302,-308,-338,-387,-439,-481,-513,-540,-572,-609,-643,-664,-675,-687,-704,-722,
--734,-742,-751,-762,-773,-782,-795,-814,-834,-851,-864,-875,-884,-891,-896,-903,-915,-930,-947,-968,-993,
--1015,-1028,-1038,-1052,-1070,-1085,-1093,-1100,-1115,-1131,-1132,-1112,-1091,-1089,-1110,-1139,-1164,-1182,-1189,-1173,-1130,
--1082,-1064,-1095,-1152,-1199,-1214,-1207,-1195,-1186,-1178,-1167,-1156,-1149,-1142,-1136,-1134,-1136,-1140,-1139,-1131,-1122,
--1116,-1112,-1107,-1099,-1092,-1089,-1089,-1086,-1078,-1067,-1054,-1043,-1035,-1031,-1027,-1021,-1014,-1006,-997,-986,-972,
--958,-944,-930,-913,-893,-872,-852,-836,-821,-806,-793,-782,-771,-757,-737,-714,-692,-675,-659,-643,-625,
--610,-596,-582,-567,-551,-535,-520,-506,-495,-484,-475,-465,-455,-446,-438,-429,-419,-409,-400,-394,-387,
--381,-379,-382,-388,-389,-387,-384,-384,-382,-376,-367,-363,-367,-373,-373,-368,-364,-366,-367,-362,-356,
--355,-360,-365,-364,-361,-361,-364,-363,-357,-351,-350,-350,-350,-346,-342,-336,-328,-321,-319,-320,-320,
--316,-312,-311,-310,-308,-305,-300,-294,-287,-281,-280,-282,-280,-269,-254,-242,-236,-231,-223,-214,-209,
--208,-209,-207,-201,-189,-178,-171,-166,-158,-146,-134,-126,-117,-103,-87,-79,-79,-76,-62,-41,-24,
--15,-10,-4,2,10,21,30,33,31,33,43,56,66,74,86,102,115,124,134,149,165,
-176,187,203,221,233,241,252,267,283,296,311,333,359,382,400,419,444,476,510,540,562,
-584,617,662,702,712,696,686,710,759,799,808,801,803,823,849,871,892,923,967,1014,1050,
-1077,1111,1168,1244,1317,1370,1410,1449,1495,1541,1587,1635,1682,1723,1762,1815,1884,1947,1982,1998,2008,
-1979,1841,1580,1313,1242,1503,2049,2670,3129,3328,3349,3364,3473,3631,3737,3782,3857,4027,4232,4357,4378,
-4376,4413,4447,4415,4343,4302,4268,4106,3725,3217,2785,2549,2472,2444,2409,2375,2354,2334,2307,2278,2257,
-2236,2201,2155,2107,2063,2019,1979,1947,1920,1887,1839,1781,1725,1677,1635,1590,1533,1463,1385,1301,1208,
-1103,999,909,828,737,617,475,331,200,87,-6,-74,-119,-151,-179,-202,-218,-236,-265,-307,-353,
--399,-441,-476,-497,-504,-500,-492,-482,-475,-480,-500,-522,-529,-519,-504,-487,-455,-398,-324,-258,-221,
--217,-240,-276,-305,-318,-318,-327,-357,-405,-458,-508,-545,-563,-564,-563,-572,-585,-581,-564,-570,-635,
--756,-888,-992,-1059,-1100,-1119,-1111,-1080,-1040,-1005,-983,-971,-968,-967,-962,-947,-924,-895,-869,-850,-837,
--825,-808,-788,-771,-762,-758,-753,-745,-740,-738,-733,-717,-692,-668,-652,-644,-641,-640,-638,-635,-633,
--633,-634,-632,-628,-624,-621,-616,-608,-602,-597,-593,-587,-581,-576,-570,-558,-540,-520,-499,-476,-449,
--426,-409,-392,-366,-333,-301,-274,-248,-220,-191,-167,-142,-112,-77,-47,-21,6,42,80,114,146,
-181,219,254,286,320,356,389,417,444,473,507,540,571,604,639,673,702,731,767,810,854,
-892,922,952,989,1033,1074,1103,1122,1143,1174,1206,1228,1235,1239,1246,1252,1252,1251,1255,1264,1269,
-1267,1262,1261,1263,1266,1271,1282,1294,1302,1307,1317,1333,1349,1360,1369,1383,1401,1420,1438,1458,1480,
-1501,1521,1545,1573,1600,1621,1638,1656,1676,1695,1712,1730,1749,1766,1780,1795,1814,1823,1848,1874,1901,
-1930,1962,1994,2028,2064,2101,2133,2161,2191,2224,2255,2285,2323,2375,2432,2477,2509,2542,2580,2607,2609,
-2597,2579,2537,2452,2345,2288,2327,2416,2456,2396,2283,2203,2193,2220,2240,2244,2251,2268,2289,2314,2349,
-2394,2439,2480,2531,2605,2695,2778,2841,2891,2932,2959,2966,2966,2981,3020,3065,3099,3129,3171,3227,3271,
-3273,3233,3176,3122,3065,2988,2889,2790,2713,2664,2629,2597,2565,2532,2497,2456,2413,2376,2349,2325,2296,
-2260,2226,2202,2182,2159,2127,2090,2051,2009,1963,1917,1882,1864,1858,1851,1831,1796,1750,1702,1659,1623,
-1596,1579,1577,1591,1609,1620,1623,1626,1628,1613,1559,1465,1349,1242,1166,1132,1132,1136,1104,1016,896,
-788,714,666,628,601,601,625,652,664,658,642,612,552,462,363,287,247,231,214,184,149,
-129,131,143,153,151,138,114,81,48,30,30,39,42,36,29,24,15,-6,-45,-96,-136,
--130,-49,95,245,335,354,349,378,447,526,590,641,678,669,583,447,334,299,309,279,161,
--5,-140,-201,-219,-245,-295,-348,-384,-405,-419,-418,-396,-364,-342,-338,-334,-315,-283,-256,-243,-235,
--224,-210,-197,-187,-184,-193,-212,-224,-218,-197,-180,-180,-193,-209,-225,-247,-277,-305,-325,-337,-341,
--333,-319,-313,-324,-343,-349,-335,-316,-309,-316,-326,-331,-330,-325,-321,-322,-328,-336,-340,-343,-351,
--369,-390,-408,-427,-450,-477,-499,-519,-543,-572,-595,-607,-618,-637,-663,-686,-704,-723,-751,-782,-810,
--841,-881,-928,-979,-1030,-1084,-1137,-1182,-1218,-1256,-1305,-1366,-1428,-1489,-1549,-1603,-1643,-1670,-1696,-1736,-1792,
--1856,-1919,-1978,-2033,-2082,-2127,-2175,-2228,-2286,-2347,-2411,-2473,-2526,-2568,-2600,-2631,-2667,-2710,-2759,-2813,-2862,
--2903,-2938,-2978,-3025,-3070,-3106,-3134,-3164,-3197,-3229,-3259,-3293,-3334,-3374,-3407,-3436,-3471,-3514,-3558,-3592,-3614,
--3631,-3648,-3665,-3681,-3696,-3708,-3717,-3719,-3713,-3699,-3690,-3707,-3768,-3858,-3943,-3994,-4014,-4032,-4071,-4131,-4193,
--4241,-4269,-4283,-4296,-4316,-4340,-4361,-4377,-4391,-4407,-4423,-4433,-4435,-4434,-4433,-4434,-4436,-4441,-4447,-4454,-4457,
--4460,-4465,-4477,-4494,-4513,-4532,-4549,-4562,-4569,-4569,-4565,-4558,-4546,-4528,-4503,-4474,-4443,-4410,-4372,-4330,-4293,
--4267,-4251,-4234,-4204,-4158,-4107,-4063,-4031,-4001,-3962,-3909,-3850,-3799,-3761,-3737,-3725,-3722,-3725,-3722,-3706,-3675,
--3640,-3604,-3562,-3502,-3426,-3347,-3279,-3227,-3187,-3159,-3143,-3143,-3159,-3190,-3226,-3251,-3249,-3222,-3187,-3149,-3097,
--3010,-2888,-2747,-2604,-2469,-2342,-2226,-2120,-2015,-1902,-1791,-1695,-1616,-1541,-1459,-1376,-1301,-1235,-1166,-1088,-1012,
--956,-928,-921,-917,-898,-848,-768,-679,-611,-578,-569,-568,-562,-548,-524,-477,-406,-325,-256,-211,-186,
--164,-138,-109,-83,-61,-42,-25,-8,9,35,73,124,181,230,261,272,272,279,306,360,436,
-519,590,638,666,685,704,727,757,795,840,890,940,988,1030,1059,1070,1068,1076,1121,1209,1327,
-1451,1569,1677,1772,1850,1908,1955,2002,2059,2122,2187,2251,2319,2398,2481,2553,2601,2630,2659,2703,2762,
-2825,2880,2929,2980,3039,3111,3193,3278,3357,3426,3489,3551,3604,3636,3640,3626,3611,3604,3601,3596,3591,
-3596,3613,3640,3677,3726,3792,3875,3961,4040,4116,4204,4313,4430,4528,4596,4652,4719,4799,4868,4904,4910,
-4905,4906,4914,4928,4949,4982,5025,5068,5101,5110,5090,5051,5024,5029,5051,5055,5021,4975,4949,4946,4939,
-4914,4895,4911,4946,4947,4882,4785,4724,4734,4788,4829,4832,4817,4816,4832,4843,4830,4801,4776,4768,4774,
-4791,4828,4893,4972,5031,5043,5017,4989,4991,5033,5094,5144,5162,5153,5141,5152,5184,5207,5194,5153,5116,
-5111,5133,5159,5175,5185,5200,5219,5239,5265,5306,5368,5444,5517,5579,5632,5683,5730,5757,5751,5713,5663,
-5618,5579,5528,5449,5335,5200,5065,4959,4896,4872,4867,4866,4874,4903,4952,5003,5043,5084,5143,5218,5287,
-5330,5351,5366,5385,5396,5386,5354,5313,5277,5248,5219,5183,5146,5113,5088,5066,5042,5020,5008,5008,5014,
-5021,5029,5042,5065,5104,5155,5205,5233,5225,5196,5179,5192,5217,5220,5191,5162,5163,5152,5007,4607,3953,
-3210,2624,2366,2433,2672,2910,3056,3120,3149,3165,3164,3137,3090,3038,2986,2931,2863,2783,2700,2624,2555,
-2490,2427,2367,2310,2253,2187,2114,2043,1981,1924,1864,1803,1748,1702,1660,1617,1571,1528,1493,1460,1426,
-1385,1340,1296,1257,1226,1201,1180,1165,1157,1154,1146,1123,1086,1048,1015,989,964,936,905,869,830,
-791,755,724,693,659,623,587,550,512,475,441,412,385,357,327,300,276,257,242,228,212,
-191,164,134,100,67,38,9,-26,-75,-125,-155,-152,-130,-124,-157,-216,-264,-276,-262,-260,-299,
--376,-458,-507,-518,-515,-532,-578,-632,-668,-679,-679,-683,-695,-706,-713,-719,-727,-741,-759,-783,-810,
--836,-858,-876,-889,-898,-906,-915,-927,-940,-948,-955,-966,-985,-1006,-1022,-1034,-1048,-1066,-1081,-1091,-1101,
--1117,-1132,-1134,-1118,-1099,-1097,-1117,-1148,-1174,-1189,-1184,-1155,-1102,-1049,-1029,-1060,-1125,-1188,-1222,-1228,-1221,
--1212,-1203,-1193,-1181,-1168,-1154,-1142,-1135,-1134,-1134,-1129,-1120,-1112,-1108,-1103,-1095,-1085,-1079,-1081,-1086,-1087,
--1082,-1069,-1054,-1041,-1034,-1030,-1026,-1018,-1009,-1002,-995,-987,-976,-963,-950,-935,-918,-898,-877,-858,-841,
--826,-811,-799,-789,-778,-764,-745,-726,-708,-691,-674,-658,-641,-627,-614,-599,-583,-567,-552,-538,-523,
--509,-497,-487,-478,-469,-460,-453,-444,-432,-420,-411,-407,-405,-405,-406,-409,-412,-410,-402,-396,-395,
--394,-389,-380,-376,-380,-386,-384,-377,-373,-376,-380,-378,-373,-370,-373,-375,-371,-367,-367,-369,-368,
--362,-358,-357,-356,-352,-346,-341,-335,-329,-322,-319,-318,-316,-312,-308,-306,-306,-304,-302,-297,-289,
--278,-269,-268,-271,-269,-259,-246,-236,-230,-223,-214,-206,-202,-199,-196,-192,-186,-177,-167,-159,-153,
--143,-128,-111,-100,-91,-79,-67,-60,-59,-56,-44,-26,-11,-2,4,9,13,20,30,40,42,
-40,42,54,69,79,87,99,116,130,138,149,165,180,190,197,210,226,241,255,272,292,
-308,319,335,359,382,394,399,414,448,491,527,551,576,613,662,701,710,687,661,669,721,
-786,823,821,804,806,832,867,894,917,947,987,1031,1069,1102,1140,1195,1264,1330,1381,1417,1452,
-1491,1537,1586,1640,1693,1738,1780,1831,1890,1938,1963,1975,1981,1945,1799,1539,1287,1242,1530,2085,2680,
-3085,3227,3222,3249,3378,3540,3637,3678,3765,3955,4175,4310,4342,4353,4401,4445,4424,4358,4303,4234,4033,
-3638,3147,2749,2545,2488,2467,2431,2392,2367,2350,2329,2310,2299,2290,2268,2227,2176,2121,2064,2006,1954,
-1910,1870,1829,1784,1738,1693,1648,1597,1530,1449,1364,1280,1193,1096,994,900,816,724,610,476,341,
-221,120,41,-18,-66,-108,-144,-170,-187,-203,-227,-253,-280,-309,-347,-388,-418,-427,-423,-417,-416,
--419,-431,-452,-472,-479,-468,-448,-419,-378,-325,-273,-242,-236,-249,-271,-300,-330,-351,-362,-370,-387,
--416,-458,-506,-550,-577,-581,-576,-576,-578,-576,-579,-624,-732,-878,-1009,-1091,-1130,-1149,-1156,-1139,-1097,
--1046,-1005,-982,-973,-969,-964,-955,-940,-918,-894,-871,-850,-832,-814,-796,-779,-768,-762,-757,-751,-745,
--744,-743,-735,-717,-694,-674,-659,-650,-644,-640,-638,-636,-633,-630,-627,-622,-618,-614,-610,-604,-596,
--590,-584,-576,-563,-553,-549,-546,-536,-515,-493,-471,-448,-422,-398,-380,-363,-338,-305,-273,-247,-221,
--192,-164,-139,-116,-87,-55,-24,2,32,67,103,135,168,206,247,283,314,345,379,410,434,
-459,489,523,557,589,623,658,691,720,750,786,830,876,919,958,997,1038,1079,1116,1140,1153,
-1163,1178,1196,1210,1219,1228,1240,1248,1250,1249,1255,1266,1272,1269,1263,1263,1266,1271,1277,1288,1299,
-1308,1317,1330,1348,1364,1373,1380,1394,1413,1432,1449,1469,1491,1511,1529,1551,1577,1601,1618,1629,1643,
-1662,1683,1701,1720,1741,1762,1781,1800,1823,1831,1860,1890,1921,1953,1985,2015,2045,2078,2113,2146,2176,
-2209,2247,2286,2322,2362,2414,2469,2513,2545,2577,2612,2636,2633,2610,2579,2530,2444,2340,2281,2310,2388,
-2426,2377,2283,2221,2217,2241,2252,2251,2258,2277,2301,2328,2369,2422,2473,2513,2555,2616,2693,2767,2824,
-2870,2909,2940,2958,2971,2997,3038,3080,3110,3137,3182,3241,3282,3273,3218,3150,3092,3040,2971,2880,2787,
-2719,2677,2645,2614,2584,2563,2543,2515,2480,2449,2426,2403,2368,2323,2283,2258,2240,2217,2186,2154,2121,
-2081,2031,1977,1934,1909,1896,1885,1864,1828,1777,1720,1674,1647,1635,1635,1648,1676,1707,1727,1730,1726,
-1719,1690,1613,1485,1336,1205,1121,1093,1110,1141,1142,1085,983,879,803,751,708,676,670,693,725,
-742,742,731,704,643,547,441,364,328,317,297,261,223,208,217,232,235,219,192,161,131,
-107,95,93,93,88,78,66,56,47,33,7,-37,-86,-96,-24,118,268,354,374,387,445,
-533,606,645,675,708,709,641,523,426,393,389,340,215,60,-59,-122,-157,-198,-250,-296,-326,
--344,-352,-343,-315,-283,-267,-268,-267,-254,-232,-214,-202,-192,-179,-164,-150,-141,-139,-148,-164,-169,
--152,-122,-102,-104,-123,-145,-165,-188,-216,-243,-264,-278,-281,-274,-266,-268,-284,-299,-294,-271,-250,
--245,-254,-261,-260,-258,-261,-268,-276,-285,-294,-302,-309,-317,-326,-337,-349,-364,-384,-408,-431,-455,
--481,-507,-525,-536,-550,-573,-601,-625,-644,-665,-689,-712,-736,-766,-806,-854,-902,-952,-1006,-1059,-1102,
--1135,-1173,-1226,-1292,-1356,-1413,-1462,-1505,-1539,-1566,-1598,-1647,-1710,-1776,-1839,-1895,-1944,-1989,-2035,-2085,-2141,
--2202,-2265,-2328,-2388,-2437,-2475,-2508,-2545,-2587,-2633,-2681,-2732,-2782,-2825,-2862,-2901,-2945,-2988,-3022,-3049,-3077,
--3110,-3142,-3173,-3206,-3245,-3286,-3324,-3360,-3400,-3444,-3485,-3519,-3545,-3568,-3591,-3611,-3628,-3641,-3651,-3656,-3654,
--3646,-3635,-3637,-3669,-3737,-3822,-3892,-3931,-3948,-3971,-4015,-4076,-4141,-4194,-4228,-4244,-4253,-4268,-4292,-4317,-4337,
--4352,-4367,-4382,-4390,-4390,-4387,-4387,-4392,-4398,-4406,-4415,-4424,-4432,-4440,-4451,-4466,-4481,-4493,-4502,-4510,-4521,
--4530,-4534,-4531,-4521,-4507,-4489,-4467,-4442,-4413,-4381,-4347,-4312,-4278,-4249,-4223,-4200,-4171,-4134,-4092,-4054,-4028,
--4008,-3982,-3943,-3895,-3847,-3804,-3763,-3725,-3699,-3693,-3703,-3709,-3699,-3672,-3637,-3593,-3531,-3453,-3370,-3296,-3238,
--3193,-3163,-3152,-3159,-3182,-3215,-3249,-3271,-3271,-3249,-3215,-3171,-3102,-2995,-2853,-2698,-2554,-2425,-2308,-2200,-2102,
--2011,-1923,-1836,-1757,-1688,-1618,-1541,-1457,-1374,-1296,-1221,-1146,-1078,-1024,-990,-974,-968,-954,-914,-844,-762,
--697,-659,-636,-609,-575,-542,-511,-474,-424,-366,-315,-278,-253,-234,-218,-208,-202,-198,-191,-179,-160,
--132,-97,-52,4,73,141,189,206,202,201,224,275,345,414,471,510,536,556,576,596,619,
-644,671,697,721,746,773,795,804,803,814,860,946,1056,1174,1289,1401,1502,1585,1646,1695,1747,
-1811,1888,1973,2064,2161,2264,2361,2440,2495,2533,2568,2611,2662,2715,2769,2822,2874,2927,2991,3073,3168,
-3259,3330,3384,3435,3485,3519,3524,3505,3482,3467,3461,3459,3460,3472,3495,3525,3561,3609,3678,3767,3860,
-3942,4015,4096,4201,4318,4422,4498,4563,4636,4720,4790,4827,4838,4841,4849,4857,4865,4880,4911,4957,5010,
-5052,5071,5056,5019,4989,4988,5004,4999,4957,4902,4872,4868,4858,4822,4785,4783,4806,4806,4750,4669,4624,
-4650,4717,4772,4788,4781,4777,4782,4782,4764,4736,4718,4720,4735,4753,4774,4809,4860,4909,4936,4934,4924,
-4934,4975,5038,5094,5120,5112,5089,5082,5100,5131,5147,5132,5098,5070,5066,5083,5111,5138,5159,5176,5193,
-5213,5242,5289,5354,5429,5498,5550,5593,5636,5679,5701,5685,5639,5592,5563,5543,5508,5438,5336,5222,5122,
-5050,5005,4979,4967,4977,5017,5082,5153,5212,5261,5308,5352,5383,5395,5393,5391,5388,5377,5352,5317,5284,
-5258,5233,5203,5164,5125,5092,5069,5050,5029,5008,4993,4989,4995,5006,5022,5042,5069,5102,5144,5190,5220,
-5219,5194,5176,5187,5212,5210,5172,5131,5119,5076,4860,4360,3631,2903,2437,2348,2543,2823,3033,3138,3178,
-3198,3205,3189,3149,3098,3046,2994,2932,2858,2778,2697,2622,2551,2485,2422,2363,2306,2246,2180,2110,2039,
-1972,1908,1847,1789,1736,1690,1648,1606,1565,1526,1491,1460,1426,1384,1335,1287,1249,1222,1196,1169,1147,
-1139,1141,1137,1115,1078,1039,1008,983,957,926,889,849,808,769,733,701,669,637,609,580,547,
-506,464,430,404,381,352,317,283,257,240,228,217,202,184,161,132,94,51,11,-18,-44,
--77,-120,-160,-178,-173,-168,-186,-230,-273,-287,-275,-272,-314,-402,-492,-534,-515,-474,-464,-507,-579,
--636,-658,-657,-657,-668,-686,-701,-710,-719,-735,-759,-788,-816,-839,-860,-880,-896,-906,-913,-923,-938,
--953,-963,-969,-978,-992,-1008,-1022,-1033,-1046,-1063,-1080,-1095,-1109,-1126,-1140,-1144,-1137,-1126,-1127,-1142,-1164,
--1182,-1189,-1184,-1167,-1138,-1107,-1093,-1108,-1148,-1192,-1221,-1230,-1226,-1220,-1216,-1213,-1207,-1193,-1176,-1160,-1149,
--1145,-1140,-1130,-1119,-1112,-1106,-1099,-1088,-1076,-1072,-1076,-1082,-1085,-1081,-1069,-1055,-1041,-1033,-1029,-1026,-1018,
--1007,-997,-990,-982,-972,-960,-948,-934,-918,-900,-882,-866,-850,-833,-817,-804,-793,-780,-763,-746,-731,
--717,-703,-686,-669,-653,-639,-625,-609,-593,-577,-564,-551,-537,-522,-508,-498,-489,-481,-472,-463,-453,
--441,-429,-422,-420,-422,-424,-426,-428,-428,-423,-413,-404,-402,-402,-398,-390,-387,-393,-399,-397,-388,
--382,-384,-390,-390,-387,-385,-385,-384,-379,-374,-373,-374,-372,-368,-365,-363,-361,-355,-347,-340,-333,
--327,-321,-318,-317,-314,-309,-306,-303,-301,-298,-296,-291,-281,-269,-261,-262,-265,-262,-251,-239,-230,
--223,-214,-204,-197,-192,-187,-181,-177,-171,-163,-152,-143,-137,-128,-111,-91,-75,-65,-56,-49,-44,
--40,-31,-17,-4,4,10,16,22,27,32,42,51,53,49,50,63,81,94,103,115,130,
-143,152,163,180,197,208,214,223,234,247,265,290,317,333,343,359,387,413,418,410,417,
-452,499,531,551,579,628,683,710,696,662,648,677,739,795,818,812,803,815,846,885,918,
-945,972,1004,1043,1085,1128,1173,1225,1284,1341,1385,1417,1445,1479,1522,1577,1641,1704,1756,1796,1835,
-1877,1913,1932,1943,1946,1906,1763,1516,1285,1264,1571,2128,2693,3041,3126,3090,3113,3252,3422,3528,3586,
-3697,3903,4133,4279,4325,4339,4375,4410,4400,4348,4272,4137,3868,3461,3030,2720,2578,2535,2499,2446,2402,
-2384,2376,2362,2347,2341,2338,2324,2287,2232,2166,2095,2025,1963,1911,1870,1834,1798,1755,1707,1655,1597,
-1529,1449,1362,1273,1183,1085,985,891,804,713,607,487,367,261,175,111,61,16,-28,-73,-111,
--143,-175,-203,-215,-211,-209,-227,-267,-303,-319,-319,-319,-326,-338,-354,-376,-402,-419,-418,-392,-347,
--292,-245,-224,-233,-257,-279,-297,-321,-354,-388,-414,-430,-446,-467,-498,-538,-581,-612,-624,-626,-628,
--633,-641,-663,-725,-838,-972,-1081,-1141,-1165,-1176,-1175,-1149,-1097,-1039,-997,-978,-972,-967,-958,-946,-930,
--910,-889,-869,-850,-833,-818,-804,-793,-784,-775,-764,-752,-744,-741,-736,-726,-709,-691,-676,-662,-649,
--639,-634,-633,-630,-626,-620,-613,-608,-604,-602,-599,-593,-583,-575,-567,-557,-542,-530,-525,-523,-512,
--491,-468,-449,-430,-407,-381,-359,-338,-312,-281,-251,-227,-202,-171,-139,-112,-87,-59,-29,0,28,
-60,95,129,158,190,228,270,306,337,368,402,433,459,484,516,552,587,619,652,688,721,
-751,782,819,860,903,948,996,1043,1085,1118,1144,1162,1172,1175,1178,1184,1194,1206,1221,1237,1247,
-1251,1253,1260,1271,1277,1274,1271,1273,1279,1284,1290,1299,1310,1321,1331,1345,1359,1370,1376,1383,1399,
-1421,1441,1460,1483,1507,1527,1543,1560,1582,1600,1610,1616,1627,1646,1666,1685,1704,1728,1754,1779,1804,
-1831,1855,1887,1919,1950,1982,2013,2041,2067,2097,2131,2164,2193,2224,2263,2305,2345,2386,2435,2491,2540,
-2580,2617,2653,2675,2666,2634,2595,2545,2469,2371,2296,2285,2322,2346,2322,2275,2251,2261,2276,2275,2268,
-2274,2293,2313,2337,2378,2434,2487,2525,2563,2621,2697,2770,2819,2852,2881,2913,2944,2975,3012,3055,3095,
-3128,3164,3217,3275,3306,3282,3209,3125,3059,3006,2943,2862,2782,2726,2693,2665,2632,2603,2591,2587,2573,
-2546,2516,2492,2465,2422,2369,2324,2298,2282,2261,2235,2211,2187,2153,2105,2053,2010,1978,1950,1920,1887,
-1844,1788,1726,1675,1653,1659,1681,1717,1763,1804,1822,1812,1790,1766,1725,1636,1494,1331,1191,1103,1076,
-1103,1156,1190,1165,1081,977,893,836,791,757,745,762,791,812,818,811,785,722,623,520,450,
-423,410,381,333,292,282,297,312,307,281,243,208,181,167,164,162,151,133,115,101,91,
-84,77,60,20,-32,-50,16,163,318,412,443,472,545,637,696,711,718,737,742,694,603,
-521,478,442,366,238,101,-1,-64,-109,-152,-194,-227,-252,-269,-274,-262,-238,-217,-208,-206,-202,
--192,-180,-170,-160,-146,-131,-119,-111,-107,-106,-111,-117,-111,-88,-60,-46,-52,-72,-93,-113,-137,
--165,-191,-209,-219,-222,-219,-218,-224,-236,-241,-231,-210,-195,-193,-197,-194,-187,-185,-193,-206,-217,
--228,-243,-260,-271,-276,-278,-283,-291,-304,-321,-341,-364,-388,-412,-431,-446,-461,-485,-516,-546,-569,
--589,-611,-633,-651,-668,-696,-737,-784,-828,-874,-926,-980,-1024,-1058,-1097,-1151,-1216,-1277,-1326,-1365,-1400,
--1432,-1468,-1514,-1572,-1637,-1700,-1757,-1808,-1854,-1897,-1944,-1998,-2058,-2121,-2183,-2244,-2299,-2345,-2382,-2420,-2464,
--2511,-2556,-2598,-2645,-2695,-2744,-2787,-2826,-2868,-2907,-2940,-2967,-2996,-3029,-3062,-3092,-3124,-3161,-3202,-3243,-3284,
--3328,-3372,-3414,-3449,-3480,-3509,-3535,-3557,-3574,-3586,-3592,-3593,-3587,-3576,-3567,-3576,-3620,-3694,-3776,-3836,-3868,
--3887,-3917,-3967,-4032,-4098,-4154,-4190,-4203,-4206,-4217,-4244,-4276,-4301,-4314,-4326,-4339,-4349,-4352,-4350,-4350,-4356,
--4366,-4377,-4390,-4402,-4413,-4424,-4437,-4452,-4465,-4471,-4472,-4474,-4482,-4492,-4498,-4495,-4483,-4466,-4449,-4431,-4410,
--4385,-4355,-4324,-4294,-4264,-4232,-4198,-4167,-4139,-4112,-4081,-4049,-4020,-3996,-3974,-3948,-3919,-3889,-3851,-3800,-3740,
--3690,-3669,-3679,-3700,-3713,-3708,-3684,-3637,-3564,-3471,-3379,-3306,-3250,-3207,-3176,-3166,-3179,-3209,-3245,-3278,-3296,
--3292,-3265,-3221,-3162,-3081,-2966,-2819,-2663,-2518,-2391,-2276,-2173,-2087,-2018,-1956,-1891,-1823,-1757,-1692,-1621,-1539,
--1450,-1361,-1279,-1210,-1152,-1104,-1066,-1042,-1030,-1020,-991,-935,-864,-799,-747,-698,-641,-581,-531,-496,-467,
--436,-403,-373,-347,-322,-302,-291,-289,-294,-299,-302,-298,-282,-251,-212,-169,-115,-43,37,101,129,
-126,119,135,182,245,308,359,397,422,440,453,464,474,484,490,491,490,495,511,535,558,
-581,616,673,750,833,919,1009,1106,1202,1285,1352,1414,1481,1560,1650,1753,1869,1994,2118,2227,2313,
-2377,2428,2475,2521,2566,2612,2664,2720,2774,2823,2877,2952,3046,3138,3210,3264,3311,3358,3388,3388,3365,
-3339,3323,3319,3323,3334,3356,3384,3415,3450,3498,3569,3660,3757,3845,3922,4002,4097,4204,4306,4392,4470,
-4554,4639,4708,4749,4770,4786,4800,4808,4811,4821,4851,4898,4950,4995,5019,5013,4982,4952,4945,4952,4945,
-4907,4862,4838,4830,4803,4739,4669,4632,4632,4627,4590,4540,4519,4550,4612,4666,4697,4711,4720,4728,4725,
-4707,4683,4665,4664,4678,4698,4719,4740,4768,4798,4823,4841,4857,4884,4926,4982,5038,5077,5086,5067,5040,
-5030,5048,5079,5096,5082,5046,5011,5000,5016,5049,5087,5123,5152,5173,5189,5215,5268,5347,5428,5490,5529,
-5563,5601,5630,5628,5598,5563,5545,5538,5517,5466,5393,5318,5258,5218,5193,5176,5168,5177,5205,5246,5289,
-5324,5351,5375,5392,5398,5393,5384,5376,5365,5346,5320,5292,5267,5243,5214,5180,5145,5112,5084,5060,5038,
-5015,4992,4977,4974,4986,5005,5026,5048,5072,5102,5141,5183,5211,5208,5183,5167,5182,5206,5198,5148,5093,
-5056,4961,4666,4090,3344,2694,2376,2428,2692,2962,3126,3195,3225,3243,3240,3211,3163,3112,3061,3002,2930,
-2851,2772,2695,2621,2548,2478,2415,2356,2297,2234,2170,2104,2035,1965,1896,1833,1778,1728,1678,1630,1589,
-1555,1524,1492,1458,1421,1378,1328,1280,1241,1211,1181,1151,1128,1122,1128,1127,1107,1072,1035,1004,976,
-947,913,875,833,791,752,717,682,648,619,596,574,541,499,459,434,420,402,370,325,281,
-248,227,215,205,193,178,158,132,96,52,8,-25,-50,-75,-108,-146,-177,-193,-203,-225,-266,
--311,-335,-333,-328,-355,-420,-490,-515,-479,-418,-390,-425,-504,-580,-622,-634,-639,-656,-684,-712,-729,
--740,-755,-780,-807,-828,-842,-855,-874,-893,-907,-915,-925,-938,-953,-966,-977,-990,-1005,-1018,-1028,-1039,
--1052,-1068,-1085,-1101,-1118,-1133,-1146,-1153,-1155,-1157,-1164,-1176,-1187,-1194,-1194,-1193,-1198,-1205,-1209,-1207,-1205,
--1209,-1219,-1228,-1228,-1223,-1219,-1221,-1227,-1227,-1218,-1201,-1185,-1174,-1167,-1159,-1147,-1135,-1127,-1120,-1110,-1096,
--1083,-1078,-1077,-1078,-1076,-1071,-1063,-1052,-1041,-1032,-1029,-1027,-1021,-1011,-1000,-991,-983,-973,-961,-948,-934,
--918,-901,-886,-873,-858,-840,-823,-809,-796,-780,-762,-745,-732,-720,-707,-690,-674,-660,-647,-632,-616,
--599,-584,-571,-560,-547,-533,-520,-509,-500,-491,-482,-471,-459,-449,-441,-437,-437,-438,-438,-438,-437,
--436,-431,-422,-415,-412,-411,-407,-400,-398,-404,-411,-411,-402,-395,-395,-399,-401,-398,-395,-394,-391,
--386,-382,-381,-382,-380,-376,-373,-370,-366,-359,-350,-341,-332,-324,-319,-317,-315,-312,-307,-303,-299,
--294,-290,-287,-283,-273,-260,-253,-254,-255,-248,-234,-221,-213,-206,-196,-185,-176,-170,-165,-160,-157,
--154,-144,-130,-119,-115,-112,-99,-79,-60,-47,-42,-39,-36,-29,-15,2,16,21,24,30,37,
-43,49,59,71,76,74,73,83,100,115,125,136,150,162,170,180,194,210,223,234,244,
-252,259,273,298,323,335,339,356,394,430,437,422,419,447,490,519,534,560,609,658,676,
-662,649,668,718,768,792,792,789,801,829,864,900,934,963,988,1013,1048,1095,1147,1196,1244,
-1295,1347,1388,1417,1439,1468,1511,1571,1645,1719,1777,1812,1836,1863,1890,1910,1919,1917,1874,1738,1509,
-1299,1301,1630,2198,2753,3066,3105,3034,3043,3184,3369,3501,3590,3714,3910,4122,4266,4321,4332,4348,4369,
-4371,4332,4222,3997,3648,3244,2908,2719,2646,2599,2525,2444,2398,2391,2394,2386,2374,2369,2368,2356,2322,
-2266,2195,2120,2049,1988,1938,1897,1859,1819,1772,1717,1659,1599,1533,1455,1366,1271,1172,1072,974,882,
-796,708,612,510,409,316,240,183,139,98,55,10,-32,-78,-128,-168,-177,-150,-115,-107,-131,
--163,-179,-182,-187,-201,-217,-234,-259,-298,-341,-365,-353,-305,-247,-213,-222,-259,-295,-310,-315,-335,
--376,-423,-462,-489,-512,-539,-571,-609,-651,-686,-708,-719,-729,-743,-761,-792,-851,-942,-1040,-1114,-1154,
--1172,-1181,-1173,-1137,-1077,-1019,-983,-971,-970,-965,-954,-940,-924,-907,-887,-868,-851,-837,-824,-811,-799,
--786,-773,-758,-743,-732,-724,-715,-703,-690,-678,-668,-655,-641,-631,-628,-628,-624,-617,-610,-603,-596,
--591,-589,-585,-577,-565,-554,-546,-535,-521,-507,-500,-494,-481,-458,-436,-419,-404,-381,-353,-326,-300,
--273,-243,-215,-191,-166,-135,-101,-71,-44,-16,12,41,69,99,133,164,192,221,258,298,333,
-364,397,433,468,496,525,558,594,629,660,693,727,760,792,825,860,894,928,970,1023,1075,
-1114,1137,1152,1168,1181,1187,1187,1190,1199,1213,1230,1245,1255,1260,1264,1271,1278,1282,1281,1282,1287,
-1295,1301,1306,1315,1326,1338,1348,1359,1370,1377,1383,1394,1413,1434,1454,1474,1498,1525,1545,1558,1571,
-1587,1601,1607,1611,1623,1644,1666,1684,1705,1734,1767,1798,1826,1855,1895,1927,1958,1986,2014,2043,2069,
-2094,2121,2152,2182,2208,2235,2270,2311,2351,2391,2438,2495,2554,2605,2649,2690,2714,2707,2670,2622,2571,
-2505,2417,2334,2289,2285,2294,2291,2284,2290,2305,2310,2300,2291,2298,2313,2324,2338,2374,2430,2483,2520,
-2557,2620,2708,2792,2847,2875,2894,2920,2954,2991,3029,3066,3103,3142,3191,3251,3306,3327,3290,3207,3113,
-3037,2980,2922,2852,2785,2738,2711,2686,2655,2629,2623,2628,2623,2598,2566,2537,2506,2460,2404,2356,2329,
-2312,2292,2271,2256,2243,2219,2179,2135,2098,2062,2017,1965,1914,1864,1806,1740,1687,1669,1689,1736,1796,
-1858,1905,1915,1887,1843,1803,1752,1660,1519,1359,1224,1138,1107,1129,1188,1243,1245,1176,1069,971,906,
-863,833,819,828,851,872,883,880,853,787,688,592,533,511,491,447,390,352,350,369,380,
-367,335,296,261,237,228,229,225,207,180,158,147,141,135,130,115,76,18,-8,52,202,
-374,493,548,589,654,726,764,763,757,765,764,724,654,585,528,461,359,233,114,27,-32,
--74,-106,-130,-154,-181,-203,-209,-198,-181,-169,-161,-150,-136,-124,-121,-120,-113,-99,-85,-76,-75,
--76,-77,-76,-70,-55,-33,-13,-7,-16,-33,-51,-73,-99,-128,-151,-163,-167,-168,-168,-168,-170,
--171,-169,-162,-154,-151,-151,-148,-139,-130,-131,-138,-146,-154,-167,-187,-208,-221,-224,-225,-232,-244,
--257,-269,-283,-301,-322,-340,-355,-371,-395,-427,-460,-485,-504,-525,-553,-579,-596,-609,-632,-670,-714,
--756,-798,-846,-898,-944,-982,-1023,-1075,-1135,-1191,-1235,-1268,-1300,-1336,-1383,-1440,-1504,-1565,-1621,-1670,-1717,
--1762,-1806,-1855,-1913,-1977,-2041,-2101,-2157,-2208,-2251,-2291,-2334,-2382,-2431,-2472,-2511,-2556,-2610,-2664,-2710,-2748,
--2785,-2821,-2855,-2885,-2916,-2949,-2983,-3015,-3047,-3084,-3124,-3165,-3208,-3252,-3298,-3342,-3381,-3416,-3448,-3476,-3499,
--3515,-3526,-3531,-3530,-3522,-3508,-3498,-3509,-3557,-3635,-3716,-3775,-3807,-3833,-3872,-3930,-3996,-4059,-4112,-4144,-4153,
--4152,-4161,-4192,-4230,-4258,-4270,-4279,-4294,-4309,-4316,-4315,-4315,-4321,-4334,-4351,-4368,-4384,-4397,-4406,-4416,-4427,
--4438,-4443,-4443,-4444,-4449,-4457,-4462,-4459,-4449,-4434,-4417,-4399,-4378,-4354,-4325,-4296,-4270,-4244,-4215,-4180,-4144,
--4114,-4091,-4071,-4045,-4015,-3983,-3955,-3931,-3911,-3891,-3865,-3826,-3776,-3728,-3696,-3684,-3686,-3696,-3709,-3712,-3681,
--3603,-3496,-3394,-3322,-3275,-3237,-3206,-3192,-3204,-3236,-3274,-3306,-3322,-3313,-3274,-3212,-3134,-3040,-2923,-2785,-2638,
--2498,-2371,-2257,-2160,-2090,-2044,-2005,-1954,-1889,-1820,-1756,-1692,-1617,-1527,-1433,-1349,-1284,-1238,-1202,-1168,-1140,
--1121,-1105,-1077,-1027,-961,-892,-824,-752,-673,-597,-539,-500,-475,-458,-444,-432,-413,-388,-366,-356,-359,
--367,-375,-382,-385,-372,-342,-305,-267,-219,-149,-61,14,49,44,28,36,76,135,197,250,291,
-319,336,347,355,363,369,366,355,340,334,345,370,406,450,508,577,647,708,763,827,904,
-988,1066,1138,1211,1290,1374,1466,1573,1700,1840,1977,2094,2184,2255,2318,2377,2428,2471,2513,2563,2620,
-2675,2723,2772,2838,2922,3008,3080,3136,3185,3226,3245,3238,3215,3195,3187,3190,3201,3222,3251,3282,3313,
-3348,3399,3471,3559,3653,3744,3829,3913,4002,4098,4195,4288,4378,4467,4550,4618,4669,4707,4738,4757,4762,
-4760,4768,4795,4838,4884,4925,4952,4955,4934,4906,4892,4892,4887,4866,4844,4836,4830,4785,4689,4574,4491,
-4456,4448,4442,4437,4446,4473,4509,4546,4582,4617,4647,4662,4662,4649,4629,4611,4604,4614,4637,4666,4694,
-4717,4738,4757,4778,4804,4838,4877,4922,4974,5026,5061,5060,5026,4989,4980,5004,5037,5046,5019,4973,4937,
-4931,4957,5007,5065,5114,5141,5149,5160,5199,5273,5358,5427,5470,5501,5533,5558,5560,5540,5517,5505,5500,
-5482,5442,5389,5345,5321,5315,5316,5315,5314,5318,5329,5344,5355,5360,5365,5373,5379,5378,5371,5362,5353,
-5337,5314,5288,5266,5244,5215,5181,5149,5124,5103,5080,5052,5023,4996,4973,4960,4962,4982,5008,5030,5045,
-5064,5096,5143,5187,5207,5194,5167,5157,5176,5194,5171,5106,5037,4971,4821,4455,3838,3129,2597,2421,2567,
-2844,3071,3190,3240,3271,3286,3271,3228,3177,3129,3077,3011,2932,2849,2772,2699,2623,2546,2472,2405,2343,
-2281,2218,2157,2098,2035,1964,1892,1826,1772,1721,1668,1615,1574,1547,1524,1496,1459,1418,1374,1327,1279,
-1235,1197,1162,1132,1113,1109,1113,1110,1091,1062,1031,1001,971,938,904,866,824,781,741,704,667,
-632,603,582,560,527,486,454,442,439,426,390,338,288,249,223,206,193,180,166,148,124,
-93,56,17,-19,-48,-73,-100,-131,-166,-199,-229,-259,-297,-338,-370,-380,-375,-378,-404,-439,-452,
--425,-380,-356,-382,-452,-531,-586,-611,-621,-640,-674,-713,-740,-757,-772,-795,-821,-839,-846,-853,-867,
--885,-902,-914,-926,-939,-952,-965,-979,-997,-1014,-1028,-1040,-1053,-1069,-1084,-1098,-1111,-1124,-1135,-1144,-1152,
--1161,-1174,-1187,-1199,-1207,-1209,-1206,-1208,-1222,-1248,-1271,-1279,-1270,-1256,-1247,-1243,-1238,-1232,-1228,-1232,-1239,
--1242,-1235,-1221,-1207,-1197,-1190,-1181,-1170,-1158,-1150,-1143,-1133,-1119,-1106,-1095,-1086,-1077,-1067,-1061,-1057,-1051,
--1042,-1034,-1031,-1029,-1024,-1016,-1007,-999,-990,-978,-965,-951,-937,-920,-903,-888,-876,-862,-846,-829,-815,
--802,-785,-767,-749,-735,-722,-707,-692,-678,-665,-653,-638,-623,-607,-593,-579,-568,-557,-545,-532,-520,
--510,-501,-492,-481,-471,-464,-461,-460,-459,-458,-453,-449,-446,-444,-442,-436,-430,-426,-423,-418,-411,
--409,-414,-421,-422,-416,-410,-410,-413,-414,-411,-406,-402,-398,-394,-391,-390,-390,-389,-385,-381,-376,
--370,-361,-352,-341,-331,-322,-317,-314,-311,-307,-302,-297,-292,-286,-281,-278,-274,-263,-250,-241,-239,
--237,-225,-208,-195,-189,-185,-175,-162,-151,-143,-137,-135,-137,-136,-125,-109,-96,-94,-95,-87,-69,
--50,-35,-28,-25,-24,-20,-6,13,29,37,40,46,54,59,63,73,89,101,104,103,109,
-122,135,146,158,172,183,192,199,207,217,229,246,264,277,282,290,307,324,327,323,339,
-386,435,451,435,424,447,491,523,537,555,588,618,626,623,642,698,761,794,787,771,777,
-809,850,884,914,945,974,995,1017,1053,1104,1157,1202,1243,1291,1345,1389,1417,1437,1465,1510,1575,
-1655,1735,1795,1824,1836,1852,1875,1894,1899,1888,1841,1713,1499,1308,1332,1695,2305,2889,3202,3214,3106,
-3085,3216,3417,3587,3708,3827,3976,4129,4242,4298,4317,4328,4345,4356,4319,4166,3860,3453,3076,2847,2765,
-2733,2655,2530,2423,2381,2389,2403,2403,2396,2394,2391,2376,2342,2288,2220,2148,2081,2027,1981,1938,1891,
-1842,1789,1733,1674,1613,1546,1467,1372,1267,1160,1058,964,877,794,712,630,546,461,378,304,245,
-199,158,119,82,46,3,-51,-99,-112,-80,-30,0,0,-10,-13,-13,-25,-52,-79,-102,-132,
--185,-255,-314,-331,-304,-261,-246,-274,-320,-345,-337,-324,-339,-388,-448,-499,-538,-575,-616,-659,-705,
--752,-794,-823,-841,-856,-875,-899,-931,-976,-1033,-1090,-1128,-1148,-1158,-1162,-1150,-1112,-1054,-1002,-974,-966,
--965,-959,-947,-933,-919,-906,-889,-872,-856,-842,-827,-809,-791,-775,-762,-749,-735,-720,-706,-691,-678,
--666,-658,-650,-639,-628,-622,-623,-623,-618,-609,-602,-597,-590,-582,-575,-568,-557,-541,-528,-518,-508,
--493,-477,-465,-454,-438,-414,-390,-371,-352,-326,-294,-263,-235,-207,-177,-149,-125,-100,-70,-39,-12,
-13,41,70,98,124,152,183,213,239,267,301,338,373,404,438,475,510,540,570,602,636,
-668,700,733,767,799,831,865,898,926,953,990,1042,1096,1132,1147,1158,1175,1195,1206,1207,1208,
-1217,1231,1246,1257,1266,1273,1278,1282,1286,1289,1291,1296,1303,1311,1317,1324,1333,1344,1354,1364,1373,
-1383,1390,1399,1413,1434,1453,1469,1487,1513,1541,1561,1571,1582,1597,1611,1620,1629,1646,1671,1694,1714,
-1739,1772,1809,1840,1867,1895,1935,1966,1993,2016,2039,2065,2092,2115,2140,2167,2194,2217,2241,2273,2313,
-2352,2388,2432,2490,2554,2610,2659,2705,2739,2742,2709,2654,2594,2529,2453,2375,2320,2299,2300,2307,2314,
-2325,2334,2331,2320,2314,2321,2329,2331,2337,2366,2419,2473,2512,2552,2617,2713,2815,2889,2928,2946,2964,
-2988,3018,3049,3079,3113,3155,3209,3270,3318,3332,3293,3212,3116,3035,2974,2919,2857,2797,2753,2726,2704,
-2679,2659,2656,2663,2658,2633,2600,2571,2539,2493,2435,2386,2355,2335,2315,2298,2293,2291,2275,2243,2207,
-2178,2144,2092,2028,1967,1915,1858,1792,1739,1726,1758,1819,1889,1953,1992,1987,1941,1883,1839,1795,1714,
-1586,1440,1316,1232,1187,1186,1230,1290,1312,1259,1150,1039,964,925,903,891,893,908,926,939,939,
-911,842,745,657,605,583,552,496,434,405,414,435,437,413,377,342,312,291,281,280,274,
-254,227,209,203,199,193,184,168,128,66,27,70,212,396,549,641,695,740,776,790,788,
-787,788,771,726,667,612,554,469,352,228,125,48,-5,-39,-54,-63,-83,-116,-146,-154,-143,
--130,-121,-111,-91,-69,-58,-61,-69,-68,-59,-47,-41,-41,-43,-42,-35,-23,-6,9,20,23,
-19,9,-7,-31,-61,-89,-108,-115,-116,-116,-116,-113,-107,-100,-96,-98,-102,-105,-102,-94,-87,
--86,-91,-97,-99,-103,-117,-138,-157,-166,-168,-174,-188,-203,-213,-219,-227,-241,-259,-275,-291,-311,
--339,-370,-396,-413,-428,-453,-487,-519,-538,-550,-570,-602,-643,-683,-723,-768,-817,-864,-906,-949,-997,
--1050,-1100,-1141,-1176,-1211,-1254,-1308,-1370,-1433,-1489,-1537,-1583,-1628,-1673,-1720,-1772,-1832,-1897,-1960,-2017,-2069,
--2118,-2162,-2204,-2249,-2298,-2345,-2386,-2428,-2479,-2536,-2589,-2630,-2662,-2694,-2730,-2766,-2800,-2835,-2869,-2904,-2939,
--2975,-3013,-3052,-3091,-3131,-3175,-3221,-3267,-3311,-3350,-3385,-3414,-3436,-3452,-3464,-3471,-3471,-3462,-3445,-3430,-3437,
--3482,-3562,-3647,-3711,-3750,-3785,-3833,-3894,-3957,-4013,-4058,-4086,-4093,-4092,-4103,-4135,-4177,-4207,-4222,-4233,-4249,
--4267,-4276,-4276,-4277,-4286,-4302,-4322,-4342,-4361,-4373,-4380,-4384,-4392,-4401,-4409,-4412,-4414,-4416,-4420,-4422,-4420,
--4414,-4402,-4385,-4365,-4342,-4316,-4289,-4262,-4239,-4219,-4196,-4165,-4127,-4092,-4068,-4054,-4038,-4015,-3983,-3949,-3916,
--3887,-3862,-3839,-3819,-3804,-3788,-3762,-3722,-3677,-3656,-3672,-3706,-3709,-3647,-3538,-3431,-3360,-3320,-3287,-3254,-3235,
--3240,-3265,-3297,-3325,-3341,-3332,-3286,-3209,-3112,-3005,-2886,-2755,-2618,-2486,-2363,-2252,-2162,-2106,-2080,-2059,-2018,
--1952,-1878,-1813,-1755,-1689,-1607,-1517,-1436,-1378,-1343,-1322,-1300,-1274,-1247,-1219,-1182,-1129,-1061,-985,-904,-816,
--726,-644,-581,-539,-513,-501,-499,-496,-480,-451,-426,-418,-427,-441,-452,-461,-465,-452,-423,-386,-351,
--307,-235,-142,-62,-29,-43,-70,-75,-46,7,68,127,177,215,242,264,287,309,326,329,317,
-300,290,295,315,349,397,461,534,601,653,697,747,812,884,956,1029,1105,1185,1264,1346,1443,
-1566,1708,1848,1968,2062,2139,2209,2274,2329,2372,2412,2459,2515,2572,2624,2676,2739,2815,2892,2960,3015,
-3061,3091,3098,3085,3069,3062,3067,3076,3092,3116,3148,3181,3214,3254,3313,3389,3474,3562,3651,3738,3821,
-3904,3991,4087,4187,4284,4372,4450,4521,4585,4643,4688,4713,4716,4712,4718,4742,4776,4813,4848,4877,4889,
-4879,4855,4838,4832,4828,4819,4816,4827,4832,4790,4680,4531,4399,4322,4306,4331,4374,4409,4425,4427,4435,
-4467,4514,4555,4577,4580,4575,4566,4557,4553,4559,4580,4612,4653,4696,4730,4749,4757,4767,4789,4821,4860,
-4908,4964,5013,5030,5006,4963,4934,4939,4963,4978,4966,4931,4892,4874,4888,4937,5003,5060,5091,5099,5106,
-5140,5206,5284,5352,5399,5434,5467,5491,5497,5483,5461,5447,5438,5426,5401,5367,5339,5327,5333,5345,5352,
-5352,5350,5354,5363,5369,5367,5363,5362,5363,5359,5350,5338,5324,5303,5275,5250,5231,5210,5180,5145,5117,
-5101,5086,5061,5028,4997,4973,4955,4944,4949,4974,5005,5024,5031,5045,5083,5141,5189,5202,5180,5152,5150,
-5170,5174,5129,5048,4969,4881,4685,4267,3642,3001,2591,2529,2723,2978,3156,3244,3290,3322,3328,3297,3244,
-3191,3142,3087,3016,2934,2852,2776,2703,2627,2548,2470,2397,2331,2269,2207,2147,2090,2032,1966,1893,1825,
-1767,1714,1659,1605,1565,1541,1523,1497,1459,1416,1374,1329,1281,1230,1183,1143,1115,1100,1097,1096,1086,
-1068,1045,1021,993,961,930,900,866,825,780,737,698,658,620,589,567,542,506,466,439,434,
-437,424,387,336,288,250,221,197,178,162,145,124,101,77,50,20,-13,-47,-77,-102,-129,
--163,-205,-244,-275,-300,-327,-355,-377,-383,-380,-380,-388,-398,-398,-388,-383,-401,-449,-509,-559,-584,
--589,-600,-632,-680,-722,-749,-768,-791,-819,-840,-849,-855,-865,-881,-896,-912,-929,-946,-961,-972,-985,
--1002,-1021,-1037,-1053,-1071,-1090,-1106,-1116,-1125,-1133,-1141,-1146,-1151,-1160,-1174,-1190,-1203,-1214,-1220,-1222,-1224,
--1233,-1252,-1271,-1280,-1275,-1265,-1260,-1259,-1258,-1254,-1250,-1250,-1252,-1251,-1245,-1234,-1223,-1213,-1205,-1195,-1184,
--1173,-1166,-1161,-1154,-1144,-1131,-1117,-1102,-1085,-1071,-1064,-1061,-1057,-1049,-1041,-1035,-1031,-1026,-1018,-1012,-1006,
--995,-980,-963,-950,-938,-923,-905,-889,-877,-866,-852,-837,-823,-809,-793,-775,-759,-743,-728,-711,-695,
--683,-671,-658,-644,-631,-618,-605,-591,-578,-568,-558,-545,-530,-519,-511,-504,-495,-488,-485,-485,-485,
--483,-478,-472,-466,-462,-460,-458,-455,-450,-444,-437,-429,-422,-421,-425,-430,-431,-425,-421,-422,-427,
--429,-426,-421,-415,-409,-405,-401,-399,-397,-394,-391,-386,-380,-372,-362,-352,-342,-331,-321,-315,-310,
--305,-298,-292,-288,-283,-277,-273,-270,-265,-252,-236,-226,-223,-219,-207,-190,-179,-176,-173,-165,-153,
--141,-130,-123,-121,-123,-122,-113,-97,-86,-82,-79,-69,-53,-37,-23,-11,-2,0,-1,4,21,
-39,50,55,62,70,75,75,79,92,107,115,118,122,132,145,158,171,184,196,208,217,
-222,225,231,248,273,294,305,312,326,338,337,330,344,391,446,468,455,444,468,519,560,
-577,584,597,608,607,609,642,709,774,799,785,771,786,827,870,901,927,956,983,1003,1026,
-1064,1116,1162,1197,1230,1279,1337,1384,1412,1433,1466,1519,1588,1668,1747,1804,1828,1832,1841,1860,1874,
-1871,1852,1804,1685,1485,1308,1356,1760,2428,3066,3405,3408,3268,3210,3319,3525,3724,3868,3969,4050,4121,
-4186,4243,4288,4317,4336,4340,4281,4085,3732,3316,2994,2853,2834,2801,2681,2518,2404,2376,2399,2422,2431,
-2435,2436,2427,2402,2363,2312,2248,2178,2112,2059,2015,1969,1916,1862,1810,1758,1702,1638,1566,1481,1381,
-1269,1155,1050,960,880,803,727,654,582,509,433,361,300,250,206,166,135,111,83,41,-1,
--18,3,49,89,115,137,159,165,141,90,37,-5,-47,-106,-188,-269,-316,-316,-295,-291,-321,
--360,-369,-344,-318,-330,-386,-459,-526,-585,-643,-702,-759,-814,-868,-915,-947,-964,-977,-994,-1017,-1043,
--1072,-1103,-1129,-1141,-1141,-1136,-1130,-1116,-1085,-1042,-1001,-975,-962,-954,-943,-930,-917,-906,-896,-883,-867,
--852,-837,-821,-801,-783,-771,-764,-755,-739,-717,-694,-674,-657,-646,-638,-632,-624,-617,-615,-616,-613,
--604,-593,-587,-584,-578,-568,-556,-545,-532,-514,-497,-485,-472,-456,-436,-420,-407,-390,-366,-339,-314,
--289,-257,-222,-188,-159,-130,-100,-70,-45,-21,4,29,52,73,99,128,157,182,209,238,267,
-294,321,352,386,419,450,482,517,550,580,609,639,669,699,730,763,797,828,858,892,926,
-954,979,1013,1063,1114,1148,1163,1175,1195,1217,1227,1226,1225,1232,1245,1257,1266,1274,1282,1288,1291,
-1294,1299,1306,1313,1320,1327,1333,1341,1351,1360,1369,1377,1387,1398,1407,1418,1432,1451,1468,1482,1500,
-1525,1552,1572,1584,1598,1617,1638,1655,1671,1694,1721,1745,1767,1793,1827,1862,1888,1910,1935,1961,1989,
-2013,2031,2050,2076,2103,2127,2150,2175,2200,2224,2249,2282,2321,2356,2388,2428,2484,2546,2601,2649,2701,
-2751,2774,2751,2691,2617,2542,2467,2397,2347,2330,2335,2343,2347,2348,2349,2346,2341,2338,2340,2342,2338,
-2340,2364,2413,2469,2515,2558,2619,2709,2816,2910,2971,2999,3010,3022,3044,3071,3101,3134,3175,3227,3281,
-3322,3331,3297,3223,3132,3047,2981,2927,2872,2815,2768,2737,2717,2700,2688,2687,2689,2681,2658,2632,2608,
-2580,2533,2472,2418,2381,2357,2338,2328,2332,2337,2325,2295,2264,2241,2216,2173,2115,2057,2005,1949,1886,
-1840,1835,1871,1925,1979,2021,2037,2010,1951,1895,1870,1859,1814,1715,1587,1468,1374,1300,1260,1274,1329,
-1367,1332,1228,1108,1026,989,975,965,961,967,979,991,990,960,891,799,718,673,647,606,539,
-477,454,472,494,485,449,408,376,352,332,319,314,306,289,269,257,254,251,241,229,213,
-177,117,65,81,193,371,551,684,760,790,793,789,796,813,814,779,719,665,627,578,489,
-367,247,154,87,38,10,4,3,-14,-50,-82,-89,-78,-65,-58,-48,-28,-9,-4,-12,-23,
--27,-24,-19,-14,-10,-6,0,10,22,32,39,44,50,54,52,37,12,-14,-38,-52,-59,
--61,-61,-61,-56,-47,-39,-38,-43,-50,-49,-40,-31,-32,-41,-53,-57,-57,-63,-78,-98,-110,
--113,-115,-126,-142,-155,-159,-159,-165,-179,-198,-217,-236,-258,-283,-308,-328,-344,-363,-390,-424,-455,
--476,-490,-507,-534,-569,-609,-650,-694,-741,-787,-832,-875,-919,-964,-1009,-1051,-1092,-1133,-1180,-1236,-1297,
--1356,-1408,-1453,-1497,-1544,-1591,-1640,-1694,-1754,-1816,-1875,-1931,-1984,-2034,-2080,-2124,-2167,-2213,-2259,-2306,-2357,
--2415,-2471,-2515,-2545,-2570,-2600,-2638,-2679,-2719,-2756,-2793,-2829,-2867,-2906,-2945,-2981,-3017,-3055,-3096,-3141,-3188,
--3234,-3279,-3319,-3349,-3371,-3388,-3402,-3411,-3411,-3401,-3379,-3356,-3357,-3399,-3480,-3573,-3646,-3695,-3736,-3788,-3847,
--3905,-3955,-3996,-4025,-4036,-4039,-4050,-4081,-4122,-4156,-4176,-4192,-4211,-4228,-4237,-4239,-4244,-4256,-4274,-4292,-4311,
--4328,-4341,-4346,-4348,-4353,-4362,-4372,-4378,-4381,-4381,-4381,-4379,-4377,-4372,-4363,-4346,-4325,-4302,-4279,-4255,-4231,
--4209,-4191,-4173,-4147,-4111,-4073,-4045,-4030,-4022,-4009,-3984,-3951,-3913,-3873,-3833,-3799,-3785,-3798,-3820,-3818,-3768,
--3688,-3633,-3640,-3692,-3725,-3691,-3599,-3500,-3433,-3392,-3356,-3317,-3290,-3285,-3297,-3317,-3337,-3352,-3345,-3300,-3218,
--3112,-2996,-2872,-2739,-2606,-2480,-2364,-2258,-2176,-2130,-2117,-2108,-2075,-2011,-1935,-1868,-1811,-1752,-1680,-1599,-1525,
--1475,-1451,-1444,-1438,-1421,-1393,-1356,-1312,-1256,-1186,-1104,-1014,-919,-824,-738,-669,-618,-585,-572,-572,-569,
--550,-516,-487,-481,-496,-517,-536,-549,-552,-538,-507,-469,-431,-383,-307,-212,-134,-107,-129,-167,-186,
--173,-132,-75,-10,54,110,157,200,244,288,321,335,330,315,304,304,318,344,384,439,503,
-565,615,659,708,766,829,894,962,1038,1115,1189,1263,1352,1465,1596,1727,1841,1936,2018,2093,2160,
-2216,2259,2298,2343,2398,2458,2517,2578,2648,2721,2790,2846,2891,2925,2943,2942,2932,2929,2940,2958,2974,
-2990,3012,3042,3074,3111,3162,3233,3318,3404,3487,3568,3648,3723,3796,3879,3977,4083,4183,4268,4343,4418,
-4494,4567,4623,4655,4664,4666,4674,4693,4717,4742,4771,4801,4821,4822,4808,4792,4783,4774,4762,4762,4781,
-4802,4784,4694,4542,4378,4261,4225,4265,4336,4383,4381,4347,4329,4352,4404,4452,4480,4491,4498,4504,4510,
-4514,4517,4522,4543,4594,4673,4747,4781,4769,4741,4735,4761,4804,4850,4898,4941,4964,4959,4933,4907,4897,
-4899,4901,4894,4875,4851,4832,4837,4876,4937,4992,5022,5032,5045,5081,5141,5210,5273,5323,5364,5399,5428,
-5443,5438,5418,5395,5381,5377,5373,5357,5331,5311,5310,5324,5336,5335,5327,5329,5343,5358,5362,5356,5347,
-5340,5330,5317,5302,5285,5262,5234,5211,5194,5177,5152,5120,5095,5078,5059,5028,4994,4968,4954,4942,4932,
-4936,4962,4994,5012,5013,5024,5067,5132,5181,5189,5163,5141,5147,5164,5150,5085,4995,4914,4811,4576,4122,
-3505,2935,2629,2644,2855,3081,3225,3299,3345,3372,3364,3321,3265,3212,3158,3093,3016,2933,2850,2771,2697,
-2625,2551,2471,2393,2323,2260,2197,2134,2074,2019,1960,1894,1825,1761,1705,1652,1601,1561,1535,1516,1490,
-1453,1410,1368,1326,1277,1223,1169,1125,1097,1084,1079,1073,1060,1043,1025,1004,977,945,916,892,864,
-826,781,737,697,656,614,580,554,527,489,448,419,410,407,391,357,315,277,245,217,190,
-167,146,125,100,75,54,34,13,-15,-50,-83,-111,-136,-169,-210,-250,-275,-284,-290,-309,-339,
--368,-382,-383,-380,-386,-402,-422,-439,-455,-480,-514,-545,-557,-548,-544,-570,-625,-684,-725,-751,-775,
--803,-828,-843,-853,-864,-877,-892,-909,-930,-954,-973,-985,-995,-1009,-1026,-1043,-1060,-1082,-1104,-1122,-1131,
--1138,-1145,-1152,-1156,-1159,-1164,-1174,-1185,-1197,-1209,-1222,-1231,-1237,-1242,-1248,-1255,-1258,-1258,-1258,-1262,-1268,
--1271,-1271,-1268,-1266,-1263,-1259,-1253,-1246,-1236,-1225,-1214,-1201,-1187,-1175,-1166,-1162,-1159,-1153,-1143,-1131,-1116,
--1100,-1088,-1080,-1075,-1070,-1062,-1052,-1045,-1037,-1029,-1022,-1017,-1010,-996,-976,-957,-944,-936,-925,-909,-894,
--882,-873,-862,-848,-833,-816,-800,-783,-769,-754,-738,-721,-706,-694,-681,-667,-652,-641,-631,-619,-604,
--591,-581,-571,-557,-541,-528,-521,-517,-512,-508,-505,-504,-502,-498,-493,-491,-488,-485,-481,-477,-474,
--468,-460,-449,-438,-432,-432,-438,-443,-442,-436,-431,-432,-437,-441,-439,-433,-427,-422,-418,-413,-408,
--402,-397,-392,-388,-380,-370,-360,-351,-341,-330,-319,-310,-304,-297,-289,-282,-277,-273,-269,-266,-263,
--255,-241,-225,-216,-215,-213,-203,-189,-179,-176,-172,-165,-155,-144,-134,-124,-118,-114,-111,-102,-92,
--85,-80,-68,-51,-37,-28,-19,-3,14,21,18,18,31,48,58,62,69,81,91,90,87,
-90,100,109,113,119,130,145,160,172,182,194,210,227,239,242,242,250,271,294,309,321,
-336,353,360,361,374,413,459,478,468,462,489,541,582,598,603,617,634,641,643,662,706,
-757,785,788,790,811,845,878,904,931,962,990,1012,1038,1080,1129,1167,1190,1218,1267,1328,1376,
-1403,1429,1471,1534,1607,1683,1755,1807,1829,1830,1835,1849,1857,1847,1823,1777,1668,1480,1317,1382,1812,
-2515,3189,3555,3573,3434,3363,3450,3640,3836,3981,4061,4088,4096,4124,4190,4268,4318,4326,4292,4185,3953,
-3596,3219,2961,2873,2868,2816,2675,2513,2419,2410,2440,2464,2477,2487,2489,2469,2430,2383,2332,2272,2201,
-2132,2076,2030,1984,1931,1880,1834,1787,1731,1662,1583,1496,1396,1282,1164,1057,970,895,823,748,675,
-606,539,470,406,352,306,262,219,184,162,146,124,98,85,96,126,164,208,256,298,310,
-275,201,117,44,-15,-78,-154,-232,-288,-303,-291,-284,-302,-332,-343,-326,-308,-324,-382,-466,-556,
--644,-729,-805,-871,-929,-984,-1029,-1056,-1066,-1070,-1079,-1093,-1110,-1128,-1147,-1161,-1162,-1147,-1124,-1103,-1086,
--1066,-1039,-1008,-977,-953,-935,-921,-909,-896,-884,-871,-858,-843,-828,-813,-799,-785,-775,-771,-769,-760,
--740,-711,-683,-660,-643,-631,-623,-617,-611,-607,-605,-604,-596,-582,-567,-559,-557,-553,-543,-531,-518,
--503,-484,-466,-450,-435,-416,-395,-378,-365,-350,-325,-296,-267,-238,-205,-169,-134,-104,-73,-41,-11,
-13,36,60,83,103,123,147,176,205,231,257,286,315,341,367,395,426,457,487,517,548,
-579,608,638,667,696,724,755,789,822,851,879,911,947,978,1007,1042,1086,1130,1161,1178,1194,
-1216,1234,1240,1235,1235,1243,1256,1266,1273,1281,1290,1297,1300,1305,1313,1322,1330,1335,1339,1345,1354,
-1364,1373,1380,1389,1402,1415,1426,1435,1446,1463,1482,1499,1517,1542,1567,1587,1603,1622,1648,1676,1700,
-1722,1747,1775,1799,1820,1845,1876,1903,1922,1938,1961,1973,1998,2020,2035,2054,2081,2111,2138,2161,2186,
-2212,2236,2262,2295,2331,2363,2390,2426,2476,2534,2586,2638,2700,2767,2807,2794,2729,2642,2555,2475,2405,
-2359,2348,2360,2372,2372,2366,2365,2368,2369,2365,2358,2353,2351,2355,2374,2415,2471,2528,2578,2629,2699,
-2794,2898,2980,3022,3033,3039,3060,3094,3130,3164,3201,3248,3298,3336,3345,3314,3244,3152,3060,2988,2934,
-2885,2834,2785,2749,2730,2721,2719,2719,2717,2705,2686,2668,2651,2626,2578,2515,2456,2415,2391,2378,2375,
-2384,2389,2376,2344,2315,2301,2291,2267,2224,2173,2120,2060,2002,1969,1975,2007,2038,2056,2062,2049,2005,
-1940,1895,1905,1947,1957,1897,1782,1653,1530,1415,1333,1319,1370,1425,1411,1315,1192,1102,1062,1049,1038,
-1028,1027,1034,1041,1033,998,931,848,778,740,715,669,595,527,503,521,538,523,480,435,403,
-381,360,342,332,325,313,299,291,290,286,275,264,252,227,177,122,109,177,326,512,679,
-783,813,798,786,809,848,855,807,735,681,652,607,513,388,274,195,141,97,70,63,63,
-48,17,-8,-13,-3,5,9,17,28,36,34,26,19,14,10,8,11,21,33,45,58,
-67,69,67,68,76,86,87,73,52,32,17,5,-4,-10,-11,-9,-4,1,5,5,3,
-3,9,19,22,13,-1,-11,-13,-13,-21,-37,-53,-60,-61,-64,-75,-88,-93,-92,-93,-102,
--118,-138,-159,-181,-203,-224,-244,-266,-293,-321,-347,-370,-391,-411,-429,-447,-469,-498,-536,-580,-625,
--670,-716,-762,-805,-845,-883,-923,-967,-1014,-1061,-1111,-1165,-1221,-1275,-1323,-1367,-1412,-1459,-1509,-1562,-1618,
--1676,-1733,-1788,-1844,-1900,-1953,-2001,-2043,-2086,-2131,-2179,-2233,-2293,-2353,-2403,-2435,-2455,-2477,-2510,-2553,-2599,
--2642,-2682,-2721,-2761,-2800,-2838,-2874,-2908,-2942,-2978,-3018,-3060,-3105,-3155,-3206,-3250,-3283,-3304,-3320,-3336,-3347,
--3347,-3332,-3303,-3274,-3270,-3311,-3395,-3494,-3578,-3637,-3684,-3735,-3789,-3843,-3892,-3936,-3970,-3988,-3994,-4004,-4032,
--4071,-4106,-4131,-4152,-4173,-4190,-4201,-4209,-4220,-4236,-4251,-4265,-4278,-4293,-4306,-4313,-4316,-4321,-4330,-4339,-4346,
--4349,-4349,-4347,-4343,-4338,-4330,-4319,-4303,-4286,-4269,-4251,-4231,-4206,-4180,-4160,-4143,-4123,-4093,-4057,-4026,-4009,
--4000,-3989,-3969,-3940,-3908,-3872,-3827,-3780,-3751,-3761,-3799,-3823,-3796,-3725,-3662,-3656,-3701,-3740,-3727,-3664,-3590,
--3533,-3489,-3441,-3391,-3356,-3341,-3340,-3345,-3354,-3361,-3351,-3304,-3223,-3119,-3003,-2876,-2741,-2606,-2482,-2372,-2274,
--2199,-2160,-2153,-2151,-2124,-2065,-1991,-1921,-1859,-1798,-1731,-1659,-1594,-1549,-1533,-1538,-1548,-1545,-1524,-1492,-1452,
--1401,-1335,-1254,-1162,-1066,-970,-880,-801,-736,-692,-669,-660,-649,-623,-586,-556,-550,-565,-589,-613,-631,
--638,-625,-593,-553,-510,-456,-379,-289,-217,-191,-208,-242,-265,-267,-246,-199,-132,-54,18,81,137,
-194,251,298,327,333,324,314,313,325,347,379,420,467,515,560,605,654,707,761,817,881,
-955,1037,1119,1201,1291,1393,1502,1608,1705,1793,1877,1956,2027,2085,2129,2167,2210,2263,2324,2390,2459,
-2535,2610,2672,2715,2744,2765,2778,2782,2785,2799,2827,2857,2879,2894,2912,2937,2968,3011,3073,3155,3246,
-3330,3408,3481,3553,3620,3689,3770,3871,3979,4077,4159,4234,4313,4396,4474,4536,4577,4601,4614,4627,4640,
-4655,4672,4696,4725,4749,4760,4757,4750,4743,4731,4712,4699,4709,4736,4747,4699,4576,4409,4264,4203,4235,
-4310,4351,4323,4260,4221,4239,4294,4349,4387,4414,4435,4453,4468,4476,4472,4456,4458,4517,4639,4767,4825,
-4793,4721,4682,4702,4753,4803,4838,4866,4887,4898,4898,4890,4877,4859,4843,4832,4824,4810,4793,4789,4816,
-4870,4924,4956,4970,4985,5019,5073,5138,5203,5259,5302,5335,5364,5390,5402,5390,5362,5341,5343,5356,5354,
-5325,5288,5275,5293,5317,5323,5313,5306,5316,5331,5336,5325,5310,5296,5284,5271,5258,5244,5225,5202,5179,
-5163,5148,5127,5101,5076,5056,5031,4998,4967,4949,4942,4935,4925,4927,4952,4984,4999,4997,5007,5050,5115,
-5162,5166,5143,5129,5140,5153,5128,5056,4970,4892,4771,4498,4015,3411,2903,2673,2736,2948,3150,3276,3346,
-3391,3408,3388,3345,3296,3246,3183,3103,3017,2932,2847,2761,2683,2616,2549,2471,2388,2313,2249,2185,2117,
-2051,1996,1948,1893,1826,1758,1698,1645,1597,1557,1528,1506,1479,1441,1397,1353,1311,1265,1212,1157,1110,
-1078,1062,1054,1046,1033,1018,1004,985,957,924,895,873,848,814,773,735,698,657,613,573,545,
-518,482,439,403,381,366,346,318,289,262,238,212,187,164,143,119,91,63,40,22,5,
--18,-50,-85,-116,-143,-172,-208,-243,-264,-266,-262,-271,-304,-351,-390,-403,-394,-385,-395,-427,-465,
--494,-511,-527,-541,-541,-522,-505,-523,-579,-648,-701,-732,-755,-781,-806,-824,-838,-854,-872,-889,-906,
--928,-955,-977,-992,-1002,-1015,-1030,-1045,-1062,-1083,-1107,-1126,-1137,-1143,-1150,-1158,-1164,-1168,-1174,-1182,-1190,
--1198,-1207,-1218,-1230,-1241,-1249,-1255,-1258,-1259,-1259,-1260,-1263,-1266,-1269,-1272,-1274,-1274,-1271,-1268,-1265,-1261,
--1253,-1241,-1226,-1210,-1193,-1175,-1160,-1151,-1147,-1143,-1136,-1128,-1120,-1112,-1104,-1096,-1088,-1081,-1072,-1064,-1056,
--1048,-1039,-1032,-1027,-1019,-1003,-981,-959,-947,-940,-932,-918,-904,-893,-885,-876,-861,-843,-823,-805,-789,
--776,-764,-751,-736,-723,-710,-697,-681,-665,-654,-645,-634,-620,-606,-596,-585,-570,-553,-540,-534,-532,
--528,-524,-521,-516,-511,-505,-504,-506,-508,-505,-498,-492,-488,-482,-472,-459,-447,-442,-444,-451,-456,
--455,-449,-444,-444,-448,-449,-446,-441,-435,-431,-427,-422,-414,-405,-397,-391,-384,-375,-364,-354,-347,
--339,-328,-315,-304,-297,-291,-285,-278,-271,-266,-263,-261,-258,-248,-233,-220,-215,-216,-213,-203,-190,
--180,-173,-164,-154,-146,-141,-135,-125,-114,-104,-95,-87,-83,-82,-78,-63,-43,-32,-33,-32,-16,
-7,21,22,23,35,51,58,58,65,84,104,110,106,102,105,111,116,122,134,151,166,
-175,180,187,204,229,253,264,261,259,266,280,293,303,319,342,364,381,398,425,452,463,
-457,456,479,515,541,551,567,609,666,705,712,706,713,742,777,802,819,834,851,869,892,
-924,960,991,1016,1048,1093,1139,1170,1186,1211,1260,1321,1369,1401,1437,1492,1562,1633,1700,1762,1810,
-1831,1833,1838,1853,1862,1851,1823,1772,1661,1480,1329,1405,1835,2526,3188,3566,3625,3541,3507,3590,3745,
-3900,4017,4083,4098,4093,4117,4191,4279,4323,4294,4201,4040,3792,3467,3149,2939,2863,2843,2782,2661,2542,
-2484,2485,2505,2516,2524,2530,2524,2492,2442,2388,2337,2280,2212,2145,2089,2042,1994,1943,1896,1855,1812,
-1753,1678,1596,1510,1415,1304,1187,1081,997,925,851,769,686,611,545,484,433,393,361,324,279,
-235,204,189,183,180,181,189,204,232,275,329,376,390,357,281,185,87,3,-67,-132,-193,
--237,-251,-236,-220,-229,-262,-297,-313,-321,-346,-405,-496,-607,-724,-831,-918,-983,-1036,-1083,-1118,-1133,
--1129,-1122,-1121,-1126,-1135,-1149,-1169,-1187,-1188,-1165,-1127,-1092,-1070,-1057,-1041,-1014,-978,-944,-920,-906,-894,
--880,-863,-846,-829,-811,-793,-777,-764,-756,-751,-752,-750,-739,-716,-688,-663,-644,-628,-616,-607,-602,
--597,-593,-590,-587,-578,-561,-542,-529,-523,-518,-510,-500,-488,-474,-455,-436,-419,-403,-383,-362,-345,
--332,-316,-291,-260,-230,-202,-172,-138,-105,-72,-40,-8,20,44,67,92,117,140,161,186,215,
-244,270,295,322,350,375,400,426,454,484,512,541,571,601,631,662,693,723,752,782,816,
-848,877,903,933,967,1002,1036,1070,1107,1142,1168,1187,1206,1226,1239,1241,1239,1244,1257,1270,1279,
-1285,1293,1302,1309,1313,1319,1327,1336,1342,1346,1349,1355,1363,1373,1382,1392,1404,1419,1435,1447,1455,
-1466,1484,1506,1527,1548,1570,1593,1613,1632,1654,1682,1711,1736,1759,1783,1809,1833,1854,1878,1904,1925,
-1939,1953,1973,1984,2006,2025,2041,2063,2093,2126,2156,2182,2207,2230,2251,2272,2302,2335,2366,2392,2424,
-2470,2523,2575,2633,2707,2786,2832,2814,2740,2646,2560,2485,2419,2373,2361,2377,2395,2397,2391,2391,2398,
-2401,2391,2376,2369,2372,2380,2394,2424,2477,2542,2600,2643,2690,2765,2867,2963,3021,3038,3045,3072,3117,
-3161,3195,3228,3273,3327,3371,3382,3350,3276,3173,3068,2984,2929,2890,2848,2802,2764,2745,2745,2754,2760,
-2755,2739,2719,2702,2687,2661,2614,2554,2500,2465,2447,2440,2441,2448,2449,2430,2399,2375,2372,2378,2372,
-2343,2296,2238,2175,2125,2109,2126,2149,2151,2133,2111,2085,2038,1976,1944,1982,2068,2126,2096,1982,1828,
-1664,1511,1400,1372,1429,1501,1506,1418,1290,1189,1138,1116,1100,1087,1084,1089,1089,1071,1028,963,890,
-834,806,787,743,668,591,553,556,567,551,510,466,432,405,379,356,342,334,324,315,311,
-314,314,308,300,293,278,245,198,169,197,304,473,652,778,819,803,793,828,886,903,856,
-779,721,685,626,520,392,289,229,191,155,126,114,111,99,76,58,53,57,60,63,68,
-73,73,67,62,62,58,49,42,45,59,76,92,104,111,110,104,102,110,118,117,104,
-88,76,66,53,38,29,30,37,42,44,45,46,49,52,55,54,48,37,27,24,28,
-30,24,13,2,-3,-7,-14,-22,-28,-29,-30,-36,-50,-66,-82,-102,-125,-148,-166,-185,-212,
--247,-279,-298,-306,-318,-340,-366,-388,-407,-431,-466,-510,-556,-600,-645,-691,-734,-771,-806,-845,-891,
--941,-992,-1042,-1093,-1144,-1193,-1238,-1281,-1324,-1371,-1424,-1482,-1541,-1599,-1652,-1704,-1760,-1817,-1871,-1917,-1960,
--2005,-2054,-2108,-2166,-2226,-2280,-2320,-2344,-2363,-2390,-2430,-2477,-2524,-2568,-2610,-2652,-2694,-2732,-2768,-2799,-2830,
--2864,-2901,-2940,-2980,-3024,-3077,-3133,-3182,-3214,-3232,-3247,-3265,-3277,-3276,-3254,-3219,-3187,-3184,-3227,-3313,-3417,
--3509,-3578,-3631,-3679,-3728,-3777,-3829,-3879,-3920,-3941,-3948,-3958,-3983,-4020,-4054,-4079,-4101,-4123,-4143,-4160,-4175,
--4192,-4210,-4223,-4234,-4246,-4262,-4277,-4288,-4293,-4299,-4306,-4314,-4320,-4323,-4324,-4322,-4316,-4306,-4294,-4281,-4268,
--4256,-4243,-4226,-4201,-4168,-4135,-4111,-4098,-4087,-4069,-4042,-4014,-3994,-3980,-3965,-3940,-3913,-3890,-3870,-3839,-3790,
--3740,-3721,-3744,-3783,-3793,-3763,-3721,-3707,-3726,-3747,-3742,-3711,-3674,-3639,-3594,-3535,-3475,-3432,-3410,-3398,-3390,
--3385,-3380,-3356,-3299,-3214,-3114,-3008,-2888,-2754,-2617,-2493,-2386,-2298,-2233,-2199,-2192,-2189,-2165,-2113,-2043,-1970,
--1898,-1828,-1761,-1695,-1637,-1596,-1582,-1595,-1617,-1628,-1619,-1597,-1567,-1526,-1468,-1392,-1306,-1217,-1129,-1040,-954,
--879,-822,-785,-759,-733,-700,-665,-640,-632,-640,-658,-679,-699,-709,-700,-671,-631,-586,-530,-461,-386,
--326,-294,-286,-289,-295,-299,-290,-256,-193,-114,-39,21,72,125,185,244,291,315,317,310,305,
-312,327,349,374,403,436,473,517,567,617,666,717,780,859,952,1051,1150,1247,1338,1420,1494,
-1564,1639,1720,1803,1880,1944,1992,2031,2072,2123,2182,2246,2315,2391,2465,2524,2560,2580,2596,2616,2636,
-2658,2687,2723,2759,2787,2805,2821,2842,2875,2926,2997,3081,3163,3236,3303,3373,3445,3519,3595,3683,3783,
-3884,3975,4054,4133,4215,4296,4369,4431,4482,4520,4545,4560,4569,4579,4595,4617,4646,4672,4689,4697,4700,
-4701,4694,4676,4654,4644,4658,4681,4672,4593,4445,4289,4202,4216,4281,4312,4267,4185,4134,4146,4197,4254,
-4302,4344,4376,4397,4411,4419,4411,4386,4380,4449,4604,4771,4846,4797,4690,4626,4641,4700,4754,4786,4806,
-4827,4847,4860,4864,4854,4831,4805,4792,4789,4779,4758,4742,4757,4805,4862,4902,4920,4934,4959,5004,5068,
-5141,5205,5247,5272,5296,5329,5358,5358,5331,5304,5305,5327,5334,5304,5258,5237,5258,5296,5316,5310,5295,
-5292,5296,5294,5280,5264,5252,5242,5231,5220,5209,5196,5176,5153,5134,5116,5096,5074,5051,5031,5007,4979,
-4953,4939,4932,4923,4915,4921,4946,4972,4981,4976,4985,5029,5091,5134,5137,5118,5110,5122,5131,5104,5041,
-4968,4888,4740,4429,3927,3348,2899,2728,2817,3020,3200,3311,3378,3419,3428,3403,3365,3327,3281,3209,3118,
-3026,2940,2852,2759,2675,2608,2546,2470,2383,2303,2238,2177,2106,2036,1982,1941,1896,1832,1761,1695,1641,
-1594,1553,1521,1497,1469,1429,1380,1332,1289,1247,1201,1149,1100,1063,1041,1028,1016,1003,991,981,965,
-939,904,873,847,822,790,756,725,696,658,612,568,536,510,478,436,393,358,332,310,287,
-267,247,227,206,186,167,147,123,95,67,42,21,4,-14,-41,-74,-109,-140,-167,-195,-221,
--242,-249,-250,-258,-288,-338,-388,-409,-392,-361,-353,-387,-445,-493,-516,-525,-532,-532,-518,-502,-512,
--559,-624,-678,-711,-733,-757,-780,-798,-815,-837,-863,-885,-904,-924,-947,-969,-986,-1001,-1016,-1033,-1049,
--1064,-1084,-1108,-1127,-1137,-1142,-1147,-1155,-1164,-1173,-1183,-1195,-1205,-1212,-1215,-1219,-1226,-1237,-1250,-1263,-1271,
--1273,-1271,-1267,-1263,-1260,-1260,-1265,-1273,-1276,-1276,-1275,-1275,-1275,-1269,-1258,-1245,-1229,-1210,-1186,-1164,-1148,
--1137,-1128,-1120,-1115,-1114,-1113,-1108,-1099,-1090,-1082,-1077,-1071,-1065,-1058,-1051,-1045,-1040,-1033,-1018,-998,-977,
--964,-956,-946,-932,-918,-908,-899,-888,-873,-853,-832,-813,-796,-784,-773,-762,-749,-737,-725,-713,-698,
--683,-671,-661,-650,-636,-623,-611,-599,-585,-569,-556,-550,-546,-542,-539,-535,-529,-521,-515,-515,-519,
--521,-518,-510,-503,-499,-493,-484,-472,-461,-455,-456,-461,-465,-465,-462,-459,-459,-460,-458,-452,-445,
--439,-435,-430,-424,-415,-404,-395,-387,-378,-368,-357,-348,-343,-338,-328,-314,-301,-295,-294,-292,-285,
--274,-266,-262,-261,-256,-246,-232,-224,-221,-217,-207,-192,-179,-169,-158,-143,-128,-121,-121,-121,-115,
--105,-93,-81,-71,-67,-71,-72,-62,-46,-38,-42,-45,-32,-9,5,9,15,31,50,55,52,
-57,79,106,122,125,126,131,138,143,148,157,169,182,189,192,194,204,227,254,273,275,
-268,266,274,282,287,294,313,344,377,402,421,433,437,437,444,459,475,479,482,512,587,
-685,758,774,751,732,746,786,824,842,843,840,848,873,910,950,986,1017,1055,1102,1146,1173,
-1187,1209,1254,1312,1366,1411,1462,1527,1596,1656,1709,1759,1798,1818,1824,1837,1864,1886,1884,1851,1780,
-1647,1459,1322,1412,1831,2477,3091,3460,3575,3584,3626,3728,3842,3934,4010,4074,4118,4146,4186,4250,4306,
-4304,4223,4082,3896,3663,3388,3122,2930,2834,2788,2736,2665,2602,2572,2567,2565,2558,2553,2548,2529,2487,
-2432,2377,2325,2270,2211,2154,2105,2058,2007,1954,1908,1869,1827,1768,1693,1611,1528,1436,1330,1218,1117,
-1036,964,883,789,692,608,540,486,444,417,397,371,330,280,240,221,226,245,266,280,288,
-301,328,366,398,411,394,346,264,157,47,-42,-103,-142,-166,-175,-165,-156,-172,-222,-285,-336,
--370,-406,-468,-566,-692,-823,-936,-1018,-1072,-1111,-1142,-1161,-1161,-1147,-1133,-1127,-1129,-1136,-1152,-1177,-1200,
--1202,-1175,-1130,-1090,-1069,-1062,-1052,-1026,-988,-949,-923,-908,-895,-878,-859,-840,-820,-797,-771,-749,-732,
--722,-717,-715,-709,-697,-677,-655,-637,-621,-606,-592,-582,-578,-574,-569,-565,-563,-557,-543,-523,-505,
--493,-485,-478,-469,-459,-445,-427,-408,-391,-373,-353,-330,-311,-296,-277,-250,-219,-189,-162,-134,-102,
--71,-40,-9,20,47,70,93,118,146,172,197,223,251,279,303,326,351,377,402,427,454,
-482,510,538,567,597,627,657,687,720,751,781,810,842,875,905,933,960,991,1025,1060,1094,
-1126,1154,1177,1198,1217,1233,1241,1242,1245,1257,1272,1284,1291,1298,1307,1316,1324,1330,1336,1343,1349,
-1353,1357,1362,1367,1373,1382,1394,1407,1421,1438,1455,1469,1481,1496,1517,1541,1563,1583,1604,1625,1645,
-1664,1684,1708,1734,1756,1775,1797,1820,1843,1864,1885,1909,1930,1947,1964,1984,1995,2016,2034,2054,2079,
-2111,2144,2175,2203,2227,2245,2259,2275,2302,2338,2372,2401,2433,2474,2521,2572,2635,2717,2799,2838,2802,
-2709,2608,2534,2484,2440,2402,2389,2402,2422,2429,2423,2420,2425,2425,2413,2396,2390,2398,2409,2418,2439,
-2486,2553,2614,2652,2685,2745,2843,2947,3015,3039,3052,3087,3143,3195,3228,3257,3303,3364,3417,3432,3397,
-3313,3196,3074,2977,2918,2885,2853,2813,2775,2758,2767,2789,2804,2800,2779,2753,2731,2710,2682,2637,2586,
-2545,2523,2515,2512,2511,2510,2502,2482,2456,2443,2452,2469,2473,2452,2408,2350,2291,2253,2252,2275,2288,
-2269,2231,2203,2185,2153,2104,2081,2130,2230,2302,2275,2147,1964,1771,1597,1477,1451,1514,1598,1614,1531,
-1397,1280,1210,1173,1149,1136,1137,1142,1134,1105,1055,991,927,883,865,856,824,754,670,609,588,
-584,571,539,501,466,431,396,368,350,341,333,327,329,338,348,350,345,337,326,306,275,
-248,254,322,457,622,753,808,804,804,848,913,938,898,823,759,706,627,509,386,299,257,
-232,203,175,159,152,141,123,107,99,96,95,98,104,109,107,102,100,101,96,84,78,
-86,104,122,135,144,150,151,148,146,151,155,151,139,128,120,111,94,76,68,73,82,
-86,85,84,88,93,93,84,71,59,52,52,56,61,66,69,67,62,54,45,37,31,
-27,23,15,2,-10,-21,-32,-50,-76,-100,-117,-130,-150,-176,-199,-209,-213,-227,-260,-297,-324,
--343,-364,-398,-441,-485,-527,-571,-616,-658,-694,-729,-770,-819,-870,-921,-970,-1019,-1067,-1112,-1155,-1196,
--1240,-1287,-1343,-1406,-1470,-1528,-1578,-1627,-1680,-1736,-1787,-1832,-1877,-1927,-1984,-2043,-2101,-2154,-2197,-2228,-2250,
--2276,-2312,-2359,-2407,-2452,-2495,-2538,-2582,-2622,-2659,-2691,-2720,-2751,-2785,-2824,-2863,-2903,-2950,-3006,-3065,-3113,
--3141,-3157,-3174,-3194,-3207,-3201,-3173,-3135,-3108,-3112,-3159,-3245,-3348,-3444,-3521,-3580,-3627,-3670,-3715,-3767,-3822,
--3866,-3889,-3897,-3907,-3933,-3969,-4000,-4024,-4043,-4066,-4089,-4111,-4131,-4150,-4168,-4182,-4195,-4212,-4233,-4252,-4266,
--4274,-4279,-4285,-4291,-4296,-4298,-4299,-4295,-4287,-4274,-4260,-4248,-4239,-4230,-4214,-4185,-4141,-4094,-4055,-4037,-4036,
--4042,-4041,-4026,-4004,-3984,-3968,-3949,-3920,-3889,-3867,-3858,-3846,-3809,-3754,-3709,-3703,-3731,-3761,-3769,-3756,-3743,
--3738,-3736,-3731,-3728,-3728,-3718,-3684,-3625,-3565,-3520,-3491,-3467,-3444,-3427,-3408,-3369,-3299,-3206,-3110,-3014,-2905,
--2776,-2639,-2512,-2407,-2327,-2272,-2242,-2230,-2220,-2196,-2151,-2090,-2014,-1932,-1854,-1785,-1726,-1673,-1631,-1614,-1625,
--1652,-1670,-1669,-1653,-1629,-1593,-1538,-1466,-1390,-1316,-1242,-1162,-1082,-1009,-952,-906,-864,-823,-785,-756,-741,
--736,-737,-743,-753,-764,-769,-759,-734,-697,-653,-603,-549,-498,-454,-415,-374,-333,-301,-283,-268,-235,
--177,-108,-48,-7,24,66,127,200,267,309,319,308,291,278,272,273,279,294,318,353,399,
-451,506,559,616,687,777,881,993,1101,1198,1278,1338,1387,1437,1499,1574,1658,1740,1811,1864,1906,
-1947,1996,2052,2110,2170,2238,2309,2368,2405,2426,2448,2482,2522,2561,2594,2628,2661,2691,2714,2734,2759,
-2800,2861,2936,3012,3077,3130,3184,3251,3333,3424,3518,3615,3711,3799,3880,3959,4043,4127,4201,4263,4318,
-4371,4416,4445,4459,4466,4478,4500,4530,4563,4594,4619,4635,4643,4648,4650,4645,4625,4601,4591,4606,4619,
-4578,4455,4292,4178,4168,4224,4257,4217,4136,4083,4087,4126,4172,4218,4264,4300,4319,4328,4337,4337,4322,
-4322,4396,4558,4730,4803,4744,4629,4562,4579,4640,4695,4729,4756,4783,4804,4816,4819,4811,4791,4769,4759,
-4761,4755,4731,4705,4706,4744,4799,4845,4869,4883,4903,4944,5009,5086,5152,5189,5203,5221,5258,5298,5310,
-5287,5256,5253,5275,5289,5268,5224,5200,5218,5260,5291,5293,5280,5269,5265,5259,5248,5236,5227,5218,5205,
-5191,5177,5164,5147,5125,5103,5083,5062,5040,5020,5001,4982,4962,4942,4926,4912,4901,4898,4912,4938,4957,
-4955,4945,4957,5005,5065,5103,5106,5091,5085,5094,5098,5075,5023,4956,4861,4677,4334,3833,3301,2923,2811,
-2919,3104,3252,3339,3395,3433,3440,3415,3377,3342,3296,3222,3128,3037,2954,2867,2769,2678,2607,2545,2471,
-2383,2302,2238,2178,2110,2041,1987,1946,1902,1839,1766,1698,1641,1591,1549,1517,1491,1462,1418,1364,1312,
-1269,1232,1191,1144,1096,1057,1029,1009,990,972,959,951,942,920,888,853,824,796,766,736,711,
-687,654,609,562,525,497,467,429,385,345,312,287,266,247,227,208,191,176,162,144,122,
-96,70,45,23,5,-9,-28,-57,-93,-130,-157,-176,-190,-205,-221,-237,-255,-283,-326,-372,-395,
--378,-337,-316,-348,-414,-472,-493,-492,-495,-509,-519,-519,-526,-558,-607,-653,-684,-708,-733,-759,-778,
--795,-818,-848,-876,-897,-916,-936,-957,-977,-995,-1015,-1035,-1053,-1069,-1088,-1110,-1129,-1139,-1142,-1145,-1153,
--1165,-1177,-1190,-1204,-1218,-1227,-1231,-1230,-1231,-1237,-1249,-1263,-1273,-1275,-1272,-1266,-1260,-1257,-1258,-1265,-1274,
--1278,-1278,-1277,-1278,-1280,-1278,-1272,-1264,-1252,-1234,-1210,-1185,-1166,-1149,-1133,-1118,-1111,-1111,-1111,-1105,-1094,
--1084,-1080,-1077,-1074,-1069,-1064,-1059,-1054,-1050,-1043,-1031,-1016,-1000,-986,-975,-961,-946,-932,-920,-910,-897,
--882,-864,-845,-825,-808,-794,-783,-771,-758,-745,-734,-725,-714,-701,-688,-676,-665,-653,-641,-628,-614,
--600,-585,-573,-564,-557,-553,-552,-551,-546,-538,-531,-530,-532,-531,-526,-518,-513,-510,-505,-497,-486,
--477,-471,-468,-467,-468,-470,-470,-471,-472,-471,-467,-459,-452,-446,-440,-434,-425,-415,-403,-393,-384,
--376,-367,-357,-350,-346,-341,-332,-318,-305,-300,-303,-304,-297,-284,-273,-268,-265,-258,-245,-234,-229,
--225,-214,-192,-171,-160,-157,-149,-131,-111,-102,-105,-109,-108,-101,-93,-80,-66,-58,-60,-64,-60,
--48,-39,-38,-36,-25,-10,-2,-1,6,27,48,56,53,55,72,96,115,126,137,152,165,
-172,176,179,185,194,203,210,211,212,222,241,261,270,270,273,288,303,308,305,312,339,
-377,411,429,437,443,455,472,487,493,488,490,524,602,699,770,785,760,740,755,797,834,
-844,834,823,830,856,894,937,979,1019,1062,1108,1150,1179,1196,1217,1254,1307,1365,1425,1490,1556,
-1613,1655,1691,1726,1757,1776,1789,1814,1858,1901,1914,1882,1787,1620,1417,1297,1417,1839,2441,2995,3339,
-3494,3586,3704,3832,3920,3964,4007,4078,4162,4232,4281,4307,4297,4229,4106,3952,3780,3586,3362,3134,2944,
-2818,2749,2710,2682,2657,2634,2611,2591,2576,2566,2549,2516,2468,2414,2360,2306,2252,2202,2160,2120,2074,
-2018,1960,1911,1870,1829,1776,1709,1633,1552,1460,1356,1250,1155,1077,1002,914,810,705,615,543,488,
-448,424,409,390,355,309,269,252,267,303,343,367,374,373,377,386,394,401,406,395,340,
-231,97,-13,-72,-89,-93,-101,-115,-138,-182,-251,-328,-391,-437,-485,-558,-667,-799,-927,-1027,-1088,
--1121,-1140,-1153,-1156,-1144,-1126,-1113,-1110,-1116,-1128,-1149,-1177,-1199,-1196,-1165,-1122,-1090,-1079,-1080,-1076,-1054,
--1016,-976,-946,-925,-907,-888,-868,-850,-829,-801,-768,-737,-714,-699,-688,-679,-670,-657,-641,-623,-606,
--590,-573,-557,-547,-542,-539,-535,-531,-530,-528,-519,-502,-483,-468,-458,-450,-441,-430,-417,-399,-379,
--359,-338,-315,-290,-268,-248,-227,-201,-170,-139,-110,-80,-48,-18,8,34,61,87,111,132,155,
-180,206,232,259,287,313,336,357,379,404,430,458,487,516,543,570,600,631,661,688,716,
-746,778,808,835,864,897,930,960,987,1014,1045,1079,1114,1144,1170,1194,1217,1236,1247,1249,1251,
-1258,1273,1286,1294,1298,1306,1318,1330,1339,1346,1352,1358,1361,1365,1372,1379,1384,1389,1398,1411,1427,
-1442,1457,1473,1491,1509,1527,1549,1572,1592,1610,1629,1651,1672,1689,1705,1726,1748,1767,1783,1800,1821,
-1842,1861,1880,1902,1926,1950,1973,1995,2002,2023,2044,2068,2095,2124,2153,2183,2212,2236,2252,2263,2279,
-2311,2353,2394,2428,2462,2501,2543,2588,2647,2729,2810,2840,2784,2666,2550,2483,2460,2449,2434,2424,2434,
-2452,2459,2452,2442,2440,2439,2430,2417,2413,2422,2433,2441,2458,2500,2563,2622,2657,2686,2742,2839,2945,
-3016,3043,3060,3102,3167,3227,3262,3288,3331,3393,3448,3467,3432,3345,3220,3088,2981,2917,2884,2856,2818,
-2781,2767,2785,2818,2840,2838,2815,2787,2762,2736,2702,2657,2614,2586,2578,2579,2577,2568,2554,2537,2517,
-2502,2502,2520,2540,2548,2533,2499,2454,2410,2384,2388,2408,2411,2383,2345,2327,2328,2321,2296,2288,2335,
-2421,2469,2417,2267,2069,1872,1704,1592,1568,1626,1705,1722,1643,1506,1374,1281,1226,1195,1184,1188,1190,
-1175,1136,1081,1020,962,923,913,918,904,846,757,674,622,600,586,565,536,499,458,415,382,
-363,355,350,349,356,372,389,398,396,384,369,353,337,324,328,371,465,594,712,779,801,
-820,867,924,942,903,833,766,703,619,508,402,332,299,276,249,222,207,198,184,163,146,
-135,129,125,127,135,142,142,138,136,133,124,113,114,130,152,167,174,178,184,189,190,
-190,191,193,189,181,174,168,157,140,124,119,125,130,128,122,120,125,130,124,108,90,
-82,84,90,91,91,97,111,123,124,114,103,95,89,80,66,51,39,32,26,14,-6,
--33,-54,-64,-64,-66,-73,-83,-92,-108,-140,-185,-227,-255,-273,-296,-331,-373,-413,-453,-495,-539,
--580,-616,-654,-698,-747,-797,-845,-893,-941,-987,-1030,-1072,-1116,-1163,-1214,-1273,-1338,-1404,-1463,-1511,-1557,
--1606,-1657,-1705,-1751,-1800,-1857,-1920,-1980,-2034,-2077,-2110,-2136,-2161,-2196,-2241,-2291,-2338,-2382,-2425,-2469,-2511,
--2547,-2579,-2610,-2641,-2674,-2710,-2748,-2788,-2831,-2882,-2941,-2998,-3041,-3066,-3084,-3105,-3128,-3137,-3123,-3090,-3056,
--3040,-3058,-3111,-3195,-3292,-3386,-3467,-3531,-3578,-3616,-3656,-3705,-3761,-3808,-3835,-3847,-3861,-3888,-3923,-3953,-3975,
--3993,-4016,-4041,-4064,-4084,-4102,-4119,-4136,-4154,-4176,-4201,-4223,-4240,-4250,-4257,-4261,-4265,-4269,-4271,-4268,-4261,
--4248,-4233,-4220,-4212,-4208,-4198,-4171,-4120,-4054,-3992,-3957,-3955,-3977,-4003,-4017,-4011,-3994,-3976,-3961,-3945,-3917,
--3882,-3853,-3840,-3835,-3817,-3777,-3730,-3702,-3704,-3722,-3738,-3742,-3736,-3725,-3714,-3711,-3725,-3748,-3759,-3740,-3697,
--3649,-3609,-3573,-3534,-3496,-3467,-3441,-3395,-3319,-3223,-3129,-3040,-2940,-2815,-2676,-2544,-2439,-2363,-2314,-2283,-2263,
--2244,-2220,-2184,-2130,-2054,-1965,-1881,-1815,-1765,-1716,-1670,-1642,-1642,-1661,-1676,-1676,-1664,-1642,-1606,-1550,-1478,
--1406,-1341,-1279,-1213,-1148,-1093,-1050,-1011,-967,-920,-881,-860,-855,-856,-857,-854,-850,-843,-829,-806,-778,
--745,-706,-665,-627,-598,-575,-539,-479,-402,-329,-274,-229,-178,-115,-56,-15,4,21,57,125,211,
-289,337,344,320,281,238,199,169,157,165,189,226,275,332,396,465,540,628,729,837,943,
-1039,1121,1187,1240,1285,1333,1391,1459,1536,1614,1686,1745,1793,1838,1891,1948,2004,2056,2113,2176,2233,
-2273,2300,2330,2376,2430,2476,2507,2531,2557,2588,2620,2651,2688,2739,2805,2877,2942,2992,3033,3081,3148,
-3237,3340,3446,3547,3636,3715,3791,3875,3964,4045,4107,4152,4194,4241,4285,4312,4323,4332,4353,4388,4431,
-4476,4519,4556,4579,4587,4588,4594,4602,4595,4566,4538,4540,4563,4549,4442,4266,4118,4075,4123,4170,4153,
-4092,4048,4049,4075,4103,4135,4175,4211,4229,4236,4247,4258,4257,4266,4332,4468,4611,4671,4624,4538,4499,
-4527,4584,4631,4666,4701,4734,4754,4759,4759,4755,4743,4728,4721,4725,4725,4707,4679,4668,4690,4733,4776,
-4806,4827,4856,4903,4972,5046,5102,5127,5133,5150,5190,5235,5253,5236,5208,5201,5219,5237,5229,5199,5176,
-5184,5216,5248,5259,5253,5244,5240,5236,5229,5219,5209,5198,5181,5160,5141,5126,5112,5096,5077,5057,5036,
-5013,4991,4971,4952,4936,4920,4903,4885,4871,4874,4898,4928,4941,4931,4919,4936,4988,5046,5078,5076,5060,
-5055,5061,5062,5039,4988,4909,4782,4555,4187,3707,3242,2951,2906,3039,3206,3314,3364,3400,3436,3448,3424,
-3380,3337,3289,3219,3131,3044,2962,2876,2779,2685,2609,2544,2473,2390,2310,2243,2182,2117,2052,1999,1955,
-1906,1842,1771,1704,1646,1594,1548,1514,1487,1455,1409,1353,1301,1259,1223,1185,1140,1094,1054,1023,996,
-969,945,928,921,915,899,871,837,807,779,749,719,694,671,642,601,555,513,480,448,413,
-373,335,302,275,250,226,203,183,169,158,146,129,108,86,63,40,17,-1,-13,-25,-47,
--81,-120,-150,-162,-163,-166,-183,-213,-244,-274,-309,-349,-378,-375,-345,-327,-355,-416,-460,-458,-432,
--426,-457,-499,-525,-538,-557,-592,-629,-658,-682,-711,-740,-763,-781,-800,-826,-855,-880,-902,-925,-947,
--968,-989,-1012,-1034,-1053,-1071,-1089,-1110,-1128,-1140,-1145,-1150,-1159,-1172,-1186,-1198,-1209,-1221,-1232,-1241,-1246,
--1249,-1252,-1259,-1268,-1273,-1273,-1268,-1263,-1261,-1262,-1267,-1273,-1278,-1279,-1278,-1276,-1277,-1279,-1279,-1278,-1274,
--1266,-1252,-1234,-1216,-1201,-1184,-1163,-1142,-1128,-1123,-1119,-1109,-1095,-1086,-1083,-1082,-1078,-1072,-1067,-1064,-1060,
--1053,-1044,-1033,-1022,-1011,-999,-986,-971,-956,-941,-929,-917,-904,-890,-876,-860,-843,-825,-809,-795,-782,
--766,-751,-740,-734,-727,-717,-704,-692,-682,-672,-661,-647,-631,-615,-601,-588,-576,-567,-563,-565,-568,
--566,-558,-550,-546,-545,-541,-534,-528,-526,-524,-518,-509,-500,-494,-487,-481,-476,-474,-475,-476,-476,
--476,-474,-470,-464,-459,-455,-450,-443,-433,-421,-409,-397,-388,-380,-374,-366,-359,-354,-348,-339,-326,
--313,-308,-310,-311,-304,-291,-280,-274,-268,-256,-239,-229,-228,-226,-209,-179,-156,-152,-160,-160,-145,
--125,-115,-116,-119,-117,-111,-106,-96,-80,-65,-58,-59,-57,-47,-33,-20,-9,1,8,6,1,
-6,25,48,60,60,61,70,83,96,109,125,145,162,172,177,178,179,184,197,211,218,
-216,214,222,238,252,262,280,312,346,362,357,351,365,398,434,456,469,484,507,534,556,
-568,574,583,608,653,705,738,740,725,723,750,794,826,835,827,823,832,853,885,927,977,
-1026,1071,1111,1149,1184,1213,1240,1271,1314,1371,1436,1503,1559,1598,1624,1648,1676,1703,1725,1747,1782,
-1833,1886,1915,1892,1789,1599,1384,1286,1447,1889,2469,2971,3279,3441,3574,3736,3887,3975,4007,4039,4111,
-4210,4295,4332,4309,4228,4107,3968,3829,3687,3527,3339,3140,2960,2825,2744,2708,2692,2674,2641,2605,2583,
-2577,2569,2543,2500,2450,2400,2348,2292,2238,2195,2163,2128,2081,2023,1962,1908,1860,1816,1769,1715,1652,
-1576,1485,1382,1279,1187,1107,1028,937,834,730,638,561,499,455,429,412,394,366,331,302,294,
-317,362,410,440,445,433,417,401,388,389,406,417,376,264,113,-9,-59,-52,-37,-50,-97,
--164,-243,-324,-398,-455,-503,-564,-656,-778,-907,-1016,-1087,-1120,-1129,-1129,-1127,-1119,-1104,-1088,-1080,-1083,
--1094,-1112,-1139,-1168,-1184,-1176,-1145,-1111,-1093,-1094,-1103,-1104,-1086,-1050,-1010,-974,-946,-921,-897,-876,-857,
--834,-802,-763,-727,-700,-680,-664,-650,-637,-624,-608,-589,-569,-550,-532,-516,-506,-502,-500,-497,-494,
--493,-491,-483,-469,-454,-442,-432,-421,-410,-398,-383,-365,-343,-319,-294,-268,-242,-217,-197,-176,-152,
--123,-92,-59,-26,6,34,57,80,105,132,156,177,197,218,242,267,293,321,346,369,389,
-411,434,461,491,522,553,580,606,635,666,696,721,746,774,805,835,861,887,917,952,984,
-1010,1034,1062,1096,1131,1162,1188,1213,1238,1257,1265,1265,1266,1275,1289,1299,1303,1308,1318,1331,1343,
-1351,1357,1364,1369,1373,1378,1386,1396,1403,1408,1419,1435,1451,1464,1476,1492,1512,1531,1550,1569,1588,
-1605,1623,1643,1666,1687,1703,1718,1738,1762,1781,1795,1809,1826,1846,1864,1879,1897,1921,1950,1978,2002,
-2004,2027,2051,2078,2104,2128,2152,2179,2209,2237,2257,2275,2300,2338,2384,2427,2463,2502,2547,2592,2633,
-2682,2753,2829,2857,2796,2660,2520,2441,2429,2445,2453,2452,2458,2471,2478,2469,2454,2446,2446,2445,2441,
-2437,2441,2449,2460,2479,2518,2574,2626,2663,2697,2759,2857,2959,3025,3048,3063,3106,3177,3243,3281,3304,
-3337,3391,3444,3468,3440,3360,3240,3110,3002,2936,2901,2870,2831,2796,2788,2812,2848,2870,2865,2844,2820,
-2800,2775,2735,2684,2640,2620,2623,2631,2627,2607,2580,2555,2539,2535,2546,2567,2585,2591,2584,2568,2545,
-2521,2503,2502,2510,2508,2486,2460,2452,2464,2477,2483,2501,2552,2610,2616,2526,2358,2166,1989,1845,1745,
-1714,1750,1808,1818,1744,1610,1468,1357,1285,1249,1240,1242,1236,1210,1166,1112,1053,997,961,958,976,
-979,932,838,733,655,613,596,582,560,526,481,436,402,385,381,382,387,398,416,435,447,
-447,434,413,395,388,393,407,435,490,573,667,745,799,844,890,923,918,870,803,744,689,
-620,536,455,399,363,332,301,276,262,249,229,204,186,175,168,162,160,165,170,172,169,
-165,159,150,146,154,175,196,207,209,212,219,226,229,228,227,227,226,223,220,212,201,
-187,179,179,181,178,168,157,153,157,159,151,135,123,125,135,141,135,127,135,160,183,
-189,180,168,162,153,134,110,94,90,90,83,65,43,24,15,16,23,29,28,18,-3,
--39,-86,-133,-169,-188,-204,-229,-266,-307,-344,-381,-422,-465,-504,-541,-582,-628,-677,-723,-768,-814,
--862,-907,-949,-991,-1039,-1092,-1149,-1209,-1273,-1336,-1393,-1441,-1485,-1531,-1579,-1627,-1675,-1729,-1790,-1853,-1911,
--1957,-1993,-2021,-2047,-2078,-2120,-2170,-2221,-2269,-2315,-2361,-2403,-2440,-2470,-2499,-2531,-2567,-2604,-2640,-2677,-2718,
--2766,-2821,-2879,-2929,-2964,-2989,-3013,-3042,-3064,-3066,-3043,-3009,-2985,-2985,-3017,-3078,-3158,-3247,-3334,-3413,-3477,
--3526,-3561,-3597,-3644,-3701,-3753,-3788,-3807,-3824,-3850,-3883,-3911,-3933,-3953,-3976,-4001,-4024,-4044,-4061,-4078,-4096,
--4117,-4139,-4163,-4186,-4207,-4222,-4230,-4231,-4232,-4235,-4239,-4236,-4224,-4207,-4190,-4180,-4176,-4173,-4160,-4123,-4058,
--3979,-3914,-3889,-3906,-3947,-3985,-4004,-4002,-3986,-3968,-3954,-3940,-3919,-3886,-3851,-3826,-3816,-3809,-3791,-3763,-3733,
--3713,-3704,-3703,-3706,-3709,-3706,-3700,-3701,-3719,-3747,-3767,-3765,-3743,-3717,-3688,-3649,-3596,-3544,-3506,-3476,-3431,
--3357,-3265,-3175,-3090,-2993,-2871,-2731,-2596,-2490,-2415,-2365,-2328,-2296,-2269,-2245,-2215,-2165,-2088,-1994,-1912,-1855,
--1813,-1767,-1713,-1669,-1652,-1656,-1664,-1663,-1657,-1645,-1617,-1563,-1489,-1412,-1342,-1279,-1219,-1167,-1131,-1109,-1087,
--1055,-1017,-985,-969,-968,-973,-976,-972,-959,-931,-890,-847,-810,-780,-749,-714,-685,-671,-663,-642,-588,
--504,-408,-317,-230,-146,-69,-10,20,34,52,98,176,269,347,386,380,342,285,220,154,104,
-81,89,117,155,201,260,333,418,513,615,719,817,898,964,1020,1073,1126,1183,1243,1306,1368,
-1431,1497,1563,1625,1680,1733,1794,1861,1923,1976,2023,2074,2123,2161,2192,2227,2277,2334,2381,2410,2428,
-2451,2486,2531,2579,2630,2685,2746,2806,2861,2908,2955,3009,3080,3168,3268,3370,3466,3550,3627,3709,3799,
-3888,3958,4002,4028,4056,4093,4132,4158,4171,4187,4218,4266,4323,4383,4442,4495,4528,4536,4531,4534,4549,
-4555,4532,4498,4492,4520,4520,4420,4228,4044,3969,4003,4061,4068,4029,4001,4009,4032,4047,4063,4093,4129,
-4151,4157,4165,4175,4180,4190,4236,4331,4433,4482,4467,4437,4444,4488,4536,4570,4600,4639,4674,4693,4697,
-4702,4707,4704,4690,4678,4678,4680,4670,4647,4633,4642,4673,4710,4741,4771,4812,4874,4951,5021,5064,5074,
-5075,5093,5134,5178,5198,5190,5172,5165,5176,5191,5193,5179,5162,5161,5181,5208,5224,5224,5216,5211,5209,
-5203,5192,5179,5165,5148,5127,5106,5090,5080,5071,5056,5037,5015,4993,4969,4943,4919,4902,4890,4877,4859,
-4845,4852,4881,4916,4930,4919,4909,4930,4984,5038,5061,5049,5028,5022,5028,5026,4998,4934,4828,4660,4391,
-4001,3542,3140,2933,2963,3135,3301,3377,3386,3395,3426,3446,3424,3371,3318,3271,3213,3134,3045,2958,2871,
-2779,2688,2609,2540,2471,2394,2315,2242,2173,2108,2051,2003,1959,1907,1843,1777,1715,1658,1602,1553,1515,
-1484,1449,1403,1351,1302,1261,1223,1182,1137,1092,1051,1016,985,955,927,907,898,891,876,851,822,
-795,769,739,706,675,650,624,589,546,502,463,428,393,357,323,293,265,236,206,180,160,
-149,140,127,109,88,68,48,26,3,-16,-29,-38,-54,-81,-117,-147,-160,-154,-146,-157,-190,
--228,-259,-285,-319,-355,-374,-370,-367,-394,-439,-459,-426,-369,-347,-384,-452,-503,-526,-542,-569,-604,
--633,-657,-683,-714,-742,-761,-778,-798,-825,-854,-883,-910,-935,-959,-981,-1004,-1027,-1047,-1065,-1082,-1102,
--1121,-1135,-1145,-1153,-1165,-1180,-1194,-1204,-1212,-1219,-1229,-1243,-1257,-1268,-1275,-1281,-1287,-1288,-1284,-1278,-1273,
--1272,-1275,-1279,-1281,-1282,-1281,-1280,-1279,-1279,-1280,-1280,-1279,-1277,-1271,-1260,-1249,-1241,-1235,-1223,-1202,-1178,
--1160,-1150,-1139,-1124,-1109,-1099,-1096,-1093,-1087,-1079,-1075,-1072,-1066,-1056,-1043,-1030,-1020,-1011,-1001,-990,-978,
--964,-950,-937,-923,-910,-899,-889,-877,-862,-844,-827,-813,-799,-782,-766,-754,-748,-743,-735,-723,-711,
--702,-694,-683,-667,-648,-632,-619,-606,-591,-580,-576,-581,-586,-583,-573,-563,-559,-557,-552,-545,-541,
--541,-538,-531,-520,-512,-506,-500,-493,-488,-486,-485,-484,-480,-477,-475,-471,-468,-464,-462,-459,-454,
--446,-435,-423,-409,-398,-389,-383,-377,-370,-361,-353,-344,-332,-321,-314,-310,-305,-296,-284,-277,-273,
--263,-244,-224,-216,-220,-222,-206,-177,-156,-159,-175,-184,-174,-156,-147,-147,-145,-137,-127,-121,-114,
--100,-81,-67,-62,-58,-49,-32,-13,1,12,15,10,4,7,22,42,57,64,68,73,79,
-86,96,110,124,136,146,154,159,159,161,172,191,205,208,205,211,226,241,256,280,322,
-369,399,400,389,391,412,442,465,483,504,532,559,583,604,627,651,669,680,683,680,677,
-681,701,739,781,815,837,853,867,874,878,890,925,981,1038,1080,1110,1142,1185,1233,1273,1305,
-1340,1388,1446,1500,1540,1566,1588,1614,1645,1679,1710,1741,1774,1812,1853,1886,1878,1783,1588,1371,1293,
-1494,1965,2535,2999,3273,3424,3566,3744,3913,4022,4071,4107,4166,4247,4316,4332,4273,4151,4005,3871,3751,
-3621,3461,3281,3106,2957,2842,2762,2714,2684,2653,2612,2577,2564,2569,2565,2534,2483,2433,2389,2341,2288,
-2237,2199,2167,2129,2080,2024,1966,1907,1847,1791,1744,1703,1656,1590,1505,1406,1305,1211,1125,1042,955,
-861,764,670,587,521,475,448,430,412,388,365,350,353,379,423,467,493,492,470,439,408,
-386,383,401,411,365,243,87,-28,-60,-32,-6,-31,-107,-208,-309,-395,-461,-514,-569,-648,-756,
--880,-993,-1073,-1111,-1117,-1107,-1097,-1089,-1080,-1066,-1054,-1048,-1053,-1065,-1087,-1117,-1145,-1158,-1149,-1124,-1101,
--1094,-1101,-1113,-1116,-1100,-1068,-1027,-988,-956,-927,-900,-874,-849,-821,-786,-746,-708,-678,-654,-634,-616,
--601,-588,-571,-551,-530,-512,-496,-482,-471,-464,-461,-460,-459,-457,-450,-439,-426,-417,-409,-400,-387,
--372,-358,-343,-323,-299,-273,-247,-223,-198,-175,-154,-134,-112,-85,-54,-22,11,43,70,93,114,
-139,166,191,212,232,253,276,301,328,354,379,402,424,446,470,495,524,555,586,613,639,
-667,697,727,752,775,802,834,865,891,915,943,975,1006,1032,1056,1083,1117,1152,1181,1206,1230,
-1254,1273,1280,1280,1281,1291,1305,1315,1319,1325,1336,1348,1356,1360,1365,1372,1377,1381,1387,1396,1407,
-1417,1427,1440,1457,1473,1486,1498,1514,1533,1551,1566,1582,1599,1616,1634,1654,1677,1697,1712,1729,1751,
-1777,1798,1811,1823,1840,1860,1877,1889,1903,1925,1953,1980,2004,2009,2034,2062,2090,2114,2134,2155,2180,
-2210,2241,2269,2298,2333,2377,2421,2457,2490,2534,2592,2648,2689,2722,2771,2832,2862,2811,2679,2529,2434,
-2417,2443,2466,2472,2475,2482,2486,2477,2460,2450,2452,2459,2461,2458,2457,2462,2475,2497,2534,2584,2633,
-2674,2718,2786,2884,2981,3042,3060,3069,3104,3168,3232,3272,3292,3317,3362,3415,3448,3433,3362,3249,3126,
-3027,2967,2933,2901,2863,2835,2836,2864,2894,2904,2891,2869,2853,2840,2817,2772,2715,2667,2648,2658,2673,
-2667,2637,2598,2570,2561,2571,2591,2611,2623,2626,2625,2625,2624,2615,2599,2588,2587,2589,2582,2570,2563,
-2570,2590,2622,2671,2729,2764,2729,2610,2439,2267,2120,2000,1908,1861,1869,1900,1901,1833,1705,1558,1433,
-1351,1314,1305,1301,1283,1247,1200,1150,1094,1038,1003,1007,1037,1047,998,891,768,672,619,599,588,
-571,541,500,457,427,413,415,424,436,452,468,483,495,500,491,469,448,443,458,483,503,
-525,565,632,716,799,864,905,913,884,827,767,721,685,642,586,527,475,432,392,359,335,
-317,298,273,248,231,221,212,202,194,193,195,196,194,191,187,185,188,201,219,233,240,
-244,251,261,270,273,271,268,266,266,265,262,253,241,232,229,231,229,219,204,193,189,
-189,188,180,169,164,173,187,192,184,178,191,223,251,258,248,239,233,220,193,164,152,
-157,159,147,127,114,118,127,131,125,111,92,65,28,-17,-63,-98,-118,-128,-142,-169,-206,
--244,-279,-314,-354,-395,-433,-469,-512,-560,-608,-651,-693,-739,-788,-832,-871,-913,-964,-1023,-1083,-1141,
--1200,-1258,-1312,-1361,-1407,-1454,-1502,-1551,-1603,-1660,-1720,-1778,-1829,-1869,-1901,-1930,-1960,-1998,-2045,-2098,-2151,
--2200,-2249,-2295,-2336,-2367,-2394,-2424,-2460,-2501,-2540,-2576,-2613,-2655,-2706,-2762,-2815,-2857,-2886,-2913,-2945,-2978,
--2997,-2990,-2963,-2936,-2925,-2940,-2981,-3045,-3125,-3209,-3289,-3359,-3419,-3466,-3503,-3539,-3586,-3645,-3703,-3745,-3769,
--3788,-3811,-3840,-3868,-3890,-3910,-3932,-3957,-3982,-4004,-4024,-4043,-4062,-4081,-4100,-4121,-4145,-4171,-4192,-4201,-4198,
--4193,-4195,-4202,-4203,-4192,-4174,-4157,-4148,-4144,-4140,-4124,-4086,-4025,-3954,-3902,-3890,-3914,-3953,-3984,-3997,-3994,
--3979,-3961,-3944,-3929,-3911,-3885,-3853,-3822,-3802,-3795,-3792,-3784,-3767,-3743,-3718,-3701,-3696,-3699,-3702,-3700,-3701,
--3714,-3738,-3759,-3768,-3768,-3764,-3750,-3715,-3660,-3602,-3558,-3522,-3476,-3405,-3318,-3231,-3146,-3052,-2934,-2799,-2668,
--2563,-2487,-2432,-2383,-2338,-2302,-2275,-2245,-2193,-2113,-2022,-1947,-1899,-1861,-1811,-1749,-1695,-1667,-1660,-1661,-1662,
--1667,-1673,-1663,-1622,-1550,-1466,-1384,-1311,-1246,-1195,-1163,-1147,-1135,-1118,-1097,-1078,-1066,-1061,-1059,-1061,-1061,
--1048,-1010,-952,-891,-846,-818,-793,-763,-736,-724,-725,-719,-686,-619,-524,-414,-297,-186,-95,-34,0,
-22,58,123,214,312,386,416,402,360,304,238,171,120,102,116,149,183,222,275,349,438,
-535,633,723,798,851,888,921,963,1017,1083,1155,1224,1284,1335,1388,1447,1509,1569,1629,1696,1773,
-1846,1904,1947,1984,2021,2056,2090,2129,2178,2233,2279,2309,2330,2356,2398,2454,2518,2579,2633,2680,2724,
-2772,2828,2891,2961,3036,3117,3203,3290,3374,3455,3540,3632,3726,3807,3860,3885,3897,3915,3944,3978,4005,
-4026,4051,4091,4147,4215,4286,4359,4424,4467,4481,4477,4481,4500,4515,4501,4468,4458,4481,4482,4383,4182,
-3980,3886,3911,3972,3988,3959,3940,3957,3984,3994,3998,4019,4057,4085,4093,4090,4089,4094,4107,4142,4204,
-4270,4311,4328,4349,4392,4445,4484,4509,4538,4577,4610,4627,4635,4650,4667,4670,4654,4635,4626,4624,4613,
-4595,4583,4594,4625,4662,4691,4718,4759,4828,4915,4990,5028,5032,5031,5049,5087,5123,5141,5143,5140,5140,
-5143,5149,5152,5148,5138,5136,5151,5177,5195,5195,5183,5175,5172,5168,5155,5140,5127,5116,5100,5080,5063,
-5054,5046,5030,5007,4985,4966,4944,4917,4887,4866,4858,4852,4839,4825,4829,4860,4899,4920,4913,4905,4928,
-4983,5036,5051,5029,5000,4990,4997,4993,4953,4869,4736,4534,4231,3820,3364,3000,2856,2954,3179,3367,3431,
-3408,3388,3407,3429,3409,3353,3295,3253,3209,3139,3045,2947,2856,2772,2690,2611,2537,2466,2393,2314,2233,
-2154,2087,2036,1997,1957,1907,1846,1785,1727,1671,1615,1563,1519,1481,1443,1400,1355,1313,1272,1230,1184,
-1138,1093,1049,1010,975,945,919,899,884,870,853,830,807,785,761,730,693,658,630,604,573,
-534,490,449,411,375,341,309,281,253,223,191,163,144,133,124,110,90,69,49,30,10,
--10,-30,-47,-60,-73,-92,-118,-146,-163,-161,-153,-158,-187,-223,-247,-260,-281,-317,-351,-369,-381,
--409,-449,-459,-410,-331,-289,-320,-395,-461,-491,-506,-531,-568,-602,-625,-647,-676,-707,-732,-750,-768,
--792,-823,-856,-887,-915,-941,-966,-991,-1015,-1036,-1054,-1072,-1092,-1112,-1128,-1141,-1151,-1162,-1176,-1191,-1205,
--1214,-1221,-1229,-1242,-1259,-1276,-1289,-1299,-1307,-1310,-1308,-1301,-1294,-1290,-1290,-1289,-1288,-1288,-1288,-1290,-1290,
--1288,-1285,-1283,-1281,-1278,-1272,-1262,-1255,-1252,-1250,-1242,-1225,-1205,-1189,-1177,-1163,-1146,-1129,-1119,-1113,-1108,
--1100,-1092,-1088,-1084,-1077,-1064,-1049,-1036,-1025,-1015,-1006,-998,-989,-976,-961,-946,-930,-917,-908,-901,-894,
--881,-865,-848,-833,-821,-806,-791,-778,-770,-764,-756,-744,-732,-724,-717,-705,-687,-668,-653,-642,-630,
--615,-601,-598,-602,-605,-599,-584,-573,-569,-569,-566,-560,-556,-554,-551,-542,-532,-523,-517,-510,-503,
--498,-497,-496,-492,-487,-484,-482,-480,-476,-470,-467,-465,-461,-455,-448,-438,-425,-410,-397,-388,-380,
--372,-362,-352,-343,-335,-326,-318,-308,-294,-280,-271,-269,-267,-256,-234,-211,-204,-213,-219,-209,-185,
--168,-173,-189,-197,-190,-177,-171,-170,-164,-149,-134,-126,-123,-114,-97,-81,-71,-67,-60,-48,-34,
--22,-12,-6,-3,-2,2,13,30,46,60,69,77,85,94,104,111,113,115,122,135,145,
-149,149,155,171,188,198,204,216,233,249,260,276,308,350,382,392,386,385,396,413,430,
-447,470,494,512,527,546,578,615,640,645,636,632,643,669,704,740,775,816,864,913,946,
-949,928,914,935,991,1053,1092,1111,1137,1186,1248,1302,1339,1369,1408,1453,1493,1522,1546,1577,1617,
-1660,1702,1743,1780,1805,1817,1828,1848,1847,1760,1563,1346,1288,1525,2021,2584,3021,3274,3425,3578,3763,
-3940,4066,4138,4182,4226,4281,4329,4334,4265,4133,3987,3865,3755,3612,3419,3214,3048,2934,2850,2774,2708,
-2657,2617,2580,2554,2548,2555,2549,2515,2464,2417,2377,2335,2290,2246,2210,2171,2124,2072,2022,1973,1911,
-1836,1765,1714,1681,1647,1594,1520,1429,1332,1234,1142,1057,975,890,798,703,617,552,510,487,470,
-451,431,417,414,424,449,484,519,535,524,491,450,413,389,385,395,390,328,201,56,-37,
--48,-10,7,-35,-131,-246,-351,-437,-508,-575,-650,-743,-851,-958,-1044,-1093,-1105,-1092,-1073,-1060,-1055,
--1052,-1043,-1031,-1023,-1024,-1034,-1054,-1081,-1106,-1119,-1115,-1100,-1088,-1084,-1089,-1097,-1098,-1085,-1056,-1018,-981,
--951,-924,-895,-864,-834,-803,-768,-728,-688,-654,-626,-601,-581,-564,-550,-534,-516,-498,-482,-468,-453,
--436,-424,-419,-420,-422,-419,-409,-395,-382,-374,-368,-360,-345,-327,-311,-294,-274,-250,-226,-205,-186,
--166,-144,-122,-100,-76,-49,-20,10,41,70,97,121,145,170,195,218,240,263,287,312,338,
-364,389,414,437,461,484,507,531,557,586,615,644,670,697,725,754,780,805,832,863,894,
-921,944,969,998,1027,1054,1079,1108,1143,1178,1207,1229,1249,1271,1288,1295,1294,1294,1303,1317,1329,
-1336,1342,1352,1361,1366,1368,1372,1379,1386,1391,1397,1406,1418,1430,1443,1457,1473,1489,1502,1517,1534,
-1552,1567,1581,1597,1616,1633,1650,1669,1690,1709,1725,1743,1766,1792,1811,1823,1835,1854,1877,1895,1907,
-1919,1937,1961,1986,2009,2022,2050,2080,2107,2130,2150,2170,2195,2221,2250,2281,2319,2364,2411,2453,2484,
-2512,2555,2617,2678,2715,2730,2745,2775,2796,2762,2660,2532,2446,2430,2459,2488,2497,2495,2495,2495,2484,
-2467,2457,2461,2471,2477,2476,2475,2479,2491,2512,2547,2595,2644,2690,2739,2810,2907,3004,3067,3086,3088,
-3107,3153,3206,3244,3267,3293,3340,3400,3443,3434,3362,3246,3126,3039,2994,2970,2945,2917,2903,2914,2939,
-2955,2948,2924,2901,2886,2874,2849,2802,2742,2695,2679,2693,2710,2703,2665,2620,2595,2601,2627,2657,2677,
-2683,2682,2683,2691,2698,2696,2680,2664,2662,2673,2684,2681,2668,2660,2674,2716,2779,2839,2855,2800,2677,
-2522,2375,2249,2140,2046,1987,1974,1986,1979,1914,1790,1639,1504,1417,1380,1372,1361,1332,1289,1244,1199,
-1145,1090,1058,1069,1102,1106,1038,911,773,672,620,600,589,574,549,516,482,457,448,455,472,
-493,512,526,537,548,557,555,537,514,505,520,544,556,555,566,614,699,794,868,902,896,
-860,809,762,730,709,684,645,594,538,488,449,419,396,373,346,318,295,280,268,255,242,
-232,228,226,224,221,218,219,224,235,247,257,264,271,283,297,311,320,324,325,324,321,
-318,316,311,299,285,274,271,269,262,250,239,231,228,226,223,219,214,211,218,231,241,
-243,249,269,301,324,327,318,312,307,293,264,237,230,236,233,216,201,211,240,260,249,
-210,159,113,73,37,2,-27,-48,-60,-70,-88,-116,-151,-184,-217,-251,-290,-327,-361,-397,-439,
--488,-535,-577,-620,-667,-716,-761,-799,-840,-892,-952,-1013,-1067,-1119,-1172,-1226,-1278,-1328,-1377,-1427,-1478,
--1532,-1589,-1645,-1696,-1739,-1775,-1806,-1839,-1876,-1923,-1976,-2032,-2085,-2133,-2179,-2222,-2260,-2291,-2321,-2357,-2398,
--2440,-2479,-2516,-2553,-2597,-2647,-2700,-2748,-2783,-2811,-2841,-2877,-2910,-2924,-2916,-2896,-2881,-2881,-2898,-2937,-3001,
--3084,-3172,-3249,-3310,-3360,-3404,-3443,-3483,-3533,-3594,-3653,-3697,-3724,-3742,-3765,-3794,-3822,-3845,-3862,-3881,-3905,
--3933,-3960,-3982,-4002,-4022,-4042,-4060,-4079,-4102,-4131,-4156,-4166,-4160,-4150,-4149,-4156,-4162,-4156,-4141,-4127,-4118,
--4112,-4103,-4087,-4059,-4018,-3974,-3944,-3940,-3955,-3972,-3980,-3979,-3976,-3970,-3957,-3937,-3914,-3894,-3873,-3851,-3825,
--3802,-3788,-3785,-3786,-3783,-3770,-3750,-3732,-3722,-3718,-3713,-3706,-3701,-3709,-3726,-3746,-3763,-3777,-3789,-3790,-3769,
--3726,-3675,-3630,-3587,-3533,-3460,-3374,-3288,-3204,-3112,-3001,-2876,-2753,-2651,-2572,-2506,-2444,-2386,-2340,-2306,-2269,
--2209,-2128,-2045,-1983,-1941,-1897,-1836,-1768,-1716,-1692,-1686,-1684,-1686,-1699,-1719,-1727,-1704,-1645,-1564,-1480,-1401,
--1330,-1271,-1225,-1195,-1175,-1163,-1156,-1150,-1139,-1123,-1110,-1106,-1112,-1107,-1075,-1015,-950,-901,-872,-851,-825,
--799,-784,-784,-786,-770,-726,-648,-542,-421,-307,-220,-164,-127,-87,-28,55,158,262,341,379,376,
-348,309,263,217,187,185,211,245,275,303,344,405,479,555,626,691,743,781,808,837,875,
-926,988,1061,1135,1198,1250,1298,1353,1414,1476,1536,1602,1680,1758,1821,1862,1890,1919,1956,1998,2045,
-2095,2146,2190,2223,2249,2280,2327,2389,2459,2525,2575,2612,2648,2696,2762,2840,2920,2996,3069,3142,3213,
-3284,3361,3452,3552,3646,3713,3749,3764,3773,3790,3816,3846,3874,3901,3932,3976,4036,4109,4189,4268,4339,
-4391,4416,4424,4437,4462,4483,4474,4442,4423,4432,4418,4312,4113,3915,3824,3853,3917,3933,3902,3882,3900,
-3928,3933,3925,3937,3976,4015,4027,4016,4006,4017,4051,4101,4153,4193,4218,4241,4279,4333,4381,4414,4441,
-4477,4518,4548,4562,4574,4595,4617,4622,4607,4588,4575,4564,4546,4524,4516,4535,4579,4625,4654,4668,4692,
-4752,4843,4930,4978,4986,4985,5002,5035,5063,5078,5088,5097,5104,5105,5103,5103,5103,5099,5099,5113,5140,
-5160,5159,5144,5135,5137,5138,5128,5111,5100,5091,5077,5057,5038,5026,5015,4995,4968,4944,4929,4914,4889,
-4858,4836,4829,4828,4819,4803,4802,4830,4873,4901,4898,4890,4911,4970,5027,5043,5015,4977,4964,4970,4960,
-4907,4805,4655,4437,4114,3680,3214,2861,2755,2905,3180,3399,3469,3430,3385,3385,3402,3385,3330,3271,3233,
-3200,3138,3043,2937,2844,2768,2695,2617,2538,2463,2389,2311,2226,2142,2074,2025,1990,1953,1905,1848,1791,
-1736,1682,1627,1573,1523,1477,1434,1395,1359,1323,1283,1237,1190,1144,1099,1052,1008,970,941,917,895,
-873,850,828,808,790,773,750,719,681,644,613,586,554,516,476,437,400,364,327,294,267,
-241,212,180,150,128,115,103,88,69,49,31,13,-5,-22,-40,-58,-76,-91,-104,-118,-139,
--160,-170,-171,-178,-202,-232,-249,-250,-256,-281,-314,-337,-355,-388,-434,-455,-414,-330,-270,-283,-351,
--418,-450,-461,-482,-519,-557,-585,-608,-637,-671,-701,-722,-738,-759,-788,-822,-854,-885,-914,-944,-973,
--1000,-1022,-1041,-1061,-1081,-1102,-1119,-1133,-1143,-1153,-1165,-1181,-1200,-1216,-1226,-1235,-1245,-1260,-1276,-1290,-1302,
--1313,-1323,-1326,-1321,-1314,-1308,-1305,-1303,-1301,-1301,-1303,-1304,-1303,-1298,-1292,-1287,-1285,-1282,-1275,-1266,-1258,
--1252,-1247,-1238,-1226,-1213,-1203,-1193,-1181,-1164,-1148,-1138,-1131,-1124,-1116,-1109,-1105,-1099,-1089,-1076,-1064,-1053,
--1042,-1031,-1022,-1014,-1005,-992,-976,-957,-939,-925,-916,-911,-906,-897,-883,-867,-853,-841,-830,-817,-804,
--793,-785,-775,-763,-752,-745,-738,-726,-709,-691,-679,-671,-661,-646,-632,-626,-628,-628,-617,-600,-587,
--583,-584,-582,-576,-571,-567,-563,-555,-546,-538,-530,-522,-512,-505,-502,-500,-496,-494,-496,-499,-499,
--491,-482,-475,-471,-465,-458,-452,-446,-436,-421,-403,-387,-376,-369,-361,-351,-343,-337,-332,-325,-312,
--294,-278,-269,-270,-271,-262,-240,-219,-212,-220,-228,-221,-203,-188,-188,-196,-199,-192,-181,-176,-175,
--168,-152,-136,-128,-126,-121,-109,-94,-84,-79,-75,-69,-62,-54,-45,-33,-21,-11,-3,6,21,
-41,58,72,81,92,104,116,120,116,112,117,132,148,157,158,161,171,185,198,212,230,
-251,266,273,278,292,315,337,351,358,363,371,377,385,398,418,439,450,453,464,493,535,
-572,594,606,623,655,694,727,751,776,819,885,959,1008,1010,975,943,952,1004,1065,1104,1121,
-1144,1192,1258,1315,1352,1380,1412,1451,1486,1515,1549,1596,1651,1701,1744,1789,1829,1848,1840,1827,1830,
-1817,1717,1506,1288,1258,1537,2057,2611,3022,3269,3441,3619,3809,3974,4093,4172,4226,4269,4312,4351,4355,
-4289,4161,4027,3926,3828,3669,3432,3183,3000,2899,2833,2757,2675,2612,2576,2555,2538,2529,2527,2518,2489,
-2446,2404,2367,2329,2290,2252,2213,2165,2109,2056,2014,1972,1910,1829,1751,1697,1666,1638,1594,1530,1451,
-1360,1264,1170,1083,1002,916,823,728,646,589,555,533,514,493,476,469,475,490,514,544,571,
-578,559,518,472,431,404,393,388,362,286,162,39,-23,-13,23,22,-43,-152,-266,-364,-452,
--541,-636,-732,-826,-915,-992,-1051,-1082,-1085,-1067,-1045,-1033,-1033,-1035,-1028,-1014,-1001,-998,-1006,-1023,-1043,
--1062,-1075,-1080,-1079,-1074,-1068,-1062,-1059,-1057,-1047,-1023,-990,-959,-935,-912,-884,-851,-820,-792,-761,-722,
--680,-641,-610,-584,-562,-543,-524,-506,-486,-469,-453,-436,-416,-396,-380,-374,-376,-378,-374,-364,-350,
--338,-330,-322,-312,-296,-278,-260,-242,-221,-200,-182,-167,-153,-135,-113,-89,-62,-35,-7,20,48,
-75,102,130,157,184,208,231,252,274,298,324,350,375,399,424,448,472,496,521,545,568,
-591,616,644,673,700,726,753,782,808,834,859,887,915,942,966,990,1017,1045,1071,1098,1130,
-1167,1204,1234,1256,1275,1294,1310,1315,1311,1307,1312,1325,1338,1346,1352,1359,1366,1373,1377,1384,1392,
-1400,1407,1413,1421,1433,1446,1459,1472,1486,1499,1513,1529,1547,1563,1578,1594,1613,1634,1651,1665,1681,
-1702,1723,1742,1760,1780,1801,1817,1829,1843,1864,1888,1907,1920,1933,1951,1974,1998,2022,2038,2069,2098,
-2124,2146,2168,2191,2213,2233,2256,2286,2329,2381,2437,2486,2521,2547,2577,2620,2664,2687,2681,2663,2656,
-2655,2634,2574,2499,2452,2454,2487,2515,2523,2518,2512,2506,2494,2478,2469,2474,2485,2492,2494,2496,2501,
-2510,2528,2562,2610,2662,2708,2755,2822,2916,3017,3090,3118,3117,3119,3143,3184,3222,3253,3289,3345,3413,
-3461,3448,3362,3232,3110,3036,3011,3007,3000,2990,2991,3004,3016,3010,2986,2957,2935,2919,2900,2870,2824,
-2772,2731,2719,2733,2749,2738,2698,2655,2640,2663,2705,2742,2760,2763,2761,2762,2768,2774,2770,2757,2744,
-2747,2766,2784,2785,2766,2746,2749,2783,2836,2882,2887,2836,2736,2613,2488,2367,2252,2152,2087,2068,2072,
-2058,1990,1864,1709,1571,1481,1444,1433,1417,1382,1338,1297,1258,1207,1154,1127,1143,1173,1159,1065,916,
-771,676,632,612,596,578,559,537,514,497,493,504,527,552,574,588,597,606,617,620,606,
-582,565,567,577,577,566,571,618,705,799,867,895,892,870,839,806,780,764,746,713,660,
-598,544,508,485,462,434,402,374,353,335,317,300,288,282,278,273,265,257,252,254,263,
-277,288,295,300,311,331,351,365,372,379,386,389,386,382,378,371,357,338,322,311,302,
-291,280,274,271,268,265,266,271,274,271,272,282,301,321,340,361,385,400,402,397,395,
-393,381,359,341,336,334,319,297,292,318,354,362,322,249,177,126,97,81,67,51,31,
-9,-15,-41,-69,-99,-128,-158,-192,-227,-260,-291,-324,-365,-412,-458,-500,-543,-592,-642,-688,-728,
--772,-824,-882,-939,-990,-1039,-1090,-1144,-1199,-1252,-1304,-1355,-1407,-1460,-1513,-1564,-1609,-1648,-1683,-1717,-1755,
--1802,-1857,-1917,-1974,-2023,-2065,-2104,-2141,-2176,-2212,-2252,-2296,-2340,-2381,-2419,-2456,-2495,-2537,-2584,-2632,-2675,
--2710,-2739,-2771,-2806,-2836,-2850,-2850,-2845,-2843,-2842,-2847,-2873,-2935,-3030,-3131,-3213,-3268,-3308,-3345,-3384,-3428,
--3483,-3545,-3604,-3647,-3671,-3690,-3716,-3751,-3783,-3804,-3817,-3832,-3856,-3886,-3916,-3939,-3957,-3977,-3999,-4020,-4038,
--4057,-4082,-4106,-4118,-4114,-4103,-4099,-4103,-4108,-4106,-4099,-4090,-4082,-4073,-4061,-4046,-4030,-4013,-3998,-3989,-3988,
--3985,-3975,-3958,-3947,-3947,-3953,-3950,-3931,-3903,-3876,-3856,-3841,-3826,-3808,-3792,-3781,-3779,-3782,-3782,-3777,-3770,
--3761,-3750,-3734,-3717,-3708,-3711,-3724,-3740,-3756,-3774,-3793,-3806,-3801,-3779,-3745,-3706,-3660,-3601,-3526,-3441,-3357,
--3272,-3181,-3075,-2957,-2841,-2740,-2655,-2577,-2500,-2431,-2376,-2333,-2282,-2212,-2130,-2060,-2012,-1972,-1915,-1840,-1770,
--1729,-1719,-1720,-1719,-1719,-1731,-1753,-1767,-1757,-1718,-1657,-1588,-1517,-1448,-1382,-1322,-1271,-1234,-1214,-1208,-1206,
--1194,-1170,-1147,-1140,-1148,-1154,-1135,-1085,-1023,-973,-942,-920,-898,-876,-862,-859,-859,-851,-822,-766,-680,
--577,-483,-416,-376,-341,-291,-220,-129,-26,79,172,235,261,262,251,236,223,220,237,270,303,
-324,339,361,397,443,491,539,588,634,677,718,760,803,848,899,964,1040,1115,1178,1231,1285,
-1345,1404,1460,1520,1591,1667,1730,1769,1794,1823,1867,1921,1978,2033,2082,2125,2160,2190,2224,2270,2331,
-2401,2465,2515,2553,2592,2647,2719,2800,2878,2951,3021,3087,3146,3205,3275,3366,3466,3552,3606,3631,3646,
-3665,3689,3715,3740,3765,3793,3827,3871,3930,4005,4087,4169,4243,4302,4342,4368,4395,4426,4447,4438,4405,
-4380,4372,4338,4218,4018,3829,3751,3791,3863,3883,3851,3825,3837,3861,3861,3843,3847,3886,3935,3956,3944,
-3934,3961,4031,4114,4174,4193,4187,4189,4217,4261,4302,4335,4370,4416,4460,4486,4498,4512,4534,4553,4556,
-4546,4534,4524,4508,4480,4450,4439,4464,4520,4581,4618,4624,4627,4667,4754,4850,4911,4926,4926,4942,4974,
-5002,5018,5031,5046,5057,5060,5058,5061,5065,5064,5063,5073,5096,5114,5112,5100,5097,5107,5114,5107,5090,
-5075,5065,5050,5028,5008,4996,4983,4962,4933,4908,4894,4882,4861,4833,4811,4804,4802,4792,4774,4768,4793,
-4838,4869,4868,4858,4880,4943,5010,5031,5000,4959,4944,4949,4932,4862,4746,4591,4371,4038,3585,3103,2755,
-2673,2853,3155,3395,3477,3437,3377,3359,3368,3356,3308,3251,3211,3177,3122,3034,2933,2843,2769,2700,2622,
-2540,2460,2384,2307,2225,2144,2076,2024,1983,1943,1896,1845,1792,1741,1689,1636,1581,1524,1469,1421,1385,
-1356,1326,1286,1240,1193,1149,1106,1058,1010,971,941,917,891,860,829,803,785,771,757,735,703,
-667,632,600,570,536,499,462,427,392,353,314,278,251,228,203,171,137,108,89,75,61,
-46,30,13,-4,-21,-36,-49,-64,-84,-101,-110,-114,-125,-144,-164,-178,-191,-215,-244,-262,-263,
--263,-278,-301,-317,-330,-362,-416,-455,-433,-356,-284,-276,-330,-393,-424,-428,-437,-466,-506,-541,-572,
--605,-643,-674,-693,-706,-723,-750,-782,-815,-847,-882,-918,-953,-981,-1003,-1023,-1043,-1065,-1086,-1105,-1121,
--1134,-1145,-1157,-1174,-1194,-1214,-1229,-1240,-1251,-1264,-1278,-1290,-1300,-1312,-1323,-1331,-1331,-1327,-1324,-1322,-1321,
--1319,-1318,-1318,-1317,-1313,-1306,-1299,-1295,-1292,-1290,-1284,-1276,-1267,-1255,-1242,-1230,-1220,-1213,-1208,-1202,-1191,
--1177,-1164,-1155,-1147,-1140,-1133,-1128,-1122,-1113,-1100,-1089,-1080,-1073,-1064,-1052,-1040,-1030,-1020,-1007,-990,-970,
--952,-936,-925,-919,-915,-908,-896,-881,-867,-856,-846,-835,-823,-812,-801,-791,-779,-769,-762,-756,-747,
--733,-719,-709,-703,-695,-681,-666,-658,-656,-653,-641,-623,-608,-602,-602,-600,-594,-587,-582,-577,-570,
--562,-555,-547,-536,-524,-513,-505,-500,-497,-500,-507,-514,-513,-504,-494,-488,-482,-473,-460,-450,-447,
--443,-431,-410,-389,-375,-369,-365,-357,-348,-341,-338,-336,-327,-310,-294,-286,-288,-290,-283,-266,-249,
--242,-245,-248,-241,-226,-213,-207,-206,-203,-196,-187,-181,-177,-171,-159,-146,-138,-134,-129,-119,-107,
--97,-91,-86,-79,-72,-64,-52,-37,-21,-9,-1,7,24,46,66,79,85,92,102,111,114,
-112,111,119,135,153,167,174,180,187,196,207,222,240,261,277,288,293,297,303,313,327,
-343,359,370,373,376,387,407,429,443,449,457,479,514,554,588,617,648,684,719,743,756,
-771,806,869,944,999,1012,989,963,969,1013,1070,1113,1137,1165,1210,1267,1316,1345,1368,1398,1438,
-1477,1515,1561,1621,1682,1730,1767,1806,1847,1869,1862,1846,1837,1802,1669,1433,1222,1236,1569,2114,2650,
-3029,3269,3468,3675,3865,4003,4096,4172,4237,4282,4311,4329,4319,4252,4135,4026,3961,3894,3737,3467,3169,
-2950,2839,2776,2702,2617,2556,2534,2526,2512,2495,2483,2476,2459,2429,2393,2356,2319,2282,2242,2197,2143,
-2086,2038,2001,1962,1902,1826,1754,1703,1670,1637,1592,1534,1466,1385,1295,1203,1115,1027,932,833,741,
-671,625,594,567,539,514,500,501,514,536,565,597,620,622,598,558,513,470,433,402,373,
-326,240,124,25,-10,17,55,41,-40,-156,-266,-360,-455,-564,-679,-782,-859,-917,-967,-1016,-1053,
--1067,-1056,-1037,-1025,-1025,-1025,-1016,-998,-984,-982,-992,-1008,-1023,-1037,-1052,-1069,-1081,-1080,-1065,-1041,-1021,
--1009,-999,-982,-957,-933,-916,-897,-869,-835,-805,-780,-754,-718,-675,-635,-604,-581,-557,-531,-505,-479,
--454,-432,-412,-392,-372,-355,-343,-339,-337,-335,-328,-318,-307,-296,-285,-273,-261,-246,-230,-211,-191,
--171,-154,-141,-130,-116,-95,-69,-41,-13,14,40,66,91,116,143,171,199,226,251,272,292,
-314,337,362,385,408,430,455,480,505,529,554,579,603,625,648,673,701,728,754,780,806,
-833,859,882,905,930,956,981,1006,1033,1060,1087,1114,1145,1182,1221,1254,1279,1299,1317,1331,1336,
-1330,1322,1323,1333,1346,1355,1360,1365,1373,1382,1391,1400,1408,1417,1425,1432,1442,1453,1464,1476,1487,
-1498,1510,1522,1537,1552,1566,1582,1600,1622,1642,1657,1669,1687,1710,1734,1755,1771,1788,1805,1820,1834,
-1851,1872,1894,1912,1926,1942,1963,1986,2011,2038,2050,2081,2110,2133,2155,2179,2203,2223,2239,2258,2290,
-2337,2396,2460,2521,2568,2592,2600,2606,2615,2617,2601,2570,2540,2520,2503,2480,2458,2455,2478,2511,2532,
-2536,2532,2527,2519,2506,2493,2490,2497,2505,2509,2510,2514,2521,2528,2544,2577,2628,2682,2726,2765,2823,
-2912,3015,3097,3134,3134,3127,3138,3170,3211,3251,3296,3355,3422,3465,3446,3350,3214,3096,3040,3039,3060,
-3075,3084,3091,3094,3076,3038,2996,2968,2955,2943,2921,2889,2850,2810,2780,2772,2784,2797,2786,2750,2715,
-2712,2746,2793,2825,2835,2834,2833,2836,2839,2839,2833,2825,2821,2829,2848,2864,2865,2849,2831,2827,2842,
-2868,2890,2888,2854,2789,2699,2591,2467,2341,2235,2173,2156,2158,2135,2057,1924,1768,1630,1542,1503,1489,
-1469,1433,1393,1359,1324,1278,1228,1206,1222,1243,1210,1096,935,793,708,670,645,618,593,577,566,
-556,548,549,564,589,615,637,651,660,669,678,681,670,646,621,603,589,572,564,587,656,
-753,842,897,920,927,927,914,888,860,841,828,802,751,683,625,588,565,540,507,471,443,
-420,397,373,355,348,347,341,329,315,304,298,298,306,319,332,341,351,368,392,413,423,
-429,437,449,455,452,445,440,434,419,396,374,356,341,327,317,314,314,312,310,319,336,
-349,348,342,350,376,409,437,455,469,481,489,493,494,491,482,473,469,467,454,424,394,
-389,410,426,401,332,251,192,168,166,169,165,147,114,74,34,1,-24,-49,-76,-105,-136,
--168,-198,-227,-259,-296,-338,-382,-423,-466,-513,-562,-610,-656,-704,-756,-811,-863,-913,-962,-1015,-1070,
--1125,-1178,-1231,-1284,-1337,-1387,-1435,-1480,-1522,-1562,-1600,-1640,-1685,-1739,-1801,-1862,-1916,-1958,-1992,-2024,-2057,
--2093,-2136,-2186,-2236,-2281,-2319,-2354,-2392,-2433,-2474,-2515,-2558,-2600,-2636,-2668,-2699,-2730,-2757,-2778,-2793,-2804,
--2807,-2796,-2780,-2792,-2855,-2964,-3081,-3172,-3228,-3262,-3292,-3327,-3372,-3430,-3498,-3560,-3601,-3622,-3640,-3669,-3709,
--3744,-3764,-3774,-3787,-3813,-3846,-3876,-3897,-3913,-3933,-3957,-3980,-3995,-4006,-4020,-4039,-4054,-4060,-4055,-4049,-4048,
--4049,-4049,-4048,-4045,-4040,-4031,-4020,-4008,-4001,-3998,-3999,-4000,-3996,-3980,-3954,-3929,-3915,-3919,-3928,-3930,-3916,
--3890,-3862,-3840,-3827,-3818,-3809,-3797,-3786,-3780,-3780,-3784,-3788,-3791,-3788,-3778,-3761,-3744,-3734,-3735,-3742,-3750,
--3759,-3773,-3790,-3805,-3811,-3806,-3789,-3762,-3722,-3667,-3599,-3523,-3442,-3356,-3262,-3156,-3041,-2927,-2823,-2729,-2639,
--2550,-2471,-2410,-2357,-2291,-2206,-2122,-2062,-2027,-1987,-1921,-1837,-1770,-1742,-1743,-1747,-1744,-1741,-1749,-1766,-1778,
--1775,-1753,-1717,-1669,-1613,-1553,-1491,-1430,-1372,-1323,-1291,-1275,-1264,-1247,-1221,-1196,-1187,-1195,-1205,-1193,-1153,
--1098,-1049,-1014,-991,-972,-956,-946,-944,-943,-938,-920,-881,-818,-739,-667,-622,-596,-569,-523,-458,-383,
--301,-207,-107,-18,43,78,101,120,139,161,187,215,237,244,240,238,250,279,324,381,445,
-508,569,628,685,735,775,815,872,952,1039,1116,1176,1228,1281,1335,1387,1442,1507,1579,1640,1681,
-1708,1739,1787,1848,1912,1971,2024,2070,2109,2144,2180,2227,2286,2351,2413,2463,2507,2554,2615,2687,2763,
-2836,2907,2979,3044,3098,3148,3209,3292,3383,3455,3495,3514,3534,3567,3603,3630,3650,3672,3700,3735,3778,
-3831,3899,3978,4061,4140,4210,4266,4310,4347,4378,4393,4380,4349,4328,4317,4272,4139,3930,3739,3661,3705,
-3786,3816,3789,3759,3762,3782,3783,3767,3768,3808,3862,3891,3884,3876,3913,4007,4117,4187,4192,4157,4133,
-4147,4186,4228,4266,4308,4356,4396,4418,4430,4449,4473,4490,4491,4484,4478,4469,4447,4412,4378,4364,4385,
-4443,4516,4569,4585,4582,4608,4684,4781,4846,4862,4859,4874,4911,4948,4969,4983,4997,5009,5015,5019,5030,
-5041,5045,5041,5042,5054,5063,5061,5053,5056,5070,5080,5074,5058,5043,5032,5018,4998,4980,4968,4956,4937,
-4912,4889,4872,4856,4834,4810,4791,4782,4776,4762,4743,4737,4759,4800,4829,4831,4825,4852,4922,4993,5012,
-4977,4934,4924,4931,4905,4820,4693,4539,4321,3975,3501,3010,2674,2615,2809,3110,3349,3443,3418,3360,3328,
-3326,3318,3285,3236,3188,3145,3092,3019,2935,2853,2779,2705,2626,2542,2458,2379,2301,2224,2150,2082,2023,
-1972,1926,1882,1837,1791,1744,1695,1644,1586,1521,1457,1405,1371,1347,1321,1283,1239,1194,1152,1109,1063,
-1016,976,944,916,885,849,812,782,763,751,738,717,688,653,619,587,556,522,488,453,418,
-380,338,295,259,233,215,194,164,125,90,65,49,37,26,13,0,-18,-38,-53,-64,-74,
--89,-105,-110,-107,-108,-123,-146,-167,-186,-210,-242,-268,-282,-290,-305,-323,-331,-335,-357,-408,-455,
--451,-388,-316,-296,-336,-391,-416,-411,-406,-424,-459,-498,-535,-574,-614,-644,-660,-670,-685,-711,-743,
--775,-807,-845,-887,-927,-957,-979,-998,-1020,-1043,-1064,-1083,-1101,-1120,-1139,-1156,-1173,-1191,-1209,-1225,-1238,
--1251,-1267,-1282,-1294,-1303,-1313,-1323,-1330,-1334,-1335,-1335,-1335,-1334,-1331,-1329,-1327,-1324,-1320,-1315,-1312,-1309,
--1305,-1301,-1296,-1290,-1282,-1270,-1253,-1237,-1226,-1221,-1217,-1209,-1198,-1187,-1177,-1170,-1162,-1154,-1148,-1144,-1138,
--1127,-1114,-1103,-1095,-1088,-1079,-1066,-1053,-1040,-1029,-1016,-1001,-985,-968,-951,-937,-929,-923,-917,-907,-892,
--878,-867,-857,-848,-839,-829,-819,-809,-798,-788,-781,-776,-770,-760,-749,-740,-734,-728,-716,-702,-691,
--685,-680,-670,-653,-637,-628,-623,-618,-611,-604,-599,-594,-587,-579,-570,-562,-552,-541,-529,-518,-509,
--505,-508,-515,-517,-512,-503,-498,-499,-498,-486,-466,-450,-446,-448,-441,-422,-399,-384,-380,-378,-371,
--359,-349,-346,-346,-341,-330,-317,-311,-311,-312,-307,-295,-283,-276,-273,-268,-259,-247,-236,-227,-221,
--216,-211,-204,-198,-192,-184,-175,-165,-156,-149,-141,-133,-122,-113,-103,-92,-79,-65,-52,-38,-24,
--10,-2,2,10,27,51,73,84,86,86,89,92,94,96,103,115,132,149,165,179,190,
-197,203,212,225,241,259,278,297,312,320,321,323,333,352,372,387,394,400,412,432,457,
-482,501,517,536,561,590,620,646,670,694,718,738,753,765,787,826,879,931,963,972,971,
-984,1021,1071,1118,1155,1191,1236,1282,1318,1337,1353,1381,1424,1471,1518,1570,1630,1688,1731,1761,1794,
-1833,1861,1867,1863,1853,1795,1629,1374,1184,1253,1640,2198,2702,3039,3265,3482,3713,3902,4021,4100,4181,
-4249,4270,4241,4192,4136,4061,3971,3908,3895,3868,3727,3443,3112,2864,2743,2689,2629,2556,2506,2492,2489,
-2474,2450,2437,2435,2429,2406,2372,2335,2298,2259,2215,2165,2113,2065,2026,1992,1951,1894,1829,1770,1724,
-1684,1639,1588,1531,1469,1395,1311,1223,1133,1037,933,831,748,692,655,621,582,542,514,504,512,
-534,565,601,634,650,644,620,589,556,515,463,406,349,284,195,88,3,-18,19,62,48,
--33,-150,-261,-361,-466,-584,-700,-785,-831,-859,-895,-952,-1012,-1051,-1058,-1045,-1032,-1027,-1022,-1009,-992,
--981,-985,-1001,-1019,-1035,-1051,-1073,-1099,-1119,-1115,-1084,-1037,-994,-969,-958,-947,-933,-917,-903,-883,-852,
--814,-781,-756,-731,-697,-656,-619,-590,-566,-538,-505,-472,-441,-414,-390,-370,-352,-337,-327,-320,-315,
--308,-298,-286,-276,-268,-257,-243,-227,-214,-202,-188,-169,-149,-131,-118,-107,-94,-74,-47,-16,13,
-40,66,89,113,136,161,186,212,238,263,287,309,330,352,375,397,418,439,461,486,511,
-535,558,583,609,634,657,678,701,726,753,778,802,827,853,878,901,923,946,972,999,1027,
-1054,1082,1108,1133,1160,1193,1229,1264,1292,1314,1331,1344,1349,1345,1338,1338,1348,1361,1372,1378,1382,
-1390,1399,1409,1417,1424,1431,1439,1448,1458,1468,1478,1488,1499,1511,1523,1534,1544,1555,1567,1583,1602,
-1623,1640,1654,1669,1690,1716,1740,1759,1774,1789,1806,1824,1841,1860,1880,1900,1916,1933,1953,1975,1997,
-2021,2050,2056,2087,2116,2139,2161,2185,2209,2227,2242,2265,2305,2359,2420,2484,2546,2593,2611,2598,2571,
-2551,2542,2533,2514,2490,2468,2455,2450,2457,2476,2503,2525,2533,2533,2533,2534,2529,2518,2511,2514,2524,
-2528,2525,2521,2524,2532,2539,2554,2588,2642,2696,2737,2771,2821,2901,2997,3077,3118,3124,3120,3129,3160,
-3202,3245,3286,3335,3390,3426,3409,3324,3204,3108,3074,3094,3134,3166,3185,3190,3169,3113,3038,2977,2951,
-2951,2951,2937,2913,2887,2862,2843,2839,2854,2870,2866,2838,2812,2814,2844,2876,2887,2880,2873,2877,2885,
-2887,2881,2874,2873,2881,2894,2908,2919,2925,2925,2923,2918,2914,2912,2911,2903,2880,2834,2761,2661,2540,
-2414,2310,2253,2240,2238,2203,2109,1966,1809,1678,1595,1558,1541,1521,1489,1455,1427,1396,1353,1307,1285,
-1296,1306,1260,1139,981,849,772,734,700,659,626,609,607,606,605,612,630,656,681,701,716,
-727,737,743,743,733,712,681,644,604,573,575,629,730,843,927,969,986,1002,1017,1014,986,
-950,929,925,912,869,803,741,697,667,633,591,550,518,491,461,435,421,420,419,407,388,
-371,362,359,358,362,374,389,403,418,438,463,482,490,494,503,515,519,512,503,497,490,
-474,450,426,407,391,376,367,368,372,373,374,386,409,429,432,424,429,456,495,526,543,
-555,570,587,597,593,581,571,574,586,589,567,523,484,469,469,453,398,322,261,239,247,
-261,262,245,213,168,120,78,47,24,0,-27,-56,-86,-115,-145,-174,-203,-236,-273,-313,-354,
--395,-438,-484,-532,-582,-634,-686,-737,-787,-837,-890,-945,-999,-1052,-1104,-1158,-1212,-1265,-1313,-1356,-1396,
--1438,-1482,-1526,-1573,-1624,-1682,-1744,-1800,-1845,-1879,-1909,-1939,-1975,-2017,-2066,-2122,-2175,-2218,-2252,-2286,-2325,
--2367,-2406,-2444,-2483,-2525,-2564,-2597,-2625,-2652,-2679,-2708,-2737,-2760,-2762,-2738,-2708,-2712,-2779,-2897,-3023,-3120,
--3179,-3215,-3244,-3274,-3313,-3372,-3447,-3517,-3561,-3578,-3590,-3616,-3654,-3688,-3706,-3716,-3732,-3762,-3799,-3831,-3852,
--3870,-3890,-3915,-3936,-3948,-3952,-3957,-3970,-3988,-4003,-4007,-4002,-3995,-3993,-3996,-3999,-3999,-3996,-3990,-3986,-3984,
--3983,-3982,-3981,-3978,-3969,-3950,-3927,-3907,-3899,-3900,-3901,-3897,-3884,-3866,-3845,-3825,-3812,-3805,-3802,-3798,-3793,
--3789,-3786,-3786,-3790,-3796,-3801,-3800,-3793,-3784,-3779,-3779,-3780,-3781,-3783,-3788,-3797,-3805,-3811,-3813,-3809,-3794,
--3765,-3722,-3668,-3604,-3529,-3442,-3345,-3237,-3123,-3009,-2902,-2800,-2698,-2598,-2513,-2445,-2381,-2300,-2201,-2110,-2056,
--2030,-1997,-1933,-1853,-1795,-1774,-1775,-1772,-1762,-1758,-1769,-1786,-1797,-1796,-1785,-1761,-1725,-1677,-1625,-1575,-1526,
--1476,-1427,-1386,-1355,-1331,-1307,-1280,-1257,-1245,-1248,-1252,-1242,-1209,-1162,-1117,-1083,-1060,-1041,-1028,-1023,-1027,
--1032,-1034,-1026,-1000,-951,-886,-824,-785,-766,-747,-715,-674,-633,-588,-522,-430,-330,-244,-179,-126,-76,
--32,1,22,36,40,31,11,-3,5,51,133,237,342,431,503,566,625,674,712,747,800,
-880,973,1056,1118,1165,1210,1257,1304,1356,1419,1489,1552,1598,1632,1666,1712,1769,1830,1892,1953,2008,
-2057,2099,2142,2192,2252,2316,2376,2427,2473,2522,2581,2648,2720,2793,2868,2944,3012,3065,3112,3168,3241,
-3316,3370,3394,3406,3432,3475,3521,3552,3570,3590,3621,3660,3701,3746,3800,3868,3949,4037,4121,4192,4247,
-4289,4317,4321,4300,4272,4263,4267,4228,4095,3881,3682,3594,3631,3714,3755,3734,3694,3680,3692,3703,3704,
-3715,3753,3805,3838,3836,3826,3856,3944,4056,4128,4128,4082,4050,4064,4111,4163,4208,4251,4294,4325,4342,
-4357,4382,4411,4430,4432,4426,4417,4400,4370,4333,4302,4288,4302,4352,4428,4500,4538,4547,4570,4638,4729,
-4793,4807,4798,4810,4850,4894,4922,4936,4948,4961,4970,4980,4996,5015,5024,5022,5017,5016,5015,5010,5006,
-5012,5025,5033,5028,5018,5009,5003,4992,4976,4959,4944,4929,4911,4893,4875,4856,4834,4810,4789,4775,4765,
-4752,4736,4721,4718,4736,4767,4792,4799,4806,4845,4918,4982,4989,4944,4902,4899,4908,4872,4772,4639,4489,
-4269,3904,3404,2907,2595,2565,2766,3052,3283,3396,3405,3361,3312,3283,3269,3252,3220,3171,3115,3059,3001,
-2939,2870,2795,2715,2632,2547,2462,2378,2297,2222,2151,2084,2019,1960,1910,1868,1830,1790,1747,1701,1650,
-1588,1517,1448,1394,1360,1337,1312,1279,1240,1200,1158,1114,1067,1022,981,945,913,880,844,805,771,
-746,732,720,703,676,642,607,573,541,512,482,449,410,364,317,272,236,212,197,182,156,
-118,80,52,34,22,11,0,-12,-29,-51,-70,-82,-89,-98,-108,-110,-102,-96,-105,-127,-151,
--171,-193,-224,-256,-282,-303,-326,-347,-354,-351,-361,-398,-442,-451,-410,-355,-335,-362,-401,-415,-401,
--388,-395,-419,-450,-483,-521,-563,-596,-616,-629,-649,-678,-710,-740,-770,-808,-853,-896,-929,-953,-973,
--996,-1021,-1042,-1061,-1081,-1105,-1129,-1152,-1171,-1189,-1204,-1218,-1231,-1246,-1262,-1279,-1294,-1305,-1314,-1322,-1328,
--1332,-1335,-1337,-1337,-1335,-1332,-1329,-1329,-1329,-1328,-1327,-1327,-1325,-1319,-1312,-1305,-1302,-1298,-1288,-1272,-1256,
--1244,-1236,-1229,-1219,-1207,-1196,-1188,-1180,-1172,-1163,-1157,-1153,-1148,-1140,-1128,-1117,-1107,-1098,-1087,-1075,-1061,
--1048,-1036,-1024,-1012,-999,-985,-969,-955,-945,-937,-930,-919,-906,-893,-882,-873,-865,-857,-850,-843,-835,
--824,-814,-806,-801,-796,-789,-780,-770,-763,-757,-748,-737,-725,-717,-710,-701,-687,-672,-659,-649,-639,
--628,-619,-613,-609,-603,-594,-584,-576,-569,-562,-552,-541,-532,-526,-525,-524,-517,-505,-496,-497,-507,
--511,-500,-477,-457,-452,-455,-452,-437,-417,-403,-398,-396,-388,-373,-360,-355,-353,-350,-342,-332,-327,
--326,-324,-318,-311,-305,-299,-291,-281,-270,-261,-253,-245,-237,-232,-229,-226,-220,-212,-204,-195,-185,
--174,-164,-156,-149,-141,-131,-118,-102,-84,-66,-50,-36,-24,-13,-6,-3,4,20,42,63,75,
-78,78,78,79,80,85,97,112,126,140,155,171,185,193,199,208,221,237,254,274,298,
-320,335,339,340,346,359,375,391,405,419,434,451,472,500,531,557,577,594,613,633,652,
-665,680,700,727,753,770,781,794,822,864,911,949,975,999,1031,1076,1125,1171,1214,1258,1297,
-1325,1338,1349,1376,1421,1473,1522,1570,1620,1668,1707,1738,1772,1809,1837,1849,1854,1843,1770,1586,1335,
-1183,1304,1722,2266,2724,3018,3230,3459,3704,3900,4025,4124,4227,4288,4245,4104,3941,3818,3739,3692,3687,
-3720,3721,3592,3311,2981,2740,2636,2608,2575,2519,2473,2458,2452,2436,2415,2407,2409,2403,2376,2337,2300,
-2267,2229,2181,2130,2085,2051,2023,1990,1946,1891,1837,1788,1744,1694,1638,1580,1522,1461,1389,1307,1221,
-1131,1031,925,828,759,716,683,642,592,547,520,517,531,557,591,626,650,651,631,606,589,
-574,542,481,404,330,260,177,77,-6,-33,-2,39,33,-38,-151,-267,-378,-492,-608,-705,-758,
--772,-779,-813,-884,-968,-1030,-1055,-1052,-1040,-1031,-1022,-1012,-1002,-1002,-1014,-1035,-1057,-1079,-1101,-1126,-1152,
--1165,-1152,-1106,-1040,-980,-946,-936,-934,-928,-915,-897,-871,-834,-791,-752,-721,-695,-663,-626,-591,-559,
--528,-494,-458,-426,-400,-379,-361,-345,-332,-319,-308,-296,-284,-271,-257,-244,-235,-227,-216,-200,-185,
--173,-164,-153,-136,-116,-99,-87,-76,-59,-34,-2,29,59,85,110,133,157,181,206,229,251,
-272,295,318,341,364,386,408,431,454,475,496,519,542,565,588,611,637,662,685,706,729,
-753,777,801,823,846,871,895,919,942,968,996,1025,1054,1083,1111,1137,1160,1181,1207,1239,1273,
-1303,1325,1342,1353,1359,1358,1356,1357,1367,1381,1394,1401,1406,1411,1418,1425,1431,1437,1443,1450,1458,
-1467,1475,1484,1493,1505,1518,1530,1541,1550,1560,1572,1587,1604,1622,1638,1655,1674,1698,1722,1743,1758,
-1773,1791,1810,1830,1849,1868,1888,1907,1926,1946,1968,1989,2008,2029,2056,2060,2093,2124,2150,2174,2198,
-2219,2234,2251,2281,2330,2389,2446,2498,2542,2571,2574,2549,2512,2487,2483,2491,2497,2495,2489,2483,2483,
-2491,2507,2522,2527,2523,2521,2527,2536,2536,2528,2525,2533,2544,2544,2534,2525,2527,2536,2544,2559,2594,
-2646,2700,2741,2776,2822,2891,2969,3037,3079,3097,3107,3122,3151,3190,3227,3259,3291,3329,3359,3353,3297,
-3213,3148,3134,3165,3209,3244,3263,3258,3216,3131,3029,2953,2927,2936,2951,2954,2948,2937,2925,2916,2923,
-2948,2976,2981,2960,2936,2932,2943,2947,2929,2902,2890,2899,2914,2917,2908,2901,2908,2925,2941,2953,2966,
-2986,3012,3031,3031,3012,2989,2972,2956,2924,2866,2786,2690,2585,2475,2380,2326,2312,2306,2260,2150,1992,
-1832,1711,1642,1611,1596,1577,1551,1524,1500,1470,1428,1382,1356,1357,1354,1302,1185,1040,920,849,808,
-766,717,676,659,658,662,665,674,695,721,746,767,784,799,809,811,807,798,780,748,698,
-640,602,616,697,823,945,1022,1051,1063,1082,1105,1106,1077,1037,1015,1016,1014,985,931,873,825,
-784,736,681,631,592,560,529,505,496,497,492,473,449,435,434,436,434,433,442,459,476,
-493,512,534,552,560,566,574,583,583,572,560,553,545,527,502,480,466,453,439,431,437,
-450,459,460,465,482,502,511,509,515,541,579,611,630,643,661,680,684,667,640,623,632,
-654,661,635,584,538,515,500,466,406,347,320,328,346,346,322,282,239,197,158,126,101,
-78,51,19,-11,-40,-68,-97,-126,-154,-182,-215,-252,-292,-331,-371,-413,-459,-510,-563,-615,-665,
--714,-765,-821,-877,-929,-979,-1029,-1084,-1140,-1193,-1239,-1279,-1318,-1361,-1409,-1460,-1513,-1568,-1626,-1681,-1727,
--1762,-1790,-1819,-1856,-1899,-1949,-2003,-2059,-2111,-2151,-2183,-2216,-2255,-2297,-2337,-2374,-2413,-2454,-2493,-2525,-2552,
--2577,-2605,-2640,-2677,-2705,-2708,-2683,-2654,-2663,-2731,-2844,-2960,-3053,-3118,-3165,-3200,-3225,-3254,-3309,-3389,-3469,
--3517,-3531,-3535,-3552,-3584,-3615,-3632,-3644,-3664,-3697,-3735,-3769,-3796,-3819,-3843,-3866,-3885,-3896,-3902,-3907,-3916,
--3933,-3949,-3957,-3953,-3946,-3943,-3947,-3950,-3944,-3935,-3932,-3944,-3961,-3973,-3972,-3962,-3949,-3935,-3920,-3906,-3899,
--3896,-3891,-3878,-3861,-3846,-3835,-3824,-3812,-3801,-3794,-3793,-3794,-3796,-3798,-3799,-3797,-3797,-3802,-3812,-3822,-3825,
--3822,-3820,-3821,-3824,-3826,-3828,-3828,-3825,-3821,-3819,-3821,-3822,-3813,-3792,-3761,-3722,-3670,-3601,-3516,-3419,-3315,
--3205,-3093,-2983,-2875,-2764,-2655,-2559,-2482,-2407,-2312,-2198,-2101,-2051,-2036,-2016,-1964,-1896,-1848,-1831,-1825,-1811,
--1792,-1789,-1806,-1830,-1844,-1846,-1836,-1813,-1774,-1725,-1677,-1637,-1601,-1562,-1516,-1470,-1431,-1399,-1371,-1344,-1318,
--1299,-1290,-1287,-1278,-1253,-1216,-1179,-1152,-1132,-1114,-1100,-1097,-1107,-1123,-1134,-1133,-1113,-1070,-1010,-948,-906,
--885,-874,-859,-845,-836,-825,-789,-717,-625,-536,-459,-388,-320,-263,-231,-221,-224,-229,-239,-250,-249,
--210,-117,23,182,322,424,489,538,584,627,664,702,755,831,918,996,1054,1098,1137,1176,1216,
-1264,1324,1395,1463,1518,1561,1600,1641,1688,1742,1804,1873,1940,1999,2048,2096,2150,2213,2279,2340,2394,
-2441,2487,2540,2602,2674,2752,2832,2909,2975,3030,3080,3136,3200,3257,3289,3300,3310,3340,3390,3443,3478,
-3499,3520,3552,3595,3637,3676,3717,3773,3851,3945,4039,4117,4177,4221,4246,4242,4213,4184,4184,4203,4183,
-4068,3869,3675,3580,3607,3690,3741,3722,3663,3615,3603,3619,3643,3670,3706,3752,3787,3794,3784,3793,3851,
-3939,4005,4011,3978,3956,3978,4035,4094,4144,4187,4226,4252,4267,4283,4309,4340,4361,4367,4363,4349,4322,
-4282,4245,4221,4211,4220,4259,4331,4412,4466,4489,4516,4583,4673,4739,4753,4743,4751,4789,4832,4859,4872,
-4886,4904,4920,4933,4948,4968,4982,4986,4982,4974,4965,4959,4959,4968,4980,4988,4989,4988,4987,4982,4971,
-4955,4937,4916,4894,4874,4862,4853,4837,4813,4790,4775,4765,4752,4736,4720,4713,4716,4728,4747,4764,4777,
-4801,4853,4926,4976,4965,4911,4870,4873,4878,4825,4708,4571,4428,4204,3816,3290,2792,2513,2521,2734,3008,
-3238,3385,3442,3418,3344,3266,3223,3211,3197,3156,3092,3030,2981,2936,2881,2809,2725,2639,2555,2471,2385,
-2302,2226,2157,2089,2020,1955,1902,1859,1822,1783,1742,1700,1651,1588,1515,1444,1389,1354,1329,1304,1276,
-1245,1211,1169,1122,1074,1028,985,943,906,875,843,807,769,738,718,707,692,667,633,594,556,
-525,500,476,443,399,346,296,253,218,193,177,164,144,113,78,49,30,14,-1,-16,-27,
--40,-59,-81,-97,-105,-110,-113,-111,-101,-90,-93,-112,-137,-158,-176,-201,-230,-259,-287,-316,-342,
--355,-354,-355,-378,-412,-431,-419,-392,-382,-397,-414,-412,-395,-383,-385,-396,-405,-419,-446,-486,-526,
--557,-584,-615,-650,-684,-712,-741,-777,-822,-866,-902,-928,-951,-977,-1005,-1030,-1051,-1071,-1093,-1117,-1141,
--1163,-1182,-1199,-1214,-1227,-1239,-1253,-1268,-1283,-1297,-1309,-1317,-1322,-1326,-1329,-1331,-1332,-1330,-1329,-1329,-1332,
--1335,-1337,-1338,-1338,-1336,-1329,-1319,-1311,-1307,-1305,-1298,-1286,-1271,-1258,-1248,-1239,-1227,-1215,-1204,-1195,-1186,
--1177,-1167,-1160,-1156,-1152,-1146,-1137,-1126,-1115,-1103,-1092,-1081,-1070,-1058,-1045,-1034,-1023,-1013,-1000,-987,-975,
--965,-957,-947,-936,-926,-916,-906,-896,-887,-881,-876,-872,-865,-856,-846,-837,-831,-826,-819,-810,-798,
--788,-782,-775,-767,-757,-747,-740,-733,-722,-708,-693,-678,-663,-647,-634,-625,-621,-617,-610,-601,-594,
--589,-585,-579,-570,-560,-553,-548,-540,-528,-513,-505,-508,-518,-522,-512,-491,-473,-467,-469,-467,-455,
--439,-426,-419,-413,-403,-389,-378,-371,-367,-361,-352,-343,-337,-334,-330,-325,-322,-320,-316,-305,-291,
--280,-273,-268,-262,-254,-248,-246,-243,-239,-231,-224,-214,-202,-188,-178,-172,-168,-160,-148,-133,-115,
--98,-82,-68,-57,-46,-35,-26,-19,-10,2,21,38,51,60,67,73,78,81,89,101,114,
-125,135,147,162,175,184,191,202,218,237,255,273,294,312,325,332,337,345,353,362,375,
-394,417,434,445,458,479,508,535,555,570,587,609,629,646,663,688,721,754,776,785,789,
-804,839,888,936,974,1003,1037,1080,1129,1177,1221,1262,1299,1324,1338,1350,1377,1422,1475,1521,1558,
-1591,1626,1664,1704,1747,1783,1803,1810,1811,1795,1713,1532,1309,1207,1371,1794,2301,2707,2969,3177,3413,
-3661,3858,4000,4134,4265,4312,4194,3938,3667,3484,3406,3394,3425,3474,3479,3361,3108,2822,2627,2564,2566,
-2553,2504,2455,2432,2424,2412,2400,2399,2401,2387,2350,2304,2267,2236,2200,2152,2102,2064,2039,2016,1983,
-1938,1888,1841,1797,1750,1693,1631,1571,1512,1448,1374,1292,1209,1119,1021,921,836,780,746,714,669,
-619,580,561,563,579,602,628,648,651,631,598,574,569,569,547,491,415,343,279,204,109,
-20,-23,-13,14,9,-53,-158,-277,-399,-519,-627,-699,-723,-716,-717,-757,-837,-931,-1005,-1042,-1049,
--1040,-1029,-1021,-1019,-1024,-1037,-1057,-1080,-1106,-1132,-1155,-1173,-1183,-1181,-1158,-1109,-1043,-983,-950,-945,-948,
--942,-921,-891,-856,-815,-770,-727,-692,-662,-632,-598,-561,-522,-482,-443,-410,-388,-373,-360,-347,-333,
--319,-300,-276,-249,-227,-211,-201,-194,-187,-179,-167,-153,-141,-133,-127,-117,-100,-80,-63,-50,-36,
--17,7,36,65,91,116,141,166,193,220,246,268,287,306,327,351,376,398,419,442,467,
-492,515,535,554,574,595,618,641,665,689,712,734,757,782,806,828,849,871,894,917,941,
-966,993,1023,1053,1082,1110,1138,1163,1184,1203,1224,1251,1285,1317,1343,1361,1371,1376,1377,1377,1379,
-1386,1396,1407,1415,1420,1423,1427,1432,1438,1445,1452,1458,1464,1471,1478,1486,1494,1504,1516,1528,1540,
-1551,1564,1579,1595,1611,1626,1643,1661,1683,1705,1724,1741,1757,1776,1797,1818,1836,1853,1872,1893,1915,
-1937,1961,1983,2002,2016,2034,2060,2066,2100,2134,2164,2191,2216,2236,2251,2269,2303,2353,2412,2463,2499,
-2517,2517,2499,2470,2445,2437,2446,2463,2481,2496,2508,2514,2513,2512,2515,2518,2516,2509,2508,2519,2532,
-2536,2532,2531,2540,2550,2549,2537,2528,2531,2540,2550,2566,2599,2647,2700,2744,2784,2829,2882,2939,2992,
-3038,3076,3105,3127,3150,3180,3212,3238,3259,3282,3303,3306,3275,3223,3185,3186,3218,3255,3280,3287,3272,
-3221,3132,3030,2954,2927,2941,2967,2987,2999,3001,2996,2995,3015,3057,3099,3110,3088,3056,3037,3026,3004,
-2963,2924,2912,2926,2945,2948,2938,2933,2944,2965,2983,2995,3014,3053,3106,3146,3148,3118,3081,3053,3024,
-2969,2882,2784,2696,2614,2526,2438,2378,2361,2357,2309,2186,2013,1847,1736,1683,1665,1654,1637,1615,1593,
-1570,1540,1497,1451,1418,1404,1386,1328,1219,1089,982,918,878,834,782,739,719,718,721,724,734,
-755,783,811,834,854,870,878,877,870,860,844,811,755,691,654,680,777,910,1027,1092,1110,
-1117,1137,1163,1169,1146,1109,1087,1085,1085,1069,1036,996,955,907,844,774,713,667,632,604,584,
-576,575,566,545,523,514,516,518,512,509,518,537,556,572,586,604,620,630,638,645,650,
-646,633,622,614,603,583,559,542,536,528,514,505,516,540,558,557,548,549,565,585,599,
-615,641,675,705,722,730,739,746,739,713,677,656,662,681,684,653,603,562,543,530,502,
-460,429,424,435,433,402,351,300,262,233,209,186,162,134,100,66,34,6,-20,-49,-77,
--103,-129,-160,-195,-233,-270,-307,-346,-391,-441,-494,-546,-595,-646,-699,-754,-808,-857,-905,-956,-1012,
--1069,-1120,-1164,-1204,-1244,-1289,-1341,-1397,-1454,-1511,-1565,-1612,-1648,-1675,-1700,-1734,-1779,-1832,-1887,-1943,-1998,
--2045,-2083,-2114,-2145,-2183,-2225,-2267,-2307,-2346,-2386,-2423,-2455,-2482,-2509,-2538,-2573,-2612,-2643,-2654,-2643,-2632,
--2652,-2717,-2808,-2899,-2977,-3047,-3111,-3156,-3178,-3195,-3241,-3324,-3412,-3466,-3479,-3477,-3489,-3519,-3548,-3566,-3580,
--3601,-3632,-3666,-3701,-3734,-3765,-3792,-3812,-3828,-3844,-3858,-3869,-3876,-3886,-3897,-3906,-3905,-3900,-3899,-3899,-3891,
--3867,-3841,-3838,-3868,-3915,-3952,-3962,-3952,-3934,-3917,-3905,-3899,-3899,-3899,-3888,-3865,-3840,-3821,-3811,-3804,-3797,
--3791,-3789,-3789,-3790,-3794,-3803,-3812,-3815,-3815,-3819,-3832,-3846,-3853,-3850,-3846,-3848,-3859,-3873,-3883,-3882,-3869,
--3854,-3844,-3842,-3842,-3832,-3812,-3786,-3756,-3714,-3655,-3578,-3490,-3396,-3293,-3183,-3071,-2957,-2840,-2722,-2616,-2526,
--2436,-2327,-2203,-2103,-2057,-2055,-2049,-2010,-1953,-1911,-1896,-1886,-1865,-1840,-1834,-1851,-1877,-1895,-1900,-1891,-1864,
--1821,-1769,-1725,-1694,-1665,-1628,-1580,-1531,-1490,-1462,-1438,-1413,-1381,-1350,-1328,-1318,-1312,-1297,-1270,-1242,-1223,
--1210,-1196,-1183,-1179,-1191,-1212,-1225,-1223,-1202,-1163,-1110,-1055,-1014,-995,-990,-989,-990,-996,-997,-977,-927,
--855,-781,-710,-639,-570,-516,-491,-490,-493,-485,-466,-437,-387,-296,-152,27,207,349,438,486,518,
-551,589,631,678,734,801,871,934,987,1032,1073,1107,1140,1180,1236,1305,1377,1441,1494,1538,1578,
-1619,1667,1728,1800,1873,1935,1987,2037,2092,2155,2223,2290,2350,2402,2449,2500,2561,2635,2717,2795,2864,
-2921,2974,3028,3085,3139,3177,3195,3202,3218,3255,3311,3368,3408,3432,3453,3483,3525,3571,3611,3650,3702,
-3777,3870,3963,4040,4099,4146,4173,4169,4135,4101,4100,4124,4119,4030,3862,3688,3594,3611,3694,3760,3754,
-3679,3586,3531,3532,3569,3613,3652,3691,3729,3752,3750,3742,3763,3817,3872,3892,3881,3876,3906,3962,4020,
-4069,4114,4155,4185,4200,4213,4234,4261,4282,4292,4292,4278,4248,4205,4168,4147,4139,4146,4178,4242,4318,
-4372,4399,4431,4501,4595,4667,4689,4684,4693,4727,4765,4786,4796,4812,4838,4863,4881,4895,4909,4924,4932,
-4931,4923,4912,4907,4912,4926,4942,4954,4963,4968,4968,4958,4940,4921,4903,4882,4856,4835,4827,4824,4814,
-4794,4776,4765,4757,4743,4724,4714,4716,4725,4733,4739,4748,4765,4800,4861,4930,4966,4943,4886,4850,4853,
-4844,4766,4626,4483,4342,4115,3708,3165,2678,2441,2494,2727,2997,3231,3411,3517,3518,3422,3293,3204,3177,
-3169,3137,3074,3007,2958,2920,2872,2804,2721,2637,2555,2474,2393,2314,2240,2171,2101,2029,1961,1902,1854,
-1811,1770,1731,1693,1648,1587,1515,1445,1391,1354,1325,1298,1273,1250,1221,1181,1132,1082,1034,987,940,
-900,870,844,811,772,736,712,697,682,657,622,580,540,507,485,464,432,385,331,283,245,
-211,181,159,145,130,106,75,49,29,11,-9,-30,-43,-50,-63,-83,-103,-115,-120,-122,-118,
--105,-90,-87,-102,-127,-149,-166,-185,-210,-237,-265,-295,-324,-343,-348,-350,-363,-388,-411,-419,-418,
--421,-428,-429,-418,-405,-404,-410,-408,-392,-378,-384,-414,-457,-498,-538,-579,-620,-657,-688,-720,-757,
--801,-842,-875,-902,-928,-958,-990,-1020,-1046,-1068,-1088,-1108,-1128,-1149,-1170,-1191,-1209,-1223,-1234,-1244,-1256,
--1270,-1286,-1299,-1309,-1315,-1319,-1324,-1329,-1331,-1333,-1335,-1338,-1342,-1345,-1345,-1344,-1344,-1341,-1335,-1326,-1317,
--1310,-1305,-1299,-1289,-1276,-1265,-1255,-1245,-1235,-1224,-1212,-1201,-1191,-1181,-1172,-1164,-1158,-1152,-1146,-1139,-1129,
--1117,-1106,-1096,-1089,-1080,-1070,-1058,-1047,-1037,-1026,-1015,-1003,-994,-985,-976,-966,-956,-948,-942,-934,-923,
--913,-905,-901,-898,-893,-886,-877,-869,-863,-857,-850,-840,-827,-815,-806,-799,-791,-782,-774,-767,-760,
--751,-739,-725,-709,-691,-672,-654,-641,-634,-631,-629,-624,-619,-614,-610,-604,-596,-586,-577,-569,-562,
--552,-542,-536,-536,-539,-536,-525,-509,-496,-491,-490,-485,-476,-463,-451,-441,-430,-418,-407,-400,-396,
--392,-384,-373,-364,-357,-351,-346,-343,-344,-345,-341,-327,-310,-297,-292,-289,-284,-276,-269,-264,-260,
--255,-250,-244,-235,-222,-207,-196,-191,-186,-175,-159,-142,-127,-114,-102,-91,-81,-70,-58,-46,-35,
--25,-13,1,15,28,40,54,68,80,88,98,109,119,127,134,143,156,170,180,189,202,
-219,240,260,277,289,296,301,309,321,335,344,351,363,385,410,429,437,443,455,474,493,
-507,522,545,574,604,631,655,681,709,736,755,769,782,804,837,879,920,955,988,1026,1070,
-1118,1164,1204,1242,1277,1304,1323,1340,1369,1413,1464,1508,1537,1556,1579,1614,1663,1713,1749,1763,1761,
-1756,1731,1642,1473,1295,1256,1466,1884,2346,2704,2947,3160,3398,3629,3802,3935,4077,4216,4248,4089,3779,
-3461,3251,3162,3146,3167,3203,3207,3118,2928,2717,2584,2554,2565,2548,2492,2437,2410,2404,2400,2397,2400,
-2399,2379,2336,2286,2247,2214,2176,2129,2083,2048,2023,1996,1960,1917,1875,1834,1792,1741,1682,1622,1563,
-1503,1434,1359,1280,1200,1112,1016,924,852,807,778,747,708,670,646,637,643,655,669,677,673,
-652,618,585,567,567,569,554,514,458,399,337,258,160,69,16,9,18,4,-53,-148,-265,
--392,-518,-621,-679,-691,-681,-689,-739,-823,-916,-990,-1032,-1045,-1039,-1026,-1019,-1025,-1044,-1068,-1091,-1113,
--1137,-1162,-1179,-1182,-1172,-1156,-1134,-1099,-1051,-1005,-979,-975,-974,-958,-922,-877,-833,-792,-751,-710,-672,
--639,-607,-574,-535,-491,-445,-406,-381,-368,-358,-344,-326,-306,-286,-259,-223,-186,-158,-145,-142,-141,
--134,-124,-112,-103,-96,-90,-82,-69,-51,-31,-12,3,17,33,53,76,98,120,141,164,190,
-218,247,274,296,315,335,359,385,410,432,452,475,501,528,551,569,585,603,625,649,673,
-694,714,736,760,785,811,835,857,879,901,923,946,969,994,1020,1049,1077,1103,1128,1153,1177,
-1198,1216,1235,1260,1293,1329,1360,1382,1393,1398,1399,1399,1399,1401,1404,1409,1415,1421,1424,1427,1432,
-1440,1449,1456,1461,1466,1472,1480,1487,1495,1503,1512,1523,1535,1550,1567,1586,1603,1618,1634,1651,1669,
-1687,1703,1718,1735,1755,1779,1801,1820,1836,1853,1874,1897,1922,1946,1969,1991,2007,2021,2039,2066,2074,
-2107,2141,2174,2204,2231,2254,2274,2295,2327,2372,2424,2470,2496,2496,2471,2433,2403,2393,2403,2421,2435,
-2447,2465,2488,2504,2506,2499,2493,2492,2492,2490,2493,2505,2519,2527,2527,2529,2539,2549,2549,2540,2535,
-2539,2549,2561,2578,2609,2654,2705,2753,2798,2839,2876,2912,2956,3013,3074,3119,3142,3154,3174,3204,3234,
-3252,3263,3270,3265,3240,3205,3185,3195,3228,3259,3272,3264,3239,3191,3119,3040,2982,2962,2975,3005,3038,
-3062,3069,3063,3065,3096,3155,3207,3220,3189,3144,3108,3079,3040,2991,2953,2947,2967,2988,2991,2981,2978,
-2989,3007,3019,3027,3051,3109,3185,3240,3243,3201,3147,3104,3057,2978,2869,2765,2692,2635,2561,2469,2398,
-2379,2384,2344,2217,2032,1862,1759,1723,1718,1710,1693,1671,1650,1627,1596,1554,1509,1472,1444,1407,1338,
-1232,1115,1023,969,936,897,848,805,783,779,782,785,794,815,845,875,901,920,934,940,936,
-928,917,899,863,806,746,720,758,859,987,1090,1142,1154,1159,1175,1198,1206,1191,1165,1144,1136,
-1134,1130,1121,1106,1079,1028,954,871,800,748,713,686,666,655,650,641,626,611,604,602,597,
-590,589,602,625,645,657,668,680,692,700,705,710,711,705,692,680,671,658,639,619,611,
-612,609,595,585,598,630,655,652,629,615,628,663,701,733,760,785,804,809,802,792,784,
-774,756,732,715,710,711,697,663,624,598,591,588,572,547,529,524,517,486,433,375,333,
-309,293,274,248,218,183,148,114,85,58,30,2,-24,-50,-78,-109,-143,-177,-211,-245,-283,
--327,-375,-425,-476,-528,-580,-634,-687,-737,-784,-832,-885,-941,-995,-1043,-1085,-1126,-1171,-1220,-1275,-1333,
--1391,-1447,-1497,-1537,-1567,-1591,-1619,-1659,-1712,-1771,-1829,-1884,-1933,-1976,-2011,-2041,-2073,-2110,-2152,-2196,-2239,
--2279,-2317,-2352,-2385,-2418,-2448,-2478,-2509,-2544,-2578,-2603,-2616,-2630,-2663,-2720,-2785,-2846,-2906,-2977,-3052,-3107,
--3126,-3134,-3171,-3254,-3348,-3410,-3427,-3426,-3440,-3472,-3503,-3522,-3534,-3552,-3578,-3608,-3639,-3674,-3709,-3737,-3754,
--3769,-3788,-3810,-3825,-3830,-3834,-3843,-3856,-3863,-3864,-3862,-3854,-3826,-3776,-3728,-3718,-3764,-3842,-3911,-3946,-3948,
--3934,-3918,-3906,-3901,-3900,-3899,-3886,-3863,-3837,-3816,-3801,-3788,-3780,-3781,-3787,-3792,-3792,-3796,-3809,-3826,-3836,
--3836,-3840,-3854,-3872,-3880,-3873,-3864,-3866,-3885,-3909,-3926,-3926,-3910,-3891,-3879,-3875,-3869,-3852,-3826,-3800,-3775,
--3744,-3696,-3634,-3562,-3481,-3386,-3277,-3161,-3044,-2924,-2801,-2686,-2582,-2478,-2357,-2225,-2123,-2083,-2091,-2097,-2066,
--2011,-1969,-1954,-1948,-1929,-1904,-1890,-1897,-1912,-1926,-1932,-1927,-1903,-1861,-1814,-1779,-1756,-1732,-1691,-1637,-1584,
--1547,-1527,-1513,-1492,-1457,-1415,-1381,-1364,-1358,-1347,-1326,-1303,-1291,-1289,-1284,-1275,-1271,-1280,-1293,-1297,-1283,
--1256,-1223,-1186,-1151,-1124,-1113,-1115,-1121,-1125,-1126,-1122,-1103,-1066,-1015,-960,-903,-842,-782,-738,-718,-711,
--694,-650,-582,-495,-387,-250,-83,91,243,352,417,454,481,513,553,603,660,721,777,826,870,
-916,965,1012,1050,1081,1117,1170,1238,1310,1375,1431,1479,1520,1561,1608,1668,1739,1809,1871,1924,1975,
-2031,2093,2160,2228,2293,2352,2405,2460,2523,2599,2678,2749,2805,2851,2897,2948,3001,3044,3071,3086,3101,
-3131,3179,3237,3292,3334,3361,3379,3404,3442,3491,3540,3588,3642,3715,3803,3890,3961,4020,4070,4105,4106,
-4074,4038,4030,4049,4049,3980,3838,3678,3576,3574,3654,3748,3778,3713,3589,3483,3452,3490,3547,3592,3627,
-3668,3705,3715,3701,3695,3721,3767,3799,3808,3816,3847,3897,3949,3996,4043,4088,4120,4135,4145,4162,4186,
-4207,4218,4219,4209,4184,4147,4112,4088,4077,4082,4112,4170,4235,4281,4306,4341,4415,4512,4588,4617,4621,
-4637,4673,4708,4725,4731,4743,4772,4806,4833,4849,4860,4869,4877,4880,4875,4864,4858,4865,4884,4905,4921,
-4933,4939,4935,4918,4894,4876,4865,4852,4831,4810,4799,4796,4791,4777,4764,4757,4748,4733,4717,4713,4722,
-4734,4737,4735,4738,4755,4794,4855,4919,4946,4918,4864,4836,4838,4812,4705,4538,4378,4228,3990,3571,3031,
-2576,2392,2495,2746,3003,3221,3408,3545,3579,3492,3343,3221,3164,3143,3111,3055,2992,2939,2894,2842,2775,
-2697,2617,2540,2464,2390,2318,2250,2183,2113,2041,1971,1909,1854,1804,1759,1720,1686,1645,1587,1516,1448,
-1397,1360,1328,1298,1272,1250,1224,1185,1136,1086,1038,989,940,899,869,845,815,777,740,712,691,
-669,641,607,567,527,493,470,449,418,372,321,278,246,214,179,148,129,116,96,70,45,
-28,12,-9,-32,-47,-53,-62,-80,-103,-120,-129,-132,-129,-115,-98,-89,-97,-118,-141,-160,-180,
--205,-233,-261,-290,-317,-338,-350,-358,-369,-387,-405,-417,-427,-440,-449,-449,-442,-442,-455,-469,-461,
--429,-393,-378,-393,-426,-465,-506,-548,-588,-626,-663,-702,-746,-788,-823,-850,-875,-902,-935,-970,-1006,
--1038,-1064,-1085,-1101,-1118,-1137,-1157,-1178,-1197,-1213,-1226,-1236,-1248,-1263,-1279,-1293,-1304,-1311,-1318,-1324,-1331,
--1337,-1343,-1348,-1352,-1354,-1353,-1351,-1349,-1348,-1347,-1343,-1336,-1326,-1315,-1306,-1298,-1290,-1281,-1271,-1261,-1252,
--1243,-1234,-1222,-1210,-1199,-1189,-1181,-1173,-1165,-1157,-1149,-1140,-1131,-1120,-1111,-1103,-1097,-1090,-1081,-1071,-1061,
--1052,-1041,-1030,-1019,-1010,-1001,-991,-980,-971,-967,-965,-959,-949,-937,-927,-922,-918,-914,-909,-904,-899,
--893,-887,-879,-869,-857,-844,-832,-822,-813,-804,-795,-788,-782,-774,-762,-748,-734,-720,-703,-684,-666,
--654,-650,-650,-650,-648,-643,-637,-630,-620,-608,-596,-588,-582,-578,-575,-572,-569,-564,-555,-542,-531,
--524,-521,-516,-508,-498,-488,-478,-465,-451,-437,-429,-427,-427,-424,-417,-408,-398,-388,-379,-373,-373,
--377,-379,-372,-355,-336,-322,-316,-315,-311,-303,-294,-286,-279,-273,-270,-266,-259,-245,-229,-216,-208,
--199,-185,-166,-148,-135,-125,-115,-103,-92,-80,-69,-58,-46,-35,-22,-8,3,15,27,42,59,
-75,89,101,113,123,131,137,144,156,170,185,198,210,224,242,262,279,286,285,284,290,
-307,325,339,349,363,385,408,424,433,441,451,460,467,475,491,517,550,583,613,640,663,
-681,694,708,727,755,790,826,861,892,924,961,1002,1045,1088,1127,1164,1201,1238,1269,1294,1317,
-1346,1388,1438,1483,1514,1531,1549,1581,1630,1683,1717,1728,1727,1719,1682,1580,1421,1294,1333,1602,2024,
-2445,2760,2987,3206,3440,3640,3767,3853,3955,4059,4071,3916,3635,3347,3143,3026,2964,2942,2960,2984,2954,
-2848,2715,2626,2597,2583,2541,2473,2417,2395,2394,2394,2393,2395,2392,2371,2330,2281,2236,2196,2155,2110,
-2069,2036,2004,1967,1926,1887,1851,1815,1772,1721,1666,1612,1555,1490,1418,1343,1271,1194,1108,1015,931,
-871,834,807,779,753,734,726,724,727,732,736,728,703,666,634,613,604,598,589,576,558,
-528,477,396,292,184,102,64,60,61,38,-18,-105,-217,-348,-482,-590,-650,-665,-668,-693,-754,
--839,-925,-994,-1036,-1053,-1048,-1032,-1022,-1030,-1052,-1078,-1098,-1114,-1132,-1151,-1158,-1148,-1129,-1114,-1106,-1093,
--1065,-1030,-1004,-993,-983,-957,-911,-856,-807,-767,-728,-689,-650,-615,-582,-548,-509,-466,-422,-386,-363,
--349,-333,-309,-280,-251,-226,-199,-167,-136,-115,-106,-102,-95,-81,-68,-60,-58,-54,-45,-30,-11,
-8,27,45,61,73,84,97,114,135,155,173,190,211,237,265,290,312,333,356,383,412,
-438,460,481,503,528,554,578,597,614,633,656,681,704,723,740,760,784,812,839,863,884,
-906,929,952,975,998,1020,1045,1071,1096,1120,1142,1163,1185,1206,1225,1244,1266,1296,1331,1365,1391,
-1405,1410,1413,1415,1416,1414,1411,1411,1415,1420,1424,1426,1430,1438,1446,1453,1458,1463,1471,1480,1489,
-1497,1506,1514,1524,1536,1552,1571,1590,1607,1622,1639,1656,1672,1684,1695,1709,1729,1753,1776,1795,1811,
-1829,1850,1876,1903,1929,1952,1973,1992,2010,2026,2047,2074,2085,2114,2145,2177,2208,2239,2268,2296,2324,
-2356,2393,2436,2475,2497,2489,2451,2402,2368,2364,2382,2401,2407,2411,2426,2453,2477,2482,2473,2464,2463,
-2468,2472,2477,2488,2501,2512,2519,2527,2539,2551,2554,2550,2548,2551,2561,2573,2592,2623,2665,2714,2766,
-2813,2849,2872,2895,2937,3008,3086,3141,3157,3154,3162,3192,3227,3248,3251,3240,3219,3187,3156,3146,3167,
-3206,3238,3243,3225,3191,3148,3099,3052,3018,3007,3018,3048,3087,3117,3124,3112,3112,3150,3219,3278,3288,
-3249,3192,3143,3102,3056,3009,2981,2985,3010,3031,3034,3028,3027,3036,3045,3044,3043,3069,3140,3236,3308,
-3313,3256,3175,3100,3024,2926,2815,2725,2676,2638,2568,2469,2391,2375,2392,2362,2235,2045,1874,1780,1757,
-1760,1755,1737,1714,1692,1665,1632,1594,1556,1521,1482,1426,1341,1232,1125,1049,1009,984,952,909,869,
-846,841,842,846,856,878,908,939,964,981,991,994,992,985,973,951,911,855,806,796,847,
-950,1066,1154,1198,1210,1213,1222,1232,1233,1224,1209,1198,1192,1193,1199,1207,1209,1190,1140,1062,973,
-894,838,799,769,744,727,718,713,708,701,693,686,678,676,684,702,724,741,750,757,765,
-771,773,774,773,770,760,745,730,717,705,690,679,679,687,688,678,669,681,715,745,747,
-722,700,711,754,809,852,877,887,886,873,850,827,816,818,824,825,815,795,768,735,701,
-678,672,676,672,653,626,603,583,556,511,458,415,390,376,359,332,299,263,229,197,168,
-143,117,89,59,30,0,-30,-63,-96,-126,-156,-189,-226,-268,-312,-359,-408,-459,-512,-565,-616,
--664,-711,-759,-812,-866,-916,-959,-1001,-1046,-1096,-1149,-1205,-1263,-1321,-1374,-1420,-1455,-1484,-1513,-1548,-1595,
--1653,-1714,-1771,-1820,-1861,-1898,-1932,-1964,-1999,-2038,-2082,-2127,-2171,-2210,-2245,-2280,-2317,-2355,-2391,-2421,-2448,
--2478,-2514,-2551,-2585,-2620,-2664,-2715,-2762,-2800,-2846,-2912,-2990,-3047,-3065,-3066,-3098,-3180,-3280,-3350,-3375,-3380,
--3398,-3432,-3463,-3479,-3489,-3504,-3528,-3553,-3580,-3611,-3645,-3671,-3686,-3699,-3719,-3743,-3760,-3765,-3769,-3785,-3810,
--3829,-3837,-3834,-3815,-3770,-3700,-3634,-3617,-3669,-3768,-3864,-3924,-3944,-3938,-3924,-3910,-3901,-3899,-3896,-3884,-3865,
--3843,-3822,-3799,-3777,-3765,-3771,-3789,-3802,-3805,-3809,-3823,-3843,-3854,-3853,-3853,-3868,-3890,-3902,-3896,-3884,-3885,
--3902,-3927,-3943,-3945,-3934,-3922,-3915,-3912,-3899,-3873,-3839,-3810,-3788,-3763,-3727,-3680,-3625,-3559,-3473,-3366,-3251,
--3134,-3014,-2890,-2768,-2655,-2541,-2411,-2274,-2170,-2132,-2145,-2158,-2131,-2078,-2035,-2021,-2020,-2008,-1985,-1965,-1955,
--1952,-1952,-1954,-1952,-1935,-1902,-1864,-1838,-1825,-1806,-1768,-1713,-1659,-1621,-1601,-1590,-1574,-1542,-1496,-1453,-1425,
--1412,-1400,-1380,-1361,-1356,-1364,-1372,-1371,-1366,-1366,-1365,-1352,-1324,-1291,-1266,-1250,-1238,-1228,-1226,-1232,-1240,
--1242,-1236,-1222,-1198,-1164,-1122,-1076,-1025,-972,-921,-883,-859,-832,-781,-694,-579,-447,-303,-149,4,138,
-238,305,353,394,433,471,514,568,633,699,751,786,815,852,902,953,996,1032,1074,1130,1196,
-1262,1321,1371,1416,1459,1503,1553,1614,1682,1751,1813,1871,1929,1989,2051,2113,2174,2234,2292,2349,2408,
-2474,2548,2622,2686,2735,2774,2813,2856,2900,2935,2960,2983,3014,3060,3114,3168,3216,3255,3283,3302,3323,
-3358,3409,3466,3521,3577,3644,3724,3806,3878,3940,3998,4040,4049,4024,3992,3982,3994,3990,3925,3791,3627,
-3499,3464,3536,3662,3749,3722,3594,3454,3390,3419,3485,3536,3569,3606,3645,3663,3650,3634,3649,3690,3728,
-3747,3761,3792,3838,3888,3933,3978,4021,4050,4063,4072,4091,4121,4144,4153,4148,4136,4117,4091,4062,4037,
-4024,4028,4059,4113,4170,4210,4237,4278,4354,4450,4525,4559,4571,4591,4628,4665,4684,4687,4693,4715,4749,
-4785,4809,4820,4824,4828,4835,4836,4827,4818,4822,4841,4863,4879,4887,4889,4883,4867,4846,4834,4832,4830,
-4816,4796,4780,4773,4767,4758,4749,4742,4734,4721,4711,4712,4723,4731,4729,4721,4722,4739,4779,4839,4896,
-4916,4885,4836,4815,4818,4780,4649,4455,4267,4090,3828,3402,2885,2484,2367,2518,2776,3003,3172,3324,3461,
-3530,3493,3381,3260,3175,3122,3077,3030,2979,2927,2870,2805,2735,2663,2590,2516,2444,2374,2308,2244,2181,
-2115,2048,1981,1919,1861,1808,1759,1719,1684,1643,1586,1516,1451,1404,1371,1339,1305,1273,1247,1218,1180,
-1133,1085,1038,991,944,903,873,848,817,779,743,714,687,659,626,592,556,518,482,456,435,
-405,360,312,274,247,218,180,144,120,106,89,62,38,23,13,-2,-22,-39,-47,-57,-77,
--103,-125,-137,-141,-139,-128,-111,-98,-101,-117,-138,-158,-180,-207,-239,-270,-299,-324,-344,-359,-372,
--388,-403,-412,-416,-425,-442,-460,-470,-474,-485,-508,-529,-527,-499,-461,-438,-437,-454,-479,-509,-540,
--570,-601,-639,-685,-735,-776,-805,-826,-848,-877,-912,-949,-987,-1022,-1052,-1075,-1093,-1111,-1129,-1147,-1164,
--1181,-1198,-1213,-1227,-1241,-1258,-1275,-1289,-1300,-1309,-1317,-1325,-1332,-1340,-1348,-1354,-1358,-1358,-1356,-1354,-1354,
--1355,-1354,-1351,-1344,-1333,-1320,-1309,-1302,-1297,-1291,-1282,-1271,-1262,-1254,-1246,-1236,-1224,-1213,-1202,-1194,-1185,
--1176,-1167,-1157,-1148,-1138,-1129,-1120,-1113,-1107,-1100,-1092,-1083,-1074,-1066,-1056,-1045,-1034,-1023,-1012,-1000,-989,
--982,-981,-982,-978,-969,-957,-947,-940,-935,-931,-928,-925,-922,-917,-910,-903,-894,-883,-871,-859,-848,
--837,-826,-816,-808,-802,-793,-779,-765,-753,-745,-736,-720,-700,-682,-673,-673,-676,-676,-671,-663,-654,
--644,-631,-618,-607,-602,-599,-598,-595,-591,-584,-574,-564,-556,-552,-548,-541,-531,-521,-513,-505,-493,
--479,-467,-460,-458,-457,-453,-448,-442,-433,-421,-408,-400,-400,-405,-406,-397,-378,-358,-345,-340,-337,
--333,-325,-316,-306,-297,-290,-287,-284,-277,-263,-246,-230,-219,-207,-193,-176,-161,-150,-140,-128,-113,
--99,-87,-77,-67,-56,-43,-29,-14,-1,9,20,34,50,68,85,101,116,129,138,145,151,
-161,175,192,208,219,229,242,258,274,281,281,279,285,299,314,327,342,361,381,396,406,
-417,431,444,449,448,452,469,498,530,558,583,609,631,645,654,665,689,724,765,803,835,
-866,901,942,983,1020,1053,1086,1123,1163,1202,1236,1265,1293,1323,1362,1409,1458,1499,1526,1547,1579,
-1626,1674,1705,1716,1717,1707,1652,1526,1368,1294,1421,1761,2197,2578,2845,3051,3273,3509,3689,3773,3798,
-3826,3858,3833,3703,3497,3286,3111,2967,2851,2792,2809,2871,2906,2870,2788,2710,2655,2602,2531,2456,2407,
-2392,2392,2391,2387,2385,2380,2360,2322,2273,2224,2177,2133,2092,2057,2023,1984,1939,1894,1857,1824,1787,
-1743,1694,1648,1600,1544,1473,1396,1323,1256,1184,1100,1013,941,892,860,832,807,793,793,796,793,
-786,784,782,767,733,694,670,663,657,639,615,603,603,589,528,413,274,161,107,107,124,
-123,91,31,-50,-159,-294,-438,-558,-629,-658,-678,-717,-785,-866,-942,-1003,-1044,-1065,-1063,-1048,-1033,
--1032,-1046,-1064,-1077,-1085,-1094,-1103,-1103,-1091,-1076,-1071,-1076,-1075,-1053,-1017,-986,-969,-958,-936,-895,-843,
--790,-740,-695,-653,-615,-583,-553,-521,-486,-448,-408,-371,-341,-316,-291,-259,-222,-188,-161,-140,-123,
--109,-98,-88,-71,-45,-18,-3,-5,-14,-16,-2,20,44,62,77,92,105,114,120,129,147,
-171,193,210,222,237,259,284,308,330,353,379,407,435,460,483,505,528,551,575,599,623,
-645,666,689,712,735,753,770,789,812,839,866,888,908,928,950,973,996,1018,1039,1062,1087,
-1112,1136,1157,1178,1199,1221,1243,1262,1282,1304,1333,1363,1388,1404,1413,1418,1423,1426,1424,1420,1417,
-1419,1423,1427,1429,1431,1436,1443,1449,1455,1462,1471,1481,1492,1502,1513,1523,1532,1542,1556,1572,1589,
-1604,1620,1638,1656,1670,1680,1690,1707,1729,1751,1768,1782,1798,1822,1851,1881,1909,1935,1958,1980,1999,
-2017,2037,2059,2085,2096,2122,2150,2180,2211,2243,2275,2311,2348,2385,2419,2451,2478,2489,2475,2434,2384,
-2351,2347,2364,2380,2386,2390,2407,2435,2459,2466,2458,2450,2449,2454,2460,2465,2474,2487,2501,2515,2529,
-2545,2558,2564,2564,2563,2565,2572,2584,2605,2634,2673,2721,2774,2823,2857,2873,2889,2934,3014,3103,3159,
-3166,3147,3142,3165,3201,3225,3227,3211,3182,3146,3117,3112,3138,3180,3212,3215,3192,3154,3114,3081,3057,
-3042,3034,3040,3067,3108,3145,3154,3141,3138,3176,3247,3306,3312,3268,3204,3148,3101,3057,3019,3003,3016,
-3042,3061,3065,3064,3068,3075,3075,3061,3051,3077,3159,3274,3367,3383,3315,3199,3075,2957,2841,2738,2673,
-2646,2621,2557,2462,2392,2382,2399,2363,2232,2043,1879,1795,1778,1786,1784,1769,1749,1724,1693,1658,1626,
-1599,1570,1524,1449,1346,1232,1135,1074,1046,1029,1003,967,934,913,906,904,907,918,940,971,1000,
-1022,1035,1043,1048,1049,1045,1031,1004,961,911,879,889,952,1053,1155,1227,1264,1277,1282,1283,1279,
-1268,1259,1257,1261,1268,1275,1285,1296,1298,1280,1232,1158,1072,991,927,880,844,815,794,784,783,
-786,784,777,770,770,780,798,817,831,839,843,848,852,853,851,845,840,831,816,796,776,
-761,752,744,740,744,755,762,760,758,769,800,834,848,835,815,817,852,903,945,963,958,
-939,915,889,869,867,885,912,928,918,883,833,788,761,756,763,765,748,713,672,637,607,
-573,533,496,471,456,439,413,378,341,308,278,250,226,202,177,149,117,84,50,14,-19,
--50,-79,-108,-140,-176,-213,-253,-296,-341,-389,-439,-491,-543,-593,-640,-688,-738,-788,-833,-875,-918,
--967,-1022,-1079,-1135,-1190,-1245,-1294,-1335,-1369,-1401,-1438,-1483,-1538,-1599,-1658,-1709,-1749,-1782,-1814,-1849,-1887,
--1928,-1971,-2016,-2062,-2104,-2141,-2174,-2208,-2247,-2290,-2329,-2361,-2387,-2415,-2451,-2492,-2535,-2581,-2632,-2684,-2724,
--2754,-2790,-2849,-2923,-2980,-2998,-2997,-3024,-3102,-3204,-3283,-3320,-3333,-3352,-3384,-3411,-3425,-3434,-3449,-3471,-3493,
--3513,-3536,-3563,-3586,-3600,-3612,-3632,-3658,-3677,-3689,-3703,-3730,-3766,-3795,-3807,-3801,-3777,-3726,-3651,-3581,-3561,
--3613,-3715,-3820,-3893,-3926,-3928,-3915,-3900,-3892,-3891,-3891,-3882,-3865,-3846,-3825,-3800,-3772,-3758,-3769,-3794,-3814,
--3820,-3825,-3841,-3861,-3870,-3863,-3858,-3870,-3894,-3911,-3910,-3901,-3900,-3911,-3927,-3939,-3943,-3943,-3944,-3947,-3945,
--3930,-3898,-3860,-3827,-3803,-3778,-3747,-3711,-3671,-3619,-3546,-3449,-3340,-3228,-3111,-2986,-2859,-2740,-2623,-2493,-2357,
--2251,-2210,-2220,-2232,-2209,-2160,-2121,-2110,-2111,-2103,-2082,-2057,-2036,-2014,-1995,-1985,-1981,-1972,-1948,-1917,-1897,
--1890,-1881,-1855,-1810,-1759,-1714,-1682,-1661,-1643,-1616,-1575,-1528,-1489,-1466,-1449,-1433,-1422,-1425,-1441,-1457,-1461,
--1455,-1446,-1432,-1408,-1374,-1344,-1329,-1328,-1329,-1326,-1325,-1329,-1336,-1337,-1328,-1309,-1280,-1242,-1196,-1144,-1088,
--1035,-988,-950,-912,-856,-768,-649,-510,-364,-217,-76,44,133,190,234,282,338,391,434,473,523,
-588,658,715,752,781,815,860,907,950,992,1041,1100,1164,1222,1270,1312,1353,1397,1444,1499,1562,
-1631,1700,1768,1834,1901,1968,2029,2084,2132,2179,2229,2285,2346,2411,2478,2546,2608,2660,2700,2734,2769,
-2805,2839,2870,2905,2950,3005,3062,3110,3149,3182,3208,3230,3252,3288,3340,3399,3454,3503,3558,3627,3704,
-3782,3856,3922,3971,3987,3970,3944,3935,3941,3927,3856,3718,3541,3387,3322,3382,3530,3662,3680,3570,3421,
-3339,3357,3424,3479,3509,3536,3569,3586,3580,3572,3593,3637,3676,3692,3703,3731,3779,3831,3875,3916,3952,
-3976,3987,3996,4021,4056,4083,4088,4074,4054,4037,4021,4003,3985,3975,3983,4014,4065,4117,4157,4189,4237,
-4315,4408,4487,4531,4550,4566,4592,4622,4643,4652,4656,4669,4697,4734,4765,4778,4778,4781,4791,4800,4795,
-4782,4782,4800,4823,4836,4836,4831,4826,4817,4806,4800,4802,4804,4797,4779,4761,4749,4743,4736,4729,4723,
-4716,4707,4703,4707,4715,4716,4708,4698,4698,4718,4760,4820,4872,4883,4845,4798,4784,4789,4744,4596,4376,
-4155,3937,3642,3212,2735,2406,2361,2555,2813,2999,3104,3194,3302,3395,3426,3385,3297,3194,3102,3035,2993,
-2961,2916,2851,2774,2700,2633,2566,2494,2422,2354,2290,2229,2169,2109,2049,1988,1928,1871,1817,1767,1723,
-1682,1637,1579,1511,1450,1407,1379,1351,1314,1274,1238,1205,1168,1125,1079,1035,991,947,909,878,849,
-815,777,743,714,685,651,615,581,547,509,472,443,420,391,348,302,267,244,219,182,144,
-118,103,85,59,32,17,9,0,-14,-29,-41,-55,-78,-107,-130,-143,-147,-146,-138,-124,-113,
--113,-124,-141,-159,-181,-208,-241,-274,-304,-329,-347,-363,-380,-399,-415,-421,-419,-423,-440,-464,-483,
--494,-507,-529,-553,-563,-555,-538,-523,-517,-521,-534,-551,-569,-584,-600,-628,-672,-721,-761,-785,-801,
--823,-853,-890,-930,-969,-1005,-1036,-1060,-1080,-1101,-1121,-1139,-1154,-1170,-1186,-1202,-1218,-1233,-1250,-1267,-1282,
--1294,-1305,-1314,-1322,-1328,-1334,-1342,-1350,-1355,-1355,-1355,-1356,-1358,-1359,-1358,-1353,-1345,-1334,-1321,-1311,-1306,
--1304,-1300,-1292,-1281,-1271,-1264,-1258,-1251,-1242,-1231,-1219,-1207,-1197,-1188,-1180,-1171,-1161,-1151,-1141,-1132,-1124,
--1117,-1110,-1102,-1094,-1085,-1075,-1066,-1056,-1045,-1033,-1021,-1008,-997,-991,-990,-992,-989,-982,-971,-962,-955,
--949,-945,-942,-940,-937,-933,-927,-919,-911,-902,-892,-882,-872,-861,-849,-837,-829,-822,-814,-800,-783,
--771,-767,-765,-756,-737,-716,-702,-700,-703,-703,-697,-687,-678,-668,-656,-642,-631,-624,-619,-614,-608,
--604,-600,-594,-587,-580,-575,-570,-563,-552,-543,-536,-530,-522,-513,-503,-497,-491,-485,-478,-472,-467,
--460,-447,-432,-422,-421,-424,-422,-411,-393,-376,-365,-360,-356,-349,-341,-331,-321,-312,-304,-300,-296,
--288,-275,-258,-242,-229,-217,-205,-193,-182,-173,-162,-148,-133,-117,-104,-92,-81,-68,-53,-38,-23,
--10,2,15,30,47,65,84,103,120,135,147,155,161,167,178,193,209,221,229,237,248,
-260,269,274,279,285,291,295,303,320,345,365,373,375,385,404,420,423,419,424,447,479,
-508,531,552,576,601,620,635,652,678,712,748,782,815,851,894,939,979,1011,1037,1068,1106,
-1147,1184,1216,1247,1279,1311,1347,1391,1443,1493,1531,1560,1594,1640,1684,1711,1720,1721,1700,1617,1463,
-1308,1291,1508,1918,2363,2702,2917,3100,3323,3565,3742,3804,3785,3740,3688,3609,3493,3362,3236,3106,2958,
-2816,2742,2766,2851,2916,2911,2849,2769,2692,2610,2524,2451,2409,2396,2392,2387,2381,2378,2370,2347,2306,
-2256,2205,2156,2111,2072,2039,2004,1961,1913,1868,1830,1796,1755,1709,1665,1627,1587,1531,1458,1377,1304,
-1237,1167,1089,1014,958,921,890,856,830,824,836,844,834,815,803,800,788,757,720,699,695,
-686,658,627,618,624,603,515,365,211,120,111,152,185,175,126,56,-26,-133,-269,-417,-543,
--626,-670,-703,-750,-813,-881,-942,-992,-1030,-1056,-1062,-1051,-1033,-1022,-1023,-1030,-1038,-1042,-1045,-1046,-1042,
--1032,-1024,-1022,-1023,-1013,-984,-946,-917,-907,-910,-907,-884,-841,-783,-717,-655,-606,-573,-550,-528,-501,
--471,-437,-399,-357,-314,-276,-244,-211,-175,-137,-104,-83,-75,-74,-70,-52,-15,32,71,82,66,
-41,31,43,68,90,102,109,119,130,139,144,152,171,197,223,240,253,267,288,313,337,
-359,383,410,437,462,485,508,532,554,576,598,624,651,677,700,720,741,763,784,802,820,
-842,867,892,913,932,949,969,990,1011,1032,1053,1076,1101,1127,1153,1176,1198,1221,1246,1270,1293,
-1311,1327,1346,1369,1391,1408,1418,1424,1427,1428,1426,1423,1420,1421,1425,1429,1433,1436,1440,1446,1453,
-1461,1469,1478,1487,1497,1508,1520,1530,1537,1544,1554,1568,1583,1597,1612,1630,1649,1665,1678,1693,1713,
-1735,1752,1764,1776,1797,1826,1857,1885,1912,1939,1968,1994,2014,2032,2051,2073,2096,2106,2129,2156,2186,
-2217,2248,2281,2320,2364,2408,2442,2463,2469,2459,2431,2393,2357,2336,2336,2349,2363,2374,2386,2406,2429,
-2448,2453,2450,2445,2445,2449,2454,2460,2469,2482,2498,2516,2535,2553,2566,2573,2574,2575,2577,2584,2599,
-2619,2645,2678,2721,2774,2826,2861,2875,2890,2937,3021,3114,3171,3174,3145,3124,3133,3162,3190,3202,3198,
-3180,3154,3131,3126,3144,3174,3196,3195,3173,3139,3106,3082,3067,3054,3041,3036,3055,3098,3144,3166,3161,
-3159,3192,3252,3299,3297,3248,3183,3128,3087,3053,3030,3026,3042,3064,3078,3082,3086,3097,3105,3100,3078,
-3064,3091,3183,3318,3436,3474,3408,3267,3097,2935,2797,2699,2649,2633,2613,2559,2485,2433,2423,2418,2355,
-2211,2030,1882,1807,1791,1797,1799,1793,1778,1754,1721,1688,1664,1648,1624,1571,1479,1361,1244,1156,1108,
-1087,1073,1052,1026,1004,988,977,968,967,977,1000,1028,1054,1073,1085,1094,1100,1103,1099,1084,1053,
-1012,976,966,998,1072,1165,1247,1300,1325,1337,1345,1346,1336,1319,1310,1317,1335,1352,1362,1367,1367,
-1360,1338,1296,1234,1158,1080,1010,955,916,887,866,856,856,860,861,859,860,872,895,918,931,
-935,934,934,936,937,934,927,918,908,893,875,852,831,817,812,811,813,816,824,835,844,
-852,864,889,923,951,956,940,926,935,967,1000,1013,1001,976,953,939,935,944,964,988,997,
-977,931,875,832,814,816,823,816,785,739,693,658,631,603,575,551,534,518,492,457,421,
-390,363,335,307,280,257,232,203,170,134,98,62,29,0,-31,-62,-95,-127,-160,-195,-234,
--276,-319,-364,-415,-470,-523,-571,-616,-662,-708,-752,-795,-842,-896,-954,-1011,-1065,-1116,-1165,-1209,-1247,
--1282,-1321,-1368,-1424,-1484,-1544,-1598,-1640,-1672,-1700,-1732,-1771,-1816,-1863,-1910,-1956,-2000,-2039,-2073,-2104,-2137,
--2174,-2216,-2257,-2292,-2322,-2353,-2387,-2424,-2464,-2510,-2563,-2617,-2661,-2692,-2726,-2781,-2852,-2912,-2937,-2939,-2959,
--3024,-3121,-3207,-3256,-3279,-3300,-3330,-3358,-3375,-3386,-3401,-3418,-3431,-3441,-3454,-3475,-3495,-3509,-3522,-3542,-3571,
--3598,-3621,-3646,-3681,-3721,-3752,-3765,-3759,-3735,-3687,-3619,-3558,-3542,-3590,-3682,-3779,-3849,-3886,-3894,-3887,-3876,
--3873,-3878,-3882,-3876,-3860,-3844,-3827,-3806,-3781,-3768,-3779,-3804,-3823,-3828,-3834,-3852,-3874,-3883,-3874,-3864,-3871,
--3891,-3906,-3909,-3905,-3905,-3913,-3921,-3929,-3936,-3945,-3956,-3964,-3965,-3953,-3927,-3892,-3858,-3827,-3796,-3762,-3729,
--3699,-3662,-3605,-3526,-3434,-3334,-3222,-3095,-2962,-2838,-2720,-2596,-2469,-2369,-2324,-2324,-2323,-2292,-2244,-2211,-2204,
--2205,-2193,-2167,-2142,-2118,-2087,-2050,-2023,-2012,-2007,-1992,-1968,-1948,-1943,-1943,-1933,-1905,-1862,-1813,-1766,-1726,
--1698,-1671,-1638,-1595,-1554,-1525,-1508,-1498,-1496,-1505,-1522,-1536,-1538,-1528,-1514,-1498,-1478,-1454,-1436,-1432,-1436,
--1439,-1434,-1426,-1423,-1424,-1422,-1411,-1388,-1353,-1306,-1248,-1184,-1122,-1068,-1023,-978,-920,-833,-717,-580,-440,
--305,-179,-67,23,85,128,173,233,301,361,402,434,474,533,601,665,716,759,799,838,877,
-915,959,1013,1072,1129,1178,1219,1258,1300,1347,1399,1458,1523,1592,1664,1736,1808,1879,1945,2002,2049,
-2088,2128,2176,2232,2293,2352,2409,2466,2527,2584,2630,2663,2693,2726,2764,2803,2845,2895,2955,3015,3064,
-3098,3123,3144,3165,3190,3228,3280,3339,3391,3432,3474,3529,3601,3680,3761,3836,3891,3912,3901,3879,3868,
-3865,3840,3761,3619,3440,3280,3206,3256,3402,3545,3585,3500,3367,3287,3297,3354,3404,3432,3457,3486,3505,
-3510,3522,3560,3612,3644,3648,3647,3671,3720,3773,3815,3851,3885,3911,3924,3935,3957,3990,4014,4016,3998,
-3974,3956,3945,3936,3929,3929,3942,3974,4020,4069,4110,4148,4196,4271,4366,4461,4532,4566,4570,4565,4569,
-4585,4606,4621,4633,4654,4688,4721,4735,4733,4735,4749,4762,4758,4742,4740,4761,4791,4803,4794,4778,4771,
-4770,4766,4760,4758,4761,4760,4750,4737,4727,4721,4717,4711,4703,4695,4690,4689,4694,4697,4694,4683,4673,
-4675,4698,4746,4808,4853,4852,4806,4761,4753,4759,4701,4535,4292,4038,3779,3449,3021,2595,2347,2375,2603,
-2857,3010,3066,3101,3169,3263,3339,3359,3309,3201,3078,2987,2947,2929,2895,2828,2748,2676,2612,2545,2470,
-2397,2332,2272,2213,2156,2102,2047,1990,1930,1874,1821,1770,1722,1676,1628,1570,1505,1446,1405,1381,1355,
-1317,1269,1226,1189,1153,1113,1071,1030,988,948,911,879,847,810,771,736,707,678,644,607,571,
-536,497,459,428,403,375,335,293,261,241,219,185,147,119,103,86,61,33,12,2,-5,
--17,-30,-43,-60,-84,-112,-134,-147,-152,-150,-144,-135,-128,-129,-137,-149,-164,-182,-205,-234,-266,
--298,-327,-348,-365,-382,-402,-421,-429,-428,-431,-447,-471,-489,-497,-503,-516,-538,-559,-574,-581,-583,
--584,-586,-595,-609,-622,-626,-627,-640,-671,-712,-746,-766,-778,-796,-825,-863,-907,-951,-990,-1020,-1043,
--1064,-1087,-1109,-1128,-1145,-1163,-1181,-1198,-1213,-1226,-1242,-1259,-1275,-1289,-1301,-1311,-1319,-1324,-1329,-1335,-1344,
--1350,-1352,-1353,-1356,-1359,-1359,-1356,-1350,-1343,-1334,-1323,-1314,-1309,-1307,-1304,-1297,-1287,-1279,-1273,-1269,-1264,
--1257,-1247,-1234,-1220,-1207,-1197,-1190,-1182,-1172,-1161,-1150,-1140,-1131,-1122,-1115,-1109,-1100,-1090,-1079,-1068,-1060,
--1051,-1041,-1030,-1018,-1008,-1001,-997,-996,-994,-989,-980,-972,-966,-961,-957,-953,-950,-947,-943,-938,-932,
--924,-915,-905,-897,-890,-881,-869,-857,-848,-843,-837,-824,-807,-794,-790,-790,-785,-769,-748,-734,-731,
--733,-731,-722,-710,-700,-691,-679,-667,-656,-650,-643,-634,-625,-619,-617,-615,-610,-602,-594,-588,-582,
--573,-565,-558,-554,-549,-544,-538,-532,-524,-513,-501,-493,-487,-481,-471,-457,-447,-444,-443,-437,-424,
--409,-396,-388,-382,-375,-367,-358,-349,-339,-329,-320,-313,-307,-299,-288,-274,-260,-247,-235,-225,-216,
--207,-196,-184,-171,-157,-144,-130,-115,-99,-81,-64,-48,-34,-22,-9,6,24,43,62,82,103,
-121,136,147,155,161,166,172,182,196,210,219,226,231,239,247,259,271,279,278,273,276,
-296,325,346,350,348,357,377,395,399,398,408,436,471,500,521,542,565,589,611,632,657,
-685,713,742,771,804,844,890,938,981,1015,1046,1080,1118,1155,1184,1209,1238,1273,1310,1346,1388,
-1439,1491,1531,1564,1601,1649,1692,1715,1721,1714,1676,1567,1394,1257,1304,1605,2070,2516,2817,2995,3161,
-3381,3615,3776,3821,3775,3682,3563,3432,3317,3242,3190,3112,2981,2836,2751,2761,2827,2877,2874,2827,2761,
-2685,2599,2513,2448,2414,2399,2389,2380,2375,2372,2360,2329,2282,2230,2180,2132,2086,2045,2009,1972,1930,
-1885,1844,1807,1769,1725,1678,1638,1606,1572,1521,1450,1370,1296,1227,1157,1086,1026,984,955,920,878,
-848,846,864,874,857,827,808,805,798,771,732,703,689,675,652,631,625,616,563,438,275,
-144,103,145,209,231,193,116,31,-55,-157,-284,-423,-545,-631,-686,-729,-775,-826,-874,-916,-951,
--984,-1011,-1026,-1023,-1007,-989,-980,-983,-992,-1000,-1003,-1000,-995,-988,-980,-968,-947,-915,-877,-846,-833,
--841,-861,-877,-874,-841,-780,-700,-623,-568,-539,-525,-509,-485,-458,-427,-389,-342,-289,-242,-206,-176,
--141,-97,-54,-23,-12,-13,-9,16,67,128,171,178,151,114,94,99,117,130,132,131,136,
-148,160,169,177,193,216,240,259,275,294,318,345,370,393,418,445,470,492,513,536,561,
-584,606,627,653,681,707,729,747,766,789,811,831,848,868,891,915,937,955,972,991,1011,
-1033,1053,1074,1096,1121,1146,1172,1196,1220,1244,1270,1296,1320,1338,1352,1366,1383,1404,1422,1432,1434,
-1431,1427,1425,1423,1421,1422,1427,1434,1441,1447,1453,1459,1466,1474,1482,1489,1495,1502,1511,1522,1530,
-1535,1539,1548,1562,1577,1591,1605,1622,1640,1658,1676,1696,1720,1741,1757,1769,1787,1813,1842,1867,1887,
-1910,1942,1978,2009,2031,2048,2065,2085,2106,2115,2136,2161,2191,2224,2257,2293,2335,2383,2428,2458,2465,
-2446,2408,2366,2335,2323,2327,2337,2347,2357,2372,2390,2409,2422,2429,2433,2436,2439,2442,2445,2451,2461,
-2473,2487,2503,2522,2542,2559,2570,2575,2577,2581,2587,2599,2616,2635,2656,2681,2718,2770,2822,2859,2874,
-2888,2933,3016,3109,3171,3180,3151,3120,3111,3128,3156,3183,3201,3206,3199,3188,3183,3189,3198,3201,3194,
-3177,3155,3133,3115,3098,3077,3050,3029,3035,3076,3133,3173,3184,3187,3208,3246,3271,3254,3201,3140,3096,
-3072,3060,3055,3061,3075,3088,3094,3095,3102,3116,3127,3121,3099,3086,3120,3221,3371,3511,3575,3531,3392,
-3204,3014,2858,2753,2700,2675,2647,2601,2548,2512,2489,2444,2342,2186,2021,1896,1829,1807,1805,1810,1812,
-1806,1787,1759,1735,1723,1714,1688,1624,1517,1388,1272,1193,1154,1136,1120,1101,1085,1074,1063,1047,1032,
-1027,1037,1057,1080,1101,1118,1131,1140,1146,1149,1144,1128,1098,1066,1049,1063,1116,1197,1280,1342,1373,
-1383,1390,1401,1409,1404,1390,1383,1392,1411,1426,1430,1424,1413,1398,1375,1340,1291,1227,1154,1085,1030,
-993,968,948,936,933,937,941,945,955,977,1006,1027,1035,1033,1031,1030,1029,1023,1015,1005,992,
-977,958,939,919,901,888,885,891,897,898,901,913,933,953,966,981,1009,1043,1059,1045,1012,
-994,1006,1035,1051,1042,1020,1006,1007,1017,1026,1031,1029,1015,984,939,894,863,849,846,840,821,
-787,749,717,694,674,653,631,611,593,571,539,503,473,449,425,395,361,329,304,280,251,
-216,179,145,113,84,53,20,-13,-45,-74,-103,-136,-173,-212,-250,-291,-340,-395,-450,-498,-540,
--583,-627,-673,-720,-772,-829,-889,-944,-994,-1040,-1083,-1123,-1160,-1201,-1249,-1306,-1367,-1427,-1482,-1528,-1564,
--1592,-1620,-1656,-1701,-1752,-1802,-1849,-1894,-1935,-1972,-2004,-2034,-2065,-2100,-2138,-2177,-2217,-2255,-2290,-2322,-2351,
--2380,-2417,-2464,-2518,-2568,-2607,-2647,-2703,-2779,-2849,-2887,-2895,-2905,-2952,-3034,-3121,-3180,-3214,-3240,-3275,-3311,
--3339,-3356,-3365,-3369,-3369,-3370,-3381,-3401,-3422,-3437,-3448,-3468,-3500,-3536,-3568,-3599,-3634,-3672,-3703,-3720,-3721,
--3701,-3657,-3597,-3547,-3540,-3585,-3663,-3742,-3800,-3836,-3852,-3856,-3855,-3858,-3866,-3872,-3866,-3853,-3841,-3833,-3820,
--3802,-3792,-3799,-3817,-3828,-3829,-3834,-3854,-3879,-3892,-3887,-3878,-3881,-3891,-3898,-3898,-3899,-3905,-3914,-3921,-3926,
--3936,-3948,-3960,-3967,-3969,-3964,-3950,-3925,-3895,-3861,-3824,-3786,-3751,-3723,-3694,-3653,-3595,-3526,-3446,-3347,-3224,
--3086,-2952,-2828,-2707,-2595,-2512,-2474,-2463,-2439,-2382,-2318,-2282,-2278,-2277,-2256,-2222,-2194,-2172,-2142,-2098,-2058,
--2039,-2036,-2030,-2013,-1995,-1989,-1992,-1992,-1979,-1950,-1908,-1856,-1803,-1759,-1727,-1698,-1666,-1632,-1604,-1589,-1584,
--1586,-1591,-1597,-1598,-1591,-1577,-1564,-1557,-1552,-1548,-1547,-1551,-1557,-1558,-1550,-1537,-1527,-1520,-1509,-1491,-1460,
--1416,-1359,-1292,-1222,-1158,-1106,-1059,-1002,-921,-808,-673,-535,-407,-293,-193,-105,-34,21,72,131,202,
-274,333,373,403,438,484,540,601,663,721,772,811,846,884,933,990,1047,1096,1138,1177,1219,
-1265,1317,1375,1437,1502,1570,1641,1716,1789,1857,1913,1959,1998,2037,2083,2138,2201,2263,2314,2356,2400,
-2455,2514,2564,2600,2630,2666,2708,2749,2789,2836,2898,2965,3021,3055,3074,3087,3103,3127,3164,3217,3278,
-3334,3376,3414,3460,3521,3594,3672,3748,3805,3830,3822,3800,3784,3775,3743,3659,3516,3342,3195,3130,3176,
-3298,3417,3454,3394,3297,3238,3241,3278,3315,3346,3381,3419,3447,3465,3496,3550,3604,3626,3612,3599,3618,
-3667,3718,3755,3786,3822,3858,3883,3896,3909,3927,3943,3944,3929,3908,3889,3875,3867,3867,3876,3896,3929,
-3972,4021,4067,4106,4148,4211,4308,4429,4539,4599,4595,4551,4515,4516,4546,4579,4600,4619,4649,4681,4697,
-4696,4698,4712,4725,4717,4697,4694,4722,4760,4776,4760,4735,4721,4718,4715,4706,4702,4705,4712,4713,4707,
-4702,4699,4696,4689,4680,4672,4668,4668,4671,4672,4668,4661,4656,4663,4691,4744,4803,4836,4820,4770,4733,
-4732,4727,4643,4449,4186,3911,3620,3264,2845,2478,2315,2409,2660,2901,3034,3071,3081,3117,3186,3263,3307,
-3279,3177,3044,2943,2902,2889,2859,2796,2721,2655,2592,2520,2439,2366,2307,2255,2202,2147,2095,2042,1985,
-1924,1867,1815,1765,1715,1667,1620,1566,1504,1445,1403,1379,1355,1316,1264,1214,1175,1140,1103,1063,1023,
-984,946,909,874,841,804,764,726,695,665,631,594,558,522,485,448,416,388,358,322,285,
-258,240,219,187,150,121,105,91,69,40,16,0,-11,-24,-38,-53,-71,-93,-116,-136,-150,
--156,-156,-151,-145,-141,-143,-149,-156,-165,-179,-199,-222,-251,-285,-321,-351,-373,-390,-409,-428,-440,
--445,-450,-463,-482,-496,-501,-501,-507,-523,-545,-569,-589,-604,-612,-618,-630,-649,-666,-671,-668,-671,
--689,-716,-740,-753,-761,-774,-797,-834,-881,-930,-974,-1005,-1027,-1047,-1069,-1091,-1110,-1129,-1151,-1175,-1196,
--1210,-1223,-1239,-1257,-1274,-1287,-1300,-1312,-1321,-1326,-1329,-1335,-1342,-1348,-1351,-1352,-1354,-1355,-1355,-1352,-1349,
--1346,-1339,-1330,-1320,-1313,-1309,-1306,-1300,-1293,-1286,-1280,-1273,-1267,-1262,-1255,-1243,-1227,-1212,-1202,-1196,-1189,
--1179,-1166,-1154,-1143,-1132,-1122,-1114,-1108,-1100,-1090,-1078,-1068,-1061,-1054,-1047,-1038,-1029,-1020,-1011,-1004,-1000,
--997,-994,-988,-982,-977,-973,-970,-965,-959,-954,-950,-946,-941,-934,-925,-915,-907,-901,-893,-884,-873,
--865,-861,-857,-848,-834,-820,-814,-813,-808,-794,-775,-762,-759,-760,-756,-745,-733,-722,-713,-701,-688,
--678,-674,-669,-661,-650,-642,-639,-638,-632,-622,-613,-606,-601,-594,-586,-580,-575,-571,-567,-562,-557,
--550,-539,-527,-516,-510,-505,-497,-487,-478,-473,-467,-458,-444,-430,-419,-412,-404,-395,-386,-378,-370,
--360,-349,-338,-330,-322,-315,-307,-297,-286,-272,-259,-248,-239,-228,-215,-200,-188,-177,-166,-152,-136,
--117,-97,-76,-58,-45,-33,-20,-3,15,34,53,74,95,113,126,135,142,149,153,156,163,
-175,189,199,204,207,211,220,235,251,261,260,254,260,282,312,331,334,333,343,365,383,
-391,398,417,449,483,510,532,553,574,592,608,629,656,687,715,741,770,803,841,883,929,
-977,1023,1065,1104,1140,1168,1188,1206,1233,1271,1312,1352,1395,1444,1492,1529,1558,1595,1643,1685,1706,
-1706,1689,1633,1506,1335,1236,1352,1721,2222,2664,2948,3120,3288,3493,3683,3790,3795,3726,3608,3454,3296,
-3188,3158,3164,3127,3007,2850,2734,2698,2717,2740,2743,2729,2697,2641,2563,2488,2439,2420,2410,2395,2378,
-2366,2357,2338,2300,2250,2199,2151,2103,2054,2007,1967,1930,1895,1859,1823,1787,1748,1703,1657,1619,1587,
-1553,1508,1446,1374,1302,1232,1163,1099,1048,1014,985,946,900,868,867,887,897,877,841,817,811,
-803,773,725,681,655,644,640,640,634,595,494,341,191,114,134,209,265,251,171,64,-36,
--126,-222,-331,-447,-552,-633,-694,-742,-783,-820,-850,-874,-897,-921,-946,-964,-968,-957,-939,-928,-933,
--949,-964,-970,-969,-965,-961,-951,-926,-883,-835,-795,-776,-779,-797,-820,-840,-846,-824,-770,-692,-613,
--555,-523,-505,-485,-458,-430,-401,-365,-318,-264,-214,-176,-144,-107,-60,-10,26,41,44,51,80,
-134,195,238,245,220,185,163,161,170,174,169,161,163,174,188,200,208,220,237,256,274,
-293,316,343,372,399,423,447,472,496,519,541,565,591,616,638,660,684,710,734,754,772,
-792,815,838,856,872,890,913,938,961,981,999,1020,1043,1066,1088,1109,1131,1153,1175,1197,1219,
-1241,1263,1286,1309,1332,1350,1364,1377,1394,1415,1435,1446,1445,1438,1432,1430,1431,1432,1434,1439,1448,
-1457,1464,1469,1472,1477,1483,1489,1493,1497,1502,1510,1519,1526,1530,1536,1547,1563,1579,1593,1605,1619,
-1635,1654,1676,1699,1724,1746,1764,1782,1804,1831,1854,1871,1886,1909,1944,1983,2016,2038,2056,2075,2095,
-2115,2124,2144,2167,2195,2228,2267,2312,2361,2409,2448,2467,2458,2418,2361,2310,2290,2303,2332,2353,2361,
-2365,2378,2397,2411,2414,2411,2414,2424,2435,2442,2446,2453,2466,2481,2496,2512,2531,2552,2567,2574,2576,
-2578,2584,2595,2610,2629,2648,2664,2683,2714,2761,2813,2849,2865,2878,2917,2994,3088,3159,3182,3162,3126,
-3103,3103,3124,3157,3191,3216,3231,3238,3244,3249,3248,3242,3232,3222,3211,3199,3183,3160,3127,3084,3046,
-3038,3071,3129,3182,3208,3217,3227,3241,3242,3211,3157,3106,3081,3079,3088,3096,3105,3114,3121,3123,3122,
-3126,3138,3146,3141,3124,3122,3168,3279,3434,3580,3661,3647,3539,3367,3176,3008,2888,2816,2770,2723,2673,
-2629,2594,2548,2461,2327,2170,2029,1929,1869,1838,1828,1832,1839,1837,1825,1811,1804,1803,1795,1759,1680,
-1562,1430,1316,1243,1209,1191,1172,1152,1140,1134,1125,1108,1093,1089,1099,1116,1131,1146,1162,1176,1184,
-1188,1191,1190,1178,1156,1134,1134,1169,1237,1321,1396,1443,1458,1456,1458,1471,1485,1488,1480,1473,1476,
-1485,1488,1481,1468,1454,1439,1416,1382,1337,1281,1219,1159,1113,1081,1057,1035,1018,1011,1014,1023,1034,
-1050,1075,1103,1122,1130,1133,1135,1135,1127,1113,1099,1088,1074,1055,1034,1017,1001,984,969,963,971,
-982,986,986,998,1026,1057,1073,1081,1097,1127,1145,1127,1080,1045,1048,1082,1108,1105,1084,1071,1076,
-1086,1085,1067,1038,1005,971,940,914,894,879,862,841,816,791,771,756,744,728,707,683,662,
-641,616,585,554,528,507,482,448,410,377,351,327,297,260,224,193,165,137,105,71,37,
-7,-20,-47,-79,-115,-150,-184,-221,-267,-320,-373,-419,-461,-503,-549,-598,-648,-703,-761,-820,-874,
--921,-963,-1002,-1040,-1081,-1129,-1186,-1249,-1309,-1363,-1409,-1448,-1481,-1511,-1544,-1588,-1639,-1692,-1741,-1786,-1827,
--1866,-1900,-1931,-1961,-1993,-2027,-2064,-2104,-2148,-2192,-2230,-2259,-2279,-2296,-2318,-2353,-2401,-2453,-2502,-2553,-2617,
--2698,-2779,-2832,-2848,-2852,-2880,-2945,-3025,-3090,-3131,-3164,-3206,-3254,-3294,-3314,-3314,-3303,-3293,-3295,-3315,-3345,
--3373,-3389,-3399,-3417,-3449,-3487,-3522,-3551,-3583,-3620,-3656,-3684,-3696,-3683,-3643,-3589,-3549,-3551,-3597,-3663,-3724,
--3769,-3801,-3826,-3842,-3852,-3857,-3862,-3863,-3856,-3847,-3843,-3843,-3838,-3827,-3820,-3824,-3835,-3839,-3835,-3837,-3855,
--3879,-3893,-3894,-3893,-3896,-3900,-3897,-3893,-3896,-3908,-3920,-3925,-3930,-3940,-3953,-3961,-3963,-3964,-3966,-3963,-3949,
--3925,-3895,-3859,-3820,-3781,-3748,-3719,-3686,-3645,-3598,-3543,-3467,-3361,-3226,-3081,-2939,-2809,-2707,-2648,-2634,-2628,
--2584,-2493,-2397,-2343,-2335,-2332,-2304,-2259,-2223,-2204,-2181,-2142,-2101,-2077,-2073,-2072,-2061,-2048,-2043,-2045,-2045,
--2037,-2022,-1999,-1960,-1906,-1849,-1804,-1774,-1752,-1728,-1705,-1690,-1684,-1682,-1677,-1664,-1644,-1620,-1601,-1594,-1600,
--1613,-1626,-1634,-1640,-1643,-1643,-1640,-1633,-1624,-1611,-1592,-1563,-1523,-1472,-1409,-1340,-1271,-1210,-1157,-1101,-1024,
--919,-790,-652,-523,-411,-315,-232,-161,-99,-40,23,96,172,240,295,341,382,421,457,494,538,
-595,657,713,757,796,844,905,971,1029,1075,1114,1153,1196,1243,1298,1359,1426,1493,1560,1628,1703,
-1777,1840,1885,1917,1948,1991,2047,2113,2181,2239,2282,2313,2347,2395,2451,2503,2544,2581,2622,2667,2706,
-2738,2779,2839,2912,2973,3008,3022,3030,3042,3063,3097,3149,3215,3282,3337,3381,3426,3479,3542,3612,3680,
-3733,3755,3745,3721,3705,3698,3669,3582,3433,3260,3124,3074,3115,3208,3291,3316,3284,3232,3201,3198,3212,
-3236,3275,3329,3383,3418,3443,3484,3543,3591,3596,3568,3548,3569,3621,3670,3701,3726,3762,3808,3844,3862,
-3868,3873,3877,3877,3868,3851,3829,3808,3795,3795,3809,3834,3869,3915,3971,4026,4068,4100,4147,4237,4375,
-4520,4610,4608,4541,4473,4455,4487,4531,4559,4579,4606,4637,4657,4662,4668,4683,4694,4682,4658,4652,4681,
-4723,4741,4724,4694,4674,4666,4660,4651,4647,4654,4666,4672,4670,4667,4665,4663,4657,4650,4645,4644,4645,
-4644,4643,4641,4641,4644,4660,4697,4751,4800,4813,4781,4733,4709,4711,4680,4552,4323,4046,3764,3458,3086,
-2685,2384,2309,2463,2721,2937,3049,3084,3096,3113,3147,3194,3227,3209,3122,3000,2905,2864,2849,2816,2755,
-2688,2630,2569,2491,2405,2333,2282,2239,2189,2136,2085,2034,1977,1916,1860,1809,1759,1708,1661,1617,1568,
-1509,1449,1406,1382,1359,1321,1267,1214,1172,1136,1098,1057,1019,982,943,902,864,830,796,758,718,
-682,650,617,580,543,509,477,446,413,379,345,311,281,258,240,218,187,153,127,111,98,
-78,51,25,6,-9,-25,-43,-63,-83,-101,-119,-135,-150,-160,-164,-161,-156,-155,-157,-159,-159,
--161,-170,-187,-207,-233,-267,-308,-349,-380,-403,-421,-440,-454,-464,-471,-483,-497,-509,-516,-519,-525,
--537,-552,-571,-589,-605,-616,-624,-638,-659,-682,-697,-703,-707,-717,-732,-746,-754,-759,-768,-786,-819,
--865,-914,-956,-986,-1007,-1028,-1051,-1071,-1087,-1105,-1130,-1159,-1185,-1203,-1217,-1235,-1254,-1270,-1283,-1295,-1307,
--1319,-1326,-1329,-1333,-1339,-1344,-1347,-1348,-1349,-1350,-1350,-1350,-1351,-1350,-1346,-1338,-1327,-1320,-1315,-1310,-1305,
--1299,-1291,-1281,-1270,-1260,-1254,-1248,-1239,-1225,-1210,-1201,-1197,-1191,-1183,-1172,-1160,-1148,-1135,-1122,-1112,-1106,
--1098,-1088,-1077,-1069,-1065,-1060,-1055,-1048,-1041,-1033,-1024,-1015,-1008,-1005,-1003,-999,-995,-991,-989,-985,-979,
--971,-964,-958,-953,-947,-940,-932,-924,-917,-910,-905,-897,-889,-880,-875,-871,-865,-855,-844,-837,-834,
--828,-816,-799,-787,-783,-781,-775,-764,-752,-744,-735,-724,-710,-699,-694,-692,-687,-678,-669,-664,-660,
--653,-643,-634,-627,-621,-614,-606,-599,-594,-589,-582,-576,-572,-568,-562,-552,-542,-534,-528,-521,-513,
--505,-498,-490,-477,-463,-449,-439,-431,-421,-411,-402,-396,-388,-378,-366,-355,-347,-339,-331,-324,-318,
--308,-295,-280,-268,-258,-247,-233,-218,-204,-194,-183,-170,-154,-136,-115,-94,-73,-56,-43,-29,-11,
-6,24,41,61,83,100,111,118,123,130,136,141,146,156,166,173,176,176,181,193,209,
-223,231,234,237,251,275,298,310,312,316,332,355,374,388,405,433,467,496,519,541,564,
-584,597,607,625,653,686,718,750,784,818,850,884,925,976,1029,1076,1115,1145,1167,1183,1202,
-1231,1272,1316,1360,1405,1454,1499,1531,1557,1591,1635,1673,1688,1680,1651,1579,1444,1287,1233,1410,1825,
-2341,2782,3076,3276,3461,3639,3757,3781,3732,3642,3515,3351,3189,3101,3114,3162,3140,3005,2809,2644,2560,
-2544,2563,2594,2621,2623,2582,2512,2454,2434,2442,2445,2426,2391,2359,2331,2301,2261,2216,2169,2121,2069,
-2014,1964,1925,1893,1865,1836,1804,1770,1732,1691,1648,1607,1569,1530,1487,1436,1377,1313,1248,1183,1125,
-1078,1042,1008,968,924,894,892,907,912,893,860,833,817,797,756,697,641,608,604,621,639,
-630,562,430,273,159,139,199,275,297,239,126,0,-112,-209,-300,-390,-478,-559,-631,-693,-743,
--778,-801,-818,-834,-850,-868,-888,-905,-913,-908,-896,-890,-900,-921,-941,-948,-946,-946,-947,-940,-912,
--863,-812,-776,-763,-766,-773,-781,-790,-794,-783,-747,-687,-617,-556,-511,-475,-444,-413,-383,-354,-319,
--275,-225,-180,-143,-110,-73,-28,14,44,58,63,74,105,153,206,246,259,249,229,217,217,
-222,223,217,209,207,214,225,234,241,250,264,282,300,318,340,366,394,422,447,470,494,
-518,542,568,595,622,647,670,693,717,741,763,783,803,824,847,867,884,899,918,942,968,
-991,1012,1031,1053,1078,1103,1126,1148,1169,1189,1207,1224,1242,1260,1279,1299,1318,1337,1354,1368,1381,
-1399,1421,1442,1454,1453,1447,1445,1448,1453,1456,1457,1461,1469,1476,1480,1479,1478,1480,1484,1487,1490,
-1493,1499,1506,1514,1521,1529,1539,1553,1569,1584,1597,1608,1621,1637,1656,1678,1703,1729,1753,1774,1796,
-1818,1839,1856,1870,1887,1913,1945,1979,2007,2032,2055,2080,2104,2124,2132,2155,2179,2203,2232,2271,2322,
-2378,2426,2456,2464,2446,2400,2338,2286,2272,2299,2341,2369,2375,2374,2383,2401,2412,2410,2405,2410,2426,
-2442,2450,2454,2463,2477,2493,2508,2524,2544,2564,2577,2580,2579,2581,2588,2600,2615,2632,2649,2664,2680,
-2706,2748,2797,2835,2854,2866,2900,2970,3062,3143,3182,3175,3140,3105,3087,3093,3118,3152,3187,3219,3249,
-3276,3299,3312,3315,3311,3304,3297,3285,3266,3237,3196,3146,3102,3082,3099,3144,3194,3227,3241,3246,3247,
-3235,3200,3152,3114,3105,3117,3133,3142,3145,3154,3167,3178,3181,3179,3178,3175,3167,3160,3178,3245,3364,
-3509,3636,3711,3714,3643,3507,3331,3158,3022,2931,2864,2803,2744,2696,2651,2582,2467,2319,2173,2058,1979,
-1923,1888,1873,1877,1884,1881,1873,1872,1882,1888,1873,1823,1733,1612,1482,1371,1300,1266,1247,1227,1205,
-1191,1183,1173,1159,1150,1153,1165,1176,1184,1194,1210,1224,1231,1235,1242,1252,1253,1240,1226,1235,1280,
-1357,1443,1514,1554,1564,1558,1557,1568,1584,1589,1580,1567,1561,1557,1549,1535,1522,1511,1496,1469,1427,
-1379,1330,1282,1239,1205,1177,1150,1122,1098,1088,1093,1106,1120,1139,1163,1190,1212,1225,1234,1241,1239,
-1225,1205,1190,1181,1169,1149,1126,1109,1097,1079,1057,1046,1054,1070,1078,1078,1088,1122,1163,1187,1194,
-1202,1223,1234,1210,1157,1116,1122,1161,1191,1186,1158,1135,1130,1128,1112,1078,1036,999,972,954,943,
-932,915,888,860,837,824,816,808,795,776,752,728,705,684,660,631,603,578,555,527,493,
-458,428,403,377,345,309,275,245,217,187,155,121,90,60,31,1,-29,-61,-91,-122,-158,
--200,-247,-295,-339,-383,-428,-477,-527,-579,-633,-689,-745,-797,-844,-886,-926,-967,-1012,-1067,-1129,-1191,
--1245,-1289,-1326,-1361,-1396,-1432,-1474,-1525,-1580,-1633,-1679,-1719,-1758,-1794,-1826,-1856,-1887,-1922,-1960,-2001,-2044,
--2090,-2135,-2173,-2199,-2213,-2220,-2227,-2245,-2281,-2332,-2390,-2450,-2519,-2601,-2686,-2749,-2778,-2785,-2804,-2853,-2923,
--2987,-3034,-3074,-3121,-3176,-3221,-3240,-3233,-3215,-3205,-3217,-3252,-3295,-3329,-3347,-3358,-3377,-3409,-3444,-3474,-3500,
--3529,-3567,-3610,-3648,-3671,-3669,-3638,-3594,-3565,-3575,-3622,-3682,-3730,-3763,-3790,-3818,-3844,-3859,-3865,-3863,-3857,
--3849,-3844,-3846,-3850,-3850,-3846,-3844,-3851,-3858,-3857,-3851,-3851,-3863,-3878,-3886,-3889,-3896,-3906,-3909,-3902,-3895,
--3900,-3915,-3927,-3930,-3933,-3943,-3957,-3965,-3965,-3965,-3970,-3971,-3961,-3941,-3918,-3891,-3856,-3814,-3773,-3736,-3703,
--3668,-3636,-3603,-3557,-3478,-3360,-3210,-3046,-2896,-2787,-2744,-2758,-2777,-2739,-2631,-2504,-2422,-2397,-2390,-2358,-2304,
--2259,-2240,-2227,-2202,-2166,-2140,-2128,-2122,-2113,-2106,-2106,-2108,-2104,-2094,-2087,-2084,-2067,-2023,-1961,-1904,-1868,
--1848,-1830,-1810,-1794,-1787,-1783,-1767,-1732,-1684,-1640,-1615,-1615,-1634,-1659,-1677,-1684,-1681,-1676,-1675,-1679,-1686,
--1688,-1680,-1658,-1623,-1577,-1522,-1460,-1394,-1330,-1271,-1212,-1138,-1040,-917,-783,-654,-542,-444,-358,-281,-217,
--160,-100,-28,51,126,187,238,291,349,402,440,464,491,533,587,640,688,737,798,871,946,
-1009,1059,1102,1143,1184,1225,1275,1339,1412,1485,1552,1618,1692,1769,1831,1869,1890,1915,1959,2021,2089,
-2152,2201,2238,2267,2299,2343,2394,2444,2490,2535,2585,2633,2669,2697,2733,2791,2861,2919,2951,2963,2972,
-2988,3009,3041,3091,3162,3239,3306,3358,3405,3458,3520,3585,3644,3683,3693,3675,3649,3638,3639,3615,3525,
-3366,3188,3059,3020,3059,3128,3180,3196,3188,3175,3166,3160,3161,3184,3237,3308,3367,3399,3421,3461,3515,
-3551,3542,3505,3487,3515,3574,3625,3652,3671,3703,3747,3787,3810,3818,3819,3817,3812,3802,3784,3760,3735,
-3719,3720,3736,3763,3799,3850,3916,3982,4030,4056,4087,4163,4299,4456,4563,4575,4510,4437,4412,4439,4481,
-4510,4527,4550,4580,4605,4619,4634,4653,4666,4656,4634,4626,4648,4681,4696,4681,4653,4632,4621,4613,4607,
-4607,4616,4626,4629,4625,4621,4621,4622,4619,4616,4617,4621,4624,4622,4617,4615,4618,4631,4659,4706,4761,
-4794,4784,4738,4696,4685,4678,4604,4420,4154,3870,3592,3281,2905,2534,2308,2323,2532,2787,2966,3049,3082,
-3100,3109,3113,3126,3142,3127,3055,2951,2868,2830,2812,2773,2711,2648,2596,2538,2461,2377,2310,2264,2222,
-2173,2120,2072,2026,1973,1915,1860,1809,1757,1702,1653,1611,1567,1513,1455,1412,1390,1370,1333,1278,1224,
-1180,1142,1101,1058,1019,981,940,893,851,817,788,753,713,674,639,606,568,531,499,474,449,
-416,378,339,306,280,259,239,215,186,158,136,120,105,84,58,34,14,-2,-20,-43,-67,
--90,-106,-117,-129,-144,-158,-166,-167,-166,-167,-170,-167,-159,-152,-156,-170,-190,-212,-243,-285,-332,
--374,-405,-428,-448,-465,-478,-487,-498,-512,-525,-537,-548,-559,-570,-580,-591,-604,-617,-626,-633,-641,
--657,-680,-703,-721,-734,-744,-753,-759,-765,-773,-784,-803,-833,-871,-910,-941,-963,-982,-1005,-1031,-1052,
--1066,-1082,-1107,-1138,-1165,-1185,-1201,-1219,-1239,-1254,-1264,-1275,-1289,-1303,-1312,-1316,-1321,-1327,-1334,-1339,-1341,
--1343,-1345,-1346,-1347,-1349,-1349,-1346,-1338,-1330,-1324,-1320,-1314,-1307,-1299,-1290,-1277,-1261,-1248,-1240,-1235,-1228,
--1215,-1202,-1195,-1193,-1191,-1185,-1177,-1168,-1157,-1144,-1130,-1118,-1111,-1103,-1093,-1083,-1077,-1074,-1071,-1066,-1060,
--1054,-1047,-1039,-1031,-1024,-1020,-1017,-1014,-1011,-1009,-1006,-1002,-994,-985,-976,-968,-959,-950,-943,-938,-934,
--929,-924,-919,-914,-907,-898,-889,-883,-876,-869,-861,-855,-851,-846,-836,-822,-810,-802,-797,-789,-779,
--769,-762,-756,-746,-733,-721,-714,-711,-707,-700,-692,-685,-679,-673,-666,-659,-652,-643,-634,-625,-618,
--613,-606,-597,-589,-585,-583,-581,-574,-564,-554,-546,-537,-527,-520,-513,-504,-491,-475,-462,-453,-444,
--434,-424,-415,-408,-399,-388,-377,-368,-361,-354,-345,-336,-329,-320,-308,-295,-284,-276,-267,-254,-240,
--227,-216,-204,-190,-173,-155,-136,-115,-93,-73,-56,-38,-18,1,19,34,51,70,86,96,102,
-107,115,123,130,137,144,150,151,149,148,156,169,182,191,197,204,219,242,265,279,281,
-282,292,314,338,357,374,399,434,469,495,514,534,559,582,596,609,629,660,695,730,768,
-808,843,871,897,932,981,1031,1071,1100,1122,1143,1167,1195,1231,1275,1320,1365,1412,1460,1503,1535,
-1562,1594,1632,1660,1666,1649,1609,1522,1379,1237,1221,1439,1878,2395,2839,3160,3401,3604,3749,3795,3749,
-3662,3565,3438,3267,3105,3039,3087,3159,3132,2962,2720,2517,2412,2398,2437,2498,2549,2560,2521,2462,2430,
-2445,2482,2496,2468,2412,2353,2305,2265,2228,2192,2150,2099,2038,1979,1930,1894,1868,1842,1814,1784,1753,
-1720,1684,1644,1599,1551,1506,1463,1420,1372,1319,1263,1208,1156,1109,1069,1030,990,951,924,914,916,
-913,896,868,839,810,771,715,647,587,552,550,573,595,581,505,378,251,185,203,269,316,
-297,210,86,-43,-165,-274,-366,-441,-503,-564,-630,-692,-739,-764,-775,-784,-798,-815,-834,-852,-868,
--878,-879,-874,-875,-891,-916,-936,-942,-937,-936,-940,-937,-916,-876,-832,-799,-780,-767,-753,-740,-732,
--731,-726,-706,-665,-607,-540,-476,-422,-382,-354,-330,-299,-257,-209,-166,-134,-108,-81,-49,-13,17,
-36,46,54,72,104,147,190,223,241,247,248,252,260,268,271,269,264,263,266,270,274,
-279,287,302,321,339,354,369,389,415,443,471,495,519,543,572,601,631,657,682,705,728,
-752,775,797,818,840,861,882,900,916,933,954,979,1004,1027,1046,1065,1085,1108,1131,1153,1174,
-1195,1214,1231,1245,1260,1276,1295,1315,1334,1354,1371,1385,1398,1414,1434,1453,1463,1463,1461,1464,1472,
-1477,1477,1475,1476,1482,1486,1484,1479,1477,1480,1484,1487,1488,1492,1498,1505,1512,1521,1532,1546,1560,
-1572,1583,1595,1608,1623,1640,1660,1682,1707,1733,1760,1784,1806,1824,1839,1854,1873,1896,1921,1945,1968,
-1992,2020,2052,2082,2108,2132,2133,2170,2204,2226,2242,2268,2311,2361,2404,2431,2443,2437,2405,2350,2295,
-2273,2293,2335,2365,2372,2370,2377,2392,2402,2402,2400,2410,2430,2448,2457,2463,2473,2489,2505,2519,2536,
-2556,2575,2586,2587,2586,2588,2595,2603,2612,2625,2640,2654,2670,2694,2731,2778,2820,2846,2863,2895,2958,
-3047,3133,3185,3189,3158,3115,3083,3072,3082,3109,3145,3186,3230,3278,3325,3366,3392,3401,3396,3381,3360,
-3335,3303,3266,3224,3185,3160,3159,3180,3212,3239,3257,3266,3267,3255,3226,3188,3161,3158,3170,3178,3174,
-3170,3185,3222,3260,3276,3266,3245,3223,3210,3213,3252,3339,3461,3581,3666,3706,3704,3656,3551,3395,3223,
-3079,2982,2915,2855,2795,2740,2681,2593,2466,2319,2189,2096,2033,1985,1953,1944,1949,1950,1939,1929,1935,
-1951,1956,1930,1869,1779,1665,1541,1431,1357,1320,1302,1284,1261,1243,1230,1219,1210,1209,1219,1231,1237,
-1240,1249,1266,1281,1287,1292,1309,1334,1348,1342,1331,1343,1394,1474,1561,1629,1669,1681,1678,1677,1685,
-1696,1694,1677,1656,1640,1628,1614,1597,1583,1571,1551,1515,1465,1416,1377,1347,1322,1297,1271,1242,1209,
-1182,1170,1175,1187,1201,1219,1245,1275,1301,1318,1328,1334,1330,1315,1296,1285,1281,1271,1249,1224,1208,
-1199,1183,1159,1144,1151,1170,1180,1178,1187,1223,1272,1306,1318,1323,1335,1337,1306,1252,1214,1221,1258,
-1280,1264,1224,1189,1169,1152,1122,1081,1042,1012,992,980,974,967,952,928,904,889,882,875,861,
-842,820,798,777,754,730,705,678,651,624,598,570,538,508,481,456,427,395,361,331,302,
-272,238,204,174,145,113,79,45,16,-9,-34,-64,-99,-139,-179,-220,-263,-310,-360,-409,-457,
--507,-560,-614,-666,-716,-764,-811,-856,-902,-952,-1010,-1071,-1127,-1172,-1206,-1238,-1273,-1312,-1356,-1406,-1462,
--1520,-1571,-1615,-1653,-1688,-1722,-1752,-1782,-1815,-1855,-1900,-1945,-1990,-2034,-2075,-2110,-2135,-2149,-2152,-2151,-2155,
--2178,-2223,-2283,-2346,-2412,-2486,-2566,-2636,-2679,-2700,-2721,-2763,-2826,-2890,-2945,-2993,-3045,-3100,-3142,-3159,-3153,
--3140,-3139,-3162,-3203,-3246,-3276,-3293,-3308,-3332,-3365,-3398,-3424,-3447,-3477,-3517,-3560,-3600,-3626,-3634,-3620,-3595,
--3580,-3597,-3642,-3696,-3737,-3763,-3786,-3812,-3839,-3857,-3862,-3858,-3851,-3845,-3842,-3844,-3847,-3850,-3854,-3864,-3877,
--3883,-3877,-3869,-3870,-3879,-3884,-3880,-3880,-3892,-3911,-3918,-3908,-3899,-3905,-3923,-3935,-3936,-3937,-3949,-3966,-3975,
--3975,-3975,-3979,-3978,-3966,-3946,-3928,-3909,-3880,-3839,-3793,-3751,-3714,-3678,-3647,-3625,-3602,-3555,-3465,-3327,-3156,
--2984,-2853,-2799,-2823,-2870,-2865,-2774,-2636,-2524,-2470,-2448,-2413,-2358,-2311,-2290,-2286,-2273,-2245,-2213,-2189,-2170,
--2157,-2155,-2163,-2171,-2167,-2154,-2149,-2155,-2154,-2125,-2067,-2006,-1964,-1940,-1920,-1900,-1889,-1891,-1891,-1867,-1808,
--1731,-1669,-1641,-1650,-1678,-1705,-1719,-1714,-1698,-1682,-1677,-1687,-1707,-1725,-1728,-1711,-1675,-1626,-1569,-1509,-1449,
--1391,-1332,-1265,-1177,-1063,-931,-800,-684,-587,-498,-413,-336,-273,-220,-162,-89,-9,60,110,153,206,
-276,346,398,427,450,484,532,585,638,693,757,830,903,969,1031,1090,1142,1182,1214,1253,1312,
-1389,1468,1538,1604,1676,1752,1814,1850,1867,1889,1933,1996,2059,2111,2151,2185,2220,2257,2298,2340,2383,
-2429,2480,2537,2589,2627,2657,2695,2751,2814,2862,2887,2899,2913,2934,2960,2995,3048,3124,3208,3278,3331,
-3378,3435,3504,3571,3623,3648,3642,3614,3586,3577,3575,3542,3440,3276,3106,2997,2975,3013,3062,3089,3096,
-3099,3104,3106,3103,3112,3153,3226,3303,3350,3363,3373,3408,3457,3485,3470,3434,3424,3460,3522,3575,3605,
-3624,3651,3685,3718,3741,3754,3759,3757,3746,3728,3707,3683,3664,3655,3660,3679,3704,3738,3789,3857,3929,
-3980,4007,4033,4098,4218,4360,4462,4484,4442,4390,4377,4402,4438,4460,4475,4494,4522,4548,4569,4591,4616,
-4633,4633,4619,4613,4626,4644,4649,4634,4611,4592,4580,4573,4570,4576,4585,4590,4586,4580,4578,4582,4585,
-4584,4584,4589,4599,4606,4605,4599,4594,4597,4615,4655,4713,4766,4783,4753,4700,4666,4660,4630,4504,4263,
-3963,3672,3395,3080,2713,2388,2248,2352,2607,2852,2994,3049,3075,3094,3096,3082,3080,3091,3079,3013,2911,
-2827,2790,2772,2735,2671,2605,2551,2497,2429,2356,2295,2249,2203,2151,2101,2058,2016,1967,1912,1859,1807,
-1750,1689,1637,1597,1560,1511,1456,1415,1396,1378,1342,1287,1232,1187,1149,1107,1061,1020,982,938,888,
-842,807,780,748,709,669,634,600,562,522,491,469,448,418,378,337,305,281,261,238,213,
-189,166,147,129,109,86,61,38,19,3,-15,-39,-65,-88,-102,-110,-118,-133,-150,-162,-167,
--169,-174,-177,-172,-158,-144,-143,-156,-175,-196,-223,-261,-308,-354,-392,-422,-446,-466,-482,-496,-509,
--524,-538,-553,-567,-582,-597,-608,-619,-631,-643,-653,-659,-662,-670,-684,-706,-729,-748,-762,-769,-775,
--783,-795,-813,-834,-860,-888,-914,-931,-942,-958,-983,-1011,-1034,-1049,-1066,-1090,-1119,-1144,-1161,-1176,-1192,
--1210,-1224,-1234,-1246,-1261,-1276,-1287,-1294,-1302,-1312,-1321,-1329,-1334,-1338,-1340,-1341,-1341,-1342,-1342,-1339,-1333,
--1328,-1324,-1320,-1312,-1303,-1293,-1284,-1272,-1256,-1242,-1232,-1226,-1219,-1208,-1197,-1191,-1190,-1189,-1185,-1180,-1173,
--1164,-1153,-1140,-1131,-1123,-1115,-1104,-1092,-1085,-1083,-1081,-1078,-1073,-1067,-1061,-1056,-1049,-1043,-1038,-1033,-1029,
--1026,-1024,-1020,-1012,-1004,-997,-990,-981,-969,-957,-948,-946,-945,-943,-940,-936,-931,-925,-915,-905,-895,
--888,-881,-874,-868,-864,-860,-854,-844,-833,-822,-813,-803,-793,-784,-778,-773,-767,-757,-747,-737,-730,
--724,-719,-712,-705,-699,-693,-689,-684,-677,-668,-657,-648,-641,-635,-627,-616,-607,-602,-599,-596,-589,
--580,-569,-558,-546,-536,-528,-523,-516,-503,-488,-474,-466,-460,-451,-441,-430,-421,-410,-398,-387,-380,
--376,-370,-360,-348,-338,-330,-320,-309,-299,-292,-285,-275,-262,-251,-241,-229,-213,-193,-173,-154,-134,
--113,-93,-74,-53,-28,-3,17,33,46,59,71,80,86,94,103,114,122,130,135,138,135,
-130,129,137,150,160,165,169,182,204,231,250,256,254,257,274,300,324,341,358,386,423,
-459,485,503,523,546,569,589,609,635,669,704,741,781,821,854,879,902,937,981,1023,1050,
-1067,1083,1107,1141,1182,1227,1274,1321,1366,1411,1455,1494,1525,1554,1588,1621,1639,1636,1613,1564,1465,
-1315,1183,1197,1445,1894,2406,2854,3198,3469,3676,3786,3781,3701,3610,3520,3385,3192,3016,2958,3029,3114,
-3076,2882,2621,2416,2326,2333,2389,2452,2494,2495,2461,2429,2434,2479,2524,2529,2484,2412,2340,2282,2240,
-2209,2179,2140,2084,2017,1955,1910,1878,1851,1822,1791,1763,1736,1710,1680,1640,1591,1538,1489,1448,1410,
-1369,1324,1277,1232,1188,1145,1102,1059,1018,980,948,925,911,900,885,863,831,788,730,662,594,
-537,500,489,497,505,487,424,332,257,236,269,315,323,276,186,73,-50,-180,-302,-399,-464,
--511,-563,-629,-693,-735,-749,-748,-751,-766,-789,-812,-832,-848,-859,-863,-865,-873,-895,-925,-948,-955,
--948,-940,-937,-932,-916,-887,-852,-819,-789,-758,-727,-702,-686,-677,-668,-649,-613,-557,-483,-404,-340,
--304,-289,-274,-238,-183,-127,-89,-75,-70,-60,-37,-9,16,33,45,60,84,119,156,190,214,
-231,245,261,279,296,308,313,315,315,317,320,323,326,329,338,353,370,385,395,404,417,
-438,467,498,525,551,578,608,640,670,695,718,740,763,787,810,831,852,873,894,913,930,
-948,968,990,1014,1038,1059,1077,1095,1112,1131,1150,1169,1190,1210,1229,1246,1260,1275,1294,1315,1337,
-1360,1383,1404,1420,1434,1448,1463,1476,1481,1479,1478,1483,1490,1492,1487,1481,1480,1484,1485,1480,1475,
-1476,1483,1490,1492,1492,1496,1503,1510,1515,1523,1536,1550,1562,1570,1578,1591,1607,1625,1642,1661,1682,
-1707,1734,1762,1789,1811,1828,1841,1858,1881,1906,1927,1943,1959,1985,2018,2052,2078,2102,2133,2131,2189,
-2238,2262,2266,2271,2289,2317,2348,2381,2420,2451,2448,2400,2328,2276,2273,2306,2341,2356,2358,2361,2371,
-2379,2381,2385,2399,2421,2440,2452,2462,2477,2494,2510,2525,2542,2563,2580,2588,2589,2589,2593,2599,2602,
-2605,2612,2626,2643,2660,2682,2716,2762,2808,2842,2866,2898,2955,3038,3123,3180,3194,3169,3128,3090,3068,
-3068,3088,3122,3163,3208,3261,3324,3391,3446,3472,3468,3443,3410,3379,3350,3324,3297,3272,3250,3235,3231,
-3239,3255,3272,3285,3292,3286,3265,3235,3213,3210,3215,3211,3192,3182,3209,3273,3342,3376,3363,3323,3283,
-3262,3272,3323,3418,3530,3617,3652,3646,3620,3577,3493,3356,3194,3059,2975,2925,2879,2822,2758,2682,2580,
-2448,2309,2198,2126,2080,2047,2028,2028,2033,2025,2001,1984,1989,2004,2003,1968,1907,1825,1724,1607,1493,
-1411,1370,1353,1339,1319,1299,1285,1275,1271,1274,1285,1296,1299,1300,1310,1327,1341,1348,1360,1389,1425,
-1445,1440,1431,1449,1508,1594,1680,1746,1784,1798,1799,1799,1805,1808,1796,1767,1736,1712,1696,1678,1656,
-1633,1611,1582,1539,1491,1450,1425,1411,1397,1378,1355,1327,1296,1270,1258,1260,1269,1280,1297,1324,1357,
-1383,1399,1406,1411,1409,1399,1387,1381,1380,1369,1345,1318,1303,1299,1290,1272,1259,1264,1281,1288,1286,
-1297,1335,1388,1425,1437,1438,1439,1430,1394,1341,1306,1311,1336,1343,1314,1268,1230,1204,1174,1134,1093,
-1062,1042,1026,1012,1004,999,990,976,961,952,945,933,912,888,869,853,835,810,782,753,726,
-700,672,644,616,587,558,531,503,473,441,411,386,359,327,290,256,228,201,169,130,93,
-66,45,23,-6,-42,-78,-112,-149,-193,-242,-292,-339,-384,-432,-484,-537,-587,-635,-684,-736,-788,
--839,-892,-948,-1004,-1054,-1091,-1121,-1151,-1188,-1233,-1283,-1337,-1396,-1454,-1506,-1548,-1584,-1618,-1648,-1678,-1709,
--1747,-1792,-1841,-1886,-1927,-1965,-2001,-2033,-2061,-2080,-2089,-2088,-2087,-2102,-2140,-2194,-2251,-2306,-2367,-2438,-2512,
--2570,-2608,-2638,-2681,-2741,-2811,-2878,-2940,-2996,-3045,-3080,-3095,-3098,-3100,-3113,-3140,-3173,-3201,-3219,-3230,-3246,
--3275,-3310,-3343,-3369,-3396,-3433,-3475,-3515,-3545,-3566,-3579,-3583,-3579,-3580,-3598,-3637,-3683,-3720,-3746,-3768,-3793,
--3818,-3836,-3843,-3843,-3840,-3837,-3835,-3833,-3831,-3837,-3855,-3881,-3900,-3901,-3887,-3878,-3887,-3902,-3904,-3891,-3884,
--3898,-3922,-3931,-3918,-3904,-3910,-3931,-3947,-3950,-3953,-3966,-3983,-3990,-3987,-3985,-3989,-3987,-3971,-3948,-3930,-3915,
--3891,-3853,-3809,-3769,-3732,-3693,-3656,-3632,-3619,-3596,-3538,-3432,-3282,-3107,-2947,-2852,-2848,-2904,-2941,-2896,-2773,
--2637,-2542,-2491,-2451,-2404,-2362,-2343,-2342,-2336,-2312,-2275,-2238,-2207,-2188,-2187,-2202,-2220,-2223,-2212,-2203,-2205,
--2208,-2188,-2144,-2092,-2050,-2021,-1997,-1980,-1980,-1997,-2002,-1966,-1882,-1782,-1712,-1692,-1712,-1743,-1763,-1763,-1748,
--1725,-1702,-1692,-1703,-1731,-1762,-1777,-1766,-1729,-1676,-1615,-1556,-1500,-1446,-1389,-1319,-1225,-1105,-972,-845,-736,
--644,-559,-474,-396,-334,-283,-228,-158,-82,-21,16,45,91,162,243,311,358,394,436,490,550,
-611,669,727,785,846,914,993,1078,1151,1198,1221,1243,1287,1356,1436,1509,1575,1645,1717,1776,1811,
-1829,1854,1900,1962,2022,2067,2102,2138,2177,2218,2255,2289,2323,2365,2416,2474,2528,2571,2609,2652,2707,
-2763,2804,2825,2834,2848,2869,2899,2942,3008,3096,3187,3258,3307,3351,3409,3482,3551,3597,3609,3593,3563,
-3537,3520,3492,3423,3297,3138,3002,2937,2941,2975,2999,3002,3000,3006,3015,3018,3022,3052,3123,3216,3286,
-3307,3295,3292,3324,3374,3404,3395,3374,3375,3413,3469,3519,3554,3581,3608,3634,3655,3672,3687,3697,3695,
-3681,3659,3636,3619,3609,3610,3621,3640,3664,3694,3739,3801,3866,3915,3946,3981,4049,4155,4269,4344,4361,
-4340,4321,4331,4363,4395,4416,4430,4450,4475,4500,4523,4547,4572,4591,4597,4596,4599,4609,4616,4609,4589,
-4565,4545,4531,4525,4528,4540,4552,4555,4549,4544,4546,4553,4557,4555,4555,4561,4572,4581,4584,4580,4576,
-4579,4603,4652,4716,4764,4766,4723,4671,4646,4635,4574,4399,4113,3784,3476,3181,2857,2513,2259,2216,2397,
-2678,2907,3021,3060,3083,3097,3087,3065,3066,3089,3085,3012,2890,2786,2738,2724,2694,2634,2564,2504,2449,
-2391,2331,2278,2230,2179,2125,2077,2039,2000,1950,1895,1844,1793,1733,1668,1614,1579,1548,1504,1449,1407,
-1387,1373,1340,1286,1230,1185,1148,1107,1061,1019,981,939,890,844,807,778,744,704,665,631,599,
-560,517,482,458,438,411,375,337,307,282,258,234,211,191,173,154,132,109,87,65,44,
-25,7,-11,-33,-56,-77,-90,-97,-105,-121,-141,-157,-166,-170,-174,-176,-170,-155,-141,-138,-150,
--169,-190,-215,-249,-292,-337,-377,-409,-436,-459,-479,-498,-517,-535,-551,-564,-576,-592,-610,-628,-644,
--660,-674,-687,-695,-699,-702,-708,-720,-738,-756,-771,-782,-791,-802,-818,-836,-856,-876,-896,-912,-922,
--931,-945,-968,-994,-1017,-1035,-1054,-1079,-1104,-1124,-1137,-1148,-1163,-1179,-1193,-1206,-1221,-1237,-1252,-1264,-1274,
--1287,-1300,-1313,-1321,-1327,-1332,-1335,-1335,-1334,-1335,-1336,-1335,-1333,-1329,-1324,-1317,-1307,-1296,-1288,-1281,-1272,
--1258,-1243,-1232,-1225,-1217,-1207,-1198,-1192,-1189,-1186,-1181,-1175,-1170,-1162,-1153,-1143,-1137,-1131,-1124,-1112,-1098,
--1089,-1085,-1085,-1084,-1079,-1074,-1069,-1066,-1062,-1057,-1051,-1044,-1039,-1037,-1034,-1028,-1018,-1010,-1005,-1002,-996,
--984,-971,-962,-959,-960,-959,-955,-950,-944,-937,-928,-918,-910,-903,-897,-890,-882,-876,-872,-868,-862,
--852,-840,-829,-819,-811,-802,-794,-788,-784,-779,-772,-762,-752,-745,-739,-733,-727,-719,-713,-709,-706,
--700,-692,-683,-675,-668,-660,-649,-638,-628,-621,-616,-610,-602,-593,-584,-573,-560,-548,-542,-539,-534,
--522,-504,-490,-483,-479,-473,-462,-450,-438,-426,-413,-402,-396,-394,-389,-379,-366,-354,-346,-338,-327,
--316,-307,-299,-289,-278,-268,-260,-249,-233,-211,-187,-166,-148,-130,-113,-95,-72,-44,-13,11,29,
-40,48,56,63,70,80,91,101,110,116,120,121,120,117,118,125,135,144,150,159,175,
-199,221,233,236,236,245,267,295,319,336,353,380,415,450,478,497,515,534,554,575,600,
-630,665,701,739,777,813,840,861,887,924,967,1003,1023,1034,1049,1078,1118,1165,1215,1266,1315,
-1360,1402,1439,1470,1498,1529,1565,1595,1607,1598,1574,1519,1412,1259,1143,1188,1465,1925,2432,2877,3229,
-3507,3699,3773,3733,3644,3563,3474,3314,3082,2879,2818,2899,2993,2958,2773,2539,2372,2316,2336,2379,2412,
-2424,2419,2413,2429,2474,2527,2548,2518,2450,2372,2305,2254,2216,2189,2162,2123,2065,1997,1938,1896,1864,
-1833,1800,1769,1746,1728,1708,1679,1638,1586,1532,1485,1448,1415,1379,1338,1298,1261,1227,1189,1148,1104,
-1060,1017,975,939,913,896,883,863,828,775,708,637,574,523,483,453,434,418,391,346,294,
-264,273,306,328,310,255,176,82,-33,-168,-299,-398,-459,-503,-557,-628,-696,-735,-740,-731,-728,
--742,-767,-794,-816,-833,-843,-846,-849,-862,-890,-927,-959,-972,-968,-953,-938,-923,-904,-880,-851,-818,
--780,-738,-701,-673,-654,-637,-615,-584,-541,-479,-397,-311,-245,-217,-214,-206,-166,-100,-36,-2,-4,
--22,-31,-22,0,28,51,70,91,118,153,188,216,234,246,261,284,311,336,351,357,357,
-356,359,366,376,385,392,400,411,422,431,438,444,454,473,500,531,561,589,617,647,679,
-707,731,752,772,795,817,839,859,879,899,919,937,956,976,996,1018,1040,1061,1082,1102,1121,
-1138,1155,1172,1190,1210,1230,1248,1265,1282,1300,1320,1342,1365,1390,1416,1440,1458,1473,1486,1499,1507,
-1505,1499,1494,1497,1501,1500,1492,1485,1484,1487,1486,1480,1477,1482,1491,1498,1498,1498,1502,1511,1518,
-1522,1528,1540,1553,1563,1569,1577,1591,1610,1628,1644,1661,1681,1705,1730,1757,1785,1809,1829,1844,1862,
-1884,1906,1923,1939,1961,1994,2029,2054,2068,2089,2131,2140,2213,2272,2299,2299,2290,2283,2281,2294,2338,
-2416,2496,2524,2474,2370,2279,2247,2273,2316,2342,2347,2345,2346,2351,2356,2364,2381,2402,2422,2438,2454,
-2472,2491,2507,2522,2541,2562,2580,2588,2589,2590,2594,2597,2596,2594,2598,2612,2632,2653,2675,2707,2751,
-2799,2837,2864,2894,2943,3014,3092,3149,3171,3160,3131,3098,3075,3070,3087,3118,3153,3188,3232,3299,3384,
-3465,3511,3512,3482,3443,3411,3387,3369,3354,3341,3324,3303,3286,3279,3283,3295,3307,3313,3309,3292,3268,
-3251,3248,3252,3242,3216,3200,3228,3306,3393,3440,3429,3382,3334,3310,3320,3371,3458,3551,3605,3600,3555,
-3505,3457,3386,3271,3134,3021,2957,2923,2882,2819,2737,2641,2524,2390,2267,2181,2138,2119,2107,2103,2106,
-2106,2086,2054,2034,2039,2053,2048,2013,1956,1885,1792,1675,1555,1464,1418,1402,1391,1375,1358,1347,1342,
-1340,1343,1351,1359,1363,1367,1376,1390,1400,1411,1433,1472,1511,1529,1524,1524,1559,1633,1724,1806,1865,
-1899,1913,1915,1915,1917,1914,1892,1853,1813,1785,1767,1745,1713,1676,1639,1600,1559,1520,1493,1480,1472,
-1460,1443,1425,1404,1380,1358,1346,1346,1353,1362,1376,1401,1430,1452,1463,1470,1478,1486,1487,1481,1476,
-1472,1460,1436,1410,1397,1397,1395,1384,1373,1374,1385,1392,1397,1416,1458,1507,1535,1536,1524,1512,1492,
-1450,1398,1366,1366,1378,1368,1332,1290,1261,1237,1202,1156,1116,1094,1083,1070,1055,1045,1043,1039,1030,
-1017,1009,1001,987,963,940,923,910,891,863,830,800,775,749,722,693,665,636,607,578,548,
-517,486,459,435,410,378,341,308,281,255,223,184,148,122,103,80,49,15,-16,-46,-81,
--126,-176,-223,-265,-306,-354,-407,-460,-509,-556,-606,-662,-718,-773,-825,-878,-929,-974,-1010,-1040,-1072,
--1112,-1160,-1213,-1269,-1327,-1382,-1432,-1475,-1512,-1543,-1572,-1602,-1639,-1683,-1732,-1779,-1818,-1852,-1883,-1915,-1949,
--1981,-2008,-2024,-2030,-2035,-2051,-2084,-2129,-2174,-2216,-2265,-2328,-2401,-2468,-2519,-2560,-2605,-2665,-2738,-2817,-2888,
--2943,-2979,-3000,-3014,-3030,-3052,-3078,-3105,-3129,-3146,-3157,-3166,-3182,-3211,-3247,-3281,-3313,-3349,-3394,-3443,-3481,
--3505,-3520,-3533,-3546,-3556,-3566,-3584,-3614,-3650,-3682,-3710,-3737,-3766,-3793,-3810,-3817,-3818,-3819,-3822,-3820,-3814,
--3809,-3820,-3853,-3894,-3918,-3910,-3888,-3883,-3907,-3937,-3942,-3922,-3906,-3919,-3946,-3955,-3936,-3915,-3919,-3944,-3967,
--3974,-3979,-3992,-4006,-4007,-3997,-3992,-3995,-3995,-3980,-3955,-3933,-3917,-3895,-3861,-3824,-3790,-3758,-3718,-3676,-3646,
--3632,-3620,-3589,-3525,-3419,-3268,-3092,-2942,-2880,-2916,-2986,-2995,-2903,-2749,-2608,-2521,-2474,-2439,-2408,-2390,-2386,
--2381,-2360,-2324,-2283,-2248,-2225,-2222,-2237,-2259,-2269,-2262,-2248,-2239,-2232,-2218,-2190,-2156,-2124,-2095,-2071,-2062,
--2075,-2099,-2097,-2038,-1932,-1825,-1767,-1767,-1798,-1822,-1823,-1807,-1785,-1764,-1744,-1733,-1743,-1775,-1813,-1836,-1828,
--1787,-1728,-1663,-1603,-1549,-1497,-1440,-1369,-1276,-1159,-1028,-901,-791,-697,-613,-531,-458,-400,-351,-299,-234,
--166,-114,-85,-63,-23,42,125,204,267,320,376,441,513,584,647,698,744,797,871,970,1081,
-1175,1227,1240,1240,1259,1311,1384,1460,1531,1600,1668,1725,1762,1786,1814,1860,1918,1972,2015,2050,2086,
-2125,2164,2200,2233,2268,2309,2357,2410,2464,2513,2557,2603,2655,2707,2746,2766,2771,2776,2790,2821,2876,
-2961,3066,3169,3246,3296,3338,3392,3459,3519,3553,3554,3535,3513,3494,3464,3395,3272,3113,2968,2886,2877,
-2906,2925,2919,2908,2916,2940,2956,2954,2954,2994,3081,3179,3236,3234,3202,3193,3226,3279,3317,3326,3327,
-3344,3382,3425,3462,3495,3529,3562,3586,3599,3610,3624,3634,3633,3619,3599,3582,3571,3566,3568,3580,3598,
-3620,3650,3692,3746,3800,3842,3876,3927,4010,4114,4203,4246,4244,4230,4236,4267,4309,4343,4365,4384,4406,
-4430,4453,4477,4501,4523,4535,4542,4553,4572,4591,4595,4578,4549,4519,4494,4477,4470,4478,4495,4511,4516,
-4513,4512,4516,4523,4526,4525,4525,4530,4538,4547,4553,4555,4555,4563,4593,4650,4714,4752,4741,4692,4645,
-4625,4603,4510,4299,3985,3633,3292,2960,2623,2324,2167,2227,2465,2745,2943,3035,3073,3099,3105,3080,3052,
-3064,3106,3113,3029,2881,2747,2680,2662,2642,2593,2526,2461,2404,2351,2300,2253,2204,2150,2096,2052,2016,
-1974,1919,1862,1814,1768,1710,1645,1591,1559,1534,1490,1430,1380,1359,1352,1329,1281,1224,1177,1139,1101,
-1057,1016,978,940,898,855,816,780,741,700,661,629,597,559,515,475,446,423,399,369,338,
-308,278,249,224,204,188,172,151,128,106,87,71,54,35,14,-5,-25,-45,-62,-75,-84,
--95,-112,-134,-154,-167,-173,-173,-170,-163,-151,-143,-144,-155,-173,-193,-217,-248,-287,-328,-365,-397,
--424,-449,-473,-497,-522,-546,-565,-578,-590,-606,-627,-650,-670,-686,-700,-714,-726,-735,-741,-744,-748,
--756,-767,-780,-793,-807,-821,-836,-851,-865,-877,-891,-904,-917,-930,-946,-966,-986,-1003,-1022,-1043,-1066,
--1087,-1102,-1113,-1125,-1140,-1157,-1172,-1189,-1206,-1223,-1237,-1248,-1261,-1277,-1293,-1305,-1313,-1319,-1325,-1328,-1328,
--1328,-1330,-1334,-1337,-1337,-1332,-1325,-1316,-1305,-1295,-1289,-1284,-1275,-1260,-1244,-1230,-1222,-1215,-1208,-1199,-1192,
--1185,-1178,-1171,-1165,-1160,-1153,-1144,-1136,-1130,-1126,-1121,-1110,-1096,-1086,-1081,-1081,-1081,-1078,-1073,-1069,-1067,
--1065,-1061,-1055,-1050,-1046,-1045,-1042,-1035,-1024,-1015,-1011,-1010,-1006,-997,-986,-979,-976,-974,-971,-966,-960,
--953,-945,-937,-930,-925,-920,-915,-908,-900,-892,-885,-880,-875,-866,-855,-843,-835,-830,-824,-815,-806,
--800,-797,-793,-785,-775,-767,-761,-756,-749,-741,-734,-729,-724,-719,-712,-706,-700,-693,-683,-671,-659,
--649,-641,-634,-626,-618,-610,-602,-592,-579,-568,-561,-558,-553,-540,-523,-508,-500,-498,-492,-481,-467,
--455,-444,-433,-421,-415,-412,-409,-400,-388,-376,-368,-360,-349,-335,-322,-312,-302,-291,-281,-272,-263,
--247,-225,-201,-180,-163,-147,-131,-112,-90,-63,-34,-6,14,27,36,43,49,56,64,75,85,
-92,95,95,97,99,103,108,115,124,134,146,161,178,195,207,213,217,224,238,261,287,
-311,332,352,377,407,438,465,487,505,522,539,560,586,617,653,692,733,770,799,818,836,
-863,902,946,980,1001,1017,1037,1067,1107,1152,1201,1252,1299,1344,1382,1414,1439,1466,1500,1539,1567,
-1574,1564,1539,1483,1370,1220,1125,1206,1516,1987,2486,2916,3259,3525,3692,3732,3667,3569,3484,3375,3178,
-2908,2682,2618,2703,2803,2788,2648,2480,2377,2357,2373,2380,2367,2351,2356,2394,2464,2540,2581,2559,2482,
-2388,2309,2255,2214,2180,2151,2122,2082,2027,1966,1912,1873,1841,1809,1778,1755,1740,1730,1713,1683,1639,
-1585,1532,1489,1457,1429,1399,1365,1332,1303,1275,1244,1207,1166,1122,1074,1026,984,953,933,917,896,
-857,800,732,667,612,565,519,470,424,383,345,307,277,269,289,316,322,293,238,168,81,
--31,-166,-295,-390,-449,-497,-559,-636,-703,-739,-743,-731,-725,-733,-752,-776,-798,-815,-823,-824,-826,
--839,-869,-911,-950,-972,-973,-958,-936,-912,-890,-868,-844,-811,-768,-720,-678,-649,-628,-604,-571,-528,
--474,-405,-319,-230,-162,-133,-129,-120,-80,-14,48,79,73,48,24,17,28,50,75,98,120,
-147,180,216,245,263,275,290,315,348,381,403,411,405,395,391,397,414,433,449,459,464,
-468,474,481,491,504,523,547,576,605,633,660,687,714,740,763,783,802,823,844,865,885,
-904,924,944,963,983,1004,1024,1044,1063,1083,1104,1127,1148,1167,1185,1203,1223,1244,1263,1280,1297,
-1316,1337,1358,1377,1396,1418,1442,1466,1486,1502,1515,1527,1531,1525,1514,1506,1505,1508,1508,1502,1498,
-1498,1499,1496,1489,1486,1490,1498,1502,1500,1501,1508,1518,1525,1528,1533,1542,1554,1562,1569,1579,1595,
-1613,1631,1647,1665,1685,1706,1727,1749,1775,1801,1823,1839,1855,1871,1890,1911,1936,1970,2009,2039,2052,
-2060,2085,2140,2164,2231,2280,2305,2312,2306,2287,2263,2261,2317,2430,2548,2596,2534,2401,2280,2232,2255,
-2303,2333,2336,2328,2324,2328,2337,2350,2367,2388,2408,2427,2446,2466,2484,2499,2514,2534,2558,2578,2589,
-2591,2590,2590,2589,2586,2582,2586,2602,2625,2649,2675,2706,2746,2790,2828,2855,2879,2915,2968,3029,3081,
-3114,3126,3121,3104,3084,3075,3084,3110,3139,3165,3199,3261,3353,3448,3510,3521,3497,3464,3439,3421,3405,
-3392,3381,3370,3356,3342,3334,3334,3338,3340,3337,3329,3313,3294,3283,3287,3296,3289,3261,3236,3252,3319,
-3404,3455,3452,3413,3373,3355,3367,3411,3481,3549,3578,3547,3479,3410,3354,3292,3203,3099,3013,2958,2915,
-2855,2768,2664,2550,2425,2300,2199,2146,2138,2150,2160,2163,2163,2153,2126,2095,2081,2092,2110,2109,2077,
-2025,1954,1857,1735,1610,1517,1470,1453,1441,1425,1413,1409,1410,1411,1411,1415,1422,1429,1436,1443,1449,
-1458,1475,1508,1552,1587,1601,1604,1627,1689,1780,1870,1938,1982,2007,2018,2019,2018,2017,2009,1982,1938,
-1895,1867,1850,1826,1785,1733,1682,1638,1599,1571,1554,1545,1535,1519,1503,1491,1479,1461,1440,1427,1428,
-1436,1445,1455,1470,1489,1505,1515,1526,1544,1563,1573,1570,1564,1558,1550,1533,1514,1502,1500,1496,1484,
-1472,1471,1481,1494,1511,1541,1583,1618,1626,1609,1584,1563,1534,1486,1434,1403,1400,1400,1379,1339,1305,
-1288,1271,1235,1187,1149,1135,1133,1126,1113,1105,1104,1101,1088,1071,1059,1051,1038,1016,993,974,958,
-935,905,874,847,823,798,770,741,713,685,656,627,598,568,537,508,481,455,424,389,355,
-327,302,273,239,206,179,157,132,102,71,44,16,-18,-64,-112,-154,-192,-232,-279,-333,-385,
--433,-481,-533,-590,-648,-703,-754,-803,-851,-895,-933,-968,-1005,-1048,-1097,-1150,-1204,-1255,-1304,-1352,-1396,
--1434,-1466,-1495,-1527,-1569,-1620,-1671,-1713,-1745,-1772,-1802,-1837,-1876,-1912,-1940,-1958,-1968,-1979,-2002,-2037,-2077,
--2114,-2149,-2191,-2248,-2315,-2382,-2438,-2485,-2532,-2588,-2659,-2735,-2802,-2845,-2862,-2866,-2877,-2904,-2941,-2976,-3004,
--3028,-3051,-3072,-3092,-3115,-3146,-3186,-3228,-3268,-3311,-3361,-3413,-3454,-3479,-3493,-3505,-3518,-3532,-3547,-3566,-3590,
--3616,-3642,-3670,-3704,-3743,-3776,-3792,-3794,-3791,-3794,-3802,-3807,-3803,-3799,-3813,-3854,-3904,-3929,-3916,-3889,-3891,
--3932,-3977,-3984,-3954,-3928,-3938,-3970,-3984,-3965,-3939,-3939,-3964,-3988,-3997,-4001,-4013,-4025,-4022,-4007,-3997,-4000,
--4003,-3990,-3965,-3942,-3926,-3904,-3873,-3840,-3811,-3784,-3747,-3706,-3675,-3658,-3645,-3625,-3592,-3534,-3425,-3254,-3065,
--2943,-2944,-3028,-3083,-3022,-2858,-2678,-2557,-2503,-2479,-2456,-2434,-2422,-2415,-2400,-2373,-2340,-2310,-2290,-2283,-2290,
--2304,-2312,-2306,-2286,-2265,-2248,-2233,-2218,-2201,-2182,-2163,-2149,-2152,-2171,-2184,-2156,-2068,-1949,-1855,-1828,-1856,
--1893,-1901,-1876,-1844,-1821,-1807,-1794,-1785,-1795,-1828,-1871,-1897,-1888,-1844,-1780,-1714,-1654,-1600,-1546,-1486,-1414,
--1323,-1212,-1086,-958,-843,-745,-661,-588,-524,-472,-426,-378,-323,-267,-222,-192,-162,-117,-49,32,113,
-185,250,314,385,463,540,609,664,712,771,858,976,1102,1200,1245,1239,1217,1214,1251,1320,1400,
-1478,1550,1617,1675,1719,1751,1782,1818,1861,1902,1939,1973,2005,2037,2072,2112,2159,2208,2257,2304,2355,
-2411,2467,2516,2560,2603,2648,2687,2708,2713,2711,2720,2754,2820,2916,3029,3137,3222,3281,3328,3379,3434,
-3477,3492,3479,3456,3441,3429,3388,3283,3114,2931,2807,2778,2816,2853,2849,2821,2820,2871,2942,2979,2964,
-2937,2952,3023,3108,3151,3138,3104,3097,3133,3189,3234,3262,3287,3321,3359,3389,3410,3433,3463,3495,3520,
-3535,3547,3561,3570,3568,3556,3543,3533,3524,3515,3510,3516,3533,3558,3590,3634,3686,3734,3769,3802,3861,
-3957,4067,4146,4168,4150,4134,4151,4196,4243,4277,4301,4323,4346,4368,4391,4417,4443,4461,4468,4474,4496,
-4534,4569,4578,4556,4518,4480,4451,4432,4425,4432,4449,4464,4471,4471,4471,4474,4478,4482,4486,4492,4498,
-4504,4509,4517,4523,4529,4544,4583,4646,4706,4730,4705,4654,4615,4596,4556,4432,4193,3863,3489,3107,2731,
-2391,2160,2118,2280,2555,2810,2966,3038,3080,3110,3106,3062,3023,3038,3091,3107,3026,2871,2722,2633,2598,
-2575,2534,2480,2423,2368,2316,2270,2226,2178,2123,2069,2026,1989,1943,1884,1827,1783,1742,1689,1623,1569,
-1539,1513,1465,1396,1337,1315,1318,1312,1276,1221,1170,1131,1095,1055,1014,975,939,902,862,821,779,
-736,694,658,627,596,559,516,475,440,412,388,364,339,308,273,237,208,189,177,163,144,
-122,103,89,76,61,43,22,1,-18,-35,-51,-65,-77,-90,-106,-127,-149,-166,-174,-171,-163,
--154,-148,-148,-155,-167,-183,-200,-221,-250,-284,-320,-354,-384,-413,-441,-468,-496,-525,-554,-578,-597,
--614,-633,-655,-677,-696,-710,-722,-734,-749,-763,-774,-779,-780,-781,-784,-792,-805,-820,-836,-852,-864,
--873,-880,-888,-900,-917,-935,-954,-971,-984,-997,-1014,-1034,-1054,-1071,-1083,-1096,-1111,-1128,-1146,-1162,-1180,
--1198,-1214,-1226,-1237,-1252,-1268,-1283,-1293,-1300,-1307,-1315,-1319,-1319,-1319,-1322,-1329,-1334,-1335,-1330,-1322,-1313,
--1304,-1297,-1291,-1284,-1272,-1255,-1237,-1224,-1215,-1209,-1203,-1194,-1184,-1173,-1163,-1156,-1152,-1149,-1144,-1136,-1127,
--1120,-1115,-1110,-1101,-1090,-1081,-1075,-1074,-1074,-1073,-1070,-1067,-1064,-1062,-1059,-1055,-1052,-1051,-1052,-1050,-1043,
--1032,-1024,-1019,-1016,-1012,-1004,-998,-993,-989,-985,-980,-975,-970,-963,-955,-949,-944,-939,-934,-929,-924,
--918,-910,-901,-893,-886,-878,-867,-856,-849,-846,-843,-836,-826,-818,-814,-810,-804,-795,-787,-781,-776,
--768,-760,-753,-747,-741,-733,-726,-721,-716,-709,-700,-690,-678,-668,-660,-653,-645,-638,-631,-623,-613,
--601,-588,-579,-572,-566,-554,-538,-525,-518,-515,-508,-496,-483,-473,-465,-456,-444,-436,-432,-428,-419,
--407,-396,-390,-383,-371,-355,-341,-330,-322,-311,-299,-288,-277,-262,-242,-219,-199,-182,-165,-146,-126,
--105,-84,-61,-36,-14,4,18,28,36,41,47,55,64,71,72,70,70,75,85,96,104,
-112,124,140,158,173,182,187,191,200,213,229,246,267,291,317,342,366,390,416,443,468,
-488,507,526,550,578,610,649,692,737,772,794,806,821,849,887,928,961,988,1013,1040,1071,
-1107,1147,1191,1234,1276,1314,1351,1382,1411,1443,1484,1526,1554,1558,1546,1520,1460,1342,1194,1120,1237,
-1576,2051,2528,2929,3249,3496,3643,3660,3575,3460,3354,3216,2989,2701,2475,2415,2498,2598,2608,2530,2445,
-2414,2426,2430,2398,2349,2319,2340,2415,2521,2610,2632,2570,2456,2340,2257,2206,2168,2132,2098,2065,2025,
-1975,1920,1872,1835,1804,1778,1757,1744,1738,1731,1715,1686,1643,1590,1537,1494,1463,1440,1419,1397,1375,
-1354,1330,1303,1272,1237,1198,1155,1110,1070,1039,1015,992,963,921,864,801,741,689,641,588,526,
-464,407,359,318,290,284,298,315,308,268,204,126,33,-80,-207,-322,-406,-462,-513,-578,-652,
--713,-747,-755,-749,-742,-741,-748,-763,-780,-796,-804,-805,-806,-817,-844,-883,-922,-949,-956,-946,-926,
--903,-883,-864,-842,-810,-763,-709,-660,-624,-599,-573,-537,-490,-431,-359,-272,-182,-110,-68,-50,-33,
-2,55,108,141,150,138,115,92,79,80,94,112,134,159,192,228,260,283,299,316,342,
-379,421,455,469,461,439,421,419,436,462,484,498,502,505,511,523,541,560,580,603,628,
-656,682,706,728,750,773,796,815,834,853,875,897,918,938,958,978,998,1018,1038,1058,1078,
-1097,1115,1136,1159,1181,1201,1221,1241,1262,1282,1300,1316,1333,1353,1376,1395,1411,1425,1441,1462,1485,
-1505,1522,1536,1545,1547,1540,1526,1515,1512,1514,1516,1515,1514,1513,1512,1507,1500,1497,1500,1503,1504,
-1503,1506,1514,1522,1527,1529,1534,1542,1551,1557,1563,1574,1591,1611,1630,1648,1670,1692,1713,1729,1747,
-1768,1792,1813,1828,1839,1853,1873,1901,1936,1975,2010,2033,2046,2063,2102,2164,2180,2217,2238,2254,2271,
-2279,2264,2234,2233,2301,2433,2562,2605,2533,2393,2274,2232,2259,2303,2324,2318,2305,2301,2310,2324,2341,
-2361,2382,2402,2420,2438,2456,2474,2488,2503,2524,2550,2575,2590,2594,2591,2585,2581,2576,2574,2579,2595,
-2620,2649,2679,2710,2746,2785,2820,2846,2865,2884,2912,2949,2991,3035,3076,3104,3110,3095,3077,3076,3094,
-3121,3144,3172,3224,3306,3395,3456,3476,3467,3456,3451,3447,3436,3420,3407,3401,3400,3401,3405,3407,3404,
-3394,3379,3365,3349,3334,3328,3337,3350,3348,3320,3288,3286,3330,3398,3448,3457,3438,3418,3414,3432,3471,
-3524,3569,3574,3524,3439,3356,3292,3237,3174,3101,3030,2964,2887,2789,2674,2557,2443,2328,2221,2145,2122,
-2143,2177,2199,2203,2196,2180,2155,2133,2130,2148,2170,2172,2145,2091,2012,1904,1775,1652,1567,1524,1506,
-1490,1473,1464,1466,1473,1476,1475,1477,1485,1496,1503,1506,1507,1516,1541,1583,1627,1656,1670,1693,1750,
-1843,1943,2019,2062,2084,2099,2106,2105,2101,2098,2087,2060,2019,1980,1959,1945,1920,1872,1809,1749,1700,
-1663,1638,1624,1614,1600,1584,1570,1564,1557,1541,1520,1507,1510,1519,1525,1525,1528,1538,1551,1564,1583,
-1609,1635,1648,1648,1643,1643,1645,1639,1628,1617,1608,1595,1578,1567,1571,1589,1612,1637,1666,1695,1707,
-1693,1664,1639,1621,1592,1539,1480,1445,1437,1431,1403,1360,1329,1318,1306,1272,1225,1193,1187,1191,1188,
-1177,1170,1169,1163,1145,1121,1105,1097,1087,1067,1043,1020,998,973,946,920,897,874,846,816,788,
-763,736,707,678,652,624,592,558,526,498,469,436,401,372,347,322,293,262,232,205,178,
-150,125,102,74,38,-5,-48,-87,-124,-165,-213,-263,-312,-360,-410,-465,-524,-581,-635,-685,-732,
--777,-821,-863,-905,-946,-991,-1041,-1092,-1141,-1185,-1227,-1270,-1316,-1358,-1392,-1421,-1455,-1501,-1555,-1606,-1645,
--1672,-1699,-1734,-1778,-1823,-1860,-1882,-1889,-1892,-1903,-1929,-1968,-2012,-2055,-2096,-2142,-2196,-2256,-2315,-2371,-2421,
--2470,-2522,-2581,-2645,-2698,-2726,-2726,-2721,-2732,-2767,-2809,-2843,-2866,-2891,-2926,-2966,-3004,-3039,-3081,-3135,-3194,
--3248,-3295,-3338,-3380,-3418,-3447,-3466,-3477,-3486,-3499,-3519,-3545,-3571,-3591,-3608,-3633,-3673,-3722,-3761,-3777,-3772,
--3763,-3768,-3788,-3808,-3814,-3812,-3823,-3862,-3912,-3937,-3923,-3897,-3905,-3954,-4004,-4007,-3965,-3929,-3939,-3980,-4005,
--3994,-3970,-3968,-3990,-4009,-4011,-4009,-4019,-4032,-4031,-4016,-4005,-4007,-4009,-3998,-3975,-3955,-3940,-3921,-3892,-3859,
--3832,-3807,-3775,-3740,-3712,-3695,-3676,-3650,-3625,-3594,-3524,-3378,-3181,-3024,-2996,-3080,-3158,-3116,-2946,-2741,-2599,
--2543,-2527,-2505,-2473,-2450,-2444,-2439,-2426,-2404,-2385,-2372,-2364,-2360,-2358,-2353,-2340,-2318,-2293,-2270,-2253,-2242,
--2233,-2227,-2225,-2230,-2244,-2259,-2247,-2184,-2072,-1954,-1886,-1891,-1938,-1973,-1964,-1925,-1886,-1864,-1853,-1840,-1831,
--1841,-1878,-1924,-1951,-1939,-1892,-1826,-1761,-1703,-1650,-1594,-1532,-1460,-1374,-1270,-1151,-1025,-906,-804,-721,-655,
--600,-555,-514,-472,-429,-386,-347,-306,-257,-192,-114,-30,51,128,200,268,336,408,484,557,622,
-682,757,862,992,1118,1200,1219,1191,1155,1149,1188,1262,1348,1431,1504,1570,1629,1680,1721,1751,1772,
-1789,1808,1834,1864,1891,1915,1944,1991,2056,2127,2188,2240,2294,2360,2428,2486,2525,2556,2589,2624,2650,
-2660,2664,2680,2723,2793,2883,2982,3078,3162,3230,3288,3344,3395,3427,3427,3396,3358,3337,3324,3276,3154,
-2966,2782,2683,2692,2754,2787,2761,2726,2756,2866,2992,3051,3019,2949,2917,2950,3011,3046,3038,3015,3018,
-3059,3118,3169,3209,3247,3290,3329,3353,3364,3374,3391,3415,3437,3458,3480,3499,3508,3504,3493,3484,3478,
-3468,3452,3440,3442,3460,3487,3520,3565,3619,3669,3703,3731,3782,3876,3988,4071,4094,4075,4061,4082,4130,
-4179,4211,4234,4254,4274,4292,4312,4340,4371,4391,4397,4407,4440,4495,4544,4557,4530,4485,4444,4416,4400,
-4394,4398,4408,4417,4421,4422,4422,4424,4427,4434,4446,4459,4469,4474,4479,4487,4495,4503,4523,4571,4638,
-4692,4700,4662,4613,4585,4565,4498,4335,4064,3711,3313,2894,2492,2176,2033,2110,2357,2649,2870,2987,3043,
-3086,3115,3098,3037,2984,2984,3025,3040,2980,2857,2727,2629,2563,2512,2465,2422,2380,2334,2285,2240,2201,
-2157,2102,2046,1999,1959,1912,1854,1798,1757,1719,1668,1603,1547,1514,1485,1433,1356,1289,1265,1278,1288,
-1267,1217,1165,1125,1093,1057,1014,971,932,896,857,815,770,727,689,657,627,596,560,522,482,
-443,407,379,358,337,309,271,231,198,177,163,151,138,122,107,91,76,61,44,25,5,
--14,-30,-45,-61,-76,-89,-102,-118,-137,-157,-168,-167,-157,-147,-145,-152,-166,-182,-197,-212,-230,
--253,-281,-310,-341,-372,-404,-437,-469,-499,-529,-559,-587,-613,-637,-659,-681,-700,-717,-730,-741,-754,
--769,-784,-796,-804,-807,-807,-807,-809,-816,-828,-844,-860,-875,-886,-893,-898,-906,-920,-939,-958,-974,
--986,-998,-1015,-1034,-1051,-1064,-1076,-1090,-1108,-1127,-1144,-1161,-1177,-1194,-1207,-1218,-1229,-1243,-1258,-1269,-1277,
--1284,-1294,-1304,-1309,-1308,-1307,-1309,-1315,-1320,-1320,-1316,-1310,-1304,-1298,-1291,-1283,-1273,-1259,-1243,-1228,-1217,
--1209,-1202,-1194,-1184,-1172,-1160,-1149,-1142,-1140,-1140,-1138,-1132,-1124,-1117,-1110,-1104,-1096,-1087,-1079,-1074,-1071,
--1071,-1072,-1071,-1069,-1066,-1062,-1059,-1055,-1053,-1055,-1057,-1056,-1051,-1043,-1036,-1031,-1026,-1018,-1012,-1008,-1005,
--1000,-994,-988,-984,-981,-976,-969,-964,-960,-955,-946,-938,-934,-931,-926,-916,-906,-898,-891,-881,-870,
--862,-859,-857,-852,-843,-834,-828,-824,-818,-810,-803,-797,-791,-784,-777,-771,-765,-757,-747,-737,-730,
--724,-719,-712,-704,-695,-686,-677,-671,-665,-658,-649,-639,-629,-618,-606,-594,-584,-575,-565,-554,-544,
--538,-534,-527,-515,-503,-494,-488,-481,-470,-460,-453,-447,-437,-424,-414,-409,-405,-395,-379,-363,-353,
--346,-336,-323,-309,-296,-281,-261,-239,-219,-201,-182,-160,-138,-119,-104,-88,-68,-47,-25,-7,8,
-18,22,24,28,36,46,50,49,49,55,67,81,91,99,110,124,140,152,158,163,172,
-186,203,218,231,247,271,300,328,351,371,395,421,448,471,492,515,543,574,610,651,698,
-741,771,785,792,808,837,874,910,943,975,1009,1042,1073,1107,1144,1184,1219,1250,1281,1316,1352,
-1388,1430,1480,1528,1556,1560,1548,1522,1456,1329,1179,1121,1265,1624,2093,2539,2902,3194,3425,3561,3565,
-3465,3332,3205,3049,2817,2541,2336,2285,2360,2452,2480,2456,2442,2467,2500,2493,2439,2373,2345,2380,2472,
-2585,2665,2666,2583,2452,2326,2235,2175,2130,2088,2049,2012,1971,1924,1874,1830,1793,1765,1745,1734,1731,
-1729,1721,1706,1683,1648,1602,1551,1505,1470,1448,1434,1425,1415,1402,1381,1355,1327,1300,1271,1239,1204,
-1171,1141,1113,1082,1044,998,942,880,818,762,708,649,583,515,455,404,362,330,315,313,308,
-277,213,126,28,-74,-184,-294,-386,-451,-498,-544,-601,-663,-715,-749,-768,-774,-771,-764,-758,-761,
--772,-786,-795,-796,-796,-802,-822,-855,-892,-920,-931,-926,-911,-892,-875,-859,-840,-809,-762,-704,-647,
--603,-573,-548,-516,-471,-412,-339,-255,-169,-93,-37,0,30,62,98,137,176,209,225,218,190,
-156,133,128,136,153,175,204,236,266,291,310,329,356,395,442,486,511,507,481,453,442,
-454,478,502,517,525,532,542,559,581,605,628,651,676,703,729,750,769,787,809,831,851,
-869,889,912,937,960,981,1001,1020,1039,1058,1077,1097,1118,1138,1157,1175,1196,1217,1238,1257,1277,
-1296,1314,1330,1345,1361,1381,1402,1420,1434,1445,1460,1480,1503,1524,1542,1555,1563,1563,1555,1541,1528,
-1521,1521,1523,1524,1523,1520,1517,1513,1510,1508,1508,1508,1507,1508,1512,1517,1521,1522,1524,1531,1540,
-1546,1549,1554,1566,1584,1604,1625,1647,1672,1697,1718,1735,1751,1771,1792,1809,1820,1829,1844,1868,1900,
-1935,1967,1993,2015,2041,2079,2130,2180,2159,2157,2152,2163,2187,2204,2196,2180,2199,2284,2413,2518,2535,
-2456,2339,2258,2245,2277,2308,2311,2294,2280,2281,2294,2311,2330,2353,2376,2395,2409,2422,2440,2460,2477,
-2493,2511,2535,2562,2583,2591,2587,2579,2572,2569,2569,2577,2594,2621,2653,2685,2715,2745,2779,2813,2841,
-2858,2865,2869,2880,2907,2957,3022,3082,3112,3107,3083,3068,3078,3105,3134,3161,3199,3253,3311,3353,3373,
-3386,3408,3439,3464,3468,3456,3441,3436,3444,3460,3476,3484,3479,3462,3440,3420,3403,3389,3384,3391,3404,
-3403,3379,3346,3332,3357,3407,3453,3475,3476,3475,3486,3512,3549,3587,3606,3583,3510,3409,3315,3249,3205,
-3164,3112,3042,2949,2831,2699,2573,2466,2374,2283,2198,2142,2133,2164,2202,2225,2227,2217,2204,2188,2177,
-2180,2197,2215,2216,2190,2134,2047,1930,1801,1688,1615,1579,1559,1539,1520,1513,1520,1530,1535,1536,1539,
-1547,1558,1564,1565,1568,1582,1614,1657,1696,1721,1744,1794,1886,2000,2097,2149,2164,2169,2175,2180,2176,
-2169,2163,2153,2130,2095,2063,2045,2031,2001,1947,1880,1817,1767,1730,1705,1689,1679,1666,1652,1644,1641,
-1637,1623,1603,1592,1595,1600,1596,1585,1579,1587,1604,1625,1647,1674,1698,1713,1718,1721,1729,1736,1738,
-1732,1723,1709,1691,1673,1671,1690,1722,1751,1771,1783,1787,1775,1746,1717,1705,1703,1680,1621,1547,1498,
-1481,1472,1443,1400,1367,1356,1345,1314,1273,1247,1245,1253,1249,1236,1225,1222,1213,1193,1167,1150,1141,
-1132,1112,1087,1063,1041,1017,994,971,950,924,893,862,837,814,788,757,727,702,676,645,607,
-572,543,515,484,450,419,395,372,346,316,284,254,227,202,180,157,129,94,54,16,-20,
--60,-104,-150,-195,-240,-288,-342,-401,-458,-514,-567,-618,-664,-707,-751,-797,-844,-891,-936,-984,-1033,
--1078,-1116,-1152,-1194,-1241,-1285,-1321,-1350,-1385,-1434,-1489,-1539,-1574,-1601,-1632,-1676,-1729,-1779,-1814,-1826,-1818,
--1806,-1806,-1829,-1872,-1927,-1986,-2047,-2108,-2166,-2219,-2271,-2325,-2380,-2433,-2482,-2533,-2587,-2634,-2658,-2661,-2663,
--2684,-2724,-2763,-2781,-2786,-2797,-2829,-2875,-2920,-2963,-3015,-3085,-3165,-3236,-3287,-3320,-3347,-3376,-3405,-3429,-3443,
--3450,-3461,-3486,-3520,-3551,-3571,-3583,-3604,-3647,-3701,-3744,-3758,-3746,-3734,-3745,-3779,-3819,-3839,-3841,-3846,-3875,
--3918,-3943,-3934,-3912,-3920,-3966,-4010,-4005,-3956,-3916,-3929,-3980,-4018,-4016,-3998,-3997,-4015,-4027,-4021,-4011,-4015,
--4028,-4031,-4021,-4010,-4011,-4011,-4000,-3980,-3964,-3954,-3939,-3912,-3880,-3854,-3832,-3804,-3773,-3751,-3735,-3711,-3673,
--3636,-3607,-3557,-3439,-3261,-3104,-3062,-3136,-3214,-3174,-2998,-2782,-2634,-2582,-2573,-2550,-2509,-2478,-2471,-2475,-2470,
--2455,-2443,-2437,-2433,-2423,-2405,-2385,-2365,-2345,-2325,-2305,-2287,-2272,-2264,-2268,-2285,-2309,-2331,-2332,-2292,-2203,
--2085,-1983,-1938,-1957,-2002,-2025,-2009,-1971,-1939,-1920,-1902,-1878,-1863,-1876,-1919,-1969,-1994,-1978,-1925,-1858,-1793,
--1737,-1686,-1636,-1579,-1514,-1436,-1341,-1229,-1105,-984,-879,-798,-738,-692,-652,-614,-578,-543,-509,-471,-418,
--346,-260,-171,-85,-1,82,163,234,297,359,428,501,570,639,725,844,983,1102,1161,1151,1104,
-1068,1078,1135,1221,1312,1394,1463,1523,1579,1631,1676,1703,1710,1704,1701,1715,1742,1768,1788,1814,1863,
-1939,2023,2096,2157,2222,2302,2387,2454,2491,2511,2532,2561,2591,2614,2635,2669,2722,2790,2862,2934,3006,
-3078,3148,3216,3284,3344,3380,3375,3330,3272,3232,3205,3151,3025,2841,2670,2594,2626,2695,2719,2681,2648,
-2701,2845,2997,3061,3015,2919,2860,2869,2915,2947,2947,2938,2956,3008,3075,3132,3172,3206,3243,3280,3306,
-3319,3323,3329,3339,3357,3383,3414,3441,3451,3444,3432,3424,3420,3409,3391,3378,3381,3401,3425,3449,3486,
-3543,3605,3650,3676,3710,3784,3888,3979,4018,4013,4006,4028,4075,4121,4153,4174,4191,4206,4218,4235,4265,
-4300,4325,4335,4350,4391,4455,4507,4517,4485,4436,4398,4378,4370,4368,4369,4372,4375,4375,4375,4376,4379,
-4385,4395,4410,4426,4437,4446,4456,4467,4476,4483,4506,4559,4627,4671,4662,4615,4575,4560,4537,4439,4224,
-3901,3510,3082,2647,2259,2005,1965,2141,2439,2725,2912,3003,3053,3095,3116,3089,3020,2954,2926,2930,2929,
-2899,2841,2769,2683,2585,2486,2409,2362,2331,2295,2250,2209,2175,2137,2084,2023,1969,1925,1880,1826,1773,
-1731,1693,1644,1583,1528,1492,1460,1405,1326,1255,1227,1240,1258,1247,1205,1155,1117,1089,1057,1012,963,
-919,881,845,804,759,719,687,660,631,599,565,530,493,451,409,374,350,332,308,275,236,
-201,174,154,141,133,126,113,95,74,57,42,26,7,-11,-27,-41,-57,-75,-92,-103,-113,
--127,-146,-160,-162,-154,-146,-147,-158,-176,-195,-213,-230,-249,-268,-289,-310,-335,-365,-399,-437,-474,
--507,-536,-564,-592,-621,-648,-673,-693,-711,-727,-742,-758,-774,-788,-799,-808,-817,-825,-830,-831,-830,
--831,-837,-848,-864,-882,-898,-909,-915,-919,-927,-941,-958,-973,-987,-1003,-1022,-1042,-1058,-1069,-1080,-1096,
--1114,-1132,-1148,-1164,-1179,-1193,-1203,-1211,-1222,-1235,-1246,-1254,-1261,-1270,-1283,-1294,-1299,-1297,-1295,-1295,-1298,
--1299,-1298,-1294,-1291,-1288,-1282,-1275,-1266,-1255,-1244,-1232,-1221,-1212,-1203,-1194,-1185,-1176,-1167,-1155,-1144,-1136,
--1132,-1131,-1131,-1129,-1127,-1123,-1116,-1108,-1098,-1089,-1082,-1077,-1074,-1074,-1075,-1076,-1074,-1071,-1067,-1062,-1058,
--1057,-1058,-1061,-1061,-1057,-1052,-1049,-1046,-1041,-1033,-1027,-1024,-1021,-1015,-1006,-999,-996,-993,-988,-983,-980,
--977,-971,-959,-946,-940,-939,-936,-927,-916,-909,-905,-898,-887,-876,-870,-867,-862,-855,-847,-841,-836,
--830,-823,-817,-811,-805,-798,-791,-787,-781,-773,-761,-750,-741,-734,-727,-720,-714,-706,-697,-688,-682,
--678,-672,-662,-649,-639,-630,-621,-609,-597,-588,-581,-573,-565,-559,-554,-548,-537,-526,-517,-511,-503,
--493,-482,-475,-469,-458,-444,-433,-430,-429,-420,-404,-386,-374,-366,-356,-344,-330,-317,-301,-280,-257,
--236,-217,-198,-175,-153,-135,-123,-110,-93,-73,-53,-35,-18,-6,-2,-4,-3,3,17,28,33,
-34,40,51,65,76,85,92,102,112,122,131,142,157,175,192,206,220,239,264,292,318,
-339,360,385,412,438,460,480,504,534,567,605,648,694,731,751,758,764,785,819,857,892,
-925,962,1000,1033,1063,1096,1137,1178,1210,1235,1262,1298,1339,1381,1429,1484,1535,1565,1571,1563,1538,
-1466,1327,1172,1123,1288,1660,2122,2542,2875,3147,3368,3497,3490,3373,3224,3086,2932,2720,2478,2302,2261,
-2327,2408,2444,2449,2473,2522,2557,2540,2479,2419,2408,2461,2557,2654,2706,2681,2585,2455,2331,2235,2165,
-2110,2062,2019,1977,1933,1887,1842,1801,1766,1738,1721,1716,1717,1714,1705,1692,1677,1655,1621,1577,1531,
-1494,1469,1456,1451,1448,1439,1421,1394,1368,1345,1325,1302,1276,1250,1223,1193,1157,1115,1066,1008,941,
-871,806,746,684,618,552,497,453,418,385,354,321,275,204,108,0,-107,-208,-304,-390,-456,
--500,-530,-563,-604,-651,-696,-736,-770,-792,-798,-791,-780,-776,-782,-792,-797,-794,-787,-787,-800,-831,
--869,-901,-915,-910,-893,-873,-855,-840,-823,-797,-756,-703,-645,-597,-563,-537,-507,-466,-411,-342,-265,
--184,-107,-40,16,60,92,117,145,185,234,277,292,277,244,212,194,189,194,207,225,246,
-267,287,308,331,359,397,446,495,528,531,508,480,468,476,495,514,528,540,553,568,587,
-610,636,662,687,712,738,764,787,805,825,846,869,889,908,929,954,981,1005,1025,1044,1062,
-1080,1097,1114,1135,1157,1178,1195,1212,1231,1252,1274,1293,1309,1325,1341,1356,1370,1385,1403,1421,1437,
-1451,1463,1479,1498,1521,1543,1561,1574,1581,1581,1573,1561,1546,1534,1528,1528,1529,1528,1523,1519,1516,
-1517,1517,1515,1510,1508,1510,1514,1516,1515,1515,1520,1530,1539,1544,1546,1553,1568,1586,1605,1623,1645,
-1669,1694,1716,1736,1757,1778,1798,1813,1823,1834,1850,1874,1900,1926,1949,1974,2007,2051,2101,2141,2159,
-2094,2070,2067,2089,2118,2129,2124,2134,2191,2295,2402,2453,2423,2341,2265,2240,2264,2299,2311,2297,2275,
-2266,2272,2284,2298,2316,2340,2366,2383,2390,2399,2418,2446,2472,2487,2498,2515,2540,2564,2577,2576,2568,
-2561,2560,2564,2575,2595,2625,2660,2691,2717,2741,2769,2800,2830,2850,2855,2849,2843,2856,2902,2976,3054,
-3104,3111,3088,3064,3064,3088,3124,3159,3189,3214,3233,3245,3259,3291,3349,3421,3482,3513,3513,3498,3486,
-3490,3506,3526,3539,3539,3526,3504,3482,3461,3445,3438,3443,3452,3452,3433,3404,3386,3395,3429,3469,3498,
-3514,3523,3538,3562,3592,3614,3605,3551,3456,3348,3258,3203,3174,3149,3104,3025,2906,2762,2619,2505,2425,
-2363,2297,2230,2182,2173,2195,2226,2244,2247,2242,2237,2232,2228,2228,2234,2241,2238,2215,2163,2075,1959,
-1835,1732,1668,1633,1610,1587,1569,1564,1572,1584,1592,1597,1601,1607,1615,1621,1626,1636,1657,1692,1732,
-1765,1791,1829,1905,2019,2138,2218,2247,2245,2243,2250,2254,2248,2236,2228,2219,2198,2166,2135,2112,2090,
-2052,1996,1933,1877,1832,1796,1769,1753,1743,1732,1722,1715,1714,1712,1702,1689,1682,1681,1675,1659,1640,
-1635,1649,1675,1701,1722,1741,1760,1776,1789,1801,1810,1814,1812,1809,1806,1797,1780,1766,1774,1809,1852,
-1879,1883,1874,1861,1837,1804,1780,1781,1792,1775,1707,1614,1543,1515,1506,1484,1444,1411,1396,1385,1360,
-1326,1305,1306,1311,1305,1287,1272,1265,1256,1237,1214,1197,1186,1174,1153,1130,1108,1089,1068,1043,1019,
-995,968,938,910,888,866,837,803,771,745,722,692,656,620,590,563,533,501,471,447,425,
-398,368,337,309,284,260,237,212,183,150,116,81,44,1,-44,-88,-128,-169,-219,-277,-336,
--391,-444,-498,-551,-598,-640,-682,-731,-783,-832,-877,-921,-966,-1009,-1047,-1082,-1123,-1169,-1213,-1248,-1279,
--1317,-1369,-1425,-1471,-1504,-1532,-1569,-1619,-1675,-1726,-1757,-1763,-1746,-1723,-1713,-1730,-1774,-1839,-1917,-2000,-2078,
--2144,-2195,-2243,-2297,-2357,-2415,-2467,-2517,-2572,-2625,-2664,-2687,-2709,-2746,-2791,-2823,-2824,-2806,-2795,-2810,-2841,
--2876,-2910,-2955,-3023,-3106,-3186,-3245,-3283,-3309,-3338,-3372,-3404,-3423,-3430,-3437,-3459,-3496,-3532,-3556,-3571,-3594,
--3637,-3690,-3729,-3738,-3721,-3706,-3719,-3763,-3818,-3856,-3867,-3871,-3890,-3927,-3954,-3951,-3932,-3934,-3970,-4006,-4001,
--3956,-3921,-3936,-3988,-4029,-4032,-4016,-4015,-4032,-4044,-4035,-4020,-4018,-4026,-4028,-4018,-4009,-4009,-4008,-3997,-3978,
--3965,-3959,-3949,-3925,-3898,-3878,-3861,-3835,-3804,-3782,-3770,-3748,-3703,-3650,-3606,-3556,-3462,-3315,-3181,-3142,-3203,
--3264,-3212,-3029,-2810,-2665,-2620,-2618,-2598,-2554,-2518,-2510,-2513,-2506,-2487,-2473,-2471,-2471,-2459,-2434,-2405,-2384,
--2372,-2363,-2351,-2334,-2316,-2310,-2323,-2354,-2387,-2402,-2383,-2324,-2233,-2134,-2057,-2023,-2029,-2048,-2053,-2038,-2015,
--1995,-1972,-1939,-1900,-1881,-1900,-1951,-2003,-2023,-2001,-1944,-1875,-1810,-1754,-1708,-1667,-1623,-1571,-1503,-1413,-1301,
--1177,-1055,-953,-881,-834,-800,-768,-730,-689,-651,-613,-568,-504,-417,-319,-223,-136,-51,36,124,199,
-259,315,378,447,512,577,662,786,932,1051,1097,1069,1014,989,1021,1098,1191,1280,1357,1422,1477,
-1524,1567,1607,1631,1632,1613,1596,1602,1629,1661,1685,1711,1759,1835,1924,2006,2079,2156,2247,2340,2411,
-2448,2464,2478,2503,2535,2570,2611,2663,2724,2787,2846,2901,2957,3017,3082,3153,3230,3303,3349,3346,3295,
-3224,3167,3125,3059,2929,2750,2592,2528,2565,2633,2654,2615,2583,2628,2752,2879,2927,2884,2808,2769,2791,
-2839,2868,2869,2870,2905,2978,3062,3125,3155,3169,3186,3214,3245,3265,3274,3275,3279,3292,3318,3352,3381,
-3393,3386,3373,3365,3362,3353,3337,3326,3333,3353,3368,3378,3402,3462,3545,3614,3649,3669,3715,3800,3892,
-3948,3959,3956,3972,4013,4058,4091,4112,4129,4141,4152,4171,4203,4242,4269,4283,4303,4347,4409,4455,4457,
-4419,4371,4340,4329,4329,4332,4336,4341,4343,4341,4337,4337,4342,4351,4364,4378,4390,4400,4413,4431,4449,
-4459,4466,4490,4544,4609,4640,4617,4566,4536,4535,4505,4370,4094,3708,3266,2815,2394,2065,1909,1973,2215,
-2522,2775,2928,3007,3058,3097,3107,3073,3009,2941,2885,2842,2812,2804,2814,2813,2759,2640,2495,2378,2313,
-2282,2251,2210,2173,2145,2113,2062,1998,1939,1892,1849,1800,1748,1702,1663,1620,1568,1518,1479,1443,1388,
-1312,1241,1207,1213,1229,1223,1187,1142,1106,1079,1047,1001,948,903,869,838,800,758,720,690,666,
-638,606,572,539,504,460,414,373,345,324,304,277,246,212,179,149,130,124,123,116,97,
-74,55,42,29,11,-6,-19,-30,-47,-71,-94,-110,-119,-129,-145,-160,-166,-163,-159,-161,-173,
--189,-208,-228,-249,-271,-291,-307,-323,-341,-367,-401,-441,-480,-514,-543,-569,-596,-624,-651,-676,-697,
--715,-732,-751,-772,-791,-804,-812,-818,-827,-838,-848,-854,-855,-854,-856,-862,-873,-888,-906,-920,-929,
--934,-939,-949,-961,-975,-989,-1007,-1028,-1049,-1065,-1076,-1087,-1101,-1117,-1132,-1147,-1163,-1178,-1189,-1195,-1202,
--1211,-1223,-1232,-1238,-1245,-1257,-1271,-1282,-1285,-1283,-1281,-1282,-1282,-1280,-1276,-1273,-1270,-1266,-1260,-1254,-1247,
--1240,-1232,-1223,-1213,-1203,-1192,-1183,-1176,-1172,-1167,-1160,-1150,-1139,-1131,-1126,-1123,-1124,-1126,-1128,-1124,-1115,
--1104,-1094,-1088,-1083,-1080,-1080,-1080,-1080,-1078,-1075,-1072,-1069,-1064,-1062,-1062,-1065,-1065,-1063,-1060,-1059,-1059,
--1057,-1051,-1047,-1044,-1040,-1032,-1021,-1014,-1010,-1006,-1000,-994,-992,-991,-986,-973,-958,-950,-947,-944,-935,
--924,-918,-916,-910,-900,-887,-879,-874,-869,-863,-857,-852,-849,-843,-837,-832,-827,-822,-815,-808,-802,
--796,-787,-776,-766,-759,-750,-740,-730,-721,-712,-702,-693,-687,-685,-681,-671,-658,-648,-641,-635,-624,
--612,-604,-598,-592,-583,-574,-568,-563,-555,-544,-533,-524,-516,-507,-499,-493,-488,-479,-465,-454,-451,
--450,-443,-426,-407,-392,-382,-373,-361,-348,-336,-320,-298,-273,-250,-232,-214,-193,-173,-156,-142,-127,
--109,-89,-71,-56,-41,-29,-25,-28,-31,-26,-11,5,17,22,27,36,48,59,69,76,82,
-89,98,111,127,144,159,173,189,210,235,262,287,309,329,352,379,407,431,451,470,493,
-522,555,594,637,680,712,725,729,739,767,807,847,883,918,956,993,1022,1049,1085,1131,1177,
-1212,1239,1270,1310,1354,1397,1443,1496,1546,1577,1587,1583,1560,1481,1330,1167,1122,1298,1679,2137,2546,
-2871,3143,3366,3488,3464,3324,3156,3015,2876,2696,2491,2343,2311,2371,2447,2485,2500,2528,2570,2592,2563,
-2503,2462,2480,2557,2657,2730,2739,2676,2566,2444,2336,2246,2171,2106,2051,2004,1959,1912,1867,1828,1793,
-1760,1731,1713,1708,1708,1704,1693,1681,1672,1661,1641,1610,1574,1541,1515,1496,1485,1479,1470,1453,1428,
-1403,1382,1363,1342,1320,1297,1272,1243,1208,1165,1113,1049,974,896,824,760,699,635,575,529,500,
-475,439,382,304,206,92,-25,-135,-230,-312,-386,-448,-493,-518,-532,-549,-576,-613,-657,-705,-752,
--789,-808,-810,-805,-802,-805,-809,-806,-794,-778,-769,-778,-809,-852,-889,-904,-895,-870,-841,-818,-804,
--793,-777,-748,-705,-654,-606,-569,-540,-512,-477,-431,-373,-304,-227,-148,-70,0,58,98,122,143,
-175,222,271,304,313,304,286,267,250,239,237,243,254,265,280,301,327,359,399,447,498,
-533,538,519,496,488,497,512,525,537,552,571,591,611,634,663,692,719,743,767,793,817,
-840,862,886,910,932,951,973,998,1024,1047,1065,1082,1100,1118,1135,1153,1173,1194,1214,1230,1245,
-1264,1286,1307,1325,1339,1353,1369,1384,1399,1413,1428,1443,1459,1473,1487,1502,1520,1540,1561,1580,1592,
-1598,1596,1590,1578,1562,1546,1535,1534,1537,1537,1532,1525,1522,1523,1523,1517,1509,1505,1508,1513,1513,
-1512,1515,1525,1536,1543,1547,1552,1565,1582,1599,1612,1624,1642,1663,1685,1706,1730,1756,1782,1804,1820,
-1832,1845,1861,1878,1896,1914,1937,1973,2020,2071,2107,2113,2094,2011,2001,2032,2079,2105,2099,2094,2136,
-2237,2354,2421,2403,2324,2243,2212,2236,2282,2312,2309,2287,2268,2266,2274,2281,2289,2304,2330,2357,2371,
-2373,2379,2403,2442,2476,2491,2492,2496,2514,2539,2556,2560,2554,2548,2548,2555,2571,2597,2631,2665,2693,
-2713,2731,2751,2778,2806,2831,2845,2846,2841,2846,2880,2944,3023,3084,3107,3092,3062,3047,3061,3101,3150,
-3188,3204,3200,3190,3196,3238,3317,3416,3508,3566,3584,3572,3551,3537,3540,3553,3569,3577,3575,3559,3535,
-3508,3489,3483,3489,3498,3497,3482,3457,3433,3424,3436,3464,3496,3520,3530,3535,3543,3555,3556,3523,3449,
-3349,3253,3188,3156,3142,3120,3068,2974,2842,2694,2564,2475,2422,2381,2331,2274,2231,2217,2229,2249,2264,
-2271,2275,2279,2282,2282,2278,2274,2271,2267,2251,2208,2126,2014,1895,1796,1729,1688,1659,1636,1620,1617,
-1624,1636,1648,1657,1663,1667,1672,1682,1696,1716,1743,1777,1811,1842,1875,1930,2022,2141,2248,2308,2321,
-2316,2319,2331,2336,2327,2313,2303,2293,2271,2236,2198,2165,2131,2089,2039,1990,1949,1914,1880,1851,1832,
-1820,1808,1796,1787,1784,1783,1779,1773,1769,1763,1748,1723,1703,1704,1727,1759,1785,1801,1812,1824,1841,
-1861,1878,1883,1878,1870,1872,1881,1882,1866,1849,1859,1897,1940,1956,1946,1932,1924,1911,1884,1856,1850,
-1859,1842,1768,1660,1571,1534,1530,1519,1489,1456,1439,1427,1407,1378,1360,1360,1364,1356,1338,1322,1312,
-1302,1284,1262,1246,1233,1217,1195,1173,1155,1138,1116,1088,1059,1034,1010,984,959,937,913,883,847,
-814,789,766,738,703,669,640,612,583,552,524,500,475,446,416,390,368,345,320,293,265,
-236,205,174,141,103,60,15,-25,-63,-104,-156,-214,-271,-322,-373,-427,-483,-531,-572,-614,-664,
--719,-770,-813,-852,-893,-935,-975,-1014,-1055,-1100,-1139,-1172,-1204,-1249,-1307,-1364,-1408,-1437,-1467,-1509,-1561,
--1614,-1658,-1685,-1690,-1677,-1656,-1646,-1661,-1706,-1776,-1864,-1957,-2044,-2113,-2165,-2212,-2268,-2331,-2392,-2446,-2499,
--2559,-2623,-2679,-2721,-2759,-2805,-2851,-2879,-2876,-2854,-2839,-2845,-2865,-2885,-2900,-2919,-2955,-3009,-3077,-3143,-3202,
--3251,-3297,-3345,-3388,-3415,-3423,-3426,-3440,-3472,-3512,-3544,-3567,-3594,-3635,-3683,-3716,-3720,-3701,-3681,-3686,-3726,
--3788,-3844,-3877,-3894,-3915,-3948,-3974,-3975,-3958,-3953,-3979,-4013,-4018,-3989,-3962,-3973,-4015,-4046,-4044,-4026,-4022,
--4038,-4052,-4050,-4039,-4035,-4036,-4030,-4016,-4005,-4004,-4002,-3988,-3969,-3957,-3953,-3945,-3926,-3907,-3897,-3888,-3865,
--3831,-3804,-3792,-3777,-3736,-3675,-3615,-3558,-3479,-3367,-3266,-3239,-3288,-3327,-3259,-3071,-2853,-2709,-2665,-2666,-2652,
--2613,-2579,-2565,-2559,-2540,-2512,-2490,-2485,-2484,-2472,-2449,-2426,-2413,-2410,-2410,-2402,-2386,-2373,-2377,-2401,-2435,
--2455,-2444,-2400,-2338,-2272,-2213,-2166,-2132,-2109,-2092,-2076,-2062,-2050,-2032,-1999,-1950,-1904,-1888,-1915,-1970,-2019,
--2034,-2008,-1954,-1889,-1826,-1771,-1727,-1694,-1663,-1622,-1560,-1469,-1352,-1223,-1104,-1014,-962,-940,-927,-904,-863,
--810,-753,-698,-638,-561,-465,-360,-260,-170,-85,3,89,162,219,272,332,397,454,506,581,704,
-856,982,1029,999,948,937,986,1069,1156,1235,1309,1379,1435,1473,1500,1525,1544,1544,1522,1500,1499,
-1527,1567,1604,1639,1690,1766,1857,1948,2033,2117,2206,2290,2354,2393,2414,2431,2452,2484,2526,2580,2643,
-2708,2770,2829,2889,2948,3005,3062,3128,3205,3281,3326,3318,3263,3193,3137,3089,3010,2868,2684,2528,2464,
-2496,2559,2583,2553,2520,2536,2605,2677,2702,2680,2656,2673,2727,2780,2801,2796,2805,2863,2964,3069,3134,
-3148,3135,3129,3146,3177,3204,3217,3220,3224,3234,3256,3285,3311,3324,3321,3311,3304,3300,3293,3279,3272,
-3282,3300,3308,3305,3319,3383,3490,3592,3647,3661,3682,3742,3824,3886,3904,3899,3905,3935,3977,4014,4039,
-4056,4071,4087,4113,4150,4190,4218,4233,4257,4303,4361,4399,4394,4356,4313,4288,4280,4282,4287,4297,4309,
-4316,4313,4306,4303,4307,4318,4333,4345,4355,4365,4381,4404,4425,4435,4442,4468,4522,4580,4599,4566,4516,
-4494,4496,4448,4270,3935,3489,3005,2548,2170,1933,1893,2050,2327,2607,2808,2925,2996,3051,3084,3081,3043,
-2990,2932,2863,2783,2719,2709,2755,2802,2779,2661,2494,2351,2270,2234,2206,2170,2135,2109,2081,2036,1975,
-1915,1868,1826,1778,1725,1675,1635,1597,1557,1514,1472,1429,1372,1302,1237,1200,1197,1206,1200,1170,1129,
-1092,1063,1028,982,932,891,863,839,808,767,728,696,671,645,613,581,548,512,468,421,378,
-345,319,297,275,252,224,188,149,121,112,114,111,95,74,57,46,33,17,1,-7,-15,
--32,-62,-93,-116,-130,-141,-157,-173,-182,-185,-186,-191,-200,-211,-224,-241,-264,-287,-308,-324,-337,
--353,-376,-408,-446,-485,-519,-548,-573,-599,-627,-654,-680,-704,-724,-743,-763,-784,-802,-816,-824,-831,
--840,-853,-866,-875,-880,-883,-885,-889,-894,-903,-916,-931,-942,-951,-958,-966,-975,-984,-995,-1010,-1030,
--1050,-1066,-1077,-1087,-1097,-1108,-1121,-1136,-1152,-1167,-1175,-1180,-1185,-1196,-1207,-1215,-1220,-1228,-1242,-1257,-1265,
--1266,-1264,-1264,-1267,-1266,-1262,-1258,-1254,-1250,-1244,-1238,-1234,-1232,-1230,-1223,-1211,-1198,-1185,-1174,-1167,-1165,
--1166,-1165,-1161,-1153,-1144,-1135,-1127,-1120,-1119,-1122,-1125,-1124,-1116,-1105,-1096,-1091,-1088,-1087,-1085,-1084,-1081,
--1078,-1076,-1076,-1075,-1072,-1069,-1068,-1069,-1071,-1069,-1067,-1066,-1066,-1066,-1063,-1060,-1057,-1053,-1045,-1036,-1029,
--1025,-1020,-1012,-1004,-1001,-1001,-997,-987,-973,-964,-959,-954,-945,-935,-929,-925,-917,-905,-893,-885,-881,
--876,-871,-866,-864,-861,-857,-852,-848,-846,-841,-834,-826,-818,-810,-800,-790,-784,-778,-770,-758,-744,
--732,-721,-710,-700,-694,-694,-692,-683,-670,-660,-653,-646,-635,-624,-617,-613,-607,-596,-584,-576,-573,
--567,-556,-543,-532,-525,-517,-511,-508,-505,-498,-487,-476,-470,-466,-459,-444,-428,-414,-404,-394,-381,
--368,-356,-339,-317,-291,-269,-251,-234,-215,-195,-177,-162,-143,-121,-99,-82,-69,-56,-45,-40,-44,
--50,-47,-34,-16,-1,6,11,18,28,39,51,61,68,74,83,97,114,127,137,148,168,
-196,227,254,275,293,314,340,367,393,416,437,460,487,517,550,587,629,669,698,712,721,
-739,772,814,854,890,926,962,995,1021,1049,1089,1140,1190,1228,1259,1295,1341,1385,1425,1466,1514,
-1561,1591,1602,1601,1575,1488,1324,1152,1103,1280,1659,2112,2522,2858,3148,3384,3505,3464,3301,3116,2973,
-2850,2696,2517,2383,2355,2415,2493,2537,2555,2577,2607,2614,2578,2521,2495,2537,2637,2742,2790,2754,2652,
-2528,2421,2336,2261,2184,2109,2047,1998,1952,1905,1862,1828,1799,1768,1736,1713,1705,1704,1699,1688,1676,
-1669,1664,1654,1638,1619,1598,1573,1549,1529,1515,1502,1485,1462,1440,1419,1397,1372,1345,1319,1295,1268,
-1233,1188,1132,1062,983,902,828,762,699,636,584,554,541,524,476,385,259,117,-20,-136,-226,
--293,-350,-403,-450,-481,-494,-498,-507,-528,-562,-606,-657,-711,-758,-790,-807,-814,-819,-822,-821,-811,
--792,-770,-755,-761,-791,-834,-871,-885,-869,-836,-801,-776,-766,-764,-761,-745,-712,-668,-624,-587,-556,
--529,-502,-469,-423,-361,-283,-198,-113,-36,28,78,110,131,153,182,218,253,282,302,310,302,
-282,262,251,254,262,270,282,300,327,362,404,455,506,541,546,527,506,501,512,525,536,
-547,567,591,616,639,666,699,732,759,779,799,823,850,876,902,928,954,977,997,1017,1040,
-1064,1086,1103,1119,1136,1155,1174,1194,1214,1235,1252,1267,1282,1301,1322,1341,1355,1367,1381,1397,1414,
-1430,1443,1457,1473,1490,1506,1521,1534,1547,1563,1583,1601,1612,1614,1609,1601,1590,1574,1555,1541,1539,
-1545,1548,1543,1534,1528,1527,1526,1519,1511,1508,1513,1518,1520,1522,1527,1536,1542,1544,1547,1558,1577,
-1594,1605,1611,1620,1635,1655,1674,1694,1720,1751,1781,1807,1826,1841,1855,1870,1883,1898,1917,1948,1991,
-2040,2075,2078,2049,2011,1955,1982,2048,2108,2119,2094,2094,2169,2301,2413,2432,2356,2250,2187,2195,2247,
-2296,2313,2299,2278,2266,2268,2275,2279,2283,2298,2323,2349,2361,2361,2368,2397,2444,2483,2495,2486,2480,
-2491,2514,2534,2541,2539,2535,2537,2547,2568,2599,2635,2667,2688,2703,2716,2733,2752,2774,2800,2826,2846,
-2855,2863,2884,2929,2995,3059,3099,3100,3071,3038,3033,3067,3129,3189,3220,3218,3203,3204,3242,3317,3416,
-3517,3596,3639,3643,3622,3595,3579,3578,3590,3603,3609,3597,3567,3532,3508,3504,3514,3525,3525,3511,3487,
-3455,3426,3414,3426,3458,3486,3494,3482,3465,3450,3428,3380,3306,3224,3162,3132,3122,3109,3074,3003,2895,
-2763,2631,2527,2462,2423,2389,2345,2298,2264,2251,2257,2272,2286,2298,2309,2321,2333,2340,2341,2335,2330,
-2326,2315,2279,2203,2093,1973,1870,1796,1746,1711,1687,1675,1673,1679,1690,1705,1718,1725,1729,1736,1752,
-1779,1809,1839,1869,1899,1930,1971,2036,2132,2244,2336,2385,2395,2395,2405,2418,2421,2410,2395,2385,2372,
-2345,2304,2260,2220,2182,2144,2108,2078,2052,2023,1990,1957,1933,1916,1900,1884,1872,1865,1862,1858,1854,
-1850,1840,1820,1795,1779,1786,1812,1843,1865,1875,1881,1890,1907,1929,1947,1950,1940,1935,1950,1974,1980,
-1957,1926,1924,1956,1991,1995,1977,1969,1985,1996,1973,1927,1895,1887,1867,1798,1689,1595,1556,1560,1562,
-1539,1507,1485,1472,1454,1430,1412,1408,1411,1405,1391,1376,1364,1351,1332,1311,1294,1281,1264,1241,1219,
-1202,1184,1159,1129,1100,1077,1056,1034,1009,983,956,925,892,862,836,811,782,749,718,691,664,
-635,605,577,550,520,488,460,438,422,401,374,344,314,286,257,225,192,156,116,75,36,
--2,-46,-97,-153,-206,-254,-304,-359,-415,-463,-504,-546,-597,-654,-704,-745,-781,-819,-860,-902,-944,
--989,-1032,-1067,-1097,-1131,-1182,-1244,-1303,-1344,-1374,-1407,-1453,-1505,-1552,-1586,-1606,-1613,-1608,-1599,-1598,-1620,
--1669,-1741,-1827,-1917,-1998,-2064,-2116,-2164,-2221,-2284,-2345,-2398,-2450,-2510,-2575,-2633,-2680,-2720,-2761,-2801,-2829,
--2839,-2841,-2849,-2871,-2899,-2921,-2928,-2921,-2913,-2919,-2953,-3014,-3087,-3159,-3223,-3283,-3335,-3372,-3386,-3387,-3397,
--3428,-3471,-3511,-3540,-3567,-3603,-3646,-3679,-3690,-3677,-3653,-3644,-3669,-3730,-3806,-3872,-3916,-3949,-3981,-4004,-4006,
--3989,-3980,-4000,-4036,-4056,-4044,-4023,-4022,-4044,-4061,-4055,-4036,-4028,-4039,-4053,-4057,-4055,-4055,-4053,-4041,-4021,
--4005,-3999,-3992,-3976,-3955,-3943,-3939,-3933,-3919,-3908,-3908,-3909,-3890,-3852,-3819,-3806,-3797,-3765,-3704,-3635,-3572,
--3502,-3420,-3352,-3340,-3379,-3398,-3315,-3124,-2907,-2759,-2708,-2706,-2697,-2668,-2637,-2618,-2601,-2573,-2538,-2511,-2499,
--2492,-2481,-2467,-2459,-2462,-2467,-2465,-2453,-2440,-2440,-2460,-2491,-2511,-2496,-2444,-2378,-2328,-2305,-2295,-2277,-2237,
--2185,-2137,-2104,-2087,-2073,-2047,-2002,-1946,-1903,-1896,-1928,-1979,-2019,-2028,-2007,-1965,-1913,-1858,-1805,-1762,-1730,
--1703,-1667,-1606,-1513,-1391,-1258,-1143,-1071,-1047,-1054,-1063,-1049,-1006,-940,-865,-789,-709,-617,-510,-396,-285,
--186,-95,-9,69,133,183,233,291,351,400,443,511,630,783,912,964,944,907,912,969,1046,
-1117,1183,1258,1337,1398,1427,1434,1440,1450,1450,1431,1406,1401,1429,1477,1529,1581,1644,1726,1824,1923,
-2015,2096,2168,2230,2282,2325,2360,2388,2411,2439,2482,2542,2610,2675,2736,2803,2876,2945,3002,3050,3107,
-3178,3244,3272,3248,3189,3132,3093,3050,2959,2800,2607,2451,2387,2412,2470,2500,2487,2459,2454,2475,2501,
-2509,2512,2537,2599,2676,2726,2733,2720,2738,2818,2944,3062,3123,3121,3090,3073,3086,3116,3142,3155,3161,
-3168,3180,3195,3215,3236,3251,3253,3247,3240,3235,3227,3215,3211,3224,3244,3251,3243,3253,3321,3446,3576,
-3652,3665,3663,3695,3761,3820,3840,3832,3828,3850,3892,3934,3965,3986,4004,4026,4058,4098,4134,4159,4177,
-4207,4258,4315,4349,4343,4310,4275,4254,4244,4238,4239,4250,4268,4281,4281,4274,4271,4277,4290,4304,4317,
-4328,4339,4356,4376,4393,4402,4413,4442,4494,4542,4550,4514,4470,4451,4439,4357,4130,3743,3255,2752,2310,
-1993,1858,1927,2157,2444,2683,2831,2915,2980,3037,3064,3047,3004,2960,2916,2850,2755,2665,2629,2660,2709,
-2701,2604,2450,2309,2222,2183,2160,2131,2099,2071,2043,2005,1954,1901,1853,1810,1763,1709,1656,1612,1578,
-1544,1506,1462,1410,1350,1285,1228,1194,1185,1188,1180,1154,1115,1077,1044,1008,966,921,885,862,843,
-816,777,736,700,671,644,616,586,553,516,472,426,385,350,319,292,272,255,234,199,155,
-120,105,106,105,93,73,58,48,37,22,10,4,-2,-20,-52,-88,-116,-135,-151,-170,-188,
--201,-209,-216,-225,-233,-240,-246,-258,-276,-297,-315,-330,-342,-357,-381,-415,-454,-492,-524,-551,-577,
--604,-632,-659,-686,-713,-738,-761,-780,-797,-814,-827,-838,-848,-858,-871,-884,-894,-902,-908,-914,-918,
--922,-926,-935,-946,-957,-967,-976,-985,-992,-997,-1003,-1013,-1029,-1047,-1062,-1073,-1081,-1087,-1095,-1105,-1119,
--1136,-1149,-1156,-1161,-1169,-1182,-1194,-1201,-1206,-1215,-1230,-1244,-1249,-1247,-1246,-1248,-1251,-1250,-1247,-1244,-1242,
--1237,-1228,-1220,-1218,-1220,-1219,-1211,-1196,-1182,-1171,-1164,-1160,-1158,-1157,-1155,-1150,-1145,-1141,-1136,-1130,-1122,
--1117,-1115,-1116,-1114,-1106,-1098,-1091,-1089,-1089,-1089,-1089,-1087,-1083,-1078,-1077,-1080,-1083,-1081,-1077,-1074,-1075,
--1077,-1076,-1073,-1070,-1069,-1069,-1066,-1062,-1060,-1057,-1052,-1046,-1041,-1037,-1033,-1025,-1017,-1012,-1009,-1005,-997,
--988,-980,-974,-966,-957,-948,-942,-936,-925,-911,-899,-893,-889,-884,-879,-876,-875,-873,-869,-864,-862,
--862,-859,-852,-843,-834,-824,-813,-804,-798,-794,-787,-775,-761,-750,-740,-729,-717,-710,-708,-706,-699,
--686,-674,-666,-657,-646,-635,-628,-626,-620,-609,-596,-589,-586,-581,-570,-556,-545,-539,-534,-528,-525,
--523,-519,-510,-499,-489,-481,-472,-460,-448,-438,-430,-419,-406,-391,-377,-360,-337,-312,-291,-274,-257,
--237,-215,-196,-179,-160,-136,-112,-94,-81,-70,-60,-56,-59,-64,-62,-50,-34,-22,-14,-8,-1,
-7,17,29,41,51,60,70,83,97,107,115,128,153,185,216,239,257,277,301,328,353,
-375,397,424,455,487,519,552,587,624,659,687,706,724,750,786,827,865,900,934,968,1000,
-1029,1065,1113,1167,1214,1249,1280,1318,1364,1407,1444,1482,1527,1570,1597,1607,1606,1578,1482,1308,1125,
-1068,1233,1595,2035,2445,2798,3110,3364,3490,3444,3275,3088,2946,2827,2679,2503,2367,2331,2387,2468,2522,
-2551,2579,2613,2625,2594,2538,2512,2557,2664,2769,2802,2738,2612,2486,2397,2337,2274,2193,2108,2040,1993,
-1953,1910,1867,1832,1803,1772,1738,1712,1700,1697,1693,1685,1676,1670,1668,1664,1659,1652,1641,1622,1597,
-1574,1554,1536,1515,1492,1471,1451,1427,1394,1358,1326,1299,1272,1235,1185,1122,1049,972,896,823,753,
-684,621,580,568,571,554,487,363,203,42,-91,-186,-247,-290,-330,-373,-413,-437,-446,-450,-460,
--484,-517,-557,-604,-655,-705,-747,-778,-798,-811,-817,-816,-804,-785,-763,-749,-752,-776,-813,-844,-853,
--836,-803,-768,-746,-742,-750,-755,-745,-719,-682,-645,-612,-582,-555,-530,-503,-463,-402,-322,-234,-153,
--83,-24,27,69,98,117,132,149,173,206,242,270,280,272,258,254,263,278,289,299,314,
-336,368,410,461,514,550,557,539,519,514,525,539,552,567,590,619,647,674,706,743,778,
-802,817,832,856,886,915,943,969,997,1022,1042,1059,1078,1100,1122,1141,1157,1174,1192,1212,1233,
-1255,1275,1292,1307,1323,1341,1360,1374,1385,1396,1410,1427,1444,1459,1473,1488,1505,1524,1543,1558,1568,
-1578,1591,1608,1624,1631,1627,1617,1608,1599,1584,1565,1550,1546,1551,1555,1550,1540,1532,1531,1531,1527,
-1522,1522,1527,1533,1535,1537,1541,1544,1542,1538,1542,1557,1577,1591,1596,1599,1611,1632,1653,1671,1690,
-1719,1755,1791,1820,1838,1849,1859,1872,1892,1918,1948,1978,2009,2033,2039,2017,1977,1955,1954,2004,2073,
-2113,2097,2061,2077,2180,2320,2404,2377,2274,2181,2160,2205,2266,2301,2302,2286,2271,2264,2265,2269,2273,
-2279,2292,2316,2339,2351,2353,2361,2391,2436,2472,2480,2468,2458,2467,2489,2510,2520,2522,2523,2528,2541,
-2567,2603,2638,2663,2677,2689,2703,2719,2732,2745,2766,2799,2834,2860,2873,2886,2914,2964,3029,3085,3111,
-3094,3053,3025,3042,3104,3180,3233,3249,3245,3248,3273,3323,3394,3481,3571,3644,3684,3686,3663,3633,3614,
-3609,3615,3617,3600,3561,3516,3485,3480,3491,3500,3499,3489,3471,3442,3404,3375,3374,3402,3433,3440,3415,
-3376,3336,3294,3241,3179,3128,3104,3102,3099,3071,3009,2917,2803,2683,2576,2496,2445,2410,2375,2337,2304,
-2283,2277,2280,2291,2307,2325,2343,2364,2387,2410,2424,2426,2420,2412,2397,2357,2279,2167,2046,1940,1860,
-1804,1766,1744,1735,1734,1739,1750,1765,1779,1787,1791,1804,1831,1869,1906,1938,1965,1994,2024,2064,2125,
-2215,2321,2413,2470,2492,2500,2508,2513,2508,2493,2479,2468,2451,2419,2375,2330,2290,2257,2228,2205,2187,
-2167,2138,2102,2068,2042,2023,2004,1986,1973,1964,1956,1946,1937,1929,1917,1898,1875,1863,1870,1893,1918,
-1936,1946,1952,1960,1976,1998,2017,2021,2015,2019,2048,2084,2089,2051,2002,1990,2020,2052,2047,2020,2014,
-2044,2069,2043,1972,1907,1880,1863,1809,1714,1628,1594,1604,1614,1596,1562,1535,1520,1505,1483,1465,1459,
-1459,1454,1441,1425,1412,1397,1377,1356,1341,1329,1313,1291,1267,1246,1227,1202,1174,1149,1129,1110,1086,
-1057,1027,997,968,939,910,883,855,823,792,765,741,716,688,658,628,599,565,530,502,484,
-470,450,421,389,361,336,307,274,240,207,173,136,96,54,9,-40,-92,-142,-190,-239,-293,
--346,-393,-435,-480,-531,-586,-635,-675,-711,-748,-787,-829,-874,-921,-966,-1002,-1031,-1065,-1117,-1180,-1238,
--1280,-1312,-1350,-1399,-1451,-1491,-1516,-1530,-1535,-1536,-1538,-1550,-1584,-1642,-1716,-1797,-1875,-1946,-2004,-2055,-2106,
--2164,-2226,-2283,-2334,-2383,-2436,-2491,-2541,-2582,-2615,-2647,-2679,-2708,-2737,-2769,-2809,-2855,-2901,-2939,-2958,-2951,
--2922,-2895,-2895,-2932,-2995,-3059,-3115,-3168,-3222,-3267,-3291,-3301,-3317,-3353,-3402,-3443,-3468,-3487,-3516,-3559,-3604,
--3633,-3637,-3618,-3599,-3608,-3665,-3758,-3855,-3930,-3978,-4012,-4035,-4039,-4024,-4011,-4024,-4060,-4089,-4089,-4067,-4050,
--4052,-4061,-4060,-4051,-4044,-4047,-4053,-4058,-4061,-4066,-4066,-4052,-4029,-4009,-3996,-3982,-3961,-3939,-3928,-3926,-3922,
--3911,-3904,-3910,-3918,-3905,-3871,-3836,-3819,-3811,-3785,-3729,-3659,-3591,-3527,-3463,-3418,-3418,-3448,-3446,-3348,-3154,
--2939,-2788,-2727,-2718,-2712,-2691,-2666,-2645,-2624,-2596,-2566,-2544,-2529,-2515,-2501,-2498,-2509,-2527,-2536,-2526,-2507,
--2498,-2513,-2546,-2573,-2562,-2501,-2411,-2335,-2310,-2332,-2363,-2361,-2312,-2237,-2170,-2127,-2104,-2082,-2046,-1996,-1945,
--1913,-1913,-1942,-1982,-2011,-2018,-2006,-1981,-1946,-1903,-1855,-1810,-1773,-1742,-1706,-1649,-1558,-1435,-1301,-1192,-1137,
--1137,-1166,-1188,-1178,-1133,-1065,-985,-897,-801,-692,-572,-444,-318,-204,-103,-17,54,110,155,200,253,
-307,352,394,463,579,726,849,904,897,882,905,966,1035,1091,1146,1219,1300,1358,1373,1360,1348,
-1348,1348,1331,1308,1304,1334,1390,1455,1524,1602,1694,1797,1900,1990,2062,2113,2153,2194,2246,2302,2347,
-2376,2401,2443,2505,2574,2635,2692,2758,2834,2902,2950,2987,3035,3100,3152,3159,3117,3060,3024,3006,2966,
-2858,2683,2490,2349,2298,2325,2380,2415,2415,2399,2392,2398,2409,2415,2430,2473,2545,2621,2664,2662,2645,
-2666,2752,2879,2992,3044,3037,3010,3005,3030,3063,3084,3093,3101,3114,3129,3140,3153,3170,3188,3195,3191,
-3180,3171,3162,3154,3155,3173,3199,3211,3205,3213,3281,3413,3557,3645,3657,3636,3641,3690,3746,3770,3762,
-3754,3772,3816,3866,3905,3931,3952,3977,4009,4044,4073,4093,4114,4152,4209,4267,4298,4293,4267,4241,4224,
-4211,4199,4194,4202,4219,4233,4239,4241,4248,4260,4273,4284,4295,4306,4319,4333,4347,4358,4370,4389,4423,
-4468,4500,4498,4466,4432,4413,4376,4247,3967,3537,3026,2524,2115,1868,1823,1975,2248,2529,2730,2840,2905,
-2966,3022,3044,3019,2970,2927,2890,2835,2745,2644,2575,2560,2576,2571,2507,2393,2271,2182,2135,2114,2094,
-2065,2032,2000,1968,1931,1887,1840,1793,1744,1693,1641,1595,1558,1526,1490,1445,1388,1325,1265,1216,1186,
-1175,1171,1161,1136,1099,1060,1027,995,959,919,884,859,839,814,780,739,699,664,635,610,586,
-557,520,476,432,392,357,323,293,272,259,242,209,164,125,107,106,105,93,75,60,49,
-38,26,17,12,4,-15,-48,-83,-111,-132,-153,-176,-197,-212,-223,-236,-249,-260,-267,-273,-282,
--295,-310,-322,-331,-340,-355,-380,-417,-459,-498,-530,-556,-582,-610,-637,-663,-688,-717,-746,-773,-795,
--812,-827,-841,-854,-865,-877,-890,-902,-912,-920,-927,-934,-939,-944,-948,-955,-962,-970,-977,-986,-996,
--1004,-1009,-1012,-1019,-1031,-1046,-1058,-1068,-1074,-1080,-1087,-1097,-1111,-1126,-1139,-1147,-1154,-1165,-1180,-1192,-1199,
--1204,-1213,-1227,-1238,-1240,-1237,-1236,-1239,-1242,-1241,-1238,-1237,-1237,-1232,-1221,-1210,-1207,-1209,-1206,-1196,-1183,
--1176,-1174,-1173,-1169,-1161,-1152,-1143,-1135,-1131,-1130,-1130,-1127,-1119,-1111,-1105,-1102,-1097,-1090,-1083,-1080,-1080,
--1082,-1085,-1088,-1088,-1085,-1080,-1078,-1082,-1087,-1089,-1085,-1080,-1080,-1082,-1081,-1077,-1074,-1072,-1070,-1067,-1062,
--1059,-1058,-1057,-1054,-1049,-1045,-1042,-1037,-1030,-1023,-1017,-1011,-1005,-1000,-995,-987,-977,-967,-960,-956,-949,
--936,-921,-910,-904,-899,-893,-887,-885,-885,-884,-880,-874,-872,-872,-868,-861,-852,-845,-837,-826,-816,
--808,-802,-795,-786,-776,-769,-763,-754,-741,-730,-725,-721,-713,-701,-689,-681,-673,-662,-651,-644,-641,
--635,-624,-613,-607,-605,-600,-588,-575,-565,-560,-556,-549,-544,-542,-539,-533,-522,-510,-498,-488,-477,
--467,-459,-451,-440,-426,-411,-397,-380,-358,-334,-313,-296,-278,-256,-233,-214,-196,-177,-154,-131,-113,
--100,-89,-81,-78,-80,-81,-76,-64,-51,-42,-36,-29,-20,-11,-3,6,17,29,40,51,64,
-76,87,98,117,145,178,205,224,242,266,296,324,345,364,389,420,455,489,521,553,585,
-616,644,669,693,719,750,788,827,865,900,934,968,1002,1039,1085,1138,1191,1233,1263,1291,1327,
-1368,1407,1441,1479,1522,1560,1584,1594,1594,1563,1462,1281,1094,1030,1178,1518,1941,2348,2709,3031,3290,
-3423,3393,3247,3076,2936,2803,2634,2438,2284,2232,2274,2350,2412,2456,2507,2568,2608,2595,2542,2504,2534,
-2630,2731,2762,2697,2574,2459,2385,2337,2274,2186,2095,2028,1989,1957,1916,1870,1830,1797,1766,1733,1705,
-1690,1686,1686,1685,1684,1685,1686,1685,1681,1673,1662,1645,1626,1607,1589,1566,1537,1508,1486,1467,1441,
-1403,1358,1319,1289,1260,1219,1163,1095,1025,955,888,817,740,661,599,572,578,590,565,474,324,
-153,0,-110,-178,-220,-254,-292,-334,-369,-390,-401,-411,-431,-460,-492,-524,-560,-604,-653,-700,-739,
--767,-785,-794,-795,-787,-772,-754,-741,-742,-760,-788,-812,-822,-811,-786,-759,-741,-739,-748,-753,-744,
--720,-690,-664,-640,-613,-581,-548,-514,-470,-405,-324,-242,-175,-127,-86,-44,0,39,66,81,90,
-102,125,160,197,224,236,240,250,268,288,304,317,331,352,378,413,458,508,546,560,550,
-535,533,544,561,579,600,627,656,684,712,745,783,817,838,849,864,889,921,952,980,1007,
-1037,1064,1084,1098,1114,1135,1158,1180,1197,1212,1228,1247,1269,1291,1311,1328,1344,1361,1381,1398,1410,
-1420,1431,1445,1462,1477,1489,1503,1519,1539,1559,1577,1590,1598,1604,1614,1627,1639,1641,1632,1620,1613,
-1610,1602,1585,1569,1560,1561,1562,1556,1546,1540,1541,1542,1541,1538,1538,1541,1543,1542,1541,1542,1540,
-1534,1529,1536,1553,1572,1581,1585,1594,1617,1644,1665,1681,1702,1738,1784,1825,1851,1859,1854,1849,1859,
-1890,1938,1981,2004,2004,1992,1976,1957,1943,1954,2004,2042,2072,2068,2030,2005,2050,2169,2292,2330,2265,
-2163,2113,2146,2220,2277,2293,2285,2275,2268,2262,2257,2258,2266,2276,2289,2306,2326,2340,2346,2354,2376,
-2408,2434,2440,2432,2430,2443,2466,2485,2496,2503,2509,2519,2537,2565,2601,2634,2653,2662,2673,2692,2710,
-2720,2724,2738,2767,2804,2836,2853,2863,2880,2917,2978,3050,3104,3116,3085,3044,3038,3083,3156,3220,3256,
-3271,3285,3301,3320,3349,3404,3492,3595,3679,3719,3711,3674,3631,3600,3585,3575,3550,3504,3452,3416,3406,
-3410,3410,3404,3399,3398,3389,3363,3334,3325,3344,3373,3379,3353,3306,3254,3203,3149,3101,3076,3077,3086,
-3073,3020,2933,2828,2718,2616,2531,2469,2426,2391,2357,2328,2311,2303,2302,2304,2312,2330,2356,2384,2416,
-2454,2494,2524,2533,2523,2504,2473,2420,2332,2217,2097,1995,1917,1861,1824,1803,1796,1798,1803,1814,1828,
-1840,1846,1854,1875,1912,1956,1995,2026,2055,2085,2112,2140,2186,2265,2375,2487,2571,2616,2632,2633,2623,
-2606,2587,2571,2555,2532,2496,2452,2410,2373,2343,2319,2301,2284,2262,2230,2194,2165,2144,2127,2108,2091,
-2079,2070,2058,2040,2023,2011,1999,1981,1960,1949,1954,1971,1991,2008,2021,2031,2041,2056,2078,2098,2105,
-2102,2112,2147,2187,2187,2137,2078,2067,2108,2148,2139,2095,2071,2090,2110,2076,1987,1903,1866,1854,1817,
-1742,1669,1641,1655,1666,1647,1611,1583,1570,1558,1541,1524,1517,1514,1505,1488,1469,1454,1439,1421,1402,
-1388,1377,1363,1340,1314,1291,1271,1249,1225,1202,1182,1160,1133,1102,1070,1042,1014,985,955,926,895,
-864,835,812,791,767,738,707,676,645,610,575,548,530,516,494,465,435,410,386,358,324,
-291,262,232,197,154,109,64,19,-27,-77,-128,-178,-229,-277,-323,-368,-415,-466,-517,-563,-603,
--641,-678,-716,-756,-802,-853,-903,-943,-972,-1005,-1053,-1114,-1172,-1218,-1255,-1297,-1344,-1391,-1425,-1445,-1455,
--1460,-1463,-1470,-1492,-1537,-1605,-1683,-1762,-1833,-1895,-1950,-2001,-2054,-2113,-2173,-2228,-2277,-2324,-2370,-2417,-2460,
--2498,-2532,-2563,-2591,-2621,-2659,-2707,-2761,-2813,-2863,-2913,-2954,-2972,-2963,-2940,-2930,-2947,-2980,-3010,-3033,-3065,
--3112,-3163,-3201,-3223,-3249,-3291,-3340,-3375,-3388,-3394,-3417,-3462,-3519,-3566,-3588,-3582,-3565,-3570,-3622,-3719,-3829,
--3919,-3979,-4019,-4050,-4065,-4058,-4043,-4045,-4071,-4100,-4104,-4079,-4047,-4032,-4038,-4051,-4060,-4062,-4062,-4061,-4060,
--4062,-4067,-4065,-4052,-4030,-4010,-3995,-3977,-3953,-3930,-3919,-3920,-3918,-3909,-3902,-3907,-3916,-3911,-3885,-3855,-3838,
--3828,-3802,-3751,-3682,-3610,-3541,-3481,-3447,-3452,-3474,-3454,-3339,-3141,-2931,-2784,-2721,-2708,-2702,-2686,-2667,-2651,
--2634,-2616,-2601,-2590,-2578,-2560,-2543,-2545,-2568,-2595,-2603,-2588,-2568,-2568,-2593,-2626,-2633,-2585,-2488,-2380,-2314,
--2316,-2369,-2417,-2412,-2349,-2259,-2182,-2135,-2107,-2080,-2043,-1998,-1957,-1933,-1933,-1953,-1982,-2004,-2013,-2010,-1996,
--1975,-1943,-1902,-1856,-1811,-1772,-1734,-1682,-1600,-1482,-1351,-1249,-1207,-1224,-1264,-1286,-1271,-1226,-1165,-1092,-1003,
--895,-770,-636,-500,-368,-245,-138,-49,22,78,125,171,218,265,308,358,434,550,686,799,855,
-864,869,906,968,1030,1077,1126,1191,1260,1299,1295,1265,1243,1239,1236,1223,1207,1213,1252,1315,1387,
-1465,1551,1650,1753,1853,1939,2002,2041,2068,2104,2165,2240,2304,2343,2370,2412,2475,2542,2598,2648,2705,
-2769,2822,2853,2876,2915,2970,3009,3002,2957,2916,2904,2898,2845,2712,2523,2343,2232,2210,2251,2307,2339,
-2341,2330,2329,2346,2368,2384,2397,2426,2482,2549,2594,2599,2582,2590,2652,2751,2839,2882,2888,2891,2919,
-2966,3006,3025,3031,3043,3062,3080,3091,3101,3120,3141,3150,3143,3127,3113,3104,3101,3108,3132,3164,3182,
-3180,3186,3249,3380,3529,3624,3634,3598,3583,3616,3670,3701,3697,3685,3697,3739,3795,3843,3876,3900,3925,
-3955,3984,4007,4025,4050,4094,4153,4206,4231,4227,4207,4190,4179,4169,4159,4156,4163,4176,4187,4197,4212,
-4234,4254,4265,4267,4270,4279,4291,4302,4312,4325,4347,4381,4419,4450,4461,4446,4420,4400,4381,4317,4139,
-3807,3341,2818,2332,1970,1794,1826,2029,2314,2573,2744,2835,2894,2953,3004,3020,2993,2943,2896,2856,2806,
-2730,2634,2544,2488,2471,2469,2446,2378,2274,2171,2103,2074,2060,2035,1996,1957,1928,1903,1869,1821,1767,
-1717,1671,1625,1578,1537,1503,1469,1426,1369,1306,1249,1207,1180,1165,1156,1142,1117,1081,1045,1014,988,
-958,922,884,851,826,803,775,738,696,656,623,599,582,562,531,488,442,400,362,327,295,
-273,260,244,214,170,131,111,108,107,97,80,64,51,40,29,20,14,3,-18,-49,-81,
--108,-131,-154,-178,-197,-212,-225,-240,-258,-274,-287,-298,-309,-322,-331,-337,-340,-343,-353,-376,-413,
--457,-498,-531,-558,-584,-612,-639,-663,-686,-713,-745,-776,-801,-822,-839,-855,-868,-880,-890,-903,-916,
--928,-937,-943,-948,-952,-956,-962,-969,-975,-979,-983,-990,-1001,-1012,-1019,-1024,-1029,-1037,-1047,-1056,-1064,
--1072,-1081,-1090,-1101,-1115,-1129,-1142,-1151,-1160,-1173,-1188,-1199,-1204,-1209,-1218,-1230,-1237,-1236,-1232,-1232,-1236,
--1239,-1236,-1233,-1232,-1232,-1226,-1215,-1204,-1200,-1199,-1193,-1183,-1176,-1179,-1187,-1189,-1180,-1163,-1146,-1134,-1127,
--1123,-1120,-1118,-1112,-1104,-1096,-1091,-1087,-1083,-1076,-1071,-1069,-1070,-1073,-1076,-1081,-1085,-1084,-1078,-1075,-1078,
--1085,-1089,-1088,-1084,-1083,-1084,-1084,-1080,-1077,-1076,-1074,-1071,-1065,-1062,-1062,-1063,-1062,-1057,-1051,-1048,-1045,
--1041,-1034,-1026,-1018,-1014,-1012,-1009,-1000,-988,-976,-970,-966,-961,-949,-934,-923,-916,-910,-902,-896,-895,
--896,-895,-889,-882,-878,-876,-872,-864,-857,-851,-845,-835,-823,-813,-805,-798,-790,-784,-782,-779,-772,
--759,-746,-737,-730,-722,-711,-701,-695,-690,-682,-671,-662,-655,-647,-636,-626,-621,-619,-615,-604,-592,
--583,-577,-572,-565,-559,-556,-555,-550,-541,-529,-518,-506,-494,-483,-473,-462,-449,-435,-424,-413,-398,
--377,-352,-330,-311,-293,-274,-253,-233,-214,-193,-170,-150,-135,-124,-114,-106,-102,-102,-101,-92,-79,
--67,-60,-55,-46,-35,-25,-20,-14,-5,6,19,33,46,58,69,83,106,136,167,193,212,
-234,263,296,323,344,364,391,424,456,486,516,548,580,608,631,653,678,709,744,781,820,
-859,897,933,968,1003,1043,1090,1140,1187,1227,1259,1290,1324,1358,1389,1420,1457,1497,1531,1553,1566,
-1569,1536,1428,1244,1060,996,1136,1462,1873,2276,2634,2944,3189,3324,3326,3228,3090,2945,2776,2562,2333,
-2162,2097,2126,2191,2249,2304,2382,2480,2558,2573,2529,2482,2492,2571,2667,2708,2660,2555,2452,2380,2324,
-2253,2160,2072,2014,1982,1953,1912,1862,1818,1786,1757,1727,1700,1683,1679,1684,1693,1703,1713,1718,1717,
-1707,1691,1671,1651,1637,1626,1611,1584,1546,1510,1485,1468,1445,1405,1355,1310,1277,1245,1203,1144,1076,
-1010,949,889,819,736,653,596,583,601,612,569,452,286,118,-14,-99,-149,-185,-223,-266,-309,
--342,-363,-379,-400,-430,-463,-492,-516,-543,-578,-623,-668,-707,-735,-755,-769,-774,-771,-758,-741,-727,
--725,-738,-761,-785,-800,-801,-790,-771,-754,-748,-749,-748,-736,-713,-690,-674,-660,-637,-600,-556,-509,
--455,-387,-308,-235,-184,-157,-138,-112,-76,-35,1,29,45,56,68,92,127,164,192,211,228,
-248,270,291,312,335,361,388,418,454,496,534,555,558,554,557,571,591,614,639,668,695,
-720,745,777,812,844,864,877,895,923,955,986,1014,1044,1076,1105,1126,1139,1153,1173,1197,1221,
-1239,1254,1269,1287,1308,1329,1349,1365,1381,1399,1418,1436,1449,1460,1472,1487,1501,1512,1523,1537,1554,
-1573,1591,1605,1616,1621,1623,1627,1635,1642,1642,1633,1624,1622,1626,1624,1613,1596,1583,1578,1574,1566,
-1557,1553,1554,1555,1551,1545,1542,1541,1539,1535,1533,1533,1533,1530,1530,1540,1557,1572,1580,1590,1611,
-1642,1671,1687,1699,1726,1773,1827,1869,1886,1877,1852,1826,1825,1861,1923,1977,1991,1969,1941,1932,1946,
-1972,2004,2072,2066,2043,2006,1972,1981,2061,2187,2278,2268,2173,2081,2071,2141,2225,2268,2270,2264,2266,
-2267,2257,2244,2245,2259,2275,2285,2297,2314,2333,2342,2346,2354,2370,2386,2393,2395,2404,2424,2446,2463,
-2473,2483,2496,2510,2529,2555,2589,2618,2635,2644,2658,2680,2700,2708,2708,2715,2737,2767,2793,2809,2819,
-2830,2855,2905,2981,3062,3111,3108,3072,3048,3067,3122,3184,3232,3269,3301,3321,3320,3312,3330,3401,3515,
-3629,3699,3703,3657,3590,3532,3498,3478,3451,3407,3356,3318,3301,3292,3277,3259,3254,3270,3289,3290,3274,
-3263,3272,3292,3298,3279,3242,3197,3148,3099,3062,3051,3061,3065,3033,2958,2856,2750,2652,2567,2498,2448,
-2412,2382,2356,2338,2333,2335,2336,2337,2346,2370,2405,2443,2486,2536,2589,2628,2639,2622,2587,2537,2466,
-2367,2249,2134,2040,1969,1918,1883,1864,1857,1860,1867,1878,1890,1899,1906,1918,1946,1988,2031,2065,2095,
-2129,2163,2186,2199,2226,2297,2419,2562,2682,2752,2776,2769,2747,2722,2698,2676,2652,2619,2577,2533,2492,
-2455,2423,2396,2376,2357,2331,2300,2271,2250,2237,2221,2201,2183,2174,2166,2151,2129,2109,2096,2084,2066,
-2046,2034,2037,2053,2072,2090,2106,2118,2129,2146,2171,2193,2199,2191,2195,2228,2267,2267,2214,2153,2145,
-2196,2245,2234,2171,2119,2114,2121,2085,1998,1911,1869,1858,1831,1771,1711,1689,1701,1708,1688,1654,1631,
-1623,1617,1602,1587,1580,1574,1560,1535,1512,1497,1486,1471,1453,1438,1425,1409,1386,1359,1335,1316,1296,
-1273,1250,1226,1200,1172,1143,1116,1089,1061,1029,997,967,939,911,885,861,839,814,783,750,718,
-687,655,623,597,577,561,539,511,483,459,436,407,374,343,316,288,252,209,164,123,82,
-36,-15,-68,-119,-165,-209,-254,-303,-353,-403,-449,-491,-532,-573,-613,-650,-687,-732,-785,-839,-883,
--915,-946,-989,-1047,-1109,-1163,-1208,-1249,-1288,-1323,-1349,-1367,-1380,-1389,-1395,-1407,-1436,-1489,-1562,-1644,-1722,
--1792,-1851,-1905,-1957,-2013,-2070,-2128,-2182,-2231,-2277,-2323,-2366,-2409,-2452,-2494,-2532,-2564,-2596,-2636,-2685,-2733,
--2773,-2810,-2854,-2907,-2954,-2981,-2992,-3003,-3022,-3039,-3042,-3041,-3057,-3102,-3159,-3204,-3233,-3262,-3302,-3342,-3363,
--3363,-3362,-3383,-3428,-3483,-3530,-3558,-3567,-3568,-3583,-3632,-3716,-3813,-3894,-3950,-3995,-4038,-4069,-4076,-4063,-4056,
--4070,-4094,-4099,-4071,-4030,-4004,-4006,-4028,-4052,-4067,-4072,-4070,-4068,-4068,-4066,-4058,-4042,-4022,-4007,-3996,-3978,
--3952,-3926,-3912,-3911,-3911,-3907,-3902,-3904,-3911,-3908,-3891,-3870,-3855,-3841,-3814,-3764,-3696,-3618,-3536,-3467,-3432,
--3443,-3465,-3435,-3308,-3105,-2902,-2766,-2711,-2700,-2693,-2678,-2664,-2654,-2648,-2645,-2646,-2649,-2643,-2624,-2606,-2607,
--2629,-2655,-2662,-2650,-2640,-2650,-2677,-2695,-2672,-2597,-2488,-2391,-2347,-2369,-2425,-2461,-2439,-2362,-2266,-2188,-2140,
--2110,-2083,-2051,-2014,-1980,-1957,-1950,-1960,-1982,-2003,-2014,-2012,-2003,-1988,-1967,-1935,-1890,-1840,-1792,-1750,-1702,
--1627,-1515,-1389,-1295,-1269,-1302,-1350,-1368,-1343,-1292,-1235,-1169,-1080,-960,-822,-683,-552,-428,-312,-205,-112,
--34,31,89,141,186,228,270,325,409,525,654,762,822,845,862,899,953,1004,1047,1093,1148,
-1195,1210,1189,1155,1135,1130,1126,1116,1112,1135,1189,1258,1331,1408,1495,1593,1692,1786,1867,1930,1968,
-1992,2027,2091,2176,2255,2307,2342,2387,2450,2516,2569,2614,2663,2717,2758,2775,2785,2809,2844,2862,2846,
-2813,2798,2807,2798,2716,2552,2354,2196,2123,2135,2193,2251,2277,2269,2250,2253,2290,2341,2372,2374,2371,
-2399,2460,2521,2546,2533,2518,2537,2589,2647,2689,2720,2764,2830,2898,2942,2958,2964,2980,3005,3025,3038,
-3052,3075,3099,3108,3096,3076,3060,3052,3053,3064,3092,3128,3149,3146,3149,3204,3330,3482,3586,3602,3561,
-3532,3551,3602,3637,3635,3616,3615,3648,3703,3756,3794,3821,3847,3879,3911,3939,3962,3992,4036,4089,4134,
-4155,4153,4140,4129,4123,4119,4118,4125,4138,4150,4157,4167,4188,4217,4241,4247,4241,4238,4244,4255,4265,
-4275,4297,4335,4382,4420,4433,4420,4395,4375,4368,4346,4253,4030,3653,3158,2632,2174,1872,1773,1870,2103,
-2373,2597,2741,2824,2884,2938,2975,2982,2958,2916,2867,2817,2761,2694,2610,2520,2445,2412,2423,2438,2407,
-2309,2182,2083,2039,2029,2010,1968,1923,1893,1875,1847,1797,1738,1686,1646,1607,1563,1519,1481,1447,1405,
-1350,1290,1237,1199,1174,1157,1143,1125,1099,1065,1031,1002,980,955,921,879,841,811,788,765,735,
-695,651,612,588,577,567,544,506,459,412,369,329,295,271,256,239,211,171,134,112,106,
-104,97,84,70,55,40,26,15,6,-6,-26,-53,-81,-107,-132,-157,-179,-195,-207,-221,-239,
--260,-280,-299,-316,-332,-344,-352,-354,-355,-355,-360,-376,-407,-448,-489,-522,-550,-577,-607,-635,-659,
--681,-708,-740,-772,-800,-824,-845,-864,-879,-889,-898,-909,-923,-938,-949,-956,-960,-961,-964,-969,-977,
--984,-988,-990,-995,-1006,-1019,-1030,-1037,-1042,-1047,-1052,-1058,-1065,-1075,-1087,-1099,-1111,-1123,-1137,-1149,-1160,
--1170,-1182,-1194,-1203,-1208,-1213,-1221,-1230,-1233,-1229,-1225,-1227,-1232,-1234,-1230,-1223,-1218,-1215,-1210,-1201,-1195,
--1193,-1191,-1183,-1174,-1172,-1181,-1190,-1188,-1171,-1150,-1135,-1129,-1127,-1123,-1116,-1106,-1095,-1086,-1082,-1082,-1083,
--1080,-1075,-1071,-1071,-1072,-1073,-1073,-1077,-1080,-1081,-1076,-1072,-1073,-1080,-1086,-1087,-1084,-1083,-1084,-1084,-1082,
--1080,-1080,-1079,-1076,-1071,-1067,-1068,-1070,-1069,-1065,-1058,-1053,-1051,-1048,-1043,-1035,-1028,-1024,-1023,-1020,-1012,
--999,-987,-979,-975,-969,-958,-945,-934,-927,-921,-913,-908,-908,-909,-907,-898,-889,-883,-880,-876,-869,
--863,-857,-850,-840,-828,-817,-808,-801,-793,-787,-785,-783,-777,-765,-753,-743,-736,-728,-718,-710,-706,
--703,-697,-686,-674,-663,-652,-640,-631,-626,-624,-621,-613,-602,-592,-584,-577,-570,-565,-564,-563,-559,
--551,-541,-530,-518,-506,-494,-482,-469,-455,-442,-432,-425,-413,-393,-367,-341,-320,-304,-289,-272,-254,
--233,-209,-185,-169,-158,-150,-140,-130,-124,-122,-119,-109,-95,-83,-76,-70,-59,-46,-37,-32,-29,
--22,-10,4,19,33,46,57,71,93,122,153,181,204,231,263,294,320,342,366,396,428,
-454,479,509,545,580,606,625,646,674,709,745,780,816,854,893,928,961,995,1031,1069,1108,
-1148,1190,1232,1272,1306,1334,1360,1389,1424,1461,1493,1519,1540,1547,1507,1387,1198,1019,964,1107,1430,
-1839,2239,2582,2862,3078,3214,3258,3221,3119,2959,2735,2466,2211,2041,1985,2013,2064,2110,2168,2266,2395,
-2506,2549,2521,2476,2475,2538,2623,2666,2634,2546,2448,2366,2293,2212,2125,2049,2001,1971,1939,1895,1847,
-1807,1778,1752,1723,1698,1683,1683,1694,1710,1726,1740,1747,1744,1730,1708,1681,1658,1644,1637,1623,1592,
-1549,1510,1487,1475,1455,1416,1363,1313,1275,1242,1199,1142,1075,1011,953,895,826,745,669,624,623,
-645,643,577,439,265,105,-9,-80,-127,-168,-212,-258,-300,-334,-360,-384,-414,-448,-481,-507,-527,
--549,-579,-617,-655,-688,-714,-734,-750,-762,-764,-754,-736,-718,-712,-721,-742,-767,-787,-799,-799,-787,
--770,-756,-748,-741,-725,-703,-685,-675,-667,-648,-612,-565,-512,-454,-384,-308,-240,-196,-177,-168,-156,
--133,-101,-62,-23,8,27,40,56,85,120,150,170,185,203,228,256,286,319,354,387,419,
-454,492,529,557,572,578,587,602,622,646,673,701,726,747,769,796,828,859,882,902,926,
-956,989,1019,1049,1082,1117,1148,1170,1184,1198,1218,1241,1264,1284,1301,1317,1335,1355,1375,1394,1410,
-1425,1441,1458,1474,1488,1501,1514,1526,1537,1546,1556,1570,1586,1601,1614,1625,1635,1641,1642,1642,1645,
-1650,1651,1646,1640,1640,1644,1643,1633,1617,1602,1593,1584,1573,1564,1561,1561,1557,1549,1540,1536,1535,
-1532,1529,1528,1532,1537,1540,1544,1555,1569,1582,1592,1609,1637,1669,1689,1697,1709,1744,1798,1850,1880,
-1886,1872,1844,1813,1800,1822,1873,1920,1932,1917,1912,1944,2002,2051,2072,2109,2056,2001,1966,1963,2014,
-2121,2245,2309,2268,2157,2069,2070,2140,2211,2238,2236,2240,2254,2258,2242,2224,2226,2246,2266,2276,2285,
-2304,2327,2338,2336,2333,2338,2349,2360,2371,2388,2412,2433,2446,2455,2467,2485,2501,2517,2537,2564,2591,
-2610,2625,2643,2667,2686,2692,2691,2697,2714,2735,2753,2766,2777,2786,2798,2830,2897,2991,3074,3108,3091,
-3062,3061,3095,3144,3194,3244,3295,3332,3334,3311,3301,3344,3442,3554,3625,3628,3571,3489,3418,3378,3359,
-3339,3303,3255,3215,3190,3166,3132,3097,3082,3100,3135,3159,3163,3159,3164,3176,3182,3175,3156,3128,3094,
-3057,3034,3032,3043,3034,2982,2891,2785,2685,2600,2528,2472,2433,2409,2391,2378,2371,2375,2383,2387,2391,
-2405,2435,2477,2522,2570,2626,2684,2726,2735,2710,2661,2595,2509,2400,2280,2169,2081,2017,1971,1940,1923,
-1918,1920,1928,1939,1950,1957,1965,1983,2016,2058,2093,2118,2144,2182,2222,2244,2247,2263,2334,2471,2642,
-2790,2879,2908,2897,2871,2843,2815,2787,2752,2708,2660,2613,2569,2529,2490,2459,2436,2417,2394,2369,2347,
-2334,2322,2304,2280,2261,2252,2245,2231,2211,2193,2181,2170,2151,2129,2119,2125,2142,2163,2180,2195,2205,
-2215,2234,2263,2289,2293,2277,2271,2300,2343,2352,2303,2236,2215,2254,2297,2280,2207,2137,2117,2121,2095,
-2024,1945,1898,1880,1852,1802,1756,1740,1747,1747,1725,1698,1685,1685,1681,1666,1650,1641,1634,1616,1587,
-1562,1549,1541,1528,1508,1488,1470,1452,1428,1403,1381,1362,1342,1317,1290,1263,1237,1211,1186,1163,1139,
-1109,1073,1039,1012,988,964,938,910,884,856,824,790,758,728,699,670,644,622,604,583,557,
-531,506,481,452,421,391,365,337,303,262,221,183,144,97,43,-10,-59,-101,-142,-189,-241,
--294,-341,-383,-423,-464,-509,-552,-590,-627,-669,-720,-774,-821,-855,-887,-927,-983,-1048,-1111,-1162,-1201,
--1228,-1249,-1267,-1286,-1305,-1322,-1338,-1359,-1395,-1452,-1525,-1604,-1680,-1747,-1807,-1861,-1914,-1968,-2024,-2079,-2131,
--2181,-2229,-2276,-2319,-2362,-2408,-2456,-2500,-2538,-2573,-2616,-2665,-2709,-2740,-2763,-2796,-2845,-2900,-2949,-2990,-3032,
--3074,-3103,-3114,-3119,-3143,-3194,-3253,-3296,-3321,-3345,-3375,-3401,-3409,-3403,-3405,-3431,-3471,-3509,-3536,-3561,-3588,
--3620,-3657,-3705,-3766,-3830,-3883,-3922,-3960,-4005,-4045,-4063,-4058,-4051,-4061,-4082,-4089,-4066,-4024,-3992,-3988,-4007,
--4032,-4050,-4060,-4067,-4073,-4076,-4071,-4055,-4033,-4014,-4003,-3994,-3975,-3942,-3907,-3884,-3879,-3885,-3894,-3900,-3906,
--3907,-3900,-3886,-3872,-3860,-3843,-3812,-3762,-3695,-3609,-3511,-3425,-3385,-3404,-3437,-3411,-3280,-3074,-2876,-2753,-2709,
--2701,-2691,-2675,-2663,-2664,-2671,-2680,-2692,-2704,-2705,-2692,-2677,-2676,-2692,-2710,-2716,-2713,-2717,-2736,-2756,-2750,
--2701,-2616,-2522,-2454,-2434,-2455,-2488,-2495,-2454,-2374,-2286,-2215,-2168,-2137,-2111,-2084,-2054,-2022,-1993,-1978,-1982,
--1999,-2016,-2022,-2016,-2005,-1994,-1983,-1960,-1921,-1868,-1814,-1768,-1720,-1648,-1540,-1418,-1332,-1320,-1369,-1428,-1447,
--1414,-1355,-1294,-1225,-1129,-1000,-856,-722,-605,-499,-393,-289,-191,-104,-24,47,109,157,196,235,290,
-375,491,617,726,794,826,842,865,898,935,974,1017,1062,1091,1090,1066,1041,1032,1034,1031,1025,
-1035,1077,1145,1218,1287,1358,1440,1531,1623,1708,1787,1853,1898,1927,1960,2020,2108,2195,2261,2308,2359,
-2423,2490,2545,2592,2644,2698,2738,2754,2754,2755,2757,2745,2719,2700,2708,2723,2692,2574,2387,2197,2070,
-2032,2068,2136,2195,2216,2198,2173,2187,2255,2344,2393,2377,2330,2316,2363,2440,2489,2486,2458,2443,2460,
-2496,2540,2596,2672,2761,2835,2875,2886,2894,2914,2941,2963,2978,2997,3027,3054,3062,3049,3027,3012,3006,
-3009,3024,3055,3093,3114,3106,3097,3137,3251,3403,3520,3554,3523,3489,3495,3535,3570,3571,3549,3538,3560,
-3610,3663,3701,3726,3753,3791,3836,3877,3909,3940,3978,4023,4064,4088,4095,4093,4087,4079,4074,4076,4090,
-4111,4127,4135,4142,4160,4186,4206,4210,4205,4205,4213,4224,4233,4247,4278,4328,4379,4408,4403,4375,4346,
-4334,4329,4293,4164,3895,3479,2967,2452,2040,1812,1795,1952,2198,2440,2620,2737,2816,2879,2922,2939,2933,
-2913,2885,2842,2782,2713,2644,2571,2486,2407,2367,2385,2425,2419,2327,2182,2058,2002,1995,1986,1948,1899,
-1866,1849,1823,1774,1713,1661,1624,1590,1549,1504,1464,1425,1381,1327,1270,1223,1189,1166,1146,1128,1107,
-1081,1048,1014,985,963,940,909,869,828,796,773,753,728,692,649,609,582,571,565,550,517,
-471,422,376,332,294,265,246,229,206,174,141,116,103,96,90,82,70,55,36,16,0,
--10,-19,-33,-53,-78,-105,-133,-158,-178,-191,-202,-218,-238,-261,-284,-306,-327,-345,-356,-361,-364,
--368,-371,-374,-382,-403,-436,-472,-505,-534,-563,-594,-625,-653,-679,-707,-738,-769,-796,-821,-844,-866,
--884,-894,-902,-912,-925,-939,-953,-963,-968,-969,-969,-973,-981,-991,-998,-1001,-1005,-1014,-1026,-1038,-1047,
--1054,-1058,-1060,-1063,-1070,-1081,-1095,-1108,-1118,-1128,-1139,-1150,-1161,-1172,-1184,-1194,-1202,-1207,-1213,-1220,-1226,
--1225,-1220,-1216,-1218,-1224,-1225,-1217,-1206,-1196,-1190,-1185,-1181,-1180,-1182,-1182,-1175,-1167,-1167,-1174,-1177,-1167,
--1146,-1126,-1119,-1122,-1126,-1123,-1113,-1101,-1091,-1084,-1084,-1090,-1095,-1095,-1091,-1088,-1088,-1089,-1087,-1083,-1081,
--1083,-1084,-1081,-1077,-1077,-1082,-1088,-1089,-1087,-1085,-1086,-1087,-1087,-1086,-1085,-1084,-1081,-1076,-1073,-1072,-1074,
--1074,-1072,-1067,-1061,-1056,-1053,-1050,-1045,-1039,-1034,-1031,-1028,-1021,-1011,-1000,-992,-986,-978,-966,-953,-943,
--936,-932,-928,-924,-924,-923,-918,-909,-898,-892,-888,-886,-881,-875,-867,-857,-845,-832,-823,-816,-809,
--800,-792,-786,-781,-774,-763,-752,-745,-740,-733,-723,-714,-709,-706,-700,-690,-678,-666,-654,-643,-633,
--628,-626,-624,-618,-610,-600,-590,-580,-574,-570,-570,-568,-562,-553,-543,-532,-520,-509,-499,-490,-479,
--465,-452,-442,-436,-425,-406,-379,-351,-328,-312,-299,-287,-272,-252,-227,-204,-189,-182,-176,-165,-152,
--144,-141,-138,-127,-112,-99,-91,-83,-72,-59,-49,-44,-41,-33,-21,-6,9,24,38,50,65,
-85,114,146,177,204,233,263,291,316,339,366,398,426,449,473,505,543,577,598,613,633,
-665,702,737,767,796,828,861,892,924,960,997,1030,1061,1096,1141,1192,1237,1269,1292,1317,1350,
-1389,1426,1461,1496,1529,1537,1484,1345,1147,974,934,1089,1416,1826,2218,2535,2776,2959,3100,3194,3218,
-3147,2962,2682,2366,2105,1961,1936,1973,2014,2047,2102,2211,2359,2489,2549,2536,2498,2493,2538,2600,2628,
-2596,2518,2425,2336,2251,2167,2090,2030,1989,1957,1920,1877,1836,1804,1776,1748,1718,1695,1687,1694,1710,
-1727,1742,1751,1755,1753,1742,1723,1698,1675,1660,1648,1630,1597,1554,1520,1503,1495,1477,1437,1382,1329,
-1287,1251,1208,1151,1085,1017,954,891,824,753,694,666,673,690,672,587,440,269,119,11,-60,
--115,-165,-213,-259,-300,-337,-371,-402,-434,-466,-495,-519,-540,-562,-589,-621,-653,-680,-701,-720,-738,
--754,-763,-761,-747,-730,-721,-726,-741,-762,-781,-794,-798,-791,-775,-759,-747,-736,-720,-700,-683,-673,
--665,-649,-619,-579,-532,-476,-409,-335,-268,-223,-200,-189,-178,-163,-140,-106,-63,-21,10,31,49,
-73,100,121,134,147,170,203,240,272,303,334,369,407,448,492,536,572,596,610,620,632,
-649,670,695,721,745,764,784,807,834,864,891,919,950,984,1017,1048,1081,1117,1153,1185,1208,
-1225,1242,1261,1281,1302,1322,1342,1361,1380,1399,1419,1439,1456,1471,1484,1497,1509,1522,1535,1547,1557,
-1566,1574,1584,1596,1607,1616,1625,1637,1651,1663,1668,1670,1672,1678,1681,1677,1669,1662,1658,1650,1637,
-1621,1608,1597,1585,1571,1561,1557,1556,1552,1543,1535,1534,1537,1538,1538,1541,1548,1556,1560,1564,1573,
-1585,1597,1609,1627,1652,1673,1684,1691,1710,1751,1797,1825,1829,1827,1834,1844,1842,1830,1823,1832,1845,
-1852,1864,1909,1994,2082,2126,2109,2082,2004,1954,1946,1978,2051,2162,2278,2336,2296,2190,2102,2088,2132,
-2178,2194,2198,2213,2234,2236,2215,2194,2199,2223,2246,2256,2267,2289,2313,2324,2319,2312,2317,2331,2345,
-2359,2378,2402,2421,2432,2440,2455,2475,2491,2502,2515,2535,2561,2584,2606,2631,2655,2671,2674,2673,2679,
-2694,2709,2720,2732,2747,2757,2761,2774,2825,2920,3025,3091,3101,3083,3074,3090,3120,3155,3200,3262,3321,
-3348,3338,3320,3336,3398,3478,3527,3518,3456,3374,3309,3276,3266,3253,3220,3170,3121,3083,3045,2997,2943,
-2910,2912,2941,2973,2993,3005,3019,3036,3048,3052,3048,3037,3021,3005,2999,3009,3017,2994,2926,2825,2721,
-2631,2557,2497,2453,2430,2423,2422,2421,2423,2431,2442,2451,2461,2481,2516,2560,2606,2656,2714,2774,2814,
-2818,2785,2726,2649,2552,2438,2317,2208,2123,2063,2022,1996,1983,1979,1982,1988,1998,2008,2015,2024,2045,
-2082,2121,2148,2163,2184,2222,2266,2288,2289,2305,2385,2539,2726,2887,2983,3015,3007,2983,2956,2926,2891,
-2847,2795,2740,2689,2642,2597,2554,2519,2495,2478,2461,2441,2424,2411,2398,2378,2353,2334,2326,2320,2307,
-2289,2275,2265,2253,2233,2212,2204,2215,2236,2257,2273,2282,2287,2293,2311,2346,2379,2388,2370,2359,2386,
-2437,2459,2416,2337,2286,2289,2305,2279,2206,2138,2118,2128,2118,2063,1991,1938,1907,1877,1839,1807,1797,
-1799,1790,1767,1747,1745,1751,1747,1728,1709,1699,1690,1671,1643,1619,1606,1598,1583,1559,1534,1513,1493,
-1471,1447,1427,1408,1386,1360,1331,1304,1280,1256,1233,1211,1186,1154,1118,1085,1060,1039,1015,985,952,
-923,895,866,833,801,772,744,716,688,664,644,625,603,578,552,525,497,467,438,411,383,
-351,315,278,241,200,153,100,49,4,-36,-78,-126,-179,-231,-277,-317,-356,-400,-448,-496,-537,
--574,-613,-660,-713,-762,-802,-836,-874,-924,-986,-1049,-1103,-1139,-1159,-1172,-1187,-1209,-1235,-1261,-1288,-1322,
--1368,-1428,-1497,-1567,-1635,-1699,-1757,-1811,-1862,-1914,-1968,-2021,-2072,-2123,-2173,-2221,-2264,-2304,-2346,-2392,-2437,
--2477,-2516,-2562,-2614,-2664,-2702,-2728,-2757,-2796,-2841,-2886,-2934,-2989,-3050,-3104,-3141,-3173,-3217,-3274,-3328,-3363,
--3383,-3401,-3425,-3441,-3442,-3439,-3452,-3486,-3521,-3541,-3551,-3576,-3629,-3697,-3760,-3807,-3844,-3874,-3898,-3917,-3940,
--3972,-4006,-4026,-4030,-4032,-4048,-4072,-4085,-4070,-4036,-4008,-4001,-4009,-4019,-4025,-4032,-4044,-4062,-4076,-4075,-4058,
--4034,-4013,-3997,-3980,-3949,-3903,-3853,-3819,-3811,-3827,-3857,-3885,-3901,-3900,-3886,-3871,-3861,-3853,-3834,-3798,-3747,
--3680,-3590,-3480,-3378,-3330,-3353,-3400,-3386,-3259,-3054,-2860,-2744,-2708,-2703,-2692,-2673,-2665,-2675,-2693,-2711,-2727,
--2741,-2749,-2748,-2744,-2748,-2761,-2772,-2774,-2776,-2788,-2809,-2817,-2792,-2731,-2654,-2590,-2554,-2545,-2549,-2546,-2522,
--2471,-2402,-2331,-2269,-2223,-2190,-2166,-2143,-2117,-2086,-2056,-2039,-2039,-2048,-2054,-2050,-2037,-2025,-2017,-2010,-1991,
--1955,-1905,-1853,-1807,-1758,-1687,-1580,-1461,-1377,-1368,-1422,-1487,-1510,-1478,-1416,-1349,-1274,-1174,-1044,-905,-782,
--680,-584,-482,-373,-268,-172,-82,2,74,126,161,193,243,326,441,569,683,757,789,795,798,
-810,834,867,905,941,960,956,940,932,938,949,953,957,982,1039,1114,1186,1249,1312,1386,1469,
-1549,1625,1698,1767,1820,1855,1891,1951,2038,2129,2204,2261,2318,2386,2456,2517,2571,2628,2687,2731,2748,
-2740,2719,2689,2652,2618,2606,2616,2612,2544,2396,2209,2050,1966,1958,2002,2067,2123,2143,2127,2112,2152,
-2264,2395,2459,2418,2318,2253,2272,2348,2413,2427,2407,2388,2393,2419,2463,2530,2620,2713,2781,2811,2819,
-2829,2851,2878,2898,2915,2941,2976,3007,3016,3004,2986,2974,2969,2972,2988,3024,3066,3088,3074,3047,3059,
-3147,3289,3420,3483,3475,3444,3436,3463,3495,3504,3492,3486,3510,3559,3611,3645,3662,3683,3722,3776,3827,
-3863,3888,3916,3954,3997,4033,4056,4067,4065,4053,4038,4031,4040,4062,4083,4097,4108,4123,4141,4157,4165,
-4170,4179,4191,4200,4208,4226,4264,4317,4361,4376,4358,4327,4303,4295,4280,4210,4030,3709,3259,2745,2266,
-1923,1781,1844,2048,2294,2501,2641,2733,2809,2873,2907,2905,2885,2868,2853,2818,2753,2672,2599,2530,2451,
-2364,2309,2315,2360,2373,2300,2160,2030,1965,1956,1954,1925,1879,1844,1823,1796,1749,1691,1642,1606,1574,
-1535,1492,1448,1405,1357,1303,1252,1211,1181,1156,1132,1108,1085,1058,1025,990,960,937,915,887,852,
-815,782,756,736,714,685,649,611,582,565,555,539,509,468,424,381,338,297,262,236,219,
-203,181,154,128,106,90,80,72,63,48,26,2,-16,-27,-34,-41,-54,-74,-101,-130,-156,
--175,-188,-200,-216,-236,-258,-282,-306,-330,-348,-356,-360,-364,-373,-381,-386,-391,-403,-426,-458,-490,
--520,-550,-583,-616,-647,-677,-708,-740,-768,-792,-814,-837,-860,-880,-894,-904,-913,-924,-936,-949,-961,
--968,-970,-969,-972,-981,-994,-1005,-1012,-1015,-1020,-1029,-1040,-1050,-1059,-1066,-1069,-1073,-1079,-1089,-1102,-1113,
--1122,-1128,-1136,-1146,-1158,-1169,-1182,-1193,-1201,-1206,-1211,-1216,-1219,-1217,-1211,-1208,-1211,-1215,-1214,-1205,-1191,
--1180,-1172,-1167,-1165,-1167,-1170,-1171,-1166,-1161,-1161,-1164,-1160,-1145,-1126,-1113,-1112,-1116,-1117,-1114,-1109,-1106,
--1103,-1101,-1103,-1108,-1113,-1115,-1113,-1110,-1112,-1113,-1110,-1103,-1096,-1094,-1096,-1095,-1093,-1093,-1096,-1101,-1102,
--1099,-1096,-1096,-1098,-1098,-1097,-1094,-1092,-1089,-1085,-1082,-1079,-1078,-1078,-1078,-1075,-1069,-1063,-1059,-1056,-1053,
--1049,-1043,-1037,-1031,-1026,-1019,-1011,-1004,-997,-988,-975,-962,-952,-948,-947,-945,-942,-938,-934,-929,-921,
--912,-905,-900,-897,-894,-889,-880,-867,-852,-840,-831,-826,-820,-810,-800,-790,-782,-772,-761,-751,-746,
--742,-737,-727,-717,-709,-703,-698,-689,-679,-668,-657,-647,-638,-632,-629,-627,-623,-616,-608,-597,-588,
--581,-578,-577,-574,-567,-555,-543,-530,-517,-506,-499,-495,-488,-476,-463,-451,-443,-433,-415,-390,-362,
--337,-319,-305,-295,-284,-268,-247,-226,-212,-204,-198,-186,-173,-164,-160,-155,-144,-129,-115,-106,-97,
--86,-74,-64,-57,-51,-41,-28,-15,-1,14,30,46,64,87,116,149,179,207,233,261,288,
-313,338,365,394,420,442,468,501,536,561,573,582,600,633,669,700,725,750,776,801,826,
-859,904,954,999,1034,1068,1110,1154,1191,1215,1237,1270,1314,1360,1401,1440,1485,1526,1531,1459,1300,
-1094,933,915,1091,1430,1839,2213,2495,2689,2845,2996,3136,3211,3157,2950,2631,2298,2054,1949,1955,2001,
-2033,2055,2110,2226,2380,2510,2567,2555,2521,2513,2539,2569,2569,2528,2460,2382,2301,2215,2131,2059,2008,
-1972,1939,1902,1864,1831,1802,1771,1735,1703,1687,1691,1707,1727,1742,1749,1752,1751,1750,1745,1735,1719,
-1699,1681,1664,1639,1605,1567,1539,1524,1514,1492,1450,1396,1344,1302,1265,1222,1165,1094,1015,938,868,
-804,750,712,700,709,715,683,590,447,290,150,42,-40,-109,-168,-218,-262,-303,-344,-381,-413,
--440,-466,-491,-517,-541,-566,-592,-621,-649,-674,-694,-709,-724,-741,-757,-766,-765,-756,-747,-747,-754,
--766,-777,-786,-788,-783,-772,-758,-745,-734,-721,-705,-689,-677,-665,-648,-623,-590,-551,-502,-440,-372,
--310,-266,-238,-218,-198,-177,-154,-124,-85,-41,-2,28,55,82,106,120,129,145,178,225,268,
-297,314,331,357,395,441,491,540,583,614,633,645,654,667,685,708,733,757,778,798,818,
-840,864,892,925,962,999,1034,1067,1102,1138,1172,1201,1225,1246,1268,1288,1305,1322,1341,1362,1384,
-1403,1422,1443,1464,1484,1500,1513,1525,1536,1549,1562,1575,1585,1594,1602,1611,1621,1627,1630,1636,1651,
-1673,1693,1704,1708,1711,1715,1715,1707,1692,1676,1660,1645,1630,1616,1606,1597,1585,1570,1559,1555,1555,
-1552,1544,1540,1543,1549,1553,1554,1558,1566,1574,1577,1579,1586,1599,1613,1625,1637,1652,1665,1676,1693,
-1723,1761,1781,1769,1742,1740,1785,1857,1909,1915,1883,1840,1806,1795,1828,1915,2033,2123,2139,2082,2002,
-1932,1910,1933,1976,2035,2122,2226,2296,2285,2207,2125,2093,2109,2136,2150,2161,2183,2204,2203,2181,2164,
-2172,2198,2220,2231,2244,2267,2290,2297,2292,2290,2302,2321,2336,2348,2366,2389,2409,2420,2429,2443,2463,
-2478,2486,2494,2511,2535,2561,2588,2616,2642,2657,2659,2656,2660,2671,2681,2688,2699,2717,2732,2734,2738,
-2777,2865,2979,3068,3107,3109,3106,3111,3118,3124,3148,3205,3283,3344,3365,3357,3355,3379,3417,3436,3416,
-3361,3295,3245,3225,3221,3208,3169,3110,3050,2999,2951,2894,2830,2778,2756,2762,2782,2806,2833,2867,2901,
-2927,2941,2947,2947,2945,2946,2956,2972,2974,2938,2860,2760,2666,2591,2533,2486,2456,2446,2455,2467,2476,
-2483,2492,2505,2518,2535,2561,2598,2640,2684,2733,2792,2849,2885,2883,2843,2777,2693,2591,2475,2355,2248,
-2165,2108,2071,2052,2044,2044,2046,2051,2059,2067,2072,2080,2101,2138,2176,2199,2210,2228,2265,2305,2326,
-2329,2355,2447,2611,2803,2963,3059,3096,3097,3082,3057,3026,2987,2938,2882,2823,2767,2715,2667,2622,2584,
-2559,2542,2526,2508,2492,2480,2467,2449,2430,2415,2407,2400,2387,2372,2359,2350,2336,2315,2297,2294,2308,
-2330,2349,2363,2370,2370,2371,2388,2427,2472,2491,2479,2465,2487,2538,2566,2527,2438,2357,2322,2311,2277,
-2212,2153,2136,2146,2141,2095,2027,1970,1933,1905,1879,1861,1855,1851,1835,1810,1797,1802,1811,1807,1788,
-1768,1757,1747,1727,1700,1678,1665,1652,1631,1603,1577,1557,1539,1517,1494,1473,1453,1430,1402,1374,1350,
-1327,1304,1279,1253,1227,1197,1164,1133,1107,1085,1057,1023,987,958,934,909,879,848,819,791,762,
-732,705,684,666,647,624,597,571,544,516,488,459,431,401,369,333,294,251,205,158,112,
-71,29,-14,-63,-114,-163,-207,-248,-290,-337,-389,-442,-488,-526,-563,-605,-657,-713,-762,-801,-835,
--873,-922,-976,-1025,-1059,-1080,-1094,-1114,-1141,-1172,-1205,-1241,-1286,-1341,-1404,-1467,-1528,-1588,-1648,-1704,-1756,
--1805,-1855,-1908,-1961,-2014,-2065,-2116,-2165,-2208,-2246,-2285,-2328,-2372,-2414,-2453,-2498,-2551,-2605,-2653,-2692,-2728,
--2764,-2798,-2832,-2868,-2917,-2976,-3036,-3089,-3138,-3192,-3247,-3291,-3319,-3339,-3364,-3390,-3406,-3407,-3408,-3430,-3469,
--3503,-3518,-3531,-3573,-3654,-3750,-3825,-3864,-3879,-3889,-3902,-3918,-3936,-3958,-3981,-3998,-4009,-4021,-4043,-4069,-4084,
--4079,-4060,-4044,-4039,-4037,-4028,-4013,-4004,-4011,-4032,-4054,-4062,-4055,-4036,-4015,-3989,-3954,-3902,-3837,-3775,-3732,
--3722,-3747,-3795,-3844,-3873,-3873,-3855,-3840,-3838,-3838,-3822,-3784,-3731,-3666,-3578,-3464,-3351,-3291,-3309,-3360,-3355,
--3239,-3041,-2852,-2743,-2712,-2711,-2700,-2681,-2676,-2691,-2716,-2737,-2753,-2767,-2781,-2794,-2807,-2822,-2837,-2842,-2837,
--2833,-2842,-2857,-2857,-2824,-2767,-2710,-2674,-2659,-2650,-2632,-2600,-2556,-2504,-2447,-2387,-2330,-2282,-2248,-2227,-2210,
--2191,-2166,-2144,-2131,-2129,-2129,-2124,-2113,-2101,-2092,-2083,-2066,-2037,-1998,-1954,-1913,-1875,-1830,-1759,-1655,-1536,
--1446,-1420,-1455,-1507,-1528,-1502,-1447,-1383,-1311,-1218,-1101,-978,-869,-773,-675,-565,-449,-338,-236,-138,-45,
-32,86,115,138,182,262,380,515,633,708,734,728,717,718,734,761,791,816,829,830,827,
-834,851,871,886,906,946,1010,1084,1150,1204,1260,1328,1401,1472,1538,1606,1673,1731,1776,1821,1886,
-1974,2064,2139,2199,2262,2336,2414,2482,2541,2598,2652,2689,2697,2679,2644,2602,2560,2531,2519,2508,2461,
-2347,2181,2019,1914,1882,1900,1942,1994,2039,2059,2052,2055,2126,2276,2436,2505,2440,2302,2197,2190,2254,
-2323,2353,2352,2348,2357,2378,2415,2481,2572,2662,2723,2745,2751,2764,2789,2814,2832,2851,2883,2924,2958,
-2970,2963,2951,2942,2935,2935,2950,2989,3038,3065,3050,3008,2989,3040,3160,3298,3392,3416,3396,3377,3385,
-3413,3436,3446,3459,3494,3552,3608,3639,3646,3655,3687,3739,3788,3818,3831,3847,3880,3925,3970,4005,4026,
-4033,4025,4006,3988,3983,3994,4016,4039,4060,4078,4095,4111,4127,4143,4159,4168,4171,4178,4203,4249,4299,
-4330,4330,4306,4279,4263,4250,4208,4087,3846,3470,2995,2499,2081,1826,1775,1904,2134,2369,2542,2649,2724,
-2796,2859,2888,2876,2848,2831,2820,2788,2721,2637,2564,2503,2427,2331,2252,2233,2270,2301,2261,2148,2022,
-1942,1918,1912,1892,1855,1820,1791,1759,1716,1667,1625,1590,1557,1519,1477,1435,1389,1338,1286,1241,1206,
-1177,1147,1116,1086,1061,1033,999,963,931,907,885,861,830,797,766,739,717,697,676,649,617,
-586,561,541,518,488,452,415,379,343,303,264,232,211,199,185,166,141,114,90,73,62,
-52,38,17,-6,-26,-39,-47,-53,-63,-80,-103,-131,-157,-177,-191,-204,-218,-234,-251,-272,-298,
--324,-343,-351,-353,-358,-370,-382,-390,-395,-404,-424,-452,-483,-514,-546,-580,-614,-645,-675,-707,-738,
--766,-788,-808,-828,-850,-871,-889,-903,-914,-924,-934,-945,-956,-965,-969,-969,-970,-979,-993,-1008,-1017,
--1022,-1026,-1033,-1042,-1052,-1062,-1070,-1075,-1079,-1084,-1092,-1103,-1113,-1121,-1128,-1136,-1145,-1157,-1169,-1182,-1194,
--1201,-1205,-1206,-1207,-1207,-1205,-1202,-1201,-1203,-1207,-1204,-1195,-1184,-1175,-1169,-1165,-1162,-1160,-1159,-1158,-1155,
--1153,-1153,-1153,-1147,-1135,-1124,-1118,-1117,-1113,-1105,-1100,-1103,-1114,-1121,-1120,-1115,-1115,-1119,-1125,-1127,-1127,
--1129,-1132,-1130,-1122,-1114,-1110,-1111,-1113,-1112,-1111,-1112,-1116,-1119,-1118,-1115,-1113,-1113,-1113,-1110,-1107,-1104,
--1101,-1099,-1097,-1093,-1089,-1086,-1085,-1084,-1080,-1073,-1067,-1064,-1063,-1061,-1054,-1045,-1037,-1032,-1026,-1019,-1011,
--1003,-994,-984,-973,-966,-964,-965,-964,-959,-951,-943,-938,-933,-927,-919,-912,-906,-903,-898,-890,-877,
--863,-850,-840,-834,-827,-819,-809,-798,-788,-776,-764,-754,-749,-745,-740,-732,-721,-712,-704,-698,-691,
--682,-672,-660,-649,-640,-634,-630,-626,-622,-616,-610,-602,-594,-588,-584,-582,-578,-570,-559,-547,-533,
--519,-507,-499,-496,-490,-481,-468,-457,-447,-437,-420,-398,-373,-348,-326,-309,-298,-289,-279,-264,-247,
--232,-221,-210,-199,-187,-180,-175,-169,-157,-142,-131,-124,-116,-105,-92,-81,-72,-63,-50,-35,-22,
--9,4,21,40,61,87,118,149,176,200,223,250,280,308,335,361,386,410,434,463,495,
-525,544,552,562,582,610,638,664,693,728,761,784,801,828,877,939,998,1042,1075,1105,1131,
-1150,1166,1193,1241,1301,1354,1394,1432,1479,1518,1510,1416,1238,1033,895,915,1127,1490,1899,2245,2477,
-2620,2747,2908,3079,3181,3131,2911,2588,2275,2071,2002,2023,2064,2085,2102,2161,2280,2426,2536,2572,2547,
-2511,2502,2513,2516,2490,2441,2387,2335,2272,2192,2104,2030,1980,1947,1917,1884,1852,1822,1790,1751,1710,
-1684,1680,1696,1720,1739,1750,1753,1752,1750,1749,1748,1743,1732,1716,1697,1676,1650,1618,1585,1558,1539,
-1519,1487,1444,1396,1354,1319,1285,1242,1181,1100,1006,913,837,782,749,732,728,729,718,671,577,
-447,305,175,64,-29,-108,-172,-223,-265,-305,-345,-381,-409,-430,-452,-476,-503,-531,-557,-583,-610,
--638,-664,-685,-699,-709,-722,-741,-761,-773,-773,-767,-763,-764,-769,-774,-777,-776,-773,-765,-755,-744,
--733,-722,-710,-696,-682,-666,-644,-618,-589,-556,-514,-461,-403,-353,-315,-288,-260,-228,-194,-162,-130,
--95,-57,-18,19,58,97,129,149,160,179,215,266,313,343,359,373,395,427,465,505,545,
-583,614,636,649,660,673,692,715,740,767,793,818,840,857,874,896,927,965,1004,1041,1075,
-1109,1141,1171,1197,1221,1246,1272,1294,1311,1326,1344,1365,1387,1408,1428,1449,1471,1492,1511,1527,1543,
-1558,1574,1590,1604,1616,1626,1635,1644,1651,1655,1657,1664,1681,1706,1728,1739,1741,1740,1738,1731,1716,
-1694,1671,1653,1639,1627,1618,1612,1605,1594,1580,1570,1569,1569,1566,1557,1551,1552,1556,1558,1558,1562,
-1571,1579,1581,1582,1590,1607,1624,1635,1641,1651,1667,1692,1724,1761,1786,1778,1735,1689,1690,1760,1868,
-1956,1982,1947,1881,1820,1793,1824,1915,2026,2093,2077,2002,1914,1878,1893,1932,1961,1982,2030,2114,2195,
-2219,2176,2111,2075,2079,2099,2115,2130,2149,2165,2164,2148,2140,2153,2178,2197,2207,2221,2243,2262,2268,
-2265,2271,2290,2311,2325,2335,2353,2379,2402,2413,2420,2432,2449,2463,2469,2477,2494,2518,2543,2568,2596,
-2623,2640,2644,2640,2640,2646,2650,2652,2661,2680,2699,2706,2712,2745,2825,2934,3033,3094,3123,3136,3141,
-3130,3110,3108,3153,3238,3323,3371,3377,3367,3363,3369,3369,3348,3308,3264,3232,3218,3212,3193,3151,3089,
-3025,2969,2917,2857,2789,2727,2685,2664,2658,2668,2696,2743,2798,2843,2871,2885,2890,2894,2900,2911,2919,
-2907,2861,2784,2698,2626,2574,2535,2503,2483,2483,2497,2515,2528,2538,2548,2562,2579,2604,2638,2678,2718,
-2755,2798,2849,2901,2930,2923,2879,2810,2723,2621,2506,2390,2288,2209,2154,2122,2109,2107,2109,2111,2114,
-2120,2126,2128,2133,2151,2186,2224,2249,2263,2283,2318,2353,2369,2374,2408,2509,2673,2856,3005,3099,3147,
-3164,3163,3145,3115,3076,3029,2972,2909,2848,2793,2744,2698,2658,2627,2606,2588,2572,2557,2546,2537,2527,
-2516,2505,2496,2486,2472,2458,2447,2436,2421,2401,2388,2389,2403,2421,2438,2451,2460,2461,2461,2477,2521,
-2575,2607,2599,2576,2577,2609,2628,2590,2501,2410,2359,2335,2303,2248,2195,2171,2169,2155,2111,2049,1996,
-1963,1940,1922,1909,1903,1895,1875,1853,1843,1849,1859,1856,1842,1827,1818,1806,1785,1759,1737,1722,1703,
-1676,1646,1622,1607,1590,1567,1541,1518,1497,1473,1445,1417,1394,1373,1348,1319,1291,1267,1242,1213,1182,
-1153,1125,1094,1059,1025,997,976,954,927,897,868,840,809,777,747,724,706,689,666,641,616,
-591,566,538,508,479,450,418,382,341,299,257,217,178,137,93,46,-1,-48,-92,-135,-179,
--225,-275,-331,-386,-435,-475,-510,-551,-605,-668,-727,-772,-803,-828,-861,-901,-942,-976,-1001,-1024,-1051,
--1083,-1117,-1152,-1193,-1245,-1307,-1372,-1432,-1487,-1542,-1598,-1652,-1702,-1750,-1800,-1852,-1906,-1959,-2010,-2061,-2111,
--2155,-2195,-2236,-2281,-2328,-2372,-2411,-2451,-2497,-2547,-2597,-2643,-2686,-2728,-2765,-2797,-2828,-2864,-2906,-2952,-2997,
--3045,-3095,-3142,-3177,-3204,-3232,-3269,-3305,-3325,-3327,-3329,-3351,-3389,-3423,-3446,-3477,-3542,-3643,-3745,-3812,-3831,
--3827,-3829,-3850,-3885,-3923,-3957,-3985,-4004,-4018,-4032,-4052,-4072,-4085,-4086,-4081,-4078,-4079,-4072,-4051,-4020,-3993,
--3985,-3995,-4013,-4027,-4033,-4028,-4011,-3977,-3922,-3851,-3774,-3709,-3665,-3654,-3676,-3725,-3779,-3814,-3818,-3802,-3793,
--3804,-3819,-3812,-3776,-3721,-3658,-3575,-3464,-3347,-3275,-3278,-3321,-3320,-3217,-3035,-2860,-2758,-2732,-2734,-2724,-2705,
--2699,-2716,-2744,-2769,-2787,-2805,-2826,-2850,-2875,-2897,-2910,-2907,-2891,-2875,-2874,-2883,-2881,-2856,-2814,-2777,-2757,
--2748,-2733,-2700,-2653,-2603,-2552,-2497,-2438,-2378,-2328,-2298,-2284,-2277,-2268,-2255,-2245,-2242,-2242,-2239,-2232,-2227,
--2228,-2227,-2210,-2170,-2116,-2065,-2027,-2001,-1973,-1932,-1863,-1764,-1648,-1548,-1492,-1485,-1501,-1504,-1479,-1433,-1381,
--1321,-1244,-1150,-1048,-949,-851,-744,-626,-507,-396,-294,-193,-95,-13,37,60,75,113,195,317,457,
-577,649,667,653,637,637,652,673,691,705,715,724,735,750,773,800,829,866,917,980,1046,
-1101,1149,1200,1263,1331,1398,1462,1526,1590,1648,1700,1757,1832,1920,2002,2068,2125,2192,2275,2361,2438,
-2503,2558,2599,2616,2602,2566,2525,2491,2468,2450,2429,2381,2280,2126,1960,1840,1797,1815,1854,1891,1927,
-1960,1977,1973,1984,2064,2217,2373,2434,2363,2225,2124,2116,2174,2237,2271,2283,2291,2301,2315,2345,2408,
-2501,2592,2649,2668,2674,2690,2716,2741,2759,2781,2819,2865,2902,2918,2917,2910,2903,2894,2887,2896,2930,
-2981,3018,3014,2974,2939,2957,3047,3180,3297,3353,3349,3323,3315,3335,3367,3394,3422,3468,3534,3597,3633,
-3638,3639,3662,3708,3753,3777,3783,3792,3819,3858,3896,3926,3949,3967,3977,3973,3959,3946,3944,3959,3985,
-4013,4038,4059,4080,4103,4123,4133,4131,4127,4137,4173,4226,4270,4287,4275,4251,4229,4212,4180,4097,3920,
-3619,3200,2715,2256,1917,1760,1793,1968,2202,2415,2562,2649,2712,2776,2834,2860,2849,2821,2801,2785,2748,
-2678,2598,2534,2484,2416,2317,2220,2179,2206,2253,2247,2165,2042,1938,1882,1862,1848,1825,1794,1758,1719,
-1678,1641,1609,1577,1541,1502,1462,1421,1375,1323,1273,1233,1202,1172,1136,1098,1065,1038,1011,977,939,
-906,880,858,833,805,775,747,722,700,683,666,646,620,589,558,530,501,468,433,400,371,
-341,305,266,230,205,190,180,166,145,120,94,72,57,44,30,11,-9,-29,-46,-60,-71,
--83,-99,-119,-143,-167,-187,-203,-216,-227,-237,-248,-265,-289,-315,-335,-344,-347,-353,-365,-379,-390,
--398,-410,-430,-455,-484,-515,-549,-585,-619,-649,-677,-706,-735,-762,-784,-803,-821,-842,-862,-882,-899,
--915,-927,-937,-946,-956,-966,-971,-972,-974,-980,-993,-1007,-1018,-1027,-1035,-1043,-1051,-1058,-1064,-1070,-1076,
--1079,-1083,-1089,-1098,-1108,-1118,-1128,-1139,-1150,-1161,-1173,-1185,-1195,-1201,-1201,-1198,-1195,-1193,-1190,-1188,-1188,
--1191,-1192,-1189,-1182,-1175,-1170,-1168,-1165,-1160,-1154,-1149,-1144,-1140,-1139,-1140,-1139,-1134,-1129,-1126,-1126,-1123,
--1111,-1095,-1090,-1101,-1119,-1129,-1121,-1107,-1100,-1108,-1122,-1132,-1137,-1142,-1146,-1146,-1140,-1132,-1128,-1128,-1130,
--1129,-1125,-1123,-1125,-1128,-1131,-1130,-1128,-1125,-1123,-1121,-1118,-1115,-1114,-1113,-1112,-1109,-1105,-1101,-1099,-1098,
--1095,-1089,-1083,-1079,-1078,-1075,-1068,-1059,-1052,-1046,-1039,-1028,-1015,-1005,-998,-992,-985,-980,-980,-982,-981,
--974,-962,-951,-946,-943,-939,-930,-919,-910,-905,-901,-895,-886,-873,-860,-848,-838,-830,-823,-816,-808,
--797,-785,-773,-764,-757,-752,-746,-739,-730,-720,-711,-703,-695,-686,-675,-661,-648,-638,-632,-627,-622,
--616,-610,-605,-599,-593,-588,-584,-581,-576,-569,-560,-551,-541,-528,-515,-505,-497,-490,-481,-471,-461,
--452,-440,-423,-402,-379,-356,-335,-316,-303,-294,-287,-276,-261,-245,-230,-216,-204,-194,-188,-184,-177,
--165,-154,-148,-144,-137,-125,-110,-98,-88,-76,-60,-41,-25,-12,0,15,32,53,78,108,138,
-162,182,204,232,266,298,326,350,375,402,431,463,495,526,552,576,602,627,647,662,685,
-728,790,848,879,884,888,916,967,1024,1067,1094,1111,1120,1128,1145,1185,1249,1319,1372,1406,1436,
-1473,1496,1463,1343,1153,959,858,930,1195,1592,2001,2309,2479,2566,2668,2832,3015,3116,3053,2833,2539,
-2282,2130,2086,2103,2127,2136,2154,2215,2328,2455,2537,2545,2503,2463,2453,2459,2448,2407,2357,2318,2289,
-2245,2171,2081,2003,1952,1922,1895,1866,1834,1802,1765,1723,1688,1673,1681,1704,1727,1741,1748,1751,1751,
-1750,1748,1745,1740,1730,1715,1698,1679,1655,1627,1597,1569,1542,1512,1474,1433,1395,1365,1338,1307,1261,
-1192,1099,990,889,816,779,769,766,759,740,703,640,545,425,295,172,62,-33,-113,-177,-226,
--268,-307,-344,-376,-400,-420,-442,-468,-495,-521,-545,-567,-591,-617,-644,-668,-684,-695,-706,-724,-747,
--766,-772,-769,-763,-762,-766,-770,-770,-767,-763,-759,-752,-744,-733,-720,-708,-695,-679,-658,-632,-604,
--577,-550,-518,-477,-431,-390,-358,-331,-300,-261,-218,-177,-141,-107,-75,-41,-1,47,102,153,188,
-207,221,244,280,323,366,406,446,484,517,541,558,574,592,611,628,641,655,674,697,722,
-748,777,810,843,870,888,900,915,941,975,1013,1048,1080,1110,1139,1165,1189,1214,1241,1269,1293,
-1313,1330,1349,1370,1392,1416,1439,1461,1483,1502,1521,1542,1564,1586,1604,1621,1636,1649,1660,1668,1676,
-1683,1689,1695,1705,1722,1743,1759,1763,1758,1750,1742,1729,1709,1684,1663,1650,1642,1635,1629,1625,1619,
-1610,1598,1591,1591,1591,1584,1572,1561,1557,1556,1554,1552,1556,1567,1577,1580,1581,1589,1607,1624,1634,
-1640,1654,1684,1723,1762,1791,1800,1784,1747,1717,1724,1780,1860,1925,1952,1940,1905,1866,1842,1856,1912,
-1979,2008,1976,1914,1855,1865,1912,1957,1966,1951,1961,2019,2094,2132,2114,2071,2047,2055,2076,2091,2102,
-2113,2124,2124,2119,2120,2137,2159,2174,2184,2198,2219,2237,2244,2247,2259,2281,2301,2314,2326,2348,2377,
-2401,2411,2416,2425,2440,2451,2458,2467,2487,2512,2534,2553,2574,2599,2619,2626,2624,2623,2625,2626,2625,
-2629,2643,2663,2677,2690,2721,2787,2879,2972,3046,3100,3138,3156,3143,3112,3096,3128,3206,3293,3350,3363,
-3351,3337,3329,3323,3310,3288,3263,3242,3226,3210,3186,3148,3098,3047,2998,2947,2888,2822,2759,2708,2668,
-2635,2619,2631,2676,2741,2804,2849,2872,2879,2878,2874,2868,2855,2824,2772,2707,2647,2604,2577,2555,2534,
-2521,2523,2536,2553,2568,2581,2596,2615,2640,2677,2723,2768,2804,2827,2851,2884,2920,2940,2930,2889,2824,
-2741,2641,2531,2421,2326,2253,2203,2175,2166,2169,2174,2176,2178,2181,2184,2183,2186,2201,2234,2271,2298,
-2318,2343,2377,2407,2419,2424,2463,2564,2717,2878,3008,3097,3158,3200,3220,3215,3191,3157,3114,3059,2994,
-2930,2875,2828,2783,2739,2701,2674,2656,2641,2628,2619,2614,2610,2604,2594,2582,2570,2558,2547,2536,2522,
-2506,2490,2483,2488,2499,2510,2522,2536,2551,2559,2563,2580,2625,2684,2718,2706,2666,2638,2639,2639,2599,
-2518,2435,2387,2368,2345,2300,2247,2210,2189,2163,2120,2069,2029,2004,1985,1968,1954,1945,1935,1918,1900,
-1891,1895,1901,1900,1894,1887,1881,1867,1843,1816,1795,1777,1755,1724,1694,1673,1660,1642,1615,1586,1561,
-1541,1518,1489,1460,1436,1414,1389,1359,1332,1310,1289,1263,1230,1196,1164,1134,1102,1070,1043,1021,999,
-974,945,916,888,856,822,789,764,745,726,705,681,658,635,610,582,552,523,494,463,428,
-388,350,314,279,242,199,152,105,60,18,-24,-68,-115,-165,-218,-273,-327,-377,-417,-453,-494,
--550,-617,-682,-731,-760,-780,-804,-836,-872,-906,-936,-965,-998,-1032,-1065,-1101,-1144,-1199,-1265,-1330,-1390,
--1443,-1495,-1547,-1599,-1648,-1696,-1745,-1798,-1852,-1903,-1954,-2005,-2054,-2099,-2140,-2183,-2231,-2282,-2330,-2371,-2407,
--2446,-2489,-2535,-2581,-2628,-2675,-2722,-2766,-2804,-2838,-2868,-2897,-2929,-2968,-3013,-3054,-3087,-3117,-3153,-3198,-3239,
--3261,-3265,-3268,-3284,-3314,-3346,-3377,-3423,-3502,-3604,-3695,-3743,-3744,-3727,-3725,-3755,-3811,-3878,-3942,-3992,-4024,
--4042,-4053,-4065,-4076,-4084,-4088,-4090,-4094,-4098,-4092,-4070,-4036,-4003,-3980,-3972,-3975,-3985,-3998,-4006,-3998,-3962,
--3897,-3817,-3740,-3681,-3644,-3630,-3640,-3673,-3716,-3748,-3754,-3747,-3749,-3773,-3802,-3806,-3774,-3717,-3652,-3571,-3465,
--3349,-3270,-3258,-3289,-3287,-3198,-3037,-2879,-2786,-2761,-2760,-2748,-2727,-2719,-2737,-2770,-2803,-2833,-2862,-2892,-2921,
--2946,-2962,-2966,-2952,-2925,-2901,-2893,-2900,-2906,-2895,-2871,-2847,-2831,-2816,-2790,-2748,-2698,-2647,-2597,-2541,-2480,
--2421,-2379,-2361,-2362,-2369,-2372,-2372,-2374,-2379,-2383,-2381,-2382,-2393,-2413,-2421,-2393,-2327,-2246,-2179,-2142,-2122,
--2099,-2056,-1988,-1898,-1793,-1689,-1604,-1548,-1514,-1483,-1444,-1398,-1351,-1301,-1241,-1167,-1082,-990,-888,-776,-657,
--543,-441,-343,-243,-145,-64,-17,2,17,56,135,253,385,498,565,583,570,556,557,570,584,
-592,600,614,634,656,680,708,742,784,834,889,947,1001,1049,1093,1142,1201,1269,1338,1406,1470,
-1529,1582,1636,1702,1782,1866,1938,1993,2046,2115,2203,2296,2382,2456,2516,2552,2550,2510,2454,2409,2387,
-2379,2363,2317,2223,2078,1908,1765,1696,1706,1759,1808,1840,1865,1891,1905,1899,1903,1961,2079,2198,2241,
-2185,2090,2035,2052,2110,2159,2183,2195,2205,2212,2218,2244,2312,2413,2509,2565,2581,2586,2603,2631,2656,
-2676,2705,2748,2798,2837,2854,2857,2855,2850,2840,2828,2828,2850,2893,2936,2953,2936,2906,2905,2966,3081,
-3206,3287,3302,3278,3260,3270,3300,3329,3356,3398,3461,3529,3574,3589,3596,3622,3671,3723,3756,3771,3785,
-3807,3832,3847,3853,3862,3884,3915,3938,3946,3940,3934,3940,3958,3983,4009,4034,4060,4086,4102,4100,4086,
-4077,4095,4140,4193,4225,4227,4208,4187,4167,4134,4065,3931,3702,3361,2922,2452,2047,1794,1731,1833,2032,
-2254,2441,2569,2648,2705,2758,2804,2827,2819,2796,2772,2747,2702,2633,2559,2503,2461,2402,2308,2209,2157,
-2174,2224,2239,2177,2057,1932,1846,1809,1800,1791,1767,1726,1681,1643,1617,1597,1569,1531,1487,1445,1404,
-1358,1307,1259,1222,1193,1161,1120,1078,1044,1019,993,959,921,886,858,834,807,779,751,727,706,
-687,671,657,640,616,585,553,522,490,456,420,386,357,329,298,264,229,202,182,169,156,
-139,118,96,74,56,41,26,8,-12,-33,-54,-74,-92,-110,-126,-144,-164,-184,-203,-220,-233,
--242,-249,-257,-269,-289,-313,-331,-342,-348,-356,-368,-382,-396,-409,-426,-446,-468,-492,-519,-554,-592,
--629,-659,-685,-710,-736,-761,-782,-801,-820,-840,-861,-880,-898,-914,-928,-939,-949,-959,-968,-975,-979,
--981,-986,-994,-1005,-1017,-1030,-1044,-1056,-1063,-1065,-1065,-1067,-1071,-1075,-1079,-1085,-1093,-1104,-1117,-1130,-1144,
--1156,-1167,-1177,-1186,-1194,-1197,-1197,-1193,-1188,-1185,-1182,-1180,-1179,-1178,-1176,-1170,-1163,-1158,-1155,-1154,-1151,
--1146,-1141,-1136,-1131,-1126,-1123,-1122,-1120,-1118,-1117,-1118,-1121,-1117,-1104,-1089,-1088,-1102,-1121,-1124,-1108,-1088,
--1083,-1098,-1121,-1140,-1149,-1154,-1159,-1162,-1159,-1153,-1149,-1151,-1155,-1155,-1147,-1137,-1131,-1130,-1133,-1134,-1134,
--1132,-1130,-1129,-1128,-1125,-1122,-1120,-1120,-1121,-1120,-1119,-1118,-1118,-1116,-1111,-1104,-1099,-1095,-1090,-1083,-1075,
--1069,-1064,-1056,-1042,-1025,-1011,-1003,-999,-996,-994,-994,-996,-995,-986,-973,-961,-953,-949,-943,-932,-920,
--910,-904,-901,-896,-890,-880,-868,-854,-841,-832,-828,-824,-818,-808,-796,-786,-778,-769,-761,-753,-746,
--739,-730,-719,-708,-699,-690,-679,-664,-650,-639,-633,-628,-621,-614,-607,-601,-596,-590,-585,-581,-578,
--573,-565,-557,-551,-545,-537,-526,-513,-501,-491,-483,-475,-468,-457,-443,-423,-401,-380,-361,-343,-327,
--313,-302,-293,-283,-270,-255,-240,-224,-210,-201,-196,-193,-186,-177,-169,-165,-163,-155,-141,-125,-113,
--103,-91,-72,-50,-29,-13,0,12,25,42,65,93,122,147,167,191,221,255,287,313,338,
-367,401,437,472,505,543,587,638,688,723,733,733,751,813,908,998,1040,1031,1000,986,1004,
-1039,1072,1094,1107,1115,1129,1159,1213,1285,1353,1398,1423,1442,1462,1457,1391,1248,1056,887,834,966,
-1285,1712,2111,2371,2478,2521,2614,2790,2975,3053,2962,2741,2492,2302,2201,2169,2167,2168,2168,2186,2243,
-2339,2440,2498,2489,2438,2392,2379,2382,2367,2325,2279,2251,2236,2205,2139,2054,1980,1933,1906,1880,1849,
-1814,1779,1743,1707,1682,1678,1691,1710,1723,1730,1733,1735,1736,1734,1730,1726,1720,1710,1696,1682,1667,
-1649,1626,1597,1568,1538,1505,1468,1433,1403,1378,1351,1315,1259,1179,1075,963,867,811,798,805,805,
-780,731,665,585,488,374,254,138,35,-51,-123,-181,-230,-275,-316,-352,-382,-406,-429,-454,-479,
--502,-522,-540,-556,-574,-594,-618,-645,-668,-684,-697,-713,-733,-753,-763,-762,-757,-756,-760,-763,-762,
--757,-753,-752,-751,-747,-736,-722,-704,-686,-665,-640,-612,-585,-563,-546,-525,-496,-458,-418,-383,-353,
--321,-284,-243,-200,-159,-123,-90,-58,-20,30,94,162,216,245,252,251,260,287,337,405,480,
-547,595,618,622,620,620,625,633,645,662,686,713,741,767,796,830,867,900,923,937,951,
-972,1001,1033,1062,1089,1116,1144,1172,1197,1222,1248,1275,1301,1326,1348,1369,1390,1414,1440,1468,1494,
-1515,1531,1549,1572,1599,1623,1641,1654,1667,1679,1689,1695,1701,1709,1717,1726,1738,1753,1769,1778,1776,
-1765,1754,1746,1734,1715,1693,1674,1664,1658,1652,1644,1637,1630,1622,1613,1607,1606,1604,1595,1581,1569,
-1563,1561,1558,1556,1561,1574,1584,1586,1585,1591,1605,1619,1627,1634,1656,1693,1734,1759,1765,1763,1766,
-1779,1798,1817,1827,1826,1821,1827,1852,1887,1910,1912,1906,1910,1919,1912,1882,1855,1834,1882,1947,1990,
-1986,1954,1942,1973,2025,2053,2045,2024,2021,2040,2063,2074,2077,2081,2088,2092,2092,2099,2115,2135,2149,
-2158,2171,2192,2211,2223,2234,2250,2271,2291,2306,2323,2349,2378,2398,2406,2411,2423,2439,2450,2456,2467,
-2489,2516,2536,2548,2561,2580,2598,2607,2607,2605,2608,2611,2609,2608,2614,2630,2650,2670,2698,2745,2811,
-2885,2961,3034,3099,3139,3141,3117,3100,3123,3185,3257,3305,3320,3312,3301,3293,3289,3284,3275,3261,3242,
-3217,3189,3159,3128,3097,3068,3035,2992,2937,2877,2823,2776,2731,2685,2649,2641,2675,2740,2810,2864,2891,
-2893,2879,2855,2824,2787,2743,2694,2648,2614,2593,2581,2569,2557,2551,2554,2565,2580,2597,2618,2643,2672,
-2710,2761,2819,2870,2898,2901,2897,2902,2916,2924,2912,2876,2819,2743,2650,2546,2444,2358,2293,2250,2227,
-2223,2230,2239,2242,2242,2242,2240,2238,2241,2258,2289,2323,2350,2371,2398,2432,2458,2466,2474,2517,2616,
-2753,2887,2992,3072,3144,3209,3252,3265,3252,3224,3187,3136,3073,3010,2958,2915,2870,2822,2778,2748,2730,
-2717,2705,2695,2690,2689,2685,2677,2666,2656,2648,2639,2626,2608,2590,2579,2579,2588,2595,2599,2607,2624,
-2647,2664,2671,2687,2726,2776,2803,2783,2728,2680,2659,2645,2603,2528,2452,2408,2394,2380,2343,2292,2245,
-2209,2176,2137,2099,2071,2051,2034,2015,1998,1988,1980,1969,1955,1947,1946,1947,1948,1947,1946,1941,1925,
-1899,1871,1851,1833,1809,1778,1749,1729,1714,1693,1663,1632,1607,1588,1565,1535,1505,1479,1457,1432,1404,
-1378,1358,1338,1309,1273,1237,1206,1178,1150,1119,1091,1066,1043,1019,992,963,933,900,864,831,803,
-782,764,744,722,700,677,650,621,591,564,538,510,478,443,409,375,341,301,256,208,164,
-123,83,40,-7,-59,-111,-162,-213,-264,-311,-353,-393,-438,-494,-558,-619,-666,-697,-720,-746,-779,
--817,-853,-886,-918,-951,-983,-1015,-1050,-1095,-1152,-1218,-1284,-1344,-1397,-1447,-1497,-1546,-1594,-1641,-1691,-1743,
--1794,-1845,-1896,-1946,-1993,-2037,-2077,-2119,-2166,-2217,-2266,-2309,-2346,-2383,-2426,-2472,-2520,-2567,-2615,-2666,-2719,
--2770,-2811,-2843,-2869,-2898,-2936,-2980,-3022,-3057,-3090,-3128,-3171,-3209,-3231,-3239,-3246,-3261,-3284,-3310,-3340,-3388,
--3462,-3551,-3628,-3669,-3673,-3661,-3659,-3684,-3738,-3812,-3892,-3961,-4010,-4038,-4053,-4064,-4075,-4083,-4088,-4091,-4095,
--4097,-4091,-4076,-4052,-4025,-4000,-3978,-3964,-3962,-3972,-3985,-3983,-3951,-3886,-3805,-3732,-3681,-3650,-3635,-3633,-3647,
--3675,-3701,-3713,-3716,-3729,-3761,-3797,-3807,-3777,-3718,-3647,-3563,-3459,-3348,-3268,-3248,-3267,-3263,-3185,-3043,-2901,
--2814,-2784,-2777,-2760,-2738,-2730,-2751,-2792,-2839,-2884,-2926,-2964,-2991,-3005,-3007,-2997,-2976,-2948,-2926,-2921,-2931,
--2942,-2942,-2929,-2910,-2890,-2864,-2826,-2777,-2726,-2679,-2634,-2587,-2537,-2495,-2475,-2478,-2497,-2518,-2532,-2542,-2551,
--2559,-2563,-2562,-2566,-2587,-2616,-2628,-2595,-2515,-2418,-2340,-2293,-2265,-2233,-2184,-2120,-2044,-1958,-1860,-1760,-1667,
--1586,-1513,-1445,-1381,-1324,-1273,-1219,-1156,-1082,-996,-896,-785,-672,-567,-472,-382,-290,-201,-130,-83,-54,
--25,21,92,185,287,379,441,468,470,465,466,474,480,485,495,518,550,585,620,657,702,
-754,810,864,915,962,1006,1050,1097,1154,1220,1292,1362,1425,1477,1523,1575,1643,1725,1805,1869,1919,
-1972,2042,2127,2218,2306,2391,2465,2508,2500,2446,2378,2328,2305,2288,2245,2156,2020,1859,1709,1613,1596,
-1642,1707,1753,1777,1798,1823,1840,1837,1832,1860,1930,2002,2028,2000,1962,1960,1999,2047,2076,2087,2096,
-2106,2109,2111,2139,2215,2324,2422,2475,2489,2494,2513,2543,2570,2595,2630,2680,2733,2770,2786,2788,2788,
-2787,2782,2773,2766,2773,2798,2837,2872,2886,2878,2873,2907,2995,3111,3204,3240,3231,3216,3224,3248,3269,
-3281,3303,3350,3414,3467,3497,3520,3562,3628,3701,3760,3800,3831,3856,3868,3858,3835,3819,3828,3861,3900,
-3927,3937,3938,3941,3949,3964,3984,4009,4037,4061,4070,4060,4041,4037,4062,4108,4148,4162,4150,4131,4114,
-4085,4020,3898,3708,3439,3081,2655,2224,1887,1719,1736,1887,2095,2296,2457,2572,2649,2703,2745,2776,2791,
-2785,2765,2739,2707,2660,2595,2528,2474,2430,2373,2288,2195,2137,2136,2170,2183,2134,2028,1906,1811,1765,
-1755,1753,1734,1695,1648,1614,1598,1587,1564,1523,1473,1426,1383,1338,1289,1245,1212,1185,1152,1109,1063,
-1026,1000,975,943,905,869,839,813,786,757,731,709,690,673,658,645,628,605,575,541,509,
-477,445,411,377,345,315,285,255,226,201,179,162,146,130,113,95,76,59,43,26,7,
--15,-39,-64,-88,-112,-134,-154,-172,-189,-205,-221,-237,-250,-261,-268,-275,-285,-301,-320,-338,-351,
--362,-373,-386,-400,-415,-432,-451,-471,-489,-505,-528,-560,-599,-638,-670,-696,-719,-742,-763,-782,-800,
--820,-842,-864,-883,-899,-913,-926,-937,-948,-958,-968,-977,-983,-987,-991,-995,-1002,-1014,-1030,-1048,-1062,
--1067,-1066,-1062,-1061,-1065,-1071,-1078,-1086,-1096,-1107,-1120,-1134,-1146,-1158,-1167,-1175,-1183,-1189,-1193,-1195,-1193,
--1190,-1187,-1185,-1183,-1181,-1175,-1166,-1155,-1146,-1140,-1136,-1132,-1127,-1123,-1122,-1123,-1121,-1116,-1111,-1108,-1107,
--1106,-1106,-1106,-1106,-1102,-1095,-1088,-1092,-1106,-1119,-1117,-1100,-1084,-1085,-1106,-1133,-1151,-1158,-1161,-1167,-1173,
--1175,-1172,-1171,-1178,-1188,-1194,-1187,-1170,-1152,-1139,-1135,-1136,-1137,-1138,-1140,-1141,-1141,-1137,-1129,-1123,-1121,
--1124,-1128,-1131,-1133,-1132,-1131,-1127,-1122,-1117,-1111,-1103,-1094,-1087,-1082,-1080,-1073,-1059,-1040,-1022,-1012,-1008,
--1006,-1006,-1007,-1008,-1006,-998,-985,-971,-959,-950,-939,-928,-917,-910,-905,-901,-896,-891,-884,-874,-861,
--848,-839,-836,-832,-826,-815,-804,-795,-787,-776,-764,-754,-749,-744,-736,-722,-708,-698,-691,-683,-671,
--657,-645,-638,-633,-626,-618,-610,-602,-595,-588,-584,-582,-580,-574,-564,-553,-547,-544,-539,-530,-516,
--501,-491,-483,-477,-469,-457,-441,-420,-400,-381,-365,-350,-337,-324,-313,-302,-290,-278,-265,-252,-238,
--224,-214,-209,-207,-203,-195,-187,-181,-175,-165,-151,-136,-124,-116,-104,-86,-63,-40,-21,-5,6,
-18,32,54,82,112,139,163,190,222,254,282,306,331,366,407,448,483,515,555,611,680,
-746,784,787,774,787,855,968,1074,1124,1106,1053,1010,1000,1018,1046,1072,1096,1120,1152,1197,1258,
-1325,1379,1411,1428,1439,1439,1403,1305,1147,970,843,847,1034,1391,1825,2193,2399,2460,2495,2617,2831,
-3025,3071,2938,2706,2489,2350,2280,2239,2207,2183,2176,2192,2234,2302,2376,2421,2412,2363,2313,2290,2286,
-2273,2241,2205,2185,2175,2150,2094,2023,1961,1922,1895,1867,1833,1798,1766,1737,1711,1695,1694,1703,1711,
-1714,1713,1713,1711,1706,1698,1691,1689,1687,1681,1669,1657,1645,1631,1610,1582,1554,1527,1500,1469,1437,
-1405,1373,1334,1283,1215,1126,1023,921,846,815,822,835,821,766,683,591,499,404,299,189,85,
--4,-78,-139,-194,-247,-297,-343,-381,-411,-437,-463,-489,-510,-526,-538,-551,-564,-575,-588,-607,-633,
--661,-683,-696,-708,-724,-743,-756,-759,-756,-753,-754,-755,-751,-744,-741,-743,-748,-750,-743,-727,-705,
--680,-654,-626,-597,-572,-554,-542,-529,-508,-473,-431,-390,-355,-325,-295,-260,-219,-175,-131,-91,-57,
--23,21,81,153,219,261,272,261,248,254,289,352,431,511,575,616,635,640,641,645,653,
-666,688,716,749,780,807,833,860,892,924,952,975,995,1017,1041,1065,1088,1111,1138,1168,1199,
-1227,1252,1275,1299,1325,1353,1381,1404,1425,1447,1475,1506,1535,1555,1569,1586,1611,1640,1663,1678,1687,
-1697,1708,1716,1721,1724,1730,1737,1746,1756,1769,1783,1791,1787,1777,1768,1764,1758,1744,1724,1705,1692,
-1682,1671,1658,1648,1640,1632,1624,1617,1613,1608,1599,1588,1580,1579,1581,1580,1579,1584,1593,1600,1600,
-1597,1600,1612,1623,1628,1635,1655,1688,1713,1712,1693,1686,1719,1790,1862,1890,1854,1776,1704,1690,1747,
-1844,1926,1957,1939,1900,1864,1837,1822,1834,1837,1900,1963,1995,1983,1951,1933,1948,1976,1992,1989,1988,
-2004,2032,2052,2057,2055,2059,2066,2071,2072,2077,2092,2111,2125,2133,2145,2163,2184,2202,2217,2235,2256,
-2277,2297,2320,2347,2372,2386,2393,2403,2422,2443,2457,2463,2475,2498,2526,2545,2554,2561,2573,2587,2592,
-2589,2587,2591,2596,2594,2588,2587,2598,2619,2644,2671,2701,2741,2793,2862,2947,3032,3095,3118,3110,3101,
-3117,3162,3214,3253,3269,3270,3265,3260,3254,3251,3246,3234,3210,3174,3134,3097,3069,3052,3041,3026,2998,
-2957,2909,2864,2825,2785,2741,2703,2692,2720,2779,2846,2894,2911,2899,2867,2823,2775,2726,2680,2641,2613,
-2596,2586,2578,2571,2567,2570,2579,2591,2605,2626,2656,2693,2736,2785,2846,2910,2961,2979,2966,2940,2921,
-2914,2908,2890,2855,2803,2733,2646,2550,2459,2385,2332,2297,2280,2280,2291,2302,2307,2305,2300,2296,2294,
-2301,2321,2352,2382,2404,2423,2448,2478,2499,2505,2518,2569,2671,2800,2914,2997,3065,3137,3214,3274,3301,
-3298,3279,3247,3201,3142,3085,3037,2996,2951,2900,2853,2821,2805,2793,2779,2767,2761,2761,2762,2759,2753,
-2748,2744,2736,2718,2694,2674,2668,2675,2687,2693,2694,2702,2724,2753,2773,2778,2783,2805,2838,2853,2828,
-2776,2729,2708,2692,2649,2573,2492,2439,2418,2405,2374,2327,2278,2237,2200,2164,2132,2108,2091,2074,2057,
-2042,2034,2029,2020,2009,2001,1998,1999,2001,2003,2003,1996,1978,1951,1925,1905,1888,1866,1836,1807,1786,
-1768,1745,1714,1683,1658,1637,1613,1582,1550,1523,1500,1476,1450,1426,1404,1381,1350,1313,1278,1249,1224,
-1196,1164,1133,1106,1084,1061,1036,1006,973,939,904,872,845,823,804,786,768,746,721,691,661,
-633,609,587,562,534,504,472,439,401,358,312,266,225,187,147,102,50,-4,-58,-107,-151,
--196,-242,-289,-338,-390,-445,-499,-548,-588,-621,-651,-686,-725,-766,-806,-842,-875,-906,-936,-967,-1005,
--1051,-1108,-1172,-1236,-1296,-1350,-1401,-1449,-1496,-1543,-1591,-1640,-1689,-1738,-1787,-1838,-1888,-1935,-1977,-2017,-2059,
--2105,-2154,-2201,-2242,-2280,-2319,-2364,-2414,-2466,-2514,-2560,-2608,-2661,-2715,-2766,-2807,-2840,-2875,-2916,-2961,-3003,
--3039,-3072,-3108,-3145,-3178,-3199,-3213,-3228,-3248,-3271,-3295,-3321,-3360,-3417,-3487,-3555,-3609,-3644,-3662,-3671,-3683,
--3711,-3759,-3824,-3891,-3947,-3989,-4022,-4050,-4073,-4089,-4096,-4098,-4097,-4094,-4087,-4077,-4064,-4049,-4029,-4006,-3985,
--3972,-3973,-3980,-3979,-3951,-3892,-3814,-3739,-3685,-3652,-3634,-3627,-3634,-3654,-3679,-3698,-3712,-3733,-3767,-3802,-3813,
--3786,-3729,-3653,-3563,-3458,-3350,-3274,-3251,-3263,-3256,-3185,-3061,-2936,-2856,-2825,-2812,-2793,-2772,-2768,-2792,-2838,
--2890,-2942,-2988,-3024,-3044,-3047,-3038,-3022,-3004,-2987,-2979,-2981,-2992,-2999,-2995,-2981,-2962,-2939,-2906,-2861,-2808,
--2759,-2720,-2691,-2666,-2645,-2632,-2635,-2656,-2686,-2715,-2737,-2752,-2763,-2769,-2767,-2759,-2755,-2767,-2788,-2795,-2764,
--2691,-2597,-2510,-2445,-2394,-2343,-2288,-2231,-2175,-2110,-2029,-1929,-1819,-1708,-1600,-1498,-1406,-1327,-1261,-1201,-1139,
--1071,-992,-902,-801,-695,-593,-500,-416,-339,-271,-215,-165,-114,-56,4,61,113,168,227,287,333,
-359,369,371,372,375,383,402,435,477,522,567,615,670,728,784,836,883,928,973,1018,1064,
-1115,1176,1244,1312,1370,1416,1457,1507,1576,1657,1736,1801,1855,1913,1980,2055,2132,2214,2302,2386,2438,
-2435,2384,2318,2267,2230,2178,2083,1944,1784,1640,1542,1508,1535,1598,1658,1693,1708,1724,1750,1772,1779,
-1778,1792,1830,1872,1892,1890,1892,1916,1952,1977,1985,1989,2001,2014,2014,2012,2041,2121,2233,2330,2381,
-2397,2408,2432,2463,2490,2518,2560,2616,2671,2705,2717,2717,2717,2721,2725,2725,2719,2715,2720,2744,2782,
-2819,2836,2838,2854,2912,3007,3100,3155,3170,3174,3192,3220,3235,3232,3231,3254,3299,3349,3388,3428,3487,
-3572,3667,3754,3825,3880,3919,3931,3913,3875,3840,3826,3837,3862,3887,3906,3917,3924,3929,3937,3951,3974,
-3999,4018,4022,4011,3999,4005,4034,4071,4092,4088,4071,4056,4037,3986,3872,3689,3446,3149,2798,2409,2040,
-1778,1689,1769,1952,2158,2334,2470,2572,2647,2700,2733,2752,2757,2747,2725,2697,2662,2618,2563,2502,2446,
-2393,2332,2255,2171,2107,2078,2077,2072,2036,1963,1873,1793,1742,1722,1714,1697,1663,1622,1591,1579,1572,
-1552,1510,1457,1406,1361,1318,1275,1238,1211,1188,1156,1110,1058,1015,984,957,927,891,855,824,797,
-770,743,717,694,673,654,639,626,611,591,562,528,493,460,429,400,370,338,305,272,243,
-218,197,177,157,138,122,106,90,73,58,43,26,5,-20,-47,-74,-101,-128,-155,-179,-199,
--215,-229,-242,-256,-269,-279,-287,-293,-301,-315,-333,-353,-371,-388,-403,-418,-430,-443,-459,-479,-497,
--513,-526,-544,-572,-607,-645,-677,-704,-728,-749,-767,-783,-799,-819,-843,-867,-886,-899,-910,-921,-932,
--944,-955,-965,-974,-981,-987,-992,-995,-1001,-1011,-1026,-1043,-1055,-1060,-1058,-1055,-1056,-1061,-1069,-1080,-1091,
--1104,-1116,-1127,-1136,-1144,-1152,-1159,-1166,-1173,-1180,-1186,-1189,-1188,-1185,-1182,-1183,-1185,-1183,-1174,-1159,-1143,
--1134,-1130,-1127,-1119,-1109,-1104,-1106,-1113,-1116,-1112,-1106,-1103,-1105,-1106,-1104,-1099,-1094,-1092,-1091,-1092,-1098,
--1108,-1116,-1114,-1105,-1100,-1108,-1128,-1146,-1155,-1155,-1155,-1163,-1174,-1181,-1183,-1184,-1193,-1208,-1223,-1224,-1210,
--1186,-1163,-1150,-1147,-1149,-1152,-1155,-1157,-1157,-1151,-1140,-1129,-1124,-1126,-1131,-1135,-1136,-1134,-1132,-1130,-1128,
--1124,-1119,-1112,-1103,-1095,-1091,-1089,-1085,-1074,-1056,-1037,-1022,-1015,-1014,-1015,-1018,-1019,-1016,-1008,-995,-980,
--965,-951,-936,-924,-917,-913,-909,-903,-896,-891,-887,-881,-870,-858,-849,-843,-837,-827,-815,-804,-796,
--787,-774,-759,-748,-745,-744,-738,-723,-706,-694,-689,-684,-673,-659,-647,-638,-632,-625,-618,-610,-603,
--594,-585,-580,-580,-580,-576,-565,-553,-544,-540,-535,-524,-509,-494,-483,-476,-469,-459,-446,-431,-416,
--400,-384,-368,-354,-343,-333,-324,-312,-298,-285,-273,-262,-249,-236,-226,-223,-223,-222,-216,-205,-194,
--182,-170,-158,-146,-136,-127,-115,-98,-79,-59,-39,-21,-6,7,24,47,77,107,135,162,192,
-225,256,281,302,329,367,412,455,487,513,545,594,659,722,759,760,744,751,808,908,1005,
-1052,1040,995,959,955,978,1015,1056,1097,1141,1189,1242,1297,1347,1381,1402,1414,1418,1398,1331,1209,
-1053,911,844,909,1139,1507,1915,2233,2389,2432,2500,2691,2967,3179,3195,3017,2763,2559,2442,2372,2303,
-2232,2183,2169,2178,2200,2235,2284,2322,2323,2282,2229,2194,2184,2180,2166,2147,2133,2120,2093,2045,1988,
-1940,1905,1877,1846,1814,1787,1765,1745,1726,1713,1710,1711,1710,1706,1701,1698,1690,1675,1658,1649,1651,
-1655,1652,1642,1630,1620,1607,1584,1556,1530,1509,1489,1462,1426,1382,1334,1278,1213,1136,1049,960,883,
-838,830,843,841,796,705,592,485,392,305,214,118,28,-48,-112,-170,-227,-285,-341,-391,-430,
--459,-485,-510,-533,-550,-560,-568,-578,-589,-598,-607,-622,-645,-672,-693,-703,-709,-719,-737,-753,-761,
--760,-754,-749,-744,-737,-730,-728,-733,-742,-749,-745,-731,-709,-682,-653,-624,-595,-570,-550,-536,-523,
--503,-471,-430,-388,-352,-324,-298,-267,-227,-180,-130,-83,-45,-12,23,71,132,198,251,282,289,
-285,282,291,316,357,412,474,532,576,605,623,639,659,684,713,747,784,821,855,882,904,
-925,949,978,1009,1040,1067,1090,1109,1129,1153,1182,1214,1247,1277,1302,1323,1344,1367,1395,1423,1447,
-1466,1484,1509,1539,1568,1587,1600,1616,1641,1670,1693,1707,1717,1728,1741,1749,1752,1753,1757,1763,1768,
-1775,1786,1802,1812,1811,1801,1791,1787,1784,1773,1754,1733,1716,1703,1689,1676,1665,1658,1651,1642,1632,
-1624,1617,1610,1602,1598,1601,1606,1608,1607,1608,1612,1615,1613,1610,1616,1629,1640,1643,1645,1659,1682,
-1693,1677,1647,1642,1691,1784,1867,1887,1826,1720,1633,1620,1690,1805,1905,1947,1928,1877,1826,1797,1800,
-1837,1846,1903,1947,1960,1941,1914,1905,1917,1938,1951,1959,1973,1999,2025,2038,2037,2037,2045,2055,2059,
-2057,2061,2075,2095,2110,2117,2125,2141,2161,2181,2198,2216,2238,2262,2288,2314,2339,2359,2370,2379,2396,
-2421,2447,2464,2473,2486,2508,2534,2553,2562,2568,2576,2583,2583,2577,2572,2573,2575,2573,2565,2560,2567,
-2588,2615,2641,2664,2689,2726,2785,2869,2962,3038,3079,3090,3092,3107,3140,3180,3212,3232,3239,3236,3225,
-3211,3199,3189,3173,3144,3104,3059,3020,2994,2982,2980,2981,2974,2953,2917,2874,2830,2786,2747,2724,2728,
-2764,2821,2875,2905,2903,2873,2828,2776,2726,2682,2644,2617,2600,2589,2580,2572,2569,2576,2591,2609,2623,
-2636,2658,2695,2743,2796,2851,2912,2971,3013,3025,3006,2975,2949,2931,2913,2884,2841,2786,2718,2636,2550,
-2472,2412,2371,2346,2335,2337,2349,2361,2367,2364,2357,2352,2352,2363,2387,2417,2442,2459,2473,2495,2520,
-2536,2541,2560,2624,2738,2869,2977,3047,3100,3162,3233,3293,3325,3329,3317,3293,3253,3202,3150,3106,3065,
-3019,2967,2921,2892,2878,2867,2853,2840,2836,2840,2846,2848,2847,2845,2842,2831,2809,2782,2762,2758,2769,
-2782,2789,2794,2806,2833,2862,2876,2870,2858,2860,2876,2884,2864,2825,2792,2779,2766,2723,2642,2550,2481,
-2446,2427,2401,2361,2315,2271,2232,2195,2161,2136,2118,2105,2094,2086,2081,2075,2065,2053,2047,2047,2052,
-2056,2057,2055,2046,2028,2003,1979,1960,1944,1923,1896,1868,1845,1824,1800,1770,1739,1712,1686,1657,1624,
-1592,1565,1542,1518,1493,1468,1445,1419,1387,1353,1322,1296,1271,1241,1206,1171,1143,1122,1100,1074,1043,
-1009,975,944,916,890,868,849,832,814,792,764,734,704,680,659,639,616,590,562,531,497,
-458,414,370,327,287,248,207,160,107,50,-3,-50,-91,-131,-178,-232,-293,-352,-404,-448,-485,
--518,-552,-589,-630,-673,-715,-756,-793,-828,-859,-891,-926,-967,-1017,-1072,-1131,-1191,-1250,-1306,-1357,-1405,
--1452,-1499,-1547,-1593,-1638,-1683,-1730,-1781,-1830,-1877,-1920,-1964,-2010,-2059,-2109,-2155,-2195,-2231,-2267,-2309,-2359,
--2412,-2463,-2509,-2554,-2602,-2655,-2709,-2757,-2798,-2836,-2877,-2919,-2958,-2993,-3027,-3062,-3097,-3127,-3148,-3166,-3188,
--3214,-3243,-3271,-3298,-3329,-3367,-3414,-3473,-3541,-3611,-3671,-3708,-3723,-3730,-3746,-3778,-3822,-3873,-3926,-3981,-4034,
--4076,-4102,-4112,-4114,-4111,-4105,-4097,-4086,-4076,-4065,-4052,-4035,-4016,-4000,-3990,-3988,-3984,-3964,-3917,-3844,-3763,
--3693,-3647,-3623,-3617,-3625,-3644,-3669,-3693,-3716,-3744,-3780,-3814,-3827,-3807,-3755,-3679,-3585,-3477,-3372,-3298,-3272,
--3278,-3269,-3210,-3108,-3007,-2943,-2919,-2909,-2892,-2874,-2870,-2891,-2929,-2974,-3016,-3052,-3078,-3091,-3091,-3082,-3074,
--3070,-3070,-3076,-3083,-3087,-3079,-3060,-3035,-3012,-2990,-2961,-2921,-2875,-2836,-2813,-2806,-2808,-2814,-2823,-2838,-2861,
--2888,-2915,-2936,-2951,-2960,-2960,-2951,-2933,-2916,-2908,-2909,-2906,-2883,-2828,-2749,-2660,-2574,-2493,-2419,-2357,-2309,
--2268,-2222,-2156,-2068,-1963,-1846,-1723,-1599,-1482,-1379,-1292,-1215,-1145,-1075,-1004,-926,-836,-735,-632,-536,-456,
--395,-349,-306,-251,-176,-91,-17,25,40,52,84,142,209,260,285,289,286,289,304,333,374,
-421,470,521,575,633,691,744,793,841,889,936,981,1024,1070,1124,1186,1247,1301,1345,1387,1438,
-1504,1582,1660,1732,1798,1863,1928,1990,2052,2121,2204,2284,2335,2335,2296,2244,2196,2138,2039,1888,1710,
-1554,1455,1422,1444,1497,1558,1606,1632,1644,1656,1677,1699,1713,1724,1743,1774,1807,1830,1845,1862,1884,
-1901,1904,1901,1907,1926,1938,1931,1922,1948,2026,2135,2229,2283,2308,2328,2357,2385,2410,2440,2487,2548,
-2603,2635,2645,2645,2648,2656,2667,2676,2678,2671,2661,2666,2695,2738,2772,2787,2799,2836,2907,2989,3051,
-3087,3116,3154,3195,3219,3216,3202,3202,3221,3252,3286,3329,3394,3484,3587,3690,3783,3862,3922,3951,3948,
-3923,3892,3867,3851,3845,3847,3857,3869,3879,3886,3893,3905,3923,3941,3953,3955,3953,3956,3973,3999,4022,
-4028,4018,4005,3992,3957,3867,3697,3458,3176,2868,2539,2200,1902,1718,1698,1823,2022,2217,2369,2481,2568,
-2638,2689,2718,2728,2724,2708,2680,2647,2611,2570,2521,2466,2408,2350,2290,2221,2148,2078,2023,1985,1959,
-1935,1904,1858,1802,1746,1704,1677,1658,1634,1604,1577,1562,1550,1530,1491,1440,1389,1343,1303,1265,1234,
-1211,1192,1163,1118,1063,1013,975,945,916,882,848,815,786,759,732,705,679,655,632,614,599,
-587,571,549,518,481,445,413,387,362,333,299,262,230,206,187,168,148,128,110,94,79,
-64,49,35,19,-1,-28,-56,-84,-113,-142,-172,-200,-223,-239,-251,-263,-276,-289,-299,-304,-308,
--314,-327,-346,-369,-393,-415,-435,-451,-463,-473,-485,-501,-519,-536,-552,-569,-593,-622,-652,-681,-708,
--732,-753,-771,-785,-800,-818,-840,-862,-880,-893,-903,-914,-926,-940,-952,-962,-970,-978,-984,-989,-994,
--999,-1008,-1020,-1033,-1042,-1046,-1047,-1048,-1052,-1059,-1068,-1079,-1093,-1107,-1120,-1128,-1132,-1135,-1139,-1143,-1150,
--1158,-1167,-1173,-1173,-1166,-1156,-1149,-1152,-1159,-1162,-1155,-1138,-1122,-1117,-1120,-1122,-1116,-1103,-1094,-1096,-1106,
--1112,-1110,-1104,-1104,-1108,-1111,-1106,-1097,-1090,-1091,-1095,-1100,-1103,-1106,-1109,-1111,-1113,-1118,-1127,-1139,-1145,
--1143,-1138,-1138,-1149,-1167,-1182,-1188,-1187,-1188,-1197,-1213,-1225,-1224,-1209,-1188,-1172,-1166,-1167,-1169,-1168,-1166,
--1164,-1160,-1152,-1144,-1138,-1137,-1138,-1137,-1133,-1128,-1125,-1124,-1124,-1122,-1119,-1114,-1107,-1101,-1097,-1096,-1094,
--1085,-1069,-1050,-1032,-1022,-1019,-1022,-1025,-1027,-1023,-1014,-1001,-987,-972,-957,-942,-930,-923,-921,-918,-911,
--902,-897,-894,-890,-882,-870,-859,-849,-838,-825,-811,-801,-794,-785,-771,-754,-743,-741,-742,-737,-722,
--705,-692,-685,-677,-666,-651,-638,-629,-623,-617,-611,-605,-598,-589,-579,-573,-572,-574,-572,-563,-552,
--543,-537,-528,-514,-496,-481,-470,-463,-454,-442,-428,-417,-409,-400,-387,-370,-353,-341,-335,-330,-321,
--307,-291,-277,-265,-252,-240,-231,-228,-231,-233,-230,-220,-206,-192,-180,-170,-161,-151,-139,-124,-109,
--93,-76,-57,-38,-20,-3,15,41,71,101,128,155,186,221,254,279,301,329,368,413,455,
-484,504,525,557,603,652,686,696,691,696,733,799,866,904,907,895,895,919,963,1015,1067,
-1119,1172,1224,1274,1316,1346,1365,1377,1384,1378,1336,1243,1110,973,883,884,1009,1267,1622,1979,2235,
-2348,2398,2521,2787,3120,3342,3331,3119,2853,2657,2549,2465,2360,2250,2178,2158,2163,2168,2176,2200,2229,
-2234,2200,2148,2110,2101,2109,2115,2110,2096,2074,2040,1995,1948,1909,1877,1848,1818,1795,1780,1769,1754,
-1737,1725,1720,1718,1712,1702,1694,1687,1674,1653,1631,1622,1625,1631,1628,1618,1607,1598,1582,1555,1522,
-1496,1479,1463,1435,1389,1331,1268,1202,1131,1055,980,916,871,854,856,856,823,740,618,488,378,
-290,213,134,52,-26,-96,-159,-220,-282,-344,-400,-447,-484,-510,-532,-553,-571,-585,-594,-600,-608,
--617,-625,-634,-648,-670,-693,-709,-713,-713,-719,-735,-752,-763,-762,-754,-744,-734,-726,-720,-720,-726,
--734,-739,-737,-727,-709,-686,-660,-633,-605,-578,-553,-531,-511,-489,-461,-426,-389,-355,-325,-297,-264,
--224,-178,-129,-82,-41,-5,27,64,109,162,218,271,317,351,371,375,368,363,377,415,467,
-515,550,575,603,640,681,721,758,796,841,888,927,953,968,983,1008,1044,1084,1118,1143,1165,
-1188,1216,1249,1281,1311,1339,1364,1387,1406,1427,1450,1475,1496,1511,1525,1544,1570,1596,1614,1625,1640,
-1662,1689,1712,1729,1744,1760,1774,1782,1784,1786,1792,1799,1804,1808,1818,1834,1846,1843,1828,1811,1800,
-1792,1780,1761,1742,1728,1718,1708,1697,1689,1684,1677,1666,1653,1643,1637,1632,1625,1622,1623,1628,1630,
-1628,1625,1624,1623,1621,1621,1629,1643,1653,1654,1654,1665,1688,1705,1701,1685,1686,1726,1789,1833,1822,
-1756,1674,1623,1630,1691,1776,1849,1884,1879,1846,1810,1791,1803,1846,1845,1888,1913,1909,1886,1868,1870,
-1891,1917,1937,1954,1976,1999,2015,2018,2016,2020,2033,2045,2047,2045,2049,2065,2086,2101,2107,2114,2128,
-2148,2167,2184,2201,2224,2251,2280,2306,2329,2346,2360,2375,2395,2421,2446,2466,2481,2498,2518,2538,2553,
-2562,2569,2578,2583,2581,2573,2565,2560,2557,2552,2545,2543,2551,2570,2595,2623,2649,2674,2705,2753,2823,
-2906,2982,3035,3064,3082,3103,3131,3162,3189,3208,3214,3207,3187,3162,3139,3120,3099,3070,3036,3002,2973,
-2952,2941,2940,2949,2958,2952,2921,2864,2795,2734,2695,2690,2719,2772,2828,2868,2878,2859,2820,2775,2731,
-2694,2662,2635,2614,2599,2589,2580,2575,2578,2594,2619,2642,2656,2667,2689,2729,2783,2841,2896,2946,2990,
-3020,3028,3015,2995,2975,2957,2930,2891,2840,2779,2710,2634,2556,2489,2441,2412,2396,2390,2394,2404,2415,
-2419,2416,2410,2408,2412,2427,2450,2476,2496,2509,2522,2542,2565,2579,2587,2612,2686,2809,2946,3055,3120,
-3161,3204,3256,3304,3331,3339,3334,3319,3289,3246,3201,3160,3121,3077,3030,2990,2966,2954,2944,2933,2925,
-2925,2932,2939,2940,2938,2935,2931,2919,2897,2873,2855,2851,2860,2872,2881,2891,2908,2933,2953,2955,2935,
-2911,2902,2911,2920,2910,2882,2854,2838,2819,2773,2690,2594,2515,2471,2449,2427,2394,2352,2307,2264,2224,
-2189,2162,2145,2136,2131,2129,2126,2118,2106,2095,2092,2097,2105,2110,2108,2101,2091,2077,2058,2037,2017,
-1999,1979,1955,1929,1903,1880,1855,1826,1795,1764,1731,1698,1665,1635,1608,1584,1559,1533,1508,1482,1455,
-1425,1396,1370,1346,1319,1286,1249,1213,1184,1161,1137,1109,1077,1044,1014,987,962,938,915,894,875,
-855,832,803,774,749,729,711,691,667,640,613,583,550,512,471,430,389,347,304,259,213,
-162,107,53,6,-35,-77,-127,-188,-254,-315,-364,-400,-429,-461,-498,-540,-585,-627,-667,-705,-742,
--776,-810,-846,-888,-937,-990,-1043,-1095,-1149,-1204,-1260,-1313,-1362,-1409,-1456,-1502,-1545,-1585,-1627,-1673,-1723,
--1771,-1816,-1860,-1907,-1959,-2013,-2066,-2114,-2156,-2191,-2223,-2259,-2302,-2352,-2405,-2454,-2501,-2549,-2602,-2657,-2706,
--2748,-2787,-2825,-2864,-2901,-2936,-2972,-3010,-3046,-3075,-3097,-3115,-3138,-3167,-3201,-3235,-3268,-3298,-3324,-3350,-3388,
--3449,-3532,-3620,-3690,-3732,-3750,-3760,-3772,-3794,-3829,-3879,-3942,-4009,-4064,-4100,-4117,-4123,-4124,-4121,-4112,-4099,
--4085,-4072,-4059,-4047,-4033,-4018,-4003,-3994,-3990,-3981,-3953,-3894,-3812,-3728,-3666,-3635,-3630,-3641,-3659,-3680,-3702,
--3728,-3762,-3803,-3841,-3860,-3849,-3804,-3732,-3636,-3526,-3420,-3343,-3310,-3307,-3297,-3252,-3179,-3108,-3067,-3054,-3049,
--3036,-3017,-3008,-3019,-3044,-3075,-3105,-3131,-3151,-3164,-3170,-3173,-3178,-3186,-3196,-3206,-3211,-3204,-3181,-3145,-3110,
--3083,-3064,-3046,-3021,-2993,-2973,-2969,-2980,-2998,-3014,-3026,-3036,-3046,-3061,-3077,-3091,-3101,-3103,-3097,-3084,-3063,
--3038,-3015,-2998,-2985,-2967,-2933,-2874,-2790,-2691,-2587,-2495,-2423,-2374,-2336,-2294,-2237,-2163,-2075,-1973,-1858,-1733,
--1607,-1490,-1384,-1289,-1202,-1121,-1047,-972,-887,-789,-684,-586,-509,-457,-420,-380,-319,-233,-140,-67,-34,
--35,-40,-16,43,121,185,219,225,222,226,248,285,331,379,428,479,533,588,641,690,740,
-791,843,892,935,974,1015,1064,1120,1177,1231,1280,1326,1376,1433,1501,1576,1654,1733,1807,1872,1928,
-1982,2047,2122,2190,2227,2223,2191,2152,2103,2019,1874,1681,1492,1364,1321,1345,1400,1456,1503,1540,1566,
-1583,1596,1610,1625,1640,1659,1686,1720,1753,1780,1800,1818,1833,1839,1837,1838,1851,1869,1872,1855,1840,
-1864,1939,2042,2131,2187,2220,2248,2277,2301,2322,2354,2407,2471,2525,2557,2569,2575,2583,2594,2607,2622,
-2634,2635,2623,2614,2626,2661,2700,2728,2746,2774,2825,2888,2943,2986,3028,3082,3141,3185,3202,3198,3191,
-3189,3193,3206,3235,3288,3365,3458,3557,3657,3752,3831,3886,3916,3927,3925,3913,3890,3862,3839,3830,3831,
-3835,3838,3843,3852,3863,3872,3876,3881,3893,3913,3935,3952,3959,3957,3952,3946,3924,3857,3718,3500,3228,
-2933,2632,2329,2040,1809,1697,1732,1885,2085,2264,2395,2487,2561,2622,2668,2693,2698,2689,2668,2637,2600,
-2559,2515,2467,2413,2357,2302,2246,2189,2127,2060,1991,1931,1891,1876,1876,1868,1830,1766,1697,1649,1626,
-1614,1597,1572,1547,1526,1502,1468,1423,1375,1330,1289,1252,1222,1199,1181,1155,1115,1064,1014,973,942,
-913,880,845,812,781,751,722,692,664,638,613,591,572,557,546,533,511,478,438,401,372,
-349,324,290,252,219,194,175,156,134,112,93,77,62,47,32,17,0,-20,-45,-72,-99,
--127,-156,-187,-216,-238,-253,-266,-278,-293,-307,-317,-321,-322,-327,-340,-360,-384,-410,-435,-459,-478,
--492,-501,-509,-521,-538,-558,-578,-597,-617,-640,-664,-688,-712,-736,-757,-775,-790,-803,-818,-835,-853,
--868,-880,-891,-903,-918,-933,-947,-958,-966,-973,-979,-984,-988,-994,-1002,-1012,-1020,-1027,-1031,-1035,-1041,
--1048,-1055,-1063,-1073,-1087,-1102,-1114,-1121,-1123,-1123,-1124,-1127,-1134,-1143,-1151,-1156,-1151,-1135,-1114,-1100,-1100,
--1111,-1120,-1118,-1105,-1093,-1093,-1104,-1115,-1113,-1102,-1092,-1093,-1102,-1109,-1109,-1106,-1106,-1110,-1111,-1104,-1095,
--1091,-1096,-1105,-1108,-1104,-1099,-1098,-1103,-1112,-1120,-1126,-1130,-1130,-1127,-1125,-1129,-1143,-1166,-1188,-1198,-1194,
--1180,-1171,-1176,-1190,-1202,-1204,-1196,-1186,-1181,-1181,-1178,-1170,-1161,-1157,-1160,-1163,-1164,-1162,-1157,-1151,-1144,
--1137,-1130,-1127,-1125,-1124,-1120,-1115,-1110,-1106,-1103,-1102,-1102,-1100,-1094,-1081,-1063,-1045,-1032,-1027,-1027,-1030,
--1031,-1026,-1016,-1003,-991,-979,-967,-955,-944,-938,-935,-932,-925,-917,-911,-908,-905,-898,-886,-872,-857,
--843,-828,-815,-806,-799,-789,-774,-757,-743,-738,-736,-731,-719,-704,-691,-680,-669,-654,-638,-626,-620,
--616,-612,-608,-604,-598,-589,-579,-571,-567,-567,-564,-558,-549,-541,-532,-520,-503,-485,-471,-461,-453,
--441,-426,-412,-403,-399,-394,-383,-365,-345,-332,-327,-326,-322,-311,-295,-280,-266,-254,-243,-234,-229,
--230,-234,-235,-230,-220,-207,-196,-188,-180,-169,-153,-136,-118,-102,-85,-65,-45,-26,-9,9,34,
-65,94,121,148,179,216,250,279,304,333,371,413,451,481,501,518,539,569,606,642,667,
-681,691,712,747,785,815,833,853,885,933,989,1044,1097,1148,1198,1244,1282,1310,1328,1339,1346,
-1346,1323,1258,1147,1016,913,884,954,1132,1405,1727,2022,2213,2295,2357,2523,2832,3177,3382,3345,3122,
-2870,2702,2613,2526,2399,2262,2173,2146,2150,2150,2144,2149,2162,2160,2129,2081,2049,2047,2064,2077,2074,
-2054,2021,1979,1936,1899,1871,1846,1820,1797,1782,1777,1770,1756,1739,1730,1729,1727,1716,1699,1683,1672,
-1658,1638,1619,1610,1611,1612,1605,1594,1585,1576,1555,1518,1477,1448,1433,1418,1386,1332,1266,1198,1132,
-1064,997,938,899,883,883,882,855,786,673,536,406,301,219,146,70,-6,-79,-148,-214,-282,
--347,-405,-454,-494,-525,-548,-565,-578,-592,-604,-614,-621,-625,-630,-636,-647,-664,-685,-706,-718,-721,
--721,-726,-738,-753,-763,-763,-755,-743,-732,-722,-718,-719,-724,-728,-729,-725,-718,-706,-689,-668,-644,
--618,-590,-562,-533,-507,-482,-457,-427,-394,-360,-327,-292,-255,-216,-176,-136,-95,-53,-12,26,59,
-91,128,174,236,312,391,455,488,488,473,466,479,506,528,538,548,575,623,678,725,758,
-791,838,899,957,995,1013,1024,1045,1080,1123,1162,1193,1220,1252,1287,1322,1351,1376,1400,1427,1454,
-1476,1494,1512,1530,1548,1560,1572,1587,1608,1631,1648,1660,1672,1689,1711,1731,1750,1769,1787,1801,1805,
-1804,1807,1818,1831,1840,1845,1853,1865,1873,1867,1847,1824,1805,1792,1777,1760,1746,1738,1734,1728,1720,
-1713,1708,1701,1688,1673,1662,1658,1655,1650,1646,1645,1647,1648,1644,1639,1636,1634,1633,1633,1638,1646,
-1651,1650,1651,1667,1700,1737,1759,1768,1776,1794,1807,1794,1748,1691,1655,1656,1684,1720,1752,1780,1806,
-1822,1821,1807,1797,1809,1845,1820,1854,1872,1865,1848,1841,1854,1882,1912,1936,1955,1973,1988,1995,1995,
-1996,2005,2020,2031,2032,2032,2039,2056,2076,2089,2096,2105,2122,2143,2163,2179,2196,2219,2248,2276,2300,
-2320,2338,2358,2380,2402,2423,2445,2467,2488,2509,2526,2539,2548,2556,2565,2574,2580,2580,2575,2567,2557,
-2546,2539,2537,2543,2555,2571,2593,2623,2659,2695,2730,2767,2815,2874,2937,2993,3037,3071,3100,3126,3149,
-3168,3182,3186,3176,3153,3124,3095,3070,3046,3022,3000,2983,2969,2954,2937,2927,2930,2939,2936,2899,2825,
-2734,2658,2623,2638,2688,2751,2802,2826,2823,2799,2766,2734,2708,2687,2667,2646,2626,2609,2598,2593,2593,
-2601,2620,2646,2669,2683,2695,2716,2756,2811,2867,2916,2954,2983,3001,3006,3001,2991,2981,2965,2938,2896,
-2843,2782,2714,2641,2569,2510,2471,2451,2444,2444,2449,2457,2464,2466,2464,2462,2464,2472,2487,2508,2527,
-2542,2551,2565,2587,2613,2631,2644,2675,2750,2869,3003,3110,3174,3207,3236,3269,3301,3322,3329,3329,3321,
-3302,3272,3236,3201,3167,3131,3095,3065,3045,3033,3024,3017,3016,3021,3028,3030,3024,3017,3011,3006,2998,
-2983,2967,2953,2947,2949,2957,2968,2982,2998,3012,3017,3006,2981,2956,2949,2961,2976,2971,2941,2899,2862,
-2825,2774,2698,2610,2536,2490,2468,2451,2423,2383,2338,2293,2252,2219,2196,2182,2176,2174,2172,2169,2163,
-2154,2147,2147,2153,2160,2161,2154,2144,2136,2127,2114,2097,2076,2055,2034,2012,1986,1959,1932,1905,1877,
-1846,1811,1775,1741,1710,1683,1657,1630,1602,1575,1548,1521,1493,1465,1439,1416,1393,1365,1330,1294,1259,
-1229,1202,1174,1144,1114,1084,1057,1032,1009,985,962,939,916,893,868,841,816,795,779,761,740,
-714,688,662,635,603,567,530,491,450,404,357,309,264,216,166,113,62,15,-33,-89,-151,
--214,-268,-310,-342,-373,-408,-451,-497,-544,-586,-623,-658,-690,-722,-757,-799,-850,-906,-961,-1011,-1057,
--1105,-1157,-1211,-1263,-1312,-1358,-1405,-1451,-1492,-1530,-1571,-1617,-1666,-1712,-1754,-1796,-1843,-1896,-1951,-2004,-2054,
--2099,-2139,-2174,-2207,-2245,-2291,-2343,-2395,-2447,-2499,-2554,-2608,-2657,-2698,-2735,-2775,-2816,-2856,-2893,-2930,-2969,
--3006,-3037,-3059,-3077,-3098,-3126,-3160,-3197,-3235,-3269,-3292,-3305,-3322,-3360,-3426,-3513,-3602,-3675,-3727,-3760,-3779,
--3794,-3812,-3844,-3894,-3953,-4010,-4055,-4084,-4102,-4109,-4109,-4103,-4093,-4081,-4068,-4055,-4043,-4031,-4017,-4002,-3991,
--3989,-3993,-3985,-3948,-3879,-3798,-3733,-3700,-3697,-3709,-3723,-3735,-3749,-3772,-3809,-3855,-3899,-3924,-3918,-3878,-3808,
--3714,-3606,-3501,-3419,-3374,-3356,-3338,-3301,-3247,-3198,-3172,-3165,-3161,-3146,-3126,-3113,-3117,-3138,-3169,-3203,-3234,
--3260,-3280,-3296,-3311,-3323,-3332,-3338,-3339,-3336,-3323,-3296,-3259,-3220,-3192,-3175,-3164,-3153,-3143,-3140,-3149,-3165,
--3181,-3192,-3196,-3195,-3195,-3197,-3203,-3208,-3208,-3201,-3189,-3172,-3152,-3127,-3099,-3073,-3052,-3036,-3015,-2975,-2908,
--2815,-2709,-2607,-2524,-2461,-2409,-2355,-2295,-2229,-2158,-2078,-1985,-1876,-1759,-1644,-1533,-1427,-1323,-1226,-1135,-1048,
--955,-854,-749,-653,-579,-525,-479,-426,-358,-278,-201,-146,-119,-112,-102,-69,-8,64,124,159,169,
-170,178,204,245,294,344,392,441,490,540,590,639,691,747,801,850,890,927,965,1010,1060,
-1114,1170,1226,1277,1323,1368,1421,1489,1572,1660,1742,1810,1867,1925,1993,2064,2119,2140,2126,2092,2051,
-1987,1872,1693,1484,1310,1224,1232,1291,1354,1397,1427,1457,1489,1517,1536,1548,1558,1572,1595,1624,1658,
-1688,1711,1729,1745,1758,1768,1774,1784,1799,1810,1804,1783,1772,1799,1870,1960,2039,2093,2130,2161,2188,
-2208,2229,2267,2325,2392,2444,2475,2492,2507,2523,2537,2551,2569,2592,2609,2610,2599,2596,2611,2640,2670,
-2695,2723,2762,2807,2847,2881,2919,2973,3041,3108,3159,3188,3197,3191,3177,3165,3170,3198,3249,3316,3396,
-3489,3588,3681,3759,3820,3868,3904,3921,3914,3889,3861,3839,3826,3815,3806,3802,3803,3804,3801,3799,3809,
-3835,3868,3890,3894,3884,3876,3876,3868,3823,3715,3532,3292,3020,2738,2454,2173,1923,1750,1698,1776,1943,
-2132,2291,2404,2484,2548,2600,2636,2655,2657,2645,2624,2594,2556,2511,2460,2406,2351,2299,2249,2200,2151,
-2099,2042,1978,1913,1867,1855,1871,1884,1860,1790,1701,1633,1602,1596,1588,1565,1533,1501,1473,1443,1405,
-1360,1315,1272,1234,1202,1176,1155,1131,1097,1054,1010,972,941,910,876,841,807,776,745,711,677,
-647,623,602,578,553,531,518,511,499,474,436,394,358,330,303,272,238,207,185,168,148,
-124,98,75,57,41,26,10,-7,-26,-48,-71,-95,-118,-143,-169,-197,-223,-244,-259,-273,-287,
--302,-315,-325,-332,-337,-345,-359,-378,-400,-422,-447,-474,-499,-518,-530,-537,-547,-562,-582,-602,-621,
--638,-657,-678,-701,-724,-746,-766,-783,-797,-809,-820,-833,-846,-858,-869,-881,-893,-907,-921,-935,-947,
--957,-965,-970,-974,-977,-983,-991,-999,-1006,-1012,-1017,-1024,-1032,-1041,-1048,-1056,-1065,-1078,-1092,-1103,-1110,
--1112,-1112,-1114,-1116,-1121,-1129,-1138,-1143,-1138,-1120,-1095,-1074,-1069,-1079,-1092,-1095,-1088,-1079,-1081,-1094,-1107,
--1110,-1103,-1096,-1096,-1104,-1111,-1113,-1111,-1112,-1114,-1111,-1103,-1095,-1097,-1106,-1114,-1112,-1100,-1089,-1086,-1094,
--1105,-1112,-1114,-1115,-1118,-1122,-1128,-1135,-1148,-1170,-1196,-1214,-1213,-1194,-1169,-1155,-1159,-1173,-1184,-1186,-1185,
--1186,-1186,-1179,-1165,-1151,-1147,-1157,-1173,-1183,-1183,-1175,-1165,-1157,-1151,-1147,-1145,-1142,-1136,-1127,-1116,-1107,
--1103,-1102,-1103,-1104,-1103,-1098,-1089,-1076,-1061,-1049,-1040,-1035,-1033,-1031,-1025,-1015,-1003,-992,-984,-976,-968,
--959,-953,-949,-947,-943,-936,-930,-925,-922,-916,-906,-893,-878,-863,-848,-834,-823,-813,-801,-785,-766,
--749,-736,-728,-720,-710,-700,-690,-678,-663,-646,-631,-622,-619,-618,-616,-612,-609,-605,-598,-589,-580,
--572,-567,-562,-556,-548,-538,-526,-510,-494,-478,-466,-457,-448,-434,-417,-402,-391,-385,-378,-367,-351,
--332,-318,-312,-312,-312,-307,-296,-283,-272,-263,-254,-243,-233,-228,-229,-234,-235,-230,-220,-210,-202,
--194,-182,-166,-147,-128,-109,-89,-66,-44,-26,-10,7,32,62,92,119,147,180,217,252,283,
-312,344,379,415,448,477,503,527,549,575,607,645,682,710,730,748,770,796,823,850,884,
-928,979,1030,1077,1121,1166,1209,1245,1271,1289,1301,1310,1313,1300,1255,1168,1048,935,878,914,1050,
-1270,1544,1824,2052,2187,2246,2319,2502,2805,3113,3269,3204,2992,2780,2661,2610,2545,2424,2280,2176,2136,
-2133,2131,2123,2119,2119,2105,2072,2031,2006,2007,2022,2029,2018,1990,1951,1910,1874,1851,1837,1824,1806,
-1789,1778,1773,1765,1750,1736,1732,1738,1738,1723,1699,1677,1662,1650,1634,1617,1605,1599,1591,1578,1566,
-1557,1545,1515,1467,1417,1385,1371,1356,1321,1264,1198,1137,1078,1017,958,913,894,895,900,884,828,
-731,604,472,354,258,177,99,20,-57,-129,-197,-267,-337,-400,-451,-489,-521,-548,-568,-580,-587,
--594,-605,-616,-624,-627,-628,-632,-645,-664,-686,-704,-715,-721,-725,-733,-743,-754,-762,-764,-760,-750,
--738,-726,-720,-720,-723,-724,-721,-717,-712,-704,-692,-673,-651,-627,-601,-572,-541,-511,-485,-460,-432,
--400,-365,-329,-292,-254,-216,-181,-148,-111,-70,-24,19,56,83,108,141,194,273,371,467,537,
-573,584,590,601,609,603,583,572,592,642,703,749,774,798,840,906,977,1029,1056,1068,1085,
-1117,1157,1196,1230,1263,1300,1341,1377,1403,1422,1444,1473,1505,1532,1551,1566,1580,1595,1607,1618,1631,
-1650,1672,1691,1706,1719,1732,1746,1760,1774,1792,1809,1819,1818,1813,1815,1828,1846,1859,1865,1869,1875,
-1878,1871,1854,1834,1818,1804,1789,1773,1763,1758,1755,1748,1739,1731,1726,1719,1705,1688,1677,1673,1672,
-1669,1666,1665,1667,1666,1660,1653,1650,1652,1653,1652,1650,1648,1646,1643,1648,1671,1712,1759,1793,1810,
-1816,1814,1796,1755,1702,1666,1669,1703,1736,1743,1731,1727,1748,1782,1803,1800,1789,1793,1820,1776,1807,
-1827,1829,1825,1831,1851,1879,1905,1925,1940,1952,1961,1967,1971,1979,1992,2005,2013,2016,2020,2031,2049,
-2065,2077,2087,2101,2122,2146,2166,2181,2198,2221,2249,2277,2298,2315,2335,2359,2384,2407,2426,2445,2468,
-2495,2518,2533,2540,2545,2553,2563,2572,2577,2578,2576,2569,2556,2541,2531,2535,2550,2567,2582,2600,2632,
-2678,2729,2772,2804,2832,2867,2911,2960,3007,3047,3080,3104,3121,3135,3147,3153,3150,3133,3109,3081,3055,
-3032,3013,2999,2988,2973,2947,2912,2882,2868,2866,2856,2817,2745,2661,2601,2589,2624,2685,2741,2775,2781,
-2770,2751,2732,2718,2709,2701,2689,2671,2650,2633,2624,2621,2624,2632,2647,2668,2689,2705,2720,2743,2781,
-2829,2877,2916,2945,2965,2979,2983,2981,2974,2965,2952,2928,2891,2844,2787,2722,2652,2585,2532,2501,2488,
-2487,2492,2501,2509,2515,2515,2513,2514,2520,2530,2544,2560,2573,2583,2591,2606,2631,2662,2688,2710,2743,
-2809,2912,3029,3127,3191,3226,3251,3277,3299,3313,3317,3316,3312,3303,3287,3264,3239,3212,3187,3163,3144,
-3127,3111,3099,3095,3101,3111,3116,3111,3100,3089,3083,3079,3074,3069,3063,3056,3048,3043,3046,3059,3074,
-3084,3083,3072,3054,3032,3016,3013,3024,3035,3025,2985,2924,2863,2810,2757,2694,2622,2557,2513,2491,2473,
-2446,2405,2359,2315,2279,2253,2236,2226,2221,2217,2213,2209,2206,2205,2205,2208,2212,2213,2209,2199,2189,
-2183,2179,2172,2156,2133,2108,2086,2064,2040,2011,1980,1950,1922,1891,1857,1821,1788,1760,1735,1708,1678,
-1648,1619,1590,1561,1531,1504,1480,1458,1433,1403,1369,1336,1304,1274,1243,1212,1182,1154,1127,1100,1075,
-1051,1028,1004,981,957,933,908,884,864,848,832,814,789,763,738,715,690,660,625,588,550,
-509,462,412,363,317,273,227,176,122,65,6,-54,-113,-164,-206,-240,-273,-311,-353,-400,-449,
--497,-541,-578,-610,-638,-669,-706,-754,-810,-869,-924,-970,-1011,-1055,-1104,-1157,-1208,-1255,-1301,-1348,-1394,
--1436,-1475,-1517,-1564,-1613,-1659,-1698,-1737,-1782,-1833,-1885,-1934,-1982,-2030,-2075,-2116,-2153,-2192,-2238,-2289,-2341,
--2393,-2446,-2502,-2555,-2602,-2642,-2681,-2725,-2772,-2817,-2856,-2891,-2926,-2962,-2994,-3019,-3040,-3063,-3089,-3120,-3154,
--3191,-3228,-3257,-3275,-3286,-3304,-3344,-3409,-3490,-3575,-3651,-3711,-3753,-3777,-3789,-3803,-3829,-3869,-3921,-3974,-4017,
--4043,-4052,-4049,-4045,-4046,-4050,-4049,-4042,-4031,-4020,-4009,-3999,-3990,-3990,-3998,-4003,-3988,-3946,-3889,-3839,-3813,
--3812,-3822,-3832,-3839,-3847,-3864,-3896,-3940,-3982,-4007,-4002,-3963,-3896,-3811,-3715,-3621,-3539,-3480,-3440,-3404,-3360,
--3310,-3266,-3239,-3227,-3217,-3203,-3185,-3178,-3189,-3222,-3269,-3320,-3366,-3402,-3428,-3448,-3464,-3475,-3475,-3467,-3454,
--3443,-3431,-3414,-3388,-3359,-3334,-3316,-3303,-3294,-3289,-3290,-3299,-3310,-3317,-3319,-3317,-3314,-3311,-3308,-3305,-3301,
--3292,-3276,-3255,-3231,-3206,-3181,-3153,-3124,-3098,-3078,-3061,-3037,-2993,-2926,-2838,-2744,-2655,-2577,-2504,-2431,-2357,
--2286,-2220,-2155,-2082,-1997,-1902,-1803,-1703,-1601,-1495,-1385,-1275,-1165,-1052,-939,-831,-739,-666,-603,-537,-462,
--383,-314,-264,-231,-206,-179,-143,-96,-43,11,58,92,113,125,142,171,213,264,315,362,407,
-453,500,550,603,659,716,769,815,853,890,928,968,1011,1059,1115,1175,1231,1276,1313,1355,1418,
-1502,1596,1685,1758,1820,1883,1952,2017,2061,2068,2042,1997,1937,1845,1701,1507,1308,1169,1127,1168,1241,
-1298,1328,1348,1376,1412,1445,1468,1484,1499,1520,1545,1574,1603,1627,1644,1657,1669,1683,1696,1708,1718,
-1728,1732,1726,1717,1719,1749,1808,1878,1941,1991,2032,2068,2096,2117,2140,2182,2243,2309,2359,2390,2412,
-2436,2460,2479,2495,2517,2552,2589,2612,2612,2601,2594,2600,2617,2642,2673,2710,2748,2777,2798,2821,2861,
-2922,2998,3077,3145,3187,3198,3182,3156,3139,3144,3167,3207,3263,3338,3430,3526,3616,3696,3767,3827,3869,
-3886,3883,3870,3855,3837,3814,3792,3775,3765,3755,3741,3732,3743,3776,3812,3830,3821,3798,3783,3775,3750,
-3673,3528,3325,3091,2844,2586,2316,2049,1828,1705,1707,1820,1991,2163,2300,2400,2472,2528,2571,2597,2608,
-2605,2593,2572,2544,2506,2459,2402,2343,2289,2241,2196,2149,2102,2057,2013,1963,1906,1858,1842,1861,1887,
-1878,1816,1719,1632,1584,1570,1564,1543,1510,1475,1446,1417,1382,1338,1291,1248,1211,1181,1157,1134,1108,
-1074,1035,997,964,933,900,863,827,797,770,739,703,664,632,610,593,572,542,513,493,485,
-479,461,427,384,343,308,278,249,220,196,179,164,145,119,88,60,37,19,3,-12,-31,
--52,-75,-98,-119,-139,-159,-181,-204,-227,-247,-265,-281,-294,-306,-316,-325,-335,-347,-362,-380,-399,
--417,-436,-458,-486,-516,-542,-558,-568,-576,-589,-606,-623,-638,-652,-669,-691,-715,-740,-761,-779,-794,
--806,-815,-824,-834,-845,-856,-867,-878,-889,-899,-909,-921,-932,-944,-952,-958,-961,-964,-970,-978,-987,
--995,-1002,-1009,-1016,-1025,-1034,-1043,-1052,-1063,-1075,-1086,-1096,-1103,-1107,-1109,-1111,-1112,-1113,-1118,-1127,-1136,
--1139,-1130,-1112,-1093,-1084,-1089,-1100,-1106,-1103,-1096,-1094,-1101,-1109,-1112,-1109,-1105,-1108,-1114,-1119,-1122,-1123,
--1124,-1123,-1118,-1110,-1107,-1110,-1118,-1120,-1110,-1093,-1080,-1080,-1090,-1102,-1109,-1110,-1111,-1117,-1128,-1137,-1144,
--1151,-1165,-1190,-1216,-1229,-1222,-1200,-1179,-1169,-1171,-1175,-1178,-1181,-1186,-1190,-1185,-1168,-1151,-1148,-1161,-1181,
--1193,-1190,-1179,-1169,-1166,-1167,-1168,-1166,-1161,-1153,-1142,-1129,-1116,-1108,-1104,-1103,-1103,-1100,-1095,-1089,-1082,
--1074,-1065,-1054,-1044,-1036,-1030,-1023,-1014,-1003,-993,-986,-980,-975,-968,-961,-958,-957,-955,-950,-943,-937,
--934,-931,-926,-917,-905,-892,-878,-863,-846,-830,-815,-799,-781,-761,-742,-726,-714,-705,-698,-690,-679,
--663,-645,-630,-621,-618,-616,-614,-611,-608,-605,-602,-596,-587,-578,-570,-564,-558,-550,-537,-521,-502,
--486,-473,-463,-454,-442,-426,-410,-394,-381,-369,-359,-347,-334,-319,-306,-298,-296,-298,-298,-293,-286,
--279,-274,-266,-254,-239,-228,-225,-229,-234,-233,-226,-216,-206,-198,-188,-172,-153,-134,-114,-93,-68,
--46,-28,-12,6,32,62,92,120,150,183,220,256,288,321,354,388,418,444,471,502,535,
-566,596,629,666,703,734,758,780,805,835,865,895,930,970,1013,1053,1091,1130,1172,1210,1239,
-1255,1265,1275,1284,1281,1249,1177,1069,952,872,873,978,1173,1422,1680,1908,2070,2158,2208,2296,2483,
-2753,2998,3094,3005,2814,2650,2584,2580,2553,2460,2325,2208,2139,2110,2097,2090,2086,2079,2057,2021,1985,
-1965,1963,1966,1962,1945,1918,1885,1851,1826,1815,1815,1814,1804,1789,1775,1765,1754,1740,1732,1734,1744,
-1746,1732,1709,1690,1680,1670,1653,1631,1610,1592,1572,1550,1532,1519,1499,1460,1404,1350,1319,1306,1290,
-1253,1195,1135,1082,1032,979,926,891,882,890,887,849,768,657,533,417,316,229,145,60,-24,
--102,-171,-237,-305,-373,-431,-473,-503,-530,-555,-574,-583,-584,-585,-593,-606,-616,-620,-622,-628,-642,
--662,-681,-695,-704,-712,-720,-730,-741,-749,-756,-761,-763,-758,-747,-733,-723,-719,-719,-716,-712,-708,
--706,-702,-693,-677,-656,-633,-608,-579,-547,-516,-488,-462,-434,-404,-372,-339,-306,-270,-233,-196,-158,
--119,-77,-33,10,48,78,104,131,172,235,319,411,492,552,594,628,657,672,665,642,629,
-647,697,754,794,812,827,863,925,997,1055,1089,1107,1126,1155,1190,1225,1256,1289,1326,1367,1402,
-1427,1446,1467,1497,1532,1562,1584,1600,1616,1631,1645,1656,1669,1686,1708,1731,1751,1768,1781,1789,1795,
-1802,1815,1829,1838,1835,1826,1822,1831,1848,1861,1867,1868,1868,1868,1864,1857,1848,1839,1828,1813,1798,
-1788,1782,1776,1765,1753,1746,1743,1737,1723,1706,1693,1688,1686,1683,1681,1682,1685,1682,1673,1662,1661,
-1667,1673,1672,1665,1658,1655,1657,1666,1690,1726,1762,1782,1782,1771,1757,1738,1711,1684,1676,1699,1737,
-1758,1745,1715,1702,1722,1758,1780,1773,1756,1754,1776,1736,1762,1782,1792,1803,1820,1843,1866,1885,1899,
-1910,1919,1928,1937,1948,1962,1975,1985,1993,2001,2013,2028,2045,2060,2073,2088,2107,2131,2155,2174,2190,
-2206,2228,2255,2282,2303,2320,2337,2360,2386,2409,2428,2448,2472,2499,2521,2534,2539,2545,2556,2568,2574,
-2574,2571,2570,2565,2554,2537,2528,2535,2555,2576,2590,2606,2637,2687,2745,2794,2828,2851,2874,2903,2936,
-2971,3003,3034,3060,3082,3101,3117,3129,3132,3124,3105,3082,3061,3045,3030,3013,2986,2944,2889,2829,2780,
-2752,2740,2728,2700,2656,2614,2599,2622,2672,2726,2760,2768,2757,2741,2731,2726,2725,2725,2722,2716,2703,
-2687,2673,2666,2664,2666,2669,2676,2690,2708,2728,2748,2774,2807,2845,2881,2910,2933,2953,2968,2975,2974,
-2965,2953,2938,2917,2886,2843,2790,2728,2663,2603,2559,2535,2527,2530,2538,2549,2559,2566,2567,2566,2568,
-2575,2586,2598,2609,2619,2627,2636,2653,2680,2714,2748,2778,2813,2868,2949,3044,3131,3196,3238,3268,3293,
-3313,3323,3322,3316,3312,3310,3307,3298,3281,3260,3243,3231,3221,3206,3187,3172,3170,3182,3194,3196,3188,
-3177,3169,3163,3157,3152,3153,3160,3162,3154,3143,3140,3152,3169,3175,3165,3145,3126,3110,3096,3085,3078,
-3072,3051,3004,2934,2862,2803,2754,2704,2645,2587,2544,2517,2494,2462,2417,2370,2330,2302,2284,2273,2267,
-2263,2258,2251,2246,2246,2251,2256,2260,2261,2259,2254,2246,2238,2233,2230,2224,2208,2183,2156,2133,2112,
-2089,2061,2028,1996,1966,1936,1903,1868,1836,1809,1782,1753,1721,1689,1660,1630,1600,1569,1542,1519,1496,
-1468,1435,1402,1372,1344,1315,1284,1252,1224,1197,1171,1142,1113,1087,1064,1042,1020,998,976,955,936,
-919,904,888,867,841,814,790,770,747,718,682,645,608,568,522,471,421,375,332,289,239,
-181,115,48,-15,-67,-105,-134,-165,-204,-249,-298,-346,-394,-442,-486,-524,-555,-584,-618,-661,-714,
--772,-829,-878,-919,-957,-1000,-1049,-1102,-1152,-1198,-1243,-1289,-1336,-1380,-1420,-1462,-1510,-1560,-1606,-1646,-1685,
--1728,-1778,-1829,-1877,-1923,-1969,-2015,-2058,-2099,-2143,-2191,-2243,-2293,-2342,-2392,-2445,-2497,-2543,-2582,-2621,-2668,
--2719,-2766,-2804,-2836,-2868,-2902,-2936,-2965,-2991,-3018,-3047,-3075,-3103,-3134,-3170,-3208,-3240,-3262,-3281,-3307,-3348,
--3405,-3473,-3545,-3615,-3674,-3718,-3742,-3754,-3767,-3794,-3840,-3896,-3945,-3971,-3970,-3957,-3954,-3969,-3994,-4015,-4019,
--4014,-4008,-4006,-4006,-4004,-4002,-4005,-4011,-4012,-4000,-3977,-3952,-3935,-3929,-3932,-3940,-3948,-3958,-3973,-3996,-4027,
--4058,-4074,-4065,-4028,-3971,-3905,-3835,-3764,-3694,-3629,-3572,-3517,-3460,-3403,-3354,-3319,-3299,-3287,-3277,-3272,-3279,
--3305,-3352,-3412,-3474,-3525,-3559,-3578,-3590,-3599,-3603,-3597,-3580,-3559,-3542,-3532,-3524,-3512,-3496,-3477,-3458,-3440,
--3423,-3411,-3406,-3406,-3407,-3406,-3403,-3402,-3400,-3397,-3389,-3377,-3363,-3347,-3324,-3295,-3260,-3224,-3192,-3162,-3132,
--3104,-3078,-3058,-3041,-3018,-2980,-2922,-2850,-2770,-2689,-2608,-2524,-2437,-2353,-2280,-2217,-2157,-2091,-2018,-1939,-1858,
--1774,-1681,-1577,-1460,-1332,-1197,-1063,-941,-841,-760,-685,-602,-509,-423,-359,-324,-302,-274,-231,-178,-129,
--90,-57,-20,19,56,86,113,147,192,244,295,339,380,422,468,520,575,631,685,733,775,
-815,854,893,930,966,1007,1059,1121,1182,1231,1269,1309,1368,1452,1552,1651,1737,1807,1869,1926,1973,
-1998,1992,1953,1889,1799,1674,1510,1324,1160,1066,1060,1116,1186,1236,1263,1284,1312,1345,1374,1396,1418,
-1445,1476,1505,1531,1554,1573,1588,1600,1610,1621,1632,1638,1640,1641,1643,1648,1656,1670,1694,1732,1778,
-1829,1882,1934,1980,2013,2035,2057,2096,2152,2213,2262,2296,2325,2356,2388,2412,2432,2459,2503,2557,2602,
-2620,2612,2592,2575,2572,2587,2620,2662,2703,2734,2751,2764,2786,2828,2893,2975,3060,3128,3161,3158,3135,
-3114,3108,3118,3140,3175,3231,3307,3397,3489,3574,3650,3715,3767,3802,3825,3840,3845,3835,3811,3781,3757,
-3740,3722,3699,3681,3682,3705,3735,3746,3731,3701,3674,3645,3589,3481,3319,3123,2916,2698,2456,2191,1933,
-1743,1670,1724,1866,2036,2187,2303,2389,2456,2505,2538,2554,2558,2552,2538,2515,2483,2443,2392,2333,2274,
-2224,2182,2141,2096,2049,2008,1974,1936,1887,1838,1814,1829,1864,1876,1832,1741,1641,1570,1536,1522,1505,
-1479,1450,1423,1394,1358,1313,1264,1219,1184,1161,1144,1125,1095,1056,1013,976,948,920,886,845,807,
-779,757,731,695,653,618,595,580,562,534,501,476,461,453,438,409,370,329,291,258,228,
-203,185,171,158,140,113,80,47,19,-2,-19,-34,-50,-70,-92,-115,-136,-155,-173,-193,-213,
--234,-256,-276,-294,-307,-314,-318,-325,-336,-352,-372,-394,-415,-433,-452,-473,-500,-531,-559,-580,-592,
--602,-613,-627,-640,-651,-662,-678,-699,-724,-750,-772,-789,-803,-814,-823,-832,-842,-852,-864,-875,-886,
--895,-902,-908,-916,-925,-934,-942,-948,-952,-956,-963,-973,-983,-993,-1001,-1009,-1017,-1025,-1034,-1044,-1056,
--1068,-1079,-1088,-1095,-1102,-1109,-1113,-1115,-1113,-1112,-1112,-1118,-1129,-1139,-1143,-1138,-1128,-1120,-1119,-1125,-1129,
--1128,-1122,-1117,-1116,-1118,-1118,-1117,-1118,-1121,-1125,-1129,-1131,-1133,-1135,-1135,-1130,-1125,-1124,-1126,-1126,-1119,
--1104,-1088,-1079,-1082,-1093,-1105,-1114,-1119,-1122,-1126,-1133,-1140,-1143,-1144,-1149,-1166,-1193,-1221,-1236,-1234,-1220,
--1206,-1195,-1187,-1182,-1185,-1194,-1203,-1201,-1186,-1168,-1163,-1173,-1188,-1192,-1182,-1168,-1163,-1170,-1180,-1183,-1177,
--1168,-1159,-1153,-1145,-1135,-1123,-1114,-1107,-1101,-1094,-1088,-1082,-1079,-1077,-1072,-1062,-1050,-1038,-1029,-1022,-1014,
--1004,-994,-987,-982,-977,-971,-964,-961,-961,-960,-955,-947,-940,-937,-936,-934,-930,-922,-913,-901,-885,
--865,-844,-827,-814,-801,-784,-763,-742,-726,-714,-706,-697,-684,-667,-649,-633,-620,-611,-606,-601,-597,
--594,-592,-589,-585,-578,-569,-561,-556,-554,-548,-537,-519,-499,-482,-470,-461,-450,-435,-419,-405,-391,
--377,-361,-347,-334,-324,-314,-302,-293,-289,-290,-292,-291,-287,-282,-278,-272,-261,-245,-230,-225,-228,
--233,-234,-227,-217,-208,-200,-189,-173,-153,-135,-117,-98,-77,-57,-38,-19,2,30,61,89,117,
-147,182,219,253,286,321,358,392,420,442,466,498,537,575,610,644,678,709,735,758,783,
-814,848,881,911,943,980,1018,1054,1089,1128,1170,1207,1231,1240,1246,1256,1263,1249,1193,1093,972,
-871,839,909,1083,1326,1585,1811,1975,2072,2123,2176,2287,2481,2719,2905,2953,2853,2688,2567,2539,2570,
-2580,2521,2404,2272,2165,2095,2059,2046,2042,2033,2008,1971,1937,1918,1910,1903,1893,1880,1865,1845,1820,
-1800,1794,1801,1808,1804,1788,1770,1754,1742,1731,1726,1731,1740,1743,1736,1727,1724,1724,1717,1697,1667,
-1636,1606,1574,1540,1508,1480,1448,1401,1344,1296,1271,1261,1242,1199,1140,1082,1035,991,942,895,865,
-859,861,840,780,683,571,462,366,280,195,107,18,-65,-139,-203,-264,-328,-389,-440,-475,-501,
--524,-548,-567,-576,-576,-576,-582,-594,-605,-611,-616,-626,-642,-662,-678,-688,-693,-699,-707,-718,-728,
--736,-744,-752,-758,-758,-750,-738,-726,-717,-711,-705,-699,-695,-695,-695,-690,-678,-660,-638,-613,-584,
--551,-519,-489,-461,-435,-409,-383,-357,-330,-298,-260,-216,-169,-122,-78,-36,1,37,71,105,139,
-178,227,287,353,416,470,519,569,618,656,674,677,682,708,754,802,835,851,866,898,951,
-1014,1069,1109,1136,1162,1192,1225,1255,1282,1309,1340,1377,1412,1440,1462,1484,1512,1544,1574,1599,1620,
-1640,1660,1677,1691,1704,1720,1739,1762,1785,1806,1821,1828,1830,1831,1839,1853,1863,1862,1851,1842,1842,
-1852,1864,1870,1871,1869,1868,1868,1868,1866,1860,1848,1832,1818,1808,1802,1793,1779,1767,1761,1760,1756,
-1744,1729,1718,1711,1706,1699,1695,1697,1701,1698,1684,1671,1668,1676,1683,1681,1673,1670,1674,1685,1699,
-1718,1741,1758,1757,1736,1706,1685,1678,1680,1686,1699,1722,1744,1748,1730,1704,1697,1715,1741,1751,1738,
-1719,1717,1736,1716,1732,1746,1760,1780,1805,1828,1847,1861,1873,1885,1895,1903,1913,1926,1940,1952,1962,
-1973,1988,2008,2028,2046,2062,2080,2100,2123,2146,2168,2188,2205,2222,2242,2268,2295,2318,2335,2349,2366,
-2388,2411,2433,2454,2476,2500,2519,2531,2537,2545,2558,2569,2573,2568,2561,2558,2557,2551,2542,2537,2545,
-2564,2585,2600,2616,2643,2685,2735,2780,2816,2845,2872,2896,2914,2929,2947,2975,3012,3049,3081,3104,3117,
-3119,3112,3096,3080,3070,3065,3054,3025,2969,2890,2804,2730,2683,2660,2652,2644,2631,2621,2625,2652,2698,
-2745,2778,2785,2772,2753,2740,2738,2741,2745,2746,2747,2746,2743,2735,2725,2717,2712,2709,2706,2707,2715,
-2731,2752,2777,2806,2838,2869,2895,2915,2934,2953,2972,2984,2986,2979,2967,2951,2928,2895,2850,2794,2734,
-2675,2626,2594,2577,2572,2574,2581,2592,2605,2614,2619,2621,2625,2633,2645,2655,2664,2671,2679,2690,2708,
-2736,2771,2810,2847,2885,2933,2998,3076,3154,3218,3264,3297,3323,3343,3352,3349,3340,3335,3340,3348,3347,
-3333,3312,3298,3295,3295,3285,3266,3252,3253,3266,3277,3275,3266,3260,3259,3255,3243,3233,3238,3256,3269,
-3261,3239,3224,3231,3249,3258,3249,3231,3215,3200,3176,3140,3103,3074,3046,3002,2939,2868,2808,2762,2719,
-2669,2615,2570,2537,2506,2467,2420,2375,2342,2322,2310,2304,2301,2301,2298,2292,2285,2284,2289,2295,2299,
-2299,2298,2296,2294,2288,2281,2274,2265,2249,2225,2198,2174,2155,2134,2107,2075,2043,2012,1982,1950,1915,
-1881,1851,1822,1791,1759,1727,1698,1669,1638,1608,1581,1559,1534,1503,1468,1434,1407,1382,1354,1323,1293,
-1266,1240,1213,1181,1149,1122,1099,1078,1057,1038,1020,1004,989,973,957,938,916,891,865,843,823,
-802,774,741,705,669,629,583,532,481,435,392,348,295,231,160,89,29,-13,-41,-65,-98,
--144,-195,-245,-291,-336,-382,-426,-463,-495,-529,-571,-623,-680,-736,-785,-827,-864,-901,-944,-995,-1048,
--1098,-1142,-1184,-1229,-1276,-1320,-1361,-1402,-1448,-1498,-1546,-1589,-1629,-1673,-1723,-1776,-1828,-1875,-1919,-1960,-2000,
--2041,-2088,-2140,-2194,-2245,-2292,-2340,-2390,-2441,-2486,-2524,-2563,-2609,-2659,-2706,-2744,-2776,-2808,-2844,-2879,-2910,
--2938,-2967,-2999,-3029,-3055,-3081,-3113,-3153,-3195,-3233,-3262,-3289,-3319,-3354,-3394,-3443,-3500,-3565,-3626,-3674,-3702,
--3721,-3746,-3789,-3844,-3889,-3907,-3897,-3878,-3876,-3901,-3940,-3972,-3986,-3988,-3991,-4002,-4016,-4022,-4019,-4014,-4015,
--4023,-4034,-4040,-4036,-4022,-4006,-3996,-3999,-4013,-4032,-4049,-4064,-4079,-4093,-4098,-4085,-4054,-4013,-3972,-3933,-3891,
--3842,-3787,-3729,-3669,-3610,-3553,-3503,-3468,-3447,-3437,-3436,-3443,-3461,-3495,-3542,-3596,-3646,-3681,-3698,-3701,-3700,
--3702,-3704,-3701,-3687,-3666,-3646,-3632,-3621,-3610,-3599,-3585,-3569,-3549,-3526,-3506,-3492,-3483,-3476,-3470,-3464,-3461,
--3456,-3445,-3426,-3401,-3377,-3355,-3331,-3299,-3258,-3213,-3173,-3140,-3112,-3084,-3056,-3030,-3010,-2994,-2974,-2942,-2894,
--2835,-2771,-2702,-2624,-2536,-2446,-2365,-2300,-2246,-2193,-2133,-2066,-1997,-1929,-1857,-1773,-1670,-1544,-1398,-1240,-1088,
--956,-850,-758,-668,-575,-490,-427,-391,-367,-333,-283,-230,-189,-164,-140,-104,-53,0,44,81,121,
-172,228,279,320,356,394,439,490,542,593,641,684,725,765,807,849,887,920,956,1002,1061,
-1125,1183,1228,1270,1326,1408,1514,1632,1741,1826,1883,1916,1932,1932,1911,1858,1769,1643,1485,1312,1152,
-1037,990,1010,1067,1126,1168,1197,1226,1256,1285,1307,1328,1356,1393,1428,1455,1474,1491,1509,1525,1538,
-1549,1560,1569,1572,1568,1563,1567,1582,1600,1614,1625,1640,1671,1720,1784,1850,1906,1942,1961,1977,2005,
-2049,2102,2151,2192,2229,2268,2304,2335,2361,2394,2443,2505,2563,2598,2604,2586,2559,2541,2545,2572,2616,
-2663,2701,2725,2741,2757,2782,2823,2882,2952,3018,3062,3076,3070,3060,3060,3072,3091,3117,3157,3215,3291,
-3375,3457,3529,3590,3644,3692,3738,3778,3805,3808,3791,3764,3741,3724,3703,3674,3641,3622,3624,3637,3641,
-3625,3590,3544,3483,3394,3268,3113,2945,2768,2568,2329,2065,1825,1677,1660,1759,1919,2079,2207,2303,2379,
-2438,2480,2502,2510,2509,2502,2485,2457,2418,2371,2317,2258,2202,2156,2120,2086,2045,2001,1963,1932,1898,
-1852,1800,1767,1772,1805,1831,1812,1741,1645,1559,1505,1479,1464,1449,1430,1407,1378,1341,1294,1242,1193,
-1156,1136,1127,1114,1084,1038,988,950,926,905,873,831,789,758,738,716,684,644,607,581,564,
-546,521,491,463,442,426,410,387,356,319,281,245,215,192,175,162,148,128,103,72,38,
-5,-21,-41,-56,-69,-84,-102,-122,-144,-165,-187,-207,-226,-246,-267,-289,-307,-319,-324,-327,-332,
--342,-357,-378,-400,-424,-447,-469,-491,-516,-545,-572,-594,-610,-621,-632,-643,-654,-664,-674,-687,-706,
--728,-751,-773,-793,-809,-823,-835,-846,-857,-868,-878,-889,-899,-908,-914,-919,-923,-928,-935,-940,-945,
--950,-958,-967,-978,-988,-996,-1005,-1013,-1022,-1030,-1040,-1052,-1065,-1078,-1086,-1093,-1099,-1106,-1115,-1121,-1124,
--1123,-1120,-1118,-1118,-1123,-1132,-1140,-1144,-1143,-1138,-1134,-1134,-1134,-1132,-1128,-1124,-1122,-1122,-1123,-1125,-1127,
--1130,-1133,-1135,-1138,-1140,-1142,-1141,-1139,-1136,-1135,-1133,-1128,-1117,-1104,-1094,-1088,-1087,-1092,-1102,-1117,-1132,
--1140,-1140,-1138,-1138,-1141,-1142,-1142,-1147,-1164,-1191,-1219,-1236,-1238,-1229,-1215,-1202,-1195,-1197,-1209,-1220,-1219,
--1205,-1187,-1180,-1185,-1192,-1188,-1172,-1159,-1162,-1179,-1194,-1195,-1179,-1161,-1151,-1150,-1150,-1145,-1133,-1119,-1107,
--1098,-1091,-1085,-1079,-1075,-1073,-1070,-1063,-1052,-1040,-1030,-1022,-1014,-1005,-996,-989,-984,-979,-972,-966,-963,
--962,-961,-956,-947,-938,-933,-931,-928,-924,-919,-914,-906,-891,-870,-850,-836,-829,-823,-811,-792,-770,
--752,-737,-725,-712,-698,-682,-664,-646,-629,-614,-603,-597,-591,-585,-579,-573,-567,-559,-550,-542,-538,
--538,-538,-531,-517,-499,-483,-472,-462,-450,-435,-421,-409,-399,-385,-368,-350,-336,-325,-316,-306,-297,
--293,-294,-295,-294,-289,-283,-279,-274,-266,-252,-240,-234,-236,-239,-238,-231,-222,-213,-204,-191,-172,
--151,-133,-118,-105,-90,-72,-53,-30,-4,25,54,81,109,141,177,214,248,279,314,353,391,
-421,445,471,503,541,579,615,649,682,711,733,753,778,810,844,875,905,937,975,1015,1050,
-1084,1121,1162,1197,1217,1224,1230,1240,1243,1212,1133,1013,894,828,859,1003,1237,1508,1755,1931,2026,
-2062,2086,2149,2283,2484,2695,2839,2861,2770,2640,2555,2549,2591,2618,2580,2477,2337,2201,2095,2033,2009,
-2003,1992,1963,1925,1892,1872,1860,1848,1839,1835,1833,1824,1806,1786,1780,1789,1800,1800,1785,1764,1746,
-1732,1723,1718,1719,1723,1725,1727,1735,1748,1761,1759,1740,1711,1680,1649,1611,1563,1513,1465,1417,1364,
-1311,1271,1252,1243,1219,1171,1108,1048,1001,957,910,865,836,824,808,765,687,587,487,399,320,
-240,154,63,-23,-100,-167,-225,-282,-338,-390,-433,-464,-487,-508,-530,-550,-562,-567,-570,-576,-585,
--593,-600,-608,-619,-636,-654,-669,-678,-682,-686,-693,-703,-714,-724,-732,-739,-746,-749,-746,-739,-728,
--717,-706,-695,-686,-682,-682,-685,-683,-674,-659,-640,-617,-589,-558,-525,-494,-465,-438,-414,-392,-370,
--346,-315,-276,-229,-179,-127,-78,-36,0,33,68,106,148,193,239,288,336,378,416,456,504,
-560,615,659,690,717,751,792,831,860,879,900,931,975,1026,1074,1116,1153,1188,1223,1256,1285,
-1309,1332,1357,1388,1423,1456,1483,1508,1532,1559,1588,1615,1640,1665,1689,1710,1729,1744,1757,1772,1789,
-1809,1831,1849,1859,1861,1862,1870,1885,1897,1898,1887,1873,1867,1872,1881,1888,1891,1891,1891,1891,1891,
-1886,1876,1860,1843,1832,1826,1822,1812,1798,1785,1779,1776,1770,1760,1750,1745,1742,1735,1723,1716,1718,
-1723,1721,1707,1692,1687,1692,1694,1685,1673,1672,1684,1703,1717,1728,1740,1751,1748,1726,1694,1673,1674,
-1690,1710,1725,1732,1732,1724,1709,1697,1700,1716,1729,1727,1713,1700,1702,1716,1709,1716,1724,1740,1765,
-1794,1815,1830,1842,1855,1869,1879,1884,1891,1903,1917,1930,1943,1960,1983,2007,2029,2047,2066,2089,2114,
-2138,2159,2181,2204,2227,2246,2264,2284,2309,2334,2352,2364,2376,2393,2415,2438,2458,2477,2497,2514,2526,
-2532,2540,2550,2561,2565,2560,2551,2547,2550,2553,2554,2556,2564,2579,2596,2613,2631,2655,2683,2713,2742,
-2772,2808,2845,2872,2882,2883,2891,2921,2971,3025,3069,3095,3105,3106,3100,3091,3084,3084,3086,3075,3033,
-2954,2853,2759,2698,2675,2676,2678,2671,2661,2664,2686,2725,2765,2792,2800,2791,2775,2762,2758,2763,2769,
-2773,2775,2778,2783,2786,2784,2776,2765,2754,2747,2742,2741,2744,2756,2776,2805,2840,2876,2906,2929,2943,
-2956,2972,2989,3003,3011,3011,3004,2989,2961,2919,2864,2803,2743,2692,2654,2630,2620,2618,2619,2625,2635,
-2649,2662,2670,2675,2683,2695,2709,2721,2729,2734,2740,2752,2769,2795,2829,2869,2912,2955,3003,3061,3130,
-3201,3261,3304,3334,3357,3378,3392,3393,3387,3385,3394,3406,3407,3390,3365,3351,3355,3364,3362,3348,3337,
-3342,3355,3362,3355,3346,3347,3354,3352,3334,3318,3325,3353,3374,3361,3321,3285,3278,3295,3310,3309,3297,
-3284,3265,3227,3168,3107,3063,3035,3000,2945,2876,2813,2765,2724,2678,2629,2585,2548,2511,2467,2419,2379,
-2355,2344,2337,2332,2330,2333,2336,2332,2325,2320,2322,2328,2331,2331,2332,2335,2336,2331,2321,2308,2295,
-2280,2260,2236,2213,2194,2174,2149,2118,2086,2056,2027,1995,1959,1923,1889,1858,1827,1796,1766,1738,1709,
-1678,1648,1621,1597,1570,1537,1502,1469,1443,1419,1392,1362,1333,1307,1282,1252,1219,1187,1160,1138,1116,
-1096,1078,1065,1053,1038,1019,1000,981,962,940,917,896,877,857,833,803,770,733,691,642,591,
-542,498,455,405,344,271,195,127,75,42,19,-6,-45,-95,-148,-195,-237,-279,-323,-365,-402,
--435,-475,-527,-586,-644,-693,-733,-770,-806,-846,-891,-942,-995,-1044,-1086,-1126,-1167,-1212,-1256,-1297,-1338,
--1383,-1433,-1484,-1529,-1570,-1612,-1660,-1714,-1769,-1819,-1863,-1902,-1939,-1980,-2028,-2083,-2139,-2192,-2240,-2288,-2338,
--2388,-2433,-2471,-2510,-2554,-2603,-2650,-2691,-2727,-2763,-2801,-2836,-2865,-2891,-2920,-2954,-2987,-3016,-3041,-3071,-3108,
--3152,-3195,-3232,-3264,-3293,-3318,-3342,-3368,-3406,-3462,-3528,-3590,-3636,-3669,-3701,-3742,-3790,-3830,-3848,-3844,-3837,
--3844,-3871,-3905,-3931,-3942,-3947,-3960,-3983,-4008,-4023,-4022,-4012,-4004,-4010,-4030,-4052,-4062,-4052,-4027,-4005,-4003,
--4022,-4050,-4073,-4084,-4089,-4090,-4086,-4073,-4051,-4026,-4004,-3987,-3968,-3939,-3903,-3860,-3815,-3769,-3723,-3684,-3656,
--3641,-3635,-3637,-3646,-3664,-3690,-3722,-3755,-3781,-3794,-3795,-3788,-3782,-3782,-3787,-3789,-3783,-3767,-3744,-3720,-3696,
--3675,-3658,-3646,-3633,-3616,-3593,-3570,-3551,-3536,-3524,-3513,-3502,-3490,-3476,-3453,-3421,-3385,-3354,-3331,-3310,-3283,
--3245,-3199,-3156,-3122,-3096,-3072,-3044,-3015,-2989,-2969,-2952,-2929,-2897,-2858,-2816,-2771,-2714,-2642,-2560,-2483,-2422,
--2376,-2330,-2274,-2207,-2137,-2072,-2013,-1952,-1875,-1770,-1631,-1460,-1273,-1094,-944,-826,-733,-650,-577,-518,-475,
--441,-403,-357,-312,-278,-253,-223,-176,-115,-55,-6,34,80,138,201,255,297,331,367,409,455,
-501,546,590,633,675,716,757,798,838,874,909,950,1002,1064,1125,1178,1225,1278,1357,1469,1607,
-1742,1845,1897,1905,1889,1865,1830,1763,1648,1486,1301,1127,997,931,927,964,1015,1060,1094,1124,1157,
-1190,1218,1240,1266,1301,1340,1371,1389,1400,1414,1432,1450,1462,1472,1484,1500,1510,1511,1508,1512,1525,
-1541,1548,1548,1554,1582,1637,1709,1781,1837,1871,1888,1898,1916,1949,1994,2042,2088,2132,2174,2215,2253,
-2290,2331,2382,2443,2502,2547,2567,2563,2543,2523,2518,2535,2571,2614,2654,2688,2717,2743,2767,2792,2821,
-2859,2904,2943,2968,2978,2982,2992,3011,3036,3063,3094,3138,3196,3265,3336,3403,3463,3521,3583,3646,3703,
-3742,3755,3747,3731,3717,3705,3685,3648,3602,3561,3538,3531,3525,3504,3457,3384,3287,3171,3045,2918,2787,
-2636,2441,2201,1948,1748,1659,1695,1823,1980,2118,2223,2302,2368,2420,2452,2464,2464,2460,2451,2432,2399,
-2354,2302,2246,2189,2136,2093,2060,2030,1996,1957,1919,1884,1848,1802,1750,1709,1695,1711,1734,1735,1697,
-1628,1550,1486,1447,1430,1422,1412,1391,1362,1326,1282,1230,1177,1133,1109,1102,1094,1067,1017,963,923,
-903,889,863,821,775,738,714,695,669,636,602,574,553,532,508,481,453,427,405,387,369,
-346,314,275,235,203,182,168,154,137,115,89,61,30,-3,-35,-60,-78,-89,-98,-110,-127,
--148,-173,-199,-223,-243,-261,-279,-299,-316,-328,-335,-341,-348,-359,-372,-389,-410,-434,-460,-485,-508,
--532,-558,-585,-609,-627,-640,-649,-658,-667,-678,-689,-702,-717,-734,-754,-775,-796,-816,-834,-850,-864,
--877,-887,-896,-904,-913,-922,-929,-934,-936,-939,-942,-945,-950,-956,-966,-977,-986,-993,-998,-1004,-1012,
--1021,-1031,-1043,-1056,-1070,-1082,-1090,-1095,-1101,-1111,-1122,-1132,-1137,-1140,-1139,-1137,-1132,-1127,-1124,-1126,-1130,
--1133,-1133,-1130,-1126,-1123,-1120,-1118,-1118,-1121,-1124,-1128,-1131,-1134,-1137,-1139,-1141,-1144,-1146,-1147,-1145,-1142,
--1140,-1137,-1133,-1126,-1120,-1117,-1115,-1108,-1094,-1083,-1086,-1109,-1139,-1158,-1158,-1148,-1142,-1146,-1154,-1155,-1151,
--1153,-1167,-1190,-1211,-1222,-1222,-1217,-1210,-1207,-1210,-1220,-1228,-1226,-1213,-1197,-1189,-1193,-1197,-1190,-1175,-1166,
--1174,-1196,-1213,-1208,-1184,-1156,-1139,-1137,-1139,-1135,-1122,-1107,-1096,-1090,-1089,-1087,-1083,-1078,-1072,-1067,-1061,
--1052,-1043,-1033,-1023,-1014,-1005,-997,-991,-986,-981,-975,-970,-967,-967,-966,-960,-951,-941,-932,-925,-917,
--911,-906,-903,-898,-885,-867,-848,-837,-833,-831,-822,-806,-787,-771,-757,-745,-732,-719,-706,-693,-677,
--658,-640,-627,-619,-612,-602,-589,-578,-568,-558,-547,-535,-527,-524,-524,-520,-511,-498,-485,-475,-466,
--455,-443,-431,-421,-412,-399,-382,-363,-345,-331,-320,-311,-304,-302,-302,-302,-299,-293,-288,-284,-281,
--275,-266,-257,-252,-250,-249,-244,-235,-226,-218,-207,-192,-171,-150,-134,-122,-112,-100,-84,-64,-40,
--13,16,45,72,102,137,175,212,244,274,307,346,385,420,451,481,514,548,580,611,644,
-678,710,734,756,781,811,843,873,902,937,976,1015,1048,1078,1111,1149,1182,1200,1207,1213,1222,
-1215,1167,1070,948,853,841,943,1152,1424,1698,1912,2033,2067,2059,2069,2141,2287,2480,2662,2774,2788,
-2724,2638,2587,2588,2618,2629,2587,2486,2348,2205,2090,2020,1991,1980,1963,1930,1890,1859,1840,1828,1815,
-1805,1802,1804,1802,1789,1774,1769,1777,1789,1792,1780,1761,1742,1728,1716,1707,1702,1700,1700,1705,1719,
-1739,1757,1761,1751,1734,1717,1695,1661,1609,1549,1487,1426,1366,1310,1269,1248,1234,1206,1156,1091,1030,
-979,932,884,837,802,773,735,671,585,493,413,346,277,198,108,18,-60,-126,-185,-240,-292,
--340,-382,-417,-445,-468,-490,-509,-528,-543,-555,-565,-571,-577,-582,-588,-596,-607,-620,-636,-651,-663,
--670,-675,-681,-692,-705,-717,-724,-729,-732,-736,-739,-737,-729,-717,-703,-690,-681,-676,-676,-677,-676,
--669,-656,-638,-617,-594,-567,-537,-505,-473,-443,-416,-392,-367,-339,-306,-269,-227,-182,-131,-79,-30,
-10,45,77,112,152,197,246,295,341,380,413,448,491,544,600,651,694,733,773,814,852,
-883,909,935,967,1004,1043,1083,1124,1165,1205,1243,1279,1310,1336,1358,1380,1408,1441,1476,1507,1534,
-1557,1582,1610,1638,1665,1691,1717,1741,1764,1781,1794,1804,1816,1832,1853,1872,1886,1893,1900,1912,1927,
-1939,1939,1928,1913,1905,1906,1913,1919,1922,1924,1925,1924,1920,1911,1896,1879,1865,1858,1855,1851,1841,
-1826,1814,1804,1796,1784,1773,1769,1772,1776,1770,1757,1747,1750,1757,1756,1744,1731,1727,1730,1724,1705,
-1684,1677,1688,1705,1714,1717,1722,1737,1749,1747,1732,1719,1719,1732,1744,1746,1734,1717,1699,1689,1690,
-1701,1714,1720,1713,1702,1696,1700,1709,1696,1702,1712,1731,1759,1785,1803,1813,1823,1837,1850,1858,1862,
-1868,1882,1901,1919,1938,1960,1986,2012,2032,2049,2070,2096,2124,2147,2167,2191,2221,2252,2274,2288,2301,
-2320,2343,2360,2371,2380,2395,2417,2439,2457,2471,2488,2507,2521,2528,2531,2537,2546,2554,2554,2548,2545,
-2548,2558,2568,2575,2581,2589,2602,2619,2641,2663,2681,2692,2702,2722,2756,2797,2828,2840,2839,2845,2874,
-2927,2987,3035,3066,3085,3098,3108,3113,3113,3110,3103,3081,3031,2950,2856,2781,2750,2758,2778,2784,2767,
-2745,2738,2752,2778,2799,2806,2803,2796,2792,2792,2795,2800,2804,2807,2809,2814,2821,2826,2825,2816,2801,
-2789,2782,2779,2779,2781,2788,2806,2837,2878,2919,2952,2972,2984,2993,3003,3015,3028,3038,3045,3044,3029,
-2995,2943,2881,2817,2760,2714,2682,2663,2657,2658,2664,2672,2685,2699,2713,2722,2730,2742,2759,2780,2796,
-2803,2806,2810,2818,2833,2855,2885,2923,2968,3016,3065,3122,3187,3254,3312,3352,3377,3398,3421,3442,3452,
-3451,3450,3458,3468,3466,3445,3418,3406,3414,3429,3432,3423,3419,3429,3445,3449,3438,3429,3436,3452,3453,
-3433,3412,3420,3454,3477,3455,3396,3338,3315,3325,3338,3335,3322,3308,3287,3244,3178,3111,3065,3040,3010,
-2957,2885,2817,2766,2726,2684,2639,2596,2557,2518,2471,2425,2391,2376,2372,2368,2360,2356,2359,2364,2363,
-2356,2350,2352,2357,2360,2359,2360,2363,2366,2362,2349,2335,2323,2311,2295,2274,2251,2229,2208,2182,2152,
-2122,2093,2065,2034,1998,1961,1927,1896,1866,1835,1806,1778,1749,1718,1687,1658,1631,1601,1569,1536,1507,
-1482,1457,1430,1401,1373,1348,1321,1290,1256,1226,1201,1180,1159,1139,1123,1112,1100,1083,1060,1038,1021,
-1007,992,974,953,934,915,894,869,837,798,752,700,649,604,563,518,460,387,305,227,166,
-125,98,73,41,-3,-54,-102,-143,-181,-222,-266,-308,-344,-380,-426,-484,-544,-596,-636,-670,-706,
--747,-792,-840,-890,-941,-990,-1031,-1068,-1106,-1149,-1193,-1237,-1279,-1324,-1375,-1427,-1475,-1517,-1556,-1600,-1651,
--1703,-1752,-1797,-1838,-1878,-1923,-1972,-2027,-2083,-2135,-2185,-2233,-2283,-2331,-2375,-2415,-2455,-2499,-2549,-2597,-2640,
--2680,-2719,-2758,-2793,-2821,-2847,-2875,-2908,-2943,-2975,-3004,-3035,-3073,-3115,-3155,-3192,-3226,-3257,-3285,-3306,-3325,
--3349,-3389,-3443,-3501,-3550,-3589,-3624,-3663,-3706,-3745,-3774,-3795,-3814,-3837,-3860,-3875,-3880,-3880,-3886,-3906,-3937,
--3969,-3991,-3995,-3985,-3969,-3962,-3972,-3997,-4018,-4021,-4005,-3986,-3983,-4002,-4034,-4060,-4072,-4073,-4068,-4061,-4050,
--4036,-4023,-4012,-4003,-3989,-3971,-3949,-3927,-3903,-3875,-3845,-3819,-3801,-3792,-3789,-3788,-3789,-3795,-3807,-3822,-3835,
--3844,-3848,-3849,-3849,-3849,-3850,-3853,-3853,-3846,-3830,-3805,-3773,-3739,-3708,-3684,-3669,-3657,-3642,-3622,-3598,-3577,
--3558,-3542,-3526,-3508,-3487,-3463,-3432,-3395,-3357,-3326,-3305,-3289,-3270,-3240,-3200,-3158,-3123,-3095,-3072,-3046,-3017,
--2989,-2965,-2944,-2921,-2892,-2861,-2832,-2805,-2770,-2720,-2658,-2598,-2551,-2516,-2478,-2425,-2353,-2273,-2200,-2140,-2090,
--2037,-1962,-1849,-1686,-1483,-1267,-1074,-924,-819,-741,-675,-616,-566,-523,-484,-444,-407,-373,-338,-291,-230,
--163,-105,-59,-19,30,94,161,219,264,303,342,382,422,460,500,545,594,639,678,713,750,
-790,831,869,907,950,1003,1065,1126,1181,1238,1314,1426,1570,1717,1825,1869,1858,1822,1785,1742,1664,
-1526,1337,1133,966,867,841,866,913,959,994,1022,1050,1081,1113,1143,1173,1209,1248,1282,1304,1316,
-1330,1353,1380,1397,1399,1395,1402,1422,1445,1458,1459,1459,1464,1471,1474,1474,1484,1517,1574,1643,1707,
-1754,1785,1805,1820,1840,1869,1908,1952,1996,2038,2078,2120,2166,2215,2269,2325,2382,2435,2478,2506,2517,
-2513,2502,2496,2504,2527,2557,2590,2625,2664,2705,2742,2769,2787,2806,2832,2864,2892,2908,2916,2924,2942,
-2968,2997,3027,3061,3104,3156,3213,3273,3334,3402,3476,3551,3614,3656,3674,3678,3677,3675,3667,3644,3600,
-3543,3487,3445,3419,3397,3358,3287,3182,3056,2932,2827,2740,2645,2509,2315,2082,1864,1725,1700,1778,1911,
-2046,2155,2236,2303,2361,2405,2427,2430,2421,2410,2394,2370,2333,2287,2236,2182,2128,2077,2035,2003,1976,
-1947,1911,1870,1828,1787,1746,1703,1660,1625,1609,1612,1623,1623,1595,1538,1471,1418,1393,1388,1384,1366,
-1335,1299,1261,1218,1168,1120,1088,1077,1070,1046,996,939,898,880,871,850,811,763,722,694,673,
-652,627,601,576,552,530,506,479,448,417,390,371,358,342,314,273,228,192,171,160,147,
-128,103,76,49,20,-11,-44,-73,-94,-107,-114,-121,-134,-155,-182,-211,-237,-258,-275,-293,-311,
--328,-341,-352,-362,-373,-385,-397,-411,-429,-452,-477,-502,-525,-547,-573,-601,-627,-648,-660,-667,-674,
--682,-694,-708,-722,-736,-750,-767,-786,-806,-826,-845,-863,-880,-895,-906,-913,-919,-927,-936,-943,-946,
--947,-948,-950,-953,-957,-964,-974,-985,-993,-996,-997,-999,-1005,-1015,-1025,-1037,-1050,-1064,-1077,-1086,-1092,
--1101,-1114,-1128,-1140,-1149,-1155,-1159,-1159,-1153,-1142,-1130,-1123,-1123,-1127,-1130,-1131,-1128,-1124,-1121,-1121,-1124,
--1129,-1136,-1140,-1142,-1143,-1144,-1147,-1150,-1154,-1155,-1155,-1152,-1148,-1144,-1139,-1132,-1127,-1129,-1137,-1143,-1133,
--1105,-1077,-1072,-1099,-1142,-1173,-1176,-1160,-1148,-1152,-1162,-1167,-1162,-1156,-1160,-1175,-1190,-1201,-1207,-1212,-1215,
--1217,-1219,-1222,-1224,-1221,-1210,-1197,-1192,-1196,-1202,-1200,-1190,-1185,-1193,-1212,-1225,-1219,-1193,-1161,-1139,-1128,
--1123,-1115,-1102,-1088,-1080,-1079,-1083,-1087,-1086,-1081,-1073,-1065,-1058,-1051,-1043,-1033,-1023,-1013,-1005,-998,-993,
--988,-983,-978,-975,-973,-973,-971,-967,-959,-949,-939,-927,-916,-906,-901,-898,-894,-882,-863,-844,-831,
--825,-820,-810,-796,-781,-771,-764,-756,-747,-738,-730,-721,-708,-691,-675,-663,-656,-647,-634,-618,-603,
--592,-582,-570,-555,-540,-527,-518,-511,-502,-493,-483,-474,-465,-455,-445,-434,-423,-412,-398,-382,-364,
--347,-331,-319,-310,-306,-304,-302,-300,-297,-294,-292,-291,-289,-284,-277,-271,-266,-261,-255,-246,-234,
--223,-213,-201,-186,-168,-151,-137,-126,-116,-103,-87,-66,-43,-17,10,38,67,99,136,175,211,
-242,271,302,338,377,414,450,485,519,549,574,600,629,663,696,725,750,778,810,843,875,
-906,941,979,1014,1043,1070,1102,1138,1169,1187,1194,1199,1201,1180,1115,1010,903,852,904,1070,1321,
-1603,1853,2023,2095,2094,2071,2083,2164,2308,2478,2625,2711,2727,2695,2652,2627,2622,2619,2591,2521,2413,
-2284,2159,2060,2001,1976,1964,1944,1909,1869,1840,1826,1816,1803,1788,1776,1772,1771,1767,1762,1761,1767,
-1774,1775,1767,1753,1739,1724,1711,1699,1690,1684,1682,1683,1691,1705,1717,1722,1720,1715,1712,1703,1680,
-1639,1586,1528,1466,1399,1331,1274,1235,1207,1176,1130,1074,1018,967,917,864,811,762,714,654,577,
-491,413,351,296,231,149,59,-23,-90,-145,-198,-250,-298,-339,-370,-398,-425,-452,-475,-494,-509,
--526,-542,-554,-562,-566,-570,-577,-588,-598,-608,-619,-633,-648,-659,-666,-672,-683,-698,-712,-720,-722,
--723,-727,-731,-732,-725,-712,-698,-688,-681,-678,-676,-674,-671,-664,-650,-633,-614,-594,-572,-546,-514,
--479,-444,-413,-385,-354,-320,-284,-247,-212,-173,-128,-76,-22,25,65,97,126,159,197,241,288,
-335,378,418,459,505,555,605,651,692,735,781,829,874,911,944,975,1007,1039,1071,1105,1141,
-1180,1220,1258,1294,1328,1357,1382,1405,1431,1462,1495,1526,1554,1579,1605,1633,1662,1688,1712,1735,1760,
-1783,1802,1816,1827,1839,1855,1876,1896,1913,1927,1943,1961,1978,1986,1983,1971,1958,1951,1950,1951,1953,
-1953,1954,1955,1954,1949,1940,1928,1914,1904,1897,1892,1884,1873,1860,1849,1841,1829,1814,1801,1797,1804,
-1810,1806,1794,1785,1787,1794,1792,1780,1770,1772,1779,1775,1752,1721,1703,1705,1714,1716,1712,1713,1728,
-1749,1762,1762,1755,1753,1754,1752,1739,1716,1691,1670,1662,1667,1683,1699,1706,1700,1690,1686,1690,1696,
-1680,1692,1706,1725,1750,1771,1784,1791,1799,1811,1822,1828,1833,1845,1867,1893,1918,1941,1965,1993,2019,
-2038,2055,2076,2104,2133,2157,2179,2206,2242,2276,2299,2309,2314,2326,2343,2357,2366,2375,2391,2414,2436,
-2450,2460,2475,2494,2512,2520,2521,2524,2534,2547,2554,2553,2550,2553,2564,2577,2587,2590,2592,2598,2612,
-2632,2653,2668,2674,2677,2687,2712,2747,2778,2796,2802,2808,2829,2868,2917,2966,3012,3057,3102,3139,3155,
-3147,3121,3087,3051,3005,2946,2883,2839,2831,2850,2871,2868,2840,2807,2790,2795,2811,2823,2827,2830,2836,
-2844,2848,2847,2843,2841,2841,2843,2847,2852,2855,2853,2844,2831,2823,2821,2824,2827,2828,2834,2851,2883,
-2922,2959,2987,3003,3013,3022,3032,3041,3051,3061,3070,3070,3052,3013,2956,2893,2834,2784,2743,2712,2694,
-2689,2696,2710,2725,2741,2756,2768,2778,2788,2803,2826,2852,2872,2881,2883,2884,2890,2901,2917,2941,2976,
-3020,3069,3119,3173,3235,3303,3364,3408,3435,3458,3484,3509,3522,3522,3516,3517,3521,3516,3497,3476,3469,
-3481,3496,3499,3493,3496,3516,3540,3547,3536,3526,3537,3558,3561,3539,3515,3521,3553,3573,3545,3477,3410,
-3379,3379,3377,3355,3324,3300,3281,3247,3191,3130,3085,3056,3022,2966,2895,2829,2782,2746,2706,2659,2612,
-2571,2530,2486,2443,2415,2406,2406,2402,2391,2382,2380,2382,2380,2373,2369,2373,2380,2384,2381,2378,2380,
-2383,2382,2373,2362,2353,2345,2331,2310,2285,2261,2236,2209,2179,2150,2123,2097,2068,2033,1998,1964,1934,
-1905,1874,1844,1815,1787,1758,1727,1696,1665,1633,1602,1571,1544,1520,1494,1466,1438,1412,1387,1359,1326,
-1293,1265,1243,1224,1203,1184,1170,1159,1146,1126,1100,1078,1064,1056,1046,1030,1011,991,973,954,930,
-898,857,809,757,708,665,624,574,506,422,337,264,213,180,154,123,81,33,-14,-55,-90,
--126,-167,-211,-252,-290,-331,-381,-438,-493,-536,-568,-600,-641,-689,-739,-788,-836,-886,-934,-976,-1012,
--1050,-1092,-1139,-1185,-1229,-1274,-1323,-1376,-1426,-1469,-1509,-1551,-1597,-1645,-1690,-1733,-1777,-1823,-1872,-1923,-1975,
--2026,-2076,-2125,-2174,-2222,-2269,-2312,-2353,-2394,-2439,-2488,-2537,-2582,-2622,-2660,-2698,-2733,-2765,-2795,-2825,-2858,
--2892,-2923,-2954,-2989,-3031,-3075,-3116,-3150,-3182,-3215,-3247,-3276,-3298,-3320,-3348,-3385,-3426,-3464,-3499,-3531,-3566,
--3603,-3641,-3681,-3723,-3765,-3799,-3815,-3814,-3803,-3798,-3808,-3834,-3869,-3904,-3932,-3945,-3937,-3913,-3887,-3879,-3897,
--3929,-3957,-3967,-3964,-3965,-3979,-4005,-4029,-4043,-4045,-4040,-4032,-4022,-4014,-4008,-4002,-3992,-3974,-3954,-3938,-3928,
--3920,-3906,-3888,-3872,-3864,-3864,-3863,-3859,-3851,-3846,-3846,-3850,-3854,-3859,-3867,-3878,-3890,-3897,-3896,-3888,-3875,
--3858,-3836,-3809,-3778,-3745,-3715,-3690,-3672,-3657,-3639,-3618,-3594,-3570,-3549,-3530,-3510,-3488,-3464,-3436,-3402,-3366,
--3333,-3306,-3289,-3276,-3260,-3235,-3200,-3159,-3121,-3089,-3063,-3037,-3011,-2985,-2961,-2938,-2912,-2881,-2848,-2820,-2798,
--2775,-2743,-2702,-2661,-2628,-2604,-2575,-2527,-2456,-2373,-2291,-2223,-2171,-2128,-2079,-2001,-1872,-1689,-1475,-1266,-1094,
--967,-872,-792,-717,-650,-595,-551,-515,-483,-449,-405,-346,-276,-207,-150,-107,-65,-12,52,119,178,
-228,273,317,359,394,426,463,510,563,611,647,676,707,747,793,836,872,909,957,1020,1094,
-1167,1235,1310,1409,1533,1661,1753,1785,1765,1723,1683,1635,1545,1390,1185,981,833,765,768,808,857,
-898,931,958,985,1012,1041,1072,1109,1151,1190,1216,1231,1247,1280,1330,1376,1394,1377,1347,1333,1346,
-1374,1395,1399,1393,1390,1392,1397,1404,1421,1456,1507,1563,1613,1652,1683,1712,1741,1772,1806,1843,1880,
-1916,1949,1982,2021,2070,2130,2195,2260,2317,2365,2401,2429,2448,2458,2462,2465,2473,2490,2511,2534,2560,
-2594,2637,2684,2723,2751,2772,2798,2830,2859,2874,2875,2871,2875,2893,2920,2949,2979,3012,3053,3099,3152,
-3213,3286,3367,3446,3509,3550,3575,3592,3606,3613,3604,3572,3521,3460,3398,3343,3294,3241,3169,3066,2936,
-2803,2696,2630,2584,2517,2389,2199,1990,1826,1758,1791,1891,2010,2113,2193,2256,2313,2361,2394,2407,2402,
-2386,2364,2336,2301,2260,2214,2166,2116,2065,2017,1975,1944,1919,1893,1858,1813,1765,1724,1694,1668,1633,
-1585,1539,1518,1530,1558,1563,1522,1447,1376,1341,1341,1347,1332,1297,1257,1225,1195,1157,1113,1079,1062,
-1051,1025,976,917,874,856,848,831,794,748,708,678,657,637,616,595,574,554,534,511,484,
-452,415,382,360,350,341,318,277,229,188,164,151,138,118,92,64,36,9,-19,-50,-79,
--102,-117,-126,-133,-145,-166,-194,-224,-249,-269,-287,-307,-330,-351,-368,-381,-393,-405,-418,-429,-442,
--458,-478,-500,-521,-541,-562,-587,-615,-642,-663,-676,-684,-690,-699,-712,-727,-743,-756,-770,-786,-804,
--822,-839,-855,-872,-890,-907,-919,-927,-933,-941,-950,-955,-956,-955,-956,-959,-963,-967,-972,-981,-992,
--1000,-1003,-1001,-1001,-1006,-1013,-1022,-1030,-1040,-1052,-1065,-1076,-1087,-1099,-1115,-1131,-1145,-1155,-1163,-1169,-1172,
--1170,-1161,-1150,-1141,-1138,-1140,-1144,-1147,-1148,-1147,-1145,-1144,-1147,-1151,-1154,-1155,-1154,-1153,-1154,-1157,-1161,
--1164,-1166,-1165,-1162,-1158,-1153,-1146,-1137,-1132,-1137,-1152,-1163,-1154,-1124,-1091,-1081,-1107,-1150,-1182,-1184,-1166,
--1149,-1145,-1151,-1155,-1154,-1154,-1163,-1177,-1189,-1197,-1203,-1213,-1223,-1227,-1225,-1221,-1218,-1215,-1208,-1199,-1194,
--1197,-1206,-1209,-1206,-1201,-1203,-1213,-1221,-1217,-1198,-1174,-1152,-1136,-1123,-1110,-1097,-1085,-1078,-1076,-1077,-1079,
--1079,-1075,-1068,-1060,-1052,-1045,-1037,-1028,-1019,-1011,-1005,-1000,-994,-989,-984,-980,-978,-977,-977,-975,-972,
--968,-961,-951,-939,-926,-914,-908,-905,-899,-886,-866,-846,-830,-819,-808,-795,-781,-771,-767,-765,-762,
--754,-745,-737,-728,-716,-702,-689,-678,-671,-662,-650,-635,-622,-613,-606,-597,-582,-563,-541,-520,-504,
--492,-483,-475,-465,-454,-442,-431,-419,-404,-388,-372,-357,-344,-332,-319,-310,-304,-301,-298,-293,-288,
--286,-287,-290,-291,-288,-283,-277,-272,-268,-262,-253,-241,-227,-215,-203,-192,-178,-163,-148,-134,-122,
--108,-93,-76,-56,-33,-9,15,41,69,101,136,173,208,239,269,300,334,368,404,441,477,
-512,540,563,586,614,645,676,704,732,763,799,836,870,903,938,972,1002,1030,1060,1096,1135,
-1164,1179,1184,1186,1178,1141,1063,960,881,881,990,1200,1467,1732,1942,2066,2106,2093,2081,2114,2207,
-2345,2489,2603,2670,2690,2680,2660,2641,2618,2578,2510,2413,2299,2185,2085,2010,1966,1947,1937,1919,1888,
-1853,1829,1819,1814,1802,1781,1759,1746,1745,1749,1753,1754,1752,1748,1743,1738,1733,1727,1718,1706,1695,
-1687,1683,1681,1678,1676,1676,1676,1672,1666,1662,1659,1655,1643,1620,1590,1552,1502,1433,1351,1270,1205,
-1158,1122,1086,1046,1004,959,908,850,787,722,654,581,501,422,355,299,243,175,93,9,-61,
--117,-163,-211,-260,-303,-336,-359,-382,-410,-440,-465,-483,-497,-510,-526,-539,-546,-550,-557,-569,-584,
--595,-602,-609,-622,-638,-651,-659,-664,-674,-689,-705,-714,-717,-717,-721,-724,-723,-715,-702,-691,-685,
--682,-678,-675,-671,-667,-660,-647,-630,-611,-592,-572,-546,-514,-477,-441,-409,-378,-345,-306,-265,-227,
--192,-157,-117,-69,-18,30,74,111,144,177,210,244,281,320,361,406,455,508,560,606,645,
-683,727,779,835,885,928,964,998,1032,1065,1097,1128,1162,1198,1235,1272,1308,1343,1375,1403,1428,
-1454,1482,1512,1542,1569,1595,1623,1650,1676,1699,1719,1739,1762,1784,1804,1820,1836,1855,1877,1900,1921,
-1939,1958,1981,2005,2023,2029,2022,2010,2000,1995,1992,1988,1983,1980,1979,1980,1979,1976,1971,1963,1954,
-1943,1933,1923,1912,1901,1892,1886,1882,1873,1860,1848,1842,1843,1845,1839,1830,1823,1824,1824,1815,1801,
-1793,1801,1818,1822,1803,1771,1745,1736,1738,1739,1737,1736,1743,1754,1759,1756,1748,1740,1730,1714,1693,
-1669,1646,1629,1621,1625,1642,1664,1677,1678,1670,1666,1670,1680,1675,1692,1706,1718,1733,1749,1761,1770,
-1778,1787,1794,1801,1810,1828,1857,1889,1918,1942,1968,1996,2024,2046,2064,2085,2113,2144,2171,2197,2227,
-2262,2295,2315,2322,2323,2330,2342,2352,2357,2364,2381,2406,2429,2442,2449,2461,2480,2499,2509,2512,2515,
-2526,2542,2555,2559,2559,2564,2574,2588,2597,2600,2600,2601,2607,2617,2630,2644,2657,2667,2676,2691,2713,
-2739,2762,2775,2780,2784,2800,2832,2882,2947,3023,3095,3145,3156,3125,3070,3016,2980,2960,2942,2917,2894,
-2883,2886,2889,2876,2850,2824,2817,2830,2852,2870,2884,2897,2911,2920,2917,2904,2888,2877,2873,2873,2874,
-2876,2878,2876,2871,2864,2861,2864,2870,2875,2879,2888,2907,2937,2968,2991,3003,3009,3018,3033,3048,3061,
-3069,3077,3083,3079,3057,3014,2959,2903,2855,2815,2779,2749,2730,2727,2740,2759,2779,2796,2811,2824,2836,
-2850,2869,2894,2922,2944,2954,2957,2959,2965,2975,2987,3006,3037,3079,3125,3173,3223,3284,3353,3421,3474,
-3510,3536,3561,3583,3592,3586,3573,3565,3565,3562,3552,3541,3543,3557,3570,3571,3568,3581,3615,3649,3661,
-3650,3640,3649,3668,3670,3646,3618,3616,3639,3651,3620,3557,3499,3475,3469,3447,3395,3335,3295,3276,3254,
-3212,3157,3106,3067,3026,2970,2907,2854,2817,2783,2738,2681,2626,2581,2544,2507,2471,2448,2442,2442,2436,
-2422,2408,2400,2397,2392,2385,2383,2389,2398,2402,2397,2392,2391,2395,2398,2395,2389,2383,2375,2361,2338,
-2312,2286,2261,2233,2203,2174,2150,2126,2100,2068,2034,2003,1974,1945,1913,1881,1851,1824,1797,1768,1736,
-1703,1671,1640,1610,1583,1556,1529,1501,1475,1451,1426,1396,1363,1330,1305,1285,1267,1248,1229,1214,1201,
-1186,1164,1140,1122,1112,1106,1096,1080,1061,1043,1026,1007,982,950,911,865,816,768,721,672,610,
-533,448,369,310,271,242,210,170,122,73,30,-6,-39,-74,-115,-158,-199,-239,-283,-334,-387,
--434,-469,-498,-532,-578,-631,-684,-733,-780,-829,-876,-918,-956,-994,-1039,-1089,-1137,-1181,-1224,-1271,-1322,
--1371,-1416,-1458,-1503,-1549,-1595,-1637,-1677,-1721,-1769,-1820,-1871,-1919,-1966,-2014,-2063,-2112,-2160,-2207,-2250,-2292,
--2334,-2379,-2427,-2476,-2520,-2559,-2596,-2632,-2668,-2705,-2740,-2776,-2809,-2840,-2869,-2899,-2936,-2981,-3029,-3071,-3106,
--3136,-3168,-3202,-3236,-3267,-3293,-3320,-3349,-3378,-3407,-3436,-3464,-3493,-3521,-3552,-3587,-3630,-3673,-3706,-3717,-3711,
--3703,-3706,-3727,-3760,-3795,-3830,-3863,-3883,-3882,-3855,-3817,-3796,-3809,-3852,-3901,-3934,-3946,-3947,-3953,-3967,-3986,
--4002,-4008,-4004,-3994,-3983,-3976,-3976,-3974,-3965,-3944,-3921,-3904,-3897,-3895,-3889,-3879,-3874,-3878,-3888,-3895,-3891,
--3880,-3869,-3863,-3861,-3862,-3866,-3876,-3891,-3905,-3909,-3900,-3880,-3854,-3826,-3800,-3774,-3748,-3724,-3702,-3682,-3662,
--3641,-3618,-3593,-3568,-3545,-3522,-3502,-3482,-3461,-3437,-3407,-3373,-3337,-3306,-3284,-3269,-3256,-3239,-3213,-3177,-3136,
--3097,-3063,-3035,-3010,-2984,-2959,-2935,-2913,-2887,-2855,-2820,-2788,-2764,-2743,-2720,-2690,-2659,-2633,-2613,-2587,-2547,
--2486,-2411,-2332,-2259,-2200,-2156,-2120,-2073,-1990,-1858,-1687,-1502,-1331,-1186,-1062,-948,-840,-743,-664,-606,-566,
--535,-504,-463,-405,-335,-264,-205,-156,-107,-50,15,82,141,194,244,294,338,372,401,435,481,
-534,581,616,642,670,709,757,803,844,882,933,1006,1097,1190,1271,1342,1414,1499,1585,1647,1666,
-1647,1612,1574,1518,1412,1241,1033,844,724,687,709,753,794,828,862,896,929,956,981,1010,1048,
-1091,1126,1145,1157,1183,1239,1316,1383,1403,1372,1317,1278,1275,1298,1321,1327,1320,1314,1316,1324,1337,
-1355,1383,1422,1467,1510,1547,1582,1618,1657,1698,1740,1780,1815,1844,1870,1897,1932,1980,2040,2109,2177,
-2238,2285,2318,2344,2366,2387,2405,2422,2441,2465,2489,2509,2523,2539,2566,2605,2649,2689,2724,2758,2795,
-2827,2843,2841,2829,2821,2826,2843,2866,2893,2924,2962,3005,3053,3110,3181,3261,3340,3403,3448,3481,3509,
-3531,3539,3522,3481,3425,3363,3299,3230,3149,3052,2934,2796,2656,2541,2474,2455,2446,2395,2274,2099,1932,
-1835,1834,1909,2013,2108,2180,2236,2285,2328,2361,2380,2384,2375,2355,2323,2282,2235,2188,2142,2096,2048,
-1999,1953,1913,1881,1855,1829,1796,1751,1702,1663,1644,1637,1616,1569,1509,1472,1481,1521,1541,1502,1413,
-1323,1280,1286,1304,1296,1258,1214,1184,1165,1141,1106,1072,1049,1031,1000,947,888,846,828,822,805,
-771,728,690,663,642,622,601,581,562,546,530,513,491,459,420,382,355,344,337,320,286,
-240,197,166,145,128,107,82,54,27,1,-24,-50,-77,-101,-120,-133,-143,-157,-180,-209,-237,
--260,-277,-295,-319,-348,-377,-399,-416,-429,-441,-452,-463,-476,-491,-509,-527,-543,-559,-577,-599,-623,
--646,-666,-680,-692,-704,-717,-731,-745,-758,-771,-784,-801,-820,-838,-852,-866,-881,-899,-916,-929,-937,
--944,-953,-963,-968,-968,-966,-967,-970,-974,-977,-981,-989,-1001,-1011,-1016,-1016,-1017,-1021,-1026,-1031,-1034,
--1038,-1046,-1057,-1071,-1084,-1100,-1117,-1133,-1147,-1157,-1164,-1170,-1175,-1178,-1177,-1174,-1169,-1165,-1163,-1163,-1165,
--1168,-1169,-1170,-1169,-1169,-1169,-1168,-1165,-1163,-1161,-1163,-1166,-1171,-1174,-1175,-1173,-1171,-1167,-1162,-1153,-1143,
--1135,-1138,-1151,-1165,-1165,-1147,-1125,-1118,-1134,-1163,-1182,-1180,-1165,-1149,-1142,-1140,-1138,-1138,-1149,-1170,-1191,
--1203,-1205,-1208,-1216,-1228,-1233,-1230,-1224,-1222,-1222,-1218,-1209,-1200,-1199,-1206,-1214,-1215,-1210,-1205,-1205,-1207,
--1205,-1197,-1184,-1169,-1154,-1139,-1126,-1116,-1108,-1099,-1088,-1078,-1070,-1066,-1064,-1060,-1053,-1046,-1037,-1029,-1020,
--1013,-1008,-1004,-1001,-996,-989,-984,-981,-980,-980,-979,-977,-976,-974,-971,-963,-952,-938,-926,-918,-912,
--905,-893,-875,-857,-841,-828,-815,-801,-789,-782,-780,-778,-771,-759,-744,-729,-715,-702,-689,-676,-666,
--657,-648,-638,-628,-618,-610,-604,-597,-586,-569,-545,-518,-494,-478,-469,-462,-452,-438,-423,-409,-394,
--377,-357,-339,-326,-317,-309,-301,-296,-294,-293,-290,-283,-276,-274,-278,-282,-282,-277,-270,-266,-264,
--262,-256,-247,-235,-223,-211,-199,-188,-175,-160,-143,-124,-106,-90,-74,-57,-37,-14,9,33,57,
-81,108,139,171,204,236,269,301,332,363,396,430,466,499,528,554,580,608,637,664,690,
-718,752,790,826,859,891,923,954,983,1014,1051,1093,1132,1157,1168,1170,1168,1153,1104,1019,926,
-878,924,1078,1314,1578,1813,1980,2064,2081,2071,2081,2140,2249,2382,2505,2597,2649,2665,2656,2633,2601,
-2557,2494,2409,2308,2203,2105,2024,1962,1921,1901,1891,1879,1858,1830,1810,1802,1801,1793,1773,1746,1728,
-1726,1734,1741,1738,1725,1709,1698,1696,1701,1705,1704,1699,1693,1690,1690,1690,1687,1680,1670,1657,1641,
-1622,1605,1591,1581,1572,1563,1554,1538,1504,1443,1356,1259,1172,1108,1066,1038,1014,986,949,899,834,
-757,674,593,516,444,377,315,253,188,114,37,-34,-93,-140,-183,-227,-271,-307,-333,-352,-372,
--400,-430,-456,-473,-485,-496,-511,-523,-532,-537,-545,-560,-577,-589,-595,-602,-614,-630,-646,-654,-660,
--668,-683,-699,-710,-714,-716,-718,-719,-716,-706,-695,-687,-684,-681,-676,-670,-664,-660,-655,-644,-629,
--610,-591,-570,-542,-509,-474,-439,-408,-376,-340,-299,-255,-214,-176,-139,-102,-62,-20,22,65,109,
-154,197,234,266,293,322,357,400,451,507,560,605,642,679,722,774,828,877,917,953,990,
-1029,1068,1105,1140,1174,1210,1247,1284,1319,1353,1386,1416,1444,1473,1502,1531,1559,1586,1611,1635,1658,
-1678,1696,1714,1735,1758,1781,1801,1820,1842,1869,1898,1923,1942,1959,1979,2005,2033,2053,2057,2051,2041,
-2033,2029,2024,2017,2011,2007,2007,2008,2007,2005,2001,1995,1985,1971,1959,1950,1945,1940,1932,1925,1918,
-1911,1903,1895,1889,1884,1879,1872,1864,1860,1859,1853,1838,1820,1813,1822,1840,1847,1834,1806,1779,1767,
-1767,1773,1779,1782,1779,1770,1756,1742,1729,1715,1693,1665,1639,1621,1612,1604,1594,1589,1598,1620,1642,
-1651,1649,1649,1658,1675,1678,1697,1705,1709,1716,1729,1745,1757,1766,1773,1778,1785,1797,1820,1851,1885,
-1915,1940,1966,1996,2026,2052,2073,2095,2122,2152,2183,2212,2242,2274,2301,2317,2322,2325,2332,2342,2347,
-2348,2352,2367,2393,2417,2433,2441,2451,2466,2483,2495,2501,2507,2519,2535,2551,2562,2571,2582,2594,2604,
-2610,2613,2616,2618,2617,2614,2615,2625,2645,2666,2681,2689,2698,2716,2738,2755,2756,2747,2743,2762,2812,
-2887,2969,3039,3073,3063,3013,2952,2909,2905,2929,2954,2955,2931,2896,2867,2850,2838,2830,2832,2849,2879,
-2912,2939,2958,2973,2984,2986,2975,2954,2932,2917,2909,2905,2904,2905,2908,2910,2909,2905,2901,2901,2904,
-2909,2916,2931,2957,2986,3008,3014,3010,3007,3015,3033,3055,3071,3081,3087,3090,3082,3056,3013,2963,2917,
-2881,2850,2819,2791,2774,2774,2789,2810,2830,2845,2860,2877,2894,2914,2937,2965,2992,3013,3024,3028,3033,
-3042,3053,3066,3083,3110,3148,3191,3236,3283,3341,3411,3483,3542,3582,3608,3629,3645,3649,3638,3623,3613,
-3613,3614,3612,3613,3622,3639,3651,3654,3659,3683,3726,3765,3777,3763,3749,3755,3770,3769,3741,3709,3698,
-3706,3704,3666,3608,3566,3557,3554,3521,3447,3363,3307,3285,3270,3235,3180,3121,3072,3027,2977,2927,2886,
-2853,2815,2758,2690,2628,2585,2555,2528,2502,2483,2476,2475,2467,2452,2434,2422,2415,2408,2401,2399,2405,
-2414,2417,2412,2406,2404,2408,2412,2413,2410,2404,2394,2377,2354,2329,2306,2282,2256,2227,2199,2177,2157,
-2134,2106,2075,2046,2019,1989,1957,1924,1893,1866,1838,1809,1777,1744,1713,1682,1652,1622,1592,1564,1538,
-1514,1491,1465,1435,1402,1372,1348,1329,1311,1291,1270,1253,1237,1220,1199,1180,1168,1161,1154,1140,1121,
-1104,1090,1078,1059,1033,1002,966,925,878,825,766,701,626,545,468,406,364,334,304,265,217,
-168,123,85,50,14,-23,-63,-104,-145,-188,-234,-282,-329,-369,-401,-432,-470,-518,-572,-625,-674,
--721,-769,-816,-857,-896,-937,-984,-1035,-1083,-1127,-1170,-1216,-1264,-1311,-1354,-1396,-1442,-1492,-1540,-1583,-1623,
--1664,-1711,-1760,-1808,-1855,-1902,-1951,-2001,-2051,-2100,-2147,-2193,-2238,-2282,-2326,-2373,-2420,-2466,-2507,-2544,-2579,
--2615,-2652,-2691,-2728,-2764,-2796,-2825,-2855,-2891,-2934,-2980,-3022,-3057,-3087,-3118,-3151,-3186,-3221,-3254,-3286,-3317,
--3347,-3375,-3402,-3427,-3451,-3472,-3491,-3512,-3538,-3566,-3588,-3599,-3603,-3611,-3631,-3662,-3696,-3726,-3756,-3787,-3812,
--3819,-3801,-3771,-3755,-3772,-3819,-3872,-3908,-3917,-3912,-3909,-3915,-3932,-3949,-3960,-3960,-3949,-3936,-3929,-3930,-3933,
--3929,-3912,-3890,-3872,-3865,-3862,-3859,-3857,-3861,-3877,-3897,-3911,-3910,-3899,-3885,-3876,-3871,-3870,-3870,-3874,-3879,
--3880,-3872,-3853,-3827,-3799,-3773,-3748,-3725,-3705,-3689,-3674,-3658,-3637,-3612,-3584,-3558,-3534,-3512,-3491,-3470,-3450,
--3431,-3409,-3380,-3345,-3308,-3277,-3256,-3242,-3228,-3207,-3176,-3137,-3097,-3061,-3032,-3008,-2983,-2955,-2926,-2899,-2876,
--2852,-2824,-2791,-2759,-2732,-2709,-2687,-2659,-2628,-2599,-2573,-2545,-2509,-2461,-2402,-2336,-2269,-2207,-2158,-2122,-2090,
--2042,-1961,-1846,-1708,-1565,-1424,-1285,-1145,-1007,-880,-774,-695,-640,-602,-572,-534,-482,-414,-343,-277,-219,
--162,-99,-28,42,107,166,222,275,321,356,386,419,461,511,558,594,621,648,683,726,774,
-822,873,936,1021,1124,1227,1310,1366,1406,1446,1490,1526,1539,1530,1507,1472,1408,1287,1106,900,727,
-634,621,655,696,725,750,783,826,868,899,922,948,984,1026,1060,1078,1090,1118,1180,1265,1337,
-1359,1325,1263,1214,1204,1223,1246,1255,1251,1246,1250,1260,1272,1286,1305,1336,1374,1416,1455,1490,1525,
-1564,1610,1659,1704,1742,1770,1796,1827,1866,1913,1968,2029,2092,2151,2199,2233,2259,2284,2311,2341,2372,
-2405,2442,2478,2502,2512,2514,2521,2543,2578,2617,2654,2689,2725,2759,2782,2790,2787,2781,2780,2784,2795,
-2815,2846,2886,2930,2975,3025,3089,3166,3245,3313,3364,3401,3432,3453,3454,3430,3385,3330,3272,3204,3116,
-2997,2849,2682,2515,2376,2290,2269,2292,2310,2271,2162,2019,1907,1877,1932,2032,2129,2197,2242,2279,2311,
-2337,2349,2351,2348,2341,2321,2283,2231,2176,2125,2078,2032,1984,1936,1893,1854,1820,1788,1759,1727,1687,
-1641,1604,1589,1589,1581,1543,1485,1444,1451,1493,1519,1481,1384,1283,1230,1232,1251,1247,1213,1173,1151,
-1141,1125,1094,1058,1028,1002,965,910,851,810,795,792,777,743,700,663,639,623,606,586,564,
-544,527,515,504,489,465,429,389,357,338,328,315,291,254,213,175,145,121,99,76,52,
-25,0,-23,-47,-73,-98,-121,-138,-151,-169,-194,-224,-252,-271,-285,-301,-325,-356,-388,-416,-437,
--455,-470,-484,-497,-510,-524,-540,-554,-567,-580,-595,-612,-629,-646,-661,-678,-695,-714,-732,-748,-761,
--771,-780,-793,-810,-831,-851,-867,-880,-894,-911,-928,-941,-948,-955,-964,-975,-982,-984,-982,-983,-986,
--989,-991,-994,-1001,-1013,-1025,-1032,-1035,-1038,-1043,-1049,-1053,-1052,-1050,-1053,-1062,-1074,-1089,-1104,-1120,-1135,
--1149,-1158,-1165,-1171,-1177,-1183,-1188,-1192,-1192,-1189,-1183,-1176,-1173,-1173,-1175,-1177,-1177,-1176,-1175,-1173,-1170,
--1169,-1169,-1172,-1176,-1180,-1183,-1183,-1181,-1177,-1172,-1166,-1158,-1148,-1139,-1136,-1143,-1156,-1165,-1166,-1162,-1160,
--1165,-1172,-1174,-1170,-1166,-1167,-1168,-1163,-1154,-1151,-1164,-1190,-1214,-1222,-1217,-1212,-1215,-1226,-1234,-1235,-1235,
--1238,-1241,-1236,-1223,-1210,-1204,-1210,-1219,-1223,-1219,-1211,-1205,-1201,-1197,-1194,-1189,-1181,-1169,-1156,-1145,-1139,
--1134,-1124,-1107,-1088,-1071,-1063,-1060,-1058,-1053,-1044,-1034,-1024,-1014,-1008,-1004,-1002,-999,-994,-988,-983,-982,
--982,-982,-981,-980,-980,-980,-978,-971,-960,-947,-934,-924,-916,-907,-897,-885,-873,-861,-850,-839,-827,
--818,-811,-806,-798,-785,-765,-744,-723,-706,-692,-679,-667,-655,-642,-631,-622,-614,-604,-593,-581,-572,
--564,-552,-532,-505,-479,-461,-453,-449,-440,-426,-410,-395,-381,-364,-345,-327,-313,-303,-295,-289,-287,
--289,-290,-286,-279,-271,-270,-273,-275,-272,-264,-257,-254,-254,-253,-247,-239,-230,-221,-211,-201,-191,
--178,-162,-141,-115,-91,-73,-59,-43,-23,1,27,51,73,94,118,144,172,203,236,269,301,
-331,360,392,425,458,489,517,547,578,608,636,660,685,716,751,786,817,846,874,905,936,
-966,1000,1041,1084,1119,1138,1143,1145,1143,1123,1067,981,902,886,972,1162,1415,1674,1884,2015,2064,
-2060,2050,2078,2162,2284,2413,2520,2591,2626,2629,2604,2560,2507,2450,2386,2311,2227,2140,2057,1983,1920,
-1872,1843,1832,1827,1815,1793,1773,1764,1765,1763,1749,1726,1709,1707,1715,1718,1709,1687,1666,1653,1654,
-1663,1673,1679,1682,1684,1686,1691,1695,1695,1689,1676,1657,1633,1605,1578,1553,1533,1518,1509,1503,1493,
-1468,1416,1338,1243,1152,1079,1031,1002,982,959,925,872,796,704,605,516,443,386,334,277,210,
-136,61,-6,-66,-116,-161,-202,-242,-279,-308,-330,-349,-369,-394,-422,-445,-461,-472,-485,-500,-515,
--525,-531,-539,-551,-566,-578,-586,-593,-606,-624,-641,-652,-659,-669,-683,-699,-710,-715,-717,-717,-716,
--711,-703,-694,-689,-686,-682,-675,-666,-659,-653,-647,-637,-624,-608,-590,-567,-538,-506,-473,-442,-411,
--377,-336,-292,-247,-205,-165,-127,-90,-54,-21,13,53,100,152,204,249,286,316,346,380,423,
-473,525,573,615,651,686,727,772,818,859,895,931,971,1016,1061,1103,1140,1177,1214,1251,1288,
-1322,1354,1386,1418,1451,1484,1517,1547,1574,1599,1621,1641,1658,1673,1690,1710,1736,1764,1790,1811,1832,
-1857,1888,1919,1943,1959,1973,1993,2020,2048,2068,2074,2070,2064,2058,2054,2047,2040,2036,2037,2039,2041,
-2040,2038,2033,2024,2009,1995,1989,1995,2006,2010,1998,1973,1948,1932,1927,1927,1925,1920,1913,1906,1902,
-1900,1897,1889,1875,1862,1857,1861,1868,1865,1850,1828,1808,1798,1798,1806,1815,1819,1810,1790,1768,1753,
-1743,1727,1697,1659,1632,1627,1637,1638,1621,1595,1583,1593,1614,1630,1636,1642,1656,1678,1673,1691,1698,
-1699,1705,1720,1739,1753,1760,1764,1770,1779,1794,1817,1848,1882,1915,1943,1970,2000,2030,2058,2081,2103,
-2127,2155,2184,2213,2241,2267,2288,2303,2311,2318,2327,2334,2337,2336,2337,2349,2373,2399,2419,2432,2442,
-2455,2469,2482,2491,2500,2512,2528,2547,2568,2589,2607,2619,2621,2618,2618,2623,2630,2631,2624,2618,2624,
-2646,2673,2692,2697,2698,2708,2726,2741,2740,2725,2714,2726,2769,2830,2889,2925,2929,2903,2863,2831,2833,
-2875,2937,2985,2989,2948,2886,2834,2808,2809,2827,2856,2894,2936,2973,2999,3014,3022,3027,3025,3014,2997,
-2979,2963,2952,2946,2944,2948,2956,2962,2961,2953,2942,2933,2928,2928,2937,2958,2988,3018,3035,3034,3022,
-3015,3022,3039,3060,3077,3089,3098,3101,3092,3065,3024,2980,2942,2912,2885,2857,2832,2820,2823,2839,2859,
-2877,2892,2909,2929,2952,2977,3005,3034,3062,3083,3094,3100,3107,3119,3134,3149,3166,3190,3224,3264,3306,
-3352,3408,3474,3542,3598,3636,3660,3676,3688,3692,3685,3676,3670,3672,3676,3678,3684,3699,3719,3735,3745,
-3760,3791,3834,3866,3869,3850,3834,3838,3852,3848,3820,3787,3770,3765,3744,3690,3624,3584,3583,3590,3561,
-3485,3395,3330,3302,3286,3252,3197,3136,3085,3043,3001,2958,2918,2878,2829,2764,2693,2633,2595,2573,2554,
-2533,2516,2508,2502,2492,2475,2457,2444,2436,2429,2422,2419,2423,2430,2432,2427,2421,2419,2421,2424,2424,
-2421,2415,2403,2384,2363,2343,2325,2306,2281,2253,2226,2206,2190,2171,2147,2120,2093,2067,2039,2007,1974,
-1942,1912,1882,1850,1816,1785,1755,1725,1693,1661,1629,1600,1575,1552,1529,1502,1473,1442,1415,1392,1372,
-1351,1330,1308,1289,1271,1253,1235,1223,1215,1209,1197,1178,1160,1150,1145,1139,1122,1095,1063,1029,989,
-938,874,800,719,637,560,497,453,424,398,362,315,264,220,184,151,115,75,33,-7,-48,
--91,-136,-181,-224,-264,-300,-334,-371,-413,-460,-511,-563,-613,-663,-711,-755,-796,-836,-880,-928,-978,
--1024,-1067,-1111,-1160,-1210,-1255,-1294,-1331,-1374,-1424,-1476,-1523,-1566,-1606,-1650,-1695,-1742,-1789,-1839,-1890,-1942,
--1991,-2038,-2086,-2135,-2184,-2230,-2274,-2319,-2367,-2415,-2460,-2499,-2535,-2570,-2605,-2640,-2677,-2714,-2750,-2785,-2819,
--2854,-2892,-2931,-2970,-3005,-3037,-3069,-3102,-3135,-3169,-3203,-3237,-3273,-3307,-3337,-3363,-3387,-3410,-3429,-3445,-3458,
--3470,-3483,-3496,-3510,-3527,-3552,-3583,-3615,-3642,-3662,-3681,-3704,-3726,-3739,-3737,-3731,-3737,-3765,-3808,-3846,-3863,
--3860,-3848,-3843,-3851,-3867,-3887,-3901,-3906,-3900,-3890,-3882,-3883,-3887,-3888,-3880,-3865,-3850,-3839,-3833,-3828,-3828,
--3837,-3857,-3880,-3894,-3893,-3881,-3865,-3854,-3847,-3845,-3843,-3839,-3831,-3815,-3793,-3767,-3744,-3727,-3711,-3695,-3677,
--3659,-3644,-3632,-3618,-3598,-3572,-3544,-3519,-3498,-3479,-3459,-3437,-3416,-3397,-3376,-3351,-3319,-3285,-3256,-3235,-3221,
--3205,-3180,-3145,-3104,-3066,-3036,-3014,-2995,-2972,-2942,-2908,-2877,-2851,-2828,-2803,-2774,-2744,-2717,-2693,-2668,-2638,
--2603,-2568,-2535,-2501,-2465,-2425,-2379,-2329,-2274,-2217,-2165,-2123,-2088,-2049,-1994,-1917,-1823,-1718,-1605,-1481,-1347,
--1208,-1075,-956,-858,-781,-724,-679,-633,-576,-505,-429,-358,-295,-234,-165,-87,-6,71,142,207,264,
-311,348,378,411,452,500,549,590,619,643,668,703,751,810,878,958,1050,1148,1239,1303,1335,
-1344,1351,1368,1391,1407,1410,1399,1370,1305,1182,1002,802,640,558,555,593,631,655,674,706,753,
-800,834,855,877,911,955,994,1017,1029,1050,1097,1163,1221,1241,1216,1169,1134,1130,1152,1176,1187,
-1185,1181,1185,1195,1209,1222,1238,1262,1295,1333,1369,1400,1431,1468,1515,1568,1617,1655,1684,1716,1759,
-1813,1871,1925,1975,2025,2074,2117,2150,2176,2201,2233,2270,2312,2357,2405,2451,2486,2502,2505,2508,2521,
-2544,2570,2592,2612,2635,2664,2694,2719,2736,2744,2745,2743,2743,2754,2780,2819,2861,2901,2944,3001,3076,
-3158,3231,3285,3321,3346,3359,3356,3331,3290,3241,3185,3113,3008,2861,2676,2474,2286,2148,2085,2094,2142,
-2174,2148,2063,1964,1912,1940,2032,2140,2222,2268,2291,2310,2325,2330,2323,2312,2305,2298,2279,2237,2180,
-2120,2068,2021,1974,1927,1882,1842,1804,1764,1723,1688,1657,1624,1584,1546,1525,1521,1517,1488,1437,1396,
-1399,1443,1480,1462,1381,1279,1207,1181,1178,1167,1142,1121,1118,1122,1111,1076,1033,996,966,928,874,
-816,776,761,759,746,713,670,632,609,597,587,571,550,528,509,497,489,481,465,437,402,
-367,340,321,306,287,260,225,186,150,120,97,76,54,29,3,-20,-44,-71,-99,-125,-145,
--160,-178,-204,-235,-264,-284,-296,-310,-330,-357,-386,-413,-439,-464,-488,-508,-524,-539,-555,-569,-582,
--593,-604,-616,-629,-640,-650,-662,-678,-698,-720,-742,-760,-775,-785,-794,-806,-823,-844,-865,-883,-897,
--911,-927,-944,-957,-964,-969,-977,-988,-998,-1002,-1003,-1004,-1006,-1008,-1009,-1012,-1018,-1030,-1041,-1048,-1052,
--1055,-1062,-1070,-1075,-1075,-1072,-1072,-1077,-1087,-1098,-1111,-1124,-1137,-1149,-1160,-1168,-1174,-1179,-1185,-1191,-1199,
--1203,-1202,-1194,-1184,-1176,-1172,-1172,-1174,-1175,-1175,-1176,-1177,-1178,-1179,-1180,-1182,-1186,-1190,-1193,-1194,-1191,
--1184,-1176,-1169,-1163,-1157,-1150,-1145,-1146,-1155,-1167,-1179,-1185,-1186,-1180,-1170,-1162,-1162,-1175,-1196,-1212,-1212,
--1200,-1193,-1202,-1223,-1241,-1242,-1230,-1217,-1215,-1223,-1233,-1242,-1251,-1259,-1262,-1254,-1238,-1222,-1216,-1221,-1230,
--1233,-1231,-1225,-1218,-1211,-1204,-1197,-1192,-1186,-1176,-1164,-1152,-1145,-1141,-1134,-1120,-1101,-1084,-1074,-1070,-1067,
--1060,-1050,-1037,-1024,-1013,-1005,-1000,-997,-995,-991,-986,-983,-982,-983,-983,-984,-985,-986,-986,-983,-976,
--965,-953,-941,-930,-920,-910,-901,-893,-885,-877,-869,-860,-851,-843,-835,-825,-812,-795,-775,-753,-733,
--717,-705,-696,-685,-671,-654,-639,-627,-618,-605,-587,-567,-551,-542,-533,-518,-494,-468,-450,-442,-438,
--432,-420,-405,-393,-382,-370,-354,-338,-322,-308,-296,-288,-285,-287,-288,-285,-278,-271,-269,-270,-269,
--263,-254,-248,-246,-245,-241,-233,-225,-220,-214,-206,-197,-188,-179,-165,-143,-116,-90,-71,-57,-43,
--22,3,30,54,75,97,121,148,176,205,236,268,298,326,355,387,421,452,480,508,538,
-571,602,628,651,677,709,745,777,802,827,854,887,920,952,987,1027,1067,1096,1110,1113,1116,
-1115,1092,1032,947,883,896,1019,1241,1512,1770,1963,2064,2081,2055,2041,2084,2187,2320,2442,2529,2577,
-2592,2577,2534,2472,2406,2347,2292,2233,2163,2087,2011,1939,1874,1821,1788,1775,1772,1763,1743,1721,1710,
-1713,1717,1711,1697,1685,1684,1691,1692,1679,1656,1634,1622,1620,1625,1633,1642,1651,1659,1667,1674,1682,
-1687,1686,1676,1658,1635,1609,1583,1556,1530,1504,1481,1460,1438,1407,1361,1297,1221,1144,1076,1023,982,
-948,912,867,805,721,618,510,418,353,313,278,231,166,92,22,-36,-86,-133,-178,-220,-254,
--282,-306,-328,-349,-370,-392,-413,-432,-448,-462,-477,-494,-510,-523,-531,-538,-548,-561,-572,-582,-591,
--604,-621,-638,-651,-661,-673,-687,-701,-712,-717,-718,-716,-713,-708,-701,-695,-690,-687,-681,-674,-666,
--657,-648,-636,-624,-611,-599,-583,-560,-531,-500,-473,-448,-419,-382,-337,-290,-244,-202,-163,-123,-85,
--49,-17,14,51,95,145,196,245,288,327,367,410,458,507,554,595,629,662,696,734,776,
-817,855,892,932,975,1022,1067,1109,1146,1182,1217,1252,1285,1317,1347,1378,1413,1450,1486,1520,1550,
-1576,1599,1620,1639,1657,1674,1695,1721,1753,1786,1814,1838,1859,1883,1910,1937,1958,1974,1988,2009,2036,
-2063,2082,2091,2091,2089,2084,2078,2071,2065,2064,2067,2071,2073,2073,2072,2066,2054,2036,2024,2031,2058,
-2090,2102,2079,2031,1980,1950,1944,1952,1959,1957,1951,1946,1945,1943,1939,1931,1924,1923,1925,1925,1916,
-1898,1878,1862,1853,1849,1846,1844,1842,1836,1821,1800,1784,1780,1782,1771,1739,1698,1677,1690,1717,1725,
-1694,1640,1597,1586,1600,1618,1627,1635,1650,1673,1656,1675,1686,1692,1703,1721,1739,1749,1752,1755,1766,
-1781,1800,1822,1851,1886,1923,1955,1982,2007,2034,2062,2087,2110,2131,2153,2177,2200,2222,2243,2263,2281,
-2294,2305,2313,2317,2319,2318,2320,2330,2350,2375,2398,2416,2430,2444,2459,2473,2486,2498,2512,2530,2553,
-2580,2608,2629,2638,2633,2621,2612,2614,2622,2628,2629,2629,2638,2659,2684,2701,2707,2708,2715,2728,2738,
-2734,2719,2708,2716,2743,2777,2800,2804,2793,2779,2774,2790,2834,2900,2967,3005,2993,2938,2867,2813,2796,
-2811,2846,2890,2935,2978,3012,3034,3043,3046,3047,3048,3045,3038,3026,3012,2999,2992,2993,3001,3013,3019,
-3016,3004,2987,2971,2959,2954,2960,2980,3009,3036,3051,3051,3043,3038,3042,3054,3069,3087,3105,3121,3128,
-3118,3091,3052,3013,2979,2948,2919,2891,2870,2862,2869,2887,2907,2927,2945,2965,2988,3012,3037,3066,3099,
-3130,3154,3169,3178,3187,3201,3218,3235,3254,3276,3305,3341,3381,3427,3480,3540,3598,3646,3679,3700,3715,
-3727,3734,3735,3734,3735,3738,3741,3746,3758,3778,3803,3823,3839,3858,3889,3924,3943,3934,3910,3897,3904,
-3918,3913,3885,3855,3840,3829,3793,3719,3632,3576,3568,3579,3564,3503,3421,3356,3321,3298,3264,3212,3158,
-3113,3076,3037,2992,2944,2894,2839,2775,2711,2659,2626,2605,2586,2566,2548,2537,2527,2513,2493,2475,2462,
-2455,2449,2443,2439,2440,2443,2444,2440,2435,2431,2430,2431,2431,2429,2423,2411,2393,2375,2359,2347,2332,
-2309,2282,2257,2239,2225,2209,2188,2163,2137,2112,2086,2056,2025,1993,1961,1927,1891,1856,1825,1796,1767,
-1734,1700,1668,1639,1614,1591,1565,1538,1509,1481,1454,1430,1407,1384,1363,1343,1324,1307,1290,1276,1267,
-1261,1251,1235,1216,1205,1207,1213,1212,1195,1165,1131,1094,1049,988,911,824,738,660,595,546,513,
-487,457,414,362,314,278,250,221,183,138,94,51,9,-35,-82,-125,-162,-196,-231,-270,-312,
--357,-403,-451,-502,-554,-605,-653,-696,-737,-780,-826,-875,-921,-963,-1004,-1050,-1103,-1155,-1201,-1238,-1271,
--1309,-1357,-1411,-1463,-1509,-1551,-1592,-1634,-1679,-1728,-1780,-1833,-1884,-1930,-1975,-2023,-2073,-2123,-2170,-2214,-2258,
--2305,-2353,-2399,-2441,-2480,-2515,-2549,-2583,-2617,-2655,-2694,-2735,-2773,-2810,-2845,-2881,-2917,-2953,-2987,-3022,-3057,
--3090,-3122,-3152,-3184,-3218,-3252,-3281,-3306,-3328,-3352,-3377,-3400,-3418,-3429,-3437,-3447,-3463,-3486,-3514,-3543,-3567,
--3584,-3595,-3605,-3617,-3631,-3643,-3655,-3672,-3700,-3735,-3767,-3782,-3780,-3769,-3762,-3767,-3780,-3797,-3812,-3824,-3833,
--3836,-3834,-3831,-3830,-3833,-3837,-3837,-3832,-3823,-3810,-3797,-3786,-3782,-3789,-3806,-3824,-3834,-3831,-3817,-3799,-3785,
--3778,-3776,-3776,-3772,-3759,-3734,-3704,-3676,-3659,-3652,-3649,-3641,-3626,-3609,-3594,-3582,-3570,-3554,-3531,-3506,-3483,
--3465,-3449,-3431,-3410,-3386,-3363,-3341,-3319,-3295,-3270,-3246,-3226,-3209,-3190,-3163,-3127,-3088,-3051,-3024,-3005,-2987,
--2965,-2935,-2901,-2870,-2842,-2818,-2792,-2764,-2735,-2709,-2684,-2657,-2625,-2591,-2554,-2518,-2481,-2443,-2404,-2365,-2324,
--2278,-2227,-2175,-2128,-2085,-2039,-1984,-1919,-1848,-1774,-1697,-1609,-1508,-1399,-1288,-1180,-1078,-984,-900,-825,-754,
--678,-596,-512,-436,-369,-305,-234,-153,-64,26,111,188,251,300,336,364,396,437,487,538,582,
-612,630,647,676,727,800,886,975,1060,1134,1191,1221,1224,1213,1207,1216,1236,1256,1265,1262,1242,
-1189,1081,917,728,570,487,481,519,562,590,611,643,688,733,765,784,803,835,878,922,951,
-966,980,1007,1046,1083,1098,1088,1066,1054,1063,1088,1111,1120,1116,1109,1110,1123,1142,1163,1182,1202,
-1225,1252,1280,1307,1338,1378,1428,1480,1525,1555,1580,1616,1675,1752,1830,1894,1942,1980,2015,2046,2071,
-2090,2111,2142,2184,2234,2290,2347,2402,2446,2477,2495,2510,2527,2546,2558,2561,2559,2563,2577,2603,2633,
-2662,2683,2695,2698,2697,2704,2725,2756,2790,2822,2859,2912,2985,3068,3141,3194,3226,3244,3254,3252,3233,
-3197,3149,3089,3012,2904,2754,2565,2357,2166,2029,1971,1986,2036,2069,2053,1997,1945,1944,2009,2115,2215,
-2279,2307,2318,2324,2326,2316,2297,2278,2266,2257,2235,2190,2130,2069,2014,1965,1915,1867,1825,1790,1753,
-1709,1661,1620,1591,1565,1531,1492,1462,1451,1444,1417,1367,1321,1316,1360,1419,1439,1394,1305,1214,1147,
-1104,1072,1053,1054,1073,1090,1080,1041,991,951,923,892,845,791,750,732,727,717,687,646,607,
-583,571,563,551,533,513,495,483,477,470,459,439,412,381,350,323,301,280,257,228,193,
-156,124,99,78,55,29,3,-21,-45,-73,-103,-132,-154,-170,-187,-212,-243,-272,-293,-308,-321,
--339,-360,-383,-407,-434,-464,-495,-522,-544,-562,-580,-597,-610,-621,-630,-640,-649,-658,-665,-674,-687,
--704,-724,-745,-766,-786,-803,-816,-830,-846,-867,-886,-902,-914,-926,-942,-960,-974,-981,-986,-994,-1006,
--1018,-1025,-1027,-1027,-1027,-1029,-1030,-1033,-1039,-1048,-1057,-1062,-1065,-1069,-1076,-1085,-1091,-1093,-1092,-1091,-1095,
--1102,-1110,-1120,-1129,-1140,-1150,-1160,-1168,-1174,-1177,-1180,-1185,-1192,-1200,-1202,-1199,-1191,-1183,-1178,-1176,-1175,
--1174,-1175,-1178,-1183,-1188,-1190,-1191,-1191,-1192,-1196,-1201,-1203,-1201,-1194,-1185,-1178,-1175,-1173,-1171,-1168,-1168,
--1172,-1181,-1189,-1194,-1191,-1180,-1165,-1155,-1160,-1181,-1211,-1234,-1239,-1231,-1223,-1228,-1244,-1257,-1257,-1244,-1230,
--1224,-1227,-1236,-1249,-1263,-1274,-1276,-1266,-1250,-1237,-1233,-1237,-1242,-1242,-1239,-1236,-1232,-1225,-1215,-1204,-1197,
--1191,-1182,-1168,-1153,-1142,-1136,-1132,-1124,-1111,-1098,-1089,-1083,-1077,-1067,-1055,-1041,-1027,-1014,-1003,-996,-993,
--990,-988,-986,-983,-982,-982,-983,-986,-988,-990,-989,-985,-978,-969,-960,-952,-943,-932,-921,-911,-902,
--894,-885,-877,-869,-861,-852,-842,-830,-815,-800,-785,-770,-756,-744,-735,-727,-719,-705,-688,-670,-655,
--642,-625,-601,-574,-552,-539,-531,-518,-497,-472,-452,-441,-434,-426,-414,-401,-390,-382,-373,-361,-346,
--330,-314,-299,-288,-283,-283,-283,-279,-271,-264,-262,-262,-259,-252,-244,-239,-236,-231,-222,-211,-205,
--202,-199,-192,-183,-175,-169,-162,-146,-123,-100,-81,-66,-50,-28,-2,21,43,65,90,119,149,
-177,204,234,263,292,318,347,379,412,443,470,497,528,561,590,614,635,660,693,727,756,
-778,802,834,871,907,939,972,1010,1047,1073,1086,1091,1097,1096,1069,1002,917,866,906,1062,1312,
-1599,1855,2031,2103,2090,2044,2031,2088,2210,2350,2463,2530,2556,2554,2528,2478,2412,2346,2289,2238,2179,
-2106,2025,1948,1883,1828,1782,1751,1736,1727,1713,1690,1667,1657,1663,1672,1672,1663,1656,1659,1668,1670,
-1658,1638,1619,1605,1596,1592,1593,1600,1611,1620,1629,1637,1649,1660,1664,1658,1644,1629,1614,1598,1575,
-1545,1509,1470,1430,1387,1341,1292,1242,1190,1138,1083,1025,963,900,835,770,699,613,512,408,320,
-265,237,216,180,123,55,-6,-57,-103,-149,-195,-234,-261,-282,-303,-328,-352,-372,-388,-403,-420,
--437,-454,-471,-487,-504,-518,-530,-539,-549,-562,-576,-589,-600,-611,-624,-638,-652,-664,-675,-688,-700,
--709,-714,-716,-714,-709,-703,-696,-691,-686,-680,-675,-670,-665,-657,-643,-625,-608,-595,-585,-571,-548,
--517,-489,-467,-450,-427,-393,-350,-303,-257,-213,-170,-127,-86,-48,-13,21,58,98,141,187,234,
-280,326,374,425,479,531,575,611,640,669,703,742,785,829,871,914,958,1002,1046,1087,1125,
-1160,1194,1226,1256,1285,1313,1343,1375,1411,1449,1486,1518,1545,1569,1592,1616,1641,1667,1693,1720,1752,
-1786,1819,1848,1871,1891,1911,1932,1953,1972,1989,2008,2031,2058,2084,2103,2114,2119,2119,2116,2109,2101,
-2096,2096,2098,2101,2102,2103,2104,2100,2086,2067,2057,2072,2111,2154,2169,2139,2077,2015,1979,1976,1990,
-2002,2003,1997,1992,1990,1987,1979,1970,1968,1976,1986,1986,1970,1945,1923,1914,1915,1916,1907,1891,1871,
-1850,1826,1805,1793,1796,1803,1794,1763,1726,1716,1742,1780,1788,1745,1671,1609,1586,1595,1612,1620,1623,
-1635,1656,1644,1666,1681,1692,1706,1723,1736,1742,1744,1752,1770,1793,1815,1835,1861,1896,1935,1968,1991,
-2011,2032,2059,2087,2111,2131,2149,2166,2182,2198,2216,2237,2260,2280,2292,2297,2297,2297,2300,2307,2319,
-2335,2354,2376,2397,2417,2435,2453,2470,2486,2502,2519,2538,2561,2586,2610,2629,2639,2640,2634,2626,2619,
-2616,2619,2626,2638,2655,2674,2691,2704,2713,2722,2733,2742,2743,2733,2718,2708,2710,2723,2735,2741,2742,
-2747,2764,2795,2838,2888,2938,2975,2983,2956,2903,2848,2814,2813,2837,2875,2918,2960,3000,3033,3055,3064,
-3068,3070,3075,3078,3075,3067,3055,3045,3040,3043,3050,3058,3061,3057,3048,3037,3025,3013,3005,3005,3015,
-3033,3052,3063,3067,3066,3064,3066,3072,3086,3108,3137,3161,3170,3157,3126,3088,3052,3019,2986,2954,2925,
-2908,2904,2914,2932,2955,2979,3003,3026,3048,3069,3093,3122,3157,3192,3222,3245,3260,3273,3289,3307,3327,
-3347,3369,3394,3426,3464,3508,3558,3610,3658,3697,3727,3748,3763,3774,3781,3786,3790,3795,3799,3806,3819,
-3842,3873,3902,3921,3932,3946,3970,3994,4002,3988,3966,3958,3968,3978,3965,3935,3908,3900,3894,3855,3768,
-3661,3583,3559,3567,3560,3515,3444,3379,3337,3308,3273,3229,3183,3145,3110,3069,3020,2966,2911,2857,2801,
-2748,2703,2669,2643,2620,2598,2580,2566,2552,2533,2512,2494,2483,2477,2471,2463,2456,2454,2455,2455,2451,
-2446,2441,2439,2439,2439,2438,2434,2423,2407,2392,2380,2371,2358,2339,2314,2293,2277,2263,2247,2225,2200,
-2175,2152,2126,2098,2069,2039,2008,1974,1936,1901,1869,1841,1811,1777,1742,1709,1680,1654,1628,1601,1572,
-1544,1517,1490,1463,1436,1413,1392,1375,1359,1343,1329,1319,1311,1303,1289,1270,1257,1257,1271,1286,1285,
-1265,1231,1193,1151,1097,1024,935,845,765,700,649,609,577,546,509,461,411,368,338,314,285,
-245,198,153,110,66,20,-25,-65,-97,-128,-164,-208,-255,-302,-347,-394,-445,-497,-547,-592,-634,
--677,-724,-773,-820,-863,-902,-942,-987,-1039,-1092,-1138,-1176,-1210,-1249,-1296,-1349,-1403,-1453,-1496,-1535,-1574,
--1617,-1666,-1720,-1774,-1824,-1870,-1914,-1961,-2010,-2059,-2106,-2149,-2192,-2237,-2282,-2327,-2370,-2411,-2450,-2488,-2524,
--2559,-2596,-2635,-2676,-2716,-2753,-2790,-2827,-2864,-2900,-2935,-2972,-3009,-3044,-3077,-3107,-3136,-3167,-3198,-3225,-3247,
--3268,-3293,-3323,-3355,-3381,-3398,-3408,-3418,-3433,-3453,-3474,-3491,-3505,-3516,-3525,-3533,-3539,-3545,-3553,-3568,-3594,
--3628,-3660,-3678,-3679,-3671,-3667,-3676,-3695,-3714,-3725,-3729,-3733,-3741,-3753,-3761,-3765,-3764,-3765,-3769,-3776,-3781,
--3778,-3766,-3748,-3731,-3723,-3727,-3740,-3755,-3762,-3759,-3745,-3725,-3707,-3697,-3696,-3701,-3702,-3690,-3665,-3633,-3608,
--3595,-3594,-3596,-3590,-3577,-3559,-3543,-3532,-3523,-3511,-3494,-3473,-3451,-3434,-3421,-3409,-3392,-3369,-3340,-3313,-3290,
--3271,-3254,-3235,-3214,-3192,-3168,-3141,-3110,-3075,-3041,-3012,-2989,-2969,-2947,-2920,-2891,-2862,-2835,-2808,-2780,-2750,
--2721,-2695,-2669,-2642,-2611,-2579,-2547,-2513,-2477,-2437,-2397,-2358,-2317,-2271,-2221,-2171,-2125,-2082,-2033,-1975,-1910,
--1846,-1789,-1735,-1676,-1609,-1536,-1460,-1380,-1292,-1194,-1091,-987,-888,-792,-697,-604,-518,-440,-369,-296,-217,
--130,-38,55,141,214,265,299,324,352,392,442,493,535,561,576,592,625,685,771,866,951,
-1014,1050,1063,1058,1042,1027,1025,1039,1063,1082,1093,1095,1086,1049,961,817,644,494,411,403,443,
-492,529,558,590,631,670,698,715,733,762,802,844,875,894,907,925,950,974,989,991,989,
-993,1008,1030,1047,1052,1045,1034,1032,1045,1071,1102,1127,1145,1159,1173,1193,1221,1258,1302,1352,1397,
-1430,1448,1467,1506,1577,1672,1770,1849,1903,1938,1964,1984,1997,2005,2018,2043,2085,2142,2207,2275,2338,
-2393,2438,2473,2504,2532,2552,2558,2552,2538,2526,2523,2530,2545,2567,2591,2612,2628,2639,2651,2669,2692,
-2716,2742,2778,2831,2903,2982,3050,3098,3127,3146,3159,3161,3145,3106,3048,2978,2897,2799,2672,2512,2330,
-2156,2027,1967,1969,2002,2023,2013,1983,1969,2001,2078,2174,2254,2299,2317,2322,2324,2320,2304,2277,2252,
-2234,2218,2191,2147,2089,2028,1968,1910,1852,1800,1758,1726,1691,1646,1596,1554,1527,1505,1477,1440,1409,
-1394,1385,1359,1305,1248,1227,1264,1334,1388,1385,1325,1237,1151,1082,1032,1004,1002,1019,1033,1021,981,
-932,894,871,850,817,772,731,708,699,689,666,630,593,565,547,535,521,505,488,476,470,
-467,461,450,433,413,390,363,334,305,278,252,225,194,160,128,101,77,51,24,-2,-25,
--48,-75,-106,-136,-159,-177,-196,-221,-251,-277,-297,-312,-328,-348,-369,-388,-409,-434,-466,-500,-531,
--556,-578,-600,-620,-637,-649,-658,-666,-673,-680,-686,-693,-703,-716,-730,-748,-770,-795,-820,-841,-859,
--877,-896,-913,-925,-933,-941,-955,-972,-988,-998,-1005,-1014,-1027,-1039,-1047,-1048,-1047,-1047,-1049,-1051,-1053,
--1057,-1062,-1069,-1075,-1079,-1083,-1089,-1095,-1100,-1103,-1104,-1105,-1109,-1115,-1122,-1130,-1139,-1147,-1155,-1162,-1167,
--1171,-1172,-1172,-1175,-1181,-1190,-1196,-1196,-1193,-1188,-1185,-1183,-1181,-1177,-1175,-1176,-1182,-1189,-1193,-1193,-1192,
--1193,-1197,-1203,-1208,-1208,-1204,-1198,-1193,-1192,-1192,-1193,-1195,-1198,-1201,-1204,-1204,-1200,-1192,-1181,-1169,-1163,
--1167,-1182,-1202,-1218,-1222,-1219,-1217,-1224,-1240,-1254,-1259,-1255,-1247,-1240,-1238,-1243,-1254,-1268,-1281,-1283,-1274,
--1261,-1251,-1249,-1250,-1248,-1242,-1237,-1236,-1235,-1230,-1220,-1208,-1201,-1197,-1191,-1178,-1161,-1146,-1138,-1133,-1126,
--1117,-1106,-1097,-1088,-1079,-1067,-1054,-1042,-1029,-1016,-1004,-995,-990,-989,-989,-988,-986,-983,-981,-982,-985,
--988,-990,-988,-983,-977,-971,-966,-961,-955,-947,-936,-925,-913,-902,-892,-882,-874,-865,-856,-845,-832,
--818,-806,-796,-786,-776,-765,-756,-749,-742,-731,-717,-700,-684,-668,-649,-622,-592,-567,-550,-540,-528,
--510,-487,-465,-449,-436,-423,-408,-393,-380,-370,-361,-349,-336,-321,-306,-292,-282,-277,-275,-271,-265,
--256,-251,-249,-249,-245,-238,-232,-228,-224,-215,-203,-191,-185,-185,-183,-176,-166,-158,-154,-151,-141,
--124,-104,-87,-70,-52,-29,-6,14,34,57,87,119,149,176,202,230,260,287,313,338,368,
-400,432,460,489,521,554,582,604,625,649,680,711,736,757,784,821,862,898,929,960,996,
-1032,1058,1072,1081,1091,1089,1056,982,897,858,921,1102,1371,1663,1908,2058,2100,2063,2011,2007,2083,
-2219,2361,2462,2511,2523,2516,2492,2447,2385,2322,2267,2212,2143,2056,1966,1891,1839,1802,1772,1745,1723,
-1702,1677,1647,1623,1616,1624,1634,1633,1624,1618,1625,1639,1647,1643,1628,1610,1593,1578,1566,1560,1561,
-1566,1570,1573,1581,1596,1613,1621,1618,1610,1604,1603,1598,1579,1544,1501,1454,1404,1348,1287,1230,1185,
-1153,1124,1083,1021,935,837,740,655,578,500,414,326,252,206,185,168,137,86,25,-30,-76,
--120,-165,-209,-243,-265,-283,-304,-331,-356,-372,-382,-393,-409,-430,-449,-464,-478,-493,-508,-521,-533,
--545,-561,-579,-595,-608,-618,-630,-642,-655,-667,-677,-686,-695,-703,-710,-713,-711,-705,-698,-690,-684,
--678,-672,-667,-664,-662,-655,-640,-619,-600,-587,-577,-562,-537,-505,-476,-458,-445,-430,-404,-368,-326,
--280,-232,-182,-133,-89,-50,-13,23,61,100,141,185,232,280,327,375,426,483,539,587,623,
-651,679,714,756,802,848,894,939,982,1024,1063,1099,1136,1172,1206,1237,1266,1293,1322,1353,1386,
-1421,1457,1492,1522,1547,1570,1596,1626,1659,1694,1727,1759,1791,1823,1851,1877,1898,1916,1934,1951,1969,
-1987,2007,2031,2057,2084,2108,2126,2140,2148,2151,2148,2142,2134,2130,2129,2130,2130,2130,2131,2133,2131,
-2118,2099,2088,2100,2134,2169,2179,2152,2098,2048,2023,2026,2041,2051,2049,2041,2036,2034,2030,2020,2008,
-2001,2005,2014,2016,2004,1983,1966,1961,1964,1962,1949,1926,1900,1873,1845,1818,1799,1792,1788,1771,1737,
-1704,1697,1724,1760,1764,1720,1650,1596,1581,1597,1615,1620,1619,1626,1644,1649,1669,1683,1692,1704,1718,
-1730,1737,1745,1761,1787,1815,1836,1853,1874,1906,1942,1972,1991,2006,2025,2051,2078,2102,2120,2136,2151,
-2165,2177,2193,2215,2242,2267,2281,2283,2279,2280,2289,2302,2316,2330,2346,2364,2386,2408,2431,2454,2476,
-2496,2512,2528,2543,2559,2574,2586,2600,2620,2646,2670,2678,2668,2646,2629,2630,2646,2668,2685,2694,2702,
-2715,2732,2746,2749,2739,2722,2706,2698,2700,2709,2721,2737,2761,2796,2837,2878,2910,2932,2944,2944,2931,
-2904,2871,2845,2836,2847,2872,2903,2938,2976,3015,3051,3077,3092,3100,3105,3109,3110,3107,3101,3094,3090,
-3089,3088,3087,3083,3080,3081,3084,3088,3088,3082,3072,3063,3062,3066,3074,3081,3087,3091,3092,3092,3095,
-3110,3141,3178,3205,3209,3188,3153,3117,3085,3054,3021,2988,2964,2953,2954,2963,2978,3000,3026,3054,3079,
-3100,3120,3144,3175,3211,3249,3284,3314,3338,3359,3378,3397,3419,3441,3464,3488,3517,3553,3595,3640,3684,
-3722,3756,3784,3806,3821,3828,3831,3836,3842,3849,3857,3871,3899,3941,3986,4016,4025,4020,4019,4032,4049,
-4054,4042,4027,4024,4031,4028,4001,3961,3935,3935,3938,3905,3819,3707,3617,3579,3577,3570,3531,3466,3401,
-3353,3319,3286,3248,3207,3170,3132,3090,3040,2987,2935,2884,2833,2785,2741,2705,2675,2651,2631,2615,2599,
-2581,2558,2536,2520,2511,2505,2496,2484,2474,2470,2469,2468,2464,2459,2454,2451,2450,2451,2451,2447,2437,
-2424,2411,2402,2395,2384,2368,2348,2331,2316,2302,2282,2258,2234,2211,2189,2165,2137,2109,2081,2052,2020,
-1985,1951,1919,1889,1856,1820,1783,1750,1721,1694,1666,1638,1609,1581,1553,1524,1494,1467,1444,1426,1410,
-1394,1379,1368,1361,1355,1345,1326,1307,1299,1310,1333,1350,1345,1318,1280,1240,1194,1133,1050,956,869,
-802,753,713,675,636,596,554,509,465,428,400,375,342,300,253,207,164,121,76,33,-3,
--33,-64,-103,-149,-198,-245,-291,-338,-389,-439,-485,-527,-569,-615,-664,-712,-757,-798,-838,-879,-925,
--973,-1021,-1065,-1105,-1144,-1186,-1234,-1287,-1342,-1392,-1436,-1475,-1512,-1553,-1601,-1655,-1710,-1763,-1811,-1857,-1903,
--1950,-1998,-2043,-2087,-2130,-2174,-2217,-2259,-2301,-2344,-2388,-2431,-2471,-2508,-2544,-2581,-2620,-2657,-2695,-2733,-2772,
--2810,-2845,-2879,-2914,-2952,-2990,-3026,-3059,-3089,-3119,-3150,-3178,-3201,-3223,-3248,-3280,-3313,-3341,-3360,-3372,-3384,
--3398,-3414,-3426,-3434,-3441,-3449,-3460,-3470,-3477,-3480,-3484,-3496,-3518,-3544,-3564,-3574,-3574,-3575,-3587,-3611,-3638,
--3657,-3661,-3656,-3653,-3659,-3672,-3686,-3694,-3695,-3694,-3699,-3709,-3718,-3719,-3708,-3691,-3675,-3669,-3675,-3690,-3705,
--3715,-3714,-3701,-3680,-3658,-3643,-3641,-3648,-3652,-3643,-3620,-3591,-3570,-3561,-3561,-3561,-3553,-3537,-3518,-3502,-3490,
--3482,-3473,-3460,-3441,-3419,-3401,-3390,-3384,-3376,-3357,-3327,-3293,-3263,-3243,-3228,-3212,-3190,-3164,-3138,-3113,-3088,
--3060,-3028,-2996,-2969,-2946,-2925,-2902,-2877,-2850,-2822,-2793,-2762,-2732,-2705,-2679,-2653,-2625,-2595,-2566,-2537,-2507,
--2472,-2433,-2391,-2349,-2304,-2255,-2202,-2154,-2114,-2079,-2040,-1990,-1932,-1874,-1822,-1774,-1724,-1671,-1617,-1568,-1516,
--1450,-1362,-1255,-1141,-1032,-929,-831,-732,-632,-535,-445,-363,-286,-210,-127,-37,52,130,187,223,249,
-278,318,363,405,436,456,472,497,543,614,703,792,859,891,890,868,840,821,817,830,853,
-877,895,907,917,918,891,814,683,527,396,328,331,376,430,471,502,535,572,607,632,650,
-670,699,735,770,797,816,833,852,876,898,916,926,932,939,951,966,979,985,979,969,963,
-973,1000,1035,1066,1085,1095,1106,1124,1155,1194,1238,1279,1313,1334,1348,1368,1411,1486,1585,1688,1774,
-1835,1876,1903,1920,1928,1930,1936,1954,1992,2049,2120,2197,2270,2336,2391,2437,2477,2510,2534,2544,2542,
-2531,2516,2500,2484,2475,2476,2489,2512,2537,2560,2581,2600,2620,2642,2671,2711,2767,2836,2907,2968,3013,
-3046,3070,3086,3088,3066,3016,2944,2862,2778,2692,2593,2472,2333,2196,2090,2034,2022,2030,2032,2020,2010,
-2023,2070,2143,2216,2268,2296,2308,2314,2317,2310,2289,2256,2221,2192,2167,2140,2102,2053,1994,1930,1860,
-1791,1731,1687,1653,1619,1576,1529,1489,1462,1442,1417,1386,1360,1349,1343,1319,1265,1200,1161,1176,1231,
-1289,1311,1291,1246,1195,1145,1094,1043,1002,977,961,942,910,872,840,819,803,780,747,714,689,
-674,663,643,613,578,547,523,504,486,468,453,447,450,454,451,438,421,404,388,370,344,
-312,279,249,220,191,160,130,100,72,44,17,-7,-28,-49,-75,-105,-134,-158,-179,-202,-230,
--259,-282,-297,-311,-329,-353,-377,-399,-419,-444,-474,-508,-538,-565,-590,-615,-640,-661,-676,-686,-694,
--701,-707,-712,-718,-725,-734,-745,-758,-778,-804,-833,-859,-882,-903,-922,-938,-947,-952,-957,-968,-983,
--999,-1011,-1022,-1033,-1047,-1058,-1064,-1064,-1062,-1063,-1067,-1070,-1071,-1071,-1073,-1078,-1085,-1092,-1098,-1103,-1107,
--1109,-1109,-1111,-1114,-1119,-1126,-1134,-1143,-1153,-1161,-1166,-1170,-1173,-1176,-1177,-1177,-1178,-1181,-1186,-1190,-1191,
--1189,-1187,-1188,-1189,-1186,-1180,-1174,-1171,-1174,-1182,-1188,-1191,-1192,-1194,-1199,-1206,-1212,-1215,-1215,-1214,-1212,
--1211,-1209,-1210,-1213,-1219,-1224,-1224,-1218,-1207,-1197,-1191,-1187,-1186,-1185,-1187,-1191,-1195,-1197,-1198,-1203,-1214,
--1229,-1244,-1255,-1260,-1260,-1257,-1252,-1252,-1258,-1270,-1282,-1286,-1281,-1271,-1263,-1260,-1257,-1250,-1241,-1236,-1235,
--1235,-1230,-1219,-1208,-1203,-1201,-1197,-1187,-1173,-1160,-1150,-1142,-1132,-1119,-1106,-1096,-1086,-1076,-1064,-1053,-1043,
--1032,-1020,-1007,-996,-992,-992,-994,-993,-990,-985,-982,-982,-984,-987,-988,-985,-981,-976,-971,-967,-963,
--958,-952,-944,-935,-924,-912,-901,-890,-881,-872,-863,-853,-841,-828,-816,-806,-797,-786,-774,-762,-753,
--745,-736,-726,-713,-699,-683,-663,-638,-609,-582,-562,-549,-537,-521,-500,-479,-459,-441,-424,-406,-389,
--374,-360,-348,-334,-320,-306,-293,-283,-275,-269,-265,-258,-249,-241,-238,-238,-238,-234,-227,-220,-217,
--214,-206,-194,-182,-175,-173,-171,-163,-152,-143,-138,-134,-124,-109,-93,-78,-63,-44,-22,-1,17,
-37,62,92,124,152,176,200,228,258,286,309,332,359,390,422,453,483,516,548,577,600,
-622,648,678,706,728,750,781,821,863,898,925,954,990,1026,1053,1069,1081,1092,1088,1049,971,
-887,860,940,1139,1413,1696,1918,2038,2056,2010,1967,1984,2080,2222,2355,2440,2476,2485,2482,2464,2422,
-2361,2296,2237,2179,2105,2016,1930,1867,1830,1809,1786,1758,1727,1694,1658,1621,1593,1584,1590,1597,1592,
-1578,1569,1576,1595,1613,1618,1610,1595,1578,1559,1543,1531,1524,1518,1509,1503,1507,1525,1545,1557,1556,
-1553,1558,1570,1575,1559,1523,1479,1435,1387,1327,1256,1190,1144,1121,1104,1070,1001,897,774,656,557,
-478,410,343,276,220,184,163,143,108,56,0,-51,-94,-134,-177,-216,-246,-267,-286,-309,-335,
--357,-369,-375,-385,-404,-425,-445,-459,-471,-484,-499,-513,-525,-538,-555,-574,-593,-608,-621,-634,-648,
--661,-672,-680,-686,-692,-700,-707,-712,-710,-703,-694,-685,-679,-674,-668,-663,-660,-659,-653,-641,-623,
--605,-592,-580,-562,-535,-502,-473,-452,-438,-423,-403,-375,-341,-298,-246,-190,-136,-90,-51,-16,20,
-59,98,140,186,236,285,330,374,423,480,541,595,636,667,698,735,779,824,867,908,948,
-987,1025,1060,1097,1135,1174,1212,1246,1279,1310,1343,1376,1408,1441,1474,1506,1535,1562,1588,1617,1652,
-1689,1727,1762,1793,1821,1848,1872,1895,1916,1935,1953,1971,1988,2006,2028,2053,2080,2106,2129,2147,2162,
-2172,2177,2176,2170,2164,2161,2161,2162,2161,2160,2160,2162,2160,2151,2137,2125,2127,2141,2157,2159,2140,
-2109,2082,2072,2077,2087,2090,2085,2076,2072,2071,2070,2062,2047,2032,2022,2020,2020,2015,2005,1995,1987,
-1980,1970,1955,1938,1921,1902,1876,1843,1810,1783,1761,1733,1698,1664,1651,1663,1682,1680,1648,1604,1578,
-1584,1609,1627,1630,1627,1632,1649,1659,1674,1682,1686,1694,1709,1726,1740,1756,1778,1808,1835,1855,1868,
-1885,1912,1942,1967,1983,1998,2017,2041,2065,2083,2098,2114,2132,2150,2163,2177,2197,2224,2250,2265,2268,
-2266,2270,2283,2301,2317,2332,2347,2366,2387,2411,2436,2464,2491,2514,2528,2536,2544,2552,2558,2561,2571,
-2601,2652,2709,2742,2735,2698,2659,2645,2658,2681,2697,2701,2704,2715,2731,2740,2733,2713,2693,2683,2686,
-2698,2717,2743,2780,2827,2876,2915,2937,2940,2931,2920,2908,2896,2883,2870,2864,2867,2881,2901,2925,2955,
-2991,3032,3071,3103,3125,3138,3144,3145,3142,3138,3135,3135,3137,3136,3128,3114,3100,3095,3101,3118,3134,
-3143,3139,3128,3116,3107,3103,3104,3110,3118,3124,3125,3122,3123,3141,3174,3210,3230,3222,3194,3161,3133,
-3110,3083,3053,3025,3009,3006,3010,3016,3025,3041,3065,3092,3116,3138,3162,3192,3227,3265,3301,3338,3375,
-3410,3440,3462,3482,3503,3527,3552,3578,3606,3641,3680,3720,3754,3785,3813,3841,3864,3877,3882,3883,3887,
-3895,3903,3914,3936,3978,4037,4091,4118,4111,4087,4072,4076,4091,4098,4091,4081,4076,4073,4055,4014,3968,
-3942,3946,3952,3922,3841,3734,3647,3606,3598,3586,3546,3483,3419,3372,3339,3308,3273,3233,3191,3150,3108,
-3061,3013,2963,2912,2860,2811,2768,2733,2707,2687,2671,2656,2638,2614,2588,2566,2552,2544,2536,2523,2508,
-2496,2489,2488,2486,2482,2477,2472,2468,2466,2464,2463,2460,2452,2442,2433,2426,2420,2411,2398,2382,2368,
-2355,2339,2317,2293,2269,2249,2229,2205,2177,2148,2120,2093,2065,2033,2001,1969,1936,1900,1861,1823,1789,
-1761,1733,1705,1675,1647,1619,1589,1558,1528,1501,1482,1466,1450,1432,1416,1407,1404,1402,1390,1369,1349,
-1344,1360,1386,1401,1390,1356,1314,1271,1223,1156,1069,977,900,847,812,778,736,689,641,598,559,
-523,491,462,432,396,352,306,261,218,175,132,92,58,28,-5,-46,-93,-140,-187,-233,-282,
--332,-378,-420,-461,-505,-554,-603,-647,-687,-726,-770,-817,-866,-912,-955,-996,-1037,-1079,-1123,-1171,-1223,
--1277,-1328,-1373,-1411,-1449,-1490,-1537,-1591,-1646,-1699,-1749,-1797,-1844,-1890,-1936,-1981,-2026,-2071,-2115,-2158,-2200,
--2242,-2286,-2331,-2375,-2416,-2454,-2491,-2528,-2566,-2603,-2640,-2679,-2718,-2756,-2791,-2823,-2857,-2893,-2932,-2970,-3003,
--3034,-3064,-3096,-3127,-3155,-3181,-3208,-3237,-3267,-3291,-3308,-3322,-3337,-3355,-3372,-3384,-3390,-3394,-3401,-3412,-3422,
--3429,-3432,-3436,-3445,-3459,-3475,-3488,-3498,-3507,-3522,-3545,-3572,-3597,-3611,-3615,-3611,-3609,-3614,-3625,-3637,-3644,
--3646,-3647,-3652,-3660,-3666,-3665,-3654,-3639,-3629,-3629,-3642,-3660,-3677,-3688,-3689,-3678,-3657,-3633,-3618,-3615,-3622,
--3624,-3613,-3590,-3565,-3549,-3545,-3544,-3539,-3526,-3508,-3488,-3472,-3458,-3448,-3438,-3426,-3408,-3385,-3364,-3352,-3349,
--3348,-3336,-3309,-3272,-3237,-3213,-3199,-3184,-3163,-3137,-3113,-3092,-3072,-3047,-3016,-2983,-2954,-2932,-2913,-2892,-2866,
--2837,-2808,-2779,-2751,-2724,-2699,-2674,-2647,-2617,-2585,-2555,-2527,-2497,-2462,-2423,-2381,-2339,-2295,-2245,-2192,-2145,
--2109,-2083,-2056,-2020,-1975,-1927,-1880,-1831,-1778,-1722,-1671,-1630,-1593,-1544,-1471,-1375,-1271,-1172,-1083,-996,-901,
--792,-676,-563,-463,-380,-307,-235,-155,-71,7,68,113,150,188,230,268,296,312,325,347,386,
-444,518,598,667,710,716,690,652,621,612,624,648,671,685,694,707,726,737,715,640,516,
-382,283,249,274,327,378,414,442,474,509,542,567,588,613,645,679,708,728,743,759,779,
-802,826,846,859,867,871,877,888,903,915,919,914,909,914,935,966,997,1020,1035,1049,1071,
-1101,1137,1172,1202,1226,1245,1265,1294,1343,1413,1499,1589,1670,1735,1785,1821,1844,1856,1861,1866,1882,
-1914,1966,2037,2118,2200,2274,2336,2386,2427,2461,2488,2507,2518,2519,2509,2489,2460,2432,2415,2413,2426,
-2447,2469,2491,2513,2539,2570,2609,2656,2711,2771,2830,2884,2932,2973,3003,3019,3012,2978,2920,2843,2758,
-2671,2587,2499,2403,2303,2212,2145,2107,2090,2076,2058,2043,2047,2080,2137,2198,2246,2274,2287,2294,2300,
-2300,2287,2259,2219,2174,2132,2099,2072,2043,2006,1954,1887,1809,1733,1668,1619,1581,1544,1503,1459,1421,
-1394,1372,1351,1328,1312,1306,1302,1282,1234,1171,1122,1107,1124,1151,1173,1188,1208,1234,1244,1215,1139,
-1039,949,891,863,848,831,807,783,762,741,718,693,670,651,635,614,585,551,518,493,473,
-455,435,420,415,422,432,434,423,405,389,377,364,343,312,276,242,213,185,157,128,98,
-69,40,15,-6,-25,-46,-71,-100,-128,-153,-176,-202,-233,-262,-283,-296,-309,-329,-356,-385,-410,
--432,-457,-486,-518,-548,-574,-599,-626,-654,-678,-698,-713,-724,-731,-736,-740,-745,-752,-760,-767,-777,
--792,-814,-840,-868,-894,-918,-939,-954,-963,-968,-972,-981,-994,-1008,-1022,-1035,-1049,-1063,-1072,-1075,-1073,
--1072,-1076,-1083,-1088,-1089,-1087,-1087,-1090,-1097,-1106,-1114,-1119,-1121,-1121,-1120,-1122,-1126,-1131,-1139,-1148,-1158,
--1169,-1177,-1182,-1185,-1189,-1194,-1198,-1200,-1199,-1198,-1198,-1196,-1192,-1188,-1187,-1190,-1193,-1194,-1188,-1179,-1174,
--1175,-1182,-1190,-1196,-1200,-1204,-1210,-1216,-1221,-1225,-1229,-1231,-1232,-1229,-1224,-1220,-1221,-1225,-1229,-1227,-1219,
--1208,-1203,-1204,-1208,-1211,-1209,-1204,-1201,-1201,-1205,-1211,-1219,-1228,-1238,-1248,-1258,-1265,-1270,-1271,-1267,-1264,
--1266,-1272,-1281,-1285,-1283,-1276,-1270,-1265,-1260,-1254,-1248,-1245,-1245,-1242,-1233,-1221,-1211,-1205,-1202,-1197,-1188,
--1177,-1168,-1160,-1150,-1136,-1119,-1105,-1094,-1086,-1076,-1066,-1055,-1046,-1038,-1027,-1014,-1003,-998,-998,-1000,-999,
--995,-989,-985,-985,-987,-988,-987,-985,-981,-978,-973,-967,-961,-955,-950,-945,-938,-930,-919,-907,-897,
--887,-878,-869,-860,-849,-838,-826,-813,-801,-790,-777,-764,-751,-739,-730,-721,-712,-702,-689,-672,-649,
--622,-596,-574,-557,-542,-526,-507,-487,-467,-449,-432,-414,-397,-381,-365,-350,-335,-319,-305,-292,-282,
--275,-268,-260,-250,-239,-232,-230,-231,-231,-225,-216,-209,-206,-205,-201,-191,-180,-171,-164,-158,-149,
--138,-129,-121,-111,-98,-84,-70,-59,-47,-30,-10,10,29,48,71,99,127,153,175,200,228,
-257,282,304,326,353,385,418,450,480,510,540,566,591,617,646,678,705,729,754,788,830,
-871,903,928,957,992,1028,1055,1071,1083,1094,1086,1042,962,883,868,962,1165,1432,1693,1886,1982,
-1989,1952,1932,1977,2089,2231,2350,2419,2447,2457,2458,2440,2392,2320,2244,2180,2122,2056,1981,1913,1867,
-1843,1825,1799,1764,1727,1689,1649,1605,1569,1552,1551,1554,1546,1529,1516,1521,1542,1564,1577,1577,1567,
-1552,1533,1513,1496,1479,1459,1437,1421,1422,1440,1461,1473,1474,1478,1494,1519,1533,1522,1491,1454,1419,
-1379,1322,1248,1176,1126,1102,1085,1046,970,858,731,610,508,426,358,298,246,206,178,155,126,
-83,28,-25,-71,-109,-145,-183,-219,-248,-269,-290,-314,-338,-356,-367,-376,-389,-408,-428,-444,-456,
--468,-483,-500,-514,-525,-537,-553,-573,-592,-610,-625,-640,-654,-667,-676,-682,-687,-693,-701,-708,-712,
--709,-701,-690,-680,-675,-671,-666,-662,-659,-657,-654,-647,-634,-619,-604,-588,-567,-540,-509,-480,-455,
--432,-411,-389,-366,-338,-301,-250,-193,-137,-90,-50,-13,23,61,100,141,187,236,284,327,368,
-416,474,538,596,641,676,712,753,799,842,879,913,946,982,1018,1055,1093,1133,1174,1215,1253,
-1291,1329,1367,1402,1433,1462,1492,1523,1554,1583,1611,1642,1677,1715,1751,1782,1809,1834,1859,1883,1906,
-1929,1951,1972,1992,2009,2025,2045,2069,2095,2121,2143,2162,2178,2190,2197,2199,2196,2191,2189,2190,2191,
-2191,2190,2189,2189,2189,2186,2180,2172,2167,2164,2161,2156,2147,2135,2125,2120,2118,2117,2115,2111,2105,
-2101,2100,2100,2097,2085,2065,2044,2029,2024,2025,2025,2018,2004,1986,1967,1952,1943,1938,1929,1907,1870,
-1826,1787,1757,1731,1701,1670,1646,1635,1631,1622,1605,1588,1588,1605,1627,1638,1637,1635,1643,1659,1662,
-1671,1674,1677,1689,1710,1733,1753,1772,1795,1821,1846,1864,1879,1895,1917,1939,1957,1971,1987,2009,2033,
-2052,2063,2073,2090,2113,2136,2153,2166,2183,2206,2230,2247,2254,2258,2267,2282,2300,2316,2334,2355,2379,
-2402,2424,2449,2480,2512,2536,2545,2545,2549,2561,2577,2588,2597,2619,2665,2724,2766,2766,2728,2683,2662,
-2673,2698,2714,2716,2714,2717,2722,2718,2701,2678,2665,2673,2696,2726,2758,2795,2840,2887,2924,2942,2939,
-2924,2911,2907,2908,2909,2905,2898,2893,2894,2902,2917,2940,2972,3011,3054,3096,3132,3160,3178,3186,3185,
-3179,3175,3175,3179,3181,3174,3158,3138,3124,3124,3137,3157,3173,3177,3172,3160,3150,3142,3138,3138,3144,
-3153,3160,3158,3151,3151,3167,3196,3221,3227,3209,3181,3158,3146,3134,3114,3086,3064,3057,3062,3069,3071,
-3073,3083,3103,3126,3147,3168,3196,3234,3277,3316,3353,3391,3435,3479,3515,3540,3558,3577,3602,3630,3657,
-3686,3719,3756,3790,3818,3841,3864,3890,3914,3927,3932,3936,3943,3953,3961,3969,3992,4039,4104,4160,4180,
-4162,4128,4107,4110,4125,4131,4123,4109,4099,4085,4056,4010,3967,3947,3952,3952,3913,3830,3731,3655,3621,
-3612,3596,3556,3497,3440,3398,3367,3338,3302,3260,3215,3172,3130,3086,3040,2990,2937,2885,2837,2799,2770,
-2749,2733,2717,2699,2676,2648,2621,2600,2586,2577,2566,2549,2532,2520,2513,2510,2507,2503,2498,2493,2488,
-2484,2480,2478,2476,2472,2466,2461,2456,2450,2442,2430,2416,2403,2390,2374,2353,2330,2308,2289,2270,2246,
-2218,2188,2159,2132,2105,2077,2047,2015,1980,1941,1900,1862,1829,1801,1773,1744,1713,1684,1655,1624,1591,
-1562,1539,1523,1509,1492,1472,1455,1448,1450,1451,1439,1415,1393,1387,1404,1429,1441,1426,1388,1341,1292,
-1237,1167,1084,1002,939,900,873,840,794,740,690,648,614,583,553,521,487,448,405,360,317,
-274,232,191,153,119,86,50,8,-37,-83,-128,-175,-224,-272,-316,-356,-398,-447,-498,-546,-584,
--618,-655,-702,-755,-808,-855,-897,-937,-978,-1020,-1063,-1109,-1160,-1213,-1264,-1310,-1350,-1388,-1431,-1480,-1532,
--1585,-1635,-1684,-1731,-1778,-1824,-1870,-1915,-1961,-2006,-2051,-2095,-2139,-2182,-2227,-2271,-2314,-2353,-2391,-2429,-2468,
--2507,-2546,-2584,-2622,-2661,-2700,-2737,-2772,-2808,-2844,-2881,-2915,-2945,-2972,-3001,-3032,-3065,-3097,-3127,-3156,-3186,
--3213,-3235,-3252,-3268,-3286,-3309,-3332,-3350,-3360,-3367,-3373,-3379,-3386,-3391,-3396,-3401,-3409,-3420,-3432,-3445,-3460,
--3480,-3503,-3526,-3545,-3560,-3572,-3581,-3590,-3597,-3603,-3608,-3613,-3618,-3622,-3627,-3632,-3636,-3635,-3627,-3612,-3599,
--3594,-3600,-3615,-3632,-3647,-3655,-3656,-3648,-3631,-3613,-3601,-3600,-3604,-3603,-3587,-3563,-3540,-3528,-3526,-3525,-3516,
--3499,-3480,-3463,-3447,-3432,-3418,-3405,-3393,-3376,-3354,-3331,-3314,-3309,-3308,-3301,-3279,-3245,-3213,-3190,-3176,-3164,
--3146,-3124,-3102,-3085,-3066,-3041,-3008,-2974,-2946,-2926,-2909,-2887,-2858,-2827,-2797,-2772,-2750,-2729,-2706,-2680,-2651,
--2618,-2585,-2552,-2520,-2487,-2450,-2410,-2371,-2335,-2298,-2255,-2208,-2162,-2126,-2098,-2074,-2044,-2009,-1970,-1929,-1883,
--1829,-1770,-1715,-1671,-1633,-1588,-1527,-1449,-1367,-1292,-1225,-1157,-1075,-972,-852,-726,-608,-508,-424,-349,-275,
--200,-129,-65,-10,43,95,140,171,184,190,203,235,286,350,417,478,524,546,538,507,471,
-450,456,480,503,509,497,482,483,503,520,504,438,334,232,177,182,230,288,332,359,384,
-416,451,483,506,529,558,594,628,653,667,676,685,700,720,742,763,779,788,792,797,808,
-825,844,857,860,859,862,877,901,927,951,971,990,1014,1042,1073,1101,1125,1146,1168,1197,1236,
-1287,1347,1413,1482,1552,1619,1680,1727,1758,1774,1784,1794,1812,1844,1893,1961,2044,2131,2211,2276,2325,
-2364,2397,2427,2453,2472,2482,2479,2462,2435,2405,2382,2368,2365,2368,2378,2397,2425,2463,2509,2557,2605,
-2649,2689,2730,2776,2828,2880,2917,2930,2915,2875,2818,2747,2665,2573,2475,2380,2294,2227,2183,2160,2147,
-2130,2100,2067,2052,2072,2124,2187,2238,2265,2274,2275,2275,2273,2264,2242,2209,2165,2115,2065,2023,1992,
-1967,1937,1890,1825,1748,1672,1607,1554,1510,1469,1427,1386,1350,1322,1300,1283,1271,1263,1260,1253,1232,
-1191,1139,1090,1055,1032,1019,1018,1046,1114,1206,1278,1283,1202,1063,923,829,794,794,797,785,759,
-731,709,691,671,649,627,606,581,550,514,480,457,443,430,414,396,386,389,399,405,398,
-384,369,359,349,329,299,263,229,201,177,152,126,97,69,42,20,1,-15,-36,-63,-93,
--121,-145,-168,-194,-225,-254,-278,-294,-312,-335,-365,-395,-420,-444,-469,-499,-531,-559,-584,-609,-635,
--663,-690,-714,-733,-748,-758,-764,-768,-772,-779,-787,-793,-799,-809,-824,-846,-872,-899,-924,-945,-961,
--972,-978,-983,-991,-1002,-1015,-1030,-1045,-1061,-1074,-1080,-1080,-1078,-1080,-1088,-1099,-1106,-1109,-1107,-1107,-1110,
--1117,-1124,-1131,-1136,-1138,-1139,-1139,-1141,-1145,-1150,-1157,-1166,-1175,-1184,-1191,-1195,-1200,-1208,-1217,-1224,-1227,
--1226,-1222,-1218,-1213,-1207,-1202,-1199,-1201,-1205,-1206,-1202,-1195,-1191,-1192,-1198,-1206,-1212,-1216,-1220,-1226,-1231,
--1235,-1239,-1242,-1245,-1246,-1243,-1235,-1228,-1225,-1224,-1223,-1217,-1208,-1201,-1202,-1209,-1218,-1223,-1223,-1222,-1223,
--1229,-1238,-1247,-1254,-1259,-1262,-1264,-1268,-1273,-1279,-1283,-1283,-1280,-1277,-1276,-1277,-1278,-1277,-1275,-1271,-1268,
--1264,-1261,-1260,-1260,-1258,-1250,-1238,-1226,-1216,-1209,-1202,-1193,-1182,-1173,-1168,-1163,-1153,-1137,-1121,-1108,-1100,
--1093,-1083,-1071,-1060,-1051,-1044,-1035,-1024,-1013,-1007,-1007,-1007,-1006,-1001,-995,-991,-991,-992,-992,-990,-986,
--984,-982,-977,-970,-961,-953,-948,-945,-940,-932,-921,-909,-898,-887,-876,-866,-856,-848,-838,-826,-814,
--802,-791,-781,-768,-753,-738,-726,-717,-710,-703,-693,-679,-660,-638,-614,-591,-571,-553,-534,-514,-493,
--474,-458,-444,-428,-412,-396,-379,-364,-349,-332,-316,-302,-290,-281,-272,-261,-249,-237,-229,-225,-225,
--222,-214,-204,-195,-192,-192,-190,-185,-175,-164,-153,-142,-132,-122,-112,-102,-89,-75,-61,-50,-41,
--30,-14,6,26,42,57,75,97,122,147,172,199,227,253,276,297,321,351,386,420,451,
-479,507,533,557,582,609,641,674,704,730,759,797,841,881,910,935,963,997,1032,1057,1072,
-1084,1091,1078,1029,951,883,881,982,1179,1424,1653,1818,1898,1909,1894,1905,1975,2100,2240,2350,2413,
-2440,2451,2451,2424,2361,2274,2188,2119,2061,2003,1943,1893,1862,1844,1822,1789,1749,1712,1679,1640,1592,
-1545,1515,1506,1507,1502,1488,1475,1476,1491,1511,1526,1530,1525,1514,1497,1476,1453,1427,1397,1367,1345,
-1340,1353,1370,1380,1384,1395,1421,1453,1474,1471,1449,1424,1402,1371,1320,1249,1177,1125,1094,1066,1017,
-936,830,715,606,505,415,335,269,221,189,166,141,103,53,-2,-51,-91,-123,-155,-190,-224,
--252,-274,-295,-317,-339,-356,-371,-386,-404,-423,-438,-448,-458,-472,-489,-507,-521,-532,-545,-562,-583,
--603,-620,-636,-650,-663,-673,-679,-684,-690,-697,-705,-710,-712,-709,-700,-688,-677,-669,-664,-660,-656,
--654,-653,-654,-652,-645,-632,-614,-594,-570,-544,-517,-488,-459,-430,-401,-375,-352,-327,-294,-250,-197,
--143,-94,-51,-9,32,72,109,148,190,235,280,321,361,409,467,530,587,633,672,712,759,
-806,848,882,912,944,981,1021,1060,1100,1139,1178,1216,1256,1297,1340,1381,1418,1449,1477,1506,1538,
-1569,1598,1627,1658,1692,1728,1761,1789,1815,1840,1867,1893,1918,1942,1966,1989,2009,2025,2039,2055,2076,
-2102,2128,2150,2169,2185,2200,2212,2220,2222,2221,2219,2219,2220,2221,2219,2216,2214,2215,2218,2219,2217,
-2210,2200,2190,2184,2182,2181,2174,2161,2147,2139,2138,2140,2138,2131,2123,2118,2116,2110,2095,2074,2055,
-2047,2049,2051,2044,2026,2001,1979,1965,1959,1957,1948,1925,1888,1846,1810,1787,1773,1755,1729,1697,1666,
-1643,1628,1618,1616,1622,1632,1639,1638,1634,1636,1647,1662,1662,1668,1672,1680,1699,1725,1751,1771,1788,
-1807,1830,1852,1871,1888,1905,1923,1938,1949,1959,1975,1999,2023,2040,2048,2056,2073,2098,2123,2142,2156,
-2172,2193,2216,2234,2246,2257,2271,2288,2304,2320,2341,2370,2401,2425,2443,2464,2496,2533,2558,2561,2553,
-2559,2594,2645,2685,2698,2694,2696,2714,2736,2740,2720,2693,2682,2696,2719,2734,2733,2724,2717,2710,2697,
-2678,2665,2672,2702,2745,2788,2825,2858,2890,2917,2931,2929,2918,2909,2913,2928,2943,2949,2943,2931,2919,
-2913,2917,2931,2958,2995,3039,3085,3130,3171,3204,3226,3235,3233,3226,3220,3219,3219,3214,3199,3180,3164,
-3161,3172,3188,3201,3203,3195,3183,3173,3167,3164,3163,3166,3173,3182,3185,3180,3171,3170,3184,3206,3220,
-3213,3191,3169,3163,3166,3164,3146,3121,3105,3106,3118,3125,3125,3124,3132,3149,3168,3183,3200,3229,3272,
-3320,3364,3403,3446,3497,3547,3587,3612,3629,3649,3676,3704,3730,3756,3788,3823,3856,3879,3896,3915,3939,
-3961,3975,3982,3988,3999,4010,4014,4017,4035,4080,4142,4193,4208,4185,4153,4137,4144,4155,4153,4136,4115,
-4096,4076,4043,4001,3970,3962,3967,3957,3904,3815,3721,3657,3631,3624,3606,3568,3517,3469,3431,3401,3368,
-3328,3283,3236,3192,3150,3107,3062,3013,2962,2915,2875,2845,2821,2801,2781,2759,2735,2709,2682,2657,2638,
-2623,2610,2595,2576,2560,2548,2541,2536,2531,2525,2521,2516,2510,2504,2500,2499,2500,2500,2497,2493,2488,
-2482,2474,2461,2446,2432,2420,2406,2389,2369,2348,2328,2307,2283,2255,2226,2198,2170,2143,2115,2087,2056,
-2021,1981,1940,1902,1870,1842,1814,1784,1752,1721,1690,1658,1625,1597,1576,1562,1549,1532,1513,1498,1494,
-1497,1497,1483,1457,1432,1426,1442,1466,1477,1462,1422,1368,1310,1246,1175,1100,1035,988,959,933,898,
-849,794,746,707,675,644,611,575,537,498,456,415,374,333,293,253,215,180,145,106,63,
-18,-25,-70,-116,-165,-211,-253,-293,-338,-390,-443,-488,-523,-554,-590,-636,-690,-743,-791,-835,-876,
--918,-960,-1002,-1047,-1098,-1151,-1202,-1247,-1287,-1328,-1374,-1424,-1475,-1525,-1571,-1616,-1662,-1709,-1757,-1803,-1849,
--1894,-1938,-1982,-2026,-2072,-2118,-2164,-2209,-2250,-2289,-2327,-2365,-2405,-2445,-2485,-2524,-2563,-2602,-2642,-2682,-2723,
--2763,-2802,-2836,-2865,-2890,-2914,-2940,-2970,-3003,-3036,-3068,-3100,-3130,-3159,-3183,-3202,-3219,-3238,-3261,-3286,-3310,
--3328,-3340,-3348,-3354,-3358,-3363,-3369,-3376,-3385,-3395,-3406,-3420,-3441,-3466,-3489,-3506,-3516,-3523,-3534,-3551,-3569,
--3583,-3590,-3590,-3590,-3593,-3599,-3608,-3616,-3618,-3611,-3597,-3581,-3569,-3566,-3574,-3586,-3598,-3607,-3612,-3614,-3610,
--3600,-3588,-3580,-3579,-3579,-3572,-3554,-3529,-3510,-3502,-3501,-3497,-3485,-3467,-3449,-3436,-3425,-3411,-3395,-3378,-3363,
--3348,-3330,-3309,-3290,-3279,-3273,-3265,-3247,-3220,-3194,-3175,-3162,-3150,-3132,-3111,-3092,-3076,-3058,-3032,-2998,-2963,
--2937,-2919,-2902,-2879,-2848,-2816,-2790,-2771,-2756,-2738,-2715,-2688,-2657,-2624,-2589,-2554,-2518,-2480,-2440,-2402,-2367,
--2338,-2310,-2279,-2241,-2199,-2160,-2125,-2092,-2059,-2022,-1985,-1948,-1907,-1859,-1804,-1748,-1697,-1649,-1601,-1546,-1486,
--1428,-1376,-1328,-1277,-1212,-1129,-1026,-908,-786,-670,-566,-476,-397,-325,-258,-192,-127,-62,-2,42,67,
-74,81,103,147,208,271,325,368,396,406,396,370,344,337,355,385,402,387,343,292,263,
-263,274,267,224,158,103,91,126,187,243,281,305,330,363,397,426,447,470,501,537,571,
-593,603,608,613,623,639,659,681,701,716,725,732,743,759,776,789,795,800,808,822,841,
-861,880,899,920,943,970,999,1028,1054,1077,1101,1132,1174,1225,1278,1329,1383,1443,1513,1583,1639,
-1674,1690,1698,1709,1732,1768,1821,1891,1977,2066,2147,2211,2259,2296,2329,2359,2386,2404,2412,2409,2398,
-2381,2362,2345,2328,2313,2302,2302,2321,2358,2410,2465,2516,2553,2576,2590,2609,2643,2696,2757,2804,2823,
-2809,2770,2715,2645,2557,2451,2338,2238,2170,2139,2141,2154,2157,2134,2091,2052,2046,2083,2150,2216,2257,
-2269,2263,2254,2245,2230,2207,2176,2142,2103,2056,2004,1953,1912,1881,1850,1807,1748,1678,1608,1544,1488,
-1437,1391,1350,1313,1279,1252,1231,1220,1216,1215,1210,1193,1164,1125,1083,1044,1007,968,929,904,918,
-986,1093,1194,1233,1179,1050,901,790,739,734,741,736,717,694,677,663,645,621,597,575,552,
-522,485,449,425,413,407,395,377,362,357,361,365,362,352,341,334,325,308,280,246,214,
-188,167,146,123,98,72,49,30,14,-1,-22,-50,-82,-112,-137,-159,-182,-209,-237,-264,-288,
--313,-343,-374,-404,-430,-454,-482,-513,-545,-573,-596,-619,-643,-671,-698,-724,-746,-764,-776,-784,-789,
--795,-802,-810,-816,-821,-827,-838,-855,-877,-901,-924,-945,-961,-974,-984,-992,-1001,-1010,-1022,-1036,-1052,
--1067,-1078,-1082,-1081,-1081,-1088,-1099,-1112,-1121,-1125,-1126,-1129,-1134,-1139,-1144,-1148,-1153,-1156,-1159,-1162,-1165,
--1169,-1174,-1180,-1187,-1193,-1199,-1203,-1206,-1211,-1220,-1230,-1239,-1242,-1241,-1237,-1235,-1234,-1232,-1228,-1224,-1221,
--1221,-1220,-1218,-1214,-1213,-1215,-1220,-1225,-1228,-1230,-1233,-1237,-1241,-1244,-1246,-1248,-1250,-1249,-1245,-1239,-1233,
--1229,-1225,-1219,-1209,-1200,-1196,-1200,-1209,-1217,-1221,-1222,-1226,-1234,-1246,-1256,-1264,-1268,-1270,-1272,-1272,-1274,
--1277,-1284,-1292,-1296,-1295,-1288,-1280,-1274,-1271,-1272,-1273,-1273,-1271,-1269,-1267,-1267,-1266,-1261,-1251,-1239,-1228,
--1220,-1214,-1206,-1194,-1182,-1174,-1170,-1166,-1156,-1141,-1127,-1116,-1110,-1102,-1090,-1076,-1063,-1055,-1049,-1042,-1033,
--1024,-1019,-1017,-1017,-1014,-1008,-1002,-998,-998,-998,-997,-994,-990,-987,-985,-980,-973,-965,-957,-952,-948,
--942,-933,-922,-910,-898,-885,-871,-858,-846,-836,-827,-817,-807,-797,-790,-782,-771,-757,-742,-729,-720,
--714,-707,-697,-684,-668,-649,-629,-608,-588,-567,-545,-521,-499,-480,-466,-453,-438,-422,-405,-389,-375,
--360,-343,-326,-310,-296,-285,-275,-263,-250,-238,-229,-222,-216,-209,-200,-190,-183,-178,-175,-174,-170,
--163,-153,-141,-129,-117,-106,-96,-85,-72,-59,-49,-39,-29,-15,4,25,42,53,61,72,89,
-112,139,169,199,227,251,273,296,324,358,394,426,456,485,513,539,562,586,612,643,675,
-705,734,767,807,850,888,916,940,968,1000,1031,1054,1069,1079,1081,1062,1011,941,890,904,1007,
-1184,1393,1583,1721,1796,1823,1834,1872,1959,2090,2231,2344,2413,2446,2458,2448,2408,2334,2241,2153,2082,
-2023,1966,1911,1868,1843,1826,1801,1764,1723,1691,1664,1629,1578,1523,1482,1465,1464,1464,1455,1445,1441,
-1448,1460,1469,1474,1475,1471,1460,1442,1418,1389,1356,1323,1296,1283,1282,1287,1292,1299,1318,1349,1383,
-1404,1405,1395,1384,1373,1352,1306,1242,1177,1126,1089,1048,987,905,810,713,617,518,416,322,246,
-197,167,145,115,72,19,-32,-75,-107,-136,-167,-200,-233,-260,-282,-302,-321,-341,-359,-379,-401,
--423,-440,-450,-456,-465,-479,-498,-514,-527,-539,-555,-575,-597,-616,-632,-647,-661,-672,-679,-683,-689,
--698,-706,-712,-715,-714,-711,-705,-695,-681,-668,-659,-652,-648,-646,-646,-649,-650,-646,-634,-614,-590,
--566,-541,-515,-487,-456,-425,-395,-368,-344,-319,-288,-248,-201,-153,-104,-57,-10,35,78,117,155,
-196,240,283,322,363,410,466,525,580,626,667,711,759,806,847,880,911,947,987,1029,1070,
-1108,1145,1180,1216,1254,1295,1339,1381,1418,1451,1482,1515,1549,1581,1610,1638,1668,1703,1737,1769,1797,
-1824,1851,1879,1905,1928,1950,1974,1997,2018,2033,2045,2059,2080,2105,2131,2152,2169,2185,2203,2223,2240,
-2250,2254,2254,2254,2255,2254,2251,2245,2240,2239,2242,2246,2245,2238,2228,2220,2219,2222,2222,2211,2192,
-2172,2163,2168,2177,2178,2167,2149,2135,2129,2127,2122,2110,2098,2090,2085,2078,2061,2037,2011,1991,1979,
-1970,1962,1948,1927,1898,1868,1845,1831,1824,1813,1789,1754,1716,1684,1665,1657,1655,1655,1651,1644,1637,
-1634,1639,1651,1662,1670,1673,1680,1696,1719,1745,1767,1782,1798,1817,1840,1863,1882,1898,1914,1929,1940,
-1947,1953,1965,1986,2009,2026,2036,2046,2062,2084,2106,2125,2142,2162,2186,2209,2227,2242,2259,2280,2301,
-2317,2334,2359,2394,2429,2452,2464,2481,2512,2551,2575,2571,2556,2566,2626,2719,2797,2821,2789,2734,2696,
-2687,2695,2703,2706,2713,2727,2742,2747,2739,2725,2713,2705,2698,2694,2701,2727,2771,2820,2861,2888,2905,
-2917,2922,2921,2916,2914,2923,2942,2963,2976,2976,2966,2952,2941,2936,2940,2956,2987,3030,3080,3132,3180,
-3223,3259,3283,3292,3289,3279,3271,3265,3257,3242,3221,3203,3197,3206,3223,3236,3236,3223,3204,3188,3179,
-3175,3175,3176,3181,3191,3200,3201,3193,3183,3183,3199,3219,3226,3214,3191,3178,3182,3193,3193,3175,3153,
-3144,3153,3170,3178,3177,3176,3185,3203,3218,3229,3242,3270,3314,3364,3410,3453,3501,3556,3609,3648,3674,
-3694,3720,3751,3778,3799,3821,3850,3886,3919,3940,3954,3969,3990,4012,4025,4030,4036,4048,4059,4062,4063,
-4078,4120,4177,4221,4230,4207,4179,4169,4176,4180,4165,4136,4107,4085,4062,4031,3996,3976,3977,3984,3966,
-3905,3814,3729,3676,3656,3647,3627,3590,3546,3505,3469,3433,3391,3344,3297,3251,3207,3165,3122,3078,3034,
-2991,2953,2922,2898,2875,2850,2821,2791,2764,2739,2717,2698,2681,2664,2645,2626,2607,2592,2581,2573,2566,
-2557,2550,2545,2541,2534,2528,2526,2528,2533,2534,2531,2524,2517,2511,2502,2489,2472,2457,2446,2436,2423,
-2407,2386,2364,2341,2316,2291,2264,2237,2208,2179,2150,2121,2091,2057,2019,1978,1941,1910,1883,1855,1824,
-1791,1759,1727,1696,1665,1637,1616,1601,1588,1572,1556,1545,1542,1543,1538,1519,1490,1466,1461,1477,1501,
-1513,1499,1458,1398,1330,1260,1192,1131,1083,1048,1021,990,949,899,849,806,769,736,702,665,626,
-587,547,507,469,432,395,357,318,279,243,206,167,124,80,35,-10,-57,-104,-149,-191,-232,
--278,-329,-379,-422,-458,-491,-529,-574,-624,-672,-718,-761,-805,-848,-891,-934,-981,-1033,-1086,-1135,-1178,
--1218,-1261,-1310,-1363,-1415,-1462,-1507,-1551,-1597,-1645,-1694,-1742,-1787,-1830,-1872,-1915,-1959,-2007,-2056,-2104,-2149,
--2191,-2232,-2272,-2311,-2350,-2389,-2428,-2467,-2506,-2544,-2584,-2627,-2671,-2714,-2753,-2786,-2814,-2837,-2861,-2888,-2919,
--2952,-2985,-3017,-3048,-3079,-3109,-3136,-3158,-3176,-3192,-3211,-3235,-3261,-3285,-3304,-3316,-3324,-3331,-3339,-3349,-3360,
--3369,-3377,-3386,-3400,-3419,-3441,-3461,-3475,-3482,-3489,-3501,-3519,-3539,-3553,-3558,-3557,-3555,-3557,-3565,-3575,-3582,
--3584,-3577,-3565,-3553,-3545,-3544,-3550,-3557,-3563,-3567,-3570,-3574,-3574,-3569,-3561,-3552,-3546,-3541,-3530,-3513,-3493,
--3479,-3474,-3473,-3468,-3454,-3436,-3421,-3413,-3406,-3394,-3376,-3355,-3337,-3323,-3310,-3295,-3278,-3264,-3252,-3240,-3222,
--3201,-3179,-3162,-3148,-3131,-3110,-3087,-3069,-3055,-3039,-3015,-2984,-2952,-2927,-2910,-2893,-2869,-2839,-2808,-2786,-2772,
--2761,-2744,-2721,-2692,-2662,-2630,-2595,-2557,-2516,-2475,-2435,-2399,-2368,-2344,-2323,-2299,-2270,-2233,-2193,-2153,-2113,
--2072,-2029,-1987,-1946,-1905,-1862,-1814,-1762,-1707,-1652,-1599,-1550,-1506,-1468,-1431,-1393,-1349,-1298,-1237,-1163,-1072,
--966,-850,-736,-632,-541,-461,-386,-310,-235,-163,-103,-63,-41,-27,-8,27,81,142,198,241,272,
-290,295,286,266,248,250,275,311,331,313,257,181,115,77,63,53,36,14,5,25,72,
-130,180,216,245,275,307,337,361,382,408,442,477,506,522,530,535,543,555,571,591,614,
-637,656,671,683,695,706,714,719,722,731,746,764,781,794,807,823,843,867,894,926,959,
-989,1014,1035,1062,1104,1158,1213,1262,1308,1362,1431,1507,1571,1608,1619,1617,1621,1641,1681,1741,1818,
-1908,1998,2078,2140,2186,2224,2259,2290,2313,2323,2322,2314,2304,2296,2290,2282,2270,2254,2243,2247,2271,
-2316,2371,2424,2464,2483,2485,2477,2477,2498,2548,2614,2674,2707,2704,2668,2604,2515,2402,2277,2163,2086,
-2060,2081,2122,2153,2151,2113,2060,2025,2034,2088,2163,2225,2254,2254,2241,2225,2207,2179,2141,2103,2071,
-2040,1999,1946,1887,1834,1795,1762,1723,1672,1612,1548,1484,1423,1366,1318,1279,1247,1217,1190,1169,1160,
-1160,1160,1149,1122,1082,1039,1001,972,946,917,880,845,832,862,937,1032,1100,1102,1028,909,793,
-713,674,661,654,646,640,635,627,609,583,558,539,524,502,469,432,403,387,379,369,354,
-338,328,325,323,318,310,303,300,295,283,259,229,200,175,154,134,115,94,74,55,38,
-24,9,-10,-37,-69,-102,-129,-151,-172,-195,-221,-249,-278,-309,-343,-376,-405,-432,-459,-491,-526,
--559,-586,-609,-631,-654,-681,-707,-732,-753,-771,-784,-794,-803,-811,-820,-830,-838,-844,-850,-858,-870,
--886,-904,-923,-943,-961,-977,-992,-1004,-1014,-1023,-1032,-1043,-1057,-1070,-1080,-1083,-1084,-1087,-1096,-1110,-1122,
--1129,-1133,-1137,-1144,-1152,-1157,-1160,-1162,-1165,-1170,-1176,-1181,-1185,-1190,-1196,-1202,-1207,-1211,-1214,-1215,-1216,
--1219,-1224,-1232,-1239,-1242,-1242,-1243,-1246,-1251,-1254,-1253,-1249,-1244,-1239,-1235,-1232,-1230,-1230,-1232,-1234,-1235,
--1233,-1232,-1234,-1237,-1241,-1243,-1244,-1245,-1244,-1242,-1238,-1234,-1232,-1231,-1229,-1223,-1213,-1204,-1202,-1206,-1212,
--1215,-1215,-1216,-1220,-1230,-1240,-1247,-1250,-1253,-1257,-1262,-1267,-1271,-1277,-1285,-1294,-1301,-1302,-1295,-1285,-1276,
--1273,-1275,-1279,-1280,-1278,-1274,-1270,-1266,-1262,-1255,-1245,-1234,-1226,-1221,-1216,-1207,-1197,-1187,-1181,-1177,-1171,
--1161,-1147,-1135,-1126,-1119,-1109,-1095,-1080,-1068,-1060,-1055,-1048,-1039,-1032,-1027,-1026,-1025,-1022,-1016,-1009,-1005,
--1004,-1004,-1004,-1001,-996,-990,-985,-979,-973,-966,-960,-956,-951,-943,-933,-921,-909,-898,-885,-870,-853,
--837,-823,-812,-803,-795,-787,-782,-776,-768,-757,-746,-737,-729,-721,-710,-697,-682,-666,-651,-635,-618,
--601,-580,-556,-529,-504,-484,-468,-454,-438,-421,-404,-389,-376,-362,-345,-327,-311,-296,-284,-272,-261,
--250,-240,-230,-219,-207,-197,-188,-182,-177,-171,-164,-158,-153,-147,-140,-131,-120,-108,-96,-84,-71,
--60,-51,-44,-34,-21,-1,20,39,52,58,61,68,82,105,134,167,199,227,252,276,304,
-336,371,404,433,462,492,524,554,579,603,627,656,686,715,744,778,818,858,893,921,945,
-972,1002,1028,1047,1061,1069,1068,1045,996,939,909,939,1037,1185,1348,1497,1615,1696,1747,1787,1843,
-1935,2063,2203,2323,2405,2446,2455,2434,2381,2303,2216,2138,2075,2018,1959,1901,1856,1830,1813,1788,1750,
-1711,1680,1655,1622,1572,1515,1469,1445,1438,1435,1427,1417,1411,1411,1413,1416,1420,1425,1431,1431,1422,
-1403,1378,1349,1318,1289,1264,1246,1234,1231,1239,1261,1293,1323,1339,1342,1340,1340,1338,1322,1283,1227,
-1171,1123,1081,1029,961,878,791,703,610,506,397,297,222,175,148,123,89,43,-6,-52,-88,
--118,-147,-179,-212,-242,-267,-289,-308,-327,-346,-366,-389,-412,-434,-449,-458,-465,-475,-491,-508,-521,
--531,-543,-561,-583,-603,-619,-634,-650,-666,-679,-686,-691,-699,-710,-719,-723,-720,-717,-716,-715,-708,
--695,-678,-664,-653,-646,-642,-640,-640,-641,-636,-623,-603,-580,-555,-530,-503,-473,-442,-413,-388,-365,
--340,-313,-281,-244,-204,-161,-116,-68,-20,26,70,112,154,200,247,291,330,370,416,469,527,
-581,631,677,722,768,810,848,881,915,953,995,1037,1076,1113,1148,1183,1218,1254,1294,1335,1375,
-1413,1448,1484,1521,1557,1591,1622,1651,1683,1717,1750,1780,1808,1835,1863,1889,1911,1931,1950,1973,1997,
-2019,2035,2049,2065,2086,2112,2137,2156,2171,2188,2209,2235,2259,2278,2288,2292,2294,2294,2290,2282,2273,
-2266,2263,2263,2263,2259,2252,2245,2242,2244,2247,2245,2232,2214,2197,2192,2198,2208,2211,2200,2181,2162,
-2151,2149,2151,2151,2149,2140,2123,2095,2062,2031,2008,1993,1981,1966,1947,1929,1914,1901,1889,1877,1865,
-1852,1835,1810,1777,1742,1713,1695,1687,1682,1676,1667,1658,1652,1653,1658,1665,1670,1680,1682,1693,1712,
-1734,1755,1770,1784,1801,1826,1853,1877,1894,1906,1919,1932,1944,1952,1957,1966,1981,1997,2012,2023,2035,
-2051,2069,2087,2104,2124,2151,2180,2205,2223,2239,2260,2289,2316,2338,2358,2385,2421,2456,2478,2486,2499,
-2529,2569,2592,2584,2561,2568,2635,2746,2845,2875,2827,2740,2669,2646,2665,2699,2727,2746,2755,2758,2750,
-2736,2722,2717,2721,2734,2752,2777,2811,2849,2884,2909,2920,2924,2923,2920,2917,2919,2930,2949,2969,2982,
-2983,2977,2971,2968,2968,2970,2975,2991,3025,3074,3132,3188,3239,3283,3318,3341,3350,3346,3336,3324,3313,
-3299,3278,3255,3239,3237,3247,3261,3267,3259,3239,3216,3198,3186,3178,3175,3179,3191,3209,3224,3226,3216,
-3206,3208,3226,3245,3249,3235,3215,3206,3212,3221,3217,3200,3182,3182,3198,3218,3226,3224,3224,3236,3254,
-3270,3280,3294,3322,3366,3415,3460,3504,3554,3608,3658,3695,3722,3749,3783,3817,3842,3858,3876,3905,3943,
-3976,3994,4004,4018,4041,4064,4076,4079,4083,4094,4107,4114,4119,4135,4175,4226,4261,4262,4235,4206,4194,
-4193,4185,4159,4124,4094,4075,4055,4026,3995,3979,3982,3988,3966,3906,3825,3754,3713,3696,3683,3657,3621,
-3581,3544,3505,3460,3409,3358,3310,3267,3225,3183,3142,3103,3065,3029,2997,2970,2946,2920,2890,2857,2824,
-2797,2777,2760,2744,2725,2704,2680,2657,2639,2626,2617,2609,2599,2589,2580,2575,2570,2564,2558,2557,2562,
-2568,2568,2561,2551,2542,2535,2527,2513,2495,2479,2469,2462,2454,2440,2421,2399,2375,2353,2329,2304,2277,
-2246,2214,2181,2151,2121,2088,2052,2014,1978,1948,1922,1895,1864,1831,1798,1768,1739,1710,1684,1662,1645,
-1629,1615,1603,1595,1591,1586,1572,1547,1518,1499,1498,1516,1538,1548,1533,1491,1429,1358,1289,1229,1181,
-1145,1114,1082,1041,994,945,902,865,830,794,756,717,679,640,600,561,524,490,457,421,382,
-343,305,269,232,190,145,98,50,3,-43,-88,-132,-175,-219,-265,-308,-348,-385,-424,-467,-513,
--560,-604,-646,-688,-732,-775,-818,-864,-914,-967,-1019,-1066,-1106,-1147,-1192,-1244,-1299,-1351,-1398,-1443,-1489,
--1536,-1585,-1634,-1681,-1725,-1767,-1808,-1851,-1898,-1948,-1999,-2046,-2090,-2133,-2175,-2218,-2258,-2297,-2336,-2375,-2414,
--2454,-2492,-2530,-2571,-2614,-2656,-2695,-2728,-2756,-2781,-2806,-2834,-2867,-2901,-2936,-2968,-2998,-3026,-3055,-3085,-3110,
--3131,-3147,-3165,-3187,-3214,-3240,-3262,-3276,-3286,-3297,-3311,-3327,-3341,-3352,-3359,-3366,-3375,-3389,-3406,-3423,-3438,
--3451,-3463,-3476,-3491,-3505,-3514,-3519,-3521,-3522,-3525,-3530,-3536,-3540,-3541,-3538,-3532,-3527,-3525,-3526,-3529,-3532,
--3533,-3534,-3536,-3540,-3542,-3539,-3530,-3519,-3509,-3498,-3486,-3472,-3460,-3452,-3450,-3448,-3441,-3427,-3412,-3400,-3394,
--3388,-3377,-3358,-3335,-3314,-3299,-3288,-3277,-3265,-3252,-3238,-3221,-3202,-3181,-3162,-3145,-3128,-3108,-3084,-3061,-3042,
--3029,-3016,-2996,-2970,-2942,-2920,-2904,-2887,-2864,-2835,-2807,-2787,-2775,-2763,-2746,-2721,-2692,-2662,-2631,-2596,-2555,
--2512,-2471,-2434,-2402,-2374,-2351,-2330,-2308,-2282,-2248,-2209,-2168,-2125,-2081,-2034,-1985,-1937,-1893,-1851,-1808,-1761,
--1709,-1655,-1604,-1561,-1527,-1500,-1470,-1435,-1393,-1349,-1305,-1256,-1194,-1116,-1021,-919,-818,-721,-627,-531,-434,
--343,-264,-204,-163,-132,-103,-66,-20,30,79,121,154,179,195,199,190,174,162,168,195,235,
-269,274,238,166,79,0,-54,-82,-88,-81,-62,-31,10,56,102,144,182,216,245,268,288,
-313,346,385,418,439,448,454,463,477,493,511,530,551,572,592,610,628,643,653,655,651,
-649,658,677,697,712,721,731,747,770,796,824,855,889,920,943,961,988,1036,1100,1166,1218,
-1258,1302,1364,1441,1512,1555,1563,1552,1543,1553,1589,1650,1732,1824,1915,1993,2055,2104,2147,2188,2221,
-2240,2243,2235,2222,2211,2204,2201,2198,2194,2189,2190,2205,2236,2277,2319,2351,2368,2368,2356,2339,2329,
-2341,2381,2444,2511,2559,2571,2537,2456,2336,2194,2062,1972,1948,1987,2062,2130,2157,2134,2076,2020,1997,
-2025,2090,2163,2213,2229,2222,2207,2191,2168,2131,2085,2042,2009,1979,1939,1884,1821,1764,1723,1690,1656,
-1611,1555,1492,1425,1359,1299,1251,1217,1191,1164,1136,1112,1101,1098,1094,1076,1040,993,946,909,885,
-869,857,837,807,776,765,796,870,960,1019,1013,941,832,727,651,609,589,582,583,584,580,
-563,538,513,496,486,474,451,419,388,364,349,337,324,310,300,294,286,277,267,261,261,
-262,255,238,212,184,157,134,114,96,81,66,51,35,20,4,-14,-37,-65,-95,-122,-146,
--168,-190,-214,-241,-271,-304,-337,-369,-398,-427,-459,-496,-534,-570,-598,-622,-645,-669,-694,-719,-742,
--760,-776,-790,-802,-813,-825,-837,-849,-861,-871,-879,-887,-894,-903,-915,-929,-946,-965,-984,-1003,-1019,
--1032,-1040,-1047,-1055,-1065,-1075,-1083,-1088,-1091,-1097,-1109,-1121,-1131,-1136,-1140,-1146,-1155,-1163,-1168,-1170,-1171,
--1174,-1180,-1187,-1193,-1199,-1205,-1211,-1216,-1220,-1223,-1224,-1225,-1225,-1225,-1227,-1232,-1236,-1240,-1243,-1247,-1254,
--1261,-1266,-1268,-1265,-1261,-1258,-1254,-1251,-1248,-1246,-1244,-1241,-1236,-1232,-1229,-1229,-1232,-1235,-1236,-1237,-1237,
--1237,-1235,-1231,-1228,-1228,-1230,-1232,-1229,-1222,-1216,-1214,-1217,-1220,-1220,-1218,-1217,-1220,-1226,-1232,-1234,-1235,
--1238,-1244,-1253,-1262,-1270,-1277,-1285,-1294,-1301,-1302,-1298,-1291,-1285,-1284,-1286,-1289,-1289,-1285,-1278,-1271,-1264,
--1257,-1250,-1241,-1232,-1225,-1218,-1211,-1203,-1194,-1187,-1182,-1178,-1170,-1160,-1149,-1139,-1131,-1123,-1113,-1100,-1088,
--1078,-1070,-1061,-1052,-1043,-1037,-1033,-1032,-1031,-1028,-1022,-1017,-1013,-1011,-1011,-1011,-1008,-1003,-994,-985,-977,
--970,-965,-960,-956,-950,-941,-930,-918,-906,-894,-882,-867,-849,-830,-814,-800,-789,-781,-776,-771,-766,
--761,-754,-748,-742,-735,-724,-710,-693,-677,-662,-649,-637,-625,-610,-590,-565,-537,-509,-485,-466,-449,
--432,-415,-399,-386,-374,-361,-344,-327,-311,-297,-283,-269,-256,-246,-238,-228,-215,-200,-187,-180,-177,
--175,-169,-158,-147,-137,-130,-124,-117,-108,-97,-86,-73,-61,-51,-44,-38,-28,-13,7,27,42,
-51,54,58,65,80,103,132,165,197,227,255,283,315,349,382,411,437,466,498,533,565,
-592,616,641,670,699,729,759,792,829,866,898,926,952,981,1008,1030,1046,1057,1064,1060,1034,
-990,946,934,974,1062,1178,1299,1413,1519,1615,1697,1766,1837,1928,2048,2181,2304,2392,2436,2438,2405,
-2343,2266,2190,2128,2079,2032,1979,1923,1878,1848,1825,1798,1762,1723,1691,1664,1631,1585,1534,1489,1459,
-1441,1426,1410,1396,1388,1385,1384,1381,1381,1387,1398,1406,1407,1397,1382,1363,1342,1317,1287,1257,1230,
-1216,1219,1238,1265,1288,1300,1304,1308,1312,1312,1296,1260,1213,1165,1120,1073,1013,939,855,766,673,
-570,458,348,256,194,157,132,105,69,25,-17,-56,-90,-123,-156,-189,-220,-247,-269,-291,-312,
--333,-353,-374,-395,-416,-436,-451,-461,-473,-487,-504,-519,-528,-537,-550,-569,-589,-605,-617,-631,-649,
--669,-685,-693,-700,-709,-722,-731,-732,-726,-720,-720,-721,-718,-707,-691,-675,-663,-654,-645,-637,-632,
--628,-620,-605,-586,-564,-541,-515,-485,-453,-423,-398,-379,-359,-335,-304,-271,-238,-204,-167,-125,-79,
--32,12,55,99,147,197,247,292,333,373,417,469,527,585,641,691,737,779,817,853,889,
-927,966,1005,1044,1083,1120,1157,1194,1229,1266,1304,1343,1382,1419,1456,1493,1531,1567,1601,1633,1666,
-1699,1732,1762,1789,1815,1841,1866,1889,1909,1927,1947,1972,1998,2023,2044,2061,2081,2105,2131,2155,2173,
-2188,2204,2226,2253,2280,2301,2316,2325,2330,2329,2321,2309,2297,2289,2286,2286,2284,2278,2272,2269,2269,
-2270,2268,2260,2249,2237,2228,2223,2223,2224,2224,2219,2209,2195,2182,2177,2180,2188,2192,2182,2153,2111,
-2069,2040,2028,2022,2009,1981,1947,1918,1903,1901,1901,1895,1879,1858,1834,1807,1780,1754,1732,1718,1709,
-1703,1697,1692,1687,1684,1683,1683,1681,1680,1687,1692,1704,1721,1739,1755,1767,1781,1803,1832,1863,1887,
-1901,1910,1919,1932,1946,1958,1967,1975,1982,1991,2000,2009,2023,2039,2056,2072,2088,2111,2141,2174,2200,
-2219,2237,2263,2299,2334,2362,2384,2409,2443,2476,2497,2505,2517,2545,2585,2611,2606,2583,2581,2631,2720,
-2800,2821,2772,2690,2628,2617,2651,2698,2736,2756,2761,2758,2751,2742,2738,2747,2768,2798,2831,2860,2885,
-2903,2914,2919,2921,2921,2922,2922,2923,2930,2944,2961,2974,2978,2974,2971,2976,2987,2997,3001,3006,3023,
-3061,3119,3184,3245,3297,3338,3370,3393,3403,3401,3390,3377,3361,3344,3324,3303,3287,3280,3281,3285,3284,
-3275,3260,3241,3220,3199,3182,3176,3186,3213,3246,3271,3276,3266,3253,3253,3267,3281,3282,3266,3248,3240,
-3244,3248,3242,3225,3214,3221,3241,3261,3268,3266,3268,3281,3301,3318,3333,3353,3386,3429,3474,3515,3556,
-3603,3653,3698,3732,3762,3796,3835,3871,3893,3906,3925,3958,3997,4026,4037,4041,4056,4085,4115,4131,4133,
-4134,4147,4165,4178,4185,4199,4230,4269,4293,4285,4252,4217,4196,4185,4167,4137,4103,4079,4066,4051,4026,
-3997,3980,3980,3979,3955,3901,3836,3784,3756,3742,3723,3692,3655,3618,3580,3537,3485,3429,3378,3334,3295,
-3256,3217,3181,3147,3114,3080,3047,3016,2989,2962,2932,2900,2870,2845,2826,2809,2791,2768,2742,2714,2690,
-2672,2660,2652,2643,2633,2623,2615,2609,2605,2599,2594,2593,2597,2600,2597,2587,2575,2565,2558,2548,2534,
-2517,2501,2492,2488,2482,2470,2453,2434,2413,2393,2371,2345,2316,2283,2248,2214,2182,2152,2121,2086,2051,
-2017,1987,1961,1934,1904,1873,1841,1812,1784,1758,1732,1709,1690,1673,1660,1651,1644,1636,1623,1602,1574,
-1549,1537,1543,1561,1579,1582,1561,1518,1458,1393,1332,1281,1242,1210,1176,1135,1088,1039,995,957,922,
-886,846,806,768,732,696,658,619,583,550,518,482,443,404,367,333,297,255,208,158,109,
-61,15,-29,-74,-118,-161,-201,-238,-274,-311,-353,-400,-449,-496,-541,-583,-625,-667,-709,-752,-799,
--850,-904,-954,-999,-1040,-1083,-1131,-1183,-1236,-1286,-1333,-1380,-1427,-1475,-1522,-1569,-1614,-1657,-1698,-1741,-1786,
--1837,-1890,-1941,-1986,-2027,-2067,-2110,-2154,-2197,-2238,-2278,-2319,-2360,-2400,-2438,-2476,-2515,-2556,-2596,-2634,-2667,
--2696,-2722,-2747,-2774,-2805,-2841,-2877,-2911,-2941,-2967,-2995,-3025,-3054,-3079,-3100,-3120,-3144,-3173,-3200,-3220,-3231,
--3240,-3252,-3271,-3292,-3311,-3324,-3332,-3339,-3347,-3358,-3372,-3387,-3405,-3423,-3440,-3453,-3463,-3471,-3479,-3487,-3494,
--3500,-3504,-3506,-3506,-3506,-3504,-3503,-3503,-3504,-3506,-3508,-3509,-3508,-3506,-3505,-3506,-3506,-3506,-3502,-3495,-3485,
--3474,-3462,-3451,-3441,-3434,-3429,-3426,-3421,-3413,-3402,-3390,-3381,-3375,-3367,-3355,-3338,-3317,-3297,-3280,-3267,-3256,
--3246,-3234,-3219,-3201,-3180,-3159,-3140,-3124,-3108,-3089,-3068,-3047,-3028,-3013,-2999,-2979,-2955,-2931,-2911,-2896,-2881,
--2861,-2835,-2809,-2790,-2776,-2762,-2741,-2714,-2683,-2653,-2621,-2587,-2548,-2508,-2471,-2439,-2410,-2383,-2358,-2333,-2308,
--2279,-2245,-2204,-2161,-2118,-2074,-2027,-1976,-1926,-1878,-1837,-1799,-1759,-1715,-1668,-1622,-1583,-1552,-1526,-1499,-1468,
--1433,-1396,-1359,-1320,-1275,-1220,-1156,-1083,-1002,-911,-808,-693,-575,-465,-373,-301,-244,-191,-139,-88,-44,
--11,13,36,60,83,101,107,104,96,93,100,122,159,203,237,238,193,105,1,-88,-140,
--152,-138,-113,-86,-57,-20,24,73,119,155,180,198,219,250,290,330,360,373,377,382,394,
-412,431,448,463,479,497,514,533,553,574,588,591,586,582,589,606,624,636,643,654,675,
-703,732,759,787,818,846,868,888,919,975,1051,1126,1181,1213,1243,1293,1366,1441,1490,1503,1489,
-1471,1472,1502,1560,1640,1731,1820,1897,1961,2015,2064,2110,2144,2164,2167,2160,2148,2136,2126,2118,2114,
-2116,2123,2139,2163,2192,2220,2237,2237,2223,2202,2178,2159,2147,2149,2172,2218,2277,2329,2353,2327,2245,
-2118,1979,1868,1825,1861,1957,2064,2136,2145,2100,2033,1984,1981,2022,2087,2145,2177,2182,2173,2162,2150,
-2127,2088,2040,1994,1956,1920,1875,1818,1758,1707,1671,1640,1605,1557,1497,1430,1359,1291,1232,1188,1159,
-1136,1111,1082,1057,1041,1033,1020,994,954,907,864,829,804,789,782,775,757,724,695,698,750,
-840,926,962,931,849,755,679,626,590,562,540,526,518,507,490,470,453,441,431,416,394,
-368,344,324,306,290,276,267,260,252,240,229,223,223,225,222,210,188,162,134,109,88,
-70,57,46,34,19,1,-16,-36,-56,-77,-100,-123,-145,-168,-191,-216,-243,-272,-303,-334,-364,
--393,-423,-458,-498,-538,-575,-605,-631,-656,-682,-708,-733,-754,-772,-787,-800,-813,-827,-841,-856,-872,
--886,-900,-911,-919,-925,-930,-938,-948,-961,-977,-993,-1011,-1030,-1045,-1056,-1064,-1070,-1077,-1086,-1093,-1099,
--1104,-1112,-1123,-1135,-1144,-1150,-1154,-1161,-1170,-1177,-1180,-1180,-1180,-1183,-1189,-1195,-1202,-1208,-1214,-1219,-1223,
--1226,-1228,-1229,-1230,-1231,-1232,-1234,-1236,-1241,-1245,-1251,-1257,-1263,-1268,-1271,-1272,-1273,-1274,-1276,-1276,-1274,
--1270,-1264,-1258,-1249,-1240,-1232,-1228,-1227,-1228,-1229,-1229,-1230,-1232,-1234,-1233,-1230,-1225,-1224,-1226,-1229,-1230,
--1226,-1222,-1221,-1223,-1225,-1226,-1225,-1225,-1227,-1230,-1233,-1236,-1238,-1244,-1252,-1260,-1267,-1274,-1281,-1289,-1296,
--1300,-1301,-1299,-1296,-1294,-1293,-1293,-1291,-1289,-1285,-1279,-1272,-1264,-1257,-1249,-1241,-1233,-1225,-1216,-1206,-1195,
--1186,-1179,-1173,-1166,-1158,-1150,-1142,-1135,-1129,-1121,-1112,-1104,-1096,-1089,-1079,-1066,-1054,-1045,-1040,-1038,-1036,
--1033,-1030,-1027,-1024,-1021,-1018,-1017,-1016,-1014,-1008,-998,-987,-977,-970,-966,-961,-956,-948,-939,-927,-914,
--900,-887,-873,-858,-842,-825,-808,-793,-782,-774,-770,-766,-763,-758,-753,-748,-743,-735,-723,-707,-691,
--676,-664,-653,-643,-631,-617,-598,-574,-546,-516,-488,-464,-443,-424,-408,-394,-383,-371,-357,-342,-326,
--312,-299,-283,-266,-250,-238,-229,-220,-207,-191,-177,-170,-167,-165,-159,-148,-135,-124,-115,-107,-99,
--91,-83,-75,-64,-53,-44,-36,-30,-20,-6,11,27,37,43,47,53,64,81,103,132,164,
-196,228,258,289,322,355,387,415,443,472,504,536,566,593,619,648,678,709,740,772,806,
-841,875,905,933,964,994,1022,1042,1055,1066,1072,1065,1036,992,954,951,994,1073,1166,1258,1351,
-1454,1565,1675,1771,1857,1950,2061,2185,2301,2384,2422,2416,2375,2310,2237,2171,2121,2086,2055,2018,1974,
-1930,1894,1863,1831,1794,1757,1724,1694,1660,1619,1573,1531,1497,1467,1439,1413,1395,1386,1383,1379,1372,
-1363,1361,1365,1374,1380,1381,1378,1374,1367,1355,1334,1304,1273,1249,1241,1248,1265,1281,1292,1299,1303,
-1306,1299,1277,1243,1204,1164,1121,1067,999,917,827,731,625,510,393,290,214,167,140,116,88,
-53,17,-18,-53,-90,-127,-164,-197,-224,-247,-267,-289,-312,-336,-357,-377,-396,-416,-434,-450,-464,
--480,-496,-513,-526,-537,-548,-565,-584,-602,-614,-623,-635,-654,-676,-692,-700,-705,-714,-727,-737,-737,
--731,-724,-722,-723,-719,-709,-695,-682,-672,-661,-648,-635,-624,-615,-604,-587,-566,-545,-522,-497,-467,
--435,-406,-384,-367,-349,-324,-292,-260,-231,-202,-170,-130,-86,-40,3,47,92,141,191,241,286,
-328,369,413,464,521,583,642,695,740,780,818,858,900,941,979,1017,1054,1093,1134,1174,1212,
-1249,1287,1325,1365,1404,1442,1479,1515,1548,1579,1610,1641,1674,1707,1738,1766,1792,1817,1843,1868,1889,
-1909,1930,1955,1984,2015,2042,2064,2086,2109,2134,2159,2181,2199,2215,2232,2252,2275,2298,2318,2334,2345,
-2351,2350,2340,2327,2315,2309,2309,2310,2309,2305,2302,2302,2304,2301,2292,2281,2273,2268,2264,2255,2243,
-2231,2226,2226,2225,2217,2204,2194,2196,2208,2215,2205,2173,2131,2101,2095,2107,2117,2103,2060,2002,1950,
-1918,1907,1904,1897,1882,1861,1838,1817,1796,1776,1759,1745,1735,1729,1726,1723,1719,1713,1705,1697,1690,
-1687,1699,1705,1716,1730,1744,1758,1771,1787,1808,1835,1863,1885,1900,1909,1919,1930,1944,1956,1966,1975,
-1982,1988,1992,1999,2012,2030,2050,2068,2085,2107,2136,2168,2196,2219,2243,2276,2317,2356,2387,2408,2431,
-2460,2490,2511,2521,2531,2556,2593,2625,2635,2625,2619,2639,2679,2711,2707,2667,2618,2596,2612,2654,2697,
-2725,2739,2747,2754,2761,2770,2783,2804,2834,2867,2896,2915,2923,2921,2915,2910,2911,2918,2926,2931,2933,
-2936,2943,2954,2964,2968,2970,2976,2989,3004,3015,3020,3027,3050,3097,3163,3234,3296,3345,3382,3412,3436,
-3449,3449,3438,3420,3400,3381,3364,3347,3332,3318,3307,3300,3296,3294,3288,3275,3251,3221,3196,3190,3210,
-3253,3302,3336,3345,3333,3316,3309,3313,3317,3310,3293,3276,3270,3274,3276,3269,3256,3251,3261,3282,3300,
-3308,3309,3315,3330,3350,3369,3389,3415,3452,3495,3536,3572,3610,3653,3700,3741,3774,3805,3843,3884,3919,
-3940,3957,3982,4020,4058,4079,4079,4078,4095,4131,4169,4188,4189,4191,4206,4228,4243,4245,4245,4257,4278,
-4290,4278,4243,4206,4179,4160,4140,4112,4084,4068,4059,4048,4027,4003,3988,3983,3975,3947,3900,3851,3816,
-3799,3785,3761,3726,3687,3650,3611,3564,3508,3454,3408,3371,3337,3302,3266,3233,3203,3172,3137,3100,3065,
-3035,3008,2980,2951,2923,2899,2879,2859,2836,2810,2781,2752,2728,2710,2697,2688,2679,2669,2659,2651,2647,
-2643,2638,2634,2632,2631,2629,2621,2608,2594,2584,2576,2566,2553,2537,2525,2519,2515,2509,2498,2485,2470,
-2454,2435,2412,2383,2352,2320,2287,2255,2224,2194,2163,2131,2097,2063,2032,2003,1975,1946,1916,1887,1859,
-1831,1804,1777,1753,1733,1717,1705,1696,1687,1675,1656,1631,1605,1587,1583,1594,1611,1620,1613,1586,1541,
-1487,1431,1380,1336,1299,1263,1224,1179,1133,1089,1051,1016,978,937,894,854,820,788,755,718,680,
-644,610,576,540,501,463,429,396,359,314,263,211,162,117,75,32,-11,-55,-96,-134,-169,
--203,-240,-283,-330,-380,-430,-478,-523,-565,-607,-648,-691,-740,-791,-843,-891,-936,-980,-1026,-1076,-1126,
--1175,-1222,-1269,-1317,-1365,-1412,-1457,-1501,-1545,-1589,-1632,-1675,-1722,-1775,-1828,-1878,-1922,-1960,-1999,-2041,-2086,
--2131,-2174,-2216,-2258,-2300,-2341,-2380,-2418,-2458,-2499,-2540,-2577,-2610,-2639,-2664,-2688,-2712,-2741,-2777,-2816,-2852,
--2883,-2908,-2934,-2964,-2995,-3023,-3047,-3070,-3097,-3127,-3156,-3175,-3185,-3192,-3204,-3226,-3250,-3271,-3286,-3296,-3306,
--3318,-3331,-3344,-3359,-3377,-3396,-3413,-3425,-3432,-3437,-3445,-3456,-3467,-3476,-3481,-3483,-3482,-3479,-3476,-3474,-3475,
--3479,-3483,-3485,-3483,-3479,-3477,-3476,-3475,-3473,-3469,-3465,-3461,-3456,-3449,-3439,-3428,-3420,-3414,-3408,-3402,-3393,
--3383,-3374,-3367,-3361,-3353,-3343,-3331,-3317,-3302,-3286,-3269,-3254,-3240,-3227,-3214,-3199,-3180,-3159,-3138,-3118,-3103,
--3089,-3075,-3060,-3042,-3023,-3004,-2984,-2962,-2939,-2916,-2898,-2884,-2871,-2853,-2831,-2807,-2788,-2772,-2755,-2731,-2700,
--2666,-2634,-2604,-2574,-2542,-2509,-2478,-2450,-2422,-2392,-2362,-2331,-2301,-2268,-2229,-2186,-2140,-2095,-2051,-2006,-1960,
--1913,-1869,-1829,-1794,-1760,-1724,-1685,-1645,-1607,-1572,-1541,-1516,-1495,-1474,-1449,-1417,-1376,-1331,-1286,-1243,-1198,
--1142,-1066,-967,-850,-725,-603,-493,-395,-306,-224,-151,-96,-64,-54,-53,-46,-29,-5,14,25,33,
-41,52,64,78,102,142,188,214,191,112,0,-105,-168,-184,-172,-154,-138,-119,-87,-40,11,
-57,90,113,134,161,197,238,273,296,305,308,315,328,347,364,379,393,408,422,437,453,
-473,495,513,522,522,520,526,538,552,562,571,586,611,642,673,699,724,753,782,806,828,
-862,918,994,1069,1122,1149,1172,1213,1279,1350,1402,1418,1408,1392,1394,1424,1484,1564,1653,1738,1812,
-1874,1927,1976,2018,2051,2071,2081,2083,2080,2072,2059,2046,2041,2046,2061,2082,2107,2131,2146,2144,2118,
-2074,2025,1983,1953,1931,1916,1911,1923,1955,1998,2033,2035,1991,1910,1820,1763,1769,1843,1954,2057,2109,
-2098,2044,1986,1958,1974,2022,2076,2114,2127,2123,2115,2107,2097,2075,2037,1991,1945,1902,1859,1809,1754,
-1703,1663,1632,1599,1554,1495,1426,1354,1283,1217,1163,1124,1098,1076,1050,1022,997,980,966,945,911,
-869,828,794,766,741,720,707,701,691,670,646,640,669,729,792,827,819,783,744,713,682,
-635,569,501,452,431,431,435,431,417,400,383,368,353,336,318,297,274,252,235,223,217,
-210,202,192,186,185,185,183,172,154,130,106,82,61,44,31,21,10,-3,-21,-42,-64,
--83,-101,-118,-134,-153,-173,-195,-220,-248,-277,-308,-337,-365,-394,-424,-459,-497,-536,-572,-604,-633,
--661,-689,-718,-745,-769,-789,-806,-819,-832,-845,-860,-877,-894,-911,-925,-937,-946,-953,-961,-969,-977,
--986,-994,-1003,-1015,-1030,-1047,-1063,-1074,-1083,-1091,-1099,-1107,-1114,-1119,-1126,-1135,-1146,-1156,-1165,-1174,-1182,
--1190,-1195,-1196,-1196,-1195,-1197,-1201,-1206,-1210,-1215,-1220,-1225,-1228,-1230,-1231,-1233,-1236,-1239,-1242,-1246,-1250,
--1254,-1259,-1264,-1268,-1271,-1273,-1273,-1274,-1277,-1283,-1289,-1292,-1290,-1285,-1279,-1271,-1261,-1251,-1241,-1234,-1232,
--1232,-1231,-1229,-1229,-1231,-1233,-1233,-1230,-1224,-1221,-1222,-1225,-1226,-1224,-1220,-1219,-1220,-1222,-1225,-1227,-1229,
--1231,-1233,-1236,-1241,-1249,-1258,-1265,-1269,-1272,-1276,-1283,-1292,-1298,-1301,-1300,-1298,-1296,-1295,-1291,-1286,-1281,
--1277,-1275,-1274,-1270,-1264,-1255,-1246,-1239,-1232,-1224,-1214,-1203,-1192,-1182,-1172,-1163,-1154,-1146,-1139,-1134,-1129,
--1122,-1114,-1107,-1102,-1098,-1092,-1080,-1065,-1053,-1046,-1044,-1043,-1039,-1034,-1030,-1029,-1030,-1028,-1024,-1020,-1017,
--1014,-1008,-999,-988,-979,-974,-970,-966,-958,-948,-937,-925,-912,-897,-881,-865,-850,-836,-822,-809,-796,
--785,-778,-773,-770,-767,-762,-756,-750,-742,-733,-721,-708,-695,-683,-672,-660,-647,-633,-617,-599,-577,
--551,-521,-491,-463,-440,-419,-403,-388,-376,-362,-347,-332,-318,-306,-294,-279,-260,-242,-227,-216,-206,
--195,-181,-168,-158,-153,-148,-141,-132,-124,-117,-108,-98,-88,-79,-74,-68,-61,-52,-42,-33,-24,
--14,-1,11,23,31,36,42,51,65,83,106,135,168,202,234,265,295,325,355,387,418,
-450,481,511,539,565,591,621,653,685,716,746,779,814,850,881,910,940,973,1007,1036,1057,
-1071,1083,1089,1079,1046,997,958,954,997,1073,1160,1246,1334,1437,1555,1675,1785,1884,1984,2094,2209,
-2311,2378,2403,2390,2349,2293,2231,2175,2133,2109,2092,2073,2042,2001,1957,1914,1875,1839,1804,1770,1735,
-1696,1652,1607,1564,1526,1491,1459,1431,1412,1402,1397,1389,1374,1355,1338,1329,1331,1341,1353,1363,1371,
-1375,1376,1370,1355,1330,1304,1285,1278,1283,1292,1302,1309,1311,1306,1290,1264,1231,1198,1163,1118,1056,
-975,881,782,678,565,446,334,244,183,146,120,94,65,37,9,-19,-53,-94,-134,-171,-200,
--223,-244,-265,-288,-312,-335,-357,-377,-396,-415,-435,-453,-470,-486,-501,-516,-530,-543,-559,-580,-601,
--618,-628,-636,-648,-666,-685,-699,-705,-710,-718,-730,-740,-742,-738,-733,-730,-726,-719,-707,-694,-683,
--674,-662,-647,-631,-617,-605,-591,-572,-549,-526,-504,-480,-452,-421,-392,-370,-353,-333,-307,-277,-248,
--222,-196,-166,-129,-87,-44,-2,41,88,137,187,235,281,325,369,414,463,517,577,635,688,
-732,773,814,859,905,947,985,1020,1058,1099,1142,1184,1224,1262,1302,1344,1386,1426,1465,1501,1534,
-1563,1588,1614,1642,1673,1706,1738,1768,1798,1828,1856,1880,1901,1921,1947,1979,2013,2044,2070,2093,2116,
-2140,2164,2186,2206,2223,2240,2257,2275,2293,2311,2328,2344,2355,2361,2360,2352,2342,2334,2331,2332,2332,
-2330,2327,2325,2326,2326,2322,2312,2302,2297,2298,2296,2285,2266,2248,2239,2239,2238,2227,2210,2197,2199,
-2211,2219,2207,2177,2148,2143,2168,2208,2234,2221,2169,2092,2017,1960,1926,1908,1896,1884,1871,1857,1841,
-1824,1806,1787,1770,1759,1753,1751,1748,1741,1729,1715,1704,1698,1699,1722,1727,1732,1740,1754,1771,1788,
-1804,1820,1836,1855,1873,1891,1906,1919,1930,1937,1943,1950,1961,1973,1983,1989,1995,2006,2024,2046,2067,
-2086,2106,2133,2165,2198,2230,2262,2300,2341,2380,2410,2432,2453,2479,2507,2527,2538,2546,2565,2597,2634,
-2659,2668,2665,2658,2651,2637,2616,2597,2596,2620,2660,2698,2720,2727,2732,2744,2765,2790,2815,2838,2863,
-2889,2912,2928,2935,2932,2923,2912,2907,2911,2922,2936,2943,2941,2937,2936,2943,2955,2967,2977,2987,2998,
-3010,3020,3031,3050,3086,3141,3210,3279,3338,3383,3418,3446,3469,3482,3483,3470,3448,3426,3408,3395,3384,
-3370,3352,3332,3318,3313,3315,3315,3304,3279,3246,3222,3222,3252,3303,3357,3392,3401,3389,3370,3357,3352,
-3346,3332,3313,3298,3294,3297,3298,3293,3284,3284,3298,3320,3340,3352,3361,3373,3392,3412,3431,3452,3479,
-3515,3556,3595,3631,3669,3712,3757,3796,3828,3860,3897,3938,3972,3997,4020,4053,4095,4130,4142,4135,4132,
-4151,4191,4228,4244,4241,4241,4257,4281,4293,4284,4264,4252,4253,4257,4246,4219,4187,4160,4141,4122,4101,
-4082,4070,4062,4051,4034,4016,4006,4000,3986,3955,3912,3873,3850,3838,3822,3794,3755,3714,3675,3635,3587,
-3534,3485,3447,3417,3387,3354,3319,3287,3258,3227,3191,3152,3115,3083,3054,3024,2994,2966,2943,2924,2903,
-2880,2852,2824,2797,2774,2755,2740,2728,2717,2706,2696,2688,2683,2680,2678,2674,2669,2662,2652,2638,2622,
-2607,2597,2588,2579,2567,2556,2548,2545,2543,2537,2528,2518,2507,2495,2476,2450,2419,2388,2359,2331,2302,
-2273,2244,2214,2183,2150,2115,2080,2047,2017,1988,1960,1933,1907,1879,1850,1821,1796,1777,1762,1751,1739,
-1725,1708,1686,1663,1644,1634,1636,1647,1658,1659,1643,1610,1567,1518,1471,1427,1386,1347,1306,1264,1222,
-1181,1145,1110,1074,1032,987,944,908,877,848,816,779,742,705,670,633,595,558,523,491,458,
-416,365,310,259,214,175,138,99,59,18,-20,-58,-95,-132,-171,-214,-261,-311,-363,-413,-459,
--501,-541,-584,-630,-680,-731,-781,-827,-873,-920,-969,-1019,-1066,-1111,-1157,-1206,-1256,-1305,-1351,-1394,-1437,
--1482,-1528,-1573,-1618,-1665,-1716,-1767,-1815,-1858,-1896,-1936,-1980,-2027,-2073,-2117,-2158,-2199,-2240,-2279,-2319,-2359,
--2401,-2443,-2483,-2519,-2550,-2579,-2606,-2630,-2655,-2684,-2720,-2760,-2798,-2829,-2855,-2881,-2910,-2941,-2969,-2992,-3015,
--3041,-3073,-3103,-3125,-3138,-3148,-3163,-3186,-3211,-3232,-3247,-3259,-3272,-3288,-3304,-3318,-3333,-3349,-3366,-3382,-3392,
--3398,-3402,-3409,-3419,-3430,-3439,-3445,-3449,-3451,-3449,-3445,-3442,-3443,-3448,-3453,-3454,-3451,-3447,-3445,-3446,-3447,
--3446,-3441,-3436,-3434,-3433,-3428,-3419,-3407,-3398,-3392,-3387,-3378,-3367,-3356,-3348,-3344,-3340,-3333,-3321,-3308,-3297,
--3287,-3276,-3261,-3244,-3228,-3213,-3199,-3183,-3164,-3143,-3121,-3101,-3084,-3070,-3059,-3046,-3031,-3011,-2989,-2966,-2943,
--2921,-2902,-2885,-2871,-2858,-2842,-2822,-2801,-2781,-2762,-2742,-2715,-2682,-2647,-2615,-2590,-2567,-2544,-2518,-2490,-2460,
--2428,-2394,-2357,-2321,-2285,-2248,-2209,-2165,-2120,-2074,-2031,-1989,-1948,-1908,-1869,-1832,-1797,-1764,-1731,-1698,-1662,
--1624,-1584,-1549,-1526,-1516,-1511,-1500,-1471,-1426,-1377,-1334,-1300,-1269,-1227,-1166,-1084,-985,-872,-749,-619,-486,
--359,-248,-165,-117,-102,-107,-116,-113,-97,-74,-55,-39,-21,3,28,46,55,69,100,144,172,
-151,70,-42,-143,-199,-209,-198,-187,-182,-168,-136,-89,-42,-5,20,44,74,110,148,182,207,
-222,231,238,249,264,282,299,315,331,347,362,375,387,401,420,439,452,457,459,464,475,
-488,500,513,531,557,587,615,641,669,702,736,764,786,814,858,920,985,1034,1066,1092,1132,
-1189,1250,1293,1308,1304,1299,1312,1353,1420,1505,1593,1675,1744,1799,1844,1883,1916,1942,1962,1978,1992,
-2000,1999,1991,1982,1980,1988,2002,2017,2035,2055,2070,2065,2030,1965,1888,1817,1762,1717,1673,1630,1599,
-1595,1624,1675,1725,1755,1759,1752,1756,1792,1861,1944,2007,2028,2006,1962,1929,1928,1963,2014,2057,2080,
-2081,2072,2063,2055,2041,2014,1974,1928,1883,1839,1795,1745,1696,1652,1617,1585,1545,1490,1422,1348,1275,
-1208,1148,1100,1065,1039,1015,987,958,932,913,895,868,829,788,753,730,711,690,665,645,634,
-631,626,618,611,614,625,635,635,630,636,660,690,694,648,556,448,366,331,338,361,377,
-376,362,342,323,306,292,276,258,236,211,189,174,166,161,155,149,143,141,140,136,126,
-110,90,70,52,36,21,8,-3,-14,-26,-41,-60,-82,-104,-125,-142,-158,-173,-189,-207,-228,
--252,-280,-310,-339,-368,-395,-425,-458,-494,-530,-566,-599,-630,-661,-691,-722,-753,-783,-809,-828,-843,
--854,-866,-881,-899,-918,-934,-948,-958,-967,-976,-987,-998,-1008,-1013,-1014,-1014,-1017,-1027,-1043,-1061,-1077,
--1090,-1100,-1110,-1119,-1126,-1131,-1136,-1143,-1152,-1164,-1176,-1188,-1198,-1206,-1211,-1213,-1213,-1213,-1214,-1216,-1218,
--1221,-1224,-1229,-1233,-1237,-1240,-1242,-1245,-1248,-1252,-1258,-1263,-1269,-1273,-1275,-1277,-1278,-1279,-1279,-1279,-1279,
--1283,-1288,-1292,-1293,-1290,-1286,-1282,-1278,-1273,-1265,-1256,-1249,-1246,-1245,-1243,-1240,-1237,-1236,-1235,-1232,-1227,
--1221,-1218,-1219,-1221,-1222,-1221,-1217,-1215,-1214,-1215,-1217,-1220,-1222,-1224,-1227,-1232,-1240,-1251,-1261,-1268,-1270,
--1271,-1274,-1281,-1291,-1297,-1299,-1297,-1295,-1293,-1290,-1284,-1275,-1268,-1266,-1266,-1267,-1265,-1258,-1248,-1238,-1230,
--1224,-1218,-1211,-1203,-1195,-1186,-1176,-1165,-1155,-1145,-1138,-1132,-1126,-1117,-1108,-1101,-1097,-1094,-1087,-1075,-1061,
--1051,-1047,-1048,-1046,-1041,-1034,-1030,-1031,-1033,-1033,-1028,-1021,-1015,-1011,-1005,-997,-987,-980,-976,-974,-968,
--958,-945,-933,-922,-911,-897,-881,-864,-848,-835,-823,-813,-803,-793,-786,-781,-777,-773,-766,-759,-751,
--743,-735,-725,-715,-704,-693,-679,-663,-645,-627,-609,-592,-573,-550,-522,-492,-463,-438,-417,-399,-382,
--367,-350,-334,-318,-304,-292,-281,-268,-252,-234,-218,-205,-194,-184,-173,-162,-152,-143,-134,-126,-122,
--119,-117,-111,-101,-89,-80,-74,-69,-63,-54,-43,-32,-21,-10,0,11,21,28,35,43,54,
-69,89,115,145,179,213,245,274,301,326,354,384,418,452,484,512,537,562,591,625,658,
-688,716,744,777,814,850,881,910,940,975,1012,1043,1067,1084,1098,1104,1091,1054,1001,958,952,
-995,1077,1176,1276,1374,1477,1585,1695,1800,1904,2012,2126,2235,2320,2365,2372,2352,2321,2286,2247,2211,
-2182,2167,2162,2153,2129,2086,2030,1974,1925,1884,1846,1805,1760,1710,1660,1610,1565,1524,1490,1463,1442,
-1426,1414,1403,1389,1369,1342,1315,1297,1296,1312,1334,1353,1363,1367,1369,1372,1371,1362,1344,1324,1311,
-1306,1308,1312,1314,1312,1302,1282,1255,1224,1193,1155,1100,1022,925,819,711,603,492,382,285,211,
-161,127,97,66,39,17,-1,-26,-61,-102,-140,-171,-195,-217,-239,-264,-288,-311,-333,-355,-376,
--397,-418,-438,-458,-476,-492,-505,-518,-532,-549,-569,-591,-612,-627,-638,-647,-660,-676,-693,-705,-713,
--720,-728,-738,-745,-747,-746,-744,-742,-737,-726,-712,-698,-687,-676,-662,-644,-625,-609,-595,-578,-557,
--533,-510,-489,-468,-442,-411,-381,-355,-334,-312,-286,-259,-232,-207,-181,-152,-120,-86,-51,-14,28,
-76,127,177,226,275,324,372,419,466,518,574,631,683,728,769,811,856,901,941,976,1010,
-1049,1092,1136,1178,1217,1258,1302,1347,1390,1428,1465,1499,1532,1560,1585,1610,1638,1671,1706,1741,1777,
-1813,1849,1879,1903,1921,1942,1971,2006,2041,2071,2096,2118,2141,2165,2187,2205,2222,2240,2258,2276,2292,
-2307,2324,2342,2357,2367,2370,2369,2366,2363,2360,2358,2356,2351,2344,2336,2329,2326,2325,2322,2318,2314,
-2314,2317,2316,2308,2293,2281,2275,2272,2262,2241,2216,2202,2206,2219,2222,2205,2175,2155,2165,2203,2249,
-2276,2265,2219,2150,2075,2010,1959,1924,1904,1892,1883,1873,1860,1844,1826,1807,1790,1777,1770,1767,1763,
-1753,1739,1725,1718,1718,1722,1747,1747,1746,1750,1763,1783,1804,1819,1830,1838,1848,1861,1879,1899,1917,
-1930,1934,1933,1935,1945,1961,1978,1989,1995,2003,2017,2038,2061,2082,2104,2132,2168,2208,2248,2286,2324,
-2362,2398,2428,2453,2477,2503,2530,2551,2562,2570,2584,2609,2642,2671,2687,2684,2663,2632,2603,2591,2609,
-2656,2717,2767,2788,2783,2768,2763,2776,2802,2830,2855,2877,2897,2915,2929,2936,2938,2937,2933,2926,2921,
-2922,2930,2941,2947,2945,2938,2935,2942,2956,2972,2983,2990,2995,3006,3024,3050,3087,3135,3192,3254,3314,
-3366,3410,3445,3473,3493,3503,3501,3488,3469,3451,3438,3431,3424,3411,3390,3364,3342,3331,3330,3329,3319,
-3297,3272,3256,3263,3294,3340,3385,3414,3421,3411,3395,3382,3372,3362,3347,3330,3317,3312,3313,3312,3308,
-3305,3313,3334,3362,3388,3408,3425,3444,3466,3488,3506,3523,3547,3580,3619,3659,3698,3738,3781,3822,3858,
-3888,3920,3957,3997,4032,4060,4086,4120,4159,4190,4202,4200,4204,4226,4261,4286,4290,4279,4275,4290,4312,
-4319,4301,4268,4241,4230,4229,4223,4206,4181,4159,4140,4124,4109,4096,4088,4079,4065,4049,4036,4031,4025,
-4008,3973,3931,3898,3879,3868,3850,3817,3774,3732,3693,3654,3610,3565,3525,3495,3469,3441,3408,3373,3340,
-3309,3275,3238,3199,3163,3130,3097,3062,3028,3000,2980,2963,2944,2920,2892,2865,2841,2819,2801,2784,2770,
-2756,2743,2731,2721,2715,2713,2711,2708,2701,2689,2672,2653,2634,2619,2608,2600,2591,2581,2574,2570,2570,
-2568,2564,2557,2551,2544,2534,2515,2487,2456,2426,2400,2376,2350,2322,2292,2262,2232,2198,2162,2125,2090,
-2057,2028,2001,1977,1952,1926,1898,1870,1845,1825,1811,1797,1781,1761,1738,1717,1701,1691,1689,1692,1697,
-1698,1690,1668,1635,1595,1552,1511,1471,1432,1391,1349,1308,1269,1235,1202,1166,1126,1082,1039,1001,969,
-942,912,877,840,802,765,729,690,652,616,584,553,516,468,412,357,310,273,241,208,172,
-134,96,60,23,-16,-57,-101,-147,-196,-247,-299,-348,-392,-432,-473,-518,-568,-620,-670,-716,-760,
--806,-856,-906,-954,-999,-1043,-1091,-1143,-1197,-1247,-1292,-1333,-1376,-1423,-1471,-1519,-1566,-1613,-1661,-1709,-1753,
--1794,-1834,-1878,-1925,-1974,-2020,-2063,-2103,-2142,-2182,-2221,-2260,-2302,-2345,-2386,-2424,-2457,-2486,-2515,-2543,-2572,
--2600,-2632,-2668,-2706,-2742,-2773,-2800,-2828,-2858,-2890,-2917,-2940,-2961,-2987,-3018,-3050,-3075,-3093,-3108,-3127,-3151,
--3176,-3196,-3211,-3223,-3238,-3255,-3272,-3287,-3301,-3316,-3333,-3348,-3360,-3367,-3372,-3377,-3385,-3392,-3399,-3406,-3413,
--3417,-3416,-3412,-3409,-3410,-3416,-3423,-3424,-3419,-3413,-3412,-3416,-3421,-3421,-3417,-3412,-3409,-3408,-3403,-3393,-3380,
--3371,-3367,-3364,-3357,-3346,-3334,-3327,-3324,-3322,-3315,-3303,-3290,-3278,-3269,-3258,-3243,-3226,-3210,-3196,-3183,-3168,
--3150,-3129,-3107,-3085,-3066,-3050,-3038,-3026,-3011,-2991,-2969,-2947,-2927,-2909,-2893,-2877,-2862,-2847,-2831,-2813,-2792,
--2771,-2749,-2725,-2696,-2664,-2633,-2606,-2586,-2569,-2549,-2523,-2491,-2456,-2420,-2381,-2341,-2301,-2261,-2224,-2187,-2149,
--2109,-2068,-2028,-1988,-1949,-1913,-1877,-1840,-1804,-1769,-1736,-1705,-1673,-1637,-1597,-1560,-1538,-1532,-1536,-1531,-1506,
--1465,-1419,-1381,-1353,-1324,-1284,-1231,-1168,-1096,-1007,-890,-741,-573,-410,-279,-196,-161,-159,-169,-172,-160,
--138,-116,-100,-85,-63,-33,-3,16,27,44,79,123,144,110,16,-100,-192,-233,-233,-221,-218,
--218,-206,-171,-126,-89,-67,-50,-25,14,58,95,119,132,142,154,168,184,201,220,240,259,
-277,293,306,317,326,337,352,368,382,390,394,400,411,427,445,464,485,508,533,559,587,
-620,659,698,728,748,766,795,838,889,936,974,1010,1051,1099,1144,1175,1186,1188,1196,1224,1277,
-1353,1442,1532,1611,1674,1723,1760,1791,1815,1836,1855,1874,1892,1906,1913,1915,1919,1927,1936,1942,1945,
-1953,1972,1994,1999,1965,1890,1792,1697,1616,1543,1466,1385,1317,1287,1313,1389,1493,1599,1686,1749,1793,
-1828,1861,1890,1906,1902,1881,1858,1854,1879,1930,1988,2033,2054,2053,2043,2032,2018,1995,1958,1911,1861,
-1816,1775,1733,1688,1640,1595,1555,1515,1468,1411,1347,1279,1213,1153,1099,1055,1022,995,967,934,898,
-867,843,819,790,753,717,689,671,658,640,616,595,586,588,596,599,593,576,548,511,475,
-459,477,530,591,621,594,512,407,317,268,261,277,297,309,309,300,283,264,244,225,207,
-187,166,145,129,118,112,106,99,93,90,89,87,78,62,43,26,14,5,-3,-14,-27,
--39,-50,-61,-75,-95,-119,-145,-169,-189,-204,-217,-228,-241,-259,-282,-309,-338,-367,-395,-424,-455,
--489,-524,-560,-595,-628,-660,-692,-724,-757,-791,-823,-848,-864,-875,-886,-902,-921,-941,-958,-970,-980,
--987,-996,-1007,-1019,-1029,-1035,-1034,-1030,-1028,-1032,-1043,-1059,-1076,-1091,-1105,-1117,-1128,-1136,-1140,-1144,-1148,
--1156,-1168,-1180,-1192,-1203,-1212,-1220,-1226,-1230,-1231,-1232,-1232,-1233,-1236,-1239,-1243,-1248,-1252,-1257,-1261,-1263,
--1266,-1269,-1274,-1281,-1286,-1289,-1288,-1286,-1285,-1285,-1286,-1287,-1288,-1289,-1290,-1290,-1288,-1283,-1279,-1279,-1280,
--1281,-1279,-1274,-1270,-1267,-1266,-1264,-1260,-1255,-1249,-1243,-1236,-1227,-1220,-1217,-1218,-1221,-1223,-1221,-1217,-1213,
--1210,-1209,-1207,-1208,-1210,-1213,-1218,-1226,-1235,-1246,-1256,-1263,-1266,-1268,-1272,-1280,-1289,-1294,-1295,-1294,-1292,
--1290,-1286,-1280,-1273,-1268,-1266,-1266,-1264,-1259,-1250,-1239,-1230,-1222,-1216,-1211,-1207,-1202,-1196,-1190,-1182,-1173,
--1162,-1152,-1143,-1134,-1125,-1116,-1106,-1098,-1094,-1090,-1083,-1072,-1060,-1052,-1049,-1048,-1046,-1040,-1034,-1031,-1033,
--1035,-1033,-1026,-1018,-1012,-1008,-1003,-996,-987,-980,-975,-971,-964,-951,-936,-923,-912,-904,-894,-882,-866,
--850,-835,-823,-814,-805,-798,-791,-784,-778,-772,-764,-756,-749,-743,-738,-732,-723,-711,-698,-682,-665,
--646,-627,-609,-593,-574,-552,-524,-493,-463,-438,-417,-398,-381,-363,-346,-330,-314,-299,-285,-272,-259,
--247,-233,-218,-203,-189,-178,-169,-160,-151,-140,-129,-121,-118,-118,-117,-112,-101,-90,-80,-72,-66,
--58,-48,-36,-24,-13,-2,8,17,24,32,39,49,62,80,103,130,160,192,222,252,279,
-303,327,352,381,413,446,476,502,527,554,588,624,658,685,709,736,770,808,844,876,905,
-937,974,1012,1045,1071,1092,1107,1112,1096,1057,1004,962,957,1004,1097,1216,1340,1455,1557,1647,1731,
-1818,1916,2030,2150,2253,2320,2341,2329,2305,2287,2279,2274,2268,2262,2263,2267,2262,2235,2181,2108,2033,
-1968,1913,1859,1802,1742,1686,1634,1586,1541,1500,1468,1448,1435,1423,1409,1391,1372,1350,1324,1298,1280,
-1282,1304,1335,1357,1361,1351,1343,1343,1350,1355,1352,1343,1333,1325,1318,1310,1302,1294,1285,1272,1250,
-1220,1181,1127,1054,958,846,729,617,510,408,314,236,178,137,104,70,38,13,-2,-17,-39,
--73,-109,-141,-164,-184,-207,-235,-263,-288,-309,-331,-354,-379,-402,-422,-441,-461,-479,-496,-510,-523,
--538,-557,-578,-599,-617,-631,-643,-654,-667,-682,-697,-710,-722,-733,-742,-748,-751,-750,-750,-752,-752,
--749,-738,-724,-710,-697,-683,-666,-644,-622,-602,-584,-564,-541,-518,-498,-482,-463,-439,-408,-374,-343,
--317,-293,-269,-245,-221,-195,-167,-138,-110,-85,-60,-30,9,57,109,161,212,264,316,368,417,
-464,516,573,631,684,729,768,807,847,887,924,958,994,1035,1078,1121,1160,1199,1243,1291,1337,
-1377,1410,1442,1475,1509,1541,1570,1599,1632,1670,1710,1750,1789,1830,1868,1899,1922,1939,1960,1989,2025,
-2060,2088,2111,2135,2160,2183,2202,2218,2235,2255,2277,2296,2312,2328,2347,2367,2382,2388,2386,2383,2383,
-2386,2388,2385,2377,2366,2354,2342,2330,2322,2317,2317,2319,2323,2326,2327,2325,2321,2318,2320,2322,2316,
-2297,2266,2238,2227,2233,2243,2239,2215,2183,2162,2166,2187,2210,2220,2210,2185,2148,2102,2049,1996,1952,
-1922,1905,1894,1882,1869,1856,1843,1829,1815,1802,1791,1783,1775,1764,1752,1743,1741,1744,1747,1760,1756,
-1753,1757,1770,1787,1804,1818,1830,1840,1849,1859,1871,1888,1908,1926,1935,1936,1935,1940,1955,1973,1987,
-1995,2001,2012,2031,2055,2080,2107,2140,2181,2227,2271,2310,2345,2379,2412,2444,2474,2502,2530,2555,2576,
-2591,2604,2619,2638,2660,2677,2682,2670,2645,2617,2605,2626,2683,2763,2838,2880,2880,2854,2827,2818,2829,
-2849,2866,2879,2892,2907,2921,2933,2941,2947,2953,2956,2952,2942,2934,2934,2940,2947,2949,2946,2946,2953,
-2966,2978,2984,2985,2990,3006,3038,3082,3133,3184,3233,3282,3331,3381,3428,3468,3496,3511,3515,3511,3503,
-3494,3487,3483,3480,3473,3457,3430,3396,3365,3345,3334,3329,3321,3309,3297,3292,3299,3321,3350,3378,3397,
-3402,3397,3386,3375,3367,3359,3349,3339,3331,3327,3326,3325,3325,3330,3348,3379,3416,3449,3474,3494,3516,
-3542,3566,3585,3601,3622,3651,3689,3731,3773,3813,3850,3884,3915,3945,3978,4017,4057,4092,4118,4139,4163,
-4190,4216,4236,4253,4273,4299,4321,4327,4317,4302,4299,4312,4327,4326,4303,4270,4243,4231,4229,4225,4213,
-4194,4173,4154,4136,4124,4117,4113,4104,4089,4071,4058,4053,4047,4026,3990,3948,3915,3899,3887,3868,3833,
-3789,3747,3709,3674,3637,3602,3572,3548,3524,3496,3463,3427,3393,3359,3321,3281,3242,3206,3172,3137,3100,
-3066,3040,3023,3006,2985,2956,2925,2897,2876,2858,2841,2824,2807,2792,2777,2763,2751,2744,2741,2739,2736,
-2728,2713,2694,2672,2653,2638,2627,2619,2611,2603,2597,2594,2593,2591,2588,2584,2581,2577,2568,2550,2523,
-2494,2467,2443,2420,2393,2363,2332,2302,2271,2237,2202,2166,2131,2099,2069,2042,2017,1995,1972,1948,1922,
-1897,1876,1859,1841,1820,1795,1770,1753,1744,1743,1745,1745,1740,1730,1715,1692,1661,1625,1587,1549,1512,
-1475,1437,1398,1360,1324,1289,1255,1216,1174,1132,1094,1063,1037,1010,977,939,899,861,824,787,748,
-709,674,643,609,566,514,458,409,373,345,318,285,246,206,169,134,98,57,14,-32,-81,
--133,-187,-239,-286,-327,-366,-408,-456,-509,-561,-608,-650,-693,-739,-790,-841,-888,-932,-977,-1027,-1082,
--1137,-1186,-1229,-1270,-1313,-1360,-1409,-1459,-1507,-1555,-1603,-1648,-1689,-1728,-1768,-1813,-1863,-1914,-1961,-2004,-2043,
--2082,-2122,-2163,-2203,-2245,-2287,-2328,-2364,-2395,-2424,-2452,-2481,-2511,-2543,-2575,-2610,-2644,-2677,-2707,-2736,-2767,
--2801,-2835,-2865,-2889,-2913,-2940,-2971,-3002,-3029,-3049,-3068,-3089,-3114,-3138,-3157,-3172,-3186,-3202,-3219,-3236,-3250,
--3264,-3279,-3297,-3314,-3328,-3337,-3343,-3349,-3356,-3364,-3371,-3378,-3384,-3387,-3386,-3382,-3379,-3382,-3388,-3394,-3395,
--3388,-3381,-3379,-3383,-3389,-3391,-3387,-3382,-3379,-3377,-3372,-3362,-3350,-3342,-3339,-3339,-3334,-3324,-3312,-3304,-3302,
--3299,-3293,-3282,-3269,-3257,-3245,-3232,-3217,-3200,-3185,-3173,-3161,-3148,-3130,-3110,-3088,-3066,-3047,-3031,-3019,-3007,
--2993,-2974,-2952,-2932,-2915,-2901,-2886,-2869,-2852,-2836,-2821,-2804,-2783,-2758,-2733,-2706,-2678,-2651,-2625,-2604,-2586,
--2569,-2544,-2512,-2473,-2434,-2397,-2360,-2321,-2281,-2240,-2202,-2169,-2138,-2105,-2070,-2031,-1992,-1954,-1919,-1885,-1850,
--1813,-1777,-1744,-1714,-1686,-1653,-1615,-1580,-1556,-1548,-1548,-1542,-1521,-1489,-1457,-1434,-1413,-1385,-1342,-1290,-1240,
--1190,-1124,-1016,-856,-662,-474,-329,-248,-222,-224,-227,-215,-189,-160,-139,-126,-114,-95,-70,-47,-32,
--18,9,60,114,131,83,-24,-148,-236,-268,-262,-252,-255,-259,-245,-207,-164,-136,-126,-117,-90,
--46,1,34,49,55,62,77,96,117,139,162,185,204,219,228,237,246,256,269,283,298,
-311,320,325,332,344,363,387,412,435,457,478,503,533,569,610,649,679,698,712,732,763,
-804,847,888,925,963,1000,1033,1055,1068,1079,1097,1134,1193,1271,1362,1452,1530,1591,1637,1673,1704,
-1730,1751,1768,1783,1796,1808,1819,1833,1851,1869,1878,1875,1867,1869,1891,1921,1931,1897,1816,1710,1605,
-1512,1422,1324,1222,1142,1115,1157,1262,1404,1549,1673,1761,1808,1820,1811,1794,1779,1767,1758,1757,1774,
-1816,1880,1950,2005,2034,2038,2028,2012,1992,1960,1915,1859,1804,1758,1720,1683,1640,1589,1534,1479,1428,
-1380,1332,1282,1229,1174,1121,1072,1030,996,964,928,888,846,807,774,747,720,692,666,645,627,
-610,589,567,551,547,555,566,571,562,537,497,447,399,369,371,405,454,494,504,478,423,
-357,294,246,216,208,216,231,242,239,224,200,176,155,137,119,102,87,76,68,60,50,
-41,38,38,39,33,18,-2,-19,-29,-31,-33,-39,-51,-65,-78,-89,-102,-119,-143,-170,-197,
--220,-237,-248,-255,-261,-272,-290,-314,-342,-371,-399,-428,-457,-489,-523,-559,-597,-633,-666,-696,-726,
--758,-793,-828,-859,-880,-894,-907,-922,-942,-962,-981,-995,-1005,-1012,-1018,-1026,-1034,-1044,-1051,-1053,-1052,
--1048,-1047,-1052,-1062,-1077,-1093,-1109,-1125,-1137,-1145,-1149,-1151,-1156,-1164,-1174,-1185,-1195,-1205,-1216,-1227,-1237,
--1244,-1248,-1250,-1251,-1254,-1257,-1262,-1266,-1270,-1274,-1278,-1281,-1282,-1283,-1284,-1287,-1292,-1297,-1298,-1295,-1292,
--1291,-1292,-1295,-1296,-1296,-1295,-1295,-1293,-1289,-1284,-1281,-1281,-1284,-1288,-1290,-1289,-1289,-1288,-1287,-1284,-1279,
--1273,-1266,-1258,-1248,-1237,-1228,-1224,-1225,-1226,-1226,-1223,-1218,-1213,-1209,-1204,-1200,-1198,-1199,-1205,-1214,-1223,
--1232,-1242,-1250,-1257,-1264,-1270,-1276,-1283,-1288,-1291,-1290,-1289,-1289,-1288,-1286,-1283,-1280,-1277,-1275,-1271,-1264,
--1253,-1242,-1233,-1225,-1219,-1213,-1207,-1201,-1196,-1191,-1187,-1181,-1174,-1164,-1153,-1142,-1132,-1123,-1115,-1106,-1099,
--1093,-1088,-1082,-1073,-1063,-1054,-1047,-1044,-1040,-1037,-1034,-1034,-1034,-1034,-1029,-1021,-1013,-1009,-1006,-1003,-997,
--988,-979,-972,-966,-957,-943,-927,-912,-901,-893,-885,-875,-862,-847,-832,-820,-810,-802,-795,-788,-781,
--774,-766,-758,-751,-746,-743,-740,-735,-725,-712,-699,-687,-676,-662,-645,-625,-605,-583,-557,-527,-493,
--462,-436,-416,-399,-383,-366,-350,-336,-322,-307,-290,-273,-260,-249,-238,-224,-207,-189,-175,-164,-155,
--146,-134,-124,-117,-114,-111,-105,-96,-85,-74,-65,-56,-47,-37,-27,-16,-5,6,17,26,33,
-39,45,53,64,80,100,125,151,177,202,225,250,276,303,328,353,380,410,440,468,493,
-518,549,585,622,655,683,709,739,775,812,847,878,910,945,982,1019,1052,1080,1102,1117,1118,
-1099,1059,1012,978,981,1032,1133,1269,1415,1546,1648,1720,1776,1839,1928,2043,2165,2263,2313,2314,2287,
-2259,2253,2269,2295,2319,2340,2360,2375,2372,2339,2270,2178,2083,1996,1918,1840,1762,1690,1635,1594,1560,
-1521,1480,1446,1425,1416,1408,1393,1372,1351,1332,1312,1291,1278,1282,1308,1342,1364,1362,1341,1320,1313,
-1319,1331,1339,1342,1339,1331,1313,1288,1265,1252,1249,1247,1234,1201,1146,1070,975,865,746,628,517,
-416,325,246,183,139,106,76,44,14,-7,-21,-34,-56,-86,-115,-138,-155,-174,-201,-233,-263,
--286,-306,-328,-354,-382,-405,-422,-438,-456,-475,-493,-508,-524,-541,-562,-583,-603,-619,-633,-646,-660,
--674,-688,-701,-716,-731,-744,-753,-755,-754,-752,-753,-757,-759,-756,-747,-734,-720,-707,-691,-671,-647,
--623,-600,-578,-554,-529,-508,-492,-480,-465,-442,-411,-376,-342,-312,-286,-264,-244,-223,-199,-170,-139,
--110,-86,-64,-37,0,46,97,148,198,251,305,358,408,457,510,569,629,683,727,764,799,
-834,871,906,942,981,1024,1067,1107,1143,1183,1229,1279,1324,1359,1387,1415,1449,1487,1524,1559,1593,
-1632,1674,1717,1757,1796,1835,1873,1906,1930,1950,1973,2004,2039,2072,2099,2123,2148,2173,2196,2213,2227,
-2246,2272,2300,2323,2341,2357,2376,2396,2409,2410,2403,2397,2398,2403,2406,2401,2390,2378,2367,2357,2345,
-2333,2326,2326,2332,2340,2343,2340,2333,2330,2334,2345,2353,2346,2322,2290,2265,2257,2264,2270,2261,2236,
-2206,2185,2175,2169,2160,2149,2143,2142,2139,2121,2081,2029,1979,1944,1924,1910,1897,1885,1878,1873,1867,
-1854,1837,1819,1804,1792,1780,1769,1763,1761,1761,1760,1756,1753,1755,1763,1774,1783,1790,1799,1817,1840,
-1860,1870,1874,1880,1895,1918,1937,1946,1946,1947,1956,1971,1986,1996,2004,2017,2038,2065,2094,2126,2164,
-2208,2255,2299,2337,2369,2401,2434,2468,2500,2528,2553,2576,2598,2619,2639,2659,2676,2685,2684,2671,2650,
-2631,2624,2643,2695,2774,2858,2918,2936,2916,2881,2856,2855,2868,2882,2888,2889,2894,2908,2925,2939,2951,
-2960,2969,2973,2967,2954,2940,2934,2938,2948,2956,2960,2964,2970,2978,2985,2987,2988,2998,3023,3065,3116,
-3167,3211,3251,3291,3337,3390,3444,3489,3517,3528,3526,3522,3520,3522,3526,3527,3524,3511,3488,3454,3415,
-3376,3347,3330,3322,3321,3321,3321,3321,3323,3328,3338,3349,3360,3365,3361,3352,3342,3335,3332,3332,3333,
-3335,3340,3345,3351,3358,3373,3401,3439,3481,3516,3540,3558,3580,3607,3636,3661,3681,3701,3729,3767,3808,
-3847,3880,3908,3936,3965,3997,4033,4073,4113,4147,4169,4180,4185,4194,4213,4244,4283,4320,4344,4350,4339,
-4323,4315,4321,4333,4336,4321,4294,4267,4252,4247,4245,4239,4228,4212,4193,4172,4152,4139,4134,4133,4127,
-4110,4090,4075,4069,4062,4042,4006,3965,3934,3919,3910,3893,3860,3816,3770,3730,3696,3666,3639,3617,3597,
-3573,3545,3511,3477,3443,3406,3365,3322,3282,3246,3213,3180,3146,3117,3094,3076,3054,3024,2987,2952,2926,
-2908,2893,2878,2860,2841,2824,2807,2792,2780,2772,2768,2766,2762,2753,2739,2721,2700,2682,2668,2658,2650,
-2643,2636,2629,2624,2620,2617,2613,2610,2607,2603,2595,2579,2557,2532,2509,2486,2461,2434,2403,2371,2339,
-2306,2272,2238,2205,2175,2146,2116,2086,2059,2037,2018,1997,1973,1947,1922,1900,1877,1853,1828,1807,1795,
-1793,1796,1796,1790,1776,1759,1740,1718,1692,1660,1623,1587,1552,1519,1486,1451,1415,1377,1341,1303,1265,
-1225,1188,1156,1129,1104,1075,1039,999,957,918,881,844,806,768,732,696,657,611,560,511,473,
-447,426,400,364,320,276,236,199,162,121,76,29,-19,-71,-124,-175,-221,-261,-300,-344,-395,
--449,-499,-543,-583,-625,-674,-726,-777,-825,-869,-914,-965,-1019,-1071,-1119,-1163,-1205,-1248,-1295,-1344,-1393,
--1442,-1490,-1538,-1582,-1621,-1659,-1699,-1746,-1798,-1849,-1897,-1939,-1978,-2018,-2059,-2101,-2143,-2185,-2226,-2267,-2305,
--2339,-2368,-2396,-2423,-2453,-2484,-2517,-2550,-2581,-2610,-2639,-2669,-2703,-2739,-2775,-2808,-2837,-2866,-2896,-2927,-2955,
--2979,-3000,-3022,-3047,-3073,-3097,-3116,-3131,-3146,-3164,-3182,-3199,-3213,-3227,-3242,-3260,-3278,-3294,-3304,-3311,-3318,
--3328,-3338,-3347,-3353,-3356,-3356,-3354,-3353,-3353,-3356,-3360,-3363,-3361,-3355,-3348,-3345,-3347,-3351,-3353,-3350,-3346,
--3344,-3343,-3340,-3332,-3323,-3316,-3313,-3312,-3307,-3298,-3288,-3279,-3275,-3271,-3265,-3256,-3244,-3233,-3222,-3208,-3192,
--3176,-3161,-3150,-3139,-3125,-3107,-3087,-3066,-3045,-3027,-3013,-3003,-2993,-2979,-2961,-2940,-2920,-2904,-2889,-2873,-2855,
--2838,-2822,-2809,-2793,-2771,-2744,-2715,-2688,-2663,-2640,-2619,-2600,-2580,-2556,-2524,-2485,-2444,-2405,-2372,-2341,-2307,
--2269,-2230,-2193,-2162,-2133,-2102,-2067,-2029,-1991,-1954,-1921,-1890,-1858,-1825,-1790,-1757,-1728,-1699,-1668,-1634,-1601,
--1577,-1565,-1559,-1549,-1531,-1509,-1492,-1482,-1472,-1447,-1403,-1350,-1305,-1267,-1216,-1121,-967,-770,-572,-418,-328,
--293,-282,-268,-239,-202,-170,-150,-141,-132,-116,-97,-83,-75,-62,-28,28,83,96,38,-76,-201,
--287,-316,-310,-303,-308,-312,-296,-258,-217,-194,-187,-179,-151,-105,-58,-30,-21,-19,-12,2,23,
-46,72,100,126,144,150,151,156,167,184,201,215,227,239,249,257,266,278,297,322,350,
-376,400,422,448,479,514,550,584,611,632,649,670,698,734,773,810,844,874,902,927,949,
-968,988,1014,1053,1111,1189,1279,1368,1446,1505,1551,1589,1624,1656,1681,1697,1705,1709,1714,1727,1749,
-1776,1797,1803,1795,1787,1798,1831,1868,1874,1828,1737,1628,1527,1439,1350,1251,1156,1097,1104,1183,1311,
-1456,1589,1691,1754,1777,1763,1729,1692,1668,1662,1668,1684,1714,1765,1834,1910,1971,2005,2011,1998,1978,
-1954,1920,1873,1816,1758,1710,1673,1640,1598,1543,1477,1410,1353,1309,1272,1236,1195,1149,1102,1058,1018,
-978,935,888,839,792,751,718,690,668,650,634,618,595,567,538,515,505,509,520,526,522,
-506,480,447,411,375,341,317,311,328,368,420,465,482,455,387,297,212,157,140,151,170,
-181,177,160,139,116,95,74,56,41,31,23,15,4,-6,-11,-10,-7,-10,-22,-42,-61,
--71,-71,-66,-66,-75,-91,-109,-126,-142,-160,-181,-206,-230,-252,-268,-278,-283,-287,-294,-308,-330,
--357,-388,-418,-446,-472,-499,-529,-564,-604,-644,-679,-708,-733,-759,-791,-827,-862,-890,-911,-927,-943,
--961,-981,-1001,-1017,-1029,-1038,-1043,-1047,-1052,-1058,-1066,-1072,-1075,-1072,-1068,-1066,-1070,-1081,-1098,-1116,-1134,
--1147,-1154,-1158,-1161,-1167,-1175,-1185,-1195,-1204,-1213,-1224,-1236,-1249,-1258,-1264,-1268,-1272,-1277,-1284,-1290,-1294,
--1297,-1298,-1300,-1300,-1300,-1299,-1298,-1299,-1301,-1303,-1303,-1301,-1300,-1301,-1304,-1307,-1308,-1307,-1307,-1306,-1306,
--1303,-1298,-1294,-1292,-1292,-1294,-1296,-1298,-1300,-1301,-1299,-1294,-1287,-1280,-1275,-1270,-1263,-1254,-1245,-1241,-1238,
--1236,-1231,-1224,-1217,-1212,-1208,-1203,-1199,-1196,-1197,-1203,-1211,-1220,-1227,-1233,-1240,-1248,-1258,-1269,-1279,-1285,
--1287,-1287,-1286,-1285,-1286,-1286,-1285,-1284,-1284,-1283,-1280,-1273,-1261,-1248,-1236,-1229,-1223,-1217,-1210,-1201,-1193,
--1187,-1182,-1178,-1173,-1166,-1157,-1146,-1134,-1125,-1118,-1112,-1105,-1098,-1091,-1085,-1079,-1072,-1063,-1052,-1043,-1036,
--1034,-1034,-1035,-1036,-1035,-1030,-1023,-1015,-1008,-1004,-1003,-1000,-995,-987,-978,-969,-961,-950,-938,-923,-908,
--895,-884,-875,-866,-855,-843,-831,-819,-809,-800,-792,-784,-778,-772,-765,-758,-752,-748,-746,-744,-738,
--726,-713,-703,-697,-691,-680,-659,-632,-603,-576,-548,-517,-484,-453,-428,-411,-396,-382,-366,-351,-340,
--328,-314,-296,-277,-262,-252,-242,-228,-210,-191,-174,-161,-150,-138,-126,-116,-110,-105,-99,-88,-75,
--62,-52,-44,-34,-23,-12,-3,5,14,26,38,48,55,60,66,75,88,105,126,150,174,
-194,212,230,252,279,308,336,362,389,419,449,477,503,530,562,598,634,668,699,731,767,
-804,840,871,902,935,972,1008,1040,1068,1094,1117,1130,1127,1103,1066,1031,1012,1026,1082,1186,1329,
-1486,1627,1727,1784,1818,1862,1941,2053,2171,2261,2299,2289,2255,2228,2229,2256,2296,2336,2373,2408,2435,
-2441,2408,2333,2231,2122,2021,1926,1830,1735,1655,1601,1572,1551,1519,1475,1433,1407,1397,1392,1380,1360,
-1339,1321,1304,1288,1276,1281,1305,1338,1361,1361,1342,1319,1305,1305,1311,1318,1324,1326,1316,1288,1248,
-1210,1190,1191,1197,1186,1144,1071,975,867,754,639,529,427,335,254,188,137,102,75,50,23,
--2,-23,-37,-52,-73,-98,-121,-139,-153,-174,-203,-236,-263,-283,-301,-323,-351,-378,-399,-414,-426,
--442,-462,-481,-497,-513,-531,-554,-577,-598,-614,-629,-645,-663,-679,-694,-707,-722,-736,-748,-756,-758,
--757,-758,-762,-766,-767,-762,-752,-740,-727,-713,-696,-675,-652,-628,-604,-579,-553,-528,-507,-492,-481,
--467,-446,-417,-384,-351,-321,-294,-271,-253,-236,-215,-187,-154,-120,-90,-62,-31,6,51,99,148,
-196,248,301,354,405,455,508,566,624,677,721,757,790,825,861,898,936,978,1022,1063,1100,
-1135,1174,1220,1267,1309,1342,1371,1403,1442,1486,1526,1564,1600,1640,1683,1725,1762,1796,1833,1871,1907,
-1937,1964,1993,2026,2060,2089,2114,2136,2161,2185,2205,2218,2233,2255,2287,2322,2350,2369,2385,2402,2419,
-2428,2425,2414,2406,2406,2412,2415,2410,2399,2390,2385,2381,2373,2361,2352,2351,2357,2364,2365,2357,2346,
-2340,2343,2352,2357,2349,2326,2299,2279,2275,2280,2281,2272,2253,2234,2220,2205,2185,2162,2146,2148,2162,
-2170,2152,2106,2047,1996,1965,1949,1938,1927,1917,1913,1911,1905,1890,1868,1845,1826,1812,1800,1788,1778,
-1769,1762,1756,1734,1732,1744,1763,1780,1786,1783,1785,1805,1840,1873,1889,1888,1884,1891,1913,1939,1955,
-1959,1960,1965,1978,1994,2008,2023,2042,2068,2097,2128,2161,2198,2242,2287,2330,2367,2400,2434,2468,2500,
-2528,2551,2573,2595,2619,2644,2668,2688,2700,2701,2689,2671,2655,2652,2670,2713,2777,2848,2906,2934,2926,
-2895,2864,2851,2861,2880,2893,2895,2893,2897,2911,2929,2944,2953,2959,2963,2964,2959,2948,2938,2936,2944,
-2956,2968,2975,2980,2985,2991,2996,3000,3008,3025,3055,3095,3139,3181,3219,3254,3294,3344,3403,3463,3511,
-3538,3544,3539,3533,3533,3539,3545,3544,3534,3515,3487,3451,3410,3370,3338,3319,3314,3319,3329,3336,3337,
-3332,3324,3320,3322,3329,3332,3328,3316,3302,3293,3293,3302,3315,3331,3350,3370,3390,3409,3432,3464,3504,
-3545,3577,3598,3613,3634,3664,3700,3733,3758,3781,3809,3844,3881,3913,3936,3957,3981,4012,4048,4086,4123,
-4161,4195,4217,4222,4212,4203,4213,4249,4301,4345,4361,4348,4324,4313,4324,4347,4359,4345,4311,4276,4257,
-4255,4259,4257,4246,4232,4220,4206,4189,4169,4153,4147,4145,4138,4119,4097,4083,4079,4077,4062,4031,3993,
-3965,3954,3950,3938,3908,3861,3809,3762,3722,3692,3669,3651,3633,3611,3583,3550,3516,3482,3444,3403,3360,
-3320,3285,3254,3225,3198,3173,3152,3129,3099,3062,3022,2988,2965,2949,2935,2918,2897,2876,2856,2837,2821,
-2809,2802,2799,2796,2791,2781,2767,2750,2732,2716,2703,2693,2686,2680,2673,2666,2660,2655,2650,2645,2639,
-2633,2627,2618,2604,2587,2567,2547,2526,2502,2474,2445,2414,2381,2346,2309,2275,2245,2219,2194,2166,2135,
-2107,2084,2065,2045,2020,1990,1959,1931,1907,1885,1866,1852,1846,1847,1848,1843,1830,1810,1790,1772,1753,
-1730,1699,1664,1628,1595,1565,1535,1502,1465,1426,1387,1350,1316,1283,1252,1222,1194,1166,1134,1097,1057,
-1015,974,936,900,863,825,787,747,703,657,613,576,549,529,507,478,437,391,345,303,263,
-222,177,131,85,39,-9,-58,-106,-150,-191,-233,-280,-331,-384,-431,-473,-514,-559,-609,-662,-714,
--762,-807,-853,-902,-953,-1003,-1050,-1096,-1142,-1190,-1237,-1285,-1331,-1378,-1426,-1472,-1515,-1555,-1595,-1638,-1686,
--1738,-1790,-1836,-1877,-1915,-1954,-1995,-2037,-2079,-2121,-2164,-2206,-2246,-2283,-2315,-2342,-2368,-2396,-2428,-2462,-2496,
--2526,-2553,-2581,-2611,-2645,-2680,-2716,-2750,-2783,-2816,-2848,-2877,-2901,-2923,-2946,-2973,-3003,-3033,-3058,-3076,-3091,
--3106,-3124,-3144,-3163,-3179,-3193,-3208,-3225,-3242,-3257,-3267,-3274,-3282,-3293,-3305,-3314,-3318,-3317,-3315,-3316,-3320,
--3325,-3327,-3327,-3324,-3321,-3317,-3314,-3312,-3312,-3313,-3312,-3311,-3310,-3310,-3310,-3308,-3302,-3295,-3289,-3285,-3282,
--3278,-3271,-3263,-3256,-3250,-3245,-3237,-3228,-3219,-3210,-3200,-3188,-3173,-3157,-3143,-3131,-3119,-3105,-3087,-3067,-3046,
--3026,-3008,-2995,-2985,-2976,-2962,-2944,-2923,-2904,-2888,-2873,-2857,-2839,-2822,-2808,-2796,-2780,-2758,-2730,-2700,-2673,
--2651,-2631,-2611,-2589,-2564,-2534,-2498,-2458,-2419,-2384,-2355,-2328,-2298,-2265,-2230,-2197,-2166,-2135,-2100,-2063,-2025,
--1989,-1957,-1927,-1898,-1869,-1837,-1804,-1771,-1739,-1709,-1678,-1647,-1619,-1598,-1585,-1577,-1568,-1552,-1534,-1521,-1516,
--1511,-1493,-1455,-1405,-1358,-1320,-1276,-1200,-1072,-900,-715,-556,-444,-375,-329,-287,-241,-197,-165,-150,-146,
--141,-130,-112,-98,-89,-76,-49,-6,28,22,-45,-160,-279,-359,-387,-381,-373,-373,-374,-358,-324,
--288,-265,-254,-239,-207,-162,-121,-97,-90,-89,-83,-70,-51,-27,2,35,62,76,77,76,83,
-103,126,144,154,160,169,181,194,205,217,233,256,285,314,341,367,395,424,455,484,512,
-537,559,581,605,633,666,704,740,773,799,823,846,871,896,922,951,990,1047,1125,1215,1305,
-1381,1436,1477,1512,1547,1581,1609,1625,1629,1628,1631,1646,1672,1699,1714,1713,1704,1709,1744,1801,1847,
-1844,1779,1672,1560,1466,1389,1311,1229,1164,1152,1211,1328,1464,1582,1661,1705,1720,1712,1685,1645,1609,
-1591,1594,1614,1645,1685,1738,1804,1873,1928,1956,1956,1940,1918,1895,1866,1823,1769,1712,1661,1623,1590,
-1551,1497,1432,1366,1312,1273,1243,1211,1173,1131,1091,1054,1015,966,905,840,782,737,704,677,653,
-633,618,606,588,560,521,484,462,459,470,481,481,464,437,408,384,367,347,319,282,247,
-236,267,337,423,487,497,448,357,258,179,131,112,108,111,114,112,104,87,63,35,10,
--7,-17,-24,-31,-40,-51,-59,-61,-59,-58,-66,-81,-97,-107,-108,-102,-98,-104,-120,-142,-165,
--187,-208,-229,-250,-269,-286,-299,-310,-316,-321,-327,-337,-356,-383,-416,-448,-476,-498,-518,-541,-573,
--613,-656,-695,-724,-746,-767,-793,-826,-863,-896,-923,-944,-961,-980,-999,-1018,-1035,-1050,-1061,-1068,-1071,
--1074,-1078,-1084,-1090,-1094,-1092,-1088,-1083,-1084,-1091,-1106,-1125,-1142,-1156,-1164,-1168,-1173,-1181,-1192,-1203,-1213,
--1220,-1228,-1237,-1248,-1259,-1270,-1277,-1283,-1289,-1297,-1306,-1314,-1319,-1321,-1322,-1321,-1321,-1320,-1319,-1319,-1317,
--1316,-1314,-1311,-1310,-1311,-1315,-1321,-1324,-1326,-1326,-1326,-1326,-1325,-1322,-1316,-1310,-1305,-1303,-1302,-1302,-1304,
--1306,-1307,-1303,-1295,-1286,-1280,-1276,-1274,-1271,-1265,-1260,-1256,-1253,-1247,-1238,-1227,-1218,-1213,-1210,-1208,-1206,
--1203,-1202,-1204,-1208,-1212,-1215,-1218,-1224,-1233,-1246,-1259,-1271,-1278,-1281,-1281,-1280,-1280,-1282,-1282,-1281,-1280,
--1279,-1278,-1273,-1265,-1253,-1240,-1231,-1224,-1218,-1211,-1202,-1193,-1185,-1179,-1174,-1169,-1164,-1158,-1149,-1137,-1126,
--1117,-1112,-1107,-1101,-1093,-1084,-1076,-1071,-1065,-1057,-1047,-1037,-1030,-1029,-1032,-1035,-1034,-1031,-1025,-1018,-1011,
--1006,-1001,-997,-993,-989,-983,-975,-966,-955,-944,-934,-922,-909,-895,-882,-871,-861,-853,-845,-836,-826,
--816,-805,-794,-785,-779,-775,-772,-768,-762,-758,-756,-754,-748,-737,-725,-715,-708,-698,-677,-643,-602,
--565,-536,-514,-491,-465,-439,-417,-403,-391,-378,-362,-347,-336,-325,-312,-296,-278,-263,-253,-243,-229,
--212,-194,-180,-169,-157,-142,-128,-117,-111,-106,-98,-86,-71,-59,-50,-40,-28,-15,-4,3,8,
-16,28,42,55,65,74,84,95,110,126,146,169,191,211,228,247,270,298,327,355,382,
-411,442,475,506,535,564,597,632,667,701,734,771,810,847,878,906,937,972,1008,1038,1062,
-1083,1107,1131,1143,1135,1109,1077,1056,1055,1083,1144,1246,1386,1543,1685,1781,1826,1846,1879,1951,2056,
-2165,2244,2274,2261,2232,2212,2216,2242,2277,2313,2350,2392,2432,2453,2435,2371,2275,2170,2070,1976,1877,
-1776,1685,1622,1586,1560,1525,1474,1424,1391,1380,1379,1371,1353,1330,1309,1292,1275,1264,1266,1288,1322,
-1350,1358,1348,1329,1312,1300,1292,1288,1289,1290,1281,1251,1205,1160,1135,1131,1131,1109,1050,960,852,
-741,634,532,435,346,268,201,148,107,77,54,32,8,-15,-35,-51,-67,-87,-109,-130,-145,
--161,-182,-210,-240,-265,-282,-297,-317,-341,-365,-383,-395,-407,-424,-444,-463,-478,-492,-511,-535,-561,
--583,-600,-617,-635,-655,-675,-694,-711,-726,-741,-751,-758,-761,-764,-770,-776,-779,-777,-770,-759,-747,
--734,-720,-702,-681,-658,-635,-611,-587,-561,-536,-514,-497,-481,-464,-443,-418,-390,-361,-332,-303,-278,
--259,-243,-224,-198,-163,-125,-88,-54,-20,18,61,107,155,204,255,308,361,411,461,512,566,
-621,671,715,754,790,826,863,901,941,983,1025,1065,1101,1137,1175,1218,1261,1299,1333,1366,1406,
-1453,1501,1544,1582,1618,1657,1697,1735,1769,1801,1836,1876,1915,1951,1984,2017,2050,2082,2109,2131,2151,
-2173,2194,2210,2222,2236,2261,2297,2336,2368,2390,2405,2421,2434,2440,2435,2424,2416,2416,2422,2426,2423,
-2416,2410,2409,2409,2404,2394,2385,2380,2382,2385,2384,2375,2363,2353,2350,2352,2351,2341,2321,2300,2286,
-2282,2283,2282,2276,2266,2258,2250,2238,2218,2199,2193,2203,2216,2210,2172,2110,2047,2005,1987,1982,1976,
-1964,1953,1947,1941,1930,1909,1884,1861,1845,1831,1816,1798,1779,1762,1746,1734,1703,1702,1723,1762,1801,
-1823,1824,1820,1829,1856,1889,1907,1907,1901,1905,1923,1947,1964,1972,1977,1988,2004,2023,2040,2059,2082,
-2111,2141,2171,2200,2234,2274,2317,2357,2394,2428,2463,2498,2527,2550,2569,2590,2615,2642,2667,2686,2696,
-2699,2696,2690,2685,2689,2708,2744,2792,2844,2888,2914,2915,2896,2868,2848,2846,2859,2877,2890,2893,2895,
-2902,2915,2930,2940,2942,2941,2939,2937,2936,2935,2937,2944,2955,2967,2977,2985,2990,2996,3003,3011,3022,
-3037,3060,3088,3120,3153,3187,3222,3260,3306,3361,3422,3483,3531,3558,3562,3552,3542,3538,3539,3538,3530,
-3513,3490,3463,3432,3396,3358,3326,3306,3303,3311,3325,3334,3334,3326,3316,3311,3313,3318,3321,3314,3298,
-3281,3271,3271,3283,3304,3331,3364,3399,3433,3463,3492,3524,3561,3599,3630,3652,3668,3691,3725,3765,3804,
-3834,3858,3885,3916,3947,3972,3988,4005,4031,4066,4103,4136,4166,4197,4232,4260,4268,4253,4233,4233,4267,
-4320,4361,4365,4336,4304,4301,4332,4371,4383,4356,4305,4263,4250,4257,4265,4259,4241,4225,4217,4212,4202,
-4185,4169,4160,4155,4143,4122,4099,4087,4090,4096,4088,4061,4027,4003,3996,3998,3991,3963,3914,3854,3798,
-3752,3719,3695,3678,3662,3641,3614,3582,3548,3512,3475,3435,3395,3358,3326,3297,3272,3249,3227,3204,3176,
-3141,3103,3066,3038,3018,3001,2983,2960,2936,2912,2890,2869,2851,2838,2832,2829,2826,2820,2809,2795,2779,
-2763,2748,2735,2726,2720,2715,2710,2705,2701,2696,2690,2682,2673,2664,2654,2644,2632,2617,2600,2581,2561,
-2539,2514,2487,2458,2425,2389,2351,2315,2284,2259,2236,2211,2183,2157,2134,2114,2092,2063,2029,1994,1964,
-1941,1926,1915,1909,1907,1905,1899,1887,1869,1848,1828,1811,1793,1770,1740,1707,1673,1642,1613,1583,1549,
-1511,1471,1433,1400,1371,1345,1318,1288,1256,1223,1189,1153,1113,1071,1029,990,954,918,881,839,795,
-751,710,676,650,630,608,580,543,499,454,412,372,330,284,234,185,139,95,50,5,-39,
--82,-124,-169,-217,-267,-317,-363,-405,-448,-494,-545,-598,-649,-697,-744,-791,-840,-888,-936,-985,-1034,
--1084,-1133,-1182,-1230,-1276,-1321,-1366,-1409,-1451,-1492,-1536,-1583,-1633,-1684,-1734,-1779,-1819,-1855,-1892,-1931,-1974,
--2018,-2061,-2103,-2145,-2185,-2222,-2254,-2281,-2307,-2336,-2371,-2409,-2445,-2475,-2502,-2528,-2558,-2592,-2627,-2661,-2696,
--2732,-2767,-2799,-2824,-2844,-2864,-2890,-2923,-2961,-2995,-3021,-3039,-3051,-3065,-3082,-3104,-3125,-3144,-3160,-3175,-3190,
--3206,-3220,-3230,-3238,-3247,-3258,-3269,-3276,-3276,-3272,-3271,-3276,-3286,-3295,-3296,-3291,-3283,-3279,-3279,-3280,-3279,
--3276,-3274,-3273,-3275,-3277,-3278,-3276,-3272,-3265,-3259,-3254,-3252,-3250,-3248,-3244,-3239,-3234,-3229,-3222,-3214,-3204,
--3195,-3186,-3177,-3165,-3152,-3137,-3123,-3111,-3099,-3085,-3069,-3050,-3029,-3009,-2991,-2976,-2964,-2953,-2938,-2921,-2902,
--2886,-2873,-2861,-2847,-2830,-2813,-2798,-2784,-2766,-2743,-2715,-2687,-2663,-2642,-2622,-2599,-2572,-2541,-2508,-2473,-2438,
--2404,-2373,-2345,-2318,-2289,-2259,-2230,-2202,-2174,-2141,-2103,-2063,-2027,-1996,-1968,-1940,-1910,-1878,-1845,-1812,-1779,
--1747,-1716,-1687,-1661,-1637,-1619,-1607,-1600,-1592,-1577,-1557,-1540,-1530,-1527,-1518,-1494,-1452,-1403,-1357,-1312,-1254,
--1165,-1038,-885,-730,-590,-474,-380,-300,-233,-180,-148,-136,-137,-141,-137,-123,-103,-83,-64,-43,-25,
--24,-59,-140,-253,-363,-438,-466,-460,-447,-440,-436,-422,-397,-368,-342,-321,-295,-259,-218,-184,-165,
--157,-154,-148,-136,-120,-97,-66,-33,-6,5,7,12,29,56,82,96,97,97,104,120,138,
-151,161,173,194,223,254,284,311,338,364,391,416,441,465,489,512,535,561,594,633,673,
-710,741,766,792,819,847,874,902,939,995,1073,1164,1254,1326,1377,1411,1438,1467,1498,1526,1543,
-1551,1554,1563,1583,1609,1631,1635,1624,1616,1638,1698,1778,1833,1825,1747,1628,1511,1420,1349,1283,1223,
-1195,1228,1330,1468,1592,1665,1684,1670,1645,1620,1593,1563,1536,1526,1540,1573,1619,1672,1728,1786,1838,
-1874,1889,1884,1867,1848,1828,1803,1766,1716,1659,1606,1563,1530,1496,1453,1401,1348,1303,1268,1237,1202,
-1160,1118,1084,1055,1017,957,878,796,730,691,669,652,630,605,583,566,545,512,471,433,413,
-414,428,438,432,407,372,340,319,308,299,280,245,204,177,186,234,304,366,396,391,358,
-310,254,191,127,74,42,37,48,57,53,32,3,-25,-46,-59,-67,-75,-84,-94,-105,-112,
--114,-114,-117,-125,-137,-147,-149,-145,-142,-146,-160,-182,-206,-231,-255,-277,-296,-313,-327,-339,-350,
--359,-366,-370,-377,-392,-416,-448,-482,-510,-529,-543,-560,-587,-626,-670,-710,-741,-762,-780,-801,-830,
--865,-900,-930,-955,-976,-996,-1016,-1035,-1053,-1068,-1080,-1088,-1094,-1096,-1099,-1101,-1104,-1106,-1106,-1104,-1101,
--1102,-1107,-1118,-1133,-1149,-1163,-1173,-1182,-1191,-1203,-1216,-1228,-1237,-1242,-1246,-1251,-1259,-1269,-1279,-1288,-1296,
--1303,-1310,-1317,-1325,-1332,-1337,-1340,-1341,-1342,-1343,-1344,-1344,-1342,-1336,-1329,-1323,-1321,-1323,-1329,-1336,-1341,
--1345,-1348,-1349,-1349,-1345,-1338,-1329,-1322,-1318,-1316,-1314,-1312,-1311,-1311,-1310,-1306,-1298,-1289,-1281,-1276,-1272,
--1269,-1266,-1263,-1262,-1260,-1254,-1245,-1233,-1223,-1217,-1216,-1216,-1215,-1212,-1209,-1206,-1205,-1204,-1205,-1207,-1213,
--1223,-1235,-1248,-1260,-1267,-1271,-1271,-1272,-1274,-1276,-1278,-1278,-1275,-1271,-1265,-1258,-1250,-1240,-1231,-1223,-1217,
--1209,-1201,-1193,-1185,-1178,-1172,-1166,-1161,-1156,-1149,-1141,-1131,-1121,-1113,-1107,-1101,-1094,-1084,-1074,-1067,-1061,
--1057,-1049,-1040,-1031,-1027,-1028,-1031,-1031,-1028,-1023,-1018,-1015,-1012,-1007,-1000,-992,-985,-980,-976,-970,-960,
--948,-937,-927,-918,-908,-898,-886,-875,-867,-860,-854,-847,-839,-827,-814,-800,-788,-783,-782,-782,-779,
--774,-769,-766,-765,-762,-754,-743,-732,-719,-698,-663,-614,-562,-520,-495,-482,-470,-453,-433,-416,-404,
--395,-383,-367,-351,-338,-326,-314,-298,-282,-269,-259,-248,-234,-218,-203,-194,-187,-177,-163,-147,-135,
--128,-124,-117,-106,-94,-82,-72,-60,-44,-28,-17,-11,-7,0,12,27,42,57,72,88,104,
-120,136,155,179,204,227,250,274,301,330,358,384,410,440,474,509,541,571,601,636,672,
-706,738,769,805,842,875,903,930,961,997,1031,1056,1072,1089,1114,1139,1152,1140,1112,1084,1076,
-1092,1131,1194,1290,1421,1571,1706,1796,1835,1850,1880,1949,2047,2145,2212,2237,2230,2214,2206,2214,2233,
-2254,2276,2304,2346,2398,2440,2448,2408,2329,2237,2149,2068,1979,1879,1775,1688,1625,1577,1528,1470,1414,
-1377,1364,1363,1358,1340,1315,1290,1269,1252,1242,1246,1269,1304,1335,1350,1346,1328,1306,1283,1262,1247,
-1241,1243,1238,1218,1181,1141,1114,1098,1077,1028,944,835,720,613,516,426,344,271,210,162,123,
-91,64,41,19,-3,-26,-46,-63,-79,-98,-119,-139,-156,-172,-192,-217,-244,-267,-283,-298,-313,
--331,-348,-361,-373,-387,-405,-425,-443,-457,-471,-490,-515,-541,-563,-582,-599,-617,-639,-663,-686,-708,
--728,-744,-755,-762,-766,-771,-778,-784,-786,-782,-774,-764,-754,-743,-728,-710,-688,-665,-641,-618,-594,
--569,-544,-521,-499,-477,-456,-433,-411,-388,-363,-335,-305,-277,-253,-233,-212,-184,-150,-111,-74,-41,
--9,26,68,114,163,213,264,315,367,417,465,515,566,618,668,714,756,796,834,873,912,
-952,993,1035,1075,1113,1150,1188,1228,1266,1302,1336,1374,1419,1469,1517,1561,1599,1635,1674,1713,1750,
-1783,1816,1853,1892,1932,1968,2001,2033,2066,2097,2123,2143,2162,2182,2201,2217,2230,2246,2272,2308,2347,
-2381,2406,2424,2439,2450,2454,2450,2441,2434,2434,2438,2443,2444,2443,2441,2440,2438,2433,2425,2416,2409,
-2405,2402,2397,2389,2378,2368,2361,2357,2352,2344,2330,2315,2304,2299,2298,2297,2293,2288,2282,2273,2257,
-2237,2222,2220,2228,2229,2205,2153,2091,2043,2021,2019,2020,2012,1998,1985,1977,1968,1950,1924,1896,1873,
-1854,1831,1803,1775,1750,1732,1715,1703,1710,1713,1738,1794,1864,1918,1939,1931,1916,1910,1915,1920,1920,
-1920,1928,1945,1965,1980,1990,2002,2021,2045,2066,2083,2100,2123,2152,2183,2211,2237,2268,2305,2345,2381,
-2414,2445,2479,2513,2542,2564,2583,2606,2634,2661,2681,2688,2686,2682,2684,2694,2712,2737,2770,2808,2845,
-2874,2892,2897,2893,2882,2870,2863,2862,2867,2875,2882,2889,2897,2908,2921,2930,2933,2930,2924,2919,2919,
-2924,2933,2944,2956,2967,2977,2985,2992,3001,3010,3019,3031,3046,3066,3090,3116,3142,3170,3201,3238,3280,
-3328,3383,3443,3504,3552,3578,3580,3566,3549,3537,3529,3521,3506,3487,3466,3446,3422,3391,3356,3323,3301,
-3294,3299,3307,3313,3313,3311,3311,3315,3322,3328,3329,3320,3304,3289,3281,3284,3297,3320,3352,3390,3434,
-3476,3512,3543,3575,3610,3648,3683,3710,3734,3761,3798,3839,3878,3907,3931,3955,3983,4009,4028,4042,4059,
-4089,4127,4163,4188,4206,4229,4262,4296,4310,4297,4271,4263,4290,4339,4376,4373,4336,4301,4303,4342,4386,
-4397,4362,4305,4263,4254,4266,4273,4261,4237,4218,4213,4215,4213,4203,4191,4182,4173,4157,4133,4110,4102,
-4109,4117,4110,4082,4047,4023,4018,4025,4022,3998,3951,3892,3836,3788,3753,3727,3707,3690,3670,3644,3613,
-3579,3542,3506,3469,3434,3401,3372,3345,3322,3301,3279,3254,3223,3187,3151,3120,3096,3074,3051,3025,2997,
-2972,2948,2925,2902,2882,2867,2860,2859,2856,2849,2837,2823,2808,2794,2780,2767,2758,2752,2748,2745,2743,
-2740,2735,2729,2720,2709,2698,2687,2677,2665,2650,2632,2614,2595,2574,2552,2526,2498,2467,2432,2395,2358,
-2325,2298,2274,2250,2226,2202,2180,2158,2132,2101,2067,2034,2007,1989,1979,1975,1973,1970,1962,1949,1930,
-1909,1888,1869,1851,1830,1805,1777,1747,1717,1688,1659,1627,1593,1555,1518,1483,1454,1429,1406,1380,1349,
-1314,1278,1242,1206,1167,1126,1084,1044,1008,972,932,888,842,800,767,743,725,706,679,642,598,
-553,511,472,434,392,343,292,242,195,152,110,66,22,-21,-66,-112,-160,-209,-256,-301,-345,
--389,-436,-485,-534,-583,-632,-681,-729,-778,-825,-874,-923,-974,-1023,-1072,-1119,-1168,-1216,-1263,-1307,-1348,
--1389,-1433,-1479,-1528,-1577,-1625,-1672,-1716,-1755,-1792,-1828,-1868,-1912,-1960,-2006,-2049,-2088,-2124,-2158,-2188,-2215,
--2243,-2275,-2313,-2353,-2390,-2420,-2446,-2472,-2503,-2538,-2575,-2612,-2650,-2688,-2723,-2752,-2773,-2790,-2809,-2837,-2875,
--2915,-2951,-2978,-2995,-3007,-3020,-3037,-3059,-3082,-3103,-3121,-3136,-3152,-3167,-3182,-3194,-3203,-3212,-3223,-3234,-3240,
--3239,-3234,-3233,-3240,-3254,-3264,-3265,-3258,-3249,-3245,-3247,-3249,-3247,-3240,-3234,-3234,-3239,-3244,-3245,-3240,-3231,
--3223,-3217,-3215,-3214,-3215,-3215,-3214,-3211,-3206,-3201,-3195,-3189,-3181,-3171,-3160,-3148,-3136,-3123,-3110,-3097,-3085,
--3073,-3060,-3046,-3030,-3012,-2992,-2974,-2958,-2945,-2931,-2916,-2899,-2883,-2870,-2861,-2852,-2840,-2823,-2805,-2787,-2769,
--2748,-2724,-2697,-2673,-2651,-2631,-2609,-2581,-2550,-2517,-2484,-2452,-2421,-2392,-2364,-2338,-2310,-2281,-2253,-2227,-2203,
--2176,-2143,-2105,-2067,-2033,-2006,-1979,-1949,-1915,-1879,-1846,-1814,-1783,-1753,-1726,-1701,-1680,-1659,-1641,-1626,-1617,
--1608,-1594,-1573,-1548,-1532,-1528,-1529,-1522,-1495,-1449,-1395,-1345,-1299,-1243,-1163,-1049,-907,-751,-596,-457,-341,
--250,-184,-141,-120,-117,-124,-131,-128,-110,-82,-54,-33,-32,-57,-117,-211,-322,-427,-499,-530,-529,
--516,-504,-497,-488,-471,-446,-416,-383,-347,-310,-276,-251,-234,-224,-216,-206,-196,-182,-161,-132,-101,
--77,-64,-57,-44,-20,9,31,39,37,37,48,68,88,100,107,118,137,165,195,222,247,
-271,295,320,346,371,398,424,448,470,494,524,563,605,645,679,709,739,771,802,830,857,
-890,941,1012,1097,1182,1252,1302,1335,1361,1387,1415,1441,1461,1474,1484,1499,1523,1551,1569,1568,1554,
-1548,1576,1644,1729,1784,1776,1699,1584,1471,1379,1307,1245,1198,1191,1247,1357,1483,1576,1609,1589,1548,
-1512,1491,1477,1463,1453,1457,1484,1533,1597,1662,1720,1766,1797,1813,1816,1810,1797,1781,1762,1736,1701,
-1654,1600,1547,1503,1471,1445,1417,1381,1342,1304,1271,1236,1195,1149,1106,1075,1048,1009,944,857,768,
-702,668,652,636,609,575,545,522,499,468,431,396,377,376,382,384,370,343,309,279,259,
-249,244,232,208,175,144,127,128,144,166,194,233,280,315,313,259,164,62,-8,-31,-20,
--2,1,-11,-33,-55,-72,-87,-101,-115,-126,-136,-145,-155,-162,-166,-170,-178,-189,-199,-203,-201,
--198,-201,-213,-232,-255,-278,-301,-322,-342,-358,-371,-383,-395,-407,-416,-422,-427,-437,-456,-485,-515,
--541,-559,-572,-587,-611,-645,-686,-725,-755,-776,-794,-813,-839,-871,-903,-934,-961,-985,-1008,-1031,-1052,
--1070,-1085,-1096,-1106,-1113,-1117,-1118,-1117,-1114,-1113,-1114,-1117,-1119,-1122,-1126,-1132,-1142,-1155,-1170,-1185,-1198,
--1213,-1228,-1244,-1257,-1265,-1267,-1267,-1267,-1271,-1279,-1289,-1300,-1309,-1315,-1319,-1323,-1328,-1334,-1342,-1349,-1355,
--1359,-1362,-1364,-1364,-1360,-1353,-1343,-1335,-1331,-1332,-1336,-1342,-1348,-1355,-1362,-1366,-1365,-1359,-1348,-1338,-1332,
--1330,-1331,-1330,-1326,-1322,-1318,-1315,-1311,-1305,-1297,-1288,-1280,-1273,-1266,-1262,-1259,-1259,-1259,-1255,-1248,-1238,
--1229,-1224,-1221,-1219,-1217,-1214,-1210,-1206,-1203,-1201,-1202,-1207,-1214,-1224,-1235,-1245,-1253,-1259,-1262,-1263,-1263,
--1266,-1269,-1273,-1273,-1270,-1262,-1252,-1242,-1233,-1226,-1220,-1215,-1209,-1202,-1194,-1187,-1180,-1173,-1165,-1158,-1151,
--1145,-1140,-1134,-1125,-1117,-1109,-1102,-1095,-1087,-1077,-1069,-1062,-1057,-1051,-1042,-1033,-1027,-1025,-1026,-1028,-1026,
--1020,-1015,-1013,-1014,-1013,-1009,-1000,-989,-981,-975,-971,-965,-955,-943,-931,-921,-914,-906,-899,-892,-885,
--878,-872,-865,-857,-848,-837,-822,-806,-794,-788,-788,-789,-786,-778,-770,-765,-765,-765,-763,-757,-749,
--736,-712,-674,-623,-571,-531,-507,-496,-486,-470,-451,-435,-424,-416,-405,-391,-374,-360,-347,-332,-316,
--300,-288,-277,-266,-249,-231,-216,-207,-203,-196,-184,-169,-157,-150,-145,-138,-129,-118,-108,-97,-82,
--65,-48,-36,-28,-22,-13,0,15,32,50,71,92,112,129,146,166,192,221,249,276,303,
-333,362,390,415,441,471,505,539,568,595,626,662,700,734,762,788,818,851,881,908,933,
-965,1001,1033,1056,1071,1089,1117,1145,1156,1140,1108,1083,1084,1111,1157,1220,1307,1426,1564,1688,1769,
-1806,1824,1859,1929,2023,2110,2168,2193,2197,2197,2203,2216,2231,2244,2256,2277,2318,2378,2437,2467,2448,
-2385,2302,2222,2150,2072,1975,1862,1751,1660,1588,1527,1466,1409,1369,1350,1345,1338,1321,1296,1270,1248,
-1232,1224,1231,1254,1288,1318,1331,1325,1305,1278,1250,1224,1206,1199,1201,1203,1195,1175,1149,1122,1091,
-1041,960,848,723,603,500,411,332,263,206,163,132,107,81,55,31,7,-14,-36,-56,-74,
--90,-108,-129,-149,-167,-183,-200,-222,-247,-270,-288,-301,-313,-324,-335,-345,-357,-371,-388,-405,-421,
--435,-450,-470,-494,-519,-542,-562,-581,-602,-625,-649,-674,-699,-722,-741,-755,-763,-768,-772,-777,-781,
--781,-778,-772,-764,-755,-745,-732,-715,-695,-672,-648,-622,-596,-570,-545,-520,-495,-471,-447,-425,-403,
--382,-358,-330,-301,-271,-242,-215,-187,-155,-120,-84,-52,-23,4,36,77,124,174,224,273,321,
-370,418,466,514,564,616,666,714,758,798,837,878,920,963,1007,1050,1091,1131,1169,1208,1245,
-1282,1317,1353,1393,1436,1481,1526,1567,1607,1646,1687,1726,1764,1799,1835,1873,1910,1945,1977,2006,2036,
-2069,2100,2128,2151,2172,2192,2212,2230,2248,2268,2293,2325,2360,2393,2421,2443,2459,2469,2473,2470,2464,
-2457,2454,2455,2458,2464,2468,2470,2468,2464,2458,2451,2445,2437,2427,2418,2409,2401,2392,2382,2374,2368,
-2365,2362,2354,2344,2335,2330,2328,2328,2326,2321,2312,2297,2274,2247,2226,2213,2206,2191,2159,2116,2079,
-2060,2060,2065,2060,2044,2028,2020,2017,2007,1980,1944,1909,1879,1845,1802,1753,1716,1702,1705,1711,1710,
-1838,1839,1850,1897,1978,2056,2096,2087,2044,1994,1956,1933,1924,1928,1944,1966,1986,1998,2009,2025,2050,
-2078,2100,2115,2131,2154,2185,2218,2247,2273,2303,2339,2375,2407,2433,2458,2487,2521,2552,2576,2595,2616,
-2640,2661,2673,2673,2668,2670,2686,2713,2747,2782,2813,2839,2857,2866,2870,2871,2874,2880,2886,2887,2883,
-2876,2872,2875,2885,2901,2917,2930,2936,2935,2930,2925,2922,2925,2933,2945,2958,2969,2978,2985,2994,3004,
-3017,3030,3042,3055,3072,3094,3118,3143,3170,3200,3235,3275,3317,3360,3408,3463,3520,3568,3593,3592,3573,
-3550,3532,3520,3508,3492,3475,3460,3447,3429,3402,3367,3333,3308,3296,3291,3289,3287,3288,3295,3309,3326,
-3340,3345,3342,3331,3319,3311,3312,3324,3344,3370,3402,3439,3482,3526,3565,3599,3630,3663,3701,3740,3775,
-3808,3842,3879,3918,3952,3978,3999,4021,4044,4065,4080,4093,4113,4147,4189,4225,4246,4256,4271,4299,4332,
-4347,4333,4303,4287,4306,4350,4386,4386,4354,4321,4320,4353,4388,4392,4356,4304,4269,4265,4277,4282,4267,
-4241,4222,4220,4226,4229,4225,4219,4212,4203,4186,4160,4138,4130,4135,4138,4123,4087,4046,4020,4015,4023,
-4024,4007,3969,3922,3875,3834,3798,3767,3740,3716,3694,3670,3642,3610,3575,3541,3508,3477,3448,3422,3398,
-3377,3358,3336,3309,3276,3240,3206,3176,3149,3122,3092,3060,3031,3007,2986,2963,2938,2915,2899,2892,2890,
-2887,2880,2869,2856,2843,2830,2815,2802,2791,2784,2781,2778,2775,2772,2768,2761,2752,2742,2732,2724,2714,
-2701,2684,2665,2647,2630,2612,2590,2564,2534,2504,2472,2439,2405,2373,2342,2316,2291,2268,2245,2221,2195,
-2167,2137,2107,2082,2062,2049,2042,2037,2032,2025,2012,1993,1971,1948,1929,1910,1889,1865,1837,1810,1783,
-1757,1730,1699,1666,1633,1601,1570,1540,1513,1488,1463,1435,1404,1368,1331,1293,1257,1220,1181,1142,1103,
-1066,1026,982,935,890,852,825,808,791,769,736,695,650,607,566,527,487,444,397,348,301,
-257,215,172,128,82,36,-10,-58,-105,-152,-198,-244,-289,-335,-381,-427,-473,-521,-571,-620,-669,
--716,-763,-813,-863,-913,-960,-1004,-1049,-1098,-1149,-1200,-1247,-1290,-1331,-1376,-1423,-1471,-1517,-1562,-1605,-1648,
--1688,-1726,-1763,-1805,-1853,-1905,-1954,-1997,-2033,-2065,-2096,-2127,-2156,-2186,-2219,-2257,-2296,-2331,-2361,-2387,-2414,
--2447,-2485,-2524,-2564,-2604,-2643,-2678,-2705,-2723,-2738,-2759,-2789,-2827,-2867,-2901,-2926,-2944,-2959,-2974,-2991,-3012,
--3035,-3057,-3077,-3093,-3108,-3124,-3140,-3152,-3162,-3172,-3183,-3194,-3203,-3204,-3201,-3200,-3206,-3217,-3228,-3231,-3227,
--3222,-3220,-3222,-3221,-3215,-3204,-3198,-3198,-3205,-3210,-3210,-3203,-3193,-3184,-3179,-3178,-3179,-3180,-3181,-3178,-3173,
--3167,-3163,-3160,-3159,-3154,-3145,-3131,-3117,-3104,-3092,-3081,-3069,-3056,-3044,-3032,-3020,-3005,-2989,-2972,-2955,-2941,
--2928,-2915,-2899,-2882,-2868,-2857,-2848,-2839,-2826,-2809,-2789,-2769,-2749,-2727,-2703,-2679,-2657,-2637,-2616,-2590,-2560,
--2527,-2494,-2463,-2433,-2405,-2379,-2355,-2332,-2308,-2282,-2254,-2227,-2200,-2172,-2139,-2103,-2067,-2037,-2010,-1981,-1948,
--1911,-1876,-1845,-1818,-1791,-1764,-1739,-1719,-1701,-1682,-1660,-1639,-1624,-1615,-1603,-1583,-1557,-1535,-1527,-1532,-1538,
--1527,-1493,-1444,-1393,-1352,-1314,-1265,-1185,-1064,-909,-737,-573,-432,-323,-240,-178,-132,-105,-98,-107,-118,
--118,-99,-71,-50,-53,-91,-164,-263,-373,-472,-543,-579,-586,-578,-568,-563,-558,-546,-522,-488,-448,
--408,-374,-347,-326,-309,-292,-277,-265,-254,-242,-223,-198,-170,-147,-132,-120,-103,-80,-55,-38,-32,
--29,-21,-2,20,38,48,55,65,84,109,133,154,174,196,221,248,275,303,334,364,393,
-417,441,468,500,535,569,601,634,670,709,748,782,810,839,879,935,1004,1077,1144,1199,1241,
-1276,1306,1334,1358,1376,1390,1403,1421,1448,1478,1501,1510,1506,1507,1532,1586,1652,1695,1689,1630,1537,
-1438,1347,1265,1193,1141,1130,1171,1252,1338,1393,1402,1377,1346,1328,1327,1335,1346,1361,1389,1437,1504,
-1580,1650,1703,1733,1743,1741,1736,1730,1721,1706,1682,1652,1616,1576,1530,1484,1445,1418,1400,1383,1357,
-1323,1285,1249,1213,1172,1127,1083,1047,1016,976,914,835,757,700,668,649,624,587,545,511,489,
-470,444,410,376,352,339,330,316,294,265,236,213,197,190,186,180,167,146,119,89,59,
-28,8,17,69,157,247,290,260,166,55,-27,-61,-61,-54,-59,-73,-87,-96,-102,-115,-135,
--155,-168,-175,-179,-186,-195,-204,-215,-229,-245,-259,-265,-263,-258,-259,-269,-287,-308,-328,-347,-366,
--385,-402,-415,-426,-438,-451,-463,-472,-479,-489,-505,-527,-551,-572,-588,-602,-618,-642,-673,-707,-740,
--766,-787,-805,-826,-851,-881,-912,-941,-967,-991,-1015,-1039,-1062,-1082,-1097,-1110,-1121,-1130,-1136,-1137,-1132,
--1126,-1122,-1123,-1129,-1135,-1140,-1143,-1147,-1154,-1166,-1181,-1198,-1214,-1231,-1249,-1267,-1282,-1291,-1292,-1289,-1286,
--1286,-1292,-1302,-1314,-1323,-1329,-1330,-1330,-1331,-1336,-1344,-1353,-1361,-1367,-1371,-1372,-1372,-1368,-1361,-1352,-1345,
--1341,-1340,-1341,-1344,-1350,-1357,-1366,-1372,-1372,-1366,-1355,-1346,-1341,-1342,-1344,-1343,-1339,-1332,-1325,-1320,-1316,
--1311,-1305,-1298,-1288,-1278,-1269,-1262,-1259,-1257,-1256,-1252,-1246,-1239,-1233,-1228,-1223,-1218,-1213,-1208,-1205,-1202,
--1200,-1199,-1202,-1209,-1218,-1228,-1237,-1244,-1250,-1254,-1256,-1256,-1256,-1256,-1259,-1263,-1264,-1260,-1251,-1239,-1228,
--1220,-1214,-1210,-1207,-1202,-1197,-1191,-1185,-1178,-1170,-1160,-1150,-1142,-1136,-1131,-1125,-1118,-1110,-1103,-1096,-1088,
--1080,-1072,-1065,-1060,-1054,-1047,-1037,-1027,-1022,-1021,-1023,-1023,-1019,-1015,-1011,-1010,-1011,-1010,-1005,-996,-987,
--980,-975,-969,-961,-951,-941,-931,-922,-914,-907,-902,-898,-895,-890,-883,-873,-863,-854,-844,-832,-818,
--806,-799,-797,-795,-789,-777,-764,-755,-752,-754,-756,-756,-756,-753,-743,-719,-683,-640,-603,-574,-551,
--530,-506,-484,-468,-458,-450,-439,-424,-408,-393,-378,-363,-345,-328,-315,-303,-289,-270,-248,-229,-215,
--206,-199,-188,-176,-165,-157,-150,-141,-131,-121,-111,-100,-86,-69,-53,-40,-29,-16,-1,15,33,
-51,71,94,118,139,155,173,196,225,255,283,308,333,361,390,418,443,469,500,533,562,
-586,610,640,678,718,751,775,797,823,853,883,908,932,961,995,1027,1050,1069,1093,1124,1151,
-1156,1133,1097,1074,1081,1116,1167,1230,1313,1423,1548,1657,1727,1758,1779,1821,1896,1987,2066,2119,2148,
-2164,2178,2194,2211,2227,2239,2253,2275,2315,2374,2436,2473,2463,2406,2322,2238,2164,2090,1997,1883,1765,
-1663,1585,1523,1467,1413,1370,1344,1331,1320,1304,1282,1261,1243,1230,1223,1227,1244,1270,1292,1301,1292,
-1271,1246,1223,1204,1189,1181,1180,1181,1178,1167,1148,1119,1072,997,891,762,630,511,412,331,262,
-204,160,131,111,92,69,42,17,-4,-25,-46,-66,-85,-102,-119,-137,-157,-175,-192,-210,-229,
--252,-274,-292,-303,-311,-319,-328,-338,-349,-360,-371,-383,-396,-411,-428,-448,-469,-492,-514,-538,-563,
--588,-613,-637,-661,-685,-709,-729,-745,-755,-763,-768,-773,-776,-776,-774,-769,-761,-752,-740,-728,-715,
--700,-680,-655,-627,-599,-571,-543,-517,-491,-466,-444,-423,-401,-377,-351,-324,-295,-266,-235,-202,-166,
--130,-94,-61,-33,-7,19,52,93,141,192,241,288,334,380,427,474,521,569,618,667,713,
-755,794,833,876,922,970,1017,1061,1102,1142,1181,1219,1256,1293,1330,1369,1410,1450,1489,1527,1567,
-1608,1651,1693,1733,1772,1810,1847,1884,1918,1948,1976,2003,2034,2068,2102,2134,2161,2184,2205,2226,2248,
-2271,2293,2317,2342,2370,2400,2429,2454,2472,2483,2488,2489,2486,2480,2472,2466,2465,2471,2479,2484,2483,
-2476,2470,2466,2462,2455,2443,2431,2421,2414,2406,2396,2386,2379,2378,2378,2376,2369,2362,2358,2357,2356,
-2353,2345,2335,2320,2299,2271,2241,2213,2188,2163,2137,2115,2106,2110,2119,2116,2097,2075,2063,2064,2063,
-2043,2001,1950,1907,1873,1831,1774,1714,1684,1703,1758,1812,1838,2097,2085,2052,2049,2095,2161,2204,2196,
-2141,2067,1999,1952,1929,1930,1951,1979,2002,2016,2025,2039,2062,2089,2112,2130,2148,2176,2211,2247,2277,
-2303,2331,2365,2400,2428,2449,2469,2495,2527,2558,2582,2597,2611,2625,2639,2649,2654,2661,2678,2708,2746,
-2782,2810,2828,2840,2845,2846,2845,2847,2855,2869,2883,2889,2885,2875,2869,2873,2887,2907,2925,2937,2942,
-2941,2938,2936,2937,2942,2952,2963,2974,2984,2991,2998,3008,3022,3038,3054,3069,3085,3104,3125,3149,3175,
-3207,3245,3287,3329,3365,3397,3432,3476,3525,3567,3587,3582,3561,3538,3521,3509,3497,3483,3470,3461,3453,
-3439,3414,3381,3349,3325,3310,3297,3283,3270,3269,3283,3310,3337,3354,3356,3346,3333,3325,3329,3346,3375,
-3408,3441,3472,3506,3544,3586,3629,3667,3699,3728,3760,3798,3838,3879,3920,3959,3994,4023,4045,4064,4083,
-4101,4117,4128,4140,4162,4199,4244,4282,4305,4314,4325,4346,4371,4381,4364,4331,4309,4316,4350,4382,4388,
-4368,4343,4339,4357,4375,4369,4336,4295,4271,4271,4284,4287,4274,4254,4241,4241,4248,4252,4251,4249,4246,
-4238,4221,4196,4174,4165,4165,4159,4135,4094,4050,4021,4015,4021,4025,4013,3988,3955,3920,3884,3847,3809,
-3772,3740,3713,3689,3665,3637,3607,3577,3547,3519,3494,3471,3450,3433,3415,3393,3365,3331,3294,3259,3227,
-3196,3164,3132,3100,3073,3050,3028,3002,2976,2953,2938,2931,2928,2923,2915,2905,2895,2883,2869,2853,2835,
-2822,2813,2809,2806,2803,2800,2795,2788,2780,2772,2764,2756,2746,2732,2715,2697,2680,2666,2650,2628,2600,
-2568,2536,2507,2480,2452,2423,2393,2365,2340,2315,2290,2262,2232,2202,2175,2153,2137,2125,2115,2105,2095,
-2084,2070,2053,2032,2009,1988,1969,1951,1929,1903,1874,1848,1823,1799,1770,1737,1704,1673,1648,1625,1600,
-1573,1545,1516,1486,1455,1420,1382,1345,1309,1274,1240,1205,1167,1126,1080,1030,981,940,908,886,867,
-845,816,781,742,702,662,622,580,536,491,446,403,361,320,278,235,190,143,95,47,0,
--47,-93,-138,-185,-232,-278,-323,-368,-413,-462,-512,-561,-608,-653,-698,-748,-800,-851,-898,-941,-984,
--1033,-1086,-1139,-1188,-1233,-1277,-1323,-1370,-1417,-1461,-1503,-1545,-1586,-1627,-1666,-1705,-1749,-1800,-1853,-1903,-1943,
--1975,-2005,-2037,-2070,-2103,-2135,-2167,-2202,-2239,-2273,-2304,-2333,-2364,-2399,-2438,-2477,-2517,-2555,-2593,-2624,-2648,
--2666,-2683,-2709,-2743,-2783,-2820,-2850,-2873,-2892,-2909,-2927,-2946,-2967,-2990,-3012,-3032,-3049,-3065,-3080,-3095,-3107,
--3116,-3124,-3135,-3147,-3159,-3164,-3164,-3162,-3165,-3174,-3184,-3191,-3194,-3194,-3195,-3196,-3192,-3183,-3173,-3167,-3168,
--3172,-3175,-3172,-3165,-3158,-3152,-3149,-3148,-3147,-3147,-3146,-3142,-3135,-3128,-3124,-3125,-3127,-3125,-3116,-3103,-3088,
--3076,-3067,-3056,-3044,-3030,-3016,-3004,-2991,-2977,-2961,-2946,-2932,-2921,-2910,-2897,-2881,-2865,-2851,-2840,-2830,-2818,
--2803,-2786,-2767,-2748,-2729,-2708,-2685,-2663,-2642,-2621,-2598,-2570,-2538,-2506,-2476,-2448,-2420,-2392,-2368,-2348,-2331,
--2313,-2290,-2262,-2231,-2198,-2165,-2132,-2098,-2066,-2037,-2009,-1978,-1943,-1908,-1877,-1852,-1829,-1805,-1778,-1753,-1732,
--1714,-1694,-1670,-1645,-1627,-1618,-1611,-1597,-1573,-1548,-1531,-1530,-1537,-1538,-1522,-1490,-1451,-1416,-1385,-1348,-1287,
--1189,-1050,-883,-712,-561,-441,-346,-265,-189,-126,-89,-84,-102,-122,-127,-114,-99,-105,-148,-226,-327,
--432,-524,-589,-626,-638,-636,-631,-627,-624,-614,-592,-560,-522,-486,-456,-430,-407,-384,-361,-342,-327,
--316,-304,-286,-263,-238,-215,-198,-183,-167,-150,-133,-121,-111,-99,-81,-57,-35,-18,-8,1,15,
-32,50,65,79,97,121,150,179,208,237,270,305,340,371,397,421,445,470,496,523,555,
-593,638,684,725,758,787,819,859,909,965,1024,1081,1133,1178,1215,1244,1265,1280,1292,1306,1326,
-1354,1389,1425,1452,1469,1482,1503,1536,1575,1603,1603,1570,1508,1426,1332,1232,1136,1062,1026,1032,1066,
-1105,1129,1135,1132,1134,1148,1172,1203,1240,1286,1344,1413,1489,1564,1625,1662,1673,1665,1649,1637,1631,
-1622,1604,1576,1543,1511,1481,1448,1414,1383,1360,1346,1330,1304,1266,1224,1186,1154,1121,1082,1039,997,
-958,917,868,810,755,712,680,650,610,561,516,484,467,451,426,389,351,318,294,272,247,
-217,186,160,140,127,121,119,117,109,97,81,60,31,-7,-46,-63,-37,32,115,169,164,
-108,35,-19,-43,-54,-72,-102,-134,-152,-154,-152,-160,-178,-198,-210,-212,-210,-211,-219,-231,-249,
--271,-295,-315,-324,-321,-312,-310,-318,-336,-355,-373,-389,-406,-423,-440,-454,-465,-477,-491,-504,-517,
--527,-539,-554,-573,-591,-607,-620,-634,-652,-676,-704,-732,-758,-780,-799,-818,-840,-866,-895,-926,-955,
--979,-1000,-1020,-1041,-1063,-1084,-1103,-1119,-1133,-1145,-1153,-1155,-1151,-1144,-1138,-1138,-1143,-1150,-1156,-1160,-1165,
--1173,-1185,-1199,-1213,-1227,-1243,-1261,-1281,-1299,-1311,-1314,-1311,-1307,-1305,-1308,-1316,-1326,-1336,-1342,-1343,-1342,
--1342,-1344,-1349,-1356,-1364,-1370,-1374,-1375,-1375,-1372,-1367,-1363,-1359,-1357,-1356,-1355,-1356,-1359,-1364,-1370,-1374,
--1374,-1369,-1361,-1354,-1351,-1351,-1352,-1352,-1349,-1343,-1335,-1328,-1321,-1315,-1309,-1303,-1294,-1285,-1276,-1269,-1264,
--1260,-1256,-1250,-1244,-1238,-1234,-1230,-1224,-1217,-1209,-1203,-1201,-1199,-1198,-1197,-1199,-1204,-1212,-1222,-1230,-1236,
--1241,-1244,-1247,-1248,-1247,-1246,-1247,-1249,-1249,-1245,-1238,-1228,-1219,-1212,-1208,-1205,-1201,-1197,-1192,-1188,-1184,
--1177,-1167,-1157,-1147,-1139,-1133,-1127,-1120,-1112,-1103,-1096,-1089,-1081,-1073,-1066,-1060,-1055,-1049,-1041,-1031,-1022,
--1017,-1016,-1017,-1016,-1014,-1011,-1009,-1008,-1006,-1002,-996,-990,-985,-981,-976,-967,-957,-947,-939,-933,-926,
--917,-909,-903,-901,-899,-895,-886,-875,-864,-857,-852,-845,-835,-825,-816,-811,-805,-795,-780,-764,-751,
--744,-742,-743,-746,-751,-758,-762,-755,-735,-704,-667,-629,-592,-558,-529,-507,-495,-488,-482,-471,-454,
--436,-420,-406,-390,-372,-354,-338,-325,-309,-289,-265,-242,-223,-208,-195,-183,-171,-161,-152,-142,-129,
--117,-105,-95,-83,-70,-55,-40,-25,-7,13,36,58,77,95,116,140,163,182,198,216,241,
-271,300,323,343,364,390,418,445,469,493,522,552,579,601,624,654,693,732,763,785,805,
-832,864,894,917,937,962,994,1027,1054,1077,1103,1133,1155,1152,1123,1084,1063,1074,1115,1173,1242,
-1330,1439,1554,1647,1698,1718,1737,1784,1863,1952,2028,2077,2108,2132,2153,2171,2186,2200,2218,2240,2269,
-2307,2355,2403,2432,2420,2363,2276,2186,2106,2028,1938,1832,1722,1629,1561,1511,1465,1417,1375,1345,1328,
-1316,1301,1283,1265,1253,1244,1237,1233,1237,1249,1262,1268,1263,1248,1232,1219,1209,1199,1189,1179,1170,
-1158,1140,1112,1069,1004,914,800,673,548,439,349,275,215,167,133,110,93,73,49,24,2,
--16,-34,-54,-75,-95,-112,-127,-143,-161,-180,-199,-217,-237,-257,-276,-290,-298,-304,-311,-320,-331,
--340,-346,-350,-356,-368,-386,-406,-426,-445,-463,-485,-511,-540,-569,-596,-620,-644,-667,-690,-710,-727,
--741,-753,-763,-770,-775,-778,-777,-772,-762,-749,-735,-724,-714,-703,-687,-663,-635,-606,-577,-548,-520,
--492,-468,-447,-427,-404,-377,-349,-320,-293,-264,-232,-195,-157,-119,-85,-56,-28,-1,28,64,107,
-156,206,257,305,353,401,449,495,538,582,626,672,715,755,792,831,875,923,973,1019,1062,
-1103,1143,1182,1219,1254,1290,1329,1371,1413,1451,1488,1524,1564,1608,1652,1694,1734,1772,1811,1848,1883,
-1914,1943,1971,2001,2035,2070,2106,2140,2171,2197,2219,2240,2263,2287,2312,2333,2353,2374,2400,2429,2456,
-2477,2489,2496,2501,2504,2500,2489,2475,2468,2471,2481,2487,2485,2479,2473,2471,2468,2461,2450,2438,2432,
-2428,2422,2410,2396,2386,2383,2383,2382,2377,2373,2371,2370,2366,2357,2345,2337,2330,2320,2300,2272,2240,
-2211,2187,2170,2161,2162,2169,2170,2156,2131,2110,2103,2104,2090,2047,1982,1925,1896,1888,1871,1828,1779,
-1768,1827,1939,2047,2097,2357,2318,2229,2155,2135,2160,2189,2189,2152,2093,2032,1982,1951,1943,1959,1989,
-2018,2035,2042,2050,2067,2091,2116,2139,2163,2194,2230,2265,2292,2313,2336,2366,2400,2429,2451,2470,2492,
-2519,2545,2564,2576,2585,2598,2615,2634,2653,2676,2705,2740,2775,2801,2816,2823,2829,2833,2836,2834,2832,
-2835,2845,2858,2869,2873,2872,2873,2880,2894,2911,2925,2934,2937,2938,2939,2941,2946,2954,2965,2978,2990,
-3001,3009,3017,3028,3042,3059,3076,3096,3117,3139,3162,3186,3214,3249,3293,3341,3383,3412,3431,3448,3474,
-3506,3534,3547,3542,3526,3510,3499,3491,3480,3467,3456,3451,3447,3436,3413,3385,3360,3343,3329,3310,3286,
-3265,3260,3278,3311,3342,3359,3357,3343,3330,3328,3345,3379,3426,3475,3515,3546,3573,3606,3650,3699,3744,
-3776,3799,3821,3852,3894,3943,3990,4031,4063,4089,4109,4128,4145,4161,4173,4183,4195,4217,4253,4295,4331,
-4353,4361,4368,4381,4397,4403,4390,4361,4335,4328,4341,4359,4365,4357,4345,4343,4350,4353,4340,4312,4285,
-4274,4280,4290,4292,4284,4273,4268,4272,4277,4280,4278,4277,4275,4267,4250,4227,4208,4198,4194,4185,4160,
-4121,4081,4055,4047,4049,4050,4041,4022,3997,3968,3933,3893,3849,3806,3767,3736,3711,3687,3663,3638,3611,
-3585,3559,3536,3516,3499,3484,3467,3445,3416,3381,3344,3308,3274,3242,3211,3180,3151,3125,3100,3072,3043,
-3015,2994,2982,2975,2969,2961,2950,2941,2932,2922,2906,2886,2864,2847,2837,2832,2831,2829,2826,2822,2815,
-2807,2798,2789,2780,2770,2756,2740,2723,2709,2696,2681,2659,2630,2597,2567,2540,2516,2493,2469,2443,2416,
-2390,2363,2335,2304,2273,2245,2222,2206,2196,2189,2179,2165,2149,2131,2112,2092,2070,2048,2028,2011,1992,
-1971,1945,1918,1892,1868,1842,1813,1779,1746,1719,1698,1680,1658,1630,1598,1565,1534,1503,1470,1434,1398,
-1365,1334,1303,1269,1228,1180,1125,1072,1026,991,967,947,924,893,856,818,782,748,713,673,628,
-582,538,497,457,417,376,334,290,245,199,151,104,56,11,-33,-78,-125,-172,-218,-263,-308,
--354,-403,-453,-502,-547,-588,-632,-680,-734,-788,-838,-883,-929,-977,-1030,-1082,-1131,-1176,-1222,-1270,-1318,
--1365,-1408,-1449,-1489,-1530,-1570,-1610,-1652,-1700,-1753,-1805,-1851,-1886,-1914,-1942,-1975,-2010,-2046,-2078,-2110,-2144,
--2179,-2215,-2250,-2283,-2318,-2355,-2393,-2431,-2467,-2502,-2535,-2564,-2586,-2605,-2627,-2658,-2698,-2740,-2776,-2804,-2824,
--2842,-2860,-2880,-2900,-2922,-2944,-2967,-2989,-3007,-3023,-3038,-3052,-3064,-3073,-3080,-3089,-3101,-3113,-3121,-3123,-3123,
--3124,-3131,-3141,-3151,-3159,-3164,-3166,-3165,-3159,-3150,-3143,-3140,-3141,-3141,-3138,-3131,-3125,-3122,-3121,-3121,-3119,
--3117,-3116,-3115,-3112,-3105,-3099,-3096,-3097,-3099,-3096,-3087,-3074,-3062,-3053,-3045,-3034,-3019,-3003,-2988,-2976,-2964,
--2950,-2933,-2916,-2903,-2894,-2885,-2873,-2858,-2842,-2829,-2819,-2809,-2797,-2781,-2764,-2748,-2731,-2713,-2692,-2670,-2648,
--2627,-2605,-2579,-2550,-2519,-2490,-2464,-2439,-2413,-2386,-2362,-2343,-2329,-2314,-2293,-2265,-2230,-2195,-2161,-2128,-2097,
--2067,-2039,-2010,-1979,-1946,-1914,-1886,-1863,-1841,-1818,-1791,-1764,-1740,-1718,-1695,-1669,-1644,-1627,-1619,-1615,-1607,
--1589,-1564,-1540,-1525,-1522,-1525,-1526,-1518,-1501,-1477,-1447,-1411,-1360,-1280,-1162,-1009,-841,-684,-556,-456,-369,
--280,-192,-124,-95,-105,-134,-156,-162,-160,-174,-222,-306,-409,-509,-592,-648,-678,-690,-690,-685,-679,
--671,-660,-643,-619,-592,-565,-538,-510,-481,-452,-426,-407,-393,-381,-367,-348,-326,-303,-282,-264,-249,
--235,-223,-211,-199,-185,-168,-148,-126,-107,-90,-74,-56,-39,-25,-16,-10,0,21,51,85,116,
-144,171,204,243,281,315,342,364,386,411,437,464,492,525,565,609,653,695,732,766,798,
-833,872,919,971,1023,1072,1111,1139,1159,1175,1191,1210,1235,1266,1305,1346,1386,1420,1447,1469,1492,
-1515,1534,1543,1533,1496,1424,1320,1195,1072,975,917,896,899,910,923,942,970,1006,1046,1087,1132,
-1187,1255,1331,1407,1476,1532,1571,1590,1586,1568,1545,1530,1521,1512,1494,1467,1437,1413,1394,1373,1346,
-1316,1291,1271,1249,1217,1174,1130,1095,1071,1050,1021,980,935,892,854,819,783,749,716,682,639,
-586,530,485,457,442,424,391,346,299,260,232,210,188,162,132,102,76,57,48,46,45,
-39,28,19,13,6,-13,-45,-79,-93,-76,-37,-1,11,2,-11,-15,-13,-23,-58,-114,-170,
--203,-214,-213,-217,-229,-242,-248,-246,-243,-244,-250,-263,-280,-305,-334,-359,-373,-371,-362,-357,-364,
--380,-398,-414,-427,-440,-455,-472,-488,-504,-519,-533,-546,-558,-569,-582,-599,-619,-636,-650,-661,-674,
--691,-712,-736,-758,-779,-799,-818,-837,-858,-883,-911,-943,-972,-996,-1014,-1029,-1045,-1064,-1086,-1107,-1126,
--1143,-1157,-1168,-1172,-1171,-1166,-1161,-1160,-1163,-1169,-1174,-1180,-1187,-1198,-1211,-1224,-1234,-1244,-1256,-1272,-1293,
--1313,-1328,-1335,-1335,-1332,-1329,-1329,-1332,-1338,-1345,-1351,-1356,-1358,-1359,-1359,-1360,-1364,-1369,-1375,-1380,-1383,
--1384,-1383,-1382,-1381,-1380,-1380,-1380,-1380,-1381,-1382,-1384,-1384,-1382,-1378,-1373,-1367,-1363,-1360,-1359,-1358,-1358,
--1358,-1355,-1349,-1340,-1330,-1320,-1312,-1304,-1297,-1289,-1282,-1276,-1271,-1266,-1260,-1252,-1244,-1238,-1234,-1230,-1225,
--1218,-1210,-1206,-1204,-1203,-1201,-1198,-1196,-1197,-1202,-1209,-1216,-1221,-1225,-1229,-1233,-1235,-1236,-1235,-1234,-1233,
--1231,-1228,-1223,-1217,-1212,-1208,-1205,-1201,-1196,-1190,-1185,-1181,-1176,-1170,-1162,-1153,-1146,-1140,-1134,-1127,-1117,
--1107,-1097,-1089,-1081,-1073,-1065,-1057,-1051,-1047,-1041,-1033,-1025,-1018,-1014,-1012,-1011,-1009,-1007,-1005,-1005,-1004,
--1000,-994,-988,-984,-983,-980,-974,-963,-950,-941,-935,-932,-926,-917,-907,-900,-896,-893,-887,-877,-866,
--858,-855,-855,-854,-849,-840,-831,-824,-817,-806,-792,-776,-762,-753,-746,-742,-738,-738,-741,-743,-740,
--725,-699,-662,-622,-582,-547,-522,-508,-504,-504,-501,-491,-475,-457,-440,-424,-408,-391,-373,-356,-339,
--322,-303,-282,-261,-240,-221,-203,-187,-174,-163,-151,-137,-121,-106,-93,-80,-67,-52,-35,-18,0,
-23,50,78,102,121,138,158,180,201,219,233,251,277,306,333,353,371,392,419,447,471,
-490,510,534,562,589,613,637,668,705,741,769,790,813,842,875,903,922,940,965,999,1035,
-1064,1088,1112,1136,1152,1144,1111,1071,1051,1065,1110,1175,1254,1351,1464,1574,1653,1687,1693,1707,1757,
-1841,1933,2006,2053,2082,2104,2122,2133,2139,2149,2169,2200,2236,2272,2306,2335,2347,2328,2272,2188,2098,
-2013,1932,1843,1745,1649,1573,1522,1485,1450,1411,1375,1352,1339,1329,1312,1291,1274,1264,1258,1251,1240,
-1230,1228,1233,1240,1242,1238,1231,1225,1220,1213,1201,1183,1160,1130,1091,1039,973,891,795,689,579,
-473,378,299,233,180,140,111,90,71,50,26,4,-12,-26,-41,-60,-83,-105,-121,-134,-146,
--162,-181,-202,-222,-241,-259,-273,-283,-288,-292,-298,-307,-316,-321,-322,-322,-327,-341,-364,-390,-412,
--430,-446,-464,-487,-514,-542,-568,-594,-620,-645,-668,-688,-705,-721,-737,-752,-763,-770,-774,-774,-770,
--761,-748,-735,-724,-716,-706,-690,-667,-640,-612,-585,-558,-528,-500,-474,-453,-433,-409,-382,-352,-323,
--296,-267,-232,-193,-153,-119,-90,-64,-38,-8,26,66,110,160,212,264,317,370,422,471,516,
-556,595,635,679,722,762,799,838,881,927,973,1017,1058,1099,1140,1181,1217,1249,1282,1318,1359,
-1401,1440,1477,1516,1558,1604,1648,1689,1728,1767,1806,1844,1877,1907,1936,1967,2002,2038,2074,2109,2144,
-2177,2206,2229,2249,2271,2296,2321,2342,2358,2375,2398,2429,2459,2482,2496,2505,2513,2519,2517,2505,2489,
-2478,2479,2488,2493,2491,2484,2479,2477,2475,2467,2455,2445,2442,2442,2438,2425,2408,2393,2386,2382,2378,
-2373,2370,2372,2372,2365,2350,2335,2326,2325,2323,2311,2290,2267,2247,2233,2221,2211,2202,2197,2189,2175,
-2156,2141,2132,2120,2084,2020,1950,1912,1928,1977,2012,2003,1968,1964,2037,2171,2301,2357,2427,2372,2254,
-2139,2076,2069,2088,2102,2101,2084,2058,2026,1995,1976,1980,2005,2036,2058,2067,2071,2082,2103,2130,2157,
-2183,2211,2242,2270,2291,2306,2323,2348,2379,2411,2436,2455,2471,2489,2506,2521,2535,2554,2581,2615,2650,
-2683,2713,2741,2767,2787,2799,2805,2811,2819,2829,2834,2831,2822,2816,2820,2833,2851,2867,2878,2886,2894,
-2902,2909,2916,2920,2925,2930,2936,2943,2951,2962,2975,2992,3008,3023,3034,3043,3052,3064,3079,3098,3122,
-3150,3178,3203,3227,3253,3287,3330,3375,3413,3434,3440,3442,3449,3462,3477,3486,3486,3481,3476,3472,3464,
-3451,3438,3431,3429,3429,3420,3402,3380,3363,3353,3341,3320,3291,3266,3261,3279,3311,3341,3356,3353,3343,
-3336,3343,3371,3418,3477,3535,3578,3606,3628,3660,3709,3767,3819,3851,3867,3879,3906,3951,4007,4060,4100,
-4129,4150,4170,4189,4208,4223,4236,4248,4265,4288,4320,4353,4378,4390,4390,4386,4386,4393,4399,4395,4380,
-4358,4339,4330,4327,4326,4326,4329,4334,4338,4333,4318,4300,4289,4290,4300,4307,4307,4300,4294,4294,4299,
-4303,4304,4302,4300,4296,4288,4272,4252,4235,4226,4221,4213,4194,4165,4135,4114,4104,4101,4097,4087,4069,
-4044,4013,3976,3934,3889,3846,3807,3773,3744,3719,3695,3672,3647,3622,3598,3577,3561,3547,3533,3515,3490,
-3460,3425,3389,3354,3321,3289,3259,3230,3203,3175,3146,3114,3082,3056,3037,3026,3018,3007,2993,2981,2972,
-2964,2954,2937,2913,2889,2871,2861,2857,2858,2858,2857,2853,2845,2834,2821,2809,2798,2788,2776,2761,2747,
-2732,2718,2700,2678,2652,2624,2598,2574,2553,2531,2509,2485,2460,2433,2404,2374,2345,2318,2294,2276,2263,
-2255,2247,2237,2221,2200,2178,2156,2134,2112,2091,2071,2052,2033,2012,1987,1960,1934,1909,1884,1856,1826,
-1796,1771,1750,1730,1707,1677,1645,1611,1580,1550,1519,1486,1454,1422,1392,1359,1320,1271,1216,1158,1106,
-1067,1041,1023,1003,975,937,895,855,820,788,753,712,669,625,585,547,509,468,424,380,336,
-293,249,203,156,109,64,19,-24,-69,-115,-161,-206,-251,-297,-346,-395,-443,-487,-528,-570,-617,
--669,-723,-776,-826,-875,-924,-974,-1024,-1071,-1117,-1165,-1214,-1263,-1309,-1352,-1391,-1430,-1469,-1509,-1552,-1599,
--1652,-1708,-1759,-1800,-1829,-1852,-1878,-1910,-1946,-1981,-2014,-2047,-2082,-2119,-2157,-2194,-2229,-2266,-2304,-2342,-2379,
--2413,-2446,-2478,-2505,-2528,-2549,-2574,-2608,-2650,-2692,-2728,-2755,-2774,-2791,-2809,-2829,-2851,-2874,-2897,-2921,-2943,
--2962,-2978,-2994,-3010,-3024,-3034,-3043,-3051,-3062,-3073,-3081,-3085,-3086,-3089,-3095,-3105,-3116,-3126,-3132,-3133,-3129,
--3122,-3115,-3111,-3112,-3112,-3109,-3101,-3091,-3086,-3086,-3089,-3090,-3089,-3087,-3087,-3087,-3085,-3080,-3075,-3072,-3073,
--3072,-3066,-3054,-3042,-3034,-3029,-3022,-3008,-2989,-2970,-2957,-2948,-2938,-2924,-2905,-2887,-2874,-2865,-2857,-2846,-2831,
--2816,-2805,-2798,-2791,-2780,-2765,-2749,-2732,-2716,-2697,-2675,-2652,-2628,-2606,-2584,-2559,-2531,-2502,-2475,-2452,-2430,
--2408,-2383,-2360,-2340,-2323,-2306,-2283,-2255,-2222,-2188,-2157,-2127,-2097,-2068,-2039,-2011,-1982,-1952,-1921,-1892,-1867,
--1845,-1823,-1800,-1775,-1747,-1719,-1689,-1661,-1637,-1621,-1613,-1609,-1603,-1591,-1572,-1549,-1527,-1513,-1509,-1515,-1524,
--1526,-1515,-1489,-1453,-1406,-1342,-1243,-1105,-939,-772,-633,-530,-448,-367,-281,-204,-157,-151,-171,-196,-208,
--216,-240,-297,-387,-493,-591,-665,-712,-737,-745,-742,-732,-717,-701,-684,-668,-654,-640,-621,-597,-567,
--535,-507,-486,-473,-461,-448,-429,-408,-385,-365,-347,-331,-317,-304,-292,-279,-266,-251,-236,-221,-206,
--189,-167,-143,-119,-103,-95,-94,-90,-75,-46,-10,25,54,79,105,139,178,216,246,270,293,
-321,356,392,422,444,462,484,519,565,618,668,710,743,770,799,835,879,926,970,1007,1035,
-1057,1079,1104,1133,1165,1199,1232,1267,1304,1342,1378,1410,1435,1456,1473,1486,1486,1457,1387,1274,1136,
-1002,902,847,830,835,849,872,908,957,1013,1064,1109,1155,1212,1281,1351,1412,1457,1485,1502,1507,
-1499,1481,1460,1446,1438,1431,1417,1395,1374,1357,1343,1326,1299,1264,1229,1198,1166,1128,1085,1045,1017,
-1000,985,960,921,875,833,799,773,748,721,689,649,599,541,486,443,418,401,378,338,285,
-231,189,164,150,140,124,98,64,26,-5,-23,-26,-25,-30,-41,-52,-54,-48,-48,-65,-99,
--136,-158,-159,-148,-132,-114,-90,-56,-27,-22,-53,-111,-175,-225,-252,-266,-274,-281,-284,-282,-279,
--280,-287,-297,-306,-318,-337,-363,-391,-411,-416,-412,-408,-413,-428,-445,-460,-470,-477,-487,-500,-518,
--539,-561,-579,-592,-600,-608,-620,-640,-663,-684,-701,-713,-724,-737,-752,-768,-784,-802,-822,-843,-863,
--883,-904,-929,-958,-988,-1013,-1031,-1045,-1059,-1076,-1095,-1116,-1135,-1152,-1166,-1178,-1185,-1187,-1186,-1185,-1186,
--1188,-1192,-1196,-1202,-1211,-1224,-1238,-1251,-1261,-1269,-1279,-1293,-1312,-1331,-1347,-1357,-1361,-1361,-1359,-1356,-1355,
--1354,-1357,-1361,-1368,-1374,-1377,-1379,-1378,-1379,-1382,-1386,-1392,-1396,-1398,-1399,-1400,-1401,-1401,-1402,-1403,-1404,
--1406,-1407,-1406,-1402,-1394,-1386,-1380,-1375,-1372,-1370,-1367,-1366,-1366,-1367,-1366,-1361,-1351,-1339,-1327,-1317,-1309,
--1302,-1294,-1287,-1280,-1276,-1271,-1265,-1257,-1248,-1240,-1235,-1230,-1225,-1219,-1214,-1211,-1209,-1208,-1206,-1202,-1198,
--1197,-1198,-1202,-1206,-1209,-1211,-1213,-1215,-1218,-1220,-1221,-1220,-1218,-1215,-1212,-1208,-1205,-1202,-1200,-1196,-1192,
--1186,-1179,-1173,-1168,-1164,-1159,-1153,-1146,-1141,-1136,-1130,-1123,-1113,-1102,-1092,-1083,-1074,-1065,-1056,-1048,-1043,
--1039,-1034,-1027,-1020,-1015,-1011,-1009,-1006,-1002,-999,-998,-998,-998,-995,-989,-983,-980,-978,-975,-966,-954,
--942,-934,-930,-927,-921,-912,-901,-893,-887,-881,-873,-862,-852,-846,-845,-847,-848,-845,-839,-833,-826,
--820,-812,-802,-791,-780,-771,-762,-751,-738,-725,-712,-700,-686,-667,-641,-610,-578,-549,-525,-510,-503,
--503,-505,-506,-501,-490,-474,-456,-438,-421,-404,-386,-368,-350,-331,-313,-297,-280,-262,-243,-222,-204,
--188,-174,-160,-143,-125,-108,-94,-79,-62,-42,-21,0,21,47,76,104,127,144,159,177,197,
-217,233,247,266,291,319,344,365,386,412,442,470,491,505,520,542,569,597,622,647,677,
-712,745,770,791,815,844,875,899,915,933,961,999,1038,1068,1089,1109,1131,1143,1133,1099,1059,
-1039,1053,1098,1164,1247,1349,1465,1574,1646,1671,1671,1684,1739,1830,1929,2004,2046,2068,2081,2089,2090,
-2087,2091,2111,2146,2186,2221,2246,2260,2257,2230,2173,2094,2007,1923,1839,1751,1660,1577,1515,1477,1451,
-1423,1392,1368,1356,1354,1347,1326,1296,1272,1260,1257,1251,1236,1217,1205,1206,1216,1226,1229,1227,1223,
-1220,1213,1199,1174,1137,1086,1021,942,854,762,671,581,493,406,325,254,194,148,114,89,69,
-49,29,9,-7,-20,-32,-48,-68,-90,-112,-128,-140,-152,-167,-186,-206,-225,-242,-255,-266,-274,
--279,-282,-285,-289,-293,-294,-293,-293,-301,-319,-347,-376,-403,-422,-438,-454,-472,-492,-513,-537,-563,
--592,-621,-645,-665,-682,-699,-716,-732,-744,-750,-754,-756,-756,-752,-743,-734,-725,-716,-705,-687,-663,
--636,-612,-589,-564,-536,-507,-481,-459,-438,-414,-387,-358,-331,-305,-274,-237,-196,-157,-125,-100,-76,
--49,-16,23,66,113,164,218,273,329,383,436,485,529,567,604,643,686,730,772,811,849,
-890,932,974,1014,1054,1096,1141,1183,1218,1248,1276,1308,1346,1386,1425,1463,1503,1548,1596,1641,1682,
-1721,1762,1803,1841,1875,1904,1934,1969,2006,2042,2074,2106,2141,2177,2210,2234,2254,2274,2299,2326,2348,
-2364,2380,2403,2435,2468,2494,2509,2518,2525,2531,2530,2518,2503,2494,2496,2504,2510,2507,2500,2496,2495,
-2492,2482,2467,2456,2453,2454,2450,2437,2418,2402,2392,2384,2375,2367,2363,2366,2369,2364,2351,2336,2327,
-2323,2317,2302,2283,2268,2262,2258,2247,2226,2203,2187,2181,2177,2167,2152,2133,2107,2065,2010,1967,1971,
-2035,2130,2199,2203,2160,2130,2169,2274,2385,2427,2260,2219,2129,2041,1994,1992,2015,2044,2068,2085,2091,
-2078,2048,2019,2009,2026,2057,2085,2097,2101,2110,2131,2160,2188,2210,2230,2252,2275,2294,2309,2324,2344,
-2372,2401,2426,2442,2451,2460,2471,2489,2516,2553,2599,2648,2693,2728,2753,2768,2779,2786,2790,2795,2804,
-2814,2824,2826,2818,2806,2799,2805,2823,2848,2871,2888,2898,2903,2905,2907,2909,2914,2923,2934,2945,2954,
-2964,2975,2990,3010,3030,3048,3061,3070,3078,3089,3104,3125,3153,3184,3215,3242,3264,3286,3313,3346,3379,
-3405,3418,3418,3412,3410,3414,3423,3432,3440,3445,3446,3442,3430,3415,3403,3400,3403,3406,3401,3387,3372,
-3362,3356,3344,3322,3294,3271,3268,3285,3313,3337,3349,3352,3352,3358,3376,3411,3462,3523,3581,3624,3652,
-3676,3712,3767,3832,3886,3916,3927,3938,3968,4020,4082,4135,4171,4192,4207,4224,4244,4263,4279,4293,4311,
-4334,4363,4393,4419,4433,4434,4420,4400,4382,4374,4374,4377,4375,4364,4344,4322,4306,4301,4308,4321,4333,
-4336,4328,4314,4304,4304,4314,4325,4330,4326,4318,4312,4313,4318,4322,4323,4322,4320,4315,4307,4293,4277,
-4262,4252,4246,4237,4223,4204,4184,4168,4158,4151,4144,4133,4115,4089,4054,4014,3972,3931,3892,3855,3820,
-3788,3760,3734,3709,3684,3659,3636,3617,3604,3593,3579,3559,3532,3500,3465,3430,3396,3362,3329,3297,3267,
-3239,3210,3181,3150,3121,3097,3080,3066,3052,3036,3020,3007,2999,2992,2980,2962,2939,2916,2900,2891,2888,
-2889,2891,2890,2885,2874,2860,2844,2830,2819,2809,2799,2786,2772,2756,2737,2717,2695,2673,2653,2635,2616,
-2595,2572,2548,2522,2495,2466,2436,2408,2384,2364,2347,2332,2319,2309,2300,2287,2270,2247,2222,2198,2175,
-2154,2133,2112,2091,2071,2048,2023,1996,1968,1943,1920,1897,1873,1848,1823,1798,1773,1746,1717,1687,1656,
-1626,1596,1566,1536,1505,1472,1436,1395,1346,1292,1236,1184,1141,1111,1091,1073,1051,1019,980,938,899,
-862,826,787,745,704,666,631,595,556,513,468,424,382,341,299,254,208,161,115,70,25,
--19,-64,-109,-154,-199,-245,-292,-339,-386,-431,-475,-518,-563,-610,-660,-712,-764,-815,-865,-914,-961,
--1009,-1058,-1108,-1159,-1208,-1252,-1292,-1329,-1366,-1404,-1445,-1491,-1544,-1603,-1660,-1710,-1746,-1771,-1793,-1818,-1849,
--1884,-1919,-1952,-1987,-2026,-2066,-2104,-2139,-2172,-2207,-2245,-2285,-2322,-2357,-2389,-2420,-2450,-2476,-2501,-2528,-2560,
--2597,-2636,-2670,-2696,-2717,-2737,-2757,-2779,-2803,-2828,-2852,-2876,-2896,-2914,-2930,-2946,-2963,-2979,-2992,-3004,-3014,
--3024,-3035,-3043,-3048,-3052,-3057,-3063,-3072,-3083,-3092,-3099,-3101,-3096,-3088,-3081,-3078,-3080,-3081,-3077,-3068,-3059,
--3054,-3055,-3058,-3060,-3059,-3059,-3059,-3059,-3056,-3050,-3045,-3043,-3043,-3041,-3032,-3020,-3010,-3006,-3004,-2997,-2980,
--2958,-2938,-2927,-2922,-2915,-2900,-2879,-2859,-2846,-2840,-2833,-2822,-2806,-2792,-2783,-2778,-2773,-2763,-2749,-2732,-2715,
--2697,-2678,-2655,-2630,-2606,-2584,-2562,-2539,-2513,-2486,-2461,-2439,-2420,-2401,-2380,-2358,-2337,-2316,-2294,-2269,-2241,
--2211,-2181,-2153,-2124,-2095,-2064,-2034,-2006,-1980,-1952,-1921,-1890,-1862,-1840,-1823,-1807,-1787,-1758,-1722,-1685,-1654,
--1631,-1616,-1606,-1597,-1589,-1581,-1572,-1559,-1540,-1519,-1505,-1505,-1516,-1527,-1524,-1503,-1471,-1433,-1383,-1305,-1182,
--1019,-844,-689,-575,-496,-430,-363,-298,-251,-233,-239,-253,-265,-279,-312,-377,-471,-576,-668,-736,-777,
--797,-803,-797,-781,-756,-729,-704,-687,-676,-668,-655,-634,-606,-579,-558,-546,-539,-530,-514,-491,-465,
--443,-424,-408,-393,-379,-366,-353,-339,-325,-312,-303,-295,-283,-264,-237,-208,-186,-177,-177,-177,-167,
--141,-104,-65,-33,-9,14,42,78,117,151,176,196,221,257,302,346,375,387,389,396,424,
-473,534,593,638,669,694,722,759,802,847,888,921,949,974,1002,1034,1069,1103,1132,1156,1179,
-1206,1243,1287,1331,1366,1388,1398,1401,1393,1362,1295,1190,1064,950,877,854,869,903,939,976,1020,
-1073,1128,1177,1217,1257,1303,1354,1401,1434,1449,1454,1455,1454,1448,1435,1420,1408,1402,1397,1388,1372,
-1355,1340,1326,1307,1278,1240,1199,1159,1120,1080,1041,1007,984,968,948,917,875,828,786,752,723,
-692,658,619,574,523,469,420,383,362,346,323,284,232,178,134,108,96,91,81,59,20,
--27,-71,-97,-102,-96,-93,-102,-117,-126,-125,-121,-126,-147,-178,-206,-223,-228,-226,-214,-189,-151,
--111,-88,-94,-130,-181,-231,-273,-305,-327,-337,-335,-327,-321,-324,-335,-347,-354,-359,-369,-389,-416,
--440,-454,-457,-457,-463,-478,-496,-511,-520,-523,-524,-529,-543,-566,-594,-619,-636,-644,-649,-660,-679,
--705,-731,-753,-768,-780,-789,-797,-804,-813,-828,-849,-873,-895,-914,-930,-950,-975,-1002,-1029,-1050,-1067,
--1082,-1097,-1114,-1131,-1147,-1161,-1174,-1186,-1194,-1199,-1202,-1205,-1209,-1213,-1216,-1220,-1225,-1234,-1246,-1261,-1275,
--1288,-1299,-1309,-1321,-1335,-1350,-1363,-1375,-1383,-1388,-1389,-1387,-1383,-1378,-1375,-1376,-1381,-1388,-1395,-1399,-1400,
--1400,-1400,-1402,-1405,-1408,-1410,-1411,-1413,-1415,-1417,-1417,-1418,-1418,-1420,-1421,-1419,-1413,-1405,-1396,-1390,-1385,
--1382,-1379,-1376,-1374,-1373,-1373,-1371,-1366,-1356,-1344,-1334,-1325,-1319,-1312,-1303,-1294,-1287,-1280,-1276,-1271,-1265,
--1256,-1247,-1239,-1232,-1226,-1222,-1217,-1214,-1211,-1209,-1206,-1204,-1201,-1199,-1199,-1200,-1201,-1201,-1200,-1199,-1199,
--1200,-1202,-1203,-1202,-1200,-1197,-1194,-1192,-1189,-1186,-1183,-1179,-1174,-1169,-1163,-1158,-1153,-1149,-1145,-1140,-1135,
--1129,-1123,-1118,-1111,-1104,-1095,-1086,-1077,-1067,-1058,-1049,-1042,-1038,-1034,-1029,-1023,-1016,-1011,-1008,-1005,-1002,
--998,-994,-992,-992,-992,-990,-986,-981,-976,-971,-963,-954,-943,-935,-930,-927,-923,-916,-906,-896,-888,
--881,-874,-864,-852,-842,-835,-832,-831,-830,-826,-822,-817,-813,-810,-804,-798,-791,-785,-779,-770,-756,
--737,-714,-690,-665,-642,-619,-595,-573,-555,-540,-528,-519,-512,-506,-503,-503,-502,-497,-486,-468,-446,
--424,-406,-389,-373,-354,-335,-318,-304,-291,-276,-257,-236,-217,-200,-185,-169,-151,-132,-115,-101,-85,
--65,-41,-16,6,29,55,84,111,134,151,165,181,200,218,234,250,270,294,320,345,367,
-392,422,455,482,501,514,529,552,580,607,630,654,682,715,746,771,793,817,845,871,891,
-904,923,953,994,1032,1058,1077,1098,1122,1136,1125,1088,1045,1025,1040,1086,1149,1227,1322,1434,1542,
-1617,1647,1652,1670,1731,1829,1933,2009,2047,2058,2060,2059,2055,2049,2049,2065,2097,2136,2169,2190,2197,
-2185,2149,2087,2007,1922,1839,1757,1674,1591,1520,1471,1441,1419,1394,1366,1348,1347,1352,1348,1324,1286,
-1254,1240,1238,1233,1217,1194,1178,1180,1194,1208,1215,1213,1209,1205,1197,1178,1142,1086,1013,926,830,
-735,647,568,497,427,354,281,215,162,124,96,74,54,36,19,4,-8,-21,-36,-54,-75,
--98,-119,-136,-150,-164,-179,-196,-213,-227,-239,-248,-257,-265,-272,-275,-275,-274,-273,-273,-273,-277,
--287,-305,-330,-358,-384,-406,-424,-439,-455,-470,-487,-508,-534,-564,-594,-619,-639,-657,-674,-693,-708,
--719,-725,-728,-732,-736,-737,-734,-728,-720,-711,-698,-679,-656,-631,-609,-589,-566,-540,-512,-486,-464,
--442,-418,-391,-364,-339,-313,-284,-247,-205,-166,-135,-110,-84,-53,-15,28,75,126,180,237,294,
-348,400,449,496,539,578,615,655,697,741,782,820,857,895,935,974,1012,1051,1094,1138,1179,
-1213,1242,1269,1300,1337,1376,1413,1452,1494,1541,1590,1636,1677,1718,1760,1804,1845,1880,1910,1942,1977,
-2012,2044,2072,2101,2136,2175,2210,2236,2256,2276,2302,2330,2354,2371,2386,2410,2443,2477,2504,2519,2527,
-2533,2537,2535,2524,2511,2506,2511,2520,2525,2522,2516,2514,2514,2511,2499,2481,2467,2461,2460,2455,2441,
-2424,2409,2399,2389,2376,2363,2355,2356,2360,2360,2354,2346,2341,2334,2318,2292,2267,2256,2258,2260,2246,
-2215,2185,2172,2175,2179,2166,2137,2105,2080,2065,2055,2058,2090,2159,2240,2288,2269,2195,2123,2108,2159,
-2230,2260,2012,2008,1984,1968,1979,2010,2043,2068,2089,2109,2123,2118,2091,2057,2040,2052,2083,2113,2129,
-2135,2146,2169,2199,2226,2244,2258,2276,2300,2326,2348,2365,2381,2401,2423,2441,2453,2460,2469,2486,2515,
-2554,2602,2652,2698,2734,2759,2771,2777,2780,2783,2788,2795,2803,2809,2809,2803,2792,2784,2786,2802,2829,
-2856,2879,2893,2900,2904,2908,2912,2918,2927,2940,2953,2965,2975,2983,2994,3010,3030,3051,3069,3083,3093,
-3103,3115,3133,3156,3184,3214,3244,3270,3291,3309,3326,3344,3360,3372,3378,3377,3375,3376,3382,3393,3406,
-3417,3423,3420,3409,3392,3377,3369,3372,3381,3386,3383,3374,3365,3359,3353,3340,3319,3295,3281,3283,3298,
-3318,3334,3344,3354,3369,3390,3418,3455,3502,3556,3611,3658,3694,3729,3775,3834,3895,3941,3966,3978,3997,
-4040,4102,4166,4214,4239,4250,4259,4274,4292,4308,4320,4333,4353,4382,4416,4450,4478,4493,4492,4475,4444,
-4408,4377,4360,4356,4357,4355,4344,4326,4313,4312,4324,4341,4354,4353,4341,4325,4317,4319,4330,4340,4342,
-4338,4331,4327,4329,4334,4339,4343,4344,4342,4338,4331,4320,4307,4294,4282,4270,4257,4242,4228,4215,4203,
-4194,4187,4181,4172,4156,4131,4095,4054,4013,3974,3937,3900,3864,3830,3800,3774,3749,3722,3695,3671,3654,
-3642,3632,3619,3597,3568,3534,3499,3464,3428,3391,3354,3319,3287,3259,3232,3206,3182,3159,3138,3119,3099,
-3079,3059,3043,3033,3026,3018,3004,2986,2966,2947,2934,2926,2922,2922,2922,2921,2915,2903,2886,2870,2857,
-2847,2839,2829,2817,2802,2785,2766,2744,2723,2704,2689,2674,2658,2636,2611,2584,2556,2527,2497,2468,2444,
-2426,2413,2402,2389,2375,2361,2348,2333,2314,2290,2262,2236,2214,2193,2173,2151,2129,2106,2083,2059,2032,
-2004,1978,1956,1936,1916,1894,1867,1838,1808,1780,1754,1728,1701,1672,1642,1611,1579,1546,1508,1463,1412,
-1357,1304,1257,1218,1189,1165,1144,1120,1091,1057,1021,983,946,908,868,824,782,743,709,677,641,
-600,556,511,470,430,391,350,307,263,217,171,125,78,32,-13,-58,-104,-150,-196,-241,-286,
--332,-378,-425,-470,-514,-559,-604,-653,-704,-756,-805,-853,-900,-949,-1000,-1054,-1107,-1155,-1198,-1235,-1270,
--1305,-1344,-1388,-1438,-1495,-1554,-1610,-1654,-1686,-1709,-1731,-1758,-1791,-1826,-1862,-1898,-1936,-1977,-2018,-2055,-2087,
--2118,-2152,-2191,-2231,-2269,-2301,-2330,-2360,-2392,-2425,-2456,-2484,-2513,-2544,-2576,-2607,-2635,-2660,-2684,-2708,-2733,
--2759,-2786,-2811,-2833,-2851,-2867,-2883,-2898,-2915,-2930,-2944,-2957,-2969,-2981,-2992,-3002,-3010,-3016,-3023,-3029,-3036,
--3045,-3055,-3063,-3068,-3066,-3059,-3051,-3048,-3049,-3050,-3047,-3040,-3032,-3028,-3028,-3030,-3031,-3031,-3031,-3031,-3030,
--3024,-3017,-3011,-3011,-3012,-3009,-2999,-2986,-2978,-2977,-2978,-2971,-2952,-2929,-2910,-2902,-2900,-2894,-2878,-2855,-2834,
--2821,-2815,-2810,-2798,-2782,-2767,-2758,-2754,-2751,-2742,-2728,-2711,-2694,-2677,-2659,-2639,-2615,-2591,-2568,-2545,-2523,
--2499,-2474,-2450,-2428,-2409,-2391,-2373,-2354,-2334,-2312,-2288,-2262,-2234,-2205,-2176,-2148,-2119,-2089,-2058,-2027,-1998,
--1972,-1946,-1917,-1886,-1858,-1837,-1823,-1812,-1793,-1763,-1723,-1684,-1653,-1635,-1625,-1613,-1599,-1584,-1574,-1572,-1568,
--1556,-1534,-1511,-1500,-1503,-1512,-1513,-1499,-1475,-1449,-1416,-1359,-1258,-1109,-935,-770,-641,-552,-489,-436,-387,
--348,-327,-322,-327,-337,-358,-403,-475,-568,-664,-746,-803,-836,-850,-852,-844,-825,-799,-769,-741,-721,
--709,-700,-690,-673,-650,-629,-615,-608,-603,-593,-574,-549,-522,-498,-478,-460,-444,-430,-418,-406,-394,
--382,-373,-366,-359,-346,-324,-295,-270,-257,-257,-261,-255,-233,-196,-154,-118,-92,-71,-47,-15,21,
-58,87,109,129,156,195,242,284,308,313,309,315,345,398,460,513,548,569,591,625,673,
-727,777,816,846,872,898,927,959,991,1020,1043,1063,1084,1113,1157,1213,1269,1309,1326,1322,1304,
-1279,1244,1191,1115,1030,961,932,950,1002,1063,1117,1159,1195,1233,1273,1311,1345,1376,1408,1438,1460,
-1468,1463,1453,1445,1440,1434,1423,1409,1397,1390,1384,1376,1361,1342,1323,1306,1287,1264,1234,1200,1163,
-1124,1084,1047,1015,990,966,935,894,845,796,750,708,665,619,570,521,473,425,378,338,309,
-292,281,264,233,189,140,96,63,42,29,16,-7,-46,-97,-145,-176,-183,-174,-164,-166,-177,
--190,-196,-197,-198,-206,-220,-235,-250,-264,-278,-287,-283,-263,-231,-201,-187,-194,-217,-251,-292,-333,
--370,-393,-398,-390,-380,-376,-382,-390,-395,-397,-403,-418,-443,-468,-486,-495,-498,-504,-518,-539,-558,
--570,-572,-567,-564,-570,-589,-618,-647,-669,-682,-690,-702,-720,-745,-770,-794,-813,-829,-839,-844,-846,
--850,-861,-880,-905,-928,-948,-963,-978,-997,-1020,-1044,-1067,-1087,-1104,-1119,-1133,-1146,-1159,-1171,-1183,-1193,
--1202,-1209,-1215,-1222,-1228,-1233,-1237,-1241,-1246,-1254,-1265,-1280,-1296,-1312,-1326,-1337,-1346,-1354,-1363,-1373,-1383,
--1394,-1403,-1409,-1411,-1410,-1405,-1400,-1397,-1398,-1402,-1409,-1416,-1419,-1420,-1418,-1417,-1416,-1416,-1416,-1416,-1419,
--1422,-1426,-1428,-1428,-1428,-1427,-1426,-1424,-1420,-1415,-1409,-1404,-1399,-1394,-1388,-1384,-1381,-1380,-1378,-1375,-1368,
--1360,-1351,-1344,-1337,-1332,-1325,-1317,-1307,-1298,-1290,-1284,-1279,-1273,-1266,-1257,-1248,-1239,-1233,-1227,-1222,-1215,
--1209,-1204,-1201,-1200,-1200,-1198,-1196,-1194,-1193,-1192,-1191,-1188,-1186,-1185,-1185,-1185,-1183,-1180,-1177,-1174,-1173,
--1171,-1168,-1164,-1161,-1157,-1153,-1149,-1144,-1139,-1136,-1133,-1128,-1122,-1114,-1106,-1100,-1096,-1092,-1087,-1079,-1070,
--1061,-1051,-1044,-1038,-1035,-1031,-1025,-1018,-1010,-1004,-1001,-1000,-999,-997,-994,-992,-990,-989,-987,-983,-978,
--971,-962,-952,-943,-935,-931,-929,-926,-920,-911,-901,-892,-885,-879,-872,-864,-853,-844,-835,-827,-820,
--813,-806,-800,-795,-792,-788,-784,-780,-775,-771,-767,-760,-747,-727,-703,-677,-652,-629,-607,-587,-569,
--557,-549,-545,-539,-529,-516,-505,-498,-496,-494,-484,-464,-438,-412,-392,-378,-364,-348,-331,-315,-302,
--289,-275,-256,-236,-218,-203,-188,-172,-153,-134,-118,-104,-88,-67,-43,-18,4,27,52,81,111,
-136,156,171,187,204,221,237,255,275,299,323,346,370,397,428,458,483,501,517,538,565,
-594,618,637,658,686,718,749,774,796,820,847,872,890,903,922,953,991,1023,1046,1065,1090,
-1118,1133,1117,1073,1028,1012,1037,1090,1151,1215,1293,1392,1498,1584,1630,1647,1672,1734,1831,1934,2007,
-2039,2041,2034,2030,2029,2028,2030,2040,2060,2085,2109,2124,2126,2109,2066,1998,1916,1832,1753,1680,1608,
-1539,1482,1443,1419,1397,1367,1336,1316,1314,1322,1320,1297,1260,1228,1214,1212,1208,1191,1168,1154,1158,
-1174,1190,1196,1194,1188,1183,1170,1138,1082,1003,909,810,715,630,558,498,442,382,315,248,188,
-144,113,90,70,50,32,18,8,-3,-18,-38,-60,-83,-105,-126,-145,-162,-177,-192,-206,-218,
--227,-233,-238,-245,-254,-263,-268,-269,-266,-265,-266,-272,-279,-289,-301,-317,-336,-356,-375,-393,-409,
--426,-443,-462,-484,-510,-539,-567,-591,-611,-631,-651,-672,-689,-700,-707,-712,-718,-725,-727,-724,-717,
--709,-701,-689,-673,-652,-631,-610,-591,-569,-544,-517,-492,-469,-446,-420,-392,-364,-339,-313,-284,-249,
--210,-174,-143,-115,-85,-49,-7,38,87,141,199,259,316,368,415,461,506,551,593,632,672,
-712,753,792,828,862,899,936,974,1011,1049,1087,1127,1165,1198,1228,1258,1293,1332,1372,1411,1450,
-1494,1542,1591,1636,1677,1717,1760,1806,1849,1886,1919,1951,1984,2017,2044,2069,2096,2130,2169,2205,2233,
-2253,2275,2302,2332,2357,2376,2392,2416,2448,2481,2506,2520,2528,2534,2538,2536,2526,2515,2510,2516,2526,
-2530,2526,2520,2518,2520,2517,2505,2488,2473,2466,2463,2455,2441,2423,2410,2402,2393,2378,2362,2350,2346,
-2348,2349,2348,2348,2348,2341,2320,2289,2260,2249,2253,2255,2239,2208,2184,2182,2195,2198,2169,2116,2073,
-2066,2095,2136,2166,2184,2199,2211,2203,2154,2068,1982,1936,1945,1984,2012,1879,1903,1933,1979,2038,2091,
-2121,2127,2124,2126,2133,2131,2112,2087,2075,2087,2118,2147,2164,2172,2184,2209,2242,2269,2287,2300,2320,
-2350,2384,2414,2432,2443,2451,2461,2471,2481,2495,2517,2550,2593,2639,2681,2713,2736,2751,2760,2767,2772,
-2778,2784,2791,2796,2798,2795,2786,2774,2764,2765,2781,2809,2841,2868,2886,2895,2900,2906,2915,2927,2938,
-2951,2963,2974,2984,2992,3001,3013,3029,3049,3069,3086,3098,3109,3122,3138,3158,3182,3207,3233,3258,3281,
-3300,3315,3326,3333,3337,3340,3343,3346,3351,3359,3371,3385,3398,3406,3405,3395,3377,3359,3347,3347,3355,
-3365,3370,3368,3363,3359,3354,3347,3332,3314,3299,3296,3304,3318,3329,3336,3345,3362,3390,3424,3460,3497,
-3538,3586,3638,3690,3741,3793,3849,3905,3952,3983,4001,4020,4058,4118,4190,4251,4288,4301,4305,4312,4327,
-4344,4355,4361,4368,4385,4412,4447,4483,4515,4538,4549,4541,4512,4466,4417,4378,4357,4350,4350,4348,4343,
-4341,4346,4361,4378,4386,4381,4365,4346,4333,4330,4334,4339,4341,4340,4339,4341,4346,4352,4358,4363,4366,
-4368,4366,4360,4352,4341,4328,4312,4294,4276,4260,4247,4238,4231,4225,4221,4216,4208,4193,4168,4134,4095,
-4055,4016,3978,3940,3902,3869,3840,3814,3787,3759,3730,3706,3688,3676,3665,3649,3626,3596,3562,3526,3489,
-3450,3410,3371,3335,3302,3274,3249,3227,3208,3190,3172,3151,3127,3103,3083,3069,3061,3053,3043,3027,3009,
-2992,2978,2968,2959,2954,2951,2951,2949,2942,2928,2911,2896,2886,2880,2872,2862,2849,2835,2821,2805,2786,
-2765,2745,2726,2709,2690,2668,2642,2614,2587,2560,2533,2509,2490,2477,2468,2458,2445,2428,2411,2394,2378,
-2357,2330,2302,2275,2253,2233,2212,2189,2165,2141,2119,2097,2073,2046,2020,1996,1976,1955,1931,1903,1872,
-1842,1816,1794,1771,1746,1716,1682,1647,1612,1574,1531,1482,1428,1375,1330,1296,1271,1249,1226,1199,1166,
-1130,1094,1059,1025,990,951,909,867,826,791,758,724,686,643,598,556,516,478,438,397,356,
-314,272,228,180,132,85,40,-4,-51,-99,-147,-193,-236,-280,-326,-374,-421,-466,-510,-554,-601,
--652,-703,-751,-797,-843,-892,-945,-1000,-1054,-1102,-1143,-1178,-1213,-1250,-1291,-1339,-1393,-1450,-1506,-1554,-1592,
--1619,-1641,-1664,-1695,-1730,-1769,-1807,-1846,-1886,-1928,-1968,-2003,-2035,-2067,-2103,-2144,-2184,-2218,-2246,-2270,-2298,
--2332,-2370,-2407,-2440,-2468,-2494,-2521,-2551,-2581,-2610,-2636,-2663,-2689,-2717,-2744,-2768,-2788,-2805,-2821,-2838,-2856,
--2872,-2887,-2899,-2910,-2923,-2936,-2948,-2960,-2970,-2979,-2987,-2994,-2999,-3006,-3015,-3025,-3033,-3035,-3031,-3024,-3020,
--3020,-3020,-3017,-3011,-3004,-3000,-2999,-3000,-3000,-3000,-3000,-3001,-2999,-2993,-2986,-2983,-2984,-2985,-2980,-2968,-2955,
--2947,-2947,-2948,-2941,-2923,-2900,-2884,-2879,-2879,-2873,-2857,-2832,-2810,-2797,-2791,-2784,-2772,-2756,-2741,-2732,-2729,
--2726,-2719,-2707,-2691,-2676,-2662,-2647,-2630,-2609,-2585,-2560,-2535,-2511,-2488,-2466,-2443,-2420,-2399,-2381,-2363,-2346,
--2327,-2306,-2283,-2257,-2229,-2199,-2169,-2140,-2112,-2084,-2055,-2026,-1996,-1968,-1942,-1915,-1889,-1863,-1842,-1825,-1810,
--1788,-1757,-1719,-1684,-1661,-1652,-1647,-1638,-1619,-1598,-1583,-1578,-1576,-1566,-1544,-1518,-1500,-1495,-1498,-1499,-1491,
--1476,-1462,-1445,-1409,-1333,-1211,-1056,-897,-759,-654,-579,-522,-477,-441,-418,-405,-404,-416,-448,-505,-584,
--673,-757,-822,-862,-880,-881,-874,-861,-847,-830,-811,-791,-773,-759,-750,-740,-727,-709,-690,-674,-664,
--654,-642,-623,-599,-573,-548,-525,-504,-487,-475,-467,-461,-453,-443,-433,-424,-413,-396,-372,-348,-332,
--329,-335,-335,-321,-288,-246,-207,-177,-154,-132,-105,-73,-39,-8,17,40,63,92,128,167,201,
-224,233,239,257,294,346,399,434,450,457,474,514,572,635,689,727,754,778,804,834,865,
-894,921,947,975,1010,1056,1114,1180,1239,1276,1283,1263,1230,1197,1167,1137,1100,1063,1040,1049,1093,
-1163,1234,1287,1319,1336,1351,1370,1395,1421,1446,1466,1481,1487,1483,1471,1456,1443,1432,1419,1403,1386,
-1370,1359,1349,1338,1320,1298,1275,1257,1243,1233,1221,1204,1179,1146,1107,1067,1030,997,962,921,874,
-822,770,718,665,607,546,486,431,382,337,296,261,237,222,210,194,166,128,86,44,7,
--23,-48,-70,-96,-131,-173,-215,-247,-260,-257,-247,-243,-245,-252,-258,-261,-262,-265,-270,-277,-287,
--302,-322,-341,-350,-346,-332,-314,-300,-291,-286,-289,-306,-340,-385,-428,-454,-459,-449,-437,-431,-430,
--432,-436,-443,-458,-480,-504,-522,-531,-534,-538,-550,-568,-590,-605,-611,-608,-603,-606,-621,-646,-674,
--697,-713,-727,-742,-760,-780,-801,-823,-844,-865,-881,-890,-892,-893,-900,-916,-938,-961,-980,-996,-1009,
--1024,-1041,-1061,-1081,-1101,-1118,-1133,-1146,-1157,-1167,-1179,-1190,-1200,-1209,-1217,-1226,-1236,-1245,-1252,-1256,-1260,
--1265,-1273,-1285,-1299,-1315,-1332,-1346,-1358,-1365,-1370,-1374,-1380,-1388,-1398,-1408,-1417,-1425,-1431,-1432,-1428,-1422,
--1418,-1417,-1421,-1427,-1431,-1432,-1430,-1426,-1423,-1420,-1418,-1418,-1421,-1426,-1432,-1436,-1438,-1437,-1434,-1431,-1428,
--1426,-1424,-1422,-1419,-1413,-1405,-1397,-1391,-1388,-1388,-1387,-1383,-1378,-1372,-1366,-1359,-1353,-1346,-1338,-1331,-1323,
--1314,-1304,-1295,-1287,-1280,-1273,-1266,-1257,-1248,-1241,-1235,-1228,-1219,-1209,-1201,-1197,-1196,-1196,-1194,-1190,-1186,
--1183,-1182,-1180,-1178,-1175,-1173,-1171,-1169,-1166,-1161,-1157,-1155,-1155,-1155,-1155,-1153,-1150,-1147,-1144,-1140,-1135,
--1130,-1126,-1123,-1118,-1111,-1102,-1093,-1087,-1083,-1081,-1077,-1070,-1062,-1054,-1046,-1040,-1035,-1030,-1025,-1019,-1011,
--1004,-999,-996,-997,-998,-999,-997,-993,-990,-986,-983,-980,-975,-968,-959,-949,-941,-935,-932,-929,-925,
--917,-907,-896,-886,-879,-874,-870,-865,-859,-851,-842,-831,-819,-806,-795,-786,-778,-772,-766,-761,-756,
--753,-750,-747,-740,-729,-711,-689,-667,-647,-629,-610,-589,-567,-549,-540,-539,-541,-538,-528,-513,-499,
--490,-481,-467,-446,-419,-394,-375,-362,-351,-338,-322,-307,-295,-282,-268,-250,-232,-216,-202,-188,-172,
--152,-133,-117,-104,-88,-68,-44,-21,1,23,49,79,111,139,160,178,194,210,226,244,262,
-283,305,327,349,373,400,430,458,480,498,518,544,574,601,622,639,660,688,720,749,771,
-791,815,843,870,890,907,929,960,994,1021,1041,1062,1091,1120,1129,1102,1051,1007,1003,1046,1111,
-1170,1218,1272,1353,1455,1552,1616,1649,1680,1737,1825,1919,1986,2012,2010,2001,2001,2010,2020,2026,2028,
-2029,2031,2033,2032,2025,2002,1958,1893,1816,1739,1672,1612,1554,1500,1455,1425,1403,1378,1343,1303,1275,
-1267,1271,1271,1255,1227,1202,1192,1191,1186,1170,1149,1138,1144,1160,1173,1175,1169,1160,1149,1125,1076,
-998,900,797,702,623,559,506,458,408,350,286,223,172,137,113,93,72,50,32,20,11,
-0,-15,-38,-63,-88,-112,-136,-157,-175,-189,-200,-209,-216,-222,-224,-226,-231,-240,-251,-259,-262,
--262,-263,-269,-279,-289,-298,-304,-311,-319,-330,-343,-357,-373,-391,-412,-436,-462,-490,-517,-542,-565,
--586,-608,-631,-653,-671,-684,-693,-702,-711,-718,-719,-714,-706,-698,-690,-681,-668,-650,-630,-612,-594,
--574,-550,-524,-498,-474,-450,-423,-393,-362,-333,-305,-274,-240,-204,-170,-140,-110,-78,-41,0,42,
-88,141,201,262,320,372,418,464,511,559,604,645,684,723,763,801,836,870,905,940,976,
-1011,1046,1082,1119,1154,1188,1220,1255,1293,1335,1376,1415,1456,1500,1549,1596,1639,1678,1716,1758,1803,
-1847,1886,1920,1952,1985,2015,2041,2063,2089,2123,2162,2198,2226,2249,2273,2303,2334,2361,2381,2399,2423,
-2452,2482,2504,2517,2526,2535,2542,2541,2531,2517,2511,2515,2523,2527,2523,2517,2515,2516,2514,2504,2489,
-2477,2471,2467,2458,2441,2423,2410,2402,2394,2383,2368,2357,2350,2347,2343,2339,2338,2338,2333,2314,2284,
-2257,2246,2249,2250,2237,2216,2207,2222,2243,2239,2191,2119,2071,2079,2137,2198,2218,2189,2134,2085,2048,
-2010,1958,1898,1854,1841,1855,1879,1902,1928,1973,2034,2099,2147,2162,2148,2126,2115,2119,2124,2121,2110,
-2108,2123,2151,2178,2195,2205,2219,2245,2279,2308,2328,2345,2369,2402,2440,2469,2483,2485,2481,2479,2483,
-2497,2522,2562,2614,2667,2711,2737,2746,2745,2743,2747,2756,2768,2777,2783,2786,2785,2783,2776,2767,2757,
-2753,2761,2783,2815,2849,2877,2894,2902,2908,2916,2927,2941,2954,2966,2977,2986,2994,3004,3016,3033,3052,
-3073,3091,3104,3114,3124,3137,3154,3175,3198,3220,3241,3261,3279,3294,3307,3315,3320,3324,3326,3330,3336,
-3345,3356,3369,3382,3392,3395,3389,3374,3356,3341,3335,3339,3348,3356,3359,3358,3355,3353,3348,3338,3325,
-3312,3308,3315,3329,3341,3346,3347,3355,3377,3413,3458,3503,3545,3584,3627,3676,3732,3794,3860,3922,3971,
-4002,4017,4033,4066,4127,4206,4282,4335,4357,4360,4361,4372,4390,4407,4415,4418,4422,4435,4456,4482,4509,
-4535,4559,4576,4578,4557,4514,4461,4413,4381,4367,4364,4365,4366,4369,4377,4390,4402,4408,4403,4389,4371,
-4355,4344,4339,4338,4339,4343,4349,4356,4362,4367,4372,4378,4384,4389,4391,4388,4380,4368,4352,4333,4313,
-4293,4277,4266,4260,4257,4256,4254,4250,4241,4224,4199,4168,4132,4094,4056,4017,3979,3943,3911,3882,3855,
-3826,3795,3766,3741,3723,3709,3694,3674,3648,3617,3584,3548,3510,3469,3427,3388,3352,3320,3291,3265,3243,
-3225,3210,3194,3175,3152,3129,3110,3097,3088,3078,3065,3048,3031,3018,3007,2997,2987,2980,2977,2977,2975,
-2966,2950,2932,2919,2912,2909,2903,2892,2879,2868,2859,2849,2834,2812,2786,2761,2738,2716,2694,2671,2646,
-2623,2600,2580,2561,2546,2534,2524,2511,2495,2476,2457,2439,2420,2397,2371,2344,2319,2297,2276,2253,2226,
-2199,2174,2153,2135,2114,2091,2065,2039,2015,1991,1965,1937,1908,1882,1858,1837,1814,1786,1752,1714,1674,
-1635,1595,1553,1506,1459,1415,1380,1353,1331,1307,1279,1245,1207,1169,1132,1097,1062,1026,987,947,908,
-871,838,805,769,728,684,641,600,561,521,478,436,395,357,318,276,230,182,135,91,47,
-1,-47,-97,-144,-189,-232,-277,-324,-372,-417,-461,-505,-552,-602,-652,-700,-744,-789,-836,-888,-942,
--994,-1041,-1080,-1116,-1151,-1189,-1234,-1286,-1342,-1398,-1449,-1492,-1524,-1548,-1571,-1596,-1628,-1666,-1707,-1749,-1790,
--1830,-1870,-1907,-1943,-1978,-2014,-2054,-2095,-2133,-2164,-2189,-2212,-2241,-2277,-2318,-2359,-2394,-2422,-2447,-2473,-2502,
--2533,-2563,-2591,-2617,-2643,-2670,-2695,-2717,-2735,-2752,-2771,-2792,-2814,-2834,-2848,-2860,-2870,-2882,-2895,-2908,-2920,
--2932,-2944,-2954,-2962,-2968,-2972,-2979,-2987,-2995,-2998,-2997,-2993,-2991,-2990,-2989,-2985,-2977,-2970,-2967,-2966,-2967,
--2967,-2967,-2967,-2966,-2965,-2962,-2959,-2959,-2961,-2960,-2953,-2938,-2923,-2915,-2915,-2915,-2907,-2889,-2869,-2855,-2851,
--2852,-2848,-2833,-2812,-2791,-2778,-2769,-2760,-2746,-2730,-2717,-2710,-2707,-2706,-2700,-2690,-2677,-2663,-2649,-2636,-2621,
--2603,-2579,-2552,-2525,-2499,-2477,-2457,-2435,-2413,-2390,-2370,-2351,-2333,-2314,-2293,-2270,-2246,-2219,-2190,-2159,-2129,
--2103,-2080,-2056,-2029,-1998,-1967,-1939,-1915,-1893,-1871,-1848,-1826,-1802,-1777,-1747,-1716,-1691,-1676,-1672,-1671,-1662,
--1644,-1620,-1601,-1590,-1583,-1572,-1552,-1529,-1510,-1501,-1498,-1495,-1488,-1479,-1474,-1467,-1445,-1393,-1301,-1177,-1039,
--908,-795,-705,-635,-582,-540,-509,-487,-480,-493,-534,-601,-685,-771,-842,-889,-909,-906,-888,-865,-846,
--837,-836,-836,-832,-822,-812,-803,-796,-786,-769,-748,-725,-706,-691,-677,-661,-640,-617,-593,-570,-550,
--536,-529,-527,-524,-518,-505,-490,-473,-455,-436,-415,-400,-394,-397,-401,-395,-373,-338,-301,-271,-246,
--223,-197,-166,-136,-108,-82,-57,-30,-3,23,50,79,108,137,162,185,214,253,298,337,359,
-363,361,371,403,454,512,562,600,629,658,691,728,765,801,838,878,925,978,1039,1103,1164,
-1211,1236,1235,1214,1187,1164,1151,1144,1137,1131,1133,1157,1205,1268,1329,1371,1388,1388,1384,1387,1400,
-1417,1434,1445,1451,1450,1445,1435,1422,1406,1389,1369,1348,1328,1309,1294,1281,1265,1246,1224,1201,1184,
-1177,1178,1184,1187,1177,1153,1115,1070,1023,978,933,886,837,787,734,677,615,549,482,420,367,
-320,277,238,205,179,158,136,107,69,27,-12,-49,-81,-112,-140,-167,-191,-215,-243,-272,-298,
--318,-327,-329,-328,-325,-324,-323,-324,-327,-332,-338,-345,-354,-366,-379,-388,-391,-391,-392,-396,-397,
--387,-361,-328,-308,-316,-357,-416,-469,-501,-507,-498,-487,-482,-483,-488,-496,-509,-527,-545,-561,-570,
--574,-577,-584,-596,-612,-625,-633,-637,-642,-652,-670,-691,-710,-727,-741,-757,-776,-795,-813,-829,-847,
--868,-892,-913,-927,-933,-935,-940,-951,-969,-988,-1007,-1023,-1038,-1051,-1064,-1078,-1092,-1109,-1125,-1140,-1153,
--1164,-1174,-1184,-1194,-1202,-1210,-1220,-1233,-1249,-1262,-1271,-1276,-1280,-1286,-1295,-1308,-1322,-1336,-1350,-1363,-1374,
--1383,-1388,-1391,-1395,-1399,-1405,-1412,-1423,-1435,-1447,-1455,-1456,-1450,-1441,-1434,-1433,-1435,-1436,-1435,-1432,-1427,
--1423,-1421,-1420,-1421,-1424,-1430,-1435,-1440,-1442,-1442,-1438,-1434,-1431,-1428,-1428,-1427,-1425,-1421,-1413,-1405,-1400,
--1398,-1399,-1399,-1397,-1393,-1388,-1383,-1376,-1367,-1357,-1349,-1342,-1336,-1329,-1318,-1305,-1293,-1284,-1277,-1270,-1262,
--1253,-1245,-1238,-1230,-1220,-1209,-1200,-1195,-1194,-1194,-1191,-1186,-1180,-1176,-1173,-1172,-1169,-1165,-1161,-1159,-1157,
--1153,-1148,-1143,-1141,-1142,-1145,-1146,-1146,-1145,-1143,-1140,-1135,-1129,-1123,-1119,-1115,-1110,-1104,-1095,-1087,-1080,
--1076,-1072,-1067,-1060,-1054,-1047,-1042,-1036,-1030,-1023,-1017,-1011,-1006,-1001,-997,-995,-995,-997,-998,-997,-993,
--989,-984,-980,-976,-973,-968,-961,-954,-947,-941,-935,-930,-923,-914,-903,-890,-879,-871,-865,-863,-861,
--859,-853,-844,-832,-820,-808,-796,-784,-772,-761,-752,-744,-739,-735,-732,-729,-723,-713,-696,-675,-655,
--639,-625,-608,-582,-551,-522,-506,-507,-519,-531,-533,-521,-502,-482,-463,-445,-426,-406,-388,-374,-362,
--350,-336,-320,-305,-292,-280,-266,-250,-234,-219,-206,-191,-173,-154,-135,-120,-106,-90,-70,-46,-21,
-2,26,53,83,113,140,161,179,196,214,232,250,269,288,308,328,348,372,399,429,455,
-477,497,519,546,576,601,620,637,660,689,719,743,759,776,799,829,859,883,905,932,966,
-1000,1026,1044,1064,1091,1114,1114,1079,1025,989,1001,1059,1132,1186,1215,1246,1307,1402,1504,1583,1631,
-1670,1727,1808,1891,1949,1971,1967,1963,1972,1992,2013,2022,2018,2002,1980,1955,1932,1908,1879,1838,1784,
-1721,1660,1606,1558,1513,1470,1433,1407,1385,1357,1316,1270,1233,1218,1219,1221,1214,1197,1182,1175,1174,
-1168,1153,1137,1129,1135,1148,1154,1150,1138,1123,1101,1060,992,900,799,707,634,580,535,492,442,
-385,321,257,201,159,131,112,93,71,49,31,20,12,2,-14,-37,-63,-90,-118,-145,-170,
--187,-197,-202,-205,-210,-214,-217,-217,-220,-227,-239,-249,-255,-257,-260,-268,-280,-292,-301,-305,-307,
--311,-317,-325,-335,-347,-364,-387,-414,-443,-472,-498,-521,-544,-566,-588,-610,-630,-647,-660,-672,-684,
--696,-703,-705,-701,-694,-688,-682,-673,-659,-641,-622,-606,-592,-576,-556,-531,-505,-479,-454,-427,-396,
--363,-330,-297,-263,-228,-193,-161,-131,-101,-68,-32,3,40,81,131,188,249,308,361,410,458,
-508,557,603,645,685,726,768,808,845,879,912,945,978,1012,1046,1083,1122,1161,1198,1233,1269,
-1307,1347,1387,1426,1466,1510,1556,1602,1642,1679,1715,1755,1799,1841,1879,1913,1946,1978,2009,2036,2060,
-2087,2121,2158,2194,2224,2249,2276,2307,2339,2366,2387,2407,2431,2459,2486,2506,2519,2530,2542,2550,2548,
-2536,2519,2510,2513,2522,2527,2525,2521,2520,2521,2519,2512,2500,2490,2484,2477,2466,2448,2429,2415,2408,
-2402,2393,2384,2377,2373,2367,2357,2344,2334,2329,2322,2305,2280,2256,2245,2245,2246,2239,2233,2243,2272,
-2298,2290,2233,2156,2106,2115,2167,2210,2199,2133,2054,2007,2004,2021,2022,1993,1948,1911,1895,1902,1982,
-2000,2034,2077,2118,2145,2146,2128,2107,2099,2107,2119,2125,2122,2123,2136,2161,2187,2206,2219,2237,2263,
-2295,2324,2347,2368,2394,2427,2460,2483,2490,2484,2473,2467,2471,2489,2525,2575,2633,2686,2722,2736,2734,
-2727,2727,2737,2752,2766,2773,2773,2769,2766,2765,2765,2765,2763,2763,2768,2784,2810,2843,2874,2898,2914,
-2923,2929,2936,2946,2958,2971,2982,2993,3005,3019,3038,3060,3084,3104,3120,3130,3137,3145,3155,3170,3187,
-3206,3226,3245,3261,3274,3284,3292,3301,3310,3319,3328,3335,3341,3348,3356,3366,3376,3384,3384,3378,3365,
-3350,3339,3334,3336,3342,3347,3350,3351,3349,3346,3340,3330,3321,3317,3323,3338,3354,3365,3369,3369,3377,
-3400,3441,3493,3550,3602,3647,3688,3730,3783,3848,3920,3985,4030,4050,4059,4079,4131,4212,4304,4378,4417,
-4425,4420,4422,4437,4458,4475,4483,4487,4494,4508,4524,4538,4548,4557,4567,4574,4572,4553,4518,4475,4436,
-4410,4396,4392,4391,4390,4391,4394,4401,4410,4416,4415,4408,4395,4380,4366,4355,4350,4350,4355,4363,4371,
-4376,4378,4380,4384,4391,4399,4403,4402,4392,4376,4357,4337,4318,4301,4287,4277,4273,4272,4275,4276,4273,
-4264,4246,4222,4194,4162,4128,4093,4056,4021,3988,3957,3928,3896,3863,3830,3802,3781,3763,3746,3725,3699,
-3669,3638,3605,3570,3532,3490,3448,3409,3374,3341,3309,3280,3255,3237,3224,3212,3197,3178,3157,3139,3124,
-3112,3099,3084,3068,3053,3042,3031,3021,3010,3002,2999,2999,2996,2985,2967,2948,2935,2931,2931,2929,2921,
-2911,2903,2897,2891,2877,2853,2824,2795,2771,2751,2733,2714,2694,2673,2654,2637,2620,2605,2590,2574,2556,
-2537,2518,2498,2479,2458,2436,2412,2388,2365,2342,2319,2292,2262,2233,2208,2188,2170,2152,2130,2106,2080,
-2054,2028,2002,1976,1950,1925,1901,1877,1849,1817,1779,1737,1696,1656,1618,1580,1543,1507,1473,1443,1414,
-1385,1352,1315,1277,1241,1206,1171,1136,1098,1059,1020,982,946,911,878,842,804,764,722,682,643,
-604,562,518,474,433,395,358,317,272,225,179,137,95,50,2,-47,-95,-141,-186,-232,-279,
--326,-370,-413,-456,-501,-550,-599,-646,-691,-736,-783,-832,-883,-931,-975,-1014,-1049,-1085,-1125,-1172,-1225,
--1281,-1335,-1383,-1422,-1454,-1480,-1504,-1532,-1564,-1603,-1645,-1689,-1731,-1771,-1808,-1844,-1881,-1919,-1959,-1999,-2038,
--2072,-2103,-2130,-2159,-2192,-2231,-2272,-2310,-2344,-2372,-2398,-2426,-2456,-2486,-2515,-2542,-2567,-2593,-2620,-2644,-2664,
--2681,-2697,-2717,-2742,-2768,-2791,-2809,-2821,-2832,-2844,-2856,-2868,-2879,-2891,-2905,-2920,-2931,-2938,-2942,-2946,-2950,
--2954,-2955,-2954,-2954,-2955,-2956,-2955,-2950,-2941,-2934,-2932,-2934,-2938,-2939,-2936,-2932,-2929,-2927,-2926,-2927,-2930,
--2932,-2929,-2920,-2905,-2892,-2885,-2885,-2883,-2874,-2857,-2838,-2825,-2822,-2822,-2819,-2808,-2792,-2776,-2763,-2752,-2739,
--2724,-2710,-2699,-2694,-2692,-2690,-2685,-2677,-2664,-2650,-2635,-2620,-2606,-2588,-2566,-2539,-2511,-2485,-2464,-2444,-2423,
--2401,-2378,-2358,-2339,-2320,-2299,-2277,-2253,-2231,-2207,-2180,-2150,-2120,-2095,-2073,-2052,-2026,-1995,-1962,-1933,-1911,
--1893,-1874,-1851,-1825,-1798,-1770,-1744,-1721,-1703,-1692,-1687,-1683,-1673,-1656,-1636,-1618,-1605,-1594,-1581,-1565,-1548,
--1535,-1524,-1515,-1503,-1491,-1483,-1482,-1480,-1467,-1428,-1359,-1264,-1154,-1041,-934,-838,-759,-697,-648,-608,-578,
--565,-579,-624,-696,-780,-859,-918,-949,-951,-928,-890,-851,-824,-817,-827,-844,-855,-857,-852,-847,-843,
--835,-819,-794,-767,-744,-727,-714,-700,-682,-660,-638,-619,-605,-599,-598,-598,-594,-581,-561,-536,-512,
--490,-472,-458,-451,-452,-457,-457,-446,-421,-391,-363,-341,-321,-296,-266,-234,-205,-178,-150,-119,-86,
--59,-41,-26,-7,23,62,101,135,165,196,231,266,290,298,291,284,289,312,350,397,445,
-492,538,584,632,680,731,786,845,908,970,1028,1078,1116,1140,1151,1151,1148,1146,1149,1157,1164,
-1167,1167,1172,1190,1225,1272,1318,1349,1360,1355,1344,1339,1342,1349,1355,1357,1355,1352,1349,1344,1334,
-1319,1300,1281,1262,1245,1230,1214,1197,1180,1161,1140,1121,1106,1102,1109,1124,1140,1145,1132,1100,1054,
-1000,943,888,834,781,728,671,610,543,476,413,358,310,268,227,189,155,124,93,54,6,
--47,-98,-138,-167,-190,-213,-238,-262,-282,-297,-309,-323,-341,-362,-382,-397,-405,-406,-403,-399,-399,
--402,-408,-415,-423,-431,-438,-441,-437,-429,-425,-433,-451,-467,-462,-425,-366,-312,-290,-314,-375,-446,
--504,-536,-546,-546,-547,-550,-555,-561,-567,-575,-586,-597,-606,-612,-618,-624,-632,-639,-644,-649,-657,
--673,-697,-722,-743,-755,-761,-768,-782,-803,-825,-844,-859,-875,-894,-916,-936,-951,-959,-964,-971,-981,
--995,-1011,-1028,-1045,-1062,-1076,-1087,-1095,-1104,-1115,-1129,-1145,-1160,-1173,-1183,-1192,-1198,-1202,-1208,-1220,-1237,
--1258,-1277,-1289,-1296,-1301,-1308,-1319,-1332,-1345,-1356,-1366,-1377,-1389,-1400,-1408,-1413,-1416,-1417,-1419,-1423,-1432,
--1446,-1462,-1475,-1479,-1475,-1465,-1456,-1450,-1446,-1442,-1436,-1428,-1423,-1420,-1420,-1422,-1426,-1430,-1434,-1438,-1440,
--1440,-1439,-1436,-1432,-1427,-1423,-1421,-1420,-1420,-1419,-1416,-1412,-1409,-1408,-1409,-1408,-1404,-1399,-1394,-1389,-1383,
--1373,-1363,-1355,-1349,-1345,-1338,-1326,-1312,-1298,-1287,-1280,-1272,-1262,-1251,-1241,-1233,-1225,-1216,-1206,-1197,-1191,
--1189,-1188,-1186,-1181,-1175,-1171,-1167,-1163,-1158,-1152,-1148,-1147,-1146,-1144,-1139,-1134,-1132,-1133,-1135,-1137,-1138,
--1137,-1135,-1133,-1129,-1124,-1118,-1113,-1109,-1104,-1098,-1091,-1085,-1079,-1074,-1068,-1060,-1052,-1046,-1041,-1037,-1031,
--1024,-1016,-1010,-1006,-1003,-1000,-997,-995,-994,-994,-994,-993,-989,-985,-981,-978,-974,-970,-966,-962,-957,
--951,-944,-936,-928,-920,-913,-903,-891,-879,-869,-863,-861,-860,-856,-848,-837,-827,-818,-810,-801,-789,
--775,-761,-748,-738,-730,-722,-717,-712,-707,-697,-682,-661,-642,-627,-616,-602,-578,-544,-509,-486,-484,
--499,-518,-527,-518,-495,-467,-443,-425,-412,-403,-395,-387,-376,-362,-344,-327,-311,-297,-284,-271,-256,
--241,-226,-211,-194,-175,-157,-141,-127,-112,-95,-73,-47,-21,4,31,59,88,115,138,158,177,
-197,218,239,258,276,294,311,328,347,370,397,426,454,477,499,523,550,577,600,619,638,
-663,692,718,737,750,766,791,822,853,878,902,932,967,1002,1027,1043,1058,1079,1095,1089,1053,
-1007,984,1009,1074,1144,1188,1203,1219,1266,1351,1449,1533,1594,1648,1714,1794,1866,1909,1920,1915,1917,
-1938,1969,1995,2005,1995,1969,1934,1893,1852,1815,1780,1742,1699,1652,1604,1560,1519,1480,1443,1412,1388,
-1365,1334,1289,1239,1197,1176,1174,1181,1182,1175,1166,1160,1156,1149,1137,1124,1119,1123,1132,1135,1128,
-1112,1087,1048,988,904,809,720,655,613,583,549,501,437,364,292,227,176,141,119,104,88,
-69,50,34,23,14,1,-16,-38,-63,-91,-121,-153,-179,-196,-203,-203,-204,-208,-213,-215,-215,
--216,-222,-233,-244,-251,-253,-255,-262,-273,-285,-295,-301,-304,-308,-314,-321,-328,-338,-353,-374,-400,
--427,-455,-480,-503,-525,-547,-568,-587,-603,-617,-631,-644,-659,-672,-681,-684,-683,-681,-678,-673,-662,
--645,-624,-605,-592,-583,-573,-556,-534,-508,-482,-456,-430,-400,-367,-332,-296,-259,-223,-189,-157,-126,
--94,-60,-25,8,43,81,127,181,240,298,353,404,453,503,552,597,639,681,724,768,810,
-848,882,915,947,979,1013,1050,1091,1135,1180,1221,1258,1292,1327,1364,1402,1441,1480,1522,1565,1607,
-1647,1683,1720,1760,1800,1838,1873,1906,1939,1974,2008,2038,2066,2095,2129,2166,2201,2231,2258,2285,2315,
-2344,2369,2389,2409,2433,2462,2489,2510,2525,2538,2550,2557,2552,2537,2521,2512,2516,2527,2536,2538,2537,
-2538,2541,2541,2535,2524,2512,2503,2492,2477,2459,2442,2431,2425,2419,2411,2404,2401,2401,2398,2386,2368,
-2351,2340,2332,2318,2296,2274,2259,2255,2255,2255,2259,2279,2311,2335,2325,2271,2200,2152,2150,2175,2186,
-2155,2096,2053,2064,2125,2190,2213,2176,2102,2031,1990,1982,2037,2057,2080,2099,2114,2122,2122,2113,2105,
-2105,2113,2121,2122,2116,2113,2122,2143,2169,2191,2209,2228,2252,2279,2305,2330,2355,2383,2415,2442,2459,
-2461,2453,2445,2444,2455,2481,2520,2568,2618,2658,2683,2694,2698,2704,2717,2735,2751,2759,2758,2752,2747,
-2748,2756,2768,2779,2785,2785,2783,2785,2798,2824,2858,2893,2919,2933,2938,2940,2946,2958,2974,2992,3008,
-3024,3042,3065,3092,3117,3138,3152,3159,3165,3170,3178,3187,3199,3214,3231,3248,3263,3272,3277,3282,3291,
-3304,3319,3332,3340,3345,3349,3355,3363,3372,3377,3377,3371,3362,3350,3339,3332,3329,3330,3335,3340,3343,
-3343,3338,3330,3324,3322,3329,3344,3361,3378,3389,3395,3400,3410,3432,3473,3531,3599,3665,3719,3759,3793,
-3837,3899,3974,4043,4087,4106,4116,4146,4213,4307,4401,4467,4492,4489,4481,4485,4502,4521,4532,4536,4540,
-4551,4568,4584,4593,4594,4589,4582,4572,4555,4529,4496,4465,4441,4429,4424,4422,4419,4415,4411,4411,4415,
-4422,4428,4430,4426,4416,4404,4391,4382,4377,4376,4379,4384,4389,4391,4391,4389,4389,4391,4396,4400,4398,
-4387,4370,4351,4333,4318,4306,4294,4284,4277,4275,4278,4282,4284,4278,4264,4244,4218,4190,4158,4125,4092,
-4060,4030,4001,3968,3933,3897,3866,3842,3824,3806,3784,3756,3724,3691,3659,3627,3592,3553,3511,3469,3430,
-3394,3361,3328,3297,3272,3254,3242,3232,3221,3205,3186,3166,3148,3133,3118,3104,3089,3076,3064,3052,3040,
-3028,3018,3014,3012,3008,2997,2980,2963,2953,2950,2953,2955,2952,2946,2940,2934,2926,2911,2888,2860,2835,
-2816,2803,2792,2777,2758,2737,2716,2698,2680,2661,2641,2619,2597,2576,2557,2538,2518,2497,2476,2454,2432,
-2409,2384,2357,2328,2299,2273,2250,2230,2210,2189,2167,2144,2120,2095,2070,2044,2019,1993,1967,1939,1909,
-1876,1840,1802,1761,1721,1683,1648,1617,1588,1560,1532,1502,1468,1429,1387,1345,1306,1272,1241,1210,1174,
-1136,1096,1057,1020,985,949,911,873,834,796,759,723,686,647,605,562,519,478,438,398,356,
-312,266,222,180,138,94,48,1,-45,-91,-138,-186,-234,-281,-326,-368,-409,-453,-498,-546,-593,
--640,-688,-735,-782,-828,-873,-914,-952,-989,-1026,-1068,-1115,-1168,-1221,-1271,-1315,-1352,-1383,-1412,-1440,-1470,
--1503,-1542,-1585,-1630,-1673,-1713,-1749,-1785,-1824,-1865,-1906,-1944,-1978,-2009,-2041,-2074,-2110,-2148,-2186,-2224,-2258,
--2290,-2320,-2348,-2377,-2408,-2438,-2466,-2492,-2518,-2545,-2571,-2596,-2615,-2631,-2646,-2667,-2692,-2720,-2745,-2765,-2779,
--2792,-2803,-2813,-2823,-2833,-2845,-2861,-2878,-2893,-2902,-2907,-2910,-2912,-2913,-2913,-2912,-2913,-2917,-2921,-2921,-2916,
--2907,-2900,-2900,-2905,-2910,-2911,-2907,-2900,-2893,-2890,-2890,-2892,-2895,-2895,-2892,-2883,-2872,-2864,-2860,-2859,-2856,
--2845,-2828,-2812,-2800,-2796,-2793,-2789,-2781,-2771,-2761,-2750,-2738,-2723,-2707,-2694,-2685,-2680,-2678,-2674,-2669,-2662,
--2650,-2636,-2620,-2603,-2588,-2571,-2550,-2525,-2498,-2472,-2450,-2429,-2407,-2384,-2362,-2343,-2327,-2310,-2289,-2265,-2241,
--2219,-2199,-2176,-2148,-2117,-2088,-2064,-2042,-2017,-1987,-1955,-1926,-1904,-1888,-1871,-1851,-1826,-1799,-1772,-1748,-1727,
--1712,-1702,-1695,-1688,-1678,-1664,-1648,-1634,-1622,-1609,-1596,-1582,-1572,-1563,-1553,-1538,-1518,-1499,-1489,-1489,-1490,
--1481,-1449,-1394,-1320,-1233,-1139,-1043,-952,-871,-806,-755,-714,-685,-674,-690,-736,-807,-884,-951,-995,-1010,
--998,-962,-911,-860,-826,-817,-831,-855,-875,-883,-885,-884,-883,-877,-862,-837,-811,-789,-775,-763,-748,
--728,-706,-686,-673,-668,-667,-668,-665,-653,-632,-604,-573,-546,-525,-512,-506,-506,-512,-516,-514,-500,
--476,-449,-424,-404,-384,-362,-334,-305,-274,-240,-201,-160,-124,-102,-94,-90,-75,-41,3,46,76,
-96,116,148,189,224,236,220,183,147,134,158,217,297,380,452,510,560,612,673,744,818,
-887,943,984,1009,1021,1027,1032,1043,1062,1089,1116,1136,1144,1142,1135,1132,1140,1161,1193,1227,1254,
-1268,1270,1264,1256,1251,1247,1240,1231,1222,1215,1213,1210,1204,1192,1177,1164,1155,1148,1140,1128,1112,
-1094,1075,1057,1040,1027,1021,1027,1043,1063,1079,1080,1062,1025,972,910,844,779,714,649,582,512,
-442,377,321,274,233,194,155,117,81,46,7,-42,-100,-161,-213,-251,-274,-291,-308,-328,-349,
--366,-376,-381,-386,-397,-415,-437,-457,-472,-478,-479,-479,-480,-484,-487,-488,-490,-494,-498,-498,-492,
--482,-475,-482,-501,-521,-520,-486,-425,-359,-318,-320,-363,-427,-492,-542,-574,-594,-608,-619,-626,-629,
--630,-629,-630,-632,-635,-641,-650,-661,-671,-674,-673,-671,-677,-697,-729,-761,-784,-793,-793,-794,-805,
--826,-850,-872,-888,-903,-919,-936,-952,-963,-972,-981,-993,-1007,-1020,-1034,-1049,-1068,-1087,-1103,-1113,-1117,
--1120,-1126,-1138,-1154,-1171,-1185,-1196,-1204,-1208,-1210,-1214,-1224,-1243,-1267,-1289,-1305,-1315,-1322,-1331,-1343,-1355,
--1366,-1375,-1383,-1392,-1403,-1414,-1423,-1430,-1433,-1434,-1435,-1438,-1445,-1458,-1474,-1487,-1493,-1492,-1486,-1479,-1471,
--1463,-1452,-1440,-1429,-1422,-1420,-1423,-1429,-1435,-1441,-1445,-1446,-1444,-1440,-1436,-1432,-1428,-1422,-1416,-1411,-1409,
--1410,-1413,-1415,-1416,-1415,-1415,-1413,-1409,-1402,-1394,-1387,-1381,-1376,-1370,-1363,-1356,-1351,-1346,-1339,-1328,-1314,
--1301,-1291,-1282,-1274,-1262,-1249,-1238,-1229,-1221,-1213,-1203,-1192,-1184,-1179,-1177,-1174,-1170,-1165,-1161,-1157,-1152,
--1145,-1139,-1135,-1135,-1136,-1136,-1133,-1129,-1126,-1126,-1126,-1127,-1126,-1124,-1122,-1121,-1119,-1116,-1111,-1107,-1101,
--1096,-1090,-1086,-1082,-1078,-1073,-1066,-1056,-1047,-1040,-1036,-1032,-1026,-1019,-1012,-1006,-1002,-999,-996,-994,-992,
--992,-992,-990,-987,-983,-980,-978,-976,-972,-966,-960,-955,-951,-946,-938,-929,-921,-915,-911,-906,-898,
--888,-878,-873,-870,-866,-858,-845,-831,-820,-814,-810,-803,-793,-778,-763,-750,-738,-726,-712,-700,-690,
--683,-675,-661,-642,-623,-609,-602,-595,-581,-556,-525,-500,-491,-496,-507,-510,-499,-475,-447,-423,-409,
--404,-403,-401,-395,-383,-368,-350,-332,-317,-302,-288,-273,-259,-245,-230,-214,-197,-178,-162,-147,-134,
--118,-99,-75,-49,-23,3,31,60,88,113,134,155,177,201,225,247,266,283,299,315,331,
-349,370,396,424,451,476,501,527,555,582,605,625,646,670,696,719,737,754,777,807,841,
-869,890,909,935,967,997,1018,1030,1042,1059,1073,1069,1043,1010,1000,1031,1094,1158,1197,1212,1228,
-1270,1342,1427,1505,1573,1644,1723,1800,1852,1867,1853,1840,1850,1884,1926,1955,1961,1946,1918,1883,1843,
-1800,1757,1719,1682,1645,1605,1563,1522,1484,1450,1420,1394,1372,1349,1317,1270,1217,1171,1146,1142,1152,
-1160,1160,1154,1146,1140,1132,1122,1112,1106,1108,1114,1118,1115,1100,1067,1010,929,833,740,670,631,
-616,601,568,509,429,343,264,199,152,122,104,92,81,69,55,42,29,16,-1,-21,-44,
--67,-94,-124,-156,-184,-201,-207,-207,-208,-213,-219,-222,-221,-220,-225,-235,-245,-252,-253,-253,-258,
--269,-282,-293,-300,-304,-309,-315,-322,-329,-337,-349,-367,-389,-414,-439,-462,-485,-506,-526,-544,-561,
--576,-591,-605,-620,-636,-649,-658,-663,-664,-663,-661,-655,-644,-626,-605,-588,-577,-570,-562,-549,-528,
--503,-478,-453,-426,-397,-364,-328,-292,-257,-222,-189,-156,-124,-90,-55,-19,15,51,90,134,184,
-240,296,350,401,452,501,548,594,638,683,727,770,810,846,880,914,949,984,1021,1060,1103,
-1149,1195,1237,1274,1308,1342,1379,1417,1456,1495,1535,1576,1616,1656,1695,1733,1771,1807,1841,1873,1905,
-1940,1977,2014,2047,2077,2109,2143,2180,2214,2243,2268,2293,2320,2345,2367,2384,2403,2426,2456,2486,2512,
-2532,2548,2559,2562,2556,2541,2527,2522,2528,2539,2548,2552,2554,2558,2563,2565,2560,2549,2535,2522,2507,
-2490,2473,2461,2454,2450,2444,2434,2426,2424,2426,2426,2416,2399,2382,2370,2364,2354,2337,2316,2299,2291,
-2288,2288,2294,2308,2328,2339,2324,2279,2224,2184,2173,2176,2167,2139,2114,2126,2193,2285,2351,2345,2269,
-2162,2076,2035,2037,2077,2106,2119,2117,2113,2112,2115,2117,2117,2117,2117,2114,2107,2098,2096,2107,2129,
-2156,2178,2194,2208,2224,2245,2270,2296,2326,2357,2387,2411,2423,2425,2423,2425,2436,2459,2491,2530,2569,
-2601,2624,2639,2652,2668,2690,2713,2732,2740,2740,2734,2730,2731,2738,2752,2769,2787,2800,2804,2800,2794,
-2795,2810,2842,2880,2915,2936,2945,2948,2954,2968,2989,3011,3030,3047,3065,3089,3117,3144,3164,3177,3183,
-3188,3194,3201,3207,3214,3222,3235,3251,3265,3274,3279,3283,3292,3306,3320,3331,3337,3340,3345,3353,3363,
-3370,3372,3369,3362,3354,3344,3333,3322,3316,3316,3323,3331,3336,3334,3327,3320,3320,3330,3346,3365,3382,
-3397,3410,3423,3436,3451,3474,3513,3573,3648,3723,3784,3824,3855,3894,3955,4030,4100,4146,4165,4181,4219,
-4294,4392,4481,4536,4550,4542,4536,4543,4559,4571,4573,4566,4562,4569,4584,4601,4614,4619,4618,4609,4591,
-4562,4525,4489,4462,4448,4444,4445,4445,4443,4440,4439,4441,4447,4454,4459,4458,4451,4440,4430,4422,4418,
-4417,4416,4415,4415,4416,4417,4415,4410,4403,4396,4392,4391,4388,4381,4368,4354,4341,4333,4325,4316,4304,
-4292,4285,4284,4288,4292,4291,4282,4266,4244,4217,4187,4155,4124,4094,4066,4036,4003,3969,3937,3910,3890,
-3872,3850,3821,3787,3750,3715,3682,3648,3612,3572,3531,3490,3452,3417,3383,3351,3322,3298,3279,3265,3253,
-3241,3226,3208,3188,3170,3153,3139,3125,3111,3097,3084,3071,3057,3044,3032,3024,3018,3014,3007,2998,2988,
-2982,2980,2982,2984,2983,2979,2973,2967,2957,2942,2922,2899,2881,2869,2862,2854,2841,2821,2798,2774,2753,
-2734,2712,2689,2664,2641,2620,2601,2583,2563,2541,2519,2497,2475,2450,2421,2392,2364,2340,2321,2303,2284,
-2260,2235,2210,2186,2163,2140,2115,2088,2060,2032,2001,1969,1934,1898,1863,1827,1791,1755,1720,1688,1659,
-1632,1606,1578,1546,1510,1469,1425,1382,1344,1311,1280,1248,1212,1173,1134,1097,1061,1025,986,945,904,
-866,831,797,761,724,685,646,606,567,526,484,441,397,354,311,268,224,179,134,90,46,
-3,-40,-87,-136,-185,-232,-277,-320,-364,-408,-452,-498,-545,-594,-643,-691,-736,-777,-817,-856,-895,
--935,-977,-1021,-1069,-1120,-1169,-1214,-1252,-1284,-1314,-1343,-1375,-1408,-1444,-1483,-1526,-1570,-1614,-1654,-1691,-1730,
--1770,-1812,-1853,-1888,-1919,-1950,-1984,-2023,-2062,-2101,-2136,-2169,-2202,-2235,-2268,-2300,-2331,-2361,-2390,-2418,-2445,
--2472,-2498,-2523,-2546,-2566,-2583,-2601,-2623,-2649,-2676,-2700,-2720,-2735,-2748,-2760,-2769,-2778,-2787,-2799,-2816,-2835,
--2851,-2861,-2867,-2871,-2874,-2876,-2877,-2877,-2879,-2883,-2887,-2888,-2883,-2874,-2867,-2867,-2871,-2877,-2878,-2874,-2866,
--2859,-2856,-2857,-2860,-2862,-2861,-2857,-2850,-2844,-2839,-2838,-2835,-2829,-2817,-2803,-2790,-2781,-2775,-2769,-2762,-2754,
--2748,-2741,-2734,-2722,-2706,-2691,-2678,-2671,-2666,-2662,-2657,-2652,-2645,-2636,-2623,-2607,-2590,-2574,-2557,-2537,-2512,
--2485,-2460,-2438,-2416,-2392,-2368,-2346,-2329,-2316,-2303,-2283,-2258,-2233,-2211,-2192,-2172,-2146,-2115,-2084,-2056,-2032,
--2008,-1982,-1954,-1927,-1904,-1886,-1869,-1850,-1828,-1803,-1775,-1748,-1725,-1708,-1701,-1698,-1696,-1690,-1678,-1664,-1651,
--1638,-1624,-1609,-1596,-1587,-1581,-1573,-1557,-1534,-1511,-1499,-1498,-1501,-1496,-1473,-1429,-1370,-1300,-1222,-1137,-1052,
--974,-910,-862,-828,-808,-806,-829,-876,-937,-998,-1044,-1068,-1068,-1046,-1006,-953,-901,-864,-852,-863,-886,
--906,-918,-923,-926,-928,-924,-910,-888,-865,-846,-833,-819,-801,-778,-755,-739,-731,-729,-728,-724,-714,
--696,-670,-640,-610,-587,-572,-567,-568,-573,-579,-583,-579,-564,-538,-506,-475,-449,-430,-413,-394,-370,
--336,-292,-242,-195,-162,-147,-145,-142,-123,-87,-44,-11,6,16,32,63,105,138,138,98,30,
--35,-60,-24,70,198,322,415,472,510,553,616,697,779,845,887,907,913,914,917,928,949,
-982,1019,1050,1066,1067,1057,1045,1039,1043,1057,1079,1105,1131,1150,1160,1160,1151,1138,1122,1105,1087,
-1072,1061,1056,1052,1044,1033,1022,1015,1016,1021,1024,1021,1011,995,979,963,947,934,926,926,937,
-957,977,991,988,966,923,863,792,715,636,557,476,398,325,262,210,167,128,89,51,13,
--23,-60,-103,-153,-208,-259,-301,-330,-351,-367,-385,-404,-423,-438,-448,-455,-463,-473,-488,-507,-524,
--538,-546,-550,-554,-560,-564,-565,-560,-554,-551,-552,-556,-557,-552,-545,-545,-555,-569,-574,-558,-520,
--470,-428,-411,-423,-458,-505,-552,-592,-623,-648,-667,-681,-691,-697,-698,-694,-685,-676,-672,-676,-689,
--703,-710,-709,-703,-705,-721,-751,-785,-809,-819,-819,-820,-830,-850,-874,-895,-912,-927,-940,-953,-965,
--975,-985,-999,-1017,-1034,-1049,-1062,-1076,-1094,-1114,-1132,-1141,-1143,-1143,-1146,-1156,-1171,-1187,-1202,-1213,-1221,
--1226,-1229,-1232,-1241,-1258,-1279,-1301,-1318,-1331,-1342,-1353,-1365,-1377,-1388,-1396,-1404,-1411,-1419,-1427,-1434,-1440,
--1444,-1448,-1450,-1453,-1459,-1468,-1480,-1490,-1497,-1500,-1499,-1496,-1491,-1481,-1467,-1452,-1440,-1433,-1433,-1437,-1444,
--1451,-1458,-1463,-1463,-1457,-1449,-1441,-1435,-1431,-1426,-1419,-1412,-1408,-1409,-1412,-1416,-1418,-1419,-1418,-1415,-1410,
--1400,-1389,-1379,-1372,-1368,-1364,-1359,-1354,-1348,-1342,-1335,-1325,-1313,-1302,-1292,-1284,-1275,-1264,-1252,-1241,-1232,
--1225,-1217,-1206,-1193,-1181,-1173,-1166,-1161,-1156,-1151,-1147,-1144,-1139,-1134,-1130,-1128,-1128,-1130,-1130,-1128,-1124,
--1121,-1119,-1119,-1117,-1115,-1112,-1109,-1108,-1107,-1105,-1102,-1097,-1092,-1086,-1081,-1077,-1075,-1072,-1067,-1060,-1050,
--1041,-1035,-1030,-1026,-1020,-1014,-1008,-1003,-999,-994,-990,-987,-987,-988,-989,-987,-982,-976,-974,-974,-974,
--971,-963,-953,-946,-940,-935,-928,-919,-911,-907,-906,-905,-902,-895,-889,-885,-882,-876,-865,-848,-832,
--819,-812,-807,-799,-786,-771,-758,-746,-735,-721,-702,-683,-667,-656,-647,-634,-617,-599,-585,-578,-576,
--572,-561,-543,-525,-511,-504,-500,-492,-477,-455,-432,-415,-405,-401,-399,-395,-386,-373,-357,-343,-329,
--316,-302,-287,-271,-257,-244,-232,-218,-201,-184,-169,-154,-140,-121,-99,-74,-49,-25,0,26,55,
-82,107,129,151,175,200,224,245,262,279,296,314,332,351,371,394,420,446,472,499,528,
-559,587,612,632,652,674,696,718,739,762,793,830,864,890,906,920,939,963,986,1002,1014,
-1029,1051,1071,1073,1055,1033,1031,1065,1126,1189,1234,1263,1291,1334,1393,1456,1519,1587,1666,1751,1816,
-1835,1807,1760,1733,1750,1803,1861,1895,1897,1877,1849,1821,1790,1754,1714,1675,1637,1601,1561,1521,1483,
-1450,1423,1400,1379,1359,1336,1305,1262,1212,1166,1137,1131,1139,1149,1152,1147,1138,1130,1124,1116,1107,
-1099,1097,1101,1109,1112,1098,1057,986,888,782,692,635,611,606,595,558,492,408,320,241,179,
-134,106,90,82,76,68,58,45,30,12,-8,-31,-53,-76,-100,-129,-160,-187,-205,-213,-216,
--219,-226,-232,-235,-234,-233,-236,-243,-251,-255,-256,-257,-263,-276,-290,-302,-310,-314,-318,-323,-329,
--335,-340,-349,-362,-380,-401,-424,-446,-466,-485,-503,-519,-536,-551,-567,-582,-597,-611,-624,-632,-636,
--637,-634,-631,-625,-615,-600,-584,-570,-559,-551,-541,-527,-508,-487,-464,-441,-414,-384,-351,-316,-282,
--249,-215,-181,-148,-115,-81,-47,-12,24,60,98,139,185,235,289,343,395,446,496,544,592,
-640,688,733,774,809,843,878,916,957,998,1039,1079,1121,1165,1208,1247,1282,1316,1352,1391,1432,
-1472,1511,1550,1590,1630,1670,1708,1745,1780,1813,1845,1876,1910,1946,1985,2023,2057,2088,2121,2156,2192,
-2225,2252,2275,2298,2321,2344,2364,2380,2397,2420,2449,2483,2514,2539,2558,2568,2571,2565,2554,2545,2543,
-2547,2553,2557,2559,2561,2567,2574,2577,2573,2563,2550,2536,2522,2505,2490,2479,2475,2473,2469,2461,2454,
-2451,2452,2452,2443,2428,2411,2401,2397,2392,2381,2365,2349,2338,2333,2328,2324,2323,2323,2317,2298,2266,
-2230,2206,2198,2194,2183,2166,2164,2199,2268,2338,2361,2315,2217,2116,2056,2050,2077,2128,2151,2146,2125,
-2107,2101,2104,2109,2109,2104,2097,2091,2088,2091,2104,2128,2156,2180,2193,2197,2197,2204,2220,2247,2280,
-2315,2348,2376,2394,2403,2406,2411,2422,2445,2478,2515,2552,2580,2598,2608,2617,2631,2655,2683,2706,2718,
-2718,2713,2712,2716,2725,2734,2744,2756,2774,2795,2812,2820,2818,2813,2818,2838,2871,2908,2937,2954,2963,
-2974,2990,3012,3034,3052,3067,3084,3107,3135,3163,3184,3195,3201,3207,3214,3222,3227,3230,3234,3242,3254,
-3268,3279,3288,3296,3306,3316,3325,3329,3331,3333,3340,3351,3362,3366,3362,3353,3345,3339,3333,3325,3315,
-3310,3311,3320,3329,3332,3326,3317,3313,3321,3340,3363,3383,3399,3412,3429,3451,3475,3500,3528,3568,3627,
-3700,3775,3836,3878,3913,3957,4020,4094,4159,4200,4219,4240,4286,4365,4459,4538,4581,4589,4581,4579,4589,
-4604,4611,4604,4588,4575,4570,4576,4588,4603,4618,4628,4629,4615,4586,4548,4512,4486,4473,4469,4468,4467,
-4466,4467,4471,4479,4487,4494,4496,4492,4483,4473,4466,4465,4469,4472,4470,4464,4457,4453,4452,4450,4442,
-4427,4411,4399,4394,4392,4390,4384,4376,4368,4363,4358,4350,4338,4325,4314,4308,4307,4307,4304,4296,4283,
-4265,4242,4215,4187,4157,4128,4099,4069,4038,4009,3985,3965,3947,3924,3894,3858,3819,3782,3747,3712,3675,
-3634,3594,3554,3517,3482,3446,3411,3380,3352,3329,3308,3288,3270,3252,3236,3219,3203,3187,3171,3158,3144,
-3130,3116,3102,3090,3079,3066,3053,3040,3030,3025,3024,3025,3024,3022,3019,3015,3012,3008,3004,2999,2994,
-2987,2976,2961,2945,2931,2921,2914,2905,2891,2871,2847,2822,2800,2780,2759,2736,2712,2689,2669,2651,2632,
-2610,2587,2564,2541,2517,2490,2460,2430,2405,2388,2375,2361,2340,2313,2283,2255,2230,2208,2184,2157,2127,
-2096,2063,2028,1992,1956,1921,1889,1857,1826,1795,1763,1732,1703,1673,1643,1611,1578,1543,1506,1468,1428,
-1391,1356,1322,1287,1249,1209,1170,1133,1098,1062,1022,981,940,903,869,834,797,758,718,681,645,
-608,569,526,481,438,397,357,314,269,221,175,131,91,50,7,-37,-84,-131,-176,-221,-267,
--314,-362,-408,-454,-500,-548,-597,-644,-686,-724,-759,-797,-838,-882,-927,-974,-1023,-1071,-1117,-1158,-1191,
--1219,-1246,-1276,-1311,-1348,-1387,-1428,-1469,-1512,-1553,-1594,-1633,-1674,-1716,-1757,-1795,-1829,-1861,-1895,-1933,-1974,
--2013,-2048,-2080,-2110,-2144,-2181,-2219,-2254,-2285,-2314,-2342,-2370,-2399,-2426,-2450,-2471,-2491,-2510,-2530,-2553,-2579,
--2606,-2632,-2655,-2674,-2690,-2705,-2717,-2727,-2736,-2746,-2760,-2778,-2797,-2813,-2823,-2829,-2833,-2838,-2843,-2846,-2848,
--2849,-2851,-2853,-2853,-2847,-2839,-2833,-2831,-2833,-2837,-2837,-2835,-2830,-2826,-2826,-2828,-2831,-2833,-2831,-2827,-2822,
--2817,-2815,-2814,-2810,-2801,-2789,-2777,-2768,-2762,-2756,-2748,-2738,-2729,-2723,-2720,-2715,-2705,-2690,-2674,-2662,-2654,
--2649,-2645,-2640,-2635,-2629,-2621,-2609,-2594,-2578,-2562,-2545,-2523,-2497,-2470,-2445,-2423,-2402,-2380,-2356,-2335,-2318,
--2306,-2294,-2276,-2252,-2225,-2201,-2181,-2161,-2137,-2109,-2079,-2051,-2026,-2004,-1981,-1957,-1932,-1909,-1886,-1865,-1846,
--1826,-1802,-1773,-1741,-1713,-1696,-1694,-1703,-1710,-1709,-1697,-1680,-1663,-1650,-1636,-1620,-1604,-1593,-1588,-1584,-1573,
--1554,-1531,-1514,-1509,-1512,-1512,-1499,-1471,-1428,-1375,-1312,-1240,-1163,-1090,-1029,-984,-957,-946,-954,-981,-1022,
--1068,-1105,-1125,-1126,-1113,-1088,-1052,-1007,-963,-930,-917,-924,-941,-957,-966,-971,-974,-976,-973,-962,-944,
--923,-904,-887,-869,-848,-825,-805,-793,-786,-782,-776,-766,-752,-732,-708,-681,-657,-641,-635,-637,-644,
--650,-652,-650,-641,-622,-592,-554,-516,-485,-466,-455,-444,-422,-385,-334,-282,-241,-218,-210,-203,-187,
--157,-121,-90,-73,-67,-61,-46,-22,-1,0,-30,-92,-164,-213,-207,-128,12,178,324,418,460,
-478,509,572,660,746,806,833,835,831,833,844,862,886,911,934,949,952,943,931,922,922,
-929,941,956,976,997,1018,1031,1031,1020,1000,976,953,932,914,901,892,882,870,855,842,835,
-839,851,864,872,871,863,852,840,828,816,806,802,806,819,837,853,859,847,813,759,690,
-612,529,444,361,281,210,149,97,53,12,-27,-64,-100,-136,-174,-216,-261,-303,-339,-367,-390,
--410,-432,-453,-472,-487,-500,-513,-526,-540,-556,-572,-588,-602,-611,-617,-621,-627,-635,-643,-646,-643,
--634,-626,-623,-625,-628,-626,-620,-613,-612,-620,-631,-637,-629,-607,-577,-552,-539,-543,-563,-590,-619,
--645,-667,-687,-710,-734,-757,-771,-773,-761,-741,-722,-714,-719,-730,-739,-741,-737,-737,-749,-774,-803,
--827,-839,-843,-846,-857,-876,-898,-918,-933,-946,-959,-971,-982,-993,-1008,-1026,-1048,-1068,-1083,-1094,-1105,
--1121,-1139,-1155,-1165,-1167,-1167,-1171,-1181,-1196,-1211,-1223,-1233,-1242,-1249,-1255,-1261,-1269,-1281,-1297,-1315,-1332,
--1347,-1360,-1373,-1385,-1397,-1408,-1419,-1428,-1435,-1439,-1442,-1444,-1449,-1455,-1461,-1466,-1468,-1471,-1476,-1483,-1491,
--1498,-1504,-1508,-1509,-1506,-1498,-1486,-1473,-1464,-1461,-1462,-1465,-1469,-1473,-1478,-1482,-1481,-1475,-1465,-1454,-1447,
--1443,-1438,-1432,-1425,-1420,-1418,-1419,-1421,-1422,-1421,-1421,-1419,-1415,-1407,-1394,-1382,-1372,-1365,-1360,-1354,-1348,
--1341,-1334,-1328,-1320,-1311,-1301,-1291,-1282,-1273,-1263,-1254,-1246,-1239,-1233,-1224,-1212,-1199,-1186,-1175,-1167,-1159,
--1152,-1145,-1139,-1135,-1131,-1129,-1127,-1126,-1125,-1124,-1122,-1119,-1115,-1112,-1111,-1110,-1108,-1105,-1102,-1100,-1097,
--1095,-1093,-1089,-1085,-1081,-1075,-1071,-1067,-1063,-1060,-1055,-1048,-1040,-1033,-1028,-1024,-1019,-1013,-1007,-1002,-999,
--995,-989,-984,-981,-982,-986,-987,-984,-977,-970,-968,-970,-973,-971,-962,-951,-941,-934,-928,-921,-912,
--904,-899,-898,-899,-897,-893,-889,-885,-882,-876,-865,-851,-836,-824,-815,-805,-792,-775,-758,-745,-735,
--726,-713,-694,-673,-654,-641,-630,-618,-603,-585,-568,-556,-549,-546,-543,-538,-530,-521,-509,-496,-481,
--464,-447,-431,-418,-409,-401,-393,-383,-370,-355,-342,-331,-322,-312,-299,-283,-267,-254,-244,-234,-223,
--208,-191,-175,-159,-141,-120,-95,-70,-47,-25,-3,21,48,74,97,118,140,164,188,210,229,
-246,264,284,306,327,347,368,390,414,438,464,491,522,554,585,611,632,650,668,686,704,
-725,751,783,819,852,877,895,912,932,954,974,990,1009,1036,1069,1093,1096,1078,1057,1060,1099,
-1164,1233,1290,1332,1372,1416,1463,1508,1556,1617,1695,1774,1818,1803,1735,1657,1620,1646,1716,1790,1832,
-1835,1813,1786,1761,1735,1702,1664,1624,1585,1547,1509,1472,1441,1418,1400,1381,1359,1335,1311,1285,1255,
-1218,1182,1156,1145,1147,1151,1150,1142,1132,1125,1121,1118,1110,1100,1094,1096,1104,1108,1091,1042,957,
-850,741,652,598,573,561,542,503,442,368,291,221,163,120,94,80,75,70,63,51,36,
-20,1,-19,-41,-64,-87,-112,-139,-168,-193,-212,-222,-229,-235,-242,-249,-253,-254,-253,-254,-258,
--262,-264,-265,-268,-278,-292,-307,-319,-326,-331,-336,-341,-344,-346,-346,-349,-357,-370,-388,-408,-427,
--446,-462,-478,-494,-509,-524,-538,-550,-561,-572,-583,-592,-597,-598,-594,-589,-583,-575,-566,-555,-543,
--531,-518,-505,-490,-475,-458,-441,-421,-397,-368,-336,-304,-272,-239,-204,-168,-131,-97,-65,-33,0,
-33,68,103,139,179,224,276,331,386,437,486,535,584,636,688,735,776,811,845,882,924,
-970,1016,1060,1102,1143,1184,1223,1260,1294,1329,1366,1406,1447,1487,1526,1565,1605,1645,1683,1718,1750,
-1781,1813,1845,1879,1916,1955,1994,2032,2065,2097,2129,2164,2200,2233,2259,2281,2301,2323,2346,2366,2383,
-2401,2423,2452,2486,2520,2548,2567,2578,2581,2579,2574,2570,2569,2568,2566,2562,2560,2563,2570,2578,2580,
-2576,2567,2557,2548,2538,2524,2510,2498,2493,2492,2492,2490,2486,2485,2484,2482,2471,2455,2437,2426,2420,
-2417,2410,2400,2389,2380,2373,2362,2348,2333,2318,2304,2288,2270,2254,2246,2244,2241,2230,2215,2208,2221,
-2249,2267,2249,2191,2117,2065,2057,2088,2128,2162,2162,2138,2107,2086,2081,2084,2088,2086,2080,2076,2078,
-2090,2112,2144,2180,2211,2227,2225,2211,2197,2196,2213,2247,2289,2330,2363,2385,2396,2402,2407,2417,2437,
-2465,2500,2535,2566,2588,2599,2603,2609,2623,2645,2669,2685,2690,2689,2689,2697,2711,2725,2732,2732,2736,
-2752,2781,2815,2840,2849,2844,2839,2845,2869,2904,2938,2964,2981,2994,3009,3029,3050,3068,3085,3103,3126,
-3155,3182,3202,3213,3217,3222,3230,3239,3246,3249,3251,3256,3266,3279,3294,3306,3317,3325,3331,3333,3331,
-3328,3330,3337,3348,3355,3354,3346,3335,3328,3326,3325,3322,3317,3314,3317,3324,3330,3329,3321,3312,3313,
-3328,3353,3378,3398,3411,3425,3447,3477,3514,3553,3593,3640,3696,3758,3819,3873,3919,3966,4024,4094,4163,
-4217,4248,4268,4297,4353,4433,4518,4582,4613,4615,4608,4609,4620,4633,4639,4633,4617,4601,4589,4584,4587,
-4598,4613,4628,4633,4623,4600,4570,4543,4525,4513,4506,4500,4495,4494,4498,4505,4511,4516,4519,4520,4518,
-4514,4512,4513,4519,4527,4532,4528,4516,4502,4491,4484,4479,4468,4452,4433,4419,4412,4412,4413,4410,4403,
-4394,4387,4381,4374,4366,4355,4345,4337,4330,4322,4312,4300,4288,4274,4258,4240,4218,4192,4164,4134,4103,
-4075,4052,4035,4022,4003,3976,3938,3896,3856,3821,3787,3750,3709,3665,3625,3589,3555,3521,3483,3446,3411,
-3383,3358,3334,3308,3282,3260,3241,3227,3213,3199,3184,3170,3157,3145,3133,3123,3115,3108,3099,3086,3071,
-3058,3051,3052,3057,3061,3060,3054,3046,3038,3032,3027,3024,3022,3020,3016,3008,2996,2982,2969,2957,2946,
-2933,2914,2891,2866,2843,2822,2801,2780,2758,2737,2717,2698,2677,2654,2629,2604,2580,2557,2531,2504,2478,
-2457,2441,2428,2411,2386,2356,2324,2296,2271,2248,2222,2192,2159,2125,2090,2053,2017,1981,1948,1919,1891,
-1862,1833,1804,1774,1745,1712,1677,1641,1606,1573,1541,1507,1471,1434,1398,1363,1327,1288,1247,1205,1166,
-1129,1094,1057,1018,979,942,907,870,831,791,751,714,680,646,607,565,521,479,439,400,359,
-314,267,220,177,136,95,51,6,-38,-80,-121,-164,-210,-260,-311,-360,-406,-452,-500,-548,-594,
--634,-669,-704,-741,-784,-830,-877,-923,-968,-1014,-1058,-1097,-1130,-1158,-1186,-1217,-1255,-1296,-1339,-1381,-1421,
--1460,-1499,-1539,-1580,-1622,-1663,-1701,-1736,-1768,-1803,-1841,-1883,-1925,-1962,-1994,-2023,-2054,-2091,-2131,-2170,-2203,
--2231,-2258,-2286,-2317,-2349,-2378,-2401,-2420,-2436,-2453,-2475,-2500,-2528,-2556,-2581,-2603,-2623,-2642,-2659,-2673,-2685,
--2695,-2706,-2722,-2741,-2761,-2776,-2786,-2792,-2797,-2802,-2808,-2813,-2815,-2816,-2817,-2817,-2814,-2809,-2803,-2798,-2796,
--2797,-2799,-2799,-2797,-2794,-2793,-2794,-2797,-2801,-2802,-2801,-2797,-2792,-2790,-2789,-2789,-2786,-2778,-2766,-2755,-2747,
--2742,-2736,-2727,-2716,-2707,-2702,-2700,-2696,-2687,-2673,-2658,-2646,-2638,-2632,-2628,-2624,-2619,-2612,-2602,-2589,-2574,
--2559,-2544,-2527,-2505,-2478,-2450,-2425,-2405,-2388,-2369,-2349,-2328,-2311,-2298,-2285,-2267,-2243,-2217,-2191,-2168,-2146,
--2124,-2100,-2075,-2049,-2024,-2001,-1978,-1955,-1932,-1908,-1883,-1859,-1838,-1819,-1798,-1769,-1736,-1705,-1689,-1693,-1710,
--1725,-1724,-1708,-1686,-1667,-1656,-1647,-1634,-1617,-1603,-1596,-1594,-1590,-1575,-1553,-1531,-1519,-1518,-1521,-1519,-1505,
--1479,-1442,-1395,-1340,-1279,-1218,-1164,-1123,-1099,-1092,-1103,-1126,-1155,-1180,-1191,-1187,-1172,-1151,-1128,-1100,-1069,
--1036,-1011,-1001,-1005,-1016,-1024,-1025,-1022,-1019,-1019,-1018,-1011,-996,-975,-952,-930,-907,-886,-867,-853,-844,
--836,-828,-818,-805,-792,-775,-755,-732,-711,-700,-700,-709,-719,-722,-716,-702,-683,-659,-628,-591,-555,
--526,-508,-499,-486,-459,-416,-366,-323,-296,-285,-275,-254,-220,-181,-152,-140,-140,-141,-133,-124,-126,
--150,-198,-257,-306,-327,-303,-225,-94,71,239,370,442,463,468,494,562,656,744,796,807,794,
-780,779,790,805,817,822,821,815,804,791,783,783,791,804,817,828,840,855,870,879,876,
-861,838,814,793,776,761,748,735,721,703,683,663,650,649,658,673,686,692,692,687,680,
-673,665,656,650,648,653,662,671,671,657,624,574,512,443,371,299,229,161,99,42,-8,
--55,-98,-137,-171,-202,-234,-269,-307,-346,-380,-406,-427,-448,-472,-498,-521,-539,-552,-563,-577,-595,
--615,-635,-652,-666,-679,-687,-692,-695,-698,-706,-716,-726,-730,-726,-717,-708,-702,-699,-695,-689,-681,
--676,-680,-692,-707,-716,-713,-697,-676,-657,-649,-651,-660,-670,-677,-683,-695,-716,-746,-778,-805,-818,
--815,-800,-782,-768,-762,-762,-764,-763,-763,-766,-779,-801,-827,-849,-862,-868,-874,-886,-903,-924,-942,
--957,-969,-981,-994,-1007,-1021,-1039,-1060,-1083,-1103,-1117,-1126,-1134,-1145,-1158,-1170,-1178,-1182,-1186,-1195,-1209,
--1225,-1239,-1250,-1257,-1263,-1270,-1279,-1288,-1297,-1307,-1319,-1333,-1349,-1364,-1379,-1392,-1403,-1414,-1426,-1439,-1450,
--1458,-1460,-1458,-1458,-1462,-1469,-1477,-1482,-1482,-1481,-1483,-1488,-1496,-1505,-1512,-1518,-1521,-1522,-1518,-1512,-1505,
--1502,-1502,-1503,-1502,-1499,-1495,-1494,-1495,-1494,-1490,-1481,-1472,-1464,-1459,-1455,-1449,-1441,-1435,-1430,-1428,-1427,
--1425,-1424,-1425,-1426,-1424,-1418,-1406,-1392,-1378,-1368,-1359,-1350,-1341,-1333,-1327,-1323,-1318,-1310,-1300,-1288,-1277,
--1267,-1258,-1251,-1245,-1239,-1232,-1224,-1212,-1201,-1190,-1181,-1174,-1167,-1158,-1150,-1141,-1135,-1131,-1129,-1128,-1126,
--1123,-1118,-1112,-1106,-1102,-1100,-1100,-1099,-1098,-1095,-1092,-1090,-1087,-1084,-1081,-1078,-1075,-1071,-1067,-1062,-1057,
--1052,-1046,-1040,-1034,-1028,-1023,-1020,-1017,-1012,-1006,-999,-994,-992,-989,-985,-981,-978,-980,-984,-985,-981,
--974,-967,-966,-969,-973,-971,-963,-951,-941,-934,-928,-921,-912,-902,-895,-892,-891,-889,-885,-879,-874,
--869,-863,-856,-847,-838,-830,-820,-807,-789,-769,-751,-736,-726,-716,-704,-689,-673,-658,-645,-635,-625,
--613,-597,-578,-558,-540,-528,-523,-523,-522,-518,-507,-491,-474,-458,-445,-432,-420,-408,-397,-387,-375,
--363,-349,-337,-326,-318,-308,-295,-279,-263,-251,-242,-234,-223,-209,-192,-174,-156,-137,-115,-91,-67,
--45,-25,-4,18,41,64,85,104,125,147,170,191,212,232,254,278,301,323,343,363,385,
-407,430,454,480,510,543,574,601,622,638,653,666,679,694,714,739,767,797,826,855,886,
-918,947,971,994,1023,1061,1099,1121,1114,1087,1065,1073,1123,1198,1273,1333,1378,1421,1467,1513,1556,
-1601,1657,1729,1794,1819,1782,1697,1609,1570,1597,1671,1746,1789,1792,1772,1745,1719,1690,1653,1612,1571,
-1533,1495,1458,1426,1404,1392,1380,1361,1329,1294,1264,1245,1234,1221,1204,1186,1172,1165,1159,1149,1135,
-1122,1116,1117,1118,1113,1103,1094,1093,1099,1098,1074,1014,920,809,701,614,554,514,484,453,415,
-368,314,256,198,145,104,79,68,65,61,52,37,21,5,-10,-28,-49,-73,-99,-126,-153,
--181,-205,-224,-237,-245,-251,-259,-266,-271,-274,-276,-277,-278,-279,-280,-283,-289,-300,-313,-325,-335,
--342,-349,-355,-360,-361,-358,-353,-349,-351,-358,-371,-387,-404,-419,-434,-450,-466,-482,-496,-506,-512,
--518,-524,-534,-544,-552,-554,-552,-546,-540,-534,-528,-518,-506,-492,-478,-463,-450,-437,-425,-412,-395,
--375,-351,-326,-299,-270,-237,-199,-159,-119,-83,-51,-20,11,45,78,111,143,178,221,272,328,
-383,434,481,527,576,628,682,732,776,815,852,892,935,981,1027,1070,1113,1155,1196,1236,1273,
-1308,1345,1383,1422,1461,1500,1538,1577,1618,1657,1692,1721,1749,1778,1810,1845,1884,1923,1964,2004,2042,
-2076,2108,2141,2174,2209,2240,2266,2288,2308,2330,2352,2373,2391,2409,2431,2459,2492,2525,2553,2572,2584,
-2591,2593,2595,2595,2592,2587,2578,2570,2566,2568,2576,2582,2583,2578,2570,2563,2560,2555,2546,2533,2520,
-2512,2511,2514,2517,2517,2516,2513,2508,2497,2482,2465,2451,2442,2436,2431,2426,2422,2418,2411,2398,2379,
-2359,2342,2330,2321,2314,2307,2302,2298,2290,2274,2249,2224,2205,2190,2171,2141,2104,2076,2073,2098,2136,
-2162,2149,2133,2109,2089,2080,2082,2088,2092,2093,2093,2095,2104,2120,2147,2183,2219,2246,2253,2240,2215,
-2194,2191,2212,2252,2299,2341,2370,2386,2393,2400,2411,2430,2457,2487,2518,2547,2570,2586,2595,2599,2605,
-2615,2630,2645,2654,2658,2661,2669,2686,2708,2724,2730,2729,2732,2749,2781,2819,2850,2863,2859,2851,2852,
-2871,2904,2940,2970,2988,3000,3013,3031,3054,3078,3101,3124,3148,3173,3198,3216,3226,3231,3235,3242,3252,
-3260,3266,3270,3277,3287,3302,3316,3328,3336,3341,3341,3339,3335,3331,3331,3335,3341,3343,3339,3331,3324,
-3322,3324,3326,3324,3321,3319,3321,3326,3329,3325,3318,3314,3321,3340,3366,3392,3411,3426,3442,3466,3502,
-3549,3604,3663,3720,3773,3818,3857,3897,3946,4011,4089,4167,4231,4273,4298,4323,4366,4431,4508,4577,4621,
-4637,4635,4629,4631,4640,4651,4657,4655,4646,4635,4623,4615,4612,4615,4623,4629,4627,4616,4597,4579,4565,
-4556,4548,4538,4528,4522,4522,4527,4533,4534,4531,4528,4528,4533,4540,4549,4560,4571,4580,4583,4576,4560,
-4540,4521,4506,4494,4481,4465,4450,4439,4435,4436,4437,4435,4429,4420,4411,4402,4392,4383,4373,4365,4357,
-4347,4334,4319,4303,4290,4279,4270,4258,4242,4221,4195,4166,4136,4111,4093,4081,4069,4050,4019,3978,3936,
-3897,3864,3831,3793,3749,3705,3666,3633,3601,3565,3523,3480,3442,3411,3385,3360,3331,3301,3275,3254,3239,
-3224,3209,3193,3179,3167,3159,3152,3147,3145,3142,3136,3126,3113,3099,3089,3086,3087,3087,3084,3078,3071,
-3066,3062,3060,3059,3059,3061,3061,3057,3046,3030,3013,3000,2988,2977,2960,2938,2913,2887,2864,2842,2820,
-2799,2778,2759,2739,2717,2692,2665,2639,2616,2596,2575,2555,2534,2515,2497,2477,2453,2422,2390,2359,2333,
-2309,2284,2255,2222,2187,2151,2116,2079,2044,2011,1981,1954,1927,1898,1868,1839,1811,1781,1748,1711,1673,
-1637,1605,1574,1541,1505,1468,1433,1400,1367,1330,1288,1243,1200,1162,1128,1094,1057,1019,980,942,904,
-866,826,788,752,719,684,647,605,562,520,480,441,400,357,312,268,225,182,138,92,46,
-3,-36,-74,-114,-159,-208,-258,-308,-356,-403,-451,-500,-545,-585,-621,-657,-697,-742,-789,-833,-875,
--914,-955,-996,-1036,-1072,-1104,-1134,-1168,-1208,-1253,-1298,-1341,-1380,-1416,-1454,-1494,-1536,-1578,-1616,-1649,-1680,
--1711,-1747,-1788,-1832,-1873,-1909,-1940,-1969,-2002,-2040,-2079,-2114,-2143,-2167,-2193,-2223,-2260,-2297,-2330,-2356,-2374,
--2390,-2406,-2426,-2450,-2476,-2501,-2525,-2547,-2569,-2591,-2611,-2627,-2640,-2651,-2663,-2679,-2698,-2718,-2735,-2747,-2754,
--2759,-2763,-2768,-2772,-2776,-2778,-2779,-2778,-2774,-2770,-2766,-2765,-2767,-2770,-2772,-2771,-2768,-2764,-2762,-2762,-2765,
--2768,-2770,-2769,-2766,-2763,-2762,-2764,-2767,-2768,-2762,-2751,-2739,-2730,-2723,-2717,-2708,-2698,-2689,-2683,-2680,-2676,
--2668,-2656,-2642,-2630,-2621,-2616,-2612,-2608,-2602,-2593,-2581,-2566,-2549,-2535,-2521,-2505,-2484,-2459,-2431,-2407,-2389,
--2374,-2359,-2342,-2323,-2306,-2291,-2275,-2257,-2235,-2210,-2184,-2160,-2137,-2114,-2093,-2071,-2047,-2021,-1994,-1968,-1944,
--1923,-1902,-1878,-1853,-1831,-1812,-1792,-1767,-1737,-1710,-1696,-1702,-1721,-1735,-1732,-1712,-1687,-1670,-1665,-1663,-1655,
--1637,-1619,-1608,-1605,-1604,-1593,-1570,-1544,-1526,-1521,-1524,-1526,-1518,-1499,-1471,-1439,-1403,-1364,-1323,-1283,-1251,
--1230,-1224,-1231,-1246,-1261,-1267,-1260,-1240,-1216,-1194,-1175,-1156,-1135,-1112,-1096,-1090,-1094,-1100,-1100,-1090,-1075,
--1063,-1058,-1055,-1050,-1036,-1015,-989,-962,-939,-920,-906,-896,-888,-879,-869,-858,-848,-839,-826,-808,-785,
--764,-754,-758,-770,-779,-777,-761,-735,-707,-680,-653,-625,-598,-575,-559,-545,-523,-487,-440,-394,-362,
--347,-338,-320,-283,-238,-202,-191,-200,-213,-214,-207,-213,-254,-331,-417,-469,-457,-377,-246,-92,65,
-214,339,427,470,479,482,513,584,678,761,804,801,771,740,723,717,714,704,688,671,656,
-644,637,635,642,656,672,686,695,701,708,714,714,706,689,669,651,638,628,618,607,594,
-578,559,535,511,491,480,480,486,493,498,497,494,489,484,479,473,467,464,463,464,460,
-448,421,382,333,279,227,176,127,79,29,-19,-67,-114,-160,-201,-237,-267,-293,-318,-348,-381,
--414,-444,-468,-490,-513,-539,-566,-589,-606,-619,-632,-649,-670,-690,-707,-721,-734,-746,-756,-763,-766,
--767,-771,-780,-792,-803,-806,-801,-790,-777,-767,-761,-757,-754,-751,-752,-757,-765,-771,-770,-763,-752,
--743,-740,-741,-742,-737,-727,-718,-715,-722,-736,-753,-767,-779,-790,-801,-809,-813,-811,-804,-795,-788,
--786,-793,-810,-833,-857,-877,-889,-896,-902,-913,-930,-950,-969,-984,-998,-1010,-1023,-1037,-1053,-1071,-1092,
--1113,-1131,-1145,-1154,-1161,-1168,-1175,-1182,-1188,-1193,-1200,-1214,-1232,-1251,-1267,-1277,-1281,-1283,-1288,-1297,-1308,
--1321,-1334,-1346,-1358,-1371,-1386,-1400,-1412,-1422,-1431,-1442,-1455,-1467,-1474,-1476,-1473,-1472,-1476,-1484,-1492,-1494,
--1491,-1488,-1489,-1497,-1507,-1517,-1525,-1531,-1536,-1542,-1545,-1546,-1546,-1546,-1546,-1544,-1537,-1526,-1514,-1506,-1503,
--1504,-1503,-1499,-1492,-1485,-1479,-1473,-1466,-1457,-1448,-1441,-1436,-1433,-1431,-1430,-1431,-1432,-1431,-1425,-1414,-1399,
--1385,-1373,-1362,-1351,-1341,-1332,-1326,-1322,-1317,-1310,-1299,-1286,-1273,-1262,-1252,-1244,-1237,-1230,-1221,-1212,-1202,
--1193,-1185,-1179,-1175,-1171,-1165,-1157,-1148,-1140,-1135,-1131,-1129,-1125,-1119,-1111,-1103,-1096,-1092,-1090,-1090,-1089,
--1087,-1084,-1080,-1078,-1076,-1074,-1073,-1071,-1069,-1065,-1060,-1053,-1046,-1040,-1034,-1028,-1022,-1017,-1014,-1012,-1010,
--1004,-997,-989,-984,-982,-982,-981,-979,-977,-978,-980,-981,-977,-972,-968,-968,-971,-973,-971,-963,-952,
--943,-936,-931,-923,-914,-903,-896,-891,-889,-885,-879,-871,-863,-855,-849,-845,-841,-838,-832,-823,-810,
--792,-774,-757,-741,-728,-715,-703,-691,-681,-672,-664,-655,-648,-639,-627,-610,-588,-564,-544,-531,-526,
--522,-514,-499,-480,-460,-445,-432,-420,-407,-394,-384,-377,-373,-366,-355,-341,-328,-317,-306,-294,-279,
--263,-249,-238,-227,-216,-201,-183,-164,-145,-127,-107,-86,-66,-45,-26,-6,14,34,53,72,91,
-111,133,156,179,203,228,254,279,301,319,337,355,377,399,422,445,469,497,528,557,583,
-603,619,633,644,655,665,678,696,719,748,782,824,870,916,956,987,1016,1048,1086,1118,1128,
-1108,1074,1055,1076,1139,1222,1296,1347,1385,1428,1486,1553,1619,1680,1741,1803,1852,1864,1826,1749,1673,
-1636,1650,1698,1744,1765,1759,1738,1714,1688,1655,1615,1574,1537,1502,1467,1431,1399,1380,1372,1364,1341,
-1300,1252,1214,1199,1201,1209,1211,1204,1192,1181,1168,1151,1131,1115,1108,1110,1113,1109,1099,1090,1088,
-1092,1086,1054,986,888,778,673,585,515,457,408,366,331,300,267,225,175,124,83,59,51,
-51,48,38,23,8,-4,-17,-33,-56,-82,-111,-139,-166,-191,-215,-235,-249,-258,-265,-270,-277,
--284,-291,-296,-300,-301,-302,-305,-311,-320,-330,-341,-348,-353,-357,-363,-369,-372,-371,-364,-356,-349,
--346,-349,-356,-365,-376,-388,-403,-420,-438,-457,-472,-482,-487,-490,-494,-501,-510,-517,-520,-518,-513,
--507,-500,-492,-482,-469,-456,-442,-430,-418,-406,-394,-380,-365,-348,-331,-313,-293,-269,-238,-200,-159,
--119,-82,-48,-15,19,56,92,125,156,190,231,281,336,389,437,481,525,572,624,677,729,
-775,818,858,900,943,985,1027,1068,1109,1151,1192,1233,1271,1309,1348,1388,1428,1467,1504,1543,1583,
-1624,1662,1694,1721,1747,1776,1810,1848,1888,1928,1969,2010,2050,2086,2119,2150,2181,2212,2242,2269,2292,
-2313,2335,2356,2376,2395,2413,2435,2462,2493,2524,2551,2572,2587,2597,2605,2612,2615,2615,2609,2600,2589,
-2583,2583,2588,2592,2592,2587,2580,2576,2576,2575,2570,2559,2548,2540,2538,2539,2540,2538,2533,2527,2521,
-2514,2506,2496,2485,2475,2466,2460,2457,2458,2457,2453,2441,2423,2405,2391,2383,2378,2369,2357,2341,2323,
-2302,2278,2248,2217,2187,2160,2136,2116,2103,2101,2113,2132,2148,2149,2124,2115,2109,2110,2116,2123,2130,
-2137,2143,2148,2152,2154,2158,2169,2189,2214,2234,2240,2230,2209,2192,2190,2210,2245,2284,2318,2341,2353,
-2362,2376,2399,2431,2467,2502,2531,2554,2572,2585,2594,2600,2606,2611,2618,2625,2632,2638,2646,2659,2677,
-2697,2714,2727,2737,2750,2769,2794,2820,2838,2846,2846,2845,2853,2875,2907,2941,2967,2983,2992,3003,3022,
-3050,3083,3114,3140,3162,3183,3203,3220,3232,3240,3246,3252,3260,3268,3275,3284,3294,3308,3323,3336,3344,
-3346,3344,3341,3337,3334,3332,3331,3331,3331,3330,3327,3324,3324,3325,3327,3327,3324,3321,3320,3322,3325,
-3325,3322,3320,3324,3337,3358,3383,3407,3429,3447,3466,3491,3528,3581,3651,3728,3799,3848,3875,3891,3917,
-3970,4052,4147,4233,4292,4327,4353,4388,4443,4511,4575,4621,4644,4648,4646,4645,4649,4655,4660,4663,4662,
-4658,4650,4641,4633,4629,4631,4635,4634,4625,4610,4595,4584,4577,4570,4558,4543,4528,4522,4526,4535,4541,
-4541,4536,4532,4535,4546,4564,4582,4598,4610,4617,4618,4611,4596,4575,4551,4527,4504,4482,4464,4451,4446,
-4448,4457,4468,4479,4489,4494,4490,4478,4456,4431,4407,4389,4376,4364,4351,4335,4320,4306,4296,4286,4275,
-4259,4240,4216,4191,4167,4147,4132,4121,4107,4085,4054,4015,3975,3938,3906,3872,3834,3792,3751,3714,3681,
-3647,3606,3560,3513,3472,3440,3414,3389,3360,3330,3303,3280,3260,3242,3222,3204,3190,3181,3176,3174,3173,
-3173,3171,3168,3163,3154,3143,3132,3123,3116,3109,3104,3101,3101,3103,3104,3104,3103,3104,3105,3105,3100,
-3088,3071,3054,3042,3033,3023,3008,2986,2959,2931,2905,2881,2858,2835,2815,2795,2776,2755,2730,2704,2679,
-2658,2642,2627,2611,2594,2574,2551,2523,2491,2457,2425,2397,2372,2348,2320,2288,2252,2214,2178,2142,2106,
-2073,2043,2017,1993,1966,1936,1904,1872,1842,1813,1780,1744,1707,1673,1642,1611,1578,1540,1502,1468,1437,
-1406,1370,1327,1281,1237,1199,1166,1134,1098,1058,1016,976,938,901,865,829,794,758,723,686,646,
-604,561,519,477,436,394,352,310,267,224,178,132,87,44,4,-34,-73,-115,-161,-209,-259,
--308,-358,-407,-454,-498,-538,-576,-615,-660,-707,-754,-797,-834,-869,-904,-942,-981,-1019,-1054,-1088,-1124,
--1166,-1211,-1258,-1301,-1339,-1375,-1412,-1452,-1493,-1534,-1570,-1600,-1629,-1659,-1695,-1736,-1779,-1818,-1853,-1884,-1916,
--1950,-1987,-2023,-2054,-2079,-2103,-2130,-2164,-2204,-2245,-2282,-2310,-2331,-2348,-2365,-2385,-2406,-2429,-2452,-2474,-2497,
--2521,-2544,-2565,-2582,-2596,-2608,-2621,-2636,-2653,-2672,-2689,-2702,-2712,-2719,-2723,-2727,-2731,-2735,-2740,-2742,-2740,
--2736,-2732,-2731,-2734,-2741,-2747,-2749,-2748,-2743,-2738,-2735,-2735,-2737,-2740,-2742,-2742,-2739,-2737,-2736,-2740,-2746,
--2749,-2745,-2735,-2722,-2711,-2704,-2698,-2692,-2683,-2673,-2665,-2659,-2654,-2646,-2636,-2624,-2613,-2605,-2599,-2594,-2589,
--2583,-2573,-2560,-2544,-2527,-2512,-2499,-2484,-2466,-2443,-2419,-2396,-2377,-2361,-2346,-2331,-2314,-2297,-2281,-2263,-2245,
--2224,-2202,-2179,-2155,-2131,-2108,-2086,-2064,-2041,-2014,-1984,-1956,-1932,-1914,-1896,-1875,-1851,-1827,-1806,-1786,-1764,
--1739,-1717,-1706,-1713,-1730,-1742,-1739,-1720,-1696,-1682,-1680,-1680,-1673,-1655,-1632,-1617,-1612,-1610,-1600,-1578,-1552,
--1533,-1527,-1529,-1527,-1514,-1489,-1460,-1434,-1412,-1392,-1372,-1351,-1331,-1318,-1314,-1319,-1327,-1331,-1325,-1307,-1283,
--1258,-1239,-1224,-1210,-1195,-1179,-1169,-1168,-1173,-1177,-1171,-1154,-1131,-1111,-1098,-1091,-1081,-1065,-1041,-1014,-989,
--969,-955,-945,-936,-927,-917,-908,-900,-894,-886,-873,-854,-831,-812,-804,-808,-818,-824,-816,-793,-762,
--732,-706,-685,-665,-645,-625,-606,-585,-556,-517,-474,-435,-409,-394,-377,-346,-303,-262,-243,-251,-274,
--289,-286,-283,-311,-387,-494,-578,-579,-474,-285,-69,121,259,353,417,462,491,505,520,556,621,
-702,769,797,780,734,683,641,609,580,550,524,506,498,497,499,504,513,527,543,557,566,
-570,569,565,556,541,524,508,497,491,486,480,470,457,442,426,405,382,359,341,329,324,
-320,316,309,301,291,282,274,266,262,260,260,257,246,223,188,144,98,55,19,-11,-40,
--71,-106,-145,-185,-226,-265,-301,-332,-359,-383,-407,-433,-460,-487,-513,-536,-558,-582,-606,-630,-650,
--666,-682,-700,-721,-743,-761,-775,-784,-793,-803,-815,-825,-830,-831,-832,-835,-844,-855,-862,-862,-855,
--843,-834,-828,-828,-830,-830,-828,-825,-820,-816,-810,-804,-800,-801,-806,-810,-808,-799,-786,-774,-765,
--755,-739,-716,-692,-683,-698,-737,-787,-829,-851,-851,-839,-827,-823,-830,-846,-867,-888,-906,-918,-925,
--932,-942,-957,-976,-996,-1013,-1027,-1041,-1055,-1070,-1086,-1103,-1120,-1137,-1153,-1167,-1178,-1186,-1192,-1196,-1200,
--1203,-1207,-1216,-1231,-1251,-1272,-1289,-1299,-1301,-1301,-1302,-1310,-1325,-1343,-1360,-1375,-1387,-1399,-1411,-1424,-1436,
--1445,-1454,-1463,-1473,-1483,-1489,-1491,-1489,-1488,-1492,-1499,-1503,-1502,-1498,-1495,-1499,-1509,-1522,-1532,-1539,-1545,
--1553,-1564,-1575,-1581,-1583,-1582,-1579,-1573,-1563,-1547,-1531,-1519,-1513,-1513,-1516,-1516,-1513,-1508,-1502,-1495,-1486,
--1476,-1465,-1456,-1448,-1443,-1440,-1439,-1439,-1439,-1435,-1428,-1417,-1404,-1391,-1380,-1369,-1358,-1347,-1336,-1328,-1322,
--1314,-1305,-1294,-1281,-1270,-1259,-1249,-1240,-1230,-1220,-1210,-1200,-1191,-1181,-1174,-1168,-1165,-1163,-1159,-1154,-1146,
--1139,-1133,-1130,-1127,-1123,-1117,-1108,-1099,-1093,-1089,-1088,-1087,-1085,-1080,-1075,-1070,-1067,-1066,-1066,-1066,-1066,
--1063,-1058,-1050,-1042,-1034,-1029,-1024,-1020,-1014,-1009,-1005,-1002,-999,-994,-987,-980,-975,-974,-975,-976,-976,
--975,-975,-975,-974,-973,-970,-969,-969,-970,-970,-967,-960,-952,-945,-939,-934,-926,-917,-908,-901,-896,
--892,-887,-880,-871,-861,-852,-846,-842,-839,-836,-831,-822,-810,-795,-782,-769,-757,-742,-727,-712,-702,
--695,-690,-683,-674,-664,-655,-645,-633,-615,-595,-575,-561,-550,-537,-518,-493,-466,-443,-427,-416,-403,
--389,-376,-368,-368,-370,-369,-360,-345,-328,-316,-306,-297,-284,-268,-251,-235,-221,-208,-193,-176,-157,
--138,-120,-101,-83,-65,-46,-27,-8,8,25,42,60,80,101,123,144,167,192,219,247,271,
-290,305,321,340,363,388,412,436,459,485,512,538,561,581,598,615,630,644,658,674,695,
-721,752,789,835,886,937,980,1014,1040,1068,1096,1115,1113,1087,1055,1045,1079,1150,1233,1298,1338,
-1371,1423,1506,1611,1717,1808,1879,1934,1970,1975,1944,1887,1828,1789,1776,1775,1769,1748,1719,1692,1670,
-1648,1618,1584,1552,1526,1501,1469,1429,1390,1365,1354,1347,1325,1283,1230,1189,1171,1177,1192,1202,1203,
-1198,1190,1180,1165,1144,1125,1114,1111,1109,1103,1090,1080,1077,1079,1072,1037,968,872,766,664,575,
-496,425,365,320,291,273,251,215,164,108,63,38,30,30,29,22,10,0,-10,-21,-39,
--63,-91,-120,-147,-172,-196,-219,-240,-256,-267,-273,-277,-283,-292,-302,-312,-319,-324,-328,-333,-341,
--352,-363,-370,-374,-375,-376,-377,-378,-376,-371,-363,-355,-350,-348,-348,-348,-350,-355,-364,-378,-396,
--417,-437,-455,-469,-479,-485,-491,-496,-500,-502,-501,-497,-490,-483,-475,-465,-454,-442,-430,-419,-408,
--396,-382,-366,-350,-334,-320,-307,-294,-278,-258,-231,-198,-161,-124,-88,-52,-14,25,67,105,139,
-171,205,245,292,342,392,438,482,527,575,627,680,729,775,819,861,904,946,986,1025,1063,
-1102,1141,1180,1218,1256,1294,1335,1378,1420,1460,1498,1537,1577,1618,1654,1686,1714,1742,1774,1810,1848,
-1885,1922,1961,2002,2044,2083,2117,2147,2174,2203,2232,2260,2287,2311,2333,2354,2374,2393,2412,2434,2460,
-2489,2519,2546,2570,2589,2604,2616,2625,2632,2636,2635,2629,2621,2612,2607,2606,2606,2606,2604,2600,2597,
-2596,2595,2592,2585,2577,2571,2567,2565,2561,2554,2543,2534,2528,2527,2527,2526,2520,2511,2501,2493,2490,
-2489,2488,2483,2471,2454,2438,2426,2417,2406,2389,2364,2334,2303,2275,2250,2228,2208,2191,2177,2167,2158,
-2152,2148,2144,2140,2133,2124,2145,2148,2155,2162,2167,2170,2173,2179,2188,2196,2196,2186,2172,2163,2166,
-2181,2200,2214,2218,2212,2205,2203,2213,2231,2254,2275,2291,2303,2317,2337,2369,2410,2456,2498,2532,2556,
-2574,2587,2598,2606,2611,2614,2617,2622,2631,2641,2653,2664,2674,2685,2700,2720,2744,2768,2788,2800,2804,
-2806,2809,2817,2832,2854,2882,2912,2940,2960,2973,2983,2995,3018,3050,3087,3122,3148,3167,3183,3200,3218,
-3235,3247,3255,3260,3264,3270,3277,3288,3301,3317,3333,3343,3347,3344,3337,3331,3328,3327,3327,3326,3323,
-3320,3317,3318,3321,3324,3327,3326,3323,3321,3322,3325,3329,3329,3326,3324,3328,3340,3358,3380,3403,3427,
-3452,3477,3501,3527,3562,3618,3697,3787,3865,3913,3927,3929,3950,4009,4104,4209,4294,4347,4378,4407,4451,
-4510,4568,4611,4632,4637,4638,4641,4647,4653,4655,4655,4653,4650,4644,4632,4619,4610,4609,4615,4623,4626,
-4621,4612,4603,4595,4586,4571,4549,4523,4503,4494,4497,4506,4516,4523,4527,4534,4547,4567,4590,4611,4628,
-4639,4645,4646,4643,4633,4616,4590,4555,4516,4479,4452,4440,4445,4467,4501,4544,4591,4635,4667,4674,4654,
-4608,4548,4489,4442,4411,4391,4376,4362,4348,4335,4323,4310,4294,4275,4253,4232,4214,4200,4187,4175,4160,
-4140,4114,4083,4048,4012,3978,3945,3910,3874,3835,3798,3762,3726,3687,3643,3594,3547,3506,3473,3445,3418,
-3391,3363,3337,3313,3290,3268,3245,3224,3208,3199,3195,3195,3195,3195,3195,3194,3192,3189,3183,3175,3164,
-3153,3144,3140,3142,3148,3153,3155,3154,3151,3150,3150,3148,3141,3127,3110,3095,3084,3076,3065,3048,3025,
-2998,2972,2947,2922,2897,2872,2849,2829,2811,2792,2771,2749,2729,2712,2699,2685,2668,2648,2623,2595,2562,
-2528,2494,2464,2438,2414,2387,2355,2319,2280,2241,2204,2168,2133,2102,2076,2054,2032,2006,1975,1940,1906,
-1875,1844,1811,1776,1741,1709,1681,1652,1620,1584,1546,1510,1477,1444,1406,1362,1316,1274,1238,1206,1174,
-1137,1095,1052,1011,975,940,905,869,831,794,757,720,681,640,597,554,511,470,429,387,344,
-300,255,211,169,128,87,46,5,-35,-76,-120,-165,-214,-266,-317,-365,-409,-449,-487,-527,-569,
--616,-665,-713,-755,-791,-825,-857,-892,-930,-967,-1004,-1041,-1081,-1124,-1171,-1217,-1260,-1298,-1334,-1370,-1408,
--1448,-1485,-1519,-1550,-1579,-1611,-1647,-1686,-1725,-1761,-1794,-1826,-1860,-1896,-1932,-1966,-1995,-2021,-2048,-2078,-2115,
--2154,-2194,-2229,-2257,-2279,-2298,-2317,-2338,-2360,-2383,-2407,-2431,-2455,-2478,-2501,-2521,-2539,-2554,-2570,-2585,-2600,
--2616,-2631,-2645,-2659,-2670,-2679,-2685,-2689,-2694,-2700,-2706,-2709,-2707,-2701,-2696,-2696,-2702,-2711,-2719,-2722,-2720,
--2715,-2711,-2710,-2712,-2716,-2719,-2721,-2721,-2718,-2714,-2713,-2716,-2720,-2722,-2718,-2709,-2697,-2688,-2682,-2679,-2674,
--2667,-2657,-2647,-2638,-2631,-2624,-2616,-2607,-2598,-2590,-2583,-2576,-2569,-2562,-2553,-2541,-2526,-2509,-2494,-2479,-2464,
--2447,-2427,-2406,-2386,-2367,-2349,-2332,-2316,-2300,-2284,-2268,-2250,-2229,-2208,-2187,-2166,-2145,-2122,-2098,-2075,-2053,
--2030,-2004,-1976,-1948,-1925,-1908,-1892,-1874,-1850,-1825,-1801,-1779,-1757,-1735,-1717,-1709,-1716,-1733,-1748,-1749,-1735,
--1715,-1701,-1695,-1692,-1682,-1661,-1638,-1621,-1614,-1610,-1600,-1582,-1560,-1545,-1540,-1539,-1530,-1508,-1474,-1438,-1410,
--1393,-1383,-1375,-1368,-1361,-1357,-1359,-1364,-1368,-1364,-1351,-1331,-1307,-1287,-1272,-1261,-1252,-1241,-1230,-1223,-1224,
--1229,-1231,-1224,-1206,-1183,-1162,-1145,-1130,-1112,-1088,-1061,-1036,-1017,-1004,-995,-986,-976,-967,-960,-954,-949,
--941,-928,-911,-892,-874,-863,-859,-861,-864,-860,-847,-824,-797,-771,-748,-729,-709,-686,-661,-637,-612,
--586,-557,-526,-497,-471,-445,-415,-377,-339,-315,-315,-335,-355,-361,-354,-359,-404,-493,-587,-622,-544,
--350,-94,144,309,389,416,433,462,501,538,571,608,658,713,755,763,730,670,600,535,480,
-432,393,367,358,362,372,382,388,394,405,419,434,444,447,443,432,416,397,378,364,355,
-351,346,338,326,313,300,287,271,253,232,212,196,183,172,161,148,132,115,96,77,63,
-56,57,61,60,50,27,-6,-44,-80,-110,-133,-153,-174,-199,-229,-263,-299,-333,-364,-392,-420,
--447,-475,-503,-530,-554,-575,-593,-611,-630,-650,-671,-690,-707,-722,-739,-759,-780,-801,-819,-832,-842,
--850,-859,-869,-879,-887,-891,-891,-892,-895,-902,-909,-913,-911,-905,-899,-895,-896,-898,-898,-895,-888,
--880,-871,-862,-855,-851,-851,-852,-853,-849,-842,-837,-837,-836,-823,-786,-726,-662,-622,-628,-681,-760,
--833,-879,-893,-887,-878,-875,-881,-892,-904,-916,-929,-941,-953,-964,-976,-990,-1007,-1024,-1040,-1054,-1068,
--1083,-1099,-1117,-1133,-1148,-1161,-1174,-1186,-1197,-1207,-1214,-1218,-1221,-1224,-1229,-1238,-1252,-1270,-1290,-1306,-1316,
--1318,-1315,-1314,-1321,-1337,-1360,-1384,-1403,-1416,-1426,-1436,-1448,-1460,-1471,-1481,-1489,-1497,-1503,-1508,-1509,-1509,
--1510,-1513,-1516,-1516,-1513,-1509,-1509,-1516,-1527,-1539,-1548,-1554,-1561,-1572,-1585,-1597,-1603,-1603,-1599,-1594,-1589,
--1580,-1566,-1549,-1533,-1524,-1522,-1524,-1526,-1525,-1522,-1516,-1510,-1504,-1495,-1486,-1475,-1466,-1459,-1454,-1452,-1449,
--1446,-1439,-1430,-1420,-1408,-1398,-1388,-1377,-1366,-1353,-1341,-1330,-1320,-1309,-1298,-1286,-1276,-1267,-1258,-1250,-1239,
--1229,-1218,-1207,-1197,-1186,-1175,-1165,-1157,-1152,-1148,-1145,-1140,-1133,-1126,-1121,-1119,-1118,-1117,-1113,-1106,-1099,
--1094,-1091,-1090,-1089,-1084,-1077,-1069,-1062,-1059,-1057,-1058,-1058,-1057,-1053,-1046,-1037,-1028,-1021,-1018,-1015,-1013,
--1008,-1002,-996,-990,-986,-981,-977,-972,-969,-969,-970,-971,-972,-971,-970,-969,-969,-968,-966,-965,-964,
--962,-961,-958,-955,-952,-949,-945,-939,-931,-922,-915,-908,-903,-898,-891,-883,-875,-868,-860,-854,-848,
--843,-837,-830,-819,-806,-794,-785,-778,-770,-759,-745,-731,-721,-714,-707,-696,-680,-663,-647,-634,-623,
--612,-601,-591,-583,-573,-556,-529,-497,-465,-442,-428,-417,-404,-388,-372,-364,-365,-369,-369,-359,-342,
--325,-314,-309,-305,-296,-280,-259,-240,-224,-211,-199,-184,-166,-145,-123,-103,-84,-65,-46,-28,-10,
-4,18,33,50,70,91,110,127,145,166,191,217,240,259,274,293,317,346,376,404,429,
-453,476,499,520,541,561,583,607,630,652,675,702,732,765,799,833,871,914,959,998,1028,
-1050,1069,1087,1098,1094,1073,1051,1051,1088,1157,1232,1290,1328,1368,1435,1542,1678,1816,1934,2023,2082,
-2114,2116,2090,2042,1987,1937,1892,1845,1789,1729,1677,1641,1620,1602,1581,1558,1538,1525,1510,1481,1437,
-1389,1352,1333,1323,1306,1272,1227,1190,1172,1173,1183,1191,1195,1197,1200,1200,1190,1171,1148,1130,1120,
-1112,1101,1084,1069,1062,1061,1051,1018,954,865,765,667,578,496,424,366,327,308,295,273,231,
-170,105,53,22,11,9,7,2,-3,-10,-16,-26,-44,-69,-97,-125,-150,-174,-198,-222,-244,
--262,-273,-281,-286,-292,-302,-314,-327,-338,-346,-352,-358,-366,-376,-385,-391,-394,-393,-390,-387,-381,
--374,-366,-359,-354,-353,-353,-351,-348,-345,-347,-356,-371,-389,-409,-427,-445,-461,-475,-487,-496,-500,
--501,-498,-492,-485,-476,-467,-457,-446,-435,-424,-414,-403,-391,-376,-359,-341,-325,-310,-298,-286,-274,
--258,-240,-217,-190,-160,-127,-92,-53,-10,34,78,117,151,183,217,255,298,344,390,435,482,
-532,584,637,688,734,778,820,862,905,946,986,1025,1063,1101,1139,1174,1209,1244,1282,1322,1365,
-1407,1446,1484,1521,1560,1598,1634,1667,1699,1732,1766,1803,1838,1871,1905,1941,1982,2024,2064,2098,2127,
-2153,2181,2212,2243,2274,2301,2326,2348,2369,2390,2411,2434,2459,2486,2513,2540,2566,2588,2607,2622,2633,
-2642,2649,2655,2657,2652,2643,2634,2627,2624,2624,2625,2623,2620,2616,2613,2610,2606,2601,2596,2590,2585,
-2578,2569,2559,2550,2546,2545,2545,2544,2539,2530,2519,2510,2502,2496,2488,2476,2460,2443,2427,2413,2400,
-2383,2360,2332,2303,2276,2254,2239,2228,2222,2220,2219,2218,2214,2205,2191,2175,2160,2149,2145,2208,2207,
-2203,2196,2185,2176,2172,2177,2185,2191,2187,2174,2156,2144,2144,2157,2179,2202,2219,2227,2228,2226,2225,
-2229,2240,2254,2270,2285,2299,2317,2345,2384,2430,2477,2517,2546,2566,2580,2592,2601,2608,2613,2617,2626,
-2639,2655,2669,2676,2678,2680,2690,2712,2741,2769,2784,2785,2777,2771,2777,2798,2828,2861,2890,2914,2934,
-2952,2967,2984,3003,3029,3062,3097,3129,3153,3171,3186,3202,3220,3238,3252,3261,3264,3267,3270,3277,3288,
-3301,3316,3329,3336,3338,3333,3326,3319,3315,3315,3315,3313,3310,3307,3307,3310,3314,3318,3319,3318,3318,
-3322,3331,3340,3343,3339,3332,3329,3338,3358,3383,3406,3428,3452,3481,3514,3545,3576,3613,3669,3749,3840,
-3918,3962,3974,3979,4008,4078,4178,4279,4354,4395,4420,4451,4497,4550,4591,4612,4614,4611,4613,4621,4628,
-4630,4627,4623,4621,4618,4609,4593,4574,4563,4564,4575,4588,4597,4600,4601,4601,4600,4592,4576,4552,4526,
-4502,4485,4473,4466,4466,4475,4494,4522,4555,4587,4615,4638,4655,4667,4673,4675,4675,4669,4655,4627,4583,
-4527,4474,4439,4434,4463,4523,4604,4695,4786,4863,4911,4918,4880,4803,4705,4608,4529,4472,4436,4411,4391,
-4373,4357,4344,4330,4313,4291,4269,4250,4238,4232,4225,4214,4194,4168,4138,4107,4076,4046,4013,3979,3944,
-3909,3875,3840,3803,3763,3719,3673,3627,3583,3542,3506,3473,3444,3418,3394,3372,3350,3327,3303,3279,3256,
-3235,3220,3211,3207,3208,3211,3215,3218,3220,3221,3221,3218,3214,3209,3207,3210,3216,3221,3221,3214,3205,
-3198,3197,3199,3197,3189,3174,3156,3141,3130,3119,3103,3082,3058,3035,3013,2991,2966,2938,2909,2883,2862,
-2845,2829,2812,2796,2782,2770,2757,2740,2718,2690,2658,2626,2593,2561,2531,2503,2477,2450,2420,2384,2345,
-2304,2266,2230,2195,2163,2135,2112,2091,2069,2042,2010,1975,1941,1910,1879,1846,1811,1776,1746,1719,1693,
-1664,1630,1594,1557,1520,1481,1440,1396,1352,1312,1277,1244,1209,1170,1129,1088,1051,1015,981,944,906,
-866,826,788,751,713,673,631,588,546,506,465,422,377,329,282,240,202,166,129,88,45,
-1,-39,-81,-124,-172,-224,-274,-321,-361,-398,-435,-475,-520,-568,-616,-661,-702,-739,-774,-808,-842,
--878,-915,-954,-996,-1040,-1086,-1133,-1178,-1220,-1258,-1294,-1330,-1367,-1403,-1438,-1470,-1501,-1532,-1566,-1602,-1638,
--1672,-1705,-1737,-1770,-1805,-1841,-1876,-1908,-1938,-1968,-2000,-2034,-2071,-2108,-2143,-2174,-2199,-2220,-2239,-2260,-2283,
--2308,-2335,-2362,-2388,-2412,-2434,-2455,-2473,-2491,-2509,-2528,-2548,-2566,-2582,-2595,-2606,-2618,-2630,-2640,-2648,-2654,
--2660,-2667,-2673,-2676,-2674,-2668,-2663,-2664,-2671,-2680,-2688,-2690,-2687,-2683,-2682,-2685,-2690,-2696,-2699,-2699,-2697,
--2694,-2691,-2689,-2690,-2690,-2689,-2685,-2677,-2668,-2662,-2659,-2657,-2654,-2647,-2638,-2628,-2619,-2612,-2605,-2599,-2592,
--2584,-2575,-2566,-2557,-2549,-2541,-2532,-2520,-2506,-2490,-2474,-2458,-2442,-2425,-2407,-2389,-2372,-2355,-2337,-2319,-2301,
--2286,-2271,-2256,-2237,-2215,-2191,-2168,-2148,-2129,-2108,-2085,-2061,-2038,-2016,-1993,-1968,-1943,-1921,-1902,-1885,-1866,
--1845,-1821,-1797,-1775,-1753,-1731,-1714,-1708,-1717,-1735,-1753,-1759,-1750,-1733,-1716,-1705,-1696,-1683,-1663,-1642,-1626,
--1617,-1611,-1601,-1587,-1571,-1559,-1554,-1548,-1535,-1510,-1476,-1440,-1411,-1391,-1377,-1368,-1363,-1363,-1368,-1376,-1383,
--1383,-1375,-1360,-1340,-1321,-1305,-1295,-1288,-1283,-1277,-1271,-1267,-1266,-1266,-1263,-1255,-1241,-1224,-1207,-1191,-1170,
--1145,-1115,-1088,-1067,-1056,-1049,-1042,-1032,-1021,-1013,-1010,-1008,-1002,-988,-966,-944,-929,-923,-923,-924,-920,
--911,-896,-878,-859,-839,-819,-798,-775,-749,-720,-689,-662,-639,-622,-607,-590,-565,-533,-494,-453,-417,
--394,-389,-399,-413,-420,-415,-410,-428,-481,-551,-591,-545,-387,-143,114,310,407,420,403,404,442,
-504,563,608,643,677,709,726,710,659,581,496,418,352,300,262,242,240,250,263,272,275,
-277,283,295,310,321,326,323,311,294,274,254,239,229,222,214,203,188,173,159,146,133,
-118,101,84,67,53,39,26,10,-8,-33,-61,-89,-111,-121,-119,-112,-108,-113,-130,-154,-179,
--200,-218,-234,-252,-273,-300,-331,-364,-396,-425,-450,-473,-498,-526,-560,-594,-624,-647,-663,-675,-686,
--700,-717,-735,-752,-768,-783,-798,-813,-829,-846,-864,-882,-897,-908,-916,-921,-928,-936,-944,-949,-951,
--952,-955,-959,-964,-967,-965,-960,-955,-952,-950,-949,-946,-942,-937,-933,-926,-918,-908,-900,-893,-886,
--879,-875,-879,-892,-905,-903,-869,-803,-726,-671,-664,-709,-784,-856,-902,-919,-919,-918,-923,-932,-937,
--937,-937,-943,-957,-976,-997,-1015,-1030,-1044,-1057,-1069,-1081,-1093,-1107,-1124,-1142,-1159,-1173,-1184,-1193,-1202,
--1212,-1222,-1229,-1235,-1240,-1244,-1251,-1261,-1275,-1292,-1310,-1325,-1333,-1333,-1328,-1324,-1328,-1344,-1368,-1396,-1419,
--1435,-1445,-1455,-1466,-1480,-1493,-1504,-1512,-1517,-1522,-1526,-1529,-1532,-1534,-1536,-1536,-1534,-1531,-1529,-1531,-1538,
--1548,-1557,-1564,-1570,-1580,-1592,-1604,-1611,-1610,-1604,-1598,-1596,-1596,-1594,-1585,-1567,-1548,-1532,-1525,-1523,-1524,
--1522,-1518,-1513,-1510,-1508,-1505,-1501,-1494,-1485,-1478,-1472,-1467,-1461,-1454,-1444,-1433,-1422,-1411,-1401,-1390,-1379,
--1367,-1355,-1343,-1331,-1319,-1306,-1293,-1282,-1273,-1266,-1260,-1252,-1243,-1232,-1222,-1211,-1199,-1186,-1173,-1160,-1150,
--1143,-1137,-1131,-1123,-1114,-1107,-1102,-1101,-1103,-1104,-1103,-1099,-1095,-1091,-1088,-1087,-1084,-1078,-1071,-1063,-1056,
--1051,-1049,-1048,-1047,-1044,-1039,-1032,-1024,-1017,-1011,-1009,-1007,-1005,-1002,-995,-988,-981,-975,-971,-968,-967,
--966,-966,-966,-967,-967,-967,-967,-967,-966,-964,-961,-958,-954,-951,-949,-949,-950,-952,-953,-950,-944,
--936,-928,-923,-918,-912,-904,-895,-887,-881,-876,-872,-866,-859,-851,-843,-833,-820,-807,-795,-787,-782,
--777,-771,-762,-751,-740,-730,-717,-700,-677,-652,-627,-607,-593,-584,-581,-582,-584,-581,-567,-543,-514,
--487,-469,-457,-446,-430,-408,-387,-374,-371,-372,-369,-358,-341,-325,-317,-316,-315,-308,-292,-271,-250,
--235,-224,-215,-203,-185,-161,-137,-113,-92,-71,-51,-31,-13,0,12,24,40,59,78,94,107,
-121,138,160,185,207,226,244,267,298,333,369,401,427,450,470,489,507,527,551,579,610,
-641,669,697,730,766,802,834,861,888,919,954,989,1016,1035,1050,1066,1080,1085,1077,1067,1070,
-1103,1163,1233,1297,1349,1403,1479,1588,1722,1865,1997,2108,2192,2242,2252,2223,2162,2088,2014,1943,1870,
-1793,1716,1653,1612,1589,1573,1557,1540,1527,1519,1508,1482,1438,1385,1339,1311,1295,1279,1253,1220,1192,
-1177,1176,1181,1186,1190,1198,1209,1216,1211,1191,1164,1141,1126,1116,1102,1083,1063,1049,1040,1026,995,
-938,858,765,672,584,505,441,394,369,356,343,312,258,186,114,57,22,5,-2,-8,-13,
--18,-21,-24,-33,-49,-72,-99,-126,-152,-178,-204,-229,-252,-270,-284,-294,-302,-310,-320,-331,-344,
--357,-367,-375,-380,-386,-390,-395,-397,-397,-395,-391,-385,-376,-367,-359,-354,-354,-355,-354,-351,-345,
--342,-347,-360,-379,-399,-415,-428,-440,-453,-467,-480,-491,-497,-498,-495,-489,-480,-469,-456,-443,-431,
--421,-411,-401,-389,-373,-355,-337,-320,-307,-296,-286,-274,-260,-243,-224,-204,-182,-157,-126,-89,-47,
-0,46,90,128,163,196,230,267,307,349,392,438,488,541,596,649,698,742,784,825,867,
-908,948,987,1026,1065,1105,1143,1179,1213,1247,1283,1321,1360,1398,1434,1468,1503,1539,1575,1611,1646,
-1680,1717,1753,1789,1823,1855,1888,1924,1964,2004,2042,2074,2103,2132,2162,2196,2229,2261,2290,2316,2340,
-2364,2388,2413,2437,2461,2484,2508,2532,2557,2582,2604,2621,2634,2644,2654,2664,2672,2675,2670,2660,2651,
-2645,2643,2642,2639,2634,2628,2624,2622,2621,2618,2612,2604,2595,2587,2581,2575,2569,2563,2555,2547,2537,
-2525,2515,2505,2497,2488,2476,2459,2439,2418,2398,2381,2366,2352,2336,2318,2302,2289,2281,2275,2271,2267,
-2262,2259,2256,2253,2249,2242,2233,2223,2214,2209,2208,2252,2233,2210,2185,2164,2151,2146,2148,2151,2150,
-2145,2138,2132,2132,2141,2156,2176,2197,2217,2231,2238,2239,2239,2245,2261,2284,2309,2326,2335,2340,2350,
-2374,2411,2453,2492,2521,2540,2552,2563,2572,2582,2591,2601,2615,2633,2652,2668,2678,2681,2683,2692,2711,
-2736,2757,2766,2763,2755,2755,2771,2802,2838,2870,2892,2907,2923,2942,2967,2995,3024,3053,3082,3111,3137,
-3159,3176,3191,3206,3223,3238,3250,3256,3260,3263,3269,3278,3288,3299,3309,3317,3322,3323,3321,3316,3310,
-3304,3301,3299,3297,3296,3296,3297,3300,3304,3306,3307,3309,3315,3327,3342,3352,3353,3343,3333,3333,3348,
-3376,3407,3433,3455,3480,3513,3554,3597,3639,3683,3740,3814,3893,3959,3998,4017,4039,4088,4171,4270,4356,
-4409,4434,4452,4482,4525,4568,4594,4599,4593,4589,4591,4596,4595,4587,4578,4576,4579,4579,4570,4553,4536,
-4530,4536,4549,4557,4559,4557,4559,4567,4578,4587,4592,4594,4590,4578,4550,4507,4459,4423,4417,4443,4491,
-4546,4594,4631,4657,4678,4692,4701,4702,4699,4692,4676,4644,4593,4528,4468,4436,4451,4518,4628,4760,4892,
-5004,5083,5118,5104,5045,4951,4841,4734,4644,4573,4519,4473,4432,4395,4367,4348,4335,4322,4305,4285,4268,
-4257,4252,4248,4237,4215,4185,4154,4125,4099,4072,4040,4005,3969,3935,3902,3869,3831,3787,3742,3697,3655,
-3615,3575,3536,3500,3470,3446,3426,3408,3388,3367,3345,3323,3299,3272,3247,3226,3215,3215,3224,3236,3246,
-3253,3257,3261,3266,3274,3284,3297,3310,3319,3318,3305,3284,3263,3252,3250,3253,3253,3243,3226,3207,3191,
-3178,3162,3142,3119,3095,3074,3056,3035,3009,2978,2947,2921,2900,2883,2868,2852,2839,2828,2817,2804,2783,
-2754,2720,2685,2652,2621,2593,2565,2538,2510,2480,2446,2409,2369,2330,2293,2260,2228,2199,2173,2149,2126,
-2100,2070,2036,2003,1973,1945,1917,1885,1850,1815,1783,1756,1730,1703,1672,1638,1600,1561,1520,1477,1434,
-1393,1355,1319,1282,1242,1202,1163,1126,1091,1056,1019,980,940,899,860,823,785,746,707,666,624,
-583,543,503,460,413,364,317,274,238,204,167,126,81,36,-5,-44,-84,-129,-179,-228,-272,
--311,-347,-386,-429,-476,-523,-567,-607,-645,-683,-720,-756,-793,-829,-868,-909,-955,-1003,-1051,-1097,-1140,
--1179,-1217,-1254,-1292,-1329,-1364,-1398,-1429,-1460,-1492,-1525,-1558,-1591,-1622,-1653,-1686,-1720,-1754,-1788,-1820,-1851,
--1882,-1916,-1951,-1989,-2027,-2063,-2095,-2123,-2146,-2166,-2185,-2206,-2230,-2258,-2286,-2313,-2338,-2361,-2383,-2403,-2421,
--2440,-2459,-2480,-2502,-2523,-2541,-2555,-2567,-2578,-2590,-2601,-2610,-2618,-2625,-2631,-2637,-2639,-2638,-2634,-2632,-2635,
--2644,-2653,-2659,-2659,-2655,-2652,-2653,-2658,-2666,-2671,-2672,-2671,-2668,-2666,-2666,-2666,-2666,-2665,-2662,-2657,-2652,
--2646,-2642,-2638,-2634,-2628,-2622,-2615,-2608,-2602,-2596,-2589,-2582,-2575,-2567,-2558,-2547,-2537,-2528,-2520,-2511,-2500,
--2485,-2470,-2454,-2439,-2424,-2407,-2390,-2372,-2357,-2341,-2326,-2308,-2291,-2274,-2260,-2246,-2228,-2204,-2178,-2154,-2132,
--2114,-2096,-2074,-2050,-2026,-2003,-1982,-1961,-1938,-1915,-1894,-1873,-1855,-1836,-1818,-1798,-1777,-1755,-1733,-1717,-1713,
--1722,-1741,-1758,-1765,-1757,-1740,-1722,-1708,-1698,-1686,-1670,-1651,-1634,-1621,-1613,-1605,-1594,-1582,-1571,-1561,-1551,
--1538,-1520,-1499,-1475,-1451,-1424,-1398,-1376,-1362,-1361,-1369,-1381,-1389,-1389,-1381,-1368,-1355,-1342,-1331,-1323,-1318,
--1315,-1313,-1313,-1311,-1307,-1299,-1288,-1275,-1263,-1251,-1240,-1226,-1206,-1179,-1150,-1127,-1112,-1106,-1102,-1093,-1080,
--1067,-1061,-1061,-1061,-1053,-1032,-1006,-984,-976,-982,-991,-993,-982,-960,-936,-916,-900,-884,-865,-840,-813,
--785,-757,-730,-705,-687,-674,-664,-648,-619,-576,-526,-481,-452,-442,-446,-453,-453,-446,-441,-451,-486,
--534,-561,-525,-397,-185,57,265,385,413,385,359,371,423,493,554,595,625,652,673,673,639,
-569,476,381,299,237,192,162,148,146,152,159,161,159,158,161,171,184,196,204,204,197,
-184,166,147,131,119,111,103,91,75,58,40,25,10,-4,-20,-37,-54,-72,-89,-105,-122,
--142,-167,-197,-227,-251,-263,-262,-255,-249,-251,-261,-274,-287,-298,-309,-323,-342,-365,-391,-419,-449,
--478,-505,-528,-549,-572,-601,-635,-671,-702,-725,-739,-747,-756,-767,-782,-799,-817,-835,-852,-865,-875,
--882,-892,-908,-930,-951,-966,-973,-973,-974,-979,-989,-998,-1004,-1006,-1007,-1011,-1015,-1019,-1019,-1014,-1007,
--1001,-996,-992,-989,-989,-989,-988,-984,-975,-963,-950,-940,-932,-924,-919,-921,-934,-953,-963,-949,-908,
--853,-810,-800,-825,-870,-908,-926,-926,-923,-930,-947,-964,-969,-962,-951,-950,-965,-994,-1025,-1052,-1071,
--1084,-1094,-1104,-1112,-1121,-1131,-1144,-1159,-1175,-1189,-1201,-1210,-1219,-1228,-1237,-1245,-1251,-1255,-1260,-1267,-1279,
--1296,-1315,-1334,-1349,-1354,-1352,-1343,-1335,-1335,-1345,-1367,-1394,-1419,-1439,-1454,-1466,-1479,-1493,-1507,-1518,-1525,
--1529,-1532,-1537,-1543,-1550,-1555,-1557,-1555,-1552,-1550,-1550,-1553,-1558,-1563,-1568,-1575,-1585,-1600,-1615,-1624,-1623,
--1612,-1600,-1594,-1597,-1604,-1608,-1601,-1582,-1558,-1538,-1527,-1523,-1521,-1517,-1510,-1503,-1498,-1498,-1500,-1501,-1500,
--1497,-1493,-1489,-1483,-1474,-1463,-1449,-1435,-1421,-1408,-1396,-1384,-1372,-1361,-1352,-1343,-1333,-1321,-1308,-1295,-1284,
--1275,-1269,-1262,-1254,-1246,-1237,-1227,-1216,-1203,-1187,-1172,-1159,-1149,-1142,-1134,-1125,-1113,-1102,-1093,-1087,-1086,
--1087,-1089,-1089,-1087,-1083,-1080,-1077,-1074,-1070,-1065,-1059,-1053,-1049,-1045,-1043,-1040,-1036,-1031,-1026,-1021,-1016,
--1011,-1006,-1001,-998,-995,-992,-988,-982,-976,-969,-964,-962,-961,-961,-962,-962,-961,-962,-963,-965,-966,
--966,-963,-959,-954,-949,-946,-945,-946,-949,-952,-953,-950,-943,-936,-931,-927,-924,-919,-909,-899,-890,
--885,-883,-881,-876,-869,-861,-852,-843,-833,-821,-808,-797,-789,-784,-779,-772,-762,-750,-735,-718,-696,
--671,-643,-616,-592,-574,-564,-562,-567,-573,-575,-568,-553,-535,-519,-507,-497,-482,-460,-432,-407,-390,
--382,-379,-374,-363,-347,-333,-325,-323,-321,-314,-299,-278,-259,-245,-236,-229,-217,-198,-174,-148,-125,
--104,-84,-62,-39,-19,-4,7,17,31,48,67,83,98,112,130,153,176,196,214,233,258,
-291,329,367,399,425,446,463,479,497,518,547,581,617,649,676,701,730,763,796,823,844,
-864,890,922,956,984,1005,1022,1043,1066,1083,1089,1086,1090,1118,1176,1255,1338,1415,1485,1556,1641,
-1743,1863,1996,2132,2257,2346,2377,2344,2258,2149,2042,1949,1869,1792,1719,1655,1610,1582,1564,1547,1530,
-1515,1503,1489,1465,1427,1379,1335,1301,1276,1252,1225,1197,1176,1168,1170,1176,1180,1185,1195,1207,1216,
-1211,1191,1163,1138,1123,1114,1103,1085,1063,1042,1026,1008,979,929,858,771,680,593,519,463,430,
-414,404,384,343,279,204,132,76,39,17,2,-10,-19,-25,-28,-33,-42,-57,-78,-102,-129,
--157,-186,-214,-239,-260,-278,-294,-308,-321,-331,-340,-349,-359,-371,-383,-393,-400,-403,-404,-402,-399,
--394,-389,-382,-375,-367,-360,-354,-352,-352,-352,-348,-341,-334,-334,-343,-363,-386,-408,-423,-432,-439,
--447,-457,-468,-478,-486,-490,-491,-486,-476,-461,-443,-426,-413,-404,-396,-387,-373,-356,-337,-320,-306,
--296,-286,-275,-262,-247,-229,-212,-194,-174,-149,-119,-81,-37,9,55,97,136,173,209,246,283,
-320,358,399,446,498,552,606,657,703,747,791,835,877,917,955,991,1028,1067,1107,1146,1184,
-1220,1255,1290,1325,1360,1393,1426,1459,1492,1526,1561,1595,1630,1666,1704,1741,1777,1812,1847,1883,1921,
-1960,1997,2030,2060,2089,2120,2154,2188,2222,2252,2280,2306,2333,2360,2387,2415,2441,2464,2484,2503,2523,
-2546,2572,2598,2620,2637,2649,2659,2671,2681,2688,2689,2684,2675,2667,2660,2653,2646,2638,2634,2633,2636,
-2638,2636,2628,2615,2601,2590,2581,2573,2564,2552,2537,2519,2502,2488,2479,2473,2470,2463,2450,2431,2407,
-2384,2364,2349,2336,2324,2312,2304,2302,2305,2312,2317,2317,2310,2298,2284,2271,2263,2260,2261,2264,2267,
-2268,2263,2252,2247,2218,2188,2164,2150,2144,2142,2139,2132,2122,2114,2114,2123,2137,2151,2163,2174,2186,
-2201,2216,2228,2238,2249,2270,2304,2344,2380,2400,2401,2391,2385,2393,2415,2445,2472,2490,2500,2506,2513,
-2523,2536,2551,2566,2583,2602,2621,2639,2655,2667,2681,2697,2716,2734,2746,2749,2747,2747,2759,2784,2817,
-2850,2873,2886,2896,2911,2936,2971,3009,3044,3074,3098,3119,3138,3156,3172,3186,3200,3213,3224,3232,3238,
-3244,3251,3262,3274,3286,3295,3300,3303,3305,3307,3308,3307,3302,3295,3288,3284,3284,3286,3288,3290,3292,
-3294,3297,3301,3308,3319,3332,3345,3352,3349,3339,3332,3337,3360,3396,3432,3462,3486,3512,3549,3598,3654,
-3712,3769,3828,3891,3950,3996,4028,4056,4101,4174,4268,4359,4424,4454,4464,4477,4505,4545,4579,4595,4594,
-4587,4583,4582,4578,4567,4555,4552,4558,4567,4564,4547,4525,4514,4523,4545,4560,4556,4533,4507,4493,4499,
-4522,4558,4601,4647,4684,4695,4663,4587,4488,4406,4370,4391,4451,4524,4587,4632,4664,4690,4710,4721,4720,
-4711,4695,4673,4637,4584,4520,4465,4447,4488,4592,4741,4903,5045,5144,5191,5191,5153,5091,5017,4939,4864,
-4796,4730,4662,4589,4513,4442,4386,4349,4330,4320,4310,4295,4278,4265,4257,4251,4240,4220,4193,4164,4138,
-4115,4090,4059,4021,3983,3948,3916,3883,3845,3802,3758,3716,3679,3642,3604,3565,3529,3501,3480,3463,3445,
-3424,3403,3385,3369,3348,3320,3285,3251,3230,3227,3240,3259,3278,3291,3300,3311,3325,3346,3370,3397,3419,
-3429,3422,3399,3365,3335,3315,3309,3307,3301,3287,3267,3247,3231,3217,3201,3180,3156,3134,3115,3097,3074,
-3045,3014,2985,2963,2947,2933,2917,2899,2883,2869,2855,2837,2812,2779,2745,2712,2683,2656,2629,2600,2571,
-2541,2508,2473,2435,2397,2361,2327,2296,2267,2239,2213,2187,2159,2129,2095,2060,2028,2001,1977,1951,1921,
-1888,1853,1821,1793,1766,1738,1707,1673,1637,1597,1556,1515,1475,1437,1401,1363,1322,1280,1239,1200,1165,
-1130,1093,1053,1012,971,933,896,859,820,781,741,700,659,617,576,536,495,451,406,360,317,
-279,243,205,162,116,70,28,-8,-45,-86,-131,-178,-222,-261,-300,-342,-388,-436,-482,-522,-559,
--593,-630,-668,-708,-747,-786,-827,-871,-918,-966,-1013,-1056,-1095,-1132,-1168,-1207,-1246,-1286,-1324,-1359,-1391,
--1422,-1453,-1483,-1514,-1544,-1575,-1607,-1640,-1674,-1707,-1738,-1767,-1796,-1828,-1864,-1903,-1942,-1980,-2016,-2050,-2079,
--2102,-2122,-2140,-2161,-2185,-2212,-2239,-2264,-2286,-2307,-2329,-2351,-2373,-2392,-2411,-2430,-2451,-2473,-2493,-2511,-2526,
--2538,-2550,-2562,-2572,-2581,-2588,-2594,-2598,-2601,-2601,-2600,-2601,-2607,-2617,-2627,-2632,-2632,-2627,-2624,-2626,-2632,
--2638,-2642,-2642,-2640,-2638,-2639,-2642,-2646,-2647,-2646,-2642,-2638,-2634,-2630,-2625,-2618,-2610,-2601,-2594,-2590,-2588,
--2584,-2579,-2572,-2564,-2555,-2546,-2536,-2526,-2517,-2510,-2504,-2496,-2484,-2468,-2452,-2437,-2425,-2413,-2398,-2380,-2361,
--2344,-2329,-2315,-2299,-2281,-2263,-2248,-2233,-2216,-2195,-2170,-2144,-2122,-2104,-2087,-2067,-2044,-2018,-1993,-1972,-1952,
--1932,-1911,-1888,-1867,-1848,-1832,-1818,-1801,-1781,-1758,-1736,-1721,-1719,-1730,-1748,-1764,-1768,-1758,-1741,-1723,-1710,
--1702,-1693,-1678,-1658,-1638,-1621,-1612,-1607,-1603,-1595,-1582,-1566,-1550,-1540,-1535,-1534,-1528,-1511,-1479,-1437,-1396,
--1368,-1359,-1364,-1374,-1380,-1381,-1377,-1374,-1372,-1370,-1365,-1356,-1348,-1345,-1346,-1350,-1353,-1348,-1336,-1319,-1301,
--1285,-1273,-1262,-1250,-1232,-1209,-1187,-1171,-1161,-1157,-1150,-1138,-1122,-1108,-1102,-1103,-1103,-1094,-1074,-1051,-1036,
--1036,-1048,-1058,-1056,-1038,-1011,-985,-966,-950,-931,-905,-876,-849,-827,-810,-793,-774,-755,-737,-718,-691,
--650,-597,-542,-499,-477,-472,-473,-468,-456,-446,-453,-485,-530,-559,-533,-427,-246,-26,174,309,360,
-349,322,319,352,408,462,499,521,542,565,583,577,531,450,352,259,185,134,100,79,66,
-61,59,57,53,49,48,52,60,70,80,87,90,88,78,62,43,25,14,8,4,-3,
--16,-35,-55,-76,-94,-110,-126,-145,-167,-192,-217,-241,-261,-280,-300,-323,-347,-368,-379,-381,-378,
--376,-380,-387,-395,-401,-408,-418,-433,-452,-473,-492,-511,-532,-556,-582,-607,-630,-653,-679,-710,-743,
--771,-793,-806,-817,-827,-838,-852,-866,-883,-902,-921,-936,-944,-947,-951,-962,-980,-1002,-1018,-1025,-1023,
--1021,-1023,-1030,-1039,-1044,-1046,-1048,-1052,-1058,-1063,-1064,-1061,-1055,-1050,-1045,-1041,-1038,-1036,-1036,-1036,-1033,
--1025,-1014,-1004,-998,-995,-990,-982,-975,-974,-984,-997,-1003,-994,-975,-957,-953,-963,-974,-973,-955,-930,
--918,-929,-956,-982,-992,-983,-967,-962,-977,-1010,-1049,-1082,-1104,-1118,-1129,-1138,-1148,-1155,-1161,-1167,-1175,
--1186,-1200,-1213,-1225,-1237,-1249,-1260,-1268,-1273,-1276,-1278,-1284,-1296,-1315,-1337,-1357,-1372,-1377,-1373,-1364,-1355,
--1350,-1353,-1367,-1388,-1412,-1436,-1457,-1474,-1490,-1505,-1518,-1529,-1535,-1538,-1541,-1546,-1555,-1564,-1572,-1574,-1573,
--1570,-1569,-1570,-1572,-1573,-1572,-1572,-1579,-1595,-1616,-1636,-1644,-1638,-1622,-1606,-1599,-1604,-1614,-1618,-1609,-1588,
--1564,-1546,-1538,-1536,-1534,-1528,-1516,-1503,-1494,-1489,-1489,-1491,-1494,-1495,-1497,-1496,-1492,-1483,-1470,-1454,-1437,
--1420,-1405,-1391,-1378,-1367,-1359,-1352,-1345,-1336,-1324,-1311,-1298,-1288,-1279,-1270,-1261,-1252,-1244,-1236,-1228,-1217,
--1204,-1188,-1174,-1163,-1156,-1150,-1142,-1131,-1118,-1105,-1095,-1089,-1085,-1083,-1081,-1079,-1076,-1073,-1069,-1064,-1059,
--1054,-1050,-1046,-1044,-1042,-1041,-1038,-1034,-1028,-1022,-1017,-1013,-1010,-1006,-1000,-993,-986,-981,-979,-978,-976,
--972,-965,-958,-954,-952,-953,-955,-956,-956,-957,-959,-961,-963,-963,-961,-958,-956,-953,-952,-952,-952,
--953,-953,-951,-947,-940,-934,-930,-928,-926,-921,-912,-900,-891,-886,-885,-884,-882,-876,-869,-863,-858,
--851,-841,-828,-815,-803,-794,-787,-778,-766,-750,-731,-711,-690,-668,-645,-622,-601,-583,-572,-566,-565,
--567,-566,-561,-554,-546,-539,-533,-523,-505,-480,-450,-424,-406,-396,-390,-384,-373,-360,-346,-337,-331,
--324,-314,-299,-281,-263,-249,-239,-229,-214,-195,-172,-150,-131,-115,-96,-74,-48,-24,-6,5,14,
-26,43,62,82,101,121,142,166,187,205,220,237,260,291,326,360,389,413,433,450,468,
-487,511,541,576,610,639,662,682,705,731,759,783,803,825,853,888,923,953,975,996,1023,
-1053,1078,1090,1090,1095,1125,1191,1288,1395,1494,1573,1634,1691,1758,1851,1977,2131,2291,2417,2474,2445,
-2344,2207,2072,1961,1875,1800,1728,1662,1608,1572,1549,1531,1513,1493,1475,1458,1437,1408,1373,1336,1301,
-1269,1236,1202,1173,1154,1149,1156,1165,1172,1177,1183,1192,1198,1194,1179,1156,1134,1120,1112,1103,1088,
-1067,1045,1026,1007,981,937,872,789,699,613,542,493,465,451,437,409,361,295,224,159,108,
-69,40,16,-2,-15,-24,-30,-39,-52,-70,-90,-112,-137,-164,-192,-219,-241,-261,-278,-297,-316,
--332,-344,-352,-358,-366,-377,-390,-402,-412,-417,-417,-413,-406,-397,-388,-379,-371,-365,-360,-357,-356,
--354,-349,-341,-330,-322,-322,-334,-354,-378,-399,-414,-423,-431,-439,-448,-457,-464,-471,-475,-477,-473,
--460,-441,-418,-398,-384,-377,-372,-366,-355,-340,-325,-311,-298,-286,-274,-259,-243,-227,-211,-194,-176,
--155,-130,-99,-63,-23,19,62,104,144,183,222,259,294,327,362,403,451,505,560,611,658,
-703,748,795,843,889,929,966,1000,1036,1074,1112,1150,1186,1222,1257,1292,1327,1359,1391,1423,1456,
-1490,1523,1556,1588,1622,1658,1695,1733,1770,1807,1846,1886,1927,1964,1998,2028,2056,2085,2118,2153,2187,
-2218,2247,2274,2301,2329,2358,2388,2417,2444,2469,2489,2506,2523,2544,2570,2599,2626,2647,2662,2674,2684,
-2693,2700,2704,2702,2696,2687,2676,2664,2654,2647,2646,2650,2657,2662,2659,2648,2630,2609,2588,2569,2551,
-2533,2516,2500,2485,2473,2464,2460,2458,2457,2452,2442,2426,2407,2388,2371,2358,2346,2336,2328,2323,2323,
-2328,2333,2335,2330,2319,2302,2284,2268,2260,2259,2265,2275,2282,2281,2270,2247,2228,2204,2185,2173,2170,
-2171,2168,2158,2140,2121,2111,2114,2129,2147,2161,2167,2171,2177,2190,2207,2223,2239,2260,2293,2340,2391,
-2433,2454,2454,2443,2435,2438,2451,2464,2470,2468,2462,2460,2465,2477,2493,2511,2529,2547,2565,2582,2599,
-2617,2638,2663,2689,2711,2725,2730,2730,2732,2740,2760,2788,2820,2847,2866,2877,2888,2906,2935,2974,3015,
-3052,3081,3101,3115,3127,3139,3152,3165,3177,3188,3198,3207,3214,3223,3234,3248,3264,3277,3285,3288,3288,
-3288,3290,3294,3295,3292,3285,3278,3275,3278,3283,3287,3288,3288,3290,3296,3306,3318,3329,3337,3343,3345,
-3343,3340,3341,3353,3381,3418,3458,3492,3520,3551,3592,3647,3715,3786,3856,3918,3969,4006,4032,4055,4092,
-4156,4245,4343,4424,4470,4485,4487,4498,4526,4560,4586,4595,4591,4583,4577,4570,4561,4555,4561,4582,4607,
-4615,4593,4548,4506,4495,4522,4565,4589,4575,4526,4469,4430,4424,4449,4498,4564,4640,4709,4742,4715,4626,
-4503,4394,4341,4356,4420,4500,4568,4617,4655,4687,4714,4729,4727,4711,4688,4660,4622,4571,4512,4466,4459,
-4514,4631,4787,4946,5069,5136,5149,5126,5089,5057,5035,5020,5001,4969,4915,4838,4741,4631,4523,4432,4369,
-4334,4319,4310,4299,4284,4268,4256,4248,4238,4221,4198,4173,4150,4128,4103,4070,4031,3991,3955,3923,3893,
-3857,3817,3775,3735,3700,3666,3630,3595,3564,3540,3521,3501,3477,3451,3430,3417,3410,3398,3372,3334,3292,
-3262,3253,3264,3287,3312,3334,3354,3376,3402,3432,3464,3494,3517,3526,3518,3490,3453,3415,3386,3368,3354,
-3339,3318,3296,3277,3262,3249,3233,3213,3192,3173,3154,3133,3106,3074,3044,3021,3008,2999,2989,2973,2953,
-2932,2912,2890,2865,2834,2801,2770,2743,2719,2693,2665,2633,2601,2568,2535,2501,2465,2430,2397,2367,2338,
-2309,2279,2249,2220,2191,2158,2124,2089,2058,2030,2005,1978,1948,1916,1884,1854,1826,1799,1770,1738,1703,
-1666,1628,1588,1549,1511,1476,1440,1403,1363,1321,1281,1243,1207,1168,1127,1084,1042,1003,967,931,892,
-851,810,771,731,690,647,604,563,524,485,446,404,362,321,283,243,200,154,107,65,28,
--5,-42,-83,-127,-170,-213,-254,-297,-343,-390,-434,-473,-508,-542,-578,-618,-660,-702,-745,-788,-832,
--879,-925,-968,-1007,-1043,-1078,-1115,-1153,-1194,-1236,-1275,-1312,-1346,-1378,-1408,-1438,-1468,-1498,-1530,-1563,-1598,
--1631,-1662,-1690,-1717,-1747,-1781,-1819,-1859,-1897,-1935,-1970,-2004,-2033,-2058,-2078,-2096,-2117,-2141,-2168,-2193,-2215,
--2234,-2254,-2278,-2304,-2329,-2351,-2369,-2386,-2404,-2426,-2448,-2469,-2486,-2500,-2512,-2524,-2535,-2545,-2553,-2559,-2562,
--2565,-2565,-2567,-2570,-2577,-2587,-2596,-2602,-2603,-2600,-2599,-2601,-2606,-2612,-2616,-2616,-2614,-2614,-2617,-2623,-2628,
--2629,-2627,-2622,-2618,-2615,-2612,-2606,-2598,-2587,-2577,-2572,-2570,-2570,-2568,-2561,-2552,-2542,-2533,-2524,-2515,-2506,
--2499,-2495,-2492,-2487,-2474,-2456,-2437,-2422,-2412,-2404,-2391,-2372,-2350,-2330,-2314,-2302,-2288,-2270,-2250,-2231,-2215,
--2200,-2182,-2159,-2134,-2112,-2093,-2077,-2060,-2037,-2011,-1985,-1963,-1944,-1927,-1909,-1888,-1867,-1848,-1832,-1818,-1801,
--1779,-1753,-1730,-1717,-1717,-1731,-1751,-1767,-1771,-1762,-1744,-1727,-1714,-1706,-1697,-1681,-1658,-1634,-1617,-1610,-1612,
--1616,-1613,-1599,-1576,-1556,-1547,-1554,-1569,-1579,-1568,-1532,-1478,-1423,-1381,-1360,-1354,-1353,-1351,-1348,-1348,-1356,
--1367,-1376,-1378,-1372,-1364,-1362,-1367,-1378,-1386,-1386,-1376,-1358,-1337,-1317,-1300,-1284,-1269,-1252,-1235,-1221,-1210,
--1202,-1195,-1185,-1171,-1156,-1145,-1140,-1140,-1139,-1131,-1117,-1103,-1098,-1102,-1111,-1114,-1103,-1081,-1056,-1034,-1018,
--1000,-976,-946,-917,-896,-884,-877,-866,-845,-817,-786,-752,-713,-664,-610,-559,-524,-507,-502,-496,-482,
--466,-463,-486,-529,-566,-560,-485,-338,-148,35,170,237,248,240,245,280,335,384,412,418,416,
-422,436,445,428,377,298,211,134,78,40,16,-1,-14,-24,-31,-36,-41,-43,-42,-36,-29,
--23,-19,-16,-15,-17,-26,-43,-64,-83,-95,-98,-97,-100,-109,-127,-148,-171,-190,-207,-224,-244,
--270,-302,-336,-367,-392,-411,-426,-442,-459,-475,-486,-492,-496,-501,-510,-519,-527,-533,-539,-549,-564,
--581,-596,-607,-615,-627,-645,-668,-693,-716,-739,-763,-789,-816,-840,-860,-875,-890,-904,-918,-929,-939,
--950,-965,-984,-1001,-1013,-1016,-1017,-1021,-1031,-1047,-1061,-1069,-1071,-1070,-1071,-1074,-1077,-1077,-1076,-1077,-1083,
--1092,-1100,-1105,-1105,-1104,-1102,-1100,-1096,-1090,-1086,-1084,-1083,-1082,-1077,-1069,-1063,-1061,-1062,-1059,-1050,-1035,
--1023,-1021,-1029,-1042,-1050,-1053,-1054,-1057,-1060,-1055,-1033,-996,-958,-939,-948,-978,-1009,-1023,-1015,-998,-990,
--1003,-1034,-1072,-1104,-1125,-1138,-1150,-1164,-1179,-1191,-1197,-1199,-1201,-1206,-1217,-1230,-1245,-1259,-1272,-1285,-1295,
--1301,-1303,-1304,-1307,-1317,-1334,-1355,-1375,-1388,-1393,-1392,-1388,-1383,-1378,-1377,-1381,-1393,-1412,-1435,-1459,-1480,
--1498,-1514,-1528,-1540,-1548,-1553,-1557,-1563,-1572,-1583,-1592,-1596,-1596,-1593,-1593,-1593,-1593,-1589,-1582,-1578,-1583,
--1601,-1626,-1649,-1658,-1652,-1635,-1619,-1613,-1615,-1620,-1619,-1607,-1589,-1572,-1562,-1561,-1564,-1563,-1555,-1540,-1522,
--1506,-1494,-1487,-1484,-1484,-1485,-1487,-1489,-1487,-1481,-1470,-1455,-1440,-1424,-1409,-1395,-1382,-1372,-1364,-1357,-1348,
--1336,-1322,-1308,-1297,-1287,-1278,-1268,-1256,-1245,-1234,-1227,-1220,-1212,-1201,-1189,-1178,-1171,-1167,-1162,-1154,-1144,
--1132,-1121,-1113,-1107,-1101,-1094,-1087,-1081,-1075,-1071,-1065,-1059,-1052,-1046,-1041,-1039,-1038,-1037,-1035,-1031,-1026,
--1019,-1013,-1008,-1005,-1002,-997,-990,-981,-972,-966,-965,-966,-967,-965,-958,-951,-945,-943,-945,-948,-951,
--952,-953,-955,-957,-958,-959,-958,-957,-958,-959,-960,-960,-959,-958,-956,-953,-949,-942,-936,-931,-928,
--925,-921,-913,-902,-892,-886,-884,-884,-883,-880,-875,-872,-868,-864,-856,-845,-830,-817,-805,-794,-782,
--767,-748,-728,-707,-689,-674,-659,-645,-629,-615,-601,-590,-580,-571,-563,-555,-550,-548,-547,-544,-535,
--518,-495,-470,-447,-429,-416,-407,-398,-388,-377,-365,-354,-343,-331,-317,-301,-283,-266,-250,-236,-221,
--203,-183,-162,-144,-130,-118,-101,-79,-51,-24,-4,8,17,27,42,62,84,105,127,149,172,
-192,208,222,237,258,285,316,345,370,392,413,434,456,479,503,530,559,587,613,634,655,
-678,704,730,753,774,799,830,866,901,929,951,975,1005,1037,1060,1069,1067,1075,1113,1191,1299,
-1415,1517,1596,1655,1707,1768,1852,1969,2115,2273,2406,2478,2466,2376,2243,2104,1985,1890,1807,1727,1650,
-1585,1540,1514,1497,1481,1461,1441,1422,1404,1383,1357,1327,1295,1261,1226,1190,1160,1142,1139,1147,1158,
-1165,1167,1168,1171,1176,1177,1172,1159,1144,1130,1119,1108,1095,1077,1059,1041,1023,997,956,894,815,
-727,643,575,530,504,487,464,428,376,315,254,198,148,103,63,29,4,-11,-20,-29,-42,
--61,-83,-104,-124,-145,-167,-191,-214,-234,-252,-271,-292,-314,-332,-346,-354,-361,-368,-379,-392,-404,
--414,-420,-422,-420,-413,-405,-395,-386,-379,-374,-371,-368,-366,-361,-353,-340,-327,-316,-314,-322,-338,
--356,-372,-385,-395,-406,-419,-430,-439,-445,-448,-450,-448,-441,-425,-403,-378,-358,-346,-341,-339,-336,
--329,-320,-310,-300,-289,-275,-258,-240,-222,-206,-190,-172,-151,-126,-99,-68,-34,2,41,80,121,
-161,201,240,274,305,334,367,407,457,512,567,618,662,705,749,797,846,893,935,973,1011,
-1048,1086,1122,1156,1189,1222,1257,1292,1327,1361,1393,1424,1457,1490,1522,1553,1584,1617,1652,1690,1728,
-1767,1805,1845,1887,1928,1965,1998,2028,2057,2088,2121,2156,2188,2218,2246,2273,2300,2329,2358,2388,2417,
-2446,2473,2496,2516,2534,2553,2576,2602,2629,2653,2673,2688,2699,2707,2713,2717,2716,2713,2706,2696,2686,
-2678,2674,2675,2679,2683,2683,2676,2662,2642,2618,2592,2564,2536,2513,2498,2491,2490,2492,2493,2489,2482,
-2474,2464,2454,2442,2429,2416,2402,2389,2377,2367,2359,2352,2347,2340,2333,2324,2313,2301,2288,2276,2267,
-2262,2263,2268,2272,2273,2266,2251,2228,2234,2221,2212,2206,2202,2197,2188,2172,2151,2133,2124,2128,2141,
-2157,2168,2173,2177,2188,2205,2225,2242,2257,2277,2309,2354,2405,2446,2471,2480,2485,2493,2506,2515,2510,
-2490,2464,2444,2438,2446,2461,2477,2493,2510,2528,2547,2563,2575,2589,2608,2634,2663,2687,2701,2705,2704,
-2706,2718,2741,2771,2802,2830,2853,2870,2887,2908,2936,2971,3010,3046,3073,3091,3101,3109,3116,3126,3138,
-3151,3164,3176,3188,3199,3209,3221,3234,3248,3262,3271,3274,3274,3274,3276,3279,3280,3278,3272,3269,3271,
-3279,3288,3293,3292,3289,3291,3301,3317,3332,3341,3344,3345,3346,3350,3356,3365,3381,3406,3441,3481,3522,
-3559,3597,3643,3702,3775,3855,3930,3991,4031,4051,4062,4081,4124,4198,4292,4384,4452,4486,4496,4501,4515,
-4541,4567,4582,4583,4575,4563,4550,4536,4530,4542,4582,4641,4688,4692,4639,4552,4479,4459,4496,4558,4595,
-4581,4521,4447,4395,4376,4389,4423,4475,4538,4602,4640,4626,4557,4455,4365,4326,4347,4409,4483,4545,4591,
-4630,4668,4700,4719,4719,4702,4677,4647,4611,4564,4510,4465,4455,4498,4595,4723,4850,4943,4989,4993,4980,
-4975,4992,5028,5066,5087,5076,5029,4948,4841,4719,4596,4487,4403,4351,4325,4314,4305,4292,4277,4263,4252,
-4241,4226,4206,4183,4160,4137,4111,4079,4040,4001,3966,3937,3909,3877,3839,3798,3758,3722,3689,3656,3626,
-3600,3578,3557,3532,3503,3473,3452,3445,3445,3439,3418,3380,3337,3304,3293,3302,3325,3355,3386,3420,3457,
-3495,3530,3560,3584,3600,3606,3598,3576,3541,3503,3467,3436,3410,3386,3363,3342,3326,3311,3295,3276,3254,
-3234,3216,3197,3172,3140,3105,3076,3057,3048,3042,3032,3016,2995,2973,2950,2923,2891,2855,2822,2794,2771,
-2750,2723,2691,2655,2621,2589,2558,2527,2494,2463,2434,2407,2379,2348,2315,2281,2250,2220,2191,2159,2127,
-2095,2065,2036,2006,1973,1939,1908,1879,1853,1826,1797,1764,1729,1693,1656,1618,1579,1542,1506,1472,1436,
-1399,1360,1322,1285,1246,1205,1161,1117,1076,1039,1003,965,923,879,837,799,761,721,678,632,589,
-551,516,480,441,398,356,316,277,237,193,148,106,69,36,2,-34,-76,-121,-166,-209,-251,
--295,-338,-380,-419,-455,-490,-527,-567,-610,-655,-701,-746,-790,-834,-877,-917,-955,-992,-1028,-1064,-1103,
--1144,-1184,-1223,-1260,-1294,-1327,-1358,-1389,-1420,-1452,-1486,-1521,-1555,-1588,-1617,-1645,-1673,-1705,-1742,-1781,-1820,
--1856,-1891,-1924,-1955,-1985,-2009,-2030,-2048,-2069,-2094,-2120,-2145,-2167,-2186,-2205,-2229,-2257,-2284,-2308,-2327,-2345,
--2364,-2386,-2409,-2430,-2446,-2459,-2472,-2485,-2499,-2511,-2521,-2527,-2530,-2532,-2533,-2535,-2540,-2547,-2557,-2566,-2573,
--2576,-2576,-2576,-2578,-2582,-2588,-2591,-2593,-2593,-2595,-2599,-2604,-2608,-2609,-2605,-2600,-2596,-2593,-2591,-2586,-2578,
--2568,-2560,-2556,-2556,-2556,-2552,-2543,-2532,-2522,-2514,-2507,-2499,-2490,-2483,-2481,-2481,-2477,-2466,-2446,-2423,-2405,
--2394,-2387,-2375,-2357,-2333,-2312,-2297,-2286,-2275,-2258,-2237,-2215,-2197,-2183,-2168,-2148,-2125,-2101,-2081,-2065,-2048,
--2028,-2003,-1978,-1955,-1938,-1922,-1905,-1886,-1866,-1846,-1830,-1813,-1794,-1771,-1744,-1721,-1708,-1710,-1725,-1747,-1766,
--1773,-1767,-1751,-1733,-1719,-1707,-1696,-1679,-1656,-1633,-1618,-1615,-1623,-1634,-1634,-1619,-1593,-1570,-1561,-1572,-1595,
--1612,-1605,-1569,-1512,-1452,-1403,-1370,-1349,-1330,-1312,-1299,-1296,-1306,-1325,-1343,-1353,-1356,-1358,-1365,-1379,-1398,
--1412,-1417,-1411,-1397,-1378,-1358,-1338,-1317,-1298,-1281,-1267,-1255,-1246,-1236,-1226,-1214,-1203,-1193,-1188,-1186,-1185,
--1182,-1175,-1167,-1162,-1160,-1161,-1160,-1151,-1133,-1111,-1089,-1072,-1057,-1039,-1016,-991,-971,-960,-953,-943,-923,
--890,-849,-806,-763,-719,-672,-626,-589,-566,-556,-551,-542,-528,-521,-532,-564,-599,-608,-562,-452,-297,
--137,-10,62,87,93,112,160,229,296,337,347,334,317,306,300,285,251,194,127,63,14,
--20,-45,-66,-83,-97,-106,-113,-117,-120,-119,-115,-108,-103,-101,-104,-107,-110,-115,-125,-143,-165,
--185,-197,-200,-199,-199,-206,-220,-239,-258,-276,-293,-311,-332,-360,-394,-430,-465,-496,-520,-539,-555,
--571,-586,-597,-606,-614,-625,-637,-650,-661,-669,-677,-686,-699,-712,-722,-728,-733,-740,-752,-769,-787,
--806,-824,-844,-866,-889,-910,-928,-944,-961,-979,-996,-1008,-1015,-1020,-1028,-1042,-1059,-1073,-1079,-1079,-1079,
--1082,-1090,-1100,-1110,-1117,-1122,-1124,-1123,-1119,-1112,-1107,-1107,-1114,-1125,-1135,-1142,-1146,-1148,-1150,-1150,-1146,
--1139,-1133,-1131,-1133,-1136,-1135,-1129,-1122,-1119,-1118,-1116,-1108,-1095,-1082,-1076,-1078,-1087,-1095,-1099,-1103,-1108,
--1112,-1108,-1089,-1055,-1021,-1001,-1006,-1030,-1057,-1070,-1065,-1049,-1040,-1048,-1072,-1102,-1126,-1140,-1147,-1158,-1175,
--1198,-1218,-1231,-1236,-1237,-1241,-1248,-1260,-1272,-1284,-1295,-1307,-1318,-1327,-1332,-1334,-1336,-1343,-1356,-1372,-1386,
--1394,-1399,-1402,-1406,-1411,-1413,-1413,-1412,-1415,-1426,-1445,-1467,-1487,-1505,-1520,-1534,-1549,-1562,-1571,-1578,-1585,
--1594,-1606,-1617,-1624,-1625,-1623,-1622,-1621,-1619,-1613,-1604,-1597,-1599,-1614,-1636,-1655,-1663,-1657,-1643,-1630,-1623,
--1621,-1619,-1613,-1602,-1591,-1584,-1585,-1590,-1594,-1590,-1579,-1563,-1544,-1527,-1512,-1500,-1490,-1483,-1478,-1476,-1474,
--1472,-1467,-1461,-1453,-1443,-1431,-1418,-1405,-1393,-1383,-1373,-1363,-1351,-1335,-1319,-1305,-1294,-1286,-1278,-1267,-1252,
--1237,-1223,-1213,-1206,-1200,-1192,-1184,-1177,-1173,-1171,-1167,-1161,-1152,-1143,-1136,-1132,-1128,-1121,-1112,-1101,-1092,
--1084,-1078,-1071,-1062,-1053,-1046,-1041,-1038,-1035,-1031,-1026,-1020,-1014,-1008,-1003,-998,-995,-992,-988,-981,-973,
--964,-958,-955,-956,-957,-955,-950,-943,-938,-938,-942,-946,-950,-951,-951,-952,-953,-954,-954,-954,-955,
--956,-958,-960,-960,-959,-959,-959,-958,-956,-951,-944,-936,-931,-927,-923,-916,-908,-899,-892,-889,-888,
--887,-885,-881,-878,-874,-869,-861,-850,-836,-823,-811,-800,-787,-771,-751,-730,-712,-698,-689,-682,-674,
--664,-652,-637,-620,-602,-585,-571,-561,-556,-555,-556,-553,-546,-533,-516,-498,-479,-461,-444,-429,-418,
--408,-399,-390,-377,-362,-346,-328,-310,-292,-273,-254,-236,-217,-197,-175,-155,-139,-126,-114,-98,-75,
--47,-20,0,12,19,28,43,61,80,99,117,136,157,176,194,210,228,250,275,302,327,
-350,373,397,424,451,474,495,515,536,558,582,608,635,664,693,719,741,762,787,817,850,
-879,903,926,951,982,1010,1024,1022,1016,1028,1077,1164,1271,1374,1459,1529,1597,1676,1766,1865,1969,
-2076,2185,2282,2345,2353,2301,2205,2091,1980,1882,1792,1705,1623,1556,1508,1481,1463,1447,1428,1407,1387,
-1369,1350,1326,1298,1268,1239,1210,1182,1158,1143,1140,1147,1157,1163,1161,1156,1153,1157,1165,1171,1169,
-1159,1145,1131,1120,1110,1099,1086,1070,1049,1019,975,914,836,751,673,612,571,545,523,493,451,
-399,346,294,244,192,137,83,37,7,-8,-16,-25,-41,-64,-88,-110,-129,-145,-163,-183,-204,
--224,-244,-265,-286,-307,-325,-339,-350,-360,-371,-383,-395,-404,-411,-415,-417,-416,-413,-407,-400,-394,
--389,-386,-383,-380,-376,-369,-358,-343,-327,-314,-308,-309,-317,-327,-336,-345,-355,-369,-385,-400,-410,
--415,-416,-414,-410,-401,-384,-362,-339,-321,-311,-307,-305,-302,-298,-292,-287,-282,-273,-260,-243,-224,
--207,-190,-172,-150,-125,-96,-65,-33,1,37,76,116,155,194,232,268,301,330,359,390,430,
-478,532,585,632,675,715,757,802,847,891,932,972,1012,1054,1094,1130,1162,1192,1225,1260,1298,
-1334,1368,1399,1429,1459,1489,1519,1549,1579,1613,1650,1689,1729,1768,1806,1845,1885,1925,1963,1998,2030,
-2062,2095,2128,2162,2193,2221,2247,2273,2299,2326,2353,2381,2409,2439,2468,2496,2520,2542,2561,2579,2598,
-2619,2643,2666,2688,2706,2719,2727,2731,2732,2732,2730,2725,2720,2714,2711,2709,2707,2702,2693,2680,2665,
-2650,2633,2612,2586,2561,2543,2536,2542,2555,2565,2565,2553,2531,2507,2486,2471,2461,2451,2440,2425,2411,
-2398,2389,2383,2377,2368,2354,2338,2321,2307,2297,2291,2286,2283,2280,2278,2277,2274,2268,2259,2247,2234,
-2259,2252,2242,2229,2215,2201,2188,2174,2159,2148,2143,2148,2159,2171,2180,2186,2195,2211,2233,2254,2269,
-2279,2292,2317,2355,2400,2440,2471,2496,2522,2552,2577,2582,2560,2519,2478,2455,2457,2474,2493,2505,2512,
-2521,2537,2557,2573,2582,2586,2594,2611,2636,2660,2676,2681,2681,2684,2696,2719,2750,2783,2815,2843,2866,
-2886,2906,2931,2962,2998,3033,3061,3078,3088,3093,3100,3110,3123,3137,3151,3166,3180,3193,3204,3213,3223,
-3235,3247,3258,3264,3265,3265,3264,3265,3264,3261,3257,3257,3265,3279,3292,3299,3297,3292,3294,3305,3323,
-3339,3348,3350,3350,3356,3367,3381,3394,3408,3430,3463,3506,3554,3601,3646,3697,3759,3833,3914,3986,4039,
-4067,4076,4082,4104,4153,4228,4314,4391,4445,4475,4489,4503,4523,4544,4559,4562,4555,4542,4526,4506,4485,
-4479,4505,4570,4653,4714,4711,4636,4522,4428,4400,4439,4508,4554,4546,4494,4431,4386,4368,4367,4371,4378,
-4395,4421,4444,4445,4416,4370,4333,4329,4363,4418,4474,4520,4556,4593,4631,4666,4687,4689,4676,4657,4633,
-4603,4562,4510,4462,4437,4450,4504,4585,4670,4736,4775,4794,4810,4840,4891,4953,5006,5032,5019,4971,4896,
-4806,4707,4605,4508,4427,4370,4339,4325,4317,4307,4292,4277,4262,4249,4232,4212,4188,4164,4141,4116,4086,
-4051,4016,3985,3958,3931,3901,3864,3823,3782,3745,3711,3682,3654,3630,3607,3582,3555,3525,3499,3484,3480,
-3480,3473,3450,3413,3375,3349,3342,3354,3379,3411,3450,3496,3546,3593,3631,3656,3669,3676,3678,3673,3659,
-3634,3601,3564,3529,3498,3472,3452,3436,3421,3403,3379,3351,3322,3297,3276,3253,3224,3187,3149,3117,3095,
-3082,3069,3053,3032,3010,2991,2970,2944,2912,2875,2843,2817,2796,2773,2742,2706,2668,2635,2607,2580,2552,
-2523,2495,2470,2446,2419,2386,2348,2311,2278,2251,2225,2197,2166,2134,2103,2072,2040,2005,1969,1935,1904,
-1876,1848,1818,1786,1752,1718,1683,1647,1609,1571,1535,1500,1466,1431,1394,1357,1319,1280,1239,1195,1153,
-1114,1078,1041,1001,956,910,867,829,794,755,712,667,624,586,551,515,473,428,383,342,306,
-269,229,187,145,108,76,45,11,-30,-75,-122,-166,-207,-248,-289,-330,-370,-407,-443,-480,-519,
--563,-609,-656,-701,-744,-785,-826,-865,-904,-943,-981,-1019,-1057,-1097,-1137,-1176,-1211,-1245,-1276,-1308,-1341,
--1374,-1408,-1443,-1477,-1511,-1543,-1573,-1602,-1633,-1668,-1705,-1744,-1781,-1815,-1846,-1877,-1907,-1936,-1962,-1983,-2003,
--2024,-2048,-2075,-2101,-2124,-2144,-2163,-2185,-2210,-2235,-2258,-2280,-2302,-2325,-2350,-2373,-2392,-2405,-2416,-2428,-2444,
--2461,-2478,-2490,-2496,-2499,-2500,-2501,-2505,-2512,-2521,-2532,-2541,-2549,-2554,-2556,-2557,-2558,-2561,-2565,-2569,-2571,
--2573,-2576,-2581,-2586,-2589,-2589,-2586,-2581,-2577,-2575,-2573,-2569,-2562,-2553,-2547,-2544,-2544,-2542,-2536,-2525,-2514,
--2505,-2499,-2495,-2487,-2478,-2470,-2466,-2466,-2463,-2453,-2433,-2409,-2388,-2375,-2367,-2356,-2339,-2316,-2295,-2280,-2270,
--2261,-2246,-2225,-2203,-2184,-2170,-2156,-2139,-2118,-2094,-2072,-2053,-2036,-2017,-1995,-1972,-1950,-1932,-1916,-1899,-1879,
--1858,-1838,-1821,-1805,-1787,-1765,-1741,-1719,-1705,-1705,-1719,-1739,-1759,-1770,-1768,-1755,-1736,-1719,-1706,-1694,-1680,
--1662,-1643,-1630,-1629,-1637,-1647,-1648,-1633,-1607,-1583,-1574,-1584,-1605,-1621,-1615,-1583,-1533,-1478,-1430,-1392,-1358,
--1323,-1289,-1261,-1248,-1253,-1269,-1289,-1306,-1322,-1340,-1363,-1391,-1416,-1433,-1438,-1433,-1423,-1411,-1397,-1382,-1364,
--1345,-1327,-1312,-1300,-1288,-1275,-1262,-1252,-1245,-1242,-1242,-1242,-1239,-1234,-1227,-1221,-1217,-1212,-1204,-1192,-1174,
--1154,-1134,-1116,-1100,-1084,-1067,-1053,-1043,-1038,-1032,-1020,-995,-956,-909,-861,-815,-771,-727,-685,-649,-626,
--616,-614,-611,-605,-601,-611,-640,-677,-698,-677,-600,-476,-338,-218,-139,-100,-79,-50,3,78,158,
-221,253,256,241,219,196,167,126,72,14,-37,-75,-98,-114,-130,-148,-164,-176,-181,-183,-185,
--186,-184,-180,-174,-171,-174,-181,-188,-194,-199,-207,-221,-239,-257,-269,-275,-276,-278,-284,-293,-304,
--316,-329,-345,-366,-391,-421,-454,-489,-526,-564,-600,-634,-664,-688,-705,-716,-722,-728,-737,-751,-767,
--783,-795,-805,-814,-824,-834,-843,-850,-855,-861,-869,-877,-886,-894,-905,-920,-939,-960,-978,-993,-1007,
--1023,-1042,-1062,-1077,-1086,-1090,-1094,-1102,-1114,-1126,-1134,-1136,-1135,-1135,-1138,-1146,-1156,-1165,-1173,-1177,-1174,
--1167,-1156,-1148,-1145,-1150,-1158,-1167,-1174,-1178,-1183,-1187,-1188,-1185,-1180,-1176,-1177,-1183,-1189,-1190,-1185,-1176,
--1169,-1166,-1164,-1160,-1153,-1145,-1140,-1139,-1141,-1142,-1140,-1139,-1141,-1147,-1149,-1142,-1123,-1099,-1083,-1083,-1098,
--1117,-1128,-1125,-1113,-1105,-1109,-1124,-1143,-1157,-1162,-1163,-1168,-1184,-1209,-1235,-1255,-1267,-1273,-1279,-1287,-1296,
--1305,-1312,-1320,-1329,-1341,-1354,-1362,-1365,-1367,-1370,-1378,-1387,-1395,-1399,-1401,-1406,-1416,-1431,-1443,-1449,-1449,
--1449,-1455,-1468,-1485,-1500,-1513,-1524,-1537,-1553,-1569,-1584,-1594,-1602,-1612,-1624,-1637,-1646,-1650,-1650,-1648,-1647,
--1645,-1641,-1634,-1629,-1630,-1638,-1651,-1660,-1662,-1655,-1643,-1633,-1627,-1622,-1616,-1608,-1601,-1599,-1602,-1609,-1614,
--1612,-1603,-1588,-1572,-1557,-1544,-1532,-1520,-1507,-1495,-1485,-1476,-1469,-1462,-1457,-1453,-1449,-1445,-1437,-1426,-1413,
--1400,-1388,-1378,-1367,-1355,-1339,-1323,-1310,-1300,-1292,-1284,-1272,-1256,-1238,-1222,-1208,-1198,-1188,-1180,-1172,-1166,
--1163,-1161,-1157,-1152,-1145,-1139,-1136,-1135,-1134,-1129,-1120,-1111,-1102,-1094,-1086,-1077,-1067,-1057,-1049,-1044,-1039,
--1034,-1027,-1018,-1009,-1002,-997,-994,-992,-989,-986,-982,-978,-971,-964,-958,-954,-952,-951,-948,-944,-940,
--937,-938,-942,-946,-949,-950,-950,-950,-951,-953,-955,-955,-955,-954,-954,-954,-954,-954,-955,-958,-961,
--963,-960,-953,-944,-937,-931,-928,-924,-919,-913,-907,-902,-899,-896,-893,-889,-885,-879,-872,-862,-850,
--837,-826,-815,-805,-793,-777,-758,-738,-722,-712,-707,-705,-702,-695,-682,-664,-644,-622,-603,-588,-579,
--576,-576,-575,-571,-564,-553,-541,-528,-512,-493,-473,-455,-442,-433,-426,-417,-404,-386,-367,-347,-326,
--306,-285,-264,-243,-222,-199,-177,-156,-138,-123,-109,-92,-69,-43,-19,-1,9,16,25,38,54,
-71,85,100,115,134,154,175,195,217,241,266,291,314,337,362,391,421,448,470,486,500,
-514,534,559,589,621,654,683,707,727,748,771,799,827,850,870,892,919,948,967,967,951,
-939,960,1026,1126,1231,1315,1376,1434,1517,1634,1770,1895,1984,2038,2074,2107,2140,2158,2144,2093,2013,
-1920,1830,1746,1671,1604,1550,1511,1483,1459,1434,1407,1380,1356,1336,1314,1289,1260,1233,1210,1192,1174,
-1158,1146,1142,1148,1157,1162,1157,1147,1140,1141,1152,1163,1168,1162,1149,1138,1133,1132,1132,1124,1107,
-1080,1042,992,929,853,773,700,645,609,584,558,524,479,429,382,338,293,239,177,112,57,
-20,1,-7,-18,-35,-59,-85,-106,-124,-139,-155,-174,-195,-216,-237,-257,-278,-296,-312,-326,-340,
--355,-371,-385,-396,-402,-404,-405,-406,-407,-405,-402,-399,-396,-394,-392,-390,-386,-380,-371,-359,-342,
--323,-306,-294,-289,-290,-295,-300,-307,-316,-330,-347,-362,-372,-377,-379,-378,-375,-366,-351,-331,-310,
--293,-283,-279,-277,-273,-268,-263,-259,-254,-247,-235,-220,-204,-188,-170,-149,-124,-95,-64,-33,0,
-35,75,117,158,197,233,267,302,336,369,401,434,471,514,560,606,649,689,729,770,813,
-854,893,930,968,1008,1051,1092,1129,1162,1195,1230,1269,1310,1348,1382,1410,1437,1465,1493,1522,1552,
-1583,1617,1654,1694,1735,1774,1812,1850,1887,1925,1962,1998,2032,2066,2099,2132,2164,2194,2220,2244,2267,
-2289,2313,2338,2364,2392,2420,2450,2479,2509,2536,2558,2575,2589,2604,2624,2650,2679,2705,2726,2739,2745,
-2749,2752,2753,2751,2746,2739,2732,2725,2718,2708,2697,2686,2677,2671,2666,2657,2644,2630,2620,2619,2627,
-2637,2639,2627,2600,2565,2530,2503,2486,2475,2466,2454,2438,2421,2409,2403,2401,2399,2393,2380,2363,2346,
-2333,2324,2318,2312,2306,2300,2294,2287,2281,2274,2268,2263,2259,2277,2270,2257,2237,2218,2202,2193,2186,
-2180,2175,2173,2177,2186,2195,2200,2204,2211,2224,2244,2264,2278,2287,2300,2322,2357,2398,2435,2468,2501,
-2539,2580,2609,2609,2577,2528,2489,2480,2504,2541,2570,2579,2574,2570,2577,2593,2608,2611,2605,2600,2606,
-2625,2650,2671,2681,2685,2690,2702,2724,2753,2786,2817,2845,2867,2884,2901,2923,2953,2988,3024,3052,3069,
-3077,3084,3093,3107,3122,3137,3150,3164,3178,3192,3203,3211,3218,3227,3237,3247,3254,3257,3257,3256,3255,
-3253,3249,3245,3246,3256,3273,3291,3301,3301,3297,3297,3308,3324,3339,3348,3352,3356,3365,3381,3398,3414,
-3431,3455,3492,3540,3593,3645,3694,3749,3815,3891,3968,4031,4068,4082,4085,4097,4130,4187,4258,4326,4381,
-4419,4445,4470,4496,4521,4537,4540,4532,4520,4508,4492,4468,4440,4426,4445,4504,4581,4634,4626,4550,4442,
-4357,4334,4373,4436,4478,4476,4443,4407,4389,4386,4382,4364,4332,4302,4287,4288,4297,4305,4313,4327,4356,
-4394,4433,4465,4490,4516,4549,4586,4619,4638,4641,4636,4627,4615,4595,4560,4513,4463,4424,4410,4424,4460,
-4506,4550,4587,4618,4650,4690,4738,4787,4821,4828,4805,4760,4706,4651,4596,4540,4480,4424,4380,4352,4339,
-4332,4322,4307,4288,4270,4252,4234,4213,4190,4166,4143,4119,4093,4064,4034,4005,3979,3953,3922,3885,3844,
-3803,3766,3734,3706,3679,3652,3625,3598,3572,3550,3536,3529,3528,3522,3505,3474,3437,3406,3391,3395,3413,
-3442,3477,3522,3576,3635,3687,3725,3744,3750,3750,3749,3749,3744,3731,3709,3679,3648,3620,3598,3581,3568,
-3551,3527,3493,3453,3415,3382,3353,3323,3286,3242,3199,3164,3138,3117,3093,3065,3035,3010,2991,2975,2954,
-2926,2894,2865,2841,2820,2794,2759,2720,2682,2653,2630,2609,2584,2556,2529,2505,2482,2454,2419,2379,2340,
-2309,2283,2260,2232,2201,2168,2137,2108,2079,2045,2009,1971,1936,1903,1871,1839,1806,1773,1741,1708,1674,
-1638,1601,1564,1529,1495,1460,1423,1385,1346,1307,1267,1227,1187,1149,1112,1074,1033,988,943,901,863,
-827,789,747,704,664,627,592,553,509,459,411,369,333,298,262,222,182,146,115,85,51,
-12,-32,-78,-122,-164,-204,-245,-286,-327,-365,-402,-440,-480,-523,-569,-614,-656,-696,-734,-773,-814,
--854,-893,-931,-969,-1007,-1048,-1090,-1130,-1166,-1198,-1229,-1260,-1294,-1329,-1365,-1401,-1434,-1466,-1498,-1530,-1562,
--1596,-1632,-1669,-1705,-1739,-1770,-1800,-1830,-1861,-1891,-1919,-1943,-1964,-1986,-2009,-2035,-2061,-2086,-2108,-2129,-2149,
--2169,-2190,-2212,-2235,-2261,-2289,-2316,-2338,-2353,-2363,-2372,-2385,-2404,-2426,-2446,-2459,-2466,-2467,-2467,-2470,-2476,
--2486,-2497,-2509,-2520,-2528,-2534,-2537,-2539,-2540,-2542,-2545,-2548,-2551,-2555,-2559,-2564,-2569,-2572,-2572,-2570,-2566,
--2562,-2560,-2558,-2553,-2546,-2538,-2532,-2529,-2529,-2526,-2520,-2509,-2498,-2490,-2485,-2483,-2477,-2468,-2459,-2452,-2449,
--2446,-2436,-2418,-2396,-2376,-2362,-2353,-2342,-2326,-2304,-2283,-2267,-2255,-2245,-2231,-2212,-2191,-2173,-2159,-2146,-2130,
--2110,-2087,-2065,-2044,-2026,-2007,-1986,-1965,-1946,-1929,-1912,-1893,-1872,-1850,-1829,-1812,-1797,-1781,-1764,-1743,-1723,
--1709,-1706,-1714,-1732,-1751,-1765,-1766,-1755,-1736,-1718,-1705,-1696,-1688,-1677,-1662,-1649,-1644,-1646,-1651,-1649,-1635,
--1611,-1589,-1579,-1586,-1602,-1613,-1606,-1579,-1537,-1493,-1453,-1416,-1377,-1335,-1291,-1255,-1233,-1227,-1234,-1249,-1268,
--1292,-1324,-1363,-1401,-1431,-1446,-1446,-1439,-1431,-1427,-1425,-1421,-1412,-1398,-1382,-1365,-1350,-1335,-1321,-1310,-1303,
--1300,-1301,-1302,-1299,-1294,-1286,-1279,-1271,-1262,-1249,-1232,-1213,-1195,-1180,-1168,-1154,-1137,-1118,-1104,-1099,-1102,
--1104,-1096,-1069,-1026,-975,-926,-884,-846,-804,-759,-716,-684,-669,-667,-668,-665,-662,-670,-701,-749,-795,
--810,-773,-684,-568,-454,-366,-306,-262,-214,-150,-72,6,69,108,123,119,107,87,59,19,-33,
--90,-141,-177,-196,-204,-209,-219,-232,-244,-249,-249,-247,-247,-248,-248,-245,-242,-241,-245,-252,-260,
--265,-266,-268,-275,-285,-297,-307,-313,-318,-324,-329,-332,-333,-333,-338,-352,-376,-407,-440,-473,-508,
--548,-597,-652,-709,-761,-800,-823,-831,-832,-832,-837,-850,-869,-889,-906,-919,-928,-937,-945,-953,-961,
--968,-974,-979,-981,-981,-982,-987,-997,-1014,-1032,-1049,-1060,-1069,-1080,-1095,-1114,-1132,-1146,-1154,-1158,-1163,
--1170,-1178,-1185,-1189,-1191,-1193,-1195,-1200,-1207,-1216,-1223,-1227,-1226,-1220,-1210,-1201,-1195,-1194,-1196,-1198,-1201,
--1205,-1210,-1215,-1219,-1220,-1219,-1219,-1223,-1230,-1236,-1237,-1233,-1226,-1221,-1219,-1219,-1218,-1213,-1206,-1199,-1196,
--1194,-1191,-1187,-1184,-1185,-1188,-1192,-1190,-1180,-1166,-1154,-1151,-1159,-1172,-1182,-1184,-1179,-1174,-1174,-1182,-1193,
--1199,-1200,-1197,-1197,-1207,-1226,-1249,-1270,-1286,-1296,-1305,-1315,-1325,-1334,-1341,-1349,-1360,-1374,-1388,-1397,-1399,
--1396,-1394,-1397,-1402,-1408,-1411,-1412,-1417,-1429,-1447,-1465,-1477,-1482,-1484,-1488,-1498,-1511,-1521,-1528,-1534,-1542,
--1556,-1573,-1589,-1601,-1610,-1619,-1631,-1644,-1655,-1662,-1664,-1664,-1664,-1664,-1664,-1663,-1663,-1665,-1669,-1673,-1672,
--1665,-1655,-1645,-1638,-1633,-1627,-1619,-1610,-1606,-1609,-1618,-1625,-1627,-1619,-1604,-1587,-1573,-1563,-1554,-1544,-1533,
--1522,-1511,-1501,-1491,-1480,-1470,-1462,-1457,-1454,-1449,-1442,-1429,-1414,-1400,-1388,-1379,-1371,-1362,-1350,-1337,-1323,
--1312,-1303,-1293,-1281,-1267,-1250,-1233,-1217,-1203,-1189,-1177,-1166,-1157,-1151,-1146,-1140,-1134,-1127,-1122,-1120,-1119,
--1119,-1117,-1112,-1106,-1099,-1093,-1087,-1078,-1068,-1059,-1052,-1046,-1042,-1036,-1028,-1017,-1007,-1000,-996,-993,-991,
--989,-986,-983,-979,-974,-969,-963,-957,-953,-949,-946,-942,-939,-938,-939,-942,-945,-947,-947,-946,-947,
--949,-953,-956,-959,-959,-958,-956,-955,-954,-954,-956,-960,-964,-966,-965,-959,-952,-944,-938,-934,-933,
--931,-929,-925,-921,-915,-910,-904,-899,-894,-888,-879,-868,-855,-842,-830,-820,-811,-799,-785,-767,-749,
--734,-726,-723,-724,-723,-716,-702,-682,-658,-635,-617,-606,-601,-601,-601,-598,-592,-584,-574,-564,-553,
--538,-520,-500,-483,-469,-460,-452,-441,-426,-407,-386,-364,-343,-321,-299,-276,-253,-230,-206,-182,-158,
--138,-121,-105,-87,-67,-44,-24,-10,0,6,15,27,42,57,71,84,100,118,139,161,184,
-208,232,257,280,304,328,355,385,415,440,458,471,482,496,516,542,572,603,633,659,680,
-700,721,746,773,798,818,835,855,881,904,911,894,866,854,889,981,1105,1221,1300,1346,1392,
-1481,1625,1794,1940,2022,2037,2014,1991,1989,2000,1998,1966,1903,1824,1748,1686,1640,1606,1578,1551,1522,
-1488,1447,1403,1362,1329,1303,1280,1256,1232,1211,1196,1184,1173,1160,1148,1143,1146,1154,1160,1155,1144,
-1133,1131,1139,1150,1155,1151,1141,1136,1140,1152,1160,1157,1137,1103,1060,1008,946,875,800,731,678,
-643,618,592,555,508,460,416,378,337,287,226,159,100,56,29,11,-5,-27,-52,-77,-98,
--115,-131,-148,-166,-185,-204,-223,-242,-260,-277,-293,-308,-324,-342,-360,-374,-383,-388,-390,-391,-393,
--395,-396,-395,-393,-393,-393,-393,-390,-385,-378,-368,-354,-336,-314,-291,-272,-260,-255,-256,-261,-268,
--278,-292,-308,-322,-331,-336,-338,-339,-338,-331,-317,-297,-276,-259,-250,-247,-247,-244,-240,-233,-226,
--218,-208,-196,-182,-167,-150,-131,-107,-80,-50,-21,7,38,73,113,155,195,230,262,293,327,
-365,403,440,475,509,544,580,618,656,696,739,784,829,871,908,942,976,1013,1052,1091,1128,
-1163,1198,1237,1280,1324,1365,1399,1427,1453,1480,1509,1538,1568,1598,1629,1664,1702,1742,1782,1820,1856,
-1891,1926,1960,1994,2027,2058,2089,2119,2149,2179,2207,2230,2251,2271,2293,2319,2347,2376,2404,2431,2459,
-2489,2520,2549,2571,2586,2599,2617,2642,2672,2702,2725,2740,2748,2754,2759,2762,2759,2750,2738,2726,2718,
-2715,2714,2714,2715,2718,2722,2725,2724,2718,2709,2701,2695,2689,2680,2662,2634,2599,2563,2533,2513,2501,
-2493,2484,2471,2455,2440,2428,2423,2421,2420,2414,2403,2389,2375,2363,2352,2341,2329,2317,2306,2298,2291,
-2286,2281,2279,2279,2277,2284,2277,2264,2248,2233,2224,2221,2219,2215,2208,2204,2205,2212,2219,2221,2219,
-2217,2222,2236,2254,2271,2286,2303,2328,2361,2396,2426,2451,2477,2511,2550,2577,2578,2548,2507,2483,2497,
-2548,2611,2657,2671,2659,2642,2637,2643,2650,2646,2632,2618,2616,2633,2660,2687,2705,2715,2723,2737,2758,
-2784,2813,2839,2860,2875,2888,2902,2923,2952,2987,3020,3045,3059,3068,3078,3093,3112,3131,3146,3157,3168,
-3181,3194,3207,3215,3220,3226,3232,3239,3244,3247,3248,3249,3252,3252,3250,3245,3244,3251,3267,3286,3299,
-3305,3305,3307,3315,3329,3342,3350,3355,3361,3374,3391,3410,3432,3458,3494,3540,3593,3644,3691,3738,3796,
-3868,3949,4020,4067,4084,4083,4087,4114,4167,4235,4299,4345,4373,4392,4415,4448,4485,4513,4523,4516,4499,
-4485,4476,4465,4446,4417,4393,4391,4419,4462,4490,4476,4420,4347,4297,4292,4328,4375,4404,4404,4389,4380,
-4388,4403,4406,4383,4340,4293,4259,4247,4256,4279,4311,4349,4387,4417,4435,4445,4455,4476,4508,4544,4573,
-4589,4594,4595,4597,4596,4584,4557,4516,4471,4432,4407,4399,4406,4425,4452,4481,4509,4534,4557,4579,4596,
-4603,4595,4571,4538,4508,4485,4469,4453,4431,4405,4380,4363,4354,4346,4335,4317,4295,4273,4254,4236,4217,
-4196,4172,4149,4125,4101,4075,4048,4022,3997,3970,3939,3901,3860,3821,3786,3757,3730,3703,3672,3641,3612,
-3590,3578,3576,3579,3579,3568,3541,3503,3465,3438,3430,3441,3465,3498,3540,3593,3655,3718,3772,3807,3821,
-3822,3818,3818,3821,3823,3821,3811,3794,3771,3747,3726,3709,3692,3672,3643,3604,3559,3513,3472,3433,3391,
-3342,3290,3243,3206,3179,3155,3125,3089,3051,3020,2999,2983,2964,2940,2912,2887,2866,2845,2817,2781,2740,
-2704,2678,2660,2642,2619,2592,2565,2540,2515,2485,2449,2408,2371,2342,2320,2297,2268,2234,2198,2166,2139,
-2112,2081,2045,2006,1968,1933,1899,1865,1830,1795,1762,1730,1697,1662,1625,1589,1555,1521,1486,1449,1410,
-1371,1333,1295,1257,1218,1178,1138,1098,1058,1016,975,934,895,857,817,776,736,699,664,629,589,
-544,494,445,402,364,329,294,257,219,185,153,122,88,50,8,-33,-75,-116,-157,-199,-241,
--282,-322,-361,-401,-444,-488,-532,-573,-610,-646,-682,-722,-764,-805,-843,-879,-914,-952,-994,-1038,-1080,
--1117,-1150,-1180,-1212,-1247,-1286,-1324,-1360,-1392,-1423,-1455,-1488,-1524,-1561,-1597,-1632,-1664,-1695,-1725,-1754,-1784,
--1815,-1846,-1875,-1901,-1925,-1948,-1971,-1996,-2023,-2049,-2074,-2097,-2118,-2138,-2157,-2177,-2201,-2227,-2255,-2281,-2301,
--2314,-2323,-2333,-2348,-2369,-2392,-2412,-2426,-2433,-2435,-2436,-2440,-2448,-2459,-2472,-2484,-2494,-2503,-2509,-2514,-2517,
--2520,-2522,-2525,-2529,-2534,-2539,-2545,-2550,-2554,-2556,-2555,-2552,-2548,-2544,-2541,-2539,-2535,-2529,-2522,-2515,-2512,
--2511,-2510,-2505,-2496,-2486,-2476,-2471,-2468,-2465,-2459,-2451,-2443,-2436,-2429,-2417,-2401,-2383,-2365,-2352,-2342,-2331,
--2315,-2295,-2274,-2257,-2243,-2230,-2216,-2198,-2179,-2162,-2147,-2133,-2117,-2098,-2078,-2057,-2037,-2017,-1997,-1977,-1958,
--1941,-1925,-1909,-1891,-1870,-1848,-1827,-1809,-1794,-1778,-1761,-1742,-1724,-1710,-1704,-1710,-1725,-1746,-1762,-1766,-1757,
--1739,-1720,-1707,-1702,-1699,-1692,-1680,-1665,-1655,-1652,-1652,-1648,-1634,-1612,-1592,-1582,-1586,-1597,-1603,-1595,-1571,
--1538,-1502,-1468,-1435,-1398,-1355,-1312,-1274,-1248,-1235,-1233,-1239,-1253,-1278,-1315,-1360,-1404,-1436,-1451,-1449,-1440,
--1434,-1436,-1443,-1450,-1450,-1442,-1426,-1408,-1390,-1376,-1366,-1360,-1359,-1360,-1361,-1359,-1353,-1344,-1335,-1327,-1317,
--1302,-1282,-1258,-1237,-1225,-1220,-1217,-1209,-1193,-1174,-1161,-1158,-1161,-1156,-1133,-1090,-1036,-988,-955,-930,-903,
--863,-812,-764,-733,-723,-723,-720,-711,-705,-723,-771,-839,-896,-912,-872,-787,-686,-593,-517,-452,-381,
--298,-208,-125,-65,-34,-28,-37,-51,-68,-87,-112,-147,-187,-229,-264,-287,-299,-305,-308,-314,-320,
--324,-323,-320,-316,-315,-317,-317,-316,-313,-312,-315,-321,-326,-327,-325,-323,-323,-327,-331,-335,-339,
--344,-350,-355,-354,-345,-334,-328,-335,-357,-389,-424,-459,-495,-540,-601,-677,-758,-832,-886,-917,-926,
--925,-923,-928,-943,-964,-987,-1006,-1019,-1030,-1038,-1045,-1052,-1059,-1064,-1068,-1071,-1072,-1072,-1072,-1075,-1083,
--1096,-1111,-1124,-1133,-1139,-1145,-1154,-1167,-1184,-1200,-1211,-1218,-1222,-1225,-1230,-1235,-1242,-1247,-1251,-1254,-1257,
--1260,-1266,-1271,-1276,-1277,-1275,-1270,-1262,-1254,-1248,-1242,-1238,-1235,-1236,-1240,-1245,-1250,-1255,-1259,-1264,-1270,
--1277,-1281,-1281,-1279,-1277,-1277,-1279,-1281,-1280,-1273,-1263,-1253,-1247,-1244,-1243,-1243,-1242,-1241,-1239,-1237,-1233,
--1225,-1215,-1207,-1203,-1207,-1216,-1226,-1233,-1235,-1234,-1234,-1237,-1242,-1246,-1247,-1246,-1245,-1250,-1260,-1276,-1291,
--1303,-1311,-1318,-1327,-1337,-1348,-1360,-1374,-1390,-1408,-1424,-1431,-1428,-1419,-1411,-1410,-1417,-1427,-1435,-1439,-1444,
--1454,-1469,-1486,-1500,-1507,-1511,-1516,-1525,-1536,-1544,-1549,-1551,-1556,-1566,-1580,-1595,-1607,-1617,-1625,-1634,-1645,
--1656,-1664,-1668,-1671,-1674,-1677,-1681,-1685,-1689,-1694,-1696,-1695,-1688,-1677,-1667,-1659,-1655,-1651,-1643,-1632,-1621,
--1616,-1619,-1626,-1632,-1630,-1620,-1604,-1589,-1577,-1567,-1558,-1547,-1535,-1525,-1518,-1513,-1507,-1499,-1490,-1480,-1473,
--1467,-1460,-1449,-1434,-1417,-1401,-1388,-1380,-1375,-1369,-1360,-1348,-1333,-1319,-1306,-1294,-1283,-1272,-1260,-1247,-1233,
--1218,-1202,-1187,-1174,-1162,-1152,-1144,-1134,-1124,-1114,-1105,-1099,-1096,-1095,-1094,-1092,-1088,-1084,-1080,-1075,-1069,
--1062,-1055,-1049,-1044,-1041,-1037,-1030,-1022,-1014,-1007,-1001,-998,-995,-992,-988,-985,-981,-976,-971,-965,-959,
--953,-949,-945,-942,-939,-937,-938,-940,-942,-944,-945,-944,-944,-946,-950,-955,-960,-963,-964,-965,-965,
--966,-966,-967,-967,-968,-968,-967,-964,-959,-952,-944,-939,-937,-937,-939,-939,-935,-929,-922,-915,-908,
--903,-898,-891,-880,-867,-853,-841,-830,-820,-809,-796,-780,-764,-750,-741,-739,-739,-739,-732,-718,-696,
--671,-647,-631,-622,-621,-623,-624,-621,-614,-605,-596,-586,-574,-560,-543,-525,-510,-497,-485,-473,-457,
--438,-418,-398,-378,-358,-335,-311,-286,-261,-236,-210,-184,-159,-137,-119,-103,-87,-70,-52,-37,-25,
--17,-10,-1,11,25,40,56,72,89,108,128,149,170,194,218,242,265,288,313,342,371,
-398,419,434,446,459,477,500,525,551,577,601,624,646,668,693,720,749,772,790,805,822,
-842,855,850,823,789,784,839,959,1112,1250,1337,1377,1411,1490,1630,1804,1957,2041,2049,2010,1967,
-1944,1937,1920,1876,1805,1729,1668,1634,1621,1618,1611,1593,1563,1521,1467,1409,1352,1305,1269,1242,1223,
-1208,1198,1192,1187,1178,1165,1151,1144,1146,1154,1160,1157,1146,1133,1128,1132,1140,1142,1136,1128,1127,
-1138,1156,1168,1164,1142,1105,1063,1017,965,903,835,769,715,678,650,622,583,535,485,441,405,
-370,328,276,217,160,113,76,46,18,-10,-38,-63,-84,-102,-119,-137,-154,-170,-184,-200,-216,
--235,-253,-271,-288,-305,-321,-336,-346,-352,-356,-360,-365,-371,-376,-380,-381,-382,-384,-386,-386,-383,
--377,-369,-359,-346,-327,-302,-274,-248,-228,-217,-213,-215,-222,-233,-247,-262,-275,-284,-288,-289,-289,
--287,-279,-265,-244,-223,-207,-200,-200,-203,-204,-201,-194,-183,-170,-157,-142,-127,-111,-93,-72,-46,
--18,10,37,63,91,122,157,193,227,255,282,312,346,386,427,466,501,532,563,594,627,
-663,704,749,798,848,894,934,969,1001,1035,1070,1105,1139,1173,1208,1248,1291,1337,1379,1416,1448,
-1476,1504,1532,1560,1588,1614,1642,1672,1706,1744,1783,1821,1856,1889,1921,1952,1983,2012,2040,2066,2093,
-2122,2153,2183,2210,2233,2254,2278,2307,2340,2372,2400,2424,2448,2475,2507,2540,2567,2587,2602,2619,2640,
-2666,2690,2707,2717,2724,2731,2740,2747,2747,2737,2723,2712,2709,2717,2733,2751,2767,2780,2787,2788,2784,
-2773,2760,2743,2725,2702,2674,2640,2605,2574,2550,2536,2528,2523,2518,2509,2497,2482,2468,2457,2448,2441,
-2432,2420,2406,2392,2380,2369,2358,2344,2329,2315,2304,2297,2293,2290,2287,2286,2285,2284,2293,2288,2279,
-2269,2260,2256,2254,2250,2241,2229,2221,2221,2228,2234,2234,2228,2221,2222,2234,2253,2273,2290,2308,2332,
-2360,2387,2405,2416,2430,2455,2491,2523,2532,2515,2485,2472,2499,2563,2642,2702,2725,2716,2694,2679,2675,
-2673,2664,2645,2628,2625,2640,2670,2701,2726,2743,2757,2772,2793,2816,2840,2860,2876,2889,2901,2915,2934,
-2960,2989,3015,3034,3045,3056,3071,3094,3121,3145,3162,3172,3181,3192,3205,3217,3225,3229,3231,3232,3234,
-3235,3237,3240,3247,3256,3263,3266,3263,3259,3261,3271,3285,3300,3310,3317,3324,3334,3345,3355,3362,3367,
-3375,3388,3406,3429,3458,3496,3545,3601,3654,3699,3737,3781,3842,3920,3999,4058,4082,4076,4065,4079,4129,
-4208,4290,4347,4371,4372,4373,4391,4427,4469,4497,4502,4486,4463,4446,4439,4434,4423,4402,4378,4363,4362,
-4368,4367,4349,4316,4284,4272,4286,4317,4347,4362,4362,4361,4370,4388,4407,4411,4394,4362,4326,4298,4284,
-4285,4302,4332,4367,4398,4415,4418,4415,4419,4440,4475,4511,4538,4552,4559,4566,4575,4580,4572,4549,4515,
-4479,4450,4430,4418,4414,4419,4434,4454,4473,4485,4488,4485,4481,4474,4464,4449,4429,4412,4403,4400,4401,
-4398,4391,4381,4373,4367,4358,4345,4324,4300,4278,4259,4243,4226,4206,4182,4157,4132,4107,4083,4059,4035,
-4011,3985,3952,3915,3875,3838,3806,3780,3754,3727,3696,3664,3635,3616,3608,3610,3616,3616,3603,3576,3539,
-3502,3475,3465,3472,3494,3532,3584,3650,3722,3791,3843,3872,3882,3881,3877,3877,3882,3889,3894,3894,3886,
-3870,3847,3822,3798,3777,3755,3727,3690,3645,3597,3547,3497,3442,3382,3322,3271,3234,3210,3189,3161,3125,
-3087,3053,3029,3010,2989,2963,2934,2909,2888,2866,2839,2803,2765,2731,2707,2690,2672,2650,2623,2596,2570,
-2544,2514,2477,2437,2403,2377,2357,2335,2306,2269,2231,2196,2167,2139,2107,2070,2031,1994,1960,1927,1892,
-1856,1819,1784,1751,1718,1682,1646,1610,1575,1543,1510,1474,1436,1398,1361,1325,1288,1248,1205,1162,1120,
-1080,1041,1003,965,925,884,843,802,763,727,692,656,617,573,527,481,438,399,363,328,293,
-259,225,192,159,123,86,47,9,-29,-68,-110,-152,-195,-236,-276,-318,-362,-409,-454,-496,-532,
--564,-596,-633,-675,-720,-763,-801,-834,-867,-903,-944,-989,-1031,-1068,-1100,-1131,-1165,-1204,-1246,-1287,-1323,
--1354,-1384,-1415,-1450,-1487,-1525,-1560,-1592,-1621,-1651,-1681,-1711,-1741,-1771,-1799,-1827,-1854,-1880,-1906,-1931,-1956,
--1982,-2007,-2034,-2060,-2084,-2106,-2126,-2147,-2170,-2195,-2220,-2243,-2261,-2274,-2285,-2297,-2313,-2333,-2355,-2374,-2387,
--2394,-2399,-2404,-2411,-2421,-2433,-2445,-2455,-2464,-2472,-2479,-2485,-2491,-2496,-2499,-2503,-2508,-2514,-2521,-2529,-2534,
--2537,-2537,-2535,-2530,-2524,-2520,-2517,-2516,-2515,-2512,-2507,-2501,-2497,-2496,-2495,-2493,-2486,-2476,-2465,-2456,-2452,
--2449,-2447,-2442,-2435,-2425,-2413,-2398,-2382,-2366,-2351,-2339,-2327,-2315,-2300,-2282,-2264,-2247,-2232,-2217,-2202,-2186,
--2169,-2153,-2136,-2120,-2102,-2085,-2067,-2049,-2030,-2011,-1990,-1970,-1951,-1935,-1919,-1904,-1887,-1868,-1849,-1831,-1813,
--1795,-1777,-1757,-1738,-1720,-1706,-1700,-1705,-1721,-1744,-1765,-1774,-1768,-1750,-1730,-1716,-1710,-1708,-1702,-1691,-1676,
--1665,-1660,-1660,-1655,-1640,-1618,-1597,-1586,-1589,-1599,-1605,-1599,-1578,-1549,-1517,-1487,-1456,-1421,-1382,-1342,-1306,
--1281,-1265,-1257,-1255,-1262,-1281,-1314,-1357,-1401,-1436,-1455,-1458,-1453,-1449,-1452,-1461,-1470,-1473,-1466,-1451,-1433,
--1417,-1407,-1404,-1406,-1412,-1417,-1417,-1413,-1403,-1392,-1383,-1374,-1363,-1345,-1321,-1295,-1275,-1267,-1270,-1273,-1270,
--1256,-1238,-1224,-1216,-1208,-1187,-1146,-1092,-1040,-1005,-989,-979,-958,-915,-860,-813,-787,-781,-780,-770,-753,
--748,-776,-842,-923,-983,-991,-943,-857,-764,-682,-609,-532,-441,-339,-246,-179,-148,-148,-166,-191,-215,
--237,-259,-281,-301,-320,-339,-359,-378,-393,-403,-407,-407,-405,-403,-400,-396,-394,-392,-392,-391,-389,
--386,-385,-386,-388,-390,-390,-389,-389,-389,-390,-388,-384,-380,-380,-385,-388,-385,-371,-350,-333,-329,
--342,-370,-403,-436,-474,-524,-596,-688,-788,-880,-947,-985,-999,-1002,-1006,-1017,-1037,-1059,-1079,-1095,-1107,
--1116,-1125,-1134,-1141,-1145,-1147,-1148,-1151,-1155,-1160,-1165,-1170,-1175,-1182,-1191,-1201,-1209,-1214,-1218,-1223,-1231,
--1242,-1256,-1268,-1276,-1279,-1281,-1284,-1288,-1294,-1299,-1303,-1306,-1308,-1310,-1314,-1319,-1324,-1327,-1329,-1328,-1323,
--1316,-1307,-1298,-1290,-1284,-1281,-1280,-1281,-1284,-1289,-1297,-1306,-1316,-1323,-1328,-1329,-1329,-1330,-1333,-1336,-1338,
--1336,-1329,-1320,-1312,-1306,-1303,-1304,-1305,-1305,-1301,-1294,-1285,-1276,-1268,-1262,-1256,-1252,-1251,-1255,-1262,-1271,
--1277,-1280,-1280,-1280,-1282,-1286,-1290,-1293,-1295,-1299,-1305,-1315,-1325,-1331,-1333,-1333,-1334,-1339,-1348,-1361,-1378,
--1397,-1417,-1432,-1439,-1435,-1426,-1418,-1420,-1432,-1449,-1465,-1475,-1482,-1488,-1498,-1510,-1521,-1528,-1531,-1535,-1542,
--1551,-1561,-1567,-1571,-1575,-1583,-1595,-1608,-1620,-1629,-1636,-1642,-1649,-1656,-1663,-1669,-1676,-1682,-1689,-1695,-1701,
--1707,-1712,-1715,-1713,-1705,-1695,-1687,-1683,-1681,-1678,-1668,-1654,-1639,-1630,-1630,-1634,-1637,-1633,-1622,-1609,-1596,
--1586,-1575,-1562,-1546,-1531,-1521,-1516,-1515,-1513,-1509,-1503,-1495,-1488,-1481,-1472,-1459,-1443,-1424,-1407,-1394,-1385,
--1378,-1370,-1360,-1346,-1330,-1312,-1297,-1284,-1274,-1266,-1259,-1250,-1239,-1226,-1213,-1200,-1189,-1178,-1168,-1157,-1144,
--1130,-1116,-1102,-1090,-1083,-1079,-1076,-1073,-1070,-1066,-1062,-1058,-1054,-1049,-1044,-1039,-1034,-1031,-1028,-1025,-1021,
--1016,-1009,-1003,-999,-995,-992,-989,-985,-981,-976,-970,-965,-959,-953,-948,-944,-940,-937,-935,-936,-939,
--942,-946,-947,-947,-945,-945,-947,-952,-957,-963,-968,-972,-976,-980,-981,-980,-977,-974,-972,-971,-970,
--967,-960,-952,-944,-940,-940,-943,-945,-943,-938,-930,-922,-916,-912,-908,-903,-894,-883,-870,-857,-845,
--835,-824,-812,-798,-784,-770,-760,-756,-754,-752,-746,-732,-711,-687,-666,-651,-643,-642,-644,-645,-643,
--638,-631,-622,-611,-597,-581,-564,-547,-533,-518,-503,-485,-465,-445,-426,-408,-390,-369,-346,-320,-294,
--267,-240,-212,-185,-160,-139,-122,-108,-94,-81,-68,-57,-48,-39,-31,-21,-8,5,21,39,59,
-78,97,114,132,152,175,200,224,246,268,292,319,347,372,391,404,418,435,458,482,505,
-526,546,568,593,619,645,672,700,726,749,766,779,791,802,806,794,766,741,753,828,971,
-1144,1297,1390,1423,1440,1490,1600,1749,1890,1979,2003,1984,1957,1937,1919,1881,1816,1732,1657,1611,1600,
-1609,1619,1617,1598,1566,1523,1470,1408,1342,1280,1230,1197,1179,1175,1177,1182,1183,1177,1165,1152,1145,
-1147,1156,1162,1160,1149,1136,1129,1130,1134,1133,1126,1117,1116,1127,1144,1154,1148,1123,1088,1051,1015,
-977,928,870,808,754,712,680,647,606,555,502,456,420,389,357,317,270,221,175,133,95,
-59,25,-4,-28,-49,-68,-88,-108,-126,-142,-155,-170,-187,-207,-229,-249,-266,-281,-293,-302,-307,
--310,-313,-319,-327,-336,-345,-351,-356,-360,-364,-367,-367,-364,-357,-349,-340,-327,-309,-284,-254,-224,
--200,-184,-175,-173,-176,-184,-196,-209,-221,-229,-231,-230,-226,-220,-210,-194,-176,-158,-145,-141,-143,
--147,-149,-146,-137,-126,-112,-96,-80,-64,-47,-28,-6,18,45,72,99,125,151,179,207,234,
-260,284,309,339,374,414,454,491,526,558,589,621,654,690,729,774,823,872,919,960,995,
-1028,1060,1094,1128,1161,1193,1226,1262,1303,1347,1392,1433,1468,1499,1526,1551,1575,1599,1622,1648,1676,
-1708,1744,1781,1818,1851,1881,1911,1940,1970,2000,2027,2051,2076,2103,2134,2167,2197,2223,2246,2271,2300,
-2334,2369,2398,2422,2443,2466,2494,2524,2551,2573,2590,2607,2625,2644,2659,2669,2674,2680,2691,2707,2722,
-2730,2729,2722,2719,2724,2740,2764,2789,2811,2825,2829,2823,2809,2788,2766,2742,2717,2688,2656,2623,2594,
-2574,2563,2559,2557,2552,2542,2530,2516,2501,2488,2475,2462,2448,2432,2415,2399,2384,2373,2363,2353,2342,
-2329,2318,2311,2308,2306,2304,2301,2298,2296,2293,2313,2308,2299,2289,2280,2273,2269,2261,2250,2237,2228,
-2228,2234,2240,2242,2237,2235,2240,2256,2276,2293,2307,2320,2338,2361,2381,2391,2394,2402,2427,2469,2514,
-2538,2531,2503,2482,2496,2548,2620,2681,2709,2704,2683,2665,2658,2656,2650,2637,2624,2623,2639,2668,2703,
-2733,2757,2775,2791,2809,2828,2847,2867,2885,2903,2919,2934,2950,2968,2987,3004,3017,3029,3044,3066,3097,
-3130,3159,3179,3192,3200,3209,3220,3229,3236,3238,3238,3237,3235,3234,3234,3238,3248,3263,3278,3288,3290,
-3288,3287,3289,3296,3305,3316,3327,3341,3355,3368,3376,3381,3387,3397,3412,3433,3459,3492,3535,3589,3647,
-3700,3743,3782,3828,3891,3965,4029,4063,4059,4035,4024,4056,4135,4238,4328,4376,4381,4363,4352,4366,4402,
-4442,4467,4467,4449,4424,4406,4396,4391,4385,4375,4362,4350,4338,4325,4307,4287,4271,4267,4278,4301,4325,
-4343,4352,4359,4369,4384,4398,4405,4399,4386,4369,4353,4339,4326,4319,4322,4338,4363,4387,4399,4397,4391,
-4394,4415,4450,4484,4509,4523,4532,4543,4555,4561,4553,4531,4503,4479,4463,4453,4445,4439,4438,4447,4463,
-4479,4488,4485,4475,4464,4457,4451,4442,4429,4414,4401,4395,4394,4394,4392,4387,4382,4374,4364,4348,4328,
-4305,4284,4267,4251,4235,4215,4190,4163,4136,4110,4087,4065,4043,4021,3994,3963,3927,3890,3855,3826,3801,
-3778,3753,3726,3697,3672,3654,3645,3641,3640,3635,3622,3599,3570,3539,3512,3495,3493,3511,3551,3614,3692,
-3772,3841,3889,3913,3922,3923,3925,3930,3937,3945,3951,3953,3949,3934,3910,3879,3849,3824,3802,3778,3746,
-3702,3650,3592,3532,3469,3404,3342,3290,3254,3230,3212,3189,3158,3124,3094,3070,3049,3025,2995,2963,2933,
-2908,2885,2859,2827,2792,2761,2737,2719,2700,2677,2650,2623,2598,2572,2542,2506,2468,2435,2409,2388,2367,
-2338,2303,2265,2230,2197,2164,2127,2088,2048,2013,1981,1950,1916,1880,1842,1807,1775,1742,1707,1670,1632,
-1597,1564,1533,1499,1463,1426,1389,1354,1317,1278,1235,1190,1147,1106,1068,1031,992,951,910,869,829,
-791,754,717,679,639,598,555,513,472,432,395,361,328,296,264,231,195,157,119,81,45,
-8,-31,-72,-115,-157,-198,-240,-283,-330,-377,-421,-460,-492,-521,-553,-592,-637,-684,-728,-767,-800,
--833,-869,-909,-951,-991,-1026,-1058,-1090,-1126,-1167,-1210,-1252,-1287,-1318,-1347,-1378,-1413,-1450,-1486,-1519,-1548,
--1576,-1605,-1637,-1670,-1701,-1731,-1757,-1783,-1809,-1837,-1866,-1894,-1919,-1943,-1967,-1992,-2017,-2043,-2067,-2089,-2111,
--2133,-2156,-2179,-2200,-2217,-2231,-2244,-2259,-2276,-2294,-2313,-2329,-2341,-2351,-2361,-2371,-2383,-2396,-2409,-2419,-2428,
--2435,-2441,-2449,-2458,-2465,-2471,-2474,-2477,-2480,-2486,-2494,-2503,-2510,-2514,-2514,-2511,-2507,-2503,-2499,-2497,-2497,
--2498,-2498,-2495,-2490,-2484,-2480,-2478,-2476,-2472,-2464,-2454,-2443,-2435,-2431,-2430,-2428,-2422,-2412,-2397,-2381,-2365,
--2350,-2337,-2324,-2310,-2296,-2281,-2266,-2251,-2237,-2222,-2207,-2192,-2177,-2162,-2146,-2129,-2111,-2092,-2074,-2059,-2043,
--2027,-2008,-1988,-1968,-1949,-1932,-1915,-1898,-1880,-1863,-1847,-1832,-1816,-1798,-1780,-1760,-1741,-1724,-1709,-1702,-1705,
--1721,-1745,-1770,-1784,-1782,-1766,-1746,-1729,-1721,-1716,-1709,-1697,-1683,-1673,-1670,-1671,-1666,-1651,-1627,-1603,-1592,
--1595,-1607,-1618,-1616,-1600,-1573,-1544,-1515,-1486,-1455,-1421,-1386,-1355,-1330,-1313,-1302,-1295,-1294,-1304,-1327,-1361,
--1400,-1435,-1460,-1473,-1477,-1478,-1479,-1483,-1486,-1484,-1477,-1465,-1451,-1441,-1437,-1440,-1448,-1458,-1465,-1467,-1461,
--1451,-1439,-1429,-1420,-1410,-1393,-1370,-1345,-1327,-1319,-1321,-1323,-1319,-1306,-1289,-1272,-1257,-1238,-1205,-1157,-1103,
--1059,-1033,-1023,-1013,-985,-939,-887,-849,-833,-830,-824,-808,-792,-801,-852,-938,-1024,-1068,-1047,-970,-869,
--773,-696,-626,-546,-452,-356,-281,-243,-241,-260,-285,-310,-333,-358,-383,-403,-414,-420,-427,-442,-463,
--484,-496,-496,-488,-479,-474,-473,-473,-471,-468,-463,-460,-458,-457,-456,-455,-454,-454,-457,-462,-469,
--475,-476,-470,-458,-445,-437,-437,-439,-436,-421,-396,-371,-357,-362,-381,-408,-439,-477,-532,-613,-716,
--829,-931,-1006,-1049,-1067,-1076,-1087,-1106,-1129,-1150,-1166,-1175,-1182,-1190,-1201,-1213,-1222,-1226,-1227,-1227,-1230,
--1238,-1249,-1260,-1266,-1269,-1269,-1271,-1276,-1283,-1290,-1295,-1298,-1302,-1309,-1319,-1329,-1336,-1340,-1341,-1342,-1344,
--1347,-1350,-1353,-1354,-1356,-1359,-1363,-1367,-1371,-1373,-1375,-1375,-1374,-1370,-1364,-1357,-1349,-1343,-1338,-1333,-1328,
--1325,-1326,-1332,-1342,-1355,-1366,-1374,-1380,-1383,-1386,-1387,-1387,-1386,-1384,-1382,-1380,-1378,-1376,-1373,-1371,-1369,
--1365,-1358,-1348,-1336,-1326,-1319,-1315,-1311,-1306,-1300,-1296,-1297,-1303,-1310,-1314,-1315,-1313,-1313,-1316,-1321,-1326,
--1331,-1337,-1345,-1356,-1366,-1371,-1369,-1363,-1356,-1353,-1354,-1359,-1367,-1377,-1389,-1400,-1409,-1414,-1415,-1419,-1430,
--1449,-1472,-1492,-1505,-1512,-1516,-1523,-1531,-1539,-1544,-1546,-1548,-1553,-1561,-1572,-1581,-1588,-1594,-1601,-1610,-1621,
--1632,-1643,-1650,-1655,-1658,-1660,-1664,-1670,-1679,-1688,-1696,-1703,-1709,-1715,-1721,-1725,-1724,-1719,-1712,-1707,-1705,
--1705,-1703,-1694,-1679,-1664,-1654,-1650,-1651,-1650,-1644,-1633,-1620,-1609,-1599,-1588,-1573,-1555,-1538,-1525,-1518,-1515,
--1512,-1508,-1503,-1498,-1493,-1488,-1479,-1467,-1450,-1433,-1417,-1402,-1390,-1378,-1365,-1351,-1335,-1318,-1300,-1284,-1271,
--1262,-1256,-1249,-1241,-1231,-1221,-1210,-1201,-1194,-1187,-1179,-1169,-1157,-1143,-1127,-1111,-1097,-1087,-1079,-1074,-1070,
--1064,-1057,-1051,-1046,-1042,-1038,-1033,-1026,-1019,-1014,-1010,-1009,-1007,-1004,-999,-994,-990,-988,-986,-985,-983,
--979,-974,-970,-965,-960,-955,-949,-943,-938,-935,-934,-936,-940,-945,-950,-953,-953,-951,-950,-950,-953,
--958,-964,-970,-976,-982,-987,-990,-990,-986,-982,-978,-976,-975,-973,-968,-961,-953,-948,-947,-949,-950,
--948,-942,-935,-929,-925,-922,-919,-915,-908,-899,-889,-878,-867,-856,-844,-832,-819,-805,-791,-779,-771,
--766,-761,-755,-743,-726,-706,-688,-675,-668,-665,-665,-665,-664,-660,-655,-646,-632,-615,-596,-578,-561,
--547,-531,-513,-493,-471,-451,-434,-417,-400,-379,-354,-327,-299,-272,-244,-217,-191,-168,-149,-134,-121,
--110,-100,-91,-83,-75,-65,-54,-41,-27,-12,5,26,48,69,87,102,118,137,162,187,211,
-230,247,268,293,320,345,364,379,394,414,438,462,482,499,518,542,572,602,630,654,678,
-701,724,742,753,759,760,755,742,726,723,762,861,1019,1199,1352,1439,1460,1453,1468,1534,1641,
-1754,1835,1874,1883,1883,1884,1873,1833,1763,1680,1613,1580,1580,1593,1597,1583,1554,1520,1484,1442,1388,
-1322,1251,1191,1151,1136,1139,1152,1164,1170,1167,1157,1146,1141,1145,1153,1160,1158,1149,1136,1128,1127,
-1129,1128,1120,1110,1107,1114,1127,1134,1127,1104,1072,1040,1013,985,949,902,848,795,750,711,672,
-627,575,523,477,442,414,387,355,317,276,234,194,154,116,81,52,28,8,-10,-32,-56,
--79,-100,-118,-136,-156,-177,-198,-216,-231,-242,-250,-257,-261,-264,-269,-276,-285,-296,-307,-315,-322,
--327,-331,-333,-333,-330,-325,-319,-310,-297,-278,-252,-224,-196,-173,-158,-148,-142,-140,-143,-149,-158,
--167,-172,-172,-167,-159,-148,-135,-120,-106,-95,-88,-85,-85,-85,-83,-77,-68,-56,-44,-30,-14,
-2,21,40,60,81,105,129,155,182,208,233,257,279,301,324,351,383,420,458,496,531,
-566,601,635,669,703,736,773,813,856,901,943,980,1012,1044,1076,1110,1145,1179,1212,1244,1277,
-1315,1356,1401,1444,1483,1514,1539,1559,1578,1599,1623,1650,1681,1714,1748,1783,1816,1848,1876,1905,1934,
-1966,1998,2028,2054,2077,2103,2131,2162,2192,2218,2239,2260,2284,2314,2347,2378,2406,2429,2452,2475,2498,
-2519,2538,2556,2573,2591,2607,2620,2628,2635,2645,2663,2686,2709,2726,2736,2742,2748,2758,2773,2791,2809,
-2824,2833,2832,2821,2801,2775,2749,2725,2702,2680,2658,2637,2620,2609,2602,2595,2586,2571,2553,2534,2517,
-2501,2486,2472,2457,2443,2430,2417,2404,2392,2382,2373,2364,2355,2345,2338,2334,2332,2331,2328,2323,2319,
-2316,2313,2331,2325,2314,2301,2288,2279,2272,2266,2259,2251,2245,2243,2247,2251,2254,2257,2263,2275,2293,
-2310,2323,2332,2343,2361,2383,2401,2408,2410,2420,2453,2507,2564,2596,2587,2547,2504,2491,2518,2571,2620,
-2643,2637,2616,2601,2601,2611,2621,2624,2622,2627,2644,2674,2711,2747,2775,2794,2807,2817,2828,2842,2862,
-2886,2912,2934,2951,2962,2971,2981,2991,3004,3018,3038,3064,3098,3134,3167,3192,3208,3217,3224,3230,3236,
-3240,3244,3245,3245,3244,3242,3241,3245,3255,3270,3287,3302,3313,3319,3320,3319,3317,3317,3321,3334,3352,
-3372,3387,3395,3400,3408,3424,3447,3473,3500,3528,3562,3608,3663,3719,3773,3824,3879,3940,3996,4030,4031,
-4003,3973,3977,4035,4138,4252,4335,4367,4354,4326,4313,4329,4364,4400,4419,4419,4404,4386,4370,4357,4347,
-4339,4335,4335,4335,4328,4312,4290,4270,4263,4271,4291,4313,4331,4343,4356,4373,4394,4411,4416,4408,4392,
-4379,4372,4370,4364,4351,4335,4325,4332,4352,4376,4390,4391,4386,4388,4404,4431,4460,4481,4494,4505,4518,
-4530,4536,4528,4509,4487,4472,4466,4464,4461,4455,4452,4458,4473,4491,4503,4504,4497,4487,4479,4473,4465,
-4452,4436,4422,4412,4408,4405,4402,4395,4385,4373,4360,4344,4325,4307,4289,4274,4258,4241,4219,4193,4165,
-4137,4111,4088,4067,4045,4022,3996,3965,3933,3901,3871,3845,3822,3800,3778,3756,3736,3718,3704,3690,3677,
-3663,3647,3629,3611,3591,3571,3550,3535,3531,3546,3587,3651,3728,3803,3862,3901,3922,3935,3949,3964,3979,
-3989,3995,3997,3996,3991,3976,3950,3916,3883,3855,3833,3809,3774,3724,3664,3599,3536,3476,3418,3364,3317,
-3281,3254,3233,3209,3181,3152,3126,3105,3086,3063,3033,2998,2965,2935,2910,2884,2856,2826,2798,2774,2754,
-2733,2708,2681,2654,2628,2601,2571,2537,2500,2466,2437,2412,2387,2358,2325,2291,2258,2225,2190,2150,2107,
-2067,2031,2000,1968,1935,1898,1862,1829,1799,1770,1736,1699,1660,1623,1589,1557,1524,1488,1450,1412,1376,
-1340,1302,1262,1220,1177,1136,1097,1057,1017,975,934,894,857,820,784,746,706,665,624,583,543,
-503,463,425,390,358,327,297,264,228,189,151,113,75,37,-2,-44,-88,-131,-173,-215,-260,
--305,-349,-389,-424,-454,-484,-519,-560,-606,-652,-694,-732,-767,-803,-841,-880,-920,-957,-991,-1024,-1058,
--1095,-1135,-1176,-1214,-1248,-1279,-1309,-1341,-1377,-1413,-1448,-1478,-1505,-1530,-1559,-1592,-1628,-1663,-1694,-1721,-1746,
--1773,-1802,-1832,-1861,-1887,-1910,-1931,-1953,-1976,-2000,-2024,-2046,-2068,-2091,-2115,-2137,-2157,-2173,-2188,-2202,-2219,
--2237,-2256,-2272,-2287,-2299,-2310,-2323,-2337,-2353,-2368,-2382,-2393,-2401,-2408,-2414,-2422,-2431,-2440,-2445,-2446,-2446,
--2447,-2452,-2461,-2472,-2481,-2486,-2489,-2489,-2488,-2487,-2486,-2484,-2483,-2483,-2483,-2481,-2476,-2469,-2461,-2455,-2453,
--2452,-2448,-2441,-2430,-2419,-2412,-2409,-2407,-2403,-2395,-2381,-2366,-2352,-2339,-2328,-2315,-2300,-2283,-2267,-2252,-2239,
--2226,-2211,-2195,-2179,-2164,-2151,-2137,-2121,-2103,-2085,-2068,-2053,-2039,-2024,-2007,-1988,-1970,-1952,-1935,-1916,-1896,
--1875,-1857,-1842,-1829,-1816,-1801,-1784,-1768,-1752,-1737,-1722,-1712,-1710,-1722,-1745,-1772,-1791,-1793,-1780,-1760,-1742,
--1731,-1724,-1715,-1701,-1685,-1674,-1671,-1672,-1669,-1654,-1630,-1607,-1594,-1598,-1614,-1629,-1633,-1622,-1600,-1573,-1547,
--1524,-1501,-1477,-1451,-1425,-1403,-1384,-1369,-1357,-1350,-1349,-1358,-1375,-1400,-1428,-1455,-1477,-1494,-1503,-1507,-1506,
--1502,-1495,-1488,-1482,-1477,-1476,-1478,-1482,-1489,-1496,-1502,-1504,-1499,-1490,-1479,-1468,-1460,-1451,-1439,-1422,-1402,
--1385,-1375,-1369,-1364,-1353,-1337,-1317,-1298,-1280,-1258,-1226,-1185,-1141,-1104,-1079,-1059,-1034,-997,-951,-910,-885,
--875,-866,-848,-827,-825,-866,-953,-1059,-1136,-1144,-1076,-958,-836,-741,-673,-613,-540,-453,-372,-322,-312,
--332,-362,-385,-400,-416,-438,-464,-484,-495,-500,-509,-527,-552,-573,-578,-568,-551,-539,-536,-540,-543,
--539,-531,-522,-518,-518,-519,-519,-516,-513,-515,-523,-536,-550,-561,-563,-554,-537,-519,-507,-505,-508,
--507,-494,-470,-444,-426,-425,-438,-461,-489,-527,-586,-672,-783,-902,-1007,-1083,-1125,-1143,-1154,-1169,-1192,
--1216,-1236,-1247,-1252,-1256,-1263,-1276,-1290,-1301,-1307,-1308,-1308,-1312,-1322,-1336,-1349,-1357,-1359,-1356,-1355,-1356,
--1361,-1367,-1371,-1373,-1376,-1380,-1387,-1394,-1400,-1402,-1402,-1402,-1402,-1402,-1403,-1403,-1404,-1406,-1410,-1415,-1419,
--1419,-1418,-1416,-1416,-1416,-1415,-1412,-1408,-1404,-1400,-1396,-1392,-1385,-1379,-1374,-1375,-1381,-1391,-1403,-1415,-1426,
--1436,-1441,-1443,-1440,-1436,-1435,-1437,-1442,-1446,-1446,-1442,-1435,-1428,-1421,-1414,-1404,-1392,-1381,-1374,-1370,-1366,
--1360,-1351,-1343,-1339,-1340,-1345,-1349,-1350,-1347,-1345,-1344,-1346,-1349,-1353,-1360,-1372,-1386,-1400,-1410,-1411,-1407,
--1400,-1394,-1388,-1380,-1371,-1362,-1356,-1359,-1369,-1386,-1405,-1425,-1447,-1470,-1492,-1509,-1520,-1525,-1529,-1534,-1542,
--1550,-1557,-1561,-1563,-1568,-1576,-1587,-1599,-1608,-1614,-1619,-1624,-1632,-1642,-1652,-1661,-1667,-1669,-1669,-1671,-1675,
--1682,-1690,-1697,-1702,-1707,-1713,-1719,-1725,-1728,-1727,-1723,-1719,-1719,-1719,-1718,-1711,-1701,-1689,-1681,-1677,-1675,
--1672,-1664,-1652,-1640,-1630,-1621,-1610,-1595,-1578,-1561,-1547,-1537,-1527,-1518,-1509,-1500,-1495,-1492,-1488,-1481,-1469,
--1455,-1439,-1424,-1410,-1395,-1379,-1361,-1344,-1326,-1309,-1292,-1277,-1264,-1254,-1246,-1238,-1229,-1218,-1208,-1198,-1190,
--1184,-1179,-1173,-1166,-1158,-1149,-1138,-1126,-1114,-1103,-1095,-1089,-1083,-1075,-1065,-1056,-1048,-1042,-1036,-1030,-1021,
--1010,-1001,-995,-992,-989,-986,-982,-978,-976,-976,-978,-978,-977,-974,-971,-968,-965,-961,-956,-949,-943,
--938,-936,-936,-939,-943,-947,-952,-955,-957,-958,-959,-960,-963,-966,-970,-975,-980,-985,-990,-994,-996,
--994,-990,-986,-984,-983,-981,-977,-973,-968,-965,-963,-961,-958,-953,-947,-942,-939,-937,-935,-933,-928,
--922,-916,-909,-902,-892,-880,-867,-853,-838,-823,-808,-793,-781,-771,-764,-756,-746,-732,-716,-702,-691,
--685,-681,-679,-678,-677,-674,-669,-659,-643,-623,-602,-584,-569,-555,-541,-523,-502,-482,-463,-446,-429,
--410,-388,-362,-335,-308,-281,-254,-228,-204,-183,-166,-152,-139,-128,-120,-113,-108,-100,-89,-74,-58,
--42,-25,-5,17,42,64,83,97,112,131,155,180,201,216,229,246,270,298,324,343,359,
-375,396,420,442,461,477,497,525,558,589,614,633,652,674,698,719,729,726,715,700,689,
-690,717,789,916,1088,1271,1416,1493,1500,1473,1460,1488,1556,1633,1692,1723,1740,1758,1781,1793,1775,
-1723,1655,1598,1569,1564,1566,1553,1522,1481,1445,1416,1386,1344,1285,1218,1160,1124,1116,1127,1146,1160,
-1166,1161,1149,1139,1133,1136,1143,1150,1152,1146,1137,1131,1130,1131,1129,1121,1111,1105,1108,1117,1123,
-1118,1100,1072,1044,1020,999,972,937,892,844,797,752,708,661,613,567,528,497,471,443,411,
-374,335,296,257,218,179,142,111,85,64,44,21,-2,-27,-52,-74,-95,-115,-134,-151,-164,
--173,-181,-188,-195,-203,-212,-220,-230,-242,-254,-266,-276,-282,-286,-288,-288,-288,-286,-284,-280,-272,
--258,-237,-211,-184,-160,-143,-133,-127,-121,-116,-112,-110,-111,-113,-113,-109,-99,-86,-71,-56,-44,
--36,-32,-30,-29,-26,-21,-13,-3,6,16,27,40,56,75,95,115,133,151,169,189,212,
-237,262,287,309,331,354,380,410,444,479,515,549,583,617,652,685,717,746,775,808,845,
-885,926,964,997,1026,1054,1084,1117,1152,1188,1223,1256,1289,1322,1359,1399,1441,1480,1512,1537,1555,
-1573,1595,1622,1653,1686,1719,1751,1784,1815,1846,1874,1902,1930,1961,1994,2026,2055,2080,2104,2128,2155,
-2181,2204,2223,2240,2258,2283,2313,2346,2378,2406,2430,2451,2469,2486,2502,2519,2538,2557,2576,2592,2606,
-2621,2640,2663,2688,2712,2731,2747,2760,2772,2783,2793,2801,2807,2813,2818,2817,2809,2792,2768,2743,2721,
-2703,2689,2676,2664,2652,2642,2631,2615,2595,2571,2547,2526,2508,2493,2477,2463,2451,2442,2437,2433,2427,
-2419,2409,2399,2389,2380,2373,2367,2363,2360,2357,2352,2346,2340,2336,2331,2342,2335,2326,2313,2301,2291,
-2287,2285,2283,2280,2275,2272,2271,2274,2280,2289,2301,2316,2331,2344,2355,2367,2384,2407,2430,2442,2442,
-2439,2450,2488,2548,2605,2630,2608,2551,2493,2465,2481,2526,2568,2585,2574,2552,2543,2556,2585,2616,2636,
-2645,2654,2672,2702,2742,2781,2811,2828,2834,2833,2834,2841,2859,2886,2916,2942,2959,2968,2972,2978,2989,
-3003,3021,3041,3066,3098,3134,3169,3198,3218,3227,3231,3233,3237,3243,3249,3254,3257,3257,3257,3258,3261,
-3267,3277,3290,3306,3325,3342,3352,3353,3345,3335,3331,3341,3362,3385,3403,3411,3416,3429,3455,3490,3525,
-3550,3566,3584,3614,3662,3726,3796,3865,3926,3974,4003,4003,3978,3945,3931,3964,4047,4160,4262,4321,4327,
-4299,4269,4263,4285,4320,4349,4363,4363,4357,4350,4342,4331,4316,4305,4303,4310,4318,4318,4305,4283,4265,
-4262,4274,4296,4316,4330,4342,4358,4382,4408,4426,4429,4417,4401,4392,4392,4396,4391,4374,4350,4333,4334,
-4352,4376,4393,4397,4394,4393,4403,4422,4443,4460,4472,4482,4495,4507,4513,4507,4493,4478,4470,4468,4470,
-4470,4466,4464,4467,4479,4495,4508,4511,4506,4495,4484,4474,4464,4452,4440,4430,4424,4421,4417,4410,4398,
-4382,4366,4349,4334,4319,4305,4292,4279,4263,4244,4221,4194,4166,4138,4112,4088,4065,4043,4019,3992,3964,
-3936,3910,3887,3865,3842,3819,3797,3779,3766,3758,3751,3741,3723,3699,3671,3646,3626,3612,3603,3595,3592,
-3596,3615,3653,3706,3764,3817,3855,3881,3902,3927,3960,3994,4021,4035,4037,4033,4028,4021,4007,3983,3951,
-3917,3887,3860,3827,3781,3719,3648,3580,3522,3475,3435,3397,3360,3326,3296,3269,3241,3211,3180,3153,3133,
-3115,3096,3071,3040,3006,2975,2947,2921,2894,2866,2840,2816,2795,2773,2748,2720,2690,2660,2631,2599,2565,
-2529,2495,2462,2432,2402,2371,2338,2306,2276,2244,2210,2171,2130,2090,2053,2020,1987,1952,1916,1881,1849,
-1821,1793,1762,1725,1687,1649,1614,1581,1547,1510,1470,1430,1392,1355,1319,1282,1244,1204,1164,1123,1082,
-1040,997,957,919,883,849,814,776,736,695,654,613,573,534,495,457,421,387,355,323,290,
-255,218,181,143,105,66,25,-16,-60,-104,-148,-193,-237,-280,-319,-354,-386,-417,-452,-492,-535,
--578,-619,-657,-693,-730,-769,-808,-848,-885,-921,-956,-991,-1028,-1065,-1102,-1138,-1171,-1203,-1235,-1269,-1305,
--1342,-1378,-1411,-1440,-1465,-1490,-1518,-1551,-1587,-1623,-1656,-1685,-1711,-1739,-1768,-1798,-1827,-1853,-1875,-1896,-1918,
--1940,-1963,-1985,-2006,-2028,-2051,-2075,-2098,-2118,-2134,-2148,-2164,-2183,-2203,-2223,-2240,-2253,-2264,-2275,-2288,-2304,
--2322,-2338,-2353,-2365,-2373,-2380,-2386,-2394,-2402,-2410,-2414,-2414,-2413,-2414,-2421,-2432,-2444,-2455,-2461,-2465,-2467,
--2469,-2471,-2472,-2471,-2469,-2467,-2465,-2464,-2459,-2451,-2441,-2433,-2429,-2430,-2430,-2428,-2419,-2408,-2397,-2391,-2387,
--2384,-2377,-2366,-2353,-2341,-2330,-2321,-2309,-2293,-2275,-2257,-2241,-2227,-2213,-2197,-2180,-2163,-2148,-2136,-2123,-2109,
--2093,-2077,-2061,-2046,-2032,-2017,-2001,-1985,-1969,-1954,-1939,-1920,-1899,-1878,-1859,-1843,-1829,-1815,-1800,-1785,-1772,
--1760,-1748,-1734,-1721,-1715,-1722,-1744,-1772,-1794,-1800,-1788,-1768,-1749,-1737,-1729,-1720,-1704,-1684,-1668,-1662,-1662,
--1662,-1652,-1632,-1610,-1597,-1600,-1617,-1636,-1646,-1641,-1624,-1602,-1581,-1565,-1554,-1543,-1529,-1511,-1490,-1469,-1449,
--1433,-1420,-1409,-1401,-1396,-1397,-1407,-1427,-1456,-1487,-1513,-1528,-1531,-1524,-1516,-1510,-1510,-1515,-1521,-1525,-1526,
--1526,-1526,-1527,-1527,-1524,-1517,-1508,-1498,-1491,-1486,-1480,-1471,-1457,-1442,-1427,-1413,-1399,-1381,-1359,-1335,-1314,
--1294,-1275,-1251,-1221,-1187,-1154,-1123,-1091,-1055,-1017,-981,-955,-939,-923,-897,-864,-844,-864,-940,-1057,-1166,
--1216,-1176,-1059,-914,-792,-716,-673,-630,-564,-481,-408,-373,-382,-418,-456,-478,-489,-499,-516,-540,-560,
--571,-579,-591,-613,-636,-649,-642,-621,-599,-589,-592,-601,-603,-595,-581,-569,-565,-569,-572,-571,-565,
--561,-564,-577,-597,-618,-631,-634,-625,-610,-595,-588,-590,-597,-600,-592,-572,-548,-530,-527,-538,-557,
--582,-619,-677,-764,-874,-992,-1095,-1167,-1205,-1222,-1233,-1250,-1274,-1300,-1320,-1331,-1335,-1339,-1346,-1358,-1370,
--1380,-1385,-1387,-1388,-1393,-1402,-1415,-1428,-1437,-1442,-1443,-1442,-1443,-1446,-1448,-1448,-1447,-1447,-1449,-1454,-1459,
--1462,-1463,-1461,-1460,-1459,-1459,-1458,-1457,-1457,-1459,-1465,-1470,-1472,-1471,-1466,-1461,-1459,-1459,-1458,-1455,-1451,
--1448,-1447,-1448,-1450,-1448,-1443,-1437,-1432,-1431,-1435,-1442,-1452,-1466,-1480,-1493,-1499,-1500,-1498,-1496,-1498,-1503,
--1507,-1505,-1499,-1490,-1482,-1478,-1474,-1467,-1455,-1441,-1428,-1420,-1415,-1410,-1403,-1396,-1390,-1389,-1390,-1392,-1391,
--1387,-1382,-1377,-1374,-1373,-1374,-1379,-1389,-1404,-1420,-1434,-1443,-1448,-1450,-1452,-1449,-1437,-1416,-1391,-1369,-1360,
--1368,-1390,-1419,-1448,-1473,-1492,-1507,-1517,-1524,-1529,-1534,-1541,-1550,-1559,-1568,-1575,-1581,-1589,-1599,-1611,-1622,
--1632,-1637,-1641,-1643,-1647,-1654,-1661,-1669,-1675,-1679,-1681,-1682,-1685,-1688,-1692,-1694,-1695,-1696,-1699,-1706,-1714,
--1721,-1725,-1725,-1724,-1724,-1725,-1724,-1721,-1714,-1707,-1702,-1699,-1696,-1692,-1685,-1676,-1667,-1658,-1650,-1639,-1625,
--1610,-1594,-1580,-1567,-1552,-1536,-1520,-1507,-1499,-1494,-1490,-1483,-1472,-1458,-1444,-1431,-1417,-1401,-1383,-1364,-1344,
--1326,-1309,-1292,-1276,-1261,-1248,-1237,-1227,-1218,-1207,-1196,-1186,-1178,-1170,-1163,-1157,-1151,-1147,-1143,-1139,-1134,
--1127,-1119,-1112,-1105,-1099,-1091,-1081,-1070,-1060,-1052,-1045,-1036,-1026,-1015,-1005,-996,-989,-984,-978,-972,-968,
--967,-969,-971,-972,-970,-967,-964,-962,-961,-960,-955,-949,-942,-938,-937,-938,-941,-943,-946,-949,-953,
--957,-962,-966,-970,-973,-976,-979,-982,-985,-989,-994,-998,-1000,-1001,-1000,-999,-997,-996,-995,-993,-991,
--989,-987,-984,-979,-971,-963,-956,-953,-952,-952,-951,-948,-942,-937,-932,-928,-923,-915,-904,-890,-875,
--859,-842,-825,-807,-791,-777,-765,-755,-743,-729,-716,-704,-695,-689,-684,-681,-678,-677,-676,-671,-661,
--646,-626,-607,-591,-579,-567,-554,-537,-518,-498,-479,-462,-443,-422,-399,-375,-350,-325,-299,-273,-247,
--223,-204,-187,-172,-157,-145,-135,-129,-124,-117,-104,-88,-71,-54,-37,-17,6,33,57,77,92,
-107,126,149,172,190,201,213,230,255,284,309,328,342,358,379,404,428,448,466,487,516,
-549,578,599,613,629,652,680,701,707,694,671,648,638,653,704,803,953,1140,1329,1474,1545,
-1546,1510,1484,1495,1540,1592,1624,1632,1632,1647,1681,1718,1732,1709,1658,1603,1563,1541,1524,1497,1456,
-1411,1373,1346,1321,1287,1240,1186,1143,1122,1126,1144,1164,1174,1173,1162,1147,1133,1125,1123,1128,1136,
-1142,1144,1143,1142,1143,1145,1142,1134,1122,1111,1108,1111,1117,1116,1104,1083,1058,1037,1019,1000,974,
-940,899,853,808,763,721,682,647,617,591,565,534,496,455,412,370,329,286,242,197,155,
-119,90,66,44,24,3,-15,-34,-52,-69,-84,-97,-105,-111,-115,-121,-129,-140,-151,-163,-175,
--188,-202,-215,-226,-234,-237,-236,-234,-233,-234,-235,-234,-227,-213,-192,-167,-142,-121,-108,-101,-97,
--93,-86,-77,-67,-58,-50,-43,-33,-20,-4,10,24,33,36,37,36,37,40,47,56,66,
-77,88,100,115,132,151,170,189,206,223,239,257,277,299,323,346,369,393,419,449,480,
-512,544,573,602,631,660,689,714,736,757,781,811,849,892,935,976,1012,1042,1069,1095,1122,
-1153,1188,1223,1258,1289,1318,1347,1380,1416,1454,1489,1517,1541,1562,1587,1617,1649,1682,1713,1743,1773,
-1805,1838,1868,1895,1919,1944,1973,2003,2034,2062,2086,2109,2132,2156,2179,2200,2219,2239,2262,2291,2324,
-2357,2387,2412,2432,2449,2465,2482,2500,2520,2540,2560,2580,2601,2625,2651,2676,2698,2715,2728,2740,2753,
-2768,2780,2788,2792,2795,2801,2808,2813,2812,2800,2782,2760,2739,2721,2705,2689,2675,2661,2647,2630,2610,
-2585,2559,2537,2520,2507,2495,2483,2471,2461,2457,2457,2457,2453,2445,2433,2421,2410,2402,2396,2390,2386,
-2381,2376,2369,2361,2354,2348,2342,2348,2344,2339,2332,2323,2315,2310,2309,2308,2306,2303,2300,2300,2306,
-2316,2329,2342,2355,2366,2377,2392,2413,2438,2461,2472,2466,2448,2434,2442,2482,2539,2585,2593,2553,2485,
-2426,2408,2438,2494,2544,2564,2555,2538,2537,2563,2606,2649,2676,2687,2693,2707,2736,2774,2813,2842,2856,
-2857,2851,2846,2849,2865,2889,2918,2942,2959,2968,2975,2984,2999,3016,3035,3053,3075,3102,3136,3172,3204,
-3226,3236,3239,3240,3245,3253,3262,3268,3271,3273,3275,3280,3285,3290,3293,3299,3313,3335,3361,3381,3387,
-3377,3361,3352,3359,3381,3407,3425,3432,3437,3454,3489,3537,3580,3606,3612,3613,3630,3674,3743,3824,3898,
-3952,3979,3979,3958,3931,3917,3937,4003,4101,4204,4277,4299,4278,4241,4217,4222,4250,4283,4305,4311,4310,
-4310,4313,4314,4309,4298,4289,4290,4300,4310,4309,4294,4272,4255,4256,4273,4298,4319,4334,4345,4361,4384,
-4408,4425,4430,4424,4417,4417,4423,4429,4423,4404,4377,4357,4352,4362,4380,4393,4397,4394,4394,4403,4419,
-4437,4453,4465,4475,4486,4497,4502,4500,4491,4480,4473,4472,4475,4478,4480,4481,4484,4491,4500,4506,4506,
-4500,4490,4478,4466,4455,4446,4439,4434,4430,4427,4421,4410,4395,4377,4359,4342,4327,4315,4303,4292,4280,
-4264,4244,4219,4192,4163,4134,4109,4085,4063,4041,4017,3991,3965,3941,3920,3900,3880,3857,3831,3806,3788,
-3780,3781,3785,3783,3770,3745,3713,3681,3656,3642,3637,3639,3647,3662,3685,3717,3752,3785,3810,3827,3843,
-3868,3908,3959,4010,4048,4065,4065,4057,4050,4044,4035,4017,3990,3959,3926,3890,3845,3785,3711,3634,3567,
-3518,3485,3461,3436,3408,3376,3346,3318,3290,3258,3225,3193,3166,3145,3127,3106,3081,3052,3021,2991,2961,
-2931,2902,2875,2851,2830,2810,2786,2759,2727,2693,2659,2625,2590,2555,2522,2490,2458,2425,2391,2355,2321,
-2288,2256,2223,2188,2150,2111,2075,2041,2007,1973,1938,1903,1870,1839,1809,1777,1743,1706,1670,1635,1601,
-1566,1529,1490,1449,1409,1371,1335,1300,1263,1226,1186,1146,1105,1064,1024,985,948,913,878,842,805,
-766,725,684,643,603,566,529,493,457,420,384,348,313,279,244,209,172,135,96,56,15,
--27,-72,-119,-165,-210,-250,-285,-315,-346,-381,-421,-465,-509,-550,-587,-621,-656,-694,-735,-775,-813,
--848,-882,-918,-955,-994,-1031,-1065,-1096,-1127,-1160,-1195,-1232,-1270,-1307,-1342,-1374,-1402,-1428,-1454,-1482,-1513,
--1547,-1582,-1615,-1644,-1672,-1700,-1730,-1759,-1787,-1813,-1836,-1858,-1882,-1906,-1929,-1951,-1971,-1992,-2014,-2039,-2062,
--2082,-2098,-2114,-2131,-2152,-2174,-2195,-2211,-2222,-2231,-2242,-2255,-2272,-2290,-2307,-2321,-2333,-2343,-2350,-2357,-2364,
--2371,-2376,-2380,-2381,-2383,-2387,-2397,-2411,-2425,-2436,-2441,-2442,-2442,-2444,-2448,-2451,-2452,-2451,-2449,-2447,-2446,
--2443,-2436,-2427,-2418,-2413,-2413,-2415,-2415,-2410,-2400,-2389,-2381,-2375,-2371,-2364,-2353,-2339,-2327,-2317,-2308,-2298,
--2284,-2267,-2248,-2231,-2215,-2200,-2185,-2167,-2151,-2136,-2123,-2111,-2098,-2083,-2068,-2054,-2041,-2027,-2012,-1996,-1981,
--1967,-1955,-1941,-1925,-1906,-1886,-1868,-1852,-1836,-1819,-1800,-1783,-1770,-1761,-1751,-1739,-1727,-1720,-1726,-1747,-1776,
--1800,-1806,-1794,-1772,-1751,-1737,-1730,-1722,-1706,-1684,-1664,-1654,-1654,-1657,-1653,-1639,-1620,-1605,-1605,-1620,-1642,
--1659,-1664,-1654,-1638,-1622,-1612,-1609,-1609,-1603,-1590,-1570,-1545,-1523,-1504,-1489,-1472,-1449,-1421,-1395,-1382,-1390,
--1420,-1465,-1510,-1543,-1558,-1557,-1549,-1545,-1548,-1556,-1564,-1567,-1563,-1555,-1549,-1547,-1546,-1545,-1540,-1532,-1524,
--1520,-1519,-1518,-1514,-1504,-1488,-1469,-1450,-1431,-1410,-1386,-1361,-1337,-1314,-1293,-1271,-1245,-1215,-1182,-1147,-1113,
--1081,-1054,-1034,-1019,-1002,-973,-931,-891,-879,-922,-1018,-1134,-1216,-1217,-1129,-987,-849,-761,-730,-724,-699,
--636,-548,-473,-442,-459,-504,-548,-574,-586,-595,-611,-630,-645,-652,-657,-668,-685,-701,-703,-687,-661,
--640,-636,-645,-656,-655,-642,-623,-611,-609,-615,-618,-614,-605,-600,-605,-623,-648,-673,-691,-697,-694,
--687,-681,-683,-692,-704,-712,-707,-690,-669,-653,-649,-658,-675,-699,-733,-787,-866,-968,-1076,-1170,-1236,
--1273,-1293,-1309,-1330,-1357,-1385,-1406,-1420,-1428,-1434,-1441,-1449,-1456,-1461,-1464,-1466,-1468,-1473,-1480,-1490,-1500,
--1510,-1517,-1522,-1525,-1527,-1527,-1525,-1521,-1517,-1514,-1514,-1516,-1519,-1521,-1520,-1519,-1518,-1518,-1517,-1516,-1513,
--1511,-1512,-1516,-1521,-1524,-1523,-1519,-1515,-1512,-1509,-1505,-1499,-1491,-1486,-1486,-1492,-1501,-1507,-1508,-1505,-1500,
--1494,-1490,-1489,-1493,-1504,-1519,-1536,-1550,-1557,-1559,-1558,-1558,-1559,-1559,-1556,-1549,-1542,-1539,-1539,-1540,-1535,
--1522,-1504,-1486,-1473,-1466,-1462,-1458,-1452,-1447,-1443,-1440,-1438,-1434,-1428,-1421,-1415,-1409,-1404,-1401,-1401,-1406,
--1416,-1429,-1442,-1455,-1469,-1484,-1499,-1509,-1507,-1491,-1465,-1439,-1425,-1427,-1444,-1467,-1488,-1503,-1511,-1516,-1522,
--1530,-1540,-1552,-1562,-1571,-1578,-1584,-1590,-1598,-1607,-1619,-1631,-1643,-1654,-1661,-1667,-1670,-1672,-1674,-1676,-1679,
--1682,-1685,-1688,-1691,-1694,-1697,-1697,-1696,-1692,-1689,-1688,-1692,-1700,-1709,-1717,-1722,-1725,-1726,-1727,-1728,-1726,
--1723,-1719,-1714,-1711,-1708,-1704,-1699,-1694,-1690,-1685,-1678,-1667,-1653,-1637,-1623,-1610,-1597,-1581,-1563,-1543,-1526,
--1514,-1507,-1500,-1491,-1479,-1465,-1451,-1438,-1425,-1410,-1392,-1372,-1352,-1334,-1316,-1298,-1279,-1260,-1243,-1229,-1218,
--1208,-1199,-1189,-1179,-1170,-1161,-1152,-1143,-1137,-1133,-1132,-1131,-1129,-1126,-1120,-1113,-1107,-1101,-1094,-1086,-1077,
--1068,-1060,-1053,-1046,-1038,-1029,-1019,-1011,-1002,-993,-984,-976,-971,-969,-969,-970,-969,-965,-960,-956,-955,
--955,-954,-951,-946,-940,-938,-938,-940,-943,-944,-946,-948,-952,-959,-965,-971,-975,-978,-981,-983,-986,
--990,-993,-997,-1000,-1003,-1005,-1007,-1010,-1011,-1013,-1013,-1012,-1011,-1009,-1007,-1002,-996,-987,-979,-972,-969,
--969,-968,-966,-960,-953,-947,-943,-940,-936,-930,-921,-909,-895,-880,-863,-844,-825,-806,-788,-773,-758,
--742,-727,-713,-702,-693,-686,-680,-674,-671,-670,-670,-668,-662,-649,-634,-618,-606,-596,-586,-573,-557,
--538,-519,-500,-481,-461,-439,-416,-394,-372,-348,-323,-295,-269,-246,-227,-211,-195,-178,-161,-148,-140,
--133,-126,-114,-99,-83,-68,-53,-34,-11,15,41,62,80,96,116,139,160,175,187,200,219,
-245,274,297,313,326,342,365,394,421,443,463,486,514,544,570,587,600,616,639,664,680,
-678,657,627,602,596,618,678,787,946,1141,1336,1487,1562,1564,1529,1505,1522,1572,1623,1644,1628,
-1599,1590,1617,1666,1704,1706,1667,1605,1546,1502,1469,1437,1398,1357,1321,1293,1268,1239,1202,1165,1140,
-1135,1148,1166,1179,1180,1169,1154,1138,1125,1115,1111,1112,1119,1129,1139,1147,1152,1157,1159,1158,1150,
-1137,1122,1111,1108,1111,1111,1105,1090,1070,1052,1037,1024,1007,983,950,911,870,833,801,773,749,
-726,702,673,638,596,551,505,460,414,366,312,255,197,144,99,64,39,20,7,-3,-13,
--25,-37,-50,-62,-70,-75,-78,-80,-85,-91,-100,-109,-119,-130,-142,-155,-168,-176,-180,-180,-178,
--176,-176,-176,-175,-169,-157,-139,-118,-97,-79,-66,-56,-49,-42,-33,-21,-7,8,22,36,49,
-61,72,82,89,93,95,96,97,99,102,107,113,122,133,149,166,184,201,216,229,243,
-259,277,297,318,340,361,381,401,421,445,474,505,538,569,596,618,638,658,678,696,710,
-723,736,755,783,821,866,914,963,1009,1049,1082,1109,1131,1154,1182,1215,1249,1279,1304,1325,1348,
-1376,1412,1450,1485,1516,1543,1571,1602,1635,1667,1696,1725,1756,1790,1826,1858,1884,1904,1922,1943,1970,
-2001,2032,2059,2083,2105,2128,2154,2181,2208,2235,2263,2291,2321,2350,2376,2398,2416,2433,2450,2469,2490,
-2510,2529,2548,2568,2591,2619,2648,2673,2692,2702,2709,2716,2727,2740,2753,2763,2772,2782,2793,2806,2815,
-2817,2811,2797,2779,2760,2739,2715,2691,2668,2649,2633,2619,2600,2579,2556,2538,2527,2520,2514,2506,2496,
-2487,2482,2480,2477,2471,2459,2446,2434,2425,2418,2413,2408,2402,2397,2390,2382,2372,2362,2354,2348,2358,
-2357,2356,2352,2345,2335,2327,2322,2320,2320,2321,2324,2331,2342,2356,2369,2380,2389,2398,2412,2433,2458,
-2481,2489,2478,2448,2414,2397,2412,2457,2511,2543,2530,2472,2398,2346,2345,2394,2467,2530,2560,2563,2558,
-2569,2603,2648,2686,2705,2708,2708,2718,2744,2781,2817,2843,2855,2857,2855,2855,2862,2876,2897,2919,2940,
-2956,2968,2980,2995,3013,3033,3052,3069,3089,3114,3146,3182,3214,3236,3246,3250,3253,3261,3272,3282,3287,
-3288,3289,3294,3304,3315,3321,3322,3322,3330,3352,3383,3409,3419,3410,3393,3383,3391,3415,3441,3457,3460,
-3462,3480,3521,3576,3624,3651,3654,3652,3666,3709,3778,3854,3915,3947,3949,3931,3910,3903,3925,3982,4068,
-4163,4240,4276,4268,4232,4196,4183,4198,4228,4256,4270,4271,4268,4270,4276,4281,4282,4279,4281,4289,4302,
-4308,4300,4278,4253,4239,4245,4269,4300,4327,4345,4358,4372,4389,4407,4420,4426,4428,4430,4437,4446,4451,
-4446,4430,4408,4389,4378,4377,4381,4383,4382,4382,4386,4399,4417,4438,4456,4470,4481,4490,4498,4503,4502,
-4496,4488,4480,4477,4479,4484,4491,4497,4501,4503,4503,4502,4499,4494,4487,4479,4469,4460,4452,4446,4441,
-4434,4426,4416,4403,4388,4372,4356,4340,4325,4311,4299,4287,4274,4257,4236,4210,4182,4152,4125,4100,4079,
-4059,4040,4019,3995,3970,3946,3924,3903,3881,3856,3828,3803,3787,3783,3790,3802,3810,3805,3787,3758,3726,
-3697,3677,3667,3667,3674,3689,3710,3734,3756,3773,3782,3789,3803,3834,3885,3949,4011,4057,4080,4083,4077,
-4070,4066,4061,4050,4030,4002,3969,3928,3875,3806,3727,3649,3585,3542,3515,3495,3470,3439,3406,3377,3354,
-3332,3307,3276,3241,3208,3181,3159,3139,3117,3091,3060,3028,2996,2963,2931,2902,2877,2857,2838,2817,2791,
-2760,2725,2688,2651,2615,2580,2548,2517,2487,2455,2420,2383,2344,2307,2272,2238,2204,2168,2132,2095,2060,
-2027,1996,1963,1929,1894,1859,1824,1790,1757,1723,1689,1654,1618,1582,1545,1507,1469,1430,1392,1355,1319,
-1282,1245,1206,1166,1127,1089,1054,1018,983,946,908,870,832,793,752,711,670,632,596,563,529,
-494,455,415,376,339,304,270,235,199,161,123,83,43,0,-45,-92,-138,-182,-219,-251,-281,
--312,-348,-391,-436,-481,-521,-556,-591,-627,-666,-707,-746,-781,-813,-846,-881,-919,-957,-993,-1025,-1056,
--1088,-1124,-1162,-1201,-1237,-1270,-1301,-1331,-1360,-1389,-1418,-1448,-1479,-1511,-1543,-1575,-1604,-1633,-1663,-1693,-1722,
--1750,-1774,-1797,-1820,-1845,-1871,-1896,-1918,-1938,-1957,-1978,-2001,-2024,-2045,-2064,-2082,-2101,-2124,-2146,-2165,-2178,
--2186,-2194,-2206,-2222,-2241,-2259,-2275,-2289,-2301,-2311,-2321,-2329,-2336,-2342,-2346,-2349,-2353,-2358,-2366,-2378,-2394,
--2409,-2420,-2423,-2421,-2418,-2417,-2421,-2427,-2432,-2434,-2434,-2433,-2432,-2430,-2425,-2418,-2410,-2404,-2403,-2403,-2403,
--2399,-2392,-2383,-2376,-2371,-2365,-2356,-2343,-2327,-2312,-2301,-2292,-2284,-2272,-2257,-2240,-2223,-2208,-2194,-2179,-2164,
--2148,-2134,-2121,-2108,-2095,-2081,-2067,-2054,-2043,-2030,-2016,-2001,-1985,-1970,-1957,-1943,-1927,-1911,-1894,-1879,-1864,
--1848,-1829,-1808,-1788,-1773,-1764,-1756,-1745,-1734,-1727,-1734,-1756,-1786,-1810,-1817,-1803,-1777,-1752,-1737,-1730,-1723,
--1710,-1689,-1668,-1656,-1656,-1661,-1662,-1652,-1634,-1618,-1615,-1627,-1652,-1676,-1691,-1692,-1683,-1672,-1665,-1665,-1666,
--1661,-1646,-1622,-1596,-1574,-1558,-1546,-1528,-1498,-1454,-1407,-1374,-1369,-1397,-1448,-1507,-1555,-1582,-1590,-1587,-1584,
--1586,-1592,-1596,-1595,-1587,-1578,-1571,-1569,-1569,-1568,-1564,-1556,-1550,-1548,-1551,-1554,-1551,-1540,-1522,-1500,-1480,
--1462,-1444,-1425,-1401,-1375,-1347,-1318,-1289,-1257,-1224,-1192,-1162,-1136,-1116,-1102,-1090,-1075,-1049,-1010,-966,-936,
--944,-999,-1085,-1163,-1187,-1132,-1015,-884,-792,-766,-788,-813,-797,-728,-634,-557,-529,-550,-597,-640,-666,
--678,-689,-705,-721,-730,-731,-729,-733,-743,-750,-745,-724,-698,-681,-680,-690,-698,-695,-679,-661,-652,
--654,-661,-663,-657,-646,-641,-648,-670,-700,-731,-756,-772,-780,-783,-786,-793,-804,-816,-824,-821,-807,
--787,-773,-770,-780,-799,-824,-857,-906,-975,-1062,-1154,-1235,-1295,-1333,-1359,-1382,-1409,-1439,-1466,-1489,-1505,
--1519,-1530,-1540,-1546,-1548,-1548,-1548,-1549,-1553,-1557,-1562,-1567,-1573,-1580,-1587,-1592,-1595,-1596,-1594,-1590,-1584,
--1579,-1575,-1573,-1574,-1577,-1579,-1579,-1580,-1580,-1581,-1581,-1577,-1571,-1565,-1561,-1562,-1566,-1571,-1573,-1572,-1570,
--1567,-1564,-1557,-1548,-1537,-1530,-1529,-1536,-1547,-1557,-1564,-1566,-1563,-1558,-1553,-1548,-1546,-1550,-1560,-1574,-1589,
--1600,-1605,-1606,-1605,-1605,-1605,-1604,-1601,-1599,-1598,-1599,-1599,-1595,-1583,-1567,-1549,-1536,-1527,-1522,-1516,-1509,
--1500,-1492,-1485,-1479,-1474,-1467,-1461,-1454,-1447,-1441,-1435,-1430,-1429,-1431,-1436,-1445,-1456,-1472,-1493,-1517,-1539,
--1552,-1554,-1545,-1532,-1523,-1522,-1527,-1533,-1535,-1532,-1525,-1523,-1528,-1542,-1563,-1584,-1601,-1610,-1612,-1611,-1611,
--1614,-1622,-1632,-1643,-1654,-1665,-1677,-1689,-1698,-1703,-1704,-1700,-1696,-1692,-1690,-1691,-1694,-1697,-1701,-1703,-1703,
--1701,-1697,-1694,-1695,-1699,-1706,-1714,-1720,-1724,-1726,-1728,-1729,-1730,-1729,-1727,-1724,-1721,-1716,-1712,-1708,-1706,
--1704,-1701,-1695,-1685,-1671,-1656,-1644,-1634,-1623,-1611,-1593,-1573,-1554,-1538,-1526,-1516,-1505,-1491,-1477,-1462,-1449,
--1435,-1419,-1401,-1382,-1363,-1345,-1328,-1309,-1289,-1269,-1249,-1232,-1218,-1207,-1196,-1186,-1175,-1166,-1156,-1146,-1137,
--1128,-1121,-1117,-1114,-1112,-1108,-1102,-1096,-1090,-1085,-1079,-1073,-1067,-1061,-1056,-1052,-1048,-1043,-1037,-1031,-1024,
--1016,-1006,-996,-986,-979,-976,-975,-975,-972,-967,-960,-954,-951,-950,-949,-946,-943,-939,-938,-939,-942,
--945,-948,-950,-952,-957,-963,-969,-974,-977,-979,-980,-983,-988,-992,-996,-999,-1000,-1001,-1003,-1007,-1012,
--1017,-1022,-1025,-1025,-1024,-1022,-1019,-1015,-1010,-1004,-998,-993,-989,-985,-980,-973,-964,-957,-951,-946,-943,
--939,-933,-926,-918,-907,-894,-879,-860,-840,-821,-802,-784,-766,-747,-729,-714,-703,-694,-685,-677,-668,
--663,-662,-664,-665,-663,-656,-645,-633,-623,-613,-603,-591,-575,-558,-541,-523,-504,-483,-461,-438,-416,
--395,-371,-345,-317,-291,-269,-253,-238,-223,-204,-184,-167,-153,-144,-134,-123,-110,-97,-85,-72,-55,
--32,-5,20,42,61,81,103,126,146,162,174,188,209,235,261,282,297,310,328,355,385,
-414,438,459,483,510,538,561,577,590,605,625,642,648,635,609,581,565,568,593,650,749,
-898,1089,1287,1444,1524,1530,1501,1490,1528,1607,1684,1715,1688,1629,1584,1583,1622,1666,1679,1647,1582,
-1509,1450,1409,1377,1345,1310,1278,1251,1229,1207,1182,1160,1148,1148,1158,1168,1168,1157,1141,1126,1116,
-1110,1105,1100,1099,1103,1113,1126,1138,1148,1155,1159,1161,1157,1147,1133,1121,1113,1112,1112,1109,1098,
-1082,1066,1054,1044,1033,1015,990,960,931,905,883,865,846,823,797,765,728,687,644,599,555,
-509,459,403,339,270,202,140,88,49,21,3,-7,-15,-24,-35,-48,-60,-70,-74,-75,-74,
--72,-73,-76,-79,-84,-90,-98,-108,-118,-127,-132,-132,-130,-126,-122,-118,-112,-102,-90,-75,-60,
--45,-29,-13,1,15,28,40,53,67,82,98,111,120,124,124,122,119,118,119,123,128,
-132,135,137,139,147,162,183,208,230,246,255,261,268,281,301,327,355,380,401,416,429,
-443,461,487,519,553,585,611,629,643,654,664,674,683,693,705,722,746,778,817,864,919,
-979,1038,1087,1122,1145,1162,1182,1209,1242,1274,1298,1315,1330,1352,1384,1423,1462,1497,1527,1557,1589,
-1623,1658,1691,1722,1753,1788,1825,1859,1885,1903,1917,1934,1957,1987,2018,2046,2070,2091,2113,2140,2171,
-2204,2236,2266,2294,2320,2343,2363,2381,2397,2413,2430,2450,2471,2491,2510,2528,2548,2572,2599,2626,2650,
-2667,2678,2685,2692,2701,2711,2723,2735,2748,2764,2780,2794,2801,2800,2794,2785,2775,2761,2742,2715,2685,
-2658,2640,2630,2623,2611,2594,2574,2557,2547,2542,2539,2533,2524,2513,2505,2499,2492,2483,2472,2460,2450,
-2443,2438,2432,2425,2417,2410,2402,2394,2383,2372,2363,2358,2376,2374,2373,2368,2359,2347,2337,2332,2334,
-2340,2349,2360,2372,2384,2395,2403,2409,2414,2424,2440,2461,2481,2489,2478,2449,2413,2388,2390,2425,2480,
-2529,2544,2510,2439,2362,2315,2319,2370,2442,2506,2544,2560,2572,2593,2626,2660,2682,2688,2685,2686,2701,
-2731,2767,2799,2821,2834,2843,2852,2863,2876,2891,2908,2926,2943,2960,2976,2992,3009,3028,3047,3067,3086,
-3107,3133,3164,3197,3225,3244,3254,3259,3265,3276,3290,3301,3306,3306,3308,3317,3331,3346,3354,3354,3352,
-3359,3380,3410,3437,3447,3439,3423,3416,3427,3453,3479,3491,3491,3490,3506,3545,3597,3644,3671,3680,3687,
-3710,3757,3819,3875,3906,3908,3891,3873,3872,3898,3954,4031,4114,4185,4228,4236,4215,4183,4160,4158,4177,
-4203,4223,4232,4233,4233,4238,4245,4251,4255,4261,4272,4288,4301,4301,4284,4256,4230,4221,4234,4265,4302,
-4333,4357,4373,4388,4402,4415,4426,4432,4437,4442,4448,4454,4457,4454,4446,4434,4422,4409,4397,4386,4376,
-4370,4369,4377,4393,4415,4438,4460,4477,4490,4498,4504,4507,4508,4506,4501,4495,4491,4490,4494,4499,4504,
-4505,4502,4497,4492,4490,4488,4485,4480,4473,4465,4458,4451,4443,4433,4420,4405,4391,4378,4366,4351,4335,
-4318,4301,4286,4273,4259,4242,4221,4195,4166,4137,4111,4088,4070,4054,4038,4020,3997,3971,3942,3915,3888,
-3862,3836,3811,3792,3781,3783,3793,3806,3815,3814,3802,3781,3757,3734,3714,3699,3690,3687,3693,3705,3722,
-3738,3749,3755,3760,3774,3805,3857,3924,3994,4051,4087,4102,4103,4098,4091,4084,4073,4057,4035,4007,3968,
-3913,3843,3764,3687,3625,3582,3552,3524,3489,3448,3408,3377,3358,3346,3331,3308,3277,3244,3215,3191,3170,
-3147,3120,3090,3058,3025,2993,2962,2933,2907,2885,2865,2843,2818,2788,2754,2718,2681,2644,2607,2572,2539,
-2508,2477,2445,2409,2370,2331,2293,2259,2225,2191,2154,2117,2080,2048,2018,1988,1955,1919,1880,1843,1808,
-1776,1744,1710,1673,1634,1595,1557,1520,1484,1447,1409,1372,1336,1299,1262,1222,1182,1144,1109,1077,1046,
-1013,976,937,896,856,817,777,738,698,660,626,593,560,524,485,445,404,366,331,296,260,
-223,185,145,104,63,19,-26,-71,-115,-156,-191,-224,-255,-288,-325,-367,-409,-451,-489,-525,-561,
--599,-639,-679,-716,-750,-782,-814,-848,-884,-920,-954,-987,-1020,-1056,-1095,-1135,-1172,-1205,-1233,-1259,-1287,
--1317,-1348,-1380,-1412,-1445,-1477,-1509,-1540,-1569,-1599,-1630,-1662,-1692,-1720,-1744,-1765,-1788,-1813,-1839,-1865,-1888,
--1907,-1925,-1945,-1966,-1988,-2010,-2031,-2051,-2073,-2096,-2117,-2132,-2141,-2147,-2156,-2171,-2191,-2212,-2230,-2244,-2255,
--2265,-2278,-2291,-2302,-2310,-2315,-2319,-2324,-2330,-2338,-2348,-2360,-2374,-2388,-2399,-2403,-2402,-2398,-2396,-2399,-2406,
--2415,-2421,-2423,-2422,-2419,-2416,-2412,-2408,-2404,-2399,-2397,-2395,-2393,-2389,-2383,-2377,-2372,-2367,-2361,-2351,-2336,
--2320,-2305,-2293,-2285,-2278,-2268,-2254,-2239,-2224,-2210,-2196,-2182,-2167,-2152,-2139,-2126,-2114,-2102,-2088,-2075,-2063,
--2052,-2041,-2028,-2013,-1997,-1980,-1965,-1949,-1932,-1916,-1901,-1888,-1876,-1861,-1843,-1823,-1803,-1788,-1778,-1769,-1758,
--1746,-1739,-1744,-1764,-1794,-1819,-1826,-1813,-1787,-1759,-1741,-1733,-1727,-1716,-1697,-1678,-1665,-1664,-1669,-1673,-1666,
--1650,-1634,-1627,-1638,-1662,-1690,-1712,-1722,-1722,-1717,-1713,-1712,-1709,-1699,-1679,-1651,-1624,-1605,-1596,-1590,-1576,
--1546,-1498,-1443,-1401,-1386,-1406,-1452,-1509,-1560,-1594,-1610,-1614,-1614,-1615,-1616,-1615,-1610,-1603,-1597,-1595,-1596,
--1597,-1594,-1586,-1577,-1571,-1572,-1578,-1583,-1581,-1568,-1548,-1526,-1508,-1495,-1484,-1470,-1449,-1422,-1389,-1353,-1315,
--1278,-1245,-1216,-1194,-1178,-1166,-1152,-1134,-1106,-1071,-1034,-1006,-1002,-1028,-1078,-1126,-1141,-1099,-1006,-893,-809,
--786,-823,-881,-912,-883,-802,-706,-638,-622,-649,-693,-727,-744,-752,-763,-781,-799,-807,-804,-797,-796,
--800,-802,-794,-771,-745,-726,-720,-725,-729,-725,-713,-702,-699,-705,-713,-715,-709,-701,-698,-708,-731,
--763,-799,-834,-863,-884,-896,-900,-903,-907,-913,-918,-916,-906,-893,-884,-887,-903,-930,-961,-997,-1043,
--1102,-1173,-1247,-1314,-1365,-1401,-1428,-1452,-1477,-1501,-1524,-1546,-1568,-1591,-1614,-1632,-1642,-1644,-1641,-1639,-1640,
--1642,-1645,-1646,-1646,-1648,-1651,-1655,-1657,-1657,-1654,-1650,-1646,-1642,-1637,-1634,-1632,-1632,-1635,-1639,-1642,-1645,
--1647,-1647,-1645,-1640,-1630,-1620,-1612,-1609,-1611,-1616,-1620,-1621,-1621,-1619,-1616,-1610,-1602,-1593,-1585,-1583,-1588,
--1596,-1605,-1612,-1615,-1616,-1616,-1614,-1611,-1607,-1606,-1609,-1616,-1625,-1633,-1637,-1638,-1638,-1640,-1645,-1650,-1653,
--1654,-1652,-1649,-1645,-1639,-1631,-1622,-1612,-1604,-1596,-1587,-1576,-1563,-1549,-1536,-1527,-1520,-1514,-1508,-1502,-1495,
--1488,-1480,-1472,-1464,-1457,-1453,-1452,-1455,-1463,-1474,-1492,-1514,-1538,-1561,-1580,-1592,-1600,-1603,-1605,-1603,-1595,
--1582,-1565,-1549,-1541,-1546,-1563,-1590,-1618,-1639,-1650,-1651,-1646,-1641,-1640,-1644,-1650,-1657,-1663,-1672,-1684,-1700,
--1715,-1727,-1731,-1729,-1721,-1712,-1705,-1699,-1697,-1697,-1700,-1705,-1711,-1716,-1718,-1718,-1718,-1719,-1721,-1723,-1726,
--1727,-1727,-1728,-1729,-1731,-1733,-1735,-1735,-1734,-1731,-1726,-1720,-1715,-1711,-1707,-1701,-1692,-1681,-1670,-1660,-1653,
--1647,-1637,-1623,-1604,-1584,-1565,-1550,-1536,-1522,-1507,-1492,-1476,-1461,-1446,-1430,-1413,-1394,-1375,-1358,-1342,-1325,
--1308,-1289,-1270,-1253,-1237,-1221,-1207,-1192,-1179,-1167,-1156,-1146,-1135,-1124,-1113,-1103,-1095,-1089,-1083,-1077,-1071,
--1065,-1060,-1054,-1050,-1045,-1042,-1039,-1037,-1035,-1033,-1030,-1026,-1022,-1016,-1008,-999,-990,-983,-979,-978,-979,
--977,-973,-967,-960,-955,-951,-949,-946,-943,-940,-939,-941,-944,-948,-952,-955,-958,-962,-967,-972,-976,
--979,-981,-984,-988,-993,-998,-1002,-1004,-1004,-1004,-1004,-1006,-1010,-1014,-1019,-1023,-1026,-1026,-1025,-1023,-1021,
--1019,-1017,-1014,-1010,-1004,-995,-984,-972,-962,-954,-949,-945,-941,-936,-930,-923,-916,-908,-896,-881,-864,
--846,-829,-812,-794,-775,-754,-735,-720,-708,-698,-688,-676,-666,-659,-658,-662,-665,-666,-661,-653,-643,
--634,-626,-616,-604,-590,-575,-561,-546,-528,-508,-485,-462,-440,-417,-393,-366,-338,-312,-292,-277,-265,
--250,-232,-211,-190,-173,-160,-148,-136,-125,-114,-102,-88,-69,-46,-20,3,24,43,64,88,112,
-133,149,162,177,197,221,245,264,280,296,319,347,376,402,423,444,469,498,526,547,562,
-574,590,606,616,611,589,560,540,537,551,580,627,710,842,1022,1218,1377,1462,1470,1446,1449,
-1516,1633,1748,1804,1776,1692,1605,1563,1572,1604,1619,1593,1531,1458,1396,1353,1322,1291,1257,1226,1203,
-1190,1181,1171,1161,1154,1152,1153,1150,1139,1121,1103,1092,1090,1093,1095,1093,1091,1092,1100,1113,1127,
-1137,1145,1151,1157,1160,1158,1152,1143,1136,1133,1133,1130,1121,1108,1093,1081,1071,1060,1046,1026,1005,
-985,969,956,942,922,896,865,831,795,758,720,679,638,597,552,503,446,380,309,237,169,
-112,65,29,3,-15,-31,-44,-56,-65,-71,-72,-70,-66,-64,-63,-65,-67,-70,-72,-76,-81,
--88,-94,-96,-96,-92,-87,-80,-71,-59,-44,-28,-12,1,15,30,47,67,88,107,123,137,
-149,161,172,178,179,173,162,150,139,132,129,131,135,137,136,133,133,139,156,182,211,
-238,256,266,270,276,288,309,337,367,393,413,425,431,436,446,464,492,525,559,587,607,
-621,631,640,650,663,679,697,715,733,752,777,814,869,940,1017,1087,1138,1169,1185,1201,1224,
-1257,1291,1319,1338,1352,1371,1398,1434,1472,1506,1536,1566,1599,1637,1677,1715,1749,1780,1812,1846,1878,
-1905,1925,1940,1955,1975,2000,2026,2050,2070,2089,2109,2134,2163,2194,2225,2253,2278,2302,2323,2343,2360,
-2376,2392,2408,2426,2445,2465,2487,2509,2532,2557,2581,2604,2624,2641,2655,2667,2678,2686,2693,2700,2709,
-2722,2738,2754,2763,2764,2758,2752,2748,2746,2741,2727,2704,2677,2655,2645,2645,2647,2641,2626,2605,2585,
-2572,2566,2562,2555,2544,2532,2522,2515,2509,2502,2493,2484,2477,2471,2465,2456,2444,2433,2424,2417,2409,
-2400,2390,2381,2376,2403,2398,2393,2385,2374,2364,2359,2361,2370,2383,2397,2410,2419,2423,2425,2423,2422,
-2426,2437,2452,2467,2474,2466,2446,2423,2409,2418,2452,2504,2555,2583,2572,2522,2450,2381,2342,2342,2377,
-2429,2478,2515,2543,2568,2594,2619,2636,2642,2640,2640,2654,2683,2722,2760,2789,2808,2821,2836,2854,2873,
-2892,2908,2922,2938,2957,2977,2996,3013,3029,3046,3063,3083,3105,3128,3154,3181,3208,3232,3248,3258,3265,
-3274,3287,3302,3315,3323,3328,3334,3345,3359,3372,3378,3379,3381,3391,3414,3442,3464,3470,3461,3448,3444,
-3458,3484,3507,3518,3518,3519,3534,3567,3609,3647,3672,3690,3712,3750,3800,3848,3875,3873,3849,3826,3823,
-3853,3911,3986,4059,4118,4154,4166,4158,4140,4124,4118,4126,4142,4158,4170,4178,4185,4195,4208,4220,4228,
-4236,4248,4265,4284,4295,4289,4266,4237,4216,4215,4236,4270,4308,4340,4365,4385,4403,4418,4431,4441,4448,
-4454,4458,4461,4461,4460,4458,4457,4455,4449,4437,4420,4400,4383,4373,4372,4380,4395,4415,4438,4462,4482,
-4497,4506,4510,4512,4515,4519,4520,4520,4517,4513,4511,4509,4505,4499,4491,4483,4478,4476,4477,4475,4470,
-4462,4454,4448,4443,4437,4426,4412,4396,4380,4367,4354,4340,4323,4305,4288,4273,4259,4245,4227,4205,4179,
-4151,4125,4100,4079,4062,4047,4031,4013,3989,3960,3927,3894,3862,3833,3808,3788,3777,3774,3781,3790,3798,
-3798,3790,3778,3765,3758,3754,3753,3751,3747,3742,3742,3747,3757,3767,3773,3771,3766,3766,3782,3821,3882,
-3954,4024,4079,4112,4125,4123,4112,4098,4083,4068,4052,4030,3996,3945,3876,3797,3721,3659,3615,3581,3547,
-3506,3458,3412,3377,3356,3344,3332,3314,3289,3261,3236,3214,3194,3170,3143,3112,3081,3051,3022,2995,2968,
-2943,2919,2896,2872,2843,2811,2778,2744,2710,2674,2636,2596,2556,2520,2487,2455,2422,2386,2348,2312,2278,
-2247,2215,2180,2142,2104,2069,2038,2008,1975,1939,1900,1862,1828,1797,1766,1731,1691,1649,1606,1567,1529,
-1493,1456,1418,1381,1346,1311,1274,1235,1193,1154,1119,1089,1060,1030,995,956,915,876,838,802,765,
-727,690,654,619,583,546,508,468,430,393,357,321,284,246,207,167,125,82,37,-6,-50,
--90,-127,-162,-197,-233,-271,-309,-348,-387,-424,-460,-495,-531,-568,-606,-644,-681,-716,-750,-783,-818,
--852,-886,-919,-952,-988,-1027,-1067,-1106,-1141,-1171,-1197,-1223,-1251,-1281,-1313,-1346,-1379,-1412,-1445,-1477,-1508,
--1538,-1567,-1598,-1630,-1661,-1690,-1714,-1736,-1758,-1783,-1810,-1837,-1860,-1880,-1898,-1917,-1937,-1958,-1980,-2001,-2023,
--2046,-2068,-2087,-2100,-2108,-2116,-2127,-2146,-2168,-2189,-2204,-2213,-2219,-2228,-2242,-2258,-2272,-2281,-2286,-2290,-2298,
--2308,-2320,-2331,-2341,-2352,-2362,-2373,-2380,-2383,-2382,-2381,-2383,-2391,-2402,-2410,-2413,-2411,-2405,-2400,-2396,-2395,
--2395,-2395,-2395,-2393,-2389,-2383,-2377,-2371,-2365,-2360,-2353,-2343,-2331,-2317,-2305,-2297,-2290,-2283,-2273,-2260,-2246,
--2231,-2218,-2204,-2189,-2174,-2159,-2146,-2135,-2125,-2113,-2101,-2087,-2075,-2063,-2051,-2039,-2024,-2008,-1992,-1976,-1960,
--1944,-1928,-1913,-1900,-1888,-1875,-1858,-1839,-1822,-1807,-1796,-1785,-1773,-1759,-1749,-1752,-1770,-1798,-1823,-1834,-1824,
--1800,-1772,-1751,-1740,-1732,-1722,-1706,-1688,-1676,-1673,-1678,-1683,-1680,-1668,-1653,-1646,-1652,-1673,-1699,-1722,-1737,
--1743,-1745,-1746,-1746,-1742,-1728,-1703,-1674,-1648,-1633,-1628,-1626,-1617,-1591,-1550,-1502,-1463,-1445,-1454,-1485,-1527,
--1567,-1598,-1617,-1627,-1632,-1632,-1630,-1626,-1620,-1617,-1618,-1622,-1626,-1626,-1619,-1607,-1595,-1589,-1591,-1598,-1604,
--1602,-1590,-1572,-1553,-1539,-1530,-1522,-1511,-1492,-1464,-1429,-1391,-1353,-1318,-1288,-1266,-1249,-1236,-1220,-1196,-1164,
--1127,-1091,-1068,-1064,-1082,-1112,-1137,-1133,-1087,-1002,-904,-831,-813,-854,-928,-988,-993,-934,-837,-746,-699,
--703,-739,-778,-800,-805,-807,-819,-841,-863,-875,-874,-867,-864,-866,-866,-855,-832,-803,-779,-766,-763,
--764,-763,-760,-758,-762,-770,-777,-781,-780,-779,-782,-794,-814,-843,-880,-921,-959,-988,-1003,-1004,-998,
--992,-992,-996,-1001,-1001,-999,-1002,-1018,-1046,-1082,-1122,-1161,-1204,-1252,-1307,-1364,-1414,-1453,-1479,-1494,-1504,
--1512,-1522,-1536,-1559,-1593,-1635,-1677,-1711,-1730,-1736,-1735,-1732,-1731,-1731,-1729,-1724,-1720,-1718,-1720,-1723,-1723,
--1720,-1715,-1709,-1705,-1702,-1700,-1696,-1693,-1693,-1696,-1701,-1706,-1710,-1711,-1710,-1707,-1701,-1692,-1681,-1671,-1666,
--1664,-1667,-1669,-1671,-1670,-1668,-1666,-1664,-1660,-1655,-1651,-1649,-1651,-1655,-1660,-1662,-1664,-1664,-1665,-1667,-1667,
--1667,-1666,-1666,-1668,-1671,-1672,-1671,-1668,-1667,-1669,-1676,-1686,-1695,-1699,-1698,-1692,-1684,-1677,-1672,-1669,-1667,
--1664,-1659,-1649,-1636,-1619,-1603,-1589,-1578,-1570,-1562,-1554,-1547,-1539,-1531,-1523,-1514,-1504,-1494,-1487,-1483,-1483,
--1487,-1493,-1502,-1515,-1532,-1553,-1577,-1601,-1621,-1637,-1645,-1646,-1640,-1628,-1612,-1597,-1586,-1584,-1593,-1612,-1635,
--1657,-1670,-1675,-1675,-1674,-1677,-1681,-1686,-1687,-1687,-1687,-1692,-1704,-1720,-1735,-1746,-1751,-1749,-1743,-1735,-1725,
--1715,-1707,-1704,-1706,-1714,-1725,-1735,-1742,-1745,-1745,-1743,-1740,-1737,-1734,-1732,-1730,-1731,-1733,-1737,-1741,-1745,
--1748,-1747,-1744,-1737,-1728,-1719,-1712,-1705,-1698,-1690,-1681,-1674,-1667,-1661,-1654,-1643,-1627,-1609,-1590,-1573,-1557,
--1541,-1525,-1509,-1492,-1476,-1460,-1444,-1427,-1408,-1390,-1372,-1355,-1340,-1325,-1310,-1295,-1280,-1264,-1248,-1230,-1212,
--1195,-1179,-1165,-1153,-1141,-1127,-1113,-1100,-1087,-1077,-1068,-1061,-1054,-1048,-1041,-1035,-1029,-1024,-1020,-1017,-1014,
--1012,-1010,-1008,-1007,-1005,-1002,-998,-991,-983,-977,-974,-974,-976,-978,-978,-975,-969,-964,-959,-955,-952,
--949,-946,-944,-944,-947,-951,-956,-959,-962,-965,-968,-973,-979,-985,-991,-996,-1001,-1006,-1011,-1015,-1018,
--1020,-1020,-1019,-1017,-1016,-1016,-1017,-1018,-1020,-1022,-1022,-1022,-1022,-1021,-1021,-1021,-1017,-1010,-999,-985,-971,
--961,-953,-949,-945,-940,-933,-926,-919,-912,-903,-891,-876,-861,-846,-833,-820,-804,-786,-766,-747,-731,
--718,-706,-694,-681,-669,-662,-662,-665,-669,-669,-664,-657,-649,-642,-635,-627,-616,-604,-591,-578,-564,
--548,-529,-508,-486,-464,-442,-418,-390,-362,-335,-315,-299,-287,-273,-256,-236,-215,-196,-179,-165,-153,
--142,-130,-116,-98,-76,-51,-28,-7,9,26,47,70,95,116,132,147,163,183,206,229,249,
-267,288,313,341,367,387,405,425,452,483,510,530,542,555,571,589,597,586,559,529,514,
-519,542,573,615,686,806,977,1169,1328,1413,1422,1402,1416,1504,1652,1798,1874,1847,1742,1621,1540,
-1518,1533,1546,1526,1474,1410,1354,1312,1277,1239,1199,1164,1144,1140,1145,1150,1150,1146,1141,1136,1128,
-1114,1095,1079,1070,1073,1081,1088,1090,1089,1091,1100,1115,1131,1143,1152,1160,1169,1178,1185,1186,1182,
-1177,1173,1171,1168,1161,1150,1137,1124,1112,1099,1084,1066,1048,1034,1023,1013,999,977,949,917,883,
-850,815,778,739,699,661,625,588,545,492,428,358,285,216,153,99,55,21,-2,-18,-26,
--29,-27,-23,-18,-15,-17,-21,-28,-34,-38,-40,-41,-43,-45,-46,-45,-42,-40,-37,-35,-29,
--19,-3,16,37,56,73,91,111,135,162,188,211,230,245,255,261,261,256,245,229,213,
-197,182,170,159,150,140,131,122,118,123,137,161,190,218,242,259,273,286,302,323,347,
-373,398,418,432,441,446,452,463,483,510,540,569,594,615,632,650,670,694,720,745,765,
-778,784,793,814,859,929,1014,1097,1162,1202,1223,1239,1261,1293,1330,1362,1386,1403,1422,1448,1481,
-1516,1547,1575,1603,1635,1674,1716,1755,1789,1819,1846,1874,1904,1931,1954,1972,1987,2002,2018,2035,2051,
-2067,2084,2103,2126,2152,2178,2203,2226,2249,2272,2295,2318,2339,2358,2376,2392,2408,2427,2448,2472,2500,
-2528,2554,2576,2593,2608,2622,2637,2652,2665,2674,2677,2679,2684,2694,2708,2720,2726,2723,2716,2711,2712,
-2717,2718,2711,2694,2675,2663,2663,2670,2677,2673,2657,2635,2613,2599,2591,2585,2577,2565,2553,2544,2539,
-2535,2531,2524,2517,2509,2502,2493,2482,2468,2455,2445,2438,2432,2425,2417,2409,2403,2436,2429,2421,2412,
-2404,2400,2402,2410,2421,2433,2442,2446,2446,2441,2434,2427,2424,2429,2441,2455,2461,2456,2441,2426,2424,
-2445,2488,2540,2583,2602,2589,2549,2494,2441,2403,2385,2388,2406,2433,2464,2498,2533,2567,2596,2612,2615,
-2609,2606,2615,2642,2682,2726,2762,2787,2803,2817,2836,2859,2883,2904,2921,2937,2956,2979,3004,3026,3044,
-3059,3072,3088,3108,3130,3152,3174,3195,3215,3235,3252,3265,3275,3285,3297,3312,3328,3343,3355,3366,3376,
-3384,3390,3394,3397,3406,3423,3448,3472,3486,3487,3476,3466,3466,3481,3504,3524,3536,3542,3551,3570,3598,
-3628,3652,3672,3695,3731,3779,3827,3855,3852,3823,3788,3774,3797,3857,3936,4012,4067,4094,4098,4088,4075,
-4066,4066,4074,4086,4097,4105,4110,4117,4129,4147,4168,4186,4202,4217,4235,4257,4277,4286,4280,4260,4238,
-4228,4237,4262,4297,4331,4359,4383,4403,4421,4437,4449,4458,4465,4472,4476,4477,4474,4469,4466,4466,4467,
-4464,4454,4435,4415,4398,4390,4391,4399,4411,4426,4447,4470,4492,4508,4517,4519,4520,4523,4529,4536,4540,
-4538,4533,4524,4515,4504,4491,4480,4471,4467,4467,4467,4464,4457,4447,4439,4435,4434,4430,4422,4407,4389,
-4372,4357,4343,4329,4313,4296,4281,4269,4256,4240,4220,4195,4167,4140,4115,4093,4074,4056,4039,4021,4000,
-3974,3943,3909,3874,3841,3812,3788,3771,3763,3765,3772,3778,3776,3762,3742,3722,3715,3726,3752,3787,3820,
-3845,3861,3870,3876,3880,3879,3867,3844,3812,3782,3767,3779,3820,3886,3962,4033,4086,4116,4125,4118,4104,
-4089,4075,4061,4041,4007,3955,3885,3808,3734,3676,3636,3607,3579,3545,3503,3460,3422,3392,3368,3345,3319,
-3292,3266,3244,3226,3208,3186,3160,3130,3100,3071,3044,3018,2993,2969,2947,2924,2898,2867,2831,2795,2761,
-2730,2698,2662,2620,2576,2533,2495,2461,2429,2395,2359,2323,2290,2261,2232,2201,2166,2128,2092,2057,2025,
-1991,1954,1915,1878,1843,1811,1779,1744,1704,1661,1620,1580,1543,1504,1465,1424,1386,1350,1317,1283,1245,
-1204,1164,1128,1098,1070,1040,1007,969,929,891,856,822,788,752,715,677,639,601,563,525,488,
-452,417,381,342,303,263,225,186,146,104,61,18,-22,-59,-95,-132,-171,-212,-254,-294,-332,
--368,-403,-438,-472,-507,-541,-575,-610,-646,-682,-719,-755,-790,-824,-858,-891,-926,-963,-1001,-1039,-1074,
--1106,-1136,-1164,-1194,-1226,-1258,-1290,-1321,-1352,-1383,-1415,-1447,-1477,-1506,-1533,-1562,-1592,-1623,-1653,-1679,-1703,
--1726,-1752,-1780,-1807,-1832,-1853,-1872,-1891,-1911,-1932,-1953,-1973,-1994,-2016,-2038,-2058,-2073,-2084,-2095,-2110,-2130,
--2152,-2169,-2179,-2183,-2187,-2195,-2210,-2228,-2242,-2249,-2253,-2258,-2268,-2284,-2302,-2316,-2324,-2330,-2337,-2346,-2356,
--2363,-2366,-2367,-2371,-2378,-2388,-2398,-2402,-2399,-2392,-2385,-2382,-2383,-2387,-2391,-2394,-2392,-2388,-2381,-2373,-2365,
--2358,-2350,-2342,-2333,-2323,-2314,-2307,-2301,-2295,-2288,-2277,-2264,-2250,-2238,-2226,-2214,-2200,-2184,-2169,-2157,-2147,
--2137,-2127,-2114,-2099,-2084,-2070,-2057,-2043,-2028,-2013,-1998,-1984,-1972,-1959,-1945,-1930,-1916,-1902,-1888,-1872,-1854,
--1836,-1821,-1808,-1796,-1783,-1769,-1760,-1762,-1778,-1804,-1828,-1841,-1834,-1813,-1786,-1764,-1750,-1741,-1731,-1716,-1700,
--1688,-1685,-1690,-1696,-1696,-1687,-1675,-1667,-1670,-1685,-1707,-1729,-1745,-1755,-1762,-1768,-1771,-1767,-1754,-1731,-1704,
--1680,-1666,-1660,-1657,-1650,-1632,-1605,-1575,-1550,-1537,-1538,-1550,-1569,-1590,-1610,-1626,-1638,-1644,-1644,-1641,-1637,
--1635,-1639,-1646,-1653,-1657,-1655,-1645,-1631,-1619,-1612,-1613,-1618,-1621,-1619,-1610,-1596,-1582,-1570,-1561,-1551,-1537,
--1516,-1488,-1455,-1421,-1389,-1360,-1337,-1318,-1300,-1281,-1257,-1226,-1192,-1159,-1137,-1131,-1140,-1158,-1168,-1153,-1104,
--1025,-938,-872,-857,-899,-977,-1052,-1080,-1042,-949,-842,-764,-739,-763,-807,-842,-855,-854,-855,-869,-896,
--921,-936,-936,-930,-926,-927,-925,-915,-894,-866,-840,-825,-820,-823,-828,-834,-839,-845,-852,-859,-866,
--873,-882,-893,-906,-922,-945,-976,-1014,-1053,-1083,-1096,-1092,-1081,-1073,-1076,-1088,-1103,-1118,-1132,-1151,-1181,
--1220,-1264,-1306,-1342,-1375,-1408,-1446,-1485,-1520,-1543,-1552,-1546,-1531,-1514,-1503,-1508,-1536,-1588,-1654,-1721,-1774,
--1806,-1818,-1820,-1818,-1817,-1814,-1807,-1797,-1787,-1783,-1784,-1787,-1788,-1784,-1778,-1772,-1768,-1766,-1764,-1760,-1757,
--1756,-1759,-1765,-1770,-1773,-1772,-1768,-1765,-1761,-1755,-1747,-1738,-1730,-1726,-1726,-1726,-1725,-1723,-1721,-1719,-1719,
--1719,-1719,-1717,-1716,-1717,-1719,-1721,-1721,-1718,-1715,-1712,-1711,-1713,-1716,-1720,-1723,-1726,-1728,-1726,-1720,-1712,
--1704,-1701,-1705,-1714,-1726,-1735,-1739,-1736,-1730,-1723,-1719,-1716,-1715,-1714,-1710,-1703,-1693,-1681,-1668,-1656,-1643,
--1631,-1618,-1605,-1593,-1583,-1575,-1567,-1559,-1550,-1540,-1532,-1527,-1526,-1528,-1531,-1534,-1537,-1542,-1553,-1569,-1590,
--1611,-1630,-1645,-1655,-1662,-1665,-1664,-1658,-1648,-1637,-1630,-1630,-1639,-1652,-1664,-1674,-1682,-1691,-1703,-1714,-1724,
--1726,-1723,-1717,-1713,-1715,-1723,-1736,-1748,-1759,-1767,-1771,-1769,-1761,-1748,-1732,-1718,-1712,-1714,-1722,-1734,-1745,
--1752,-1755,-1754,-1750,-1747,-1743,-1741,-1742,-1743,-1745,-1747,-1750,-1754,-1758,-1760,-1759,-1754,-1745,-1734,-1725,-1718,
--1711,-1704,-1695,-1685,-1675,-1667,-1660,-1651,-1640,-1625,-1609,-1592,-1575,-1559,-1542,-1524,-1506,-1489,-1473,-1458,-1441,
--1423,-1403,-1383,-1364,-1348,-1333,-1320,-1308,-1295,-1283,-1269,-1253,-1236,-1218,-1200,-1184,-1169,-1155,-1142,-1127,-1113,
--1098,-1084,-1072,-1062,-1053,-1045,-1037,-1030,-1023,-1016,-1009,-1003,-998,-994,-990,-988,-987,-987,-986,-984,-979,
--973,-967,-963,-964,-968,-973,-977,-978,-977,-974,-972,-969,-967,-963,-959,-955,-954,-957,-961,-967,-971,
--973,-974,-976,-981,-989,-999,-1008,-1015,-1019,-1023,-1026,-1031,-1036,-1040,-1044,-1044,-1041,-1036,-1030,-1025,-1023,
--1023,-1024,-1025,-1024,-1022,-1020,-1020,-1019,-1017,-1012,-1004,-992,-980,-971,-963,-957,-951,-944,-936,-928,-920,
--913,-903,-892,-878,-865,-853,-843,-832,-819,-803,-785,-768,-753,-739,-725,-710,-694,-682,-675,-674,-676,
--676,-674,-668,-660,-655,-651,-646,-639,-629,-617,-604,-591,-578,-564,-546,-527,-508,-490,-470,-448,-421,
--393,-365,-341,-322,-307,-292,-276,-257,-237,-219,-201,-186,-173,-161,-147,-130,-107,-81,-56,-34,-17,
--4,9,28,51,74,95,113,130,149,172,196,219,238,258,282,309,337,360,377,393,415,
-444,476,501,517,525,536,554,577,589,581,553,522,506,513,537,570,612,682,799,966,1153,
-1307,1387,1394,1374,1394,1493,1653,1810,1890,1859,1740,1599,1497,1460,1468,1481,1468,1427,1372,1323,1283,
-1245,1201,1153,1113,1091,1091,1104,1116,1119,1116,1111,1108,1104,1095,1082,1067,1060,1062,1072,1082,1089,
-1093,1099,1112,1132,1153,1172,1186,1198,1210,1221,1230,1233,1230,1223,1217,1213,1210,1205,1196,1185,1172,
-1159,1144,1127,1108,1090,1075,1064,1052,1038,1018,992,963,932,901,866,827,786,745,708,677,647,
-613,569,514,451,384,317,254,197,148,110,83,69,65,69,75,80,83,81,74,64,54,
-46,43,42,43,44,44,45,47,49,48,43,36,29,29,39,59,84,110,134,157,182,
-210,242,276,310,339,361,375,381,380,373,362,349,331,309,282,250,217,187,162,144,134,
-131,135,145,162,183,208,235,262,288,313,337,357,377,396,417,439,463,484,502,516,529,
-543,560,582,608,635,664,694,724,756,789,822,853,875,887,887,884,890,917,970,1043,1120,
-1186,1231,1258,1277,1300,1331,1368,1402,1428,1449,1470,1496,1527,1560,1591,1618,1644,1673,1707,1744,1780,
-1811,1838,1863,1889,1917,1945,1970,1989,2004,2015,2024,2032,2043,2055,2072,2093,2116,2139,2161,2183,2203,
-2225,2248,2272,2296,2319,2341,2361,2380,2399,2419,2441,2467,2496,2525,2551,2571,2585,2596,2607,2620,2635,
-2647,2653,2655,2656,2659,2669,2681,2692,2697,2696,2693,2693,2699,2707,2712,2708,2697,2686,2683,2688,2698,
-2703,2696,2679,2657,2638,2626,2620,2613,2604,2593,2583,2577,2574,2572,2567,2559,2549,2540,2532,2523,2512,
-2500,2488,2477,2469,2462,2456,2449,2442,2436,2469,2462,2455,2448,2445,2446,2452,2459,2464,2464,2459,2452,
-2445,2438,2432,2428,2430,2438,2452,2463,2463,2451,2434,2426,2441,2480,2531,2572,2583,2558,2507,2452,2414,
-2399,2405,2418,2430,2437,2447,2466,2499,2541,2583,2613,2626,2622,2613,2609,2620,2645,2679,2714,2743,2765,
-2783,2804,2831,2860,2889,2914,2936,2957,2981,3008,3035,3059,3078,3093,3107,3124,3143,3161,3177,3191,3205,
-3222,3241,3261,3279,3293,3303,3312,3325,3342,3361,3380,3393,3401,3403,3403,3405,3414,3431,3454,3478,3495,
-3501,3496,3487,3482,3487,3501,3518,3535,3550,3566,3587,3613,3638,3655,3667,3680,3705,3747,3796,3832,3839,
-3813,3772,3743,3750,3802,3884,3969,4034,4066,4068,4052,4033,4021,4018,4025,4038,4052,4063,4069,4071,4074,
-4082,4097,4117,4139,4161,4184,4211,4238,4262,4276,4277,4269,4261,4264,4280,4307,4339,4368,4394,4416,4436,
-4452,4463,4470,4474,4479,4485,4490,4491,4488,4481,4476,4475,4475,4471,4461,4445,4429,4419,4418,4424,4432,
-4442,4453,4468,4487,4507,4522,4529,4529,4526,4526,4530,4535,4538,4536,4528,4518,4507,4495,4483,4472,4464,
-4461,4461,4461,4457,4450,4441,4435,4433,4432,4429,4419,4403,4385,4367,4353,4340,4326,4312,4298,4285,4273,
-4259,4241,4216,4187,4157,4129,4105,4085,4068,4050,4032,4012,3988,3960,3929,3897,3866,3837,3810,3786,3767,
-3755,3753,3756,3757,3748,3724,3692,3663,3654,3674,3722,3789,3860,3923,3969,4000,4015,4017,4003,3972,3924,
-3863,3803,3756,3736,3751,3796,3863,3936,4002,4052,4084,4098,4101,4095,4083,4065,4035,3992,3932,3861,3789,
-3725,3680,3653,3638,3625,3607,3581,3550,3516,3481,3444,3403,3359,3317,3282,3256,3236,3219,3199,3174,3147,
-3118,3089,3058,3028,2999,2975,2956,2938,2918,2889,2852,2812,2774,2741,2712,2680,2642,2599,2554,2512,2476,
-2443,2409,2373,2335,2301,2270,2242,2214,2182,2147,2111,2075,2040,2005,1968,1930,1892,1855,1821,1786,1750,
-1712,1673,1635,1598,1562,1523,1481,1437,1396,1359,1325,1292,1256,1219,1181,1146,1115,1086,1056,1022,984,
-945,908,873,839,806,771,734,696,658,619,580,543,508,474,438,400,358,316,274,235,199,
-162,123,83,42,3,-33,-70,-109,-150,-194,-237,-277,-313,-349,-384,-420,-456,-490,-522,-554,-586,
--621,-656,-693,-729,-764,-799,-834,-871,-908,-944,-979,-1012,-1042,-1071,-1100,-1132,-1167,-1203,-1239,-1271,-1302,
--1330,-1359,-1388,-1418,-1447,-1474,-1499,-1526,-1555,-1585,-1615,-1643,-1669,-1694,-1720,-1748,-1774,-1799,-1821,-1841,-1862,
--1884,-1906,-1926,-1946,-1965,-1986,-2009,-2030,-2050,-2065,-2080,-2096,-2114,-2132,-2146,-2154,-2158,-2163,-2173,-2189,-2205,
--2216,-2220,-2222,-2227,-2241,-2262,-2284,-2301,-2309,-2313,-2316,-2323,-2333,-2342,-2349,-2353,-2357,-2364,-2375,-2384,-2390,
--2388,-2382,-2375,-2371,-2372,-2377,-2383,-2386,-2386,-2382,-2376,-2368,-2360,-2351,-2342,-2333,-2324,-2315,-2308,-2303,-2298,
--2292,-2283,-2272,-2259,-2248,-2238,-2230,-2220,-2209,-2195,-2182,-2169,-2159,-2148,-2136,-2121,-2104,-2088,-2073,-2059,-2045,
--2030,-2015,-2001,-1989,-1978,-1968,-1956,-1942,-1927,-1913,-1898,-1882,-1865,-1848,-1832,-1817,-1804,-1791,-1780,-1775,-1779,
--1794,-1818,-1839,-1850,-1843,-1823,-1797,-1775,-1761,-1752,-1743,-1730,-1715,-1703,-1700,-1704,-1710,-1712,-1704,-1693,-1684,
--1685,-1698,-1719,-1741,-1759,-1771,-1779,-1785,-1789,-1788,-1778,-1760,-1738,-1716,-1699,-1688,-1680,-1673,-1665,-1655,-1647,
--1641,-1636,-1633,-1631,-1631,-1634,-1641,-1649,-1656,-1658,-1657,-1654,-1654,-1659,-1667,-1678,-1685,-1686,-1681,-1672,-1661,
--1652,-1646,-1643,-1642,-1642,-1639,-1632,-1622,-1609,-1596,-1582,-1568,-1550,-1527,-1500,-1471,-1443,-1416,-1393,-1372,-1351,
--1328,-1303,-1277,-1251,-1230,-1216,-1209,-1207,-1205,-1194,-1165,-1114,-1045,-974,-924,-915,-956,-1033,-1113,-1160,-1144,
--1066,-954,-849,-787,-780,-813,-858,-890,-902,-903,-908,-926,-951,-974,-985,-983,-976,-971,-969,-967,-959,
--943,-923,-906,-898,-899,-906,-915,-923,-930,-936,-943,-952,-965,-983,-1003,-1022,-1038,-1052,-1069,-1093,-1125,
--1158,-1182,-1191,-1188,-1181,-1181,-1195,-1220,-1248,-1275,-1301,-1331,-1369,-1414,-1458,-1493,-1518,-1535,-1552,-1572,-1595,
--1615,-1624,-1617,-1593,-1555,-1515,-1487,-1486,-1520,-1589,-1676,-1763,-1830,-1870,-1886,-1892,-1894,-1897,-1896,-1887,-1872,
--1857,-1847,-1845,-1846,-1846,-1842,-1835,-1828,-1824,-1823,-1822,-1819,-1816,-1816,-1820,-1827,-1832,-1834,-1830,-1825,-1822,
--1820,-1818,-1813,-1805,-1797,-1791,-1788,-1788,-1787,-1784,-1780,-1777,-1776,-1776,-1777,-1777,-1777,-1778,-1781,-1784,-1784,
--1779,-1770,-1761,-1755,-1753,-1756,-1764,-1772,-1780,-1786,-1787,-1782,-1772,-1760,-1750,-1745,-1748,-1757,-1769,-1779,-1784,
--1784,-1781,-1776,-1770,-1766,-1762,-1759,-1755,-1751,-1746,-1738,-1726,-1711,-1694,-1675,-1657,-1641,-1629,-1620,-1614,-1607,
--1600,-1592,-1585,-1580,-1579,-1580,-1581,-1580,-1577,-1572,-1571,-1575,-1584,-1597,-1611,-1626,-1642,-1659,-1678,-1693,-1700,
--1696,-1683,-1667,-1653,-1647,-1647,-1651,-1658,-1666,-1679,-1695,-1715,-1734,-1746,-1751,-1750,-1747,-1744,-1745,-1748,-1753,
--1761,-1771,-1779,-1785,-1783,-1772,-1755,-1736,-1720,-1712,-1712,-1719,-1729,-1738,-1745,-1749,-1749,-1749,-1749,-1752,-1757,
--1762,-1766,-1767,-1767,-1767,-1768,-1770,-1771,-1769,-1762,-1753,-1745,-1738,-1732,-1724,-1713,-1700,-1686,-1675,-1667,-1660,
--1651,-1638,-1623,-1606,-1589,-1572,-1554,-1535,-1516,-1497,-1481,-1465,-1449,-1432,-1412,-1390,-1370,-1351,-1335,-1321,-1308,
--1295,-1284,-1272,-1261,-1248,-1233,-1217,-1201,-1186,-1172,-1161,-1149,-1136,-1122,-1107,-1091,-1077,-1065,-1055,-1047,-1039,
--1031,-1023,-1015,-1007,-999,-992,-987,-984,-982,-980,-979,-977,-972,-966,-960,-956,-956,-960,-966,-973,-978,
--981,-984,-986,-987,-986,-983,-979,-975,-974,-978,-985,-992,-998,-1000,-1001,-1003,-1007,-1015,-1024,-1032,-1037,
--1040,-1041,-1042,-1045,-1051,-1057,-1062,-1064,-1063,-1058,-1051,-1045,-1041,-1039,-1038,-1036,-1033,-1028,-1024,-1021,-1021,
--1021,-1021,-1017,-1010,-1001,-991,-982,-973,-964,-953,-943,-934,-927,-920,-913,-904,-894,-883,-871,-860,-848,
--834,-819,-805,-792,-780,-767,-752,-734,-716,-701,-693,-689,-688,-685,-680,-672,-666,-662,-660,-657,-651,
--640,-627,-615,-603,-591,-577,-562,-546,-531,-515,-499,-479,-454,-426,-397,-371,-349,-330,-313,-296,-278,
--260,-242,-225,-210,-196,-182,-166,-145,-119,-91,-66,-46,-32,-21,-7,10,33,56,75,93,111,
-134,160,187,209,229,249,273,301,330,354,372,389,412,443,474,497,507,512,520,540,566,
-584,580,555,524,506,510,533,568,615,691,812,979,1159,1302,1372,1372,1350,1370,1469,1626,1776,
-1847,1807,1682,1538,1436,1401,1412,1429,1422,1386,1336,1290,1254,1218,1174,1125,1083,1060,1059,1070,1079,
-1081,1076,1072,1072,1075,1074,1066,1055,1049,1053,1067,1083,1096,1105,1115,1130,1153,1181,1207,1229,1246,
-1261,1272,1278,1278,1272,1263,1254,1248,1245,1241,1234,1224,1211,1197,1183,1167,1148,1129,1111,1096,1082,
-1068,1051,1030,1006,980,949,914,874,832,791,756,725,695,660,616,564,507,450,395,345,300,
-261,231,211,201,199,201,203,201,195,185,172,160,150,146,146,150,154,157,157,157,156,
-154,150,141,129,117,112,117,135,161,191,221,249,278,310,347,389,430,466,494,511,518,
-518,512,503,489,467,434,390,336,282,237,205,190,187,192,200,209,219,232,250,274,304,
-338,371,400,423,440,453,468,489,517,550,583,611,632,646,659,674,694,722,755,793,830,
-867,902,937,970,997,1014,1019,1014,1010,1018,1046,1092,1148,1201,1244,1274,1299,1326,1359,1394,1426,
-1452,1474,1494,1519,1548,1580,1611,1638,1663,1688,1716,1746,1775,1803,1830,1856,1883,1911,1939,1965,1986,
-2002,2013,2021,2028,2037,2049,2066,2087,2109,2130,2150,2170,2190,2211,2233,2255,2276,2296,2318,2341,2365,
-2390,2415,2440,2465,2491,2516,2540,2558,2573,2585,2595,2607,2618,2627,2632,2635,2639,2646,2656,2668,2678,
-2682,2684,2687,2693,2703,2713,2718,2716,2710,2707,2709,2716,2722,2721,2710,2693,2676,2663,2656,2651,2645,
-2636,2627,2620,2616,2614,2611,2603,2592,2581,2571,2563,2557,2549,2538,2526,2514,2504,2495,2487,2481,2475,
-2469,2502,2494,2485,2479,2479,2484,2491,2495,2491,2479,2464,2452,2446,2446,2448,2451,2456,2464,2475,2483,
-2480,2465,2445,2436,2447,2478,2513,2529,2511,2464,2406,2365,2358,2382,2421,2452,2465,2464,2462,2476,2510,
-2556,2602,2635,2649,2648,2639,2633,2633,2641,2656,2676,2699,2727,2760,2796,2834,2872,2908,2940,2969,2996,
-3023,3049,3072,3093,3111,3128,3146,3164,3180,3192,3200,3206,3215,3231,3253,3278,3300,3314,3322,3328,3338,
-3354,3375,3395,3408,3414,3414,3415,3421,3436,3459,3482,3500,3508,3506,3501,3498,3501,3511,3524,3536,3549,
-3566,3591,3622,3652,3672,3680,3681,3689,3713,3753,3793,3813,3801,3766,3730,3723,3760,3835,3925,4001,4046,
-4057,4046,4028,4012,4002,4000,4004,4016,4032,4047,4058,4061,4059,4057,4061,4073,4094,4120,4149,4181,4213,
-4241,4263,4276,4284,4291,4303,4322,4348,4376,4405,4432,4457,4477,4491,4497,4496,4494,4494,4498,4503,4506,
-4503,4497,4492,4490,4489,4485,4476,4465,4455,4452,4458,4468,4478,4485,4490,4498,4509,4521,4531,4533,4530,
-4525,4522,4521,4521,4518,4512,4504,4495,4487,4479,4471,4462,4454,4449,4447,4447,4446,4443,4439,4436,4434,
-4431,4424,4412,4397,4381,4367,4355,4343,4329,4313,4297,4282,4268,4252,4231,4205,4175,4145,4119,4096,4078,
-4062,4046,4029,4009,3984,3956,3925,3896,3869,3845,3822,3798,3775,3757,3747,3743,3740,3728,3701,3664,3629,
-3612,3625,3671,3742,3824,3901,3965,4009,4035,4041,4027,3993,3939,3872,3802,3742,3702,3691,3709,3752,3811,
-3876,3940,3995,4037,4063,4072,4063,4036,3992,3933,3865,3796,3736,3693,3670,3663,3664,3665,3661,3650,3634,
-3612,3584,3546,3497,3440,3384,3335,3297,3267,3243,3219,3194,3169,3143,3113,3080,3042,3005,2974,2954,2942,
-2929,2907,2874,2832,2790,2753,2721,2691,2657,2617,2574,2533,2496,2463,2430,2395,2357,2319,2285,2255,2226,
-2195,2161,2124,2087,2051,2016,1980,1943,1905,1868,1831,1794,1758,1721,1685,1649,1614,1578,1539,1498,1456,
-1414,1375,1339,1304,1270,1235,1202,1170,1140,1109,1077,1041,1003,965,928,893,858,824,788,752,715,
-678,640,602,565,529,493,457,417,373,328,285,245,209,173,137,99,60,21,-16,-55,-96,
--137,-179,-218,-254,-289,-325,-361,-400,-437,-472,-504,-535,-567,-600,-634,-668,-702,-736,-772,-811,-850,
--889,-926,-958,-987,-1013,-1039,-1068,-1100,-1136,-1174,-1211,-1246,-1277,-1305,-1332,-1359,-1387,-1414,-1441,-1468,-1496,
--1524,-1554,-1583,-1611,-1638,-1664,-1690,-1716,-1741,-1764,-1786,-1809,-1832,-1856,-1880,-1902,-1922,-1941,-1962,-1984,-2008,
--2030,-2048,-2063,-2077,-2091,-2106,-2118,-2128,-2136,-2146,-2158,-2173,-2187,-2195,-2198,-2200,-2207,-2222,-2243,-2266,-2284,
--2293,-2297,-2299,-2304,-2312,-2322,-2331,-2337,-2344,-2352,-2362,-2371,-2377,-2377,-2372,-2366,-2362,-2361,-2363,-2366,-2369,
--2370,-2369,-2366,-2361,-2354,-2346,-2337,-2328,-2318,-2309,-2302,-2295,-2289,-2282,-2273,-2262,-2250,-2240,-2233,-2227,-2220,
--2211,-2200,-2187,-2174,-2161,-2148,-2133,-2116,-2099,-2083,-2071,-2060,-2048,-2035,-2020,-2005,-1992,-1980,-1969,-1957,-1943,
--1928,-1914,-1902,-1889,-1876,-1862,-1846,-1830,-1816,-1804,-1795,-1792,-1798,-1813,-1833,-1852,-1859,-1852,-1832,-1807,-1787,
--1774,-1766,-1758,-1746,-1730,-1718,-1714,-1717,-1722,-1723,-1714,-1701,-1690,-1692,-1707,-1731,-1757,-1777,-1788,-1793,-1796,
--1798,-1799,-1795,-1785,-1768,-1747,-1726,-1708,-1694,-1686,-1685,-1689,-1698,-1706,-1710,-1707,-1699,-1690,-1684,-1682,-1683,
--1682,-1679,-1674,-1673,-1676,-1686,-1697,-1705,-1707,-1704,-1699,-1694,-1690,-1686,-1682,-1676,-1671,-1667,-1664,-1660,-1651,
--1637,-1618,-1598,-1579,-1559,-1538,-1515,-1490,-1465,-1441,-1420,-1400,-1377,-1352,-1327,-1306,-1292,-1286,-1284,-1277,-1257,
--1219,-1163,-1096,-1028,-973,-946,-956,-1007,-1086,-1172,-1231,-1239,-1187,-1088,-974,-881,-834,-836,-869,-909,-939,
--953,-961,-971,-988,-1007,-1020,-1024,-1020,-1012,-1007,-1004,-1001,-994,-986,-978,-975,-978,-987,-996,-1005,-1010,
--1014,-1020,-1030,-1046,-1070,-1099,-1129,-1156,-1176,-1192,-1210,-1233,-1262,-1291,-1311,-1320,-1321,-1324,-1338,-1364,-1398,
--1432,-1462,-1490,-1520,-1557,-1597,-1633,-1658,-1671,-1675,-1677,-1684,-1694,-1704,-1704,-1689,-1657,-1612,-1564,-1530,-1526,
--1563,-1637,-1732,-1823,-1891,-1931,-1948,-1955,-1963,-1972,-1976,-1970,-1953,-1933,-1918,-1909,-1905,-1901,-1893,-1883,-1875,
--1872,-1871,-1871,-1870,-1869,-1871,-1877,-1886,-1892,-1894,-1890,-1885,-1881,-1880,-1879,-1875,-1866,-1858,-1852,-1851,-1853,
--1855,-1852,-1846,-1840,-1835,-1833,-1834,-1834,-1835,-1837,-1841,-1844,-1844,-1839,-1829,-1816,-1804,-1798,-1798,-1803,-1812,
--1822,-1833,-1841,-1845,-1843,-1834,-1822,-1811,-1804,-1804,-1810,-1818,-1827,-1832,-1834,-1832,-1827,-1822,-1817,-1814,-1812,
--1810,-1806,-1798,-1786,-1770,-1751,-1732,-1714,-1698,-1684,-1674,-1666,-1659,-1653,-1646,-1639,-1635,-1633,-1632,-1632,-1629,
--1623,-1614,-1605,-1600,-1599,-1601,-1606,-1613,-1624,-1640,-1661,-1681,-1698,-1705,-1703,-1695,-1684,-1675,-1667,-1659,-1653,
--1649,-1652,-1663,-1682,-1705,-1730,-1750,-1766,-1777,-1783,-1785,-1784,-1780,-1777,-1776,-1779,-1782,-1782,-1776,-1762,-1743,
--1723,-1709,-1702,-1704,-1712,-1725,-1737,-1746,-1750,-1752,-1753,-1758,-1766,-1776,-1784,-1788,-1787,-1784,-1783,-1783,-1783,
--1782,-1777,-1769,-1763,-1757,-1753,-1747,-1737,-1724,-1710,-1698,-1689,-1680,-1669,-1655,-1637,-1618,-1600,-1582,-1564,-1544,
--1523,-1502,-1484,-1467,-1451,-1434,-1415,-1395,-1375,-1356,-1339,-1323,-1307,-1291,-1277,-1265,-1254,-1244,-1233,-1220,-1206,
--1193,-1182,-1172,-1164,-1155,-1143,-1128,-1112,-1097,-1083,-1072,-1063,-1056,-1049,-1041,-1033,-1024,-1015,-1007,-1000,-995,
--990,-987,-983,-979,-974,-968,-963,-959,-959,-961,-966,-972,-979,-985,-992,-998,-1002,-1004,-1002,-999,-997,
--999,-1005,-1015,-1025,-1033,-1038,-1040,-1043,-1046,-1051,-1056,-1060,-1062,-1062,-1062,-1062,-1063,-1065,-1068,-1072,-1074,
--1075,-1074,-1071,-1067,-1064,-1061,-1059,-1055,-1050,-1044,-1038,-1034,-1034,-1036,-1037,-1036,-1031,-1023,-1013,-1003,-992,
--981,-968,-956,-945,-936,-930,-925,-920,-914,-905,-892,-876,-858,-840,-824,-813,-804,-797,-786,-771,-752,
--733,-718,-709,-703,-699,-694,-686,-680,-675,-673,-671,-667,-659,-648,-636,-626,-616,-606,-595,-581,-566,
--552,-538,-522,-504,-480,-454,-427,-401,-378,-357,-337,-318,-300,-282,-265,-249,-234,-220,-204,-186,-163,
--135,-107,-82,-64,-51,-40,-25,-4,18,39,56,72,90,114,142,171,194,213,233,258,288,
-319,345,365,383,406,434,463,484,494,499,508,529,555,572,570,548,519,501,503,524,560,
-615,701,832,1000,1174,1304,1360,1349,1322,1339,1433,1581,1719,1779,1734,1610,1473,1380,1352,1368,1387,
-1378,1339,1287,1242,1209,1180,1145,1104,1066,1043,1039,1045,1050,1049,1043,1039,1042,1048,1050,1047,1041,
-1041,1053,1076,1102,1122,1134,1143,1156,1178,1207,1238,1264,1284,1296,1302,1302,1297,1289,1280,1274,1271,
-1271,1268,1261,1250,1238,1226,1215,1204,1190,1172,1153,1135,1119,1104,1088,1071,1050,1024,994,958,919,
-880,843,811,781,750,712,667,617,566,518,475,438,405,378,357,343,336,331,325,315,301,
-284,265,247,232,223,220,222,229,235,238,237,234,229,226,224,223,221,222,227,239,260,
-287,318,351,383,416,452,491,532,570,602,625,637,640,637,631,620,602,571,526,467,402,
-341,297,273,270,280,295,308,318,326,335,348,368,395,427,462,495,522,541,551,557,566,
-583,610,643,676,703,723,737,751,771,798,833,870,906,939,970,1001,1034,1066,1093,1109,1114,
-1111,1109,1117,1137,1169,1206,1243,1278,1313,1349,1387,1424,1455,1478,1497,1513,1532,1556,1582,1609,1636,
-1660,1685,1709,1735,1761,1786,1812,1839,1866,1894,1921,1946,1969,1988,2004,2018,2030,2042,2056,2072,2091,
-2109,2126,2143,2161,2181,2202,2223,2242,2259,2276,2295,2320,2349,2381,2411,2439,2463,2486,2507,2527,2546,
-2563,2578,2591,2601,2609,2615,2621,2628,2638,2650,2663,2674,2680,2682,2684,2690,2699,2710,2719,2722,2721,
-2720,2721,2727,2732,2734,2729,2718,2705,2696,2691,2689,2685,2677,2667,2658,2652,2649,2646,2640,2631,2619,
-2609,2602,2597,2591,2584,2575,2563,2551,2539,2529,2520,2514,2508,2502,2537,2524,2510,2499,2497,2502,2512,
-2517,2514,2501,2486,2478,2479,2487,2495,2498,2497,2497,2499,2502,2498,2484,2463,2446,2442,2452,2466,2468,
-2448,2414,2382,2372,2392,2433,2475,2498,2500,2490,2485,2499,2534,2578,2620,2650,2665,2667,2662,2652,2641,
-2632,2632,2648,2681,2728,2781,2832,2877,2916,2953,2988,3022,3053,3079,3098,3114,3128,3144,3163,3182,3198,
-3209,3214,3215,3219,3230,3250,3276,3302,3323,3336,3341,3345,3353,3367,3385,3402,3413,3419,3422,3429,3442,
-3463,3487,3506,3515,3515,3511,3509,3514,3525,3539,3551,3561,3572,3593,3622,3655,3682,3694,3693,3688,3693,
-3715,3747,3772,3773,3749,3715,3700,3724,3790,3879,3963,4020,4041,4038,4025,4015,4009,4004,3999,3997,4002,
-4017,4038,4055,4062,4058,4049,4046,4055,4077,4106,4137,4168,4199,4228,4255,4279,4299,4316,4333,4352,4375,
-4403,4433,4464,4492,4514,4526,4530,4526,4522,4522,4525,4529,4531,4530,4525,4521,4519,4517,4513,4506,4498,
-4494,4497,4507,4519,4528,4532,4532,4532,4533,4535,4535,4531,4524,4518,4513,4511,4507,4501,4492,4482,4474,
-4469,4464,4456,4447,4437,4429,4426,4426,4428,4430,4430,4428,4425,4420,4412,4402,4390,4379,4368,4357,4342,
-4324,4303,4281,4261,4243,4226,4207,4185,4161,4137,4114,4094,4076,4060,4044,4028,4010,3986,3959,3929,3900,
-3876,3857,3837,3816,3792,3770,3752,3742,3735,3723,3700,3667,3631,3605,3601,3623,3666,3722,3779,3830,3872,
-3901,3918,3919,3904,3871,3826,3774,3723,3683,3658,3653,3668,3703,3752,3809,3867,3919,3957,3976,3972,3944,
-3897,3835,3770,3711,3670,3650,3650,3661,3675,3684,3685,3680,3672,3663,3649,3624,3585,3534,3478,3424,3377,
-3334,3295,3258,3224,3195,3170,3145,3114,3075,3030,2989,2959,2941,2929,2914,2888,2850,2808,2769,2734,2703,
-2670,2632,2590,2549,2512,2480,2450,2418,2383,2346,2310,2276,2244,2210,2174,2136,2097,2060,2024,1989,1953,
-1916,1878,1841,1804,1768,1732,1695,1657,1620,1583,1546,1509,1472,1433,1395,1357,1319,1284,1250,1219,1190,
-1160,1128,1093,1055,1018,983,949,916,881,846,810,774,738,702,664,625,585,546,508,471,432,
-390,346,302,261,224,188,153,116,78,39,-1,-42,-84,-124,-162,-197,-229,-262,-297,-334,-372,
--409,-443,-475,-507,-539,-573,-606,-639,-672,-706,-744,-784,-825,-864,-899,-930,-957,-984,-1012,-1041,-1072,
--1106,-1141,-1178,-1213,-1245,-1274,-1300,-1325,-1351,-1378,-1407,-1437,-1467,-1496,-1526,-1554,-1582,-1609,-1636,-1662,-1687,
--1711,-1735,-1757,-1781,-1806,-1832,-1858,-1882,-1903,-1923,-1944,-1967,-1991,-2013,-2031,-2044,-2055,-2065,-2078,-2091,-2105,
--2118,-2130,-2142,-2154,-2164,-2172,-2178,-2185,-2195,-2210,-2230,-2249,-2265,-2275,-2280,-2284,-2290,-2298,-2307,-2315,-2324,
--2332,-2341,-2350,-2358,-2362,-2363,-2361,-2357,-2353,-2351,-2351,-2353,-2355,-2358,-2360,-2360,-2357,-2351,-2343,-2334,-2324,
--2314,-2304,-2294,-2286,-2278,-2270,-2262,-2253,-2243,-2234,-2226,-2219,-2212,-2203,-2192,-2180,-2166,-2152,-2137,-2121,-2104,
--2089,-2076,-2067,-2059,-2050,-2038,-2025,-2010,-1996,-1983,-1971,-1957,-1942,-1927,-1914,-1904,-1896,-1887,-1876,-1863,-1848,
--1834,-1821,-1811,-1807,-1812,-1825,-1844,-1860,-1867,-1861,-1842,-1820,-1802,-1790,-1782,-1774,-1760,-1743,-1729,-1723,-1726,
--1732,-1733,-1723,-1708,-1695,-1695,-1712,-1739,-1768,-1788,-1797,-1798,-1796,-1797,-1801,-1805,-1803,-1793,-1774,-1750,-1726,
--1706,-1695,-1695,-1705,-1721,-1737,-1745,-1745,-1739,-1730,-1724,-1720,-1717,-1711,-1703,-1697,-1695,-1701,-1710,-1718,-1720,
--1715,-1709,-1706,-1709,-1713,-1715,-1712,-1705,-1698,-1695,-1695,-1693,-1684,-1666,-1641,-1614,-1592,-1575,-1559,-1540,-1517,
--1492,-1469,-1450,-1433,-1416,-1396,-1375,-1358,-1348,-1342,-1330,-1302,-1250,-1175,-1087,-1005,-948,-930,-956,-1022,-1113,
--1208,-1283,-1314,-1292,-1219,-1116,-1013,-936,-900,-903,-931,-964,-992,-1010,-1023,-1035,-1047,-1058,-1063,-1063,-1061,
--1058,-1057,-1055,-1051,-1045,-1041,-1042,-1051,-1065,-1078,-1087,-1090,-1090,-1090,-1097,-1114,-1141,-1176,-1214,-1250,-1279,
--1302,-1324,-1348,-1380,-1416,-1449,-1473,-1487,-1496,-1509,-1533,-1564,-1599,-1629,-1652,-1672,-1694,-1721,-1751,-1775,-1790,
--1795,-1793,-1791,-1792,-1796,-1797,-1793,-1778,-1752,-1716,-1678,-1651,-1650,-1683,-1749,-1833,-1912,-1969,-2000,-2012,-2018,
--2028,-2042,-2051,-2049,-2034,-2013,-1994,-1980,-1971,-1961,-1949,-1935,-1925,-1921,-1921,-1921,-1921,-1920,-1922,-1930,-1940,
--1949,-1952,-1950,-1944,-1940,-1938,-1936,-1930,-1922,-1914,-1911,-1914,-1921,-1926,-1925,-1917,-1907,-1900,-1897,-1897,-1898,
--1899,-1900,-1901,-1902,-1900,-1895,-1885,-1873,-1861,-1852,-1847,-1846,-1848,-1855,-1866,-1881,-1896,-1909,-1913,-1909,-1899,
--1885,-1873,-1866,-1863,-1864,-1868,-1871,-1875,-1877,-1877,-1876,-1874,-1871,-1866,-1858,-1847,-1834,-1819,-1804,-1789,-1776,
--1763,-1750,-1737,-1725,-1714,-1706,-1699,-1692,-1687,-1683,-1680,-1677,-1673,-1667,-1658,-1648,-1640,-1634,-1630,-1628,-1625,
--1625,-1627,-1635,-1648,-1666,-1684,-1700,-1712,-1719,-1719,-1713,-1699,-1680,-1662,-1648,-1644,-1651,-1668,-1692,-1720,-1749,
--1778,-1801,-1816,-1822,-1819,-1810,-1800,-1793,-1788,-1783,-1774,-1760,-1742,-1722,-1705,-1696,-1698,-1709,-1727,-1747,-1762,
--1769,-1769,-1765,-1765,-1769,-1779,-1789,-1797,-1799,-1799,-1798,-1797,-1797,-1794,-1788,-1780,-1773,-1769,-1767,-1764,-1759,
--1750,-1739,-1728,-1718,-1707,-1692,-1674,-1653,-1632,-1612,-1594,-1576,-1556,-1533,-1510,-1489,-1470,-1453,-1436,-1418,-1399,
--1381,-1364,-1348,-1332,-1314,-1294,-1276,-1260,-1248,-1237,-1227,-1216,-1204,-1192,-1181,-1173,-1166,-1158,-1149,-1138,-1124,
--1110,-1097,-1086,-1077,-1070,-1063,-1056,-1048,-1040,-1031,-1023,-1015,-1009,-1003,-998,-993,-987,-982,-978,-974,-973,
--972,-974,-977,-981,-986,-993,-1000,-1007,-1012,-1014,-1013,-1012,-1012,-1017,-1025,-1036,-1048,-1058,-1065,-1071,-1075,
--1079,-1081,-1082,-1082,-1081,-1081,-1082,-1082,-1083,-1082,-1081,-1081,-1082,-1084,-1086,-1088,-1088,-1086,-1084,-1080,-1077,
--1072,-1066,-1061,-1058,-1056,-1055,-1054,-1051,-1044,-1035,-1026,-1018,-1009,-1000,-988,-975,-962,-951,-943,-939,-936,
--932,-923,-908,-886,-862,-838,-820,-808,-801,-794,-785,-772,-755,-739,-727,-719,-714,-709,-704,-698,-693,
--691,-690,-687,-680,-669,-658,-648,-640,-633,-625,-614,-600,-585,-571,-557,-542,-524,-501,-477,-452,-428,
--406,-384,-362,-341,-321,-302,-285,-269,-255,-241,-225,-206,-181,-154,-126,-102,-85,-73,-61,-44,-22,
-0,21,36,49,66,89,119,149,174,195,217,242,273,305,332,353,370,389,414,440,462,
-476,487,501,522,546,560,555,534,507,488,488,506,541,601,698,841,1016,1189,1311,1355,1335,
-1300,1311,1397,1536,1666,1723,1681,1566,1439,1352,1325,1337,1348,1331,1285,1229,1183,1154,1134,1111,1081,
-1050,1029,1021,1023,1026,1025,1021,1020,1024,1031,1034,1034,1034,1043,1067,1101,1135,1161,1175,1182,1192,
-1212,1241,1271,1295,1308,1308,1300,1287,1275,1265,1261,1263,1270,1277,1280,1277,1269,1260,1254,1249,1245,
-1237,1225,1208,1190,1173,1157,1140,1122,1098,1069,1035,998,959,922,890,862,836,809,777,741,701,
-660,622,586,552,521,495,473,458,446,434,420,400,377,353,330,310,293,280,273,272,276,
-281,284,283,277,271,269,275,290,310,334,358,384,410,438,469,502,539,578,617,654,687,
-712,728,734,732,725,715,704,689,665,629,579,518,457,408,379,371,380,395,409,420,428,
-437,449,465,484,505,531,562,597,630,654,665,664,657,653,660,678,703,729,750,768,786,
-809,840,875,910,940,964,986,1011,1041,1075,1108,1135,1151,1157,1159,1162,1170,1187,1212,1245,1286,
-1332,1381,1429,1471,1503,1524,1539,1550,1562,1576,1593,1612,1634,1657,1682,1708,1734,1759,1782,1805,1828,
-1852,1876,1900,1924,1948,1970,1991,2010,2027,2044,2060,2077,2094,2109,2123,2137,2153,2172,2193,2214,2234,
-2251,2269,2289,2314,2344,2377,2409,2438,2462,2483,2503,2522,2540,2558,2575,2588,2598,2605,2611,2618,2630,
-2646,2664,2680,2689,2691,2690,2690,2694,2702,2711,2716,2717,2717,2718,2723,2729,2734,2734,2729,2723,2719,
-2720,2723,2723,2717,2707,2695,2684,2678,2673,2666,2657,2646,2637,2631,2627,2624,2619,2612,2603,2593,2585,
-2576,2569,2561,2555,2547,2537,2576,2557,2535,2516,2506,2509,2520,2531,2534,2528,2520,2518,2524,2536,2543,
-2540,2528,2513,2503,2500,2499,2493,2479,2462,2449,2446,2450,2454,2452,2447,2447,2460,2486,2514,2534,2537,
-2528,2520,2524,2547,2581,2617,2646,2664,2674,2678,2676,2666,2651,2640,2645,2676,2732,2802,2870,2923,2959,
-2983,3007,3037,3070,3102,3126,3140,3149,3159,3174,3192,3209,3219,3223,3223,3225,3234,3253,3280,3309,3334,
-3351,3361,3365,3368,3375,3385,3398,3409,3418,3424,3433,3447,3467,3490,3510,3523,3527,3524,3522,3524,3534,
-3549,3564,3576,3589,3606,3630,3660,3688,3705,3707,3700,3694,3700,3718,3737,3742,3723,3690,3667,3677,3731,
-3819,3913,3984,4017,4019,4007,3999,4002,4008,4008,4000,3989,3987,3998,4019,4039,4048,4047,4043,4046,4063,
-4091,4124,4155,4182,4206,4232,4261,4291,4318,4341,4360,4379,4402,4430,4461,4493,4521,4541,4552,4556,4557,
-4558,4562,4568,4573,4575,4573,4569,4565,4561,4556,4549,4542,4536,4537,4544,4556,4567,4574,4574,4570,4566,
-4561,4555,4546,4535,4523,4514,4510,4508,4504,4498,4487,4476,4466,4459,4452,4444,4434,4423,4416,4413,4415,
-4418,4419,4418,4415,4410,4405,4400,4394,4387,4378,4367,4352,4333,4310,4285,4261,4239,4219,4201,4183,4166,
-4148,4132,4115,4097,4079,4060,4043,4026,4009,3988,3962,3933,3906,3883,3865,3849,3832,3811,3790,3770,3755,
-3744,3732,3713,3687,3657,3631,3613,3608,3614,3626,3644,3665,3689,3716,3743,3764,3775,3774,3759,3734,3704,
-3675,3652,3638,3637,3647,3668,3695,3726,3756,3783,3803,3813,3809,3789,3755,3714,3675,3650,3643,3653,3673,
-3692,3701,3699,3691,3682,3676,3670,3658,3636,3603,3563,3521,3476,3427,3372,3314,3258,3213,3181,3160,3139,
-3108,3065,3017,2972,2940,2918,2902,2882,2855,2821,2786,2753,2722,2690,2653,2611,2569,2531,2497,2467,2436,
-2404,2369,2334,2299,2263,2226,2187,2146,2106,2067,2030,1994,1957,1920,1882,1846,1811,1777,1741,1703,1663,
-1622,1584,1548,1515,1482,1448,1412,1374,1335,1298,1265,1234,1204,1172,1138,1100,1063,1027,995,965,935,
-902,867,831,795,760,723,685,643,600,558,518,480,442,404,363,322,281,242,205,170,135,
-98,60,19,-23,-65,-105,-141,-173,-204,-237,-272,-309,-345,-379,-410,-440,-472,-506,-542,-576,-610,
--643,-679,-718,-759,-798,-833,-864,-893,-923,-954,-987,-1019,-1051,-1082,-1114,-1148,-1183,-1215,-1244,-1269,-1291,
--1315,-1343,-1373,-1405,-1436,-1466,-1494,-1522,-1550,-1578,-1606,-1633,-1659,-1685,-1710,-1734,-1759,-1785,-1811,-1836,-1860,
--1882,-1905,-1927,-1951,-1975,-1996,-2013,-2025,-2034,-2044,-2056,-2071,-2087,-2102,-2113,-2122,-2129,-2136,-2145,-2157,-2171,
--2186,-2202,-2218,-2232,-2245,-2256,-2265,-2274,-2282,-2290,-2298,-2307,-2316,-2325,-2334,-2342,-2348,-2351,-2353,-2353,-2353,
--2352,-2351,-2351,-2353,-2358,-2364,-2368,-2369,-2364,-2355,-2343,-2331,-2320,-2309,-2297,-2286,-2276,-2267,-2260,-2254,-2246,
--2237,-2228,-2219,-2210,-2202,-2192,-2181,-2168,-2155,-2141,-2127,-2114,-2100,-2088,-2076,-2067,-2059,-2050,-2039,-2028,-2016,
--2005,-1994,-1982,-1969,-1953,-1938,-1925,-1915,-1907,-1899,-1890,-1879,-1867,-1853,-1840,-1829,-1822,-1823,-1833,-1850,-1867,
--1876,-1873,-1859,-1838,-1820,-1808,-1800,-1791,-1776,-1758,-1742,-1735,-1738,-1745,-1748,-1741,-1725,-1710,-1706,-1719,-1744,
--1772,-1792,-1800,-1799,-1796,-1797,-1805,-1814,-1818,-1813,-1797,-1773,-1747,-1725,-1711,-1710,-1719,-1735,-1752,-1763,-1767,
--1765,-1761,-1756,-1752,-1747,-1739,-1730,-1723,-1721,-1725,-1730,-1732,-1727,-1719,-1714,-1715,-1723,-1732,-1737,-1735,-1728,
--1722,-1723,-1727,-1727,-1716,-1692,-1662,-1632,-1611,-1597,-1585,-1569,-1546,-1520,-1497,-1483,-1474,-1465,-1451,-1431,-1407,
--1384,-1358,-1323,-1271,-1200,-1114,-1031,-969,-945,-966,-1027,-1116,-1213,-1298,-1350,-1358,-1318,-1239,-1143,-1053,-991,
--963,-968,-992,-1021,-1046,-1064,-1077,-1087,-1094,-1100,-1103,-1107,-1112,-1120,-1126,-1128,-1126,-1120,-1118,-1124,-1139,
--1158,-1174,-1181,-1180,-1175,-1173,-1182,-1204,-1238,-1279,-1320,-1356,-1383,-1408,-1435,-1470,-1515,-1563,-1607,-1640,-1662,
--1680,-1699,-1726,-1756,-1784,-1805,-1820,-1831,-1845,-1861,-1878,-1891,-1897,-1899,-1899,-1901,-1903,-1903,-1900,-1892,-1881,
--1867,-1849,-1832,-1820,-1825,-1852,-1902,-1964,-2022,-2062,-2081,-2086,-2088,-2096,-2109,-2120,-2119,-2107,-2089,-2070,-2056,
--2044,-2030,-2015,-1999,-1987,-1981,-1980,-1980,-1977,-1975,-1976,-1982,-1993,-2003,-2009,-2008,-2004,-1999,-1996,-1992,-1986,
--1978,-1972,-1972,-1978,-1988,-1995,-1996,-1989,-1979,-1971,-1967,-1968,-1969,-1969,-1966,-1961,-1956,-1951,-1945,-1937,-1928,
--1919,-1910,-1902,-1894,-1888,-1887,-1893,-1909,-1931,-1955,-1974,-1984,-1983,-1973,-1957,-1940,-1925,-1913,-1907,-1906,-1909,
--1915,-1920,-1923,-1923,-1918,-1911,-1901,-1889,-1876,-1864,-1853,-1844,-1835,-1825,-1813,-1798,-1784,-1771,-1760,-1751,-1743,
--1735,-1727,-1721,-1715,-1710,-1705,-1698,-1691,-1684,-1679,-1675,-1671,-1663,-1653,-1643,-1635,-1635,-1645,-1665,-1692,-1719,
--1742,-1755,-1757,-1748,-1730,-1709,-1689,-1673,-1664,-1662,-1667,-1682,-1705,-1736,-1769,-1799,-1821,-1832,-1834,-1831,-1825,
--1818,-1808,-1795,-1777,-1755,-1731,-1712,-1701,-1702,-1717,-1742,-1769,-1790,-1800,-1799,-1791,-1782,-1779,-1783,-1791,-1798,
--1803,-1805,-1807,-1808,-1808,-1805,-1799,-1791,-1783,-1778,-1776,-1775,-1772,-1765,-1756,-1746,-1735,-1722,-1707,-1687,-1667,
--1646,-1627,-1610,-1591,-1570,-1546,-1523,-1501,-1482,-1464,-1447,-1428,-1408,-1390,-1373,-1358,-1342,-1325,-1306,-1286,-1268,
--1252,-1239,-1228,-1216,-1204,-1191,-1179,-1169,-1160,-1152,-1143,-1134,-1124,-1114,-1103,-1093,-1083,-1074,-1066,-1059,-1051,
--1044,-1036,-1028,-1021,-1016,-1011,-1006,-1002,-998,-994,-992,-991,-991,-993,-994,-996,-999,-1002,-1007,-1012,-1017,
--1020,-1021,-1019,-1018,-1019,-1024,-1031,-1041,-1051,-1061,-1070,-1079,-1086,-1091,-1094,-1093,-1090,-1088,-1089,-1091,-1094,
--1095,-1094,-1092,-1090,-1090,-1094,-1098,-1102,-1103,-1102,-1100,-1098,-1096,-1093,-1089,-1085,-1080,-1075,-1071,-1066,-1059,
--1050,-1041,-1034,-1028,-1024,-1018,-1010,-999,-985,-972,-963,-956,-952,-947,-937,-919,-895,-868,-842,-820,-805,
--795,-785,-775,-762,-749,-739,-733,-729,-727,-722,-717,-713,-712,-712,-711,-707,-697,-685,-673,-664,-657,
--651,-643,-630,-616,-602,-589,-577,-563,-544,-522,-498,-474,-452,-430,-409,-386,-363,-341,-322,-304,-289,
--275,-261,-245,-226,-202,-175,-148,-125,-108,-95,-82,-65,-43,-20,0,15,29,46,69,99,131,
-158,181,204,229,259,290,316,336,353,370,392,417,441,462,480,500,523,543,553,546,524,
-498,478,472,482,511,571,674,827,1013,1191,1314,1357,1334,1294,1298,1373,1501,1623,1681,1649,1549,
-1433,1350,1317,1315,1312,1284,1231,1173,1130,1107,1097,1084,1064,1038,1016,1005,1003,1005,1006,1007,1009,
-1014,1019,1023,1026,1032,1050,1082,1123,1163,1192,1209,1218,1232,1254,1284,1312,1328,1327,1308,1279,1248,
-1223,1209,1209,1220,1239,1258,1273,1280,1282,1281,1280,1281,1281,1278,1271,1259,1246,1231,1217,1199,1177,
-1149,1115,1076,1035,995,958,926,901,880,863,846,827,805,780,751,718,682,645,610,581,557,
-537,518,496,472,448,425,406,389,374,361,352,347,348,352,354,352,345,339,339,350,374,
-409,447,483,513,539,563,590,624,663,707,749,785,810,823,824,813,796,776,756,736,715,
-689,654,609,560,516,486,475,479,490,499,503,503,507,518,538,561,582,598,615,637,668,
-703,733,750,750,739,726,723,731,748,766,782,796,813,839,873,911,947,975,994,1010,1028,
-1051,1079,1109,1136,1157,1173,1185,1194,1202,1214,1232,1262,1305,1359,1418,1475,1521,1553,1574,1587,1597,
-1606,1615,1623,1633,1647,1666,1691,1719,1746,1771,1791,1808,1825,1843,1864,1886,1909,1932,1955,1975,1994,
-2012,2030,2049,2069,2087,2105,2120,2135,2150,2168,2188,2210,2233,2254,2276,2299,2324,2351,2378,2406,2432,
-2456,2478,2497,2515,2531,2547,2562,2575,2586,2595,2603,2613,2629,2648,2668,2684,2692,2693,2690,2689,2692,
-2698,2703,2706,2706,2706,2710,2718,2726,2732,2732,2731,2732,2738,2746,2753,2753,2745,2731,2717,2706,2699,
-2691,2680,2668,2657,2650,2646,2645,2642,2637,2629,2623,2620,2618,2616,2612,2606,2599,2590,2576,2613,2596,
-2571,2546,2528,2522,2528,2537,2541,2538,2532,2530,2537,2549,2555,2548,2528,2504,2486,2479,2483,2489,2490,
-2485,2479,2477,2481,2491,2504,2517,2530,2544,2555,2560,2557,2549,2544,2552,2575,2608,2641,2664,2675,2679,
-2682,2686,2688,2685,2678,2681,2705,2760,2838,2921,2988,3026,3038,3039,3045,3065,3095,3127,3150,3163,3172,
-3182,3197,3213,3225,3229,3229,3228,3236,3255,3284,3316,3344,3365,3378,3385,3390,3394,3400,3406,3412,3417,
-3424,3433,3447,3467,3488,3509,3525,3534,3538,3538,3540,3545,3554,3566,3580,3596,3616,3642,3672,3699,3718,
-3723,3718,3711,3710,3720,3731,3732,3712,3675,3637,3625,3658,3734,3834,3924,3979,3996,3986,3973,3972,3983,
-3997,3999,3989,3974,3966,3972,3989,4007,4019,4024,4031,4048,4078,4116,4152,4181,4202,4222,4246,4277,4312,
-4344,4370,4390,4411,4434,4464,4495,4525,4549,4565,4574,4581,4587,4595,4604,4612,4618,4621,4621,4619,4616,
-4610,4601,4590,4582,4578,4583,4593,4605,4613,4615,4611,4604,4597,4591,4583,4571,4554,4538,4524,4517,4513,
-4510,4502,4491,4477,4465,4455,4447,4438,4430,4423,4419,4420,4423,4424,4422,4415,4408,4401,4398,4397,4395,
-4388,4377,4360,4340,4320,4300,4282,4265,4246,4224,4200,4175,4153,4135,4122,4110,4096,4078,4059,4039,4020,
-4001,3982,3959,3933,3907,3884,3866,3852,3838,3824,3807,3790,3774,3760,3745,3729,3710,3690,3670,3651,3633,
-3614,3597,3583,3578,3586,3607,3636,3668,3694,3709,3711,3701,3686,3670,3657,3649,3645,3641,3633,3619,3603,
-3593,3596,3619,3658,3704,3743,3764,3763,3747,3726,3713,3714,3725,3738,3744,3739,3726,3711,3696,3684,3670,
-3653,3633,3611,3588,3558,3515,3453,3375,3292,3221,3171,3145,3131,3115,3086,3042,2991,2946,2912,2889,2870,
-2850,2826,2798,2771,2743,2714,2681,2642,2601,2560,2521,2486,2453,2419,2385,2348,2312,2274,2235,2195,2154,
-2114,2075,2037,1999,1961,1923,1885,1849,1814,1781,1747,1710,1671,1630,1591,1555,1521,1489,1457,1422,1386,
-1349,1313,1280,1248,1216,1182,1146,1108,1071,1036,1006,976,946,914,879,842,806,770,733,694,652,
-609,566,525,486,449,411,374,335,295,257,219,183,148,113,77,37,-3,-45,-84,-119,-152,
--183,-217,-252,-288,-322,-353,-382,-412,-444,-480,-517,-553,-587,-623,-660,-699,-738,-774,-804,-830,-858,
--889,-925,-964,-1000,-1032,-1062,-1092,-1125,-1159,-1191,-1219,-1242,-1264,-1287,-1314,-1345,-1377,-1407,-1435,-1463,-1491,
--1521,-1550,-1579,-1607,-1633,-1660,-1686,-1713,-1739,-1763,-1787,-1810,-1834,-1858,-1882,-1908,-1933,-1957,-1978,-1995,-2008,
--2018,-2028,-2040,-2055,-2072,-2086,-2097,-2103,-2107,-2113,-2124,-2140,-2159,-2177,-2192,-2204,-2215,-2226,-2239,-2253,-2267,
--2279,-2288,-2297,-2305,-2315,-2325,-2334,-2340,-2345,-2348,-2351,-2354,-2358,-2359,-2360,-2362,-2366,-2373,-2382,-2387,-2387,
--2378,-2364,-2347,-2331,-2317,-2304,-2292,-2280,-2269,-2260,-2253,-2246,-2239,-2230,-2220,-2211,-2204,-2196,-2188,-2177,-2165,
--2152,-2140,-2129,-2120,-2110,-2099,-2087,-2075,-2064,-2053,-2043,-2033,-2025,-2017,-2010,-2001,-1990,-1977,-1962,-1948,-1936,
--1925,-1915,-1904,-1894,-1885,-1875,-1865,-1854,-1845,-1841,-1846,-1859,-1875,-1887,-1888,-1876,-1857,-1838,-1825,-1816,-1808,
--1795,-1778,-1762,-1754,-1755,-1763,-1767,-1762,-1747,-1730,-1722,-1729,-1749,-1775,-1796,-1807,-1809,-1809,-1811,-1817,-1825,
--1830,-1826,-1813,-1793,-1770,-1750,-1737,-1734,-1742,-1758,-1776,-1790,-1798,-1798,-1795,-1789,-1782,-1775,-1766,-1757,-1751,
--1748,-1748,-1749,-1746,-1740,-1733,-1730,-1733,-1742,-1750,-1753,-1750,-1746,-1745,-1749,-1754,-1753,-1739,-1712,-1680,-1653,
--1635,-1624,-1612,-1594,-1569,-1543,-1523,-1513,-1509,-1501,-1483,-1452,-1411,-1366,-1318,-1268,-1214,-1156,-1101,-1060,-1044,
--1058,-1101,-1165,-1239,-1310,-1363,-1388,-1377,-1328,-1252,-1165,-1090,-1041,-1025,-1036,-1061,-1087,-1106,-1118,-1124,-1130,
--1135,-1141,-1149,-1159,-1173,-1189,-1203,-1211,-1212,-1210,-1211,-1219,-1235,-1254,-1271,-1279,-1279,-1274,-1272,-1281,-1303,
--1336,-1375,-1413,-1444,-1469,-1495,-1530,-1576,-1634,-1694,-1747,-1788,-1816,-1838,-1859,-1884,-1910,-1932,-1947,-1957,-1965,
--1974,-1985,-1993,-1997,-1997,-1998,-2002,-2009,-2015,-2016,-2010,-2001,-1993,-1989,-1988,-1990,-1993,-2002,-2022,-2055,-2095,
--2133,-2159,-2169,-2169,-2169,-2174,-2183,-2190,-2189,-2178,-2161,-2145,-2131,-2119,-2104,-2087,-2070,-2058,-2051,-2048,-2045,
--2041,-2036,-2034,-2038,-2047,-2058,-2065,-2067,-2065,-2061,-2058,-2055,-2050,-2044,-2039,-2038,-2043,-2051,-2057,-2058,-2054,
--2047,-2042,-2040,-2040,-2039,-2035,-2027,-2017,-2007,-1999,-1993,-1987,-1981,-1975,-1967,-1958,-1947,-1935,-1926,-1925,-1934,
--1953,-1977,-2002,-2022,-2034,-2037,-2032,-2020,-2004,-1986,-1969,-1957,-1951,-1950,-1950,-1950,-1949,-1945,-1941,-1935,-1927,
--1918,-1909,-1899,-1890,-1881,-1872,-1861,-1849,-1837,-1825,-1815,-1805,-1795,-1783,-1771,-1759,-1750,-1743,-1738,-1733,-1728,
--1723,-1720,-1718,-1716,-1712,-1702,-1689,-1674,-1665,-1665,-1675,-1695,-1720,-1743,-1760,-1769,-1771,-1768,-1762,-1752,-1739,
--1722,-1703,-1684,-1671,-1671,-1684,-1708,-1739,-1770,-1797,-1818,-1834,-1844,-1849,-1847,-1838,-1820,-1797,-1770,-1746,-1730,
--1727,-1738,-1760,-1787,-1811,-1824,-1827,-1820,-1812,-1805,-1804,-1806,-1808,-1810,-1810,-1811,-1813,-1815,-1815,-1811,-1805,
--1799,-1794,-1791,-1787,-1782,-1773,-1762,-1750,-1738,-1725,-1710,-1694,-1676,-1658,-1641,-1623,-1603,-1581,-1558,-1535,-1515,
--1498,-1482,-1465,-1446,-1425,-1405,-1386,-1370,-1355,-1339,-1321,-1303,-1284,-1267,-1252,-1238,-1224,-1211,-1198,-1185,-1172,
--1160,-1148,-1138,-1128,-1120,-1111,-1103,-1093,-1082,-1072,-1063,-1055,-1048,-1041,-1034,-1027,-1022,-1019,-1017,-1015,-1013,
--1010,-1008,-1007,-1008,-1010,-1012,-1015,-1017,-1019,-1021,-1024,-1028,-1031,-1032,-1031,-1029,-1026,-1026,-1028,-1032,-1037,
--1044,-1053,-1063,-1073,-1083,-1090,-1093,-1092,-1089,-1086,-1086,-1088,-1090,-1092,-1091,-1090,-1090,-1091,-1095,-1100,-1103,
--1105,-1106,-1107,-1108,-1109,-1108,-1105,-1100,-1093,-1086,-1080,-1073,-1066,-1057,-1049,-1042,-1037,-1034,-1030,-1025,-1017,
--1007,-996,-987,-979,-972,-963,-949,-931,-907,-881,-856,-834,-816,-801,-787,-773,-761,-751,-746,-744,-744,
--741,-736,-731,-728,-729,-731,-731,-727,-717,-704,-692,-683,-676,-669,-658,-644,-630,-618,-608,-598,-585,
--567,-544,-520,-496,-475,-454,-433,-411,-388,-366,-346,-329,-313,-298,-283,-267,-249,-226,-200,-173,-148,
--129,-114,-101,-84,-63,-40,-18,0,17,36,60,90,120,147,170,192,215,241,269,294,315,
-335,355,379,405,431,455,478,501,524,542,549,541,522,498,477,464,463,481,532,633,788,
-979,1166,1301,1358,1347,1315,1315,1376,1484,1590,1641,1615,1528,1425,1346,1307,1293,1276,1239,1183,1126,
-1087,1072,1070,1066,1052,1030,1008,994,989,991,994,997,1000,1003,1007,1010,1014,1025,1048,1085,1129,
-1171,1203,1224,1240,1259,1287,1319,1346,1356,1343,1311,1266,1220,1184,1163,1161,1175,1200,1229,1256,1275,
-1287,1292,1294,1293,1291,1288,1283,1279,1274,1268,1257,1241,1218,1187,1151,1112,1072,1033,996,964,940,
-923,915,910,906,898,883,861,829,792,751,711,675,644,617,591,566,542,520,503,490,481,
-474,469,466,466,470,475,477,473,463,453,448,454,475,505,539,569,592,608,624,644,673,
-711,754,797,834,860,873,873,860,837,807,775,744,716,688,658,625,594,568,555,555,563,
-571,572,567,562,564,581,608,636,658,669,675,685,704,732,760,780,788,789,793,806,828,
-852,869,875,876,881,898,930,970,1010,1041,1061,1076,1089,1105,1123,1142,1161,1181,1200,1219,1235,
-1246,1256,1268,1292,1332,1388,1450,1508,1553,1583,1603,1618,1633,1647,1659,1665,1669,1674,1686,1707,1733,
-1760,1782,1799,1812,1824,1840,1860,1884,1908,1930,1950,1968,1983,1999,2015,2035,2056,2077,2099,2119,2138,
-2155,2174,2193,2214,2237,2260,2285,2309,2332,2354,2375,2397,2419,2442,2464,2483,2497,2509,2520,2533,2548,
-2562,2576,2588,2600,2615,2632,2649,2663,2670,2671,2670,2671,2675,2681,2687,2690,2692,2697,2705,2716,2727,
-2734,2737,2740,2746,2758,2770,2777,2774,2763,2747,2733,2724,2717,2708,2697,2683,2672,2666,2664,2662,2658,
-2651,2645,2642,2643,2645,2646,2643,2638,2631,2624,2613,2640,2633,2616,2592,2568,2551,2543,2540,2535,2525,
-2514,2509,2515,2528,2538,2536,2519,2494,2472,2463,2469,2483,2499,2509,2514,2518,2525,2535,2547,2559,2568,
-2572,2569,2561,2551,2547,2556,2581,2616,2651,2676,2686,2686,2684,2687,2697,2708,2716,2725,2746,2790,2861,
-2947,3026,3078,3096,3088,3074,3072,3089,3120,3151,3174,3188,3197,3208,3222,3235,3243,3244,3243,3248,3263,
-3289,3320,3348,3369,3382,3390,3398,3406,3413,3417,3419,3420,3423,3431,3445,3465,3486,3506,3521,3532,3541,
-3547,3553,3559,3564,3571,3579,3593,3615,3643,3676,3705,3726,3734,3733,3729,3730,3739,3750,3750,3730,3687,
-3635,3598,3600,3652,3741,3841,3921,3964,3970,3957,3946,3948,3961,3973,3974,3964,3950,3944,3949,3963,3979,
-3992,4004,4021,4050,4089,4130,4165,4190,4209,4230,4258,4295,4334,4369,4397,4418,4439,4464,4494,4525,4553,
-4574,4588,4598,4606,4615,4624,4631,4637,4641,4646,4652,4659,4663,4662,4655,4645,4637,4636,4643,4655,4665,
-4667,4661,4649,4636,4627,4621,4614,4603,4586,4567,4550,4538,4529,4521,4511,4497,4483,4470,4460,4453,4446,
-4440,4435,4433,4434,4435,4433,4427,4417,4408,4403,4403,4404,4401,4391,4372,4348,4327,4312,4305,4303,4297,
-4282,4255,4218,4178,4143,4118,4103,4094,4086,4073,4055,4033,4011,3990,3969,3947,3924,3899,3876,3857,3842,
-3830,3820,3810,3799,3787,3773,3759,3743,3729,3715,3703,3689,3671,3649,3624,3602,3589,3590,3605,3629,3656,
-3678,3689,3689,3679,3667,3658,3655,3657,3659,3651,3625,3582,3529,3486,3472,3501,3573,3672,3772,3849,3887,
-3886,3860,3827,3804,3794,3794,3796,3793,3782,3765,3743,3718,3692,3664,3641,3624,3614,3601,3574,3521,3439,
-3340,3244,3171,3128,3111,3104,3090,3060,3018,2971,2931,2900,2877,2855,2832,2805,2778,2752,2725,2697,2663,
-2626,2585,2545,2505,2468,2431,2394,2356,2317,2277,2236,2196,2156,2117,2079,2043,2006,1969,1931,1893,1856,
-1821,1786,1752,1717,1680,1642,1604,1567,1530,1494,1459,1424,1391,1358,1327,1295,1262,1228,1192,1155,1119,
-1085,1052,1019,987,954,919,882,845,807,770,732,693,654,614,574,534,494,455,416,378,341,
-304,266,228,192,156,122,86,49,9,-30,-68,-102,-133,-164,-197,-232,-267,-301,-332,-362,-392,
--426,-463,-500,-536,-570,-605,-642,-680,-717,-750,-777,-801,-828,-862,-900,-941,-979,-1012,-1041,-1071,-1104,
--1138,-1170,-1197,-1220,-1241,-1266,-1294,-1325,-1356,-1384,-1410,-1437,-1467,-1498,-1530,-1558,-1584,-1609,-1634,-1662,-1690,
--1717,-1742,-1764,-1785,-1809,-1835,-1863,-1891,-1917,-1941,-1962,-1979,-1994,-2005,-2016,-2027,-2040,-2054,-2068,-2080,-2087,
--2094,-2101,-2114,-2130,-2149,-2166,-2179,-2189,-2197,-2208,-2223,-2241,-2259,-2274,-2285,-2294,-2304,-2315,-2325,-2334,-2340,
--2344,-2348,-2353,-2359,-2363,-2366,-2367,-2368,-2374,-2384,-2394,-2401,-2398,-2387,-2368,-2348,-2330,-2315,-2303,-2291,-2279,
--2268,-2259,-2251,-2243,-2234,-2224,-2214,-2205,-2200,-2195,-2189,-2180,-2168,-2156,-2145,-2137,-2129,-2122,-2112,-2100,-2087,
--2074,-2063,-2053,-2045,-2038,-2032,-2026,-2018,-2009,-1999,-1987,-1975,-1963,-1950,-1936,-1923,-1912,-1904,-1898,-1892,-1884,
--1873,-1865,-1862,-1869,-1883,-1895,-1899,-1891,-1873,-1853,-1837,-1829,-1823,-1814,-1801,-1786,-1776,-1773,-1778,-1781,-1777,
--1764,-1747,-1735,-1736,-1753,-1778,-1803,-1822,-1831,-1834,-1834,-1835,-1836,-1834,-1828,-1816,-1801,-1784,-1770,-1760,-1760,
--1769,-1786,-1807,-1825,-1834,-1834,-1827,-1816,-1806,-1797,-1790,-1784,-1779,-1776,-1773,-1771,-1768,-1765,-1762,-1761,-1762,
--1764,-1765,-1763,-1760,-1759,-1763,-1769,-1772,-1768,-1752,-1727,-1702,-1681,-1667,-1655,-1640,-1618,-1591,-1566,-1548,-1538,
--1529,-1510,-1477,-1428,-1371,-1314,-1264,-1224,-1194,-1176,-1172,-1184,-1213,-1253,-1298,-1342,-1382,-1415,-1435,-1435,-1410,
--1356,-1281,-1203,-1142,-1109,-1109,-1130,-1157,-1178,-1186,-1186,-1184,-1185,-1191,-1201,-1213,-1227,-1243,-1260,-1276,-1289,
--1296,-1301,-1305,-1314,-1328,-1345,-1361,-1371,-1376,-1377,-1379,-1388,-1406,-1433,-1463,-1492,-1519,-1546,-1578,-1622,-1681,
--1749,-1816,-1873,-1915,-1943,-1964,-1985,-2008,-2030,-2048,-2061,-2069,-2078,-2087,-2097,-2102,-2102,-2099,-2099,-2103,-2114,
--2124,-2128,-2124,-2117,-2112,-2114,-2121,-2131,-2140,-2149,-2162,-2183,-2209,-2234,-2251,-2259,-2259,-2259,-2261,-2266,-2269,
--2264,-2252,-2235,-2218,-2204,-2191,-2177,-2160,-2143,-2131,-2123,-2120,-2116,-2110,-2103,-2097,-2097,-2104,-2113,-2121,-2125,
--2127,-2127,-2127,-2127,-2125,-2120,-2114,-2110,-2108,-2109,-2112,-2113,-2112,-2110,-2109,-2108,-2106,-2101,-2093,-2082,-2070,
--2061,-2053,-2047,-2041,-2035,-2029,-2022,-2012,-2000,-1987,-1975,-1967,-1966,-1973,-1986,-2004,-2024,-2044,-2063,-2077,-2083,
--2081,-2069,-2051,-2031,-2012,-1996,-1982,-1972,-1964,-1960,-1959,-1960,-1960,-1956,-1949,-1939,-1928,-1918,-1910,-1902,-1894,
--1886,-1877,-1869,-1860,-1848,-1833,-1817,-1801,-1789,-1779,-1772,-1767,-1761,-1755,-1751,-1750,-1751,-1752,-1750,-1744,-1733,
--1722,-1714,-1711,-1714,-1721,-1730,-1739,-1748,-1759,-1772,-1786,-1796,-1799,-1790,-1769,-1740,-1710,-1688,-1677,-1680,-1694,
--1715,-1740,-1767,-1794,-1820,-1843,-1860,-1868,-1865,-1854,-1835,-1813,-1794,-1782,-1781,-1789,-1803,-1819,-1830,-1837,-1838,
--1838,-1837,-1837,-1835,-1832,-1827,-1822,-1819,-1819,-1821,-1823,-1823,-1821,-1817,-1813,-1809,-1803,-1795,-1784,-1770,-1756,
--1742,-1729,-1715,-1700,-1684,-1667,-1649,-1630,-1610,-1588,-1566,-1546,-1529,-1514,-1500,-1484,-1465,-1445,-1424,-1404,-1387,
--1371,-1356,-1339,-1322,-1304,-1286,-1269,-1252,-1237,-1223,-1210,-1198,-1185,-1172,-1158,-1144,-1132,-1121,-1112,-1103,-1093,
--1083,-1073,-1064,-1057,-1050,-1044,-1037,-1031,-1028,-1026,-1026,-1026,-1025,-1023,-1021,-1020,-1021,-1023,-1027,-1030,-1032,
--1033,-1035,-1038,-1042,-1045,-1046,-1046,-1044,-1041,-1039,-1038,-1038,-1040,-1044,-1051,-1061,-1071,-1081,-1089,-1092,-1093,
--1091,-1088,-1086,-1085,-1084,-1083,-1081,-1080,-1080,-1082,-1085,-1087,-1089,-1091,-1095,-1101,-1107,-1112,-1113,-1110,-1104,
--1097,-1091,-1087,-1083,-1078,-1071,-1062,-1053,-1044,-1036,-1029,-1024,-1019,-1015,-1010,-1005,-999,-990,-977,-961,-941,
--919,-896,-875,-855,-837,-820,-803,-788,-776,-768,-764,-763,-760,-755,-748,-742,-739,-741,-745,-747,-744,
--735,-724,-712,-703,-696,-687,-675,-661,-647,-637,-628,-619,-606,-587,-564,-540,-518,-497,-477,-457,-436,
--414,-395,-377,-360,-343,-326,-308,-291,-273,-251,-226,-199,-172,-149,-131,-115,-99,-79,-56,-32,-9,
-11,32,56,83,110,134,156,176,195,217,241,265,289,313,341,370,400,428,452,475,497,
-518,535,542,537,523,504,484,467,456,460,497,585,731,919,1111,1264,1349,1369,1361,1368,1415,
-1494,1568,1597,1564,1483,1391,1320,1281,1261,1237,1194,1137,1083,1047,1035,1036,1037,1028,1010,992,980,
-979,984,990,995,997,996,996,996,1001,1015,1042,1081,1127,1170,1205,1230,1251,1273,1302,1333,1358,
-1368,1357,1327,1284,1239,1201,1177,1168,1175,1194,1220,1246,1267,1280,1284,1280,1272,1262,1255,1253,1256,
-1262,1265,1262,1249,1227,1199,1169,1138,1107,1076,1044,1016,993,979,973,971,968,960,944,920,889,
-854,816,778,742,708,677,648,623,600,580,566,557,553,554,560,568,579,591,599,600,593,
-579,561,546,539,544,557,574,589,600,607,615,628,650,680,718,758,797,833,860,876,876,
-859,826,785,741,704,674,651,632,617,607,604,608,617,625,627,624,622,631,652,683,714,
-735,743,743,742,747,758,772,783,792,809,840,887,943,992,1020,1023,1009,994,993,1012,1047,
-1086,1119,1143,1159,1172,1183,1194,1205,1217,1231,1249,1269,1287,1299,1306,1314,1332,1367,1417,1475,1528,
-1568,1596,1617,1638,1661,1685,1702,1710,1711,1709,1714,1728,1748,1771,1790,1804,1814,1826,1843,1866,1891,
-1917,1940,1959,1974,1989,2004,2020,2038,2057,2077,2099,2120,2143,2164,2184,2204,2222,2242,2263,2284,2306,
-2327,2345,2362,2381,2402,2425,2447,2465,2476,2482,2489,2499,2515,2533,2551,2565,2577,2588,2599,2611,2621,
-2628,2631,2634,2638,2646,2656,2666,2673,2680,2689,2702,2716,2728,2737,2742,2748,2758,2772,2785,2791,2787,
-2774,2758,2745,2737,2732,2725,2715,2703,2694,2689,2687,2684,2678,2669,2662,2659,2660,2661,2659,2652,2645,
-2640,2640,2640,2651,2656,2649,2631,2606,2582,2564,2549,2535,2519,2504,2498,2505,2521,2537,2543,2532,2511,
-2487,2474,2475,2488,2507,2523,2534,2541,2546,2551,2558,2563,2567,2567,2563,2558,2555,2560,2576,2602,2632,
-2657,2671,2675,2676,2682,2697,2719,2742,2765,2790,2827,2883,2956,3032,3094,3127,3132,3121,3113,3121,3145,
-3178,3207,3225,3235,3241,3250,3260,3269,3275,3277,3282,3294,3314,3338,3360,3375,3383,3387,3393,3403,3415,
-3425,3429,3428,3428,3433,3447,3468,3491,3511,3526,3534,3540,3547,3556,3566,3575,3582,3588,3597,3615,3641,
-3672,3702,3724,3733,3735,3735,3742,3757,3774,3780,3763,3719,3659,3603,3579,3601,3669,3764,3857,3924,3954,
-3955,3942,3932,3931,3937,3941,3938,3930,3923,3924,3934,3949,3965,3980,3997,4022,4056,4095,4132,4163,4186,
-4207,4234,4270,4313,4356,4391,4417,4436,4456,4481,4510,4541,4570,4593,4609,4622,4632,4640,4645,4646,4646,
-4648,4655,4668,4686,4702,4711,4712,4708,4703,4703,4709,4719,4725,4722,4709,4691,4673,4660,4652,4646,4637,
-4624,4606,4589,4572,4558,4543,4528,4512,4499,4489,4482,4476,4469,4459,4449,4441,4435,4431,4425,4418,4411,
-4406,4407,4411,4414,4409,4392,4366,4338,4317,4309,4314,4323,4325,4310,4276,4227,4175,4131,4101,4086,4081,
-4077,4068,4052,4030,4005,3979,3955,3931,3908,3884,3861,3840,3823,3809,3800,3793,3787,3781,3773,3763,3751,
-3739,3727,3717,3706,3692,3676,3658,3644,3636,3638,3646,3659,3672,3679,3679,3670,3657,3644,3636,3636,3644,
-3649,3642,3613,3562,3501,3451,3434,3469,3554,3674,3799,3899,3955,3964,3937,3893,3853,3825,3813,3810,3811,
-3809,3802,3787,3763,3729,3690,3654,3629,3618,3615,3605,3573,3509,3417,3315,3225,3161,3125,3109,3098,3078,
-3047,3008,2969,2935,2905,2877,2846,2814,2781,2750,2722,2694,2663,2628,2589,2549,2509,2471,2435,2399,2362,
-2322,2280,2238,2195,2154,2115,2078,2044,2010,1976,1942,1906,1870,1833,1795,1757,1721,1685,1649,1612,1574,
-1535,1495,1458,1425,1396,1369,1341,1310,1275,1237,1199,1163,1131,1100,1069,1036,1000,963,925,887,849,
-811,771,732,693,656,621,585,547,506,465,424,386,351,316,279,242,204,166,130,95,59,
-22,-15,-51,-84,-114,-144,-174,-208,-243,-277,-311,-343,-377,-412,-449,-485,-520,-552,-585,-620,-656,
--691,-722,-750,-776,-805,-839,-878,-919,-955,-987,-1017,-1047,-1080,-1114,-1145,-1172,-1196,-1219,-1245,-1275,-1306,
--1336,-1362,-1387,-1414,-1445,-1478,-1510,-1538,-1561,-1584,-1608,-1637,-1668,-1697,-1723,-1746,-1768,-1792,-1821,-1851,-1880,
--1907,-1929,-1949,-1966,-1981,-1993,-2003,-2011,-2021,-2034,-2047,-2061,-2073,-2084,-2095,-2108,-2123,-2139,-2153,-2164,-2172,
--2180,-2192,-2208,-2227,-2246,-2261,-2274,-2285,-2296,-2307,-2317,-2326,-2332,-2338,-2344,-2351,-2359,-2363,-2365,-2364,-2366,
--2373,-2384,-2395,-2401,-2397,-2383,-2364,-2345,-2328,-2315,-2304,-2293,-2282,-2272,-2263,-2255,-2246,-2235,-2223,-2212,-2203,
--2198,-2194,-2189,-2181,-2170,-2159,-2149,-2141,-2134,-2127,-2117,-2107,-2096,-2086,-2077,-2070,-2063,-2056,-2048,-2040,-2031,
--2022,-2013,-2005,-1996,-1987,-1975,-1960,-1945,-1932,-1924,-1920,-1918,-1911,-1900,-1886,-1876,-1875,-1884,-1897,-1905,-1901,
--1887,-1867,-1850,-1840,-1835,-1829,-1819,-1806,-1793,-1787,-1787,-1789,-1787,-1776,-1759,-1745,-1743,-1755,-1781,-1810,-1836,
--1852,-1858,-1857,-1852,-1844,-1836,-1826,-1816,-1804,-1792,-1781,-1776,-1778,-1790,-1810,-1832,-1851,-1861,-1858,-1847,-1834,
--1823,-1816,-1814,-1812,-1809,-1804,-1799,-1797,-1798,-1801,-1802,-1801,-1796,-1789,-1780,-1774,-1772,-1775,-1780,-1784,-1782,
--1774,-1760,-1744,-1730,-1719,-1708,-1694,-1672,-1644,-1616,-1593,-1575,-1557,-1532,-1494,-1444,-1388,-1335,-1294,-1268,-1258,
--1262,-1280,-1312,-1354,-1401,-1445,-1480,-1505,-1521,-1531,-1534,-1522,-1487,-1428,-1352,-1280,-1229,-1211,-1224,-1253,-1280,
--1292,-1289,-1277,-1268,-1267,-1275,-1289,-1302,-1314,-1325,-1338,-1352,-1367,-1379,-1388,-1396,-1403,-1413,-1425,-1439,-1452,
--1464,-1474,-1485,-1497,-1513,-1532,-1552,-1574,-1598,-1628,-1670,-1727,-1797,-1873,-1943,-1998,-2035,-2058,-2075,-2094,-2116,
--2137,-2154,-2164,-2170,-2176,-2185,-2195,-2202,-2203,-2200,-2198,-2201,-2211,-2223,-2232,-2235,-2233,-2233,-2236,-2244,-2254,
--2261,-2267,-2275,-2288,-2306,-2326,-2341,-2349,-2351,-2351,-2352,-2353,-2351,-2343,-2328,-2310,-2292,-2276,-2262,-2248,-2232,
--2218,-2206,-2199,-2195,-2191,-2184,-2174,-2165,-2160,-2161,-2166,-2174,-2181,-2186,-2191,-2197,-2201,-2202,-2200,-2193,-2185,
--2176,-2170,-2166,-2164,-2165,-2167,-2170,-2170,-2166,-2158,-2148,-2137,-2128,-2122,-2117,-2111,-2104,-2095,-2085,-2075,-2064,
--2053,-2040,-2028,-2017,-2008,-2003,-2003,-2007,-2018,-2036,-2059,-2086,-2109,-2125,-2130,-2124,-2108,-2087,-2063,-2038,-2015,
--1997,-1986,-1982,-1982,-1984,-1982,-1977,-1969,-1962,-1956,-1952,-1948,-1943,-1936,-1928,-1918,-1908,-1897,-1883,-1867,-1850,
--1835,-1823,-1814,-1806,-1797,-1788,-1780,-1776,-1776,-1780,-1784,-1786,-1783,-1777,-1767,-1757,-1746,-1737,-1730,-1727,-1729,
--1738,-1755,-1778,-1802,-1820,-1828,-1823,-1807,-1784,-1761,-1742,-1728,-1720,-1718,-1720,-1729,-1745,-1768,-1797,-1827,-1855,
--1876,-1889,-1891,-1884,-1872,-1858,-1845,-1836,-1831,-1830,-1832,-1835,-1841,-1847,-1854,-1858,-1858,-1854,-1846,-1838,-1832,
--1829,-1829,-1830,-1830,-1829,-1826,-1823,-1820,-1815,-1807,-1797,-1785,-1771,-1757,-1742,-1727,-1709,-1691,-1671,-1652,-1633,
--1614,-1595,-1576,-1560,-1544,-1529,-1514,-1497,-1479,-1459,-1440,-1423,-1406,-1390,-1375,-1358,-1342,-1324,-1306,-1288,-1271,
--1254,-1240,-1228,-1217,-1206,-1194,-1179,-1164,-1149,-1136,-1124,-1112,-1101,-1091,-1082,-1074,-1068,-1061,-1055,-1048,-1043,
--1039,-1038,-1038,-1038,-1037,-1034,-1031,-1030,-1030,-1033,-1036,-1038,-1040,-1041,-1042,-1045,-1049,-1053,-1057,-1060,-1062,
--1061,-1059,-1056,-1054,-1054,-1057,-1063,-1071,-1080,-1088,-1094,-1098,-1101,-1102,-1103,-1102,-1098,-1094,-1088,-1083,-1080,
--1079,-1078,-1077,-1075,-1075,-1077,-1083,-1092,-1101,-1108,-1110,-1108,-1104,-1100,-1097,-1097,-1096,-1093,-1086,-1076,-1062,
--1047,-1032,-1021,-1012,-1008,-1008,-1009,-1010,-1007,-1000,-988,-971,-952,-931,-911,-893,-876,-860,-844,-828,-814,
--802,-794,-788,-783,-777,-769,-760,-754,-752,-756,-761,-763,-760,-752,-740,-730,-721,-714,-706,-696,-683,
--670,-658,-648,-636,-621,-602,-580,-558,-538,-519,-500,-480,-460,-440,-424,-408,-393,-376,-357,-336,-316,
--297,-276,-252,-225,-198,-172,-150,-132,-115,-95,-72,-46,-21,2,24,47,71,95,118,139,158,
-176,195,215,237,261,289,321,355,389,419,445,468,489,509,524,533,532,524,511,496,478,
-460,452,473,542,670,847,1040,1210,1326,1385,1409,1428,1463,1510,1546,1545,1497,1417,1334,1271,1236,
-1215,1190,1148,1093,1041,1005,990,988,988,981,970,960,959,966,979,991,997,998,995,992,991,
-997,1013,1042,1083,1130,1176,1214,1241,1262,1281,1304,1331,1355,1370,1372,1358,1334,1305,1276,1253,1239,
-1233,1235,1243,1253,1260,1262,1255,1242,1226,1211,1202,1204,1213,1226,1235,1236,1226,1209,1189,1170,1154,
-1137,1117,1094,1070,1050,1036,1028,1020,1009,990,964,934,902,870,839,806,771,736,703,674,651,
-631,616,603,594,591,593,604,619,638,655,667,669,661,643,620,597,577,564,558,557,560,
-562,566,571,581,596,617,645,680,720,765,808,843,860,853,822,775,725,681,653,638,634,
-634,636,640,649,660,671,679,684,690,704,727,759,791,816,829,834,833,832,828,821,813,
-810,827,873,948,1037,1117,1168,1181,1163,1135,1116,1117,1137,1167,1197,1220,1236,1248,1259,1268,1275,
-1283,1293,1306,1322,1336,1346,1351,1358,1373,1402,1445,1495,1542,1581,1612,1640,1669,1700,1727,1745,1750,
-1747,1742,1743,1752,1768,1786,1801,1813,1823,1837,1855,1879,1905,1930,1951,1971,1988,2006,2024,2041,2058,
-2073,2087,2103,2122,2144,2168,2191,2212,2229,2245,2260,2276,2293,2309,2325,2342,2361,2384,2409,2432,2449,
-2458,2462,2465,2473,2487,2505,2523,2536,2545,2552,2559,2568,2578,2587,2594,2602,2611,2624,2639,2653,2665,
-2676,2687,2699,2712,2723,2731,2738,2745,2758,2775,2790,2799,2798,2788,2774,2762,2754,2748,2742,2733,2723,
-2715,2711,2710,2706,2698,2688,2678,2673,2671,2668,2661,2650,2640,2637,2642,2651,2647,2654,2652,2640,2620,
-2599,2580,2566,2554,2543,2534,2533,2541,2557,2572,2577,2568,2547,2523,2505,2499,2504,2516,2529,2539,2544,
-2547,2550,2554,2559,2564,2568,2572,2575,2580,2589,2602,2619,2635,2647,2656,2665,2678,2701,2731,2767,2802,
-2835,2872,2917,2973,3035,3092,3131,3149,3151,3151,3161,3186,3220,3254,3277,3288,3291,3293,3298,3305,3313,
-3319,3326,3339,3358,3379,3398,3409,3410,3407,3406,3413,3426,3441,3451,3454,3454,3457,3468,3487,3512,3535,
-3550,3558,3560,3560,3564,3572,3581,3591,3600,3611,3626,3648,3674,3699,3717,3725,3727,3730,3742,3765,3791,
-3806,3797,3755,3690,3623,3578,3577,3625,3708,3803,3884,3935,3953,3948,3934,3921,3914,3911,3908,3903,3900,
-3902,3910,3925,3941,3959,3977,4001,4030,4065,4102,4134,4161,4186,4213,4248,4290,4336,4377,4409,4433,4451,
-4470,4493,4522,4552,4582,4607,4627,4643,4657,4668,4675,4679,4681,4685,4692,4705,4721,4737,4749,4752,4749,
-4743,4739,4739,4743,4746,4743,4734,4720,4705,4694,4687,4683,4677,4667,4652,4634,4613,4591,4569,4549,4532,
-4521,4515,4511,4504,4493,4475,4455,4436,4422,4412,4405,4399,4395,4395,4400,4408,4412,4407,4388,4361,4332,
-4312,4306,4312,4319,4318,4298,4261,4212,4163,4124,4099,4087,4082,4076,4066,4049,4026,3999,3970,3942,3916,
-3891,3867,3845,3824,3804,3787,3773,3764,3758,3755,3752,3749,3743,3734,3724,3712,3699,3685,3673,3664,3660,
-3659,3660,3662,3662,3659,3654,3647,3638,3627,3616,3609,3607,3609,3610,3602,3578,3539,3492,3455,3445,3474,
-3542,3635,3735,3820,3875,3896,3888,3864,3834,3808,3789,3779,3779,3785,3793,3797,3790,3768,3731,3688,3652,
-3630,3624,3624,3613,3578,3514,3427,3335,3253,3191,3147,3116,3087,3056,3022,2987,2954,2923,2892,2860,2826,
-2791,2759,2727,2695,2661,2623,2581,2539,2499,2462,2429,2397,2363,2327,2286,2244,2200,2157,2116,2078,2043,
-2009,1977,1946,1914,1880,1843,1803,1761,1721,1682,1646,1610,1574,1536,1499,1464,1434,1409,1386,1360,1328,
-1288,1246,1204,1168,1138,1110,1081,1048,1010,971,933,897,861,823,782,741,700,663,629,596,559,
-519,477,437,399,366,333,299,261,221,182,145,110,76,41,5,-30,-63,-93,-122,-153,-185,
--221,-257,-292,-327,-362,-397,-433,-467,-500,-532,-564,-597,-630,-663,-694,-722,-750,-781,-817,-857,-896,
--931,-962,-992,-1023,-1056,-1089,-1120,-1147,-1170,-1195,-1222,-1253,-1284,-1313,-1339,-1363,-1390,-1421,-1454,-1485,-1512,
--1534,-1557,-1583,-1614,-1648,-1681,-1709,-1733,-1756,-1781,-1810,-1841,-1870,-1896,-1917,-1935,-1951,-1965,-1978,-1988,-1996,
--2005,-2016,-2030,-2045,-2060,-2074,-2088,-2101,-2115,-2129,-2140,-2150,-2158,-2168,-2180,-2196,-2213,-2230,-2245,-2258,-2270,
--2282,-2293,-2302,-2310,-2317,-2326,-2336,-2347,-2356,-2361,-2362,-2362,-2365,-2373,-2385,-2394,-2397,-2390,-2375,-2357,-2339,
--2326,-2316,-2306,-2295,-2284,-2274,-2266,-2259,-2251,-2241,-2229,-2217,-2208,-2201,-2196,-2190,-2182,-2172,-2162,-2155,-2148,
--2141,-2133,-2124,-2114,-2106,-2100,-2094,-2089,-2082,-2073,-2064,-2055,-2045,-2036,-2028,-2021,-2015,-2009,-1999,-1986,-1971,
--1956,-1946,-1942,-1940,-1935,-1923,-1905,-1889,-1881,-1885,-1898,-1910,-1914,-1905,-1887,-1869,-1856,-1848,-1842,-1833,-1820,
--1807,-1798,-1796,-1799,-1798,-1791,-1776,-1762,-1756,-1764,-1787,-1817,-1846,-1867,-1877,-1878,-1872,-1863,-1853,-1843,-1832,
--1820,-1808,-1798,-1794,-1797,-1810,-1830,-1852,-1869,-1876,-1872,-1861,-1849,-1842,-1840,-1841,-1841,-1837,-1830,-1824,-1823,
--1829,-1839,-1846,-1847,-1838,-1824,-1811,-1802,-1800,-1802,-1803,-1800,-1791,-1779,-1769,-1764,-1764,-1762,-1754,-1736,-1710,
--1681,-1654,-1630,-1604,-1570,-1524,-1470,-1416,-1375,-1354,-1353,-1367,-1389,-1413,-1439,-1470,-1505,-1541,-1572,-1597,-1615,
--1631,-1645,-1651,-1639,-1600,-1535,-1456,-1385,-1341,-1332,-1351,-1380,-1401,-1405,-1394,-1377,-1367,-1367,-1377,-1388,-1399,
--1406,-1414,-1424,-1438,-1452,-1465,-1475,-1481,-1485,-1490,-1498,-1510,-1526,-1544,-1564,-1584,-1604,-1621,-1638,-1655,-1673,
--1698,-1733,-1784,-1850,-1927,-2005,-2074,-2123,-2153,-2169,-2182,-2197,-2218,-2239,-2254,-2262,-2263,-2264,-2270,-2279,-2288,
--2293,-2294,-2292,-2294,-2301,-2312,-2324,-2333,-2339,-2344,-2349,-2356,-2361,-2365,-2369,-2374,-2383,-2398,-2414,-2428,-2436,
--2438,-2437,-2436,-2434,-2429,-2419,-2404,-2385,-2366,-2350,-2335,-2322,-2308,-2295,-2285,-2278,-2273,-2267,-2259,-2248,-2236,
--2226,-2221,-2222,-2227,-2235,-2244,-2253,-2261,-2268,-2272,-2272,-2267,-2258,-2247,-2235,-2225,-2219,-2218,-2220,-2223,-2224,
--2221,-2213,-2204,-2196,-2191,-2188,-2184,-2178,-2169,-2156,-2142,-2128,-2115,-2103,-2092,-2080,-2069,-2058,-2048,-2039,-2032,
--2030,-2036,-2051,-2074,-2101,-2127,-2148,-2160,-2163,-2156,-2140,-2117,-2090,-2063,-2041,-2025,-2015,-2008,-2001,-1995,-1990,
--1988,-1990,-1993,-1994,-1990,-1982,-1971,-1959,-1948,-1938,-1926,-1913,-1898,-1884,-1871,-1861,-1851,-1841,-1830,-1818,-1809,
--1804,-1804,-1808,-1812,-1815,-1814,-1808,-1799,-1788,-1776,-1764,-1754,-1748,-1748,-1755,-1769,-1788,-1809,-1828,-1841,-1847,
--1847,-1841,-1831,-1817,-1799,-1779,-1759,-1743,-1735,-1739,-1755,-1781,-1813,-1847,-1877,-1900,-1913,-1917,-1913,-1903,-1889,
--1875,-1861,-1851,-1845,-1845,-1848,-1854,-1858,-1860,-1857,-1852,-1847,-1843,-1842,-1841,-1840,-1837,-1833,-1828,-1824,-1820,
--1815,-1810,-1803,-1795,-1784,-1772,-1757,-1740,-1719,-1697,-1675,-1654,-1636,-1619,-1605,-1591,-1578,-1563,-1547,-1528,-1508,
--1488,-1469,-1451,-1435,-1420,-1405,-1389,-1374,-1359,-1344,-1328,-1312,-1295,-1279,-1264,-1252,-1241,-1231,-1220,-1206,-1191,
--1176,-1160,-1145,-1131,-1118,-1106,-1097,-1088,-1081,-1074,-1067,-1060,-1054,-1050,-1049,-1048,-1047,-1045,-1041,-1038,-1037,
--1039,-1042,-1045,-1047,-1048,-1048,-1048,-1050,-1054,-1059,-1065,-1071,-1076,-1079,-1079,-1078,-1076,-1076,-1078,-1082,-1089,
--1095,-1100,-1105,-1110,-1115,-1121,-1126,-1127,-1125,-1119,-1113,-1106,-1102,-1099,-1095,-1090,-1085,-1081,-1082,-1086,-1094,
--1101,-1105,-1106,-1105,-1103,-1104,-1107,-1110,-1110,-1106,-1097,-1084,-1068,-1051,-1033,-1018,-1005,-998,-996,-997,-1000,
--1002,-999,-991,-978,-962,-945,-928,-912,-897,-883,-869,-856,-843,-831,-821,-812,-804,-795,-786,-778,-773,
--773,-776,-780,-780,-775,-765,-753,-742,-734,-729,-723,-715,-705,-692,-679,-666,-651,-634,-616,-596,-577,
--559,-542,-523,-503,-483,-465,-451,-439,-426,-410,-390,-367,-345,-323,-301,-278,-252,-225,-199,-175,-154,
--135,-114,-91,-65,-38,-13,9,32,54,77,101,123,145,165,183,201,220,242,269,301,336,
-371,404,433,459,482,503,518,527,530,527,520,509,491,469,451,459,511,622,785,974,1153,
-1291,1376,1419,1443,1466,1488,1497,1477,1423,1348,1273,1216,1182,1160,1134,1097,1050,1004,970,951,944,
-940,935,931,932,942,960,979,993,1000,1000,997,994,994,1003,1021,1050,1091,1138,1184,1222,1250,
-1269,1285,1303,1326,1351,1373,1387,1390,1384,1372,1358,1343,1328,1314,1299,1284,1269,1253,1236,1218,1200,
-1182,1169,1163,1167,1179,1192,1200,1201,1195,1184,1175,1169,1165,1158,1144,1124,1101,1080,1065,1053,1039,
-1019,990,956,921,888,860,832,802,767,731,697,671,653,641,632,624,615,609,610,618,633,
-652,669,681,685,680,666,644,619,592,567,547,533,526,525,529,535,544,555,569,588,613,
-647,689,735,775,798,797,771,727,678,638,616,612,620,633,647,660,674,689,703,715,725,
-735,750,774,807,844,879,906,924,935,937,930,911,887,869,874,915,994,1098,1201,1278,1315,
-1313,1289,1263,1249,1253,1270,1290,1309,1323,1334,1344,1352,1358,1361,1365,1369,1374,1378,1382,1385,1390,
-1403,1427,1461,1502,1546,1591,1634,1676,1714,1746,1766,1773,1770,1763,1760,1764,1777,1793,1809,1821,1831,
-1842,1857,1877,1899,1921,1942,1961,1979,1998,2018,2038,2056,2072,2084,2095,2106,2121,2140,2163,2187,2209,
-2228,2243,2255,2267,2279,2291,2305,2320,2339,2363,2389,2414,2433,2443,2447,2450,2456,2467,2482,2496,2506,
-2513,2518,2526,2537,2550,2564,2576,2589,2603,2620,2638,2656,2670,2682,2691,2701,2710,2718,2724,2729,2736,
-2750,2768,2788,2803,2809,2805,2795,2784,2775,2767,2758,2748,2738,2731,2728,2725,2721,2712,2701,2690,2683,
-2680,2676,2668,2656,2644,2637,2639,2647,2638,2638,2636,2628,2615,2602,2592,2587,2586,2587,2589,2593,2599,
-2607,2611,2608,2595,2576,2554,2537,2528,2528,2533,2539,2545,2548,2552,2556,2561,2568,2575,2582,2589,2596,
-2605,2615,2626,2637,2647,2657,2671,2690,2719,2756,2797,2838,2875,2910,2948,2991,3038,3083,3118,3138,3145,
-3149,3161,3186,3223,3261,3290,3307,3313,3315,3320,3328,3338,3347,3356,3370,3389,3413,3437,3454,3460,3458,
-3455,3456,3466,3480,3494,3502,3506,3509,3516,3532,3553,3574,3591,3600,3601,3599,3597,3598,3601,3607,3615,
-3626,3642,3662,3683,3701,3712,3714,3713,3716,3732,3761,3797,3824,3824,3788,3722,3645,3583,3562,3590,3661,
-3753,3841,3905,3938,3943,3932,3915,3900,3888,3880,3876,3875,3880,3890,3903,3918,3933,3951,3974,4003,4038,
-4075,4109,4141,4169,4198,4232,4272,4315,4357,4394,4423,4447,4467,4489,4514,4542,4570,4597,4621,4641,4661,
-4681,4706,4733,4760,4781,4795,4798,4795,4788,4780,4772,4764,4753,4740,4728,4719,4715,4715,4718,4719,4718,
-4716,4715,4715,4717,4716,4710,4695,4672,4643,4613,4584,4559,4542,4532,4526,4519,4508,4492,4470,4449,4431,
-4418,4408,4399,4388,4378,4372,4372,4378,4384,4383,4372,4352,4329,4311,4302,4300,4297,4286,4262,4228,4191,
-4158,4134,4118,4106,4093,4078,4059,4038,4014,3990,3963,3935,3906,3879,3855,3833,3813,3793,3773,3754,3738,
-3726,3719,3716,3715,3715,3711,3704,3691,3676,3660,3648,3642,3641,3642,3640,3634,3624,3612,3602,3596,3593,
-3590,3586,3581,3575,3568,3559,3546,3527,3502,3477,3459,3456,3469,3499,3541,3589,3639,3687,3731,3768,3792,
-3801,3796,3781,3763,3752,3754,3768,3787,3800,3796,3773,3736,3695,3663,3646,3642,3640,3626,3590,3529,3449,
-3361,3276,3201,3138,3086,3040,3000,2964,2932,2905,2880,2856,2831,2806,2779,2750,2717,2678,2634,2587,2539,
-2494,2454,2419,2387,2356,2322,2286,2246,2205,2164,2124,2085,2047,2011,1976,1942,1910,1877,1841,1803,1761,
-1719,1679,1641,1606,1573,1540,1508,1479,1453,1429,1406,1378,1343,1301,1255,1212,1175,1144,1116,1087,1053,
-1015,976,939,904,871,835,795,753,711,673,639,605,569,530,488,449,413,381,350,316,278,
-237,197,160,127,95,63,28,-7,-41,-74,-105,-136,-170,-206,-243,-279,-313,-346,-379,-412,-445,
--478,-511,-544,-577,-609,-640,-669,-696,-725,-757,-793,-832,-871,-906,-938,-969,-1000,-1033,-1066,-1096,-1123,
--1147,-1172,-1200,-1231,-1262,-1292,-1318,-1343,-1370,-1400,-1431,-1461,-1487,-1511,-1535,-1565,-1598,-1634,-1668,-1697,-1721,
--1744,-1769,-1797,-1827,-1855,-1879,-1899,-1915,-1931,-1945,-1958,-1971,-1982,-1993,-2006,-2021,-2037,-2053,-2068,-2082,-2095,
--2109,-2121,-2132,-2141,-2150,-2161,-2173,-2188,-2204,-2219,-2232,-2245,-2257,-2269,-2279,-2288,-2297,-2306,-2317,-2331,-2346,
--2357,-2363,-2365,-2367,-2372,-2381,-2392,-2399,-2398,-2387,-2371,-2353,-2338,-2327,-2318,-2308,-2297,-2285,-2275,-2268,-2262,
--2256,-2249,-2239,-2229,-2220,-2213,-2205,-2197,-2188,-2180,-2174,-2170,-2165,-2159,-2151,-2141,-2132,-2125,-2120,-2114,-2107,
--2099,-2089,-2081,-2073,-2066,-2059,-2051,-2043,-2036,-2030,-2023,-2012,-1998,-1983,-1972,-1968,-1967,-1964,-1952,-1932,-1911,
--1896,-1894,-1904,-1919,-1928,-1925,-1910,-1892,-1876,-1865,-1857,-1848,-1835,-1821,-1811,-1808,-1811,-1813,-1809,-1798,-1783,
--1775,-1780,-1800,-1829,-1860,-1885,-1899,-1904,-1902,-1897,-1890,-1881,-1869,-1855,-1842,-1831,-1827,-1830,-1842,-1859,-1877,
--1891,-1896,-1893,-1884,-1875,-1870,-1869,-1868,-1864,-1857,-1847,-1841,-1843,-1855,-1871,-1885,-1890,-1885,-1873,-1861,-1853,
--1849,-1845,-1837,-1823,-1806,-1791,-1785,-1788,-1795,-1798,-1792,-1776,-1755,-1733,-1710,-1682,-1642,-1586,-1520,-1459,-1420,
--1414,-1440,-1486,-1533,-1568,-1587,-1594,-1600,-1608,-1622,-1639,-1659,-1682,-1711,-1739,-1757,-1749,-1709,-1639,-1558,-1489,
--1450,-1445,-1464,-1488,-1502,-1500,-1487,-1473,-1465,-1464,-1468,-1472,-1475,-1480,-1490,-1506,-1525,-1541,-1552,-1556,-1556,
--1556,-1560,-1568,-1581,-1599,-1621,-1646,-1672,-1699,-1723,-1746,-1769,-1794,-1826,-1868,-1923,-1991,-2065,-2138,-2199,-2241,
--2264,-2274,-2281,-2292,-2310,-2330,-2344,-2349,-2348,-2344,-2346,-2353,-2365,-2375,-2381,-2382,-2384,-2389,-2398,-2411,-2424,
--2434,-2442,-2449,-2454,-2458,-2461,-2464,-2468,-2475,-2485,-2498,-2509,-2515,-2516,-2513,-2510,-2506,-2501,-2493,-2480,-2464,
--2446,-2429,-2414,-2400,-2387,-2375,-2364,-2355,-2347,-2340,-2332,-2321,-2308,-2297,-2289,-2286,-2289,-2296,-2305,-2314,-2322,
--2328,-2332,-2333,-2330,-2324,-2314,-2300,-2287,-2276,-2270,-2269,-2271,-2272,-2270,-2265,-2258,-2253,-2249,-2247,-2243,-2236,
--2224,-2210,-2195,-2181,-2168,-2155,-2142,-2130,-2119,-2109,-2099,-2088,-2077,-2067,-2060,-2059,-2067,-2084,-2107,-2134,-2160,
--2181,-2195,-2198,-2190,-2172,-2147,-2121,-2096,-2073,-2053,-2034,-2020,-2011,-2008,-2011,-2017,-2020,-2019,-2012,-2002,-1991,
--1982,-1974,-1965,-1954,-1941,-1928,-1915,-1906,-1897,-1888,-1878,-1865,-1853,-1844,-1839,-1837,-1839,-1840,-1841,-1839,-1836,
--1831,-1826,-1818,-1810,-1801,-1792,-1786,-1784,-1789,-1799,-1814,-1832,-1848,-1860,-1868,-1871,-1867,-1856,-1839,-1819,-1796,
--1777,-1765,-1762,-1770,-1787,-1810,-1836,-1862,-1885,-1904,-1917,-1924,-1924,-1919,-1908,-1896,-1885,-1875,-1869,-1864,-1860,
--1856,-1852,-1849,-1848,-1849,-1851,-1852,-1850,-1846,-1841,-1834,-1827,-1821,-1815,-1809,-1802,-1795,-1787,-1777,-1764,-1747,
--1728,-1706,-1683,-1662,-1643,-1628,-1615,-1604,-1593,-1579,-1563,-1543,-1521,-1499,-1479,-1460,-1444,-1428,-1413,-1398,-1384,
--1371,-1359,-1347,-1334,-1320,-1305,-1290,-1276,-1264,-1252,-1240,-1227,-1214,-1200,-1185,-1169,-1154,-1139,-1125,-1113,-1103,
--1094,-1085,-1077,-1069,-1063,-1059,-1057,-1055,-1053,-1050,-1047,-1045,-1046,-1049,-1053,-1056,-1058,-1058,-1058,-1059,-1060,
--1063,-1068,-1073,-1080,-1086,-1091,-1095,-1096,-1096,-1096,-1099,-1103,-1109,-1114,-1118,-1122,-1126,-1133,-1141,-1148,-1152,
--1152,-1148,-1142,-1138,-1134,-1132,-1128,-1123,-1117,-1112,-1110,-1111,-1112,-1112,-1110,-1107,-1105,-1107,-1112,-1119,-1122,
--1120,-1113,-1102,-1089,-1076,-1062,-1048,-1032,-1017,-1004,-995,-991,-991,-992,-991,-987,-980,-969,-957,-944,-930,
--917,-905,-893,-880,-867,-854,-842,-831,-821,-812,-804,-797,-793,-792,-793,-794,-790,-782,-771,-758,-748,
--742,-738,-735,-730,-721,-709,-695,-680,-665,-649,-632,-615,-598,-582,-565,-546,-526,-507,-490,-478,-468,
--457,-442,-423,-399,-374,-350,-326,-302,-277,-251,-225,-201,-180,-159,-138,-114,-87,-60,-34,-9,13,
-36,59,84,109,133,155,175,193,212,233,258,288,321,355,389,421,451,477,499,515,526,
-531,532,530,521,503,477,452,449,491,590,744,928,1106,1247,1335,1377,1393,1401,1409,1411,1394,
-1354,1296,1233,1179,1138,1107,1079,1046,1010,976,951,936,927,923,921,924,934,952,974,993,1005,
-1007,1005,1002,1001,1006,1017,1036,1063,1099,1141,1184,1220,1247,1265,1281,1299,1322,1348,1372,1389,1397,
-1397,1394,1392,1390,1387,1376,1355,1324,1287,1250,1218,1192,1175,1163,1156,1154,1157,1164,1172,1178,1180,
-1180,1180,1181,1182,1181,1172,1153,1126,1097,1072,1052,1037,1019,995,962,924,887,856,829,803,774,
-741,706,676,654,643,638,635,629,622,615,612,615,625,637,647,653,654,649,638,622,599,
-573,546,522,505,496,495,501,511,522,532,542,552,566,585,610,639,667,684,684,665,632,
-596,569,556,560,576,597,619,639,659,678,696,710,722,736,756,787,830,878,925,965,993,
-1011,1020,1017,1003,980,959,953,979,1044,1140,1248,1343,1406,1430,1424,1404,1385,1378,1382,1395,1410,
-1425,1437,1448,1456,1460,1459,1454,1445,1435,1426,1419,1416,1418,1425,1439,1461,1494,1538,1592,1652,1708,
-1753,1778,1783,1773,1761,1755,1761,1778,1801,1822,1836,1846,1855,1866,1882,1902,1921,1940,1956,1971,1987,
-2003,2020,2037,2052,2066,2079,2091,2104,2117,2134,2153,2175,2197,2216,2233,2248,2260,2271,2281,2292,2304,
-2321,2342,2367,2392,2413,2427,2436,2441,2448,2458,2470,2482,2491,2497,2504,2514,2527,2544,2560,2575,2590,
-2607,2626,2646,2666,2681,2693,2702,2709,2716,2722,2725,2728,2732,2742,2759,2779,2798,2810,2813,2808,2799,
-2790,2780,2770,2759,2750,2742,2738,2735,2730,2721,2709,2697,2690,2686,2684,2680,2671,2658,2646,2639,2638,
-2639,2635,2633,2630,2624,2617,2614,2614,2619,2626,2632,2635,2634,2630,2623,2613,2600,2586,2574,2564,2559,
-2558,2559,2561,2563,2566,2569,2574,2579,2584,2588,2592,2596,2603,2613,2628,2643,2659,2673,2688,2708,2735,
-2773,2816,2861,2900,2932,2959,2986,3016,3048,3076,3096,3106,3112,3122,3143,3175,3211,3244,3267,3279,3287,
-3297,3312,3331,3348,3362,3375,3391,3413,3439,3464,3484,3495,3501,3506,3514,3527,3540,3550,3556,3561,3570,
-3583,3601,3619,3633,3641,3644,3644,3645,3646,3648,3648,3650,3655,3666,3682,3700,3714,3717,3711,3701,3698,
-3711,3743,3786,3824,3836,3811,3749,3668,3594,3554,3562,3617,3700,3788,3859,3902,3916,3910,3894,3875,3858,
-3846,3842,3845,3855,3871,3887,3901,3913,3927,3946,3973,4008,4046,4084,4118,4149,4180,4214,4252,4291,4330,
-4365,4397,4426,4454,4481,4509,4537,4565,4592,4615,4635,4653,4673,4704,4749,4807,4870,4921,4949,4946,4916,
-4871,4826,4790,4766,4749,4735,4720,4706,4696,4693,4694,4697,4700,4702,4706,4714,4724,4731,4729,4714,4687,
-4651,4614,4582,4558,4541,4529,4515,4499,4480,4461,4448,4443,4445,4449,4447,4432,4406,4374,4345,4328,4325,
-4332,4341,4344,4338,4326,4313,4302,4292,4280,4262,4238,4212,4189,4171,4157,4143,4125,4101,4072,4044,4020,
-4000,3982,3961,3935,3905,3874,3846,3822,3802,3784,3766,3746,3726,3707,3692,3682,3677,3676,3674,3668,3658,
-3643,3628,3616,3609,3606,3604,3598,3587,3572,3557,3547,3545,3547,3551,3553,3550,3543,3531,3517,3499,3481,
-3464,3453,3448,3448,3449,3448,3447,3452,3473,3519,3588,3671,3749,3804,3829,3825,3805,3784,3775,3783,3801,
-3820,3826,3815,3787,3748,3710,3680,3662,3652,3640,3617,3575,3512,3433,3344,3256,3174,3102,3041,2990,2946,
-2910,2880,2857,2838,2821,2804,2783,2758,2726,2688,2646,2599,2552,2505,2460,2418,2380,2344,2308,2272,2235,
-2198,2162,2127,2092,2056,2017,1977,1937,1899,1863,1829,1794,1757,1718,1679,1641,1607,1576,1548,1521,1494,
-1468,1441,1413,1381,1345,1304,1261,1220,1182,1150,1119,1087,1052,1013,974,937,903,870,835,798,758,
-718,681,647,612,576,538,497,459,425,393,362,327,289,249,210,174,142,112,81,47,11,
--23,-57,-89,-122,-157,-193,-230,-264,-296,-326,-356,-387,-420,-454,-488,-524,-558,-590,-621,-648,-675,
--703,-734,-769,-807,-845,-881,-914,-946,-977,-1010,-1043,-1074,-1101,-1127,-1153,-1181,-1212,-1245,-1276,-1304,-1332,
--1359,-1387,-1415,-1443,-1470,-1496,-1524,-1555,-1589,-1624,-1656,-1684,-1708,-1731,-1755,-1782,-1811,-1838,-1862,-1881,-1897,
--1911,-1925,-1938,-1952,-1967,-1983,-2001,-2018,-2035,-2051,-2066,-2080,-2094,-2107,-2118,-2127,-2135,-2144,-2155,-2168,-2184,
--2199,-2213,-2225,-2237,-2249,-2261,-2272,-2282,-2292,-2303,-2317,-2333,-2349,-2361,-2368,-2371,-2375,-2381,-2391,-2401,-2406,
--2402,-2390,-2372,-2355,-2342,-2333,-2325,-2315,-2304,-2292,-2281,-2274,-2269,-2264,-2258,-2251,-2244,-2238,-2231,-2223,-2213,
--2203,-2195,-2191,-2189,-2187,-2182,-2173,-2164,-2156,-2150,-2145,-2138,-2128,-2116,-2105,-2098,-2094,-2091,-2086,-2077,-2068,
--2059,-2052,-2046,-2037,-2025,-2011,-2001,-1997,-1998,-1998,-1989,-1969,-1943,-1921,-1912,-1917,-1930,-1941,-1940,-1928,-1911,
--1895,-1884,-1876,-1867,-1854,-1839,-1826,-1820,-1821,-1824,-1822,-1813,-1800,-1793,-1798,-1817,-1848,-1880,-1908,-1927,-1936,
--1938,-1935,-1929,-1919,-1905,-1891,-1878,-1869,-1866,-1870,-1880,-1892,-1905,-1915,-1921,-1921,-1916,-1909,-1900,-1892,-1883,
--1874,-1864,-1855,-1853,-1860,-1874,-1894,-1911,-1922,-1924,-1920,-1914,-1909,-1902,-1893,-1877,-1857,-1836,-1821,-1815,-1817,
--1821,-1822,-1818,-1811,-1804,-1796,-1780,-1746,-1687,-1610,-1532,-1477,-1466,-1501,-1569,-1643,-1698,-1723,-1719,-1701,-1684,
--1678,-1682,-1696,-1717,-1746,-1782,-1817,-1838,-1829,-1785,-1714,-1636,-1574,-1544,-1546,-1565,-1584,-1591,-1586,-1574,-1563,
--1555,-1548,-1538,-1527,-1520,-1524,-1542,-1571,-1600,-1621,-1628,-1625,-1619,-1616,-1621,-1634,-1651,-1671,-1694,-1719,-1746,
--1776,-1807,-1842,-1880,-1922,-1969,-2022,-2080,-2141,-2203,-2261,-2309,-2343,-2361,-2368,-2372,-2379,-2392,-2408,-2421,-2427,
--2426,-2422,-2422,-2429,-2441,-2455,-2465,-2471,-2476,-2481,-2491,-2503,-2515,-2525,-2533,-2539,-2544,-2549,-2553,-2555,-2557,
--2560,-2565,-2572,-2578,-2583,-2583,-2581,-2578,-2575,-2572,-2567,-2558,-2546,-2530,-2513,-2497,-2482,-2468,-2456,-2443,-2431,
--2421,-2412,-2403,-2394,-2384,-2374,-2366,-2362,-2362,-2367,-2373,-2379,-2383,-2385,-2385,-2384,-2384,-2381,-2374,-2363,-2349,
--2335,-2325,-2319,-2318,-2318,-2317,-2314,-2308,-2303,-2298,-2294,-2288,-2280,-2269,-2257,-2245,-2233,-2221,-2208,-2194,-2180,
--2167,-2156,-2147,-2138,-2128,-2115,-2102,-2091,-2086,-2089,-2100,-2120,-2145,-2173,-2198,-2216,-2224,-2222,-2212,-2196,-2176,
--2153,-2128,-2101,-2074,-2051,-2035,-2026,-2025,-2026,-2027,-2027,-2024,-2021,-2017,-2011,-2003,-1992,-1979,-1965,-1954,-1946,
--1940,-1934,-1926,-1915,-1903,-1892,-1883,-1878,-1875,-1873,-1871,-1869,-1867,-1866,-1865,-1864,-1860,-1854,-1844,-1832,-1822,
--1815,-1813,-1816,-1822,-1828,-1834,-1838,-1842,-1845,-1848,-1850,-1848,-1843,-1834,-1824,-1814,-1806,-1802,-1803,-1809,-1820,
--1838,-1860,-1885,-1909,-1930,-1945,-1951,-1950,-1944,-1933,-1920,-1906,-1892,-1878,-1867,-1860,-1856,-1855,-1856,-1857,-1857,
--1855,-1852,-1847,-1841,-1834,-1825,-1815,-1805,-1795,-1786,-1776,-1765,-1752,-1736,-1718,-1697,-1676,-1656,-1638,-1622,-1610,
--1598,-1587,-1573,-1556,-1536,-1515,-1494,-1474,-1456,-1439,-1423,-1408,-1393,-1380,-1368,-1357,-1345,-1333,-1319,-1305,-1290,
--1276,-1262,-1249,-1237,-1225,-1213,-1201,-1187,-1172,-1157,-1142,-1129,-1118,-1108,-1099,-1090,-1082,-1076,-1071,-1067,-1063,
--1059,-1056,-1053,-1053,-1056,-1059,-1063,-1065,-1066,-1067,-1068,-1070,-1072,-1075,-1078,-1082,-1086,-1092,-1099,-1105,-1109,
--1111,-1113,-1117,-1122,-1128,-1134,-1139,-1143,-1147,-1153,-1160,-1166,-1169,-1170,-1167,-1164,-1162,-1161,-1160,-1159,-1157,
--1154,-1151,-1149,-1146,-1141,-1133,-1125,-1117,-1114,-1117,-1124,-1131,-1133,-1129,-1119,-1108,-1098,-1090,-1083,-1073,-1060,
--1044,-1028,-1014,-1003,-996,-992,-988,-983,-977,-970,-961,-951,-941,-931,-920,-909,-897,-883,-868,-853,-841,
--830,-821,-815,-809,-805,-802,-800,-797,-792,-783,-772,-761,-752,-748,-746,-745,-740,-732,-721,-707,-693,
--679,-665,-650,-634,-617,-601,-583,-566,-548,-531,-516,-503,-492,-481,-466,-446,-423,-398,-372,-348,-323,
--298,-273,-249,-227,-206,-186,-165,-140,-113,-85,-58,-32,-9,14,37,61,86,111,134,156,178,
-200,224,251,280,312,344,377,410,442,470,493,509,521,528,534,536,530,511,481,450,439,
-472,564,711,889,1063,1198,1278,1309,1311,1306,1308,1315,1316,1302,1268,1220,1167,1116,1072,1033,1001,
-974,954,941,934,931,930,933,944,962,986,1009,1025,1031,1029,1024,1022,1025,1033,1046,1062,1085,
-1114,1148,1183,1215,1239,1257,1274,1293,1317,1342,1361,1370,1369,1364,1363,1371,1386,1401,1404,1388,1352,
-1304,1254,1213,1186,1173,1168,1167,1166,1164,1165,1168,1174,1183,1192,1201,1207,1207,1197,1175,1142,1104,
-1066,1036,1012,993,972,944,908,868,829,795,767,742,716,689,664,643,630,624,619,613,602,
-588,574,564,559,558,557,552,542,529,513,497,480,462,443,425,412,406,409,419,435,454,
-471,485,494,499,501,503,508,517,529,538,540,533,518,501,489,487,496,513,535,557,580,
-603,626,648,668,688,712,748,798,861,927,986,1029,1055,1067,1071,1072,1070,1063,1052,1047,1059,
-1100,1171,1264,1361,1440,1487,1502,1492,1473,1458,1455,1463,1479,1498,1516,1532,1545,1553,1554,1546,1529,
-1508,1487,1470,1459,1454,1453,1456,1466,1490,1532,1593,1662,1726,1769,1783,1774,1754,1740,1744,1767,1800,
-1833,1855,1866,1871,1877,1888,1904,1922,1939,1954,1968,1982,1998,2012,2023,2033,2041,2052,2067,2084,2102,
-2118,2133,2148,2165,2183,2203,2223,2241,2256,2269,2280,2291,2302,2316,2333,2355,2378,2399,2416,2429,2439,
-2449,2462,2475,2489,2499,2507,2515,2524,2537,2551,2567,2582,2597,2613,2632,2652,2671,2686,2698,2708,2717,
-2725,2731,2734,2734,2734,2739,2749,2766,2783,2796,2802,2801,2795,2788,2782,2775,2767,2759,2752,2747,2743,
-2738,2729,2717,2705,2696,2690,2688,2686,2680,2669,2656,2645,2639,2657,2657,2660,2661,2659,2655,2650,2648,
-2649,2652,2652,2649,2640,2629,2617,2608,2602,2598,2596,2593,2591,2589,2587,2587,2587,2588,2589,2591,2592,
-2593,2593,2593,2596,2604,2618,2637,2659,2678,2694,2708,2726,2753,2791,2838,2884,2923,2948,2964,2974,2987,
-3003,3023,3042,3059,3076,3098,3126,3158,3189,3213,3229,3240,3253,3272,3298,3326,3350,3367,3380,3394,3412,
-3435,3458,3479,3496,3511,3525,3540,3554,3564,3572,3579,3589,3604,3624,3643,3657,3663,3665,3667,3673,3683,
-3694,3701,3704,3706,3710,3721,3735,3746,3746,3733,3713,3697,3698,3722,3764,3807,3830,3816,3764,3687,3609,
-3557,3549,3587,3656,3736,3804,3849,3868,3867,3854,3836,3819,3804,3798,3802,3817,3841,3866,3887,3902,3912,
-3926,3948,3980,4018,4058,4093,4125,4155,4188,4224,4261,4297,4330,4359,4388,4419,4452,4486,4519,4550,4578,
-4605,4627,4646,4661,4682,4717,4775,4855,4943,5017,5053,5043,4992,4920,4852,4804,4782,4779,4782,4784,4781,
-4775,4766,4753,4736,4715,4694,4682,4681,4691,4703,4707,4696,4669,4634,4601,4577,4563,4552,4536,4510,4476,
-4444,4426,4429,4453,4487,4516,4523,4500,4450,4386,4327,4288,4274,4283,4300,4316,4323,4320,4311,4300,4288,
-4273,4255,4235,4214,4197,4184,4171,4154,4128,4096,4061,4030,4009,3994,3981,3964,3937,3903,3865,3831,3803,
-3783,3769,3757,3744,3727,3707,3686,3667,3652,3642,3634,3627,3617,3605,3592,3580,3573,3569,3565,3558,3546,
-3532,3519,3511,3510,3513,3517,3519,3517,3513,3504,3492,3476,3458,3443,3434,3432,3434,3432,3421,3402,3389,
-3397,3440,3519,3623,3729,3813,3861,3876,3868,3854,3848,3853,3865,3876,3877,3863,3837,3800,3760,3720,3684,
-3655,3629,3602,3568,3522,3462,3392,3317,3243,3173,3109,3051,2996,2946,2901,2863,2832,2805,2779,2751,2719,
-2685,2650,2616,2583,2548,2510,2468,2425,2381,2338,2297,2257,2218,2181,2147,2116,2086,2055,2020,1980,1936,
-1891,1851,1815,1783,1751,1717,1680,1643,1608,1578,1552,1527,1500,1470,1437,1402,1367,1331,1295,1259,1222,
-1186,1151,1117,1082,1046,1009,970,933,896,861,827,791,755,719,685,651,617,581,544,506,470,
-436,404,373,339,303,264,227,193,161,130,98,64,28,-6,-40,-72,-105,-139,-175,-209,-242,
--272,-301,-330,-362,-395,-430,-466,-502,-536,-569,-600,-629,-657,-685,-716,-750,-787,-823,-858,-891,-923,
--955,-987,-1020,-1052,-1081,-1108,-1134,-1163,-1194,-1227,-1260,-1291,-1320,-1347,-1373,-1401,-1428,-1457,-1486,-1517,-1549,
--1581,-1613,-1643,-1669,-1695,-1719,-1744,-1771,-1799,-1825,-1849,-1870,-1887,-1900,-1912,-1924,-1938,-1955,-1975,-1995,-2015,
--2033,-2049,-2065,-2080,-2095,-2108,-2118,-2124,-2129,-2136,-2147,-2162,-2179,-2195,-2209,-2221,-2232,-2244,-2257,-2269,-2281,
--2291,-2303,-2318,-2334,-2350,-2362,-2369,-2373,-2378,-2386,-2396,-2406,-2411,-2407,-2394,-2378,-2362,-2350,-2342,-2334,-2325,
--2315,-2305,-2296,-2289,-2282,-2275,-2268,-2262,-2258,-2254,-2250,-2242,-2232,-2221,-2213,-2208,-2206,-2203,-2197,-2189,-2181,
--2175,-2172,-2169,-2163,-2151,-2138,-2125,-2118,-2116,-2114,-2110,-2101,-2090,-2080,-2073,-2068,-2061,-2051,-2038,-2028,-2025,
--2028,-2030,-2023,-2004,-1975,-1948,-1933,-1932,-1942,-1951,-1952,-1942,-1925,-1910,-1900,-1894,-1887,-1874,-1857,-1841,-1832,
--1830,-1831,-1830,-1822,-1812,-1806,-1812,-1833,-1865,-1900,-1930,-1952,-1962,-1964,-1959,-1949,-1935,-1920,-1906,-1897,-1895,
--1897,-1902,-1908,-1915,-1922,-1931,-1940,-1946,-1945,-1937,-1922,-1905,-1889,-1878,-1872,-1871,-1875,-1884,-1897,-1912,-1926,
--1937,-1945,-1948,-1948,-1945,-1940,-1931,-1917,-1901,-1886,-1874,-1865,-1857,-1850,-1842,-1837,-1840,-1849,-1855,-1843,-1799,
--1724,-1633,-1554,-1517,-1537,-1607,-1697,-1775,-1814,-1813,-1785,-1754,-1738,-1740,-1755,-1777,-1801,-1828,-1860,-1888,-1901,
--1885,-1836,-1765,-1694,-1645,-1629,-1640,-1663,-1680,-1684,-1676,-1664,-1654,-1642,-1625,-1599,-1571,-1553,-1554,-1578,-1617,
--1656,-1681,-1689,-1683,-1675,-1674,-1684,-1703,-1725,-1748,-1770,-1792,-1815,-1844,-1880,-1924,-1979,-2041,-2107,-2172,-2232,
--2284,-2329,-2369,-2403,-2429,-2446,-2455,-2460,-2464,-2473,-2485,-2497,-2505,-2508,-2507,-2508,-2513,-2523,-2535,-2547,-2557,
--2565,-2575,-2586,-2598,-2609,-2617,-2622,-2625,-2629,-2633,-2638,-2641,-2641,-2640,-2640,-2641,-2645,-2648,-2649,-2647,-2645,
--2642,-2640,-2637,-2633,-2624,-2611,-2596,-2580,-2565,-2553,-2541,-2528,-2515,-2502,-2490,-2480,-2471,-2463,-2455,-2448,-2443,
--2441,-2442,-2445,-2447,-2446,-2443,-2439,-2437,-2435,-2434,-2431,-2423,-2411,-2396,-2384,-2376,-2372,-2370,-2368,-2364,-2357,
--2350,-2343,-2337,-2330,-2321,-2312,-2302,-2293,-2283,-2273,-2262,-2247,-2232,-2217,-2203,-2192,-2183,-2174,-2164,-2153,-2141,
--2132,-2127,-2127,-2133,-2145,-2162,-2181,-2199,-2214,-2224,-2231,-2235,-2235,-2229,-2214,-2190,-2158,-2122,-2088,-2062,-2045,
--2038,-2037,-2040,-2045,-2048,-2048,-2044,-2036,-2025,-2013,-2002,-1994,-1988,-1983,-1977,-1969,-1959,-1948,-1938,-1929,-1923,
--1917,-1911,-1905,-1900,-1895,-1892,-1890,-1889,-1887,-1884,-1878,-1871,-1862,-1854,-1846,-1838,-1830,-1821,-1811,-1802,-1797,
--1798,-1806,-1819,-1835,-1849,-1859,-1862,-1859,-1850,-1838,-1826,-1817,-1814,-1819,-1835,-1858,-1888,-1918,-1946,-1967,-1982,
--1988,-1988,-1981,-1970,-1956,-1939,-1922,-1906,-1892,-1881,-1872,-1866,-1862,-1860,-1859,-1857,-1855,-1849,-1840,-1829,-1816,
--1803,-1790,-1778,-1767,-1755,-1742,-1727,-1710,-1691,-1670,-1650,-1631,-1615,-1603,-1591,-1580,-1566,-1549,-1530,-1509,-1489,
--1471,-1454,-1437,-1421,-1405,-1389,-1374,-1359,-1345,-1332,-1319,-1306,-1292,-1277,-1262,-1248,-1236,-1226,-1216,-1206,-1194,
--1181,-1167,-1154,-1143,-1134,-1125,-1117,-1108,-1100,-1093,-1086,-1080,-1073,-1067,-1062,-1060,-1061,-1064,-1069,-1071,-1072,
--1071,-1071,-1073,-1076,-1081,-1085,-1087,-1089,-1092,-1097,-1104,-1111,-1117,-1122,-1126,-1130,-1136,-1143,-1151,-1157,-1161,
--1165,-1168,-1172,-1176,-1179,-1180,-1179,-1178,-1177,-1177,-1178,-1180,-1181,-1181,-1182,-1181,-1177,-1170,-1159,-1147,-1137,
--1133,-1134,-1139,-1144,-1144,-1138,-1130,-1120,-1113,-1108,-1103,-1096,-1086,-1073,-1058,-1044,-1031,-1019,-1008,-997,-987,
--978,-970,-962,-954,-946,-938,-929,-919,-906,-891,-875,-859,-844,-833,-824,-817,-811,-807,-804,-803,-801,
--796,-789,-778,-768,-760,-757,-755,-754,-751,-743,-732,-719,-706,-694,-681,-667,-650,-632,-614,-597,-582,
--567,-552,-538,-524,-509,-493,-476,-456,-434,-411,-388,-365,-342,-319,-296,-274,-254,-236,-217,-196,-171,
--143,-114,-86,-60,-36,-14,9,32,57,82,106,130,154,181,209,240,271,303,334,365,397,
-428,457,480,497,509,519,528,534,532,514,481,444,424,446,525,661,831,1001,1136,1218,1249,
-1247,1236,1233,1240,1251,1254,1240,1208,1161,1108,1055,1008,971,946,933,928,928,931,935,944,960,
-984,1013,1039,1058,1066,1066,1065,1066,1071,1080,1091,1103,1119,1140,1167,1196,1222,1243,1259,1275,1293,
-1313,1331,1341,1338,1327,1316,1315,1330,1358,1387,1403,1394,1359,1308,1254,1212,1188,1180,1181,1183,1181,
-1177,1174,1177,1187,1202,1219,1231,1232,1220,1194,1155,1108,1062,1020,987,960,936,909,874,832,787,
-743,705,673,647,625,609,597,592,590,588,580,563,537,504,472,444,422,404,385,362,334,
-303,271,244,223,209,202,203,210,226,248,275,306,336,362,382,393,395,392,388,386,390,
-400,412,422,428,427,424,424,429,440,456,475,494,514,535,557,581,606,637,678,735,811,
-898,985,1056,1101,1119,1118,1112,1111,1118,1127,1132,1133,1136,1154,1196,1264,1348,1428,1488,1516,1515,
-1497,1477,1468,1472,1489,1512,1537,1560,1582,1599,1608,1607,1594,1571,1545,1523,1507,1498,1492,1488,1490,
-1506,1542,1598,1664,1721,1756,1763,1750,1735,1735,1759,1801,1845,1878,1893,1894,1891,1893,1903,1919,1934,
-1946,1957,1970,1987,2007,2024,2036,2041,2045,2052,2066,2085,2106,2124,2138,2150,2164,2180,2199,2219,2238,
-2255,2269,2283,2296,2309,2324,2341,2360,2379,2397,2414,2427,2440,2453,2469,2486,2503,2517,2526,2533,2540,
-2549,2561,2574,2588,2603,2618,2634,2651,2667,2681,2692,2702,2712,2721,2728,2733,2733,2733,2735,2742,2754,
-2768,2778,2783,2783,2780,2778,2778,2778,2776,2771,2764,2758,2753,2748,2741,2731,2719,2707,2697,2691,2687,
-2682,2675,2667,2660,2657,2683,2688,2693,2696,2696,2691,2685,2680,2676,2673,2667,2657,2644,2632,2623,2620,
-2621,2623,2622,2618,2612,2607,2604,2604,2605,2604,2602,2599,2597,2597,2600,2604,2610,2619,2633,2652,2670,
-2686,2695,2701,2710,2731,2767,2815,2865,2906,2928,2935,2932,2933,2943,2966,2997,3033,3069,3104,3137,3167,
-3190,3207,3218,3229,3245,3268,3296,3325,3348,3364,3375,3386,3400,3416,3434,3452,3470,3488,3506,3523,3538,
-3549,3557,3567,3582,3603,3626,3645,3656,3659,3661,3667,3682,3702,3722,3737,3747,3754,3764,3778,3790,3794,
-3783,3759,3732,3717,3723,3752,3789,3815,3811,3770,3700,3623,3565,3547,3571,3628,3697,3758,3797,3814,3814,
-3804,3791,3778,3765,3757,3758,3772,3798,3831,3863,3886,3900,3911,3926,3952,3988,4028,4065,4096,4124,4152,
-4186,4222,4259,4291,4318,4345,4375,4410,4449,4487,4520,4550,4579,4607,4633,4655,4672,4689,4719,4772,4847,
-4933,5005,5039,5025,4971,4899,4839,4807,4810,4837,4874,4909,4934,4945,4940,4913,4865,4802,4735,4681,4652,
-4646,4653,4658,4650,4630,4606,4591,4588,4594,4593,4573,4531,4477,4429,4409,4425,4473,4534,4582,4594,4561,
-4490,4403,4325,4273,4256,4265,4286,4304,4311,4306,4294,4280,4267,4255,4241,4224,4206,4190,4175,4160,4141,
-4116,4086,4056,4031,4012,3998,3983,3961,3930,3889,3845,3805,3775,3756,3747,3743,3740,3732,3717,3695,3670,
-3645,3624,3607,3594,3581,3569,3556,3547,3541,3538,3536,3532,3524,3513,3503,3496,3493,3492,3491,3490,3489,
-3488,3486,3482,3472,3458,3442,3430,3426,3428,3429,3422,3406,3392,3394,3426,3492,3583,3680,3764,3823,3859,
-3880,3898,3918,3940,3954,3956,3942,3915,3879,3838,3794,3747,3700,3654,3613,3576,3543,3508,3470,3427,3379,
-3328,3276,3221,3161,3097,3030,2966,2908,2857,2811,2767,2720,2671,2624,2583,2552,2528,2508,2485,2455,2419,
-2379,2338,2297,2256,2214,2171,2131,2096,2066,2040,2011,1977,1935,1890,1846,1808,1775,1745,1713,1678,1640,
-1604,1573,1547,1523,1496,1464,1427,1387,1350,1315,1283,1252,1219,1183,1145,1108,1072,1037,1002,966,929,
-892,856,820,786,753,720,687,653,619,585,549,514,480,448,417,385,353,319,285,251,218,
-185,152,118,82,46,10,-23,-56,-89,-122,-155,-188,-219,-249,-279,-311,-345,-382,-418,-453,-486,
--517,-548,-578,-609,-640,-671,-704,-737,-772,-807,-841,-873,-904,-935,-967,-999,-1031,-1061,-1089,-1116,-1145,
--1175,-1207,-1240,-1272,-1301,-1327,-1353,-1379,-1408,-1439,-1473,-1506,-1539,-1570,-1599,-1627,-1654,-1681,-1709,-1736,-1763,
--1789,-1816,-1840,-1863,-1881,-1896,-1908,-1920,-1933,-1951,-1970,-1991,-2010,-2027,-2044,-2061,-2079,-2097,-2111,-2119,-2122,
--2124,-2129,-2139,-2156,-2176,-2194,-2208,-2219,-2229,-2240,-2253,-2267,-2280,-2292,-2304,-2317,-2332,-2347,-2359,-2367,-2373,
--2380,-2389,-2400,-2410,-2416,-2413,-2402,-2388,-2373,-2360,-2350,-2342,-2335,-2328,-2321,-2315,-2308,-2299,-2289,-2279,-2272,
--2269,-2268,-2266,-2261,-2252,-2242,-2233,-2227,-2223,-2219,-2212,-2203,-2196,-2193,-2193,-2193,-2188,-2179,-2166,-2154,-2146,
--2143,-2140,-2135,-2125,-2114,-2105,-2100,-2096,-2089,-2077,-2063,-2052,-2048,-2051,-2054,-2049,-2030,-2002,-1973,-1955,-1952,
--1960,-1968,-1967,-1956,-1939,-1924,-1914,-1908,-1901,-1889,-1872,-1855,-1845,-1843,-1845,-1845,-1839,-1829,-1822,-1826,-1844,
--1875,-1911,-1944,-1967,-1979,-1980,-1972,-1957,-1938,-1922,-1911,-1907,-1911,-1917,-1922,-1924,-1924,-1928,-1937,-1950,-1963,
--1967,-1960,-1942,-1921,-1905,-1898,-1901,-1910,-1919,-1925,-1929,-1933,-1938,-1945,-1952,-1958,-1961,-1961,-1960,-1957,-1953,
--1949,-1945,-1938,-1926,-1909,-1889,-1872,-1866,-1874,-1890,-1899,-1883,-1829,-1744,-1650,-1581,-1566,-1612,-1700,-1793,-1856,
--1873,-1849,-1811,-1786,-1787,-1810,-1843,-1873,-1896,-1917,-1939,-1959,-1964,-1941,-1887,-1816,-1749,-1710,-1705,-1726,-1755,
--1773,-1775,-1765,-1752,-1740,-1727,-1705,-1672,-1634,-1606,-1600,-1621,-1659,-1700,-1729,-1742,-1743,-1742,-1748,-1764,-1788,
--1814,-1838,-1859,-1879,-1899,-1925,-1961,-2010,-2073,-2148,-2227,-2302,-2362,-2407,-2438,-2462,-2483,-2505,-2523,-2537,-2546,
--2551,-2558,-2568,-2580,-2591,-2598,-2600,-2601,-2603,-2609,-2618,-2628,-2638,-2649,-2661,-2674,-2687,-2697,-2703,-2704,-2704,
--2706,-2710,-2715,-2718,-2719,-2716,-2714,-2714,-2717,-2720,-2721,-2718,-2713,-2707,-2703,-2701,-2698,-2693,-2684,-2671,-2659,
--2648,-2638,-2630,-2620,-2606,-2591,-2575,-2561,-2550,-2541,-2534,-2527,-2520,-2516,-2514,-2513,-2512,-2508,-2503,-2498,-2494,
--2492,-2491,-2489,-2484,-2474,-2461,-2449,-2439,-2433,-2428,-2423,-2417,-2409,-2400,-2392,-2384,-2377,-2369,-2360,-2351,-2342,
--2333,-2324,-2313,-2300,-2285,-2270,-2254,-2241,-2229,-2219,-2211,-2204,-2198,-2192,-2186,-2180,-2175,-2172,-2173,-2176,-2182,
--2190,-2201,-2215,-2233,-2251,-2266,-2272,-2264,-2242,-2208,-2168,-2131,-2101,-2081,-2071,-2068,-2069,-2069,-2068,-2064,-2057,
--2050,-2043,-2038,-2035,-2031,-2026,-2018,-2008,-1997,-1986,-1976,-1968,-1962,-1955,-1948,-1941,-1933,-1926,-1919,-1913,-1908,
--1904,-1901,-1898,-1894,-1889,-1883,-1875,-1865,-1853,-1838,-1822,-1807,-1795,-1789,-1790,-1798,-1811,-1826,-1840,-1850,-1856,
--1857,-1853,-1847,-1840,-1835,-1836,-1842,-1856,-1875,-1898,-1923,-1947,-1969,-1988,-2002,-2012,-2017,-2016,-2009,-1997,-1980,
--1961,-1940,-1919,-1901,-1886,-1876,-1870,-1865,-1861,-1855,-1847,-1836,-1823,-1809,-1795,-1780,-1765,-1750,-1737,-1724,-1711,
--1697,-1681,-1664,-1647,-1631,-1617,-1605,-1592,-1577,-1560,-1540,-1519,-1500,-1482,-1466,-1451,-1436,-1419,-1401,-1382,-1364,
--1347,-1332,-1319,-1305,-1292,-1277,-1261,-1247,-1234,-1223,-1214,-1204,-1194,-1182,-1171,-1160,-1152,-1146,-1140,-1133,-1126,
--1118,-1109,-1101,-1092,-1084,-1076,-1070,-1067,-1069,-1074,-1079,-1082,-1082,-1080,-1078,-1079,-1082,-1088,-1092,-1096,-1098,
--1100,-1104,-1111,-1118,-1124,-1129,-1133,-1138,-1144,-1152,-1159,-1164,-1168,-1169,-1171,-1173,-1176,-1179,-1182,-1184,-1186,
--1186,-1188,-1189,-1191,-1194,-1198,-1201,-1202,-1199,-1192,-1181,-1170,-1160,-1154,-1154,-1155,-1157,-1156,-1151,-1144,-1136,
--1129,-1123,-1116,-1108,-1100,-1091,-1082,-1072,-1061,-1047,-1031,-1015,-999,-986,-976,-968,-961,-954,-947,-939,-929,
--917,-903,-886,-869,-852,-838,-826,-818,-812,-809,-809,-811,-812,-811,-804,-794,-782,-772,-767,-765,-764,
--761,-755,-744,-733,-721,-710,-697,-683,-665,-646,-627,-611,-597,-584,-571,-557,-540,-521,-501,-481,-461,
--441,-421,-402,-383,-363,-343,-323,-304,-286,-269,-250,-229,-203,-174,-144,-115,-89,-65,-43,-19,6,
-33,60,85,110,136,163,194,226,258,289,319,349,380,411,440,464,483,495,506,517,526,
-526,512,481,441,412,417,475,588,741,905,1047,1147,1199,1212,1205,1193,1187,1185,1185,1178,1162,
-1133,1094,1048,1001,960,931,914,910,914,920,929,942,962,990,1023,1056,1082,1100,1110,1117,1122,
-1129,1135,1141,1147,1155,1170,1190,1214,1237,1255,1270,1283,1297,1311,1321,1322,1312,1295,1282,1281,1297,
-1327,1356,1371,1361,1328,1279,1232,1197,1179,1177,1182,1185,1184,1181,1178,1183,1194,1210,1224,1228,1217,
-1190,1149,1099,1046,997,956,921,889,858,821,779,733,686,641,602,569,544,527,520,522,531,
-543,551,545,523,483,430,373,320,274,237,206,177,147,117,89,66,53,51,58,74,94,
-117,141,168,195,223,247,266,276,280,280,283,293,311,336,361,381,390,390,385,381,383,
-391,403,417,430,443,456,471,490,514,549,599,671,765,874,981,1069,1125,1148,1147,1138,1137,
-1149,1169,1187,1196,1197,1202,1224,1272,1340,1415,1477,1511,1516,1501,1480,1467,1469,1484,1507,1532,1557,
-1581,1603,1619,1625,1618,1599,1575,1554,1539,1531,1527,1524,1524,1534,1560,1601,1648,1689,1713,1718,1716,
-1722,1749,1796,1852,1899,1924,1925,1914,1904,1904,1914,1929,1940,1946,1952,1963,1983,2009,2034,2051,2060,
-2064,2070,2082,2098,2116,2131,2144,2156,2170,2188,2207,2226,2242,2254,2266,2280,2296,2314,2332,2349,2366,
-2382,2397,2410,2422,2435,2448,2465,2484,2502,2517,2527,2534,2539,2547,2559,2574,2590,2605,2620,2633,2646,
-2658,2668,2677,2685,2693,2701,2708,2713,2717,2721,2727,2736,2748,2759,2767,2770,2771,2771,2775,2782,2789,
-2792,2789,2781,2772,2765,2760,2755,2749,2739,2726,2713,2702,2695,2690,2686,2683,2682,2683,2704,2705,2706,
-2707,2706,2704,2701,2699,2697,2693,2684,2672,2658,2647,2642,2643,2645,2644,2637,2626,2614,2607,2607,2612,
-2616,2617,2613,2609,2609,2616,2627,2639,2648,2654,2660,2667,2675,2682,2685,2686,2690,2707,2739,2786,2835,
-2874,2894,2896,2890,2889,2904,2938,2985,3036,3082,3119,3146,3167,3183,3196,3209,3223,3241,3263,3286,3307,
-3325,3339,3352,3365,3379,3395,3411,3426,3441,3457,3475,3493,3510,3524,3536,3549,3566,3586,3607,3624,3635,
-3641,3648,3659,3678,3700,3723,3741,3756,3771,3789,3806,3819,3819,3805,3781,3759,3752,3764,3789,3810,3810,
-3777,3714,3640,3578,3549,3562,3608,3669,3724,3758,3770,3765,3754,3744,3736,3731,3727,3726,3734,3755,3787,
-3823,3855,3877,3890,3902,3920,3949,3986,4024,4057,4085,4110,4140,4174,4211,4246,4275,4301,4329,4364,4406,
-4449,4488,4520,4546,4573,4603,4636,4665,4686,4701,4720,4752,4803,4863,4914,4937,4925,4884,4835,4801,4797,
-4823,4873,4933,4995,5050,5090,5105,5084,5023,4930,4824,4730,4665,4633,4622,4618,4608,4595,4587,4595,4619,
-4645,4655,4631,4573,4497,4431,4400,4417,4471,4539,4590,4600,4562,4489,4403,4329,4284,4271,4280,4297,4305,
-4299,4282,4260,4239,4224,4213,4202,4189,4173,4157,4143,4131,4118,4102,4084,4063,4042,4021,3998,3972,3940,
-3901,3857,3813,3776,3749,3734,3730,3732,3736,3735,3725,3706,3679,3650,3622,3599,3579,3562,3545,3530,3519,
-3514,3514,3517,3517,3514,3506,3497,3490,3485,3482,3478,3475,3473,3474,3477,3480,3477,3468,3454,3440,3434,
-3434,3436,3435,3427,3417,3414,3430,3470,3529,3597,3663,3721,3773,3825,3881,3937,3985,4012,4011,3986,3943,
-3893,3843,3794,3745,3695,3645,3597,3555,3520,3491,3464,3436,3406,3373,3334,3285,3225,3154,3078,3004,2939,
-2887,2842,2797,2745,2684,2620,2561,2514,2481,2457,2436,2412,2384,2354,2324,2294,2261,2223,2178,2130,2085,
-2048,2020,1994,1967,1932,1890,1846,1805,1769,1737,1706,1671,1634,1597,1564,1537,1514,1489,1458,1422,1382,
-1344,1309,1278,1248,1215,1178,1138,1099,1061,1027,994,962,927,893,858,824,792,760,727,693,659,
-623,589,555,522,490,458,426,394,362,331,300,269,237,205,170,134,97,60,24,-10,-45,
--79,-112,-144,-175,-204,-234,-266,-302,-341,-380,-417,-450,-479,-505,-531,-560,-591,-624,-658,-693,-727,
--760,-794,-827,-858,-889,-920,-950,-981,-1012,-1043,-1072,-1101,-1130,-1160,-1191,-1223,-1253,-1281,-1307,-1331,-1358,
--1387,-1421,-1457,-1493,-1526,-1556,-1584,-1611,-1639,-1668,-1698,-1726,-1754,-1780,-1805,-1830,-1854,-1875,-1892,-1907,-1921,
--1936,-1954,-1973,-1991,-2007,-2022,-2038,-2057,-2079,-2100,-2116,-2124,-2125,-2124,-2127,-2138,-2156,-2178,-2197,-2211,-2221,
--2229,-2240,-2253,-2268,-2282,-2295,-2306,-2318,-2332,-2347,-2360,-2370,-2378,-2386,-2395,-2406,-2417,-2422,-2420,-2412,-2399,
--2385,-2371,-2360,-2351,-2344,-2340,-2336,-2332,-2326,-2317,-2305,-2293,-2285,-2282,-2283,-2284,-2281,-2275,-2267,-2259,-2254,
--2250,-2245,-2238,-2230,-2222,-2218,-2218,-2218,-2215,-2207,-2197,-2187,-2180,-2176,-2172,-2165,-2156,-2146,-2139,-2135,-2131,
--2122,-2108,-2090,-2076,-2070,-2073,-2077,-2073,-2056,-2029,-2001,-1983,-1979,-1985,-1990,-1988,-1974,-1954,-1936,-1924,-1917,
--1910,-1898,-1882,-1868,-1861,-1861,-1867,-1870,-1865,-1855,-1844,-1842,-1854,-1880,-1915,-1950,-1978,-1995,-1999,-1992,-1975,
--1955,-1937,-1927,-1926,-1932,-1939,-1942,-1939,-1936,-1937,-1947,-1964,-1982,-1990,-1984,-1969,-1951,-1941,-1943,-1955,-1968,
--1975,-1974,-1967,-1959,-1956,-1958,-1963,-1969,-1973,-1974,-1976,-1980,-1986,-1992,-1995,-1992,-1981,-1962,-1942,-1926,-1921,
--1928,-1940,-1940,-1914,-1854,-1769,-1686,-1635,-1636,-1690,-1774,-1853,-1896,-1897,-1869,-1840,-1832,-1854,-1893,-1933,-1962,
--1979,-1993,-2011,-2030,-2034,-2011,-1955,-1882,-1815,-1777,-1776,-1801,-1832,-1852,-1853,-1841,-1828,-1819,-1810,-1795,-1767,
--1732,-1700,-1685,-1693,-1720,-1755,-1786,-1807,-1821,-1833,-1849,-1870,-1894,-1918,-1940,-1961,-1981,-2003,-2030,-2064,-2112,
--2175,-2252,-2335,-2411,-2471,-2510,-2533,-2548,-2562,-2580,-2599,-2616,-2627,-2635,-2643,-2654,-2668,-2680,-2689,-2693,-2693,
--2693,-2696,-2702,-2711,-2721,-2731,-2742,-2754,-2765,-2774,-2779,-2779,-2778,-2777,-2779,-2783,-2786,-2788,-2788,-2788,-2790,
--2794,-2797,-2798,-2793,-2783,-2773,-2765,-2760,-2758,-2755,-2750,-2742,-2733,-2726,-2720,-2715,-2707,-2695,-2678,-2659,-2642,
--2628,-2618,-2610,-2603,-2596,-2589,-2583,-2579,-2575,-2570,-2564,-2559,-2555,-2553,-2552,-2550,-2545,-2536,-2525,-2514,-2503,
--2495,-2487,-2479,-2471,-2462,-2453,-2446,-2439,-2432,-2424,-2415,-2405,-2395,-2385,-2374,-2364,-2352,-2340,-2327,-2312,-2297,
--2283,-2271,-2262,-2256,-2252,-2249,-2244,-2237,-2228,-2219,-2210,-2202,-2195,-2191,-2192,-2198,-2212,-2233,-2257,-2278,-2290,
--2289,-2273,-2247,-2215,-2184,-2156,-2134,-2116,-2103,-2093,-2084,-2077,-2072,-2070,-2069,-2070,-2071,-2069,-2063,-2053,-2042,
--2029,-2018,-2009,-2001,-1993,-1986,-1979,-1973,-1967,-1961,-1954,-1947,-1939,-1931,-1924,-1918,-1912,-1906,-1899,-1892,-1883,
--1874,-1865,-1855,-1845,-1835,-1826,-1818,-1811,-1808,-1807,-1808,-1812,-1818,-1825,-1832,-1839,-1844,-1848,-1850,-1852,-1855,
--1860,-1868,-1881,-1897,-1918,-1941,-1965,-1989,-2010,-2028,-2040,-2045,-2042,-2031,-2013,-1991,-1967,-1943,-1923,-1904,-1889,
--1874,-1861,-1849,-1837,-1825,-1813,-1798,-1781,-1763,-1745,-1729,-1716,-1705,-1695,-1685,-1674,-1662,-1649,-1635,-1621,-1606,
--1588,-1569,-1547,-1526,-1507,-1489,-1475,-1461,-1446,-1431,-1413,-1394,-1375,-1357,-1342,-1328,-1314,-1300,-1284,-1268,-1252,
--1238,-1226,-1215,-1205,-1194,-1183,-1172,-1163,-1157,-1152,-1148,-1143,-1136,-1128,-1121,-1113,-1105,-1096,-1088,-1082,-1080,
--1083,-1088,-1095,-1099,-1100,-1097,-1094,-1093,-1095,-1099,-1104,-1108,-1110,-1112,-1116,-1120,-1126,-1131,-1135,-1139,-1143,
--1149,-1156,-1162,-1166,-1167,-1167,-1165,-1166,-1168,-1173,-1179,-1184,-1187,-1190,-1192,-1194,-1197,-1202,-1206,-1210,-1212,
--1210,-1204,-1195,-1186,-1178,-1173,-1170,-1169,-1169,-1167,-1164,-1159,-1153,-1145,-1135,-1124,-1114,-1106,-1100,-1095,-1088,
--1078,-1063,-1045,-1027,-1010,-998,-988,-981,-973,-965,-958,-950,-941,-932,-920,-905,-888,-869,-852,-836,-824,
--817,-815,-818,-823,-827,-827,-821,-809,-795,-784,-778,-776,-776,-774,-769,-760,-748,-737,-725,-711,-696,
--678,-659,-640,-624,-611,-599,-586,-572,-555,-536,-515,-494,-474,-454,-436,-419,-403,-387,-370,-352,-335,
--318,-300,-281,-258,-231,-201,-170,-140,-114,-91,-68,-43,-14,17,49,78,104,129,154,182,213,
-244,274,302,330,360,390,420,446,466,480,491,502,513,517,509,484,448,414,404,435,516,
-638,784,927,1047,1129,1171,1179,1165,1140,1114,1096,1087,1085,1082,1071,1046,1008,965,927,902,893,
-897,910,927,947,972,1002,1039,1077,1111,1137,1156,1167,1175,1180,1183,1184,1185,1188,1196,1210,1228,
-1245,1261,1273,1284,1294,1302,1306,1303,1291,1275,1262,1259,1267,1283,1296,1296,1279,1247,1208,1173,1150,
-1141,1142,1147,1150,1150,1149,1148,1152,1158,1164,1164,1155,1132,1096,1051,1001,951,904,861,821,782,
-741,698,654,613,576,545,519,500,486,479,481,494,515,539,560,568,554,517,459,388,315,
-251,205,177,165,165,171,182,196,214,236,258,275,283,280,269,256,246,243,245,248,251,
-254,260,276,304,344,387,425,447,449,433,407,381,361,351,347,347,347,348,349,353,363,
-381,412,463,538,638,757,879,985,1063,1105,1121,1125,1132,1150,1177,1205,1225,1236,1246,1265,1305,
-1363,1429,1487,1522,1531,1520,1504,1494,1498,1514,1535,1556,1573,1589,1602,1612,1615,1608,1593,1572,1555,
-1545,1543,1546,1549,1553,1560,1573,1594,1618,1638,1650,1659,1673,1705,1756,1821,1882,1925,1941,1935,1920,
-1912,1916,1930,1945,1952,1953,1954,1961,1980,2007,2035,2058,2072,2082,2091,2102,2115,2127,2137,2147,2159,
-2177,2198,2219,2235,2246,2253,2260,2272,2287,2306,2324,2341,2356,2370,2383,2396,2408,2420,2432,2447,2464,
-2481,2495,2505,2512,2519,2529,2545,2564,2583,2600,2614,2625,2634,2643,2651,2658,2664,2669,2674,2679,2685,
-2692,2701,2713,2726,2740,2751,2758,2762,2765,2771,2781,2795,2808,2814,2811,2801,2787,2777,2770,2767,2763,
-2756,2745,2732,2721,2714,2709,2707,2706,2704,2704,2716,2711,2707,2706,2706,2706,2707,2708,2707,2702,2691,
-2678,2664,2655,2653,2656,2657,2652,2640,2624,2612,2610,2616,2628,2636,2638,2634,2632,2639,2656,2678,2695,
-2701,2696,2684,2674,2672,2676,2684,2692,2701,2716,2742,2777,2815,2845,2861,2863,2861,2869,2894,2936,2987,
-3035,3069,3090,3100,3107,3117,3133,3154,3177,3199,3219,3237,3253,3268,3284,3303,3325,3349,3371,3391,3407,
-3421,3436,3453,3474,3494,3513,3529,3543,3558,3573,3590,3606,3621,3634,3647,3661,3676,3692,3707,3722,3738,
-3756,3775,3790,3798,3796,3785,3772,3768,3776,3795,3812,3813,3786,3730,3659,3594,3555,3555,3590,3644,3697,
-3731,3741,3733,3716,3703,3697,3697,3699,3701,3707,3719,3742,3774,3808,3837,3858,3872,3886,3908,3938,3974,
-4008,4038,4063,4090,4121,4157,4194,4227,4254,4280,4311,4351,4399,4446,4485,4514,4538,4562,4595,4633,4669,
-4697,4714,4726,4743,4769,4801,4829,4841,4833,4811,4788,4776,4783,4809,4849,4899,4959,5026,5089,5132,5138,
-5095,5008,4898,4790,4707,4654,4625,4605,4589,4579,4585,4614,4658,4700,4713,4682,4609,4514,4429,4382,4382,
-4421,4473,4511,4516,4485,4430,4371,4325,4302,4299,4307,4312,4304,4283,4253,4222,4196,4178,4166,4156,4145,
-4132,4120,4111,4106,4102,4097,4087,4071,4048,4018,3983,3943,3900,3857,3817,3783,3756,3739,3731,3730,3734,
-3738,3738,3728,3710,3685,3657,3631,3608,3586,3564,3541,3519,3502,3493,3494,3499,3503,3502,3496,3487,3479,
-3475,3474,3474,3473,3472,3473,3476,3480,3481,3477,3468,3458,3450,3447,3448,3448,3444,3437,3432,3436,3455,
-3488,3529,3576,3625,3681,3747,3821,3895,3955,3989,3989,3959,3910,3854,3800,3753,3708,3664,3620,3576,3536,
-3500,3468,3437,3405,3373,3338,3297,3246,3181,3104,3024,2952,2898,2867,2850,2834,2804,2753,2683,2606,2534,
-2476,2432,2396,2363,2331,2302,2279,2261,2243,2219,2183,2138,2088,2043,2007,1979,1952,1922,1884,1842,1799,
-1761,1727,1696,1663,1628,1591,1558,1529,1504,1480,1452,1420,1383,1345,1310,1277,1245,1211,1174,1134,1095,
-1058,1023,991,959,927,895,864,834,805,774,741,706,669,633,598,565,533,500,466,432,399,
-367,336,307,277,247,214,180,143,106,69,32,-4,-40,-75,-108,-139,-168,-196,-226,-259,-296,
--336,-377,-413,-445,-471,-493,-517,-543,-574,-608,-644,-679,-713,-746,-779,-811,-843,-874,-904,-933,-964,
--994,-1026,-1058,-1089,-1120,-1150,-1180,-1210,-1240,-1267,-1293,-1318,-1345,-1375,-1409,-1445,-1481,-1514,-1544,-1571,-1598,
--1626,-1656,-1686,-1716,-1745,-1771,-1797,-1821,-1844,-1865,-1884,-1901,-1919,-1938,-1958,-1976,-1993,-2006,-2019,-2035,-2057,
--2082,-2106,-2124,-2132,-2132,-2129,-2132,-2142,-2161,-2183,-2202,-2216,-2225,-2233,-2244,-2258,-2273,-2288,-2300,-2312,-2324,
--2338,-2352,-2365,-2376,-2384,-2392,-2401,-2411,-2421,-2426,-2425,-2418,-2407,-2394,-2382,-2372,-2364,-2358,-2354,-2353,-2350,
--2345,-2336,-2324,-2311,-2303,-2300,-2301,-2303,-2303,-2298,-2292,-2285,-2281,-2278,-2275,-2270,-2263,-2256,-2251,-2247,-2244,
--2240,-2233,-2226,-2219,-2214,-2211,-2207,-2199,-2191,-2182,-2177,-2173,-2168,-2156,-2139,-2118,-2103,-2098,-2101,-2106,-2104,
--2089,-2063,-2036,-2017,-2009,-2011,-2012,-2005,-1988,-1967,-1948,-1936,-1929,-1922,-1910,-1896,-1883,-1876,-1879,-1886,-1892,
--1889,-1879,-1866,-1859,-1865,-1886,-1919,-1956,-1990,-2016,-2028,-2027,-2013,-1992,-1973,-1961,-1958,-1962,-1967,-1967,-1963,
--1958,-1959,-1971,-1989,-2007,-2015,-2012,-2000,-1989,-1987,-1996,-2011,-2022,-2023,-2013,-1999,-1987,-1981,-1983,-1988,-1993,
--1996,-1999,-2004,-2011,-2019,-2026,-2028,-2024,-2017,-2009,-2003,-2001,-2003,-2005,-2004,-1989,-1954,-1900,-1834,-1776,-1744,
--1749,-1790,-1847,-1896,-1920,-1918,-1903,-1895,-1908,-1942,-1984,-2017,-2037,-2047,-2058,-2079,-2102,-2111,-2092,-2039,-1966,
--1899,-1859,-1856,-1879,-1908,-1925,-1924,-1912,-1900,-1896,-1897,-1896,-1883,-1859,-1831,-1811,-1807,-1819,-1844,-1872,-1900,
--1926,-1949,-1971,-1991,-2008,-2024,-2041,-2061,-2086,-2114,-2146,-2185,-2233,-2293,-2366,-2443,-2515,-2571,-2607,-2627,-2639,
--2650,-2665,-2682,-2697,-2708,-2716,-2725,-2737,-2752,-2765,-2773,-2775,-2774,-2774,-2778,-2788,-2799,-2810,-2818,-2825,-2832,
--2839,-2846,-2851,-2852,-2850,-2848,-2847,-2847,-2849,-2851,-2853,-2856,-2860,-2866,-2870,-2870,-2864,-2854,-2841,-2831,-2825,
--2822,-2820,-2817,-2812,-2805,-2798,-2793,-2789,-2782,-2771,-2755,-2737,-2719,-2705,-2695,-2687,-2681,-2674,-2666,-2658,-2650,
--2642,-2635,-2628,-2622,-2618,-2615,-2612,-2609,-2603,-2595,-2585,-2575,-2564,-2555,-2545,-2536,-2527,-2518,-2510,-2503,-2497,
--2490,-2482,-2473,-2463,-2452,-2440,-2429,-2418,-2407,-2396,-2385,-2373,-2359,-2344,-2330,-2318,-2309,-2303,-2298,-2293,-2286,
--2277,-2268,-2259,-2249,-2238,-2227,-2216,-2208,-2207,-2216,-2233,-2254,-2276,-2291,-2297,-2293,-2279,-2258,-2233,-2207,-2182,
--2158,-2138,-2122,-2111,-2104,-2100,-2100,-2099,-2098,-2095,-2088,-2079,-2069,-2058,-2048,-2039,-2030,-2022,-2013,-2006,-2001,
--1997,-1994,-1990,-1984,-1976,-1966,-1955,-1944,-1934,-1924,-1914,-1904,-1896,-1890,-1886,-1884,-1881,-1877,-1870,-1859,-1845,
--1830,-1816,-1804,-1795,-1792,-1794,-1801,-1811,-1822,-1831,-1835,-1835,-1832,-1829,-1828,-1832,-1841,-1855,-1874,-1896,-1921,
--1948,-1975,-2001,-2024,-2040,-2048,-2047,-2039,-2024,-2006,-1985,-1962,-1938,-1913,-1889,-1868,-1851,-1837,-1825,-1812,-1797,
--1779,-1759,-1740,-1723,-1709,-1697,-1686,-1675,-1663,-1651,-1638,-1623,-1608,-1591,-1573,-1554,-1534,-1515,-1498,-1482,-1467,
--1453,-1438,-1422,-1406,-1389,-1373,-1357,-1343,-1328,-1313,-1297,-1280,-1264,-1250,-1237,-1226,-1216,-1204,-1193,-1181,-1172,
--1165,-1159,-1154,-1148,-1142,-1135,-1129,-1124,-1118,-1113,-1107,-1102,-1100,-1102,-1108,-1114,-1120,-1122,-1121,-1118,-1115,
--1115,-1117,-1120,-1124,-1126,-1129,-1131,-1134,-1137,-1140,-1143,-1146,-1151,-1156,-1162,-1168,-1172,-1172,-1170,-1168,-1166,
--1168,-1171,-1176,-1181,-1185,-1189,-1192,-1195,-1200,-1205,-1210,-1213,-1214,-1212,-1208,-1202,-1195,-1190,-1185,-1182,-1179,
--1178,-1176,-1175,-1173,-1168,-1159,-1148,-1135,-1124,-1115,-1109,-1104,-1096,-1083,-1066,-1047,-1030,-1016,-1006,-999,-991,
--981,-971,-961,-952,-946,-941,-933,-922,-906,-888,-869,-851,-837,-828,-824,-826,-830,-834,-834,-829,-819,
--808,-799,-795,-795,-795,-794,-788,-778,-765,-751,-737,-721,-704,-686,-667,-649,-632,-618,-605,-593,-580,
--566,-551,-534,-515,-495,-474,-454,-436,-421,-407,-392,-375,-357,-339,-321,-302,-280,-254,-225,-195,-165,
--139,-115,-91,-64,-32,3,39,72,99,124,148,173,202,231,259,286,312,339,368,397,425,
-446,463,476,488,499,507,505,490,464,434,417,425,469,550,659,784,907,1013,1088,1126,1127,
-1101,1062,1029,1014,1019,1037,1050,1046,1019,975,927,891,876,882,903,933,966,1001,1039,1080,1121,
-1157,1185,1203,1213,1218,1220,1222,1224,1226,1229,1233,1239,1247,1255,1262,1267,1272,1276,1278,1276,1269,
-1256,1241,1227,1218,1213,1209,1200,1183,1158,1128,1100,1078,1063,1056,1052,1051,1050,1050,1051,1052,1051,
-1047,1039,1024,1002,975,941,903,862,818,773,728,683,639,597,558,525,502,490,488,494,506,
-520,536,554,575,600,630,659,681,685,665,619,553,479,414,371,360,381,426,488,556,624,
-688,741,776,785,765,716,649,575,510,461,430,413,405,403,410,430,468,519,573,618,641,
-635,604,554,496,440,391,351,320,295,278,269,267,273,290,320,369,441,538,654,776,888,
-978,1038,1071,1088,1103,1125,1155,1189,1221,1249,1275,1307,1349,1401,1457,1503,1531,1538,1532,1523,1523,
-1534,1555,1577,1594,1603,1605,1604,1601,1595,1585,1571,1555,1543,1539,1543,1553,1563,1572,1578,1584,1589,
-1593,1597,1602,1614,1639,1682,1743,1809,1867,1906,1922,1922,1920,1925,1939,1959,1974,1979,1977,1974,1977,
-1991,2011,2034,2054,2071,2086,2102,2117,2130,2139,2144,2150,2162,2180,2203,2225,2240,2248,2252,2257,2266,
-2279,2293,2306,2318,2329,2341,2356,2372,2388,2401,2413,2425,2439,2453,2466,2476,2484,2493,2506,2524,2546,
-2567,2585,2598,2606,2614,2621,2629,2637,2642,2646,2649,2653,2659,2668,2680,2694,2708,2721,2731,2739,2745,
-2752,2764,2780,2798,2815,2824,2822,2812,2799,2787,2779,2775,2771,2765,2755,2745,2737,2732,2731,2730,2727,
-2722,2716,2727,2722,2720,2721,2723,2725,2723,2718,2708,2695,2678,2663,2651,2647,2651,2659,2664,2664,2656,
-2646,2641,2645,2656,2668,2673,2669,2662,2661,2674,2698,2726,2744,2742,2721,2692,2669,2663,2672,2692,2713,
-2730,2744,2759,2778,2801,2820,2834,2841,2849,2866,2895,2934,2972,2999,3009,3006,2998,2995,3006,3029,3059,
-3091,3118,3140,3157,3172,3190,3213,3241,3272,3306,3336,3361,3381,3396,3411,3429,3450,3475,3498,3518,3533,
-3546,3559,3576,3596,3619,3641,3659,3672,3681,3687,3695,3704,3717,3731,3741,3744,3740,3731,3725,3729,3746,
-3772,3797,3804,3785,3736,3669,3603,3557,3546,3569,3617,3669,3708,3724,3718,3699,3679,3667,3664,3668,3674,
-3680,3688,3702,3723,3751,3782,3809,3830,3849,3870,3897,3928,3961,3992,4018,4043,4071,4104,4141,4176,4207,
-4233,4259,4292,4334,4383,4430,4469,4497,4519,4544,4577,4618,4659,4693,4717,4733,4747,4765,4783,4798,4803,
-4799,4789,4780,4775,4774,4776,4781,4794,4824,4874,4937,4995,5026,5014,4959,4877,4789,4716,4662,4624,4596,
-4575,4569,4586,4629,4686,4732,4743,4704,4619,4513,4416,4352,4329,4339,4363,4381,4384,4371,4349,4331,4322,
-4322,4326,4327,4317,4295,4264,4229,4196,4169,4150,4136,4124,4114,4104,4097,4094,4094,4095,4093,4083,4064,
-4035,3997,3952,3905,3860,3820,3789,3767,3754,3747,3746,3747,3749,3749,3743,3729,3709,3685,3661,3640,3622,
-3604,3581,3552,3521,3495,3479,3474,3479,3484,3484,3478,3469,3463,3462,3468,3475,3481,3483,3482,3482,3483,
-3485,3485,3481,3474,3467,3462,3460,3458,3454,3449,3444,3445,3455,3476,3505,3540,3580,3628,3683,3745,3805,
-3853,3877,3874,3847,3805,3760,3718,3683,3651,3620,3586,3551,3515,3478,3438,3395,3350,3304,3258,3209,3151,
-3080,2997,2910,2835,2787,2771,2781,2798,2800,2773,2715,2638,2557,2487,2430,2383,2340,2296,2255,2223,2203,
-2192,2181,2162,2130,2087,2041,1999,1965,1936,1906,1871,1831,1788,1749,1714,1684,1655,1624,1591,1557,1526,
-1497,1470,1443,1413,1379,1343,1307,1272,1238,1204,1169,1133,1097,1062,1027,993,959,927,897,868,842,
-814,785,752,716,680,645,611,578,545,511,476,440,406,375,345,316,286,254,219,183,146,
-109,72,35,0,-34,-67,-99,-128,-157,-185,-215,-248,-283,-322,-360,-395,-426,-452,-475,-498,-525,
--557,-592,-629,-664,-698,-729,-761,-792,-824,-856,-886,-916,-946,-977,-1010,-1043,-1077,-1109,-1140,-1169,-1197,
--1226,-1254,-1282,-1311,-1340,-1370,-1403,-1438,-1472,-1504,-1534,-1562,-1588,-1616,-1646,-1677,-1708,-1738,-1767,-1793,-1816,
--1837,-1856,-1874,-1893,-1912,-1933,-1954,-1973,-1988,-2000,-2013,-2030,-2053,-2080,-2107,-2126,-2136,-2137,-2137,-2140,-2151,
--2168,-2188,-2206,-2218,-2228,-2237,-2249,-2263,-2278,-2293,-2305,-2317,-2330,-2343,-2357,-2369,-2379,-2386,-2393,-2402,-2412,
--2421,-2427,-2427,-2422,-2413,-2403,-2393,-2385,-2379,-2375,-2372,-2370,-2368,-2364,-2356,-2345,-2334,-2326,-2322,-2321,-2322,
--2321,-2317,-2310,-2304,-2299,-2297,-2295,-2292,-2288,-2283,-2279,-2274,-2270,-2264,-2258,-2252,-2248,-2245,-2243,-2238,-2231,
--2222,-2214,-2209,-2205,-2198,-2186,-2167,-2147,-2132,-2128,-2132,-2138,-2137,-2124,-2100,-2073,-2051,-2039,-2033,-2027,-2016,
--1999,-1980,-1965,-1955,-1950,-1944,-1933,-1918,-1903,-1895,-1896,-1902,-1907,-1905,-1896,-1884,-1875,-1877,-1893,-1922,-1960,
--1998,-2032,-2054,-2061,-2053,-2035,-2016,-2001,-1993,-1993,-1994,-1992,-1988,-1985,-1989,-2002,-2020,-2035,-2042,-2038,-2029,
--2023,-2026,-2036,-2048,-2054,-2049,-2037,-2024,-2016,-2014,-2018,-2023,-2027,-2030,-2037,-2046,-2057,-2063,-2062,-2055,-2047,
--2046,-2054,-2069,-2083,-2088,-2078,-2055,-2023,-1989,-1956,-1928,-1908,-1899,-1902,-1915,-1933,-1947,-1953,-1954,-1958,-1971,
--1998,-2034,-2069,-2092,-2104,-2112,-2126,-2148,-2172,-2182,-2165,-2118,-2055,-1997,-1963,-1959,-1976,-1998,-2008,-2003,-1989,
--1978,-1978,-1987,-1997,-2000,-1991,-1974,-1958,-1951,-1955,-1971,-1995,-2021,-2048,-2072,-2092,-2106,-2116,-2125,-2138,-2159,
--2190,-2228,-2271,-2318,-2371,-2432,-2498,-2566,-2626,-2673,-2703,-2721,-2733,-2746,-2760,-2775,-2787,-2794,-2800,-2808,-2819,
--2833,-2844,-2849,-2848,-2845,-2846,-2854,-2869,-2886,-2900,-2908,-2911,-2912,-2915,-2920,-2925,-2927,-2926,-2922,-2918,-2915,
--2913,-2914,-2916,-2919,-2923,-2929,-2933,-2934,-2931,-2922,-2912,-2902,-2896,-2892,-2889,-2886,-2880,-2873,-2866,-2860,-2854,
--2848,-2838,-2825,-2810,-2795,-2782,-2772,-2765,-2760,-2754,-2747,-2738,-2727,-2716,-2705,-2696,-2688,-2682,-2678,-2673,-2668,
--2661,-2653,-2644,-2635,-2626,-2616,-2607,-2597,-2588,-2579,-2571,-2563,-2555,-2547,-2538,-2529,-2520,-2510,-2500,-2488,-2476,
--2464,-2452,-2441,-2430,-2418,-2405,-2390,-2376,-2364,-2353,-2345,-2337,-2328,-2320,-2313,-2306,-2298,-2289,-2276,-2261,-2246,
--2234,-2228,-2231,-2242,-2258,-2275,-2290,-2299,-2302,-2297,-2286,-2270,-2251,-2231,-2213,-2196,-2182,-2169,-2157,-2145,-2134,
--2125,-2116,-2108,-2100,-2092,-2085,-2076,-2068,-2058,-2049,-2040,-2032,-2026,-2023,-2020,-2016,-2011,-2003,-1993,-1982,-1970,
--1959,-1948,-1938,-1928,-1919,-1911,-1906,-1902,-1899,-1896,-1891,-1883,-1873,-1861,-1847,-1832,-1817,-1803,-1794,-1790,-1791,
--1795,-1800,-1803,-1803,-1799,-1796,-1794,-1796,-1802,-1811,-1821,-1832,-1845,-1861,-1881,-1905,-1931,-1956,-1978,-1995,-2006,
--2013,-2015,-2011,-2001,-1983,-1960,-1934,-1908,-1886,-1868,-1855,-1843,-1831,-1816,-1798,-1779,-1758,-1737,-1716,-1695,-1676,
--1657,-1640,-1625,-1611,-1597,-1584,-1571,-1556,-1540,-1523,-1506,-1489,-1472,-1456,-1442,-1428,-1414,-1400,-1385,-1370,-1355,
--1340,-1325,-1310,-1296,-1282,-1269,-1258,-1247,-1237,-1226,-1214,-1202,-1190,-1180,-1171,-1163,-1156,-1149,-1143,-1138,-1135,
--1132,-1130,-1126,-1123,-1121,-1122,-1126,-1132,-1138,-1141,-1142,-1140,-1137,-1136,-1136,-1138,-1141,-1144,-1147,-1150,-1153,
--1155,-1157,-1159,-1161,-1164,-1168,-1174,-1179,-1184,-1186,-1185,-1184,-1182,-1181,-1182,-1184,-1187,-1190,-1192,-1196,-1200,
--1204,-1209,-1214,-1216,-1216,-1214,-1211,-1207,-1204,-1200,-1195,-1191,-1187,-1184,-1183,-1182,-1182,-1179,-1172,-1163,-1152,
--1141,-1133,-1126,-1118,-1106,-1090,-1072,-1053,-1037,-1026,-1017,-1009,-997,-983,-968,-954,-946,-941,-938,-933,-925,
--912,-896,-879,-863,-850,-841,-836,-834,-835,-836,-836,-834,-831,-827,-825,-824,-825,-824,-820,-811,-798,
--781,-763,-744,-724,-704,-684,-665,-648,-631,-616,-602,-589,-578,-568,-558,-546,-531,-511,-489,-467,-449,
--433,-420,-405,-389,-370,-351,-333,-315,-298,-277,-252,-223,-194,-166,-140,-114,-85,-52,-15,21,55,
-84,110,136,162,191,219,246,270,293,318,344,373,400,424,445,462,477,490,500,501,493,
-476,455,438,433,447,484,547,633,738,850,954,1034,1076,1079,1054,1021,1000,999,1017,1037,1042,
-1021,978,927,883,861,866,892,933,980,1029,1079,1128,1172,1208,1233,1245,1249,1250,1251,1257,1265,
-1273,1280,1284,1283,1280,1274,1266,1259,1251,1242,1232,1219,1202,1184,1166,1151,1137,1123,1107,1085,1058,
-1029,1002,979,960,943,927,913,901,894,894,898,900,897,885,863,837,809,782,757,729,697,
-660,619,576,536,502,476,459,453,459,479,513,557,609,661,707,745,772,793,813,833,853,
-866,863,838,791,732,678,646,649,691,765,861,967,1071,1165,1239,1284,1291,1255,1180,1079,970,
-873,800,753,726,711,704,706,721,753,801,856,908,941,947,922,868,794,706,616,532,461,
-408,375,362,364,379,404,439,488,554,637,732,833,926,1002,1056,1087,1102,1111,1121,1139,1164,
-1196,1233,1273,1319,1369,1420,1466,1500,1519,1521,1516,1511,1516,1532,1555,1578,1594,1600,1597,1588,1578,
-1569,1559,1549,1540,1533,1531,1536,1547,1559,1571,1579,1583,1584,1583,1583,1587,1601,1628,1670,1722,1777,
-1825,1863,1889,1910,1931,1955,1981,2002,2014,2015,2011,2007,2009,2016,2027,2039,2050,2064,2081,2101,2122,
-2138,2147,2151,2156,2165,2182,2202,2222,2236,2245,2250,2257,2266,2275,2284,2289,2292,2298,2310,2328,2348,
-2367,2382,2394,2405,2417,2430,2443,2453,2462,2471,2484,2503,2525,2546,2564,2577,2585,2592,2599,2606,2613,
-2618,2621,2625,2629,2637,2648,2660,2673,2684,2694,2703,2711,2719,2729,2742,2760,2778,2795,2807,2810,2807,
-2799,2792,2786,2781,2775,2767,2758,2749,2743,2742,2743,2743,2740,2734,2727,2733,2735,2740,2748,2753,2752,
-2742,2724,2702,2679,2659,2646,2641,2647,2660,2676,2690,2698,2700,2701,2704,2711,2719,2722,2716,2701,2685,
-2679,2690,2713,2739,2751,2740,2711,2675,2649,2645,2662,2691,2719,2738,2748,2754,2764,2778,2797,2814,2830,
-2845,2863,2886,2909,2926,2931,2923,2908,2896,2896,2912,2941,2975,3007,3034,3055,3075,3096,3120,3150,3182,
-3217,3251,3282,3308,3329,3345,3360,3377,3399,3424,3450,3474,3494,3511,3528,3550,3577,3607,3635,3656,3668,
-3673,3677,3684,3695,3707,3714,3711,3695,3674,3657,3656,3675,3710,3747,3769,3762,3722,3660,3593,3541,3521,
-3535,3576,3628,3673,3699,3703,3689,3667,3647,3636,3635,3640,3648,3657,3668,3682,3701,3725,3751,3778,3804,
-3830,3859,3890,3922,3952,3979,4004,4028,4056,4089,4124,4157,4186,4212,4240,4273,4314,4359,4402,4438,4467,
-4492,4520,4554,4594,4634,4671,4700,4725,4747,4768,4785,4795,4797,4792,4785,4779,4773,4761,4741,4715,4692,
-4685,4703,4742,4788,4820,4825,4800,4754,4702,4655,4617,4586,4558,4539,4537,4562,4610,4668,4711,4716,4672,
-4589,4487,4392,4324,4287,4275,4277,4283,4290,4300,4314,4331,4349,4360,4359,4345,4318,4284,4248,4214,4184,
-4159,4139,4121,4106,4094,4086,4082,4083,4084,4083,4076,4060,4035,4001,3960,3916,3872,3833,3802,3781,3770,
-3765,3765,3767,3768,3766,3759,3747,3728,3705,3680,3659,3643,3630,3616,3596,3566,3531,3498,3474,3463,3463,
-3466,3467,3462,3456,3452,3456,3467,3482,3493,3497,3496,3492,3490,3491,3492,3492,3488,3481,3474,3468,3464,
-3460,3455,3451,3452,3459,3476,3501,3531,3563,3596,3629,3662,3690,3710,3717,3709,3691,3668,3646,3628,3613,
-3599,3580,3556,3528,3494,3455,3410,3358,3303,3248,3196,3145,3088,3017,2929,2831,2739,2673,2642,2646,2667,
-2681,2671,2632,2573,2510,2459,2422,2391,2357,2310,2255,2201,2159,2134,2124,2115,2099,2070,2030,1988,1949,
-1916,1886,1853,1816,1776,1736,1701,1672,1646,1621,1592,1559,1525,1492,1461,1432,1402,1370,1336,1299,1262,
-1226,1192,1160,1130,1099,1066,1032,996,961,928,897,869,842,815,784,752,718,684,652,620,588,
-554,519,484,450,419,389,360,330,296,260,222,183,145,107,70,35,2,-27,-56,-83,-111,
--141,-171,-203,-236,-270,-304,-338,-371,-401,-429,-455,-482,-512,-545,-581,-618,-652,-684,-714,-744,-775,
--808,-841,-872,-903,-933,-964,-997,-1032,-1066,-1098,-1127,-1153,-1179,-1206,-1235,-1267,-1300,-1332,-1365,-1397,-1430,
--1462,-1495,-1525,-1554,-1581,-1609,-1637,-1668,-1700,-1733,-1763,-1790,-1813,-1833,-1850,-1867,-1885,-1904,-1925,-1945,-1963,
--1976,-1988,-2001,-2019,-2043,-2070,-2097,-2118,-2131,-2137,-2141,-2148,-2160,-2176,-2193,-2207,-2218,-2227,-2237,-2250,-2265,
--2280,-2294,-2306,-2319,-2332,-2346,-2360,-2372,-2380,-2387,-2395,-2404,-2416,-2427,-2433,-2435,-2430,-2423,-2414,-2406,-2400,
--2394,-2390,-2387,-2386,-2384,-2381,-2375,-2367,-2357,-2348,-2342,-2338,-2337,-2335,-2331,-2326,-2320,-2315,-2311,-2308,-2305,
--2303,-2301,-2298,-2296,-2293,-2288,-2283,-2279,-2277,-2275,-2273,-2268,-2259,-2250,-2241,-2235,-2231,-2224,-2213,-2196,-2177,
--2164,-2158,-2161,-2166,-2165,-2154,-2133,-2108,-2085,-2068,-2056,-2045,-2031,-2015,-1999,-1988,-1982,-1979,-1973,-1962,-1946,
--1931,-1921,-1918,-1922,-1925,-1924,-1917,-1905,-1895,-1893,-1902,-1924,-1957,-1996,-2034,-2064,-2081,-2082,-2071,-2054,-2039,
--2028,-2022,-2018,-2014,-2010,-2010,-2018,-2033,-2052,-2067,-2073,-2068,-2059,-2053,-2053,-2059,-2066,-2067,-2063,-2056,-2051,
--2052,-2056,-2060,-2061,-2063,-2069,-2082,-2101,-2118,-2124,-2115,-2097,-2083,-2086,-2106,-2135,-2154,-2148,-2114,-2062,-2013,
--1985,-1985,-2006,-2033,-2052,-2055,-2045,-2028,-2015,-2011,-2018,-2034,-2057,-2085,-2113,-2138,-2158,-2173,-2187,-2202,-2219,
--2231,-2229,-2209,-2171,-2127,-2090,-2071,-2072,-2083,-2094,-2094,-2082,-2067,-2057,-2059,-2071,-2087,-2099,-2104,-2102,-2099,
--2100,-2106,-2118,-2134,-2152,-2170,-2188,-2203,-2216,-2226,-2237,-2254,-2281,-2319,-2366,-2418,-2474,-2531,-2589,-2647,-2700,
--2744,-2775,-2795,-2809,-2822,-2837,-2855,-2871,-2882,-2888,-2891,-2895,-2903,-2914,-2922,-2924,-2920,-2916,-2917,-2928,-2946,
--2967,-2983,-2992,-2993,-2992,-2992,-2995,-3000,-3003,-3003,-2999,-2993,-2987,-2983,-2982,-2983,-2985,-2988,-2992,-2995,-2997,
--2996,-2991,-2983,-2974,-2966,-2960,-2955,-2950,-2945,-2938,-2931,-2925,-2920,-2914,-2906,-2896,-2884,-2869,-2856,-2845,-2837,
--2831,-2826,-2821,-2813,-2803,-2790,-2778,-2767,-2758,-2751,-2745,-2738,-2730,-2721,-2712,-2703,-2696,-2689,-2681,-2672,-2663,
--2653,-2643,-2633,-2623,-2612,-2602,-2591,-2582,-2574,-2567,-2558,-2546,-2533,-2518,-2504,-2491,-2480,-2469,-2457,-2445,-2431,
--2418,-2406,-2396,-2386,-2376,-2366,-2357,-2348,-2340,-2331,-2320,-2307,-2294,-2280,-2269,-2263,-2261,-2263,-2269,-2277,-2286,
--2295,-2301,-2304,-2305,-2302,-2298,-2291,-2281,-2268,-2250,-2228,-2205,-2182,-2163,-2149,-2138,-2130,-2122,-2113,-2103,-2093,
--2083,-2074,-2066,-2058,-2051,-2044,-2039,-2033,-2027,-2019,-2011,-2002,-1993,-1984,-1976,-1968,-1959,-1950,-1941,-1931,-1921,
--1912,-1904,-1898,-1893,-1889,-1885,-1878,-1868,-1852,-1834,-1815,-1799,-1788,-1783,-1782,-1782,-1782,-1782,-1781,-1782,-1785,
--1789,-1792,-1794,-1793,-1791,-1791,-1795,-1804,-1817,-1834,-1852,-1872,-1893,-1917,-1941,-1962,-1977,-1981,-1975,-1960,-1939,
--1918,-1899,-1885,-1873,-1863,-1852,-1838,-1820,-1799,-1774,-1747,-1719,-1692,-1667,-1645,-1626,-1610,-1595,-1582,-1569,-1555,
--1540,-1524,-1507,-1490,-1474,-1460,-1447,-1435,-1423,-1410,-1395,-1380,-1365,-1351,-1339,-1327,-1316,-1305,-1293,-1283,-1273,
--1263,-1252,-1239,-1226,-1212,-1199,-1188,-1178,-1169,-1161,-1154,-1149,-1146,-1144,-1142,-1140,-1138,-1136,-1136,-1139,-1144,
--1151,-1156,-1159,-1159,-1158,-1157,-1157,-1158,-1161,-1165,-1169,-1173,-1177,-1180,-1182,-1183,-1183,-1183,-1184,-1186,-1190,
--1195,-1200,-1203,-1204,-1204,-1203,-1202,-1202,-1203,-1204,-1207,-1210,-1214,-1218,-1222,-1224,-1225,-1225,-1223,-1222,-1220,
--1218,-1214,-1209,-1202,-1195,-1190,-1187,-1187,-1187,-1187,-1183,-1177,-1169,-1161,-1154,-1147,-1138,-1126,-1110,-1093,-1077,
--1063,-1051,-1039,-1025,-1008,-988,-969,-954,-944,-939,-934,-928,-918,-905,-892,-880,-870,-863,-857,-852,-849,
--847,-847,-848,-851,-854,-857,-860,-861,-859,-853,-843,-829,-812,-792,-771,-748,-724,-701,-679,-659,-642,
--626,-610,-595,-581,-569,-561,-554,-545,-532,-515,-494,-474,-456,-442,-429,-415,-398,-379,-360,-343,-329,
--316,-300,-279,-253,-223,-193,-163,-134,-104,-72,-37,-2,31,61,90,119,148,178,206,231,253,
-274,297,323,350,378,403,427,449,469,486,497,499,491,476,460,446,437,433,436,454,495,
-567,671,795,918,1016,1071,1082,1063,1036,1019,1017,1025,1027,1012,977,930,886,860,858,882,924,
-978,1037,1096,1151,1199,1234,1256,1265,1265,1264,1266,1274,1285,1298,1308,1311,1306,1294,1276,1255,1233,
-1210,1186,1160,1133,1105,1079,1057,1042,1032,1022,1010,992,969,943,918,893,869,843,815,789,770,
-762,765,775,782,779,762,733,700,668,642,619,596,568,535,499,467,445,436,442,461,490,
-529,578,640,713,795,876,946,996,1021,1027,1021,1015,1014,1019,1021,1012,986,947,908,883,886,
-924,992,1081,1180,1280,1372,1449,1499,1515,1491,1430,1344,1251,1170,1110,1073,1053,1042,1034,1029,1034,
-1054,1092,1144,1203,1255,1290,1296,1268,1206,1116,1010,904,813,749,716,711,727,756,792,832,877,
-929,986,1046,1105,1157,1198,1225,1235,1230,1213,1190,1170,1159,1164,1188,1230,1284,1344,1401,1448,1481,
-1498,1500,1495,1489,1490,1499,1515,1533,1547,1554,1554,1548,1542,1536,1530,1525,1518,1511,1506,1504,1507,
-1515,1525,1535,1544,1550,1556,1565,1578,1600,1631,1669,1711,1754,1795,1835,1876,1920,1964,2003,2033,2049,
-2052,2046,2039,2037,2041,2047,2053,2056,2059,2065,2078,2097,2118,2135,2144,2149,2154,2163,2177,2194,2209,
-2221,2230,2239,2249,2260,2269,2273,2273,2272,2276,2288,2306,2328,2346,2360,2370,2380,2391,2406,2420,2432,
-2441,2450,2462,2480,2502,2524,2544,2559,2568,2575,2581,2585,2589,2591,2592,2596,2603,2613,2627,2640,2652,
-2663,2672,2682,2691,2700,2710,2720,2731,2744,2758,2771,2781,2787,2790,2791,2790,2787,2781,2772,2762,2754,
-2749,2748,2747,2746,2742,2736,2733,2729,2734,2743,2753,2757,2751,2735,2712,2688,2669,2659,2658,2666,2681,
-2699,2718,2733,2742,2748,2752,2756,2761,2763,2758,2743,2720,2696,2681,2680,2690,2701,2703,2688,2660,2631,
-2615,2619,2641,2671,2696,2710,2715,2718,2727,2745,2770,2794,2814,2828,2837,2844,2850,2851,2848,2841,2834,
-2835,2846,2868,2895,2922,2944,2964,2983,3006,3034,3066,3099,3131,3159,3185,3209,3231,3251,3269,3285,3302,
-3322,3347,3374,3402,3428,3452,3475,3502,3531,3561,3588,3607,3619,3627,3638,3653,3672,3688,3691,3678,3650,
-3620,3602,3607,3637,3678,3711,3719,3692,3636,3568,3510,3480,3485,3519,3569,3617,3652,3666,3662,3645,3625,
-3608,3599,3599,3606,3619,3633,3649,3666,3684,3705,3729,3756,3785,3817,3850,3883,3913,3940,3964,3987,4011,
-4039,4069,4101,4132,4161,4189,4219,4253,4290,4329,4366,4400,4431,4462,4495,4531,4568,4603,4635,4666,4696,
-4725,4752,4771,4779,4776,4768,4759,4753,4746,4734,4710,4675,4639,4612,4603,4610,4627,4639,4639,4626,4605,
-4584,4565,4546,4525,4501,4482,4480,4501,4542,4588,4618,4614,4573,4503,4424,4353,4303,4275,4264,4265,4275,
-4295,4326,4362,4397,4419,4421,4401,4364,4319,4275,4236,4204,4177,4153,4129,4107,4088,4074,4067,4064,4064,
-4063,4055,4040,4017,3987,3953,3916,3880,3847,3819,3799,3786,3781,3780,3780,3780,3777,3771,3760,3744,3722,
-3697,3671,3649,3634,3623,3612,3597,3572,3540,3507,3480,3463,3458,3457,3457,3455,3451,3451,3458,3472,3488,
-3501,3506,3506,3502,3500,3500,3502,3501,3496,3488,3479,3472,3467,3463,3460,3456,3455,3460,3473,3494,3518,
-3542,3562,3575,3582,3583,3580,3573,3565,3558,3555,3557,3561,3564,3561,3550,3530,3503,3471,3432,3386,3334,
-3276,3221,3170,3124,3075,3012,2927,2823,2714,2618,2553,2522,2517,2517,2506,2476,2436,2401,2384,2385,2391,
-2385,2351,2289,2214,2145,2097,2073,2067,2061,2045,2014,1973,1931,1894,1863,1834,1803,1767,1729,1693,1662,
-1636,1613,1588,1558,1524,1488,1454,1423,1393,1363,1330,1293,1255,1217,1182,1150,1122,1093,1063,1030,995,
-960,927,896,867,838,808,776,743,711,681,651,622,591,558,523,490,460,431,402,371,336,
-298,256,215,175,136,99,64,32,3,-21,-44,-68,-95,-125,-160,-195,-230,-263,-294,-325,-356,
--387,-418,-448,-478,-509,-543,-578,-612,-645,-675,-704,-733,-763,-796,-830,-864,-895,-926,-957,-990,-1025,
--1059,-1090,-1117,-1141,-1164,-1190,-1219,-1253,-1289,-1324,-1358,-1390,-1422,-1454,-1486,-1518,-1548,-1576,-1604,-1632,-1662,
--1693,-1725,-1755,-1782,-1805,-1825,-1843,-1861,-1880,-1901,-1921,-1940,-1955,-1967,-1978,-1992,-2009,-2031,-2057,-2081,-2102,
--2118,-2131,-2142,-2155,-2169,-2184,-2196,-2206,-2215,-2224,-2235,-2250,-2265,-2281,-2295,-2307,-2320,-2334,-2350,-2364,-2376,
--2386,-2394,-2403,-2414,-2427,-2439,-2447,-2449,-2445,-2438,-2430,-2422,-2415,-2409,-2404,-2401,-2399,-2398,-2396,-2393,-2387,
--2378,-2368,-2359,-2353,-2350,-2348,-2347,-2345,-2342,-2338,-2334,-2329,-2324,-2321,-2318,-2318,-2317,-2316,-2314,-2311,-2308,
--2306,-2304,-2302,-2297,-2289,-2280,-2271,-2264,-2259,-2253,-2243,-2229,-2212,-2198,-2191,-2189,-2190,-2188,-2179,-2162,-2141,
--2119,-2101,-2086,-2071,-2055,-2039,-2026,-2016,-2009,-2004,-1997,-1985,-1971,-1958,-1950,-1948,-1950,-1953,-1951,-1944,-1932,
--1919,-1911,-1911,-1925,-1951,-1987,-2028,-2066,-2092,-2104,-2102,-2091,-2077,-2065,-2055,-2045,-2037,-2031,-2032,-2042,-2062,
--2085,-2104,-2112,-2108,-2097,-2085,-2079,-2076,-2077,-2077,-2077,-2079,-2086,-2095,-2102,-2104,-2101,-2101,-2109,-2131,-2159,
--2183,-2189,-2176,-2152,-2135,-2140,-2165,-2196,-2205,-2177,-2112,-2031,-1970,-1953,-1987,-2055,-2125,-2170,-2179,-2158,-2127,
--2105,-2102,-2115,-2136,-2156,-2172,-2187,-2204,-2226,-2252,-2275,-2290,-2292,-2280,-2255,-2223,-2192,-2168,-2157,-2158,-2166,
--2173,-2173,-2164,-2150,-2136,-2131,-2135,-2148,-2165,-2181,-2194,-2206,-2218,-2230,-2244,-2256,-2267,-2277,-2289,-2304,-2322,
--2342,-2364,-2389,-2419,-2456,-2500,-2549,-2602,-2656,-2708,-2757,-2800,-2835,-2860,-2875,-2883,-2891,-2902,-2920,-2942,-2961,
--2974,-2979,-2979,-2980,-2984,-2991,-2997,-3000,-2998,-2995,-2997,-3006,-3022,-3041,-3058,-3068,-3071,-3071,-3071,-3073,-3076,
--3078,-3078,-3074,-3068,-3063,-3060,-3059,-3059,-3060,-3061,-3063,-3064,-3065,-3064,-3060,-3053,-3043,-3033,-3025,-3018,-3012,
--3008,-3003,-2998,-2994,-2989,-2983,-2976,-2966,-2954,-2939,-2923,-2909,-2898,-2891,-2887,-2884,-2878,-2870,-2859,-2847,-2837,
--2828,-2822,-2815,-2808,-2797,-2786,-2774,-2764,-2756,-2750,-2744,-2736,-2727,-2717,-2706,-2694,-2682,-2669,-2657,-2645,-2634,
--2625,-2617,-2608,-2596,-2582,-2566,-2550,-2536,-2525,-2514,-2504,-2492,-2481,-2469,-2459,-2449,-2440,-2430,-2419,-2407,-2394,
--2381,-2369,-2357,-2347,-2337,-2328,-2318,-2309,-2300,-2292,-2285,-2281,-2282,-2286,-2293,-2302,-2312,-2321,-2328,-2332,-2332,
--2324,-2309,-2287,-2262,-2238,-2218,-2202,-2189,-2178,-2165,-2150,-2135,-2122,-2110,-2101,-2094,-2086,-2078,-2068,-2059,-2050,
--2042,-2035,-2028,-2021,-2013,-2006,-1998,-1991,-1984,-1976,-1967,-1957,-1945,-1933,-1921,-1912,-1906,-1903,-1901,-1898,-1890,
--1876,-1857,-1835,-1814,-1798,-1789,-1785,-1786,-1787,-1789,-1789,-1789,-1790,-1790,-1789,-1785,-1778,-1769,-1760,-1753,-1748,
--1745,-1745,-1747,-1754,-1769,-1793,-1825,-1862,-1896,-1923,-1937,-1938,-1930,-1916,-1901,-1888,-1876,-1867,-1857,-1846,-1833,
--1816,-1796,-1773,-1750,-1727,-1705,-1684,-1663,-1642,-1621,-1600,-1580,-1560,-1541,-1523,-1506,-1490,-1476,-1465,-1455,-1446,
--1435,-1423,-1408,-1393,-1379,-1367,-1358,-1349,-1340,-1329,-1317,-1305,-1293,-1281,-1269,-1257,-1243,-1229,-1216,-1205,-1196,
--1187,-1180,-1173,-1167,-1161,-1157,-1154,-1152,-1149,-1148,-1148,-1151,-1156,-1163,-1170,-1176,-1178,-1179,-1179,-1179,-1181,
--1184,-1188,-1193,-1198,-1203,-1207,-1209,-1209,-1207,-1204,-1202,-1200,-1202,-1205,-1211,-1216,-1221,-1223,-1223,-1223,-1221,
--1221,-1222,-1225,-1229,-1233,-1237,-1240,-1241,-1241,-1240,-1239,-1239,-1238,-1236,-1232,-1225,-1215,-1204,-1196,-1191,-1189,
--1190,-1191,-1190,-1187,-1182,-1177,-1172,-1166,-1160,-1151,-1139,-1126,-1112,-1098,-1083,-1066,-1047,-1026,-1005,-987,-973,
--963,-954,-943,-930,-915,-900,-887,-879,-875,-873,-872,-871,-870,-869,-870,-874,-879,-886,-891,-893,-891,
--884,-873,-857,-839,-820,-798,-775,-750,-723,-698,-675,-656,-639,-623,-607,-591,-575,-561,-551,-543,-535,
--525,-511,-494,-478,-464,-452,-440,-426,-409,-389,-371,-356,-344,-334,-321,-302,-276,-245,-213,-181,-149,
--119,-88,-56,-25,5,36,67,100,132,163,189,211,231,252,277,304,332,360,385,409,434,
-460,483,498,500,491,474,457,443,433,421,406,393,397,436,522,651,805,951,1060,1116,1121,
-1095,1060,1034,1022,1015,1003,978,942,905,878,872,890,929,982,1042,1100,1153,1195,1224,1242,1251,
-1253,1254,1256,1261,1267,1272,1275,1272,1262,1245,1222,1194,1164,1134,1103,1071,1039,1008,981,962,954,
-955,963,971,973,969,956,938,914,887,856,825,798,781,778,787,802,813,812,795,765,728,
-693,662,635,607,576,542,510,488,482,497,529,576,631,692,759,834,918,1009,1097,1170,1216,
-1230,1214,1180,1144,1118,1106,1105,1103,1091,1069,1041,1020,1016,1036,1078,1136,1203,1274,1343,1404,1452,
-1479,1480,1455,1413,1365,1324,1296,1281,1274,1269,1262,1256,1254,1265,1293,1337,1395,1457,1513,1551,1560,
-1533,1474,1392,1306,1234,1189,1177,1192,1226,1269,1312,1353,1391,1424,1452,1474,1490,1501,1507,1507,1495,
-1464,1411,1340,1261,1192,1147,1138,1163,1214,1279,1343,1396,1435,1457,1465,1464,1457,1450,1448,1451,1460,
-1471,1483,1491,1495,1494,1491,1486,1479,1468,1456,1442,1431,1426,1427,1434,1445,1457,1471,1487,1509,1538,
-1576,1619,1664,1708,1750,1793,1839,1892,1950,2005,2050,2076,2083,2075,2062,2054,2054,2062,2072,2079,2081,
-2080,2081,2087,2097,2109,2120,2126,2132,2139,2150,2163,2178,2189,2198,2206,2216,2228,2242,2252,2257,2257,
-2258,2264,2277,2295,2313,2327,2336,2343,2351,2363,2378,2394,2406,2415,2424,2437,2455,2478,2502,2524,2541,
-2553,2560,2565,2567,2566,2564,2564,2568,2577,2590,2606,2621,2635,2648,2661,2675,2688,2699,2706,2709,2712,
-2716,2725,2738,2752,2766,2777,2783,2786,2785,2782,2776,2770,2765,2761,2757,2752,2745,2737,2730,2729,2723,
-2723,2726,2727,2723,2712,2696,2680,2671,2672,2684,2703,2724,2744,2759,2768,2770,2768,2763,2757,2754,2754,
-2753,2749,2738,2719,2695,2673,2655,2644,2634,2623,2607,2590,2578,2579,2594,2618,2642,2659,2665,2665,2668,
-2680,2702,2729,2753,2768,2772,2768,2763,2759,2759,2763,2770,2781,2797,2817,2839,2860,2875,2887,2900,2919,
-2946,2980,3017,3050,3075,3095,3111,3129,3149,3171,3193,3214,3233,3253,3277,3304,3333,3361,3388,3413,3437,
-3460,3483,3501,3516,3529,3543,3562,3587,3613,3632,3635,3620,3594,3571,3564,3581,3614,3649,3666,3651,3603,
-3538,3476,3436,3430,3455,3499,3546,3583,3603,3608,3600,3586,3572,3561,3556,3560,3572,3590,3612,3634,3655,
-3674,3693,3716,3743,3774,3808,3842,3872,3897,3920,3942,3965,3989,4016,4045,4073,4101,4129,4159,4191,4224,
-4258,4292,4325,4359,4395,4432,4470,4506,4538,4566,4592,4620,4651,4684,4714,4734,4741,4736,4725,4714,4708,
-4704,4697,4680,4654,4623,4595,4574,4562,4554,4546,4536,4525,4518,4515,4513,4506,4489,4464,4440,4428,4433,
-4452,4473,4480,4465,4427,4378,4332,4299,4285,4285,4296,4315,4341,4377,4419,4460,4488,4493,4471,4425,4367,
-4308,4258,4219,4189,4164,4140,4114,4089,4068,4053,4045,4042,4039,4032,4017,3995,3967,3935,3903,3874,3848,
-3827,3810,3799,3793,3790,3788,3784,3779,3771,3759,3746,3729,3709,3685,3660,3637,3619,3606,3595,3583,3565,
-3542,3515,3490,3471,3460,3454,3451,3448,3446,3449,3456,3469,3483,3495,3502,3504,3505,3506,3508,3510,3507,
-3500,3489,3479,3471,3469,3468,3469,3468,3467,3470,3478,3491,3507,3520,3528,3528,3521,3511,3500,3492,3489,
-3491,3499,3511,3524,3532,3531,3519,3498,3471,3439,3403,3362,3312,3257,3201,3149,3103,3059,3006,2933,2837,
-2727,2619,2532,2474,2443,2423,2400,2367,2330,2304,2301,2322,2351,2366,2347,2290,2208,2124,2062,2030,2024,
-2028,2023,2000,1961,1917,1876,1843,1818,1793,1763,1728,1690,1656,1627,1602,1578,1550,1518,1483,1447,1414,
-1383,1354,1322,1287,1249,1211,1174,1142,1112,1083,1053,1021,987,953,921,891,861,831,799,767,735,
-705,677,650,622,592,560,528,497,469,440,408,371,328,283,239,198,161,127,94,62,32,
-6,-15,-34,-54,-80,-112,-149,-189,-227,-261,-292,-322,-353,-386,-419,-452,-483,-514,-545,-576,-608,
--639,-669,-696,-725,-755,-789,-823,-858,-890,-921,-951,-984,-1018,-1053,-1085,-1113,-1138,-1161,-1186,-1216,-1249,
--1285,-1321,-1355,-1387,-1418,-1450,-1482,-1513,-1543,-1572,-1600,-1629,-1658,-1689,-1720,-1748,-1773,-1795,-1815,-1835,-1857,
--1879,-1901,-1922,-1939,-1953,-1965,-1977,-1991,-2008,-2028,-2049,-2069,-2088,-2106,-2123,-2139,-2156,-2172,-2185,-2195,-2203,
--2210,-2220,-2234,-2250,-2267,-2283,-2297,-2310,-2324,-2338,-2354,-2370,-2384,-2395,-2405,-2415,-2427,-2439,-2450,-2458,-2461,
--2458,-2453,-2446,-2438,-2432,-2425,-2420,-2417,-2415,-2414,-2413,-2411,-2406,-2398,-2388,-2379,-2371,-2366,-2365,-2365,-2366,
--2368,-2367,-2365,-2360,-2353,-2347,-2343,-2341,-2341,-2341,-2339,-2337,-2334,-2332,-2331,-2330,-2327,-2321,-2314,-2306,-2299,
--2293,-2286,-2277,-2264,-2249,-2236,-2226,-2221,-2219,-2215,-2207,-2193,-2174,-2154,-2135,-2117,-2100,-2083,-2067,-2053,-2042,
--2032,-2022,-2012,-2000,-1989,-1981,-1976,-1976,-1978,-1979,-1976,-1968,-1955,-1941,-1929,-1924,-1931,-1953,-1988,-2031,-2073,
--2107,-2126,-2130,-2124,-2113,-2100,-2087,-2073,-2060,-2051,-2051,-2063,-2086,-2114,-2137,-2149,-2147,-2135,-2119,-2105,-2096,
--2092,-2092,-2097,-2108,-2122,-2136,-2145,-2146,-2143,-2142,-2153,-2178,-2209,-2232,-2236,-2220,-2195,-2181,-2190,-2217,-2240,
--2235,-2184,-2097,-2004,-1945,-1948,-2012,-2113,-2209,-2269,-2282,-2260,-2230,-2213,-2220,-2241,-2263,-2275,-2277,-2279,-2292,
--2319,-2354,-2383,-2391,-2373,-2333,-2282,-2236,-2206,-2197,-2204,-2219,-2232,-2237,-2233,-2222,-2211,-2205,-2207,-2217,-2231,
--2247,-2263,-2279,-2297,-2317,-2338,-2357,-2373,-2387,-2401,-2419,-2443,-2475,-2512,-2552,-2593,-2634,-2677,-2721,-2764,-2807,
--2846,-2882,-2914,-2940,-2959,-2970,-2974,-2975,-2977,-2986,-3002,-3023,-3043,-3056,-3060,-3059,-3055,-3055,-3060,-3067,-3074,
--3079,-3081,-3084,-3090,-3101,-3115,-3129,-3141,-3148,-3153,-3155,-3156,-3157,-3156,-3154,-3150,-3146,-3142,-3140,-3139,-3139,
--3139,-3139,-3139,-3138,-3137,-3134,-3129,-3122,-3112,-3101,-3091,-3083,-3078,-3074,-3071,-3067,-3063,-3057,-3049,-3041,-3030,
--3017,-3002,-2985,-2969,-2957,-2949,-2944,-2942,-2938,-2931,-2921,-2910,-2901,-2894,-2890,-2885,-2878,-2867,-2852,-2838,-2825,
--2816,-2809,-2803,-2797,-2788,-2778,-2767,-2756,-2744,-2731,-2717,-2702,-2688,-2675,-2663,-2651,-2637,-2622,-2607,-2592,-2579,
--2568,-2558,-2548,-2537,-2526,-2515,-2505,-2496,-2488,-2479,-2470,-2458,-2444,-2429,-2414,-2400,-2387,-2377,-2368,-2360,-2351,
--2340,-2328,-2316,-2306,-2299,-2297,-2298,-2302,-2308,-2315,-2322,-2328,-2331,-2331,-2325,-2314,-2301,-2287,-2274,-2262,-2250,
--2236,-2218,-2198,-2178,-2161,-2149,-2141,-2134,-2125,-2114,-2101,-2088,-2076,-2066,-2059,-2052,-2044,-2035,-2024,-2014,-2004,
--1996,-1989,-1982,-1975,-1967,-1959,-1950,-1940,-1932,-1925,-1919,-1913,-1904,-1892,-1875,-1856,-1837,-1821,-1811,-1807,-1807,
--1808,-1808,-1806,-1802,-1797,-1792,-1787,-1782,-1776,-1770,-1764,-1757,-1749,-1739,-1727,-1715,-1707,-1708,-1720,-1744,-1776,
--1812,-1843,-1866,-1879,-1881,-1877,-1869,-1860,-1852,-1844,-1836,-1827,-1816,-1805,-1793,-1781,-1769,-1758,-1746,-1731,-1712,
--1689,-1662,-1634,-1605,-1579,-1556,-1535,-1517,-1501,-1487,-1475,-1465,-1456,-1445,-1433,-1419,-1405,-1393,-1383,-1375,-1367,
--1357,-1344,-1330,-1315,-1300,-1287,-1275,-1262,-1250,-1238,-1228,-1219,-1213,-1209,-1204,-1198,-1191,-1184,-1178,-1173,-1169,
--1166,-1165,-1165,-1168,-1173,-1180,-1187,-1193,-1197,-1199,-1200,-1200,-1202,-1206,-1210,-1215,-1220,-1224,-1228,-1230,-1231,
--1229,-1226,-1222,-1219,-1219,-1221,-1225,-1231,-1237,-1241,-1242,-1241,-1239,-1237,-1237,-1239,-1242,-1246,-1251,-1254,-1255,
--1256,-1256,-1256,-1257,-1257,-1255,-1249,-1241,-1229,-1215,-1204,-1196,-1192,-1191,-1192,-1192,-1191,-1189,-1186,-1184,-1181,
--1178,-1173,-1165,-1154,-1141,-1124,-1105,-1085,-1065,-1046,-1030,-1016,-1004,-992,-977,-959,-940,-920,-904,-893,-887,
--884,-884,-884,-885,-887,-891,-898,-905,-913,-919,-921,-920,-914,-904,-891,-873,-853,-832,-807,-781,-754,
--726,-699,-676,-657,-641,-625,-609,-591,-573,-557,-544,-534,-526,-518,-508,-496,-484,-472,-461,-448,-434,
--418,-401,-385,-373,-362,-351,-336,-315,-289,-260,-228,-196,-165,-134,-105,-76,-49,-22,6,38,74,
-110,142,168,189,208,229,256,287,318,345,367,389,414,444,474,497,505,498,480,460,444,
-433,420,399,373,355,367,429,547,708,880,1029,1127,1166,1156,1121,1083,1053,1032,1013,989,958,
-926,904,903,926,969,1025,1082,1131,1167,1190,1204,1212,1219,1225,1230,1233,1231,1226,1217,1205,1191,
-1174,1153,1127,1098,1069,1042,1018,997,978,960,945,938,943,961,991,1026,1059,1082,1094,1093,1083,
-1065,1044,1022,1005,996,998,1010,1027,1040,1042,1031,1006,973,937,901,865,828,788,747,711,686,
-678,689,719,763,816,877,943,1017,1096,1178,1255,1314,1345,1343,1312,1264,1214,1176,1156,1150,1149,
-1145,1131,1112,1095,1090,1099,1125,1162,1205,1249,1294,1336,1372,1398,1411,1411,1400,1387,1375,1368,1365,
-1363,1359,1353,1348,1348,1356,1375,1406,1447,1496,1547,1593,1623,1632,1617,1585,1548,1520,1513,1530,1567,
-1616,1670,1721,1767,1806,1833,1848,1850,1844,1836,1828,1817,1795,1746,1662,1545,1410,1281,1183,1131,1125,
-1154,1199,1245,1281,1305,1320,1328,1331,1328,1323,1318,1318,1327,1344,1366,1386,1401,1405,1401,1391,1376,
-1359,1343,1327,1316,1310,1312,1321,1335,1353,1373,1399,1432,1475,1528,1587,1646,1702,1754,1804,1858,1916,
-1977,2032,2073,2094,2094,2081,2066,2057,2060,2071,2085,2097,2103,2104,2103,2103,2103,2104,2105,2108,2113,
-2123,2136,2151,2163,2172,2178,2184,2195,2208,2223,2235,2244,2249,2255,2265,2279,2294,2306,2314,2318,2322,
-2329,2342,2357,2371,2382,2391,2401,2414,2434,2456,2479,2500,2516,2528,2538,2544,2548,2548,2547,2548,2552,
-2562,2577,2593,2608,2622,2637,2654,2672,2690,2703,2708,2708,2705,2704,2710,2722,2737,2751,2761,2767,2769,
-2769,2769,2769,2770,2770,2769,2765,2758,2749,2738,2729,2723,2738,2728,2716,2700,2682,2663,2649,2644,2654,
-2677,2709,2744,2773,2792,2800,2796,2784,2766,2744,2723,2707,2699,2698,2701,2703,2698,2684,2661,2632,2603,
-2576,2556,2542,2537,2542,2557,2577,2599,2615,2621,2620,2617,2618,2628,2645,2664,2678,2682,2677,2669,2662,
-2663,2673,2689,2708,2730,2752,2773,2792,2807,2818,2829,2844,2866,2896,2930,2965,2993,3013,3027,3041,3058,
-3082,3110,3139,3165,3187,3209,3231,3257,3284,3311,3335,3355,3371,3384,3396,3409,3421,3436,3455,3478,3504,
-3527,3541,3543,3534,3522,3519,3531,3558,3589,3609,3602,3565,3506,3443,3397,3381,3396,3433,3475,3510,3531,
-3538,3537,3532,3527,3523,3521,3522,3530,3545,3567,3594,3620,3643,3662,3681,3704,3732,3764,3798,3830,3856,
-3878,3897,3918,3942,3968,3995,4022,4047,4071,4097,4125,4155,4187,4220,4252,4285,4320,4358,4398,4436,4469,
-4496,4519,4542,4569,4601,4636,4667,4687,4693,4689,4680,4671,4667,4664,4659,4647,4628,4606,4584,4565,4549,
-4535,4521,4509,4502,4503,4508,4512,4508,4491,4463,4432,4409,4396,4391,4384,4368,4339,4303,4269,4249,4247,
-4262,4289,4322,4359,4400,4443,4484,4514,4523,4505,4460,4397,4330,4269,4221,4187,4162,4139,4116,4091,4068,
-4048,4033,4024,4017,4009,3996,3977,3951,3922,3893,3866,3844,3827,3814,3805,3799,3794,3789,3784,3776,3765,
-3751,3736,3721,3706,3690,3671,3650,3628,3607,3590,3575,3563,3549,3532,3513,3493,3475,3461,3450,3442,3436,
-3433,3433,3439,3450,3462,3474,3484,3492,3499,3505,3510,3512,3507,3498,3485,3474,3468,3468,3472,3477,3482,
-3485,3488,3494,3501,3506,3508,3503,3494,3483,3474,3469,3469,3472,3479,3486,3495,3501,3501,3494,3478,3454,
-3426,3398,3367,3332,3288,3235,3175,3115,3061,3012,2962,2900,2821,2727,2631,2548,2488,2450,2423,2393,2352,
-2304,2262,2240,2243,2260,2272,2257,2208,2134,2056,1997,1971,1975,1991,2000,1988,1955,1909,1863,1828,1802,
-1781,1757,1725,1689,1652,1618,1590,1566,1540,1510,1476,1440,1404,1371,1339,1307,1274,1238,1202,1168,1136,
-1105,1075,1043,1010,976,943,912,883,854,825,794,762,732,704,677,651,623,594,564,534,506,
-478,447,409,364,315,266,223,187,158,131,103,74,44,18,-3,-21,-39,-64,-97,-136,-179,
--219,-255,-288,-319,-352,-387,-422,-456,-487,-516,-544,-573,-603,-633,-662,-691,-720,-751,-784,-819,-853,
--885,-915,-945,-976,-1009,-1045,-1079,-1110,-1137,-1163,-1189,-1218,-1250,-1284,-1319,-1352,-1385,-1416,-1447,-1478,-1508,
--1538,-1566,-1595,-1625,-1657,-1688,-1718,-1744,-1767,-1787,-1807,-1829,-1852,-1877,-1900,-1920,-1936,-1950,-1963,-1977,-1993,
--2011,-2030,-2048,-2065,-2081,-2097,-2114,-2132,-2150,-2166,-2178,-2188,-2196,-2206,-2218,-2234,-2252,-2270,-2287,-2301,-2314,
--2327,-2342,-2358,-2375,-2390,-2403,-2414,-2424,-2434,-2444,-2453,-2460,-2463,-2464,-2461,-2457,-2452,-2447,-2442,-2438,-2436,
--2435,-2435,-2433,-2430,-2425,-2419,-2411,-2403,-2395,-2389,-2385,-2384,-2385,-2388,-2390,-2389,-2386,-2381,-2375,-2370,-2367,
--2366,-2365,-2364,-2361,-2357,-2355,-2354,-2354,-2354,-2352,-2347,-2340,-2333,-2326,-2318,-2308,-2296,-2283,-2270,-2261,-2255,
--2252,-2248,-2240,-2228,-2210,-2189,-2167,-2146,-2127,-2110,-2094,-2080,-2067,-2055,-2043,-2032,-2021,-2013,-2006,-2003,-2001,
--1999,-1996,-1990,-1981,-1970,-1958,-1948,-1943,-1950,-1970,-2004,-2047,-2090,-2124,-2145,-2152,-2147,-2137,-2124,-2110,-2095,
--2080,-2070,-2068,-2079,-2101,-2129,-2155,-2169,-2170,-2160,-2146,-2132,-2123,-2119,-2121,-2128,-2139,-2154,-2169,-2179,-2183,
--2183,-2187,-2199,-2221,-2244,-2257,-2254,-2236,-2216,-2210,-2223,-2247,-2260,-2239,-2176,-2087,-2005,-1970,-2003,-2095,-2215,
--2319,-2378,-2386,-2361,-2334,-2328,-2345,-2374,-2398,-2405,-2400,-2395,-2406,-2435,-2472,-2499,-2499,-2465,-2406,-2340,-2286,
--2255,-2250,-2262,-2280,-2292,-2296,-2292,-2285,-2282,-2286,-2296,-2310,-2325,-2340,-2355,-2372,-2391,-2413,-2437,-2462,-2487,
--2513,-2543,-2580,-2623,-2672,-2723,-2772,-2819,-2862,-2901,-2937,-2968,-2995,-3017,-3035,-3049,-3060,-3068,-3073,-3075,-3074,
--3075,-3079,-3089,-3104,-3119,-3129,-3133,-3130,-3125,-3122,-3126,-3135,-3147,-3158,-3166,-3171,-3174,-3178,-3187,-3199,-3213,
--3226,-3235,-3241,-3242,-3240,-3237,-3233,-3229,-3226,-3223,-3221,-3220,-3218,-3217,-3215,-3214,-3211,-3209,-3204,-3199,-3192,
--3183,-3173,-3164,-3155,-3149,-3144,-3140,-3135,-3128,-3121,-3112,-3102,-3091,-3078,-3064,-3049,-3034,-3021,-3012,-3007,-3002,
--2996,-2988,-2977,-2965,-2956,-2951,-2950,-2948,-2943,-2934,-2920,-2904,-2890,-2879,-2871,-2865,-2859,-2852,-2843,-2833,-2823,
--2811,-2798,-2783,-2765,-2746,-2727,-2709,-2692,-2675,-2660,-2645,-2632,-2620,-2610,-2601,-2592,-2581,-2570,-2558,-2547,-2537,
--2527,-2519,-2511,-2502,-2492,-2479,-2465,-2449,-2433,-2418,-2405,-2394,-2384,-2374,-2364,-2353,-2344,-2335,-2329,-2324,-2320,
--2316,-2312,-2310,-2310,-2311,-2314,-2317,-2318,-2317,-2315,-2312,-2306,-2297,-2283,-2266,-2246,-2228,-2213,-2203,-2196,-2188,
--2178,-2165,-2148,-2132,-2116,-2104,-2093,-2083,-2072,-2060,-2048,-2035,-2023,-2012,-2003,-1997,-1992,-1987,-1983,-1978,-1971,
--1963,-1953,-1944,-1935,-1927,-1917,-1905,-1891,-1875,-1860,-1848,-1840,-1835,-1832,-1827,-1820,-1812,-1802,-1794,-1788,-1784,
--1782,-1781,-1781,-1780,-1776,-1769,-1758,-1744,-1731,-1723,-1722,-1730,-1747,-1767,-1788,-1806,-1818,-1824,-1827,-1827,-1827,
--1825,-1822,-1817,-1810,-1800,-1790,-1780,-1772,-1766,-1761,-1755,-1745,-1729,-1708,-1682,-1655,-1629,-1606,-1585,-1566,-1547,
--1528,-1509,-1491,-1475,-1461,-1447,-1435,-1422,-1410,-1400,-1391,-1383,-1373,-1361,-1347,-1331,-1314,-1299,-1286,-1274,-1263,
--1252,-1242,-1235,-1230,-1228,-1227,-1226,-1222,-1217,-1210,-1203,-1198,-1194,-1192,-1191,-1191,-1193,-1196,-1201,-1206,-1210,
--1214,-1215,-1216,-1217,-1220,-1223,-1228,-1233,-1237,-1241,-1244,-1246,-1248,-1249,-1249,-1247,-1245,-1244,-1244,-1248,-1252,
--1258,-1262,-1264,-1263,-1260,-1257,-1254,-1252,-1254,-1257,-1260,-1264,-1267,-1269,-1270,-1271,-1271,-1272,-1270,-1265,-1257,
--1245,-1232,-1218,-1207,-1200,-1196,-1194,-1194,-1194,-1193,-1193,-1192,-1192,-1191,-1188,-1182,-1170,-1155,-1136,-1115,-1096,
--1080,-1066,-1054,-1042,-1027,-1008,-986,-963,-942,-927,-917,-911,-907,-903,-898,-894,-894,-899,-910,-923,-936,
--946,-951,-952,-949,-943,-934,-923,-906,-885,-859,-829,-796,-764,-733,-706,-683,-664,-646,-629,-611,-592,
--572,-555,-541,-530,-521,-514,-506,-497,-488,-477,-465,-452,-438,-424,-412,-401,-391,-380,-366,-347,-324,
--299,-272,-245,-216,-185,-154,-125,-98,-75,-53,-28,3,40,80,116,144,165,183,205,235,269,
-303,331,351,369,390,420,455,487,506,507,492,471,452,438,425,405,377,349,342,378,469,
-613,785,952,1084,1163,1191,1181,1152,1119,1085,1050,1012,973,941,928,941,981,1042,1108,1166,1203,
-1219,1217,1207,1200,1200,1207,1217,1222,1219,1207,1188,1168,1147,1125,1100,1071,1039,1011,989,978,977,
-980,985,990,999,1018,1051,1098,1155,1214,1265,1305,1330,1343,1347,1345,1339,1334,1330,1333,1341,1355,
-1371,1382,1385,1376,1356,1325,1287,1243,1194,1143,1092,1045,1003,972,954,949,959,982,1020,1070,1130,
-1197,1264,1323,1365,1382,1373,1342,1300,1259,1228,1212,1206,1205,1201,1192,1179,1171,1173,1188,1214,1248,
-1283,1316,1345,1369,1387,1400,1405,1404,1400,1395,1392,1390,1387,1382,1376,1370,1368,1372,1381,1394,1409,
-1427,1449,1476,1508,1540,1568,1587,1598,1604,1614,1634,1665,1709,1762,1822,1886,1949,2007,2052,2081,2094,
-2095,2093,2092,2089,2069,2016,1918,1778,1613,1452,1321,1234,1188,1168,1154,1135,1106,1077,1054,1044,1045,
-1052,1059,1066,1077,1097,1127,1162,1195,1218,1225,1218,1201,1181,1162,1148,1138,1135,1138,1150,1170,1196,
-1228,1264,1306,1355,1413,1479,1549,1619,1685,1746,1804,1862,1922,1981,2033,2070,2090,2092,2082,2070,2063,
-2064,2073,2086,2098,2107,2113,2115,2114,2111,2108,2105,2106,2112,2124,2138,2151,2161,2167,2172,2179,2190,
-2205,2220,2233,2243,2251,2261,2272,2285,2296,2302,2305,2306,2310,2318,2330,2343,2354,2362,2370,2381,2397,
-2417,2438,2457,2472,2485,2497,2509,2521,2532,2538,2542,2546,2553,2563,2576,2590,2602,2614,2627,2643,2664,
-2684,2699,2706,2706,2703,2701,2706,2715,2727,2736,2741,2742,2742,2743,2747,2753,2759,2764,2765,2765,2762,
-2758,2753,2746,2738,2766,2749,2723,2690,2657,2629,2613,2614,2632,2663,2700,2736,2764,2781,2786,2781,2767,
-2744,2716,2685,2658,2641,2637,2644,2657,2666,2663,2646,2618,2585,2554,2533,2523,2524,2534,2547,2561,2571,
-2576,2575,2570,2564,2562,2565,2572,2578,2581,2579,2575,2574,2579,2593,2613,2637,2659,2679,2697,2713,2730,
-2747,2765,2785,2807,2831,2858,2886,2911,2932,2950,2966,2984,3008,3037,3069,3101,3128,3152,3175,3197,3222,
-3248,3272,3290,3304,3312,3319,3328,3340,3355,3374,3394,3413,3430,3441,3446,3446,3445,3450,3465,3491,3520,
-3541,3541,3515,3466,3409,3361,3337,3343,3371,3409,3442,3463,3471,3471,3471,3475,3482,3490,3496,3503,3512,
-3528,3550,3576,3602,3625,3645,3664,3687,3716,3749,3783,3813,3837,3857,3875,3895,3919,3946,3974,3999,4022,
-4044,4067,4092,4121,4151,4183,4216,4250,4287,4325,4362,4396,4423,4445,4466,4489,4517,4551,4585,4612,4629,
-4634,4632,4627,4623,4623,4621,4615,4603,4585,4566,4549,4536,4525,4515,4505,4498,4497,4502,4510,4514,4510,
-4493,4467,4440,4415,4397,4380,4358,4328,4289,4250,4220,4206,4211,4230,4259,4293,4329,4368,4405,4436,4453,
-4447,4417,4368,4309,4251,4203,4167,4141,4119,4099,4078,4056,4036,4019,4006,3995,3985,3973,3957,3937,3913,
-3887,3864,3844,3829,3818,3810,3803,3796,3787,3777,3766,3754,3740,3724,3708,3694,3680,3668,3655,3639,3620,
-3599,3578,3559,3543,3529,3516,3503,3489,3476,3463,3450,3439,3429,3422,3419,3421,3428,3438,3450,3463,3475,
-3486,3496,3503,3506,3501,3491,3479,3469,3463,3464,3469,3477,3485,3492,3498,3503,3505,3502,3492,3478,3464,
-3454,3451,3456,3466,3475,3481,3481,3478,3471,3461,3447,3428,3404,3379,3354,3330,3302,3265,3216,3155,3088,
-3024,2966,2912,2856,2791,2715,2635,2564,2509,2473,2446,2415,2370,2311,2248,2197,2167,2157,2150,2132,2090,
-2029,1966,1919,1903,1916,1944,1966,1967,1942,1900,1854,1815,1786,1765,1744,1717,1683,1646,1611,1581,1555,
-1529,1502,1470,1434,1397,1361,1326,1292,1259,1226,1194,1162,1132,1102,1071,1038,1003,968,935,904,875,
-848,820,791,762,733,705,677,649,620,591,563,536,510,482,448,405,356,305,258,221,194,
-172,150,124,94,61,33,10,-8,-26,-51,-85,-126,-170,-212,-249,-282,-314,-348,-384,-421,-457,
--488,-517,-543,-570,-599,-629,-659,-688,-718,-749,-782,-817,-851,-883,-913,-942,-972,-1003,-1037,-1070,-1102,
--1132,-1159,-1186,-1214,-1245,-1278,-1312,-1345,-1379,-1412,-1443,-1474,-1502,-1530,-1558,-1587,-1619,-1652,-1686,-1716,-1742,
--1763,-1782,-1802,-1824,-1848,-1873,-1895,-1914,-1929,-1943,-1958,-1975,-1994,-2014,-2033,-2050,-2066,-2080,-2094,-2110,-2126,
--2141,-2156,-2169,-2182,-2194,-2207,-2223,-2240,-2257,-2275,-2290,-2304,-2318,-2331,-2346,-2361,-2378,-2394,-2409,-2421,-2432,
--2441,-2449,-2456,-2462,-2466,-2469,-2469,-2466,-2462,-2458,-2455,-2454,-2454,-2455,-2455,-2453,-2449,-2444,-2440,-2435,-2430,
--2424,-2418,-2412,-2407,-2404,-2405,-2406,-2407,-2406,-2403,-2398,-2395,-2393,-2393,-2393,-2391,-2388,-2384,-2381,-2380,-2381,
--2381,-2381,-2378,-2373,-2366,-2358,-2350,-2340,-2328,-2315,-2303,-2293,-2288,-2285,-2283,-2277,-2266,-2249,-2228,-2204,-2180,
--2159,-2141,-2125,-2111,-2099,-2087,-2076,-2066,-2057,-2050,-2044,-2038,-2031,-2023,-2014,-2005,-1997,-1988,-1980,-1974,-1973,
--1980,-1998,-2028,-2066,-2105,-2137,-2157,-2163,-2160,-2151,-2140,-2127,-2114,-2100,-2089,-2086,-2094,-2112,-2136,-2158,-2172,
--2178,-2175,-2169,-2165,-2163,-2163,-2166,-2170,-2176,-2184,-2194,-2203,-2212,-2220,-2230,-2243,-2257,-2268,-2269,-2259,-2243,
--2231,-2232,-2245,-2260,-2256,-2220,-2152,-2076,-2025,-2029,-2099,-2216,-2345,-2444,-2491,-2488,-2458,-2433,-2432,-2456,-2490,
--2515,-2523,-2518,-2513,-2523,-2549,-2581,-2601,-2596,-2560,-2503,-2441,-2391,-2361,-2352,-2355,-2362,-2366,-2366,-2363,-2362,
--2365,-2374,-2387,-2403,-2420,-2438,-2457,-2478,-2501,-2526,-2554,-2586,-2624,-2667,-2717,-2773,-2832,-2889,-2942,-2987,-3025,
--3057,-3085,-3110,-3131,-3147,-3156,-3161,-3163,-3164,-3167,-3170,-3173,-3173,-3172,-3172,-3174,-3180,-3189,-3197,-3202,-3202,
--3198,-3196,-3198,-3207,-3221,-3236,-3247,-3252,-3252,-3252,-3256,-3267,-3282,-3299,-3313,-3321,-3323,-3320,-3316,-3312,-3309,
--3308,-3306,-3304,-3301,-3298,-3295,-3293,-3290,-3286,-3281,-3275,-3268,-3261,-3253,-3245,-3237,-3228,-3220,-3212,-3205,-3198,
--3191,-3183,-3174,-3164,-3154,-3142,-3130,-3116,-3103,-3091,-3080,-3072,-3064,-3055,-3043,-3030,-3017,-3008,-3003,-3002,-3003,
--3002,-2996,-2986,-2972,-2959,-2947,-2938,-2931,-2924,-2917,-2908,-2898,-2888,-2877,-2864,-2849,-2830,-2808,-2785,-2762,-2740,
--2721,-2703,-2687,-2673,-2661,-2651,-2642,-2633,-2624,-2614,-2603,-2590,-2577,-2565,-2554,-2545,-2538,-2531,-2522,-2510,-2495,
--2477,-2459,-2442,-2428,-2417,-2407,-2398,-2390,-2381,-2373,-2365,-2358,-2350,-2341,-2331,-2322,-2315,-2312,-2312,-2315,-2318,
--2321,-2323,-2323,-2320,-2314,-2304,-2293,-2281,-2270,-2262,-2256,-2252,-2245,-2236,-2223,-2208,-2191,-2174,-2158,-2142,-2127,
--2113,-2100,-2088,-2077,-2065,-2054,-2042,-2031,-2021,-2014,-2009,-2004,-1998,-1991,-1982,-1972,-1964,-1958,-1952,-1945,-1934,
--1920,-1905,-1889,-1876,-1865,-1855,-1846,-1836,-1825,-1814,-1805,-1799,-1797,-1796,-1797,-1798,-1799,-1799,-1797,-1792,-1785,
--1777,-1769,-1764,-1762,-1764,-1769,-1776,-1782,-1787,-1792,-1797,-1804,-1811,-1817,-1820,-1819,-1814,-1804,-1791,-1777,-1764,
--1754,-1745,-1736,-1725,-1710,-1693,-1673,-1654,-1637,-1622,-1609,-1594,-1577,-1555,-1531,-1507,-1484,-1465,-1450,-1437,-1427,
--1418,-1409,-1399,-1388,-1376,-1361,-1346,-1330,-1315,-1302,-1291,-1280,-1270,-1259,-1250,-1242,-1238,-1237,-1237,-1237,-1236,
--1232,-1228,-1223,-1220,-1219,-1219,-1220,-1222,-1223,-1226,-1228,-1231,-1234,-1236,-1236,-1237,-1238,-1240,-1243,-1247,-1251,
--1255,-1259,-1262,-1266,-1270,-1274,-1276,-1277,-1276,-1274,-1272,-1273,-1276,-1280,-1285,-1289,-1290,-1288,-1284,-1280,-1277,
--1275,-1276,-1278,-1281,-1284,-1285,-1286,-1287,-1287,-1287,-1287,-1284,-1278,-1269,-1257,-1243,-1231,-1220,-1213,-1208,-1205,
--1203,-1201,-1200,-1200,-1200,-1199,-1196,-1188,-1176,-1160,-1142,-1124,-1109,-1098,-1088,-1077,-1060,-1036,-1006,-975,-950,
--934,-930,-932,-937,-937,-930,-919,-910,-907,-914,-930,-950,-968,-981,-986,-985,-983,-980,-976,-969,-954,
--931,-899,-861,-822,-784,-751,-724,-700,-680,-660,-639,-618,-597,-577,-559,-545,-533,-522,-514,-505,-498,
--489,-480,-469,-457,-445,-434,-426,-417,-408,-395,-377,-355,-331,-307,-285,-263,-237,-207,-174,-142,-116,
--97,-81,-62,-35,2,45,85,118,140,159,180,210,247,285,317,339,354,372,397,431,467,
-494,504,497,479,459,442,427,408,380,348,326,335,391,498,644,803,951,1065,1138,1172,1177,
-1161,1130,1090,1043,1000,970,967,996,1054,1129,1204,1262,1291,1291,1272,1246,1226,1220,1226,1237,1245,
-1245,1236,1221,1204,1186,1165,1139,1105,1069,1035,1013,1006,1015,1032,1053,1072,1092,1118,1157,1211,1276,
-1348,1416,1475,1522,1558,1583,1600,1608,1610,1607,1604,1606,1618,1639,1664,1688,1702,1700,1681,1644,1595,
-1539,1479,1420,1362,1305,1251,1201,1158,1128,1114,1121,1147,1189,1241,1294,1338,1368,1379,1373,1354,1330,
-1310,1296,1290,1288,1287,1283,1277,1273,1275,1288,1312,1342,1375,1403,1426,1442,1451,1453,1450,1443,1434,
-1425,1420,1418,1417,1416,1411,1405,1399,1399,1403,1412,1421,1427,1430,1433,1441,1459,1485,1517,1549,1577,
-1599,1617,1635,1656,1685,1726,1782,1852,1933,2016,2090,2148,2188,2214,2235,2254,2267,2262,2221,2135,2008,
-1857,1707,1578,1475,1391,1307,1210,1095,976,870,797,763,761,778,800,821,839,862,890,924,954,
-973,976,963,940,915,894,877,867,862,866,879,906,948,1003,1072,1149,1234,1323,1412,1499,1580,
-1653,1719,1781,1841,1902,1960,2012,2054,2080,2092,2093,2087,2081,2076,2075,2077,2082,2090,2098,2104,2109,
-2110,2111,2112,2116,2125,2137,2149,2158,2164,2168,2174,2184,2197,2213,2226,2237,2245,2253,2262,2272,2281,
-2287,2289,2289,2290,2295,2304,2316,2327,2335,2342,2350,2363,2381,2403,2423,2438,2449,2459,2471,2488,2506,
-2523,2535,2543,2549,2556,2566,2578,2589,2598,2606,2616,2630,2650,2670,2687,2697,2699,2698,2697,2699,2705,
-2712,2716,2718,2718,2721,2728,2737,2747,2753,2755,2756,2756,2760,2766,2772,2773,2766,2767,2746,2712,2671,
-2631,2601,2585,2584,2598,2620,2645,2668,2687,2700,2709,2714,2712,2703,2683,2657,2629,2607,2599,2605,2619,
-2633,2637,2629,2609,2584,2561,2545,2536,2533,2531,2528,2523,2517,2510,2505,2501,2498,2495,2493,2491,2490,
-2489,2491,2497,2509,2528,2552,2577,2599,2617,2630,2642,2656,2675,2700,2728,2757,2783,2805,2824,2841,2858,
-2876,2896,2919,2945,2975,3006,3036,3064,3089,3112,3134,3158,3182,3207,3227,3242,3252,3259,3266,3277,3294,
-3314,3335,3353,3365,3371,3372,3370,3371,3377,3393,3415,3440,3459,3462,3446,3411,3366,3324,3297,3294,3313,
-3344,3375,3398,3409,3411,3413,3420,3433,3450,3465,3477,3486,3497,3511,3532,3558,3584,3607,3627,3647,3670,
-3697,3729,3761,3789,3813,3832,3849,3869,3891,3917,3943,3968,3991,4013,4035,4060,4087,4117,4150,4185,4221,
-4259,4295,4328,4355,4377,4396,4416,4441,4470,4501,4529,4547,4555,4554,4550,4548,4550,4553,4554,4550,4538,
-4523,4507,4494,4484,4477,4470,4464,4460,4460,4465,4472,4475,4471,4459,4443,4426,4413,4403,4389,4368,4336,
-4296,4255,4220,4197,4186,4184,4189,4198,4212,4232,4254,4273,4282,4277,4256,4225,4190,4158,4131,4110,4090,
-4070,4048,4026,4006,3989,3976,3965,3956,3946,3934,3920,3902,3882,3862,3844,3830,3821,3814,3807,3798,3785,
-3770,3754,3738,3724,3710,3696,3683,3669,3656,3645,3633,3621,3605,3587,3567,3546,3528,3513,3501,3492,3484,
-3478,3471,3463,3454,3444,3434,3427,3424,3426,3431,3440,3449,3460,3470,3480,3487,3490,3488,3482,3473,3466,
-3462,3462,3466,3472,3478,3484,3488,3490,3488,3478,3463,3444,3428,3421,3425,3438,3453,3463,3465,3457,3442,
-3425,3409,3392,3374,3354,3333,3313,3295,3274,3245,3203,3148,3083,3016,2955,2901,2848,2791,2724,2651,2579,
-2519,2474,2439,2403,2356,2295,2228,2166,2122,2097,2084,2068,2036,1987,1932,1888,1867,1873,1897,1922,1931,
-1918,1885,1843,1804,1772,1748,1726,1702,1672,1638,1603,1571,1544,1518,1492,1463,1430,1395,1359,1323,1288,
-1254,1222,1191,1161,1131,1101,1069,1035,999,964,930,899,870,843,816,789,761,732,703,673,642,
-611,581,554,528,503,474,437,393,343,295,254,224,203,185,164,137,103,68,37,13,-5,
--24,-50,-85,-127,-172,-214,-250,-282,-312,-345,-382,-420,-457,-491,-521,-548,-574,-601,-629,-658,-687,
--716,-747,-781,-816,-851,-885,-916,-946,-975,-1004,-1034,-1065,-1095,-1124,-1151,-1179,-1207,-1238,-1270,-1304,-1338,
--1373,-1408,-1441,-1471,-1499,-1525,-1552,-1581,-1613,-1646,-1679,-1709,-1734,-1756,-1776,-1797,-1821,-1846,-1870,-1892,-1910,
--1925,-1939,-1955,-1973,-1994,-2015,-2035,-2053,-2069,-2084,-2098,-2112,-2126,-2140,-2155,-2170,-2186,-2202,-2219,-2235,-2251,
--2267,-2281,-2296,-2311,-2325,-2340,-2354,-2369,-2385,-2401,-2417,-2432,-2444,-2454,-2462,-2469,-2475,-2480,-2483,-2482,-2479,
--2473,-2468,-2465,-2465,-2468,-2472,-2473,-2471,-2467,-2463,-2460,-2459,-2457,-2455,-2450,-2443,-2437,-2432,-2430,-2431,-2431,
--2430,-2427,-2424,-2421,-2421,-2422,-2423,-2423,-2420,-2417,-2414,-2413,-2413,-2413,-2412,-2410,-2405,-2400,-2394,-2387,-2379,
--2367,-2353,-2339,-2327,-2320,-2317,-2316,-2313,-2306,-2292,-2272,-2248,-2224,-2201,-2181,-2163,-2149,-2135,-2124,-2113,-2105,
--2098,-2093,-2087,-2080,-2070,-2059,-2048,-2038,-2029,-2022,-2016,-2012,-2011,-2015,-2028,-2050,-2080,-2113,-2143,-2164,-2175,
--2178,-2173,-2164,-2153,-2140,-2127,-2118,-2114,-2118,-2131,-2147,-2164,-2177,-2186,-2192,-2197,-2204,-2210,-2215,-2216,-2214,
--2211,-2210,-2213,-2222,-2234,-2250,-2266,-2280,-2290,-2292,-2287,-2276,-2265,-2262,-2268,-2276,-2274,-2250,-2199,-2133,-2077,
--2062,-2105,-2205,-2336,-2462,-2548,-2582,-2571,-2542,-2522,-2526,-2551,-2584,-2609,-2617,-2614,-2612,-2620,-2640,-2664,-2680,
--2677,-2654,-2618,-2577,-2542,-2515,-2496,-2481,-2468,-2456,-2447,-2443,-2443,-2449,-2459,-2472,-2491,-2514,-2541,-2572,-2605,
--2637,-2671,-2707,-2748,-2797,-2853,-2914,-2977,-3036,-3088,-3130,-3161,-3184,-3203,-3220,-3237,-3252,-3264,-3270,-3270,-3267,
--3262,-3260,-3261,-3262,-3261,-3258,-3253,-3250,-3251,-3256,-3265,-3273,-3277,-3277,-3276,-3277,-3285,-3297,-3312,-3324,-3329,
--3329,-3327,-3329,-3337,-3352,-3370,-3385,-3394,-3397,-3394,-3391,-3389,-3388,-3389,-3388,-3386,-3382,-3379,-3376,-3374,-3371,
--3365,-3358,-3349,-3339,-3330,-3322,-3315,-3306,-3297,-3287,-3277,-3267,-3260,-3253,-3245,-3237,-3227,-3217,-3206,-3195,-3182,
--3170,-3157,-3146,-3134,-3124,-3113,-3100,-3087,-3073,-3063,-3056,-3053,-3053,-3053,-3051,-3045,-3035,-3025,-3014,-3004,-2994,
--2985,-2974,-2963,-2952,-2941,-2930,-2919,-2905,-2888,-2868,-2846,-2824,-2801,-2780,-2760,-2741,-2724,-2708,-2695,-2683,-2674,
--2666,-2658,-2648,-2637,-2623,-2609,-2595,-2582,-2573,-2565,-2556,-2546,-2532,-2515,-2498,-2482,-2468,-2456,-2446,-2435,-2424,
--2412,-2401,-2392,-2385,-2379,-2372,-2365,-2357,-2349,-2342,-2337,-2333,-2330,-2328,-2325,-2322,-2318,-2312,-2307,-2301,-2297,
--2293,-2290,-2289,-2287,-2284,-2279,-2272,-2263,-2252,-2239,-2223,-2206,-2189,-2173,-2159,-2149,-2140,-2131,-2119,-2103,-2086,
--2068,-2054,-2043,-2035,-2028,-2020,-2012,-2003,-1995,-1988,-1983,-1976,-1967,-1954,-1939,-1923,-1908,-1895,-1883,-1872,-1860,
--1848,-1837,-1829,-1823,-1821,-1820,-1819,-1817,-1814,-1813,-1812,-1812,-1812,-1811,-1809,-1806,-1804,-1801,-1798,-1797,-1795,
--1795,-1796,-1800,-1807,-1815,-1823,-1828,-1830,-1826,-1817,-1803,-1787,-1771,-1755,-1742,-1728,-1714,-1699,-1682,-1664,-1648,
--1634,-1623,-1613,-1601,-1585,-1565,-1542,-1518,-1496,-1478,-1466,-1457,-1450,-1443,-1433,-1421,-1406,-1389,-1371,-1354,-1339,
--1327,-1316,-1306,-1297,-1286,-1275,-1264,-1255,-1249,-1246,-1245,-1245,-1244,-1241,-1239,-1237,-1237,-1239,-1243,-1247,-1251,
--1255,-1258,-1262,-1265,-1267,-1269,-1270,-1270,-1269,-1270,-1271,-1273,-1276,-1278,-1282,-1287,-1292,-1299,-1305,-1309,-1311,
--1310,-1308,-1304,-1302,-1302,-1305,-1309,-1313,-1317,-1318,-1317,-1314,-1311,-1309,-1308,-1308,-1309,-1310,-1311,-1310,-1309,
--1308,-1308,-1308,-1307,-1304,-1298,-1289,-1278,-1266,-1255,-1245,-1237,-1229,-1223,-1217,-1212,-1208,-1204,-1200,-1195,-1187,
--1175,-1162,-1148,-1136,-1127,-1121,-1112,-1097,-1073,-1038,-1000,-965,-942,-935,-942,-957,-969,-971,-962,-946,-931,
--926,-935,-956,-980,-1002,-1015,-1019,-1018,-1015,-1015,-1014,-1010,-997,-973,-938,-897,-854,-815,-783,-755,-732,
--709,-685,-660,-636,-613,-592,-574,-559,-544,-531,-519,-509,-501,-494,-488,-481,-472,-463,-453,-444,-434,
--421,-404,-381,-356,-333,-312,-295,-277,-254,-225,-190,-157,-131,-114,-103,-90,-67,-32,12,56,92,
-117,134,153,181,218,260,298,326,345,360,380,409,442,472,490,492,481,465,448,432,411,
-384,349,316,301,319,378,476,600,732,854,955,1029,1077,1100,1101,1087,1063,1040,1030,1043,1081,
-1142,1213,1280,1327,1349,1346,1327,1305,1289,1286,1293,1304,1312,1313,1307,1298,1287,1275,1257,1232,1196,
-1155,1115,1086,1073,1076,1089,1107,1126,1146,1172,1209,1259,1321,1389,1457,1519,1575,1623,1663,1693,1711,
-1717,1713,1707,1705,1716,1741,1778,1818,1850,1864,1857,1828,1781,1725,1665,1607,1550,1493,1435,1376,1319,
-1271,1237,1224,1232,1257,1294,1332,1365,1386,1396,1395,1389,1383,1379,1379,1381,1383,1383,1382,1384,1391,
-1405,1427,1452,1476,1495,1507,1513,1514,1512,1508,1501,1492,1482,1475,1472,1474,1479,1484,1485,1481,1476,
-1472,1472,1475,1480,1483,1484,1486,1492,1506,1529,1556,1584,1607,1622,1628,1627,1625,1629,1647,1684,1743,
-1819,1906,1992,2067,2129,2179,2224,2266,2301,2320,2310,2264,2187,2090,1989,1892,1798,1691,1559,1395,1209,
-1027,876,780,741,748,777,807,823,826,823,819,819,819,813,797,771,738,703,669,637,605,
-574,548,534,542,578,644,740,859,992,1131,1266,1391,1501,1596,1675,1745,1808,1868,1926,1982,2030,
-2070,2097,2112,2114,2106,2092,2076,2063,2056,2057,2064,2073,2083,2091,2097,2104,2112,2123,2133,2142,2147,
-2150,2155,2164,2178,2194,2209,2220,2227,2232,2238,2246,2256,2263,2266,2266,2264,2265,2272,2284,2297,2308,
-2315,2321,2330,2345,2366,2388,2408,2422,2433,2443,2458,2477,2499,2517,2529,2536,2539,2545,2554,2565,2576,
-2585,2592,2600,2612,2629,2649,2666,2678,2682,2683,2682,2684,2687,2690,2693,2697,2704,2715,2731,2746,2756,
-2758,2752,2743,2739,2742,2753,2766,2773,2767,2709,2686,2651,2614,2582,2560,2550,2551,2557,2565,2572,2576,
-2580,2586,2597,2611,2625,2632,2630,2618,2601,2585,2578,2581,2590,2600,2603,2598,2584,2568,2553,2541,2530,
-2516,2497,2474,2451,2433,2423,2421,2423,2426,2427,2424,2420,2419,2421,2430,2444,2464,2488,2512,2535,2553,
-2567,2578,2590,2607,2630,2660,2692,2723,2748,2766,2779,2791,2807,2829,2856,2887,2919,2950,2978,3002,3025,
-3046,3068,3090,3114,3138,3159,3175,3187,3196,3203,3214,3229,3250,3272,3291,3305,3312,3313,3311,3311,3317,
-3329,3345,3361,3372,3373,3362,3340,3311,3284,3265,3259,3267,3287,3310,3332,3347,3356,3363,3372,3385,3403,
-3421,3437,3450,3461,3473,3490,3514,3541,3569,3594,3617,3637,3659,3682,3708,3735,3761,3782,3801,3818,3836,
-3855,3877,3900,3924,3947,3971,3995,4021,4048,4079,4112,4149,4187,4225,4260,4289,4313,4332,4351,4372,4397,
-4424,4448,4465,4472,4469,4461,4454,4452,4455,4461,4465,4464,4457,4448,4438,4429,4421,4414,4405,4398,4392,
-4392,4395,4400,4403,4401,4396,4388,4383,4381,4380,4374,4359,4333,4298,4260,4222,4188,4157,4129,4102,4081,
-4067,4063,4068,4078,4087,4092,4092,4088,4083,4077,4071,4060,4044,4022,3997,3974,3954,3940,3930,3923,3916,
-3909,3901,3890,3876,3860,3843,3828,3816,3808,3801,3794,3783,3766,3746,3725,3707,3693,3681,3671,3660,3647,
-3633,3620,3607,3595,3583,3570,3554,3538,3521,3505,3493,3485,3481,3481,3483,3485,3484,3480,3473,3464,3456,
-3450,3446,3444,3444,3445,3448,3453,3457,3461,3463,3462,3460,3459,3459,3462,3467,3472,3475,3477,3476,3471,
-3462,3447,3428,3409,3395,3390,3396,3408,3421,3427,3422,3406,3385,3363,3344,3328,3314,3299,3284,3269,3255,
-3240,3218,3185,3138,3081,3021,2964,2914,2868,2819,2759,2688,2611,2537,2473,2420,2371,2319,2261,2201,2148,
-2112,2096,2094,2091,2073,2036,1982,1928,1886,1867,1869,1881,1890,1885,1864,1831,1795,1761,1733,1709,1685,
-1657,1626,1593,1561,1530,1502,1475,1448,1419,1389,1356,1324,1290,1257,1225,1193,1162,1131,1098,1065,1030,
-995,960,927,896,868,840,813,786,758,729,698,666,634,601,571,544,519,492,461,422,376,
-327,282,245,219,200,181,159,129,93,58,29,6,-12,-32,-59,-95,-137,-181,-221,-255,-284,
--313,-344,-381,-420,-460,-496,-527,-555,-581,-606,-631,-657,-684,-713,-744,-778,-814,-850,-886,-920,-951,
--980,-1008,-1036,-1064,-1092,-1120,-1149,-1178,-1208,-1239,-1271,-1305,-1339,-1374,-1408,-1441,-1471,-1499,-1526,-1553,-1582,
--1613,-1645,-1675,-1702,-1726,-1748,-1770,-1794,-1820,-1847,-1872,-1894,-1912,-1927,-1943,-1960,-1979,-2000,-2020,-2039,-2058,
--2075,-2091,-2107,-2121,-2134,-2148,-2163,-2179,-2198,-2217,-2235,-2251,-2265,-2277,-2291,-2306,-2323,-2340,-2356,-2370,-2384,
--2398,-2412,-2428,-2443,-2457,-2468,-2477,-2485,-2493,-2499,-2502,-2501,-2496,-2489,-2482,-2479,-2481,-2485,-2490,-2493,-2492,
--2489,-2486,-2484,-2483,-2483,-2482,-2479,-2474,-2470,-2467,-2466,-2466,-2464,-2461,-2456,-2451,-2448,-2448,-2449,-2451,-2451,
--2450,-2448,-2447,-2447,-2448,-2448,-2446,-2442,-2438,-2435,-2432,-2428,-2422,-2411,-2396,-2379,-2364,-2353,-2349,-2348,-2347,
--2342,-2332,-2315,-2294,-2270,-2246,-2224,-2204,-2186,-2170,-2156,-2145,-2137,-2131,-2126,-2122,-2118,-2111,-2103,-2093,-2084,
--2075,-2067,-2061,-2055,-2051,-2050,-2056,-2069,-2090,-2118,-2148,-2175,-2195,-2206,-2208,-2202,-2191,-2176,-2163,-2153,-2149,
--2152,-2160,-2172,-2184,-2196,-2207,-2218,-2230,-2242,-2251,-2255,-2253,-2246,-2238,-2231,-2231,-2239,-2254,-2273,-2293,-2310,
--2320,-2321,-2317,-2311,-2308,-2311,-2317,-2317,-2302,-2265,-2210,-2156,-2126,-2142,-2212,-2323,-2449,-2557,-2623,-2643,-2631,
--2611,-2603,-2615,-2643,-2673,-2693,-2699,-2697,-2696,-2703,-2720,-2740,-2756,-2764,-2762,-2752,-2736,-2715,-2688,-2655,-2619,
--2583,-2555,-2538,-2531,-2534,-2541,-2554,-2572,-2597,-2631,-2673,-2717,-2762,-2805,-2846,-2889,-2937,-2991,-3048,-3106,-3160,
--3206,-3242,-3269,-3288,-3302,-3314,-3325,-3338,-3350,-3361,-3367,-3368,-3364,-3358,-3351,-3346,-3343,-3340,-3335,-3330,-3326,
--3326,-3331,-3339,-3349,-3355,-3357,-3357,-3357,-3363,-3373,-3387,-3400,-3407,-3409,-3408,-3408,-3414,-3426,-3442,-3456,-3465,
--3469,-3468,-3466,-3466,-3466,-3467,-3466,-3463,-3459,-3456,-3455,-3454,-3451,-3445,-3435,-3422,-3410,-3400,-3391,-3384,-3375,
--3364,-3352,-3340,-3330,-3322,-3315,-3307,-3298,-3288,-3277,-3265,-3254,-3244,-3232,-3220,-3208,-3196,-3184,-3173,-3162,-3151,
--3138,-3126,-3116,-3108,-3103,-3099,-3096,-3092,-3087,-3079,-3070,-3060,-3049,-3037,-3024,-3010,-2996,-2984,-2972,-2962,-2951,
--2939,-2925,-2908,-2890,-2870,-2849,-2828,-2806,-2785,-2765,-2747,-2731,-2718,-2709,-2700,-2692,-2683,-2671,-2656,-2641,-2626,
--2613,-2601,-2591,-2579,-2566,-2552,-2538,-2524,-2513,-2502,-2491,-2477,-2461,-2444,-2428,-2416,-2407,-2403,-2400,-2398,-2394,
--2387,-2380,-2371,-2362,-2353,-2345,-2337,-2330,-2323,-2317,-2312,-2308,-2304,-2301,-2299,-2298,-2297,-2296,-2296,-2297,-2297,
--2295,-2290,-2280,-2267,-2252,-2236,-2224,-2214,-2205,-2195,-2182,-2164,-2143,-2122,-2103,-2088,-2078,-2069,-2060,-2050,-2039,
--2027,-2017,-2007,-1998,-1987,-1975,-1963,-1951,-1939,-1929,-1918,-1905,-1892,-1878,-1866,-1858,-1853,-1851,-1849,-1846,-1842,
--1836,-1832,-1829,-1829,-1832,-1834,-1837,-1839,-1839,-1838,-1837,-1834,-1832,-1829,-1827,-1827,-1828,-1830,-1833,-1834,-1834,
--1830,-1823,-1813,-1803,-1792,-1781,-1771,-1760,-1747,-1731,-1711,-1688,-1666,-1645,-1627,-1612,-1598,-1585,-1570,-1554,-1537,
--1523,-1511,-1503,-1497,-1491,-1482,-1470,-1454,-1435,-1413,-1393,-1374,-1358,-1345,-1334,-1324,-1314,-1303,-1291,-1281,-1273,
--1267,-1264,-1263,-1262,-1261,-1259,-1257,-1256,-1257,-1260,-1265,-1271,-1277,-1283,-1288,-1293,-1298,-1301,-1304,-1305,-1306,
--1305,-1304,-1303,-1302,-1302,-1303,-1306,-1311,-1318,-1326,-1334,-1340,-1344,-1345,-1344,-1342,-1340,-1338,-1339,-1341,-1344,
--1346,-1348,-1348,-1347,-1346,-1344,-1343,-1343,-1343,-1342,-1341,-1338,-1336,-1334,-1333,-1332,-1332,-1331,-1328,-1322,-1314,
--1305,-1294,-1284,-1273,-1262,-1251,-1239,-1228,-1218,-1208,-1199,-1190,-1181,-1171,-1160,-1151,-1145,-1141,-1137,-1129,-1111,
--1083,-1047,-1009,-978,-962,-964,-978,-996,-1008,-1006,-992,-970,-953,-948,-959,-982,-1009,-1031,-1044,-1047,-1045,
--1041,-1040,-1039,-1034,-1022,-998,-966,-927,-888,-852,-823,-797,-773,-748,-721,-692,-665,-640,-619,-601,-583,
--566,-549,-534,-521,-513,-509,-506,-502,-496,-487,-476,-463,-448,-429,-407,-381,-354,-331,-313,-299,-285,
--266,-240,-208,-177,-151,-135,-125,-114,-93,-59,-14,31,69,95,112,128,152,187,230,273,307,
-332,349,366,389,417,446,469,481,482,475,464,450,431,405,372,335,305,291,303,345,412,
-498,592,686,774,850,914,964,1002,1031,1058,1088,1125,1171,1223,1273,1316,1345,1359,1362,1360,1360,
-1366,1378,1395,1409,1417,1415,1406,1391,1373,1353,1330,1300,1264,1225,1187,1157,1137,1128,1126,1130,1138,
-1151,1173,1207,1251,1304,1359,1415,1469,1520,1570,1616,1654,1681,1694,1695,1691,1689,1698,1721,1756,1795,
-1830,1851,1852,1834,1800,1756,1709,1663,1620,1578,1535,1491,1447,1407,1376,1359,1358,1370,1392,1416,1437,
-1451,1457,1459,1459,1460,1462,1467,1471,1474,1477,1483,1494,1511,1534,1559,1579,1590,1591,1585,1575,1567,
-1564,1564,1566,1565,1562,1559,1557,1560,1565,1572,1576,1575,1570,1563,1556,1551,1550,1551,1555,1562,1573,
-1588,1606,1625,1642,1653,1657,1653,1643,1630,1619,1615,1625,1652,1698,1757,1824,1891,1955,2016,2076,2135,
-2191,2237,2267,2275,2263,2235,2197,2147,2077,1975,1833,1657,1465,1288,1155,1084,1073,1101,1141,1166,1163,
-1132,1083,1028,976,930,888,846,804,760,715,668,614,552,482,408,341,295,281,309,382,498,
-648,822,1005,1185,1349,1491,1607,1700,1773,1834,1889,1943,1995,2044,2086,2114,2126,2120,2099,2071,2044,
-2026,2020,2024,2036,2048,2059,2067,2074,2081,2090,2097,2103,2107,2112,2119,2132,2149,2167,2182,2191,2197,
-2202,2209,2220,2233,2242,2247,2246,2245,2247,2255,2269,2284,2296,2303,2310,2319,2333,2352,2373,2391,2405,
-2416,2428,2444,2464,2484,2500,2508,2511,2512,2517,2526,2539,2551,2561,2568,2575,2584,2598,2614,2629,2640,
-2646,2650,2653,2657,2661,2665,2669,2676,2688,2705,2726,2743,2751,2746,2732,2715,2702,2700,2706,2716,2719,
-2709,2614,2589,2560,2535,2518,2512,2514,2519,2522,2521,2514,2504,2497,2495,2501,2515,2533,2549,2559,2560,
-2556,2550,2547,2547,2548,2547,2541,2529,2513,2497,2484,2471,2457,2436,2410,2382,2357,2343,2340,2347,2358,
-2367,2370,2368,2364,2364,2370,2382,2398,2417,2435,2454,2472,2488,2505,2521,2539,2561,2586,2615,2644,2671,
-2693,2710,2726,2744,2767,2795,2828,2862,2893,2920,2943,2964,2985,3008,3031,3055,3077,3095,3109,3120,3128,
-3137,3148,3162,3180,3200,3219,3234,3243,3248,3250,3254,3261,3273,3285,3294,3296,3290,3277,3261,3246,3237,
-3234,3236,3243,3252,3262,3273,3284,3297,3311,3327,3344,3361,3376,3390,3402,3414,3428,3446,3468,3495,3525,
-3555,3583,3608,3630,3650,3670,3690,3710,3731,3750,3768,3785,3802,3818,3836,3856,3878,3901,3925,3950,3975,
-4002,4032,4064,4100,4137,4174,4207,4235,4259,4279,4299,4321,4344,4366,4382,4391,4390,4383,4374,4367,4365,
-4368,4371,4374,4374,4371,4366,4362,4357,4351,4343,4333,4323,4316,4316,4320,4326,4331,4332,4331,4328,4327,
-4327,4327,4323,4311,4291,4264,4233,4199,4164,4126,4084,4041,4002,3971,3952,3946,3949,3958,3970,3982,3995,
-4007,4016,4020,4016,4002,3981,3956,3934,3916,3904,3897,3892,3887,3882,3876,3868,3856,3841,3825,3809,3796,
-3786,3779,3771,3759,3742,3722,3700,3681,3667,3656,3647,3637,3625,3611,3597,3584,3573,3564,3556,3546,3534,
-3520,3505,3492,3482,3479,3483,3492,3504,3514,3519,3518,3511,3499,3485,3469,3452,3437,3424,3416,3412,3412,
-3415,3419,3423,3427,3433,3440,3450,3461,3470,3475,3475,3468,3456,3439,3420,3401,3383,3370,3364,3365,3370,
-3374,3372,3360,3340,3315,3292,3271,3256,3244,3233,3222,3213,3204,3193,3177,3149,3109,3057,3002,2950,2905,
-2865,2825,2775,2714,2641,2564,2489,2421,2358,2298,2238,2181,2136,2108,2102,2111,2122,2120,2095,2046,1985,
-1925,1880,1857,1851,1853,1852,1841,1818,1787,1754,1722,1693,1667,1641,1613,1583,1551,1519,1487,1457,1428,
-1400,1372,1345,1317,1288,1258,1227,1195,1162,1129,1095,1061,1027,993,960,928,898,868,840,811,783,
-755,726,695,663,630,599,569,543,518,491,458,418,372,323,279,242,214,192,169,144,113,
-79,47,20,0,-19,-41,-69,-104,-145,-185,-222,-254,-282,-311,-344,-381,-421,-461,-498,-530,-558,
--583,-607,-631,-657,-683,-713,-744,-779,-815,-851,-886,-919,-950,-978,-1006,-1034,-1061,-1090,-1120,-1150,-1182,
--1214,-1247,-1280,-1313,-1345,-1377,-1409,-1440,-1469,-1498,-1527,-1557,-1587,-1618,-1649,-1677,-1702,-1724,-1747,-1770,-1796,
--1823,-1850,-1875,-1895,-1913,-1930,-1948,-1967,-1988,-2008,-2027,-2045,-2062,-2080,-2097,-2113,-2128,-2143,-2157,-2172,-2190,
--2209,-2229,-2246,-2261,-2273,-2286,-2301,-2318,-2337,-2356,-2373,-2387,-2399,-2410,-2423,-2437,-2451,-2464,-2476,-2485,-2494,
--2503,-2510,-2516,-2518,-2516,-2511,-2506,-2504,-2505,-2510,-2514,-2517,-2517,-2515,-2513,-2511,-2511,-2510,-2508,-2504,-2501,
--2499,-2498,-2498,-2498,-2495,-2490,-2483,-2476,-2473,-2472,-2473,-2474,-2474,-2473,-2473,-2474,-2477,-2479,-2480,-2477,-2473,
--2468,-2465,-2465,-2464,-2461,-2452,-2437,-2418,-2401,-2388,-2382,-2380,-2379,-2376,-2367,-2352,-2332,-2309,-2285,-2261,-2239,
--2220,-2202,-2187,-2175,-2165,-2158,-2153,-2151,-2150,-2148,-2145,-2138,-2129,-2119,-2110,-2101,-2095,-2091,-2088,-2089,-2094,
--2107,-2128,-2156,-2188,-2216,-2237,-2246,-2243,-2231,-2214,-2199,-2189,-2185,-2188,-2195,-2204,-2215,-2226,-2238,-2250,-2263,
--2273,-2279,-2280,-2275,-2268,-2260,-2255,-2256,-2264,-2279,-2298,-2320,-2338,-2351,-2357,-2357,-2354,-2354,-2357,-2361,-2357,
--2340,-2308,-2270,-2242,-2241,-2282,-2361,-2464,-2564,-2639,-2678,-2684,-2673,-2666,-2674,-2699,-2731,-2758,-2773,-2777,-2776,
--2779,-2791,-2810,-2834,-2857,-2877,-2892,-2899,-2896,-2879,-2846,-2799,-2746,-2698,-2663,-2646,-2645,-2654,-2668,-2688,-2714,
--2749,-2794,-2844,-2895,-2943,-2987,-3029,-3073,-3121,-3172,-3223,-3268,-3304,-3332,-3354,-3371,-3387,-3401,-3413,-3422,-3431,
--3438,-3446,-3452,-3454,-3453,-3448,-3440,-3432,-3425,-3420,-3416,-3413,-3412,-3413,-3417,-3423,-3430,-3435,-3437,-3436,-3437,
--3441,-3451,-3464,-3477,-3487,-3491,-3491,-3491,-3494,-3503,-3515,-3527,-3537,-3543,-3545,-3545,-3544,-3543,-3540,-3536,-3531,
--3527,-3525,-3525,-3525,-3523,-3516,-3506,-3493,-3481,-3471,-3462,-3454,-3445,-3433,-3419,-3405,-3394,-3385,-3376,-3367,-3356,
--3344,-3332,-3321,-3312,-3304,-3296,-3285,-3273,-3260,-3247,-3237,-3228,-3219,-3208,-3195,-3180,-3166,-3153,-3143,-3136,-3131,
--3126,-3121,-3115,-3107,-3097,-3086,-3073,-3059,-3045,-3031,-3018,-3007,-2996,-2986,-2975,-2962,-2948,-2932,-2913,-2893,-2872,
--2850,-2828,-2807,-2788,-2772,-2758,-2746,-2736,-2726,-2714,-2700,-2685,-2670,-2655,-2642,-2629,-2617,-2604,-2592,-2580,-2570,
--2560,-2551,-2539,-2525,-2508,-2489,-2470,-2454,-2442,-2435,-2430,-2425,-2421,-2414,-2407,-2398,-2389,-2380,-2371,-2362,-2354,
--2346,-2338,-2331,-2324,-2318,-2312,-2307,-2303,-2300,-2299,-2300,-2302,-2306,-2309,-2310,-2307,-2301,-2291,-2279,-2268,-2257,
--2247,-2236,-2222,-2206,-2188,-2170,-2154,-2140,-2129,-2119,-2109,-2097,-2083,-2069,-2054,-2039,-2026,-2013,-2001,-1992,-1984,
--1976,-1968,-1957,-1943,-1927,-1910,-1897,-1887,-1882,-1881,-1880,-1877,-1873,-1868,-1863,-1860,-1859,-1860,-1863,-1866,-1869,
--1872,-1873,-1873,-1873,-1871,-1868,-1865,-1861,-1857,-1853,-1849,-1844,-1838,-1833,-1828,-1824,-1821,-1819,-1818,-1816,-1812,
--1803,-1789,-1768,-1742,-1713,-1684,-1659,-1639,-1625,-1615,-1606,-1597,-1587,-1576,-1565,-1555,-1545,-1535,-1523,-1507,-1488,
--1467,-1444,-1422,-1402,-1383,-1367,-1352,-1338,-1325,-1313,-1303,-1296,-1292,-1291,-1291,-1293,-1294,-1294,-1292,-1290,-1288,
--1288,-1290,-1294,-1299,-1304,-1309,-1313,-1317,-1320,-1322,-1325,-1328,-1330,-1331,-1331,-1330,-1329,-1328,-1328,-1330,-1334,
--1340,-1347,-1355,-1362,-1368,-1373,-1377,-1379,-1381,-1382,-1382,-1382,-1382,-1380,-1379,-1377,-1376,-1375,-1374,-1374,-1374,
--1373,-1371,-1369,-1366,-1363,-1360,-1358,-1357,-1357,-1356,-1354,-1350,-1344,-1336,-1327,-1316,-1305,-1291,-1277,-1262,-1246,
--1231,-1216,-1203,-1191,-1180,-1170,-1161,-1155,-1151,-1149,-1146,-1137,-1120,-1096,-1066,-1038,-1018,-1012,-1019,-1034,-1047,
--1050,-1038,-1016,-990,-972,-968,-979,-1003,-1030,-1053,-1067,-1071,-1068,-1064,-1060,-1055,-1046,-1032,-1010,-981,-948,
--915,-886,-860,-836,-813,-787,-759,-731,-703,-678,-657,-637,-619,-600,-581,-563,-548,-539,-534,-531,-528,
--522,-511,-497,-480,-460,-437,-412,-385,-358,-334,-315,-301,-289,-275,-255,-230,-204,-182,-165,-153,-138,
--115,-81,-38,7,46,74,92,108,129,160,199,241,279,308,329,348,368,393,420,446,466,
-478,483,482,476,464,447,421,390,358,329,310,306,318,347,392,449,517,592,671,752,834,
-915,994,1070,1141,1203,1255,1294,1320,1337,1348,1358,1373,1395,1424,1457,1490,1516,1530,1529,1513,1483,
-1445,1401,1356,1313,1276,1245,1220,1202,1188,1176,1166,1159,1158,1167,1188,1221,1262,1306,1349,1390,1431,
-1473,1518,1564,1607,1642,1665,1676,1679,1680,1686,1698,1718,1741,1763,1778,1782,1776,1760,1736,1709,1682,
-1656,1633,1612,1591,1570,1547,1527,1512,1504,1505,1513,1523,1533,1541,1544,1544,1545,1546,1549,1552,1555,
-1559,1563,1572,1587,1607,1630,1651,1664,1666,1657,1643,1631,1626,1629,1639,1650,1657,1657,1652,1644,1637,
-1634,1635,1637,1637,1635,1629,1622,1615,1610,1609,1612,1618,1628,1640,1651,1661,1668,1672,1675,1676,1675,
-1671,1663,1651,1639,1634,1640,1660,1694,1738,1788,1843,1900,1960,2022,2083,2140,2188,2227,2253,2264,2253,
-2212,2135,2022,1886,1747,1631,1559,1539,1564,1610,1652,1668,1646,1590,1512,1425,1341,1267,1204,1150,1103,
-1059,1016,970,915,847,761,659,547,435,336,266,239,266,351,492,678,891,1110,1315,1490,1627,
-1726,1797,1849,1894,1942,1992,2041,2081,2103,2103,2083,2051,2019,1997,1990,1996,2010,2024,2034,2039,2042,
-2044,2047,2052,2056,2060,2066,2076,2090,2108,2127,2142,2153,2161,2169,2181,2197,2214,2228,2235,2238,2238,
-2241,2250,2263,2278,2290,2298,2304,2311,2322,2336,2351,2366,2377,2388,2400,2415,2432,2449,2461,2468,2472,
-2475,2483,2495,2509,2523,2534,2541,2547,2553,2562,2571,2580,2587,2594,2601,2610,2620,2628,2634,2638,2641,
-2648,2660,2675,2687,2691,2684,2669,2652,2639,2634,2634,2635,2630,2614,2530,2507,2486,2472,2468,2472,2480,
-2487,2490,2486,2477,2466,2457,2453,2456,2464,2476,2487,2496,2499,2498,2494,2488,2480,2469,2454,2434,2411,
-2388,2368,2353,2341,2329,2314,2296,2280,2270,2270,2280,2296,2311,2319,2321,2318,2315,2316,2323,2334,2348,
-2361,2374,2387,2403,2423,2445,2470,2494,2518,2542,2565,2589,2612,2635,2658,2683,2710,2740,2772,2803,2830,
-2854,2874,2895,2918,2945,2973,3001,3023,3040,3050,3057,3063,3071,3082,3097,3115,3134,3152,3167,3178,3185,
-3191,3197,3206,3219,3230,3237,3236,3225,3207,3189,3179,3180,3193,3211,3227,3236,3237,3233,3231,3236,3251,
-3273,3298,3321,3338,3349,3358,3368,3382,3401,3424,3451,3478,3506,3534,3562,3588,3612,3633,3652,3668,3684,
-3700,3718,3736,3753,3770,3786,3802,3819,3839,3860,3883,3906,3930,3954,3980,4009,4040,4072,4104,4134,4161,
-4185,4207,4229,4250,4271,4288,4299,4304,4304,4301,4298,4296,4297,4297,4297,4294,4290,4286,4283,4281,4279,
-4275,4267,4258,4250,4246,4248,4254,4262,4269,4272,4272,4270,4268,4266,4263,4256,4244,4226,4206,4183,4158,
-4130,4098,4061,4021,3984,3953,3931,3920,3918,3921,3927,3935,3945,3955,3964,3969,3967,3956,3940,3921,3904,
-3890,3879,3872,3865,3860,3853,3847,3838,3828,3815,3800,3785,3771,3761,3752,3743,3733,3718,3699,3679,3659,
-3643,3629,3618,3608,3599,3588,3578,3569,3561,3554,3547,3540,3531,3520,3506,3493,3483,3479,3485,3499,3518,
-3536,3550,3555,3550,3535,3514,3487,3458,3430,3405,3385,3373,3369,3369,3373,3377,3382,3389,3399,3413,3430,
-3445,3453,3453,3444,3429,3410,3392,3375,3360,3348,3339,3332,3327,3320,3311,3297,3277,3253,3228,3205,3186,
-3171,3160,3152,3147,3143,3137,3123,3099,3062,3015,2961,2909,2862,2822,2784,2742,2692,2632,2566,2497,2429,
-2362,2295,2229,2167,2115,2081,2067,2072,2084,2090,2078,2044,1992,1933,1882,1846,1828,1823,1823,1818,1803,
-1778,1746,1712,1679,1651,1626,1601,1575,1545,1513,1480,1446,1414,1385,1358,1333,1307,1281,1254,1224,1194,
-1162,1129,1096,1063,1031,999,967,936,905,874,843,813,783,754,725,695,663,630,599,571,545,
-521,495,464,427,384,338,294,255,222,194,166,137,106,74,45,19,-3,-24,-49,-78,-112,
--148,-185,-219,-250,-281,-313,-349,-387,-426,-463,-497,-527,-555,-581,-606,-632,-660,-689,-720,-753,-788,
--824,-858,-890,-919,-946,-972,-998,-1025,-1054,-1084,-1116,-1149,-1183,-1217,-1251,-1284,-1316,-1347,-1377,-1407,-1435,
--1464,-1494,-1524,-1556,-1590,-1622,-1653,-1681,-1706,-1729,-1752,-1776,-1802,-1828,-1853,-1874,-1892,-1909,-1926,-1946,-1969,
--1992,-2013,-2033,-2050,-2066,-2082,-2099,-2115,-2132,-2147,-2163,-2180,-2198,-2217,-2235,-2252,-2266,-2279,-2293,-2310,-2329,
--2350,-2369,-2385,-2397,-2408,-2419,-2431,-2445,-2459,-2471,-2482,-2490,-2499,-2508,-2517,-2525,-2531,-2534,-2534,-2533,-2534,
--2536,-2539,-2541,-2542,-2542,-2541,-2541,-2541,-2540,-2538,-2535,-2530,-2525,-2523,-2523,-2523,-2522,-2517,-2510,-2503,-2499,
--2497,-2498,-2500,-2500,-2498,-2495,-2495,-2498,-2503,-2507,-2509,-2507,-2501,-2496,-2493,-2493,-2494,-2493,-2485,-2471,-2453,
--2437,-2425,-2419,-2417,-2416,-2413,-2404,-2389,-2369,-2345,-2320,-2295,-2274,-2255,-2239,-2226,-2215,-2205,-2196,-2189,-2186,
--2185,-2186,-2185,-2179,-2169,-2157,-2144,-2136,-2132,-2131,-2132,-2131,-2131,-2135,-2146,-2168,-2199,-2231,-2259,-2275,-2276,
--2266,-2251,-2236,-2226,-2223,-2225,-2230,-2237,-2246,-2257,-2271,-2285,-2297,-2304,-2306,-2304,-2300,-2296,-2295,-2297,-2301,
--2308,-2319,-2334,-2353,-2373,-2389,-2398,-2398,-2394,-2390,-2388,-2390,-2390,-2386,-2376,-2365,-2366,-2390,-2441,-2515,-2595,
--2663,-2704,-2717,-2711,-2703,-2707,-2728,-2762,-2798,-2825,-2839,-2845,-2851,-2863,-2885,-2914,-2946,-2977,-3004,-3025,-3037,
--3033,-3010,-2969,-2914,-2858,-2812,-2786,-2781,-2793,-2814,-2838,-2865,-2897,-2937,-2983,-3032,-3078,-3118,-3153,-3187,-3225,
--3270,-3316,-3358,-3392,-3414,-3429,-3443,-3459,-3477,-3496,-3511,-3519,-3521,-3522,-3524,-3529,-3534,-3538,-3536,-3529,-3520,
--3511,-3506,-3503,-3503,-3504,-3504,-3506,-3508,-3511,-3515,-3517,-3519,-3521,-3526,-3533,-3544,-3555,-3563,-3568,-3568,-3568,
--3570,-3575,-3585,-3596,-3606,-3615,-3619,-3621,-3619,-3615,-3609,-3601,-3594,-3589,-3587,-3587,-3587,-3585,-3580,-3571,-3560,
--3550,-3542,-3535,-3526,-3515,-3501,-3485,-3469,-3456,-3445,-3436,-3425,-3413,-3400,-3388,-3379,-3373,-3368,-3362,-3353,-3341,
--3327,-3313,-3302,-3293,-3284,-3274,-3260,-3243,-3223,-3204,-3188,-3176,-3168,-3163,-3158,-3153,-3148,-3142,-3135,-3126,-3116,
--3104,-3090,-3075,-3060,-3044,-3029,-3016,-3002,-2988,-2974,-2958,-2942,-2924,-2906,-2888,-2869,-2850,-2833,-2816,-2800,-2786,
--2771,-2756,-2741,-2725,-2709,-2694,-2680,-2667,-2655,-2643,-2632,-2622,-2612,-2603,-2594,-2584,-2572,-2558,-2543,-2527,-2511,
--2496,-2482,-2470,-2458,-2448,-2438,-2429,-2422,-2414,-2408,-2401,-2393,-2386,-2377,-2368,-2359,-2350,-2341,-2334,-2328,-2324,
--2320,-2317,-2314,-2312,-2310,-2310,-2309,-2308,-2306,-2300,-2292,-2282,-2271,-2261,-2252,-2243,-2234,-2224,-2214,-2203,-2191,
--2180,-2168,-2155,-2142,-2128,-2114,-2099,-2083,-2068,-2055,-2043,-2033,-2025,-2016,-2006,-1993,-1977,-1959,-1942,-1928,-1918,
--1913,-1912,-1911,-1910,-1907,-1905,-1902,-1900,-1899,-1900,-1901,-1902,-1904,-1905,-1905,-1905,-1904,-1902,-1899,-1896,-1893,
--1890,-1885,-1878,-1870,-1862,-1855,-1851,-1848,-1848,-1849,-1850,-1851,-1849,-1843,-1832,-1815,-1793,-1768,-1744,-1723,-1708,
--1699,-1694,-1689,-1682,-1671,-1655,-1637,-1618,-1599,-1582,-1565,-1548,-1530,-1511,-1491,-1471,-1451,-1430,-1409,-1387,-1365,
--1345,-1329,-1318,-1313,-1313,-1316,-1322,-1327,-1330,-1332,-1331,-1329,-1327,-1326,-1327,-1330,-1333,-1337,-1339,-1340,-1339,
--1338,-1338,-1338,-1340,-1344,-1348,-1351,-1354,-1356,-1357,-1359,-1361,-1363,-1366,-1370,-1374,-1379,-1384,-1390,-1396,-1403,
--1409,-1414,-1417,-1417,-1416,-1413,-1410,-1406,-1404,-1402,-1401,-1400,-1400,-1399,-1397,-1394,-1391,-1387,-1385,-1382,-1381,
--1381,-1380,-1378,-1374,-1368,-1360,-1351,-1340,-1327,-1313,-1298,-1282,-1265,-1249,-1233,-1217,-1203,-1190,-1179,-1171,-1166,
--1163,-1162,-1158,-1150,-1136,-1116,-1096,-1078,-1069,-1070,-1078,-1088,-1091,-1083,-1063,-1036,-1009,-991,-987,-998,-1020,
--1045,-1067,-1082,-1090,-1091,-1087,-1081,-1071,-1056,-1037,-1014,-987,-959,-932,-908,-886,-865,-845,-823,-800,-776,
--751,-727,-705,-684,-665,-646,-627,-609,-593,-581,-572,-565,-558,-549,-536,-519,-499,-477,-453,-427,-400,
--372,-347,-325,-307,-294,-281,-267,-250,-231,-212,-195,-179,-160,-135,-102,-62,-21,17,47,71,91,
-112,139,172,208,244,275,301,324,345,369,393,417,440,458,472,482,487,487,482,470,452,
-429,403,376,351,331,321,322,338,369,416,476,550,635,731,835,942,1046,1140,1218,1277,1317,
-1343,1359,1373,1390,1414,1448,1488,1532,1572,1599,1608,1593,1554,1497,1429,1362,1305,1266,1245,1238,1240,
-1242,1242,1237,1233,1234,1247,1271,1306,1344,1382,1415,1445,1474,1507,1545,1588,1630,1667,1696,1715,1726,
-1733,1737,1741,1746,1751,1755,1757,1757,1755,1748,1738,1726,1714,1705,1700,1698,1698,1694,1684,1669,1651,
-1633,1620,1614,1613,1615,1618,1621,1622,1623,1625,1627,1631,1634,1638,1644,1651,1662,1676,1689,1700,1704,
-1700,1692,1682,1677,1678,1687,1699,1711,1716,1712,1701,1686,1671,1659,1654,1654,1657,1661,1664,1664,1663,
-1659,1657,1656,1659,1665,1671,1677,1681,1684,1689,1697,1710,1725,1737,1741,1734,1717,1696,1680,1676,1687,
-1711,1745,1783,1823,1863,1907,1957,2011,2068,2124,2170,2202,2211,2193,2149,2084,2011,1943,1897,1881,1897,
-1935,1979,2011,2018,1995,1945,1877,1802,1729,1666,1612,1569,1533,1502,1475,1448,1417,1377,1320,1239,1125,
-978,805,620,448,318,256,280,392,577,811,1061,1295,1491,1637,1736,1799,1844,1884,1929,1977,2020,
-2050,2060,2048,2024,1997,1980,1978,1990,2007,2023,2032,2033,2030,2026,2024,2026,2029,2033,2038,2045,2057,
-2073,2091,2107,2121,2132,2144,2157,2174,2192,2208,2219,2225,2229,2233,2241,2251,2262,2271,2277,2282,2287,
-2294,2304,2316,2328,2338,2348,2358,2370,2383,2397,2409,2420,2430,2441,2454,2470,2486,2500,2512,2521,2529,
-2535,2541,2544,2545,2544,2546,2553,2565,2580,2592,2598,2597,2590,2584,2580,2580,2583,2583,2579,2572,2565,
-2561,2560,2561,2558,2548,2530,2478,2461,2446,2437,2435,2438,2442,2445,2445,2443,2440,2440,2441,2444,2447,
-2451,2453,2454,2452,2445,2435,2421,2403,2382,2358,2331,2303,2276,2252,2234,2222,2215,2211,2208,2206,2207,
-2212,2224,2239,2254,2265,2270,2268,2264,2262,2265,2273,2284,2296,2306,2316,2329,2348,2372,2399,2428,2455,
-2478,2499,2519,2540,2564,2591,2621,2653,2685,2716,2743,2766,2784,2800,2818,2840,2869,2902,2934,2962,2981,
-2991,2996,2999,3006,3018,3034,3053,3072,3090,3105,3118,3129,3138,3148,3157,3168,3177,3183,3182,3171,3154,
-3135,3122,3123,3139,3166,3193,3212,3216,3207,3193,3184,3188,3206,3235,3266,3291,3307,3316,3325,3337,3357,
-3382,3409,3435,3459,3482,3504,3529,3556,3582,3605,3623,3639,3652,3666,3682,3700,3718,3735,3752,3768,3785,
-3804,3824,3845,3866,3887,3907,3929,3952,3977,4002,4028,4052,4076,4099,4122,4144,4165,4184,4197,4206,4211,
-4214,4217,4221,4225,4229,4229,4226,4220,4213,4206,4202,4200,4199,4197,4194,4189,4186,4186,4189,4195,4201,
-4206,4208,4209,4208,4206,4204,4199,4190,4177,4161,4144,4126,4108,4089,4067,4042,4014,3989,3967,3950,3939,
-3931,3925,3919,3914,3911,3910,3911,3912,3910,3904,3893,3881,3868,3856,3845,3836,3827,3819,3810,3802,3794,
-3785,3776,3766,3755,3745,3735,3725,3715,3704,3690,3674,3656,3637,3618,3601,3588,3578,3572,3568,3564,3559,
-3552,3545,3536,3528,3520,3510,3501,3491,3485,3484,3492,3509,3531,3554,3573,3581,3578,3563,3540,3510,3477,
-3445,3415,3391,3375,3367,3364,3363,3361,3359,3357,3360,3367,3379,3392,3401,3402,3395,3382,3369,3357,3348,
-3341,3332,3321,3308,3293,3280,3267,3254,3237,3216,3191,3163,3137,3116,3101,3092,3088,3084,3078,3065,3044,
-3012,2971,2924,2874,2825,2778,2732,2686,2637,2584,2529,2472,2413,2353,2289,2223,2157,2096,2047,2015,2001,
-2000,2003,2000,1982,1951,1909,1867,1832,1809,1798,1794,1790,1780,1760,1732,1700,1666,1636,1610,1587,1564,
-1538,1510,1479,1446,1415,1386,1359,1334,1309,1283,1256,1226,1196,1164,1132,1101,1070,1040,1010,980,948,
-915,882,848,815,784,753,723,693,660,627,596,566,540,516,492,465,432,395,354,313,273,
-236,202,168,136,103,72,43,16,-9,-35,-63,-92,-123,-155,-187,-219,-252,-288,-325,-364,-401,
--437,-469,-498,-525,-552,-580,-609,-638,-668,-700,-732,-766,-801,-836,-869,-899,-925,-948,-970,-993,-1019,
--1047,-1078,-1111,-1145,-1179,-1214,-1248,-1281,-1314,-1346,-1377,-1407,-1436,-1464,-1493,-1524,-1556,-1589,-1622,-1653,-1681,
--1706,-1730,-1755,-1780,-1807,-1832,-1853,-1872,-1887,-1903,-1921,-1942,-1966,-1991,-2015,-2036,-2053,-2069,-2085,-2101,-2118,
--2135,-2152,-2170,-2188,-2207,-2226,-2244,-2260,-2275,-2289,-2305,-2322,-2341,-2360,-2377,-2391,-2402,-2414,-2426,-2441,-2457,
--2471,-2484,-2494,-2503,-2511,-2520,-2530,-2539,-2546,-2551,-2555,-2558,-2561,-2563,-2565,-2566,-2565,-2564,-2564,-2566,-2569,
--2570,-2569,-2565,-2559,-2554,-2551,-2550,-2549,-2546,-2540,-2533,-2527,-2525,-2527,-2531,-2534,-2533,-2529,-2525,-2523,-2525,
--2531,-2536,-2539,-2536,-2531,-2526,-2524,-2525,-2527,-2525,-2518,-2505,-2489,-2474,-2465,-2461,-2461,-2461,-2458,-2450,-2434,
--2413,-2389,-2362,-2336,-2314,-2296,-2283,-2273,-2264,-2255,-2245,-2237,-2232,-2230,-2230,-2229,-2222,-2209,-2193,-2179,-2171,
--2170,-2175,-2179,-2180,-2175,-2170,-2171,-2184,-2209,-2242,-2273,-2296,-2304,-2301,-2290,-2279,-2270,-2266,-2264,-2264,-2267,
--2274,-2286,-2303,-2320,-2334,-2341,-2343,-2341,-2340,-2343,-2348,-2354,-2358,-2361,-2366,-2376,-2392,-2412,-2430,-2439,-2437,
--2427,-2416,-2413,-2420,-2436,-2454,-2469,-2480,-2495,-2520,-2560,-2612,-2667,-2710,-2734,-2737,-2731,-2729,-2740,-2767,-2804,
--2840,-2868,-2886,-2899,-2914,-2938,-2971,-3010,-3048,-3083,-3111,-3131,-3140,-3132,-3107,-3065,-3015,-2968,-2937,-2928,-2940,
--2965,-2994,-3024,-3053,-3084,-3120,-3160,-3201,-3236,-3264,-3288,-3313,-3344,-3383,-3425,-3462,-3489,-3506,-3517,-3528,-3545,
--3567,-3588,-3603,-3609,-3607,-3603,-3603,-3608,-3617,-3624,-3626,-3620,-3610,-3599,-3592,-3589,-3589,-3589,-3588,-3586,-3586,
--3588,-3593,-3600,-3607,-3612,-3616,-3621,-3625,-3630,-3635,-3638,-3640,-3640,-3642,-3646,-3654,-3664,-3674,-3683,-3688,-3689,
--3687,-3681,-3673,-3664,-3657,-3652,-3649,-3649,-3649,-3647,-3642,-3635,-3628,-3620,-3614,-3607,-3597,-3583,-3566,-3548,-3531,
--3517,-3506,-3496,-3486,-3474,-3461,-3449,-3440,-3434,-3430,-3425,-3417,-3405,-3392,-3378,-3367,-3357,-3348,-3337,-3322,-3302,
--3281,-3259,-3240,-3226,-3215,-3206,-3199,-3193,-3187,-3183,-3179,-3175,-3170,-3161,-3149,-3132,-3112,-3090,-3068,-3048,-3030,
--3015,-3000,-2987,-2974,-2962,-2949,-2936,-2923,-2909,-2894,-2877,-2860,-2843,-2824,-2806,-2787,-2768,-2749,-2731,-2715,-2700,
--2688,-2676,-2666,-2656,-2646,-2637,-2628,-2620,-2612,-2603,-2594,-2583,-2571,-2556,-2539,-2522,-2504,-2489,-2476,-2466,-2457,
--2450,-2442,-2434,-2426,-2416,-2407,-2397,-2387,-2378,-2370,-2365,-2361,-2358,-2355,-2352,-2346,-2339,-2330,-2323,-2316,-2311,
--2307,-2301,-2293,-2283,-2274,-2267,-2262,-2261,-2262,-2262,-2259,-2252,-2241,-2226,-2209,-2193,-2178,-2164,-2151,-2138,-2125,
--2111,-2097,-2085,-2073,-2063,-2052,-2039,-2023,-2007,-1990,-1975,-1963,-1956,-1951,-1949,-1947,-1945,-1944,-1942,-1942,-1942,
--1942,-1943,-1943,-1943,-1943,-1941,-1939,-1937,-1934,-1930,-1928,-1927,-1926,-1926,-1924,-1920,-1914,-1906,-1899,-1893,-1888,
--1884,-1881,-1876,-1871,-1864,-1857,-1848,-1838,-1826,-1814,-1803,-1795,-1791,-1790,-1790,-1787,-1779,-1764,-1742,-1717,-1691,
--1667,-1646,-1629,-1614,-1600,-1588,-1574,-1559,-1542,-1521,-1495,-1467,-1436,-1408,-1384,-1367,-1359,-1357,-1359,-1364,-1368,
--1370,-1370,-1369,-1367,-1366,-1365,-1367,-1369,-1372,-1374,-1375,-1374,-1372,-1370,-1368,-1367,-1368,-1371,-1375,-1380,-1385,
--1390,-1394,-1398,-1401,-1404,-1405,-1406,-1406,-1407,-1408,-1410,-1412,-1416,-1421,-1425,-1429,-1432,-1433,-1434,-1433,-1431,
--1429,-1428,-1427,-1426,-1425,-1424,-1421,-1418,-1415,-1412,-1409,-1408,-1408,-1407,-1406,-1404,-1400,-1393,-1385,-1374,-1363,
--1349,-1335,-1320,-1304,-1288,-1272,-1256,-1240,-1224,-1210,-1199,-1191,-1187,-1186,-1185,-1183,-1176,-1164,-1148,-1132,-1120,
--1114,-1115,-1119,-1121,-1116,-1102,-1079,-1053,-1030,-1016,-1013,-1021,-1037,-1057,-1076,-1091,-1102,-1107,-1106,-1098,-1085,
--1065,-1041,-1015,-988,-963,-939,-919,-901,-886,-872,-858,-842,-824,-803,-780,-757,-736,-716,-698,-681,-665,
--649,-634,-621,-609,-597,-584,-568,-548,-526,-501,-475,-447,-420,-391,-364,-339,-317,-300,-286,-274,-262,
--248,-232,-215,-197,-176,-152,-124,-91,-56,-20,12,42,69,95,121,149,178,209,239,269,296,
-321,344,365,385,405,425,444,462,478,489,496,497,492,483,468,449,427,404,383,368,360,
-361,374,397,433,485,556,646,756,879,1006,1126,1230,1311,1367,1400,1417,1426,1435,1453,1481,1520,
-1562,1597,1614,1607,1572,1513,1442,1371,1314,1278,1266,1272,1288,1305,1318,1327,1335,1348,1368,1398,1433,
-1468,1499,1525,1548,1571,1598,1629,1664,1699,1731,1756,1776,1791,1803,1812,1818,1820,1819,1815,1808,1798,
-1787,1773,1759,1747,1741,1743,1754,1771,1788,1798,1795,1779,1753,1724,1697,1679,1669,1668,1671,1675,1679,
-1682,1685,1689,1695,1702,1710,1719,1727,1734,1739,1739,1737,1732,1725,1719,1715,1715,1718,1722,1724,1724,
-1720,1712,1701,1689,1678,1669,1666,1667,1673,1681,1691,1698,1701,1700,1697,1694,1695,1699,1707,1714,1720,
-1725,1732,1743,1760,1781,1801,1814,1815,1806,1790,1776,1772,1780,1798,1821,1843,1859,1872,1886,1907,1937,
-1976,2019,2059,2088,2102,2100,2086,2066,2046,2034,2032,2042,2063,2087,2111,2127,2131,2121,2099,2069,2035,
-2001,1971,1946,1924,1904,1885,1869,1857,1852,1850,1843,1816,1747,1621,1429,1179,898,625,404,272,252,
-344,529,772,1035,1280,1483,1632,1733,1797,1843,1883,1923,1963,1995,2013,2014,2004,1992,1985,1991,2006,
-2025,2039,2045,2042,2033,2025,2021,2021,2023,2025,2027,2031,2037,2049,2066,2083,2100,2114,2126,2136,2148,
-2162,2176,2188,2197,2204,2209,2214,2219,2224,2228,2232,2236,2241,2250,2260,2273,2285,2297,2307,2317,2327,
-2337,2349,2362,2377,2394,2413,2432,2450,2465,2479,2493,2507,2521,2535,2543,2545,2539,2531,2525,2526,2536,
-2550,2562,2566,2559,2544,2525,2508,2496,2490,2487,2487,2488,2490,2495,2500,2504,2503,2494,2478,2443,2430,
-2417,2408,2401,2396,2391,2387,2385,2387,2394,2405,2417,2427,2433,2432,2426,2416,2401,2383,2361,2335,2307,
-2278,2250,2224,2200,2180,2165,2155,2150,2149,2152,2157,2163,2170,2179,2188,2198,2206,2210,2210,2208,2207,
-2209,2214,2223,2233,2243,2253,2264,2280,2301,2328,2357,2385,2411,2433,2454,2475,2499,2526,2557,2589,2621,
-2651,2677,2698,2715,2730,2746,2767,2794,2827,2860,2890,2912,2925,2931,2936,2943,2956,2974,2993,3011,3026,
-3039,3050,3063,3078,3093,3106,3117,3124,3126,3124,3116,3103,3088,3077,3075,3085,3107,3136,3161,3176,3175,
-3162,3146,3138,3145,3166,3197,3228,3253,3269,3279,3291,3309,3334,3364,3392,3417,3437,3454,3473,3496,3521,
-3547,3569,3587,3600,3611,3624,3639,3656,3674,3692,3710,3727,3745,3764,3785,3805,3824,3843,3861,3879,3897,
-3917,3936,3956,3976,3997,4018,4040,4063,4083,4099,4111,4119,4124,4129,4134,4141,4147,4152,4154,4151,4147,
-4140,4134,4130,4127,4126,4126,4127,4128,4130,4133,4137,4139,4141,4141,4141,4141,4141,4142,4140,4136,4127,
-4114,4099,4082,4066,4051,4036,4019,4002,3985,3969,3955,3943,3933,3922,3910,3896,3882,3870,3861,3856,3854,
-3851,3847,3839,3829,3817,3805,3794,3784,3775,3767,3759,3752,3745,3739,3734,3729,3723,3716,3708,3697,3685,
-3672,3659,3645,3630,3613,3596,3580,3566,3557,3552,3551,3549,3545,3537,3526,3514,3503,3496,3492,3488,3486,
-3486,3489,3500,3519,3544,3569,3590,3601,3602,3593,3575,3553,3528,3502,3477,3456,3441,3431,3425,3418,3408,
-3393,3375,3360,3349,3346,3347,3349,3349,3347,3342,3339,3340,3342,3343,3338,3326,3308,3287,3268,3253,3240,
-3226,3206,3180,3150,3119,3093,3075,3063,3054,3045,3031,3012,2989,2962,2933,2900,2863,2820,2772,2718,2662,
-2604,2548,2493,2439,2387,2333,2276,2217,2156,2096,2042,1999,1969,1952,1945,1940,1932,1915,1889,1856,1823,
-1795,1774,1762,1754,1745,1731,1710,1683,1652,1622,1595,1570,1547,1523,1498,1471,1444,1418,1393,1369,1346,
-1322,1295,1266,1234,1201,1168,1135,1103,1073,1044,1015,985,954,920,885,849,814,780,748,717,686,
-654,621,589,558,530,503,478,451,422,389,353,316,278,239,201,164,127,92,60,29,0,
--28,-56,-84,-112,-138,-165,-193,-224,-259,-298,-339,-380,-417,-448,-476,-501,-527,-555,-586,-617,-649,
--680,-710,-740,-773,-807,-842,-875,-905,-931,-952,-973,-994,-1019,-1047,-1079,-1113,-1147,-1181,-1215,-1248,-1281,
--1315,-1348,-1381,-1413,-1444,-1473,-1502,-1531,-1561,-1592,-1622,-1650,-1677,-1702,-1727,-1753,-1780,-1807,-1833,-1855,-1873,
--1889,-1904,-1922,-1943,-1968,-1993,-2017,-2039,-2058,-2074,-2090,-2106,-2123,-2141,-2159,-2179,-2199,-2219,-2238,-2256,-2273,
--2288,-2303,-2319,-2336,-2353,-2369,-2384,-2396,-2408,-2421,-2436,-2453,-2470,-2486,-2499,-2510,-2519,-2529,-2540,-2550,-2558,
--2565,-2569,-2572,-2577,-2581,-2586,-2589,-2589,-2588,-2587,-2588,-2590,-2594,-2597,-2597,-2594,-2590,-2586,-2584,-2584,-2582,
--2578,-2572,-2565,-2559,-2558,-2561,-2566,-2569,-2567,-2563,-2558,-2555,-2557,-2562,-2566,-2568,-2566,-2561,-2559,-2559,-2562,
--2565,-2564,-2557,-2544,-2528,-2515,-2507,-2505,-2507,-2508,-2507,-2500,-2487,-2467,-2442,-2414,-2386,-2360,-2340,-2326,-2317,
--2310,-2302,-2293,-2284,-2279,-2278,-2278,-2277,-2270,-2255,-2237,-2220,-2211,-2211,-2219,-2226,-2227,-2219,-2208,-2202,-2207,
--2226,-2257,-2290,-2317,-2333,-2336,-2331,-2324,-2316,-2309,-2302,-2296,-2294,-2299,-2313,-2333,-2354,-2371,-2381,-2383,-2383,
--2385,-2392,-2401,-2408,-2409,-2406,-2404,-2410,-2425,-2446,-2465,-2473,-2467,-2453,-2443,-2450,-2478,-2522,-2567,-2602,-2617,
--2618,-2614,-2619,-2638,-2669,-2703,-2730,-2747,-2755,-2764,-2780,-2807,-2840,-2873,-2902,-2926,-2948,-2974,-3006,-3044,-3084,
--3122,-3154,-3179,-3197,-3207,-3204,-3188,-3159,-3125,-3095,-3080,-3084,-3105,-3135,-3166,-3193,-3218,-3243,-3272,-3304,-3338,
--3366,-3388,-3406,-3424,-3449,-3481,-3517,-3550,-3575,-3592,-3603,-3615,-3632,-3651,-3670,-3682,-3685,-3683,-3681,-3683,-3691,
--3702,-3711,-3713,-3707,-3695,-3683,-3675,-3671,-3669,-3668,-3665,-3661,-3659,-3662,-3670,-3681,-3692,-3700,-3704,-3704,-3703,
--3703,-3705,-3709,-3713,-3716,-3720,-3725,-3730,-3737,-3744,-3750,-3752,-3752,-3747,-3741,-3733,-3726,-3720,-3716,-3715,-3713,
--3712,-3709,-3704,-3699,-3694,-3689,-3684,-3677,-3666,-3652,-3634,-3616,-3599,-3585,-3574,-3564,-3553,-3540,-3527,-3513,-3502,
--3493,-3486,-3480,-3473,-3464,-3454,-3444,-3435,-3427,-3416,-3403,-3385,-3364,-3341,-3320,-3301,-3286,-3274,-3263,-3253,-3242,
--3232,-3225,-3219,-3215,-3211,-3204,-3193,-3177,-3155,-3131,-3105,-3082,-3061,-3044,-3030,-3018,-3008,-2998,-2988,-2979,-2969,
--2959,-2947,-2933,-2918,-2900,-2881,-2860,-2839,-2817,-2796,-2775,-2755,-2738,-2722,-2709,-2697,-2687,-2677,-2668,-2660,-2652,
--2646,-2640,-2634,-2627,-2617,-2606,-2592,-2576,-2561,-2546,-2534,-2523,-2512,-2501,-2489,-2476,-2464,-2452,-2440,-2430,-2421,
--2412,-2404,-2398,-2394,-2392,-2390,-2388,-2383,-2375,-2366,-2355,-2345,-2336,-2328,-2319,-2309,-2299,-2291,-2286,-2287,-2292,
--2299,-2306,-2308,-2302,-2290,-2271,-2251,-2230,-2212,-2197,-2184,-2171,-2157,-2144,-2130,-2117,-2104,-2093,-2080,-2067,-2053,
--2039,-2026,-2015,-2007,-2001,-1997,-1993,-1989,-1986,-1984,-1983,-1984,-1985,-1986,-1987,-1987,-1986,-1985,-1982,-1980,-1976,
--1972,-1969,-1966,-1965,-1966,-1967,-1966,-1963,-1959,-1952,-1945,-1939,-1932,-1925,-1916,-1905,-1894,-1882,-1872,-1864,-1857,
--1852,-1848,-1845,-1845,-1846,-1849,-1851,-1849,-1842,-1828,-1809,-1787,-1765,-1745,-1729,-1717,-1707,-1699,-1691,-1683,-1674,
--1662,-1645,-1622,-1593,-1561,-1528,-1499,-1477,-1461,-1451,-1445,-1441,-1437,-1432,-1426,-1421,-1417,-1414,-1412,-1412,-1412,
--1412,-1412,-1412,-1413,-1414,-1416,-1418,-1420,-1421,-1423,-1424,-1425,-1426,-1429,-1432,-1436,-1440,-1444,-1447,-1449,-1451,
--1451,-1451,-1449,-1446,-1443,-1440,-1438,-1437,-1439,-1441,-1445,-1447,-1450,-1451,-1451,-1451,-1450,-1449,-1447,-1444,-1441,
--1438,-1436,-1435,-1436,-1437,-1437,-1437,-1434,-1430,-1423,-1415,-1405,-1393,-1380,-1365,-1349,-1332,-1315,-1298,-1281,-1265,
--1248,-1234,-1222,-1214,-1210,-1209,-1210,-1209,-1204,-1194,-1181,-1167,-1155,-1147,-1143,-1141,-1136,-1127,-1111,-1092,-1072,
--1055,-1046,-1044,-1048,-1057,-1069,-1082,-1095,-1106,-1113,-1115,-1108,-1094,-1072,-1046,-1019,-992,-968,-946,-928,-914,
--903,-896,-888,-879,-865,-846,-823,-798,-776,-757,-742,-729,-716,-701,-686,-670,-655,-640,-625,-608,-586,
--559,-529,-497,-466,-436,-407,-380,-355,-333,-313,-297,-284,-271,-259,-244,-228,-209,-189,-168,-145,-120,
--91,-59,-24,10,43,73,100,125,150,176,205,235,265,293,317,337,355,373,393,415,439,
-462,481,496,505,511,512,510,505,496,484,472,460,450,442,435,430,430,440,469,524,609,
-723,859,1004,1143,1263,1353,1412,1443,1455,1458,1464,1477,1500,1527,1551,1562,1555,1527,1483,1431,1381,
-1343,1322,1318,1327,1343,1361,1378,1396,1415,1438,1466,1498,1530,1560,1586,1608,1629,1651,1677,1704,1732,
-1757,1777,1793,1806,1819,1833,1848,1864,1878,1887,1889,1883,1867,1843,1813,1783,1759,1748,1753,1773,1803,
-1833,1853,1855,1840,1811,1777,1746,1723,1712,1710,1714,1719,1722,1723,1723,1725,1731,1742,1757,1775,1791,
-1802,1805,1800,1790,1778,1770,1766,1767,1768,1768,1762,1750,1735,1720,1710,1705,1705,1707,1710,1713,1715,
-1718,1723,1729,1733,1734,1730,1725,1720,1720,1726,1737,1750,1762,1771,1778,1786,1798,1814,1832,1846,1854,
-1855,1852,1851,1856,1869,1888,1907,1920,1925,1921,1916,1915,1923,1940,1963,1986,2005,2017,2026,2033,2042,
-2055,2071,2087,2100,2110,2117,2122,2127,2134,2140,2145,2147,2146,2144,2141,2136,2130,2118,2100,2080,2064,
-2060,2073,2096,2114,2102,2032,1884,1654,1358,1032,721,471,320,286,365,539,774,1031,1275,1480,1636,
-1743,1812,1857,1892,1924,1953,1975,1990,1997,2000,2006,2016,2030,2044,2052,2051,2042,2029,2018,2013,2013,
-2016,2019,2021,2023,2027,2037,2053,2073,2093,2108,2117,2122,2127,2133,2141,2153,2164,2174,2180,2182,2183,
-2183,2183,2187,2192,2201,2213,2226,2240,2254,2268,2280,2291,2301,2310,2321,2334,2351,2372,2394,2414,2431,
-2445,2457,2471,2490,2512,2533,2549,2553,2547,2534,2522,2518,2523,2534,2545,2549,2541,2525,2503,2483,2468,
-2458,2453,2451,2451,2452,2456,2460,2462,2461,2454,2443,2404,2392,2380,2368,2355,2343,2333,2326,2326,2333,
-2346,2363,2377,2386,2385,2376,2361,2342,2320,2296,2271,2245,2219,2195,2174,2159,2148,2140,2136,2133,2132,
-2132,2133,2136,2138,2141,2143,2144,2146,2146,2147,2149,2151,2155,2161,2167,2174,2181,2188,2198,2211,2230,
-2253,2280,2307,2332,2356,2379,2403,2429,2458,2490,2521,2552,2579,2604,2625,2644,2663,2683,2707,2734,2765,
-2796,2824,2845,2859,2866,2873,2882,2897,2917,2938,2955,2967,2973,2978,2987,3002,3021,3042,3058,3067,3068,
-3062,3054,3045,3037,3033,3033,3039,3053,3073,3095,3113,3121,3120,3111,3102,3102,3113,3136,3165,3192,3214,
-3230,3244,3260,3282,3310,3340,3368,3392,3412,3430,3449,3471,3493,3515,3532,3544,3553,3561,3572,3587,3605,
-3624,3643,3662,3681,3701,3721,3742,3763,3781,3798,3814,3830,3846,3864,3881,3899,3918,3936,3956,3977,3996,
-4014,4028,4039,4047,4053,4058,4063,4068,4073,4077,4080,4081,4080,4077,4074,4069,4065,4062,4062,4065,4070,
-4077,4083,4086,4086,4085,4082,4080,4079,4080,4081,4079,4074,4065,4052,4036,4020,4005,3990,3975,3961,3947,
-3932,3919,3907,3896,3886,3874,3861,3847,3832,3819,3809,3802,3798,3794,3789,3781,3770,3758,3746,3736,3729,
-3725,3722,3719,3714,3708,3702,3696,3692,3689,3684,3676,3665,3652,3638,3626,3615,3606,3595,3583,3570,3557,
-3547,3540,3536,3531,3523,3512,3498,3485,3477,3473,3474,3477,3479,3482,3488,3499,3518,3544,3572,3596,3614,
-3623,3624,3619,3611,3600,3587,3573,3558,3546,3537,3528,3517,3500,3474,3442,3408,3378,3356,3344,3339,3340,
-3342,3347,3354,3362,3370,3374,3368,3353,3329,3301,3276,3257,3241,3225,3205,3179,3149,3120,3097,3080,3068,
-3055,3036,3008,2976,2944,2917,2896,2879,2861,2834,2796,2746,2688,2626,2564,2503,2445,2387,2330,2272,2216,
-2161,2110,2062,2020,1985,1959,1941,1930,1920,1908,1887,1859,1823,1787,1754,1729,1712,1701,1691,1678,1659,
-1636,1609,1581,1554,1528,1503,1478,1454,1430,1409,1389,1370,1350,1328,1302,1272,1239,1204,1168,1133,1099,
-1067,1037,1008,978,948,915,880,844,807,772,738,705,674,643,612,582,552,522,493,464,435,
-404,372,338,304,269,231,193,153,113,75,39,7,-23,-51,-78,-104,-129,-152,-175,-200,-230,
--265,-304,-346,-387,-422,-453,-480,-505,-533,-564,-598,-631,-662,-691,-717,-743,-772,-804,-839,-873,-904,
--931,-954,-975,-997,-1022,-1052,-1086,-1122,-1157,-1192,-1224,-1256,-1287,-1319,-1352,-1386,-1419,-1451,-1482,-1513,-1542,
--1570,-1598,-1625,-1650,-1675,-1699,-1724,-1751,-1779,-1807,-1833,-1857,-1877,-1894,-1912,-1930,-1951,-1974,-1998,-2022,-2043,
--2063,-2080,-2097,-2114,-2131,-2149,-2168,-2187,-2208,-2228,-2248,-2266,-2283,-2299,-2315,-2331,-2348,-2363,-2378,-2391,-2404,
--2418,-2433,-2449,-2467,-2482,-2496,-2507,-2518,-2530,-2544,-2558,-2570,-2579,-2584,-2587,-2589,-2593,-2600,-2607,-2612,-2615,
--2615,-2615,-2615,-2617,-2620,-2622,-2622,-2620,-2618,-2616,-2617,-2618,-2618,-2615,-2609,-2602,-2595,-2593,-2594,-2596,-2597,
--2596,-2592,-2589,-2588,-2590,-2594,-2597,-2597,-2594,-2591,-2590,-2593,-2599,-2603,-2603,-2596,-2583,-2569,-2556,-2549,-2547,
--2549,-2551,-2551,-2546,-2536,-2519,-2496,-2467,-2437,-2409,-2385,-2369,-2358,-2350,-2342,-2334,-2326,-2321,-2321,-2324,-2324,
--2319,-2304,-2285,-2266,-2255,-2255,-2261,-2269,-2270,-2262,-2249,-2238,-2238,-2252,-2279,-2311,-2339,-2357,-2365,-2365,-2360,
--2352,-2343,-2332,-2322,-2318,-2323,-2338,-2362,-2386,-2405,-2415,-2417,-2418,-2422,-2430,-2440,-2445,-2442,-2435,-2430,-2435,
--2452,-2474,-2493,-2498,-2490,-2478,-2481,-2512,-2573,-2654,-2728,-2774,-2777,-2742,-2690,-2646,-2628,-2642,-2679,-2725,-2765,
--2793,-2812,-2829,-2849,-2876,-2906,-2938,-2969,-3000,-3033,-3070,-3107,-3142,-3173,-3198,-3220,-3240,-3257,-3269,-3271,-3264,
--3250,-3237,-3231,-3238,-3258,-3284,-3311,-3335,-3355,-3375,-3399,-3427,-3457,-3484,-3505,-3521,-3535,-3552,-3575,-3602,-3629,
--3653,-3671,-3686,-3699,-3713,-3727,-3739,-3747,-3750,-3750,-3752,-3759,-3770,-3781,-3789,-3789,-3781,-3770,-3759,-3753,-3751,
--3750,-3748,-3744,-3739,-3736,-3738,-3746,-3758,-3769,-3776,-3779,-3778,-3775,-3775,-3779,-3785,-3792,-3798,-3804,-3808,-3811,
--3814,-3817,-3817,-3816,-3812,-3806,-3799,-3792,-3786,-3782,-3780,-3778,-3776,-3773,-3769,-3765,-3760,-3757,-3753,-3749,-3743,
--3734,-3722,-3708,-3692,-3677,-3664,-3651,-3639,-3626,-3611,-3596,-3580,-3565,-3553,-3543,-3535,-3528,-3522,-3518,-3513,-3507,
--3499,-3488,-3472,-3451,-3428,-3406,-3385,-3368,-3355,-3343,-3332,-3319,-3305,-3291,-3278,-3266,-3257,-3249,-3241,-3229,-3214,
--3195,-3172,-3149,-3126,-3106,-3090,-3076,-3064,-3053,-3043,-3032,-3022,-3012,-3002,-2991,-2979,-2965,-2948,-2931,-2911,-2891,
--2871,-2850,-2829,-2809,-2789,-2770,-2754,-2739,-2727,-2717,-2707,-2698,-2690,-2681,-2674,-2666,-2658,-2651,-2642,-2633,-2624,
--2615,-2607,-2597,-2587,-2575,-2560,-2544,-2528,-2512,-2498,-2487,-2476,-2467,-2456,-2446,-2435,-2427,-2421,-2417,-2415,-2412,
--2408,-2402,-2395,-2387,-2378,-2370,-2360,-2350,-2341,-2333,-2329,-2330,-2335,-2343,-2351,-2354,-2350,-2339,-2323,-2303,-2283,
--2264,-2247,-2231,-2215,-2198,-2181,-2165,-2150,-2138,-2126,-2115,-2104,-2092,-2081,-2070,-2062,-2055,-2050,-2045,-2041,-2036,
--2032,-2029,-2029,-2030,-2031,-2032,-2033,-2032,-2030,-2028,-2026,-2024,-2021,-2018,-2015,-2012,-2010,-2008,-2007,-2004,-1999,
--1993,-1987,-1980,-1974,-1968,-1961,-1953,-1942,-1931,-1919,-1909,-1901,-1894,-1888,-1882,-1876,-1871,-1868,-1866,-1866,-1864,
--1860,-1853,-1843,-1832,-1821,-1811,-1803,-1795,-1789,-1782,-1777,-1772,-1768,-1763,-1755,-1742,-1724,-1703,-1678,-1654,-1632,
--1613,-1596,-1581,-1565,-1550,-1535,-1521,-1509,-1500,-1492,-1485,-1478,-1470,-1462,-1456,-1452,-1452,-1457,-1464,-1473,-1480,
--1485,-1485,-1483,-1479,-1475,-1472,-1471,-1472,-1475,-1478,-1483,-1489,-1495,-1501,-1505,-1506,-1503,-1496,-1486,-1477,-1469,
--1465,-1463,-1465,-1467,-1470,-1473,-1474,-1475,-1475,-1474,-1472,-1468,-1465,-1462,-1461,-1461,-1464,-1466,-1468,-1468,-1466,
--1461,-1455,-1448,-1439,-1428,-1415,-1399,-1381,-1361,-1342,-1323,-1305,-1289,-1273,-1259,-1247,-1237,-1230,-1227,-1226,-1224,
--1220,-1212,-1202,-1190,-1179,-1170,-1163,-1156,-1147,-1136,-1122,-1106,-1092,-1081,-1075,-1073,-1074,-1078,-1083,-1091,-1100,
--1109,-1117,-1119,-1114,-1101,-1081,-1056,-1030,-1004,-980,-959,-942,-929,-920,-915,-911,-903,-890,-871,-846,-820,
--797,-779,-766,-756,-747,-735,-720,-704,-689,-675,-661,-644,-621,-591,-556,-519,-483,-451,-424,-400,-378,
--357,-336,-316,-299,-283,-269,-254,-238,-220,-201,-181,-161,-138,-113,-83,-50,-15,18,49,75,99,
-121,144,171,201,231,260,285,307,327,347,369,394,421,447,470,489,504,517,528,537,543,
-547,548,547,545,543,540,534,524,512,501,499,517,561,638,743,868,1001,1126,1233,1316,1376,
-1417,1446,1469,1489,1506,1515,1515,1502,1479,1450,1420,1396,1381,1375,1376,1381,1388,1395,1403,1414,1430,
-1453,1481,1511,1541,1568,1591,1612,1633,1657,1683,1711,1739,1764,1783,1795,1803,1809,1818,1830,1849,1872,
-1898,1921,1938,1942,1931,1905,1867,1826,1790,1769,1766,1782,1808,1835,1853,1856,1844,1822,1798,1778,1766,
-1763,1765,1768,1768,1763,1754,1743,1735,1734,1744,1763,1789,1816,1835,1844,1842,1833,1822,1817,1819,1827,
-1834,1835,1825,1805,1781,1760,1748,1748,1756,1768,1778,1783,1783,1779,1775,1771,1766,1760,1751,1741,1732,
-1730,1737,1750,1766,1781,1792,1799,1805,1811,1822,1836,1851,1862,1870,1874,1877,1884,1896,1912,1929,1943,
-1951,1953,1951,1949,1950,1955,1965,1975,1986,1998,2011,2029,2050,2075,2099,2118,2130,2136,2139,2142,2149,
-2160,2174,2188,2198,2206,2210,2214,2216,2214,2204,2184,2157,2128,2110,2109,2127,2154,2170,2150,2068,1912,
-1684,1402,1098,811,578,429,383,442,592,807,1051,1291,1497,1654,1760,1826,1865,1893,1919,1944,1968,
-1989,2006,2020,2032,2042,2047,2047,2039,2026,2011,1999,1994,1995,2001,2007,2013,2017,2024,2036,2054,2076,
-2097,2112,2120,2121,2119,2119,2123,2132,2143,2153,2159,2161,2160,2160,2162,2168,2178,2190,2202,2214,2227,
-2240,2253,2267,2280,2292,2302,2311,2324,2340,2361,2383,2404,2420,2431,2440,2452,2469,2491,2514,2532,2540,
-2537,2527,2516,2511,2515,2525,2535,2541,2537,2525,2509,2492,2479,2468,2460,2452,2444,2437,2432,2428,2425,
-2420,2414,2404,2360,2348,2334,2319,2304,2290,2279,2275,2278,2288,2303,2318,2327,2326,2315,2296,2273,2248,
-2224,2203,2184,2165,2150,2137,2128,2122,2120,2118,2115,2110,2105,2099,2094,2090,2087,2086,2084,2083,2083,
-2085,2090,2096,2103,2110,2116,2120,2123,2127,2133,2143,2160,2181,2205,2230,2254,2276,2298,2323,2351,2383,
-2418,2453,2486,2514,2537,2557,2576,2597,2620,2647,2677,2708,2738,2764,2784,2797,2805,2812,2822,2838,2859,
-2881,2900,2912,2916,2917,2920,2931,2949,2973,2995,3010,3014,3009,2999,2989,2984,2986,2992,3001,3012,3023,
-3036,3048,3057,3063,3064,3064,3066,3074,3090,3112,3137,3161,3181,3197,3213,3231,3254,3281,3310,3337,3362,
-3385,3407,3429,3450,3469,3483,3491,3496,3500,3507,3518,3535,3554,3575,3595,3615,3635,3656,3678,3700,3720,
-3739,3755,3770,3786,3802,3821,3840,3860,3879,3898,3915,3932,3946,3959,3970,3979,3988,3995,4002,4006,4009,
-4011,4013,4016,4019,4022,4023,4022,4017,4011,4005,4003,4006,4012,4021,4028,4032,4033,4031,4029,4027,4027,
-4026,4025,4020,4013,4003,3990,3977,3964,3950,3936,3922,3908,3893,3879,3865,3851,3839,3827,3815,3804,3793,
-3781,3770,3759,3750,3743,3736,3730,3722,3713,3703,3694,3688,3686,3688,3691,3692,3689,3681,3672,3662,3655,
-3649,3644,3638,3629,3619,3608,3598,3592,3587,3582,3574,3564,3551,3539,3527,3518,3508,3497,3485,3473,3465,
-3461,3464,3468,3472,3474,3474,3476,3485,3503,3529,3559,3589,3612,3629,3639,3645,3648,3648,3644,3636,3626,
-3617,3609,3602,3593,3576,3548,3511,3468,3427,3396,3378,3373,3376,3384,3394,3404,3411,3415,3411,3397,3373,
-3341,3306,3275,3250,3230,3211,3190,3165,3140,3117,3102,3093,3085,3072,3046,3008,2963,2920,2887,2868,2859,
-2853,2842,2818,2781,2732,2677,2619,2558,2495,2428,2358,2289,2223,2164,2113,2069,2030,1996,1967,1943,1926,
-1913,1901,1884,1858,1824,1783,1742,1706,1680,1663,1653,1644,1634,1618,1597,1572,1545,1517,1489,1462,1436,
-1413,1393,1375,1357,1339,1318,1293,1265,1233,1198,1162,1126,1090,1056,1024,994,965,936,905,872,837,
-801,764,728,693,661,630,601,573,546,518,488,457,424,390,356,324,291,258,224,186,145,
-103,61,22,-11,-42,-69,-94,-118,-141,-164,-186,-211,-240,-273,-311,-351,-389,-425,-456,-485,-514,
--545,-578,-612,-645,-675,-701,-724,-747,-774,-805,-838,-872,-903,-930,-953,-975,-998,-1025,-1057,-1094,-1132,
--1169,-1204,-1236,-1265,-1294,-1323,-1354,-1385,-1418,-1451,-1484,-1516,-1546,-1576,-1603,-1629,-1653,-1677,-1701,-1726,-1753,
--1781,-1808,-1834,-1858,-1879,-1898,-1918,-1938,-1959,-1982,-2005,-2027,-2048,-2069,-2088,-2106,-2123,-2140,-2158,-2176,-2195,
--2215,-2235,-2254,-2272,-2289,-2305,-2321,-2338,-2355,-2371,-2386,-2400,-2414,-2430,-2446,-2464,-2480,-2494,-2504,-2514,-2524,
--2537,-2553,-2570,-2586,-2596,-2603,-2606,-2608,-2613,-2620,-2628,-2636,-2640,-2642,-2642,-2643,-2645,-2648,-2650,-2650,-2648,
--2647,-2647,-2649,-2651,-2653,-2652,-2647,-2640,-2634,-2629,-2627,-2627,-2626,-2624,-2623,-2622,-2624,-2627,-2631,-2632,-2630,
--2626,-2623,-2623,-2627,-2633,-2637,-2637,-2631,-2619,-2606,-2595,-2589,-2587,-2588,-2590,-2590,-2586,-2578,-2564,-2543,-2516,
--2487,-2458,-2435,-2418,-2406,-2397,-2388,-2379,-2370,-2365,-2365,-2368,-2370,-2366,-2353,-2333,-2314,-2302,-2300,-2306,-2314,
--2316,-2309,-2295,-2282,-2277,-2284,-2304,-2330,-2356,-2375,-2386,-2389,-2388,-2381,-2371,-2359,-2348,-2343,-2350,-2368,-2393,
--2419,-2437,-2446,-2447,-2448,-2453,-2462,-2471,-2475,-2470,-2462,-2458,-2465,-2484,-2508,-2525,-2527,-2519,-2514,-2534,-2594,
--2692,-2807,-2903,-2949,-2931,-2857,-2757,-2671,-2626,-2633,-2680,-2744,-2803,-2843,-2863,-2873,-2883,-2903,-2931,-2967,-3006,
--3045,-3085,-3123,-3160,-3192,-3219,-3240,-3260,-3281,-3305,-3330,-3351,-3364,-3368,-3367,-3366,-3372,-3386,-3407,-3432,-3455,
--3475,-3495,-3516,-3540,-3567,-3592,-3612,-3626,-3636,-3646,-3659,-3678,-3699,-3722,-3743,-3761,-3775,-3787,-3796,-3803,-3808,
--3812,-3815,-3821,-3830,-3840,-3849,-3853,-3851,-3844,-3836,-3831,-3829,-3830,-3831,-3830,-3827,-3822,-3819,-3819,-3824,-3832,
--3840,-3845,-3847,-3848,-3848,-3852,-3857,-3865,-3872,-3878,-3882,-3884,-3885,-3885,-3884,-3882,-3878,-3872,-3865,-3857,-3851,
--3845,-3842,-3839,-3836,-3834,-3830,-3827,-3823,-3819,-3815,-3812,-3809,-3805,-3799,-3791,-3782,-3770,-3757,-3744,-3730,-3715,
--3700,-3683,-3666,-3649,-3634,-3619,-3607,-3597,-3589,-3583,-3579,-3576,-3571,-3564,-3552,-3536,-3516,-3495,-3474,-3455,-3439,
--3427,-3416,-3404,-3391,-3376,-3360,-3343,-3326,-3311,-3298,-3285,-3271,-3256,-3239,-3221,-3201,-3182,-3164,-3148,-3133,-3120,
--3107,-3095,-3082,-3070,-3057,-3045,-3033,-3019,-3004,-2988,-2970,-2953,-2936,-2920,-2904,-2887,-2870,-2852,-2833,-2814,-2797,
--2781,-2768,-2756,-2745,-2735,-2723,-2712,-2700,-2689,-2680,-2673,-2667,-2663,-2659,-2655,-2648,-2639,-2627,-2612,-2595,-2579,
--2564,-2552,-2541,-2532,-2522,-2510,-2496,-2482,-2468,-2457,-2450,-2445,-2442,-2440,-2436,-2432,-2427,-2422,-2416,-2411,-2405,
--2398,-2393,-2388,-2386,-2387,-2390,-2394,-2396,-2395,-2389,-2380,-2367,-2353,-2338,-2323,-2306,-2287,-2267,-2246,-2226,-2208,
--2192,-2178,-2165,-2154,-2142,-2131,-2121,-2112,-2105,-2099,-2093,-2088,-2084,-2081,-2079,-2079,-2080,-2081,-2081,-2081,-2079,
--2076,-2073,-2070,-2068,-2065,-2062,-2059,-2055,-2051,-2046,-2041,-2034,-2027,-2020,-2013,-2007,-2002,-1997,-1992,-1986,-1979,
--1972,-1965,-1958,-1951,-1944,-1934,-1923,-1910,-1897,-1886,-1878,-1872,-1868,-1865,-1862,-1858,-1853,-1848,-1843,-1837,-1831,
--1824,-1818,-1812,-1808,-1807,-1808,-1810,-1811,-1810,-1807,-1801,-1792,-1780,-1766,-1748,-1729,-1707,-1685,-1664,-1645,-1630,
--1617,-1605,-1593,-1578,-1561,-1542,-1525,-1512,-1506,-1507,-1514,-1524,-1535,-1542,-1545,-1545,-1542,-1539,-1535,-1533,-1531,
--1529,-1528,-1528,-1532,-1538,-1547,-1555,-1561,-1562,-1558,-1548,-1537,-1525,-1515,-1509,-1505,-1504,-1504,-1505,-1507,-1508,
--1508,-1506,-1502,-1498,-1493,-1489,-1487,-1488,-1491,-1494,-1496,-1496,-1494,-1489,-1483,-1476,-1468,-1458,-1444,-1426,-1405,
--1383,-1361,-1342,-1325,-1311,-1299,-1287,-1276,-1264,-1254,-1245,-1238,-1231,-1226,-1219,-1211,-1203,-1195,-1188,-1181,-1173,
--1164,-1153,-1140,-1126,-1115,-1105,-1099,-1096,-1095,-1096,-1098,-1103,-1109,-1116,-1121,-1122,-1117,-1105,-1087,-1064,-1040,
--1015,-991,-970,-953,-940,-932,-927,-924,-917,-904,-884,-858,-832,-808,-790,-778,-769,-759,-747,-732,-717,
--702,-690,-678,-664,-644,-616,-582,-545,-510,-479,-454,-431,-410,-387,-362,-338,-314,-294,-277,-261,-246,
--229,-211,-190,-168,-144,-118,-90,-61,-31,-2,24,48,70,91,114,139,166,195,223,249,273,
-297,321,347,373,399,424,446,468,488,509,530,550,568,581,589,595,599,604,610,617,620,
-619,613,605,601,609,637,686,755,840,932,1025,1115,1200,1280,1353,1418,1470,1502,1511,1496,1462,
-1421,1384,1361,1357,1368,1389,1412,1428,1436,1439,1440,1446,1460,1482,1508,1534,1558,1578,1595,1613,1634,
-1660,1690,1722,1752,1778,1798,1812,1821,1829,1837,1847,1862,1883,1908,1935,1959,1974,1976,1961,1934,1899,
-1864,1838,1823,1820,1823,1827,1827,1821,1812,1804,1800,1803,1812,1823,1831,1833,1826,1809,1785,1759,1737,
-1725,1726,1742,1768,1797,1821,1834,1837,1832,1827,1829,1841,1859,1876,1885,1881,1864,1839,1817,1802,1800,
-1807,1818,1827,1830,1826,1818,1809,1800,1791,1780,1768,1755,1745,1742,1746,1758,1774,1790,1803,1812,1819,
-1827,1838,1853,1870,1884,1893,1897,1896,1895,1897,1905,1919,1936,1954,1970,1982,1989,1994,1997,2000,2005,
-2013,2025,2040,2059,2080,2103,2123,2141,2155,2166,2177,2189,2203,2218,2232,2242,2247,2247,2246,2245,2246,
-2245,2240,2227,2204,2176,2150,2134,2130,2137,2144,2135,2094,2006,1864,1669,1433,1175,922,705,554,492,
-530,660,860,1094,1325,1523,1670,1766,1824,1859,1887,1915,1944,1973,1996,2013,2023,2029,2030,2027,2019,
-2008,1996,1985,1981,1982,1989,1998,2007,2017,2028,2043,2061,2082,2102,2117,2125,2125,2121,2117,2117,2122,
-2130,2138,2144,2147,2148,2151,2157,2168,2180,2193,2203,2211,2218,2227,2239,2254,2271,2285,2297,2308,2319,
-2334,2354,2377,2401,2419,2431,2438,2443,2451,2464,2480,2494,2504,2506,2503,2498,2497,2501,2510,2518,2522,
-2519,2510,2496,2482,2468,2456,2445,2433,2421,2409,2399,2390,2384,2378,2370,2360,2314,2301,2287,2271,2255,
-2241,2232,2229,2234,2245,2258,2269,2273,2267,2251,2228,2202,2177,2155,2138,2123,2112,2102,2094,2088,2083,
-2077,2069,2060,2048,2035,2024,2016,2011,2009,2010,2013,2018,2024,2032,2041,2050,2059,2065,2069,2070,2072,
-2076,2084,2098,2118,2142,2166,2189,2209,2228,2248,2273,2303,2340,2379,2418,2452,2479,2500,2518,2536,2557,
-2582,2611,2641,2670,2696,2716,2731,2742,2752,2763,2779,2798,2819,2838,2852,2859,2863,2867,2876,2893,2915,
-2938,2956,2965,2963,2954,2945,2940,2943,2951,2963,2974,2983,2989,2994,2998,3003,3008,3013,3020,3030,3044,
-3063,3086,3109,3131,3151,3168,3185,3204,3226,3250,3276,3303,3329,3354,3379,3403,3422,3437,3444,3447,3447,
-3449,3457,3470,3489,3510,3530,3550,3570,3590,3611,3633,3655,3676,3694,3711,3728,3745,3764,3786,3808,3830,
-3852,3870,3886,3898,3907,3914,3920,3927,3936,3944,3951,3956,3957,3956,3955,3957,3960,3965,3969,3969,3966,
-3961,3955,3953,3954,3960,3966,3972,3976,3977,3976,3975,3975,3975,3972,3968,3961,3952,3942,3933,3924,3915,
-3904,3891,3877,3862,3847,3833,3819,3806,3793,3781,3771,3762,3753,3742,3729,3714,3700,3686,3677,3670,3666,
-3662,3659,3656,3655,3656,3660,3664,3665,3662,3652,3639,3625,3613,3605,3601,3597,3593,3587,3581,3575,3572,
-3569,3566,3559,3549,3536,3521,3507,3494,3483,3473,3465,3459,3456,3459,3464,3469,3471,3469,3465,3463,3469,
-3484,3508,3537,3564,3586,3602,3611,3618,3620,3619,3614,3604,3593,3584,3579,3579,3579,3574,3556,3527,3489,
-3452,3424,3409,3408,3416,3428,3439,3444,3443,3434,3418,3392,3359,3321,3282,3248,3220,3198,3179,3160,3139,
-3118,3102,3092,3088,3084,3072,3048,3009,2962,2917,2881,2861,2852,2849,2842,2825,2796,2759,2716,2669,2618,
-2558,2489,2411,2329,2248,2176,2115,2064,2021,1982,1948,1918,1894,1878,1867,1856,1840,1814,1780,1741,1702,
-1669,1645,1631,1623,1616,1607,1593,1573,1547,1518,1487,1456,1428,1403,1381,1361,1341,1320,1298,1273,1245,
-1215,1183,1150,1116,1081,1046,1014,983,954,927,899,869,836,802,765,728,691,656,622,591,563,
-535,508,479,448,414,378,344,310,278,247,214,177,136,92,48,7,-27,-57,-82,-105,-128,
--152,-176,-202,-230,-260,-292,-328,-364,-401,-436,-468,-499,-530,-561,-593,-625,-656,-683,-708,-731,-755,
--783,-814,-846,-878,-908,-934,-957,-979,-1004,-1033,-1066,-1103,-1141,-1177,-1211,-1242,-1270,-1298,-1327,-1356,-1387,
--1418,-1451,-1483,-1516,-1547,-1577,-1604,-1630,-1654,-1679,-1704,-1731,-1758,-1786,-1812,-1837,-1859,-1879,-1900,-1921,-1944,
--1967,-1990,-2013,-2035,-2056,-2076,-2097,-2116,-2134,-2152,-2170,-2188,-2206,-2225,-2244,-2263,-2280,-2297,-2313,-2330,-2347,
--2364,-2380,-2395,-2410,-2424,-2441,-2459,-2477,-2494,-2508,-2519,-2528,-2538,-2551,-2567,-2584,-2600,-2613,-2620,-2625,-2629,
--2635,-2642,-2650,-2657,-2662,-2664,-2666,-2668,-2672,-2677,-2680,-2683,-2683,-2683,-2683,-2685,-2688,-2690,-2690,-2687,-2682,
--2676,-2672,-2669,-2668,-2666,-2664,-2663,-2663,-2665,-2668,-2671,-2672,-2670,-2666,-2663,-2663,-2666,-2670,-2673,-2671,-2664,
--2654,-2643,-2634,-2629,-2627,-2628,-2629,-2629,-2627,-2620,-2608,-2589,-2564,-2536,-2509,-2487,-2472,-2461,-2452,-2442,-2431,
--2420,-2413,-2411,-2414,-2416,-2412,-2399,-2381,-2362,-2349,-2347,-2353,-2361,-2365,-2360,-2347,-2331,-2320,-2320,-2331,-2349,
--2371,-2391,-2406,-2415,-2418,-2414,-2405,-2391,-2379,-2375,-2382,-2401,-2427,-2452,-2469,-2477,-2479,-2481,-2487,-2497,-2507,
--2510,-2506,-2499,-2498,-2508,-2529,-2552,-2567,-2567,-2559,-2564,-2602,-2686,-2810,-2943,-3046,-3082,-3039,-2932,-2802,-2694,
--2643,-2656,-2717,-2795,-2861,-2898,-2908,-2905,-2905,-2919,-2949,-2990,-3034,-3078,-3120,-3161,-3200,-3236,-3268,-3292,-3313,
--3334,-3357,-3385,-3413,-3438,-3454,-3463,-3468,-3475,-3488,-3509,-3533,-3559,-3582,-3602,-3621,-3640,-3660,-3680,-3697,-3709,
--3718,-3725,-3734,-3747,-3767,-3789,-3812,-3832,-3847,-3858,-3865,-3870,-3875,-3880,-3886,-3893,-3901,-3907,-3912,-3913,-3912,
--3909,-3906,-3904,-3905,-3906,-3907,-3905,-3903,-3900,-3899,-3900,-3903,-3908,-3912,-3917,-3920,-3924,-3929,-3935,-3941,-3947,
--3950,-3951,-3950,-3949,-3948,-3947,-3946,-3944,-3940,-3934,-3926,-3918,-3910,-3904,-3899,-3895,-3891,-3889,-3887,-3885,-3883,
--3880,-3876,-3873,-3869,-3865,-3860,-3855,-3849,-3840,-3829,-3816,-3801,-3785,-3768,-3752,-3736,-3721,-3706,-3691,-3677,-3663,
--3651,-3641,-3633,-3625,-3618,-3611,-3601,-3590,-3576,-3561,-3545,-3528,-3513,-3499,-3485,-3471,-3457,-3442,-3426,-3409,-3390,
--3372,-3354,-3337,-3321,-3306,-3290,-3274,-3258,-3240,-3223,-3206,-3190,-3174,-3160,-3146,-3133,-3119,-3106,-3092,-3078,-3062,
--3044,-3026,-3008,-2990,-2974,-2961,-2949,-2938,-2926,-2912,-2896,-2878,-2860,-2842,-2825,-2810,-2797,-2783,-2769,-2754,-2740,
--2726,-2715,-2706,-2699,-2695,-2692,-2688,-2682,-2673,-2662,-2649,-2636,-2623,-2611,-2601,-2592,-2584,-2574,-2562,-2549,-2535,
--2522,-2510,-2500,-2493,-2488,-2483,-2477,-2472,-2466,-2462,-2460,-2459,-2458,-2457,-2455,-2451,-2446,-2442,-2439,-2438,-2438,
--2439,-2439,-2437,-2433,-2427,-2419,-2409,-2396,-2380,-2360,-2338,-2315,-2292,-2270,-2250,-2233,-2218,-2204,-2190,-2178,-2167,
--2158,-2151,-2145,-2140,-2136,-2134,-2132,-2132,-2132,-2133,-2133,-2132,-2129,-2125,-2121,-2116,-2112,-2107,-2103,-2098,-2093,
--2087,-2080,-2073,-2065,-2058,-2051,-2044,-2038,-2032,-2026,-2020,-2014,-2009,-2004,-2000,-1997,-1993,-1987,-1978,-1967,-1953,
--1939,-1927,-1916,-1907,-1900,-1893,-1886,-1879,-1870,-1861,-1853,-1844,-1836,-1829,-1822,-1817,-1814,-1813,-1816,-1821,-1829,
--1839,-1848,-1857,-1863,-1864,-1860,-1850,-1835,-1817,-1798,-1780,-1763,-1750,-1738,-1728,-1715,-1700,-1680,-1658,-1634,-1614,
--1598,-1589,-1587,-1590,-1596,-1603,-1609,-1615,-1621,-1626,-1630,-1632,-1631,-1625,-1617,-1608,-1601,-1598,-1600,-1604,-1609,
--1612,-1610,-1603,-1594,-1583,-1573,-1565,-1559,-1555,-1553,-1553,-1553,-1553,-1552,-1549,-1543,-1536,-1529,-1522,-1519,-1519,
--1521,-1523,-1524,-1523,-1520,-1514,-1507,-1500,-1490,-1478,-1462,-1443,-1421,-1398,-1377,-1358,-1344,-1333,-1324,-1315,-1305,
--1294,-1281,-1269,-1258,-1247,-1239,-1231,-1223,-1217,-1211,-1205,-1199,-1193,-1185,-1176,-1165,-1153,-1141,-1131,-1122,-1117,
--1113,-1112,-1112,-1114,-1117,-1119,-1120,-1117,-1109,-1096,-1079,-1059,-1036,-1012,-989,-968,-951,-939,-932,-929,-928,
--923,-913,-896,-873,-847,-824,-804,-789,-776,-762,-747,-730,-713,-698,-686,-676,-666,-651,-631,-605,-576,
--547,-519,-495,-470,-445,-416,-385,-353,-324,-300,-280,-265,-252,-237,-219,-197,-172,-145,-119,-93,-69,
--46,-24,-3,18,40,62,86,111,136,162,187,213,239,265,292,319,345,368,389,410,431,
-455,484,514,545,572,593,607,616,623,631,645,663,684,702,715,720,717,711,708,711,727,
-755,797,852,920,1001,1092,1190,1286,1369,1429,1458,1455,1426,1385,1349,1328,1329,1350,1383,1416,1442,
-1459,1468,1476,1488,1505,1528,1551,1572,1588,1601,1614,1630,1651,1678,1709,1741,1771,1798,1823,1844,1864,
-1880,1894,1905,1914,1923,1934,1949,1965,1980,1989,1991,1984,1970,1951,1930,1909,1888,1865,1841,1818,1799,
-1790,1793,1808,1832,1857,1879,1892,1892,1880,1856,1825,1793,1764,1743,1736,1742,1758,1778,1795,1806,1809,
-1807,1808,1816,1835,1859,1883,1898,1900,1888,1868,1847,1832,1826,1829,1835,1840,1841,1838,1833,1826,1818,
-1810,1800,1788,1776,1767,1763,1767,1778,1793,1809,1823,1835,1845,1856,1871,1888,1907,1923,1934,1937,1933,
-1927,1921,1923,1932,1950,1972,1995,2014,2026,2032,2034,2035,2040,2049,2062,2077,2094,2110,2125,2139,2153,
-2168,2185,2203,2221,2239,2255,2268,2276,2279,2279,2276,2273,2272,2272,2271,2268,2259,2246,2229,2211,2193,
-2176,2157,2131,2092,2033,1945,1821,1657,1454,1226,993,786,638,577,615,745,940,1164,1379,1558,1688,
-1774,1827,1864,1895,1925,1952,1974,1989,1996,1999,2001,2002,2002,2000,1996,1990,1986,1984,1987,1995,2005,
-2017,2031,2046,2063,2081,2098,2111,2119,2121,2118,2114,2111,2113,2117,2123,2129,2133,2136,2141,2149,2160,
-2172,2183,2191,2195,2199,2207,2219,2236,2256,2274,2289,2300,2310,2324,2344,2370,2397,2420,2435,2441,2441,
-2439,2440,2446,2455,2465,2473,2477,2478,2479,2481,2483,2483,2480,2471,2457,2441,2424,2408,2395,2383,2374,
-2365,2357,2350,2344,2339,2332,2325,2314,2262,2250,2237,2223,2210,2199,2191,2188,2191,2199,2208,2216,2219,
-2214,2202,2184,2164,2143,2124,2108,2093,2080,2068,2056,2044,2031,2017,2002,1987,1972,1959,1950,1944,1943,
-1945,1951,1959,1969,1979,1990,2000,2008,2013,2017,2018,2020,2025,2033,2047,2065,2087,2111,2134,2154,2172,
-2188,2206,2230,2260,2298,2339,2379,2415,2443,2464,2481,2498,2517,2541,2568,2596,2622,2643,2661,2675,2689,
-2705,2723,2742,2760,2776,2788,2797,2804,2813,2826,2845,2867,2888,2904,2912,2911,2906,2900,2898,2903,2914,
-2926,2937,2944,2946,2947,2948,2950,2955,2961,2969,2979,2992,3010,3031,3056,3081,3104,3124,3142,3158,3176,
-3197,3220,3244,3270,3296,3322,3346,3368,3384,3395,3400,3402,3403,3409,3419,3434,3452,3472,3491,3509,3527,
-3545,3565,3586,3607,3627,3646,3664,3683,3703,3726,3750,3774,3797,3819,3838,3852,3862,3868,3873,3877,3883,
-3890,3898,3904,3907,3906,3902,3898,3897,3899,3904,3910,3914,3915,3914,3912,3911,3914,3918,3922,3925,3926,
-3926,3926,3926,3925,3923,3919,3912,3903,3894,3887,3881,3876,3869,3859,3846,3830,3814,3800,3787,3776,3765,
-3755,3745,3737,3729,3720,3708,3691,3672,3651,3633,3621,3616,3617,3622,3626,3628,3629,3630,3631,3633,3632,
-3628,3618,3604,3588,3575,3566,3561,3560,3559,3558,3555,3552,3549,3546,3541,3534,3523,3510,3495,3482,3472,
-3463,3457,3453,3451,3451,3454,3458,3461,3461,3458,3454,3452,3456,3467,3483,3500,3514,3523,3525,3524,3520,
-3513,3503,3488,3470,3453,3442,3440,3449,3464,3475,3477,3466,3445,3420,3401,3393,3397,3408,3420,3428,3427,
-3418,3401,3377,3347,3311,3273,3235,3202,3176,3157,3142,3128,3113,3096,3081,3070,3063,3056,3044,3023,2991,
-2953,2915,2886,2868,2859,2853,2843,2824,2796,2762,2725,2689,2650,2604,2546,2475,2395,2311,2231,2160,2097,
-2042,1991,1943,1899,1863,1838,1823,1814,1805,1792,1770,1740,1705,1672,1645,1627,1617,1612,1607,1597,1579,
-1554,1522,1487,1452,1420,1393,1369,1347,1325,1301,1274,1246,1217,1187,1158,1129,1099,1068,1038,1007,978,
-951,924,898,870,841,809,775,738,701,663,625,589,555,524,494,464,433,398,362,325,290,
-255,222,188,152,111,68,25,-13,-47,-74,-96,-116,-138,-162,-190,-220,-251,-284,-317,-351,-385,
--420,-454,-487,-518,-548,-577,-605,-632,-659,-684,-709,-734,-762,-791,-823,-856,-887,-916,-941,-965,-990,
--1017,-1047,-1081,-1116,-1150,-1183,-1214,-1243,-1272,-1302,-1333,-1364,-1396,-1428,-1460,-1491,-1522,-1551,-1579,-1605,-1630,
--1653,-1678,-1705,-1733,-1762,-1791,-1817,-1841,-1862,-1882,-1904,-1927,-1951,-1976,-2000,-2023,-2044,-2064,-2085,-2105,-2125,
--2145,-2164,-2182,-2200,-2219,-2238,-2257,-2275,-2293,-2309,-2325,-2342,-2359,-2376,-2392,-2407,-2421,-2435,-2450,-2468,-2487,
--2506,-2522,-2537,-2549,-2560,-2572,-2586,-2601,-2615,-2626,-2635,-2642,-2648,-2655,-2663,-2671,-2677,-2682,-2685,-2689,-2693,
--2699,-2706,-2713,-2717,-2720,-2721,-2723,-2725,-2727,-2729,-2729,-2727,-2724,-2721,-2719,-2718,-2716,-2714,-2711,-2709,-2707,
--2707,-2709,-2711,-2711,-2711,-2709,-2707,-2708,-2710,-2712,-2712,-2708,-2701,-2692,-2682,-2673,-2668,-2666,-2666,-2668,-2669,
--2669,-2665,-2654,-2636,-2612,-2584,-2558,-2537,-2522,-2512,-2503,-2493,-2480,-2468,-2460,-2458,-2459,-2461,-2458,-2446,-2428,
--2410,-2396,-2393,-2398,-2407,-2413,-2410,-2398,-2382,-2368,-2360,-2363,-2375,-2393,-2413,-2433,-2448,-2456,-2455,-2445,-2429,
--2415,-2408,-2413,-2431,-2455,-2479,-2496,-2505,-2509,-2513,-2522,-2534,-2544,-2548,-2546,-2542,-2544,-2556,-2578,-2599,-2610,
--2609,-2604,-2617,-2670,-2771,-2907,-3043,-3137,-3155,-3088,-2960,-2818,-2710,-2669,-2700,-2777,-2864,-2929,-2957,-2954,-2939,
--2933,-2947,-2981,-3026,-3071,-3113,-3151,-3190,-3233,-3278,-3320,-3354,-3379,-3398,-3415,-3436,-3462,-3489,-3514,-3533,-3547,
--3559,-3574,-3594,-3619,-3645,-3668,-3688,-3704,-3719,-3734,-3750,-3766,-3780,-3792,-3802,-3812,-3827,-3845,-3866,-3887,-3905,
--3919,-3928,-3934,-3940,-3946,-3954,-3961,-3968,-3973,-3976,-3977,-3979,-3980,-3982,-3984,-3985,-3984,-3981,-3978,-3974,-3972,
--3972,-3974,-3978,-3982,-3986,-3990,-3994,-3999,-4006,-4014,-4020,-4024,-4025,-4023,-4019,-4015,-4012,-4011,-4011,-4010,-4008,
--4003,-3997,-3988,-3979,-3970,-3962,-3955,-3950,-3946,-3944,-3944,-3945,-3945,-3944,-3941,-3937,-3932,-3927,-3921,-3916,-3910,
--3902,-3891,-3879,-3865,-3850,-3835,-3819,-3804,-3789,-3774,-3758,-3742,-3726,-3710,-3694,-3680,-3668,-3658,-3650,-3644,-3638,
--3633,-3625,-3615,-3601,-3585,-3567,-3549,-3531,-3514,-3498,-3482,-3466,-3448,-3429,-3409,-3390,-3372,-3355,-3340,-3325,-3310,
--3294,-3277,-3259,-3242,-3226,-3210,-3196,-3183,-3170,-3157,-3142,-3126,-3109,-3090,-3070,-3050,-3031,-3014,-3000,-2988,-2979,
--2970,-2960,-2948,-2934,-2917,-2900,-2882,-2865,-2848,-2833,-2817,-2802,-2786,-2771,-2757,-2745,-2736,-2728,-2722,-2716,-2708,
--2700,-2690,-2680,-2670,-2661,-2652,-2644,-2636,-2628,-2619,-2609,-2599,-2589,-2579,-2570,-2562,-2554,-2546,-2538,-2529,-2521,
--2513,-2507,-2504,-2504,-2506,-2508,-2508,-2506,-2501,-2495,-2489,-2485,-2484,-2485,-2487,-2489,-2490,-2490,-2488,-2484,-2478,
--2468,-2455,-2436,-2414,-2388,-2363,-2339,-2317,-2298,-2282,-2267,-2252,-2239,-2227,-2218,-2210,-2203,-2198,-2194,-2190,-2187,
--2185,-2184,-2183,-2182,-2179,-2176,-2171,-2165,-2160,-2155,-2150,-2144,-2138,-2131,-2123,-2115,-2106,-2099,-2091,-2084,-2077,
--2068,-2060,-2050,-2042,-2035,-2029,-2025,-2021,-2018,-2014,-2009,-2003,-1996,-1989,-1981,-1972,-1963,-1953,-1942,-1929,-1915,
--1901,-1887,-1873,-1863,-1854,-1848,-1845,-1842,-1840,-1837,-1835,-1834,-1836,-1842,-1850,-1860,-1870,-1877,-1880,-1880,-1875,
--1868,-1859,-1850,-1842,-1835,-1829,-1824,-1817,-1809,-1797,-1782,-1763,-1743,-1723,-1706,-1694,-1686,-1683,-1685,-1691,-1700,
--1712,-1725,-1737,-1744,-1746,-1740,-1729,-1714,-1699,-1687,-1679,-1674,-1672,-1669,-1664,-1657,-1649,-1640,-1631,-1623,-1617,
--1613,-1609,-1607,-1605,-1604,-1601,-1597,-1590,-1581,-1572,-1565,-1561,-1559,-1559,-1560,-1559,-1557,-1552,-1545,-1536,-1526,
--1513,-1498,-1480,-1460,-1439,-1418,-1398,-1381,-1367,-1356,-1346,-1337,-1328,-1318,-1308,-1298,-1288,-1278,-1268,-1259,-1250,
--1241,-1233,-1226,-1220,-1215,-1210,-1204,-1195,-1185,-1174,-1162,-1151,-1142,-1134,-1129,-1126,-1123,-1120,-1115,-1108,-1099,
--1088,-1075,-1059,-1041,-1022,-1000,-978,-957,-939,-927,-921,-919,-920,-919,-913,-901,-883,-861,-838,-817,-797,
--779,-762,-743,-724,-705,-690,-677,-667,-658,-648,-635,-618,-599,-578,-555,-531,-504,-473,-439,-402,-367,
--334,-308,-288,-273,-260,-245,-228,-206,-180,-153,-128,-104,-85,-68,-51,-34,-14,8,34,61,87,
-112,136,159,183,209,237,265,292,316,338,357,377,398,424,455,490,526,559,586,607,621,
-633,645,662,685,714,746,776,799,814,819,818,813,808,808,814,830,858,902,963,1040,1129,
-1218,1296,1351,1379,1380,1363,1341,1325,1324,1339,1366,1398,1429,1456,1479,1501,1525,1551,1577,1600,1618,
-1632,1643,1656,1673,1696,1723,1752,1780,1807,1832,1858,1885,1912,1936,1956,1968,1972,1971,1966,1963,1963,
-1967,1975,1984,1992,1997,1997,1989,1973,1948,1915,1879,1847,1823,1815,1822,1842,1869,1896,1916,1926,1925,
-1914,1895,1872,1847,1825,1807,1797,1794,1797,1804,1809,1812,1812,1812,1816,1827,1846,1868,1888,1899,1900,
-1890,1875,1859,1848,1844,1846,1850,1854,1856,1855,1853,1849,1843,1835,1825,1814,1803,1794,1791,1793,1802,
-1814,1827,1839,1851,1862,1873,1887,1904,1922,1939,1953,1961,1964,1962,1960,1962,1969,1983,2002,2021,2036,
-2045,2049,2050,2054,2061,2073,2088,2104,2117,2128,2138,2149,2162,2178,2196,2214,2231,2246,2260,2274,2288,
-2300,2309,2314,2316,2314,2310,2307,2304,2302,2298,2290,2278,2259,2233,2198,2157,2107,2049,1977,1886,1767,
-1614,1427,1217,1005,824,704,669,727,866,1057,1267,1460,1616,1728,1802,1850,1884,1912,1935,1953,1964,
-1969,1971,1975,1982,1991,1999,2003,2002,1997,1990,1987,1988,1995,2006,2020,2034,2049,2064,2079,2092,2101,
-2107,2108,2106,2105,2106,2109,2115,2121,2125,2129,2132,2137,2143,2151,2159,2167,2173,2179,2188,2202,2220,
-2239,2258,2273,2284,2295,2309,2329,2356,2385,2410,2427,2431,2427,2419,2413,2414,2423,2436,2449,2457,2460,
-2457,2450,2441,2431,2418,2403,2386,2367,2348,2332,2319,2311,2306,2304,2302,2300,2296,2290,2283,2273,2262,
-2206,2196,2188,2181,2173,2166,2160,2157,2156,2158,2162,2165,2166,2163,2156,2145,2131,2116,2100,2084,2067,
-2050,2034,2016,1999,1982,1965,1951,1939,1930,1925,1923,1922,1923,1925,1928,1934,1942,1951,1960,1967,1971,
-1974,1975,1978,1983,1992,2004,2020,2039,2059,2080,2100,2119,2136,2154,2173,2197,2226,2262,2301,2340,2373,
-2399,2419,2436,2453,2474,2500,2530,2558,2583,2603,2619,2635,2652,2672,2693,2714,2729,2739,2744,2749,2757,
-2773,2795,2819,2841,2855,2858,2852,2844,2839,2842,2853,2870,2887,2900,2906,2906,2904,2903,2907,2913,2922,
-2930,2938,2946,2959,2978,3002,3031,3059,3084,3104,3121,3135,3152,3171,3194,3220,3246,3271,3294,3314,3329,
-3341,3350,3355,3361,3367,3377,3390,3406,3424,3441,3457,3473,3490,3508,3526,3544,3562,3579,3596,3615,3635,
-3658,3682,3707,3731,3753,3773,3791,3805,3816,3824,3831,3836,3843,3850,3857,3863,3864,3861,3856,3849,3846,
-3845,3849,3854,3860,3864,3867,3869,3872,3877,3881,3884,3886,3886,3886,3886,3886,3885,3882,3875,3866,3856,
-3847,3841,3837,3833,3825,3814,3798,3781,3765,3752,3742,3734,3726,3718,3708,3699,3689,3679,3665,3648,3627,
-3606,3588,3577,3576,3582,3591,3599,3604,3604,3602,3600,3599,3597,3593,3585,3573,3559,3547,3537,3532,3531,
-3531,3531,3530,3527,3524,3519,3513,3505,3494,3482,3471,3461,3454,3450,3447,3445,3442,3440,3439,3439,3439,
-3439,3438,3438,3438,3440,3442,3442,3438,3430,3418,3404,3390,3377,3364,3346,3324,3297,3271,3254,3252,3265,
-3289,3316,3337,3345,3340,3329,3318,3314,3318,3327,3336,3340,3337,3328,3312,3293,3269,3240,3210,3178,3151,
-3130,3116,3107,3100,3091,3079,3065,3050,3036,3023,3007,2986,2960,2930,2901,2879,2866,2859,2853,2842,2821,
-2791,2755,2720,2688,2657,2625,2585,2534,2472,2402,2330,2259,2192,2127,2062,1997,1934,1877,1832,1800,1780,
-1768,1757,1742,1720,1692,1664,1639,1622,1614,1612,1611,1603,1585,1556,1518,1476,1434,1398,1370,1347,1326,
-1304,1278,1249,1216,1183,1152,1124,1098,1073,1049,1024,1000,975,950,924,898,870,841,811,779,746,
-710,673,633,593,555,518,484,452,418,382,343,302,262,222,185,149,112,74,34,-4,-38,
--68,-91,-110,-128,-148,-172,-201,-233,-268,-302,-335,-369,-402,-436,-468,-500,-530,-558,-584,-610,-635,
--659,-684,-710,-737,-766,-797,-828,-860,-890,-918,-944,-971,-998,-1028,-1061,-1095,-1128,-1159,-1188,-1215,-1243,
--1272,-1304,-1339,-1373,-1408,-1440,-1471,-1501,-1530,-1557,-1583,-1608,-1631,-1654,-1678,-1705,-1734,-1764,-1794,-1820,-1844,
--1866,-1887,-1909,-1933,-1959,-1985,-2009,-2031,-2051,-2070,-2089,-2110,-2131,-2152,-2173,-2192,-2210,-2229,-2248,-2268,-2287,
--2305,-2323,-2339,-2356,-2373,-2390,-2406,-2420,-2434,-2447,-2460,-2476,-2494,-2514,-2532,-2550,-2565,-2578,-2591,-2603,-2616,
--2628,-2638,-2648,-2656,-2665,-2674,-2683,-2692,-2701,-2708,-2713,-2718,-2724,-2731,-2738,-2744,-2748,-2752,-2754,-2756,-2759,
--2761,-2763,-2764,-2763,-2762,-2761,-2760,-2760,-2759,-2758,-2755,-2751,-2748,-2746,-2746,-2747,-2748,-2748,-2749,-2749,-2749,
--2750,-2751,-2750,-2747,-2740,-2732,-2722,-2712,-2704,-2700,-2698,-2701,-2706,-2710,-2710,-2702,-2685,-2660,-2632,-2604,-2582,
--2567,-2556,-2548,-2537,-2525,-2514,-2506,-2503,-2505,-2508,-2506,-2496,-2480,-2461,-2446,-2440,-2442,-2449,-2455,-2455,-2448,
--2435,-2421,-2411,-2407,-2412,-2424,-2442,-2462,-2480,-2491,-2492,-2482,-2465,-2447,-2437,-2438,-2453,-2475,-2498,-2516,-2527,
--2535,-2543,-2554,-2567,-2578,-2583,-2583,-2582,-2587,-2602,-2622,-2640,-2646,-2643,-2641,-2663,-2727,-2838,-2979,-3112,-3193,
--3192,-3107,-2966,-2821,-2720,-2694,-2740,-2830,-2924,-2988,-3010,-3000,-2982,-2978,-2999,-3041,-3091,-3136,-3171,-3200,-3231,
--3272,-3321,-3372,-3416,-3447,-3465,-3477,-3490,-3510,-3537,-3567,-3594,-3617,-3634,-3650,-3667,-3687,-3709,-3730,-3749,-3765,
--3780,-3797,-3815,-3835,-3855,-3872,-3888,-3903,-3918,-3934,-3951,-3966,-3978,-3988,-3994,-4001,-4009,-4018,-4027,-4035,-4040,
--4041,-4041,-4041,-4045,-4051,-4059,-4065,-4067,-4065,-4058,-4051,-4045,-4043,-4045,-4050,-4056,-4060,-4064,-4067,-4071,-4077,
--4084,-4092,-4097,-4099,-4097,-4093,-4089,-4085,-4084,-4083,-4082,-4080,-4075,-4069,-4061,-4052,-4043,-4034,-4024,-4016,-4009,
--4004,-4002,-4002,-4003,-4005,-4005,-4003,-4000,-3995,-3989,-3983,-3977,-3970,-3961,-3952,-3941,-3929,-3917,-3903,-3888,-3872,
--3854,-3836,-3819,-3801,-3784,-3767,-3750,-3733,-3719,-3706,-3697,-3691,-3688,-3686,-3682,-3675,-3663,-3646,-3627,-3606,-3586,
--3567,-3550,-3534,-3517,-3499,-3479,-3459,-3438,-3419,-3402,-3386,-3372,-3358,-3343,-3327,-3311,-3294,-3278,-3263,-3249,-3235,
--3222,-3207,-3191,-3174,-3155,-3136,-3117,-3098,-3079,-3061,-3045,-3030,-3018,-3008,-2999,-2990,-2979,-2966,-2951,-2934,-2917,
--2901,-2885,-2869,-2854,-2838,-2822,-2806,-2792,-2780,-2770,-2760,-2751,-2742,-2732,-2723,-2714,-2706,-2698,-2690,-2683,-2676,
--2668,-2661,-2653,-2646,-2638,-2631,-2623,-2616,-2609,-2601,-2593,-2585,-2575,-2567,-2560,-2555,-2553,-2553,-2554,-2554,-2552,
--2548,-2542,-2536,-2532,-2531,-2532,-2534,-2535,-2536,-2536,-2536,-2537,-2536,-2534,-2528,-2516,-2499,-2478,-2456,-2434,-2415,
--2398,-2383,-2368,-2353,-2338,-2322,-2308,-2296,-2285,-2275,-2266,-2257,-2248,-2241,-2236,-2233,-2230,-2227,-2223,-2219,-2213,
--2209,-2205,-2201,-2198,-2193,-2186,-2177,-2168,-2158,-2149,-2139,-2130,-2120,-2110,-2098,-2088,-2078,-2069,-2061,-2055,-2048,
--2042,-2037,-2032,-2030,-2027,-2025,-2021,-2016,-2008,-1997,-1986,-1973,-1959,-1946,-1933,-1921,-1912,-1905,-1903,-1902,-1902,
--1899,-1894,-1885,-1875,-1865,-1857,-1853,-1854,-1856,-1861,-1865,-1869,-1873,-1876,-1878,-1880,-1880,-1879,-1877,-1875,-1874,
--1874,-1874,-1871,-1865,-1855,-1842,-1827,-1812,-1800,-1791,-1787,-1788,-1791,-1798,-1805,-1812,-1817,-1819,-1816,-1810,-1802,
--1793,-1785,-1778,-1771,-1765,-1757,-1748,-1737,-1726,-1714,-1703,-1693,-1684,-1676,-1669,-1664,-1659,-1655,-1650,-1644,-1636,
--1628,-1620,-1614,-1610,-1608,-1607,-1606,-1604,-1600,-1595,-1587,-1576,-1563,-1547,-1529,-1509,-1488,-1469,-1450,-1433,-1418,
--1402,-1387,-1372,-1358,-1347,-1338,-1332,-1328,-1323,-1318,-1310,-1300,-1289,-1277,-1266,-1256,-1249,-1244,-1241,-1237,-1231,
--1223,-1212,-1199,-1186,-1173,-1161,-1152,-1143,-1133,-1122,-1110,-1097,-1083,-1071,-1059,-1048,-1036,-1021,-1002,-981,-958,
--937,-919,-908,-902,-900,-899,-895,-887,-874,-858,-839,-819,-799,-779,-760,-741,-722,-705,-689,-675,-663,
--652,-642,-631,-620,-607,-592,-573,-550,-523,-491,-456,-420,-385,-354,-328,-307,-290,-274,-257,-239,-217,
--193,-169,-146,-126,-109,-95,-81,-64,-43,-18,9,39,66,91,114,136,158,183,210,239,267,
-292,316,337,358,381,407,436,469,503,538,570,599,623,644,663,683,706,734,768,803,839,
-871,898,918,933,943,949,950,948,946,950,965,998,1049,1117,1191,1262,1317,1351,1363,1361,1352,
-1347,1350,1365,1388,1417,1448,1480,1512,1544,1574,1603,1628,1650,1668,1686,1706,1729,1755,1782,1807,1831,
-1851,1871,1892,1916,1941,1964,1984,1996,1999,1994,1984,1973,1965,1961,1962,1969,1979,1989,1996,1997,1989,
-1973,1949,1922,1899,1883,1877,1882,1894,1909,1921,1928,1930,1926,1920,1913,1905,1898,1890,1883,1876,1871,
-1866,1862,1858,1855,1854,1856,1863,1875,1890,1905,1914,1917,1912,1903,1893,1886,1883,1884,1888,1892,1895,
-1896,1894,1891,1886,1879,1869,1858,1846,1835,1826,1822,1821,1824,1829,1835,1842,1849,1856,1865,1875,1888,
-1903,1920,1937,1952,1964,1973,1978,1984,1991,2001,2013,2025,2035,2043,2049,2055,2064,2076,2090,2105,2118,
-2127,2135,2144,2156,2172,2190,2208,2223,2235,2245,2257,2274,2295,2318,2339,2353,2359,2357,2350,2341,2332,
-2324,2315,2304,2291,2274,2252,2225,2189,2143,2086,2016,1932,1830,1705,1555,1381,1195,1016,872,790,788,
-868,1015,1200,1391,1559,1688,1776,1832,1868,1894,1917,1935,1948,1955,1960,1964,1972,1983,1995,2003,2003,
-1996,1985,1974,1969,1971,1979,1992,2006,2020,2034,2048,2063,2075,2085,2091,2094,2095,2098,2103,2110,2118,
-2124,2126,2126,2124,2123,2127,2134,2143,2154,2164,2175,2186,2198,2212,2226,2240,2252,2266,2283,2305,2331,
-2359,2382,2395,2397,2390,2379,2371,2372,2383,2399,2415,2425,2425,2416,2400,2382,2364,2348,2335,2322,2309,
-2295,2284,2275,2269,2267,2265,2263,2259,2251,2241,2228,2216,2206,2156,2151,2148,2146,2143,2141,2137,2133,
-2130,2126,2121,2115,2109,2102,2094,2085,2075,2064,2052,2038,2023,2007,1991,1975,1959,1945,1934,1927,1926,
-1928,1933,1937,1939,1937,1933,1928,1926,1927,1931,1937,1943,1947,1950,1952,1957,1965,1976,1989,2003,2018,
-2034,2051,2069,2089,2110,2132,2156,2181,2211,2243,2277,2309,2336,2357,2373,2388,2407,2433,2465,2501,2535,
-2562,2582,2595,2608,2624,2645,2667,2687,2700,2706,2707,2710,2721,2741,2768,2795,2813,2817,2808,2793,2780,
-2778,2790,2813,2839,2861,2872,2873,2870,2867,2871,2881,2895,2907,2915,2920,2925,2935,2954,2981,3014,3045,
-3071,3090,3104,3117,3132,3152,3177,3204,3231,3254,3272,3286,3296,3303,3310,3317,3325,3336,3349,3363,3379,
-3396,3412,3428,3445,3461,3478,3494,3509,3522,3535,3549,3566,3587,3610,3635,3659,3681,3702,3720,3736,3751,
-3764,3774,3784,3792,3800,3808,3816,3822,3825,3824,3820,3815,3810,3808,3809,3811,3814,3817,3819,3823,3828,
-3833,3839,3843,3846,3847,3849,3850,3851,3851,3848,3841,3831,3821,3812,3806,3801,3795,3786,3772,3755,3738,
-3724,3714,3707,3702,3694,3683,3670,3655,3641,3628,3615,3600,3584,3568,3556,3549,3550,3556,3565,3572,3574,
-3573,3569,3566,3565,3564,3562,3557,3548,3536,3524,3515,3509,3507,3506,3506,3505,3503,3499,3493,3486,3478,
-3468,3458,3449,3443,3440,3438,3437,3433,3428,3422,3415,3411,3410,3410,3413,3414,3413,3407,3395,3376,3351,
-3322,3294,3271,3254,3243,3234,3220,3197,3167,3135,3109,3099,3107,3130,3161,3190,3208,3214,3209,3201,3195,
-3194,3196,3199,3200,3198,3193,3187,3179,3169,3154,3136,3115,3095,3079,3070,3067,3066,3064,3058,3048,3035,
-3022,3007,2991,2970,2944,2915,2886,2863,2848,2840,2835,2827,2811,2784,2751,2714,2681,2651,2624,2597,2564,
-2523,2475,2420,2362,2301,2236,2165,2090,2012,1936,1867,1812,1771,1742,1720,1701,1679,1654,1629,1608,1596,
-1592,1596,1599,1594,1577,1545,1502,1452,1406,1366,1337,1316,1298,1278,1254,1223,1189,1154,1121,1093,1067,
-1045,1025,1005,986,965,943,918,891,861,829,797,766,734,701,666,629,590,551,513,478,443,
-408,369,327,281,235,190,149,111,76,42,7,-25,-55,-82,-103,-122,-140,-161,-185,-214,-247,
--281,-315,-349,-382,-414,-445,-476,-506,-535,-562,-588,-614,-640,-666,-692,-720,-747,-776,-805,-836,-865,
--893,-920,-946,-973,-1001,-1032,-1066,-1101,-1134,-1165,-1193,-1219,-1246,-1275,-1307,-1341,-1376,-1410,-1442,-1472,-1501,
--1530,-1558,-1585,-1610,-1634,-1658,-1682,-1708,-1737,-1767,-1796,-1822,-1846,-1867,-1889,-1912,-1937,-1963,-1989,-2013,-2034,
--2053,-2072,-2092,-2113,-2136,-2158,-2179,-2199,-2217,-2236,-2256,-2276,-2297,-2317,-2336,-2353,-2370,-2387,-2403,-2420,-2435,
--2449,-2463,-2476,-2491,-2507,-2524,-2542,-2559,-2575,-2591,-2605,-2619,-2633,-2645,-2656,-2666,-2675,-2683,-2693,-2704,-2715,
--2726,-2736,-2746,-2753,-2760,-2766,-2771,-2774,-2777,-2779,-2782,-2784,-2788,-2791,-2794,-2795,-2795,-2794,-2794,-2794,-2795,
--2795,-2794,-2792,-2789,-2786,-2785,-2784,-2785,-2786,-2787,-2787,-2787,-2786,-2786,-2785,-2785,-2783,-2779,-2773,-2764,-2753,
--2743,-2735,-2732,-2734,-2741,-2748,-2753,-2749,-2734,-2711,-2682,-2654,-2631,-2616,-2605,-2597,-2588,-2577,-2565,-2557,-2554,
--2555,-2558,-2557,-2550,-2536,-2518,-2502,-2492,-2489,-2492,-2496,-2499,-2497,-2491,-2481,-2470,-2462,-2458,-2462,-2472,-2488,
--2504,-2517,-2521,-2514,-2498,-2480,-2468,-2467,-2477,-2497,-2518,-2537,-2552,-2563,-2575,-2588,-2601,-2611,-2616,-2618,-2620,
--2629,-2645,-2664,-2677,-2679,-2673,-2671,-2698,-2769,-2887,-3032,-3164,-3241,-3232,-3138,-2991,-2841,-2739,-2714,-2762,-2854,
--2950,-3016,-3041,-3036,-3025,-3031,-3063,-3115,-3171,-3218,-3250,-3271,-3294,-3327,-3373,-3424,-3471,-3504,-3524,-3533,-3543,
--3560,-3587,-3619,-3652,-3679,-3700,-3714,-3727,-3741,-3757,-3776,-3795,-3814,-3833,-3855,-3880,-3906,-3931,-3954,-3974,-3990,
--4004,-4017,-4028,-4038,-4045,-4052,-4058,-4065,-4075,-4086,-4097,-4104,-4106,-4104,-4100,-4100,-4104,-4113,-4124,-4133,-4138,
--4136,-4130,-4123,-4119,-4118,-4122,-4127,-4132,-4135,-4136,-4138,-4140,-4145,-4152,-4157,-4161,-4161,-4159,-4157,-4156,-4156,
--4156,-4156,-4154,-4149,-4141,-4133,-4125,-4118,-4110,-4103,-4094,-4085,-4077,-4070,-4066,-4064,-4064,-4063,-4061,-4059,-4055,
--4051,-4047,-4042,-4036,-4028,-4020,-4011,-4002,-3993,-3984,-3972,-3957,-3940,-3920,-3899,-3879,-3860,-3844,-3829,-3814,-3798,
--3782,-3768,-3756,-3746,-3739,-3733,-3727,-3718,-3706,-3691,-3674,-3656,-3639,-3622,-3606,-3590,-3572,-3553,-3532,-3511,-3489,
--3469,-3450,-3433,-3418,-3404,-3390,-3376,-3360,-3345,-3330,-3315,-3301,-3287,-3272,-3256,-3238,-3218,-3199,-3180,-3163,-3146,
--3130,-3114,-3097,-3081,-3065,-3052,-3041,-3031,-3021,-3010,-2997,-2983,-2967,-2951,-2936,-2921,-2906,-2891,-2876,-2860,-2845,
--2832,-2819,-2808,-2798,-2787,-2776,-2765,-2754,-2744,-2736,-2728,-2721,-2715,-2709,-2703,-2697,-2690,-2682,-2674,-2665,-2657,
--2650,-2644,-2639,-2634,-2629,-2623,-2617,-2612,-2608,-2605,-2603,-2601,-2597,-2592,-2586,-2581,-2577,-2576,-2576,-2576,-2576,
--2575,-2573,-2572,-2572,-2573,-2574,-2572,-2567,-2557,-2545,-2532,-2520,-2510,-2500,-2491,-2480,-2466,-2450,-2433,-2416,-2400,
--2384,-2369,-2354,-2339,-2324,-2312,-2302,-2294,-2288,-2282,-2275,-2268,-2260,-2254,-2250,-2246,-2243,-2239,-2234,-2226,-2217,
--2208,-2198,-2189,-2179,-2169,-2158,-2147,-2136,-2128,-2119,-2111,-2102,-2091,-2080,-2070,-2061,-2056,-2052,-2048,-2044,-2037,
--2029,-2020,-2011,-2004,-1998,-1993,-1988,-1981,-1975,-1971,-1968,-1968,-1967,-1964,-1957,-1946,-1930,-1914,-1897,-1884,-1874,
--1868,-1865,-1865,-1868,-1873,-1881,-1889,-1896,-1900,-1901,-1899,-1896,-1896,-1898,-1903,-1908,-1913,-1914,-1912,-1907,-1902,
--1896,-1891,-1887,-1882,-1875,-1867,-1858,-1848,-1841,-1835,-1833,-1835,-1839,-1846,-1853,-1860,-1863,-1862,-1858,-1849,-1838,
--1824,-1809,-1793,-1778,-1763,-1749,-1737,-1726,-1718,-1710,-1702,-1694,-1685,-1677,-1669,-1664,-1660,-1657,-1655,-1652,-1649,
--1646,-1641,-1634,-1624,-1611,-1593,-1572,-1549,-1528,-1510,-1494,-1480,-1465,-1448,-1429,-1409,-1390,-1376,-1367,-1363,-1362,
--1362,-1359,-1352,-1342,-1330,-1317,-1305,-1294,-1287,-1281,-1277,-1272,-1266,-1258,-1247,-1234,-1219,-1204,-1190,-1175,-1161,
--1146,-1129,-1112,-1095,-1081,-1071,-1065,-1060,-1055,-1046,-1031,-1009,-983,-956,-930,-909,-894,-883,-875,-868,-861,
--852,-842,-829,-815,-799,-783,-766,-749,-732,-716,-701,-685,-670,-655,-641,-628,-617,-606,-593,-577,-556,
--532,-503,-472,-441,-411,-384,-358,-334,-311,-290,-268,-248,-227,-206,-186,-167,-150,-136,-121,-106,-88,
--65,-38,-9,20,48,71,92,112,133,155,181,209,238,266,292,317,342,367,392,419,448,
-479,513,550,587,623,656,686,712,737,763,792,825,862,900,939,976,1011,1043,1069,1087,1094,
-1091,1082,1074,1076,1096,1136,1193,1259,1320,1367,1395,1404,1401,1394,1392,1400,1417,1441,1470,1499,1527,
-1554,1581,1608,1635,1664,1693,1722,1752,1780,1807,1832,1854,1872,1888,1902,1917,1932,1949,1964,1978,1987,
-1992,1993,1991,1987,1984,1982,1982,1983,1985,1987,1988,1986,1980,1971,1961,1951,1943,1940,1939,1941,1942,
-1940,1936,1929,1921,1915,1912,1912,1914,1917,1919,1920,1919,1916,1910,1904,1897,1893,1893,1898,1908,1920,
-1933,1942,1945,1943,1938,1933,1930,1931,1934,1938,1941,1942,1941,1937,1932,1927,1920,1912,1903,1893,1884,
-1876,1869,1864,1860,1856,1852,1850,1850,1853,1857,1864,1873,1883,1896,1911,1927,1943,1958,1969,1976,1982,
-1987,1993,2002,2012,2024,2036,2049,2063,2078,2094,2107,2118,2124,2128,2134,2144,2160,2181,2202,2220,2233,
-2241,2248,2260,2279,2304,2331,2355,2370,2377,2377,2374,2368,2361,2349,2331,2309,2286,2267,2253,2242,2228,
-2200,2154,2087,2001,1901,1789,1663,1521,1363,1199,1046,931,879,904,1005,1161,1341,1511,1648,1744,1804,
-1840,1868,1894,1920,1943,1959,1967,1970,1974,1980,1987,1993,1993,1985,1971,1956,1944,1940,1944,1954,1966,
-1978,1991,2005,2021,2035,2048,2056,2059,2060,2061,2065,2073,2082,2090,2094,2092,2088,2084,2085,2092,2104,
-2117,2129,2136,2140,2143,2148,2156,2168,2185,2205,2228,2254,2282,2307,2327,2336,2335,2326,2314,2306,2307,
-2318,2335,2350,2358,2354,2340,2318,2297,2280,2270,2266,2265,2264,2261,2256,2251,2246,2241,2236,2229,2219,
-2205,2190,2176,2164,2156,2116,2115,2114,2113,2111,2108,2104,2100,2094,2085,2073,2059,2043,2028,2015,2005,
-1996,1989,1981,1973,1964,1953,1943,1932,1922,1914,1910,1912,1919,1931,1943,1952,1954,1949,1939,1928,1919,
-1915,1917,1922,1929,1934,1939,1945,1952,1961,1972,1985,1996,2007,2020,2034,2053,2075,2101,2128,2156,2185,
-2214,2245,2273,2298,2317,2329,2338,2349,2367,2396,2434,2476,2514,2543,2561,2570,2579,2591,2609,2631,2651,
-2663,2668,2669,2673,2686,2710,2741,2770,2787,2787,2772,2753,2739,2739,2756,2784,2813,2834,2843,2844,2842,
-2844,2854,2871,2889,2902,2907,2907,2908,2916,2935,2965,3000,3033,3058,3075,3087,3098,3114,3135,3162,3190,
-3216,3236,3250,3259,3266,3271,3277,3285,3295,3306,3320,3334,3350,3366,3383,3400,3417,3434,3449,3462,3473,
-3483,3492,3503,3518,3538,3561,3585,3609,3631,3651,3669,3685,3699,3713,3724,3734,3743,3752,3761,3771,3779,
-3785,3788,3787,3784,3781,3778,3776,3775,3774,3774,3774,3777,3781,3786,3792,3797,3800,3803,3804,3807,3809,
-3810,3808,3804,3797,3788,3780,3773,3767,3758,3747,3733,3716,3701,3690,3682,3677,3672,3663,3649,3631,3612,
-3594,3579,3567,3557,3549,3541,3535,3532,3532,3535,3538,3540,3539,3536,3534,3532,3533,3534,3532,3528,3519,
-3507,3496,3487,3482,3481,3481,3481,3480,3478,3473,3467,3459,3451,3441,3433,3426,3422,3421,3420,3419,3415,
-3408,3399,3390,3384,3381,3381,3382,3381,3373,3358,3333,3300,3262,3224,3192,3171,3163,3164,3167,3165,3151,
-3125,3092,3061,3040,3036,3049,3071,3095,3112,3117,3112,3101,3088,3078,3072,3068,3065,3062,3061,3061,3063,
-3063,3062,3056,3048,3037,3029,3024,3024,3025,3027,3026,3024,3020,3016,3012,3003,2988,2963,2931,2895,2862,
-2837,2821,2814,2809,2799,2780,2751,2715,2677,2642,2611,2584,2558,2530,2497,2458,2415,2366,2310,2245,2172,
-2091,2007,1925,1851,1790,1742,1705,1673,1643,1613,1585,1563,1550,1548,1553,1559,1558,1544,1515,1472,1424,
-1377,1338,1309,1289,1272,1255,1232,1204,1171,1138,1106,1077,1051,1027,1005,984,964,944,923,898,871,
-839,805,770,736,703,671,638,604,568,532,497,463,429,394,354,310,262,212,165,123,86,
-53,23,-5,-34,-62,-89,-113,-135,-157,-180,-206,-236,-267,-300,-334,-366,-399,-430,-460,-490,-517,
--544,-570,-596,-622,-651,-679,-708,-737,-765,-793,-821,-849,-877,-904,-930,-954,-978,-1005,-1035,-1069,-1104,
--1139,-1172,-1201,-1229,-1255,-1283,-1313,-1344,-1377,-1408,-1438,-1466,-1495,-1524,-1554,-1584,-1612,-1639,-1665,-1691,-1717,
--1745,-1773,-1801,-1826,-1848,-1869,-1890,-1913,-1938,-1965,-1992,-2016,-2039,-2059,-2078,-2099,-2121,-2144,-2167,-2189,-2208,
--2227,-2245,-2265,-2287,-2309,-2332,-2352,-2371,-2388,-2403,-2419,-2434,-2451,-2467,-2482,-2498,-2513,-2528,-2544,-2559,-2575,
--2591,-2607,-2624,-2641,-2658,-2673,-2685,-2695,-2704,-2711,-2718,-2727,-2738,-2750,-2763,-2775,-2785,-2793,-2800,-2804,-2807,
--2809,-2811,-2814,-2817,-2821,-2824,-2827,-2829,-2830,-2830,-2830,-2830,-2831,-2832,-2832,-2831,-2830,-2829,-2829,-2829,-2830,
--2831,-2831,-2830,-2828,-2826,-2823,-2821,-2821,-2820,-2819,-2816,-2810,-2801,-2790,-2781,-2776,-2776,-2783,-2791,-2797,-2795,
--2784,-2762,-2736,-2709,-2688,-2673,-2664,-2657,-2649,-2639,-2628,-2618,-2612,-2611,-2611,-2610,-2604,-2594,-2579,-2564,-2551,
--2544,-2541,-2542,-2545,-2547,-2546,-2541,-2532,-2520,-2509,-2503,-2503,-2512,-2525,-2539,-2547,-2546,-2536,-2522,-2510,-2506,
--2513,-2528,-2547,-2567,-2584,-2600,-2615,-2630,-2643,-2651,-2654,-2654,-2658,-2668,-2686,-2705,-2718,-2717,-2708,-2704,-2729,
--2799,-2918,-3066,-3203,-3286,-3286,-3199,-3055,-2901,-2788,-2747,-2779,-2860,-2952,-3022,-3058,-3067,-3068,-3083,-3122,-3180,
--3242,-3294,-3329,-3352,-3370,-3396,-3432,-3475,-3516,-3546,-3565,-3576,-3586,-3604,-3631,-3664,-3699,-3729,-3751,-3767,-3779,
--3790,-3804,-3822,-3841,-3863,-3887,-3913,-3941,-3971,-3998,-4022,-4042,-4058,-4070,-4080,-4090,-4098,-4106,-4113,-4121,-4130,
--4142,-4154,-4163,-4169,-4169,-4164,-4159,-4157,-4159,-4167,-4177,-4186,-4191,-4191,-4188,-4185,-4185,-4188,-4193,-4197,-4201,
--4202,-4201,-4202,-4204,-4208,-4212,-4215,-4216,-4215,-4214,-4214,-4216,-4219,-4221,-4221,-4217,-4210,-4202,-4195,-4189,-4185,
--4180,-4175,-4167,-4158,-4150,-4143,-4137,-4133,-4128,-4123,-4117,-4111,-4105,-4101,-4098,-4094,-4089,-4082,-4073,-4064,-4056,
--4048,-4041,-4033,-4020,-4004,-3985,-3964,-3944,-3927,-3911,-3896,-3881,-3865,-3848,-3831,-3815,-3801,-3789,-3778,-3767,-3755,
--3742,-3729,-3716,-3703,-3690,-3677,-3663,-3647,-3629,-3609,-3589,-3567,-3546,-3524,-3504,-3485,-3468,-3451,-3436,-3421,-3406,
--3390,-3376,-3361,-3348,-3334,-3319,-3303,-3284,-3264,-3244,-3226,-3210,-3196,-3183,-3169,-3154,-3138,-3121,-3105,-3091,-3078,
--3067,-3055,-3042,-3027,-3012,-2996,-2982,-2968,-2954,-2940,-2926,-2912,-2897,-2884,-2873,-2862,-2851,-2839,-2827,-2813,-2799,
--2787,-2775,-2766,-2759,-2753,-2749,-2744,-2739,-2732,-2724,-2715,-2706,-2697,-2690,-2685,-2682,-2681,-2680,-2678,-2675,-2671,
--2667,-2664,-2660,-2655,-2650,-2643,-2636,-2629,-2624,-2620,-2618,-2616,-2615,-2612,-2608,-2605,-2602,-2600,-2599,-2597,-2594,
--2590,-2586,-2582,-2580,-2578,-2577,-2573,-2567,-2557,-2544,-2529,-2515,-2500,-2486,-2471,-2455,-2438,-2422,-2408,-2395,-2385,
--2375,-2364,-2351,-2336,-2321,-2308,-2296,-2287,-2280,-2273,-2266,-2259,-2253,-2247,-2242,-2237,-2230,-2222,-2213,-2203,-2194,
--2186,-2179,-2171,-2161,-2148,-2134,-2119,-2106,-2096,-2087,-2079,-2070,-2059,-2048,-2039,-2032,-2030,-2031,-2033,-2035,-2033,
--2030,-2026,-2022,-2019,-2016,-2012,-2006,-1996,-1982,-1967,-1952,-1938,-1926,-1916,-1908,-1903,-1900,-1902,-1907,-1914,-1921,
--1925,-1925,-1922,-1918,-1914,-1914,-1916,-1920,-1926,-1931,-1935,-1940,-1946,-1952,-1958,-1960,-1957,-1947,-1930,-1907,-1884,
--1863,-1848,-1842,-1844,-1854,-1869,-1885,-1900,-1912,-1919,-1921,-1919,-1913,-1903,-1889,-1873,-1855,-1837,-1820,-1806,-1794,
--1785,-1776,-1768,-1757,-1746,-1733,-1722,-1712,-1704,-1697,-1691,-1686,-1682,-1679,-1677,-1674,-1668,-1657,-1640,-1619,-1595,
--1572,-1553,-1538,-1525,-1512,-1496,-1477,-1456,-1436,-1421,-1411,-1407,-1406,-1404,-1400,-1391,-1379,-1366,-1353,-1342,-1333,
--1325,-1318,-1311,-1303,-1294,-1283,-1271,-1257,-1243,-1228,-1212,-1194,-1175,-1154,-1132,-1112,-1095,-1083,-1078,-1077,-1080,
--1080,-1076,-1063,-1044,-1018,-989,-960,-933,-910,-890,-874,-861,-850,-842,-835,-828,-820,-810,-798,-784,-768,
--752,-736,-719,-702,-684,-665,-648,-633,-620,-608,-597,-583,-565,-544,-519,-493,-467,-441,-415,-388,-360,
--332,-304,-278,-255,-236,-218,-203,-189,-175,-161,-145,-128,-106,-81,-53,-24,4,29,50,68,85,
-103,124,149,176,205,234,263,291,318,344,369,394,421,450,484,523,567,612,655,695,730,
-762,792,823,856,891,926,962,998,1035,1073,1111,1145,1173,1190,1198,1200,1203,1215,1241,1281,1329,
-1378,1417,1442,1453,1454,1453,1457,1469,1487,1510,1532,1550,1565,1578,1594,1616,1645,1679,1717,1755,1789,
-1819,1843,1862,1878,1893,1906,1919,1931,1942,1952,1961,1969,1977,1984,1992,2001,2008,2015,2019,2021,2019,
-2014,2006,1997,1987,1977,1970,1966,1965,1967,1970,1973,1973,1969,1962,1952,1940,1930,1921,1915,1911,1909,
-1910,1912,1914,1917,1917,1916,1912,1908,1905,1907,1913,1923,1935,1947,1955,1960,1963,1964,1967,1972,1977,
-1982,1983,1981,1975,1968,1961,1955,1951,1946,1941,1935,1929,1924,1921,1917,1913,1907,1899,1891,1884,1880,
-1881,1886,1894,1904,1916,1928,1940,1952,1963,1972,1976,1978,1979,1981,1986,1995,2008,2024,2042,2061,2080,
-2098,2113,2123,2128,2129,2130,2135,2147,2166,2189,2211,2227,2237,2244,2253,2268,2290,2316,2339,2356,2363,
-2365,2367,2373,2382,2388,2384,2367,2338,2305,2279,2266,2265,2265,2254,2219,2157,2073,1976,1875,1770,1654,
-1519,1364,1201,1056,959,937,998,1130,1301,1475,1620,1723,1785,1821,1849,1879,1914,1946,1970,1982,1983,
-1980,1978,1979,1981,1981,1975,1962,1946,1932,1923,1922,1926,1932,1939,1948,1958,1970,1983,1992,1996,1993,
-1985,1977,1972,1975,1984,1994,2002,2005,2003,2001,2002,2008,2020,2033,2042,2045,2043,2039,2037,2043,2057,
-2078,2105,2134,2164,2192,2216,2233,2241,2241,2233,2223,2216,2217,2226,2240,2252,2257,2250,2234,2212,2192,
-2180,2177,2182,2192,2201,2206,2206,2202,2196,2189,2181,2171,2160,2147,2136,2126,2120,2116,2076,2076,2074,
-2069,2062,2055,2049,2043,2037,2027,2012,1994,1974,1954,1938,1927,1920,1915,1911,1908,1903,1898,1893,1887,
-1882,1879,1880,1887,1899,1915,1932,1944,1949,1946,1936,1923,1913,1908,1909,1913,1920,1927,1933,1940,1949,
-1960,1973,1986,1998,2010,2022,2036,2055,2078,2105,2133,2163,2193,2224,2253,2281,2302,2316,2322,2325,2330,
-2343,2369,2406,2447,2485,2512,2527,2535,2541,2552,2570,2592,2612,2624,2628,2628,2633,2647,2674,2709,2741,
-2761,2763,2750,2732,2719,2720,2736,2761,2788,2807,2817,2820,2823,2830,2845,2864,2881,2890,2891,2888,2888,
-2898,2921,2953,2987,3018,3041,3055,3065,3077,3094,3116,3143,3169,3192,3208,3220,3228,3235,3242,3251,3260,
-3270,3281,3294,3308,3323,3339,3355,3371,3386,3400,3412,3423,3431,3439,3447,3457,3471,3489,3511,3534,3558,
-3580,3601,3620,3637,3652,3665,3676,3685,3694,3703,3713,3723,3733,3741,3746,3747,3745,3742,3739,3737,3736,
-3735,3736,3737,3739,3743,3748,3753,3756,3758,3758,3758,3758,3759,3760,3760,3758,3754,3748,3741,3734,3726,
-3715,3703,3688,3672,3658,3647,3639,3634,3627,3618,3604,3588,3570,3553,3540,3532,3527,3523,3521,3519,3517,
-3515,3513,3511,3508,3505,3503,3503,3504,3506,3506,3502,3495,3484,3472,3461,3454,3452,3453,3454,3456,3455,
-3452,3447,3440,3432,3422,3413,3406,3400,3397,3396,3395,3393,3389,3381,3373,3364,3358,3354,3351,3347,3339,
-3325,3303,3273,3238,3202,3169,3145,3133,3134,3146,3160,3170,3169,3154,3129,3100,3076,3063,3063,3072,3082,
-3088,3085,3073,3056,3037,3021,3008,2998,2990,2983,2978,2976,2977,2981,2986,2991,2994,2995,2996,2997,2998,
-3000,3001,3002,3005,3010,3018,3026,3030,3025,3007,2976,2937,2896,2860,2835,2821,2812,2804,2788,2761,2725,
-2683,2641,2602,2570,2542,2515,2489,2459,2426,2387,2342,2287,2223,2149,2069,1986,1907,1836,1777,1726,1682,
-1642,1603,1566,1534,1512,1501,1499,1501,1500,1489,1466,1432,1391,1351,1316,1289,1268,1250,1232,1210,1185,
-1158,1130,1102,1074,1046,1018,988,960,933,909,886,862,836,807,773,738,703,669,636,603,570,
-537,503,471,439,406,371,331,287,239,190,144,102,67,36,9,-17,-44,-72,-99,-126,-152,
--177,-203,-230,-260,-290,-322,-354,-387,-420,-452,-483,-512,-539,-564,-588,-612,-638,-665,-694,-723,-751,
--779,-806,-834,-862,-891,-918,-944,-968,-991,-1016,-1045,-1077,-1112,-1148,-1183,-1214,-1242,-1269,-1295,-1322,-1351,
--1381,-1410,-1439,-1468,-1496,-1526,-1556,-1587,-1617,-1645,-1673,-1700,-1727,-1755,-1783,-1810,-1834,-1856,-1876,-1897,-1919,
--1944,-1972,-2000,-2026,-2050,-2071,-2092,-2112,-2135,-2158,-2180,-2201,-2221,-2239,-2257,-2278,-2300,-2325,-2349,-2371,-2391,
--2407,-2422,-2436,-2450,-2466,-2483,-2500,-2518,-2536,-2553,-2569,-2585,-2600,-2615,-2631,-2649,-2667,-2686,-2704,-2719,-2730,
--2738,-2744,-2749,-2756,-2765,-2776,-2788,-2800,-2812,-2822,-2830,-2837,-2842,-2847,-2851,-2854,-2857,-2859,-2862,-2864,-2866,
--2867,-2869,-2870,-2871,-2872,-2873,-2874,-2874,-2874,-2874,-2874,-2875,-2876,-2877,-2878,-2877,-2876,-2873,-2870,-2867,-2864,
--2863,-2863,-2861,-2857,-2850,-2842,-2833,-2828,-2827,-2831,-2838,-2843,-2842,-2831,-2813,-2789,-2765,-2745,-2730,-2721,-2715,
--2709,-2700,-2690,-2680,-2672,-2666,-2663,-2660,-2656,-2648,-2638,-2626,-2613,-2602,-2595,-2591,-2591,-2594,-2596,-2595,-2588,
--2575,-2559,-2545,-2538,-2540,-2550,-2565,-2578,-2583,-2579,-2568,-2557,-2551,-2553,-2563,-2579,-2598,-2618,-2637,-2657,-2674,
--2687,-2694,-2693,-2690,-2691,-2700,-2719,-2741,-2756,-2759,-2749,-2742,-2759,-2818,-2927,-3071,-3214,-3314,-3339,-3280,-3157,
--3010,-2888,-2824,-2830,-2888,-2970,-3043,-3092,-3115,-3128,-3146,-3181,-3233,-3293,-3348,-3390,-3420,-3444,-3467,-3495,-3527,
--3557,-3581,-3597,-3609,-3622,-3642,-3669,-3702,-3737,-3769,-3795,-3815,-3832,-3848,-3864,-3881,-3900,-3920,-3944,-3970,-3999,
--4028,-4055,-4078,-4097,-4111,-4123,-4133,-4144,-4155,-4165,-4176,-4186,-4197,-4208,-4219,-4226,-4230,-4230,-4226,-4221,-4218,
--4219,-4223,-4229,-4234,-4237,-4238,-4238,-4240,-4243,-4248,-4254,-4258,-4261,-4261,-4262,-4263,-4267,-4270,-4272,-4272,-4270,
--4268,-4266,-4268,-4271,-4276,-4278,-4278,-4273,-4267,-4260,-4255,-4252,-4249,-4245,-4238,-4229,-4220,-4212,-4205,-4201,-4197,
--4192,-4184,-4174,-4164,-4156,-4150,-4147,-4143,-4138,-4130,-4119,-4108,-4099,-4092,-4086,-4080,-4072,-4060,-4045,-4028,-4011,
--3994,-3977,-3960,-3942,-3923,-3904,-3885,-3869,-3855,-3841,-3828,-3815,-3801,-3786,-3773,-3762,-3751,-3740,-3729,-3715,-3699,
--3681,-3663,-3644,-3625,-3605,-3585,-3563,-3542,-3521,-3501,-3483,-3466,-3450,-3433,-3417,-3402,-3388,-3374,-3361,-3347,-3331,
--3313,-3295,-3277,-3261,-3247,-3235,-3223,-3210,-3195,-3179,-3163,-3147,-3133,-3119,-3105,-3090,-3074,-3057,-3040,-3025,-3011,
--2998,-2985,-2972,-2959,-2946,-2934,-2923,-2913,-2903,-2891,-2878,-2864,-2849,-2835,-2822,-2811,-2802,-2795,-2789,-2784,-2779,
--2773,-2767,-2761,-2754,-2747,-2740,-2736,-2733,-2732,-2731,-2730,-2729,-2727,-2724,-2721,-2718,-2713,-2708,-2700,-2692,-2683,
--2675,-2669,-2664,-2661,-2658,-2654,-2650,-2644,-2639,-2633,-2628,-2624,-2619,-2616,-2614,-2613,-2613,-2615,-2615,-2614,-2611,
--2605,-2598,-2590,-2583,-2576,-2568,-2559,-2548,-2536,-2524,-2513,-2503,-2494,-2484,-2470,-2453,-2432,-2410,-2388,-2367,-2349,
--2333,-2318,-2307,-2297,-2291,-2288,-2286,-2285,-2282,-2276,-2267,-2257,-2247,-2239,-2232,-2224,-2215,-2204,-2191,-2177,-2165,
--2154,-2143,-2132,-2119,-2104,-2089,-2076,-2067,-2063,-2064,-2067,-2070,-2071,-2070,-2068,-2065,-2062,-2059,-2055,-2049,-2040,
--2030,-2019,-2009,-2000,-1991,-1982,-1973,-1965,-1958,-1953,-1953,-1955,-1958,-1961,-1961,-1959,-1956,-1953,-1950,-1948,-1946,
--1945,-1944,-1946,-1951,-1960,-1973,-1987,-1999,-2005,-2002,-1991,-1973,-1952,-1931,-1914,-1904,-1900,-1901,-1906,-1913,-1919,
--1925,-1930,-1934,-1936,-1936,-1932,-1925,-1914,-1900,-1885,-1871,-1861,-1854,-1850,-1846,-1839,-1829,-1815,-1799,-1782,-1765,
--1750,-1736,-1724,-1714,-1705,-1701,-1698,-1698,-1696,-1689,-1676,-1657,-1634,-1611,-1591,-1575,-1562,-1550,-1536,-1520,-1502,
--1484,-1470,-1461,-1457,-1453,-1448,-1440,-1428,-1413,-1398,-1386,-1376,-1368,-1360,-1352,-1341,-1328,-1316,-1303,-1291,-1279,
--1266,-1251,-1231,-1207,-1180,-1150,-1122,-1098,-1080,-1071,-1070,-1075,-1081,-1086,-1084,-1075,-1060,-1040,-1017,-995,-973,
--951,-929,-908,-888,-871,-858,-848,-842,-836,-829,-819,-806,-790,-773,-755,-737,-718,-698,-679,-661,-645,
--632,-620,-609,-597,-582,-564,-543,-521,-497,-473,-447,-418,-387,-355,-323,-295,-270,-251,-235,-223,-211,
--199,-184,-168,-148,-124,-98,-70,-42,-17,4,22,38,53,71,92,117,146,176,207,237,266,
-294,320,346,371,396,424,457,494,537,583,630,675,718,760,801,841,882,920,955,986,1013,
-1041,1071,1107,1145,1185,1221,1250,1273,1292,1312,1336,1367,1400,1433,1460,1478,1490,1498,1509,1525,1548,
-1573,1595,1611,1618,1619,1620,1626,1642,1669,1705,1744,1783,1816,1842,1862,1877,1891,1905,1919,1932,1944,
-1955,1963,1970,1977,1986,1995,2006,2016,2026,2033,2037,2038,2035,2029,2020,2011,2001,1992,1985,1980,1978,
-1978,1979,1980,1980,1979,1977,1974,1969,1962,1953,1941,1929,1917,1909,1905,1907,1911,1916,1919,1920,1918,
-1916,1916,1921,1929,1939,1951,1962,1973,1984,1995,2007,2017,2024,2025,2021,2012,2001,1992,1986,1983,1981,
-1979,1976,1971,1965,1959,1955,1951,1946,1940,1932,1924,1918,1915,1916,1921,1929,1939,1951,1962,1973,1983,
-1990,1993,1993,1990,1987,1988,1995,2007,2023,2042,2062,2082,2100,2116,2128,2136,2139,2139,2141,2148,2162,
-2182,2204,2222,2235,2243,2250,2262,2282,2309,2336,2356,2363,2361,2355,2354,2365,2385,2405,2413,2402,2373,
-2334,2301,2282,2277,2278,2269,2238,2182,2108,2029,1952,1876,1789,1673,1521,1342,1163,1024,960,989,1103,
-1272,1454,1611,1724,1791,1827,1853,1882,1917,1953,1979,1990,1989,1980,1973,1971,1975,1979,1978,1971,1960,
-1948,1939,1934,1933,1933,1933,1934,1937,1943,1950,1954,1950,1937,1915,1891,1872,1863,1867,1878,1890,1900,
-1904,1904,1904,1908,1915,1924,1931,1932,1929,1925,1924,1931,1948,1971,1998,2026,2052,2075,2094,2108,2117,
-2120,2118,2112,2109,2110,2118,2130,2140,2144,2138,2123,2104,2086,2075,2074,2081,2092,2104,2111,2113,2111,
-2106,2100,2093,2087,2081,2076,2073,2073,2074,2076,2020,2021,2017,2009,1999,1989,1981,1975,1970,1962,1950,
-1933,1914,1895,1879,1868,1860,1856,1853,1851,1848,1846,1844,1842,1841,1841,1844,1852,1866,1884,1903,1919,
-1928,1930,1924,1915,1907,1902,1902,1906,1912,1918,1925,1933,1944,1959,1976,1993,2009,2023,2037,2052,2070,
-2091,2114,2140,2168,2197,2228,2259,2288,2311,2325,2331,2331,2332,2340,2358,2388,2422,2454,2478,2493,2502,
-2511,2525,2545,2567,2586,2597,2599,2597,2600,2614,2641,2676,2709,2730,2736,2728,2713,2703,2705,2720,2743,
-2767,2786,2798,2804,2810,2820,2834,2849,2861,2866,2866,2867,2873,2890,2917,2950,2981,3007,3023,3033,3042,
-3053,3071,3093,3117,3139,3157,3170,3180,3190,3201,3212,3224,3235,3246,3257,3269,3283,3299,3315,3330,3344,
-3355,3364,3372,3380,3388,3397,3406,3416,3429,3444,3463,3483,3505,3526,3547,3567,3585,3601,3615,3626,3637,
-3647,3657,3668,3679,3689,3697,3700,3700,3698,3694,3692,3691,3693,3696,3700,3705,3709,3714,3718,3721,3723,
-3723,3721,3719,3716,3715,3714,3714,3713,3710,3704,3697,3688,3678,3666,3653,3638,3623,3608,3595,3584,3575,
-3567,3558,3548,3537,3526,3517,3510,3506,3504,3503,3502,3501,3498,3494,3490,3486,3482,3480,3480,3482,3484,
-3484,3481,3474,3463,3450,3438,3430,3426,3426,3428,3431,3432,3431,3427,3422,3415,3407,3398,3389,3382,3376,
-3373,3371,3369,3365,3359,3351,3342,3334,3328,3323,3317,3308,3295,3277,3254,3229,3203,3180,3160,3148,3144,
-3149,3162,3179,3194,3203,3202,3191,3174,3156,3142,3133,3129,3125,3117,3103,3082,3059,3037,3017,3002,2990,
-2979,2968,2956,2945,2938,2938,2943,2953,2966,2979,2991,3000,3005,3008,3008,3009,3013,3020,3032,3045,3056,
-3058,3048,3024,2990,2950,2912,2881,2859,2843,2828,2808,2779,2741,2697,2652,2610,2574,2544,2518,2493,2467,
-2438,2404,2364,2316,2259,2193,2118,2040,1963,1891,1826,1770,1719,1671,1623,1577,1534,1499,1474,1458,1449,
-1442,1431,1412,1387,1357,1325,1296,1270,1247,1225,1203,1180,1157,1134,1112,1090,1066,1037,1005,969,932,
-898,868,841,817,793,767,738,706,673,640,608,576,544,512,480,448,415,382,346,306,262,
-215,168,123,83,48,18,-9,-36,-62,-89,-116,-142,-167,-193,-220,-248,-277,-307,-338,-370,-402,
--436,-470,-504,-535,-564,-589,-612,-634,-657,-682,-708,-734,-760,-785,-811,-838,-866,-895,-924,-952,-979,
--1004,-1031,-1060,-1092,-1126,-1161,-1195,-1225,-1252,-1277,-1302,-1328,-1356,-1387,-1417,-1448,-1478,-1507,-1537,-1566,-1595,
--1623,-1651,-1678,-1706,-1734,-1763,-1793,-1820,-1846,-1868,-1889,-1909,-1932,-1957,-1985,-2014,-2041,-2066,-2087,-2108,-2127,
--2148,-2169,-2191,-2213,-2233,-2252,-2272,-2292,-2315,-2339,-2363,-2386,-2406,-2424,-2439,-2453,-2467,-2482,-2498,-2515,-2534,
--2553,-2572,-2591,-2608,-2624,-2639,-2655,-2671,-2689,-2708,-2726,-2743,-2756,-2767,-2775,-2782,-2790,-2799,-2809,-2819,-2830,
--2841,-2850,-2860,-2869,-2878,-2885,-2891,-2894,-2896,-2897,-2898,-2899,-2902,-2904,-2908,-2910,-2913,-2914,-2915,-2916,-2916,
--2917,-2917,-2916,-2916,-2917,-2918,-2920,-2922,-2924,-2923,-2922,-2919,-2915,-2912,-2910,-2907,-2903,-2897,-2890,-2883,-2878,
--2876,-2878,-2882,-2886,-2885,-2877,-2862,-2842,-2819,-2799,-2783,-2772,-2765,-2759,-2753,-2745,-2737,-2729,-2721,-2715,-2710,
--2706,-2700,-2693,-2684,-2673,-2660,-2649,-2641,-2638,-2639,-2642,-2643,-2639,-2627,-2610,-2593,-2580,-2576,-2582,-2595,-2608,
--2617,-2617,-2610,-2600,-2592,-2591,-2596,-2607,-2623,-2643,-2666,-2690,-2712,-2729,-2736,-2735,-2728,-2723,-2728,-2745,-2769,
--2790,-2798,-2793,-2783,-2787,-2828,-2915,-3042,-3185,-3305,-3368,-3355,-3275,-3157,-3041,-2962,-2940,-2970,-3033,-3101,-3157,
--3191,-3210,-3226,-3250,-3286,-3333,-3384,-3430,-3469,-3500,-3528,-3553,-3578,-3600,-3619,-3635,-3649,-3666,-3687,-3714,-3745,
--3778,-3810,-3840,-3866,-3890,-3911,-3929,-3946,-3963,-3980,-4001,-4026,-4054,-4084,-4111,-4134,-4152,-4166,-4177,-4188,-4199,
--4213,-4226,-4240,-4252,-4262,-4272,-4279,-4284,-4287,-4287,-4285,-4284,-4283,-4284,-4287,-4290,-4292,-4294,-4295,-4298,-4301,
--4307,-4313,-4318,-4321,-4322,-4322,-4323,-4326,-4328,-4330,-4330,-4327,-4322,-4318,-4317,-4320,-4325,-4330,-4333,-4332,-4327,
--4321,-4316,-4312,-4309,-4305,-4297,-4286,-4273,-4260,-4251,-4246,-4245,-4244,-4241,-4235,-4225,-4215,-4206,-4199,-4195,-4191,
--4185,-4175,-4163,-4150,-4139,-4130,-4124,-4118,-4112,-4104,-4093,-4080,-4065,-4050,-4033,-4014,-3994,-3973,-3953,-3936,-3921,
--3910,-3899,-3887,-3873,-3858,-3842,-3827,-3814,-3802,-3791,-3778,-3764,-3747,-3731,-3714,-3698,-3683,-3665,-3646,-3624,-3601,
--3578,-3557,-3536,-3518,-3499,-3481,-3462,-3444,-3428,-3414,-3401,-3389,-3376,-3362,-3346,-3330,-3314,-3300,-3286,-3274,-3260,
--3246,-3231,-3216,-3202,-3188,-3174,-3160,-3144,-3127,-3110,-3092,-3076,-3061,-3047,-3034,-3020,-3006,-2993,-2981,-2969,-2959,
--2949,-2939,-2927,-2914,-2901,-2888,-2876,-2865,-2855,-2846,-2837,-2829,-2823,-2818,-2814,-2811,-2807,-2804,-2799,-2795,-2790,
--2786,-2783,-2780,-2777,-2775,-2773,-2771,-2768,-2765,-2761,-2754,-2747,-2739,-2731,-2724,-2718,-2713,-2709,-2705,-2700,-2694,
--2688,-2681,-2674,-2667,-2660,-2655,-2650,-2646,-2643,-2641,-2638,-2634,-2630,-2626,-2623,-2621,-2620,-2620,-2619,-2616,-2611,
--2605,-2599,-2593,-2589,-2584,-2577,-2567,-2553,-2535,-2514,-2492,-2470,-2448,-2427,-2407,-2388,-2373,-2361,-2353,-2347,-2342,
--2336,-2326,-2314,-2301,-2289,-2278,-2270,-2263,-2256,-2248,-2240,-2232,-2223,-2215,-2206,-2196,-2182,-2166,-2149,-2132,-2118,
--2109,-2104,-2102,-2103,-2104,-2106,-2108,-2111,-2112,-2112,-2109,-2103,-2094,-2083,-2073,-2065,-2058,-2052,-2045,-2037,-2027,
--2018,-2010,-2004,-2002,-2001,-2002,-2003,-2004,-2004,-2004,-2002,-1999,-1994,-1987,-1978,-1972,-1969,-1972,-1981,-1995,-2011,
--2026,-2037,-2043,-2043,-2039,-2033,-2025,-2016,-2007,-1997,-1986,-1975,-1964,-1954,-1947,-1943,-1941,-1941,-1939,-1935,-1927,
--1917,-1905,-1897,-1892,-1891,-1894,-1897,-1896,-1891,-1880,-1864,-1847,-1828,-1810,-1793,-1775,-1757,-1740,-1727,-1718,-1712,
--1708,-1702,-1692,-1676,-1657,-1637,-1618,-1603,-1591,-1580,-1568,-1554,-1538,-1524,-1512,-1504,-1500,-1496,-1489,-1479,-1465,
--1450,-1434,-1422,-1411,-1403,-1393,-1382,-1369,-1355,-1341,-1330,-1320,-1312,-1300,-1283,-1258,-1225,-1187,-1146,-1109,-1080,
--1062,-1055,-1057,-1065,-1073,-1078,-1078,-1071,-1060,-1048,-1036,-1025,-1014,-1001,-983,-962,-938,-914,-892,-876,-864,
--855,-846,-836,-824,-808,-791,-773,-755,-736,-717,-698,-680,-663,-648,-636,-624,-612,-599,-584,-567,-548,
--528,-506,-481,-453,-421,-388,-355,-324,-298,-277,-260,-245,-232,-219,-204,-186,-165,-142,-117,-92,-69,
--48,-30,-15,0,16,36,61,91,123,156,189,220,250,278,306,332,358,383,410,439,472,
-509,549,591,636,681,729,778,829,880,927,968,1002,1029,1054,1080,1110,1145,1183,1221,1256,1287,
-1315,1340,1367,1396,1425,1453,1477,1497,1514,1532,1555,1582,1611,1638,1659,1669,1669,1664,1660,1663,1677,
-1701,1732,1767,1801,1830,1854,1876,1895,1913,1930,1945,1957,1964,1969,1973,1978,1985,1994,2005,2016,2024,
-2029,2029,2027,2024,2020,2018,2018,2018,2018,2017,2013,2007,1999,1991,1983,1978,1976,1980,1986,1993,1998,
-1997,1989,1975,1958,1942,1931,1927,1929,1935,1941,1945,1946,1943,1940,1938,1941,1947,1957,1969,1984,2001,
-2019,2038,2055,2068,2074,2072,2063,2049,2037,2027,2022,2021,2020,2017,2011,2001,1989,1978,1968,1960,1954,
-1948,1943,1939,1936,1936,1937,1939,1943,1949,1956,1966,1978,1989,1997,2001,2001,1999,1998,2002,2013,2028,
-2048,2068,2087,2104,2119,2133,2144,2152,2156,2160,2164,2173,2188,2207,2226,2242,2251,2257,2264,2278,2302,
-2332,2361,2381,2387,2381,2371,2366,2374,2392,2412,2423,2414,2386,2347,2311,2287,2275,2268,2253,2221,2173,
-2118,2066,2022,1980,1919,1816,1662,1463,1253,1077,979,983,1084,1251,1440,1609,1732,1805,1844,1867,1892,
-1923,1954,1977,1988,1985,1977,1971,1972,1981,1991,1999,2000,1997,1992,1989,1988,1988,1985,1981,1975,1972,
-1973,1977,1979,1972,1952,1921,1884,1852,1831,1827,1835,1849,1861,1868,1867,1864,1861,1862,1865,1869,1872,
-1873,1873,1877,1886,1901,1919,1938,1954,1968,1978,1987,1994,2000,2004,2004,2002,2001,2004,2012,2024,2035,
-2042,2040,2029,2013,1997,1985,1981,1984,1991,1998,2004,2007,2007,2006,2004,2003,2002,2001,2002,2005,2010,
-2016,2020,1947,1949,1946,1939,1930,1921,1914,1909,1905,1900,1892,1880,1865,1850,1836,1824,1815,1809,1804,
-1801,1799,1798,1799,1801,1803,1805,1810,1817,1829,1845,1863,1880,1893,1900,1900,1896,1892,1889,1890,1894,
-1900,1907,1917,1929,1944,1963,1984,2005,2026,2044,2060,2076,2093,2111,2131,2153,2177,2203,2232,2262,2291,
-2316,2334,2343,2346,2347,2351,2364,2385,2411,2437,2458,2474,2487,2500,2518,2538,2559,2576,2585,2586,2584,
-2586,2599,2621,2651,2678,2697,2703,2698,2691,2687,2694,2712,2735,2759,2778,2789,2796,2802,2809,2817,2826,
-2833,2838,2843,2853,2869,2894,2925,2955,2980,2996,3005,3010,3017,3029,3046,3067,3087,3103,3115,3125,3134,
-3146,3159,3174,3188,3201,3212,3224,3238,3254,3272,3289,3304,3316,3325,3331,3338,3346,3354,3364,3374,3384,
-3394,3406,3420,3436,3454,3473,3493,3511,3528,3545,3559,3573,3586,3599,3612,3625,3637,3648,3655,3658,3656,
-3653,3649,3647,3648,3652,3658,3665,3671,3675,3679,3682,3685,3687,3688,3687,3686,3684,3682,3680,3678,3674,
-3669,3662,3652,3641,3629,3616,3604,3591,3577,3562,3547,3532,3518,3507,3497,3491,3486,3484,3482,3482,3481,
-3480,3478,3477,3474,3471,3468,3464,3461,3460,3460,3461,3463,3463,3461,3454,3444,3432,3421,3412,3407,3406,
-3407,3408,3410,3409,3408,3405,3401,3395,3389,3381,3372,3364,3358,3354,3351,3346,3340,3331,3321,3311,3303,
-3297,3291,3282,3269,3252,3232,3213,3196,3183,3176,3171,3170,3171,3175,3182,3194,3208,3221,3229,3232,3227,
-3218,3206,3193,3179,3163,3144,3120,3093,3066,3042,3023,3010,2999,2988,2975,2958,2941,2927,2920,2923,2936,
-2955,2977,2998,3015,3027,3034,3037,3039,3042,3047,3054,3062,3068,3068,3060,3042,3016,2985,2952,2922,2895,
-2871,2848,2821,2789,2751,2709,2666,2626,2591,2561,2536,2512,2488,2461,2430,2392,2347,2293,2230,2159,2084,
-2007,1934,1866,1805,1748,1695,1643,1592,1545,1502,1467,1440,1420,1404,1388,1371,1350,1326,1301,1275,1249,
-1223,1197,1170,1144,1119,1097,1078,1059,1037,1011,979,943,905,868,835,805,778,753,727,699,671,
-641,612,583,554,524,494,462,430,396,361,323,282,238,193,149,106,68,33,2,-27,-55,
--81,-107,-131,-155,-178,-203,-230,-259,-290,-320,-351,-382,-414,-448,-483,-518,-553,-584,-612,-637,-659,
--681,-703,-726,-748,-771,-793,-815,-839,-865,-893,-923,-953,-984,-1013,-1043,-1074,-1107,-1140,-1173,-1204,-1231,
--1256,-1279,-1302,-1329,-1358,-1389,-1422,-1455,-1486,-1517,-1547,-1576,-1603,-1630,-1657,-1683,-1710,-1739,-1769,-1799,-1829,
--1856,-1880,-1902,-1923,-1946,-1971,-1998,-2026,-2054,-2079,-2101,-2120,-2139,-2159,-2180,-2202,-2225,-2247,-2269,-2290,-2310,
--2331,-2353,-2375,-2396,-2417,-2437,-2455,-2472,-2488,-2503,-2518,-2534,-2551,-2569,-2589,-2608,-2627,-2645,-2661,-2676,-2691,
--2707,-2723,-2741,-2758,-2774,-2789,-2802,-2814,-2825,-2836,-2847,-2857,-2866,-2875,-2884,-2894,-2903,-2913,-2921,-2928,-2932,
--2933,-2934,-2934,-2936,-2939,-2943,-2947,-2951,-2953,-2954,-2956,-2957,-2958,-2960,-2961,-2961,-2960,-2960,-2960,-2961,-2964,
--2968,-2971,-2973,-2972,-2969,-2966,-2962,-2957,-2952,-2946,-2939,-2932,-2926,-2923,-2923,-2925,-2928,-2929,-2925,-2915,-2899,
--2879,-2859,-2841,-2826,-2816,-2809,-2805,-2800,-2795,-2788,-2780,-2773,-2766,-2760,-2755,-2749,-2742,-2732,-2720,-2706,-2695,
--2688,-2687,-2690,-2693,-2692,-2683,-2667,-2648,-2632,-2622,-2622,-2629,-2639,-2646,-2648,-2644,-2637,-2631,-2628,-2630,-2637,
--2649,-2666,-2689,-2717,-2745,-2769,-2783,-2785,-2778,-2769,-2767,-2778,-2799,-2822,-2837,-2838,-2827,-2821,-2837,-2894,-2995,
--3125,-3255,-3354,-3397,-3376,-3306,-3216,-3137,-3093,-3092,-3126,-3178,-3229,-3268,-3292,-3307,-3322,-3345,-3378,-3419,-3463,
--3505,-3542,-3574,-3601,-3624,-3645,-3664,-3683,-3703,-3723,-3746,-3771,-3798,-3827,-3856,-3886,-3915,-3942,-3966,-3985,-4000,
--4014,-4029,-4048,-4073,-4103,-4134,-4164,-4188,-4207,-4220,-4230,-4241,-4254,-4268,-4284,-4299,-4313,-4324,-4332,-4337,-4341,
--4342,-4343,-4343,-4344,-4346,-4349,-4353,-4357,-4361,-4364,-4368,-4372,-4378,-4384,-4389,-4392,-4392,-4391,-4389,-4388,-4388,
--4388,-4387,-4383,-4377,-4371,-4366,-4366,-4369,-4375,-4381,-4383,-4381,-4376,-4370,-4365,-4362,-4359,-4354,-4344,-4328,-4310,
--4293,-4281,-4274,-4273,-4273,-4273,-4269,-4263,-4255,-4248,-4242,-4238,-4234,-4227,-4217,-4204,-4190,-4178,-4168,-4160,-4153,
--4145,-4136,-4126,-4114,-4103,-4090,-4076,-4060,-4042,-4023,-4005,-3990,-3978,-3968,-3958,-3946,-3930,-3913,-3895,-3878,-3864,
--3852,-3840,-3828,-3814,-3798,-3782,-3768,-3754,-3740,-3725,-3707,-3685,-3662,-3638,-3616,-3596,-3577,-3559,-3539,-3518,-3497,
--3477,-3460,-3445,-3432,-3419,-3406,-3393,-3378,-3363,-3349,-3335,-3321,-3307,-3292,-3277,-3263,-3249,-3237,-3225,-3213,-3199,
--3184,-3167,-3151,-3134,-3118,-3103,-3088,-3073,-3058,-3043,-3029,-3016,-3004,-2993,-2982,-2971,-2960,-2950,-2940,-2931,-2922,
--2912,-2902,-2891,-2882,-2873,-2868,-2865,-2863,-2862,-2860,-2857,-2852,-2846,-2840,-2834,-2829,-2825,-2822,-2818,-2815,-2812,
--2808,-2804,-2800,-2795,-2790,-2784,-2778,-2773,-2768,-2763,-2758,-2753,-2748,-2742,-2736,-2731,-2725,-2718,-2711,-2704,-2697,
--2690,-2682,-2674,-2666,-2659,-2653,-2649,-2647,-2647,-2647,-2648,-2646,-2644,-2640,-2635,-2632,-2629,-2626,-2623,-2619,-2613,
--2605,-2595,-2585,-2573,-2559,-2544,-2525,-2506,-2485,-2466,-2448,-2432,-2416,-2401,-2384,-2366,-2348,-2332,-2319,-2308,-2300,
--2294,-2289,-2283,-2278,-2273,-2267,-2261,-2252,-2241,-2227,-2212,-2196,-2181,-2168,-2157,-2150,-2145,-2145,-2147,-2153,-2159,
--2166,-2169,-2168,-2163,-2153,-2142,-2130,-2121,-2113,-2107,-2099,-2091,-2081,-2071,-2062,-2054,-2049,-2045,-2043,-2042,-2042,
--2044,-2046,-2048,-2048,-2044,-2037,-2026,-2014,-2004,-1998,-1999,-2006,-2019,-2036,-2056,-2075,-2093,-2108,-2118,-2123,-2123,
--2116,-2105,-2090,-2072,-2052,-2034,-2018,-2005,-1994,-1986,-1977,-1968,-1956,-1942,-1928,-1917,-1911,-1910,-1913,-1918,-1922,
--1922,-1919,-1913,-1904,-1894,-1882,-1868,-1849,-1827,-1801,-1776,-1754,-1737,-1723,-1711,-1699,-1684,-1668,-1651,-1635,-1623,
--1613,-1604,-1595,-1583,-1569,-1556,-1545,-1538,-1533,-1530,-1526,-1518,-1506,-1491,-1476,-1463,-1451,-1440,-1427,-1414,-1399,
--1384,-1372,-1363,-1357,-1352,-1342,-1323,-1294,-1255,-1209,-1162,-1121,-1090,-1073,-1069,-1074,-1083,-1091,-1093,-1090,-1082,
--1071,-1062,-1055,-1052,-1049,-1043,-1032,-1013,-989,-961,-934,-911,-893,-879,-868,-857,-846,-833,-818,-803,-786,
--768,-749,-729,-709,-688,-668,-650,-634,-620,-606,-593,-580,-566,-551,-534,-512,-487,-458,-426,-394,-364,
--336,-312,-291,-273,-255,-238,-220,-201,-181,-161,-140,-120,-102,-86,-71,-57,-41,-21,3,32,66,
-102,137,170,202,232,262,290,319,347,374,401,429,458,490,525,562,602,645,691,741,794,
-847,900,948,992,1030,1064,1096,1129,1162,1194,1224,1251,1275,1299,1324,1352,1384,1418,1452,1482,1510,
-1536,1562,1589,1617,1645,1668,1683,1689,1689,1686,1686,1693,1708,1730,1756,1783,1810,1837,1864,1893,1921,
-1948,1969,1982,1985,1980,1971,1962,1959,1963,1973,1988,2002,2013,2019,2020,2018,2014,2014,2016,2022,2031,
-2038,2043,2042,2034,2022,2006,1992,1982,1979,1983,1993,2004,2012,2012,2005,1992,1978,1967,1961,1962,1967,
-1973,1977,1976,1971,1965,1960,1960,1964,1972,1983,1997,2013,2031,2053,2075,2094,2108,2113,2110,2098,2084,
-2070,2059,2052,2046,2040,2031,2019,2004,1989,1976,1964,1956,1950,1946,1944,1944,1947,1950,1953,1954,1954,
-1954,1957,1964,1976,1988,1999,2005,2007,2007,2008,2014,2027,2045,2066,2087,2106,2122,2137,2150,2162,2171,
-2177,2181,2185,2192,2204,2221,2239,2256,2268,2275,2282,2295,2316,2343,2372,2394,2405,2405,2398,2394,2397,
-2406,2416,2418,2406,2380,2347,2316,2294,2281,2269,2250,2218,2177,2135,2103,2079,2052,1998,1895,1730,1517,
-1289,1097,985,978,1072,1237,1426,1598,1725,1803,1844,1869,1893,1921,1951,1974,1986,1988,1986,1987,1995,
-2008,2022,2034,2040,2043,2046,2052,2059,2064,2064,2059,2051,2045,2045,2051,2058,2057,2042,2013,1975,1938,
-1911,1899,1901,1912,1922,1926,1922,1913,1903,1897,1896,1899,1903,1907,1910,1913,1919,1926,1934,1940,1942,
-1941,1938,1934,1932,1930,1927,1924,1920,1917,1919,1925,1936,1948,1957,1960,1954,1943,1929,1918,1912,1911,
-1913,1917,1920,1922,1925,1927,1930,1932,1934,1935,1935,1937,1939,1944,1947,1866,1869,1869,1866,1860,1852,
-1844,1838,1834,1830,1826,1820,1812,1802,1791,1782,1774,1768,1763,1761,1761,1764,1768,1773,1777,1780,1783,
-1788,1795,1807,1822,1837,1851,1860,1865,1867,1868,1871,1875,1883,1892,1904,1918,1934,1953,1975,1999,2023,
-2045,2066,2084,2103,2121,2140,2160,2180,2200,2221,2244,2268,2294,2317,2336,2349,2356,2361,2367,2378,2393,
-2413,2433,2452,2469,2483,2499,2516,2535,2553,2567,2576,2579,2582,2587,2598,2616,2636,2654,2666,2670,2670,
-2671,2678,2694,2717,2742,2764,2779,2786,2789,2790,2791,2796,2801,2809,2818,2831,2849,2873,2902,2931,2954,
-2970,2978,2980,2983,2990,3003,3021,3039,3054,3064,3071,3076,3084,3096,3110,3125,3139,3152,3164,3177,3194,
-3214,3235,3256,3272,3285,3294,3301,3309,3318,3328,3337,3346,3354,3361,3370,3381,3395,3411,3428,3444,3460,
-3475,3490,3505,3521,3536,3551,3566,3581,3594,3605,3614,3618,3619,3618,3615,3614,3615,3618,3623,3628,3632,
-3634,3636,3637,3639,3642,3645,3648,3650,3650,3648,3646,3642,3637,3630,3621,3609,3597,3583,3571,3559,3547,
-3535,3521,3506,3489,3473,3459,3449,3444,3442,3444,3447,3450,3450,3450,3448,3445,3443,3440,3439,3438,3437,
-3438,3438,3439,3438,3435,3428,3419,3408,3398,3391,3386,3386,3386,3387,3387,3386,3384,3383,3382,3381,3379,
-3374,3367,3358,3350,3343,3337,3332,3327,3318,3307,3295,3284,3275,3268,3260,3249,3233,3213,3192,3174,3164,
-3162,3167,3175,3182,3187,3189,3192,3196,3204,3215,3226,3234,3235,3229,3218,3202,3184,3162,3136,3108,3077,
-3049,3024,3006,2995,2986,2978,2966,2950,2932,2916,2907,2909,2922,2944,2969,2994,3015,3031,3041,3048,3053,
-3055,3057,3057,3054,3050,3042,3030,3015,2996,2973,2947,2920,2892,2865,2837,2808,2776,2741,2704,2665,2628,
-2594,2564,2539,2516,2495,2473,2446,2414,2375,2326,2268,2201,2127,2050,1972,1896,1824,1758,1696,1640,1587,
-1539,1497,1460,1429,1403,1380,1360,1339,1319,1299,1278,1255,1231,1205,1176,1146,1115,1086,1060,1037,1016,
-994,970,942,912,880,847,815,785,754,723,692,662,632,603,576,551,525,499,470,440,407,
-372,335,296,255,213,170,129,91,55,22,-9,-39,-69,-96,-122,-145,-168,-191,-216,-244,-275,
--308,-340,-372,-403,-433,-465,-499,-534,-569,-603,-634,-660,-684,-705,-726,-746,-767,-787,-806,-826,-847,
--871,-897,-926,-957,-989,-1021,-1054,-1087,-1119,-1152,-1183,-1211,-1237,-1261,-1284,-1308,-1335,-1364,-1395,-1428,-1460,
--1492,-1523,-1553,-1582,-1611,-1638,-1664,-1691,-1717,-1745,-1775,-1805,-1835,-1864,-1890,-1914,-1936,-1959,-1983,-2009,-2037,
--2064,-2090,-2113,-2133,-2153,-2173,-2195,-2218,-2242,-2267,-2291,-2313,-2334,-2354,-2373,-2392,-2411,-2432,-2453,-2474,-2494,
--2513,-2531,-2546,-2560,-2575,-2591,-2609,-2629,-2649,-2668,-2686,-2701,-2716,-2730,-2745,-2761,-2778,-2795,-2812,-2828,-2843,
--2858,-2871,-2883,-2893,-2903,-2911,-2920,-2929,-2939,-2949,-2958,-2965,-2971,-2974,-2977,-2979,-2983,-2987,-2991,-2994,-2996,
--2997,-2998,-2999,-3001,-3005,-3009,-3012,-3014,-3013,-3012,-3010,-3009,-3010,-3014,-3017,-3021,-3023,-3023,-3022,-3019,-3016,
--3011,-3004,-2997,-2989,-2982,-2977,-2975,-2975,-2978,-2979,-2978,-2972,-2961,-2946,-2928,-2909,-2893,-2881,-2872,-2866,-2861,
--2857,-2850,-2843,-2834,-2825,-2819,-2814,-2810,-2804,-2796,-2783,-2769,-2755,-2746,-2743,-2744,-2748,-2749,-2744,-2731,-2713,
--2695,-2681,-2674,-2674,-2677,-2680,-2681,-2679,-2675,-2672,-2671,-2671,-2675,-2682,-2695,-2715,-2744,-2777,-2810,-2834,-2844,
--2841,-2830,-2821,-2822,-2835,-2856,-2876,-2884,-2877,-2865,-2862,-2887,-2952,-3055,-3179,-3298,-3385,-3422,-3409,-3360,-3297,
--3245,-3219,-3222,-3248,-3285,-3321,-3349,-3370,-3388,-3408,-3435,-3468,-3507,-3546,-3583,-3615,-3643,-3667,-3690,-3714,-3738,
--3762,-3787,-3811,-3833,-3856,-3879,-3904,-3931,-3958,-3984,-4006,-4024,-4038,-4051,-4066,-4086,-4112,-4142,-4174,-4204,-4228,
--4247,-4261,-4273,-4285,-4300,-4317,-4335,-4353,-4369,-4382,-4391,-4397,-4400,-4401,-4402,-4402,-4403,-4406,-4411,-4417,-4423,
--4430,-4436,-4443,-4449,-4456,-4462,-4466,-4467,-4465,-4461,-4456,-4452,-4449,-4446,-4441,-4434,-4426,-4419,-4414,-4413,-4416,
--4420,-4424,-4423,-4420,-4414,-4409,-4405,-4405,-4405,-4402,-4394,-4380,-4361,-4342,-4325,-4312,-4305,-4301,-4298,-4294,-4288,
--4282,-4277,-4274,-4270,-4265,-4258,-4249,-4238,-4226,-4216,-4207,-4199,-4190,-4180,-4167,-4154,-4142,-4131,-4121,-4111,-4100,
--4087,-4074,-4060,-4047,-4036,-4025,-4012,-3996,-3977,-3957,-3937,-3920,-3907,-3897,-3888,-3877,-3865,-3850,-3835,-3820,-3807,
--3794,-3779,-3762,-3741,-3719,-3696,-3675,-3655,-3638,-3620,-3601,-3580,-3558,-3536,-3515,-3496,-3479,-3465,-3450,-3436,-3422,
--3409,-3395,-3382,-3368,-3353,-3338,-3322,-3306,-3292,-3279,-3268,-3257,-3246,-3233,-3219,-3204,-3189,-3174,-3159,-3143,-3128,
--3112,-3097,-3082,-3067,-3054,-3041,-3028,-3016,-3004,-2994,-2986,-2979,-2972,-2964,-2955,-2946,-2937,-2929,-2923,-2920,-2918,
--2917,-2914,-2910,-2904,-2897,-2891,-2886,-2882,-2878,-2874,-2870,-2865,-2859,-2853,-2848,-2843,-2839,-2835,-2831,-2827,-2822,
--2817,-2811,-2806,-2801,-2796,-2793,-2789,-2786,-2782,-2778,-2772,-2766,-2758,-2750,-2740,-2731,-2721,-2711,-2701,-2693,-2687,
--2683,-2680,-2677,-2674,-2670,-2664,-2658,-2651,-2645,-2640,-2636,-2633,-2632,-2633,-2635,-2637,-2638,-2637,-2632,-2623,-2609,
--2591,-2571,-2549,-2526,-2503,-2481,-2459,-2437,-2418,-2400,-2384,-2371,-2359,-2349,-2341,-2333,-2326,-2319,-2313,-2306,-2298,
--2290,-2280,-2269,-2258,-2246,-2234,-2223,-2212,-2203,-2198,-2197,-2201,-2207,-2214,-2218,-2219,-2214,-2207,-2197,-2187,-2178,
--2169,-2162,-2153,-2144,-2134,-2124,-2114,-2105,-2097,-2090,-2083,-2078,-2074,-2073,-2075,-2078,-2082,-2083,-2080,-2074,-2065,
--2054,-2045,-2040,-2041,-2048,-2061,-2080,-2101,-2124,-2145,-2162,-2174,-2181,-2183,-2181,-2175,-2167,-2157,-2144,-2130,-2114,
--2097,-2081,-2063,-2045,-2025,-2004,-1983,-1963,-1947,-1936,-1929,-1927,-1928,-1929,-1931,-1934,-1937,-1939,-1938,-1933,-1920,
--1900,-1873,-1842,-1812,-1786,-1763,-1744,-1726,-1708,-1690,-1672,-1657,-1645,-1636,-1629,-1622,-1612,-1600,-1588,-1576,-1568,
--1563,-1560,-1558,-1552,-1543,-1532,-1518,-1504,-1490,-1476,-1461,-1445,-1428,-1413,-1400,-1392,-1387,-1382,-1372,-1354,-1326,
--1289,-1247,-1205,-1170,-1147,-1135,-1135,-1141,-1147,-1150,-1147,-1137,-1122,-1107,-1094,-1085,-1081,-1079,-1075,-1066,-1051,
--1030,-1005,-978,-954,-933,-917,-903,-892,-881,-871,-859,-846,-831,-814,-794,-772,-747,-720,-693,-668,-644,
--624,-607,-594,-583,-572,-562,-548,-532,-511,-486,-459,-431,-404,-378,-354,-332,-310,-288,-265,-244,-223,
--202,-184,-167,-151,-137,-123,-109,-92,-73,-49,-21,11,45,79,113,145,175,204,234,264,295,
-325,356,386,417,448,480,515,550,587,626,667,711,758,807,858,909,959,1008,1054,1098,1139,
-1175,1205,1230,1249,1266,1285,1309,1339,1374,1414,1453,1490,1523,1552,1579,1605,1630,1652,1670,1681,1687,
-1690,1694,1701,1714,1731,1752,1772,1793,1815,1840,1869,1902,1936,1967,1988,1995,1989,1971,1949,1930,1918,
-1918,1929,1948,1970,1991,2008,2021,2029,2035,2039,2044,2049,2055,2059,2060,2057,2049,2036,2022,2009,2001,
-1999,2004,2012,2020,2023,2019,2010,1999,1990,1986,1988,1994,1999,2001,1998,1990,1980,1973,1972,1976,1986,
-1998,2010,2022,2034,2048,2065,2084,2101,2115,2121,2119,2112,2101,2089,2077,2065,2052,2037,2020,2003,1988,
-1975,1967,1960,1955,1949,1945,1943,1945,1950,1958,1967,1973,1976,1978,1981,1988,1999,2011,2020,2025,2025,
-2023,2021,2026,2037,2055,2076,2097,2115,2132,2146,2161,2174,2185,2191,2193,2193,2194,2202,2216,2235,2256,
-2274,2287,2296,2305,2319,2338,2360,2381,2397,2405,2409,2410,2412,2415,2416,2409,2393,2370,2345,2325,2311,
-2303,2292,2272,2239,2198,2156,2118,2082,2036,1960,1836,1659,1446,1230,1057,967,977,1080,1245,1428,1592,
-1714,1790,1834,1862,1890,1921,1954,1982,2000,2011,2017,2026,2037,2051,2062,2070,2073,2076,2082,2093,2106,
-2116,2119,2114,2104,2096,2096,2106,2119,2130,2128,2111,2082,2049,2022,2007,2004,2008,2013,2011,2003,1989,
-1977,1968,1966,1968,1972,1974,1974,1972,1969,1966,1963,1959,1952,1943,1932,1920,1910,1900,1890,1880,1870,
-1863,1859,1861,1867,1875,1882,1885,1882,1875,1867,1861,1858,1858,1859,1859,1859,1859,1860,1863,1867,1871,
-1872,1871,1868,1865,1863,1864,1866,1782,1788,1791,1791,1785,1776,1766,1756,1750,1746,1745,1744,1743,1741,
-1739,1736,1734,1733,1733,1736,1741,1748,1755,1761,1766,1769,1770,1772,1777,1785,1796,1809,1823,1834,1844,
-1851,1858,1866,1875,1887,1901,1916,1933,1952,1973,1996,2020,2044,2067,2089,2110,2131,2153,2175,2196,2215,
-2233,2248,2264,2280,2298,2317,2334,2349,2362,2372,2381,2392,2406,2422,2439,2455,2469,2483,2496,2510,2525,
-2539,2552,2563,2572,2580,2590,2601,2613,2625,2633,2639,2643,2649,2661,2679,2703,2728,2750,2765,2771,2771,
-2767,2765,2765,2771,2780,2792,2807,2826,2849,2875,2900,2922,2938,2946,2949,2951,2956,2966,2981,2997,3011,
-3020,3024,3025,3027,3033,3042,3055,3069,3082,3095,3109,3125,3146,3170,3194,3217,3235,3249,3259,3269,3279,
-3289,3299,3308,3314,3320,3326,3334,3345,3359,3374,3390,3404,3417,3430,3444,3459,3476,3492,3508,3522,3536,
-3548,3561,3571,3580,3586,3589,3589,3589,3588,3589,3591,3593,3595,3595,3595,3595,3596,3599,3603,3607,3609,
-3610,3608,3604,3599,3594,3587,3579,3569,3557,3543,3528,3514,3500,3487,3474,3459,3444,3430,3417,3409,3404,
-3405,3408,3412,3415,3417,3417,3416,3414,3413,3412,3412,3413,3414,3415,3414,3413,3408,3401,3391,3379,3369,
-3361,3358,3358,3359,3361,3361,3359,3356,3354,3354,3357,3359,3360,3357,3351,3342,3333,3326,3320,3316,3310,
-3301,3289,3274,3260,3248,3237,3227,3214,3197,3176,3155,3139,3132,3135,3147,3162,3175,3184,3187,3187,3187,
-3191,3197,3204,3209,3209,3202,3190,3173,3154,3132,3107,3080,3050,3022,2998,2979,2967,2960,2953,2943,2930,
-2914,2901,2893,2895,2908,2928,2951,2973,2991,3003,3011,3016,3018,3018,3016,3011,3002,2991,2979,2967,2954,
-2939,2922,2901,2877,2850,2822,2794,2767,2739,2709,2677,2642,2606,2571,2540,2514,2494,2478,2464,2447,2426,
-2398,2360,2313,2255,2187,2110,2027,1940,1854,1772,1695,1627,1568,1517,1474,1437,1405,1375,1348,1323,1301,
-1281,1262,1245,1227,1208,1185,1158,1127,1095,1062,1030,1001,974,948,924,900,876,851,825,798,767,
-734,699,662,626,593,563,536,512,488,462,435,405,373,338,301,262,221,181,141,104,69,
-37,5,-24,-55,-86,-115,-143,-167,-191,-214,-239,-268,-299,-332,-365,-397,-428,-458,-490,-522,-557,
--592,-625,-655,-681,-703,-722,-741,-759,-778,-797,-817,-838,-860,-883,-910,-938,-969,-1001,-1033,-1065,-1098,
--1129,-1160,-1191,-1219,-1247,-1273,-1300,-1327,-1354,-1384,-1413,-1443,-1473,-1503,-1532,-1561,-1591,-1620,-1648,-1675,-1702,
--1728,-1755,-1784,-1814,-1844,-1874,-1902,-1927,-1951,-1974,-1998,-2024,-2050,-2078,-2104,-2129,-2152,-2173,-2194,-2216,-2239,
--2263,-2288,-2313,-2337,-2359,-2379,-2398,-2416,-2434,-2454,-2474,-2497,-2519,-2540,-2559,-2576,-2590,-2604,-2618,-2634,-2653,
--2673,-2693,-2713,-2730,-2746,-2761,-2775,-2791,-2807,-2824,-2841,-2858,-2873,-2888,-2901,-2913,-2924,-2934,-2944,-2954,-2964,
--2974,-2985,-2995,-3005,-3013,-3020,-3027,-3032,-3038,-3043,-3046,-3048,-3048,-3047,-3046,-3047,-3050,-3055,-3061,-3066,-3069,
--3070,-3068,-3066,-3063,-3062,-3064,-3066,-3070,-3074,-3077,-3078,-3079,-3077,-3074,-3069,-3062,-3055,-3048,-3042,-3039,-3037,
--3036,-3036,-3034,-3029,-3020,-3008,-2993,-2977,-2962,-2949,-2938,-2930,-2923,-2917,-2909,-2901,-2892,-2883,-2877,-2873,-2871,
--2868,-2862,-2851,-2836,-2821,-2809,-2803,-2802,-2805,-2807,-2805,-2796,-2782,-2765,-2749,-2738,-2731,-2727,-2725,-2722,-2719,
--2717,-2715,-2716,-2716,-2718,-2721,-2729,-2745,-2771,-2806,-2844,-2877,-2896,-2900,-2890,-2875,-2866,-2870,-2885,-2906,-2922,
--2925,-2916,-2904,-2905,-2934,-3000,-3097,-3210,-3315,-3394,-3432,-3431,-3401,-3361,-3328,-3311,-3314,-3333,-3361,-3392,-3421,
--3448,-3474,-3503,-3534,-3567,-3601,-3632,-3660,-3685,-3709,-3734,-3760,-3788,-3816,-3843,-3868,-3890,-3911,-3931,-3953,-3976,
--4000,-4023,-4043,-4061,-4076,-4091,-4108,-4128,-4153,-4180,-4208,-4233,-4255,-4273,-4290,-4306,-4324,-4343,-4364,-4385,-4404,
--4421,-4435,-4445,-4453,-4457,-4460,-4461,-4462,-4464,-4468,-4473,-4480,-4487,-4494,-4501,-4507,-4514,-4520,-4526,-4529,-4529,
--4526,-4521,-4515,-4510,-4506,-4501,-4496,-4489,-4480,-4472,-4465,-4461,-4460,-4460,-4460,-4457,-4451,-4445,-4441,-4440,-4443,
--4447,-4449,-4447,-4438,-4423,-4404,-4384,-4366,-4351,-4339,-4329,-4320,-4312,-4306,-4302,-4298,-4294,-4290,-4283,-4275,-4266,
--4258,-4251,-4245,-4239,-4230,-4219,-4205,-4190,-4176,-4164,-4154,-4146,-4137,-4129,-4119,-4108,-4097,-4086,-4073,-4058,-4040,
--4019,-3997,-3977,-3961,-3949,-3940,-3932,-3922,-3910,-3896,-3881,-3866,-3852,-3839,-3825,-3809,-3791,-3770,-3748,-3727,-3708,
--3691,-3674,-3656,-3637,-3617,-3596,-3575,-3555,-3536,-3518,-3501,-3485,-3470,-3456,-3444,-3432,-3419,-3404,-3388,-3371,-3354,
--3337,-3323,-3310,-3298,-3286,-3274,-3261,-3247,-3234,-3220,-3207,-3193,-3179,-3165,-3151,-3137,-3124,-3110,-3096,-3082,-3068,
--3055,-3043,-3033,-3025,-3018,-3011,-3005,-2997,-2991,-2985,-2981,-2978,-2976,-2974,-2970,-2964,-2957,-2950,-2945,-2941,-2938,
--2936,-2934,-2930,-2924,-2916,-2908,-2900,-2893,-2887,-2882,-2877,-2872,-2867,-2861,-2855,-2849,-2844,-2841,-2838,-2836,-2834,
--2832,-2830,-2826,-2821,-2816,-2810,-2803,-2795,-2786,-2776,-2765,-2754,-2744,-2735,-2729,-2723,-2719,-2713,-2706,-2698,-2688,
--2677,-2667,-2659,-2653,-2650,-2650,-2652,-2655,-2659,-2662,-2664,-2663,-2658,-2649,-2636,-2620,-2601,-2582,-2563,-2544,-2526,
--2509,-2492,-2476,-2460,-2443,-2428,-2414,-2402,-2391,-2380,-2370,-2360,-2350,-2340,-2330,-2322,-2314,-2307,-2298,-2289,-2279,
--2269,-2261,-2256,-2255,-2257,-2261,-2263,-2262,-2259,-2254,-2247,-2240,-2233,-2227,-2219,-2210,-2200,-2190,-2179,-2169,-2160,
--2150,-2140,-2129,-2119,-2110,-2106,-2105,-2107,-2111,-2116,-2118,-2118,-2115,-2109,-2104,-2100,-2099,-2102,-2111,-2124,-2139,
--2156,-2172,-2186,-2196,-2204,-2211,-2217,-2223,-2229,-2232,-2231,-2224,-2212,-2197,-2179,-2160,-2140,-2119,-2096,-2071,-2044,
--2018,-1994,-1973,-1957,-1946,-1939,-1937,-1938,-1942,-1948,-1953,-1955,-1950,-1938,-1920,-1898,-1874,-1852,-1831,-1812,-1793,
--1771,-1747,-1723,-1701,-1683,-1671,-1662,-1654,-1646,-1635,-1622,-1610,-1599,-1592,-1588,-1584,-1580,-1573,-1563,-1551,-1538,
--1524,-1510,-1495,-1478,-1460,-1443,-1427,-1415,-1405,-1396,-1384,-1367,-1345,-1318,-1289,-1262,-1243,-1232,-1229,-1231,-1234,
--1234,-1228,-1215,-1197,-1176,-1155,-1137,-1124,-1114,-1106,-1099,-1089,-1075,-1058,-1037,-1015,-993,-973,-955,-940,-926,
--915,-904,-893,-882,-869,-852,-833,-810,-783,-753,-722,-692,-663,-637,-616,-600,-587,-577,-566,-555,-540,
--523,-503,-482,-461,-441,-421,-401,-380,-357,-332,-306,-280,-256,-235,-216,-199,-184,-169,-153,-135,-114,
--90,-63,-33,-2,29,60,90,119,148,176,205,235,266,298,330,364,399,435,472,509,547,
-583,620,656,694,735,779,826,875,926,977,1028,1077,1123,1164,1198,1226,1248,1267,1288,1314,1345,
-1381,1419,1457,1492,1523,1551,1577,1602,1626,1647,1665,1679,1688,1696,1704,1715,1729,1745,1763,1779,1796,
-1813,1834,1859,1888,1918,1943,1960,1964,1957,1942,1923,1908,1899,1899,1909,1925,1947,1971,1996,2020,2040,
-2056,2066,2071,2072,2069,2065,2060,2055,2050,2044,2039,2036,2035,2038,2043,2047,2050,2047,2041,2032,2024,
-2020,2021,2025,2029,2029,2023,2011,1998,1989,1987,1993,2005,2020,2032,2039,2042,2043,2045,2050,2060,2071,
-2082,2089,2094,2096,2097,2096,2091,2082,2066,2045,2020,1998,1981,1971,1967,1964,1959,1951,1941,1931,1928,
-1931,1942,1957,1972,1986,1997,2007,2018,2031,2042,2051,2053,2050,2044,2039,2039,2047,2062,2080,2098,2114,
-2129,2142,2157,2172,2186,2195,2198,2198,2196,2200,2211,2229,2253,2275,2294,2306,2315,2322,2332,2345,2361,
-2376,2389,2399,2406,2410,2410,2406,2395,2379,2359,2340,2326,2317,2310,2298,2276,2240,2191,2134,2071,1999,
-1911,1794,1641,1458,1264,1092,975,942,997,1127,1299,1474,1624,1731,1798,1839,1868,1899,1934,1971,2003,
-2027,2044,2057,2069,2080,2089,2093,2091,2086,2083,2087,2098,2112,2124,2126,2118,2104,2090,2086,2093,2108,
-2124,2132,2127,2109,2086,2064,2049,2042,2041,2039,2033,2021,2007,1995,1988,1986,1989,1992,1991,1986,1977,
-1966,1956,1946,1938,1928,1917,1905,1891,1878,1864,1851,1838,1825,1815,1808,1804,1804,1804,1805,1803,1800,
-1796,1794,1796,1799,1803,1806,1804,1800,1795,1791,1790,1791,1793,1794,1792,1787,1782,1778,1779,1782,1697,
-1706,1714,1717,1713,1703,1691,1679,1669,1665,1665,1668,1673,1678,1683,1689,1695,1702,1710,1719,1728,1738,
-1747,1754,1759,1763,1766,1770,1776,1785,1797,1810,1824,1838,1850,1861,1872,1884,1897,1911,1926,1942,1960,
-1979,2000,2022,2046,2070,2094,2117,2140,2163,2186,2209,2230,2248,2263,2275,2286,2297,2309,2324,2341,2357,
-2373,2387,2400,2413,2426,2439,2453,2466,2478,2489,2498,2507,2517,2528,2540,2553,2565,2578,2589,2599,2606,
-2610,2614,2618,2626,2639,2659,2683,2708,2729,2741,2745,2742,2735,2730,2730,2736,2749,2765,2785,2805,2827,
-2849,2870,2889,2903,2912,2918,2922,2927,2937,2950,2965,2978,2986,2988,2985,2981,2980,2983,2991,3002,3015,
-3028,3042,3059,3079,3104,3130,3156,3179,3197,3211,3223,3234,3246,3258,3268,3276,3281,3286,3292,3300,3313,
-3327,3342,3355,3366,3376,3388,3402,3418,3437,3454,3470,3483,3494,3505,3517,3530,3543,3554,3561,3564,3564,
-3562,3561,3561,3562,3563,3564,3564,3564,3564,3565,3568,3570,3570,3568,3564,3559,3554,3550,3546,3540,3533,
-3521,3506,3488,3468,3450,3433,3418,3405,3394,3384,3377,3372,3371,3372,3375,3379,3382,3385,3386,3386,3386,
-3387,3388,3389,3390,3390,3390,3389,3385,3379,3370,3358,3346,3335,3328,3326,3326,3329,3331,3331,3328,3326,
-3325,3327,3331,3336,3339,3338,3333,3324,3316,3310,3305,3302,3296,3287,3272,3254,3235,3218,3203,3190,3176,
-3160,3142,3125,3111,3107,3111,3124,3139,3154,3163,3167,3168,3168,3170,3174,3178,3179,3176,3167,3154,3138,
-3120,3102,3081,3058,3033,3007,2984,2966,2953,2944,2937,2928,2915,2900,2887,2880,2881,2891,2907,2926,2941,
-2952,2956,2955,2951,2946,2940,2934,2927,2919,2911,2903,2896,2889,2880,2867,2848,2825,2797,2769,2742,2716,
-2691,2665,2637,2605,2571,2538,2509,2487,2471,2462,2454,2446,2434,2416,2390,2355,2310,2253,2184,2103,2011,
-1914,1815,1721,1636,1563,1502,1451,1408,1370,1335,1303,1273,1247,1226,1208,1194,1180,1164,1146,1123,1096,
-1066,1033,1000,968,937,908,881,857,835,813,789,763,734,700,663,626,589,556,526,499,474,
-448,422,394,363,331,297,261,223,185,146,108,73,40,8,-21,-51,-83,-115,-146,-176,-203,
--227,-250,-273,-298,-326,-355,-386,-418,-450,-482,-516,-551,-586,-620,-652,-678,-700,-717,-732,-746,-762,
--779,-799,-821,-844,-870,-898,-927,-957,-988,-1018,-1049,-1078,-1108,-1137,-1167,-1196,-1226,-1257,-1287,-1317,-1347,
--1377,-1407,-1436,-1465,-1492,-1520,-1547,-1575,-1603,-1632,-1660,-1688,-1714,-1742,-1770,-1798,-1829,-1860,-1890,-1919,-1946,
--1971,-1995,-2019,-2044,-2070,-2097,-2123,-2149,-2174,-2197,-2218,-2239,-2260,-2282,-2305,-2329,-2353,-2377,-2400,-2422,-2442,
--2461,-2480,-2500,-2521,-2542,-2563,-2582,-2599,-2615,-2629,-2643,-2659,-2677,-2697,-2717,-2737,-2755,-2771,-2786,-2801,-2817,
--2834,-2852,-2869,-2887,-2903,-2917,-2931,-2943,-2955,-2966,-2977,-2987,-2998,-3009,-3020,-3031,-3042,-3053,-3064,-3073,-3082,
--3089,-3095,-3098,-3099,-3099,-3099,-3099,-3100,-3103,-3108,-3113,-3117,-3120,-3121,-3121,-3120,-3119,-3118,-3119,-3121,-3124,
--3128,-3131,-3133,-3134,-3133,-3131,-3127,-3122,-3117,-3113,-3110,-3107,-3105,-3101,-3097,-3090,-3082,-3071,-3060,-3047,-3035,
--3022,-3010,-2999,-2989,-2980,-2972,-2963,-2954,-2945,-2938,-2933,-2931,-2930,-2929,-2925,-2916,-2902,-2887,-2873,-2864,-2861,
--2862,-2864,-2864,-2859,-2849,-2835,-2821,-2808,-2797,-2788,-2779,-2771,-2764,-2759,-2757,-2757,-2758,-2759,-2761,-2766,-2777,
--2798,-2830,-2868,-2905,-2932,-2942,-2936,-2921,-2905,-2899,-2907,-2926,-2948,-2962,-2963,-2954,-2943,-2945,-2973,-3031,-3115,
--3212,-3304,-3375,-3417,-3430,-3422,-3405,-3391,-3386,-3394,-3414,-3440,-3471,-3503,-3534,-3565,-3596,-3626,-3653,-3678,-3701,
--3723,-3745,-3768,-3795,-3824,-3854,-3883,-3911,-3936,-3958,-3980,-4001,-4022,-4043,-4063,-4082,-4101,-4119,-4138,-4158,-4180,
--4203,-4225,-4246,-4265,-4282,-4300,-4319,-4341,-4364,-4389,-4412,-4433,-4451,-4465,-4477,-4487,-4496,-4502,-4508,-4512,-4516,
--4520,-4526,-4532,-4539,-4546,-4552,-4557,-4562,-4566,-4570,-4574,-4576,-4575,-4572,-4568,-4562,-4558,-4554,-4551,-4548,-4542,
--4535,-4526,-4517,-4510,-4505,-4501,-4497,-4492,-4486,-4480,-4476,-4475,-4478,-4483,-4487,-4487,-4482,-4470,-4454,-4435,-4416,
--4397,-4380,-4366,-4353,-4343,-4336,-4330,-4327,-4323,-4319,-4313,-4306,-4298,-4292,-4286,-4282,-4277,-4270,-4260,-4248,-4234,
--4220,-4207,-4195,-4185,-4175,-4165,-4155,-4144,-4134,-4124,-4113,-4099,-4082,-4063,-4042,-4023,-4006,-3992,-3982,-3972,-3962,
--3949,-3935,-3921,-3906,-3893,-3880,-3867,-3852,-3835,-3816,-3796,-3775,-3754,-3735,-3717,-3699,-3682,-3665,-3647,-3630,-3613,
--3596,-3578,-3559,-3541,-3524,-3509,-3496,-3483,-3471,-3457,-3441,-3424,-3407,-3389,-3373,-3358,-3343,-3329,-3315,-3301,-3287,
--3274,-3262,-3250,-3238,-3227,-3215,-3202,-3190,-3178,-3166,-3153,-3140,-3127,-3113,-3101,-3090,-3080,-3072,-3064,-3057,-3051,
--3045,-3041,-3038,-3037,-3035,-3033,-3028,-3021,-3014,-3006,-3000,-2996,-2994,-2993,-2991,-2989,-2984,-2978,-2970,-2961,-2952,
--2944,-2937,-2930,-2923,-2916,-2909,-2903,-2897,-2893,-2889,-2886,-2884,-2882,-2880,-2877,-2874,-2871,-2868,-2864,-2861,-2856,
--2850,-2842,-2831,-2819,-2807,-2796,-2788,-2781,-2776,-2771,-2765,-2757,-2747,-2735,-2724,-2713,-2704,-2695,-2688,-2681,-2675,
--2670,-2667,-2665,-2665,-2665,-2664,-2660,-2654,-2646,-2636,-2625,-2614,-2603,-2592,-2579,-2565,-2549,-2532,-2515,-2501,-2488,
--2476,-2465,-2453,-2439,-2423,-2407,-2392,-2379,-2369,-2360,-2352,-2344,-2335,-2327,-2320,-2316,-2314,-2314,-2315,-2315,-2313,
--2308,-2303,-2297,-2291,-2285,-2279,-2272,-2264,-2255,-2246,-2236,-2226,-2216,-2206,-2194,-2181,-2169,-2159,-2152,-2149,-2149,
--2151,-2155,-2158,-2160,-2160,-2160,-2159,-2158,-2159,-2162,-2168,-2176,-2187,-2198,-2207,-2215,-2221,-2226,-2231,-2237,-2246,
--2255,-2262,-2266,-2264,-2257,-2247,-2235,-2223,-2211,-2198,-2182,-2162,-2138,-2110,-2080,-2051,-2023,-2000,-1980,-1964,-1953,
--1945,-1942,-1941,-1941,-1939,-1935,-1930,-1923,-1916,-1909,-1903,-1893,-1879,-1858,-1831,-1801,-1772,-1746,-1726,-1711,-1699,
--1689,-1677,-1663,-1648,-1634,-1623,-1615,-1608,-1602,-1595,-1586,-1576,-1566,-1555,-1544,-1531,-1517,-1501,-1483,-1464,-1446,
--1429,-1413,-1395,-1377,-1358,-1339,-1323,-1312,-1307,-1307,-1310,-1313,-1311,-1302,-1287,-1266,-1243,-1219,-1197,-1179,-1162,
--1148,-1133,-1119,-1104,-1088,-1070,-1052,-1032,-1011,-991,-971,-952,-936,-922,-911,-900,-890,-879,-865,-848,-828,
--804,-778,-749,-720,-691,-664,-641,-621,-605,-592,-579,-566,-551,-535,-519,-503,-488,-474,-460,-444,-425,
--402,-376,-348,-321,-295,-273,-253,-236,-219,-201,-180,-157,-131,-103,-74,-43,-13,16,45,74,103,
-131,160,188,216,244,273,305,340,378,419,461,502,540,576,610,643,678,717,759,804,851,
-898,946,993,1040,1086,1130,1171,1208,1240,1269,1298,1326,1356,1388,1421,1452,1481,1508,1534,1560,1588,
-1616,1643,1667,1686,1700,1710,1718,1726,1736,1747,1760,1773,1787,1802,1819,1837,1857,1876,1893,1906,1915,
-1920,1925,1929,1934,1939,1944,1948,1952,1958,1968,1983,2002,2023,2042,2055,2061,2061,2057,2052,2049,2049,
-2051,2056,2061,2065,2069,2072,2075,2077,2078,2077,2075,2074,2074,2077,2080,2080,2076,2065,2048,2029,2014,
-2008,2012,2024,2039,2051,2054,2048,2036,2020,2007,2000,1999,2001,2006,2012,2020,2032,2047,2062,2074,2077,
-2067,2047,2020,1993,1973,1962,1959,1959,1956,1947,1932,1917,1906,1905,1914,1932,1954,1976,1996,2014,2030,
-2045,2058,2066,2068,2064,2057,2050,2048,2053,2064,2078,2092,2105,2117,2130,2146,2165,2185,2201,2212,2217,
-2218,2220,2228,2242,2262,2285,2305,2319,2329,2335,2341,2348,2358,2369,2380,2389,2395,2397,2396,2389,2377,
-2360,2341,2322,2304,2289,2273,2253,2222,2177,2118,2045,1956,1849,1722,1571,1402,1227,1070,958,913,948,
-1056,1216,1396,1562,1693,1782,1836,1868,1895,1924,1959,1995,2027,2052,2071,2085,2097,2106,2110,2107,2098,
-2087,2080,2080,2088,2100,2108,2107,2095,2074,2053,2039,2037,2044,2055,2062,2060,2049,2033,2017,2004,1997,
-1992,1986,1976,1963,1948,1936,1930,1929,1932,1933,1931,1923,1912,1899,1887,1876,1867,1858,1847,1835,1822,
-1808,1794,1782,1771,1761,1753,1746,1741,1736,1730,1724,1717,1711,1709,1711,1717,1727,1736,1741,1740,1734,
-1724,1715,1709,1706,1705,1704,1701,1696,1691,1688,1691,1697,1618,1630,1642,1649,1650,1645,1635,1624,1616,
-1611,1610,1613,1618,1625,1634,1643,1655,1667,1681,1694,1706,1717,1726,1734,1741,1748,1756,1766,1778,1791,
-1806,1821,1836,1851,1866,1880,1895,1909,1924,1939,1955,1972,1989,2009,2031,2054,2079,2104,2129,2153,2176,
-2198,2219,2240,2258,2274,2287,2297,2306,2316,2329,2343,2360,2378,2396,2412,2427,2440,2454,2466,2478,2489,
-2498,2505,2511,2516,2522,2530,2539,2550,2562,2573,2582,2588,2591,2594,2597,2604,2617,2636,2658,2680,2698,
-2708,2709,2704,2696,2690,2691,2700,2716,2738,2761,2784,2806,2826,2844,2860,2873,2883,2890,2896,2903,2912,
-2925,2939,2952,2960,2961,2957,2950,2943,2940,2942,2949,2959,2971,2984,2999,3018,3042,3068,3095,3121,3142,
-3158,3172,3185,3199,3213,3227,3239,3247,3253,3259,3265,3275,3287,3300,3312,3321,3327,3334,3345,3359,3378,
-3399,3418,3433,3445,3454,3463,3475,3489,3505,3520,3529,3534,3533,3531,3528,3528,3529,3531,3533,3533,3533,
-3531,3531,3531,3532,3531,3529,3524,3519,3513,3508,3504,3500,3494,3482,3466,3446,3424,3402,3384,3369,3358,
-3351,3346,3344,3342,3343,3344,3346,3347,3349,3351,3353,3354,3357,3359,3360,3361,3361,3361,3360,3357,3353,
-3347,3339,3328,3316,3305,3298,3294,3294,3297,3299,3300,3300,3299,3300,3303,3309,3314,3318,3318,3314,3307,
-3300,3294,3290,3286,3280,3268,3251,3229,3206,3185,3168,3153,3141,3129,3117,3105,3097,3094,3097,3106,3117,
-3127,3133,3137,3139,3141,3145,3150,3154,3154,3150,3140,3126,3110,3093,3077,3060,3041,3020,2998,2978,2961,
-2948,2938,2928,2917,2901,2884,2867,2855,2851,2856,2867,2881,2892,2898,2896,2889,2879,2868,2859,2851,2846,
-2843,2841,2841,2842,2840,2835,2824,2805,2781,2752,2722,2693,2667,2643,2618,2592,2565,2538,2513,2494,2480,
-2471,2465,2458,2448,2434,2415,2392,2365,2332,2291,2237,2168,2083,1986,1881,1775,1676,1587,1511,1448,1394,
-1347,1304,1265,1230,1200,1175,1155,1138,1123,1107,1090,1069,1045,1018,990,961,932,902,874,846,819,
-794,768,741,712,680,647,612,578,546,516,489,463,436,409,380,349,317,285,253,220,186,
-150,113,77,41,8,-23,-54,-86,-118,-151,-184,-216,-245,-271,-293,-313,-334,-355,-380,-407,-438,
--471,-507,-544,-581,-618,-651,-679,-702,-719,-731,-742,-752,-765,-781,-801,-825,-852,-882,-913,-944,-976,
--1006,-1036,-1064,-1091,-1118,-1145,-1173,-1202,-1232,-1263,-1295,-1327,-1358,-1389,-1420,-1450,-1480,-1508,-1536,-1563,-1591,
--1618,-1645,-1672,-1700,-1728,-1757,-1787,-1818,-1849,-1881,-1911,-1940,-1967,-1993,-2018,-2043,-2068,-2093,-2119,-2145,-2171,
--2196,-2219,-2242,-2262,-2283,-2303,-2323,-2345,-2369,-2394,-2419,-2444,-2467,-2488,-2508,-2527,-2545,-2564,-2583,-2602,-2619,
--2636,-2651,-2667,-2684,-2702,-2721,-2740,-2758,-2774,-2789,-2803,-2817,-2833,-2850,-2870,-2890,-2910,-2929,-2947,-2963,-2977,
--2990,-3002,-3014,-3024,-3034,-3044,-3054,-3065,-3076,-3088,-3101,-3113,-3123,-3132,-3138,-3143,-3146,-3149,-3152,-3156,-3159,
--3163,-3166,-3169,-3170,-3171,-3171,-3172,-3173,-3174,-3176,-3178,-3181,-3183,-3186,-3187,-3188,-3187,-3185,-3181,-3177,-3173,
--3171,-3171,-3173,-3174,-3174,-3170,-3163,-3152,-3140,-3127,-3114,-3102,-3091,-3080,-3069,-3059,-3049,-3040,-3030,-3021,-3012,
--3003,-2996,-2990,-2987,-2987,-2986,-2983,-2976,-2965,-2951,-2937,-2927,-2921,-2920,-2922,-2923,-2921,-2914,-2904,-2892,-2879,
--2866,-2854,-2841,-2828,-2816,-2807,-2801,-2800,-2801,-2803,-2806,-2810,-2818,-2835,-2861,-2894,-2930,-2960,-2978,-2979,-2968,
--2951,-2938,-2937,-2949,-2970,-2991,-3004,-3004,-2995,-2985,-2986,-3007,-3052,-3119,-3197,-3275,-3341,-3390,-3420,-3435,-3442,
--3448,-3457,-3472,-3492,-3516,-3544,-3573,-3603,-3632,-3659,-3685,-3707,-3728,-3747,-3767,-3790,-3815,-3844,-3876,-3908,-3940,
--3971,-3998,-4023,-4044,-4063,-4080,-4096,-4112,-4130,-4151,-4174,-4200,-4225,-4248,-4268,-4285,-4300,-4315,-4333,-4354,-4378,
--4405,-4430,-4452,-4471,-4485,-4497,-4508,-4518,-4528,-4537,-4545,-4552,-4558,-4565,-4572,-4581,-4590,-4597,-4603,-4608,-4611,
--4614,-4617,-4619,-4620,-4618,-4614,-4609,-4602,-4597,-4594,-4591,-4589,-4586,-4580,-4573,-4564,-4556,-4549,-4544,-4539,-4534,
--4529,-4523,-4517,-4513,-4511,-4511,-4510,-4507,-4501,-4492,-4478,-4463,-4447,-4431,-4416,-4403,-4391,-4381,-4373,-4368,-4364,
--4362,-4359,-4354,-4348,-4340,-4332,-4324,-4316,-4309,-4301,-4293,-4284,-4274,-4263,-4251,-4239,-4226,-4213,-4200,-4188,-4176,
--4166,-4156,-4147,-4135,-4121,-4104,-4086,-4067,-4049,-4033,-4020,-4008,-3997,-3985,-3972,-3960,-3947,-3934,-3921,-3908,-3894,
--3877,-3860,-3840,-3820,-3799,-3779,-3758,-3739,-3721,-3705,-3691,-3677,-3664,-3650,-3635,-3618,-3600,-3582,-3565,-3549,-3535,
--3521,-3507,-3491,-3475,-3459,-3443,-3427,-3411,-3396,-3380,-3364,-3348,-3333,-3319,-3307,-3295,-3283,-3272,-3260,-3248,-3236,
--3225,-3213,-3202,-3191,-3181,-3170,-3160,-3151,-3143,-3135,-3127,-3119,-3111,-3105,-3100,-3097,-3095,-3093,-3090,-3086,-3079,
--3071,-3062,-3055,-3049,-3045,-3043,-3042,-3040,-3037,-3033,-3028,-3021,-3014,-3006,-2998,-2991,-2984,-2977,-2970,-2963,-2956,
--2950,-2945,-2940,-2936,-2932,-2929,-2927,-2924,-2922,-2919,-2917,-2915,-2913,-2909,-2903,-2894,-2884,-2872,-2860,-2849,-2841,
--2834,-2828,-2823,-2816,-2809,-2801,-2792,-2783,-2774,-2763,-2751,-2738,-2723,-2709,-2696,-2687,-2682,-2680,-2680,-2679,-2677,
--2672,-2667,-2661,-2654,-2648,-2641,-2633,-2622,-2610,-2598,-2587,-2579,-2572,-2567,-2560,-2550,-2535,-2516,-2495,-2473,-2453,
--2435,-2420,-2407,-2395,-2385,-2376,-2371,-2368,-2368,-2370,-2371,-2371,-2367,-2362,-2354,-2346,-2338,-2332,-2325,-2319,-2313,
--2306,-2299,-2291,-2282,-2272,-2262,-2250,-2237,-2226,-2217,-2210,-2206,-2203,-2202,-2202,-2201,-2201,-2201,-2202,-2203,-2205,
--2207,-2210,-2215,-2221,-2228,-2237,-2245,-2252,-2256,-2258,-2259,-2261,-2263,-2266,-2267,-2267,-2265,-2260,-2255,-2250,-2246,
--2244,-2241,-2236,-2225,-2209,-2188,-2163,-2136,-2108,-2080,-2053,-2027,-2002,-1980,-1962,-1948,-1939,-1932,-1929,-1929,-1931,
--1935,-1942,-1947,-1948,-1943,-1929,-1907,-1878,-1847,-1818,-1793,-1774,-1759,-1745,-1730,-1714,-1696,-1679,-1663,-1650,-1639,
--1630,-1621,-1612,-1602,-1593,-1585,-1578,-1569,-1559,-1547,-1532,-1514,-1494,-1472,-1449,-1426,-1402,-1380,-1362,-1350,-1344,
--1345,-1349,-1354,-1354,-1348,-1334,-1314,-1291,-1268,-1247,-1229,-1213,-1197,-1179,-1160,-1139,-1118,-1098,-1078,-1058,-1038,
--1017,-995,-972,-951,-932,-916,-903,-894,-885,-875,-864,-851,-835,-816,-795,-772,-747,-722,-697,-675,-655,
--637,-621,-605,-589,-573,-556,-540,-525,-511,-498,-485,-470,-451,-429,-404,-378,-353,-329,-309,-290,-273,
--253,-232,-208,-180,-151,-121,-90,-60,-30,0,30,61,92,123,152,178,202,227,252,283,319,
-360,405,451,494,532,565,595,624,657,693,735,779,823,867,908,949,991,1036,1083,1132,1179,
-1224,1264,1299,1330,1358,1385,1412,1438,1464,1490,1517,1545,1576,1607,1639,1667,1691,1708,1720,1727,1732,
-1736,1742,1751,1762,1776,1792,1807,1822,1836,1848,1859,1873,1890,1913,1941,1971,2000,2021,2031,2029,2017,
-2002,1989,1984,1987,1998,2011,2023,2031,2034,2035,2037,2042,2050,2060,2070,2076,2079,2079,2077,2076,2078,
-2083,2091,2102,2114,2125,2133,2135,2128,2111,2086,2058,2033,2016,2011,2016,2026,2033,2032,2018,1995,1967,
-1941,1922,1910,1904,1900,1895,1890,1889,1894,1908,1929,1950,1964,1965,1952,1930,1907,1892,1889,1898,1913,
-1928,1936,1937,1932,1927,1929,1939,1956,1978,2001,2021,2038,2052,2064,2073,2077,2076,2069,2059,2049,2043,
-2044,2052,2064,2078,2093,2109,2126,2147,2171,2197,2220,2238,2249,2254,2256,2261,2270,2285,2302,2320,2334,
-2345,2352,2358,2363,2369,2376,2381,2385,2386,2384,2379,2370,2358,2342,2322,2298,2271,2241,2206,2165,2116,
-2056,1984,1897,1793,1670,1529,1373,1214,1069,959,907,925,1013,1159,1334,1510,1662,1773,1843,1883,1906,
-1927,1952,1982,2014,2043,2066,2083,2097,2109,2117,2120,2116,2107,2096,2088,2087,2092,2099,2103,2097,2080,
-2055,2028,2006,1993,1988,1988,1987,1980,1969,1954,1941,1931,1925,1920,1912,1900,1884,1868,1854,1845,1842,
-1841,1840,1836,1829,1819,1808,1799,1790,1782,1774,1764,1752,1739,1725,1712,1701,1692,1685,1679,1675,1671,
-1666,1660,1652,1643,1635,1631,1632,1639,1650,1660,1668,1670,1666,1658,1649,1642,1636,1632,1627,1621,1614,
-1607,1605,1609,1618,1553,1566,1580,1591,1598,1599,1595,1590,1584,1580,1579,1579,1582,1586,1594,1604,1617,
-1631,1647,1662,1675,1686,1695,1703,1712,1722,1735,1750,1766,1782,1800,1817,1834,1851,1868,1886,1904,1922,
-1939,1958,1976,1995,2016,2038,2063,2088,2115,2142,2167,2191,2213,2234,2252,2269,2284,2296,2306,2315,2325,
-2336,2349,2365,2383,2402,2420,2437,2452,2466,2479,2491,2502,2511,2518,2523,2526,2529,2531,2535,2541,2548,
-2556,2563,2568,2572,2575,2579,2587,2599,2615,2633,2651,2664,2670,2669,2663,2657,2653,2657,2669,2689,2712,
-2737,2760,2780,2798,2814,2828,2842,2853,2863,2870,2877,2886,2896,2908,2920,2929,2933,2932,2925,2918,2912,
-2910,2913,2920,2929,2939,2951,2966,2985,3008,3033,3059,3082,3102,3118,3133,3147,3163,3180,3196,3210,3220,
-3227,3234,3242,3252,3264,3274,3282,3287,3290,3295,3305,3320,3340,3362,3381,3396,3405,3412,3420,3431,3447,
-3464,3479,3489,3494,3494,3492,3490,3490,3492,3494,3495,3494,3490,3487,3486,3486,3488,3490,3490,3486,3480,
-3473,3465,3458,3451,3443,3432,3416,3398,3379,3361,3346,3335,3328,3324,3321,3320,3318,3317,3315,3314,3313,
-3313,3313,3314,3317,3320,3323,3325,3326,3325,3322,3320,3316,3312,3307,3301,3292,3282,3273,3265,3261,3261,
-3264,3268,3271,3273,3275,3277,3281,3286,3291,3294,3295,3292,3286,3279,3273,3267,3261,3253,3240,3222,3200,
-3177,3156,3139,3126,3116,3108,3101,3094,3089,3087,3088,3092,3097,3101,3104,3107,3109,3114,3120,3127,3132,
-3134,3129,3118,3102,3085,3067,3050,3033,3016,2998,2979,2961,2945,2932,2920,2907,2891,2871,2847,2824,2806,
-2795,2793,2799,2809,2818,2823,2823,2817,2810,2801,2795,2791,2791,2792,2795,2798,2800,2799,2792,2778,2759,
-2733,2705,2675,2647,2621,2596,2573,2551,2531,2514,2503,2496,2492,2488,2480,2465,2443,2414,2383,2353,2327,
-2303,2276,2241,2190,2121,2034,1933,1826,1720,1623,1537,1464,1402,1349,1302,1259,1221,1186,1156,1130,1107,
-1085,1064,1041,1017,993,968,943,919,895,871,846,819,791,760,728,695,660,624,589,556,526,
-499,473,449,424,397,368,336,302,269,236,205,174,143,111,77,42,8,-25,-58,-89,-121,
--153,-186,-220,-253,-283,-311,-335,-355,-374,-394,-416,-441,-471,-504,-541,-578,-615,-649,-678,-701,-720,
--733,-743,-753,-764,-777,-794,-815,-840,-868,-898,-930,-961,-992,-1022,-1050,-1077,-1102,-1128,-1155,-1183,-1213,
--1244,-1275,-1305,-1336,-1366,-1396,-1426,-1456,-1487,-1518,-1549,-1578,-1606,-1633,-1660,-1687,-1715,-1745,-1776,-1809,-1842,
--1875,-1906,-1936,-1963,-1990,-2016,-2041,-2068,-2094,-2120,-2146,-2171,-2195,-2219,-2243,-2266,-2289,-2311,-2332,-2353,-2375,
--2398,-2423,-2448,-2473,-2497,-2519,-2539,-2556,-2573,-2590,-2607,-2624,-2642,-2659,-2676,-2693,-2711,-2729,-2748,-2767,-2784,
--2799,-2813,-2825,-2837,-2850,-2866,-2885,-2906,-2928,-2951,-2972,-2991,-3009,-3025,-3039,-3051,-3062,-3072,-3081,-3090,-3100,
--3112,-3124,-3138,-3151,-3163,-3173,-3181,-3187,-3193,-3200,-3207,-3214,-3221,-3227,-3230,-3231,-3230,-3229,-3228,-3228,-3229,
--3232,-3235,-3238,-3241,-3243,-3245,-3246,-3245,-3243,-3239,-3234,-3229,-3226,-3226,-3228,-3233,-3237,-3240,-3238,-3232,-3222,
--3209,-3195,-3182,-3170,-3159,-3148,-3137,-3126,-3116,-3106,-3097,-3088,-3079,-3069,-3059,-3051,-3046,-3043,-3041,-3039,-3034,
--3026,-3015,-3003,-2992,-2985,-2983,-2984,-2985,-2985,-2981,-2973,-2962,-2950,-2937,-2924,-2909,-2894,-2879,-2866,-2857,-2852,
--2852,-2855,-2859,-2863,-2870,-2882,-2902,-2929,-2962,-2994,-3019,-3030,-3028,-3016,-3000,-2990,-2991,-3002,-3021,-3039,-3050,
--3052,-3046,-3038,-3036,-3049,-3080,-3127,-3186,-3250,-3312,-3366,-3410,-3445,-3471,-3492,-3511,-3529,-3547,-3569,-3592,-3618,
--3646,-3674,-3701,-3725,-3747,-3767,-3786,-3807,-3831,-3858,-3890,-3925,-3961,-3997,-4029,-4057,-4078,-4094,-4107,-4117,-4129,
--4145,-4166,-4192,-4221,-4250,-4276,-4298,-4317,-4333,-4349,-4368,-4389,-4413,-4437,-4459,-4478,-4494,-4508,-4521,-4534,-4548,
--4562,-4573,-4582,-4589,-4594,-4600,-4608,-4617,-4627,-4636,-4645,-4651,-4655,-4659,-4662,-4664,-4664,-4662,-4657,-4650,-4642,
--4635,-4630,-4626,-4623,-4620,-4616,-4610,-4603,-4597,-4592,-4588,-4585,-4581,-4576,-4569,-4561,-4553,-4545,-4539,-4532,-4525,
--4516,-4505,-4493,-4481,-4469,-4458,-4448,-4438,-4429,-4420,-4413,-4408,-4405,-4404,-4403,-4400,-4395,-4386,-4375,-4361,-4348,
--4335,-4324,-4314,-4306,-4299,-4291,-4283,-4273,-4262,-4250,-4237,-4225,-4213,-4202,-4192,-4182,-4170,-4156,-4140,-4123,-4104,
--4086,-4070,-4055,-4042,-4031,-4021,-4011,-4000,-3989,-3976,-3962,-3947,-3931,-3915,-3898,-3882,-3864,-3846,-3827,-3807,-3787,
--3768,-3750,-3735,-3722,-3711,-3699,-3686,-3671,-3654,-3637,-3620,-3602,-3586,-3569,-3553,-3536,-3520,-3505,-3490,-3476,-3462,
--3448,-3433,-3417,-3401,-3385,-3370,-3357,-3344,-3332,-3320,-3307,-3294,-3281,-3268,-3256,-3245,-3235,-3227,-3219,-3213,-3208,
--3202,-3197,-3191,-3184,-3176,-3169,-3163,-3158,-3155,-3152,-3148,-3143,-3136,-3128,-3119,-3111,-3104,-3098,-3094,-3091,-3088,
--3085,-3082,-3078,-3074,-3070,-3065,-3061,-3055,-3050,-3044,-3038,-3030,-3022,-3013,-3005,-2997,-2991,-2986,-2982,-2979,-2977,
--2975,-2972,-2970,-2968,-2966,-2964,-2960,-2955,-2947,-2937,-2925,-2913,-2903,-2893,-2886,-2879,-2873,-2867,-2861,-2855,-2849,
--2843,-2834,-2824,-2810,-2795,-2779,-2764,-2751,-2741,-2734,-2728,-2721,-2714,-2706,-2697,-2688,-2681,-2674,-2667,-2659,-2651,
--2643,-2637,-2633,-2633,-2634,-2637,-2636,-2632,-2622,-2606,-2587,-2566,-2545,-2525,-2506,-2487,-2469,-2451,-2436,-2425,-2418,
--2416,-2417,-2418,-2418,-2415,-2409,-2402,-2393,-2385,-2378,-2372,-2366,-2361,-2357,-2351,-2345,-2338,-2328,-2318,-2306,-2295,
--2285,-2276,-2270,-2266,-2262,-2257,-2252,-2248,-2245,-2244,-2244,-2246,-2249,-2251,-2252,-2254,-2257,-2262,-2269,-2277,-2284,
--2289,-2292,-2291,-2288,-2284,-2279,-2274,-2269,-2264,-2259,-2256,-2254,-2254,-2255,-2256,-2255,-2251,-2243,-2232,-2218,-2200,
--2181,-2159,-2134,-2107,-2079,-2051,-2026,-2004,-1986,-1973,-1963,-1957,-1955,-1957,-1961,-1966,-1970,-1969,-1962,-1947,-1926,
--1902,-1878,-1857,-1839,-1823,-1809,-1793,-1776,-1756,-1737,-1718,-1701,-1686,-1672,-1660,-1648,-1636,-1625,-1616,-1608,-1600,
--1592,-1583,-1571,-1557,-1540,-1521,-1498,-1472,-1445,-1419,-1396,-1379,-1370,-1367,-1369,-1370,-1368,-1359,-1344,-1324,-1303,
--1284,-1267,-1253,-1239,-1224,-1205,-1184,-1161,-1138,-1118,-1099,-1082,-1065,-1046,-1024,-1001,-977,-956,-938,-923,-911,
--900,-890,-878,-864,-849,-832,-813,-793,-772,-750,-729,-708,-689,-672,-656,-639,-622,-604,-585,-566,-548,
--532,-516,-500,-483,-464,-443,-421,-399,-378,-359,-341,-323,-304,-283,-259,-231,-202,-171,-141,-110,-80,
--50,-18,14,48,82,113,142,166,188,209,234,264,303,349,399,449,494,532,562,587,611,
-638,671,709,750,791,830,865,901,939,983,1033,1088,1145,1198,1246,1286,1320,1349,1376,1403,1432,
-1461,1490,1518,1546,1574,1601,1629,1655,1680,1700,1716,1727,1735,1740,1745,1752,1763,1777,1794,1811,1827,
-1840,1852,1864,1879,1901,1933,1972,2014,2054,2083,2097,2095,2079,2057,2035,2019,2011,2011,2015,2020,2024,
-2026,2028,2032,2039,2050,2060,2067,2070,2069,2065,2061,2061,2067,2079,2096,2116,2134,2147,2152,2145,2126,
-2096,2062,2027,2001,1986,1982,1986,1988,1982,1964,1932,1895,1860,1836,1826,1826,1829,1827,1814,1792,1764,
-1741,1728,1727,1735,1744,1747,1742,1730,1721,1722,1741,1778,1826,1877,1923,1958,1983,2000,2016,2033,2053,
-2074,2092,2106,2114,2117,2116,2110,2101,2089,2072,2055,2039,2029,2027,2034,2049,2069,2092,2118,2144,2172,
-2199,2225,2247,2262,2270,2273,2275,2278,2287,2300,2317,2334,2348,2358,2364,2368,2371,2374,2377,2378,2377,
-2374,2368,2360,2351,2340,2326,2306,2280,2245,2200,2143,2075,1997,1910,1814,1711,1598,1477,1349,1220,1102,
-1009,958,962,1027,1146,1303,1472,1630,1757,1845,1897,1923,1938,1953,1973,1998,2025,2050,2070,2087,2100,
-2112,2120,2125,2124,2120,2113,2108,2106,2107,2107,2103,2091,2071,2044,2017,1993,1976,1965,1956,1946,1932,
-1916,1900,1886,1877,1870,1865,1858,1846,1831,1814,1798,1785,1776,1770,1764,1757,1748,1739,1730,1722,1716,
-1710,1704,1696,1686,1675,1663,1651,1640,1629,1620,1614,1609,1607,1605,1602,1597,1590,1582,1575,1571,1573,
-1579,1587,1595,1601,1604,1603,1600,1596,1592,1586,1579,1569,1559,1549,1544,1545,1553,1513,1521,1532,1543,
-1551,1555,1557,1556,1555,1553,1553,1553,1554,1558,1565,1575,1589,1605,1622,1638,1651,1662,1671,1679,1689,
-1701,1715,1731,1749,1767,1785,1804,1824,1844,1865,1886,1907,1929,1950,1971,1993,2016,2040,2066,2092,2119,
-2146,2173,2198,2222,2244,2264,2282,2297,2308,2317,2324,2331,2339,2350,2364,2380,2398,2416,2434,2450,2464,
-2478,2490,2501,2511,2519,2525,2529,2531,2532,2533,2535,2538,2541,2544,2548,2551,2555,2560,2569,2581,2595,
-2609,2622,2630,2632,2628,2622,2618,2618,2627,2644,2667,2692,2716,2736,2752,2763,2774,2786,2799,2813,2826,
-2838,2847,2854,2862,2871,2881,2891,2898,2901,2900,2895,2890,2888,2888,2893,2900,2909,2919,2929,2942,2959,
-2978,3001,3023,3044,3063,3080,3095,3112,3129,3147,3163,3176,3186,3195,3202,3211,3222,3233,3243,3251,3256,
-3260,3266,3276,3292,3312,3332,3349,3360,3367,3372,3379,3389,3403,3419,3433,3442,3447,3447,3447,3447,3449,
-3452,3454,3453,3449,3444,3439,3437,3439,3443,3447,3449,3447,3439,3429,3417,3405,3394,3384,3373,3361,3348,
-3335,3323,3314,3308,3304,3300,3296,3292,3288,3283,3279,3276,3273,3272,3272,3273,3276,3280,3283,3286,3286,
-3285,3281,3276,3271,3267,3263,3258,3252,3246,3239,3233,3231,3231,3234,3239,3244,3247,3250,3253,3256,3260,
-3264,3268,3269,3267,3262,3255,3246,3237,3228,3217,3204,3189,3171,3153,3136,3121,3109,3100,3093,3086,3081,
-3076,3074,3074,3076,3078,3081,3083,3086,3089,3094,3100,3107,3111,3111,3104,3092,3076,3057,3038,3019,3002,
-2985,2969,2952,2935,2919,2903,2887,2868,2847,2822,2795,2769,2747,2732,2726,2726,2731,2737,2741,2743,2743,
-2742,2742,2743,2745,2749,2752,2754,2753,2748,2739,2726,2709,2689,2667,2644,2621,2598,2577,2555,2536,2518,
-2505,2497,2496,2498,2500,2497,2485,2460,2424,2381,2337,2299,2270,2248,2229,2205,2168,2112,2036,1944,1842,
-1738,1640,1554,1479,1417,1365,1320,1279,1241,1205,1171,1139,1109,1079,1050,1021,992,963,936,911,887,
-865,843,820,795,767,735,699,661,621,581,544,510,480,454,431,409,385,359,329,295,259,
-222,187,154,123,93,63,33,1,-30,-63,-95,-127,-158,-190,-222,-255,-287,-319,-348,-373,-396,
--417,-438,-460,-486,-515,-547,-581,-615,-646,-673,-695,-712,-725,-737,-748,-760,-775,-792,-812,-835,-860,
--887,-916,-946,-976,-1006,-1035,-1062,-1089,-1115,-1143,-1171,-1202,-1233,-1266,-1298,-1328,-1357,-1385,-1413,-1440,-1469,
--1500,-1531,-1563,-1595,-1625,-1654,-1681,-1709,-1738,-1769,-1802,-1836,-1870,-1903,-1934,-1963,-1989,-2015,-2042,-2070,-2098,
--2126,-2154,-2179,-2202,-2225,-2247,-2270,-2295,-2320,-2345,-2369,-2393,-2416,-2439,-2462,-2486,-2510,-2533,-2554,-2573,-2590,
--2606,-2621,-2637,-2653,-2670,-2688,-2705,-2723,-2741,-2760,-2779,-2798,-2816,-2832,-2846,-2858,-2869,-2880,-2894,-2910,-2929,
--2950,-2972,-2993,-3014,-3033,-3051,-3068,-3084,-3097,-3109,-3119,-3129,-3140,-3151,-3164,-3178,-3193,-3206,-3218,-3227,-3235,
--3241,-3249,-3257,-3267,-3276,-3284,-3289,-3291,-3291,-3289,-3288,-3287,-3288,-3290,-3292,-3294,-3296,-3298,-3299,-3300,-3301,
--3299,-3296,-3292,-3287,-3283,-3282,-3284,-3289,-3294,-3297,-3298,-3294,-3287,-3277,-3266,-3255,-3244,-3232,-3220,-3208,-3196,
--3185,-3175,-3166,-3158,-3148,-3137,-3125,-3114,-3106,-3101,-3100,-3099,-3097,-3091,-3081,-3069,-3058,-3049,-3045,-3045,-3047,
--3049,-3048,-3043,-3034,-3023,-3010,-2996,-2981,-2965,-2948,-2932,-2919,-2911,-2907,-2907,-2910,-2914,-2920,-2929,-2944,-2967,
--2996,-3029,-3059,-3081,-3091,-3087,-3075,-3059,-3049,-3047,-3056,-3072,-3090,-3105,-3111,-3111,-3106,-3103,-3107,-3124,-3154,
--3196,-3248,-3304,-3361,-3413,-3458,-3495,-3525,-3548,-3568,-3587,-3608,-3633,-3661,-3692,-3722,-3751,-3777,-3798,-3817,-3835,
--3855,-3879,-3907,-3940,-3976,-4012,-4047,-4078,-4102,-4120,-4134,-4145,-4157,-4171,-4191,-4215,-4242,-4269,-4296,-4320,-4341,
--4362,-4382,-4403,-4425,-4447,-4467,-4484,-4499,-4513,-4528,-4544,-4562,-4581,-4599,-4613,-4623,-4628,-4631,-4634,-4638,-4646,
--4655,-4665,-4675,-4683,-4688,-4693,-4697,-4699,-4701,-4700,-4698,-4693,-4687,-4680,-4674,-4669,-4663,-4658,-4652,-4645,-4639,
--4635,-4632,-4630,-4628,-4625,-4619,-4611,-4602,-4593,-4584,-4577,-4569,-4561,-4550,-4538,-4525,-4511,-4499,-4489,-4480,-4472,
--4465,-4457,-4450,-4445,-4442,-4441,-4440,-4439,-4435,-4427,-4415,-4399,-4381,-4363,-4348,-4334,-4323,-4314,-4307,-4300,-4293,
--4286,-4279,-4271,-4263,-4255,-4245,-4234,-4222,-4208,-4193,-4178,-4161,-4145,-4128,-4112,-4097,-4084,-4072,-4061,-4051,-4040,
--4027,-4013,-3996,-3978,-3961,-3945,-3931,-3918,-3906,-3894,-3879,-3863,-3844,-3825,-3806,-3789,-3773,-3759,-3746,-3733,-3719,
--3704,-3688,-3671,-3654,-3636,-3618,-3599,-3581,-3563,-3547,-3533,-3520,-3507,-3494,-3481,-3467,-3452,-3437,-3423,-3410,-3398,
--3386,-3373,-3360,-3347,-3333,-3319,-3307,-3295,-3285,-3277,-3270,-3265,-3261,-3258,-3254,-3250,-3245,-3240,-3234,-3228,-3223,
--3219,-3214,-3209,-3203,-3195,-3187,-3179,-3171,-3164,-3157,-3152,-3146,-3141,-3136,-3131,-3127,-3124,-3121,-3119,-3117,-3115,
--3113,-3109,-3103,-3096,-3087,-3077,-3066,-3057,-3049,-3044,-3039,-3036,-3033,-3030,-3026,-3023,-3019,-3017,-3016,-3015,-3013,
--3009,-3002,-2993,-2983,-2973,-2962,-2953,-2945,-2938,-2931,-2925,-2919,-2914,-2908,-2902,-2894,-2884,-2873,-2861,-2848,-2835,
--2822,-2809,-2796,-2783,-2769,-2756,-2743,-2731,-2721,-2710,-2700,-2690,-2680,-2671,-2665,-2662,-2663,-2667,-2672,-2675,-2675,
--2672,-2666,-2658,-2649,-2639,-2627,-2613,-2595,-2573,-2550,-2526,-2505,-2488,-2477,-2469,-2464,-2460,-2456,-2450,-2444,-2438,
--2432,-2426,-2422,-2418,-2414,-2411,-2406,-2401,-2394,-2386,-2376,-2364,-2353,-2343,-2335,-2329,-2323,-2318,-2312,-2305,-2299,
--2294,-2293,-2294,-2297,-2300,-2302,-2301,-2300,-2298,-2299,-2301,-2306,-2312,-2317,-2319,-2318,-2314,-2307,-2300,-2293,-2287,
--2281,-2276,-2272,-2269,-2267,-2265,-2263,-2261,-2259,-2256,-2251,-2245,-2238,-2227,-2213,-2195,-2173,-2149,-2125,-2103,-2083,
--2066,-2051,-2037,-2025,-2013,-2004,-1997,-1992,-1989,-1985,-1978,-1967,-1953,-1936,-1920,-1904,-1890,-1878,-1866,-1853,-1837,
--1819,-1799,-1780,-1761,-1743,-1726,-1709,-1693,-1677,-1662,-1647,-1634,-1622,-1610,-1600,-1589,-1579,-1567,-1553,-1536,-1515,
--1491,-1466,-1441,-1420,-1406,-1397,-1392,-1388,-1382,-1371,-1356,-1337,-1317,-1300,-1284,-1271,-1257,-1242,-1224,-1203,-1184,
--1166,-1153,-1142,-1134,-1124,-1112,-1094,-1072,-1048,-1024,-1001,-980,-962,-945,-928,-911,-894,-875,-856,-837,-817,
--796,-776,-756,-737,-720,-705,-690,-674,-657,-638,-617,-596,-575,-555,-536,-517,-500,-481,-463,-444,-425,
--407,-389,-370,-351,-329,-304,-276,-247,-216,-185,-155,-125,-94,-63,-31,3,37,71,103,130,154,
-176,198,225,258,300,349,402,453,499,536,564,587,608,633,663,698,735,772,806,837,868,
-902,943,992,1048,1107,1165,1217,1262,1301,1336,1370,1405,1440,1476,1509,1538,1562,1582,1600,1619,1639,
-1662,1685,1706,1725,1740,1750,1759,1766,1776,1789,1804,1822,1839,1856,1871,1885,1902,1923,1951,1984,2019,
-2053,2080,2096,2101,2096,2086,2075,2066,2059,2054,2049,2042,2034,2026,2020,2018,2020,2026,2034,2040,2045,
-2049,2054,2062,2074,2090,2109,2126,2140,2147,2144,2130,2106,2074,2037,2002,1974,1958,1955,1961,1969,1970,
-1956,1926,1885,1843,1812,1802,1813,1839,1867,1881,1873,1840,1789,1732,1681,1643,1620,1608,1601,1594,1588,
-1591,1607,1644,1700,1771,1846,1915,1973,2016,2049,2075,2100,2126,2150,2171,2183,2186,2178,2163,2142,2118,
-2093,2070,2051,2036,2029,2031,2042,2062,2088,2119,2152,2184,2214,2239,2257,2267,2269,2265,2260,2258,2263,
-2276,2296,2319,2341,2358,2369,2373,2373,2372,2371,2370,2369,2367,2362,2354,2344,2333,2322,2309,2292,2268,
-2230,2176,2102,2010,1900,1778,1651,1524,1402,1290,1191,1110,1054,1030,1045,1103,1202,1333,1481,1627,1753,
-1848,1909,1942,1955,1962,1969,1982,2001,2022,2042,2059,2072,2083,2093,2101,2106,2109,2109,2108,2106,2103,
-2099,2092,2080,2061,2038,2012,1988,1968,1953,1942,1930,1916,1898,1878,1858,1841,1829,1822,1816,1810,1800,
-1788,1774,1760,1748,1737,1727,1717,1705,1693,1681,1670,1661,1654,1649,1645,1642,1637,1631,1622,1611,1599,
-1584,1571,1560,1553,1551,1553,1555,1556,1553,1546,1537,1528,1522,1520,1523,1530,1538,1545,1551,1555,1557,
-1556,1553,1547,1537,1527,1517,1510,1509,1513,1494,1499,1504,1510,1514,1517,1519,1521,1523,1524,1527,1529,
-1533,1539,1548,1561,1576,1594,1612,1628,1642,1654,1664,1674,1685,1698,1712,1729,1747,1766,1787,1808,1831,
-1854,1878,1901,1924,1947,1969,1992,2016,2041,2067,2094,2121,2147,2172,2196,2220,2244,2267,2288,2306,2321,
-2331,2338,2342,2346,2352,2360,2372,2387,2404,2421,2436,2451,2463,2474,2485,2494,2503,2511,2518,2523,2526,
-2529,2530,2531,2532,2533,2534,2536,2539,2544,2552,2562,2573,2584,2592,2596,2594,2589,2582,2579,2583,2596,
-2618,2645,2673,2698,2715,2725,2729,2732,2737,2747,2762,2779,2796,2811,2822,2831,2838,2846,2854,2862,2869,
-2872,2872,2869,2866,2866,2868,2874,2882,2892,2901,2912,2924,2938,2955,2974,2993,3012,3029,3045,3062,3078,
-3095,3112,3127,3139,3148,3156,3165,3175,3186,3198,3209,3218,3226,3234,3244,3257,3274,3292,3309,3322,3331,
-3336,3340,3345,3354,3366,3378,3389,3396,3399,3400,3401,3404,3408,3413,3415,3414,3410,3404,3400,3399,3401,
-3405,3408,3408,3403,3393,3380,3366,3353,3342,3332,3324,3315,3306,3297,3289,3283,3278,3272,3267,3260,3253,
-3247,3241,3237,3235,3234,3233,3234,3235,3237,3240,3244,3247,3248,3247,3243,3238,3232,3227,3223,3220,3218,
-3215,3211,3209,3207,3208,3211,3215,3219,3222,3225,3227,3229,3232,3237,3242,3244,3244,3240,3232,3221,3209,
-3197,3185,3174,3162,3149,3136,3123,3110,3098,3087,3076,3068,3060,3055,3053,3054,3057,3061,3066,3070,3074,
-3077,3080,3083,3085,3084,3081,3073,3060,3044,3026,3008,2990,2974,2958,2943,2927,2911,2893,2874,2852,2829,
-2803,2776,2751,2727,2709,2696,2688,2685,2684,2683,2683,2681,2681,2682,2685,2691,2697,2702,2704,2701,2693,
-2679,2662,2642,2622,2604,2588,2574,2561,2549,2536,2521,2506,2492,2482,2477,2477,2481,2483,2479,2464,2436,
-2397,2351,2305,2264,2231,2206,2183,2157,2119,2066,1995,1909,1815,1719,1629,1548,1480,1423,1377,1336,1299,
-1263,1228,1192,1157,1122,1087,1053,1020,987,955,924,894,866,840,815,791,765,737,706,670,631,
-589,547,507,470,438,412,389,368,347,323,295,262,226,187,148,112,78,47,18,-9,-38,
--68,-100,-133,-166,-199,-232,-265,-297,-328,-358,-386,-411,-434,-455,-476,-499,-525,-553,-584,-615,-645,
--670,-690,-705,-716,-726,-736,-748,-764,-782,-804,-827,-851,-877,-903,-932,-961,-991,-1022,-1051,-1080,-1108,
--1136,-1165,-1195,-1227,-1260,-1295,-1328,-1360,-1390,-1417,-1443,-1468,-1495,-1523,-1553,-1584,-1616,-1648,-1679,-1708,-1737,
--1767,-1798,-1831,-1865,-1899,-1933,-1964,-1993,-2020,-2048,-2075,-2105,-2134,-2164,-2191,-2216,-2238,-2259,-2279,-2301,-2325,
--2350,-2376,-2403,-2428,-2452,-2476,-2499,-2523,-2547,-2570,-2592,-2611,-2628,-2644,-2659,-2674,-2689,-2706,-2723,-2741,-2758,
--2776,-2794,-2813,-2832,-2850,-2868,-2884,-2897,-2909,-2921,-2933,-2947,-2963,-2981,-3000,-3019,-3038,-3057,-3076,-3094,-3112,
--3129,-3144,-3157,-3169,-3180,-3192,-3204,-3219,-3234,-3249,-3261,-3272,-3280,-3287,-3293,-3301,-3309,-3319,-3328,-3335,-3339,
--3342,-3342,-3341,-3341,-3341,-3342,-3343,-3345,-3345,-3346,-3347,-3348,-3348,-3347,-3346,-3342,-3339,-3336,-3334,-3335,-3338,
--3341,-3345,-3346,-3345,-3341,-3335,-3327,-3318,-3308,-3297,-3284,-3272,-3260,-3249,-3241,-3233,-3225,-3215,-3204,-3191,-3179,
--3170,-3166,-3166,-3167,-3166,-3162,-3152,-3138,-3123,-3111,-3104,-3103,-3107,-3111,-3114,-3112,-3107,-3097,-3084,-3070,-3054,
--3036,-3017,-2998,-2981,-2967,-2958,-2954,-2954,-2957,-2963,-2971,-2983,-3002,-3027,-3058,-3090,-3119,-3139,-3146,-3141,-3128,
--3112,-3101,-3099,-3108,-3125,-3145,-3164,-3176,-3181,-3179,-3176,-3176,-3184,-3204,-3238,-3282,-3335,-3390,-3442,-3489,-3527,
--3557,-3581,-3603,-3625,-3650,-3680,-3714,-3748,-3782,-3811,-3835,-3855,-3871,-3886,-3903,-3923,-3948,-3978,-4011,-4045,-4080,
--4112,-4141,-4167,-4191,-4212,-4232,-4252,-4272,-4291,-4310,-4328,-4347,-4367,-4388,-4412,-4437,-4462,-4485,-4504,-4520,-4532,
--4544,-4558,-4574,-4592,-4612,-4630,-4645,-4655,-4661,-4664,-4666,-4670,-4677,-4684,-4693,-4700,-4706,-4710,-4713,-4717,-4720,
--4724,-4727,-4731,-4733,-4734,-4733,-4730,-4725,-4718,-4708,-4696,-4685,-4676,-4670,-4666,-4664,-4663,-4659,-4654,-4647,-4639,
--4632,-4627,-4623,-4619,-4614,-4604,-4590,-4573,-4555,-4538,-4524,-4512,-4503,-4496,-4488,-4482,-4476,-4472,-4470,-4469,-4468,
--4466,-4460,-4450,-4436,-4420,-4403,-4385,-4368,-4353,-4338,-4325,-4314,-4306,-4300,-4296,-4294,-4291,-4288,-4281,-4272,-4261,
--4248,-4235,-4222,-4209,-4196,-4183,-4168,-4153,-4137,-4122,-4107,-4093,-4078,-4063,-4046,-4027,-4008,-3990,-3974,-3961,-3952,
--3943,-3935,-3926,-3913,-3898,-3881,-3863,-3844,-3826,-3809,-3793,-3777,-3762,-3747,-3732,-3717,-3702,-3686,-3668,-3649,-3630,
--3611,-3594,-3578,-3564,-3552,-3540,-3528,-3516,-3504,-3492,-3479,-3467,-3455,-3443,-3430,-3418,-3405,-3392,-3379,-3368,-3357,
--3347,-3339,-3331,-3325,-3320,-3315,-3311,-3307,-3303,-3299,-3294,-3290,-3286,-3281,-3276,-3270,-3264,-3256,-3248,-3240,-3234,
--3228,-3222,-3216,-3209,-3201,-3193,-3186,-3179,-3175,-3172,-3170,-3170,-3169,-3168,-3166,-3162,-3156,-3148,-3140,-3131,-3122,
--3115,-3109,-3104,-3100,-3095,-3090,-3085,-3079,-3074,-3070,-3069,-3068,-3068,-3068,-3066,-3061,-3055,-3047,-3038,-3030,-3021,
--3014,-3006,-2999,-2991,-2984,-2977,-2969,-2962,-2954,-2944,-2933,-2921,-2906,-2891,-2874,-2858,-2842,-2827,-2815,-2804,-2793,
--2783,-2771,-2757,-2742,-2726,-2711,-2699,-2691,-2687,-2685,-2686,-2686,-2686,-2687,-2689,-2693,-2698,-2704,-2707,-2706,-2699,
--2684,-2663,-2639,-2614,-2590,-2569,-2551,-2536,-2522,-2510,-2500,-2491,-2484,-2479,-2475,-2472,-2469,-2466,-2462,-2459,-2454,
--2449,-2442,-2434,-2424,-2413,-2403,-2393,-2385,-2378,-2372,-2365,-2358,-2352,-2348,-2347,-2348,-2352,-2355,-2357,-2356,-2352,
--2348,-2344,-2342,-2342,-2343,-2345,-2345,-2343,-2339,-2333,-2327,-2322,-2316,-2312,-2307,-2302,-2297,-2292,-2287,-2282,-2279,
--2276,-2273,-2271,-2267,-2261,-2252,-2238,-2222,-2203,-2184,-2166,-2151,-2139,-2129,-2119,-2109,-2097,-2083,-2069,-2056,-2044,
--2034,-2024,-2013,-2000,-1985,-1968,-1952,-1938,-1926,-1916,-1906,-1896,-1884,-1869,-1852,-1833,-1814,-1795,-1776,-1757,-1739,
--1721,-1702,-1684,-1665,-1647,-1630,-1614,-1600,-1589,-1580,-1571,-1560,-1547,-1531,-1512,-1492,-1473,-1457,-1444,-1434,-1424,
--1412,-1397,-1379,-1359,-1339,-1321,-1304,-1289,-1274,-1257,-1240,-1223,-1208,-1198,-1192,-1190,-1190,-1188,-1181,-1167,-1147,
--1122,-1094,-1066,-1039,-1013,-989,-966,-944,-923,-902,-882,-862,-842,-822,-802,-782,-765,-749,-735,-721,-707,
--691,-672,-651,-628,-604,-582,-562,-543,-525,-508,-491,-474,-456,-437,-417,-395,-371,-345,-316,-287,-256,
--226,-196,-166,-136,-105,-73,-40,-6,27,60,91,120,147,172,199,230,266,309,356,406,453,
-496,531,559,583,608,635,667,703,741,778,810,839,865,894,928,969,1019,1072,1127,1180,1229,
-1275,1318,1361,1405,1448,1490,1527,1557,1580,1597,1611,1625,1641,1661,1683,1706,1728,1746,1760,1770,1777,
-1785,1795,1808,1824,1842,1862,1881,1898,1916,1932,1949,1967,1985,2002,2016,2028,2038,2044,2048,2050,2050,
-2046,2039,2027,2013,1998,1986,1979,1978,1983,1992,2005,2019,2036,2057,2082,2111,2141,2168,2187,2195,2190,
-2172,2142,2105,2064,2024,1989,1965,1954,1957,1973,1996,2016,2024,2013,1984,1945,1907,1887,1893,1927,1982,
-2040,2084,2100,2081,2033,1967,1899,1841,1797,1767,1748,1734,1725,1723,1732,1757,1797,1845,1895,1938,1969,
-1988,2000,2012,2030,2057,2090,2123,2148,2159,2156,2140,2115,2090,2068,2055,2050,2054,2065,2080,2099,2119,
-2142,2167,2193,2220,2244,2262,2272,2271,2262,2248,2235,2229,2234,2251,2278,2310,2339,2361,2374,2377,2374,
-2370,2366,2364,2363,2362,2357,2348,2335,2319,2304,2289,2272,2249,2215,2161,2083,1978,1850,1705,1555,1411,
-1284,1185,1118,1087,1092,1130,1200,1295,1409,1532,1652,1760,1846,1905,1939,1954,1957,1957,1958,1965,1977,
-1990,2003,2013,2021,2027,2032,2036,2041,2044,2048,2050,2051,2050,2044,2032,2015,1993,1967,1943,1922,1906,
-1895,1886,1875,1861,1842,1821,1800,1782,1768,1758,1750,1744,1737,1728,1720,1711,1703,1696,1688,1678,1666,
-1652,1637,1624,1612,1602,1596,1592,1590,1589,1586,1581,1572,1559,1543,1527,1513,1505,1502,1506,1511,1516,
-1517,1512,1503,1492,1482,1476,1475,1479,1486,1493,1501,1507,1511,1513,1513,1511,1507,1502,1497,1493,1492,
-1494,1484,1487,1490,1492,1493,1494,1495,1497,1500,1504,1509,1515,1522,1530,1541,1554,1569,1586,1604,1621,
-1636,1651,1664,1678,1692,1708,1725,1743,1763,1784,1806,1830,1855,1880,1904,1928,1950,1972,1995,2018,2043,
-2070,2097,2124,2149,2173,2195,2217,2240,2264,2287,2309,2328,2342,2351,2356,2359,2361,2365,2372,2383,2396,
-2410,2424,2437,2447,2457,2465,2472,2480,2489,2497,2504,2511,2517,2521,2525,2527,2528,2528,2530,2532,2536,
-2541,2548,2555,2561,2564,2564,2559,2552,2546,2545,2551,2566,2590,2619,2649,2674,2690,2697,2697,2693,2692,
-2696,2708,2726,2748,2769,2787,2800,2810,2818,2826,2834,2841,2846,2848,2847,2844,2841,2840,2843,2849,2858,
-2869,2880,2891,2903,2917,2931,2947,2963,2979,2995,3010,3025,3041,3057,3072,3087,3099,3110,3121,3131,3141,
-3153,3165,3176,3187,3198,3209,3222,3238,3255,3272,3286,3297,3303,3308,3312,3319,3327,3338,3347,3355,3359,
-3361,3361,3363,3366,3371,3375,3378,3377,3375,3371,3368,3368,3369,3370,3369,3363,3353,3340,3327,3315,3306,
-3300,3296,3291,3285,3278,3269,3261,3252,3245,3237,3229,3221,3213,3206,3202,3200,3200,3200,3200,3200,3199,
-3199,3201,3204,3207,3209,3210,3208,3204,3199,3195,3193,3191,3191,3191,3190,3189,3188,3189,3190,3193,3196,
-3198,3200,3202,3204,3209,3215,3221,3226,3228,3224,3216,3205,3191,3178,3166,3155,3145,3136,3125,3113,3099,
-3086,3072,3060,3049,3041,3036,3034,3035,3040,3046,3052,3058,3062,3064,3063,3060,3056,3050,3043,3034,3022,
-3008,2992,2974,2958,2942,2927,2914,2901,2887,2870,2851,2827,2802,2775,2750,2728,2711,2698,2690,2685,2680,
-2674,2666,2657,2648,2640,2637,2637,2641,2646,2650,2649,2643,2630,2611,2589,2566,2545,2528,2517,2509,2504,
-2500,2493,2484,2472,2460,2449,2441,2437,2436,2434,2428,2415,2394,2363,2327,2289,2251,2216,2182,2148,2109,
-2062,2003,1934,1856,1772,1689,1610,1538,1477,1425,1381,1343,1306,1270,1233,1196,1157,1120,1084,1049,1016,
-983,950,915,881,847,814,783,753,725,695,664,629,591,549,506,464,425,390,362,338,319,
-301,282,259,230,197,159,120,82,48,17,-10,-37,-63,-93,-125,-160,-198,-236,-274,-310,-344,
--375,-404,-429,-452,-471,-490,-508,-529,-553,-581,-610,-641,-668,-691,-708,-720,-729,-736,-746,-759,-776,
--797,-820,-844,-870,-897,-924,-953,-984,-1017,-1049,-1082,-1113,-1142,-1170,-1198,-1227,-1257,-1290,-1323,-1357,-1390,
--1421,-1450,-1477,-1502,-1527,-1554,-1582,-1613,-1645,-1677,-1710,-1741,-1772,-1802,-1833,-1865,-1898,-1932,-1965,-1997,-2028,
--2057,-2085,-2114,-2142,-2171,-2199,-2226,-2250,-2272,-2293,-2313,-2335,-2358,-2383,-2409,-2435,-2460,-2484,-2508,-2532,-2558,
--2583,-2609,-2633,-2655,-2673,-2690,-2705,-2720,-2736,-2753,-2771,-2788,-2806,-2822,-2839,-2855,-2872,-2889,-2906,-2922,-2937,
--2951,-2964,-2977,-2991,-3006,-3022,-3039,-3056,-3073,-3091,-3108,-3127,-3146,-3164,-3181,-3197,-3210,-3222,-3234,-3246,-3260,
--3275,-3290,-3304,-3315,-3324,-3331,-3338,-3344,-3352,-3361,-3370,-3378,-3384,-3387,-3389,-3389,-3390,-3390,-3392,-3394,-3395,
--3396,-3397,-3396,-3395,-3394,-3392,-3389,-3386,-3384,-3382,-3381,-3382,-3384,-3387,-3390,-3392,-3392,-3390,-3387,-3381,-3374,
--3365,-3354,-3342,-3331,-3321,-3313,-3307,-3302,-3296,-3287,-3275,-3262,-3250,-3241,-3238,-3238,-3241,-3242,-3237,-3226,-3210,
--3191,-3175,-3165,-3162,-3166,-3173,-3179,-3182,-3180,-3172,-3160,-3145,-3128,-3109,-3088,-3066,-3045,-3027,-3013,-3005,-3002,
--3004,-3009,-3017,-3028,-3043,-3063,-3089,-3119,-3149,-3173,-3189,-3194,-3188,-3176,-3163,-3154,-3154,-3163,-3180,-3200,-3219,
--3233,-3241,-3243,-3244,-3248,-3258,-3279,-3310,-3351,-3397,-3444,-3488,-3526,-3557,-3582,-3604,-3626,-3652,-3682,-3717,-3753,
--3790,-3823,-3851,-3874,-3891,-3905,-3917,-3930,-3945,-3965,-3990,-4022,-4059,-4100,-4145,-4191,-4236,-4276,-4309,-4336,-4354,
--4366,-4373,-4379,-4386,-4398,-4415,-4437,-4463,-4491,-4518,-4541,-4559,-4574,-4585,-4596,-4608,-4622,-4637,-4651,-4665,-4676,
--4686,-4694,-4700,-4707,-4713,-4719,-4723,-4726,-4728,-4728,-4729,-4730,-4733,-4738,-4746,-4755,-4764,-4774,-4781,-4784,-4782,
--4775,-4762,-4745,-4728,-4714,-4703,-4696,-4693,-4691,-4687,-4682,-4676,-4670,-4666,-4665,-4665,-4665,-4662,-4654,-4640,-4621,
--4600,-4578,-4560,-4545,-4535,-4526,-4520,-4513,-4508,-4502,-4498,-4496,-4493,-4491,-4486,-4480,-4472,-4461,-4449,-4434,-4418,
--4399,-4380,-4360,-4342,-4327,-4317,-4311,-4308,-4307,-4305,-4300,-4294,-4285,-4276,-4268,-4261,-4254,-4246,-4237,-4224,-4208,
--4190,-4172,-4154,-4136,-4119,-4102,-4085,-4066,-4047,-4028,-4012,-3997,-3986,-3977,-3968,-3959,-3948,-3936,-3922,-3906,-3889,
--3872,-3853,-3835,-3817,-3800,-3785,-3772,-3759,-3746,-3733,-3718,-3701,-3683,-3665,-3647,-3630,-3616,-3603,-3591,-3580,-3569,
--3558,-3548,-3536,-3525,-3513,-3500,-3486,-3473,-3460,-3448,-3438,-3429,-3421,-3413,-3406,-3399,-3392,-3385,-3378,-3371,-3365,
--3358,-3353,-3348,-3344,-3340,-3336,-3332,-3326,-3320,-3313,-3306,-3300,-3295,-3290,-3286,-3280,-3273,-3264,-3255,-3246,-3239,
--3233,-3230,-3228,-3226,-3225,-3223,-3220,-3216,-3212,-3207,-3202,-3196,-3190,-3183,-3177,-3172,-3166,-3160,-3154,-3147,-3140,
--3134,-3129,-3126,-3124,-3124,-3124,-3124,-3123,-3119,-3114,-3108,-3100,-3093,-3085,-3077,-3069,-3062,-3054,-3046,-3037,-3028,
--3018,-3006,-2993,-2977,-2959,-2941,-2923,-2906,-2893,-2882,-2874,-2868,-2861,-2853,-2841,-2824,-2805,-2785,-2765,-2749,-2735,
--2725,-2717,-2710,-2704,-2699,-2698,-2700,-2708,-2720,-2734,-2748,-2759,-2764,-2762,-2755,-2742,-2726,-2708,-2688,-2666,-2643,
--2619,-2595,-2575,-2558,-2545,-2535,-2528,-2522,-2516,-2511,-2506,-2503,-2500,-2497,-2493,-2488,-2480,-2471,-2460,-2449,-2439,
--2431,-2423,-2416,-2409,-2404,-2400,-2398,-2399,-2401,-2403,-2405,-2403,-2400,-2395,-2390,-2385,-2382,-2379,-2377,-2375,-2372,
--2368,-2363,-2359,-2354,-2350,-2346,-2342,-2337,-2331,-2326,-2321,-2317,-2313,-2310,-2306,-2300,-2292,-2281,-2267,-2249,-2229,
--2208,-2189,-2173,-2162,-2154,-2149,-2146,-2142,-2137,-2130,-2122,-2113,-2103,-2092,-2080,-2065,-2047,-2026,-2005,-1985,-1967,
--1953,-1942,-1933,-1924,-1913,-1900,-1884,-1866,-1848,-1829,-1811,-1794,-1778,-1762,-1746,-1728,-1709,-1689,-1668,-1648,-1630,
--1614,-1602,-1593,-1584,-1575,-1564,-1551,-1537,-1522,-1508,-1495,-1481,-1467,-1451,-1432,-1411,-1390,-1369,-1350,-1333,-1317,
--1301,-1285,-1268,-1252,-1239,-1230,-1226,-1224,-1224,-1221,-1214,-1200,-1180,-1155,-1127,-1097,-1067,-1039,-1012,-987,-964,
--944,-925,-907,-889,-871,-851,-831,-812,-794,-778,-764,-751,-737,-720,-701,-679,-656,-633,-610,-589,-570,
--552,-535,-517,-498,-478,-457,-434,-410,-384,-357,-328,-299,-271,-242,-213,-184,-154,-122,-89,-55,-21,
-11,44,75,105,135,165,197,232,269,310,352,395,437,475,509,540,570,601,634,672,713,
-755,794,828,857,882,906,933,965,1003,1047,1094,1144,1193,1241,1289,1336,1384,1430,1475,1516,1552,
-1582,1607,1628,1647,1665,1683,1701,1718,1733,1746,1756,1765,1773,1781,1791,1804,1820,1839,1859,1879,1897,
-1911,1921,1926,1926,1922,1918,1913,1911,1910,1912,1914,1915,1913,1906,1897,1888,1882,1884,1895,1915,1941,
-1972,2002,2031,2059,2089,2122,2160,2200,2237,2266,2279,2273,2249,2210,2163,2114,2068,2031,2006,1994,1997,
-2012,2039,2070,2097,2112,2110,2090,2059,2032,2021,2037,2085,2157,2239,2312,2361,2377,2361,2324,2277,2232,
-2197,2172,2154,2138,2122,2105,2090,2079,2071,2062,2048,2022,1985,1941,1899,1870,1863,1880,1917,1965,2010,
-2042,2056,2053,2041,2029,2025,2035,2059,2092,2126,2155,2176,2186,2190,2192,2198,2208,2223,2238,2250,2254,
-2249,2238,2225,2218,2221,2237,2262,2293,2322,2345,2358,2361,2358,2353,2349,2348,2349,2349,2346,2337,2321,
-2302,2281,2260,2240,2217,2186,2139,2070,1976,1856,1718,1573,1436,1321,1241,1201,1202,1240,1307,1393,1488,
-1583,1671,1746,1806,1848,1875,1889,1894,1896,1897,1900,1905,1913,1921,1928,1933,1936,1938,1939,1940,1941,
-1944,1947,1951,1954,1953,1947,1936,1918,1895,1871,1848,1829,1814,1804,1795,1786,1774,1759,1743,1727,1712,
-1700,1690,1682,1674,1667,1659,1653,1647,1643,1640,1636,1630,1622,1612,1599,1587,1574,1564,1555,1549,1545,
-1542,1540,1535,1527,1516,1502,1487,1474,1465,1461,1463,1468,1472,1474,1471,1465,1458,1451,1446,1446,1448,
-1452,1457,1461,1463,1464,1466,1467,1469,1471,1473,1476,1478,1481,1484,1465,1469,1473,1475,1477,1479,1481,
-1484,1488,1494,1500,1507,1515,1523,1533,1544,1557,1572,1589,1607,1625,1643,1662,1681,1701,1720,1741,1761,
-1782,1804,1827,1851,1875,1899,1922,1944,1966,1988,2012,2037,2065,2093,2121,2148,2173,2196,2218,2240,2263,
-2286,2309,2330,2347,2360,2368,2372,2374,2376,2380,2387,2395,2405,2415,2425,2433,2439,2445,2451,2457,2464,
-2472,2480,2488,2495,2502,2508,2512,2516,2519,2522,2526,2530,2535,2539,2543,2544,2542,2537,2530,2522,2517,
-2517,2524,2540,2564,2592,2619,2642,2657,2662,2660,2654,2649,2649,2657,2673,2695,2719,2742,2761,2776,2787,
-2796,2803,2810,2815,2819,2819,2817,2814,2811,2811,2814,2821,2830,2841,2852,2863,2874,2886,2898,2911,2924,
-2937,2950,2964,2977,2992,3007,3024,3040,3056,3072,3086,3099,3112,3123,3134,3144,3154,3166,3179,3195,3212,
-3230,3246,3258,3267,3273,3279,3285,3293,3303,3313,3322,3329,3333,3334,3335,3336,3337,3339,3341,3341,3340,
-3337,3336,3335,3336,3336,3333,3326,3315,3300,3285,3272,3265,3261,3262,3264,3263,3260,3253,3243,3233,3223,
-3214,3206,3198,3190,3183,3178,3174,3173,3172,3172,3170,3167,3164,3162,3161,3163,3167,3171,3173,3174,3173,
-3171,3168,3167,3167,3167,3167,3167,3166,3165,3165,3166,3169,3172,3174,3177,3180,3185,3190,3198,3206,3212,
-3214,3212,3204,3192,3179,3165,3153,3143,3134,3125,3114,3102,3088,3074,3061,3049,3040,3033,3028,3025,3025,
-3027,3030,3035,3038,3040,3038,3034,3027,3019,3010,3001,2991,2980,2966,2950,2933,2915,2899,2885,2874,2866,
-2857,2846,2831,2811,2787,2762,2738,2718,2703,2694,2688,2684,2678,2669,2656,2641,2626,2613,2604,2600,2599,
-2601,2602,2599,2592,2579,2560,2538,2515,2493,2476,2463,2455,2450,2447,2442,2436,2426,2414,2402,2390,2380,
-2372,2365,2358,2348,2334,2316,2292,2264,2231,2195,2155,2110,2060,2005,1946,1882,1814,1745,1676,1609,1546,
-1488,1436,1388,1345,1303,1262,1221,1179,1139,1100,1063,1029,997,966,933,898,862,824,785,747,712,
-677,644,610,573,535,493,450,407,367,331,302,278,259,244,228,210,188,160,127,93,58,
-26,-1,-27,-52,-78,-107,-140,-178,-219,-262,-305,-346,-384,-418,-449,-475,-497,-515,-531,-548,-566,
--588,-614,-643,-671,-698,-720,-736,-747,-755,-762,-772,-785,-803,-825,-849,-875,-902,-930,-959,-991,-1024,
--1058,-1093,-1127,-1159,-1188,-1216,-1241,-1267,-1293,-1321,-1350,-1382,-1414,-1446,-1477,-1507,-1535,-1562,-1590,-1619,-1650,
--1682,-1716,-1750,-1784,-1816,-1847,-1877,-1908,-1940,-1973,-2006,-2038,-2070,-2099,-2127,-2154,-2181,-2207,-2233,-2258,-2283,
--2306,-2329,-2352,-2376,-2401,-2426,-2451,-2476,-2500,-2523,-2547,-2572,-2599,-2627,-2655,-2681,-2705,-2725,-2743,-2759,-2775,
--2792,-2810,-2829,-2848,-2866,-2883,-2898,-2913,-2927,-2941,-2956,-2970,-2985,-2998,-3012,-3026,-3041,-3056,-3073,-3090,-3106,
--3123,-3139,-3155,-3172,-3190,-3208,-3226,-3242,-3257,-3271,-3283,-3296,-3309,-3323,-3337,-3350,-3362,-3372,-3380,-3388,-3396,
--3405,-3414,-3424,-3432,-3437,-3440,-3441,-3441,-3441,-3442,-3445,-3448,-3452,-3454,-3455,-3454,-3451,-3448,-3444,-3441,-3438,
--3436,-3435,-3435,-3436,-3438,-3440,-3442,-3445,-3446,-3445,-3443,-3438,-3432,-3422,-3412,-3402,-3392,-3385,-3381,-3378,-3376,
--3371,-3363,-3352,-3338,-3325,-3315,-3311,-3311,-3314,-3315,-3311,-3301,-3285,-3265,-3247,-3234,-3228,-3230,-3237,-3244,-3249,
--3250,-3245,-3236,-3222,-3206,-3187,-3166,-3144,-3121,-3100,-3083,-3072,-3066,-3065,-3068,-3074,-3083,-3095,-3111,-3131,-3155,
--3181,-3206,-3226,-3238,-3241,-3237,-3228,-3220,-3215,-3215,-3223,-3236,-3251,-3267,-3281,-3292,-3301,-3310,-3322,-3339,-3361,
--3390,-3423,-3458,-3492,-3522,-3547,-3570,-3590,-3612,-3636,-3664,-3697,-3732,-3768,-3803,-3834,-3861,-3884,-3901,-3915,-3926,
--3937,-3950,-3968,-3994,-4029,-4074,-4128,-4187,-4248,-4305,-4354,-4392,-4417,-4431,-4436,-4436,-4436,-4438,-4447,-4462,-4483,
--4508,-4535,-4562,-4585,-4604,-4620,-4632,-4642,-4651,-4661,-4672,-4685,-4699,-4713,-4727,-4738,-4748,-4754,-4757,-4758,-4756,
--4754,-4752,-4751,-4751,-4753,-4757,-4764,-4773,-4784,-4796,-4807,-4815,-4818,-4813,-4802,-4786,-4769,-4752,-4739,-4730,-4724,
--4721,-4716,-4711,-4704,-4698,-4694,-4693,-4694,-4695,-4693,-4687,-4675,-4658,-4639,-4619,-4601,-4587,-4576,-4567,-4560,-4554,
--4547,-4540,-4533,-4527,-4521,-4516,-4511,-4507,-4502,-4496,-4489,-4480,-4467,-4451,-4431,-4409,-4387,-4366,-4350,-4338,-4329,
--4322,-4316,-4309,-4301,-4294,-4288,-4283,-4280,-4277,-4273,-4266,-4256,-4242,-4226,-4209,-4193,-4177,-4163,-4148,-4132,-4114,
--4096,-4077,-4059,-4042,-4027,-4012,-3999,-3987,-3975,-3963,-3951,-3938,-3924,-3909,-3892,-3874,-3857,-3840,-3825,-3813,-3802,
--3792,-3781,-3768,-3753,-3736,-3719,-3701,-3685,-3670,-3657,-3644,-3633,-3622,-3612,-3602,-3591,-3579,-3567,-3553,-3539,-3525,
--3511,-3500,-3490,-3483,-3477,-3472,-3467,-3462,-3456,-3449,-3441,-3432,-3423,-3414,-3405,-3398,-3392,-3388,-3384,-3380,-3376,
--3371,-3366,-3361,-3356,-3353,-3350,-3346,-3341,-3335,-3328,-3319,-3312,-3306,-3301,-3298,-3296,-3293,-3289,-3285,-3280,-3275,
--3270,-3266,-3262,-3258,-3253,-3247,-3240,-3233,-3226,-3219,-3213,-3207,-3201,-3195,-3189,-3184,-3180,-3178,-3177,-3177,-3176,
--3174,-3171,-3165,-3158,-3150,-3141,-3133,-3126,-3120,-3113,-3106,-3098,-3089,-3077,-3062,-3046,-3027,-3008,-2990,-2973,-2959,
--2948,-2941,-2936,-2932,-2926,-2917,-2904,-2887,-2867,-2847,-2828,-2812,-2799,-2787,-2776,-2765,-2754,-2744,-2737,-2734,-2737,
--2744,-2756,-2769,-2781,-2792,-2801,-2807,-2811,-2812,-2808,-2799,-2783,-2761,-2734,-2705,-2676,-2651,-2630,-2613,-2598,-2585,
--2573,-2562,-2553,-2546,-2542,-2540,-2539,-2536,-2531,-2523,-2513,-2502,-2492,-2482,-2474,-2467,-2461,-2456,-2451,-2448,-2446,
--2446,-2445,-2445,-2443,-2440,-2436,-2431,-2426,-2421,-2417,-2413,-2409,-2406,-2402,-2398,-2394,-2391,-2387,-2383,-2379,-2375,
--2371,-2366,-2362,-2358,-2353,-2347,-2339,-2329,-2316,-2299,-2280,-2259,-2237,-2216,-2197,-2180,-2168,-2159,-2152,-2148,-2146,
--2144,-2142,-2141,-2139,-2135,-2128,-2118,-2103,-2084,-2061,-2038,-2016,-1996,-1981,-1968,-1957,-1946,-1934,-1919,-1902,-1884,
--1865,-1848,-1833,-1820,-1808,-1797,-1786,-1773,-1758,-1740,-1721,-1700,-1680,-1662,-1645,-1631,-1618,-1606,-1594,-1581,-1568,
--1555,-1542,-1528,-1514,-1498,-1481,-1461,-1441,-1421,-1403,-1386,-1372,-1358,-1344,-1328,-1312,-1295,-1279,-1266,-1255,-1246,
--1237,-1227,-1214,-1198,-1179,-1156,-1132,-1107,-1082,-1057,-1033,-1011,-991,-972,-956,-939,-922,-904,-885,-865,-844,
--826,-808,-793,-777,-761,-743,-723,-701,-678,-655,-634,-613,-593,-574,-554,-534,-512,-490,-468,-445,-421,
--396,-371,-344,-318,-291,-264,-236,-206,-175,-141,-107,-72,-39,-6,24,53,83,113,145,178,213,
-250,288,327,366,405,444,481,518,554,591,630,671,713,755,795,832,864,891,916,940,967,
-997,1033,1072,1115,1160,1204,1249,1292,1335,1378,1421,1464,1507,1550,1591,1628,1659,1685,1704,1717,1725,
-1731,1737,1744,1753,1765,1779,1794,1810,1826,1841,1855,1867,1875,1878,1874,1862,1843,1820,1794,1770,1750,
-1735,1723,1714,1705,1695,1687,1684,1692,1716,1757,1816,1887,1962,2034,2094,2142,2179,2208,2235,2264,2294,
-2320,2337,2340,2325,2295,2253,2208,2165,2128,2100,2081,2071,2069,2076,2090,2109,2128,2141,2143,2133,2115,
-2098,2094,2113,2161,2233,2320,2406,2477,2525,2547,2550,2542,2532,2525,2521,2517,2509,2492,2468,2437,2400,
-2358,2308,2244,2165,2072,1972,1880,1807,1767,1764,1794,1845,1901,1947,1977,1988,1989,1990,2001,2029,2072,
-2121,2167,2198,2210,2202,2181,2158,2141,2138,2149,2171,2196,2218,2230,2234,2230,2226,2225,2232,2247,2267,
-2287,2303,2312,2314,2311,2306,2302,2300,2301,2303,2301,2295,2282,2264,2242,2218,2194,2170,2141,2104,2053,
-1983,1895,1793,1685,1582,1497,1439,1414,1422,1456,1509,1568,1625,1672,1708,1731,1745,1753,1759,1766,1774,
-1785,1797,1809,1820,1830,1838,1844,1848,1851,1853,1854,1854,1853,1852,1851,1850,1847,1843,1835,1823,1807,
-1786,1765,1744,1726,1712,1701,1692,1684,1677,1669,1662,1655,1650,1645,1640,1634,1626,1616,1606,1597,1590,
-1584,1581,1577,1574,1569,1563,1555,1547,1537,1528,1520,1513,1507,1503,1500,1496,1490,1483,1472,1461,1449,
-1439,1432,1428,1427,1427,1428,1427,1426,1425,1425,1426,1429,1432,1434,1435,1434,1432,1430,1429,1430,1433,
-1437,1442,1448,1454,1460,1465,1432,1438,1444,1449,1454,1458,1463,1468,1473,1480,1488,1496,1504,1513,1522,
-1532,1544,1559,1576,1596,1617,1640,1664,1688,1711,1734,1756,1777,1799,1820,1843,1865,1888,1910,1932,1953,
-1975,1998,2022,2048,2077,2105,2134,2161,2187,2212,2236,2260,2285,2309,2331,2350,2364,2374,2379,2382,2384,
-2387,2391,2396,2402,2407,2411,2414,2418,2422,2427,2433,2441,2448,2456,2463,2469,2475,2480,2485,2491,2497,
-2503,2510,2517,2523,2527,2530,2528,2523,2515,2506,2497,2492,2493,2501,2517,2539,2564,2587,2605,2616,2619,
-2616,2609,2603,2602,2607,2620,2639,2661,2685,2706,2725,2739,2751,2760,2767,2772,2776,2777,2777,2776,2776,
-2777,2781,2788,2796,2806,2815,2823,2831,2838,2846,2855,2865,2876,2887,2898,2910,2922,2936,2951,2968,2987,
-3007,3027,3045,3062,3076,3088,3098,3107,3117,3129,3144,3162,3181,3200,3216,3228,3236,3242,3248,3255,3264,
-3275,3286,3296,3304,3310,3313,3315,3315,3316,3315,3313,3309,3306,3302,3301,3301,3302,3301,3297,3287,3272,
-3256,3240,3228,3222,3221,3224,3228,3229,3226,3219,3210,3201,3192,3185,3179,3174,3168,3162,3157,3153,3150,
-3147,3145,3141,3137,3133,3130,3130,3132,3136,3141,3145,3148,3149,3148,3147,3147,3147,3147,3146,3144,3142,
-3141,3141,3143,3146,3150,3155,3159,3164,3169,3175,3182,3189,3195,3197,3194,3186,3175,3162,3149,3139,3129,
-3121,3112,3101,3089,3075,3063,3052,3043,3036,3031,3025,3020,3015,3010,3007,3005,3003,3002,2998,2993,2985,
-2976,2966,2957,2947,2935,2922,2906,2888,2870,2854,2842,2836,2832,2830,2826,2816,2800,2779,2753,2728,2705,
-2688,2675,2667,2659,2651,2640,2626,2611,2596,2583,2573,2566,2562,2560,2557,2553,2545,2533,2517,2497,2476,
-2454,2435,2419,2406,2398,2392,2387,2381,2374,2364,2353,2340,2326,2314,2302,2291,2280,2269,2255,2238,2215,
-2186,2151,2108,2061,2010,1957,1903,1848,1793,1736,1679,1620,1561,1502,1446,1392,1340,1292,1244,1198,1154,
-1111,1070,1033,999,968,937,906,873,836,797,756,714,672,631,591,551,511,470,429,387,346,
-308,273,244,219,200,184,170,154,136,113,87,59,30,2,-24,-49,-73,-100,-130,-164,-202,
--244,-287,-331,-374,-415,-453,-487,-517,-543,-565,-584,-601,-619,-640,-663,-688,-712,-735,-753,-766,-775,
--781,-789,-800,-815,-835,-859,-885,-914,-943,-974,-1006,-1039,-1074,-1109,-1144,-1177,-1208,-1236,-1262,-1286,-1308,
--1331,-1355,-1381,-1409,-1439,-1470,-1503,-1536,-1568,-1600,-1631,-1663,-1695,-1730,-1765,-1800,-1836,-1870,-1902,-1933,-1963,
--1994,-2025,-2056,-2087,-2117,-2146,-2173,-2199,-2224,-2248,-2273,-2297,-2322,-2347,-2372,-2398,-2424,-2451,-2477,-2504,-2529,
--2553,-2576,-2599,-2624,-2650,-2677,-2705,-2731,-2756,-2777,-2795,-2812,-2829,-2847,-2867,-2888,-2909,-2928,-2946,-2962,-2977,
--2991,-3004,-3018,-3032,-3046,-3059,-3072,-3084,-3098,-3114,-3130,-3148,-3165,-3182,-3198,-3214,-3229,-3245,-3262,-3279,-3296,
--3313,-3328,-3343,-3356,-3368,-3380,-3392,-3402,-3412,-3421,-3430,-3439,-3449,-3460,-3472,-3483,-3492,-3498,-3501,-3501,-3500,
--3500,-3500,-3503,-3506,-3510,-3513,-3514,-3514,-3512,-3509,-3507,-3505,-3503,-3502,-3501,-3499,-3498,-3496,-3496,-3496,-3497,
--3498,-3499,-3498,-3495,-3490,-3481,-3472,-3462,-3454,-3449,-3446,-3445,-3444,-3440,-3434,-3423,-3410,-3397,-3386,-3380,-3379,
--3381,-3382,-3380,-3373,-3359,-3342,-3324,-3309,-3300,-3297,-3300,-3305,-3310,-3313,-3313,-3308,-3298,-3285,-3269,-3249,-3228,
--3205,-3183,-3163,-3147,-3137,-3131,-3131,-3134,-3141,-3151,-3164,-3181,-3200,-3221,-3242,-3260,-3274,-3283,-3286,-3284,-3281,
--3277,-3276,-3278,-3283,-3292,-3304,-3317,-3331,-3344,-3359,-3374,-3390,-3409,-3430,-3453,-3477,-3501,-3525,-3546,-3567,-3587,
--3608,-3632,-3657,-3684,-3714,-3744,-3775,-3805,-3834,-3861,-3885,-3907,-3925,-3940,-3954,-3970,-3990,-4019,-4057,-4105,-4161,
--4222,-4284,-4340,-4389,-4428,-4457,-4475,-4487,-4493,-4497,-4501,-4508,-4518,-4532,-4551,-4573,-4596,-4618,-4638,-4655,-4668,
--4678,-4688,-4699,-4712,-4728,-4746,-4762,-4777,-4786,-4791,-4791,-4789,-4785,-4783,-4782,-4783,-4785,-4788,-4789,-4791,-4793,
--4797,-4803,-4811,-4818,-4824,-4825,-4822,-4814,-4803,-4791,-4781,-4772,-4766,-4759,-4753,-4745,-4736,-4728,-4721,-4717,-4715,
--4714,-4713,-4709,-4701,-4690,-4677,-4664,-4651,-4639,-4629,-4621,-4612,-4604,-4594,-4585,-4575,-4565,-4556,-4547,-4539,-4533,
--4527,-4522,-4518,-4512,-4504,-4492,-4477,-4459,-4439,-4420,-4401,-4384,-4369,-4354,-4341,-4328,-4315,-4305,-4297,-4291,-4287,
--4283,-4278,-4271,-4262,-4251,-4240,-4229,-4219,-4210,-4200,-4188,-4175,-4160,-4144,-4126,-4109,-4091,-4074,-4057,-4040,-4025,
--4010,-3997,-3985,-3973,-3962,-3949,-3935,-3919,-3903,-3887,-3874,-3862,-3851,-3841,-3830,-3818,-3803,-3787,-3770,-3753,-3737,
--3723,-3710,-3697,-3685,-3673,-3662,-3651,-3640,-3629,-3617,-3605,-3592,-3579,-3566,-3556,-3547,-3539,-3533,-3528,-3523,-3518,
--3512,-3506,-3499,-3491,-3482,-3472,-3463,-3454,-3446,-3440,-3434,-3430,-3426,-3422,-3418,-3415,-3412,-3410,-3408,-3406,-3402,
--3397,-3390,-3384,-3378,-3374,-3371,-3369,-3368,-3365,-3360,-3354,-3347,-3340,-3334,-3329,-3325,-3321,-3316,-3309,-3301,-3291,
--3282,-3275,-3269,-3264,-3259,-3254,-3247,-3240,-3234,-3229,-3226,-3224,-3224,-3223,-3221,-3217,-3210,-3201,-3192,-3183,-3176,
--3170,-3165,-3159,-3152,-3142,-3129,-3114,-3097,-3080,-3063,-3047,-3034,-3023,-3015,-3008,-3003,-2996,-2988,-2976,-2962,-2946,
--2930,-2914,-2900,-2888,-2877,-2867,-2856,-2844,-2831,-2818,-2807,-2799,-2796,-2796,-2799,-2804,-2810,-2817,-2826,-2836,-2848,
--2860,-2868,-2871,-2866,-2853,-2834,-2809,-2784,-2759,-2737,-2716,-2696,-2676,-2655,-2635,-2617,-2603,-2593,-2587,-2584,-2581,
--2578,-2572,-2564,-2554,-2544,-2535,-2528,-2521,-2515,-2510,-2504,-2500,-2496,-2492,-2490,-2487,-2484,-2480,-2475,-2469,-2463,
--2457,-2452,-2447,-2443,-2440,-2437,-2434,-2431,-2428,-2426,-2423,-2420,-2416,-2413,-2408,-2402,-2395,-2386,-2376,-2363,-2349,
--2333,-2316,-2298,-2280,-2263,-2246,-2230,-2214,-2199,-2186,-2173,-2163,-2154,-2148,-2144,-2142,-2140,-2137,-2133,-2125,-2113,
--2097,-2080,-2061,-2043,-2027,-2012,-1999,-1986,-1972,-1955,-1938,-1919,-1900,-1882,-1867,-1855,-1845,-1837,-1830,-1822,-1812,
--1801,-1787,-1771,-1753,-1734,-1716,-1697,-1679,-1660,-1642,-1625,-1607,-1591,-1575,-1560,-1545,-1530,-1514,-1497,-1480,-1463,
--1447,-1433,-1421,-1410,-1400,-1388,-1374,-1358,-1340,-1321,-1302,-1284,-1267,-1250,-1234,-1217,-1200,-1184,-1167,-1151,-1135,
--1118,-1100,-1081,-1061,-1041,-1021,-1001,-981,-961,-940,-919,-898,-878,-859,-841,-823,-805,-786,-765,-743,-720,
--698,-677,-657,-638,-619,-599,-577,-554,-531,-507,-484,-460,-437,-413,-387,-361,-334,-306,-278,-249,-219,
--186,-152,-117,-82,-48,-16,12,39,66,93,122,153,186,221,257,295,334,375,417,460,502,
-544,584,623,661,699,736,774,810,844,877,907,936,965,994,1026,1060,1097,1134,1171,1208,1242,
-1277,1312,1350,1392,1439,1490,1542,1592,1635,1670,1694,1708,1716,1721,1727,1737,1753,1772,1793,1812,1826,
-1835,1837,1833,1824,1809,1789,1763,1732,1697,1661,1628,1599,1578,1563,1554,1548,1543,1540,1542,1556,1589,
-1644,1724,1825,1938,2050,2150,2229,2284,2317,2334,2344,2352,2361,2369,2372,2367,2350,2325,2293,2260,2229,
-2202,2178,2156,2134,2113,2095,2083,2079,2080,2084,2086,2082,2074,2066,2067,2085,2125,2187,2263,2343,2416,
-2474,2514,2539,2555,2568,2580,2591,2598,2598,2589,2572,2548,2519,2486,2443,2386,2310,2215,2107,1999,1907,
-1844,1818,1827,1862,1908,1951,1979,1992,1995,1997,2008,2033,2072,2116,2154,2175,2175,2155,2123,2091,2069,
-2065,2080,2109,2145,2179,2204,2217,2220,2217,2214,2214,2219,2228,2237,2245,2249,2247,2243,2236,2230,2225,
-2223,2223,2222,2219,2213,2201,2185,2165,2142,2118,2091,2061,2026,1984,1934,1876,1814,1755,1703,1665,1644,
-1639,1648,1664,1679,1688,1688,1681,1668,1655,1648,1649,1659,1676,1698,1721,1741,1757,1769,1778,1785,1792,
-1798,1802,1805,1804,1800,1793,1783,1771,1759,1745,1731,1715,1697,1679,1661,1645,1630,1617,1607,1600,1593,
-1589,1587,1587,1589,1592,1594,1594,1592,1586,1577,1566,1555,1545,1537,1530,1524,1518,1512,1506,1499,1492,
-1485,1479,1474,1469,1466,1465,1464,1464,1464,1461,1455,1446,1434,1422,1409,1398,1391,1386,1385,1386,1389,
-1394,1400,1406,1410,1413,1414,1413,1411,1409,1407,1406,1407,1409,1411,1415,1418,1422,1427,1432,1401,1407,
-1414,1421,1427,1432,1437,1443,1450,1459,1469,1480,1491,1502,1514,1527,1541,1558,1577,1599,1623,1649,1675,
-1701,1726,1749,1771,1793,1816,1839,1862,1886,1909,1932,1953,1973,1993,2013,2035,2058,2082,2108,2135,2162,
-2189,2217,2246,2274,2302,2327,2348,2364,2374,2380,2383,2385,2387,2391,2395,2398,2400,2400,2399,2397,2398,
-2401,2407,2416,2426,2435,2442,2448,2451,2454,2458,2463,2470,2479,2488,2497,2505,2510,2511,2508,2502,2493,
-2482,2473,2468,2469,2477,2492,2512,2533,2552,2566,2573,2573,2568,2561,2556,2554,2559,2569,2584,2603,2622,
-2642,2659,2676,2690,2702,2712,2719,2724,2727,2728,2729,2731,2735,2742,2751,2762,2772,2780,2787,2791,2795,
-2798,2802,2808,2816,2825,2836,2846,2858,2869,2882,2897,2914,2934,2955,2976,2997,3015,3031,3043,3054,3064,
-3075,3089,3106,3127,3148,3169,3186,3200,3209,3216,3222,3229,3237,3248,3259,3269,3277,3284,3289,3292,3294,
-3295,3293,3290,3285,3280,3276,3274,3273,3273,3272,3267,3257,3243,3228,3213,3202,3195,3194,3195,3196,3195,
-3191,3184,3176,3169,3162,3158,3154,3150,3145,3140,3134,3129,3125,3122,3118,3115,3113,3111,3110,3111,3115,
-3119,3123,3127,3130,3131,3132,3133,3134,3135,3134,3133,3131,3128,3126,3126,3128,3132,3137,3142,3146,3150,
-3153,3157,3162,3168,3171,3172,3168,3160,3149,3137,3126,3117,3109,3102,3094,3084,3072,3059,3047,3038,3030,
-3024,3018,3010,3000,2989,2978,2967,2960,2954,2951,2947,2943,2937,2929,2920,2911,2902,2892,2880,2866,2852,
-2837,2826,2818,2815,2815,2816,2813,2805,2789,2766,2739,2711,2685,2662,2645,2631,2619,2607,2594,2581,2568,
-2556,2546,2538,2531,2524,2518,2510,2501,2490,2477,2463,2446,2427,2408,2390,2373,2360,2349,2342,2337,2334,
-2329,2323,2315,2304,2290,2275,2260,2244,2228,2212,2194,2174,2151,2122,2088,2049,2005,1959,1911,1863,1814,
-1765,1714,1661,1605,1547,1488,1430,1373,1319,1268,1219,1172,1127,1083,1043,1005,971,939,908,877,845,
-810,772,731,687,642,595,549,504,459,416,374,334,296,261,228,199,173,152,134,118,102,
-86,66,45,20,-5,-31,-58,-84,-112,-141,-172,-207,-244,-283,-323,-364,-405,-445,-484,-521,-555,
--585,-611,-633,-653,-672,-691,-711,-731,-749,-765,-777,-785,-791,-798,-806,-819,-838,-860,-887,-917,-948,
--981,-1015,-1051,-1087,-1123,-1159,-1192,-1223,-1251,-1277,-1301,-1323,-1345,-1368,-1391,-1415,-1441,-1469,-1500,-1533,-1567,
--1602,-1637,-1672,-1707,-1742,-1778,-1815,-1852,-1889,-1926,-1960,-1992,-2023,-2052,-2080,-2109,-2138,-2166,-2194,-2222,-2248,
--2274,-2299,-2323,-2348,-2371,-2395,-2419,-2444,-2470,-2497,-2525,-2553,-2580,-2606,-2631,-2655,-2679,-2703,-2728,-2753,-2778,
--2800,-2821,-2841,-2859,-2878,-2897,-2918,-2940,-2961,-2982,-3001,-3018,-3034,-3050,-3066,-3082,-3097,-3111,-3124,-3137,-3149,
--3162,-3177,-3194,-3212,-3231,-3249,-3266,-3281,-3295,-3309,-3324,-3339,-3356,-3373,-3389,-3404,-3418,-3429,-3439,-3447,-3454,
--3461,-3468,-3475,-3484,-3495,-3507,-3520,-3534,-3545,-3554,-3560,-3562,-3563,-3564,-3564,-3565,-3567,-3568,-3569,-3569,-3568,
--3568,-3568,-3570,-3572,-3575,-3576,-3574,-3571,-3565,-3559,-3553,-3549,-3547,-3547,-3548,-3549,-3547,-3544,-3537,-3529,-3520,
--3511,-3505,-3502,-3500,-3499,-3496,-3492,-3484,-3475,-3465,-3456,-3450,-3447,-3447,-3448,-3447,-3442,-3432,-3419,-3402,-3387,
--3374,-3365,-3361,-3362,-3366,-3371,-3374,-3374,-3370,-3362,-3348,-3331,-3310,-3287,-3264,-3242,-3222,-3207,-3196,-3190,-3190,
--3195,-3205,-3219,-3235,-3253,-3270,-3286,-3299,-3308,-3315,-3320,-3322,-3325,-3328,-3331,-3335,-3340,-3347,-3355,-3365,-3376,
--3388,-3402,-3416,-3432,-3448,-3466,-3485,-3505,-3526,-3547,-3569,-3591,-3613,-3636,-3658,-3680,-3701,-3722,-3744,-3765,-3789,
--3815,-3843,-3873,-3902,-3930,-3956,-3977,-3997,-4016,-4038,-4064,-4097,-4137,-4183,-4234,-4287,-4340,-4391,-4439,-4481,-4517,
--4544,-4564,-4575,-4581,-4584,-4586,-4592,-4603,-4618,-4636,-4655,-4673,-4688,-4700,-4711,-4722,-4735,-4751,-4768,-4785,-4799,
--4808,-4812,-4812,-4809,-4808,-4808,-4812,-4819,-4826,-4831,-4832,-4830,-4825,-4820,-4816,-4815,-4817,-4821,-4826,-4829,-4831,
--4830,-4827,-4823,-4818,-4812,-4805,-4796,-4786,-4775,-4764,-4755,-4748,-4743,-4740,-4737,-4734,-4729,-4723,-4716,-4708,-4700,
--4692,-4683,-4674,-4664,-4653,-4642,-4630,-4619,-4608,-4596,-4585,-4574,-4564,-4555,-4547,-4540,-4534,-4527,-4519,-4509,-4497,
--4483,-4468,-4453,-4436,-4419,-4401,-4383,-4365,-4349,-4335,-4324,-4314,-4306,-4297,-4287,-4277,-4266,-4256,-4248,-4242,-4236,
--4230,-4223,-4214,-4203,-4190,-4176,-4163,-4150,-4137,-4123,-4108,-4092,-4075,-4059,-4044,-4032,-4020,-4009,-3998,-3985,-3971,
--3955,-3940,-3926,-3914,-3902,-3891,-3879,-3866,-3851,-3835,-3819,-3804,-3790,-3777,-3764,-3751,-3738,-3726,-3713,-3701,-3690,
--3679,-3669,-3659,-3649,-3639,-3630,-3622,-3614,-3606,-3599,-3591,-3583,-3576,-3569,-3562,-3556,-3549,-3542,-3535,-3527,-3518,
--3510,-3503,-3496,-3490,-3485,-3480,-3476,-3472,-3470,-3468,-3467,-3465,-3462,-3458,-3452,-3446,-3440,-3436,-3434,-3433,-3432,
--3430,-3426,-3421,-3414,-3407,-3402,-3397,-3394,-3390,-3386,-3378,-3369,-3359,-3348,-3339,-3332,-3326,-3321,-3315,-3307,-3298,
--3289,-3281,-3275,-3272,-3271,-3271,-3270,-3267,-3262,-3254,-3246,-3237,-3230,-3224,-3218,-3212,-3203,-3193,-3180,-3165,-3149,
--3134,-3120,-3108,-3098,-3090,-3082,-3075,-3068,-3059,-3049,-3038,-3027,-3014,-3002,-2991,-2980,-2970,-2960,-2949,-2936,-2923,
--2909,-2896,-2885,-2878,-2873,-2870,-2868,-2866,-2864,-2863,-2865,-2869,-2876,-2885,-2895,-2902,-2905,-2902,-2894,-2883,-2869,
--2855,-2840,-2823,-2804,-2781,-2755,-2728,-2701,-2678,-2659,-2646,-2636,-2630,-2624,-2619,-2612,-2604,-2597,-2590,-2583,-2577,
--2570,-2564,-2558,-2552,-2546,-2541,-2536,-2531,-2526,-2520,-2514,-2506,-2499,-2491,-2485,-2480,-2476,-2472,-2470,-2467,-2466,
--2464,-2463,-2461,-2459,-2456,-2451,-2445,-2437,-2427,-2414,-2400,-2385,-2369,-2354,-2340,-2328,-2316,-2305,-2293,-2281,-2267,
--2251,-2235,-2218,-2202,-2187,-2174,-2163,-2154,-2147,-2140,-2133,-2125,-2116,-2106,-2094,-2083,-2071,-2059,-2047,-2033,-2018,
--2001,-1982,-1963,-1945,-1928,-1913,-1901,-1892,-1884,-1877,-1869,-1861,-1851,-1839,-1826,-1811,-1796,-1779,-1762,-1743,-1724,
--1703,-1682,-1660,-1639,-1618,-1599,-1581,-1564,-1547,-1530,-1513,-1497,-1481,-1467,-1456,-1446,-1438,-1428,-1418,-1405,-1390,
--1372,-1353,-1333,-1313,-1292,-1273,-1254,-1238,-1223,-1211,-1201,-1192,-1184,-1174,-1161,-1144,-1124,-1100,-1075,-1048,-1022,
--997,-973,-951,-931,-913,-895,-878,-860,-840,-818,-794,-769,-745,-723,-704,-687,-671,-654,-634,-612,-587,
--561,-536,-510,-484,-458,-430,-401,-370,-339,-308,-279,-249,-219,-188,-155,-121,-85,-50,-17,12,40,
-66,92,118,147,178,211,245,281,320,360,402,445,489,531,571,608,642,675,707,741,775,
-811,848,884,919,952,985,1017,1049,1082,1115,1147,1178,1208,1237,1266,1299,1337,1381,1430,1482,1534,
-1581,1621,1650,1672,1687,1701,1716,1735,1757,1779,1799,1812,1816,1807,1788,1759,1723,1683,1640,1598,1559,
-1524,1497,1480,1475,1480,1495,1515,1536,1556,1575,1597,1628,1673,1739,1825,1928,2039,2147,2240,2311,2358,
-2382,2391,2391,2390,2389,2388,2385,2377,2362,2341,2316,2290,2264,2237,2209,2176,2140,2102,2066,2037,2019,
-2010,2009,2010,2009,2005,2001,2003,2018,2051,2103,2167,2236,2301,2354,2392,2417,2434,2445,2455,2463,2467,
-2466,2460,2451,2444,2440,2438,2433,2418,2385,2329,2252,2163,2076,2005,1960,1944,1952,1974,1998,2015,2020,
-2018,2014,2017,2030,2054,2081,2105,2117,2116,2101,2081,2063,2055,2061,2080,2107,2135,2158,2171,2175,2172,
-2167,2162,2161,2163,2169,2175,2179,2181,2179,2175,2168,2161,2154,2148,2143,2141,2139,2137,2133,2125,2113,
-2095,2073,2049,2024,2000,1976,1952,1928,1901,1873,1844,1817,1793,1774,1759,1745,1732,1716,1696,1675,1655,
-1640,1633,1636,1648,1667,1689,1710,1727,1739,1746,1752,1756,1761,1766,1769,1770,1767,1758,1745,1727,1707,
-1686,1665,1645,1625,1607,1591,1577,1565,1555,1547,1539,1532,1525,1520,1516,1514,1514,1516,1519,1521,1521,
-1519,1516,1511,1505,1500,1494,1488,1482,1474,1464,1454,1443,1433,1424,1418,1414,1412,1414,1418,1425,1431,
-1436,1438,1435,1427,1414,1398,1381,1366,1354,1348,1347,1351,1358,1366,1373,1379,1382,1384,1383,1383,1383,
-1383,1385,1387,1389,1391,1391,1391,1391,1393,1396,1401,1383,1391,1398,1405,1411,1415,1420,1426,1433,1444,
-1456,1470,1485,1500,1516,1532,1549,1567,1588,1611,1636,1662,1688,1713,1737,1760,1783,1807,1832,1858,1886,
-1913,1939,1963,1983,2000,2015,2029,2044,2061,2081,2103,2128,2156,2186,2218,2250,2282,2312,2337,2356,2368,
-2374,2376,2377,2379,2382,2387,2392,2396,2396,2394,2390,2386,2385,2388,2395,2404,2414,2423,2429,2432,2434,
-2437,2442,2449,2459,2470,2479,2486,2489,2488,2482,2474,2464,2453,2446,2442,2443,2451,2465,2482,2499,2515,
-2526,2530,2528,2522,2515,2510,2509,2513,2522,2534,2548,2562,2576,2589,2604,2618,2633,2647,2659,2669,2675,
-2678,2680,2683,2687,2694,2704,2715,2727,2737,2744,2748,2750,2751,2752,2754,2759,2766,2774,2785,2796,2808,
-2821,2834,2850,2867,2886,2906,2927,2948,2967,2984,2998,3010,3022,3035,3050,3069,3091,3113,3135,3154,3170,
-3182,3191,3199,3208,3217,3227,3236,3244,3251,3256,3260,3263,3265,3267,3267,3265,3263,3259,3255,3251,3249,
-3247,3244,3238,3230,3219,3207,3196,3188,3183,3180,3179,3178,3175,3169,3162,3154,3146,3139,3133,3128,3123,
-3118,3113,3108,3104,3101,3098,3096,3094,3093,3093,3094,3096,3099,3102,3105,3107,3109,3111,3114,3118,3122,
-3126,3128,3128,3127,3124,3122,3122,3124,3127,3131,3133,3134,3134,3134,3135,3137,3140,3143,3143,3139,3131,
-3120,3108,3097,3089,3083,3077,3071,3062,3051,3038,3025,3014,3004,2996,2987,2976,2962,2947,2931,2917,2906,
-2899,2895,2893,2890,2886,2881,2874,2867,2859,2851,2842,2834,2825,2817,2810,2806,2805,2804,2802,2795,2782,
-2763,2738,2710,2682,2656,2634,2615,2598,2583,2568,2554,2541,2530,2520,2512,2505,2497,2488,2476,2462,2446,
-2430,2414,2398,2382,2367,2351,2336,2322,2310,2302,2296,2293,2291,2288,2285,2279,2271,2260,2245,2229,2210,
-2188,2166,2141,2115,2086,2056,2022,1985,1945,1901,1855,1806,1756,1704,1651,1597,1542,1487,1433,1381,1331,
-1283,1237,1192,1149,1107,1066,1027,989,954,920,888,857,825,792,756,716,674,628,579,530,480,
-433,387,344,303,265,229,196,165,137,113,92,74,57,40,21,0,-22,-46,-73,-100,-128,
--157,-188,-220,-254,-289,-325,-363,-401,-439,-478,-516,-552,-586,-616,-642,-665,-685,-703,-721,-739,-755,
--770,-782,-791,-798,-804,-812,-824,-840,-860,-885,-913,-944,-976,-1012,-1049,-1089,-1130,-1170,-1207,-1240,-1269,
--1293,-1314,-1335,-1356,-1377,-1401,-1425,-1451,-1478,-1506,-1536,-1568,-1601,-1636,-1672,-1708,-1745,-1782,-1820,-1858,-1898,
--1937,-1976,-2012,-2046,-2077,-2106,-2133,-2160,-2187,-2214,-2242,-2270,-2299,-2326,-2353,-2379,-2403,-2426,-2447,-2468,-2490,
--2513,-2539,-2567,-2596,-2626,-2655,-2682,-2708,-2733,-2756,-2779,-2801,-2823,-2844,-2865,-2885,-2905,-2926,-2947,-2969,-2991,
--3012,-3032,-3051,-3069,-3085,-3102,-3119,-3135,-3152,-3167,-3181,-3195,-3208,-3223,-3240,-3260,-3280,-3301,-3320,-3337,-3351,
--3364,-3375,-3387,-3400,-3414,-3429,-3444,-3459,-3471,-3482,-3490,-3497,-3502,-3508,-3513,-3520,-3527,-3537,-3548,-3561,-3575,
--3588,-3600,-3610,-3617,-3623,-3626,-3629,-3630,-3630,-3629,-3626,-3624,-3623,-3624,-3627,-3633,-3640,-3648,-3653,-3656,-3654,
--3649,-3641,-3632,-3625,-3619,-3615,-3613,-3611,-3609,-3604,-3598,-3590,-3581,-3572,-3565,-3559,-3555,-3553,-3550,-3548,-3545,
--3541,-3536,-3531,-3527,-3523,-3521,-3519,-3517,-3512,-3505,-3494,-3481,-3466,-3451,-3438,-3430,-3427,-3428,-3433,-3439,-3443,
--3443,-3438,-3427,-3411,-3391,-3368,-3345,-3322,-3301,-3282,-3268,-3259,-3255,-3259,-3268,-3283,-3301,-3319,-3335,-3347,-3354,
--3357,-3357,-3357,-3358,-3362,-3368,-3377,-3386,-3396,-3405,-3413,-3421,-3429,-3438,-3447,-3459,-3472,-3487,-3504,-3522,-3542,
--3563,-3586,-3608,-3631,-3654,-3676,-3697,-3717,-3734,-3750,-3764,-3779,-3796,-3816,-3840,-3869,-3901,-3934,-3966,-3995,-4020,
--4042,-4062,-4081,-4102,-4126,-4155,-4189,-4229,-4276,-4328,-4386,-4445,-4502,-4554,-4596,-4626,-4644,-4653,-4656,-4657,-4660,
--4667,-4678,-4691,-4703,-4714,-4722,-4729,-4736,-4744,-4756,-4770,-4785,-4798,-4809,-4816,-4819,-4820,-4823,-4828,-4836,-4846,
--4858,-4867,-4872,-4873,-4869,-4861,-4853,-4845,-4840,-4838,-4839,-4842,-4846,-4851,-4854,-4855,-4854,-4851,-4845,-4837,-4827,
--4817,-4807,-4798,-4791,-4784,-4778,-4773,-4767,-4762,-4756,-4750,-4744,-4738,-4731,-4723,-4714,-4703,-4692,-4680,-4669,-4657,
--4645,-4634,-4621,-4609,-4597,-4585,-4574,-4563,-4553,-4544,-4535,-4526,-4517,-4507,-4497,-4485,-4472,-4457,-4441,-4424,-4408,
--4393,-4379,-4368,-4356,-4344,-4331,-4317,-4301,-4287,-4275,-4265,-4258,-4252,-4245,-4237,-4227,-4216,-4205,-4195,-4187,-4179,
--4172,-4164,-4152,-4138,-4122,-4106,-4091,-4079,-4068,-4058,-4048,-4036,-4022,-4007,-3991,-3975,-3961,-3947,-3935,-3923,-3910,
--3897,-3883,-3870,-3858,-3846,-3834,-3822,-3810,-3796,-3783,-3769,-3756,-3744,-3733,-3724,-3715,-3707,-3700,-3694,-3688,-3682,
--3675,-3667,-3658,-3648,-3638,-3628,-3620,-3614,-3608,-3603,-3598,-3592,-3585,-3578,-3571,-3564,-3557,-3551,-3544,-3539,-3534,
--3530,-3527,-3526,-3524,-3522,-3518,-3513,-3506,-3500,-3494,-3490,-3488,-3486,-3485,-3483,-3479,-3475,-3470,-3467,-3465,-3463,
--3462,-3459,-3454,-3446,-3436,-3426,-3416,-3407,-3400,-3393,-3386,-3377,-3367,-3355,-3344,-3335,-3328,-3324,-3322,-3321,-3319,
--3315,-3309,-3303,-3296,-3289,-3283,-3277,-3269,-3259,-3248,-3234,-3219,-3204,-3190,-3178,-3167,-3158,-3150,-3142,-3134,-3127,
--3120,-3112,-3105,-3097,-3089,-3081,-3072,-3062,-3051,-3038,-3024,-3010,-2994,-2980,-2968,-2959,-2953,-2949,-2946,-2944,-2940,
--2935,-2928,-2922,-2918,-2915,-2915,-2917,-2919,-2922,-2923,-2922,-2921,-2919,-2915,-2909,-2900,-2886,-2867,-2843,-2816,-2788,
--2760,-2736,-2716,-2700,-2687,-2676,-2666,-2658,-2651,-2644,-2638,-2633,-2627,-2620,-2613,-2606,-2598,-2591,-2584,-2577,-2571,
--2564,-2557,-2548,-2540,-2532,-2524,-2518,-2512,-2508,-2504,-2501,-2499,-2497,-2496,-2495,-2494,-2492,-2489,-2484,-2477,-2468,
--2456,-2444,-2430,-2416,-2403,-2391,-2379,-2369,-2359,-2349,-2338,-2326,-2313,-2298,-2282,-2265,-2248,-2232,-2217,-2202,-2188,
--2175,-2163,-2153,-2143,-2135,-2127,-2119,-2111,-2101,-2090,-2078,-2063,-2047,-2031,-2014,-1998,-1984,-1971,-1961,-1951,-1943,
--1935,-1926,-1917,-1905,-1893,-1879,-1864,-1849,-1833,-1816,-1799,-1780,-1761,-1740,-1718,-1696,-1675,-1655,-1635,-1616,-1598,
--1579,-1559,-1540,-1521,-1504,-1489,-1477,-1466,-1456,-1446,-1435,-1423,-1408,-1392,-1374,-1355,-1336,-1316,-1297,-1278,-1262,
--1248,-1238,-1231,-1226,-1221,-1215,-1204,-1189,-1168,-1142,-1113,-1083,-1053,-1025,-1001,-980,-963,-948,-935,-920,-902,
--881,-856,-829,-802,-776,-754,-735,-719,-704,-687,-668,-645,-619,-592,-564,-535,-506,-475,-443,-409,-373,
--339,-306,-276,-248,-222,-194,-164,-130,-94,-57,-20,14,46,76,105,134,164,196,228,260,292,
-325,358,393,430,469,508,546,582,616,648,680,713,747,783,820,858,895,931,965,998,1031,
-1065,1098,1131,1164,1195,1224,1253,1284,1316,1353,1395,1439,1484,1527,1566,1599,1626,1648,1668,1688,1707,
-1725,1740,1748,1747,1733,1708,1671,1627,1580,1534,1492,1459,1437,1429,1437,1459,1496,1544,1599,1655,1707,
-1753,1791,1825,1857,1894,1940,1997,2062,2130,2196,2253,2297,2327,2346,2357,2365,2371,2377,2380,2377,2368,
-2351,2327,2300,2270,2240,2208,2173,2136,2097,2059,2026,2002,1989,1986,1987,1988,1985,1978,1969,1966,1976,
-2003,2049,2109,2175,2236,2286,2321,2342,2352,2355,2355,2351,2345,2336,2325,2316,2312,2317,2330,2348,2361,
-2360,2338,2293,2230,2158,2089,2035,2001,1988,1989,1996,2003,2005,2004,2003,2005,2014,2029,2047,2064,2077,
-2083,2086,2089,2095,2105,2120,2135,2146,2148,2141,2127,2109,2092,2081,2077,2080,2087,2094,2101,2105,2108,
-2108,2108,2107,2104,2100,2094,2087,2080,2075,2072,2070,2066,2060,2048,2032,2013,1993,1976,1962,1951,1942,
-1932,1918,1900,1877,1852,1827,1804,1784,1767,1752,1738,1726,1714,1706,1702,1702,1707,1715,1723,1730,1734,
-1736,1735,1733,1731,1729,1726,1722,1715,1705,1691,1673,1654,1634,1614,1594,1576,1559,1543,1530,1520,1513,
-1507,1501,1495,1488,1477,1466,1453,1442,1433,1426,1423,1422,1422,1424,1426,1429,1433,1437,1441,1443,1442,
-1437,1429,1417,1404,1390,1376,1366,1360,1359,1362,1370,1381,1392,1401,1406,1404,1396,1382,1364,1346,1331,
-1321,1316,1318,1323,1331,1338,1343,1346,1347,1346,1346,1347,1350,1354,1359,1364,1367,1369,1369,1369,1369,
-1372,1376,1383,1376,1387,1396,1403,1409,1413,1418,1424,1433,1444,1457,1473,1489,1506,1523,1540,1558,1577,
-1598,1621,1646,1671,1696,1721,1744,1767,1791,1816,1843,1872,1901,1930,1956,1978,1995,2007,2017,2026,2037,
-2051,2069,2093,2120,2151,2184,2218,2251,2283,2310,2332,2347,2356,2360,2361,2362,2366,2371,2379,2386,2392,
-2393,2392,2387,2383,2381,2382,2386,2392,2399,2404,2408,2410,2413,2419,2426,2437,2448,2458,2464,2464,2459,
-2449,2437,2425,2415,2409,2409,2414,2423,2437,2451,2466,2477,2484,2486,2483,2477,2470,2466,2465,2468,2475,
-2484,2494,2503,2512,2520,2530,2541,2555,2571,2587,2602,2614,2622,2628,2632,2636,2642,2650,2660,2671,2681,
-2689,2695,2698,2699,2699,2700,2701,2705,2711,2719,2730,2742,2756,2772,2788,2806,2824,2843,2863,2884,2905,
-2925,2943,2959,2974,2987,3001,3017,3035,3055,3076,3098,3118,3136,3150,3163,3175,3186,3197,3207,3216,3223,
-3228,3230,3232,3233,3233,3234,3235,3235,3234,3232,3228,3224,3220,3215,3209,3203,3196,3188,3181,3175,3170,
-3168,3167,3166,3165,3162,3157,3150,3141,3132,3123,3114,3106,3099,3093,3088,3085,3082,3080,3077,3075,3072,
-3070,3069,3069,3070,3072,3073,3075,3076,3078,3082,3088,3096,3104,3112,3118,3121,3122,3120,3119,3119,3120,
-3122,3123,3123,3120,3116,3112,3109,3109,3110,3112,3111,3108,3100,3090,3078,3068,3060,3054,3050,3045,3038,
-3027,3015,3001,2988,2975,2964,2952,2938,2923,2906,2888,2872,2860,2851,2846,2844,2842,2840,2836,2831,2826,
-2820,2814,2808,2802,2796,2791,2787,2783,2780,2775,2767,2754,2737,2715,2691,2667,2643,2623,2605,2589,2573,
-2557,2541,2525,2511,2500,2491,2484,2477,2468,2456,2440,2420,2399,2377,2357,2338,2320,2304,2289,2274,2262,
-2251,2243,2238,2235,2233,2231,2229,2225,2220,2212,2202,2188,2171,2149,2123,2094,2062,2029,1995,1960,1923,
-1883,1839,1791,1739,1684,1627,1570,1515,1463,1414,1369,1327,1288,1250,1213,1176,1140,1103,1066,1028,991,
-955,919,884,850,817,783,748,711,671,628,582,533,483,433,384,338,293,250,210,172,137,
-106,79,55,35,16,-2,-22,-44,-67,-92,-117,-142,-167,-193,-220,-249,-280,-313,-349,-387,-425,
--464,-503,-540,-575,-607,-634,-658,-679,-697,-715,-733,-751,-768,-784,-798,-809,-819,-828,-839,-853,-871,
--892,-916,-942,-971,-1002,-1038,-1078,-1121,-1167,-1211,-1252,-1286,-1313,-1335,-1352,-1368,-1386,-1406,-1430,-1457,-1485,
--1515,-1545,-1576,-1607,-1640,-1674,-1709,-1746,-1783,-1821,-1860,-1900,-1941,-1981,-2021,-2058,-2093,-2125,-2154,-2181,-2207,
--2233,-2260,-2287,-2315,-2344,-2373,-2401,-2428,-2453,-2476,-2497,-2518,-2538,-2561,-2586,-2613,-2643,-2674,-2705,-2734,-2762,
--2787,-2810,-2832,-2853,-2873,-2893,-2913,-2934,-2955,-2976,-2999,-3022,-3045,-3067,-3088,-3107,-3124,-3140,-3155,-3169,-3183,
--3197,-3210,-3224,-3238,-3255,-3273,-3294,-3317,-3341,-3363,-3383,-3399,-3411,-3421,-3430,-3439,-3449,-3461,-3474,-3488,-3502,
--3514,-3525,-3535,-3543,-3551,-3558,-3565,-3572,-3579,-3586,-3595,-3605,-3617,-3629,-3642,-3653,-3664,-3673,-3681,-3686,-3690,
--3692,-3693,-3692,-3691,-3692,-3694,-3700,-3710,-3721,-3734,-3746,-3756,-3762,-3764,-3761,-3755,-3747,-3737,-3726,-3715,-3704,
--3693,-3683,-3672,-3663,-3654,-3646,-3638,-3631,-3625,-3620,-3616,-3614,-3612,-3611,-3611,-3609,-3607,-3604,-3600,-3596,-3591,
--3586,-3580,-3572,-3561,-3549,-3536,-3523,-3513,-3507,-3507,-3510,-3515,-3520,-3522,-3520,-3511,-3497,-3478,-3458,-3436,-3414,
--3393,-3374,-3357,-3344,-3337,-3337,-3344,-3357,-3375,-3394,-3411,-3424,-3429,-3429,-3425,-3419,-3414,-3412,-3415,-3422,-3432,
--3444,-3456,-3466,-3475,-3483,-3490,-3498,-3507,-3518,-3532,-3548,-3567,-3587,-3608,-3629,-3650,-3670,-3689,-3708,-3727,-3746,
--3763,-3779,-3794,-3809,-3823,-3840,-3859,-3882,-3908,-3936,-3965,-3994,-4020,-4044,-4066,-4086,-4106,-4125,-4145,-4167,-4194,
--4227,-4268,-4317,-4374,-4435,-4496,-4553,-4602,-4641,-4669,-4688,-4702,-4713,-4723,-4733,-4743,-4751,-4756,-4758,-4758,-4758,
--4759,-4764,-4772,-4783,-4796,-4808,-4819,-4827,-4834,-4839,-4845,-4853,-4862,-4873,-4885,-4895,-4903,-4907,-4908,-4904,-4898,
--4890,-4882,-4875,-4871,-4869,-4870,-4872,-4874,-4875,-4875,-4872,-4868,-4862,-4855,-4848,-4842,-4836,-4829,-4822,-4813,-4805,
--4796,-4787,-4779,-4772,-4765,-4758,-4750,-4742,-4732,-4721,-4710,-4698,-4686,-4674,-4662,-4649,-4636,-4624,-4611,-4599,-4586,
--4573,-4560,-4548,-4537,-4526,-4517,-4508,-4498,-4488,-4477,-4464,-4451,-4439,-4428,-4418,-4408,-4399,-4387,-4373,-4357,-4339,
--4322,-4307,-4295,-4284,-4274,-4264,-4253,-4241,-4230,-4220,-4213,-4207,-4204,-4199,-4193,-4182,-4169,-4153,-4138,-4124,-4114,
--4106,-4099,-4091,-4081,-4068,-4053,-4036,-4019,-4002,-3988,-3975,-3963,-3953,-3942,-3932,-3923,-3913,-3904,-3893,-3881,-3868,
--3854,-3840,-3826,-3813,-3801,-3790,-3780,-3771,-3762,-3755,-3748,-3743,-3738,-3733,-3727,-3719,-3710,-3700,-3691,-3682,-3675,
--3668,-3663,-3657,-3652,-3646,-3639,-3633,-3627,-3621,-3615,-3609,-3602,-3596,-3592,-3588,-3586,-3584,-3582,-3579,-3575,-3569,
--3562,-3554,-3548,-3544,-3541,-3539,-3536,-3534,-3531,-3528,-3525,-3524,-3524,-3524,-3524,-3521,-3516,-3508,-3499,-3490,-3482,
--3474,-3468,-3462,-3454,-3444,-3433,-3420,-3408,-3397,-3389,-3382,-3378,-3374,-3370,-3365,-3361,-3355,-3350,-3344,-3338,-3331,
--3321,-3310,-3297,-3283,-3269,-3255,-3242,-3230,-3220,-3210,-3201,-3194,-3187,-3182,-3177,-3172,-3167,-3161,-3154,-3145,-3134,
--3121,-3108,-3095,-3081,-3068,-3055,-3044,-3035,-3028,-3023,-3019,-3015,-3011,-3005,-2998,-2989,-2980,-2971,-2963,-2957,-2952,
--2948,-2946,-2944,-2944,-2943,-2942,-2938,-2933,-2924,-2911,-2895,-2876,-2856,-2834,-2813,-2792,-2771,-2752,-2734,-2718,-2704,
--2693,-2685,-2678,-2673,-2668,-2662,-2655,-2647,-2638,-2629,-2621,-2612,-2604,-2595,-2586,-2578,-2570,-2562,-2555,-2550,-2545,
--2540,-2536,-2533,-2529,-2527,-2525,-2523,-2521,-2518,-2514,-2509,-2502,-2494,-2485,-2476,-2466,-2455,-2445,-2434,-2423,-2412,
--2399,-2386,-2372,-2358,-2343,-2328,-2314,-2300,-2287,-2273,-2259,-2244,-2229,-2215,-2201,-2189,-2177,-2168,-2159,-2150,-2140,
--2129,-2117,-2103,-2089,-2075,-2062,-2050,-2039,-2030,-2021,-2012,-2002,-1992,-1982,-1971,-1959,-1947,-1933,-1919,-1903,-1887,
--1869,-1850,-1830,-1808,-1787,-1765,-1744,-1724,-1705,-1687,-1669,-1652,-1634,-1615,-1595,-1574,-1553,-1534,-1517,-1502,-1488,
--1477,-1465,-1453,-1440,-1426,-1411,-1394,-1376,-1357,-1337,-1317,-1296,-1278,-1261,-1248,-1239,-1233,-1228,-1222,-1213,-1200,
--1182,-1159,-1133,-1104,-1077,-1051,-1029,-1010,-995,-982,-970,-955,-937,-915,-889,-861,-832,-806,-782,-762,-744,
--727,-708,-686,-661,-634,-605,-576,-546,-516,-484,-450,-415,-379,-345,-313,-285,-259,-234,-208,-178,-144,
--107,-67,-27,11,48,82,116,150,184,218,251,282,311,337,362,388,416,447,481,517,553,
-590,625,660,694,729,764,800,836,871,906,940,974,1009,1046,1083,1121,1158,1194,1227,1258,1287,
-1317,1349,1384,1421,1459,1497,1531,1560,1583,1600,1612,1620,1624,1626,1623,1615,1601,1580,1554,1523,1492,
-1464,1443,1434,1439,1459,1496,1547,1611,1684,1760,1835,1903,1962,2009,2044,2071,2091,2108,2126,2145,2165,
-2186,2207,2225,2243,2259,2276,2293,2311,2327,2338,2341,2335,2318,2292,2262,2229,2196,2165,2134,2104,2074,
-2045,2021,2005,1998,2000,2007,2014,2015,2007,1991,1972,1959,1959,1979,2019,2076,2140,2201,2253,2290,2313,
-2324,2328,2327,2323,2315,2303,2287,2271,2258,2252,2253,2259,2264,2261,2244,2209,2159,2100,2041,1991,1955,
-1935,1928,1931,1938,1945,1954,1963,1976,1991,2008,2026,2042,2055,2067,2079,2093,2110,2126,2139,2144,2137,
-2117,2088,2056,2026,2005,1996,1997,2004,2013,2020,2023,2024,2023,2025,2029,2035,2040,2043,2041,2035,2025,
-2014,2005,1999,1994,1990,1984,1974,1962,1948,1936,1927,1921,1917,1912,1905,1892,1875,1855,1836,1818,1805,
-1795,1789,1784,1779,1772,1763,1753,1743,1734,1726,1720,1715,1710,1706,1701,1696,1689,1680,1668,1653,1636,
-1616,1596,1577,1559,1544,1531,1519,1507,1496,1485,1476,1469,1464,1461,1457,1452,1443,1431,1414,1396,1378,
-1362,1350,1342,1338,1338,1339,1343,1348,1354,1362,1371,1380,1387,1391,1391,1385,1375,1362,1347,1334,1324,
-1319,1320,1327,1337,1349,1359,1364,1364,1357,1344,1329,1315,1303,1295,1293,1295,1300,1305,1308,1310,1310,
-1309,1310,1311,1315,1321,1327,1332,1337,1339,1341,1342,1344,1349,1356,1366,1376,1370,1382,1393,1402,1409,
-1416,1423,1431,1441,1453,1467,1482,1497,1513,1530,1547,1566,1586,1608,1632,1657,1684,1710,1735,1759,1782,
-1805,1828,1853,1878,1905,1929,1951,1968,1981,1990,1997,2006,2018,2035,2057,2085,2116,2149,2182,2213,2242,
-2267,2289,2306,2318,2326,2331,2335,2339,2345,2353,2363,2372,2379,2382,2382,2378,2373,2370,2368,2368,2371,
-2374,2377,2380,2383,2388,2396,2405,2415,2424,2428,2426,2418,2406,2391,2377,2368,2365,2368,2378,2391,2406,
-2420,2432,2439,2442,2441,2436,2430,2423,2418,2416,2417,2422,2429,2437,2444,2450,2456,2462,2469,2479,2492,
-2507,2523,2538,2551,2562,2570,2577,2584,2593,2603,2613,2624,2633,2641,2645,2648,2648,2647,2647,2647,2649,
-2654,2662,2673,2688,2706,2726,2746,2766,2787,2806,2826,2846,2866,2886,2906,2924,2941,2956,2971,2986,3002,
-3021,3041,3061,3081,3100,3116,3130,3143,3155,3167,3178,3188,3196,3201,3204,3206,3206,3205,3204,3204,3203,
-3202,3199,3196,3191,3185,3179,3173,3166,3160,3154,3149,3146,3143,3142,3142,3143,3143,3142,3139,3134,3126,
-3117,3106,3095,3085,3077,3071,3066,3064,3062,3059,3055,3050,3045,3040,3037,3035,3036,3037,3039,3041,3042,
-3046,3051,3059,3069,3081,3092,3101,3106,3109,3109,3109,3109,3111,3112,3112,3110,3106,3099,3092,3087,3084,
-3083,3083,3083,3079,3072,3062,3051,3041,3033,3028,3024,3021,3016,3008,2997,2985,2972,2959,2946,2933,2918,
-2902,2884,2865,2847,2831,2820,2811,2806,2803,2801,2798,2795,2791,2786,2780,2774,2767,2760,2753,2746,2739,
-2731,2722,2710,2696,2679,2659,2640,2621,2605,2591,2578,2565,2551,2534,2517,2500,2486,2475,2467,2460,2453,
-2443,2429,2410,2387,2362,2337,2313,2291,2270,2249,2230,2212,2195,2181,2170,2162,2157,2153,2151,2149,2147,
-2144,2141,2137,2130,2118,2100,2077,2048,2014,1979,1942,1906,1869,1830,1788,1742,1691,1637,1580,1524,1471,
-1422,1377,1338,1302,1268,1235,1203,1171,1139,1106,1072,1037,1001,964,926,888,850,814,779,744,708,
-670,630,587,541,493,444,394,345,296,249,204,162,125,91,62,37,14,-7,-30,-55,-81,
--107,-132,-155,-176,-195,-214,-234,-258,-285,-317,-353,-392,-432,-474,-514,-553,-589,-621,-648,-672,-693,
--713,-732,-752,-772,-792,-810,-826,-840,-852,-863,-876,-890,-908,-927,-948,-971,-997,-1026,-1061,-1101,-1146,
--1194,-1242,-1285,-1321,-1348,-1368,-1383,-1396,-1411,-1430,-1454,-1483,-1515,-1548,-1582,-1616,-1650,-1684,-1719,-1754,-1791,
--1829,-1868,-1907,-1947,-1987,-2027,-2066,-2103,-2137,-2169,-2198,-2225,-2251,-2276,-2302,-2328,-2354,-2381,-2409,-2437,-2464,
--2491,-2517,-2542,-2566,-2590,-2615,-2640,-2668,-2696,-2725,-2754,-2783,-2810,-2835,-2858,-2880,-2901,-2921,-2941,-2960,-2979,
--3000,-3021,-3043,-3067,-3091,-3116,-3139,-3160,-3179,-3195,-3209,-3220,-3229,-3238,-3247,-3258,-3271,-3288,-3309,-3332,-3357,
--3382,-3404,-3423,-3437,-3447,-3456,-3463,-3471,-3482,-3495,-3509,-3524,-3539,-3553,-3567,-3579,-3590,-3600,-3610,-3619,-3626,
--3634,-3641,-3649,-3658,-3668,-3679,-3690,-3701,-3711,-3719,-3727,-3734,-3740,-3747,-3754,-3761,-3768,-3776,-3784,-3795,-3808,
--3823,-3840,-3858,-3875,-3890,-3900,-3905,-3903,-3895,-3880,-3861,-3838,-3814,-3791,-3770,-3754,-3741,-3731,-3724,-3718,-3712,
--3704,-3697,-3690,-3685,-3683,-3682,-3682,-3682,-3682,-3679,-3676,-3671,-3666,-3661,-3656,-3651,-3644,-3635,-3625,-3615,-3605,
--3598,-3595,-3596,-3599,-3603,-3605,-3604,-3598,-3587,-3572,-3555,-3535,-3515,-3494,-3473,-3453,-3435,-3422,-3414,-3415,-3423,
--3438,-3458,-3477,-3494,-3505,-3510,-3507,-3500,-3491,-3483,-3477,-3476,-3479,-3487,-3498,-3510,-3522,-3533,-3543,-3552,-3562,
--3573,-3586,-3602,-3620,-3640,-3660,-3678,-3696,-3712,-3727,-3743,-3760,-3779,-3798,-3818,-3838,-3856,-3873,-3889,-3904,-3920,
--3937,-3955,-3974,-3994,-4015,-4038,-4061,-4085,-4109,-4132,-4153,-4173,-4192,-4212,-4236,-4266,-4304,-4349,-4400,-4456,-4511,
--4563,-4610,-4650,-4684,-4713,-4738,-4760,-4778,-4791,-4801,-4806,-4807,-4805,-4803,-4802,-4804,-4810,-4819,-4830,-4842,-4853,
--4862,-4868,-4872,-4874,-4877,-4881,-4888,-4898,-4911,-4924,-4935,-4942,-4944,-4940,-4932,-4921,-4909,-4900,-4893,-4889,-4889,
--4889,-4890,-4891,-4889,-4887,-4884,-4880,-4875,-4870,-4864,-4856,-4847,-4838,-4828,-4818,-4809,-4800,-4793,-4785,-4777,-4769,
--4760,-4749,-4737,-4724,-4711,-4697,-4683,-4670,-4657,-4644,-4633,-4621,-4608,-4595,-4581,-4567,-4554,-4541,-4531,-4521,-4512,
--4502,-4492,-4481,-4470,-4460,-4452,-4444,-4437,-4430,-4420,-4408,-4393,-4377,-4361,-4345,-4332,-4319,-4308,-4296,-4283,-4271,
--4259,-4249,-4241,-4236,-4231,-4226,-4217,-4206,-4192,-4177,-4162,-4151,-4143,-4138,-4134,-4129,-4121,-4110,-4096,-4080,-4063,
--4047,-4033,-4020,-4009,-3999,-3990,-3982,-3974,-3965,-3957,-3946,-3934,-3921,-3908,-3894,-3882,-3871,-3860,-3850,-3840,-3830,
--3820,-3811,-3802,-3795,-3790,-3785,-3781,-3776,-3770,-3763,-3755,-3747,-3740,-3732,-3725,-3717,-3709,-3701,-3693,-3687,-3682,
--3678,-3675,-3671,-3666,-3661,-3656,-3651,-3648,-3646,-3645,-3643,-3640,-3636,-3630,-3623,-3616,-3610,-3605,-3601,-3598,-3594,
--3589,-3585,-3581,-3578,-3576,-3575,-3574,-3572,-3569,-3563,-3556,-3549,-3542,-3537,-3533,-3529,-3525,-3519,-3510,-3499,-3486,
--3474,-3462,-3452,-3445,-3438,-3433,-3428,-3424,-3419,-3414,-3409,-3403,-3396,-3388,-3378,-3367,-3355,-3342,-3329,-3316,-3303,
--3292,-3281,-3272,-3264,-3257,-3251,-3246,-3240,-3234,-3225,-3216,-3205,-3194,-3183,-3172,-3163,-3155,-3146,-3138,-3129,-3119,
--3109,-3100,-3092,-3084,-3078,-3071,-3064,-3056,-3047,-3037,-3026,-3016,-3006,-2997,-2989,-2982,-2975,-2968,-2960,-2952,-2943,
--2934,-2925,-2917,-2909,-2900,-2890,-2877,-2861,-2842,-2820,-2797,-2775,-2755,-2738,-2726,-2716,-2710,-2704,-2699,-2692,-2685,
--2677,-2667,-2657,-2647,-2636,-2626,-2616,-2607,-2599,-2592,-2586,-2581,-2576,-2572,-2568,-2563,-2559,-2556,-2552,-2549,-2545,
--2541,-2536,-2530,-2523,-2516,-2509,-2502,-2495,-2487,-2478,-2467,-2456,-2442,-2428,-2413,-2398,-2383,-2369,-2355,-2343,-2330,
--2318,-2306,-2293,-2279,-2265,-2251,-2237,-2224,-2213,-2201,-2190,-2179,-2167,-2154,-2140,-2127,-2115,-2104,-2096,-2088,-2081,
--2073,-2064,-2053,-2040,-2026,-2012,-1998,-1986,-1973,-1961,-1948,-1934,-1917,-1897,-1876,-1853,-1829,-1805,-1781,-1759,-1739,
--1721,-1704,-1689,-1674,-1658,-1642,-1623,-1605,-1585,-1566,-1548,-1532,-1517,-1504,-1491,-1478,-1464,-1450,-1435,-1418,-1400,
--1380,-1359,-1336,-1313,-1290,-1269,-1251,-1237,-1226,-1218,-1211,-1202,-1192,-1179,-1162,-1142,-1121,-1099,-1078,-1058,-1040,
--1024,-1009,-994,-977,-958,-935,-910,-883,-856,-830,-805,-783,-761,-738,-714,-689,-661,-631,-602,-573,-544,
--516,-486,-456,-424,-392,-360,-331,-303,-276,-249,-220,-187,-150,-109,-68,-26,12,50,85,120,155,
-191,226,261,292,320,345,367,389,412,438,468,501,535,571,606,641,676,711,746,780,815,
-849,883,917,952,990,1029,1070,1111,1151,1189,1224,1255,1285,1315,1347,1381,1417,1453,1486,1514,1533,
-1542,1541,1530,1514,1494,1473,1454,1439,1427,1419,1416,1418,1426,1442,1468,1506,1557,1619,1692,1772,1854,
-1933,2005,2066,2114,2149,2174,2190,2201,2210,2217,2223,2228,2231,2232,2233,2234,2238,2247,2260,2275,2289,
-2298,2298,2285,2262,2229,2193,2156,2124,2099,2078,2062,2047,2032,2018,2008,2003,2007,2016,2028,2038,2039,
-2029,2009,1984,1963,1954,1963,1990,2033,2085,2137,2182,2217,2241,2257,2267,2275,2280,2281,2276,2266,2250,
-2231,2212,2194,2179,2163,2142,2114,2076,2030,1982,1937,1899,1874,1861,1858,1864,1875,1889,1906,1924,1944,
-1964,1983,1998,2008,2014,2016,2019,2024,2031,2038,2043,2040,2028,2007,1982,1958,1940,1932,1935,1944,1955,
-1962,1962,1956,1947,1939,1936,1940,1949,1960,1968,1970,1964,1952,1938,1924,1914,1907,1903,1900,1895,1888,
-1879,1869,1861,1855,1851,1848,1844,1837,1828,1818,1808,1800,1793,1788,1783,1777,1767,1753,1736,1717,1697,
-1679,1664,1654,1646,1643,1641,1639,1636,1630,1619,1603,1582,1557,1531,1506,1484,1465,1451,1441,1431,1422,
-1413,1404,1397,1391,1388,1386,1385,1382,1375,1365,1352,1337,1323,1312,1305,1301,1300,1299,1298,1295,1292,
-1289,1289,1292,1299,1309,1320,1328,1333,1333,1326,1316,1304,1292,1284,1281,1284,1291,1300,1309,1315,1317,
-1313,1306,1297,1288,1281,1277,1276,1277,1278,1278,1276,1274,1273,1273,1275,1280,1287,1294,1301,1305,1308,
-1310,1311,1315,1321,1330,1342,1356,1370,1360,1373,1384,1394,1404,1415,1426,1438,1450,1463,1476,1489,1503,
-1519,1536,1555,1575,1597,1621,1647,1674,1702,1729,1754,1778,1800,1820,1840,1860,1879,1899,1918,1935,1949,
-1960,1969,1978,1990,2006,2028,2054,2084,2115,2144,2171,2195,2215,2232,2248,2261,2273,2283,2292,2300,2308,
-2316,2325,2334,2343,2349,2352,2352,2349,2345,2341,2338,2338,2339,2343,2347,2352,2357,2363,2370,2376,2381,
-2382,2378,2368,2355,2340,2327,2319,2318,2324,2337,2353,2370,2384,2394,2399,2399,2395,2389,2382,2375,2370,
-2366,2366,2367,2371,2377,2384,2391,2398,2405,2412,2420,2430,2440,2452,2465,2477,2489,2500,2510,2521,2533,
-2545,2558,2571,2583,2592,2599,2603,2603,2602,2599,2596,2595,2595,2600,2610,2624,2644,2666,2690,2715,2737,
-2758,2777,2794,2812,2830,2849,2869,2888,2906,2922,2938,2954,2970,2988,3008,3029,3049,3067,3083,3096,3108,
-3118,3127,3137,3147,3157,3166,3172,3177,3179,3179,3178,3176,3173,3170,3167,3163,3158,3153,3149,3144,3139,
-3135,3130,3126,3122,3119,3116,3115,3114,3114,3113,3112,3108,3102,3093,3083,3071,3061,3052,3046,3042,3040,
-3037,3033,3028,3021,3014,3008,3004,3003,3005,3007,3010,3012,3014,3017,3023,3031,3042,3054,3067,3078,3086,
-3090,3093,3095,3096,3099,3101,3102,3101,3097,3090,3082,3075,3069,3066,3065,3063,3059,3053,3044,3035,3025,
-3017,3011,3007,3004,2999,2994,2986,2976,2966,2955,2944,2931,2917,2900,2881,2860,2840,2821,2805,2792,2782,
-2775,2770,2766,2762,2758,2753,2746,2738,2729,2718,2708,2697,2686,2676,2666,2655,2642,2627,2613,2598,2585,
-2574,2563,2553,2541,2528,2512,2495,2479,2466,2456,2448,2442,2434,2423,2406,2385,2360,2334,2308,2282,2258,
-2234,2210,2185,2161,2138,2118,2101,2088,2078,2071,2066,2062,2059,2058,2058,2058,2056,2051,2039,2021,1995,
-1964,1929,1894,1859,1825,1791,1756,1718,1675,1629,1580,1529,1479,1432,1387,1346,1307,1270,1234,1200,1166,
-1134,1101,1068,1034,999,961,922,882,843,805,768,732,697,660,623,582,539,494,447,399,351,
-304,258,214,174,139,107,79,53,27,0,-30,-63,-96,-127,-154,-177,-195,-210,-225,-242,-263,
--289,-321,-358,-397,-438,-479,-520,-560,-598,-633,-665,-694,-721,-745,-769,-792,-814,-834,-853,-868,-881,
--891,-901,-912,-924,-940,-957,-977,-999,-1024,-1052,-1085,-1123,-1166,-1212,-1258,-1300,-1336,-1364,-1385,-1401,-1415,
--1431,-1450,-1475,-1505,-1539,-1575,-1613,-1652,-1690,-1728,-1766,-1805,-1843,-1881,-1920,-1958,-1997,-2035,-2073,-2109,-2144,
--2176,-2206,-2234,-2261,-2286,-2310,-2334,-2358,-2383,-2408,-2434,-2461,-2489,-2518,-2548,-2578,-2607,-2636,-2663,-2689,-2715,
--2740,-2765,-2790,-2815,-2840,-2864,-2888,-2911,-2934,-2955,-2976,-2996,-3016,-3036,-3056,-3077,-3100,-3124,-3148,-3173,-3197,
--3218,-3236,-3251,-3262,-3270,-3276,-3282,-3289,-3300,-3314,-3333,-3356,-3380,-3403,-3424,-3442,-3455,-3465,-3474,-3483,-3494,
--3508,-3524,-3542,-3561,-3579,-3597,-3612,-3626,-3638,-3649,-3659,-3668,-3677,-3686,-3696,-3707,-3720,-3734,-3748,-3760,-3770,
--3776,-3780,-3783,-3786,-3791,-3800,-3812,-3828,-3846,-3864,-3882,-3899,-3915,-3933,-3951,-3969,-3987,-4004,-4017,-4024,-4024,
--4014,-3996,-3971,-3940,-3908,-3877,-3850,-3829,-3815,-3805,-3799,-3795,-3789,-3782,-3773,-3764,-3756,-3751,-3747,-3747,-3747,
--3748,-3748,-3747,-3744,-3740,-3736,-3733,-3729,-3724,-3718,-3711,-3702,-3693,-3685,-3680,-3678,-3679,-3681,-3682,-3682,-3678,
--3671,-3660,-3647,-3630,-3611,-3591,-3568,-3544,-3521,-3500,-3484,-3476,-3477,-3486,-3503,-3524,-3547,-3566,-3579,-3585,-3582,
--3573,-3560,-3547,-3536,-3531,-3532,-3539,-3551,-3566,-3583,-3598,-3611,-3623,-3635,-3648,-3663,-3681,-3700,-3719,-3738,-3755,
--3771,-3786,-3800,-3816,-3834,-3854,-3875,-3897,-3918,-3936,-3953,-3967,-3980,-3991,-4002,-4014,-4027,-4042,-4059,-4080,-4103,
--4129,-4154,-4178,-4199,-4216,-4230,-4243,-4256,-4274,-4299,-4331,-4371,-4416,-4466,-4516,-4564,-4610,-4653,-4692,-4728,-4760,
--4789,-4813,-4833,-4847,-4856,-4861,-4862,-4862,-4863,-4866,-4873,-4882,-4892,-4901,-4908,-4911,-4909,-4905,-4900,-4898,-4900,
--4908,-4920,-4935,-4949,-4959,-4963,-4961,-4953,-4943,-4931,-4921,-4914,-4910,-4908,-4908,-4908,-4907,-4906,-4903,-4899,-4894,
--4889,-4883,-4876,-4868,-4860,-4852,-4844,-4837,-4830,-4823,-4816,-4808,-4800,-4790,-4779,-4767,-4753,-4739,-4724,-4709,-4694,
--4681,-4668,-4657,-4645,-4634,-4622,-4609,-4596,-4583,-4571,-4561,-4551,-4541,-4531,-4520,-4509,-4497,-4486,-4477,-4470,-4463,
--4456,-4448,-4437,-4425,-4412,-4398,-4385,-4373,-4362,-4351,-4340,-4327,-4314,-4302,-4290,-4280,-4272,-4264,-4256,-4247,-4236,
--4223,-4210,-4199,-4189,-4183,-4178,-4174,-4168,-4161,-4152,-4140,-4127,-4114,-4100,-4087,-4074,-4062,-4050,-4040,-4030,-4021,
--4013,-4004,-3994,-3983,-3971,-3959,-3948,-3938,-3929,-3921,-3914,-3906,-3897,-3887,-3877,-3867,-3859,-3852,-3846,-3841,-3836,
--3832,-3826,-3820,-3813,-3806,-3798,-3790,-3780,-3770,-3760,-3752,-3745,-3740,-3737,-3736,-3734,-3731,-3727,-3722,-3716,-3712,
--3709,-3707,-3706,-3704,-3702,-3698,-3693,-3687,-3681,-3675,-3669,-3664,-3658,-3652,-3645,-3638,-3632,-3628,-3625,-3622,-3619,
--3615,-3611,-3605,-3599,-3593,-3590,-3587,-3585,-3583,-3580,-3574,-3565,-3555,-3544,-3533,-3523,-3516,-3509,-3504,-3499,-3494,
--3488,-3483,-3477,-3470,-3463,-3456,-3447,-3437,-3425,-3413,-3401,-3389,-3378,-3368,-3358,-3350,-3342,-3335,-3327,-3319,-3310,
--3299,-3288,-3276,-3264,-3253,-3243,-3236,-3230,-3225,-3220,-3214,-3206,-3197,-3185,-3174,-3162,-3152,-3143,-3135,-3127,-3119,
--3110,-3100,-3089,-3078,-3067,-3056,-3045,-3033,-3021,-3007,-2992,-2976,-2961,-2948,-2938,-2931,-2928,-2926,-2924,-2919,-2911,
--2897,-2879,-2858,-2835,-2813,-2793,-2776,-2763,-2753,-2745,-2737,-2730,-2723,-2714,-2704,-2694,-2682,-2671,-2660,-2649,-2640,
--2631,-2624,-2619,-2613,-2608,-2603,-2598,-2593,-2588,-2584,-2579,-2574,-2568,-2562,-2555,-2548,-2541,-2534,-2527,-2520,-2513,
--2505,-2496,-2485,-2474,-2461,-2449,-2436,-2424,-2411,-2399,-2387,-2374,-2361,-2348,-2335,-2321,-2307,-2294,-2281,-2268,-2256,
--2243,-2231,-2219,-2206,-2193,-2180,-2167,-2156,-2146,-2138,-2131,-2124,-2117,-2107,-2095,-2081,-2065,-2048,-2032,-2017,-2004,
--1991,-1979,-1966,-1952,-1935,-1915,-1894,-1871,-1847,-1823,-1799,-1777,-1755,-1736,-1718,-1701,-1687,-1673,-1659,-1645,-1630,
--1614,-1598,-1581,-1565,-1548,-1533,-1517,-1503,-1488,-1474,-1458,-1441,-1423,-1402,-1380,-1355,-1330,-1305,-1281,-1260,-1242,
--1227,-1215,-1205,-1195,-1185,-1174,-1163,-1149,-1135,-1119,-1102,-1084,-1066,-1047,-1028,-1009,-989,-969,-947,-925,-901,
--877,-852,-826,-800,-773,-746,-717,-686,-656,-625,-595,-567,-539,-513,-486,-460,-433,-405,-378,-350,-322,
--293,-261,-226,-188,-146,-103,-60,-18,19,55,89,122,155,188,222,255,287,316,342,367,391,
-416,442,469,497,527,556,587,618,651,685,720,756,791,826,861,896,931,969,1009,1050,1092,
-1133,1171,1206,1239,1271,1303,1338,1375,1413,1449,1479,1499,1505,1497,1475,1443,1405,1367,1335,1313,1304,
-1310,1330,1364,1408,1462,1523,1591,1664,1741,1820,1900,1977,2046,2104,2149,2179,2197,2205,2208,2210,2215,
-2225,2239,2255,2271,2283,2292,2297,2300,2303,2306,2311,2313,2310,2297,2273,2238,2193,2145,2100,2064,2040,
-2027,2024,2025,2026,2024,2019,2013,2009,2009,2014,2022,2029,2031,2025,2011,1992,1974,1962,1961,1972,1993,
-2020,2049,2074,2095,2111,2125,2139,2152,2164,2174,2178,2176,2167,2152,2134,2114,2093,2070,2043,2011,1975,
-1936,1898,1865,1841,1828,1825,1829,1839,1852,1867,1883,1900,1916,1931,1942,1947,1945,1936,1922,1907,1895,
-1886,1882,1879,1878,1874,1870,1866,1865,1870,1880,1895,1910,1920,1922,1915,1901,1885,1871,1864,1865,1871,
-1880,1887,1888,1882,1871,1857,1845,1835,1830,1828,1826,1822,1815,1806,1795,1783,1773,1765,1760,1755,1752,
-1748,1745,1741,1736,1731,1724,1714,1700,1683,1663,1641,1619,1600,1584,1572,1564,1561,1559,1560,1561,1560,
-1556,1548,1535,1517,1494,1469,1443,1419,1396,1376,1359,1343,1328,1315,1304,1295,1291,1289,1290,1291,1292,
-1289,1284,1277,1271,1267,1267,1271,1277,1282,1284,1280,1270,1255,1238,1224,1215,1213,1219,1231,1245,1258,
-1268,1271,1268,1261,1251,1243,1238,1237,1241,1247,1255,1261,1264,1265,1263,1260,1257,1256,1255,1255,1254,
-1252,1248,1244,1239,1237,1238,1242,1250,1259,1267,1274,1278,1281,1284,1288,1295,1305,1317,1332,1346,1360,
-1355,1366,1377,1388,1401,1415,1429,1443,1456,1468,1480,1492,1506,1522,1541,1563,1586,1610,1635,1660,1685,
-1711,1736,1759,1780,1800,1817,1833,1848,1864,1880,1897,1913,1929,1943,1956,1970,1986,2005,2027,2052,2078,
-2103,2125,2144,2159,2173,2185,2198,2211,2225,2238,2250,2261,2270,2278,2286,2293,2299,2303,2305,2305,2303,
-2300,2298,2297,2299,2303,2310,2317,2324,2331,2335,2338,2337,2333,2326,2316,2303,2290,2279,2273,2273,2281,
-2294,2310,2326,2340,2349,2353,2352,2348,2342,2336,2331,2327,2325,2323,2322,2323,2325,2329,2336,2345,2355,
-2366,2377,2387,2396,2405,2413,2421,2430,2439,2449,2460,2473,2487,2502,2517,2531,2543,2552,2558,2561,2560,
-2556,2551,2546,2543,2544,2551,2564,2583,2607,2634,2662,2689,2712,2732,2749,2765,2780,2796,2814,2833,2851,
-2869,2886,2902,2918,2934,2952,2972,2993,3013,3032,3047,3060,3069,3077,3084,3092,3101,3111,3122,3132,3140,
-3146,3149,3149,3146,3143,3138,3134,3130,3126,3124,3122,3120,3119,3117,3115,3112,3109,3105,3101,3098,3094,
-3092,3089,3085,3079,3072,3062,3050,3038,3028,3019,3013,3009,3007,3005,3002,2997,2991,2985,2981,2978,2977,
-2979,2981,2983,2984,2985,2987,2991,2998,3009,3022,3036,3049,3060,3067,3072,3077,3081,3085,3089,3092,3092,
-3090,3085,3078,3071,3065,3060,3057,3054,3050,3044,3037,3028,3019,3010,3003,2997,2991,2986,2981,2975,2968,
-2960,2952,2942,2930,2915,2898,2879,2858,2837,2817,2799,2783,2769,2757,2747,2739,2732,2725,2718,2710,2701,
-2690,2679,2666,2655,2643,2633,2623,2613,2601,2589,2577,2564,2553,2543,2535,2526,2516,2505,2492,2478,2466,
-2455,2446,2439,2432,2422,2409,2390,2366,2341,2314,2288,2263,2240,2217,2192,2166,2139,2112,2086,2063,2043,
-2026,2012,2000,1989,1981,1975,1971,1970,1969,1966,1960,1948,1929,1904,1874,1843,1812,1783,1755,1727,1697,
-1664,1627,1586,1542,1496,1449,1403,1359,1315,1274,1234,1195,1158,1122,1086,1051,1015,978,939,900,861,
-822,785,749,715,680,645,608,570,530,488,445,401,358,316,276,240,206,177,149,123,95,
-63,28,-10,-50,-89,-125,-153,-175,-192,-206,-222,-241,-266,-297,-333,-371,-411,-450,-488,-526,-565,
--603,-641,-678,-714,-747,-777,-805,-831,-854,-875,-893,-907,-918,-927,-936,-945,-957,-972,-991,-1012,-1037,
--1063,-1092,-1122,-1156,-1192,-1230,-1268,-1305,-1338,-1367,-1391,-1412,-1431,-1451,-1474,-1500,-1531,-1565,-1604,-1644,-1686,
--1729,-1771,-1813,-1854,-1893,-1932,-1969,-2005,-2041,-2076,-2111,-2144,-2176,-2206,-2234,-2259,-2284,-2307,-2329,-2352,-2374,
--2397,-2421,-2446,-2474,-2503,-2534,-2566,-2599,-2631,-2661,-2689,-2714,-2738,-2760,-2782,-2804,-2827,-2851,-2875,-2900,-2926,
--2951,-2977,-3001,-3025,-3048,-3069,-3090,-3110,-3131,-3151,-3172,-3193,-3215,-3236,-3255,-3272,-3286,-3296,-3304,-3310,-3316,
--3325,-3336,-3352,-3372,-3393,-3415,-3436,-3454,-3469,-3482,-3494,-3508,-3523,-3542,-3562,-3585,-3607,-3629,-3648,-3665,-3680,
--3692,-3702,-3711,-3720,-3730,-3742,-3757,-3775,-3796,-3819,-3839,-3856,-3868,-3872,-3871,-3867,-3863,-3863,-3869,-3881,-3900,
--3923,-3947,-3971,-3992,-4010,-4026,-4041,-4054,-4067,-4078,-4085,-4088,-4085,-4074,-4056,-4033,-4006,-3977,-3950,-3926,-3906,
--3892,-3882,-3875,-3869,-3863,-3855,-3846,-3836,-3827,-3820,-3815,-3813,-3813,-3814,-3816,-3816,-3816,-3815,-3813,-3810,-3806,
--3801,-3795,-3788,-3779,-3771,-3763,-3757,-3753,-3752,-3752,-3752,-3752,-3749,-3745,-3737,-3727,-3715,-3699,-3681,-3660,-3637,
--3612,-3588,-3567,-3551,-3543,-3545,-3555,-3574,-3596,-3620,-3640,-3652,-3656,-3651,-3637,-3620,-3603,-3591,-3585,-3589,-3600,
--3617,-3636,-3655,-3673,-3687,-3700,-3713,-3726,-3742,-3760,-3780,-3801,-3821,-3839,-3855,-3871,-3887,-3903,-3921,-3939,-3958,
--3977,-3995,-4012,-4027,-4042,-4055,-4068,-4081,-4093,-4106,-4119,-4135,-4152,-4171,-4192,-4213,-4232,-4249,-4262,-4273,-4283,
--4294,-4307,-4325,-4349,-4379,-4413,-4450,-4490,-4529,-4569,-4609,-4649,-4690,-4731,-4771,-4809,-4842,-4869,-4889,-4900,-4905,
--4906,-4905,-4907,-4912,-4920,-4931,-4941,-4949,-4951,-4948,-4941,-4932,-4924,-4921,-4923,-4930,-4940,-4951,-4959,-4964,-4965,
--4962,-4956,-4949,-4943,-4938,-4934,-4931,-4929,-4926,-4922,-4917,-4912,-4905,-4898,-4891,-4884,-4878,-4872,-4867,-4863,-4858,
--4854,-4849,-4843,-4836,-4828,-4819,-4809,-4798,-4786,-4773,-4759,-4745,-4730,-4716,-4703,-4690,-4678,-4665,-4653,-4642,-4630,
--4620,-4610,-4601,-4592,-4582,-4571,-4559,-4546,-4533,-4521,-4511,-4503,-4495,-4488,-4480,-4470,-4459,-4446,-4434,-4423,-4413,
--4404,-4395,-4385,-4374,-4361,-4348,-4334,-4322,-4310,-4301,-4292,-4284,-4276,-4267,-4259,-4250,-4243,-4235,-4227,-4220,-4211,
--4203,-4194,-4186,-4177,-4168,-4159,-4148,-4135,-4121,-4107,-4092,-4080,-4069,-4060,-4052,-4044,-4036,-4027,-4017,-4008,-3999,
--3992,-3986,-3980,-3974,-3967,-3959,-3950,-3941,-3932,-3924,-3917,-3910,-3903,-3895,-3888,-3881,-3874,-3867,-3861,-3854,-3847,
--3839,-3830,-3821,-3814,-3809,-3806,-3804,-3802,-3799,-3794,-3789,-3782,-3776,-3771,-3767,-3765,-3764,-3762,-3759,-3755,-3749,
--3743,-3737,-3730,-3724,-3717,-3710,-3703,-3696,-3689,-3684,-3679,-3676,-3672,-3668,-3663,-3658,-3652,-3647,-3643,-3641,-3638,
--3636,-3632,-3627,-3620,-3612,-3603,-3594,-3587,-3581,-3576,-3571,-3566,-3561,-3555,-3549,-3543,-3536,-3530,-3522,-3513,-3502,
--3490,-3477,-3465,-3453,-3444,-3435,-3428,-3422,-3415,-3407,-3398,-3387,-3376,-3365,-3353,-3341,-3330,-3320,-3311,-3302,-3295,
--3288,-3281,-3273,-3264,-3255,-3245,-3234,-3224,-3214,-3204,-3195,-3185,-3175,-3164,-3152,-3141,-3129,-3118,-3107,-3096,-3084,
--3070,-3054,-3036,-3017,-2997,-2979,-2964,-2953,-2947,-2943,-2942,-2941,-2937,-2931,-2920,-2906,-2890,-2871,-2853,-2836,-2820,
--2805,-2792,-2780,-2770,-2759,-2749,-2739,-2728,-2717,-2707,-2696,-2686,-2678,-2670,-2662,-2656,-2650,-2643,-2637,-2631,-2625,
--2619,-2613,-2606,-2599,-2591,-2583,-2574,-2566,-2558,-2551,-2544,-2537,-2529,-2520,-2510,-2500,-2489,-2479,-2469,-2460,-2451,
--2441,-2430,-2417,-2403,-2388,-2373,-2358,-2345,-2332,-2319,-2307,-2296,-2284,-2272,-2259,-2247,-2235,-2223,-2212,-2201,-2191,
--2181,-2172,-2163,-2153,-2143,-2131,-2118,-2103,-2088,-2072,-2057,-2042,-2028,-2013,-1998,-1982,-1965,-1947,-1928,-1909,-1889,
--1869,-1849,-1828,-1806,-1784,-1762,-1741,-1722,-1706,-1692,-1680,-1668,-1657,-1644,-1629,-1612,-1594,-1575,-1557,-1539,-1523,
--1507,-1492,-1476,-1459,-1439,-1418,-1394,-1369,-1343,-1318,-1295,-1274,-1255,-1239,-1224,-1211,-1199,-1187,-1176,-1166,-1155,
--1145,-1133,-1119,-1103,-1085,-1065,-1044,-1023,-1003,-983,-963,-942,-921,-898,-872,-844,-815,-784,-752,-720,-688,
--657,-626,-597,-569,-541,-515,-489,-464,-439,-415,-391,-365,-338,-308,-274,-236,-194,-151,-106,-62,-21,
-17,53,86,119,151,183,214,244,273,301,329,356,384,412,439,466,491,515,539,563,590,
-621,655,691,729,767,803,837,871,904,940,978,1018,1059,1100,1140,1178,1214,1250,1286,1324,1363,
-1402,1435,1460,1473,1471,1455,1425,1387,1346,1310,1284,1273,1281,1308,1354,1415,1489,1570,1654,1738,1819,
-1895,1963,2024,2076,2118,2149,2169,2181,2185,2187,2188,2194,2207,2227,2253,2282,2311,2336,2355,2368,2375,
-2377,2374,2368,2355,2335,2305,2264,2216,2163,2112,2068,2036,2019,2014,2019,2028,2034,2036,2031,2022,2011,
-2002,1997,1996,1998,1999,1997,1992,1984,1975,1968,1964,1964,1967,1973,1978,1983,1988,1993,2000,2010,2021,
-2033,2042,2046,2045,2039,2029,2019,2008,1997,1985,1969,1947,1921,1892,1863,1839,1823,1817,1819,1829,1841,
-1855,1867,1878,1886,1891,1893,1891,1884,1870,1852,1830,1808,1788,1774,1767,1765,1768,1775,1784,1795,1808,
-1823,1838,1852,1863,1867,1864,1855,1842,1828,1817,1812,1811,1814,1817,1818,1816,1809,1801,1792,1785,1782,
-1781,1781,1780,1775,1766,1753,1738,1722,1707,1694,1684,1675,1668,1662,1656,1650,1643,1635,1624,1610,1593,
-1575,1557,1539,1524,1513,1504,1498,1493,1488,1483,1479,1475,1471,1468,1464,1458,1450,1437,1420,1400,1376,
-1351,1324,1298,1274,1252,1234,1220,1212,1209,1210,1213,1216,1217,1216,1212,1207,1204,1205,1211,1221,1232,
-1242,1246,1242,1230,1211,1188,1167,1150,1142,1143,1153,1167,1184,1199,1210,1214,1214,1210,1205,1200,1199,
-1200,1203,1207,1211,1214,1215,1216,1217,1218,1220,1223,1224,1225,1223,1219,1214,1210,1208,1210,1215,1223,
-1232,1241,1248,1253,1259,1265,1273,1284,1298,1313,1328,1342,1355,1354,1365,1376,1387,1400,1415,1429,1443,
-1455,1466,1477,1489,1505,1523,1545,1568,1593,1617,1641,1663,1684,1704,1723,1742,1759,1774,1788,1801,1814,
-1827,1843,1861,1880,1900,1919,1938,1956,1974,1992,2012,2032,2052,2071,2088,2103,2117,2129,2142,2156,2170,
-2185,2198,2210,2219,2226,2233,2238,2244,2249,2253,2256,2257,2256,2255,2254,2255,2259,2265,2274,2282,2289,
-2292,2292,2289,2282,2272,2261,2249,2239,2231,2227,2229,2236,2247,2261,2276,2288,2296,2299,2299,2296,2292,
-2290,2288,2288,2289,2289,2289,2287,2286,2286,2290,2296,2307,2319,2333,2346,2357,2367,2374,2380,2385,2392,
-2399,2409,2419,2432,2445,2459,2473,2486,2497,2506,2511,2513,2511,2506,2500,2494,2491,2494,2503,2519,2541,
-2568,2597,2626,2653,2676,2696,2713,2729,2745,2761,2779,2798,2817,2834,2850,2865,2879,2893,2909,2927,2946,
-2965,2984,3001,3015,3026,3035,3043,3050,3059,3069,3079,3089,3099,3106,3110,3112,3110,3107,3102,3098,3093,
-3090,3088,3088,3088,3090,3092,3094,3095,3096,3095,3093,3090,3085,3078,3070,3060,3049,3035,3021,3007,2994,
-2983,2975,2970,2967,2966,2966,2965,2962,2959,2956,2953,2951,2949,2949,2948,2948,2947,2946,2948,2952,2960,
-2971,2985,2999,3014,3026,3035,3043,3049,3055,3061,3067,3072,3075,3075,3074,3070,3065,3060,3056,3051,3047,
-3042,3036,3029,3020,3010,3001,2991,2983,2976,2969,2964,2958,2952,2946,2937,2926,2912,2896,2879,2860,2841,
-2823,2806,2790,2774,2759,2745,2731,2718,2706,2695,2686,2676,2667,2657,2646,2635,2624,2613,2603,2593,2583,
-2571,2558,2545,2532,2521,2511,2503,2496,2489,2481,2473,2463,2453,2445,2437,2430,2422,2411,2396,2377,2354,
-2329,2303,2279,2257,2236,2216,2194,2170,2144,2116,2087,2059,2032,2007,1983,1960,1938,1918,1901,1887,1878,
-1873,1870,1867,1861,1851,1835,1815,1791,1766,1740,1713,1686,1658,1626,1592,1554,1513,1471,1428,1386,1344,
-1305,1266,1228,1190,1153,1114,1076,1036,995,955,914,875,837,801,766,734,701,669,636,601,565,
-528,490,451,413,376,340,307,276,249,223,197,169,137,100,57,12,-33,-74,-109,-135,-153,
--166,-179,-196,-220,-251,-288,-329,-371,-411,-448,-484,-518,-553,-590,-628,-667,-705,-741,-774,-804,-832,
--858,-881,-902,-920,-936,-949,-960,-973,-988,-1006,-1029,-1056,-1085,-1115,-1144,-1173,-1200,-1227,-1254,-1281,-1309,
--1337,-1365,-1393,-1419,-1446,-1473,-1501,-1532,-1566,-1602,-1642,-1685,-1729,-1774,-1818,-1861,-1902,-1941,-1977,-2011,-2044,
--2076,-2108,-2139,-2169,-2198,-2225,-2249,-2272,-2293,-2313,-2332,-2351,-2372,-2394,-2417,-2443,-2470,-2500,-2531,-2564,-2596,
--2628,-2659,-2687,-2713,-2738,-2762,-2785,-2809,-2833,-2857,-2883,-2909,-2936,-2964,-2992,-3021,-3049,-3077,-3102,-3126,-3146,
--3164,-3180,-3195,-3210,-3225,-3242,-3259,-3276,-3292,-3306,-3317,-3326,-3334,-3342,-3353,-3367,-3384,-3404,-3426,-3448,-3469,
--3488,-3506,-3524,-3543,-3564,-3588,-3612,-3638,-3663,-3687,-3708,-3727,-3742,-3755,-3766,-3775,-3785,-3797,-3811,-3830,-3854,
--3880,-3908,-3934,-3955,-3968,-3973,-3970,-3963,-3955,-3951,-3952,-3961,-3976,-3997,-4019,-4040,-4059,-4075,-4086,-4095,-4102,
--4106,-4109,-4109,-4107,-4101,-4093,-4082,-4069,-4054,-4039,-4024,-4009,-3994,-3981,-3968,-3957,-3946,-3937,-3928,-3919,-3911,
--3903,-3896,-3891,-3886,-3884,-3882,-3882,-3883,-3884,-3884,-3884,-3882,-3879,-3874,-3868,-3860,-3852,-3844,-3837,-3832,-3828,
--3825,-3823,-3821,-3819,-3816,-3811,-3806,-3800,-3792,-3783,-3771,-3757,-3740,-3719,-3697,-3674,-3654,-3639,-3632,-3633,-3643,
--3660,-3681,-3702,-3718,-3727,-3726,-3717,-3701,-3683,-3667,-3657,-3656,-3663,-3677,-3695,-3715,-3733,-3749,-3762,-3774,-3786,
--3800,-3817,-3836,-3856,-3876,-3896,-3914,-3932,-3948,-3964,-3980,-3997,-4013,-4029,-4045,-4062,-4078,-4096,-4114,-4132,-4150,
--4166,-4181,-4195,-4207,-4218,-4229,-4240,-4253,-4266,-4280,-4294,-4308,-4322,-4336,-4350,-4365,-4381,-4399,-4418,-4438,-4460,
--4484,-4510,-4539,-4571,-4608,-4649,-4694,-4741,-4787,-4828,-4863,-4887,-4902,-4909,-4910,-4911,-4913,-4921,-4933,-4948,-4965,
--4978,-4985,-4986,-4981,-4972,-4962,-4953,-4949,-4948,-4952,-4958,-4964,-4969,-4972,-4972,-4971,-4968,-4964,-4960,-4955,-4951,
--4946,-4941,-4934,-4927,-4919,-4910,-4902,-4894,-4888,-4883,-4879,-4876,-4873,-4870,-4867,-4862,-4856,-4850,-4843,-4836,-4828,
--4819,-4809,-4798,-4785,-4772,-4758,-4743,-4729,-4714,-4700,-4687,-4675,-4664,-4655,-4647,-4639,-4631,-4621,-4610,-4598,-4585,
--4572,-4560,-4550,-4542,-4535,-4527,-4518,-4508,-4495,-4482,-4470,-4458,-4448,-4440,-4432,-4424,-4414,-4403,-4390,-4376,-4363,
--4351,-4341,-4333,-4327,-4322,-4318,-4313,-4307,-4301,-4292,-4282,-4271,-4260,-4250,-4242,-4236,-4232,-4227,-4221,-4213,-4201,
--4186,-4170,-4153,-4138,-4126,-4117,-4110,-4104,-4098,-4091,-4083,-4075,-4066,-4058,-4051,-4045,-4038,-4032,-4025,-4018,-4011,
--4004,-3997,-3990,-3981,-3971,-3960,-3949,-3938,-3929,-3923,-3918,-3915,-3912,-3908,-3903,-3898,-3892,-3887,-3882,-3878,-3874,
--3869,-3864,-3857,-3849,-3841,-3835,-3829,-3825,-3822,-3819,-3815,-3809,-3803,-3795,-3788,-3779,-3772,-3765,-3758,-3752,-3746,
--3741,-3737,-3734,-3730,-3727,-3723,-3719,-3714,-3709,-3705,-3702,-3699,-3696,-3693,-3689,-3683,-3676,-3668,-3661,-3653,-3647,
--3640,-3635,-3629,-3623,-3617,-3611,-3606,-3601,-3596,-3591,-3584,-3576,-3564,-3551,-3538,-3524,-3513,-3503,-3496,-3489,-3483,
--3476,-3467,-3457,-3446,-3436,-3425,-3416,-3408,-3400,-3391,-3382,-3370,-3358,-3345,-3332,-3320,-3309,-3300,-3291,-3283,-3275,
--3266,-3256,-3246,-3234,-3222,-3209,-3196,-3183,-3170,-3159,-3148,-3136,-3125,-3112,-3097,-3080,-3062,-3042,-3022,-3003,-2987,
--2974,-2965,-2959,-2955,-2953,-2950,-2947,-2941,-2933,-2921,-2908,-2893,-2876,-2859,-2843,-2827,-2812,-2799,-2786,-2775,-2764,
--2754,-2745,-2736,-2728,-2720,-2713,-2706,-2699,-2692,-2685,-2677,-2669,-2662,-2653,-2645,-2635,-2625,-2615,-2605,-2595,-2586,
--2579,-2572,-2566,-2559,-2551,-2542,-2532,-2521,-2511,-2502,-2493,-2484,-2475,-2465,-2452,-2438,-2422,-2406,-2390,-2376,-2364,
--2353,-2342,-2331,-2320,-2308,-2296,-2284,-2272,-2261,-2252,-2242,-2233,-2223,-2212,-2200,-2187,-2174,-2162,-2149,-2137,-2125,
--2113,-2101,-2088,-2073,-2057,-2039,-2020,-2001,-1980,-1961,-1943,-1927,-1911,-1896,-1880,-1862,-1841,-1819,-1796,-1773,-1752,
--1734,-1720,-1707,-1696,-1685,-1671,-1654,-1635,-1614,-1592,-1572,-1553,-1537,-1522,-1507,-1491,-1474,-1453,-1429,-1403,-1376,
--1350,-1326,-1305,-1287,-1271,-1256,-1242,-1227,-1213,-1199,-1186,-1175,-1164,-1154,-1144,-1132,-1118,-1101,-1083,-1063,-1043,
--1023,-1003,-984,-963,-941,-916,-887,-856,-823,-790,-756,-724,-694,-665,-638,-611,-583,-556,-529,-502,-476,
--451,-428,-404,-379,-353,-323,-289,-251,-210,-168,-125,-83,-42,-3,34,71,107,141,173,203,231,
-257,282,308,334,362,391,420,447,472,496,518,542,568,598,633,670,709,746,781,813,844,
-874,906,941,979,1019,1061,1103,1144,1184,1223,1262,1302,1341,1377,1407,1430,1442,1443,1434,1417,1396,
-1375,1360,1353,1358,1379,1415,1466,1530,1605,1685,1766,1843,1912,1972,2020,2057,2086,2108,2126,2141,2155,
-2170,2186,2203,2224,2247,2273,2300,2328,2354,2376,2393,2403,2406,2402,2392,2376,2354,2327,2293,2255,2214,
-2172,2134,2102,2078,2062,2054,2051,2050,2047,2040,2030,2017,2003,1990,1979,1971,1965,1960,1956,1951,1947,
-1943,1941,1939,1938,1936,1932,1928,1923,1920,1920,1923,1929,1937,1943,1945,1943,1935,1925,1914,1907,1904,
-1904,1904,1903,1896,1882,1863,1842,1823,1810,1806,1810,1822,1838,1853,1864,1870,1870,1865,1855,1841,1825,
-1807,1789,1771,1756,1744,1737,1735,1737,1743,1751,1759,1768,1775,1781,1785,1787,1786,1782,1776,1770,1763,
-1759,1757,1757,1758,1758,1757,1753,1748,1742,1738,1735,1736,1738,1740,1740,1736,1728,1717,1702,1687,1672,
-1657,1644,1631,1619,1606,1593,1580,1567,1555,1542,1529,1515,1501,1487,1474,1463,1456,1450,1446,1441,1434,
-1425,1413,1401,1390,1381,1375,1374,1374,1373,1371,1364,1352,1333,1310,1284,1256,1229,1206,1189,1177,1171,
-1171,1174,1178,1180,1179,1173,1165,1156,1149,1145,1147,1153,1161,1170,1175,1174,1167,1153,1136,1118,1103,
-1094,1093,1099,1111,1126,1143,1157,1168,1175,1178,1178,1178,1177,1177,1178,1178,1179,1179,1178,1178,1178,
-1180,1183,1186,1189,1191,1191,1189,1187,1185,1186,1189,1195,1203,1212,1220,1227,1234,1241,1251,1263,1278,
-1294,1312,1328,1342,1354,1350,1360,1371,1381,1394,1407,1420,1433,1446,1458,1471,1486,1503,1525,1549,1574,
-1600,1623,1645,1664,1682,1698,1713,1728,1742,1753,1764,1773,1782,1793,1806,1822,1842,1863,1884,1905,1925,
-1943,1960,1977,1994,2011,2028,2045,2062,2078,2094,2110,2125,2138,2151,2161,2169,2175,2180,2186,2192,2199,
-2206,2213,2217,2219,2219,2218,2218,2219,2223,2229,2235,2240,2242,2241,2235,2226,2215,2204,2194,2186,2180,
-2179,2181,2187,2195,2206,2217,2228,2236,2241,2243,2243,2243,2243,2244,2248,2252,2255,2257,2256,2254,2252,
-2252,2254,2261,2271,2284,2297,2309,2319,2327,2334,2339,2345,2352,2360,2370,2380,2392,2403,2414,2426,2437,
-2447,2456,2461,2464,2462,2458,2453,2448,2446,2450,2460,2476,2498,2524,2551,2578,2603,2626,2647,2667,2685,
-2704,2723,2743,2762,2780,2798,2813,2827,2839,2851,2864,2878,2893,2910,2927,2945,2962,2977,2991,3004,3015,
-3025,3035,3044,3053,3060,3066,3069,3070,3069,3066,3062,3058,3053,3049,3047,3046,3047,3049,3053,3059,3065,
-3071,3076,3079,3077,3072,3062,3048,3030,3011,2991,2971,2955,2941,2931,2924,2920,2919,2919,2920,2920,2920,
-2920,2919,2917,2915,2914,2912,2910,2909,2908,2909,2913,2919,2928,2940,2953,2966,2978,2989,2998,3006,3013,
-3020,3027,3034,3040,3045,3049,3051,3050,3049,3046,3043,3038,3033,3026,3018,3008,2998,2987,2976,2966,2957,
-2950,2944,2939,2935,2929,2922,2911,2897,2880,2861,2842,2823,2807,2793,2781,2770,2758,2745,2731,2716,2701,
-2687,2675,2664,2655,2647,2637,2627,2617,2606,2595,2584,2574,2562,2550,2536,2522,2508,2495,2484,2475,2468,
-2461,2455,2447,2438,2428,2419,2411,2404,2396,2387,2375,2359,2340,2318,2296,2274,2253,2234,2216,2197,2175,
-2151,2124,2095,2065,2034,2003,1971,1939,1907,1876,1847,1822,1802,1789,1781,1778,1776,1773,1767,1756,1740,
-1719,1695,1666,1634,1600,1563,1524,1483,1443,1404,1367,1332,1301,1271,1243,1214,1183,1150,1113,1074,1033,
-990,947,904,864,827,792,759,727,697,666,635,603,571,538,505,471,437,404,372,343,315,
-290,265,239,209,173,131,84,35,-11,-52,-84,-106,-119,-129,-140,-155,-179,-212,-251,-293,-336,
--376,-412,-446,-479,-512,-547,-583,-620,-655,-690,-722,-754,-784,-815,-845,-874,-901,-924,-945,-963,-982,
--1002,-1026,-1055,-1087,-1122,-1157,-1189,-1216,-1239,-1258,-1275,-1292,-1311,-1333,-1359,-1387,-1418,-1452,-1487,-1525,-1563,
--1604,-1647,-1692,-1738,-1785,-1830,-1874,-1916,-1953,-1988,-2019,-2048,-2076,-2103,-2131,-2158,-2185,-2210,-2234,-2255,-2273,
--2290,-2305,-2321,-2337,-2355,-2375,-2397,-2421,-2448,-2477,-2508,-2539,-2571,-2604,-2635,-2667,-2697,-2726,-2756,-2784,-2812,
--2840,-2868,-2895,-2922,-2949,-2977,-3006,-3035,-3065,-3095,-3123,-3149,-3170,-3187,-3201,-3212,-3223,-3234,-3247,-3261,-3278,
--3294,-3310,-3324,-3336,-3346,-3356,-3368,-3382,-3399,-3419,-3441,-3465,-3489,-3512,-3536,-3560,-3585,-3611,-3639,-3668,-3697,
--3725,-3750,-3773,-3792,-3808,-3822,-3834,-3845,-3857,-3870,-3886,-3904,-3926,-3949,-3973,-3996,-4013,-4025,-4030,-4029,-4025,
--4019,-4016,-4017,-4024,-4034,-4048,-4062,-4076,-4087,-4096,-4103,-4107,-4110,-4111,-4110,-4108,-4105,-4102,-4099,-4097,-4097,
--4096,-4095,-4093,-4087,-4077,-4064,-4049,-4034,-4021,-4010,-4002,-3996,-3991,-3986,-3981,-3974,-3965,-3957,-3950,-3945,-3942,
--3942,-3943,-3945,-3946,-3946,-3943,-3938,-3932,-3925,-3918,-3913,-3908,-3905,-3902,-3898,-3894,-3889,-3884,-3878,-3873,-3868,
--3864,-3861,-3856,-3849,-3839,-3825,-3806,-3785,-3763,-3743,-3727,-3719,-3720,-3730,-3745,-3764,-3782,-3795,-3801,-3798,-3788,
--3774,-3759,-3747,-3740,-3741,-3748,-3761,-3777,-3793,-3808,-3822,-3835,-3847,-3860,-3874,-3890,-3907,-3925,-3943,-3962,-3980,
--3998,-4016,-4034,-4051,-4069,-4086,-4102,-4119,-4135,-4152,-4170,-4188,-4207,-4226,-4244,-4260,-4274,-4285,-4294,-4301,-4308,
--4315,-4325,-4336,-4350,-4366,-4383,-4400,-4416,-4430,-4442,-4452,-4462,-4472,-4483,-4497,-4514,-4535,-4561,-4592,-4630,-4672,
--4717,-4762,-4803,-4837,-4863,-4878,-4886,-4890,-4892,-4898,-4910,-4928,-4950,-4973,-4995,-5010,-5018,-5019,-5013,-5003,-4993,
--4985,-4980,-4978,-4979,-4982,-4985,-4987,-4988,-4987,-4985,-4982,-4978,-4974,-4969,-4963,-4957,-4949,-4941,-4932,-4923,-4914,
--4907,-4901,-4897,-4893,-4890,-4887,-4884,-4880,-4875,-4870,-4865,-4860,-4854,-4848,-4840,-4831,-4821,-4810,-4797,-4782,-4767,
--4752,-4737,-4722,-4710,-4699,-4689,-4682,-4674,-4667,-4658,-4648,-4636,-4624,-4612,-4602,-4593,-4585,-4578,-4570,-4561,-4549,
--4536,-4522,-4509,-4497,-4486,-4478,-4470,-4463,-4455,-4446,-4436,-4425,-4414,-4404,-4394,-4387,-4381,-4377,-4373,-4370,-4365,
--4359,-4352,-4342,-4332,-4321,-4311,-4304,-4298,-4295,-4291,-4287,-4280,-4270,-4257,-4242,-4226,-4212,-4199,-4190,-4182,-4175,
--4169,-4161,-4152,-4143,-4134,-4124,-4116,-4107,-4099,-4092,-4085,-4079,-4074,-4069,-4065,-4059,-4052,-4043,-4031,-4018,-4005,
--3994,-3985,-3980,-3978,-3977,-3976,-3975,-3972,-3968,-3963,-3958,-3953,-3948,-3942,-3936,-3929,-3922,-3914,-3906,-3898,-3892,
--3885,-3879,-3873,-3865,-3856,-3847,-3837,-3827,-3818,-3809,-3802,-3797,-3792,-3789,-3786,-3783,-3780,-3776,-3772,-3768,-3764,
--3760,-3758,-3757,-3756,-3756,-3754,-3751,-3747,-3741,-3734,-3726,-3719,-3711,-3703,-3695,-3687,-3678,-3669,-3662,-3657,-3653,
--3650,-3647,-3642,-3636,-3626,-3613,-3600,-3587,-3575,-3565,-3557,-3550,-3543,-3534,-3523,-3511,-3498,-3487,-3477,-3470,-3465,
--3459,-3452,-3443,-3430,-3415,-3399,-3383,-3368,-3356,-3345,-3336,-3328,-3319,-3309,-3298,-3286,-3274,-3261,-3249,-3236,-3224,
--3212,-3199,-3186,-3173,-3159,-3145,-3131,-3116,-3100,-3083,-3065,-3047,-3029,-3013,-2999,-2989,-2981,-2976,-2973,-2971,-2968,
--2963,-2956,-2946,-2934,-2920,-2905,-2890,-2874,-2859,-2846,-2833,-2821,-2810,-2800,-2790,-2782,-2774,-2767,-2760,-2753,-2745,
--2737,-2729,-2720,-2711,-2701,-2691,-2680,-2668,-2656,-2643,-2631,-2621,-2612,-2605,-2599,-2593,-2587,-2579,-2570,-2560,-2549,
--2539,-2529,-2519,-2509,-2498,-2485,-2471,-2454,-2438,-2422,-2407,-2395,-2384,-2374,-2364,-2353,-2341,-2328,-2316,-2304,-2293,
--2284,-2276,-2267,-2258,-2247,-2234,-2220,-2206,-2192,-2180,-2169,-2159,-2149,-2139,-2127,-2113,-2097,-2078,-2059,-2038,-2017,
--1998,-1980,-1964,-1950,-1936,-1923,-1907,-1889,-1869,-1847,-1824,-1801,-1781,-1764,-1749,-1736,-1723,-1708,-1691,-1669,-1646,
--1621,-1597,-1576,-1559,-1545,-1533,-1521,-1507,-1490,-1468,-1442,-1414,-1385,-1359,-1336,-1317,-1301,-1288,-1276,-1263,-1250,
--1235,-1220,-1205,-1191,-1178,-1166,-1155,-1144,-1131,-1116,-1099,-1081,-1063,-1044,-1024,-1004,-981,-956,-928,-898,-864,
--830,-797,-765,-735,-708,-682,-658,-634,-608,-582,-555,-527,-501,-474,-448,-422,-395,-365,-332,-297,-258,
--219,-179,-140,-101,-63,-26,11,49,87,123,158,189,216,241,264,287,311,337,365,394,422,
-450,476,502,528,557,588,622,658,694,729,762,792,822,851,883,916,953,991,1031,1070,1109,
-1148,1187,1227,1266,1305,1342,1375,1403,1426,1444,1457,1468,1477,1487,1497,1510,1525,1546,1572,1606,1649,
-1700,1759,1820,1881,1937,1985,2023,2051,2074,2093,2113,2136,2163,2193,2225,2256,2285,2309,2330,2348,2363,
-2375,2386,2393,2395,2391,2381,2364,2342,2315,2286,2258,2231,2208,2188,2171,2156,2141,2124,2106,2085,2063,
-2040,2019,2000,1984,1972,1963,1954,1945,1934,1922,1909,1897,1888,1882,1880,1881,1883,1883,1881,1876,1870,
-1864,1862,1863,1867,1873,1877,1876,1870,1859,1845,1832,1823,1821,1824,1830,1837,1840,1836,1826,1811,1796,
-1785,1781,1786,1798,1814,1829,1841,1845,1841,1829,1811,1792,1772,1754,1740,1731,1725,1723,1724,1727,1730,
-1733,1734,1734,1732,1728,1722,1714,1705,1696,1689,1683,1680,1680,1682,1686,1688,1689,1687,1683,1677,1671,
-1667,1666,1667,1670,1673,1672,1668,1659,1647,1633,1620,1609,1600,1593,1585,1576,1565,1550,1535,1518,1503,
-1489,1476,1465,1453,1441,1429,1418,1407,1398,1391,1385,1378,1370,1360,1348,1335,1322,1312,1304,1300,1299,
-1299,1298,1294,1286,1273,1256,1236,1214,1194,1177,1164,1157,1154,1155,1158,1160,1160,1155,1147,1136,1124,
-1112,1103,1097,1096,1098,1102,1106,1107,1106,1100,1092,1082,1072,1064,1060,1061,1067,1078,1092,1107,1121,
-1134,1144,1151,1156,1159,1161,1162,1162,1161,1159,1157,1155,1154,1154,1154,1156,1158,1159,1160,1160,1160,
-1162,1165,1171,1178,1187,1196,1204,1212,1220,1228,1239,1253,1270,1288,1306,1323,1338,1350,1340,1349,1358,
-1368,1380,1393,1409,1425,1442,1459,1477,1496,1518,1541,1566,1591,1615,1638,1658,1677,1694,1709,1725,1739,
-1751,1761,1769,1775,1780,1786,1794,1806,1820,1837,1856,1874,1892,1908,1924,1938,1953,1969,1986,2004,2023,
-2041,2059,2076,2090,2102,2111,2118,2124,2130,2136,2144,2153,2163,2173,2180,2185,2187,2187,2187,2187,2189,
-2192,2196,2198,2199,2195,2187,2177,2164,2152,2143,2136,2132,2131,2132,2136,2141,2148,2156,2165,2174,2182,
-2188,2192,2196,2198,2201,2205,2210,2215,2218,2220,2220,2219,2218,2218,2222,2228,2238,2249,2260,2270,2277,
-2283,2288,2294,2300,2309,2319,2330,2341,2352,2362,2372,2382,2392,2402,2411,2417,2420,2419,2415,2411,2407,
-2407,2411,2421,2437,2457,2481,2506,2531,2555,2579,2602,2625,2646,2667,2686,2705,2723,2740,2756,2772,2786,
-2800,2813,2826,2838,2850,2863,2878,2894,2911,2930,2948,2965,2981,2994,3005,3014,3021,3025,3028,3029,3029,
-3027,3024,3019,3015,3011,3007,3004,3003,3003,3005,3010,3017,3026,3036,3045,3051,3052,3046,3033,3015,2991,
-2966,2942,2921,2904,2891,2883,2878,2875,2873,2872,2871,2871,2871,2872,2874,2875,2877,2877,2878,2879,2880,
-2883,2889,2896,2905,2915,2924,2934,2942,2949,2956,2962,2969,2977,2985,2993,3001,3008,3014,3019,3022,3024,
-3025,3024,3021,3017,3010,3000,2989,2976,2963,2950,2938,2928,2920,2914,2911,2908,2905,2901,2893,2880,2863,
-2843,2821,2800,2782,2767,2757,2749,2742,2734,2724,2713,2700,2687,2675,2665,2657,2650,2643,2635,2624,2612,
-2600,2587,2575,2564,2553,2541,2527,2512,2497,2481,2466,2453,2442,2431,2420,2409,2397,2385,2374,2365,2358,
-2352,2347,2340,2329,2316,2298,2279,2258,2238,2219,2201,2182,2162,2139,2114,2086,2057,2026,1994,1962,1927,
-1892,1855,1820,1786,1756,1733,1716,1706,1701,1698,1696,1690,1679,1662,1638,1609,1573,1534,1493,1450,1408,
-1369,1332,1300,1272,1248,1226,1206,1184,1161,1133,1102,1067,1029,989,948,907,868,830,794,759,725,
-693,661,631,601,573,544,516,487,457,427,398,370,345,321,298,273,245,211,170,124,76,
-29,-12,-45,-69,-85,-97,-109,-124,-145,-173,-206,-242,-278,-313,-347,-379,-412,-445,-479,-514,-549,
--584,-618,-652,-688,-725,-763,-802,-839,-874,-903,-927,-949,-969,-992,-1019,-1052,-1090,-1130,-1169,-1204,-1232,
--1254,-1269,-1281,-1292,-1306,-1324,-1348,-1378,-1413,-1452,-1496,-1542,-1591,-1642,-1694,-1746,-1797,-1846,-1891,-1932,-1968,
--1999,-2027,-2052,-2075,-2099,-2123,-2147,-2171,-2195,-2217,-2237,-2253,-2267,-2279,-2290,-2302,-2314,-2328,-2345,-2365,-2388,
--2414,-2442,-2472,-2504,-2538,-2573,-2609,-2645,-2680,-2716,-2751,-2785,-2817,-2849,-2880,-2909,-2938,-2966,-2994,-3023,-3051,
--3080,-3108,-3135,-3159,-3180,-3198,-3213,-3226,-3238,-3250,-3264,-3279,-3295,-3312,-3328,-3343,-3356,-3369,-3382,-3396,-3412,
--3431,-3452,-3475,-3500,-3525,-3551,-3577,-3605,-3634,-3665,-3698,-3730,-3762,-3791,-3817,-3838,-3856,-3871,-3884,-3897,-3909,
--3922,-3936,-3950,-3965,-3980,-3995,-4008,-4019,-4027,-4032,-4035,-4035,-4035,-4036,-4038,-4042,-4048,-4055,-4061,-4067,-4071,
--4073,-4075,-4077,-4079,-4082,-4084,-4087,-4089,-4091,-4094,-4098,-4104,-4111,-4120,-4127,-4132,-4133,-4128,-4120,-4108,-4097,
--4087,-4082,-4080,-4080,-4082,-4081,-4077,-4068,-4054,-4039,-4024,-4011,-4003,-4000,-4000,-4003,-4007,-4009,-4010,-4008,-4003,
--3998,-3993,-3988,-3985,-3981,-3978,-3974,-3969,-3962,-3955,-3948,-3941,-3937,-3934,-3932,-3931,-3928,-3921,-3910,-3894,-3874,
--3851,-3828,-3809,-3796,-3790,-3794,-3805,-3821,-3840,-3857,-3870,-3877,-3876,-3869,-3859,-3847,-3836,-3830,-3829,-3833,-3842,
--3854,-3868,-3883,-3897,-3912,-3926,-3939,-3953,-3967,-3982,-3998,-4014,-4032,-4051,-4070,-4090,-4111,-4131,-4151,-4170,-4188,
--4203,-4217,-4231,-4244,-4259,-4275,-4292,-4311,-4330,-4347,-4362,-4374,-4383,-4390,-4397,-4405,-4415,-4427,-4442,-4456,-4470,
--4481,-4490,-4497,-4503,-4509,-4516,-4525,-4536,-4550,-4567,-4587,-4611,-4640,-4674,-4711,-4749,-4786,-4817,-4841,-4857,-4866,
--4871,-4876,-4885,-4899,-4920,-4945,-4973,-4999,-5020,-5034,-5041,-5041,-5035,-5028,-5020,-5014,-5009,-5007,-5006,-5005,-5005,
--5005,-5004,-5003,-5001,-4998,-4995,-4990,-4984,-4976,-4968,-4960,-4951,-4944,-4937,-4930,-4925,-4920,-4915,-4910,-4905,-4901,
--4896,-4892,-4887,-4883,-4878,-4873,-4867,-4860,-4852,-4842,-4832,-4820,-4806,-4792,-4778,-4764,-4750,-4739,-4729,-4721,-4714,
--4707,-4699,-4690,-4680,-4669,-4659,-4649,-4640,-4632,-4624,-4616,-4607,-4597,-4585,-4573,-4561,-4550,-4540,-4531,-4524,-4517,
--4510,-4503,-4496,-4489,-4482,-4474,-4467,-4460,-4453,-4446,-4440,-4434,-4429,-4424,-4418,-4411,-4403,-4394,-4385,-4377,-4369,
--4363,-4357,-4352,-4346,-4338,-4329,-4318,-4307,-4296,-4285,-4275,-4265,-4255,-4245,-4234,-4223,-4213,-4203,-4194,-4186,-4177,
--4168,-4159,-4150,-4143,-4137,-4133,-4131,-4128,-4125,-4120,-4111,-4100,-4088,-4076,-4065,-4057,-4052,-4049,-4047,-4045,-4042,
--4039,-4034,-4029,-4025,-4020,-4016,-4011,-4006,-3999,-3991,-3983,-3974,-3964,-3955,-3946,-3936,-3926,-3915,-3904,-3893,-3881,
--3871,-3862,-3855,-3849,-3845,-3841,-3838,-3835,-3831,-3826,-3820,-3814,-3810,-3806,-3805,-3805,-3807,-3809,-3810,-3809,-3808,
--3804,-3799,-3794,-3787,-3780,-3772,-3762,-3752,-3740,-3729,-3719,-3711,-3706,-3702,-3699,-3695,-3689,-3681,-3671,-3659,-3648,
--3638,-3630,-3622,-3615,-3606,-3595,-3582,-3566,-3551,-3536,-3524,-3515,-3508,-3502,-3495,-3486,-3474,-3461,-3446,-3431,-3417,
--3405,-3393,-3382,-3371,-3358,-3345,-3331,-3318,-3306,-3295,-3286,-3277,-3267,-3256,-3242,-3227,-3211,-3194,-3177,-3162,-3147,
--3133,-3119,-3105,-3090,-3075,-3060,-3046,-3034,-3023,-3015,-3008,-3001,-2995,-2988,-2980,-2971,-2961,-2950,-2939,-2928,-2917,
--2906,-2895,-2884,-2873,-2862,-2851,-2841,-2831,-2822,-2814,-2805,-2797,-2788,-2779,-2770,-2760,-2750,-2740,-2729,-2717,-2704,
--2690,-2676,-2663,-2652,-2643,-2635,-2629,-2622,-2615,-2607,-2598,-2587,-2576,-2564,-2554,-2543,-2532,-2520,-2506,-2491,-2476,
--2461,-2446,-2433,-2422,-2411,-2401,-2389,-2377,-2363,-2350,-2337,-2325,-2315,-2307,-2298,-2288,-2277,-2265,-2251,-2237,-2223,
--2212,-2202,-2193,-2185,-2175,-2162,-2147,-2130,-2111,-2091,-2071,-2053,-2036,-2020,-2006,-1993,-1979,-1965,-1949,-1931,-1912,
--1890,-1868,-1847,-1827,-1809,-1792,-1778,-1763,-1746,-1726,-1703,-1676,-1648,-1621,-1597,-1578,-1563,-1552,-1544,-1534,-1522,
--1505,-1483,-1456,-1428,-1400,-1374,-1352,-1335,-1321,-1309,-1297,-1285,-1272,-1257,-1241,-1224,-1208,-1193,-1179,-1166,-1154,
--1140,-1126,-1112,-1095,-1078,-1060,-1040,-1018,-994,-968,-939,-909,-877,-845,-813,-783,-755,-729,-704,-680,-656,
--631,-606,-580,-553,-526,-499,-470,-440,-407,-372,-334,-294,-253,-212,-173,-137,-102,-69,-36,-2,32,
-68,104,139,171,201,227,251,274,297,321,347,375,404,434,463,493,522,552,582,613,645,
-678,710,742,775,808,842,877,912,947,981,1014,1046,1078,1112,1147,1186,1228,1271,1316,1361,1404,
-1445,1484,1523,1560,1596,1629,1658,1680,1696,1706,1714,1722,1736,1759,1791,1832,1880,1929,1975,2015,2050,
-2078,2104,2131,2159,2191,2225,2258,2288,2312,2329,2340,2346,2350,2353,2357,2360,2361,2358,2347,2328,2301,
-2270,2239,2211,2190,2177,2172,2170,2167,2159,2141,2113,2076,2034,1992,1954,1926,1908,1900,1898,1899,1898,
-1892,1880,1866,1850,1836,1828,1825,1827,1831,1834,1834,1828,1820,1810,1802,1797,1797,1801,1806,1809,1807,
-1802,1792,1782,1773,1769,1771,1776,1783,1789,1790,1786,1778,1767,1757,1753,1754,1760,1771,1782,1789,1791,
-1785,1771,1753,1733,1714,1699,1689,1684,1682,1683,1684,1684,1683,1679,1673,1666,1658,1650,1642,1635,1628,
-1622,1618,1616,1616,1617,1620,1622,1622,1619,1614,1607,1600,1594,1591,1590,1591,1591,1589,1583,1572,1558,
-1542,1526,1514,1506,1501,1499,1497,1492,1485,1475,1463,1452,1442,1434,1428,1423,1416,1406,1393,1377,1360,
-1343,1329,1317,1309,1303,1298,1294,1288,1281,1273,1264,1254,1245,1236,1227,1219,1210,1200,1189,1177,1165,
-1153,1143,1135,1130,1127,1126,1126,1125,1124,1120,1114,1107,1098,1088,1080,1073,1068,1066,1065,1066,1067,
-1067,1066,1063,1057,1049,1041,1033,1028,1027,1031,1039,1052,1067,1082,1096,1108,1117,1125,1130,1134,1138,
-1140,1141,1141,1140,1139,1138,1137,1136,1135,1135,1134,1134,1135,1138,1142,1149,1158,1169,1179,1190,1199,
-1209,1219,1232,1246,1263,1281,1299,1315,1329,1340,1333,1341,1351,1362,1376,1394,1416,1440,1465,1491,1515,
-1539,1562,1584,1605,1626,1645,1663,1679,1695,1711,1726,1740,1754,1766,1776,1784,1789,1793,1797,1802,1809,
-1818,1830,1843,1856,1870,1882,1895,1906,1918,1932,1946,1962,1978,1995,2011,2026,2039,2049,2058,2065,2073,
-2082,2092,2103,2115,2126,2135,2142,2146,2148,2149,2151,2154,2158,2162,2165,2164,2159,2150,2137,2122,2108,
-2096,2089,2085,2084,2085,2087,2090,2093,2098,2105,2114,2123,2134,2143,2150,2155,2159,2163,2166,2170,2175,
-2179,2182,2184,2185,2186,2188,2193,2200,2208,2218,2227,2234,2240,2244,2249,2254,2261,2270,2281,2293,2305,
-2316,2326,2336,2345,2354,2363,2370,2374,2375,2373,2369,2364,2361,2362,2367,2379,2395,2415,2438,2463,2489,
-2515,2542,2568,2593,2617,2638,2656,2671,2685,2698,2712,2728,2744,2762,2779,2795,2809,2821,2833,2844,2857,
-2872,2889,2907,2926,2944,2959,2972,2981,2987,2991,2992,2991,2988,2984,2979,2975,2971,2968,2965,2963,2962,
-2963,2964,2968,2974,2983,2993,3003,3011,3014,3009,2997,2979,2955,2930,2906,2887,2872,2861,2855,2850,2846,
-2841,2837,2834,2832,2833,2836,2841,2846,2851,2856,2859,2862,2865,2871,2878,2887,2897,2906,2914,2919,2922,
-2925,2928,2933,2940,2949,2959,2969,2979,2987,2993,2997,2999,3001,3002,3001,2998,2992,2984,2972,2958,2943,
-2927,2913,2900,2890,2883,2879,2877,2876,2873,2869,2860,2846,2829,2808,2787,2767,2750,2738,2729,2723,2718,
-2711,2703,2693,2682,2672,2665,2659,2656,2652,2647,2639,2628,2614,2599,2584,2570,2558,2547,2535,2522,2506,
-2488,2468,2448,2428,2410,2394,2378,2363,2349,2335,2324,2314,2308,2304,2300,2296,2289,2279,2264,2247,2228,
-2209,2190,2172,2153,2134,2112,2088,2061,2033,2004,1975,1945,1914,1880,1845,1807,1769,1732,1699,1671,1650,
-1635,1625,1617,1609,1598,1583,1561,1534,1502,1466,1428,1390,1353,1318,1286,1257,1232,1209,1188,1167,1147,
-1125,1100,1074,1045,1013,980,945,908,871,833,795,757,719,682,648,616,587,560,535,509,484,
-457,430,403,377,354,333,313,294,272,246,214,176,134,91,49,11,-21,-48,-70,-90,-108,
--127,-148,-169,-191,-214,-239,-265,-293,-325,-359,-395,-433,-471,-511,-553,-597,-644,-694,-744,-793,-837,
--874,-902,-923,-940,-957,-977,-1004,-1038,-1078,-1120,-1160,-1195,-1223,-1243,-1257,-1268,-1280,-1296,-1318,-1346,-1381,
--1421,-1467,-1517,-1570,-1627,-1685,-1743,-1800,-1853,-1900,-1941,-1976,-2004,-2027,-2048,-2067,-2088,-2109,-2133,-2157,-2181,
--2204,-2224,-2240,-2252,-2261,-2268,-2273,-2279,-2287,-2298,-2312,-2330,-2352,-2378,-2408,-2441,-2477,-2516,-2556,-2597,-2639,
--2679,-2719,-2756,-2792,-2828,-2862,-2895,-2929,-2962,-2995,-3027,-3057,-3086,-3113,-3139,-3162,-3184,-3204,-3223,-3240,-3257,
--3274,-3291,-3308,-3326,-3343,-3360,-3376,-3391,-3406,-3421,-3436,-3454,-3473,-3495,-3518,-3542,-3567,-3591,-3617,-3643,-3670,
--3700,-3732,-3766,-3799,-3831,-3859,-3883,-3902,-3916,-3928,-3939,-3950,-3963,-3976,-3991,-4005,-4018,-4028,-4036,-4040,-4041,
--4041,-4039,-4037,-4036,-4037,-4039,-4042,-4046,-4049,-4051,-4051,-4049,-4045,-4041,-4037,-4036,-4037,-4041,-4047,-4055,-4063,
--4072,-4081,-4090,-4100,-4111,-4123,-4134,-4143,-4150,-4154,-4156,-4156,-4157,-4159,-4165,-4173,-4181,-4188,-4191,-4187,-4177,
--4161,-4141,-4119,-4100,-4085,-4075,-4071,-4072,-4075,-4078,-4079,-4079,-4077,-4073,-4068,-4064,-4060,-4057,-4053,-4050,-4045,
--4039,-4032,-4025,-4018,-4013,-4009,-4006,-4004,-4000,-3993,-3983,-3969,-3950,-3929,-3908,-3888,-3873,-3865,-3864,-3871,-3884,
--3901,-3919,-3937,-3950,-3958,-3959,-3955,-3947,-3936,-3926,-3918,-3914,-3916,-3922,-3933,-3946,-3961,-3977,-3992,-4007,-4021,
--4035,-4049,-4064,-4079,-4095,-4111,-4129,-4148,-4167,-4188,-4209,-4230,-4250,-4267,-4281,-4293,-4303,-4313,-4326,-4341,-4361,
--4383,-4406,-4429,-4448,-4463,-4474,-4482,-4489,-4496,-4505,-4515,-4526,-4537,-4545,-4552,-4557,-4562,-4567,-4575,-4584,-4594,
--4605,-4617,-4628,-4640,-4655,-4674,-4698,-4726,-4757,-4789,-4817,-4840,-4856,-4867,-4873,-4879,-4888,-4902,-4921,-4945,-4971,
--4996,-5017,-5033,-5043,-5047,-5047,-5045,-5041,-5036,-5032,-5029,-5027,-5025,-5025,-5024,-5025,-5025,-5024,-5021,-5017,-5011,
--5004,-4996,-4989,-4981,-4975,-4969,-4963,-4957,-4950,-4943,-4936,-4930,-4924,-4918,-4914,-4910,-4906,-4902,-4898,-4893,-4887,
--4881,-4874,-4867,-4858,-4848,-4836,-4824,-4811,-4798,-4787,-4777,-4769,-4761,-4755,-4747,-4739,-4730,-4720,-4709,-4699,-4689,
--4680,-4672,-4665,-4657,-4650,-4642,-4635,-4627,-4619,-4611,-4603,-4595,-4588,-4580,-4574,-4568,-4563,-4559,-4555,-4550,-4544,
--4536,-4527,-4517,-4509,-4501,-4494,-4489,-4483,-4477,-4470,-4461,-4450,-4440,-4429,-4420,-4412,-4406,-4400,-4395,-4390,-4385,
--4379,-4371,-4362,-4351,-4339,-4327,-4315,-4303,-4293,-4284,-4276,-4268,-4260,-4250,-4239,-4228,-4217,-4207,-4200,-4196,-4194,
--4193,-4192,-4189,-4183,-4175,-4165,-4154,-4144,-4136,-4128,-4122,-4117,-4112,-4106,-4101,-4097,-4093,-4089,-4086,-4083,-4079,
--4073,-4066,-4058,-4048,-4037,-4026,-4014,-4002,-3990,-3978,-3966,-3954,-3943,-3932,-3923,-3916,-3911,-3908,-3905,-3902,-3899,
--3894,-3888,-3880,-3872,-3865,-3859,-3855,-3853,-3852,-3853,-3854,-3854,-3853,-3851,-3849,-3847,-3844,-3840,-3835,-3829,-3820,
--3809,-3797,-3786,-3775,-3766,-3758,-3751,-3745,-3737,-3729,-3720,-3711,-3702,-3695,-3689,-3683,-3676,-3668,-3656,-3641,-3624,
--3606,-3589,-3573,-3560,-3549,-3539,-3529,-3519,-3508,-3496,-3483,-3471,-3459,-3448,-3436,-3423,-3408,-3393,-3377,-3362,-3348,
--3336,-3328,-3320,-3313,-3304,-3294,-3280,-3264,-3247,-3228,-3211,-3194,-3180,-3166,-3153,-3141,-3128,-3116,-3104,-3092,-3081,
--3071,-3061,-3051,-3041,-3030,-3018,-3007,-2995,-2985,-2976,-2968,-2960,-2953,-2945,-2937,-2927,-2917,-2907,-2896,-2886,-2876,
--2866,-2856,-2846,-2836,-2826,-2816,-2806,-2796,-2786,-2776,-2765,-2753,-2740,-2726,-2712,-2699,-2687,-2677,-2668,-2659,-2651,
--2642,-2632,-2621,-2610,-2598,-2586,-2575,-2564,-2553,-2541,-2528,-2515,-2502,-2488,-2476,-2464,-2452,-2441,-2428,-2415,-2402,
--2388,-2375,-2363,-2353,-2343,-2333,-2322,-2309,-2295,-2280,-2265,-2253,-2243,-2235,-2229,-2223,-2215,-2204,-2189,-2171,-2151,
--2130,-2110,-2092,-2077,-2064,-2052,-2040,-2027,-2012,-1995,-1977,-1957,-1937,-1916,-1895,-1876,-1857,-1840,-1823,-1806,-1787,
--1766,-1742,-1715,-1686,-1658,-1632,-1610,-1592,-1580,-1570,-1561,-1550,-1536,-1517,-1493,-1467,-1440,-1414,-1390,-1370,-1354,
--1340,-1327,-1314,-1301,-1286,-1270,-1254,-1237,-1220,-1205,-1190,-1175,-1161,-1148,-1134,-1120,-1105,-1089,-1071,-1051,-1028,
--1004,-978,-951,-923,-894,-866,-837,-809,-780,-752,-723,-695,-668,-641,-615,-590,-565,-539,-512,-482,-449,
--413,-375,-333,-290,-248,-206,-168,-132,-99,-69,-39,-10,20,52,86,120,154,185,215,241,266,
-289,313,338,364,392,422,452,483,513,543,571,599,627,656,687,721,757,795,835,874,911,
-944,975,1002,1027,1053,1083,1118,1160,1209,1263,1321,1379,1438,1494,1549,1601,1650,1696,1736,1769,1792,
-1804,1807,1802,1796,1792,1797,1813,1841,1880,1925,1973,2019,2059,2094,2123,2149,2173,2197,2221,2243,2262,
-2276,2285,2288,2289,2289,2291,2296,2303,2310,2313,2309,2294,2269,2236,2199,2164,2135,2115,2104,2100,2097,
-2088,2069,2037,1994,1942,1889,1842,1807,1786,1780,1786,1799,1811,1819,1821,1816,1807,1799,1793,1791,1793,
-1798,1801,1801,1795,1785,1771,1757,1747,1742,1743,1748,1754,1760,1762,1760,1756,1750,1745,1743,1744,1747,
-1751,1753,1751,1746,1739,1730,1722,1716,1714,1714,1715,1715,1713,1706,1696,1683,1670,1657,1646,1639,1634,
-1631,1628,1624,1618,1609,1599,1589,1579,1572,1567,1565,1565,1567,1568,1570,1571,1573,1573,1573,1572,1569,
-1564,1558,1550,1543,1536,1530,1527,1523,1519,1513,1503,1490,1474,1456,1440,1426,1415,1407,1401,1396,1390,
-1384,1377,1371,1368,1368,1371,1375,1378,1378,1371,1358,1339,1316,1292,1271,1254,1244,1241,1242,1245,1248,
-1247,1242,1231,1216,1199,1181,1164,1150,1139,1132,1126,1121,1116,1111,1105,1098,1092,1086,1082,1078,1076,
-1074,1073,1072,1071,1069,1066,1063,1059,1054,1050,1046,1044,1043,1042,1042,1040,1036,1029,1021,1011,1002,
-996,995,998,1005,1016,1029,1041,1053,1064,1074,1083,1092,1100,1108,1114,1119,1122,1123,1123,1122,1121,
-1120,1119,1118,1117,1118,1119,1123,1130,1139,1150,1162,1175,1187,1200,1214,1228,1244,1261,1278,1295,1310,
-1322,1333,1333,1345,1359,1376,1397,1424,1454,1488,1522,1554,1583,1608,1629,1646,1660,1672,1683,1693,1702,
-1711,1721,1730,1739,1749,1758,1767,1775,1781,1787,1793,1799,1806,1813,1822,1831,1840,1849,1858,1866,1875,
-1883,1892,1902,1914,1926,1939,1952,1964,1976,1987,1997,2007,2018,2030,2042,2055,2067,2077,2085,2091,2095,
-2099,2104,2110,2117,2124,2129,2129,2124,2113,2097,2079,2061,2047,2037,2032,2032,2034,2037,2040,2042,2046,
-2050,2058,2068,2079,2091,2101,2109,2114,2117,2120,2124,2128,2134,2140,2146,2151,2154,2156,2159,2163,2168,
-2175,2183,2191,2198,2203,2207,2212,2218,2226,2236,2248,2260,2273,2284,2293,2302,2309,2316,2321,2326,2327,
-2326,2322,2317,2311,2308,2309,2314,2325,2341,2361,2385,2410,2438,2467,2497,2528,2558,2585,2608,2626,2640,
-2652,2662,2674,2688,2705,2724,2744,2764,2781,2795,2807,2817,2828,2840,2853,2869,2886,2903,2919,2933,2944,
-2951,2956,2956,2954,2950,2944,2937,2932,2928,2926,2925,2924,2924,2923,2923,2923,2927,2933,2942,2953,2963,
-2970,2971,2966,2953,2935,2915,2895,2879,2866,2858,2852,2848,2844,2839,2834,2831,2831,2835,2841,2848,2856,
-2861,2864,2864,2863,2862,2864,2868,2875,2884,2891,2898,2901,2903,2904,2905,2910,2918,2928,2940,2953,2964,
-2972,2978,2981,2983,2983,2983,2981,2977,2971,2961,2948,2933,2916,2900,2885,2873,2863,2857,2853,2850,2848,
-2844,2838,2828,2815,2798,2780,2761,2745,2731,2722,2715,2709,2704,2697,2688,2678,2668,2659,2654,2652,2651,
-2650,2647,2640,2628,2613,2596,2578,2563,2549,2536,2522,2507,2488,2467,2442,2418,2393,2371,2351,2334,2318,
-2304,2292,2281,2272,2265,2260,2256,2251,2244,2234,2222,2207,2190,2174,2157,2141,2125,2107,2086,2062,2034,
-2005,1976,1946,1917,1888,1857,1824,1789,1751,1712,1674,1639,1609,1585,1567,1552,1538,1524,1508,1488,1465,
-1439,1411,1382,1354,1326,1299,1273,1248,1223,1198,1174,1150,1126,1102,1078,1052,1026,998,969,937,904,
-868,829,790,749,709,670,634,600,571,544,519,494,470,445,419,393,368,345,325,308,293,
-278,262,242,218,190,158,123,87,51,16,-16,-44,-67,-86,-100,-111,-119,-128,-140,-157,-179,
--208,-242,-281,-324,-371,-422,-479,-541,-608,-677,-744,-805,-856,-894,-921,-937,-949,-962,-979,-1005,-1038,
--1077,-1115,-1150,-1179,-1199,-1214,-1226,-1240,-1258,-1284,-1318,-1359,-1405,-1456,-1508,-1563,-1619,-1675,-1733,-1789,-1842,
--1891,-1932,-1966,-1992,-2012,-2028,-2043,-2059,-2079,-2102,-2128,-2155,-2182,-2206,-2226,-2241,-2250,-2254,-2255,-2255,-2255,
--2259,-2266,-2279,-2297,-2321,-2350,-2385,-2424,-2467,-2512,-2559,-2606,-2652,-2696,-2737,-2776,-2812,-2848,-2883,-2919,-2956,
--2994,-3031,-3068,-3102,-3133,-3161,-3186,-3208,-3228,-3248,-3267,-3287,-3307,-3327,-3347,-3368,-3387,-3406,-3424,-3442,-3459,
--3476,-3493,-3512,-3533,-3554,-3578,-3602,-3626,-3650,-3673,-3696,-3719,-3743,-3768,-3796,-3825,-3854,-3881,-3906,-3927,-3944,
--3957,-3968,-3978,-3989,-4002,-4017,-4032,-4047,-4061,-4071,-4078,-4081,-4081,-4080,-4077,-4074,-4071,-4069,-4067,-4066,-4063,
--4060,-4056,-4050,-4044,-4037,-4031,-4026,-4024,-4025,-4029,-4036,-4046,-4057,-4069,-4082,-4094,-4106,-4118,-4131,-4144,-4157,
--4172,-4186,-4201,-4216,-4232,-4248,-4264,-4279,-4291,-4299,-4302,-4299,-4289,-4274,-4254,-4232,-4210,-4191,-4175,-4165,-4159,
--4157,-4156,-4157,-4157,-4155,-4152,-4148,-4143,-4139,-4135,-4132,-4128,-4125,-4121,-4116,-4110,-4104,-4098,-4093,-4088,-4084,
--4078,-4072,-4063,-4051,-4036,-4019,-4001,-3984,-3970,-3960,-3955,-3956,-3962,-3973,-3988,-4004,-4019,-4032,-4040,-4043,-4041,
--4035,-4025,-4015,-4008,-4003,-4003,-4008,-4017,-4029,-4042,-4056,-4070,-4085,-4100,-4115,-4131,-4147,-4162,-4176,-4189,-4203,
--4217,-4233,-4252,-4273,-4295,-4316,-4335,-4351,-4364,-4375,-4386,-4399,-4417,-4437,-4461,-4485,-4507,-4525,-4540,-4551,-4561,
--4570,-4580,-4591,-4603,-4615,-4625,-4633,-4639,-4644,-4650,-4657,-4666,-4676,-4686,-4694,-4700,-4704,-4708,-4715,-4726,-4743,
--4765,-4792,-4819,-4845,-4866,-4882,-4892,-4900,-4907,-4915,-4926,-4940,-4957,-4975,-4992,-5008,-5022,-5032,-5040,-5045,-5049,
--5050,-5049,-5048,-5047,-5045,-5045,-5045,-5045,-5046,-5045,-5043,-5040,-5034,-5028,-5021,-5014,-5008,-5003,-4998,-4993,-4986,
--4979,-4970,-4962,-4954,-4947,-4942,-4939,-4936,-4933,-4931,-4927,-4923,-4918,-4913,-4908,-4903,-4896,-4889,-4880,-4869,-4858,
--4847,-4836,-4826,-4818,-4811,-4803,-4796,-4787,-4778,-4768,-4757,-4746,-4737,-4728,-4720,-4714,-4709,-4704,-4701,-4698,-4695,
--4691,-4687,-4680,-4672,-4664,-4655,-4647,-4641,-4636,-4633,-4631,-4628,-4624,-4617,-4608,-4597,-4587,-4577,-4569,-4562,-4556,
--4549,-4542,-4532,-4521,-4509,-4496,-4485,-4475,-4467,-4462,-4458,-4455,-4452,-4449,-4444,-4439,-4431,-4422,-4413,-4403,-4394,
--4385,-4377,-4370,-4362,-4353,-4342,-4329,-4315,-4300,-4285,-4273,-4264,-4258,-4255,-4254,-4253,-4251,-4247,-4241,-4234,-4226,
--4216,-4207,-4199,-4190,-4182,-4174,-4167,-4161,-4155,-4151,-4147,-4143,-4140,-4135,-4129,-4122,-4113,-4103,-4092,-4080,-4067,
--4054,-4041,-4028,-4015,-4004,-3994,-3985,-3979,-3975,-3974,-3973,-3972,-3970,-3966,-3960,-3952,-3943,-3932,-3922,-3914,-3907,
--3901,-3896,-3892,-3889,-3886,-3884,-3883,-3883,-3884,-3885,-3885,-3884,-3880,-3874,-3865,-3855,-3843,-3832,-3821,-3810,-3800,
--3790,-3779,-3770,-3761,-3752,-3746,-3740,-3734,-3728,-3720,-3709,-3695,-3679,-3662,-3644,-3628,-3612,-3598,-3584,-3571,-3558,
--3545,-3532,-3520,-3508,-3496,-3484,-3471,-3457,-3443,-3427,-3411,-3396,-3383,-3371,-3361,-3352,-3343,-3333,-3320,-3307,-3291,
--3275,-3259,-3244,-3229,-3215,-3201,-3187,-3174,-3161,-3149,-3138,-3129,-3120,-3113,-3105,-3095,-3084,-3072,-3058,-3045,-3031,
--3019,-3009,-3000,-2991,-2982,-2974,-2964,-2955,-2945,-2936,-2927,-2919,-2911,-2903,-2894,-2884,-2873,-2862,-2851,-2840,-2830,
--2820,-2810,-2799,-2787,-2774,-2761,-2747,-2734,-2721,-2710,-2699,-2689,-2678,-2667,-2656,-2643,-2631,-2619,-2607,-2595,-2584,
--2572,-2561,-2549,-2537,-2525,-2514,-2502,-2490,-2478,-2465,-2452,-2438,-2424,-2412,-2400,-2390,-2380,-2370,-2359,-2345,-2329,
--2313,-2296,-2282,-2272,-2265,-2260,-2257,-2253,-2246,-2235,-2219,-2201,-2181,-2162,-2144,-2128,-2114,-2101,-2088,-2074,-2058,
--2041,-2023,-2005,-1986,-1968,-1950,-1932,-1914,-1895,-1875,-1855,-1833,-1810,-1785,-1759,-1732,-1706,-1682,-1661,-1644,-1631,
--1619,-1608,-1595,-1578,-1557,-1532,-1503,-1475,-1447,-1423,-1402,-1384,-1369,-1354,-1340,-1325,-1309,-1293,-1277,-1261,-1246,
--1231,-1216,-1201,-1186,-1171,-1156,-1142,-1128,-1113,-1098,-1080,-1059,-1036,-1011,-985,-959,-933,-907,-882,-856,-828,
--799,-768,-735,-703,-671,-641,-614,-589,-564,-539,-513,-483,-451,-415,-377,-336,-295,-254,-214,-176,-141,
--107,-77,-47,-18,9,39,70,103,136,168,199,228,255,280,303,327,352,378,406,436,467,
-497,527,555,582,609,637,667,701,738,777,816,856,892,925,955,982,1008,1038,1072,1114,1163,
-1221,1285,1352,1419,1485,1545,1601,1651,1695,1735,1768,1795,1815,1827,1831,1830,1827,1826,1829,1842,1865,
-1897,1938,1981,2025,2063,2095,2120,2138,2152,2164,2175,2185,2195,2204,2209,2211,2212,2212,2213,2219,2227,
-2238,2248,2253,2249,2232,2203,2164,2119,2073,2032,1999,1974,1954,1935,1912,1881,1841,1795,1745,1700,1665,
-1644,1639,1649,1668,1691,1713,1729,1738,1741,1740,1738,1737,1739,1743,1748,1750,1749,1744,1736,1727,1719,
-1714,1713,1717,1722,1728,1733,1734,1732,1727,1720,1714,1710,1707,1707,1706,1705,1703,1698,1690,1681,1671,
-1661,1653,1645,1639,1633,1628,1623,1618,1612,1607,1602,1597,1593,1588,1581,1573,1563,1551,1539,1528,1519,
-1512,1510,1510,1512,1515,1518,1521,1521,1522,1521,1520,1519,1518,1516,1512,1507,1499,1491,1483,1474,1466,
-1458,1450,1441,1431,1419,1405,1390,1374,1358,1343,1327,1313,1301,1290,1283,1279,1280,1286,1294,1304,1313,
-1317,1314,1305,1288,1265,1241,1217,1199,1187,1183,1184,1189,1194,1196,1192,1181,1166,1146,1127,1109,1096,
-1087,1083,1081,1081,1079,1076,1071,1064,1057,1049,1043,1038,1035,1033,1033,1034,1036,1037,1038,1037,1034,
-1030,1026,1020,1016,1013,1011,1010,1010,1009,1006,1001,994,988,982,978,978,980,985,992,999,1007,
-1016,1026,1036,1048,1060,1071,1082,1090,1096,1100,1102,1103,1104,1106,1107,1109,1110,1111,1112,1114,1119,
-1126,1136,1148,1163,1178,1194,1210,1227,1244,1261,1278,1294,1308,1321,1333,1340,1359,1382,1408,1438,1473,
-1511,1551,1589,1623,1653,1676,1693,1705,1713,1718,1722,1726,1729,1731,1733,1734,1736,1737,1740,1744,1749,
-1755,1763,1770,1777,1785,1791,1798,1805,1811,1818,1825,1831,1838,1845,1852,1860,1870,1880,1891,1902,1914,
-1926,1937,1948,1959,1971,1982,1994,2005,2016,2025,2034,2041,2049,2057,2067,2076,2085,2091,2092,2087,2075,
-2056,2035,2013,1995,1982,1976,1975,1979,1984,1989,1994,1998,2002,2009,2017,2028,2039,2050,2058,2064,2067,
-2069,2072,2077,2085,2094,2104,2112,2118,2121,2122,2123,2124,2127,2133,2139,2147,2153,2159,2164,2170,2177,
-2187,2199,2212,2226,2238,2249,2257,2263,2268,2273,2277,2280,2282,2281,2277,2272,2265,2260,2258,2260,2267,
-2280,2297,2318,2342,2369,2399,2432,2466,2500,2533,2562,2586,2605,2620,2632,2644,2657,2672,2689,2708,2726,
-2743,2758,2771,2782,2793,2805,2818,2832,2848,2864,2880,2895,2908,2918,2923,2925,2923,2918,2911,2904,2898,
-2894,2893,2892,2892,2891,2889,2886,2883,2882,2886,2894,2907,2921,2935,2944,2947,2944,2934,2920,2906,2893,
-2883,2877,2875,2874,2874,2874,2876,2880,2886,2894,2903,2910,2915,2914,2909,2899,2888,2879,2873,2872,2875,
-2882,2889,2894,2897,2898,2897,2897,2900,2905,2914,2926,2938,2948,2957,2963,2967,2969,2969,2968,2964,2959,
-2950,2938,2923,2907,2890,2875,2862,2851,2844,2839,2836,2833,2829,2824,2816,2806,2792,2777,2760,2744,2730,
-2719,2710,2703,2697,2691,2683,2674,2665,2655,2648,2644,2642,2642,2642,2639,2632,2621,2606,2589,2570,2553,
-2536,2520,2503,2484,2463,2438,2412,2385,2360,2336,2316,2298,2282,2267,2254,2242,2231,2222,2215,2210,2204,
-2197,2189,2179,2167,2154,2141,2127,2113,2098,2081,2060,2035,2007,1976,1945,1913,1882,1853,1823,1792,1760,
-1727,1692,1659,1627,1599,1575,1555,1538,1522,1506,1488,1469,1447,1424,1401,1378,1355,1333,1311,1288,1265,
-1241,1217,1192,1166,1141,1116,1090,1063,1034,1004,972,938,902,864,824,783,743,702,664,628,594,
-564,537,511,488,464,441,416,391,366,342,320,301,285,272,263,255,248,239,227,210,187,
-160,129,97,66,41,22,10,4,1,0,-5,-16,-33,-58,-91,-129,-175,-227,-288,-358,-437,
--522,-611,-696,-772,-834,-880,-912,-932,-947,-963,-985,-1014,-1048,-1083,-1116,-1141,-1158,-1168,-1175,-1184,-1200,
--1227,-1267,-1317,-1375,-1436,-1497,-1556,-1612,-1665,-1716,-1765,-1812,-1857,-1896,-1929,-1955,-1974,-1987,-1998,-2009,-2023,
--2041,-2064,-2091,-2120,-2149,-2176,-2198,-2213,-2222,-2225,-2225,-2223,-2222,-2224,-2232,-2246,-2267,-2296,-2331,-2371,-2416,
--2464,-2514,-2565,-2616,-2665,-2711,-2755,-2795,-2833,-2869,-2904,-2939,-2975,-3012,-3049,-3084,-3118,-3150,-3178,-3203,-3226,
--3247,-3267,-3287,-3307,-3328,-3349,-3370,-3392,-3414,-3437,-3461,-3484,-3507,-3530,-3552,-3573,-3595,-3616,-3637,-3659,-3681,
--3702,-3722,-3741,-3760,-3778,-3796,-3815,-3835,-3856,-3878,-3898,-3918,-3935,-3950,-3964,-3977,-3990,-4004,-4018,-4033,-4046,
--4059,-4071,-4080,-4089,-4096,-4102,-4107,-4111,-4113,-4113,-4110,-4104,-4097,-4090,-4083,-4077,-4072,-4069,-4068,-4067,-4068,
--4069,-4072,-4077,-4085,-4094,-4105,-4117,-4129,-4141,-4154,-4166,-4180,-4196,-4215,-4237,-4261,-4287,-4312,-4335,-4355,-4370,
--4380,-4385,-4386,-4383,-4376,-4366,-4352,-4336,-4318,-4300,-4282,-4267,-4256,-4248,-4244,-4243,-4243,-4243,-4241,-4238,-4233,
--4227,-4222,-4217,-4213,-4209,-4205,-4201,-4197,-4191,-4185,-4178,-4172,-4165,-4159,-4152,-4144,-4134,-4123,-4111,-4097,-4084,
--4072,-4061,-4053,-4048,-4047,-4050,-4057,-4068,-4082,-4096,-4109,-4119,-4124,-4125,-4121,-4115,-4108,-4101,-4098,-4097,-4100,
--4105,-4113,-4122,-4133,-4145,-4160,-4177,-4195,-4213,-4229,-4244,-4256,-4266,-4276,-4287,-4302,-4319,-4341,-4364,-4386,-4407,
--4424,-4439,-4451,-4464,-4478,-4494,-4513,-4533,-4553,-4571,-4587,-4600,-4613,-4625,-4639,-4655,-4671,-4687,-4702,-4715,-4726,
--4735,-4743,-4752,-4761,-4770,-4779,-4785,-4788,-4788,-4787,-4787,-4791,-4799,-4812,-4831,-4852,-4874,-4894,-4912,-4925,-4936,
--4944,-4952,-4959,-4967,-4975,-4983,-4992,-5001,-5010,-5020,-5029,-5038,-5047,-5053,-5057,-5060,-5061,-5060,-5060,-5060,-5061,
--5061,-5061,-5060,-5057,-5053,-5048,-5042,-5038,-5033,-5030,-5026,-5021,-5015,-5007,-4999,-4990,-4983,-4977,-4973,-4971,-4970,
--4968,-4966,-4962,-4958,-4953,-4948,-4942,-4937,-4932,-4926,-4919,-4911,-4902,-4893,-4884,-4875,-4867,-4859,-4851,-4842,-4833,
--4823,-4812,-4802,-4793,-4785,-4779,-4773,-4768,-4764,-4760,-4758,-4756,-4754,-4752,-4749,-4745,-4739,-4731,-4722,-4713,-4706,
--4701,-4698,-4696,-4694,-4692,-4688,-4682,-4673,-4664,-4655,-4646,-4638,-4631,-4624,-4616,-4607,-4597,-4586,-4575,-4564,-4553,
--4543,-4535,-4527,-4520,-4514,-4509,-4505,-4502,-4499,-4496,-4493,-4488,-4483,-4476,-4469,-4462,-4453,-4443,-4433,-4420,-4406,
--4391,-4375,-4360,-4347,-4335,-4327,-4321,-4316,-4313,-4311,-4307,-4302,-4296,-4289,-4281,-4271,-4262,-4252,-4242,-4232,-4222,
--4213,-4205,-4198,-4192,-4187,-4183,-4178,-4174,-4168,-4161,-4153,-4143,-4131,-4118,-4104,-4089,-4075,-4062,-4051,-4043,-4037,
--4035,-4034,-4036,-4037,-4037,-4035,-4031,-4024,-4015,-4004,-3992,-3980,-3968,-3957,-3947,-3938,-3930,-3924,-3919,-3916,-3916,
--3918,-3921,-3924,-3927,-3927,-3926,-3921,-3915,-3906,-3897,-3886,-3875,-3864,-3853,-3841,-3829,-3818,-3807,-3797,-3789,-3781,
--3772,-3763,-3753,-3741,-3728,-3713,-3698,-3683,-3669,-3654,-3639,-3625,-3610,-3594,-3579,-3564,-3549,-3535,-3521,-3507,-3493,
--3479,-3465,-3450,-3436,-3422,-3409,-3396,-3383,-3369,-3354,-3340,-3326,-3312,-3299,-3287,-3275,-3262,-3249,-3235,-3220,-3205,
--3191,-3178,-3168,-3160,-3154,-3149,-3143,-3135,-3126,-3115,-3102,-3089,-3076,-3062,-3049,-3037,-3024,-3011,-2998,-2985,-2974,
--2964,-2956,-2950,-2945,-2940,-2934,-2927,-2919,-2909,-2898,-2886,-2875,-2865,-2854,-2843,-2831,-2819,-2805,-2792,-2778,-2764,
--2751,-2739,-2727,-2716,-2704,-2692,-2679,-2666,-2653,-2641,-2628,-2616,-2605,-2593,-2582,-2571,-2560,-2549,-2538,-2526,-2514,
--2502,-2488,-2473,-2458,-2445,-2432,-2422,-2412,-2402,-2392,-2380,-2365,-2350,-2333,-2319,-2306,-2297,-2291,-2287,-2283,-2277,
--2269,-2258,-2243,-2228,-2212,-2196,-2181,-2167,-2152,-2136,-2119,-2101,-2082,-2063,-2046,-2030,-2016,-2002,-1987,-1970,-1951,
--1930,-1906,-1881,-1855,-1829,-1803,-1778,-1754,-1733,-1716,-1702,-1690,-1681,-1672,-1660,-1642,-1619,-1590,-1557,-1522,-1488,
--1459,-1434,-1415,-1399,-1385,-1371,-1356,-1339,-1321,-1303,-1286,-1271,-1258,-1245,-1231,-1217,-1201,-1184,-1168,-1151,-1135,
--1120,-1104,-1086,-1066,-1043,-1017,-990,-963,-936,-911,-887,-862,-835,-806,-775,-742,-709,-677,-646,-619,-593,
--569,-543,-516,-485,-451,-415,-377,-339,-300,-262,-225,-188,-153,-119,-87,-56,-27,0,28,57,87,
-118,150,181,211,238,264,288,311,334,359,386,415,445,476,507,538,567,596,625,655,687,
-721,756,791,827,862,897,931,966,1002,1043,1088,1138,1195,1256,1321,1387,1451,1511,1566,1613,1652,
-1685,1712,1735,1754,1771,1786,1799,1810,1820,1830,1842,1858,1880,1907,1940,1976,2011,2043,2068,2086,2097,
-2102,2106,2110,2115,2123,2132,2140,2145,2145,2143,2139,2138,2142,2151,2164,2178,2185,2182,2163,2126,2075,
-2013,1947,1885,1830,1785,1750,1721,1694,1665,1633,1600,1567,1540,1523,1517,1525,1543,1566,1592,1614,1630,
-1639,1642,1641,1639,1638,1640,1645,1652,1659,1665,1670,1673,1675,1676,1677,1679,1680,1681,1681,1679,1675,
-1669,1661,1653,1646,1640,1637,1635,1635,1635,1634,1631,1625,1618,1608,1598,1589,1580,1574,1570,1567,1565,
-1564,1562,1559,1555,1549,1543,1536,1529,1520,1512,1503,1494,1486,1480,1475,1471,1468,1465,1462,1458,1455,
-1451,1448,1447,1448,1450,1452,1452,1450,1445,1436,1425,1412,1401,1390,1383,1377,1372,1367,1360,1349,1335,
-1317,1297,1277,1257,1240,1226,1217,1212,1211,1214,1219,1225,1232,1235,1235,1229,1218,1202,1182,1163,1145,
-1133,1125,1123,1125,1128,1129,1126,1118,1106,1092,1078,1066,1057,1053,1051,1051,1051,1049,1045,1040,1033,
-1026,1019,1015,1011,1009,1008,1007,1006,1005,1005,1004,1002,999,996,991,986,981,977,974,974,974,
-976,977,977,976,974,972,969,968,967,968,970,973,978,984,992,1002,1014,1026,1039,1050,1058,
-1065,1070,1074,1078,1082,1088,1094,1100,1104,1107,1109,1112,1115,1121,1129,1141,1155,1171,1188,1205,1222,
-1238,1255,1272,1289,1306,1323,1340,1351,1380,1411,1445,1482,1521,1562,1602,1639,1671,1697,1717,1732,1741,
-1748,1752,1755,1758,1760,1761,1760,1758,1754,1750,1746,1744,1744,1745,1748,1752,1755,1759,1762,1765,1769,
-1773,1779,1786,1794,1803,1812,1822,1832,1842,1854,1865,1877,1889,1901,1911,1922,1931,1941,1950,1960,1971,
-1981,1992,2004,2015,2027,2038,2049,2057,2061,2060,2053,2039,2020,1998,1977,1957,1944,1937,1936,1939,1945,
-1951,1956,1960,1964,1969,1976,1984,1994,2003,2010,2015,2018,2019,2021,2026,2033,2044,2055,2066,2075,2080,
-2081,2081,2079,2080,2082,2088,2094,2101,2107,2113,2118,2124,2133,2144,2158,2173,2188,2200,2209,2215,2220,
-2224,2228,2234,2240,2245,2247,2244,2238,2229,2219,2210,2207,2209,2217,2231,2251,2274,2301,2330,2362,2396,
-2431,2466,2500,2531,2558,2581,2600,2616,2631,2644,2658,2671,2685,2699,2713,2726,2739,2752,2766,2780,2796,
-2812,2829,2846,2862,2876,2887,2894,2897,2895,2890,2883,2876,2871,2868,2867,2868,2869,2869,2867,2863,2860,
-2858,2861,2869,2883,2901,2920,2936,2946,2950,2947,2939,2930,2921,2914,2912,2914,2920,2928,2938,2949,2962,
-2975,2987,2996,3001,2999,2991,2976,2959,2940,2925,2915,2911,2913,2918,2923,2926,2926,2923,2918,2912,2909,
-2910,2913,2920,2928,2936,2943,2948,2952,2954,2954,2952,2947,2939,2927,2912,2894,2875,2857,2842,2831,2823,
-2819,2818,2817,2816,2814,2810,2803,2793,2781,2767,2751,2735,2720,2706,2694,2684,2676,2668,2660,2653,2646,
-2639,2635,2632,2631,2631,2630,2627,2621,2611,2597,2580,2562,2543,2524,2504,2483,2461,2437,2411,2385,2358,
-2333,2309,2287,2266,2246,2227,2209,2193,2179,2169,2161,2157,2154,2151,2147,2140,2131,2119,2106,2091,2075,
-2058,2039,2019,1995,1969,1941,1911,1882,1853,1824,1796,1767,1739,1712,1685,1660,1638,1618,1602,1588,1574,
-1561,1546,1528,1508,1486,1463,1439,1415,1391,1367,1343,1319,1295,1270,1246,1223,1199,1175,1150,1123,1093,
-1061,1025,988,948,907,865,824,782,742,702,664,629,595,565,538,514,492,471,451,431,410,
-387,363,340,318,301,288,283,283,288,296,303,305,300,288,268,242,215,189,168,153,143,
-136,130,122,110,93,71,44,12,-26,-73,-131,-201,-283,-376,-474,-570,-659,-734,-794,-839,-873,
--901,-930,-962,-998,-1036,-1072,-1101,-1120,-1130,-1134,-1137,-1146,-1166,-1201,-1251,-1312,-1379,-1448,-1513,-1573,-1626,
--1673,-1716,-1756,-1795,-1832,-1865,-1893,-1914,-1930,-1941,-1948,-1954,-1963,-1976,-1993,-2015,-2040,-2066,-2092,-2115,-2134,
--2147,-2156,-2161,-2165,-2170,-2179,-2193,-2214,-2241,-2275,-2315,-2359,-2406,-2455,-2505,-2555,-2605,-2655,-2703,-2749,-2793,
--2833,-2871,-2906,-2939,-2970,-3001,-3030,-3059,-3087,-3114,-3139,-3163,-3186,-3208,-3228,-3248,-3267,-3286,-3305,-3326,-3350,
--3377,-3407,-3439,-3472,-3504,-3534,-3560,-3583,-3602,-3620,-3636,-3653,-3670,-3687,-3705,-3721,-3735,-3747,-3759,-3769,-3780,
--3793,-3808,-3825,-3843,-3862,-3880,-3897,-3913,-3927,-3940,-3952,-3963,-3973,-3983,-3993,-4005,-4020,-4036,-4055,-4074,-4092,
--4107,-4118,-4124,-4125,-4124,-4121,-4120,-4122,-4127,-4134,-4143,-4151,-4157,-4161,-4163,-4164,-4166,-4170,-4177,-4185,-4195,
--4205,-4215,-4224,-4235,-4249,-4266,-4288,-4313,-4341,-4367,-4391,-4409,-4421,-4427,-4428,-4427,-4425,-4423,-4420,-4416,-4409,
--4400,-4388,-4374,-4360,-4348,-4340,-4336,-4336,-4338,-4340,-4341,-4339,-4333,-4326,-4317,-4309,-4302,-4296,-4292,-4287,-4282,
--4276,-4269,-4261,-4252,-4242,-4233,-4224,-4215,-4205,-4196,-4186,-4175,-4165,-4155,-4146,-4137,-4130,-4125,-4123,-4125,-4130,
--4140,-4153,-4168,-4182,-4194,-4202,-4205,-4205,-4202,-4198,-4194,-4191,-4190,-4191,-4193,-4197,-4203,-4212,-4224,-4239,-4257,
--4277,-4297,-4315,-4330,-4342,-4353,-4363,-4374,-4388,-4405,-4425,-4445,-4465,-4483,-4498,-4512,-4524,-4536,-4550,-4566,-4584,
--4602,-4620,-4636,-4652,-4666,-4680,-4695,-4711,-4728,-4745,-4762,-4779,-4795,-4810,-4824,-4837,-4850,-4860,-4869,-4874,-4876,
--4876,-4874,-4873,-4875,-4880,-4888,-4900,-4913,-4927,-4940,-4952,-4964,-4974,-4985,-4995,-5005,-5013,-5020,-5026,-5029,-5031,
--5033,-5036,-5039,-5045,-5051,-5057,-5062,-5065,-5068,-5069,-5070,-5071,-5072,-5074,-5075,-5075,-5074,-5072,-5069,-5066,-5064,
--5062,-5060,-5057,-5053,-5048,-5042,-5035,-5028,-5022,-5017,-5014,-5013,-5011,-5009,-5006,-5001,-4995,-4989,-4983,-4977,-4972,
--4968,-4963,-4958,-4953,-4947,-4940,-4933,-4927,-4919,-4911,-4902,-4891,-4880,-4870,-4860,-4852,-4846,-4842,-4839,-4836,-4832,
--4828,-4822,-4817,-4812,-4807,-4804,-4801,-4798,-4793,-4788,-4781,-4774,-4767,-4761,-4757,-4755,-4754,-4753,-4752,-4749,-4745,
--4740,-4734,-4727,-4719,-4712,-4704,-4696,-4688,-4680,-4672,-4663,-4654,-4644,-4633,-4621,-4608,-4595,-4583,-4573,-4566,-4561,
--4560,-4560,-4561,-4560,-4557,-4552,-4545,-4537,-4528,-4520,-4512,-4504,-4496,-4487,-4476,-4464,-4450,-4436,-4423,-4411,-4401,
--4393,-4387,-4381,-4376,-4369,-4362,-4353,-4344,-4334,-4322,-4311,-4299,-4286,-4274,-4262,-4251,-4241,-4233,-4228,-4223,-4220,
--4217,-4214,-4209,-4201,-4191,-4179,-4164,-4149,-4133,-4119,-4107,-4098,-4092,-4089,-4089,-4090,-4092,-4093,-4093,-4090,-4085,
--4078,-4069,-4058,-4046,-4034,-4022,-4009,-3997,-3986,-3976,-3968,-3963,-3959,-3958,-3959,-3960,-3962,-3963,-3963,-3961,-3959,
--3955,-3950,-3944,-3937,-3929,-3919,-3907,-3895,-3881,-3867,-3853,-3840,-3828,-3816,-3805,-3794,-3783,-3772,-3760,-3748,-3736,
--3723,-3710,-3696,-3680,-3664,-3647,-3630,-3612,-3595,-3578,-3562,-3547,-3532,-3518,-3504,-3489,-3475,-3460,-3444,-3427,-3410,
--3393,-3377,-3361,-3347,-3335,-3324,-3314,-3303,-3292,-3279,-3265,-3250,-3235,-3221,-3210,-3200,-3193,-3187,-3181,-3175,-3168,
--3159,-3148,-3137,-3126,-3114,-3102,-3089,-3074,-3059,-3043,-3026,-3011,-2998,-2988,-2980,-2975,-2971,-2967,-2962,-2956,-2948,
--2939,-2929,-2919,-2909,-2898,-2888,-2876,-2864,-2850,-2836,-2822,-2807,-2794,-2781,-2768,-2756,-2744,-2731,-2718,-2704,-2690,
--2676,-2663,-2650,-2638,-2627,-2616,-2605,-2595,-2586,-2576,-2566,-2556,-2544,-2531,-2516,-2500,-2485,-2470,-2456,-2444,-2433,
--2423,-2412,-2399,-2386,-2373,-2359,-2347,-2337,-2329,-2321,-2314,-2305,-2295,-2283,-2270,-2257,-2245,-2233,-2222,-2210,-2197,
--2181,-2163,-2143,-2123,-2104,-2087,-2073,-2061,-2049,-2037,-2022,-2004,-1982,-1958,-1932,-1906,-1879,-1853,-1828,-1803,-1780,
--1759,-1742,-1729,-1721,-1715,-1709,-1700,-1684,-1660,-1629,-1592,-1553,-1516,-1483,-1458,-1440,-1426,-1413,-1400,-1384,-1365,
--1344,-1324,-1305,-1288,-1274,-1261,-1248,-1233,-1215,-1196,-1176,-1156,-1138,-1121,-1105,-1088,-1070,-1048,-1024,-997,-969,
--942,-915,-889,-864,-838,-810,-781,-750,-719,-689,-661,-635,-610,-584,-558,-528,-494,-458,-419,-379,-339,
--300,-263,-226,-191,-157,-124,-92,-63,-34,-7,18,45,72,101,131,161,190,218,244,268,292,
-315,339,365,393,423,455,486,518,550,582,613,645,676,708,741,775,810,848,889,932,979,
-1028,1080,1133,1187,1241,1295,1350,1403,1456,1505,1549,1587,1619,1643,1661,1677,1691,1705,1722,1740,1760,
-1780,1798,1817,1835,1855,1879,1905,1934,1964,1992,2014,2030,2039,2043,2045,2047,2051,2059,2069,2078,2083,
-2083,2077,2069,2062,2060,2066,2081,2099,2116,2123,2111,2078,2023,1949,1865,1780,1703,1639,1592,1559,1538,
-1522,1507,1491,1474,1457,1444,1437,1439,1449,1466,1486,1505,1521,1532,1537,1538,1536,1534,1534,1537,1543,
-1553,1564,1575,1585,1594,1599,1601,1601,1599,1596,1592,1588,1584,1579,1574,1569,1564,1559,1555,1554,1554,
-1556,1559,1561,1562,1561,1558,1552,1545,1539,1533,1529,1526,1523,1521,1517,1511,1505,1497,1490,1483,1478,
-1473,1469,1465,1460,1455,1448,1441,1433,1424,1416,1407,1398,1389,1382,1376,1372,1371,1372,1374,1375,1375,
-1371,1363,1352,1340,1328,1318,1311,1306,1305,1303,1299,1293,1282,1267,1250,1232,1215,1201,1189,1181,1174,
-1169,1166,1163,1161,1160,1158,1156,1153,1146,1137,1125,1111,1097,1086,1077,1072,1071,1071,1071,1069,1065,
-1058,1050,1041,1034,1029,1026,1023,1021,1018,1013,1007,1000,994,989,986,985,985,985,983,981,978,
-975,972,969,968,966,964,961,958,953,949,946,944,943,944,946,948,950,951,951,950,950,
-950,951,952,954,958,963,969,978,988,999,1009,1019,1027,1034,1039,1045,1052,1059,1068,1077,1086,
-1094,1099,1104,1107,1112,1118,1127,1138,1152,1167,1183,1198,1213,1229,1245,1262,1281,1302,1325,1351,1367,
-1402,1439,1477,1516,1556,1594,1630,1664,1692,1715,1733,1746,1754,1760,1765,1769,1773,1777,1780,1782,1781,
-1778,1774,1769,1763,1758,1753,1748,1744,1740,1736,1733,1731,1732,1735,1742,1751,1762,1774,1788,1801,1814,
-1827,1840,1852,1864,1875,1886,1896,1905,1914,1923,1933,1943,1955,1969,1983,1997,2010,2021,2029,2034,2033,
-2027,2016,2001,1983,1964,1947,1933,1924,1921,1922,1926,1932,1936,1938,1939,1939,1939,1942,1946,1953,1961,
-1968,1973,1975,1976,1977,1980,1986,1995,2005,2017,2026,2032,2035,2035,2034,2034,2037,2042,2050,2058,2065,
-2070,2074,2077,2082,2090,2102,2117,2132,2147,2158,2166,2171,2175,2180,2186,2195,2204,2212,2214,2209,2197,
-2181,2162,2147,2138,2140,2152,2172,2200,2231,2262,2293,2323,2352,2381,2411,2442,2474,2505,2533,2559,2581,
-2599,2613,2625,2636,2646,2657,2668,2680,2694,2708,2723,2740,2756,2774,2791,2808,2825,2839,2851,2858,2861,
-2860,2856,2849,2843,2838,2836,2838,2841,2846,2850,2853,2854,2854,2856,2862,2872,2887,2905,2925,2944,2958,
-2967,2969,2968,2963,2959,2957,2958,2963,2971,2983,2998,3013,3029,3044,3056,3064,3065,3060,3049,3033,3015,
-2999,2987,2980,2979,2981,2984,2985,2982,2975,2965,2954,2943,2936,2932,2931,2933,2935,2937,2939,2939,2938,
-2937,2935,2932,2926,2915,2901,2882,2860,2837,2816,2799,2787,2780,2778,2779,2781,2783,2784,2784,2781,2776,
-2769,2760,2748,2734,2718,2701,2684,2667,2653,2640,2631,2623,2618,2615,2614,2614,2615,2615,2614,2611,2605,
-2596,2583,2566,2548,2527,2504,2480,2455,2429,2402,2375,2348,2322,2297,2271,2247,2222,2198,2174,2152,2133,
-2118,2109,2105,2104,2106,2108,2108,2103,2093,2079,2061,2041,2019,1998,1978,1959,1939,1920,1901,1880,1857,
-1833,1808,1782,1755,1728,1702,1678,1657,1639,1624,1612,1601,1590,1579,1566,1552,1535,1516,1496,1474,1450,
-1424,1397,1369,1341,1313,1287,1262,1238,1216,1192,1167,1139,1108,1073,1035,995,953,911,869,828,787,
-747,707,669,633,599,568,542,519,500,483,468,453,437,420,401,382,364,349,339,336,339,
-347,359,370,378,379,372,357,335,309,282,256,233,214,196,180,163,145,125,106,86,65,
-40,9,-32,-86,-156,-239,-331,-426,-518,-601,-672,-731,-780,-823,-864,-906,-949,-990,-1027,-1056,-1077,
--1090,-1099,-1109,-1125,-1151,-1191,-1242,-1302,-1365,-1428,-1486,-1539,-1585,-1627,-1666,-1704,-1742,-1779,-1813,-1843,-1867,
--1884,-1895,-1902,-1905,-1908,-1913,-1920,-1932,-1947,-1965,-1985,-2005,-2025,-2043,-2060,-2075,-2089,-2105,-2123,-2146,-2173,
--2206,-2244,-2285,-2329,-2375,-2422,-2469,-2518,-2567,-2616,-2666,-2715,-2762,-2807,-2848,-2886,-2920,-2950,-2977,-3002,-3026,
--3048,-3070,-3092,-3114,-3135,-3154,-3172,-3189,-3204,-3219,-3236,-3255,-3279,-3309,-3343,-3380,-3418,-3454,-3486,-3512,-3532,
--3547,-3560,-3571,-3584,-3598,-3615,-3631,-3647,-3660,-3670,-3677,-3683,-3689,-3696,-3706,-3718,-3733,-3749,-3764,-3779,-3793,
--3806,-3817,-3827,-3837,-3847,-3858,-3870,-3886,-3905,-3929,-3957,-3988,-4020,-4050,-4076,-4098,-4114,-4126,-4137,-4149,-4163,
--4181,-4200,-4220,-4238,-4252,-4260,-4263,-4264,-4263,-4264,-4267,-4272,-4279,-4286,-4292,-4297,-4302,-4308,-4318,-4332,-4350,
--4371,-4393,-4413,-4428,-4438,-4442,-4443,-4443,-4443,-4444,-4448,-4451,-4453,-4451,-4447,-4440,-4432,-4425,-4422,-4423,-4428,
--4435,-4441,-4444,-4443,-4437,-4428,-4417,-4405,-4396,-4388,-4383,-4378,-4374,-4368,-4360,-4351,-4339,-4327,-4314,-4301,-4288,
--4275,-4263,-4253,-4243,-4235,-4228,-4222,-4216,-4211,-4206,-4202,-4200,-4201,-4206,-4214,-4226,-4240,-4254,-4266,-4274,-4279,
--4281,-4281,-4279,-4278,-4277,-4276,-4277,-4278,-4280,-4285,-4292,-4302,-4317,-4334,-4354,-4375,-4394,-4412,-4427,-4440,-4452,
--4464,-4478,-4492,-4507,-4522,-4536,-4549,-4562,-4574,-4588,-4602,-4620,-4639,-4659,-4679,-4699,-4717,-4732,-4746,-4758,-4770,
--4781,-4794,-4808,-4825,-4843,-4862,-4882,-4902,-4920,-4934,-4944,-4949,-4952,-4952,-4953,-4955,-4960,-4968,-4977,-4986,-4994,
--5001,-5005,-5008,-5012,-5017,-5026,-5038,-5052,-5067,-5079,-5088,-5092,-5092,-5089,-5084,-5079,-5075,-5073,-5072,-5072,-5074,
--5076,-5078,-5081,-5084,-5088,-5091,-5095,-5097,-5098,-5098,-5097,-5096,-5095,-5094,-5093,-5092,-5090,-5087,-5083,-5077,-5072,
--5068,-5064,-5061,-5058,-5055,-5051,-5046,-5040,-5034,-5028,-5022,-5017,-5014,-5010,-5007,-5003,-4999,-4995,-4990,-4985,-4980,
--4973,-4965,-4956,-4945,-4934,-4924,-4915,-4909,-4906,-4905,-4905,-4905,-4902,-4898,-4891,-4882,-4873,-4865,-4858,-4854,-4850,
--4848,-4844,-4840,-4835,-4829,-4823,-4818,-4815,-4813,-4812,-4812,-4813,-4812,-4811,-4807,-4802,-4796,-4788,-4780,-4772,-4764,
--4757,-4750,-4744,-4738,-4731,-4721,-4710,-4696,-4680,-4665,-4651,-4639,-4632,-4628,-4626,-4625,-4623,-4619,-4613,-4605,-4596,
--4588,-4582,-4578,-4576,-4574,-4573,-4569,-4562,-4553,-4541,-4528,-4515,-4502,-4491,-4481,-4472,-4463,-4454,-4445,-4434,-4423,
--4411,-4399,-4386,-4374,-4360,-4347,-4332,-4319,-4305,-4294,-4285,-4278,-4273,-4269,-4266,-4261,-4255,-4246,-4235,-4221,-4206,
--4191,-4176,-4163,-4153,-4145,-4140,-4137,-4136,-4136,-4136,-4136,-4135,-4133,-4129,-4124,-4117,-4108,-4098,-4087,-4075,-4063,
--4050,-4038,-4028,-4018,-4011,-4005,-4001,-3997,-3995,-3993,-3991,-3990,-3989,-3988,-3987,-3986,-3985,-3981,-3975,-3967,-3955,
--3941,-3926,-3909,-3893,-3877,-3863,-3850,-3839,-3828,-3818,-3808,-3797,-3786,-3774,-3761,-3746,-3730,-3713,-3695,-3676,-3658,
--3639,-3621,-3604,-3587,-3571,-3555,-3539,-3523,-3506,-3489,-3471,-3454,-3436,-3420,-3404,-3390,-3377,-3365,-3354,-3342,-3329,
--3316,-3302,-3288,-3275,-3262,-3252,-3243,-3235,-3228,-3220,-3212,-3202,-3191,-3180,-3169,-3159,-3150,-3141,-3131,-3121,-3108,
--3093,-3078,-3061,-3046,-3032,-3021,-3013,-3006,-3000,-2994,-2988,-2981,-2973,-2964,-2956,-2948,-2940,-2932,-2922,-2912,-2899,
--2885,-2870,-2855,-2841,-2827,-2814,-2801,-2788,-2775,-2761,-2746,-2731,-2715,-2700,-2686,-2673,-2660,-2649,-2638,-2628,-2619,
--2611,-2603,-2594,-2584,-2573,-2560,-2545,-2530,-2514,-2499,-2484,-2471,-2458,-2446,-2433,-2420,-2408,-2396,-2385,-2375,-2366,
--2357,-2347,-2336,-2323,-2309,-2294,-2280,-2267,-2257,-2248,-2240,-2230,-2218,-2203,-2186,-2168,-2150,-2135,-2122,-2111,-2101,
--2089,-2074,-2055,-2033,-2008,-1983,-1958,-1935,-1913,-1889,-1864,-1836,-1805,-1776,-1750,-1730,-1718,-1713,-1712,-1711,-1704,
--1688,-1662,-1627,-1588,-1549,-1515,-1489,-1471,-1459,-1449,-1438,-1423,-1403,-1379,-1354,-1330,-1309,-1291,-1276,-1261,-1244,
--1225,-1204,-1181,-1158,-1136,-1118,-1102,-1087,-1072,-1054,-1033,-1009,-983,-955,-928,-900,-874,-847,-819,-791,-762,
--733,-704,-677,-651,-626,-601,-573,-543,-509,-472,-432,-392,-351,-311,-273,-237,-202,-169,-137,-106,-77,
--49,-23,2,28,54,82,110,138,167,194,220,245,270,295,320,347,375,405,435,465,497,
-528,561,593,627,661,696,733,772,815,861,913,968,1026,1084,1141,1194,1242,1286,1326,1364,1402,
-1440,1478,1514,1547,1574,1596,1611,1624,1635,1648,1665,1685,1707,1729,1750,1769,1786,1803,1821,1843,1868,
-1896,1924,1949,1969,1981,1987,1988,1988,1989,1993,1998,2003,2006,2004,1999,1992,1987,1988,1996,2013,2033,
-2050,2056,2043,2006,1945,1866,1776,1685,1604,1539,1494,1466,1451,1445,1440,1433,1423,1411,1398,1388,1384,
-1386,1395,1408,1424,1441,1456,1467,1476,1481,1484,1486,1487,1489,1492,1495,1499,1503,1506,1507,1507,1505,
-1502,1499,1497,1497,1498,1500,1501,1502,1501,1499,1496,1494,1492,1493,1495,1499,1503,1506,1507,1506,1503,
-1499,1495,1492,1489,1486,1482,1477,1470,1462,1453,1444,1437,1431,1427,1424,1420,1415,1409,1401,1392,1383,
-1374,1366,1358,1350,1342,1334,1325,1317,1309,1304,1300,1298,1296,1292,1288,1281,1273,1264,1256,1250,1245,
-1242,1239,1235,1229,1221,1210,1198,1187,1176,1168,1161,1155,1149,1142,1134,1126,1117,1110,1104,1100,1096,
-1092,1086,1079,1070,1060,1051,1044,1039,1037,1036,1035,1034,1030,1025,1018,1011,1005,999,994,990,985,
-978,971,963,955,950,947,946,947,949,950,949,947,943,940,937,936,937,938,939,939,937,
-934,930,925,921,918,917,917,918,919,920,921,923,925,928,931,934,938,942,947,952,959,
-966,974,983,992,1000,1009,1017,1025,1033,1043,1053,1063,1072,1080,1088,1094,1100,1106,1114,1125,1137,
-1150,1164,1178,1192,1206,1220,1236,1255,1278,1304,1334,1367,1380,1418,1457,1495,1533,1571,1606,1640,1671,
-1697,1718,1734,1744,1749,1752,1752,1753,1754,1756,1758,1761,1763,1764,1763,1760,1755,1748,1741,1732,1724,
-1715,1707,1702,1699,1699,1703,1711,1723,1737,1752,1767,1782,1796,1809,1821,1832,1842,1852,1862,1872,1882,
-1892,1904,1917,1931,1946,1962,1977,1990,2000,2005,2005,1999,1988,1972,1953,1935,1918,1905,1899,1898,1902,
-1910,1919,1927,1931,1930,1927,1921,1915,1911,1910,1913,1919,1925,1931,1935,1937,1938,1941,1945,1951,1960,
-1970,1978,1984,1986,1986,1985,1985,1988,1995,2004,2014,2024,2030,2034,2035,2037,2040,2047,2059,2074,2089,
-2103,2114,2121,2126,2131,2138,2147,2158,2168,2174,2171,2158,2135,2108,2081,2061,2054,2063,2089,2127,2172,
-2218,2261,2296,2323,2345,2363,2382,2402,2427,2454,2482,2510,2535,2556,2573,2586,2596,2606,2615,2625,2636,
-2648,2661,2675,2690,2705,2721,2738,2755,2772,2787,2800,2809,2814,2815,2812,2807,2801,2798,2797,2799,2805,
-2813,2823,2832,2841,2849,2858,2869,2882,2898,2916,2935,2955,2972,2986,2996,3002,3006,3007,3008,3008,3009,
-3012,3016,3023,3031,3041,3050,3058,3063,3065,3062,3057,3050,3044,3040,3040,3043,3047,3050,3049,3044,3033,
-3019,3003,2989,2978,2971,2968,2968,2967,2964,2958,2950,2939,2929,2920,2913,2906,2898,2887,2872,2851,2826,
-2800,2774,2752,2736,2726,2721,2720,2722,2725,2728,2732,2736,2739,2742,2744,2742,2736,2725,2710,2691,2669,
-2648,2628,2611,2599,2591,2586,2585,2585,2587,2587,2587,2584,2578,2569,2556,2539,2518,2494,2468,2439,2409,
-2378,2348,2319,2291,2264,2238,2213,2188,2163,2139,2116,2096,2080,2068,2062,2061,2063,2066,2068,2066,2059,
-2045,2027,2004,1980,1956,1934,1915,1899,1886,1874,1862,1848,1831,1810,1785,1757,1727,1696,1667,1639,1614,
-1592,1573,1556,1541,1528,1515,1503,1492,1482,1472,1461,1449,1433,1414,1391,1365,1337,1308,1280,1254,1229,
-1205,1181,1155,1126,1095,1060,1024,986,948,910,872,835,796,758,720,682,646,613,584,558,536,
-517,501,486,471,457,443,430,417,405,396,390,386,385,386,386,386,381,372,357,336,311,
-283,254,226,198,172,146,120,96,72,51,33,18,7,-4,-18,-41,-75,-124,-187,-262,-345,
--430,-511,-585,-651,-708,-757,-802,-844,-883,-920,-954,-984,-1009,-1031,-1053,-1076,-1103,-1137,-1176,-1221,-1268,
--1316,-1362,-1406,-1448,-1490,-1532,-1575,-1621,-1667,-1712,-1754,-1791,-1822,-1846,-1863,-1875,-1882,-1886,-1888,-1891,-1895,
--1901,-1909,-1921,-1935,-1951,-1968,-1986,-2005,-2023,-2042,-2062,-2084,-2110,-2140,-2175,-2213,-2256,-2301,-2348,-2398,-2448,
--2500,-2552,-2604,-2657,-2708,-2757,-2805,-2849,-2891,-2929,-2964,-2995,-3024,-3050,-3074,-3096,-3116,-3133,-3149,-3162,-3174,
--3184,-3195,-3207,-3222,-3242,-3266,-3294,-3325,-3354,-3382,-3404,-3422,-3434,-3444,-3454,-3465,-3480,-3497,-3517,-3536,-3554,
--3568,-3578,-3586,-3592,-3597,-3604,-3611,-3620,-3629,-3637,-3644,-3651,-3657,-3665,-3676,-3690,-3708,-3728,-3749,-3772,-3795,
--3819,-3846,-3875,-3908,-3943,-3978,-4013,-4045,-4073,-4099,-4123,-4146,-4171,-4199,-4228,-4256,-4283,-4304,-4319,-4329,-4335,
--4339,-4342,-4348,-4356,-4364,-4372,-4377,-4379,-4379,-4378,-4378,-4381,-4389,-4401,-4415,-4429,-4442,-4450,-4456,-4458,-4460,
--4462,-4466,-4472,-4478,-4483,-4487,-4487,-4486,-4485,-4486,-4491,-4500,-4512,-4524,-4535,-4541,-4542,-4536,-4526,-4513,-4501,
--4490,-4482,-4477,-4474,-4471,-4467,-4460,-4452,-4440,-4427,-4412,-4396,-4380,-4363,-4348,-4334,-4322,-4313,-4307,-4303,-4301,
--4299,-4296,-4292,-4288,-4284,-4284,-4286,-4293,-4303,-4314,-4326,-4337,-4345,-4350,-4352,-4353,-4354,-4354,-4355,-4356,-4357,
--4358,-4359,-4361,-4366,-4373,-4384,-4399,-4417,-4437,-4457,-4477,-4495,-4511,-4525,-4538,-4550,-4562,-4574,-4587,-4599,-4612,
--4625,-4640,-4656,-4674,-4694,-4715,-4738,-4760,-4781,-4799,-4814,-4825,-4834,-4840,-4847,-4857,-4869,-4886,-4907,-4930,-4954,
--4976,-4993,-5005,-5012,-5016,-5019,-5023,-5030,-5041,-5055,-5070,-5083,-5091,-5095,-5093,-5088,-5083,-5080,-5084,-5093,-5107,
--5125,-5142,-5156,-5165,-5167,-5163,-5155,-5143,-5132,-5121,-5112,-5105,-5102,-5101,-5102,-5105,-5109,-5113,-5118,-5122,-5124,
--5126,-5126,-5125,-5124,-5124,-5124,-5124,-5125,-5124,-5123,-5121,-5117,-5114,-5110,-5107,-5103,-5100,-5096,-5092,-5087,-5082,
--5077,-5072,-5069,-5066,-5064,-5061,-5058,-5055,-5050,-5046,-5041,-5037,-5032,-5027,-5021,-5013,-5004,-4995,-4985,-4977,-4972,
--4969,-4969,-4969,-4970,-4969,-4965,-4959,-4950,-4941,-4932,-4924,-4918,-4914,-4911,-4908,-4904,-4899,-4894,-4888,-4882,-4878,
--4875,-4873,-4872,-4872,-4872,-4871,-4868,-4864,-4858,-4851,-4842,-4833,-4825,-4817,-4811,-4807,-4803,-4800,-4795,-4788,-4779,
--4768,-4755,-4742,-4730,-4719,-4711,-4704,-4698,-4692,-4684,-4675,-4666,-4656,-4647,-4640,-4636,-4635,-4634,-4634,-4633,-4630,
--4624,-4617,-4608,-4598,-4589,-4580,-4572,-4564,-4555,-4545,-4533,-4521,-4508,-4495,-4483,-4470,-4458,-4445,-4432,-4418,-4403,
--4388,-4373,-4359,-4347,-4337,-4329,-4321,-4314,-4307,-4298,-4288,-4276,-4262,-4248,-4234,-4220,-4207,-4196,-4187,-4179,-4174,
--4171,-4169,-4167,-4167,-4167,-4167,-4165,-4163,-4159,-4154,-4146,-4137,-4125,-4113,-4100,-4087,-4075,-4064,-4055,-4047,-4040,
--4033,-4028,-4023,-4019,-4017,-4016,-4017,-4019,-4020,-4021,-4019,-4014,-4006,-3995,-3980,-3964,-3947,-3931,-3915,-3901,-3889,
--3878,-3868,-3858,-3847,-3836,-3823,-3808,-3792,-3775,-3756,-3737,-3717,-3697,-3678,-3660,-3642,-3624,-3607,-3589,-3571,-3553,
--3534,-3515,-3497,-3480,-3464,-3450,-3437,-3425,-3413,-3401,-3387,-3372,-3357,-3341,-3326,-3312,-3300,-3291,-3283,-3277,-3270,
--3262,-3252,-3240,-3227,-3213,-3201,-3190,-3181,-3173,-3166,-3159,-3150,-3140,-3127,-3113,-3098,-3084,-3072,-3061,-3051,-3042,
--3034,-3025,-3016,-3008,-2999,-2992,-2986,-2980,-2974,-2967,-2958,-2948,-2935,-2921,-2906,-2890,-2876,-2861,-2848,-2834,-2820,
--2805,-2790,-2774,-2758,-2741,-2725,-2710,-2695,-2681,-2668,-2656,-2645,-2635,-2626,-2617,-2608,-2598,-2587,-2575,-2561,-2548,
--2534,-2520,-2507,-2494,-2481,-2467,-2453,-2439,-2425,-2413,-2401,-2391,-2382,-2372,-2362,-2350,-2336,-2322,-2307,-2294,-2284,
--2275,-2268,-2260,-2250,-2238,-2224,-2209,-2194,-2181,-2171,-2162,-2154,-2143,-2128,-2107,-2082,-2055,-2028,-2004,-1984,-1967,
--1950,-1930,-1903,-1867,-1826,-1782,-1742,-1711,-1693,-1689,-1694,-1703,-1707,-1701,-1681,-1649,-1609,-1567,-1529,-1501,-1484,
--1475,-1471,-1467,-1457,-1440,-1417,-1389,-1360,-1334,-1311,-1292,-1275,-1258,-1239,-1216,-1191,-1166,-1142,-1120,-1103,-1088,
--1074,-1059,-1043,-1022,-999,-973,-946,-919,-892,-865,-838,-810,-781,-751,-722,-693,-665,-638,-612,-585,-557,
--526,-494,-460,-424,-388,-352,-316,-281,-246,-212,-179,-146,-115,-84,-54,-25,3,31,59,86,113,
-139,165,190,215,241,269,298,327,358,388,417,446,475,504,534,567,601,639,680,725,774,
-828,886,948,1012,1076,1137,1192,1240,1280,1313,1341,1367,1393,1421,1451,1481,1509,1533,1552,1566,1579,
-1591,1607,1626,1650,1677,1702,1725,1743,1756,1766,1777,1791,1809,1832,1857,1883,1904,1918,1926,1927,1923,
-1918,1913,1909,1907,1906,1905,1904,1906,1912,1922,1939,1957,1974,1983,1976,1949,1901,1835,1755,1673,1596,
-1532,1485,1456,1441,1435,1432,1426,1416,1401,1383,1365,1350,1340,1337,1340,1350,1364,1382,1402,1422,1442,
-1459,1473,1483,1487,1487,1482,1475,1466,1458,1450,1443,1438,1434,1431,1431,1433,1438,1444,1452,1460,1466,
-1469,1469,1466,1462,1457,1454,1453,1453,1456,1458,1460,1461,1460,1458,1455,1453,1452,1450,1448,1446,1441,
-1435,1428,1420,1412,1404,1397,1389,1380,1369,1358,1345,1333,1322,1315,1310,1307,1305,1302,1297,1289,1278,
-1265,1253,1242,1233,1227,1224,1221,1219,1216,1212,1206,1201,1195,1189,1184,1177,1170,1162,1154,1145,1137,
-1130,1124,1119,1115,1110,1104,1096,1088,1079,1072,1065,1060,1056,1053,1048,1042,1036,1029,1022,1017,1014,
-1012,1011,1009,1006,1001,994,986,977,970,963,956,950,944,937,929,921,914,909,906,905,906,
-908,908,908,906,904,902,901,902,905,907,910,910,909,906,901,896,892,889,888,888,889,
-890,892,894,898,902,907,913,919,924,929,933,937,941,947,953,962,972,983,994,1005,1016,
-1026,1036,1045,1054,1062,1069,1077,1084,1092,1101,1111,1122,1134,1147,1160,1173,1185,1199,1214,1232,1253,
-1279,1310,1344,1380,1377,1415,1453,1490,1527,1563,1598,1631,1661,1687,1707,1720,1727,1727,1723,1716,1709,
-1703,1698,1697,1698,1699,1701,1703,1702,1700,1697,1692,1687,1682,1677,1674,1673,1673,1677,1684,1694,1705,
-1719,1734,1749,1763,1776,1787,1797,1806,1815,1823,1833,1844,1856,1869,1884,1901,1917,1934,1949,1962,1971,
-1976,1974,1967,1953,1935,1914,1893,1874,1861,1855,1856,1864,1876,1889,1901,1908,1909,1905,1898,1888,1880,
-1875,1875,1877,1883,1889,1894,1897,1900,1902,1905,1911,1918,1927,1934,1940,1942,1942,1939,1937,1938,1942,
-1949,1959,1970,1978,1983,1985,1985,1986,1990,1999,2012,2027,2043,2057,2068,2076,2083,2090,2100,2113,2125,
-2134,2135,2124,2102,2070,2035,2004,1987,1988,2011,2054,2110,2172,2231,2280,2316,2339,2352,2359,2367,2377,
-2393,2414,2439,2464,2487,2507,2524,2537,2548,2557,2567,2576,2586,2597,2607,2617,2628,2640,2654,2669,2685,
-2703,2720,2736,2749,2758,2764,2766,2765,2763,2762,2762,2764,2770,2778,2789,2802,2816,2830,2844,2859,2875,
-2893,2912,2932,2954,2977,2999,3020,3037,3049,3056,3056,3051,3042,3030,3019,3010,3005,3003,3005,3010,3015,
-3020,3025,3031,3039,3049,3063,3079,3094,3107,3114,3112,3102,3086,3066,3047,3032,3023,3021,3022,3023,3021,
-3012,2997,2975,2952,2928,2908,2893,2882,2872,2860,2844,2823,2796,2766,2736,2709,2687,2672,2662,2658,2656,
-2657,2661,2666,2675,2686,2700,2714,2726,2734,2735,2727,2711,2689,2662,2634,2608,2585,2568,2556,2549,2546,
-2546,2546,2546,2544,2539,2530,2517,2500,2477,2451,2421,2389,2356,2323,2290,2260,2231,2204,2179,2155,2132,
-2111,2093,2076,2062,2052,2045,2040,2038,2035,2032,2026,2016,2003,1985,1965,1944,1922,1902,1885,1870,1857,
-1846,1835,1821,1804,1782,1756,1725,1691,1656,1622,1589,1560,1533,1509,1487,1466,1447,1428,1412,1399,1390,
-1385,1383,1383,1382,1378,1369,1354,1334,1310,1284,1258,1232,1207,1183,1158,1132,1103,1073,1040,1007,974,
-940,907,874,841,807,773,739,706,676,648,623,600,578,557,535,513,491,469,449,433,419,
-409,400,392,384,373,359,343,323,301,277,252,226,200,174,148,122,95,69,42,15,-11,
--35,-56,-73,-86,-94,-101,-108,-121,-141,-173,-218,-274,-340,-412,-485,-556,-621,-678,-727,-767,-800,
--828,-853,-876,-899,-925,-953,-984,-1019,-1055,-1092,-1128,-1162,-1193,-1221,-1249,-1279,-1314,-1354,-1401,-1454,-1510,
--1568,-1624,-1675,-1721,-1760,-1794,-1822,-1846,-1866,-1882,-1895,-1905,-1913,-1919,-1925,-1931,-1939,-1948,-1960,-1971,-1982,
--1992,-2001,-2009,-2018,-2029,-2045,-2068,-2099,-2138,-2184,-2236,-2292,-2350,-2408,-2465,-2520,-2573,-2626,-2677,-2729,-2782,
--2835,-2887,-2938,-2985,-3028,-3065,-3096,-3121,-3140,-3155,-3167,-3176,-3185,-3193,-3201,-3211,-3222,-3235,-3249,-3263,-3275,
--3286,-3294,-3300,-3304,-3310,-3318,-3329,-3347,-3368,-3393,-3418,-3441,-3460,-3475,-3487,-3496,-3505,-3515,-3527,-3538,-3548,
--3554,-3556,-3554,-3551,-3549,-3553,-3565,-3587,-3616,-3652,-3689,-3725,-3757,-3784,-3808,-3830,-3853,-3878,-3907,-3938,-3971,
--4003,-4035,-4065,-4095,-4125,-4156,-4189,-4222,-4254,-4282,-4307,-4326,-4342,-4356,-4369,-4384,-4399,-4414,-4428,-4438,-4443,
--4443,-4440,-4436,-4432,-4432,-4435,-4442,-4451,-4460,-4468,-4475,-4480,-4485,-4490,-4496,-4503,-4510,-4516,-4520,-4524,-4526,
--4530,-4537,-4548,-4563,-4580,-4598,-4612,-4622,-4624,-4620,-4611,-4598,-4586,-4574,-4566,-4561,-4558,-4555,-4553,-4549,-4543,
--4535,-4525,-4512,-4498,-4481,-4463,-4443,-4425,-4408,-4394,-4385,-4379,-4376,-4375,-4373,-4371,-4367,-4363,-4360,-4359,-4362,
--4368,-4377,-4389,-4400,-4410,-4418,-4423,-4427,-4429,-4431,-4432,-4434,-4436,-4437,-4437,-4436,-4435,-4436,-4440,-4448,-4461,
--4477,-4496,-4516,-4536,-4555,-4572,-4587,-4601,-4615,-4628,-4642,-4657,-4671,-4686,-4701,-4715,-4731,-4748,-4766,-4787,-4809,
--4831,-4852,-4871,-4886,-4897,-4905,-4912,-4919,-4929,-4943,-4961,-4982,-5005,-5027,-5046,-5060,-5070,-5077,-5084,-5094,-5107,
--5124,-5145,-5166,-5185,-5197,-5202,-5200,-5192,-5181,-5172,-5167,-5169,-5177,-5190,-5206,-5221,-5232,-5238,-5238,-5233,-5224,
--5212,-5199,-5186,-5176,-5167,-5160,-5156,-5153,-5152,-5152,-5152,-5151,-5150,-5148,-5146,-5144,-5143,-5143,-5144,-5146,-5148,
--5149,-5150,-5150,-5148,-5147,-5145,-5143,-5141,-5140,-5138,-5136,-5133,-5130,-5128,-5126,-5124,-5123,-5121,-5119,-5115,-5110,
--5105,-5099,-5094,-5090,-5086,-5083,-5080,-5076,-5071,-5064,-5056,-5049,-5042,-5037,-5033,-5031,-5030,-5028,-5026,-5021,-5016,
--5010,-5004,-4998,-4993,-4988,-4983,-4978,-4972,-4966,-4960,-4954,-4948,-4943,-4940,-4937,-4935,-4933,-4930,-4927,-4923,-4918,
--4912,-4906,-4898,-4890,-4882,-4875,-4868,-4864,-4860,-4858,-4857,-4855,-4852,-4847,-4839,-4830,-4820,-4809,-4799,-4789,-4780,
--4770,-4761,-4751,-4740,-4730,-4719,-4710,-4701,-4694,-4688,-4682,-4677,-4671,-4665,-4660,-4655,-4650,-4647,-4644,-4641,-4637,
--4631,-4624,-4615,-4604,-4591,-4579,-4566,-4554,-4542,-4530,-4517,-4504,-4489,-4473,-4456,-4439,-4423,-4407,-4393,-4381,-4370,
--4360,-4351,-4341,-4331,-4320,-4307,-4293,-4278,-4263,-4248,-4234,-4222,-4211,-4203,-4198,-4194,-4193,-4193,-4194,-4195,-4196,
--4197,-4195,-4192,-4186,-4178,-4167,-4156,-4143,-4131,-4119,-4109,-4099,-4091,-4083,-4075,-4068,-4062,-4057,-4054,-4052,-4052,
--4053,-4054,-4054,-4053,-4049,-4041,-4030,-4017,-4002,-3986,-3970,-3955,-3942,-3929,-3918,-3906,-3894,-3882,-3868,-3852,-3835,
--3816,-3796,-3776,-3755,-3735,-3715,-3696,-3678,-3660,-3642,-3623,-3604,-3584,-3564,-3545,-3527,-3511,-3496,-3484,-3472,-3461,
--3449,-3436,-3422,-3406,-3390,-3373,-3358,-3345,-3335,-3326,-3319,-3312,-3304,-3294,-3283,-3270,-3256,-3243,-3232,-3222,-3215,
--3208,-3201,-3194,-3184,-3173,-3160,-3146,-3133,-3120,-3109,-3099,-3090,-3081,-3071,-3061,-3051,-3042,-3034,-3027,-3021,-3015,
--3008,-3001,-2991,-2979,-2965,-2950,-2935,-2920,-2905,-2890,-2875,-2860,-2845,-2829,-2812,-2796,-2780,-2764,-2749,-2733,-2717,
--2702,-2686,-2670,-2656,-2642,-2630,-2619,-2608,-2597,-2586,-2574,-2563,-2551,-2540,-2530,-2519,-2509,-2497,-2484,-2469,-2453,
--2438,-2423,-2410,-2399,-2389,-2380,-2370,-2360,-2348,-2337,-2326,-2316,-2307,-2300,-2292,-2283,-2271,-2258,-2243,-2228,-2215,
--2206,-2199,-2193,-2186,-2174,-2155,-2130,-2101,-2070,-2043,-2021,-2006,-1994,-1981,-1962,-1932,-1890,-1840,-1786,-1737,-1700,
--1681,-1679,-1690,-1705,-1715,-1713,-1692,-1655,-1607,-1556,-1512,-1480,-1463,-1461,-1466,-1473,-1475,-1468,-1450,-1425,-1395,
--1366,-1339,-1317,-1298,-1281,-1262,-1240,-1214,-1188,-1161,-1136,-1115,-1097,-1081,-1066,-1050,-1032,-1011,-988,-964,-939,
--914,-890,-865,-839,-812,-783,-752,-720,-689,-659,-630,-602,-575,-549,-523,-496,-469,-440,-411,-380,-348,
--314,-280,-244,-207,-170,-133,-98,-63,-30,0,30,57,82,106,130,154,179,207,237,269,302,
-335,367,397,426,454,481,510,542,579,620,667,719,776,837,902,968,1034,1097,1154,1205,1247,
-1282,1311,1336,1359,1383,1408,1433,1457,1478,1495,1508,1520,1533,1549,1573,1603,1639,1676,1711,1739,1757,
-1767,1769,1767,1767,1770,1779,1793,1810,1825,1837,1843,1842,1837,1828,1818,1810,1803,1800,1802,1808,1820,
-1838,1860,1882,1902,1913,1908,1885,1843,1783,1713,1639,1572,1519,1483,1463,1457,1457,1458,1453,1440,1419,
-1392,1364,1338,1317,1304,1297,1296,1301,1310,1324,1342,1363,1388,1414,1437,1456,1468,1473,1469,1460,1448,
-1434,1421,1410,1402,1397,1394,1393,1395,1399,1405,1413,1422,1429,1435,1437,1436,1433,1428,1423,1420,1419,
-1419,1420,1422,1422,1422,1420,1419,1417,1416,1416,1415,1414,1412,1408,1402,1396,1388,1380,1370,1359,1346,
-1329,1311,1293,1276,1261,1252,1248,1247,1249,1251,1250,1245,1235,1222,1206,1191,1178,1169,1163,1160,1158,
-1156,1153,1148,1142,1135,1128,1120,1113,1107,1100,1093,1086,1079,1072,1065,1060,1054,1049,1045,1040,1036,
-1032,1028,1025,1022,1018,1015,1010,1004,998,992,987,984,982,980,978,975,970,963,955,945,936,
-927,920,914,908,902,895,888,881,874,869,866,865,865,865,865,865,864,864,863,864,866,
-868,870,871,870,867,863,859,856,854,854,856,858,861,864,867,870,874,878,884,890,897,
-903,909,914,918,922,928,936,947,959,972,986,1000,1011,1021,1030,1037,1044,1051,1058,1066,1074,
-1083,1093,1104,1115,1126,1138,1149,1161,1173,1186,1202,1222,1245,1273,1305,1340,1377,1356,1393,1430,1466,
-1502,1537,1570,1601,1629,1652,1670,1680,1684,1681,1673,1663,1652,1642,1635,1630,1629,1629,1629,1630,1630,
-1631,1631,1632,1634,1638,1643,1649,1656,1664,1671,1679,1688,1699,1710,1723,1736,1749,1762,1774,1784,1794,
-1803,1813,1824,1836,1850,1865,1881,1896,1911,1925,1936,1944,1948,1949,1944,1935,1920,1903,1882,1862,1845,
-1832,1825,1825,1831,1840,1851,1860,1866,1867,1863,1857,1851,1846,1844,1844,1848,1853,1857,1861,1863,1865,
-1867,1871,1876,1883,1891,1897,1900,1901,1899,1896,1894,1894,1897,1903,1910,1918,1923,1926,1928,1929,1933,
-1940,1951,1966,1983,1999,2013,2024,2034,2043,2054,2068,2082,2095,2102,2098,2083,2057,2024,1992,1970,1963,
-1978,2015,2070,2134,2198,2255,2298,2325,2339,2343,2343,2346,2354,2368,2387,2409,2430,2448,2462,2473,2482,
-2490,2498,2508,2518,2528,2537,2546,2554,2562,2571,2582,2596,2611,2629,2647,2665,2682,2697,2709,2719,2727,
-2732,2736,2740,2743,2748,2754,2762,2772,2785,2800,2816,2833,2851,2870,2891,2915,2941,2970,3000,3029,3055,
-3073,3082,3081,3070,3052,3029,3007,2988,2976,2971,2972,2978,2987,2997,3009,3024,3043,3067,3096,3127,3158,
-3184,3201,3206,3198,3180,3157,3134,3115,3102,3097,3095,3092,3085,3069,3045,3013,2978,2944,2914,2891,2874,
-2860,2845,2827,2803,2774,2741,2707,2676,2651,2632,2620,2612,2609,2608,2609,2614,2622,2636,2654,2675,2696,
-2714,2725,2727,2718,2699,2672,2639,2606,2574,2547,2526,2511,2502,2498,2497,2497,2497,2494,2487,2475,2458,
-2436,2409,2379,2346,2313,2281,2250,2221,2194,2168,2145,2123,2103,2086,2072,2060,2051,2044,2037,2030,2021,
-2010,1996,1980,1963,1944,1926,1908,1892,1878,1864,1851,1838,1823,1806,1786,1762,1733,1700,1665,1628,1591,
-1557,1527,1502,1482,1465,1451,1438,1423,1407,1389,1373,1358,1348,1343,1341,1342,1343,1342,1335,1322,1303,
-1280,1254,1228,1204,1181,1159,1138,1115,1091,1064,1035,1003,972,940,908,876,845,815,786,760,735,
-713,694,676,657,635,610,580,546,511,475,443,414,391,372,355,338,318,296,270,241,211,
-182,155,131,109,89,69,49,28,5,-19,-43,-67,-89,-109,-126,-140,-152,-161,-170,-180,-192,
--209,-233,-265,-307,-358,-417,-481,-547,-611,-668,-717,-754,-782,-801,-814,-827,-842,-863,-891,-926,-965,
--1004,-1041,-1072,-1095,-1112,-1126,-1141,-1161,-1189,-1228,-1278,-1335,-1396,-1458,-1517,-1571,-1619,-1663,-1705,-1744,-1782,
--1820,-1855,-1886,-1912,-1933,-1948,-1960,-1970,-1979,-1987,-1996,-2003,-2007,-2007,-2002,-1994,-1984,-1977,-1975,-1983,-2003,
--2036,-2081,-2135,-2196,-2258,-2318,-2374,-2426,-2473,-2519,-2566,-2617,-2673,-2733,-2797,-2861,-2922,-2977,-3022,-3057,-3083,
--3100,-3112,-3121,-3130,-3139,-3150,-3163,-3176,-3189,-3199,-3205,-3207,-3206,-3201,-3195,-3190,-3188,-3193,-3205,-3225,-3251,
--3282,-3313,-3341,-3365,-3382,-3395,-3405,-3416,-3430,-3448,-3468,-3489,-3507,-3519,-3522,-3519,-3511,-3505,-3506,-3518,-3542,
--3578,-3621,-3666,-3708,-3742,-3766,-3782,-3793,-3802,-3815,-3833,-3857,-3886,-3918,-3950,-3982,-4013,-4043,-4074,-4106,-4139,
--4172,-4204,-4234,-4260,-4284,-4305,-4326,-4347,-4368,-4389,-4409,-4425,-4437,-4444,-4447,-4446,-4445,-4445,-4447,-4452,-4459,
--4468,-4478,-4488,-4497,-4506,-4516,-4526,-4535,-4544,-4551,-4557,-4561,-4566,-4571,-4580,-4592,-4609,-4627,-4646,-4662,-4673,
--4677,-4675,-4667,-4655,-4642,-4630,-4620,-4612,-4606,-4602,-4600,-4598,-4596,-4595,-4593,-4589,-4583,-4572,-4557,-4537,-4515,
--4491,-4470,-4452,-4439,-4431,-4428,-4427,-4428,-4428,-4427,-4426,-4425,-4427,-4431,-4439,-4450,-4462,-4474,-4486,-4495,-4501,
--4506,-4510,-4513,-4515,-4517,-4519,-4519,-4518,-4516,-4515,-4516,-4520,-4528,-4540,-4556,-4573,-4592,-4610,-4626,-4642,-4656,
--4670,-4684,-4700,-4716,-4732,-4748,-4762,-4776,-4788,-4801,-4815,-4831,-4850,-4871,-4894,-4917,-4939,-4957,-4972,-4983,-4991,
--5000,-5010,-5022,-5037,-5055,-5073,-5091,-5107,-5122,-5135,-5148,-5163,-5182,-5204,-5228,-5253,-5275,-5292,-5301,-5303,-5297,
--5287,-5275,-5265,-5258,-5257,-5260,-5268,-5278,-5289,-5298,-5305,-5309,-5309,-5306,-5299,-5291,-5280,-5268,-5255,-5243,-5230,
--5219,-5208,-5198,-5189,-5180,-5172,-5166,-5161,-5159,-5158,-5160,-5164,-5168,-5172,-5175,-5177,-5178,-5179,-5180,-5181,-5182,
--5183,-5185,-5186,-5186,-5186,-5186,-5185,-5185,-5184,-5182,-5179,-5175,-5170,-5164,-5158,-5153,-5149,-5146,-5144,-5143,-5142,
--5139,-5135,-5130,-5123,-5116,-5109,-5102,-5096,-5091,-5087,-5084,-5082,-5079,-5077,-5075,-5073,-5070,-5065,-5059,-5052,-5044,
--5035,-5027,-5021,-5015,-5012,-5009,-5006,-5003,-5000,-4995,-4990,-4985,-4980,-4975,-4970,-4964,-4959,-4952,-4945,-4938,-4931,
--4925,-4920,-4916,-4913,-4911,-4908,-4905,-4899,-4892,-4884,-4875,-4865,-4856,-4848,-4840,-4832,-4823,-4814,-4803,-4792,-4779,
--4767,-4754,-4742,-4731,-4721,-4713,-4706,-4701,-4697,-4695,-4694,-4693,-4692,-4690,-4686,-4679,-4671,-4662,-4650,-4638,-4626,
--4613,-4601,-4588,-4574,-4560,-4545,-4528,-4511,-4492,-4474,-4457,-4441,-4427,-4415,-4405,-4396,-4387,-4377,-4366,-4353,-4338,
--4322,-4305,-4288,-4273,-4259,-4247,-4238,-4230,-4225,-4222,-4220,-4220,-4221,-4222,-4224,-4224,-4223,-4219,-4213,-4205,-4196,
--4185,-4175,-4165,-4156,-4148,-4141,-4133,-4125,-4117,-4109,-4101,-4095,-4090,-4087,-4085,-4084,-4084,-4081,-4078,-4071,-4062,
--4050,-4037,-4022,-4007,-3992,-3977,-3963,-3950,-3936,-3922,-3906,-3890,-3872,-3853,-3833,-3811,-3790,-3770,-3749,-3730,-3711,
--3693,-3675,-3656,-3637,-3617,-3597,-3578,-3561,-3544,-3530,-3517,-3506,-3494,-3482,-3470,-3456,-3442,-3427,-3413,-3399,-3388,
--3377,-3368,-3358,-3349,-3338,-3326,-3314,-3302,-3290,-3280,-3272,-3265,-3258,-3251,-3242,-3231,-3218,-3204,-3190,-3176,-3164,
--3153,-3144,-3135,-3127,-3118,-3109,-3099,-3090,-3081,-3072,-3065,-3057,-3048,-3039,-3028,-3015,-3001,-2986,-2971,-2956,-2941,
--2927,-2911,-2895,-2879,-2861,-2844,-2827,-2811,-2796,-2782,-2767,-2752,-2736,-2718,-2700,-2682,-2665,-2649,-2635,-2622,-2611,
--2599,-2588,-2577,-2566,-2555,-2546,-2537,-2529,-2520,-2509,-2497,-2483,-2468,-2453,-2438,-2425,-2414,-2405,-2396,-2387,-2378,
--2368,-2358,-2349,-2340,-2332,-2324,-2315,-2305,-2292,-2276,-2260,-2245,-2233,-2224,-2218,-2213,-2206,-2193,-2173,-2147,-2116,
--2085,-2058,-2037,-2023,-2012,-2000,-1981,-1951,-1910,-1860,-1808,-1762,-1729,-1714,-1715,-1728,-1743,-1749,-1739,-1708,-1658,
--1597,-1534,-1480,-1444,-1429,-1433,-1449,-1469,-1485,-1490,-1481,-1461,-1433,-1402,-1372,-1347,-1326,-1307,-1289,-1269,-1245,
--1219,-1192,-1165,-1141,-1120,-1101,-1083,-1066,-1047,-1026,-1005,-982,-960,-939,-918,-897,-876,-852,-825,-796,-764,
--730,-697,-665,-634,-606,-580,-556,-533,-511,-488,-463,-437,-408,-376,-342,-305,-267,-228,-189,-151,-114,
--79,-46,-15,14,41,68,94,120,147,175,206,237,270,303,335,367,398,429,461,494,531,
-573,619,670,726,786,848,911,973,1033,1087,1137,1180,1218,1251,1282,1311,1339,1367,1394,1417,1436,
-1450,1459,1466,1475,1488,1511,1544,1586,1635,1684,1728,1760,1779,1784,1777,1762,1746,1732,1723,1720,1722,
-1726,1731,1733,1732,1728,1722,1715,1709,1706,1707,1713,1726,1745,1770,1798,1824,1843,1848,1835,1802,1751,
-1687,1618,1553,1502,1469,1455,1456,1466,1475,1477,1468,1446,1415,1379,1344,1314,1291,1276,1267,1263,1260,
-1260,1263,1270,1283,1302,1326,1352,1377,1397,1410,1416,1415,1410,1401,1393,1384,1377,1371,1365,1360,1356,
-1354,1354,1357,1362,1369,1375,1381,1384,1385,1384,1382,1380,1379,1380,1382,1384,1385,1386,1385,1384,1382,
-1379,1375,1372,1367,1361,1355,1349,1342,1336,1330,1323,1314,1303,1288,1270,1251,1231,1213,1199,1191,1188,
-1188,1190,1190,1187,1180,1169,1155,1140,1126,1115,1106,1100,1095,1090,1084,1077,1068,1060,1051,1044,1039,
-1034,1030,1026,1021,1016,1009,1002,995,989,985,981,979,979,979,979,979,977,975,971,966,961,
-955,949,945,942,939,937,934,930,924,917,908,899,891,883,876,869,863,856,849,841,834,
-827,823,820,819,819,820,821,822,823,824,826,828,830,833,833,833,830,826,822,819,817,
-818,821,826,831,836,839,842,844,846,848,853,858,865,871,878,885,892,900,909,920,933,
-948,963,977,990,1000,1009,1015,1021,1027,1034,1041,1050,1060,1071,1081,1092,1102,1112,1122,1132,1142,
-1153,1166,1182,1202,1226,1253,1285,1319,1356,1332,1368,1405,1440,1473,1504,1533,1558,1579,1596,1607,1614,
-1615,1612,1605,1598,1591,1585,1582,1580,1580,1580,1580,1580,1580,1580,1583,1588,1597,1608,1621,1635,1648,
-1659,1667,1674,1680,1687,1696,1707,1720,1735,1751,1767,1782,1797,1811,1825,1839,1853,1869,1883,1897,1908,
-1917,1923,1926,1926,1925,1922,1917,1910,1900,1887,1871,1853,1835,1819,1806,1798,1795,1797,1802,1809,1814,
-1818,1820,1820,1819,1819,1819,1821,1824,1827,1830,1832,1833,1833,1834,1837,1840,1845,1849,1853,1855,1855,
-1854,1852,1852,1853,1857,1862,1868,1873,1877,1879,1882,1885,1891,1901,1914,1929,1945,1960,1973,1985,1996,
-2008,2021,2036,2050,2061,2063,2057,2040,2016,1991,1973,1967,1980,2012,2062,2121,2183,2237,2279,2304,2315,
-2315,2312,2311,2316,2329,2348,2369,2390,2406,2417,2422,2424,2426,2429,2435,2444,2455,2467,2478,2488,2496,
-2504,2513,2523,2535,2548,2564,2580,2597,2614,2631,2648,2665,2682,2697,2711,2722,2729,2735,2739,2744,2750,
-2760,2772,2787,2805,2825,2847,2871,2897,2925,2956,2988,3018,3045,3063,3071,3069,3057,3038,3018,3000,2990,
-2988,2994,3006,3022,3038,3053,3067,3083,3104,3132,3169,3212,3258,3300,3332,3349,3349,3334,3308,3276,3244,
-3217,3197,3181,3167,3150,3128,3098,3063,3024,2986,2952,2923,2900,2879,2858,2834,2805,2771,2734,2698,2665,
-2639,2619,2606,2598,2593,2589,2587,2587,2589,2597,2609,2626,2646,2664,2679,2685,2682,2669,2647,2618,2585,
-2552,2521,2495,2475,2461,2453,2451,2451,2452,2451,2447,2437,2422,2400,2373,2343,2311,2280,2250,2223,2198,
-2175,2153,2132,2112,2093,2076,2061,2050,2040,2031,2021,2010,1996,1979,1960,1939,1918,1899,1882,1868,1854,
-1841,1827,1810,1790,1767,1740,1709,1676,1640,1603,1567,1533,1504,1480,1464,1455,1452,1455,1458,1461,1460,
-1455,1444,1431,1416,1402,1391,1382,1374,1366,1355,1339,1317,1290,1260,1230,1201,1177,1157,1141,1126,1112,
-1095,1074,1048,1018,985,950,914,880,848,818,793,772,754,739,726,711,693,670,639,602,560,
-514,467,423,382,346,314,284,254,223,191,160,130,104,82,65,52,41,28,13,-7,-31,
--58,-86,-110,-131,-146,-156,-162,-167,-172,-179,-189,-202,-218,-236,-257,-283,-315,-355,-403,-460,-522,
--587,-649,-704,-749,-782,-806,-821,-835,-850,-872,-901,-938,-979,-1019,-1056,-1084,-1104,-1116,-1124,-1132,-1145,
--1167,-1199,-1240,-1288,-1339,-1389,-1437,-1481,-1523,-1563,-1605,-1649,-1695,-1743,-1790,-1834,-1872,-1905,-1932,-1954,-1974,
--1993,-2012,-2029,-2044,-2054,-2057,-2053,-2041,-2025,-2010,-1999,-1998,-2010,-2036,-2076,-2126,-2180,-2235,-2286,-2330,-2367,
--2400,-2432,-2467,-2509,-2560,-2619,-2684,-2750,-2813,-2869,-2913,-2945,-2966,-2979,-2987,-2995,-3006,-3020,-3038,-3058,-3079,
--3098,-3112,-3120,-3122,-3120,-3115,-3111,-3110,-3115,-3129,-3152,-3183,-3219,-3256,-3290,-3320,-3342,-3356,-3366,-3375,-3386,
--3404,-3427,-3456,-3487,-3515,-3536,-3548,-3550,-3547,-3542,-3541,-3550,-3569,-3600,-3637,-3675,-3710,-3736,-3753,-3761,-3765,
--3768,-3775,-3789,-3810,-3838,-3870,-3903,-3935,-3965,-3994,-4022,-4051,-4081,-4110,-4139,-4167,-4191,-4212,-4230,-4247,-4263,
--4280,-4298,-4316,-4334,-4350,-4364,-4376,-4386,-4395,-4404,-4415,-4427,-4441,-4455,-4470,-4485,-4499,-4514,-4528,-4543,-4556,
--4567,-4576,-4583,-4587,-4591,-4595,-4601,-4610,-4623,-4639,-4655,-4669,-4679,-4684,-4682,-4675,-4665,-4652,-4638,-4626,-4616,
--4608,-4603,-4601,-4602,-4608,-4617,-4628,-4640,-4650,-4654,-4651,-4639,-4619,-4594,-4566,-4539,-4517,-4502,-4494,-4492,-4493,
--4497,-4500,-4501,-4501,-4501,-4501,-4505,-4511,-4521,-4533,-4546,-4558,-4569,-4578,-4585,-4591,-4595,-4597,-4599,-4600,-4600,
--4600,-4601,-4602,-4606,-4612,-4621,-4634,-4648,-4662,-4677,-4690,-4702,-4713,-4724,-4736,-4749,-4763,-4778,-4794,-4809,-4823,
--4836,-4849,-4861,-4876,-4893,-4913,-4937,-4962,-4987,-5010,-5030,-5046,-5058,-5066,-5073,-5080,-5089,-5099,-5113,-5128,-5144,
--5161,-5179,-5198,-5218,-5239,-5262,-5286,-5310,-5333,-5352,-5365,-5373,-5375,-5371,-5364,-5354,-5344,-5336,-5330,-5329,-5332,
--5339,-5349,-5362,-5374,-5386,-5395,-5399,-5398,-5392,-5381,-5366,-5349,-5329,-5310,-5290,-5271,-5253,-5237,-5222,-5210,-5201,
--5195,-5193,-5194,-5198,-5203,-5208,-5213,-5218,-5221,-5224,-5227,-5230,-5233,-5236,-5240,-5242,-5244,-5245,-5245,-5245,-5244,
--5243,-5242,-5240,-5237,-5233,-5229,-5224,-5218,-5213,-5209,-5206,-5203,-5201,-5199,-5196,-5193,-5188,-5182,-5176,-5169,-5162,
--5155,-5149,-5144,-5141,-5139,-5139,-5139,-5139,-5138,-5135,-5130,-5123,-5114,-5105,-5096,-5089,-5083,-5080,-5078,-5076,-5074,
--5071,-5067,-5062,-5057,-5052,-5049,-5045,-5042,-5038,-5033,-5026,-5017,-5007,-4996,-4985,-4976,-4968,-4963,-4958,-4954,-4950,
--4945,-4939,-4933,-4926,-4920,-4914,-4909,-4903,-4897,-4890,-4881,-4871,-4860,-4848,-4836,-4823,-4812,-4801,-4791,-4782,-4774,
--4766,-4759,-4753,-4748,-4743,-4739,-4735,-4731,-4725,-4717,-4707,-4696,-4683,-4670,-4656,-4643,-4630,-4616,-4603,-4589,-4573,
--4556,-4537,-4519,-4501,-4485,-4471,-4460,-4450,-4441,-4433,-4423,-4411,-4398,-4383,-4367,-4351,-4335,-4321,-4308,-4296,-4284,
--4274,-4265,-4257,-4251,-4247,-4246,-4247,-4249,-4251,-4253,-4252,-4249,-4243,-4236,-4227,-4218,-4210,-4202,-4195,-4188,-4180,
--4172,-4162,-4152,-4141,-4131,-4122,-4116,-4111,-4108,-4106,-4103,-4100,-4095,-4087,-4077,-4066,-4052,-4037,-4022,-4006,-3990,
--3973,-3957,-3939,-3921,-3903,-3883,-3862,-3841,-3820,-3799,-3778,-3758,-3739,-3720,-3702,-3683,-3665,-3646,-3628,-3610,-3593,
--3577,-3563,-3550,-3537,-3525,-3512,-3500,-3487,-3474,-3462,-3450,-3438,-3427,-3416,-3405,-3394,-3381,-3369,-3356,-3344,-3333,
--3324,-3317,-3310,-3303,-3296,-3286,-3275,-3261,-3247,-3232,-3218,-3206,-3195,-3186,-3178,-3171,-3162,-3154,-3144,-3135,-3125,
--3116,-3107,-3098,-3088,-3077,-3064,-3050,-3035,-3019,-3004,-2990,-2976,-2962,-2948,-2933,-2915,-2897,-2878,-2859,-2841,-2825,
--2810,-2796,-2781,-2766,-2749,-2731,-2712,-2694,-2676,-2661,-2648,-2637,-2626,-2616,-2605,-2594,-2583,-2572,-2562,-2553,-2544,
--2535,-2526,-2515,-2503,-2489,-2476,-2464,-2453,-2444,-2436,-2428,-2419,-2410,-2399,-2387,-2375,-2364,-2355,-2346,-2337,-2326,
--2314,-2299,-2284,-2269,-2256,-2246,-2238,-2232,-2223,-2209,-2190,-2165,-2135,-2105,-2077,-2055,-2038,-2026,-2013,-1995,-1970,
--1937,-1898,-1858,-1824,-1801,-1793,-1796,-1806,-1813,-1809,-1786,-1742,-1681,-1609,-1539,-1481,-1444,-1429,-1436,-1457,-1483,
--1505,-1516,-1512,-1494,-1467,-1434,-1403,-1374,-1351,-1331,-1314,-1295,-1275,-1253,-1228,-1204,-1180,-1158,-1138,-1119,-1099,
--1079,-1057,-1035,-1012,-990,-969,-949,-929,-909,-887,-863,-836,-806,-774,-741,-708,-677,-648,-620,-595,-571,
--548,-525,-501,-475,-448,-418,-386,-352,-317,-282,-248,-213,-180,-146,-113,-79,-45,-11,22,56,89,
-120,150,179,208,236,265,296,329,365,404,447,492,541,592,646,702,759,817,874,930,981,
-1029,1072,1110,1145,1177,1208,1239,1272,1304,1336,1365,1389,1406,1416,1422,1427,1436,1452,1479,1518,1566,
-1619,1669,1712,1742,1755,1754,1740,1719,1695,1672,1653,1639,1629,1623,1619,1616,1613,1611,1611,1612,1615,
-1621,1630,1643,1661,1684,1710,1738,1763,1780,1784,1770,1737,1687,1627,1565,1509,1467,1442,1435,1440,1450,
-1458,1456,1441,1415,1380,1343,1308,1280,1260,1247,1238,1231,1223,1215,1208,1204,1207,1217,1235,1258,1283,
-1307,1326,1340,1348,1351,1351,1350,1347,1343,1338,1330,1321,1311,1302,1296,1293,1294,1299,1306,1313,1318,
-1321,1322,1322,1320,1320,1320,1322,1326,1329,1333,1335,1335,1332,1328,1322,1314,1304,1293,1282,1272,1263,
-1257,1253,1251,1249,1245,1238,1227,1213,1196,1178,1161,1148,1139,1133,1130,1127,1124,1118,1110,1099,1087,
-1075,1064,1054,1046,1038,1030,1021,1011,1001,991,983,976,972,969,968,966,964,961,956,950,944,
-938,934,931,930,930,931,931,932,931,929,926,922,917,912,907,902,898,893,889,883,878,
-872,866,859,853,846,840,833,825,816,807,798,789,782,777,774,773,774,776,778,780,783,
-785,788,791,795,799,803,805,805,803,800,797,795,794,796,800,805,810,814,816,818,818,
-819,820,823,828,834,841,849,858,868,879,891,905,919,934,949,962,972,981,987,993,998,
-1005,1012,1022,1032,1044,1055,1066,1077,1087,1096,1105,1115,1124,1135,1148,1164,1182,1205,1232,1262,1296,
-1332,1315,1350,1384,1416,1444,1469,1490,1507,1520,1529,1535,1537,1537,1536,1534,1532,1532,1534,1537,1540,
-1544,1547,1548,1548,1548,1549,1552,1559,1570,1583,1598,1613,1626,1635,1642,1646,1650,1655,1663,1675,1691,
-1710,1731,1753,1773,1793,1812,1830,1848,1866,1882,1896,1906,1912,1912,1908,1900,1891,1881,1873,1867,1861,
-1855,1847,1836,1821,1803,1785,1768,1755,1747,1745,1748,1755,1764,1773,1780,1785,1789,1790,1791,1792,1794,
-1795,1797,1798,1798,1799,1799,1799,1800,1800,1800,1799,1798,1798,1799,1801,1805,1811,1818,1825,1832,1838,
-1842,1844,1847,1852,1859,1868,1880,1894,1908,1923,1936,1950,1964,1979,1994,2008,2018,2022,2017,2003,1983,
-1962,1947,1943,1958,1991,2042,2104,2167,2224,2267,2293,2301,2297,2288,2281,2281,2291,2309,2332,2354,2372,
-2382,2385,2381,2375,2371,2371,2376,2386,2399,2413,2426,2437,2447,2457,2466,2477,2490,2503,2516,2529,2542,
-2555,2571,2589,2609,2633,2657,2679,2698,2713,2722,2728,2732,2736,2743,2755,2771,2792,2815,2841,2867,2894,
-2922,2950,2976,3000,3019,3031,3036,3033,3025,3016,3010,3013,3025,3049,3080,3115,3149,3177,3197,3211,3224,
-3240,3264,3299,3345,3397,3450,3494,3522,3530,3517,3486,3443,3394,3348,3306,3272,3243,3217,3190,3161,3128,
-3093,3057,3022,2990,2961,2933,2905,2874,2840,2803,2764,2727,2694,2666,2645,2629,2617,2607,2597,2587,2578,
-2571,2566,2566,2571,2578,2588,2597,2603,2603,2597,2585,2566,2543,2517,2490,2465,2443,2425,2414,2408,2407,
-2409,2411,2410,2403,2390,2369,2342,2311,2278,2247,2218,2194,2173,2155,2138,2122,2104,2087,2068,2051,2035,
-2019,2005,1991,1976,1960,1943,1925,1906,1887,1870,1853,1836,1817,1796,1772,1743,1712,1679,1645,1612,1581,
-1554,1529,1507,1489,1476,1468,1466,1470,1480,1494,1509,1522,1531,1533,1529,1518,1503,1485,1467,1450,1433,
-1414,1393,1366,1335,1300,1263,1227,1196,1171,1153,1142,1134,1127,1116,1100,1077,1046,1009,969,927,887,
-851,820,794,774,758,743,728,710,688,659,623,581,534,485,436,387,342,298,257,216,177,
-139,103,73,49,33,24,19,15,9,-3,-25,-56,-93,-131,-167,-194,-210,-214,-209,-198,-185,
--176,-173,-178,-188,-204,-223,-244,-267,-294,-327,-368,-419,-478,-543,-610,-674,-732,-781,-820,-853,-881,
--910,-943,-982,-1026,-1072,-1117,-1158,-1190,-1214,-1231,-1242,-1251,-1263,-1279,-1300,-1326,-1354,-1384,-1412,-1438,-1463,
--1490,-1519,-1552,-1591,-1634,-1679,-1724,-1767,-1807,-1842,-1874,-1904,-1936,-1969,-2004,-2039,-2073,-2101,-2121,-2132,-2133,
--2128,-2121,-2116,-2118,-2130,-2154,-2187,-2227,-2269,-2309,-2342,-2368,-2387,-2403,-2419,-2440,-2469,-2509,-2558,-2613,-2670,
--2723,-2769,-2804,-2828,-2844,-2854,-2863,-2873,-2888,-2908,-2933,-2959,-2986,-3009,-3029,-3043,-3052,-3059,-3066,-3074,-3088,
--3107,-3134,-3168,-3207,-3250,-3292,-3331,-3364,-3390,-3409,-3422,-3434,-3447,-3464,-3487,-3514,-3544,-3573,-3597,-3615,-3625,
--3630,-3631,-3634,-3642,-3656,-3676,-3700,-3725,-3748,-3765,-3776,-3782,-3786,-3792,-3802,-3818,-3840,-3868,-3899,-3930,-3960,
--3989,-4016,-4042,-4068,-4094,-4119,-4142,-4162,-4178,-4189,-4196,-4200,-4203,-4206,-4211,-4219,-4229,-4242,-4257,-4273,-4291,
--4311,-4332,-4356,-4380,-4404,-4427,-4450,-4470,-4489,-4506,-4522,-4537,-4550,-4561,-4569,-4575,-4577,-4578,-4579,-4582,-4587,
--4595,-4606,-4618,-4629,-4637,-4640,-4639,-4633,-4623,-4611,-4598,-4587,-4577,-4570,-4567,-4569,-4577,-4591,-4614,-4642,-4674,
--4706,-4733,-4751,-4757,-4750,-4731,-4704,-4674,-4645,-4621,-4606,-4599,-4599,-4602,-4605,-4607,-4605,-4600,-4594,-4588,-4586,
--4587,-4594,-4604,-4616,-4630,-4642,-4653,-4661,-4668,-4672,-4676,-4678,-4680,-4681,-4682,-4683,-4685,-4688,-4694,-4702,-4712,
--4724,-4737,-4749,-4760,-4770,-4779,-4788,-4797,-4807,-4818,-4831,-4846,-4861,-4876,-4891,-4906,-4922,-4939,-4958,-4980,-5003,
--5027,-5051,-5074,-5093,-5108,-5120,-5128,-5134,-5140,-5146,-5155,-5166,-5181,-5197,-5215,-5235,-5255,-5275,-5295,-5316,-5336,
--5356,-5375,-5392,-5407,-5417,-5424,-5425,-5423,-5416,-5408,-5400,-5394,-5391,-5394,-5403,-5416,-5432,-5449,-5464,-5476,-5482,
--5481,-5476,-5465,-5450,-5433,-5415,-5396,-5376,-5355,-5335,-5315,-5297,-5282,-5270,-5262,-5259,-5259,-5262,-5267,-5272,-5277,
--5282,-5285,-5289,-5292,-5295,-5298,-5301,-5303,-5304,-5304,-5304,-5303,-5301,-5300,-5299,-5299,-5298,-5296,-5293,-5289,-5284,
--5277,-5271,-5264,-5258,-5252,-5247,-5244,-5241,-5238,-5235,-5232,-5228,-5222,-5216,-5209,-5203,-5198,-5194,-5192,-5192,-5193,
--5194,-5194,-5192,-5187,-5181,-5172,-5164,-5156,-5149,-5145,-5142,-5140,-5138,-5136,-5133,-5130,-5126,-5123,-5120,-5118,-5115,
--5112,-5108,-5101,-5091,-5079,-5066,-5052,-5039,-5028,-5019,-5011,-5006,-5001,-4997,-4992,-4987,-4982,-4976,-4971,-4966,-4960,
--4955,-4948,-4942,-4935,-4927,-4920,-4913,-4906,-4899,-4892,-4884,-4875,-4864,-4852,-4839,-4827,-4815,-4805,-4796,-4789,-4783,
--4777,-4770,-4761,-4749,-4736,-4722,-4708,-4694,-4682,-4671,-4660,-4648,-4635,-4620,-4603,-4584,-4565,-4547,-4531,-4516,-4505,
--4494,-4485,-4475,-4465,-4453,-4441,-4427,-4414,-4401,-4388,-4376,-4363,-4349,-4334,-4319,-4305,-4292,-4283,-4277,-4276,-4278,
--4283,-4287,-4290,-4291,-4288,-4282,-4274,-4265,-4255,-4247,-4239,-4232,-4225,-4218,-4209,-4199,-4187,-4175,-4164,-4153,-4145,
--4138,-4133,-4129,-4126,-4122,-4117,-4110,-4101,-4090,-4076,-4061,-4045,-4027,-4009,-3990,-3970,-3950,-3929,-3908,-3887,-3866,
--3844,-3823,-3802,-3781,-3761,-3742,-3723,-3704,-3686,-3669,-3652,-3636,-3621,-3607,-3593,-3580,-3567,-3554,-3541,-3528,-3515,
--3503,-3490,-3479,-3467,-3456,-3445,-3434,-3422,-3410,-3397,-3385,-3375,-3365,-3356,-3348,-3340,-3332,-3322,-3310,-3298,-3284,
--3271,-3259,-3249,-3240,-3232,-3225,-3217,-3208,-3198,-3187,-3176,-3165,-3155,-3146,-3137,-3128,-3118,-3105,-3091,-3075,-3059,
--3043,-3028,-3015,-3002,-2988,-2974,-2958,-2940,-2920,-2900,-2880,-2861,-2844,-2828,-2814,-2798,-2782,-2764,-2746,-2727,-2709,
--2694,-2681,-2670,-2661,-2653,-2644,-2634,-2622,-2610,-2598,-2587,-2577,-2568,-2560,-2550,-2540,-2529,-2517,-2505,-2495,-2486,
--2479,-2472,-2465,-2457,-2446,-2433,-2419,-2404,-2391,-2379,-2370,-2361,-2352,-2342,-2329,-2315,-2301,-2286,-2273,-2262,-2252,
--2241,-2226,-2207,-2183,-2155,-2126,-2097,-2073,-2053,-2037,-2023,-2008,-1990,-1968,-1944,-1920,-1900,-1887,-1882,-1884,-1888,
--1886,-1872,-1841,-1793,-1732,-1663,-1597,-1542,-1506,-1490,-1492,-1507,-1526,-1541,-1547,-1540,-1521,-1493,-1460,-1428,-1399,
--1375,-1355,-1338,-1321,-1304,-1285,-1264,-1243,-1222,-1202,-1182,-1162,-1143,-1122,-1099,-1076,-1052,-1027,-1003,-980,-957,
--933,-909,-884,-858,-830,-801,-773,-744,-716,-689,-663,-638,-613,-587,-562,-536,-509,-480,-451,-420,-390,
--359,-329,-300,-272,-244,-215,-183,-149,-111,-71,-29,12,51,87,120,148,175,201,229,261,300,
-345,396,452,512,573,635,694,752,807,859,907,952,993,1029,1061,1089,1115,1140,1166,1193,1223,
-1254,1285,1312,1335,1352,1364,1373,1383,1397,1420,1452,1492,1537,1582,1622,1652,1669,1673,1665,1650,1630,
-1609,1591,1575,1561,1549,1537,1526,1515,1508,1505,1507,1515,1527,1543,1562,1582,1604,1628,1652,1676,1697,
-1710,1713,1702,1674,1632,1581,1526,1476,1435,1407,1393,1390,1390,1389,1380,1363,1337,1307,1275,1247,1225,
-1210,1200,1193,1186,1177,1167,1157,1150,1149,1156,1170,1189,1211,1233,1251,1266,1276,1282,1287,1290,1291,
-1292,1290,1285,1277,1267,1257,1249,1244,1242,1244,1248,1252,1255,1256,1254,1249,1244,1240,1237,1237,1240,
-1244,1249,1254,1257,1258,1256,1250,1243,1232,1220,1207,1195,1185,1178,1174,1173,1174,1176,1176,1173,1165,
-1154,1140,1124,1109,1095,1085,1076,1070,1064,1058,1051,1043,1034,1025,1016,1007,999,991,983,974,964,
-955,945,937,931,927,924,923,921,919,917,913,908,903,899,894,891,889,888,887,886,885,
-884,883,881,879,876,872,868,862,855,848,840,833,826,820,815,811,807,802,797,790,782,
-772,762,753,745,739,737,737,739,742,746,749,752,754,757,760,764,769,774,779,782,784,
-785,784,783,782,782,784,788,792,796,799,801,802,803,803,805,809,814,820,827,836,845,
-855,866,878,892,906,919,932,943,952,960,966,972,979,987,996,1007,1019,1031,1043,1054,1065,
-1075,1085,1095,1105,1116,1127,1140,1155,1173,1194,1219,1249,1281,1315,1289,1319,1347,1373,1396,1415,1430,
-1443,1453,1461,1467,1471,1473,1475,1477,1479,1482,1487,1493,1499,1505,1510,1514,1517,1520,1523,1527,1534,
-1544,1555,1567,1577,1586,1592,1596,1599,1603,1610,1621,1636,1656,1679,1702,1726,1748,1768,1787,1806,1824,
-1842,1858,1870,1877,1878,1871,1858,1841,1822,1804,1789,1779,1772,1767,1762,1756,1746,1733,1718,1704,1694,
-1688,1688,1694,1705,1718,1730,1741,1748,1752,1753,1753,1752,1751,1752,1754,1756,1758,1759,1758,1756,1752,
-1747,1741,1736,1733,1732,1735,1741,1749,1760,1772,1782,1791,1798,1803,1807,1810,1814,1821,1829,1840,1852,
-1866,1882,1898,1917,1937,1957,1975,1989,1994,1990,1975,1951,1925,1903,1892,1900,1929,1979,2045,2117,2186,
-2243,2281,2298,2299,2289,2276,2267,2267,2278,2296,2317,2336,2348,2351,2346,2338,2328,2323,2324,2330,2342,
-2356,2370,2382,2393,2402,2411,2423,2436,2452,2468,2484,2499,2512,2525,2540,2558,2581,2607,2634,2661,2685,
-2703,2714,2721,2724,2728,2735,2748,2768,2793,2822,2854,2885,2916,2944,2968,2990,3006,3018,3023,3024,3021,
-3017,3018,3029,3051,3088,3138,3197,3257,3313,3359,3392,3413,3426,3439,3457,3485,3525,3573,3623,3666,3695,
-3703,3688,3651,3598,3537,3474,3416,3366,3325,3291,3261,3233,3203,3171,3138,3103,3069,3036,3004,2972,2939,
-2905,2871,2836,2801,2769,2739,2712,2688,2666,2646,2625,2605,2584,2565,2548,2534,2523,2516,2512,2510,2510,
-2510,2509,2507,2500,2490,2475,2455,2432,2409,2387,2371,2360,2357,2359,2365,2370,2371,2365,2350,2326,2296,
-2264,2232,2204,2182,2166,2155,2146,2137,2126,2111,2092,2071,2047,2023,1999,1976,1954,1933,1913,1894,1876,
-1858,1840,1819,1796,1768,1735,1699,1660,1621,1585,1555,1533,1518,1509,1506,1506,1507,1509,1511,1515,1521,
-1530,1542,1555,1568,1576,1578,1574,1563,1546,1526,1505,1484,1463,1443,1420,1394,1364,1331,1295,1261,1230,
-1205,1188,1177,1170,1164,1154,1137,1111,1077,1035,989,942,898,858,824,796,773,753,734,712,686,
-656,620,579,535,489,442,396,351,307,263,219,175,132,93,59,32,14,3,0,-3,-8,
--22,-45,-81,-125,-174,-221,-260,-284,-291,-281,-258,-227,-195,-168,-150,-144,-148,-160,-178,-200,-225,
--252,-285,-324,-371,-427,-490,-557,-625,-690,-751,-806,-857,-905,-952,-1002,-1053,-1106,-1160,-1211,-1257,-1297,
--1331,-1358,-1380,-1400,-1418,-1436,-1452,-1467,-1480,-1491,-1498,-1505,-1513,-1524,-1541,-1563,-1591,-1623,-1658,-1693,-1727,
--1759,-1790,-1822,-1856,-1894,-1938,-1985,-2034,-2082,-2125,-2161,-2189,-2208,-2220,-2228,-2238,-2251,-2270,-2296,-2327,-2361,
--2394,-2423,-2445,-2460,-2469,-2475,-2481,-2492,-2510,-2535,-2568,-2605,-2644,-2680,-2711,-2736,-2755,-2770,-2785,-2800,-2820,
--2843,-2871,-2900,-2929,-2955,-2979,-2999,-3015,-3030,-3045,-3061,-3080,-3103,-3130,-3164,-3202,-3245,-3291,-3340,-3388,-3434,
--3475,-3510,-3538,-3560,-3577,-3590,-3602,-3614,-3627,-3640,-3654,-3667,-3679,-3690,-3701,-3712,-3725,-3740,-3758,-3776,-3794,
--3810,-3824,-3836,-3846,-3856,-3867,-3881,-3897,-3917,-3938,-3960,-3984,-4007,-4031,-4056,-4082,-4108,-4135,-4159,-4180,-4196,
--4206,-4210,-4209,-4203,-4196,-4189,-4183,-4179,-4179,-4183,-4191,-4203,-4221,-4244,-4271,-4301,-4334,-4366,-4397,-4424,-4447,
--4466,-4482,-4496,-4507,-4517,-4525,-4530,-4534,-4535,-4535,-4535,-4537,-4541,-4548,-4558,-4568,-4578,-4584,-4586,-4583,-4576,
--4567,-4555,-4544,-4535,-4528,-4524,-4525,-4531,-4545,-4567,-4599,-4640,-4687,-4738,-4785,-4825,-4851,-4862,-4856,-4836,-4808,
--4777,-4748,-4727,-4715,-4711,-4712,-4716,-4719,-4718,-4712,-4702,-4691,-4681,-4675,-4673,-4677,-4685,-4696,-4708,-4720,-4730,
--4739,-4747,-4753,-4758,-4762,-4764,-4763,-4761,-4757,-4753,-4750,-4750,-4754,-4763,-4776,-4792,-4809,-4826,-4841,-4853,-4863,
--4871,-4879,-4887,-4897,-4909,-4924,-4939,-4955,-4972,-4988,-5005,-5022,-5041,-5061,-5083,-5105,-5127,-5147,-5165,-5180,-5191,
--5200,-5208,-5215,-5223,-5233,-5246,-5260,-5275,-5291,-5307,-5322,-5338,-5354,-5371,-5388,-5406,-5425,-5442,-5457,-5468,-5474,
--5475,-5473,-5469,-5464,-5461,-5462,-5468,-5477,-5490,-5503,-5516,-5527,-5534,-5537,-5537,-5535,-5530,-5524,-5517,-5507,-5495,
--5480,-5462,-5441,-5419,-5397,-5377,-5361,-5350,-5343,-5340,-5340,-5343,-5346,-5350,-5353,-5356,-5359,-5362,-5365,-5367,-5369,
--5370,-5369,-5368,-5367,-5364,-5362,-5360,-5358,-5357,-5354,-5352,-5348,-5343,-5337,-5329,-5321,-5313,-5306,-5299,-5294,-5290,
--5288,-5286,-5285,-5283,-5280,-5275,-5269,-5262,-5254,-5248,-5243,-5241,-5241,-5242,-5244,-5246,-5245,-5242,-5237,-5230,-5222,
--5214,-5206,-5200,-5196,-5192,-5189,-5187,-5184,-5182,-5179,-5177,-5175,-5174,-5171,-5168,-5163,-5155,-5146,-5135,-5122,-5110,
--5098,-5088,-5079,-5072,-5066,-5060,-5054,-5048,-5041,-5034,-5026,-5019,-5011,-5004,-4997,-4990,-4984,-4979,-4975,-4972,-4969,
--4967,-4964,-4959,-4952,-4943,-4932,-4919,-4905,-4892,-4880,-4869,-4861,-4853,-4845,-4836,-4825,-4812,-4798,-4783,-4768,-4754,
--4742,-4731,-4722,-4711,-4700,-4686,-4670,-4651,-4631,-4612,-4593,-4576,-4562,-4549,-4538,-4527,-4516,-4504,-4493,-4481,-4469,
--4459,-4448,-4437,-4424,-4410,-4395,-4377,-4360,-4345,-4333,-4325,-4322,-4323,-4327,-4333,-4337,-4339,-4337,-4332,-4323,-4312,
--4300,-4289,-4280,-4272,-4265,-4258,-4251,-4244,-4235,-4225,-4214,-4204,-4194,-4184,-4176,-4168,-4161,-4154,-4147,-4138,-4129,
--4118,-4105,-4091,-4075,-4057,-4038,-4018,-3997,-3976,-3954,-3932,-3910,-3888,-3866,-3844,-3823,-3802,-3781,-3761,-3741,-3722,
--3704,-3687,-3671,-3657,-3643,-3631,-3618,-3607,-3594,-3582,-3569,-3555,-3542,-3528,-3515,-3503,-3491,-3480,-3470,-3459,-3449,
--3439,-3429,-3419,-3410,-3400,-3391,-3382,-3372,-3361,-3349,-3336,-3324,-3312,-3302,-3293,-3286,-3280,-3273,-3265,-3256,-3245,
--3232,-3219,-3206,-3195,-3185,-3176,-3168,-3160,-3150,-3137,-3123,-3107,-3090,-3074,-3058,-3044,-3030,-3015,-3000,-2983,-2964,
--2944,-2924,-2904,-2887,-2870,-2855,-2839,-2824,-2806,-2788,-2769,-2751,-2735,-2722,-2711,-2702,-2694,-2686,-2676,-2664,-2651,
--2638,-2625,-2614,-2605,-2597,-2590,-2581,-2572,-2561,-2548,-2536,-2525,-2516,-2509,-2503,-2496,-2489,-2479,-2466,-2452,-2437,
--2422,-2410,-2400,-2391,-2383,-2374,-2363,-2349,-2333,-2317,-2301,-2286,-2272,-2258,-2243,-2224,-2202,-2175,-2147,-2118,-2091,
--2068,-2049,-2034,-2021,-2008,-1995,-1980,-1966,-1954,-1945,-1939,-1937,-1934,-1926,-1910,-1883,-1844,-1795,-1741,-1687,-1641,
--1607,-1585,-1575,-1574,-1576,-1576,-1570,-1556,-1535,-1508,-1479,-1451,-1425,-1403,-1383,-1366,-1349,-1332,-1313,-1294,-1273,
--1253,-1233,-1213,-1193,-1173,-1151,-1129,-1106,-1082,-1057,-1032,-1006,-980,-952,-925,-898,-870,-844,-818,-794,-770,
--747,-725,-702,-678,-653,-627,-600,-572,-543,-512,-481,-449,-417,-386,-356,-327,-301,-276,-250,-223,-193,
--160,-123,-84,-43,-4,33,68,100,131,164,200,243,294,352,416,483,552,619,681,739,791,
-838,881,920,956,988,1017,1043,1066,1086,1106,1125,1146,1168,1191,1215,1236,1256,1272,1288,1303,1322,
-1347,1378,1415,1456,1496,1531,1556,1570,1572,1564,1550,1534,1520,1509,1502,1496,1490,1481,1467,1451,1434,
-1420,1412,1412,1422,1440,1464,1491,1518,1544,1567,1588,1606,1620,1627,1627,1615,1591,1555,1511,1462,1413,
-1370,1337,1313,1297,1287,1278,1266,1251,1231,1209,1188,1169,1155,1145,1139,1133,1127,1119,1111,1103,1099,
-1099,1106,1118,1134,1151,1167,1180,1190,1197,1201,1206,1211,1216,1221,1225,1226,1224,1220,1214,1208,1204,
-1201,1200,1199,1199,1197,1192,1185,1176,1166,1158,1152,1148,1148,1150,1153,1157,1161,1163,1164,1163,1160,
-1154,1146,1137,1126,1116,1108,1102,1099,1098,1100,1101,1101,1099,1093,1085,1073,1061,1049,1037,1027,1019,
-1011,1004,997,990,983,975,968,960,953,946,939,932,924,916,908,901,895,890,886,882,879,
-876,873,870,866,862,858,855,851,848,845,843,840,838,837,836,836,835,834,831,827,821,
-814,806,797,788,781,775,770,767,764,760,755,749,741,733,724,717,713,710,711,714,718,
-723,728,731,734,737,739,743,747,751,756,761,764,767,768,769,769,770,772,775,779,782,
-785,788,790,791,792,794,798,802,807,814,821,828,836,845,855,866,877,889,902,913,924,
-933,941,949,957,966,976,987,999,1011,1023,1034,1046,1056,1067,1078,1088,1099,1110,1122,1134,1148,
-1164,1183,1205,1231,1259,1289,1233,1255,1276,1295,1312,1329,1344,1359,1374,1390,1404,1417,1427,1435,1440,
-1443,1445,1447,1450,1454,1460,1467,1475,1483,1491,1498,1506,1514,1522,1530,1537,1542,1547,1550,1553,1558,
-1565,1577,1592,1612,1634,1656,1678,1697,1713,1727,1740,1753,1766,1779,1792,1802,1807,1806,1797,1781,1761,
-1737,1715,1696,1683,1674,1670,1667,1665,1661,1656,1649,1643,1639,1639,1644,1653,1666,1680,1692,1703,1709,
-1712,1712,1710,1708,1707,1707,1709,1711,1713,1713,1710,1705,1697,1689,1680,1673,1669,1670,1674,1683,1694,
-1707,1721,1733,1743,1750,1756,1761,1766,1771,1778,1787,1798,1811,1827,1845,1866,1890,1915,1940,1961,1975,
-1977,1966,1944,1914,1883,1860,1852,1866,1904,1964,2038,2116,2189,2246,2283,2299,2297,2286,2272,2262,2261,
-2269,2282,2297,2309,2314,2312,2305,2296,2289,2287,2291,2301,2315,2329,2341,2350,2356,2362,2370,2381,2398,
-2419,2442,2467,2490,2512,2532,2552,2574,2597,2623,2650,2674,2694,2708,2716,2718,2719,2721,2729,2744,2768,
-2800,2837,2877,2917,2955,2989,3018,3042,3060,3071,3076,3077,3074,3072,3077,3091,3121,3166,3228,3301,3378,
-3454,3520,3573,3612,3639,3659,3679,3702,3732,3767,3803,3833,3850,3850,3828,3785,3727,3658,3586,3518,3457,
-3406,3364,3328,3296,3264,3232,3198,3162,3127,3093,3061,3031,3003,2976,2950,2923,2895,2865,2834,2803,2770,
-2738,2707,2676,2647,2619,2592,2567,2542,2518,2496,2476,2460,2449,2443,2441,2443,2444,2442,2435,2420,2398,
-2372,2344,2320,2304,2298,2301,2313,2328,2343,2351,2350,2339,2320,2295,2270,2249,2233,2225,2222,2223,2222,
-2217,2205,2185,2157,2123,2085,2044,2004,1966,1932,1900,1873,1848,1824,1801,1775,1747,1714,1677,1639,1601,
-1567,1539,1522,1514,1516,1525,1538,1550,1560,1565,1566,1565,1564,1565,1569,1575,1582,1587,1588,1581,1568,
-1549,1527,1503,1481,1462,1445,1429,1412,1392,1370,1343,1316,1288,1264,1243,1227,1213,1199,1182,1159,1129,
-1091,1047,999,951,906,866,831,802,776,752,728,701,670,635,596,555,512,470,427,386,344,
-303,261,219,177,138,102,71,47,28,15,3,-10,-29,-57,-95,-142,-193,-244,-288,-319,-332,
--327,-305,-270,-228,-185,-147,-119,-103,-99,-107,-123,-147,-176,-210,-249,-293,-343,-398,-456,-518,-580,
--642,-704,-764,-823,-881,-940,-998,-1056,-1112,-1165,-1216,-1262,-1306,-1346,-1384,-1420,-1454,-1486,-1515,-1538,-1555,
--1566,-1571,-1572,-1572,-1572,-1577,-1586,-1600,-1619,-1641,-1666,-1690,-1715,-1740,-1767,-1797,-1831,-1871,-1916,-1965,-2015,
--2065,-2112,-2153,-2189,-2218,-2244,-2267,-2289,-2314,-2341,-2372,-2404,-2438,-2470,-2498,-2522,-2539,-2552,-2560,-2567,-2574,
--2582,-2593,-2606,-2621,-2638,-2654,-2671,-2689,-2707,-2728,-2752,-2781,-2813,-2847,-2881,-2914,-2943,-2968,-2989,-3006,-3022,
--3036,-3052,-3070,-3089,-3112,-3138,-3168,-3203,-3244,-3293,-3350,-3412,-3477,-3541,-3599,-3648,-3683,-3704,-3711,-3707,-3696,
--3682,-3669,-3661,-3660,-3665,-3677,-3695,-3715,-3737,-3760,-3782,-3803,-3824,-3843,-3862,-3880,-3897,-3913,-3927,-3940,-3950,
--3959,-3966,-3974,-3983,-3996,-4013,-4035,-4061,-4090,-4120,-4147,-4171,-4188,-4200,-4205,-4206,-4203,-4199,-4193,-4187,-4182,
--4178,-4176,-4178,-4183,-4195,-4214,-4239,-4269,-4303,-4337,-4370,-4398,-4422,-4441,-4455,-4467,-4476,-4485,-4493,-4499,-4505,
--4510,-4514,-4519,-4525,-4534,-4545,-4558,-4571,-4582,-4589,-4590,-4586,-4577,-4564,-4551,-4538,-4529,-4522,-4520,-4522,-4529,
--4543,-4565,-4596,-4636,-4685,-4738,-4791,-4839,-4875,-4896,-4901,-4889,-4865,-4836,-4806,-4782,-4768,-4763,-4767,-4776,-4787,
--4795,-4799,-4798,-4794,-4787,-4780,-4775,-4774,-4776,-4780,-4787,-4795,-4804,-4813,-4824,-4834,-4845,-4853,-4858,-4857,-4851,
--4839,-4824,-4809,-4796,-4790,-4792,-4804,-4824,-4850,-4878,-4905,-4927,-4944,-4955,-4962,-4968,-4973,-4981,-4991,-5004,-5019,
--5034,-5048,-5062,-5074,-5087,-5102,-5119,-5139,-5162,-5186,-5210,-5232,-5251,-5266,-5278,-5287,-5294,-5301,-5308,-5317,-5327,
--5339,-5351,-5363,-5375,-5388,-5401,-5416,-5432,-5449,-5466,-5483,-5498,-5510,-5519,-5525,-5528,-5530,-5532,-5535,-5539,-5545,
--5552,-5559,-5565,-5570,-5574,-5577,-5581,-5585,-5590,-5596,-5601,-5604,-5603,-5597,-5585,-5568,-5547,-5524,-5500,-5478,-5460,
--5445,-5434,-5427,-5423,-5421,-5420,-5421,-5422,-5425,-5428,-5432,-5435,-5438,-5441,-5442,-5442,-5441,-5438,-5434,-5430,-5424,
--5419,-5413,-5408,-5403,-5398,-5393,-5388,-5383,-5378,-5372,-5366,-5360,-5355,-5351,-5348,-5346,-5344,-5341,-5337,-5332,-5325,
--5316,-5308,-5300,-5294,-5291,-5291,-5292,-5294,-5297,-5297,-5295,-5291,-5285,-5277,-5268,-5260,-5252,-5246,-5240,-5236,-5232,
--5228,-5226,-5224,-5222,-5222,-5221,-5221,-5219,-5216,-5212,-5205,-5196,-5186,-5175,-5164,-5154,-5144,-5135,-5126,-5118,-5109,
--5100,-5091,-5082,-5072,-5063,-5055,-5047,-5040,-5034,-5028,-5023,-5019,-5016,-5013,-5010,-5007,-5004,-4999,-4993,-4986,-4979,
--4971,-4963,-4955,-4947,-4938,-4928,-4916,-4902,-4887,-4870,-4853,-4836,-4821,-4808,-4796,-4784,-4773,-4761,-4747,-4731,-4713,
--4693,-4673,-4654,-4637,-4621,-4606,-4593,-4580,-4568,-4555,-4543,-4531,-4520,-4509,-4499,-4488,-4477,-4465,-4451,-4436,-4421,
--4407,-4396,-4389,-4386,-4386,-4389,-4393,-4397,-4398,-4395,-4388,-4378,-4365,-4351,-4338,-4325,-4315,-4306,-4299,-4293,-4287,
--4281,-4275,-4267,-4259,-4249,-4238,-4227,-4215,-4203,-4190,-4177,-4163,-4150,-4136,-4122,-4107,-4092,-4075,-4057,-4038,-4018,
--3997,-3975,-3953,-3931,-3908,-3886,-3863,-3841,-3819,-3798,-3777,-3757,-3738,-3720,-3703,-3687,-3672,-3659,-3647,-3636,-3625,
--3614,-3602,-3590,-3578,-3565,-3553,-3541,-3529,-3518,-3508,-3499,-3490,-3481,-3472,-3464,-3456,-3447,-3438,-3429,-3420,-3409,
--3397,-3386,-3374,-3362,-3352,-3343,-3335,-3328,-3321,-3313,-3303,-3292,-3279,-3265,-3252,-3239,-3227,-3218,-3209,-3201,-3192,
--3182,-3169,-3154,-3137,-3120,-3103,-3086,-3070,-3054,-3037,-3020,-3002,-2982,-2963,-2945,-2927,-2911,-2896,-2882,-2868,-2852,
--2836,-2819,-2802,-2786,-2772,-2761,-2751,-2743,-2734,-2724,-2711,-2697,-2681,-2666,-2652,-2642,-2634,-2628,-2623,-2616,-2608,
--2597,-2583,-2570,-2557,-2546,-2538,-2531,-2526,-2520,-2512,-2501,-2489,-2474,-2460,-2447,-2436,-2425,-2416,-2405,-2393,-2379,
--2362,-2345,-2328,-2311,-2296,-2282,-2266,-2248,-2227,-2202,-2175,-2146,-2118,-2093,-2071,-2054,-2040,-2028,-2016,-2003,-1991,
--1978,-1966,-1956,-1948,-1940,-1932,-1919,-1901,-1877,-1845,-1808,-1769,-1731,-1696,-1666,-1642,-1623,-1606,-1591,-1575,-1557,
--1537,-1515,-1493,-1471,-1450,-1430,-1411,-1391,-1372,-1352,-1331,-1310,-1289,-1267,-1246,-1224,-1202,-1180,-1157,-1135,-1113,
--1091,-1069,-1046,-1023,-998,-973,-946,-919,-892,-865,-841,-818,-796,-774,-753,-731,-707,-682,-656,-628,-599,
--569,-537,-503,-468,-431,-394,-358,-324,-294,-267,-243,-222,-201,-180,-156,-130,-100,-67,-32,5,45,
-89,137,190,249,314,382,453,523,589,650,704,752,794,831,866,899,931,960,988,1012,1033,
-1051,1066,1081,1095,1109,1124,1139,1154,1168,1183,1200,1220,1247,1279,1319,1362,1404,1443,1471,1487,1489,
-1480,1462,1442,1424,1412,1406,1406,1408,1408,1402,1390,1373,1353,1335,1324,1323,1333,1354,1382,1414,1446,
-1475,1499,1517,1528,1534,1533,1525,1508,1482,1447,1404,1357,1310,1267,1230,1201,1180,1165,1154,1144,1133,
-1122,1110,1099,1091,1084,1080,1076,1073,1068,1062,1055,1049,1046,1046,1051,1060,1071,1082,1092,1099,1104,
-1107,1110,1114,1120,1128,1138,1148,1155,1160,1162,1161,1158,1155,1151,1148,1144,1141,1136,1129,1121,1113,
-1103,1095,1087,1082,1078,1075,1073,1072,1071,1071,1071,1071,1070,1068,1065,1060,1054,1046,1038,1031,1025,
-1022,1020,1021,1022,1023,1023,1020,1016,1009,1001,992,984,975,967,960,952,945,937,930,922,915,
-907,900,892,885,878,871,864,857,851,845,840,835,831,827,824,821,818,816,814,812,810,
-808,805,802,799,797,795,793,792,790,789,786,783,778,772,765,757,751,745,740,735,732,
-728,723,717,711,704,698,693,689,688,689,692,696,701,706,710,715,719,723,727,732,737,
-741,746,749,751,752,753,755,756,759,762,766,769,772,773,774,774,774,774,776,779,783,
-789,795,802,810,818,827,836,847,858,870,882,893,903,913,922,931,941,951,962,974,987,
-1000,1012,1024,1035,1046,1057,1068,1078,1088,1098,1107,1117,1127,1139,1153,1170,1190,1211,1233,1159,1173,
-1187,1201,1215,1231,1249,1270,1293,1319,1344,1366,1385,1398,1406,1409,1409,1407,1406,1408,1413,1421,1432,
-1445,1459,1473,1485,1495,1504,1510,1515,1518,1521,1523,1528,1535,1546,1560,1578,1599,1620,1639,1656,1668,
-1676,1680,1683,1687,1691,1698,1706,1714,1720,1722,1717,1707,1691,1672,1652,1634,1620,1611,1605,1604,1604,
-1604,1605,1605,1606,1608,1612,1619,1628,1638,1649,1658,1665,1670,1672,1671,1670,1668,1667,1666,1666,1665,
-1664,1660,1654,1647,1638,1630,1622,1618,1617,1620,1627,1638,1650,1663,1675,1687,1696,1705,1713,1721,1729,
-1739,1750,1761,1774,1788,1804,1822,1843,1866,1892,1916,1935,1946,1946,1933,1910,1880,1853,1834,1833,1855,
-1899,1964,2040,2119,2189,2243,2276,2288,2284,2271,2256,2245,2242,2247,2257,2269,2277,2280,2278,2271,2264,
-2261,2263,2271,2284,2300,2315,2327,2335,2340,2345,2353,2365,2384,2409,2438,2470,2502,2532,2561,2587,2612,
-2635,2657,2677,2692,2702,2707,2706,2703,2701,2703,2713,2734,2765,2805,2851,2901,2950,2998,3041,3079,3111,
-3138,3158,3171,3177,3179,3178,3180,3189,3210,3247,3301,3370,3449,3533,3613,3686,3748,3796,3835,3865,3892,
-3917,3940,3961,3974,3977,3963,3932,3884,3820,3747,3670,3594,3523,3461,3408,3363,3323,3287,3252,3218,3184,
-3151,3119,3091,3066,3043,3024,3005,2986,2964,2939,2911,2880,2846,2812,2779,2747,2719,2692,2665,2638,2609,
-2577,2543,2509,2478,2453,2436,2426,2424,2425,2425,2420,2406,2383,2352,2319,2287,2264,2253,2257,2273,2298,
-2327,2352,2370,2378,2377,2368,2358,2348,2344,2344,2350,2356,2360,2357,2343,2317,2280,2232,2178,2119,2061,
-2005,1953,1907,1866,1831,1801,1773,1746,1720,1692,1664,1637,1613,1593,1579,1574,1576,1583,1594,1604,1610,
-1611,1606,1596,1585,1576,1571,1571,1576,1584,1590,1592,1586,1572,1551,1525,1498,1473,1452,1437,1426,1417,
-1407,1393,1375,1351,1323,1294,1265,1237,1212,1187,1163,1136,1106,1072,1035,996,956,917,880,848,818,
-791,765,739,712,683,653,620,586,550,512,473,432,390,348,306,266,229,195,166,140,117,
-96,72,45,13,-26,-71,-121,-171,-220,-261,-292,-310,-314,-305,-283,-253,-218,-183,-150,-123,-105,
--96,-98,-111,-135,-169,-212,-262,-317,-375,-433,-489,-545,-598,-650,-703,-756,-811,-868,-925,-981,-1033,
--1082,-1127,-1168,-1206,-1244,-1284,-1326,-1371,-1417,-1462,-1504,-1539,-1567,-1587,-1599,-1607,-1611,-1616,-1623,-1632,-1644,
--1659,-1674,-1689,-1705,-1721,-1739,-1759,-1784,-1813,-1847,-1886,-1927,-1972,-2017,-2062,-2106,-2148,-2189,-2228,-2265,-2300,
--2333,-2366,-2398,-2430,-2463,-2495,-2527,-2558,-2586,-2610,-2628,-2641,-2648,-2650,-2648,-2644,-2640,-2638,-2639,-2646,-2659,
--2680,-2707,-2739,-2776,-2815,-2854,-2891,-2923,-2951,-2975,-2994,-3010,-3026,-3041,-3056,-3073,-3090,-3108,-3128,-3153,-3183,
--3223,-3274,-3336,-3409,-3489,-3569,-3644,-3707,-3751,-3774,-3777,-3761,-3732,-3697,-3664,-3637,-3622,-3618,-3626,-3643,-3666,
--3692,-3719,-3745,-3770,-3795,-3821,-3846,-3871,-3895,-3916,-3933,-3943,-3947,-3945,-3941,-3936,-3934,-3937,-3948,-3966,-3991,
--4019,-4047,-4074,-4097,-4114,-4127,-4136,-4144,-4150,-4156,-4162,-4168,-4172,-4174,-4176,-4179,-4184,-4194,-4210,-4232,-4260,
--4292,-4325,-4356,-4383,-4407,-4426,-4442,-4457,-4472,-4488,-4505,-4521,-4537,-4552,-4565,-4579,-4593,-4608,-4625,-4643,-4661,
--4675,-4685,-4687,-4683,-4672,-4657,-4640,-4624,-4611,-4601,-4597,-4596,-4600,-4608,-4622,-4641,-4668,-4701,-4739,-4780,-4818,
--4848,-4868,-4874,-4866,-4847,-4821,-4795,-4773,-4759,-4757,-4765,-4781,-4803,-4825,-4846,-4862,-4873,-4880,-4882,-4882,-4881,
--4878,-4876,-4875,-4875,-4878,-4885,-4896,-4911,-4927,-4943,-4955,-4959,-4954,-4940,-4918,-4892,-4867,-4848,-4840,-4844,-4860,
--4887,-4919,-4952,-4982,-5007,-5024,-5035,-5043,-5049,-5058,-5068,-5082,-5097,-5113,-5126,-5138,-5147,-5155,-5164,-5175,-5189,
--5208,-5230,-5255,-5280,-5302,-5321,-5336,-5347,-5354,-5361,-5367,-5374,-5383,-5393,-5404,-5416,-5427,-5438,-5449,-5459,-5470,
--5481,-5494,-5507,-5520,-5533,-5546,-5557,-5568,-5578,-5587,-5596,-5604,-5610,-5615,-5619,-5621,-5622,-5623,-5626,-5630,-5637,
--5646,-5657,-5668,-5678,-5685,-5688,-5685,-5678,-5666,-5650,-5632,-5613,-5594,-5576,-5559,-5544,-5530,-5519,-5511,-5505,-5501,
--5500,-5501,-5503,-5506,-5509,-5512,-5514,-5515,-5515,-5513,-5509,-5503,-5496,-5487,-5478,-5469,-5461,-5455,-5451,-5448,-5446,
--5445,-5442,-5439,-5434,-5428,-5422,-5416,-5411,-5407,-5404,-5401,-5397,-5392,-5385,-5377,-5368,-5359,-5352,-5346,-5344,-5343,
--5344,-5345,-5345,-5343,-5340,-5335,-5328,-5320,-5312,-5304,-5296,-5289,-5283,-5277,-5273,-5270,-5268,-5268,-5270,-5272,-5275,
--5276,-5275,-5271,-5264,-5255,-5244,-5232,-5219,-5207,-5195,-5184,-5174,-5163,-5154,-5144,-5135,-5127,-5119,-5112,-5106,-5100,
--5093,-5087,-5079,-5072,-5064,-5057,-5051,-5047,-5044,-5042,-5041,-5041,-5040,-5039,-5037,-5033,-5027,-5018,-5007,-4994,-4979,
--4962,-4944,-4926,-4908,-4891,-4875,-4860,-4846,-4832,-4817,-4802,-4786,-4768,-4750,-4731,-4713,-4695,-4679,-4663,-4649,-4635,
--4621,-4608,-4596,-4584,-4572,-4561,-4550,-4540,-4529,-4519,-4507,-4496,-4485,-4476,-4468,-4462,-4460,-4459,-4460,-4460,-4460,
--4458,-4453,-4445,-4434,-4421,-4407,-4392,-4377,-4364,-4352,-4343,-4334,-4328,-4322,-4316,-4309,-4301,-4292,-4281,-4267,-4252,
--4236,-4219,-4201,-4184,-4167,-4150,-4134,-4119,-4104,-4088,-4071,-4054,-4035,-4015,-3994,-3972,-3949,-3925,-3902,-3879,-3856,
--3834,-3813,-3792,-3773,-3754,-3736,-3719,-3704,-3689,-3675,-3662,-3650,-3639,-3628,-3617,-3607,-3597,-3587,-3577,-3567,-3558,
--3549,-3540,-3532,-3523,-3514,-3506,-3497,-3488,-3479,-3471,-3463,-3454,-3445,-3436,-3426,-3416,-3406,-3396,-3386,-3377,-3367,
--3357,-3347,-3336,-3324,-3311,-3298,-3286,-3274,-3262,-3252,-3242,-3231,-3219,-3206,-3192,-3176,-3159,-3142,-3125,-3108,-3091,
--3074,-3056,-3037,-3018,-2998,-2979,-2961,-2945,-2930,-2916,-2903,-2889,-2875,-2860,-2845,-2831,-2819,-2809,-2801,-2794,-2787,
--2778,-2766,-2752,-2734,-2716,-2699,-2684,-2672,-2664,-2659,-2655,-2649,-2642,-2633,-2621,-2608,-2595,-2585,-2576,-2570,-2564,
--2559,-2551,-2542,-2529,-2515,-2501,-2486,-2472,-2460,-2448,-2436,-2423,-2409,-2394,-2378,-2362,-2347,-2332,-2318,-2303,-2285,
--2264,-2239,-2212,-2184,-2155,-2130,-2107,-2088,-2072,-2058,-2044,-2029,-2013,-1996,-1979,-1963,-1950,-1939,-1930,-1921,-1910,
--1895,-1875,-1849,-1818,-1783,-1747,-1711,-1678,-1647,-1621,-1598,-1577,-1559,-1542,-1525,-1508,-1489,-1469,-1447,-1424,-1401,
--1378,-1356,-1334,-1314,-1294,-1273,-1252,-1229,-1206,-1181,-1156,-1131,-1108,-1087,-1067,-1048,-1030,-1011,-991,-969,-946,
--922,-897,-873,-849,-825,-801,-776,-751,-724,-697,-670,-642,-614,-585,-554,-520,-484,-444,-403,-360,-320,
--282,-251,-225,-206,-191,-179,-166,-151,-131,-104,-69,-25,24,81,144,211,280,349,417,482,541,
-595,643,685,724,760,795,830,865,898,929,956,979,997,1010,1021,1030,1039,1048,1058,1069,1080,
-1091,1104,1120,1140,1168,1203,1244,1289,1333,1371,1399,1412,1411,1397,1375,1351,1329,1313,1305,1304,1306,
-1308,1306,1297,1284,1267,1252,1242,1242,1253,1274,1303,1336,1369,1398,1421,1437,1444,1444,1436,1420,1396,
-1365,1326,1282,1236,1190,1148,1112,1084,1064,1050,1041,1035,1029,1024,1020,1016,1014,1014,1015,1016,1016,
-1014,1010,1005,1000,996,994,994,998,1002,1008,1013,1016,1019,1021,1024,1030,1038,1048,1060,1073,1084,
-1093,1098,1100,1099,1096,1093,1088,1084,1080,1075,1071,1066,1060,1054,1049,1043,1037,1031,1025,1018,1011,
-1004,999,994,991,989,987,985,983,979,973,967,961,955,952,950,951,954,958,961,964,964,
-963,959,953,946,938,930,922,914,906,899,891,883,876,868,860,852,844,836,828,821,813,
-806,800,794,789,784,781,777,775,774,773,773,773,773,772,771,769,766,762,758,754,750,
-746,742,738,734,729,725,722,718,715,712,709,706,702,697,691,685,679,674,670,668,668,
-669,672,676,679,683,687,692,697,703,709,717,724,731,736,740,742,742,742,743,743,745,
-749,752,756,758,759,758,756,752,749,747,747,749,753,759,766,775,784,794,805,816,827,
-839,851,862,873,882,891,899,908,918,928,941,954,968,982,996,1009,1022,1034,1045,1055,1064,
-1072,1078,1083,1088,1093,1100,1108,1118,1130,1144,1159,1104,1115,1126,1137,1150,1164,1183,1205,1231,1260,
-1288,1315,1337,1353,1361,1364,1363,1360,1357,1358,1363,1373,1387,1403,1422,1440,1456,1470,1481,1489,1495,
-1499,1502,1505,1510,1517,1528,1542,1558,1577,1595,1611,1623,1630,1632,1630,1626,1621,1618,1619,1623,1630,
-1638,1645,1649,1649,1644,1635,1622,1609,1596,1585,1578,1573,1572,1573,1575,1579,1584,1589,1594,1600,1606,
-1612,1618,1623,1626,1629,1630,1631,1630,1629,1627,1625,1621,1616,1610,1603,1595,1588,1581,1575,1572,1573,
-1576,1583,1592,1603,1615,1627,1638,1649,1659,1670,1681,1694,1708,1722,1737,1752,1766,1780,1794,1808,1824,
-1842,1860,1877,1890,1896,1893,1880,1861,1840,1823,1818,1830,1862,1915,1982,2058,2131,2194,2238,2262,2266,
-2255,2237,2219,2208,2206,2214,2227,2243,2256,2263,2264,2261,2255,2252,2254,2262,2276,2295,2314,2333,2349,
-2362,2374,2386,2401,2421,2444,2471,2501,2531,2560,2586,2610,2630,2646,2658,2666,2669,2667,2662,2656,2652,
-2653,2663,2684,2717,2760,2811,2867,2923,2978,3029,3075,3116,3153,3186,3215,3238,3254,3265,3272,3276,3282,
-3296,3320,3359,3412,3479,3556,3638,3719,3795,3861,3918,3965,4002,4031,4053,4067,4071,4062,4039,3999,3944,
-3875,3795,3711,3626,3545,3472,3410,3357,3314,3277,3246,3217,3190,3163,3136,3111,3088,3067,3048,3031,3013,
-2995,2974,2950,2924,2897,2870,2844,2822,2802,2784,2765,2743,2717,2684,2645,2604,2564,2528,2500,2482,2472,
-2469,2466,2459,2444,2419,2386,2348,2311,2281,2265,2264,2278,2304,2337,2371,2399,2420,2432,2437,2438,2438,
-2441,2445,2452,2456,2456,2446,2425,2390,2344,2287,2224,2158,2093,2031,1974,1924,1880,1843,1812,1785,1764,
-1746,1731,1719,1709,1702,1697,1695,1695,1695,1695,1691,1683,1670,1651,1629,1606,1585,1571,1564,1566,1574,
-1584,1594,1598,1593,1578,1555,1527,1497,1470,1448,1432,1422,1415,1407,1394,1374,1346,1311,1271,1229,1189,
-1152,1121,1095,1073,1055,1038,1020,1000,977,951,922,893,862,833,805,781,759,740,722,704,683,
-658,626,587,542,494,444,397,355,319,292,269,250,229,204,171,128,78,22,-36,-91,-140,
--180,-208,-227,-237,-240,-239,-235,-230,-222,-213,-202,-190,-179,-171,-171,-181,-205,-243,-293,-354,-421,
--488,-552,-610,-661,-706,-748,-789,-832,-877,-925,-974,-1020,-1063,-1100,-1133,-1162,-1190,-1220,-1255,-1296,-1342,
--1392,-1443,-1491,-1534,-1570,-1599,-1622,-1641,-1658,-1674,-1689,-1705,-1719,-1730,-1739,-1745,-1749,-1752,-1756,-1762,-1771,
--1785,-1804,-1829,-1859,-1896,-1939,-1989,-2046,-2107,-2171,-2233,-2292,-2344,-2387,-2423,-2452,-2478,-2503,-2530,-2560,-2594,
--2629,-2662,-2690,-2710,-2721,-2721,-2714,-2702,-2689,-2679,-2676,-2682,-2696,-2718,-2746,-2778,-2810,-2842,-2872,-2898,-2921,
--2941,-2960,-2979,-2997,-3016,-3035,-3055,-3074,-3093,-3113,-3134,-3160,-3192,-3234,-3287,-3351,-3424,-3503,-3583,-3656,-3716,
--3759,-3781,-3782,-3765,-3735,-3699,-3664,-3634,-3615,-3607,-3609,-3621,-3638,-3658,-3680,-3702,-3726,-3750,-3777,-3806,-3837,
--3867,-3893,-3915,-3929,-3935,-3934,-3929,-3924,-3920,-3922,-3930,-3944,-3963,-3984,-4004,-4021,-4034,-4043,-4049,-4055,-4062,
--4071,-4084,-4098,-4113,-4128,-4141,-4153,-4165,-4179,-4195,-4216,-4242,-4271,-4302,-4332,-4360,-4385,-4406,-4426,-4446,-4468,
--4494,-4524,-4556,-4589,-4620,-4649,-4673,-4695,-4714,-4733,-4752,-4772,-4792,-4809,-4823,-4830,-4829,-4821,-4808,-4791,-4774,
--4759,-4747,-4740,-4736,-4735,-4736,-4740,-4746,-4755,-4768,-4785,-4804,-4824,-4842,-4854,-4857,-4852,-4839,-4820,-4800,-4782,
--4770,-4767,-4775,-4791,-4814,-4842,-4871,-4898,-4923,-4943,-4958,-4968,-4973,-4973,-4969,-4963,-4957,-4954,-4956,-4964,-4978,
--4998,-5019,-5039,-5052,-5055,-5047,-5029,-5003,-4973,-4947,-4927,-4919,-4922,-4936,-4959,-4985,-5011,-5035,-5054,-5070,-5084,
--5098,-5114,-5132,-5152,-5173,-5193,-5209,-5222,-5230,-5235,-5238,-5243,-5251,-5263,-5279,-5298,-5318,-5338,-5355,-5369,-5381,
--5390,-5398,-5407,-5417,-5429,-5442,-5456,-5469,-5482,-5492,-5501,-5508,-5514,-5519,-5526,-5534,-5543,-5555,-5568,-5582,-5597,
--5611,-5626,-5639,-5650,-5660,-5668,-5674,-5678,-5682,-5685,-5689,-5694,-5700,-5707,-5715,-5723,-5732,-5740,-5748,-5754,-5760,
--5763,-5764,-5762,-5756,-5746,-5733,-5716,-5698,-5678,-5659,-5642,-5627,-5615,-5606,-5599,-5593,-5589,-5585,-5581,-5578,-5576,
--5575,-5574,-5572,-5568,-5563,-5556,-5548,-5538,-5528,-5520,-5513,-5509,-5507,-5506,-5505,-5502,-5498,-5492,-5485,-5477,-5470,
--5465,-5462,-5461,-5460,-5458,-5455,-5449,-5441,-5431,-5421,-5411,-5402,-5396,-5391,-5389,-5388,-5387,-5386,-5384,-5380,-5375,
--5369,-5363,-5355,-5347,-5339,-5331,-5325,-5320,-5318,-5318,-5320,-5323,-5327,-5330,-5330,-5328,-5322,-5313,-5302,-5289,-5276,
--5263,-5251,-5240,-5230,-5221,-5212,-5203,-5194,-5187,-5180,-5174,-5169,-5164,-5159,-5153,-5146,-5137,-5127,-5117,-5107,-5099,
--5094,-5091,-5090,-5091,-5092,-5092,-5091,-5088,-5082,-5074,-5064,-5052,-5039,-5025,-5010,-4994,-4977,-4960,-4943,-4926,-4909,
--4893,-4876,-4860,-4844,-4828,-4811,-4794,-4777,-4759,-4741,-4725,-4709,-4694,-4680,-4667,-4655,-4644,-4633,-4622,-4610,-4599,
--4588,-4577,-4567,-4558,-4550,-4543,-4538,-4534,-4531,-4529,-4526,-4523,-4519,-4513,-4506,-4497,-4486,-4474,-4460,-4446,-4431,
--4417,-4403,-4390,-4378,-4367,-4357,-4347,-4338,-4328,-4316,-4303,-4289,-4273,-4256,-4238,-4221,-4203,-4186,-4170,-4154,-4139,
--4123,-4108,-4091,-4073,-4054,-4034,-4012,-3989,-3966,-3942,-3917,-3894,-3871,-3849,-3828,-3809,-3791,-3774,-3758,-3742,-3726,
--3711,-3697,-3683,-3669,-3657,-3645,-3635,-3625,-3616,-3608,-3601,-3594,-3587,-3580,-3572,-3564,-3555,-3546,-3536,-3526,-3515,
--3506,-3497,-3490,-3483,-3476,-3469,-3461,-3452,-3442,-3432,-3420,-3409,-3397,-3385,-3374,-3363,-3352,-3341,-3330,-3319,-3307,
--3294,-3281,-3267,-3253,-3238,-3222,-3206,-3190,-3174,-3159,-3144,-3129,-3113,-3096,-3078,-3059,-3039,-3018,-2998,-2979,-2961,
--2945,-2929,-2915,-2900,-2887,-2873,-2861,-2851,-2842,-2836,-2832,-2828,-2823,-2815,-2805,-2791,-2774,-2755,-2737,-2720,-2707,
--2696,-2689,-2683,-2678,-2672,-2665,-2657,-2648,-2640,-2632,-2625,-2619,-2612,-2605,-2595,-2583,-2569,-2553,-2537,-2521,-2506,
--2492,-2480,-2468,-2456,-2444,-2431,-2417,-2403,-2389,-2374,-2359,-2341,-2320,-2297,-2271,-2243,-2214,-2187,-2163,-2142,-2124,
--2110,-2096,-2081,-2065,-2047,-2027,-2007,-1987,-1970,-1956,-1944,-1933,-1922,-1908,-1890,-1867,-1839,-1806,-1770,-1734,-1699,
--1668,-1641,-1618,-1598,-1582,-1565,-1548,-1529,-1507,-1481,-1454,-1425,-1397,-1372,-1349,-1329,-1312,-1297,-1281,-1264,-1244,
--1221,-1195,-1167,-1139,-1113,-1089,-1068,-1050,-1034,-1019,-1003,-987,-968,-948,-926,-903,-879,-854,-828,-800,-772,
--743,-714,-685,-657,-629,-601,-573,-542,-508,-471,-430,-387,-344,-302,-265,-234,-208,-188,-172,-156,-137,
--113,-81,-39,11,69,133,199,265,328,386,437,483,524,561,596,632,671,712,756,800,843,
-882,914,938,954,963,967,969,971,976,983,993,1004,1016,1027,1039,1052,1068,1091,1120,1156,1196,
-1237,1273,1301,1317,1319,1308,1289,1266,1244,1226,1215,1211,1211,1212,1211,1207,1199,1189,1180,1176,1178,
-1189,1208,1233,1262,1291,1316,1337,1350,1355,1351,1340,1320,1291,1256,1214,1168,1122,1078,1039,1006,982,
-966,955,949,945,943,940,938,936,937,939,943,948,952,955,956,954,951,947,944,942,941,
-942,944,946,949,951,954,958,964,973,983,996,1008,1020,1030,1037,1040,1041,1040,1037,1032,1028,
-1024,1020,1016,1012,1009,1005,1001,997,992,986,979,971,963,955,947,940,935,930,927,924,921,
-918,913,909,904,900,898,898,900,904,908,913,917,919,919,916,911,904,896,887,879,871,
-864,857,851,846,840,834,828,822,814,807,798,790,782,775,767,761,755,750,746,742,740,
-739,738,737,737,737,737,736,733,730,726,720,714,708,701,694,688,683,679,676,675,675,
-676,676,676,674,672,668,664,660,656,654,654,656,659,662,666,670,673,675,678,682,687,
-693,701,709,717,724,729,732,733,732,731,730,731,733,736,739,742,743,742,738,734,729,
-724,721,721,723,729,736,746,756,768,779,792,804,816,828,839,848,857,864,871,877,885,
-894,905,917,932,947,963,979,995,1009,1023,1035,1046,1054,1060,1063,1065,1066,1066,1068,1071,1077,
-1085,1094,1104,1093,1103,1113,1123,1134,1146,1161,1178,1199,1221,1245,1267,1286,1300,1309,1313,1314,1313,
-1313,1315,1321,1332,1347,1366,1386,1406,1425,1443,1457,1469,1477,1483,1487,1490,1493,1498,1504,1514,1527,
-1542,1557,1572,1583,1590,1592,1588,1580,1571,1562,1556,1555,1558,1567,1578,1589,1599,1606,1607,1603,1595,
-1584,1572,1561,1553,1547,1546,1548,1553,1559,1566,1572,1577,1581,1584,1585,1587,1588,1589,1590,1591,1590,
-1589,1586,1582,1576,1569,1560,1552,1545,1538,1534,1532,1533,1536,1542,1550,1559,1569,1580,1592,1604,1616,
-1629,1643,1657,1673,1690,1707,1723,1739,1753,1766,1779,1791,1803,1815,1827,1837,1843,1845,1841,1832,1821,
-1813,1811,1822,1850,1895,1955,2025,2096,2161,2211,2242,2251,2243,2222,2198,2178,2168,2171,2187,2211,2238,
-2263,2280,2288,2287,2281,2275,2272,2275,2287,2307,2333,2362,2392,2420,2445,2466,2486,2503,2520,2536,2551,
-2566,2580,2591,2600,2606,2609,2607,2602,2594,2585,2576,2572,2575,2588,2614,2653,2704,2763,2826,2890,2949,
-3001,3046,3083,3115,3144,3171,3199,3227,3253,3278,3300,3320,3338,3358,3382,3413,3455,3507,3569,3638,3711,
-3786,3858,3924,3982,4032,4072,4101,4119,4122,4110,4082,4036,3974,3898,3811,3718,3626,3539,3461,3395,3343,
-3304,3275,3253,3234,3217,3198,3176,3153,3129,3105,3081,3060,3039,3020,3000,2979,2958,2937,2916,2898,2883,
-2871,2861,2850,2836,2817,2791,2758,2720,2681,2644,2614,2592,2578,2570,2564,2555,2538,2512,2478,2438,2398,
-2364,2341,2332,2337,2354,2379,2405,2428,2446,2456,2459,2459,2456,2453,2451,2447,2441,2429,2408,2377,2337,
-2288,2234,2178,2122,2069,2021,1977,1939,1905,1876,1851,1832,1817,1808,1804,1805,1810,1817,1823,1827,1827,
-1820,1807,1786,1759,1725,1689,1653,1620,1594,1577,1569,1570,1576,1585,1591,1592,1584,1568,1545,1518,1491,
-1467,1448,1436,1428,1421,1411,1394,1367,1330,1283,1230,1175,1123,1079,1046,1025,1017,1018,1025,1033,1037,
-1035,1025,1005,977,945,913,884,862,848,843,842,843,839,826,799,759,706,645,581,522,471,
-433,406,388,373,355,329,291,240,180,115,52,-2,-44,-73,-90,-100,-107,-116,-132,-154,-182,
--210,-235,-254,-265,-269,-271,-276,-290,-318,-361,-419,-489,-564,-639,-706,-765,-812,-851,-884,-915,-948,
--983,-1021,-1060,-1098,-1131,-1161,-1185,-1208,-1231,-1258,-1291,-1330,-1374,-1422,-1469,-1514,-1555,-1592,-1624,-1655,-1684,
--1713,-1743,-1771,-1796,-1816,-1828,-1833,-1830,-1820,-1806,-1790,-1775,-1761,-1752,-1749,-1754,-1770,-1800,-1845,-1906,-1982,
--2070,-2164,-2257,-2343,-2415,-2471,-2510,-2535,-2551,-2565,-2582,-2605,-2636,-2672,-2709,-2742,-2767,-2782,-2786,-2782,-2773,
--2765,-2763,-2768,-2781,-2801,-2826,-2851,-2873,-2890,-2902,-2909,-2914,-2918,-2924,-2934,-2948,-2966,-2988,-3012,-3038,-3064,
--3091,-3120,-3151,-3187,-3229,-3278,-3333,-3394,-3458,-3523,-3584,-3638,-3682,-3712,-3729,-3732,-3724,-3709,-3689,-3670,-3654,
--3644,-3640,-3641,-3646,-3655,-3666,-3678,-3691,-3708,-3728,-3752,-3781,-3813,-3846,-3879,-3908,-3931,-3948,-3959,-3966,-3971,
--3975,-3982,-3992,-4004,-4016,-4028,-4037,-4041,-4041,-4038,-4032,-4028,-4026,-4029,-4036,-4048,-4063,-4080,-4099,-4119,-4141,
--4166,-4194,-4225,-4258,-4291,-4322,-4350,-4372,-4391,-4407,-4424,-4446,-4474,-4510,-4553,-4601,-4651,-4698,-4739,-4772,-4797,
--4816,-4832,-4847,-4864,-4882,-4901,-4919,-4933,-4942,-4944,-4940,-4932,-4920,-4908,-4897,-4889,-4883,-4879,-4875,-4872,-4870,
--4868,-4868,-4870,-4875,-4882,-4891,-4898,-4903,-4904,-4900,-4891,-4879,-4866,-4854,-4847,-4844,-4848,-4859,-4875,-4897,-4921,
--4948,-4974,-4999,-5020,-5036,-5046,-5049,-5047,-5042,-5037,-5034,-5037,-5046,-5062,-5082,-5105,-5125,-5138,-5143,-5138,-5123,
--5103,-5079,-5056,-5038,-5027,-5022,-5024,-5032,-5042,-5055,-5069,-5084,-5102,-5123,-5148,-5174,-5202,-5229,-5252,-5271,-5284,
--5292,-5296,-5298,-5301,-5305,-5313,-5324,-5338,-5353,-5367,-5380,-5392,-5402,-5412,-5423,-5435,-5450,-5467,-5485,-5503,-5520,
--5534,-5546,-5554,-5559,-5563,-5567,-5571,-5577,-5585,-5595,-5607,-5621,-5635,-5648,-5662,-5674,-5686,-5697,-5708,-5718,-5728,
--5738,-5748,-5756,-5762,-5765,-5767,-5766,-5765,-5765,-5767,-5773,-5783,-5798,-5816,-5835,-5852,-5866,-5873,-5873,-5866,-5854,
--5837,-5819,-5800,-5782,-5766,-5750,-5734,-5717,-5699,-5681,-5663,-5647,-5634,-5626,-5621,-5620,-5621,-5621,-5620,-5617,-5610,
--5602,-5593,-5584,-5577,-5572,-5569,-5566,-5563,-5559,-5553,-5546,-5538,-5530,-5524,-5520,-5519,-5519,-5519,-5519,-5516,-5511,
--5502,-5492,-5480,-5468,-5458,-5448,-5441,-5436,-5432,-5429,-5427,-5425,-5422,-5419,-5414,-5409,-5402,-5395,-5388,-5381,-5376,
--5372,-5371,-5372,-5374,-5378,-5380,-5381,-5379,-5374,-5367,-5357,-5347,-5336,-5326,-5318,-5310,-5302,-5294,-5285,-5276,-5266,
--5257,-5248,-5241,-5235,-5231,-5227,-5223,-5218,-5211,-5203,-5193,-5183,-5173,-5165,-5158,-5153,-5149,-5145,-5141,-5136,-5129,
--5121,-5113,-5104,-5095,-5086,-5076,-5066,-5055,-5042,-5027,-5011,-4993,-4976,-4958,-4942,-4927,-4912,-4898,-4883,-4868,-4851,
--4833,-4814,-4795,-4777,-4761,-4746,-4734,-4722,-4712,-4701,-4690,-4678,-4665,-4652,-4640,-4628,-4618,-4611,-4605,-4601,-4597,
--4594,-4590,-4585,-4579,-4572,-4564,-4555,-4546,-4535,-4524,-4512,-4500,-4486,-4471,-4456,-4441,-4425,-4410,-4395,-4380,-4366,
--4351,-4336,-4320,-4305,-4289,-4273,-4257,-4242,-4228,-4214,-4199,-4184,-4169,-4152,-4134,-4115,-4095,-4074,-4052,-4030,-4006,
--3983,-3959,-3935,-3912,-3890,-3869,-3849,-3831,-3814,-3799,-3784,-3769,-3755,-3741,-3726,-3712,-3698,-3685,-3672,-3661,-3650,
--3641,-3633,-3626,-3620,-3614,-3608,-3601,-3594,-3586,-3577,-3567,-3556,-3546,-3536,-3528,-3520,-3512,-3505,-3497,-3489,-3479,
--3468,-3455,-3442,-3429,-3417,-3405,-3395,-3385,-3375,-3366,-3355,-3344,-3331,-3316,-3300,-3283,-3266,-3248,-3231,-3215,-3200,
--3186,-3173,-3160,-3146,-3132,-3117,-3100,-3081,-3062,-3041,-3020,-2999,-2980,-2961,-2943,-2927,-2911,-2897,-2885,-2874,-2866,
--2860,-2856,-2853,-2850,-2847,-2841,-2834,-2823,-2809,-2794,-2778,-2762,-2747,-2734,-2723,-2715,-2708,-2702,-2698,-2693,-2690,
--2686,-2682,-2676,-2669,-2660,-2648,-2634,-2618,-2600,-2582,-2564,-2548,-2534,-2520,-2509,-2497,-2486,-2474,-2462,-2449,-2435,
--2420,-2403,-2384,-2362,-2338,-2311,-2282,-2253,-2225,-2200,-2178,-2161,-2147,-2135,-2124,-2112,-2097,-2080,-2061,-2040,-2019,
--2000,-1982,-1966,-1950,-1935,-1917,-1896,-1872,-1844,-1814,-1782,-1750,-1721,-1694,-1671,-1651,-1633,-1616,-1598,-1577,-1553,
--1526,-1495,-1462,-1429,-1398,-1371,-1348,-1330,-1316,-1304,-1293,-1280,-1264,-1243,-1219,-1191,-1162,-1134,-1107,-1084,-1064,
--1046,-1031,-1017,-1002,-986,-969,-950,-929,-908,-885,-860,-835,-807,-778,-748,-718,-687,-657,-628,-598,-569,
--538,-505,-470,-432,-392,-351,-311,-272,-236,-202,-169,-135,-99,-58,-12,39,96,156,216,273,324,
-367,403,432,456,479,504,534,572,619,671,728,784,835,876,906,923,928,925,917,909,905,
-907,914,926,941,955,967,978,987,997,1011,1030,1055,1086,1119,1151,1178,1196,1204,1203,1193,1179,
-1164,1151,1142,1138,1137,1137,1137,1135,1131,1126,1122,1121,1126,1136,1152,1172,1194,1217,1237,1252,1262,
-1265,1260,1247,1225,1195,1158,1115,1069,1023,980,944,915,894,882,875,872,871,870,868,866,864,
-864,865,869,875,882,888,892,895,895,894,892,891,890,890,891,893,895,897,900,903,908,
-915,924,935,946,958,968,977,982,985,985,983,979,975,970,965,960,955,951,946,942,938,
-934,929,925,920,915,910,905,901,896,892,888,884,880,876,872,867,864,860,859,858,859,
-861,863,866,867,867,866,863,857,851,843,835,827,819,813,807,803,800,797,794,791,787,
-782,777,770,762,755,747,739,732,726,720,715,711,708,705,702,700,698,696,693,691,688,
-685,681,676,671,665,658,652,646,641,637,635,635,636,638,640,642,643,644,643,643,643,
-644,646,649,654,660,665,670,674,677,679,680,683,686,691,696,702,708,713,715,716,716,
-714,713,713,714,715,718,720,721,721,719,715,711,706,704,703,705,710,718,727,738,749,
-762,774,786,798,810,820,830,838,844,850,856,862,869,878,890,902,917,933,949,966,982,
-998,1014,1028,1040,1050,1058,1062,1064,1063,1063,1063,1064,1068,1074,1083,1093,1105,1116,1126,1135,1144,
-1152,1160,1170,1182,1196,1212,1227,1242,1255,1264,1271,1276,1279,1283,1289,1297,1309,1324,1342,1362,1384,
-1405,1424,1442,1457,1469,1476,1481,1483,1483,1483,1485,1490,1500,1513,1529,1546,1561,1571,1576,1574,1565,
-1551,1535,1520,1510,1506,1509,1519,1533,1549,1563,1574,1578,1577,1570,1559,1547,1536,1528,1524,1524,1527,
-1532,1539,1545,1549,1552,1554,1554,1555,1555,1557,1558,1559,1559,1557,1554,1548,1541,1534,1526,1519,1513,
-1510,1507,1507,1508,1511,1515,1521,1529,1539,1551,1564,1579,1594,1610,1626,1641,1656,1671,1685,1699,1713,
-1726,1739,1752,1766,1778,1791,1801,1810,1815,1817,1817,1814,1814,1819,1834,1861,1903,1958,2023,2092,2157,
-2211,2247,2263,2258,2236,2206,2176,2154,2146,2155,2180,2217,2258,2297,2327,2345,2350,2346,2336,2327,2324,
-2331,2348,2376,2411,2450,2489,2523,2551,2572,2584,2591,2591,2588,2584,2577,2571,2564,2556,2546,2536,2524,
-2512,2502,2497,2499,2512,2539,2579,2633,2697,2768,2839,2907,2965,3011,3046,3069,3086,3099,3113,3132,3158,
-3190,3229,3271,3314,3357,3398,3437,3476,3516,3558,3604,3655,3711,3772,3836,3900,3963,4021,4071,4110,4134,
-4142,4131,4100,4049,3981,3899,3808,3713,3620,3535,3461,3402,3358,3327,3307,3294,3283,3272,3258,3239,3216,
-3191,3165,3139,3116,3095,3075,3055,3035,3013,2991,2969,2948,2931,2917,2906,2897,2887,2875,2858,2836,2809,
-2780,2751,2727,2707,2693,2682,2673,2660,2641,2614,2580,2541,2501,2466,2439,2423,2418,2422,2431,2442,2449,
-2451,2445,2434,2418,2401,2382,2364,2345,2324,2299,2270,2235,2195,2154,2112,2073,2038,2008,1982,1959,1938,
-1918,1898,1880,1864,1853,1847,1848,1856,1869,1883,1896,1904,1904,1894,1874,1844,1807,1765,1722,1682,1647,
-1620,1602,1591,1586,1584,1583,1579,1571,1557,1539,1518,1496,1478,1463,1454,1450,1447,1442,1430,1409,1376,
-1331,1274,1212,1148,1090,1043,1012,998,1001,1019,1045,1074,1098,1112,1112,1099,1073,1039,1005,977,959,
-955,964,982,1001,1014,1013,992,950,889,815,736,662,599,552,520,501,487,470,444,405,352,
-291,227,167,119,85,67,59,56,49,33,4,-37,-89,-144,-197,-241,-274,-297,-314,-332,-358,
--396,-449,-516,-592,-672,-747,-814,-869,-911,-943,-968,-992,-1016,-1044,-1074,-1105,-1135,-1163,-1187,-1209,-1231,
--1255,-1284,-1318,-1356,-1398,-1441,-1481,-1518,-1552,-1583,-1614,-1646,-1682,-1722,-1764,-1804,-1840,-1868,-1886,-1891,-1884,
--1868,-1844,-1815,-1784,-1753,-1725,-1704,-1693,-1696,-1717,-1761,-1827,-1915,-2019,-2133,-2246,-2349,-2434,-2498,-2539,-2562,
--2573,-2580,-2591,-2609,-2637,-2672,-2709,-2744,-2771,-2789,-2797,-2798,-2798,-2802,-2813,-2832,-2859,-2889,-2918,-2940,-2953,
--2954,-2945,-2931,-2914,-2899,-2891,-2892,-2900,-2916,-2937,-2963,-2991,-3021,-3055,-3093,-3136,-3185,-3240,-3298,-3357,-3415,
--3468,-3514,-3553,-3582,-3604,-3619,-3629,-3635,-3639,-3642,-3645,-3647,-3651,-3654,-3658,-3662,-3667,-3671,-3676,-3682,-3691,
--3702,-3718,-3738,-3763,-3793,-3826,-3860,-3894,-3926,-3955,-3979,-4000,-4017,-4032,-4046,-4058,-4068,-4077,-4083,-4086,-4084,
--4078,-4069,-4059,-4048,-4040,-4034,-4032,-4035,-4043,-4055,-4072,-4095,-4123,-4156,-4193,-4232,-4272,-4308,-4339,-4363,-4381,
--4393,-4404,-4418,-4439,-4470,-4512,-4564,-4623,-4684,-4740,-4789,-4826,-4851,-4867,-4876,-4884,-4893,-4906,-4925,-4946,-4969,
--4991,-5008,-5019,-5023,-5022,-5017,-5010,-5002,-4995,-4988,-4982,-4977,-4971,-4966,-4962,-4960,-4961,-4965,-4971,-4979,-4988,
--4995,-5000,-5000,-4996,-4988,-4976,-4962,-4947,-4935,-4926,-4923,-4927,-4939,-4958,-4983,-5012,-5043,-5071,-5096,-5113,-5124,
--5127,-5126,-5123,-5121,-5123,-5130,-5143,-5161,-5181,-5200,-5217,-5227,-5230,-5226,-5215,-5200,-5182,-5162,-5144,-5128,-5115,
--5107,-5104,-5107,-5116,-5132,-5154,-5180,-5208,-5237,-5263,-5284,-5301,-5312,-5319,-5324,-5329,-5334,-5342,-5353,-5366,-5379,
--5392,-5404,-5414,-5423,-5432,-5441,-5453,-5468,-5487,-5507,-5529,-5550,-5569,-5585,-5597,-5606,-5612,-5617,-5622,-5628,-5636,
--5646,-5657,-5669,-5680,-5691,-5700,-5708,-5716,-5724,-5733,-5744,-5757,-5771,-5787,-5801,-5811,-5818,-5818,-5812,-5801,-5788,
--5775,-5767,-5766,-5774,-5791,-5816,-5846,-5878,-5908,-5931,-5948,-5957,-5959,-5955,-5949,-5941,-5933,-5922,-5909,-5893,-5871,
--5843,-5812,-5779,-5747,-5719,-5697,-5683,-5677,-5676,-5679,-5682,-5683,-5681,-5676,-5669,-5660,-5651,-5644,-5639,-5635,-5632,
--5628,-5623,-5617,-5609,-5601,-5593,-5586,-5581,-5578,-5577,-5575,-5574,-5570,-5565,-5558,-5549,-5539,-5528,-5517,-5507,-5497,
--5488,-5481,-5474,-5469,-5465,-5461,-5458,-5454,-5451,-5446,-5441,-5436,-5431,-5428,-5426,-5426,-5428,-5430,-5433,-5434,-5434,
--5431,-5426,-5419,-5412,-5405,-5399,-5393,-5388,-5383,-5376,-5368,-5358,-5346,-5334,-5323,-5313,-5305,-5300,-5297,-5295,-5293,
--5290,-5285,-5279,-5271,-5262,-5252,-5243,-5233,-5223,-5214,-5203,-5193,-5181,-5170,-5159,-5150,-5142,-5135,-5128,-5121,-5112,
--5102,-5089,-5073,-5056,-5039,-5023,-5007,-4994,-4982,-4971,-4959,-4945,-4930,-4913,-4894,-4875,-4856,-4838,-4823,-4809,-4798,
--4787,-4775,-4763,-4749,-4734,-4719,-4703,-4690,-4678,-4669,-4662,-4657,-4653,-4650,-4646,-4640,-4633,-4626,-4617,-4607,-4598,
--4588,-4577,-4565,-4553,-4539,-4523,-4507,-4490,-4472,-4454,-4436,-4418,-4400,-4382,-4364,-4346,-4329,-4313,-4298,-4284,-4271,
--4258,-4245,-4231,-4216,-4198,-4179,-4159,-4137,-4114,-4091,-4068,-4046,-4023,-4001,-3979,-3958,-3937,-3916,-3896,-3877,-3860,
--3843,-3827,-3812,-3798,-3784,-3770,-3756,-3743,-3729,-3716,-3703,-3691,-3680,-3669,-3660,-3652,-3645,-3639,-3633,-3627,-3620,
--3613,-3605,-3597,-3588,-3579,-3571,-3562,-3554,-3545,-3536,-3525,-3514,-3501,-3487,-3473,-3458,-3444,-3431,-3420,-3409,-3399,
--3389,-3379,-3367,-3354,-3340,-3324,-3307,-3290,-3273,-3256,-3240,-3225,-3211,-3197,-3183,-3169,-3156,-3142,-3128,-3113,-3097,
--3080,-3062,-3043,-3024,-3004,-2984,-2966,-2948,-2933,-2919,-2908,-2898,-2891,-2885,-2880,-2876,-2872,-2868,-2863,-2857,-2850,
--2841,-2831,-2820,-2807,-2794,-2781,-2768,-2757,-2748,-2741,-2736,-2734,-2731,-2729,-2725,-2719,-2710,-2696,-2680,-2661,-2641,
--2621,-2602,-2585,-2570,-2556,-2543,-2530,-2517,-2503,-2489,-2475,-2460,-2445,-2428,-2411,-2391,-2368,-2343,-2315,-2286,-2257,
--2230,-2206,-2186,-2170,-2158,-2147,-2137,-2126,-2112,-2096,-2078,-2058,-2038,-2018,-1998,-1979,-1961,-1941,-1920,-1897,-1872,
--1845,-1818,-1790,-1763,-1739,-1716,-1695,-1676,-1657,-1638,-1617,-1595,-1570,-1542,-1512,-1480,-1449,-1419,-1391,-1367,-1347,
--1331,-1317,-1304,-1291,-1276,-1258,-1237,-1213,-1188,-1162,-1137,-1114,-1094,-1076,-1059,-1044,-1028,-1012,-996,-978,-960,
--941,-922,-901,-880,-856,-829,-800,-767,-733,-697,-662,-628,-595,-564,-534,-504,-473,-440,-404,-364,-321,
--276,-227,-176,-123,-68,-11,47,106,164,218,268,310,343,369,387,400,413,429,452,485,529,
-583,644,707,767,818,855,878,886,883,871,858,847,842,844,853,868,884,898,910,917,922,
-926,932,943,958,979,1004,1029,1052,1070,1082,1087,1088,1085,1081,1078,1076,1076,1076,1076,1074,1071,
-1066,1062,1059,1061,1067,1079,1095,1114,1133,1152,1167,1178,1184,1182,1174,1158,1135,1103,1066,1023,978,
-933,892,858,831,814,804,801,801,803,806,807,807,806,806,808,811,816,822,828,833,837,
-839,840,841,841,842,843,844,845,847,847,848,850,853,857,864,873,883,894,904,912,918,
-922,922,921,917,913,908,903,899,894,890,886,882,879,876,873,871,869,868,866,865,863,
-860,857,853,849,844,840,836,832,829,826,823,821,819,817,816,814,812,810,807,804,799,
-794,788,782,775,767,761,755,750,746,743,741,739,736,733,729,724,718,711,705,698,691,
-685,680,676,672,669,665,662,658,655,651,647,643,640,637,635,632,630,627,624,621,617,
-614,611,609,609,609,611,613,616,619,622,625,628,632,636,641,647,653,659,665,670,674,
-676,678,680,682,683,686,689,691,694,695,695,695,694,693,693,693,694,696,697,698,698,
-696,694,691,688,686,686,688,692,698,707,716,727,738,750,762,774,786,797,808,817,826,
-833,840,846,853,862,872,884,897,911,926,941,956,972,988,1005,1021,1036,1049,1059,1067,1072,
-1073,1074,1075,1076,1080,1086,1095,1105,1109,1119,1129,1137,1143,1148,1153,1158,1164,1173,1184,1196,1208,
-1221,1232,1241,1250,1257,1264,1272,1282,1294,1308,1325,1345,1365,1387,1408,1428,1445,1459,1468,1472,1473,
-1472,1470,1469,1473,1482,1496,1516,1537,1558,1575,1585,1585,1576,1558,1535,1511,1490,1475,1469,1472,1484,
-1501,1519,1536,1549,1555,1555,1549,1540,1529,1519,1512,1508,1506,1507,1509,1511,1513,1515,1517,1519,1522,
-1527,1531,1536,1539,1540,1539,1535,1529,1522,1515,1509,1504,1501,1500,1499,1500,1500,1502,1505,1510,1518,
-1528,1542,1559,1577,1595,1612,1627,1639,1649,1658,1666,1675,1685,1697,1711,1727,1742,1758,1772,1783,1792,
-1798,1803,1807,1814,1825,1844,1873,1914,1966,2028,2095,2160,2218,2261,2287,2291,2277,2249,2214,2182,2159,
-2153,2166,2197,2242,2293,2343,2385,2414,2428,2430,2423,2412,2405,2405,2415,2437,2467,2502,2538,2570,2595,
-2610,2614,2610,2598,2581,2563,2545,2529,2515,2504,2495,2487,2480,2474,2471,2472,2479,2496,2525,2566,2618,
-2681,2749,2818,2883,2939,2983,3013,3032,3041,3046,3053,3066,3090,3126,3174,3233,3298,3365,3429,3487,3538,
-3581,3618,3651,3684,3721,3764,3813,3869,3928,3987,4040,4083,4110,4119,4106,4071,4017,3946,3864,3776,3688,
-3606,3534,3474,3428,3396,3374,3359,3348,3337,3324,3307,3287,3264,3240,3216,3195,3176,3158,3141,3123,3101,
-3077,3049,3020,2992,2967,2946,2931,2919,2910,2900,2889,2874,2855,2834,2812,2791,2774,2760,2748,2736,2721,
-2701,2674,2641,2604,2566,2531,2503,2483,2472,2467,2465,2462,2454,2439,2417,2388,2355,2319,2283,2249,2217,
-2185,2154,2122,2090,2058,2028,2001,1978,1960,1946,1934,1923,1910,1895,1877,1858,1840,1826,1819,1820,1830,
-1846,1865,1884,1897,1901,1894,1876,1848,1812,1772,1732,1695,1663,1638,1619,1605,1593,1583,1571,1557,1541,
-1522,1503,1486,1471,1461,1455,1453,1453,1453,1448,1435,1412,1376,1329,1273,1210,1148,1091,1045,1015,1003,
-1010,1032,1064,1099,1130,1150,1156,1145,1121,1088,1055,1029,1017,1021,1040,1071,1104,1130,1139,1126,1087,
-1026,947,862,779,708,654,616,592,574,555,527,488,437,377,317,263,221,194,180,177,174,
-166,146,109,58,-3,-69,-133,-189,-234,-270,-300,-332,-370,-420,-483,-557,-636,-715,-788,-850,-898,
--934,-960,-982,-1001,-1023,-1047,-1073,-1100,-1125,-1148,-1169,-1189,-1210,-1235,-1264,-1299,-1337,-1376,-1414,-1447,-1477,
--1503,-1529,-1556,-1588,-1627,-1671,-1719,-1766,-1809,-1842,-1863,-1872,-1868,-1854,-1832,-1806,-1776,-1746,-1718,-1695,-1680,
--1678,-1694,-1732,-1792,-1875,-1975,-2084,-2193,-2294,-2376,-2438,-2478,-2501,-2513,-2522,-2535,-2556,-2585,-2621,-2658,-2690,
--2715,-2730,-2737,-2741,-2746,-2758,-2779,-2809,-2847,-2885,-2919,-2942,-2951,-2946,-2929,-2906,-2881,-2861,-2849,-2847,-2855,
--2869,-2888,-2911,-2936,-2964,-2997,-3037,-3086,-3143,-3206,-3271,-3334,-3391,-3438,-3473,-3496,-3510,-3518,-3523,-3529,-3537,
--3550,-3565,-3582,-3599,-3615,-3628,-3639,-3647,-3654,-3659,-3665,-3671,-3679,-3689,-3701,-3716,-3735,-3758,-3786,-3818,-3853,
--3889,-3926,-3960,-3991,-4017,-4039,-4055,-4068,-4077,-4084,-4088,-4090,-4089,-4086,-4081,-4074,-4066,-4058,-4051,-4046,-4044,
--4047,-4057,-4072,-4095,-4125,-4161,-4202,-4244,-4285,-4322,-4354,-4378,-4395,-4408,-4419,-4434,-4457,-4490,-4534,-4588,-4649,
--4711,-4769,-4818,-4855,-4879,-4891,-4896,-4899,-4903,-4913,-4930,-4954,-4984,-5015,-5045,-5070,-5087,-5097,-5100,-5096,-5089,
--5081,-5072,-5065,-5060,-5056,-5053,-5053,-5053,-5055,-5059,-5064,-5070,-5076,-5083,-5088,-5090,-5088,-5081,-5069,-5052,-5032,
--5010,-4989,-4972,-4962,-4961,-4970,-4990,-5018,-5052,-5089,-5125,-5156,-5180,-5195,-5203,-5205,-5203,-5200,-5201,-5205,-5215,
--5231,-5250,-5271,-5291,-5308,-5320,-5324,-5321,-5311,-5295,-5274,-5250,-5228,-5208,-5195,-5188,-5190,-5200,-5217,-5238,-5260,
--5282,-5300,-5314,-5323,-5329,-5334,-5340,-5347,-5359,-5373,-5390,-5408,-5425,-5439,-5451,-5460,-5467,-5475,-5484,-5496,-5512,
--5531,-5552,-5574,-5596,-5614,-5630,-5641,-5650,-5657,-5664,-5671,-5680,-5691,-5703,-5716,-5728,-5739,-5748,-5754,-5759,-5763,
--5768,-5775,-5784,-5797,-5812,-5828,-5842,-5851,-5855,-5851,-5839,-5820,-5799,-5778,-5762,-5755,-5758,-5774,-5799,-5832,-5869,
--5906,-5939,-5966,-5988,-6004,-6016,-6025,-6034,-6041,-6046,-6046,-6039,-6023,-5999,-5966,-5927,-5887,-5847,-5813,-5787,-5769,
--5759,-5754,-5752,-5751,-5748,-5743,-5736,-5727,-5719,-5712,-5706,-5702,-5700,-5697,-5694,-5688,-5682,-5673,-5664,-5655,-5647,
--5640,-5634,-5630,-5626,-5623,-5620,-5616,-5611,-5605,-5598,-5589,-5579,-5567,-5555,-5542,-5530,-5520,-5511,-5504,-5499,-5496,
--5493,-5490,-5487,-5484,-5481,-5478,-5477,-5478,-5480,-5483,-5487,-5490,-5492,-5492,-5490,-5486,-5481,-5475,-5470,-5465,-5461,
--5456,-5450,-5443,-5434,-5423,-5411,-5400,-5390,-5381,-5376,-5372,-5370,-5369,-5368,-5365,-5361,-5355,-5348,-5340,-5330,-5320,
--5309,-5298,-5285,-5272,-5258,-5244,-5230,-5218,-5208,-5198,-5190,-5181,-5172,-5160,-5147,-5132,-5115,-5099,-5083,-5070,-5058,
--5048,-5039,-5029,-5019,-5006,-4991,-4974,-4955,-4937,-4920,-4904,-4889,-4876,-4864,-4851,-4836,-4821,-4804,-4787,-4770,-4754,
--4741,-4730,-4721,-4714,-4709,-4704,-4699,-4693,-4686,-4678,-4669,-4660,-4651,-4640,-4629,-4616,-4601,-4585,-4568,-4550,-4531,
--4512,-4493,-4475,-4456,-4438,-4420,-4401,-4384,-4366,-4349,-4333,-4318,-4304,-4289,-4275,-4258,-4241,-4221,-4200,-4177,-4153,
--4129,-4106,-4084,-4063,-4042,-4023,-4004,-3985,-3966,-3947,-3929,-3910,-3893,-3875,-3859,-3843,-3827,-3812,-3797,-3783,-3769,
--3755,-3741,-3729,-3717,-3705,-3695,-3685,-3676,-3667,-3659,-3652,-3644,-3637,-3629,-3622,-3614,-3607,-3599,-3592,-3584,-3576,
--3568,-3558,-3546,-3533,-3519,-3503,-3488,-3472,-3458,-3444,-3432,-3420,-3409,-3397,-3384,-3371,-3356,-3340,-3325,-3309,-3295,
--3280,-3266,-3252,-3237,-3222,-3205,-3189,-3172,-3156,-3142,-3129,-3118,-3107,-3096,-3083,-3070,-3054,-3036,-3018,-2999,-2982,
--2967,-2954,-2943,-2935,-2928,-2921,-2915,-2909,-2902,-2895,-2888,-2882,-2877,-2871,-2866,-2859,-2850,-2840,-2828,-2815,-2803,
--2791,-2782,-2775,-2770,-2766,-2762,-2755,-2746,-2733,-2716,-2696,-2676,-2655,-2636,-2619,-2603,-2589,-2575,-2561,-2545,-2528,
--2510,-2491,-2474,-2457,-2441,-2427,-2412,-2396,-2378,-2356,-2331,-2305,-2277,-2251,-2227,-2206,-2188,-2174,-2161,-2148,-2134,
--2119,-2102,-2084,-2065,-2046,-2027,-2009,-1990,-1972,-1952,-1930,-1907,-1882,-1855,-1829,-1802,-1777,-1752,-1728,-1705,-1682,
--1661,-1639,-1618,-1596,-1575,-1553,-1530,-1506,-1481,-1456,-1430,-1405,-1382,-1360,-1341,-1323,-1306,-1290,-1273,-1255,-1235,
--1214,-1193,-1172,-1152,-1133,-1115,-1099,-1082,-1066,-1049,-1032,-1014,-996,-978,-960,-943,-925,-904,-881,-853,-821,
--785,-746,-707,-668,-632,-598,-569,-541,-513,-484,-451,-412,-367,-315,-258,-197,-133,-68,-4,56,113,
-165,210,249,281,306,325,339,353,369,390,419,458,507,562,622,681,734,776,806,822,825,
-820,810,800,793,793,800,811,826,840,853,861,866,869,871,876,884,896,911,929,946,961,
-973,981,985,988,990,993,997,1001,1005,1007,1006,1003,996,989,983,981,985,995,1011,1032,1055,
-1077,1096,1110,1117,1117,1110,1096,1075,1048,1015,977,935,892,851,813,781,757,741,733,731,734,
-739,745,750,754,758,762,765,770,775,780,785,789,793,795,796,797,798,799,801,802,803,
-803,803,802,802,802,804,808,814,822,830,837,843,847,849,848,845,842,839,836,834,833,
-833,833,833,832,831,830,828,827,826,825,823,822,819,817,813,809,805,801,798,796,794,
-792,791,789,786,783,778,773,768,764,759,755,752,749,745,741,736,729,722,714,706,698,
-691,685,680,676,673,669,666,662,657,652,647,641,636,632,628,626,624,622,620,619,616,
-614,610,607,604,601,598,597,596,596,597,597,597,596,595,593,592,591,591,591,593,596,
-600,604,609,614,620,625,630,636,641,646,651,655,659,662,664,666,668,670,671,673,674,
-674,674,674,673,673,673,674,675,676,677,678,677,676,674,671,668,667,666,667,670,674,
-680,688,696,706,716,728,741,754,767,780,792,802,812,820,828,836,844,855,866,879,893,
-908,923,937,952,967,982,998,1014,1029,1043,1055,1064,1070,1074,1076,1077,1080,1084,1090,1099,1109,
-1092,1103,1112,1119,1125,1129,1133,1137,1143,1150,1160,1171,1183,1195,1207,1217,1226,1234,1242,1250,1259,
-1270,1282,1297,1315,1334,1355,1375,1395,1413,1428,1438,1444,1446,1445,1443,1443,1447,1458,1474,1497,1523,
-1549,1572,1587,1591,1585,1567,1541,1512,1483,1460,1446,1442,1448,1463,1482,1502,1519,1532,1538,1537,1531,
-1522,1510,1499,1488,1479,1472,1467,1464,1463,1464,1468,1475,1484,1495,1506,1516,1523,1527,1527,1524,1518,
-1511,1505,1501,1498,1498,1500,1503,1506,1509,1512,1517,1523,1532,1544,1559,1577,1595,1612,1626,1637,1644,
-1648,1651,1654,1660,1668,1680,1694,1710,1726,1740,1752,1761,1767,1772,1778,1787,1801,1824,1855,1898,1949,
-2009,2074,2139,2201,2252,2290,2311,2315,2303,2280,2252,2225,2208,2205,2218,2247,2290,2339,2390,2435,2469,
-2491,2500,2499,2492,2484,2479,2481,2491,2508,2529,2551,2570,2583,2588,2584,2572,2554,2533,2512,2494,2480,
-2472,2469,2470,2475,2481,2488,2494,2501,2509,2521,2539,2565,2599,2643,2693,2748,2804,2856,2901,2936,2962,
-2979,2992,3005,3023,3051,3093,3148,3216,3292,3372,3448,3517,3573,3616,3647,3669,3687,3707,3733,3767,3811,
-3861,3913,3962,4000,4022,4024,4005,3965,3908,3838,3763,3687,3617,3556,3507,3469,3443,3424,3410,3398,3384,
-3368,3347,3323,3297,3270,3246,3224,3205,3188,3173,3156,3138,3116,3090,3062,3033,3007,2985,2967,2955,2947,
-2940,2931,2919,2902,2880,2855,2830,2806,2786,2770,2758,2747,2734,2717,2693,2664,2629,2593,2558,2528,2505,
-2488,2477,2467,2456,2439,2415,2382,2342,2296,2249,2202,2158,2119,2083,2052,2023,1997,1972,1950,1931,1914,
-1901,1889,1878,1865,1849,1830,1807,1784,1762,1746,1737,1739,1750,1770,1794,1818,1838,1849,1849,1837,1815,
-1785,1751,1716,1683,1654,1630,1610,1592,1576,1560,1543,1525,1506,1487,1470,1455,1444,1435,1430,1426,1421,
-1415,1405,1389,1366,1335,1296,1250,1200,1148,1100,1060,1031,1016,1016,1029,1052,1080,1105,1121,1125,1116,
-1093,1063,1031,1007,994,998,1018,1049,1085,1116,1132,1127,1099,1048,981,906,832,767,716,679,653,
-631,608,577,536,484,426,367,314,273,244,227,217,206,189,159,116,59,-4,-71,-134,-189,
--235,-272,-307,-343,-388,-442,-508,-582,-659,-733,-800,-855,-898,-931,-956,-979,-1002,-1027,-1055,-1084,-1112,
--1138,-1161,-1181,-1199,-1219,-1243,-1271,-1304,-1340,-1376,-1410,-1440,-1467,-1490,-1513,-1539,-1570,-1608,-1650,-1695,-1739,
--1776,-1805,-1822,-1828,-1824,-1814,-1800,-1783,-1768,-1753,-1741,-1733,-1731,-1738,-1757,-1792,-1845,-1914,-1996,-2086,-2175,
--2256,-2324,-2375,-2410,-2432,-2447,-2462,-2482,-2508,-2541,-2577,-2611,-2639,-2657,-2666,-2668,-2668,-2673,-2686,-2710,-2745,
--2786,-2828,-2865,-2890,-2902,-2900,-2887,-2869,-2852,-2841,-2838,-2844,-2857,-2874,-2893,-2912,-2931,-2952,-2979,-3013,-3058,
--3112,-3174,-3240,-3304,-3361,-3407,-3441,-3463,-3475,-3483,-3489,-3498,-3511,-3528,-3549,-3571,-3592,-3610,-3625,-3638,-3647,
--3655,-3663,-3669,-3676,-3681,-3687,-3692,-3698,-3707,-3721,-3742,-3770,-3806,-3847,-3891,-3935,-3976,-4011,-4039,-4059,-4072,
--4079,-4083,-4085,-4085,-4085,-4084,-4083,-4080,-4076,-4072,-4068,-4066,-4067,-4074,-4086,-4105,-4130,-4162,-4197,-4236,-4276,
--4315,-4351,-4383,-4411,-4434,-4455,-4475,-4497,-4524,-4558,-4598,-4645,-4697,-4749,-4798,-4840,-4874,-4897,-4911,-4919,-4924,
--4930,-4942,-4960,-4986,-5018,-5053,-5088,-5119,-5143,-5159,-5166,-5165,-5160,-5152,-5146,-5142,-5142,-5145,-5151,-5159,-5166,
--5171,-5173,-5173,-5169,-5164,-5158,-5151,-5144,-5137,-5128,-5117,-5102,-5085,-5065,-5044,-5024,-5009,-5001,-5002,-5013,-5034,
--5064,-5100,-5138,-5175,-5208,-5233,-5251,-5262,-5266,-5268,-5269,-5271,-5278,-5289,-5306,-5326,-5348,-5371,-5390,-5404,-5412,
--5412,-5404,-5389,-5370,-5350,-5331,-5316,-5308,-5307,-5312,-5323,-5337,-5352,-5364,-5374,-5379,-5381,-5382,-5383,-5387,-5394,
--5407,-5422,-5441,-5459,-5476,-5490,-5501,-5509,-5515,-5522,-5532,-5544,-5560,-5579,-5599,-5620,-5638,-5654,-5666,-5675,-5682,
--5688,-5694,-5702,-5712,-5724,-5737,-5751,-5764,-5775,-5784,-5791,-5797,-5802,-5807,-5815,-5824,-5836,-5849,-5862,-5872,-5878,
--5878,-5871,-5857,-5838,-5817,-5797,-5782,-5776,-5780,-5795,-5820,-5852,-5888,-5924,-5957,-5986,-6010,-6031,-6049,-6066,-6084,
--6101,-6117,-6130,-6137,-6136,-6124,-6103,-6074,-6038,-6000,-5963,-5928,-5899,-5875,-5856,-5841,-5828,-5816,-5804,-5793,-5782,
--5772,-5763,-5757,-5752,-5749,-5746,-5743,-5739,-5734,-5728,-5721,-5714,-5707,-5700,-5694,-5688,-5683,-5679,-5676,-5673,-5670,
--5667,-5662,-5656,-5647,-5637,-5624,-5609,-5594,-5580,-5567,-5556,-5548,-5542,-5537,-5533,-5529,-5526,-5523,-5521,-5521,-5522,
--5526,-5532,-5539,-5546,-5551,-5554,-5555,-5553,-5549,-5543,-5537,-5532,-5526,-5521,-5516,-5510,-5504,-5496,-5487,-5478,-5470,
--5462,-5456,-5451,-5448,-5445,-5441,-5438,-5433,-5427,-5421,-5414,-5407,-5399,-5391,-5382,-5371,-5360,-5346,-5332,-5317,-5303,
--5288,-5275,-5262,-5250,-5237,-5224,-5210,-5195,-5180,-5164,-5150,-5137,-5126,-5116,-5107,-5098,-5089,-5077,-5064,-5049,-5033,
--5015,-4998,-4982,-4966,-4951,-4936,-4921,-4905,-4888,-4871,-4854,-4837,-4822,-4808,-4796,-4785,-4776,-4768,-4760,-4752,-4743,
--4735,-4726,-4717,-4707,-4697,-4686,-4674,-4660,-4644,-4626,-4607,-4587,-4567,-4548,-4529,-4511,-4494,-4477,-4461,-4444,-4427,
--4409,-4392,-4375,-4357,-4340,-4322,-4304,-4285,-4265,-4243,-4221,-4198,-4174,-4151,-4129,-4107,-4087,-4067,-4048,-4030,-4012,
--3995,-3977,-3960,-3943,-3927,-3910,-3894,-3877,-3861,-3844,-3827,-3811,-3794,-3779,-3764,-3750,-3737,-3725,-3715,-3705,-3695,
--3686,-3677,-3667,-3658,-3647,-3637,-3627,-3617,-3608,-3600,-3593,-3586,-3580,-3572,-3564,-3554,-3542,-3529,-3515,-3500,-3485,
--3471,-3458,-3445,-3432,-3419,-3405,-3391,-3376,-3360,-3345,-3330,-3317,-3304,-3292,-3280,-3266,-3251,-3233,-3214,-3194,-3175,
--3158,-3144,-3133,-3126,-3121,-3116,-3110,-3102,-3090,-3075,-3058,-3039,-3022,-3006,-2993,-2984,-2976,-2970,-2964,-2957,-2949,
--2940,-2930,-2921,-2913,-2906,-2900,-2895,-2888,-2881,-2871,-2860,-2847,-2834,-2821,-2810,-2801,-2793,-2785,-2778,-2768,-2755,
--2740,-2722,-2703,-2683,-2665,-2649,-2635,-2622,-2610,-2595,-2579,-2560,-2538,-2516,-2494,-2474,-2457,-2443,-2432,-2421,-2410,
--2397,-2380,-2359,-2335,-2310,-2284,-2260,-2237,-2218,-2201,-2185,-2170,-2154,-2137,-2119,-2101,-2083,-2065,-2048,-2031,-2014,
--1995,-1975,-1952,-1927,-1901,-1873,-1846,-1818,-1790,-1763,-1736,-1710,-1685,-1660,-1637,-1616,-1597,-1580,-1563,-1547,-1530,
--1512,-1491,-1469,-1445,-1420,-1396,-1374,-1354,-1336,-1319,-1303,-1286,-1268,-1248,-1228,-1207,-1186,-1167,-1148,-1131,-1115,
--1098,-1081,-1064,-1045,-1026,-1007,-989,-972,-955,-937,-917,-894,-867,-836,-801,-765,-728,-692,-658,-626,-596,
--566,-533,-496,-453,-403,-346,-285,-220,-155,-92,-32,21,70,113,151,184,213,238,262,284,307,
-333,363,399,441,488,539,590,638,680,714,737,750,755,755,752,752,754,761,772,785,799,
-811,822,829,836,842,850,860,873,888,902,915,924,928,927,922,915,910,907,908,912,919,
-925,930,930,926,919,911,905,903,908,922,942,967,995,1020,1041,1054,1058,1053,1040,1019,992,
-961,926,889,851,813,777,745,718,697,682,674,671,672,677,683,690,698,705,713,720,728,
-735,742,748,753,757,759,760,761,762,763,764,765,766,765,763,761,758,756,755,755,757,
-760,763,767,768,769,767,765,762,759,758,758,761,765,770,775,779,783,784,785,784,783,
-781,778,776,774,771,768,765,762,759,756,755,754,754,755,755,755,753,750,745,739,732,
-725,719,713,708,703,698,693,687,680,672,663,653,643,634,625,618,612,607,603,600,597,
-593,590,586,582,578,575,573,571,570,570,571,572,572,572,572,570,568,566,565,563,563,
-563,563,564,565,566,566,566,566,565,565,566,568,571,575,580,586,592,598,604,609,614,
-618,623,627,630,634,637,641,644,646,649,650,652,652,653,653,653,653,654,654,655,656,
-656,656,656,654,653,651,649,648,648,650,652,656,660,666,673,681,690,701,714,728,742,
-756,770,782,792,800,808,814,821,830,841,854,869,885,903,920,937,953,968,982,996,1008,
-1019,1029,1036,1042,1046,1048,1050,1053,1057,1063,1072,1082,1092,1066,1078,1088,1096,1101,1106,1110,1115,
-1121,1130,1140,1151,1163,1174,1185,1195,1203,1211,1218,1225,1233,1242,1253,1265,1279,1295,1311,1329,1347,
-1364,1379,1390,1398,1403,1405,1405,1407,1411,1422,1438,1461,1488,1517,1543,1562,1572,1571,1558,1536,1509,
-1480,1455,1437,1428,1429,1439,1454,1473,1490,1503,1510,1510,1505,1494,1480,1465,1450,1436,1424,1416,1411,
-1410,1415,1423,1436,1452,1470,1487,1502,1512,1518,1519,1516,1510,1504,1499,1497,1498,1503,1509,1517,1525,
-1532,1538,1545,1552,1561,1572,1584,1598,1610,1621,1629,1633,1634,1634,1633,1636,1641,1651,1664,1680,1696,
-1710,1721,1728,1733,1736,1741,1750,1765,1790,1824,1868,1921,1980,2043,2106,2167,2222,2268,2304,2329,2342,
-2344,2338,2328,2318,2311,2312,2322,2341,2369,2403,2438,2471,2498,2516,2526,2528,2525,2518,2511,2507,2507,
-2511,2518,2527,2534,2537,2536,2529,2516,2500,2483,2467,2454,2447,2447,2454,2466,2483,2501,2519,2534,2546,
-2553,2559,2563,2571,2583,2602,2630,2665,2706,2750,2793,2833,2868,2898,2924,2949,2979,3016,3064,3125,3197,
-3277,3358,3436,3504,3558,3596,3620,3633,3640,3648,3662,3685,3717,3757,3799,3836,3863,3874,3865,3837,3791,
-3733,3668,3604,3546,3499,3464,3442,3431,3426,3424,3421,3414,3400,3379,3352,3320,3286,3252,3220,3190,3163,
-3138,3113,3088,3064,3039,3015,2995,2980,2972,2970,2974,2982,2988,2991,2986,2971,2946,2913,2875,2837,2804,
-2778,2761,2751,2746,2741,2732,2716,2692,2660,2623,2585,2548,2517,2491,2471,2453,2434,2411,2380,2342,2296,
-2245,2193,2141,2094,2053,2017,1987,1961,1938,1916,1895,1875,1855,1836,1818,1799,1780,1759,1737,1714,1692,
-1672,1659,1655,1660,1675,1699,1727,1756,1782,1799,1807,1804,1789,1767,1739,1707,1676,1647,1621,1596,1574,
-1554,1534,1514,1495,1477,1460,1444,1430,1417,1404,1391,1378,1363,1348,1332,1314,1295,1275,1251,1225,1195,
-1162,1127,1094,1065,1043,1031,1028,1033,1044,1056,1065,1064,1054,1032,1002,970,941,920,913,919,937,
-961,985,1001,1003,989,959,916,867,818,774,739,712,691,670,646,612,568,516,457,398,345,
-299,264,235,210,183,148,103,46,-18,-87,-154,-214,-264,-304,-337,-367,-400,-441,-491,-552,-619,
--689,-756,-816,-866,-906,-939,-968,-996,-1027,-1061,-1098,-1136,-1173,-1207,-1236,-1261,-1283,-1306,-1331,-1359,-1392,
--1426,-1461,-1495,-1525,-1553,-1578,-1603,-1631,-1662,-1696,-1733,-1769,-1801,-1824,-1839,-1842,-1837,-1825,-1811,-1797,-1788,
--1784,-1786,-1793,-1805,-1823,-1848,-1880,-1921,-1972,-2033,-2100,-2171,-2239,-2300,-2350,-2388,-2415,-2435,-2451,-2468,-2491,
--2518,-2550,-2582,-2611,-2632,-2644,-2648,-2647,-2645,-2648,-2661,-2685,-2718,-2758,-2798,-2833,-2858,-2872,-2876,-2872,-2866,
--2862,-2865,-2876,-2894,-2916,-2939,-2960,-2978,-2993,-3008,-3026,-3051,-3086,-3131,-3184,-3243,-3302,-3358,-3405,-3443,-3472,
--3494,-3513,-3531,-3550,-3571,-3595,-3619,-3641,-3661,-3678,-3691,-3701,-3709,-3715,-3720,-3724,-3724,-3721,-3715,-3706,-3698,
--3694,-3697,-3712,-3739,-3779,-3829,-3887,-3946,-4003,-4052,-4091,-4119,-4136,-4145,-4147,-4145,-4141,-4135,-4129,-4122,-4115,
--4108,-4103,-4100,-4102,-4109,-4123,-4143,-4168,-4197,-4229,-4263,-4296,-4329,-4362,-4394,-4426,-4458,-4490,-4521,-4551,-4581,
--4610,-4639,-4669,-4700,-4732,-4765,-4798,-4830,-4860,-4887,-4909,-4928,-4945,-4961,-4980,-5001,-5027,-5056,-5087,-5117,-5145,
--5166,-5181,-5187,-5188,-5185,-5182,-5182,-5187,-5198,-5215,-5235,-5256,-5272,-5283,-5285,-5277,-5262,-5242,-5218,-5195,-5176,
--5160,-5148,-5140,-5132,-5124,-5113,-5100,-5085,-5070,-5059,-5052,-5054,-5065,-5085,-5114,-5148,-5184,-5220,-5253,-5280,-5301,
--5317,-5328,-5337,-5345,-5354,-5366,-5381,-5399,-5420,-5442,-5462,-5480,-5494,-5501,-5502,-5498,-5489,-5478,-5466,-5457,-5452,
--5451,-5455,-5462,-5471,-5479,-5486,-5489,-5490,-5488,-5486,-5484,-5484,-5487,-5494,-5503,-5513,-5524,-5533,-5541,-5546,-5552,
--5557,-5565,-5575,-5589,-5606,-5624,-5643,-5660,-5676,-5687,-5696,-5702,-5707,-5712,-5718,-5726,-5736,-5748,-5760,-5773,-5784,
--5795,-5803,-5811,-5818,-5825,-5833,-5842,-5853,-5864,-5876,-5887,-5895,-5899,-5897,-5891,-5881,-5867,-5853,-5842,-5835,-5836,
--5845,-5863,-5888,-5918,-5950,-5982,-6011,-6036,-6057,-6073,-6088,-6101,-6115,-6131,-6147,-6163,-6177,-6186,-6190,-6186,-6174,
--6155,-6130,-6101,-6069,-6037,-6005,-5975,-5946,-5920,-5897,-5876,-5857,-5841,-5827,-5816,-5806,-5797,-5790,-5783,-5778,-5773,
--5769,-5767,-5765,-5763,-5762,-5761,-5758,-5755,-5751,-5746,-5741,-5736,-5731,-5727,-5723,-5717,-5711,-5702,-5691,-5679,-5664,
--5650,-5635,-5622,-5611,-5601,-5592,-5585,-5579,-5573,-5569,-5567,-5567,-5569,-5575,-5583,-5592,-5602,-5611,-5618,-5622,-5622,
--5620,-5615,-5609,-5603,-5597,-5592,-5587,-5582,-5577,-5571,-5565,-5558,-5550,-5543,-5536,-5529,-5523,-5517,-5511,-5504,-5497,
--5490,-5483,-5476,-5470,-5465,-5459,-5454,-5447,-5438,-5428,-5415,-5400,-5385,-5368,-5352,-5336,-5321,-5307,-5293,-5279,-5265,
--5251,-5238,-5225,-5212,-5201,-5190,-5180,-5170,-5159,-5147,-5134,-5120,-5104,-5087,-5070,-5053,-5035,-5018,-5000,-4983,-4966,
--4949,-4933,-4917,-4902,-4888,-4875,-4864,-4852,-4841,-4830,-4819,-4807,-4795,-4783,-4771,-4759,-4748,-4737,-4725,-4712,-4698,
--4682,-4664,-4646,-4626,-4607,-4588,-4570,-4552,-4536,-4520,-4503,-4487,-4470,-4453,-4435,-4416,-4397,-4378,-4358,-4338,-4317,
--4296,-4275,-4253,-4230,-4207,-4185,-4162,-4140,-4119,-4097,-4076,-4056,-4037,-4019,-4001,-3985,-3970,-3955,-3941,-3927,-3912,
--3896,-3879,-3862,-3843,-3825,-3806,-3789,-3773,-3759,-3747,-3736,-3727,-3719,-3711,-3702,-3693,-3682,-3670,-3657,-3644,-3631,
--3619,-3608,-3599,-3591,-3584,-3577,-3569,-3560,-3550,-3538,-3524,-3510,-3495,-3482,-3468,-3456,-3443,-3431,-3418,-3404,-3389,
--3374,-3359,-3345,-3332,-3319,-3307,-3294,-3280,-3264,-3246,-3226,-3206,-3187,-3171,-3159,-3151,-3147,-3146,-3145,-3143,-3138,
--3129,-3116,-3099,-3081,-3063,-3047,-3034,-3024,-3016,-3011,-3005,-2999,-2990,-2981,-2970,-2959,-2948,-2938,-2929,-2920,-2911,
--2901,-2890,-2877,-2863,-2849,-2835,-2823,-2812,-2803,-2794,-2784,-2773,-2759,-2744,-2727,-2710,-2693,-2679,-2665,-2653,-2642,
--2629,-2613,-2595,-2574,-2550,-2527,-2505,-2486,-2470,-2459,-2449,-2441,-2431,-2418,-2401,-2380,-2357,-2332,-2308,-2285,-2265,
--2247,-2232,-2218,-2203,-2188,-2172,-2155,-2136,-2118,-2099,-2080,-2061,-2039,-2016,-1990,-1962,-1931,-1899,-1867,-1836,-1807,
--1779,-1754,-1730,-1707,-1685,-1663,-1643,-1623,-1605,-1588,-1572,-1557,-1541,-1524,-1505,-1485,-1464,-1442,-1422,-1403,-1387,
--1371,-1357,-1341,-1324,-1304,-1282,-1257,-1232,-1207,-1183,-1162,-1144,-1127,-1112,-1096,-1080,-1061,-1042,-1022,-1001,-982,
--964,-948,-932,-915,-896,-875,-850,-823,-793,-760,-727,-692,-655,-615,-572,-524,-472,-414,-353,-291,-229,
--169,-114,-64,-19,20,56,89,121,152,183,213,244,274,305,338,373,411,451,493,535,575,
-611,640,664,680,692,700,707,715,725,737,752,767,782,796,809,821,834,848,864,883,902,
-920,934,941,941,932,916,896,876,858,846,840,842,847,855,861,864,863,857,850,844,842,
-847,860,880,905,931,956,975,985,986,977,958,933,902,868,834,799,765,734,706,681,660,
-643,631,623,619,618,620,623,628,634,642,651,660,671,681,691,700,707,713,716,719,720,
-722,723,723,723,722,720,717,712,706,701,695,691,687,685,684,684,683,681,679,677,675,
-674,676,679,684,691,699,706,713,718,721,722,722,722,721,720,719,719,719,718,717,716,
-715,713,713,712,713,713,714,713,712,709,705,699,691,683,675,666,657,649,640,632,624,
-615,605,596,586,576,567,558,551,545,541,537,535,533,531,529,527,525,522,519,517,515,
-514,514,515,517,519,521,523,524,525,524,524,522,521,521,520,521,521,522,523,524,525,
-526,528,530,532,536,540,545,551,557,564,570,576,582,587,592,597,602,606,610,614,618,
-621,624,627,629,630,631,632,633,633,633,633,633,633,631,630,629,628,627,628,629,631,
-635,640,645,651,658,665,674,683,694,706,719,733,748,761,773,783,791,796,800,804,809,
-816,826,839,856,874,894,914,933,951,966,978,987,994,997,999,999,999,998,999,1002,1007,
-1015,1026,1038,1052,1066,1040,1053,1063,1070,1074,1078,1082,1087,1094,1103,1114,1126,1138,1151,1162,1173,
-1184,1194,1203,1213,1223,1232,1241,1250,1260,1270,1281,1293,1307,1321,1335,1348,1358,1366,1371,1374,1377,
-1382,1391,1406,1426,1451,1479,1506,1528,1542,1547,1540,1525,1503,1478,1455,1436,1426,1424,1429,1440,1454,
-1466,1475,1479,1476,1468,1456,1440,1424,1410,1397,1388,1383,1383,1388,1398,1411,1428,1447,1467,1485,1500,
-1511,1516,1517,1515,1511,1507,1506,1507,1512,1521,1531,1542,1553,1562,1570,1576,1582,1588,1595,1601,1607,
-1612,1615,1615,1614,1611,1609,1609,1612,1620,1632,1648,1664,1680,1693,1703,1710,1716,1724,1736,1756,1785,
-1824,1872,1928,1987,2048,2107,2162,2212,2256,2294,2328,2356,2381,2401,2416,2428,2436,2442,2446,2449,2453,
-2458,2465,2473,2481,2488,2493,2495,2493,2488,2481,2474,2468,2464,2463,2464,2468,2472,2476,2479,2478,2474,
-2467,2459,2450,2444,2441,2444,2453,2468,2488,2510,2532,2552,2568,2579,2584,2586,2587,2590,2596,2609,2629,
-2655,2685,2719,2752,2783,2812,2840,2869,2903,2945,2998,3062,3135,3215,3296,3371,3435,3486,3520,3539,3549,
-3552,3557,3566,3584,3610,3642,3673,3699,3714,3712,3692,3655,3605,3547,3488,3436,3394,3367,3355,3356,3367,
-3381,3395,3404,3405,3395,3376,3347,3312,3272,3229,3186,3141,3098,3055,3013,2973,2937,2908,2887,2878,2881,
-2897,2922,2954,2987,3015,3033,3035,3022,2992,2951,2904,2857,2817,2787,2769,2762,2762,2764,2763,2753,2732,
-2701,2661,2615,2569,2526,2488,2456,2427,2398,2368,2332,2290,2243,2190,2137,2085,2038,1997,1961,1932,1905,
-1881,1856,1831,1805,1778,1752,1726,1703,1682,1662,1644,1628,1615,1605,1602,1605,1615,1634,1660,1690,1722,
-1751,1774,1790,1796,1791,1778,1758,1732,1704,1674,1644,1615,1586,1560,1534,1511,1490,1471,1453,1437,1422,
-1405,1387,1368,1346,1324,1304,1285,1271,1261,1254,1249,1242,1232,1217,1195,1168,1138,1109,1083,1064,1052,
-1047,1047,1046,1042,1030,1009,979,943,906,873,848,833,829,833,842,851,856,852,841,824,803,
-781,763,747,735,722,706,682,649,605,553,497,439,386,338,296,258,220,177,125,64,-5,
--81,-158,-229,-290,-339,-377,-406,-432,-459,-494,-537,-590,-649,-711,-772,-826,-873,-913,-948,-980,-1013,
--1050,-1092,-1137,-1184,-1231,-1274,-1314,-1349,-1381,-1411,-1442,-1474,-1509,-1545,-1580,-1615,-1647,-1677,-1705,-1734,-1763,
--1793,-1825,-1855,-1883,-1904,-1915,-1916,-1907,-1890,-1868,-1847,-1830,-1820,-1819,-1829,-1848,-1875,-1910,-1950,-1996,-2047,
--2103,-2162,-2223,-2282,-2336,-2383,-2420,-2448,-2468,-2483,-2497,-2512,-2531,-2555,-2580,-2605,-2627,-2643,-2651,-2655,-2655,
--2657,-2664,-2679,-2703,-2733,-2768,-2802,-2831,-2853,-2866,-2872,-2875,-2878,-2886,-2900,-2921,-2948,-2977,-3005,-3029,-3048,
--3063,-3075,-3089,-3107,-3133,-3168,-3210,-3258,-3308,-3357,-3404,-3446,-3484,-3519,-3552,-3585,-3619,-3652,-3683,-3711,-3735,
--3754,-3768,-3778,-3786,-3791,-3795,-3796,-3793,-3784,-3769,-3749,-3724,-3700,-3682,-3675,-3684,-3711,-3757,-3818,-3890,-3967,
--4042,-4109,-4164,-4205,-4231,-4245,-4249,-4245,-4236,-4222,-4206,-4189,-4172,-4157,-4145,-4141,-4144,-4156,-4176,-4203,-4234,
--4266,-4297,-4326,-4352,-4376,-4400,-4426,-4456,-4491,-4528,-4567,-4604,-4637,-4664,-4685,-4700,-4712,-4724,-4738,-4757,-4782,
--4812,-4846,-4882,-4917,-4949,-4978,-5004,-5027,-5049,-5070,-5090,-5109,-5125,-5138,-5147,-5151,-5151,-5151,-5153,-5161,-5176,
--5199,-5229,-5262,-5295,-5321,-5338,-5342,-5332,-5310,-5280,-5247,-5214,-5188,-5170,-5160,-5158,-5159,-5162,-5162,-5157,-5148,
--5135,-5121,-5109,-5104,-5107,-5120,-5142,-5173,-5208,-5246,-5283,-5317,-5346,-5370,-5390,-5405,-5419,-5432,-5446,-5461,-5479,
--5499,-5520,-5541,-5561,-5578,-5592,-5601,-5606,-5607,-5605,-5601,-5597,-5594,-5593,-5594,-5597,-5600,-5604,-5607,-5609,-5609,
--5608,-5606,-5603,-5601,-5600,-5599,-5598,-5598,-5596,-5594,-5592,-5591,-5592,-5595,-5602,-5612,-5626,-5643,-5660,-5677,-5692,
--5705,-5715,-5723,-5729,-5736,-5744,-5753,-5764,-5776,-5788,-5800,-5810,-5819,-5825,-5830,-5834,-5838,-5843,-5850,-5859,-5870,
--5882,-5895,-5906,-5916,-5922,-5925,-5924,-5920,-5915,-5909,-5904,-5903,-5907,-5916,-5932,-5953,-5978,-6006,-6033,-6059,-6082,
--6101,-6115,-6126,-6135,-6142,-6150,-6158,-6168,-6180,-6191,-6202,-6210,-6215,-6213,-6206,-6192,-6172,-6147,-6117,-6085,-6052,
--6021,-5991,-5966,-5944,-5925,-5909,-5895,-5881,-5869,-5856,-5843,-5832,-5822,-5815,-5812,-5811,-5813,-5817,-5820,-5823,-5823,
--5821,-5817,-5811,-5804,-5797,-5790,-5784,-5778,-5772,-5766,-5758,-5748,-5737,-5724,-5711,-5698,-5686,-5674,-5664,-5655,-5647,
--5640,-5634,-5631,-5630,-5632,-5637,-5644,-5654,-5664,-5674,-5682,-5687,-5690,-5689,-5687,-5683,-5679,-5674,-5669,-5665,-5660,
--5654,-5648,-5640,-5632,-5623,-5614,-5606,-5598,-5590,-5583,-5575,-5568,-5560,-5552,-5544,-5537,-5530,-5525,-5519,-5514,-5508,
--5501,-5493,-5482,-5468,-5453,-5437,-5420,-5403,-5387,-5371,-5357,-5343,-5330,-5318,-5305,-5293,-5281,-5269,-5258,-5246,-5234,
--5222,-5209,-5195,-5181,-5165,-5149,-5131,-5114,-5095,-5077,-5058,-5040,-5022,-5005,-4990,-4975,-4961,-4949,-4937,-4926,-4915,
--4904,-4892,-4879,-4865,-4850,-4835,-4819,-4805,-4790,-4776,-4762,-4748,-4734,-4718,-4702,-4685,-4668,-4649,-4631,-4613,-4595,
--4577,-4559,-4542,-4525,-4507,-4490,-4472,-4453,-4435,-4415,-4396,-4376,-4355,-4335,-4313,-4292,-4270,-4248,-4225,-4202,-4178,
--4154,-4130,-4106,-4083,-4061,-4040,-4021,-4004,-3989,-3975,-3962,-3950,-3937,-3924,-3909,-3893,-3876,-3858,-3840,-3822,-3806,
--3791,-3779,-3768,-3760,-3754,-3748,-3742,-3735,-3727,-3716,-3704,-3690,-3676,-3662,-3649,-3636,-3625,-3615,-3606,-3596,-3585,
--3572,-3557,-3541,-3524,-3507,-3492,-3478,-3465,-3454,-3444,-3433,-3422,-3410,-3396,-3381,-3366,-3351,-3336,-3321,-3307,-3292,
--3277,-3261,-3244,-3228,-3214,-3201,-3192,-3186,-3183,-3182,-3182,-3180,-3175,-3167,-3155,-3140,-3123,-3106,-3090,-3077,-3066,
--3058,-3051,-3045,-3037,-3029,-3019,-3008,-2996,-2984,-2972,-2960,-2948,-2936,-2923,-2909,-2894,-2879,-2865,-2851,-2838,-2827,
--2816,-2806,-2796,-2784,-2771,-2756,-2741,-2725,-2710,-2696,-2683,-2670,-2656,-2641,-2623,-2604,-2583,-2561,-2541,-2523,-2508,
--2496,-2487,-2478,-2468,-2455,-2438,-2418,-2395,-2371,-2347,-2326,-2308,-2293,-2281,-2270,-2259,-2247,-2233,-2215,-2196,-2174,
--2152,-2127,-2101,-2073,-2042,-2008,-1970,-1929,-1886,-1844,-1805,-1770,-1740,-1717,-1698,-1684,-1673,-1661,-1650,-1636,-1621,
--1605,-1587,-1568,-1549,-1529,-1510,-1491,-1472,-1454,-1438,-1423,-1410,-1399,-1388,-1376,-1362,-1345,-1323,-1297,-1269,-1240,
--1211,-1185,-1162,-1143,-1127,-1112,-1098,-1082,-1064,-1043,-1021,-998,-975,-955,-937,-923,-910,-897,-884,-869,-849,
--825,-795,-760,-720,-675,-625,-570,-512,-452,-391,-330,-272,-218,-170,-126,-87,-51,-17,15,50,85,
-122,158,193,226,257,285,312,338,366,397,430,466,503,539,572,602,626,647,664,679,695,
-711,729,748,769,791,811,832,852,872,891,911,930,947,959,965,963,952,932,906,877,848,
-824,806,796,794,797,804,810,814,813,809,803,797,794,797,806,821,841,863,882,897,904,
-901,890,869,842,810,776,741,707,676,649,625,605,590,578,570,564,561,560,561,563,565,
-570,576,584,593,604,616,627,638,647,655,661,664,667,668,669,668,667,664,660,654,647,
-638,629,620,612,605,599,596,594,592,592,592,592,593,595,599,603,609,616,623,630,636,
-641,644,646,648,649,650,652,654,657,660,662,664,665,665,665,663,662,660,658,656,653,
-651,647,643,637,631,623,613,603,592,581,570,558,547,537,527,517,508,499,491,484,478,
-473,469,465,463,462,462,462,461,461,460,459,457,455,454,453,454,455,457,460,463,467,
-469,471,471,471,471,471,470,471,471,473,474,477,479,482,484,487,490,494,498,503,508,
-514,521,528,535,542,549,556,562,568,573,579,583,588,592,595,599,602,605,608,610,611,
-612,612,612,611,610,608,607,607,607,609,612,617,623,630,638,647,656,665,675,685,696,
-708,720,734,747,760,773,783,792,799,804,808,811,816,822,830,841,855,871,888,905,921,
-935,947,954,958,959,956,952,947,943,942,943,949,959,973,990,1007,1025,1040,1022,1032,1038,
-1041,1042,1042,1044,1049,1056,1065,1077,1090,1104,1118,1133,1149,1164,1180,1196,1211,1225,1238,1248,1256,
-1262,1267,1272,1279,1287,1298,1310,1322,1334,1344,1351,1356,1361,1367,1376,1390,1410,1434,1462,1489,1512,
-1529,1536,1533,1520,1501,1479,1457,1441,1431,1429,1435,1445,1457,1468,1475,1476,1472,1462,1448,1433,1419,
-1407,1399,1396,1397,1402,1411,1422,1436,1450,1465,1480,1493,1504,1512,1518,1520,1522,1522,1524,1527,1533,
-1541,1551,1562,1573,1582,1590,1597,1601,1605,1609,1613,1616,1619,1621,1622,1621,1619,1617,1616,1617,1621,
-1630,1641,1655,1669,1683,1696,1707,1719,1734,1753,1780,1817,1863,1918,1978,2039,2099,2154,2201,2240,2272,
-2299,2325,2350,2378,2407,2438,2468,2495,2515,2527,2530,2524,2512,2495,2476,2457,2440,2425,2413,2403,2394,
-2386,2378,2371,2366,2363,2364,2369,2377,2389,2403,2417,2430,2440,2446,2448,2448,2447,2446,2448,2454,2465,
-2482,2501,2524,2546,2567,2585,2599,2610,2619,2628,2637,2649,2662,2678,2694,2709,2723,2735,2746,2759,2776,
-2800,2836,2884,2945,3016,3094,3172,3245,3308,3358,3393,3415,3428,3436,3446,3460,3480,3505,3533,3559,3576,
-3581,3569,3540,3497,3444,3386,3332,3287,3256,3240,3239,3252,3273,3297,3319,3335,3341,3337,3321,3295,3261,
-3220,3174,3125,3074,3021,2968,2917,2869,2828,2797,2778,2774,2786,2813,2852,2898,2944,2985,3015,3028,3023,
-3002,2967,2925,2882,2843,2814,2795,2786,2783,2782,2776,2762,2737,2701,2655,2604,2551,2501,2454,2413,2376,
-2341,2305,2265,2221,2173,2123,2071,2023,1978,1939,1906,1876,1849,1822,1794,1764,1733,1701,1670,1642,1618,
-1599,1585,1576,1570,1568,1569,1574,1583,1597,1617,1641,1669,1699,1729,1755,1776,1790,1796,1793,1783,1767,
-1745,1718,1689,1659,1627,1596,1566,1539,1514,1492,1472,1454,1436,1418,1398,1376,1353,1331,1311,1296,1287,
-1285,1287,1293,1298,1299,1293,1277,1253,1222,1188,1155,1126,1104,1091,1083,1078,1072,1061,1042,1014,978,
-937,896,859,829,808,796,792,791,792,792,789,784,778,772,767,763,758,750,735,712,679,
-637,587,532,478,426,378,334,292,247,197,138,70,-6,-87,-168,-243,-308,-361,-401,-433,-460,
--487,-519,-559,-606,-659,-716,-771,-823,-868,-908,-944,-978,-1013,-1052,-1096,-1143,-1193,-1244,-1293,-1339,-1382,
--1421,-1459,-1495,-1531,-1568,-1604,-1640,-1673,-1705,-1734,-1761,-1788,-1815,-1843,-1871,-1898,-1921,-1937,-1945,-1944,-1933,
--1915,-1894,-1873,-1856,-1848,-1851,-1864,-1889,-1924,-1967,-2015,-2069,-2124,-2182,-2238,-2293,-2343,-2387,-2424,-2453,-2475,
--2491,-2504,-2515,-2528,-2543,-2561,-2579,-2598,-2614,-2627,-2636,-2643,-2650,-2659,-2672,-2690,-2714,-2742,-2771,-2798,-2820,
--2837,-2849,-2856,-2864,-2873,-2888,-2908,-2934,-2964,-2994,-3023,-3047,-3068,-3084,-3098,-3113,-3131,-3153,-3181,-3215,-3252,
--3292,-3333,-3374,-3416,-3459,-3503,-3547,-3593,-3638,-3680,-3717,-3747,-3771,-3787,-3798,-3805,-3811,-3815,-3818,-3818,-3814,
--3802,-3782,-3754,-3721,-3689,-3662,-3648,-3653,-3679,-3727,-3794,-3875,-3963,-4049,-4128,-4195,-4246,-4281,-4300,-4307,-4302,
--4289,-4270,-4247,-4222,-4198,-4178,-4165,-4160,-4166,-4182,-4208,-4240,-4273,-4306,-4334,-4358,-4376,-4392,-4409,-4431,-4459,
--4494,-4535,-4578,-4620,-4655,-4680,-4696,-4703,-4705,-4707,-4714,-4729,-4755,-4791,-4835,-4882,-4929,-4971,-5005,-5031,-5050,
--5062,-5072,-5079,-5087,-5094,-5101,-5106,-5110,-5112,-5116,-5122,-5134,-5153,-5181,-5216,-5254,-5291,-5322,-5341,-5347,-5338,
--5317,-5287,-5254,-5223,-5200,-5187,-5185,-5191,-5201,-5212,-5219,-5219,-5212,-5199,-5184,-5170,-5163,-5164,-5176,-5198,-5230,
--5267,-5306,-5344,-5378,-5407,-5429,-5446,-5459,-5470,-5482,-5494,-5510,-5528,-5550,-5573,-5598,-5622,-5646,-5666,-5684,-5697,
--5706,-5711,-5712,-5710,-5707,-5702,-5698,-5694,-5691,-5689,-5688,-5688,-5689,-5690,-5691,-5691,-5691,-5690,-5687,-5682,-5675,
--5667,-5658,-5649,-5642,-5638,-5638,-5642,-5650,-5661,-5675,-5689,-5703,-5716,-5727,-5737,-5747,-5757,-5769,-5782,-5798,-5815,
--5832,-5848,-5861,-5871,-5877,-5879,-5878,-5876,-5874,-5873,-5875,-5881,-5890,-5901,-5915,-5930,-5945,-5958,-5968,-5975,-5979,
--5980,-5977,-5974,-5970,-5967,-5968,-5973,-5983,-5998,-6017,-6041,-6066,-6091,-6115,-6135,-6150,-6162,-6169,-6174,-6177,-6180,
--6185,-6192,-6201,-6212,-6222,-6231,-6235,-6234,-6227,-6212,-6191,-6165,-6137,-6109,-6082,-6058,-6039,-6022,-6008,-5996,-5982,
--5968,-5951,-5934,-5916,-5899,-5885,-5875,-5869,-5868,-5869,-5872,-5876,-5878,-5877,-5875,-5870,-5864,-5857,-5850,-5843,-5838,
--5832,-5826,-5819,-5812,-5803,-5793,-5782,-5772,-5762,-5753,-5744,-5737,-5730,-5724,-5719,-5716,-5714,-5713,-5715,-5719,-5724,
--5729,-5735,-5739,-5743,-5745,-5745,-5745,-5743,-5742,-5740,-5738,-5735,-5730,-5724,-5716,-5706,-5695,-5683,-5672,-5662,-5653,
--5645,-5639,-5633,-5627,-5621,-5614,-5607,-5599,-5590,-5582,-5575,-5568,-5560,-5553,-5544,-5534,-5523,-5509,-5494,-5478,-5461,
--5444,-5428,-5412,-5397,-5383,-5369,-5356,-5344,-5331,-5319,-5307,-5294,-5282,-5269,-5256,-5242,-5227,-5212,-5197,-5181,-5164,
--5148,-5131,-5113,-5096,-5079,-5062,-5046,-5031,-5016,-5003,-4991,-4979,-4968,-4957,-4946,-4933,-4919,-4904,-4888,-4871,-4853,
--4836,-4818,-4801,-4785,-4769,-4753,-4737,-4721,-4704,-4686,-4667,-4647,-4628,-4608,-4588,-4569,-4550,-4533,-4516,-4499,-4482,
--4465,-4448,-4430,-4411,-4392,-4371,-4350,-4329,-4307,-4285,-4262,-4239,-4215,-4191,-4166,-4142,-4117,-4093,-4070,-4049,-4029,
--4011,-3994,-3979,-3966,-3954,-3942,-3930,-3918,-3905,-3892,-3878,-3864,-3849,-3835,-3823,-3812,-3803,-3796,-3790,-3785,-3780,
--3773,-3765,-3754,-3741,-3727,-3712,-3697,-3683,-3670,-3658,-3646,-3633,-3619,-3603,-3585,-3566,-3545,-3525,-3506,-3490,-3477,
--3466,-3458,-3450,-3442,-3432,-3420,-3406,-3390,-3372,-3355,-3338,-3322,-3308,-3295,-3284,-3273,-3264,-3255,-3247,-3240,-3235,
--3230,-3226,-3222,-3217,-3210,-3202,-3191,-3178,-3164,-3150,-3136,-3123,-3111,-3100,-3090,-3080,-3071,-3061,-3050,-3039,-3027,
--3016,-3004,-2992,-2980,-2967,-2953,-2939,-2924,-2908,-2893,-2878,-2864,-2851,-2839,-2827,-2814,-2802,-2788,-2773,-2758,-2743,
--2728,-2712,-2696,-2680,-2662,-2643,-2624,-2604,-2585,-2567,-2553,-2541,-2532,-2525,-2519,-2510,-2499,-2484,-2465,-2444,-2421,
--2399,-2380,-2364,-2352,-2343,-2335,-2326,-2315,-2300,-2280,-2256,-2229,-2200,-2169,-2136,-2102,-2064,-2023,-1976,-1925,-1871,
--1815,-1762,-1714,-1675,-1645,-1625,-1615,-1612,-1612,-1613,-1612,-1608,-1598,-1584,-1566,-1545,-1523,-1502,-1482,-1463,-1446,
--1432,-1420,-1410,-1400,-1392,-1383,-1372,-1358,-1340,-1318,-1293,-1266,-1237,-1209,-1183,-1161,-1141,-1124,-1107,-1091,-1072,
--1051,-1026,-1000,-973,-946,-922,-902,-885,-872,-861,-851,-838,-821,-799,-770,-733,-689,-639,-584,-525,-465,
--405,-349,-297,-250,-210,-175,-143,-113,-83,-50,-13,28,72,117,161,201,235,263,285,303,319,
-337,359,386,418,455,494,534,571,604,633,659,683,706,731,758,787,819,852,884,913,939,
-960,977,988,994,994,989,978,961,938,911,881,851,823,800,782,771,766,765,767,768,767,
-763,757,750,744,740,742,748,760,775,792,807,817,822,818,806,785,758,727,692,656,621,
-589,560,535,515,501,491,485,483,483,486,489,493,498,504,510,518,527,537,549,560,571,
-581,589,596,600,603,604,604,603,600,597,591,584,576,566,556,546,537,529,523,519,518,
-517,518,520,522,524,527,530,535,540,545,551,557,563,567,571,575,577,579,581,583,586,
-589,592,595,598,600,601,600,599,596,592,588,584,579,575,570,565,559,553,546,537,528,
-517,506,494,482,470,459,448,438,430,422,415,408,402,396,392,388,385,384,384,384,386,
-388,389,390,391,391,391,391,392,393,395,397,400,404,407,410,412,414,415,416,417,418,
-420,422,424,427,431,434,438,442,446,450,454,459,464,470,476,484,491,499,507,514,522,
-528,535,541,546,551,557,562,567,572,577,581,584,587,589,590,591,592,592,593,595,598,
-601,606,612,619,627,636,645,655,665,675,686,697,708,720,732,744,756,769,781,794,805,
-817,827,836,845,853,860,867,874,880,887,894,900,906,911,914,915,914,911,907,902,898,
-897,900,906,918,933,952,972,992,1009,1022,1021,1025,1025,1022,1018,1015,1015,1018,1024,1033,1045,
-1058,1073,1089,1107,1125,1145,1166,1188,1210,1229,1246,1260,1270,1276,1280,1283,1287,1292,1299,1308,1317,
-1326,1334,1341,1346,1351,1358,1369,1386,1409,1436,1467,1497,1522,1540,1548,1544,1531,1511,1489,1468,1453,
-1447,1449,1460,1477,1495,1512,1524,1529,1528,1521,1509,1496,1484,1474,1467,1464,1464,1465,1468,1472,1475,
-1479,1483,1487,1492,1498,1505,1513,1521,1529,1538,1547,1556,1565,1574,1582,1590,1597,1603,1608,1613,1618,
-1623,1630,1637,1645,1653,1661,1667,1673,1677,1680,1684,1688,1694,1701,1709,1718,1728,1738,1749,1763,1780,
-1803,1833,1873,1922,1977,2038,2098,2155,2205,2244,2273,2292,2304,2313,2324,2339,2361,2388,2420,2452,2481,
-2501,2511,2508,2493,2468,2436,2401,2366,2335,2308,2286,2269,2255,2245,2237,2231,2229,2231,2237,2250,2268,
-2291,2318,2345,2371,2393,2410,2422,2430,2435,2438,2443,2451,2463,2480,2502,2526,2553,2580,2606,2630,2653,
-2674,2693,2711,2727,2740,2749,2752,2750,2742,2730,2716,2704,2699,2704,2722,2756,2805,2866,2934,3005,3073,
-3133,3183,3221,3250,3273,3293,3314,3339,3367,3398,3427,3449,3461,3459,3439,3404,3356,3300,3242,3188,3145,
-3115,3101,3101,3113,3132,3154,3174,3187,3192,3187,3172,3149,3118,3082,3043,3002,2960,2918,2877,2838,2801,
-2769,2744,2728,2722,2728,2746,2774,2810,2850,2888,2921,2944,2955,2954,2942,2922,2897,2871,2846,2824,2805,
-2786,2765,2740,2709,2671,2626,2576,2524,2473,2424,2380,2340,2302,2266,2228,2187,2143,2096,2048,2001,1956,
-1917,1882,1852,1825,1799,1773,1744,1714,1682,1650,1620,1594,1574,1559,1551,1548,1548,1552,1559,1567,1577,
-1590,1606,1626,1648,1672,1697,1720,1740,1756,1766,1769,1767,1759,1746,1728,1706,1681,1654,1626,1597,1570,
-1544,1520,1498,1479,1460,1441,1422,1403,1382,1363,1347,1334,1326,1324,1327,1331,1334,1334,1326,1311,1287,
-1257,1224,1191,1163,1141,1126,1117,1112,1106,1097,1080,1056,1025,990,952,918,888,866,851,841,835,
-831,826,820,812,803,795,787,780,772,761,743,718,684,641,590,536,480,426,376,329,284,
-238,187,130,65,-7,-85,-163,-237,-304,-360,-407,-445,-478,-510,-543,-582,-626,-674,-725,-776,-824,
--869,-909,-946,-981,-1017,-1056,-1098,-1144,-1192,-1241,-1289,-1335,-1378,-1419,-1457,-1494,-1530,-1565,-1599,-1630,-1660,
--1687,-1711,-1734,-1756,-1778,-1801,-1825,-1848,-1869,-1886,-1897,-1901,-1898,-1889,-1878,-1868,-1862,-1863,-1874,-1895,-1926,
--1966,-2013,-2063,-2116,-2168,-2218,-2265,-2308,-2346,-2378,-2406,-2430,-2450,-2467,-2482,-2497,-2512,-2528,-2543,-2559,-2574,
--2587,-2599,-2611,-2623,-2636,-2652,-2671,-2693,-2718,-2743,-2767,-2788,-2806,-2821,-2833,-2844,-2857,-2873,-2892,-2915,-2941,
--2968,-2994,-3019,-3041,-3060,-3078,-3096,-3115,-3136,-3160,-3187,-3215,-3245,-3275,-3307,-3342,-3379,-3420,-3466,-3515,-3566,
--3615,-3659,-3696,-3723,-3740,-3750,-3754,-3755,-3758,-3762,-3768,-3773,-3776,-3772,-3760,-3739,-3711,-3682,-3658,-3645,-3649,
--3674,-3722,-3789,-3871,-3961,-4050,-4132,-4202,-4255,-4290,-4309,-4313,-4304,-4287,-4263,-4236,-4210,-4186,-4169,-4160,-4162,
--4176,-4199,-4229,-4263,-4297,-4326,-4349,-4366,-4377,-4387,-4400,-4419,-4447,-4484,-4528,-4576,-4622,-4661,-4692,-4712,-4723,
--4731,-4739,-4752,-4775,-4810,-4853,-4904,-4955,-5002,-5040,-5067,-5083,-5090,-5092,-5091,-5092,-5096,-5104,-5115,-5127,-5139,
--5150,-5160,-5171,-5184,-5203,-5227,-5256,-5288,-5320,-5346,-5363,-5368,-5360,-5342,-5316,-5289,-5265,-5248,-5242,-5246,-5257,
--5271,-5284,-5291,-5291,-5284,-5270,-5255,-5242,-5236,-5241,-5257,-5283,-5317,-5355,-5393,-5426,-5452,-5470,-5481,-5485,-5486,
--5487,-5490,-5497,-5509,-5528,-5551,-5579,-5609,-5640,-5671,-5699,-5725,-5746,-5763,-5774,-5780,-5782,-5779,-5773,-5765,-5757,
--5748,-5741,-5736,-5732,-5731,-5732,-5735,-5738,-5741,-5743,-5743,-5741,-5736,-5730,-5721,-5713,-5705,-5699,-5695,-5695,-5698,
--5704,-5713,-5722,-5732,-5742,-5751,-5761,-5772,-5784,-5798,-5815,-5834,-5855,-5876,-5896,-5913,-5925,-5933,-5936,-5935,-5930,
--5925,-5920,-5917,-5917,-5922,-5931,-5945,-5962,-5981,-6000,-6018,-6034,-6044,-6050,-6050,-6045,-6036,-6025,-6015,-6007,-6004,
--6008,-6019,-6037,-6062,-6090,-6120,-6149,-6174,-6193,-6206,-6213,-6216,-6216,-6215,-6216,-6219,-6225,-6233,-6241,-6249,-6252,
--6251,-6244,-6230,-6212,-6190,-6168,-6146,-6127,-6112,-6100,-6090,-6080,-6070,-6057,-6042,-6023,-6003,-5982,-5962,-5945,-5932,
--5923,-5918,-5916,-5916,-5917,-5917,-5916,-5915,-5911,-5907,-5903,-5897,-5892,-5886,-5880,-5872,-5865,-5857,-5849,-5841,-5835,
--5829,-5825,-5821,-5819,-5817,-5814,-5812,-5809,-5807,-5804,-5802,-5800,-5798,-5796,-5795,-5793,-5792,-5790,-5789,-5789,-5790,
--5791,-5792,-5793,-5793,-5790,-5785,-5777,-5766,-5753,-5739,-5726,-5713,-5702,-5694,-5688,-5683,-5679,-5674,-5669,-5662,-5654,
--5645,-5635,-5625,-5615,-5606,-5597,-5588,-5579,-5569,-5558,-5545,-5531,-5516,-5500,-5483,-5467,-5450,-5434,-5418,-5403,-5388,
--5374,-5361,-5348,-5335,-5322,-5308,-5295,-5281,-5266,-5252,-5238,-5224,-5210,-5196,-5181,-5167,-5152,-5136,-5119,-5102,-5085,
--5068,-5052,-5037,-5024,-5011,-5000,-4989,-4977,-4965,-4952,-4936,-4919,-4901,-4882,-4862,-4843,-4824,-4806,-4789,-4771,-4754,
--4735,-4716,-4696,-4674,-4652,-4630,-4608,-4588,-4569,-4551,-4535,-4520,-4505,-4490,-4475,-4458,-4440,-4420,-4400,-4378,-4357,
--4335,-4313,-4291,-4270,-4248,-4227,-4205,-4183,-4160,-4137,-4114,-4091,-4068,-4047,-4026,-4008,-3991,-3977,-3965,-3956,-3948,
--3940,-3932,-3924,-3913,-3901,-3888,-3874,-3859,-3845,-3832,-3821,-3810,-3799,-3788,-3776,-3763,-3747,-3731,-3714,-3698,-3683,
--3670,-3659,-3650,-3640,-3630,-3618,-3602,-3585,-3565,-3544,-3524,-3506,-3492,-3481,-3472,-3466,-3459,-3452,-3442,-3429,-3414,
--3397,-3379,-3361,-3346,-3334,-3325,-3318,-3314,-3310,-3307,-3302,-3297,-3290,-3281,-3272,-3262,-3252,-3242,-3232,-3221,-3210,
--3198,-3187,-3174,-3161,-3149,-3136,-3123,-3110,-3098,-3086,-3074,-3063,-3053,-3043,-3033,-3022,-3012,-3000,-2987,-2973,-2957,
--2941,-2925,-2908,-2891,-2874,-2858,-2842,-2827,-2813,-2799,-2785,-2771,-2757,-2742,-2726,-2708,-2688,-2667,-2645,-2623,-2603,
--2585,-2572,-2562,-2555,-2551,-2547,-2542,-2535,-2523,-2508,-2491,-2473,-2456,-2442,-2431,-2425,-2420,-2415,-2408,-2396,-2377,
--2351,-2319,-2283,-2245,-2206,-2169,-2132,-2094,-2055,-2011,-1962,-1907,-1848,-1787,-1728,-1675,-1632,-1601,-1582,-1575,-1576,
--1581,-1587,-1590,-1588,-1579,-1564,-1545,-1524,-1503,-1482,-1465,-1450,-1438,-1428,-1420,-1411,-1403,-1393,-1382,-1368,-1352,
--1334,-1313,-1289,-1264,-1237,-1211,-1185,-1160,-1135,-1112,-1088,-1064,-1038,-1010,-980,-950,-919,-890,-863,-840,-821,
--806,-793,-780,-767,-750,-728,-699,-663,-621,-573,-521,-467,-413,-363,-318,-278,-245,-217,-193,-169,-144,
--113,-76,-31,19,75,131,185,232,271,300,320,334,345,357,374,396,426,462,502,544,585,
-624,660,693,725,758,793,832,875,919,965,1007,1043,1071,1089,1096,1092,1078,1057,1029,997,963,
-928,895,863,835,811,791,775,763,753,745,737,728,717,707,696,686,679,677,679,686,698,
-712,726,738,746,748,742,729,709,682,650,615,579,542,507,474,446,423,406,394,388,386,
-389,394,401,409,418,427,436,446,456,467,478,489,500,509,518,524,529,532,533,533,532,
-530,526,522,516,509,502,494,486,479,473,469,466,464,464,464,465,466,467,469,470,473,
-476,481,486,492,498,504,509,513,516,518,518,519,519,519,520,521,523,524,526,527,527,
-526,523,519,514,508,502,495,488,481,474,466,458,449,439,428,417,405,394,383,372,363,
-354,347,340,333,327,322,317,313,310,308,307,308,310,312,316,319,322,325,327,329,330,
-332,334,336,339,342,345,348,351,354,356,358,359,361,364,366,370,373,378,382,388,393,
-398,404,409,416,422,429,436,444,452,460,468,475,483,490,496,503,509,516,522,529,535,
-542,547,552,557,560,563,565,568,571,575,580,587,594,602,611,620,629,638,647,656,666,
-676,687,697,708,719,730,740,751,763,775,789,804,821,839,858,875,892,905,915,921,923,
-922,918,913,907,901,895,890,886,882,879,877,876,878,883,892,905,922,941,962,982,999,
-1013,1021,1052,1052,1048,1042,1036,1031,1030,1031,1036,1045,1055,1067,1080,1094,1110,1128,1148,1171,1195,
-1220,1244,1267,1286,1301,1312,1321,1327,1332,1337,1342,1348,1352,1355,1357,1357,1356,1358,1363,1374,1392,
-1417,1449,1484,1518,1548,1568,1578,1576,1563,1544,1522,1504,1492,1490,1498,1517,1542,1570,1597,1619,1635,
-1643,1643,1638,1630,1620,1609,1599,1589,1579,1567,1554,1540,1525,1511,1499,1491,1487,1489,1496,1508,1522,
-1538,1553,1568,1580,1589,1597,1602,1606,1610,1613,1618,1624,1632,1643,1655,1669,1685,1701,1717,1732,1747,
-1760,1772,1783,1793,1803,1812,1820,1829,1838,1848,1859,1875,1896,1923,1958,2000,2047,2098,2149,2195,2234,
-2263,2281,2289,2289,2286,2283,2285,2293,2310,2334,2362,2389,2411,2424,2426,2414,2391,2358,2319,2279,2239,
-2204,2174,2149,2130,2114,2103,2095,2091,2092,2099,2114,2136,2165,2199,2236,2272,2306,2335,2358,2375,2389,
-2401,2413,2429,2450,2476,2507,2543,2580,2616,2651,2684,2712,2738,2761,2781,2798,2812,2821,2824,2819,2804,
-2782,2752,2720,2688,2661,2645,2643,2656,2684,2726,2777,2833,2890,2943,2990,3032,3070,3104,3139,3175,3213,
-3253,3290,3322,3345,3353,3345,3319,3278,3225,3165,3105,3049,3003,2970,2951,2946,2950,2962,2975,2987,2992,
-2990,2980,2962,2937,2909,2880,2852,2827,2806,2790,2777,2766,2756,2746,2735,2724,2713,2706,2703,2706,2717,
-2736,2761,2791,2823,2853,2879,2897,2906,2906,2896,2876,2847,2812,2770,2723,2673,2621,2568,2515,2465,2418,
-2376,2337,2302,2269,2236,2201,2163,2121,2076,2029,1982,1938,1896,1860,1829,1801,1777,1754,1731,1707,1681,
-1655,1629,1606,1586,1571,1561,1556,1555,1557,1561,1567,1575,1583,1594,1606,1620,1635,1651,1666,1680,1691,
-1698,1702,1702,1700,1695,1688,1680,1669,1656,1641,1623,1603,1582,1559,1538,1516,1496,1478,1460,1443,1425,
-1408,1392,1376,1362,1351,1342,1335,1328,1321,1311,1297,1279,1256,1229,1202,1177,1155,1137,1124,1115,1108,
-1100,1088,1072,1052,1027,1002,977,956,939,928,922,917,912,905,894,879,860,840,820,801,784,
-768,752,731,704,668,624,571,513,452,392,334,280,229,181,131,78,21,-42,-110,-180,-249,
--315,-374,-427,-472,-513,-550,-586,-624,-664,-707,-751,-795,-839,-880,-920,-959,-997,-1036,-1077,-1120,-1165,
--1211,-1257,-1301,-1344,-1384,-1422,-1457,-1491,-1524,-1556,-1586,-1614,-1640,-1664,-1685,-1705,-1724,-1742,-1762,-1782,-1803,
--1822,-1839,-1852,-1860,-1863,-1863,-1861,-1861,-1865,-1877,-1898,-1929,-1968,-2014,-2064,-2115,-2164,-2208,-2247,-2281,-2308,
--2332,-2354,-2374,-2394,-2416,-2439,-2462,-2485,-2507,-2527,-2545,-2560,-2574,-2586,-2598,-2611,-2627,-2646,-2669,-2693,-2719,
--2746,-2770,-2792,-2812,-2828,-2843,-2858,-2874,-2892,-2913,-2935,-2959,-2982,-3004,-3024,-3042,-3059,-3076,-3094,-3115,-3139,
--3165,-3193,-3221,-3247,-3272,-3295,-3319,-3345,-3375,-3411,-3454,-3501,-3550,-3597,-3638,-3669,-3688,-3695,-3694,-3688,-3682,
--3679,-3682,-3692,-3706,-3720,-3731,-3735,-3731,-3719,-3703,-3688,-3683,-3692,-3720,-3769,-3837,-3920,-4010,-4101,-4184,-4252,
--4303,-4334,-4345,-4340,-4322,-4295,-4264,-4233,-4206,-4186,-4176,-4176,-4188,-4209,-4238,-4270,-4303,-4331,-4353,-4367,-4374,
--4377,-4381,-4389,-4406,-4433,-4471,-4518,-4569,-4620,-4667,-4707,-4739,-4765,-4788,-4813,-4842,-4879,-4922,-4971,-5020,-5065,
--5101,-5126,-5138,-5139,-5134,-5127,-5123,-5126,-5138,-5158,-5184,-5212,-5240,-5264,-5283,-5299,-5314,-5328,-5345,-5365,-5387,
--5409,-5428,-5439,-5441,-5433,-5417,-5394,-5370,-5350,-5335,-5329,-5331,-5339,-5349,-5357,-5361,-5358,-5349,-5336,-5323,-5315,
--5314,-5324,-5345,-5374,-5410,-5446,-5479,-5504,-5520,-5525,-5522,-5512,-5500,-5490,-5483,-5483,-5491,-5506,-5528,-5555,-5586,
--5619,-5652,-5684,-5715,-5742,-5766,-5785,-5800,-5811,-5816,-5818,-5817,-5812,-5806,-5800,-5793,-5787,-5783,-5780,-5779,-5780,
--5782,-5784,-5786,-5787,-5787,-5785,-5782,-5777,-5772,-5766,-5762,-5759,-5758,-5759,-5762,-5767,-5772,-5779,-5786,-5793,-5800,
--5809,-5820,-5833,-5848,-5865,-5885,-5905,-5924,-5942,-5956,-5967,-5973,-5974,-5973,-5969,-5965,-5963,-5963,-5968,-5978,-5992,
--6010,-6031,-6053,-6073,-6090,-6101,-6107,-6106,-6100,-6089,-6078,-6067,-6060,-6060,-6067,-6082,-6104,-6131,-6161,-6191,-6219,
--6240,-6256,-6265,-6267,-6266,-6262,-6258,-6256,-6256,-6258,-6263,-6267,-6269,-6268,-6263,-6253,-6238,-6221,-6202,-6183,-6167,
--6153,-6142,-6134,-6126,-6119,-6110,-6098,-6084,-6067,-6048,-6030,-6012,-5996,-5983,-5974,-5967,-5964,-5962,-5961,-5961,-5961,
--5959,-5957,-5954,-5949,-5943,-5936,-5928,-5919,-5911,-5903,-5897,-5893,-5891,-5891,-5893,-5895,-5898,-5901,-5902,-5903,-5901,
--5899,-5895,-5890,-5884,-5878,-5872,-5865,-5859,-5853,-5848,-5844,-5842,-5842,-5844,-5847,-5850,-5853,-5853,-5851,-5845,-5835,
--5822,-5808,-5792,-5777,-5763,-5752,-5743,-5735,-5730,-5724,-5719,-5712,-5704,-5694,-5683,-5671,-5660,-5649,-5638,-5629,-5620,
--5612,-5603,-5594,-5584,-5573,-5560,-5545,-5529,-5513,-5495,-5477,-5460,-5443,-5427,-5412,-5398,-5384,-5370,-5357,-5343,-5329,
--5314,-5300,-5286,-5272,-5258,-5245,-5232,-5219,-5205,-5190,-5174,-5156,-5138,-5119,-5100,-5083,-5066,-5052,-5039,-5027,-5016,
--5004,-4992,-4978,-4962,-4945,-4927,-4907,-4888,-4869,-4850,-4831,-4812,-4792,-4772,-4750,-4728,-4704,-4681,-4657,-4634,-4613,
--4594,-4576,-4560,-4545,-4529,-4514,-4497,-4479,-4460,-4440,-4419,-4397,-4376,-4354,-4333,-4313,-4294,-4274,-4256,-4237,-4218,
--4199,-4179,-4158,-4136,-4114,-4091,-4069,-4049,-4030,-4015,-4003,-3993,-3986,-3981,-3976,-3969,-3960,-3948,-3933,-3915,-3895,
--3874,-3853,-3832,-3812,-3792,-3772,-3751,-3728,-3705,-3682,-3660,-3640,-3623,-3612,-3604,-3601,-3600,-3599,-3597,-3592,-3583,
--3570,-3554,-3537,-3520,-3504,-3492,-3482,-3475,-3470,-3464,-3456,-3446,-3434,-3419,-3403,-3388,-3375,-3365,-3359,-3355,-3354,
--3354,-3353,-3351,-3345,-3336,-3324,-3310,-3295,-3280,-3266,-3252,-3240,-3229,-3219,-3209,-3198,-3187,-3175,-3162,-3149,-3136,
--3124,-3112,-3101,-3091,-3082,-3072,-3063,-3053,-3042,-3030,-3017,-3002,-2985,-2967,-2948,-2928,-2908,-2888,-2868,-2851,-2834,
--2820,-2808,-2796,-2786,-2774,-2761,-2745,-2726,-2705,-2681,-2656,-2632,-2611,-2594,-2581,-2572,-2566,-2562,-2558,-2551,-2541,
--2529,-2515,-2501,-2489,-2481,-2478,-2478,-2481,-2484,-2482,-2473,-2454,-2424,-2385,-2339,-2289,-2240,-2195,-2155,-2121,-2090,
--2059,-2027,-1989,-1944,-1893,-1839,-1785,-1735,-1693,-1662,-1643,-1634,-1632,-1634,-1635,-1632,-1623,-1608,-1588,-1564,-1539,
--1516,-1496,-1481,-1469,-1461,-1455,-1448,-1440,-1430,-1417,-1401,-1382,-1362,-1339,-1315,-1290,-1263,-1234,-1204,-1172,-1140,
--1107,-1074,-1042,-1009,-977,-945,-913,-882,-852,-824,-799,-775,-755,-736,-720,-704,-687,-669,-646,-620,-588,
--552,-512,-469,-425,-382,-343,-308,-278,-253,-232,-212,-190,-163,-128,-85,-33,26,91,156,219,274,
-320,355,380,397,410,422,437,457,483,515,552,592,632,672,711,749,788,828,873,921,973,
-1027,1080,1129,1170,1199,1215,1217,1204,1179,1143,1101,1055,1008,963,922,885,853,826,803,783,764,
-746,728,709,690,670,651,635,623,616,614,618,627,639,653,665,674,678,676,666,649,626,
-598,566,531,495,459,424,392,363,339,319,305,296,292,292,296,304,313,323,334,346,358,
-370,382,394,405,416,426,434,441,447,451,453,454,454,454,452,450,447,443,439,435,431,
-427,424,421,419,418,417,417,416,415,415,415,415,416,419,423,428,434,440,447,452,456,
-458,459,459,457,456,454,453,453,454,456,459,461,463,465,464,462,457,451,443,435,425,
-415,405,395,385,375,365,354,343,332,321,310,300,290,282,275,269,264,260,256,253,251,
-248,247,246,246,247,249,251,254,258,262,265,269,272,275,277,280,282,285,288,290,293,
-295,297,300,302,304,307,310,314,319,324,330,336,343,350,357,365,373,381,389,398,406,
-415,423,431,439,446,454,461,468,476,484,491,499,506,513,519,524,527,530,533,536,539,
-544,551,559,569,581,593,605,617,628,640,651,662,673,685,698,710,722,734,744,754,764,
-773,784,797,813,831,852,875,897,918,935,947,953,954,950,941,931,919,908,898,891,885,
-882,881,882,886,893,904,919,936,957,980,1002,1021,1037,1047,1052,1127,1128,1124,1118,1112,1107,
-1104,1106,1110,1116,1125,1134,1144,1155,1168,1182,1200,1220,1243,1269,1295,1320,1345,1366,1384,1399,1411,
-1421,1428,1434,1436,1436,1433,1426,1418,1409,1403,1401,1406,1420,1442,1473,1508,1544,1577,1602,1618,1623,
-1618,1607,1592,1580,1573,1576,1587,1608,1636,1667,1699,1728,1752,1769,1780,1786,1786,1782,1773,1761,1744,
-1722,1696,1664,1630,1596,1563,1535,1515,1503,1501,1507,1519,1536,1554,1572,1587,1599,1607,1612,1615,1618,
-1622,1627,1635,1646,1659,1674,1690,1707,1725,1743,1761,1779,1798,1816,1835,1854,1872,1890,1907,1924,1939,
-1954,1970,1987,2007,2032,2060,2093,2129,2165,2201,2232,2255,2270,2276,2273,2263,2251,2240,2234,2235,2246,
-2264,2288,2313,2336,2351,2356,2349,2330,2301,2264,2223,2182,2143,2108,2078,2051,2029,2009,1994,1983,1979,
-1982,1995,2017,2049,2088,2132,2177,2219,2256,2286,2309,2327,2343,2362,2385,2417,2457,2506,2562,2619,2676,
-2727,2771,2806,2831,2849,2861,2868,2873,2875,2874,2869,2858,2839,2812,2779,2740,2699,2662,2631,2611,2604,
-2610,2629,2659,2696,2738,2782,2827,2871,2916,2962,3010,3059,3110,3159,3202,3237,3259,3265,3253,3224,3179,
-3123,3060,2997,2939,2890,2853,2829,2817,2815,2819,2826,2830,2829,2821,2806,2783,2757,2729,2703,2684,2672,
-2669,2675,2688,2704,2719,2730,2734,2729,2717,2698,2678,2660,2649,2650,2664,2691,2730,2776,2823,2866,2899,
-2917,2917,2899,2863,2812,2750,2683,2613,2546,2485,2431,2384,2345,2313,2283,2255,2226,2194,2158,2117,2072,
-2024,1976,1929,1885,1845,1810,1780,1755,1732,1711,1692,1673,1654,1637,1621,1607,1596,1588,1583,1580,1580,
-1581,1583,1587,1593,1600,1609,1620,1631,1641,1650,1655,1657,1654,1648,1639,1630,1621,1614,1610,1608,1607,
-1607,1606,1601,1593,1581,1566,1548,1529,1509,1491,1473,1457,1442,1427,1412,1396,1380,1363,1346,1329,1311,
-1293,1274,1254,1234,1213,1193,1173,1155,1138,1124,1110,1097,1083,1066,1047,1025,1003,981,962,949,941,
-939,941,946,950,949,942,927,905,878,849,819,792,769,748,729,709,683,649,607,554,495,
-430,363,298,237,181,129,80,31,-19,-73,-131,-192,-256,-319,-380,-437,-489,-537,-580,-619,-657,
--694,-731,-768,-806,-844,-882,-921,-961,-1002,-1045,-1089,-1135,-1182,-1228,-1273,-1316,-1357,-1395,-1431,-1465,-1498,
--1530,-1561,-1591,-1620,-1647,-1672,-1695,-1717,-1738,-1758,-1779,-1800,-1820,-1838,-1853,-1863,-1869,-1870,-1869,-1867,-1868,
--1875,-1891,-1918,-1955,-2001,-2054,-2108,-2161,-2208,-2247,-2278,-2301,-2317,-2331,-2344,-2360,-2381,-2406,-2435,-2466,-2498,
--2526,-2550,-2569,-2583,-2594,-2604,-2615,-2629,-2648,-2673,-2701,-2732,-2764,-2794,-2820,-2843,-2862,-2878,-2894,-2910,-2929,
--2949,-2972,-2996,-3019,-3039,-3057,-3071,-3084,-3097,-3113,-3132,-3156,-3184,-3215,-3247,-3276,-3302,-3323,-3341,-3357,-3376,
--3399,-3429,-3467,-3510,-3556,-3599,-3635,-3660,-3672,-3671,-3661,-3646,-3633,-3625,-3627,-3639,-3658,-3682,-3706,-3724,-3734,
--3736,-3732,-3729,-3731,-3747,-3780,-3834,-3907,-3995,-4091,-4187,-4274,-4345,-4396,-4424,-4429,-4415,-4387,-4350,-4310,-4274,
--4245,-4227,-4221,-4227,-4245,-4270,-4299,-4329,-4354,-4373,-4384,-4387,-4385,-4380,-4377,-4381,-4395,-4420,-4457,-4503,-4554,
--4608,-4660,-4709,-4753,-4794,-4833,-4873,-4917,-4963,-5012,-5059,-5102,-5136,-5158,-5168,-5168,-5159,-5149,-5142,-5144,-5157,
--5182,-5217,-5258,-5302,-5342,-5375,-5401,-5420,-5433,-5444,-5455,-5467,-5482,-5497,-5511,-5519,-5521,-5514,-5499,-5478,-5455,
--5432,-5413,-5400,-5393,-5391,-5392,-5393,-5392,-5387,-5380,-5372,-5367,-5366,-5373,-5389,-5413,-5444,-5478,-5510,-5538,-5557,
--5567,-5567,-5559,-5545,-5530,-5516,-5505,-5500,-5502,-5510,-5523,-5540,-5561,-5585,-5610,-5636,-5663,-5691,-5718,-5745,-5771,
--5795,-5816,-5834,-5848,-5859,-5866,-5869,-5870,-5867,-5863,-5858,-5853,-5848,-5843,-5840,-5839,-5838,-5837,-5836,-5835,-5832,
--5828,-5823,-5817,-5812,-5807,-5805,-5804,-5806,-5809,-5813,-5818,-5822,-5826,-5829,-5832,-5837,-5843,-5852,-5864,-5881,-5900,
--5922,-5944,-5965,-5982,-5995,-6003,-6007,-6007,-6005,-6002,-6002,-6005,-6013,-6025,-6042,-6062,-6083,-6103,-6121,-6134,-6143,
--6147,-6147,-6146,-6145,-6146,-6150,-6159,-6174,-6192,-6214,-6237,-6259,-6278,-6294,-6304,-6309,-6310,-6307,-6303,-6298,-6294,
--6291,-6290,-6291,-6291,-6291,-6288,-6282,-6273,-6261,-6246,-6229,-6213,-6197,-6183,-6171,-6161,-6153,-6146,-6140,-6132,-6124,
--6115,-6104,-6093,-6081,-6070,-6060,-6051,-6043,-6037,-6033,-6029,-6026,-6023,-6019,-6015,-6009,-6002,-5994,-5985,-5976,-5968,
--5960,-5955,-5952,-5952,-5954,-5959,-5965,-5972,-5978,-5984,-5987,-5988,-5988,-5986,-5982,-5977,-5972,-5965,-5958,-5951,-5943,
--5935,-5927,-5920,-5915,-5912,-5911,-5913,-5916,-5919,-5922,-5922,-5919,-5913,-5903,-5890,-5874,-5858,-5842,-5827,-5813,-5802,
--5793,-5785,-5777,-5769,-5759,-5748,-5736,-5723,-5709,-5696,-5683,-5671,-5661,-5653,-5646,-5640,-5633,-5626,-5617,-5606,-5593,
--5577,-5560,-5541,-5522,-5504,-5486,-5469,-5454,-5441,-5428,-5415,-5403,-5390,-5376,-5362,-5347,-5332,-5316,-5301,-5286,-5271,
--5255,-5239,-5223,-5205,-5187,-5168,-5149,-5131,-5114,-5098,-5083,-5070,-5057,-5044,-5031,-5017,-5002,-4986,-4969,-4951,-4933,
--4914,-4895,-4876,-4856,-4835,-4813,-4790,-4766,-4742,-4718,-4694,-4671,-4650,-4630,-4611,-4592,-4574,-4555,-4536,-4516,-4496,
--4475,-4454,-4433,-4413,-4393,-4373,-4354,-4335,-4315,-4296,-4277,-4258,-4239,-4220,-4201,-4182,-4163,-4144,-4125,-4105,-4086,
--4069,-4054,-4040,-4029,-4020,-4012,-4004,-3995,-3984,-3970,-3953,-3934,-3912,-3889,-3866,-3842,-3818,-3794,-3768,-3741,-3712,
--3681,-3650,-3620,-3593,-3572,-3557,-3549,-3548,-3552,-3559,-3566,-3571,-3571,-3567,-3557,-3544,-3529,-3514,-3500,-3489,-3481,
--3475,-3470,-3464,-3456,-3447,-3436,-3423,-3411,-3400,-3391,-3386,-3383,-3382,-3382,-3381,-3378,-3371,-3361,-3347,-3331,-3313,
--3295,-3278,-3263,-3250,-3238,-3229,-3220,-3212,-3203,-3195,-3186,-3177,-3167,-3158,-3149,-3140,-3131,-3121,-3111,-3100,-3088,
--3075,-3060,-3044,-3027,-3009,-2989,-2968,-2947,-2926,-2905,-2886,-2869,-2854,-2842,-2833,-2825,-2816,-2807,-2794,-2778,-2757,
--2732,-2705,-2677,-2650,-2627,-2608,-2594,-2585,-2578,-2572,-2565,-2555,-2544,-2531,-2518,-2508,-2503,-2504,-2510,-2520,-2531,
--2538,-2537,-2523,-2495,-2453,-2400,-2339,-2278,-2220,-2170,-2132,-2104,-2084,-2069,-2054,-2036,-2011,-1980,-1942,-1902,-1864,
--1830,-1804,-1785,-1774,-1768,-1763,-1756,-1743,-1723,-1697,-1665,-1631,-1598,-1567,-1542,-1522,-1508,-1497,-1488,-1478,-1466,
--1451,-1433,-1411,-1386,-1359,-1330,-1300,-1268,-1235,-1200,-1163,-1125,-1087,-1049,-1012,-977,-945,-916,-889,-864,-840,
--817,-795,-772,-750,-728,-705,-683,-661,-639,-616,-592,-565,-537,-505,-472,-437,-403,-369,-338,-310,-286,
--265,-245,-225,-201,-171,-134,-87,-32,30,97,166,232,292,344,387,420,445,464,480,497,516,
-540,567,599,634,672,711,751,793,836,882,931,983,1037,1093,1147,1197,1239,1272,1292,1299,1292,
-1272,1241,1200,1152,1100,1047,995,945,899,858,821,788,758,730,703,677,651,626,603,584,569,
-560,557,561,569,580,591,601,606,605,597,581,559,530,498,463,428,392,359,328,299,274,
-252,233,218,207,200,198,199,203,211,221,232,245,258,271,284,296,308,319,329,338,346,
-352,358,362,365,368,369,369,370,369,368,367,366,365,365,364,363,363,363,363,363,363,
-364,364,366,368,371,374,378,382,387,392,396,399,402,403,404,404,404,403,403,403,404,
-405,407,410,412,414,415,415,413,408,402,394,385,374,363,351,339,328,317,306,295,284,
-273,262,252,242,233,225,219,214,210,208,207,206,206,206,206,205,205,205,205,206,208,
-211,214,217,221,225,229,233,236,239,242,244,246,248,250,252,255,257,261,264,268,272,
-277,283,289,295,302,309,316,324,331,339,347,356,364,373,382,390,399,407,416,424,433,
-441,450,459,467,475,482,488,493,496,499,501,504,508,514,521,531,542,555,568,582,596,
-610,625,639,654,670,687,704,721,737,751,763,773,782,789,797,807,819,834,852,872,892,
-912,928,941,948,951,949,944,937,929,922,916,911,909,908,909,913,919,929,943,962,985,
-1011,1038,1064,1088,1107,1120,1127,1238,1242,1241,1236,1229,1223,1220,1219,1223,1228,1236,1244,1253,1262,
-1271,1282,1295,1311,1330,1352,1375,1399,1422,1444,1464,1481,1495,1506,1514,1520,1522,1520,1514,1505,1493,
-1479,1467,1457,1454,1459,1472,1493,1522,1554,1586,1616,1641,1659,1670,1674,1675,1675,1676,1681,1691,1705,
-1725,1748,1772,1796,1819,1841,1859,1874,1886,1892,1892,1884,1867,1841,1806,1764,1718,1670,1625,1586,1557,
-1539,1532,1535,1546,1562,1580,1597,1612,1623,1632,1640,1647,1655,1665,1677,1692,1708,1725,1741,1757,1771,
-1783,1795,1807,1820,1835,1853,1873,1895,1918,1942,1966,1989,2011,2032,2052,2073,2096,2120,2147,2174,2201,
-2225,2244,2257,2261,2257,2246,2229,2211,2195,2184,2181,2189,2205,2229,2256,2282,2303,2315,2316,2305,2284,
-2254,2218,2180,2143,2107,2074,2043,2013,1986,1960,1938,1921,1912,1913,1927,1953,1991,2037,2088,2139,2184,
-2222,2251,2272,2289,2305,2326,2357,2400,2456,2524,2599,2675,2747,2810,2858,2891,2908,2913,2908,2898,2886,
-2875,2864,2855,2843,2829,2809,2782,2750,2714,2677,2642,2613,2592,2583,2585,2598,2620,2650,2686,2726,2770,
-2818,2868,2921,2975,3028,3078,3122,3156,3177,3182,3170,3142,3099,3046,2987,2927,2870,2821,2783,2756,2741,
-2735,2736,2739,2741,2739,2730,2714,2692,2665,2638,2614,2597,2590,2593,2608,2630,2657,2683,2704,2715,2714,
-2702,2680,2654,2629,2612,2608,2620,2649,2694,2748,2806,2859,2901,2924,2925,2904,2861,2800,2728,2651,2575,
-2504,2442,2391,2349,2314,2284,2255,2225,2191,2152,2108,2061,2011,1960,1912,1867,1827,1792,1762,1736,1714,
-1695,1679,1664,1651,1639,1630,1623,1618,1615,1612,1610,1608,1606,1605,1604,1605,1609,1615,1624,1634,1645,
-1653,1658,1657,1651,1638,1622,1603,1584,1569,1559,1555,1557,1564,1572,1581,1586,1586,1581,1570,1554,1536,
-1516,1497,1480,1464,1450,1437,1423,1408,1392,1373,1352,1330,1307,1284,1262,1241,1222,1204,1188,1173,1158,
-1143,1127,1109,1089,1064,1037,1008,979,951,927,908,898,894,897,905,913,919,919,911,895,871,
-841,808,776,746,721,699,680,661,637,607,568,520,463,401,335,270,208,151,99,52,7,
--37,-84,-135,-189,-247,-307,-368,-427,-483,-535,-582,-625,-664,-701,-735,-769,-803,-838,-874,-913,-953,
--995,-1039,-1085,-1131,-1177,-1223,-1266,-1308,-1348,-1386,-1423,-1459,-1494,-1528,-1562,-1595,-1626,-1656,-1684,-1710,-1735,
--1759,-1784,-1808,-1831,-1852,-1871,-1884,-1892,-1893,-1889,-1883,-1876,-1873,-1878,-1894,-1923,-1965,-2017,-2075,-2135,-2192,
--2241,-2281,-2308,-2327,-2338,-2346,-2355,-2370,-2390,-2418,-2451,-2486,-2521,-2551,-2575,-2592,-2603,-2610,-2617,-2626,-2641,
--2663,-2691,-2725,-2762,-2798,-2830,-2858,-2880,-2897,-2911,-2924,-2939,-2956,-2977,-3001,-3025,-3048,-3069,-3086,-3100,-3112,
--3125,-3141,-3161,-3187,-3217,-3250,-3282,-3311,-3336,-3354,-3368,-3380,-3393,-3412,-3438,-3472,-3513,-3556,-3598,-3633,-3656,
--3666,-3664,-3651,-3635,-3619,-3610,-3610,-3622,-3644,-3671,-3699,-3722,-3739,-3747,-3749,-3751,-3757,-3776,-3812,-3868,-3943,
--4035,-4135,-4236,-4328,-4404,-4458,-4487,-4491,-4474,-4441,-4400,-4356,-4317,-4287,-4269,-4265,-4272,-4290,-4313,-4339,-4364,
--4383,-4395,-4400,-4398,-4392,-4386,-4383,-4388,-4401,-4426,-4460,-4503,-4553,-4605,-4658,-4710,-4760,-4809,-4857,-4905,-4953,
--5001,-5047,-5088,-5121,-5144,-5156,-5158,-5154,-5146,-5141,-5143,-5155,-5180,-5215,-5259,-5308,-5355,-5397,-5430,-5455,-5471,
--5480,-5488,-5495,-5505,-5518,-5532,-5546,-5557,-5562,-5559,-5548,-5530,-5507,-5482,-5458,-5438,-5421,-5410,-5402,-5398,-5395,
--5393,-5392,-5392,-5396,-5404,-5418,-5437,-5461,-5488,-5516,-5542,-5564,-5580,-5589,-5593,-5592,-5587,-5581,-5575,-5569,-5565,
--5563,-5561,-5562,-5563,-5566,-5571,-5579,-5591,-5607,-5627,-5651,-5679,-5709,-5741,-5773,-5804,-5833,-5860,-5882,-5901,-5914,
--5923,-5928,-5928,-5925,-5920,-5913,-5907,-5900,-5895,-5891,-5886,-5882,-5876,-5868,-5859,-5849,-5839,-5829,-5822,-5818,-5816,
--5818,-5823,-5828,-5833,-5837,-5839,-5839,-5838,-5838,-5841,-5847,-5859,-5876,-5899,-5924,-5951,-5977,-5999,-6016,-6027,-6032,
--6033,-6031,-6029,-6028,-6031,-6039,-6051,-6067,-6086,-6105,-6125,-6143,-6158,-6172,-6183,-6194,-6205,-6216,-6229,-6243,-6259,
--6275,-6291,-6305,-6317,-6326,-6332,-6335,-6336,-6335,-6332,-6329,-6327,-6324,-6323,-6322,-6320,-6319,-6316,-6311,-6304,-6296,
--6286,-6274,-6261,-6247,-6234,-6221,-6209,-6199,-6191,-6185,-6180,-6176,-6173,-6171,-6169,-6167,-6164,-6160,-6155,-6148,-6141,
--6133,-6124,-6115,-6105,-6096,-6086,-6076,-6067,-6057,-6047,-6038,-6030,-6024,-6020,-6018,-6019,-6023,-6029,-6036,-6044,-6052,
--6058,-6063,-6066,-6067,-6066,-6064,-6061,-6057,-6053,-6049,-6043,-6036,-6028,-6018,-6008,-5998,-5988,-5981,-5976,-5973,-5974,
--5976,-5979,-5981,-5982,-5980,-5975,-5966,-5954,-5939,-5924,-5908,-5893,-5879,-5866,-5855,-5844,-5833,-5821,-5808,-5793,-5777,
--5761,-5744,-5727,-5713,-5700,-5691,-5683,-5677,-5673,-5668,-5661,-5653,-5641,-5627,-5610,-5590,-5570,-5550,-5531,-5514,-5500,
--5488,-5478,-5469,-5460,-5450,-5440,-5427,-5412,-5395,-5377,-5359,-5339,-5320,-5302,-5283,-5265,-5248,-5231,-5214,-5197,-5180,
--5164,-5148,-5133,-5118,-5102,-5087,-5071,-5055,-5039,-5022,-5005,-4988,-4970,-4952,-4933,-4913,-4892,-4870,-4847,-4823,-4799,
--4775,-4752,-4729,-4708,-4687,-4667,-4646,-4625,-4604,-4581,-4558,-4534,-4512,-4490,-4470,-4452,-4435,-4418,-4402,-4385,-4367,
--4347,-4325,-4302,-4279,-4255,-4233,-4211,-4192,-4174,-4156,-4140,-4124,-4108,-4092,-4077,-4062,-4048,-4034,-4021,-4008,-3995,
--3981,-3966,-3950,-3933,-3917,-3901,-3885,-3870,-3854,-3837,-3817,-3794,-3766,-3735,-3701,-3666,-3633,-3603,-3580,-3565,-3557,
--3556,-3560,-3566,-3572,-3576,-3575,-3569,-3559,-3546,-3532,-3519,-3507,-3497,-3490,-3484,-3478,-3471,-3463,-3453,-3442,-3431,
--3420,-3411,-3405,-3401,-3398,-3396,-3393,-3388,-3381,-3370,-3356,-3339,-3322,-3304,-3287,-3272,-3260,-3249,-3241,-3234,-3228,
--3223,-3219,-3214,-3209,-3204,-3198,-3191,-3183,-3174,-3164,-3151,-3138,-3122,-3106,-3089,-3071,-3053,-3034,-3015,-2995,-2976,
--2957,-2939,-2922,-2908,-2896,-2886,-2877,-2869,-2860,-2848,-2832,-2810,-2784,-2754,-2722,-2690,-2661,-2636,-2618,-2605,-2598,
--2593,-2590,-2585,-2579,-2571,-2563,-2556,-2552,-2554,-2562,-2574,-2589,-2601,-2606,-2599,-2576,-2536,-2480,-2413,-2339,-2265,
--2199,-2146,-2108,-2086,-2076,-2076,-2079,-2081,-2077,-2067,-2049,-2027,-2002,-1979,-1958,-1943,-1930,-1920,-1908,-1892,-1870,
--1840,-1803,-1760,-1714,-1668,-1625,-1587,-1554,-1527,-1505,-1485,-1465,-1444,-1422,-1396,-1368,-1338,-1306,-1272,-1238,-1202,
--1166,-1129,-1091,-1054,-1019,-986,-957,-932,-912,-895,-882,-870,-858,-844,-828,-809,-787,-762,-735,-706,-677,
--647,-617,-587,-556,-526,-494,-463,-432,-401,-373,-348,-325,-305,-286,-268,-248,-224,-194,-157,-112,-60,
--1,62,128,192,254,309,357,397,430,458,481,502,523,546,571,600,633,670,711,755,802,
-851,902,954,1006,1059,1110,1160,1206,1247,1283,1310,1329,1337,1334,1318,1290,1249,1199,1140,1075,1009,
-943,880,824,774,731,694,662,634,608,584,561,541,524,511,504,502,505,511,519,526,528,
-524,513,493,466,433,395,356,317,280,246,216,190,168,149,133,119,109,101,97,97,100,
-107,116,128,142,156,170,183,196,208,218,228,237,245,252,259,265,271,275,279,281,284,
-286,287,289,291,293,295,297,298,300,302,304,307,310,314,319,324,330,336,342,347,350,
-353,355,355,356,356,356,357,358,360,362,365,368,370,371,372,372,372,370,368,366,362,
-358,352,345,337,328,318,307,296,285,274,264,254,244,235,226,217,208,200,193,186,182,
-178,176,176,176,177,179,180,181,182,182,182,183,184,186,189,193,197,201,206,210,213,
-216,219,220,222,223,225,227,229,232,236,239,244,248,253,258,262,267,272,276,281,286,
-291,297,304,312,320,329,338,348,358,368,377,387,396,405,414,423,431,439,446,453,458,
-463,468,472,477,483,489,498,508,519,532,545,560,575,591,609,627,647,669,691,714,735,
-756,774,789,801,810,818,825,832,841,852,865,880,895,909,922,933,941,945,948,948,948,
-947,946,945,945,944,944,945,948,954,965,982,1006,1035,1070,1107,1143,1177,1205,1225,1238,1357,
-1366,1365,1360,1351,1343,1338,1336,1338,1344,1352,1361,1370,1378,1385,1392,1400,1410,1421,1434,1448,1462,
-1477,1489,1500,1509,1516,1521,1524,1526,1527,1526,1524,1518,1511,1501,1489,1479,1470,1466,1468,1476,1492,
-1515,1543,1574,1606,1637,1665,1689,1708,1722,1732,1740,1745,1749,1753,1759,1766,1777,1792,1809,1830,1851,
-1872,1889,1900,1901,1891,1870,1837,1795,1747,1698,1651,1611,1581,1562,1556,1559,1572,1589,1610,1632,1653,
-1672,1691,1710,1730,1751,1774,1798,1823,1846,1866,1883,1896,1904,1910,1913,1917,1922,1930,1940,1954,1970,
-1988,2005,2022,2037,2050,2062,2073,2086,2099,2115,2133,2151,2169,2184,2194,2198,2194,2183,2167,2149,2131,
-2117,2111,2115,2127,2149,2175,2204,2230,2250,2261,2262,2253,2235,2210,2183,2155,2127,2101,2076,2050,2024,
-1996,1968,1940,1917,1900,1895,1902,1924,1958,2002,2051,2100,2145,2181,2209,2229,2244,2259,2281,2313,2359,
-2420,2492,2571,2651,2725,2787,2831,2858,2866,2860,2844,2823,2802,2785,2774,2768,2766,2763,2758,2748,2732,
-2710,2683,2655,2628,2607,2593,2588,2592,2606,2628,2655,2688,2724,2763,2803,2845,2887,2928,2966,2999,3025,
-3041,3046,3038,3017,2985,2944,2897,2849,2802,2760,2726,2701,2685,2677,2676,2677,2679,2678,2672,2660,2642,
-2621,2599,2579,2565,2559,2562,2575,2594,2618,2640,2657,2665,2663,2651,2631,2609,2589,2578,2580,2599,2634,
-2684,2742,2801,2854,2893,2913,2909,2883,2835,2772,2699,2623,2549,2482,2424,2375,2334,2297,2262,2224,2183,
-2136,2084,2028,1972,1917,1866,1821,1782,1752,1728,1710,1696,1685,1677,1670,1665,1661,1658,1656,1656,1655,
-1654,1652,1648,1642,1635,1627,1620,1615,1613,1616,1622,1630,1639,1646,1649,1647,1638,1623,1605,1584,1565,
-1549,1540,1537,1541,1550,1561,1571,1578,1580,1574,1563,1546,1526,1505,1484,1466,1450,1436,1424,1412,1399,
-1384,1366,1347,1325,1303,1280,1259,1239,1221,1205,1190,1175,1160,1143,1124,1101,1075,1045,1013,979,945,
-914,887,865,850,841,838,838,838,836,830,817,797,771,740,707,674,642,614,589,565,542,
-516,484,447,402,351,296,238,180,125,74,27,-15,-56,-97,-139,-184,-233,-285,-340,-396,-451,
--505,-555,-602,-644,-683,-720,-754,-788,-822,-857,-894,-932,-972,-1013,-1055,-1097,-1139,-1180,-1220,-1259,-1297,
--1334,-1371,-1408,-1445,-1482,-1519,-1554,-1588,-1620,-1649,-1676,-1701,-1725,-1748,-1771,-1795,-1819,-1841,-1860,-1874,-1882,
--1884,-1882,-1876,-1871,-1871,-1879,-1900,-1934,-1982,-2040,-2104,-2170,-2231,-2283,-2324,-2351,-2367,-2375,-2381,-2387,-2399,
--2418,-2445,-2478,-2514,-2548,-2578,-2601,-2617,-2627,-2633,-2640,-2650,-2666,-2690,-2722,-2758,-2796,-2831,-2862,-2886,-2904,
--2915,-2924,-2933,-2944,-2960,-2981,-3005,-3032,-3058,-3081,-3102,-3118,-3132,-3146,-3161,-3180,-3204,-3231,-3260,-3289,-3315,
--3335,-3351,-3362,-3372,-3384,-3401,-3426,-3459,-3499,-3543,-3585,-3622,-3649,-3664,-3666,-3660,-3648,-3637,-3630,-3633,-3645,
--3665,-3690,-3717,-3740,-3756,-3765,-3769,-3772,-3779,-3797,-3831,-3884,-3955,-4042,-4137,-4233,-4321,-4394,-4447,-4476,-4482,
--4467,-4438,-4400,-4361,-4325,-4297,-4281,-4277,-4283,-4298,-4318,-4341,-4362,-4381,-4395,-4405,-4411,-4416,-4421,-4429,-4443,
--4463,-4490,-4525,-4566,-4612,-4661,-4712,-4762,-4812,-4861,-4908,-4954,-4997,-5037,-5071,-5099,-5119,-5131,-5136,-5137,-5135,
--5134,-5140,-5153,-5177,-5210,-5251,-5297,-5343,-5386,-5422,-5450,-5469,-5481,-5489,-5496,-5504,-5515,-5530,-5547,-5565,-5581,
--5592,-5596,-5592,-5580,-5562,-5540,-5516,-5493,-5473,-5457,-5446,-5439,-5437,-5438,-5442,-5449,-5459,-5470,-5483,-5497,-5511,
--5525,-5537,-5549,-5560,-5570,-5580,-5590,-5601,-5613,-5625,-5636,-5646,-5651,-5653,-5650,-5644,-5635,-5625,-5616,-5611,-5609,
--5613,-5623,-5637,-5656,-5678,-5701,-5727,-5752,-5778,-5804,-5829,-5854,-5877,-5897,-5914,-5927,-5936,-5942,-5944,-5943,-5941,
--5937,-5932,-5926,-5919,-5910,-5898,-5884,-5868,-5851,-5836,-5822,-5812,-5807,-5807,-5811,-5818,-5827,-5835,-5842,-5846,-5849,
--5850,-5853,-5858,-5867,-5881,-5900,-5923,-5949,-5975,-5998,-6017,-6031,-6040,-6045,-6046,-6047,-6048,-6052,-6060,-6072,-6086,
--6103,-6121,-6139,-6155,-6171,-6185,-6199,-6214,-6229,-6245,-6263,-6281,-6299,-6315,-6329,-6340,-6348,-6352,-6354,-6355,-6354,
--6354,-6354,-6355,-6356,-6357,-6358,-6357,-6355,-6352,-6346,-6339,-6331,-6322,-6313,-6304,-6294,-6285,-6277,-6268,-6260,-6253,
--6248,-6244,-6241,-6241,-6243,-6246,-6250,-6254,-6257,-6257,-6255,-6250,-6241,-6229,-6215,-6200,-6184,-6167,-6152,-6138,-6125,
--6114,-6105,-6098,-6093,-6090,-6089,-6091,-6095,-6100,-6107,-6113,-6120,-6125,-6129,-6131,-6131,-6130,-6127,-6124,-6121,-6118,
--6114,-6110,-6104,-6097,-6088,-6077,-6065,-6052,-6039,-6028,-6019,-6014,-6011,-6012,-6015,-6018,-6022,-6024,-6023,-6019,-6011,
--6001,-5988,-5974,-5959,-5944,-5930,-5915,-5901,-5887,-5872,-5856,-5839,-5820,-5801,-5782,-5764,-5747,-5733,-5722,-5713,-5707,
--5702,-5697,-5691,-5683,-5672,-5658,-5640,-5621,-5600,-5580,-5561,-5544,-5531,-5520,-5513,-5507,-5501,-5495,-5487,-5476,-5462,
--5446,-5427,-5406,-5385,-5363,-5342,-5322,-5303,-5286,-5269,-5254,-5239,-5224,-5209,-5194,-5178,-5161,-5144,-5126,-5108,-5090,
--5072,-5053,-5035,-5017,-4999,-4980,-4960,-4939,-4917,-4893,-4869,-4845,-4821,-4798,-4776,-4756,-4736,-4717,-4698,-4678,-4656,
--4633,-4608,-4583,-4558,-4534,-4513,-4495,-4479,-4466,-4454,-4442,-4429,-4412,-4393,-4369,-4343,-4316,-4287,-4260,-4235,-4212,
--4191,-4173,-4156,-4140,-4125,-4109,-4092,-4076,-4058,-4041,-4024,-4007,-3991,-3976,-3962,-3949,-3938,-3929,-3923,-3918,-3915,
--3911,-3907,-3899,-3886,-3868,-3843,-3813,-3779,-3744,-3709,-3678,-3652,-3633,-3620,-3613,-3610,-3609,-3608,-3605,-3600,-3592,
--3582,-3570,-3558,-3546,-3536,-3526,-3517,-3508,-3499,-3489,-3478,-3467,-3455,-3444,-3435,-3427,-3421,-3416,-3411,-3406,-3400,
--3391,-3380,-3367,-3352,-3336,-3321,-3306,-3293,-3282,-3273,-3265,-3259,-3254,-3251,-3247,-3244,-3241,-3237,-3233,-3227,-3220,
--3210,-3198,-3184,-3168,-3151,-3133,-3115,-3097,-3080,-3063,-3047,-3031,-3015,-2999,-2983,-2968,-2954,-2941,-2929,-2917,-2904,
--2888,-2870,-2847,-2819,-2787,-2752,-2716,-2683,-2654,-2632,-2617,-2609,-2608,-2610,-2615,-2619,-2623,-2625,-2627,-2629,-2634,
--2643,-2654,-2668,-2680,-2686,-2682,-2662,-2626,-2571,-2501,-2421,-2336,-2254,-2183,-2128,-2091,-2074,-2073,-2084,-2101,-2119,
--2132,-2138,-2137,-2127,-2113,-2095,-2076,-2058,-2041,-2023,-2002,-1977,-1945,-1906,-1860,-1808,-1752,-1695,-1640,-1588,-1540,
--1498,-1460,-1425,-1393,-1363,-1333,-1304,-1274,-1243,-1213,-1182,-1151,-1120,-1089,-1059,-1030,-1004,-981,-963,-949,-939,
--934,-931,-929,-927,-922,-912,-899,-880,-857,-830,-800,-768,-735,-702,-667,-632,-597,-561,-525,-491,-458,
--428,-401,-378,-359,-343,-328,-313,-296,-274,-247,-213,-172,-125,-73,-17,41,99,156,210,260,305,
-345,380,411,438,465,490,518,548,583,624,670,722,778,837,897,956,1011,1064,1112,1155,1195,
-1232,1265,1296,1322,1342,1352,1351,1335,1303,1256,1194,1120,1039,955,875,802,738,687,646,615,590,
-570,551,531,512,492,474,459,448,442,441,444,446,447,442,430,410,382,346,305,262,218,
-177,140,107,80,57,38,23,10,1,-5,-8,-7,-3,4,16,30,45,60,76,90,102,
-113,123,131,140,147,155,163,170,177,183,189,194,198,203,207,211,216,221,226,231,236,
-240,244,248,252,257,264,271,279,287,296,303,309,314,316,316,314,312,310,309,310,312,
-316,321,325,329,332,333,332,329,325,321,316,311,307,303,299,294,289,282,275,266,257,
-247,238,228,220,213,206,199,193,187,182,176,171,166,163,160,159,158,159,160,162,164,
-166,168,169,171,174,177,180,184,189,193,198,202,205,207,209,210,210,211,212,213,214,
-216,219,222,225,228,231,234,237,240,242,245,247,251,255,260,267,275,284,294,305,316,
-328,339,350,359,368,376,383,390,397,403,410,416,423,430,438,446,455,465,475,487,500,
-514,529,545,563,581,601,622,646,670,696,723,749,775,798,819,837,853,865,876,885,894,
-904,914,924,935,946,955,963,970,976,980,984,987,990,992,994,995,993,991,987,983,982,
-986,996,1016,1044,1082,1127,1176,1225,1271,1310,1339,1357,1446,1457,1457,1451,1441,1431,1425,1423,1426,
-1433,1442,1452,1461,1469,1474,1477,1479,1480,1482,1484,1487,1489,1490,1490,1487,1481,1474,1466,1459,1453,
-1448,1446,1446,1446,1445,1443,1438,1431,1422,1413,1406,1403,1406,1416,1435,1461,1494,1531,1569,1605,1638,
-1664,1682,1692,1694,1690,1683,1675,1670,1669,1675,1687,1707,1732,1758,1783,1802,1812,1812,1799,1775,1742,
-1703,1662,1623,1592,1570,1559,1559,1570,1590,1618,1650,1685,1722,1760,1799,1839,1879,1920,1960,1998,2032,
-2062,2086,2104,2115,2121,2123,2122,2120,2118,2117,2116,2116,2116,2113,2108,2099,2088,2074,2060,2047,2037,
-2031,2031,2036,2045,2057,2069,2078,2083,2083,2078,2068,2057,2046,2039,2039,2045,2059,2079,2102,2126,2147,
-2163,2172,2172,2166,2155,2141,2126,2113,2102,2092,2083,2073,2058,2040,2017,1991,1966,1943,1929,1924,1931,
-1950,1979,2014,2052,2087,2117,2141,2160,2175,2191,2213,2244,2287,2342,2407,2477,2547,2610,2660,2696,2713,
-2715,2705,2686,2666,2648,2638,2635,2641,2652,2666,2679,2687,2690,2685,2675,2660,2645,2632,2623,2620,2624,
-2634,2648,2666,2685,2704,2723,2740,2757,2773,2788,2803,2817,2828,2836,2839,2836,2826,2809,2786,2759,2728,
-2698,2669,2644,2624,2610,2601,2597,2595,2594,2592,2587,2579,2568,2555,2543,2532,2526,2526,2532,2544,2558,
-2573,2586,2593,2592,2582,2567,2547,2528,2516,2514,2527,2556,2599,2654,2715,2774,2824,2859,2875,2869,2841,
-2796,2736,2670,2601,2535,2475,2423,2376,2334,2292,2248,2199,2144,2083,2017,1950,1884,1823,1771,1728,1696,
-1675,1663,1660,1662,1668,1676,1686,1695,1703,1711,1717,1720,1721,1719,1713,1702,1689,1672,1655,1639,1624,
-1614,1608,1607,1608,1612,1615,1616,1614,1607,1596,1583,1569,1556,1547,1543,1544,1549,1557,1565,1571,1573,
-1569,1558,1542,1521,1497,1474,1451,1431,1414,1399,1387,1375,1363,1349,1333,1316,1297,1277,1256,1236,1217,
-1198,1180,1162,1143,1123,1102,1079,1053,1026,997,967,936,905,876,849,824,802,784,768,753,738,
-722,704,681,655,625,591,556,519,482,446,411,376,341,304,266,225,181,135,88,40,-5,
--49,-91,-130,-168,-205,-242,-281,-322,-366,-411,-457,-503,-549,-593,-634,-672,-709,-743,-776,-809,-842,
--877,-913,-950,-988,-1026,-1065,-1103,-1140,-1175,-1208,-1240,-1272,-1303,-1334,-1367,-1401,-1437,-1474,-1511,-1547,-1580,
--1611,-1637,-1660,-1680,-1698,-1715,-1733,-1752,-1771,-1791,-1811,-1827,-1841,-1851,-1858,-1864,-1871,-1884,-1905,-1938,-1982,
--2037,-2101,-2169,-2236,-2297,-2347,-2385,-2408,-2420,-2425,-2426,-2428,-2437,-2453,-2477,-2509,-2544,-2579,-2611,-2638,-2658,
--2673,-2686,-2698,-2714,-2735,-2762,-2795,-2830,-2865,-2896,-2921,-2939,-2949,-2955,-2958,-2963,-2971,-2986,-3007,-3034,-3063,
--3092,-3119,-3142,-3160,-3174,-3186,-3197,-3210,-3226,-3245,-3266,-3287,-3307,-3323,-3336,-3347,-3357,-3370,-3387,-3412,-3445,
--3485,-3529,-3573,-3613,-3646,-3669,-3682,-3686,-3685,-3683,-3682,-3688,-3699,-3717,-3739,-3761,-3781,-3796,-3807,-3814,-3822,
--3834,-3854,-3888,-3936,-3999,-4073,-4153,-4233,-4305,-4366,-4409,-4434,-4440,-4431,-4410,-4382,-4353,-4326,-4306,-4293,-4289,
--4294,-4305,-4322,-4342,-4365,-4389,-4412,-4436,-4459,-4482,-4505,-4530,-4557,-4587,-4619,-4656,-4696,-4739,-4785,-4832,-4880,
--4927,-4971,-5013,-5049,-5080,-5104,-5120,-5130,-5134,-5133,-5131,-5128,-5129,-5136,-5150,-5174,-5205,-5244,-5288,-5333,-5376,
--5415,-5448,-5474,-5494,-5508,-5520,-5531,-5543,-5558,-5576,-5596,-5616,-5635,-5651,-5661,-5666,-5663,-5655,-5642,-5625,-5607,
--5589,-5574,-5562,-5554,-5551,-5552,-5556,-5562,-5568,-5573,-5575,-5574,-5567,-5558,-5546,-5534,-5526,-5522,-5527,-5540,-5562,
--5591,-5624,-5658,-5689,-5715,-5734,-5744,-5747,-5744,-5738,-5732,-5727,-5726,-5728,-5732,-5737,-5742,-5746,-5748,-5747,-5746,
--5745,-5746,-5752,-5762,-5778,-5797,-5819,-5843,-5865,-5886,-5903,-5916,-5926,-5932,-5935,-5935,-5932,-5925,-5916,-5903,-5887,
--5869,-5852,-5835,-5822,-5813,-5810,-5812,-5819,-5829,-5841,-5852,-5862,-5870,-5877,-5882,-5888,-5896,-5907,-5921,-5938,-5957,
--5977,-5996,-6012,-6025,-6034,-6041,-6046,-6051,-6057,-6066,-6078,-6092,-6108,-6124,-6140,-6154,-6167,-6178,-6188,-6199,-6210,
--6224,-6241,-6259,-6280,-6301,-6320,-6337,-6351,-6361,-6368,-6372,-6374,-6376,-6378,-6381,-6385,-6390,-6394,-6397,-6398,-6397,
--6392,-6386,-6377,-6367,-6357,-6348,-6339,-6332,-6325,-6321,-6317,-6314,-6312,-6312,-6313,-6315,-6320,-6326,-6333,-6340,-6347,
--6351,-6352,-6349,-6342,-6331,-6315,-6297,-6277,-6256,-6236,-6217,-6201,-6188,-6177,-6170,-6165,-6163,-6162,-6163,-6165,-6169,
--6172,-6176,-6179,-6182,-6183,-6183,-6181,-6178,-6174,-6170,-6164,-6159,-6153,-6148,-6141,-6134,-6126,-6116,-6105,-6093,-6080,
--6068,-6058,-6049,-6043,-6040,-6039,-6041,-6044,-6047,-6049,-6050,-6048,-6043,-6035,-6025,-6013,-5999,-5984,-5968,-5952,-5936,
--5919,-5902,-5884,-5865,-5846,-5827,-5808,-5790,-5774,-5760,-5749,-5740,-5733,-5727,-5721,-5714,-5705,-5694,-5681,-5665,-5647,
--5628,-5610,-5592,-5577,-5564,-5553,-5545,-5538,-5531,-5524,-5515,-5504,-5490,-5474,-5456,-5437,-5416,-5396,-5376,-5356,-5338,
--5321,-5305,-5290,-5275,-5260,-5245,-5229,-5213,-5195,-5177,-5158,-5139,-5120,-5101,-5083,-5064,-5046,-5027,-5007,-4987,-4964,
--4941,-4916,-4891,-4867,-4843,-4821,-4800,-4782,-4765,-4748,-4730,-4712,-4691,-4667,-4642,-4616,-4590,-4566,-4544,-4525,-4510,
--4498,-4487,-4477,-4466,-4452,-4434,-4413,-4389,-4362,-4334,-4306,-4279,-4254,-4231,-4211,-4191,-4173,-4155,-4137,-4118,-4100,
--4081,-4063,-4045,-4029,-4014,-4000,-3988,-3977,-3969,-3962,-3959,-3957,-3957,-3958,-3959,-3957,-3952,-3941,-3925,-3903,-3875,
--3844,-3810,-3777,-3746,-3720,-3697,-3681,-3668,-3660,-3653,-3648,-3642,-3636,-3628,-3619,-3609,-3597,-3586,-3574,-3561,-3548,
--3535,-3522,-3509,-3496,-3485,-3474,-3465,-3457,-3451,-3445,-3439,-3432,-3424,-3414,-3403,-3391,-3377,-3364,-3350,-3338,-3326,
--3316,-3306,-3298,-3290,-3284,-3278,-3273,-3269,-3266,-3263,-3259,-3254,-3247,-3238,-3226,-3211,-3195,-3177,-3159,-3141,-3124,
--3108,-3094,-3080,-3066,-3052,-3037,-3021,-3004,-2985,-2966,-2946,-2925,-2903,-2879,-2852,-2823,-2792,-2759,-2725,-2692,-2662,
--2638,-2620,-2609,-2606,-2608,-2615,-2625,-2635,-2646,-2655,-2664,-2673,-2683,-2693,-2704,-2713,-2717,-2712,-2696,-2664,-2615,
--2550,-2473,-2388,-2301,-2220,-2151,-2100,-2069,-2057,-2063,-2082,-2108,-2135,-2158,-2173,-2180,-2176,-2164,-2145,-2121,-2095,
--2067,-2036,-2003,-1966,-1925,-1878,-1826,-1770,-1710,-1649,-1588,-1529,-1474,-1423,-1376,-1335,-1298,-1265,-1235,-1209,-1185,
--1163,-1142,-1122,-1102,-1083,-1064,-1046,-1031,-1018,-1008,-1002,-999,-999,-999,-1000,-998,-994,-985,-971,-953,-931,
--907,-881,-854,-826,-797,-767,-735,-701,-664,-625,-585,-546,-510,-477,-449,-427,-409,-395,-383,-369,-354,
--334,-308,-277,-241,-201,-158,-112,-65,-18,29,77,124,170,215,257,297,334,368,401,434,469,
-508,553,605,665,731,802,873,943,1007,1065,1114,1156,1191,1222,1249,1274,1297,1317,1330,1333,1323,
-1296,1251,1189,1113,1026,935,847,767,699,645,606,579,561,548,536,521,503,482,459,435,415,
-398,387,380,376,371,364,352,332,304,269,228,183,138,95,55,20,-8,-32,-52,-68,-80,
--90,-96,-98,-97,-91,-82,-70,-55,-39,-22,-7,6,17,27,36,43,51,59,67,75,83,
-91,99,106,111,117,122,128,134,141,149,156,164,171,177,183,187,191,195,200,205,213,
-221,229,237,244,250,253,254,254,252,251,250,251,253,258,263,268,272,275,276,275,272,
-268,263,259,254,251,249,247,244,241,237,230,223,214,205,196,187,180,175,171,168,165,
-163,161,159,156,153,150,148,146,145,144,145,146,148,150,152,155,158,161,165,170,174,
-179,184,188,191,194,196,198,198,199,199,199,199,199,200,200,201,202,202,203,204,205,
-206,208,211,215,220,225,233,242,251,262,274,286,298,310,321,331,339,346,352,357,361,
-365,370,375,381,389,398,409,423,437,454,472,491,512,533,556,580,604,630,656,684,713,
-742,771,800,828,854,878,899,918,935,950,964,976,989,1000,1011,1020,1028,1035,1039,1042,1044,
-1045,1046,1048,1051,1054,1057,1057,1055,1050,1042,1032,1021,1014,1013,1021,1040,1071,1115,1168,1226,1285,
-1340,1387,1423,1446,1473,1486,1487,1481,1471,1462,1456,1455,1459,1468,1478,1489,1499,1505,1508,1509,1507,
-1504,1500,1497,1494,1490,1485,1477,1465,1450,1431,1412,1393,1376,1362,1353,1348,1347,1348,1348,1346,1342,
-1333,1322,1310,1298,1291,1290,1297,1313,1338,1370,1407,1444,1478,1507,1528,1540,1543,1540,1532,1524,1518,
-1517,1524,1539,1561,1589,1619,1648,1672,1689,1696,1692,1679,1658,1633,1606,1582,1563,1552,1551,1561,1581,
-1611,1649,1695,1747,1804,1863,1925,1987,2049,2107,2162,2211,2253,2287,2314,2332,2343,2349,2350,2347,2342,
-2333,2322,2308,2289,2264,2234,2198,2158,2114,2070,2028,1990,1960,1939,1928,1927,1933,1946,1962,1979,1994,
-2005,2012,2014,2014,2012,2011,2013,2018,2027,2039,2052,2065,2076,2083,2086,2085,2080,2074,2069,2066,2067,
-2072,2079,2087,2093,2095,2091,2080,2062,2041,2018,1997,1980,1971,1971,1978,1992,2010,2029,2048,2064,2080,
-2095,2112,2135,2165,2204,2252,2306,2363,2418,2468,2507,2533,2545,2546,2538,2525,2513,2505,2505,2514,2531,
-2554,2579,2605,2626,2642,2652,2655,2655,2652,2650,2650,2653,2659,2667,2675,2683,2687,2688,2685,2678,2669,
-2659,2650,2643,2637,2635,2634,2634,2634,2633,2628,2621,2610,2597,2582,2567,2552,2539,2528,2518,2510,2503,
-2496,2489,2482,2474,2467,2462,2459,2460,2466,2476,2489,2503,2516,2526,2529,2525,2512,2493,2470,2447,2428,
-2419,2423,2443,2479,2529,2588,2651,2711,2761,2797,2814,2810,2788,2750,2701,2645,2588,2533,2483,2438,2396,
-2355,2312,2263,2208,2146,2075,2000,1923,1848,1780,1721,1673,1640,1621,1614,1618,1632,1651,1674,1698,1721,
-1742,1759,1772,1779,1781,1776,1766,1751,1731,1708,1684,1660,1638,1619,1605,1594,1587,1583,1580,1577,1574,
-1569,1565,1560,1556,1554,1555,1558,1564,1571,1577,1581,1581,1575,1563,1546,1524,1498,1472,1446,1422,1400,
-1382,1366,1352,1339,1326,1312,1298,1282,1264,1245,1226,1206,1185,1162,1139,1115,1089,1063,1035,1008,980,
-953,927,901,876,851,826,801,775,749,722,694,667,638,610,580,549,516,481,443,404,361,
-317,270,223,174,125,77,29,-16,-60,-102,-141,-178,-212,-245,-276,-307,-338,-370,-403,-438,-475,
--512,-550,-587,-624,-658,-691,-722,-751,-778,-806,-834,-863,-893,-925,-960,-995,-1032,-1069,-1105,-1140,-1173,
--1204,-1232,-1259,-1284,-1309,-1336,-1364,-1394,-1427,-1463,-1499,-1535,-1568,-1599,-1625,-1647,-1664,-1679,-1692,-1704,-1718,
--1733,-1751,-1770,-1791,-1812,-1833,-1855,-1877,-1903,-1933,-1970,-2015,-2068,-2128,-2193,-2257,-2318,-2371,-2413,-2441,-2457,
--2463,-2462,-2458,-2457,-2462,-2475,-2498,-2528,-2563,-2600,-2637,-2670,-2699,-2724,-2747,-2770,-2794,-2822,-2853,-2886,-2919,
--2950,-2976,-2995,-3008,-3014,-3016,-3017,-3020,-3028,-3043,-3065,-3092,-3122,-3152,-3179,-3201,-3218,-3229,-3236,-3242,-3248,
--3256,-3267,-3279,-3294,-3308,-3321,-3333,-3343,-3354,-3368,-3386,-3410,-3441,-3479,-3521,-3565,-3608,-3646,-3678,-3702,-3719,
--3730,-3738,-3745,-3753,-3763,-3777,-3792,-3808,-3824,-3839,-3853,-3868,-3885,-3908,-3938,-3977,-4026,-4082,-4145,-4209,-4270,
--4324,-4368,-4399,-4418,-4425,-4422,-4412,-4399,-4384,-4370,-4360,-4353,-4351,-4353,-4361,-4373,-4391,-4413,-4439,-4470,-4504,
--4539,-4575,-4611,-4647,-4681,-4715,-4749,-4785,-4823,-4864,-4907,-4953,-5000,-5045,-5087,-5122,-5149,-5167,-5175,-5174,-5166,
--5154,-5140,-5129,-5122,-5124,-5135,-5155,-5184,-5221,-5263,-5308,-5354,-5397,-5437,-5473,-5503,-5529,-5552,-5572,-5590,-5607,
--5625,-5642,-5661,-5679,-5697,-5714,-5729,-5740,-5747,-5750,-5748,-5742,-5731,-5719,-5705,-5692,-5681,-5674,-5670,-5670,-5670,
--5669,-5664,-5653,-5633,-5606,-5572,-5535,-5499,-5468,-5447,-5441,-5451,-5478,-5518,-5569,-5624,-5679,-5729,-5772,-5804,-5828,
--5845,-5858,-5868,-5879,-5890,-5901,-5910,-5914,-5912,-5900,-5879,-5849,-5815,-5779,-5745,-5718,-5700,-5694,-5699,-5714,-5735,
--5761,-5789,-5815,-5838,-5858,-5873,-5886,-5895,-5901,-5905,-5905,-5903,-5897,-5889,-5879,-5868,-5858,-5851,-5846,-5846,-5849,
--5856,-5865,-5875,-5884,-5893,-5900,-5906,-5911,-5917,-5925,-5935,-5948,-5962,-5977,-5991,-6005,-6016,-6025,-6033,-6039,-6046,
--6054,-6064,-6076,-6089,-6104,-6118,-6131,-6142,-6151,-6158,-6164,-6172,-6181,-6194,-6211,-6232,-6256,-6282,-6307,-6331,-6351,
--6367,-6379,-6387,-6392,-6396,-6400,-6404,-6410,-6416,-6423,-6429,-6433,-6435,-6434,-6429,-6422,-6413,-6402,-6391,-6381,-6373,
--6367,-6363,-6362,-6364,-6367,-6373,-6380,-6389,-6399,-6409,-6418,-6426,-6432,-6434,-6432,-6426,-6416,-6401,-6383,-6362,-6341,
--6320,-6299,-6282,-6266,-6254,-6245,-6239,-6234,-6232,-6230,-6230,-6230,-6231,-6231,-6231,-6230,-6229,-6226,-6223,-6218,-6212,
--6205,-6197,-6189,-6181,-6172,-6164,-6155,-6147,-6138,-6129,-6120,-6111,-6102,-6094,-6086,-6080,-6075,-6072,-6070,-6069,-6069,
--6069,-6069,-6067,-6064,-6058,-6051,-6042,-6031,-6018,-6004,-5989,-5973,-5956,-5939,-5922,-5904,-5886,-5868,-5851,-5834,-5818,
--5804,-5791,-5779,-5769,-5760,-5752,-5744,-5735,-5726,-5716,-5704,-5692,-5678,-5664,-5650,-5636,-5622,-5609,-5597,-5585,-5573,
--5561,-5549,-5535,-5521,-5506,-5491,-5474,-5458,-5441,-5424,-5407,-5390,-5374,-5357,-5341,-5325,-5309,-5292,-5276,-5259,-5241,
--5223,-5205,-5186,-5168,-5149,-5131,-5113,-5095,-5077,-5059,-5039,-5019,-4997,-4975,-4951,-4926,-4902,-4878,-4856,-4836,-4818,
--4801,-4784,-4768,-4749,-4729,-4707,-4682,-4655,-4628,-4601,-4576,-4554,-4534,-4518,-4504,-4492,-4480,-4467,-4452,-4435,-4416,
--4395,-4372,-4349,-4326,-4303,-4280,-4259,-4237,-4217,-4196,-4176,-4156,-4138,-4120,-4104,-4089,-4076,-4064,-4053,-4042,-4032,
--4022,-4012,-4003,-3995,-3988,-3982,-3977,-3972,-3965,-3957,-3945,-3929,-3909,-3885,-3859,-3831,-3804,-3778,-3754,-3735,-3719,
--3707,-3698,-3691,-3685,-3679,-3673,-3665,-3656,-3645,-3632,-3618,-3603,-3587,-3572,-3557,-3544,-3531,-3521,-3512,-3504,-3497,
--3491,-3484,-3476,-3468,-3458,-3447,-3435,-3422,-3410,-3398,-3386,-3375,-3363,-3352,-3340,-3329,-3318,-3307,-3298,-3291,-3286,
--3282,-3279,-3277,-3274,-3269,-3261,-3249,-3234,-3215,-3195,-3174,-3154,-3135,-3118,-3104,-3091,-3079,-3066,-3051,-3033,-3011,
--2987,-2959,-2928,-2896,-2863,-2830,-2798,-2766,-2736,-2706,-2679,-2654,-2633,-2615,-2601,-2592,-2587,-2586,-2587,-2590,-2594,
--2598,-2603,-2608,-2613,-2619,-2625,-2630,-2631,-2627,-2614,-2590,-2553,-2503,-2441,-2369,-2293,-2217,-2147,-2089,-2046,-2021,
--2013,-2020,-2038,-2062,-2088,-2110,-2125,-2131,-2126,-2112,-2089,-2059,-2024,-1986,-1945,-1902,-1857,-1810,-1761,-1710,-1657,
--1603,-1549,-1495,-1443,-1393,-1348,-1306,-1271,-1240,-1215,-1195,-1179,-1167,-1157,-1149,-1140,-1132,-1124,-1115,-1106,-1099,
--1092,-1088,-1085,-1083,-1081,-1077,-1070,-1059,-1043,-1023,-1000,-974,-948,-923,-900,-879,-859,-838,-816,-791,-761,
--727,-688,-647,-606,-567,-533,-503,-480,-462,-447,-433,-418,-400,-378,-352,-322,-289,-256,-222,-190,-157,
--125,-90,-52,-11,33,82,132,183,231,276,318,357,395,435,480,533,594,664,740,820,900,
-975,1042,1099,1144,1179,1206,1227,1244,1258,1270,1277,1277,1266,1241,1200,1142,1070,988,900,814,735,
-669,617,580,557,544,536,529,519,504,483,458,430,401,376,354,336,322,310,296,279,257,
-229,195,157,115,73,33,-3,-35,-62,-85,-103,-119,-131,-140,-147,-151,-151,-148,-141,-130,-117,
--103,-89,-75,-63,-53,-45,-37,-30,-23,-15,-6,2,11,20,28,35,40,45,49,53,59,
-65,73,81,90,98,106,112,116,119,122,124,128,132,137,144,152,159,166,171,175,177,
-179,179,180,181,183,187,191,196,200,204,206,207,207,206,204,202,201,200,200,199,198,
-196,192,187,180,172,164,156,149,143,140,137,137,137,138,138,139,138,137,135,133,131,
-130,128,128,128,128,129,131,133,136,140,144,149,154,159,164,169,173,176,179,181,183,
-184,185,186,186,186,186,185,183,181,179,177,176,176,177,180,184,190,197,205,215,225,
-235,245,255,265,274,283,291,298,304,310,315,319,323,327,333,339,348,359,372,389,408,
-431,456,483,512,543,575,609,642,677,711,746,780,814,847,877,906,932,955,976,994,1010,
-1024,1038,1051,1063,1074,1085,1093,1099,1102,1103,1100,1096,1091,1087,1085,1084,1086,1089,1092,1093,1091,
-1084,1073,1059,1044,1032,1026,1030,1047,1078,1122,1176,1238,1300,1359,1410,1448,1473,1445,1456,1457,1449,
-1438,1428,1421,1418,1422,1429,1440,1451,1461,1468,1472,1474,1474,1473,1472,1472,1473,1473,1471,1466,1456,
-1442,1422,1398,1373,1348,1325,1306,1292,1282,1276,1271,1267,1260,1251,1239,1225,1210,1197,1189,1186,1192,
-1204,1223,1247,1273,1298,1321,1338,1351,1358,1362,1364,1367,1373,1385,1402,1426,1455,1487,1519,1550,1576,
-1596,1608,1612,1610,1602,1591,1578,1566,1558,1555,1559,1572,1594,1626,1668,1720,1780,1848,1921,1996,2072,
-2146,2214,2276,2329,2372,2406,2431,2449,2460,2465,2466,2463,2456,2442,2423,2396,2360,2316,2264,2206,2145,
-2083,2023,1970,1925,1892,1872,1864,1869,1883,1904,1930,1957,1983,2006,2024,2037,2046,2050,2052,2052,2052,
-2051,2051,2051,2051,2050,2048,2045,2041,2038,2036,2037,2042,2052,2064,2080,2096,2111,2122,2127,2125,2117,
-2103,2084,2064,2044,2027,2015,2007,2004,2004,2008,2014,2021,2031,2043,2059,2081,2110,2145,2186,2231,2278,
-2322,2361,2391,2412,2423,2426,2424,2420,2417,2419,2428,2444,2466,2493,2522,2550,2575,2595,2610,2621,2628,
-2633,2638,2643,2650,2658,2665,2671,2673,2671,2663,2650,2632,2612,2590,2569,2550,2536,2525,2518,2514,2512,
-2512,2511,2510,2508,2504,2499,2493,2486,2478,2469,2459,2448,2436,2423,2410,2397,2387,2380,2378,2381,2390,
-2404,2421,2440,2456,2469,2474,2470,2456,2434,2407,2377,2349,2329,2321,2327,2350,2389,2441,2501,2564,2624,
-2674,2711,2731,2734,2720,2693,2656,2613,2569,2526,2485,2447,2411,2374,2332,2285,2229,2165,2092,2013,1931,
-1850,1775,1708,1653,1613,1588,1578,1581,1595,1618,1646,1676,1705,1732,1754,1769,1778,1781,1777,1767,1752,
-1733,1712,1690,1667,1645,1625,1607,1592,1578,1567,1558,1551,1546,1542,1542,1544,1548,1555,1564,1574,1584,
-1593,1598,1599,1594,1583,1567,1546,1521,1494,1466,1440,1415,1392,1373,1355,1340,1325,1311,1297,1282,1267,
-1251,1234,1215,1194,1172,1146,1119,1089,1057,1024,990,958,927,898,871,847,824,801,778,754,728,
-700,670,638,605,571,537,502,468,432,395,355,313,266,216,162,106,49,-7,-62,-114,-162,
--205,-243,-276,-305,-331,-355,-378,-401,-425,-451,-479,-509,-540,-571,-603,-635,-666,-696,-724,-752,-778,
--804,-829,-855,-881,-909,-938,-969,-1002,-1036,-1070,-1105,-1139,-1172,-1202,-1230,-1257,-1281,-1305,-1329,-1355,-1383,
--1414,-1448,-1484,-1520,-1556,-1590,-1620,-1646,-1667,-1683,-1697,-1710,-1722,-1737,-1755,-1776,-1800,-1829,-1860,-1894,-1931,
--1972,-2016,-2064,-2116,-2172,-2230,-2287,-2342,-2392,-2432,-2463,-2482,-2491,-2492,-2489,-2484,-2482,-2486,-2498,-2519,-2547,
--2581,-2618,-2655,-2692,-2726,-2758,-2789,-2818,-2849,-2880,-2913,-2945,-2976,-3004,-3026,-3042,-3052,-3058,-3060,-3062,-3067,
--3077,-3092,-3113,-3139,-3167,-3195,-3220,-3240,-3255,-3265,-3271,-3275,-3278,-3283,-3290,-3300,-3312,-3324,-3337,-3349,-3360,
--3372,-3384,-3400,-3421,-3447,-3479,-3516,-3556,-3598,-3639,-3677,-3710,-3738,-3760,-3777,-3790,-3801,-3810,-3818,-3826,-3834,
--3844,-3857,-3873,-3893,-3920,-3954,-3994,-4041,-4094,-4149,-4205,-4258,-4305,-4346,-4378,-4403,-4420,-4431,-4438,-4443,-4446,
--4448,-4451,-4453,-4455,-4457,-4460,-4465,-4473,-4486,-4504,-4527,-4556,-4590,-4625,-4661,-4696,-4729,-4760,-4789,-4817,-4848,
--4881,-4920,-4963,-5009,-5058,-5104,-5145,-5178,-5200,-5210,-5208,-5196,-5177,-5156,-5136,-5122,-5116,-5120,-5135,-5160,-5193,
--5232,-5275,-5320,-5364,-5407,-5448,-5486,-5521,-5553,-5581,-5606,-5628,-5646,-5661,-5674,-5687,-5699,-5712,-5727,-5743,-5759,
--5774,-5786,-5794,-5796,-5792,-5782,-5768,-5752,-5737,-5725,-5716,-5711,-5708,-5704,-5696,-5680,-5654,-5617,-5571,-5519,-5466,
--5419,-5385,-5367,-5371,-5396,-5439,-5498,-5566,-5636,-5703,-5764,-5814,-5856,-5889,-5918,-5944,-5969,-5993,-6015,-6033,-6044,
--6042,-6028,-5999,-5957,-5906,-5850,-5795,-5746,-5708,-5683,-5672,-5673,-5685,-5704,-5726,-5748,-5768,-5785,-5799,-5812,-5823,
--5833,-5844,-5855,-5866,-5875,-5883,-5888,-5891,-5891,-5891,-5890,-5890,-5891,-5893,-5896,-5899,-5903,-5905,-5908,-5910,-5912,
--5916,-5922,-5930,-5942,-5956,-5972,-5988,-6004,-6018,-6029,-6039,-6046,-6052,-6057,-6062,-6068,-6075,-6083,-6090,-6096,-6102,
--6106,-6110,-6114,-6121,-6130,-6144,-6163,-6188,-6216,-6247,-6279,-6310,-6337,-6361,-6379,-6392,-6401,-6407,-6412,-6417,-6423,
--6431,-6439,-6448,-6456,-6462,-6465,-6465,-6460,-6453,-6442,-6431,-6419,-6410,-6403,-6399,-6400,-6405,-6414,-6425,-6438,-6452,
--6465,-6476,-6484,-6489,-6490,-6486,-6478,-6466,-6452,-6434,-6416,-6398,-6380,-6363,-6347,-6334,-6322,-6313,-6304,-6298,-6292,
--6287,-6283,-6280,-6277,-6275,-6272,-6270,-6267,-6264,-6260,-6254,-6247,-6238,-6229,-6218,-6207,-6197,-6186,-6176,-6167,-6159,
--6151,-6145,-6139,-6133,-6128,-6123,-6118,-6113,-6108,-6104,-6099,-6095,-6091,-6087,-6083,-6079,-6074,-6068,-6061,-6053,-6044,
--6034,-6022,-6009,-5995,-5979,-5964,-5947,-5931,-5914,-5898,-5883,-5868,-5853,-5840,-5827,-5814,-5802,-5791,-5780,-5769,-5758,
--5748,-5739,-5729,-5720,-5711,-5701,-5692,-5681,-5670,-5658,-5644,-5629,-5613,-5597,-5579,-5562,-5545,-5529,-5513,-5498,-5484,
--5470,-5456,-5442,-5427,-5411,-5394,-5377,-5359,-5341,-5323,-5305,-5287,-5269,-5251,-5233,-5215,-5197,-5178,-5160,-5142,-5124,
--5106,-5088,-5070,-5051,-5031,-5011,-4989,-4967,-4944,-4922,-4900,-4879,-4859,-4840,-4822,-4803,-4785,-4764,-4742,-4718,-4693,
--4666,-4638,-4611,-4585,-4560,-4538,-4518,-4501,-4485,-4470,-4455,-4440,-4425,-4409,-4392,-4374,-4356,-4336,-4317,-4296,-4275,
--4254,-4233,-4213,-4193,-4176,-4160,-4147,-4136,-4126,-4117,-4108,-4098,-4087,-4075,-4061,-4046,-4031,-4016,-4002,-3990,-3978,
--3968,-3957,-3947,-3935,-3921,-3904,-3886,-3866,-3845,-3824,-3804,-3787,-3772,-3759,-3749,-3742,-3735,-3729,-3722,-3714,-3705,
--3693,-3680,-3665,-3650,-3634,-3619,-3605,-3593,-3582,-3572,-3564,-3556,-3548,-3539,-3529,-3517,-3504,-3491,-3478,-3465,-3453,
--3442,-3431,-3421,-3410,-3398,-3385,-3370,-3354,-3337,-3321,-3307,-3296,-3288,-3284,-3282,-3281,-3279,-3274,-3265,-3250,-3230,
--3204,-3176,-3146,-3117,-3091,-3069,-3052,-3039,-3028,-3017,-3005,-2989,-2968,-2940,-2907,-2870,-2830,-2789,-2749,-2712,-2679,
--2650,-2627,-2607,-2591,-2578,-2566,-2556,-2545,-2535,-2524,-2513,-2502,-2491,-2481,-2472,-2465,-2459,-2456,-2453,-2450,-2446,
--2438,-2424,-2403,-2373,-2334,-2287,-2234,-2177,-2120,-2067,-2021,-1984,-1958,-1944,-1940,-1944,-1953,-1964,-1974,-1979,-1978,
--1969,-1953,-1929,-1898,-1862,-1823,-1780,-1737,-1694,-1651,-1609,-1568,-1528,-1490,-1453,-1417,-1384,-1352,-1323,-1298,-1277,
--1260,-1247,-1239,-1234,-1232,-1230,-1229,-1227,-1222,-1217,-1209,-1201,-1192,-1184,-1176,-1169,-1162,-1152,-1140,-1125,-1104,
--1080,-1052,-1022,-992,-965,-940,-920,-903,-889,-874,-858,-837,-810,-778,-741,-701,-661,-623,-590,-562,-538,
--519,-502,-485,-465,-440,-412,-380,-347,-314,-284,-257,-234,-213,-193,-170,-141,-104,-59,-6,51,112,
-171,226,275,317,354,389,426,469,521,583,655,735,818,900,975,1041,1094,1134,1163,1183,1195,
-1203,1208,1210,1206,1194,1172,1137,1088,1026,954,875,796,721,656,604,565,539,523,513,506,497,
-483,464,440,412,382,353,326,303,281,262,243,221,197,168,136,101,64,27,-6,-37,-64,
--86,-105,-120,-133,-145,-155,-163,-168,-171,-171,-168,-161,-152,-141,-131,-120,-111,-103,-97,-91,-84,
--78,-70,-60,-50,-40,-31,-22,-16,-11,-8,-6,-4,-2,1,6,13,21,30,38,45,51,
-55,58,60,62,65,69,74,80,87,94,101,106,110,113,115,117,118,120,122,126,129,
-134,138,142,145,148,150,152,153,154,155,155,155,155,153,151,148,144,139,135,130,126,
-123,122,120,120,120,120,120,119,118,117,115,113,111,109,108,106,105,105,105,106,108,
-111,115,119,125,131,137,143,148,153,157,161,164,167,169,171,173,174,175,174,173,171,
-168,164,161,159,158,159,162,167,173,181,188,196,203,209,215,219,223,226,229,233,238,
-243,249,256,264,273,284,295,309,324,343,364,388,416,447,481,517,556,595,636,678,719,
-760,801,841,879,915,948,977,1003,1024,1041,1055,1066,1075,1083,1091,1098,1106,1113,1119,1123,1123,
-1120,1114,1104,1092,1081,1070,1063,1060,1060,1064,1069,1074,1076,1073,1067,1056,1043,1032,1026,1029,1044,
-1072,1112,1163,1221,1281,1337,1385,1422,1445,1396,1401,1395,1382,1366,1350,1337,1329,1328,1333,1342,1353,
-1365,1376,1386,1394,1400,1407,1413,1420,1428,1435,1441,1443,1440,1431,1416,1396,1372,1346,1320,1296,1275,
-1258,1244,1233,1223,1214,1204,1192,1179,1166,1153,1142,1134,1131,1132,1137,1146,1157,1169,1182,1194,1206,
-1219,1232,1248,1266,1288,1313,1342,1372,1404,1436,1466,1493,1516,1536,1551,1562,1570,1574,1576,1576,1574,
-1573,1573,1576,1584,1599,1623,1657,1703,1759,1824,1897,1973,2049,2121,2187,2244,2291,2328,2356,2376,2389,
-2399,2405,2408,2408,2403,2391,2372,2343,2305,2258,2204,2145,2084,2026,1975,1932,1900,1880,1873,1878,1893,
-1915,1943,1974,2005,2035,2061,2083,2100,2112,2118,2119,2115,2108,2099,2088,2077,2066,2057,2050,2046,2045,
-2047,2053,2063,2075,2089,2105,2120,2134,2146,2155,2159,2158,2153,2144,2133,2119,2105,2092,2080,2071,2063,
-2057,2052,2050,2050,2054,2061,2072,2089,2112,2141,2173,2208,2242,2275,2302,2323,2337,2345,2348,2348,2348,
-2350,2358,2371,2390,2413,2440,2468,2495,2518,2537,2552,2563,2571,2577,2584,2591,2599,2608,2617,2625,2629,
-2630,2625,2615,2601,2583,2563,2542,2522,2503,2488,2474,2464,2455,2449,2445,2441,2439,2437,2435,2433,2431,
-2427,2421,2412,2401,2387,2370,2354,2338,2325,2317,2314,2318,2328,2342,2359,2375,2388,2395,2393,2382,2362,
-2335,2304,2273,2247,2230,2225,2235,2260,2300,2350,2407,2467,2523,2571,2607,2629,2638,2632,2615,2590,2558,
-2524,2489,2454,2418,2382,2343,2299,2248,2190,2124,2051,1973,1892,1813,1739,1673,1618,1577,1551,1538,1539,
-1550,1570,1594,1620,1645,1668,1685,1698,1705,1706,1704,1698,1690,1680,1670,1658,1646,1633,1620,1606,1592,
-1578,1565,1552,1542,1535,1531,1531,1535,1542,1552,1564,1577,1588,1596,1600,1599,1593,1581,1565,1544,1521,
-1495,1470,1444,1420,1398,1377,1357,1339,1322,1306,1290,1275,1260,1244,1228,1210,1191,1168,1143,1114,1083,
-1049,1013,977,942,908,876,847,819,794,769,745,719,693,666,637,606,576,545,514,483,451,
-418,382,344,301,254,204,149,92,35,-22,-77,-129,-176,-218,-254,-286,-314,-339,-362,-384,-406,
--428,-451,-475,-500,-527,-554,-583,-614,-645,-677,-710,-743,-776,-808,-838,-868,-897,-925,-952,-980,-1010,
--1040,-1072,-1106,-1141,-1175,-1209,-1241,-1272,-1300,-1326,-1352,-1378,-1406,-1436,-1469,-1505,-1542,-1581,-1618,-1653,-1684,
--1711,-1733,-1752,-1768,-1784,-1801,-1821,-1845,-1873,-1907,-1944,-1986,-2031,-2078,-2128,-2179,-2230,-2282,-2332,-2380,-2424,
--2462,-2494,-2517,-2533,-2542,-2546,-2547,-2548,-2550,-2557,-2570,-2589,-2614,-2643,-2675,-2708,-2742,-2774,-2805,-2836,-2865,
--2895,-2924,-2953,-2982,-3008,-3030,-3048,-3062,-3071,-3076,-3080,-3085,-3091,-3102,-3118,-3138,-3163,-3189,-3215,-3239,-3259,
--3275,-3287,-3296,-3303,-3310,-3317,-3326,-3338,-3351,-3365,-3379,-3392,-3404,-3415,-3427,-3439,-3454,-3472,-3496,-3524,-3556,
--3592,-3630,-3669,-3705,-3739,-3768,-3793,-3811,-3825,-3833,-3838,-3841,-3844,-3849,-3857,-3872,-3893,-3923,-3960,-4004,-4054,
--4106,-4158,-4208,-4253,-4292,-4325,-4352,-4375,-4395,-4415,-4435,-4456,-4477,-4499,-4520,-4538,-4554,-4566,-4576,-4585,-4594,
--4606,-4622,-4641,-4665,-4691,-4718,-4745,-4769,-4791,-4810,-4827,-4846,-4868,-4896,-4930,-4971,-5016,-5064,-5110,-5150,-5181,
--5200,-5206,-5201,-5187,-5169,-5150,-5135,-5127,-5129,-5142,-5165,-5195,-5232,-5271,-5312,-5352,-5392,-5429,-5465,-5500,-5533,
--5564,-5591,-5615,-5634,-5649,-5659,-5665,-5670,-5676,-5685,-5697,-5713,-5732,-5752,-5770,-5782,-5788,-5786,-5775,-5759,-5739,
--5720,-5704,-5693,-5689,-5689,-5691,-5690,-5682,-5663,-5631,-5587,-5533,-5476,-5423,-5380,-5354,-5349,-5367,-5407,-5465,-5534,
--5607,-5679,-5743,-5799,-5844,-5880,-5910,-5936,-5961,-5986,-6010,-6030,-6044,-6048,-6040,-6018,-5984,-5940,-5890,-5840,-5795,
--5758,-5732,-5718,-5715,-5720,-5729,-5739,-5748,-5754,-5756,-5756,-5755,-5755,-5758,-5765,-5777,-5793,-5811,-5831,-5850,-5867,
--5882,-5893,-5901,-5907,-5912,-5914,-5916,-5916,-5916,-5914,-5912,-5910,-5909,-5910,-5914,-5922,-5934,-5949,-5968,-5989,-6011,
--6031,-6048,-6062,-6072,-6079,-6083,-6084,-6084,-6083,-6082,-6080,-6079,-6077,-6076,-6075,-6076,-6079,-6087,-6099,-6117,-6141,
--6171,-6204,-6240,-6276,-6310,-6340,-6366,-6387,-6403,-6414,-6423,-6431,-6439,-6447,-6456,-6465,-6474,-6481,-6485,-6486,-6482,
--6474,-6464,-6452,-6441,-6431,-6425,-6424,-6429,-6438,-6452,-6469,-6486,-6501,-6514,-6521,-6523,-6519,-6510,-6496,-6479,-6461,
--6442,-6425,-6410,-6398,-6388,-6380,-6375,-6369,-6364,-6358,-6352,-6344,-6336,-6328,-6320,-6313,-6308,-6303,-6300,-6297,-6294,
--6291,-6286,-6280,-6272,-6262,-6251,-6239,-6227,-6215,-6204,-6195,-6187,-6180,-6175,-6171,-6167,-6163,-6158,-6153,-6147,-6141,
--6134,-6127,-6120,-6113,-6106,-6101,-6096,-6091,-6086,-6082,-6077,-6071,-6064,-6056,-6046,-6035,-6022,-6008,-5994,-5978,-5962,
--5947,-5931,-5916,-5902,-5888,-5874,-5861,-5848,-5836,-5824,-5812,-5800,-5789,-5778,-5769,-5760,-5752,-5744,-5737,-5729,-5720,
--5710,-5698,-5685,-5670,-5653,-5636,-5618,-5600,-5583,-5567,-5552,-5537,-5523,-5509,-5495,-5479,-5463,-5445,-5427,-5408,-5388,
--5369,-5350,-5331,-5313,-5296,-5278,-5260,-5242,-5223,-5204,-5184,-5164,-5145,-5127,-5109,-5092,-5076,-5059,-5042,-5024,-5005,
--4984,-4963,-4941,-4918,-4896,-4874,-4853,-4833,-4813,-4793,-4773,-4752,-4729,-4706,-4682,-4656,-4631,-4606,-4581,-4558,-4536,
--4515,-4495,-4477,-4459,-4442,-4426,-4409,-4392,-4375,-4358,-4340,-4321,-4302,-4283,-4265,-4246,-4229,-4214,-4200,-4187,-4177,
--4167,-4158,-4149,-4138,-4127,-4114,-4099,-4083,-4067,-4051,-4035,-4021,-4008,-3997,-3986,-3977,-3967,-3956,-3944,-3931,-3916,
--3900,-3884,-3868,-3852,-3838,-3826,-3815,-3806,-3798,-3790,-3782,-3773,-3763,-3752,-3738,-3724,-3709,-3694,-3680,-3667,-3654,
--3643,-3632,-3620,-3608,-3595,-3580,-3564,-3547,-3529,-3512,-3497,-3484,-3472,-3463,-3455,-3446,-3436,-3424,-3408,-3389,-3367,
--3344,-3321,-3301,-3284,-3271,-3263,-3258,-3255,-3250,-3242,-3227,-3204,-3173,-3136,-3093,-3048,-3005,-2967,-2935,-2912,-2896,
--2887,-2881,-2876,-2867,-2853,-2831,-2802,-2766,-2725,-2682,-2639,-2600,-2566,-2538,-2518,-2503,-2493,-2485,-2478,-2471,-2461,
--2448,-2432,-2413,-2393,-2372,-2351,-2332,-2315,-2301,-2289,-2280,-2272,-2266,-2258,-2249,-2236,-2219,-2198,-2171,-2140,-2105,
--2067,-2028,-1990,-1953,-1920,-1892,-1868,-1849,-1835,-1824,-1815,-1806,-1796,-1784,-1768,-1747,-1722,-1692,-1659,-1624,-1589,
--1554,-1521,-1491,-1465,-1443,-1424,-1408,-1394,-1382,-1371,-1361,-1353,-1346,-1340,-1337,-1335,-1334,-1334,-1333,-1330,-1325,
--1317,-1306,-1294,-1279,-1264,-1249,-1235,-1221,-1207,-1193,-1176,-1157,-1135,-1110,-1083,-1056,-1030,-1007,-987,-971,-957,
--945,-932,-915,-894,-867,-835,-799,-761,-723,-689,-659,-634,-613,-594,-575,-553,-526,-493,-455,-413,-371,
--331,-295,-265,-242,-222,-204,-183,-156,-120,-73,-17,45,111,176,234,283,322,352,376,400,427,
-463,511,571,642,721,802,881,952,1012,1059,1093,1116,1130,1138,1142,1143,1140,1132,1117,1091,1054,
-1005,945,877,806,735,669,612,564,527,500,479,462,446,428,408,384,358,331,305,281,258,
-239,220,202,182,159,133,104,73,41,9,-21,-48,-71,-90,-106,-120,-132,-142,-152,-160,-167,
--171,-173,-172,-168,-162,-155,-146,-139,-132,-126,-122,-118,-114,-109,-103,-95,-86,-76,-67,-58,-50,
--45,-42,-40,-40,-39,-38,-35,-31,-25,-17,-9,-1,5,11,17,21,24,27,31,35,40,
-46,51,57,62,66,70,72,73,74,75,76,78,81,85,89,94,98,103,107,110,112,
-113,114,114,114,114,113,112,112,112,112,112,112,113,113,112,111,109,107,103,100,96,
-92,89,86,84,82,80,79,79,79,79,80,82,84,88,93,99,106,113,120,126,131,
-135,138,140,142,144,145,147,149,151,152,153,154,153,151,149,147,145,144,145,147,150,
-154,159,163,166,168,169,168,166,164,163,164,166,171,179,189,203,218,236,255,277,301,
-326,355,386,420,456,495,536,578,622,666,710,754,797,839,881,920,958,992,1022,1048,1068,
-1083,1092,1097,1098,1098,1097,1096,1097,1100,1104,1107,1110,1110,1106,1098,1087,1072,1057,1043,1031,1024,
-1022,1025,1031,1039,1046,1050,1052,1050,1045,1041,1040,1045,1060,1084,1119,1163,1212,1263,1310,1350,1379,
-1396,1344,1340,1327,1308,1285,1263,1245,1232,1227,1230,1239,1254,1271,1290,1308,1326,1341,1355,1368,1380,
-1390,1399,1406,1409,1409,1404,1395,1381,1363,1343,1321,1301,1281,1264,1249,1236,1225,1214,1204,1193,1182,
-1170,1159,1147,1137,1128,1121,1116,1114,1115,1118,1125,1135,1149,1168,1190,1216,1246,1276,1308,1338,1366,
-1391,1413,1433,1450,1466,1481,1498,1515,1532,1549,1565,1577,1586,1592,1594,1595,1596,1602,1616,1638,1673,
-1718,1773,1836,1902,1968,2028,2081,2124,2156,2179,2194,2204,2211,2217,2225,2233,2240,2245,2245,2239,2225,
-2202,2171,2135,2096,2058,2023,1995,1975,1964,1962,1968,1980,1997,2018,2039,2062,2083,2104,2123,2140,2154,
-2164,2169,2168,2163,2153,2139,2122,2106,2091,2081,2076,2078,2087,2102,2122,2145,2169,2191,2211,2226,2235,
-2240,2239,2234,2226,2217,2208,2199,2191,2185,2181,2177,2174,2170,2166,2162,2158,2155,2154,2155,2161,2170,
-2184,2201,2220,2239,2257,2271,2280,2284,2284,2279,2272,2266,2263,2265,2273,2288,2310,2336,2365,2394,2421,
-2445,2463,2477,2486,2493,2498,2504,2511,2521,2533,2546,2559,2570,2579,2583,2581,2574,2561,2544,2522,2499,
-2473,2448,2424,2403,2384,2369,2357,2350,2345,2344,2345,2347,2349,2349,2346,2340,2330,2317,2302,2285,2270,
-2257,2248,2243,2244,2250,2258,2267,2274,2277,2274,2263,2245,2221,2193,2165,2140,2121,2113,2116,2133,2162,
-2202,2251,2304,2358,2408,2453,2488,2513,2527,2531,2524,2509,2487,2459,2426,2389,2347,2300,2248,2190,2127,
-2059,1986,1911,1836,1763,1695,1634,1583,1543,1516,1500,1495,1500,1511,1527,1544,1561,1575,1585,1592,1595,
-1595,1594,1592,1591,1591,1593,1595,1598,1600,1600,1598,1594,1586,1577,1566,1554,1544,1536,1531,1530,1532,
-1538,1546,1555,1564,1571,1576,1578,1576,1569,1559,1545,1528,1509,1488,1466,1443,1420,1397,1375,1352,1331,
-1310,1291,1272,1254,1237,1220,1203,1185,1166,1144,1120,1094,1065,1033,1001,967,932,899,866,834,803,
-774,745,717,690,663,637,611,586,561,537,514,489,463,435,404,369,330,287,241,191,140,
-89,37,-12,-59,-105,-148,-188,-226,-263,-298,-331,-364,-394,-424,-451,-478,-504,-530,-557,-586,-616,
--650,-686,-725,-765,-806,-846,-884,-920,-952,-982,-1010,-1036,-1063,-1092,-1122,-1155,-1191,-1228,-1265,-1302,-1338,
--1371,-1402,-1432,-1460,-1489,-1519,-1551,-1586,-1623,-1662,-1701,-1739,-1775,-1806,-1834,-1859,-1881,-1902,-1923,-1946,-1973,
--2004,-2040,-2079,-2122,-2167,-2214,-2260,-2306,-2350,-2393,-2433,-2471,-2506,-2538,-2565,-2589,-2609,-2625,-2638,-2650,-2661,
--2672,-2686,-2702,-2721,-2743,-2768,-2795,-2822,-2850,-2878,-2905,-2931,-2957,-2981,-3004,-3026,-3046,-3063,-3078,-3089,-3096,
--3101,-3105,-3109,-3114,-3121,-3133,-3150,-3170,-3194,-3220,-3245,-3270,-3292,-3311,-3326,-3338,-3349,-3359,-3369,-3381,-3394,
--3408,-3424,-3439,-3454,-3468,-3481,-3492,-3502,-3513,-3525,-3540,-3558,-3580,-3606,-3636,-3668,-3701,-3734,-3766,-3794,-3817,
--3835,-3847,-3854,-3858,-3861,-3864,-3871,-3883,-3902,-3928,-3962,-4001,-4045,-4090,-4134,-4174,-4210,-4242,-4269,-4293,-4317,
--4342,-4370,-4402,-4438,-4477,-4517,-4557,-4594,-4627,-4656,-4682,-4704,-4724,-4744,-4765,-4787,-4809,-4831,-4851,-4868,-4881,
--4891,-4897,-4903,-4911,-4923,-4941,-4967,-5000,-5037,-5077,-5115,-5147,-5171,-5185,-5188,-5183,-5173,-5161,-5151,-5148,-5154,
--5169,-5194,-5226,-5262,-5301,-5340,-5376,-5410,-5441,-5470,-5499,-5526,-5554,-5580,-5604,-5624,-5640,-5650,-5656,-5658,-5659,
--5662,-5668,-5680,-5696,-5716,-5737,-5757,-5770,-5776,-5772,-5759,-5739,-5716,-5693,-5676,-5666,-5665,-5672,-5683,-5693,-5696,
--5689,-5668,-5632,-5583,-5528,-5473,-5425,-5392,-5379,-5389,-5421,-5473,-5537,-5607,-5676,-5740,-5793,-5834,-5864,-5886,-5902,
--5916,-5928,-5941,-5952,-5960,-5963,-5959,-5946,-5926,-5899,-5869,-5839,-5813,-5793,-5781,-5776,-5778,-5782,-5786,-5787,-5783,
--5772,-5755,-5735,-5715,-5697,-5684,-5679,-5682,-5694,-5713,-5737,-5764,-5792,-5819,-5844,-5865,-5884,-5899,-5911,-5921,-5928,
--5932,-5934,-5934,-5932,-5930,-5929,-5930,-5934,-5943,-5956,-5974,-5995,-6018,-6041,-6063,-6082,-6097,-6108,-6115,-6118,-6118,
--6116,-6112,-6108,-6103,-6097,-6091,-6086,-6082,-6080,-6081,-6087,-6098,-6116,-6140,-6169,-6203,-6240,-6278,-6315,-6349,-6378,
--6404,-6424,-6441,-6454,-6465,-6475,-6483,-6491,-6497,-6501,-6502,-6499,-6494,-6485,-6475,-6464,-6454,-6448,-6447,-6451,-6461,
--6476,-6494,-6514,-6532,-6546,-6553,-6553,-6545,-6530,-6509,-6484,-6458,-6434,-6414,-6399,-6391,-6388,-6389,-6394,-6400,-6404,
--6406,-6405,-6400,-6391,-6380,-6367,-6354,-6343,-6334,-6327,-6322,-6319,-6317,-6314,-6310,-6304,-6296,-6287,-6275,-6263,-6252,
--6241,-6232,-6224,-6218,-6214,-6210,-6207,-6203,-6198,-6192,-6184,-6176,-6166,-6157,-6148,-6139,-6132,-6126,-6121,-6118,-6114,
--6111,-6108,-6104,-6099,-6092,-6083,-6073,-6062,-6049,-6035,-6019,-6004,-5988,-5972,-5956,-5941,-5927,-5914,-5901,-5890,-5879,
--5869,-5859,-5849,-5840,-5830,-5821,-5812,-5802,-5793,-5784,-5774,-5764,-5754,-5743,-5731,-5719,-5705,-5691,-5676,-5661,-5646,
--5631,-5615,-5600,-5584,-5568,-5550,-5532,-5513,-5493,-5472,-5451,-5430,-5409,-5390,-5371,-5353,-5336,-5319,-5302,-5284,-5266,
--5246,-5225,-5205,-5184,-5165,-5146,-5130,-5115,-5101,-5087,-5073,-5058,-5042,-5023,-5003,-4980,-4956,-4932,-4908,-4885,-4863,
--4843,-4824,-4806,-4789,-4772,-4754,-4736,-4716,-4695,-4673,-4650,-4627,-4602,-4578,-4554,-4530,-4506,-4483,-4461,-4440,-4419,
--4400,-4382,-4365,-4349,-4333,-4319,-4305,-4292,-4279,-4266,-4254,-4241,-4228,-4215,-4202,-4188,-4173,-4158,-4143,-4127,-4112,
--4097,-4082,-4069,-4056,-4045,-4036,-4027,-4018,-4010,-4001,-3991,-3980,-3967,-3954,-3940,-3925,-3910,-3896,-3883,-3871,-3860,
--3850,-3840,-3830,-3820,-3808,-3795,-3781,-3765,-3749,-3733,-3716,-3700,-3684,-3668,-3652,-3635,-3617,-3598,-3578,-3558,-3537,
--3517,-3499,-3484,-3472,-3462,-3455,-3449,-3442,-3432,-3419,-3401,-3378,-3352,-3323,-3295,-3268,-3245,-3227,-3215,-3206,-3199,
--3190,-3177,-3156,-3126,-3085,-3036,-2981,-2922,-2864,-2812,-2769,-2736,-2715,-2704,-2700,-2700,-2700,-2695,-2685,-2666,-2640,
--2606,-2569,-2530,-2493,-2460,-2433,-2413,-2399,-2390,-2384,-2380,-2375,-2368,-2359,-2346,-2330,-2312,-2292,-2272,-2253,-2235,
--2218,-2203,-2191,-2180,-2171,-2164,-2157,-2151,-2144,-2136,-2125,-2111,-2093,-2070,-2041,-2007,-1970,-1929,-1888,-1847,-1809,
--1775,-1746,-1723,-1704,-1688,-1675,-1661,-1645,-1627,-1605,-1579,-1551,-1522,-1495,-1470,-1449,-1433,-1423,-1418,-1417,-1418,
--1421,-1424,-1426,-1426,-1426,-1424,-1422,-1419,-1416,-1412,-1406,-1399,-1389,-1376,-1360,-1342,-1322,-1301,-1280,-1259,-1239,
--1220,-1201,-1182,-1163,-1143,-1123,-1104,-1086,-1070,-1057,-1046,-1038,-1030,-1021,-1009,-992,-969,-940,-906,-869,-832,
--795,-763,-735,-712,-691,-672,-650,-624,-590,-549,-501,-448,-394,-341,-293,-252,-217,-189,-162,-135,-103,
--64,-16,39,100,163,223,275,317,348,369,382,393,408,430,464,512,572,643,718,794,864,
-926,976,1014,1040,1058,1069,1077,1081,1083,1082,1074,1059,1034,998,951,894,830,764,697,635,578,
-528,486,450,418,389,360,332,304,277,251,228,209,193,180,169,159,147,132,114,92,66,
-38,10,-17,-43,-65,-84,-100,-113,-124,-134,-142,-150,-156,-161,-163,-164,-161,-157,-151,-144,-138,
--132,-128,-126,-124,-123,-122,-119,-115,-110,-103,-95,-86,-79,-72,-67,-64,-62,-61,-60,-58,-56,
--52,-46,-40,-33,-25,-18,-12,-7,-2,1,5,8,12,16,20,24,28,32,35,37,38,
-39,40,41,43,45,48,52,56,61,66,70,74,76,77,77,77,76,75,74,74,75,
-76,79,81,84,86,88,88,86,83,78,73,67,62,57,53,50,49,48,49,49,51,
-52,54,56,59,63,68,74,81,88,95,100,105,108,109,108,107,105,104,103,103,105,
-107,110,113,117,119,120,121,121,120,120,120,121,122,123,123,124,123,121,119,116,113,
-111,112,115,122,132,147,164,185,209,236,264,295,327,362,399,439,480,524,568,613,658,
-702,744,786,826,866,904,942,978,1013,1044,1072,1093,1109,1117,1119,1114,1106,1094,1083,1074,1068,
-1068,1071,1079,1088,1096,1103,1106,1104,1097,1087,1075,1064,1054,1048,1047,1050,1057,1065,1073,1080,1086,
-1089,1091,1095,1102,1114,1133,1159,1190,1225,1261,1294,1320,1338,1344,1280,1272,1257,1237,1215,1194,1177,
-1167,1164,1170,1184,1205,1231,1260,1289,1317,1342,1363,1380,1394,1403,1409,1412,1412,1409,1403,1396,1386,
-1375,1363,1350,1338,1325,1313,1301,1290,1280,1269,1258,1246,1234,1221,1208,1194,1180,1167,1154,1144,1136,
-1132,1133,1139,1152,1171,1196,1226,1258,1291,1322,1350,1372,1388,1399,1405,1410,1414,1421,1433,1451,1475,
-1502,1532,1561,1587,1607,1620,1626,1627,1627,1628,1635,1651,1677,1714,1760,1812,1866,1918,1963,1998,2022,
-2036,2041,2040,2038,2037,2039,2048,2061,2078,2095,2112,2124,2130,2129,2123,2113,2102,2091,2084,2082,2084,
-2092,2103,2116,2128,2139,2148,2154,2159,2162,2166,2171,2177,2184,2191,2196,2197,2194,2186,2174,2160,2145,
-2133,2127,2128,2140,2161,2191,2228,2268,2307,2343,2371,2390,2399,2399,2391,2377,2360,2343,2328,2316,2308,
-2304,2303,2304,2305,2305,2305,2302,2299,2295,2291,2290,2290,2293,2298,2303,2308,2310,2307,2300,2286,2267,
-2245,2221,2198,2180,2168,2166,2173,2190,2216,2247,2281,2315,2346,2372,2391,2404,2413,2418,2421,2426,2435,
-2447,2463,2482,2503,2524,2541,2553,2557,2553,2539,2517,2487,2452,2413,2373,2335,2301,2272,2250,2235,2226,
-2224,2227,2232,2239,2245,2248,2248,2244,2236,2224,2210,2196,2182,2170,2162,2157,2155,2155,2156,2155,2151,
-2142,2128,2109,2086,2060,2035,2013,1996,1988,1989,2002,2024,2056,2096,2141,2188,2236,2282,2324,2361,2390,
-2412,2426,2431,2427,2414,2391,2357,2314,2262,2200,2131,2055,1975,1893,1812,1735,1663,1600,1547,1505,1475,
-1457,1450,1452,1460,1472,1486,1498,1508,1514,1515,1513,1507,1499,1492,1487,1485,1487,1493,1504,1516,1530,
-1543,1555,1562,1566,1566,1562,1556,1549,1542,1536,1532,1531,1532,1535,1540,1544,1548,1551,1551,1549,1545,
-1538,1529,1518,1505,1489,1473,1454,1434,1412,1390,1366,1342,1317,1294,1270,1248,1227,1206,1186,1166,1145,
-1124,1101,1078,1052,1026,998,968,938,907,876,844,811,779,747,715,685,656,628,604,581,560,
-542,524,506,487,466,442,415,384,350,313,273,232,190,148,106,64,22,-20,-64,-110,-157,
--206,-256,-305,-354,-400,-444,-483,-519,-552,-582,-611,-641,-672,-707,-744,-783,-825,-868,-910,-951,-988,
--1022,-1052,-1080,-1107,-1133,-1161,-1191,-1224,-1260,-1298,-1338,-1378,-1417,-1453,-1488,-1521,-1552,-1582,-1613,-1646,-1681,
--1718,-1756,-1796,-1835,-1873,-1908,-1941,-1971,-1999,-2027,-2054,-2083,-2114,-2148,-2185,-2224,-2264,-2305,-2344,-2382,-2417,
--2450,-2481,-2510,-2538,-2566,-2592,-2619,-2645,-2670,-2695,-2718,-2740,-2762,-2783,-2803,-2824,-2846,-2870,-2894,-2920,-2947,
--2974,-3001,-3028,-3053,-3076,-3097,-3115,-3129,-3140,-3148,-3153,-3155,-3155,-3154,-3154,-3155,-3160,-3168,-3182,-3199,-3221,
--3246,-3272,-3298,-3322,-3345,-3363,-3379,-3392,-3402,-3411,-3421,-3432,-3445,-3459,-3476,-3493,-3511,-3528,-3544,-3558,-3570,
--3580,-3588,-3597,-3607,-3619,-3635,-3654,-3677,-3704,-3733,-3763,-3793,-3819,-3842,-3860,-3874,-3884,-3891,-3897,-3905,-3917,
--3933,-3955,-3982,-4014,-4048,-4083,-4117,-4148,-4176,-4201,-4224,-4246,-4271,-4300,-4334,-4374,-4421,-4472,-4527,-4582,-4636,
--4688,-4736,-4780,-4820,-4856,-4890,-4922,-4951,-4977,-4999,-5016,-5027,-5032,-5032,-5029,-5025,-5023,-5024,-5032,-5046,-5066,
--5090,-5115,-5139,-5158,-5171,-5176,-5174,-5168,-5161,-5156,-5156,-5165,-5182,-5208,-5242,-5280,-5320,-5359,-5395,-5427,-5455,
--5480,-5504,-5527,-5551,-5575,-5599,-5621,-5641,-5655,-5665,-5670,-5672,-5673,-5675,-5681,-5692,-5707,-5727,-5747,-5765,-5778,
--5781,-5775,-5760,-5738,-5713,-5689,-5672,-5663,-5665,-5675,-5690,-5706,-5716,-5715,-5699,-5667,-5622,-5567,-5509,-5457,-5417,
--5396,-5398,-5422,-5466,-5526,-5594,-5663,-5728,-5782,-5825,-5855,-5873,-5883,-5886,-5886,-5884,-5881,-5876,-5870,-5860,-5847,
--5832,-5814,-5797,-5782,-5772,-5767,-5768,-5773,-5780,-5785,-5786,-5780,-5766,-5742,-5712,-5676,-5640,-5608,-5582,-5567,-5563,
--5571,-5590,-5617,-5651,-5688,-5726,-5764,-5800,-5833,-5863,-5890,-5914,-5933,-5949,-5960,-5968,-5971,-5972,-5970,-5968,-5968,
--5970,-5975,-5985,-5999,-6017,-6037,-6057,-6077,-6095,-6110,-6122,-6131,-6137,-6140,-6142,-6141,-6139,-6136,-6131,-6125,-6119,
--6113,-6108,-6107,-6109,-6117,-6131,-6153,-6180,-6213,-6249,-6288,-6326,-6362,-6395,-6424,-6448,-6468,-6484,-6496,-6506,-6513,
--6517,-6520,-6519,-6517,-6512,-6506,-6499,-6492,-6488,-6488,-6492,-6502,-6516,-6534,-6553,-6572,-6587,-6595,-6596,-6588,-6571,
--6546,-6516,-6485,-6455,-6429,-6410,-6400,-6398,-6403,-6414,-6428,-6442,-6453,-6459,-6459,-6453,-6442,-6426,-6409,-6391,-6375,
--6362,-6353,-6347,-6343,-6341,-6339,-6336,-6331,-6324,-6315,-6304,-6293,-6283,-6274,-6266,-6261,-6257,-6253,-6251,-6247,-6243,
--6236,-6228,-6219,-6208,-6197,-6187,-6178,-6170,-6164,-6159,-6156,-6153,-6150,-6147,-6142,-6136,-6128,-6119,-6108,-6096,-6083,
--6069,-6055,-6040,-6025,-6009,-5994,-5979,-5964,-5950,-5938,-5926,-5916,-5908,-5900,-5894,-5887,-5881,-5874,-5866,-5857,-5847,
--5836,-5825,-5812,-5800,-5787,-5775,-5763,-5751,-5739,-5728,-5716,-5703,-5690,-5676,-5660,-5643,-5624,-5604,-5583,-5561,-5538,
--5514,-5491,-5469,-5448,-5428,-5409,-5392,-5375,-5358,-5342,-5324,-5306,-5287,-5267,-5246,-5226,-5206,-5188,-5172,-5157,-5144,
--5132,-5121,-5109,-5096,-5081,-5064,-5044,-5022,-4999,-4975,-4951,-4928,-4906,-4887,-4869,-4852,-4837,-4823,-4808,-4793,-4776,
--4758,-4738,-4716,-4692,-4667,-4640,-4613,-4584,-4555,-4527,-4500,-4474,-4450,-4429,-4411,-4396,-4383,-4374,-4366,-4359,-4353,
--4345,-4337,-4326,-4314,-4299,-4281,-4262,-4242,-4221,-4199,-4178,-4157,-4137,-4118,-4101,-4086,-4072,-4059,-4048,-4039,-4030,
--4022,-4014,-4005,-3995,-3985,-3972,-3959,-3944,-3929,-3913,-3897,-3881,-3866,-3851,-3837,-3822,-3808,-3792,-3775,-3756,-3735,
--3714,-3691,-3668,-3646,-3623,-3602,-3581,-3561,-3542,-3522,-3504,-3485,-3468,-3452,-3437,-3425,-3415,-3407,-3401,-3395,-3387,
--3377,-3363,-3344,-3320,-3293,-3263,-3234,-3206,-3182,-3163,-3150,-3140,-3133,-3125,-3113,-3093,-3064,-3025,-2975,-2917,-2854,
--2791,-2731,-2678,-2636,-2606,-2587,-2578,-2576,-2577,-2579,-2576,-2568,-2553,-2531,-2504,-2474,-2443,-2414,-2388,-2367,-2351,
--2339,-2331,-2325,-2320,-2315,-2309,-2302,-2292,-2282,-2270,-2257,-2242,-2227,-2211,-2195,-2179,-2164,-2150,-2139,-2130,-2124,
--2120,-2118,-2116,-2112,-2105,-2093,-2073,-2046,-2011,-1970,-1925,-1878,-1832,-1789,-1752,-1722,-1699,-1682,-1668,-1657,-1645,
--1630,-1613,-1591,-1567,-1541,-1516,-1493,-1475,-1462,-1455,-1454,-1457,-1463,-1469,-1475,-1479,-1479,-1477,-1473,-1467,-1459,
--1451,-1443,-1434,-1424,-1413,-1399,-1384,-1366,-1345,-1323,-1299,-1274,-1248,-1223,-1199,-1176,-1154,-1135,-1119,-1106,-1096,
--1091,-1089,-1089,-1091,-1091,-1089,-1081,-1067,-1045,-1015,-980,-941,-901,-863,-827,-796,-770,-746,-722,-696,-665,
--627,-581,-527,-468,-406,-345,-287,-235,-189,-148,-111,-75,-37,4,51,102,156,209,258,300,332,
-355,368,376,382,391,408,436,476,529,590,657,724,788,845,892,929,956,975,989,999,1007,
-1013,1016,1014,1005,987,959,920,871,815,753,690,627,568,514,464,418,376,337,299,262,227,
-195,167,144,126,114,107,104,102,99,94,85,71,53,31,7,-16,-39,-59,-77,-90,-101,
--110,-118,-124,-131,-137,-142,-146,-148,-148,-146,-142,-137,-132,-127,-123,-121,-120,-121,-122,-124,-124,
--124,-122,-118,-112,-106,-100,-95,-90,-86,-83,-81,-80,-78,-76,-73,-69,-64,-59,-53,-48,-43,
--38,-35,-31,-29,-26,-23,-20,-17,-14,-11,-8,-5,-2,0,1,2,4,6,9,12,16,
-20,25,29,33,36,38,39,38,37,36,35,34,34,35,37,39,41,42,43,43,41,
-38,35,31,26,23,20,18,18,19,20,22,25,27,29,31,34,37,40,44,49,54,
-59,63,66,67,67,64,60,56,52,48,46,46,48,52,57,64,70,75,80,84,86,
-87,87,86,85,84,82,81,79,76,74,73,72,74,78,85,96,111,130,153,178,207,
-237,270,304,340,379,420,463,508,554,601,648,693,736,776,813,847,879,911,942,974,1006,
-1038,1068,1095,1116,1131,1137,1134,1123,1106,1085,1064,1045,1033,1029,1034,1048,1068,1092,1117,1139,1157,
-1168,1173,1172,1166,1159,1151,1146,1144,1145,1149,1155,1161,1166,1171,1174,1176,1178,1182,1189,1200,1214,
-1230,1247,1263,1275,1281,1280,1206,1201,1193,1183,1171,1161,1154,1152,1158,1171,1191,1219,1253,1289,1327,
-1364,1397,1426,1448,1466,1477,1483,1484,1483,1479,1473,1466,1459,1452,1444,1436,1428,1419,1410,1400,1389,
-1377,1365,1352,1338,1324,1309,1293,1277,1261,1244,1229,1216,1206,1201,1202,1211,1226,1248,1276,1308,1340,
-1371,1397,1416,1427,1430,1428,1421,1415,1412,1415,1427,1448,1477,1513,1551,1589,1621,1646,1662,1670,1671,
-1670,1669,1674,1688,1712,1745,1787,1833,1878,1920,1952,1974,1985,1985,1978,1968,1959,1954,1957,1968,1986,
-2010,2036,2061,2083,2099,2109,2114,2116,2117,2120,2127,2139,2155,2174,2194,2211,2225,2232,2233,2229,2220,
-2210,2201,2194,2191,2192,2197,2203,2209,2212,2211,2207,2200,2192,2187,2187,2196,2215,2245,2285,2333,2384,
-2434,2480,2517,2542,2556,2557,2548,2531,2510,2488,2469,2452,2441,2434,2431,2431,2431,2431,2429,2426,2421,
-2416,2412,2408,2406,2405,2404,2401,2395,2383,2365,2340,2307,2269,2228,2187,2150,2120,2102,2096,2103,2123,
-2152,2189,2228,2266,2299,2326,2344,2356,2361,2363,2364,2368,2376,2391,2412,2438,2467,2495,2518,2535,2541,
-2536,2517,2487,2447,2399,2348,2297,2249,2208,2175,2152,2138,2133,2135,2142,2152,2161,2168,2171,2170,2164,
-2155,2142,2129,2115,2104,2094,2087,2083,2080,2077,2072,2065,2054,2039,2020,1998,1974,1951,1931,1915,1906,
-1904,1910,1925,1947,1974,2007,2043,2081,2120,2159,2197,2232,2265,2293,2316,2331,2337,2332,2315,2285,2242,
-2186,2119,2042,1959,1872,1785,1701,1625,1558,1502,1459,1429,1412,1405,1407,1416,1428,1441,1452,1459,1461,
-1457,1449,1437,1424,1411,1400,1395,1394,1400,1412,1428,1447,1467,1486,1503,1516,1524,1528,1529,1527,1524,
-1521,1519,1519,1521,1524,1527,1531,1533,1535,1534,1531,1527,1520,1512,1503,1492,1480,1467,1452,1435,1416,
-1396,1374,1351,1327,1302,1278,1254,1230,1207,1184,1162,1139,1116,1092,1067,1041,1014,987,960,932,903,
-873,843,811,779,747,714,682,651,622,595,572,552,534,519,504,490,474,455,434,409,380,
-349,316,282,247,212,178,144,110,74,35,-6,-53,-103,-158,-216,-276,-336,-393,-448,-497,-542,
--582,-619,-652,-684,-716,-749,-784,-821,-859,-899,-938,-976,-1012,-1045,-1076,-1105,-1133,-1161,-1191,-1222,-1255,
--1292,-1330,-1370,-1410,-1449,-1488,-1524,-1560,-1593,-1627,-1660,-1694,-1730,-1767,-1806,-1845,-1884,-1923,-1961,-1997,-2033,
--2068,-2103,-2138,-2175,-2214,-2253,-2294,-2333,-2372,-2407,-2440,-2468,-2493,-2514,-2533,-2552,-2570,-2590,-2611,-2635,-2660,
--2688,-2716,-2744,-2772,-2799,-2824,-2849,-2874,-2899,-2925,-2952,-2981,-3011,-3042,-3073,-3103,-3131,-3155,-3176,-3192,-3202,
--3208,-3209,-3207,-3203,-3198,-3194,-3192,-3193,-3199,-3210,-3226,-3246,-3269,-3294,-3320,-3345,-3368,-3388,-3404,-3417,-3427,
--3436,-3444,-3453,-3464,-3478,-3495,-3514,-3535,-3557,-3578,-3597,-3612,-3624,-3632,-3638,-3641,-3644,-3649,-3657,-3670,-3688,
--3710,-3738,-3768,-3799,-3830,-3858,-3881,-3900,-3915,-3926,-3935,-3945,-3956,-3970,-3989,-4012,-4038,-4067,-4096,-4125,-4151,
--4175,-4198,-4219,-4241,-4267,-4297,-4335,-4379,-4431,-4488,-4551,-4616,-4682,-4747,-4808,-4866,-4919,-4967,-5011,-5048,-5080,
--5106,-5125,-5137,-5141,-5140,-5133,-5123,-5112,-5103,-5098,-5098,-5104,-5114,-5127,-5141,-5153,-5162,-5166,-5166,-5162,-5156,
--5152,-5151,-5158,-5172,-5194,-5224,-5260,-5298,-5337,-5373,-5406,-5436,-5462,-5486,-5509,-5533,-5558,-5583,-5608,-5632,-5652,
--5667,-5677,-5682,-5684,-5684,-5685,-5690,-5699,-5713,-5731,-5749,-5765,-5776,-5779,-5773,-5758,-5737,-5713,-5690,-5673,-5665,
--5665,-5674,-5688,-5702,-5710,-5708,-5691,-5659,-5613,-5556,-5496,-5438,-5392,-5363,-5355,-5370,-5406,-5459,-5523,-5592,-5660,
--5720,-5770,-5808,-5832,-5846,-5849,-5845,-5836,-5823,-5807,-5788,-5768,-5747,-5726,-5707,-5692,-5681,-5676,-5678,-5683,-5692,
--5700,-5705,-5702,-5691,-5669,-5637,-5598,-5555,-5512,-5474,-5445,-5428,-5425,-5437,-5461,-5497,-5540,-5588,-5638,-5688,-5736,
--5780,-5820,-5857,-5889,-5917,-5941,-5959,-5973,-5983,-5988,-5989,-5989,-5987,-5987,-5988,-5993,-6001,-6012,-6026,-6042,-6059,
--6075,-6090,-6104,-6116,-6127,-6136,-6143,-6149,-6153,-6155,-6156,-6154,-6150,-6145,-6139,-6134,-6131,-6131,-6138,-6150,-6169,
--6194,-6224,-6258,-6294,-6330,-6364,-6396,-6424,-6447,-6467,-6483,-6497,-6508,-6517,-6525,-6531,-6536,-6539,-6542,-6543,-6545,
--6548,-6554,-6561,-6572,-6585,-6599,-6614,-6626,-6634,-6636,-6630,-6616,-6595,-6569,-6538,-6507,-6479,-6456,-6441,-6435,-6436,
--6445,-6459,-6474,-6489,-6499,-6504,-6502,-6494,-6479,-6460,-6440,-6420,-6402,-6387,-6377,-6370,-6367,-6365,-6364,-6362,-6358,
--6352,-6344,-6335,-6324,-6315,-6306,-6299,-6294,-6289,-6286,-6283,-6279,-6273,-6266,-6258,-6248,-6238,-6228,-6219,-6211,-6204,
--6199,-6195,-6192,-6188,-6184,-6178,-6170,-6161,-6150,-6139,-6126,-6114,-6101,-6088,-6076,-6064,-6051,-6038,-6025,-6011,-5997,
--5983,-5970,-5957,-5947,-5937,-5930,-5923,-5917,-5911,-5905,-5898,-5890,-5880,-5869,-5856,-5843,-5830,-5817,-5805,-5794,-5783,
--5773,-5762,-5751,-5739,-5725,-5709,-5691,-5671,-5650,-5627,-5603,-5579,-5555,-5531,-5509,-5489,-5469,-5451,-5434,-5417,-5400,
--5384,-5366,-5348,-5329,-5309,-5289,-5270,-5251,-5233,-5216,-5201,-5188,-5176,-5164,-5153,-5141,-5128,-5114,-5098,-5080,-5061,
--5041,-5020,-4999,-4979,-4960,-4941,-4924,-4907,-4890,-4873,-4856,-4837,-4818,-4796,-4774,-4750,-4724,-4697,-4669,-4640,-4611,
--4581,-4552,-4524,-4498,-4475,-4455,-4439,-4428,-4420,-4415,-4412,-4410,-4408,-4405,-4400,-4392,-4380,-4365,-4346,-4325,-4302,
--4276,-4250,-4223,-4197,-4170,-4145,-4120,-4098,-4077,-4059,-4043,-4029,-4018,-4009,-4001,-3993,-3984,-3974,-3962,-3947,-3929,
--3908,-3886,-3862,-3838,-3815,-3791,-3769,-3747,-3725,-3703,-3679,-3654,-3627,-3599,-3570,-3540,-3511,-3484,-3459,-3438,-3420,
--3404,-3392,-3381,-3372,-3363,-3355,-3347,-3339,-3331,-3323,-3315,-3306,-3296,-3284,-3269,-3250,-3229,-3206,-3181,-3157,-3134,
--3115,-3100,-3090,-3084,-3081,-3079,-3074,-3063,-3045,-3018,-2981,-2936,-2883,-2827,-2771,-2718,-2672,-2634,-2606,-2586,-2575,
--2569,-2565,-2561,-2556,-2546,-2531,-2513,-2490,-2465,-2440,-2415,-2391,-2371,-2353,-2338,-2326,-2316,-2308,-2301,-2294,-2288,
--2282,-2274,-2265,-2254,-2240,-2224,-2206,-2186,-2166,-2147,-2130,-2117,-2109,-2106,-2107,-2111,-2116,-2118,-2116,-2107,-2090,
--2063,-2028,-1986,-1940,-1893,-1848,-1808,-1774,-1747,-1726,-1711,-1699,-1688,-1676,-1662,-1644,-1624,-1602,-1580,-1560,-1542,
--1530,-1522,-1518,-1518,-1519,-1521,-1521,-1519,-1515,-1507,-1497,-1485,-1473,-1462,-1451,-1442,-1433,-1424,-1414,-1402,-1388,
--1371,-1351,-1328,-1302,-1274,-1246,-1217,-1190,-1166,-1144,-1128,-1116,-1110,-1110,-1114,-1121,-1129,-1136,-1139,-1135,-1124,
--1105,-1076,-1041,-1001,-957,-914,-873,-835,-801,-770,-739,-708,-673,-634,-588,-536,-480,-420,-361,-302,-247,
--197,-150,-106,-65,-23,20,65,112,158,203,243,276,302,321,332,340,348,359,376,403,439,
-484,536,593,650,704,753,794,827,853,873,888,900,909,915,917,913,901,880,850,809,761,
-706,647,588,530,476,426,381,340,301,264,228,192,157,124,95,71,52,40,34,33,34,
-36,37,35,28,17,3,-13,-30,-47,-62,-73,-82,-88,-92,-96,-100,-104,-110,-117,-123,-129,
--134,-136,-136,-134,-130,-125,-120,-116,-114,-113,-115,-118,-121,-125,-128,-129,-129,-128,-125,-122,-118,
--115,-112,-110,-108,-107,-106,-104,-102,-100,-97,-93,-89,-86,-83,-80,-79,-77,-76,-75,-73,-71,
--68,-65,-62,-58,-55,-52,-49,-47,-45,-43,-41,-38,-35,-32,-28,-23,-19,-15,-12,-9,-7,
--6,-6,-7,-7,-7,-7,-7,-6,-5,-5,-4,-4,-5,-6,-7,-9,-10,-11,-11,-10,-9,
--7,-5,-2,0,1,2,3,4,6,7,9,11,13,15,15,15,13,10,6,1,-3,
--7,-9,-10,-8,-4,1,9,17,25,32,38,43,47,49,49,49,48,47,46,44,43,
-42,42,44,49,56,67,82,101,124,151,180,212,245,280,316,354,393,435,478,524,571,
-619,666,711,752,789,821,847,871,891,911,933,957,984,1014,1044,1074,1100,1118,1128,1128,1117,
-1098,1073,1046,1021,1004,996,1001,1018,1047,1083,1125,1167,1205,1236,1259,1272,1278,1276,1270,1262,1255,
-1250,1247,1246,1246,1247,1246,1243,1238,1231,1223,1216,1209,1205,1203,1204,1206,1208,1208,1206,1177,1180,
-1183,1185,1187,1190,1194,1202,1214,1232,1255,1285,1319,1358,1398,1438,1476,1511,1542,1566,1585,1599,1607,
-1611,1611,1608,1603,1596,1588,1577,1566,1553,1539,1524,1509,1494,1479,1466,1453,1442,1431,1421,1410,1399,
-1387,1375,1362,1351,1342,1337,1337,1344,1357,1377,1400,1427,1452,1475,1493,1503,1506,1502,1493,1483,1475,
-1472,1477,1492,1516,1547,1584,1621,1655,1682,1700,1709,1710,1705,1698,1694,1697,1709,1732,1764,1804,1847,
-1889,1925,1953,1971,1978,1978,1974,1970,1970,1976,1992,2015,2044,2076,2106,2131,2148,2154,2151,2141,2127,
-2112,2102,2098,2103,2117,2136,2160,2184,2204,2219,2225,2225,2217,2206,2194,2183,2177,2175,2178,2186,2195,
-2204,2212,2218,2221,2224,2228,2236,2250,2273,2304,2344,2391,2441,2491,2537,2575,2602,2618,2623,2618,2605,
-2589,2570,2553,2540,2530,2524,2521,2520,2519,2517,2514,2509,2503,2496,2489,2483,2478,2473,2468,2459,2446,
-2427,2400,2365,2322,2274,2225,2176,2134,2101,2081,2075,2084,2106,2139,2178,2219,2258,2292,2317,2333,2341,
-2343,2341,2339,2340,2346,2360,2381,2407,2436,2465,2489,2504,2509,2501,2479,2445,2402,2352,2299,2248,2203,
-2165,2136,2118,2109,2107,2111,2118,2126,2131,2134,2132,2125,2115,2103,2089,2076,2065,2055,2049,2044,2041,
-2039,2036,2031,2024,2013,2000,1984,1967,1951,1935,1923,1915,1911,1911,1916,1926,1938,1954,1972,1992,2014,
-2038,2063,2090,2118,2146,2173,2196,2214,2226,2228,2219,2199,2166,2121,2066,2001,1929,1854,1777,1703,1632,
-1569,1515,1470,1436,1412,1396,1388,1385,1385,1387,1387,1385,1380,1371,1360,1347,1335,1325,1318,1318,1323,
-1335,1352,1373,1397,1420,1442,1461,1475,1485,1490,1492,1491,1490,1489,1490,1492,1496,1500,1505,1510,1513,
-1514,1512,1508,1501,1493,1483,1471,1459,1445,1431,1415,1399,1380,1360,1339,1317,1295,1272,1249,1227,1205,
-1183,1161,1139,1116,1092,1067,1041,1014,986,958,928,899,869,838,807,775,743,711,679,648,619,
-592,569,549,532,517,505,493,480,465,448,427,402,374,344,311,278,245,212,181,150,118,
-86,51,12,-29,-76,-127,-182,-239,-297,-354,-409,-461,-509,-552,-592,-629,-663,-697,-730,-764,-799,
--836,-873,-910,-948,-984,-1020,-1054,-1088,-1121,-1154,-1187,-1222,-1258,-1295,-1333,-1372,-1411,-1450,-1489,-1528,-1566,
--1603,-1641,-1678,-1716,-1753,-1791,-1830,-1868,-1905,-1943,-1981,-2019,-2058,-2099,-2141,-2185,-2231,-2279,-2326,-2373,-2416,
--2456,-2491,-2520,-2543,-2561,-2575,-2586,-2596,-2607,-2620,-2637,-2656,-2679,-2704,-2732,-2759,-2787,-2813,-2839,-2863,-2887,
--2912,-2937,-2964,-2993,-3024,-3055,-3087,-3118,-3147,-3172,-3192,-3207,-3217,-3221,-3221,-3218,-3214,-3209,-3207,-3208,-3213,
--3223,-3237,-3256,-3279,-3303,-3328,-3353,-3375,-3395,-3412,-3426,-3439,-3450,-3461,-3473,-3488,-3506,-3527,-3551,-3577,-3603,
--3627,-3649,-3665,-3676,-3682,-3681,-3677,-3671,-3666,-3663,-3666,-3676,-3693,-3718,-3749,-3784,-3821,-3857,-3889,-3916,-3938,
--3953,-3963,-3971,-3978,-3986,-3998,-4015,-4036,-4061,-4090,-4120,-4149,-4177,-4202,-4226,-4249,-4272,-4298,-4328,-4365,-4410,
--4463,-4523,-4589,-4659,-4730,-4800,-4868,-4930,-4986,-5034,-5075,-5106,-5130,-5144,-5151,-5150,-5144,-5132,-5118,-5104,-5091,
--5083,-5079,-5080,-5087,-5098,-5112,-5126,-5139,-5148,-5153,-5155,-5153,-5152,-5151,-5154,-5163,-5179,-5201,-5229,-5261,-5295,
--5330,-5363,-5395,-5425,-5452,-5479,-5506,-5534,-5562,-5589,-5615,-5638,-5656,-5669,-5677,-5679,-5678,-5676,-5676,-5679,-5687,
--5700,-5716,-5734,-5751,-5762,-5767,-5764,-5753,-5736,-5715,-5695,-5679,-5670,-5668,-5672,-5681,-5689,-5693,-5688,-5670,-5638,
--5592,-5537,-5476,-5417,-5366,-5328,-5309,-5310,-5332,-5371,-5423,-5484,-5547,-5608,-5662,-5706,-5739,-5759,-5769,-5768,-5758,
--5741,-5719,-5692,-5663,-5635,-5608,-5586,-5570,-5562,-5562,-5568,-5580,-5594,-5606,-5613,-5610,-5597,-5572,-5537,-5493,-5447,
--5401,-5362,-5334,-5320,-5323,-5342,-5376,-5421,-5475,-5533,-5591,-5647,-5698,-5743,-5782,-5815,-5843,-5866,-5885,-5902,-5915,
--5926,-5936,-5944,-5952,-5959,-5967,-5976,-5987,-6000,-6014,-6029,-6045,-6060,-6075,-6088,-6101,-6111,-6121,-6130,-6138,-6145,
--6152,-6158,-6162,-6164,-6164,-6162,-6158,-6154,-6150,-6148,-6149,-6155,-6166,-6183,-6205,-6230,-6259,-6289,-6318,-6347,-6373,
--6397,-6418,-6438,-6456,-6474,-6492,-6510,-6527,-6544,-6559,-6573,-6586,-6596,-6604,-6611,-6618,-6623,-6629,-6634,-6638,-6640,
--6640,-6636,-6627,-6614,-6596,-6575,-6553,-6530,-6510,-6494,-6483,-6479,-6480,-6486,-6496,-6506,-6515,-6520,-6521,-6516,-6505,
--6490,-6472,-6453,-6435,-6419,-6407,-6398,-6393,-6391,-6390,-6389,-6387,-6384,-6378,-6370,-6361,-6350,-6340,-6331,-6323,-6316,
--6311,-6306,-6302,-6297,-6291,-6285,-6277,-6268,-6260,-6251,-6243,-6236,-6231,-6226,-6221,-6217,-6211,-6205,-6197,-6188,-6177,
--6165,-6153,-6142,-6130,-6120,-6111,-6101,-6093,-6083,-6073,-6062,-6049,-6036,-6021,-6007,-5992,-5979,-5967,-5957,-5948,-5940,
--5933,-5926,-5919,-5911,-5901,-5891,-5880,-5869,-5857,-5846,-5835,-5824,-5813,-5802,-5791,-5778,-5763,-5746,-5728,-5707,-5685,
--5662,-5638,-5614,-5592,-5570,-5550,-5531,-5513,-5496,-5480,-5464,-5448,-5431,-5413,-5395,-5376,-5357,-5337,-5318,-5299,-5280,
--5263,-5246,-5231,-5216,-5202,-5189,-5175,-5162,-5148,-5134,-5119,-5104,-5089,-5073,-5058,-5042,-5025,-5009,-4991,-4973,-4953,
--4933,-4911,-4887,-4863,-4838,-4811,-4785,-4758,-4731,-4703,-4675,-4648,-4621,-4594,-4568,-4544,-4522,-4502,-4486,-4473,-4462,
--4455,-4450,-4446,-4443,-4439,-4434,-4427,-4418,-4406,-4392,-4377,-4359,-4339,-4317,-4294,-4269,-4243,-4215,-4187,-4158,-4129,
--4102,-4076,-4054,-4035,-4020,-4008,-3997,-3987,-3977,-3964,-3948,-3927,-3902,-3873,-3840,-3805,-3769,-3735,-3702,-3671,-3642,
--3615,-3589,-3563,-3536,-3507,-3477,-3445,-3413,-3383,-3355,-3331,-3312,-3299,-3290,-3285,-3284,-3284,-3283,-3282,-3278,-3272,
--3264,-3253,-3241,-3228,-3215,-3201,-3187,-3172,-3156,-3140,-3123,-3106,-3090,-3076,-3065,-3057,-3052,-3050,-3049,-3049,-3046,
--3040,-3027,-3008,-2982,-2949,-2911,-2869,-2826,-2785,-2747,-2713,-2685,-2663,-2645,-2630,-2617,-2604,-2590,-2573,-2554,-2532,
--2508,-2482,-2456,-2429,-2404,-2381,-2359,-2340,-2324,-2310,-2299,-2289,-2281,-2273,-2266,-2256,-2245,-2231,-2214,-2195,-2174,
--2152,-2132,-2115,-2103,-2098,-2098,-2105,-2117,-2131,-2145,-2155,-2159,-2154,-2138,-2113,-2078,-2035,-1989,-1940,-1894,-1851,
--1815,-1785,-1762,-1744,-1730,-1718,-1707,-1695,-1683,-1669,-1655,-1641,-1628,-1617,-1608,-1600,-1593,-1586,-1579,-1571,-1561,
--1550,-1536,-1522,-1508,-1494,-1481,-1469,-1459,-1451,-1443,-1434,-1425,-1414,-1400,-1383,-1364,-1343,-1319,-1294,-1268,-1243,
--1219,-1199,-1182,-1170,-1162,-1159,-1160,-1165,-1170,-1174,-1175,-1171,-1160,-1142,-1115,-1082,-1043,-1001,-957,-913,-871,
--831,-794,-758,-722,-685,-646,-603,-558,-509,-459,-407,-356,-307,-259,-212,-167,-122,-76,-30,16,63,
-108,151,188,220,244,263,276,286,295,308,325,348,379,416,459,505,551,596,638,675,708,
-735,758,777,791,801,806,803,792,770,738,695,643,584,521,458,397,342,294,253,219,190,
-166,143,120,96,71,47,23,2,-14,-25,-32,-34,-33,-30,-27,-25,-27,-31,-39,-48,-58,
--67,-74,-79,-82,-82,-81,-80,-81,-83,-88,-95,-103,-111,-119,-125,-128,-128,-125,-120,-114,-108,
--103,-100,-100,-102,-106,-112,-118,-124,-129,-133,-136,-137,-138,-138,-137,-136,-136,-136,-135,-135,-134,
--133,-131,-129,-127,-125,-124,-123,-123,-124,-125,-126,-127,-127,-127,-125,-123,-120,-117,-114,-111,-108,
--106,-104,-102,-100,-98,-95,-92,-88,-84,-79,-74,-70,-67,-64,-62,-60,-59,-57,-56,-55,-54,
--52,-51,-49,-48,-47,-47,-47,-47,-48,-48,-48,-48,-48,-47,-46,-45,-44,-43,-43,-42,-41,
--41,-40,-39,-38,-38,-38,-40,-42,-44,-48,-51,-55,-57,-58,-58,-56,-52,-47,-40,-33,-26,
--19,-13,-7,-3,0,4,7,10,13,15,18,21,24,28,33,39,48,61,77,98,123,
-151,183,217,254,291,329,368,407,448,489,533,577,622,665,707,745,777,804,824,837,847,
-854,861,872,887,908,935,966,1000,1032,1059,1078,1087,1086,1074,1054,1030,1007,990,982,987,1005,
-1037,1080,1131,1184,1234,1279,1315,1340,1353,1357,1354,1345,1334,1323,1314,1306,1300,1295,1289,1282,1272,
-1259,1245,1229,1213,1199,1188,1180,1175,1174,1175,1177,1246,1254,1263,1273,1283,1292,1303,1314,1328,1346,
-1367,1392,1422,1456,1492,1531,1570,1608,1644,1677,1706,1730,1748,1762,1769,1771,1767,1758,1743,1725,1702,
-1677,1651,1626,1602,1581,1565,1553,1546,1544,1545,1549,1553,1556,1558,1557,1554,1549,1544,1540,1538,1541,
-1547,1558,1572,1587,1602,1614,1623,1626,1624,1619,1611,1604,1600,1602,1611,1628,1651,1679,1707,1733,1753,
-1764,1766,1760,1747,1732,1717,1708,1707,1718,1739,1769,1806,1845,1883,1916,1941,1960,1973,1983,1995,2012,
-2036,2071,2114,2164,2216,2265,2304,2328,2335,2322,2293,2249,2198,2146,2098,2062,2040,2034,2042,2062,2088,
-2117,2144,2165,2178,2182,2180,2174,2166,2159,2156,2158,2164,2175,2188,2203,2218,2232,2246,2259,2275,2293,
-2316,2343,2376,2413,2451,2489,2523,2551,2572,2585,2590,2588,2581,2572,2563,2556,2552,2551,2554,2558,2562,
-2566,2567,2566,2561,2554,2546,2536,2526,2516,2506,2494,2480,2461,2437,2405,2366,2322,2273,2223,2176,2135,
-2105,2087,2084,2095,2119,2153,2193,2235,2275,2309,2335,2352,2361,2362,2360,2357,2355,2357,2365,2377,2394,
-2412,2428,2441,2446,2442,2428,2403,2371,2331,2289,2246,2207,2173,2146,2127,2115,2109,2108,2109,2110,2109,
-2106,2100,2091,2080,2067,2054,2043,2033,2026,2021,2019,2018,2017,2016,2015,2012,2009,2004,1998,1993,1988,
-1985,1983,1982,1982,1984,1985,1987,1988,1989,1990,1991,1993,1996,2002,2010,2022,2036,2051,2068,2084,2098,
-2108,2114,2113,2105,2090,2067,2036,1998,1953,1902,1846,1786,1725,1663,1603,1546,1494,1447,1408,1376,1351,
-1332,1319,1308,1301,1294,1287,1281,1275,1270,1268,1270,1276,1288,1305,1327,1353,1380,1407,1431,1452,1468,
-1479,1484,1486,1485,1482,1479,1478,1478,1480,1482,1486,1489,1490,1489,1485,1479,1470,1458,1445,1430,1415,
-1399,1382,1365,1347,1328,1308,1287,1266,1244,1222,1199,1178,1156,1135,1114,1093,1072,1049,1026,1002,976,
-948,919,890,859,827,795,762,729,697,666,636,609,584,562,544,529,516,506,497,488,477,
-464,448,428,404,376,345,311,277,242,207,172,138,105,71,37,0,-37,-78,-121,-167,-215,
--264,-314,-362,-409,-455,-498,-539,-578,-615,-651,-687,-723,-759,-797,-836,-876,-917,-958,-1000,-1042,-1083,
--1124,-1165,-1205,-1244,-1283,-1322,-1360,-1399,-1439,-1478,-1519,-1560,-1603,-1645,-1688,-1731,-1773,-1814,-1853,-1892,-1928,
--1964,-2000,-2037,-2075,-2116,-2160,-2207,-2259,-2312,-2367,-2422,-2475,-2523,-2566,-2602,-2630,-2651,-2666,-2675,-2682,-2688,
--2694,-2704,-2717,-2733,-2754,-2777,-2803,-2829,-2855,-2880,-2903,-2924,-2945,-2965,-2986,-3007,-3030,-3054,-3079,-3105,-3130,
--3154,-3175,-3192,-3205,-3213,-3218,-3219,-3218,-3217,-3217,-3219,-3225,-3235,-3249,-3267,-3288,-3312,-3336,-3360,-3383,-3404,
--3422,-3439,-3455,-3470,-3487,-3506,-3529,-3556,-3587,-3621,-3656,-3690,-3722,-3747,-3765,-3775,-3774,-3765,-3748,-3727,-3706,
--3687,-3674,-3671,-3678,-3697,-3726,-3763,-3806,-3849,-3891,-3927,-3956,-3977,-3990,-3997,-4000,-4003,-4008,-4018,-4033,-4055,
--4083,-4115,-4149,-4182,-4214,-4243,-4269,-4292,-4315,-4340,-4369,-4404,-4448,-4500,-4561,-4628,-4701,-4774,-4847,-4914,-4975,
--5026,-5065,-5093,-5110,-5115,-5111,-5099,-5081,-5060,-5038,-5017,-5001,-4990,-4987,-4991,-5002,-5019,-5040,-5064,-5088,-5109,
--5127,-5141,-5151,-5157,-5162,-5167,-5174,-5184,-5199,-5219,-5243,-5271,-5302,-5335,-5367,-5400,-5432,-5464,-5495,-5526,-5556,
--5585,-5612,-5635,-5654,-5667,-5674,-5677,-5675,-5671,-5668,-5667,-5671,-5681,-5696,-5715,-5736,-5755,-5771,-5780,-5782,-5776,
--5764,-5747,-5730,-5715,-5705,-5700,-5700,-5704,-5708,-5709,-5703,-5686,-5658,-5619,-5569,-5514,-5458,-5405,-5362,-5332,-5319,
--5322,-5341,-5374,-5418,-5467,-5518,-5567,-5610,-5644,-5668,-5680,-5681,-5671,-5651,-5624,-5592,-5558,-5525,-5497,-5476,-5465,
--5465,-5476,-5497,-5523,-5552,-5578,-5597,-5605,-5599,-5578,-5544,-5501,-5452,-5404,-5363,-5334,-5320,-5323,-5345,-5382,-5431,
--5488,-5548,-5606,-5658,-5702,-5737,-5763,-5780,-5790,-5796,-5800,-5804,-5809,-5817,-5828,-5843,-5862,-5884,-5909,-5935,-5963,
--5992,-6020,-6046,-6070,-6091,-6109,-6123,-6134,-6143,-6149,-6155,-6159,-6163,-6168,-6171,-6174,-6176,-6176,-6174,-6171,-6167,
--6163,-6160,-6160,-6162,-6169,-6180,-6195,-6214,-6236,-6259,-6282,-6305,-6328,-6349,-6370,-6391,-6412,-6434,-6458,-6484,-6509,
--6535,-6559,-6581,-6599,-6613,-6623,-6628,-6629,-6627,-6622,-6617,-6611,-6606,-6600,-6593,-6587,-6579,-6570,-6560,-6549,-6539,
--6528,-6520,-6514,-6510,-6509,-6511,-6513,-6516,-6519,-6519,-6516,-6510,-6501,-6489,-6476,-6463,-6450,-6439,-6430,-6424,-6420,
--6418,-6416,-6414,-6411,-6406,-6400,-6391,-6381,-6371,-6361,-6351,-6343,-6335,-6329,-6324,-6319,-6315,-6309,-6303,-6296,-6288,
--6280,-6273,-6265,-6258,-6252,-6247,-6242,-6236,-6230,-6223,-6215,-6206,-6196,-6185,-6174,-6163,-6153,-6144,-6135,-6127,-6118,
--6109,-6100,-6089,-6077,-6065,-6051,-6037,-6024,-6011,-5999,-5989,-5979,-5971,-5963,-5955,-5948,-5939,-5930,-5920,-5910,-5899,
--5887,-5875,-5862,-5850,-5836,-5822,-5806,-5790,-5772,-5752,-5731,-5710,-5688,-5666,-5645,-5624,-5605,-5588,-5571,-5555,-5540,
--5526,-5511,-5495,-5480,-5463,-5446,-5428,-5410,-5391,-5373,-5354,-5336,-5318,-5299,-5281,-5263,-5245,-5227,-5210,-5193,-5177,
--5162,-5148,-5135,-5123,-5111,-5099,-5086,-5072,-5057,-5040,-5021,-5000,-4977,-4953,-4927,-4900,-4873,-4846,-4820,-4793,-4768,
--4743,-4718,-4694,-4670,-4646,-4624,-4602,-4581,-4562,-4545,-4530,-4516,-4504,-4492,-4481,-4470,-4457,-4444,-4430,-4416,-4401,
--4386,-4372,-4359,-4347,-4335,-4323,-4310,-4294,-4276,-4254,-4230,-4202,-4172,-4141,-4111,-4083,-4058,-4036,-4017,-4001,-3985,
--3968,-3948,-3925,-3896,-3861,-3822,-3780,-3736,-3692,-3651,-3613,-3581,-3552,-3528,-3507,-3486,-3466,-3444,-3420,-3393,-3366,
--3339,-3314,-3293,-3276,-3264,-3258,-3256,-3257,-3259,-3261,-3261,-3257,-3250,-3240,-3228,-3214,-3199,-3186,-3173,-3162,-3152,
--3143,-3134,-3124,-3113,-3101,-3088,-3074,-3061,-3049,-3039,-3031,-3024,-3019,-3014,-3007,-2998,-2985,-2969,-2948,-2923,-2895,
--2865,-2834,-2804,-2774,-2746,-2720,-2695,-2670,-2646,-2622,-2596,-2569,-2542,-2513,-2484,-2455,-2427,-2400,-2375,-2352,-2331,
--2313,-2297,-2284,-2272,-2262,-2252,-2242,-2232,-2220,-2206,-2190,-2173,-2155,-2136,-2120,-2108,-2101,-2101,-2107,-2121,-2141,
--2165,-2190,-2213,-2231,-2240,-2239,-2226,-2202,-2166,-2121,-2070,-2017,-1963,-1913,-1869,-1831,-1800,-1777,-1760,-1749,-1740,
--1734,-1728,-1722,-1714,-1705,-1695,-1683,-1669,-1654,-1639,-1622,-1606,-1590,-1574,-1559,-1545,-1532,-1520,-1509,-1498,-1487,
--1477,-1466,-1454,-1442,-1429,-1416,-1402,-1388,-1373,-1358,-1343,-1328,-1313,-1298,-1283,-1268,-1254,-1242,-1231,-1222,-1214,
--1207,-1200,-1192,-1181,-1167,-1148,-1125,-1098,-1066,-1031,-994,-956,-917,-878,-840,-802,-764,-726,-687,-647,-606,
--564,-522,-479,-436,-393,-349,-304,-258,-210,-160,-108,-56,-4,44,89,129,162,187,206,219,229,
-237,247,260,278,301,330,364,402,441,480,519,556,591,622,651,675,695,708,712,707,689,
-659,615,560,495,423,348,274,206,146,97,59,31,11,-1,-11,-19,-28,-39,-52,-66,-79,
--91,-100,-105,-106,-104,-100,-95,-90,-87,-85,-86,-89,-92,-95,-97,-97,-95,-92,-87,-83,-80,
--79,-80,-83,-88,-94,-101,-106,-109,-109,-107,-102,-96,-90,-85,-81,-79,-80,-84,-90,-98,-106,
--114,-122,-129,-135,-140,-144,-147,-150,-152,-154,-156,-157,-158,-158,-158,-158,-158,-158,-159,-161,-164,
--168,-172,-177,-181,-185,-188,-189,-189,-188,-186,-183,-180,-177,-174,-171,-169,-166,-164,-162,-159,-156,
--153,-149,-146,-142,-139,-136,-133,-130,-127,-124,-121,-118,-114,-111,-107,-104,-101,-99,-98,-98,-99,
--101,-103,-105,-107,-109,-111,-112,-112,-111,-109,-107,-104,-101,-98,-95,-92,-90,-88,-88,-88,-90,
--91,-93,-95,-97,-97,-96,-94,-91,-87,-83,-79,-75,-71,-67,-64,-61,-57,-52,-46,-39,-31,
--21,-11,-1,9,19,29,39,51,64,81,101,126,155,189,225,265,306,348,391,432,473,
-513,552,590,628,664,698,728,754,775,789,796,799,797,794,792,794,801,817,840,870,904,
-940,974,1002,1022,1033,1035,1029,1018,1006,998,998,1008,1031,1066,1112,1165,1221,1276,1325,1366,1395,
-1412,1418,1414,1404,1390,1375,1360,1348,1339,1332,1326,1320,1313,1304,1294,1282,1269,1257,1247,1240,1236,
-1236,1240,1246,1374,1381,1389,1398,1408,1419,1430,1442,1456,1472,1491,1513,1538,1567,1599,1634,1671,1709,
-1747,1784,1819,1850,1877,1897,1911,1916,1913,1901,1881,1854,1822,1786,1750,1715,1684,1659,1643,1635,1636,
-1644,1659,1677,1696,1715,1731,1743,1750,1754,1754,1752,1750,1749,1750,1753,1758,1764,1770,1774,1776,1775,
-1772,1768,1763,1761,1762,1768,1780,1795,1814,1834,1850,1862,1866,1862,1849,1830,1808,1786,1768,1757,1757,
-1766,1785,1812,1842,1873,1902,1926,1945,1960,1975,1994,2021,2059,2111,2176,2253,2335,2416,2489,2545,2577,
-2582,2558,2508,2437,2352,2263,2178,2106,2052,2020,2009,2017,2040,2071,2105,2137,2162,2178,2186,2186,2182,
-2176,2172,2172,2177,2188,2203,2223,2244,2267,2289,2311,2332,2353,2374,2395,2417,2440,2462,2482,2500,2513,
-2522,2526,2526,2524,2520,2516,2515,2516,2522,2532,2544,2557,2571,2582,2590,2593,2592,2587,2578,2566,2552,
-2537,2520,2502,2481,2457,2428,2394,2355,2312,2267,2221,2179,2143,2116,2101,2098,2109,2131,2163,2202,2243,
-2283,2320,2351,2374,2389,2398,2402,2402,2401,2399,2398,2398,2398,2397,2393,2385,2372,2353,2329,2300,2268,
-2234,2201,2171,2146,2125,2109,2097,2089,2083,2078,2072,2064,2055,2044,2032,2019,2008,1998,1991,1986,1983,
-1982,1983,1984,1984,1984,1983,1982,1981,1981,1983,1988,1995,2004,2015,2028,2039,2050,2057,2061,2060,2055,
-2047,2037,2025,2014,2004,1996,1992,1991,1992,1996,2001,2007,2014,2020,2025,2030,2033,2034,2031,2025,2013,
-1994,1966,1929,1882,1826,1762,1692,1619,1546,1477,1415,1361,1319,1287,1266,1254,1249,1249,1252,1256,1260,
-1265,1271,1279,1289,1304,1323,1346,1372,1401,1430,1457,1480,1499,1512,1519,1520,1518,1513,1507,1501,1496,
-1492,1490,1488,1486,1483,1477,1469,1459,1445,1429,1412,1393,1375,1356,1338,1319,1301,1283,1263,1243,1221,
-1198,1174,1149,1124,1100,1076,1053,1031,1009,988,966,944,920,895,868,839,808,776,743,709,676,
-644,615,588,564,545,529,516,507,499,493,487,480,471,459,444,425,401,374,344,311,276,
-240,203,166,129,93,57,21,-14,-51,-89,-128,-169,-210,-253,-297,-342,-386,-430,-473,-515,-556,
--595,-634,-672,-710,-748,-788,-829,-872,-917,-963,-1012,-1061,-1110,-1159,-1207,-1253,-1297,-1339,-1380,-1420,-1459,
--1499,-1540,-1582,-1627,-1673,-1720,-1768,-1816,-1862,-1907,-1949,-1989,-2027,-2064,-2100,-2137,-2177,-2221,-2269,-2321,-2377,
--2436,-2496,-2555,-2610,-2660,-2703,-2737,-2762,-2780,-2790,-2795,-2797,-2799,-2803,-2809,-2820,-2835,-2855,-2878,-2904,-2931,
--2958,-2983,-3006,-3027,-3046,-3062,-3077,-3092,-3107,-3122,-3138,-3154,-3171,-3186,-3201,-3213,-3223,-3230,-3235,-3237,-3239,
--3241,-3244,-3249,-3257,-3268,-3284,-3302,-3324,-3347,-3370,-3394,-3416,-3437,-3456,-3475,-3494,-3514,-3538,-3567,-3600,-3639,
--3681,-3727,-3772,-3815,-3851,-3877,-3892,-3894,-3882,-3859,-3827,-3790,-3752,-3719,-3695,-3683,-3685,-3702,-3732,-3772,-3818,
--3866,-3911,-3950,-3981,-4002,-4014,-4020,-4021,-4023,-4027,-4036,-4053,-4077,-4108,-4143,-4181,-4218,-4252,-4283,-4309,-4332,
--4354,-4377,-4404,-4438,-4481,-4533,-4594,-4664,-4738,-4813,-4886,-4952,-5009,-5053,-5083,-5098,-5100,-5088,-5067,-5039,-5007,
--4975,-4945,-4922,-4906,-4899,-4902,-4914,-4934,-4961,-4993,-5026,-5059,-5089,-5116,-5138,-5156,-5169,-5181,-5191,-5202,-5214,
--5230,-5250,-5273,-5300,-5330,-5362,-5396,-5430,-5465,-5500,-5534,-5566,-5597,-5624,-5647,-5665,-5678,-5685,-5687,-5686,-5682,
--5678,-5677,-5679,-5687,-5701,-5720,-5742,-5766,-5789,-5808,-5821,-5826,-5824,-5816,-5804,-5790,-5776,-5765,-5758,-5756,-5756,
--5757,-5757,-5751,-5738,-5716,-5684,-5643,-5596,-5546,-5497,-5452,-5416,-5392,-5380,-5383,-5398,-5424,-5458,-5497,-5536,-5572,
--5602,-5624,-5634,-5633,-5620,-5595,-5563,-5525,-5486,-5450,-5421,-5403,-5399,-5411,-5437,-5476,-5523,-5573,-5621,-5660,-5685,
--5694,-5685,-5660,-5622,-5575,-5526,-5482,-5448,-5428,-5426,-5441,-5471,-5514,-5564,-5617,-5666,-5708,-5740,-5760,-5769,-5768,
--5759,-5747,-5733,-5723,-5718,-5719,-5729,-5748,-5774,-5808,-5846,-5889,-5933,-5977,-6019,-6058,-6093,-6122,-6145,-6163,-6176,
--6185,-6190,-6193,-6194,-6194,-6193,-6192,-6190,-6187,-6184,-6179,-6174,-6169,-6165,-6161,-6161,-6163,-6169,-6179,-6193,-6210,
--6229,-6249,-6270,-6290,-6310,-6329,-6348,-6368,-6389,-6411,-6436,-6462,-6490,-6518,-6544,-6567,-6586,-6600,-6608,-6609,-6606,
--6599,-6589,-6578,-6568,-6558,-6551,-6547,-6544,-6544,-6544,-6544,-6544,-6542,-6540,-6537,-6534,-6531,-6528,-6525,-6523,-6522,
--6520,-6519,-6516,-6512,-6507,-6501,-6494,-6486,-6478,-6470,-6464,-6458,-6453,-6448,-6443,-6439,-6433,-6426,-6419,-6411,-6402,
--6393,-6384,-6376,-6369,-6363,-6358,-6353,-6349,-6345,-6340,-6334,-6327,-6320,-6312,-6303,-6295,-6287,-6280,-6273,-6267,-6261,
--6255,-6249,-6242,-6234,-6226,-6216,-6206,-6195,-6184,-6172,-6161,-6150,-6138,-6127,-6116,-6105,-6094,-6083,-6073,-6063,-6053,
--6045,-6037,-6029,-6022,-6015,-6008,-6000,-5992,-5983,-5972,-5960,-5947,-5933,-5918,-5901,-5884,-5866,-5847,-5827,-5807,-5786,
--5765,-5745,-5725,-5705,-5687,-5669,-5653,-5638,-5623,-5609,-5596,-5582,-5568,-5554,-5539,-5523,-5507,-5492,-5476,-5460,-5444,
--5428,-5412,-5395,-5377,-5359,-5339,-5318,-5297,-5276,-5255,-5234,-5215,-5198,-5183,-5170,-5157,-5146,-5134,-5122,-5108,-5092,
--5073,-5052,-5028,-5003,-4977,-4951,-4925,-4900,-4877,-4856,-4835,-4816,-4797,-4778,-4758,-4737,-4716,-4693,-4671,-4649,-4628,
--4608,-4590,-4572,-4556,-4539,-4522,-4503,-4483,-4460,-4436,-4410,-4385,-4361,-4340,-4322,-4308,-4298,-4292,-4287,-4283,-4278,
--4270,-4257,-4238,-4215,-4187,-4155,-4122,-4088,-4056,-4025,-3998,-3972,-3947,-3922,-3895,-3864,-3829,-3790,-3747,-3702,-3657,
--3613,-3574,-3541,-3514,-3494,-3479,-3468,-3460,-3451,-3441,-3428,-3411,-3392,-3371,-3350,-3329,-3312,-3298,-3289,-3283,-3279,
--3278,-3276,-3273,-3268,-3260,-3251,-3240,-3228,-3217,-3207,-3200,-3195,-3191,-3187,-3183,-3178,-3169,-3157,-3141,-3122,-3101,
--3079,-3057,-3036,-3017,-3000,-2986,-2974,-2963,-2952,-2940,-2927,-2912,-2894,-2874,-2852,-2829,-2803,-2776,-2747,-2718,-2686,
--2654,-2621,-2587,-2552,-2519,-2486,-2455,-2426,-2400,-2376,-2356,-2337,-2321,-2307,-2294,-2281,-2269,-2258,-2246,-2235,-2223,
--2211,-2198,-2184,-2170,-2156,-2143,-2132,-2123,-2119,-2121,-2129,-2144,-2166,-2192,-2222,-2253,-2281,-2304,-2318,-2321,-2311,
--2288,-2252,-2205,-2150,-2090,-2030,-1971,-1918,-1873,-1837,-1809,-1791,-1779,-1771,-1767,-1762,-1756,-1747,-1734,-1717,-1697,
--1674,-1650,-1627,-1606,-1587,-1572,-1560,-1550,-1543,-1537,-1530,-1522,-1512,-1499,-1484,-1467,-1449,-1432,-1416,-1402,-1391,
--1383,-1378,-1374,-1371,-1368,-1362,-1354,-1342,-1327,-1309,-1289,-1267,-1245,-1223,-1202,-1182,-1163,-1145,-1128,-1110,-1090,
--1069,-1046,-1020,-992,-961,-928,-893,-857,-819,-780,-741,-702,-663,-625,-587,-549,-511,-471,-430,-386,-339,
--288,-234,-179,-122,-67,-14,32,73,106,131,149,161,169,175,182,192,206,226,250,280,313,
-349,385,423,459,494,528,559,586,608,623,630,625,608,576,531,472,403,325,245,164,89,
-23,-32,-75,-107,-127,-140,-146,-150,-154,-158,-164,-171,-179,-187,-192,-195,-195,-191,-184,-175,-166,
--157,-149,-143,-139,-136,-134,-133,-130,-126,-121,-115,-108,-102,-96,-91,-87,-85,-85,-85,-85,-85,
--83,-81,-78,-74,-70,-66,-64,-63,-64,-67,-72,-79,-87,-96,-105,-114,-122,-130,-137,-144,-150,
--155,-161,-165,-170,-174,-177,-180,-184,-187,-191,-195,-201,-207,-214,-222,-229,-237,-243,-248,-252,-255,
--256,-255,-253,-250,-247,-244,-241,-237,-234,-232,-229,-227,-225,-224,-222,-221,-220,-219,-217,-215,-213,
--210,-206,-202,-197,-191,-186,-180,-175,-171,-168,-166,-166,-166,-168,-171,-174,-177,-180,-181,-182,-181,
--178,-174,-169,-163,-156,-149,-142,-135,-130,-126,-124,-122,-122,-122,-123,-124,-124,-124,-123,-121,-119,
--117,-115,-113,-112,-111,-111,-109,-107,-102,-96,-86,-74,-60,-44,-27,-10,5,21,36,50,65,
-82,101,125,154,187,226,270,316,365,414,462,507,549,587,622,653,680,704,724,741,754,
-763,767,768,765,760,755,751,750,755,767,785,809,838,870,902,931,956,975,988,997,1002,
-1007,1015,1030,1052,1085,1127,1177,1232,1289,1345,1394,1434,1463,1480,1485,1481,1468,1451,1433,1415,1399,
-1388,1380,1376,1374,1374,1374,1374,1373,1371,1368,1366,1364,1363,1365,1368,1374,1448,1452,1457,1464,1473,
-1484,1496,1510,1527,1545,1566,1589,1614,1641,1671,1703,1737,1772,1809,1845,1880,1913,1942,1965,1982,1989,
-1988,1978,1958,1930,1896,1859,1821,1785,1754,1730,1715,1710,1715,1728,1747,1770,1795,1819,1840,1856,1868,
-1876,1880,1881,1882,1882,1884,1886,1889,1893,1896,1897,1897,1895,1892,1888,1886,1887,1890,1898,1909,1923,
-1938,1951,1960,1963,1960,1949,1932,1911,1890,1871,1857,1851,1854,1865,1882,1903,1925,1943,1957,1966,1971,
-1974,1980,1994,2022,2066,2128,2208,2302,2403,2503,2593,2664,2709,2722,2702,2652,2576,2483,2382,2283,2195,
-2125,2077,2053,2050,2064,2091,2123,2154,2181,2201,2211,2214,2211,2206,2202,2201,2205,2216,2233,2255,2280,
-2307,2333,2358,2380,2400,2416,2431,2443,2453,2461,2467,2471,2472,2471,2467,2463,2458,2453,2452,2453,2459,
-2469,2483,2500,2519,2538,2554,2568,2576,2579,2577,2569,2558,2542,2524,2504,2482,2458,2432,2402,2370,2334,
-2296,2257,2219,2183,2152,2128,2113,2108,2114,2130,2155,2186,2221,2258,2294,2326,2354,2377,2394,2405,2411,
-2413,2411,2406,2397,2385,2368,2348,2324,2297,2267,2235,2202,2171,2142,2117,2095,2078,2065,2054,2045,2037,
-2027,2017,2004,1991,1977,1963,1951,1941,1935,1932,1932,1934,1938,1941,1944,1944,1943,1940,1936,1933,1932,
-1936,1943,1956,1974,1996,2020,2044,2066,2083,2094,2099,2096,2088,2075,2058,2041,2025,2010,1998,1989,1984,
-1980,1979,1978,1978,1979,1981,1985,1990,1998,2006,2015,2021,2023,2018,2002,1974,1932,1876,1807,1728,1643,
-1557,1474,1400,1337,1289,1256,1238,1233,1238,1249,1264,1279,1294,1307,1318,1328,1339,1352,1369,1389,1413,
-1439,1467,1493,1516,1535,1547,1553,1554,1549,1541,1531,1521,1511,1503,1497,1491,1484,1477,1468,1456,1441,
-1423,1403,1381,1359,1337,1317,1298,1281,1264,1248,1231,1213,1192,1169,1143,1116,1088,1059,1031,1004,979,
-956,934,914,893,872,849,823,795,765,732,698,664,631,600,572,549,529,515,504,496,491,
-487,483,477,469,458,444,426,404,379,351,321,289,256,222,187,153,118,84,50,15,-19,
--54,-91,-129,-169,-210,-253,-298,-344,-390,-437,-483,-528,-571,-613,-652,-690,-727,-765,-802,-842,-884,
--929,-977,-1027,-1079,-1132,-1185,-1237,-1286,-1334,-1378,-1420,-1461,-1501,-1541,-1582,-1625,-1670,-1718,-1767,-1816,-1866,
--1915,-1961,-2006,-2048,-2088,-2128,-2168,-2210,-2255,-2304,-2358,-2416,-2477,-2540,-2603,-2663,-2718,-2766,-2805,-2834,-2854,
--2866,-2870,-2870,-2866,-2863,-2862,-2865,-2872,-2886,-2905,-2928,-2954,-2983,-3012,-3040,-3065,-3088,-3108,-3124,-3138,-3151,
--3162,-3172,-3183,-3194,-3205,-3217,-3228,-3239,-3248,-3256,-3262,-3267,-3270,-3273,-3276,-3281,-3289,-3299,-3313,-3330,-3350,
--3373,-3396,-3421,-3444,-3467,-3489,-3510,-3532,-3555,-3582,-3613,-3650,-3692,-3739,-3789,-3838,-3885,-3925,-3954,-3970,-3972,
--3958,-3931,-3893,-3849,-3804,-3763,-3730,-3711,-3707,-3718,-3745,-3783,-3829,-3878,-3926,-3968,-4003,-4028,-4045,-4054,-4059,
--4062,-4067,-4078,-4094,-4117,-4146,-4180,-4216,-4251,-4284,-4313,-4339,-4361,-4383,-4406,-4434,-4468,-4511,-4564,-4625,-4693,
--4766,-4840,-4910,-4972,-5023,-5061,-5083,-5091,-5084,-5065,-5037,-5003,-4968,-4935,-4906,-4884,-4872,-4869,-4877,-4893,-4917,
--4947,-4981,-5016,-5051,-5083,-5113,-5139,-5161,-5180,-5197,-5213,-5229,-5246,-5265,-5287,-5312,-5339,-5369,-5402,-5436,-5470,
--5505,-5539,-5572,-5602,-5630,-5653,-5672,-5685,-5694,-5698,-5699,-5697,-5695,-5693,-5695,-5701,-5712,-5727,-5747,-5769,-5792,
--5814,-5832,-5844,-5851,-5852,-5847,-5839,-5828,-5818,-5809,-5803,-5800,-5798,-5797,-5794,-5788,-5776,-5756,-5729,-5694,-5654,
--5609,-5564,-5521,-5484,-5454,-5435,-5427,-5430,-5443,-5464,-5491,-5520,-5548,-5571,-5586,-5592,-5586,-5568,-5540,-5504,-5464,
--5423,-5387,-5361,-5348,-5353,-5375,-5415,-5469,-5533,-5601,-5667,-5724,-5767,-5792,-5798,-5784,-5755,-5715,-5670,-5626,-5589,
--5564,-5554,-5560,-5580,-5612,-5651,-5691,-5729,-5761,-5782,-5792,-5791,-5781,-5764,-5744,-5723,-5707,-5697,-5695,-5703,-5721,
--5749,-5784,-5826,-5871,-5918,-5966,-6011,-6052,-6089,-6120,-6146,-6166,-6180,-6189,-6195,-6197,-6197,-6195,-6191,-6187,-6182,
--6176,-6169,-6163,-6157,-6151,-6148,-6147,-6149,-6154,-6164,-6177,-6193,-6212,-6233,-6254,-6276,-6296,-6316,-6334,-6352,-6370,
--6389,-6409,-6431,-6455,-6480,-6505,-6529,-6550,-6568,-6581,-6588,-6590,-6586,-6579,-6569,-6559,-6549,-6541,-6535,-6533,-6534,
--6537,-6541,-6545,-6549,-6552,-6553,-6551,-6549,-6545,-6541,-6536,-6533,-6530,-6528,-6527,-6526,-6525,-6524,-6521,-6518,-6513,
--6507,-6501,-6494,-6486,-6479,-6472,-6465,-6459,-6452,-6445,-6439,-6432,-6425,-6419,-6412,-6406,-6401,-6397,-6393,-6389,-6385,
--6381,-6376,-6370,-6364,-6356,-6348,-6338,-6329,-6320,-6311,-6303,-6296,-6289,-6283,-6277,-6271,-6265,-6257,-6249,-6239,-6228,
--6216,-6203,-6190,-6176,-6163,-6150,-6138,-6127,-6117,-6108,-6101,-6094,-6088,-6082,-6077,-6072,-6066,-6059,-6052,-6043,-6033,
--6021,-6008,-5993,-5976,-5958,-5938,-5917,-5895,-5872,-5848,-5825,-5801,-5779,-5758,-5739,-5722,-5707,-5693,-5681,-5670,-5658,
--5647,-5635,-5622,-5608,-5592,-5576,-5559,-5542,-5526,-5511,-5497,-5483,-5470,-5457,-5443,-5429,-5412,-5393,-5372,-5350,-5327,
--5303,-5280,-5258,-5239,-5222,-5207,-5194,-5182,-5170,-5157,-5142,-5124,-5103,-5079,-5053,-5026,-4998,-4971,-4946,-4925,-4906,
--4890,-4876,-4863,-4851,-4837,-4822,-4803,-4782,-4758,-4731,-4704,-4677,-4651,-4627,-4604,-4584,-4564,-4544,-4523,-4500,-4473,
--4443,-4411,-4376,-4341,-4308,-4279,-4254,-4235,-4223,-4216,-4214,-4214,-4214,-4212,-4205,-4193,-4174,-4148,-4117,-4083,-4046,
--4009,-3972,-3938,-3905,-3874,-3844,-3814,-3782,-3747,-3711,-3672,-3634,-3595,-3560,-3529,-3503,-3484,-3472,-3465,-3463,-3462,
--3462,-3460,-3455,-3447,-3434,-3418,-3400,-3381,-3363,-3347,-3333,-3321,-3312,-3305,-3300,-3294,-3288,-3282,-3275,-3268,-3262,
--3256,-3252,-3249,-3248,-3247,-3245,-3242,-3237,-3228,-3215,-3198,-3177,-3153,-3127,-3100,-3073,-3047,-3023,-3000,-2980,-2961,
--2943,-2926,-2910,-2893,-2876,-2859,-2840,-2819,-2797,-2773,-2746,-2716,-2684,-2649,-2613,-2576,-2540,-2505,-2472,-2444,-2419,
--2399,-2383,-2370,-2359,-2349,-2340,-2329,-2318,-2304,-2290,-2275,-2260,-2245,-2231,-2219,-2208,-2198,-2188,-2179,-2171,-2164,
--2158,-2155,-2156,-2162,-2173,-2191,-2213,-2240,-2268,-2295,-2317,-2331,-2335,-2326,-2303,-2267,-2219,-2163,-2100,-2037,-1976,
--1921,-1875,-1839,-1814,-1797,-1787,-1781,-1777,-1771,-1761,-1747,-1728,-1704,-1677,-1650,-1624,-1601,-1583,-1571,-1563,-1560,
--1559,-1559,-1557,-1552,-1543,-1529,-1511,-1490,-1468,-1446,-1427,-1412,-1401,-1396,-1396,-1398,-1401,-1404,-1403,-1398,-1387,
--1370,-1347,-1320,-1289,-1258,-1226,-1197,-1170,-1148,-1128,-1112,-1098,-1084,-1071,-1056,-1038,-1017,-993,-965,-933,-899,
--863,-826,-789,-751,-715,-680,-645,-610,-574,-537,-497,-454,-407,-356,-302,-246,-189,-135,-84,-38,0,
-30,54,70,82,92,100,110,124,141,163,190,220,253,287,321,353,385,414,441,466,488,
-506,519,525,522,508,482,443,392,329,258,182,104,29,-39,-99,-148,-186,-213,-231,-243,-250,
--254,-259,-265,-271,-279,-286,-292,-295,-295,-291,-283,-272,-259,-245,-231,-218,-207,-199,-192,-186,-180,
--175,-169,-161,-153,-143,-133,-122,-112,-104,-96,-90,-85,-81,-78,-75,-73,-71,-69,-67,-66,-66,
--66,-68,-71,-75,-81,-87,-95,-103,-111,-120,-129,-137,-145,-154,-161,-169,-176,-183,-190,-197,-205,
--213,-221,-230,-239,-249,-259,-269,-278,-287,-295,-302,-307,-311,-314,-315,-315,-315,-314,-313,-311,-309,
--307,-306,-304,-303,-303,-302,-302,-302,-302,-302,-301,-300,-298,-294,-290,-284,-277,-270,-262,-255,-248,
--241,-236,-233,-230,-229,-229,-229,-230,-231,-231,-230,-229,-225,-221,-215,-207,-199,-190,-181,-172,-164,
--157,-152,-148,-145,-144,-144,-145,-146,-146,-147,-147,-146,-145,-144,-142,-140,-139,-137,-134,-130,-124,
--116,-106,-92,-76,-58,-39,-19,0,18,35,51,66,82,99,120,145,176,214,258,307,360,
-415,470,523,572,615,651,681,704,721,733,742,747,750,752,753,753,753,753,753,754,757,
-763,771,783,798,816,835,856,876,896,914,932,949,967,988,1013,1044,1082,1127,1178,1235,1293,
-1352,1406,1454,1493,1521,1537,1541,1536,1522,1503,1481,1459,1440,1424,1413,1407,1405,1407,1411,1417,1422,
-1428,1432,1436,1439,1441,1443,1445,1448,1408,1414,1422,1432,1444,1459,1476,1496,1518,1541,1566,1591,1618,
-1645,1672,1700,1729,1759,1790,1821,1851,1880,1907,1929,1946,1957,1959,1954,1940,1920,1894,1866,1836,1808,
-1785,1768,1757,1755,1760,1771,1787,1805,1823,1841,1856,1868,1877,1884,1889,1894,1899,1905,1912,1920,1927,
-1934,1939,1942,1942,1940,1937,1933,1930,1930,1934,1941,1952,1965,1978,1991,2000,2004,2003,1996,1984,1970,
-1956,1944,1938,1937,1942,1952,1965,1979,1989,1995,1994,1987,1976,1963,1954,1955,1969,2001,2052,2121,2205,
-2297,2392,2478,2549,2598,2620,2612,2577,2519,2445,2363,2280,2206,2147,2105,2082,2076,2085,2104,2127,2149,
-2167,2178,2182,2180,2175,2168,2163,2162,2167,2179,2197,2219,2245,2271,2295,2317,2334,2347,2356,2362,2364,
-2365,2364,2363,2360,2357,2354,2350,2345,2342,2340,2340,2343,2350,2362,2377,2395,2416,2437,2456,2473,2486,
-2493,2495,2492,2483,2470,2454,2435,2415,2392,2369,2344,2317,2290,2261,2232,2203,2176,2152,2132,2118,2110,
-2110,2116,2128,2146,2168,2193,2218,2243,2265,2285,2302,2315,2323,2328,2328,2324,2315,2302,2285,2264,2240,
-2213,2185,2157,2129,2104,2081,2061,2045,2031,2019,2008,1997,1986,1973,1959,1945,1930,1918,1907,1900,1897,
-1897,1900,1905,1911,1916,1918,1917,1913,1907,1900,1893,1889,1890,1898,1913,1935,1963,1995,2028,2060,2086,
-2106,2118,2121,2115,2102,2085,2066,2046,2029,2015,2005,1998,1995,1994,1993,1992,1991,1989,1988,1989,1991,
-1995,2002,2009,2015,2018,2012,1997,1968,1924,1865,1793,1711,1622,1532,1447,1371,1308,1262,1233,1221,1222,
-1235,1255,1279,1304,1326,1346,1362,1377,1391,1405,1422,1441,1462,1484,1506,1526,1541,1551,1555,1552,1543,
-1530,1514,1497,1481,1467,1456,1448,1441,1435,1428,1418,1405,1388,1368,1346,1321,1297,1274,1253,1234,1219,
-1205,1193,1180,1166,1149,1130,1107,1081,1053,1024,996,969,944,921,900,881,862,842,820,796,768,
-737,704,669,634,601,571,545,525,509,499,492,488,486,482,477,469,456,439,417,391,362,
-331,298,265,231,198,167,136,106,78,50,22,-6,-35,-66,-100,-135,-174,-216,-261,-309,-358,
--409,-460,-510,-558,-604,-646,-685,-721,-755,-789,-822,-857,-894,-935,-979,-1026,-1076,-1128,-1180,-1232,-1283,
--1331,-1376,-1419,-1461,-1501,-1541,-1582,-1625,-1669,-1714,-1761,-1809,-1856,-1903,-1948,-1991,-2033,-2075,-2116,-2160,-2206,
--2256,-2311,-2370,-2433,-2498,-2564,-2629,-2690,-2744,-2791,-2828,-2855,-2872,-2881,-2882,-2879,-2872,-2866,-2861,-2860,-2864,
--2873,-2888,-2908,-2933,-2960,-2988,-3016,-3043,-3068,-3089,-3108,-3124,-3137,-3149,-3161,-3172,-3184,-3197,-3211,-3225,-3239,
--3253,-3266,-3277,-3286,-3294,-3300,-3306,-3312,-3320,-3330,-3344,-3361,-3382,-3406,-3432,-3459,-3486,-3512,-3537,-3560,-3582,
--3604,-3628,-3655,-3687,-3723,-3764,-3809,-3856,-3902,-3942,-3975,-3996,-4003,-3996,-3976,-3944,-3904,-3861,-3820,-3786,-3764,
--3756,-3764,-3788,-3824,-3871,-3924,-3977,-4028,-4072,-4108,-4134,-4151,-4162,-4168,-4173,-4178,-4187,-4199,-4216,-4237,-4260,
--4285,-4310,-4334,-4358,-4381,-4405,-4432,-4463,-4501,-4546,-4598,-4656,-4719,-4784,-4847,-4906,-4957,-4998,-5026,-5042,-5045,
--5037,-5020,-4997,-4970,-4944,-4920,-4901,-4889,-4884,-4887,-4898,-4915,-4938,-4964,-4994,-5024,-5055,-5085,-5113,-5140,-5165,
--5188,-5211,-5233,-5256,-5279,-5303,-5329,-5356,-5385,-5415,-5446,-5477,-5508,-5539,-5569,-5597,-5623,-5646,-5666,-5681,-5693,
--5701,-5706,-5708,-5709,-5710,-5711,-5715,-5721,-5730,-5742,-5757,-5773,-5790,-5805,-5819,-5829,-5835,-5838,-5839,-5836,-5833,
--5830,-5827,-5824,-5823,-5821,-5818,-5812,-5802,-5787,-5767,-5739,-5706,-5669,-5628,-5585,-5544,-5506,-5474,-5448,-5430,-5420,
--5417,-5421,-5429,-5439,-5448,-5455,-5456,-5451,-5438,-5416,-5389,-5357,-5323,-5294,-5271,-5260,-5264,-5284,-5323,-5377,-5445,
--5521,-5601,-5676,-5743,-5795,-5830,-5845,-5841,-5822,-5791,-5753,-5714,-5681,-5656,-5643,-5643,-5655,-5677,-5705,-5736,-5765,
--5789,-5806,-5814,-5814,-5806,-5794,-5779,-5764,-5753,-5748,-5749,-5758,-5774,-5798,-5827,-5860,-5896,-5933,-5970,-6004,-6036,
--6064,-6088,-6108,-6123,-6135,-6143,-6148,-6151,-6151,-6149,-6147,-6143,-6139,-6135,-6131,-6128,-6126,-6126,-6129,-6134,-6142,
--6154,-6169,-6187,-6207,-6229,-6252,-6274,-6296,-6317,-6336,-6353,-6370,-6386,-6403,-6420,-6439,-6459,-6480,-6502,-6522,-6541,
--6557,-6569,-6577,-6581,-6581,-6577,-6572,-6565,-6559,-6554,-6551,-6550,-6551,-6553,-6556,-6559,-6562,-6562,-6561,-6558,-6554,
--6550,-6545,-6540,-6537,-6535,-6534,-6534,-6534,-6535,-6535,-6533,-6531,-6526,-6521,-6514,-6506,-6499,-6491,-6484,-6478,-6473,
--6468,-6464,-6459,-6455,-6450,-6445,-6440,-6434,-6428,-6423,-6418,-6413,-6408,-6404,-6399,-6393,-6387,-6380,-6372,-6364,-6355,
--6345,-6336,-6327,-6319,-6311,-6304,-6298,-6292,-6286,-6279,-6272,-6264,-6254,-6244,-6232,-6220,-6208,-6196,-6184,-6173,-6163,
--6154,-6146,-6138,-6131,-6124,-6117,-6109,-6101,-6092,-6082,-6072,-6060,-6047,-6033,-6018,-6002,-5984,-5965,-5944,-5922,-5899,
--5875,-5851,-5828,-5806,-5785,-5766,-5750,-5736,-5725,-5714,-5705,-5695,-5685,-5673,-5659,-5644,-5626,-5608,-5588,-5569,-5551,
--5535,-5520,-5508,-5497,-5487,-5476,-5465,-5452,-5437,-5418,-5398,-5374,-5350,-5325,-5301,-5279,-5259,-5241,-5225,-5212,-5199,
--5186,-5171,-5154,-5134,-5112,-5087,-5061,-5034,-5009,-4985,-4965,-4947,-4933,-4921,-4910,-4899,-4886,-4870,-4849,-4824,-4795,
--4763,-4728,-4693,-4659,-4627,-4598,-4572,-4550,-4528,-4507,-4485,-4459,-4430,-4396,-4358,-4317,-4275,-4235,-4198,-4166,-4141,
--4124,-4114,-4110,-4111,-4113,-4114,-4112,-4105,-4092,-4072,-4046,-4015,-3981,-3945,-3910,-3876,-3845,-3815,-3788,-3762,-3736,
--3710,-3683,-3655,-3626,-3598,-3572,-3547,-3527,-3511,-3500,-3493,-3490,-3489,-3488,-3488,-3485,-3479,-3471,-3460,-3446,-3431,
--3415,-3399,-3384,-3370,-3359,-3349,-3340,-3333,-3327,-3321,-3316,-3311,-3307,-3303,-3299,-3296,-3292,-3287,-3281,-3273,-3264,
--3252,-3238,-3222,-3204,-3185,-3165,-3144,-3123,-3101,-3079,-3055,-3032,-3007,-2983,-2958,-2933,-2908,-2884,-2861,-2838,-2815,
--2792,-2768,-2743,-2715,-2684,-2652,-2617,-2583,-2549,-2517,-2489,-2466,-2448,-2435,-2425,-2419,-2413,-2407,-2398,-2387,-2372,
--2354,-2334,-2312,-2292,-2273,-2258,-2247,-2239,-2234,-2230,-2227,-2222,-2216,-2208,-2198,-2187,-2178,-2171,-2169,-2172,-2181,
--2195,-2211,-2228,-2242,-2250,-2248,-2235,-2210,-2173,-2125,-2071,-2014,-1958,-1906,-1862,-1829,-1806,-1793,-1787,-1787,-1788,
--1789,-1785,-1777,-1762,-1742,-1718,-1693,-1668,-1647,-1630,-1619,-1614,-1613,-1614,-1616,-1616,-1613,-1604,-1590,-1572,-1550,
--1526,-1503,-1483,-1466,-1454,-1448,-1445,-1445,-1446,-1446,-1442,-1434,-1420,-1400,-1374,-1345,-1313,-1280,-1249,-1220,-1194,
--1173,-1155,-1139,-1126,-1114,-1100,-1085,-1068,-1047,-1023,-996,-967,-936,-903,-871,-839,-808,-777,-746,-716,-684,
--651,-615,-575,-532,-485,-435,-383,-330,-277,-227,-181,-140,-106,-77,-55,-36,-20,-5,10,29,51,
-77,107,140,173,206,238,267,292,314,332,348,361,372,381,387,389,385,373,352,320,277,
-224,162,93,22,-49,-115,-176,-226,-267,-297,-317,-331,-338,-343,-347,-351,-356,-363,-370,-377,-382,
--385,-384,-378,-369,-356,-340,-324,-307,-292,-277,-265,-255,-245,-237,-228,-219,-209,-198,-185,-173,-160,
--148,-137,-128,-120,-114,-110,-107,-105,-103,-101,-99,-96,-94,-92,-91,-90,-91,-93,-97,-103,-109,
--117,-125,-134,-142,-151,-159,-166,-174,-182,-190,-199,-209,-220,-231,-244,-257,-270,-283,-295,-307,-317,
--327,-335,-343,-349,-355,-360,-364,-369,-373,-376,-380,-382,-384,-386,-387,-387,-387,-387,-386,-385,-384,
--383,-381,-378,-374,-369,-363,-356,-348,-339,-329,-319,-309,-300,-291,-283,-277,-272,-267,-263,-260,-258,
--255,-252,-248,-244,-240,-234,-228,-221,-214,-206,-198,-190,-182,-176,-171,-167,-164,-164,-164,-166,-168,
--171,-173,-175,-175,-174,-172,-168,-163,-156,-148,-139,-127,-114,-100,-83,-64,-44,-23,-2,18,38,
-56,73,89,104,119,137,157,183,215,252,296,346,399,455,509,561,608,648,680,704,720,
-729,733,734,733,732,732,734,738,744,751,758,766,774,780,786,791,796,801,806,813,821,
-832,846,864,886,914,946,985,1029,1078,1133,1190,1249,1308,1365,1416,1460,1496,1521,1535,1540,1534,
-1521,1501,1478,1453,1428,1406,1387,1373,1364,1359,1357,1359,1364,1369,1376,1382,1387,1393,1398,1402,1408,
-1310,1326,1343,1363,1384,1407,1431,1457,1483,1510,1536,1561,1586,1609,1632,1654,1675,1697,1720,1742,1765,
-1788,1809,1828,1843,1854,1859,1859,1853,1842,1828,1812,1796,1781,1770,1763,1761,1763,1770,1779,1791,1802,
-1813,1822,1829,1835,1840,1845,1850,1857,1867,1878,1891,1905,1918,1929,1936,1940,1940,1937,1931,1924,1919,
-1917,1919,1925,1936,1950,1966,1982,1997,2007,2013,2014,2010,2003,1994,1987,1981,1978,1979,1982,1986,1989,
-1989,1984,1974,1957,1937,1916,1898,1886,1886,1899,1927,1970,2026,2089,2155,2218,2271,2309,2330,2332,2315,
-2284,2242,2196,2150,2110,2079,2059,2051,2051,2059,2070,2080,2087,2088,2084,2075,2062,2049,2037,2030,2029,
-2035,2047,2066,2088,2111,2133,2152,2166,2175,2179,2179,2175,2169,2163,2157,2152,2148,2146,2145,2145,2145,
-2147,2150,2155,2162,2172,2186,2204,2224,2247,2272,2295,2317,2336,2350,2358,2361,2358,2351,2339,2325,2308,
-2291,2273,2254,2236,2218,2201,2183,2166,2150,2136,2122,2112,2103,2098,2096,2097,2100,2105,2112,2120,2127,
-2135,2142,2148,2153,2156,2159,2160,2159,2156,2152,2145,2136,2125,2112,2098,2083,2068,2052,2038,2024,2010,
-1997,1985,1972,1958,1945,1931,1918,1906,1896,1889,1885,1884,1887,1891,1897,1903,1906,1907,1904,1898,1889,
-1878,1869,1864,1863,1871,1887,1912,1944,1983,2023,2064,2100,2129,2148,2158,2156,2146,2129,2108,2086,2065,
-2049,2036,2029,2027,2027,2030,2032,2033,2032,2029,2025,2021,2017,2014,2013,2012,2010,2004,1992,1970,1937,
-1891,1832,1761,1681,1595,1510,1428,1356,1296,1252,1224,1212,1215,1229,1251,1278,1308,1338,1366,1393,1419,
-1443,1468,1491,1515,1536,1555,1570,1578,1579,1571,1556,1533,1504,1473,1440,1410,1384,1362,1347,1336,1329,
-1324,1319,1311,1300,1285,1266,1244,1220,1195,1172,1151,1134,1120,1109,1100,1092,1083,1071,1057,1040,1019,
-996,972,948,924,903,883,866,849,832,814,793,769,741,710,675,640,604,571,542,518,499,
-486,479,475,473,471,467,460,447,429,405,375,341,303,263,223,183,145,109,76,47,20,
--4,-26,-48,-71,-94,-119,-147,-179,-215,-255,-299,-346,-396,-448,-500,-551,-600,-646,-687,-725,-759,
--791,-820,-849,-880,-912,-948,-987,-1029,-1075,-1123,-1172,-1221,-1270,-1317,-1363,-1406,-1449,-1491,-1533,-1575,-1618,
--1661,-1706,-1751,-1796,-1839,-1882,-1923,-1962,-2001,-2040,-2080,-2122,-2168,-2218,-2273,-2333,-2396,-2462,-2529,-2594,-2655,
--2711,-2759,-2798,-2828,-2849,-2861,-2866,-2866,-2862,-2857,-2852,-2849,-2850,-2854,-2864,-2878,-2896,-2917,-2941,-2965,-2989,
--3012,-3033,-3052,-3069,-3084,-3097,-3111,-3125,-3140,-3156,-3174,-3194,-3215,-3236,-3258,-3278,-3296,-3313,-3328,-3341,-3354,
--3368,-3383,-3402,-3423,-3447,-3475,-3505,-3536,-3567,-3596,-3622,-3646,-3667,-3687,-3706,-3726,-3749,-3776,-3808,-3844,-3883,
--3922,-3960,-3992,-4016,-4029,-4029,-4017,-3993,-3961,-3925,-3888,-3858,-3837,-3829,-3838,-3863,-3903,-3955,-4017,-4082,-4146,
--4206,-4257,-4296,-4324,-4341,-4348,-4347,-4340,-4332,-4324,-4317,-4314,-4316,-4322,-4333,-4349,-4369,-4393,-4422,-4456,-4495,
--4538,-4586,-4637,-4690,-4742,-4793,-4840,-4881,-4914,-4939,-4954,-4961,-4961,-4954,-4944,-4931,-4919,-4908,-4901,-4897,-4899,
--4905,-4916,-4930,-4948,-4968,-4990,-5013,-5038,-5063,-5089,-5115,-5141,-5168,-5196,-5225,-5253,-5283,-5312,-5342,-5372,-5402,
--5431,-5461,-5489,-5518,-5545,-5571,-5596,-5619,-5641,-5661,-5678,-5693,-5705,-5715,-5722,-5728,-5732,-5735,-5738,-5742,-5746,
--5751,-5758,-5765,-5774,-5783,-5792,-5801,-5810,-5818,-5826,-5833,-5840,-5846,-5851,-5856,-5859,-5860,-5858,-5853,-5844,-5830,
--5812,-5788,-5761,-5729,-5694,-5657,-5618,-5579,-5541,-5504,-5470,-5437,-5406,-5378,-5351,-5325,-5300,-5275,-5249,-5222,-5194,
--5165,-5138,-5113,-5092,-5078,-5073,-5080,-5101,-5138,-5189,-5255,-5333,-5418,-5507,-5594,-5675,-5743,-5797,-5832,-5850,-5851,
--5837,-5813,-5783,-5752,-5724,-5703,-5691,-5689,-5697,-5712,-5732,-5755,-5777,-5797,-5812,-5821,-5826,-5827,-5825,-5821,-5819,
--5819,-5823,-5830,-5842,-5857,-5876,-5897,-5919,-5941,-5963,-5983,-6002,-6018,-6033,-6045,-6055,-6063,-6070,-6074,-6077,-6079,
--6081,-6082,-6082,-6084,-6086,-6089,-6093,-6100,-6108,-6119,-6132,-6147,-6163,-6182,-6203,-6224,-6246,-6268,-6289,-6309,-6329,
--6347,-6363,-6379,-6393,-6407,-6422,-6436,-6452,-6467,-6484,-6500,-6516,-6531,-6544,-6555,-6563,-6569,-6572,-6573,-6574,-6573,
--6572,-6572,-6572,-6573,-6574,-6576,-6576,-6576,-6575,-6572,-6568,-6563,-6557,-6552,-6547,-6543,-6541,-6539,-6539,-6540,-6540,
--6540,-6539,-6537,-6533,-6527,-6521,-6514,-6506,-6499,-6493,-6489,-6485,-6482,-6480,-6478,-6475,-6472,-6468,-6462,-6455,-6448,
--6440,-6432,-6424,-6417,-6411,-6406,-6402,-6398,-6394,-6389,-6384,-6379,-6372,-6364,-6356,-6347,-6339,-6330,-6322,-6314,-6307,
--6300,-6293,-6286,-6279,-6272,-6264,-6255,-6246,-6237,-6227,-6217,-6208,-6198,-6189,-6179,-6169,-6159,-6148,-6137,-6125,-6112,
--6099,-6085,-6071,-6057,-6042,-6027,-6012,-5995,-5978,-5960,-5941,-5921,-5900,-5879,-5857,-5837,-5818,-5801,-5785,-5772,-5760,
--5750,-5740,-5730,-5720,-5707,-5693,-5676,-5657,-5637,-5616,-5595,-5576,-5558,-5543,-5531,-5521,-5512,-5505,-5498,-5489,-5477,
--5463,-5445,-5425,-5401,-5376,-5350,-5324,-5299,-5277,-5257,-5238,-5222,-5207,-5192,-5177,-5161,-5144,-5125,-5105,-5085,-5065,
--5045,-5027,-5010,-4994,-4978,-4962,-4944,-4923,-4899,-4870,-4836,-4799,-4759,-4717,-4675,-4635,-4598,-4565,-4536,-4511,-4488,
--4467,-4445,-4420,-4392,-4358,-4320,-4276,-4230,-4182,-4136,-4094,-4058,-4029,-4009,-3997,-3992,-3993,-3997,-4001,-4004,-4002,
--3996,-3984,-3966,-3944,-3918,-3891,-3864,-3839,-3816,-3795,-3777,-3761,-3746,-3732,-3716,-3700,-3682,-3663,-3644,-3624,-3606,
--3589,-3575,-3563,-3554,-3548,-3543,-3540,-3537,-3533,-3529,-3522,-3514,-3505,-3493,-3481,-3467,-3454,-3440,-3427,-3414,-3403,
--3392,-3382,-3373,-3364,-3356,-3347,-3337,-3326,-3314,-3301,-3286,-3270,-3253,-3237,-3221,-3207,-3193,-3181,-3170,-3159,-3148,
--3136,-3121,-3103,-3081,-3056,-3028,-2997,-2965,-2933,-2902,-2872,-2844,-2818,-2792,-2768,-2742,-2715,-2687,-2657,-2626,-2594,
--2564,-2536,-2513,-2493,-2479,-2470,-2464,-2459,-2454,-2447,-2436,-2420,-2400,-2375,-2347,-2320,-2293,-2271,-2255,-2244,-2240,
--2240,-2243,-2246,-2248,-2245,-2237,-2224,-2205,-2183,-2160,-2138,-2120,-2106,-2099,-2096,-2097,-2099,-2100,-2096,-2085,-2066,
--2038,-2003,-1962,-1920,-1878,-1842,-1812,-1792,-1783,-1782,-1789,-1800,-1812,-1823,-1829,-1828,-1821,-1808,-1789,-1768,-1746,
--1726,-1710,-1699,-1693,-1691,-1691,-1693,-1693,-1691,-1685,-1674,-1659,-1641,-1621,-1601,-1582,-1566,-1552,-1541,-1533,-1525,
--1516,-1506,-1493,-1476,-1454,-1429,-1402,-1373,-1343,-1316,-1290,-1268,-1248,-1232,-1217,-1203,-1189,-1174,-1157,-1138,-1116,
--1091,-1066,-1039,-1011,-985,-959,-934,-909,-886,-862,-837,-811,-782,-749,-713,-673,-628,-581,-532,-482,-432,
--384,-340,-299,-263,-231,-203,-179,-156,-133,-110,-84,-55,-24,9,45,80,115,147,175,198,217,
-231,242,250,256,261,265,267,265,259,246,225,193,151,99,38,-29,-100,-171,-238,-298,-349,
--388,-417,-434,-443,-445,-443,-440,-437,-436,-438,-442,-447,-452,-457,-458,-457,-451,-441,-428,-413,-396,
--378,-361,-346,-331,-318,-306,-295,-283,-272,-259,-247,-234,-221,-209,-199,-190,-182,-176,-172,-168,-165,
--161,-157,-152,-147,-141,-135,-130,-127,-125,-125,-127,-132,-138,-145,-153,-160,-168,-174,-180,-186,-191,
--197,-204,-212,-222,-234,-248,-263,-278,-294,-309,-324,-337,-348,-358,-367,-375,-383,-390,-398,-406,-414,
--423,-431,-439,-446,-452,-456,-459,-461,-461,-459,-457,-454,-450,-445,-439,-432,-424,-416,-405,-394,-382,
--370,-357,-344,-331,-319,-308,-298,-290,-282,-275,-268,-262,-256,-251,-246,-241,-236,-232,-227,-223,-218,
--214,-209,-203,-198,-193,-188,-184,-182,-180,-181,-183,-187,-191,-196,-200,-203,-204,-203,-198,-191,-181,
--167,-151,-133,-113,-92,-69,-46,-22,1,25,48,71,92,112,132,151,169,188,208,230,256,
-286,319,357,398,442,486,529,569,604,633,656,671,680,684,685,683,682,682,684,690,698,
-709,722,734,746,756,762,765,766,764,761,758,757,759,766,779,799,826,860,901,948,999,
-1054,1110,1167,1223,1276,1326,1369,1406,1436,1457,1470,1474,1470,1459,1442,1420,1394,1367,1339,1313,1290,
-1270,1254,1243,1237,1234,1236,1241,1248,1258,1269,1281,1295,1310,1237,1263,1291,1320,1350,1380,1411,1441,
-1470,1497,1523,1546,1567,1586,1603,1619,1634,1649,1664,1679,1695,1711,1726,1740,1751,1760,1764,1766,1764,
-1760,1754,1747,1742,1738,1738,1741,1747,1757,1768,1780,1792,1802,1811,1817,1822,1826,1829,1834,1840,1849,
-1860,1875,1890,1906,1921,1932,1940,1944,1942,1937,1930,1921,1914,1910,1911,1917,1929,1945,1965,1986,2005,
-2022,2035,2042,2043,2040,2032,2023,2012,2002,1992,1984,1976,1968,1958,1945,1930,1913,1893,1874,1856,1843,
-1836,1838,1849,1868,1895,1927,1961,1993,2021,2042,2054,2058,2055,2046,2033,2021,2011,2006,2005,2009,2017,
-2025,2032,2036,2034,2025,2010,1989,1965,1940,1918,1900,1890,1887,1893,1907,1925,1946,1967,1985,1999,2007,
-2009,2005,1998,1987,1975,1964,1954,1947,1942,1939,1939,1940,1943,1946,1952,1959,1968,1981,1998,2019,2043,
-2070,2099,2129,2157,2183,2204,2219,2229,2233,2231,2224,2214,2202,2188,2175,2162,2150,2140,2131,2123,2116,
-2110,2104,2098,2092,2087,2081,2074,2068,2061,2054,2047,2039,2031,2023,2015,2008,2002,1997,1994,1993,1994,
-1996,1999,2003,2006,2008,2009,2009,2006,2002,1995,1986,1976,1964,1950,1936,1922,1908,1895,1883,1874,1867,
-1863,1862,1864,1869,1875,1880,1885,1887,1887,1882,1875,1865,1854,1844,1838,1837,1845,1861,1886,1920,1961,
-2006,2052,2095,2132,2160,2178,2184,2181,2169,2150,2129,2107,2088,2073,2063,2059,2059,2062,2067,2071,2073,
-2072,2069,2062,2054,2045,2035,2025,2015,2003,1988,1968,1940,1904,1857,1800,1734,1661,1583,1506,1432,1366,
-1311,1268,1239,1225,1224,1234,1254,1282,1314,1350,1388,1427,1467,1506,1544,1579,1610,1635,1653,1660,1657,
-1642,1615,1578,1533,1482,1430,1379,1332,1292,1260,1237,1221,1211,1205,1200,1193,1185,1172,1155,1135,1113,
-1091,1069,1050,1035,1022,1013,1006,1000,994,986,975,961,945,927,907,887,868,851,835,820,805,
-790,773,753,729,701,669,635,599,563,529,500,476,457,444,436,432,429,426,420,410,395,
-373,346,312,273,231,187,142,98,57,18,-16,-47,-74,-99,-121,-141,-162,-183,-206,-231,-260,
--293,-330,-371,-415,-462,-511,-560,-608,-654,-697,-736,-772,-805,-835,-863,-891,-919,-950,-983,-1019,-1057,
--1099,-1142,-1187,-1233,-1278,-1323,-1367,-1411,-1455,-1498,-1543,-1588,-1633,-1679,-1725,-1771,-1815,-1858,-1898,-1936,-1973,
--2008,-2043,-2079,-2117,-2159,-2205,-2256,-2312,-2372,-2434,-2498,-2561,-2621,-2677,-2726,-2769,-2803,-2830,-2848,-2860,-2866,
--2868,-2866,-2864,-2861,-2860,-2862,-2866,-2874,-2886,-2900,-2917,-2936,-2956,-2975,-2994,-3012,-3028,-3043,-3057,-3071,-3086,
--3102,-3120,-3140,-3163,-3189,-3217,-3246,-3275,-3304,-3332,-3358,-3383,-3407,-3430,-3454,-3479,-3505,-3534,-3565,-3597,-3629,
--3661,-3691,-3719,-3743,-3764,-3783,-3799,-3816,-3834,-3855,-3880,-3908,-3940,-3972,-4004,-4033,-4055,-4068,-4070,-4061,-4042,
--4014,-3982,-3950,-3922,-3903,-3898,-3908,-3936,-3981,-4040,-4111,-4189,-4267,-4342,-4408,-4461,-4499,-4522,-4529,-4521,-4503,
--4477,-4447,-4417,-4390,-4369,-4356,-4352,-4358,-4375,-4401,-4435,-4477,-4524,-4574,-4625,-4676,-4724,-4767,-4804,-4835,-4858,
--4874,-4883,-4886,-4885,-4881,-4877,-4873,-4870,-4871,-4875,-4883,-4894,-4907,-4923,-4941,-4959,-4978,-4996,-5015,-5034,-5054,
--5075,-5097,-5121,-5147,-5175,-5205,-5237,-5270,-5304,-5338,-5372,-5406,-5438,-5469,-5499,-5527,-5554,-5579,-5603,-5626,-5647,
--5666,-5684,-5700,-5715,-5728,-5740,-5750,-5758,-5764,-5770,-5774,-5777,-5779,-5781,-5784,-5787,-5791,-5797,-5804,-5813,-5824,
--5836,-5850,-5864,-5879,-5893,-5904,-5913,-5919,-5920,-5916,-5908,-5895,-5878,-5857,-5833,-5808,-5780,-5752,-5723,-5692,-5660,
--5625,-5586,-5544,-5497,-5445,-5387,-5325,-5259,-5190,-5121,-5053,-4989,-4931,-4882,-4844,-4820,-4811,-4819,-4844,-4887,-4947,
--5023,-5112,-5210,-5315,-5420,-5522,-5616,-5698,-5765,-5815,-5847,-5862,-5862,-5850,-5830,-5805,-5780,-5758,-5741,-5732,-5729,
--5734,-5743,-5757,-5773,-5788,-5803,-5815,-5825,-5832,-5838,-5843,-5848,-5855,-5863,-5874,-5886,-5900,-5914,-5929,-5943,-5957,
--5968,-5978,-5987,-5993,-5999,-6003,-6007,-6009,-6012,-6014,-6015,-6017,-6019,-6022,-6026,-6032,-6039,-6049,-6061,-6076,-6093,
--6113,-6134,-6157,-6180,-6204,-6227,-6250,-6272,-6292,-6312,-6329,-6346,-6362,-6376,-6390,-6403,-6416,-6428,-6440,-6452,-6463,
--6474,-6484,-6494,-6503,-6511,-6519,-6526,-6532,-6539,-6545,-6552,-6558,-6565,-6572,-6579,-6585,-6590,-6594,-6597,-6597,-6595,
--6591,-6586,-6580,-6573,-6567,-6561,-6557,-6554,-6552,-6552,-6553,-6554,-6554,-6553,-6550,-6546,-6540,-6532,-6523,-6515,-6506,
--6499,-6493,-6488,-6485,-6483,-6482,-6481,-6479,-6476,-6472,-6465,-6457,-6448,-6439,-6429,-6420,-6413,-6406,-6402,-6399,-6397,
--6396,-6395,-6394,-6391,-6388,-6383,-6376,-6368,-6360,-6350,-6341,-6332,-6323,-6314,-6307,-6299,-6291,-6284,-6276,-6268,-6260,
--6251,-6242,-6232,-6222,-6211,-6201,-6190,-6179,-6167,-6155,-6143,-6130,-6117,-6103,-6089,-6074,-6059,-6043,-6026,-6009,-5990,
--5971,-5952,-5931,-5910,-5890,-5870,-5851,-5834,-5818,-5805,-5793,-5783,-5773,-5765,-5756,-5746,-5734,-5720,-5705,-5687,-5668,
--5648,-5628,-5609,-5592,-5577,-5565,-5555,-5547,-5540,-5534,-5526,-5517,-5504,-5489,-5470,-5447,-5422,-5394,-5365,-5337,-5309,
--5282,-5258,-5236,-5217,-5199,-5184,-5171,-5158,-5146,-5135,-5124,-5112,-5100,-5087,-5071,-5054,-5033,-5008,-4979,-4945,-4907,
--4864,-4818,-4769,-4720,-4672,-4626,-4584,-4548,-4516,-4489,-4467,-4447,-4428,-4408,-4384,-4356,-4322,-4282,-4236,-4187,-4135,
--4084,-4035,-3992,-3956,-3928,-3908,-3897,-3893,-3894,-3898,-3903,-3907,-3908,-3904,-3897,-3885,-3870,-3852,-3834,-3817,-3801,
--3788,-3777,-3769,-3764,-3759,-3755,-3750,-3744,-3736,-3725,-3713,-3699,-3685,-3670,-3656,-3645,-3635,-3628,-3623,-3620,-3619,
--3619,-3618,-3617,-3614,-3608,-3600,-3588,-3574,-3557,-3538,-3517,-3496,-3475,-3455,-3436,-3417,-3400,-3382,-3365,-3348,-3329,
--3309,-3289,-3267,-3245,-3224,-3204,-3187,-3173,-3161,-3153,-3147,-3142,-3137,-3130,-3120,-3105,-3086,-3063,-3035,-3003,-2970,
--2937,-2904,-2873,-2844,-2818,-2794,-2770,-2747,-2722,-2696,-2669,-2640,-2610,-2581,-2555,-2532,-2513,-2498,-2488,-2480,-2473,
--2465,-2454,-2438,-2417,-2391,-2360,-2326,-2293,-2262,-2235,-2215,-2202,-2197,-2198,-2203,-2209,-2213,-2213,-2207,-2194,-2173,
--2147,-2116,-2085,-2054,-2026,-2003,-1986,-1972,-1963,-1954,-1945,-1933,-1917,-1897,-1873,-1847,-1821,-1797,-1778,-1765,-1761,
--1764,-1774,-1789,-1806,-1823,-1836,-1844,-1844,-1838,-1825,-1807,-1786,-1765,-1746,-1731,-1721,-1716,-1716,-1719,-1724,-1729,
--1733,-1734,-1732,-1727,-1718,-1707,-1695,-1681,-1668,-1653,-1638,-1622,-1605,-1584,-1561,-1534,-1505,-1474,-1442,-1411,-1381,
--1355,-1332,-1313,-1298,-1285,-1275,-1265,-1254,-1241,-1225,-1206,-1184,-1160,-1134,-1108,-1083,-1059,-1037,-1018,-999,-982,
--964,-945,-924,-899,-870,-836,-799,-757,-713,-667,-621,-575,-530,-488,-449,-413,-380,-349,-320,-291,-262,
--232,-201,-167,-132,-96,-59,-24,9,40,67,90,109,125,137,148,158,166,174,181,185,185,
-179,165,140,104,56,-1,-68,-142,-219,-295,-365,-428,-479,-518,-545,-559,-564,-560,-552,-541,-532,
--524,-519,-518,-519,-522,-525,-527,-526,-522,-515,-504,-491,-475,-458,-441,-424,-409,-394,-380,-366,-353,
--340,-326,-313,-300,-288,-276,-266,-258,-251,-245,-241,-236,-232,-227,-221,-214,-206,-198,-191,-184,-178,
--175,-175,-177,-181,-186,-193,-200,-206,-211,-215,-218,-221,-223,-226,-230,-237,-245,-256,-269,-284,-300,
--317,-332,-347,-360,-372,-382,-391,-399,-407,-416,-425,-434,-445,-455,-465,-475,-483,-489,-493,-496,-496,
--494,-491,-486,-481,-474,-467,-459,-449,-439,-427,-413,-399,-383,-367,-350,-334,-319,-304,-291,-278,-267,
--257,-249,-240,-233,-226,-220,-214,-210,-206,-203,-201,-200,-199,-198,-197,-195,-194,-192,-190,-189,-188,
--188,-190,-194,-199,-204,-210,-216,-219,-220,-217,-211,-200,-185,-166,-143,-119,-93,-66,-38,-12,13,
-39,64,88,112,136,160,185,209,234,260,285,311,338,364,391,418,444,470,494,516,535,
-551,564,573,579,582,584,586,588,591,597,606,619,633,649,666,682,695,706,712,715,714,
-711,707,703,703,706,715,732,755,787,825,869,917,968,1021,1073,1124,1172,1217,1257,1292,1322,
-1347,1365,1379,1386,1387,1382,1371,1355,1334,1309,1282,1254,1227,1201,1178,1159,1146,1137,1134,1137,1144,
-1156,1172,1191,1213,1237,1199,1225,1253,1283,1314,1347,1380,1412,1443,1472,1499,1523,1544,1562,1577,1591,
-1603,1615,1626,1637,1649,1660,1671,1681,1689,1696,1700,1701,1701,1699,1697,1696,1696,1698,1704,1713,1725,
-1739,1754,1769,1784,1797,1808,1816,1822,1827,1832,1837,1844,1853,1865,1878,1893,1907,1921,1932,1939,1943,
-1942,1938,1932,1926,1920,1918,1920,1927,1939,1956,1977,1999,2020,2040,2055,2066,2070,2069,2063,2052,2038,
-2022,2005,1988,1971,1954,1938,1922,1906,1891,1876,1863,1852,1844,1840,1840,1844,1852,1863,1875,1888,1900,
-1909,1917,1921,1925,1927,1931,1936,1945,1956,1972,1989,2006,2022,2033,2039,2036,2025,2006,1980,1949,1916,
-1885,1858,1838,1826,1824,1830,1842,1860,1880,1899,1915,1926,1932,1932,1926,1917,1905,1892,1879,1868,1858,
-1850,1845,1840,1838,1836,1835,1836,1839,1846,1857,1872,1892,1916,1945,1976,2009,2041,2070,2095,2114,2128,
-2135,2137,2133,2126,2116,2105,2095,2086,2078,2073,2069,2067,2066,2065,2064,2063,2060,2056,2050,2042,2033,
-2022,2010,1996,1981,1966,1951,1936,1923,1912,1903,1897,1895,1895,1898,1904,1911,1919,1927,1933,1937,1938,
-1936,1931,1923,1912,1900,1886,1871,1857,1844,1833,1824,1819,1816,1816,1818,1822,1827,1832,1835,1837,1836,
-1832,1825,1817,1807,1799,1793,1792,1797,1809,1830,1858,1893,1932,1974,2014,2052,2083,2106,2121,2126,2123,
-2113,2099,2082,2067,2053,2044,2039,2038,2041,2046,2052,2057,2059,2059,2056,2050,2041,2030,2017,2002,1986,
-1967,1945,1918,1885,1845,1797,1743,1682,1617,1549,1483,1420,1364,1317,1281,1256,1243,1241,1250,1268,1294,
-1326,1363,1404,1448,1493,1538,1581,1620,1654,1679,1693,1696,1685,1661,1625,1578,1522,1462,1400,1341,1287,
-1240,1202,1173,1152,1138,1128,1120,1112,1103,1091,1077,1059,1041,1022,1004,989,976,965,957,951,945,
-938,930,919,906,891,873,855,837,820,804,790,776,763,748,732,712,689,662,631,597,562,
-527,494,464,438,417,401,389,380,373,365,355,341,323,299,270,237,199,158,115,72,30,
--10,-47,-82,-113,-142,-168,-192,-215,-238,-261,-285,-312,-342,-374,-410,-449,-490,-533,-577,-621,-663,
--705,-743,-779,-813,-844,-873,-902,-931,-960,-991,-1025,-1060,-1097,-1136,-1177,-1218,-1259,-1300,-1342,-1383,-1425,
--1468,-1512,-1557,-1604,-1651,-1700,-1748,-1795,-1840,-1884,-1924,-1962,-1997,-2032,-2065,-2100,-2136,-2176,-2220,-2268,-2320,
--2376,-2434,-2494,-2553,-2610,-2663,-2711,-2753,-2789,-2817,-2839,-2854,-2864,-2869,-2871,-2871,-2871,-2870,-2872,-2875,-2881,
--2891,-2903,-2918,-2935,-2953,-2972,-2991,-3009,-3026,-3042,-3056,-3070,-3085,-3100,-3118,-3138,-3161,-3188,-3217,-3249,-3283,
--3318,-3352,-3386,-3418,-3449,-3478,-3507,-3535,-3563,-3592,-3621,-3651,-3682,-3712,-3741,-3768,-3793,-3816,-3836,-3855,-3874,
--3893,-3914,-3937,-3962,-3990,-4018,-4045,-4069,-4088,-4099,-4101,-4094,-4078,-4054,-4027,-3999,-3974,-3957,-3953,-3963,-3990,
--4034,-4093,-4164,-4244,-4327,-4408,-4481,-4542,-4588,-4617,-4628,-4622,-4601,-4569,-4531,-4489,-4450,-4416,-4392,-4379,-4379,
--4392,-4417,-4454,-4499,-4550,-4603,-4657,-4708,-4754,-4793,-4824,-4846,-4861,-4868,-4869,-4866,-4861,-4856,-4853,-4852,-4856,
--4863,-4875,-4890,-4908,-4928,-4949,-4970,-4990,-5010,-5028,-5045,-5063,-5080,-5099,-5119,-5141,-5166,-5193,-5223,-5255,-5288,
--5323,-5359,-5394,-5429,-5463,-5496,-5527,-5556,-5583,-5608,-5632,-5653,-5673,-5691,-5708,-5723,-5737,-5750,-5762,-5772,-5781,
--5788,-5794,-5798,-5802,-5804,-5806,-5808,-5810,-5814,-5820,-5828,-5839,-5852,-5868,-5886,-5904,-5922,-5938,-5950,-5958,-5961,
--5959,-5950,-5937,-5919,-5898,-5876,-5853,-5831,-5810,-5790,-5770,-5750,-5726,-5699,-5664,-5621,-5568,-5504,-5429,-5344,-5251,
--5153,-5053,-4956,-4866,-4788,-4724,-4680,-4657,-4657,-4681,-4728,-4796,-4883,-4986,-5099,-5218,-5338,-5454,-5562,-5656,-5736,
--5798,-5842,-5870,-5881,-5880,-5869,-5852,-5832,-5812,-5796,-5783,-5776,-5774,-5777,-5784,-5793,-5803,-5813,-5822,-5830,-5836,
--5842,-5848,-5854,-5861,-5869,-5879,-5890,-5902,-5915,-5927,-5939,-5949,-5958,-5965,-5970,-5974,-5977,-5979,-5980,-5981,-5981,
--5982,-5983,-5984,-5986,-5989,-5994,-6001,-6010,-6023,-6038,-6057,-6079,-6103,-6129,-6156,-6183,-6210,-6235,-6259,-6281,-6300,
--6318,-6334,-6349,-6363,-6377,-6391,-6405,-6419,-6432,-6444,-6455,-6465,-6472,-6478,-6481,-6484,-6485,-6486,-6488,-6490,-6495,
--6501,-6510,-6521,-6534,-6549,-6563,-6578,-6590,-6601,-6608,-6612,-6612,-6609,-6603,-6595,-6587,-6579,-6571,-6566,-6562,-6561,
--6561,-6563,-6566,-6568,-6569,-6568,-6565,-6559,-6551,-6541,-6529,-6517,-6506,-6495,-6487,-6480,-6476,-6473,-6471,-6470,-6469,
--6467,-6464,-6460,-6454,-6447,-6439,-6431,-6424,-6417,-6412,-6409,-6406,-6405,-6405,-6405,-6404,-6402,-6399,-6394,-6388,-6381,
--6372,-6363,-6354,-6344,-6335,-6326,-6318,-6309,-6301,-6293,-6284,-6275,-6265,-6255,-6244,-6232,-6221,-6209,-6198,-6188,-6178,
--6169,-6160,-6151,-6142,-6132,-6121,-6109,-6095,-6078,-6059,-6039,-6016,-5991,-5965,-5939,-5914,-5889,-5867,-5846,-5829,-5814,
--5802,-5793,-5786,-5781,-5775,-5770,-5763,-5755,-5744,-5732,-5717,-5701,-5685,-5667,-5651,-5635,-5620,-5607,-5595,-5584,-5574,
--5562,-5550,-5536,-5519,-5499,-5476,-5451,-5422,-5392,-5360,-5328,-5296,-5265,-5237,-5210,-5187,-5167,-5150,-5137,-5128,-5121,
--5117,-5114,-5111,-5107,-5101,-5090,-5075,-5052,-5023,-4985,-4940,-4889,-4833,-4774,-4714,-4655,-4601,-4552,-4511,-4478,-4452,
--4433,-4419,-4407,-4395,-4381,-4362,-4336,-4304,-4264,-4219,-4168,-4115,-4063,-4013,-3968,-3929,-3898,-3876,-3860,-3852,-3848,
--3848,-3849,-3849,-3847,-3842,-3834,-3823,-3809,-3794,-3779,-3764,-3751,-3741,-3733,-3729,-3727,-3727,-3728,-3730,-3732,-3732,
--3732,-3730,-3726,-3722,-3716,-3711,-3707,-3703,-3701,-3700,-3701,-3703,-3706,-3709,-3710,-3709,-3706,-3698,-3686,-3670,-3649,
--3624,-3596,-3565,-3534,-3501,-3470,-3440,-3412,-3386,-3361,-3338,-3316,-3294,-3272,-3250,-3228,-3206,-3186,-3167,-3151,-3138,
--3127,-3119,-3113,-3108,-3103,-3096,-3085,-3071,-3053,-3031,-3005,-2977,-2948,-2919,-2891,-2866,-2843,-2823,-2804,-2786,-2768,
--2748,-2726,-2701,-2675,-2646,-2618,-2591,-2565,-2543,-2525,-2509,-2496,-2483,-2470,-2453,-2433,-2408,-2377,-2343,-2306,-2268,
--2232,-2200,-2174,-2154,-2141,-2135,-2132,-2132,-2131,-2128,-2120,-2106,-2087,-2062,-2034,-2004,-1974,-1946,-1922,-1901,-1885,
--1871,-1860,-1849,-1838,-1826,-1812,-1797,-1782,-1768,-1756,-1748,-1746,-1748,-1755,-1765,-1777,-1788,-1796,-1799,-1796,-1787,
--1771,-1751,-1727,-1704,-1682,-1664,-1652,-1646,-1646,-1653,-1664,-1678,-1693,-1708,-1721,-1731,-1738,-1741,-1741,-1738,-1731,
--1721,-1708,-1691,-1669,-1644,-1614,-1580,-1543,-1504,-1464,-1425,-1390,-1359,-1333,-1313,-1298,-1288,-1282,-1276,-1271,-1264,
--1254,-1240,-1222,-1202,-1179,-1154,-1130,-1106,-1085,-1065,-1047,-1031,-1014,-996,-977,-954,-927,-897,-863,-826,-786,
--746,-706,-667,-629,-594,-561,-529,-499,-469,-439,-408,-374,-339,-303,-265,-226,-188,-151,-116,-85,-57,
--33,-13,3,17,30,43,55,68,82,94,105,112,113,106,89,61,20,-32,-94,-165,-241,
--318,-393,-461,-521,-570,-607,-631,-644,-648,-645,-638,-628,-619,-612,-607,-604,-604,-605,-605,-604,-601,
--595,-587,-575,-562,-547,-531,-515,-500,-485,-471,-458,-445,-431,-418,-404,-390,-376,-363,-350,-340,-330,
--323,-317,-312,-308,-303,-298,-293,-286,-278,-270,-262,-255,-249,-246,-244,-245,-248,-251,-256,-260,-264,
--266,-268,-268,-268,-267,-268,-270,-274,-280,-288,-299,-311,-324,-338,-350,-362,-372,-381,-389,-397,-404,
--411,-419,-427,-436,-446,-455,-464,-472,-477,-481,-483,-482,-479,-476,-470,-465,-458,-451,-443,-435,-425,
--413,-400,-385,-368,-350,-330,-310,-290,-271,-253,-237,-222,-209,-198,-188,-179,-172,-165,-160,-156,-153,
--152,-152,-154,-157,-161,-165,-169,-173,-177,-179,-181,-183,-185,-187,-190,-194,-199,-204,-209,-213,-215,
--214,-209,-199,-185,-167,-144,-119,-92,-64,-36,-10,15,38,60,81,103,124,148,172,199,227,
-257,287,317,345,371,394,413,428,439,446,451,452,452,451,449,449,449,451,456,464,475,
-489,506,526,547,570,592,613,632,648,661,669,674,675,675,674,675,678,684,696,714,738,
-768,803,843,886,930,976,1020,1063,1104,1142,1178,1210,1239,1265,1287,1306,1320,1330,1335,1334,1328,
-1316,1300,1279,1256,1232,1207,1183,1162,1145,1132,1124,1121,1123,1130,1141,1157,1176,1199,1152,1163,1179,
-1198,1222,1250,1281,1313,1346,1379,1410,1438,1463,1484,1502,1517,1529,1539,1548,1557,1565,1574,1583,1592,
-1600,1607,1614,1619,1623,1626,1629,1632,1636,1642,1650,1660,1672,1686,1701,1717,1732,1745,1757,1767,1775,
-1782,1788,1795,1801,1810,1819,1830,1842,1855,1866,1877,1885,1891,1894,1894,1894,1892,1892,1892,1896,1903,
-1913,1927,1943,1961,1978,1995,2009,2019,2025,2027,2024,2017,2007,1994,1979,1963,1946,1930,1913,1898,1884,
-1871,1860,1851,1845,1842,1842,1844,1848,1854,1861,1867,1873,1878,1881,1884,1886,1889,1893,1900,1910,1923,
-1940,1958,1977,1995,2008,2017,2018,2012,1998,1976,1949,1920,1889,1861,1838,1822,1813,1811,1817,1829,1844,
-1860,1876,1889,1899,1905,1906,1903,1897,1889,1880,1871,1862,1854,1846,1839,1831,1823,1816,1809,1803,1800,
-1801,1806,1816,1832,1852,1878,1906,1936,1965,1993,2016,2035,2048,2055,2056,2054,2048,2041,2033,2026,2020,
-2016,2014,2014,2016,2017,2018,2018,2017,2014,2009,2001,1991,1980,1966,1952,1937,1921,1906,1891,1878,1867,
-1857,1851,1848,1847,1850,1855,1862,1870,1878,1885,1890,1893,1893,1889,1883,1873,1861,1847,1833,1819,1805,
-1793,1782,1775,1769,1766,1764,1764,1764,1765,1765,1764,1763,1759,1754,1749,1743,1738,1734,1733,1735,1741,
-1752,1768,1787,1810,1835,1860,1884,1905,1923,1936,1944,1947,1946,1941,1935,1929,1923,1919,1918,1919,1922,
-1927,1933,1939,1944,1948,1950,1949,1946,1941,1933,1923,1909,1892,1871,1845,1813,1775,1730,1680,1625,1567,
-1507,1449,1393,1343,1301,1267,1243,1228,1223,1227,1239,1257,1280,1307,1337,1370,1404,1438,1471,1502,1530,
-1553,1569,1576,1574,1562,1540,1507,1467,1421,1371,1320,1271,1225,1185,1152,1125,1104,1088,1075,1064,1053,
-1042,1029,1015,1000,984,969,956,944,934,926,919,913,907,899,890,879,865,850,834,817,801,
-785,771,757,745,732,719,704,686,665,640,613,583,551,520,490,461,436,414,395,379,364,
-351,336,319,300,276,249,217,182,144,104,63,22,-17,-55,-91,-124,-155,-184,-211,-237,-262,
--288,-314,-341,-370,-401,-435,-471,-508,-547,-587,-626,-665,-703,-739,-773,-805,-835,-865,-894,-923,-954,
--985,-1019,-1054,-1090,-1128,-1167,-1205,-1244,-1282,-1320,-1358,-1396,-1434,-1474,-1515,-1558,-1602,-1648,-1694,-1741,-1786,
--1830,-1872,-1911,-1949,-1984,-2019,-2054,-2090,-2129,-2171,-2217,-2267,-2321,-2377,-2435,-2493,-2550,-2604,-2654,-2698,-2737,
--2769,-2795,-2816,-2831,-2842,-2850,-2855,-2859,-2864,-2869,-2875,-2883,-2894,-2907,-2923,-2941,-2960,-2981,-3003,-3024,-3045,
--3064,-3083,-3100,-3116,-3133,-3150,-3168,-3188,-3211,-3236,-3264,-3295,-3327,-3359,-3392,-3423,-3453,-3482,-3508,-3533,-3558,
--3581,-3605,-3629,-3655,-3681,-3709,-3736,-3763,-3790,-3816,-3840,-3864,-3886,-3909,-3932,-3956,-3980,-4006,-4031,-4056,-4079,
--4098,-4111,-4119,-4119,-4112,-4100,-4083,-4065,-4049,-4038,-4035,-4043,-4063,-4098,-4145,-4204,-4271,-4343,-4416,-4484,-4545,
--4594,-4628,-4648,-4652,-4641,-4619,-4589,-4554,-4518,-4485,-4459,-4442,-4437,-4445,-4464,-4495,-4534,-4581,-4631,-4683,-4733,
--4778,-4818,-4850,-4874,-4890,-4900,-4903,-4903,-4900,-4897,-4895,-4896,-4900,-4907,-4918,-4933,-4950,-4969,-4989,-5010,-5031,
--5051,-5070,-5089,-5108,-5126,-5146,-5167,-5189,-5213,-5239,-5267,-5297,-5328,-5360,-5393,-5426,-5459,-5491,-5522,-5551,-5579,
--5604,-5628,-5649,-5669,-5687,-5703,-5717,-5731,-5743,-5755,-5766,-5775,-5784,-5792,-5798,-5803,-5807,-5809,-5812,-5814,-5817,
--5821,-5827,-5835,-5846,-5860,-5876,-5893,-5911,-5927,-5941,-5950,-5955,-5954,-5947,-5934,-5916,-5895,-5871,-5847,-5824,-5802,
--5783,-5766,-5749,-5733,-5714,-5689,-5658,-5617,-5564,-5500,-5424,-5338,-5243,-5144,-5044,-4947,-4859,-4785,-4727,-4690,-4676,
--4686,-4720,-4776,-4853,-4946,-5052,-5166,-5282,-5397,-5505,-5603,-5688,-5757,-5810,-5848,-5870,-5880,-5880,-5872,-5861,-5847,
--5834,-5824,-5817,-5814,-5815,-5819,-5825,-5833,-5841,-5848,-5855,-5860,-5864,-5868,-5871,-5874,-5878,-5883,-5888,-5895,-5903,
--5911,-5919,-5927,-5935,-5942,-5948,-5954,-5959,-5963,-5967,-5970,-5974,-5976,-5979,-5982,-5985,-5989,-5994,-6000,-6010,-6022,
--6037,-6055,-6076,-6099,-6124,-6150,-6176,-6202,-6225,-6247,-6267,-6285,-6301,-6316,-6330,-6345,-6360,-6376,-6393,-6410,-6427,
--6444,-6458,-6470,-6479,-6484,-6486,-6484,-6481,-6476,-6472,-6468,-6468,-6470,-6477,-6488,-6502,-6519,-6538,-6556,-6574,-6589,
--6600,-6606,-6608,-6606,-6599,-6590,-6579,-6567,-6557,-6549,-6544,-6542,-6543,-6546,-6552,-6557,-6563,-6566,-6567,-6565,-6560,
--6551,-6539,-6526,-6512,-6498,-6485,-6474,-6466,-6460,-6457,-6456,-6456,-6457,-6458,-6458,-6458,-6456,-6453,-6449,-6445,-6440,
--6435,-6430,-6426,-6422,-6418,-6415,-6412,-6408,-6403,-6398,-6391,-6384,-6376,-6367,-6358,-6350,-6342,-6334,-6327,-6321,-6314,
--6308,-6300,-6293,-6284,-6274,-6262,-6251,-6238,-6226,-6214,-6203,-6193,-6185,-6177,-6171,-6165,-6158,-6151,-6141,-6129,-6114,
--6096,-6073,-6048,-6020,-5990,-5959,-5929,-5901,-5875,-5853,-5835,-5821,-5811,-5804,-5800,-5797,-5794,-5791,-5786,-5779,-5770,
--5758,-5744,-5728,-5711,-5694,-5677,-5661,-5644,-5629,-5613,-5596,-5578,-5558,-5536,-5511,-5484,-5453,-5420,-5386,-5350,-5313,
--5276,-5241,-5206,-5174,-5144,-5117,-5093,-5073,-5056,-5044,-5036,-5032,-5032,-5034,-5038,-5041,-5042,-5039,-5030,-5012,-4985,
--4948,-4902,-4846,-4784,-4718,-4651,-4586,-4526,-4474,-4432,-4400,-4379,-4366,-4360,-4357,-4355,-4350,-4339,-4321,-4295,-4261,
--4220,-4173,-4123,-4074,-4027,-3985,-3950,-3921,-3901,-3887,-3878,-3872,-3869,-3865,-3859,-3850,-3838,-3823,-3805,-3786,-3766,
--3746,-3728,-3713,-3700,-3691,-3684,-3680,-3679,-3679,-3680,-3682,-3685,-3688,-3692,-3696,-3701,-3707,-3713,-3721,-3729,-3738,
--3747,-3756,-3764,-3769,-3773,-3774,-3771,-3763,-3752,-3735,-3713,-3687,-3657,-3622,-3586,-3547,-3508,-3469,-3431,-3395,-3362,
--3331,-3303,-3278,-3254,-3232,-3211,-3191,-3172,-3153,-3137,-3121,-3108,-3097,-3087,-3079,-3072,-3065,-3057,-3047,-3035,-3020,
--3002,-2981,-2958,-2935,-2912,-2889,-2870,-2852,-2838,-2826,-2815,-2804,-2793,-2780,-2764,-2744,-2722,-2697,-2670,-2643,-2616,
--2591,-2568,-2547,-2527,-2509,-2489,-2468,-2444,-2417,-2386,-2351,-2314,-2276,-2239,-2204,-2172,-2145,-2122,-2103,-2088,-2076,
--2063,-2051,-2036,-2019,-2000,-1979,-1956,-1934,-1912,-1893,-1876,-1862,-1851,-1841,-1833,-1825,-1816,-1806,-1796,-1785,-1774,
--1765,-1758,-1753,-1752,-1753,-1756,-1759,-1761,-1761,-1756,-1745,-1729,-1708,-1683,-1655,-1627,-1601,-1579,-1563,-1554,-1552,
--1558,-1571,-1588,-1608,-1629,-1650,-1670,-1687,-1700,-1710,-1716,-1717,-1715,-1708,-1696,-1679,-1656,-1629,-1596,-1558,-1518,
--1476,-1434,-1395,-1359,-1329,-1305,-1288,-1277,-1271,-1267,-1266,-1264,-1260,-1252,-1241,-1225,-1205,-1182,-1157,-1131,-1105,
--1080,-1056,-1032,-1010,-987,-963,-937,-909,-879,-847,-813,-779,-746,-714,-684,-656,-631,-608,-586,-564,-542,
--517,-489,-458,-423,-384,-344,-303,-261,-222,-186,-154,-127,-105,-87,-74,-63,-54,-47,-39,-31,-23,
--15,-8,-5,-7,-15,-31,-57,-93,-137,-191,-250,-314,-379,-443,-502,-554,-599,-633,-659,-676,-685,
--689,-690,-689,-687,-686,-687,-689,-691,-693,-694,-693,-689,-682,-672,-660,-646,-631,-615,-600,-587,-574,
--563,-552,-542,-531,-520,-508,-495,-481,-466,-452,-438,-426,-416,-408,-401,-396,-392,-389,-385,-380,-375,
--368,-361,-354,-347,-341,-337,-333,-332,-331,-331,-332,-333,-333,-332,-330,-328,-325,-322,-321,-320,-321,
--324,-329,-335,-342,-350,-357,-363,-369,-374,-378,-381,-385,-389,-393,-399,-405,-412,-419,-426,-431,-435,
--437,-437,-435,-432,-426,-420,-414,-407,-401,-394,-386,-378,-369,-357,-343,-327,-308,-287,-265,-242,-219,
--197,-177,-158,-142,-128,-117,-107,-100,-94,-89,-86,-85,-86,-88,-92,-98,-106,-115,-125,-134,-144,
--152,-159,-165,-170,-173,-177,-180,-183,-186,-189,-191,-192,-192,-188,-181,-170,-154,-135,-113,-88,-62,
--36,-12,10,30,48,64,79,93,109,126,146,169,194,221,250,278,304,327,345,359,366,
-369,367,361,353,345,338,333,332,336,344,357,375,398,423,451,479,509,537,563,587,608,
-626,641,652,661,668,673,678,684,691,701,713,729,748,771,797,826,858,892,927,964,1001,
-1039,1076,1113,1149,1184,1217,1247,1274,1298,1317,1330,1339,1341,1339,1331,1320,1304,1287,1268,1248,1229,
-1211,1194,1179,1166,1156,1149,1144,1143,1146,1152,1090,1080,1076,1080,1092,1112,1138,1170,1205,1242,1278,
-1311,1341,1366,1386,1401,1411,1418,1422,1426,1429,1434,1441,1449,1460,1472,1484,1497,1510,1523,1534,1545,
-1555,1565,1575,1585,1596,1607,1619,1631,1643,1655,1666,1677,1686,1695,1703,1711,1719,1727,1736,1746,1756,
-1766,1776,1786,1795,1803,1809,1814,1819,1822,1825,1828,1831,1835,1840,1847,1854,1861,1869,1877,1884,1890,
-1895,1898,1900,1900,1898,1895,1890,1883,1875,1866,1856,1846,1835,1825,1817,1810,1805,1802,1803,1805,1810,
-1815,1822,1828,1834,1839,1842,1845,1847,1849,1852,1857,1863,1871,1880,1891,1901,1910,1916,1918,1916,1908,
-1896,1880,1861,1840,1820,1803,1789,1780,1776,1777,1782,1790,1800,1811,1821,1829,1835,1839,1840,1840,1839,
-1837,1834,1832,1829,1826,1822,1817,1811,1804,1795,1787,1779,1773,1771,1773,1780,1792,1809,1830,1853,1879,
-1903,1926,1945,1960,1970,1975,1976,1973,1969,1964,1959,1955,1953,1953,1955,1958,1962,1966,1969,1970,1968,
-1963,1956,1946,1933,1918,1902,1885,1868,1852,1837,1823,1812,1804,1799,1797,1799,1804,1812,1821,1832,1844,
-1855,1864,1871,1875,1875,1872,1865,1855,1844,1830,1816,1801,1787,1774,1762,1752,1742,1734,1727,1720,1714,
-1708,1703,1698,1693,1689,1686,1683,1682,1682,1683,1685,1687,1691,1694,1698,1701,1704,1706,1707,1708,1707,
-1707,1706,1704,1703,1703,1703,1704,1707,1710,1714,1718,1723,1728,1733,1738,1743,1748,1752,1757,1761,1764,
-1767,1767,1765,1758,1747,1728,1703,1669,1628,1581,1527,1470,1412,1355,1302,1255,1216,1186,1166,1156,1154,
-1160,1172,1187,1205,1223,1241,1257,1272,1285,1296,1305,1312,1318,1321,1321,1318,1312,1301,1286,1266,1243,
-1217,1190,1161,1133,1107,1082,1061,1042,1026,1011,998,985,972,959,945,931,917,903,891,880,870,
-862,856,850,845,839,833,825,816,805,794,782,770,758,746,736,726,716,706,695,682,667,
-650,630,608,584,560,536,512,490,470,451,434,417,401,384,364,342,316,286,253,215,175,
-132,87,42,-2,-45,-86,-125,-161,-194,-225,-254,-282,-309,-335,-362,-390,-419,-450,-483,-517,-553,
--589,-625,-661,-695,-729,-761,-791,-821,-849,-878,-907,-938,-970,-1003,-1039,-1076,-1114,-1153,-1191,-1230,-1267,
--1303,-1338,-1373,-1407,-1442,-1478,-1515,-1553,-1593,-1634,-1675,-1716,-1756,-1795,-1832,-1867,-1902,-1935,-1969,-2005,-2043,
--2085,-2132,-2182,-2237,-2295,-2355,-2416,-2476,-2533,-2586,-2634,-2676,-2712,-2742,-2766,-2786,-2803,-2817,-2830,-2842,-2855,
--2868,-2883,-2899,-2917,-2936,-2956,-2978,-3000,-3022,-3045,-3068,-3091,-3113,-3135,-3156,-3177,-3198,-3219,-3241,-3263,-3287,
--3311,-3337,-3363,-3390,-3417,-3442,-3467,-3489,-3510,-3529,-3546,-3561,-3577,-3593,-3611,-3630,-3652,-3676,-3703,-3731,-3760,
--3790,-3819,-3847,-3874,-3899,-3923,-3946,-3968,-3990,-4012,-4035,-4059,-4082,-4104,-4125,-4143,-4157,-4168,-4174,-4177,-4178,
--4177,-4177,-4179,-4187,-4201,-4223,-4253,-4291,-4336,-4387,-4441,-4495,-4546,-4592,-4630,-4658,-4675,-4680,-4676,-4662,-4642,
--4617,-4592,-4569,-4550,-4538,-4536,-4542,-4559,-4585,-4619,-4658,-4702,-4748,-4793,-4835,-4872,-4904,-4930,-4949,-4962,-4970,
--4974,-4975,-4975,-4975,-4977,-4980,-4987,-4996,-5008,-5023,-5040,-5060,-5080,-5102,-5124,-5147,-5170,-5193,-5217,-5241,-5266,
--5291,-5317,-5343,-5370,-5397,-5425,-5452,-5480,-5506,-5532,-5556,-5579,-5600,-5620,-5637,-5654,-5669,-5683,-5696,-5709,-5721,
--5733,-5745,-5756,-5767,-5778,-5787,-5794,-5800,-5805,-5808,-5811,-5812,-5814,-5817,-5822,-5829,-5838,-5849,-5863,-5877,-5892,
--5906,-5918,-5926,-5929,-5928,-5920,-5908,-5891,-5870,-5847,-5823,-5798,-5774,-5750,-5727,-5703,-5678,-5651,-5618,-5579,-5533,
--5479,-5416,-5346,-5271,-5192,-5112,-5036,-4966,-4906,-4859,-4828,-4815,-4821,-4846,-4889,-4949,-5022,-5106,-5198,-5293,-5388,
--5480,-5565,-5641,-5706,-5759,-5800,-5829,-5848,-5858,-5860,-5858,-5852,-5846,-5841,-5837,-5836,-5838,-5843,-5850,-5858,-5868,
--5877,-5886,-5893,-5899,-5903,-5906,-5907,-5908,-5907,-5907,-5907,-5907,-5908,-5910,-5913,-5916,-5921,-5927,-5934,-5941,-5949,
--5957,-5965,-5973,-5981,-5988,-5995,-6001,-6008,-6015,-6023,-6033,-6045,-6059,-6075,-6093,-6114,-6135,-6157,-6179,-6200,-6220,
--6238,-6254,-6269,-6282,-6296,-6309,-6324,-6340,-6358,-6377,-6398,-6420,-6440,-6460,-6476,-6489,-6497,-6501,-6501,-6497,-6490,
--6483,-6475,-6470,-6468,-6470,-6476,-6487,-6501,-6517,-6535,-6551,-6566,-6577,-6583,-6585,-6581,-6574,-6563,-6549,-6536,-6523,
--6512,-6505,-6501,-6502,-6506,-6512,-6521,-6530,-6538,-6544,-6547,-6547,-6542,-6535,-6525,-6512,-6499,-6486,-6474,-6464,-6457,
--6453,-6451,-6451,-6453,-6456,-6459,-6462,-6464,-6465,-6464,-6462,-6459,-6454,-6449,-6443,-6437,-6431,-6425,-6419,-6412,-6406,
--6398,-6391,-6382,-6374,-6365,-6357,-6349,-6342,-6336,-6330,-6325,-6321,-6317,-6313,-6309,-6303,-6296,-6288,-6278,-6267,-6254,
--6242,-6229,-6216,-6205,-6194,-6185,-6176,-6168,-6159,-6150,-6138,-6125,-6108,-6089,-6067,-6042,-6016,-5989,-5963,-5939,-5917,
--5898,-5883,-5872,-5864,-5859,-5855,-5851,-5846,-5838,-5828,-5814,-5797,-5776,-5754,-5730,-5705,-5680,-5656,-5634,-5612,-5591,
--5571,-5549,-5525,-5499,-5469,-5436,-5399,-5359,-5317,-5274,-5231,-5188,-5147,-5109,-5074,-5042,-5013,-4988,-4966,-4947,-4931,
--4919,-4910,-4906,-4904,-4906,-4910,-4916,-4921,-4923,-4921,-4912,-4895,-4867,-4830,-4782,-4726,-4665,-4600,-4535,-4475,-4421,
--4376,-4342,-4320,-4307,-4302,-4303,-4305,-4307,-4304,-4294,-4276,-4251,-4217,-4178,-4136,-4093,-4052,-4016,-3986,-3963,-3947,
--3937,-3932,-3929,-3926,-3922,-3915,-3903,-3888,-3868,-3846,-3822,-3797,-3774,-3752,-3734,-3718,-3706,-3696,-3688,-3681,-3676,
--3671,-3666,-3663,-3661,-3662,-3665,-3672,-3682,-3695,-3712,-3730,-3750,-3770,-3787,-3802,-3812,-3817,-3816,-3808,-3794,-3775,
--3749,-3719,-3686,-3649,-3610,-3570,-3529,-3489,-3450,-3412,-3375,-3341,-3309,-3278,-3249,-3223,-3197,-3174,-3151,-3130,-3110,
--3092,-3076,-3062,-3049,-3038,-3029,-3021,-3013,-3004,-2995,-2984,-2971,-2955,-2938,-2918,-2898,-2878,-2859,-2842,-2827,-2815,
--2806,-2799,-2794,-2789,-2784,-2777,-2767,-2754,-2738,-2720,-2698,-2675,-2651,-2626,-2602,-2579,-2556,-2534,-2512,-2489,-2464,
--2438,-2410,-2380,-2349,-2316,-2284,-2252,-2220,-2191,-2163,-2137,-2112,-2088,-2065,-2042,-2019,-1997,-1975,-1954,-1935,-1919,
--1904,-1893,-1884,-1877,-1871,-1866,-1860,-1853,-1845,-1835,-1824,-1812,-1801,-1791,-1783,-1777,-1773,-1772,-1771,-1770,-1767,
--1761,-1751,-1737,-1717,-1693,-1666,-1639,-1611,-1587,-1566,-1552,-1544,-1542,-1547,-1556,-1569,-1584,-1600,-1616,-1630,-1642,
--1651,-1657,-1660,-1660,-1656,-1649,-1638,-1622,-1602,-1577,-1548,-1515,-1480,-1443,-1407,-1373,-1344,-1319,-1300,-1288,-1280,
--1277,-1277,-1277,-1277,-1274,-1266,-1254,-1237,-1214,-1188,-1158,-1126,-1093,-1060,-1026,-993,-961,-928,-895,-862,-828,
--794,-761,-729,-698,-671,-646,-626,-609,-594,-582,-571,-559,-544,-527,-505,-479,-447,-412,-374,-334,-295,
--257,-222,-191,-165,-144,-127,-116,-108,-104,-102,-102,-106,-111,-120,-134,-152,-176,-206,-243,-285,-333,
--384,-437,-489,-540,-586,-626,-659,-685,-703,-714,-721,-723,-724,-725,-726,-729,-735,-742,-751,-760,-768,
--773,-775,-774,-768,-758,-746,-731,-714,-698,-683,-670,-659,-650,-642,-636,-629,-622,-613,-603,-591,-578,
--564,-550,-537,-524,-514,-505,-499,-494,-490,-487,-484,-480,-476,-470,-464,-457,-451,-444,-438,-433,-429,
--426,-423,-420,-417,-413,-409,-405,-400,-394,-389,-385,-381,-379,-378,-378,-379,-379,-380,-381,-380,-379,
--378,-376,-374,-373,-372,-373,-375,-378,-381,-384,-387,-388,-389,-387,-383,-378,-371,-364,-356,-348,-340,
--333,-326,-318,-309,-299,-286,-272,-254,-234,-212,-189,-166,-142,-120,-100,-83,-68,-56,-46,-39,-33,
--30,-28,-28,-29,-32,-37,-44,-53,-64,-76,-88,-101,-113,-124,-134,-141,-146,-150,-152,-154,-155,
--156,-156,-156,-156,-154,-151,-144,-135,-123,-107,-88,-68,-47,-25,-5,12,28,41,51,60,69,
-77,87,99,114,131,151,172,194,214,233,248,259,267,270,270,269,267,266,267,272,282,
-296,316,339,367,397,428,459,489,517,544,567,588,607,624,640,655,669,683,697,711,725,
-739,753,768,782,798,814,831,850,871,895,922,952,985,1021,1059,1099,1140,1180,1218,1254,1286,
-1313,1335,1352,1363,1369,1370,1367,1361,1352,1342,1330,1316,1301,1284,1265,1245,1223,1199,1175,1150,1127,
-1106,1090,1041,1014,997,989,993,1007,1030,1062,1099,1140,1180,1217,1250,1277,1297,1309,1315,1316,1314,
-1310,1308,1307,1310,1318,1329,1345,1364,1386,1408,1430,1451,1471,1488,1502,1515,1525,1535,1543,1552,1561,
-1570,1581,1592,1604,1616,1628,1640,1652,1663,1674,1684,1694,1703,1712,1720,1728,1736,1743,1750,1757,1762,
-1768,1772,1775,1777,1778,1778,1777,1775,1772,1770,1768,1766,1765,1766,1768,1771,1775,1779,1784,1789,1792,
-1794,1795,1793,1789,1784,1778,1772,1765,1760,1755,1753,1753,1755,1759,1764,1769,1774,1779,1783,1786,1788,
-1789,1790,1790,1790,1791,1792,1793,1793,1793,1792,1789,1784,1777,1769,1759,1749,1739,1731,1724,1719,1717,
-1717,1718,1721,1725,1729,1732,1734,1736,1737,1737,1737,1737,1738,1739,1742,1745,1748,1750,1751,1751,1748,
-1744,1738,1731,1725,1720,1718,1719,1725,1735,1749,1767,1788,1810,1831,1851,1868,1881,1891,1896,1897,1896,
-1893,1889,1887,1885,1885,1887,1891,1896,1902,1908,1913,1916,1917,1914,1909,1900,1887,1872,1855,1836,1817,
-1798,1779,1763,1750,1741,1736,1736,1740,1748,1761,1776,1793,1811,1828,1843,1856,1864,1869,1869,1864,1856,
-1845,1831,1816,1800,1784,1769,1753,1739,1725,1712,1699,1687,1676,1666,1657,1650,1645,1642,1641,1642,1645,
-1649,1653,1656,1657,1656,1652,1644,1632,1617,1599,1580,1561,1542,1525,1511,1500,1494,1491,1492,1496,1502,
-1508,1515,1521,1525,1529,1531,1533,1536,1539,1543,1550,1558,1568,1579,1588,1595,1598,1594,1583,1562,1532,
-1493,1446,1393,1337,1280,1226,1177,1136,1105,1084,1073,1072,1079,1091,1107,1124,1139,1150,1158,1160,1157,
-1150,1139,1126,1112,1098,1085,1072,1062,1052,1044,1036,1028,1020,1011,1002,992,981,969,958,946,934,
-922,910,897,884,871,858,844,830,817,805,793,783,774,766,760,754,749,745,740,736,731,
-726,721,716,710,705,699,693,687,679,671,661,650,637,623,607,591,574,558,542,527,514,
-501,489,477,464,450,432,412,387,358,323,284,241,194,144,93,41,-10,-61,-109,-155,-198,
--237,-273,-306,-336,-365,-392,-419,-446,-473,-502,-531,-562,-593,-625,-657,-689,-721,-751,-781,-811,-840,
--869,-899,-930,-963,-997,-1033,-1070,-1109,-1147,-1186,-1224,-1260,-1295,-1329,-1361,-1393,-1425,-1456,-1489,-1523,-1558,
--1594,-1630,-1667,-1704,-1739,-1773,-1805,-1836,-1866,-1896,-1928,-1962,-2000,-2043,-2090,-2143,-2200,-2260,-2322,-2385,-2446,
--2503,-2556,-2604,-2645,-2681,-2712,-2738,-2761,-2782,-2803,-2824,-2846,-2870,-2895,-2921,-2948,-2975,-3001,-3027,-3052,-3075,
--3097,-3118,-3138,-3159,-3179,-3201,-3223,-3247,-3272,-3300,-3328,-3357,-3386,-3416,-3444,-3471,-3496,-3518,-3537,-3554,-3567,
--3577,-3586,-3594,-3601,-3610,-3621,-3635,-3653,-3674,-3699,-3728,-3759,-3792,-3825,-3857,-3888,-3916,-3941,-3964,-3984,-4002,
--4019,-4037,-4056,-4077,-4100,-4125,-4152,-4180,-4209,-4236,-4261,-4284,-4304,-4320,-4333,-4345,-4355,-4366,-4380,-4396,-4417,
--4443,-4473,-4508,-4546,-4586,-4625,-4661,-4693,-4719,-4736,-4745,-4746,-4738,-4723,-4704,-4682,-4660,-4641,-4627,-4619,-4620,
--4631,-4650,-4678,-4713,-4753,-4797,-4842,-4885,-4926,-4961,-4991,-5015,-5032,-5043,-5050,-5053,-5053,-5053,-5054,-5056,-5061,
--5069,-5080,-5095,-5114,-5135,-5159,-5184,-5211,-5239,-5266,-5294,-5322,-5349,-5375,-5401,-5427,-5451,-5475,-5497,-5519,-5539,
--5558,-5576,-5591,-5605,-5618,-5630,-5641,-5651,-5661,-5671,-5682,-5694,-5707,-5721,-5735,-5749,-5764,-5777,-5789,-5799,-5807,
--5812,-5816,-5819,-5820,-5821,-5823,-5826,-5831,-5837,-5847,-5858,-5870,-5884,-5897,-5908,-5917,-5923,-5926,-5924,-5917,-5907,
--5893,-5875,-5855,-5831,-5805,-5776,-5744,-5709,-5669,-5624,-5574,-5519,-5459,-5395,-5329,-5262,-5196,-5134,-5078,-5030,-4994,
--4969,-4959,-4962,-4979,-5009,-5051,-5103,-5164,-5230,-5300,-5371,-5441,-5508,-5571,-5628,-5679,-5722,-5757,-5785,-5806,-5821,
--5830,-5835,-5837,-5837,-5836,-5836,-5838,-5841,-5846,-5853,-5863,-5874,-5886,-5898,-5910,-5921,-5930,-5936,-5941,-5942,-5941,
--5938,-5934,-5928,-5922,-5917,-5912,-5909,-5908,-5909,-5913,-5918,-5926,-5935,-5946,-5958,-5970,-5982,-5994,-6006,-6018,-6030,
--6042,-6055,-6068,-6083,-6100,-6117,-6135,-6154,-6172,-6190,-6207,-6223,-6237,-6250,-6261,-6272,-6284,-6296,-6310,-6326,-6344,
--6364,-6387,-6410,-6433,-6455,-6475,-6491,-6503,-6510,-6512,-6511,-6506,-6499,-6492,-6485,-6480,-6479,-6481,-6486,-6495,-6506,
--6518,-6530,-6541,-6548,-6552,-6553,-6548,-6540,-6530,-6517,-6504,-6491,-6481,-6473,-6469,-6469,-6472,-6478,-6486,-6495,-6503,
--6511,-6516,-6518,-6518,-6514,-6508,-6501,-6492,-6483,-6474,-6467,-6462,-6459,-6457,-6458,-6459,-6462,-6465,-6467,-6468,-6468,
--6466,-6463,-6459,-6454,-6448,-6442,-6436,-6430,-6425,-6420,-6415,-6410,-6405,-6400,-6394,-6387,-6380,-6373,-6365,-6357,-6350,
--6343,-6337,-6332,-6327,-6323,-6319,-6315,-6310,-6304,-6296,-6287,-6276,-6264,-6250,-6236,-6221,-6207,-6192,-6179,-6166,-6153,
--6140,-6128,-6115,-6101,-6086,-6070,-6054,-6037,-6020,-6004,-5990,-5977,-5966,-5958,-5951,-5945,-5939,-5932,-5922,-5908,-5890,
--5867,-5838,-5805,-5768,-5728,-5687,-5646,-5607,-5571,-5538,-5508,-5481,-5456,-5432,-5407,-5381,-5352,-5319,-5283,-5244,-5203,
--5160,-5118,-5076,-5038,-5002,-4970,-4942,-4917,-4895,-4875,-4858,-4842,-4827,-4814,-4802,-4793,-4786,-4781,-4779,-4779,-4780,
--4779,-4776,-4768,-4753,-4731,-4701,-4663,-4617,-4567,-4513,-4461,-4411,-4367,-4330,-4303,-4284,-4274,-4269,-4268,-4268,-4266,
--4259,-4247,-4227,-4201,-4169,-4134,-4097,-4062,-4031,-4005,-3985,-3972,-3964,-3961,-3961,-3961,-3959,-3954,-3946,-3933,-3916,
--3895,-3873,-3850,-3829,-3809,-3792,-3777,-3765,-3754,-3744,-3734,-3723,-3711,-3699,-3686,-3674,-3664,-3658,-3657,-3662,-3673,
--3690,-3713,-3738,-3765,-3791,-3813,-3830,-3839,-3840,-3832,-3815,-3789,-3756,-3718,-3677,-3633,-3589,-3546,-3504,-3466,-3430,
--3396,-3365,-3335,-3307,-3279,-3251,-3224,-3196,-3168,-3140,-3113,-3087,-3063,-3040,-3020,-3003,-2987,-2975,-2964,-2954,-2944,
--2935,-2925,-2913,-2899,-2884,-2867,-2848,-2829,-2810,-2792,-2775,-2761,-2749,-2740,-2734,-2730,-2727,-2724,-2721,-2717,-2711,
--2703,-2692,-2679,-2663,-2646,-2627,-2607,-2586,-2566,-2545,-2523,-2502,-2481,-2459,-2437,-2414,-2391,-2368,-2344,-2320,-2294,
--2268,-2241,-2213,-2185,-2155,-2125,-2095,-2065,-2038,-2012,-1989,-1970,-1955,-1943,-1935,-1929,-1924,-1920,-1916,-1910,-1902,
--1891,-1879,-1865,-1850,-1836,-1823,-1813,-1805,-1801,-1799,-1798,-1798,-1797,-1794,-1787,-1777,-1764,-1746,-1726,-1705,-1683,
--1662,-1644,-1630,-1619,-1611,-1608,-1607,-1608,-1611,-1613,-1616,-1617,-1617,-1615,-1613,-1609,-1604,-1597,-1588,-1577,-1563,
--1546,-1526,-1503,-1477,-1449,-1421,-1393,-1368,-1346,-1328,-1316,-1309,-1305,-1305,-1307,-1308,-1308,-1304,-1295,-1280,-1260,
--1234,-1203,-1168,-1130,-1090,-1049,-1008,-968,-928,-888,-850,-813,-776,-740,-707,-675,-647,-622,-601,-584,-571,
--561,-554,-549,-543,-536,-526,-513,-496,-474,-448,-418,-386,-352,-318,-285,-254,-226,-202,-182,-167,-157,
--153,-154,-162,-176,-196,-224,-259,-301,-349,-403,-460,-520,-579,-636,-688,-734,-772,-800,-819,-829,-832,
--827,-819,-809,-799,-790,-785,-785,-788,-795,-805,-815,-826,-835,-840,-842,-839,-832,-822,-808,-794,-779,
--765,-752,-742,-734,-728,-723,-718,-713,-708,-700,-691,-680,-668,-655,-642,-630,-619,-610,-603,-597,-592,
--589,-586,-582,-578,-573,-568,-562,-555,-548,-542,-536,-530,-526,-521,-517,-513,-508,-502,-496,-488,-480,
--472,-464,-456,-449,-442,-437,-432,-428,-424,-420,-416,-411,-405,-399,-393,-387,-381,-376,-372,-369,-367,
--365,-363,-361,-358,-354,-348,-340,-332,-323,-313,-303,-294,-285,-276,-267,-258,-248,-237,-224,-209,-191,
--172,-152,-131,-109,-89,-70,-53,-39,-27,-18,-11,-6,-3,-2,-1,-2,-4,-8,-13,-20,-29,
--40,-51,-64,-76,-88,-98,-107,-113,-117,-118,-118,-117,-115,-113,-112,-111,-111,-110,-110,-107,-104,
--97,-89,-78,-64,-50,-34,-19,-4,8,18,27,33,38,43,48,53,60,69,80,92,106,
-120,134,148,161,173,185,196,208,222,238,256,279,304,333,364,396,428,460,489,515,539,
-559,576,591,604,618,632,648,667,688,711,736,763,789,815,838,860,879,895,909,922,935,
-949,966,986,1009,1037,1070,1105,1143,1182,1221,1257,1289,1317,1339,1356,1367,1373,1375,1373,1370,1365,
-1360,1354,1348,1340,1331,1318,1302,1280,1254,1222,1187,1149,1111,1074,1041,1007,976,953,942,942,954,
-976,1008,1046,1088,1130,1169,1203,1230,1249,1260,1264,1262,1256,1248,1241,1236,1237,1242,1253,1270,1291,
-1316,1343,1370,1396,1420,1441,1458,1472,1482,1491,1498,1505,1512,1521,1531,1543,1556,1571,1587,1603,1619,
-1635,1648,1661,1671,1680,1688,1694,1700,1706,1711,1717,1722,1728,1734,1739,1743,1746,1748,1747,1745,1740,
-1735,1728,1722,1715,1710,1707,1706,1707,1711,1716,1723,1731,1739,1746,1752,1756,1757,1757,1754,1750,1745,
-1739,1734,1730,1728,1727,1727,1729,1732,1735,1739,1742,1744,1746,1747,1747,1746,1744,1741,1739,1735,1731,
-1727,1723,1718,1713,1707,1702,1696,1692,1688,1684,1682,1681,1680,1680,1679,1679,1678,1676,1673,1670,1667,
-1663,1661,1659,1660,1662,1665,1670,1676,1682,1687,1691,1692,1691,1688,1682,1675,1667,1659,1654,1651,1652,
-1657,1667,1680,1697,1715,1735,1754,1772,1788,1800,1809,1815,1818,1818,1817,1815,1813,1812,1812,1814,1817,
-1822,1828,1834,1840,1845,1848,1848,1845,1839,1829,1816,1799,1780,1760,1739,1719,1701,1687,1678,1674,1676,
-1684,1697,1715,1737,1759,1782,1803,1821,1834,1843,1845,1843,1835,1823,1808,1791,1772,1754,1735,1718,1701,
-1686,1672,1658,1646,1634,1623,1614,1607,1602,1599,1599,1601,1604,1608,1613,1615,1615,1612,1604,1590,1572,
-1550,1523,1495,1466,1438,1413,1392,1375,1364,1358,1356,1358,1362,1367,1372,1376,1379,1381,1381,1381,1381,
-1383,1387,1394,1404,1417,1430,1444,1455,1462,1462,1455,1439,1413,1378,1336,1289,1238,1188,1140,1098,1064,
-1039,1024,1018,1020,1029,1041,1055,1067,1076,1081,1079,1072,1060,1043,1022,1001,980,960,942,928,918,
-910,905,902,901,899,897,893,889,883,875,866,857,846,836,825,814,802,791,780,768,756,
-745,733,722,711,701,693,685,678,673,669,667,665,664,664,663,663,661,659,655,650,644,
-636,626,616,604,592,579,567,555,544,534,524,516,507,499,490,479,466,450,431,407,379,
-347,309,268,223,174,123,70,16,-36,-89,-140,-189,-234,-277,-317,-353,-386,-417,-446,-473,-499,
--525,-551,-577,-603,-630,-658,-686,-715,-744,-773,-802,-832,-863,-895,-928,-963,-999,-1037,-1075,-1114,-1153,
--1191,-1229,-1264,-1298,-1329,-1359,-1388,-1416,-1444,-1473,-1503,-1535,-1568,-1603,-1638,-1674,-1709,-1743,-1775,-1805,-1834,
--1862,-1890,-1920,-1952,-1987,-2027,-2073,-2123,-2177,-2235,-2295,-2355,-2413,-2469,-2520,-2566,-2607,-2644,-2675,-2704,-2731,
--2757,-2784,-2812,-2842,-2874,-2907,-2940,-2974,-3007,-3037,-3065,-3090,-3112,-3132,-3150,-3168,-3185,-3204,-3224,-3247,-3273,
--3302,-3334,-3367,-3402,-3436,-3470,-3501,-3529,-3554,-3574,-3590,-3602,-3611,-3617,-3621,-3625,-3629,-3636,-3646,-3659,-3677,
--3699,-3726,-3756,-3788,-3822,-3857,-3890,-3921,-3950,-3975,-3997,-4016,-4033,-4049,-4065,-4081,-4100,-4122,-4147,-4175,-4206,
--4239,-4273,-4306,-4338,-4367,-4393,-4415,-4433,-4448,-4461,-4473,-4485,-4500,-4517,-4538,-4563,-4592,-4624,-4658,-4692,-4724,
--4753,-4775,-4791,-4798,-4798,-4789,-4774,-4753,-4731,-4708,-4688,-4673,-4666,-4667,-4677,-4697,-4727,-4763,-4805,-4850,-4896,
--4940,-4981,-5017,-5047,-5070,-5086,-5097,-5103,-5106,-5108,-5109,-5112,-5117,-5125,-5137,-5153,-5172,-5194,-5219,-5245,-5273,
--5301,-5330,-5358,-5385,-5411,-5437,-5462,-5486,-5508,-5530,-5550,-5568,-5584,-5599,-5612,-5622,-5631,-5639,-5645,-5651,-5657,
--5664,-5672,-5682,-5694,-5707,-5722,-5737,-5753,-5769,-5784,-5797,-5808,-5817,-5823,-5828,-5830,-5832,-5833,-5835,-5837,-5841,
--5847,-5855,-5864,-5875,-5887,-5898,-5909,-5919,-5927,-5933,-5936,-5937,-5935,-5930,-5922,-5910,-5893,-5872,-5844,-5810,-5768,
--5720,-5664,-5601,-5533,-5462,-5389,-5318,-5250,-5190,-5139,-5100,-5075,-5063,-5066,-5082,-5111,-5150,-5197,-5250,-5307,-5364,
--5421,-5475,-5525,-5572,-5613,-5650,-5682,-5710,-5734,-5754,-5771,-5784,-5795,-5803,-5809,-5814,-5817,-5820,-5822,-5826,-5830,
--5837,-5845,-5855,-5868,-5882,-5896,-5911,-5925,-5937,-5947,-5954,-5957,-5957,-5953,-5947,-5939,-5929,-5919,-5909,-5901,-5895,
--5892,-5892,-5895,-5901,-5910,-5921,-5934,-5948,-5964,-5980,-5996,-6013,-6030,-6047,-6065,-6083,-6102,-6120,-6138,-6155,-6172,
--6187,-6201,-6213,-6224,-6234,-6243,-6252,-6261,-6272,-6285,-6301,-6318,-6339,-6361,-6384,-6407,-6429,-6449,-6466,-6479,-6488,
--6493,-6494,-6491,-6487,-6481,-6476,-6471,-6469,-6469,-6472,-6477,-6483,-6490,-6497,-6503,-6507,-6509,-6507,-6503,-6496,-6487,
--6478,-6469,-6460,-6454,-6449,-6447,-6448,-6451,-6456,-6461,-6467,-6472,-6476,-6479,-6480,-6478,-6476,-6472,-6468,-6463,-6460,
--6457,-6456,-6456,-6457,-6459,-6462,-6465,-6467,-6468,-6468,-6466,-6462,-6456,-6450,-6442,-6435,-6427,-6420,-6415,-6410,-6408,
--6406,-6406,-6406,-6407,-6408,-6408,-6406,-6403,-6399,-6393,-6386,-6378,-6369,-6360,-6351,-6342,-6334,-6326,-6319,-6312,-6305,
--6297,-6288,-6279,-6268,-6257,-6244,-6230,-6216,-6201,-6187,-6173,-6160,-6147,-6135,-6123,-6112,-6101,-6090,-6080,-6069,-6059,
--6050,-6041,-6033,-6025,-6017,-6009,-5999,-5986,-5970,-5949,-5923,-5891,-5853,-5809,-5760,-5707,-5651,-5595,-5541,-5489,-5442,
--5400,-5364,-5332,-5305,-5281,-5259,-5237,-5213,-5188,-5160,-5129,-5096,-5062,-5028,-4995,-4965,-4937,-4913,-4892,-4873,-4857,
--4842,-4826,-4809,-4791,-4771,-4750,-4728,-4707,-4687,-4670,-4656,-4646,-4638,-4633,-4629,-4624,-4616,-4605,-4588,-4566,-4538,
--4506,-4471,-4435,-4399,-4366,-4336,-4312,-4293,-4278,-4267,-4257,-4247,-4235,-4220,-4200,-4176,-4147,-4116,-4084,-4052,-4022,
--3997,-3977,-3963,-3954,-3949,-3947,-3947,-3946,-3943,-3937,-3928,-3915,-3900,-3883,-3866,-3849,-3835,-3822,-3812,-3804,-3797,
--3789,-3781,-3769,-3755,-3737,-3717,-3697,-3676,-3658,-3645,-3639,-3639,-3648,-3665,-3688,-3715,-3745,-3773,-3797,-3815,-3823,
--3822,-3810,-3787,-3755,-3716,-3672,-3625,-3577,-3531,-3488,-3449,-3414,-3384,-3356,-3332,-3308,-3286,-3262,-3238,-3211,-3183,
--3154,-3124,-3094,-3064,-3036,-3011,-2987,-2967,-2949,-2934,-2921,-2910,-2899,-2887,-2876,-2863,-2848,-2832,-2814,-2795,-2775,
--2756,-2737,-2719,-2703,-2689,-2677,-2668,-2662,-2658,-2655,-2653,-2651,-2649,-2646,-2642,-2637,-2629,-2620,-2608,-2595,-2581,
--2565,-2549,-2532,-2514,-2497,-2480,-2463,-2447,-2431,-2414,-2397,-2379,-2359,-2337,-2312,-2286,-2256,-2225,-2192,-2159,-2127,
--2096,-2068,-2043,-2023,-2007,-1995,-1986,-1980,-1975,-1971,-1966,-1959,-1949,-1937,-1923,-1907,-1890,-1874,-1859,-1847,-1838,
--1832,-1829,-1828,-1828,-1829,-1829,-1826,-1821,-1813,-1802,-1788,-1772,-1755,-1738,-1721,-1705,-1691,-1678,-1668,-1658,-1650,
--1643,-1636,-1629,-1622,-1614,-1607,-1600,-1593,-1585,-1577,-1568,-1557,-1545,-1529,-1512,-1492,-1470,-1447,-1424,-1402,-1382,
--1366,-1354,-1346,-1343,-1343,-1345,-1349,-1351,-1351,-1346,-1337,-1321,-1299,-1270,-1237,-1199,-1159,-1116,-1073,-1030,-987,
--947,-907,-869,-832,-797,-763,-730,-699,-671,-645,-622,-603,-588,-576,-568,-561,-557,-552,-548,-541,-532,
--519,-503,-483,-460,-434,-406,-376,-347,-319,-294,-272,-255,-244,-240,-245,-258,-280,-311,-351,-400,-455,
--516,-580,-645,-708,-768,-821,-866,-902,-927,-942,-947,-944,-935,-922,-906,-891,-877,-868,-862,-861,-863,
--869,-876,-884,-890,-895,-897,-895,-890,-882,-872,-860,-849,-838,-829,-821,-814,-810,-805,-801,-797,-792,
--785,-776,-766,-755,-743,-732,-721,-712,-704,-697,-692,-689,-686,-683,-679,-675,-670,-664,-658,-650,-643,
--636,-629,-624,-619,-615,-611,-607,-602,-596,-589,-581,-571,-560,-548,-537,-525,-514,-504,-496,-488,-481,
--474,-468,-461,-454,-447,-438,-430,-421,-411,-402,-394,-386,-379,-371,-364,-357,-349,-341,-331,-321,-310,
--299,-288,-277,-267,-256,-246,-237,-227,-217,-206,-193,-180,-165,-149,-132,-114,-98,-82,-67,-54,-43,
--35,-28,-22,-18,-16,-14,-12,-12,-13,-16,-20,-25,-33,-42,-52,-63,-74,-84,-92,-99,-103,
--104,-103,-100,-96,-91,-86,-83,-80,-80,-80,-81,-82,-83,-83,-81,-77,-71,-62,-53,-42,-30,
--20,-10,-2,3,8,11,13,14,16,19,22,27,34,43,54,67,82,100,120,144,170,
-199,232,267,305,344,383,422,459,492,522,547,567,582,594,603,611,619,630,644,663,687,
-716,750,786,824,863,899,932,961,985,1004,1019,1031,1040,1049,1059,1072,1089,1109,1133,1161,1190,
-1220,1249,1276,1298,1315,1327,1333,1335,1332,1327,1321,1314,1309,1305,1303,1301,1299,1296,1289,1278,1260,
-1236,1206,1169,1129,1087,1045,1007,968,938,916,903,901,909,928,955,989,1026,1065,1101,1133,1159,
-1178,1189,1194,1193,1189,1182,1176,1172,1172,1176,1186,1200,1219,1242,1267,1292,1316,1339,1358,1375,1388,
-1398,1406,1413,1419,1425,1433,1443,1454,1468,1483,1500,1517,1534,1550,1564,1577,1588,1597,1605,1611,1616,
-1621,1626,1632,1638,1645,1653,1660,1668,1675,1681,1685,1688,1688,1687,1685,1681,1678,1674,1671,1670,1671,
-1673,1677,1682,1689,1696,1703,1709,1714,1718,1719,1720,1718,1716,1713,1710,1707,1705,1704,1704,1704,1706,
-1708,1711,1714,1717,1720,1722,1724,1725,1725,1725,1724,1723,1720,1718,1714,1710,1706,1701,1696,1691,1686,
-1680,1675,1671,1666,1661,1655,1650,1644,1637,1630,1624,1617,1612,1608,1605,1605,1608,1613,1620,1628,1637,
-1646,1654,1659,1662,1661,1656,1647,1636,1622,1607,1593,1581,1571,1566,1564,1568,1577,1590,1606,1625,1644,
-1664,1682,1698,1711,1721,1726,1729,1728,1725,1721,1716,1711,1708,1707,1708,1711,1716,1722,1729,1735,1740,
-1742,1740,1734,1724,1710,1692,1672,1651,1631,1613,1600,1593,1591,1597,1609,1627,1650,1675,1701,1725,1747,
-1763,1773,1777,1775,1767,1753,1737,1718,1698,1679,1660,1643,1629,1615,1604,1593,1583,1574,1564,1555,1547,
-1539,1533,1528,1525,1523,1522,1522,1522,1520,1516,1508,1497,1481,1462,1439,1413,1387,1360,1335,1312,1294,
-1280,1270,1265,1264,1265,1269,1274,1279,1283,1288,1291,1294,1298,1303,1309,1316,1324,1333,1342,1350,1354,
-1354,1348,1336,1316,1289,1256,1218,1176,1134,1093,1056,1024,999,982,972,969,972,977,985,992,997,
-998,994,986,974,959,941,922,904,888,875,865,858,855,853,853,854,853,852,849,844,836,
-827,817,806,795,784,774,765,757,750,743,736,728,719,710,700,689,678,668,658,649,642,
-637,634,632,632,633,634,634,633,631,627,621,612,602,591,579,567,555,545,535,527,520,
-514,508,502,494,484,472,456,436,411,383,350,314,275,234,191,146,101,55,10,-34,-79,
--123,-166,-208,-249,-288,-326,-363,-397,-430,-461,-490,-517,-544,-569,-593,-618,-641,-666,-690,-715,-741,
--767,-795,-824,-855,-887,-921,-957,-995,-1035,-1075,-1116,-1156,-1196,-1234,-1269,-1303,-1333,-1362,-1388,-1413,-1438,
--1463,-1489,-1516,-1546,-1578,-1611,-1646,-1681,-1716,-1751,-1783,-1814,-1843,-1872,-1900,-1928,-1959,-1993,-2030,-2072,-2117,
--2167,-2220,-2274,-2329,-2383,-2435,-2483,-2527,-2567,-2603,-2635,-2665,-2694,-2723,-2752,-2783,-2816,-2850,-2885,-2920,-2955,
--2989,-3020,-3048,-3074,-3096,-3117,-3136,-3154,-3173,-3193,-3216,-3241,-3270,-3301,-3334,-3369,-3404,-3439,-3472,-3502,-3529,
--3552,-3571,-3587,-3598,-3607,-3614,-3620,-3626,-3632,-3640,-3651,-3664,-3681,-3700,-3723,-3748,-3776,-3805,-3835,-3865,-3894,
--3923,-3950,-3975,-3998,-4020,-4041,-4061,-4082,-4103,-4125,-4148,-4173,-4199,-4226,-4253,-4280,-4307,-4332,-4356,-4377,-4397,
--4414,-4431,-4448,-4465,-4483,-4505,-4529,-4556,-4587,-4620,-4655,-4690,-4724,-4754,-4779,-4799,-4811,-4816,-4814,-4806,-4792,
--4776,-4758,-4742,-4730,-4724,-4724,-4733,-4750,-4774,-4806,-4842,-4881,-4922,-4961,-4998,-5031,-5059,-5082,-5099,-5113,-5122,
--5130,-5137,-5145,-5154,-5165,-5179,-5196,-5215,-5237,-5260,-5285,-5309,-5334,-5359,-5382,-5405,-5427,-5449,-5470,-5492,-5513,
--5534,-5555,-5575,-5594,-5611,-5627,-5641,-5653,-5662,-5670,-5676,-5682,-5687,-5693,-5700,-5708,-5717,-5728,-5740,-5753,-5767,
--5780,-5792,-5803,-5812,-5819,-5824,-5827,-5830,-5832,-5833,-5835,-5838,-5841,-5845,-5850,-5856,-5863,-5869,-5876,-5882,-5888,
--5893,-5899,-5904,-5909,-5913,-5916,-5917,-5915,-5909,-5898,-5880,-5853,-5818,-5773,-5720,-5660,-5593,-5523,-5453,-5385,-5324,
--5272,-5232,-5206,-5194,-5198,-5216,-5246,-5287,-5334,-5386,-5439,-5491,-5539,-5582,-5619,-5649,-5674,-5693,-5708,-5720,-5730,
--5739,-5747,-5755,-5763,-5771,-5779,-5786,-5793,-5798,-5803,-5808,-5813,-5819,-5825,-5834,-5844,-5856,-5869,-5884,-5899,-5913,
--5926,-5937,-5945,-5949,-5950,-5947,-5941,-5932,-5921,-5910,-5898,-5888,-5880,-5874,-5871,-5871,-5875,-5882,-5892,-5904,-5919,
--5935,-5954,-5973,-5993,-6014,-6036,-6057,-6078,-6098,-6117,-6135,-6150,-6163,-6175,-6184,-6191,-6198,-6203,-6209,-6216,-6225,
--6236,-6250,-6266,-6285,-6306,-6328,-6349,-6370,-6388,-6404,-6416,-6424,-6428,-6429,-6427,-6423,-6419,-6414,-6411,-6409,-6409,
--6411,-6415,-6420,-6424,-6429,-6432,-6433,-6433,-6430,-6426,-6421,-6415,-6409,-6404,-6400,-6398,-6398,-6400,-6404,-6409,-6413,
--6418,-6421,-6423,-6423,-6422,-6419,-6416,-6412,-6408,-6406,-6405,-6407,-6410,-6416,-6423,-6432,-6440,-6448,-6455,-6460,-6463,
--6462,-6459,-6453,-6445,-6436,-6426,-6416,-6406,-6399,-6393,-6389,-6387,-6388,-6390,-6393,-6397,-6401,-6404,-6406,-6406,-6405,
--6401,-6395,-6388,-6379,-6369,-6359,-6349,-6338,-6328,-6319,-6310,-6301,-6292,-6284,-6275,-6267,-6258,-6248,-6239,-6229,-6220,
--6211,-6202,-6194,-6186,-6179,-6172,-6165,-6157,-6149,-6140,-6129,-6118,-6105,-6090,-6074,-6056,-6037,-6015,-5990,-5962,-5931,
--5895,-5855,-5810,-5761,-5707,-5650,-5591,-5531,-5473,-5416,-5363,-5316,-5274,-5238,-5208,-5182,-5160,-5140,-5121,-5102,-5080,
--5057,-5031,-5003,-4974,-4945,-4918,-4892,-4869,-4850,-4834,-4821,-4809,-4798,-4785,-4770,-4752,-4730,-4704,-4674,-4643,-4611,
--4580,-4552,-4528,-4510,-4497,-4490,-4488,-4488,-4490,-4492,-4492,-4488,-4481,-4469,-4453,-4433,-4411,-4388,-4364,-4341,-4318,
--4296,-4274,-4252,-4229,-4204,-4177,-4148,-4116,-4084,-4051,-4020,-3991,-3965,-3945,-3929,-3917,-3910,-3906,-3904,-3902,-3899,
--3893,-3886,-3875,-3862,-3848,-3834,-3821,-3810,-3801,-3794,-3790,-3788,-3785,-3781,-3775,-3765,-3751,-3732,-3710,-3685,-3661,
--3638,-3619,-3606,-3601,-3604,-3615,-3633,-3656,-3682,-3707,-3729,-3746,-3755,-3754,-3744,-3724,-3695,-3658,-3617,-3573,-3529,
--3486,-3446,-3409,-3377,-3348,-3323,-3300,-3278,-3257,-3235,-3211,-3187,-3160,-3133,-3105,-3077,-3051,-3025,-3002,-2981,-2962,
--2946,-2931,-2918,-2905,-2893,-2880,-2866,-2851,-2834,-2817,-2798,-2779,-2759,-2740,-2721,-2703,-2686,-2672,-2659,-2648,-2640,
--2633,-2627,-2624,-2621,-2619,-2617,-2615,-2612,-2609,-2604,-2598,-2590,-2581,-2570,-2558,-2545,-2531,-2517,-2502,-2488,-2474,
--2459,-2445,-2430,-2413,-2395,-2375,-2353,-2328,-2301,-2271,-2241,-2210,-2179,-2150,-2124,-2100,-2081,-2065,-2053,-2044,-2037,
--2031,-2026,-2019,-2011,-2000,-1988,-1973,-1957,-1941,-1924,-1909,-1896,-1885,-1877,-1871,-1867,-1864,-1861,-1858,-1854,-1847,
--1838,-1827,-1813,-1798,-1782,-1765,-1748,-1733,-1718,-1705,-1693,-1683,-1674,-1666,-1659,-1653,-1647,-1642,-1637,-1633,-1628,
--1622,-1615,-1607,-1597,-1585,-1569,-1552,-1532,-1511,-1490,-1468,-1449,-1433,-1420,-1412,-1408,-1408,-1411,-1417,-1422,-1427,
--1428,-1424,-1415,-1400,-1378,-1350,-1316,-1278,-1237,-1195,-1152,-1110,-1070,-1031,-995,-960,-927,-895,-863,-833,-803,
--774,-746,-720,-696,-674,-655,-639,-626,-615,-606,-598,-590,-581,-570,-558,-543,-525,-505,-483,-460,-437,
--416,-398,-384,-377,-376,-383,-399,-424,-458,-500,-549,-603,-661,-720,-778,-833,-883,-926,-960,-985,-1001,
--1008,-1008,-1001,-990,-977,-963,-950,-939,-932,-928,-927,-930,-934,-940,-944,-948,-950,-949,-946,-940,-933,
--924,-916,-907,-900,-895,-891,-888,-885,-883,-881,-877,-871,-864,-855,-845,-834,-822,-811,-801,-793,-787,
--783,-780,-779,-778,-777,-775,-772,-768,-762,-755,-747,-738,-729,-721,-714,-708,-703,-698,-694,-689,-683,
--676,-668,-657,-645,-632,-618,-604,-590,-577,-566,-555,-546,-538,-530,-523,-515,-507,-498,-488,-478,-466,
--454,-442,-430,-418,-407,-396,-385,-375,-365,-355,-345,-334,-323,-312,-301,-290,-280,-270,-260,-250,-241,
--232,-222,-212,-201,-189,-177,-164,-152,-139,-127,-117,-107,-98,-91,-85,-80,-75,-71,-68,-66,-65,
--65,-66,-68,-73,-79,-87,-95,-105,-114,-122,-129,-133,-135,-134,-131,-126,-119,-111,-104,-97,-92,
--89,-87,-87,-89,-91,-92,-93,-93,-91,-87,-81,-73,-65,-56,-48,-40,-34,-29,-26,-25,-25,
--25,-26,-26,-24,-21,-15,-7,5,21,41,66,95,128,165,205,248,292,336,379,420,457,
-491,519,542,560,574,585,595,605,617,633,653,679,710,746,787,829,873,916,955,990,1020,
-1044,1061,1073,1081,1086,1089,1093,1099,1108,1120,1135,1153,1172,1191,1209,1224,1235,1242,1244,1242,1236,
-1228,1218,1209,1202,1197,1196,1196,1199,1202,1204,1203,1198,1187,1169,1144,1114,1079,1041,1003,968,925,
-898,876,860,853,854,863,879,901,926,953,980,1005,1026,1043,1055,1062,1065,1065,1064,1062,1062,
-1063,1068,1076,1087,1101,1118,1137,1156,1175,1193,1209,1223,1235,1245,1254,1261,1268,1276,1283,1292,1302,
-1313,1326,1339,1353,1367,1380,1393,1404,1415,1425,1433,1441,1448,1456,1463,1472,1480,1490,1500,1511,1521,
-1532,1542,1550,1558,1565,1570,1574,1577,1579,1581,1583,1585,1588,1592,1596,1601,1606,1612,1618,1623,1628,
-1632,1635,1638,1640,1642,1644,1645,1647,1649,1651,1654,1657,1661,1665,1669,1673,1677,1681,1684,1688,1691,
-1694,1696,1698,1699,1700,1700,1698,1696,1693,1688,1682,1675,1666,1657,1646,1635,1622,1609,1596,1582,1568,
-1555,1542,1531,1521,1514,1510,1509,1511,1517,1526,1537,1551,1565,1580,1592,1602,1609,1611,1607,1599,1586,
-1568,1548,1526,1504,1483,1466,1454,1447,1446,1451,1462,1478,1498,1521,1544,1567,1587,1603,1615,1622,1623,
-1620,1613,1603,1591,1580,1570,1562,1558,1557,1560,1565,1572,1579,1585,1589,1589,1586,1578,1565,1550,1532,
-1514,1498,1485,1477,1476,1481,1494,1512,1536,1562,1590,1617,1641,1659,1672,1678,1677,1671,1659,1644,1626,
-1608,1591,1575,1562,1550,1541,1533,1525,1517,1508,1498,1486,1473,1458,1444,1430,1417,1405,1396,1388,1382,
-1377,1373,1367,1360,1351,1339,1324,1307,1287,1267,1246,1226,1208,1193,1182,1175,1173,1175,1180,1189,1200,
-1213,1227,1242,1256,1270,1283,1294,1303,1310,1313,1313,1307,1297,1281,1259,1232,1200,1165,1126,1087,1049,
-1012,980,953,932,917,908,903,903,904,907,908,907,902,894,883,868,852,835,818,803,792,
-783,779,777,779,782,787,790,793,793,790,785,776,766,755,743,732,722,714,708,704,701,
-699,697,695,691,686,678,670,660,649,638,629,621,615,611,610,610,612,613,614,613,610,
-604,595,584,571,557,543,530,519,511,506,504,504,505,505,504,499,490,473,450,418,379,
-333,282,226,167,108,51,-4,-56,-103,-145,-183,-217,-247,-274,-300,-325,-350,-375,-401,-427,-454,
--481,-509,-536,-563,-589,-614,-638,-661,-684,-706,-728,-751,-774,-798,-824,-851,-881,-912,-946,-982,-1020,
--1060,-1101,-1142,-1182,-1222,-1260,-1295,-1329,-1359,-1387,-1413,-1438,-1462,-1486,-1511,-1537,-1565,-1594,-1625,-1658,-1691,
--1724,-1756,-1788,-1818,-1847,-1876,-1904,-1933,-1964,-1996,-2032,-2071,-2113,-2159,-2207,-2257,-2307,-2357,-2405,-2452,-2495,
--2535,-2572,-2607,-2639,-2671,-2702,-2733,-2764,-2796,-2829,-2863,-2896,-2929,-2961,-2991,-3020,-3047,-3072,-3096,-3120,-3144,
--3168,-3194,-3221,-3250,-3280,-3311,-3344,-3375,-3406,-3435,-3463,-3488,-3510,-3529,-3546,-3561,-3575,-3587,-3598,-3609,-3619,
--3629,-3639,-3650,-3661,-3672,-3684,-3697,-3711,-3728,-3745,-3765,-3788,-3813,-3840,-3869,-3900,-3932,-3964,-3996,-4026,-4056,
--4083,-4108,-4130,-4150,-4169,-4185,-4200,-4214,-4227,-4241,-4255,-4270,-4287,-4305,-4326,-4349,-4375,-4405,-4437,-4472,-4509,
--4549,-4590,-4631,-4671,-4709,-4744,-4775,-4801,-4821,-4835,-4844,-4847,-4846,-4842,-4837,-4832,-4828,-4827,-4830,-4838,-4850,
--4867,-4888,-4912,-4938,-4964,-4990,-5015,-5038,-5058,-5076,-5092,-5107,-5121,-5135,-5151,-5168,-5187,-5208,-5230,-5255,-5280,
--5305,-5330,-5354,-5376,-5396,-5414,-5430,-5446,-5460,-5475,-5491,-5507,-5525,-5544,-5565,-5586,-5607,-5629,-5649,-5667,-5684,
--5698,-5709,-5719,-5726,-5732,-5737,-5742,-5747,-5753,-5759,-5765,-5773,-5780,-5787,-5794,-5801,-5806,-5810,-5814,-5816,-5817,
--5818,-5819,-5819,-5819,-5819,-5819,-5819,-5818,-5817,-5816,-5814,-5813,-5813,-5814,-5816,-5820,-5826,-5833,-5842,-5850,-5857,
--5860,-5859,-5852,-5837,-5814,-5781,-5741,-5692,-5639,-5583,-5527,-5475,-5429,-5393,-5369,-5357,-5359,-5375,-5402,-5439,-5482,
--5529,-5577,-5623,-5663,-5698,-5725,-5744,-5756,-5762,-5763,-5761,-5757,-5753,-5751,-5750,-5752,-5756,-5762,-5770,-5779,-5787,
--5796,-5804,-5812,-5819,-5827,-5835,-5843,-5852,-5862,-5873,-5885,-5896,-5907,-5916,-5924,-5929,-5931,-5930,-5926,-5920,-5911,
--5901,-5890,-5880,-5870,-5863,-5857,-5854,-5854,-5857,-5863,-5872,-5883,-5898,-5914,-5933,-5954,-5976,-5999,-6023,-6046,-6068,
--6089,-6107,-6123,-6136,-6146,-6153,-6157,-6160,-6162,-6163,-6166,-6171,-6178,-6188,-6201,-6216,-6234,-6252,-6271,-6288,-6303,
--6316,-6324,-6329,-6330,-6328,-6324,-6318,-6312,-6306,-6302,-6300,-6300,-6301,-6305,-6309,-6314,-6318,-6321,-6323,-6322,-6320,
--6316,-6312,-6307,-6303,-6301,-6300,-6301,-6304,-6309,-6315,-6322,-6328,-6333,-6336,-6337,-6336,-6334,-6330,-6326,-6323,-6321,
--6321,-6325,-6331,-6341,-6354,-6369,-6386,-6402,-6418,-6431,-6442,-6449,-6452,-6452,-6447,-6441,-6432,-6422,-6412,-6403,-6395,
--6390,-6386,-6384,-6384,-6385,-6387,-6389,-6391,-6391,-6390,-6388,-6384,-6379,-6372,-6365,-6357,-6349,-6341,-6334,-6327,-6321,
--6315,-6309,-6303,-6296,-6290,-6283,-6276,-6268,-6260,-6253,-6246,-6240,-6235,-6231,-6228,-6225,-6223,-6220,-6217,-6211,-6204,
--6193,-6178,-6160,-6138,-6111,-6080,-6046,-6008,-5967,-5923,-5876,-5828,-5778,-5726,-5672,-5618,-5563,-5508,-5455,-5403,-5353,
--5307,-5265,-5228,-5196,-5168,-5145,-5124,-5106,-5088,-5069,-5049,-5026,-4999,-4970,-4937,-4903,-4868,-4834,-4802,-4773,-4748,
--4728,-4711,-4697,-4686,-4674,-4662,-4647,-4628,-4605,-4577,-4546,-4512,-4478,-4444,-4414,-4388,-4369,-4356,-4350,-4350,-4356,
--4366,-4378,-4391,-4401,-4409,-4413,-4412,-4406,-4395,-4380,-4361,-4338,-4311,-4283,-4252,-4219,-4184,-4147,-4110,-4072,-4035,
--4000,-3966,-3937,-3912,-3892,-3877,-3867,-3861,-3859,-3858,-3858,-3857,-3853,-3847,-3838,-3826,-3812,-3796,-3781,-3768,-3757,
--3749,-3745,-3743,-3744,-3746,-3747,-3746,-3741,-3733,-3719,-3701,-3679,-3656,-3632,-3610,-3592,-3578,-3571,-3571,-3577,-3588,
--3603,-3620,-3636,-3649,-3657,-3659,-3654,-3641,-3621,-3595,-3565,-3530,-3494,-3458,-3421,-3387,-3354,-3323,-3294,-3267,-3241,
--3216,-3191,-3166,-3142,-3118,-3095,-3073,-3053,-3034,-3017,-3001,-2987,-2975,-2963,-2951,-2939,-2926,-2912,-2896,-2880,-2862,
--2844,-2825,-2806,-2788,-2770,-2753,-2737,-2723,-2710,-2697,-2686,-2676,-2666,-2658,-2650,-2642,-2635,-2629,-2623,-2618,-2613,
--2607,-2602,-2596,-2590,-2582,-2574,-2564,-2553,-2541,-2529,-2516,-2502,-2488,-2474,-2459,-2444,-2428,-2411,-2393,-2374,-2354,
--2332,-2310,-2287,-2263,-2240,-2218,-2198,-2179,-2163,-2149,-2137,-2127,-2118,-2109,-2100,-2090,-2079,-2067,-2054,-2039,-2024,
--2008,-1993,-1979,-1966,-1955,-1945,-1936,-1928,-1920,-1912,-1903,-1892,-1880,-1866,-1850,-1834,-1816,-1799,-1782,-1766,-1751,
--1739,-1728,-1720,-1713,-1709,-1705,-1704,-1703,-1702,-1702,-1702,-1701,-1700,-1697,-1692,-1684,-1674,-1662,-1646,-1629,-1610,
--1589,-1569,-1551,-1534,-1522,-1514,-1510,-1511,-1515,-1523,-1532,-1542,-1549,-1552,-1551,-1543,-1528,-1507,-1479,-1445,-1407,
--1366,-1324,-1282,-1241,-1202,-1166,-1133,-1101,-1072,-1043,-1015,-987,-959,-929,-899,-869,-839,-809,-780,-753,-727,
--703,-682,-662,-643,-625,-607,-589,-571,-553,-535,-519,-504,-493,-486,-484,-490,-504,-526,-556,-596,-642,
--695,-752,-812,-871,-927,-979,-1024,-1060,-1087,-1103,-1110,-1107,-1097,-1081,-1061,-1039,-1018,-1000,-985,-975,-970,
--969,-973,-979,-987,-995,-1002,-1007,-1009,-1008,-1004,-998,-991,-982,-974,-967,-961,-958,-956,-956,-957,-957,
--957,-955,-951,-945,-937,-927,-915,-904,-892,-882,-874,-868,-864,-863,-863,-864,-865,-865,-864,-862,-858,
--851,-843,-834,-825,-815,-806,-797,-790,-783,-777,-770,-764,-756,-747,-737,-725,-712,-698,-684,-669,-656,
--643,-631,-621,-612,-603,-595,-587,-578,-569,-558,-546,-533,-519,-505,-491,-477,-464,-452,-440,-430,-420,
--411,-402,-393,-383,-374,-364,-354,-345,-335,-325,-316,-307,-299,-291,-283,-275,-268,-259,-251,-243,-234,
--226,-218,-210,-203,-197,-191,-186,-181,-177,-174,-171,-169,-168,-168,-168,-170,-173,-177,-182,-187,-193,
--199,-203,-207,-208,-207,-204,-199,-192,-183,-174,-165,-156,-149,-143,-140,-138,-137,-138,-139,-140,-141,
--140,-139,-135,-130,-124,-117,-109,-102,-95,-89,-84,-80,-77,-75,-74,-72,-70,-66,-60,-52,-40,
--24,-5,18,46,77,112,150,190,230,271,311,348,383,414,442,467,488,508,526,545,565,
-588,614,644,678,715,756,798,840,881,919,953,981,1004,1020,1031,1037,1039,1039,1039,1039,1041,
-1045,1053,1062,1074,1086,1097,1107,1115,1119,1119,1116,1109,1101,1091,1082,1074,1069,1067,1069,1073,1080,
-1088,1095,1099,1100,1096,1085,1069,1046,1019,988,956,925,897,872,850,831,818,810,807,810,817,
-828,841,856,871,885,898,908,917,924,929,933,937,941,945,951,958,966,976,987,999,1012,
-1025,1038,1051,1064,1076,1088,1099,1109,1119,1129,1138,1147,1156,1166,1175,1184,1193,1203,1212,1222,1231,
-1241,1252,1262,1273,1284,1295,1307,1319,1331,1343,1354,1365,1376,1386,1395,1404,1412,1420,1427,1434,1441,
-1447,1454,1461,1468,1475,1482,1489,1495,1502,1508,1514,1519,1524,1529,1533,1538,1543,1549,1555,1562,1569,
-1577,1585,1593,1600,1607,1614,1620,1625,1629,1632,1635,1637,1639,1640,1642,1643,1645,1646,1646,1646,1645,
-1643,1639,1633,1625,1615,1602,1587,1570,1551,1530,1509,1487,1465,1444,1424,1407,1393,1382,1375,1373,1375,
-1382,1393,1407,1424,1443,1462,1480,1495,1507,1514,1516,1511,1502,1486,1467,1445,1421,1397,1376,1358,1345,
-1339,1339,1346,1359,1378,1401,1425,1451,1474,1495,1510,1520,1524,1521,1513,1501,1485,1468,1451,1436,1424,
-1416,1412,1412,1415,1420,1425,1430,1433,1433,1430,1423,1413,1401,1388,1376,1368,1363,1364,1372,1385,1405,
-1429,1457,1486,1514,1539,1561,1576,1586,1589,1587,1580,1569,1557,1543,1530,1518,1508,1500,1493,1486,1479,
-1470,1460,1446,1430,1411,1390,1367,1345,1323,1302,1285,1270,1259,1250,1244,1239,1235,1229,1223,1214,1202,
-1188,1172,1155,1137,1120,1105,1094,1087,1085,1088,1098,1113,1132,1156,1182,1210,1238,1264,1287,1305,1319,
-1325,1324,1316,1299,1275,1244,1207,1166,1121,1075,1031,988,950,917,890,870,856,848,844,843,843,
-844,842,838,830,818,802,784,764,744,725,708,694,685,680,678,680,684,689,694,697,698,
-697,692,685,676,665,655,646,638,633,631,630,632,635,638,640,640,639,635,628,619,609,
-599,590,582,576,573,573,575,578,581,584,584,582,576,566,553,538,521,504,490,478,471,
-469,472,478,488,498,506,510,507,495,473,438,392,335,268,194,115,35,-43,-118,-186,-246,
--297,-339,-372,-397,-415,-429,-440,-449,-459,-470,-483,-499,-518,-538,-561,-585,-610,-634,-659,-683,-706,
--728,-750,-771,-793,-814,-837,-861,-886,-913,-942,-972,-1005,-1040,-1076,-1113,-1151,-1190,-1228,-1265,-1301,-1336,
--1369,-1401,-1431,-1459,-1487,-1514,-1541,-1568,-1595,-1623,-1652,-1680,-1709,-1738,-1766,-1795,-1822,-1850,-1877,-1905,-1933,
--1964,-1996,-2030,-2067,-2107,-2149,-2193,-2239,-2286,-2333,-2380,-2426,-2470,-2512,-2553,-2593,-2631,-2667,-2703,-2738,-2772,
--2806,-2839,-2871,-2903,-2933,-2962,-2991,-3019,-3046,-3073,-3100,-3128,-3156,-3186,-3216,-3247,-3279,-3310,-3340,-3370,-3397,
--3422,-3445,-3465,-3484,-3501,-3516,-3531,-3546,-3561,-3577,-3592,-3608,-3622,-3636,-3647,-3657,-3665,-3670,-3673,-3676,-3679,
--3682,-3689,-3699,-3713,-3734,-3759,-3790,-3826,-3866,-3907,-3949,-3990,-4028,-4062,-4090,-4114,-4131,-4143,-4151,-4155,-4158,
--4161,-4165,-4171,-4181,-4196,-4216,-4240,-4270,-4305,-4343,-4385,-4429,-4475,-4523,-4570,-4616,-4662,-4705,-4745,-4783,-4816,
--4846,-4871,-4892,-4909,-4922,-4932,-4939,-4943,-4947,-4950,-4952,-4956,-4960,-4966,-4973,-4981,-4991,-5001,-5012,-5024,-5036,
--5050,-5064,-5080,-5097,-5116,-5138,-5162,-5188,-5216,-5245,-5276,-5306,-5336,-5364,-5389,-5412,-5431,-5447,-5460,-5471,-5480,
--5489,-5498,-5509,-5521,-5535,-5553,-5572,-5594,-5617,-5641,-5665,-5687,-5707,-5725,-5740,-5752,-5761,-5768,-5772,-5775,-5776,
--5778,-5779,-5780,-5782,-5785,-5788,-5792,-5795,-5798,-5801,-5803,-5804,-5804,-5803,-5800,-5797,-5792,-5785,-5778,-5770,-5761,
--5753,-5744,-5736,-5730,-5726,-5725,-5727,-5732,-5740,-5750,-5761,-5773,-5784,-5792,-5795,-5793,-5784,-5767,-5743,-5713,-5677,
--5639,-5599,-5562,-5529,-5504,-5488,-5482,-5489,-5506,-5533,-5569,-5610,-5654,-5699,-5741,-5777,-5807,-5829,-5842,-5847,-5845,
--5837,-5825,-5812,-5797,-5785,-5774,-5768,-5765,-5765,-5769,-5776,-5785,-5796,-5807,-5818,-5830,-5841,-5851,-5861,-5870,-5880,
--5888,-5896,-5903,-5909,-5913,-5915,-5915,-5913,-5909,-5903,-5895,-5887,-5877,-5867,-5858,-5850,-5844,-5839,-5836,-5836,-5838,
--5842,-5849,-5859,-5871,-5885,-5902,-5921,-5942,-5964,-5988,-6012,-6035,-6057,-6078,-6096,-6110,-6121,-6129,-6133,-6134,-6134,
--6133,-6131,-6131,-6133,-6138,-6145,-6155,-6167,-6180,-6194,-6207,-6218,-6226,-6231,-6232,-6229,-6223,-6215,-6205,-6195,-6185,
--6178,-6173,-6170,-6171,-6173,-6178,-6184,-6189,-6194,-6198,-6200,-6200,-6199,-6196,-6193,-6191,-6189,-6189,-6190,-6193,-6198,
--6204,-6211,-6217,-6222,-6226,-6227,-6227,-6225,-6223,-6220,-6218,-6219,-6223,-6230,-6242,-6258,-6277,-6300,-6324,-6348,-6371,
--6392,-6409,-6423,-6431,-6435,-6436,-6432,-6427,-6420,-6413,-6407,-6402,-6398,-6396,-6396,-6397,-6397,-6398,-6397,-6395,-6391,
--6385,-6377,-6367,-6357,-6347,-6337,-6329,-6322,-6317,-6314,-6313,-6312,-6313,-6314,-6313,-6312,-6308,-6303,-6295,-6286,-6275,
--6263,-6251,-6239,-6228,-6219,-6211,-6205,-6199,-6194,-6188,-6181,-6171,-6157,-6139,-6116,-6087,-6052,-6012,-5966,-5917,-5865,
--5810,-5753,-5697,-5640,-5585,-5532,-5481,-5432,-5386,-5344,-5305,-5269,-5237,-5209,-5184,-5163,-5144,-5127,-5112,-5096,-5079,
--5060,-5037,-5010,-4979,-4943,-4904,-4861,-4816,-4770,-4726,-4685,-4647,-4613,-4585,-4562,-4543,-4527,-4513,-4499,-4485,-4468,
--4448,-4425,-4399,-4371,-4342,-4313,-4286,-4262,-4243,-4230,-4224,-4223,-4228,-4238,-4251,-4266,-4281,-4294,-4305,-4312,-4315,
--4311,-4303,-4288,-4268,-4243,-4213,-4179,-4141,-4101,-4059,-4017,-3976,-3937,-3902,-3871,-3846,-3827,-3815,-3808,-3807,-3810,
--3815,-3821,-3827,-3829,-3829,-3823,-3814,-3800,-3783,-3765,-3746,-3729,-3715,-3704,-3699,-3697,-3700,-3705,-3712,-3718,-3722,
--3722,-3717,-3707,-3693,-3674,-3652,-3628,-3605,-3583,-3565,-3552,-3543,-3540,-3541,-3545,-3552,-3560,-3567,-3571,-3572,-3569,
--3560,-3546,-3527,-3504,-3476,-3445,-3412,-3377,-3341,-3305,-3270,-3235,-3202,-3170,-3141,-3115,-3091,-3070,-3053,-3038,-3027,
--3017,-3010,-3004,-2998,-2992,-2984,-2975,-2964,-2950,-2935,-2917,-2897,-2877,-2857,-2838,-2819,-2802,-2788,-2775,-2764,-2754,
--2746,-2738,-2730,-2722,-2713,-2703,-2693,-2681,-2670,-2658,-2646,-2635,-2624,-2614,-2605,-2596,-2588,-2580,-2572,-2563,-2554,
--2544,-2533,-2521,-2508,-2495,-2482,-2468,-2454,-2441,-2427,-2414,-2400,-2387,-2374,-2360,-2347,-2333,-2320,-2306,-2292,-2279,
--2265,-2252,-2238,-2224,-2210,-2196,-2181,-2166,-2151,-2135,-2120,-2105,-2090,-2076,-2064,-2052,-2042,-2032,-2022,-2013,-2003,
--1992,-1979,-1965,-1950,-1933,-1914,-1895,-1875,-1856,-1838,-1821,-1806,-1793,-1783,-1775,-1770,-1766,-1765,-1765,-1766,-1768,
--1770,-1772,-1773,-1773,-1772,-1770,-1765,-1757,-1748,-1736,-1721,-1705,-1689,-1672,-1655,-1641,-1630,-1623,-1620,-1621,-1627,
--1636,-1648,-1660,-1672,-1681,-1686,-1685,-1678,-1664,-1642,-1615,-1581,-1544,-1504,-1463,-1423,-1384,-1348,-1316,-1286,-1259,
--1235,-1211,-1188,-1164,-1138,-1110,-1079,-1045,-1009,-971,-932,-892,-852,-813,-775,-739,-705,-673,-644,-617,-593,
--572,-555,-543,-536,-537,-545,-562,-588,-623,-668,-722,-783,-850,-920,-990,-1058,-1122,-1177,-1222,-1256,-1276,
--1284,-1279,-1264,-1239,-1208,-1173,-1137,-1102,-1072,-1047,-1030,-1019,-1015,-1018,-1025,-1035,-1046,-1057,-1066,-1072,-1075,
--1075,-1071,-1065,-1057,-1049,-1042,-1036,-1031,-1029,-1029,-1030,-1031,-1032,-1032,-1031,-1027,-1021,-1013,-1004,-993,-982,
--971,-962,-954,-948,-944,-943,-942,-942,-942,-942,-941,-937,-933,-926,-919,-910,-901,-891,-882,-873,-864,
--856,-848,-840,-831,-822,-811,-800,-788,-775,-761,-748,-735,-723,-712,-702,-692,-683,-675,-666,-657,-647,
--636,-624,-611,-597,-582,-568,-554,-541,-529,-519,-509,-501,-494,-487,-480,-473,-465,-457,-448,-438,-429,
--419,-410,-401,-393,-386,-380,-374,-369,-365,-360,-356,-352,-347,-343,-338,-334,-330,-327,-324,-321,-319,
--317,-316,-315,-314,-314,-313,-312,-312,-311,-311,-311,-310,-309,-308,-306,-303,-299,-293,-287,-279,-271,
--262,-252,-243,-235,-228,-222,-218,-216,-216,-216,-218,-220,-222,-223,-223,-221,-218,-213,-207,-199,-190,
--180,-170,-160,-150,-141,-133,-125,-118,-110,-103,-94,-84,-72,-57,-40,-20,2,28,56,86,119,
-152,185,219,251,282,312,340,368,394,421,448,476,507,539,574,611,650,691,731,770,807,
-841,870,894,913,926,934,939,940,940,939,938,939,942,948,956,965,975,985,994,1001,1004,
-1005,1002,997,989,981,972,965,960,958,959,964,972,983,994,1005,1014,1019,1020,1016,1007,992,
-972,949,923,897,855,834,815,797,782,770,762,757,756,757,762,768,776,786,795,806,816,
-826,835,844,853,862,869,877,884,891,898,906,913,921,930,939,950,961,973,986,1000,1013,
-1027,1040,1053,1064,1075,1084,1092,1100,1106,1113,1119,1126,1134,1143,1153,1164,1177,1191,1206,1221,1236,
-1250,1264,1276,1287,1297,1305,1312,1318,1324,1330,1336,1342,1349,1356,1365,1374,1384,1394,1404,1414,1423,
-1431,1438,1445,1450,1455,1460,1465,1471,1477,1484,1493,1503,1514,1525,1537,1549,1561,1571,1580,1587,1592,
-1595,1597,1597,1596,1595,1593,1591,1590,1589,1589,1590,1590,1591,1590,1588,1584,1577,1567,1554,1538,1519,
-1496,1472,1445,1418,1391,1365,1341,1319,1301,1288,1279,1275,1276,1281,1291,1304,1321,1338,1356,1374,1389,
-1401,1410,1414,1413,1407,1397,1383,1366,1347,1328,1310,1295,1285,1279,1278,1284,1295,1311,1330,1352,1375,
-1397,1416,1431,1441,1445,1443,1436,1425,1409,1392,1374,1358,1343,1331,1323,1319,1318,1320,1323,1326,1329,
-1331,1330,1326,1321,1314,1307,1300,1296,1295,1298,1306,1320,1338,1360,1385,1411,1437,1462,1483,1500,1512,
-1519,1522,1520,1515,1508,1500,1491,1483,1475,1468,1462,1455,1447,1437,1424,1409,1391,1370,1347,1322,1297,
-1273,1250,1229,1212,1198,1187,1179,1173,1167,1162,1156,1148,1138,1126,1112,1096,1080,1064,1050,1039,1033,
-1032,1037,1049,1066,1089,1116,1147,1179,1211,1241,1267,1288,1301,1307,1303,1290,1269,1239,1202,1160,1114,
-1066,1019,974,933,897,868,845,829,818,812,809,808,807,805,800,791,779,764,745,725,704,
-684,665,649,637,628,623,622,622,624,625,626,625,622,616,609,599,589,580,571,565,561,
-561,562,566,572,577,582,585,586,584,579,571,562,552,542,534,528,525,525,528,533,538,
-543,546,546,542,533,521,505,486,467,449,434,424,419,421,429,441,456,472,485,492,491,
-479,454,415,362,297,221,137,49,-40,-127,-208,-281,-344,-396,-437,-467,-488,-501,-509,-514,-517,
--521,-526,-534,-546,-560,-577,-597,-619,-642,-665,-689,-712,-735,-758,-780,-802,-825,-848,-871,-895,-920,
--946,-973,-1001,-1030,-1060,-1091,-1124,-1157,-1192,-1227,-1263,-1299,-1336,-1372,-1408,-1443,-1478,-1511,-1543,-1574,-1603,
--1632,-1659,-1685,-1710,-1734,-1758,-1782,-1805,-1829,-1854,-1879,-1906,-1933,-1963,-1994,-2027,-2062,-2098,-2136,-2176,-2217,
--2259,-2302,-2345,-2389,-2434,-2478,-2523,-2567,-2611,-2655,-2697,-2739,-2778,-2816,-2852,-2885,-2917,-2946,-2973,-2999,-3024,
--3049,-3075,-3102,-3130,-3160,-3192,-3224,-3257,-3291,-3323,-3354,-3382,-3408,-3431,-3451,-3469,-3484,-3499,-3513,-3528,-3543,
--3560,-3577,-3595,-3613,-3630,-3646,-3659,-3668,-3675,-3678,-3678,-3676,-3674,-3673,-3675,-3681,-3693,-3712,-3737,-3770,-3807,
--3850,-3895,-3940,-3984,-4024,-4059,-4087,-4109,-4124,-4132,-4136,-4137,-4137,-4137,-4139,-4145,-4156,-4173,-4196,-4224,-4258,
--4296,-4338,-4382,-4428,-4474,-4521,-4567,-4613,-4657,-4700,-4742,-4783,-4821,-4857,-4891,-4922,-4949,-4973,-4992,-5007,-5018,
--5024,-5027,-5028,-5026,-5022,-5018,-5015,-5012,-5011,-5012,-5016,-5022,-5032,-5045,-5061,-5080,-5102,-5127,-5154,-5184,-5215,
--5247,-5279,-5312,-5343,-5372,-5399,-5423,-5444,-5461,-5476,-5487,-5496,-5504,-5512,-5519,-5528,-5539,-5552,-5567,-5586,-5607,
--5629,-5653,-5676,-5699,-5720,-5739,-5754,-5767,-5776,-5782,-5785,-5786,-5785,-5784,-5782,-5781,-5780,-5781,-5782,-5784,-5787,
--5790,-5793,-5794,-5795,-5793,-5789,-5783,-5774,-5763,-5750,-5736,-5722,-5707,-5694,-5682,-5673,-5667,-5665,-5667,-5672,-5680,
--5691,-5703,-5715,-5726,-5734,-5739,-5738,-5731,-5718,-5699,-5675,-5648,-5619,-5590,-5563,-5542,-5527,-5521,-5524,-5537,-5559,
--5590,-5627,-5670,-5714,-5758,-5798,-5834,-5863,-5884,-5896,-5900,-5897,-5887,-5872,-5855,-5836,-5817,-5800,-5786,-5776,-5769,
--5767,-5768,-5772,-5780,-5789,-5801,-5813,-5827,-5840,-5854,-5867,-5879,-5890,-5899,-5907,-5911,-5913,-5912,-5909,-5902,-5893,
--5882,-5870,-5858,-5846,-5834,-5824,-5816,-5810,-5807,-5806,-5808,-5811,-5817,-5824,-5834,-5844,-5857,-5871,-5887,-5904,-5924,
--5944,-5966,-5989,-6011,-6032,-6052,-6068,-6082,-6093,-6100,-6104,-6105,-6104,-6102,-6100,-6098,-6099,-6101,-6105,-6112,-6120,
--6128,-6137,-6144,-6149,-6151,-6149,-6144,-6136,-6125,-6112,-6099,-6086,-6074,-6065,-6059,-6057,-6057,-6060,-6066,-6072,-6079,
--6085,-6090,-6094,-6096,-6097,-6097,-6096,-6095,-6095,-6096,-6097,-6100,-6104,-6107,-6111,-6113,-6114,-6114,-6112,-6109,-6106,
--6103,-6102,-6103,-6108,-6117,-6131,-6150,-6174,-6201,-6230,-6261,-6291,-6318,-6343,-6363,-6379,-6389,-6395,-6397,-6396,-6394,
--6391,-6388,-6386,-6387,-6388,-6392,-6396,-6400,-6403,-6405,-6404,-6401,-6395,-6386,-6375,-6363,-6351,-6339,-6329,-6322,-6317,
--6316,-6316,-6319,-6323,-6327,-6329,-6329,-6326,-6319,-6307,-6292,-6272,-6249,-6224,-6199,-6173,-6148,-6125,-6104,-6085,-6068,
--6053,-6038,-6022,-6004,-5983,-5958,-5929,-5895,-5857,-5814,-5768,-5719,-5669,-5618,-5568,-5519,-5473,-5429,-5389,-5352,-5318,
--5287,-5259,-5234,-5210,-5189,-5169,-5151,-5133,-5116,-5099,-5081,-5061,-5040,-5015,-4987,-4955,-4919,-4879,-4836,-4789,-4741,
--4692,-4644,-4598,-4556,-4518,-4484,-4456,-4432,-4413,-4397,-4382,-4369,-4355,-4340,-4322,-4303,-4281,-4258,-4234,-4210,-4187,
--4167,-4150,-4137,-4128,-4124,-4124,-4129,-4136,-4145,-4156,-4166,-4174,-4180,-4182,-4180,-4172,-4159,-4140,-4115,-4086,-4051,
--4013,-3973,-3932,-3892,-3855,-3822,-3795,-3774,-3760,-3753,-3752,-3757,-3766,-3777,-3788,-3797,-3803,-3804,-3800,-3791,-3776,
--3758,-3738,-3717,-3697,-3681,-3669,-3663,-3662,-3666,-3674,-3684,-3696,-3706,-3714,-3717,-3714,-3706,-3692,-3672,-3649,-3623,
--3596,-3571,-3549,-3530,-3517,-3509,-3506,-3507,-3512,-3518,-3525,-3531,-3534,-3533,-3527,-3515,-3497,-3473,-3444,-3410,-3373,
--3332,-3291,-3249,-3208,-3170,-3135,-3104,-3079,-3058,-3043,-3033,-3027,-3024,-3025,-3027,-3028,-3029,-3028,-3024,-3017,-3006,
--2991,-2973,-2953,-2931,-2909,-2887,-2866,-2848,-2832,-2819,-2808,-2800,-2794,-2788,-2783,-2777,-2771,-2762,-2752,-2740,-2726,
--2711,-2695,-2679,-2664,-2649,-2635,-2623,-2612,-2602,-2593,-2584,-2576,-2568,-2559,-2549,-2539,-2528,-2516,-2504,-2492,-2480,
--2469,-2458,-2448,-2439,-2431,-2423,-2415,-2407,-2399,-2390,-2381,-2370,-2357,-2343,-2327,-2310,-2292,-2273,-2253,-2234,-2214,
--2196,-2178,-2162,-2148,-2136,-2125,-2115,-2107,-2099,-2091,-2082,-2073,-2062,-2048,-2033,-2016,-1997,-1977,-1956,-1934,-1913,
--1894,-1876,-1860,-1846,-1835,-1827,-1821,-1818,-1816,-1816,-1816,-1818,-1819,-1821,-1822,-1822,-1822,-1820,-1817,-1812,-1805,
--1796,-1786,-1774,-1761,-1748,-1735,-1723,-1714,-1707,-1704,-1704,-1708,-1716,-1726,-1738,-1751,-1762,-1770,-1775,-1774,-1767,
--1753,-1733,-1707,-1677,-1643,-1607,-1572,-1538,-1506,-1478,-1453,-1433,-1415,-1399,-1385,-1370,-1353,-1333,-1309,-1280,-1246,
--1207,-1163,-1116,-1067,-1016,-965,-915,-867,-822,-781,-744,-712,-686,-665,-650,-643,-643,-651,-668,-694,-729,
--773,-825,-885,-950,-1019,-1089,-1159,-1223,-1282,-1331,-1368,-1394,-1406,-1404,-1391,-1367,-1335,-1297,-1257,-1216,-1178,
--1145,-1118,-1099,-1088,-1084,-1086,-1093,-1103,-1115,-1126,-1136,-1144,-1148,-1148,-1146,-1141,-1135,-1127,-1120,-1114,-1109,
--1106,-1104,-1104,-1104,-1104,-1104,-1102,-1100,-1095,-1089,-1082,-1074,-1065,-1056,-1047,-1040,-1033,-1028,-1023,-1019,-1016,
--1013,-1010,-1006,-1001,-995,-988,-981,-974,-965,-957,-949,-941,-933,-924,-915,-906,-896,-885,-873,-861,-849,
--836,-823,-811,-799,-788,-779,-769,-761,-753,-745,-736,-727,-716,-705,-694,-681,-669,-656,-645,-634,-624,
--616,-608,-602,-597,-591,-586,-580,-574,-567,-558,-549,-540,-530,-521,-512,-505,-498,-493,-489,-486,-485,
--483,-483,-482,-481,-480,-479,-477,-476,-474,-473,-472,-472,-472,-472,-472,-472,-472,-471,-470,-467,-463,
--459,-453,-446,-439,-431,-422,-413,-404,-395,-385,-375,-365,-354,-344,-335,-326,-317,-310,-304,-300,-297,
--296,-296,-298,-300,-302,-304,-304,-303,-300,-295,-288,-277,-265,-251,-236,-220,-204,-188,-173,-159,-146,
--135,-124,-114,-105,-95,-84,-71,-56,-39,-19,3,28,55,84,114,144,175,206,236,266,296,
-326,356,388,420,454,490,526,564,602,639,675,708,738,764,785,802,814,822,827,829,830,
-830,831,834,839,845,854,864,875,886,896,904,910,912,911,908,902,895,888,881,876,873,
-873,876,883,892,903,914,925,935,941,944,943,937,927,913,896,876,855,749,734,720,707,
-697,688,683,679,678,679,682,687,694,702,712,723,735,748,761,774,787,800,811,821,830,
-837,844,849,854,859,865,871,879,888,899,912,926,941,957,973,988,1002,1014,1025,1034,1041,
-1046,1051,1056,1060,1065,1072,1080,1090,1103,1117,1132,1149,1166,1183,1199,1215,1228,1240,1251,1259,1267,
-1273,1280,1286,1292,1299,1307,1317,1327,1337,1348,1359,1370,1380,1389,1396,1402,1408,1412,1416,1421,1425,
-1431,1438,1447,1457,1469,1482,1496,1510,1524,1536,1546,1555,1561,1565,1567,1566,1564,1561,1558,1555,1553,
-1552,1552,1553,1554,1556,1557,1557,1554,1548,1540,1527,1510,1490,1466,1439,1411,1382,1354,1327,1303,1282,
-1265,1254,1247,1245,1247,1254,1264,1276,1289,1303,1316,1327,1337,1343,1346,1346,1343,1336,1327,1316,1303,
-1291,1278,1267,1259,1253,1251,1252,1257,1266,1278,1293,1308,1324,1340,1353,1363,1370,1373,1372,1367,1358,
-1347,1334,1321,1307,1296,1286,1279,1274,1272,1272,1273,1275,1277,1279,1279,1278,1275,1272,1268,1265,1263,
-1262,1265,1271,1280,1293,1309,1326,1346,1365,1384,1402,1417,1429,1438,1443,1446,1446,1444,1440,1436,1430,
-1425,1419,1412,1405,1396,1386,1374,1359,1343,1325,1305,1284,1263,1243,1223,1206,1190,1176,1165,1156,1148,
-1140,1133,1126,1118,1109,1098,1087,1076,1064,1054,1045,1039,1037,1038,1043,1053,1066,1083,1103,1124,1145,
-1165,1183,1197,1207,1210,1207,1197,1180,1157,1127,1094,1057,1018,978,940,904,872,844,822,803,790,
-780,773,768,763,758,752,743,732,719,704,687,670,654,639,626,615,607,602,599,598,598,
-597,595,592,586,579,569,558,547,536,526,518,513,511,511,514,519,524,530,534,535,535,
-531,525,516,507,497,488,482,478,477,479,483,489,495,500,503,502,497,487,473,456,437,
-417,399,385,375,372,374,382,395,410,426,438,444,442,429,404,366,315,252,180,101,19,
--64,-144,-218,-285,-342,-390,-427,-455,-475,-489,-498,-505,-512,-519,-528,-539,-553,-570,-589,-609,-631,
--653,-676,-699,-722,-744,-767,-791,-815,-839,-865,-891,-918,-946,-974,-1002,-1031,-1060,-1089,-1119,-1149,-1180,
--1212,-1246,-1281,-1318,-1355,-1394,-1433,-1471,-1509,-1546,-1581,-1613,-1643,-1670,-1694,-1716,-1736,-1755,-1773,-1791,-1809,
--1829,-1850,-1873,-1897,-1924,-1953,-1983,-2014,-2046,-2080,-2114,-2148,-2183,-2219,-2256,-2294,-2334,-2376,-2419,-2465,-2511,
--2559,-2608,-2656,-2703,-2748,-2791,-2830,-2866,-2899,-2928,-2955,-2979,-3003,-3026,-3050,-3075,-3103,-3133,-3165,-3199,-3235,
--3270,-3306,-3340,-3372,-3401,-3427,-3449,-3469,-3487,-3503,-3518,-3534,-3550,-3566,-3584,-3602,-3620,-3638,-3655,-3670,-3683,
--3692,-3699,-3704,-3708,-3712,-3716,-3724,-3735,-3750,-3771,-3797,-3829,-3864,-3902,-3941,-3979,-4015,-4046,-4073,-4094,-4109,
--4119,-4125,-4128,-4130,-4133,-4137,-4145,-4158,-4176,-4199,-4227,-4259,-4294,-4332,-4371,-4410,-4450,-4488,-4526,-4564,-4601,
--4638,-4676,-4714,-4753,-4793,-4832,-4870,-4906,-4940,-4969,-4994,-5013,-5027,-5035,-5038,-5037,-5032,-5025,-5018,-5012,-5007,
--5005,-5007,-5014,-5024,-5039,-5058,-5081,-5106,-5134,-5163,-5193,-5224,-5255,-5285,-5314,-5342,-5369,-5394,-5417,-5438,-5458,
--5475,-5490,-5503,-5515,-5525,-5535,-5545,-5556,-5568,-5581,-5596,-5613,-5631,-5651,-5672,-5692,-5713,-5732,-5748,-5763,-5774,
--5782,-5787,-5789,-5789,-5787,-5783,-5780,-5777,-5775,-5774,-5774,-5775,-5777,-5778,-5780,-5780,-5778,-5774,-5767,-5758,-5745,
--5731,-5715,-5698,-5682,-5666,-5654,-5644,-5638,-5636,-5638,-5644,-5653,-5664,-5675,-5685,-5693,-5697,-5697,-5691,-5679,-5662,
--5640,-5614,-5587,-5559,-5534,-5512,-5497,-5489,-5490,-5500,-5519,-5547,-5581,-5620,-5663,-5707,-5749,-5788,-5821,-5849,-5868,
--5880,-5885,-5883,-5875,-5863,-5848,-5831,-5813,-5796,-5781,-5767,-5756,-5748,-5743,-5741,-5742,-5746,-5752,-5761,-5772,-5785,
--5799,-5815,-5831,-5846,-5860,-5872,-5882,-5888,-5890,-5888,-5882,-5873,-5861,-5846,-5831,-5815,-5801,-5788,-5778,-5772,-5769,
--5769,-5772,-5777,-5785,-5794,-5804,-5815,-5827,-5839,-5851,-5865,-5879,-5894,-5910,-5927,-5945,-5963,-5981,-5998,-6013,-6026,
--6036,-6044,-6049,-6052,-6053,-6053,-6052,-6052,-6053,-6054,-6058,-6062,-6068,-6073,-6078,-6082,-6083,-6082,-6077,-6070,-6060,
--6047,-6033,-6019,-6006,-5994,-5985,-5979,-5976,-5975,-5978,-5982,-5988,-5995,-6001,-6007,-6012,-6015,-6017,-6018,-6018,-6017,
--6017,-6017,-6016,-6016,-6016,-6015,-6013,-6010,-6005,-6000,-5993,-5986,-5980,-5976,-5974,-5976,-5983,-5995,-6012,-6035,-6063,
--6094,-6128,-6162,-6196,-6227,-6254,-6277,-6295,-6309,-6317,-6322,-6324,-6325,-6326,-6327,-6330,-6334,-6340,-6348,-6357,-6365,
--6373,-6379,-6383,-6384,-6381,-6377,-6370,-6361,-6353,-6344,-6337,-6332,-6330,-6329,-6329,-6330,-6331,-6330,-6326,-6318,-6305,
--6287,-6263,-6233,-6199,-6160,-6120,-6078,-6037,-5998,-5961,-5927,-5897,-5870,-5845,-5823,-5802,-5780,-5758,-5734,-5708,-5679,
--5648,-5615,-5580,-5545,-5509,-5475,-5442,-5411,-5382,-5356,-5331,-5308,-5286,-5264,-5242,-5220,-5197,-5173,-5149,-5123,-5097,
--5070,-5043,-5015,-4987,-4959,-4930,-4899,-4867,-4833,-4797,-4759,-4719,-4678,-4637,-4596,-4555,-4517,-4482,-4450,-4421,-4397,
--4377,-4359,-4345,-4332,-4320,-4307,-4293,-4278,-4261,-4241,-4220,-4196,-4172,-4148,-4125,-4104,-4086,-4071,-4060,-4053,-4051,
--4052,-4056,-4063,-4070,-4078,-4084,-4087,-4087,-4082,-4071,-4054,-4031,-4003,-3971,-3935,-3897,-3859,-3822,-3789,-3761,-3738,
--3721,-3711,-3707,-3708,-3712,-3719,-3727,-3733,-3737,-3737,-3733,-3724,-3712,-3697,-3680,-3663,-3648,-3637,-3630,-3628,-3631,
--3639,-3651,-3665,-3680,-3693,-3704,-3710,-3711,-3705,-3693,-3675,-3653,-3629,-3602,-3577,-3554,-3535,-3521,-3513,-3510,-3512,
--3517,-3526,-3534,-3542,-3547,-3547,-3542,-3531,-3512,-3486,-3454,-3417,-3375,-3331,-3286,-3242,-3200,-3163,-3130,-3104,-3085,
--3072,-3065,-3064,-3068,-3075,-3084,-3093,-3102,-3108,-3110,-3109,-3102,-3092,-3076,-3058,-3036,-3013,-2989,-2965,-2943,-2923,
--2905,-2891,-2878,-2869,-2860,-2853,-2846,-2839,-2831,-2821,-2809,-2796,-2781,-2766,-2749,-2732,-2716,-2701,-2686,-2673,-2661,
--2651,-2642,-2633,-2624,-2615,-2606,-2596,-2585,-2574,-2561,-2549,-2536,-2523,-2511,-2499,-2488,-2478,-2469,-2460,-2452,-2443,
--2434,-2424,-2412,-2400,-2385,-2369,-2351,-2331,-2311,-2290,-2270,-2250,-2231,-2214,-2199,-2185,-2174,-2165,-2157,-2150,-2143,
--2136,-2128,-2118,-2107,-2093,-2076,-2057,-2037,-2015,-1992,-1969,-1947,-1926,-1907,-1891,-1877,-1866,-1858,-1853,-1850,-1848,
--1848,-1849,-1850,-1852,-1853,-1854,-1854,-1854,-1853,-1851,-1848,-1844,-1838,-1830,-1822,-1812,-1802,-1791,-1780,-1771,-1763,
--1757,-1755,-1755,-1759,-1765,-1774,-1785,-1796,-1805,-1813,-1817,-1817,-1812,-1802,-1786,-1766,-1742,-1716,-1689,-1663,-1639,
--1618,-1601,-1588,-1579,-1574,-1570,-1567,-1563,-1556,-1545,-1528,-1505,-1475,-1439,-1397,-1350,-1299,-1246,-1192,-1140,-1090,
--1044,-1003,-968,-939,-916,-900,-891,-889,-893,-904,-922,-945,-975,-1011,-1052,-1097,-1145,-1195,-1246,-1295,-1340,
--1380,-1413,-1437,-1452,-1457,-1452,-1437,-1414,-1385,-1351,-1316,-1280,-1247,-1217,-1193,-1175,-1164,-1159,-1160,-1165,-1173,
--1183,-1193,-1202,-1210,-1214,-1216,-1214,-1210,-1204,-1197,-1190,-1182,-1175,-1170,-1165,-1162,-1160,-1159,-1159,-1158,-1158,
--1156,-1154,-1151,-1147,-1142,-1137,-1131,-1125,-1118,-1112,-1106,-1099,-1093,-1086,-1080,-1073,-1066,-1060,-1053,-1046,-1039,
--1033,-1026,-1019,-1011,-1003,-995,-985,-975,-964,-952,-939,-926,-912,-899,-886,-874,-863,-853,-843,-835,-827,
--819,-811,-803,-794,-785,-776,-767,-758,-749,-740,-733,-726,-720,-716,-712,-708,-705,-701,-697,-692,-686,
--678,-670,-662,-653,-645,-638,-631,-626,-623,-621,-620,-620,-621,-623,-624,-625,-626,-625,-625,-623,-622,
--620,-619,-618,-617,-617,-616,-616,-616,-614,-612,-609,-605,-599,-591,-583,-573,-562,-551,-540,-528,-516,
--504,-493,-480,-468,-455,-441,-428,-414,-400,-387,-375,-364,-354,-346,-340,-335,-332,-329,-327,-324,-320,
--315,-307,-296,-283,-267,-249,-229,-209,-189,-170,-153,-138,-127,-118,-112,-108,-105,-102,-99,-94,-87,
--76,-61,-42,-19,7,37,70,103,138,173,207,240,272,304,334,364,394,424,454,484,515,
-545,574,602,628,651,671,687,700,709,716,720,722,724,726,729,733,739,746,755,765,775,
-785,793,800,805,808,808,806,802,798,793,789,786,786,787,790,795,802,809,816,822,826,
-828,827,823,816,806,793,779,764,749,590,580,573,567,564,562,562,564,567,571,577,584,
-591,600,610,621,633,646,660,674,688,702,715,727,738,747,754,759,764,768,772,776,782,
-789,797,808,821,835,851,867,882,898,911,923,933,940,945,948,950,952,954,956,961,967,
-976,988,1002,1019,1038,1058,1078,1099,1119,1138,1155,1171,1185,1197,1208,1218,1228,1237,1246,1256,1266,
-1276,1286,1296,1305,1314,1323,1330,1336,1341,1345,1349,1353,1358,1364,1371,1379,1390,1402,1415,1430,1445,
-1460,1474,1486,1497,1506,1512,1517,1519,1520,1519,1519,1518,1518,1519,1520,1523,1525,1528,1529,1528,1525,
-1518,1507,1492,1472,1448,1421,1392,1362,1332,1304,1279,1258,1242,1231,1226,1226,1231,1240,1253,1267,1281,
-1295,1308,1317,1324,1327,1327,1323,1316,1307,1296,1285,1273,1262,1251,1243,1236,1231,1229,1229,1232,1236,
-1241,1248,1256,1264,1272,1279,1285,1290,1293,1293,1292,1290,1285,1279,1272,1265,1258,1251,1244,1239,1235,
-1233,1231,1230,1230,1230,1230,1229,1229,1227,1225,1223,1221,1220,1219,1219,1222,1226,1232,1239,1249,1260,
-1271,1284,1296,1308,1318,1328,1336,1342,1347,1350,1351,1351,1349,1346,1341,1335,1328,1319,1309,1297,1284,
-1270,1256,1240,1224,1209,1193,1178,1164,1151,1139,1128,1118,1109,1101,1093,1087,1081,1076,1072,1069,1068,
-1068,1070,1073,1077,1083,1090,1097,1104,1111,1117,1121,1123,1123,1119,1113,1103,1089,1072,1052,1030,1005,
-978,951,922,894,867,841,816,794,774,757,742,728,717,707,697,687,677,667,655,643,629,
-616,602,590,578,568,560,555,552,550,550,551,552,552,551,547,542,534,524,513,500,488,
-476,466,459,454,452,452,455,458,462,466,468,468,466,462,456,448,440,433,426,422,420,
-421,425,431,437,444,449,452,451,447,438,427,412,397,381,367,356,349,347,350,357,368,
-380,391,398,400,394,379,353,316,269,213,149,81,10,-59,-126,-188,-244,-292,-333,-366,-392,
--413,-430,-445,-459,-474,-489,-507,-526,-547,-569,-592,-615,-639,-662,-684,-706,-727,-749,-771,-794,-819,
--844,-872,-901,-932,-964,-996,-1029,-1062,-1095,-1129,-1162,-1196,-1230,-1265,-1301,-1338,-1377,-1416,-1456,-1496,-1535,
--1572,-1607,-1639,-1668,-1693,-1713,-1730,-1744,-1756,-1766,-1775,-1785,-1796,-1810,-1826,-1845,-1868,-1893,-1920,-1950,-1980,
--2012,-2044,-2075,-2107,-2139,-2171,-2204,-2238,-2274,-2313,-2354,-2397,-2444,-2492,-2542,-2592,-2641,-2689,-2735,-2778,-2816,
--2852,-2883,-2911,-2937,-2962,-2986,-3011,-3038,-3067,-3099,-3133,-3170,-3209,-3249,-3288,-3327,-3363,-3397,-3428,-3455,-3478,
--3499,-3518,-3534,-3550,-3566,-3582,-3599,-3616,-3634,-3653,-3672,-3690,-3708,-3725,-3741,-3757,-3772,-3788,-3804,-3822,-3842,
--3864,-3888,-3914,-3941,-3968,-3995,-4020,-4043,-4061,-4077,-4088,-4095,-4099,-4101,-4103,-4105,-4110,-4118,-4130,-4147,-4170,
--4197,-4228,-4262,-4298,-4335,-4371,-4405,-4438,-4468,-4497,-4524,-4551,-4579,-4608,-4639,-4672,-4709,-4747,-4787,-4828,-4868,
--4905,-4939,-4967,-4990,-5006,-5016,-5021,-5020,-5017,-5011,-5006,-5002,-5000,-5003,-5011,-5024,-5042,-5064,-5090,-5119,-5149,
--5181,-5212,-5242,-5271,-5298,-5324,-5348,-5371,-5393,-5414,-5434,-5454,-5473,-5491,-5509,-5526,-5542,-5557,-5571,-5585,-5597,
--5610,-5623,-5636,-5651,-5665,-5681,-5697,-5714,-5730,-5746,-5760,-5772,-5782,-5789,-5794,-5796,-5795,-5792,-5788,-5783,-5778,
--5774,-5769,-5766,-5763,-5761,-5759,-5756,-5753,-5747,-5740,-5731,-5719,-5706,-5692,-5677,-5662,-5649,-5638,-5630,-5625,-5625,
--5628,-5634,-5642,-5651,-5660,-5666,-5669,-5668,-5661,-5648,-5630,-5607,-5579,-5550,-5520,-5492,-5467,-5449,-5438,-5436,-5443,
--5460,-5485,-5517,-5555,-5596,-5639,-5681,-5720,-5754,-5783,-5805,-5821,-5829,-5832,-5829,-5823,-5813,-5802,-5789,-5777,-5765,
--5754,-5744,-5735,-5727,-5721,-5716,-5712,-5710,-5709,-5711,-5716,-5723,-5733,-5746,-5760,-5776,-5793,-5809,-5823,-5834,-5842,
--5845,-5844,-5838,-5828,-5814,-5798,-5782,-5765,-5750,-5738,-5730,-5725,-5725,-5728,-5735,-5745,-5757,-5770,-5782,-5795,-5807,
--5818,-5828,-5837,-5846,-5855,-5865,-5875,-5886,-5898,-5910,-5923,-5935,-5947,-5957,-5966,-5973,-5979,-5983,-5987,-5990,-5992,
--5995,-5999,-6003,-6007,-6012,-6016,-6020,-6022,-6023,-6021,-6016,-6009,-6000,-5988,-5976,-5963,-5951,-5940,-5931,-5924,-5920,
--5918,-5919,-5921,-5925,-5929,-5933,-5937,-5940,-5942,-5944,-5944,-5943,-5942,-5940,-5938,-5935,-5932,-5928,-5923,-5918,-5911,
--5903,-5894,-5884,-5876,-5868,-5863,-5861,-5863,-5870,-5883,-5901,-5925,-5953,-5985,-6019,-6053,-6087,-6118,-6146,-6170,-6189,
--6203,-6212,-6218,-6222,-6224,-6225,-6227,-6230,-6235,-6242,-6251,-6261,-6272,-6283,-6292,-6301,-6307,-6311,-6312,-6312,-6310,
--6307,-6304,-6300,-6297,-6295,-6292,-6289,-6284,-6278,-6268,-6254,-6236,-6211,-6182,-6146,-6106,-6062,-6015,-5967,-5919,-5872,
--5828,-5788,-5752,-5721,-5694,-5671,-5651,-5633,-5617,-5601,-5585,-5568,-5550,-5530,-5510,-5489,-5469,-5448,-5428,-5409,-5390,
--5373,-5356,-5338,-5319,-5299,-5277,-5252,-5225,-5194,-5160,-5124,-5086,-5048,-5009,-4970,-4932,-4896,-4862,-4829,-4798,-4768,
--4739,-4710,-4680,-4651,-4621,-4590,-4559,-4529,-4498,-4470,-4443,-4418,-4396,-4377,-4360,-4345,-4333,-4321,-4310,-4298,-4285,
--4270,-4253,-4234,-4213,-4189,-4165,-4141,-4117,-4095,-4076,-4060,-4049,-4041,-4039,-4040,-4044,-4051,-4059,-4067,-4073,-4076,
--4076,-4069,-4058,-4039,-4015,-3985,-3951,-3913,-3874,-3834,-3795,-3758,-3726,-3697,-3674,-3656,-3642,-3632,-3626,-3621,-3616,
--3612,-3608,-3602,-3595,-3588,-3581,-3575,-3571,-3570,-3572,-3578,-3588,-3602,-3619,-3637,-3656,-3674,-3689,-3700,-3706,-3706,
--3700,-3689,-3673,-3653,-3632,-3611,-3591,-3574,-3561,-3553,-3550,-3551,-3557,-3565,-3575,-3583,-3590,-3592,-3589,-3580,-3563,
--3540,-3510,-3475,-3435,-3393,-3349,-3307,-3267,-3231,-3201,-3177,-3160,-3150,-3147,-3150,-3158,-3170,-3184,-3198,-3212,-3224,
--3233,-3237,-3237,-3232,-3222,-3207,-3189,-3167,-3144,-3119,-3093,-3069,-3045,-3023,-3003,-2985,-2969,-2954,-2941,-2928,-2916,
--2904,-2891,-2878,-2864,-2849,-2835,-2820,-2805,-2791,-2777,-2764,-2751,-2740,-2728,-2717,-2706,-2695,-2683,-2670,-2657,-2642,
--2627,-2611,-2594,-2578,-2561,-2545,-2529,-2515,-2501,-2487,-2475,-2463,-2451,-2438,-2426,-2412,-2398,-2382,-2366,-2349,-2331,
--2313,-2296,-2279,-2263,-2248,-2235,-2223,-2214,-2205,-2198,-2191,-2184,-2176,-2167,-2156,-2143,-2128,-2110,-2090,-2069,-2046,
--2023,-1999,-1977,-1956,-1938,-1922,-1908,-1898,-1890,-1885,-1883,-1882,-1882,-1883,-1885,-1886,-1888,-1889,-1890,-1890,-1889,
--1887,-1885,-1881,-1876,-1870,-1862,-1853,-1843,-1832,-1820,-1809,-1798,-1789,-1783,-1779,-1778,-1780,-1786,-1795,-1806,-1818,
--1830,-1842,-1851,-1857,-1859,-1857,-1851,-1841,-1828,-1813,-1797,-1781,-1767,-1756,-1749,-1745,-1744,-1747,-1752,-1757,-1761,
--1762,-1760,-1752,-1738,-1717,-1690,-1656,-1617,-1575,-1530,-1484,-1440,-1398,-1360,-1327,-1300,-1279,-1264,-1255,-1251,-1253,
--1259,-1268,-1281,-1296,-1314,-1334,-1356,-1378,-1402,-1425,-1448,-1469,-1488,-1504,-1515,-1521,-1522,-1516,-1503,-1485,-1462,
--1435,-1405,-1373,-1342,-1313,-1287,-1265,-1247,-1235,-1229,-1227,-1229,-1234,-1241,-1248,-1255,-1261,-1265,-1267,-1265,-1262,
--1256,-1248,-1239,-1230,-1222,-1214,-1208,-1203,-1199,-1198,-1197,-1198,-1200,-1202,-1204,-1206,-1206,-1206,-1205,-1203,-1200,
--1196,-1190,-1184,-1178,-1170,-1163,-1156,-1148,-1141,-1134,-1128,-1121,-1115,-1108,-1101,-1094,-1086,-1078,-1068,-1058,-1046,
--1034,-1021,-1007,-994,-981,-968,-956,-944,-934,-924,-916,-908,-900,-893,-886,-879,-872,-865,-858,-851,-844,
--839,-834,-830,-826,-823,-821,-819,-817,-815,-812,-808,-803,-798,-792,-786,-780,-774,-769,-765,-763,-761,
--761,-762,-764,-766,-768,-769,-770,-770,-769,-767,-764,-760,-756,-752,-749,-745,-743,-740,-738,-735,-733,
--729,-725,-720,-714,-706,-698,-688,-678,-668,-658,-647,-636,-625,-613,-600,-586,-570,-552,-531,-509,-485,
--460,-434,-408,-382,-359,-337,-318,-301,-287,-275,-265,-256,-246,-236,-224,-210,-194,-175,-155,-135,-114,
--94,-77,-64,-54,-50,-50,-54,-61,-70,-80,-89,-96,-98,-94,-84,-68,-45,-15,18,56,96,
-138,179,218,255,288,319,346,371,393,413,433,452,471,490,509,528,547,564,580,593,604,
-613,620,624,627,628,629,630,632,634,638,642,648,654,660,666,671,676,679,682,684,684,
-685,685,685,686,688,690,692,694,696,697,697,695,690,684,676,665,653,640,627,614,601,
-590,454,448,446,445,447,450,455,461,467,473,480,487,494,501,509,518,527,538,549,562,
-575,587,600,612,623,633,641,648,653,657,661,665,670,675,683,692,703,715,730,745,760,
-775,789,801,811,819,823,826,826,825,824,823,823,826,831,840,852,868,888,910,934,960,
-986,1012,1038,1061,1083,1102,1119,1133,1146,1157,1167,1176,1184,1192,1200,1207,1215,1222,1229,1235,1242,
-1247,1253,1259,1264,1271,1278,1286,1296,1308,1320,1334,1350,1365,1381,1397,1411,1424,1436,1445,1453,1459,
-1463,1467,1470,1473,1476,1479,1483,1486,1489,1492,1492,1489,1483,1473,1459,1440,1416,1389,1358,1326,1294,
-1263,1234,1210,1192,1179,1173,1174,1181,1194,1210,1229,1249,1268,1286,1301,1312,1318,1319,1317,1310,1301,
-1289,1276,1263,1250,1239,1229,1221,1216,1212,1210,1209,1210,1211,1212,1213,1215,1216,1217,1218,1218,1219,
-1219,1220,1220,1219,1219,1217,1216,1213,1210,1206,1201,1196,1191,1185,1180,1175,1170,1166,1163,1160,1158,
-1156,1155,1154,1153,1153,1153,1153,1153,1154,1156,1158,1162,1167,1173,1180,1188,1198,1208,1219,1229,1240,
-1249,1258,1264,1269,1272,1272,1270,1265,1258,1249,1238,1226,1213,1199,1185,1171,1156,1142,1128,1115,1102,
-1089,1076,1065,1054,1044,1036,1030,1026,1025,1027,1032,1040,1052,1066,1082,1099,1117,1134,1148,1160,1167,
-1170,1166,1157,1142,1121,1095,1065,1032,996,960,923,888,855,824,797,772,751,733,718,705,694,
-683,674,664,653,642,630,617,602,586,570,554,538,523,509,496,486,478,473,470,469,469,
-471,473,475,476,475,473,468,460,451,440,428,416,405,395,386,380,376,374,375,377,379,
-382,384,385,385,383,379,374,369,364,359,357,356,357,361,367,374,382,390,396,400,401,
-400,395,388,380,370,361,354,349,348,350,355,363,371,380,387,389,386,375,356,328,291,
-246,194,136,76,14,-45,-102,-156,-203,-245,-281,-312,-338,-362,-383,-404,-425,-447,-471,-496,-522,
--550,-578,-605,-631,-657,-680,-702,-723,-743,-763,-783,-804,-827,-852,-880,-910,-943,-978,-1015,-1053,-1092,
--1132,-1173,-1214,-1256,-1297,-1340,-1382,-1425,-1467,-1509,-1550,-1590,-1627,-1660,-1690,-1716,-1737,-1752,-1763,-1770,-1773,
--1774,-1774,-1774,-1774,-1778,-1784,-1794,-1809,-1827,-1850,-1876,-1905,-1935,-1967,-2000,-2033,-2065,-2098,-2131,-2164,-2199,
--2234,-2272,-2312,-2355,-2400,-2447,-2495,-2544,-2593,-2641,-2687,-2730,-2770,-2807,-2841,-2873,-2902,-2931,-2959,-2988,-3019,
--3052,-3087,-3124,-3164,-3205,-3247,-3288,-3328,-3367,-3402,-3434,-3463,-3488,-3510,-3529,-3547,-3563,-3579,-3595,-3612,-3629,
--3649,-3669,-3691,-3714,-3739,-3764,-3789,-3816,-3842,-3869,-3896,-3923,-3949,-3975,-4000,-4022,-4043,-4060,-4074,-4083,-4089,
--4090,-4088,-4083,-4077,-4070,-4065,-4062,-4064,-4071,-4084,-4104,-4130,-4161,-4196,-4235,-4275,-4315,-4353,-4388,-4420,-4449,
--4474,-4496,-4517,-4537,-4558,-4582,-4609,-4640,-4675,-4714,-4755,-4798,-4841,-4881,-4918,-4951,-4977,-4996,-5009,-5016,-5018,
--5017,-5013,-5010,-5008,-5010,-5015,-5026,-5042,-5063,-5088,-5116,-5147,-5179,-5211,-5242,-5271,-5299,-5324,-5348,-5371,-5392,
--5412,-5433,-5453,-5474,-5495,-5516,-5537,-5557,-5576,-5593,-5609,-5624,-5637,-5649,-5659,-5670,-5680,-5690,-5701,-5713,-5725,
--5738,-5751,-5763,-5774,-5784,-5791,-5796,-5799,-5800,-5798,-5793,-5788,-5781,-5774,-5766,-5758,-5751,-5743,-5735,-5727,-5718,
--5708,-5698,-5686,-5674,-5661,-5648,-5636,-5626,-5618,-5613,-5611,-5612,-5616,-5622,-5630,-5637,-5643,-5646,-5645,-5639,-5627,
--5610,-5586,-5558,-5527,-5495,-5463,-5435,-5411,-5395,-5387,-5389,-5401,-5423,-5452,-5489,-5530,-5574,-5617,-5659,-5696,-5727,
--5752,-5770,-5780,-5784,-5783,-5778,-5770,-5761,-5751,-5743,-5735,-5729,-5724,-5720,-5717,-5715,-5712,-5709,-5705,-5702,-5698,
--5695,-5694,-5695,-5699,-5705,-5715,-5726,-5740,-5755,-5769,-5781,-5791,-5797,-5798,-5795,-5787,-5774,-5758,-5741,-5722,-5704,
--5689,-5677,-5669,-5667,-5669,-5676,-5687,-5701,-5716,-5733,-5748,-5763,-5775,-5786,-5794,-5800,-5805,-5809,-5813,-5818,-5823,
--5829,-5837,-5846,-5855,-5866,-5877,-5887,-5897,-5906,-5915,-5922,-5929,-5935,-5941,-5947,-5952,-5957,-5961,-5965,-5968,-5969,
--5969,-5967,-5963,-5957,-5949,-5939,-5929,-5918,-5907,-5897,-5889,-5882,-5876,-5873,-5871,-5871,-5872,-5873,-5875,-5877,-5878,
--5879,-5879,-5878,-5877,-5875,-5873,-5870,-5867,-5863,-5859,-5855,-5850,-5844,-5837,-5831,-5824,-5818,-5814,-5812,-5812,-5816,
--5825,-5837,-5855,-5876,-5900,-5927,-5955,-5984,-6011,-6036,-6058,-6076,-6089,-6098,-6103,-6104,-6103,-6100,-6097,-6094,-6093,
--6093,-6096,-6100,-6106,-6114,-6123,-6132,-6141,-6149,-6155,-6161,-6164,-6167,-6168,-6168,-6167,-6165,-6162,-6158,-6151,-6143,
--6132,-6117,-6098,-6074,-6046,-6014,-5978,-5938,-5896,-5853,-5810,-5769,-5730,-5694,-5663,-5637,-5615,-5597,-5583,-5573,-5564,
--5557,-5550,-5543,-5535,-5525,-5514,-5502,-5488,-5474,-5458,-5443,-5427,-5410,-5393,-5375,-5356,-5334,-5310,-5283,-5252,-5218,
--5181,-5140,-5097,-5052,-5007,-4961,-4916,-4873,-4832,-4793,-4758,-4725,-4695,-4667,-4640,-4615,-4590,-4566,-4542,-4518,-4494,
--4471,-4448,-4427,-4406,-4388,-4371,-4356,-4343,-4331,-4321,-4310,-4300,-4288,-4276,-4262,-4246,-4228,-4209,-4190,-4170,-4150,
--4132,-4116,-4103,-4093,-4086,-4083,-4084,-4087,-4092,-4098,-4104,-4109,-4110,-4108,-4102,-4089,-4071,-4047,-4017,-3983,-3943,
--3901,-3857,-3812,-3767,-3723,-3682,-3643,-3608,-3577,-3549,-3525,-3505,-3488,-3474,-3463,-3455,-3451,-3450,-3454,-3461,-3472,
--3488,-3507,-3529,-3554,-3581,-3608,-3634,-3658,-3678,-3694,-3704,-3709,-3708,-3702,-3691,-3676,-3660,-3644,-3628,-3615,-3605,
--3598,-3596,-3598,-3604,-3611,-3619,-3627,-3633,-3635,-3633,-3625,-3611,-3591,-3566,-3536,-3502,-3466,-3429,-3393,-3360,-3330,
--3306,-3286,-3273,-3266,-3265,-3269,-3277,-3289,-3303,-3318,-3333,-3346,-3357,-3364,-3368,-3368,-3363,-3354,-3340,-3323,-3303,
--3280,-3255,-3229,-3201,-3174,-3147,-3121,-3096,-3072,-3050,-3029,-3010,-2992,-2975,-2960,-2945,-2931,-2918,-2906,-2894,-2882,
--2870,-2858,-2846,-2834,-2821,-2807,-2793,-2778,-2762,-2744,-2726,-2707,-2686,-2666,-2645,-2623,-2602,-2582,-2562,-2543,-2525,
--2508,-2492,-2477,-2463,-2450,-2437,-2425,-2412,-2399,-2387,-2374,-2360,-2347,-2334,-2321,-2308,-2296,-2284,-2273,-2263,-2253,
--2244,-2235,-2225,-2215,-2204,-2191,-2177,-2162,-2144,-2125,-2105,-2084,-2063,-2042,-2021,-2002,-1985,-1970,-1957,-1946,-1938,
--1932,-1928,-1926,-1925,-1924,-1925,-1925,-1926,-1926,-1927,-1927,-1926,-1924,-1922,-1919,-1914,-1907,-1899,-1889,-1877,-1864,
--1849,-1834,-1818,-1803,-1790,-1780,-1772,-1769,-1770,-1776,-1786,-1800,-1818,-1837,-1858,-1879,-1898,-1914,-1927,-1937,-1942,
--1944,-1943,-1939,-1934,-1929,-1924,-1920,-1919,-1919,-1922,-1926,-1931,-1935,-1939,-1940,-1937,-1930,-1919,-1903,-1882,-1857,
--1829,-1798,-1767,-1736,-1707,-1680,-1657,-1638,-1623,-1612,-1606,-1603,-1603,-1606,-1611,-1616,-1623,-1630,-1637,-1644,-1651,
--1657,-1662,-1666,-1668,-1668,-1666,-1660,-1651,-1638,-1621,-1599,-1574,-1545,-1514,-1481,-1448,-1415,-1384,-1357,-1333,-1313,
--1299,-1289,-1284,-1283,-1285,-1290,-1295,-1300,-1305,-1307,-1308,-1307,-1303,-1297,-1289,-1280,-1270,-1261,-1253,-1246,-1240,
--1237,-1235,-1236,-1238,-1241,-1245,-1249,-1254,-1257,-1260,-1261,-1262,-1261,-1258,-1255,-1251,-1246,-1240,-1234,-1228,-1223,
--1217,-1211,-1205,-1199,-1193,-1186,-1178,-1170,-1161,-1150,-1139,-1127,-1115,-1102,-1089,-1076,-1064,-1052,-1041,-1032,-1023,
--1015,-1007,-1001,-994,-989,-983,-977,-971,-965,-959,-953,-948,-943,-939,-935,-931,-929,-926,-924,-922,-920,
--918,-915,-912,-909,-905,-902,-899,-896,-894,-893,-892,-893,-894,-895,-897,-898,-899,-899,-898,-896,-892,
--888,-883,-877,-871,-865,-860,-855,-850,-846,-842,-838,-833,-827,-821,-813,-803,-793,-781,-768,-755,-742,
--729,-716,-704,-691,-678,-663,-648,-629,-608,-584,-556,-525,-490,-453,-415,-376,-338,-301,-267,-237,-211,
--189,-170,-155,-141,-129,-117,-104,-89,-73,-56,-37,-18,0,16,29,37,40,37,29,15,-2,
--22,-43,-62,-77,-86,-89,-83,-68,-45,-14,23,66,111,158,203,245,283,316,344,366,383,
-396,406,415,422,430,439,449,460,473,486,499,512,523,533,540,545,548,549,548,546,544,
-542,540,539,539,540,542,546,550,555,560,565,571,576,581,586,590,594,597,599,600,599,
-597,593,587,578,568,556,542,528,513,498,484,472,462,454,372,369,368,369,373,377,383,
-390,396,403,410,417,423,429,436,443,451,459,469,480,491,502,514,526,537,547,556,564,
-570,576,581,586,591,597,604,612,622,634,647,662,676,691,705,717,727,735,740,743,743,
-742,740,738,737,738,742,749,760,775,794,816,842,869,898,928,956,983,1008,1030,1050,1066,
-1080,1091,1100,1107,1113,1119,1124,1130,1135,1141,1148,1154,1161,1168,1176,1183,1191,1200,1209,1219,1230,
-1242,1255,1270,1285,1301,1316,1332,1347,1361,1374,1385,1394,1402,1408,1414,1419,1423,1427,1431,1435,1439,
-1442,1444,1443,1440,1434,1423,1409,1389,1366,1339,1309,1278,1246,1216,1189,1166,1148,1137,1132,1134,1142,
-1155,1173,1193,1214,1235,1254,1269,1281,1289,1292,1291,1286,1278,1267,1256,1244,1233,1223,1214,1207,1201,
-1197,1193,1190,1188,1185,1183,1180,1177,1174,1171,1169,1168,1167,1168,1169,1172,1174,1177,1179,1180,1180,
-1178,1175,1169,1162,1153,1144,1133,1124,1114,1106,1099,1094,1091,1089,1089,1090,1092,1094,1096,1097,1099,
-1100,1100,1101,1101,1103,1105,1109,1115,1122,1132,1143,1155,1168,1181,1194,1205,1215,1222,1226,1227,1225,
-1220,1212,1201,1189,1175,1160,1145,1130,1114,1099,1084,1069,1054,1040,1026,1013,1001,990,982,976,974,
-975,981,991,1006,1025,1047,1071,1096,1121,1144,1163,1177,1185,1186,1178,1163,1140,1110,1073,1033,989,
-945,901,858,819,785,754,729,709,693,681,672,665,658,651,644,634,623,610,594,577,559,
-539,520,501,484,468,455,444,436,431,428,427,427,428,429,429,428,425,421,414,406,396,
-385,373,361,350,340,332,326,322,320,320,321,323,325,327,328,327,326,323,319,315,311,
-307,305,304,305,309,314,321,329,337,345,351,355,358,357,355,351,346,341,336,333,332,
-333,337,343,350,357,364,367,367,360,347,326,298,262,219,171,118,64,9,-44,-95,-142,
--185,-224,-257,-287,-314,-339,-364,-388,-413,-439,-467,-497,-527,-559,-590,-620,-649,-676,-702,-725,-746,
--766,-785,-805,-825,-847,-871,-898,-928,-962,-999,-1039,-1081,-1126,-1173,-1221,-1270,-1319,-1369,-1418,-1467,-1514,
--1560,-1604,-1645,-1683,-1717,-1746,-1771,-1790,-1804,-1812,-1816,-1815,-1811,-1805,-1798,-1792,-1786,-1784,-1785,-1790,-1800,
--1814,-1833,-1855,-1882,-1911,-1942,-1975,-2009,-2043,-2078,-2114,-2151,-2188,-2226,-2266,-2307,-2350,-2394,-2439,-2485,-2531,
--2577,-2621,-2664,-2705,-2745,-2782,-2817,-2850,-2883,-2916,-2948,-2981,-3016,-3052,-3090,-3129,-3169,-3210,-3250,-3290,-3328,
--3363,-3396,-3427,-3454,-3478,-3500,-3520,-3538,-3556,-3574,-3592,-3611,-3631,-3653,-3676,-3701,-3728,-3756,-3786,-3816,-3847,
--3878,-3910,-3940,-3971,-3999,-4025,-4049,-4069,-4085,-4096,-4102,-4103,-4100,-4092,-4082,-4070,-4057,-4046,-4038,-4035,-4037,
--4046,-4062,-4086,-4115,-4151,-4190,-4232,-4274,-4315,-4354,-4389,-4420,-4447,-4470,-4490,-4508,-4526,-4545,-4567,-4593,-4623,
--4657,-4696,-4737,-4781,-4825,-4867,-4907,-4942,-4971,-4993,-5010,-5020,-5025,-5026,-5024,-5022,-5021,-5022,-5027,-5036,-5050,
--5068,-5091,-5117,-5146,-5176,-5206,-5236,-5266,-5294,-5321,-5346,-5371,-5394,-5417,-5440,-5462,-5485,-5508,-5530,-5551,-5572,
--5591,-5608,-5623,-5637,-5648,-5658,-5666,-5674,-5681,-5689,-5698,-5707,-5717,-5728,-5740,-5751,-5762,-5772,-5781,-5788,-5792,
--5794,-5793,-5790,-5785,-5778,-5769,-5760,-5750,-5739,-5727,-5715,-5703,-5690,-5677,-5663,-5649,-5636,-5623,-5611,-5601,-5593,
--5588,-5586,-5586,-5589,-5594,-5599,-5605,-5609,-5610,-5607,-5600,-5587,-5568,-5544,-5515,-5483,-5450,-5418,-5389,-5365,-5349,
--5340,-5342,-5353,-5374,-5403,-5440,-5481,-5524,-5568,-5610,-5647,-5679,-5704,-5721,-5731,-5735,-5734,-5728,-5720,-5712,-5703,
--5696,-5691,-5687,-5686,-5687,-5688,-5690,-5691,-5692,-5691,-5689,-5687,-5683,-5681,-5679,-5680,-5682,-5688,-5696,-5706,-5719,
--5731,-5743,-5753,-5760,-5762,-5760,-5753,-5740,-5724,-5704,-5682,-5660,-5640,-5623,-5610,-5602,-5599,-5603,-5611,-5624,-5641,
--5659,-5678,-5697,-5713,-5728,-5739,-5748,-5754,-5758,-5760,-5762,-5764,-5766,-5770,-5776,-5784,-5793,-5804,-5816,-5828,-5840,
--5852,-5864,-5874,-5884,-5892,-5899,-5905,-5911,-5915,-5918,-5921,-5922,-5922,-5921,-5918,-5914,-5909,-5902,-5894,-5885,-5876,
--5867,-5858,-5850,-5844,-5839,-5835,-5832,-5831,-5831,-5831,-5832,-5833,-5834,-5834,-5834,-5834,-5834,-5833,-5832,-5831,-5830,
--5830,-5829,-5828,-5827,-5826,-5826,-5825,-5826,-5826,-5828,-5832,-5837,-5844,-5854,-5866,-5879,-5895,-5912,-5930,-5948,-5964,
--5979,-5991,-6000,-6006,-6007,-6005,-5999,-5991,-5981,-5970,-5959,-5948,-5938,-5931,-5926,-5923,-5922,-5924,-5927,-5931,-5936,
--5941,-5946,-5950,-5954,-5957,-5959,-5959,-5959,-5958,-5955,-5951,-5945,-5938,-5927,-5914,-5899,-5880,-5858,-5833,-5806,-5777,
--5747,-5717,-5688,-5660,-5635,-5614,-5595,-5581,-5570,-5562,-5557,-5554,-5552,-5550,-5548,-5544,-5539,-5531,-5522,-5510,-5496,
--5480,-5463,-5445,-5426,-5406,-5385,-5363,-5340,-5315,-5288,-5259,-5228,-5194,-5158,-5119,-5078,-5035,-4991,-4947,-4903,-4860,
--4818,-4778,-4740,-4704,-4671,-4640,-4611,-4585,-4559,-4536,-4514,-4492,-4472,-4453,-4435,-4419,-4403,-4388,-4375,-4363,-4352,
--4341,-4331,-4320,-4310,-4298,-4287,-4274,-4260,-4246,-4231,-4215,-4201,-4187,-4174,-4162,-4153,-4146,-4141,-4138,-4137,-4137,
--4138,-4138,-4138,-4137,-4133,-4126,-4115,-4100,-4081,-4057,-4028,-3996,-3959,-3919,-3876,-3831,-3785,-3738,-3692,-3646,-3602,
--3561,-3522,-3487,-3456,-3430,-3409,-3394,-3384,-3381,-3385,-3395,-3410,-3431,-3457,-3487,-3519,-3552,-3585,-3616,-3645,-3669,
--3688,-3702,-3711,-3713,-3711,-3704,-3694,-3682,-3669,-3657,-3646,-3637,-3632,-3629,-3630,-3633,-3638,-3643,-3649,-3652,-3653,
--3651,-3645,-3634,-3619,-3601,-3579,-3554,-3529,-3503,-3478,-3454,-3433,-3416,-3402,-3393,-3387,-3386,-3387,-3392,-3399,-3407,
--3417,-3426,-3435,-3443,-3449,-3452,-3454,-3452,-3447,-3439,-3428,-3414,-3396,-3376,-3352,-3327,-3300,-3271,-3242,-3213,-3184,
--3156,-3129,-3104,-3081,-3060,-3041,-3025,-3010,-2998,-2986,-2975,-2965,-2955,-2945,-2934,-2922,-2909,-2894,-2878,-2861,-2841,
--2821,-2799,-2777,-2753,-2729,-2704,-2680,-2656,-2632,-2609,-2586,-2565,-2545,-2527,-2510,-2494,-2479,-2466,-2454,-2443,-2432,
--2422,-2412,-2402,-2392,-2381,-2370,-2359,-2347,-2335,-2322,-2309,-2296,-2283,-2269,-2255,-2241,-2226,-2211,-2196,-2180,-2164,
--2146,-2129,-2111,-2093,-2075,-2057,-2039,-2023,-2007,-1992,-1979,-1968,-1957,-1949,-1942,-1937,-1932,-1930,-1929,-1929,-1930,
--1931,-1934,-1936,-1939,-1941,-1942,-1942,-1939,-1934,-1926,-1915,-1901,-1884,-1864,-1842,-1819,-1796,-1775,-1756,-1741,-1730,
--1725,-1727,-1736,-1750,-1771,-1797,-1827,-1860,-1893,-1927,-1959,-1987,-2012,-2033,-2049,-2060,-2067,-2070,-2070,-2068,-2065,
--2061,-2056,-2052,-2048,-2045,-2041,-2037,-2033,-2027,-2020,-2011,-2000,-1987,-1972,-1956,-1939,-1921,-1904,-1886,-1870,-1855,
--1841,-1829,-1818,-1810,-1803,-1797,-1793,-1790,-1789,-1788,-1789,-1790,-1791,-1792,-1793,-1793,-1791,-1787,-1780,-1770,-1755,
--1737,-1714,-1687,-1657,-1623,-1587,-1550,-1514,-1478,-1445,-1415,-1390,-1369,-1353,-1343,-1336,-1334,-1335,-1338,-1341,-1345,
--1349,-1350,-1350,-1348,-1343,-1337,-1330,-1321,-1313,-1304,-1297,-1292,-1288,-1286,-1285,-1287,-1290,-1293,-1298,-1302,-1306,
--1309,-1312,-1313,-1313,-1312,-1311,-1308,-1306,-1303,-1300,-1297,-1294,-1291,-1288,-1285,-1281,-1276,-1271,-1264,-1256,-1246,
--1235,-1223,-1211,-1198,-1184,-1171,-1159,-1147,-1137,-1127,-1119,-1112,-1106,-1101,-1096,-1091,-1087,-1083,-1078,-1073,-1068,
--1063,-1058,-1053,-1048,-1043,-1039,-1035,-1031,-1028,-1026,-1023,-1021,-1018,-1016,-1014,-1011,-1009,-1008,-1007,-1006,-1006,
--1006,-1008,-1009,-1011,-1012,-1013,-1013,-1012,-1009,-1006,-1001,-994,-988,-980,-972,-965,-958,-952,-947,-942,-938,
--933,-928,-922,-914,-904,-891,-876,-859,-839,-817,-794,-771,-748,-725,-703,-682,-662,-642,-622,-600,-578,
--552,-524,-493,-458,-421,-381,-341,-299,-259,-222,-187,-157,-131,-109,-92,-79,-68,-59,-50,-41,-31,
--19,-6,8,24,38,51,61,66,65,59,48,31,11,-11,-34,-56,-73,-83,-87,-81,-66,
--42,-10,28,72,118,165,210,251,287,317,340,356,367,373,375,376,375,375,377,381,388,
-396,407,419,431,442,453,461,467,470,471,470,466,462,457,452,448,446,444,445,447,451,
-457,463,470,477,485,492,498,504,509,512,513,513,511,508,502,494,485,473,461,448,434,
-420,407,396,386,378,372,290,285,282,281,282,284,288,293,300,307,314,322,331,340,349,
-359,370,381,392,404,416,429,441,453,465,476,485,494,502,509,516,523,529,536,544,553,
-563,575,587,601,615,629,642,654,664,673,679,683,685,686,686,685,686,687,691,698,708,
-722,739,760,783,809,835,862,889,915,938,960,978,995,1008,1019,1029,1037,1044,1050,1056,1063,
-1069,1076,1084,1092,1100,1108,1116,1125,1134,1143,1152,1162,1173,1184,1197,1210,1225,1240,1255,1270,1284,
-1298,1310,1321,1331,1338,1345,1350,1354,1357,1360,1363,1366,1369,1371,1372,1373,1371,1368,1361,1351,1338,
-1321,1302,1279,1255,1231,1206,1184,1164,1148,1136,1130,1129,1132,1140,1151,1164,1179,1194,1207,1219,1228,
-1233,1236,1235,1232,1226,1218,1210,1201,1193,1185,1179,1173,1168,1164,1160,1156,1153,1149,1145,1141,1137,
-1133,1131,1129,1128,1129,1132,1136,1140,1145,1150,1154,1157,1157,1155,1150,1143,1134,1122,1109,1096,1082,
-1070,1060,1051,1046,1043,1043,1045,1049,1054,1059,1064,1069,1072,1074,1074,1073,1072,1070,1069,1069,1070,
-1074,1080,1088,1099,1111,1125,1139,1153,1165,1176,1184,1189,1191,1190,1186,1179,1169,1157,1144,1130,1114,
-1099,1083,1068,1052,1037,1021,1007,993,980,968,959,952,948,949,953,961,974,990,1010,1031,1053,
-1074,1094,1109,1120,1125,1123,1113,1097,1074,1045,1011,973,934,894,856,821,789,761,738,719,705,
-694,685,678,672,665,656,646,633,618,600,581,560,539,518,498,481,466,453,444,438,434,
-433,433,435,436,437,437,435,432,426,417,407,396,384,371,359,348,339,331,326,323,322,
-323,325,327,329,331,331,330,327,322,316,310,302,295,289,284,280,279,280,282,286,290,
-295,298,301,301,300,296,290,282,274,265,256,250,245,242,241,243,246,250,253,254,252,
-246,235,218,195,166,132,93,51,7,-36,-80,-122,-162,-198,-231,-261,-289,-314,-338,-362,-386,
--412,-439,-468,-499,-530,-563,-596,-629,-660,-690,-718,-744,-768,-791,-813,-834,-857,-880,-906,-935,-967,
--1002,-1041,-1083,-1129,-1177,-1228,-1281,-1334,-1388,-1441,-1494,-1544,-1593,-1639,-1681,-1720,-1755,-1786,-1811,-1832,-1848,
--1859,-1866,-1869,-1868,-1865,-1860,-1854,-1848,-1843,-1840,-1840,-1842,-1848,-1858,-1871,-1888,-1908,-1932,-1958,-1987,-2017,
--2050,-2085,-2121,-2159,-2198,-2239,-2280,-2323,-2366,-2409,-2453,-2496,-2538,-2580,-2620,-2659,-2697,-2733,-2768,-2803,-2837,
--2871,-2906,-2941,-2977,-3015,-3053,-3092,-3131,-3170,-3209,-3247,-3283,-3318,-3350,-3380,-3408,-3434,-3458,-3481,-3503,-3524,
--3545,-3567,-3589,-3612,-3635,-3660,-3685,-3710,-3737,-3764,-3791,-3820,-3848,-3877,-3906,-3935,-3963,-3990,-4016,-4040,-4061,
--4078,-4091,-4100,-4105,-4105,-4102,-4095,-4087,-4078,-4070,-4065,-4063,-4066,-4075,-4091,-4112,-4139,-4172,-4207,-4245,-4284,
--4322,-4357,-4390,-4419,-4444,-4465,-4484,-4502,-4519,-4537,-4557,-4581,-4609,-4640,-4676,-4715,-4757,-4799,-4841,-4880,-4916,
--4947,-4973,-4993,-5007,-5017,-5022,-5024,-5024,-5025,-5026,-5030,-5037,-5047,-5062,-5081,-5103,-5128,-5155,-5183,-5213,-5243,
--5272,-5300,-5328,-5355,-5380,-5405,-5429,-5452,-5475,-5496,-5517,-5537,-5555,-5572,-5587,-5601,-5613,-5624,-5635,-5644,-5653,
--5663,-5673,-5683,-5694,-5705,-5717,-5729,-5740,-5751,-5761,-5769,-5775,-5779,-5780,-5780,-5777,-5773,-5766,-5759,-5750,-5741,
--5730,-5719,-5707,-5694,-5680,-5666,-5651,-5636,-5621,-5607,-5593,-5581,-5572,-5564,-5559,-5556,-5555,-5555,-5555,-5555,-5554,
--5550,-5542,-5529,-5513,-5491,-5465,-5436,-5406,-5375,-5346,-5321,-5302,-5290,-5285,-5290,-5304,-5325,-5354,-5389,-5427,-5466,
--5506,-5542,-5574,-5601,-5622,-5637,-5646,-5650,-5649,-5646,-5641,-5635,-5630,-5626,-5624,-5623,-5624,-5625,-5627,-5629,-5630,
--5630,-5629,-5627,-5625,-5623,-5622,-5623,-5627,-5633,-5642,-5654,-5667,-5682,-5697,-5711,-5722,-5729,-5731,-5728,-5719,-5705,
--5686,-5664,-5640,-5615,-5592,-5573,-5557,-5547,-5543,-5545,-5553,-5565,-5581,-5599,-5619,-5638,-5656,-5672,-5686,-5696,-5704,
--5710,-5714,-5718,-5721,-5725,-5731,-5738,-5746,-5757,-5769,-5782,-5795,-5808,-5821,-5834,-5845,-5854,-5862,-5868,-5874,-5877,
--5880,-5881,-5882,-5882,-5881,-5879,-5876,-5872,-5867,-5862,-5856,-5849,-5842,-5835,-5828,-5821,-5816,-5811,-5808,-5806,-5804,
--5804,-5804,-5805,-5807,-5808,-5810,-5811,-5812,-5813,-5814,-5815,-5817,-5818,-5820,-5822,-5824,-5827,-5831,-5835,-5840,-5845,
--5851,-5858,-5865,-5873,-5882,-5891,-5900,-5910,-5920,-5929,-5937,-5944,-5949,-5951,-5951,-5948,-5942,-5933,-5921,-5907,-5892,
--5875,-5858,-5841,-5825,-5810,-5797,-5787,-5778,-5772,-5768,-5765,-5764,-5763,-5764,-5764,-5764,-5764,-5764,-5764,-5762,-5761,
--5759,-5756,-5752,-5748,-5743,-5737,-5730,-5721,-5710,-5699,-5685,-5671,-5655,-5639,-5623,-5608,-5593,-5580,-5569,-5559,-5551,
--5545,-5541,-5537,-5534,-5531,-5528,-5523,-5517,-5509,-5499,-5486,-5472,-5456,-5438,-5418,-5398,-5377,-5356,-5335,-5313,-5291,
--5268,-5245,-5221,-5195,-5168,-5139,-5108,-5075,-5040,-5004,-4966,-4927,-4888,-4849,-4810,-4772,-4736,-4701,-4668,-4638,-4610,
--4584,-4561,-4540,-4521,-4503,-4488,-4474,-4461,-4448,-4437,-4426,-4414,-4403,-4391,-4379,-4366,-4352,-4338,-4324,-4310,-4295,
--4281,-4267,-4254,-4242,-4230,-4220,-4212,-4204,-4198,-4192,-4187,-4182,-4177,-4172,-4165,-4158,-4149,-4138,-4125,-4110,-4093,
--4073,-4051,-4026,-3998,-3968,-3936,-3901,-3864,-3825,-3784,-3743,-3702,-3661,-3620,-3582,-3547,-3516,-3489,-3468,-3452,-3443,
--3441,-3446,-3456,-3473,-3494,-3520,-3547,-3577,-3606,-3633,-3659,-3680,-3697,-3709,-3717,-3719,-3718,-3712,-3704,-3695,-3684,
--3674,-3665,-3657,-3652,-3648,-3647,-3647,-3648,-3650,-3652,-3652,-3651,-3648,-3643,-3635,-3625,-3613,-3600,-3585,-3570,-3555,
--3541,-3527,-3515,-3505,-3497,-3490,-3485,-3481,-3478,-3477,-3476,-3476,-3476,-3476,-3477,-3478,-3479,-3479,-3479,-3479,-3477,
--3474,-3469,-3462,-3452,-3439,-3424,-3406,-3385,-3362,-3336,-3310,-3282,-3255,-3228,-3202,-3178,-3156,-3136,-3118,-3102,-3089,
--3077,-3066,-3056,-3046,-3036,-3025,-3013,-3000,-2985,-2970,-2953,-2934,-2915,-2894,-2873,-2851,-2829,-2806,-2782,-2758,-2734,
--2710,-2687,-2663,-2640,-2617,-2595,-2575,-2555,-2537,-2521,-2505,-2491,-2478,-2466,-2455,-2443,-2431,-2419,-2406,-2392,-2377,
--2360,-2343,-2325,-2307,-2288,-2269,-2250,-2231,-2213,-2196,-2179,-2162,-2146,-2130,-2113,-2096,-2079,-2061,-2042,-2023,-2003,
--1982,-1962,-1943,-1924,-1907,-1892,-1880,-1870,-1864,-1861,-1862,-1866,-1874,-1884,-1897,-1910,-1925,-1939,-1951,-1962,-1968,
--1971,-1968,-1960,-1946,-1927,-1903,-1875,-1843,-1810,-1776,-1744,-1716,-1692,-1674,-1664,-1663,-1670,-1686,-1710,-1742,-1779,
--1822,-1867,-1913,-1958,-2000,-2039,-2072,-2099,-2119,-2133,-2139,-2140,-2135,-2126,-2114,-2099,-2082,-2066,-2049,-2034,-2019,
--2007,-1996,-1986,-1978,-1971,-1964,-1957,-1950,-1942,-1932,-1922,-1910,-1897,-1882,-1866,-1850,-1833,-1817,-1802,-1789,-1778,
--1769,-1764,-1761,-1760,-1762,-1766,-1770,-1775,-1779,-1780,-1779,-1774,-1764,-1750,-1731,-1707,-1679,-1648,-1614,-1579,-1545,
--1512,-1482,-1455,-1433,-1415,-1402,-1393,-1388,-1386,-1387,-1389,-1392,-1394,-1394,-1394,-1391,-1387,-1381,-1374,-1366,-1359,
--1351,-1345,-1340,-1337,-1336,-1336,-1338,-1341,-1345,-1349,-1353,-1356,-1359,-1360,-1360,-1360,-1359,-1357,-1355,-1354,-1353,
--1352,-1352,-1353,-1354,-1356,-1357,-1357,-1356,-1354,-1350,-1344,-1336,-1327,-1316,-1303,-1290,-1276,-1262,-1249,-1237,-1226,
--1216,-1207,-1200,-1194,-1189,-1184,-1180,-1176,-1172,-1167,-1163,-1159,-1154,-1149,-1145,-1141,-1137,-1134,-1131,-1129,-1126,
--1125,-1123,-1121,-1119,-1117,-1116,-1114,-1112,-1111,-1111,-1110,-1111,-1112,-1114,-1115,-1117,-1118,-1119,-1118,-1116,-1113,
--1108,-1101,-1093,-1083,-1074,-1064,-1054,-1045,-1037,-1030,-1024,-1018,-1012,-1005,-997,-986,-973,-955,-934,-909,-881,
--849,-815,-779,-743,-707,-672,-639,-608,-580,-553,-529,-506,-483,-460,-435,-410,-383,-354,-323,-292,-261,
--231,-203,-178,-156,-138,-124,-113,-105,-99,-95,-91,-86,-80,-72,-62,-51,-39,-28,-17,-9,-4,
--4,-8,-17,-30,-45,-63,-80,-96,-108,-114,-114,-106,-89,-65,-34,2,43,85,127,168,204,
-235,259,278,290,296,298,297,293,289,286,285,286,289,295,303,312,322,332,340,347,351,
-353,353,350,346,341,336,331,327,325,324,326,329,334,340,348,356,364,372,379,386,391,
-395,398,400,400,399,397,393,388,381,374,365,356,345,335,324,314,305,297,290,164,153,
-143,136,131,128,128,130,135,143,152,164,176,190,205,220,236,252,267,282,297,312,325,
-339,351,363,374,384,394,403,412,421,430,439,449,460,471,483,495,508,521,534,546,557,
-567,575,582,587,591,593,595,597,600,603,608,615,624,636,650,666,685,705,726,748,770,
-792,813,833,851,868,884,898,911,924,937,949,960,972,984,995,1006,1017,1027,1036,1045,1053,
-1061,1069,1077,1086,1095,1104,1115,1127,1141,1155,1169,1184,1198,1212,1225,1236,1246,1254,1260,1264,1267,
-1269,1271,1272,1273,1274,1275,1277,1278,1279,1279,1277,1274,1269,1262,1252,1240,1226,1211,1196,1180,1166,
-1153,1142,1133,1128,1125,1125,1126,1130,1134,1139,1143,1146,1148,1149,1147,1145,1140,1135,1129,1123,1117,
-1112,1108,1104,1101,1099,1097,1096,1094,1093,1091,1089,1087,1086,1085,1085,1086,1088,1091,1096,1101,1107,
-1113,1118,1122,1124,1123,1120,1114,1105,1093,1080,1065,1051,1036,1024,1013,1005,1001,999,1001,1005,1011,
-1019,1027,1034,1040,1045,1047,1047,1044,1041,1036,1030,1025,1022,1020,1020,1024,1030,1039,1050,1062,1076,
-1090,1103,1114,1124,1131,1136,1137,1135,1131,1124,1115,1104,1092,1078,1064,1050,1035,1020,1006,992,978,
-966,954,945,938,933,931,932,936,943,952,963,976,988,1000,1010,1017,1020,1018,1012,1001,984,
-963,939,912,883,854,826,799,775,754,737,722,711,702,694,686,679,669,658,645,629,610,
-589,566,543,519,496,475,457,442,431,424,420,420,423,427,433,439,444,448,449,448,444,
-438,429,418,407,394,383,372,364,357,354,353,354,357,361,366,370,373,375,374,370,364,
-355,343,330,316,302,288,276,264,255,248,242,238,234,231,227,222,214,205,193,179,163,
-146,128,110,93,78,66,56,49,45,42,41,40,39,37,32,23,12,-3,-22,-44,-69,
--96,-125,-153,-181,-209,-235,-260,-283,-305,-327,-348,-370,-394,-418,-445,-474,-504,-536,-569,-603,-637,
--671,-703,-734,-764,-792,-819,-846,-872,-899,-927,-956,-988,-1023,-1061,-1103,-1148,-1196,-1246,-1298,-1351,-1405,
--1459,-1511,-1562,-1610,-1656,-1698,-1737,-1773,-1804,-1831,-1855,-1876,-1892,-1906,-1917,-1925,-1931,-1935,-1937,-1938,-1938,
--1938,-1938,-1938,-1939,-1941,-1945,-1951,-1959,-1969,-1982,-1999,-2019,-2042,-2069,-2099,-2133,-2169,-2208,-2248,-2291,-2334,
--2378,-2422,-2464,-2506,-2547,-2586,-2623,-2659,-2694,-2728,-2762,-2796,-2830,-2865,-2901,-2938,-2976,-3015,-3055,-3095,-3135,
--3173,-3211,-3247,-3282,-3315,-3346,-3375,-3403,-3430,-3456,-3482,-3508,-3534,-3560,-3586,-3613,-3639,-3665,-3691,-3715,-3739,
--3763,-3785,-3807,-3829,-3851,-3873,-3896,-3920,-3945,-3971,-3997,-4024,-4049,-4073,-4095,-4114,-4130,-4141,-4149,-4154,-4155,
--4154,-4152,-4151,-4150,-4152,-4158,-4167,-4181,-4200,-4222,-4248,-4276,-4306,-4336,-4365,-4393,-4418,-4441,-4461,-4479,-4496,
--4512,-4529,-4547,-4567,-4591,-4618,-4648,-4682,-4718,-4756,-4794,-4831,-4867,-4899,-4928,-4952,-4972,-4988,-4999,-5007,-5013,
--5018,-5022,-5028,-5035,-5045,-5058,-5074,-5094,-5116,-5140,-5167,-5195,-5224,-5252,-5281,-5308,-5334,-5360,-5383,-5405,-5426,
--5446,-5464,-5481,-5498,-5513,-5528,-5543,-5557,-5571,-5586,-5600,-5615,-5631,-5646,-5662,-5677,-5693,-5707,-5721,-5733,-5744,
--5753,-5760,-5764,-5767,-5767,-5766,-5763,-5759,-5754,-5748,-5743,-5737,-5730,-5723,-5716,-5708,-5698,-5688,-5676,-5663,-5649,
--5633,-5617,-5601,-5586,-5571,-5557,-5545,-5534,-5524,-5516,-5508,-5500,-5491,-5480,-5467,-5451,-5431,-5409,-5384,-5357,-5330,
--5303,-5279,-5257,-5241,-5231,-5228,-5232,-5243,-5261,-5284,-5312,-5343,-5376,-5408,-5439,-5467,-5490,-5510,-5525,-5535,-5542,
--5545,-5546,-5545,-5544,-5542,-5540,-5539,-5537,-5536,-5535,-5534,-5532,-5530,-5527,-5524,-5522,-5520,-5520,-5522,-5527,-5536,
--5548,-5563,-5582,-5602,-5623,-5644,-5662,-5678,-5689,-5695,-5695,-5689,-5677,-5660,-5639,-5616,-5592,-5569,-5548,-5531,-5519,
--5512,-5510,-5514,-5522,-5535,-5550,-5566,-5584,-5601,-5617,-5631,-5644,-5655,-5664,-5672,-5680,-5687,-5695,-5704,-5714,-5725,
--5737,-5750,-5764,-5777,-5790,-5802,-5813,-5822,-5830,-5836,-5840,-5844,-5846,-5847,-5848,-5848,-5848,-5847,-5846,-5845,-5843,
--5841,-5837,-5834,-5829,-5824,-5818,-5813,-5807,-5801,-5797,-5792,-5789,-5787,-5785,-5785,-5785,-5786,-5788,-5790,-5792,-5794,
--5797,-5799,-5801,-5803,-5805,-5807,-5810,-5813,-5816,-5819,-5823,-5828,-5833,-5838,-5844,-5850,-5856,-5862,-5868,-5874,-5880,
--5885,-5889,-5891,-5893,-5892,-5890,-5885,-5879,-5870,-5859,-5847,-5833,-5818,-5803,-5787,-5772,-5757,-5743,-5731,-5720,-5710,
--5702,-5694,-5688,-5682,-5677,-5672,-5668,-5662,-5657,-5652,-5646,-5640,-5634,-5628,-5622,-5617,-5611,-5607,-5602,-5597,-5593,
--5589,-5584,-5579,-5574,-5568,-5562,-5556,-5549,-5543,-5536,-5529,-5523,-5517,-5510,-5504,-5497,-5490,-5482,-5473,-5463,-5452,
--5440,-5426,-5412,-5396,-5379,-5362,-5345,-5327,-5310,-5293,-5276,-5260,-5244,-5227,-5211,-5194,-5176,-5156,-5135,-5113,-5088,
--5061,-5033,-5002,-4971,-4938,-4905,-4871,-4838,-4806,-4775,-4746,-4720,-4695,-4673,-4652,-4634,-4618,-4604,-4590,-4577,-4564,
--4551,-4538,-4524,-4508,-4492,-4475,-4457,-4438,-4419,-4401,-4382,-4365,-4349,-4334,-4321,-4309,-4299,-4291,-4283,-4277,-4271,
--4265,-4259,-4252,-4244,-4234,-4223,-4211,-4197,-4181,-4164,-4146,-4126,-4106,-4085,-4062,-4039,-4015,-3990,-3963,-3936,-3907,
--3876,-3845,-3813,-3781,-3748,-3717,-3688,-3661,-3637,-3617,-3602,-3593,-3588,-3589,-3594,-3605,-3619,-3636,-3654,-3674,-3693,
--3711,-3726,-3738,-3746,-3751,-3752,-3749,-3743,-3735,-3725,-3715,-3704,-3693,-3684,-3676,-3669,-3664,-3660,-3658,-3656,-3654,
--3652,-3649,-3646,-3642,-3636,-3630,-3623,-3615,-3607,-3600,-3592,-3585,-3578,-3572,-3567,-3562,-3557,-3551,-3546,-3540,-3533,
--3525,-3518,-3510,-3502,-3494,-3487,-3481,-3477,-3474,-3472,-3471,-3471,-3471,-3472,-3471,-3470,-3466,-3460,-3452,-3441,-3427,
--3411,-3392,-3372,-3351,-3330,-3309,-3288,-3268,-3250,-3232,-3217,-3202,-3189,-3176,-3163,-3150,-3137,-3124,-3110,-3096,-3081,
--3065,-3050,-3034,-3019,-3004,-2989,-2973,-2958,-2942,-2926,-2909,-2890,-2870,-2849,-2826,-2801,-2776,-2749,-2722,-2696,-2669,
--2644,-2620,-2597,-2575,-2554,-2535,-2516,-2498,-2479,-2460,-2441,-2420,-2398,-2376,-2352,-2328,-2304,-2279,-2256,-2233,-2212,
--2192,-2173,-2156,-2139,-2122,-2106,-2088,-2069,-2049,-2026,-2001,-1975,-1946,-1916,-1886,-1857,-1829,-1804,-1782,-1766,-1755,
--1750,-1751,-1760,-1775,-1795,-1820,-1849,-1881,-1913,-1944,-1973,-1998,-2018,-2031,-2036,-2034,-2023,-2004,-1977,-1944,-1905,
--1863,-1819,-1774,-1732,-1695,-1663,-1638,-1622,-1616,-1620,-1635,-1659,-1691,-1731,-1777,-1826,-1877,-1928,-1975,-2019,-2057,
--2087,-2109,-2122,-2126,-2122,-2111,-2093,-2071,-2044,-2016,-1987,-1959,-1933,-1911,-1892,-1877,-1865,-1858,-1853,-1850,-1848,
--1847,-1844,-1840,-1833,-1824,-1811,-1796,-1779,-1759,-1739,-1720,-1701,-1685,-1672,-1662,-1656,-1655,-1657,-1663,-1671,-1680,
--1689,-1697,-1703,-1706,-1705,-1699,-1688,-1673,-1654,-1632,-1607,-1582,-1556,-1532,-1510,-1490,-1474,-1462,-1453,-1447,-1444,
--1443,-1442,-1442,-1442,-1440,-1437,-1433,-1426,-1419,-1411,-1402,-1394,-1386,-1380,-1375,-1372,-1372,-1373,-1375,-1379,-1383,
--1387,-1390,-1393,-1395,-1395,-1395,-1393,-1391,-1389,-1387,-1386,-1386,-1387,-1389,-1393,-1397,-1402,-1408,-1412,-1416,-1419,
--1420,-1418,-1414,-1408,-1400,-1389,-1378,-1365,-1352,-1339,-1327,-1315,-1304,-1294,-1285,-1278,-1271,-1265,-1259,-1254,-1248,
--1243,-1238,-1234,-1229,-1226,-1222,-1220,-1218,-1217,-1217,-1218,-1218,-1219,-1220,-1221,-1221,-1220,-1219,-1218,-1216,-1214,
--1213,-1212,-1211,-1211,-1212,-1213,-1214,-1216,-1217,-1217,-1215,-1213,-1208,-1201,-1193,-1182,-1171,-1158,-1145,-1132,-1119,
--1107,-1095,-1083,-1072,-1060,-1046,-1031,-1013,-992,-966,-937,-904,-867,-827,-784,-741,-697,-655,-615,-578,-544,
--515,-491,-470,-452,-437,-425,-413,-401,-389,-376,-362,-347,-332,-316,-301,-286,-272,-260,-250,-241,-233,
--227,-221,-214,-207,-199,-190,-179,-168,-156,-145,-134,-125,-119,-116,-116,-120,-126,-134,-143,-152,-159,
--164,-164,-159,-148,-132,-110,-83,-52,-19,14,47,79,106,130,149,162,171,175,176,174,171,
-168,165,164,164,165,169,173,178,182,186,189,190,189,187,183,177,171,165,159,155,152,
-151,152,155,161,167,175,184,193,202,211,219,226,232,238,242,246,249,252,253,254,254,
-252,250,245,239,231,222,212,200,188,176,164,28,10,-5,-19,-31,-38,-42,-42,-38,-31,
--20,-6,9,27,46,65,84,102,120,137,152,167,181,193,206,218,229,241,253,265,278,
-290,303,316,330,343,357,370,383,395,407,418,428,437,445,452,458,463,467,471,474,478,
-482,486,491,498,506,515,526,538,552,567,582,599,617,635,653,672,691,710,729,749,769,
-789,808,828,847,866,884,900,916,929,942,952,961,969,976,982,989,995,1003,1011,1021,1032,
-1045,1059,1074,1089,1105,1120,1134,1146,1157,1166,1172,1177,1180,1182,1183,1183,1183,1183,1184,1186,1187,
-1190,1192,1194,1195,1195,1194,1191,1187,1181,1173,1164,1153,1143,1132,1121,1112,1103,1095,1088,1082,1077,
-1073,1069,1065,1061,1057,1052,1047,1041,1035,1030,1025,1020,1017,1014,1013,1012,1013,1014,1016,1018,1020,
-1023,1025,1027,1030,1032,1035,1038,1042,1047,1052,1058,1064,1069,1074,1078,1080,1080,1078,1073,1065,1054,
-1042,1027,1012,997,983,970,960,952,948,947,949,953,960,968,976,984,991,995,997,997,994,
-989,982,975,967,960,954,950,949,951,957,965,975,988,1001,1016,1030,1043,1054,1064,1070,1074,
-1075,1072,1067,1060,1051,1039,1027,1013,999,985,972,958,946,935,925,918,912,908,907,908,911,
-915,921,928,935,941,945,948,948,945,938,928,915,899,880,859,837,816,794,775,757,741,
-728,717,707,699,692,684,675,665,652,636,617,595,571,545,518,491,465,441,420,403,390,
-381,378,378,382,389,398,407,416,424,430,434,434,432,426,418,409,399,388,379,371,366,
-363,363,366,371,378,386,394,400,405,407,406,401,392,379,363,344,323,301,279,258,238,
-219,203,188,176,164,152,141,128,114,98,80,59,36,11,-13,-40,-65,-89,-111,-130,-145,
--157,-166,-171,-173,-173,-172,-171,-169,-169,-170,-174,-179,-187,-196,-208,-221,-236,-252,-268,-285,-303,
--321,-341,-361,-384,-407,-433,-460,-489,-521,-553,-587,-621,-656,-690,-724,-757,-789,-820,-850,-880,-910,
--941,-972,-1006,-1041,-1079,-1120,-1163,-1209,-1257,-1307,-1358,-1409,-1460,-1511,-1560,-1606,-1651,-1692,-1731,-1766,-1799,
--1828,-1856,-1881,-1904,-1925,-1945,-1963,-1980,-1994,-2007,-2018,-2027,-2033,-2037,-2039,-2039,-2037,-2034,-2031,-2027,-2025,
--2024,-2027,-2032,-2042,-2057,-2076,-2101,-2131,-2165,-2202,-2244,-2287,-2332,-2377,-2422,-2466,-2509,-2549,-2588,-2625,-2660,
--2694,-2728,-2761,-2795,-2830,-2866,-2903,-2941,-2981,-3021,-3062,-3103,-3143,-3182,-3220,-3256,-3290,-3322,-3353,-3383,-3412,
--3440,-3469,-3498,-3527,-3557,-3587,-3618,-3648,-3677,-3705,-3731,-3756,-3779,-3799,-3818,-3836,-3852,-3869,-3886,-3905,-3926,
--3948,-3973,-4001,-4029,-4060,-4090,-4119,-4147,-4172,-4193,-4211,-4224,-4232,-4237,-4239,-4239,-4237,-4235,-4235,-4237,-4241,
--4249,-4261,-4276,-4295,-4316,-4338,-4361,-4385,-4407,-4428,-4448,-4466,-4483,-4499,-4515,-4531,-4549,-4568,-4590,-4615,-4643,
--4673,-4705,-4738,-4773,-4807,-4840,-4870,-4898,-4923,-4945,-4963,-4978,-4991,-5002,-5012,-5021,-5031,-5042,-5056,-5071,-5088,
--5108,-5131,-5155,-5180,-5207,-5233,-5260,-5285,-5310,-5333,-5354,-5373,-5391,-5408,-5423,-5438,-5452,-5467,-5482,-5498,-5515,
--5533,-5552,-5572,-5594,-5615,-5637,-5659,-5679,-5698,-5715,-5730,-5741,-5750,-5755,-5758,-5758,-5755,-5751,-5746,-5740,-5735,
--5729,-5725,-5721,-5718,-5715,-5713,-5711,-5708,-5703,-5698,-5690,-5680,-5668,-5654,-5638,-5620,-5602,-5583,-5564,-5545,-5526,
--5509,-5492,-5476,-5459,-5442,-5425,-5406,-5386,-5364,-5341,-5317,-5292,-5268,-5245,-5225,-5208,-5195,-5187,-5185,-5189,-5199,
--5214,-5234,-5257,-5283,-5310,-5337,-5363,-5387,-5408,-5426,-5440,-5450,-5458,-5462,-5465,-5465,-5464,-5462,-5460,-5457,-5454,
--5450,-5446,-5442,-5437,-5433,-5429,-5425,-5423,-5423,-5426,-5431,-5440,-5453,-5469,-5488,-5511,-5534,-5559,-5583,-5604,-5623,
--5638,-5647,-5650,-5648,-5641,-5628,-5612,-5592,-5572,-5551,-5531,-5514,-5501,-5491,-5486,-5485,-5488,-5494,-5504,-5516,-5529,
--5543,-5557,-5571,-5585,-5598,-5610,-5622,-5634,-5646,-5658,-5671,-5684,-5698,-5712,-5726,-5739,-5752,-5764,-5774,-5784,-5791,
--5797,-5802,-5806,-5808,-5811,-5813,-5815,-5817,-5819,-5821,-5823,-5824,-5825,-5826,-5825,-5823,-5820,-5816,-5811,-5805,-5798,
--5791,-5784,-5778,-5772,-5767,-5763,-5761,-5759,-5759,-5761,-5763,-5765,-5769,-5772,-5776,-5779,-5782,-5785,-5787,-5788,-5789,
--5789,-5790,-5789,-5789,-5789,-5788,-5788,-5788,-5788,-5789,-5790,-5791,-5793,-5794,-5796,-5797,-5798,-5799,-5798,-5797,-5795,
--5792,-5787,-5782,-5775,-5768,-5759,-5750,-5741,-5731,-5722,-5712,-5703,-5694,-5685,-5676,-5667,-5658,-5649,-5640,-5630,-5620,
--5609,-5598,-5587,-5575,-5564,-5552,-5542,-5531,-5522,-5514,-5507,-5501,-5497,-5494,-5491,-5490,-5489,-5488,-5487,-5487,-5486,
--5484,-5481,-5478,-5473,-5468,-5461,-5452,-5443,-5432,-5420,-5408,-5394,-5380,-5366,-5351,-5337,-5322,-5308,-5295,-5282,-5270,
--5259,-5248,-5238,-5228,-5218,-5208,-5197,-5185,-5172,-5158,-5141,-5124,-5104,-5083,-5061,-5037,-5013,-4988,-4963,-4939,-4915,
--4893,-4872,-4853,-4836,-4819,-4805,-4791,-4778,-4764,-4751,-4737,-4721,-4704,-4685,-4664,-4642,-4617,-4592,-4565,-4538,-4512,
--4486,-4462,-4441,-4421,-4405,-4391,-4380,-4372,-4367,-4363,-4360,-4358,-4355,-4352,-4347,-4341,-4332,-4320,-4306,-4290,-4271,
--4250,-4228,-4204,-4179,-4154,-4128,-4102,-4075,-4049,-4022,-3995,-3968,-3941,-3914,-3886,-3859,-3833,-3809,-3786,-3766,-3749,
--3735,-3726,-3720,-3719,-3722,-3729,-3738,-3751,-3764,-3778,-3792,-3804,-3814,-3821,-3826,-3826,-3823,-3817,-3808,-3796,-3783,
--3769,-3754,-3740,-3727,-3714,-3703,-3693,-3685,-3677,-3671,-3665,-3659,-3653,-3647,-3641,-3634,-3627,-3621,-3614,-3608,-3603,
--3599,-3596,-3593,-3591,-3589,-3588,-3586,-3583,-3579,-3573,-3566,-3557,-3547,-3535,-3523,-3510,-3498,-3486,-3477,-3469,-3463,
--3459,-3458,-3459,-3462,-3465,-3470,-3474,-3477,-3479,-3479,-3476,-3472,-3465,-3456,-3445,-3433,-3419,-3405,-3390,-3375,-3360,
--3346,-3331,-3316,-3301,-3286,-3270,-3253,-3236,-3218,-3200,-3182,-3164,-3147,-3132,-3118,-3105,-3094,-3085,-3077,-3070,-3064,
--3057,-3049,-3039,-3027,-3012,-2994,-2973,-2949,-2922,-2893,-2862,-2831,-2798,-2766,-2735,-2704,-2675,-2646,-2619,-2592,-2565,
--2538,-2511,-2482,-2453,-2423,-2392,-2361,-2329,-2299,-2269,-2241,-2216,-2192,-2171,-2151,-2134,-2117,-2100,-2083,-2064,-2042,
--2018,-1990,-1958,-1924,-1887,-1848,-1809,-1771,-1736,-1706,-1681,-1664,-1655,-1656,-1666,-1685,-1713,-1748,-1790,-1836,-1883,
--1931,-1977,-2020,-2056,-2085,-2105,-2115,-2116,-2107,-2088,-2061,-2026,-1985,-1939,-1891,-1843,-1795,-1751,-1712,-1680,-1655,
--1639,-1633,-1636,-1649,-1671,-1700,-1736,-1777,-1821,-1867,-1911,-1953,-1990,-2021,-2045,-2060,-2067,-2064,-2054,-2035,-2011,
--1982,-1949,-1915,-1881,-1850,-1821,-1797,-1777,-1763,-1753,-1748,-1747,-1749,-1752,-1755,-1757,-1757,-1754,-1748,-1739,-1726,
--1711,-1693,-1675,-1657,-1640,-1625,-1613,-1605,-1600,-1600,-1603,-1609,-1617,-1626,-1636,-1644,-1651,-1655,-1655,-1652,-1646,
--1636,-1624,-1610,-1594,-1579,-1563,-1549,-1537,-1526,-1518,-1512,-1507,-1503,-1500,-1496,-1493,-1488,-1483,-1476,-1467,-1458,
--1449,-1439,-1430,-1422,-1415,-1410,-1406,-1405,-1405,-1406,-1408,-1411,-1413,-1415,-1416,-1416,-1415,-1413,-1410,-1407,-1404,
--1402,-1400,-1400,-1401,-1404,-1409,-1415,-1422,-1430,-1438,-1444,-1450,-1454,-1456,-1455,-1453,-1447,-1440,-1431,-1421,-1410,
--1399,-1388,-1378,-1368,-1360,-1352,-1345,-1338,-1332,-1327,-1321,-1316,-1311,-1306,-1302,-1298,-1295,-1293,-1292,-1292,-1294,
--1296,-1299,-1302,-1306,-1310,-1312,-1314,-1315,-1315,-1313,-1311,-1307,-1304,-1300,-1296,-1294,-1292,-1290,-1290,-1290,-1291,
--1291,-1291,-1289,-1286,-1280,-1272,-1262,-1249,-1234,-1217,-1198,-1179,-1158,-1138,-1118,-1097,-1077,-1056,-1035,-1012,-988,
--961,-932,-899,-864,-827,-787,-747,-706,-666,-628,-593,-562,-536,-515,-499,-488,-482,-480,-481,-484,-488,
--492,-495,-497,-496,-494,-489,-482,-473,-462,-450,-437,-423,-408,-394,-378,-363,-347,-331,-315,-299,-283,
--268,-254,-242,-231,-222,-216,-212,-210,-210,-211,-213,-214,-214,-212,-208,-200,-189,-175,-158,-138,-116,
--93,-70,-48,-28,-10,5,17,26,32,35,37,38,38,38,38,38,39,40,42,43,44,
-44,42,38,33,27,19,10,2,-6,-14,-20,-24,-26,-26,-24,-19,-12,-4,4,13,23,
-33,42,51,60,68,76,84,92,99,107,114,120,125,128,130,129,125,118,108,96,81,
-64,46,28,-63,-84,-103,-120,-133,-142,-147,-147,-142,-134,-121,-106,-88,-69,-49,-29,-10,7,
-24,39,53,65,77,88,99,111,123,135,149,164,180,196,213,230,247,263,279,293,307,
-319,329,338,346,353,359,364,368,372,376,381,385,390,395,401,408,415,423,431,441,450,
-461,472,485,498,512,527,544,562,581,602,623,646,669,693,717,741,764,786,807,825,842,
-857,869,879,888,895,901,907,912,918,926,934,944,956,969,984,999,1015,1031,1046,1061,1074,
-1085,1094,1101,1106,1109,1111,1112,1112,1113,1113,1114,1116,1118,1121,1125,1128,1131,1134,1135,1135,1133,
-1130,1124,1118,1109,1100,1089,1078,1067,1056,1045,1035,1025,1016,1007,999,992,984,977,971,964,958,
-952,948,944,941,939,938,938,940,942,946,950,954,959,964,969,974,979,984,990,995,1001,
-1006,1012,1018,1024,1029,1033,1035,1037,1036,1032,1026,1018,1008,996,982,967,953,939,926,916,908,
-902,900,900,903,908,914,921,928,933,938,940,941,939,935,929,922,915,908,903,899,897,
-898,901,908,918,929,943,958,973,988,1002,1014,1023,1030,1034,1035,1032,1026,1018,1008,995,981,
-967,952,938,925,912,902,894,888,885,883,884,888,892,898,905,911,918,922,925,926,924,
-919,911,900,886,870,853,834,815,797,779,763,749,736,725,716,708,700,691,682,671,658,
-643,624,603,579,553,526,498,471,445,421,401,385,373,365,362,362,366,373,381,390,399,
-406,411,414,414,411,406,399,390,381,372,364,358,355,354,356,361,368,376,386,395,402,
-408,410,408,403,393,378,360,339,315,289,263,237,213,189,168,149,132,116,101,87,72,
-56,39,19,-2,-26,-52,-80,-109,-137,-165,-192,-215,-236,-252,-265,-273,-278,-278,-276,-271,-265,
--258,-252,-246,-241,-239,-238,-240,-245,-252,-262,-275,-289,-306,-325,-346,-369,-394,-421,-449,-479,-511,
--543,-577,-611,-645,-680,-714,-748,-781,-813,-845,-877,-908,-940,-972,-1006,-1040,-1077,-1115,-1156,-1198,-1242,
--1287,-1334,-1381,-1428,-1474,-1520,-1564,-1606,-1647,-1685,-1722,-1756,-1789,-1821,-1852,-1882,-1912,-1940,-1968,-1995,-2021,
--2044,-2065,-2084,-2098,-2109,-2116,-2118,-2117,-2112,-2104,-2094,-2084,-2073,-2065,-2059,-2057,-2060,-2069,-2084,-2105,-2132,
--2165,-2202,-2244,-2288,-2333,-2380,-2425,-2470,-2512,-2553,-2591,-2627,-2662,-2695,-2728,-2761,-2795,-2829,-2865,-2903,-2942,
--2982,-3023,-3064,-3105,-3144,-3183,-3220,-3254,-3287,-3318,-3348,-3377,-3405,-3433,-3461,-3491,-3521,-3552,-3584,-3616,-3648,
--3680,-3710,-3739,-3765,-3789,-3811,-3830,-3848,-3865,-3881,-3897,-3915,-3934,-3956,-3980,-4006,-4035,-4065,-4097,-4128,-4157,
--4185,-4209,-4229,-4245,-4256,-4263,-4265,-4265,-4262,-4258,-4254,-4251,-4250,-4253,-4258,-4268,-4281,-4297,-4316,-4336,-4358,
--4380,-4402,-4422,-4442,-4460,-4476,-4492,-4508,-4524,-4541,-4560,-4581,-4604,-4629,-4657,-4687,-4718,-4750,-4783,-4815,-4845,
--4873,-4899,-4923,-4943,-4961,-4977,-4990,-5003,-5015,-5028,-5041,-5055,-5071,-5089,-5109,-5130,-5153,-5177,-5201,-5225,-5249,
--5272,-5294,-5315,-5334,-5351,-5368,-5383,-5399,-5414,-5430,-5446,-5464,-5484,-5504,-5527,-5550,-5575,-5599,-5623,-5647,-5668,
--5687,-5704,-5717,-5727,-5734,-5737,-5737,-5734,-5730,-5724,-5718,-5712,-5706,-5701,-5698,-5696,-5695,-5695,-5695,-5695,-5695,
--5693,-5690,-5685,-5677,-5667,-5654,-5639,-5622,-5604,-5584,-5563,-5542,-5521,-5500,-5479,-5458,-5437,-5415,-5393,-5370,-5346,
--5322,-5298,-5273,-5250,-5228,-5208,-5192,-5179,-5171,-5168,-5171,-5178,-5191,-5208,-5229,-5253,-5278,-5304,-5328,-5352,-5372,
--5390,-5404,-5415,-5421,-5425,-5426,-5424,-5420,-5415,-5410,-5404,-5398,-5392,-5386,-5381,-5377,-5373,-5371,-5369,-5369,-5370,
--5373,-5378,-5386,-5397,-5410,-5426,-5444,-5464,-5485,-5506,-5526,-5544,-5560,-5573,-5581,-5586,-5585,-5581,-5572,-5561,-5546,
--5531,-5514,-5498,-5484,-5471,-5461,-5454,-5450,-5449,-5451,-5455,-5462,-5471,-5481,-5493,-5505,-5518,-5531,-5545,-5559,-5574,
--5589,-5605,-5620,-5636,-5651,-5666,-5681,-5695,-5707,-5718,-5728,-5736,-5744,-5750,-5755,-5760,-5764,-5768,-5772,-5777,-5782,
--5787,-5792,-5796,-5801,-5804,-5806,-5807,-5806,-5804,-5799,-5793,-5786,-5777,-5768,-5759,-5750,-5742,-5734,-5729,-5725,-5723,
--5723,-5724,-5727,-5731,-5737,-5742,-5748,-5753,-5758,-5762,-5765,-5766,-5766,-5764,-5761,-5757,-5751,-5745,-5738,-5731,-5724,
--5718,-5712,-5707,-5703,-5700,-5699,-5699,-5700,-5702,-5704,-5708,-5711,-5714,-5717,-5719,-5720,-5720,-5718,-5716,-5711,-5706,
--5699,-5691,-5682,-5673,-5663,-5652,-5641,-5630,-5618,-5606,-5593,-5581,-5567,-5554,-5540,-5526,-5511,-5497,-5483,-5469,-5456,
--5444,-5433,-5424,-5417,-5412,-5408,-5406,-5406,-5407,-5409,-5412,-5416,-5419,-5421,-5423,-5423,-5421,-5417,-5412,-5404,-5394,
--5383,-5370,-5356,-5341,-5326,-5311,-5296,-5283,-5270,-5259,-5249,-5240,-5233,-5226,-5221,-5215,-5209,-5203,-5196,-5188,-5178,
--5167,-5154,-5140,-5124,-5107,-5089,-5071,-5054,-5037,-5021,-5006,-4993,-4982,-4973,-4966,-4960,-4955,-4950,-4945,-4939,-4932,
--4922,-4910,-4894,-4875,-4852,-4825,-4796,-4763,-4729,-4693,-4657,-4621,-4587,-4556,-4527,-4502,-4482,-4465,-4453,-4445,-4440,
--4438,-4438,-4438,-4439,-4440,-4438,-4435,-4429,-4420,-4408,-4392,-4374,-4352,-4328,-4302,-4275,-4246,-4216,-4185,-4154,-4123,
--4092,-4060,-4029,-3998,-3968,-3939,-3911,-3884,-3860,-3839,-3820,-3805,-3794,-3788,-3785,-3787,-3792,-3801,-3812,-3826,-3840,
--3854,-3867,-3878,-3886,-3892,-3894,-3892,-3887,-3878,-3867,-3853,-3837,-3821,-3803,-3786,-3769,-3753,-3738,-3724,-3711,-3699,
--3687,-3676,-3665,-3654,-3643,-3633,-3622,-3613,-3604,-3597,-3590,-3586,-3582,-3581,-3580,-3580,-3581,-3582,-3582,-3581,-3579,
--3575,-3569,-3560,-3550,-3538,-3525,-3511,-3497,-3484,-3472,-3462,-3455,-3450,-3448,-3448,-3451,-3455,-3461,-3467,-3473,-3478,
--3483,-3486,-3487,-3486,-3484,-3480,-3474,-3467,-3459,-3450,-3440,-3429,-3417,-3405,-3391,-3376,-3359,-3342,-3322,-3302,-3281,
--3259,-3237,-3217,-3197,-3179,-3164,-3152,-3142,-3135,-3130,-3127,-3126,-3124,-3122,-3119,-3113,-3104,-3091,-3075,-3055,-3031,
--3004,-2975,-2943,-2910,-2877,-2844,-2811,-2778,-2747,-2715,-2684,-2653,-2621,-2588,-2554,-2518,-2480,-2442,-2402,-2363,-2324,
--2287,-2252,-2219,-2190,-2165,-2143,-2123,-2106,-2090,-2074,-2057,-2038,-2015,-1988,-1956,-1920,-1880,-1836,-1791,-1746,-1703,
--1664,-1632,-1607,-1593,-1589,-1597,-1616,-1647,-1688,-1737,-1793,-1852,-1914,-1973,-2030,-2080,-2123,-2156,-2179,-2191,-2193,
--2183,-2164,-2137,-2103,-2063,-2020,-1975,-1930,-1887,-1847,-1811,-1781,-1757,-1741,-1731,-1729,-1734,-1746,-1764,-1788,-1815,
--1845,-1877,-1908,-1938,-1966,-1989,-2007,-2019,-2024,-2022,-2014,-1999,-1978,-1953,-1925,-1895,-1864,-1835,-1808,-1784,-1765,
--1750,-1741,-1736,-1735,-1737,-1742,-1748,-1754,-1759,-1761,-1761,-1758,-1751,-1741,-1729,-1714,-1698,-1682,-1667,-1653,-1641,
--1632,-1626,-1623,-1623,-1625,-1629,-1634,-1639,-1644,-1648,-1651,-1652,-1650,-1647,-1642,-1635,-1627,-1619,-1610,-1601,-1592,
--1584,-1577,-1570,-1564,-1558,-1551,-1545,-1538,-1530,-1522,-1514,-1505,-1497,-1489,-1481,-1474,-1469,-1464,-1461,-1459,-1458,
--1458,-1457,-1457,-1457,-1455,-1453,-1450,-1445,-1441,-1435,-1430,-1425,-1421,-1418,-1417,-1418,-1421,-1425,-1431,-1438,-1446,
--1454,-1461,-1466,-1470,-1472,-1471,-1468,-1463,-1456,-1448,-1438,-1428,-1419,-1409,-1401,-1393,-1387,-1382,-1378,-1375,-1373,
--1371,-1370,-1368,-1367,-1366,-1364,-1363,-1363,-1363,-1363,-1365,-1367,-1371,-1375,-1379,-1383,-1387,-1390,-1392,-1393,-1392,
--1389,-1385,-1380,-1373,-1367,-1360,-1353,-1348,-1343,-1340,-1338,-1336,-1335,-1333,-1331,-1327,-1321,-1312,-1301,-1285,-1267,
--1245,-1221,-1195,-1167,-1138,-1109,-1080,-1052,-1025,-998,-973,-949,-924,-900,-875,-849,-822,-794,-766,-737,-708,
--680,-654,-630,-610,-594,-582,-575,-573,-575,-581,-590,-602,-615,-628,-640,-650,-658,-662,-663,-660,-653,
--643,-629,-612,-593,-572,-550,-527,-504,-480,-457,-435,-415,-395,-377,-361,-347,-335,-324,-315,-308,-302,
--297,-293,-289,-284,-278,-272,-264,-255,-245,-233,-220,-207,-193,-179,-166,-154,-142,-133,-124,-117,-111,
--106,-102,-99,-95,-92,-88,-85,-81,-78,-75,-73,-72,-73,-75,-79,-85,-92,-100,-109,-118,-127,
--135,-141,-145,-148,-148,-147,-143,-138,-131,-124,-115,-107,-98,-90,-81,-73,-64,-55,-45,-35,-24,
--13,-1,9,20,29,37,41,43,41,36,26,13,-2,-21,-42,-63,-125,-144,-161,-176,-187,
--194,-196,-194,-186,-175,-160,-142,-122,-102,-81,-62,-43,-26,-11,1,12,22,32,41,51,61,
-72,85,100,116,133,151,170,188,207,224,240,255,267,278,287,295,301,306,310,314,318,
-322,327,333,339,346,354,363,372,382,392,402,412,422,432,443,454,466,478,492,506,522,
-540,558,578,599,620,642,664,685,706,725,742,758,772,783,793,801,808,814,820,826,833,
-840,849,859,871,884,898,913,929,944,959,973,985,996,1005,1011,1016,1019,1021,1022,1022,1022,
-1022,1023,1024,1027,1030,1034,1039,1043,1047,1051,1053,1054,1054,1051,1047,1041,1033,1024,1013,1003,991,
-980,969,959,949,940,932,925,918,913,907,903,899,895,892,890,888,887,886,887,888,890,
-892,895,899,902,906,911,915,919,924,929,934,939,944,950,956,962,968,973,978,982,984,
-985,984,981,975,968,959,949,938,926,914,903,893,885,878,874,872,872,874,877,882,886,
-891,895,898,899,900,898,896,893,889,886,883,882,882,885,890,897,907,919,933,948,963,
-979,993,1007,1018,1026,1031,1033,1032,1027,1019,1009,997,982,967,952,936,922,909,897,888,881,
-877,875,876,878,882,887,892,897,901,904,905,903,900,893,884,872,858,843,826,809,792,
-775,759,745,731,720,710,701,692,684,676,667,656,644,630,613,594,574,551,528,504,481,
-459,439,422,407,396,389,385,384,386,390,395,400,406,410,413,413,412,409,404,397,389,
-381,374,367,362,360,359,361,365,371,378,385,392,397,401,401,398,391,381,366,349,328,
-305,281,256,231,208,186,166,148,132,118,105,92,79,66,51,34,15,-6,-30,-56,-83,
--111,-138,-165,-190,-212,-231,-247,-258,-265,-268,-268,-265,-260,-253,-246,-239,-233,-229,-227,-228,-231,
--239,-249,-262,-279,-299,-321,-346,-372,-401,-431,-463,-496,-530,-564,-599,-634,-669,-703,-737,-771,-805,
--838,-870,-902,-934,-967,-999,-1033,-1067,-1101,-1137,-1174,-1212,-1251,-1290,-1330,-1369,-1409,-1448,-1487,-1525,-1562,
--1599,-1635,-1671,-1706,-1742,-1779,-1816,-1853,-1891,-1929,-1966,-2002,-2037,-2070,-2099,-2125,-2145,-2161,-2172,-2177,-2178,
--2173,-2166,-2155,-2144,-2132,-2122,-2115,-2112,-2114,-2122,-2136,-2156,-2181,-2213,-2248,-2287,-2329,-2371,-2414,-2456,-2497,
--2535,-2571,-2605,-2638,-2668,-2699,-2728,-2759,-2791,-2824,-2859,-2896,-2934,-2974,-3014,-3054,-3094,-3133,-3170,-3205,-3238,
--3269,-3297,-3325,-3350,-3376,-3401,-3427,-3453,-3482,-3511,-3542,-3574,-3606,-3638,-3670,-3701,-3731,-3758,-3783,-3807,-3828,
--3848,-3866,-3885,-3904,-3923,-3944,-3966,-3990,-4016,-4043,-4070,-4098,-4124,-4149,-4171,-4190,-4206,-4217,-4225,-4229,-4230,
--4230,-4228,-4226,-4225,-4226,-4229,-4235,-4244,-4256,-4272,-4289,-4309,-4330,-4352,-4373,-4394,-4413,-4432,-4449,-4465,-4481,
--4497,-4513,-4531,-4550,-4572,-4595,-4621,-4650,-4680,-4712,-4744,-4776,-4808,-4839,-4867,-4893,-4916,-4937,-4955,-4971,-4985,
--4998,-5010,-5022,-5035,-5048,-5063,-5080,-5098,-5118,-5140,-5162,-5185,-5208,-5231,-5253,-5275,-5296,-5316,-5335,-5353,-5371,
--5389,-5407,-5426,-5445,-5465,-5486,-5508,-5531,-5553,-5576,-5597,-5618,-5637,-5653,-5667,-5679,-5687,-5693,-5696,-5697,-5697,
--5694,-5691,-5687,-5684,-5681,-5678,-5676,-5674,-5673,-5672,-5671,-5670,-5667,-5664,-5659,-5652,-5643,-5633,-5621,-5608,-5594,
--5578,-5562,-5545,-5528,-5510,-5492,-5472,-5452,-5431,-5408,-5385,-5360,-5334,-5308,-5282,-5256,-5232,-5211,-5193,-5179,-5170,
--5167,-5169,-5178,-5192,-5211,-5234,-5260,-5288,-5317,-5345,-5371,-5394,-5413,-5427,-5437,-5442,-5442,-5438,-5431,-5421,-5410,
--5398,-5385,-5374,-5363,-5354,-5347,-5342,-5339,-5338,-5339,-5342,-5346,-5351,-5358,-5366,-5375,-5385,-5396,-5408,-5420,-5433,
--5446,-5459,-5470,-5481,-5490,-5498,-5503,-5505,-5505,-5503,-5498,-5491,-5482,-5472,-5462,-5451,-5441,-5432,-5424,-5417,-5413,
--5410,-5410,-5411,-5415,-5420,-5428,-5436,-5447,-5458,-5471,-5485,-5499,-5515,-5531,-5547,-5563,-5579,-5595,-5610,-5624,-5637,
--5650,-5661,-5670,-5679,-5687,-5694,-5701,-5707,-5713,-5720,-5726,-5732,-5739,-5746,-5752,-5757,-5762,-5766,-5768,-5768,-5767,
--5763,-5758,-5751,-5743,-5734,-5724,-5714,-5705,-5696,-5689,-5684,-5681,-5679,-5680,-5682,-5687,-5692,-5699,-5706,-5714,-5720,
--5727,-5731,-5735,-5736,-5736,-5734,-5730,-5724,-5716,-5708,-5698,-5688,-5677,-5667,-5658,-5650,-5643,-5638,-5634,-5633,-5633,
--5634,-5637,-5641,-5645,-5650,-5654,-5658,-5660,-5661,-5660,-5658,-5653,-5647,-5639,-5629,-5618,-5605,-5592,-5578,-5564,-5550,
--5536,-5522,-5509,-5495,-5482,-5469,-5456,-5443,-5430,-5417,-5405,-5393,-5382,-5372,-5364,-5356,-5351,-5347,-5346,-5347,-5349,
--5353,-5359,-5365,-5372,-5379,-5385,-5390,-5393,-5394,-5392,-5388,-5380,-5371,-5358,-5344,-5329,-5312,-5295,-5279,-5263,-5249,
--5236,-5225,-5216,-5208,-5202,-5198,-5194,-5191,-5187,-5182,-5177,-5169,-5161,-5150,-5138,-5124,-5110,-5095,-5080,-5066,-5053,
--5043,-5035,-5029,-5027,-5027,-5030,-5035,-5041,-5048,-5055,-5060,-5062,-5062,-5057,-5048,-5033,-5013,-4989,-4959,-4925,-4887,
--4847,-4806,-4764,-4724,-4685,-4650,-4618,-4591,-4568,-4550,-4537,-4527,-4521,-4518,-4516,-4515,-4514,-4513,-4509,-4504,-4496,
--4485,-4471,-4454,-4435,-4413,-4388,-4362,-4334,-4305,-4274,-4243,-4211,-4179,-4147,-4114,-4082,-4050,-4019,-3989,-3961,-3935,
--3911,-3890,-3873,-3860,-3851,-3846,-3844,-3847,-3852,-3861,-3871,-3882,-3893,-3904,-3914,-3921,-3926,-3927,-3926,-3921,-3913,
--3903,-3890,-3876,-3860,-3843,-3826,-3808,-3791,-3774,-3757,-3741,-3724,-3708,-3693,-3677,-3661,-3646,-3631,-3616,-3603,-3591,
--3581,-3572,-3566,-3561,-3559,-3558,-3558,-3560,-3562,-3563,-3564,-3564,-3561,-3557,-3550,-3540,-3529,-3517,-3503,-3489,-3475,
--3462,-3450,-3441,-3433,-3429,-3426,-3426,-3428,-3432,-3437,-3443,-3448,-3454,-3458,-3462,-3465,-3466,-3465,-3464,-3461,-3457,
--3452,-3445,-3437,-3428,-3418,-3405,-3391,-3375,-3358,-3338,-3317,-3296,-3273,-3251,-3229,-3209,-3190,-3174,-3161,-3150,-3142,
--3137,-3133,-3130,-3128,-3126,-3122,-3116,-3108,-3096,-3080,-3062,-3040,-3015,-2988,-2959,-2930,-2900,-2870,-2841,-2813,-2785,
--2757,-2729,-2701,-2670,-2638,-2603,-2566,-2526,-2483,-2439,-2394,-2349,-2305,-2262,-2223,-2188,-2157,-2131,-2109,-2090,-2074,
--2058,-2043,-2025,-2004,-1979,-1948,-1911,-1868,-1821,-1770,-1717,-1664,-1615,-1571,-1536,-1511,-1498,-1499,-1515,-1545,-1588,
--1643,-1709,-1781,-1857,-1935,-2010,-2080,-2142,-2194,-2235,-2263,-2278,-2281,-2273,-2254,-2227,-2194,-2156,-2115,-2074,-2034,
--1997,-1963,-1935,-1911,-1894,-1882,-1875,-1874,-1878,-1886,-1897,-1912,-1929,-1947,-1965,-1984,-2001,-2017,-2030,-2040,-2046,
--2048,-2046,-2039,-2028,-2013,-1995,-1973,-1951,-1927,-1904,-1881,-1861,-1844,-1830,-1819,-1812,-1809,-1808,-1810,-1813,-1817,
--1821,-1824,-1825,-1824,-1820,-1813,-1804,-1792,-1778,-1763,-1747,-1731,-1716,-1703,-1691,-1680,-1673,-1667,-1664,-1663,-1663,
--1664,-1665,-1667,-1668,-1670,-1670,-1669,-1668,-1665,-1661,-1657,-1651,-1645,-1638,-1631,-1623,-1615,-1607,-1598,-1590,-1581,
--1573,-1565,-1558,-1552,-1546,-1542,-1538,-1536,-1535,-1534,-1534,-1534,-1534,-1534,-1533,-1530,-1526,-1522,-1515,-1508,-1501,
--1493,-1485,-1478,-1473,-1469,-1467,-1467,-1469,-1474,-1479,-1485,-1492,-1499,-1504,-1508,-1510,-1509,-1506,-1500,-1491,-1481,
--1469,-1456,-1442,-1430,-1418,-1407,-1399,-1393,-1389,-1387,-1387,-1388,-1391,-1395,-1399,-1403,-1408,-1412,-1416,-1420,-1424,
--1427,-1431,-1435,-1439,-1443,-1446,-1450,-1452,-1454,-1454,-1453,-1450,-1446,-1440,-1433,-1425,-1417,-1408,-1399,-1391,-1384,
--1378,-1373,-1369,-1365,-1361,-1356,-1349,-1340,-1329,-1313,-1294,-1270,-1243,-1213,-1179,-1144,-1108,-1071,-1036,-1002,-971,
--943,-918,-897,-879,-864,-851,-840,-830,-819,-809,-798,-786,-774,-761,-748,-735,-723,-713,-705,-700,-698,
--699,-703,-710,-719,-730,-741,-752,-763,-771,-777,-780,-779,-775,-766,-755,-739,-722,-701,-679,-657,-633,
--610,-588,-567,-547,-528,-512,-497,-484,-473,-462,-453,-445,-437,-429,-421,-413,-405,-396,-386,-376,-366,
--356,-345,-335,-325,-315,-307,-299,-291,-285,-279,-274,-269,-264,-259,-254,-249,-243,-237,-231,-225,-220,
--215,-211,-208,-206,-206,-207,-210,-214,-218,-222,-227,-231,-235,-237,-238,-237,-235,-231,-226,-221,-215,
--208,-202,-195,-189,-183,-177,-171,-165,-157,-149,-140,-129,-117,-104,-90,-76,-63,-50,-40,-32,-28,
--28,-32,-40,-52,-67,-85,-105,-125,-201,-218,-233,-246,-254,-258,-257,-251,-241,-226,-209,-189,-167,
--145,-123,-102,-83,-66,-51,-38,-27,-17,-8,0,7,17,27,39,52,67,83,100,117,134,
-151,167,182,195,206,216,224,231,236,241,246,250,256,262,269,277,286,297,308,320,332,
-345,357,369,381,393,404,415,426,437,448,460,472,485,499,514,529,545,561,577,593,607,
-621,633,644,654,662,669,675,680,686,691,697,704,713,723,734,747,762,777,793,809,825,
-839,852,864,873,880,885,887,887,886,884,881,878,875,873,872,873,874,877,881,886,891,
-896,900,904,906,907,906,903,899,894,887,879,871,862,854,847,840,834,829,825,822,820,
-819,819,819,820,821,822,824,825,827,829,830,832,834,835,837,839,840,842,843,845,847,
-849,852,855,859,864,869,874,881,887,894,901,908,914,919,922,924,924,923,920,915,909,
-902,894,887,879,872,866,861,858,856,855,856,858,861,864,867,870,873,876,877,879,880,
-881,882,884,887,891,897,905,914,925,938,952,967,982,998,1012,1025,1036,1045,1051,1054,1054,
-1051,1045,1035,1024,1011,996,981,965,949,935,921,909,899,890,883,878,874,870,868,865,863,
-859,854,848,841,831,820,807,793,777,761,744,728,712,697,683,670,659,649,640,633,627,
-620,614,608,600,591,581,570,557,543,527,511,494,478,462,448,435,424,416,409,405,404,
-404,405,408,411,413,416,418,418,418,416,414,410,406,402,398,395,393,392,392,393,396,
-399,402,405,407,408,406,402,396,387,374,359,342,323,303,282,261,241,222,205,189,175,
-162,151,141,131,120,109,96,81,64,44,23,0,-26,-52,-79,-106,-131,-154,-174,-191,-205,
--216,-222,-226,-227,-225,-222,-219,-215,-212,-211,-211,-214,-221,-230,-242,-258,-277,-299,-323,-350,-379,
--411,-443,-477,-512,-547,-583,-619,-656,-692,-728,-764,-800,-835,-869,-903,-937,-970,-1003,-1035,-1067,-1099,
--1130,-1161,-1192,-1223,-1254,-1284,-1314,-1344,-1374,-1404,-1434,-1465,-1496,-1528,-1561,-1596,-1632,-1670,-1710,-1752,-1795,
--1840,-1885,-1930,-1975,-2019,-2060,-2097,-2131,-2160,-2183,-2202,-2215,-2223,-2226,-2226,-2223,-2219,-2215,-2212,-2210,-2213,
--2219,-2229,-2244,-2265,-2289,-2317,-2348,-2382,-2416,-2451,-2486,-2519,-2550,-2580,-2607,-2633,-2658,-2682,-2707,-2732,-2759,
--2787,-2818,-2851,-2887,-2924,-2963,-3003,-3043,-3083,-3121,-3158,-3192,-3224,-3253,-3280,-3305,-3329,-3352,-3374,-3397,-3420,
--3445,-3471,-3499,-3529,-3559,-3591,-3623,-3654,-3685,-3715,-3743,-3769,-3794,-3817,-3838,-3859,-3879,-3899,-3919,-3940,-3961,
--3984,-4007,-4030,-4053,-4076,-4098,-4118,-4136,-4151,-4165,-4175,-4184,-4190,-4195,-4198,-4202,-4206,-4211,-4217,-4225,-4236,
--4248,-4263,-4279,-4296,-4315,-4333,-4352,-4370,-4388,-4405,-4422,-4438,-4454,-4471,-4489,-4508,-4528,-4551,-4576,-4604,-4634,
--4665,-4698,-4731,-4765,-4798,-4830,-4860,-4887,-4912,-4935,-4954,-4971,-4985,-4998,-5010,-5021,-5032,-5043,-5056,-5069,-5084,
--5101,-5120,-5139,-5160,-5182,-5204,-5227,-5250,-5272,-5294,-5316,-5337,-5358,-5378,-5398,-5418,-5438,-5457,-5477,-5496,-5515,
--5533,-5551,-5568,-5583,-5598,-5610,-5621,-5631,-5639,-5645,-5650,-5654,-5656,-5658,-5659,-5659,-5659,-5659,-5658,-5656,-5654,
--5651,-5647,-5642,-5637,-5630,-5622,-5613,-5604,-5594,-5584,-5573,-5563,-5553,-5544,-5534,-5525,-5515,-5504,-5492,-5478,-5462,
--5444,-5424,-5401,-5375,-5348,-5320,-5291,-5263,-5237,-5215,-5196,-5184,-5177,-5177,-5184,-5198,-5218,-5244,-5274,-5306,-5341,
--5375,-5407,-5436,-5460,-5479,-5492,-5498,-5498,-5492,-5481,-5466,-5448,-5428,-5407,-5387,-5368,-5352,-5338,-5328,-5321,-5318,
--5317,-5319,-5324,-5330,-5337,-5344,-5352,-5361,-5368,-5376,-5383,-5390,-5396,-5401,-5407,-5412,-5416,-5420,-5423,-5425,-5427,
--5428,-5427,-5426,-5424,-5420,-5416,-5412,-5406,-5401,-5396,-5391,-5386,-5383,-5380,-5379,-5380,-5382,-5386,-5392,-5399,-5408,
--5418,-5430,-5443,-5457,-5472,-5487,-5502,-5518,-5533,-5547,-5561,-5574,-5586,-5597,-5608,-5617,-5626,-5634,-5642,-5650,-5657,
--5664,-5671,-5678,-5685,-5691,-5697,-5701,-5705,-5708,-5710,-5710,-5708,-5705,-5700,-5695,-5688,-5680,-5673,-5665,-5657,-5651,
--5645,-5640,-5637,-5636,-5636,-5638,-5641,-5645,-5650,-5655,-5661,-5666,-5671,-5675,-5679,-5681,-5682,-5681,-5679,-5675,-5671,
--5665,-5658,-5651,-5643,-5635,-5628,-5621,-5614,-5609,-5605,-5602,-5601,-5600,-5601,-5603,-5605,-5607,-5610,-5612,-5613,-5613,
--5611,-5608,-5602,-5595,-5586,-5575,-5563,-5549,-5535,-5520,-5504,-5488,-5473,-5458,-5444,-5430,-5418,-5405,-5394,-5383,-5373,
--5364,-5355,-5347,-5339,-5333,-5327,-5323,-5321,-5320,-5321,-5324,-5329,-5335,-5344,-5353,-5363,-5373,-5382,-5391,-5397,-5401,
--5402,-5401,-5395,-5387,-5375,-5360,-5343,-5324,-5304,-5284,-5264,-5245,-5227,-5212,-5199,-5188,-5180,-5173,-5169,-5165,-5162,
--5160,-5156,-5152,-5146,-5139,-5130,-5119,-5108,-5095,-5083,-5071,-5060,-5051,-5045,-5041,-5041,-5045,-5051,-5061,-5073,-5086,
--5100,-5113,-5125,-5134,-5139,-5140,-5135,-5125,-5110,-5088,-5061,-5030,-4995,-4957,-4917,-4877,-4837,-4799,-4764,-4732,-4703,
--4678,-4657,-4640,-4627,-4616,-4607,-4599,-4593,-4586,-4578,-4570,-4559,-4547,-4533,-4517,-4498,-4478,-4456,-4433,-4408,-4383,
--4356,-4329,-4302,-4274,-4246,-4217,-4189,-4161,-4133,-4106,-4080,-4055,-4032,-4011,-3993,-3977,-3964,-3955,-3948,-3944,-3943,
--3944,-3946,-3949,-3953,-3957,-3960,-3961,-3961,-3959,-3954,-3948,-3939,-3929,-3917,-3903,-3889,-3873,-3858,-3841,-3825,-3808,
--3791,-3774,-3757,-3739,-3721,-3702,-3684,-3665,-3646,-3629,-3611,-3596,-3582,-3569,-3559,-3552,-3546,-3543,-3541,-3541,-3541,
--3542,-3543,-3542,-3540,-3536,-3530,-3522,-3512,-3500,-3486,-3471,-3456,-3441,-3427,-3414,-3403,-3394,-3388,-3384,-3382,-3382,
--3384,-3387,-3391,-3396,-3401,-3406,-3411,-3415,-3417,-3419,-3420,-3419,-3417,-3413,-3408,-3400,-3391,-3380,-3367,-3351,-3334,
--3316,-3296,-3275,-3253,-3232,-3212,-3192,-3175,-3159,-3146,-3135,-3126,-3119,-3113,-3108,-3103,-3097,-3090,-3080,-3067,-3052,
--3034,-3013,-2989,-2964,-2937,-2910,-2882,-2856,-2830,-2806,-2784,-2762,-2741,-2720,-2698,-2674,-2647,-2618,-2584,-2547,-2507,
--2463,-2417,-2370,-2323,-2278,-2235,-2195,-2160,-2130,-2104,-2083,-2065,-2049,-2032,-2015,-1994,-1967,-1935,-1895,-1847,-1793,
--1733,-1668,-1602,-1538,-1477,-1425,-1383,-1354,-1342,-1347,-1370,-1412,-1470,-1543,-1629,-1724,-1824,-1925,-2024,-2117,-2200,
--2271,-2327,-2368,-2394,-2404,-2400,-2384,-2357,-2322,-2282,-2240,-2197,-2156,-2118,-2086,-2059,-2038,-2024,-2016,-2013,-2015,
--2022,-2031,-2043,-2056,-2070,-2085,-2098,-2111,-2122,-2131,-2138,-2143,-2145,-2144,-2140,-2133,-2124,-2111,-2096,-2078,-2059,
--2038,-2017,-1995,-1975,-1955,-1938,-1922,-1910,-1899,-1891,-1886,-1882,-1880,-1879,-1878,-1877,-1875,-1872,-1866,-1859,-1850,
--1839,-1826,-1811,-1796,-1780,-1764,-1749,-1735,-1723,-1712,-1703,-1696,-1691,-1688,-1687,-1687,-1688,-1691,-1693,-1696,-1698,
--1699,-1700,-1699,-1697,-1694,-1689,-1683,-1676,-1668,-1659,-1650,-1640,-1632,-1623,-1616,-1611,-1606,-1604,-1602,-1602,-1604,
--1606,-1608,-1611,-1613,-1614,-1614,-1613,-1610,-1605,-1599,-1592,-1584,-1575,-1567,-1559,-1553,-1549,-1546,-1546,-1547,-1551,
--1556,-1562,-1568,-1574,-1579,-1582,-1582,-1580,-1574,-1565,-1554,-1539,-1523,-1505,-1487,-1469,-1451,-1436,-1422,-1412,-1404,
--1399,-1398,-1399,-1402,-1407,-1415,-1423,-1432,-1441,-1450,-1459,-1467,-1475,-1482,-1488,-1493,-1498,-1501,-1504,-1505,-1505,
--1504,-1501,-1497,-1491,-1485,-1477,-1468,-1459,-1450,-1442,-1434,-1426,-1420,-1414,-1409,-1404,-1398,-1390,-1381,-1369,-1353,
--1334,-1310,-1282,-1249,-1213,-1174,-1132,-1089,-1047,-1006,-969,-935,-906,-883,-865,-854,-848,-847,-851,-857,-866,
--875,-884,-891,-897,-900,-900,-897,-892,-885,-876,-867,-858,-849,-842,-837,-833,-832,-832,-835,-838,-842,
--845,-848,-850,-850,-847,-842,-835,-825,-813,-799,-784,-767,-751,-734,-717,-702,-687,-674,-662,-652,-642,
--633,-625,-618,-611,-603,-595,-587,-579,-570,-560,-551,-541,-531,-521,-512,-503,-495,-487,-481,-474,-469,
--463,-458,-453,-448,-443,-437,-431,-425,-419,-412,-406,-400,-395,-390,-387,-384,-383,-382,-381,-381,-382,
--381,-381,-379,-376,-372,-367,-361,-353,-345,-336,-327,-318,-310,-302,-295,-290,-284,-280,-275,-271,-265,
--259,-251,-241,-230,-217,-202,-187,-171,-156,-142,-130,-121,-116,-114,-117,-124,-135,-149,-165,-183,-201,
--291,-308,-322,-333,-341,-344,-342,-335,-324,-309,-291,-270,-247,-224,-201,-179,-158,-140,-124,-110,-98,
--88,-79,-70,-62,-54,-45,-34,-23,-11,2,16,31,45,60,74,87,99,109,119,127,134,
-141,148,154,161,169,177,187,198,209,222,235,249,263,277,290,303,316,328,339,350,360,
-370,380,390,401,411,422,434,445,456,467,478,488,497,505,512,518,522,526,530,533,537,
-541,547,553,562,572,584,598,614,630,648,665,682,698,712,725,735,742,746,748,747,744,
-739,733,726,719,713,707,703,701,699,700,701,704,708,711,715,719,722,724,725,724,723,
-720,717,714,710,706,702,699,697,696,696,697,699,703,707,711,716,722,727,733,738,743,
-747,751,755,758,760,762,763,764,765,765,765,765,766,767,768,770,773,777,782,787,794,
-802,810,819,828,837,846,854,860,866,870,872,873,872,870,866,862,858,852,848,843,840,
-837,835,835,835,836,838,841,844,848,852,857,861,866,871,877,883,891,899,908,919,930,
-943,957,971,986,1001,1015,1028,1041,1051,1059,1065,1068,1069,1067,1062,1055,1045,1034,1021,1007,992,
-977,962,947,932,918,904,891,879,866,854,842,830,817,803,789,774,758,742,725,708,690,
-673,656,639,624,610,597,585,575,567,559,554,549,544,541,537,533,529,524,518,511,504,
-495,486,476,465,455,445,436,427,419,413,408,404,402,401,401,402,404,406,409,412,414,
-417,420,422,424,426,429,431,433,435,437,439,441,443,444,443,442,439,434,427,418,407,
-394,379,363,345,327,309,291,273,257,241,227,215,204,193,184,175,165,155,143,130,115,
-98,78,56,33,8,-17,-44,-70,-94,-118,-139,-157,-173,-186,-195,-202,-206,-209,-210,-210,-210,
--210,-212,-215,-220,-228,-238,-251,-267,-286,-308,-333,-360,-389,-421,-454,-488,-525,-562,-600,-638,-677,
--716,-755,-794,-832,-870,-907,-943,-977,-1011,-1043,-1074,-1104,-1132,-1159,-1184,-1209,-1232,-1255,-1277,-1298,-1319,
--1341,-1363,-1385,-1409,-1435,-1462,-1492,-1524,-1559,-1596,-1636,-1679,-1724,-1770,-1818,-1866,-1914,-1962,-2007,-2049,-2089,
--2124,-2156,-2183,-2205,-2224,-2239,-2251,-2261,-2269,-2277,-2285,-2294,-2306,-2319,-2335,-2354,-2375,-2399,-2424,-2450,-2477,
--2504,-2530,-2555,-2579,-2601,-2621,-2641,-2659,-2677,-2696,-2715,-2736,-2760,-2786,-2814,-2846,-2880,-2917,-2955,-2994,-3034,
--3074,-3112,-3149,-3183,-3215,-3245,-3272,-3297,-3320,-3342,-3363,-3385,-3407,-3429,-3453,-3479,-3506,-3534,-3563,-3593,-3623,
--3653,-3683,-3711,-3739,-3765,-3789,-3813,-3835,-3856,-3877,-3897,-3918,-3938,-3959,-3980,-4002,-4023,-4044,-4065,-4085,-4103,
--4120,-4136,-4150,-4162,-4172,-4182,-4190,-4197,-4205,-4212,-4219,-4228,-4237,-4248,-4259,-4271,-4284,-4298,-4313,-4328,-4343,
--4359,-4375,-4391,-4408,-4426,-4445,-4465,-4488,-4512,-4538,-4566,-4596,-4628,-4662,-4696,-4731,-4766,-4800,-4832,-4863,-4892,
--4918,-4942,-4962,-4981,-4997,-5010,-5023,-5034,-5045,-5056,-5067,-5079,-5091,-5105,-5121,-5137,-5155,-5174,-5195,-5215,-5237,
--5259,-5281,-5303,-5325,-5347,-5368,-5389,-5409,-5428,-5447,-5464,-5481,-5497,-5511,-5525,-5537,-5548,-5558,-5567,-5576,-5583,
--5589,-5595,-5601,-5606,-5610,-5614,-5617,-5620,-5622,-5623,-5623,-5621,-5619,-5614,-5608,-5601,-5593,-5584,-5575,-5565,-5556,
--5547,-5539,-5532,-5527,-5523,-5519,-5517,-5514,-5511,-5507,-5501,-5492,-5480,-5465,-5446,-5423,-5397,-5369,-5339,-5309,-5280,
--5253,-5230,-5212,-5201,-5196,-5200,-5211,-5229,-5255,-5286,-5322,-5361,-5400,-5439,-5475,-5506,-5532,-5551,-5563,-5567,-5564,
--5554,-5537,-5516,-5491,-5464,-5437,-5409,-5384,-5361,-5342,-5326,-5315,-5307,-5303,-5302,-5304,-5307,-5312,-5318,-5323,-5329,
--5334,-5338,-5341,-5344,-5347,-5349,-5351,-5353,-5355,-5357,-5360,-5363,-5365,-5368,-5370,-5372,-5373,-5373,-5372,-5371,-5369,
--5366,-5362,-5359,-5355,-5353,-5350,-5350,-5350,-5352,-5356,-5362,-5369,-5379,-5389,-5401,-5415,-5428,-5443,-5457,-5472,-5486,
--5499,-5512,-5524,-5535,-5546,-5556,-5565,-5574,-5582,-5590,-5598,-5605,-5612,-5619,-5626,-5632,-5637,-5642,-5645,-5647,-5649,
--5648,-5647,-5644,-5641,-5636,-5631,-5626,-5620,-5614,-5609,-5605,-5602,-5599,-5597,-5597,-5597,-5598,-5599,-5601,-5604,-5606,
--5608,-5610,-5611,-5612,-5612,-5612,-5611,-5610,-5609,-5607,-5606,-5604,-5602,-5600,-5598,-5597,-5595,-5594,-5593,-5592,-5591,
--5591,-5590,-5590,-5590,-5590,-5590,-5589,-5589,-5588,-5586,-5584,-5581,-5578,-5573,-5567,-5559,-5551,-5541,-5530,-5518,-5505,
--5492,-5478,-5463,-5449,-5435,-5422,-5408,-5396,-5383,-5372,-5361,-5352,-5342,-5334,-5327,-5320,-5315,-5311,-5308,-5308,-5309,
--5311,-5316,-5323,-5331,-5341,-5352,-5364,-5376,-5388,-5399,-5408,-5415,-5418,-5419,-5416,-5409,-5398,-5384,-5366,-5346,-5324,
--5301,-5277,-5253,-5231,-5211,-5193,-5177,-5164,-5154,-5147,-5142,-5138,-5136,-5135,-5133,-5131,-5127,-5123,-5117,-5109,-5101,
--5092,-5082,-5073,-5064,-5058,-5053,-5051,-5052,-5056,-5063,-5073,-5085,-5098,-5112,-5126,-5139,-5149,-5156,-5160,-5158,-5152,
--5141,-5125,-5104,-5079,-5051,-5019,-4986,-4952,-4917,-4884,-4852,-4822,-4794,-4770,-4748,-4728,-4711,-4696,-4683,-4671,-4659,
--4647,-4635,-4622,-4607,-4592,-4575,-4557,-4538,-4517,-4496,-4474,-4451,-4427,-4403,-4379,-4355,-4330,-4306,-4282,-4259,-4235,
--4213,-4191,-4170,-4151,-4133,-4117,-4102,-4090,-4079,-4070,-4063,-4057,-4053,-4049,-4045,-4042,-4038,-4034,-4028,-4021,-4013,
--4004,-3993,-3981,-3968,-3953,-3939,-3923,-3908,-3892,-3876,-3860,-3844,-3828,-3811,-3794,-3776,-3758,-3739,-3719,-3699,-3678,
--3658,-3638,-3619,-3601,-3584,-3570,-3557,-3547,-3539,-3532,-3528,-3525,-3522,-3520,-3518,-3515,-3511,-3505,-3497,-3488,-3477,
--3464,-3450,-3435,-3419,-3403,-3388,-3374,-3362,-3351,-3343,-3336,-3332,-3331,-3331,-3333,-3337,-3342,-3347,-3354,-3360,-3366,
--3372,-3376,-3380,-3381,-3381,-3378,-3374,-3366,-3357,-3344,-3329,-3313,-3294,-3274,-3253,-3231,-3210,-3189,-3170,-3152,-3137,
--3123,-3112,-3102,-3094,-3087,-3080,-3073,-3065,-3055,-3043,-3028,-3010,-2989,-2966,-2941,-2915,-2888,-2860,-2834,-2809,-2785,
--2764,-2744,-2727,-2710,-2694,-2677,-2659,-2638,-2614,-2586,-2554,-2518,-2478,-2435,-2390,-2344,-2298,-2254,-2213,-2176,-2143,
--2115,-2091,-2071,-2053,-2035,-2017,-1995,-1968,-1934,-1892,-1841,-1782,-1715,-1641,-1563,-1484,-1408,-1337,-1275,-1227,-1196,
--1184,-1192,-1223,-1275,-1347,-1437,-1543,-1660,-1784,-1910,-2033,-2150,-2256,-2348,-2424,-2481,-2519,-2538,-2540,-2527,-2500,
--2463,-2419,-2370,-2321,-2273,-2229,-2190,-2159,-2135,-2119,-2111,-2109,-2114,-2124,-2138,-2154,-2171,-2189,-2206,-2222,-2237,
--2248,-2257,-2264,-2267,-2267,-2264,-2259,-2250,-2238,-2224,-2207,-2187,-2166,-2142,-2118,-2092,-2067,-2041,-2017,-1994,-1973,
--1954,-1938,-1925,-1914,-1905,-1899,-1895,-1892,-1890,-1888,-1886,-1882,-1878,-1872,-1865,-1855,-1844,-1832,-1818,-1804,-1789,
--1775,-1761,-1749,-1738,-1730,-1723,-1718,-1716,-1716,-1717,-1720,-1724,-1728,-1732,-1736,-1739,-1740,-1740,-1738,-1735,-1730,
--1724,-1716,-1708,-1700,-1691,-1684,-1677,-1671,-1667,-1665,-1664,-1665,-1667,-1670,-1673,-1676,-1679,-1681,-1681,-1680,-1678,
--1674,-1669,-1662,-1655,-1647,-1640,-1634,-1628,-1625,-1623,-1623,-1624,-1627,-1632,-1637,-1641,-1645,-1648,-1648,-1646,-1641,
--1633,-1622,-1607,-1590,-1571,-1551,-1530,-1509,-1489,-1470,-1454,-1441,-1430,-1423,-1420,-1419,-1422,-1427,-1434,-1443,-1453,
--1465,-1476,-1487,-1499,-1509,-1518,-1527,-1534,-1539,-1543,-1546,-1546,-1545,-1542,-1538,-1532,-1525,-1518,-1509,-1501,-1493,
--1485,-1477,-1471,-1465,-1459,-1454,-1449,-1443,-1435,-1426,-1413,-1397,-1377,-1352,-1323,-1290,-1252,-1211,-1168,-1123,-1079,
--1036,-996,-960,-930,-907,-891,-882,-880,-885,-897,-913,-933,-955,-977,-999,-1019,-1036,-1049,-1057,-1060,-1059,
--1053,-1044,-1032,-1017,-1002,-986,-971,-957,-944,-934,-926,-920,-916,-913,-911,-909,-907,-905,-902,-897,-892,
--885,-877,-868,-858,-848,-837,-827,-817,-808,-799,-791,-783,-777,-770,-764,-759,-753,-747,-741,-734,-727,
--720,-713,-706,-699,-692,-685,-679,-673,-667,-662,-657,-652,-647,-642,-637,-631,-626,-619,-613,-606,-600,
--593,-587,-581,-576,-572,-569,-566,-564,-563,-562,-560,-559,-557,-553,-548,-542,-534,-525,-514,-503,-490,
--477,-464,-452,-440,-430,-420,-412,-405,-400,-394,-389,-383,-376,-368,-358,-346,-333,-318,-301,-284,-266,
--250,-235,-222,-213,-207,-205,-208,-215,-226,-240,-256,-273,-291,-362,-377,-391,-401,-408,-411,-409,-403,
--393,-379,-361,-341,-319,-297,-275,-253,-232,-214,-197,-183,-170,-159,-149,-140,-132,-124,-115,-106,-96,
--85,-74,-61,-48,-35,-22,-9,2,14,25,36,45,54,63,71,80,89,99,109,120,131,
-143,156,169,183,196,209,222,234,246,257,267,277,287,296,305,315,324,334,344,353,363,
-373,382,391,399,407,413,418,423,426,429,432,435,438,442,448,455,463,474,487,501,516,
-533,550,567,584,600,614,626,636,643,647,649,648,645,640,634,627,619,612,605,599,594,
-590,588,587,587,588,590,592,594,596,598,599,599,599,599,598,596,595,594,593,593,593,
-594,596,599,603,607,613,618,625,631,638,644,650,656,662,667,672,676,680,682,685,687,
-688,690,691,692,694,695,697,700,704,708,714,720,728,736,745,755,765,775,785,794,803,
-811,817,822,826,827,828,827,826,823,820,816,813,809,806,804,802,802,802,803,805,808,
-812,817,823,830,837,845,853,863,874,885,897,910,923,938,952,967,981,996,1009,1021,1032,
-1042,1049,1055,1058,1059,1058,1054,1049,1041,1032,1022,1010,997,984,970,955,940,925,909,893,877,
-860,843,825,807,789,770,751,732,712,693,674,656,638,621,605,590,577,565,555,545,537,
-531,525,520,516,512,509,506,502,499,495,491,486,481,476,470,463,457,450,443,437,431,
-425,420,415,412,409,407,405,405,406,408,410,414,418,423,429,435,442,449,456,462,469,
-475,480,483,486,487,486,484,479,472,463,452,439,425,409,392,375,357,339,322,305,289,
-275,262,249,238,228,218,209,199,188,177,164,150,134,116,96,75,52,28,3,-21,-45,
--69,-91,-112,-130,-146,-160,-172,-181,-189,-194,-199,-202,-205,-209,-213,-218,-224,-232,-243,-256,-271,
--289,-310,-334,-360,-389,-420,-454,-490,-527,-567,-607,-648,-690,-733,-775,-816,-857,-897,-935,-971,-1006,
--1038,-1068,-1097,-1123,-1147,-1169,-1190,-1209,-1227,-1245,-1262,-1279,-1296,-1314,-1333,-1354,-1375,-1399,-1425,-1453,-1484,
--1517,-1552,-1589,-1628,-1670,-1712,-1755,-1799,-1843,-1886,-1928,-1968,-2007,-2043,-2076,-2107,-2136,-2161,-2185,-2207,-2228,
--2248,-2267,-2286,-2306,-2326,-2348,-2370,-2393,-2417,-2441,-2466,-2490,-2514,-2537,-2558,-2579,-2598,-2616,-2633,-2649,-2665,
--2681,-2698,-2717,-2738,-2760,-2785,-2813,-2844,-2876,-2911,-2947,-2985,-3022,-3060,-3096,-3131,-3165,-3196,-3225,-3252,-3278,
--3302,-3325,-3347,-3368,-3390,-3413,-3437,-3461,-3487,-3514,-3541,-3570,-3598,-3627,-3656,-3684,-3711,-3738,-3763,-3788,-3811,
--3834,-3856,-3878,-3900,-3921,-3943,-3964,-3986,-4007,-4028,-4048,-4068,-4086,-4104,-4120,-4135,-4148,-4159,-4169,-4178,-4186,
--4193,-4200,-4206,-4213,-4220,-4228,-4236,-4245,-4256,-4267,-4279,-4293,-4307,-4323,-4339,-4357,-4376,-4397,-4419,-4442,-4467,
--4494,-4522,-4551,-4582,-4614,-4647,-4681,-4715,-4748,-4781,-4813,-4843,-4872,-4899,-4923,-4946,-4967,-4985,-5002,-5017,-5031,
--5044,-5057,-5069,-5081,-5093,-5105,-5119,-5133,-5148,-5164,-5181,-5199,-5218,-5237,-5257,-5278,-5298,-5319,-5340,-5360,-5380,
--5398,-5416,-5433,-5448,-5461,-5473,-5484,-5493,-5501,-5507,-5513,-5518,-5522,-5525,-5529,-5532,-5535,-5539,-5542,-5545,-5547,
--5549,-5550,-5551,-5550,-5548,-5545,-5541,-5535,-5529,-5523,-5516,-5509,-5504,-5499,-5495,-5493,-5491,-5491,-5492,-5492,-5493,
--5492,-5489,-5484,-5476,-5465,-5450,-5431,-5410,-5385,-5358,-5331,-5304,-5278,-5256,-5238,-5227,-5222,-5224,-5234,-5252,-5277,
--5308,-5345,-5385,-5426,-5468,-5508,-5544,-5576,-5600,-5617,-5627,-5628,-5621,-5607,-5586,-5561,-5531,-5500,-5467,-5435,-5405,
--5377,-5353,-5333,-5316,-5303,-5294,-5289,-5286,-5285,-5285,-5287,-5289,-5291,-5293,-5294,-5296,-5297,-5299,-5300,-5302,-5304,
--5307,-5310,-5314,-5318,-5322,-5326,-5330,-5333,-5334,-5335,-5335,-5333,-5331,-5327,-5323,-5319,-5315,-5312,-5309,-5309,-5309,
--5312,-5317,-5325,-5334,-5345,-5357,-5371,-5385,-5400,-5415,-5430,-5444,-5457,-5470,-5481,-5491,-5501,-5510,-5518,-5526,-5533,
--5540,-5548,-5555,-5562,-5569,-5575,-5581,-5586,-5590,-5594,-5595,-5596,-5595,-5592,-5589,-5585,-5580,-5575,-5570,-5565,-5560,
--5557,-5555,-5554,-5554,-5555,-5557,-5560,-5563,-5567,-5569,-5572,-5574,-5574,-5574,-5572,-5570,-5567,-5563,-5559,-5555,-5551,
--5548,-5545,-5544,-5544,-5545,-5547,-5551,-5555,-5559,-5564,-5569,-5574,-5577,-5580,-5582,-5583,-5582,-5580,-5577,-5573,-5567,
--5561,-5554,-5546,-5539,-5530,-5522,-5514,-5505,-5496,-5488,-5479,-5471,-5462,-5453,-5444,-5434,-5425,-5415,-5405,-5394,-5384,
--5373,-5363,-5352,-5342,-5332,-5323,-5315,-5307,-5301,-5297,-5294,-5293,-5294,-5297,-5303,-5310,-5319,-5330,-5341,-5354,-5366,
--5378,-5388,-5396,-5403,-5406,-5405,-5401,-5394,-5382,-5367,-5349,-5328,-5306,-5282,-5257,-5233,-5210,-5189,-5170,-5153,-5140,
--5129,-5121,-5115,-5112,-5110,-5109,-5108,-5108,-5107,-5106,-5103,-5100,-5095,-5090,-5084,-5078,-5073,-5068,-5065,-5064,-5064,
--5067,-5071,-5078,-5086,-5095,-5104,-5114,-5122,-5129,-5133,-5134,-5132,-5127,-5117,-5103,-5086,-5066,-5042,-5016,-4989,-4960,
--4931,-4903,-4875,-4849,-4825,-4802,-4781,-4763,-4746,-4730,-4716,-4702,-4689,-4677,-4663,-4650,-4635,-4619,-4602,-4585,-4565,
--4545,-4524,-4502,-4479,-4455,-4431,-4407,-4383,-4359,-4335,-4312,-4290,-4269,-4249,-4230,-4213,-4197,-4183,-4171,-4161,-4152,
--4144,-4138,-4132,-4128,-4123,-4118,-4113,-4107,-4100,-4092,-4082,-4071,-4059,-4046,-4031,-4015,-3999,-3983,-3966,-3949,-3932,
--3916,-3900,-3883,-3867,-3851,-3834,-3817,-3799,-3781,-3761,-3741,-3720,-3699,-3678,-3656,-3636,-3616,-3597,-3580,-3564,-3550,
--3539,-3529,-3521,-3514,-3508,-3503,-3499,-3494,-3489,-3482,-3475,-3467,-3457,-3446,-3434,-3421,-3407,-3393,-3380,-3367,-3354,
--3343,-3334,-3326,-3321,-3317,-3316,-3317,-3319,-3323,-3329,-3335,-3342,-3350,-3356,-3363,-3367,-3370,-3371,-3370,-3365,-3358,
--3347,-3334,-3318,-3299,-3279,-3257,-3234,-3211,-3188,-3166,-3146,-3128,-3112,-3098,-3085,-3075,-3066,-3057,-3048,-3039,-3028,
--3015,-3001,-2984,-2964,-2942,-2918,-2893,-2867,-2841,-2816,-2792,-2769,-2749,-2730,-2714,-2698,-2683,-2669,-2653,-2635,-2614,
--2589,-2561,-2529,-2492,-2453,-2410,-2366,-2321,-2277,-2236,-2197,-2162,-2132,-2105,-2083,-2063,-2046,-2027,-2007,-1983,-1953,
--1916,-1871,-1816,-1753,-1683,-1606,-1526,-1445,-1366,-1295,-1234,-1187,-1157,-1148,-1160,-1194,-1251,-1329,-1427,-1539,-1664,
--1797,-1932,-2065,-2191,-2306,-2407,-2491,-2555,-2600,-2625,-2630,-2619,-2593,-2555,-2509,-2457,-2404,-2351,-2303,-2260,-2224,
--2197,-2178,-2168,-2167,-2172,-2183,-2198,-2217,-2237,-2258,-2278,-2296,-2312,-2325,-2335,-2342,-2345,-2344,-2340,-2333,-2322,
--2309,-2293,-2274,-2253,-2229,-2204,-2177,-2148,-2119,-2090,-2061,-2033,-2007,-1983,-1961,-1942,-1927,-1914,-1905,-1899,-1896,
--1895,-1895,-1896,-1898,-1899,-1900,-1899,-1896,-1891,-1884,-1875,-1863,-1851,-1837,-1823,-1809,-1795,-1783,-1772,-1763,-1756,
--1752,-1750,-1750,-1751,-1755,-1759,-1763,-1768,-1772,-1775,-1776,-1777,-1776,-1773,-1769,-1764,-1758,-1752,-1745,-1740,-1735,
--1731,-1728,-1726,-1726,-1727,-1729,-1731,-1733,-1735,-1737,-1737,-1737,-1735,-1732,-1727,-1722,-1716,-1710,-1703,-1697,-1692,
--1687,-1684,-1682,-1682,-1682,-1683,-1685,-1687,-1687,-1687,-1685,-1681,-1675,-1666,-1654,-1640,-1624,-1605,-1586,-1566,-1545,
--1525,-1506,-1489,-1474,-1462,-1453,-1446,-1443,-1443,-1445,-1450,-1457,-1466,-1477,-1488,-1500,-1513,-1524,-1536,-1546,-1555,
--1563,-1568,-1572,-1574,-1574,-1573,-1569,-1564,-1558,-1551,-1543,-1535,-1528,-1520,-1513,-1507,-1501,-1495,-1490,-1484,-1477,
--1469,-1458,-1445,-1429,-1409,-1385,-1357,-1326,-1292,-1255,-1217,-1179,-1141,-1106,-1073,-1046,-1024,-1008,-999,-996,-1001,
--1011,-1026,-1046,-1068,-1092,-1117,-1139,-1160,-1176,-1188,-1195,-1197,-1194,-1186,-1173,-1157,-1138,-1118,-1097,-1076,-1055,
--1037,-1020,-1005,-993,-984,-976,-970,-966,-962,-960,-957,-954,-951,-948,-943,-939,-933,-927,-921,-915,-908,
--902,-895,-889,-883,-877,-871,-865,-859,-853,-847,-841,-835,-829,-823,-818,-813,-808,-804,-800,-797,-794,
--791,-789,-786,-784,-780,-777,-772,-767,-761,-755,-748,-741,-733,-726,-719,-713,-707,-702,-698,-694,-691,
--688,-686,-683,-679,-674,-669,-662,-653,-643,-632,-619,-606,-592,-578,-564,-551,-539,-528,-519,-510,-502,
--495,-488,-481,-473,-464,-454,-442,-428,-412,-395,-377,-359,-341,-324,-309,-296,-287,-281,-280,-283,-290,
--300,-313,-329,-345,-362,-416,-427,-437,-444,-448,-449,-446,-439,-428,-415,-398,-380,-360,-339,-319,-299,
--280,-262,-246,-232,-219,-208,-198,-189,-180,-171,-162,-153,-143,-132,-120,-108,-96,-83,-70,-57,-44,
--32,-20,-9,0,10,20,29,38,48,57,67,78,89,100,112,124,136,147,159,171,182,
-193,203,213,223,232,241,251,260,270,280,290,301,311,321,331,341,350,358,366,372,378,
-383,388,392,396,400,405,411,417,425,434,445,457,470,484,498,513,528,542,555,567,577,
-585,591,595,597,598,597,594,591,587,583,578,574,571,568,566,565,564,564,565,565,566,
-566,567,567,566,565,564,562,560,557,555,553,551,549,547,547,546,547,548,549,551,554,
-557,561,565,569,573,577,582,586,591,595,599,603,607,611,615,619,623,627,631,636,642,
-648,654,662,670,678,688,697,707,717,727,737,746,755,762,769,774,778,780,781,781,780,
-778,776,773,769,766,763,760,758,756,756,756,757,759,762,766,772,778,785,793,803,813,
-824,837,850,864,878,893,909,924,940,955,969,982,994,1005,1014,1021,1026,1030,1031,1030,1028,
-1023,1017,1010,1001,990,979,967,953,940,925,910,894,877,861,844,826,808,790,772,754,736,
-719,702,686,670,655,641,628,616,604,594,584,575,567,559,551,544,538,531,525,520,514,
-509,503,499,494,489,485,481,477,473,469,466,462,458,455,451,448,445,442,439,438,436,
-436,436,438,440,444,449,454,460,467,475,482,489,496,502,506,510,511,511,509,504,498,
-489,478,466,452,437,421,404,388,371,355,339,325,311,298,286,275,264,254,244,234,223,
-212,200,187,172,157,139,121,102,81,60,38,17,-4,-25,-45,-64,-82,-98,-113,-126,-138,
--149,-158,-166,-174,-181,-187,-194,-202,-211,-220,-232,-245,-260,-278,-299,-322,-348,-377,-409,-444,-481,
--521,-562,-605,-649,-694,-738,-783,-826,-868,-908,-945,-981,-1013,-1043,-1071,-1096,-1118,-1139,-1158,-1176,-1193,
--1210,-1227,-1244,-1262,-1282,-1302,-1325,-1349,-1374,-1401,-1430,-1460,-1491,-1524,-1557,-1591,-1626,-1660,-1695,-1730,-1764,
--1798,-1832,-1864,-1896,-1927,-1957,-1987,-2015,-2043,-2070,-2096,-2122,-2148,-2174,-2200,-2226,-2253,-2279,-2306,-2333,-2360,
--2387,-2413,-2439,-2465,-2489,-2513,-2535,-2557,-2578,-2598,-2618,-2637,-2657,-2677,-2697,-2719,-2743,-2767,-2794,-2822,-2851,
--2882,-2914,-2947,-2980,-3013,-3046,-3078,-3109,-3138,-3167,-3194,-3220,-3244,-3268,-3291,-3314,-3337,-3360,-3384,-3408,-3433,
--3459,-3485,-3512,-3540,-3568,-3597,-3625,-3653,-3680,-3707,-3733,-3759,-3784,-3809,-3833,-3856,-3879,-3902,-3925,-3947,-3968,
--3989,-4009,-4029,-4047,-4065,-4081,-4095,-4108,-4120,-4130,-4139,-4146,-4153,-4160,-4166,-4172,-4178,-4185,-4192,-4201,-4211,
--4222,-4234,-4248,-4263,-4279,-4297,-4315,-4335,-4356,-4378,-4401,-4425,-4449,-4475,-4501,-4528,-4556,-4585,-4613,-4643,-4672,
--4702,-4731,-4760,-4789,-4817,-4843,-4869,-4894,-4918,-4940,-4961,-4980,-4998,-5015,-5031,-5046,-5060,-5073,-5086,-5099,-5112,
--5125,-5138,-5152,-5167,-5182,-5199,-5216,-5233,-5252,-5271,-5289,-5308,-5327,-5344,-5361,-5376,-5389,-5401,-5411,-5419,-5425,
--5430,-5432,-5434,-5434,-5434,-5433,-5432,-5431,-5430,-5429,-5429,-5430,-5430,-5431,-5432,-5433,-5434,-5435,-5435,-5434,-5433,
--5432,-5430,-5429,-5427,-5426,-5424,-5423,-5423,-5423,-5422,-5422,-5420,-5418,-5415,-5409,-5402,-5392,-5379,-5365,-5348,-5330,
--5311,-5293,-5275,-5259,-5247,-5239,-5236,-5239,-5249,-5265,-5288,-5317,-5351,-5389,-5430,-5472,-5514,-5554,-5590,-5621,-5646,
--5664,-5674,-5676,-5670,-5657,-5637,-5612,-5582,-5549,-5515,-5480,-5446,-5414,-5385,-5359,-5337,-5318,-5303,-5291,-5283,-5276,
--5272,-5269,-5267,-5266,-5265,-5264,-5264,-5264,-5264,-5265,-5266,-5268,-5271,-5274,-5278,-5282,-5287,-5291,-5295,-5298,-5300,
--5301,-5301,-5299,-5296,-5292,-5287,-5281,-5276,-5271,-5267,-5264,-5264,-5266,-5270,-5276,-5285,-5296,-5309,-5323,-5338,-5354,
--5370,-5385,-5400,-5414,-5427,-5438,-5448,-5457,-5465,-5472,-5478,-5485,-5491,-5497,-5503,-5510,-5517,-5523,-5529,-5535,-5540,
--5544,-5547,-5548,-5548,-5547,-5544,-5540,-5535,-5530,-5525,-5520,-5516,-5512,-5511,-5510,-5511,-5513,-5516,-5521,-5525,-5530,
--5535,-5539,-5542,-5544,-5544,-5543,-5541,-5537,-5532,-5527,-5521,-5516,-5511,-5508,-5506,-5505,-5506,-5509,-5514,-5519,-5526,
--5533,-5541,-5548,-5553,-5558,-5560,-5561,-5559,-5555,-5549,-5540,-5530,-5518,-5505,-5492,-5478,-5465,-5452,-5440,-5429,-5419,
--5411,-5404,-5399,-5394,-5390,-5387,-5384,-5381,-5377,-5374,-5369,-5364,-5358,-5351,-5344,-5335,-5327,-5318,-5309,-5301,-5294,
--5287,-5282,-5278,-5276,-5276,-5278,-5282,-5288,-5295,-5304,-5313,-5323,-5333,-5342,-5350,-5356,-5360,-5361,-5359,-5355,-5346,
--5335,-5321,-5304,-5285,-5264,-5243,-5221,-5199,-5178,-5158,-5140,-5124,-5110,-5099,-5091,-5084,-5080,-5077,-5076,-5075,-5075,
--5076,-5076,-5075,-5075,-5074,-5072,-5070,-5069,-5067,-5066,-5065,-5066,-5067,-5069,-5073,-5077,-5082,-5087,-5091,-5096,-5099,
--5100,-5100,-5097,-5091,-5082,-5070,-5056,-5038,-5018,-4996,-4973,-4948,-4922,-4897,-4872,-4847,-4824,-4802,-4782,-4764,-4747,
--4731,-4717,-4705,-4692,-4681,-4669,-4657,-4644,-4631,-4616,-4601,-4583,-4565,-4544,-4523,-4500,-4476,-4452,-4426,-4401,-4375,
--4349,-4324,-4300,-4278,-4256,-4237,-4219,-4204,-4190,-4179,-4169,-4162,-4156,-4151,-4147,-4144,-4142,-4139,-4136,-4132,-4126,
--4120,-4112,-4102,-4091,-4078,-4064,-4050,-4034,-4018,-4002,-3985,-3969,-3953,-3937,-3922,-3907,-3892,-3877,-3861,-3846,-3829,
--3812,-3795,-3776,-3756,-3736,-3716,-3695,-3674,-3654,-3634,-3615,-3598,-3582,-3568,-3555,-3544,-3535,-3528,-3521,-3516,-3511,
--3507,-3503,-3498,-3493,-3488,-3481,-3474,-3465,-3456,-3446,-3435,-3425,-3414,-3403,-3393,-3384,-3376,-3370,-3365,-3361,-3360,
--3359,-3361,-3363,-3367,-3371,-3375,-3379,-3382,-3383,-3383,-3380,-3375,-3366,-3355,-3341,-3324,-3305,-3284,-3261,-3237,-3213,
--3190,-3167,-3145,-3125,-3107,-3091,-3076,-3063,-3050,-3039,-3027,-3015,-3002,-2987,-2971,-2953,-2933,-2911,-2888,-2864,-2840,
--2816,-2792,-2770,-2750,-2730,-2713,-2696,-2681,-2665,-2650,-2632,-2613,-2591,-2565,-2536,-2503,-2467,-2428,-2387,-2345,-2302,
--2261,-2222,-2186,-2153,-2124,-2099,-2078,-2060,-2043,-2026,-2007,-1985,-1959,-1927,-1888,-1842,-1788,-1729,-1665,-1598,-1530,
--1466,-1408,-1358,-1321,-1299,-1294,-1307,-1340,-1392,-1462,-1548,-1648,-1758,-1875,-1994,-2112,-2223,-2326,-2416,-2491,-2549,
--2590,-2614,-2621,-2613,-2592,-2560,-2520,-2476,-2430,-2384,-2342,-2304,-2273,-2248,-2231,-2222,-2219,-2222,-2230,-2242,-2256,
--2272,-2287,-2302,-2315,-2326,-2334,-2340,-2343,-2343,-2340,-2335,-2328,-2318,-2307,-2294,-2278,-2261,-2243,-2222,-2200,-2176,
--2151,-2126,-2100,-2073,-2048,-2023,-2001,-1980,-1962,-1947,-1936,-1927,-1922,-1919,-1919,-1921,-1923,-1927,-1930,-1933,-1934,
--1934,-1931,-1926,-1918,-1908,-1896,-1882,-1868,-1853,-1838,-1823,-1810,-1799,-1789,-1782,-1778,-1775,-1775,-1777,-1780,-1784,
--1789,-1793,-1798,-1802,-1804,-1806,-1807,-1806,-1805,-1802,-1800,-1797,-1794,-1791,-1789,-1787,-1786,-1786,-1787,-1788,-1789,
--1790,-1791,-1791,-1791,-1790,-1788,-1786,-1782,-1778,-1773,-1768,-1763,-1758,-1753,-1749,-1745,-1742,-1740,-1737,-1735,-1733,
--1730,-1727,-1722,-1716,-1707,-1698,-1686,-1672,-1656,-1639,-1621,-1601,-1581,-1562,-1543,-1525,-1508,-1494,-1481,-1471,-1464,
--1460,-1458,-1460,-1463,-1470,-1478,-1488,-1499,-1511,-1523,-1536,-1548,-1560,-1570,-1579,-1587,-1592,-1596,-1597,-1597,-1594,
--1591,-1585,-1579,-1572,-1565,-1557,-1549,-1542,-1535,-1528,-1520,-1513,-1505,-1497,-1487,-1476,-1463,-1448,-1431,-1412,-1391,
--1369,-1346,-1322,-1299,-1277,-1257,-1240,-1226,-1216,-1210,-1208,-1210,-1216,-1226,-1238,-1253,-1267,-1282,-1296,-1307,-1315,
--1319,-1320,-1316,-1307,-1294,-1278,-1258,-1235,-1211,-1186,-1161,-1136,-1113,-1091,-1072,-1055,-1041,-1030,-1021,-1014,-1010,
--1007,-1005,-1004,-1003,-1003,-1004,-1004,-1003,-1003,-1002,-1000,-998,-996,-993,-989,-985,-980,-975,-968,-962,-954,
--947,-939,-930,-922,-914,-907,-900,-893,-888,-884,-880,-877,-875,-874,-873,-872,-871,-869,-867,-864,-861,
--856,-851,-844,-837,-830,-822,-814,-806,-799,-791,-784,-778,-772,-766,-760,-753,-747,-740,-731,-723,-713,
--702,-691,-678,-666,-653,-641,-629,-617,-607,-597,-588,-580,-572,-565,-557,-550,-541,-531,-520,-507,-493,
--478,-461,-444,-426,-410,-394,-380,-369,-360,-355,-353,-355,-360,-368,-378,-390,-403,-416,-484,-490,-494,
--496,-495,-491,-485,-476,-464,-450,-434,-417,-399,-380,-362,-344,-327,-311,-296,-283,-271,-259,-249,-239,
--229,-220,-210,-200,-189,-177,-165,-152,-139,-126,-113,-100,-88,-76,-64,-53,-43,-34,-25,-16,-8,
-0,8,17,26,36,46,56,67,78,89,101,112,123,134,145,156,166,176,186,196,206,
-216,227,237,247,258,268,278,288,298,308,317,325,333,340,347,353,360,366,372,379,386,
-393,402,411,421,431,443,454,466,478,490,501,512,522,531,538,545,551,555,558,561,563,
-564,564,565,565,566,566,567,567,568,568,569,569,569,568,567,565,563,560,556,551,546,
-540,534,528,521,515,509,503,497,492,488,484,481,479,477,477,477,478,480,483,486,490,
-494,499,504,510,516,523,530,537,545,553,561,570,579,589,598,609,619,630,641,652,663,
-673,683,693,701,709,716,721,725,728,730,731,731,730,728,725,722,719,716,713,710,708,
-706,704,704,704,705,706,708,712,716,721,727,734,743,752,763,775,789,803,818,835,852,
-869,887,905,922,939,954,969,982,993,1002,1009,1014,1016,1016,1014,1010,1003,995,985,973,960,
-946,931,916,899,883,866,849,833,817,801,785,771,756,743,730,717,705,693,681,670,658,
-647,635,624,612,599,587,575,563,551,539,528,518,508,500,493,487,482,478,475,473,472,
-472,472,473,473,473,474,474,473,472,472,471,470,469,468,468,468,470,471,474,478,482,
-486,491,496,500,504,507,509,510,509,507,503,497,490,481,471,459,447,434,420,407,393,
-380,367,355,343,332,321,311,301,291,282,272,261,250,239,226,213,199,184,168,152,135,
-117,99,81,62,44,25,7,-9,-27,-43,-59,-74,-89,-102,-115,-128,-139,-150,-161,-172,-183,
--194,-206,-219,-234,-250,-269,-290,-314,-340,-370,-403,-438,-477,-518,-561,-605,-651,-697,-743,-788,-831,
--873,-912,-948,-982,-1012,-1039,-1064,-1086,-1106,-1125,-1143,-1160,-1177,-1195,-1215,-1235,-1258,-1282,-1308,-1336,-1366,
--1398,-1430,-1464,-1498,-1532,-1565,-1598,-1630,-1661,-1690,-1719,-1746,-1772,-1797,-1821,-1844,-1867,-1890,-1913,-1937,-1960,
--1984,-2009,-2034,-2060,-2087,-2115,-2142,-2171,-2199,-2228,-2256,-2285,-2313,-2341,-2369,-2396,-2423,-2449,-2475,-2501,-2526,
--2551,-2576,-2602,-2627,-2653,-2679,-2705,-2732,-2760,-2788,-2817,-2846,-2876,-2905,-2934,-2964,-2992,-3021,-3048,-3075,-3101,
--3126,-3150,-3174,-3197,-3220,-3242,-3265,-3288,-3311,-3334,-3358,-3383,-3409,-3435,-3461,-3489,-3516,-3544,-3572,-3600,-3627,
--3655,-3682,-3709,-3735,-3761,-3787,-3812,-3836,-3860,-3884,-3906,-3928,-3949,-3969,-3988,-4006,-4022,-4038,-4051,-4064,-4075,
--4085,-4094,-4102,-4110,-4117,-4124,-4131,-4139,-4148,-4157,-4167,-4179,-4192,-4206,-4222,-4238,-4256,-4274,-4293,-4313,-4333,
--4354,-4374,-4395,-4416,-4437,-4459,-4480,-4502,-4524,-4547,-4571,-4595,-4619,-4645,-4671,-4698,-4725,-4752,-4780,-4808,-4835,
--4861,-4887,-4912,-4936,-4958,-4979,-4998,-5016,-5032,-5047,-5060,-5073,-5085,-5097,-5108,-5120,-5131,-5144,-5157,-5171,-5185,
--5201,-5216,-5232,-5248,-5264,-5279,-5293,-5305,-5316,-5325,-5332,-5336,-5338,-5339,-5337,-5334,-5329,-5324,-5317,-5311,-5305,
--5299,-5294,-5290,-5287,-5285,-5285,-5285,-5286,-5288,-5291,-5294,-5297,-5300,-5303,-5305,-5307,-5309,-5310,-5310,-5310,-5308,
--5306,-5303,-5298,-5293,-5286,-5279,-5270,-5260,-5250,-5240,-5229,-5220,-5211,-5205,-5202,-5202,-5206,-5214,-5228,-5247,-5271,
--5301,-5335,-5374,-5415,-5459,-5503,-5547,-5588,-5626,-5659,-5687,-5707,-5721,-5726,-5724,-5714,-5697,-5674,-5646,-5614,-5580,
--5544,-5507,-5472,-5438,-5408,-5380,-5355,-5334,-5317,-5303,-5291,-5282,-5275,-5269,-5265,-5261,-5257,-5254,-5251,-5248,-5245,
--5244,-5242,-5242,-5242,-5244,-5246,-5249,-5252,-5256,-5260,-5263,-5265,-5267,-5267,-5266,-5263,-5259,-5255,-5249,-5243,-5238,
--5233,-5230,-5228,-5228,-5230,-5235,-5243,-5252,-5264,-5277,-5292,-5308,-5323,-5339,-5354,-5368,-5381,-5393,-5403,-5412,-5420,
--5426,-5432,-5437,-5442,-5447,-5452,-5458,-5464,-5469,-5475,-5481,-5487,-5492,-5496,-5498,-5500,-5500,-5499,-5497,-5493,-5489,
--5484,-5479,-5475,-5471,-5468,-5467,-5467,-5468,-5470,-5474,-5479,-5484,-5489,-5494,-5499,-5502,-5504,-5505,-5504,-5502,-5498,
--5494,-5489,-5483,-5478,-5474,-5470,-5468,-5468,-5469,-5472,-5476,-5482,-5488,-5495,-5502,-5507,-5512,-5515,-5515,-5513,-5509,
--5501,-5491,-5479,-5465,-5449,-5432,-5415,-5397,-5380,-5365,-5351,-5338,-5328,-5320,-5314,-5310,-5308,-5308,-5308,-5310,-5311,
--5313,-5315,-5316,-5316,-5316,-5314,-5312,-5308,-5304,-5300,-5295,-5290,-5286,-5283,-5280,-5278,-5277,-5278,-5280,-5283,-5287,
--5292,-5298,-5304,-5309,-5314,-5318,-5321,-5322,-5321,-5318,-5312,-5304,-5294,-5282,-5267,-5251,-5234,-5215,-5196,-5176,-5157,
--5139,-5122,-5106,-5091,-5079,-5068,-5058,-5051,-5045,-5040,-5037,-5034,-5033,-5032,-5031,-5031,-5031,-5031,-5032,-5033,-5034,
--5035,-5038,-5040,-5044,-5047,-5051,-5056,-5060,-5064,-5068,-5071,-5072,-5072,-5070,-5066,-5060,-5051,-5040,-5026,-5010,-4992,
--4972,-4950,-4927,-4904,-4881,-4857,-4835,-4813,-4792,-4773,-4755,-4738,-4723,-4710,-4697,-4685,-4673,-4662,-4650,-4638,-4625,
--4611,-4595,-4578,-4560,-4540,-4519,-4496,-4472,-4446,-4420,-4394,-4367,-4341,-4315,-4290,-4266,-4244,-4224,-4206,-4189,-4175,
--4164,-4154,-4146,-4141,-4136,-4133,-4131,-4129,-4127,-4125,-4123,-4119,-4114,-4108,-4101,-4092,-4083,-4071,-4059,-4046,-4033,
--4019,-4006,-3992,-3979,-3965,-3953,-3941,-3929,-3918,-3906,-3894,-3883,-3870,-3857,-3843,-3828,-3812,-3796,-3778,-3760,-3742,
--3724,-3706,-3688,-3671,-3656,-3641,-3628,-3617,-3608,-3600,-3594,-3590,-3586,-3584,-3582,-3581,-3580,-3578,-3576,-3573,-3569,
--3564,-3558,-3550,-3541,-3531,-3520,-3509,-3497,-3485,-3474,-3463,-3453,-3444,-3436,-3429,-3424,-3420,-3416,-3413,-3410,-3407,
--3404,-3399,-3392,-3384,-3374,-3361,-3347,-3330,-3311,-3291,-3269,-3247,-3224,-3201,-3179,-3158,-3138,-3119,-3101,-3085,-3070,
--3055,-3040,-3026,-3010,-2994,-2977,-2958,-2937,-2915,-2892,-2868,-2843,-2818,-2793,-2769,-2746,-2724,-2704,-2684,-2666,-2649,
--2632,-2614,-2596,-2576,-2554,-2530,-2502,-2472,-2440,-2405,-2368,-2331,-2293,-2256,-2221,-2188,-2157,-2130,-2107,-2086,-2068,
--2052,-2037,-2021,-2004,-1985,-1962,-1935,-1903,-1867,-1827,-1784,-1739,-1694,-1651,-1612,-1579,-1554,-1540,-1537,-1548,-1572,
--1609,-1658,-1719,-1790,-1868,-1951,-2036,-2120,-2201,-2275,-2342,-2398,-2443,-2477,-2499,-2510,-2510,-2502,-2487,-2467,-2443,
--2417,-2392,-2368,-2347,-2330,-2316,-2306,-2300,-2298,-2298,-2299,-2302,-2306,-2308,-2310,-2311,-2310,-2308,-2304,-2299,-2293,
--2287,-2280,-2273,-2267,-2261,-2255,-2249,-2243,-2236,-2229,-2220,-2210,-2198,-2185,-2169,-2152,-2133,-2112,-2092,-2071,-2050,
--2030,-2013,-1997,-1983,-1973,-1965,-1960,-1957,-1956,-1957,-1958,-1960,-1962,-1963,-1962,-1960,-1955,-1948,-1939,-1928,-1916,
--1902,-1887,-1872,-1857,-1843,-1830,-1820,-1811,-1805,-1801,-1799,-1799,-1801,-1805,-1809,-1814,-1820,-1825,-1830,-1835,-1838,
--1841,-1843,-1844,-1845,-1845,-1844,-1844,-1843,-1843,-1843,-1843,-1843,-1844,-1845,-1846,-1847,-1848,-1848,-1848,-1848,-1848,
--1847,-1846,-1844,-1842,-1840,-1837,-1835,-1832,-1829,-1826,-1822,-1818,-1813,-1807,-1800,-1791,-1781,-1770,-1756,-1741,-1725,
--1706,-1687,-1666,-1644,-1622,-1600,-1578,-1557,-1538,-1520,-1504,-1490,-1479,-1471,-1465,-1463,-1463,-1467,-1473,-1481,-1491,
--1503,-1516,-1529,-1544,-1558,-1571,-1584,-1595,-1604,-1612,-1618,-1622,-1624,-1623,-1621,-1617,-1612,-1606,-1598,-1590,-1581,
--1573,-1564,-1555,-1546,-1537,-1529,-1520,-1512,-1504,-1496,-1488,-1481,-1473,-1466,-1460,-1455,-1451,-1448,-1447,-1447,-1449,
--1453,-1458,-1465,-1472,-1480,-1487,-1494,-1499,-1503,-1504,-1502,-1497,-1488,-1475,-1459,-1439,-1416,-1390,-1361,-1331,-1301,
--1270,-1239,-1210,-1183,-1157,-1135,-1115,-1098,-1084,-1072,-1064,-1058,-1055,-1053,-1053,-1054,-1057,-1060,-1064,-1069,-1073,
--1078,-1082,-1086,-1090,-1093,-1095,-1096,-1095,-1094,-1090,-1086,-1080,-1073,-1064,-1055,-1044,-1033,-1022,-1012,-1001,-991,
--983,-975,-968,-963,-959,-956,-954,-953,-952,-952,-951,-950,-948,-946,-943,-939,-934,-928,-922,-915,-907,
--899,-891,-883,-875,-866,-858,-849,-841,-831,-822,-812,-802,-791,-780,-769,-757,-746,-734,-723,-712,-702,
--692,-683,-675,-667,-659,-651,-643,-634,-625,-614,-603,-591,-577,-563,-548,-533,-518,-504,-490,-479,-469,
--461,-456,-453,-453,-455,-459,-465,-471,-478,-484,-570,-570,-569,-566,-561,-554,-545,-535,-522,-508,-492,
--476,-459,-442,-426,-410,-394,-380,-366,-354,-342,-331,-320,-310,-300,-290,-279,-268,-256,-244,-232,-219,
--206,-193,-180,-167,-155,-143,-132,-122,-112,-103,-95,-87,-79,-72,-64,-56,-48,-39,-30,-20,-10,
-0,11,23,35,46,58,69,81,92,102,113,123,133,142,152,161,170,180,189,198,207,
-216,225,234,243,252,261,269,278,286,295,303,312,321,330,339,349,359,369,379,390,401,
-411,422,432,442,452,461,469,477,484,491,497,502,507,512,516,519,523,526,528,531,533,
-534,536,536,536,535,533,531,527,523,517,511,503,495,486,477,467,457,447,438,428,419,
-411,403,397,391,387,384,381,381,381,382,385,388,393,398,405,412,420,428,437,447,457,
-468,480,492,504,517,530,543,556,570,583,596,609,620,632,642,651,659,666,671,675,678,
-680,680,680,679,677,675,672,670,667,665,663,661,660,659,658,658,658,659,660,661,663,
-665,668,671,675,681,687,695,705,716,729,744,761,779,799,820,842,865,888,910,932,952,
-971,988,1002,1013,1021,1026,1027,1025,1020,1012,1002,988,973,956,938,920,901,881,863,845,828,
-811,797,783,770,759,748,737,727,717,707,696,684,672,658,644,628,611,594,576,558,540,
-523,506,490,476,463,453,444,438,433,431,430,432,434,438,442,447,452,457,461,465,468,
-470,472,473,474,475,475,475,476,477,478,480,482,485,487,490,493,495,496,497,497,495,
-493,489,484,478,470,462,453,443,433,423,412,402,392,383,374,365,356,348,340,331,322,
-313,304,294,283,271,259,246,232,218,203,188,172,156,139,123,106,89,72,55,38,22,
-5,-11,-28,-45,-61,-77,-93,-108,-123,-137,-152,-165,-179,-193,-208,-223,-240,-258,-277,-299,-324,
--351,-381,-414,-450,-488,-529,-572,-616,-661,-707,-752,-796,-838,-878,-916,-951,-983,-1011,-1037,-1060,-1081,
--1100,-1118,-1136,-1154,-1172,-1192,-1213,-1236,-1261,-1289,-1319,-1351,-1385,-1420,-1455,-1491,-1527,-1563,-1597,-1630,-1661,
--1690,-1718,-1743,-1767,-1789,-1811,-1831,-1851,-1870,-1890,-1910,-1931,-1952,-1975,-1999,-2023,-2049,-2075,-2102,-2129,-2157,
--2185,-2212,-2240,-2267,-2294,-2321,-2348,-2374,-2400,-2427,-2454,-2481,-2508,-2536,-2565,-2594,-2624,-2654,-2685,-2716,-2747,
--2778,-2810,-2840,-2871,-2900,-2929,-2957,-2984,-3010,-3035,-3059,-3082,-3104,-3126,-3147,-3168,-3189,-3210,-3232,-3253,-3276,
--3298,-3322,-3346,-3370,-3395,-3421,-3447,-3474,-3501,-3528,-3555,-3582,-3609,-3636,-3664,-3690,-3717,-3743,-3769,-3795,-3819,
--3844,-3867,-3890,-3911,-3932,-3951,-3969,-3985,-4001,-4014,-4027,-4038,-4049,-4058,-4067,-4075,-4083,-4092,-4100,-4110,-4120,
--4131,-4143,-4156,-4171,-4186,-4203,-4220,-4238,-4256,-4275,-4293,-4312,-4331,-4349,-4367,-4384,-4401,-4419,-4436,-4453,-4471,
--4489,-4508,-4528,-4549,-4572,-4596,-4621,-4647,-4675,-4703,-4732,-4762,-4791,-4821,-4849,-4877,-4904,-4929,-4952,-4973,-4993,
--5010,-5026,-5040,-5052,-5064,-5074,-5084,-5094,-5103,-5113,-5123,-5133,-5145,-5156,-5168,-5180,-5192,-5204,-5215,-5225,-5233,
--5240,-5244,-5247,-5248,-5246,-5242,-5236,-5229,-5220,-5210,-5200,-5189,-5179,-5169,-5161,-5154,-5148,-5144,-5142,-5141,-5142,
--5144,-5147,-5152,-5157,-5162,-5167,-5172,-5176,-5179,-5181,-5181,-5181,-5178,-5174,-5169,-5163,-5155,-5147,-5138,-5130,-5123,
--5116,-5112,-5110,-5111,-5116,-5125,-5139,-5158,-5182,-5212,-5246,-5286,-5329,-5376,-5425,-5476,-5526,-5575,-5621,-5664,-5701,
--5732,-5756,-5772,-5780,-5780,-5772,-5757,-5735,-5707,-5674,-5638,-5600,-5561,-5523,-5485,-5450,-5418,-5388,-5363,-5341,-5323,
--5307,-5295,-5285,-5276,-5269,-5263,-5257,-5251,-5245,-5240,-5234,-5228,-5223,-5218,-5214,-5211,-5209,-5208,-5209,-5210,-5212,
--5214,-5217,-5219,-5222,-5223,-5224,-5223,-5222,-5219,-5216,-5212,-5208,-5204,-5200,-5198,-5197,-5198,-5201,-5206,-5213,-5222,
--5233,-5246,-5259,-5274,-5289,-5303,-5317,-5331,-5343,-5354,-5363,-5372,-5379,-5385,-5390,-5395,-5399,-5404,-5408,-5412,-5417,
--5421,-5426,-5431,-5435,-5439,-5442,-5444,-5445,-5445,-5444,-5442,-5439,-5435,-5431,-5427,-5423,-5420,-5418,-5416,-5416,-5417,
--5420,-5423,-5427,-5431,-5436,-5441,-5445,-5448,-5450,-5451,-5451,-5449,-5446,-5442,-5438,-5433,-5428,-5424,-5421,-5418,-5417,
--5418,-5419,-5422,-5426,-5431,-5436,-5441,-5445,-5449,-5451,-5451,-5448,-5444,-5437,-5428,-5416,-5403,-5389,-5373,-5357,-5341,
--5325,-5311,-5297,-5286,-5276,-5268,-5263,-5259,-5257,-5257,-5258,-5260,-5262,-5265,-5268,-5272,-5274,-5277,-5279,-5280,-5282,
--5282,-5283,-5284,-5285,-5286,-5288,-5290,-5293,-5296,-5300,-5304,-5308,-5312,-5315,-5318,-5320,-5321,-5321,-5319,-5315,-5309,
--5302,-5293,-5282,-5269,-5255,-5239,-5223,-5205,-5188,-5170,-5152,-5135,-5118,-5102,-5087,-5074,-5061,-5050,-5039,-5030,-5022,
--5014,-5008,-5002,-4997,-4993,-4989,-4986,-4984,-4982,-4981,-4981,-4982,-4983,-4986,-4989,-4993,-4998,-5003,-5008,-5013,-5018,
--5023,-5027,-5029,-5030,-5029,-5026,-5021,-5014,-5004,-4993,-4979,-4964,-4947,-4929,-4910,-4890,-4870,-4851,-4832,-4813,-4796,
--4779,-4764,-4749,-4736,-4723,-4711,-4699,-4687,-4674,-4662,-4648,-4633,-4617,-4599,-4580,-4559,-4536,-4513,-4487,-4461,-4434,
--4406,-4379,-4351,-4324,-4298,-4273,-4249,-4227,-4207,-4189,-4174,-4160,-4148,-4139,-4131,-4125,-4121,-4117,-4114,-4112,-4110,
--4108,-4105,-4102,-4098,-4093,-4087,-4080,-4073,-4064,-4055,-4045,-4034,-4024,-4014,-4003,-3993,-3984,-3974,-3966,-3957,-3949,
--3942,-3934,-3926,-3918,-3910,-3901,-3891,-3880,-3868,-3856,-3843,-3829,-3815,-3800,-3786,-3771,-3758,-3745,-3733,-3722,-3713,
--3705,-3699,-3694,-3691,-3689,-3688,-3688,-3689,-3690,-3690,-3690,-3689,-3687,-3684,-3679,-3672,-3664,-3654,-3642,-3629,-3614,
--3599,-3583,-3567,-3551,-3535,-3520,-3506,-3492,-3479,-3467,-3455,-3444,-3434,-3423,-3412,-3400,-3387,-3374,-3359,-3343,-3326,
--3308,-3289,-3269,-3249,-3229,-3209,-3189,-3170,-3152,-3135,-3118,-3102,-3086,-3070,-3054,-3037,-3019,-3000,-2980,-2958,-2934,
--2909,-2882,-2855,-2827,-2798,-2770,-2743,-2716,-2691,-2667,-2645,-2624,-2605,-2586,-2568,-2550,-2531,-2511,-2490,-2468,-2443,
--2417,-2389,-2359,-2329,-2298,-2267,-2236,-2207,-2179,-2154,-2131,-2110,-2091,-2074,-2058,-2043,-2029,-2014,-1998,-1980,-1960,
--1939,-1915,-1890,-1864,-1837,-1812,-1789,-1768,-1753,-1742,-1738,-1741,-1752,-1770,-1796,-1828,-1866,-1909,-1956,-2005,-2054,
--2103,-2150,-2193,-2233,-2268,-2297,-2322,-2342,-2357,-2368,-2376,-2382,-2385,-2388,-2389,-2391,-2392,-2393,-2394,-2395,-2395,
--2394,-2391,-2387,-2380,-2371,-2360,-2347,-2332,-2316,-2298,-2281,-2265,-2249,-2236,-2224,-2215,-2210,-2206,-2206,-2207,-2210,
--2214,-2218,-2221,-2223,-2224,-2221,-2216,-2208,-2197,-2183,-2166,-2147,-2127,-2107,-2086,-2066,-2048,-2031,-2017,-2006,-1997,
--1991,-1987,-1985,-1984,-1985,-1985,-1986,-1985,-1983,-1980,-1975,-1968,-1959,-1948,-1936,-1923,-1909,-1896,-1882,-1870,-1860,
--1850,-1843,-1838,-1835,-1834,-1835,-1838,-1841,-1846,-1852,-1858,-1864,-1870,-1876,-1881,-1885,-1888,-1891,-1893,-1895,-1896,
--1897,-1898,-1899,-1899,-1900,-1902,-1903,-1905,-1907,-1910,-1912,-1915,-1918,-1921,-1923,-1926,-1928,-1930,-1931,-1931,-1931,
--1929,-1926,-1922,-1917,-1910,-1901,-1889,-1877,-1861,-1844,-1825,-1804,-1781,-1757,-1732,-1705,-1679,-1652,-1625,-1600,-1575,
--1552,-1532,-1513,-1498,-1485,-1475,-1469,-1466,-1466,-1469,-1474,-1483,-1493,-1506,-1519,-1534,-1550,-1566,-1582,-1597,-1611,
--1623,-1635,-1644,-1651,-1656,-1659,-1660,-1658,-1655,-1650,-1643,-1636,-1627,-1617,-1607,-1597,-1586,-1577,-1568,-1560,-1554,
--1549,-1546,-1544,-1545,-1547,-1552,-1559,-1568,-1579,-1591,-1605,-1620,-1635,-1651,-1666,-1680,-1692,-1702,-1709,-1713,-1713,
--1709,-1700,-1688,-1670,-1649,-1624,-1595,-1564,-1530,-1495,-1459,-1423,-1387,-1353,-1320,-1290,-1262,-1237,-1215,-1197,-1181,
--1168,-1158,-1151,-1146,-1142,-1141,-1142,-1143,-1146,-1150,-1155,-1160,-1166,-1172,-1178,-1185,-1191,-1196,-1201,-1205,-1208,
--1209,-1209,-1207,-1203,-1197,-1190,-1181,-1171,-1160,-1148,-1136,-1124,-1112,-1100,-1090,-1080,-1072,-1066,-1060,-1056,-1053,
--1051,-1050,-1049,-1049,-1049,-1048,-1048,-1046,-1044,-1042,-1038,-1034,-1029,-1023,-1017,-1010,-1002,-995,-986,-977,-968,
--958,-948,-938,-927,-916,-904,-893,-881,-869,-858,-847,-836,-825,-814,-804,-794,-784,-775,-765,-754,-744,
--732,-721,-708,-695,-682,-668,-654,-640,-627,-614,-602,-592,-583,-576,-570,-567,-564,-564,-564,-566,-567,
--569,-570,-640,-638,-634,-629,-623,-615,-606,-595,-583,-569,-555,-540,-524,-509,-493,-478,-464,-450,-437,
--424,-413,-401,-391,-380,-370,-359,-348,-338,-326,-314,-302,-290,-277,-265,-252,-240,-228,-216,-205,-194,
--185,-175,-166,-158,-150,-142,-134,-126,-118,-110,-101,-91,-82,-71,-61,-50,-39,-27,-16,-5,6,
-17,27,38,48,57,66,75,84,92,101,109,117,125,133,141,150,158,167,175,185,194,
-203,213,223,233,243,254,265,276,287,298,309,320,331,342,353,363,373,383,392,401,409,
-417,424,431,437,443,448,453,457,461,465,468,470,472,474,475,475,474,472,469,465,460,
-454,447,439,430,421,410,400,389,378,367,356,346,337,329,322,315,311,307,305,304,304,
-306,309,313,318,324,331,339,347,357,367,378,389,401,414,428,442,456,471,486,501,516,
-531,546,560,573,585,596,605,614,620,625,629,631,631,631,630,628,625,623,620,618,616,
-615,614,614,615,616,618,620,622,624,627,629,631,632,634,635,637,639,642,645,651,657,
-666,677,691,707,725,746,769,794,820,847,874,901,927,951,973,992,1007,1019,1026,1029,1028,
-1022,1013,1000,985,966,946,925,902,880,859,838,819,802,786,772,760,750,740,732,724,716,
-708,699,689,678,664,649,632,614,594,573,552,530,508,487,467,449,433,420,409,401,396,
-393,393,395,399,405,411,418,426,433,440,446,452,456,460,463,465,467,469,470,471,473,
-475,477,479,482,486,489,492,495,497,499,499,499,497,493,489,483,476,468,460,451,441,
-431,422,412,403,395,386,379,371,364,357,349,342,333,325,315,305,294,281,268,254,240,
-225,209,193,176,160,143,127,110,93,77,60,44,27,10,-6,-23,-39,-56,-73,-90,-106,
--123,-139,-155,-171,-188,-204,-221,-238,-257,-277,-298,-321,-347,-375,-405,-438,-473,-510,-549,-590,-633,
--675,-718,-761,-802,-843,-881,-916,-949,-980,-1008,-1033,-1056,-1077,-1097,-1116,-1134,-1153,-1172,-1192,-1214,-1238,
--1264,-1292,-1322,-1354,-1387,-1421,-1456,-1491,-1526,-1560,-1593,-1625,-1655,-1684,-1711,-1737,-1761,-1784,-1807,-1828,-1849,
--1871,-1892,-1914,-1937,-1960,-1984,-2009,-2034,-2060,-2086,-2112,-2139,-2165,-2191,-2217,-2242,-2267,-2291,-2315,-2340,-2364,
--2389,-2414,-2440,-2467,-2495,-2524,-2554,-2584,-2616,-2648,-2681,-2714,-2746,-2779,-2811,-2842,-2872,-2901,-2929,-2956,-2982,
--3006,-3029,-3051,-3072,-3093,-3113,-3133,-3153,-3173,-3194,-3215,-3236,-3258,-3280,-3303,-3327,-3350,-3375,-3400,-3425,-3450,
--3476,-3502,-3528,-3554,-3581,-3607,-3634,-3661,-3688,-3714,-3741,-3767,-3793,-3818,-3842,-3865,-3888,-3909,-3928,-3946,-3963,
--3978,-3992,-4004,-4015,-4025,-4034,-4042,-4050,-4059,-4067,-4076,-4086,-4097,-4108,-4121,-4135,-4149,-4165,-4182,-4199,-4216,
--4234,-4252,-4270,-4287,-4304,-4321,-4337,-4353,-4368,-4384,-4399,-4415,-4431,-4449,-4467,-4486,-4507,-4529,-4553,-4579,-4605,
--4633,-4662,-4692,-4723,-4753,-4784,-4813,-4842,-4870,-4896,-4920,-4943,-4963,-4982,-4998,-5013,-5026,-5037,-5047,-5057,-5065,
--5073,-5081,-5089,-5097,-5105,-5112,-5120,-5128,-5136,-5143,-5149,-5155,-5159,-5162,-5163,-5162,-5160,-5156,-5150,-5142,-5133,
--5123,-5113,-5102,-5090,-5079,-5069,-5060,-5052,-5046,-5041,-5038,-5037,-5038,-5040,-5044,-5049,-5055,-5061,-5067,-5073,-5078,
--5083,-5086,-5088,-5088,-5087,-5084,-5080,-5075,-5069,-5062,-5056,-5051,-5048,-5046,-5048,-5053,-5062,-5076,-5095,-5119,-5149,
--5184,-5225,-5269,-5318,-5369,-5422,-5476,-5529,-5580,-5627,-5671,-5708,-5739,-5763,-5779,-5786,-5785,-5776,-5760,-5737,-5709,
--5675,-5639,-5600,-5560,-5520,-5481,-5445,-5411,-5380,-5353,-5330,-5310,-5293,-5279,-5267,-5257,-5249,-5242,-5234,-5228,-5220,
--5213,-5206,-5198,-5191,-5184,-5177,-5171,-5166,-5163,-5160,-5159,-5159,-5160,-5162,-5165,-5167,-5170,-5173,-5174,-5176,-5176,
--5176,-5175,-5173,-5171,-5169,-5168,-5167,-5167,-5168,-5171,-5176,-5182,-5190,-5199,-5210,-5222,-5235,-5248,-5262,-5275,-5287,
--5299,-5310,-5320,-5328,-5336,-5342,-5348,-5353,-5357,-5361,-5364,-5367,-5371,-5373,-5376,-5379,-5381,-5382,-5383,-5384,-5383,
--5382,-5380,-5378,-5375,-5372,-5368,-5365,-5362,-5360,-5358,-5358,-5358,-5359,-5362,-5365,-5368,-5372,-5376,-5380,-5384,-5387,
--5389,-5390,-5390,-5389,-5387,-5384,-5380,-5376,-5372,-5368,-5365,-5362,-5361,-5360,-5361,-5363,-5366,-5369,-5373,-5377,-5381,
--5384,-5386,-5387,-5387,-5385,-5382,-5377,-5370,-5362,-5352,-5342,-5331,-5320,-5308,-5298,-5288,-5278,-5270,-5263,-5257,-5253,
--5249,-5246,-5245,-5244,-5244,-5244,-5245,-5246,-5247,-5249,-5250,-5253,-5255,-5258,-5262,-5266,-5271,-5276,-5282,-5289,-5296,
--5302,-5309,-5315,-5321,-5326,-5329,-5331,-5331,-5329,-5325,-5319,-5310,-5300,-5288,-5274,-5258,-5242,-5225,-5207,-5189,-5171,
--5153,-5136,-5120,-5105,-5091,-5078,-5066,-5055,-5045,-5035,-5027,-5018,-5010,-5002,-4995,-4988,-4981,-4974,-4967,-4961,-4955,
--4950,-4946,-4943,-4941,-4940,-4940,-4941,-4943,-4946,-4949,-4953,-4957,-4961,-4964,-4966,-4967,-4967,-4965,-4961,-4956,-4949,
--4940,-4929,-4917,-4904,-4890,-4875,-4860,-4845,-4831,-4817,-4803,-4791,-4779,-4769,-4758,-4749,-4739,-4730,-4720,-4710,-4699,
--4686,-4672,-4656,-4638,-4618,-4596,-4572,-4547,-4519,-4490,-4461,-4430,-4399,-4369,-4339,-4310,-4282,-4256,-4231,-4209,-4189,
--4172,-4156,-4143,-4132,-4123,-4116,-4110,-4106,-4102,-4099,-4097,-4095,-4093,-4090,-4087,-4084,-4080,-4076,-4070,-4065,-4058,
--4051,-4044,-4037,-4029,-4022,-4014,-4007,-3999,-3992,-3985,-3978,-3971,-3965,-3958,-3951,-3944,-3937,-3929,-3921,-3912,-3903,
--3893,-3883,-3872,-3861,-3850,-3839,-3829,-3819,-3809,-3800,-3792,-3785,-3779,-3775,-3771,-3769,-3768,-3767,-3768,-3769,-3770,
--3771,-3772,-3772,-3772,-3770,-3766,-3761,-3754,-3746,-3736,-3724,-3710,-3695,-3679,-3661,-3643,-3624,-3605,-3586,-3567,-3548,
--3530,-3512,-3494,-3477,-3460,-3442,-3425,-3408,-3390,-3372,-3354,-3336,-3317,-3297,-3278,-3259,-3240,-3222,-3203,-3186,-3169,
--3153,-3137,-3121,-3106,-3091,-3075,-3058,-3040,-3021,-3001,-2978,-2954,-2928,-2901,-2872,-2842,-2811,-2780,-2750,-2720,-2691,
--2663,-2637,-2613,-2591,-2570,-2551,-2534,-2517,-2500,-2484,-2467,-2450,-2431,-2411,-2389,-2367,-2342,-2317,-2291,-2265,-2239,
--2214,-2189,-2165,-2143,-2123,-2104,-2087,-2071,-2056,-2043,-2029,-2016,-2003,-1990,-1976,-1961,-1947,-1932,-1917,-1903,-1890,
--1878,-1868,-1861,-1857,-1857,-1859,-1866,-1876,-1889,-1906,-1926,-1948,-1973,-1999,-2026,-2055,-2084,-2113,-2142,-2171,-2200,
--2228,-2256,-2283,-2309,-2335,-2359,-2382,-2403,-2421,-2438,-2451,-2460,-2466,-2467,-2465,-2458,-2446,-2431,-2412,-2391,-2367,
--2343,-2318,-2294,-2271,-2250,-2233,-2219,-2209,-2203,-2201,-2202,-2207,-2213,-2222,-2230,-2239,-2247,-2252,-2255,-2255,-2252,
--2245,-2235,-2221,-2205,-2186,-2166,-2146,-2125,-2105,-2086,-2069,-2054,-2042,-2032,-2025,-2021,-2018,-2017,-2017,-2018,-2018,
--2018,-2017,-2014,-2010,-2005,-1997,-1988,-1978,-1967,-1955,-1942,-1930,-1919,-1908,-1899,-1892,-1886,-1882,-1881,-1881,-1883,
--1886,-1891,-1897,-1904,-1911,-1918,-1925,-1932,-1938,-1944,-1949,-1953,-1957,-1961,-1963,-1966,-1968,-1970,-1972,-1975,-1977,
--1980,-1983,-1986,-1990,-1994,-1998,-2002,-2006,-2009,-2013,-2015,-2016,-2016,-2015,-2012,-2006,-1999,-1989,-1977,-1962,-1944,
--1924,-1901,-1877,-1850,-1821,-1792,-1761,-1730,-1699,-1669,-1640,-1613,-1587,-1564,-1544,-1526,-1512,-1502,-1494,-1490,-1490,
--1492,-1497,-1505,-1516,-1528,-1541,-1556,-1572,-1588,-1604,-1620,-1635,-1649,-1662,-1673,-1683,-1691,-1697,-1701,-1703,-1703,
--1701,-1696,-1691,-1683,-1674,-1665,-1654,-1643,-1632,-1622,-1612,-1604,-1597,-1592,-1590,-1590,-1594,-1600,-1609,-1621,-1636,
--1653,-1672,-1693,-1714,-1736,-1757,-1778,-1796,-1811,-1823,-1831,-1835,-1833,-1827,-1816,-1800,-1780,-1755,-1726,-1695,-1662,
--1627,-1591,-1555,-1521,-1487,-1456,-1427,-1401,-1378,-1358,-1341,-1327,-1316,-1307,-1300,-1295,-1291,-1289,-1287,-1286,-1286,
--1286,-1286,-1287,-1288,-1289,-1291,-1292,-1294,-1296,-1298,-1300,-1301,-1302,-1302,-1302,-1300,-1297,-1293,-1287,-1280,-1272,
--1263,-1253,-1242,-1231,-1220,-1208,-1197,-1187,-1177,-1169,-1161,-1155,-1150,-1145,-1142,-1140,-1138,-1137,-1136,-1135,-1135,
--1134,-1132,-1130,-1128,-1125,-1121,-1117,-1111,-1105,-1098,-1091,-1083,-1074,-1064,-1054,-1044,-1033,-1021,-1010,-998,-986,
--974,-962,-950,-938,-927,-915,-904,-892,-881,-869,-858,-846,-833,-820,-807,-794,-780,-766,-752,-738,-725,
--712,-700,-688,-678,-670,-662,-656,-652,-648,-646,-644,-643,-643,-642,-640,-680,-678,-674,-670,-664,-657,
--649,-639,-628,-616,-603,-589,-574,-560,-545,-530,-515,-501,-488,-475,-463,-451,-440,-430,-419,-409,-399,
--389,-378,-368,-357,-346,-334,-323,-311,-299,-287,-275,-264,-253,-242,-232,-222,-213,-204,-195,-187,-178,
--170,-162,-154,-146,-138,-129,-120,-111,-101,-92,-81,-71,-61,-50,-39,-29,-18,-8,2,12,22,
-32,41,51,60,69,77,86,94,103,111,120,128,137,145,154,164,173,183,193,203,214,
-225,236,247,259,270,281,292,303,314,324,334,343,352,361,369,376,383,389,395,401,405,
-410,414,417,420,422,423,424,423,422,420,416,412,406,400,392,384,375,365,354,344,333,
-322,311,302,292,284,277,271,266,262,260,259,260,262,265,269,274,280,287,294,303,312,
-322,332,343,355,367,380,394,408,422,437,452,467,482,497,511,524,537,548,557,565,571,
-576,579,580,580,578,576,573,570,567,564,562,560,560,560,561,564,567,571,576,581,586,
-591,595,599,602,604,605,606,607,607,608,609,612,616,622,631,642,656,673,693,716,741,
-768,796,825,854,882,908,932,952,969,982,990,993,992,986,976,962,945,926,904,882,860,
-837,816,797,779,764,751,740,731,724,719,714,709,705,699,692,683,673,660,645,627,608,
-587,565,542,519,497,476,456,438,423,411,402,396,393,393,395,399,405,413,420,429,437,
-444,451,457,462,466,469,471,473,475,476,478,480,483,487,491,496,502,508,514,520,526,
-530,534,536,537,535,532,527,520,512,502,491,479,466,453,440,428,416,404,393,383,373,
-364,356,347,339,330,321,311,301,290,277,264,251,236,221,205,188,172,155,138,121,104,
-88,71,55,38,22,6,-9,-25,-42,-58,-74,-91,-108,-125,-142,-160,-177,-196,-214,-234,-254,
--275,-298,-321,-347,-374,-402,-433,-465,-499,-535,-572,-610,-649,-689,-728,-767,-805,-842,-877,-911,-942,
--972,-999,-1025,-1049,-1072,-1093,-1114,-1134,-1155,-1176,-1198,-1220,-1244,-1269,-1296,-1324,-1353,-1383,-1414,-1446,-1477,
--1509,-1540,-1570,-1600,-1629,-1657,-1684,-1710,-1736,-1761,-1785,-1809,-1833,-1857,-1882,-1907,-1932,-1957,-1983,-2009,-2035,
--2061,-2087,-2112,-2138,-2162,-2187,-2211,-2234,-2258,-2281,-2304,-2328,-2352,-2377,-2402,-2429,-2456,-2485,-2514,-2545,-2576,
--2608,-2641,-2673,-2706,-2738,-2770,-2800,-2830,-2859,-2886,-2912,-2936,-2960,-2982,-3004,-3024,-3044,-3064,-3084,-3103,-3123,
--3143,-3163,-3184,-3205,-3227,-3249,-3271,-3294,-3317,-3340,-3364,-3387,-3411,-3435,-3459,-3483,-3508,-3533,-3558,-3584,-3611,
--3637,-3664,-3691,-3718,-3745,-3772,-3798,-3823,-3847,-3869,-3891,-3910,-3928,-3944,-3959,-3971,-3983,-3993,-4001,-4009,-4017,
--4024,-4032,-4040,-4048,-4058,-4068,-4079,-4092,-4106,-4121,-4137,-4153,-4171,-4188,-4206,-4224,-4242,-4260,-4277,-4294,-4311,
--4327,-4343,-4360,-4376,-4393,-4410,-4428,-4447,-4467,-4488,-4511,-4535,-4560,-4586,-4614,-4642,-4671,-4700,-4729,-4758,-4787,
--4815,-4841,-4866,-4890,-4912,-4932,-4950,-4966,-4981,-4994,-5005,-5015,-5023,-5031,-5037,-5043,-5049,-5053,-5058,-5062,-5066,
--5069,-5072,-5075,-5077,-5078,-5078,-5078,-5077,-5075,-5071,-5067,-5062,-5056,-5049,-5042,-5035,-5028,-5021,-5014,-5008,-5003,
--4999,-4996,-4995,-4995,-4997,-5000,-5004,-5010,-5016,-5023,-5030,-5037,-5044,-5050,-5055,-5059,-5062,-5064,-5063,-5062,-5059,
--5056,-5052,-5048,-5044,-5042,-5041,-5043,-5048,-5056,-5069,-5086,-5107,-5134,-5165,-5201,-5240,-5283,-5328,-5375,-5421,-5468,
--5512,-5553,-5589,-5621,-5647,-5666,-5678,-5683,-5681,-5672,-5656,-5635,-5609,-5579,-5546,-5512,-5477,-5442,-5408,-5375,-5346,
--5318,-5294,-5273,-5255,-5240,-5227,-5216,-5206,-5198,-5190,-5183,-5177,-5170,-5163,-5156,-5149,-5142,-5135,-5129,-5124,-5120,
--5117,-5114,-5114,-5114,-5115,-5118,-5121,-5124,-5128,-5131,-5135,-5138,-5140,-5142,-5143,-5144,-5144,-5145,-5145,-5146,-5147,
--5149,-5152,-5156,-5161,-5168,-5175,-5184,-5194,-5204,-5215,-5226,-5238,-5249,-5259,-5269,-5278,-5286,-5293,-5300,-5305,-5310,
--5314,-5317,-5319,-5322,-5323,-5324,-5325,-5326,-5326,-5326,-5325,-5324,-5322,-5321,-5318,-5316,-5313,-5311,-5308,-5306,-5304,
--5303,-5302,-5302,-5303,-5304,-5307,-5309,-5312,-5316,-5319,-5322,-5325,-5327,-5329,-5329,-5329,-5328,-5327,-5325,-5322,-5319,
--5316,-5313,-5310,-5308,-5307,-5306,-5306,-5307,-5309,-5312,-5315,-5318,-5322,-5325,-5328,-5330,-5332,-5333,-5332,-5331,-5329,
--5326,-5322,-5317,-5311,-5306,-5300,-5294,-5287,-5281,-5276,-5270,-5265,-5261,-5256,-5252,-5248,-5245,-5241,-5238,-5235,-5233,
--5231,-5230,-5229,-5229,-5230,-5232,-5235,-5239,-5244,-5249,-5256,-5263,-5271,-5279,-5286,-5293,-5299,-5304,-5307,-5309,-5308,
--5306,-5301,-5294,-5285,-5275,-5262,-5248,-5233,-5218,-5202,-5186,-5170,-5155,-5140,-5127,-5115,-5103,-5093,-5084,-5076,-5068,
--5061,-5054,-5047,-5040,-5032,-5025,-5016,-5008,-4998,-4989,-4979,-4969,-4959,-4950,-4942,-4934,-4927,-4921,-4916,-4913,-4910,
--4909,-4908,-4908,-4907,-4907,-4907,-4906,-4904,-4901,-4897,-4891,-4884,-4876,-4866,-4856,-4844,-4832,-4820,-4808,-4796,-4784,
--4774,-4764,-4755,-4747,-4740,-4733,-4728,-4722,-4716,-4710,-4703,-4694,-4684,-4673,-4658,-4642,-4623,-4602,-4578,-4552,-4523,
--4494,-4463,-4431,-4398,-4366,-4334,-4304,-4275,-4247,-4222,-4199,-4178,-4160,-4144,-4131,-4119,-4110,-4103,-4097,-4093,-4090,
--4087,-4085,-4083,-4081,-4079,-4078,-4075,-4073,-4070,-4066,-4063,-4059,-4054,-4049,-4044,-4039,-4034,-4028,-4022,-4015,-4009,
--4002,-3994,-3987,-3978,-3970,-3961,-3951,-3941,-3931,-3921,-3910,-3899,-3888,-3878,-3868,-3858,-3848,-3840,-3832,-3824,-3818,
--3813,-3809,-3806,-3803,-3802,-3802,-3802,-3803,-3805,-3807,-3809,-3811,-3813,-3814,-3814,-3814,-3813,-3810,-3806,-3801,-3794,
--3786,-3776,-3765,-3752,-3737,-3722,-3705,-3688,-3670,-3650,-3631,-3611,-3590,-3569,-3548,-3527,-3505,-3484,-3462,-3440,-3418,
--3395,-3373,-3351,-3329,-3307,-3285,-3264,-3243,-3224,-3204,-3186,-3169,-3152,-3136,-3120,-3104,-3089,-3073,-3056,-3039,-3020,
--3000,-2979,-2955,-2931,-2904,-2876,-2848,-2818,-2788,-2757,-2727,-2698,-2671,-2644,-2620,-2597,-2576,-2557,-2540,-2524,-2510,
--2496,-2483,-2470,-2456,-2441,-2425,-2409,-2390,-2371,-2350,-2328,-2306,-2283,-2260,-2238,-2216,-2196,-2177,-2159,-2143,-2130,
--2118,-2107,-2098,-2090,-2083,-2077,-2071,-2066,-2060,-2053,-2047,-2040,-2032,-2025,-2017,-2009,-2002,-1996,-1991,-1987,-1984,
--1984,-1985,-1989,-1996,-2004,-2016,-2030,-2047,-2067,-2089,-2113,-2139,-2168,-2197,-2228,-2260,-2291,-2323,-2353,-2382,-2409,
--2433,-2454,-2471,-2483,-2492,-2495,-2494,-2489,-2479,-2466,-2449,-2429,-2408,-2385,-2363,-2341,-2320,-2302,-2286,-2273,-2263,
--2257,-2254,-2253,-2256,-2260,-2265,-2271,-2277,-2282,-2286,-2287,-2286,-2283,-2276,-2267,-2255,-2241,-2225,-2207,-2189,-2171,
--2153,-2136,-2120,-2106,-2094,-2084,-2076,-2070,-2066,-2063,-2062,-2061,-2060,-2060,-2059,-2057,-2054,-2049,-2044,-2037,-2029,
--2019,-2010,-1999,-1989,-1979,-1969,-1961,-1953,-1948,-1943,-1941,-1940,-1942,-1945,-1949,-1955,-1962,-1970,-1979,-1988,-1997,
--2006,-2015,-2023,-2031,-2038,-2045,-2051,-2056,-2060,-2063,-2067,-2069,-2072,-2074,-2076,-2078,-2080,-2082,-2084,-2086,-2087,
--2089,-2090,-2090,-2089,-2087,-2084,-2079,-2072,-2063,-2051,-2037,-2021,-2002,-1980,-1956,-1930,-1902,-1872,-1842,-1811,-1780,
--1750,-1720,-1692,-1666,-1642,-1622,-1604,-1589,-1578,-1570,-1566,-1565,-1566,-1571,-1578,-1587,-1597,-1609,-1622,-1636,-1650,
--1663,-1677,-1689,-1701,-1712,-1722,-1731,-1738,-1744,-1748,-1750,-1751,-1750,-1748,-1744,-1738,-1732,-1723,-1714,-1704,-1694,
--1683,-1673,-1663,-1654,-1647,-1641,-1638,-1637,-1639,-1644,-1652,-1663,-1677,-1694,-1712,-1732,-1754,-1775,-1796,-1816,-1834,
--1849,-1860,-1868,-1871,-1870,-1864,-1853,-1837,-1817,-1794,-1767,-1738,-1708,-1677,-1645,-1614,-1585,-1558,-1534,-1512,-1493,
--1478,-1465,-1456,-1449,-1444,-1441,-1439,-1438,-1438,-1437,-1437,-1435,-1433,-1431,-1427,-1423,-1418,-1412,-1406,-1400,-1393,
--1387,-1381,-1375,-1369,-1364,-1359,-1353,-1348,-1343,-1338,-1332,-1325,-1319,-1311,-1303,-1295,-1286,-1277,-1267,-1257,-1247,
--1238,-1229,-1220,-1211,-1204,-1197,-1190,-1185,-1180,-1176,-1172,-1168,-1165,-1162,-1159,-1156,-1153,-1149,-1145,-1140,-1135,
--1129,-1122,-1114,-1106,-1097,-1088,-1078,-1067,-1056,-1045,-1034,-1022,-1010,-999,-987,-976,-965,-955,-944,-934,-923,
--913,-902,-892,-881,-869,-858,-845,-833,-820,-807,-794,-781,-768,-756,-744,-734,-724,-715,-707,-701,-696,
--692,-689,-687,-685,-683,-682,-680,-708,-706,-704,-701,-697,-692,-685,-678,-668,-658,-646,-634,-620,-606,
--592,-577,-562,-548,-534,-521,-509,-497,-485,-475,-465,-455,-446,-437,-428,-419,-409,-400,-390,-380,-370,
--359,-348,-336,-325,-314,-303,-292,-281,-271,-262,-252,-244,-236,-228,-221,-214,-208,-201,-194,-188,-181,
--173,-165,-157,-148,-138,-128,-117,-105,-93,-81,-68,-55,-42,-30,-17,-5,7,18,29,40,50,
-59,68,76,85,92,100,108,115,123,131,139,148,157,166,176,187,197,208,220,231,242,
-254,265,276,287,298,308,318,327,336,344,351,358,365,371,376,380,384,387,389,390,390,
-389,386,383,379,373,366,358,350,340,330,319,308,297,287,276,266,257,249,243,237,233,
-230,228,228,229,231,235,239,245,251,258,265,274,282,292,302,312,323,334,346,359,372,
-385,399,413,426,440,453,465,476,487,496,503,510,514,518,519,520,519,517,515,512,510,
-507,506,505,505,506,508,512,516,522,527,534,540,546,551,556,559,562,563,563,562,561,
-559,558,557,557,559,563,570,579,592,608,627,649,673,700,729,758,787,816,843,868,890,
-908,921,931,936,936,931,923,911,896,878,859,839,819,800,782,766,751,739,729,722,716,
-712,708,706,703,699,695,688,680,669,656,640,622,602,581,559,536,513,492,471,453,437,
-425,415,408,404,404,405,410,416,423,431,440,448,456,463,470,475,479,482,484,486,488,
-490,492,495,500,505,511,519,527,537,547,557,567,576,584,590,595,597,596,593,587,578,
-567,554,538,521,503,485,466,447,429,412,395,380,366,353,341,330,320,310,300,290,280,
-269,258,246,234,220,206,191,176,160,143,127,110,94,78,61,46,30,14,0,-16,-31,
--47,-63,-79,-95,-112,-130,-148,-166,-186,-206,-228,-250,-273,-297,-323,-349,-377,-406,-436,-467,-499,
--532,-566,-601,-636,-671,-707,-742,-777,-811,-844,-877,-908,-939,-968,-996,-1022,-1048,-1073,-1097,-1121,-1144,
--1167,-1191,-1215,-1239,-1263,-1289,-1315,-1341,-1368,-1395,-1423,-1450,-1478,-1506,-1533,-1560,-1587,-1614,-1640,-1666,-1692,
--1718,-1743,-1768,-1794,-1819,-1845,-1871,-1897,-1922,-1948,-1974,-2000,-2026,-2051,-2076,-2101,-2125,-2149,-2173,-2197,-2220,
--2244,-2268,-2293,-2318,-2344,-2371,-2399,-2428,-2458,-2489,-2521,-2553,-2586,-2619,-2651,-2684,-2716,-2747,-2776,-2805,-2832,
--2858,-2883,-2906,-2928,-2950,-2970,-2990,-3009,-3028,-3047,-3066,-3085,-3104,-3124,-3144,-3165,-3186,-3207,-3228,-3250,-3271,
--3292,-3313,-3334,-3354,-3375,-3396,-3417,-3438,-3459,-3481,-3504,-3527,-3551,-3576,-3602,-3629,-3656,-3683,-3710,-3737,-3764,
--3790,-3815,-3838,-3860,-3880,-3898,-3915,-3929,-3941,-3952,-3962,-3970,-3978,-3984,-3991,-3998,-4006,-4014,-4023,-4033,-4045,
--4058,-4072,-4088,-4105,-4123,-4141,-4161,-4180,-4200,-4219,-4239,-4258,-4276,-4294,-4312,-4329,-4346,-4362,-4379,-4396,-4413,
--4431,-4449,-4469,-4489,-4511,-4534,-4558,-4583,-4609,-4636,-4663,-4691,-4718,-4746,-4773,-4799,-4824,-4847,-4869,-4889,-4908,
--4924,-4938,-4950,-4960,-4969,-4975,-4980,-4984,-4986,-4988,-4989,-4989,-4989,-4989,-4989,-4990,-4990,-4990,-4991,-4992,-4993,
--4994,-4995,-4996,-4996,-4997,-4997,-4997,-4997,-4997,-4996,-4995,-4995,-4995,-4995,-4995,-4997,-4999,-5002,-5007,-5012,-5018,
--5025,-5033,-5041,-5050,-5058,-5067,-5074,-5081,-5086,-5090,-5093,-5093,-5092,-5089,-5085,-5080,-5074,-5068,-5063,-5058,-5055,
--5054,-5055,-5060,-5068,-5080,-5096,-5116,-5140,-5167,-5196,-5228,-5261,-5295,-5329,-5361,-5391,-5418,-5441,-5460,-5473,-5482,
--5485,-5483,-5476,-5464,-5448,-5429,-5407,-5382,-5357,-5331,-5305,-5281,-5257,-5235,-5216,-5198,-5183,-5170,-5159,-5149,-5141,
--5135,-5129,-5124,-5119,-5115,-5110,-5106,-5102,-5098,-5094,-5091,-5088,-5086,-5085,-5084,-5084,-5085,-5087,-5089,-5093,-5096,
--5100,-5105,-5109,-5113,-5117,-5121,-5124,-5127,-5130,-5133,-5135,-5138,-5140,-5143,-5147,-5151,-5155,-5161,-5166,-5173,-5179,
--5186,-5194,-5201,-5209,-5216,-5223,-5230,-5236,-5241,-5246,-5251,-5254,-5258,-5260,-5263,-5264,-5266,-5267,-5268,-5268,-5269,
--5269,-5269,-5269,-5268,-5268,-5267,-5266,-5265,-5264,-5263,-5263,-5262,-5261,-5261,-5261,-5262,-5262,-5263,-5265,-5266,-5267,
--5269,-5270,-5271,-5272,-5272,-5272,-5271,-5269,-5267,-5265,-5263,-5260,-5257,-5254,-5251,-5249,-5247,-5245,-5245,-5245,-5245,
--5246,-5248,-5250,-5253,-5255,-5258,-5261,-5263,-5266,-5268,-5269,-5270,-5271,-5271,-5271,-5270,-5270,-5269,-5267,-5266,-5264,
--5263,-5261,-5259,-5257,-5255,-5253,-5250,-5247,-5244,-5241,-5238,-5234,-5231,-5227,-5224,-5221,-5219,-5218,-5217,-5217,-5218,
--5220,-5223,-5226,-5231,-5235,-5240,-5245,-5250,-5254,-5258,-5260,-5261,-5261,-5259,-5256,-5252,-5246,-5239,-5230,-5221,-5211,
--5202,-5192,-5182,-5172,-5164,-5156,-5148,-5142,-5136,-5131,-5126,-5121,-5117,-5112,-5106,-5100,-5093,-5085,-5076,-5066,-5055,
--5042,-5029,-5015,-5001,-4986,-4972,-4958,-4945,-4933,-4922,-4911,-4902,-4894,-4887,-4882,-4876,-4871,-4867,-4862,-4857,-4852,
--4846,-4839,-4831,-4822,-4812,-4801,-4790,-4778,-4766,-4753,-4741,-4730,-4719,-4709,-4701,-4693,-4686,-4680,-4675,-4670,-4665,
--4660,-4655,-4648,-4641,-4631,-4620,-4607,-4591,-4572,-4552,-4529,-4504,-4477,-4448,-4419,-4389,-4359,-4329,-4300,-4272,-4245,
--4220,-4198,-4177,-4159,-4143,-4130,-4118,-4109,-4101,-4095,-4090,-4086,-4083,-4080,-4078,-4076,-4074,-4072,-4070,-4068,-4065,
--4062,-4059,-4056,-4053,-4049,-4045,-4041,-4037,-4032,-4027,-4021,-4014,-4007,-3999,-3990,-3981,-3971,-3959,-3948,-3935,-3923,
--3910,-3897,-3884,-3871,-3860,-3848,-3838,-3829,-3821,-3815,-3810,-3806,-3804,-3803,-3803,-3805,-3807,-3811,-3814,-3819,-3823,
--3827,-3831,-3835,-3838,-3841,-3842,-3843,-3842,-3840,-3837,-3833,-3827,-3820,-3811,-3802,-3791,-3779,-3765,-3750,-3734,-3718,
--3700,-3681,-3661,-3640,-3618,-3596,-3572,-3549,-3524,-3499,-3474,-3449,-3423,-3397,-3372,-3347,-3322,-3297,-3274,-3251,-3229,
--3209,-3188,-3169,-3151,-3133,-3115,-3098,-3081,-3063,-3045,-3027,-3007,-2986,-2964,-2941,-2917,-2891,-2864,-2837,-2809,-2780,
--2752,-2725,-2698,-2672,-2648,-2626,-2605,-2587,-2570,-2555,-2541,-2529,-2518,-2508,-2498,-2488,-2477,-2466,-2454,-2440,-2426,
--2411,-2394,-2377,-2360,-2342,-2325,-2308,-2293,-2279,-2267,-2257,-2249,-2243,-2240,-2239,-2239,-2242,-2245,-2250,-2255,-2260,
--2264,-2268,-2271,-2273,-2273,-2272,-2269,-2265,-2259,-2252,-2245,-2237,-2229,-2222,-2215,-2209,-2205,-2203,-2202,-2204,-2208,
--2215,-2224,-2236,-2250,-2266,-2284,-2303,-2324,-2345,-2366,-2388,-2408,-2427,-2444,-2460,-2473,-2483,-2490,-2494,-2495,-2494,
--2489,-2482,-2472,-2461,-2449,-2435,-2421,-2408,-2394,-2382,-2371,-2361,-2353,-2346,-2341,-2337,-2335,-2333,-2332,-2331,-2330,
--2329,-2326,-2323,-2318,-2311,-2303,-2294,-2283,-2270,-2257,-2243,-2228,-2214,-2199,-2185,-2172,-2160,-2148,-2138,-2130,-2122,
--2116,-2111,-2107,-2103,-2100,-2097,-2094,-2091,-2088,-2085,-2080,-2076,-2071,-2065,-2060,-2054,-2048,-2042,-2037,-2032,-2029,
--2026,-2024,-2023,-2024,-2027,-2030,-2035,-2041,-2048,-2057,-2066,-2076,-2086,-2096,-2107,-2117,-2127,-2136,-2145,-2152,-2159,
--2165,-2169,-2173,-2176,-2178,-2179,-2179,-2179,-2178,-2177,-2176,-2175,-2173,-2172,-2170,-2168,-2165,-2162,-2157,-2152,-2146,
--2138,-2129,-2117,-2104,-2088,-2071,-2051,-2030,-2007,-1982,-1957,-1930,-1904,-1878,-1852,-1827,-1804,-1783,-1764,-1747,-1733,
--1722,-1714,-1708,-1705,-1705,-1706,-1710,-1715,-1721,-1728,-1736,-1744,-1752,-1760,-1767,-1774,-1780,-1786,-1791,-1794,-1797,
--1799,-1800,-1800,-1799,-1797,-1794,-1789,-1784,-1778,-1772,-1764,-1756,-1747,-1738,-1730,-1721,-1714,-1707,-1702,-1699,-1697,
--1698,-1702,-1708,-1716,-1727,-1740,-1755,-1772,-1789,-1806,-1823,-1838,-1852,-1864,-1872,-1876,-1877,-1873,-1865,-1853,-1836,
--1816,-1793,-1766,-1738,-1709,-1679,-1650,-1622,-1595,-1571,-1550,-1532,-1517,-1506,-1498,-1493,-1491,-1491,-1492,-1495,-1498,
--1502,-1505,-1507,-1508,-1507,-1504,-1500,-1494,-1486,-1477,-1466,-1454,-1442,-1429,-1416,-1403,-1391,-1379,-1368,-1357,-1348,
--1339,-1331,-1323,-1316,-1308,-1302,-1295,-1288,-1280,-1273,-1265,-1256,-1248,-1239,-1229,-1220,-1211,-1202,-1193,-1184,-1175,
--1167,-1160,-1153,-1147,-1141,-1135,-1130,-1125,-1120,-1115,-1110,-1105,-1099,-1093,-1086,-1079,-1072,-1063,-1054,-1045,-1035,
--1025,-1015,-1005,-995,-985,-975,-966,-957,-948,-940,-932,-924,-917,-910,-903,-895,-887,-879,-871,-861,-852,
--841,-830,-819,-808,-796,-785,-774,-764,-754,-745,-737,-730,-725,-720,-717,-714,-712,-710,-709,-708,-742,
--741,-740,-738,-736,-733,-728,-722,-716,-707,-698,-687,-676,-663,-650,-636,-623,-609,-596,-583,-570,-559,
--548,-537,-528,-519,-510,-502,-494,-486,-478,-470,-462,-453,-444,-434,-425,-414,-404,-393,-382,-371,-361,
--351,-341,-332,-323,-315,-308,-301,-295,-289,-283,-278,-272,-267,-261,-254,-247,-239,-229,-220,-209,-197,
--184,-171,-157,-142,-127,-112,-97,-83,-68,-54,-41,-29,-17,-6,3,12,21,29,37,45,52,
-59,67,75,83,92,101,111,121,133,144,156,169,182,195,208,221,234,247,259,271,283,
-294,304,314,323,331,338,345,350,355,359,361,362,362,361,359,355,349,343,335,327,317,
-306,295,284,272,260,249,238,228,218,210,203,198,194,191,190,190,192,194,198,203,209,
-216,223,231,240,249,258,267,277,288,298,309,320,332,343,355,366,378,389,399,409,418,
-427,434,440,445,449,452,453,454,455,454,454,453,453,453,454,456,459,462,467,472,478,
-484,490,496,502,507,511,514,515,516,515,512,509,506,502,498,496,494,495,498,504,513,
-525,541,560,582,608,635,664,695,725,756,784,811,835,855,872,884,892,895,894,889,881,
-870,856,841,824,808,792,776,762,750,739,730,722,716,711,707,703,698,692,685,676,665,
-652,637,620,600,580,558,535,513,491,470,452,435,421,410,402,397,395,396,399,405,411,
-419,428,437,445,453,460,466,471,476,479,482,485,488,492,496,501,508,516,526,536,548,
-561,574,588,600,612,622,630,636,639,638,634,627,617,603,586,567,546,524,500,476,452,
-429,406,385,365,347,330,315,301,289,278,267,257,247,238,227,217,205,193,181,167,153,
-138,123,107,91,76,60,44,28,13,-2,-17,-32,-47,-63,-78,-95,-111,-129,-147,-166,-187,
--208,-231,-254,-279,-305,-333,-361,-390,-419,-450,-481,-513,-545,-577,-609,-642,-674,-706,-738,-770,-801,
--831,-862,-891,-921,-949,-978,-1005,-1033,-1060,-1086,-1113,-1139,-1165,-1191,-1217,-1242,-1268,-1294,-1319,-1345,-1370,
--1395,-1420,-1445,-1470,-1494,-1519,-1543,-1568,-1592,-1616,-1640,-1664,-1689,-1714,-1739,-1764,-1789,-1814,-1840,-1866,-1892,
--1917,-1943,-1968,-1994,-2018,-2043,-2068,-2092,-2116,-2140,-2164,-2189,-2213,-2239,-2265,-2292,-2320,-2349,-2379,-2410,-2442,
--2475,-2508,-2542,-2576,-2610,-2644,-2677,-2709,-2740,-2770,-2798,-2825,-2850,-2874,-2897,-2918,-2938,-2958,-2977,-2996,-3014,
--3032,-3051,-3070,-3089,-3109,-3128,-3149,-3169,-3189,-3209,-3229,-3249,-3268,-3286,-3304,-3322,-3338,-3355,-3371,-3387,-3404,
--3421,-3438,-3457,-3476,-3497,-3519,-3542,-3566,-3592,-3618,-3646,-3673,-3701,-3728,-3754,-3780,-3804,-3827,-3848,-3867,-3884,
--3899,-3912,-3924,-3933,-3942,-3950,-3957,-3964,-3971,-3978,-3987,-3996,-4007,-4019,-4033,-4048,-4064,-4082,-4100,-4120,-4140,
--4160,-4181,-4201,-4221,-4240,-4259,-4277,-4295,-4312,-4328,-4344,-4360,-4376,-4392,-4408,-4426,-4444,-4463,-4484,-4505,-4528,
--4553,-4578,-4604,-4631,-4658,-4685,-4712,-4739,-4764,-4788,-4810,-4831,-4849,-4865,-4878,-4889,-4897,-4904,-4908,-4910,-4910,
--4910,-4908,-4906,-4903,-4901,-4899,-4898,-4898,-4899,-4901,-4904,-4908,-4913,-4919,-4926,-4933,-4940,-4948,-4955,-4962,-4968,
--4974,-4979,-4983,-4987,-4991,-4994,-4997,-5001,-5005,-5009,-5014,-5021,-5028,-5036,-5045,-5055,-5066,-5077,-5087,-5098,-5107,
--5115,-5122,-5127,-5129,-5129,-5126,-5120,-5112,-5102,-5090,-5077,-5062,-5048,-5034,-5021,-5010,-5002,-4996,-4994,-4996,-5001,
--5011,-5024,-5040,-5060,-5082,-5106,-5131,-5156,-5180,-5203,-5224,-5242,-5257,-5268,-5276,-5280,-5279,-5275,-5268,-5258,-5245,
--5230,-5214,-5197,-5180,-5164,-5148,-5133,-5119,-5107,-5097,-5088,-5081,-5076,-5072,-5068,-5066,-5065,-5063,-5063,-5062,-5061,
--5061,-5060,-5059,-5059,-5058,-5058,-5058,-5058,-5059,-5060,-5062,-5064,-5066,-5069,-5073,-5077,-5082,-5086,-5091,-5096,-5101,
--5106,-5111,-5116,-5121,-5126,-5131,-5135,-5140,-5144,-5148,-5152,-5156,-5160,-5163,-5166,-5169,-5172,-5174,-5176,-5178,-5180,
--5181,-5183,-5184,-5186,-5187,-5189,-5190,-5192,-5194,-5196,-5198,-5200,-5203,-5205,-5208,-5210,-5213,-5215,-5218,-5220,-5222,
--5224,-5226,-5227,-5228,-5230,-5230,-5231,-5232,-5232,-5232,-5232,-5232,-5231,-5230,-5229,-5227,-5225,-5222,-5219,-5216,-5212,
--5208,-5204,-5200,-5196,-5192,-5188,-5184,-5181,-5178,-5175,-5173,-5172,-5171,-5171,-5172,-5173,-5174,-5175,-5177,-5179,-5181,
--5183,-5186,-5188,-5190,-5192,-5195,-5197,-5200,-5202,-5205,-5208,-5211,-5213,-5216,-5219,-5222,-5224,-5227,-5228,-5230,-5231,
--5231,-5231,-5230,-5229,-5227,-5225,-5222,-5219,-5216,-5214,-5211,-5209,-5207,-5205,-5204,-5204,-5204,-5204,-5205,-5206,-5207,
--5207,-5208,-5209,-5209,-5209,-5208,-5206,-5204,-5202,-5199,-5197,-5193,-5190,-5187,-5184,-5182,-5179,-5177,-5176,-5174,-5173,
--5172,-5171,-5169,-5166,-5163,-5159,-5154,-5147,-5139,-5129,-5117,-5104,-5090,-5074,-5057,-5039,-5021,-5002,-4984,-4965,-4948,
--4931,-4915,-4900,-4887,-4875,-4864,-4854,-4844,-4836,-4828,-4821,-4813,-4805,-4797,-4789,-4779,-4770,-4759,-4748,-4737,-4725,
--4713,-4702,-4690,-4679,-4669,-4659,-4650,-4642,-4634,-4628,-4622,-4616,-4610,-4603,-4597,-4589,-4580,-4570,-4558,-4544,-4529,
--4511,-4491,-4470,-4447,-4422,-4397,-4371,-4344,-4318,-4292,-4267,-4243,-4220,-4199,-4180,-4163,-4148,-4134,-4123,-4113,-4105,
--4098,-4092,-4087,-4083,-4079,-4076,-4072,-4069,-4066,-4062,-4059,-4055,-4051,-4047,-4043,-4039,-4035,-4030,-4026,-4021,-4016,
--4011,-4005,-3999,-3992,-3984,-3976,-3967,-3957,-3947,-3936,-3924,-3912,-3900,-3887,-3875,-3863,-3851,-3841,-3831,-3823,-3816,
--3811,-3807,-3804,-3804,-3804,-3806,-3809,-3813,-3818,-3824,-3830,-3836,-3841,-3847,-3852,-3856,-3860,-3862,-3863,-3864,-3863,
--3860,-3857,-3852,-3846,-3839,-3830,-3820,-3809,-3797,-3783,-3768,-3752,-3734,-3715,-3695,-3674,-3651,-3628,-3603,-3578,-3552,
--3525,-3498,-3471,-3443,-3416,-3389,-3363,-3338,-3313,-3289,-3266,-3244,-3223,-3203,-3184,-3165,-3147,-3129,-3111,-3093,-3074,
--3054,-3034,-3012,-2990,-2966,-2941,-2915,-2888,-2860,-2832,-2803,-2775,-2747,-2720,-2695,-2671,-2648,-2628,-2609,-2593,-2578,
--2566,-2555,-2546,-2538,-2530,-2523,-2517,-2510,-2502,-2494,-2486,-2476,-2466,-2455,-2443,-2431,-2420,-2409,-2399,-2390,-2383,
--2378,-2376,-2375,-2378,-2383,-2391,-2401,-2413,-2426,-2441,-2457,-2472,-2488,-2503,-2516,-2528,-2538,-2546,-2551,-2553,-2553,
--2551,-2546,-2539,-2531,-2521,-2511,-2499,-2488,-2476,-2466,-2456,-2447,-2439,-2433,-2429,-2426,-2425,-2425,-2427,-2431,-2435,
--2441,-2447,-2454,-2461,-2468,-2475,-2481,-2487,-2493,-2497,-2500,-2503,-2504,-2504,-2504,-2502,-2499,-2495,-2490,-2485,-2479,
--2473,-2466,-2460,-2453,-2446,-2438,-2431,-2424,-2417,-2410,-2403,-2396,-2389,-2382,-2374,-2366,-2357,-2349,-2339,-2330,-2319,
--2309,-2297,-2286,-2274,-2262,-2250,-2238,-2226,-2214,-2202,-2191,-2181,-2171,-2161,-2153,-2145,-2138,-2132,-2126,-2122,-2118,
--2115,-2113,-2112,-2110,-2110,-2110,-2110,-2111,-2112,-2113,-2114,-2116,-2117,-2120,-2122,-2125,-2128,-2132,-2136,-2141,-2147,
--2153,-2160,-2168,-2176,-2185,-2194,-2203,-2212,-2222,-2230,-2239,-2246,-2253,-2259,-2264,-2268,-2271,-2272,-2273,-2272,-2271,
--2269,-2267,-2264,-2261,-2258,-2255,-2253,-2250,-2248,-2245,-2243,-2240,-2238,-2234,-2230,-2224,-2218,-2209,-2200,-2188,-2175,
--2160,-2143,-2125,-2106,-2085,-2064,-2043,-2021,-2000,-1980,-1961,-1943,-1926,-1911,-1898,-1888,-1878,-1871,-1865,-1861,-1858,
--1856,-1855,-1855,-1855,-1855,-1855,-1855,-1855,-1855,-1855,-1854,-1853,-1851,-1849,-1847,-1844,-1841,-1838,-1834,-1830,-1826,
--1821,-1816,-1810,-1805,-1799,-1793,-1787,-1782,-1777,-1773,-1769,-1768,-1767,-1768,-1771,-1776,-1782,-1791,-1800,-1811,-1823,
--1835,-1847,-1858,-1868,-1877,-1882,-1885,-1885,-1881,-1873,-1862,-1846,-1827,-1804,-1778,-1750,-1720,-1689,-1658,-1627,-1598,
--1570,-1544,-1522,-1503,-1487,-1475,-1466,-1461,-1458,-1459,-1461,-1465,-1470,-1475,-1480,-1485,-1488,-1489,-1489,-1486,-1482,
--1475,-1466,-1456,-1444,-1430,-1416,-1401,-1386,-1371,-1357,-1343,-1330,-1317,-1306,-1296,-1287,-1279,-1271,-1264,-1257,-1251,
--1244,-1238,-1231,-1224,-1216,-1208,-1199,-1190,-1181,-1172,-1162,-1153,-1144,-1135,-1127,-1119,-1112,-1105,-1099,-1094,-1089,
--1085,-1081,-1077,-1073,-1069,-1065,-1060,-1055,-1050,-1044,-1038,-1031,-1024,-1017,-1009,-1001,-993,-986,-978,-971,-964,
--958,-952,-947,-941,-936,-931,-926,-921,-916,-910,-903,-896,-888,-879,-870,-860,-849,-838,-827,-816,-806,
--795,-786,-777,-769,-762,-757,-752,-749,-746,-744,-743,-742,-789,-788,-786,-785,-783,-781,-778,-774,-769,
--763,-756,-747,-738,-727,-716,-705,-692,-680,-668,-656,-644,-633,-622,-612,-603,-594,-586,-578,-570,-563,
--556,-549,-541,-534,-526,-518,-509,-500,-491,-481,-471,-461,-451,-442,-432,-423,-415,-407,-399,-392,-385,
--379,-373,-367,-361,-355,-349,-342,-335,-327,-319,-309,-298,-287,-275,-262,-248,-234,-219,-204,-189,-174,
--160,-145,-132,-119,-106,-94,-83,-72,-62,-52,-43,-34,-25,-16,-6,3,13,23,35,47,59,
-72,86,100,114,130,145,160,175,190,205,220,234,247,260,272,284,294,304,312,320,326,
-331,335,338,339,338,336,333,328,322,315,306,296,285,274,262,249,237,225,213,202,192,
-182,174,168,163,159,157,156,157,159,163,167,173,180,187,195,203,212,221,230,239,249,
-258,268,277,286,296,305,314,322,331,339,346,353,360,365,370,375,378,381,383,385,387,
-388,389,390,392,394,397,400,404,409,414,420,426,433,439,446,451,456,460,463,465,465,
-464,462,459,455,451,446,443,440,439,440,443,449,459,472,488,507,530,555,582,612,642,
-673,703,732,760,784,806,824,839,849,856,858,857,852,844,834,823,809,795,781,767,754,
-742,730,720,711,702,694,687,679,671,662,652,640,627,613,596,578,559,539,519,498,478,
-458,440,424,410,398,389,383,379,378,380,383,389,395,403,411,419,427,434,441,447,453,
-457,462,466,470,475,480,486,493,501,511,522,534,547,560,574,587,600,611,621,629,633,
-635,634,629,621,609,594,576,556,533,509,484,458,432,407,383,360,338,318,300,283,268,
-255,243,231,221,211,201,191,180,170,158,146,133,119,105,91,76,60,45,30,14,0,
--15,-30,-45,-60,-75,-90,-106,-123,-140,-158,-178,-198,-220,-244,-268,-294,-322,-350,-379,-410,-441,
--472,-504,-536,-568,-600,-631,-662,-693,-723,-752,-781,-810,-838,-865,-892,-919,-946,-973,-1000,-1027,-1053,
--1080,-1107,-1134,-1161,-1189,-1216,-1242,-1269,-1295,-1321,-1346,-1371,-1396,-1420,-1443,-1466,-1488,-1511,-1533,-1555,-1577,
--1599,-1621,-1643,-1666,-1689,-1713,-1737,-1761,-1786,-1812,-1837,-1862,-1888,-1914,-1939,-1964,-1989,-2014,-2038,-2063,-2087,
--2111,-2135,-2160,-2185,-2211,-2237,-2264,-2293,-2322,-2352,-2383,-2416,-2449,-2482,-2516,-2550,-2584,-2618,-2651,-2683,-2714,
--2744,-2773,-2800,-2825,-2850,-2873,-2894,-2915,-2935,-2954,-2973,-2991,-3010,-3029,-3048,-3067,-3086,-3106,-3126,-3146,-3166,
--3186,-3206,-3224,-3243,-3260,-3276,-3292,-3307,-3321,-3335,-3348,-3361,-3374,-3387,-3402,-3417,-3433,-3451,-3470,-3491,-3514,
--3538,-3563,-3590,-3617,-3645,-3674,-3702,-3729,-3756,-3781,-3804,-3826,-3846,-3864,-3880,-3894,-3906,-3917,-3926,-3934,-3942,
--3949,-3956,-3964,-3972,-3981,-3991,-4002,-4015,-4028,-4043,-4059,-4076,-4094,-4112,-4131,-4150,-4168,-4187,-4205,-4223,-4241,
--4258,-4275,-4292,-4308,-4325,-4342,-4360,-4378,-4397,-4417,-4439,-4461,-4485,-4509,-4534,-4560,-4587,-4613,-4640,-4665,-4690,
--4713,-4735,-4755,-4772,-4787,-4800,-4809,-4817,-4822,-4824,-4825,-4824,-4822,-4819,-4815,-4812,-4809,-4807,-4806,-4806,-4808,
--4811,-4816,-4823,-4831,-4840,-4851,-4862,-4873,-4884,-4896,-4906,-4916,-4925,-4933,-4939,-4945,-4950,-4954,-4958,-4961,-4965,
--4969,-4974,-4980,-4988,-4996,-5007,-5018,-5031,-5045,-5059,-5073,-5087,-5100,-5112,-5121,-5128,-5132,-5132,-5129,-5122,-5111,
--5097,-5079,-5058,-5036,-5011,-4986,-4962,-4938,-4916,-4896,-4880,-4868,-4860,-4857,-4858,-4864,-4875,-4889,-4907,-4928,-4952,
--4976,-5001,-5026,-5049,-5071,-5090,-5107,-5120,-5129,-5135,-5138,-5137,-5133,-5127,-5118,-5108,-5097,-5085,-5073,-5062,-5051,
--5042,-5033,-5027,-5021,-5018,-5015,-5014,-5014,-5015,-5016,-5018,-5019,-5021,-5023,-5024,-5025,-5025,-5025,-5024,-5023,-5022,
--5022,-5021,-5020,-5020,-5021,-5022,-5024,-5027,-5030,-5034,-5039,-5044,-5050,-5057,-5063,-5070,-5077,-5083,-5089,-5095,-5100,
--5105,-5108,-5111,-5113,-5115,-5116,-5116,-5115,-5115,-5113,-5112,-5111,-5110,-5109,-5108,-5108,-5108,-5109,-5110,-5112,-5115,
--5118,-5122,-5126,-5131,-5136,-5141,-5146,-5152,-5157,-5162,-5167,-5171,-5175,-5179,-5183,-5186,-5188,-5190,-5192,-5193,-5194,
--5195,-5195,-5194,-5193,-5192,-5191,-5188,-5186,-5183,-5180,-5176,-5172,-5167,-5162,-5157,-5152,-5147,-5142,-5137,-5132,-5127,
--5123,-5119,-5116,-5113,-5110,-5108,-5107,-5106,-5105,-5105,-5105,-5106,-5107,-5108,-5110,-5112,-5114,-5117,-5119,-5123,-5126,
--5130,-5134,-5139,-5143,-5148,-5153,-5158,-5163,-5168,-5173,-5178,-5182,-5185,-5188,-5190,-5192,-5193,-5194,-5193,-5193,-5191,
--5189,-5187,-5185,-5182,-5179,-5176,-5174,-5171,-5168,-5166,-5164,-5162,-5161,-5159,-5158,-5157,-5155,-5155,-5154,-5153,-5152,
--5152,-5151,-5151,-5151,-5151,-5152,-5152,-5153,-5154,-5156,-5157,-5158,-5158,-5158,-5158,-5157,-5155,-5151,-5146,-5140,-5132,
--5123,-5112,-5099,-5085,-5069,-5052,-5034,-5015,-4996,-4976,-4957,-4938,-4919,-4901,-4884,-4868,-4853,-4839,-4826,-4814,-4804,
--4794,-4784,-4775,-4767,-4758,-4750,-4741,-4732,-4723,-4714,-4704,-4695,-4685,-4675,-4666,-4656,-4647,-4639,-4630,-4623,-4616,
--4609,-4602,-4595,-4589,-4582,-4574,-4566,-4557,-4547,-4535,-4522,-4507,-4490,-4472,-4453,-4432,-4409,-4386,-4362,-4338,-4314,
--4290,-4267,-4244,-4223,-4203,-4184,-4167,-4152,-4139,-4127,-4116,-4107,-4100,-4093,-4087,-4082,-4077,-4072,-4068,-4063,-4059,
--4054,-4050,-4045,-4040,-4035,-4029,-4024,-4019,-4013,-4008,-4003,-3997,-3992,-3986,-3980,-3974,-3968,-3961,-3954,-3946,-3938,
--3929,-3920,-3910,-3900,-3890,-3880,-3870,-3861,-3852,-3843,-3836,-3829,-3824,-3819,-3816,-3814,-3813,-3813,-3814,-3817,-3819,
--3822,-3826,-3830,-3834,-3837,-3841,-3844,-3846,-3848,-3849,-3849,-3848,-3846,-3843,-3840,-3835,-3829,-3822,-3813,-3804,-3793,
--3781,-3767,-3752,-3735,-3717,-3697,-3677,-3654,-3631,-3606,-3580,-3554,-3527,-3499,-3472,-3445,-3418,-3392,-3366,-3342,-3319,
--3297,-3276,-3257,-3238,-3221,-3204,-3188,-3172,-3156,-3140,-3124,-3106,-3088,-3068,-3047,-3024,-2999,-2974,-2947,-2919,-2890,
--2860,-2831,-2801,-2773,-2745,-2719,-2694,-2671,-2651,-2632,-2616,-2603,-2591,-2581,-2573,-2567,-2561,-2556,-2552,-2547,-2543,
--2538,-2532,-2526,-2519,-2511,-2503,-2495,-2486,-2479,-2472,-2466,-2463,-2461,-2461,-2463,-2469,-2477,-2487,-2500,-2515,-2532,
--2551,-2570,-2590,-2611,-2630,-2649,-2666,-2682,-2695,-2706,-2715,-2720,-2723,-2723,-2721,-2716,-2710,-2701,-2691,-2680,-2668,
--2655,-2642,-2629,-2617,-2605,-2593,-2583,-2573,-2564,-2556,-2550,-2544,-2539,-2535,-2533,-2531,-2530,-2530,-2530,-2531,-2533,
--2535,-2538,-2541,-2543,-2546,-2549,-2551,-2553,-2554,-2555,-2554,-2553,-2551,-2547,-2543,-2537,-2531,-2523,-2515,-2506,-2496,
--2486,-2476,-2466,-2455,-2445,-2435,-2425,-2415,-2406,-2397,-2389,-2380,-2371,-2363,-2354,-2344,-2335,-2324,-2313,-2302,-2290,
--2278,-2265,-2252,-2239,-2226,-2213,-2201,-2189,-2179,-2170,-2162,-2156,-2151,-2148,-2147,-2147,-2149,-2152,-2156,-2161,-2167,
--2173,-2179,-2186,-2193,-2199,-2205,-2211,-2217,-2222,-2227,-2231,-2236,-2241,-2246,-2251,-2256,-2262,-2268,-2275,-2282,-2290,
--2297,-2305,-2312,-2319,-2326,-2332,-2337,-2341,-2344,-2347,-2348,-2348,-2348,-2346,-2344,-2342,-2340,-2337,-2335,-2333,-2332,
--2331,-2330,-2330,-2330,-2330,-2330,-2330,-2329,-2327,-2325,-2321,-2316,-2309,-2300,-2289,-2277,-2263,-2247,-2230,-2212,-2193,
--2174,-2154,-2135,-2115,-2097,-2079,-2062,-2046,-2032,-2019,-2007,-1997,-1987,-1978,-1971,-1964,-1957,-1951,-1945,-1939,-1934,
--1928,-1923,-1917,-1912,-1906,-1901,-1895,-1890,-1885,-1880,-1875,-1871,-1866,-1862,-1858,-1854,-1851,-1847,-1844,-1841,-1838,
--1836,-1834,-1833,-1833,-1834,-1835,-1837,-1841,-1845,-1850,-1855,-1861,-1867,-1873,-1879,-1883,-1887,-1888,-1888,-1885,-1879,
--1871,-1859,-1844,-1826,-1805,-1782,-1755,-1728,-1698,-1668,-1638,-1608,-1579,-1552,-1526,-1504,-1484,-1467,-1454,-1444,-1437,
--1432,-1431,-1431,-1434,-1437,-1441,-1446,-1450,-1453,-1455,-1455,-1454,-1451,-1446,-1439,-1430,-1419,-1408,-1395,-1381,-1367,
--1353,-1340,-1326,-1313,-1302,-1291,-1281,-1272,-1264,-1256,-1250,-1244,-1238,-1232,-1226,-1220,-1214,-1207,-1200,-1192,-1184,
--1176,-1167,-1158,-1150,-1141,-1133,-1125,-1118,-1111,-1105,-1100,-1096,-1093,-1090,-1088,-1087,-1085,-1084,-1083,-1082,-1080,
--1078,-1075,-1072,-1069,-1064,-1060,-1055,-1049,-1043,-1037,-1031,-1026,-1020,-1014,-1009,-1004,-999,-994,-989,-984,-979,
--974,-968,-962,-955,-947,-939,-930,-920,-909,-899,-887,-876,-865,-854,-844,-834,-825,-817,-810,-804,-799,
--796,-793,-791,-789,-853,-850,-848,-845,-843,-840,-836,-832,-828,-822,-816,-808,-800,-791,-782,-771,-760,
--749,-738,-727,-716,-705,-694,-684,-675,-666,-657,-650,-642,-635,-629,-622,-616,-610,-603,-597,-590,-584,
--577,-569,-562,-554,-547,-539,-531,-524,-516,-509,-501,-494,-487,-480,-473,-465,-458,-450,-443,-434,-426,
--416,-406,-396,-384,-372,-360,-346,-333,-319,-304,-290,-275,-261,-246,-232,-219,-205,-192,-180,-168,-156,
--144,-133,-122,-111,-100,-89,-78,-66,-54,-42,-29,-15,-1,12,28,43,59,75,91,108,124,
-141,157,173,189,204,218,232,245,257,268,279,287,295,302,307,310,312,313,312,309,305,
-299,292,284,275,265,254,242,231,219,208,196,186,176,168,160,154,150,146,144,144,144,
-146,149,153,158,164,170,177,184,191,198,206,213,221,228,235,242,249,255,262,267,273,
-278,283,288,292,295,298,301,302,304,305,306,307,307,308,309,310,311,313,316,319,323,
-328,333,339,345,352,358,364,370,375,379,383,385,386,386,386,384,382,380,378,377,376,
-377,379,384,390,400,412,426,444,464,486,510,535,561,588,614,639,663,685,705,721,735,
-745,752,756,757,754,749,742,734,724,713,701,689,678,667,656,647,637,628,620,612,604,
-595,586,576,566,554,542,528,514,499,484,468,452,437,423,410,398,388,380,374,370,369,
-369,370,374,378,384,390,397,404,411,417,424,429,435,440,445,450,455,460,466,473,480,
-488,497,507,518,529,540,552,562,572,580,587,592,594,593,590,583,574,562,547,529,509,
-488,465,441,417,393,369,345,323,302,282,264,247,231,217,203,191,179,167,156,144,133,
-121,109,96,83,69,56,42,27,13,0,-14,-28,-42,-55,-69,-83,-96,-110,-125,-140,-157,
--174,-193,-213,-234,-258,-282,-309,-337,-366,-397,-428,-460,-493,-526,-559,-592,-624,-656,-687,-717,-746,
--774,-802,-828,-854,-879,-904,-928,-952,-977,-1001,-1026,-1051,-1076,-1102,-1128,-1154,-1181,-1208,-1235,-1261,-1288,
--1314,-1340,-1365,-1390,-1413,-1437,-1459,-1481,-1503,-1524,-1544,-1565,-1585,-1606,-1626,-1647,-1669,-1691,-1713,-1736,-1760,
--1784,-1808,-1832,-1857,-1882,-1907,-1931,-1956,-1980,-2004,-2028,-2052,-2076,-2100,-2123,-2148,-2172,-2197,-2223,-2249,-2277,
--2305,-2334,-2365,-2395,-2427,-2459,-2491,-2524,-2556,-2588,-2620,-2651,-2680,-2709,-2736,-2763,-2788,-2811,-2834,-2855,-2876,
--2896,-2916,-2935,-2954,-2973,-2992,-3012,-3031,-3051,-3071,-3092,-3112,-3132,-3152,-3171,-3190,-3208,-3226,-3242,-3258,-3273,
--3287,-3301,-3314,-3327,-3340,-3354,-3368,-3383,-3399,-3416,-3435,-3455,-3477,-3501,-3526,-3552,-3579,-3607,-3636,-3664,-3693,
--3720,-3747,-3773,-3797,-3820,-3841,-3860,-3877,-3892,-3905,-3916,-3927,-3936,-3944,-3951,-3959,-3966,-3973,-3981,-3989,-3998,
--4008,-4019,-4030,-4043,-4056,-4070,-4085,-4100,-4116,-4132,-4148,-4165,-4182,-4199,-4217,-4235,-4254,-4273,-4293,-4313,-4335,
--4357,-4380,-4404,-4428,-4453,-4479,-4504,-4530,-4555,-4580,-4604,-4626,-4647,-4666,-4683,-4698,-4711,-4721,-4729,-4734,-4737,
--4739,-4739,-4737,-4735,-4732,-4729,-4727,-4725,-4724,-4724,-4726,-4730,-4735,-4742,-4750,-4759,-4769,-4781,-4792,-4804,-4815,
--4826,-4835,-4844,-4852,-4858,-4863,-4866,-4869,-4871,-4872,-4874,-4876,-4878,-4882,-4888,-4895,-4903,-4914,-4927,-4942,-4958,
--4975,-4993,-5011,-5028,-5044,-5058,-5069,-5077,-5081,-5080,-5075,-5065,-5051,-5032,-5008,-4981,-4952,-4920,-4887,-4854,-4821,
--4791,-4763,-4739,-4720,-4705,-4696,-4693,-4695,-4703,-4717,-4735,-4757,-4783,-4811,-4841,-4872,-4902,-4931,-4958,-4983,-5004,
--5022,-5037,-5047,-5053,-5056,-5056,-5053,-5047,-5040,-5031,-5022,-5012,-5003,-4994,-4987,-4981,-4976,-4973,-4971,-4970,-4971,
--4973,-4976,-4979,-4982,-4985,-4988,-4990,-4992,-4993,-4993,-4992,-4991,-4990,-4988,-4985,-4983,-4981,-4980,-4979,-4979,-4979,
--4981,-4983,-4986,-4991,-4995,-5001,-5007,-5013,-5019,-5025,-5031,-5036,-5040,-5044,-5047,-5050,-5051,-5052,-5051,-5051,-5050,
--5048,-5046,-5045,-5043,-5042,-5042,-5042,-5042,-5044,-5046,-5049,-5053,-5057,-5062,-5067,-5073,-5079,-5085,-5091,-5097,-5102,
--5108,-5112,-5117,-5120,-5124,-5126,-5129,-5131,-5133,-5134,-5135,-5136,-5137,-5138,-5139,-5140,-5141,-5141,-5142,-5142,-5142,
--5142,-5141,-5140,-5139,-5137,-5135,-5132,-5129,-5125,-5121,-5117,-5113,-5108,-5103,-5099,-5094,-5090,-5086,-5082,-5079,-5076,
--5073,-5071,-5069,-5068,-5067,-5067,-5067,-5067,-5068,-5069,-5070,-5072,-5074,-5076,-5078,-5081,-5084,-5087,-5090,-5093,-5096,
--5099,-5102,-5105,-5108,-5110,-5113,-5115,-5117,-5118,-5119,-5120,-5120,-5121,-5120,-5120,-5119,-5118,-5117,-5116,-5115,-5113,
--5112,-5110,-5109,-5107,-5106,-5104,-5102,-5101,-5099,-5097,-5095,-5094,-5092,-5091,-5089,-5088,-5086,-5085,-5084,-5083,-5082,
--5081,-5080,-5079,-5078,-5076,-5074,-5071,-5068,-5064,-5059,-5053,-5047,-5039,-5030,-5019,-5008,-4996,-4983,-4969,-4955,-4940,
--4924,-4909,-4893,-4878,-4863,-4848,-4834,-4821,-4808,-4796,-4785,-4774,-4763,-4754,-4744,-4735,-4727,-4718,-4710,-4701,-4693,
--4685,-4677,-4669,-4661,-4653,-4645,-4638,-4631,-4625,-4618,-4612,-4607,-4601,-4596,-4590,-4584,-4578,-4571,-4564,-4555,-4545,
--4534,-4522,-4508,-4492,-4475,-4457,-4437,-4416,-4394,-4371,-4348,-4325,-4302,-4279,-4257,-4236,-4216,-4197,-4180,-4164,-4150,
--4137,-4126,-4116,-4107,-4100,-4093,-4088,-4082,-4078,-4073,-4069,-4065,-4061,-4057,-4052,-4048,-4043,-4039,-4034,-4029,-4024,
--4019,-4014,-4009,-4004,-3999,-3994,-3988,-3983,-3977,-3971,-3965,-3958,-3951,-3943,-3935,-3927,-3918,-3909,-3900,-3891,-3882,
--3873,-3864,-3856,-3848,-3840,-3833,-3827,-3821,-3816,-3812,-3808,-3804,-3801,-3798,-3796,-3794,-3792,-3790,-3788,-3786,-3783,
--3781,-3778,-3775,-3772,-3768,-3764,-3760,-3754,-3748,-3741,-3734,-3725,-3715,-3704,-3691,-3677,-3662,-3645,-3627,-3607,-3586,
--3564,-3541,-3517,-3492,-3467,-3442,-3417,-3393,-3369,-3346,-3325,-3304,-3285,-3268,-3251,-3236,-3222,-3210,-3197,-3185,-3173,
--3161,-3148,-3135,-3120,-3104,-3086,-3067,-3046,-3023,-2999,-2974,-2947,-2920,-2892,-2864,-2837,-2811,-2785,-2761,-2739,-2719,
--2701,-2685,-2671,-2660,-2650,-2643,-2636,-2631,-2627,-2623,-2619,-2615,-2611,-2606,-2600,-2594,-2587,-2579,-2571,-2562,-2554,
--2546,-2538,-2532,-2526,-2523,-2521,-2522,-2524,-2529,-2537,-2546,-2557,-2570,-2584,-2599,-2615,-2631,-2647,-2662,-2677,-2690,
--2702,-2712,-2720,-2726,-2730,-2733,-2733,-2732,-2729,-2725,-2720,-2714,-2707,-2700,-2692,-2684,-2677,-2669,-2661,-2654,-2647,
--2641,-2635,-2630,-2625,-2621,-2618,-2615,-2612,-2611,-2610,-2610,-2610,-2612,-2613,-2615,-2618,-2620,-2623,-2625,-2628,-2629,
--2630,-2630,-2629,-2627,-2624,-2619,-2613,-2606,-2598,-2588,-2578,-2567,-2555,-2543,-2531,-2520,-2508,-2498,-2487,-2478,-2469,
--2461,-2454,-2447,-2441,-2435,-2429,-2423,-2416,-2409,-2401,-2392,-2382,-2370,-2358,-2345,-2331,-2317,-2302,-2287,-2273,-2259,
--2246,-2234,-2223,-2215,-2208,-2202,-2199,-2198,-2199,-2202,-2206,-2211,-2217,-2225,-2232,-2240,-2248,-2256,-2264,-2271,-2278,
--2284,-2290,-2295,-2300,-2305,-2310,-2315,-2320,-2325,-2331,-2337,-2344,-2351,-2358,-2365,-2373,-2380,-2388,-2394,-2401,-2406,
--2411,-2415,-2418,-2420,-2421,-2421,-2421,-2420,-2419,-2417,-2416,-2415,-2413,-2413,-2412,-2412,-2411,-2411,-2411,-2411,-2411,
--2409,-2407,-2404,-2400,-2394,-2387,-2378,-2368,-2356,-2343,-2329,-2313,-2297,-2280,-2262,-2245,-2227,-2210,-2193,-2177,-2162,
--2148,-2135,-2122,-2110,-2100,-2089,-2079,-2070,-2061,-2052,-2043,-2033,-2024,-2015,-2005,-1996,-1986,-1977,-1967,-1958,-1950,
--1942,-1934,-1928,-1921,-1916,-1912,-1908,-1905,-1903,-1901,-1900,-1899,-1899,-1899,-1899,-1900,-1900,-1900,-1901,-1901,-1901,
--1901,-1901,-1900,-1899,-1897,-1894,-1891,-1887,-1881,-1874,-1866,-1856,-1844,-1831,-1816,-1799,-1781,-1761,-1740,-1718,-1695,
--1672,-1648,-1625,-1603,-1581,-1561,-1543,-1527,-1513,-1501,-1491,-1483,-1478,-1475,-1473,-1472,-1473,-1474,-1476,-1477,-1479,
--1479,-1478,-1476,-1473,-1468,-1461,-1453,-1444,-1434,-1422,-1410,-1398,-1385,-1372,-1360,-1348,-1337,-1327,-1317,-1309,-1302,
--1295,-1289,-1284,-1279,-1274,-1270,-1265,-1260,-1255,-1249,-1243,-1236,-1228,-1220,-1212,-1204,-1195,-1187,-1179,-1171,-1164,
--1157,-1152,-1147,-1143,-1140,-1138,-1137,-1136,-1135,-1135,-1135,-1135,-1134,-1134,-1133,-1131,-1128,-1125,-1122,-1117,-1113,
--1107,-1101,-1095,-1089,-1083,-1077,-1071,-1065,-1059,-1053,-1048,-1043,-1037,-1032,-1026,-1020,-1014,-1007,-999,-992,-983,
--974,-965,-956,-946,-936,-926,-916,-907,-898,-890,-882,-876,-870,-865,-860,-856,-853,-930,-925,-920,-916,
--911,-906,-901,-896,-890,-884,-877,-869,-861,-852,-843,-833,-823,-812,-801,-790,-780,-769,-759,-749,-740,
--731,-723,-715,-708,-702,-696,-691,-686,-682,-679,-675,-672,-669,-666,-662,-659,-656,-652,-649,-644,-640,
--635,-630,-624,-618,-612,-605,-597,-589,-580,-570,-559,-548,-536,-524,-511,-497,-482,-467,-451,-436,-419,
--403,-386,-370,-353,-337,-321,-306,-291,-276,-262,-249,-236,-223,-211,-199,-187,-176,-165,-154,-143,-131,
--120,-108,-96,-83,-70,-57,-43,-28,-14,1,16,32,48,65,81,98,114,131,147,162,177,
-191,205,218,229,240,249,257,263,268,272,273,274,272,269,265,260,253,246,237,228,219,
-210,200,191,182,174,166,160,154,149,145,142,140,139,139,139,141,142,145,148,151,154,
-158,161,165,169,173,178,182,186,190,194,198,202,205,209,212,215,217,219,221,222,222,
-222,222,221,220,219,217,216,215,214,214,214,215,217,219,222,225,229,234,239,244,249,
-254,259,263,267,271,274,276,278,280,281,283,284,286,289,292,297,303,311,320,331,343,
-357,372,389,406,424,442,460,478,494,509,523,535,545,553,559,563,564,564,562,558,553,
-548,541,534,527,520,514,507,501,495,490,485,480,475,471,466,460,454,448,441,433,426,
-417,409,400,391,383,375,368,362,357,353,350,349,348,349,351,354,358,363,368,374,380,
-386,392,398,403,409,415,421,427,433,439,446,453,460,469,477,486,494,503,512,520,527,
-533,538,541,542,541,538,533,525,515,502,488,471,453,433,412,391,369,346,324,302,281,
-260,240,221,203,186,169,153,138,123,109,94,80,66,52,38,24,11,-2,-15,-28,-41,
--53,-65,-76,-87,-98,-109,-120,-130,-141,-153,-166,-180,-194,-211,-229,-249,-271,-295,-320,-348,-377,
--408,-440,-473,-507,-541,-575,-609,-643,-676,-707,-738,-768,-796,-823,-849,-873,-897,-920,-942,-964,-986,
--1008,-1030,-1052,-1075,-1099,-1123,-1147,-1172,-1198,-1224,-1251,-1277,-1304,-1330,-1356,-1382,-1407,-1431,-1455,-1477,-1500,
--1521,-1542,-1563,-1583,-1602,-1622,-1642,-1662,-1682,-1702,-1722,-1743,-1765,-1786,-1808,-1831,-1853,-1876,-1898,-1921,-1943,
--1965,-1988,-2010,-2032,-2054,-2076,-2099,-2121,-2144,-2168,-2192,-2217,-2243,-2270,-2297,-2326,-2355,-2385,-2415,-2445,-2476,
--2507,-2538,-2568,-2598,-2627,-2655,-2682,-2708,-2733,-2756,-2779,-2801,-2822,-2843,-2863,-2883,-2902,-2921,-2941,-2960,-2980,
--2999,-3019,-3040,-3060,-3080,-3101,-3121,-3141,-3160,-3179,-3197,-3215,-3232,-3249,-3265,-3280,-3296,-3311,-3327,-3343,-3359,
--3376,-3394,-3413,-3434,-3455,-3477,-3501,-3526,-3552,-3579,-3606,-3634,-3662,-3690,-3717,-3744,-3770,-3795,-3819,-3841,-3861,
--3880,-3898,-3914,-3928,-3941,-3953,-3963,-3973,-3981,-3990,-3997,-4005,-4012,-4020,-4027,-4035,-4044,-4053,-4062,-4072,-4083,
--4095,-4107,-4120,-4134,-4150,-4166,-4183,-4201,-4221,-4241,-4262,-4285,-4308,-4333,-4357,-4383,-4409,-4434,-4460,-4485,-4510,
--4533,-4555,-4576,-4595,-4612,-4627,-4640,-4650,-4658,-4665,-4669,-4672,-4673,-4673,-4672,-4671,-4669,-4668,-4667,-4667,-4668,
--4670,-4674,-4679,-4685,-4692,-4700,-4708,-4718,-4727,-4736,-4744,-4752,-4759,-4764,-4768,-4770,-4771,-4771,-4770,-4768,-4765,
--4763,-4760,-4759,-4759,-4760,-4764,-4770,-4778,-4789,-4802,-4817,-4834,-4853,-4872,-4892,-4911,-4929,-4945,-4957,-4967,-4972,
--4972,-4967,-4957,-4941,-4921,-4895,-4865,-4831,-4795,-4757,-4717,-4679,-4641,-4607,-4575,-4549,-4528,-4512,-4504,-4501,-4506,
--4517,-4535,-4558,-4586,-4618,-4654,-4691,-4730,-4769,-4807,-4843,-4876,-4906,-4933,-4955,-4973,-4986,-4996,-5001,-5003,-5001,
--4997,-4992,-4984,-4976,-4968,-4960,-4953,-4947,-4942,-4939,-4938,-4937,-4938,-4941,-4944,-4948,-4953,-4957,-4962,-4966,-4970,
--4972,-4975,-4976,-4976,-4976,-4975,-4973,-4971,-4969,-4967,-4964,-4963,-4961,-4960,-4960,-4961,-4961,-4963,-4965,-4967,-4970,
--4973,-4975,-4978,-4980,-4982,-4983,-4984,-4985,-4985,-4984,-4984,-4983,-4983,-4982,-4982,-4982,-4983,-4984,-4986,-4989,-4992,
--4996,-5001,-5007,-5013,-5020,-5026,-5033,-5039,-5045,-5051,-5056,-5061,-5064,-5067,-5070,-5071,-5072,-5072,-5072,-5072,-5071,
--5070,-5070,-5070,-5070,-5070,-5072,-5073,-5076,-5078,-5082,-5085,-5089,-5093,-5097,-5101,-5105,-5108,-5111,-5113,-5114,-5115,
--5115,-5114,-5112,-5110,-5107,-5103,-5100,-5095,-5091,-5087,-5083,-5078,-5074,-5071,-5067,-5064,-5061,-5059,-5057,-5055,-5054,
--5053,-5051,-5050,-5050,-5049,-5048,-5047,-5046,-5045,-5043,-5042,-5041,-5039,-5038,-5037,-5036,-5034,-5033,-5032,-5032,-5031,
--5031,-5031,-5031,-5032,-5033,-5034,-5035,-5036,-5038,-5039,-5040,-5042,-5043,-5044,-5045,-5045,-5046,-5045,-5045,-5043,-5042,
--5040,-5037,-5034,-5030,-5026,-5022,-5017,-5012,-5007,-5001,-4996,-4990,-4984,-4978,-4972,-4966,-4960,-4954,-4948,-4942,-4936,
--4929,-4923,-4916,-4910,-4903,-4895,-4888,-4880,-4872,-4864,-4856,-4847,-4839,-4830,-4821,-4813,-4804,-4796,-4787,-4779,-4770,
--4762,-4754,-4746,-4738,-4730,-4722,-4713,-4705,-4697,-4689,-4680,-4672,-4664,-4656,-4648,-4640,-4632,-4625,-4617,-4611,-4604,
--4598,-4592,-4587,-4581,-4576,-4570,-4565,-4559,-4552,-4545,-4537,-4528,-4518,-4507,-4494,-4480,-4465,-4449,-4432,-4413,-4394,
--4374,-4353,-4333,-4312,-4291,-4271,-4252,-4233,-4216,-4199,-4184,-4171,-4158,-4147,-4138,-4129,-4122,-4115,-4110,-4105,-4101,
--4098,-4094,-4091,-4088,-4086,-4083,-4080,-4077,-4074,-4070,-4067,-4064,-4060,-4056,-4052,-4048,-4044,-4039,-4035,-4029,-4024,
--4018,-4012,-4005,-3998,-3990,-3982,-3973,-3963,-3953,-3943,-3932,-3920,-3909,-3897,-3885,-3872,-3860,-3848,-3836,-3824,-3812,
--3801,-3790,-3778,-3768,-3757,-3747,-3737,-3728,-3718,-3709,-3701,-3692,-3684,-3676,-3668,-3661,-3654,-3647,-3640,-3633,-3626,
--3618,-3611,-3603,-3594,-3585,-3575,-3565,-3553,-3540,-3526,-3511,-3495,-3478,-3460,-3441,-3422,-3403,-3383,-3363,-3343,-3324,
--3306,-3288,-3272,-3256,-3242,-3229,-3217,-3206,-3196,-3186,-3178,-3169,-3160,-3151,-3142,-3131,-3120,-3107,-3093,-3078,-3062,
--3044,-3024,-3004,-2983,-2962,-2940,-2918,-2897,-2877,-2857,-2839,-2822,-2807,-2793,-2782,-2772,-2763,-2756,-2750,-2745,-2740,
--2736,-2732,-2728,-2723,-2718,-2712,-2705,-2697,-2688,-2678,-2667,-2656,-2645,-2633,-2622,-2611,-2602,-2593,-2585,-2580,-2575,
--2573,-2572,-2573,-2575,-2580,-2585,-2591,-2599,-2607,-2615,-2624,-2632,-2641,-2649,-2656,-2662,-2668,-2673,-2678,-2681,-2684,
--2687,-2689,-2690,-2691,-2692,-2692,-2693,-2693,-2693,-2693,-2693,-2693,-2693,-2693,-2693,-2693,-2693,-2694,-2694,-2694,-2695,
--2696,-2697,-2698,-2700,-2702,-2704,-2706,-2708,-2710,-2712,-2713,-2714,-2714,-2713,-2711,-2708,-2703,-2698,-2691,-2683,-2673,
--2662,-2651,-2638,-2626,-2612,-2599,-2586,-2573,-2561,-2550,-2540,-2531,-2523,-2516,-2510,-2505,-2501,-2497,-2493,-2489,-2485,
--2481,-2475,-2469,-2462,-2453,-2443,-2432,-2420,-2407,-2393,-2379,-2364,-2350,-2336,-2322,-2310,-2299,-2289,-2281,-2275,-2270,
--2268,-2267,-2267,-2270,-2273,-2278,-2283,-2290,-2296,-2303,-2311,-2318,-2325,-2332,-2339,-2346,-2352,-2359,-2365,-2371,-2378,
--2385,-2392,-2399,-2407,-2415,-2422,-2430,-2438,-2446,-2454,-2461,-2468,-2474,-2480,-2485,-2489,-2492,-2495,-2496,-2498,-2498,
--2498,-2498,-2497,-2497,-2496,-2494,-2493,-2492,-2490,-2488,-2486,-2484,-2481,-2477,-2472,-2466,-2460,-2452,-2443,-2433,-2423,
--2411,-2398,-2385,-2371,-2357,-2343,-2329,-2315,-2302,-2289,-2277,-2265,-2254,-2244,-2234,-2225,-2216,-2207,-2199,-2190,-2181,
--2171,-2161,-2150,-2138,-2126,-2113,-2100,-2087,-2073,-2059,-2045,-2032,-2020,-2009,-1998,-1990,-1982,-1976,-1971,-1968,-1966,
--1966,-1966,-1968,-1969,-1972,-1974,-1976,-1977,-1978,-1978,-1977,-1974,-1970,-1965,-1958,-1949,-1939,-1927,-1914,-1900,-1885,
--1868,-1851,-1833,-1814,-1795,-1776,-1757,-1738,-1720,-1701,-1684,-1667,-1651,-1636,-1623,-1610,-1599,-1589,-1581,-1574,-1569,
--1564,-1561,-1559,-1558,-1557,-1557,-1557,-1557,-1557,-1557,-1555,-1553,-1549,-1545,-1539,-1531,-1523,-1513,-1502,-1491,-1478,
--1465,-1451,-1438,-1425,-1412,-1399,-1388,-1377,-1367,-1359,-1352,-1345,-1340,-1335,-1331,-1328,-1325,-1322,-1319,-1316,-1313,
--1309,-1304,-1299,-1293,-1286,-1279,-1271,-1263,-1255,-1246,-1238,-1230,-1223,-1216,-1209,-1204,-1199,-1195,-1192,-1189,-1187,
--1186,-1185,-1183,-1182,-1181,-1179,-1177,-1175,-1171,-1167,-1163,-1157,-1151,-1145,-1138,-1131,-1124,-1116,-1109,-1102,-1095,
--1089,-1083,-1077,-1072,-1067,-1063,-1059,-1054,-1050,-1046,-1042,-1038,-1033,-1028,-1023,-1017,-1011,-1004,-998,-991,-984,
--977,-970,-964,-957,-951,-945,-940,-935,-930,-991,-986,-980,-974,-968,-962,-956,-949,-942,-935,-928,-920,
--911,-903,-894,-884,-875,-865,-855,-845,-835,-825,-816,-807,-798,-790,-783,-776,-770,-765,-761,-758,-755,
--753,-752,-752,-752,-752,-753,-754,-755,-756,-757,-758,-758,-757,-755,-753,-750,-746,-741,-734,-727,-718,
--708,-696,-684,-670,-655,-639,-622,-604,-586,-567,-547,-527,-507,-486,-466,-446,-426,-407,-388,-370,-353,
--336,-321,-306,-292,-278,-266,-254,-242,-232,-221,-211,-202,-192,-183,-173,-163,-153,-142,-131,-119,-107,
--95,-81,-67,-52,-37,-21,-5,11,28,45,62,79,96,112,128,143,157,170,182,192,201,
-209,215,220,223,225,225,224,221,218,213,208,202,195,188,181,174,167,160,153,147,141,
-136,131,127,123,119,116,113,111,109,107,106,105,104,103,103,103,103,104,106,107,109,
-112,115,118,122,125,129,132,136,139,142,144,146,147,148,148,147,145,143,141,138,135,
-132,129,126,123,121,120,119,119,120,122,124,127,130,135,139,144,149,154,158,163,168,
-172,176,180,184,187,191,195,199,203,208,214,220,227,234,242,250,259,269,278,288,297,
-306,315,323,331,337,343,348,351,354,356,357,357,357,356,355,353,352,350,349,347,346,
-345,343,343,342,341,340,339,337,336,334,332,329,326,323,320,317,313,310,307,304,302,
-300,299,298,298,299,301,303,305,309,313,317,322,328,333,339,345,352,359,366,373,381,
-388,396,405,413,422,431,439,448,456,464,471,477,482,486,489,490,489,486,482,475,467,
-456,444,430,414,397,379,360,340,319,298,277,255,234,213,192,171,151,131,111,92,73,
-55,37,19,2,-14,-30,-46,-61,-75,-89,-101,-113,-124,-134,-144,-152,-160,-168,-176,-183,-191,
--199,-208,-219,-230,-243,-259,-276,-295,-316,-340,-366,-394,-423,-454,-487,-520,-555,-589,-624,-658,-692,
--725,-756,-787,-816,-844,-870,-894,-918,-940,-962,-982,-1003,-1023,-1043,-1063,-1083,-1105,-1126,-1149,-1172,-1196,
--1221,-1246,-1272,-1298,-1324,-1350,-1377,-1403,-1428,-1453,-1477,-1501,-1523,-1546,-1567,-1587,-1607,-1627,-1646,-1665,-1684,
--1702,-1721,-1739,-1758,-1776,-1795,-1814,-1833,-1853,-1872,-1892,-1911,-1931,-1950,-1970,-1990,-2010,-2030,-2050,-2071,-2092,
--2114,-2137,-2160,-2184,-2209,-2234,-2261,-2289,-2317,-2346,-2375,-2405,-2435,-2466,-2496,-2526,-2555,-2584,-2612,-2639,-2666,
--2691,-2716,-2739,-2761,-2783,-2804,-2824,-2844,-2864,-2883,-2902,-2921,-2941,-2960,-2980,-3000,-3021,-3041,-3062,-3082,-3103,
--3124,-3144,-3164,-3184,-3203,-3222,-3240,-3258,-3275,-3292,-3309,-3326,-3343,-3360,-3377,-3395,-3413,-3432,-3452,-3473,-3495,
--3518,-3542,-3566,-3592,-3618,-3645,-3672,-3699,-3727,-3754,-3781,-3807,-3832,-3857,-3880,-3902,-3923,-3942,-3960,-3977,-3991,
--4005,-4017,-4027,-4037,-4045,-4053,-4059,-4065,-4071,-4077,-4083,-4088,-4095,-4102,-4110,-4119,-4129,-4141,-4154,-4169,-4186,
--4204,-4223,-4244,-4267,-4290,-4315,-4341,-4366,-4393,-4418,-4444,-4469,-4492,-4514,-4535,-4554,-4571,-4586,-4598,-4609,-4617,
--4624,-4628,-4631,-4633,-4634,-4634,-4634,-4634,-4634,-4634,-4635,-4637,-4640,-4644,-4648,-4653,-4659,-4665,-4672,-4678,-4683,
--4689,-4693,-4696,-4697,-4697,-4696,-4693,-4689,-4683,-4677,-4670,-4663,-4657,-4651,-4646,-4643,-4642,-4643,-4646,-4653,-4662,
--4674,-4688,-4704,-4721,-4739,-4758,-4776,-4793,-4807,-4819,-4827,-4830,-4829,-4823,-4811,-4794,-4771,-4743,-4710,-4674,-4634,
--4592,-4550,-4507,-4465,-4426,-4391,-4359,-4334,-4314,-4301,-4296,-4298,-4307,-4323,-4346,-4375,-4409,-4448,-4490,-4535,-4581,
--4627,-4672,-4715,-4756,-4793,-4827,-4856,-4880,-4900,-4915,-4926,-4933,-4936,-4936,-4934,-4930,-4925,-4919,-4912,-4907,-4902,
--4898,-4895,-4894,-4894,-4896,-4900,-4904,-4909,-4916,-4922,-4929,-4935,-4942,-4947,-4952,-4957,-4960,-4962,-4964,-4964,-4964,
--4963,-4961,-4959,-4957,-4954,-4952,-4949,-4947,-4944,-4942,-4940,-4938,-4935,-4933,-4931,-4929,-4927,-4925,-4922,-4920,-4918,
--4916,-4914,-4912,-4911,-4910,-4910,-4911,-4912,-4915,-4918,-4922,-4928,-4934,-4941,-4948,-4956,-4964,-4972,-4980,-4988,-4996,
--5002,-5008,-5013,-5017,-5020,-5022,-5023,-5023,-5023,-5021,-5020,-5018,-5016,-5014,-5013,-5012,-5011,-5012,-5013,-5015,-5018,
--5022,-5027,-5032,-5038,-5044,-5051,-5057,-5063,-5069,-5074,-5079,-5083,-5086,-5088,-5089,-5089,-5089,-5088,-5086,-5083,-5080,
--5077,-5073,-5069,-5066,-5062,-5059,-5056,-5053,-5051,-5048,-5046,-5045,-5043,-5041,-5039,-5037,-5035,-5033,-5030,-5027,-5024,
--5020,-5016,-5012,-5008,-5003,-4998,-4993,-4988,-4983,-4979,-4975,-4972,-4969,-4966,-4964,-4963,-4962,-4962,-4963,-4964,-4965,
--4967,-4969,-4971,-4974,-4976,-4978,-4979,-4980,-4981,-4981,-4980,-4978,-4976,-4973,-4968,-4964,-4958,-4951,-4944,-4936,-4928,
--4919,-4910,-4900,-4891,-4881,-4871,-4862,-4852,-4843,-4834,-4825,-4817,-4809,-4801,-4794,-4787,-4781,-4775,-4769,-4764,-4759,
--4755,-4751,-4747,-4743,-4739,-4736,-4732,-4729,-4725,-4722,-4718,-4715,-4711,-4707,-4702,-4698,-4693,-4687,-4682,-4676,-4669,
--4662,-4655,-4648,-4641,-4633,-4625,-4617,-4609,-4601,-4593,-4586,-4578,-4571,-4563,-4556,-4548,-4541,-4534,-4526,-4518,-4510,
--4501,-4492,-4483,-4472,-4461,-4449,-4436,-4423,-4409,-4394,-4379,-4363,-4347,-4330,-4314,-4297,-4281,-4266,-4251,-4236,-4223,
--4210,-4198,-4187,-4177,-4169,-4161,-4154,-4148,-4142,-4137,-4133,-4130,-4126,-4124,-4121,-4118,-4116,-4113,-4110,-4108,-4105,
--4102,-4099,-4095,-4092,-4088,-4084,-4080,-4076,-4071,-4065,-4060,-4054,-4047,-4040,-4032,-4024,-4015,-4005,-3994,-3983,-3971,
--3959,-3946,-3932,-3918,-3903,-3888,-3873,-3857,-3841,-3825,-3809,-3793,-3777,-3761,-3746,-3730,-3715,-3699,-3684,-3670,-3655,
--3641,-3627,-3613,-3600,-3587,-3575,-3563,-3551,-3540,-3529,-3518,-3508,-3499,-3489,-3480,-3471,-3461,-3452,-3443,-3433,-3423,
--3413,-3402,-3391,-3379,-3367,-3355,-3342,-3329,-3316,-3302,-3289,-3276,-3263,-3251,-3239,-3228,-3217,-3207,-3198,-3189,-3181,
--3173,-3166,-3159,-3152,-3145,-3138,-3130,-3122,-3113,-3104,-3093,-3082,-3070,-3058,-3044,-3031,-3016,-3002,-2988,-2974,-2960,
--2947,-2935,-2923,-2912,-2903,-2894,-2887,-2880,-2874,-2869,-2864,-2860,-2855,-2851,-2846,-2840,-2834,-2827,-2819,-2810,-2800,
--2790,-2778,-2765,-2752,-2739,-2725,-2712,-2698,-2685,-2673,-2662,-2651,-2642,-2634,-2627,-2622,-2618,-2616,-2614,-2614,-2615,
--2617,-2620,-2623,-2627,-2632,-2637,-2642,-2647,-2653,-2658,-2664,-2670,-2676,-2682,-2688,-2693,-2699,-2705,-2710,-2715,-2720,
--2725,-2730,-2734,-2738,-2741,-2744,-2747,-2749,-2751,-2753,-2755,-2757,-2758,-2760,-2761,-2763,-2765,-2767,-2769,-2771,-2773,
--2775,-2776,-2778,-2778,-2778,-2777,-2775,-2771,-2767,-2761,-2754,-2745,-2736,-2725,-2713,-2700,-2686,-2672,-2658,-2644,-2631,
--2617,-2605,-2594,-2583,-2574,-2566,-2559,-2553,-2548,-2544,-2540,-2537,-2534,-2531,-2527,-2523,-2519,-2513,-2506,-2499,-2490,
--2480,-2470,-2458,-2446,-2434,-2422,-2410,-2398,-2387,-2376,-2367,-2359,-2353,-2347,-2344,-2341,-2341,-2341,-2343,-2347,-2351,
--2356,-2363,-2369,-2377,-2384,-2392,-2400,-2408,-2417,-2425,-2433,-2441,-2449,-2456,-2464,-2471,-2478,-2485,-2492,-2499,-2505,
--2511,-2516,-2522,-2527,-2531,-2535,-2539,-2543,-2546,-2549,-2551,-2553,-2555,-2557,-2558,-2559,-2560,-2560,-2561,-2560,-2560,
--2558,-2556,-2554,-2550,-2546,-2540,-2534,-2526,-2518,-2508,-2498,-2487,-2475,-2463,-2450,-2438,-2425,-2413,-2401,-2390,-2379,
--2369,-2360,-2352,-2344,-2337,-2331,-2324,-2318,-2312,-2305,-2297,-2289,-2280,-2270,-2258,-2245,-2231,-2216,-2199,-2182,-2165,
--2147,-2129,-2112,-2095,-2080,-2065,-2053,-2042,-2034,-2028,-2023,-2021,-2021,-2023,-2026,-2030,-2035,-2040,-2045,-2049,-2052,
--2054,-2054,-2052,-2048,-2040,-2031,-2018,-2003,-1985,-1965,-1943,-1920,-1894,-1868,-1841,-1814,-1787,-1761,-1736,-1712,-1690,
--1669,-1651,-1635,-1622,-1611,-1602,-1595,-1591,-1588,-1588,-1589,-1591,-1594,-1597,-1601,-1605,-1609,-1611,-1613,-1614,-1614,
--1612,-1608,-1603,-1596,-1587,-1576,-1564,-1551,-1536,-1521,-1504,-1488,-1471,-1454,-1438,-1422,-1407,-1393,-1381,-1370,-1360,
--1351,-1344,-1339,-1334,-1331,-1328,-1327,-1325,-1324,-1323,-1322,-1320,-1318,-1316,-1312,-1308,-1303,-1298,-1291,-1284,-1277,
--1270,-1262,-1254,-1246,-1239,-1232,-1226,-1221,-1216,-1211,-1208,-1204,-1202,-1200,-1198,-1196,-1194,-1191,-1189,-1186,-1182,
--1178,-1173,-1168,-1161,-1155,-1147,-1140,-1132,-1124,-1116,-1108,-1100,-1093,-1086,-1080,-1075,-1071,-1067,-1064,-1061,-1059,
--1057,-1056,-1055,-1055,-1054,-1053,-1052,-1050,-1048,-1046,-1043,-1040,-1037,-1033,-1028,-1024,-1019,-1013,-1008,-1003,-997,
--991,-1019,-1014,-1008,-1003,-997,-991,-985,-979,-973,-966,-959,-952,-944,-937,-929,-921,-913,-904,-896,-888,
--879,-871,-863,-856,-849,-842,-836,-831,-827,-823,-820,-818,-817,-817,-817,-818,-820,-822,-825,-828,-831,
--834,-836,-839,-840,-841,-841,-840,-838,-835,-830,-824,-817,-808,-797,-786,-772,-758,-742,-725,-706,-687,
--667,-647,-626,-605,-583,-562,-540,-519,-498,-478,-459,-440,-422,-405,-389,-374,-359,-346,-333,-321,-310,
--299,-289,-279,-270,-260,-251,-241,-232,-222,-211,-200,-188,-176,-163,-149,-134,-119,-103,-86,-69,-51,
--33,-15,2,20,38,55,71,87,102,115,128,139,149,157,164,169,173,175,177,177,175,
-173,170,166,162,157,152,146,141,135,129,123,118,112,107,101,96,91,85,80,75,70,
-65,60,55,51,47,43,40,37,35,33,32,32,33,35,37,40,44,48,52,57,62,
-67,71,75,79,82,84,85,86,85,84,82,79,75,71,67,63,59,55,51,48,45,
-44,43,43,44,45,48,51,55,60,65,70,76,81,86,92,97,101,106,110,114,117,
-121,124,127,131,134,137,141,145,149,154,159,164,169,175,181,186,192,197,203,208,213,
-217,222,225,229,232,234,236,238,240,241,242,243,243,243,244,244,243,243,243,242,241,
-241,240,239,238,236,235,234,233,232,231,230,229,229,229,229,229,230,232,234,236,239,
-242,245,250,254,259,265,271,277,284,292,299,308,316,325,334,343,352,361,370,379,387,
-394,401,407,412,416,418,419,418,416,412,407,399,391,380,368,355,340,324,307,289,270,
-250,230,210,189,168,147,125,104,83,62,40,20,0,-20,-40,-60,-78,-97,-114,-130,-146,
--161,-174,-187,-198,-209,-218,-226,-234,-241,-248,-254,-261,-267,-275,-283,-293,-304,-317,-331,-348,-366,
--387,-410,-435,-462,-490,-521,-552,-584,-617,-651,-684,-717,-750,-782,-812,-842,-870,-897,-922,-947,-969,
--991,-1012,-1033,-1052,-1072,-1091,-1111,-1130,-1150,-1171,-1193,-1215,-1237,-1261,-1285,-1309,-1334,-1359,-1385,-1410,-1435,
--1460,-1484,-1508,-1531,-1554,-1575,-1596,-1617,-1636,-1655,-1674,-1692,-1710,-1727,-1744,-1761,-1778,-1795,-1812,-1829,-1846,
--1863,-1880,-1898,-1915,-1933,-1951,-1969,-1987,-2006,-2025,-2045,-2064,-2085,-2106,-2128,-2151,-2174,-2198,-2223,-2249,-2276,
--2303,-2332,-2360,-2389,-2419,-2448,-2477,-2507,-2536,-2564,-2592,-2619,-2645,-2670,-2695,-2718,-2741,-2762,-2784,-2804,-2824,
--2844,-2863,-2882,-2902,-2921,-2941,-2961,-2981,-3001,-3022,-3043,-3064,-3085,-3106,-3127,-3147,-3168,-3188,-3207,-3226,-3244,
--3261,-3278,-3294,-3310,-3325,-3341,-3356,-3371,-3386,-3402,-3419,-3436,-3454,-3474,-3494,-3516,-3539,-3564,-3590,-3617,-3644,
--3673,-3703,-3733,-3763,-3793,-3822,-3851,-3879,-3906,-3932,-3955,-3977,-3997,-4015,-4031,-4045,-4056,-4066,-4073,-4079,-4084,
--4087,-4090,-4092,-4094,-4096,-4099,-4102,-4107,-4113,-4121,-4131,-4143,-4157,-4173,-4191,-4211,-4233,-4256,-4281,-4307,-4333,
--4359,-4386,-4412,-4437,-4461,-4483,-4504,-4522,-4539,-4553,-4565,-4575,-4583,-4589,-4593,-4596,-4597,-4598,-4598,-4597,-4597,
--4597,-4597,-4598,-4599,-4601,-4603,-4606,-4610,-4613,-4617,-4620,-4623,-4625,-4627,-4627,-4626,-4623,-4619,-4614,-4608,-4601,
--4593,-4585,-4576,-4568,-4561,-4554,-4550,-4547,-4546,-4547,-4551,-4558,-4566,-4577,-4589,-4603,-4618,-4632,-4647,-4660,-4671,
--4679,-4684,-4686,-4683,-4675,-4662,-4644,-4621,-4593,-4561,-4526,-4487,-4446,-4403,-4361,-4319,-4280,-4243,-4210,-4182,-4160,
--4144,-4135,-4132,-4137,-4150,-4168,-4194,-4225,-4261,-4301,-4344,-4390,-4437,-4484,-4530,-4575,-4618,-4657,-4693,-4724,-4752,
--4775,-4794,-4809,-4819,-4827,-4831,-4833,-4832,-4831,-4828,-4825,-4822,-4820,-4818,-4818,-4818,-4820,-4823,-4828,-4833,-4840,
--4847,-4855,-4864,-4872,-4880,-4888,-4895,-4901,-4906,-4911,-4915,-4917,-4919,-4919,-4919,-4918,-4917,-4915,-4912,-4909,-4906,
--4902,-4898,-4894,-4890,-4885,-4881,-4876,-4871,-4867,-4862,-4858,-4853,-4849,-4845,-4842,-4839,-4837,-4835,-4835,-4835,-4836,
--4839,-4842,-4847,-4852,-4858,-4865,-4873,-4881,-4890,-4899,-4907,-4916,-4924,-4932,-4939,-4945,-4950,-4955,-4958,-4961,-4963,
--4964,-4965,-4966,-4966,-4965,-4965,-4966,-4966,-4967,-4969,-4971,-4974,-4977,-4981,-4985,-4990,-4996,-5001,-5007,-5012,-5018,
--5023,-5027,-5031,-5034,-5036,-5038,-5039,-5039,-5038,-5037,-5036,-5033,-5031,-5028,-5026,-5023,-5021,-5018,-5016,-5014,-5013,
--5012,-5011,-5010,-5009,-5008,-5007,-5007,-5005,-5004,-5002,-5000,-4997,-4994,-4990,-4985,-4981,-4976,-4970,-4964,-4958,-4953,
--4947,-4941,-4936,-4931,-4927,-4923,-4919,-4917,-4915,-4913,-4912,-4912,-4911,-4912,-4912,-4913,-4913,-4913,-4913,-4913,-4912,
--4911,-4909,-4906,-4902,-4898,-4893,-4887,-4880,-4873,-4865,-4856,-4847,-4837,-4827,-4817,-4807,-4797,-4787,-4776,-4767,-4757,
--4748,-4739,-4730,-4722,-4715,-4708,-4701,-4695,-4690,-4684,-4680,-4675,-4671,-4668,-4665,-4662,-4659,-4656,-4654,-4651,-4649,
--4647,-4645,-4643,-4640,-4638,-4635,-4633,-4630,-4627,-4623,-4620,-4616,-4612,-4608,-4603,-4598,-4593,-4587,-4582,-4576,-4569,
--4563,-4556,-4549,-4541,-4534,-4526,-4517,-4508,-4499,-4490,-4480,-4470,-4459,-4448,-4436,-4424,-4412,-4399,-4386,-4372,-4359,
--4345,-4332,-4318,-4305,-4291,-4279,-4266,-4254,-4243,-4232,-4223,-4213,-4205,-4197,-4190,-4183,-4177,-4172,-4167,-4163,-4159,
--4155,-4151,-4147,-4144,-4140,-4136,-4132,-4128,-4124,-4120,-4115,-4110,-4105,-4100,-4094,-4089,-4083,-4077,-4070,-4063,-4056,
--4049,-4041,-4033,-4024,-4015,-4006,-3995,-3985,-3973,-3961,-3949,-3936,-3922,-3908,-3893,-3878,-3863,-3847,-3831,-3815,-3799,
--3783,-3767,-3751,-3735,-3719,-3703,-3687,-3672,-3657,-3641,-3626,-3611,-3597,-3582,-3568,-3553,-3539,-3525,-3511,-3497,-3484,
--3471,-3458,-3445,-3433,-3421,-3410,-3399,-3389,-3378,-3369,-3359,-3350,-3341,-3332,-3324,-3315,-3307,-3299,-3291,-3282,-3274,
--3266,-3258,-3250,-3242,-3234,-3226,-3218,-3210,-3203,-3195,-3188,-3180,-3173,-3166,-3159,-3152,-3145,-3138,-3130,-3123,-3115,
--3107,-3099,-3091,-3082,-3074,-3065,-3056,-3047,-3038,-3029,-3021,-3012,-3004,-2997,-2990,-2983,-2976,-2970,-2965,-2959,-2954,
--2949,-2944,-2939,-2933,-2928,-2922,-2915,-2908,-2900,-2891,-2882,-2872,-2861,-2849,-2837,-2825,-2812,-2799,-2786,-2773,-2761,
--2749,-2737,-2726,-2716,-2706,-2698,-2690,-2684,-2679,-2674,-2671,-2669,-2668,-2667,-2668,-2669,-2672,-2675,-2678,-2683,-2687,
--2693,-2699,-2705,-2711,-2718,-2725,-2732,-2739,-2745,-2752,-2758,-2764,-2769,-2774,-2778,-2782,-2785,-2787,-2789,-2790,-2790,
--2791,-2791,-2790,-2790,-2790,-2789,-2789,-2790,-2790,-2792,-2793,-2795,-2797,-2799,-2802,-2804,-2806,-2808,-2809,-2809,-2808,
--2807,-2804,-2799,-2793,-2786,-2778,-2768,-2757,-2745,-2732,-2719,-2705,-2691,-2677,-2663,-2650,-2638,-2626,-2616,-2606,-2597,
--2590,-2583,-2578,-2573,-2569,-2565,-2561,-2557,-2554,-2550,-2545,-2540,-2534,-2528,-2521,-2513,-2505,-2496,-2486,-2477,-2467,
--2458,-2449,-2441,-2433,-2426,-2421,-2416,-2413,-2411,-2410,-2411,-2413,-2417,-2421,-2426,-2433,-2440,-2447,-2456,-2464,-2472,
--2481,-2489,-2497,-2505,-2512,-2519,-2525,-2530,-2535,-2539,-2542,-2545,-2548,-2550,-2551,-2553,-2554,-2555,-2556,-2557,-2558,
--2559,-2561,-2563,-2565,-2567,-2570,-2572,-2575,-2577,-2580,-2582,-2583,-2584,-2584,-2583,-2581,-2579,-2575,-2569,-2563,-2555,
--2547,-2537,-2527,-2516,-2504,-2493,-2481,-2469,-2458,-2448,-2438,-2429,-2421,-2414,-2407,-2402,-2397,-2393,-2388,-2384,-2380,
--2375,-2369,-2362,-2354,-2344,-2332,-2319,-2305,-2288,-2270,-2251,-2231,-2210,-2189,-2168,-2148,-2128,-2110,-2094,-2079,-2067,
--2057,-2050,-2046,-2044,-2044,-2046,-2050,-2056,-2062,-2069,-2075,-2081,-2086,-2088,-2089,-2087,-2082,-2075,-2064,-2049,-2032,
--2011,-1988,-1962,-1935,-1905,-1875,-1844,-1813,-1782,-1753,-1725,-1699,-1676,-1655,-1637,-1622,-1610,-1601,-1595,-1591,-1590,
--1591,-1594,-1599,-1604,-1610,-1616,-1621,-1626,-1630,-1632,-1633,-1631,-1628,-1622,-1614,-1603,-1591,-1577,-1560,-1543,-1524,
--1504,-1483,-1463,-1442,-1422,-1402,-1383,-1366,-1350,-1335,-1323,-1311,-1302,-1294,-1288,-1283,-1280,-1278,-1276,-1275,-1275,
--1275,-1274,-1274,-1272,-1271,-1268,-1265,-1262,-1257,-1252,-1246,-1239,-1232,-1225,-1218,-1211,-1204,-1197,-1191,-1185,-1180,
--1176,-1172,-1169,-1167,-1165,-1163,-1161,-1160,-1159,-1157,-1155,-1153,-1150,-1147,-1143,-1138,-1133,-1127,-1120,-1113,-1106,
--1098,-1091,-1084,-1076,-1070,-1064,-1058,-1053,-1049,-1046,-1043,-1042,-1041,-1040,-1040,-1041,-1042,-1043,-1045,-1046,-1047,
--1048,-1049,-1049,-1049,-1048,-1047,-1045,-1042,-1039,-1036,-1032,-1028,-1024,-1019,-1032,-1028,-1024,-1020,-1015,-1011,-1006,
--1000,-995,-989,-983,-977,-971,-964,-958,-951,-945,-938,-932,-925,-919,-913,-907,-902,-897,-892,-888,-885,
--882,-879,-878,-877,-876,-876,-877,-878,-879,-881,-883,-885,-886,-888,-889,-890,-890,-889,-888,-885,-882,
--878,-872,-865,-858,-848,-838,-827,-815,-802,-787,-772,-757,-741,-724,-707,-690,-672,-655,-637,-620,-603,
--587,-570,-554,-539,-524,-510,-496,-482,-469,-457,-444,-432,-420,-408,-396,-385,-372,-360,-348,-334,-321,
--307,-292,-277,-261,-244,-227,-209,-190,-171,-151,-132,-111,-91,-71,-51,-32,-13,5,22,39,54,
-69,82,93,104,112,120,126,130,133,135,136,136,135,133,130,127,123,119,115,110,106,
-101,96,91,86,81,76,71,65,59,53,47,41,34,27,20,14,7,0,-5,-11,-16,
--21,-25,-28,-31,-32,-33,-33,-32,-30,-27,-24,-20,-16,-12,-8,-4,-1,1,4,6,7,
-7,6,5,2,0,-3,-7,-11,-15,-19,-23,-26,-29,-31,-33,-33,-33,-32,-30,-28,-24,
--20,-16,-11,-5,0,5,11,16,21,26,31,35,39,43,47,51,54,57,61,65,69,
-73,78,83,89,94,101,107,114,121,128,135,142,148,155,160,166,171,175,178,181,183,
-185,185,185,185,183,182,180,177,175,172,169,166,163,161,158,156,154,153,151,150,150,
-150,150,151,152,153,155,157,159,162,165,168,171,175,179,184,188,193,198,204,210,216,
-222,229,236,243,250,258,265,272,280,286,293,299,304,309,312,315,317,317,316,314,311,
-306,299,292,283,273,261,249,235,221,206,190,173,156,139,121,102,84,65,47,28,9,
--9,-28,-47,-66,-85,-103,-121,-139,-157,-174,-191,-207,-222,-237,-251,-264,-276,-288,-299,-309,-318,
--328,-337,-346,-355,-364,-374,-385,-396,-409,-423,-438,-456,-474,-495,-517,-540,-565,-591,-619,-647,-677,
--706,-736,-767,-797,-826,-855,-884,-911,-938,-964,-989,-1013,-1036,-1058,-1079,-1100,-1121,-1141,-1161,-1182,-1202,
--1223,-1243,-1265,-1287,-1309,-1331,-1354,-1377,-1401,-1424,-1448,-1471,-1494,-1517,-1540,-1562,-1583,-1604,-1624,-1644,-1663,
--1682,-1700,-1718,-1735,-1752,-1769,-1785,-1802,-1818,-1835,-1851,-1868,-1884,-1901,-1918,-1935,-1952,-1970,-1988,-2005,-2023,
--2042,-2061,-2080,-2099,-2119,-2140,-2161,-2182,-2205,-2227,-2251,-2275,-2300,-2325,-2351,-2377,-2404,-2430,-2457,-2484,-2511,
--2537,-2563,-2589,-2614,-2638,-2662,-2686,-2708,-2730,-2752,-2772,-2793,-2813,-2833,-2853,-2872,-2892,-2912,-2932,-2952,-2973,
--2994,-3015,-3036,-3057,-3079,-3100,-3121,-3141,-3162,-3181,-3200,-3219,-3236,-3253,-3269,-3284,-3299,-3313,-3327,-3341,-3354,
--3368,-3382,-3397,-3413,-3429,-3447,-3467,-3488,-3510,-3534,-3560,-3587,-3616,-3646,-3677,-3709,-3741,-3774,-3806,-3838,-3869,
--3898,-3926,-3952,-3976,-3997,-4016,-4032,-4045,-4056,-4064,-4069,-4073,-4075,-4075,-4074,-4072,-4070,-4068,-4066,-4066,-4067,
--4070,-4075,-4082,-4092,-4104,-4118,-4135,-4155,-4176,-4200,-4224,-4250,-4277,-4304,-4331,-4357,-4383,-4407,-4429,-4449,-4467,
--4483,-4497,-4508,-4516,-4523,-4527,-4529,-4530,-4530,-4528,-4526,-4524,-4521,-4519,-4517,-4515,-4514,-4514,-4514,-4515,-4516,
--4518,-4520,-4522,-4524,-4525,-4526,-4526,-4525,-4523,-4521,-4517,-4513,-4507,-4502,-4496,-4490,-4484,-4479,-4474,-4471,-4469,
--4468,-4469,-4471,-4476,-4481,-4488,-4496,-4504,-4513,-4521,-4528,-4534,-4538,-4540,-4539,-4534,-4527,-4515,-4499,-4480,-4457,
--4430,-4400,-4368,-4334,-4299,-4263,-4228,-4194,-4162,-4132,-4107,-4086,-4069,-4059,-4053,-4054,-4061,-4073,-4091,-4114,-4141,
--4173,-4208,-4246,-4286,-4326,-4367,-4408,-4447,-4485,-4520,-4552,-4582,-4608,-4630,-4650,-4666,-4679,-4689,-4697,-4703,-4707,
--4710,-4712,-4713,-4714,-4716,-4718,-4720,-4723,-4727,-4732,-4738,-4744,-4751,-4759,-4767,-4774,-4782,-4790,-4797,-4804,-4810,
--4815,-4820,-4824,-4827,-4830,-4831,-4832,-4833,-4833,-4832,-4831,-4830,-4829,-4827,-4825,-4823,-4821,-4819,-4816,-4813,-4811,
--4808,-4805,-4802,-4799,-4796,-4793,-4791,-4788,-4786,-4785,-4783,-4783,-4783,-4784,-4785,-4788,-4791,-4794,-4799,-4804,-4810,
--4816,-4823,-4830,-4837,-4844,-4851,-4858,-4865,-4871,-4877,-4883,-4888,-4893,-4897,-4902,-4905,-4909,-4913,-4916,-4919,-4923,
--4926,-4930,-4933,-4937,-4941,-4945,-4950,-4954,-4958,-4962,-4966,-4969,-4972,-4975,-4977,-4979,-4980,-4980,-4980,-4980,-4979,
--4977,-4975,-4973,-4971,-4969,-4967,-4964,-4962,-4960,-4959,-4957,-4956,-4955,-4955,-4954,-4954,-4954,-4953,-4953,-4953,-4952,
--4951,-4950,-4948,-4946,-4943,-4940,-4936,-4932,-4928,-4924,-4919,-4914,-4909,-4904,-4900,-4895,-4891,-4887,-4884,-4881,-4878,
--4875,-4873,-4872,-4870,-4869,-4868,-4866,-4865,-4863,-4861,-4859,-4856,-4853,-4849,-4844,-4839,-4833,-4827,-4820,-4812,-4804,
--4796,-4787,-4778,-4769,-4759,-4750,-4741,-4731,-4723,-4714,-4706,-4698,-4690,-4683,-4676,-4669,-4663,-4657,-4652,-4647,-4642,
--4637,-4633,-4628,-4624,-4620,-4616,-4612,-4608,-4604,-4600,-4596,-4592,-4588,-4584,-4580,-4576,-4572,-4569,-4565,-4562,-4558,
--4555,-4552,-4549,-4546,-4544,-4541,-4538,-4535,-4532,-4529,-4526,-4522,-4519,-4514,-4510,-4505,-4499,-4493,-4486,-4478,-4470,
--4462,-4452,-4442,-4431,-4420,-4408,-4396,-4383,-4370,-4357,-4344,-4331,-4318,-4305,-4293,-4280,-4269,-4258,-4248,-4238,-4229,
--4221,-4214,-4208,-4202,-4196,-4192,-4188,-4184,-4180,-4177,-4174,-4171,-4167,-4164,-4160,-4156,-4152,-4147,-4142,-4136,-4130,
--4124,-4117,-4110,-4102,-4094,-4085,-4076,-4067,-4058,-4048,-4038,-4028,-4017,-4006,-3995,-3984,-3972,-3959,-3947,-3934,-3921,
--3907,-3893,-3878,-3864,-3849,-3834,-3819,-3804,-3789,-3774,-3759,-3745,-3730,-3716,-3702,-3689,-3676,-3663,-3651,-3639,-3627,
--3615,-3603,-3592,-3580,-3568,-3557,-3545,-3533,-3521,-3509,-3497,-3484,-3472,-3460,-3447,-3435,-3422,-3411,-3399,-3387,-3376,
--3366,-3355,-3346,-3336,-3327,-3319,-3311,-3303,-3296,-3289,-3282,-3275,-3268,-3261,-3254,-3247,-3240,-3233,-3225,-3217,-3209,
--3201,-3193,-3184,-3175,-3166,-3157,-3147,-3138,-3129,-3120,-3111,-3102,-3093,-3085,-3077,-3069,-3062,-3055,-3048,-3042,-3036,
--3031,-3026,-3021,-3016,-3012,-3008,-3004,-3000,-2996,-2992,-2988,-2983,-2979,-2974,-2969,-2963,-2956,-2950,-2942,-2934,-2926,
--2917,-2908,-2898,-2888,-2878,-2868,-2857,-2846,-2836,-2825,-2815,-2806,-2796,-2787,-2779,-2771,-2764,-2757,-2751,-2746,-2741,
--2738,-2735,-2732,-2731,-2730,-2730,-2731,-2732,-2735,-2738,-2741,-2745,-2750,-2756,-2762,-2768,-2775,-2782,-2789,-2796,-2802,
--2809,-2815,-2821,-2826,-2830,-2834,-2837,-2838,-2839,-2839,-2839,-2837,-2835,-2832,-2829,-2825,-2822,-2818,-2815,-2812,-2809,
--2808,-2807,-2806,-2807,-2808,-2809,-2812,-2814,-2817,-2820,-2823,-2826,-2828,-2829,-2830,-2829,-2827,-2824,-2820,-2814,-2807,
--2799,-2790,-2779,-2768,-2756,-2744,-2731,-2718,-2706,-2694,-2682,-2671,-2661,-2652,-2643,-2636,-2629,-2623,-2618,-2613,-2608,
--2604,-2600,-2596,-2591,-2586,-2581,-2575,-2569,-2562,-2555,-2547,-2539,-2531,-2522,-2514,-2505,-2497,-2490,-2483,-2477,-2472,
--2468,-2466,-2464,-2464,-2465,-2467,-2470,-2474,-2479,-2485,-2491,-2498,-2505,-2512,-2519,-2525,-2532,-2537,-2542,-2546,-2550,
--2553,-2554,-2555,-2556,-2555,-2555,-2553,-2552,-2550,-2548,-2546,-2544,-2543,-2542,-2541,-2540,-2540,-2540,-2541,-2541,-2542,
--2543,-2543,-2543,-2543,-2542,-2541,-2538,-2535,-2530,-2525,-2519,-2511,-2503,-2494,-2485,-2475,-2465,-2455,-2446,-2437,-2428,
--2420,-2413,-2408,-2403,-2400,-2397,-2395,-2394,-2394,-2394,-2394,-2393,-2392,-2390,-2387,-2382,-2375,-2367,-2356,-2343,-2328,
--2312,-2293,-2272,-2250,-2228,-2204,-2181,-2158,-2135,-2114,-2095,-2077,-2062,-2049,-2038,-2030,-2025,-2022,-2022,-2023,-2026,
--2030,-2035,-2040,-2045,-2049,-2051,-2052,-2051,-2047,-2040,-2031,-2019,-2003,-1986,-1965,-1943,-1918,-1892,-1865,-1838,-1811,
--1785,-1759,-1735,-1713,-1693,-1676,-1662,-1650,-1641,-1635,-1631,-1630,-1631,-1634,-1638,-1642,-1648,-1653,-1658,-1662,-1665,
--1666,-1665,-1662,-1657,-1649,-1639,-1626,-1611,-1594,-1575,-1554,-1532,-1508,-1484,-1460,-1436,-1412,-1389,-1367,-1347,-1328,
--1310,-1294,-1281,-1269,-1258,-1250,-1243,-1238,-1234,-1231,-1228,-1227,-1225,-1224,-1222,-1221,-1218,-1216,-1212,-1208,-1203,
--1198,-1191,-1185,-1177,-1170,-1162,-1154,-1147,-1140,-1133,-1126,-1120,-1115,-1111,-1107,-1104,-1102,-1100,-1099,-1098,-1097,
--1097,-1096,-1096,-1095,-1094,-1092,-1090,-1087,-1084,-1080,-1076,-1071,-1066,-1061,-1056,-1050,-1045,-1040,-1035,-1031,-1027,
--1024,-1022,-1020,-1019,-1019,-1019,-1020,-1021,-1023,-1025,-1027,-1030,-1033,-1035,-1037,-1039,-1041,-1042,-1043,-1043,-1043,
--1043,-1041,-1040,-1037,-1035,-1032,-1064,-1062,-1059,-1056,-1052,-1048,-1044,-1039,-1033,-1028,-1022,-1016,-1010,-1004,-998,
--992,-986,-981,-975,-970,-966,-961,-957,-954,-951,-948,-946,-944,-943,-942,-941,-941,-941,-942,-942,-942,
--943,-943,-943,-943,-942,-941,-939,-936,-933,-929,-925,-920,-914,-907,-900,-892,-883,-874,-865,-855,-845,
--835,-824,-813,-803,-792,-781,-771,-761,-751,-741,-731,-721,-712,-702,-693,-683,-674,-664,-654,-644,-634,
--623,-611,-599,-587,-574,-560,-545,-530,-514,-496,-479,-460,-440,-420,-399,-377,-355,-332,-309,-285,-261,
--237,-213,-189,-165,-142,-119,-97,-75,-55,-36,-17,0,15,29,42,53,63,72,79,85,90,
-93,96,97,98,97,96,95,93,91,88,85,81,78,74,70,66,62,57,52,47,41,
-35,28,22,14,7,0,-9,-17,-26,-34,-43,-51,-59,-67,-74,-81,-87,-92,-96,-100,-103,
--105,-107,-108,-109,-109,-109,-108,-108,-108,-108,-108,-109,-110,-111,-113,-115,-118,-121,-124,-127,-131,
--134,-137,-140,-143,-145,-146,-147,-147,-146,-145,-143,-140,-137,-133,-128,-124,-119,-113,-108,-102,-97,
--91,-86,-80,-75,-70,-65,-60,-54,-49,-43,-37,-31,-25,-18,-10,-3,5,13,22,32,41,
-51,60,69,78,87,94,101,108,113,117,120,122,123,123,122,120,117,113,109,104,98,
-93,87,82,77,72,67,63,60,57,56,55,55,55,56,59,61,65,69,73,78,83,
-88,94,100,105,111,117,123,129,135,141,147,153,159,164,170,175,181,186,190,195,199,
-202,205,207,209,209,209,208,206,202,198,192,185,177,168,158,148,136,123,110,96,82,
-68,53,38,23,8,-6,-21,-36,-50,-65,-79,-93,-107,-121,-135,-149,-163,-177,-191,-205,-220,
--234,-249,-263,-278,-292,-307,-322,-336,-351,-365,-379,-393,-407,-421,-435,-449,-463,-477,-492,-507,-522,
--538,-555,-572,-590,-609,-629,-650,-671,-693,-716,-740,-764,-789,-814,-839,-864,-890,-915,-940,-965,-990,
--1015,-1039,-1063,-1086,-1110,-1133,-1155,-1178,-1200,-1223,-1245,-1268,-1290,-1313,-1336,-1359,-1381,-1404,-1427,-1450,-1473,
--1496,-1518,-1540,-1562,-1584,-1604,-1625,-1645,-1664,-1684,-1702,-1720,-1738,-1755,-1772,-1789,-1806,-1822,-1839,-1855,-1872,
--1888,-1905,-1922,-1939,-1956,-1973,-1991,-2008,-2026,-2044,-2061,-2079,-2097,-2116,-2134,-2153,-2171,-2190,-2209,-2229,-2248,
--2268,-2289,-2309,-2330,-2352,-2373,-2395,-2418,-2440,-2463,-2485,-2508,-2531,-2554,-2576,-2599,-2621,-2643,-2665,-2686,-2707,
--2728,-2748,-2769,-2789,-2809,-2829,-2849,-2869,-2890,-2910,-2931,-2952,-2973,-2994,-3015,-3037,-3058,-3080,-3101,-3122,-3142,
--3162,-3182,-3201,-3219,-3236,-3253,-3269,-3285,-3300,-3315,-3329,-3343,-3357,-3372,-3387,-3403,-3420,-3438,-3457,-3478,-3500,
--3524,-3549,-3576,-3604,-3634,-3665,-3696,-3729,-3761,-3793,-3825,-3856,-3886,-3914,-3940,-3964,-3986,-4004,-4020,-4033,-4043,
--4051,-4055,-4057,-4057,-4055,-4052,-4047,-4042,-4037,-4032,-4028,-4025,-4024,-4024,-4027,-4033,-4040,-4051,-4064,-4080,-4098,
--4119,-4141,-4165,-4189,-4215,-4241,-4266,-4291,-4314,-4336,-4356,-4374,-4390,-4404,-4414,-4423,-4428,-4432,-4433,-4433,-4430,
--4427,-4423,-4417,-4412,-4407,-4401,-4397,-4393,-4390,-4387,-4386,-4386,-4386,-4388,-4390,-4392,-4395,-4398,-4401,-4403,-4406,
--4407,-4408,-4408,-4407,-4406,-4404,-4401,-4398,-4395,-4392,-4388,-4385,-4382,-4380,-4378,-4377,-4376,-4376,-4376,-4377,-4378,
--4379,-4379,-4379,-4378,-4375,-4371,-4366,-4358,-4349,-4337,-4323,-4307,-4288,-4268,-4247,-4224,-4201,-4177,-4153,-4130,-4109,
--4089,-4072,-4057,-4046,-4038,-4034,-4034,-4038,-4046,-4058,-4074,-4093,-4116,-4141,-4169,-4198,-4229,-4260,-4292,-4323,-4354,
--4384,-4412,-4439,-4464,-4486,-4507,-4525,-4542,-4556,-4569,-4580,-4589,-4598,-4605,-4612,-4618,-4624,-4629,-4635,-4641,-4646,
--4652,-4659,-4665,-4671,-4677,-4684,-4690,-4696,-4701,-4707,-4711,-4716,-4719,-4723,-4726,-4728,-4730,-4732,-4733,-4734,-4736,
--4737,-4738,-4739,-4741,-4743,-4744,-4746,-4748,-4750,-4753,-4755,-4757,-4759,-4761,-4763,-4764,-4765,-4766,-4767,-4767,-4767,
--4767,-4767,-4766,-4765,-4765,-4764,-4764,-4764,-4764,-4764,-4765,-4767,-4768,-4770,-4773,-4776,-4780,-4783,-4788,-4792,-4797,
--4802,-4807,-4812,-4818,-4823,-4829,-4834,-4839,-4845,-4850,-4856,-4861,-4867,-4872,-4877,-4882,-4887,-4892,-4896,-4900,-4904,
--4908,-4912,-4915,-4917,-4920,-4921,-4923,-4924,-4924,-4924,-4924,-4923,-4922,-4921,-4919,-4918,-4916,-4914,-4913,-4911,-4910,
--4908,-4907,-4906,-4904,-4903,-4903,-4902,-4901,-4900,-4899,-4898,-4897,-4895,-4894,-4892,-4890,-4887,-4885,-4882,-4879,-4876,
--4873,-4870,-4866,-4863,-4860,-4857,-4855,-4853,-4851,-4849,-4847,-4846,-4845,-4845,-4844,-4844,-4843,-4843,-4842,-4841,-4839,
--4837,-4835,-4832,-4828,-4824,-4819,-4814,-4807,-4800,-4793,-4785,-4776,-4767,-4758,-4748,-4738,-4729,-4719,-4709,-4700,-4691,
--4682,-4674,-4666,-4659,-4652,-4646,-4640,-4634,-4629,-4624,-4620,-4615,-4611,-4607,-4603,-4599,-4595,-4591,-4587,-4582,-4578,
--4573,-4568,-4563,-4558,-4552,-4547,-4541,-4535,-4530,-4524,-4519,-4513,-4508,-4503,-4498,-4494,-4489,-4485,-4482,-4478,-4474,
--4471,-4468,-4465,-4461,-4458,-4454,-4450,-4446,-4442,-4437,-4431,-4425,-4419,-4412,-4404,-4396,-4387,-4378,-4368,-4358,-4347,
--4337,-4326,-4315,-4305,-4294,-4284,-4274,-4265,-4256,-4248,-4240,-4233,-4227,-4221,-4216,-4212,-4208,-4205,-4202,-4200,-4197,
--4195,-4193,-4191,-4188,-4186,-4183,-4180,-4176,-4171,-4167,-4161,-4155,-4148,-4141,-4133,-4124,-4115,-4106,-4095,-4085,-4074,
--4062,-4050,-4037,-4024,-4011,-3997,-3983,-3969,-3954,-3939,-3924,-3908,-3893,-3877,-3861,-3845,-3829,-3814,-3798,-3783,-3768,
--3753,-3739,-3725,-3712,-3700,-3688,-3676,-3665,-3655,-3645,-3636,-3627,-3618,-3609,-3601,-3593,-3584,-3576,-3567,-3558,-3549,
--3539,-3529,-3519,-3508,-3497,-3486,-3475,-3463,-3451,-3440,-3428,-3416,-3405,-3394,-3383,-3372,-3362,-3352,-3343,-3333,-3324,
--3315,-3306,-3297,-3288,-3279,-3270,-3260,-3250,-3240,-3229,-3219,-3207,-3195,-3183,-3170,-3157,-3144,-3131,-3118,-3105,-3092,
--3080,-3067,-3056,-3045,-3035,-3026,-3017,-3010,-3003,-2998,-2993,-2989,-2986,-2984,-2982,-2981,-2980,-2980,-2979,-2979,-2979,
--2978,-2977,-2976,-2975,-2973,-2970,-2967,-2963,-2958,-2953,-2947,-2941,-2934,-2927,-2920,-2912,-2904,-2897,-2889,-2881,-2873,
--2866,-2859,-2852,-2846,-2839,-2834,-2828,-2823,-2819,-2815,-2811,-2808,-2805,-2803,-2801,-2800,-2800,-2799,-2800,-2801,-2803,
--2805,-2809,-2812,-2817,-2822,-2828,-2835,-2842,-2849,-2857,-2865,-2873,-2881,-2888,-2895,-2902,-2908,-2913,-2917,-2919,-2921,
--2922,-2921,-2919,-2917,-2913,-2908,-2902,-2896,-2890,-2883,-2877,-2870,-2864,-2858,-2853,-2849,-2846,-2843,-2842,-2841,-2841,
--2842,-2843,-2845,-2848,-2850,-2852,-2854,-2855,-2856,-2856,-2856,-2854,-2851,-2847,-2843,-2837,-2831,-2823,-2815,-2807,-2798,
--2789,-2780,-2771,-2762,-2753,-2745,-2738,-2730,-2724,-2718,-2712,-2706,-2701,-2696,-2691,-2686,-2681,-2676,-2670,-2663,-2656,
--2648,-2640,-2631,-2621,-2611,-2601,-2590,-2579,-2569,-2558,-2548,-2538,-2529,-2521,-2513,-2507,-2502,-2498,-2495,-2493,-2493,
--2493,-2495,-2498,-2501,-2505,-2509,-2514,-2519,-2523,-2528,-2532,-2536,-2540,-2543,-2545,-2546,-2547,-2547,-2546,-2545,-2543,
--2540,-2537,-2534,-2530,-2526,-2522,-2517,-2513,-2507,-2502,-2497,-2491,-2485,-2478,-2471,-2464,-2456,-2447,-2438,-2429,-2419,
--2408,-2397,-2386,-2375,-2365,-2354,-2344,-2334,-2326,-2318,-2312,-2307,-2304,-2302,-2302,-2304,-2307,-2311,-2316,-2323,-2330,
--2338,-2345,-2353,-2359,-2365,-2368,-2371,-2370,-2368,-2363,-2355,-2345,-2332,-2316,-2298,-2277,-2255,-2231,-2206,-2180,-2154,
--2128,-2103,-2079,-2056,-2035,-2017,-2000,-1986,-1975,-1966,-1959,-1954,-1952,-1950,-1950,-1951,-1952,-1953,-1953,-1953,-1951,
--1948,-1943,-1937,-1928,-1918,-1906,-1892,-1877,-1861,-1843,-1825,-1807,-1789,-1772,-1756,-1741,-1728,-1716,-1707,-1700,-1695,
--1692,-1691,-1692,-1694,-1698,-1703,-1708,-1714,-1720,-1725,-1729,-1731,-1732,-1731,-1727,-1722,-1713,-1702,-1689,-1673,-1654,
--1633,-1611,-1587,-1561,-1534,-1507,-1480,-1453,-1426,-1400,-1375,-1352,-1330,-1310,-1291,-1275,-1260,-1247,-1237,-1227,-1220,
--1213,-1208,-1203,-1200,-1196,-1193,-1190,-1187,-1184,-1180,-1175,-1170,-1165,-1159,-1152,-1145,-1137,-1129,-1121,-1113,-1105,
--1097,-1090,-1083,-1076,-1070,-1065,-1060,-1057,-1053,-1051,-1049,-1047,-1046,-1046,-1045,-1045,-1045,-1045,-1044,-1044,-1043,
--1042,-1041,-1039,-1037,-1035,-1033,-1030,-1028,-1025,-1023,-1021,-1019,-1018,-1017,-1016,-1016,-1016,-1017,-1019,-1021,-1023,
--1026,-1029,-1033,-1037,-1040,-1044,-1048,-1052,-1055,-1058,-1061,-1063,-1065,-1067,-1067,-1067,-1067,-1066,-1064,-1120,-1118,
--1116,-1114,-1110,-1106,-1102,-1096,-1091,-1085,-1079,-1072,-1066,-1059,-1053,-1047,-1041,-1035,-1030,-1025,-1021,-1017,-1014,
--1012,-1010,-1008,-1007,-1007,-1007,-1007,-1007,-1008,-1008,-1009,-1009,-1009,-1008,-1007,-1006,-1003,-1001,-997,-993,-988,
--982,-975,-968,-961,-953,-945,-936,-927,-919,-910,-901,-893,-885,-878,-871,-865,-859,-854,-849,-845,-842,
--838,-835,-832,-830,-827,-824,-821,-817,-812,-807,-801,-794,-786,-776,-766,-754,-741,-726,-710,-692,-674,
--654,-632,-610,-586,-562,-537,-511,-484,-457,-430,-402,-374,-347,-319,-292,-266,-240,-215,-190,-167,-144,
--123,-103,-84,-66,-49,-34,-21,-8,2,12,21,29,35,41,45,49,52,54,55,56,56,
-56,55,53,52,49,47,44,40,36,32,27,22,16,9,2,-4,-12,-20,-29,-38,-48,
--57,-67,-77,-87,-97,-107,-116,-125,-134,-143,-151,-158,-165,-172,-179,-185,-190,-195,-200,-205,-210,
--215,-219,-224,-228,-233,-238,-242,-247,-251,-256,-260,-264,-268,-271,-274,-276,-278,-280,-280,-280,-280,
--279,-277,-275,-272,-269,-265,-261,-256,-252,-247,-242,-237,-231,-226,-221,-215,-210,-204,-198,-192,-186,
--179,-172,-165,-157,-148,-139,-129,-119,-108,-97,-86,-75,-63,-52,-40,-30,-19,-10,-1,6,13,
-19,23,26,28,29,28,26,23,19,14,8,2,-3,-10,-17,-23,-29,-35,-40,-44,-47,
--49,-51,-51,-51,-49,-46,-43,-38,-33,-27,-21,-14,-7,0,8,16,24,31,39,47,54,
-61,68,75,81,87,92,97,102,106,109,112,114,115,116,115,114,112,109,105,100,94,
-86,78,68,58,47,34,22,8,-5,-19,-34,-49,-63,-78,-92,-106,-120,-133,-146,-158,-170,
--181,-191,-201,-211,-221,-230,-239,-249,-258,-268,-278,-288,-299,-311,-323,-336,-349,-364,-378,-394,-410,
--426,-443,-461,-479,-497,-515,-534,-553,-571,-590,-609,-628,-647,-666,-685,-703,-722,-741,-760,-779,-798,
--817,-836,-855,-875,-895,-915,-935,-955,-976,-997,-1018,-1039,-1061,-1083,-1106,-1128,-1151,-1175,-1198,-1222,-1246,
--1271,-1296,-1321,-1346,-1371,-1396,-1421,-1446,-1471,-1495,-1520,-1544,-1567,-1590,-1613,-1634,-1656,-1676,-1697,-1716,-1735,
--1754,-1771,-1789,-1806,-1823,-1839,-1856,-1872,-1888,-1904,-1920,-1937,-1953,-1969,-1986,-2003,-2020,-2037,-2054,-2072,-2089,
--2106,-2124,-2141,-2159,-2176,-2194,-2211,-2229,-2246,-2263,-2281,-2298,-2315,-2333,-2351,-2368,-2386,-2405,-2423,-2441,-2460,
--2479,-2498,-2517,-2537,-2556,-2576,-2595,-2615,-2635,-2654,-2674,-2694,-2714,-2733,-2753,-2773,-2793,-2812,-2832,-2853,-2873,
--2893,-2914,-2934,-2955,-2976,-2997,-3018,-3039,-3060,-3081,-3102,-3122,-3142,-3162,-3181,-3199,-3217,-3235,-3252,-3268,-3285,
--3301,-3316,-3332,-3348,-3364,-3381,-3398,-3416,-3435,-3456,-3477,-3499,-3523,-3549,-3575,-3603,-3632,-3661,-3692,-3723,-3754,
--3785,-3815,-3845,-3874,-3901,-3926,-3950,-3971,-3989,-4005,-4018,-4028,-4036,-4040,-4043,-4043,-4041,-4037,-4032,-4027,-4020,
--4014,-4008,-4003,-3999,-3997,-3996,-3997,-4001,-4008,-4016,-4027,-4040,-4056,-4073,-4092,-4112,-4133,-4155,-4177,-4198,-4219,
--4238,-4256,-4273,-4288,-4300,-4310,-4318,-4324,-4327,-4328,-4328,-4325,-4321,-4316,-4310,-4304,-4297,-4291,-4285,-4279,-4274,
--4270,-4267,-4265,-4264,-4264,-4266,-4268,-4270,-4274,-4277,-4281,-4285,-4288,-4291,-4294,-4295,-4296,-4297,-4296,-4294,-4292,
--4289,-4285,-4280,-4275,-4270,-4264,-4258,-4252,-4246,-4240,-4234,-4228,-4222,-4216,-4210,-4203,-4197,-4190,-4182,-4174,-4166,
--4157,-4147,-4136,-4125,-4113,-4101,-4089,-4077,-4065,-4053,-4042,-4032,-4023,-4015,-4009,-4006,-4004,-4005,-4008,-4013,-4021,
--4032,-4044,-4059,-4077,-4096,-4116,-4138,-4161,-4185,-4210,-4234,-4259,-4283,-4307,-4330,-4352,-4373,-4393,-4412,-4429,-4446,
--4461,-4475,-4488,-4501,-4512,-4523,-4533,-4543,-4552,-4561,-4569,-4577,-4584,-4592,-4598,-4605,-4611,-4616,-4621,-4626,-4630,
--4633,-4636,-4639,-4641,-4643,-4644,-4645,-4646,-4646,-4647,-4648,-4649,-4650,-4652,-4654,-4657,-4660,-4663,-4667,-4672,-4676,
--4682,-4687,-4693,-4698,-4704,-4710,-4715,-4720,-4725,-4729,-4733,-4737,-4739,-4742,-4743,-4744,-4745,-4745,-4745,-4744,-4743,
--4742,-4742,-4741,-4740,-4739,-4738,-4738,-4738,-4738,-4739,-4740,-4742,-4744,-4746,-4749,-4752,-4755,-4759,-4763,-4767,-4772,
--4776,-4781,-4786,-4791,-4796,-4801,-4806,-4810,-4815,-4820,-4824,-4828,-4832,-4836,-4840,-4843,-4846,-4849,-4851,-4853,-4855,
--4856,-4857,-4858,-4859,-4859,-4860,-4860,-4860,-4859,-4859,-4859,-4858,-4858,-4857,-4857,-4856,-4855,-4854,-4854,-4853,-4851,
--4850,-4849,-4847,-4846,-4844,-4842,-4840,-4838,-4835,-4833,-4831,-4828,-4826,-4824,-4822,-4820,-4819,-4818,-4817,-4817,-4816,
--4817,-4817,-4818,-4819,-4820,-4822,-4823,-4825,-4826,-4827,-4828,-4829,-4829,-4828,-4827,-4825,-4823,-4819,-4815,-4810,-4804,
--4797,-4789,-4781,-4772,-4763,-4752,-4742,-4731,-4720,-4709,-4698,-4687,-4676,-4665,-4655,-4645,-4636,-4627,-4619,-4611,-4604,
--4598,-4592,-4586,-4581,-4576,-4572,-4568,-4564,-4561,-4557,-4554,-4550,-4547,-4543,-4539,-4535,-4530,-4526,-4521,-4515,-4510,
--4504,-4498,-4491,-4484,-4478,-4471,-4464,-4457,-4450,-4442,-4435,-4429,-4422,-4415,-4409,-4402,-4396,-4390,-4384,-4378,-4372,
--4366,-4361,-4355,-4349,-4343,-4337,-4331,-4325,-4319,-4313,-4306,-4300,-4294,-4287,-4281,-4275,-4268,-4262,-4257,-4251,-4246,
--4241,-4237,-4233,-4229,-4226,-4223,-4220,-4218,-4216,-4215,-4213,-4212,-4211,-4210,-4209,-4208,-4207,-4205,-4203,-4201,-4198,
--4195,-4191,-4187,-4182,-4176,-4170,-4163,-4156,-4147,-4138,-4129,-4118,-4107,-4095,-4083,-4070,-4056,-4042,-4027,-4012,-3997,
--3981,-3964,-3948,-3931,-3914,-3897,-3880,-3863,-3847,-3831,-3815,-3799,-3784,-3770,-3756,-3743,-3731,-3719,-3707,-3697,-3687,
--3677,-3668,-3660,-3651,-3643,-3635,-3627,-3619,-3611,-3602,-3594,-3585,-3575,-3565,-3555,-3544,-3533,-3522,-3510,-3498,-3485,
--3473,-3460,-3447,-3435,-3422,-3410,-3398,-3386,-3374,-3362,-3350,-3339,-3327,-3316,-3304,-3292,-3280,-3268,-3255,-3242,-3229,
--3215,-3200,-3185,-3170,-3154,-3137,-3120,-3104,-3087,-3070,-3053,-3037,-3021,-3006,-2992,-2979,-2967,-2956,-2946,-2938,-2932,
--2926,-2922,-2920,-2918,-2918,-2919,-2921,-2924,-2927,-2931,-2936,-2940,-2945,-2949,-2953,-2957,-2960,-2962,-2964,-2966,-2966,
--2966,-2965,-2964,-2962,-2959,-2956,-2952,-2948,-2944,-2940,-2936,-2931,-2927,-2922,-2918,-2913,-2909,-2905,-2901,-2898,-2894,
--2891,-2888,-2885,-2882,-2879,-2877,-2875,-2873,-2872,-2872,-2872,-2872,-2874,-2876,-2879,-2883,-2887,-2893,-2899,-2906,-2914,
--2922,-2931,-2940,-2949,-2959,-2968,-2977,-2985,-2992,-2999,-3004,-3009,-3012,-3014,-3014,-3013,-3010,-3006,-3001,-2994,-2987,
--2978,-2969,-2960,-2950,-2941,-2931,-2922,-2914,-2906,-2899,-2893,-2888,-2884,-2881,-2878,-2877,-2877,-2877,-2878,-2879,-2880,
--2882,-2883,-2885,-2886,-2886,-2886,-2886,-2884,-2883,-2880,-2877,-2873,-2869,-2865,-2860,-2855,-2849,-2844,-2838,-2833,-2827,
--2821,-2816,-2811,-2805,-2800,-2794,-2788,-2782,-2776,-2769,-2762,-2754,-2745,-2736,-2726,-2715,-2704,-2692,-2679,-2666,-2653,
--2639,-2626,-2612,-2599,-2586,-2574,-2562,-2551,-2541,-2533,-2525,-2518,-2513,-2509,-2506,-2505,-2504,-2505,-2506,-2509,-2511,
--2515,-2518,-2522,-2526,-2530,-2534,-2537,-2539,-2541,-2543,-2543,-2542,-2541,-2538,-2535,-2530,-2524,-2518,-2510,-2500,-2490,
--2479,-2466,-2453,-2439,-2423,-2407,-2390,-2373,-2355,-2337,-2318,-2300,-2281,-2264,-2246,-2230,-2215,-2201,-2188,-2177,-2169,
--2162,-2158,-2156,-2156,-2159,-2164,-2171,-2181,-2192,-2205,-2219,-2234,-2250,-2266,-2281,-2296,-2309,-2321,-2331,-2338,-2343,
--2344,-2343,-2338,-2330,-2319,-2304,-2286,-2266,-2243,-2219,-2192,-2164,-2136,-2107,-2079,-2051,-2024,-1998,-1974,-1952,-1932,
--1915,-1899,-1886,-1875,-1866,-1859,-1853,-1849,-1845,-1843,-1840,-1838,-1836,-1833,-1829,-1825,-1820,-1815,-1808,-1801,-1793,
--1784,-1775,-1766,-1758,-1749,-1742,-1735,-1730,-1725,-1722,-1721,-1721,-1723,-1726,-1731,-1736,-1743,-1750,-1758,-1765,-1772,
--1779,-1784,-1788,-1790,-1791,-1789,-1784,-1777,-1767,-1754,-1739,-1721,-1700,-1678,-1653,-1627,-1599,-1570,-1540,-1510,-1480,
--1450,-1421,-1393,-1366,-1340,-1316,-1294,-1274,-1256,-1240,-1226,-1214,-1203,-1194,-1186,-1180,-1175,-1170,-1166,-1163,-1159,
--1156,-1153,-1150,-1146,-1142,-1137,-1132,-1127,-1121,-1115,-1109,-1102,-1096,-1089,-1082,-1076,-1070,-1064,-1059,-1054,-1049,
--1046,-1042,-1040,-1038,-1036,-1035,-1034,-1034,-1034,-1034,-1034,-1034,-1035,-1035,-1036,-1036,-1036,-1036,-1036,-1036,-1036,
--1037,-1037,-1037,-1037,-1038,-1039,-1040,-1042,-1043,-1046,-1048,-1051,-1055,-1059,-1063,-1067,-1072,-1077,-1082,-1087,-1092,
--1097,-1101,-1105,-1109,-1113,-1115,-1118,-1119,-1120,-1120,-1120,-1174,-1174,-1173,-1171,-1169,-1166,-1162,-1157,-1152,-1147,
--1141,-1135,-1128,-1122,-1115,-1109,-1103,-1097,-1092,-1087,-1083,-1079,-1076,-1074,-1071,-1070,-1069,-1068,-1068,-1068,-1068,
--1068,-1067,-1067,-1066,-1065,-1063,-1061,-1058,-1054,-1049,-1044,-1038,-1031,-1024,-1016,-1008,-999,-990,-981,-973,-964,
--956,-948,-941,-935,-929,-924,-920,-917,-915,-914,-913,-913,-914,-915,-917,-918,-920,-921,-921,-921,-921,
--919,-916,-911,-906,-898,-889,-878,-866,-852,-836,-818,-798,-778,-755,-731,-707,-681,-654,-626,-598,-569,
--541,-512,-483,-454,-426,-398,-371,-344,-319,-294,-270,-247,-225,-204,-184,-165,-148,-131,-115,-101,-88,
--75,-64,-54,-44,-36,-28,-22,-16,-11,-6,-3,0,1,3,4,4,3,2,1,-1,-4,
--7,-11,-16,-21,-27,-34,-40,-48,-55,-63,-72,-81,-90,-99,-108,-118,-127,-137,-147,-157,-166,
--176,-185,-195,-204,-213,-222,-231,-240,-249,-258,-266,-275,-283,-291,-300,-308,-315,-323,-330,-338,-344,
--351,-357,-362,-367,-371,-375,-378,-381,-382,-384,-384,-384,-383,-382,-380,-377,-375,-371,-368,-364,-360,
--356,-352,-348,-343,-339,-334,-330,-325,-320,-315,-310,-304,-298,-291,-284,-276,-268,-259,-250,-240,-229,
--219,-207,-196,-184,-172,-161,-150,-139,-128,-118,-110,-102,-95,-89,-84,-81,-79,-78,-78,-80,-82,
--86,-90,-95,-100,-106,-112,-118,-124,-129,-134,-138,-142,-144,-146,-147,-147,-145,-143,-140,-136,-132,
--126,-120,-113,-106,-98,-91,-83,-75,-67,-59,-51,-43,-36,-29,-22,-16,-11,-6,-1,2,6,
-8,11,12,12,12,11,9,6,2,-2,-8,-15,-23,-32,-41,-52,-64,-76,-89,-103,-117,
--131,-146,-160,-175,-189,-203,-216,-229,-242,-254,-265,-276,-286,-295,-304,-312,-320,-328,-335,-342,-350,
--357,-365,-373,-382,-392,-402,-413,-426,-439,-453,-468,-483,-500,-518,-536,-555,-575,-595,-615,-635,-656,
--677,-697,-718,-738,-757,-777,-796,-814,-832,-850,-867,-884,-900,-917,-933,-949,-965,-980,-997,-1013,-1030,
--1047,-1064,-1082,-1101,-1120,-1140,-1161,-1183,-1205,-1228,-1251,-1275,-1300,-1325,-1350,-1376,-1402,-1428,-1455,-1481,-1507,
--1532,-1558,-1583,-1607,-1631,-1654,-1677,-1698,-1720,-1740,-1760,-1779,-1798,-1816,-1833,-1851,-1867,-1884,-1900,-1916,-1932,
--1948,-1964,-1980,-1996,-2012,-2028,-2044,-2060,-2077,-2093,-2110,-2126,-2143,-2160,-2176,-2193,-2209,-2226,-2242,-2258,-2274,
--2290,-2306,-2322,-2338,-2354,-2370,-2386,-2402,-2418,-2435,-2451,-2468,-2485,-2502,-2520,-2537,-2555,-2573,-2591,-2610,-2628,
--2647,-2665,-2684,-2703,-2722,-2741,-2760,-2780,-2799,-2818,-2838,-2858,-2877,-2897,-2917,-2937,-2957,-2977,-2997,-3017,-3037,
--3056,-3076,-3095,-3114,-3132,-3150,-3168,-3185,-3203,-3219,-3236,-3252,-3268,-3284,-3300,-3316,-3333,-3350,-3367,-3385,-3404,
--3423,-3444,-3466,-3489,-3512,-3537,-3563,-3590,-3618,-3646,-3675,-3704,-3734,-3762,-3791,-3818,-3845,-3870,-3893,-3915,-3934,
--3952,-3967,-3979,-3989,-3997,-4003,-4006,-4007,-4007,-4005,-4002,-3997,-3993,-3988,-3983,-3979,-3975,-3973,-3972,-3972,-3975,
--3978,-3984,-3992,-4002,-4013,-4025,-4040,-4055,-4071,-4087,-4104,-4121,-4137,-4152,-4167,-4181,-4193,-4203,-4212,-4219,-4225,
--4229,-4231,-4231,-4231,-4228,-4225,-4222,-4217,-4212,-4207,-4202,-4198,-4193,-4189,-4186,-4184,-4182,-4181,-4181,-4181,-4181,
--4183,-4184,-4185,-4187,-4188,-4189,-4190,-4190,-4190,-4188,-4186,-4184,-4180,-4176,-4171,-4165,-4158,-4151,-4144,-4136,-4128,
--4119,-4110,-4101,-4092,-4083,-4074,-4065,-4056,-4047,-4038,-4029,-4020,-4010,-4001,-3992,-3984,-3975,-3966,-3958,-3950,-3943,
--3936,-3931,-3926,-3922,-3919,-3917,-3917,-3919,-3922,-3926,-3932,-3940,-3950,-3961,-3974,-3989,-4004,-4021,-4039,-4058,-4078,
--4098,-4119,-4140,-4161,-4181,-4202,-4222,-4241,-4260,-4278,-4296,-4313,-4329,-4344,-4359,-4372,-4386,-4398,-4410,-4421,-4432,
--4442,-4452,-4461,-4470,-4478,-4486,-4494,-4501,-4507,-4513,-4519,-4524,-4528,-4533,-4536,-4540,-4543,-4546,-4548,-4551,-4553,
--4555,-4557,-4559,-4562,-4565,-4567,-4571,-4574,-4578,-4582,-4587,-4592,-4597,-4602,-4608,-4614,-4620,-4626,-4632,-4637,-4643,
--4648,-4653,-4658,-4663,-4666,-4670,-4673,-4676,-4678,-4680,-4681,-4683,-4683,-4684,-4685,-4685,-4685,-4686,-4686,-4686,-4686,
--4687,-4688,-4688,-4689,-4691,-4692,-4694,-4696,-4698,-4700,-4702,-4705,-4708,-4711,-4714,-4717,-4720,-4724,-4727,-4730,-4734,
--4737,-4741,-4744,-4748,-4751,-4754,-4757,-4760,-4763,-4766,-4768,-4771,-4773,-4775,-4777,-4779,-4780,-4782,-4783,-4784,-4785,
--4786,-4786,-4787,-4787,-4788,-4788,-4788,-4788,-4788,-4788,-4788,-4788,-4787,-4787,-4786,-4785,-4785,-4784,-4783,-4782,-4781,
--4780,-4779,-4778,-4777,-4776,-4775,-4775,-4774,-4774,-4774,-4774,-4775,-4776,-4777,-4778,-4779,-4781,-4783,-4785,-4787,-4789,
--4791,-4793,-4794,-4795,-4796,-4797,-4797,-4796,-4795,-4792,-4790,-4786,-4781,-4776,-4769,-4762,-4754,-4745,-4736,-4726,-4715,
--4703,-4691,-4679,-4667,-4654,-4642,-4629,-4617,-4605,-4593,-4582,-4572,-4562,-4552,-4544,-4536,-4529,-4523,-4517,-4512,-4508,
--4504,-4501,-4499,-4496,-4494,-4492,-4490,-4488,-4485,-4483,-4480,-4477,-4473,-4469,-4464,-4459,-4453,-4446,-4439,-4432,-4423,
--4415,-4406,-4397,-4387,-4378,-4368,-4358,-4348,-4339,-4329,-4320,-4312,-4303,-4295,-4288,-4281,-4274,-4268,-4262,-4257,-4252,
--4248,-4244,-4240,-4237,-4234,-4231,-4229,-4226,-4224,-4222,-4221,-4219,-4217,-4216,-4215,-4213,-4212,-4211,-4210,-4209,-4208,
--4207,-4207,-4206,-4205,-4204,-4204,-4203,-4202,-4201,-4200,-4199,-4197,-4195,-4193,-4190,-4187,-4183,-4179,-4175,-4169,-4163,
--4157,-4149,-4141,-4132,-4123,-4112,-4101,-4089,-4077,-4064,-4050,-4035,-4020,-4005,-3989,-3973,-3957,-3941,-3924,-3908,-3892,
--3876,-3860,-3845,-3831,-3816,-3803,-3790,-3777,-3765,-3754,-3743,-3732,-3722,-3712,-3702,-3693,-3683,-3674,-3664,-3655,-3645,
--3634,-3624,-3612,-3601,-3589,-3576,-3563,-3549,-3535,-3521,-3506,-3492,-3477,-3462,-3447,-3432,-3417,-3402,-3388,-3373,-3359,
--3346,-3332,-3319,-3305,-3292,-3279,-3266,-3253,-3239,-3226,-3211,-3197,-3182,-3167,-3151,-3135,-3118,-3101,-3084,-3067,-3050,
--3032,-3015,-2998,-2982,-2967,-2952,-2938,-2926,-2915,-2905,-2896,-2889,-2884,-2880,-2878,-2877,-2878,-2880,-2883,-2888,-2893,
--2899,-2906,-2913,-2920,-2928,-2935,-2942,-2949,-2956,-2961,-2967,-2971,-2975,-2978,-2981,-2983,-2984,-2984,-2984,-2983,-2982,
--2981,-2979,-2976,-2974,-2971,-2968,-2965,-2962,-2958,-2955,-2951,-2948,-2944,-2941,-2937,-2933,-2930,-2927,-2924,-2921,-2919,
--2917,-2915,-2914,-2914,-2915,-2916,-2918,-2921,-2925,-2930,-2936,-2943,-2950,-2958,-2967,-2976,-2985,-2995,-3004,-3013,-3022,
--3030,-3037,-3043,-3048,-3052,-3054,-3055,-3055,-3052,-3049,-3044,-3037,-3030,-3021,-3011,-3001,-2990,-2979,-2968,-2957,-2947,
--2937,-2927,-2919,-2911,-2905,-2900,-2895,-2892,-2890,-2889,-2888,-2889,-2890,-2891,-2893,-2895,-2897,-2899,-2901,-2903,-2904,
--2904,-2904,-2903,-2902,-2900,-2897,-2894,-2890,-2886,-2881,-2875,-2870,-2864,-2857,-2851,-2844,-2837,-2830,-2822,-2815,-2807,
--2799,-2791,-2783,-2774,-2765,-2756,-2746,-2736,-2725,-2714,-2703,-2692,-2680,-2668,-2656,-2644,-2632,-2620,-2609,-2598,-2587,
--2577,-2568,-2559,-2552,-2545,-2539,-2534,-2530,-2527,-2525,-2524,-2523,-2523,-2523,-2524,-2526,-2527,-2529,-2530,-2531,-2532,
--2532,-2531,-2530,-2527,-2523,-2519,-2513,-2505,-2496,-2486,-2474,-2461,-2446,-2430,-2413,-2394,-2374,-2353,-2331,-2309,-2286,
--2263,-2240,-2217,-2195,-2173,-2153,-2134,-2116,-2100,-2087,-2075,-2067,-2060,-2057,-2056,-2058,-2062,-2070,-2079,-2091,-2105,
--2121,-2138,-2156,-2175,-2194,-2212,-2230,-2247,-2262,-2275,-2286,-2294,-2299,-2301,-2300,-2296,-2288,-2277,-2263,-2246,-2226,
--2204,-2180,-2154,-2126,-2098,-2070,-2041,-2013,-1986,-1959,-1934,-1911,-1889,-1870,-1852,-1836,-1822,-1810,-1800,-1791,-1784,
--1778,-1772,-1768,-1764,-1761,-1757,-1754,-1751,-1747,-1744,-1740,-1736,-1732,-1728,-1724,-1721,-1717,-1715,-1713,-1712,-1712,
--1713,-1716,-1719,-1724,-1730,-1737,-1744,-1753,-1762,-1771,-1780,-1789,-1796,-1803,-1809,-1813,-1815,-1816,-1813,-1809,-1801,
--1791,-1778,-1763,-1745,-1724,-1701,-1676,-1649,-1621,-1592,-1561,-1530,-1499,-1468,-1438,-1408,-1379,-1352,-1326,-1302,-1280,
--1260,-1242,-1226,-1212,-1199,-1189,-1180,-1173,-1167,-1162,-1159,-1156,-1153,-1152,-1150,-1148,-1147,-1145,-1143,-1140,-1138,
--1134,-1131,-1127,-1123,-1118,-1113,-1108,-1103,-1098,-1094,-1089,-1085,-1081,-1077,-1074,-1071,-1069,-1067,-1066,-1065,-1065,
--1065,-1065,-1066,-1067,-1068,-1070,-1071,-1073,-1074,-1076,-1077,-1079,-1080,-1081,-1083,-1084,-1085,-1087,-1088,-1089,-1091,
--1093,-1095,-1098,-1100,-1103,-1107,-1110,-1114,-1118,-1123,-1128,-1132,-1137,-1142,-1147,-1152,-1156,-1160,-1164,-1167,-1170,
--1172,-1173,-1174,-1219,-1220,-1221,-1222,-1221,-1220,-1218,-1216,-1213,-1209,-1205,-1200,-1195,-1190,-1185,-1179,-1174,-1169,
--1163,-1159,-1154,-1150,-1146,-1142,-1139,-1136,-1134,-1132,-1130,-1128,-1125,-1123,-1121,-1119,-1116,-1112,-1109,-1104,-1099,
--1094,-1088,-1081,-1074,-1066,-1058,-1050,-1041,-1033,-1024,-1016,-1008,-1000,-993,-987,-982,-977,-974,-971,-970,-969,
--970,-971,-973,-976,-979,-982,-986,-989,-993,-996,-998,-999,-1000,-999,-996,-993,-987,-980,-971,-960,-947,
--932,-915,-897,-877,-855,-832,-807,-782,-755,-728,-700,-672,-643,-615,-586,-558,-530,-503,-476,-450,-425,
--400,-377,-354,-333,-312,-292,-274,-256,-239,-223,-209,-195,-181,-169,-158,-147,-137,-128,-120,-112,-105,
--99,-94,-89,-85,-82,-80,-78,-77,-77,-77,-78,-80,-82,-85,-89,-93,-97,-102,-107,-113,-120,
--126,-133,-140,-147,-155,-163,-171,-179,-187,-195,-204,-213,-221,-230,-239,-248,-258,-267,-277,-286,-296,
--306,-316,-325,-335,-345,-355,-364,-374,-383,-392,-400,-408,-415,-422,-429,-434,-439,-443,-447,-450,-451,
--453,-453,-453,-452,-451,-449,-447,-444,-441,-438,-434,-430,-426,-423,-419,-415,-411,-407,-403,-399,-395,
--390,-386,-381,-376,-371,-365,-359,-353,-346,-338,-330,-322,-313,-304,-294,-285,-275,-265,-256,-246,-237,
--229,-221,-214,-208,-202,-197,-194,-191,-190,-189,-189,-190,-192,-195,-198,-202,-206,-210,-214,-218,-222,
--225,-228,-230,-232,-233,-233,-232,-231,-228,-225,-221,-216,-211,-205,-199,-192,-185,-178,-171,-164,-157,
--150,-143,-137,-131,-126,-121,-117,-113,-110,-108,-106,-105,-105,-106,-107,-109,-111,-114,-118,-123,-129,
--135,-142,-150,-159,-168,-178,-189,-200,-212,-224,-237,-250,-263,-277,-290,-303,-317,-330,-343,-355,-367,
--379,-390,-401,-411,-420,-429,-438,-446,-454,-462,-470,-477,-485,-493,-501,-510,-519,-529,-539,-550,-562,
--575,-588,-603,-618,-634,-650,-667,-685,-703,-721,-740,-759,-778,-797,-815,-834,-852,-869,-887,-904,-920,
--936,-951,-967,-981,-996,-1010,-1024,-1037,-1051,-1065,-1079,-1094,-1109,-1124,-1140,-1156,-1173,-1191,-1209,-1229,-1249,
--1269,-1291,-1313,-1335,-1358,-1382,-1406,-1430,-1454,-1479,-1503,-1528,-1552,-1576,-1600,-1623,-1646,-1668,-1690,-1711,-1732,
--1752,-1771,-1790,-1809,-1827,-1844,-1862,-1878,-1895,-1911,-1928,-1944,-1960,-1975,-1991,-2007,-2023,-2038,-2054,-2070,-2086,
--2102,-2117,-2133,-2149,-2164,-2180,-2195,-2211,-2226,-2241,-2257,-2272,-2287,-2302,-2318,-2333,-2348,-2364,-2379,-2395,-2411,
--2427,-2443,-2460,-2476,-2493,-2511,-2528,-2546,-2564,-2582,-2600,-2618,-2637,-2655,-2674,-2693,-2712,-2731,-2750,-2769,-2788,
--2807,-2826,-2845,-2864,-2883,-2902,-2921,-2940,-2959,-2978,-2997,-3015,-3033,-3052,-3069,-3087,-3104,-3121,-3138,-3154,-3171,
--3186,-3202,-3217,-3232,-3247,-3262,-3277,-3292,-3308,-3324,-3340,-3356,-3374,-3392,-3411,-3430,-3451,-3472,-3495,-3518,-3542,
--3566,-3591,-3617,-3643,-3669,-3694,-3720,-3745,-3769,-3792,-3814,-3835,-3854,-3872,-3887,-3901,-3913,-3923,-3931,-3937,-3942,
--3944,-3946,-3946,-3945,-3944,-3942,-3939,-3937,-3935,-3933,-3932,-3932,-3933,-3935,-3938,-3943,-3949,-3956,-3964,-3974,-3985,
--3996,-4008,-4021,-4034,-4047,-4061,-4073,-4086,-4097,-4108,-4118,-4127,-4135,-4142,-4147,-4151,-4154,-4156,-4157,-4157,-4156,
--4155,-4153,-4150,-4147,-4144,-4140,-4137,-4133,-4130,-4126,-4123,-4120,-4118,-4115,-4113,-4111,-4108,-4106,-4104,-4102,-4100,
--4098,-4095,-4093,-4090,-4087,-4083,-4080,-4076,-4071,-4067,-4061,-4056,-4050,-4044,-4038,-4031,-4023,-4015,-4007,-3998,-3989,
--3979,-3969,-3959,-3948,-3936,-3925,-3913,-3901,-3889,-3877,-3866,-3854,-3844,-3833,-3824,-3815,-3808,-3802,-3797,-3793,-3792,
--3791,-3793,-3796,-3801,-3808,-3816,-3826,-3837,-3850,-3864,-3880,-3896,-3913,-3931,-3949,-3968,-3987,-4006,-4024,-4042,-4060,
--4077,-4094,-4110,-4126,-4140,-4154,-4167,-4180,-4192,-4203,-4214,-4224,-4234,-4244,-4253,-4263,-4272,-4281,-4290,-4298,-4307,
--4316,-4325,-4334,-4343,-4352,-4361,-4370,-4379,-4388,-4397,-4405,-4414,-4422,-4431,-4438,-4446,-4454,-4461,-4468,-4475,-4481,
--4487,-4493,-4499,-4505,-4510,-4515,-4520,-4524,-4529,-4533,-4537,-4541,-4545,-4548,-4552,-4555,-4559,-4562,-4565,-4569,-4572,
--4575,-4578,-4581,-4585,-4588,-4591,-4594,-4598,-4601,-4604,-4607,-4610,-4613,-4617,-4620,-4622,-4625,-4628,-4631,-4634,-4636,
--4639,-4641,-4644,-4646,-4648,-4651,-4653,-4656,-4658,-4661,-4663,-4666,-4668,-4671,-4673,-4676,-4679,-4681,-4684,-4687,-4689,
--4692,-4694,-4696,-4698,-4700,-4701,-4703,-4704,-4705,-4706,-4706,-4707,-4707,-4707,-4707,-4707,-4707,-4706,-4706,-4705,-4705,
--4705,-4705,-4704,-4704,-4704,-4704,-4704,-4705,-4705,-4705,-4706,-4706,-4707,-4707,-4708,-4708,-4709,-4709,-4709,-4710,-4710,
--4711,-4711,-4711,-4711,-4712,-4712,-4712,-4713,-4713,-4714,-4714,-4715,-4716,-4716,-4717,-4717,-4718,-4718,-4719,-4719,-4719,
--4718,-4717,-4716,-4714,-4711,-4708,-4704,-4699,-4694,-4687,-4680,-4673,-4664,-4654,-4644,-4634,-4622,-4611,-4598,-4586,-4573,
--4561,-4548,-4536,-4524,-4512,-4501,-4490,-4481,-4471,-4463,-4456,-4449,-4444,-4439,-4435,-4432,-4429,-4427,-4426,-4425,-4424,
--4423,-4423,-4422,-4421,-4419,-4418,-4415,-4412,-4409,-4404,-4399,-4394,-4387,-4380,-4372,-4364,-4355,-4345,-4336,-4326,-4316,
--4306,-4296,-4286,-4277,-4268,-4259,-4251,-4244,-4237,-4231,-4225,-4220,-4216,-4212,-4209,-4207,-4205,-4203,-4202,-4200,-4200,
--4199,-4198,-4197,-4197,-4196,-4195,-4194,-4193,-4192,-4190,-4188,-4187,-4185,-4183,-4180,-4178,-4176,-4173,-4171,-4169,-4166,
--4164,-4161,-4159,-4156,-4154,-4151,-4148,-4145,-4142,-4138,-4134,-4130,-4125,-4119,-4114,-4107,-4100,-4092,-4083,-4074,-4064,
--4053,-4042,-4030,-4018,-4004,-3991,-3977,-3963,-3949,-3934,-3920,-3906,-3891,-3877,-3864,-3850,-3837,-3825,-3813,-3801,-3790,
--3779,-3768,-3758,-3748,-3738,-3729,-3719,-3709,-3699,-3689,-3678,-3667,-3656,-3644,-3631,-3618,-3604,-3590,-3575,-3560,-3544,
--3527,-3510,-3493,-3476,-3458,-3440,-3423,-3405,-3388,-3371,-3354,-3338,-3322,-3306,-3290,-3275,-3260,-3246,-3232,-3217,-3203,
--3189,-3175,-3161,-3147,-3133,-3119,-3104,-3090,-3075,-3060,-3046,-3031,-3017,-3002,-2988,-2975,-2962,-2950,-2939,-2928,-2919,
--2911,-2904,-2898,-2894,-2891,-2889,-2888,-2889,-2891,-2894,-2897,-2902,-2907,-2913,-2920,-2926,-2933,-2940,-2946,-2952,-2958,
--2964,-2969,-2973,-2977,-2980,-2982,-2984,-2985,-2986,-2986,-2985,-2984,-2982,-2980,-2977,-2975,-2972,-2968,-2965,-2962,-2958,
--2954,-2950,-2947,-2943,-2939,-2935,-2932,-2928,-2925,-2922,-2919,-2916,-2914,-2912,-2910,-2910,-2909,-2910,-2911,-2912,-2915,
--2918,-2922,-2927,-2932,-2938,-2945,-2952,-2959,-2966,-2974,-2981,-2988,-2995,-3001,-3006,-3010,-3014,-3016,-3017,-3017,-3015,
--3013,-3009,-3003,-2997,-2989,-2981,-2972,-2962,-2952,-2942,-2932,-2921,-2912,-2902,-2894,-2886,-2879,-2873,-2868,-2864,-2861,
--2859,-2858,-2858,-2859,-2861,-2862,-2865,-2867,-2869,-2872,-2873,-2875,-2876,-2876,-2875,-2874,-2871,-2868,-2864,-2858,-2852,
--2845,-2838,-2829,-2820,-2811,-2801,-2791,-2781,-2770,-2760,-2750,-2740,-2731,-2722,-2713,-2704,-2696,-2688,-2681,-2674,-2668,
--2661,-2656,-2650,-2644,-2639,-2634,-2629,-2624,-2619,-2614,-2609,-2604,-2599,-2594,-2590,-2585,-2580,-2575,-2570,-2565,-2561,
--2556,-2551,-2546,-2542,-2537,-2532,-2527,-2522,-2517,-2511,-2506,-2500,-2493,-2486,-2479,-2470,-2462,-2452,-2442,-2430,-2418,
--2406,-2392,-2377,-2361,-2345,-2328,-2310,-2292,-2273,-2253,-2234,-2214,-2194,-2175,-2156,-2138,-2120,-2104,-2089,-2075,-2063,
--2053,-2045,-2038,-2034,-2032,-2032,-2034,-2039,-2045,-2053,-2063,-2075,-2087,-2101,-2115,-2130,-2144,-2159,-2173,-2185,-2197,
--2207,-2215,-2221,-2224,-2225,-2224,-2220,-2214,-2205,-2194,-2180,-2164,-2147,-2127,-2106,-2085,-2062,-2039,-2016,-1992,-1970,
--1947,-1926,-1906,-1887,-1869,-1853,-1838,-1824,-1812,-1802,-1792,-1784,-1776,-1770,-1764,-1758,-1754,-1749,-1745,-1741,-1737,
--1733,-1729,-1725,-1721,-1718,-1715,-1712,-1710,-1708,-1707,-1707,-1708,-1710,-1713,-1717,-1722,-1728,-1735,-1743,-1751,-1760,
--1770,-1779,-1788,-1797,-1805,-1812,-1818,-1822,-1824,-1825,-1823,-1819,-1813,-1805,-1793,-1780,-1764,-1746,-1725,-1703,-1679,
--1654,-1627,-1600,-1572,-1544,-1516,-1489,-1462,-1435,-1410,-1387,-1365,-1344,-1325,-1309,-1293,-1280,-1268,-1259,-1250,-1243,
--1238,-1233,-1229,-1226,-1224,-1222,-1220,-1219,-1217,-1215,-1213,-1210,-1207,-1204,-1200,-1196,-1191,-1186,-1181,-1175,-1169,
--1164,-1158,-1153,-1148,-1143,-1139,-1135,-1131,-1129,-1127,-1125,-1124,-1124,-1124,-1125,-1126,-1127,-1129,-1131,-1133,-1136,
--1138,-1140,-1142,-1144,-1146,-1147,-1148,-1150,-1150,-1151,-1152,-1152,-1153,-1153,-1154,-1154,-1155,-1156,-1158,-1160,-1162,
--1164,-1167,-1170,-1174,-1177,-1181,-1186,-1190,-1194,-1199,-1203,-1207,-1211,-1214,-1217,-1219,-1265,-1269,-1271,-1274,-1275,
--1276,-1277,-1276,-1275,-1274,-1272,-1269,-1265,-1262,-1257,-1253,-1248,-1243,-1238,-1233,-1228,-1223,-1219,-1214,-1209,-1205,
--1201,-1196,-1192,-1188,-1184,-1180,-1175,-1171,-1166,-1161,-1155,-1149,-1143,-1136,-1130,-1122,-1115,-1107,-1100,-1092,-1084,
--1076,-1069,-1062,-1056,-1050,-1045,-1040,-1037,-1034,-1032,-1032,-1032,-1033,-1035,-1038,-1041,-1045,-1050,-1054,-1059,-1064,
--1068,-1071,-1074,-1076,-1077,-1077,-1075,-1071,-1066,-1059,-1051,-1040,-1028,-1013,-997,-979,-959,-938,-916,-892,-867,
--841,-814,-787,-759,-732,-704,-676,-648,-621,-595,-569,-544,-519,-496,-473,-452,-431,-411,-393,-375,-358,
--343,-328,-314,-301,-288,-277,-266,-256,-247,-238,-230,-223,-216,-210,-205,-200,-196,-193,-190,-188,-186,
--185,-184,-185,-185,-187,-188,-191,-193,-197,-200,-204,-209,-214,-219,-225,-230,-237,-243,-250,-257,-264,
--272,-279,-287,-296,-304,-313,-322,-332,-341,-351,-361,-371,-381,-392,-402,-413,-423,-433,-443,-453,-462,
--471,-479,-487,-495,-501,-508,-513,-517,-521,-524,-527,-528,-529,-529,-528,-527,-525,-523,-520,-517,-513,
--509,-506,-502,-498,-493,-489,-485,-481,-477,-473,-469,-465,-461,-457,-453,-449,-444,-440,-435,-430,-424,
--419,-413,-407,-400,-394,-387,-381,-374,-367,-361,-354,-348,-343,-338,-333,-330,-326,-324,-322,-321,-321,
--321,-322,-323,-325,-328,-330,-333,-336,-339,-341,-344,-346,-347,-348,-348,-347,-345,-343,-340,-336,-331,
--325,-319,-312,-304,-296,-288,-279,-271,-262,-254,-246,-239,-232,-226,-220,-216,-212,-209,-207,-206,-207,
--208,-210,-213,-217,-223,-228,-235,-243,-251,-260,-270,-280,-291,-302,-313,-325,-338,-350,-363,-376,-389,
--402,-415,-429,-442,-455,-468,-481,-493,-506,-518,-530,-541,-552,-563,-573,-583,-593,-603,-612,-621,-630,
--639,-647,-656,-665,-673,-682,-691,-701,-711,-721,-731,-742,-753,-765,-777,-790,-803,-816,-830,-844,-859,
--873,-888,-903,-917,-932,-947,-961,-976,-990,-1004,-1018,-1032,-1045,-1058,-1071,-1084,-1097,-1109,-1122,-1135,-1147,
--1160,-1174,-1187,-1201,-1215,-1230,-1245,-1260,-1276,-1293,-1310,-1327,-1345,-1364,-1383,-1402,-1422,-1442,-1462,-1482,-1502,
--1523,-1543,-1564,-1584,-1604,-1624,-1644,-1663,-1683,-1702,-1720,-1739,-1757,-1775,-1792,-1809,-1827,-1843,-1860,-1877,-1893,
--1909,-1926,-1942,-1958,-1973,-1989,-2005,-2021,-2036,-2052,-2067,-2082,-2098,-2113,-2128,-2142,-2157,-2172,-2186,-2201,-2215,
--2230,-2244,-2258,-2273,-2288,-2302,-2317,-2332,-2347,-2363,-2378,-2395,-2411,-2428,-2444,-2462,-2479,-2497,-2515,-2534,-2552,
--2571,-2590,-2609,-2629,-2648,-2667,-2687,-2706,-2726,-2745,-2764,-2783,-2803,-2822,-2841,-2860,-2878,-2897,-2916,-2934,-2952,
--2971,-2989,-3007,-3025,-3042,-3060,-3077,-3094,-3110,-3127,-3143,-3159,-3174,-3190,-3205,-3220,-3234,-3249,-3263,-3277,-3291,
--3305,-3320,-3334,-3349,-3364,-3380,-3396,-3412,-3429,-3447,-3465,-3484,-3503,-3523,-3544,-3564,-3585,-3606,-3628,-3649,-3670,
--3690,-3710,-3730,-3748,-3766,-3782,-3797,-3811,-3824,-3835,-3844,-3853,-3860,-3865,-3870,-3873,-3875,-3876,-3877,-3877,-3877,
--3876,-3876,-3876,-3876,-3877,-3878,-3881,-3884,-3888,-3893,-3899,-3906,-3914,-3923,-3932,-3943,-3954,-3965,-3977,-3989,-4001,
--4013,-4024,-4035,-4046,-4055,-4064,-4072,-4079,-4085,-4090,-4094,-4096,-4098,-4098,-4098,-4096,-4094,-4091,-4087,-4083,-4078,
--4073,-4067,-4062,-4057,-4051,-4046,-4041,-4037,-4033,-4029,-4026,-4024,-4022,-4020,-4019,-4019,-4019,-4019,-4019,-4020,-4021,
--4022,-4022,-4022,-4022,-4021,-4020,-4018,-4014,-4010,-4004,-3998,-3990,-3980,-3969,-3957,-3944,-3929,-3913,-3895,-3877,-3858,
--3838,-3818,-3797,-3777,-3757,-3737,-3718,-3700,-3683,-3667,-3653,-3641,-3631,-3623,-3617,-3614,-3612,-3613,-3616,-3622,-3629,
--3638,-3649,-3661,-3675,-3690,-3706,-3723,-3740,-3757,-3775,-3792,-3809,-3825,-3841,-3856,-3871,-3885,-3897,-3910,-3921,-3932,
--3942,-3952,-3961,-3970,-3979,-3987,-3996,-4005,-4015,-4025,-4036,-4047,-4059,-4071,-4085,-4099,-4114,-4129,-4145,-4161,-4178,
--4196,-4213,-4230,-4248,-4265,-4282,-4298,-4314,-4329,-4343,-4357,-4369,-4381,-4392,-4401,-4410,-4418,-4425,-4431,-4436,-4441,
--4445,-4448,-4451,-4454,-4456,-4458,-4460,-4462,-4464,-4466,-4469,-4472,-4475,-4478,-4481,-4485,-4489,-4494,-4498,-4503,-4508,
--4513,-4518,-4523,-4529,-4534,-4538,-4543,-4548,-4552,-4556,-4560,-4564,-4567,-4570,-4573,-4576,-4579,-4582,-4585,-4587,-4590,
--4593,-4596,-4599,-4602,-4605,-4609,-4612,-4616,-4619,-4623,-4626,-4630,-4633,-4637,-4640,-4643,-4645,-4647,-4649,-4650,-4651,
--4652,-4652,-4652,-4651,-4650,-4649,-4647,-4645,-4643,-4641,-4639,-4636,-4634,-4632,-4630,-4628,-4627,-4625,-4624,-4623,-4623,
--4623,-4623,-4623,-4623,-4624,-4625,-4626,-4627,-4628,-4629,-4630,-4630,-4631,-4631,-4631,-4632,-4631,-4631,-4631,-4630,-4629,
--4628,-4627,-4626,-4625,-4624,-4624,-4623,-4622,-4622,-4621,-4621,-4621,-4620,-4620,-4620,-4619,-4619,-4618,-4617,-4615,-4613,
--4611,-4608,-4604,-4599,-4594,-4588,-4581,-4574,-4566,-4557,-4547,-4537,-4527,-4516,-4504,-4493,-4481,-4470,-4459,-4448,-4438,
--4428,-4418,-4410,-4402,-4395,-4389,-4383,-4379,-4375,-4372,-4370,-4368,-4367,-4366,-4366,-4366,-4365,-4365,-4365,-4364,-4363,
--4362,-4360,-4357,-4354,-4350,-4346,-4341,-4335,-4329,-4322,-4315,-4308,-4300,-4293,-4285,-4277,-4269,-4262,-4255,-4248,-4242,
--4236,-4231,-4226,-4222,-4218,-4214,-4211,-4209,-4206,-4204,-4202,-4200,-4198,-4197,-4195,-4193,-4190,-4188,-4185,-4182,-4178,
--4174,-4170,-4166,-4161,-4156,-4151,-4146,-4141,-4135,-4130,-4125,-4119,-4114,-4109,-4105,-4100,-4096,-4091,-4087,-4083,-4079,
--4075,-4071,-4067,-4063,-4059,-4054,-4049,-4043,-4037,-4031,-4023,-4016,-4007,-3998,-3989,-3979,-3968,-3957,-3946,-3934,-3922,
--3910,-3897,-3885,-3872,-3860,-3847,-3836,-3824,-3813,-3802,-3791,-3781,-3772,-3762,-3753,-3745,-3736,-3728,-3720,-3712,-3703,
--3695,-3686,-3677,-3668,-3657,-3647,-3636,-3624,-3611,-3598,-3584,-3569,-3553,-3537,-3520,-3503,-3486,-3467,-3449,-3430,-3411,
--3392,-3373,-3354,-3336,-3317,-3299,-3280,-3262,-3245,-3227,-3210,-3194,-3177,-3161,-3145,-3130,-3115,-3100,-3086,-3071,-3058,
--3044,-3031,-3019,-3007,-2996,-2985,-2975,-2966,-2957,-2949,-2943,-2937,-2932,-2928,-2925,-2923,-2922,-2922,-2923,-2924,-2927,
--2930,-2933,-2937,-2941,-2946,-2950,-2955,-2959,-2964,-2968,-2971,-2974,-2977,-2979,-2980,-2981,-2981,-2980,-2979,-2977,-2975,
--2972,-2969,-2966,-2962,-2957,-2953,-2949,-2944,-2940,-2935,-2931,-2926,-2922,-2918,-2914,-2910,-2907,-2904,-2901,-2898,-2896,
--2894,-2892,-2890,-2889,-2888,-2887,-2887,-2887,-2888,-2889,-2890,-2892,-2895,-2897,-2900,-2904,-2908,-2912,-2916,-2920,-2924,
--2929,-2933,-2936,-2940,-2943,-2945,-2946,-2947,-2947,-2946,-2944,-2941,-2937,-2932,-2926,-2919,-2912,-2903,-2894,-2885,-2875,
--2865,-2855,-2846,-2836,-2827,-2818,-2811,-2804,-2797,-2792,-2788,-2784,-2782,-2781,-2780,-2780,-2781,-2782,-2783,-2785,-2787,
--2788,-2790,-2791,-2791,-2790,-2789,-2787,-2784,-2780,-2774,-2768,-2760,-2752,-2742,-2732,-2721,-2710,-2698,-2686,-2673,-2661,
--2649,-2638,-2626,-2616,-2606,-2598,-2590,-2583,-2578,-2573,-2570,-2568,-2567,-2567,-2567,-2569,-2571,-2574,-2577,-2581,-2584,
--2588,-2591,-2594,-2597,-2599,-2600,-2600,-2600,-2598,-2596,-2592,-2587,-2581,-2574,-2565,-2556,-2545,-2533,-2521,-2507,-2493,
--2478,-2462,-2445,-2428,-2411,-2394,-2376,-2358,-2340,-2322,-2304,-2287,-2269,-2252,-2235,-2219,-2203,-2187,-2172,-2158,-2144,
--2131,-2118,-2106,-2095,-2085,-2076,-2067,-2059,-2053,-2047,-2042,-2039,-2036,-2035,-2034,-2035,-2036,-2039,-2042,-2046,-2051,
--2057,-2063,-2070,-2076,-2083,-2090,-2097,-2103,-2109,-2114,-2118,-2122,-2124,-2125,-2125,-2123,-2120,-2116,-2110,-2103,-2094,
--2084,-2074,-2062,-2049,-2036,-2022,-2007,-1993,-1978,-1964,-1949,-1935,-1922,-1908,-1896,-1884,-1873,-1863,-1853,-1844,-1836,
--1828,-1821,-1814,-1808,-1802,-1796,-1790,-1784,-1779,-1773,-1767,-1762,-1756,-1750,-1745,-1740,-1735,-1730,-1726,-1722,-1719,
--1717,-1716,-1716,-1717,-1719,-1722,-1726,-1731,-1737,-1744,-1751,-1760,-1769,-1778,-1787,-1795,-1804,-1812,-1819,-1825,-1829,
--1832,-1834,-1834,-1832,-1828,-1822,-1814,-1804,-1792,-1778,-1763,-1746,-1728,-1709,-1688,-1668,-1647,-1625,-1604,-1583,-1563,
--1543,-1525,-1507,-1490,-1475,-1461,-1448,-1437,-1427,-1418,-1410,-1403,-1397,-1392,-1387,-1383,-1379,-1375,-1371,-1367,-1363,
--1358,-1353,-1348,-1341,-1335,-1327,-1320,-1312,-1303,-1294,-1285,-1276,-1267,-1258,-1249,-1240,-1232,-1225,-1218,-1212,-1207,
--1203,-1199,-1196,-1195,-1193,-1193,-1193,-1194,-1195,-1197,-1199,-1201,-1204,-1206,-1208,-1210,-1212,-1214,-1215,-1216,-1217,
--1217,-1217,-1216,-1216,-1215,-1214,-1213,-1212,-1211,-1211,-1211,-1211,-1211,-1212,-1213,-1215,-1217,-1220,-1223,-1227,-1231,
--1235,-1239,-1244,-1248,-1253,-1257,-1261,-1265,-1316,-1320,-1324,-1327,-1330,-1331,-1333,-1333,-1333,-1332,-1331,-1329,-1326,
--1323,-1319,-1314,-1310,-1305,-1299,-1294,-1288,-1283,-1277,-1271,-1266,-1260,-1255,-1249,-1244,-1239,-1234,-1228,-1223,-1218,
--1212,-1207,-1201,-1195,-1189,-1183,-1177,-1171,-1164,-1157,-1151,-1144,-1138,-1132,-1126,-1121,-1116,-1111,-1108,-1105,-1102,
--1101,-1100,-1100,-1101,-1102,-1104,-1107,-1111,-1115,-1119,-1123,-1128,-1132,-1136,-1140,-1142,-1145,-1146,-1145,-1144,-1141,
--1137,-1131,-1123,-1114,-1102,-1089,-1075,-1058,-1040,-1021,-1000,-978,-954,-930,-905,-879,-852,-826,-799,-772,-746,
--719,-693,-668,-643,-619,-596,-574,-552,-532,-513,-494,-477,-461,-445,-431,-418,-405,-394,-383,-373,-363,
--355,-347,-340,-333,-327,-321,-316,-312,-307,-304,-301,-298,-296,-294,-292,-292,-291,-291,-292,-292,-294,
--296,-298,-301,-304,-308,-312,-317,-322,-328,-334,-341,-348,-356,-364,-372,-381,-391,-400,-411,-421,-432,
--443,-454,-465,-476,-488,-499,-510,-521,-532,-542,-552,-561,-570,-579,-586,-593,-600,-605,-610,-614,-617,
--619,-621,-622,-622,-621,-620,-618,-616,-614,-611,-607,-604,-600,-596,-592,-588,-584,-579,-575,-571,-567,
--563,-559,-555,-551,-547,-543,-539,-535,-531,-526,-522,-517,-512,-508,-503,-498,-493,-488,-483,-479,-474,
--470,-467,-463,-461,-459,-457,-456,-455,-455,-456,-458,-460,-462,-465,-468,-472,-475,-479,-483,-486,-489,
--492,-493,-495,-495,-495,-493,-491,-487,-482,-477,-470,-462,-453,-444,-434,-423,-411,-400,-388,-376,-365,
--353,-343,-333,-324,-316,-309,-303,-299,-296,-295,-295,-296,-299,-304,-310,-318,-327,-337,-348,-361,-374,
--388,-403,-419,-435,-451,-468,-484,-501,-518,-534,-551,-567,-583,-598,-613,-628,-642,-656,-669,-682,-694,
--706,-717,-728,-739,-750,-760,-769,-779,-789,-798,-807,-816,-825,-834,-843,-852,-862,-871,-881,-890,-900,
--910,-920,-930,-940,-951,-961,-972,-983,-994,-1005,-1016,-1027,-1038,-1049,-1060,-1071,-1082,-1093,-1104,-1114,-1125,
--1136,-1147,-1157,-1168,-1179,-1190,-1201,-1212,-1224,-1235,-1247,-1259,-1271,-1284,-1297,-1310,-1323,-1337,-1351,-1365,-1380,
--1395,-1410,-1426,-1441,-1457,-1473,-1489,-1505,-1521,-1537,-1553,-1569,-1585,-1601,-1617,-1633,-1649,-1665,-1680,-1696,-1712,
--1727,-1742,-1758,-1773,-1789,-1804,-1820,-1835,-1851,-1867,-1882,-1898,-1914,-1930,-1946,-1961,-1977,-1993,-2008,-2024,-2039,
--2054,-2069,-2084,-2099,-2113,-2127,-2141,-2155,-2169,-2182,-2195,-2209,-2222,-2235,-2249,-2262,-2276,-2289,-2303,-2318,-2333,
--2348,-2363,-2379,-2395,-2412,-2429,-2447,-2465,-2484,-2503,-2522,-2541,-2561,-2581,-2601,-2621,-2641,-2661,-2682,-2702,-2722,
--2742,-2762,-2781,-2801,-2820,-2839,-2858,-2877,-2895,-2914,-2932,-2950,-2968,-2986,-3004,-3022,-3039,-3057,-3074,-3092,-3109,
--3126,-3142,-3159,-3176,-3192,-3208,-3223,-3239,-3254,-3269,-3284,-3298,-3313,-3327,-3341,-3355,-3369,-3383,-3396,-3410,-3424,
--3439,-3453,-3467,-3482,-3497,-3512,-3527,-3543,-3559,-3574,-3590,-3606,-3621,-3637,-3652,-3667,-3681,-3695,-3708,-3720,-3732,
--3743,-3753,-3762,-3770,-3777,-3783,-3789,-3794,-3797,-3801,-3804,-3806,-3808,-3809,-3811,-3813,-3814,-3817,-3819,-3822,-3825,
--3829,-3834,-3840,-3846,-3853,-3861,-3869,-3878,-3888,-3898,-3908,-3919,-3929,-3940,-3950,-3961,-3970,-3979,-3988,-3995,-4002,
--4008,-4012,-4016,-4018,-4019,-4020,-4019,-4017,-4014,-4010,-4006,-4001,-3996,-3990,-3984,-3978,-3972,-3966,-3961,-3957,-3953,
--3949,-3947,-3945,-3945,-3945,-3946,-3948,-3951,-3954,-3958,-3963,-3967,-3972,-3977,-3981,-3985,-3988,-3991,-3992,-3991,-3989,
--3986,-3980,-3973,-3964,-3952,-3938,-3922,-3904,-3884,-3863,-3839,-3814,-3788,-3761,-3733,-3704,-3676,-3648,-3620,-3593,-3567,
--3543,-3521,-3500,-3482,-3465,-3452,-3441,-3433,-3428,-3425,-3425,-3427,-3432,-3439,-3448,-3459,-3471,-3485,-3499,-3515,-3531,
--3547,-3564,-3580,-3596,-3611,-3626,-3640,-3653,-3666,-3677,-3688,-3698,-3708,-3717,-3725,-3734,-3742,-3750,-3759,-3768,-3778,
--3789,-3801,-3813,-3827,-3842,-3858,-3875,-3894,-3914,-3934,-3956,-3978,-4001,-4025,-4049,-4073,-4097,-4121,-4144,-4167,-4188,
--4209,-4229,-4248,-4265,-4281,-4296,-4309,-4321,-4331,-4340,-4348,-4355,-4361,-4366,-4370,-4373,-4376,-4378,-4381,-4383,-4385,
--4387,-4390,-4392,-4395,-4398,-4402,-4406,-4410,-4415,-4420,-4425,-4430,-4436,-4441,-4447,-4452,-4457,-4462,-4467,-4471,-4475,
--4479,-4483,-4486,-4489,-4491,-4494,-4496,-4498,-4500,-4503,-4505,-4508,-4510,-4513,-4516,-4520,-4524,-4528,-4533,-4538,-4543,
--4549,-4555,-4561,-4567,-4572,-4578,-4584,-4589,-4594,-4599,-4603,-4606,-4609,-4611,-4612,-4613,-4613,-4612,-4611,-4609,-4607,
--4604,-4600,-4597,-4593,-4589,-4584,-4580,-4576,-4572,-4569,-4566,-4563,-4560,-4558,-4556,-4555,-4554,-4554,-4553,-4553,-4554,
--4554,-4555,-4556,-4556,-4557,-4557,-4558,-4558,-4558,-4558,-4558,-4558,-4557,-4556,-4555,-4554,-4553,-4552,-4551,-4550,-4549,
--4548,-4547,-4546,-4545,-4545,-4544,-4544,-4543,-4543,-4542,-4542,-4541,-4540,-4538,-4537,-4534,-4532,-4528,-4524,-4520,-4515,
--4509,-4503,-4496,-4488,-4480,-4471,-4462,-4453,-4443,-4433,-4424,-4414,-4404,-4395,-4386,-4378,-4370,-4363,-4356,-4350,-4344,
--4340,-4336,-4332,-4329,-4327,-4325,-4324,-4323,-4322,-4321,-4320,-4320,-4319,-4318,-4316,-4315,-4313,-4310,-4307,-4304,-4300,
--4296,-4292,-4287,-4282,-4277,-4272,-4266,-4261,-4255,-4250,-4244,-4239,-4235,-4230,-4226,-4222,-4218,-4215,-4211,-4208,-4205,
--4202,-4200,-4197,-4194,-4191,-4188,-4184,-4180,-4176,-4172,-4167,-4162,-4156,-4150,-4143,-4137,-4130,-4122,-4115,-4107,-4100,
--4092,-4085,-4077,-4070,-4063,-4056,-4049,-4043,-4037,-4032,-4027,-4022,-4017,-4012,-4008,-4003,-3999,-3995,-3990,-3985,-3980,
--3975,-3969,-3963,-3956,-3949,-3941,-3932,-3923,-3914,-3904,-3894,-3883,-3872,-3860,-3849,-3837,-3825,-3814,-3802,-3791,-3780,
--3770,-3760,-3750,-3741,-3732,-3724,-3717,-3709,-3703,-3696,-3690,-3685,-3679,-3674,-3668,-3662,-3657,-3650,-3644,-3636,-3629,
--3620,-3611,-3601,-3591,-3579,-3567,-3553,-3539,-3524,-3508,-3491,-3473,-3455,-3436,-3416,-3396,-3376,-3355,-3334,-3312,-3291,
--3269,-3248,-3227,-3206,-3185,-3164,-3145,-3125,-3107,-3088,-3071,-3055,-3039,-3024,-3011,-2998,-2986,-2976,-2966,-2958,-2951,
--2945,-2940,-2937,-2934,-2933,-2932,-2933,-2934,-2936,-2939,-2942,-2946,-2950,-2955,-2960,-2964,-2969,-2973,-2977,-2981,-2984,
--2987,-2989,-2990,-2991,-2991,-2990,-2989,-2987,-2984,-2981,-2977,-2972,-2968,-2962,-2957,-2951,-2946,-2940,-2934,-2928,-2923,
--2918,-2913,-2908,-2904,-2900,-2896,-2893,-2890,-2887,-2885,-2884,-2882,-2881,-2880,-2880,-2880,-2880,-2880,-2881,-2882,-2883,
--2884,-2885,-2887,-2889,-2891,-2893,-2895,-2897,-2899,-2901,-2903,-2904,-2906,-2907,-2908,-2908,-2908,-2908,-2906,-2905,-2902,
--2899,-2894,-2889,-2884,-2877,-2870,-2861,-2853,-2843,-2833,-2823,-2812,-2801,-2790,-2778,-2767,-2757,-2746,-2737,-2727,-2719,
--2711,-2704,-2697,-2692,-2687,-2683,-2680,-2678,-2676,-2675,-2674,-2673,-2673,-2672,-2672,-2671,-2669,-2668,-2665,-2662,-2658,
--2653,-2648,-2642,-2635,-2627,-2618,-2609,-2599,-2589,-2579,-2568,-2558,-2548,-2539,-2530,-2521,-2514,-2508,-2503,-2499,-2496,
--2495,-2495,-2497,-2499,-2504,-2509,-2515,-2523,-2531,-2540,-2549,-2558,-2568,-2577,-2585,-2593,-2600,-2606,-2610,-2613,-2615,
--2614,-2612,-2607,-2601,-2592,-2581,-2568,-2553,-2537,-2518,-2497,-2475,-2452,-2428,-2402,-2376,-2349,-2322,-2294,-2267,-2241,
--2214,-2189,-2165,-2141,-2119,-2098,-2079,-2062,-2046,-2032,-2019,-2009,-2000,-1992,-1987,-1983,-1980,-1979,-1980,-1981,-1984,
--1987,-1991,-1996,-2001,-2007,-2013,-2019,-2026,-2032,-2037,-2043,-2048,-2052,-2056,-2059,-2062,-2063,-2064,-2064,-2063,-2061,
--2059,-2055,-2051,-2046,-2040,-2033,-2026,-2018,-2010,-2002,-1993,-1984,-1975,-1965,-1956,-1947,-1938,-1930,-1921,-1913,-1906,
--1899,-1892,-1886,-1880,-1875,-1870,-1865,-1861,-1857,-1853,-1849,-1845,-1841,-1837,-1832,-1828,-1823,-1818,-1812,-1806,-1800,
--1793,-1786,-1779,-1772,-1765,-1758,-1751,-1744,-1738,-1732,-1727,-1723,-1720,-1717,-1716,-1715,-1716,-1718,-1721,-1725,-1730,
--1736,-1742,-1750,-1757,-1766,-1774,-1783,-1791,-1799,-1806,-1813,-1818,-1823,-1827,-1829,-1829,-1829,-1827,-1823,-1818,-1811,
--1803,-1794,-1784,-1772,-1760,-1747,-1733,-1720,-1706,-1692,-1678,-1664,-1651,-1639,-1627,-1616,-1605,-1596,-1587,-1579,-1572,
--1565,-1559,-1553,-1548,-1543,-1539,-1534,-1529,-1524,-1518,-1512,-1506,-1499,-1491,-1483,-1474,-1464,-1453,-1443,-1431,-1419,
--1407,-1395,-1382,-1370,-1358,-1346,-1334,-1323,-1313,-1304,-1295,-1287,-1281,-1275,-1270,-1266,-1263,-1261,-1260,-1259,-1259,
--1260,-1261,-1262,-1263,-1265,-1267,-1268,-1270,-1271,-1272,-1272,-1273,-1273,-1272,-1271,-1270,-1269,-1268,-1266,-1264,-1263,
--1262,-1260,-1260,-1259,-1259,-1260,-1261,-1262,-1264,-1267,-1270,-1274,-1278,-1282,-1287,-1292,-1297,-1302,-1307,-1311,-1316,
--1364,-1369,-1372,-1375,-1378,-1380,-1381,-1381,-1381,-1380,-1378,-1376,-1373,-1369,-1365,-1360,-1355,-1350,-1344,-1338,-1332,
--1326,-1320,-1314,-1308,-1303,-1297,-1291,-1286,-1281,-1276,-1271,-1266,-1261,-1256,-1251,-1246,-1241,-1236,-1231,-1226,-1220,
--1215,-1209,-1204,-1198,-1193,-1188,-1182,-1178,-1173,-1169,-1165,-1162,-1159,-1157,-1155,-1154,-1154,-1154,-1155,-1156,-1158,
--1160,-1163,-1165,-1168,-1171,-1174,-1176,-1178,-1180,-1181,-1180,-1179,-1177,-1174,-1169,-1163,-1155,-1146,-1135,-1123,-1109,
--1094,-1077,-1059,-1040,-1019,-997,-975,-951,-927,-903,-878,-853,-827,-802,-778,-753,-729,-706,-683,-662,-641,
--621,-602,-584,-567,-551,-536,-522,-509,-496,-485,-475,-466,-457,-449,-442,-435,-429,-423,-418,-413,-409,
--405,-401,-398,-395,-392,-389,-387,-386,-384,-383,-383,-382,-383,-383,-385,-386,-389,-392,-395,-399,-404,
--410,-416,-423,-430,-438,-447,-456,-465,-476,-486,-497,-509,-520,-532,-544,-556,-568,-579,-591,-602,-613,
--623,-633,-642,-651,-659,-666,-673,-678,-683,-687,-691,-693,-695,-696,-697,-696,-696,-694,-693,-691,-688,
--685,-682,-679,-676,-672,-669,-665,-662,-658,-655,-652,-648,-645,-641,-638,-634,-630,-627,-623,-619,-615,
--611,-606,-602,-597,-593,-588,-583,-579,-574,-570,-566,-562,-559,-556,-554,-552,-551,-550,-550,-551,-552,
--554,-557,-560,-564,-568,-573,-578,-583,-588,-593,-597,-602,-605,-608,-611,-612,-612,-612,-610,-607,-602,
--597,-590,-582,-573,-563,-552,-540,-528,-515,-502,-488,-475,-462,-450,-438,-427,-417,-408,-401,-395,-391,
--388,-387,-388,-390,-394,-401,-408,-418,-429,-441,-455,-470,-486,-503,-520,-538,-557,-576,-595,-614,-633,
--652,-670,-689,-706,-723,-739,-755,-770,-784,-798,-811,-824,-835,-847,-858,-868,-878,-888,-897,-906,-916,
--925,-934,-942,-951,-961,-970,-979,-988,-998,-1007,-1017,-1027,-1037,-1047,-1057,-1067,-1077,-1087,-1097,-1107,-1117,
--1127,-1136,-1146,-1156,-1165,-1174,-1183,-1193,-1202,-1211,-1220,-1229,-1238,-1247,-1256,-1266,-1276,-1286,-1296,-1306,-1317,
--1328,-1339,-1351,-1362,-1375,-1387,-1400,-1413,-1426,-1439,-1453,-1467,-1481,-1494,-1508,-1522,-1536,-1550,-1563,-1577,-1590,
--1604,-1617,-1630,-1643,-1656,-1669,-1682,-1694,-1707,-1720,-1732,-1745,-1758,-1771,-1785,-1798,-1812,-1826,-1840,-1855,-1869,
--1884,-1899,-1914,-1930,-1945,-1960,-1976,-1991,-2007,-2022,-2037,-2052,-2067,-2081,-2095,-2109,-2123,-2136,-2149,-2162,-2174,
--2186,-2198,-2210,-2222,-2234,-2246,-2258,-2270,-2283,-2296,-2309,-2323,-2337,-2352,-2367,-2382,-2399,-2416,-2433,-2451,-2469,
--2488,-2508,-2527,-2547,-2567,-2588,-2608,-2629,-2650,-2670,-2691,-2711,-2731,-2751,-2771,-2790,-2810,-2828,-2847,-2865,-2884,
--2902,-2919,-2937,-2954,-2972,-2989,-3006,-3023,-3041,-3058,-3075,-3092,-3109,-3127,-3144,-3161,-3178,-3195,-3212,-3229,-3246,
--3263,-3279,-3295,-3311,-3327,-3342,-3357,-3372,-3386,-3400,-3414,-3428,-3441,-3454,-3466,-3479,-3491,-3503,-3515,-3526,-3538,
--3549,-3560,-3571,-3582,-3592,-3603,-3613,-3623,-3632,-3642,-3650,-3659,-3667,-3675,-3683,-3690,-3696,-3702,-3708,-3713,-3718,
--3722,-3727,-3731,-3735,-3738,-3742,-3745,-3749,-3753,-3756,-3761,-3765,-3770,-3775,-3780,-3786,-3792,-3799,-3806,-3814,-3821,
--3829,-3838,-3846,-3854,-3863,-3871,-3879,-3886,-3893,-3900,-3906,-3911,-3915,-3919,-3922,-3924,-3925,-3925,-3924,-3923,-3920,
--3917,-3914,-3910,-3906,-3901,-3896,-3892,-3887,-3883,-3879,-3876,-3873,-3871,-3870,-3870,-3870,-3872,-3874,-3877,-3880,-3884,
--3889,-3894,-3899,-3905,-3910,-3914,-3918,-3922,-3924,-3925,-3924,-3922,-3918,-3913,-3905,-3895,-3883,-3869,-3852,-3834,-3813,
--3791,-3767,-3741,-3715,-3687,-3658,-3629,-3600,-3570,-3542,-3514,-3487,-3461,-3437,-3415,-3395,-3377,-3361,-3348,-3338,-3329,
--3324,-3321,-3321,-3322,-3326,-3332,-3340,-3349,-3360,-3372,-3384,-3397,-3411,-3425,-3438,-3452,-3465,-3478,-3490,-3502,-3513,
--3524,-3534,-3543,-3552,-3561,-3570,-3579,-3587,-3597,-3606,-3617,-3628,-3640,-3653,-3667,-3683,-3700,-3718,-3737,-3758,-3780,
--3803,-3827,-3851,-3877,-3903,-3929,-3955,-3982,-4007,-4033,-4058,-4081,-4104,-4126,-4146,-4165,-4182,-4198,-4213,-4226,-4238,
--4248,-4257,-4265,-4271,-4277,-4282,-4287,-4291,-4294,-4298,-4301,-4305,-4308,-4312,-4317,-4321,-4326,-4332,-4338,-4344,-4351,
--4358,-4365,-4372,-4379,-4386,-4393,-4400,-4406,-4412,-4418,-4423,-4427,-4431,-4434,-4436,-4438,-4440,-4441,-4442,-4442,-4442,
--4442,-4442,-4442,-4443,-4443,-4444,-4446,-4448,-4450,-4453,-4457,-4462,-4467,-4472,-4478,-4485,-4492,-4499,-4506,-4513,-4520,
--4527,-4534,-4540,-4546,-4552,-4556,-4560,-4563,-4565,-4567,-4567,-4567,-4566,-4564,-4562,-4559,-4555,-4551,-4547,-4542,-4538,
--4533,-4528,-4524,-4520,-4516,-4512,-4509,-4506,-4503,-4502,-4500,-4499,-4498,-4498,-4498,-4499,-4499,-4500,-4501,-4502,-4503,
--4504,-4505,-4506,-4507,-4508,-4508,-4509,-4509,-4509,-4509,-4508,-4508,-4507,-4507,-4506,-4505,-4504,-4503,-4502,-4501,-4499,
--4498,-4496,-4495,-4493,-4491,-4488,-4486,-4483,-4480,-4476,-4472,-4467,-4463,-4457,-4452,-4445,-4439,-4432,-4425,-4418,-4410,
--4402,-4394,-4387,-4379,-4371,-4363,-4356,-4349,-4342,-4336,-4329,-4324,-4319,-4314,-4309,-4305,-4302,-4298,-4295,-4293,-4290,
--4288,-4285,-4283,-4281,-4278,-4276,-4273,-4270,-4267,-4264,-4260,-4256,-4252,-4248,-4243,-4239,-4234,-4229,-4224,-4219,-4215,
--4210,-4205,-4201,-4197,-4193,-4189,-4185,-4182,-4179,-4176,-4173,-4170,-4168,-4165,-4162,-4159,-4157,-4153,-4150,-4146,-4142,
--4138,-4133,-4128,-4122,-4116,-4109,-4103,-4095,-4088,-4080,-4072,-4064,-4056,-4048,-4040,-4032,-4024,-4016,-4009,-4002,-3995,
--3989,-3983,-3977,-3972,-3967,-3962,-3958,-3953,-3949,-3945,-3940,-3936,-3931,-3926,-3921,-3915,-3909,-3903,-3895,-3888,-3879,
--3871,-3861,-3851,-3841,-3830,-3819,-3808,-3797,-3785,-3773,-3762,-3750,-3739,-3729,-3718,-3708,-3699,-3690,-3683,-3675,-3669,
--3662,-3657,-3652,-3648,-3644,-3641,-3638,-3635,-3632,-3630,-3627,-3624,-3620,-3616,-3612,-3607,-3601,-3594,-3586,-3577,-3567,
--3555,-3543,-3529,-3515,-3499,-3482,-3463,-3444,-3424,-3403,-3381,-3359,-3336,-3312,-3289,-3265,-3241,-3217,-3193,-3170,-3148,
--3126,-3105,-3084,-3065,-3047,-3030,-3015,-3001,-2988,-2976,-2966,-2958,-2951,-2945,-2941,-2938,-2936,-2935,-2936,-2937,-2939,
--2942,-2946,-2950,-2954,-2958,-2963,-2967,-2972,-2976,-2980,-2983,-2986,-2988,-2989,-2990,-2990,-2989,-2988,-2986,-2983,-2980,
--2976,-2972,-2967,-2962,-2957,-2951,-2946,-2940,-2934,-2929,-2923,-2918,-2913,-2909,-2905,-2901,-2898,-2895,-2892,-2890,-2888,
--2886,-2885,-2884,-2883,-2883,-2882,-2882,-2883,-2883,-2883,-2883,-2884,-2885,-2885,-2886,-2886,-2887,-2888,-2888,-2889,-2890,
--2890,-2891,-2891,-2891,-2891,-2891,-2891,-2890,-2889,-2887,-2885,-2882,-2879,-2875,-2871,-2866,-2860,-2854,-2846,-2839,-2830,
--2821,-2811,-2801,-2790,-2779,-2768,-2756,-2744,-2733,-2721,-2709,-2698,-2687,-2676,-2666,-2656,-2647,-2638,-2630,-2623,-2616,
--2610,-2604,-2599,-2594,-2589,-2585,-2580,-2576,-2572,-2568,-2564,-2560,-2555,-2550,-2545,-2539,-2533,-2527,-2521,-2514,-2507,
--2501,-2494,-2487,-2481,-2475,-2470,-2465,-2461,-2458,-2455,-2454,-2454,-2455,-2457,-2461,-2466,-2472,-2479,-2487,-2496,-2506,
--2516,-2527,-2539,-2550,-2561,-2572,-2582,-2592,-2600,-2607,-2612,-2616,-2618,-2618,-2615,-2611,-2604,-2594,-2583,-2568,-2552,
--2533,-2512,-2489,-2464,-2438,-2410,-2381,-2351,-2320,-2289,-2258,-2228,-2197,-2168,-2139,-2112,-2086,-2062,-2040,-2020,-2002,
--1986,-1973,-1962,-1953,-1946,-1942,-1940,-1939,-1941,-1944,-1949,-1955,-1963,-1971,-1980,-1989,-1999,-2009,-2019,-2028,-2036,
--2044,-2052,-2058,-2063,-2067,-2069,-2071,-2071,-2069,-2067,-2063,-2058,-2052,-2045,-2037,-2028,-2018,-2008,-1998,-1987,-1976,
--1965,-1955,-1944,-1934,-1924,-1915,-1906,-1898,-1891,-1884,-1878,-1873,-1868,-1864,-1860,-1857,-1854,-1852,-1850,-1848,-1845,
--1843,-1841,-1838,-1835,-1832,-1828,-1824,-1820,-1814,-1809,-1803,-1796,-1789,-1782,-1775,-1767,-1760,-1752,-1745,-1738,-1732,
--1726,-1721,-1717,-1713,-1711,-1709,-1708,-1709,-1710,-1712,-1716,-1720,-1725,-1731,-1737,-1744,-1751,-1759,-1766,-1773,-1780,
--1787,-1793,-1798,-1802,-1806,-1808,-1810,-1810,-1809,-1807,-1804,-1800,-1795,-1789,-1782,-1774,-1766,-1757,-1748,-1738,-1728,
--1719,-1709,-1699,-1690,-1682,-1673,-1665,-1658,-1651,-1645,-1639,-1633,-1628,-1623,-1618,-1614,-1609,-1604,-1600,-1594,-1589,
--1583,-1577,-1570,-1562,-1554,-1546,-1536,-1526,-1516,-1505,-1494,-1482,-1470,-1458,-1446,-1434,-1422,-1411,-1400,-1389,-1379,
--1370,-1361,-1354,-1347,-1341,-1335,-1331,-1327,-1325,-1322,-1321,-1320,-1319,-1319,-1319,-1319,-1320,-1320,-1321,-1321,-1321,
--1321,-1320,-1319,-1318,-1317,-1316,-1314,-1312,-1310,-1308,-1306,-1305,-1303,-1302,-1301,-1300,-1300,-1301,-1302,-1303,-1305,
--1308,-1311,-1315,-1319,-1324,-1328,-1334,-1339,-1344,-1350,-1355,-1360,-1364,-1413,-1417,-1421,-1424,-1426,-1428,-1429,-1430,
--1430,-1429,-1428,-1425,-1423,-1419,-1416,-1412,-1407,-1402,-1397,-1392,-1387,-1381,-1376,-1371,-1365,-1360,-1355,-1350,-1345,
--1341,-1336,-1331,-1327,-1322,-1317,-1313,-1308,-1303,-1298,-1293,-1287,-1282,-1276,-1270,-1264,-1257,-1251,-1245,-1238,-1232,
--1226,-1220,-1214,-1209,-1204,-1199,-1195,-1192,-1189,-1186,-1185,-1183,-1183,-1182,-1183,-1183,-1184,-1185,-1187,-1188,-1189,
--1190,-1191,-1191,-1191,-1190,-1188,-1185,-1181,-1176,-1169,-1162,-1153,-1143,-1131,-1118,-1104,-1089,-1072,-1054,-1035,-1015,
--995,-974,-952,-930,-907,-884,-862,-839,-817,-795,-774,-753,-733,-713,-695,-677,-661,-645,-630,-617,-604,
--592,-581,-571,-562,-554,-546,-539,-533,-527,-522,-517,-513,-509,-505,-501,-498,-495,-493,-490,-488,-486,
--484,-482,-481,-480,-480,-480,-480,-481,-482,-484,-486,-489,-493,-498,-503,-508,-515,-522,-529,-537,-546,
--555,-565,-575,-585,-595,-606,-617,-627,-638,-648,-658,-667,-676,-685,-693,-701,-707,-714,-719,-724,-728,
--731,-733,-735,-736,-737,-737,-736,-735,-734,-732,-730,-727,-725,-722,-719,-716,-714,-711,-708,-705,-702,
--699,-697,-694,-691,-688,-685,-683,-680,-676,-673,-670,-666,-662,-658,-654,-650,-645,-641,-636,-632,-627,
--622,-618,-614,-610,-607,-604,-602,-600,-599,-598,-598,-599,-600,-602,-605,-608,-611,-616,-620,-625,-630,
--635,-640,-645,-649,-653,-657,-660,-662,-663,-663,-662,-660,-657,-653,-648,-642,-635,-627,-618,-608,-598,
--587,-576,-565,-554,-543,-533,-523,-513,-505,-497,-491,-486,-483,-480,-480,-481,-484,-488,-493,-501,-509,
--520,-531,-544,-557,-572,-587,-604,-620,-637,-655,-672,-690,-707,-724,-741,-758,-774,-789,-804,-818,-832,
--845,-858,-869,-881,-892,-902,-912,-922,-932,-941,-950,-959,-968,-977,-986,-995,-1004,-1013,-1023,-1032,-1042,
--1052,-1062,-1072,-1082,-1092,-1103,-1113,-1124,-1134,-1144,-1155,-1165,-1175,-1185,-1195,-1204,-1214,-1223,-1233,-1242,-1252,
--1261,-1270,-1280,-1289,-1299,-1308,-1318,-1328,-1339,-1349,-1360,-1371,-1383,-1394,-1406,-1419,-1431,-1444,-1457,-1470,-1483,
--1496,-1510,-1523,-1536,-1550,-1563,-1576,-1589,-1602,-1615,-1627,-1640,-1652,-1664,-1676,-1687,-1699,-1710,-1722,-1733,-1745,
--1756,-1768,-1779,-1791,-1804,-1816,-1829,-1842,-1855,-1868,-1882,-1896,-1910,-1925,-1940,-1955,-1970,-1985,-2000,-2015,-2030,
--2045,-2059,-2074,-2088,-2102,-2115,-2128,-2141,-2153,-2165,-2177,-2188,-2200,-2210,-2221,-2232,-2242,-2253,-2264,-2275,-2286,
--2297,-2309,-2321,-2334,-2347,-2361,-2376,-2391,-2406,-2423,-2440,-2457,-2475,-2494,-2513,-2532,-2552,-2571,-2591,-2612,-2632,
--2652,-2672,-2692,-2712,-2732,-2751,-2770,-2788,-2807,-2825,-2842,-2860,-2877,-2894,-2910,-2927,-2943,-2960,-2976,-2992,-3008,
--3025,-3041,-3058,-3074,-3091,-3108,-3126,-3143,-3161,-3178,-3196,-3214,-3232,-3249,-3267,-3285,-3302,-3319,-3336,-3353,-3369,
--3384,-3400,-3415,-3429,-3443,-3456,-3469,-3481,-3493,-3504,-3515,-3525,-3535,-3544,-3553,-3561,-3569,-3577,-3584,-3591,-3598,
--3604,-3610,-3616,-3622,-3628,-3633,-3638,-3643,-3648,-3653,-3657,-3662,-3666,-3671,-3675,-3679,-3684,-3688,-3692,-3697,-3701,
--3706,-3710,-3715,-3720,-3725,-3731,-3736,-3742,-3748,-3754,-3760,-3766,-3772,-3778,-3784,-3790,-3796,-3802,-3807,-3812,-3817,
--3822,-3826,-3830,-3833,-3836,-3838,-3840,-3841,-3841,-3842,-3841,-3840,-3839,-3838,-3836,-3834,-3832,-3830,-3828,-3826,-3825,
--3823,-3822,-3821,-3821,-3821,-3821,-3822,-3824,-3826,-3828,-3830,-3833,-3836,-3839,-3842,-3845,-3848,-3850,-3851,-3852,-3852,
--3851,-3848,-3845,-3840,-3833,-3826,-3816,-3805,-3793,-3779,-3764,-3747,-3729,-3709,-3689,-3668,-3646,-3624,-3601,-3578,-3556,
--3534,-3512,-3491,-3471,-3452,-3434,-3418,-3403,-3390,-3378,-3368,-3360,-3353,-3348,-3345,-3343,-3343,-3343,-3345,-3348,-3352,
--3357,-3362,-3368,-3374,-3380,-3386,-3393,-3400,-3406,-3413,-3420,-3426,-3433,-3440,-3447,-3455,-3463,-3471,-3481,-3491,-3502,
--3514,-3527,-3542,-3558,-3575,-3593,-3613,-3634,-3657,-3681,-3705,-3731,-3757,-3785,-3812,-3840,-3868,-3896,-3923,-3950,-3976,
--4001,-4025,-4047,-4069,-4088,-4106,-4123,-4137,-4150,-4162,-4172,-4180,-4188,-4194,-4198,-4203,-4206,-4209,-4212,-4214,-4217,
--4220,-4223,-4227,-4231,-4237,-4243,-4250,-4257,-4266,-4276,-4286,-4297,-4308,-4320,-4333,-4345,-4357,-4370,-4382,-4393,-4404,
--4414,-4424,-4432,-4440,-4446,-4451,-4456,-4459,-4460,-4461,-4461,-4461,-4459,-4457,-4454,-4451,-4448,-4445,-4441,-4438,-4436,
--4433,-4432,-4431,-4430,-4431,-4432,-4433,-4436,-4439,-4442,-4447,-4451,-4457,-4462,-4467,-4473,-4478,-4484,-4489,-4494,-4498,
--4502,-4505,-4507,-4509,-4510,-4511,-4511,-4510,-4508,-4506,-4504,-4501,-4498,-4494,-4490,-4487,-4483,-4479,-4475,-4472,-4468,
--4466,-4463,-4461,-4459,-4457,-4456,-4456,-4455,-4455,-4456,-4457,-4458,-4459,-4460,-4462,-4464,-4465,-4467,-4469,-4471,-4472,
--4474,-4475,-4476,-4477,-4478,-4478,-4479,-4479,-4479,-4478,-4478,-4477,-4476,-4474,-4472,-4470,-4468,-4465,-4463,-4459,-4456,
--4452,-4448,-4444,-4439,-4434,-4429,-4423,-4418,-4412,-4406,-4400,-4393,-4387,-4380,-4374,-4367,-4360,-4354,-4348,-4341,-4335,
--4329,-4323,-4317,-4312,-4306,-4301,-4296,-4291,-4286,-4281,-4277,-4272,-4267,-4263,-4258,-4253,-4248,-4243,-4238,-4232,-4227,
--4221,-4216,-4210,-4204,-4198,-4192,-4186,-4180,-4174,-4168,-4163,-4157,-4152,-4147,-4142,-4138,-4134,-4130,-4127,-4124,-4121,
--4118,-4116,-4113,-4111,-4109,-4107,-4105,-4103,-4101,-4098,-4095,-4092,-4089,-4085,-4081,-4076,-4071,-4066,-4060,-4054,-4047,
--4040,-4033,-4026,-4018,-4010,-4003,-3995,-3988,-3980,-3973,-3966,-3959,-3953,-3947,-3942,-3936,-3931,-3927,-3923,-3919,-3915,
--3911,-3908,-3905,-3901,-3898,-3894,-3890,-3886,-3881,-3876,-3870,-3864,-3857,-3850,-3842,-3833,-3824,-3814,-3804,-3794,-3783,
--3772,-3761,-3749,-3738,-3727,-3715,-3704,-3694,-3684,-3674,-3665,-3657,-3649,-3642,-3635,-3629,-3624,-3620,-3616,-3613,-3610,
--3607,-3605,-3603,-3600,-3598,-3596,-3593,-3590,-3586,-3582,-3576,-3570,-3563,-3555,-3546,-3536,-3524,-3511,-3498,-3483,-3466,
--3449,-3431,-3412,-3392,-3371,-3350,-3328,-3306,-3283,-3261,-3238,-3216,-3195,-3173,-3153,-3133,-3114,-3096,-3080,-3064,-3050,
--3036,-3024,-3014,-3004,-2996,-2990,-2984,-2979,-2976,-2973,-2972,-2971,-2970,-2971,-2971,-2972,-2973,-2974,-2975,-2976,-2977,
--2977,-2977,-2977,-2976,-2975,-2973,-2970,-2968,-2964,-2960,-2956,-2952,-2947,-2942,-2936,-2931,-2925,-2920,-2915,-2909,-2904,
--2900,-2895,-2891,-2887,-2884,-2881,-2878,-2875,-2873,-2872,-2870,-2869,-2869,-2868,-2867,-2867,-2867,-2867,-2866,-2866,-2866,
--2866,-2866,-2866,-2865,-2865,-2865,-2865,-2864,-2864,-2864,-2864,-2864,-2864,-2864,-2865,-2865,-2866,-2866,-2867,-2867,-2868,
--2869,-2869,-2869,-2870,-2869,-2869,-2868,-2867,-2865,-2863,-2860,-2856,-2852,-2847,-2841,-2835,-2828,-2821,-2813,-2804,-2795,
--2785,-2775,-2764,-2753,-2742,-2731,-2720,-2709,-2697,-2686,-2675,-2664,-2654,-2644,-2634,-2624,-2614,-2605,-2596,-2588,-2579,
--2571,-2563,-2555,-2547,-2540,-2532,-2524,-2517,-2509,-2502,-2494,-2487,-2480,-2473,-2466,-2459,-2453,-2447,-2442,-2437,-2433,
--2430,-2427,-2426,-2425,-2426,-2427,-2430,-2434,-2438,-2444,-2451,-2459,-2467,-2476,-2486,-2497,-2507,-2518,-2529,-2539,-2549,
--2559,-2567,-2575,-2581,-2586,-2589,-2591,-2590,-2588,-2584,-2577,-2569,-2558,-2546,-2531,-2515,-2496,-2476,-2455,-2432,-2408,
--2383,-2357,-2332,-2306,-2280,-2254,-2229,-2205,-2182,-2160,-2140,-2121,-2104,-2089,-2076,-2065,-2056,-2049,-2044,-2041,-2040,
--2040,-2043,-2047,-2052,-2058,-2065,-2073,-2082,-2090,-2099,-2108,-2117,-2125,-2132,-2139,-2145,-2149,-2153,-2155,-2156,-2155,
--2154,-2150,-2146,-2141,-2134,-2126,-2117,-2107,-2097,-2086,-2074,-2062,-2049,-2037,-2024,-2012,-2000,-1988,-1976,-1965,-1954,
--1944,-1934,-1925,-1917,-1909,-1901,-1894,-1887,-1880,-1874,-1868,-1863,-1857,-1851,-1845,-1840,-1834,-1828,-1822,-1816,-1809,
--1803,-1796,-1790,-1783,-1777,-1770,-1764,-1758,-1752,-1747,-1742,-1737,-1734,-1731,-1728,-1727,-1726,-1726,-1727,-1729,-1732,
--1735,-1739,-1743,-1748,-1754,-1760,-1766,-1772,-1779,-1785,-1791,-1796,-1802,-1806,-1810,-1813,-1816,-1817,-1818,-1818,-1817,
--1815,-1812,-1808,-1803,-1798,-1792,-1785,-1778,-1770,-1762,-1754,-1746,-1738,-1729,-1721,-1713,-1705,-1697,-1689,-1682,-1675,
--1669,-1662,-1656,-1650,-1644,-1639,-1633,-1627,-1622,-1616,-1610,-1603,-1597,-1590,-1582,-1575,-1567,-1559,-1550,-1541,-1532,
--1523,-1513,-1503,-1494,-1484,-1475,-1465,-1456,-1448,-1440,-1432,-1425,-1418,-1412,-1406,-1401,-1397,-1394,-1391,-1388,-1386,
--1384,-1383,-1382,-1381,-1381,-1380,-1380,-1379,-1379,-1378,-1377,-1376,-1374,-1373,-1371,-1369,-1366,-1364,-1361,-1359,-1356,
--1353,-1351,-1349,-1347,-1345,-1344,-1343,-1343,-1343,-1344,-1345,-1347,-1350,-1353,-1357,-1361,-1365,-1370,-1376,-1381,-1387,
--1392,-1398,-1403,-1408,-1413,-1463,-1467,-1471,-1474,-1477,-1480,-1482,-1483,-1484,-1484,-1484,-1484,-1483,-1482,-1480,-1478,
--1476,-1473,-1471,-1468,-1465,-1461,-1458,-1455,-1451,-1448,-1444,-1440,-1437,-1433,-1428,-1424,-1420,-1415,-1410,-1404,-1399,
--1393,-1386,-1379,-1372,-1365,-1357,-1348,-1340,-1331,-1322,-1313,-1303,-1294,-1285,-1276,-1267,-1258,-1250,-1243,-1235,-1229,
--1223,-1218,-1213,-1209,-1206,-1204,-1203,-1202,-1201,-1202,-1202,-1203,-1205,-1206,-1208,-1209,-1210,-1211,-1211,-1211,-1210,
--1208,-1206,-1202,-1197,-1191,-1184,-1175,-1166,-1155,-1143,-1130,-1115,-1100,-1083,-1066,-1048,-1029,-1010,-991,-971,-951,
--931,-911,-891,-872,-853,-834,-817,-800,-783,-768,-754,-740,-727,-715,-704,-694,-685,-676,-669,-662,-655,
--650,-644,-640,-635,-631,-628,-624,-621,-618,-615,-613,-610,-608,-606,-604,-602,-601,-600,-599,-598,-598,
--598,-598,-599,-601,-603,-605,-608,-612,-616,-620,-625,-631,-637,-644,-651,-658,-665,-673,-681,-689,-696,
--704,-712,-719,-726,-733,-739,-745,-750,-755,-759,-763,-766,-768,-770,-771,-772,-772,-771,-770,-769,-767,
--765,-763,-760,-758,-755,-752,-749,-746,-743,-740,-737,-734,-731,-729,-726,-723,-720,-718,-715,-712,-709,
--706,-703,-700,-697,-693,-689,-686,-682,-678,-674,-670,-666,-661,-657,-654,-650,-646,-643,-640,-638,-636,
--634,-633,-632,-632,-633,-634,-635,-637,-640,-642,-646,-649,-653,-656,-660,-664,-667,-670,-673,-676,-678,
--679,-680,-680,-680,-678,-676,-673,-670,-666,-661,-655,-649,-642,-636,-629,-621,-614,-607,-600,-594,-588,
--583,-578,-574,-571,-569,-568,-568,-570,-572,-576,-580,-586,-593,-601,-610,-620,-630,-642,-654,-666,-679,
--692,-706,-720,-733,-747,-761,-774,-788,-801,-813,-826,-838,-850,-861,-872,-883,-894,-904,-914,-923,-933,
--943,-952,-961,-971,-980,-990,-999,-1009,-1019,-1029,-1039,-1049,-1059,-1070,-1080,-1091,-1102,-1112,-1123,-1134,-1145,
--1156,-1166,-1177,-1188,-1198,-1209,-1219,-1230,-1240,-1250,-1261,-1271,-1281,-1292,-1302,-1313,-1324,-1335,-1346,-1357,-1369,
--1380,-1392,-1405,-1417,-1430,-1443,-1456,-1469,-1483,-1497,-1510,-1524,-1538,-1552,-1566,-1580,-1593,-1607,-1620,-1633,-1646,
--1659,-1672,-1684,-1696,-1708,-1720,-1731,-1742,-1754,-1765,-1776,-1787,-1798,-1809,-1821,-1832,-1844,-1856,-1868,-1880,-1893,
--1905,-1919,-1932,-1945,-1959,-1973,-1987,-2001,-2016,-2030,-2044,-2058,-2072,-2086,-2099,-2113,-2126,-2138,-2151,-2162,-2174,
--2185,-2196,-2207,-2217,-2227,-2237,-2246,-2256,-2266,-2275,-2285,-2295,-2305,-2316,-2327,-2338,-2350,-2362,-2375,-2388,-2403,
--2417,-2432,-2448,-2465,-2482,-2499,-2517,-2535,-2554,-2573,-2592,-2611,-2630,-2649,-2669,-2688,-2707,-2725,-2744,-2762,-2780,
--2798,-2815,-2832,-2849,-2865,-2881,-2897,-2913,-2929,-2945,-2960,-2976,-2992,-3008,-3024,-3040,-3056,-3073,-3090,-3107,-3124,
--3142,-3159,-3177,-3195,-3214,-3232,-3250,-3269,-3287,-3305,-3323,-3340,-3358,-3375,-3391,-3407,-3423,-3438,-3452,-3466,-3479,
--3492,-3504,-3515,-3526,-3536,-3546,-3555,-3563,-3571,-3578,-3585,-3591,-3597,-3603,-3609,-3614,-3619,-3623,-3628,-3632,-3636,
--3640,-3644,-3648,-3652,-3656,-3660,-3664,-3667,-3671,-3675,-3679,-3683,-3687,-3691,-3695,-3699,-3703,-3707,-3711,-3715,-3719,
--3723,-3727,-3731,-3735,-3739,-3743,-3747,-3751,-3755,-3758,-3762,-3765,-3768,-3772,-3775,-3777,-3780,-3782,-3785,-3786,-3788,
--3790,-3792,-3793,-3794,-3795,-3796,-3797,-3798,-3799,-3800,-3800,-3801,-3802,-3803,-3803,-3804,-3805,-3806,-3807,-3808,-3809,
--3810,-3811,-3811,-3812,-3813,-3813,-3813,-3812,-3811,-3810,-3808,-3806,-3803,-3800,-3795,-3791,-3785,-3779,-3772,-3764,-3756,
--3747,-3737,-3727,-3716,-3705,-3693,-3681,-3669,-3657,-3644,-3631,-3619,-3606,-3594,-3581,-3569,-3557,-3546,-3535,-3524,-3514,
--3504,-3494,-3485,-3476,-3467,-3459,-3451,-3443,-3435,-3428,-3421,-3414,-3407,-3400,-3393,-3387,-3381,-3376,-3370,-3366,-3362,
--3359,-3357,-3355,-3355,-3357,-3359,-3363,-3369,-3377,-3386,-3398,-3411,-3427,-3444,-3464,-3486,-3509,-3535,-3562,-3591,-3621,
--3652,-3685,-3718,-3751,-3785,-3819,-3852,-3885,-3917,-3948,-3977,-4005,-4031,-4056,-4078,-4098,-4115,-4131,-4144,-4155,-4163,
--4170,-4175,-4178,-4179,-4179,-4178,-4176,-4174,-4171,-4169,-4166,-4165,-4163,-4163,-4164,-4167,-4171,-4176,-4183,-4192,-4202,
--4214,-4227,-4242,-4259,-4276,-4294,-4313,-4333,-4353,-4373,-4393,-4412,-4431,-4449,-4466,-4481,-4495,-4508,-4519,-4528,-4536,
--4541,-4545,-4547,-4548,-4547,-4544,-4541,-4536,-4530,-4523,-4515,-4507,-4499,-4491,-4482,-4474,-4467,-4459,-4453,-4447,-4442,
--4437,-4434,-4431,-4429,-4428,-4428,-4428,-4429,-4431,-4433,-4436,-4438,-4441,-4444,-4447,-4450,-4453,-4455,-4457,-4459,-4460,
--4461,-4462,-4462,-4461,-4460,-4459,-4457,-4455,-4452,-4449,-4446,-4443,-4440,-4437,-4434,-4431,-4428,-4425,-4423,-4421,-4419,
--4417,-4416,-4415,-4415,-4415,-4415,-4416,-4416,-4418,-4419,-4421,-4423,-4425,-4428,-4430,-4433,-4436,-4438,-4441,-4444,-4446,
--4449,-4451,-4453,-4455,-4457,-4458,-4459,-4460,-4460,-4460,-4460,-4459,-4458,-4457,-4455,-4453,-4450,-4447,-4443,-4439,-4435,
--4431,-4426,-4420,-4415,-4409,-4403,-4397,-4390,-4383,-4377,-4370,-4362,-4355,-4348,-4340,-4333,-4325,-4317,-4310,-4302,-4294,
--4286,-4278,-4270,-4262,-4254,-4246,-4238,-4229,-4221,-4213,-4205,-4196,-4188,-4180,-4172,-4163,-4156,-4148,-4140,-4133,-4126,
--4119,-4113,-4107,-4101,-4095,-4090,-4086,-4081,-4078,-4074,-4071,-4068,-4065,-4063,-4061,-4059,-4057,-4055,-4053,-4052,-4049,
--4047,-4045,-4042,-4039,-4036,-4032,-4028,-4023,-4019,-4013,-4008,-4002,-3996,-3989,-3982,-3976,-3969,-3962,-3955,-3948,-3941,
--3935,-3929,-3923,-3917,-3912,-3907,-3903,-3899,-3896,-3893,-3890,-3888,-3886,-3884,-3883,-3882,-3880,-3879,-3878,-3876,-3874,
--3872,-3869,-3866,-3863,-3858,-3854,-3848,-3842,-3835,-3828,-3820,-3811,-3802,-3792,-3782,-3772,-3761,-3750,-3739,-3728,-3716,
--3705,-3694,-3684,-3674,-3664,-3654,-3646,-3637,-3629,-3622,-3615,-3609,-3603,-3598,-3593,-3589,-3584,-3580,-3576,-3572,-3568,
--3563,-3558,-3553,-3547,-3541,-3534,-3527,-3518,-3509,-3499,-3489,-3477,-3464,-3451,-3437,-3422,-3407,-3391,-3374,-3357,-3340,
--3322,-3305,-3287,-3270,-3252,-3235,-3219,-3202,-3187,-3172,-3157,-3144,-3131,-3119,-3107,-3097,-3087,-3078,-3070,-3062,-3055,
--3048,-3042,-3037,-3031,-3026,-3021,-3017,-3012,-3007,-3002,-2997,-2991,-2986,-2980,-2973,-2967,-2960,-2953,-2945,-2937,-2930,
--2922,-2914,-2905,-2897,-2889,-2882,-2874,-2867,-2860,-2853,-2847,-2842,-2837,-2832,-2828,-2825,-2822,-2820,-2819,-2817,-2817,
--2817,-2817,-2817,-2818,-2819,-2820,-2821,-2823,-2824,-2826,-2827,-2828,-2830,-2831,-2832,-2833,-2834,-2835,-2836,-2837,-2838,
--2839,-2840,-2841,-2843,-2844,-2846,-2848,-2851,-2853,-2856,-2860,-2863,-2867,-2870,-2874,-2878,-2882,-2887,-2890,-2894,-2898,
--2901,-2904,-2907,-2909,-2910,-2911,-2911,-2910,-2909,-2907,-2904,-2900,-2896,-2890,-2884,-2877,-2870,-2862,-2853,-2844,-2834,
--2824,-2814,-2803,-2792,-2781,-2769,-2757,-2746,-2734,-2722,-2710,-2698,-2686,-2674,-2662,-2649,-2637,-2625,-2613,-2600,-2588,
--2575,-2563,-2550,-2538,-2526,-2513,-2501,-2489,-2477,-2466,-2455,-2445,-2435,-2426,-2417,-2410,-2403,-2398,-2393,-2390,-2388,
--2387,-2387,-2389,-2392,-2396,-2402,-2409,-2416,-2425,-2434,-2445,-2455,-2467,-2478,-2490,-2502,-2513,-2524,-2534,-2544,-2552,
--2560,-2566,-2571,-2574,-2576,-2577,-2575,-2572,-2568,-2561,-2553,-2544,-2533,-2521,-2508,-2493,-2478,-2462,-2446,-2429,-2413,
--2396,-2379,-2363,-2348,-2333,-2320,-2307,-2296,-2285,-2276,-2269,-2263,-2258,-2254,-2252,-2251,-2251,-2253,-2255,-2258,-2262,
--2267,-2271,-2277,-2282,-2287,-2292,-2296,-2300,-2304,-2307,-2308,-2309,-2309,-2308,-2305,-2302,-2297,-2291,-2284,-2276,-2267,
--2256,-2245,-2233,-2220,-2206,-2191,-2176,-2161,-2145,-2129,-2113,-2096,-2080,-2064,-2047,-2031,-2015,-2000,-1984,-1970,-1955,
--1941,-1927,-1914,-1901,-1889,-1877,-1866,-1855,-1845,-1835,-1826,-1818,-1810,-1803,-1796,-1790,-1785,-1780,-1776,-1773,-1771,
--1769,-1768,-1768,-1768,-1770,-1772,-1774,-1778,-1782,-1786,-1791,-1797,-1802,-1809,-1815,-1822,-1828,-1835,-1841,-1847,-1853,
--1859,-1864,-1868,-1872,-1876,-1878,-1880,-1881,-1882,-1881,-1880,-1878,-1875,-1872,-1868,-1863,-1858,-1852,-1845,-1839,-1832,
--1824,-1817,-1809,-1801,-1794,-1786,-1778,-1770,-1763,-1755,-1748,-1740,-1733,-1726,-1718,-1711,-1704,-1697,-1690,-1682,-1675,
--1667,-1660,-1652,-1643,-1635,-1627,-1618,-1609,-1600,-1591,-1581,-1572,-1563,-1553,-1544,-1535,-1527,-1518,-1510,-1502,-1495,
--1488,-1482,-1476,-1471,-1466,-1462,-1458,-1455,-1453,-1451,-1449,-1448,-1447,-1446,-1445,-1445,-1444,-1444,-1443,-1443,-1442,
--1441,-1440,-1439,-1437,-1435,-1433,-1431,-1429,-1426,-1423,-1420,-1418,-1415,-1412,-1410,-1407,-1405,-1404,-1403,-1402,-1401,
--1402,-1402,-1404,-1405,-1408,-1410,-1414,-1417,-1421,-1425,-1430,-1435,-1440,-1445,-1449,-1454,-1459,-1463,-1504,-1506,-1509,
--1512,-1514,-1516,-1519,-1521,-1523,-1525,-1526,-1528,-1529,-1531,-1532,-1533,-1534,-1534,-1535,-1535,-1536,-1536,-1535,-1535,
--1534,-1533,-1532,-1531,-1528,-1526,-1523,-1520,-1516,-1511,-1506,-1500,-1493,-1486,-1478,-1470,-1460,-1451,-1440,-1429,-1418,
--1406,-1394,-1382,-1370,-1357,-1345,-1333,-1321,-1309,-1298,-1288,-1278,-1269,-1260,-1253,-1246,-1240,-1236,-1232,-1229,-1227,
--1226,-1226,-1227,-1228,-1230,-1232,-1235,-1237,-1240,-1243,-1246,-1248,-1250,-1252,-1252,-1252,-1251,-1249,-1246,-1242,-1237,
--1230,-1222,-1214,-1204,-1192,-1180,-1167,-1153,-1138,-1122,-1106,-1089,-1072,-1054,-1037,-1019,-1001,-984,-967,-950,-934,
--918,-903,-888,-875,-862,-850,-838,-828,-818,-809,-801,-793,-786,-780,-774,-768,-763,-759,-755,-751,-747,
--744,-741,-738,-735,-732,-730,-727,-725,-723,-720,-718,-717,-715,-714,-713,-712,-712,-712,-712,-713,-714,
--716,-718,-721,-724,-727,-731,-735,-740,-745,-750,-755,-760,-766,-771,-777,-782,-787,-792,-797,-802,-806,
--810,-813,-816,-819,-821,-822,-823,-824,-824,-824,-823,-822,-820,-818,-816,-814,-811,-808,-805,-802,-799,
--796,-792,-789,-786,-782,-779,-776,-772,-769,-766,-763,-760,-757,-753,-750,-747,-744,-741,-738,-735,-731,
--728,-725,-722,-719,-716,-713,-711,-708,-706,-703,-701,-700,-698,-697,-696,-696,-696,-696,-696,-697,-698,
--699,-700,-702,-704,-706,-708,-710,-712,-713,-715,-717,-718,-719,-720,-720,-720,-719,-718,-717,-715,-713,
--711,-708,-704,-701,-697,-693,-689,-685,-681,-677,-673,-670,-666,-664,-661,-660,-658,-658,-658,-658,-660,
--662,-665,-669,-673,-678,-684,-690,-697,-705,-713,-722,-731,-740,-750,-760,-770,-781,-791,-802,-813,-824,
--834,-845,-856,-866,-877,-887,-898,-908,-918,-928,-939,-949,-959,-969,-980,-990,-1000,-1010,-1021,-1031,-1042,
--1053,-1063,-1074,-1085,-1096,-1107,-1117,-1128,-1139,-1150,-1161,-1172,-1183,-1194,-1204,-1215,-1226,-1236,-1247,-1258,-1268,
--1279,-1290,-1300,-1311,-1322,-1333,-1345,-1356,-1368,-1380,-1392,-1404,-1417,-1430,-1443,-1456,-1470,-1484,-1498,-1512,-1526,
--1541,-1555,-1570,-1584,-1599,-1613,-1627,-1642,-1656,-1669,-1683,-1696,-1710,-1722,-1735,-1747,-1759,-1771,-1783,-1794,-1805,
--1816,-1827,-1838,-1849,-1859,-1870,-1881,-1892,-1903,-1914,-1925,-1937,-1948,-1960,-1972,-1984,-1996,-2008,-2021,-2034,-2046,
--2059,-2071,-2084,-2096,-2109,-2121,-2133,-2145,-2156,-2168,-2179,-2189,-2200,-2210,-2220,-2229,-2239,-2248,-2257,-2266,-2275,
--2284,-2293,-2302,-2312,-2321,-2331,-2341,-2352,-2363,-2374,-2386,-2399,-2412,-2425,-2439,-2454,-2469,-2485,-2501,-2517,-2534,
--2552,-2569,-2587,-2605,-2623,-2641,-2660,-2678,-2696,-2714,-2732,-2750,-2768,-2785,-2803,-2820,-2837,-2853,-2870,-2886,-2903,
--2919,-2935,-2951,-2967,-2983,-2999,-3015,-3031,-3048,-3064,-3081,-3098,-3115,-3132,-3150,-3167,-3185,-3203,-3221,-3239,-3257,
--3274,-3292,-3310,-3327,-3345,-3362,-3378,-3395,-3411,-3426,-3441,-3456,-3470,-3483,-3496,-3509,-3520,-3532,-3542,-3552,-3562,
--3571,-3579,-3588,-3595,-3602,-3609,-3615,-3622,-3627,-3633,-3638,-3643,-3647,-3652,-3656,-3660,-3664,-3667,-3671,-3674,-3677,
--3680,-3683,-3686,-3689,-3692,-3694,-3697,-3699,-3701,-3703,-3706,-3708,-3710,-3712,-3714,-3715,-3718,-3719,-3721,-3723,-3726,
--3728,-3730,-3732,-3734,-3737,-3739,-3742,-3744,-3747,-3750,-3753,-3756,-3758,-3761,-3764,-3767,-3770,-3773,-3776,-3778,-3781,
--3783,-3786,-3788,-3790,-3791,-3793,-3794,-3795,-3795,-3796,-3796,-3795,-3795,-3794,-3793,-3791,-3790,-3788,-3785,-3783,-3780,
--3777,-3774,-3771,-3767,-3764,-3760,-3757,-3753,-3749,-3746,-3742,-3738,-3735,-3731,-3728,-3724,-3721,-3718,-3714,-3711,-3707,
--3704,-3700,-3696,-3692,-3688,-3683,-3678,-3672,-3666,-3659,-3651,-3643,-3633,-3623,-3612,-3601,-3588,-3574,-3560,-3545,-3529,
--3512,-3495,-3477,-3459,-3440,-3422,-3404,-3386,-3369,-3352,-3337,-3322,-3310,-3298,-3289,-3282,-3277,-3274,-3275,-3278,-3284,
--3292,-3304,-3319,-3337,-3358,-3382,-3408,-3437,-3469,-3503,-3538,-3576,-3614,-3654,-3694,-3735,-3775,-3815,-3855,-3893,-3930,
--3965,-3998,-4029,-4057,-4082,-4105,-4125,-4141,-4155,-4165,-4173,-4178,-4180,-4180,-4177,-4172,-4166,-4159,-4150,-4141,-4131,
--4121,-4112,-4104,-4096,-4090,-4085,-4082,-4082,-4083,-4087,-4093,-4102,-4113,-4126,-4142,-4160,-4180,-4201,-4225,-4250,-4275,
--4302,-4329,-4356,-4383,-4410,-4436,-4461,-4484,-4506,-4527,-4545,-4561,-4575,-4587,-4597,-4604,-4609,-4611,-4611,-4609,-4605,
--4600,-4592,-4584,-4573,-4562,-4551,-4538,-4525,-4512,-4499,-4487,-4474,-4463,-4452,-4442,-4432,-4424,-4417,-4411,-4406,-4402,
--4399,-4397,-4396,-4396,-4396,-4398,-4400,-4402,-4404,-4407,-4410,-4413,-4415,-4418,-4420,-4422,-4423,-4424,-4425,-4425,-4424,
--4423,-4421,-4419,-4416,-4413,-4409,-4405,-4401,-4397,-4392,-4388,-4383,-4379,-4375,-4371,-4367,-4364,-4361,-4359,-4357,-4355,
--4355,-4355,-4355,-4356,-4358,-4360,-4363,-4367,-4371,-4376,-4381,-4386,-4392,-4398,-4404,-4410,-4417,-4423,-4429,-4435,-4441,
--4447,-4452,-4457,-4462,-4465,-4469,-4471,-4473,-4475,-4475,-4475,-4474,-4473,-4470,-4467,-4463,-4458,-4453,-4447,-4440,-4433,
--4425,-4416,-4407,-4398,-4388,-4377,-4366,-4355,-4344,-4332,-4321,-4309,-4297,-4285,-4272,-4260,-4248,-4236,-4224,-4213,-4201,
--4190,-4179,-4168,-4157,-4147,-4137,-4128,-4119,-4110,-4101,-4094,-4086,-4079,-4072,-4066,-4060,-4055,-4050,-4045,-4041,-4037,
--4033,-4030,-4027,-4024,-4021,-4018,-4016,-4013,-4011,-4008,-4005,-4002,-3999,-3996,-3992,-3988,-3984,-3980,-3975,-3970,-3965,
--3959,-3954,-3948,-3942,-3936,-3929,-3923,-3917,-3911,-3905,-3899,-3894,-3889,-3884,-3880,-3876,-3872,-3869,-3867,-3865,-3863,
--3862,-3862,-3861,-3862,-3862,-3863,-3864,-3865,-3866,-3867,-3868,-3868,-3868,-3868,-3868,-3867,-3865,-3863,-3860,-3857,-3852,
--3847,-3841,-3835,-3827,-3819,-3811,-3801,-3792,-3781,-3771,-3760,-3748,-3737,-3725,-3714,-3702,-3691,-3679,-3669,-3658,-3648,
--3638,-3629,-3620,-3611,-3603,-3596,-3589,-3582,-3575,-3569,-3563,-3557,-3552,-3546,-3540,-3535,-3529,-3522,-3516,-3509,-3502,
--3494,-3486,-3478,-3468,-3459,-3448,-3438,-3427,-3415,-3403,-3390,-3377,-3364,-3351,-3338,-3324,-3310,-3297,-3283,-3270,-3257,
--3244,-3231,-3219,-3207,-3195,-3183,-3172,-3162,-3151,-3141,-3131,-3122,-3112,-3103,-3093,-3084,-3075,-3066,-3056,-3047,-3037,
--3027,-3017,-3006,-2995,-2984,-2973,-2961,-2950,-2938,-2926,-2914,-2902,-2890,-2878,-2866,-2854,-2843,-2832,-2822,-2812,-2803,
--2794,-2786,-2779,-2773,-2767,-2762,-2758,-2755,-2753,-2751,-2751,-2751,-2751,-2752,-2754,-2757,-2760,-2763,-2767,-2771,-2775,
--2779,-2784,-2788,-2793,-2798,-2803,-2807,-2812,-2817,-2822,-2826,-2831,-2836,-2841,-2845,-2850,-2855,-2860,-2865,-2871,-2876,
--2882,-2887,-2893,-2899,-2905,-2912,-2918,-2924,-2930,-2936,-2942,-2948,-2954,-2959,-2964,-2969,-2973,-2977,-2980,-2983,-2984,
--2986,-2986,-2986,-2985,-2984,-2981,-2978,-2974,-2970,-2965,-2959,-2952,-2945,-2938,-2930,-2921,-2912,-2902,-2892,-2881,-2871,
--2859,-2848,-2835,-2823,-2810,-2797,-2783,-2769,-2755,-2740,-2725,-2710,-2694,-2677,-2660,-2643,-2626,-2608,-2590,-2573,-2554,
--2536,-2518,-2501,-2483,-2466,-2450,-2434,-2419,-2405,-2392,-2381,-2370,-2361,-2353,-2347,-2343,-2340,-2339,-2340,-2343,-2347,
--2353,-2361,-2370,-2381,-2393,-2407,-2421,-2436,-2452,-2469,-2486,-2503,-2520,-2537,-2554,-2569,-2584,-2598,-2611,-2623,-2633,
--2642,-2649,-2655,-2659,-2661,-2661,-2660,-2657,-2653,-2647,-2640,-2632,-2622,-2612,-2601,-2589,-2577,-2564,-2552,-2539,-2527,
--2515,-2503,-2492,-2482,-2473,-2465,-2457,-2451,-2445,-2441,-2437,-2435,-2433,-2432,-2432,-2433,-2434,-2435,-2437,-2439,-2441,
--2443,-2444,-2446,-2446,-2446,-2445,-2444,-2441,-2437,-2432,-2426,-2419,-2410,-2400,-2389,-2377,-2363,-2348,-2331,-2314,-2296,
--2276,-2256,-2235,-2213,-2191,-2169,-2146,-2123,-2100,-2076,-2054,-2031,-2009,-1988,-1967,-1947,-1928,-1910,-1893,-1877,-1862,
--1848,-1836,-1825,-1816,-1808,-1801,-1795,-1792,-1789,-1788,-1788,-1789,-1791,-1795,-1799,-1804,-1811,-1818,-1825,-1834,-1842,
--1851,-1861,-1870,-1879,-1889,-1898,-1907,-1915,-1923,-1931,-1938,-1944,-1949,-1954,-1958,-1961,-1963,-1964,-1965,-1964,-1963,
--1962,-1959,-1956,-1952,-1947,-1942,-1937,-1931,-1925,-1919,-1912,-1905,-1898,-1892,-1885,-1878,-1871,-1864,-1858,-1851,-1845,
--1839,-1832,-1826,-1820,-1813,-1807,-1800,-1794,-1787,-1780,-1773,-1765,-1758,-1750,-1741,-1733,-1724,-1715,-1705,-1695,-1685,
--1675,-1665,-1655,-1644,-1634,-1623,-1613,-1603,-1593,-1584,-1575,-1566,-1558,-1550,-1543,-1536,-1530,-1525,-1520,-1516,-1512,
--1509,-1506,-1504,-1502,-1501,-1499,-1499,-1498,-1498,-1497,-1497,-1497,-1497,-1497,-1496,-1496,-1495,-1495,-1494,-1493,-1492,
--1490,-1489,-1487,-1486,-1484,-1482,-1481,-1479,-1478,-1477,-1476,-1475,-1474,-1474,-1473,-1474,-1474,-1475,-1476,-1477,-1479,
--1480,-1483,-1485,-1487,-1490,-1492,-1495,-1498,-1501,-1504,-1524,-1524,-1525,-1525,-1526,-1527,-1529,-1530,-1532,-1534,-1536,
--1539,-1542,-1545,-1548,-1551,-1554,-1558,-1561,-1564,-1568,-1571,-1574,-1576,-1578,-1580,-1582,-1582,-1583,-1582,-1581,-1579,
--1576,-1573,-1568,-1563,-1557,-1550,-1542,-1533,-1523,-1512,-1501,-1489,-1477,-1463,-1450,-1436,-1422,-1408,-1394,-1380,-1366,
--1353,-1340,-1328,-1316,-1306,-1296,-1287,-1278,-1271,-1265,-1260,-1257,-1254,-1252,-1251,-1251,-1252,-1254,-1256,-1259,-1262,
--1265,-1269,-1273,-1276,-1280,-1283,-1285,-1287,-1289,-1289,-1289,-1288,-1285,-1282,-1278,-1272,-1266,-1258,-1249,-1240,-1229,
--1217,-1205,-1192,-1178,-1164,-1149,-1134,-1119,-1103,-1088,-1072,-1057,-1042,-1027,-1013,-999,-986,-973,-961,-950,-939,
--928,-919,-910,-902,-894,-887,-880,-874,-868,-863,-858,-853,-849,-845,-841,-837,-833,-830,-826,-823,-820,
--817,-814,-811,-808,-805,-803,-800,-798,-797,-795,-794,-793,-792,-792,-792,-793,-794,-796,-797,-800,-802,
--805,-809,-813,-816,-821,-825,-830,-834,-839,-844,-848,-853,-857,-861,-866,-869,-873,-876,-878,-881,-883,
--884,-885,-886,-886,-886,-886,-885,-884,-882,-880,-878,-876,-873,-870,-867,-864,-861,-858,-854,-851,-847,
--844,-840,-837,-834,-830,-827,-824,-821,-818,-815,-813,-810,-808,-806,-804,-802,-800,-798,-797,-796,-794,
--793,-793,-792,-792,-791,-791,-791,-792,-792,-793,-793,-794,-795,-796,-797,-798,-799,-800,-801,-802,-803,
--803,-804,-804,-804,-804,-804,-804,-803,-802,-801,-800,-798,-797,-795,-793,-791,-788,-786,-783,-781,-779,
--776,-774,-772,-770,-769,-767,-766,-766,-765,-766,-766,-767,-769,-771,-773,-776,-779,-783,-788,-793,-798,
--804,-810,-816,-823,-831,-838,-846,-854,-863,-871,-880,-889,-899,-908,-918,-927,-937,-947,-957,-968,-978,
--988,-999,-1009,-1020,-1031,-1042,-1052,-1063,-1074,-1085,-1096,-1107,-1118,-1129,-1140,-1151,-1162,-1173,-1184,-1194,-1205,
--1216,-1226,-1237,-1247,-1257,-1268,-1278,-1288,-1298,-1308,-1318,-1329,-1339,-1349,-1360,-1370,-1381,-1392,-1403,-1414,-1426,
--1438,-1450,-1462,-1474,-1487,-1500,-1514,-1527,-1541,-1555,-1569,-1583,-1598,-1612,-1627,-1641,-1655,-1670,-1684,-1698,-1712,
--1726,-1740,-1753,-1766,-1779,-1792,-1804,-1816,-1828,-1839,-1850,-1861,-1872,-1882,-1893,-1903,-1913,-1923,-1933,-1942,-1952,
--1962,-1972,-1982,-1992,-2002,-2012,-2023,-2033,-2044,-2054,-2065,-2076,-2087,-2098,-2109,-2120,-2130,-2141,-2152,-2163,-2173,
--2183,-2194,-2204,-2213,-2223,-2233,-2242,-2251,-2260,-2269,-2278,-2287,-2296,-2305,-2313,-2322,-2332,-2341,-2350,-2360,-2370,
--2381,-2392,-2403,-2414,-2426,-2439,-2452,-2465,-2479,-2493,-2508,-2523,-2538,-2554,-2570,-2587,-2603,-2620,-2637,-2655,-2672,
--2690,-2707,-2725,-2742,-2760,-2777,-2795,-2812,-2829,-2846,-2863,-2880,-2897,-2913,-2930,-2946,-2963,-2979,-2995,-3012,-3028,
--3044,-3060,-3076,-3093,-3109,-3125,-3142,-3158,-3174,-3191,-3207,-3223,-3239,-3255,-3272,-3288,-3303,-3319,-3334,-3350,-3365,
--3379,-3394,-3408,-3422,-3436,-3449,-3461,-3474,-3486,-3497,-3509,-3520,-3530,-3540,-3550,-3559,-3568,-3576,-3584,-3592,-3599,
--3606,-3613,-3619,-3625,-3630,-3635,-3640,-3645,-3649,-3653,-3657,-3660,-3663,-3666,-3668,-3671,-3672,-3674,-3676,-3677,-3678,
--3679,-3680,-3681,-3682,-3683,-3683,-3684,-3685,-3686,-3686,-3687,-3688,-3690,-3691,-3693,-3694,-3696,-3699,-3701,-3704,-3706,
--3709,-3713,-3716,-3719,-3723,-3726,-3730,-3734,-3737,-3740,-3744,-3747,-3750,-3752,-3754,-3757,-3758,-3759,-3760,-3760,-3760,
--3760,-3759,-3757,-3756,-3753,-3751,-3748,-3745,-3741,-3738,-3734,-3730,-3726,-3722,-3719,-3715,-3712,-3709,-3707,-3704,-3703,
--3701,-3700,-3700,-3700,-3701,-3702,-3703,-3705,-3707,-3709,-3711,-3714,-3716,-3718,-3720,-3722,-3723,-3723,-3723,-3722,-3719,
--3716,-3711,-3705,-3697,-3689,-3678,-3667,-3653,-3638,-3622,-3604,-3586,-3566,-3545,-3523,-3500,-3477,-3454,-3431,-3408,-3386,
--3365,-3344,-3325,-3308,-3293,-3279,-3268,-3260,-3255,-3252,-3253,-3257,-3265,-3275,-3289,-3306,-3327,-3351,-3377,-3407,-3438,
--3473,-3509,-3546,-3585,-3625,-3666,-3707,-3747,-3787,-3826,-3864,-3899,-3933,-3965,-3994,-4020,-4043,-4063,-4080,-4093,-4103,
--4110,-4113,-4114,-4111,-4106,-4098,-4088,-4076,-4063,-4048,-4033,-4017,-4001,-3985,-3970,-3956,-3944,-3933,-3924,-3918,-3914,
--3912,-3913,-3918,-3925,-3935,-3948,-3964,-3982,-4003,-4026,-4051,-4079,-4107,-4137,-4168,-4199,-4230,-4262,-4293,-4323,-4352,
--4380,-4406,-4430,-4452,-4472,-4489,-4504,-4517,-4527,-4534,-4539,-4541,-4541,-4539,-4534,-4528,-4520,-4510,-4499,-4487,-4475,
--4462,-4448,-4434,-4421,-4407,-4395,-4383,-4371,-4361,-4352,-4344,-4337,-4331,-4326,-4323,-4321,-4320,-4320,-4321,-4323,-4325,
--4328,-4332,-4336,-4340,-4345,-4349,-4353,-4357,-4360,-4364,-4366,-4368,-4369,-4369,-4369,-4368,-4366,-4363,-4360,-4356,-4352,
--4346,-4341,-4335,-4329,-4323,-4317,-4310,-4304,-4299,-4293,-4289,-4284,-4281,-4278,-4276,-4275,-4274,-4275,-4276,-4279,-4282,
--4287,-4292,-4298,-4305,-4312,-4321,-4329,-4339,-4348,-4358,-4368,-4378,-4388,-4398,-4408,-4417,-4425,-4434,-4441,-4448,-4453,
--4458,-4462,-4465,-4467,-4468,-4467,-4466,-4463,-4460,-4455,-4449,-4442,-4434,-4425,-4415,-4405,-4394,-4382,-4369,-4356,-4342,
--4329,-4314,-4300,-4286,-4271,-4257,-4242,-4228,-4214,-4200,-4187,-4174,-4161,-4149,-4137,-4126,-4115,-4105,-4095,-4086,-4077,
--4069,-4061,-4054,-4047,-4041,-4035,-4029,-4024,-4019,-4014,-4010,-4006,-4002,-3997,-3994,-3990,-3986,-3982,-3978,-3973,-3969,
--3965,-3960,-3955,-3950,-3945,-3940,-3934,-3929,-3923,-3917,-3911,-3905,-3899,-3893,-3887,-3881,-3876,-3870,-3865,-3860,-3855,
--3851,-3847,-3843,-3840,-3837,-3835,-3833,-3832,-3831,-3831,-3831,-3831,-3832,-3833,-3834,-3836,-3837,-3839,-3841,-3843,-3844,
--3845,-3846,-3847,-3847,-3847,-3846,-3845,-3842,-3840,-3836,-3832,-3827,-3821,-3814,-3807,-3799,-3790,-3781,-3771,-3761,-3750,
--3739,-3728,-3716,-3704,-3693,-3681,-3670,-3659,-3647,-3637,-3627,-3617,-3608,-3599,-3590,-3583,-3575,-3569,-3562,-3557,-3551,
--3546,-3542,-3538,-3533,-3529,-3526,-3522,-3518,-3514,-3509,-3504,-3500,-3494,-3488,-3482,-3475,-3468,-3460,-3451,-3442,-3432,
--3422,-3411,-3400,-3389,-3376,-3364,-3351,-3338,-3325,-3312,-3298,-3285,-3271,-3258,-3245,-3232,-3219,-3206,-3193,-3181,-3169,
--3157,-3145,-3133,-3122,-3111,-3100,-3088,-3077,-3066,-3055,-3044,-3033,-3022,-3011,-2999,-2987,-2975,-2963,-2951,-2939,-2926,
--2914,-2901,-2888,-2876,-2863,-2850,-2838,-2826,-2814,-2802,-2791,-2781,-2771,-2761,-2752,-2744,-2736,-2730,-2724,-2719,-2715,
--2711,-2709,-2707,-2707,-2707,-2708,-2709,-2712,-2715,-2719,-2723,-2729,-2734,-2741,-2747,-2754,-2762,-2770,-2778,-2786,-2795,
--2803,-2812,-2821,-2830,-2839,-2848,-2857,-2867,-2876,-2884,-2893,-2902,-2910,-2919,-2927,-2935,-2943,-2950,-2957,-2964,-2971,
--2977,-2983,-2988,-2993,-2997,-3001,-3004,-3007,-3010,-3011,-3012,-3013,-3013,-3013,-3011,-3010,-3008,-3005,-3002,-2998,-2994,
--2989,-2984,-2978,-2973,-2966,-2960,-2953,-2946,-2938,-2930,-2922,-2914,-2905,-2895,-2886,-2876,-2865,-2854,-2843,-2831,-2818,
--2805,-2792,-2777,-2762,-2747,-2730,-2713,-2696,-2678,-2659,-2640,-2620,-2600,-2580,-2560,-2539,-2519,-2499,-2479,-2460,-2441,
--2423,-2406,-2391,-2376,-2363,-2351,-2341,-2332,-2326,-2321,-2318,-2318,-2319,-2322,-2328,-2335,-2344,-2355,-2368,-2383,-2399,
--2416,-2434,-2453,-2473,-2494,-2514,-2535,-2556,-2576,-2596,-2615,-2633,-2650,-2665,-2679,-2692,-2702,-2712,-2719,-2724,-2728,
--2729,-2729,-2727,-2723,-2718,-2711,-2703,-2694,-2683,-2672,-2660,-2647,-2635,-2622,-2608,-2596,-2583,-2571,-2559,-2549,-2539,
--2530,-2522,-2515,-2509,-2504,-2500,-2497,-2495,-2494,-2493,-2493,-2494,-2495,-2497,-2498,-2500,-2501,-2502,-2502,-2502,-2500,
--2498,-2495,-2490,-2485,-2477,-2469,-2458,-2446,-2433,-2418,-2401,-2383,-2363,-2342,-2320,-2296,-2272,-2246,-2220,-2193,-2166,
--2138,-2111,-2083,-2056,-2029,-2003,-1978,-1953,-1930,-1908,-1888,-1869,-1851,-1836,-1822,-1810,-1800,-1792,-1786,-1782,-1779,
--1779,-1780,-1783,-1787,-1793,-1800,-1809,-1818,-1829,-1840,-1851,-1864,-1876,-1889,-1901,-1913,-1925,-1937,-1948,-1958,-1968,
--1976,-1984,-1991,-1997,-2001,-2005,-2007,-2008,-2009,-2008,-2006,-2003,-2000,-1995,-1990,-1985,-1979,-1972,-1965,-1958,-1951,
--1943,-1936,-1928,-1921,-1914,-1907,-1901,-1894,-1888,-1882,-1877,-1872,-1867,-1862,-1858,-1853,-1849,-1845,-1841,-1837,-1832,
--1828,-1823,-1818,-1813,-1807,-1801,-1794,-1787,-1780,-1772,-1764,-1755,-1746,-1737,-1727,-1717,-1706,-1696,-1685,-1674,-1664,
--1653,-1643,-1632,-1622,-1613,-1604,-1595,-1587,-1579,-1572,-1565,-1559,-1554,-1549,-1545,-1542,-1539,-1536,-1535,-1533,-1532,
--1532,-1532,-1532,-1533,-1534,-1535,-1536,-1537,-1538,-1539,-1541,-1542,-1543,-1544,-1544,-1545,-1546,-1546,-1546,-1546,-1546,
--1545,-1545,-1544,-1543,-1542,-1541,-1540,-1538,-1537,-1536,-1534,-1533,-1532,-1530,-1529,-1528,-1527,-1526,-1525,-1525,-1524,
--1524,-1524,-1536,-1533,-1531,-1530,-1529,-1528,-1528,-1529,-1530,-1531,-1533,-1536,-1538,-1542,-1545,-1549,-1554,-1558,-1563,
--1567,-1572,-1577,-1581,-1586,-1590,-1593,-1597,-1599,-1601,-1602,-1603,-1603,-1602,-1600,-1597,-1593,-1588,-1582,-1575,-1567,
--1559,-1549,-1539,-1528,-1516,-1504,-1491,-1478,-1464,-1451,-1437,-1424,-1410,-1397,-1384,-1372,-1360,-1350,-1339,-1330,-1321,
--1314,-1307,-1301,-1297,-1293,-1290,-1288,-1287,-1287,-1288,-1289,-1291,-1293,-1296,-1299,-1302,-1305,-1308,-1311,-1313,-1315,
--1317,-1318,-1319,-1319,-1318,-1316,-1313,-1309,-1305,-1300,-1293,-1286,-1278,-1269,-1259,-1249,-1238,-1226,-1214,-1202,-1189,
--1176,-1163,-1150,-1136,-1123,-1110,-1098,-1085,-1073,-1061,-1050,-1039,-1029,-1019,-1010,-1001,-992,-984,-977,-970,-963,
--957,-951,-945,-940,-935,-930,-925,-921,-916,-912,-908,-904,-900,-896,-892,-888,-884,-880,-877,-874,-870,
--867,-864,-862,-860,-858,-856,-855,-854,-853,-853,-853,-854,-855,-857,-859,-861,-864,-867,-871,-874,-878,
--882,-887,-891,-896,-901,-905,-910,-915,-919,-923,-927,-931,-935,-938,-941,-943,-946,-948,-949,-950,-951,
--951,-951,-951,-950,-949,-948,-947,-945,-943,-941,-938,-936,-933,-930,-928,-925,-922,-919,-917,-914,-912,
--910,-907,-905,-903,-902,-900,-899,-898,-897,-896,-896,-895,-895,-895,-895,-896,-896,-897,-898,-899,-900,
--901,-902,-903,-904,-906,-907,-908,-909,-910,-911,-912,-913,-914,-915,-915,-915,-916,-916,-916,-916,-915,
--915,-914,-914,-913,-912,-911,-910,-909,-908,-907,-906,-905,-904,-903,-902,-902,-901,-901,-901,-901,-902,
--902,-903,-905,-906,-908,-911,-913,-916,-919,-923,-927,-931,-936,-941,-946,-951,-957,-964,-970,-977,-984,
--991,-999,-1007,-1015,-1024,-1032,-1041,-1050,-1059,-1069,-1079,-1088,-1098,-1108,-1119,-1129,-1140,-1150,-1161,-1171,-1182,
--1193,-1203,-1214,-1225,-1235,-1246,-1257,-1267,-1278,-1288,-1298,-1308,-1318,-1328,-1338,-1348,-1357,-1367,-1377,-1386,-1396,
--1405,-1415,-1424,-1434,-1443,-1453,-1463,-1473,-1483,-1494,-1504,-1515,-1526,-1537,-1549,-1561,-1572,-1585,-1597,-1610,-1623,
--1636,-1649,-1662,-1675,-1689,-1702,-1716,-1729,-1743,-1756,-1770,-1783,-1796,-1809,-1821,-1834,-1846,-1858,-1869,-1881,-1892,
--1903,-1913,-1923,-1934,-1943,-1953,-1962,-1972,-1981,-1990,-1999,-2008,-2017,-2026,-2035,-2043,-2052,-2061,-2071,-2080,-2089,
--2098,-2108,-2118,-2127,-2137,-2147,-2157,-2167,-2177,-2187,-2197,-2207,-2216,-2226,-2236,-2246,-2256,-2265,-2275,-2284,-2294,
--2303,-2312,-2322,-2331,-2340,-2349,-2358,-2368,-2377,-2386,-2396,-2406,-2416,-2426,-2436,-2447,-2458,-2469,-2480,-2492,-2504,
--2517,-2529,-2543,-2556,-2570,-2584,-2599,-2613,-2628,-2644,-2659,-2675,-2691,-2707,-2723,-2740,-2756,-2773,-2789,-2806,-2822,
--2839,-2855,-2872,-2888,-2904,-2921,-2937,-2953,-2968,-2984,-3000,-3015,-3031,-3046,-3061,-3076,-3091,-3105,-3120,-3134,-3149,
--3163,-3177,-3191,-3205,-3219,-3232,-3246,-3259,-3272,-3285,-3298,-3311,-3324,-3336,-3348,-3361,-3372,-3384,-3396,-3407,-3418,
--3429,-3440,-3450,-3460,-3470,-3479,-3489,-3498,-3507,-3515,-3523,-3531,-3539,-3546,-3553,-3559,-3565,-3571,-3577,-3582,-3587,
--3591,-3595,-3599,-3602,-3605,-3608,-3610,-3612,-3614,-3616,-3617,-3618,-3619,-3620,-3621,-3621,-3622,-3622,-3623,-3624,-3624,
--3625,-3626,-3627,-3629,-3630,-3632,-3634,-3636,-3639,-3642,-3645,-3648,-3651,-3655,-3659,-3663,-3667,-3671,-3675,-3679,-3683,
--3687,-3690,-3694,-3697,-3700,-3702,-3704,-3706,-3707,-3708,-3708,-3708,-3707,-3706,-3704,-3702,-3699,-3697,-3693,-3690,-3686,
--3682,-3678,-3674,-3670,-3666,-3663,-3659,-3656,-3654,-3652,-3650,-3649,-3648,-3649,-3649,-3651,-3653,-3656,-3659,-3663,-3667,
--3672,-3676,-3682,-3687,-3692,-3697,-3702,-3706,-3710,-3713,-3715,-3716,-3717,-3716,-3714,-3711,-3706,-3700,-3693,-3684,-3673,
--3662,-3649,-3634,-3619,-3602,-3585,-3567,-3548,-3529,-3510,-3491,-3472,-3454,-3436,-3420,-3405,-3392,-3380,-3370,-3362,-3357,
--3354,-3354,-3356,-3361,-3368,-3378,-3391,-3407,-3425,-3445,-3468,-3492,-3519,-3546,-3575,-3605,-3636,-3666,-3697,-3728,-3757,
--3786,-3813,-3839,-3863,-3885,-3904,-3921,-3935,-3947,-3955,-3961,-3963,-3963,-3960,-3954,-3945,-3935,-3922,-3907,-3890,-3872,
--3853,-3834,-3814,-3794,-3774,-3756,-3738,-3721,-3706,-3693,-3683,-3674,-3669,-3665,-3665,-3668,-3674,-3682,-3694,-3708,-3725,
--3744,-3766,-3790,-3816,-3843,-3872,-3902,-3932,-3963,-3994,-4025,-4055,-4085,-4113,-4140,-4166,-4189,-4211,-4231,-4249,-4264,
--4277,-4287,-4295,-4301,-4305,-4306,-4306,-4303,-4299,-4294,-4287,-4279,-4270,-4260,-4250,-4240,-4229,-4219,-4209,-4200,-4191,
--4184,-4177,-4171,-4166,-4163,-4160,-4159,-4159,-4161,-4163,-4166,-4170,-4176,-4181,-4188,-4195,-4202,-4209,-4217,-4224,-4232,
--4239,-4245,-4251,-4256,-4261,-4265,-4268,-4270,-4271,-4272,-4271,-4270,-4268,-4265,-4262,-4258,-4253,-4248,-4243,-4238,-4233,
--4227,-4222,-4217,-4213,-4209,-4206,-4203,-4201,-4200,-4200,-4200,-4202,-4205,-4208,-4213,-4218,-4224,-4231,-4239,-4247,-4256,
--4266,-4275,-4285,-4296,-4306,-4316,-4326,-4336,-4345,-4354,-4362,-4369,-4376,-4381,-4386,-4390,-4392,-4394,-4394,-4394,-4392,
--4389,-4385,-4379,-4373,-4366,-4358,-4349,-4339,-4328,-4317,-4305,-4293,-4280,-4268,-4254,-4241,-4228,-4215,-4202,-4189,-4176,
--4163,-4151,-4140,-4128,-4118,-4107,-4097,-4088,-4079,-4070,-4062,-4055,-4047,-4040,-4034,-4028,-4022,-4016,-4010,-4005,-3999,
--3994,-3989,-3983,-3978,-3972,-3967,-3961,-3955,-3949,-3942,-3936,-3929,-3922,-3916,-3909,-3901,-3894,-3887,-3880,-3873,-3865,
--3859,-3852,-3845,-3839,-3833,-3828,-3822,-3818,-3813,-3809,-3806,-3803,-3801,-3799,-3798,-3797,-3797,-3797,-3797,-3798,-3800,
--3801,-3803,-3805,-3807,-3809,-3811,-3812,-3814,-3815,-3816,-3816,-3816,-3815,-3814,-3812,-3809,-3805,-3801,-3795,-3789,-3782,
--3774,-3765,-3756,-3746,-3735,-3723,-3711,-3699,-3686,-3673,-3659,-3646,-3632,-3619,-3606,-3593,-3581,-3569,-3557,-3547,-3536,
--3527,-3519,-3511,-3504,-3498,-3493,-3489,-3486,-3483,-3481,-3480,-3480,-3480,-3480,-3481,-3482,-3483,-3485,-3486,-3487,-3488,
--3488,-3488,-3487,-3486,-3484,-3481,-3477,-3472,-3467,-3460,-3453,-3444,-3435,-3424,-3413,-3401,-3388,-3374,-3360,-3345,-3330,
--3314,-3298,-3282,-3265,-3249,-3232,-3216,-3199,-3183,-3167,-3152,-3137,-3122,-3108,-3094,-3081,-3068,-3056,-3044,-3033,-3022,
--3011,-3001,-2991,-2982,-2972,-2963,-2954,-2945,-2936,-2927,-2918,-2909,-2900,-2891,-2882,-2872,-2863,-2853,-2843,-2833,-2823,
--2813,-2803,-2793,-2783,-2773,-2763,-2754,-2745,-2736,-2728,-2720,-2712,-2705,-2699,-2694,-2689,-2685,-2681,-2679,-2677,-2676,
--2676,-2677,-2679,-2682,-2685,-2690,-2695,-2701,-2708,-2716,-2724,-2733,-2742,-2753,-2763,-2774,-2785,-2797,-2809,-2821,-2833,
--2845,-2857,-2869,-2881,-2892,-2904,-2914,-2925,-2935,-2944,-2953,-2961,-2968,-2975,-2981,-2986,-2990,-2994,-2997,-2999,-3000,
--3000,-3000,-2999,-2997,-2995,-2991,-2988,-2984,-2979,-2973,-2968,-2962,-2955,-2949,-2942,-2935,-2927,-2920,-2912,-2904,-2897,
--2889,-2881,-2872,-2864,-2856,-2847,-2838,-2829,-2820,-2810,-2800,-2789,-2778,-2767,-2754,-2742,-2729,-2715,-2700,-2685,-2669,
--2653,-2636,-2618,-2600,-2582,-2563,-2544,-2525,-2505,-2486,-2467,-2448,-2430,-2412,-2396,-2380,-2365,-2351,-2338,-2327,-2318,
--2310,-2304,-2299,-2297,-2296,-2298,-2301,-2306,-2313,-2321,-2332,-2344,-2357,-2372,-2388,-2405,-2423,-2441,-2460,-2479,-2498,
--2517,-2536,-2554,-2572,-2588,-2604,-2618,-2631,-2643,-2652,-2661,-2667,-2672,-2675,-2677,-2676,-2674,-2671,-2666,-2659,-2652,
--2643,-2633,-2623,-2612,-2601,-2589,-2577,-2565,-2554,-2543,-2532,-2523,-2514,-2505,-2498,-2492,-2487,-2483,-2480,-2478,-2478,
--2478,-2479,-2481,-2483,-2486,-2490,-2493,-2497,-2500,-2504,-2507,-2509,-2510,-2511,-2510,-2508,-2505,-2500,-2494,-2486,-2476,
--2464,-2450,-2435,-2418,-2399,-2378,-2356,-2333,-2307,-2281,-2254,-2226,-2197,-2167,-2137,-2108,-2078,-2048,-2019,-1991,-1964,
--1938,-1913,-1889,-1868,-1848,-1829,-1813,-1799,-1787,-1777,-1769,-1763,-1759,-1757,-1757,-1759,-1763,-1769,-1775,-1784,-1793,
--1804,-1815,-1827,-1839,-1852,-1865,-1878,-1890,-1902,-1914,-1925,-1935,-1945,-1953,-1961,-1967,-1972,-1976,-1978,-1980,-1980,
--1979,-1977,-1974,-1970,-1965,-1959,-1953,-1946,-1938,-1930,-1922,-1913,-1905,-1896,-1888,-1880,-1872,-1864,-1857,-1850,-1844,
--1838,-1832,-1827,-1823,-1819,-1815,-1812,-1809,-1807,-1805,-1803,-1801,-1799,-1797,-1795,-1792,-1790,-1787,-1784,-1781,-1777,
--1772,-1768,-1762,-1756,-1750,-1743,-1736,-1728,-1720,-1712,-1703,-1694,-1684,-1675,-1665,-1656,-1647,-1637,-1628,-1620,-1611,
--1603,-1596,-1588,-1582,-1576,-1571,-1566,-1562,-1558,-1556,-1553,-1552,-1551,-1551,-1551,-1552,-1553,-1554,-1556,-1558,-1561,
--1563,-1566,-1569,-1572,-1575,-1578,-1580,-1583,-1585,-1587,-1588,-1589,-1590,-1591,-1591,-1591,-1590,-1589,-1588,-1586,-1584,
--1581,-1579,-1576,-1572,-1569,-1566,-1562,-1558,-1555,-1551,-1547,-1544,-1541,-1538,-1536,-1549,-1546,-1543,-1541,-1540,-1539,
--1538,-1538,-1538,-1539,-1540,-1542,-1545,-1548,-1551,-1555,-1559,-1563,-1567,-1572,-1577,-1581,-1586,-1590,-1595,-1598,-1602,
--1605,-1607,-1610,-1611,-1611,-1611,-1610,-1609,-1606,-1603,-1598,-1593,-1587,-1581,-1573,-1565,-1556,-1547,-1537,-1527,-1516,
--1505,-1494,-1483,-1471,-1460,-1449,-1439,-1428,-1418,-1409,-1400,-1392,-1385,-1378,-1372,-1366,-1362,-1358,-1355,-1353,-1351,
--1350,-1350,-1350,-1351,-1352,-1353,-1355,-1356,-1358,-1360,-1362,-1364,-1365,-1366,-1367,-1367,-1366,-1365,-1364,-1361,-1358,
--1355,-1350,-1345,-1340,-1333,-1326,-1318,-1310,-1301,-1292,-1282,-1272,-1261,-1250,-1240,-1229,-1217,-1206,-1195,-1184,-1174,
--1163,-1153,-1143,-1133,-1124,-1115,-1106,-1098,-1090,-1082,-1075,-1068,-1062,-1055,-1049,-1043,-1038,-1033,-1027,-1022,-1017,
--1013,-1008,-1003,-999,-994,-989,-985,-981,-976,-972,-967,-963,-959,-955,-951,-948,-944,-941,-938,-935,-933,
--931,-929,-927,-926,-926,-925,-925,-926,-927,-928,-930,-932,-934,-937,-940,-943,-947,-950,-954,-958,-962,
--967,-971,-975,-979,-983,-987,-991,-995,-998,-1002,-1005,-1007,-1010,-1012,-1014,-1016,-1017,-1018,-1019,-1020,-1020,
--1020,-1020,-1020,-1019,-1018,-1018,-1017,-1016,-1014,-1013,-1012,-1011,-1010,-1009,-1008,-1007,-1006,-1005,-1004,-1004,-1003,
--1003,-1003,-1003,-1003,-1003,-1004,-1004,-1005,-1006,-1007,-1008,-1009,-1010,-1011,-1013,-1014,-1015,-1017,-1018,-1020,-1021,
--1022,-1024,-1025,-1026,-1028,-1029,-1030,-1031,-1032,-1033,-1034,-1034,-1035,-1036,-1036,-1037,-1038,-1038,-1039,-1039,-1040,
--1040,-1041,-1042,-1042,-1043,-1044,-1045,-1046,-1047,-1049,-1050,-1052,-1054,-1056,-1058,-1060,-1063,-1066,-1069,-1072,-1075,
--1079,-1083,-1087,-1091,-1096,-1101,-1106,-1111,-1117,-1123,-1129,-1135,-1142,-1149,-1156,-1163,-1171,-1178,-1186,-1195,-1203,
--1211,-1220,-1229,-1238,-1248,-1257,-1266,-1276,-1286,-1296,-1306,-1316,-1326,-1336,-1346,-1356,-1366,-1376,-1386,-1396,-1405,
--1415,-1425,-1435,-1444,-1454,-1463,-1473,-1482,-1491,-1501,-1510,-1519,-1528,-1537,-1547,-1556,-1565,-1575,-1584,-1594,-1603,
--1613,-1623,-1633,-1643,-1654,-1664,-1675,-1686,-1697,-1708,-1719,-1731,-1743,-1754,-1766,-1778,-1790,-1802,-1814,-1826,-1838,
--1849,-1861,-1873,-1884,-1896,-1907,-1918,-1929,-1939,-1950,-1960,-1970,-1979,-1989,-1998,-2007,-2016,-2025,-2034,-2042,-2051,
--2059,-2067,-2075,-2084,-2092,-2100,-2108,-2116,-2125,-2133,-2141,-2150,-2159,-2167,-2176,-2186,-2195,-2204,-2213,-2223,-2233,
--2242,-2252,-2262,-2272,-2282,-2292,-2302,-2312,-2322,-2332,-2342,-2352,-2362,-2372,-2382,-2392,-2402,-2412,-2421,-2431,-2441,
--2450,-2460,-2470,-2480,-2490,-2500,-2510,-2520,-2530,-2541,-2552,-2563,-2574,-2585,-2596,-2608,-2620,-2632,-2645,-2658,-2671,
--2684,-2697,-2711,-2725,-2739,-2753,-2767,-2782,-2796,-2811,-2826,-2841,-2856,-2871,-2886,-2901,-2916,-2930,-2945,-2960,-2975,
--2989,-3004,-3018,-3032,-3046,-3060,-3073,-3087,-3100,-3113,-3126,-3139,-3151,-3163,-3176,-3188,-3199,-3211,-3222,-3234,-3245,
--3256,-3266,-3277,-3287,-3298,-3308,-3318,-3328,-3338,-3347,-3357,-3366,-3375,-3384,-3393,-3401,-3410,-3418,-3426,-3434,-3441,
--3449,-3456,-3463,-3469,-3476,-3482,-3488,-3493,-3498,-3503,-3508,-3512,-3516,-3520,-3523,-3526,-3529,-3532,-3534,-3536,-3538,
--3540,-3541,-3543,-3544,-3545,-3546,-3547,-3548,-3549,-3550,-3552,-3553,-3554,-3556,-3558,-3560,-3562,-3565,-3568,-3571,-3574,
--3578,-3582,-3586,-3590,-3594,-3599,-3604,-3609,-3613,-3618,-3623,-3628,-3632,-3637,-3641,-3645,-3649,-3652,-3655,-3658,-3660,
--3661,-3662,-3663,-3663,-3663,-3663,-3661,-3660,-3658,-3656,-3653,-3651,-3648,-3645,-3642,-3639,-3636,-3633,-3630,-3628,-3626,
--3624,-3623,-3622,-3622,-3622,-3624,-3625,-3627,-3630,-3634,-3638,-3642,-3647,-3652,-3658,-3664,-3670,-3676,-3683,-3689,-3695,
--3700,-3706,-3710,-3714,-3718,-3720,-3722,-3723,-3723,-3722,-3720,-3717,-3713,-3707,-3701,-3694,-3686,-3678,-3669,-3659,-3649,
--3638,-3627,-3617,-3606,-3596,-3586,-3577,-3568,-3561,-3554,-3549,-3544,-3541,-3540,-3540,-3541,-3544,-3549,-3555,-3563,-3571,
--3582,-3593,-3605,-3619,-3633,-3647,-3662,-3677,-3692,-3707,-3721,-3734,-3747,-3758,-3769,-3777,-3785,-3790,-3794,-3795,-3795,
--3793,-3788,-3782,-3773,-3763,-3750,-3736,-3721,-3704,-3686,-3667,-3647,-3627,-3606,-3586,-3565,-3546,-3527,-3509,-3492,-3477,
--3463,-3452,-3442,-3435,-3430,-3427,-3427,-3429,-3434,-3442,-3451,-3463,-3478,-3494,-3512,-3533,-3554,-3577,-3601,-3626,-3651,
--3677,-3703,-3729,-3754,-3779,-3803,-3826,-3847,-3868,-3887,-3904,-3919,-3933,-3945,-3955,-3963,-3970,-3975,-3978,-3979,-3979,
--3978,-3976,-3972,-3968,-3963,-3958,-3952,-3946,-3940,-3935,-3929,-3925,-3921,-3917,-3915,-3914,-3913,-3914,-3916,-3919,-3923,
--3928,-3934,-3942,-3950,-3959,-3969,-3979,-3990,-4002,-4013,-4025,-4037,-4049,-4061,-4072,-4083,-4094,-4104,-4113,-4122,-4130,
--4137,-4143,-4149,-4153,-4157,-4160,-4162,-4164,-4164,-4165,-4164,-4164,-4163,-4162,-4160,-4159,-4158,-4156,-4155,-4154,-4154,
--4154,-4154,-4155,-4157,-4159,-4162,-4165,-4168,-4173,-4178,-4183,-4189,-4195,-4201,-4208,-4215,-4222,-4229,-4235,-4242,-4248,
--4255,-4260,-4265,-4270,-4274,-4277,-4280,-4282,-4283,-4283,-4283,-4281,-4279,-4276,-4272,-4267,-4262,-4256,-4249,-4242,-4234,
--4226,-4217,-4208,-4199,-4189,-4179,-4169,-4160,-4150,-4140,-4130,-4121,-4112,-4103,-4094,-4085,-4077,-4069,-4061,-4054,-4047,
--4040,-4033,-4026,-4019,-4013,-4007,-4000,-3994,-3987,-3981,-3974,-3968,-3961,-3953,-3946,-3939,-3931,-3923,-3915,-3906,-3897,
--3889,-3880,-3871,-3862,-3853,-3844,-3835,-3826,-3817,-3809,-3801,-3793,-3786,-3779,-3773,-3768,-3763,-3758,-3754,-3752,-3749,
--3747,-3747,-3746,-3747,-3747,-3749,-3751,-3753,-3756,-3759,-3763,-3766,-3770,-3773,-3776,-3779,-3782,-3784,-3786,-3787,-3787,
--3787,-3786,-3783,-3780,-3775,-3770,-3763,-3756,-3747,-3737,-3726,-3714,-3701,-3687,-3672,-3657,-3641,-3624,-3607,-3590,-3572,
--3554,-3537,-3520,-3503,-3486,-3471,-3456,-3441,-3428,-3416,-3405,-3395,-3387,-3379,-3374,-3369,-3366,-3364,-3363,-3364,-3365,
--3368,-3372,-3377,-3382,-3388,-3395,-3401,-3409,-3416,-3423,-3429,-3436,-3442,-3447,-3451,-3455,-3457,-3459,-3459,-3458,-3455,
--3451,-3446,-3439,-3431,-3421,-3410,-3398,-3385,-3370,-3354,-3337,-3320,-3302,-3283,-3263,-3243,-3223,-3203,-3183,-3162,-3143,
--3123,-3104,-3086,-3068,-3051,-3034,-3019,-3004,-2990,-2977,-2966,-2954,-2944,-2935,-2927,-2919,-2912,-2905,-2899,-2894,-2889,
--2884,-2880,-2875,-2871,-2867,-2863,-2858,-2853,-2848,-2843,-2837,-2831,-2824,-2817,-2810,-2802,-2794,-2785,-2776,-2766,-2757,
--2747,-2737,-2727,-2717,-2707,-2697,-2688,-2679,-2670,-2662,-2654,-2648,-2641,-2636,-2632,-2628,-2626,-2624,-2624,-2625,-2626,
--2629,-2633,-2638,-2645,-2652,-2660,-2669,-2679,-2690,-2701,-2714,-2726,-2740,-2753,-2767,-2781,-2796,-2810,-2824,-2838,-2851,
--2865,-2877,-2889,-2901,-2912,-2922,-2931,-2939,-2947,-2953,-2959,-2963,-2967,-2969,-2971,-2971,-2971,-2970,-2968,-2965,-2961,
--2956,-2951,-2945,-2939,-2932,-2924,-2917,-2908,-2900,-2891,-2881,-2872,-2862,-2852,-2842,-2832,-2821,-2811,-2800,-2789,-2777,
--2765,-2754,-2741,-2729,-2716,-2703,-2689,-2675,-2660,-2645,-2630,-2614,-2597,-2581,-2563,-2546,-2528,-2510,-2492,-2474,-2455,
--2437,-2419,-2401,-2384,-2367,-2350,-2335,-2320,-2306,-2293,-2282,-2271,-2262,-2255,-2249,-2244,-2241,-2239,-2239,-2241,-2244,
--2249,-2256,-2263,-2273,-2283,-2294,-2307,-2320,-2335,-2349,-2364,-2380,-2395,-2411,-2426,-2441,-2456,-2469,-2482,-2494,-2505,
--2515,-2524,-2532,-2538,-2543,-2546,-2548,-2549,-2549,-2547,-2545,-2541,-2536,-2531,-2525,-2519,-2512,-2504,-2497,-2490,-2483,
--2476,-2470,-2464,-2459,-2455,-2452,-2449,-2448,-2447,-2448,-2449,-2451,-2455,-2459,-2464,-2470,-2476,-2483,-2490,-2497,-2504,
--2511,-2518,-2524,-2529,-2534,-2537,-2539,-2540,-2540,-2538,-2534,-2528,-2521,-2511,-2500,-2486,-2471,-2454,-2434,-2413,-2391,
--2366,-2340,-2313,-2285,-2255,-2225,-2194,-2163,-2131,-2099,-2068,-2037,-2007,-1977,-1949,-1921,-1895,-1871,-1848,-1827,-1808,
--1790,-1775,-1762,-1750,-1741,-1734,-1728,-1725,-1723,-1724,-1726,-1729,-1733,-1739,-1746,-1754,-1763,-1772,-1782,-1791,-1801,
--1811,-1821,-1830,-1839,-1847,-1854,-1861,-1867,-1872,-1876,-1879,-1880,-1881,-1881,-1880,-1878,-1875,-1871,-1866,-1861,-1855,
--1848,-1842,-1834,-1827,-1819,-1812,-1804,-1797,-1789,-1782,-1776,-1770,-1764,-1758,-1753,-1749,-1745,-1742,-1739,-1737,-1735,
--1733,-1732,-1731,-1730,-1730,-1729,-1729,-1728,-1728,-1727,-1727,-1726,-1725,-1723,-1721,-1719,-1716,-1713,-1709,-1705,-1700,
--1695,-1690,-1684,-1678,-1672,-1665,-1658,-1651,-1644,-1637,-1630,-1623,-1616,-1610,-1603,-1597,-1592,-1586,-1582,-1577,-1573,
--1570,-1567,-1565,-1564,-1563,-1562,-1562,-1563,-1564,-1565,-1567,-1569,-1571,-1574,-1577,-1580,-1583,-1586,-1589,-1592,-1595,
--1598,-1600,-1602,-1604,-1606,-1607,-1607,-1607,-1607,-1607,-1606,-1604,-1602,-1600,-1597,-1594,-1591,-1587,-1583,-1579,-1575,
--1571,-1567,-1563,-1559,-1556,-1552,-1549,-1560,-1558,-1557,-1555,-1554,-1554,-1554,-1554,-1555,-1556,-1557,-1559,-1561,-1563,
--1566,-1569,-1572,-1575,-1579,-1583,-1586,-1590,-1593,-1597,-1600,-1603,-1605,-1608,-1610,-1611,-1612,-1612,-1612,-1611,-1610,
--1608,-1606,-1603,-1599,-1594,-1590,-1584,-1578,-1572,-1565,-1558,-1550,-1543,-1535,-1527,-1519,-1511,-1503,-1495,-1488,-1480,
--1473,-1467,-1460,-1455,-1449,-1444,-1440,-1436,-1433,-1430,-1428,-1426,-1425,-1424,-1424,-1424,-1424,-1425,-1426,-1426,-1427,
--1428,-1429,-1430,-1431,-1432,-1432,-1432,-1431,-1431,-1429,-1428,-1425,-1423,-1419,-1415,-1411,-1406,-1400,-1394,-1388,-1381,
--1374,-1366,-1358,-1349,-1340,-1331,-1322,-1313,-1304,-1294,-1285,-1276,-1266,-1257,-1248,-1240,-1231,-1223,-1215,-1207,-1199,
--1192,-1185,-1178,-1172,-1165,-1159,-1154,-1148,-1143,-1137,-1132,-1127,-1122,-1118,-1113,-1108,-1104,-1099,-1095,-1090,-1086,
--1081,-1077,-1072,-1068,-1063,-1059,-1055,-1050,-1046,-1042,-1038,-1035,-1031,-1028,-1025,-1022,-1019,-1017,-1015,-1014,-1012,
--1011,-1010,-1010,-1010,-1011,-1011,-1012,-1014,-1015,-1017,-1019,-1022,-1024,-1027,-1030,-1034,-1037,-1040,-1044,-1048,-1051,
--1055,-1059,-1062,-1066,-1069,-1072,-1076,-1079,-1082,-1085,-1087,-1090,-1092,-1094,-1096,-1098,-1100,-1101,-1103,-1104,-1105,
--1106,-1107,-1108,-1109,-1109,-1110,-1110,-1111,-1111,-1112,-1112,-1113,-1113,-1114,-1115,-1115,-1116,-1117,-1117,-1118,-1119,
--1120,-1121,-1122,-1123,-1124,-1125,-1126,-1127,-1128,-1130,-1131,-1132,-1134,-1135,-1136,-1138,-1139,-1140,-1142,-1143,-1144,
--1146,-1147,-1149,-1150,-1152,-1153,-1154,-1156,-1158,-1159,-1161,-1162,-1164,-1166,-1168,-1169,-1171,-1173,-1176,-1178,-1180,
--1182,-1185,-1188,-1190,-1193,-1196,-1199,-1202,-1206,-1209,-1213,-1216,-1220,-1224,-1229,-1233,-1238,-1242,-1247,-1253,-1258,
--1263,-1269,-1275,-1281,-1287,-1294,-1301,-1307,-1314,-1322,-1329,-1337,-1345,-1353,-1361,-1369,-1378,-1386,-1395,-1404,-1413,
--1422,-1431,-1441,-1450,-1460,-1469,-1479,-1488,-1498,-1508,-1517,-1527,-1537,-1546,-1556,-1566,-1575,-1585,-1594,-1604,-1613,
--1623,-1632,-1641,-1651,-1660,-1670,-1679,-1689,-1698,-1707,-1717,-1727,-1736,-1746,-1756,-1766,-1776,-1786,-1796,-1806,-1816,
--1826,-1836,-1847,-1857,-1867,-1878,-1888,-1899,-1909,-1919,-1930,-1940,-1950,-1960,-1970,-1980,-1989,-1999,-2008,-2017,-2027,
--2035,-2044,-2053,-2061,-2069,-2078,-2085,-2093,-2101,-2109,-2116,-2124,-2131,-2138,-2146,-2153,-2160,-2168,-2175,-2182,-2190,
--2198,-2205,-2213,-2221,-2229,-2238,-2246,-2255,-2263,-2272,-2281,-2291,-2300,-2309,-2319,-2329,-2338,-2348,-2358,-2368,-2378,
--2388,-2398,-2409,-2419,-2429,-2439,-2449,-2459,-2469,-2479,-2489,-2499,-2509,-2519,-2529,-2539,-2549,-2559,-2569,-2579,-2589,
--2599,-2609,-2619,-2630,-2640,-2650,-2661,-2672,-2683,-2694,-2705,-2716,-2728,-2739,-2751,-2763,-2775,-2788,-2800,-2813,-2826,
--2839,-2852,-2865,-2878,-2891,-2904,-2918,-2931,-2945,-2958,-2971,-2985,-2998,-3011,-3025,-3038,-3050,-3063,-3076,-3088,-3101,
--3113,-3125,-3137,-3148,-3160,-3171,-3182,-3193,-3204,-3214,-3224,-3234,-3244,-3254,-3263,-3273,-3282,-3291,-3299,-3308,-3316,
--3324,-3332,-3340,-3348,-3355,-3362,-3369,-3376,-3383,-3389,-3396,-3402,-3408,-3413,-3419,-3424,-3429,-3433,-3438,-3442,-3446,
--3450,-3453,-3457,-3460,-3463,-3465,-3468,-3470,-3472,-3474,-3476,-3477,-3479,-3480,-3482,-3483,-3485,-3486,-3487,-3489,-3490,
--3492,-3494,-3496,-3498,-3500,-3503,-3506,-3509,-3512,-3515,-3519,-3523,-3527,-3532,-3536,-3541,-3546,-3551,-3556,-3562,-3567,
--3572,-3578,-3583,-3588,-3593,-3598,-3603,-3607,-3611,-3615,-3619,-3622,-3625,-3627,-3629,-3631,-3632,-3633,-3634,-3634,-3634,
--3633,-3633,-3632,-3630,-3629,-3628,-3626,-3625,-3623,-3622,-3621,-3620,-3619,-3619,-3619,-3619,-3620,-3621,-3623,-3625,-3627,
--3631,-3634,-3638,-3643,-3648,-3653,-3659,-3665,-3671,-3678,-3684,-3691,-3698,-3704,-3711,-3717,-3723,-3729,-3734,-3739,-3743,
--3747,-3750,-3752,-3754,-3756,-3756,-3756,-3756,-3754,-3753,-3750,-3748,-3744,-3741,-3737,-3733,-3728,-3724,-3719,-3715,-3711,
--3707,-3703,-3699,-3696,-3693,-3690,-3688,-3686,-3685,-3684,-3684,-3684,-3684,-3685,-3686,-3687,-3688,-3689,-3690,-3690,-3691,
--3691,-3691,-3690,-3688,-3686,-3683,-3679,-3673,-3667,-3660,-3652,-3643,-3632,-3620,-3608,-3594,-3580,-3564,-3548,-3531,-3514,
--3496,-3478,-3460,-3442,-3424,-3407,-3390,-3373,-3358,-3343,-3330,-3318,-3307,-3298,-3290,-3284,-3280,-3277,-3277,-3278,-3281,
--3286,-3292,-3300,-3310,-3321,-3334,-3348,-3363,-3379,-3395,-3413,-3431,-3449,-3467,-3485,-3503,-3521,-3538,-3555,-3571,-3586,
--3599,-3612,-3624,-3635,-3644,-3652,-3659,-3665,-3669,-3672,-3675,-3676,-3676,-3676,-3675,-3673,-3671,-3669,-3666,-3664,-3661,
--3659,-3657,-3656,-3655,-3655,-3655,-3657,-3659,-3662,-3667,-3672,-3678,-3686,-3694,-3704,-3714,-3725,-3737,-3750,-3763,-3778,
--3792,-3807,-3822,-3838,-3854,-3869,-3885,-3900,-3915,-3930,-3944,-3958,-3971,-3984,-3996,-4007,-4018,-4028,-4037,-4046,-4054,
--4061,-4067,-4073,-4079,-4083,-4088,-4092,-4095,-4099,-4102,-4104,-4107,-4110,-4112,-4114,-4117,-4119,-4122,-4124,-4127,-4130,
--4132,-4135,-4138,-4141,-4144,-4147,-4150,-4153,-4156,-4159,-4161,-4164,-4166,-4167,-4169,-4170,-4171,-4171,-4171,-4170,-4169,
--4167,-4165,-4162,-4159,-4155,-4151,-4147,-4142,-4136,-4131,-4125,-4118,-4111,-4105,-4097,-4090,-4083,-4075,-4068,-4060,-4053,
--4045,-4038,-4030,-4023,-4015,-4008,-4001,-3994,-3986,-3979,-3972,-3965,-3958,-3951,-3944,-3936,-3929,-3921,-3914,-3906,-3897,
--3889,-3880,-3872,-3862,-3853,-3844,-3834,-3824,-3814,-3804,-3793,-3783,-3772,-3762,-3752,-3742,-3732,-3722,-3713,-3704,-3696,
--3688,-3680,-3674,-3668,-3663,-3658,-3654,-3652,-3650,-3649,-3648,-3649,-3650,-3652,-3655,-3659,-3663,-3668,-3673,-3678,-3684,
--3690,-3696,-3702,-3708,-3714,-3719,-3724,-3728,-3731,-3734,-3736,-3736,-3736,-3734,-3731,-3727,-3722,-3715,-3707,-3698,-3687,
--3675,-3662,-3647,-3632,-3615,-3598,-3580,-3561,-3542,-3522,-3502,-3482,-3462,-3442,-3422,-3404,-3385,-3368,-3351,-3336,-3321,
--3308,-3297,-3286,-3278,-3271,-3265,-3261,-3259,-3258,-3259,-3261,-3265,-3269,-3276,-3283,-3291,-3300,-3309,-3319,-3329,-3340,
--3350,-3361,-3371,-3380,-3389,-3396,-3403,-3409,-3414,-3417,-3419,-3419,-3417,-3414,-3410,-3403,-3395,-3386,-3374,-3362,-3347,
--3332,-3315,-3297,-3278,-3258,-3237,-3215,-3193,-3171,-3149,-3126,-3104,-3082,-3060,-3039,-3018,-2999,-2980,-2962,-2945,-2930,
--2915,-2902,-2889,-2878,-2868,-2860,-2852,-2846,-2840,-2836,-2832,-2829,-2827,-2825,-2824,-2823,-2822,-2822,-2821,-2821,-2820,
--2819,-2817,-2815,-2813,-2810,-2806,-2802,-2797,-2791,-2785,-2778,-2770,-2762,-2753,-2743,-2733,-2722,-2712,-2701,-2689,-2678,
--2667,-2656,-2645,-2635,-2625,-2615,-2607,-2599,-2592,-2586,-2581,-2577,-2574,-2572,-2572,-2573,-2575,-2578,-2582,-2588,-2595,
--2603,-2613,-2623,-2634,-2646,-2659,-2673,-2687,-2702,-2717,-2733,-2749,-2764,-2780,-2796,-2811,-2827,-2841,-2855,-2869,-2882,
--2894,-2905,-2916,-2925,-2934,-2941,-2948,-2953,-2958,-2961,-2963,-2964,-2964,-2963,-2961,-2958,-2954,-2950,-2944,-2937,-2930,
--2922,-2913,-2903,-2893,-2882,-2870,-2858,-2845,-2832,-2818,-2804,-2789,-2774,-2758,-2742,-2725,-2708,-2691,-2673,-2655,-2637,
--2618,-2599,-2579,-2560,-2540,-2520,-2500,-2480,-2460,-2440,-2420,-2401,-2381,-2362,-2344,-2326,-2308,-2292,-2276,-2261,-2246,
--2233,-2221,-2210,-2201,-2192,-2185,-2179,-2175,-2172,-2170,-2170,-2171,-2174,-2178,-2183,-2189,-2196,-2205,-2214,-2224,-2235,
--2246,-2258,-2270,-2283,-2296,-2308,-2321,-2333,-2345,-2357,-2368,-2379,-2388,-2397,-2405,-2413,-2419,-2425,-2429,-2433,-2436,
--2438,-2439,-2440,-2440,-2439,-2438,-2437,-2435,-2433,-2431,-2429,-2428,-2426,-2425,-2424,-2424,-2425,-2426,-2428,-2431,-2434,
--2439,-2444,-2450,-2456,-2463,-2471,-2480,-2489,-2498,-2508,-2518,-2527,-2537,-2546,-2555,-2563,-2570,-2576,-2582,-2586,-2588,
--2590,-2589,-2587,-2583,-2577,-2570,-2560,-2548,-2535,-2519,-2501,-2482,-2460,-2437,-2412,-2386,-2358,-2329,-2299,-2268,-2236,
--2204,-2171,-2139,-2106,-2073,-2041,-2009,-1978,-1948,-1919,-1891,-1864,-1839,-1816,-1794,-1774,-1756,-1739,-1725,-1712,-1701,
--1691,-1684,-1678,-1674,-1671,-1669,-1669,-1671,-1673,-1676,-1680,-1685,-1690,-1695,-1701,-1707,-1713,-1719,-1725,-1730,-1736,
--1740,-1745,-1748,-1751,-1754,-1755,-1757,-1757,-1757,-1756,-1754,-1752,-1750,-1747,-1743,-1739,-1735,-1731,-1727,-1722,-1717,
--1713,-1708,-1704,-1700,-1696,-1692,-1689,-1685,-1683,-1680,-1678,-1676,-1675,-1674,-1673,-1673,-1672,-1672,-1672,-1672,-1673,
--1673,-1673,-1674,-1674,-1674,-1674,-1673,-1673,-1672,-1671,-1670,-1668,-1666,-1664,-1661,-1658,-1655,-1651,-1648,-1644,-1639,
--1635,-1631,-1626,-1622,-1617,-1613,-1608,-1604,-1600,-1596,-1592,-1589,-1586,-1583,-1581,-1579,-1577,-1576,-1575,-1574,-1574,
--1574,-1574,-1575,-1576,-1577,-1578,-1580,-1582,-1583,-1585,-1587,-1589,-1591,-1593,-1594,-1596,-1597,-1598,-1599,-1599,-1599,
--1599,-1599,-1598,-1597,-1596,-1594,-1592,-1590,-1588,-1586,-1583,-1580,-1578,-1575,-1572,-1569,-1567,-1564,-1562,-1560,-1584,
--1583,-1583,-1583,-1583,-1584,-1584,-1585,-1586,-1587,-1589,-1590,-1592,-1594,-1596,-1598,-1600,-1603,-1605,-1607,-1609,-1611,
--1613,-1615,-1616,-1618,-1619,-1619,-1620,-1620,-1620,-1619,-1618,-1617,-1615,-1613,-1610,-1607,-1604,-1600,-1596,-1591,-1587,
--1582,-1577,-1571,-1566,-1561,-1555,-1549,-1544,-1538,-1533,-1528,-1523,-1518,-1513,-1509,-1505,-1501,-1498,-1495,-1492,-1490,
--1488,-1487,-1485,-1485,-1484,-1484,-1484,-1484,-1484,-1485,-1486,-1486,-1487,-1488,-1488,-1489,-1489,-1489,-1489,-1489,-1488,
--1487,-1486,-1484,-1482,-1480,-1477,-1473,-1469,-1465,-1461,-1455,-1450,-1444,-1438,-1431,-1424,-1417,-1410,-1402,-1395,-1387,
--1379,-1371,-1362,-1354,-1346,-1338,-1330,-1323,-1315,-1307,-1300,-1293,-1286,-1279,-1273,-1266,-1260,-1254,-1248,-1243,-1238,
--1233,-1228,-1223,-1218,-1214,-1209,-1205,-1200,-1196,-1192,-1188,-1184,-1180,-1176,-1172,-1168,-1165,-1161,-1157,-1153,-1149,
--1146,-1142,-1139,-1135,-1132,-1129,-1126,-1123,-1120,-1118,-1115,-1113,-1111,-1109,-1108,-1107,-1106,-1105,-1105,-1105,-1105,
--1105,-1106,-1107,-1108,-1110,-1112,-1114,-1116,-1118,-1121,-1124,-1127,-1130,-1133,-1136,-1140,-1143,-1147,-1150,-1154,-1157,
--1161,-1164,-1168,-1171,-1175,-1178,-1181,-1185,-1188,-1191,-1194,-1196,-1199,-1201,-1204,-1206,-1208,-1211,-1213,-1214,-1216,
--1218,-1220,-1221,-1223,-1224,-1225,-1227,-1228,-1229,-1230,-1231,-1233,-1234,-1235,-1236,-1237,-1238,-1239,-1240,-1241,-1242,
--1243,-1244,-1245,-1246,-1247,-1249,-1250,-1251,-1252,-1253,-1255,-1256,-1257,-1259,-1260,-1262,-1263,-1265,-1267,-1268,-1270,
--1272,-1274,-1276,-1278,-1280,-1282,-1284,-1286,-1289,-1291,-1294,-1296,-1299,-1301,-1304,-1307,-1310,-1313,-1316,-1320,-1323,
--1326,-1330,-1334,-1337,-1341,-1345,-1350,-1354,-1358,-1363,-1368,-1373,-1378,-1383,-1389,-1394,-1400,-1406,-1412,-1418,-1425,
--1431,-1438,-1445,-1452,-1459,-1467,-1475,-1482,-1490,-1498,-1507,-1515,-1524,-1532,-1541,-1550,-1559,-1568,-1577,-1586,-1596,
--1605,-1614,-1624,-1634,-1643,-1653,-1662,-1672,-1681,-1691,-1701,-1710,-1720,-1730,-1739,-1749,-1759,-1768,-1778,-1788,-1797,
--1807,-1816,-1826,-1836,-1845,-1855,-1864,-1874,-1884,-1893,-1903,-1913,-1922,-1932,-1941,-1951,-1960,-1970,-1979,-1988,-1997,
--2007,-2016,-2025,-2033,-2042,-2051,-2059,-2068,-2076,-2084,-2092,-2100,-2108,-2115,-2123,-2130,-2137,-2144,-2151,-2158,-2165,
--2172,-2179,-2185,-2192,-2198,-2205,-2211,-2218,-2225,-2231,-2238,-2245,-2252,-2259,-2266,-2273,-2280,-2288,-2295,-2303,-2311,
--2319,-2327,-2335,-2344,-2352,-2361,-2370,-2379,-2388,-2397,-2406,-2416,-2425,-2435,-2444,-2454,-2464,-2474,-2483,-2493,-2503,
--2513,-2523,-2532,-2542,-2552,-2562,-2571,-2581,-2591,-2601,-2610,-2620,-2630,-2640,-2650,-2659,-2669,-2679,-2689,-2699,-2710,
--2720,-2730,-2740,-2751,-2762,-2772,-2783,-2794,-2805,-2816,-2828,-2839,-2851,-2862,-2874,-2886,-2898,-2910,-2922,-2934,-2946,
--2958,-2970,-2982,-2994,-3006,-3018,-3030,-3042,-3054,-3066,-3078,-3089,-3101,-3112,-3123,-3134,-3145,-3156,-3166,-3176,-3187,
--3196,-3206,-3216,-3225,-3234,-3243,-3252,-3260,-3268,-3276,-3284,-3292,-3299,-3306,-3313,-3320,-3327,-3333,-3339,-3345,-3351,
--3356,-3361,-3366,-3371,-3376,-3380,-3385,-3389,-3393,-3396,-3400,-3403,-3406,-3409,-3412,-3415,-3417,-3419,-3422,-3424,-3426,
--3428,-3430,-3432,-3433,-3435,-3437,-3439,-3440,-3442,-3444,-3446,-3449,-3451,-3453,-3456,-3458,-3461,-3464,-3467,-3470,-3474,
--3478,-3481,-3486,-3490,-3494,-3499,-3503,-3508,-3513,-3518,-3522,-3527,-3532,-3537,-3542,-3547,-3552,-3556,-3561,-3565,-3569,
--3573,-3576,-3580,-3583,-3586,-3588,-3590,-3592,-3594,-3596,-3597,-3598,-3598,-3599,-3599,-3599,-3599,-3599,-3599,-3599,-3599,
--3599,-3599,-3599,-3599,-3600,-3601,-3602,-3603,-3604,-3606,-3609,-3611,-3614,-3617,-3621,-3625,-3629,-3634,-3639,-3645,-3650,
--3656,-3662,-3668,-3674,-3681,-3687,-3694,-3700,-3706,-3712,-3718,-3724,-3729,-3734,-3739,-3743,-3747,-3751,-3754,-3756,-3758,
--3760,-3761,-3762,-3762,-3761,-3761,-3760,-3758,-3756,-3754,-3751,-3748,-3745,-3741,-3737,-3733,-3729,-3724,-3719,-3715,-3710,
--3704,-3699,-3694,-3688,-3682,-3676,-3670,-3664,-3657,-3650,-3643,-3636,-3628,-3620,-3611,-3602,-3593,-3583,-3573,-3563,-3552,
--3540,-3528,-3516,-3503,-3490,-3477,-3463,-3450,-3436,-3422,-3408,-3393,-3379,-3366,-3352,-3339,-3326,-3314,-3302,-3291,-3281,
--3271,-3263,-3255,-3249,-3243,-3239,-3235,-3233,-3232,-3232,-3233,-3235,-3239,-3243,-3248,-3255,-3262,-3270,-3279,-3288,-3298,
--3309,-3319,-3330,-3342,-3353,-3364,-3375,-3386,-3396,-3406,-3416,-3425,-3434,-3442,-3449,-3455,-3461,-3466,-3471,-3474,-3477,
--3480,-3481,-3483,-3483,-3484,-3484,-3483,-3483,-3482,-3481,-3481,-3480,-3480,-3480,-3480,-3481,-3483,-3485,-3488,-3491,-3495,
--3500,-3506,-3512,-3519,-3528,-3536,-3546,-3557,-3568,-3580,-3592,-3605,-3619,-3633,-3647,-3662,-3677,-3693,-3708,-3723,-3739,
--3754,-3769,-3784,-3799,-3814,-3828,-3841,-3854,-3867,-3879,-3891,-3903,-3913,-3924,-3933,-3942,-3951,-3959,-3967,-3974,-3981,
--3987,-3993,-3999,-4004,-4009,-4013,-4017,-4021,-4025,-4029,-4032,-4035,-4037,-4040,-4042,-4044,-4046,-4048,-4049,-4050,-4051,
--4052,-4052,-4052,-4052,-4052,-4051,-4050,-4048,-4046,-4044,-4042,-4039,-4035,-4032,-4028,-4024,-4019,-4014,-4009,-4003,-3997,
--3991,-3985,-3979,-3972,-3965,-3958,-3950,-3943,-3935,-3928,-3920,-3912,-3904,-3896,-3888,-3879,-3871,-3863,-3854,-3846,-3837,
--3828,-3819,-3810,-3801,-3792,-3783,-3773,-3763,-3753,-3743,-3733,-3722,-3712,-3701,-3690,-3679,-3668,-3657,-3646,-3635,-3624,
--3613,-3603,-3592,-3582,-3572,-3562,-3553,-3545,-3536,-3529,-3522,-3516,-3510,-3506,-3502,-3499,-3497,-3496,-3495,-3496,-3497,
--3500,-3503,-3507,-3512,-3518,-3524,-3531,-3539,-3547,-3555,-3563,-3572,-3581,-3590,-3598,-3606,-3614,-3621,-3628,-3634,-3639,
--3643,-3646,-3649,-3649,-3649,-3647,-3644,-3640,-3634,-3627,-3618,-3609,-3597,-3585,-3572,-3557,-3541,-3525,-3507,-3489,-3470,
--3451,-3432,-3413,-3393,-3374,-3355,-3337,-3319,-3302,-3286,-3270,-3256,-3243,-3232,-3222,-3213,-3206,-3200,-3196,-3193,-3192,
--3192,-3194,-3197,-3202,-3208,-3214,-3222,-3231,-3240,-3250,-3261,-3272,-3282,-3293,-3304,-3314,-3324,-3333,-3341,-3348,-3354,
--3359,-3363,-3365,-3366,-3365,-3362,-3358,-3353,-3345,-3336,-3326,-3314,-3300,-3285,-3269,-3252,-3233,-3214,-3193,-3172,-3151,
--3129,-3107,-3084,-3062,-3040,-3018,-2997,-2976,-2956,-2936,-2918,-2901,-2884,-2869,-2855,-2842,-2831,-2820,-2811,-2803,-2797,
--2791,-2787,-2783,-2781,-2779,-2778,-2778,-2778,-2779,-2780,-2781,-2783,-2784,-2786,-2787,-2788,-2789,-2789,-2788,-2788,-2786,
--2784,-2781,-2778,-2773,-2768,-2763,-2756,-2749,-2742,-2734,-2725,-2716,-2707,-2698,-2688,-2678,-2668,-2659,-2649,-2640,-2632,
--2624,-2616,-2610,-2604,-2598,-2594,-2591,-2589,-2588,-2588,-2589,-2591,-2594,-2598,-2604,-2611,-2618,-2627,-2637,-2647,-2658,
--2671,-2683,-2697,-2711,-2725,-2739,-2754,-2769,-2784,-2799,-2814,-2828,-2842,-2856,-2869,-2881,-2893,-2904,-2914,-2924,-2932,
--2940,-2946,-2952,-2956,-2960,-2962,-2963,-2963,-2962,-2960,-2956,-2952,-2946,-2940,-2932,-2923,-2914,-2903,-2891,-2879,-2865,
--2851,-2836,-2820,-2803,-2786,-2768,-2750,-2731,-2711,-2691,-2670,-2649,-2628,-2606,-2585,-2563,-2541,-2519,-2497,-2475,-2453,
--2431,-2410,-2389,-2369,-2349,-2330,-2311,-2293,-2276,-2260,-2245,-2230,-2217,-2205,-2193,-2184,-2175,-2167,-2161,-2156,-2152,
--2150,-2148,-2148,-2149,-2151,-2155,-2159,-2164,-2171,-2178,-2185,-2194,-2203,-2213,-2223,-2233,-2243,-2254,-2265,-2275,-2286,
--2296,-2306,-2316,-2325,-2334,-2342,-2350,-2357,-2364,-2370,-2375,-2380,-2385,-2388,-2392,-2395,-2397,-2399,-2401,-2403,-2405,
--2407,-2408,-2410,-2412,-2414,-2417,-2420,-2423,-2427,-2431,-2436,-2442,-2448,-2454,-2462,-2469,-2477,-2486,-2495,-2505,-2514,
--2524,-2534,-2544,-2554,-2563,-2573,-2581,-2589,-2597,-2603,-2608,-2613,-2616,-2618,-2618,-2617,-2614,-2609,-2603,-2595,-2585,
--2574,-2561,-2545,-2529,-2510,-2490,-2468,-2444,-2419,-2393,-2366,-2337,-2308,-2278,-2247,-2216,-2185,-2153,-2121,-2090,-2058,
--2027,-1997,-1968,-1939,-1912,-1885,-1860,-1836,-1813,-1792,-1772,-1753,-1737,-1721,-1707,-1695,-1685,-1675,-1668,-1661,-1656,
--1652,-1649,-1647,-1646,-1647,-1647,-1649,-1651,-1653,-1656,-1660,-1663,-1667,-1670,-1674,-1677,-1680,-1684,-1687,-1689,-1691,
--1693,-1695,-1696,-1697,-1697,-1697,-1697,-1696,-1695,-1694,-1693,-1691,-1689,-1688,-1686,-1684,-1681,-1679,-1677,-1675,-1673,
--1672,-1670,-1668,-1667,-1666,-1664,-1664,-1663,-1662,-1662,-1661,-1661,-1661,-1661,-1661,-1661,-1661,-1661,-1661,-1661,-1661,
--1661,-1661,-1660,-1660,-1659,-1658,-1657,-1656,-1655,-1653,-1652,-1650,-1648,-1646,-1644,-1642,-1640,-1637,-1635,-1632,-1630,
--1628,-1626,-1623,-1621,-1619,-1617,-1615,-1614,-1612,-1611,-1609,-1608,-1607,-1607,-1606,-1605,-1605,-1605,-1605,-1605,-1605,
--1605,-1605,-1605,-1605,-1605,-1605,-1605,-1605,-1605,-1605,-1605,-1605,-1604,-1604,-1603,-1602,-1601,-1600,-1599,-1598,-1597,
--1596,-1594,-1593,-1592,-1590,-1589,-1588,-1587,-1586,-1585,-1584,-1584,-1665,-1666,-1666,-1667,-1667,-1668,-1669,-1670,-1671,
--1672,-1673,-1674,-1675,-1676,-1677,-1678,-1679,-1680,-1680,-1681,-1681,-1682,-1682,-1682,-1681,-1680,-1680,-1679,-1677,-1675,
--1673,-1671,-1669,-1666,-1663,-1659,-1655,-1652,-1648,-1643,-1639,-1634,-1629,-1624,-1619,-1614,-1609,-1604,-1599,-1594,-1589,
--1584,-1580,-1575,-1571,-1567,-1563,-1559,-1556,-1553,-1551,-1548,-1546,-1544,-1543,-1541,-1540,-1540,-1539,-1539,-1539,-1539,
--1539,-1539,-1540,-1540,-1540,-1541,-1541,-1542,-1542,-1542,-1542,-1541,-1541,-1540,-1539,-1537,-1536,-1534,-1531,-1528,-1525,
--1522,-1518,-1514,-1510,-1505,-1500,-1495,-1489,-1483,-1477,-1471,-1464,-1458,-1451,-1444,-1437,-1430,-1423,-1416,-1409,-1402,
--1395,-1388,-1381,-1374,-1368,-1361,-1355,-1349,-1343,-1338,-1332,-1327,-1322,-1317,-1312,-1307,-1303,-1298,-1294,-1290,-1287,
--1283,-1279,-1276,-1273,-1270,-1267,-1264,-1261,-1258,-1256,-1253,-1251,-1248,-1246,-1244,-1242,-1240,-1238,-1237,-1235,-1233,
--1232,-1231,-1230,-1229,-1228,-1228,-1227,-1227,-1227,-1227,-1227,-1228,-1228,-1229,-1230,-1231,-1233,-1234,-1236,-1238,-1240,
--1242,-1244,-1247,-1249,-1252,-1255,-1257,-1260,-1263,-1267,-1270,-1273,-1276,-1279,-1282,-1285,-1289,-1292,-1295,-1298,-1301,
--1304,-1306,-1309,-1312,-1314,-1317,-1319,-1321,-1323,-1326,-1327,-1329,-1331,-1333,-1335,-1336,-1338,-1339,-1340,-1342,-1343,
--1344,-1345,-1346,-1347,-1348,-1350,-1351,-1352,-1353,-1354,-1355,-1356,-1357,-1358,-1359,-1361,-1362,-1363,-1365,-1366,-1368,
--1369,-1371,-1372,-1374,-1376,-1378,-1380,-1382,-1384,-1386,-1388,-1390,-1393,-1395,-1398,-1400,-1403,-1405,-1408,-1411,-1413,
--1416,-1419,-1422,-1425,-1428,-1431,-1435,-1438,-1441,-1444,-1448,-1451,-1455,-1459,-1462,-1466,-1470,-1474,-1478,-1482,-1486,
--1490,-1495,-1499,-1504,-1509,-1513,-1518,-1523,-1529,-1534,-1539,-1545,-1551,-1557,-1563,-1569,-1575,-1582,-1588,-1595,-1602,
--1609,-1616,-1623,-1631,-1638,-1646,-1654,-1662,-1670,-1678,-1686,-1694,-1703,-1711,-1720,-1728,-1737,-1745,-1754,-1763,-1772,
--1781,-1789,-1798,-1807,-1816,-1825,-1834,-1843,-1852,-1861,-1870,-1879,-1888,-1897,-1906,-1915,-1924,-1933,-1942,-1951,-1960,
--1969,-1978,-1987,-1996,-2004,-2013,-2022,-2030,-2039,-2047,-2056,-2064,-2072,-2081,-2089,-2097,-2105,-2113,-2120,-2128,-2136,
--2143,-2150,-2158,-2165,-2172,-2179,-2186,-2193,-2200,-2206,-2213,-2219,-2226,-2232,-2239,-2245,-2252,-2258,-2264,-2271,-2277,
--2284,-2290,-2297,-2303,-2310,-2317,-2323,-2330,-2337,-2344,-2352,-2359,-2366,-2374,-2382,-2390,-2397,-2406,-2414,-2422,-2430,
--2439,-2447,-2456,-2465,-2474,-2483,-2491,-2501,-2510,-2519,-2528,-2537,-2546,-2556,-2565,-2574,-2584,-2593,-2603,-2612,-2621,
--2631,-2640,-2650,-2659,-2668,-2678,-2687,-2697,-2706,-2716,-2725,-2735,-2745,-2754,-2764,-2774,-2783,-2793,-2803,-2813,-2823,
--2833,-2843,-2853,-2864,-2874,-2884,-2895,-2905,-2916,-2926,-2937,-2947,-2958,-2968,-2979,-2989,-3000,-3010,-3021,-3031,-3041,
--3052,-3062,-3072,-3082,-3092,-3101,-3111,-3121,-3130,-3139,-3148,-3157,-3166,-3174,-3183,-3191,-3199,-3207,-3215,-3222,-3229,
--3236,-3243,-3250,-3257,-3263,-3269,-3275,-3281,-3286,-3292,-3297,-3302,-3307,-3312,-3317,-3321,-3325,-3330,-3334,-3338,-3341,
--3345,-3348,-3352,-3355,-3358,-3361,-3364,-3367,-3370,-3373,-3376,-3378,-3381,-3384,-3386,-3389,-3392,-3394,-3397,-3400,-3402,
--3405,-3408,-3411,-3414,-3417,-3420,-3423,-3426,-3429,-3433,-3436,-3440,-3444,-3447,-3451,-3455,-3459,-3463,-3467,-3471,-3475,
--3479,-3483,-3486,-3490,-3494,-3498,-3502,-3505,-3509,-3512,-3515,-3518,-3521,-3524,-3526,-3529,-3531,-3533,-3535,-3537,-3538,
--3540,-3541,-3542,-3543,-3544,-3545,-3545,-3546,-3547,-3547,-3548,-3549,-3549,-3550,-3551,-3552,-3553,-3554,-3556,-3557,-3559,
--3561,-3564,-3566,-3569,-3572,-3575,-3579,-3583,-3587,-3591,-3595,-3600,-3605,-3610,-3615,-3620,-3625,-3631,-3636,-3641,-3647,
--3652,-3657,-3662,-3666,-3671,-3675,-3679,-3683,-3687,-3690,-3693,-3695,-3697,-3699,-3700,-3701,-3701,-3701,-3701,-3700,-3698,
--3697,-3695,-3692,-3689,-3686,-3682,-3678,-3673,-3668,-3663,-3658,-3652,-3646,-3640,-3633,-3626,-3619,-3611,-3604,-3596,-3588,
--3580,-3571,-3562,-3554,-3544,-3535,-3526,-3516,-3507,-3497,-3487,-3477,-3467,-3456,-3446,-3436,-3425,-3415,-3405,-3395,-3385,
--3375,-3365,-3356,-3347,-3338,-3329,-3321,-3313,-3306,-3299,-3292,-3286,-3281,-3276,-3272,-3268,-3265,-3263,-3261,-3260,-3260,
--3260,-3261,-3262,-3264,-3267,-3270,-3273,-3278,-3282,-3287,-3292,-3297,-3303,-3309,-3315,-3321,-3328,-3334,-3340,-3346,-3352,
--3358,-3363,-3368,-3373,-3378,-3383,-3387,-3390,-3394,-3397,-3400,-3403,-3405,-3407,-3408,-3410,-3411,-3412,-3413,-3414,-3415,
--3416,-3417,-3418,-3420,-3421,-3423,-3424,-3427,-3429,-3432,-3435,-3439,-3443,-3447,-3452,-3457,-3463,-3469,-3476,-3483,-3491,
--3499,-3507,-3515,-3524,-3534,-3543,-3553,-3563,-3573,-3583,-3594,-3604,-3615,-3625,-3636,-3646,-3656,-3667,-3677,-3686,-3696,
--3706,-3715,-3724,-3733,-3741,-3750,-3758,-3765,-3773,-3780,-3787,-3794,-3800,-3807,-3813,-3818,-3824,-3829,-3834,-3839,-3844,
--3848,-3852,-3856,-3860,-3864,-3867,-3870,-3873,-3875,-3878,-3880,-3882,-3883,-3884,-3885,-3886,-3886,-3886,-3886,-3885,-3884,
--3882,-3880,-3878,-3876,-3873,-3869,-3865,-3861,-3857,-3852,-3847,-3841,-3835,-3829,-3822,-3815,-3808,-3800,-3793,-3784,-3776,
--3767,-3758,-3749,-3739,-3729,-3719,-3709,-3698,-3688,-3677,-3666,-3655,-3643,-3632,-3620,-3608,-3596,-3584,-3572,-3560,-3548,
--3536,-3523,-3511,-3499,-3487,-3475,-3463,-3452,-3440,-3429,-3419,-3408,-3398,-3389,-3380,-3371,-3363,-3356,-3350,-3344,-3338,
--3334,-3330,-3328,-3326,-3325,-3325,-3325,-3327,-3329,-3333,-3337,-3342,-3348,-3354,-3362,-3370,-3378,-3387,-3397,-3406,-3416,
--3427,-3437,-3447,-3457,-3467,-3477,-3486,-3495,-3503,-3511,-3517,-3523,-3528,-3532,-3535,-3536,-3537,-3536,-3534,-3531,-3526,
--3521,-3514,-3505,-3496,-3485,-3474,-3461,-3448,-3433,-3418,-3403,-3386,-3370,-3353,-3336,-3319,-3302,-3286,-3269,-3254,-3239,
--3224,-3210,-3198,-3186,-3175,-3166,-3158,-3151,-3145,-3141,-3138,-3136,-3136,-3137,-3139,-3143,-3147,-3153,-3160,-3167,-3175,
--3184,-3194,-3203,-3213,-3223,-3233,-3243,-3253,-3262,-3271,-3279,-3286,-3292,-3298,-3302,-3305,-3307,-3307,-3306,-3304,-3300,
--3295,-3288,-3280,-3271,-3260,-3248,-3235,-3220,-3205,-3188,-3171,-3153,-3134,-3115,-3096,-3076,-3056,-3036,-3016,-2997,-2977,
--2959,-2940,-2923,-2906,-2890,-2874,-2860,-2847,-2835,-2823,-2813,-2804,-2796,-2790,-2784,-2779,-2775,-2773,-2771,-2770,-2769,
--2769,-2770,-2772,-2773,-2775,-2778,-2780,-2783,-2785,-2788,-2790,-2792,-2794,-2796,-2797,-2797,-2798,-2797,-2797,-2795,-2793,
--2791,-2788,-2785,-2781,-2777,-2773,-2768,-2763,-2758,-2752,-2747,-2742,-2736,-2731,-2725,-2721,-2716,-2712,-2708,-2704,-2701,
--2699,-2697,-2696,-2696,-2696,-2697,-2699,-2702,-2705,-2709,-2713,-2718,-2724,-2731,-2738,-2745,-2753,-2762,-2771,-2780,-2789,
--2798,-2808,-2818,-2827,-2837,-2846,-2855,-2864,-2872,-2880,-2888,-2894,-2901,-2906,-2911,-2915,-2919,-2921,-2923,-2924,-2923,
--2922,-2920,-2917,-2913,-2908,-2903,-2896,-2888,-2879,-2869,-2859,-2847,-2835,-2822,-2808,-2793,-2778,-2761,-2745,-2727,-2709,
--2691,-2672,-2653,-2633,-2613,-2593,-2573,-2553,-2533,-2512,-2492,-2472,-2452,-2433,-2414,-2395,-2377,-2360,-2343,-2327,-2311,
--2296,-2283,-2270,-2257,-2246,-2236,-2227,-2219,-2212,-2206,-2201,-2197,-2194,-2192,-2191,-2191,-2192,-2194,-2196,-2200,-2204,
--2209,-2215,-2221,-2228,-2235,-2243,-2251,-2259,-2267,-2275,-2284,-2292,-2301,-2309,-2317,-2325,-2333,-2340,-2347,-2354,-2360,
--2366,-2372,-2377,-2382,-2387,-2391,-2395,-2399,-2403,-2406,-2410,-2413,-2416,-2419,-2423,-2426,-2430,-2433,-2437,-2442,-2446,
--2451,-2456,-2462,-2468,-2474,-2481,-2488,-2496,-2504,-2512,-2520,-2528,-2537,-2546,-2554,-2563,-2571,-2579,-2587,-2595,-2602,
--2608,-2614,-2618,-2622,-2625,-2627,-2628,-2628,-2626,-2623,-2619,-2613,-2606,-2598,-2588,-2577,-2564,-2550,-2534,-2517,-2499,
--2480,-2459,-2437,-2415,-2391,-2367,-2342,-2316,-2290,-2264,-2237,-2210,-2184,-2157,-2130,-2104,-2079,-2053,-2029,-2005,-1982,
--1960,-1939,-1919,-1899,-1881,-1864,-1849,-1834,-1821,-1809,-1798,-1788,-1779,-1771,-1765,-1759,-1754,-1751,-1748,-1745,-1744,
--1743,-1743,-1743,-1743,-1744,-1745,-1747,-1748,-1750,-1752,-1754,-1756,-1757,-1759,-1760,-1761,-1762,-1763,-1764,-1764,-1764,
--1764,-1763,-1763,-1762,-1761,-1759,-1758,-1756,-1754,-1752,-1750,-1748,-1746,-1744,-1741,-1739,-1737,-1734,-1732,-1730,-1728,
--1726,-1724,-1723,-1721,-1719,-1718,-1717,-1715,-1714,-1713,-1712,-1712,-1711,-1710,-1710,-1709,-1708,-1708,-1707,-1707,-1707,
--1706,-1706,-1705,-1705,-1705,-1704,-1704,-1703,-1703,-1702,-1702,-1701,-1701,-1700,-1700,-1699,-1698,-1698,-1697,-1696,-1696,
--1695,-1694,-1694,-1693,-1692,-1692,-1691,-1690,-1689,-1689,-1688,-1687,-1687,-1686,-1685,-1685,-1684,-1683,-1682,-1681,-1680,
--1680,-1679,-1678,-1677,-1676,-1675,-1674,-1673,-1673,-1672,-1671,-1670,-1669,-1668,-1668,-1667,-1667,-1666,-1666,-1665,-1665,
--1665,-1665,-1665,-1665,-1815,-1815,-1816,-1816,-1817,-1817,-1818,-1818,-1818,-1819,-1819,-1819,-1819,-1819,-1819,-1818,-1818,
--1817,-1816,-1815,-1813,-1812,-1810,-1808,-1805,-1803,-1800,-1797,-1793,-1790,-1786,-1782,-1777,-1772,-1768,-1762,-1757,-1752,
--1746,-1740,-1734,-1729,-1722,-1716,-1710,-1704,-1698,-1692,-1686,-1680,-1675,-1669,-1664,-1659,-1654,-1649,-1645,-1641,-1637,
--1633,-1630,-1626,-1624,-1621,-1619,-1617,-1615,-1614,-1613,-1612,-1611,-1610,-1610,-1609,-1609,-1609,-1609,-1609,-1609,-1609,
--1609,-1609,-1609,-1609,-1609,-1608,-1607,-1607,-1605,-1604,-1603,-1601,-1599,-1596,-1594,-1591,-1588,-1584,-1581,-1577,-1572,
--1568,-1563,-1558,-1553,-1548,-1542,-1537,-1531,-1525,-1519,-1513,-1507,-1500,-1494,-1488,-1482,-1475,-1469,-1463,-1457,-1452,
--1446,-1440,-1435,-1430,-1424,-1420,-1415,-1410,-1406,-1402,-1398,-1394,-1391,-1387,-1384,-1381,-1379,-1376,-1374,-1372,-1370,
--1369,-1367,-1366,-1365,-1364,-1364,-1363,-1363,-1363,-1363,-1363,-1364,-1364,-1365,-1366,-1367,-1368,-1369,-1371,-1372,-1374,
--1376,-1378,-1380,-1382,-1384,-1386,-1389,-1391,-1393,-1396,-1398,-1401,-1404,-1406,-1409,-1411,-1414,-1417,-1419,-1422,-1424,
--1427,-1429,-1431,-1434,-1436,-1438,-1440,-1442,-1444,-1446,-1447,-1449,-1450,-1452,-1453,-1454,-1455,-1456,-1457,-1458,-1459,
--1459,-1460,-1460,-1461,-1461,-1461,-1462,-1462,-1462,-1463,-1463,-1463,-1464,-1464,-1464,-1465,-1465,-1466,-1467,-1467,-1468,
--1469,-1470,-1471,-1472,-1474,-1475,-1477,-1479,-1481,-1483,-1485,-1487,-1490,-1492,-1495,-1498,-1501,-1504,-1507,-1510,-1514,
--1518,-1521,-1525,-1529,-1533,-1537,-1541,-1545,-1549,-1554,-1558,-1562,-1567,-1571,-1576,-1580,-1585,-1589,-1594,-1598,-1603,
--1607,-1612,-1616,-1621,-1625,-1630,-1635,-1639,-1644,-1648,-1653,-1657,-1662,-1666,-1671,-1675,-1680,-1685,-1689,-1694,-1698,
--1703,-1708,-1713,-1718,-1723,-1728,-1733,-1738,-1743,-1748,-1754,-1759,-1765,-1770,-1776,-1782,-1787,-1793,-1799,-1805,-1811,
--1818,-1824,-1830,-1837,-1843,-1850,-1856,-1863,-1869,-1876,-1883,-1890,-1897,-1904,-1911,-1918,-1925,-1932,-1939,-1946,-1954,
--1961,-1968,-1976,-1983,-1990,-1998,-2005,-2012,-2020,-2027,-2035,-2042,-2050,-2057,-2064,-2072,-2079,-2087,-2094,-2101,-2109,
--2116,-2124,-2131,-2138,-2146,-2153,-2160,-2167,-2174,-2181,-2189,-2196,-2203,-2210,-2217,-2224,-2231,-2237,-2244,-2251,-2258,
--2265,-2271,-2278,-2285,-2292,-2298,-2305,-2312,-2319,-2326,-2332,-2339,-2346,-2353,-2360,-2367,-2374,-2381,-2388,-2396,-2403,
--2410,-2418,-2425,-2433,-2441,-2448,-2456,-2464,-2472,-2480,-2489,-2497,-2505,-2514,-2522,-2531,-2539,-2548,-2557,-2565,-2574,
--2583,-2592,-2601,-2610,-2619,-2628,-2637,-2646,-2655,-2664,-2673,-2682,-2691,-2700,-2709,-2718,-2727,-2736,-2745,-2754,-2763,
--2772,-2781,-2789,-2798,-2807,-2816,-2825,-2834,-2843,-2851,-2860,-2869,-2878,-2887,-2895,-2904,-2913,-2922,-2930,-2939,-2948,
--2956,-2965,-2974,-2982,-2991,-2999,-3007,-3016,-3024,-3032,-3041,-3049,-3057,-3065,-3073,-3080,-3088,-3096,-3103,-3110,-3118,
--3125,-3132,-3139,-3145,-3152,-3159,-3165,-3171,-3177,-3183,-3189,-3195,-3201,-3206,-3211,-3217,-3222,-3227,-3232,-3237,-3241,
--3246,-3250,-3255,-3259,-3263,-3267,-3272,-3276,-3279,-3283,-3287,-3291,-3294,-3298,-3302,-3305,-3309,-3312,-3316,-3319,-3322,
--3326,-3329,-3333,-3336,-3340,-3343,-3346,-3350,-3353,-3357,-3360,-3363,-3367,-3370,-3374,-3377,-3381,-3384,-3388,-3391,-3395,
--3398,-3402,-3405,-3409,-3412,-3416,-3419,-3422,-3426,-3429,-3432,-3435,-3438,-3442,-3444,-3447,-3450,-3453,-3455,-3458,-3460,
--3463,-3465,-3467,-3469,-3471,-3472,-3474,-3476,-3477,-3478,-3480,-3481,-3482,-3483,-3484,-3485,-3486,-3487,-3488,-3489,-3490,
--3490,-3492,-3493,-3494,-3495,-3496,-3497,-3499,-3501,-3502,-3504,-3506,-3508,-3511,-3513,-3515,-3518,-3521,-3524,-3527,-3531,
--3534,-3538,-3541,-3545,-3549,-3553,-3557,-3561,-3565,-3568,-3572,-3576,-3580,-3584,-3587,-3591,-3594,-3597,-3600,-3603,-3605,
--3608,-3610,-3611,-3613,-3614,-3615,-3616,-3616,-3616,-3616,-3615,-3614,-3613,-3612,-3610,-3608,-3605,-3602,-3599,-3596,-3593,
--3589,-3585,-3580,-3576,-3571,-3566,-3561,-3555,-3550,-3544,-3538,-3532,-3526,-3520,-3514,-3507,-3501,-3494,-3488,-3481,-3474,
--3467,-3461,-3454,-3447,-3440,-3433,-3426,-3420,-3413,-3407,-3400,-3394,-3387,-3381,-3375,-3369,-3364,-3358,-3353,-3348,-3343,
--3338,-3334,-3330,-3326,-3322,-3319,-3316,-3314,-3311,-3309,-3308,-3306,-3305,-3304,-3304,-3304,-3304,-3305,-3305,-3307,-3308,
--3309,-3311,-3313,-3316,-3318,-3321,-3323,-3326,-3329,-3332,-3336,-3339,-3342,-3346,-3349,-3352,-3356,-3359,-3363,-3366,-3369,
--3372,-3376,-3379,-3382,-3385,-3388,-3391,-3394,-3397,-3400,-3403,-3405,-3408,-3411,-3414,-3416,-3419,-3422,-3425,-3428,-3430,
--3433,-3436,-3439,-3442,-3445,-3449,-3452,-3455,-3458,-3462,-3465,-3468,-3472,-3475,-3479,-3483,-3486,-3490,-3494,-3497,-3501,
--3505,-3508,-3512,-3516,-3519,-3523,-3527,-3531,-3534,-3538,-3542,-3545,-3549,-3553,-3557,-3560,-3564,-3568,-3572,-3576,-3580,
--3584,-3588,-3592,-3597,-3601,-3605,-3610,-3614,-3619,-3623,-3628,-3633,-3637,-3642,-3647,-3652,-3656,-3661,-3666,-3670,-3675,
--3679,-3683,-3687,-3691,-3695,-3698,-3701,-3704,-3707,-3709,-3711,-3713,-3714,-3715,-3715,-3715,-3714,-3713,-3712,-3710,-3707,
--3704,-3700,-3696,-3692,-3687,-3681,-3675,-3668,-3661,-3653,-3645,-3636,-3627,-3617,-3607,-3597,-3586,-3574,-3563,-3551,-3539,
--3526,-3513,-3500,-3487,-3473,-3460,-3446,-3433,-3419,-3405,-3392,-3378,-3365,-3351,-3338,-3326,-3313,-3301,-3289,-3278,-3267,
--3257,-3247,-3238,-3229,-3221,-3214,-3207,-3202,-3197,-3192,-3189,-3186,-3185,-3184,-3184,-3185,-3186,-3189,-3192,-3196,-3201,
--3207,-3213,-3220,-3227,-3236,-3244,-3253,-3263,-3272,-3282,-3292,-3303,-3313,-3323,-3333,-3343,-3352,-3361,-3369,-3377,-3384,
--3391,-3396,-3401,-3405,-3408,-3411,-3412,-3412,-3411,-3408,-3405,-3401,-3396,-3389,-3382,-3374,-3364,-3354,-3343,-3332,-3319,
--3306,-3293,-3279,-3265,-3251,-3236,-3222,-3208,-3194,-3180,-3167,-3154,-3141,-3130,-3119,-3109,-3100,-3091,-3084,-3078,-3073,
--3069,-3066,-3065,-3064,-3065,-3067,-3069,-3073,-3078,-3083,-3090,-3097,-3105,-3113,-3122,-3131,-3141,-3150,-3160,-3170,-3179,
--3189,-3198,-3206,-3214,-3221,-3227,-3233,-3238,-3242,-3244,-3246,-3246,-3246,-3244,-3241,-3237,-3232,-3225,-3218,-3209,-3199,
--3188,-3177,-3164,-3151,-3137,-3122,-3107,-3092,-3076,-3060,-3043,-3027,-3011,-2995,-2979,-2963,-2948,-2933,-2918,-2905,-2892,
--2880,-2868,-2857,-2848,-2839,-2830,-2823,-2817,-2812,-2807,-2803,-2801,-2798,-2797,-2797,-2797,-2798,-2799,-2801,-2803,-2806,
--2809,-2813,-2816,-2820,-2824,-2828,-2832,-2836,-2840,-2844,-2848,-2851,-2854,-2857,-2860,-2862,-2865,-2866,-2868,-2869,-2870,
--2870,-2871,-2871,-2871,-2870,-2870,-2869,-2868,-2867,-2866,-2865,-2863,-2862,-2861,-2860,-2859,-2858,-2857,-2856,-2856,-2855,
--2855,-2855,-2855,-2856,-2856,-2857,-2858,-2859,-2861,-2862,-2864,-2865,-2867,-2869,-2871,-2872,-2874,-2876,-2878,-2879,-2880,
--2881,-2882,-2883,-2883,-2883,-2883,-2882,-2881,-2879,-2877,-2874,-2871,-2867,-2863,-2858,-2853,-2847,-2840,-2833,-2825,-2817,
--2808,-2798,-2788,-2778,-2766,-2754,-2742,-2729,-2716,-2702,-2688,-2674,-2659,-2644,-2629,-2613,-2597,-2582,-2566,-2550,-2534,
--2518,-2502,-2486,-2471,-2455,-2441,-2426,-2412,-2398,-2385,-2372,-2360,-2348,-2337,-2326,-2317,-2308,-2299,-2292,-2285,-2279,
--2273,-2269,-2265,-2262,-2259,-2258,-2257,-2257,-2257,-2258,-2260,-2263,-2265,-2269,-2273,-2277,-2282,-2287,-2292,-2298,-2303,
--2309,-2316,-2322,-2328,-2334,-2341,-2347,-2353,-2359,-2365,-2371,-2377,-2383,-2388,-2394,-2399,-2404,-2409,-2414,-2419,-2423,
--2428,-2432,-2437,-2442,-2446,-2451,-2455,-2460,-2465,-2470,-2475,-2481,-2486,-2492,-2498,-2504,-2511,-2518,-2524,-2531,-2539,
--2546,-2554,-2561,-2569,-2576,-2584,-2591,-2599,-2606,-2613,-2620,-2626,-2632,-2637,-2642,-2646,-2650,-2653,-2655,-2656,-2657,
--2656,-2655,-2652,-2649,-2645,-2639,-2633,-2625,-2617,-2607,-2597,-2585,-2573,-2559,-2545,-2529,-2513,-2497,-2479,-2461,-2443,
--2424,-2404,-2385,-2365,-2344,-2324,-2304,-2284,-2264,-2244,-2225,-2206,-2187,-2169,-2151,-2134,-2118,-2102,-2087,-2073,-2060,
--2047,-2035,-2024,-2014,-2004,-1995,-1987,-1980,-1973,-1968,-1962,-1958,-1954,-1950,-1947,-1945,-1942,-1941,-1939,-1938,-1937,
--1936,-1935,-1934,-1933,-1933,-1932,-1931,-1930,-1929,-1928,-1927,-1925,-1924,-1922,-1920,-1918,-1915,-1912,-1910,-1907,-1903,
--1900,-1896,-1893,-1889,-1885,-1881,-1877,-1873,-1869,-1864,-1860,-1856,-1852,-1848,-1844,-1840,-1837,-1833,-1830,-1827,-1824,
--1821,-1818,-1816,-1813,-1811,-1809,-1807,-1806,-1805,-1804,-1803,-1802,-1801,-1801,-1800,-1800,-1800,-1800,-1801,-1801,-1801,
--1802,-1802,-1803,-1804,-1805,-1805,-1806,-1807,-1808,-1809,-1810,-1810,-1811,-1812,-1813,-1813,-1814,-1815,-1815,-1816,-1816,
--1816,-1817,-1817,-1817,-1817,-1817,-1817,-1817,-1817,-1817,-1817,-1817,-1816,-1816,-1816,-1816,-1815,-1815,-1814,-1814,-1814,
--1814,-1813,-1813,-1813,-1813,-1813,-1813,-1813,-1813,-1813,-1813,-1813,-1814,-1814,-1814,-1814,-1815,-1967,-1967,-1968,-1968,
--1968,-1968,-1968,-1968,-1967,-1967,-1966,-1965,-1964,-1963,-1961,-1959,-1957,-1955,-1953,-1950,-1947,-1944,-1940,-1937,-1932,
--1928,-1924,-1919,-1914,-1908,-1903,-1897,-1891,-1885,-1878,-1872,-1865,-1858,-1851,-1844,-1837,-1830,-1823,-1816,-1809,-1802,
--1795,-1788,-1781,-1774,-1767,-1761,-1755,-1749,-1743,-1738,-1732,-1727,-1723,-1718,-1714,-1710,-1707,-1703,-1700,-1698,-1695,
--1693,-1691,-1690,-1688,-1687,-1686,-1686,-1685,-1685,-1684,-1684,-1684,-1684,-1684,-1684,-1684,-1684,-1684,-1684,-1684,-1684,
--1683,-1683,-1682,-1681,-1680,-1679,-1678,-1676,-1674,-1672,-1669,-1667,-1664,-1661,-1657,-1654,-1650,-1646,-1642,-1637,-1633,
--1628,-1623,-1618,-1613,-1607,-1602,-1597,-1591,-1586,-1580,-1575,-1569,-1564,-1558,-1553,-1548,-1542,-1537,-1533,-1528,-1523,
--1519,-1515,-1511,-1508,-1504,-1501,-1498,-1496,-1493,-1491,-1489,-1488,-1487,-1486,-1485,-1485,-1485,-1485,-1485,-1486,-1487,
--1488,-1490,-1491,-1493,-1495,-1497,-1500,-1503,-1505,-1508,-1511,-1515,-1518,-1521,-1525,-1528,-1532,-1536,-1539,-1543,-1546,
--1550,-1554,-1557,-1560,-1564,-1567,-1570,-1573,-1576,-1579,-1581,-1584,-1586,-1588,-1590,-1592,-1594,-1595,-1596,-1597,-1598,
--1599,-1599,-1600,-1600,-1600,-1600,-1600,-1599,-1599,-1598,-1597,-1596,-1595,-1594,-1593,-1592,-1591,-1590,-1589,-1587,-1586,
--1585,-1584,-1583,-1583,-1582,-1581,-1581,-1581,-1580,-1580,-1581,-1581,-1582,-1582,-1583,-1585,-1586,-1588,-1590,-1592,-1594,
--1597,-1600,-1603,-1606,-1610,-1614,-1618,-1622,-1627,-1631,-1636,-1641,-1647,-1652,-1658,-1663,-1669,-1675,-1681,-1687,-1694,
--1700,-1706,-1713,-1719,-1726,-1732,-1739,-1745,-1752,-1758,-1765,-1771,-1777,-1784,-1790,-1796,-1802,-1808,-1814,-1820,-1825,
--1831,-1836,-1842,-1847,-1852,-1857,-1863,-1868,-1872,-1877,-1882,-1887,-1891,-1896,-1900,-1905,-1909,-1913,-1918,-1922,-1926,
--1930,-1934,-1939,-1943,-1947,-1951,-1955,-1959,-1963,-1968,-1972,-1976,-1980,-1985,-1989,-1993,-1998,-2002,-2007,-2011,-2016,
--2020,-2025,-2030,-2034,-2039,-2044,-2049,-2054,-2059,-2064,-2069,-2074,-2079,-2084,-2090,-2095,-2100,-2106,-2111,-2116,-2122,
--2127,-2133,-2139,-2144,-2150,-2156,-2162,-2167,-2173,-2179,-2185,-2191,-2197,-2203,-2209,-2215,-2221,-2227,-2233,-2240,-2246,
--2252,-2258,-2265,-2271,-2277,-2284,-2290,-2296,-2303,-2309,-2316,-2323,-2329,-2336,-2343,-2349,-2356,-2363,-2370,-2377,-2384,
--2391,-2398,-2405,-2412,-2419,-2427,-2434,-2442,-2449,-2457,-2464,-2472,-2480,-2488,-2496,-2504,-2512,-2520,-2528,-2536,-2545,
--2553,-2561,-2570,-2578,-2587,-2595,-2604,-2613,-2622,-2630,-2639,-2648,-2657,-2665,-2674,-2683,-2692,-2701,-2710,-2718,-2727,
--2736,-2745,-2753,-2762,-2771,-2779,-2788,-2796,-2805,-2813,-2822,-2830,-2838,-2846,-2855,-2863,-2871,-2879,-2887,-2895,-2902,
--2910,-2918,-2925,-2933,-2941,-2948,-2955,-2963,-2970,-2977,-2984,-2991,-2998,-3005,-3012,-3018,-3025,-3032,-3038,-3044,-3051,
--3057,-3063,-3069,-3075,-3081,-3087,-3093,-3098,-3104,-3109,-3115,-3120,-3125,-3130,-3135,-3140,-3145,-3150,-3154,-3159,-3164,
--3168,-3172,-3177,-3181,-3185,-3189,-3193,-3197,-3201,-3205,-3208,-3212,-3216,-3220,-3223,-3227,-3230,-3234,-3237,-3241,-3244,
--3248,-3251,-3254,-3258,-3261,-3265,-3268,-3272,-3275,-3278,-3282,-3285,-3289,-3292,-3296,-3299,-3303,-3306,-3310,-3313,-3316,
--3320,-3323,-3327,-3330,-3334,-3337,-3341,-3344,-3347,-3351,-3354,-3357,-3361,-3364,-3367,-3370,-3373,-3376,-3379,-3382,-3385,
--3387,-3390,-3393,-3395,-3397,-3400,-3402,-3404,-3406,-3409,-3410,-3412,-3414,-3416,-3418,-3419,-3421,-3422,-3423,-3425,-3426,
--3427,-3429,-3430,-3431,-3432,-3433,-3434,-3435,-3436,-3437,-3438,-3440,-3441,-3442,-3443,-3445,-3446,-3447,-3449,-3450,-3452,
--3454,-3455,-3457,-3459,-3461,-3463,-3465,-3467,-3469,-3472,-3474,-3476,-3479,-3481,-3484,-3486,-3489,-3491,-3494,-3496,-3499,
--3501,-3504,-3506,-3508,-3510,-3513,-3515,-3516,-3518,-3520,-3521,-3523,-3524,-3525,-3526,-3527,-3527,-3528,-3528,-3528,-3528,
--3528,-3527,-3527,-3526,-3525,-3524,-3523,-3521,-3520,-3518,-3516,-3514,-3512,-3510,-3508,-3505,-3502,-3500,-3497,-3494,-3491,
--3488,-3485,-3481,-3478,-3474,-3471,-3467,-3464,-3460,-3456,-3452,-3448,-3444,-3440,-3436,-3432,-3428,-3424,-3419,-3415,-3411,
--3406,-3402,-3397,-3393,-3389,-3384,-3380,-3375,-3371,-3366,-3362,-3358,-3353,-3349,-3345,-3341,-3337,-3333,-3329,-3325,-3322,
--3318,-3315,-3312,-3309,-3306,-3304,-3301,-3299,-3297,-3295,-3294,-3292,-3291,-3290,-3290,-3290,-3289,-3290,-3290,-3291,-3292,
--3293,-3294,-3296,-3297,-3300,-3302,-3304,-3307,-3310,-3313,-3316,-3320,-3323,-3327,-3331,-3335,-3339,-3343,-3347,-3351,-3355,
--3360,-3364,-3368,-3372,-3377,-3381,-3385,-3389,-3393,-3397,-3400,-3404,-3407,-3410,-3414,-3416,-3419,-3422,-3424,-3426,-3428,
--3430,-3432,-3433,-3434,-3435,-3436,-3436,-3437,-3437,-3437,-3437,-3437,-3436,-3436,-3435,-3435,-3434,-3433,-3433,-3432,-3431,
--3430,-3430,-3429,-3429,-3429,-3428,-3428,-3429,-3429,-3430,-3430,-3431,-3433,-3434,-3436,-3438,-3441,-3443,-3446,-3450,-3453,
--3457,-3461,-3465,-3470,-3475,-3480,-3485,-3490,-3496,-3501,-3507,-3513,-3518,-3524,-3530,-3536,-3541,-3546,-3552,-3557,-3561,
--3566,-3570,-3574,-3578,-3581,-3583,-3585,-3587,-3588,-3589,-3589,-3588,-3587,-3585,-3583,-3580,-3576,-3572,-3567,-3561,-3555,
--3548,-3541,-3533,-3524,-3515,-3505,-3494,-3484,-3472,-3460,-3448,-3436,-3422,-3409,-3396,-3382,-3368,-3354,-3340,-3326,-3312,
--3298,-3284,-3270,-3256,-3243,-3230,-3217,-3204,-3193,-3181,-3170,-3160,-3150,-3141,-3132,-3124,-3117,-3111,-3105,-3100,-3096,
--3093,-3090,-3089,-3088,-3088,-3088,-3090,-3092,-3095,-3099,-3103,-3108,-3113,-3119,-3126,-3133,-3140,-3148,-3156,-3164,-3173,
--3181,-3190,-3198,-3206,-3215,-3222,-3230,-3237,-3244,-3251,-3257,-3262,-3266,-3270,-3273,-3276,-3277,-3278,-3278,-3277,-3276,
--3273,-3269,-3265,-3260,-3254,-3247,-3240,-3232,-3223,-3214,-3204,-3193,-3182,-3171,-3160,-3148,-3136,-3124,-3113,-3101,-3089,
--3078,-3067,-3057,-3047,-3037,-3028,-3020,-3013,-3006,-3000,-2995,-2991,-2988,-2985,-2984,-2983,-2984,-2985,-2987,-2991,-2994,
--2999,-3005,-3011,-3018,-3025,-3033,-3041,-3050,-3059,-3068,-3077,-3087,-3096,-3105,-3114,-3123,-3131,-3139,-3146,-3153,-3159,
--3164,-3169,-3173,-3176,-3178,-3179,-3180,-3179,-3177,-3175,-3172,-3167,-3162,-3156,-3149,-3141,-3132,-3123,-3113,-3103,-3092,
--3080,-3068,-3056,-3044,-3031,-3018,-3005,-2992,-2979,-2967,-2955,-2942,-2931,-2920,-2909,-2898,-2889,-2880,-2871,-2863,-2856,
--2850,-2844,-2839,-2835,-2832,-2829,-2827,-2826,-2826,-2826,-2827,-2828,-2831,-2833,-2837,-2840,-2845,-2849,-2854,-2859,-2865,
--2871,-2877,-2883,-2889,-2896,-2902,-2908,-2915,-2921,-2927,-2933,-2938,-2944,-2949,-2954,-2959,-2964,-2968,-2972,-2975,-2979,
--2982,-2984,-2986,-2988,-2990,-2991,-2992,-2993,-2993,-2993,-2993,-2993,-2992,-2991,-2990,-2988,-2986,-2984,-2982,-2980,-2977,
--2974,-2971,-2968,-2964,-2961,-2957,-2953,-2948,-2944,-2939,-2935,-2930,-2925,-2919,-2914,-2908,-2902,-2896,-2889,-2883,-2876,
--2869,-2861,-2854,-2846,-2838,-2830,-2821,-2812,-2803,-2794,-2784,-2775,-2764,-2754,-2744,-2733,-2722,-2711,-2699,-2688,-2676,
--2664,-2652,-2640,-2628,-2615,-2603,-2590,-2578,-2565,-2553,-2541,-2528,-2516,-2504,-2492,-2480,-2468,-2457,-2446,-2435,-2424,
--2414,-2404,-2394,-2385,-2376,-2368,-2360,-2353,-2346,-2339,-2333,-2328,-2323,-2318,-2314,-2311,-2308,-2305,-2303,-2302,-2301,
--2301,-2301,-2301,-2302,-2303,-2305,-2307,-2310,-2312,-2315,-2319,-2323,-2327,-2331,-2335,-2340,-2345,-2350,-2355,-2360,-2365,
--2371,-2376,-2382,-2388,-2394,-2399,-2405,-2411,-2417,-2423,-2430,-2436,-2442,-2449,-2455,-2461,-2468,-2475,-2481,-2488,-2495,
--2502,-2509,-2516,-2524,-2531,-2539,-2546,-2554,-2561,-2569,-2577,-2584,-2592,-2600,-2608,-2615,-2623,-2630,-2637,-2644,-2651,
--2657,-2663,-2669,-2674,-2679,-2684,-2688,-2691,-2694,-2697,-2698,-2699,-2700,-2700,-2699,-2697,-2694,-2691,-2687,-2683,-2677,
--2671,-2664,-2656,-2648,-2638,-2629,-2618,-2607,-2595,-2583,-2570,-2557,-2543,-2529,-2515,-2501,-2486,-2471,-2456,-2441,-2425,
--2410,-2395,-2380,-2366,-2351,-2337,-2323,-2309,-2296,-2283,-2270,-2258,-2247,-2236,-2225,-2215,-2205,-2196,-2187,-2179,-2172,
--2165,-2158,-2151,-2146,-2140,-2135,-2130,-2126,-2122,-2118,-2114,-2110,-2107,-2104,-2101,-2098,-2095,-2092,-2089,-2086,-2083,
--2080,-2077,-2073,-2070,-2066,-2063,-2059,-2055,-2051,-2046,-2042,-2037,-2033,-2028,-2023,-2018,-2012,-2007,-2002,-1996,-1991,
--1985,-1979,-1974,-1968,-1963,-1957,-1952,-1947,-1942,-1937,-1932,-1928,-1923,-1919,-1915,-1911,-1908,-1904,-1901,-1898,-1896,
--1894,-1892,-1890,-1888,-1887,-1886,-1885,-1885,-1884,-1884,-1884,-1885,-1885,-1886,-1887,-1888,-1889,-1891,-1892,-1894,-1895,
--1897,-1899,-1901,-1903,-1905,-1907,-1909,-1911,-1913,-1915,-1917,-1919,-1921,-1923,-1925,-1927,-1928,-1930,-1932,-1934,-1935,
--1937,-1938,-1940,-1941,-1943,-1944,-1945,-1947,-1948,-1949,-1950,-1951,-1952,-1953,-1954,-1955,-1956,-1957,-1958,-1959,-1960,
--1961,-1962,-1963,-1964,-1964,-1965,-1966,-1966,-1967,-2057,-2058,-2058,-2058,-2058,-2057,-2057,-2056,-2055,-2054,-2052,-2051,
--2049,-2047,-2044,-2042,-2039,-2036,-2032,-2029,-2025,-2021,-2016,-2012,-2007,-2002,-1996,-1991,-1985,-1979,-1973,-1967,-1960,
--1954,-1947,-1940,-1933,-1926,-1919,-1912,-1904,-1897,-1890,-1883,-1876,-1869,-1862,-1855,-1848,-1842,-1835,-1829,-1823,-1817,
--1811,-1806,-1801,-1796,-1791,-1787,-1783,-1779,-1775,-1772,-1769,-1767,-1764,-1762,-1760,-1758,-1757,-1756,-1755,-1754,-1753,
--1753,-1753,-1752,-1752,-1752,-1753,-1753,-1753,-1753,-1753,-1754,-1754,-1754,-1754,-1754,-1754,-1753,-1753,-1752,-1752,-1751,
--1750,-1748,-1747,-1745,-1743,-1741,-1738,-1736,-1733,-1730,-1727,-1723,-1720,-1716,-1712,-1707,-1703,-1699,-1694,-1689,-1685,
--1680,-1675,-1670,-1665,-1660,-1655,-1650,-1645,-1640,-1636,-1631,-1627,-1622,-1618,-1614,-1610,-1607,-1604,-1600,-1598,-1595,
--1593,-1591,-1589,-1588,-1587,-1586,-1585,-1585,-1585,-1585,-1586,-1587,-1588,-1590,-1591,-1593,-1596,-1598,-1601,-1604,-1607,
--1610,-1614,-1618,-1621,-1625,-1629,-1633,-1637,-1642,-1646,-1650,-1654,-1658,-1662,-1666,-1670,-1674,-1678,-1682,-1685,-1688,
--1692,-1695,-1697,-1700,-1703,-1705,-1707,-1709,-1710,-1711,-1713,-1714,-1714,-1715,-1715,-1715,-1715,-1715,-1714,-1714,-1713,
--1712,-1711,-1710,-1709,-1707,-1706,-1704,-1703,-1701,-1700,-1698,-1697,-1696,-1694,-1693,-1692,-1691,-1690,-1689,-1689,-1688,
--1688,-1688,-1689,-1689,-1690,-1691,-1692,-1694,-1695,-1698,-1700,-1703,-1705,-1709,-1712,-1716,-1720,-1724,-1729,-1733,-1738,
--1744,-1749,-1755,-1761,-1767,-1773,-1780,-1786,-1793,-1800,-1807,-1814,-1821,-1829,-1836,-1843,-1851,-1858,-1866,-1873,-1880,
--1888,-1895,-1902,-1909,-1917,-1923,-1930,-1937,-1944,-1951,-1957,-1963,-1969,-1976,-1981,-1987,-1993,-1998,-2004,-2009,-2014,
--2019,-2024,-2028,-2033,-2037,-2042,-2046,-2050,-2054,-2058,-2061,-2065,-2069,-2072,-2076,-2079,-2083,-2086,-2089,-2093,-2096,
--2099,-2102,-2105,-2109,-2112,-2115,-2118,-2121,-2125,-2128,-2131,-2135,-2138,-2141,-2145,-2148,-2152,-2155,-2159,-2163,-2166,
--2170,-2174,-2178,-2182,-2186,-2190,-2194,-2198,-2202,-2206,-2210,-2215,-2219,-2223,-2228,-2232,-2237,-2241,-2246,-2251,-2255,
--2260,-2265,-2270,-2275,-2280,-2285,-2290,-2295,-2300,-2305,-2310,-2315,-2321,-2326,-2331,-2337,-2342,-2348,-2353,-2359,-2365,
--2371,-2376,-2382,-2388,-2394,-2400,-2406,-2413,-2419,-2425,-2432,-2438,-2445,-2451,-2458,-2465,-2472,-2479,-2486,-2493,-2500,
--2507,-2515,-2522,-2530,-2537,-2545,-2552,-2560,-2568,-2576,-2584,-2592,-2600,-2608,-2616,-2624,-2633,-2641,-2649,-2658,-2666,
--2674,-2683,-2691,-2700,-2708,-2717,-2725,-2733,-2742,-2750,-2759,-2767,-2775,-2783,-2792,-2800,-2808,-2816,-2824,-2832,-2840,
--2848,-2855,-2863,-2871,-2878,-2886,-2893,-2900,-2908,-2915,-2922,-2929,-2936,-2943,-2949,-2956,-2962,-2969,-2975,-2981,-2988,
--2994,-3000,-3006,-3011,-3017,-3023,-3028,-3034,-3039,-3044,-3050,-3055,-3060,-3065,-3070,-3074,-3079,-3084,-3088,-3093,-3097,
--3102,-3106,-3110,-3114,-3118,-3122,-3126,-3130,-3134,-3137,-3141,-3145,-3148,-3152,-3155,-3159,-3162,-3166,-3169,-3172,-3175,
--3179,-3182,-3185,-3188,-3191,-3194,-3197,-3200,-3203,-3207,-3210,-3213,-3215,-3219,-3222,-3225,-3228,-3231,-3234,-3237,-3240,
--3243,-3246,-3249,-3252,-3255,-3258,-3261,-3264,-3267,-3270,-3273,-3276,-3279,-3282,-3285,-3288,-3290,-3293,-3296,-3299,-3302,
--3305,-3308,-3310,-3313,-3316,-3318,-3321,-3324,-3326,-3329,-3331,-3333,-3336,-3338,-3340,-3342,-3345,-3347,-3349,-3351,-3353,
--3354,-3356,-3358,-3360,-3361,-3363,-3365,-3366,-3368,-3369,-3371,-3372,-3374,-3375,-3377,-3378,-3379,-3381,-3382,-3383,-3384,
--3386,-3387,-3388,-3389,-3391,-3392,-3393,-3395,-3396,-3397,-3398,-3400,-3401,-3402,-3403,-3405,-3406,-3407,-3409,-3410,-3411,
--3412,-3414,-3415,-3416,-3417,-3418,-3419,-3420,-3421,-3422,-3423,-3424,-3425,-3426,-3426,-3427,-3428,-3428,-3429,-3429,-3429,
--3430,-3430,-3430,-3430,-3430,-3430,-3430,-3430,-3429,-3429,-3429,-3428,-3428,-3427,-3426,-3426,-3425,-3424,-3423,-3422,-3422,
--3421,-3420,-3419,-3418,-3416,-3415,-3414,-3413,-3411,-3410,-3409,-3407,-3406,-3404,-3403,-3401,-3400,-3398,-3396,-3394,-3392,
--3390,-3388,-3386,-3384,-3382,-3379,-3377,-3374,-3371,-3368,-3365,-3362,-3359,-3356,-3352,-3349,-3345,-3341,-3338,-3334,-3330,
--3326,-3321,-3317,-3313,-3308,-3304,-3300,-3295,-3291,-3286,-3282,-3277,-3273,-3269,-3264,-3260,-3256,-3252,-3248,-3245,-3241,
--3238,-3235,-3232,-3229,-3227,-3225,-3223,-3221,-3220,-3219,-3218,-3217,-3217,-3217,-3217,-3218,-3219,-3220,-3222,-3223,-3226,
--3228,-3230,-3233,-3236,-3240,-3243,-3247,-3251,-3255,-3259,-3263,-3268,-3272,-3277,-3281,-3286,-3290,-3295,-3299,-3304,-3308,
--3312,-3317,-3320,-3324,-3328,-3331,-3334,-3337,-3340,-3343,-3345,-3347,-3349,-3350,-3351,-3352,-3353,-3354,-3354,-3354,-3353,
--3353,-3352,-3352,-3351,-3349,-3348,-3347,-3345,-3344,-3342,-3340,-3339,-3337,-3336,-3334,-3333,-3332,-3330,-3329,-3329,-3328,
--3328,-3328,-3328,-3328,-3329,-3330,-3332,-3333,-3335,-3338,-3340,-3343,-3346,-3350,-3354,-3358,-3362,-3367,-3372,-3377,-3382,
--3387,-3393,-3398,-3404,-3410,-3416,-3422,-3427,-3433,-3438,-3444,-3449,-3454,-3459,-3463,-3467,-3471,-3474,-3477,-3479,-3481,
--3483,-3483,-3484,-3484,-3483,-3481,-3479,-3477,-3473,-3470,-3465,-3460,-3454,-3448,-3441,-3433,-3425,-3416,-3407,-3397,-3387,
--3377,-3365,-3354,-3342,-3330,-3318,-3305,-3293,-3280,-3267,-3254,-3241,-3228,-3215,-3202,-3189,-3177,-3165,-3153,-3142,-3130,
--3120,-3110,-3100,-3091,-3082,-3074,-3067,-3060,-3054,-3048,-3043,-3039,-3036,-3033,-3031,-3029,-3028,-3028,-3029,-3030,-3031,
--3034,-3036,-3039,-3043,-3047,-3052,-3057,-3062,-3067,-3073,-3078,-3084,-3090,-3096,-3102,-3107,-3113,-3118,-3124,-3128,-3133,
--3137,-3141,-3144,-3147,-3149,-3151,-3152,-3153,-3153,-3152,-3151,-3149,-3147,-3144,-3140,-3136,-3131,-3126,-3120,-3113,-3106,
--3099,-3092,-3084,-3075,-3067,-3058,-3050,-3041,-3032,-3023,-3014,-3006,-2997,-2989,-2981,-2974,-2966,-2960,-2954,-2948,-2943,
--2938,-2934,-2931,-2928,-2926,-2925,-2925,-2925,-2925,-2927,-2929,-2932,-2935,-2939,-2944,-2949,-2955,-2961,-2967,-2974,-2981,
--2988,-2995,-3003,-3011,-3018,-3026,-3034,-3041,-3048,-3055,-3061,-3068,-3073,-3078,-3083,-3087,-3091,-3094,-3096,-3098,-3099,
--3099,-3099,-3098,-3096,-3093,-3090,-3086,-3081,-3076,-3070,-3064,-3057,-3050,-3042,-3033,-3025,-3016,-3006,-2997,-2987,-2977,
--2968,-2958,-2948,-2938,-2929,-2920,-2910,-2902,-2893,-2885,-2878,-2871,-2864,-2858,-2852,-2847,-2843,-2839,-2836,-2833,-2831,
--2830,-2830,-2830,-2830,-2831,-2833,-2836,-2839,-2842,-2846,-2851,-2856,-2861,-2867,-2873,-2879,-2886,-2893,-2900,-2907,-2914,
--2922,-2929,-2936,-2944,-2951,-2958,-2966,-2972,-2979,-2986,-2992,-2998,-3003,-3009,-3014,-3018,-3022,-3026,-3029,-3032,-3035,
--3037,-3038,-3039,-3040,-3040,-3040,-3039,-3038,-3036,-3034,-3031,-3028,-3025,-3021,-3017,-3012,-3007,-3002,-2996,-2990,-2983,
--2977,-2970,-2962,-2955,-2947,-2939,-2930,-2922,-2913,-2904,-2894,-2885,-2875,-2866,-2856,-2846,-2836,-2825,-2815,-2804,-2794,
--2783,-2772,-2761,-2751,-2740,-2729,-2718,-2707,-2696,-2684,-2673,-2662,-2651,-2640,-2629,-2618,-2607,-2596,-2585,-2575,-2564,
--2553,-2543,-2532,-2522,-2512,-2502,-2492,-2482,-2473,-2464,-2455,-2446,-2437,-2429,-2421,-2413,-2405,-2398,-2391,-2384,-2377,
--2371,-2365,-2360,-2355,-2350,-2346,-2342,-2338,-2334,-2331,-2329,-2327,-2325,-2323,-2322,-2321,-2321,-2321,-2321,-2322,-2322,
--2324,-2325,-2327,-2330,-2332,-2335,-2339,-2342,-2346,-2350,-2355,-2359,-2364,-2369,-2375,-2380,-2386,-2392,-2399,-2405,-2412,
--2419,-2426,-2433,-2441,-2448,-2456,-2464,-2472,-2480,-2488,-2497,-2505,-2514,-2522,-2531,-2539,-2548,-2557,-2565,-2574,-2582,
--2591,-2599,-2608,-2616,-2624,-2631,-2639,-2646,-2653,-2660,-2667,-2673,-2679,-2684,-2689,-2694,-2698,-2701,-2705,-2707,-2709,
--2711,-2712,-2713,-2713,-2712,-2711,-2709,-2706,-2703,-2699,-2695,-2690,-2684,-2678,-2671,-2664,-2656,-2648,-2639,-2630,-2620,
--2610,-2599,-2588,-2577,-2565,-2553,-2541,-2529,-2517,-2504,-2491,-2479,-2466,-2453,-2440,-2428,-2415,-2403,-2390,-2378,-2367,
--2355,-2344,-2333,-2322,-2312,-2301,-2292,-2282,-2273,-2264,-2256,-2248,-2240,-2233,-2226,-2219,-2213,-2207,-2201,-2196,-2190,
--2185,-2181,-2176,-2171,-2167,-2163,-2159,-2155,-2151,-2147,-2144,-2140,-2136,-2132,-2129,-2125,-2121,-2117,-2113,-2109,-2105,
--2101,-2096,-2092,-2087,-2083,-2078,-2073,-2068,-2063,-2058,-2053,-2048,-2043,-2038,-2033,-2028,-2023,-2018,-2013,-2008,-2003,
--1998,-1993,-1989,-1984,-1980,-1976,-1972,-1968,-1964,-1961,-1958,-1955,-1952,-1949,-1947,-1945,-1943,-1942,-1940,-1939,-1938,
--1938,-1937,-1937,-1937,-1937,-1938,-1939,-1939,-1940,-1942,-1943,-1945,-1946,-1948,-1950,-1952,-1955,-1957,-1959,-1962,-1964,
--1967,-1970,-1972,-1975,-1978,-1981,-1984,-1986,-1989,-1992,-1995,-1998,-2000,-2003,-2006,-2009,-2011,-2014,-2017,-2019,-2022,
--2024,-2026,-2029,-2031,-2033,-2035,-2037,-2039,-2041,-2043,-2045,-2047,-2048,-2050,-2051,-2052,-2053,-2054,-2055,-2056,-2057,
--2057,-2112,-2112,-2112,-2111,-2111,-2110,-2109,-2107,-2106,-2104,-2102,-2100,-2098,-2096,-2093,-2090,-2087,-2084,-2080,-2077,
--2073,-2069,-2065,-2060,-2056,-2051,-2046,-2041,-2036,-2031,-2025,-2020,-2014,-2009,-2003,-1997,-1991,-1985,-1979,-1973,-1967,
--1961,-1955,-1950,-1944,-1938,-1932,-1927,-1922,-1916,-1911,-1906,-1901,-1897,-1892,-1888,-1884,-1880,-1876,-1873,-1870,-1867,
--1864,-1861,-1859,-1857,-1855,-1853,-1851,-1850,-1848,-1847,-1846,-1846,-1845,-1844,-1844,-1844,-1843,-1843,-1843,-1843,-1843,
--1843,-1843,-1843,-1843,-1842,-1842,-1842,-1841,-1841,-1840,-1839,-1839,-1838,-1836,-1835,-1833,-1832,-1830,-1828,-1825,-1823,
--1820,-1818,-1814,-1811,-1808,-1805,-1801,-1797,-1793,-1789,-1785,-1781,-1776,-1772,-1768,-1763,-1759,-1754,-1749,-1745,-1740,
--1736,-1732,-1727,-1723,-1719,-1715,-1711,-1708,-1704,-1701,-1698,-1695,-1692,-1690,-1688,-1686,-1684,-1683,-1682,-1681,-1680,
--1680,-1680,-1680,-1681,-1682,-1683,-1684,-1686,-1688,-1689,-1692,-1694,-1697,-1700,-1703,-1706,-1709,-1713,-1716,-1720,-1723,
--1727,-1731,-1735,-1739,-1743,-1747,-1751,-1755,-1758,-1762,-1766,-1769,-1773,-1776,-1779,-1782,-1785,-1788,-1790,-1793,-1795,
--1797,-1799,-1801,-1803,-1804,-1805,-1806,-1807,-1808,-1809,-1809,-1809,-1810,-1810,-1810,-1810,-1809,-1809,-1809,-1808,-1808,
--1808,-1807,-1807,-1806,-1806,-1806,-1805,-1805,-1805,-1805,-1806,-1806,-1806,-1807,-1808,-1809,-1810,-1811,-1813,-1814,-1816,
--1818,-1821,-1823,-1826,-1829,-1832,-1836,-1839,-1843,-1847,-1852,-1856,-1861,-1866,-1871,-1876,-1881,-1887,-1892,-1898,-1904,
--1910,-1916,-1922,-1928,-1935,-1941,-1947,-1954,-1960,-1966,-1973,-1979,-1986,-1992,-1998,-2004,-2010,-2016,-2022,-2028,-2034,
--2040,-2045,-2051,-2056,-2061,-2067,-2072,-2077,-2081,-2086,-2090,-2095,-2099,-2103,-2107,-2111,-2115,-2119,-2123,-2126,-2130,
--2133,-2136,-2140,-2143,-2146,-2149,-2152,-2155,-2158,-2161,-2164,-2167,-2170,-2173,-2176,-2179,-2182,-2185,-2188,-2191,-2194,
--2197,-2200,-2203,-2206,-2210,-2213,-2216,-2220,-2223,-2227,-2230,-2234,-2237,-2241,-2245,-2249,-2252,-2256,-2260,-2264,-2268,
--2272,-2277,-2281,-2285,-2289,-2294,-2298,-2302,-2307,-2311,-2315,-2320,-2324,-2329,-2334,-2338,-2343,-2347,-2352,-2357,-2361,
--2366,-2371,-2376,-2380,-2385,-2390,-2395,-2400,-2405,-2410,-2415,-2420,-2425,-2430,-2435,-2440,-2446,-2451,-2456,-2462,-2467,
--2473,-2478,-2484,-2490,-2495,-2501,-2507,-2513,-2519,-2525,-2531,-2537,-2544,-2550,-2557,-2563,-2570,-2576,-2583,-2590,-2596,
--2603,-2610,-2617,-2624,-2631,-2639,-2646,-2653,-2660,-2668,-2675,-2682,-2690,-2697,-2705,-2712,-2720,-2727,-2734,-2742,-2749,
--2757,-2764,-2772,-2779,-2786,-2794,-2801,-2808,-2816,-2823,-2830,-2837,-2844,-2851,-2858,-2865,-2871,-2878,-2885,-2891,-2898,
--2904,-2910,-2917,-2923,-2929,-2935,-2941,-2946,-2952,-2958,-2963,-2969,-2974,-2980,-2985,-2990,-2995,-3000,-3005,-3010,-3015,
--3019,-3024,-3028,-3033,-3037,-3041,-3046,-3050,-3054,-3058,-3062,-3066,-3070,-3074,-3077,-3081,-3085,-3088,-3092,-3095,-3099,
--3102,-3105,-3109,-3112,-3115,-3118,-3122,-3125,-3128,-3131,-3134,-3137,-3140,-3143,-3146,-3148,-3151,-3154,-3157,-3160,-3162,
--3165,-3168,-3171,-3173,-3176,-3179,-3181,-3184,-3187,-3189,-3192,-3195,-3197,-3200,-3202,-3205,-3208,-3210,-3213,-3215,-3218,
--3220,-3223,-3225,-3228,-3230,-3233,-3235,-3238,-3240,-3242,-3245,-3247,-3250,-3252,-3254,-3257,-3259,-3261,-3264,-3266,-3268,
--3270,-3272,-3275,-3277,-3279,-3281,-3283,-3285,-3287,-3289,-3291,-3293,-3295,-3297,-3299,-3301,-3303,-3305,-3307,-3308,-3310,
--3312,-3314,-3315,-3317,-3318,-3320,-3322,-3323,-3325,-3326,-3328,-3329,-3330,-3332,-3333,-3334,-3336,-3337,-3338,-3339,-3340,
--3341,-3342,-3343,-3344,-3345,-3345,-3346,-3347,-3347,-3348,-3348,-3349,-3349,-3349,-3350,-3350,-3350,-3350,-3350,-3350,-3350,
--3350,-3350,-3349,-3349,-3349,-3348,-3348,-3347,-3347,-3346,-3346,-3345,-3344,-3344,-3343,-3342,-3342,-3341,-3340,-3339,-3339,
--3338,-3337,-3336,-3335,-3335,-3334,-3333,-3332,-3332,-3331,-3330,-3330,-3329,-3329,-3328,-3328,-3327,-3326,-3326,-3325,-3325,
--3324,-3324,-3323,-3323,-3322,-3322,-3321,-3321,-3320,-3319,-3318,-3318,-3317,-3316,-3315,-3313,-3312,-3311,-3309,-3308,-3306,
--3304,-3303,-3301,-3298,-3296,-3294,-3291,-3289,-3286,-3283,-3280,-3277,-3273,-3270,-3266,-3263,-3259,-3255,-3251,-3247,-3243,
--3239,-3235,-3231,-3227,-3223,-3219,-3215,-3211,-3207,-3203,-3200,-3196,-3192,-3189,-3186,-3183,-3180,-3177,-3174,-3172,-3170,
--3168,-3166,-3165,-3164,-3163,-3162,-3161,-3161,-3161,-3162,-3162,-3163,-3164,-3165,-3166,-3168,-3170,-3172,-3174,-3177,-3179,
--3182,-3185,-3188,-3191,-3194,-3197,-3200,-3204,-3207,-3210,-3213,-3217,-3220,-3223,-3226,-3229,-3231,-3234,-3236,-3239,-3241,
--3243,-3245,-3246,-3248,-3249,-3250,-3251,-3252,-3252,-3253,-3253,-3253,-3252,-3252,-3252,-3251,-3250,-3249,-3248,-3247,-3246,
--3245,-3244,-3243,-3242,-3241,-3240,-3239,-3238,-3237,-3236,-3236,-3235,-3235,-3235,-3235,-3235,-3236,-3237,-3238,-3239,-3240,
--3242,-3244,-3246,-3249,-3252,-3254,-3258,-3261,-3264,-3268,-3272,-3276,-3280,-3285,-3289,-3293,-3298,-3303,-3307,-3312,-3316,
--3321,-3325,-3329,-3333,-3337,-3340,-3344,-3347,-3350,-3352,-3355,-3357,-3358,-3359,-3360,-3360,-3360,-3359,-3358,-3357,-3355,
--3352,-3349,-3346,-3342,-3338,-3333,-3327,-3322,-3315,-3309,-3302,-3295,-3287,-3279,-3270,-3262,-3253,-3244,-3235,-3225,-3216,
--3206,-3196,-3186,-3177,-3167,-3157,-3148,-3138,-3129,-3120,-3111,-3103,-3094,-3086,-3079,-3071,-3065,-3058,-3052,-3046,-3041,
--3036,-3032,-3028,-3025,-3022,-3020,-3018,-3016,-3015,-3014,-3014,-3014,-3015,-3016,-3017,-3019,-3021,-3023,-3025,-3028,-3031,
--3034,-3037,-3040,-3043,-3046,-3049,-3053,-3056,-3058,-3061,-3064,-3066,-3068,-3070,-3072,-3073,-3074,-3075,-3075,-3075,-3075,
--3074,-3073,-3071,-3069,-3067,-3064,-3061,-3057,-3054,-3049,-3045,-3040,-3035,-3030,-3024,-3019,-3013,-3007,-3001,-2995,-2989,
--2983,-2977,-2971,-2965,-2959,-2953,-2948,-2943,-2938,-2933,-2929,-2925,-2922,-2918,-2916,-2913,-2911,-2910,-2909,-2908,-2908,
--2908,-2908,-2909,-2911,-2913,-2915,-2918,-2921,-2924,-2927,-2931,-2935,-2939,-2944,-2948,-2953,-2957,-2962,-2967,-2971,-2976,
--2980,-2985,-2989,-2992,-2996,-2999,-3002,-3005,-3007,-3009,-3011,-3012,-3012,-3013,-3012,-3012,-3010,-3009,-3007,-3004,-3001,
--2998,-2994,-2990,-2985,-2980,-2975,-2969,-2963,-2957,-2951,-2944,-2938,-2931,-2924,-2917,-2910,-2903,-2896,-2890,-2883,-2876,
--2870,-2864,-2858,-2853,-2848,-2843,-2838,-2834,-2830,-2827,-2824,-2822,-2820,-2818,-2817,-2816,-2816,-2817,-2817,-2819,-2820,
--2823,-2825,-2828,-2831,-2835,-2839,-2843,-2848,-2853,-2858,-2864,-2869,-2875,-2881,-2887,-2893,-2899,-2905,-2911,-2916,-2922,
--2928,-2934,-2939,-2944,-2949,-2954,-2958,-2963,-2966,-2970,-2973,-2976,-2978,-2980,-2982,-2983,-2984,-2984,-2984,-2984,-2983,
--2982,-2980,-2978,-2975,-2972,-2969,-2965,-2961,-2956,-2951,-2946,-2940,-2934,-2928,-2921,-2914,-2907,-2899,-2892,-2884,-2876,
--2867,-2859,-2850,-2841,-2832,-2823,-2814,-2804,-2795,-2785,-2776,-2766,-2756,-2747,-2737,-2727,-2717,-2708,-2698,-2688,-2679,
--2669,-2660,-2650,-2641,-2631,-2622,-2613,-2604,-2595,-2586,-2577,-2568,-2559,-2551,-2542,-2534,-2526,-2518,-2510,-2502,-2494,
--2487,-2479,-2472,-2465,-2458,-2451,-2445,-2438,-2432,-2426,-2420,-2414,-2409,-2403,-2398,-2393,-2389,-2384,-2380,-2376,-2373,
--2369,-2366,-2363,-2361,-2358,-2356,-2354,-2353,-2352,-2351,-2350,-2350,-2350,-2350,-2351,-2352,-2353,-2355,-2357,-2359,-2361,
--2364,-2367,-2371,-2374,-2378,-2383,-2387,-2392,-2397,-2403,-2408,-2414,-2420,-2427,-2433,-2440,-2447,-2454,-2462,-2469,-2477,
--2485,-2492,-2500,-2508,-2516,-2524,-2532,-2541,-2549,-2557,-2565,-2572,-2580,-2588,-2595,-2602,-2609,-2616,-2623,-2629,-2635,
--2641,-2646,-2651,-2656,-2660,-2664,-2668,-2671,-2674,-2676,-2677,-2679,-2679,-2679,-2679,-2678,-2677,-2675,-2673,-2670,-2666,
--2662,-2658,-2653,-2648,-2642,-2635,-2629,-2621,-2614,-2605,-2597,-2588,-2579,-2569,-2560,-2550,-2539,-2529,-2518,-2507,-2496,
--2485,-2474,-2462,-2451,-2440,-2429,-2417,-2406,-2395,-2384,-2373,-2362,-2352,-2342,-2331,-2322,-2312,-2303,-2293,-2285,-2276,
--2268,-2260,-2252,-2244,-2237,-2230,-2224,-2218,-2212,-2206,-2200,-2195,-2190,-2185,-2181,-2177,-2172,-2168,-2165,-2161,-2158,
--2154,-2151,-2148,-2145,-2142,-2139,-2137,-2134,-2131,-2128,-2126,-2123,-2120,-2118,-2115,-2112,-2110,-2107,-2104,-2101,-2098,
--2096,-2093,-2090,-2087,-2084,-2081,-2078,-2075,-2072,-2069,-2066,-2063,-2060,-2058,-2055,-2052,-2049,-2047,-2044,-2042,-2039,
--2037,-2035,-2033,-2031,-2029,-2027,-2026,-2025,-2023,-2022,-2021,-2020,-2020,-2019,-2019,-2019,-2019,-2019,-2019,-2019,-2020,
--2020,-2021,-2022,-2023,-2024,-2026,-2027,-2028,-2030,-2032,-2034,-2035,-2037,-2039,-2041,-2044,-2046,-2048,-2050,-2053,-2055,
--2057,-2060,-2062,-2064,-2067,-2069,-2072,-2074,-2076,-2078,-2081,-2083,-2085,-2087,-2089,-2091,-2093,-2095,-2097,-2099,-2101,
--2102,-2104,-2105,-2106,-2108,-2109,-2110,-2110,-2111,-2112,-2112,-2112,-2112,-2112,-2197,-2196,-2194,-2193,-2191,-2190,-2188,
--2186,-2184,-2182,-2180,-2177,-2175,-2172,-2170,-2167,-2164,-2161,-2158,-2155,-2152,-2148,-2145,-2141,-2138,-2134,-2130,-2126,
--2122,-2119,-2115,-2111,-2107,-2102,-2098,-2094,-2090,-2086,-2082,-2078,-2074,-2070,-2066,-2062,-2058,-2054,-2051,-2047,-2044,
--2040,-2037,-2033,-2030,-2027,-2024,-2021,-2019,-2016,-2014,-2011,-2009,-2007,-2005,-2003,-2001,-1999,-1998,-1996,-1995,-1993,
--1992,-1991,-1990,-1989,-1988,-1987,-1986,-1985,-1984,-1983,-1982,-1981,-1980,-1980,-1979,-1978,-1977,-1975,-1974,-1973,-1972,
--1970,-1969,-1967,-1965,-1963,-1961,-1959,-1957,-1954,-1952,-1949,-1946,-1943,-1940,-1937,-1934,-1930,-1927,-1923,-1919,-1916,
--1912,-1907,-1904,-1899,-1895,-1891,-1887,-1882,-1878,-1874,-1870,-1865,-1861,-1857,-1853,-1849,-1845,-1841,-1837,-1834,-1830,
--1827,-1824,-1821,-1818,-1815,-1813,-1811,-1809,-1807,-1805,-1804,-1803,-1802,-1801,-1800,-1800,-1800,-1800,-1801,-1801,-1802,
--1803,-1804,-1806,-1807,-1809,-1811,-1813,-1816,-1818,-1821,-1823,-1826,-1829,-1832,-1835,-1838,-1842,-1845,-1848,-1852,-1855,
--1858,-1862,-1865,-1868,-1872,-1875,-1878,-1882,-1885,-1888,-1891,-1894,-1897,-1899,-1902,-1905,-1907,-1909,-1912,-1914,-1916,
--1918,-1920,-1922,-1923,-1925,-1927,-1928,-1930,-1931,-1932,-1934,-1935,-1936,-1938,-1939,-1940,-1941,-1943,-1944,-1945,-1946,
--1948,-1949,-1950,-1952,-1953,-1955,-1957,-1958,-1960,-1962,-1964,-1966,-1969,-1971,-1973,-1976,-1979,-1981,-1984,-1987,-1990,
--1993,-1997,-2000,-2004,-2007,-2011,-2014,-2018,-2022,-2026,-2030,-2034,-2038,-2042,-2046,-2050,-2055,-2059,-2063,-2067,-2071,
--2076,-2080,-2084,-2088,-2092,-2096,-2100,-2104,-2108,-2112,-2116,-2119,-2123,-2127,-2130,-2134,-2137,-2140,-2144,-2147,-2150,
--2153,-2156,-2159,-2162,-2165,-2168,-2170,-2173,-2176,-2178,-2181,-2184,-2186,-2189,-2191,-2194,-2196,-2199,-2201,-2204,-2206,
--2209,-2212,-2214,-2217,-2220,-2222,-2225,-2228,-2231,-2234,-2237,-2240,-2243,-2246,-2250,-2253,-2256,-2260,-2263,-2267,-2271,
--2274,-2278,-2282,-2286,-2290,-2294,-2298,-2303,-2307,-2311,-2315,-2320,-2324,-2329,-2333,-2338,-2342,-2347,-2352,-2356,-2361,
--2366,-2371,-2375,-2380,-2385,-2390,-2394,-2399,-2404,-2409,-2414,-2418,-2423,-2428,-2433,-2438,-2442,-2447,-2452,-2457,-2461,
--2466,-2471,-2476,-2481,-2485,-2490,-2495,-2500,-2505,-2510,-2514,-2519,-2524,-2529,-2534,-2539,-2544,-2549,-2554,-2559,-2565,
--2570,-2575,-2580,-2586,-2591,-2596,-2602,-2607,-2613,-2619,-2624,-2630,-2636,-2641,-2647,-2653,-2659,-2665,-2671,-2677,-2683,
--2689,-2695,-2701,-2707,-2713,-2720,-2726,-2732,-2738,-2744,-2751,-2757,-2763,-2769,-2776,-2782,-2788,-2794,-2800,-2807,-2813,
--2819,-2825,-2831,-2837,-2843,-2849,-2855,-2860,-2866,-2872,-2878,-2883,-2889,-2894,-2900,-2905,-2910,-2915,-2921,-2926,-2931,
--2936,-2940,-2945,-2950,-2955,-2959,-2964,-2968,-2973,-2977,-2981,-2986,-2990,-2994,-2998,-3002,-3006,-3009,-3013,-3017,-3021,
--3024,-3028,-3031,-3035,-3038,-3041,-3045,-3048,-3051,-3054,-3058,-3061,-3064,-3067,-3070,-3073,-3076,-3078,-3081,-3084,-3087,
--3090,-3092,-3095,-3098,-3100,-3103,-3106,-3108,-3111,-3113,-3116,-3118,-3121,-3123,-3126,-3128,-3130,-3133,-3135,-3138,-3140,
--3142,-3145,-3147,-3149,-3151,-3154,-3156,-3158,-3161,-3163,-3165,-3167,-3170,-3172,-3174,-3176,-3178,-3181,-3183,-3185,-3187,
--3190,-3192,-3194,-3196,-3198,-3200,-3203,-3205,-3207,-3209,-3211,-3214,-3216,-3218,-3220,-3222,-3224,-3227,-3229,-3231,-3233,
--3235,-3237,-3239,-3242,-3244,-3246,-3248,-3250,-3252,-3254,-3256,-3258,-3260,-3262,-3264,-3265,-3267,-3269,-3271,-3272,-3274,
--3276,-3277,-3279,-3281,-3282,-3283,-3285,-3286,-3287,-3289,-3290,-3291,-3292,-3293,-3294,-3294,-3295,-3296,-3297,-3297,-3298,
--3298,-3299,-3299,-3299,-3299,-3299,-3300,-3300,-3299,-3299,-3299,-3299,-3299,-3299,-3298,-3298,-3297,-3297,-3297,-3296,-3296,
--3295,-3294,-3294,-3293,-3293,-3292,-3292,-3291,-3290,-3290,-3290,-3289,-3289,-3288,-3288,-3287,-3287,-3287,-3286,-3286,-3286,
--3286,-3286,-3286,-3286,-3286,-3286,-3286,-3286,-3286,-3286,-3286,-3286,-3286,-3287,-3287,-3287,-3287,-3287,-3288,-3288,-3288,
--3288,-3288,-3288,-3288,-3288,-3288,-3287,-3287,-3286,-3286,-3285,-3285,-3284,-3283,-3282,-3281,-3280,-3278,-3277,-3275,-3274,
--3272,-3270,-3268,-3265,-3263,-3261,-3258,-3256,-3253,-3250,-3247,-3245,-3242,-3238,-3235,-3232,-3229,-3226,-3222,-3219,-3216,
--3213,-3209,-3206,-3203,-3200,-3197,-3194,-3191,-3188,-3185,-3182,-3180,-3177,-3175,-3173,-3170,-3168,-3167,-3165,-3163,-3162,
--3160,-3159,-3158,-3157,-3157,-3156,-3155,-3155,-3155,-3154,-3154,-3154,-3155,-3155,-3155,-3155,-3156,-3156,-3157,-3157,-3158,
--3158,-3159,-3159,-3160,-3160,-3161,-3161,-3161,-3161,-3162,-3162,-3162,-3162,-3162,-3161,-3161,-3161,-3160,-3159,-3159,-3158,
--3157,-3156,-3155,-3154,-3152,-3151,-3150,-3148,-3147,-3145,-3144,-3142,-3140,-3139,-3137,-3136,-3134,-3133,-3131,-3130,-3129,
--3128,-3127,-3126,-3125,-3124,-3124,-3123,-3123,-3123,-3123,-3123,-3124,-3124,-3125,-3126,-3127,-3129,-3130,-3132,-3134,-3136,
--3138,-3140,-3142,-3145,-3148,-3150,-3153,-3156,-3159,-3162,-3165,-3169,-3172,-3175,-3178,-3181,-3184,-3187,-3190,-3192,-3195,
--3197,-3200,-3202,-3204,-3206,-3207,-3208,-3210,-3210,-3211,-3211,-3211,-3211,-3211,-3210,-3209,-3208,-3207,-3205,-3203,-3201,
--3198,-3195,-3192,-3189,-3186,-3182,-3178,-3174,-3170,-3166,-3162,-3157,-3153,-3148,-3143,-3139,-3134,-3129,-3124,-3120,-3115,
--3110,-3106,-3102,-3097,-3093,-3089,-3085,-3082,-3078,-3075,-3072,-3069,-3066,-3064,-3062,-3060,-3058,-3056,-3055,-3054,-3053,
--3052,-3052,-3051,-3051,-3051,-3052,-3052,-3052,-3053,-3054,-3055,-3055,-3056,-3057,-3058,-3059,-3060,-3061,-3062,-3063,-3064,
--3064,-3065,-3065,-3065,-3065,-3065,-3065,-3065,-3064,-3063,-3062,-3061,-3059,-3058,-3056,-3054,-3051,-3049,-3046,-3043,-3039,
--3036,-3032,-3029,-3025,-3021,-3016,-3012,-3008,-3003,-2998,-2994,-2989,-2985,-2980,-2975,-2971,-2966,-2962,-2957,-2953,-2949,
--2945,-2941,-2937,-2934,-2931,-2928,-2925,-2922,-2920,-2918,-2916,-2914,-2913,-2912,-2911,-2910,-2910,-2909,-2909,-2909,-2910,
--2910,-2911,-2912,-2913,-2914,-2915,-2917,-2918,-2920,-2921,-2923,-2924,-2926,-2927,-2929,-2930,-2931,-2932,-2933,-2934,-2935,
--2935,-2936,-2936,-2936,-2936,-2935,-2934,-2933,-2932,-2931,-2929,-2927,-2925,-2923,-2921,-2918,-2915,-2912,-2909,-2905,-2902,
--2898,-2894,-2890,-2886,-2882,-2878,-2873,-2869,-2865,-2861,-2857,-2853,-2849,-2845,-2841,-2837,-2834,-2830,-2827,-2824,-2821,
--2818,-2816,-2814,-2812,-2810,-2809,-2808,-2807,-2806,-2806,-2806,-2806,-2806,-2807,-2808,-2809,-2810,-2812,-2813,-2815,-2817,
--2819,-2822,-2824,-2827,-2829,-2832,-2835,-2838,-2841,-2843,-2846,-2849,-2852,-2854,-2857,-2859,-2862,-2864,-2866,-2867,-2869,
--2871,-2872,-2873,-2873,-2874,-2874,-2874,-2874,-2873,-2873,-2871,-2870,-2868,-2866,-2864,-2862,-2859,-2856,-2852,-2849,-2845,
--2841,-2836,-2832,-2827,-2822,-2817,-2811,-2806,-2800,-2794,-2788,-2782,-2775,-2769,-2762,-2755,-2749,-2742,-2735,-2728,-2721,
--2714,-2707,-2700,-2693,-2686,-2679,-2672,-2665,-2658,-2651,-2644,-2637,-2631,-2624,-2617,-2611,-2604,-2598,-2592,-2586,-2579,
--2573,-2567,-2562,-2556,-2550,-2544,-2539,-2533,-2528,-2523,-2518,-2512,-2507,-2503,-2498,-2493,-2488,-2484,-2479,-2475,-2471,
--2467,-2462,-2458,-2455,-2451,-2447,-2444,-2440,-2437,-2434,-2431,-2428,-2426,-2423,-2421,-2419,-2416,-2415,-2413,-2411,-2410,
--2409,-2408,-2407,-2407,-2406,-2406,-2406,-2407,-2407,-2408,-2409,-2410,-2412,-2414,-2416,-2418,-2420,-2423,-2426,-2429,-2432,
--2436,-2439,-2443,-2447,-2452,-2456,-2461,-2466,-2471,-2476,-2481,-2487,-2492,-2498,-2503,-2509,-2515,-2521,-2526,-2532,-2538,
--2544,-2550,-2555,-2561,-2566,-2572,-2577,-2582,-2587,-2592,-2596,-2601,-2605,-2609,-2612,-2615,-2618,-2621,-2623,-2625,-2627,
--2628,-2629,-2630,-2630,-2630,-2629,-2628,-2627,-2625,-2623,-2621,-2618,-2614,-2611,-2607,-2602,-2597,-2592,-2587,-2581,-2575,
--2568,-2561,-2554,-2547,-2540,-2532,-2524,-2516,-2507,-2499,-2490,-2481,-2472,-2463,-2454,-2445,-2436,-2427,-2418,-2409,-2400,
--2391,-2382,-2373,-2365,-2356,-2348,-2340,-2332,-2324,-2317,-2309,-2302,-2295,-2288,-2282,-2276,-2270,-2264,-2258,-2253,-2248,
--2243,-2239,-2235,-2231,-2227,-2223,-2220,-2217,-2214,-2211,-2209,-2206,-2204,-2202,-2201,-2199,-2198,-2196,-2195,-2194,-2193,
--2192,-2191,-2191,-2190,-2190,-2189,-2189,-2188,-2188,-2188,-2187,-2187,-2187,-2187,-2187,-2186,-2186,-2186,-2186,-2186,-2185,
--2185,-2185,-2185,-2185,-2185,-2184,-2184,-2184,-2184,-2183,-2183,-2183,-2183,-2183,-2183,-2182,-2182,-2182,-2182,-2182,-2182,
--2182,-2182,-2182,-2182,-2182,-2182,-2182,-2182,-2182,-2183,-2183,-2183,-2184,-2184,-2184,-2185,-2185,-2186,-2186,-2187,-2187,
--2188,-2188,-2189,-2190,-2190,-2191,-2192,-2192,-2193,-2194,-2194,-2195,-2196,-2196,-2197,-2198,-2198,-2199,-2200,-2200,-2201,
--2201,-2202,-2202,-2203,-2203,-2204,-2204,-2204,-2204,-2205,-2205,-2205,-2205,-2205,-2205,-2204,-2204,-2204,-2203,-2203,-2202,
--2202,-2201,-2200,-2199,-2198,-2197,-2305,-2303,-2300,-2298,-2295,-2292,-2290,-2287,-2285,-2282,-2279,-2277,-2274,-2271,-2268,
--2266,-2263,-2260,-2257,-2255,-2252,-2249,-2246,-2243,-2241,-2238,-2235,-2232,-2229,-2227,-2224,-2221,-2219,-2216,-2213,-2211,
--2208,-2205,-2203,-2200,-2198,-2195,-2193,-2191,-2188,-2186,-2184,-2181,-2179,-2177,-2175,-2173,-2171,-2169,-2167,-2165,-2164,
--2162,-2160,-2158,-2157,-2155,-2154,-2152,-2150,-2149,-2147,-2146,-2144,-2143,-2141,-2140,-2139,-2137,-2135,-2134,-2132,-2131,
--2129,-2128,-2126,-2124,-2122,-2120,-2118,-2117,-2114,-2112,-2110,-2108,-2106,-2103,-2101,-2098,-2095,-2093,-2090,-2087,-2084,
--2081,-2077,-2074,-2071,-2067,-2064,-2060,-2057,-2053,-2049,-2045,-2042,-2038,-2034,-2030,-2026,-2022,-2018,-2014,-2010,-2006,
--2002,-1998,-1994,-1990,-1987,-1983,-1979,-1976,-1972,-1969,-1965,-1962,-1959,-1956,-1954,-1951,-1948,-1946,-1944,-1942,-1940,
--1938,-1937,-1935,-1934,-1933,-1932,-1932,-1931,-1931,-1930,-1931,-1931,-1931,-1932,-1933,-1934,-1935,-1936,-1937,-1939,-1940,
--1942,-1944,-1946,-1949,-1951,-1953,-1956,-1959,-1961,-1964,-1967,-1970,-1973,-1976,-1979,-1982,-1986,-1989,-1992,-1995,-1998,
--2002,-2005,-2008,-2012,-2015,-2018,-2021,-2025,-2028,-2031,-2034,-2037,-2040,-2043,-2046,-2049,-2052,-2055,-2058,-2060,-2063,
--2066,-2069,-2071,-2074,-2076,-2079,-2081,-2084,-2086,-2089,-2091,-2094,-2096,-2099,-2101,-2103,-2106,-2108,-2110,-2113,-2115,
--2118,-2120,-2122,-2125,-2127,-2130,-2132,-2134,-2137,-2139,-2142,-2144,-2147,-2149,-2152,-2154,-2157,-2159,-2162,-2164,-2166,
--2169,-2171,-2174,-2176,-2179,-2181,-2183,-2186,-2188,-2190,-2193,-2195,-2197,-2199,-2201,-2204,-2206,-2208,-2210,-2212,-2214,
--2215,-2217,-2219,-2221,-2223,-2224,-2226,-2228,-2229,-2231,-2233,-2234,-2236,-2237,-2239,-2240,-2242,-2243,-2245,-2247,-2248,
--2250,-2251,-2253,-2254,-2256,-2258,-2259,-2261,-2263,-2265,-2267,-2269,-2271,-2273,-2275,-2277,-2279,-2282,-2284,-2287,-2289,
--2292,-2295,-2298,-2300,-2303,-2307,-2310,-2313,-2316,-2320,-2323,-2327,-2330,-2334,-2338,-2342,-2346,-2350,-2354,-2358,-2362,
--2367,-2371,-2375,-2380,-2384,-2389,-2393,-2398,-2403,-2407,-2412,-2417,-2421,-2426,-2431,-2436,-2441,-2445,-2450,-2455,-2460,
--2465,-2470,-2474,-2479,-2484,-2489,-2494,-2498,-2503,-2508,-2513,-2517,-2522,-2527,-2532,-2536,-2541,-2546,-2550,-2555,-2559,
--2564,-2569,-2573,-2578,-2583,-2587,-2592,-2596,-2601,-2606,-2610,-2615,-2619,-2624,-2629,-2633,-2638,-2643,-2648,-2652,-2657,
--2662,-2667,-2671,-2676,-2681,-2686,-2691,-2696,-2701,-2706,-2711,-2716,-2721,-2726,-2731,-2736,-2741,-2746,-2751,-2756,-2761,
--2766,-2772,-2777,-2782,-2787,-2792,-2797,-2802,-2807,-2812,-2817,-2822,-2827,-2832,-2837,-2842,-2847,-2852,-2857,-2862,-2867,
--2871,-2876,-2881,-2885,-2890,-2894,-2899,-2903,-2908,-2912,-2916,-2920,-2925,-2929,-2933,-2937,-2941,-2945,-2949,-2952,-2956,
--2960,-2963,-2967,-2971,-2974,-2978,-2981,-2984,-2988,-2991,-2994,-2997,-3000,-3003,-3006,-3009,-3012,-3015,-3018,-3021,-3023,
--3026,-3029,-3031,-3034,-3037,-3039,-3042,-3044,-3047,-3049,-3051,-3054,-3056,-3058,-3061,-3063,-3065,-3067,-3070,-3072,-3074,
--3076,-3078,-3081,-3083,-3085,-3087,-3089,-3091,-3093,-3095,-3097,-3099,-3101,-3103,-3106,-3108,-3110,-3112,-3114,-3116,-3118,
--3120,-3122,-3124,-3126,-3128,-3130,-3132,-3134,-3136,-3138,-3140,-3142,-3144,-3146,-3148,-3150,-3152,-3154,-3156,-3158,-3161,
--3163,-3165,-3167,-3169,-3171,-3173,-3175,-3177,-3179,-3182,-3184,-3186,-3188,-3190,-3192,-3194,-3196,-3198,-3200,-3202,-3204,
--3206,-3208,-3210,-3212,-3214,-3216,-3218,-3220,-3222,-3224,-3226,-3227,-3229,-3231,-3232,-3234,-3236,-3237,-3239,-3240,-3242,
--3243,-3244,-3246,-3247,-3248,-3249,-3251,-3252,-3253,-3254,-3254,-3255,-3256,-3257,-3258,-3259,-3259,-3260,-3261,-3261,-3262,
--3262,-3263,-3263,-3264,-3264,-3264,-3265,-3265,-3265,-3266,-3266,-3266,-3267,-3267,-3267,-3267,-3268,-3268,-3268,-3269,-3269,
--3269,-3270,-3270,-3270,-3271,-3271,-3271,-3272,-3272,-3273,-3273,-3274,-3275,-3275,-3276,-3276,-3277,-3278,-3278,-3279,-3280,
--3280,-3281,-3282,-3282,-3283,-3284,-3284,-3285,-3286,-3286,-3287,-3287,-3288,-3288,-3289,-3289,-3289,-3289,-3290,-3290,-3290,
--3290,-3289,-3289,-3289,-3288,-3288,-3287,-3286,-3286,-3285,-3284,-3283,-3281,-3280,-3279,-3277,-3275,-3274,-3272,-3270,-3268,
--3265,-3263,-3261,-3259,-3256,-3253,-3251,-3248,-3245,-3242,-3239,-3236,-3233,-3230,-3227,-3224,-3221,-3218,-3215,-3211,-3208,
--3205,-3202,-3198,-3195,-3192,-3189,-3186,-3183,-3180,-3177,-3173,-3170,-3168,-3165,-3162,-3159,-3156,-3153,-3151,-3148,-3145,
--3143,-3140,-3137,-3135,-3132,-3130,-3127,-3125,-3122,-3120,-3118,-3115,-3113,-3110,-3108,-3105,-3103,-3101,-3098,-3096,-3093,
--3090,-3088,-3085,-3083,-3080,-3077,-3074,-3072,-3069,-3066,-3063,-3060,-3057,-3055,-3052,-3049,-3046,-3043,-3040,-3037,-3034,
--3031,-3028,-3025,-3022,-3020,-3017,-3014,-3012,-3009,-3006,-3004,-3002,-3000,-2998,-2996,-2994,-2992,-2990,-2989,-2988,-2986,
--2985,-2984,-2984,-2983,-2983,-2982,-2982,-2982,-2983,-2983,-2984,-2984,-2985,-2986,-2987,-2989,-2990,-2992,-2994,-2996,-2998,
--3000,-3002,-3004,-3007,-3009,-3012,-3014,-3017,-3020,-3023,-3026,-3028,-3031,-3034,-3037,-3040,-3043,-3045,-3048,-3051,-3054,
--3056,-3059,-3061,-3064,-3066,-3068,-3070,-3072,-3074,-3076,-3078,-3079,-3081,-3082,-3084,-3085,-3086,-3087,-3088,-3089,-3090,
--3090,-3091,-3091,-3092,-3092,-3092,-3093,-3093,-3093,-3093,-3093,-3093,-3093,-3093,-3093,-3092,-3092,-3092,-3092,-3092,-3092,
--3092,-3092,-3091,-3091,-3091,-3091,-3091,-3091,-3091,-3091,-3091,-3091,-3091,-3091,-3091,-3091,-3091,-3091,-3091,-3091,-3091,
--3091,-3091,-3091,-3091,-3091,-3090,-3090,-3089,-3089,-3088,-3087,-3087,-3086,-3085,-3083,-3082,-3081,-3079,-3078,-3076,-3074,
--3072,-3069,-3067,-3065,-3062,-3059,-3056,-3053,-3050,-3047,-3043,-3040,-3036,-3032,-3028,-3024,-3020,-3016,-3012,-3008,-3003,
--2999,-2995,-2990,-2986,-2981,-2977,-2972,-2968,-2964,-2959,-2955,-2951,-2947,-2943,-2939,-2935,-2931,-2928,-2924,-2921,-2917,
--2914,-2911,-2908,-2906,-2903,-2900,-2898,-2896,-2894,-2892,-2890,-2888,-2887,-2885,-2884,-2883,-2882,-2881,-2880,-2879,-2878,
--2878,-2877,-2876,-2876,-2875,-2875,-2874,-2874,-2873,-2873,-2873,-2872,-2872,-2871,-2871,-2870,-2869,-2869,-2868,-2867,-2866,
--2865,-2864,-2863,-2862,-2861,-2859,-2858,-2857,-2855,-2854,-2852,-2850,-2849,-2847,-2845,-2843,-2841,-2839,-2837,-2836,-2834,
--2832,-2830,-2828,-2826,-2824,-2822,-2820,-2818,-2817,-2815,-2813,-2812,-2810,-2809,-2808,-2806,-2805,-2804,-2803,-2802,-2801,
--2800,-2800,-2799,-2798,-2798,-2798,-2797,-2797,-2797,-2797,-2796,-2796,-2796,-2796,-2796,-2796,-2796,-2796,-2796,-2796,-2796,
--2796,-2796,-2796,-2796,-2795,-2795,-2795,-2794,-2793,-2793,-2792,-2791,-2790,-2789,-2787,-2786,-2784,-2782,-2780,-2778,-2776,
--2774,-2772,-2769,-2766,-2763,-2760,-2757,-2754,-2750,-2747,-2743,-2739,-2735,-2731,-2727,-2723,-2719,-2714,-2710,-2705,-2701,
--2696,-2691,-2687,-2682,-2677,-2672,-2667,-2663,-2658,-2653,-2648,-2643,-2639,-2634,-2629,-2625,-2620,-2616,-2611,-2607,-2603,
--2598,-2594,-2590,-2586,-2582,-2578,-2574,-2571,-2567,-2563,-2560,-2557,-2553,-2550,-2547,-2544,-2541,-2538,-2535,-2532,-2529,
--2527,-2524,-2522,-2519,-2517,-2515,-2512,-2510,-2508,-2506,-2504,-2502,-2500,-2498,-2496,-2494,-2492,-2491,-2489,-2487,-2486,
--2484,-2483,-2482,-2480,-2479,-2478,-2477,-2476,-2475,-2474,-2473,-2473,-2472,-2471,-2471,-2471,-2471,-2471,-2471,-2471,-2471,
--2471,-2472,-2472,-2473,-2474,-2475,-2476,-2477,-2479,-2480,-2482,-2484,-2486,-2488,-2490,-2492,-2494,-2497,-2500,-2502,-2505,
--2508,-2511,-2514,-2517,-2520,-2523,-2527,-2530,-2533,-2537,-2540,-2543,-2547,-2550,-2553,-2557,-2560,-2563,-2566,-2569,-2572,
--2575,-2577,-2580,-2582,-2584,-2586,-2588,-2590,-2592,-2593,-2594,-2595,-2595,-2596,-2596,-2596,-2596,-2595,-2595,-2593,-2592,
--2591,-2589,-2587,-2585,-2582,-2579,-2576,-2573,-2569,-2566,-2562,-2557,-2553,-2548,-2544,-2539,-2533,-2528,-2522,-2517,-2511,
--2505,-2499,-2493,-2487,-2481,-2474,-2468,-2462,-2455,-2449,-2442,-2436,-2430,-2423,-2417,-2411,-2405,-2399,-2393,-2387,-2381,
--2376,-2370,-2365,-2360,-2355,-2350,-2345,-2341,-2337,-2333,-2329,-2325,-2322,-2319,-2316,-2313,-2310,-2308,-2306,-2304,-2302,
--2300,-2299,-2298,-2297,-2296,-2295,-2295,-2294,-2294,-2294,-2295,-2295,-2295,-2296,-2297,-2298,-2299,-2300,-2301,-2302,-2304,
--2305,-2307,-2309,-2310,-2312,-2314,-2316,-2318,-2319,-2321,-2323,-2325,-2327,-2329,-2331,-2333,-2335,-2337,-2339,-2341,-2343,
--2345,-2347,-2349,-2350,-2352,-2354,-2355,-2357,-2359,-2360,-2362,-2363,-2364,-2365,-2367,-2368,-2369,-2370,-2371,-2372,-2372,
--2373,-2374,-2374,-2375,-2375,-2376,-2376,-2376,-2376,-2376,-2376,-2376,-2376,-2376,-2376,-2375,-2375,-2375,-2374,-2373,-2373,
--2372,-2371,-2370,-2370,-2369,-2368,-2367,-2365,-2364,-2363,-2362,-2360,-2359,-2357,-2356,-2354,-2353,-2351,-2349,-2348,-2346,
--2344,-2342,-2340,-2338,-2336,-2334,-2332,-2330,-2328,-2326,-2324,-2322,-2319,-2317,-2315,-2312,-2310,-2308,-2305,-2381,-2378,
--2375,-2371,-2368,-2365,-2362,-2359,-2356,-2353,-2350,-2347,-2344,-2341,-2338,-2336,-2333,-2330,-2327,-2325,-2322,-2320,-2317,
--2315,-2312,-2310,-2307,-2305,-2303,-2301,-2299,-2296,-2294,-2292,-2290,-2288,-2286,-2284,-2283,-2281,-2279,-2277,-2276,-2274,
--2272,-2271,-2269,-2267,-2266,-2264,-2263,-2261,-2260,-2258,-2257,-2255,-2254,-2252,-2251,-2249,-2248,-2246,-2245,-2243,-2242,
--2240,-2239,-2237,-2235,-2234,-2232,-2230,-2228,-2227,-2225,-2223,-2221,-2219,-2217,-2215,-2213,-2210,-2208,-2206,-2203,-2201,
--2198,-2196,-2193,-2191,-2188,-2185,-2182,-2179,-2176,-2173,-2170,-2167,-2164,-2161,-2158,-2154,-2151,-2148,-2144,-2141,-2138,
--2134,-2131,-2127,-2124,-2120,-2117,-2113,-2110,-2106,-2103,-2100,-2096,-2093,-2090,-2086,-2083,-2080,-2077,-2074,-2071,-2069,
--2066,-2063,-2061,-2058,-2056,-2054,-2052,-2050,-2048,-2046,-2044,-2043,-2042,-2040,-2039,-2038,-2038,-2037,-2036,-2036,-2036,
--2036,-2036,-2036,-2036,-2037,-2037,-2038,-2039,-2040,-2041,-2042,-2044,-2045,-2047,-2049,-2051,-2053,-2055,-2057,-2059,-2062,
--2064,-2067,-2070,-2072,-2075,-2078,-2081,-2084,-2087,-2090,-2094,-2097,-2100,-2103,-2107,-2110,-2114,-2117,-2121,-2124,-2127,
--2131,-2134,-2138,-2141,-2145,-2148,-2152,-2155,-2159,-2162,-2166,-2169,-2172,-2176,-2179,-2182,-2186,-2189,-2192,-2195,-2198,
--2202,-2205,-2208,-2211,-2214,-2217,-2220,-2222,-2225,-2228,-2231,-2234,-2236,-2239,-2242,-2244,-2247,-2249,-2252,-2254,-2256,
--2259,-2261,-2263,-2265,-2268,-2270,-2272,-2274,-2276,-2278,-2280,-2282,-2283,-2285,-2287,-2289,-2290,-2292,-2293,-2295,-2296,
--2298,-2299,-2300,-2302,-2303,-2304,-2305,-2307,-2308,-2309,-2310,-2311,-2312,-2313,-2314,-2315,-2316,-2317,-2317,-2318,-2319,
--2320,-2321,-2322,-2323,-2323,-2324,-2325,-2326,-2327,-2328,-2329,-2330,-2331,-2332,-2333,-2334,-2335,-2336,-2338,-2339,-2340,
--2342,-2343,-2345,-2346,-2348,-2350,-2352,-2354,-2355,-2357,-2360,-2362,-2364,-2366,-2369,-2371,-2374,-2376,-2379,-2382,-2385,
--2388,-2391,-2394,-2397,-2400,-2404,-2407,-2411,-2414,-2418,-2421,-2425,-2429,-2433,-2437,-2441,-2445,-2449,-2453,-2457,-2461,
--2465,-2469,-2474,-2478,-2482,-2487,-2491,-2495,-2500,-2504,-2509,-2513,-2517,-2522,-2526,-2531,-2535,-2540,-2544,-2549,-2553,
--2557,-2562,-2566,-2571,-2575,-2579,-2584,-2588,-2592,-2597,-2601,-2605,-2610,-2614,-2618,-2622,-2627,-2631,-2635,-2639,-2643,
--2648,-2652,-2656,-2660,-2664,-2669,-2673,-2677,-2681,-2685,-2689,-2694,-2698,-2702,-2706,-2710,-2714,-2719,-2723,-2727,-2731,
--2735,-2739,-2744,-2748,-2752,-2756,-2760,-2764,-2769,-2773,-2777,-2781,-2785,-2789,-2794,-2798,-2802,-2806,-2810,-2814,-2818,
--2822,-2827,-2831,-2835,-2839,-2843,-2847,-2851,-2855,-2859,-2862,-2866,-2870,-2874,-2878,-2882,-2885,-2889,-2893,-2896,-2900,
--2903,-2907,-2910,-2914,-2917,-2921,-2924,-2927,-2931,-2934,-2937,-2940,-2943,-2946,-2949,-2952,-2955,-2958,-2961,-2964,-2967,
--2970,-2972,-2975,-2978,-2980,-2983,-2985,-2988,-2990,-2993,-2995,-2998,-3000,-3002,-3005,-3007,-3009,-3011,-3013,-3016,-3018,
--3020,-3022,-3024,-3026,-3028,-3030,-3032,-3034,-3036,-3038,-3040,-3042,-3044,-3046,-3048,-3050,-3051,-3053,-3055,-3057,-3059,
--3061,-3062,-3064,-3066,-3068,-3070,-3071,-3073,-3075,-3077,-3079,-3080,-3082,-3084,-3086,-3087,-3089,-3091,-3093,-3095,-3096,
--3098,-3100,-3102,-3103,-3105,-3107,-3109,-3111,-3112,-3114,-3116,-3118,-3120,-3121,-3123,-3125,-3127,-3129,-3130,-3132,-3134,
--3136,-3138,-3139,-3141,-3143,-3145,-3146,-3148,-3150,-3152,-3153,-3155,-3157,-3159,-3160,-3162,-3164,-3165,-3167,-3169,-3170,
--3172,-3174,-3175,-3177,-3178,-3180,-3181,-3183,-3184,-3186,-3187,-3189,-3190,-3191,-3193,-3194,-3195,-3197,-3198,-3199,-3201,
--3202,-3203,-3204,-3205,-3206,-3207,-3209,-3210,-3211,-3212,-3213,-3214,-3215,-3216,-3217,-3218,-3219,-3219,-3220,-3221,-3222,
--3223,-3224,-3225,-3226,-3227,-3228,-3228,-3229,-3230,-3231,-3232,-3233,-3233,-3234,-3235,-3236,-3237,-3238,-3239,-3239,-3240,
--3241,-3242,-3243,-3244,-3244,-3245,-3246,-3247,-3247,-3248,-3249,-3250,-3250,-3251,-3251,-3252,-3253,-3253,-3254,-3254,-3254,
--3255,-3255,-3255,-3255,-3256,-3256,-3256,-3256,-3255,-3255,-3255,-3255,-3254,-3254,-3253,-3253,-3252,-3251,-3250,-3249,-3248,
--3247,-3245,-3244,-3243,-3241,-3239,-3238,-3236,-3234,-3232,-3230,-3228,-3225,-3223,-3221,-3218,-3215,-3213,-3210,-3207,-3204,
--3201,-3198,-3195,-3192,-3188,-3185,-3182,-3178,-3175,-3171,-3168,-3164,-3160,-3157,-3153,-3149,-3145,-3142,-3138,-3134,-3130,
--3126,-3122,-3118,-3114,-3110,-3107,-3103,-3099,-3095,-3091,-3087,-3083,-3079,-3075,-3071,-3067,-3063,-3059,-3055,-3051,-3047,
--3043,-3039,-3035,-3031,-3027,-3023,-3019,-3015,-3011,-3007,-3003,-2999,-2995,-2991,-2987,-2983,-2979,-2975,-2971,-2967,-2963,
--2959,-2955,-2952,-2948,-2944,-2940,-2936,-2933,-2929,-2925,-2922,-2918,-2915,-2911,-2908,-2904,-2901,-2898,-2895,-2892,-2889,
--2886,-2883,-2881,-2878,-2876,-2873,-2871,-2869,-2867,-2865,-2863,-2862,-2860,-2859,-2858,-2857,-2856,-2855,-2855,-2854,-2854,
--2854,-2854,-2854,-2855,-2855,-2856,-2857,-2858,-2859,-2860,-2862,-2863,-2865,-2867,-2869,-2871,-2873,-2875,-2878,-2881,-2883,
--2886,-2889,-2892,-2895,-2898,-2902,-2905,-2908,-2912,-2915,-2919,-2922,-2926,-2930,-2933,-2937,-2941,-2945,-2948,-2952,-2956,
--2960,-2963,-2967,-2971,-2974,-2978,-2982,-2985,-2989,-2992,-2996,-2999,-3003,-3006,-3009,-3012,-3015,-3018,-3021,-3024,-3027,
--3030,-3033,-3035,-3038,-3041,-3043,-3045,-3048,-3050,-3052,-3054,-3056,-3058,-3060,-3061,-3063,-3064,-3066,-3067,-3068,-3070,
--3071,-3072,-3073,-3073,-3074,-3075,-3075,-3076,-3076,-3076,-3076,-3076,-3076,-3076,-3076,-3075,-3075,-3074,-3073,-3072,-3071,
--3070,-3069,-3068,-3066,-3064,-3063,-3061,-3059,-3057,-3055,-3052,-3050,-3047,-3045,-3042,-3039,-3036,-3033,-3030,-3027,-3024,
--3020,-3017,-3013,-3009,-3006,-3002,-2998,-2994,-2990,-2986,-2982,-2978,-2974,-2970,-2966,-2962,-2957,-2953,-2949,-2945,-2941,
--2937,-2933,-2929,-2925,-2921,-2917,-2913,-2909,-2905,-2902,-2898,-2895,-2891,-2888,-2885,-2881,-2878,-2875,-2872,-2869,-2867,
--2864,-2861,-2859,-2856,-2854,-2852,-2850,-2848,-2846,-2844,-2842,-2840,-2839,-2837,-2836,-2834,-2833,-2832,-2830,-2829,-2828,
--2827,-2826,-2825,-2824,-2823,-2823,-2822,-2821,-2820,-2820,-2819,-2818,-2818,-2817,-2817,-2816,-2815,-2815,-2814,-2814,-2813,
--2813,-2812,-2812,-2811,-2811,-2810,-2810,-2809,-2808,-2808,-2807,-2807,-2806,-2806,-2805,-2805,-2804,-2804,-2803,-2803,-2802,
--2802,-2801,-2801,-2800,-2800,-2799,-2799,-2798,-2798,-2797,-2797,-2796,-2795,-2795,-2794,-2794,-2793,-2792,-2792,-2791,-2790,
--2789,-2789,-2788,-2787,-2786,-2785,-2784,-2783,-2782,-2781,-2779,-2778,-2777,-2775,-2774,-2772,-2771,-2769,-2767,-2765,-2763,
--2761,-2759,-2757,-2755,-2752,-2750,-2747,-2745,-2742,-2739,-2736,-2733,-2730,-2727,-2724,-2721,-2718,-2714,-2711,-2707,-2704,
--2700,-2696,-2693,-2689,-2685,-2681,-2677,-2674,-2670,-2666,-2662,-2658,-2654,-2650,-2646,-2642,-2639,-2635,-2631,-2627,-2624,
--2620,-2616,-2613,-2609,-2606,-2602,-2599,-2596,-2592,-2589,-2586,-2583,-2580,-2577,-2575,-2572,-2569,-2567,-2564,-2562,-2560,
--2558,-2556,-2553,-2552,-2550,-2548,-2546,-2544,-2543,-2541,-2540,-2538,-2537,-2536,-2535,-2534,-2532,-2531,-2530,-2529,-2529,
--2528,-2527,-2526,-2525,-2525,-2524,-2524,-2523,-2523,-2522,-2522,-2521,-2521,-2520,-2520,-2520,-2520,-2519,-2519,-2519,-2519,
--2519,-2519,-2519,-2519,-2519,-2519,-2520,-2520,-2520,-2520,-2521,-2521,-2522,-2522,-2523,-2524,-2524,-2525,-2526,-2527,-2528,
--2529,-2530,-2531,-2532,-2533,-2535,-2536,-2537,-2539,-2540,-2542,-2543,-2545,-2546,-2548,-2550,-2551,-2553,-2555,-2557,-2558,
--2560,-2562,-2563,-2565,-2567,-2569,-2570,-2572,-2573,-2575,-2576,-2578,-2579,-2580,-2581,-2582,-2583,-2584,-2585,-2586,-2586,
--2587,-2587,-2587,-2587,-2587,-2587,-2587,-2586,-2585,-2585,-2584,-2582,-2581,-2580,-2578,-2576,-2574,-2572,-2570,-2568,-2565,
--2562,-2560,-2557,-2554,-2550,-2547,-2543,-2540,-2536,-2532,-2528,-2524,-2520,-2516,-2511,-2507,-2503,-2498,-2494,-2489,-2485,
--2480,-2475,-2471,-2466,-2462,-2457,-2452,-2448,-2443,-2439,-2435,-2430,-2426,-2422,-2418,-2414,-2411,-2407,-2403,-2400,-2397,
--2394,-2391,-2388,-2385,-2383,-2380,-2378,-2376,-2374,-2372,-2371,-2369,-2368,-2367,-2366,-2366,-2365,-2365,-2365,-2365,-2365,
--2365,-2365,-2366,-2367,-2368,-2369,-2370,-2371,-2373,-2375,-2376,-2378,-2380,-2382,-2384,-2387,-2389,-2391,-2394,-2397,-2399,
--2402,-2405,-2408,-2410,-2413,-2416,-2419,-2422,-2425,-2428,-2431,-2434,-2437,-2439,-2442,-2445,-2448,-2450,-2453,-2456,-2458,
--2461,-2463,-2465,-2468,-2470,-2472,-2474,-2476,-2478,-2479,-2481,-2482,-2484,-2485,-2486,-2487,-2488,-2489,-2490,-2490,-2491,
--2491,-2491,-2491,-2491,-2491,-2491,-2490,-2490,-2489,-2488,-2487,-2486,-2485,-2484,-2483,-2481,-2480,-2478,-2476,-2475,-2473,
--2471,-2468,-2466,-2464,-2462,-2459,-2457,-2454,-2452,-2449,-2446,-2443,-2440,-2438,-2435,-2432,-2429,-2425,-2422,-2419,-2416,
--2413,-2410,-2407,-2403,-2400,-2397,-2394,-2391,-2387,-2384,-2381,-2424,-2421,-2418,-2415,-2413,-2410,-2407,-2404,-2401,-2398,
--2396,-2393,-2390,-2388,-2385,-2383,-2380,-2378,-2375,-2373,-2371,-2368,-2366,-2364,-2362,-2359,-2357,-2355,-2353,-2351,-2349,
--2348,-2346,-2344,-2342,-2340,-2339,-2337,-2335,-2334,-2332,-2331,-2329,-2328,-2326,-2325,-2323,-2322,-2320,-2319,-2317,-2316,
--2314,-2313,-2312,-2310,-2309,-2307,-2306,-2304,-2303,-2301,-2300,-2298,-2297,-2295,-2293,-2292,-2290,-2288,-2287,-2285,-2283,
--2281,-2279,-2277,-2275,-2273,-2271,-2269,-2267,-2265,-2263,-2261,-2258,-2256,-2254,-2251,-2249,-2246,-2244,-2241,-2239,-2236,
--2234,-2231,-2228,-2226,-2223,-2220,-2218,-2215,-2212,-2209,-2207,-2204,-2201,-2198,-2196,-2193,-2190,-2188,-2185,-2182,-2180,
--2177,-2174,-2172,-2170,-2167,-2165,-2162,-2160,-2158,-2156,-2154,-2152,-2150,-2148,-2146,-2145,-2143,-2141,-2140,-2139,-2137,
--2136,-2135,-2134,-2133,-2133,-2132,-2131,-2131,-2131,-2130,-2130,-2130,-2130,-2130,-2131,-2131,-2132,-2132,-2133,-2134,-2135,
--2136,-2137,-2138,-2140,-2141,-2143,-2144,-2146,-2148,-2150,-2152,-2154,-2156,-2158,-2161,-2163,-2166,-2168,-2171,-2173,-2176,
--2179,-2182,-2185,-2188,-2191,-2194,-2197,-2200,-2203,-2206,-2209,-2212,-2216,-2219,-2222,-2225,-2229,-2232,-2235,-2239,-2242,
--2245,-2249,-2252,-2255,-2259,-2262,-2265,-2268,-2272,-2275,-2278,-2281,-2284,-2287,-2290,-2293,-2296,-2299,-2302,-2305,-2308,
--2311,-2314,-2316,-2319,-2322,-2324,-2327,-2330,-2332,-2334,-2337,-2339,-2341,-2344,-2346,-2348,-2350,-2352,-2354,-2356,-2358,
--2360,-2362,-2364,-2365,-2367,-2369,-2370,-2372,-2373,-2375,-2376,-2378,-2379,-2380,-2382,-2383,-2384,-2385,-2386,-2387,-2388,
--2390,-2391,-2392,-2393,-2394,-2395,-2395,-2396,-2397,-2398,-2399,-2400,-2401,-2402,-2403,-2404,-2405,-2406,-2406,-2407,-2408,
--2409,-2410,-2411,-2413,-2414,-2415,-2416,-2417,-2418,-2420,-2421,-2422,-2424,-2425,-2427,-2428,-2430,-2431,-2433,-2435,-2436,
--2438,-2440,-2442,-2444,-2446,-2448,-2451,-2453,-2455,-2457,-2460,-2462,-2465,-2468,-2470,-2473,-2476,-2478,-2481,-2484,-2487,
--2490,-2493,-2496,-2500,-2503,-2506,-2509,-2513,-2516,-2519,-2523,-2526,-2530,-2533,-2537,-2541,-2544,-2548,-2551,-2555,-2559,
--2563,-2566,-2570,-2574,-2578,-2581,-2585,-2589,-2593,-2596,-2600,-2604,-2608,-2612,-2615,-2619,-2623,-2627,-2631,-2634,-2638,
--2642,-2646,-2649,-2653,-2657,-2661,-2664,-2668,-2672,-2675,-2679,-2683,-2686,-2690,-2693,-2697,-2701,-2704,-2708,-2711,-2715,
--2718,-2722,-2726,-2729,-2733,-2736,-2740,-2743,-2746,-2750,-2753,-2757,-2760,-2764,-2767,-2771,-2774,-2777,-2781,-2784,-2788,
--2791,-2794,-2798,-2801,-2804,-2808,-2811,-2814,-2818,-2821,-2824,-2827,-2831,-2834,-2837,-2840,-2843,-2847,-2850,-2853,-2856,
--2859,-2862,-2865,-2868,-2871,-2875,-2878,-2881,-2884,-2886,-2889,-2892,-2895,-2898,-2901,-2904,-2907,-2909,-2912,-2915,-2918,
--2920,-2923,-2926,-2928,-2931,-2933,-2936,-2938,-2941,-2943,-2946,-2948,-2951,-2953,-2955,-2958,-2960,-2962,-2965,-2967,-2969,
--2971,-2974,-2976,-2978,-2980,-2982,-2984,-2986,-2988,-2990,-2992,-2994,-2996,-2998,-3000,-3002,-3004,-3006,-3008,-3010,-3012,
--3013,-3015,-3017,-3019,-3021,-3022,-3024,-3026,-3028,-3029,-3031,-3033,-3035,-3036,-3038,-3040,-3041,-3043,-3044,-3046,-3048,
--3049,-3051,-3053,-3054,-3056,-3057,-3059,-3060,-3062,-3064,-3065,-3067,-3068,-3070,-3071,-3073,-3074,-3076,-3077,-3079,-3080,
--3082,-3083,-3084,-3086,-3087,-3089,-3090,-3092,-3093,-3094,-3096,-3097,-3099,-3100,-3101,-3103,-3104,-3106,-3107,-3108,-3110,
--3111,-3112,-3113,-3115,-3116,-3117,-3119,-3120,-3121,-3122,-3124,-3125,-3126,-3127,-3129,-3130,-3131,-3132,-3133,-3134,-3136,
--3137,-3138,-3139,-3140,-3141,-3142,-3143,-3144,-3146,-3147,-3148,-3149,-3150,-3151,-3152,-3153,-3154,-3155,-3156,-3157,-3158,
--3159,-3160,-3160,-3161,-3162,-3163,-3164,-3165,-3166,-3167,-3168,-3168,-3169,-3170,-3171,-3172,-3172,-3173,-3174,-3175,-3175,
--3176,-3177,-3177,-3178,-3179,-3179,-3180,-3180,-3181,-3182,-3182,-3183,-3183,-3183,-3184,-3184,-3185,-3185,-3185,-3185,-3186,
--3186,-3186,-3186,-3186,-3186,-3186,-3186,-3186,-3186,-3186,-3185,-3185,-3185,-3184,-3184,-3183,-3183,-3182,-3181,-3180,-3180,
--3179,-3178,-3177,-3176,-3174,-3173,-3172,-3170,-3169,-3167,-3166,-3164,-3162,-3161,-3159,-3157,-3155,-3153,-3151,-3148,-3146,
--3144,-3141,-3139,-3136,-3134,-3131,-3128,-3125,-3123,-3120,-3117,-3114,-3111,-3107,-3104,-3101,-3098,-3094,-3091,-3088,-3084,
--3081,-3077,-3074,-3070,-3067,-3063,-3059,-3056,-3052,-3048,-3045,-3041,-3037,-3033,-3030,-3026,-3022,-3018,-3014,-3011,-3007,
--3003,-2999,-2995,-2991,-2988,-2984,-2980,-2976,-2972,-2969,-2965,-2961,-2957,-2954,-2950,-2946,-2943,-2939,-2935,-2932,-2928,
--2924,-2921,-2917,-2914,-2910,-2907,-2903,-2900,-2896,-2893,-2889,-2886,-2883,-2880,-2876,-2873,-2870,-2867,-2864,-2861,-2858,
--2855,-2852,-2850,-2847,-2844,-2842,-2839,-2836,-2834,-2832,-2829,-2827,-2825,-2823,-2821,-2819,-2818,-2816,-2814,-2813,-2811,
--2810,-2809,-2808,-2807,-2806,-2805,-2804,-2804,-2803,-2803,-2803,-2803,-2803,-2803,-2803,-2803,-2804,-2804,-2805,-2806,-2807,
--2808,-2809,-2810,-2811,-2813,-2814,-2816,-2818,-2820,-2822,-2824,-2826,-2828,-2831,-2833,-2836,-2838,-2841,-2844,-2847,-2849,
--2852,-2855,-2859,-2862,-2865,-2868,-2871,-2875,-2878,-2882,-2885,-2888,-2892,-2895,-2899,-2902,-2906,-2910,-2913,-2917,-2920,
--2924,-2927,-2930,-2934,-2937,-2941,-2944,-2947,-2951,-2954,-2957,-2960,-2963,-2966,-2969,-2972,-2975,-2978,-2980,-2983,-2986,
--2988,-2990,-2993,-2995,-2997,-2999,-3001,-3003,-3005,-3007,-3008,-3010,-3011,-3013,-3014,-3015,-3016,-3017,-3018,-3019,-3019,
--3020,-3020,-3021,-3021,-3021,-3021,-3021,-3021,-3020,-3020,-3020,-3019,-3018,-3018,-3017,-3016,-3015,-3013,-3012,-3011,-3009,
--3008,-3006,-3005,-3003,-3001,-2999,-2997,-2995,-2993,-2990,-2988,-2986,-2983,-2981,-2978,-2976,-2973,-2970,-2967,-2965,-2962,
--2959,-2956,-2953,-2950,-2947,-2944,-2941,-2938,-2935,-2932,-2929,-2926,-2923,-2920,-2917,-2914,-2911,-2908,-2905,-2902,-2899,
--2896,-2893,-2890,-2887,-2885,-2882,-2879,-2877,-2874,-2872,-2869,-2867,-2864,-2862,-2860,-2857,-2855,-2853,-2851,-2849,-2847,
--2845,-2843,-2842,-2840,-2838,-2837,-2835,-2834,-2832,-2831,-2830,-2829,-2827,-2826,-2825,-2824,-2823,-2822,-2821,-2820,-2820,
--2819,-2818,-2818,-2817,-2816,-2816,-2815,-2815,-2814,-2814,-2814,-2813,-2813,-2813,-2812,-2812,-2812,-2812,-2811,-2811,-2811,
--2811,-2811,-2811,-2811,-2811,-2811,-2810,-2810,-2810,-2810,-2810,-2810,-2810,-2810,-2810,-2810,-2809,-2809,-2809,-2809,-2809,
--2809,-2808,-2808,-2808,-2807,-2807,-2807,-2806,-2806,-2805,-2805,-2804,-2803,-2803,-2802,-2801,-2800,-2799,-2798,-2797,-2796,
--2795,-2794,-2793,-2791,-2790,-2788,-2787,-2785,-2784,-2782,-2780,-2778,-2776,-2774,-2772,-2770,-2768,-2766,-2763,-2761,-2758,
--2756,-2753,-2751,-2748,-2745,-2743,-2740,-2737,-2734,-2731,-2728,-2725,-2722,-2719,-2715,-2712,-2709,-2706,-2703,-2699,-2696,
--2693,-2689,-2686,-2683,-2680,-2676,-2673,-2670,-2666,-2663,-2660,-2657,-2654,-2651,-2647,-2644,-2641,-2638,-2636,-2633,-2630,
--2627,-2624,-2622,-2619,-2616,-2614,-2611,-2609,-2607,-2604,-2602,-2600,-2598,-2596,-2594,-2592,-2590,-2588,-2587,-2585,-2583,
--2582,-2580,-2579,-2578,-2576,-2575,-2574,-2573,-2572,-2571,-2570,-2569,-2568,-2567,-2567,-2566,-2565,-2565,-2564,-2564,-2563,
--2563,-2563,-2563,-2562,-2562,-2562,-2562,-2562,-2562,-2562,-2562,-2562,-2562,-2562,-2563,-2563,-2563,-2564,-2564,-2564,-2565,
--2565,-2566,-2566,-2567,-2568,-2568,-2569,-2570,-2571,-2572,-2572,-2573,-2574,-2575,-2576,-2577,-2578,-2579,-2580,-2581,-2582,
--2584,-2585,-2586,-2587,-2588,-2589,-2590,-2592,-2593,-2594,-2595,-2596,-2597,-2598,-2599,-2600,-2601,-2602,-2603,-2604,-2605,
--2606,-2606,-2607,-2608,-2608,-2609,-2609,-2610,-2610,-2610,-2610,-2610,-2610,-2610,-2610,-2609,-2609,-2608,-2608,-2607,-2606,
--2605,-2604,-2603,-2601,-2600,-2599,-2597,-2595,-2593,-2591,-2589,-2587,-2585,-2582,-2580,-2577,-2575,-2572,-2569,-2566,-2563,
--2560,-2556,-2553,-2550,-2546,-2543,-2539,-2536,-2532,-2528,-2525,-2521,-2517,-2513,-2509,-2505,-2502,-2498,-2494,-2490,-2486,
--2483,-2479,-2475,-2472,-2468,-2464,-2461,-2458,-2454,-2451,-2448,-2445,-2442,-2439,-2436,-2433,-2431,-2428,-2426,-2424,-2422,
--2420,-2418,-2416,-2415,-2413,-2412,-2411,-2410,-2409,-2408,-2408,-2407,-2407,-2407,-2407,-2407,-2407,-2407,-2408,-2408,-2409,
--2410,-2411,-2412,-2413,-2415,-2416,-2418,-2419,-2421,-2423,-2425,-2427,-2429,-2431,-2434,-2436,-2438,-2441,-2443,-2445,-2448,
--2451,-2453,-2456,-2458,-2461,-2464,-2466,-2469,-2471,-2474,-2476,-2479,-2481,-2484,-2486,-2488,-2491,-2493,-2495,-2497,-2499,
--2501,-2503,-2505,-2506,-2508,-2509,-2511,-2512,-2513,-2514,-2515,-2516,-2517,-2517,-2518,-2518,-2519,-2519,-2519,-2519,-2519,
--2518,-2518,-2517,-2517,-2516,-2515,-2514,-2513,-2512,-2511,-2509,-2508,-2506,-2505,-2503,-2501,-2499,-2497,-2495,-2493,-2491,
--2488,-2486,-2484,-2481,-2479,-2476,-2473,-2471,-2468,-2465,-2462,-2459,-2457,-2454,-2451,-2448,-2445,-2442,-2439,-2436,-2433,
--2430,-2427,-2424,-2489,-2487,-2485,-2483,-2481,-2479,-2477,-2476,-2474,-2472,-2470,-2468,-2466,-2464,-2462,-2460,-2459,-2457,
--2455,-2453,-2452,-2450,-2448,-2447,-2445,-2443,-2442,-2440,-2439,-2437,-2436,-2434,-2433,-2431,-2430,-2428,-2427,-2425,-2424,
--2423,-2421,-2420,-2419,-2417,-2416,-2415,-2413,-2412,-2411,-2409,-2408,-2407,-2406,-2404,-2403,-2402,-2400,-2399,-2398,-2396,
--2395,-2393,-2392,-2391,-2389,-2388,-2386,-2385,-2383,-2382,-2380,-2379,-2377,-2376,-2374,-2372,-2371,-2369,-2367,-2366,-2364,
--2362,-2360,-2359,-2357,-2355,-2353,-2351,-2349,-2347,-2345,-2344,-2342,-2340,-2338,-2336,-2334,-2332,-2330,-2328,-2326,-2324,
--2322,-2320,-2318,-2316,-2314,-2312,-2310,-2308,-2306,-2304,-2302,-2301,-2299,-2297,-2295,-2293,-2292,-2290,-2289,-2287,-2285,
--2284,-2283,-2281,-2280,-2279,-2277,-2276,-2275,-2274,-2273,-2272,-2271,-2271,-2270,-2269,-2269,-2268,-2268,-2267,-2267,-2267,
--2267,-2266,-2266,-2267,-2267,-2267,-2267,-2267,-2268,-2268,-2269,-2270,-2270,-2271,-2272,-2273,-2274,-2275,-2276,-2277,-2279,
--2280,-2281,-2283,-2284,-2286,-2288,-2289,-2291,-2293,-2295,-2297,-2299,-2301,-2303,-2305,-2307,-2309,-2311,-2314,-2316,-2318,
--2321,-2323,-2325,-2328,-2330,-2333,-2335,-2338,-2340,-2343,-2345,-2348,-2350,-2353,-2356,-2358,-2361,-2363,-2366,-2368,-2371,
--2374,-2376,-2379,-2381,-2384,-2386,-2389,-2391,-2393,-2396,-2398,-2401,-2403,-2405,-2408,-2410,-2412,-2414,-2416,-2419,-2421,
--2423,-2425,-2427,-2429,-2431,-2433,-2435,-2437,-2439,-2440,-2442,-2444,-2446,-2447,-2449,-2451,-2452,-2454,-2455,-2457,-2458,
--2460,-2461,-2463,-2464,-2466,-2467,-2468,-2469,-2471,-2472,-2473,-2475,-2476,-2477,-2478,-2479,-2481,-2482,-2483,-2484,-2485,
--2486,-2487,-2489,-2490,-2491,-2492,-2493,-2494,-2495,-2497,-2498,-2499,-2500,-2502,-2503,-2504,-2505,-2507,-2508,-2509,-2511,
--2512,-2513,-2515,-2516,-2518,-2519,-2521,-2523,-2524,-2526,-2528,-2529,-2531,-2533,-2535,-2537,-2539,-2540,-2542,-2544,-2547,
--2549,-2551,-2553,-2555,-2557,-2560,-2562,-2564,-2567,-2569,-2571,-2574,-2576,-2579,-2582,-2584,-2587,-2589,-2592,-2595,-2598,
--2600,-2603,-2606,-2609,-2612,-2615,-2617,-2620,-2623,-2626,-2629,-2632,-2635,-2638,-2641,-2644,-2647,-2650,-2654,-2657,-2660,
--2663,-2666,-2669,-2672,-2675,-2678,-2681,-2684,-2687,-2691,-2694,-2697,-2700,-2703,-2706,-2709,-2712,-2715,-2718,-2721,-2724,
--2727,-2730,-2733,-2736,-2739,-2742,-2745,-2748,-2751,-2754,-2757,-2760,-2763,-2765,-2768,-2771,-2774,-2777,-2780,-2782,-2785,
--2788,-2791,-2794,-2796,-2799,-2802,-2805,-2807,-2810,-2813,-2815,-2818,-2821,-2823,-2826,-2829,-2831,-2834,-2837,-2839,-2842,
--2844,-2847,-2849,-2852,-2855,-2857,-2860,-2862,-2865,-2867,-2870,-2872,-2874,-2877,-2879,-2882,-2884,-2887,-2889,-2891,-2894,
--2896,-2898,-2901,-2903,-2905,-2908,-2910,-2912,-2914,-2917,-2919,-2921,-2923,-2926,-2928,-2930,-2932,-2934,-2936,-2939,-2941,
--2943,-2945,-2947,-2949,-2951,-2953,-2955,-2957,-2959,-2961,-2963,-2965,-2967,-2969,-2971,-2973,-2975,-2977,-2979,-2981,-2983,
--2985,-2987,-2988,-2990,-2992,-2994,-2996,-2997,-2999,-3001,-3003,-3005,-3006,-3008,-3010,-3011,-3013,-3015,-3016,-3018,-3020,
--3021,-3023,-3025,-3026,-3028,-3029,-3031,-3033,-3034,-3036,-3037,-3039,-3040,-3042,-3043,-3045,-3046,-3048,-3049,-3050,-3052,
--3053,-3055,-3056,-3057,-3059,-3060,-3062,-3063,-3064,-3065,-3067,-3068,-3069,-3071,-3072,-3073,-3074,-3076,-3077,-3078,-3079,
--3080,-3081,-3083,-3084,-3085,-3086,-3087,-3088,-3089,-3090,-3092,-3093,-3094,-3095,-3096,-3097,-3098,-3099,-3100,-3101,-3102,
--3103,-3104,-3105,-3106,-3107,-3107,-3108,-3109,-3110,-3111,-3112,-3113,-3114,-3115,-3115,-3116,-3117,-3118,-3119,-3120,-3120,
--3121,-3122,-3123,-3123,-3124,-3125,-3126,-3126,-3127,-3128,-3128,-3129,-3130,-3130,-3131,-3132,-3132,-3133,-3133,-3134,-3134,
--3135,-3136,-3136,-3136,-3137,-3137,-3138,-3138,-3139,-3139,-3139,-3140,-3140,-3140,-3140,-3141,-3141,-3141,-3141,-3141,-3141,
--3141,-3141,-3141,-3141,-3141,-3141,-3141,-3141,-3141,-3140,-3140,-3140,-3139,-3139,-3138,-3138,-3137,-3137,-3136,-3136,-3135,
--3134,-3133,-3132,-3132,-3131,-3130,-3129,-3128,-3126,-3125,-3124,-3123,-3121,-3120,-3119,-3117,-3116,-3114,-3113,-3111,-3109,
--3107,-3106,-3104,-3102,-3100,-3098,-3096,-3094,-3092,-3090,-3088,-3085,-3083,-3081,-3078,-3076,-3074,-3071,-3069,-3066,-3064,
--3061,-3059,-3056,-3053,-3051,-3048,-3045,-3043,-3040,-3037,-3035,-3032,-3029,-3026,-3023,-3021,-3018,-3015,-3012,-3009,-3006,
--3003,-3001,-2998,-2995,-2992,-2989,-2986,-2984,-2981,-2978,-2975,-2972,-2970,-2967,-2964,-2961,-2959,-2956,-2953,-2951,-2948,
--2945,-2943,-2940,-2938,-2935,-2933,-2930,-2928,-2925,-2923,-2921,-2918,-2916,-2913,-2911,-2909,-2907,-2905,-2902,-2900,-2898,
--2896,-2894,-2892,-2890,-2888,-2886,-2884,-2882,-2881,-2879,-2877,-2876,-2874,-2872,-2871,-2869,-2868,-2866,-2865,-2864,-2862,
--2861,-2860,-2859,-2857,-2856,-2855,-2854,-2853,-2853,-2852,-2851,-2850,-2850,-2849,-2848,-2848,-2848,-2847,-2847,-2847,-2846,
--2846,-2846,-2846,-2846,-2846,-2846,-2847,-2847,-2847,-2848,-2848,-2849,-2849,-2850,-2850,-2851,-2852,-2853,-2854,-2855,-2856,
--2857,-2858,-2859,-2860,-2862,-2863,-2865,-2866,-2867,-2869,-2871,-2872,-2874,-2876,-2877,-2879,-2881,-2883,-2885,-2887,-2888,
--2890,-2892,-2894,-2896,-2898,-2900,-2903,-2905,-2907,-2909,-2911,-2913,-2915,-2917,-2919,-2922,-2924,-2926,-2928,-2930,-2932,
--2934,-2936,-2938,-2940,-2942,-2944,-2946,-2948,-2950,-2952,-2953,-2955,-2957,-2959,-2960,-2962,-2963,-2965,-2966,-2968,-2969,
--2971,-2972,-2973,-2975,-2976,-2977,-2978,-2979,-2980,-2981,-2982,-2983,-2983,-2984,-2985,-2985,-2986,-2986,-2987,-2987,-2987,
--2987,-2988,-2988,-2988,-2988,-2988,-2988,-2988,-2987,-2987,-2987,-2986,-2986,-2986,-2985,-2984,-2984,-2983,-2982,-2982,-2981,
--2980,-2979,-2978,-2977,-2976,-2975,-2974,-2973,-2971,-2970,-2969,-2968,-2966,-2965,-2964,-2962,-2961,-2959,-2958,-2956,-2955,
--2953,-2952,-2950,-2948,-2947,-2945,-2944,-2942,-2940,-2939,-2937,-2935,-2934,-2932,-2930,-2929,-2927,-2925,-2924,-2922,-2920,
--2919,-2917,-2915,-2914,-2912,-2911,-2909,-2908,-2906,-2905,-2903,-2902,-2900,-2899,-2897,-2896,-2895,-2893,-2892,-2891,-2889,
--2888,-2887,-2886,-2885,-2884,-2883,-2881,-2880,-2879,-2878,-2877,-2877,-2876,-2875,-2874,-2873,-2872,-2872,-2871,-2870,-2870,
--2869,-2868,-2868,-2867,-2867,-2866,-2865,-2865,-2865,-2864,-2864,-2863,-2863,-2862,-2862,-2862,-2861,-2861,-2861,-2860,-2860,
--2860,-2860,-2859,-2859,-2859,-2858,-2858,-2858,-2858,-2857,-2857,-2857,-2856,-2856,-2856,-2855,-2855,-2855,-2854,-2854,-2853,
--2853,-2852,-2852,-2851,-2851,-2850,-2849,-2849,-2848,-2847,-2846,-2845,-2845,-2844,-2843,-2842,-2841,-2839,-2838,-2837,-2836,
--2835,-2833,-2832,-2831,-2829,-2828,-2826,-2824,-2823,-2821,-2819,-2817,-2815,-2814,-2812,-2810,-2808,-2806,-2803,-2801,-2799,
--2797,-2794,-2792,-2790,-2787,-2785,-2782,-2780,-2777,-2775,-2772,-2770,-2767,-2764,-2762,-2759,-2756,-2753,-2751,-2748,-2745,
--2743,-2740,-2737,-2734,-2731,-2729,-2726,-2723,-2720,-2718,-2715,-2712,-2710,-2707,-2704,-2702,-2699,-2697,-2694,-2692,-2689,
--2687,-2684,-2682,-2680,-2677,-2675,-2673,-2671,-2669,-2666,-2664,-2662,-2661,-2659,-2657,-2655,-2653,-2652,-2650,-2648,-2647,
--2645,-2644,-2642,-2641,-2640,-2639,-2637,-2636,-2635,-2634,-2633,-2633,-2632,-2631,-2630,-2630,-2629,-2629,-2628,-2628,-2627,
--2627,-2627,-2626,-2626,-2626,-2626,-2626,-2626,-2626,-2627,-2627,-2627,-2627,-2628,-2628,-2628,-2629,-2629,-2630,-2631,-2631,
--2632,-2633,-2633,-2634,-2635,-2636,-2637,-2638,-2638,-2639,-2640,-2641,-2642,-2643,-2644,-2645,-2646,-2647,-2648,-2649,-2650,
--2651,-2652,-2653,-2654,-2655,-2656,-2657,-2657,-2658,-2659,-2660,-2661,-2661,-2662,-2662,-2663,-2663,-2664,-2664,-2664,-2665,
--2665,-2665,-2665,-2665,-2665,-2665,-2664,-2664,-2664,-2663,-2663,-2662,-2661,-2660,-2660,-2659,-2658,-2656,-2655,-2654,-2652,
--2651,-2649,-2648,-2646,-2644,-2642,-2640,-2638,-2636,-2634,-2632,-2629,-2627,-2624,-2622,-2619,-2616,-2614,-2611,-2608,-2605,
--2602,-2599,-2596,-2593,-2590,-2587,-2584,-2581,-2578,-2575,-2571,-2568,-2565,-2562,-2559,-2556,-2553,-2550,-2547,-2544,-2541,
--2538,-2535,-2532,-2529,-2526,-2524,-2521,-2519,-2516,-2514,-2511,-2509,-2507,-2505,-2503,-2501,-2499,-2497,-2495,-2494,-2492,
--2491,-2490,-2488,-2487,-2486,-2485,-2485,-2484,-2483,-2483,-2482,-2482,-2482,-2482,-2482,-2482,-2482,-2482,-2482,-2483,-2483,
--2484,-2485,-2485,-2486,-2487,-2488,-2489,-2490,-2491,-2492,-2493,-2495,-2496,-2497,-2499,-2500,-2502,-2503,-2505,-2506,-2508,
--2509,-2511,-2512,-2514,-2515,-2517,-2518,-2520,-2521,-2523,-2524,-2526,-2527,-2528,-2530,-2531,-2532,-2533,-2535,-2536,-2537,
--2538,-2538,-2539,-2540,-2541,-2541,-2542,-2543,-2543,-2543,-2544,-2544,-2544,-2544,-2544,-2544,-2544,-2544,-2543,-2543,-2543,
--2542,-2542,-2541,-2540,-2539,-2539,-2538,-2537,-2536,-2535,-2533,-2532,-2531,-2530,-2528,-2527,-2525,-2524,-2522,-2521,-2519,
--2517,-2516,-2514,-2512,-2510,-2508,-2507,-2505,-2503,-2501,-2499,-2497,-2495,-2493,-2491,-2489,-2583,-2582,-2581,-2580,-2579,
--2578,-2577,-2576,-2575,-2574,-2573,-2572,-2571,-2570,-2569,-2568,-2567,-2566,-2565,-2564,-2563,-2562,-2561,-2560,-2559,-2558,
--2557,-2556,-2555,-2554,-2553,-2552,-2551,-2550,-2549,-2548,-2547,-2546,-2545,-2544,-2543,-2542,-2542,-2541,-2540,-2539,-2538,
--2537,-2536,-2535,-2534,-2533,-2532,-2531,-2530,-2529,-2528,-2527,-2526,-2525,-2524,-2523,-2522,-2521,-2520,-2519,-2518,-2517,
--2516,-2515,-2514,-2513,-2512,-2511,-2510,-2508,-2507,-2506,-2505,-2504,-2503,-2501,-2500,-2499,-2498,-2497,-2495,-2494,-2493,
--2492,-2490,-2489,-2488,-2486,-2485,-2484,-2483,-2481,-2480,-2479,-2478,-2476,-2475,-2474,-2473,-2471,-2470,-2469,-2468,-2466,
--2465,-2464,-2463,-2462,-2461,-2460,-2458,-2457,-2456,-2455,-2454,-2453,-2452,-2452,-2451,-2450,-2449,-2448,-2447,-2447,-2446,
--2445,-2445,-2444,-2444,-2443,-2443,-2442,-2442,-2441,-2441,-2441,-2441,-2440,-2440,-2440,-2440,-2440,-2440,-2440,-2440,-2440,
--2441,-2441,-2441,-2441,-2442,-2442,-2443,-2443,-2444,-2444,-2445,-2446,-2446,-2447,-2448,-2449,-2450,-2450,-2451,-2452,-2453,
--2454,-2455,-2457,-2458,-2459,-2460,-2461,-2463,-2464,-2465,-2466,-2468,-2469,-2471,-2472,-2473,-2475,-2476,-2478,-2479,-2481,
--2482,-2484,-2486,-2487,-2489,-2490,-2492,-2493,-2495,-2497,-2498,-2500,-2501,-2503,-2505,-2506,-2508,-2510,-2511,-2513,-2514,
--2516,-2518,-2519,-2521,-2522,-2524,-2525,-2527,-2528,-2530,-2531,-2533,-2534,-2536,-2537,-2539,-2540,-2542,-2543,-2544,-2546,
--2547,-2548,-2550,-2551,-2552,-2554,-2555,-2556,-2558,-2559,-2560,-2561,-2562,-2564,-2565,-2566,-2567,-2568,-2570,-2571,-2572,
--2573,-2574,-2575,-2576,-2577,-2579,-2580,-2581,-2582,-2583,-2584,-2585,-2586,-2587,-2589,-2590,-2591,-2592,-2593,-2594,-2595,
--2596,-2598,-2599,-2600,-2601,-2602,-2603,-2605,-2606,-2607,-2608,-2610,-2611,-2612,-2614,-2615,-2616,-2618,-2619,-2621,-2622,
--2623,-2625,-2626,-2628,-2629,-2631,-2633,-2634,-2636,-2637,-2639,-2641,-2642,-2644,-2646,-2648,-2649,-2651,-2653,-2655,-2657,
--2659,-2661,-2663,-2665,-2667,-2669,-2671,-2673,-2675,-2677,-2679,-2681,-2683,-2685,-2687,-2690,-2692,-2694,-2696,-2698,-2701,
--2703,-2705,-2707,-2710,-2712,-2714,-2717,-2719,-2721,-2724,-2726,-2728,-2731,-2733,-2735,-2738,-2740,-2743,-2745,-2747,-2750,
--2752,-2754,-2757,-2759,-2762,-2764,-2766,-2769,-2771,-2774,-2776,-2778,-2781,-2783,-2785,-2788,-2790,-2792,-2795,-2797,-2799,
--2802,-2804,-2806,-2808,-2811,-2813,-2815,-2818,-2820,-2822,-2824,-2827,-2829,-2831,-2833,-2835,-2838,-2840,-2842,-2844,-2846,
--2848,-2850,-2853,-2855,-2857,-2859,-2861,-2863,-2865,-2867,-2869,-2871,-2873,-2875,-2877,-2879,-2881,-2884,-2886,-2887,-2889,
--2891,-2893,-2895,-2897,-2899,-2901,-2903,-2905,-2907,-2909,-2911,-2913,-2915,-2917,-2918,-2920,-2922,-2924,-2926,-2928,-2930,
--2931,-2933,-2935,-2937,-2939,-2941,-2942,-2944,-2946,-2948,-2950,-2951,-2953,-2955,-2957,-2958,-2960,-2962,-2964,-2965,-2967,
--2969,-2971,-2972,-2974,-2976,-2977,-2979,-2981,-2982,-2984,-2986,-2987,-2989,-2991,-2992,-2994,-2996,-2997,-2999,-3000,-3002,
--3004,-3005,-3007,-3008,-3010,-3011,-3013,-3015,-3016,-3018,-3019,-3021,-3022,-3024,-3025,-3027,-3028,-3030,-3031,-3032,-3034,
--3035,-3037,-3038,-3040,-3041,-3042,-3044,-3045,-3046,-3048,-3049,-3050,-3052,-3053,-3054,-3056,-3057,-3058,-3059,-3061,-3062,
--3063,-3064,-3066,-3067,-3068,-3069,-3070,-3071,-3073,-3074,-3075,-3076,-3077,-3078,-3079,-3080,-3081,-3083,-3084,-3085,-3086,
--3087,-3088,-3089,-3090,-3091,-3092,-3093,-3094,-3095,-3095,-3096,-3097,-3098,-3099,-3100,-3101,-3102,-3103,-3103,-3104,-3105,
--3106,-3107,-3107,-3108,-3109,-3110,-3111,-3111,-3112,-3113,-3113,-3114,-3115,-3115,-3116,-3117,-3117,-3118,-3119,-3119,-3120,
--3120,-3121,-3121,-3122,-3122,-3123,-3123,-3124,-3124,-3125,-3125,-3125,-3126,-3126,-3126,-3127,-3127,-3127,-3127,-3128,-3128,
--3128,-3128,-3128,-3128,-3128,-3128,-3128,-3128,-3128,-3128,-3128,-3128,-3128,-3128,-3128,-3127,-3127,-3127,-3127,-3126,-3126,
--3125,-3125,-3125,-3124,-3124,-3123,-3122,-3122,-3121,-3120,-3120,-3119,-3118,-3117,-3116,-3116,-3115,-3114,-3113,-3112,-3111,
--3110,-3109,-3107,-3106,-3105,-3104,-3103,-3101,-3100,-3099,-3097,-3096,-3095,-3093,-3092,-3090,-3089,-3087,-3085,-3084,-3082,
--3081,-3079,-3077,-3076,-3074,-3072,-3070,-3069,-3067,-3065,-3063,-3062,-3060,-3058,-3056,-3054,-3052,-3050,-3049,-3047,-3045,
--3043,-3041,-3039,-3037,-3035,-3034,-3032,-3030,-3028,-3026,-3024,-3022,-3020,-3019,-3017,-3015,-3013,-3011,-3010,-3008,-3006,
--3004,-3002,-3001,-2999,-2997,-2996,-2994,-2992,-2991,-2989,-2987,-2986,-2984,-2983,-2981,-2980,-2978,-2977,-2975,-2974,-2972,
--2971,-2970,-2968,-2967,-2966,-2964,-2963,-2962,-2961,-2959,-2958,-2957,-2956,-2955,-2954,-2953,-2951,-2950,-2949,-2948,-2947,
--2946,-2946,-2945,-2944,-2943,-2942,-2941,-2940,-2940,-2939,-2938,-2937,-2937,-2936,-2935,-2935,-2934,-2933,-2933,-2932,-2932,
--2931,-2931,-2930,-2930,-2929,-2929,-2929,-2928,-2928,-2928,-2927,-2927,-2927,-2927,-2926,-2926,-2926,-2926,-2926,-2926,-2926,
--2926,-2926,-2926,-2926,-2926,-2926,-2926,-2926,-2926,-2926,-2927,-2927,-2927,-2927,-2928,-2928,-2928,-2928,-2929,-2929,-2930,
--2930,-2930,-2931,-2931,-2932,-2932,-2933,-2934,-2934,-2935,-2935,-2936,-2937,-2937,-2938,-2939,-2939,-2940,-2941,-2942,-2942,
--2943,-2944,-2945,-2946,-2946,-2947,-2948,-2949,-2950,-2951,-2951,-2952,-2953,-2954,-2955,-2956,-2957,-2958,-2959,-2960,-2960,
--2961,-2962,-2963,-2964,-2965,-2966,-2967,-2968,-2969,-2969,-2970,-2971,-2972,-2973,-2974,-2975,-2975,-2976,-2977,-2978,-2979,
--2979,-2980,-2981,-2982,-2982,-2983,-2984,-2984,-2985,-2986,-2986,-2987,-2987,-2988,-2989,-2989,-2990,-2990,-2990,-2991,-2991,
--2992,-2992,-2992,-2993,-2993,-2993,-2994,-2994,-2994,-2994,-2994,-2994,-2994,-2995,-2995,-2995,-2995,-2995,-2995,-2994,-2994,
--2994,-2994,-2994,-2994,-2994,-2993,-2993,-2993,-2992,-2992,-2992,-2991,-2991,-2990,-2990,-2989,-2989,-2988,-2988,-2987,-2987,
--2986,-2986,-2985,-2984,-2984,-2983,-2982,-2981,-2981,-2980,-2979,-2978,-2978,-2977,-2976,-2975,-2974,-2974,-2973,-2972,-2971,
--2970,-2969,-2968,-2967,-2967,-2966,-2965,-2964,-2963,-2962,-2961,-2960,-2959,-2958,-2958,-2957,-2956,-2955,-2954,-2953,-2952,
--2951,-2951,-2950,-2949,-2948,-2947,-2946,-2946,-2945,-2944,-2943,-2942,-2942,-2941,-2940,-2939,-2939,-2938,-2937,-2937,-2936,
--2935,-2935,-2934,-2933,-2933,-2932,-2931,-2931,-2930,-2930,-2929,-2928,-2928,-2927,-2927,-2926,-2926,-2925,-2924,-2924,-2923,
--2923,-2922,-2922,-2921,-2921,-2920,-2920,-2919,-2918,-2918,-2917,-2917,-2916,-2915,-2915,-2914,-2914,-2913,-2912,-2911,-2911,
--2910,-2909,-2908,-2908,-2907,-2906,-2905,-2904,-2903,-2902,-2901,-2900,-2899,-2898,-2897,-2896,-2895,-2894,-2892,-2891,-2890,
--2889,-2887,-2886,-2884,-2883,-2881,-2880,-2878,-2877,-2875,-2873,-2872,-2870,-2868,-2866,-2865,-2863,-2861,-2859,-2857,-2855,
--2853,-2851,-2849,-2847,-2845,-2842,-2840,-2838,-2836,-2834,-2831,-2829,-2827,-2824,-2822,-2820,-2817,-2815,-2813,-2810,-2808,
--2805,-2803,-2801,-2798,-2796,-2793,-2791,-2789,-2786,-2784,-2781,-2779,-2777,-2774,-2772,-2770,-2767,-2765,-2763,-2761,-2758,
--2756,-2754,-2752,-2750,-2748,-2746,-2744,-2742,-2740,-2738,-2736,-2734,-2732,-2731,-2729,-2727,-2726,-2724,-2723,-2721,-2720,
--2718,-2717,-2716,-2715,-2713,-2712,-2711,-2710,-2709,-2708,-2707,-2707,-2706,-2705,-2704,-2704,-2703,-2703,-2702,-2702,-2702,
--2701,-2701,-2701,-2701,-2701,-2701,-2701,-2701,-2701,-2701,-2701,-2701,-2702,-2702,-2702,-2703,-2703,-2704,-2704,-2705,-2705,
--2706,-2706,-2707,-2708,-2708,-2709,-2710,-2710,-2711,-2712,-2713,-2713,-2714,-2715,-2716,-2716,-2717,-2718,-2719,-2719,-2720,
--2721,-2722,-2722,-2723,-2724,-2724,-2725,-2725,-2726,-2726,-2727,-2727,-2728,-2728,-2728,-2729,-2729,-2729,-2729,-2729,-2729,
--2729,-2729,-2729,-2729,-2729,-2729,-2728,-2728,-2728,-2727,-2727,-2726,-2725,-2725,-2724,-2723,-2722,-2721,-2720,-2719,-2718,
--2717,-2716,-2715,-2713,-2712,-2711,-2709,-2708,-2706,-2705,-2703,-2701,-2700,-2698,-2696,-2694,-2693,-2691,-2689,-2687,-2685,
--2683,-2681,-2679,-2677,-2675,-2673,-2671,-2669,-2667,-2665,-2663,-2661,-2658,-2656,-2654,-2652,-2650,-2648,-2646,-2644,-2643,
--2641,-2639,-2637,-2635,-2633,-2632,-2630,-2628,-2626,-2625,-2623,-2622,-2620,-2619,-2618,-2616,-2615,-2614,-2612,-2611,-2610,
--2609,-2608,-2607,-2606,-2606,-2605,-2604,-2603,-2603,-2602,-2602,-2601,-2601,-2600,-2600,-2600,-2599,-2599,-2599,-2599,-2599,
--2599,-2599,-2599,-2599,-2599,-2599,-2599,-2599,-2600,-2600,-2600,-2600,-2601,-2601,-2601,-2602,-2602,-2602,-2603,-2603,-2603,
--2604,-2604,-2605,-2605,-2605,-2606,-2606,-2607,-2607,-2607,-2608,-2608,-2608,-2609,-2609,-2609,-2609,-2610,-2610,-2610,-2610,
--2610,-2610,-2610,-2610,-2610,-2610,-2610,-2610,-2610,-2610,-2610,-2610,-2609,-2609,-2609,-2609,-2608,-2608,-2607,-2607,-2607,
--2606,-2606,-2605,-2604,-2604,-2603,-2603,-2602,-2601,-2600,-2600,-2599,-2598,-2597,-2596,-2596,-2595,-2594,-2593,-2592,-2591,
--2590,-2589,-2588,-2587,-2586,-2585,-2584,-2583,-2658,-2657,-2657,-2656,-2655,-2655,-2654,-2654,-2653,-2653,-2652,-2651,-2651,
--2650,-2650,-2649,-2649,-2648,-2648,-2647,-2646,-2646,-2645,-2645,-2644,-2644,-2643,-2643,-2642,-2642,-2641,-2641,-2640,-2639,
--2639,-2638,-2638,-2637,-2637,-2636,-2636,-2635,-2635,-2634,-2634,-2633,-2633,-2632,-2632,-2631,-2631,-2630,-2630,-2629,-2629,
--2628,-2628,-2627,-2627,-2626,-2626,-2625,-2625,-2624,-2623,-2623,-2622,-2622,-2621,-2621,-2620,-2620,-2619,-2619,-2618,-2617,
--2617,-2616,-2616,-2615,-2615,-2614,-2613,-2613,-2612,-2612,-2611,-2611,-2610,-2609,-2609,-2608,-2608,-2607,-2607,-2606,-2605,
--2605,-2604,-2604,-2603,-2603,-2602,-2601,-2601,-2600,-2600,-2599,-2599,-2598,-2598,-2597,-2597,-2596,-2596,-2596,-2595,-2595,
--2594,-2594,-2593,-2593,-2593,-2592,-2592,-2592,-2591,-2591,-2591,-2591,-2590,-2590,-2590,-2590,-2589,-2589,-2589,-2589,-2589,
--2589,-2589,-2589,-2589,-2589,-2589,-2589,-2589,-2589,-2589,-2589,-2589,-2589,-2590,-2590,-2590,-2590,-2591,-2591,-2591,-2591,
--2592,-2592,-2592,-2593,-2593,-2594,-2594,-2595,-2595,-2596,-2596,-2597,-2597,-2598,-2599,-2599,-2600,-2600,-2601,-2602,-2602,
--2603,-2604,-2605,-2605,-2606,-2607,-2608,-2608,-2609,-2610,-2611,-2612,-2613,-2613,-2614,-2615,-2616,-2617,-2618,-2619,-2619,
--2620,-2621,-2622,-2623,-2624,-2625,-2626,-2627,-2628,-2629,-2629,-2630,-2631,-2632,-2633,-2634,-2635,-2636,-2637,-2638,-2639,
--2640,-2640,-2641,-2642,-2643,-2644,-2645,-2646,-2647,-2647,-2648,-2649,-2650,-2651,-2652,-2653,-2653,-2654,-2655,-2656,-2657,
--2658,-2658,-2659,-2660,-2661,-2662,-2663,-2663,-2664,-2665,-2666,-2667,-2667,-2668,-2669,-2670,-2671,-2671,-2672,-2673,-2674,
--2675,-2675,-2676,-2677,-2678,-2679,-2679,-2680,-2681,-2682,-2683,-2684,-2684,-2685,-2686,-2687,-2688,-2689,-2690,-2690,-2691,
--2692,-2693,-2694,-2695,-2696,-2697,-2698,-2699,-2700,-2701,-2702,-2703,-2704,-2705,-2706,-2707,-2708,-2709,-2710,-2711,-2713,
--2714,-2715,-2716,-2717,-2718,-2720,-2721,-2722,-2723,-2724,-2726,-2727,-2728,-2730,-2731,-2732,-2734,-2735,-2736,-2738,-2739,
--2740,-2742,-2743,-2745,-2746,-2748,-2749,-2751,-2752,-2754,-2755,-2757,-2758,-2760,-2761,-2763,-2765,-2766,-2768,-2769,-2771,
--2773,-2774,-2776,-2777,-2779,-2781,-2782,-2784,-2786,-2787,-2789,-2791,-2793,-2794,-2796,-2798,-2799,-2801,-2803,-2804,-2806,
--2808,-2810,-2811,-2813,-2815,-2817,-2818,-2820,-2822,-2823,-2825,-2827,-2829,-2830,-2832,-2834,-2836,-2837,-2839,-2841,-2842,
--2844,-2846,-2848,-2849,-2851,-2853,-2854,-2856,-2858,-2860,-2861,-2863,-2865,-2866,-2868,-2870,-2871,-2873,-2875,-2876,-2878,
--2880,-2881,-2883,-2885,-2886,-2888,-2890,-2891,-2893,-2895,-2896,-2898,-2899,-2901,-2903,-2904,-2906,-2907,-2909,-2911,-2912,
--2914,-2915,-2917,-2918,-2920,-2922,-2923,-2925,-2926,-2928,-2929,-2931,-2932,-2934,-2936,-2937,-2939,-2940,-2942,-2943,-2945,
--2946,-2948,-2949,-2951,-2952,-2954,-2955,-2957,-2958,-2960,-2961,-2963,-2964,-2965,-2967,-2968,-2970,-2971,-2973,-2974,-2976,
--2977,-2978,-2980,-2981,-2983,-2984,-2985,-2987,-2988,-2990,-2991,-2992,-2994,-2995,-2997,-2998,-2999,-3001,-3002,-3003,-3005,
--3006,-3007,-3009,-3010,-3011,-3013,-3014,-3015,-3016,-3018,-3019,-3020,-3022,-3023,-3024,-3025,-3026,-3028,-3029,-3030,-3031,
--3033,-3034,-3035,-3036,-3037,-3038,-3040,-3041,-3042,-3043,-3044,-3045,-3046,-3048,-3049,-3050,-3051,-3052,-3053,-3054,-3055,
--3056,-3057,-3058,-3059,-3060,-3061,-3062,-3063,-3064,-3065,-3066,-3067,-3068,-3069,-3070,-3071,-3072,-3073,-3074,-3074,-3075,
--3076,-3077,-3078,-3079,-3079,-3080,-3081,-3082,-3083,-3083,-3084,-3085,-3086,-3086,-3087,-3088,-3089,-3089,-3090,-3091,-3091,
--3092,-3092,-3093,-3094,-3094,-3095,-3095,-3096,-3096,-3097,-3097,-3098,-3098,-3099,-3099,-3100,-3100,-3100,-3101,-3101,-3102,
--3102,-3102,-3102,-3103,-3103,-3103,-3103,-3104,-3104,-3104,-3104,-3104,-3104,-3105,-3105,-3105,-3105,-3105,-3105,-3105,-3105,
--3105,-3105,-3104,-3104,-3104,-3104,-3104,-3104,-3103,-3103,-3103,-3103,-3102,-3102,-3102,-3101,-3101,-3100,-3100,-3099,-3099,
--3098,-3098,-3097,-3097,-3096,-3096,-3095,-3094,-3094,-3093,-3092,-3092,-3091,-3090,-3089,-3088,-3088,-3087,-3086,-3085,-3084,
--3083,-3082,-3081,-3080,-3079,-3078,-3078,-3076,-3075,-3074,-3073,-3072,-3071,-3070,-3069,-3068,-3067,-3066,-3065,-3063,-3062,
--3061,-3060,-3059,-3058,-3057,-3055,-3054,-3053,-3052,-3051,-3049,-3048,-3047,-3046,-3045,-3043,-3042,-3041,-3040,-3039,-3038,
--3036,-3035,-3034,-3033,-3032,-3030,-3029,-3028,-3027,-3026,-3025,-3024,-3023,-3021,-3020,-3019,-3018,-3017,-3016,-3015,-3014,
--3013,-3012,-3011,-3010,-3009,-3008,-3007,-3006,-3005,-3004,-3003,-3002,-3001,-3000,-2999,-2999,-2998,-2997,-2996,-2995,-2994,
--2994,-2993,-2992,-2991,-2990,-2990,-2989,-2988,-2988,-2987,-2986,-2985,-2985,-2984,-2983,-2983,-2982,-2981,-2981,-2980,-2980,
--2979,-2978,-2978,-2977,-2977,-2976,-2976,-2975,-2975,-2974,-2974,-2973,-2973,-2972,-2972,-2971,-2971,-2970,-2970,-2970,-2969,
--2969,-2968,-2968,-2968,-2967,-2967,-2967,-2966,-2966,-2966,-2965,-2965,-2965,-2964,-2964,-2964,-2964,-2963,-2963,-2963,-2963,
--2963,-2962,-2962,-2962,-2962,-2962,-2962,-2962,-2961,-2961,-2961,-2961,-2961,-2961,-2961,-2961,-2961,-2961,-2961,-2961,-2961,
--2961,-2961,-2961,-2961,-2961,-2962,-2962,-2962,-2962,-2962,-2962,-2962,-2963,-2963,-2963,-2963,-2964,-2964,-2964,-2964,-2965,
--2965,-2965,-2966,-2966,-2966,-2967,-2967,-2968,-2968,-2968,-2969,-2969,-2970,-2970,-2971,-2971,-2972,-2972,-2973,-2973,-2974,
--2974,-2975,-2975,-2976,-2976,-2977,-2978,-2978,-2979,-2979,-2980,-2980,-2981,-2982,-2982,-2983,-2983,-2984,-2985,-2985,-2986,
--2986,-2987,-2988,-2988,-2989,-2989,-2990,-2991,-2991,-2992,-2992,-2993,-2994,-2994,-2995,-2995,-2996,-2996,-2997,-2997,-2998,
--2998,-2999,-2999,-3000,-3000,-3001,-3001,-3001,-3002,-3002,-3002,-3003,-3003,-3003,-3004,-3004,-3004,-3005,-3005,-3005,-3005,
--3005,-3006,-3006,-3006,-3006,-3006,-3006,-3006,-3006,-3007,-3007,-3007,-3007,-3007,-3006,-3006,-3006,-3006,-3006,-3006,-3006,
--3006,-3006,-3005,-3005,-3005,-3005,-3005,-3004,-3004,-3004,-3003,-3003,-3003,-3002,-3002,-3002,-3001,-3001,-3001,-3000,-3000,
--2999,-2999,-2998,-2998,-2997,-2997,-2997,-2996,-2996,-2995,-2995,-2994,-2994,-2993,-2992,-2992,-2991,-2991,-2990,-2990,-2989,
--2989,-2988,-2988,-2987,-2987,-2986,-2985,-2985,-2984,-2984,-2983,-2983,-2982,-2981,-2981,-2980,-2980,-2979,-2979,-2978,-2977,
--2977,-2976,-2976,-2975,-2975,-2974,-2973,-2973,-2972,-2972,-2971,-2971,-2970,-2969,-2969,-2968,-2968,-2967,-2966,-2966,-2965,
--2964,-2964,-2963,-2962,-2962,-2961,-2960,-2960,-2959,-2958,-2957,-2957,-2956,-2955,-2954,-2954,-2953,-2952,-2951,-2950,-2949,
--2948,-2947,-2946,-2945,-2944,-2943,-2942,-2941,-2940,-2939,-2938,-2937,-2936,-2935,-2933,-2932,-2931,-2930,-2928,-2927,-2926,
--2924,-2923,-2921,-2920,-2918,-2917,-2915,-2914,-2912,-2911,-2909,-2907,-2906,-2904,-2902,-2901,-2899,-2897,-2895,-2894,-2892,
--2890,-2888,-2886,-2884,-2882,-2880,-2878,-2876,-2874,-2872,-2870,-2868,-2866,-2864,-2862,-2860,-2858,-2856,-2854,-2852,-2850,
--2848,-2846,-2844,-2842,-2840,-2838,-2835,-2833,-2831,-2829,-2827,-2825,-2823,-2821,-2819,-2817,-2815,-2814,-2812,-2810,-2808,
--2806,-2804,-2802,-2801,-2799,-2797,-2795,-2794,-2792,-2791,-2789,-2787,-2786,-2784,-2783,-2782,-2780,-2779,-2778,-2776,-2775,
--2774,-2773,-2772,-2771,-2769,-2768,-2768,-2767,-2766,-2765,-2764,-2763,-2763,-2762,-2761,-2761,-2760,-2760,-2759,-2759,-2758,
--2758,-2758,-2757,-2757,-2757,-2757,-2756,-2756,-2756,-2756,-2756,-2756,-2756,-2756,-2756,-2756,-2757,-2757,-2757,-2757,-2757,
--2758,-2758,-2758,-2758,-2759,-2759,-2760,-2760,-2760,-2761,-2761,-2761,-2762,-2762,-2763,-2763,-2764,-2764,-2764,-2765,-2765,
--2766,-2766,-2767,-2767,-2767,-2768,-2768,-2768,-2769,-2769,-2769,-2770,-2770,-2770,-2770,-2771,-2771,-2771,-2771,-2771,-2771,
--2772,-2772,-2772,-2772,-2772,-2772,-2772,-2771,-2771,-2771,-2771,-2771,-2770,-2770,-2770,-2770,-2769,-2769,-2768,-2768,-2768,
--2767,-2767,-2766,-2765,-2765,-2764,-2764,-2763,-2762,-2761,-2761,-2760,-2759,-2758,-2758,-2757,-2756,-2755,-2754,-2753,-2752,
--2751,-2750,-2749,-2748,-2747,-2746,-2745,-2744,-2743,-2742,-2741,-2740,-2739,-2738,-2737,-2736,-2735,-2734,-2733,-2732,-2731,
--2730,-2729,-2728,-2727,-2726,-2725,-2724,-2723,-2722,-2721,-2720,-2719,-2718,-2717,-2716,-2715,-2714,-2713,-2713,-2712,-2711,
--2710,-2709,-2709,-2708,-2707,-2706,-2706,-2705,-2704,-2703,-2703,-2702,-2701,-2701,-2700,-2700,-2699,-2698,-2698,-2697,-2697,
--2696,-2696,-2695,-2695,-2694,-2694,-2693,-2693,-2692,-2692,-2691,-2691,-2691,-2690,-2690,-2689,-2689,-2689,-2688,-2688,-2687,
--2687,-2687,-2686,-2686,-2686,-2685,-2685,-2684,-2684,-2684,-2683,-2683,-2682,-2682,-2682,-2681,-2681,-2680,-2680,-2680,-2679,
--2679,-2678,-2678,-2678,-2677,-2677,-2676,-2676,-2675,-2675,-2674,-2674,-2673,-2673,-2672,-2672,-2671,-2671,-2670,-2670,-2669,
--2669,-2668,-2668,-2667,-2667,-2666,-2666,-2665,-2664,-2664,-2663,-2663,-2662,-2662,-2661,-2661,-2660,-2659,-2659,-2658,-2658,
--2708,-2708,-2708,-2707,-2707,-2706,-2706,-2705,-2705,-2705,-2704,-2704,-2704,-2703,-2703,-2702,-2702,-2702,-2701,-2701,-2701,
--2700,-2700,-2700,-2699,-2699,-2699,-2699,-2698,-2698,-2698,-2697,-2697,-2697,-2697,-2696,-2696,-2696,-2696,-2695,-2695,-2695,
--2695,-2695,-2694,-2694,-2694,-2694,-2694,-2693,-2693,-2693,-2693,-2693,-2692,-2692,-2692,-2692,-2692,-2692,-2692,-2691,-2691,
--2691,-2691,-2691,-2691,-2691,-2691,-2690,-2690,-2690,-2690,-2690,-2690,-2690,-2690,-2690,-2690,-2689,-2689,-2689,-2689,-2689,
+-10374,-10384,-10382,-10373,-10363,-10354,-10340,-10317,-10284,-10247,-10211,-10174,-10132,-10079,-10009,-9924,-9833,-9745,-9655,-9547,-9414,
+-9265,-9122,-8993,-8871,-8744,-8609,-8475,-8356,-8255,-8155,-8025,-7855,-7666,-7492,-7343,-7193,-7020,-6829,-6647,-6492,-6357,
+-6220,-6076,-5941,-5832,-5743,-5646,-5518,-5370,-5233,-5132,-5059,-4985,-4878,-4735,-4584,-4470,-4401,-4344,-4258,-4140,-4013,
+-3887,-3745,-3574,-3387,-3207,-3043,-2898,-2782,-2703,-2637,-2537,-2359,-2102,-1804,-1517,-1264,-1045,-863,-740,-688,-677,
+-656,-593,-498,-393,-287,-185,-95,-16,65,164,273,377,472,565,659,755,855,964,1074,1171,1252,
+1333,1429,1541,1656,1767,1876,1984,2084,2166,2235,2307,2389,2475,2560,2649,2745,2837,2917,2999,3106,3231,
+3344,3432,3516,3613,3716,3807,3890,3974,4054,4125,4192,4270,4372,4514,4713,4956,5182,5332,5408,5462,5535,
+5620,5690,5733,5758,5783,5810,5817,5779,5708,5643,5592,5513,5388,5277,5262,5342,5446,5536,5640,5768,5871,
+5905,5892,5886,5899,5916,5938,5980,6042,6114,6199,6299,6407,6529,6698,6901,7040,7004,6795,6509,6214,5909,
+5626,5494,5618,5947,6316,6609,6826,6988,7062,7022,6930,6899,6980,7119,7235,7309,7362,7401,7411,7393,7383,
+7402,7432,7442,7433,7428,7430,7416,7371,7312,7265,7237,7214,7186,7158,7139,7129,7120,7108,7097,7086,7069,
+7047,7027,7019,7016,7009,6995,6983,6979,6973,6962,6947,6932,6925,6929,6943,6955,6954,6945,6943,6941,6923,
+6889,6859,6838,6812,6773,6738,6716,6694,6664,6644,6638,6622,6588,6562,6562,6561,6534,6510,6518,6530,6506,
+6469,6455,6415,6277,6100,6055,6195,6356,6346,6174,5997,5900,5839,5765,5700,5668,5641,5601,5576,5587,5614,
+5626,5629,5635,5635,5624,5618,5633,5651,5648,5627,5603,5573,5528,5485,5467,5467,5453,5407,5342,5280,5230,
+5190,5155,5119,5078,5030,4972,4899,4812,4732,4676,4642,4615,4585,4553,4518,4476,4425,4371,4316,4261,4209,
+4164,4125,4084,4041,4000,3966,3939,3912,3881,3844,3807,3776,3747,3706,3647,3581,3522,3469,3424,3389,3356,
+3309,3240,3169,3118,3088,3070,3068,3083,3091,3059,2988,2908,2838,2773,2718,2703,2749,2816,2834,2773,2671,
+2591,2568,2584,2588,2543,2454,2369,2331,2334,2331,2286,2212,2150,2122,2121,2121,2108,2081,2051,2026,2007,
+1984,1952,1924,1914,1920,1924,1918,1907,1903,1903,1897,1885,1878,1877,1869,1842,1803,1772,1759,1758,1757,
+1750,1736,1721,1704,1680,1651,1619,1591,1568,1550,1540,1536,1531,1519,1501,1479,1452,1421,1396,1385,1385,
+1382,1378,1385,1410,1434,1441,1432,1417,1406,1397,1393,1398,1404,1404,1399,1401,1410,1419,1420,1418,1422,
+1435,1463,1500,1532,1542,1529,1515,1525,1554,1576,1573,1552,1534,1532,1541,1555,1574,1595,1617,1634,1652,
+1673,1694,1706,1716,1735,1763,1789,1808,1836,1877,1905,1878,1796,1705,1652,1637,1630,1609,1580,1557,1539,
+1514,1478,1440,1410,1391,1381,1378,1380,1385,1388,1386,1378,1364,1342,1315,1288,1259,1227,1191,1155,1123,
+1097,1074,1053,1033,1010,983,956,932,911,889,861,829,795,764,739,717,695,669,638,605,572,
+537,501,467,434,400,363,324,283,240,194,147,102,62,28,-3,-34,-68,-103,-140,-176,-213,
+-251,-288,-325,-364,-404,-446,-488,-528,-568,-610,-655,-703,-751,-797,-841,-882,-916,-947,-977,-1011,-1050,
+-1088,-1123,-1151,-1174,-1198,-1228,-1262,-1297,-1332,-1366,-1401,-1435,-1466,-1499,-1534,-1566,-1595,-1624,-1656,-1691,-1725,
+-1759,-1793,-1824,-1849,-1877,-1912,-1953,-1991,-2023,-2050,-2079,-2110,-2144,-2179,-2211,-2238,-2264,-2291,-2320,-2347,-2374,
+-2401,-2425,-2445,-2464,-2484,-2506,-2522,-2534,-2546,-2561,-2576,-2588,-2597,-2607,-2618,-2630,-2643,-2654,-2660,-2662,-2663,
+-2665,-2666,-2665,-2664,-2663,-2661,-2655,-2649,-2643,-2634,-2621,-2605,-2590,-2575,-2559,-2542,-2525,-2506,-2489,-2475,-2461,
+-2444,-2425,-2409,-2392,-2374,-2352,-2332,-2315,-2297,-2281,-2266,-2252,-2235,-2214,-2195,-2177,-2157,-2134,-2114,-2097,-2080,
+-2059,-2033,-2005,-1976,-1950,-1928,-1907,-1884,-1858,-1838,-1823,-1808,-1791,-1774,-1759,-1741,-1719,-1697,-1678,-1658,-1634,
+-1608,-1585,-1562,-1539,-1515,-1489,-1458,-1425,-1397,-1375,-1355,-1332,-1306,-1280,-1253,-1221,-1186,-1153,-1126,-1100,-1072,
+-1044,-1017,-995,-974,-950,-924,-899,-877,-853,-825,-796,-766,-735,-701,-669,-644,-620,-590,-555,-522,-495,
+-468,-439,-413,-392,-369,-339,-309,-285,-264,-241,-217,-195,-174,-150,-124,-99,-73,-46,-19,9,40,
+73,103,135,175,220,259,288,324,373,423,463,500,548,603,650,693,751,828,904,967,1025,
+1084,1127,1137,1117,1084,1055,1046,1078,1156,1258,1368,1504,1701,1954,2205,2396,2528,2636,2727,2748,2645,
+2436,2214,2065,2001,1969,1941,1938,1980,2039,2063,2043,2017,2008,1992,1939,1852,1754,1653,1548,1453,1382,
+1324,1254,1164,1070,986,909,838,775,713,634,531,422,317,211,97,-14,-102,-154,-163,-136,-110,
+-143,-257,-406,-518,-571,-602,-648,-704,-754,-800,-860,-932,-991,-1015,-1006,-995,-1019,-1091,-1192,-1291,-1377,
+-1462,-1552,-1641,-1727,-1812,-1897,-1973,-2038,-2102,-2170,-2236,-2296,-2351,-2406,-2456,-2500,-2544,-2594,-2645,-2690,-2728,
+-2765,-2801,-2838,-2872,-2900,-2917,-2924,-2928,-2933,-2936,-2928,-2904,-2865,-2824,-2803,-2813,-2839,-2849,-2840,-2838,-2863,
+-2901,-2926,-2935,-2940,-2941,-2923,-2885,-2844,-2823,-2839,-2899,-2996,-3099,-3168,-3182,-3151,-3097,-3039,-2982,-2927,-2871,
+-2807,-2737,-2667,-2604,-2546,-2491,-2436,-2380,-2323,-2261,-2195,-2130,-2073,-2025,-1980,-1928,-1867,-1802,-1739,-1677,-1616,
+-1561,-1516,-1468,-1407,-1336,-1269,-1205,-1137,-1063,-990,-928,-873,-821,-773,-725,-667,-596,-517,-441,-372,-307,
+-240,-171,-104,-42,18,80,143,205,265,326,391,454,512,564,608,638,651,658,676,710,747,
+777,801,822,842,863,884,903,916,920,926,942,966,989,1008,1025,1044,1059,1068,1074,1083,1099,
+1116,1124,1123,1122,1129,1142,1154,1157,1155,1155,1166,1189,1211,1219,1214,1211,1224,1251,1279,1298,1309,
+1314,1314,1316,1328,1347,1366,1380,1397,1418,1439,1452,1460,1469,1484,1504,1528,1558,1595,1641,1692,1744,
+1797,1854,1915,1971,2012,2033,2036,2021,1996,1971,1959,1958,1955,1943,1921,1892,1862,1838,1828,1831,1836,
+1836,1834,1833,1828,1818,1807,1806,1818,1843,1876,1907,1928,1935,1931,1921,1902,1875,1843,1811,1782,1758,
+1739,1721,1700,1678,1665,1664,1667,1668,1671,1679,1689,1705,1705,1703,1698,1686,1667,1645,1627,1612,1601,
+1600,1607,1613,1610,1605,1599,1584,1564,1552,1553,1546,1525,1511,1519,1522,1501,1499,1578,1710,1773,1693,
+1533,1423,1406,1424,1415,1380,1345,1315,1287,1269,1264,1250,1204,1135,1065,1005,948,895,853,818,778,
+728,670,606,529,438,336,221,102,4,-43,-49,-54,-95,-170,-249,-319,-389,-472,-564,-656,-743,
+-824,-905,-994,-1101,-1218,-1327,-1409,-1461,-1493,-1522,-1562,-1622,-1698,-1769,-1809,-1808,-1772,-1721,-1678,-1661,-1672,
+-1692,-1701,-1691,-1674,-1655,-1628,-1593,-1563,-1539,-1504,-1446,-1382,-1345,-1340,-1344,-1340,-1332,-1323,-1303,-1263,-1217,
+-1181,-1155,-1137,-1129,-1131,-1124,-1108,-1120,-1198,-1322,-1424,-1459,-1442,-1418,-1410,-1418,-1437,-1464,-1501,-1549,-1598,
+-1624,-1607,-1558,-1511,-1486,-1486,-1516,-1578,-1640,-1649,-1595,-1540,-1555,-1639,-1746,-1851,-1972,-2115,-2245,-2320,-2337,
+-2330,-2340,-2392,-2481,-2580,-2666,-2736,-2798,-2854,-2896,-2929,-2963,-3002,-3035,-3057,-3074,-3099,-3143,-3214,-3315,-3432,
+-3542,-3641,-3740,-3843,-3945,-4049,-4164,-4292,-4416,-4525,-4630,-4740,-4850,-4946,-5026,-5092,-5138,-5160,-5167,-5159,-5117,
+-5032,-4943,-4906,-4934,-4989,-5024,-5036,-5044,-5061,-5083,-5106,-5136,-5169,-5195,-5209,-5217,-5228,-5247,-5275,-5306,-5338,
+-5368,-5396,-5429,-5466,-5504,-5536,-5563,-5591,-5623,-5661,-5707,-5765,-5834,-5904,-5969,-6035,-6109,-6190,-6262,-6314,-6351,
+-6391,-6446,-6512,-6581,-6643,-6700,-6756,-6815,-6879,-6944,-7010,-7081,-7156,-7231,-7304,-7374,-7436,-7490,-7547,-7617,-7695,
+-7762,-7810,-7855,-7915,-7988,-8061,-8132,-8213,-8312,-8421,-8529,-8627,-8712,-8790,-8870,-8958,-9049,-9134,-9214,-9293,-9368,
+-9429,-9481,-9535,-9589,-9631,-9661,-9687,-9707,-9704,-9680,-9671,-9709,-9775,-9827,-9853,-9885,-9949,-10032,-10105,-10155,-10190,
+-10222,-10255,-10290,-10322,-10346,-10362,-10374,-10381,-10375,-10358,-10342,-10342,-10354,-10366,-10370,-10370,-10367,-10361,-10350,-10332,-10305,
+-10269,-10232,-10197,-10162,-10116,-10052,-9971,-9880,-9790,-9707,-9625,-9528,-9410,-9280,-9153,-9029,-8901,-8765,-8631,-8508,-8396,
+-8286,-8162,-8011,-7832,-7648,-7483,-7343,-7202,-7043,-6870,-6705,-6555,-6403,-6235,-6065,-5928,-5843,-5784,-5700,-5564,-5400,
+-5251,-5139,-5052,-4965,-4853,-4710,-4552,-4413,-4310,-4222,-4118,-3998,-3891,-3807,-3725,-3620,-3491,-3347,-3185,-3001,-2814,
+-2657,-2539,-2427,-2276,-2072,-1838,-1600,-1360,-1118,-899,-753,-696,-686,-655,-579,-475,-367,-255,-143,-46,32,
+110,208,319,422,513,602,697,794,896,1004,1112,1209,1294,1382,1480,1588,1697,1805,1914,2023,2125,
+2215,2292,2366,2447,2535,2625,2720,2820,2917,3004,3091,3195,3314,3424,3515,3604,3703,3801,3885,3963,4045,
+4129,4204,4274,4353,4456,4600,4801,5037,5244,5367,5421,5477,5581,5707,5800,5834,5835,5845,5880,5903,5869,
+5785,5707,5655,5582,5453,5324,5291,5367,5493,5628,5779,5928,6013,6009,5972,5956,5947,5919,5901,5939,6022,
+6101,6168,6254,6376,6530,6718,6910,7015,6945,6720,6444,6182,5930,5725,5684,5870,6185,6465,6656,6812,6957,
+7028,6984,6893,6871,6956,7090,7206,7291,7360,7410,7428,7419,7412,7426,7449,7459,7454,7448,7446,7430,7384,
+7322,7272,7240,7212,7181,7157,7150,7149,7140,7125,7116,7112,7099,7073,7046,7029,7020,7014,7011,7012,7010,
+6999,6986,6979,6975,6971,6975,6988,6998,6991,6980,6979,6980,6960,6922,6892,6873,6845,6803,6773,6761,6746,
+6716,6691,6682,6667,6632,6604,6600,6596,6568,6545,6555,6566,6541,6507,6499,6460,6309,6113,6061,6217,6401,
+6406,6235,6051,5946,5878,5800,5736,5709,5690,5658,5638,5650,5665,5657,5644,5649,5660,5658,5655,5668,5686,
+5684,5667,5650,5629,5590,5541,5505,5487,5467,5431,5388,5343,5295,5244,5193,5145,5094,5038,4977,4910,4840,
+4772,4713,4664,4624,4593,4565,4530,4484,4435,4390,4343,4290,4235,4191,4155,4118,4075,4033,3997,3968,3941,
+3911,3877,3843,3811,3778,3737,3684,3625,3567,3512,3465,3430,3402,3361,3290,3204,3131,3084,3063,3066,3083,
+3088,3054,2983,2904,2834,2773,2730,2739,2814,2903,2921,2832,2686,2574,2544,2568,2579,2537,2460,2397,2376,
+2374,2351,2294,2225,2172,2146,2137,2131,2116,2089,2055,2026,2008,1991,1963,1931,1912,1908,1910,1908,1908,
+1914,1917,1913,1907,1914,1927,1924,1892,1843,1800,1775,1766,1761,1754,1741,1724,1705,1684,1657,1626,1596,
+1574,1557,1540,1525,1517,1517,1518,1509,1484,1449,1417,1398,1391,1386,1382,1390,1413,1435,1444,1439,1432,
+1430,1428,1423,1417,1412,1405,1398,1399,1410,1423,1430,1433,1437,1448,1467,1494,1519,1529,1522,1515,1523,
+1545,1560,1556,1541,1533,1539,1546,1549,1551,1562,1583,1611,1639,1665,1683,1694,1707,1732,1760,1778,1789,
+1822,1885,1940,1933,1852,1747,1674,1646,1635,1616,1591,1571,1556,1536,1507,1474,1446,1423,1406,1396,1395,
+1401,1405,1403,1398,1388,1371,1347,1318,1287,1253,1215,1179,1147,1120,1095,1074,1055,1034,1008,979,952,
+929,905,877,845,813,782,755,733,711,685,655,625,594,561,525,490,456,422,387,350,311,
+269,223,175,130,88,51,17,-16,-51,-86,-120,-155,-193,-232,-270,-307,-347,-389,-430,-469,-508,
+-548,-591,-636,-683,-730,-775,-817,-854,-887,-917,-947,-983,-1023,-1063,-1098,-1126,-1150,-1173,-1200,-1231,-1265,
+-1299,-1335,-1370,-1404,-1435,-1468,-1503,-1537,-1567,-1596,-1629,-1662,-1694,-1724,-1754,-1784,-1811,-1841,-1877,-1917,-1953,
+-1982,-2011,-2044,-2079,-2114,-2148,-2180,-2208,-2234,-2262,-2291,-2319,-2345,-2370,-2394,-2416,-2435,-2455,-2475,-2492,-2504,
+-2516,-2530,-2546,-2560,-2571,-2582,-2592,-2602,-2614,-2623,-2627,-2625,-2624,-2626,-2628,-2629,-2630,-2630,-2628,-2621,-2615,
+-2608,-2600,-2588,-2573,-2558,-2542,-2525,-2510,-2496,-2481,-2466,-2452,-2437,-2420,-2401,-2384,-2369,-2350,-2328,-2308,-2291,
+-2275,-2257,-2240,-2223,-2206,-2187,-2168,-2149,-2129,-2110,-2093,-2077,-2059,-2036,-2012,-1989,-1966,-1941,-1917,-1895,-1872,
+-1850,-1829,-1812,-1797,-1782,-1766,-1751,-1733,-1713,-1693,-1676,-1657,-1633,-1607,-1584,-1562,-1542,-1521,-1498,-1470,-1440,
+-1414,-1394,-1375,-1352,-1328,-1306,-1283,-1254,-1220,-1187,-1156,-1127,-1100,-1076,-1055,-1033,-1011,-989,-966,-940,-913,
+-885,-858,-829,-799,-767,-734,-701,-672,-647,-618,-584,-547,-514,-485,-458,-435,-415,-392,-360,-327,-301,
+-285,-270,-250,-225,-199,-173,-148,-123,-96,-66,-34,-3,26,56,85,116,155,198,236,267,302,
+347,395,436,476,525,579,627,675,739,817,889,945,998,1054,1094,1095,1069,1049,1054,1083,1131,
+1202,1303,1445,1641,1888,2139,2334,2454,2534,2615,2682,2674,2557,2370,2194,2077,2012,1967,1941,1958,2021,
+2091,2123,2115,2097,2086,2070,2033,1977,1906,1818,1717,1620,1535,1448,1347,1243,1156,1084,1012,942,889,
+840,764,643,498,360,240,135,47,-20,-62,-63,-19,34,25,-88,-267,-427,-528,-587,-639,-693,
+-744,-793,-848,-906,-952,-969,-959,-952,-986,-1074,-1183,-1278,-1356,-1436,-1522,-1601,-1671,-1744,-1829,-1914,-1988,
+-2056,-2129,-2203,-2267,-2324,-2379,-2431,-2479,-2523,-2569,-2617,-2662,-2703,-2742,-2779,-2814,-2848,-2875,-2890,-2894,-2892,
+-2892,-2893,-2887,-2862,-2814,-2758,-2724,-2734,-2773,-2804,-2809,-2807,-2819,-2845,-2870,-2888,-2901,-2904,-2890,-2859,-2822,
+-2785,-2764,-2779,-2846,-2950,-3050,-3111,-3124,-3097,-3045,-2983,-2921,-2862,-2801,-2739,-2678,-2620,-2562,-2501,-2442,-2384,
+-2325,-2261,-2191,-2122,-2061,-2009,-1959,-1903,-1841,-1781,-1726,-1671,-1613,-1557,-1505,-1451,-1390,-1322,-1256,-1193,-1128,
+-1059,-992,-931,-876,-829,-785,-736,-671,-591,-506,-429,-363,-304,-246,-184,-121,-60,0,62,124,183,
+237,292,355,423,490,549,599,629,637,635,645,674,712,749,778,801,819,837,859,880,892,
+893,897,916,949,979,999,1016,1037,1059,1072,1072,1070,1077,1090,1099,1101,1104,1115,1130,1139,1140,
+1134,1129,1133,1152,1175,1191,1199,1214,1245,1282,1309,1319,1318,1309,1295,1284,1287,1304,1326,1345,1363,
+1380,1390,1394,1404,1428,1463,1499,1534,1571,1615,1664,1710,1748,1781,1820,1866,1909,1936,1947,1947,1935,
+1912,1885,1867,1864,1866,1864,1855,1841,1828,1822,1827,1839,1850,1856,1860,1866,1868,1865,1862,1864,1873,
+1888,1907,1923,1928,1920,1906,1889,1868,1841,1812,1784,1757,1734,1714,1700,1688,1678,1676,1680,1685,1688,
+1692,1699,1705,1710,1704,1697,1689,1677,1660,1641,1624,1610,1604,1610,1621,1625,1619,1613,1610,1601,1588,
+1583,1583,1568,1539,1528,1542,1542,1507,1500,1596,1761,1849,1767,1583,1439,1398,1409,1412,1395,1368,1329,
+1283,1249,1234,1218,1176,1116,1056,1002,945,885,831,786,745,704,661,604,524,424,317,204,93,
+4,-38,-45,-63,-126,-222,-316,-396,-476,-571,-670,-756,-829,-899,-979,-1073,-1176,-1276,-1363,-1433,-1487,
+-1532,-1574,-1620,-1674,-1735,-1793,-1836,-1850,-1830,-1788,-1746,-1729,-1743,-1768,-1785,-1786,-1777,-1756,-1723,-1684,-1653,
+-1626,-1580,-1505,-1429,-1384,-1375,-1376,-1368,-1359,-1350,-1330,-1289,-1238,-1195,-1162,-1138,-1132,-1153,-1194,-1237,-1282,
+-1334,-1384,-1409,-1408,-1400,-1404,-1413,-1419,-1430,-1459,-1509,-1567,-1609,-1612,-1563,-1484,-1407,-1363,-1365,-1424,-1525,
+-1612,-1619,-1545,-1474,-1489,-1594,-1729,-1850,-1965,-2092,-2221,-2324,-2387,-2415,-2431,-2462,-2520,-2599,-2683,-2761,-2828,
+-2883,-2923,-2956,-2992,-3035,-3075,-3108,-3135,-3164,-3203,-3270,-3376,-3510,-3650,-3780,-3900,-4007,-4098,-4179,-4270,-4375,
+-4482,-4581,-4680,-4784,-4883,-4964,-5027,-5084,-5131,-5155,-5151,-5120,-5061,-4984,-4921,-4905,-4938,-4989,-5025,-5042,-5050,
+-5058,-5070,-5091,-5123,-5154,-5172,-5177,-5183,-5201,-5230,-5263,-5293,-5318,-5342,-5368,-5399,-5434,-5465,-5493,-5521,-5555,
+-5595,-5641,-5695,-5758,-5829,-5898,-5960,-6022,-6094,-6176,-6252,-6312,-6358,-6403,-6457,-6517,-6576,-6632,-6688,-6747,-6809,
+-6871,-6932,-6999,-7076,-7157,-7233,-7302,-7366,-7423,-7479,-7540,-7615,-7694,-7760,-7810,-7856,-7912,-7976,-8043,-8114,-8198,
+-8296,-8402,-8506,-8602,-8687,-8764,-8847,-8940,-9033,-9114,-9189,-9268,-9345,-9408,-9462,-9520,-9577,-9614,-9630,-9645,-9670,
+-9684,-9678,-9675,-9704,-9756,-9799,-9826,-9866,-9937,-10022,-10092,-10139,-10172,-10202,-10233,-10266,-10299,-10324,-10341,-10356,-10371,
+-10376,-10367,-10355,-10353,-10358,-10359,-10357,-10357,-10358,-10353,-10339,-10317,-10289,-10254,-10216,-10178,-10137,-10079,-9998,-9903,-9807,
+-9727,-9664,-9605,-9530,-9428,-9312,-9194,-9073,-8942,-8803,-8672,-8553,-8437,-8308,-8160,-7997,-7823,-7649,-7489,-7345,-7204,
+-7055,-6900,-6748,-6596,-6428,-6237,-6050,-5911,-5839,-5800,-5732,-5603,-5440,-5287,-5164,-5058,-4950,-4827,-4686,-4531,-4382,
+-4250,-4127,-3999,-3872,-3766,-3686,-3613,-3533,-3457,-3382,-3270,-3081,-2832,-2590,-2411,-2288,-2170,-2020,-1839,-1639,-1418,
+-1175,-947,-789,-723,-702,-660,-574,-464,-351,-235,-116,-10,75,158,254,357,451,538,628,726,825,
+925,1031,1136,1234,1326,1422,1524,1628,1734,1842,1951,2056,2157,2253,2343,2427,2512,2601,2692,2784,2880,
+2978,3072,3164,3264,3374,3480,3575,3669,3771,3872,3962,4050,4146,4243,4325,4399,4482,4588,4729,4914,5124,
+5302,5402,5449,5516,5642,5786,5877,5890,5866,5864,5902,5938,5921,5852,5784,5733,5652,5511,5370,5326,5405,
+5555,5733,5925,6087,6153,6130,6101,6112,6114,6064,6015,6040,6119,6182,6225,6308,6460,6645,6823,6959,6991,
+6867,6623,6359,6128,5932,5818,5887,6154,6468,6665,6746,6823,6940,7019,7003,6943,6937,7010,7117,7210,7284,
+7348,7402,7438,7452,7449,7446,7452,7462,7467,7465,7458,7436,7391,7332,7280,7242,7206,7170,7148,7146,7148,
+7134,7115,7109,7117,7119,7103,7079,7057,7039,7030,7033,7040,7035,7015,7003,7009,7020,7019,7014,7019,7024,
+7017,7008,7012,7019,7005,6972,6944,6925,6894,6851,6822,6814,6800,6767,6738,6726,6708,6672,6642,6637,6633,
+6608,6586,6593,6597,6567,6538,6540,6505,6347,6138,6079,6237,6432,6452,6297,6123,6019,5941,5851,5783,5760,
+5749,5722,5702,5706,5706,5675,5640,5640,5667,5689,5702,5716,5727,5722,5706,5692,5673,5634,5583,5542,5513,
+5484,5453,5425,5395,5350,5289,5223,5163,5104,5043,4980,4920,4863,4806,4748,4691,4641,4605,4576,4538,4487,
+4434,4393,4358,4314,4264,4219,4181,4144,4105,4067,4036,4005,3972,3937,3901,3864,3828,3793,3754,3706,3649,
+3591,3537,3493,3461,3436,3395,3324,3230,3143,3085,3063,3071,3089,3089,3053,2992,2925,2860,2794,2747,2763,
+2852,2955,2975,2874,2711,2586,2551,2572,2581,2547,2496,2467,2459,2439,2382,2307,2247,2213,2190,2164,2137,
+2114,2090,2062,2034,2014,1998,1975,1945,1917,1902,1901,1910,1924,1936,1936,1927,1923,1933,1946,1939,1909,
+1870,1834,1805,1780,1763,1753,1743,1726,1706,1689,1668,1641,1614,1593,1576,1551,1524,1509,1511,1519,1518,
+1500,1471,1440,1417,1404,1400,1402,1410,1423,1433,1435,1433,1435,1445,1452,1448,1435,1420,1407,1399,1398,
+1406,1418,1431,1446,1463,1481,1494,1505,1512,1514,1509,1507,1515,1529,1538,1536,1534,1544,1561,1570,1566,
+1558,1560,1574,1600,1629,1656,1673,1681,1695,1722,1752,1764,1763,1779,1830,1885,1893,1836,1749,1680,1647,
+1632,1619,1600,1581,1563,1545,1526,1508,1489,1467,1444,1427,1419,1418,1416,1412,1407,1400,1385,1361,1332,
+1303,1271,1235,1201,1173,1148,1123,1100,1080,1060,1034,1005,980,956,930,898,865,833,802,772,746,
+722,697,669,640,610,578,543,508,474,441,407,372,336,298,255,210,165,121,81,44,6,
+-33,-71,-107,-142,-180,-220,-257,-294,-333,-374,-414,-452,-491,-533,-576,-620,-664,-708,-749,-786,-820,
+-852,-882,-913,-949,-992,-1033,-1069,-1098,-1123,-1146,-1173,-1203,-1236,-1268,-1301,-1336,-1371,-1405,-1439,-1476,-1512,
+-1544,-1574,-1605,-1636,-1664,-1690,-1717,-1746,-1775,-1807,-1842,-1879,-1911,-1939,-1971,-2007,-2044,-2077,-2109,-2141,-2172,
+-2201,-2230,-2260,-2288,-2312,-2335,-2359,-2381,-2401,-2421,-2441,-2458,-2471,-2484,-2499,-2516,-2531,-2544,-2554,-2563,-2571,
+-2581,-2590,-2593,-2590,-2587,-2588,-2592,-2596,-2598,-2598,-2595,-2590,-2585,-2579,-2570,-2557,-2542,-2528,-2513,-2496,-2482,
+-2471,-2459,-2444,-2429,-2413,-2396,-2377,-2360,-2344,-2325,-2302,-2282,-2267,-2253,-2235,-2215,-2197,-2180,-2161,-2140,-2119,
+-2101,-2087,-2074,-2060,-2039,-2013,-1990,-1973,-1955,-1932,-1905,-1880,-1859,-1839,-1821,-1805,-1790,-1775,-1761,-1746,-1729,
+-1709,-1690,-1673,-1654,-1632,-1607,-1584,-1563,-1543,-1523,-1502,-1478,-1453,-1432,-1414,-1394,-1369,-1345,-1325,-1304,-1278,
+-1249,-1221,-1191,-1160,-1133,-1113,-1095,-1072,-1047,-1025,-1006,-983,-955,-926,-897,-866,-833,-802,-772,-739,-705,
+-675,-646,-614,-579,-543,-511,-482,-454,-431,-408,-381,-350,-323,-306,-293,-276,-252,-225,-197,-171,-148,
+-121,-90,-56,-26,1,31,64,98,134,173,211,246,281,319,361,402,444,492,545,601,665,
+742,820,881,928,978,1032,1058,1041,1011,1015,1068,1140,1209,1286,1411,1611,1877,2159,2389,2520,2567,
+2585,2603,2596,2520,2377,2219,2099,2027,1982,1952,1951,1998,2081,2158,2192,2182,2153,2128,2108,2086,2054,
+2002,1926,1835,1746,1657,1549,1424,1311,1232,1170,1098,1024,969,929,857,727,558,395,268,176,107,
+52,13,15,72,145,151,37,-163,-364,-502,-579,-629,-678,-731,-785,-836,-882,-917,-931,-926,-929,
+-974,-1067,-1173,-1259,-1331,-1411,-1498,-1569,-1622,-1682,-1765,-1855,-1933,-2008,-2089,-2170,-2240,-2298,-2355,-2412,-2462,
+-2505,-2545,-2588,-2632,-2675,-2714,-2750,-2784,-2816,-2843,-2860,-2866,-2864,-2860,-2856,-2847,-2819,-2763,-2693,-2648,-2656,
+-2702,-2744,-2758,-2758,-2767,-2792,-2823,-2851,-2869,-2868,-2849,-2822,-2794,-2758,-2717,-2695,-2720,-2794,-2890,-2974,-3027,
+-3040,-3016,-2968,-2910,-2849,-2790,-2735,-2684,-2634,-2577,-2513,-2447,-2382,-2317,-2253,-2189,-2126,-2064,-2004,-1947,-1891,
+-1835,-1781,-1728,-1674,-1617,-1557,-1496,-1433,-1366,-1299,-1234,-1170,-1106,-1042,-980,-919,-861,-812,-770,-720,-653,
+-574,-495,-425,-366,-314,-265,-211,-151,-87,-22,40,103,161,212,266,329,400,470,532,581,610,
+615,611,614,634,665,701,735,761,776,789,812,843,866,874,881,904,943,980,1001,1016,1037,
+1064,1079,1074,1059,1053,1060,1071,1081,1094,1112,1130,1142,1149,1154,1158,1165,1181,1202,1221,1234,1255,
+1287,1320,1336,1332,1318,1301,1283,1272,1276,1293,1312,1325,1335,1343,1346,1355,1382,1432,1490,1541,1580,
+1618,1660,1702,1730,1738,1735,1737,1752,1770,1780,1785,1794,1806,1812,1810,1810,1820,1835,1850,1861,1870,
+1877,1883,1892,1901,1906,1906,1909,1913,1913,1909,1904,1902,1902,1902,1903,1903,1895,1879,1861,1845,1828,
+1809,1788,1768,1747,1726,1709,1700,1698,1700,1704,1708,1709,1707,1707,1710,1710,1704,1697,1690,1685,1674,
+1657,1639,1624,1613,1610,1620,1633,1635,1624,1614,1612,1612,1609,1610,1607,1586,1555,1543,1553,1545,1500,
+1480,1556,1698,1779,1716,1563,1434,1382,1377,1383,1381,1361,1311,1249,1211,1208,1205,1169,1107,1049,1003,
+955,897,833,770,717,676,640,588,506,401,292,185,83,0,-47,-69,-107,-185,-290,-388,-469,
+-554,-654,-759,-848,-914,-973,-1044,-1132,-1227,-1313,-1387,-1452,-1513,-1573,-1632,-1686,-1735,-1778,-1819,-1857,-1881,
+-1879,-1849,-1815,-1800,-1811,-1830,-1843,-1846,-1838,-1817,-1781,-1742,-1711,-1682,-1633,-1561,-1489,-1441,-1419,-1406,-1393,
+-1382,-1365,-1326,-1268,-1213,-1180,-1160,-1143,-1142,-1181,-1257,-1335,-1383,-1393,-1382,-1365,-1358,-1368,-1385,-1393,-1389,
+-1393,-1422,-1478,-1541,-1584,-1581,-1521,-1418,-1310,-1247,-1262,-1360,-1498,-1591,-1576,-1478,-1401,-1433,-1567,-1725,-1851,
+-1947,-2047,-2165,-2290,-2400,-2477,-2518,-2541,-2572,-2629,-2707,-2789,-2862,-2917,-2958,-2997,-3045,-3099,-3148,-3190,-3224,
+-3256,-3294,-3360,-3472,-3626,-3791,-3943,-4067,-4159,-4223,-4278,-4349,-4444,-4544,-4632,-4713,-4797,-4880,-4951,-5007,-5058,
+-5100,-5123,-5114,-5074,-5015,-4955,-4920,-4922,-4953,-4990,-5018,-5034,-5042,-5046,-5055,-5076,-5106,-5127,-5134,-5136,-5147,
+-5173,-5209,-5243,-5269,-5289,-5310,-5336,-5366,-5395,-5421,-5447,-5481,-5525,-5575,-5629,-5686,-5751,-5823,-5895,-5959,-6019,
+-6084,-6159,-6237,-6305,-6362,-6414,-6467,-6523,-6578,-6633,-6691,-6754,-6816,-6872,-6926,-6991,-7071,-7158,-7235,-7298,-7351,
+-7405,-7465,-7533,-7609,-7684,-7750,-7804,-7853,-7903,-7954,-8012,-8087,-8179,-8280,-8380,-8478,-8571,-8657,-8737,-8822,-8916,
+-9005,-9082,-9154,-9235,-9315,-9381,-9437,-9497,-9555,-9589,-9599,-9613,-9638,-9651,-9640,-9634,-9665,-9722,-9769,-9801,-9849,
+-9929,-10016,-10080,-10119,-10149,-10178,-10208,-10241,-10275,-10301,-10320,-10337,-10355,-10364,-10359,-10350,-10348,-10351,-10350,-10346,-10347,
+-10348,-10340,-10320,-10296,-10268,-10234,-10194,-10149,-10095,-10019,-9919,-9808,-9710,-9643,-9605,-9576,-9523,-9437,-9329,-9218,-9106,
+-8982,-8847,-8715,-8588,-8456,-8307,-8146,-7985,-7824,-7663,-7502,-7348,-7202,-7059,-6914,-6764,-6605,-6429,-6241,-6063,-5930,
+-5857,-5813,-5747,-5628,-5476,-5329,-5201,-5078,-4947,-4807,-4663,-4514,-4362,-4212,-4064,-3920,-3791,-3687,-3592,-3489,-3391,
+-3337,-3324,-3280,-3124,-2850,-2543,-2299,-2150,-2054,-1953,-1814,-1637,-1428,-1201,-987,-828,-741,-695,-641,-554,-448,
+-334,-215,-94,17,112,202,292,378,455,538,636,742,843,942,1048,1157,1260,1358,1457,1559,1662,
+1768,1879,1988,2087,2183,2284,2385,2479,2568,2658,2748,2833,2921,3019,3121,3222,3322,3426,3528,3624,3719,
+3822,3925,4021,4117,4221,4325,4415,4499,4598,4720,4864,5029,5202,5346,5431,5484,5566,5697,5827,5891,5877,
+5836,5824,5852,5884,5885,5862,5844,5821,5736,5569,5403,5346,5427,5599,5814,6042,6221,6288,6272,6269,6314,
+6334,6281,6218,6223,6269,6291,6309,6408,6600,6805,6946,6995,6929,6734,6462,6208,6019,5894,5874,6043,6384,
+6723,6896,6920,6933,6999,7068,7086,7081,7101,7153,7211,7259,7299,7338,7384,7437,7475,7477,7453,7440,7453,
+7470,7470,7453,7428,7393,7347,7300,7258,7216,7170,7137,7127,7123,7108,7087,7082,7095,7108,7109,7100,7087,
+7071,7060,7066,7076,7070,7048,7037,7049,7063,7059,7047,7046,7051,7045,7034,7035,7044,7040,7021,7003,6988,
+6959,6919,6890,6877,6857,6821,6789,6774,6752,6713,6680,6671,6665,6640,6619,6621,6618,6587,6566,6578,6547,
+6388,6173,6102,6247,6439,6472,6341,6190,6096,6018,5921,5846,5819,5805,5772,5740,5730,5720,5682,5640,5636,
+5671,5710,5735,5746,5749,5742,5733,5727,5710,5671,5621,5579,5545,5510,5475,5449,5421,5377,5312,5240,5172,
+5106,5041,4981,4926,4875,4824,4773,4718,4663,4617,4580,4541,4492,4441,4402,4369,4332,4288,4243,4203,4167,
+4134,4105,4077,4043,4003,3964,3926,3886,3847,3812,3778,3732,3673,3611,3558,3518,3490,3463,3422,3353,3258,
+3163,3096,3073,3088,3114,3118,3087,3033,2974,2910,2837,2781,2786,2862,2953,2969,2876,2724,2604,2563,2576,
+2587,2572,2551,2543,2534,2489,2405,2320,2271,2255,2237,2201,2156,2122,2101,2080,2054,2030,2012,1991,1961,
+1926,1903,1905,1928,1955,1966,1954,1936,1928,1932,1934,1923,1908,1898,1886,1855,1809,1772,1753,1743,1727,
+1708,1693,1678,1657,1635,1619,1602,1574,1539,1514,1508,1510,1509,1499,1483,1462,1439,1424,1423,1429,1435,
+1436,1433,1428,1424,1429,1442,1453,1454,1444,1430,1417,1409,1407,1413,1424,1440,1460,1482,1499,1507,1507,
+1505,1502,1500,1504,1517,1531,1538,1539,1545,1563,1581,1586,1580,1576,1580,1588,1599,1615,1637,1654,1664,
+1678,1706,1737,1748,1741,1739,1762,1796,1808,1783,1733,1683,1647,1628,1617,1605,1587,1562,1541,1529,1523,
+1515,1499,1478,1459,1447,1438,1427,1416,1408,1400,1385,1361,1337,1313,1285,1252,1220,1194,1172,1148,1124,
+1103,1082,1056,1031,1010,990,965,931,896,862,828,793,760,731,705,678,651,622,591,559,527,
+496,464,428,393,358,321,281,238,193,149,106,66,25,-18,-61,-100,-137,-174,-212,-248,-284,
+-323,-363,-401,-438,-478,-521,-564,-605,-646,-686,-723,-755,-785,-816,-845,-877,-914,-957,-999,-1035,-1065,
+-1092,-1118,-1145,-1176,-1208,-1240,-1270,-1303,-1338,-1374,-1411,-1449,-1486,-1519,-1548,-1577,-1607,-1634,-1658,-1683,-1713,
+-1746,-1778,-1811,-1842,-1871,-1900,-1932,-1968,-2002,-2032,-2063,-2097,-2131,-2162,-2193,-2222,-2248,-2270,-2293,-2317,-2340,
+-2361,-2380,-2400,-2417,-2432,-2447,-2464,-2482,-2497,-2510,-2521,-2530,-2537,-2546,-2554,-2557,-2554,-2551,-2554,-2560,-2564,
+-2565,-2564,-2562,-2559,-2556,-2550,-2540,-2526,-2513,-2501,-2487,-2470,-2455,-2444,-2433,-2417,-2400,-2384,-2368,-2351,-2334,
+-2318,-2299,-2275,-2254,-2240,-2227,-2210,-2189,-2170,-2153,-2133,-2111,-2091,-2075,-2064,-2056,-2043,-2021,-1993,-1970,-1955,
+-1941,-1920,-1892,-1868,-1848,-1832,-1815,-1799,-1785,-1771,-1757,-1742,-1725,-1706,-1686,-1668,-1650,-1630,-1607,-1585,-1563,
+-1543,-1523,-1502,-1479,-1458,-1442,-1426,-1404,-1379,-1355,-1336,-1314,-1287,-1263,-1242,-1219,-1190,-1163,-1145,-1129,-1104,
+-1077,-1056,-1041,-1022,-997,-973,-947,-913,-875,-842,-813,-780,-740,-703,-674,-647,-615,-580,-546,-511,-473,
+-439,-415,-395,-372,-348,-327,-308,-289,-266,-240,-214,-189,-166,-141,-112,-80,-52,-26,4,42,80,
+112,144,182,222,257,289,326,369,415,463,515,580,659,742,814,866,913,966,1010,1013,977,
+955,1003,1116,1237,1332,1426,1577,1819,2124,2421,2635,2728,2720,2658,2569,2446,2292,2141,2037,1992,1977,
+1962,1949,1964,2026,2121,2204,2237,2215,2166,2123,2101,2092,2076,2036,1968,1886,1804,1717,1610,1488,1380,
+1306,1244,1164,1076,1010,962,890,760,589,424,299,215,152,98,60,63,119,190,195,82,-121,
+-333,-485,-568,-614,-658,-711,-768,-817,-859,-893,-914,-919,-930,-976,-1062,-1156,-1231,-1301,-1385,-1473,-1538,
+-1583,-1639,-1720,-1809,-1888,-1965,-2053,-2141,-2214,-2272,-2329,-2388,-2441,-2483,-2521,-2561,-2603,-2643,-2680,-2714,-2746,
+-2776,-2802,-2820,-2829,-2828,-2819,-2808,-2794,-2766,-2709,-2636,-2586,-2589,-2630,-2670,-2687,-2697,-2718,-2752,-2791,-2825,
+-2842,-2833,-2806,-2779,-2760,-2735,-2697,-2658,-2645,-2670,-2723,-2788,-2852,-2902,-2926,-2921,-2889,-2839,-2782,-2729,-2683,
+-2637,-2582,-2518,-2449,-2378,-2308,-2246,-2193,-2142,-2083,-2018,-1957,-1907,-1860,-1806,-1744,-1681,-1621,-1563,-1500,-1431,
+-1362,-1299,-1236,-1171,-1107,-1048,-992,-932,-869,-814,-766,-715,-651,-580,-514,-455,-402,-353,-308,-257,-196,
+-127,-57,8,71,129,184,239,302,369,433,489,533,561,574,581,592,610,633,663,696,723,
+736,746,770,809,844,861,869,889,927,965,987,1000,1019,1047,1066,1061,1042,1032,1038,1053,1071,
+1092,1118,1142,1162,1184,1209,1230,1241,1250,1262,1269,1269,1269,1280,1295,1296,1283,1263,1248,1242,1254,
+1285,1326,1361,1385,1402,1413,1419,1432,1464,1514,1565,1602,1627,1656,1692,1725,1738,1724,1697,1677,1676,
+1684,1691,1700,1722,1757,1791,1814,1832,1853,1876,1900,1923,1944,1958,1965,1968,1966,1957,1946,1939,1934,
+1926,1914,1904,1896,1888,1880,1873,1868,1859,1844,1830,1817,1804,1789,1776,1765,1753,1739,1729,1726,1729,
+1733,1737,1737,1730,1719,1712,1708,1704,1699,1694,1690,1686,1674,1654,1636,1626,1621,1620,1630,1643,1646,
+1634,1620,1617,1623,1628,1630,1623,1600,1569,1551,1552,1543,1512,1494,1530,1595,1620,1569,1479,1405,1365,
+1346,1343,1344,1317,1247,1171,1143,1167,1187,1159,1095,1036,997,964,916,850,777,709,656,613,559,
+478,374,263,156,54,-31,-91,-134,-187,-266,-363,-455,-535,-620,-721,-831,-928,-1002,-1058,-1117,-1188,
+-1266,-1342,-1412,-1479,-1549,-1619,-1686,-1745,-1787,-1814,-1838,-1872,-1907,-1924,-1912,-1887,-1873,-1876,-1884,-1888,-1888,
+-1880,-1859,-1823,-1785,-1753,-1720,-1672,-1612,-1552,-1503,-1465,-1436,-1419,-1404,-1364,-1286,-1196,-1140,-1131,-1141,-1139,
+-1139,-1174,-1247,-1315,-1341,-1325,-1302,-1298,-1316,-1342,-1358,-1353,-1339,-1339,-1370,-1429,-1497,-1554,-1572,-1530,-1425,
+-1296,-1213,-1233,-1353,-1503,-1582,-1538,-1426,-1359,-1413,-1564,-1729,-1850,-1929,-2004,-2104,-2231,-2367,-2483,-2557,-2594,
+-2623,-2670,-2743,-2826,-2901,-2957,-3001,-3052,-3116,-3183,-3240,-3285,-3324,-3364,-3415,-3494,-3618,-3780,-3948,-4093,-4199,
+-4267,-4307,-4345,-4410,-4506,-4605,-4680,-4735,-4790,-4854,-4920,-4977,-5024,-5062,-5084,-5077,-5041,-4987,-4943,-4926,-4937,
+-4961,-4982,-4999,-5011,-5019,-5026,-5038,-5059,-5081,-5091,-5092,-5097,-5116,-5146,-5180,-5209,-5232,-5252,-5275,-5302,-5330,
+-5355,-5380,-5412,-5458,-5514,-5572,-5629,-5686,-5749,-5820,-5893,-5961,-6021,-6082,-6150,-6224,-6296,-6357,-6410,-6463,-6521,
+-6583,-6644,-6705,-6766,-6824,-6877,-6929,-6991,-7069,-7154,-7228,-7285,-7333,-7387,-7454,-7529,-7603,-7670,-7733,-7793,-7847,
+-7891,-7930,-7982,-8062,-8162,-8262,-8353,-8443,-8535,-8624,-8707,-8792,-8882,-8967,-9041,-9115,-9199,-9281,-9346,-9402,-9462,
+-9520,-9556,-9574,-9597,-9619,-9609,-9569,-9549,-9591,-9671,-9735,-9779,-9839,-9930,-10019,-10074,-10102,-10126,-10156,-10188,-10221,
+-10255,-10284,-10304,-10322,-10340,-10349,-10344,-10335,-10333,-10337,-10338,-10336,-10338,-10337,-10325,-10301,-10275,-10247,-10212,-10166,-10111,
+-10044,-9952,-9833,-9709,-9608,-9551,-9532,-9521,-9486,-9411,-9312,-9211,-9109,-8996,-8866,-8730,-8590,-8442,-8284,-8124,-7974,
+-7828,-7677,-7518,-7360,-7213,-7074,-6934,-6782,-6615,-6441,-6273,-6122,-6001,-5912,-5841,-5757,-5641,-5502,-5365,-5237,-5104,
+-4957,-4803,-4651,-4502,-4350,-4190,-4025,-3870,-3744,-3641,-3531,-3393,-3261,-3197,-3214,-3230,-3137,-2896,-2572,-2275,-2077,
+-1970,-1890,-1773,-1601,-1396,-1193,-1010,-860,-749,-671,-603,-525,-429,-316,-193,-70,42,143,237,322,389,
+448,526,632,748,855,956,1067,1185,1295,1393,1490,1588,1691,1802,1919,2027,2120,2210,2312,2418,2515,
+2606,2699,2791,2875,2959,3059,3172,3282,3383,3482,3580,3672,3763,3863,3969,4068,4158,4253,4354,4452,4552,
+4670,4810,4960,5111,5254,5371,5450,5513,5601,5717,5814,5845,5819,5784,5770,5770,5762,5752,5768,5820,5852,
+5782,5599,5411,5346,5438,5635,5879,6129,6321,6400,6397,6405,6447,6453,6386,6314,6303,6317,6306,6321,6452,
+6681,6882,6962,6920,6768,6515,6217,5977,5845,5812,5892,6142,6538,6918,7121,7149,7121,7121,7149,7189,7240,
+7294,7327,7333,7332,7335,7344,7374,7432,7488,7495,7462,7442,7460,7481,7470,7439,7414,7394,7359,7311,7261,
+7206,7146,7096,7075,7075,7073,7064,7061,7069,7079,7085,7090,7092,7085,7079,7087,7102,7105,7092,7084,7091,
+7100,7093,7083,7086,7095,7089,7070,7060,7063,7066,7062,7055,7044,7021,6987,6960,6940,6912,6873,6842,6826,
+6803,6765,6730,6715,6699,6668,6642,6639,6634,6609,6596,6614,6590,6441,6229,6137,6243,6408,6448,6346,6222,
+6147,6082,5994,5917,5880,5854,5809,5763,5739,5724,5691,5655,5649,5680,5721,5749,5759,5754,5746,5746,5754,
+5751,5722,5676,5632,5589,5542,5497,5461,5427,5384,5327,5260,5187,5111,5042,4984,4935,4886,4840,4798,4753,
+4697,4637,4586,4545,4508,4469,4431,4393,4352,4308,4266,4226,4190,4161,4137,4110,4071,4026,3985,3946,3905,
+3865,3834,3806,3763,3703,3637,3585,3547,3517,3486,3444,3381,3292,3194,3118,3090,3111,3150,3168,3144,3089,
+3024,2953,2876,2814,2799,2841,2900,2915,2854,2743,2639,2584,2577,2589,2593,2589,2578,2550,2489,2402,2324,
+2284,2277,2269,2240,2195,2156,2130,2109,2084,2058,2038,2019,1989,1948,1919,1923,1955,1985,1988,1966,1941,
+1931,1929,1920,1909,1914,1935,1944,1911,1847,1790,1763,1752,1737,1718,1704,1692,1674,1654,1639,1624,1596,
+1559,1528,1513,1505,1498,1495,1493,1483,1465,1449,1448,1454,1455,1448,1438,1431,1427,1426,1431,1438,1442,
+1442,1439,1433,1428,1428,1436,1451,1465,1477,1486,1492,1496,1503,1509,1511,1511,1518,1535,1554,1560,1559,
+1565,1578,1584,1577,1570,1578,1593,1599,1595,1596,1611,1629,1643,1659,1685,1715,1729,1726,1720,1724,1736,
+1745,1744,1727,1695,1657,1629,1617,1610,1591,1562,1536,1523,1520,1515,1505,1491,1479,1467,1453,1436,1419,
+1406,1395,1379,1360,1341,1323,1299,1267,1234,1208,1187,1163,1139,1119,1100,1077,1055,1038,1023,1001,970,
+937,903,865,822,781,748,719,693,666,638,608,578,550,521,488,450,412,375,337,298,257,
+214,169,126,86,45,1,-45,-88,-126,-162,-198,-233,-271,-312,-354,-391,-428,-467,-509,-549,-585,
+-623,-662,-697,-727,-756,-785,-813,-844,-881,-923,-963,-997,-1028,-1058,-1087,-1116,-1147,-1180,-1211,-1239,-1270,
+-1305,-1341,-1378,-1415,-1452,-1486,-1515,-1543,-1573,-1601,-1626,-1653,-1684,-1719,-1752,-1781,-1809,-1837,-1867,-1900,-1932,
+-1962,-1990,-2022,-2057,-2092,-2123,-2151,-2178,-2201,-2222,-2245,-2270,-2295,-2315,-2335,-2355,-2373,-2389,-2406,-2425,-2444,
+-2459,-2471,-2483,-2492,-2500,-2507,-2515,-2519,-2519,-2520,-2524,-2530,-2533,-2532,-2531,-2530,-2528,-2524,-2518,-2507,-2494,
+-2482,-2472,-2458,-2442,-2426,-2414,-2400,-2383,-2365,-2350,-2337,-2322,-2307,-2292,-2274,-2251,-2230,-2215,-2201,-2183,-2162,
+-2143,-2126,-2106,-2084,-2065,-2051,-2042,-2034,-2022,-2002,-1976,-1954,-1939,-1925,-1905,-1881,-1860,-1843,-1827,-1810,-1794,
+-1779,-1765,-1750,-1735,-1718,-1699,-1679,-1662,-1645,-1627,-1606,-1584,-1562,-1543,-1524,-1503,-1480,-1459,-1443,-1427,-1405,
+-1379,-1358,-1341,-1319,-1292,-1269,-1253,-1236,-1210,-1185,-1169,-1154,-1131,-1104,-1085,-1071,-1053,-1032,-1014,-993,-961,
+-921,-886,-856,-819,-774,-734,-706,-682,-653,-620,-587,-548,-501,-456,-423,-402,-385,-368,-348,-325,-300,
+-275,-252,-229,-203,-179,-156,-131,-101,-73,-46,-14,24,61,88,116,153,194,227,256,293,345,
+400,451,504,572,653,730,793,845,900,953,977,954,914,929,1039,1211,1374,1493,1603,1764,2004,
+2295,2572,2765,2835,2782,2641,2449,2239,2053,1937,1909,1938,1972,1977,1966,1976,2034,2131,2221,2253,2215,
+2143,2086,2063,2064,2061,2035,1981,1906,1824,1742,1651,1549,1451,1368,1290,1200,1105,1028,968,892,768,
+610,455,335,249,180,121,80,77,115,159,149,45,-130,-318,-459,-542,-589,-632,-685,-740,-789,
+-834,-877,-909,-923,-936,-978,-1053,-1132,-1200,-1270,-1356,-1443,-1506,-1553,-1614,-1697,-1783,-1858,-1936,-2027,-2118,
+-2189,-2245,-2300,-2359,-2412,-2455,-2493,-2534,-2574,-2610,-2643,-2676,-2707,-2734,-2755,-2772,-2781,-2777,-2757,-2734,-2717,
+-2696,-2651,-2587,-2537,-2530,-2556,-2585,-2608,-2638,-2682,-2732,-2773,-2803,-2814,-2801,-2770,-2741,-2725,-2710,-2680,-2641,
+-2608,-2591,-2589,-2606,-2648,-2709,-2773,-2816,-2825,-2800,-2756,-2712,-2674,-2631,-2578,-2515,-2450,-2382,-2314,-2256,-2211,
+-2167,-2110,-2045,-1988,-1947,-1906,-1845,-1768,-1695,-1637,-1586,-1528,-1461,-1395,-1338,-1282,-1219,-1154,-1099,-1050,-995,
+-932,-870,-814,-759,-697,-635,-579,-528,-477,-427,-379,-324,-258,-186,-116,-52,7,66,122,180,239,
+299,355,405,446,477,504,533,565,593,615,639,670,697,712,723,749,791,830,848,852,865,
+897,934,959,971,989,1015,1037,1038,1027,1026,1041,1064,1087,1114,1143,1170,1193,1221,1252,1273,1278,
+1275,1275,1272,1255,1233,1221,1221,1222,1218,1211,1211,1226,1263,1324,1396,1463,1519,1568,1604,1622,1630,
+1641,1656,1666,1665,1668,1687,1720,1750,1760,1747,1723,1712,1721,1742,1758,1773,1798,1835,1872,1898,1916,
+1931,1947,1963,1978,1989,1993,1992,1988,1980,1967,1952,1939,1928,1914,1897,1884,1875,1866,1857,1851,1848,
+1844,1836,1828,1819,1806,1791,1781,1776,1771,1764,1760,1759,1758,1756,1754,1750,1738,1722,1709,1703,1699,
+1704,1701,1697,1691,1675,1653,1637,1632,1632,1632,1637,1648,1655,1647,1633,1629,1637,1644,1644,1634,1612,
+1583,1561,1557,1569,1587,1601,1599,1564,1497,1430,1392,1375,1353,1323,1307,1299,1254,1158,1062,1036,1081,
+1126,1117,1066,1016,987,965,928,870,795,715,643,582,521,445,346,234,120,12,-81,-155,-215,
+-274,-343,-426,-513,-598,-685,-781,-888,-993,-1082,-1149,-1202,-1256,-1314,-1376,-1442,-1514,-1590,-1665,-1733,-1788,
+-1823,-1839,-1853,-1886,-1932,-1966,-1968,-1950,-1935,-1932,-1934,-1934,-1932,-1921,-1897,-1860,-1823,-1789,-1750,-1703,-1653,
+-1605,-1557,-1507,-1468,-1448,-1424,-1356,-1236,-1115,-1053,-1058,-1080,-1080,-1072,-1093,-1143,-1187,-1198,-1193,-1204,-1241,
+-1285,-1315,-1320,-1306,-1291,-1294,-1329,-1389,-1462,-1532,-1577,-1569,-1488,-1361,-1261,-1261,-1366,-1500,-1560,-1509,-1406,
+-1354,-1412,-1556,-1714,-1835,-1914,-1979,-2060,-2172,-2306,-2437,-2538,-2605,-2653,-2707,-2779,-2863,-2941,-3002,-3056,-3118,
+-3192,-3262,-3314,-3355,-3402,-3466,-3548,-3655,-3791,-3943,-4085,-4198,-4278,-4328,-4359,-4393,-4455,-4549,-4646,-4714,-4751,
+-4784,-4832,-4893,-4950,-4994,-5027,-5046,-5041,-5009,-4961,-4925,-4918,-4934,-4954,-4967,-4975,-4983,-4991,-5001,-5017,-5037,
+-5051,-5056,-5059,-5070,-5091,-5116,-5141,-5167,-5194,-5220,-5245,-5269,-5293,-5315,-5344,-5388,-5448,-5513,-5576,-5633,-5690,
+-5750,-5817,-5888,-5957,-6019,-6079,-6145,-6215,-6283,-6340,-6392,-6448,-6513,-6584,-6650,-6708,-6763,-6820,-6877,-6935,-6998,
+-7070,-7145,-7213,-7267,-7316,-7373,-7444,-7521,-7591,-7652,-7713,-7777,-7835,-7877,-7912,-7964,-8047,-8146,-8237,-8317,-8401,
+-8496,-8590,-8674,-8756,-8842,-8924,-9000,-9078,-9164,-9244,-9305,-9358,-9418,-9477,-9519,-9552,-9589,-9607,-9569,-9493,-9460,
+-9515,-9620,-9705,-9762,-9836,-9939,-10030,-10075,-10088,-10105,-10136,-10171,-10207,-10242,-10273,-10295,-10313,-10330,-10339,-10335,-10326,
+-10325,-10328,-10327,-10325,-10325,-10322,-10309,-10287,-10263,-10235,-10193,-10138,-10075,-9999,-9896,-9766,-9634,-9533,-9480,-9465,-9458,
+-9427,-9360,-9270,-9175,-9078,-8969,-8842,-8701,-8554,-8401,-8247,-8099,-7960,-7825,-7682,-7531,-7378,-7235,-7102,-6970,-6823,
+-6658,-6492,-6344,-6217,-6103,-5992,-5883,-5770,-5647,-5518,-5390,-5265,-5130,-4979,-4818,-4658,-4504,-4348,-4182,-4009,-3846,
+-3715,-3606,-3482,-3321,-3164,-3081,-3095,-3145,-3124,-2967,-2687,-2368,-2109,-1954,-1857,-1734,-1549,-1341,-1165,-1026,-897,
+-768,-655,-571,-499,-414,-305,-180,-57,53,157,259,348,411,463,536,644,766,878,984,1100,1222,
+1335,1430,1520,1615,1721,1839,1960,2066,2155,2242,2342,2445,2539,2630,2729,2830,2920,3005,3108,3227,3340,
+3438,3530,3621,3706,3792,3894,4007,4107,4188,4270,4369,4480,4595,4720,4862,5010,5152,5281,5387,5467,5533,
+5610,5693,5749,5757,5741,5733,5729,5696,5627,5567,5578,5669,5753,5722,5564,5398,5360,5482,5699,5943,6176,
+6352,6429,6431,6430,6436,6395,6291,6198,6170,6168,6154,6190,6355,6597,6764,6778,6668,6471,6195,5889,5668,
+5602,5680,5883,6224,6669,7078,7313,7360,7310,7253,7234,7275,7364,7445,7466,7439,7412,7397,7388,7399,7446,
+7500,7507,7472,7452,7472,7488,7464,7425,7406,7396,7361,7297,7227,7155,7077,7009,6980,6992,7017,7033,7041,
+7048,7053,7055,7061,7071,7076,7078,7087,7105,7119,7120,7118,7122,7128,7128,7129,7138,7145,7138,7117,7101,
+7099,7103,7104,7100,7090,7070,7042,7016,6991,6958,6920,6893,6877,6856,6822,6791,6771,6746,6705,6669,6657,
+6651,6632,6623,6642,6630,6510,6314,6191,6230,6348,6392,6327,6231,6168,6117,6047,5977,5931,5896,5850,5802,
+5768,5744,5714,5683,5673,5692,5727,5761,5780,5777,5763,5760,5774,5788,5780,5747,5699,5643,5582,5524,5475,
+5434,5393,5349,5294,5220,5134,5057,5000,4954,4908,4865,4833,4800,4745,4671,4601,4555,4526,4500,4466,4423,
+4376,4332,4292,4252,4213,4180,4154,4125,4085,4038,3995,3957,3915,3874,3844,3817,3779,3723,3664,3615,3578,
+3543,3504,3461,3403,3324,3231,3152,3118,3136,3179,3205,3186,3126,3048,2969,2893,2830,2795,2800,2833,2867,
+2868,2819,2734,2648,2598,2589,2599,2595,2567,2517,2456,2391,2333,2297,2284,2281,2271,2243,2207,2174,2146,
+2121,2098,2081,2065,2036,1993,1960,1958,1982,2001,1992,1966,1947,1943,1938,1922,1911,1927,1964,1981,1948,
+1877,1814,1783,1771,1757,1739,1725,1713,1695,1673,1655,1638,1611,1575,1544,1523,1509,1499,1499,1503,1501,
+1487,1474,1473,1477,1475,1464,1453,1445,1439,1432,1426,1425,1430,1438,1446,1449,1447,1450,1463,1480,1490,
+1489,1481,1478,1493,1522,1549,1556,1546,1542,1556,1575,1579,1573,1573,1581,1578,1561,1551,1563,1585,1591,
+1581,1578,1594,1616,1632,1646,1668,1690,1703,1705,1706,1709,1712,1715,1723,1726,1708,1671,1637,1622,1614,
+1596,1565,1536,1519,1509,1502,1494,1487,1480,1471,1459,1443,1425,1408,1394,1378,1362,1347,1332,1309,1278,
+1245,1218,1195,1170,1148,1133,1119,1101,1079,1061,1046,1028,1004,978,947,907,860,814,778,747,718,
+690,661,630,598,568,538,504,466,427,390,353,314,275,235,193,150,111,72,30,-15,-60,
+-100,-136,-171,-206,-247,-291,-335,-374,-411,-450,-491,-527,-561,-597,-636,-671,-702,-730,-757,-785,-816,
+-853,-893,-930,-961,-993,-1026,-1058,-1085,-1114,-1147,-1179,-1208,-1237,-1270,-1305,-1339,-1375,-1413,-1449,-1480,-1509,
+-1540,-1570,-1596,-1622,-1655,-1690,-1722,-1750,-1778,-1809,-1842,-1873,-1903,-1931,-1961,-1994,-2029,-2061,-2088,-2113,-2136,
+-2157,-2176,-2199,-2225,-2250,-2271,-2291,-2311,-2330,-2347,-2366,-2386,-2404,-2416,-2427,-2439,-2451,-2460,-2467,-2475,-2481,
+-2485,-2489,-2496,-2501,-2502,-2500,-2501,-2501,-2498,-2492,-2484,-2474,-2462,-2451,-2440,-2427,-2410,-2395,-2381,-2366,-2347,
+-2329,-2316,-2303,-2290,-2277,-2264,-2250,-2231,-2211,-2194,-2178,-2159,-2138,-2120,-2103,-2082,-2061,-2044,-2032,-2020,-2008,
+-1995,-1978,-1958,-1939,-1923,-1907,-1888,-1868,-1852,-1838,-1821,-1802,-1784,-1770,-1756,-1740,-1724,-1708,-1690,-1672,-1656,
+-1641,-1624,-1604,-1582,-1561,-1542,-1524,-1504,-1481,-1460,-1443,-1425,-1401,-1376,-1357,-1344,-1325,-1300,-1277,-1261,-1245,
+-1221,-1199,-1184,-1170,-1149,-1126,-1109,-1094,-1074,-1053,-1036,-1020,-993,-956,-922,-891,-854,-810,-772,-745,-721,
+-692,-662,-633,-598,-551,-498,-450,-413,-389,-377,-368,-350,-321,-294,-274,-253,-226,-198,-176,-153,-123,
+-90,-60,-29,6,39,65,91,127,166,196,224,267,330,395,451,506,573,647,713,772,834,
+898,939,933,892,873,944,1113,1325,1509,1646,1773,1936,2146,2380,2591,2730,2753,2652,2458,2227,2017,
+1875,1826,1861,1933,1987,1997,1980,1978,2025,2121,2214,2245,2193,2103,2036,2013,2018,2026,2023,1994,1933,
+1850,1769,1693,1610,1508,1398,1292,1197,1112,1041,979,901,785,638,494,375,283,206,141,94,74,
+78,80,49,-35,-165,-307,-425,-505,-558,-605,-657,-708,-758,-808,-858,-895,-912,-927,-967,-1034,-1104,
+-1167,-1235,-1320,-1405,-1470,-1526,-1597,-1682,-1763,-1834,-1913,-2005,-2095,-2164,-2219,-2274,-2332,-2383,-2426,-2466,-2507,
+-2545,-2578,-2609,-2641,-2671,-2693,-2710,-2723,-2730,-2717,-2682,-2644,-2623,-2613,-2587,-2537,-2489,-2471,-2480,-2501,-2533,
+-2587,-2657,-2719,-2759,-2780,-2786,-2773,-2744,-2716,-2697,-2680,-2654,-2620,-2587,-2556,-2523,-2499,-2499,-2534,-2595,-2655,
+-2691,-2694,-2679,-2666,-2655,-2629,-2579,-2516,-2454,-2397,-2341,-2288,-2240,-2189,-2127,-2062,-2013,-1980,-1940,-1875,-1794,
+-1723,-1674,-1633,-1580,-1514,-1452,-1402,-1351,-1291,-1227,-1176,-1136,-1090,-1031,-967,-906,-848,-787,-728,-675,-626,
+-577,-526,-472,-410,-339,-266,-201,-145,-92,-36,20,77,135,190,244,295,340,378,415,460,513,
+558,588,612,640,670,693,713,743,785,823,840,842,851,878,916,945,963,979,1002,1023,1029,
+1029,1041,1068,1099,1126,1151,1178,1199,1213,1225,1238,1239,1226,1214,1214,1217,1207,1188,1178,1187,1208,
+1232,1257,1281,1311,1352,1411,1480,1556,1636,1718,1783,1817,1818,1803,1782,1756,1732,1725,1744,1778,1806,
+1819,1816,1811,1819,1844,1875,1897,1910,1925,1950,1975,1991,1996,1995,1993,1990,1986,1979,1968,1958,1952,
+1949,1942,1933,1926,1917,1905,1891,1881,1876,1870,1862,1857,1855,1852,1847,1842,1836,1825,1811,1801,1795,
+1789,1783,1779,1775,1767,1756,1748,1743,1733,1718,1708,1705,1704,1715,1710,1703,1695,1681,1660,1646,1644,
+1647,1646,1645,1654,1663,1661,1650,1645,1649,1654,1651,1640,1624,1602,1581,1583,1627,1704,1761,1738,1620,
+1469,1371,1351,1361,1342,1301,1276,1264,1212,1098,980,933,968,1023,1042,1023,994,971,949,917,867,
+799,716,629,554,490,420,328,212,89,-25,-121,-202,-269,-328,-389,-463,-555,-654,-749,-839,-934,
+-1035,-1133,-1215,-1279,-1332,-1380,-1427,-1483,-1553,-1633,-1709,-1774,-1823,-1853,-1865,-1876,-1907,-1956,-1997,-2007,-1996,
+-1984,-1984,-1989,-1991,-1985,-1967,-1934,-1893,-1856,-1820,-1776,-1727,-1683,-1646,-1602,-1548,-1501,-1473,-1435,-1343,-1196,
+-1054,-975,-959,-957,-943,-936,-963,-1011,-1050,-1072,-1103,-1158,-1220,-1262,-1276,-1272,-1263,-1259,-1274,-1319,-1387,
+-1460,-1526,-1580,-1602,-1564,-1464,-1357,-1315,-1365,-1457,-1508,-1478,-1399,-1347,-1378,-1492,-1647,-1792,-1900,-1975,-2047,
+-2141,-2262,-2390,-2504,-2592,-2662,-2729,-2804,-2890,-2975,-3049,-3117,-3188,-3257,-3309,-3342,-3379,-3446,-3549,-3675,-3810,
+-3947,-4074,-4176,-4252,-4312,-4361,-4397,-4431,-4484,-4566,-4658,-4727,-4766,-4793,-4832,-4883,-4935,-4977,-5005,-5019,-5009,
+-4974,-4929,-4900,-4901,-4921,-4942,-4953,-4958,-4960,-4963,-4972,-4989,-5009,-5024,-5031,-5039,-5053,-5070,-5086,-5105,-5133,
+-5167,-5198,-5221,-5238,-5253,-5275,-5314,-5372,-5441,-5509,-5571,-5628,-5686,-5747,-5811,-5877,-5941,-6003,-6066,-6134,-6203,
+-6266,-6320,-6372,-6433,-6504,-6577,-6641,-6694,-6745,-6803,-6868,-6935,-7002,-7070,-7138,-7201,-7256,-7306,-7362,-7431,-7503,
+-7570,-7631,-7692,-7757,-7816,-7860,-7899,-7955,-8037,-8125,-8200,-8272,-8358,-8460,-8557,-8640,-8719,-8802,-8883,-8960,-9041,
+-9126,-9200,-9258,-9311,-9374,-9435,-9483,-9529,-9580,-9597,-9543,-9450,-9411,-9477,-9593,-9686,-9751,-9836,-9950,-10040,-10073,
+-10073,-10084,-10115,-10154,-10192,-10231,-10264,-10285,-10300,-10315,-10326,-10326,-10322,-10321,-10322,-10318,-10312,-10308,-10304,-10292,-10276,
+-10256,-10225,-10175,-10112,-10044,-9963,-9852,-9714,-9583,-9489,-9443,-9425,-9408,-9370,-9303,-9215,-9120,-9019,-8908,-8781,-8641,
+-8497,-8351,-8208,-8071,-7941,-7811,-7676,-7534,-7388,-7246,-7119,-7000,-6871,-6722,-6566,-6427,-6310,-6194,-6064,-5924,-5786,
+-5654,-5527,-5404,-5283,-5153,-5005,-4843,-4677,-4514,-4351,-4181,-4005,-3842,-3704,-3582,-3440,-3269,-3106,-3010,-3006,-3057,
+-3089,-3027,-2828,-2525,-2219,-2000,-1858,-1707,-1504,-1296,-1150,-1055,-949,-805,-658,-548,-470,-391,-292,-176,-60,
+48,155,265,371,454,518,590,692,813,928,1036,1150,1268,1375,1466,1552,1645,1753,1871,1991,2096,
+2186,2274,2373,2472,2561,2653,2760,2871,2968,3054,3153,3267,3374,3466,3552,3636,3715,3798,3902,4021,4124,
+4202,4283,4392,4521,4648,4769,4895,5029,5166,5293,5402,5483,5542,5593,5634,5653,5648,5647,5664,5673,5628,
+5520,5409,5375,5444,5542,5561,5478,5393,5421,5580,5792,5991,6161,6287,6348,6358,6359,6347,6270,6125,5991,
+5925,5900,5884,5933,6102,6319,6436,6395,6251,6048,5782,5491,5294,5293,5492,5844,6308,6808,7216,7432,7468,
+7411,7339,7304,7339,7434,7521,7544,7521,7502,7497,7485,7477,7496,7519,7500,7447,7418,7433,7447,7426,7400,
+7398,7397,7356,7279,7195,7114,7023,6937,6890,6894,6922,6948,6971,6994,7012,7019,7027,7043,7063,7078,7088,
+7102,7118,7129,7135,7142,7155,7168,7178,7182,7180,7172,7161,7153,7153,7155,7154,7148,7136,7118,7093,7066,
+7036,7002,6967,6939,6918,6894,6865,6839,6819,6790,6744,6699,6672,6656,6634,6622,6638,6645,6570,6405,6253,
+6217,6284,6345,6328,6257,6187,6131,6075,6019,5973,5936,5898,5857,5818,5781,5746,5717,5702,5709,5738,5784,
+5825,5835,5815,5792,5793,5811,5822,5807,5763,5697,5625,5558,5501,5452,5412,5376,5331,5260,5170,5087,5028,
+4983,4937,4895,4866,4839,4787,4708,4625,4566,4532,4508,4477,4436,4391,4352,4317,4277,4232,4191,4161,4132,
+4093,4046,4002,3962,3921,3879,3844,3814,3777,3732,3687,3648,3611,3569,3522,3474,3418,3347,3267,3195,3157,
+3160,3190,3209,3190,3130,3050,2971,2898,2834,2785,2766,2792,2857,2923,2935,2863,2737,2627,2580,2582,2582,
+2549,2494,2444,2406,2369,2330,2300,2290,2291,2281,2252,2217,2187,2165,2147,2133,2119,2093,2054,2019,2006,
+2010,2007,1985,1963,1956,1958,1950,1929,1914,1927,1959,1975,1950,1893,1837,1805,1789,1773,1755,1742,1732,
+1717,1696,1675,1654,1626,1591,1557,1532,1515,1506,1506,1510,1507,1496,1488,1491,1499,1500,1490,1476,1462,
+1451,1441,1434,1431,1434,1444,1456,1461,1460,1462,1472,1485,1489,1481,1470,1476,1513,1571,1616,1619,1589,
+1564,1565,1579,1579,1569,1568,1579,1580,1564,1550,1554,1566,1567,1561,1571,1600,1627,1640,1649,1663,1673,
+1674,1672,1680,1691,1693,1690,1697,1708,1705,1679,1648,1628,1615,1595,1567,1539,1518,1502,1491,1484,1478,
+1470,1462,1455,1446,1432,1414,1396,1381,1366,1350,1333,1311,1284,1255,1228,1202,1175,1155,1145,1138,1124,
+1100,1076,1056,1040,1023,1003,977,938,892,847,810,778,747,717,685,651,614,580,547,512,474,
+437,403,367,330,293,256,217,176,138,101,63,19,-24,-65,-102,-137,-173,-214,-258,-302,-343,
+-382,-423,-465,-503,-537,-573,-611,-646,-675,-703,-731,-760,-793,-832,-871,-903,-930,-961,-997,-1030,-1056,
+-1082,-1114,-1147,-1176,-1205,-1236,-1270,-1303,-1337,-1376,-1414,-1448,-1479,-1510,-1541,-1567,-1593,-1624,-1659,-1691,-1719,
+-1750,-1784,-1818,-1849,-1878,-1908,-1941,-1976,-2008,-2035,-2058,-2081,-2103,-2122,-2141,-2162,-2187,-2210,-2231,-2252,-2273,
+-2293,-2310,-2329,-2349,-2364,-2373,-2382,-2394,-2407,-2417,-2425,-2435,-2443,-2450,-2456,-2464,-2469,-2468,-2467,-2470,-2472,
+-2467,-2459,-2451,-2443,-2434,-2422,-2409,-2394,-2378,-2363,-2348,-2331,-2313,-2296,-2282,-2269,-2255,-2242,-2233,-2222,-2207,
+-2190,-2173,-2156,-2137,-2117,-2100,-2082,-2061,-2042,-2027,-2014,-1998,-1980,-1963,-1949,-1935,-1921,-1906,-1890,-1872,-1855,
+-1842,-1830,-1811,-1790,-1771,-1758,-1746,-1730,-1714,-1699,-1684,-1669,-1654,-1639,-1622,-1601,-1579,-1559,-1540,-1522,-1503,
+-1482,-1461,-1443,-1424,-1402,-1377,-1358,-1345,-1329,-1308,-1286,-1268,-1249,-1226,-1205,-1191,-1176,-1156,-1136,-1120,-1106,
+-1084,-1061,-1044,-1029,-1006,-976,-947,-919,-884,-845,-812,-788,-764,-736,-710,-686,-656,-615,-563,-502,-440,
+-395,-381,-385,-377,-350,-321,-302,-285,-256,-225,-202,-181,-150,-112,-80,-52,-21,11,39,68,103,
+138,167,199,250,319,388,449,510,579,647,709,775,852,917,935,899,852,867,984,1184,1403,
+1589,1744,1899,2074,2258,2426,2551,2599,2541,2383,2174,1979,1843,1780,1790,1853,1930,1982,1993,1976,1969,
+2007,2095,2183,2209,2151,2055,1983,1957,1960,1975,1993,1995,1954,1874,1792,1725,1649,1534,1391,1260,1167,
+1103,1051,995,919,808,670,532,416,324,245,174,118,76,41,4,-45,-113,-202,-303,-397,-471,
+-529,-581,-632,-683,-733,-786,-836,-870,-884,-901,-942,-1006,-1071,-1130,-1196,-1277,-1358,-1427,-1493,-1571,-1656,
+-1734,-1804,-1884,-1975,-2062,-2132,-2190,-2248,-2304,-2353,-2394,-2432,-2471,-2507,-2541,-2575,-2608,-2636,-2653,-2665,-2677,
+-2680,-2658,-2608,-2557,-2533,-2531,-2520,-2484,-2440,-2415,-2414,-2432,-2474,-2543,-2627,-2695,-2734,-2752,-2757,-2746,-2721,
+-2696,-2678,-2659,-2633,-2605,-2581,-2559,-2529,-2491,-2455,-2440,-2455,-2489,-2520,-2537,-2553,-2585,-2622,-2630,-2593,-2528,
+-2466,-2417,-2375,-2329,-2275,-2206,-2128,-2058,-2012,-1982,-1943,-1884,-1817,-1764,-1726,-1687,-1631,-1563,-1501,-1452,-1405,
+-1347,-1287,-1239,-1206,-1170,-1119,-1057,-996,-938,-881,-824,-770,-720,-672,-624,-568,-501,-426,-354,-293,-241,
+-192,-142,-87,-31,26,82,140,198,250,290,328,377,439,496,536,566,597,632,665,696,733,
+776,814,835,844,857,884,922,957,981,999,1018,1034,1038,1040,1054,1084,1116,1140,1160,1179,1192,
+1192,1186,1176,1160,1140,1131,1143,1166,1184,1192,1204,1229,1268,1317,1372,1422,1462,1492,1519,1552,1600,
+1670,1758,1836,1878,1881,1863,1839,1814,1798,1804,1829,1860,1882,1892,1896,1900,1912,1933,1955,1966,1968,
+1973,1986,2004,2016,2016,2007,1993,1979,1965,1950,1934,1923,1919,1919,1917,1916,1917,1917,1912,1906,1904,
+1904,1901,1893,1885,1878,1869,1859,1852,1845,1834,1822,1812,1804,1793,1783,1777,1771,1758,1742,1733,1731,
+1726,1717,1712,1714,1715,1719,1711,1702,1698,1689,1674,1660,1658,1662,1662,1661,1668,1678,1679,1669,1660,
+1657,1656,1650,1640,1630,1616,1602,1613,1677,1782,1857,1822,1669,1485,1375,1356,1360,1327,1274,1249,1246,
+1208,1103,971,887,881,922,961,973,959,930,898,865,826,772,697,615,542,482,416,322,198,
+68,-44,-132,-206,-274,-334,-393,-468,-570,-687,-798,-891,-974,-1058,-1146,-1234,-1320,-1395,-1452,-1495,-1539,
+-1602,-1680,-1755,-1817,-1861,-1890,-1905,-1916,-1939,-1977,-2013,-2030,-2030,-2032,-2042,-2054,-2056,-2043,-2012,-1967,-1922,
+-1882,-1844,-1797,-1748,-1711,-1683,-1644,-1586,-1528,-1486,-1432,-1326,-1169,-1011,-900,-836,-796,-779,-806,-874,-946,
+-995,-1034,-1093,-1168,-1224,-1238,-1230,-1226,-1234,-1250,-1284,-1348,-1430,-1502,-1552,-1595,-1636,-1647,-1594,-1490,-1396,
+-1369,-1404,-1446,-1441,-1378,-1305,-1291,-1377,-1549,-1743,-1897,-1994,-2065,-2150,-2261,-2383,-2496,-2592,-2672,-2746,-2824,
+-2911,-3004,-3092,-3172,-3242,-3292,-3317,-3331,-3375,-3476,-3626,-3790,-3938,-4060,-4153,-4220,-4274,-4327,-4382,-4425,-4458,
+-4499,-4566,-4651,-4726,-4776,-4810,-4844,-4886,-4930,-4969,-4996,-5002,-4982,-4942,-4902,-4884,-4892,-4914,-4932,-4940,-4940,
+-4937,-4934,-4940,-4958,-4981,-4999,-5012,-5024,-5037,-5049,-5061,-5082,-5114,-5151,-5180,-5198,-5206,-5216,-5242,-5293,-5364,
+-5436,-5500,-5555,-5611,-5671,-5733,-5796,-5857,-5917,-5976,-6040,-6112,-6183,-6244,-6299,-6358,-6425,-6497,-6565,-6623,-6675,
+-6729,-6789,-6857,-6928,-6999,-7069,-7138,-7202,-7257,-7306,-7356,-7414,-7480,-7547,-7609,-7673,-7737,-7794,-7840,-7885,-7943,
+-8016,-8089,-8153,-8225,-8319,-8427,-8525,-8606,-8683,-8765,-8844,-8919,-8997,-9078,-9149,-9206,-9265,-9334,-9400,-9452,-9506,
+-9564,-9587,-9536,-9449,-9417,-9482,-9588,-9671,-9737,-9833,-9954,-10041,-10064,-10055,-10061,-10091,-10131,-10171,-10212,-10245,-10262,
+-10272,-10285,-10299,-10305,-10305,-10307,-10310,-10306,-10299,-10292,-10286,-10276,-10261,-10240,-10204,-10146,-10078,-10007,-9919,-9799,-9657,
+-9533,-9457,-9425,-9407,-9377,-9324,-9248,-9154,-9052,-8946,-8833,-8710,-8579,-8443,-8307,-8172,-8043,-7919,-7795,-7668,-7531,
+-7382,-7234,-7104,-6997,-6889,-6759,-6612,-6472,-6351,-6232,-6097,-5948,-5800,-5661,-5532,-5412,-5294,-5167,-5022,-4861,-4692,
+-4522,-4348,-4172,-3998,-3841,-3705,-3572,-3416,-3239,-3084,-2990,-2966,-2993,-3036,-3033,-2912,-2653,-2335,-2068,-1876,-1694,
+-1484,-1291,-1175,-1108,-1010,-851,-675,-531,-427,-341,-255,-159,-54,53,160,270,388,498,588,668,763,
+876,992,1101,1208,1314,1413,1501,1587,1680,1782,1891,2002,2107,2203,2297,2397,2495,2585,2678,2790,2909,
+3011,3096,3186,3287,3384,3469,3552,3634,3711,3791,3889,4004,4105,4185,4273,4397,4544,4681,4797,4909,5031,
+5161,5289,5398,5477,5524,5549,5560,5557,5545,5544,5563,5579,5551,5461,5344,5264,5268,5333,5388,5398,5417,
+5512,5681,5852,5981,6079,6160,6216,6252,6289,6306,6241,6079,5895,5765,5683,5626,5636,5753,5911,5979,5909,
+5754,5559,5320,5064,4907,4964,5262,5753,6346,6903,7279,7423,7414,7369,7341,7335,7362,7433,7512,7560,7579,
+7599,7618,7614,7591,7571,7538,7465,7375,7329,7342,7367,7367,7364,7378,7383,7347,7283,7222,7165,7087,6991,
+6912,6865,6841,6832,6846,6883,6923,6948,6966,6995,7037,7072,7091,7100,7114,7131,7147,7162,7182,7205,7217,
+7213,7202,7195,7197,7199,7199,7199,7198,7194,7185,7170,7149,7119,7084,7048,7014,6979,6945,6912,6881,6855,
+6831,6802,6759,6707,6664,6631,6601,6581,6589,6611,6584,6463,6299,6205,6234,6320,6356,6306,6217,6144,6100,
+6064,6022,5979,5939,5901,5859,5814,5778,5755,5745,5747,5772,5823,5878,5902,5884,5847,5827,5832,5845,5842,
+5807,5743,5668,5598,5536,5481,5433,5395,5353,5290,5207,5126,5063,5012,4961,4914,4880,4850,4802,4731,4650,
+4579,4527,4491,4459,4424,4388,4358,4332,4296,4249,4203,4171,4144,4105,4056,4009,3969,3931,3892,3855,3820,
+3785,3749,3715,3682,3643,3596,3544,3490,3430,3364,3296,3237,3197,3181,3185,3188,3167,3118,3052,2981,2911,
+2843,2784,2754,2775,2848,2937,2976,2918,2778,2632,2552,2545,2561,2550,2510,2470,2444,2418,2378,2335,2311,
+2307,2301,2279,2250,2226,2208,2191,2175,2160,2139,2108,2078,2057,2041,2016,1987,1971,1972,1975,1960,1931,
+1908,1906,1920,1935,1930,1899,1857,1819,1794,1775,1759,1747,1739,1729,1713,1693,1673,1646,1610,1570,1536,
+1517,1511,1513,1515,1509,1499,1493,1498,1511,1520,1516,1498,1474,1455,1448,1450,1453,1455,1460,1466,1468,
+1464,1460,1461,1465,1463,1457,1456,1477,1531,1603,1653,1651,1608,1569,1561,1568,1566,1556,1560,1579,1591,
+1585,1571,1563,1557,1547,1549,1578,1620,1648,1654,1657,1667,1670,1658,1646,1652,1667,1671,1662,1662,1676,
+1688,1680,1657,1633,1613,1591,1565,1541,1519,1501,1488,1482,1474,1460,1448,1444,1442,1432,1413,1395,1381,
+1366,1349,1330,1311,1290,1265,1238,1210,1183,1163,1154,1149,1136,1111,1082,1057,1037,1020,1003,979,945,
+903,863,828,796,764,732,700,664,625,589,554,518,480,442,409,376,340,305,271,235,196,
+159,124,88,48,6,-34,-72,-109,-145,-184,-225,-267,-307,-347,-390,-436,-479,-518,-556,-592,-623,
+-651,-677,-706,-738,-774,-816,-854,-883,-906,-934,-970,-1003,-1028,-1053,-1084,-1117,-1146,-1174,-1206,-1240,-1273,
+-1307,-1345,-1383,-1418,-1449,-1481,-1512,-1540,-1566,-1595,-1628,-1660,-1691,-1723,-1758,-1792,-1823,-1853,-1886,-1921,-1954,
+-1982,-2005,-2027,-2050,-2074,-2095,-2114,-2134,-2156,-2178,-2198,-2219,-2241,-2260,-2277,-2295,-2313,-2325,-2332,-2339,-2351,
+-2363,-2373,-2383,-2395,-2407,-2415,-2422,-2429,-2434,-2433,-2433,-2436,-2438,-2432,-2423,-2416,-2413,-2406,-2392,-2376,-2361,
+-2347,-2331,-2314,-2297,-2279,-2263,-2249,-2234,-2219,-2207,-2199,-2190,-2176,-2159,-2144,-2129,-2111,-2092,-2074,-2056,-2037,
+-2019,-2006,-1993,-1975,-1953,-1935,-1922,-1911,-1900,-1889,-1875,-1858,-1843,-1831,-1819,-1800,-1778,-1761,-1748,-1737,-1722,
+-1706,-1692,-1679,-1666,-1652,-1637,-1618,-1597,-1576,-1556,-1536,-1517,-1499,-1480,-1460,-1442,-1424,-1406,-1384,-1363,-1345,
+-1330,-1312,-1293,-1273,-1252,-1230,-1210,-1195,-1178,-1158,-1138,-1123,-1108,-1089,-1069,-1052,-1037,-1018,-994,-969,-943,
+-911,-877,-849,-826,-806,-786,-765,-736,-696,-654,-610,-554,-482,-420,-397,-404,-402,-375,-343,-325,-309,
+-281,-248,-226,-207,-176,-138,-107,-82,-54,-20,13,44,77,111,143,182,239,309,377,442,515,
+592,662,729,809,899,958,949,892,853,895,1030,1224,1428,1612,1786,1969,2162,2341,2472,2529,2487,
+2344,2137,1938,1805,1747,1742,1775,1836,1908,1959,1975,1965,1960,1989,2058,2130,2150,2096,2006,1933,1899,
+1892,1905,1934,1953,1926,1850,1771,1711,1643,1525,1372,1236,1150,1099,1055,1000,924,818,689,561,456,
+371,293,217,150,89,29,-33,-95,-157,-226,-303,-378,-443,-500,-555,-609,-660,-712,-766,-814,-844,
+-856,-873,-915,-975,-1035,-1090,-1154,-1231,-1309,-1379,-1450,-1532,-1618,-1696,-1769,-1847,-1933,-2014,-2084,-2146,-2204,
+-2256,-2301,-2341,-2380,-2417,-2453,-2492,-2535,-2575,-2600,-2610,-2614,-2620,-2619,-2593,-2540,-2489,-2465,-2466,-2462,-2434,
+-2398,-2376,-2377,-2398,-2444,-2515,-2593,-2654,-2692,-2714,-2722,-2711,-2689,-2672,-2663,-2654,-2635,-2611,-2592,-2580,-2563,
+-2530,-2478,-2421,-2383,-2374,-2381,-2394,-2423,-2485,-2564,-2613,-2602,-2544,-2478,-2428,-2393,-2358,-2305,-2226,-2133,-2054,
+-2003,-1970,-1933,-1886,-1839,-1800,-1764,-1717,-1654,-1585,-1524,-1474,-1427,-1374,-1318,-1271,-1239,-1208,-1163,-1105,-1044,
+-988,-936,-884,-831,-781,-735,-690,-636,-568,-493,-420,-358,-304,-254,-205,-155,-100,-43,15,75,135,
+189,227,260,306,367,429,476,513,550,591,631,669,711,754,793,821,841,859,886,924,963,
+994,1016,1033,1044,1043,1036,1039,1057,1079,1095,1106,1120,1131,1132,1127,1122,1118,1115,1121,1143,1178,
+1215,1245,1269,1289,1313,1354,1415,1484,1540,1575,1591,1600,1619,1664,1733,1801,1842,1853,1850,1848,1848,
+1854,1872,1899,1921,1933,1939,1944,1946,1946,1946,1945,1939,1931,1929,1939,1959,1976,1983,1977,1966,1955,
+1947,1940,1933,1928,1925,1921,1916,1914,1920,1926,1927,1928,1933,1937,1934,1923,1911,1898,1882,1866,1851,
+1839,1825,1813,1804,1796,1783,1770,1764,1759,1747,1733,1727,1728,1726,1718,1715,1718,1719,1716,1707,1701,
+1701,1699,1687,1672,1669,1675,1681,1683,1687,1694,1695,1686,1672,1661,1653,1644,1634,1625,1614,1607,1622,
+1680,1767,1819,1773,1633,1479,1393,1377,1366,1317,1256,1229,1234,1219,1141,1015,900,844,853,892,915,
+899,855,812,783,760,724,670,607,550,496,427,324,192,61,-40,-115,-180,-247,-311,-374,-451,
+-556,-687,-820,-933,-1018,-1081,-1141,-1217,-1316,-1422,-1507,-1563,-1605,-1661,-1733,-1805,-1862,-1904,-1936,-1957,-1967,
+-1977,-1995,-2020,-2044,-2063,-2082,-2100,-2112,-2111,-2090,-2051,-1998,-1947,-1902,-1860,-1813,-1768,-1739,-1717,-1680,-1617,
+-1548,-1490,-1424,-1313,-1152,-977,-828,-722,-669,-685,-773,-893,-981,-1022,-1054,-1115,-1186,-1221,-1213,-1198,-1208,
+-1237,-1272,-1323,-1406,-1504,-1576,-1611,-1641,-1691,-1737,-1723,-1629,-1499,-1405,-1383,-1405,-1404,-1342,-1249,-1210,-1296,
+-1500,-1740,-1925,-2031,-2099,-2181,-2292,-2412,-2521,-2615,-2698,-2774,-2853,-2939,-3034,-3127,-3208,-3267,-3298,-3305,-3321,
+-3391,-3534,-3721,-3900,-4037,-4131,-4193,-4240,-4284,-4337,-4392,-4435,-4465,-4501,-4562,-4641,-4717,-4775,-4816,-4850,-4885,
+-4922,-4959,-4984,-4984,-4954,-4912,-4881,-4877,-4893,-4911,-4921,-4921,-4916,-4909,-4903,-4908,-4927,-4952,-4974,-4990,-5003,
+-5014,-5024,-5040,-5066,-5099,-5132,-5156,-5170,-5178,-5191,-5226,-5289,-5366,-5436,-5491,-5539,-5592,-5651,-5711,-5772,-5831,
+-5888,-5944,-6008,-6081,-6153,-6216,-6274,-6340,-6415,-6488,-6552,-6609,-6667,-6728,-6789,-6851,-6918,-6990,-7065,-7140,-7206,
+-7261,-7306,-7349,-7399,-7459,-7525,-7590,-7654,-7716,-7771,-7818,-7863,-7917,-7980,-8042,-8105,-8183,-8285,-8395,-8489,-8568,
+-8646,-8728,-8804,-8874,-8947,-9026,-9097,-9158,-9222,-9298,-9370,-9427,-9483,-9541,-9568,-9530,-9464,-9445,-9500,-9581,-9644,
+-9710,-9819,-9947,-10031,-10046,-10033,-10037,-10065,-10101,-10140,-10181,-10211,-10224,-10231,-10244,-10260,-10270,-10275,-10282,-10289,-10290,
+-10284,-10277,-10268,-10255,-10236,-10209,-10165,-10104,-10035,-9960,-9865,-9734,-9591,-9482,-9431,-9417,-9399,-9356,-9286,-9197,-9094,
+-8986,-8879,-8770,-8657,-8536,-8408,-8277,-8146,-8021,-7903,-7789,-7668,-7530,-7373,-7212,-7075,-6967,-6866,-6742,-6594,-6449,
+-6323,-6208,-6086,-5951,-5809,-5669,-5538,-5418,-5302,-5174,-5026,-4862,-4694,-4523,-4344,-4159,-3982,-3832,-3704,-3572,-3408,
+-3230,-3084,-2999,-2962,-2953,-2967,-2975,-2907,-2708,-2417,-2132,-1901,-1698,-1499,-1341,-1251,-1187,-1077,-906,-716,-543,
+-398,-282,-196,-116,-18,94,198,292,398,520,635,729,820,926,1041,1150,1251,1349,1441,1530,1619,
+1712,1805,1898,1998,2102,2204,2305,2408,2509,2601,2694,2806,2929,3041,3132,3216,3303,3390,3471,3553,3638,
+3718,3796,3884,3984,4079,4165,4262,4390,4536,4671,4787,4899,5017,5139,5255,5353,5423,5461,5478,5485,5484,
+5475,5464,5464,5474,5480,5454,5380,5281,5215,5222,5284,5363,5455,5578,5719,5834,5909,5974,6050,6124,6193,
+6272,6336,6312,6164,5952,5764,5613,5480,5394,5406,5481,5509,5429,5270,5079,4871,4677,4581,4684,5030,5593,
+6264,6855,7195,7267,7222,7215,7266,7309,7322,7350,7419,7508,7592,7660,7704,7710,7684,7633,7548,7426,7314,
+7274,7309,7359,7378,7376,7373,7362,7332,7301,7294,7295,7268,7198,7099,6989,6880,6796,6763,6779,6813,6839,
+6861,6899,6956,7010,7042,7061,7085,7119,7150,7174,7198,7222,7238,7237,7230,7230,7234,7234,7229,7228,7231,
+7230,7224,7212,7190,7155,7114,7075,7038,6997,6954,6920,6892,6862,6827,6792,6753,6703,6649,6604,6569,6542,
+6535,6554,6557,6481,6330,6206,6203,6297,6366,6332,6235,6161,6140,6130,6092,6030,5971,5925,5884,5843,5814,
+5804,5805,5814,5835,5873,5917,5940,5932,5905,5881,5871,5868,5860,5832,5779,5710,5640,5575,5514,5459,5410,
+5364,5309,5241,5169,5103,5041,4980,4925,4882,4845,4801,4744,4674,4599,4530,4476,4438,4406,4377,4354,4333,
+4304,4262,4219,4186,4157,4115,4062,4011,3971,3938,3907,3878,3849,3820,3788,3753,3713,3666,3615,3563,3509,
+3447,3383,3324,3272,3228,3194,3176,3165,3147,3113,3065,3006,2937,2862,2797,2760,2760,2794,2845,2877,2850,
+2754,2630,2540,2516,2534,2547,2531,2497,2465,2438,2404,2366,2338,2323,2312,2295,2275,2257,2238,2214,2191,
+2173,2157,2137,2115,2094,2069,2036,2005,1991,1993,1990,1969,1936,1905,1881,1874,1888,1907,1906,1871,1822,
+1786,1769,1759,1749,1740,1731,1717,1701,1684,1665,1633,1589,1547,1524,1521,1527,1531,1528,1518,1509,1505,
+1511,1521,1523,1508,1482,1462,1460,1469,1476,1475,1471,1470,1467,1461,1452,1445,1440,1437,1437,1444,1467,
+1514,1575,1620,1622,1590,1559,1551,1555,1552,1545,1551,1572,1591,1595,1590,1578,1560,1544,1551,1588,1631,
+1649,1646,1648,1664,1672,1659,1641,1641,1654,1657,1645,1638,1651,1671,1676,1662,1639,1615,1591,1569,1548,
+1526,1506,1493,1485,1473,1454,1436,1430,1430,1420,1401,1384,1373,1361,1345,1329,1314,1296,1272,1245,1217,
+1191,1171,1159,1151,1136,1111,1082,1054,1029,1006,983,960,930,895,860,827,795,763,733,703,670,
+633,598,566,529,488,447,411,378,343,309,276,243,208,173,139,105,67,27,-12,-51,-89,
+-127,-164,-203,-242,-280,-319,-363,-411,-459,-503,-542,-576,-605,-631,-657,-686,-718,-756,-798,-836,-863,
+-883,-909,-943,-975,-1000,-1026,-1057,-1089,-1117,-1143,-1175,-1211,-1246,-1280,-1315,-1351,-1385,-1417,-1449,-1481,-1510,
+-1538,-1567,-1600,-1632,-1664,-1696,-1729,-1761,-1793,-1826,-1860,-1893,-1922,-1946,-1968,-1992,-2018,-2045,-2070,-2090,-2110,
+-2130,-2149,-2168,-2190,-2212,-2230,-2246,-2262,-2278,-2288,-2294,-2303,-2314,-2325,-2333,-2344,-2359,-2373,-2381,-2387,-2394,
+-2399,-2399,-2397,-2399,-2400,-2394,-2385,-2381,-2380,-2373,-2358,-2341,-2327,-2314,-2298,-2280,-2262,-2244,-2230,-2216,-2201,
+-2187,-2176,-2168,-2158,-2142,-2124,-2109,-2096,-2079,-2060,-2042,-2025,-2008,-1993,-1980,-1967,-1950,-1932,-1917,-1904,-1893,
+-1882,-1871,-1859,-1844,-1829,-1819,-1807,-1791,-1771,-1755,-1743,-1729,-1713,-1698,-1685,-1672,-1660,-1646,-1630,-1610,-1590,
+-1572,-1554,-1534,-1514,-1497,-1480,-1460,-1440,-1423,-1409,-1391,-1369,-1348,-1329,-1313,-1295,-1277,-1256,-1236,-1218,-1202,
+-1186,-1167,-1147,-1129,-1114,-1099,-1085,-1073,-1058,-1040,-1019,-996,-969,-937,-906,-879,-858,-845,-838,-820,-770,
+-695,-631,-595,-566,-514,-457,-428,-429,-423,-392,-359,-340,-325,-295,-263,-242,-224,-195,-159,-131,-109,
+-80,-43,-7,23,55,89,126,173,234,302,369,442,528,616,691,766,861,956,998,966,904,
+886,949,1081,1253,1439,1623,1808,2000,2203,2390,2520,2548,2453,2252,2015,1827,1731,1707,1716,1746,1804,
+1881,1941,1963,1959,1955,1973,2018,2068,2086,2048,1972,1898,1850,1829,1832,1856,1871,1843,1771,1697,1648,
+1596,1500,1371,1255,1178,1123,1063,992,910,810,696,585,495,417,337,255,180,112,44,-26,-95,
+-159,-226,-294,-358,-413,-467,-525,-582,-634,-685,-741,-791,-822,-836,-852,-889,-942,-996,-1051,-1115,-1189,
+-1262,-1331,-1405,-1490,-1581,-1666,-1741,-1814,-1887,-1957,-2022,-2080,-2130,-2174,-2218,-2263,-2306,-2346,-2386,-2435,-2491,
+-2540,-2565,-2565,-2555,-2547,-2538,-2515,-2476,-2438,-2421,-2421,-2415,-2394,-2368,-2356,-2365,-2396,-2447,-2511,-2569,-2611,
+-2641,-2666,-2678,-2669,-2649,-2639,-2644,-2652,-2647,-2629,-2606,-2586,-2568,-2539,-2487,-2416,-2355,-2323,-2315,-2316,-2334,
+-2390,-2479,-2555,-2577,-2541,-2476,-2416,-2375,-2348,-2313,-2249,-2160,-2076,-2017,-1976,-1937,-1895,-1856,-1818,-1770,-1711,
+-1648,-1589,-1533,-1483,-1435,-1387,-1335,-1285,-1244,-1208,-1164,-1109,-1047,-990,-939,-891,-843,-795,-751,-706,-654,
+-589,-518,-450,-387,-328,-274,-226,-179,-127,-71,-14,42,97,145,182,215,260,320,380,428,468,
+511,558,602,643,683,723,759,790,813,834,860,898,942,981,1009,1028,1038,1034,1019,1006,1006,
+1012,1018,1023,1035,1050,1065,1080,1103,1132,1159,1180,1201,1227,1260,1291,1307,1300,1285,1291,1335,1407,
+1483,1547,1594,1625,1651,1688,1740,1793,1826,1840,1849,1862,1876,1889,1904,1920,1931,1936,1941,1947,1947,
+1938,1924,1911,1900,1890,1886,1894,1912,1932,1945,1948,1945,1943,1944,1949,1954,1956,1953,1944,1933,1929,
+1933,1940,1942,1944,1950,1953,1946,1931,1916,1901,1885,1865,1847,1828,1810,1796,1789,1784,1773,1763,1758,
+1755,1746,1735,1731,1733,1730,1721,1715,1717,1716,1719,1714,1710,1711,1708,1697,1684,1682,1692,1700,1701,
+1699,1700,1701,1696,1682,1666,1652,1640,1628,1613,1601,1597,1610,1644,1684,1693,1641,1543,1451,1406,1398,
+1381,1331,1269,1229,1217,1205,1154,1051,926,835,812,838,855,828,773,729,711,703,684,649,608,
+567,517,440,328,195,72,-18,-85,-152,-227,-300,-364,-432,-528,-660,-815,-960,-1065,-1121,-1153,-1202,
+-1294,-1414,-1527,-1607,-1664,-1722,-1789,-1855,-1907,-1947,-1982,-2007,-2017,-2014,-2013,-2029,-2059,-2093,-2120,-2135,-2141,
+-2136,-2117,-2080,-2027,-1969,-1916,-1868,-1823,-1785,-1761,-1742,-1705,-1638,-1562,-1497,-1428,-1319,-1156,-964,-789,-671,
+-639,-706,-845,-982,-1052,-1060,-1068,-1117,-1179,-1209,-1206,-1208,-1241,-1288,-1335,-1394,-1481,-1577,-1644,-1674,-1696,
+-1739,-1782,-1778,-1697,-1566,-1449,-1392,-1386,-1374,-1312,-1231,-1215,-1332,-1559,-1804,-1980,-2072,-2130,-2210,-2321,-2442,
+-2552,-2648,-2734,-2812,-2890,-2975,-3066,-3153,-3222,-3266,-3288,-3304,-3351,-3462,-3639,-3838,-4003,-4110,-4170,-4208,-4244,
+-4285,-4334,-4381,-4418,-4449,-4492,-4558,-4636,-4707,-4763,-4808,-4846,-4880,-4913,-4944,-4963,-4955,-4920,-4880,-4862,-4870,
+-4889,-4901,-4901,-4896,-4888,-4879,-4874,-4880,-4898,-4924,-4947,-4965,-4978,-4986,-4997,-5017,-5045,-5075,-5102,-5125,-5145,
+-5162,-5186,-5229,-5297,-5371,-5433,-5480,-5526,-5578,-5631,-5683,-5739,-5798,-5855,-5910,-5972,-6044,-6118,-6183,-6244,-6313,
+-6391,-6468,-6537,-6601,-6667,-6733,-6793,-6848,-6908,-6979,-7057,-7134,-7199,-7252,-7297,-7340,-7388,-7444,-7506,-7569,-7631,
+-7691,-7746,-7793,-7836,-7882,-7937,-7997,-8065,-8149,-8251,-8355,-8445,-8524,-8605,-8688,-8762,-8828,-8901,-8982,-9056,-9119,
+-9183,-9260,-9337,-9400,-9457,-9509,-9530,-9502,-9457,-9452,-9498,-9555,-9601,-9671,-9793,-9929,-10009,-10019,-10004,-10009,-10034,
+-10066,-10101,-10138,-10167,-10178,-10186,-10202,-10222,-10235,-10244,-10253,-10264,-10268,-10264,-10255,-10241,-10220,-10195,-10163,-10120,-10061,
+-9994,-9917,-9815,-9682,-9549,-9459,-9427,-9420,-9396,-9338,-9255,-9157,-9051,-8943,-8840,-8739,-8633,-8519,-8395,-8265,-8135,
+-8013,-7901,-7795,-7678,-7537,-7371,-7203,-7057,-6939,-6823,-6686,-6530,-6381,-6257,-6153,-6053,-5944,-5819,-5682,-5548,-5427,
+-5312,-5181,-5024,-4854,-4689,-4527,-4353,-4163,-3977,-3823,-3700,-3573,-3411,-3233,-3090,-3008,-2960,-2916,-2887,-2882,-2850,
+-2720,-2484,-2206,-1948,-1727,-1551,-1435,-1369,-1295,-1166,-993,-808,-616,-419,-251,-141,-63,34,156,259,331,
+410,524,651,758,851,950,1059,1166,1268,1366,1458,1547,1639,1734,1823,1907,1995,2094,2197,2300,2405,
+2510,2606,2696,2800,2926,3053,3160,3247,3328,3406,3482,3560,3645,3733,3817,3902,3995,4093,4195,4304,4421,
+4539,4650,4761,4877,4994,5102,5194,5268,5321,5356,5384,5412,5433,5437,5423,5406,5410,5446,5483,5463,5365,
+5249,5203,5259,5372,5495,5610,5713,5790,5848,5916,6006,6097,6178,6269,6353,6360,6243,6047,5853,5671,5469,
+5270,5150,5123,5105,5014,4847,4658,4491,4378,4361,4494,4824,5360,6020,6611,6944,7010,6988,7045,7172,7249,
+7238,7221,7281,7409,7542,7640,7697,7719,7705,7647,7541,7414,7334,7351,7441,7524,7544,7507,7452,7396,7348,
+7329,7352,7404,7445,7439,7368,7235,7073,6927,6833,6790,6773,6764,6767,6792,6836,6882,6919,6957,7008,7071,
+7127,7164,7190,7214,7238,7255,7267,7276,7277,7268,7260,7262,7267,7261,7246,7226,7197,7153,7105,7066,7033,
+6996,6962,6948,6942,6917,6872,6829,6795,6755,6702,6654,6621,6593,6567,6561,6564,6519,6396,6261,6216,6271,
+6323,6292,6209,6163,6179,6199,6164,6085,6008,5959,5927,5897,5870,5856,5860,5878,5903,5925,5937,5938,5937,
+5936,5933,5919,5897,5874,5847,5806,5748,5680,5614,5553,5495,5438,5384,5331,5275,5214,5147,5074,5002,4943,
+4896,4854,4809,4759,4698,4624,4547,4483,4438,4404,4374,4350,4330,4305,4268,4228,4193,4159,4114,4060,4010,
+3969,3936,3911,3896,3886,3870,3838,3791,3735,3677,3624,3576,3527,3472,3414,3361,3309,3256,3209,3179,3164,
+3149,3123,3087,3037,2970,2892,2826,2781,2748,2720,2705,2719,2746,2746,2694,2611,2545,2521,2523,2518,2490,
+2453,2421,2396,2373,2352,2338,2329,2319,2305,2284,2253,2215,2185,2167,2155,2138,2121,2104,2082,2052,2024,
+2011,2009,2001,1981,1953,1915,1872,1844,1858,1899,1917,1880,1815,1769,1758,1759,1754,1742,1731,1718,1700,
+1686,1676,1656,1618,1575,1548,1544,1553,1562,1566,1563,1549,1529,1514,1512,1514,1507,1491,1479,1479,1486,
+1486,1477,1469,1467,1467,1463,1455,1444,1435,1434,1438,1442,1449,1469,1505,1541,1557,1553,1544,1542,1542,
+1537,1532,1538,1553,1568,1578,1584,1581,1565,1551,1559,1589,1615,1616,1605,1610,1639,1665,1664,1648,1641,
+1647,1648,1637,1629,1637,1655,1664,1656,1639,1619,1600,1581,1562,1540,1517,1500,1489,1475,1452,1430,1418,
+1412,1400,1382,1369,1362,1353,1340,1328,1316,1297,1270,1241,1216,1196,1178,1163,1150,1134,1111,1085,1057,
+1028,997,968,942,917,888,856,823,790,758,730,704,673,639,607,576,541,498,454,416,382,
+347,311,278,246,213,181,149,116,80,41,4,-33,-73,-112,-150,-188,-226,-264,-302,-344,-391,
+-438,-484,-524,-560,-589,-615,-642,-669,-700,-736,-776,-813,-839,-860,-884,-915,-945,-972,-999,-1032,-1064,
+-1089,-1113,-1144,-1180,-1216,-1250,-1284,-1319,-1352,-1385,-1418,-1450,-1479,-1508,-1538,-1571,-1604,-1636,-1668,-1699,-1729,
+-1762,-1798,-1832,-1860,-1884,-1906,-1930,-1957,-1985,-2014,-2040,-2064,-2084,-2103,-2120,-2139,-2161,-2182,-2199,-2214,-2230,
+-2245,-2255,-2263,-2273,-2285,-2294,-2300,-2311,-2326,-2340,-2347,-2352,-2360,-2366,-2366,-2363,-2363,-2362,-2357,-2351,-2348,
+-2346,-2337,-2321,-2305,-2292,-2280,-2265,-2247,-2229,-2211,-2196,-2183,-2171,-2159,-2150,-2141,-2128,-2110,-2091,-2077,-2064,
+-2049,-2030,-2012,-1996,-1981,-1967,-1953,-1940,-1926,-1913,-1903,-1891,-1878,-1864,-1853,-1841,-1826,-1812,-1802,-1792,-1779,
+-1764,-1751,-1737,-1722,-1705,-1689,-1676,-1664,-1650,-1636,-1620,-1602,-1584,-1569,-1553,-1534,-1514,-1498,-1482,-1463,-1440,
+-1422,-1410,-1395,-1375,-1352,-1332,-1315,-1300,-1283,-1265,-1247,-1229,-1214,-1200,-1185,-1167,-1148,-1131,-1118,-1109,-1099,
+-1084,-1066,-1047,-1023,-994,-962,-932,-906,-885,-880,-886,-869,-789,-663,-558,-520,-521,-508,-473,-447,-441,
+-428,-398,-369,-353,-336,-304,-271,-251,-233,-205,-172,-148,-126,-95,-56,-21,9,42,80,121,172,
+235,301,369,451,549,644,721,801,902,989,1007,953,900,919,1012,1147,1302,1474,1653,1832,2018,
+2225,2432,2578,2600,2474,2240,1982,1790,1696,1672,1677,1708,1775,1860,1923,1943,1939,1939,1953,1980,2014,
+2034,2018,1960,1886,1825,1791,1782,1788,1785,1748,1681,1617,1579,1544,1480,1392,1309,1241,1170,1082,987,
+896,804,707,616,537,461,376,289,212,145,77,6,-64,-132,-200,-267,-326,-378,-434,-496,-555,
+-605,-655,-711,-766,-803,-819,-833,-861,-907,-959,-1015,-1080,-1152,-1223,-1291,-1367,-1457,-1556,-1648,-1726,-1789,
+-1847,-1906,-1962,-2010,-2048,-2084,-2128,-2180,-2232,-2277,-2323,-2379,-2446,-2504,-2532,-2526,-2501,-2475,-2456,-2439,-2419,
+-2402,-2393,-2388,-2377,-2358,-2341,-2339,-2358,-2402,-2464,-2525,-2562,-2577,-2591,-2615,-2632,-2630,-2614,-2607,-2616,-2630,
+-2636,-2626,-2599,-2563,-2527,-2491,-2443,-2382,-2328,-2302,-2298,-2295,-2293,-2318,-2380,-2455,-2504,-2502,-2452,-2380,-2320,
+-2292,-2281,-2252,-2190,-2114,-2049,-1996,-1948,-1902,-1859,-1811,-1751,-1689,-1638,-1595,-1549,-1496,-1445,-1400,-1352,-1295,
+-1239,-1190,-1143,-1089,-1026,-963,-908,-860,-815,-770,-725,-680,-629,-571,-510,-451,-395,-339,-285,-237,-190,
+-140,-86,-33,17,65,111,150,191,241,301,357,401,441,487,536,582,623,660,696,727,754,
+776,795,821,860,911,957,989,1010,1022,1022,1006,986,975,973,974,976,983,997,1017,1046,1086,
+1134,1177,1203,1216,1229,1255,1283,1294,1275,1241,1226,1252,1313,1393,1478,1561,1632,1688,1738,1790,1836,
+1864,1875,1882,1891,1898,1901,1904,1907,1908,1908,1913,1921,1925,1922,1915,1910,1907,1905,1904,1908,1916,
+1927,1938,1945,1948,1949,1953,1959,1965,1969,1968,1960,1951,1949,1953,1956,1953,1950,1950,1948,1934,1914,
+1897,1884,1870,1855,1839,1822,1804,1790,1784,1781,1775,1767,1764,1762,1754,1743,1737,1736,1732,1723,1717,
+1718,1719,1735,1736,1733,1727,1719,1708,1702,1707,1717,1720,1712,1701,1697,1701,1701,1690,1670,1653,1640,
+1626,1608,1593,1591,1598,1605,1599,1575,1530,1477,1436,1418,1415,1406,1374,1320,1257,1204,1168,1128,1051,
+936,831,787,798,812,789,742,707,693,686,668,641,611,578,527,447,336,213,104,20,-55,
+-141,-237,-320,-379,-430,-505,-629,-796,-969,-1103,-1173,-1199,-1228,-1295,-1400,-1516,-1618,-1699,-1771,-1839,-1900,
+-1948,-1986,-2019,-2047,-2058,-2051,-2041,-2050,-2081,-2115,-2135,-2138,-2134,-2133,-2127,-2102,-2053,-1989,-1926,-1874,-1832,
+-1800,-1779,-1759,-1721,-1656,-1578,-1508,-1438,-1334,-1176,-983,-806,-698,-691,-780,-917,-1025,-1059,-1048,-1055,-1107,
+-1172,-1211,-1230,-1260,-1314,-1373,-1427,-1485,-1556,-1627,-1679,-1708,-1726,-1738,-1738,-1710,-1645,-1552,-1461,-1404,-1382,
+-1360,-1316,-1281,-1322,-1471,-1686,-1887,-2020,-2094,-2152,-2232,-2341,-2462,-2578,-2679,-2766,-2843,-2921,-3007,-3097,-3174,
+-3227,-3256,-3282,-3331,-3427,-3581,-3771,-3952,-4082,-4152,-4183,-4204,-4231,-4269,-4314,-4355,-4388,-4423,-4480,-4559,-4640,
+-4704,-4751,-4794,-4839,-4879,-4910,-4931,-4939,-4923,-4887,-4854,-4846,-4860,-4877,-4882,-4877,-4871,-4864,-4855,-4851,-4857,
+-4875,-4900,-4923,-4943,-4956,-4964,-4973,-4992,-5018,-5043,-5067,-5095,-5126,-5157,-5191,-5238,-5302,-5367,-5417,-5458,-5506,
+-5559,-5608,-5650,-5699,-5759,-5819,-5875,-5935,-6006,-6084,-6153,-6215,-6279,-6354,-6433,-6511,-6584,-6655,-6723,-6784,-6840,
+-6899,-6968,-7042,-7113,-7173,-7225,-7275,-7327,-7379,-7432,-7487,-7543,-7601,-7661,-7719,-7767,-7806,-7846,-7897,-7960,-8033,
+-8117,-8211,-8306,-8393,-8476,-8562,-8646,-8719,-8786,-8863,-8949,-9026,-9086,-9146,-9220,-9299,-9370,-9428,-9470,-9478,-9448,
+-9417,-9426,-9471,-9513,-9550,-9627,-9763,-9905,-9981,-9985,-9969,-9974,-9999,-10026,-10057,-10092,-10120,-10133,-10143,-10162,-10185,
+-10202,-10213,-10225,-10236,-10241,-10235,-10221,-10199,-10171,-10142,-10113,-10077,-10026,-9962,-9884,-9784,-9664,-9551,-9480,-9451,-9431,
+-9387,-9316,-9228,-9133,-9032,-8930,-8832,-8735,-8631,-8519,-8397,-8270,-8141,-8019,-7911,-7809,-7692,-7547,-7378,-7208,-7059,
+-6925,-6786,-6629,-6466,-6321,-6205,-6113,-6031,-5944,-5834,-5701,-5566,-5444,-5328,-5190,-5022,-4845,-4684,-4535,-4374,-4188,
+-3996,-3833,-3705,-3579,-3422,-3247,-3103,-3013,-2946,-2871,-2807,-2790,-2793,-2737,-2569,-2313,-2032,-1788,-1623,-1544,-1504,
+-1430,-1292,-1123,-944,-733,-481,-250,-103,-21,72,198,307,373,437,540,668,781,874,965,1062,1163,
+1267,1372,1470,1558,1649,1749,1845,1928,2009,2098,2193,2291,2396,2506,2606,2691,2784,2906,3046,3171,3266,
+3344,3418,3487,3557,3638,3735,3835,3930,4028,4142,4272,4397,4498,4575,4649,4742,4853,4962,5051,5116,5165,
+5203,5241,5292,5349,5396,5414,5403,5385,5393,5448,5515,5521,5425,5285,5216,5274,5412,5555,5670,5763,5834,
+5888,5944,6015,6091,6166,6250,6328,6340,6249,6100,5954,5794,5564,5278,5035,4894,4807,4685,4510,4337,4225,
+4195,4247,4387,4650,5079,5649,6208,6578,6725,6795,6931,7105,7193,7163,7123,7177,7313,7450,7540,7595,7634,
+7645,7603,7514,7430,7427,7529,7682,7792,7806,7740,7644,7551,7470,7411,7396,7437,7513,7573,7561,7462,7313,
+7166,7046,6948,6869,6813,6786,6776,6773,6779,6800,6845,6914,6997,7074,7131,7170,7200,7229,7258,7285,7302,
+7305,7299,7300,7309,7309,7288,7256,7224,7186,7137,7091,7064,7047,7025,7012,7028,7056,7052,7007,6963,6941,
+6919,6875,6828,6801,6777,6737,6697,6677,6642,6547,6415,6321,6295,6282,6227,6158,6142,6185,6221,6194,6118,
+6049,6018,6007,5986,5943,5895,5872,5888,5926,5952,5945,5923,5917,5936,5956,5950,5919,5883,5856,5826,5780,
+5718,5653,5594,5538,5480,5419,5361,5307,5253,5188,5111,5034,4973,4926,4883,4834,4778,4714,4642,4566,4501,
+4453,4415,4383,4356,4333,4305,4266,4225,4187,4151,4109,4063,4018,3975,3936,3909,3905,3914,3909,3875,3817,
+3750,3688,3635,3589,3544,3499,3456,3413,3360,3297,3241,3207,3190,3173,3147,3115,3072,3012,2940,2875,2822,
+2764,2690,2630,2633,2712,2809,2841,2776,2656,2552,2503,2491,2480,2455,2423,2394,2370,2354,2347,2349,2351,
+2342,2313,2266,2215,2179,2160,2145,2125,2105,2090,2076,2053,2030,2017,2013,2006,1993,1972,1932,1876,1836,
+1852,1907,1932,1884,1795,1735,1727,1739,1741,1736,1730,1721,1704,1689,1683,1674,1648,1612,1583,1573,1576,
+1584,1596,1604,1594,1567,1536,1516,1510,1506,1499,1494,1490,1484,1472,1462,1460,1469,1481,1487,1482,1469,
+1457,1452,1452,1448,1439,1436,1451,1480,1508,1525,1532,1532,1525,1517,1515,1520,1526,1533,1545,1559,1566,
+1561,1554,1560,1575,1580,1565,1550,1562,1600,1640,1654,1644,1631,1626,1624,1620,1617,1621,1629,1635,1634,
+1628,1618,1604,1588,1572,1552,1529,1508,1492,1477,1454,1430,1410,1396,1381,1366,1356,1349,1339,1328,1319,
+1308,1287,1256,1228,1209,1194,1179,1163,1150,1135,1116,1093,1069,1040,1007,975,948,923,896,865,831,
+797,764,736,709,678,644,611,581,547,505,463,425,389,352,314,278,245,212,181,151,120,
+88,54,20,-16,-55,-96,-135,-173,-211,-249,-287,-327,-370,-415,-460,-501,-538,-571,-600,-626,-652,
+-680,-713,-750,-786,-815,-838,-862,-890,-918,-945,-975,-1010,-1042,-1068,-1089,-1116,-1150,-1186,-1221,-1255,-1290,
+-1327,-1362,-1394,-1423,-1450,-1478,-1509,-1541,-1574,-1606,-1638,-1668,-1699,-1733,-1769,-1802,-1826,-1847,-1870,-1896,-1923,
+-1951,-1978,-2006,-2032,-2054,-2072,-2089,-2107,-2128,-2148,-2165,-2181,-2197,-2213,-2224,-2234,-2245,-2258,-2267,-2272,-2281,
+-2295,-2306,-2311,-2316,-2324,-2330,-2330,-2327,-2327,-2327,-2324,-2320,-2317,-2313,-2303,-2288,-2273,-2261,-2249,-2235,-2219,
+-2201,-2182,-2165,-2153,-2143,-2134,-2124,-2114,-2100,-2081,-2062,-2049,-2038,-2025,-2007,-1990,-1975,-1961,-1946,-1930,-1916,
+-1903,-1894,-1885,-1873,-1859,-1845,-1832,-1820,-1805,-1792,-1782,-1773,-1763,-1751,-1740,-1727,-1711,-1695,-1681,-1669,-1655,
+-1640,-1626,-1612,-1595,-1579,-1565,-1550,-1532,-1513,-1497,-1483,-1465,-1443,-1424,-1410,-1397,-1378,-1357,-1338,-1323,-1308,
+-1293,-1276,-1258,-1241,-1226,-1213,-1201,-1187,-1170,-1154,-1142,-1133,-1122,-1105,-1086,-1067,-1044,-1015,-986,-960,-934,
+-912,-909,-925,-909,-812,-648,-504,-448,-456,-463,-444,-423,-415,-403,-383,-367,-359,-343,-310,-277,-258,
+-240,-213,-183,-162,-139,-106,-68,-35,-1,40,84,129,180,244,311,381,467,569,663,738,817,
+914,983,968,896,864,934,1076,1228,1372,1520,1675,1837,2030,2269,2511,2666,2661,2494,2226,1949,1741,
+1636,1611,1632,1682,1758,1838,1887,1899,1898,1909,1929,1951,1977,2002,2002,1961,1893,1829,1785,1760,1743,
+1721,1681,1625,1574,1540,1511,1468,1413,1359,1299,1217,1112,1004,909,822,737,657,583,504,417,330,
+256,189,120,46,-24,-91,-159,-226,-287,-344,-405,-470,-529,-579,-629,-687,-743,-782,-799,-811,-836,
+-877,-929,-986,-1050,-1121,-1193,-1266,-1345,-1437,-1539,-1635,-1712,-1770,-1819,-1871,-1923,-1967,-1998,-2029,-2072,-2125,
+-2179,-2227,-2276,-2335,-2405,-2468,-2501,-2496,-2464,-2425,-2398,-2385,-2379,-2377,-2373,-2364,-2348,-2329,-2315,-2314,-2338,
+-2392,-2467,-2531,-2557,-2552,-2550,-2569,-2592,-2600,-2593,-2586,-2585,-2588,-2592,-2591,-2573,-2532,-2480,-2431,-2384,-2334,
+-2293,-2278,-2284,-2286,-2277,-2273,-2297,-2347,-2401,-2430,-2409,-2339,-2261,-2219,-2218,-2218,-2187,-2125,-2057,-1994,-1936,
+-1884,-1839,-1788,-1729,-1675,-1639,-1610,-1568,-1510,-1454,-1409,-1362,-1301,-1233,-1171,-1118,-1064,-1001,-935,-873,-821,
+-774,-730,-685,-640,-591,-541,-492,-446,-401,-353,-303,-254,-206,-155,-103,-53,-4,43,91,136,184,
+239,300,355,397,435,478,523,567,606,643,677,705,727,745,760,783,821,871,918,950,970,
+984,990,982,969,963,967,973,973,969,968,975,993,1023,1061,1096,1119,1131,1149,1182,1224,1253,
+1258,1251,1258,1289,1339,1398,1469,1551,1630,1699,1759,1818,1867,1896,1903,1901,1897,1894,1890,1888,1887,
+1885,1883,1885,1892,1903,1913,1923,1932,1940,1947,1952,1955,1956,1957,1961,1966,1969,1969,1968,1968,1967,
+1967,1966,1963,1961,1963,1967,1964,1955,1946,1939,1929,1911,1888,1869,1857,1847,1837,1826,1815,1802,1791,
+1786,1784,1780,1774,1771,1769,1762,1750,1740,1736,1733,1729,1727,1731,1735,1760,1763,1759,1746,1731,1724,
+1727,1737,1744,1738,1722,1706,1700,1704,1706,1694,1672,1654,1643,1630,1614,1603,1603,1602,1583,1546,1506,
+1476,1456,1439,1426,1423,1428,1423,1381,1298,1205,1139,1098,1038,936,828,771,778,805,811,793,768,
+742,710,674,642,613,579,528,454,356,248,151,66,-24,-138,-260,-356,-409,-442,-499,-612,-778,
+-960,-1112,-1210,-1263,-1297,-1341,-1409,-1501,-1607,-1710,-1798,-1871,-1932,-1980,-2017,-2047,-2074,-2090,-2090,-2083,-2087,
+-2107,-2130,-2136,-2127,-2119,-2123,-2130,-2118,-2075,-2010,-1944,-1892,-1854,-1826,-1804,-1781,-1744,-1681,-1599,-1515,-1434,
+-1333,-1191,-1016,-855,-756,-742,-799,-881,-941,-966,-988,-1041,-1121,-1194,-1240,-1275,-1325,-1391,-1456,-1515,-1569,
+-1616,-1654,-1687,-1718,-1730,-1703,-1647,-1591,-1548,-1505,-1457,-1419,-1403,-1392,-1376,-1387,-1466,-1614,-1780,-1915,-2012,
+-2091,-2171,-2261,-2368,-2488,-2606,-2708,-2789,-2862,-2942,-3031,-3120,-3190,-3231,-3256,-3299,-3389,-3533,-3712,-3890,-4032,
+-4121,-4161,-4176,-4189,-4210,-4245,-4290,-4333,-4369,-4411,-4478,-4569,-4656,-4713,-4747,-4782,-4828,-4874,-4905,-4918,-4914,
+-4893,-4863,-4842,-4842,-4856,-4865,-4863,-4855,-4847,-4839,-4831,-4829,-4838,-4858,-4881,-4904,-4925,-4937,-4943,-4949,-4964,
+-4986,-5008,-5032,-5065,-5105,-5144,-5184,-5234,-5295,-5350,-5390,-5427,-5475,-5529,-5575,-5614,-5660,-5721,-5785,-5843,-5901,
+-5971,-6052,-6129,-6193,-6252,-6317,-6392,-6471,-6547,-6619,-6688,-6755,-6821,-6886,-6952,-7020,-7084,-7141,-7196,-7253,-7311,
+-7366,-7415,-7463,-7513,-7568,-7629,-7690,-7740,-7776,-7811,-7861,-7926,-8000,-8077,-8161,-8251,-8340,-8428,-8515,-8598,-8673,
+-8744,-8826,-8915,-8993,-9052,-9109,-9181,-9262,-9338,-9398,-9432,-9426,-9390,-9366,-9386,-9433,-9468,-9504,-9590,-9738,-9884,
+-9954,-9949,-9929,-9935,-9960,-9987,-10015,-10048,-10076,-10092,-10104,-10123,-10146,-10164,-10178,-10192,-10207,-10212,-10204,-10184,-10154,
+-10120,-10091,-10069,-10041,-9994,-9929,-9850,-9760,-9663,-9576,-9515,-9473,-9427,-9361,-9283,-9202,-9118,-9026,-8929,-8833,-8737,
+-8633,-8520,-8400,-8276,-8149,-8030,-7925,-7825,-7708,-7558,-7387,-7219,-7067,-6920,-6762,-6593,-6433,-6299,-6194,-6110,-6036,
+-5958,-5856,-5726,-5589,-5464,-5343,-5198,-5021,-4838,-4677,-4537,-4390,-4216,-4029,-3861,-3724,-3594,-3443,-3277,-3134,-3030,
+-2936,-2828,-2738,-2715,-2751,-2761,-2661,-2438,-2145,-1869,-1688,-1623,-1615,-1567,-1443,-1273,-1080,-834,-531,-247,-68,
+17,95,209,323,407,483,586,706,814,904,988,1073,1165,1270,1382,1484,1571,1661,1766,1871,1959,
+2034,2112,2195,2285,2388,2502,2607,2689,2772,2886,3027,3157,3254,3333,3406,3473,3536,3613,3717,3831,3937,
+4040,4165,4314,4453,4543,4590,4636,4714,4814,4908,4978,5027,5063,5098,5149,5227,5314,5375,5393,5379,5369,
+5391,5454,5522,5524,5424,5284,5224,5304,5473,5646,5789,5910,6000,6040,6039,6042,6083,6166,6269,6346,6345,
+6260,6148,6054,5937,5715,5393,5074,4841,4674,4509,4337,4202,4148,4175,4258,4377,4550,4837,5269,5767,6188,
+6462,6656,6858,7049,7139,7119,7092,7144,7255,7346,7394,7432,7486,7525,7514,7465,7442,7509,7663,7837,7951,
+7975,7934,7873,7802,7709,7591,7486,7450,7497,7575,7602,7551,7459,7369,7281,7178,7073,6998,6955,6914,6859,
+6812,6799,6824,6873,6937,7012,7089,7155,7200,7229,7251,7274,7295,7308,7318,7331,7342,7331,7300,7264,7237,
+7206,7168,7142,7146,7157,7150,7141,7165,7208,7219,7186,7152,7148,7145,7110,7062,7036,7020,6980,6920,6871,
+6831,6761,6651,6536,6442,6352,6249,6164,6141,6169,6190,6163,6106,6064,6060,6075,6066,6010,5923,5856,5846,
+5888,5932,5941,5921,5911,5931,5958,5961,5932,5895,5867,5843,5807,5755,5694,5634,5578,5520,5458,5394,5335,
+5281,5221,5148,5070,5004,4954,4909,4854,4790,4720,4651,4583,4522,4471,4431,4399,4376,4352,4316,4269,4222,
+4183,4150,4117,4081,4044,4000,3953,3920,3916,3929,3926,3890,3831,3769,3715,3665,3614,3564,3524,3494,3464,
+3417,3352,3290,3252,3230,3207,3176,3145,3110,3063,3001,2937,2877,2808,2722,2651,2646,2734,2872,2966,2940,
+2804,2639,2532,2505,2518,2522,2495,2447,2396,2360,2349,2358,2372,2368,2337,2284,2228,2188,2163,2142,2115,
+2091,2078,2068,2049,2028,2015,2013,2011,2003,1984,1943,1884,1844,1864,1924,1947,1883,1773,1696,1682,1698,
+1707,1711,1718,1723,1716,1703,1695,1688,1669,1639,1612,1595,1585,1584,1594,1608,1611,1594,1568,1544,1527,
+1515,1504,1492,1476,1456,1441,1440,1458,1487,1515,1532,1531,1513,1490,1474,1464,1453,1439,1434,1445,1468,
+1493,1512,1520,1516,1504,1495,1496,1500,1500,1502,1514,1532,1543,1545,1545,1551,1554,1545,1528,1518,1531,
+1566,1604,1626,1622,1605,1591,1589,1592,1595,1596,1596,1597,1602,1606,1604,1593,1578,1565,1553,1535,1513,
+1494,1477,1458,1433,1408,1388,1373,1360,1349,1336,1321,1307,1298,1288,1268,1239,1214,1198,1185,1170,1156,
+1146,1136,1120,1101,1081,1059,1030,999,970,943,914,883,849,815,780,749,719,686,650,614,581,
+547,509,470,433,396,357,315,276,241,208,176,148,121,93,64,34,0,-39,-79,-118,-154,
+-191,-229,-267,-306,-347,-391,-434,-474,-512,-548,-580,-608,-633,-659,-689,-724,-760,-792,-819,-845,-872,
+-899,-927,-957,-992,-1026,-1052,-1073,-1098,-1129,-1164,-1199,-1234,-1270,-1308,-1344,-1374,-1398,-1421,-1448,-1480,-1512,
+-1545,-1577,-1610,-1641,-1672,-1705,-1739,-1769,-1792,-1813,-1837,-1863,-1889,-1913,-1939,-1967,-1994,-2018,-2038,-2055,-2073,
+-2091,-2109,-2126,-2143,-2160,-2177,-2190,-2202,-2215,-2228,-2237,-2243,-2250,-2261,-2269,-2273,-2278,-2285,-2290,-2290,-2288,
+-2289,-2291,-2290,-2287,-2284,-2278,-2268,-2256,-2244,-2233,-2220,-2206,-2192,-2174,-2154,-2135,-2124,-2116,-2107,-2095,-2083,
+-2069,-2052,-2035,-2023,-2013,-2002,-1987,-1972,-1957,-1943,-1927,-1911,-1896,-1884,-1873,-1861,-1848,-1834,-1821,-1811,-1800,
+-1786,-1773,-1763,-1753,-1743,-1731,-1720,-1708,-1694,-1681,-1670,-1659,-1646,-1630,-1617,-1604,-1590,-1573,-1558,-1543,-1526,
+-1508,-1492,-1478,-1462,-1444,-1427,-1413,-1398,-1380,-1362,-1346,-1332,-1317,-1301,-1284,-1268,-1252,-1238,-1224,-1212,-1200,
+-1186,-1173,-1162,-1151,-1137,-1118,-1099,-1081,-1060,-1033,-1008,-986,-961,-935,-930,-947,-941,-854,-694,-540,-460,
+-439,-424,-394,-371,-366,-363,-356,-355,-356,-343,-313,-286,-269,-252,-227,-200,-180,-156,-123,-87,-54,
+-13,38,91,139,194,263,333,401,483,582,672,742,814,898,943,902,823,821,950,1148,1323,
+1447,1547,1654,1801,2028,2332,2618,2756,2684,2450,2151,1869,1661,1555,1545,1595,1668,1742,1803,1838,1851,
+1863,1888,1916,1940,1963,1984,1988,1959,1905,1847,1796,1751,1711,1675,1640,1601,1562,1526,1492,1455,1418,
+1380,1331,1253,1153,1049,955,869,785,705,628,547,461,380,309,239,165,89,19,-45,-113,-182,
+-248,-311,-376,-442,-501,-555,-609,-670,-725,-760,-775,-789,-817,-861,-914,-968,-1028,-1099,-1179,-1260,-1340,
+-1427,-1523,-1616,-1692,-1749,-1800,-1857,-1916,-1964,-1999,-2028,-2061,-2102,-2146,-2193,-2245,-2305,-2373,-2434,-2471,-2471,
+-2438,-2397,-2367,-2355,-2353,-2356,-2357,-2352,-2339,-2321,-2303,-2296,-2313,-2366,-2445,-2512,-2535,-2524,-2514,-2529,-2553,
+-2567,-2569,-2566,-2558,-2544,-2539,-2547,-2549,-2522,-2468,-2411,-2360,-2314,-2274,-2253,-2252,-2258,-2256,-2249,-2248,-2263,
+-2299,-2341,-2353,-2312,-2238,-2184,-2170,-2172,-2150,-2095,-2025,-1957,-1895,-1846,-1807,-1766,-1716,-1669,-1635,-1607,-1564,
+-1504,-1445,-1398,-1352,-1295,-1227,-1160,-1098,-1039,-978,-915,-855,-800,-751,-704,-659,-613,-569,-526,-484,-445,
+-407,-366,-320,-270,-220,-170,-120,-71,-22,28,79,127,175,230,291,351,399,437,471,505,539,
+573,609,642,668,685,697,706,720,745,782,820,848,868,884,895,898,899,909,929,947,950,
+937,921,911,911,921,940,961,983,1008,1043,1094,1154,1208,1253,1297,1348,1402,1447,1483,1523,1573,
+1628,1682,1737,1796,1848,1878,1882,1870,1858,1851,1851,1856,1863,1870,1874,1879,1889,1905,1925,1943,1955,
+1961,1968,1978,1987,1990,1989,1988,1989,1989,1988,1985,1982,1976,1969,1964,1961,1961,1963,1962,1956,1944,
+1932,1921,1909,1890,1869,1853,1841,1830,1820,1811,1802,1794,1786,1783,1781,1776,1771,1768,1769,1765,1756,
+1746,1742,1742,1744,1748,1754,1760,1784,1785,1779,1762,1744,1739,1748,1758,1759,1748,1734,1722,1715,1713,
+1708,1692,1671,1654,1644,1634,1623,1620,1623,1610,1567,1507,1462,1444,1439,1428,1414,1415,1432,1441,1406,
+1318,1211,1131,1084,1027,930,821,757,764,814,864,886,872,824,759,701,658,623,581,529,464,
+382,287,196,110,8,-125,-267,-373,-425,-453,-506,-615,-768,-935,-1086,-1210,-1306,-1370,-1408,-1441,-1499,
+-1593,-1703,-1800,-1876,-1938,-1992,-2032,-2062,-2088,-2111,-2124,-2123,-2121,-2128,-2137,-2135,-2123,-2115,-2120,-2130,-2124,
+-2091,-2036,-1978,-1931,-1898,-1870,-1843,-1816,-1780,-1718,-1625,-1518,-1415,-1312,-1188,-1039,-892,-785,-734,-727,-742,
+-771,-825,-919,-1044,-1161,-1237,-1279,-1319,-1377,-1446,-1512,-1574,-1626,-1656,-1671,-1695,-1732,-1742,-1692,-1608,-1549,
+-1528,-1511,-1479,-1459,-1472,-1493,-1497,-1508,-1568,-1674,-1783,-1876,-1971,-2083,-2198,-2302,-2407,-2526,-2644,-2737,-2808,
+-2877,-2962,-3054,-3136,-3197,-3237,-3279,-3353,-3480,-3648,-3823,-3968,-4067,-4122,-4148,-4162,-4175,-4197,-4234,-4283,-4332,
+-4374,-4420,-4492,-4591,-4684,-4736,-4753,-4767,-4801,-4847,-4881,-4892,-4883,-4863,-4842,-4833,-4839,-4850,-4850,-4840,-4827,
+-4815,-4805,-4798,-4801,-4819,-4844,-4867,-4885,-4900,-4909,-4912,-4917,-4930,-4950,-4971,-4995,-5026,-5065,-5106,-5150,-5207,
+-5270,-5325,-5363,-5397,-5441,-5492,-5538,-5579,-5628,-5691,-5756,-5815,-5873,-5940,-6018,-6100,-6173,-6235,-6293,-6357,-6428,
+-6500,-6569,-6640,-6716,-6792,-6862,-6929,-6994,-7058,-7118,-7175,-7233,-7288,-7339,-7384,-7430,-7480,-7535,-7597,-7659,-7709,
+-7743,-7776,-7824,-7889,-7958,-8028,-8106,-8196,-8289,-8377,-8463,-8545,-8623,-8700,-8784,-8872,-8950,-9013,-9075,-9148,-9228,
+-9304,-9364,-9395,-9383,-9346,-9327,-9352,-9395,-9423,-9458,-9554,-9716,-9867,-9929,-9912,-9886,-9893,-9921,-9948,-9974,-10006,
+-10036,-10055,-10068,-10085,-10106,-10124,-10141,-10161,-10182,-10192,-10185,-10161,-10125,-10085,-10056,-10036,-10009,-9959,-9885,-9803,-9721,
+-9645,-9577,-9518,-9459,-9392,-9318,-9246,-9179,-9104,-9015,-8917,-8819,-8722,-8618,-8504,-8385,-8263,-8143,-8031,-7934,-7837,
+-7718,-7565,-7394,-7227,-7071,-6914,-6745,-6577,-6430,-6314,-6221,-6140,-6064,-5983,-5880,-5750,-5612,-5482,-5353,-5200,-5019,
+-4834,-4672,-4532,-4390,-4229,-4056,-3893,-3749,-3612,-3465,-3314,-3179,-3064,-2943,-2804,-2689,-2656,-2704,-2755,-2714,-2538,
+-2257,-1954,-1732,-1649,-1664,-1667,-1582,-1413,-1186,-900,-563,-248,-38,63,132,223,331,433,534,643,750,
+842,926,1011,1095,1181,1282,1397,1502,1589,1677,1782,1892,1983,2056,2127,2203,2284,2380,2494,2603,2689,
+2768,2874,3005,3126,3219,3297,3375,3446,3510,3586,3693,3812,3916,4010,4125,4269,4405,4488,4528,4572,4649,
+4744,4824,4881,4926,4970,5019,5092,5198,5308,5374,5377,5351,5344,5378,5441,5492,5478,5380,5263,5233,5340,
+5531,5724,5898,6062,6186,6217,6157,6093,6114,6232,6381,6465,6437,6329,6220,6147,6056,5865,5573,5264,5005,
+4796,4610,4459,4375,4364,4406,4473,4546,4629,4774,5048,5452,5891,6264,6548,6779,6957,7049,7066,7080,7137,
+7207,7238,7236,7253,7309,7370,7394,7394,7423,7514,7651,7780,7868,7914,7949,7983,7992,7932,7789,7614,7497,
+7479,7519,7537,7509,7475,7460,7440,7380,7300,7242,7205,7152,7071,6995,6957,6944,6934,6932,6968,7050,7144,
+7210,7239,7247,7258,7279,7303,7325,7339,7338,7320,7297,7286,7287,7282,7271,7285,7333,7376,7371,7338,7327,
+7344,7347,7318,7296,7306,7315,7284,7231,7202,7197,7173,7114,7048,6997,6951,6889,6809,6711,6585,6440,6315,
+6242,6211,6182,6135,6082,6049,6048,6069,6082,6056,5982,5896,5847,5854,5895,5928,5939,5942,5956,5974,5976,
+5955,5922,5892,5866,5835,5793,5738,5676,5612,5553,5493,5430,5366,5307,5249,5182,5103,5028,4968,4915,4857,
+4791,4727,4671,4617,4559,4500,4452,4425,4410,4389,4346,4289,4236,4198,4168,4138,4108,4074,4031,3982,3945,
+3933,3935,3924,3886,3837,3793,3755,3710,3653,3593,3548,3520,3496,3457,3397,3337,3292,3262,3234,3202,3173,
+3144,3109,3059,2998,2929,2853,2775,2710,2685,2728,2836,2952,2990,2907,2750,2619,2579,2607,2636,2614,2542,
+2453,2384,2351,2351,2363,2363,2340,2297,2247,2205,2174,2148,2120,2098,2086,2075,2056,2032,2020,2020,2021,
+2012,1988,1945,1892,1859,1880,1935,1951,1884,1771,1693,1679,1695,1700,1697,1704,1719,1726,1722,1713,1701,
+1681,1656,1633,1612,1593,1578,1575,1583,1591,1591,1585,1574,1557,1536,1512,1485,1455,1428,1417,1431,1467,
+1511,1550,1574,1574,1551,1518,1489,1468,1452,1444,1448,1464,1481,1493,1501,1504,1500,1489,1482,1482,1481,
+1477,1479,1492,1511,1522,1526,1532,1539,1539,1531,1522,1521,1529,1547,1571,1592,1595,1582,1567,1565,1572,
+1576,1573,1568,1568,1575,1583,1581,1569,1554,1547,1544,1534,1514,1492,1474,1456,1434,1410,1391,1377,1364,
+1348,1327,1305,1287,1276,1266,1250,1227,1206,1190,1174,1157,1143,1135,1126,1112,1096,1081,1065,1043,1015,
+985,955,923,892,861,829,794,760,727,694,656,618,582,548,511,474,439,403,363,321,281,
+244,210,178,150,125,101,74,44,11,-26,-65,-101,-135,-170,-207,-245,-284,-327,-369,-409,-446,
+-483,-521,-557,-588,-615,-641,-670,-703,-739,-773,-803,-832,-860,-888,-916,-947,-979,-1011,-1038,-1061,-1086,
+-1117,-1152,-1186,-1220,-1255,-1291,-1324,-1349,-1369,-1390,-1418,-1452,-1486,-1520,-1553,-1586,-1618,-1648,-1678,-1708,-1734,
+-1757,-1780,-1805,-1829,-1851,-1873,-1898,-1925,-1953,-1978,-2001,-2020,-2037,-2052,-2067,-2083,-2100,-2117,-2135,-2150,-2164,
+-2178,-2192,-2202,-2208,-2215,-2224,-2232,-2237,-2242,-2246,-2248,-2247,-2247,-2250,-2253,-2253,-2250,-2246,-2238,-2229,-2220,
+-2212,-2202,-2188,-2174,-2161,-2145,-2125,-2107,-2096,-2089,-2078,-2064,-2051,-2038,-2024,-2009,-1996,-1985,-1974,-1961,-1948,
+-1935,-1921,-1906,-1892,-1879,-1866,-1853,-1838,-1823,-1810,-1799,-1790,-1780,-1769,-1757,-1746,-1736,-1723,-1710,-1698,-1687,
+-1676,-1665,-1655,-1645,-1633,-1619,-1607,-1596,-1583,-1567,-1550,-1534,-1518,-1503,-1487,-1472,-1457,-1443,-1430,-1416,-1399,
+-1382,-1366,-1353,-1339,-1324,-1308,-1292,-1278,-1266,-1253,-1239,-1224,-1210,-1198,-1187,-1176,-1165,-1149,-1130,-1112,-1095,
+-1076,-1052,-1030,-1010,-985,-954,-940,-953,-959,-908,-794,-669,-580,-517,-452,-391,-359,-357,-362,-361,-360,
+-361,-352,-330,-311,-298,-280,-253,-227,-204,-177,-143,-109,-75,-28,30,87,140,203,280,353,417,
+492,585,674,740,801,865,889,838,774,815,1003,1251,1444,1544,1586,1632,1755,2013,2374,2684,2777,
+2616,2314,2007,1758,1584,1498,1505,1573,1651,1712,1758,1799,1835,1867,1895,1921,1945,1965,1977,1971,1945,
+1905,1859,1803,1739,1679,1636,1607,1581,1547,1510,1474,1441,1415,1390,1352,1289,1205,1114,1024,933,840,
+752,669,587,505,428,358,287,212,138,71,5,-65,-138,-206,-271,-338,-406,-469,-528,-590,-654,
+-706,-737,-753,-770,-804,-854,-907,-958,-1015,-1090,-1180,-1271,-1352,-1429,-1512,-1595,-1666,-1726,-1786,-1855,-1925,
+-1982,-2020,-2044,-2061,-2081,-2115,-2166,-2229,-2294,-2358,-2413,-2445,-2441,-2408,-2368,-2341,-2330,-2328,-2333,-2345,-2357,
+-2357,-2342,-2317,-2298,-2301,-2342,-2410,-2471,-2495,-2488,-2480,-2488,-2503,-2512,-2521,-2531,-2532,-2517,-2505,-2518,-2538,
+-2533,-2491,-2433,-2380,-2335,-2290,-2251,-2226,-2217,-2221,-2225,-2219,-2206,-2210,-2243,-2283,-2292,-2257,-2209,-2175,-2149,
+-2108,-2047,-1979,-1914,-1859,-1818,-1786,-1752,-1705,-1650,-1600,-1559,-1514,-1461,-1407,-1358,-1313,-1266,-1213,-1152,-1085,
+-1018,-959,-908,-860,-810,-760,-712,-666,-621,-580,-541,-502,-462,-424,-385,-341,-293,-245,-199,-153,-105,
+-56,-7,39,83,125,174,235,300,358,399,425,443,463,490,522,552,574,585,590,591,593,
+601,620,646,673,698,720,737,748,761,785,819,849,859,852,838,830,832,840,854,875,904,
+943,992,1049,1110,1171,1235,1307,1383,1450,1496,1527,1554,1587,1621,1656,1698,1748,1796,1823,1823,1806,
+1789,1782,1787,1802,1824,1850,1877,1901,1924,1947,1969,1982,1981,1972,1968,1976,1990,2000,2004,2004,2002,
+1999,1996,1995,1994,1989,1979,1968,1961,1956,1951,1944,1934,1923,1913,1903,1891,1876,1862,1849,1837,1825,
+1812,1800,1790,1782,1776,1773,1771,1766,1761,1759,1761,1763,1761,1758,1757,1762,1770,1777,1781,1784,1802,
+1798,1790,1775,1759,1756,1763,1767,1760,1750,1744,1739,1729,1716,1701,1684,1668,1656,1645,1630,1619,1620,
+1624,1603,1542,1467,1416,1399,1395,1387,1381,1390,1407,1408,1368,1287,1195,1120,1063,993,894,790,727,
+733,795,878,937,940,886,807,741,695,648,592,533,474,402,315,228,145,45,-91,-241,-355,
+-413,-449,-514,-625,-764,-904,-1036,-1169,-1297,-1396,-1447,-1469,-1507,-1585,-1687,-1780,-1852,-1916,-1977,-2026,-2060,
+-2089,-2117,-2136,-2137,-2130,-2129,-2134,-2134,-2127,-2118,-2117,-2120,-2117,-2099,-2065,-2022,-1982,-1950,-1920,-1886,-1852,
+-1814,-1756,-1660,-1537,-1415,-1308,-1195,-1057,-906,-774,-682,-629,-609,-635,-727,-880,-1051,-1185,-1261,-1305,-1355,
+-1422,-1489,-1549,-1607,-1656,-1680,-1689,-1715,-1758,-1771,-1724,-1653,-1616,-1605,-1573,-1523,-1518,-1580,-1645,-1645,-1604,
+-1596,-1646,-1726,-1821,-1945,-2095,-2233,-2340,-2442,-2561,-2676,-2759,-2821,-2894,-2986,-3074,-3140,-3190,-3247,-3328,-3445,
+-3596,-3761,-3905,-4008,-4071,-4107,-4130,-4149,-4170,-4199,-4242,-4294,-4347,-4391,-4438,-4512,-4615,-4712,-4761,-4761,-4751,
+-4766,-4804,-4840,-4854,-4846,-4829,-4815,-4813,-4819,-4824,-4819,-4804,-4787,-4771,-4758,-4754,-4767,-4795,-4827,-4849,-4861,
+-4867,-4869,-4869,-4875,-4889,-4910,-4931,-4953,-4980,-5013,-5052,-5100,-5162,-5232,-5293,-5337,-5372,-5411,-5457,-5504,-5552,
+-5604,-5663,-5725,-5786,-5845,-5907,-5977,-6059,-6143,-6217,-6277,-6334,-6395,-6461,-6528,-6600,-6677,-6755,-6827,-6895,-6964,
+-7033,-7097,-7152,-7203,-7251,-7294,-7338,-7386,-7440,-7499,-7561,-7622,-7671,-7706,-7740,-7787,-7849,-7912,-7977,-8053,-8142,
+-8235,-8321,-8405,-8490,-8572,-8653,-8735,-8820,-8900,-8973,-9045,-9119,-9193,-9260,-9315,-9346,-9340,-9312,-9301,-9326,-9358,
+-9373,-9405,-9513,-9689,-9843,-9896,-9868,-9836,-9845,-9878,-9906,-9930,-9962,-9996,-10021,-10038,-10055,-10074,-10094,-10115,-10141,
+-10168,-10184,-10180,-10154,-10115,-10073,-10040,-10016,-9981,-9920,-9834,-9743,-9662,-9594,-9534,-9473,-9408,-9340,-9276,-9222,-9167,
+-9092,-8995,-8888,-8786,-8688,-8583,-8468,-8348,-8230,-8120,-8021,-7931,-7832,-7706,-7551,-7386,-7228,-7073,-6909,-6736,-6576,
+-6448,-6352,-6269,-6188,-6103,-6011,-5900,-5769,-5630,-5496,-5358,-5199,-5018,-4836,-4675,-4532,-4390,-4237,-4077,-3920,-3772,
+-3626,-3480,-3341,-3218,-3100,-2961,-2800,-2664,-2611,-2646,-2705,-2703,-2588,-2352,-2044,-1773,-1641,-1653,-1705,-1678,-1530,
+-1288,-982,-636,-302,-47,106,196,271,356,457,570,682,776,852,932,1024,1117,1203,1299,1408,1514,
+1604,1692,1795,1900,1990,2065,2140,2216,2291,2376,2480,2588,2681,2765,2867,2987,3097,3183,3259,3339,3417,
+3487,3567,3673,3789,3885,3964,4059,4181,4299,4376,4422,4479,4568,4661,4728,4775,4825,4887,4962,5058,5182,
+5302,5364,5355,5320,5315,5352,5402,5426,5394,5312,5235,5246,5372,5558,5739,5914,6104,6273,6335,6276,6195,
+6217,6362,6527,6592,6521,6379,6261,6195,6126,5989,5785,5569,5372,5189,5027,4918,4881,4891,4915,4943,4966,
+4973,4993,5112,5393,5790,6178,6472,6672,6807,6896,6954,7012,7079,7125,7124,7098,7100,7146,7208,7258,7303,
+7365,7445,7521,7576,7619,7676,7767,7874,7950,7940,7827,7662,7527,7469,7460,7447,7424,7428,7473,7515,7511,
+7474,7442,7418,7374,7306,7247,7213,7171,7091,7004,6972,7023,7117,7195,7229,7235,7244,7268,7299,7323,7330,
+7323,7314,7320,7345,7375,7390,7406,7459,7547,7614,7606,7541,7480,7449,7422,7386,7366,7377,7384,7353,7301,
+7274,7278,7271,7225,7156,7097,7065,7056,7046,7004,6903,6757,6607,6484,6387,6300,6216,6140,6074,6027,6015,
+6044,6088,6100,6055,5977,5917,5905,5933,5971,6000,6013,6017,6012,5996,5971,5937,5901,5868,5834,5787,5722,
+5649,5583,5528,5473,5408,5340,5276,5209,5130,5046,4973,4911,4853,4795,4749,4715,4678,4619,4548,4491,4465,
+4457,4437,4390,4328,4272,4231,4197,4162,4127,4092,4052,4008,3971,3949,3936,3913,3879,3843,3815,3787,3748,
+3694,3634,3582,3544,3513,3474,3422,3365,3317,3280,3251,3225,3198,3171,3142,3105,3050,2973,2888,2816,2759,
+2710,2684,2718,2817,2915,2923,2831,2720,2673,2695,2721,2693,2609,2502,2413,2360,2341,2339,2336,2323,2296,
+2259,2220,2188,2162,2140,2122,2110,2096,2072,2046,2031,2032,2031,2017,1987,1947,1903,1875,1887,1926,1938,
+1888,1807,1759,1766,1785,1775,1741,1716,1716,1726,1733,1730,1718,1698,1674,1654,1634,1612,1589,1572,1564,
+1565,1571,1579,1584,1578,1559,1533,1504,1471,1442,1433,1449,1483,1522,1556,1579,1583,1563,1531,1499,1475,
+1458,1453,1461,1477,1487,1488,1489,1492,1493,1488,1481,1476,1467,1458,1458,1473,1492,1505,1513,1524,1534,
+1537,1536,1540,1546,1546,1543,1550,1566,1576,1572,1564,1561,1563,1562,1556,1553,1555,1561,1563,1557,1545,
+1533,1531,1534,1529,1512,1489,1468,1450,1431,1412,1399,1387,1372,1350,1324,1299,1277,1262,1251,1239,1222,
+1204,1187,1169,1149,1132,1121,1110,1094,1078,1064,1051,1032,1007,979,949,916,886,858,830,797,763,
+730,697,660,622,586,552,517,482,450,418,382,340,300,262,227,193,164,138,112,82,51,
+16,-19,-54,-88,-120,-154,-191,-229,-270,-313,-354,-390,-422,-455,-495,-535,-571,-602,-630,-659,-689,
+-720,-752,-784,-815,-846,-877,-907,-936,-965,-993,-1020,-1046,-1075,-1108,-1144,-1178,-1210,-1242,-1273,-1299,-1319,
+-1336,-1358,-1389,-1426,-1463,-1499,-1533,-1566,-1597,-1626,-1654,-1679,-1702,-1725,-1750,-1774,-1796,-1816,-1837,-1861,-1887,
+-1912,-1938,-1963,-1985,-2001,-2014,-2027,-2042,-2058,-2075,-2093,-2110,-2125,-2139,-2152,-2162,-2169,-2178,-2187,-2197,-2205,
+-2211,-2213,-2212,-2210,-2211,-2215,-2217,-2216,-2212,-2207,-2198,-2188,-2180,-2174,-2166,-2153,-2140,-2127,-2113,-2095,-2079,
+-2069,-2061,-2048,-2033,-2020,-2009,-1998,-1984,-1970,-1957,-1944,-1931,-1919,-1906,-1893,-1880,-1869,-1859,-1848,-1834,-1819,
+-1804,-1791,-1779,-1770,-1760,-1750,-1739,-1729,-1718,-1706,-1692,-1680,-1670,-1661,-1651,-1641,-1629,-1617,-1606,-1596,-1587,
+-1576,-1561,-1543,-1527,-1513,-1501,-1487,-1471,-1454,-1441,-1429,-1416,-1400,-1385,-1373,-1361,-1347,-1333,-1318,-1303,-1291,
+-1281,-1271,-1257,-1240,-1226,-1214,-1202,-1190,-1176,-1162,-1145,-1128,-1112,-1094,-1072,-1050,-1030,-1005,-972,-949,-950,
+-961,-947,-895,-826,-754,-668,-567,-480,-441,-443,-447,-435,-419,-408,-397,-381,-365,-351,-327,-295,-262,
+-233,-200,-163,-128,-92,-43,16,73,128,198,281,354,413,481,571,659,723,773,819,830,787,
+757,848,1087,1377,1595,1692,1701,1694,1772,2012,2376,2678,2725,2496,2148,1848,1652,1535,1481,1495,1557,
+1621,1668,1716,1781,1850,1896,1914,1927,1948,1969,1971,1950,1921,1892,1857,1800,1725,1657,1613,1585,1558,
+1523,1487,1457,1437,1424,1411,1384,1335,1264,1182,1093,995,894,798,710,626,544,468,399,334,267,
+200,133,61,-17,-92,-160,-227,-298,-370,-438,-502,-567,-632,-686,-718,-736,-756,-794,-846,-900,-951,
+-1010,-1090,-1188,-1285,-1367,-1439,-1510,-1580,-1642,-1700,-1768,-1847,-1924,-1981,-2012,-2022,-2022,-2034,-2075,-2145,-2227,
+-2301,-2360,-2403,-2420,-2403,-2361,-2322,-2303,-2298,-2298,-2308,-2335,-2369,-2385,-2372,-2341,-2313,-2307,-2332,-2381,-2430,
+-2453,-2452,-2448,-2448,-2445,-2438,-2447,-2476,-2501,-2500,-2489,-2500,-2531,-2544,-2516,-2464,-2418,-2384,-2347,-2298,-2243,
+-2203,-2187,-2189,-2185,-2160,-2133,-2140,-2187,-2239,-2258,-2237,-2194,-2139,-2072,-2001,-1936,-1884,-1842,-1807,-1777,-1740,
+-1685,-1614,-1541,-1479,-1429,-1387,-1343,-1296,-1250,-1213,-1181,-1138,-1077,-1011,-959,-924,-892,-852,-807,-761,-715,
+-671,-631,-592,-554,-515,-478,-441,-401,-360,-319,-279,-235,-186,-138,-96,-59,-26,8,49,103,168,
+227,269,291,301,314,337,367,397,417,426,428,429,429,432,444,467,500,537,569,591,607,
+624,651,688,722,743,753,762,777,796,818,842,871,909,954,1003,1053,1100,1151,1210,1277,1343,
+1397,1439,1477,1517,1557,1590,1618,1648,1685,1721,1744,1746,1735,1722,1717,1725,1746,1781,1829,1884,1935,
+1974,2003,2020,2024,2011,1989,1975,1976,1986,1996,2004,2007,2005,1998,1991,1989,1991,1989,1980,1968,1957,
+1948,1939,1928,1917,1907,1897,1887,1875,1864,1854,1842,1830,1817,1806,1795,1784,1775,1770,1767,1764,1759,
+1754,1752,1753,1758,1766,1773,1779,1788,1800,1807,1807,1802,1814,1804,1797,1789,1782,1782,1784,1777,1763,
+1752,1748,1743,1726,1703,1684,1672,1666,1658,1642,1616,1593,1589,1590,1566,1503,1428,1375,1351,1339,1333,
+1338,1350,1350,1322,1269,1208,1149,1086,1011,918,815,726,675,677,728,811,888,916,886,829,780,
+739,682,608,536,477,413,334,252,176,83,-46,-195,-314,-383,-434,-514,-630,-757,-872,-982,-1105,
+-1239,-1354,-1425,-1463,-1507,-1581,-1672,-1754,-1818,-1879,-1942,-1999,-2044,-2080,-2108,-2123,-2121,-2112,-2112,-2120,-2126,
+-2122,-2112,-2104,-2100,-2100,-2096,-2081,-2052,-2017,-1984,-1950,-1909,-1867,-1827,-1779,-1697,-1582,-1463,-1355,-1241,-1092,
+-915,-754,-644,-588,-576,-616,-721,-880,-1045,-1171,-1251,-1316,-1393,-1474,-1538,-1586,-1632,-1676,-1700,-1712,-1739,
+-1782,-1798,-1766,-1723,-1706,-1686,-1621,-1551,-1573,-1694,-1793,-1765,-1650,-1572,-1591,-1679,-1802,-1958,-2127,-2267,-2365,
+-2461,-2580,-2693,-2770,-2830,-2909,-3005,-3080,-3125,-3175,-3265,-3400,-3560,-3721,-3860,-3962,-4028,-4069,-4097,-4118,-4137,
+-4164,-4206,-4259,-4317,-4368,-4411,-4458,-4528,-4626,-4720,-4768,-4762,-4738,-4738,-4768,-4801,-4815,-4810,-4799,-4789,-4785,
+-4782,-4778,-4770,-4758,-4742,-4725,-4710,-4709,-4729,-4765,-4801,-4824,-4833,-4834,-4833,-4833,-4838,-4851,-4871,-4892,-4915,
+-4941,-4972,-5009,-5057,-5118,-5188,-5252,-5304,-5345,-5383,-5425,-5473,-5527,-5579,-5629,-5682,-5743,-5808,-5869,-5931,-6008,
+-6098,-6186,-6257,-6316,-6375,-6438,-6504,-6572,-6643,-6714,-6784,-6854,-6929,-7001,-7062,-7112,-7156,-7198,-7239,-7283,-7335,
+-7394,-7457,-7519,-7577,-7626,-7664,-7702,-7752,-7810,-7868,-7929,-8003,-8089,-8178,-8262,-8348,-8439,-8527,-8607,-8685,-8768,
+-8852,-8933,-9010,-9082,-9145,-9198,-9246,-9279,-9284,-9272,-9273,-9296,-9316,-9320,-9353,-9471,-9656,-9806,-9850,-9813,-9780,
+-9793,-9830,-9861,-9887,-9922,-9960,-9991,-10012,-10032,-10053,-10073,-10096,-10127,-10158,-10176,-10172,-10146,-10107,-10067,-10031,-9996,
+-9948,-9874,-9778,-9678,-9590,-9520,-9460,-9404,-9346,-9292,-9246,-9205,-9154,-9075,-8968,-8854,-8749,-8650,-8544,-8426,-8304,
+-8192,-8094,-8006,-7913,-7797,-7653,-7497,-7349,-7215,-7073,-6911,-6740,-6593,-6486,-6405,-6327,-6237,-6139,-6033,-5913,-5780,
+-5642,-5506,-5363,-5201,-5022,-4846,-4688,-4546,-4406,-4259,-4105,-3950,-3797,-3643,-3493,-3358,-3239,-3121,-2977,-2810,-2666,
+-2595,-2601,-2639,-2653,-2595,-2426,-2150,-1849,-1653,-1624,-1692,-1719,-1621,-1410,-1125,-792,-440,-117,124,270,346,
+400,473,578,690,780,852,933,1032,1135,1227,1317,1416,1517,1610,1702,1801,1899,1986,2066,2149,2231,
+2304,2380,2470,2571,2666,2756,2857,2970,3075,3159,3234,3310,3386,3460,3545,3649,3758,3850,3928,4015,4120,
+4221,4291,4343,4410,4503,4591,4648,4687,4740,4819,4912,5019,5141,5252,5308,5301,5279,5290,5329,5354,5338,
+5285,5223,5198,5256,5399,5571,5723,5872,6065,6273,6401,6399,6344,6361,6473,6584,6586,6467,6316,6221,6189,
+6163,6095,5996,5897,5800,5691,5588,5533,5534,5555,5564,5568,5562,5519,5449,5444,5599,5894,6200,6410,6522,
+6599,6681,6769,6859,6941,6996,7013,7008,7012,7037,7078,7130,7196,7270,7329,7358,7363,7374,7416,7494,7586,
+7654,7665,7613,7529,7457,7415,7390,7362,7347,7374,7445,7519,7553,7550,7536,7521,7498,7473,7464,7461,7413,
+7295,7144,7040,7027,7079,7140,7175,7188,7202,7229,7262,7290,7309,7327,7356,7402,7452,7483,7495,7517,7585,
+7688,7763,7759,7692,7614,7555,7504,7459,7434,7436,7434,7407,7368,7351,7355,7351,7314,7250,7185,7149,7156,
+7188,7202,7157,7055,6928,6800,6673,6551,6439,6337,6226,6107,6024,6030,6125,6235,6268,6197,6078,5992,5980,
+6018,6059,6076,6070,6057,6043,6024,5992,5950,5909,5875,5835,5772,5691,5616,5562,5513,5451,5376,5301,5227,
+5148,5064,4986,4920,4863,4816,4789,4776,4750,4690,4609,4544,4516,4508,4486,4436,4373,4316,4270,4226,4181,
+4140,4105,4069,4031,3994,3966,3942,3915,3885,3858,3832,3804,3770,3729,3683,3633,3583,3534,3487,3438,3387,
+3337,3297,3270,3250,3228,3200,3173,3146,3099,3019,2925,2852,2804,2746,2672,2636,2689,2797,2867,2849,2786,
+2747,2744,2736,2687,2601,2507,2428,2377,2350,2337,2327,2314,2295,2267,2234,2205,2185,2168,2149,2130,2110,
+2084,2056,2036,2030,2024,2007,1980,1948,1914,1889,1885,1902,1911,1889,1857,1859,1899,1928,1901,1829,1759,
+1724,1723,1734,1742,1737,1719,1695,1673,1651,1628,1603,1583,1569,1563,1564,1571,1580,1583,1578,1570,1558,
+1537,1511,1492,1488,1499,1516,1535,1552,1559,1550,1531,1511,1493,1479,1470,1473,1481,1485,1484,1486,1494,
+1499,1496,1487,1477,1463,1449,1444,1455,1472,1487,1501,1519,1534,1541,1546,1558,1568,1563,1548,1542,1553,
+1565,1567,1563,1558,1551,1541,1536,1541,1548,1549,1542,1533,1525,1519,1519,1522,1520,1506,1484,1462,1443,
+1425,1412,1404,1395,1377,1352,1326,1301,1278,1258,1244,1234,1221,1205,1188,1170,1150,1131,1113,1094,1075,
+1057,1042,1026,1006,984,960,932,901,871,844,819,791,760,729,696,660,623,590,559,528,497,
+469,443,411,371,329,289,251,215,182,152,122,89,53,18,-15,-47,-79,-111,-147,-185,-225,
+-266,-309,-348,-380,-407,-438,-478,-520,-560,-595,-626,-654,-678,-702,-728,-757,-788,-822,-857,-891,-921,
+-948,-973,-1000,-1030,-1062,-1098,-1134,-1167,-1199,-1229,-1257,-1278,-1293,-1311,-1335,-1368,-1405,-1443,-1478,-1512,-1544,
+-1573,-1602,-1630,-1654,-1676,-1698,-1723,-1747,-1769,-1789,-1810,-1833,-1855,-1877,-1901,-1926,-1948,-1966,-1980,-1993,-2008,
+-2024,-2041,-2058,-2074,-2089,-2102,-2113,-2121,-2130,-2139,-2151,-2163,-2174,-2182,-2184,-2182,-2180,-2182,-2185,-2185,-2181,
+-2177,-2172,-2163,-2151,-2142,-2136,-2129,-2118,-2105,-2093,-2080,-2064,-2051,-2040,-2030,-2016,-2001,-1989,-1981,-1971,-1959,
+-1944,-1930,-1916,-1902,-1889,-1877,-1864,-1853,-1843,-1835,-1824,-1813,-1800,-1788,-1775,-1761,-1749,-1739,-1729,-1718,-1708,
+-1698,-1688,-1677,-1666,-1657,-1649,-1641,-1629,-1616,-1604,-1594,-1586,-1576,-1565,-1553,-1538,-1522,-1509,-1499,-1487,-1471,
+-1454,-1440,-1428,-1414,-1400,-1389,-1380,-1368,-1354,-1341,-1329,-1317,-1304,-1294,-1284,-1271,-1256,-1243,-1232,-1219,-1203,
+-1188,-1175,-1161,-1145,-1129,-1112,-1091,-1068,-1047,-1023,-992,-963,-951,-954,-956,-947,-928,-892,-819,-718,-631,
+-594,-595,-589,-559,-523,-496,-477,-459,-438,-415,-382,-341,-300,-263,-224,-183,-145,-104,-54,2,55,
+110,179,260,329,385,449,535,618,678,723,757,761,732,738,874,1153,1476,1728,1855,1873,1840,
+1861,2038,2360,2653,2703,2461,2081,1760,1577,1497,1471,1488,1536,1587,1630,1688,1774,1862,1912,1921,1923,
+1941,1962,1957,1927,1896,1875,1848,1793,1721,1658,1616,1584,1548,1510,1479,1460,1451,1447,1442,1422,1378,
+1313,1234,1145,1045,941,844,754,668,585,509,446,391,336,274,201,115,27,-51,-119,-188,-265,
+-345,-415,-478,-542,-609,-667,-706,-729,-752,-789,-840,-895,-949,-1011,-1092,-1190,-1288,-1374,-1447,-1512,-1568,
+-1615,-1665,-1733,-1815,-1890,-1935,-1945,-1934,-1928,-1951,-2020,-2122,-2226,-2306,-2358,-2385,-2384,-2349,-2299,-2264,-2258,
+-2263,-2267,-2280,-2316,-2362,-2387,-2376,-2345,-2321,-2316,-2333,-2367,-2403,-2425,-2429,-2427,-2421,-2404,-2383,-2388,-2428,
+-2474,-2487,-2476,-2482,-2514,-2539,-2527,-2489,-2461,-2453,-2442,-2403,-2333,-2254,-2196,-2168,-2154,-2125,-2082,-2056,-2075,
+-2129,-2174,-2182,-2149,-2087,-2012,-1938,-1878,-1837,-1807,-1779,-1749,-1711,-1659,-1589,-1505,-1423,-1358,-1315,-1281,-1241,
+-1198,-1167,-1149,-1128,-1086,-1035,-996,-973,-950,-917,-876,-836,-795,-752,-710,-671,-636,-604,-575,-546,-513,
+-478,-445,-410,-366,-314,-265,-229,-203,-178,-150,-116,-75,-25,25,64,88,104,122,150,185,221,
+249,266,276,288,304,322,345,378,421,467,507,533,549,564,585,614,645,674,704,737,773,
+806,835,864,896,934,977,1021,1062,1101,1144,1197,1252,1297,1329,1358,1397,1446,1492,1528,1553,1574,
+1597,1621,1643,1659,1668,1675,1684,1700,1724,1763,1820,1888,1951,1997,2023,2035,2034,2023,2007,1995,1991,
+1990,1993,1998,2004,2003,1993,1982,1977,1976,1974,1965,1955,1946,1939,1932,1921,1910,1899,1887,1873,1859,
+1848,1838,1825,1810,1799,1792,1787,1780,1773,1769,1765,1761,1757,1755,1753,1753,1760,1774,1790,1802,1813,
+1824,1830,1825,1814,1818,1806,1804,1807,1812,1815,1812,1796,1774,1756,1746,1732,1709,1684,1667,1660,1656,
+1648,1626,1590,1553,1533,1525,1503,1455,1395,1348,1315,1292,1282,1288,1288,1257,1197,1142,1112,1092,1043,
+949,829,721,649,613,606,630,687,759,811,823,810,793,764,703,617,536,478,423,355,280,
+207,120,-2,-145,-266,-348,-418,-511,-628,-744,-844,-939,-1045,-1163,-1271,-1356,-1422,-1490,-1571,-1657,-1732,
+-1790,-1842,-1898,-1957,-2012,-2058,-2088,-2097,-2090,-2085,-2092,-2104,-2108,-2101,-2090,-2082,-2078,-2079,-2081,-2075,-2053,
+-2019,-1985,-1950,-1905,-1855,-1814,-1778,-1721,-1633,-1533,-1434,-1315,-1143,-934,-750,-643,-612,-630,-684,-779,-904,
+-1030,-1136,-1228,-1326,-1435,-1531,-1591,-1626,-1660,-1698,-1725,-1740,-1764,-1800,-1816,-1795,-1763,-1743,-1703,-1623,-1568,
+-1634,-1795,-1896,-1826,-1654,-1542,-1565,-1677,-1823,-1989,-2158,-2291,-2382,-2474,-2591,-2705,-2784,-2845,-2922,-3004,-3058,
+-3095,-3165,-3303,-3489,-3674,-3827,-3934,-4000,-4041,-4073,-4097,-4110,-4122,-4152,-4209,-4278,-4344,-4396,-4437,-4479,-4537,
+-4617,-4696,-4741,-4740,-4721,-4719,-4740,-4765,-4776,-4775,-4772,-4769,-4760,-4746,-4731,-4721,-4713,-4701,-4684,-4669,-4670,
+-4693,-4730,-4767,-4792,-4805,-4810,-4813,-4814,-4817,-4822,-4834,-4856,-4884,-4916,-4948,-4984,-5029,-5085,-5147,-5207,-5262,
+-5309,-5349,-5390,-5440,-5497,-5547,-5588,-5630,-5688,-5760,-5828,-5890,-5962,-6050,-6143,-6224,-6291,-6354,-6419,-6484,-6547,
+-6609,-6674,-6742,-6815,-6890,-6957,-7011,-7055,-7099,-7144,-7188,-7233,-7284,-7344,-7408,-7470,-7526,-7576,-7619,-7665,-7717,
+-7773,-7827,-7884,-7954,-8036,-8120,-8205,-8297,-8394,-8485,-8562,-8637,-8719,-8805,-8888,-8963,-9028,-9081,-9129,-9174,-9208,
+-9222,-9221,-9232,-9256,-9270,-9272,-9312,-9439,-9622,-9761,-9793,-9754,-9726,-9744,-9786,-9823,-9856,-9897,-9938,-9968,-9989,
+-10009,-10029,-10048,-10071,-10101,-10132,-10150,-10144,-10118,-10083,-10046,-10006,-9957,-9893,-9809,-9709,-9607,-9514,-9439,-9379,-9330,
+-9286,-9244,-9206,-9167,-9115,-9035,-8931,-8823,-8723,-8625,-8517,-8397,-8277,-8171,-8079,-7989,-7879,-7735,-7568,-7411,-7288,
+-7186,-7068,-6916,-6755,-6626,-6537,-6463,-6376,-6270,-6155,-6037,-5912,-5780,-5647,-5512,-5368,-5207,-5032,-4859,-4703,-4565,
+-4433,-4294,-4145,-3989,-3831,-3673,-3518,-3378,-3255,-3133,-2991,-2831,-2694,-2616,-2593,-2597,-2599,-2572,-2470,-2257,-1971,
+-1732,-1639,-1671,-1716,-1675,-1527,-1294,-987,-614,-223,108,323,419,452,491,570,677,776,859,944,1044,
+1152,1252,1343,1431,1520,1609,1702,1800,1895,1981,2064,2152,2238,2316,2390,2472,2563,2654,2744,2842,2949,
+3053,3142,3215,3283,3352,3426,3511,3609,3710,3805,3893,3986,4086,4178,4246,4299,4362,4445,4526,4582,4621,
+4674,4755,4850,4951,5056,5152,5207,5220,5232,5274,5322,5325,5268,5191,5141,5157,5257,5427,5614,5767,5905,
+6082,6296,6463,6511,6476,6457,6487,6504,6433,6290,6165,6125,6153,6182,6173,6141,6112,6084,6043,6004,6001,
+6036,6075,6098,6111,6108,6051,5943,5870,5921,6077,6224,6282,6284,6314,6404,6523,6639,6740,6828,6897,6944,
+6969,6978,6988,7017,7073,7136,7181,7200,7206,7214,7229,7245,7256,7258,7255,7259,7276,7299,7310,7298,7275,
+7269,7300,7363,7432,7481,7501,7500,7494,7495,7518,7558,7588,7560,7452,7293,7150,7072,7062,7087,7111,7123,
+7131,7148,7177,7218,7272,7343,7428,7510,7566,7584,7580,7594,7653,7738,7800,7809,7777,7733,7687,7639,7596,
+7576,7574,7569,7550,7530,7522,7516,7495,7453,7396,7332,7276,7251,7260,7276,7268,7226,7159,7069,6952,6825,
+6715,6621,6503,6340,6182,6116,6182,6312,6389,6346,6221,6106,6060,6076,6107,6121,6113,6097,6082,6069,6046,
+6007,5959,5916,5874,5814,5733,5651,5589,5540,5481,5405,5324,5246,5168,5088,5014,4951,4898,4860,4843,4837,
+4812,4748,4665,4600,4570,4555,4526,4475,4415,4360,4307,4253,4204,4166,4136,4103,4064,4026,3996,3970,3944,
+3916,3887,3855,3820,3788,3761,3732,3689,3633,3573,3517,3467,3419,3370,3327,3297,3280,3263,3239,3214,3191,
+3150,3071,2973,2898,2857,2810,2729,2655,2651,2715,2785,2810,2802,2788,2766,2715,2638,2556,2485,2432,2398,
+2382,2373,2358,2336,2311,2282,2253,2229,2213,2195,2168,2139,2113,2087,2057,2030,2013,2001,1985,1966,1947,
+1927,1904,1887,1884,1887,1882,1882,1913,1969,2001,1968,1882,1792,1739,1725,1734,1746,1748,1732,1706,1678,
+1651,1623,1597,1581,1578,1581,1584,1586,1587,1589,1594,1605,1617,1614,1590,1556,1527,1513,1511,1517,1527,
+1534,1535,1528,1520,1512,1502,1492,1487,1488,1489,1491,1497,1505,1508,1502,1493,1483,1470,1452,1440,1440,
+1451,1466,1485,1507,1525,1535,1545,1559,1569,1563,1549,1542,1547,1554,1555,1551,1541,1525,1510,1510,1524,
+1535,1530,1515,1506,1505,1506,1505,1505,1502,1494,1479,1460,1439,1421,1410,1404,1396,1377,1353,1329,1306,
+1281,1257,1241,1231,1220,1204,1187,1172,1155,1133,1109,1084,1062,1042,1023,1003,982,961,940,915,885,
+855,829,805,780,752,723,691,655,621,592,566,538,510,486,463,434,395,352,309,269,230,
+194,163,130,95,57,21,-11,-43,-75,-110,-148,-190,-232,-274,-314,-351,-381,-406,-436,-473,-513,
+-551,-587,-620,-648,-670,-687,-706,-729,-758,-792,-829,-866,-899,-926,-953,-981,-1012,-1046,-1081,-1116,-1148,
+-1179,-1211,-1239,-1260,-1277,-1297,-1325,-1357,-1391,-1425,-1458,-1489,-1517,-1544,-1573,-1602,-1628,-1651,-1674,-1700,-1725,
+-1747,-1768,-1789,-1810,-1829,-1847,-1868,-1890,-1911,-1931,-1948,-1964,-1980,-1997,-2014,-2031,-2044,-2056,-2066,-2076,-2084,
+-2092,-2102,-2114,-2127,-2140,-2150,-2154,-2153,-2152,-2154,-2155,-2152,-2147,-2142,-2138,-2130,-2119,-2110,-2103,-2095,-2085,
+-2072,-2060,-2046,-2032,-2019,-2008,-1996,-1982,-1969,-1958,-1949,-1939,-1928,-1916,-1904,-1891,-1877,-1864,-1850,-1837,-1825,
+-1816,-1806,-1796,-1786,-1777,-1767,-1755,-1741,-1728,-1718,-1708,-1697,-1686,-1676,-1669,-1660,-1650,-1641,-1635,-1629,-1618,
+-1604,-1592,-1584,-1575,-1564,-1552,-1542,-1530,-1516,-1502,-1491,-1481,-1468,-1453,-1439,-1428,-1414,-1402,-1393,-1386,-1374,
+-1359,-1347,-1338,-1328,-1316,-1304,-1292,-1279,-1266,-1256,-1247,-1233,-1215,-1200,-1190,-1178,-1162,-1145,-1128,-1108,-1084,
+-1062,-1040,-1014,-985,-964,-953,-948,-948,-950,-943,-903,-832,-765,-734,-726,-707,-664,-616,-580,-554,-526,
+-496,-461,-422,-376,-331,-288,-247,-205,-162,-116,-64,-9,41,94,157,229,293,350,413,487,557,
+614,660,691,688,664,693,856,1151,1485,1755,1915,1965,1941,1933,2058,2350,2672,2791,2591,2182,1783,
+1540,1447,1434,1457,1501,1555,1611,1678,1765,1852,1904,1918,1923,1939,1951,1938,1907,1883,1870,1845,1794,
+1731,1678,1638,1599,1557,1523,1501,1489,1480,1474,1469,1450,1408,1343,1266,1179,1082,983,888,801,716,
+634,564,509,465,414,347,261,161,63,-20,-92,-164,-242,-321,-390,-451,-517,-589,-654,-701,-732,
+-761,-802,-853,-909,-963,-1023,-1100,-1190,-1285,-1374,-1451,-1513,-1556,-1586,-1623,-1684,-1761,-1824,-1848,-1834,-1806,
+-1801,-1847,-1949,-2079,-2196,-2276,-2319,-2335,-2321,-2279,-2231,-2207,-2212,-2225,-2230,-2240,-2273,-2318,-2344,-2339,-2320,
+-2311,-2317,-2334,-2359,-2387,-2409,-2418,-2421,-2420,-2407,-2388,-2391,-2429,-2474,-2488,-2472,-2468,-2494,-2523,-2524,-2509,
+-2514,-2544,-2568,-2551,-2483,-2381,-2277,-2203,-2163,-2133,-2088,-2034,-2002,-2007,-2030,-2040,-2023,-1980,-1918,-1848,-1786,
+-1743,-1717,-1698,-1678,-1657,-1633,-1597,-1531,-1439,-1348,-1288,-1259,-1237,-1207,-1178,-1162,-1151,-1130,-1098,-1069,-1044,
+-1014,-975,-935,-900,-866,-827,-785,-748,-716,-691,-671,-651,-624,-591,-560,-528,-487,-434,-385,-352,-332,
+-311,-285,-257,-228,-195,-158,-123,-91,-61,-30,5,47,92,132,163,189,217,253,294,335,378,
+424,471,511,539,554,565,579,599,625,658,699,745,786,815,837,860,887,920,958,998,1038,
+1078,1125,1182,1238,1277,1298,1316,1347,1387,1425,1453,1475,1493,1510,1530,1558,1591,1625,1657,1686,1714,
+1741,1776,1824,1882,1936,1974,1995,2003,2006,2007,2009,2010,2007,1999,1992,1991,1994,1994,1986,1976,1968,
+1963,1957,1948,1939,1933,1929,1924,1916,1905,1893,1878,1860,1843,1832,1821,1807,1789,1778,1776,1775,1771,
+1767,1765,1761,1756,1754,1757,1760,1761,1769,1788,1810,1823,1830,1837,1841,1834,1818,1819,1809,1812,1825,
+1836,1838,1828,1807,1781,1757,1738,1716,1690,1668,1653,1641,1628,1614,1592,1555,1510,1472,1449,1427,1396,
+1358,1318,1279,1245,1228,1222,1198,1137,1060,1019,1029,1048,1016,913,773,652,579,546,534,535,562,
+617,681,730,758,769,753,698,614,537,484,440,383,314,241,153,38,-94,-215,-312,-403,-509,
+-624,-730,-822,-911,-1005,-1101,-1192,-1280,-1367,-1455,-1545,-1633,-1709,-1766,-1805,-1842,-1890,-1952,-2012,-2050,-2061,
+-2058,-2060,-2075,-2087,-2083,-2069,-2059,-2058,-2058,-2055,-2053,-2047,-2028,-1997,-1964,-1929,-1883,-1830,-1787,-1757,-1717,
+-1651,-1570,-1486,-1370,-1184,-953,-758,-661,-654,-694,-755,-835,-930,-1023,-1113,-1216,-1341,-1472,-1573,-1629,-1656,
+-1686,-1723,-1753,-1770,-1791,-1822,-1840,-1823,-1783,-1741,-1691,-1632,-1625,-1728,-1887,-1950,-1837,-1646,-1543,-1585,-1707,
+-1848,-2002,-2166,-2305,-2403,-2495,-2608,-2723,-2811,-2878,-2940,-2989,-3019,-3064,-3178,-3367,-3580,-3764,-3895,-3977,-4023,
+-4051,-4076,-4094,-4100,-4107,-4141,-4210,-4295,-4370,-4425,-4465,-4500,-4538,-4589,-4644,-4682,-4692,-4686,-4688,-4702,-4717,
+-4723,-4727,-4735,-4742,-4735,-4715,-4693,-4681,-4674,-4663,-4645,-4631,-4634,-4658,-4695,-4730,-4756,-4774,-4788,-4798,-4802,
+-4798,-4792,-4796,-4817,-4851,-4887,-4919,-4953,-4998,-5054,-5112,-5167,-5220,-5268,-5311,-5351,-5399,-5456,-5508,-5547,-5583,
+-5637,-5711,-5789,-5859,-5930,-6011,-6097,-6179,-6252,-6321,-6389,-6453,-6514,-6575,-6639,-6707,-6779,-6850,-6910,-6958,-7002,
+-7051,-7103,-7150,-7192,-7238,-7294,-7356,-7418,-7475,-7527,-7576,-7627,-7681,-7733,-7782,-7837,-7905,-7984,-8066,-8153,-8250,
+-8349,-8437,-8513,-8589,-8673,-8759,-8835,-8900,-8957,-9011,-9065,-9117,-9156,-9171,-9173,-9185,-9207,-9220,-9230,-9286,-9421,
+-9593,-9711,-9733,-9699,-9683,-9708,-9753,-9797,-9840,-9885,-9924,-9949,-9964,-9979,-9995,-10009,-10027,-10054,-10084,-10100,-10093,
+-10068,-10037,-10000,-9953,-9888,-9809,-9719,-9625,-9530,-9439,-9360,-9299,-9254,-9215,-9176,-9133,-9088,-9035,-8967,-8885,-8797,
+-8710,-8616,-8508,-8386,-8268,-8162,-8066,-7963,-7832,-7668,-7489,-7336,-7232,-7155,-7057,-6918,-6770,-6656,-6577,-6498,-6394,
+-6268,-6142,-6020,-5898,-5773,-5645,-5514,-5373,-5215,-5044,-4872,-4716,-4582,-4460,-4332,-4187,-4030,-3871,-3712,-3557,-3411,
+-3281,-3154,-3013,-2864,-2738,-2660,-2617,-2584,-2551,-2520,-2463,-2331,-2115,-1885,-1736,-1694,-1702,-1683,-1593,-1418,-1143,
+-767,-340,52,330,471,514,531,577,663,767,864,954,1052,1164,1277,1375,1456,1526,1601,1688,1786,
+1884,1973,2056,2140,2229,2317,2401,2483,2565,2649,2736,2828,2928,3028,3120,3196,3259,3321,3392,3474,3561,
+3652,3746,3842,3937,4031,4117,4187,4242,4296,4366,4446,4514,4565,4616,4681,4759,4847,4946,5043,5112,5152,
+5198,5270,5335,5334,5261,5168,5117,5138,5249,5446,5686,5901,6066,6217,6379,6510,6550,6508,6449,6412,6363,
+6259,6122,6027,6023,6085,6145,6161,6143,6125,6118,6115,6123,6159,6222,6288,6341,6380,6393,6349,6254,6171,
+6152,6164,6125,6021,5934,5953,6077,6236,6376,6493,6607,6719,6812,6866,6878,6874,6886,6927,6979,7021,7055,
+7088,7112,7106,7068,7011,6959,6937,6971,7058,7154,7210,7212,7189,7175,7183,7210,7255,7309,7350,7364,7366,
+7383,7428,7487,7532,7536,7480,7370,7241,7145,7109,7121,7140,7140,7124,7113,7124,7166,7242,7347,7465,7566,
+7628,7648,7650,7666,7707,7756,7791,7809,7822,7830,7819,7790,7765,7763,7775,7778,7768,7759,7751,7726,7678,
+7622,7571,7516,7448,7380,7333,7309,7301,7298,7284,7232,7130,7009,6918,6862,6788,6644,6457,6316,6282,6326,
+6358,6321,6237,6164,6134,6136,6145,6150,6147,6136,6121,6108,6093,6062,6013,5958,5906,5848,5773,5688,5616,
+5559,5502,5433,5356,5279,5202,5126,5056,4997,4952,4921,4906,4894,4860,4791,4708,4645,4613,4591,4554,4503,
+4450,4399,4344,4288,4242,4213,4187,4150,4103,4063,4037,4017,3992,3959,3923,3886,3850,3820,3797,3773,3735,
+3682,3622,3565,3514,3466,3416,3366,3326,3303,3291,3277,3257,3231,3189,3116,3025,2953,2913,2874,2807,2727,
+2681,2685,2715,2750,2784,2803,2779,2708,2622,2551,2497,2451,2423,2418,2421,2409,2377,2340,2306,2278,2256,
+2240,2220,2188,2150,2118,2092,2061,2026,1999,1982,1970,1958,1949,1941,1926,1906,1890,1880,1871,1870,1893,
+1932,1948,1914,1844,1780,1745,1737,1742,1750,1749,1730,1701,1674,1651,1623,1592,1573,1577,1595,1611,1616,
+1614,1611,1612,1623,1641,1648,1629,1588,1549,1528,1523,1526,1529,1532,1532,1528,1522,1518,1514,1508,1503,
+1500,1501,1504,1509,1512,1511,1504,1495,1489,1478,1460,1441,1431,1435,1448,1468,1489,1506,1517,1526,1537,
+1545,1543,1538,1537,1540,1541,1538,1532,1521,1501,1484,1485,1502,1512,1504,1488,1482,1486,1490,1487,1483,
+1481,1477,1470,1457,1440,1422,1409,1402,1394,1376,1353,1329,1306,1280,1256,1240,1229,1217,1199,1182,1168,
+1151,1129,1102,1076,1052,1029,1007,986,965,945,924,899,869,839,813,790,766,739,711,680,648,
+617,591,566,539,512,486,463,434,397,357,316,275,236,200,169,138,103,65,27,-8,-42,
+-77,-114,-156,-201,-244,-284,-322,-356,-385,-412,-441,-474,-508,-540,-573,-608,-639,-662,-678,-692,-708,
+-731,-762,-800,-838,-872,-903,-932,-962,-993,-1025,-1058,-1089,-1118,-1149,-1181,-1212,-1237,-1259,-1285,-1317,-1349,
+-1379,-1407,-1436,-1463,-1486,-1510,-1539,-1571,-1600,-1625,-1651,-1678,-1705,-1727,-1747,-1765,-1783,-1800,-1817,-1835,-1854,
+-1874,-1895,-1916,-1935,-1952,-1969,-1987,-2002,-2013,-2021,-2030,-2040,-2050,-2059,-2068,-2078,-2090,-2102,-2112,-2119,-2121,
+-2121,-2121,-2120,-2116,-2108,-2103,-2099,-2094,-2087,-2079,-2071,-2062,-2051,-2038,-2024,-2010,-1997,-1984,-1973,-1961,-1949,
+-1938,-1926,-1915,-1903,-1893,-1884,-1874,-1863,-1851,-1839,-1826,-1812,-1799,-1789,-1779,-1768,-1757,-1748,-1740,-1730,-1718,
+-1706,-1697,-1688,-1678,-1666,-1656,-1650,-1643,-1632,-1622,-1616,-1612,-1604,-1592,-1580,-1573,-1563,-1550,-1538,-1529,-1521,
+-1509,-1495,-1482,-1472,-1460,-1448,-1439,-1430,-1418,-1406,-1398,-1391,-1380,-1364,-1352,-1344,-1337,-1326,-1314,-1301,-1288,
+-1274,-1265,-1256,-1244,-1228,-1216,-1208,-1197,-1180,-1162,-1146,-1126,-1102,-1079,-1058,-1036,-1011,-987,-967,-949,-933,
+-926,-924,-909,-871,-827,-797,-777,-747,-702,-657,-622,-591,-556,-516,-478,-439,-396,-351,-307,-267,-224,
+-178,-127,-74,-21,29,83,140,202,264,327,388,446,499,555,609,639,626,598,635,805,1086,
+1389,1629,1778,1849,1870,1901,2041,2343,2710,2912,2773,2341,1850,1517,1386,1375,1403,1450,1518,1598,1675,
+1752,1826,1887,1925,1946,1956,1952,1930,1904,1891,1882,1855,1804,1748,1702,1660,1616,1576,1552,1541,1529,
+1513,1499,1489,1468,1425,1360,1284,1199,1107,1013,924,842,763,688,628,583,542,486,406,305,195,
+89,-1,-78,-148,-217,-285,-350,-416,-492,-572,-643,-697,-739,-783,-835,-892,-946,-996,-1052,-1120,-1202,
+-1292,-1382,-1459,-1514,-1545,-1563,-1590,-1638,-1697,-1740,-1747,-1719,-1686,-1688,-1751,-1868,-2002,-2116,-2192,-2234,-2247,
+-2232,-2198,-2164,-2151,-2159,-2167,-2168,-2175,-2203,-2244,-2271,-2276,-2276,-2287,-2305,-2322,-2342,-2368,-2394,-2411,-2425,
+-2442,-2453,-2456,-2464,-2491,-2520,-2520,-2494,-2476,-2487,-2506,-2513,-2525,-2570,-2640,-2692,-2692,-2635,-2533,-2409,-2298,
+-2229,-2197,-2162,-2101,-2026,-1968,-1935,-1918,-1903,-1880,-1836,-1768,-1689,-1627,-1594,-1582,-1575,-1577,-1593,-1608,-1585,
+-1504,-1396,-1316,-1290,-1293,-1287,-1262,-1236,-1216,-1197,-1170,-1136,-1094,-1046,-995,-953,-920,-890,-855,-819,-785,
+-754,-727,-708,-690,-664,-631,-598,-569,-535,-491,-448,-418,-399,-379,-352,-325,-300,-275,-245,-210,-170,
+-128,-89,-52,-13,31,78,119,155,191,235,285,333,378,418,456,489,515,531,542,554,572,
+598,632,675,720,755,777,792,811,836,866,900,941,983,1025,1071,1128,1187,1233,1259,1279,1305,
+1336,1364,1391,1420,1448,1473,1500,1534,1576,1620,1661,1700,1735,1763,1790,1823,1864,1903,1935,1956,1967,
+1974,1984,1998,2010,2010,1999,1987,1982,1980,1977,1972,1967,1962,1956,1948,1939,1930,1922,1916,1911,1903,
+1893,1881,1867,1850,1834,1822,1813,1801,1784,1772,1768,1766,1762,1759,1759,1757,1752,1751,1758,1767,1773,
+1783,1805,1827,1838,1839,1839,1841,1834,1819,1819,1813,1822,1836,1842,1834,1816,1794,1772,1750,1727,1701,
+1675,1654,1632,1607,1579,1559,1541,1512,1466,1416,1376,1350,1328,1301,1264,1221,1183,1161,1142,1095,1014,
+939,921,964,1013,1003,911,767,625,525,476,462,462,476,515,575,639,689,715,708,666,601,
+538,493,456,407,342,267,182,79,-39,-158,-272,-387,-509,-625,-722,-807,-894,-985,-1069,-1146,-1227,
+-1319,-1412,-1502,-1589,-1669,-1727,-1753,-1765,-1793,-1851,-1923,-1980,-2009,-2019,-2030,-2049,-2060,-2051,-2032,-2024,-2028,
+-2030,-2023,-2016,-2012,-2000,-1975,-1942,-1906,-1861,-1808,-1762,-1729,-1689,-1626,-1557,-1488,-1383,-1199,-964,-772,-688,
+-692,-732,-785,-859,-946,-1030,-1113,-1219,-1353,-1489,-1589,-1643,-1672,-1704,-1744,-1777,-1796,-1814,-1844,-1866,-1853,
+-1805,-1748,-1703,-1684,-1723,-1833,-1952,-1965,-1832,-1655,-1572,-1620,-1730,-1850,-1989,-2154,-2310,-2426,-2519,-2623,-2740,
+-2845,-2924,-2968,-2979,-2986,-3051,-3214,-3439,-3653,-3813,-3920,-3990,-4031,-4052,-4067,-4078,-4083,-4094,-4135,-4212,-4302,
+-4379,-4436,-4478,-4507,-4529,-4555,-4590,-4619,-4633,-4636,-4642,-4654,-4663,-4666,-4672,-4686,-4698,-4695,-4676,-4656,-4644,
+-4636,-4622,-4603,-4591,-4598,-4625,-4661,-4693,-4718,-4738,-4757,-4772,-4775,-4765,-4750,-4749,-4771,-4807,-4842,-4868,-4899,
+-4948,-5012,-5076,-5130,-5179,-5227,-5271,-5311,-5355,-5409,-5464,-5510,-5549,-5599,-5668,-5749,-5828,-5902,-5976,-6053,-6132,
+-6207,-6279,-6346,-6411,-6475,-6540,-6606,-6673,-6741,-6808,-6867,-6916,-6963,-7014,-7068,-7115,-7155,-7196,-7247,-7306,-7368,
+-7428,-7485,-7539,-7591,-7641,-7687,-7734,-7790,-7859,-7936,-8016,-8102,-8198,-8295,-8381,-8460,-8542,-8629,-8711,-8776,-8829,
+-8881,-8941,-9008,-9072,-9116,-9132,-9134,-9142,-9156,-9166,-9189,-9264,-9405,-9562,-9658,-9673,-9652,-9652,-9684,-9729,-9774,
+-9821,-9867,-9900,-9918,-9928,-9939,-9949,-9956,-9967,-9988,-10015,-10031,-10026,-10004,-9974,-9936,-9881,-9805,-9716,-9627,-9545,
+-9463,-9376,-9290,-9216,-9162,-9120,-9078,-9033,-8989,-8947,-8900,-8844,-8779,-8706,-8617,-8506,-8382,-8261,-8148,-8039,-7921,
+-7784,-7623,-7455,-7312,-7214,-7141,-7047,-6915,-6776,-6667,-6584,-6491,-6370,-6236,-6111,-5996,-5881,-5763,-5642,-5514,-5374,
+-5220,-5056,-4889,-4734,-4602,-4486,-4365,-4223,-4065,-3905,-3749,-3595,-3450,-3317,-3187,-3045,-2899,-2778,-2700,-2644,-2578,
+-2501,-2438,-2397,-2342,-2231,-2069,-1906,-1786,-1714,-1663,-1593,-1465,-1238,-898,-484,-69,266,482,580,605,619,
+667,754,854,951,1052,1168,1292,1400,1476,1530,1586,1662,1758,1861,1955,2038,2118,2209,2309,2406,2490,
+2567,2647,2734,2823,2912,3003,3093,3172,3236,3296,3364,3438,3515,3596,3687,3781,3868,3948,4027,4102,4163,
+4214,4277,4361,4448,4514,4557,4596,4648,4729,4843,4969,5067,5128,5186,5270,5348,5366,5313,5232,5171,5158,
+5231,5430,5732,6040,6257,6372,6433,6467,6459,6410,6355,6316,6267,6175,6050,5951,5923,5956,6000,6013,5996,
+5979,5984,6008,6044,6098,6173,6254,6324,6370,6383,6356,6298,6238,6180,6078,5899,5693,5576,5618,5780,5966,
+6116,6231,6337,6447,6548,6616,6644,6654,6682,6742,6813,6875,6934,6994,7031,7020,6963,6890,6830,6807,6848,
+6953,7072,7141,7140,7102,7065,7039,7031,7061,7128,7196,7228,7235,7252,7289,7333,7372,7405,7413,7372,7293,
+7233,7235,7284,7324,7319,7280,7239,7221,7232,7280,7359,7457,7550,7622,7672,7709,7744,7774,7793,7801,7818,
+7853,7889,7901,7888,7883,7906,7940,7955,7950,7940,7925,7884,7816,7747,7698,7656,7599,7525,7452,7400,7377,
+7380,7380,7337,7233,7109,7025,6996,6970,6883,6732,6573,6452,6364,6278,6196,6147,6149,6175,6188,6179,6172,
+6178,6182,6171,6149,6128,6102,6058,5998,5937,5879,5813,5735,5657,5591,5531,5469,5403,5334,5260,5182,5110,
+5052,5012,4986,4969,4946,4899,4824,4741,4679,4644,4616,4576,4526,4477,4430,4378,4326,4288,4264,4235,4187,
+4130,4089,4071,4057,4029,3988,3948,3916,3890,3866,3841,3810,3770,3724,3675,3623,3571,3521,3468,3410,3353,
+3316,3304,3299,3284,3253,3208,3148,3078,3017,2971,2926,2863,2788,2725,2688,2680,2704,2752,2786,2771,2714,
+2655,2612,2565,2501,2449,2437,2448,2442,2408,2366,2332,2305,2282,2264,2246,2216,2177,2141,2109,2073,2034,
+2003,1986,1976,1967,1962,1959,1951,1933,1912,1890,1870,1856,1857,1863,1849,1807,1761,1740,1743,1752,1758,
+1759,1750,1726,1698,1687,1688,1676,1640,1600,1584,1595,1616,1633,1642,1642,1635,1629,1633,1637,1624,1592,
+1560,1548,1551,1554,1550,1542,1535,1527,1519,1515,1514,1513,1511,1510,1509,1509,1509,1510,1509,1506,1500,
+1493,1482,1464,1443,1430,1430,1443,1461,1475,1485,1491,1497,1502,1506,1508,1512,1519,1524,1525,1523,1520,
+1511,1491,1471,1467,1478,1485,1479,1468,1466,1470,1472,1468,1465,1462,1459,1454,1448,1439,1426,1414,1406,
+1397,1379,1354,1328,1302,1277,1255,1239,1227,1212,1192,1174,1158,1140,1117,1092,1067,1042,1016,992,971,
+952,932,908,879,850,822,797,774,750,722,693,664,636,608,581,555,526,497,470,444,416,
+383,348,313,275,237,201,171,141,108,70,32,-5,-41,-79,-119,-162,-206,-249,-287,-321,-352,
+-381,-410,-441,-472,-500,-527,-557,-592,-626,-655,-675,-689,-701,-717,-742,-776,-813,-847,-879,-910,-941,
+-970,-1000,-1032,-1062,-1089,-1116,-1146,-1177,-1206,-1233,-1264,-1298,-1331,-1360,-1387,-1413,-1436,-1458,-1481,-1510,-1542,
+-1572,-1599,-1626,-1655,-1682,-1705,-1722,-1737,-1751,-1767,-1784,-1801,-1818,-1837,-1859,-1882,-1901,-1916,-1932,-1951,-1966,
+-1975,-1982,-1992,-2005,-2017,-2027,-2036,-2044,-2053,-2061,-2070,-2078,-2082,-2083,-2083,-2081,-2076,-2069,-2061,-2056,-2053,
+-2050,-2045,-2038,-2028,-2015,-2001,-1986,-1972,-1960,-1949,-1939,-1928,-1918,-1907,-1894,-1880,-1868,-1858,-1849,-1840,-1830,
+-1821,-1812,-1800,-1787,-1775,-1764,-1753,-1741,-1729,-1719,-1711,-1702,-1692,-1681,-1673,-1666,-1658,-1648,-1639,-1632,-1625,
+-1614,-1602,-1596,-1593,-1588,-1578,-1567,-1560,-1552,-1540,-1526,-1518,-1512,-1503,-1490,-1477,-1466,-1455,-1445,-1438,-1432,
+-1422,-1410,-1402,-1396,-1386,-1372,-1360,-1352,-1345,-1335,-1326,-1316,-1304,-1290,-1278,-1268,-1257,-1244,-1234,-1227,-1216,
+-1199,-1181,-1165,-1147,-1123,-1100,-1080,-1059,-1037,-1015,-994,-968,-935,-906,-891,-881,-860,-829,-797,-767,-733,
+-694,-658,-628,-597,-558,-518,-483,-450,-412,-368,-324,-284,-240,-190,-137,-86,-36,17,74,128,182,
+243,310,369,414,457,518,581,606,577,543,586,749,991,1225,1387,1482,1557,1654,1797,2016,2333,
+2688,2900,2790,2363,1837,1463,1320,1316,1344,1387,1465,1569,1662,1733,1799,1870,1936,1976,1985,1968,1941,
+1922,1916,1906,1873,1822,1772,1729,1685,1638,1603,1587,1580,1565,1544,1527,1513,1489,1441,1372,1292,1206,
+1115,1025,943,869,801,740,690,650,604,536,444,334,220,111,14,-67,-133,-189,-243,-305,-380,
+-467,-555,-629,-688,-742,-804,-872,-935,-986,-1032,-1084,-1147,-1223,-1310,-1397,-1470,-1517,-1541,-1557,-1578,-1607,
+-1635,-1652,-1649,-1627,-1610,-1626,-1692,-1795,-1904,-1997,-2067,-2113,-2133,-2128,-2110,-2093,-2086,-2085,-2082,-2082,-2096,
+-2132,-2175,-2205,-2219,-2231,-2254,-2277,-2295,-2313,-2340,-2373,-2402,-2430,-2467,-2508,-2540,-2561,-2580,-2591,-2576,-2541,
+-2512,-2503,-2499,-2499,-2528,-2607,-2706,-2768,-2768,-2718,-2634,-2520,-2401,-2315,-2280,-2262,-2219,-2142,-2053,-1976,-1922,
+-1888,-1863,-1819,-1738,-1633,-1544,-1496,-1480,-1474,-1478,-1507,-1555,-1578,-1535,-1440,-1357,-1333,-1354,-1370,-1353,-1315,
+-1277,-1242,-1201,-1149,-1090,-1031,-977,-935,-901,-870,-839,-810,-781,-746,-710,-680,-658,-634,-602,-568,-541,
+-517,-488,-457,-432,-414,-393,-365,-335,-306,-278,-246,-209,-169,-126,-88,-57,-28,5,47,89,127,
+161,198,240,283,319,347,372,398,421,440,453,468,491,521,556,595,634,665,687,708,736,
+768,800,835,877,922,960,996,1040,1092,1138,1172,1202,1236,1271,1306,1345,1392,1441,1484,1522,1561,
+1598,1632,1663,1696,1729,1757,1782,1808,1839,1873,1909,1940,1960,1968,1975,1989,2001,2000,1988,1976,1970,
+1965,1959,1955,1954,1952,1947,1940,1934,1925,1914,1903,1896,1887,1878,1868,1860,1847,1832,1821,1814,1805,
+1792,1779,1772,1765,1758,1755,1756,1757,1754,1754,1762,1773,1781,1793,1813,1833,1841,1837,1835,1836,1831,
+1819,1819,1818,1829,1840,1834,1813,1788,1769,1755,1737,1712,1681,1651,1623,1592,1555,1519,1497,1484,1462,
+1418,1362,1313,1280,1256,1229,1190,1145,1110,1088,1060,998,912,847,845,900,962,975,915,789,632,
+495,419,403,417,433,455,498,557,610,639,640,616,576,533,497,462,415,351,280,204,117,
+12,-107,-237,-374,-511,-631,-724,-803,-888,-978,-1061,-1133,-1206,-1289,-1373,-1453,-1533,-1611,-1668,-1684,-1674,
+-1676,-1719,-1795,-1874,-1932,-1964,-1985,-2007,-2021,-2016,-1998,-1986,-1986,-1986,-1980,-1978,-1985,-1985,-1963,-1926,-1886,
+-1843,-1793,-1747,-1706,-1658,-1593,-1530,-1473,-1377,-1197,-971,-801,-742,-753,-773,-801,-866,-960,-1050,-1129,-1227,
+-1356,-1487,-1585,-1643,-1680,-1717,-1757,-1791,-1811,-1826,-1849,-1870,-1862,-1817,-1762,-1731,-1739,-1790,-1875,-1950,-1943,
+-1828,-1678,-1600,-1629,-1719,-1829,-1964,-2134,-2304,-2436,-2532,-2627,-2742,-2864,-2961,-3001,-2987,-2980,-3061,-3254,-3491,
+-3688,-3819,-3909,-3979,-4022,-4038,-4042,-4049,-4061,-4083,-4131,-4207,-4290,-4362,-4420,-4465,-4496,-4513,-4531,-4555,-4576,
+-4586,-4590,-4601,-4618,-4629,-4633,-4637,-4645,-4650,-4643,-4627,-4612,-4604,-4596,-4581,-4563,-4553,-4562,-4589,-4623,-4653,
+-4676,-4696,-4715,-4729,-4730,-4716,-4700,-4699,-4723,-4759,-4789,-4812,-4843,-4897,-4967,-5034,-5088,-5133,-5179,-5226,-5270,
+-5312,-5360,-5416,-5470,-5518,-5567,-5628,-5703,-5782,-5857,-5930,-6006,-6086,-6164,-6235,-6300,-6364,-6431,-6500,-6565,-6628,
+-6692,-6759,-6822,-6876,-6925,-6974,-7025,-7074,-7118,-7161,-7207,-7262,-7323,-7387,-7448,-7504,-7553,-7597,-7638,-7685,-7745,
+-7815,-7889,-7964,-8046,-8138,-8232,-8321,-8407,-8496,-8582,-8656,-8712,-8761,-8814,-8878,-8951,-9020,-9067,-9087,-9093,-9101,
+-9107,-9113,-9146,-9239,-9387,-9527,-9601,-9612,-9608,-9625,-9661,-9701,-9740,-9782,-9821,-9848,-9863,-9873,-9882,-9887,-9889,
+-9894,-9909,-9932,-9949,-9948,-9932,-9904,-9866,-9810,-9733,-9645,-9562,-9490,-9419,-9332,-9229,-9130,-9053,-9003,-8968,-8938,
+-8913,-8892,-8866,-8827,-8773,-8705,-8615,-8501,-8372,-8243,-8121,-8001,-7876,-7747,-7611,-7470,-7339,-7234,-7147,-7044,-6911,
+-6772,-6657,-6560,-6453,-6328,-6204,-6094,-5988,-5876,-5760,-5642,-5517,-5376,-5222,-5062,-4904,-4756,-4627,-4513,-4392,-4249,
+-4088,-3926,-3772,-3624,-3483,-3352,-3220,-3074,-2925,-2801,-2719,-2653,-2564,-2447,-2344,-2296,-2294,-2286,-2221,-2091,-1926,
+-1769,-1647,-1555,-1456,-1294,-1032,-674,-268,119,426,612,681,687,698,755,847,951,1058,1175,1298,1404,
+1477,1524,1571,1639,1731,1837,1936,2020,2100,2193,2302,2405,2489,2560,2638,2728,2816,2896,2976,3061,3142,
+3211,3272,3334,3400,3470,3548,3639,3732,3812,3882,3956,4035,4104,4159,4221,4306,4399,4468,4503,4521,4556,
+4640,4778,4936,5058,5126,5176,5250,5334,5382,5374,5331,5268,5206,5211,5377,5714,6093,6348,6417,6369,6299,
+6254,6236,6242,6259,6249,6179,6055,5924,5836,5804,5804,5804,5798,5809,5851,5909,5962,6013,6074,6144,6199,
+6222,6216,6197,6172,6134,6056,5903,5685,5484,5405,5479,5646,5816,5943,6030,6097,6162,6227,6282,6314,6338,
+6393,6497,6619,6729,6825,6911,6966,6962,6911,6852,6811,6800,6834,6920,7018,7069,7050,6995,6942,6905,6898,
+6946,7050,7158,7222,7244,7260,7279,7291,7310,7353,7396,7395,7354,7340,7407,7518,7593,7593,7549,7501,7463,
+7434,7420,7432,7473,7534,7607,7684,7752,7801,7827,7835,7836,7848,7876,7908,7920,7915,7922,7959,8005,8028,
+8023,8009,7988,7947,7881,7811,7759,7725,7691,7647,7598,7553,7524,7515,7505,7455,7349,7221,7127,7084,7058,
+7003,6912,6800,6666,6493,6295,6135,6077,6123,6201,6236,6221,6201,6208,6226,6222,6191,6154,6122,6085,6033,
+5972,5912,5851,5784,5712,5641,5575,5514,5456,5397,5329,5251,5173,5111,5069,5043,5020,4987,4932,4855,4775,
+4713,4677,4647,4605,4551,4496,4447,4400,4357,4325,4300,4263,4205,4145,4108,4096,4081,4045,3997,3959,3938,
+3926,3910,3883,3847,3807,3768,3730,3685,3632,3577,3522,3457,3387,3334,3311,3306,3292,3259,3217,3174,3133,
+3091,3044,2986,2913,2837,2768,2716,2686,2689,2717,2738,2725,2697,2687,2686,2647,2560,2475,2445,2454,2454,
+2426,2391,2363,2337,2309,2289,2275,2253,2217,2176,2135,2092,2049,2018,2003,1995,1987,1980,1976,1970,1954,
+1930,1903,1879,1866,1863,1853,1816,1761,1722,1723,1747,1767,1774,1773,1762,1735,1712,1723,1759,1777,1744,
+1678,1622,1596,1598,1617,1644,1662,1657,1637,1623,1621,1616,1598,1580,1577,1582,1579,1564,1547,1536,1528,
+1522,1519,1518,1518,1516,1514,1513,1510,1506,1505,1509,1512,1509,1499,1485,1468,1451,1440,1441,1452,1463,
+1469,1469,1469,1469,1469,1471,1475,1484,1495,1503,1508,1511,1511,1504,1486,1465,1454,1455,1459,1460,1459,
+1457,1454,1451,1449,1450,1446,1437,1429,1428,1429,1426,1419,1412,1402,1384,1357,1325,1297,1274,1255,1240,
+1224,1205,1185,1167,1149,1128,1105,1082,1060,1033,1003,976,956,939,918,890,860,832,806,783,760,
+734,705,674,645,617,589,560,531,502,474,448,422,394,364,335,305,271,234,198,166,135,
+102,65,29,-6,-40,-76,-115,-157,-200,-240,-276,-307,-336,-364,-395,-428,-460,-489,-516,-545,-579,
+-615,-649,-677,-695,-705,-715,-734,-764,-797,-829,-860,-892,-923,-951,-980,-1011,-1042,-1070,-1094,-1120,-1148,
+-1176,-1204,-1235,-1269,-1303,-1334,-1362,-1389,-1413,-1435,-1459,-1488,-1520,-1548,-1575,-1602,-1630,-1656,-1679,-1697,-1710,
+-1721,-1734,-1751,-1768,-1784,-1801,-1822,-1844,-1861,-1873,-1888,-1906,-1922,-1932,-1940,-1952,-1968,-1982,-1993,-2003,-2012,
+-2018,-2022,-2026,-2033,-2038,-2040,-2040,-2039,-2037,-2031,-2022,-2015,-2012,-2012,-2010,-2003,-1993,-1979,-1965,-1950,-1936,
+-1926,-1917,-1907,-1896,-1885,-1873,-1860,-1847,-1835,-1826,-1816,-1805,-1794,-1787,-1780,-1771,-1761,-1750,-1739,-1726,-1713,
+-1701,-1691,-1683,-1676,-1667,-1656,-1646,-1639,-1635,-1629,-1622,-1614,-1606,-1596,-1585,-1578,-1576,-1572,-1563,-1553,-1547,
+-1541,-1531,-1518,-1509,-1504,-1496,-1485,-1475,-1465,-1454,-1444,-1437,-1432,-1424,-1414,-1406,-1401,-1393,-1383,-1373,-1364,
+-1355,-1345,-1337,-1331,-1322,-1309,-1296,-1285,-1274,-1263,-1254,-1245,-1233,-1216,-1200,-1185,-1168,-1146,-1125,-1106,-1087,
+-1064,-1042,-1023,-997,-958,-917,-886,-867,-848,-821,-788,-755,-723,-692,-664,-636,-604,-567,-531,-500,-469,
+-433,-389,-345,-303,-258,-205,-150,-101,-54,1,61,114,162,218,284,340,381,427,497,560,566,
+518,481,529,676,868,1030,1120,1167,1254,1445,1727,2036,2329,2574,2690,2559,2167,1684,1343,1229,1249,
+1284,1320,1399,1519,1630,1707,1773,1851,1931,1986,2002,1990,1969,1956,1947,1928,1891,1846,1807,1773,1733,
+1688,1651,1630,1615,1596,1577,1563,1549,1518,1461,1382,1291,1197,1106,1021,946,882,828,782,741,699,
+643,565,467,357,244,135,34,-51,-117,-168,-218,-279,-359,-451,-539,-614,-677,-740,-811,-885,-949,
+-999,-1047,-1100,-1162,-1233,-1314,-1398,-1469,-1515,-1543,-1564,-1580,-1583,-1574,-1562,-1558,-1562,-1580,-1621,-1686,-1758,
+-1822,-1878,-1933,-1980,-2008,-2015,-2014,-2014,-2010,-2000,-1993,-2006,-2046,-2100,-2149,-2177,-2187,-2197,-2217,-2241,-2260,
+-2282,-2315,-2358,-2396,-2431,-2476,-2533,-2585,-2620,-2639,-2640,-2621,-2588,-2558,-2539,-2518,-2504,-2532,-2619,-2722,-2777,
+-2764,-2714,-2649,-2562,-2456,-2367,-2326,-2319,-2305,-2259,-2189,-2109,-2032,-1969,-1916,-1850,-1747,-1620,-1511,-1449,-1421,
+-1396,-1369,-1368,-1407,-1456,-1463,-1413,-1349,-1322,-1339,-1360,-1351,-1314,-1266,-1218,-1166,-1108,-1049,-996,-952,-916,
+-883,-850,-819,-794,-768,-731,-684,-644,-617,-596,-569,-536,-508,-488,-470,-451,-433,-415,-392,-364,-332,
+-299,-265,-233,-201,-168,-133,-100,-74,-52,-27,5,44,80,111,140,171,204,232,251,266,285,
+307,328,345,365,393,426,460,494,528,558,586,619,660,702,739,776,822,871,909,937,968,
+1006,1044,1079,1116,1161,1209,1256,1307,1365,1425,1478,1525,1566,1599,1621,1640,1666,1698,1728,1757,1787,
+1817,1852,1894,1936,1964,1974,1977,1985,1991,1986,1971,1960,1957,1952,1944,1939,1938,1935,1928,1923,1922,
+1917,1905,1894,1887,1879,1870,1862,1858,1850,1836,1823,1816,1809,1798,1785,1776,1768,1760,1755,1758,1761,
+1761,1762,1769,1779,1785,1794,1809,1825,1831,1828,1828,1831,1828,1819,1819,1820,1834,1842,1827,1797,1770,
+1754,1742,1719,1684,1644,1607,1571,1534,1495,1461,1439,1425,1401,1359,1305,1256,1219,1190,1158,1116,1074,
+1043,1022,987,919,834,776,774,819,874,907,891,807,663,509,410,388,406,419,419,432,469,
+511,540,550,548,538,518,489,453,404,343,278,214,142,43,-83,-226,-374,-516,-640,-735,-812,
+-893,-983,-1068,-1138,-1203,-1273,-1344,-1411,-1478,-1546,-1595,-1606,-1586,-1569,-1591,-1658,-1752,-1839,-1897,-1931,-1958,
+-1980,-1985,-1969,-1948,-1938,-1936,-1936,-1946,-1964,-1971,-1948,-1907,-1865,-1825,-1780,-1734,-1692,-1643,-1584,-1531,-1480,
+-1380,-1195,-980,-848,-832,-856,-848,-834,-881,-983,-1084,-1159,-1243,-1357,-1479,-1575,-1640,-1688,-1730,-1769,-1803,
+-1824,-1834,-1842,-1851,-1844,-1810,-1769,-1748,-1755,-1783,-1831,-1887,-1901,-1830,-1701,-1604,-1604,-1688,-1810,-1950,-2109,
+-2274,-2416,-2525,-2621,-2733,-2864,-2978,-3030,-3017,-3009,-3094,-3285,-3509,-3684,-3798,-3884,-3956,-4000,-4013,-4014,-4022,
+-4042,-4074,-4126,-4194,-4266,-4333,-4394,-4446,-4480,-4501,-4519,-4539,-4552,-4553,-4555,-4573,-4600,-4619,-4625,-4625,-4623,
+-4615,-4600,-4582,-4572,-4567,-4560,-4545,-4529,-4520,-4525,-4545,-4573,-4602,-4628,-4650,-4669,-4681,-4679,-4664,-4649,-4654,
+-4681,-4716,-4745,-4771,-4809,-4866,-4932,-4993,-5040,-5081,-5125,-5175,-5224,-5269,-5313,-5363,-5419,-5475,-5528,-5584,-5648,
+-5718,-5789,-5864,-5947,-6035,-6117,-6187,-6250,-6314,-6382,-6449,-6510,-6569,-6632,-6701,-6768,-6827,-6876,-6922,-6974,-7030,
+-7084,-7132,-7176,-7224,-7282,-7345,-7406,-7462,-7507,-7545,-7584,-7636,-7701,-7770,-7836,-7903,-7981,-8071,-8167,-8261,-8354,
+-8444,-8524,-8590,-8648,-8705,-8764,-8827,-8892,-8952,-8995,-9021,-9041,-9057,-9062,-9065,-9106,-9216,-9367,-9489,-9542,-9550,
+-9562,-9593,-9631,-9662,-9691,-9722,-9751,-9774,-9791,-9804,-9810,-9810,-9808,-9810,-9822,-9841,-9859,-9867,-9858,-9835,-9800,
+-9752,-9686,-9607,-9530,-9463,-9394,-9301,-9178,-9048,-8946,-8892,-8877,-8879,-8884,-8883,-8866,-8828,-8770,-8697,-8603,-8485,
+-8349,-8215,-8090,-7967,-7845,-7730,-7620,-7505,-7383,-7267,-7160,-7044,-6906,-6763,-6638,-6528,-6416,-6302,-6198,-6105,-6004,
+-5886,-5766,-5651,-5528,-5384,-5224,-5064,-4912,-4773,-4649,-4533,-4408,-4259,-4095,-3935,-3789,-3651,-3520,-3390,-3253,-3097,
+-2940,-2812,-2728,-2654,-2548,-2403,-2268,-2201,-2218,-2273,-2291,-2222,-2062,-1854,-1657,-1513,-1415,-1313,-1142,-866,-498,
+-90,285,560,704,745,752,787,867,973,1085,1195,1299,1388,1454,1507,1561,1631,1723,1828,1928,2012,
+2092,2186,2294,2394,2473,2539,2615,2704,2788,2862,2936,3020,3106,3180,3242,3300,3360,3428,3508,3603,3698,
+3781,3854,3929,4009,4081,4141,4205,4283,4361,4418,4448,4470,4515,4610,4758,4921,5044,5108,5150,5213,5294,
+5362,5398,5399,5350,5256,5205,5328,5660,6058,6315,6341,6215,6081,6029,6070,6162,6249,6275,6216,6089,5943,
+5822,5747,5706,5684,5683,5721,5800,5887,5946,5981,6016,6057,6082,6079,6063,6054,6046,6011,5923,5781,5624,
+5519,5517,5607,5732,5838,5911,5957,5980,5995,6019,6045,6051,6048,6086,6199,6356,6510,6650,6782,6883,6916,
+6885,6838,6813,6816,6846,6904,6963,6978,6937,6876,6831,6818,6850,6950,7111,7276,7394,7461,7498,7507,7486,
+7470,7491,7522,7508,7458,7456,7553,7693,7778,7780,7747,7719,7692,7650,7602,7572,7568,7592,7644,7712,7775,
+7814,7833,7846,7860,7875,7890,7903,7910,7911,7923,7955,7995,8017,8015,8002,7987,7963,7919,7865,7816,7779,
+7755,7738,7719,7692,7663,7642,7625,7582,7498,7390,7291,7212,7138,7059,6989,6926,6830,6656,6418,6204,6106,
+6141,6234,6294,6288,6255,6243,6257,6261,6231,6181,6137,6104,6067,6012,5948,5884,5824,5763,5696,5627,5562,
+5505,5452,5392,5318,5240,5173,5127,5095,5063,5022,4967,4898,4826,4768,4730,4700,4654,4587,4515,4457,4413,
+4380,4352,4324,4283,4227,4174,4143,4127,4102,4056,4007,3976,3963,3952,3936,3912,3881,3847,3815,3782,3741,
+3688,3630,3570,3504,3430,3367,3331,3315,3296,3264,3228,3199,3178,3155,3119,3062,2982,2895,2818,2758,2717,
+2699,2695,2686,2661,2648,2671,2702,2679,2591,2499,2462,2470,2474,2455,2430,2409,2381,2345,2317,2302,2285,
+2252,2208,2161,2112,2065,2030,2015,2009,2002,1994,1988,1981,1965,1940,1912,1890,1885,1892,1888,1853,1797,
+1757,1752,1767,1779,1784,1788,1781,1755,1734,1753,1810,1852,1834,1764,1681,1618,1587,1591,1623,1659,1667,
+1648,1628,1625,1628,1621,1609,1604,1604,1594,1572,1550,1539,1539,1541,1542,1539,1532,1525,1523,1523,1519,
+1510,1506,1511,1518,1516,1506,1493,1481,1470,1461,1459,1462,1464,1461,1457,1452,1448,1447,1448,1454,1463,
+1473,1483,1491,1496,1495,1488,1475,1458,1443,1437,1440,1450,1455,1448,1434,1424,1424,1429,1425,1410,1395,
+1394,1403,1411,1411,1407,1399,1382,1354,1322,1294,1273,1257,1241,1222,1201,1182,1165,1144,1120,1096,1075,
+1054,1025,992,963,942,925,902,874,844,817,792,769,746,721,692,660,627,595,564,533,503,
+476,452,428,403,375,346,319,292,262,227,191,156,123,90,56,22,-8,-38,-70,-106,-144,
+-184,-223,-258,-289,-317,-344,-375,-411,-446,-479,-509,-539,-571,-607,-645,-681,-705,-717,-724,-739,-764,
+-795,-823,-852,-883,-914,-942,-968,-999,-1033,-1063,-1087,-1109,-1133,-1158,-1183,-1209,-1239,-1271,-1303,-1335,-1365,
+-1391,-1415,-1442,-1472,-1503,-1529,-1553,-1577,-1602,-1626,-1650,-1672,-1687,-1698,-1707,-1720,-1736,-1751,-1768,-1787,-1806,
+-1820,-1830,-1842,-1859,-1875,-1886,-1897,-1911,-1927,-1940,-1952,-1965,-1976,-1983,-1984,-1985,-1989,-1994,-1997,-1997,-1997,
+-1997,-1994,-1988,-1980,-1977,-1976,-1974,-1968,-1957,-1946,-1932,-1918,-1905,-1894,-1886,-1875,-1863,-1851,-1839,-1826,-1814,
+-1804,-1796,-1785,-1771,-1760,-1753,-1746,-1738,-1730,-1723,-1711,-1696,-1682,-1673,-1665,-1658,-1652,-1644,-1633,-1620,-1612,
+-1610,-1608,-1600,-1591,-1583,-1576,-1568,-1561,-1557,-1554,-1546,-1536,-1530,-1526,-1519,-1509,-1501,-1495,-1488,-1477,-1469,
+-1462,-1454,-1444,-1436,-1430,-1425,-1417,-1410,-1404,-1398,-1392,-1385,-1377,-1366,-1354,-1346,-1341,-1334,-1325,-1314,-1304,
+-1293,-1282,-1273,-1262,-1249,-1233,-1219,-1205,-1186,-1166,-1148,-1132,-1114,-1091,-1068,-1047,-1023,-989,-950,-914,-885,
+-861,-834,-804,-773,-745,-719,-692,-662,-629,-596,-562,-530,-495,-455,-411,-367,-324,-279,-225,-170,-121,
+-75,-19,40,92,135,185,246,302,346,402,475,523,499,427,388,436,555,695,814,888,945,
+1071,1343,1725,2083,2309,2401,2380,2209,1865,1453,1163,1085,1139,1205,1258,1342,1466,1586,1675,1748,1828,
+1910,1972,2004,2012,2007,1996,1978,1948,1910,1878,1857,1840,1811,1772,1731,1695,1663,1636,1620,1610,1592,
+1552,1486,1397,1294,1190,1097,1017,949,892,848,814,778,730,665,583,487,381,273,165,61,-31,
+-106,-165,-221,-283,-358,-442,-527,-603,-669,-733,-799,-865,-923,-976,-1032,-1093,-1155,-1218,-1291,-1372,-1445,
+-1499,-1536,-1563,-1570,-1546,-1501,-1470,-1476,-1516,-1578,-1653,-1725,-1773,-1791,-1800,-1824,-1860,-1887,-1901,-1913,-1927,
+-1932,-1929,-1939,-1984,-2056,-2129,-2177,-2192,-2186,-2181,-2191,-2214,-2241,-2271,-2312,-2360,-2402,-2434,-2470,-2520,-2574,
+-2615,-2638,-2641,-2627,-2608,-2596,-2590,-2573,-2553,-2565,-2631,-2713,-2750,-2725,-2671,-2616,-2548,-2459,-2370,-2316,-2300,
+-2298,-2287,-2258,-2204,-2128,-2043,-1959,-1864,-1745,-1611,-1499,-1431,-1390,-1341,-1274,-1221,-1217,-1258,-1298,-1299,-1264,
+-1232,-1225,-1235,-1233,-1210,-1174,-1135,-1094,-1052,-1010,-972,-938,-908,-882,-855,-827,-799,-770,-732,-686,-643,
+-613,-593,-571,-543,-513,-490,-472,-457,-442,-424,-398,-368,-337,-305,-275,-249,-227,-206,-180,-149,-120,
+-96,-72,-43,-8,28,60,87,113,141,166,182,194,211,234,258,280,304,335,369,400,430,
+460,491,521,558,604,650,689,728,777,831,875,907,936,969,1003,1036,1077,1127,1180,1230,1279,
+1329,1379,1427,1475,1520,1556,1580,1602,1632,1668,1704,1739,1772,1800,1829,1868,1913,1949,1964,1971,1980,
+1985,1974,1954,1942,1941,1939,1932,1927,1924,1918,1909,1905,1906,1905,1896,1888,1885,1880,1870,1861,1857,
+1852,1839,1824,1815,1808,1796,1784,1775,1769,1762,1757,1758,1762,1765,1768,1775,1782,1787,1792,1803,1814,
+1819,1821,1826,1831,1827,1819,1821,1822,1835,1840,1823,1791,1764,1746,1723,1686,1637,1589,1548,1512,1475,
+1439,1408,1383,1358,1327,1288,1244,1202,1165,1132,1097,1058,1020,991,966,926,856,774,715,699,718,
+756,800,827,801,704,570,466,428,429,422,394,371,376,399,424,447,473,495,497,475,435,
+383,323,266,214,149,46,-92,-243,-388,-524,-648,-750,-830,-907,-992,-1073,-1139,-1194,-1252,-1313,-1371,
+-1425,-1477,-1516,-1528,-1512,-1492,-1496,-1547,-1641,-1748,-1830,-1879,-1912,-1942,-1955,-1940,-1912,-1894,-1893,-1901,-1917,
+-1937,-1939,-1914,-1873,-1838,-1805,-1763,-1717,-1679,-1641,-1598,-1556,-1505,-1395,-1199,-997,-908,-940,-976,-932,-871,
+-898,-1014,-1133,-1208,-1276,-1373,-1482,-1574,-1643,-1701,-1750,-1791,-1827,-1854,-1862,-1857,-1851,-1841,-1820,-1794,-1775,
+-1764,-1759,-1779,-1833,-1879,-1845,-1725,-1607,-1591,-1684,-1821,-1950,-2075,-2215,-2364,-2498,-2612,-2728,-2861,-2986,-3059,
+-3068,-3071,-3146,-3309,-3503,-3663,-3776,-3863,-3932,-3973,-3988,-3995,-4011,-4036,-4074,-4125,-4189,-4255,-4322,-4387,-4440,
+-4473,-4492,-4509,-4524,-4526,-4518,-4520,-4546,-4580,-4600,-4604,-4601,-4596,-4584,-4566,-4550,-4542,-4537,-4527,-4512,-4496,
+-4486,-4485,-4495,-4518,-4548,-4577,-4602,-4622,-4632,-4628,-4612,-4601,-4611,-4638,-4667,-4694,-4726,-4774,-4834,-4893,-4943,
+-4987,-5029,-5072,-5119,-5170,-5219,-5264,-5310,-5361,-5419,-5478,-5535,-5591,-5648,-5711,-5787,-5878,-5972,-6056,-6127,-6192,
+-6258,-6325,-6387,-6445,-6506,-6572,-6641,-6707,-6766,-6817,-6868,-6926,-6991,-7053,-7103,-7144,-7187,-7238,-7295,-7352,-7405,
+-7450,-7488,-7531,-7586,-7651,-7713,-7770,-7832,-7911,-8003,-8101,-8199,-8294,-8379,-8452,-8518,-8588,-8660,-8727,-8784,-8836,
+-8881,-8916,-8947,-8981,-9008,-9015,-9019,-9071,-9195,-9346,-9449,-9483,-9488,-9511,-9551,-9587,-9611,-9632,-9656,-9679,-9700,
+-9720,-9733,-9734,-9726,-9721,-9726,-9739,-9758,-9779,-9793,-9790,-9770,-9739,-9701,-9651,-9585,-9513,-9446,-9376,-9277,-9140,
+-8990,-8874,-8824,-8832,-8862,-8887,-8892,-8868,-8817,-8748,-8668,-8573,-8454,-8317,-8184,-8063,-7947,-7832,-7725,-7628,-7527,
+-7411,-7289,-7168,-7039,-6895,-6747,-6617,-6504,-6398,-6299,-6213,-6130,-6027,-5903,-5780,-5669,-5551,-5404,-5235,-5068,-4916,
+-4780,-4657,-4540,-4411,-4260,-4097,-3946,-3816,-3697,-3578,-3449,-3299,-3130,-2963,-2834,-2748,-2667,-2546,-2382,-2228,-2144,
+-2152,-2217,-2274,-2261,-2146,-1943,-1707,-1503,-1367,-1278,-1169,-976,-678,-305,82,416,644,760,803,836,901,
+999,1108,1208,1289,1356,1418,1480,1548,1627,1723,1828,1927,2010,2088,2177,2276,2367,2440,2506,2580,2662,
+2740,2811,2886,2972,3061,3139,3204,3264,3325,3396,3478,3571,3665,3754,3837,3917,3992,4060,4126,4195,4261,
+4313,4349,4383,4434,4511,4623,4764,4905,5010,5070,5117,5181,5255,5323,5375,5402,5370,5276,5208,5304,5604,
+5974,6209,6218,6071,5920,5876,5961,6122,6265,6314,6256,6136,6012,5916,5846,5786,5728,5693,5712,5787,5877,
+5937,5961,5976,5992,5999,5997,6004,6023,6021,5971,5878,5782,5725,5731,5793,5875,5934,5961,5971,5975,5972,
+5973,5990,6005,5974,5902,5858,5904,6027,6177,6345,6540,6729,6841,6854,6820,6805,6826,6867,6911,6935,6918,
+6866,6817,6803,6832,6912,7060,7270,7490,7670,7797,7868,7869,7807,7737,7709,7697,7642,7556,7529,7607,7723,
+7783,7774,7754,7757,7763,7748,7725,7710,7704,7702,7717,7750,7783,7797,7802,7818,7847,7872,7881,7884,7891,
+7903,7919,7940,7964,7982,7987,7986,7987,7984,7971,7944,7908,7870,7838,7816,7797,7770,7736,7709,7692,7668,
+7620,7550,7470,7376,7255,7122,7013,6941,6865,6730,6528,6324,6197,6189,6265,6348,6374,6341,6299,6288,6292,
+6274,6224,6170,6134,6104,6057,5988,5918,5857,5803,5745,5681,5615,5556,5502,5445,5377,5304,5239,5192,5156,
+5117,5071,5020,4965,4906,4852,4810,4770,4712,4629,4541,4476,4440,4415,4388,4354,4313,4267,4227,4201,4176,
+4136,4084,4041,4018,4002,3977,3948,3925,3904,3879,3849,3818,3782,3732,3670,3603,3534,3466,3407,3364,3335,
+3307,3276,3245,3218,3196,3179,3160,3121,3048,2955,2867,2802,2757,2726,2702,2671,2632,2609,2624,2654,2645,
+2586,2522,2500,2511,2514,2499,2481,2462,2431,2386,2348,2325,2302,2269,2228,2184,2135,2083,2041,2021,2016,
+2011,2003,1997,1989,1974,1951,1922,1895,1883,1887,1891,1878,1846,1817,1804,1800,1794,1794,1802,1799,1773,
+1745,1753,1801,1846,1848,1803,1735,1666,1611,1588,1605,1640,1658,1649,1636,1637,1645,1643,1629,1618,1611,
+1602,1584,1567,1561,1567,1578,1582,1574,1560,1549,1547,1547,1539,1524,1512,1512,1517,1517,1512,1506,1500,
+1493,1485,1476,1466,1456,1448,1444,1441,1437,1434,1435,1441,1447,1453,1463,1472,1475,1471,1466,1464,1458,
+1444,1432,1432,1444,1450,1438,1414,1397,1396,1401,1395,1377,1360,1356,1366,1378,1385,1386,1381,1367,1344,
+1316,1292,1273,1257,1240,1220,1201,1183,1164,1142,1116,1092,1070,1047,1018,985,955,931,910,885,858,
+831,804,777,752,731,709,683,650,614,577,543,510,481,456,433,410,385,357,329,303,278,
+251,220,186,151,118,86,54,23,-6,-35,-65,-98,-134,-171,-209,-245,-277,-305,-333,-364,-400,
+-438,-473,-505,-535,-565,-599,-639,-680,-712,-730,-740,-753,-775,-802,-828,-855,-885,-915,-940,-964,-992,
+-1026,-1058,-1083,-1104,-1124,-1145,-1166,-1187,-1211,-1239,-1273,-1309,-1342,-1369,-1394,-1421,-1451,-1481,-1508,-1531,-1552,
+-1573,-1594,-1619,-1644,-1664,-1676,-1683,-1693,-1706,-1721,-1736,-1753,-1769,-1781,-1790,-1801,-1815,-1830,-1843,-1855,-1869,
+-1884,-1896,-1908,-1922,-1936,-1944,-1945,-1944,-1947,-1953,-1957,-1957,-1957,-1956,-1955,-1951,-1945,-1942,-1940,-1937,-1930,
+-1921,-1911,-1900,-1887,-1874,-1863,-1853,-1841,-1828,-1816,-1805,-1794,-1783,-1775,-1766,-1754,-1741,-1730,-1720,-1711,-1702,
+-1698,-1693,-1682,-1667,-1654,-1647,-1641,-1634,-1628,-1622,-1613,-1599,-1589,-1586,-1584,-1576,-1566,-1559,-1555,-1549,-1542,
+-1536,-1532,-1526,-1517,-1512,-1509,-1504,-1497,-1491,-1486,-1478,-1468,-1459,-1455,-1450,-1442,-1434,-1428,-1424,-1419,-1414,
+-1407,-1400,-1395,-1390,-1385,-1376,-1365,-1357,-1350,-1344,-1337,-1328,-1320,-1310,-1301,-1291,-1279,-1265,-1251,-1238,-1223,
+-1203,-1182,-1165,-1152,-1136,-1115,-1092,-1068,-1044,-1017,-986,-953,-921,-892,-865,-837,-808,-782,-758,-731,-697,
+-663,-631,-598,-559,-517,-474,-431,-387,-344,-300,-250,-196,-145,-98,-46,10,61,103,153,214,271,
+320,377,440,460,405,315,274,314,398,496,604,719,840,1018,1322,1723,2066,2223,2206,2103,1923,
+1623,1255,979,908,992,1111,1206,1301,1417,1534,1633,1721,1807,1888,1953,2001,2034,2049,2042,2016,1979,
+1944,1925,1921,1918,1902,1870,1826,1778,1733,1700,1681,1664,1635,1589,1522,1431,1319,1208,1114,1037,967,
+906,863,835,801,748,679,600,512,414,308,200,93,-8,-97,-172,-239,-302,-368,-442,-522,-600,
+-668,-722,-771,-820,-873,-932,-1000,-1071,-1133,-1188,-1252,-1328,-1404,-1465,-1507,-1530,-1521,-1473,-1412,-1383,-1411,
+-1488,-1589,-1697,-1786,-1827,-1816,-1786,-1774,-1787,-1803,-1815,-1832,-1854,-1871,-1888,-1931,-2011,-2110,-2189,-2227,-2227,
+-2206,-2188,-2191,-2217,-2252,-2289,-2331,-2380,-2422,-2448,-2467,-2495,-2534,-2572,-2597,-2606,-2603,-2604,-2619,-2643,-2651,
+-2639,-2633,-2662,-2709,-2730,-2705,-2655,-2599,-2533,-2446,-2352,-2276,-2231,-2215,-2215,-2213,-2187,-2124,-2036,-1938,-1829,
+-1706,-1581,-1481,-1416,-1369,-1308,-1221,-1130,-1075,-1078,-1116,-1144,-1135,-1102,-1077,-1074,-1081,-1079,-1063,-1041,-1022,
+-1004,-980,-945,-907,-881,-872,-866,-844,-806,-765,-727,-693,-659,-628,-603,-583,-563,-540,-516,-494,-475,
+-458,-436,-406,-373,-342,-316,-294,-278,-266,-252,-231,-200,-167,-135,-108,-80,-49,-15,17,45,71,
+97,121,140,156,176,203,233,261,290,322,354,383,411,443,475,505,540,582,626,665,702,
+748,800,846,884,921,961,1000,1038,1081,1131,1183,1228,1268,1305,1341,1379,1423,1470,1512,1544,1577,
+1615,1655,1694,1729,1760,1782,1801,1832,1876,1917,1941,1955,1970,1978,1965,1940,1923,1922,1922,1918,1915,
+1914,1909,1900,1896,1898,1896,1887,1881,1880,1877,1867,1856,1851,1846,1834,1821,1813,1806,1794,1781,1773,
+1770,1765,1760,1759,1761,1764,1767,1774,1782,1788,1795,1805,1815,1821,1827,1835,1839,1832,1821,1825,1820,
+1827,1826,1806,1774,1745,1718,1682,1630,1574,1528,1495,1463,1428,1390,1355,1321,1286,1249,1215,1182,1149,
+1114,1079,1045,1011,977,948,919,877,812,736,670,630,618,632,674,728,757,727,644,555,497,
+467,432,379,328,303,303,320,355,407,457,477,458,413,356,298,247,203,141,34,-113,-267,
+-401,-525,-645,-752,-836,-908,-984,-1058,-1114,-1156,-1201,-1256,-1312,-1361,-1402,-1433,-1450,-1450,-1443,-1445,-1480,
+-1561,-1669,-1763,-1824,-1862,-1894,-1910,-1898,-1872,-1857,-1861,-1873,-1886,-1895,-1889,-1863,-1832,-1809,-1784,-1742,-1695,
+-1662,-1638,-1609,-1574,-1523,-1409,-1215,-1031,-975,-1037,-1071,-990,-888,-906,-1047,-1192,-1273,-1329,-1409,-1506,-1587,
+-1655,-1720,-1780,-1829,-1871,-1907,-1922,-1916,-1904,-1896,-1885,-1867,-1846,-1822,-1799,-1803,-1848,-1895,-1870,-1758,-1648,
+-1641,-1743,-1871,-1963,-2038,-2144,-2295,-2456,-2600,-2733,-2872,-3005,-3097,-3132,-3147,-3204,-3328,-3489,-3640,-3762,-3853,
+-3916,-3950,-3970,-3990,-4015,-4046,-4086,-4140,-4202,-4265,-4330,-4392,-4440,-4464,-4475,-4487,-4496,-4490,-4478,-4484,-4515,
+-4545,-4554,-4548,-4544,-4544,-4538,-4527,-4519,-4517,-4510,-4493,-4474,-4459,-4450,-4447,-4455,-4476,-4504,-4531,-4552,-4568,
+-4577,-4572,-4558,-4552,-4565,-4585,-4596,-4603,-4628,-4679,-4743,-4801,-4855,-4914,-4973,-5024,-5065,-5108,-5158,-5210,-5258,
+-5306,-5362,-5425,-5486,-5540,-5589,-5645,-5719,-5810,-5902,-5983,-6056,-6128,-6200,-6264,-6320,-6379,-6448,-6519,-6586,-6645,
+-6703,-6761,-6822,-6887,-6954,-7013,-7059,-7098,-7140,-7185,-7234,-7285,-7338,-7388,-7434,-7481,-7536,-7594,-7647,-7697,-7759,
+-7842,-7937,-8035,-8131,-8223,-8304,-8376,-8450,-8534,-8618,-8685,-8737,-8780,-8817,-8847,-8879,-8919,-8952,-8959,-8966,-9030,
+-9167,-9316,-9401,-9418,-9422,-9453,-9497,-9529,-9548,-9568,-9591,-9611,-9632,-9654,-9668,-9664,-9652,-9648,-9660,-9679,-9699,
+-9719,-9730,-9724,-9701,-9673,-9646,-9612,-9559,-9493,-9426,-9353,-9255,-9118,-8966,-8852,-8811,-8831,-8871,-8892,-8881,-8839,
+-8774,-8697,-8616,-8525,-8411,-8278,-8149,-8034,-7926,-7815,-7710,-7617,-7523,-7416,-7294,-7166,-7027,-6873,-6720,-6589,-6482,
+-6386,-6298,-6219,-6141,-6042,-5923,-5805,-5697,-5580,-5431,-5259,-5088,-4932,-4792,-4666,-4547,-4417,-4268,-4112,-3973,-3862,
+-3763,-3656,-3526,-3365,-3183,-3009,-2878,-2788,-2696,-2559,-2383,-2222,-2128,-2115,-2153,-2199,-2212,-2157,-2012,-1794,-1554,
+-1355,-1221,-1118,-983,-771,-477,-126,229,527,724,819,862,911,993,1094,1186,1258,1318,1380,1446,1517,
+1600,1700,1811,1914,2000,2079,2163,2250,2328,2396,2466,2543,2620,2693,2765,2844,2929,3013,3089,3158,3224,
+3293,3370,3453,3538,3624,3714,3807,3890,3957,4017,4088,4166,4227,4257,4275,4316,4396,4506,4630,4757,4873,
+4963,5029,5092,5161,5225,5275,5314,5334,5305,5223,5171,5261,5521,5838,6052,6084,5977,5846,5800,5894,6089,
+6275,6348,6295,6183,6092,6043,6009,5949,5854,5760,5719,5754,5829,5892,5923,5932,5935,5938,5960,6011,6062,
+6062,5996,5911,5865,5881,5942,6018,6074,6085,6053,6008,5974,5961,5979,6028,6064,6022,5894,5756,5695,5723,
+5810,5966,6212,6501,6722,6809,6808,6808,6847,6903,6944,6952,6930,6900,6894,6929,6997,7101,7260,7478,7718,
+7934,8094,8175,8151,8038,7909,7830,7781,7702,7597,7542,7579,7650,7677,7661,7655,7682,7714,7733,7752,7777,
+7790,7777,7761,7766,7780,7778,7766,7771,7800,7829,7840,7841,7851,7873,7895,7914,7932,7950,7968,7985,8002,
+8015,8022,8019,8003,7973,7933,7893,7858,7822,7784,7752,7731,7709,7674,7629,7577,7501,7375,7208,7041,6909,
+6802,6686,6547,6398,6277,6226,6264,6358,6429,6426,6372,6331,6326,6322,6284,6226,6180,6147,6103,6039,5967,
+5904,5849,5794,5736,5677,5617,5558,5498,5433,5365,5306,5263,5230,5190,5141,5092,5047,5000,4948,4894,4835,
+4758,4663,4575,4521,4497,4479,4446,4401,4355,4315,4284,4257,4223,4176,4126,4093,4075,4051,4009,3965,3936,
+3919,3897,3866,3835,3804,3760,3696,3619,3545,3483,3435,3396,3360,3325,3295,3265,3231,3194,3170,3160,3140,
+3083,2996,2910,2846,2801,2768,2743,2714,2671,2625,2600,2599,2597,2575,2551,2549,2557,2553,2535,2517,2500,
+2468,2421,2377,2344,2312,2274,2236,2201,2158,2105,2058,2033,2027,2022,2013,2003,1993,1981,1962,1934,1897,
+1862,1841,1841,1851,1859,1857,1848,1834,1820,1818,1823,1814,1783,1747,1738,1759,1789,1803,1798,1773,1725,
+1663,1616,1607,1625,1642,1641,1636,1640,1649,1647,1632,1615,1607,1605,1601,1596,1596,1607,1621,1626,1617,
+1600,1589,1588,1585,1571,1548,1527,1517,1517,1519,1521,1520,1516,1509,1499,1485,1466,1446,1435,1433,1434,
+1431,1427,1426,1427,1426,1428,1436,1446,1449,1446,1448,1459,1465,1453,1434,1427,1433,1438,1426,1403,1384,
+1376,1372,1362,1346,1331,1325,1329,1339,1350,1357,1355,1344,1325,1305,1286,1269,1252,1235,1218,1201,1183,
+1163,1139,1115,1091,1067,1041,1011,980,950,923,896,870,843,816,788,761,737,718,699,675,644,
+607,569,532,499,470,443,417,391,365,339,314,290,268,245,216,183,149,118,89,61,30,
+-1,-33,-66,-99,-133,-169,-205,-242,-275,-305,-333,-364,-400,-437,-471,-501,-529,-557,-589,-627,-668,
+-706,-733,-751,-766,-786,-811,-837,-864,-891,-917,-939,-959,-983,-1014,-1046,-1072,-1092,-1111,-1131,-1150,-1168,
+-1187,-1212,-1245,-1282,-1316,-1344,-1368,-1392,-1420,-1450,-1478,-1504,-1525,-1544,-1562,-1584,-1609,-1631,-1646,-1654,-1663,
+-1675,-1690,-1705,-1721,-1735,-1747,-1756,-1767,-1780,-1793,-1805,-1817,-1830,-1843,-1855,-1867,-1880,-1893,-1902,-1905,-1905,
+-1907,-1913,-1919,-1921,-1919,-1916,-1914,-1912,-1908,-1904,-1901,-1896,-1888,-1880,-1873,-1866,-1855,-1843,-1831,-1819,-1805,
+-1793,-1782,-1774,-1764,-1755,-1746,-1736,-1725,-1714,-1703,-1692,-1679,-1669,-1666,-1664,-1656,-1642,-1631,-1625,-1618,-1608,
+-1600,-1597,-1591,-1578,-1566,-1560,-1557,-1550,-1542,-1537,-1535,-1530,-1521,-1515,-1511,-1505,-1499,-1495,-1492,-1488,-1483,
+-1480,-1479,-1473,-1462,-1453,-1448,-1445,-1439,-1431,-1425,-1422,-1420,-1416,-1410,-1403,-1397,-1393,-1390,-1385,-1378,-1371,
+-1364,-1357,-1350,-1342,-1334,-1325,-1316,-1306,-1294,-1281,-1268,-1255,-1239,-1219,-1199,-1182,-1167,-1152,-1135,-1115,-1091,
+-1065,-1041,-1017,-988,-955,-925,-899,-870,-840,-813,-790,-763,-728,-693,-662,-628,-585,-538,-494,-452,-405,
+-360,-317,-273,-222,-171,-124,-76,-23,27,76,132,197,255,298,341,382,378,304,210,176,216,
+285,364,483,652,842,1055,1338,1679,1957,2058,2010,1908,1761,1503,1153,868,784,882,1039,1166,1265,
+1361,1464,1571,1679,1779,1862,1930,1993,2048,2085,2091,2068,2029,1996,1983,1987,1990,1979,1952,1912,1864,
+1817,1781,1751,1716,1672,1623,1565,1482,1371,1257,1164,1085,1006,931,879,849,817,763,695,624,546,
+454,349,238,125,15,-86,-176,-253,-321,-385,-455,-533,-609,-667,-702,-730,-767,-820,-886,-959,-1031,
+-1095,-1149,-1208,-1276,-1346,-1403,-1440,-1450,-1424,-1367,-1314,-1312,-1377,-1487,-1612,-1737,-1841,-1892,-1879,-1833,-1799,
+-1789,-1791,-1794,-1804,-1822,-1844,-1879,-1947,-2049,-2156,-2228,-2256,-2249,-2226,-2207,-2211,-2241,-2281,-2318,-2355,-2402,
+-2447,-2473,-2481,-2489,-2510,-2536,-2556,-2566,-2573,-2590,-2626,-2675,-2711,-2715,-2704,-2704,-2723,-2734,-2718,-2676,-2617,
+-2541,-2445,-2340,-2241,-2166,-2124,-2114,-2117,-2101,-2052,-1974,-1879,-1772,-1655,-1546,-1464,-1408,-1360,-1298,-1213,-1113,
+-1024,-977,-980,-1004,-1011,-991,-969,-970,-988,-1001,-993,-974,-960,-948,-923,-878,-830,-812,-830,-852,-837,
+-782,-719,-679,-662,-647,-618,-586,-565,-560,-558,-545,-522,-495,-470,-443,-409,-372,-340,-317,-302,-294,
+-288,-277,-257,-228,-194,-161,-130,-104,-79,-53,-24,2,26,49,73,97,120,146,180,216,250,
+284,316,346,375,407,445,482,514,545,584,626,662,696,734,777,818,858,902,951,998,1042,
+1088,1138,1186,1230,1269,1306,1339,1374,1415,1461,1503,1538,1574,1613,1650,1684,1715,1744,1763,1779,1808,
+1854,1898,1924,1940,1955,1963,1951,1926,1908,1904,1904,1902,1903,1906,1905,1900,1897,1897,1890,1877,1868,
+1865,1862,1853,1844,1839,1833,1823,1812,1807,1802,1793,1783,1778,1777,1774,1770,1767,1765,1763,1764,1770,
+1781,1791,1803,1816,1829,1836,1842,1850,1852,1841,1825,1821,1808,1801,1789,1764,1730,1697,1663,1620,1567,
+1517,1481,1454,1424,1384,1340,1297,1259,1220,1183,1152,1124,1094,1060,1027,998,968,937,907,878,844,
+794,728,655,590,544,529,552,609,671,702,681,621,554,496,440,375,311,268,251,262,302,
+366,428,453,431,380,322,267,222,182,122,17,-126,-270,-390,-499,-613,-720,-804,-872,-940,-1005,
+-1052,-1083,-1120,-1174,-1233,-1285,-1325,-1356,-1380,-1399,-1415,-1428,-1454,-1512,-1600,-1687,-1748,-1788,-1820,-1841,-1840,
+-1828,-1825,-1834,-1844,-1850,-1852,-1843,-1820,-1799,-1788,-1768,-1725,-1677,-1649,-1634,-1608,-1574,-1528,-1428,-1254,-1088,
+-1048,-1117,-1141,-1036,-912,-931,-1092,-1256,-1341,-1387,-1456,-1540,-1610,-1671,-1739,-1809,-1868,-1918,-1961,-1987,-1989,
+-1985,-1985,-1981,-1962,-1933,-1905,-1885,-1884,-1905,-1920,-1881,-1790,-1721,-1745,-1845,-1940,-1988,-2023,-2103,-2244,-2414,
+-2584,-2745,-2902,-3042,-3142,-3191,-3211,-3249,-3335,-3467,-3614,-3748,-3847,-3906,-3937,-3962,-3993,-4025,-4061,-4107,-4165,
+-4224,-4278,-4332,-4384,-4421,-4436,-4441,-4452,-4461,-4455,-4447,-4460,-4490,-4509,-4502,-4485,-4479,-4482,-4483,-4481,-4484,
+-4488,-4480,-4458,-4437,-4424,-4420,-4421,-4432,-4453,-4476,-4490,-4499,-4508,-4517,-4516,-4507,-4504,-4513,-4517,-4498,-4468,
+-4465,-4504,-4568,-4635,-4708,-4799,-4896,-4969,-5011,-5043,-5089,-5148,-5206,-5258,-5314,-5378,-5441,-5496,-5543,-5598,-5669,
+-5753,-5835,-5910,-5986,-6067,-6143,-6204,-6256,-6319,-6397,-6472,-6534,-6587,-6645,-6712,-6780,-6844,-6903,-6952,-6995,-7036,
+-7081,-7125,-7168,-7216,-7273,-7334,-7389,-7439,-7489,-7538,-7583,-7630,-7694,-7780,-7874,-7968,-8060,-8150,-8233,-8309,-8392,
+-8482,-8563,-8623,-8670,-8715,-8755,-8783,-8811,-8849,-8880,-8887,-8901,-8979,-9127,-9272,-9341,-9346,-9351,-9386,-9431,-9458,
+-9476,-9499,-9523,-9540,-9558,-9582,-9599,-9598,-9589,-9591,-9611,-9635,-9655,-9665,-9662,-9642,-9613,-9590,-9578,-9561,-9523,
+-9464,-9396,-9322,-9225,-9096,-8955,-8852,-8818,-8839,-8869,-8870,-8836,-8777,-8705,-8629,-8554,-8470,-8364,-8236,-8109,-7996,
+-7890,-7782,-7678,-7589,-7504,-7406,-7288,-7156,-7007,-6843,-6683,-6551,-6451,-6366,-6285,-6211,-6139,-6053,-5949,-5839,-5729,
+-5607,-5459,-5294,-5129,-4974,-4828,-4694,-4570,-4443,-4301,-4154,-4024,-3921,-3830,-3726,-3594,-3428,-3242,-3069,-2936,-2835,
+-2726,-2573,-2392,-2233,-2138,-2104,-2101,-2104,-2106,-2095,-2034,-1889,-1666,-1419,-1212,-1068,-955,-816,-602,-299,56,
+394,644,784,849,897,967,1056,1142,1217,1286,1354,1417,1477,1550,1651,1770,1883,1979,2067,2154,2233,
+2298,2359,2432,2514,2594,2667,2742,2820,2897,2966,3034,3103,3174,3248,3329,3414,3495,3574,3664,3762,3849,
+3913,3970,4046,4132,4196,4221,4234,4276,4361,4474,4594,4713,4822,4912,4988,5060,5126,5175,5203,5216,5206,
+5157,5085,5059,5154,5374,5635,5837,5924,5895,5803,5745,5817,6021,6244,6353,6313,6202,6118,6094,6087,6039,
+5928,5792,5703,5703,5770,5847,5892,5901,5893,5895,5935,6010,6070,6064,6000,5946,5947,5987,6033,6076,6110,
+6110,6059,5976,5906,5881,5913,5989,6054,6035,5910,5743,5613,5548,5549,5657,5913,6269,6585,6755,6805,6824,
+6866,6916,6948,6958,6966,6999,7072,7172,7273,7373,7503,7687,7908,8117,8271,8331,8274,8127,7972,7874,7818,
+7742,7638,7565,7563,7594,7607,7604,7621,7662,7698,7719,7744,7780,7796,7777,7749,7747,7762,7759,7734,7716,
+7726,7749,7762,7767,7778,7804,7835,7862,7887,7915,7946,7980,8012,8036,8050,8056,8054,8037,8003,7964,7930,
+7900,7869,7834,7799,7756,7703,7652,7611,7557,7455,7293,7102,6918,6755,6618,6508,6416,6326,6251,6236,6305,
+6404,6450,6424,6381,6366,6365,6341,6291,6240,6199,6154,6098,6036,5975,5913,5852,5797,5745,5688,5624,5558,
+5491,5426,5369,5330,5301,5262,5208,5155,5113,5075,5025,4957,4876,4784,4692,4623,4591,4581,4560,4514,4455,
+4400,4356,4322,4291,4256,4215,4175,4147,4127,4096,4046,3995,3962,3941,3916,3883,3853,3825,3784,3717,3634,
+3554,3494,3455,3424,3389,3352,3320,3290,3250,3203,3169,3155,3139,3092,3018,2947,2894,2852,2819,2802,2793,
+2763,2701,2634,2595,2587,2589,2591,2595,2592,2575,2550,2532,2517,2491,2450,2407,2368,2326,2280,2241,2208,
+2171,2122,2078,2053,2044,2035,2019,2002,1987,1974,1961,1939,1901,1849,1806,1796,1821,1858,1877,1871,1855,
+1847,1851,1851,1829,1790,1755,1740,1739,1747,1763,1785,1795,1767,1706,1646,1618,1621,1633,1637,1636,1640,
+1647,1647,1632,1612,1601,1604,1611,1617,1624,1639,1657,1664,1657,1646,1640,1639,1631,1610,1583,1558,1540,
+1532,1533,1537,1535,1524,1512,1502,1489,1468,1441,1424,1422,1427,1427,1425,1423,1419,1410,1402,1406,1416,
+1421,1423,1433,1453,1465,1454,1429,1412,1411,1414,1410,1399,1386,1370,1350,1333,1320,1311,1303,1299,1304,
+1318,1330,1331,1319,1302,1285,1270,1255,1240,1225,1211,1198,1179,1157,1135,1115,1093,1067,1037,1007,978,
+948,917,888,861,834,805,775,749,729,712,693,668,637,603,567,531,497,466,437,407,377,
+349,324,302,281,261,238,209,176,142,113,87,60,30,-3,-38,-73,-107,-140,-174,-209,-245,
+-279,-310,-338,-369,-403,-439,-471,-498,-523,-548,-577,-609,-645,-684,-719,-746,-767,-788,-814,-842,-869,
+-894,-915,-933,-951,-973,-1000,-1031,-1058,-1079,-1098,-1118,-1138,-1155,-1172,-1194,-1223,-1258,-1290,-1316,-1337,-1358,
+-1383,-1413,-1443,-1471,-1494,-1514,-1530,-1548,-1569,-1590,-1607,-1619,-1629,-1641,-1656,-1672,-1688,-1702,-1715,-1727,-1741,
+-1754,-1766,-1775,-1785,-1796,-1809,-1822,-1834,-1844,-1853,-1860,-1864,-1866,-1868,-1874,-1881,-1884,-1883,-1879,-1876,-1873,
+-1870,-1866,-1862,-1855,-1847,-1839,-1834,-1829,-1821,-1810,-1797,-1785,-1771,-1759,-1750,-1743,-1734,-1725,-1716,-1708,-1698,
+-1687,-1676,-1664,-1650,-1639,-1636,-1635,-1629,-1617,-1608,-1603,-1594,-1580,-1569,-1565,-1562,-1553,-1540,-1532,-1528,-1523,
+-1517,-1514,-1513,-1509,-1501,-1495,-1491,-1487,-1483,-1481,-1479,-1476,-1472,-1470,-1471,-1468,-1461,-1453,-1447,-1442,-1437,
+-1429,-1423,-1420,-1418,-1416,-1413,-1407,-1402,-1398,-1395,-1391,-1388,-1383,-1377,-1370,-1363,-1356,-1348,-1338,-1328,-1318,
+-1306,-1293,-1281,-1268,-1253,-1235,-1218,-1202,-1185,-1167,-1152,-1136,-1115,-1090,-1066,-1043,-1015,-982,-953,-928,-899,
+-864,-835,-814,-789,-755,-719,-688,-655,-611,-563,-521,-478,-427,-376,-334,-294,-246,-195,-149,-105,-53,
+2,56,115,181,236,265,286,305,290,216,129,112,183,286,391,533,734,957,1175,1408,1654,
+1838,1890,1842,1770,1664,1448,1135,870,790,880,1025,1139,1217,1292,1383,1493,1614,1726,1817,1894,1970,
+2045,2102,2128,2118,2086,2053,2038,2041,2044,2032,2008,1975,1936,1894,1855,1812,1759,1703,1655,1607,1534,
+1429,1318,1227,1147,1058,969,907,873,839,787,724,659,588,498,392,276,157,37,-74,-173,-261,
+-340,-414,-488,-562,-624,-658,-667,-677,-712,-769,-833,-894,-954,-1015,-1076,-1136,-1193,-1247,-1292,-1322,-1327,
+-1299,-1254,-1233,-1277,-1384,-1519,-1652,-1774,-1878,-1942,-1948,-1915,-1880,-1860,-1850,-1843,-1842,-1850,-1866,-1901,-1971,
+-2070,-2165,-2225,-2246,-2243,-2229,-2218,-2228,-2261,-2301,-2333,-2365,-2412,-2466,-2503,-2512,-2510,-2514,-2524,-2531,-2535,
+-2545,-2571,-2616,-2674,-2723,-2745,-2743,-2737,-2739,-2743,-2732,-2695,-2634,-2550,-2448,-2336,-2227,-2136,-2080,-2061,-2058,
+-2039,-1992,-1922,-1835,-1730,-1618,-1522,-1460,-1419,-1371,-1307,-1227,-1133,-1032,-947,-907,-909,-922,-921,-918,-934,
+-965,-985,-971,-934,-897,-866,-829,-780,-739,-741,-787,-827,-810,-731,-643,-597,-597,-604,-584,-549,-531,
+-543,-567,-573,-551,-515,-479,-445,-409,-372,-339,-317,-306,-302,-301,-292,-274,-248,-219,-187,-156,-129,
+-108,-89,-65,-39,-16,4,27,53,83,114,151,190,228,263,295,326,358,396,440,482,516,
+547,583,623,658,690,723,762,802,843,892,945,996,1042,1086,1132,1177,1221,1266,1310,1350,1388,
+1428,1471,1510,1543,1575,1609,1639,1666,1696,1726,1751,1773,1806,1852,1894,1917,1926,1936,1942,1933,1914,
+1900,1896,1894,1891,1892,1897,1898,1896,1894,1890,1880,1864,1851,1844,1839,1833,1829,1828,1823,1812,1802,
+1798,1796,1792,1786,1785,1785,1784,1781,1777,1771,1764,1762,1769,1781,1795,1811,1828,1841,1847,1851,1855,
+1853,1840,1821,1800,1780,1760,1737,1706,1671,1637,1603,1564,1521,1481,1447,1416,1378,1331,1281,1238,1204,
+1172,1139,1106,1073,1039,1007,980,956,928,897,867,844,824,794,744,672,588,512,466,460,496,
+562,627,656,634,578,513,448,379,311,264,248,260,297,349,397,411,384,335,282,234,191,
+147,87,-7,-128,-245,-341,-435,-541,-647,-731,-797,-863,-926,-970,-1000,-1037,-1095,-1162,-1222,-1268,-1303,
+-1334,-1367,-1403,-1432,-1454,-1486,-1539,-1600,-1650,-1688,-1725,-1759,-1780,-1789,-1796,-1803,-1809,-1816,-1822,-1818,-1800,
+-1783,-1776,-1759,-1718,-1673,-1651,-1637,-1608,-1570,-1534,-1460,-1314,-1160,-1118,-1184,-1217,-1125,-1008,-1022,-1173,-1326,
+-1398,-1433,-1492,-1566,-1625,-1678,-1747,-1823,-1886,-1939,-1986,-2019,-2032,-2039,-2048,-2044,-2012,-1966,-1933,-1925,-1932,
+-1934,-1913,-1859,-1798,-1782,-1838,-1929,-1995,-2025,-2054,-2123,-2243,-2399,-2577,-2763,-2938,-3082,-3179,-3227,-3245,-3267,
+-3329,-3440,-3585,-3727,-3833,-3896,-3933,-3965,-4000,-4034,-4071,-4122,-4182,-4234,-4274,-4314,-4356,-4386,-4396,-4400,-4414,
+-4429,-4432,-4432,-4447,-4471,-4478,-4464,-4448,-4443,-4444,-4442,-4443,-4452,-4459,-4450,-4428,-4410,-4402,-4399,-4402,-4415,
+-4435,-4449,-4449,-4445,-4449,-4460,-4465,-4460,-4453,-4449,-4431,-4381,-4318,-4287,-4311,-4371,-4442,-4529,-4648,-4785,-4895,
+-4954,-4984,-5022,-5081,-5148,-5211,-5272,-5336,-5398,-5454,-5504,-5560,-5628,-5703,-5775,-5846,-5925,-6011,-6087,-6144,-6194,
+-6261,-6344,-6420,-6478,-6529,-6590,-6660,-6727,-6784,-6834,-6879,-6922,-6969,-7018,-7064,-7106,-7155,-7219,-7289,-7350,-7399,
+-7444,-7488,-7529,-7576,-7640,-7722,-7811,-7900,-7992,-8085,-8171,-8252,-8337,-8423,-8492,-8543,-8592,-8646,-8689,-8709,-8726,
+-8757,-8789,-8803,-8830,-8926,-9083,-9222,-9278,-9275,-9280,-9318,-9359,-9382,-9399,-9426,-9450,-9464,-9476,-9497,-9519,-9526,
+-9523,-9531,-9555,-9582,-9596,-9592,-9568,-9532,-9501,-9493,-9501,-9503,-9477,-9421,-9348,-9266,-9167,-9045,-8919,-8827,-8797,
+-8813,-8830,-8815,-8769,-8707,-8641,-8574,-8506,-8426,-8323,-8198,-8068,-7952,-7845,-7742,-7645,-7563,-7486,-7393,-7275,-7138,
+-6982,-6813,-6648,-6516,-6420,-6345,-6274,-6207,-6145,-6074,-5982,-5875,-5757,-5629,-5485,-5334,-5185,-5036,-4884,-4737,-4605,
+-4482,-4353,-4217,-4088,-3977,-3875,-3763,-3624,-3459,-3285,-3124,-2991,-2875,-2745,-2581,-2401,-2249,-2154,-2104,-2061,-2012,
+-1976,-1975,-1987,-1943,-1791,-1547,-1288,-1091,-970,-869,-708,-443,-101,242,516,696,808,892,972,1048,1119,
+1191,1269,1348,1409,1456,1515,1610,1732,1851,1955,2054,2151,2232,2288,2338,2407,2493,2578,2654,2728,2801,
+2866,2922,2981,3047,3116,3186,3264,3351,3434,3515,3604,3705,3797,3866,3928,4007,4100,4173,4212,4235,4275,
+4340,4427,4530,4646,4762,4860,4938,5002,5055,5089,5101,5088,5044,4972,4907,4911,5018,5205,5415,5606,5742,
+5785,5732,5664,5704,5897,6142,6287,6271,6165,6075,6049,6050,6010,5899,5754,5654,5654,5733,5825,5878,5884,
+5867,5863,5898,5960,5998,5978,5935,5932,5974,6010,6011,6011,6040,6063,6024,5930,5837,5797,5816,5872,5925,
+5927,5856,5737,5615,5510,5449,5501,5728,6090,6444,6673,6770,6805,6830,6849,6860,6883,6942,7054,7208,7368,
+7493,7578,7666,7804,7993,8185,8325,8371,8313,8188,8068,7999,7958,7890,7785,7689,7641,7631,7635,7653,7699,
+7755,7785,7784,7777,7780,7777,7751,7718,7704,7708,7700,7668,7632,7620,7630,7646,7660,7682,7715,7755,7794,
+7831,7868,7909,7953,7997,8032,8054,8063,8065,8057,8038,8016,8001,7989,7968,7933,7888,7831,7763,7699,7649,
+7595,7504,7361,7185,6993,6790,6598,6463,6398,6358,6296,6235,6238,6312,6396,6431,6424,6411,6404,6388,6356,
+6316,6270,6218,6163,6110,6053,5986,5918,5861,5814,5759,5693,5622,5554,5489,5431,5390,5359,5316,5255,5192,
+5148,5116,5073,5003,4912,4818,4741,4695,4681,4670,4635,4572,4501,4441,4393,4352,4318,4290,4262,4232,4201,
+4171,4133,4086,4039,4002,3975,3948,3919,3890,3860,3815,3750,3668,3588,3526,3487,3461,3432,3395,3357,3320,
+3278,3231,3194,3171,3143,3093,3031,2979,2939,2898,2863,2857,2872,2864,2801,2710,2642,2620,2624,2632,2633,
+2623,2596,2564,2543,2532,2513,2479,2439,2398,2352,2298,2249,2209,2171,2129,2092,2070,2056,2039,2015,1992,
+1973,1958,1945,1930,1903,1858,1813,1803,1834,1878,1893,1872,1848,1850,1867,1866,1834,1795,1775,1769,1758,
+1745,1753,1781,1797,1770,1707,1647,1621,1624,1637,1645,1647,1650,1656,1658,1647,1625,1608,1605,1614,1623,
+1634,1654,1677,1690,1689,1685,1686,1685,1672,1650,1625,1600,1576,1558,1553,1556,1552,1533,1511,1498,1488,
+1467,1437,1413,1405,1409,1416,1425,1432,1429,1411,1392,1384,1388,1395,1400,1411,1430,1441,1432,1410,1390,
+1382,1382,1387,1391,1386,1364,1333,1309,1300,1297,1287,1274,1273,1287,1303,1307,1296,1278,1260,1246,1235,
+1223,1211,1200,1187,1168,1145,1125,1108,1089,1063,1032,1003,976,948,917,889,862,833,798,765,741,
+725,709,687,660,630,600,566,530,495,463,434,404,372,342,316,294,273,252,227,198,163,
+130,100,73,46,16,-15,-49,-83,-116,-149,-181,-215,-251,-285,-315,-343,-372,-406,-441,-473,-499,
+-520,-543,-566,-592,-620,-654,-692,-728,-755,-779,-806,-839,-869,-891,-908,-924,-942,-964,-991,-1020,-1048,
+-1072,-1095,-1117,-1138,-1156,-1171,-1190,-1214,-1242,-1269,-1290,-1308,-1327,-1351,-1379,-1409,-1436,-1460,-1481,-1499,-1515,
+-1531,-1549,-1567,-1581,-1592,-1604,-1620,-1636,-1652,-1666,-1681,-1697,-1714,-1730,-1743,-1751,-1757,-1766,-1779,-1795,-1807,
+-1814,-1818,-1823,-1827,-1829,-1830,-1834,-1841,-1846,-1846,-1843,-1840,-1837,-1833,-1828,-1823,-1817,-1810,-1802,-1797,-1792,
+-1785,-1776,-1765,-1754,-1740,-1728,-1718,-1710,-1700,-1691,-1683,-1677,-1669,-1657,-1646,-1634,-1622,-1611,-1605,-1602,-1595,
+-1586,-1579,-1574,-1564,-1549,-1537,-1533,-1530,-1522,-1512,-1504,-1499,-1494,-1489,-1488,-1487,-1483,-1478,-1474,-1472,-1469,
+-1466,-1465,-1464,-1463,-1460,-1459,-1460,-1459,-1456,-1451,-1447,-1443,-1437,-1431,-1424,-1420,-1417,-1415,-1413,-1411,-1409,
+-1406,-1401,-1395,-1391,-1388,-1383,-1377,-1372,-1368,-1360,-1349,-1338,-1327,-1316,-1304,-1293,-1281,-1265,-1249,-1236,-1225,
+-1207,-1186,-1167,-1152,-1134,-1112,-1089,-1066,-1038,-1005,-977,-954,-925,-888,-857,-838,-815,-779,-742,-711,-679,
+-636,-589,-548,-504,-450,-395,-355,-318,-270,-217,-172,-128,-72,-12,40,91,149,196,216,222,232,
+218,147,65,70,200,391,574,752,956,1174,1373,1551,1704,1793,1786,1721,1653,1562,1385,1139,944,
+894,959,1048,1111,1161,1227,1317,1425,1543,1657,1756,1846,1937,2024,2096,2138,2145,2123,2092,2074,2074,
+2075,2064,2044,2020,1989,1949,1903,1850,1791,1734,1690,1647,1578,1478,1372,1286,1207,1115,1023,956,917,
+879,827,768,708,637,546,436,315,187,57,-63,-170,-269,-363,-451,-529,-594,-633,-637,-619,-616,
+-651,-711,-763,-795,-825,-876,-943,-1007,-1056,-1093,-1130,-1168,-1192,-1192,-1184,-1208,-1294,-1432,-1579,-1706,-1812,
+-1903,-1973,-2003,-1998,-1975,-1951,-1931,-1919,-1916,-1922,-1934,-1960,-2012,-2086,-2156,-2201,-2219,-2222,-2219,-2217,-2230,
+-2262,-2299,-2329,-2361,-2414,-2481,-2530,-2544,-2536,-2527,-2521,-2512,-2505,-2513,-2545,-2595,-2652,-2703,-2737,-2751,-2751,
+-2746,-2738,-2720,-2682,-2622,-2540,-2443,-2337,-2231,-2142,-2089,-2070,-2062,-2035,-1981,-1909,-1819,-1708,-1593,-1507,-1465,
+-1440,-1393,-1318,-1232,-1142,-1045,-948,-882,-863,-871,-879,-886,-911,-952,-979,-963,-909,-845,-792,-750,-718,
+-709,-740,-798,-832,-796,-696,-592,-542,-551,-574,-569,-540,-525,-546,-585,-602,-580,-535,-488,-449,-413,
+-379,-350,-330,-319,-319,-322,-318,-302,-280,-256,-226,-192,-161,-139,-120,-97,-69,-43,-21,2,30,
+59,89,123,162,201,236,268,302,340,384,430,471,504,532,565,602,637,670,708,752,800,
+850,903,959,1009,1051,1090,1128,1167,1208,1252,1298,1341,1381,1421,1463,1501,1533,1565,1596,1624,1650,
+1680,1713,1743,1770,1805,1848,1886,1904,1911,1917,1923,1920,1909,1900,1897,1893,1887,1884,1885,1885,1881,
+1877,1871,1862,1848,1835,1827,1822,1820,1822,1824,1819,1808,1798,1793,1790,1787,1786,1786,1785,1783,1781,
+1778,1770,1762,1762,1773,1788,1800,1813,1827,1838,1840,1837,1835,1832,1819,1800,1766,1745,1720,1690,1656,
+1622,1590,1559,1528,1494,1455,1411,1365,1317,1266,1219,1184,1160,1137,1108,1070,1028,990,961,940,919,
+892,861,834,817,807,793,762,701,615,525,455,419,422,463,528,583,598,575,529,468,391,
+315,271,271,296,324,347,362,356,327,286,246,207,161,106,39,-41,-129,-204,-267,-341,-442,
+-550,-641,-715,-786,-850,-896,-932,-980,-1048,-1121,-1185,-1237,-1279,-1313,-1351,-1396,-1436,-1458,-1469,-1488,-1518,
+-1550,-1585,-1632,-1687,-1733,-1758,-1766,-1766,-1770,-1786,-1806,-1809,-1790,-1770,-1763,-1752,-1718,-1681,-1663,-1649,-1614,
+-1574,-1548,-1499,-1373,-1220,-1163,-1234,-1308,-1274,-1190,-1188,-1289,-1395,-1441,-1462,-1508,-1569,-1620,-1672,-1743,-1818,
+-1877,-1925,-1974,-2012,-2031,-2043,-2055,-2046,-1994,-1923,-1878,-1882,-1907,-1914,-1880,-1822,-1782,-1797,-1868,-1955,-2023,
+-2072,-2122,-2190,-2285,-2420,-2597,-2793,-2970,-3104,-3192,-3240,-3260,-3278,-3328,-3429,-3567,-3706,-3814,-3885,-3935,-3976,
+-4012,-4041,-4075,-4126,-4183,-4228,-4258,-4290,-4328,-4354,-4360,-4362,-4377,-4398,-4411,-4418,-4428,-4437,-4435,-4427,-4426,
+-4430,-4429,-4422,-4422,-4431,-4432,-4419,-4401,-4391,-4385,-4378,-4376,-4388,-4404,-4410,-4401,-4389,-4391,-4404,-4413,-4408,
+-4389,-4361,-4316,-4251,-4186,-4157,-4180,-4236,-4300,-4380,-4500,-4656,-4799,-4890,-4934,-4968,-5019,-5086,-5156,-5225,-5291,
+-5354,-5411,-5465,-5521,-5584,-5650,-5717,-5788,-5869,-5953,-6024,-6079,-6131,-6201,-6283,-6356,-6413,-6468,-6533,-6601,-6660,
+-6712,-6762,-6813,-6860,-6908,-6958,-7006,-7054,-7107,-7173,-7243,-7304,-7352,-7396,-7439,-7481,-7527,-7588,-7662,-7745,-7834,
+-7929,-8026,-8113,-8194,-8275,-8353,-8417,-8471,-8531,-8590,-8623,-8621,-8617,-8640,-8679,-8713,-8764,-8879,-9042,-9174,-9220,
+-9212,-9217,-9254,-9291,-9310,-9328,-9356,-9379,-9388,-9394,-9411,-9433,-9443,-9445,-9455,-9479,-9506,-9516,-9499,-9459,-9416,
+-9394,-9405,-9432,-9443,-9416,-9352,-9268,-9176,-9074,-8960,-8846,-8764,-8737,-8750,-8764,-8748,-8706,-8655,-8604,-8548,-8483,
+-8400,-8292,-8162,-8031,-7914,-7812,-7717,-7631,-7556,-7479,-7383,-7259,-7117,-6961,-6795,-6633,-6502,-6411,-6346,-6287,-6230,
+-6172,-6103,-6012,-5900,-5777,-5648,-5514,-5378,-5240,-5094,-4934,-4772,-4630,-4511,-4399,-4278,-4150,-4025,-3906,-3778,-3629,
+-3467,-3310,-3170,-3045,-2915,-2766,-2596,-2423,-2277,-2175,-2104,-2030,-1939,-1862,-1845,-1892,-1932,-1873,-1681,-1416,-1183,
+-1037,-944,-816,-590,-283,38,318,546,736,893,1009,1082,1130,1184,1262,1348,1418,1464,1517,1603,1718,
+1833,1934,2033,2136,2223,2279,2325,2388,2471,2553,2626,2696,2765,2826,2879,2936,3001,3064,3126,3196,3279,
+3363,3444,3531,3629,3722,3798,3869,3954,4051,4136,4198,4244,4286,4331,4389,4476,4593,4714,4811,4879,4928,
+4967,4992,4990,4955,4887,4808,4766,4808,4932,5100,5274,5446,5595,5668,5637,5565,5578,5739,5970,6130,6151,
+6080,6008,5983,5978,5932,5815,5668,5579,5599,5697,5795,5843,5845,5831,5830,5854,5887,5892,5861,5842,5880,
+5947,5969,5935,5913,5952,6005,5993,5914,5832,5793,5784,5776,5761,5741,5712,5664,5593,5502,5427,5447,5627,
+5939,6271,6515,6644,6690,6693,6681,6686,6736,6844,7002,7188,7365,7491,7559,7615,7719,7887,8077,8226,8292,
+8280,8233,8196,8184,8165,8102,7993,7877,7786,7730,7707,7728,7794,7873,7917,7906,7864,7826,7800,7766,7713,
+7654,7606,7570,7534,7499,7475,7469,7484,7518,7568,7625,7678,7726,7771,7815,7858,7902,7950,7998,8034,8056,
+8066,8067,8061,8053,8047,8037,8015,7980,7942,7898,7844,7786,7730,7663,7559,7417,7255,7072,6840,6578,6374,
+6305,6332,6346,6293,6230,6239,6322,6416,6465,6468,6450,6434,6426,6411,6371,6306,6236,6176,6119,6051,5982,
+5928,5884,5832,5764,5691,5622,5557,5497,5450,5413,5365,5295,5223,5174,5145,5111,5049,4966,4884,4825,4795,
+4780,4751,4693,4613,4539,4482,4438,4397,4362,4338,4319,4295,4260,4216,4171,4126,4083,4045,4013,3989,3968,
+3943,3906,3856,3795,3724,3649,3582,3537,3513,3490,3454,3406,3355,3306,3262,3225,3192,3150,3094,3039,3000,
+2967,2925,2890,2893,2927,2935,2879,2784,2705,2668,2660,2663,2668,2663,2636,2597,2567,2554,2538,2507,2466,
+2425,2380,2324,2265,2214,2170,2132,2101,2078,2058,2034,2007,1986,1969,1952,1936,1922,1903,1871,1838,1835,
+1871,1910,1906,1858,1815,1817,1844,1849,1822,1799,1803,1812,1794,1762,1753,1772,1777,1737,1673,1626,1616,
+1630,1647,1658,1664,1667,1672,1676,1670,1650,1629,1620,1623,1628,1636,1656,1684,1703,1706,1705,1710,1711,
+1699,1678,1657,1632,1600,1570,1560,1565,1562,1541,1513,1493,1478,1456,1425,1397,1382,1382,1395,1418,1441,
+1447,1428,1396,1373,1368,1371,1375,1382,1392,1399,1397,1386,1371,1358,1352,1356,1368,1370,1349,1315,1291,
+1285,1284,1272,1252,1242,1249,1265,1275,1271,1255,1236,1222,1213,1204,1193,1180,1164,1144,1121,1101,1085,
+1067,1044,1017,993,972,947,919,892,865,832,791,754,729,713,697,674,646,619,591,558,523,
+488,459,433,405,374,342,314,290,268,246,220,190,157,124,92,61,30,1,-27,-57,-89,
+-121,-153,-185,-219,-254,-288,-318,-346,-375,-407,-443,-476,-503,-523,-543,-563,-583,-603,-631,-668,-706,
+-738,-764,-793,-828,-861,-884,-901,-917,-936,-959,-984,-1013,-1043,-1071,-1098,-1124,-1147,-1164,-1179,-1195,-1215,
+-1236,-1254,-1269,-1285,-1304,-1327,-1354,-1380,-1403,-1425,-1447,-1468,-1485,-1499,-1514,-1531,-1546,-1558,-1570,-1585,-1601,
+-1615,-1628,-1642,-1661,-1681,-1701,-1715,-1724,-1729,-1737,-1751,-1769,-1782,-1787,-1788,-1790,-1795,-1797,-1797,-1799,-1803,
+-1807,-1808,-1805,-1803,-1800,-1796,-1790,-1786,-1781,-1776,-1769,-1763,-1757,-1750,-1742,-1733,-1723,-1711,-1698,-1688,-1678,
+-1666,-1656,-1648,-1643,-1635,-1623,-1610,-1599,-1589,-1578,-1569,-1562,-1554,-1547,-1541,-1537,-1529,-1518,-1508,-1503,-1498,
+-1491,-1483,-1478,-1472,-1466,-1461,-1458,-1456,-1453,-1451,-1451,-1451,-1449,-1446,-1445,-1445,-1445,-1444,-1444,-1444,-1443,
+-1443,-1443,-1444,-1443,-1440,-1436,-1430,-1425,-1421,-1416,-1413,-1411,-1413,-1413,-1407,-1398,-1392,-1388,-1383,-1378,-1376,
+-1375,-1369,-1358,-1346,-1336,-1327,-1316,-1307,-1295,-1279,-1261,-1249,-1242,-1227,-1205,-1182,-1165,-1148,-1128,-1107,-1086,
+-1058,-1026,-1000,-978,-949,-912,-881,-861,-838,-801,-762,-731,-698,-654,-606,-566,-523,-469,-418,-380,-343,
+-293,-237,-192,-148,-88,-26,18,53,100,146,168,174,185,172,97,7,31,232,533,813,1032,
+1226,1417,1585,1711,1784,1787,1717,1618,1529,1432,1287,1116,1001,983,1019,1049,1070,1116,1195,1289,1387,
+1489,1595,1701,1805,1906,1996,2068,2116,2138,2131,2108,2089,2085,2084,2079,2069,2055,2027,1980,1924,1869,
+1820,1777,1741,1697,1626,1527,1426,1341,1263,1177,1091,1026,980,934,879,823,766,695,601,488,360,
+222,79,-53,-170,-278,-381,-474,-549,-602,-622,-605,-569,-555,-589,-646,-682,-681,-678,-711,-781,-853,
+-899,-929,-971,-1033,-1099,-1150,-1193,-1258,-1367,-1509,-1648,-1761,-1847,-1923,-1991,-2040,-2058,-2044,-2014,-1985,-1972,
+-1980,-2001,-2023,-2045,-2076,-2119,-2161,-2189,-2202,-2209,-2211,-2214,-2227,-2253,-2285,-2315,-2355,-2418,-2495,-2549,-2560,
+-2542,-2521,-2504,-2483,-2468,-2477,-2519,-2580,-2641,-2692,-2728,-2747,-2748,-2734,-2713,-2685,-2646,-2590,-2519,-2434,-2342,
+-2250,-2172,-2125,-2105,-2090,-2054,-1992,-1911,-1812,-1692,-1572,-1493,-1466,-1454,-1407,-1317,-1216,-1127,-1042,-954,-883,
+-851,-847,-847,-848,-867,-909,-945,-942,-894,-827,-771,-740,-737,-764,-817,-866,-872,-813,-708,-608,-560,
+-568,-595,-601,-583,-569,-583,-615,-628,-604,-553,-500,-456,-422,-394,-372,-355,-346,-346,-350,-348,-335,
+-314,-292,-264,-228,-193,-165,-144,-118,-87,-57,-31,-7,18,43,67,97,135,174,210,244,282,
+326,374,419,456,484,510,540,575,611,649,694,747,803,859,916,971,1020,1059,1094,1129,1164,
+1200,1240,1282,1323,1362,1403,1445,1484,1519,1551,1584,1614,1642,1671,1702,1730,1757,1790,1829,1862,1883,
+1895,1906,1914,1912,1905,1898,1894,1888,1879,1873,1870,1867,1862,1855,1849,1841,1834,1827,1821,1817,1816,
+1820,1822,1817,1807,1799,1792,1785,1780,1780,1780,1777,1773,1772,1770,1763,1759,1766,1782,1796,1801,1804,
+1811,1816,1813,1805,1798,1792,1782,1766,1733,1716,1691,1659,1624,1591,1557,1525,1495,1462,1417,1361,1303,
+1251,1205,1166,1138,1118,1099,1071,1032,989,951,925,907,888,861,832,809,794,786,779,763,724,
+656,571,495,439,410,412,445,493,533,553,547,502,416,324,278,296,338,361,355,338,315,
+285,253,225,193,143,77,3,-67,-123,-158,-187,-243,-340,-457,-564,-654,-731,-794,-838,-881,-944,
+-1022,-1096,-1155,-1206,-1252,-1291,-1328,-1373,-1416,-1440,-1445,-1448,-1458,-1476,-1507,-1562,-1635,-1698,-1728,-1728,-1720,
+-1726,-1753,-1785,-1793,-1771,-1747,-1742,-1738,-1713,-1683,-1668,-1655,-1617,-1574,-1555,-1524,-1413,-1255,-1181,-1256,-1383,
+-1427,-1386,-1360,-1395,-1446,-1468,-1481,-1512,-1554,-1598,-1661,-1744,-1817,-1863,-1900,-1948,-1992,-2015,-2024,-2029,-2009,
+-1943,-1858,-1808,-1820,-1864,-1885,-1860,-1807,-1768,-1781,-1848,-1944,-2043,-2128,-2193,-2252,-2333,-2467,-2648,-2834,-2985,
+-3098,-3185,-3248,-3284,-3308,-3355,-3448,-3575,-3701,-3801,-3876,-3937,-3988,-4025,-4049,-4076,-4119,-4170,-4210,-4240,-4272,
+-4307,-4326,-4325,-4321,-4335,-4361,-4384,-4396,-4397,-4389,-4378,-4380,-4398,-4412,-4409,-4402,-4405,-4411,-4403,-4383,-4370,
+-4367,-4359,-4343,-4336,-4346,-4361,-4361,-4346,-4332,-4328,-4335,-4344,-4343,-4316,-4261,-4190,-4124,-4086,-4088,-4126,-4179,
+-4228,-4286,-4383,-4528,-4687,-4810,-4880,-4922,-4967,-5028,-5099,-5171,-5240,-5305,-5366,-5424,-5479,-5535,-5594,-5659,-5732,
+-5812,-5889,-5955,-6010,-6068,-6139,-6215,-6282,-6342,-6405,-6474,-6538,-6593,-6646,-6705,-6763,-6812,-6855,-6902,-6955,-7009,
+-7066,-7128,-7191,-7247,-7296,-7342,-7385,-7425,-7469,-7525,-7595,-7675,-7766,-7867,-7966,-8052,-8128,-8204,-8281,-8350,-8417,
+-8487,-8542,-8552,-8521,-8498,-8518,-8569,-8625,-8704,-8837,-9001,-9123,-9161,-9153,-9160,-9195,-9227,-9246,-9264,-9290,-9311,
+-9318,-9321,-9334,-9350,-9358,-9361,-9372,-9397,-9425,-9436,-9417,-9375,-9336,-9327,-9351,-9381,-9383,-9340,-9260,-9164,-9068,
+-8971,-8869,-8769,-8698,-8675,-8692,-8710,-8702,-8669,-8629,-8588,-8539,-8471,-8378,-8259,-8124,-7994,-7884,-7793,-7712,-7636,
+-7564,-7482,-7376,-7247,-7104,-6953,-6797,-6646,-6522,-6438,-6381,-6330,-6274,-6208,-6127,-6025,-5908,-5787,-5669,-5549,-5422,
+-5285,-5134,-4965,-4791,-4639,-4523,-4428,-4325,-4203,-4073,-3946,-3808,-3650,-3485,-3340,-3222,-3109,-2971,-2807,-2635,-2473,
+-2331,-2212,-2112,-2013,-1903,-1803,-1765,-1811,-1890,-1904,-1782,-1550,-1303,-1128,-1024,-922,-750,-504,-226,50,321,
+585,819,989,1085,1132,1176,1246,1337,1419,1479,1532,1609,1712,1817,1908,1997,2094,2185,2252,2306,2370,
+2447,2519,2582,2645,2715,2782,2839,2896,2957,3018,3079,3145,3220,3297,3373,3454,3541,3628,3708,3788,3880,
+3980,4074,4155,4221,4271,4311,4362,4449,4568,4682,4761,4811,4852,4891,4912,4895,4838,4759,4698,4696,4776,
+4918,5083,5244,5398,5525,5583,5553,5490,5490,5602,5779,5924,5982,5972,5949,5944,5936,5873,5736,5580,5497,
+5532,5637,5729,5768,5775,5780,5796,5820,5837,5829,5802,5794,5834,5889,5896,5854,5832,5874,5933,5938,5890,
+5849,5838,5814,5739,5630,5538,5491,5473,5450,5406,5364,5387,5527,5770,6045,6275,6417,6469,6460,6446,6484,
+6590,6737,6890,7035,7166,7261,7311,7348,7428,7578,7763,7920,8011,8052,8083,8127,8170,8178,8136,8060,7971,
+7882,7802,7751,7759,7835,7946,8028,8037,7985,7921,7878,7833,7747,7618,7492,7412,7376,7352,7318,7286,7284,
+7331,7415,7506,7577,7631,7683,7738,7789,7834,7880,7934,7987,8029,8058,8076,8084,8082,8071,8050,8018,7985,
+7959,7934,7898,7854,7811,7750,7638,7473,7284,7072,6797,6459,6174,6081,6183,6327,6365,6301,6251,6298,6412,
+6506,6532,6512,6493,6501,6512,6485,6411,6320,6241,6174,6106,6042,5995,5957,5909,5841,5766,5696,5630,5569,
+5519,5476,5425,5354,5279,5222,5187,5152,5098,5030,4967,4923,4897,4869,4819,4741,4653,4578,4526,4488,4452,
+4416,4388,4367,4343,4308,4262,4213,4167,4123,4082,4047,4026,4013,3991,3951,3899,3842,3782,3713,3643,3592,
+3565,3546,3511,3455,3390,3332,3283,3243,3203,3155,3102,3056,3022,2988,2946,2914,2920,2950,2956,2908,2828,
+2761,2719,2695,2688,2699,2707,2685,2635,2591,2570,2556,2526,2481,2438,2397,2347,2287,2229,2181,2143,2113,
+2088,2064,2037,2014,1999,1988,1972,1951,1931,1909,1878,1849,1851,1890,1927,1911,1844,1781,1771,1795,1808,
+1801,1808,1841,1861,1833,1780,1752,1756,1746,1698,1639,1612,1619,1638,1652,1662,1670,1675,1678,1682,1681,
+1668,1654,1648,1647,1643,1642,1658,1687,1707,1709,1707,1713,1718,1708,1689,1667,1640,1603,1568,1553,1556,
+1557,1541,1514,1488,1465,1441,1414,1389,1370,1362,1371,1400,1433,1448,1431,1395,1364,1350,1349,1351,1352,
+1352,1356,1361,1363,1356,1340,1325,1324,1334,1339,1325,1298,1279,1275,1275,1262,1237,1215,1207,1215,1229,
+1235,1229,1214,1199,1188,1178,1164,1146,1127,1106,1084,1063,1045,1027,1008,988,971,955,936,913,889,
+860,821,776,734,705,686,669,648,624,600,572,542,509,478,451,427,403,375,346,318,293,
+270,247,221,192,160,127,93,59,27,-1,-28,-55,-85,-118,-150,-183,-218,-252,-285,-316,-345,
+-374,-407,-442,-478,-507,-528,-546,-565,-584,-601,-624,-655,-692,-725,-751,-780,-814,-848,-874,-894,-912,
+-932,-953,-977,-1005,-1035,-1066,-1096,-1124,-1146,-1162,-1177,-1195,-1214,-1231,-1243,-1253,-1266,-1286,-1310,-1336,-1358,
+-1376,-1394,-1416,-1439,-1459,-1474,-1488,-1502,-1516,-1529,-1542,-1556,-1569,-1580,-1590,-1602,-1620,-1641,-1663,-1680,-1690,
+-1698,-1707,-1722,-1740,-1753,-1758,-1759,-1761,-1766,-1768,-1768,-1768,-1770,-1771,-1770,-1767,-1764,-1761,-1757,-1752,-1749,
+-1746,-1742,-1737,-1731,-1724,-1716,-1708,-1700,-1691,-1679,-1666,-1657,-1649,-1638,-1626,-1616,-1608,-1598,-1584,-1571,-1560,
+-1551,-1541,-1530,-1520,-1512,-1506,-1500,-1495,-1490,-1485,-1481,-1474,-1467,-1459,-1454,-1451,-1446,-1440,-1434,-1431,-1427,
+-1425,-1425,-1428,-1431,-1431,-1430,-1428,-1427,-1427,-1429,-1430,-1428,-1425,-1425,-1429,-1434,-1439,-1441,-1441,-1438,-1433,
+-1428,-1421,-1413,-1409,-1410,-1413,-1409,-1400,-1394,-1391,-1387,-1381,-1379,-1379,-1374,-1363,-1353,-1346,-1339,-1330,-1321,
+-1310,-1294,-1273,-1259,-1252,-1241,-1221,-1198,-1180,-1162,-1141,-1122,-1102,-1077,-1047,-1020,-998,-970,-935,-905,-883,
+-857,-820,-780,-748,-713,-666,-618,-578,-538,-488,-441,-404,-365,-310,-253,-211,-170,-111,-50,-14,11,
+53,106,139,152,162,140,50,-47,0,267,657,1005,1246,1426,1592,1731,1813,1823,1757,1635,1499,
+1388,1291,1179,1067,1001,994,1005,1009,1030,1097,1193,1284,1365,1450,1549,1659,1771,1877,1963,2028,2076,
+2110,2123,2112,2094,2082,2079,2080,2085,2082,2057,2001,1935,1882,1849,1829,1806,1765,1692,1593,1491,1403,
+1323,1243,1168,1106,1052,995,935,882,829,762,669,555,422,270,111,-36,-163,-275,-376,-462,-528,
+-572,-589,-570,-531,-512,-539,-590,-615,-597,-574,-598,-671,-753,-807,-841,-892,-978,-1084,-1183,-1269,-1359,
+-1465,-1585,-1699,-1793,-1867,-1932,-1998,-2057,-2087,-2077,-2038,-2001,-1991,-2014,-2055,-2094,-2120,-2139,-2159,-2179,-2192,
+-2199,-2205,-2211,-2218,-2228,-2246,-2270,-2302,-2350,-2425,-2506,-2556,-2555,-2523,-2491,-2470,-2451,-2437,-2452,-2506,-2583,
+-2654,-2704,-2732,-2739,-2726,-2700,-2671,-2645,-2612,-2563,-2498,-2423,-2348,-2275,-2211,-2164,-2134,-2105,-2061,-1994,-1909,
+-1804,-1683,-1566,-1491,-1467,-1453,-1400,-1300,-1191,-1104,-1031,-956,-889,-849,-834,-823,-810,-814,-847,-887,-901,
+-877,-833,-794,-775,-789,-833,-889,-921,-905,-840,-754,-681,-643,-642,-659,-667,-654,-637,-635,-646,-647,
+-619,-569,-517,-472,-438,-413,-396,-384,-376,-372,-372,-367,-353,-334,-313,-288,-254,-218,-188,-164,-137,
+-107,-78,-52,-27,-3,16,35,62,100,141,178,215,258,306,354,396,429,458,487,520,557,
+596,639,688,742,797,850,903,956,1002,1042,1079,1116,1155,1195,1235,1277,1320,1362,1405,1446,1482,
+1514,1543,1573,1603,1631,1659,1684,1708,1735,1769,1807,1839,1864,1884,1899,1906,1900,1890,1881,1876,1870,
+1863,1858,1855,1853,1850,1844,1835,1827,1823,1822,1820,1816,1813,1813,1811,1804,1797,1792,1784,1774,1768,
+1768,1768,1763,1760,1761,1763,1759,1758,1769,1786,1793,1789,1783,1785,1786,1780,1770,1760,1751,1743,1733,
+1708,1696,1671,1637,1600,1564,1524,1484,1448,1410,1361,1301,1244,1198,1161,1126,1097,1073,1050,1023,990,
+955,923,898,879,860,835,810,791,778,767,758,753,737,696,634,570,514,466,429,413,426,
+465,518,556,540,457,351,296,317,368,391,373,342,312,282,251,225,196,149,83,9,-53,
+-92,-106,-118,-163,-258,-382,-503,-604,-684,-740,-779,-826,-899,-984,-1051,-1097,-1140,-1188,-1233,-1274,-1317,
+-1360,-1391,-1405,-1413,-1423,-1436,-1463,-1518,-1594,-1657,-1683,-1678,-1669,-1680,-1713,-1748,-1757,-1738,-1717,-1714,-1713,
+-1693,-1668,-1659,-1647,-1609,-1563,-1546,-1528,-1437,-1286,-1198,-1264,-1417,-1514,-1507,-1460,-1443,-1458,-1477,-1494,-1510,
+-1529,-1571,-1655,-1759,-1835,-1868,-1892,-1935,-1984,-2010,-2014,-2003,-1968,-1901,-1829,-1797,-1819,-1862,-1884,-1865,-1817,
+-1772,-1767,-1826,-1942,-2078,-2185,-2241,-2281,-2365,-2524,-2715,-2872,-2976,-3064,-3167,-3266,-3329,-3361,-3406,-3492,-3605,
+-3713,-3800,-3871,-3935,-3991,-4030,-4053,-4074,-4107,-4149,-4188,-4220,-4250,-4274,-4282,-4274,-4271,-4288,-4320,-4351,-4369,
+-4367,-4348,-4335,-4346,-4373,-4387,-4378,-4371,-4379,-4384,-4368,-4344,-4335,-4335,-4320,-4296,-4289,-4303,-4315,-4307,-4292,
+-4279,-4265,-4256,-4263,-4279,-4267,-4204,-4115,-4050,-4035,-4061,-4105,-4149,-4185,-4222,-4288,-4405,-4557,-4700,-4803,-4867,
+-4920,-4979,-5047,-5117,-5185,-5250,-5316,-5379,-5436,-5488,-5542,-5605,-5678,-5753,-5823,-5884,-5944,-6008,-6077,-6145,-6207,
+-6271,-6342,-6415,-6479,-6535,-6595,-6660,-6720,-6764,-6801,-6848,-6906,-6966,-7023,-7078,-7133,-7187,-7238,-7284,-7322,-7356,
+-7398,-7455,-7526,-7606,-7697,-7798,-7898,-7985,-8060,-8136,-8214,-8288,-8360,-8424,-8461,-8450,-8409,-8388,-8415,-8475,-8549,
+-8649,-8793,-8950,-9057,-9092,-9091,-9104,-9138,-9169,-9187,-9205,-9227,-9243,-9250,-9254,-9264,-9275,-9280,-9286,-9303,-9334,
+-9368,-9383,-9369,-9335,-9309,-9310,-9333,-9349,-9329,-9265,-9171,-9071,-8980,-8896,-8810,-8724,-8664,-8651,-8675,-8699,-8692,
+-8657,-8613,-8570,-8519,-8445,-8342,-8214,-8077,-7953,-7854,-7777,-7709,-7641,-7567,-7479,-7370,-7241,-7102,-6960,-6815,-6678,
+-6567,-6491,-6437,-6384,-6318,-6236,-6139,-6026,-5907,-5793,-5688,-5579,-5456,-5315,-5160,-4988,-4810,-4653,-4537,-4453,-4365,
+-4255,-4132,-4009,-3872,-3707,-3532,-3389,-3287,-3185,-3043,-2869,-2698,-2548,-2409,-2271,-2140,-2019,-1907,-1811,-1765,-1792,
+-1866,-1912,-1853,-1674,-1437,-1232,-1101,-1009,-891,-715,-491,-240,31,318,591,815,973,1074,1147,1221,1309,
+1399,1470,1525,1591,1683,1785,1873,1952,2037,2128,2209,2279,2349,2422,2486,2542,2603,2677,2749,2806,2853,
+2904,2967,3036,3107,3177,3244,3313,3389,3470,3550,3628,3713,3809,3911,4006,4092,4166,4224,4272,4335,4432,
+4547,4641,4694,4727,4770,4820,4844,4814,4743,4671,4644,4682,4780,4923,5092,5265,5416,5510,5529,5493,5451,
+5455,5522,5630,5740,5821,5867,5891,5909,5902,5832,5688,5530,5452,5488,5582,5656,5687,5706,5736,5771,5800,
+5820,5826,5817,5806,5815,5832,5827,5797,5782,5804,5832,5827,5801,5800,5824,5809,5701,5515,5325,5197,5151,
+5157,5178,5206,5267,5391,5584,5816,6029,6167,6204,6179,6187,6297,6490,6679,6800,6864,6913,6963,7002,7034,
+7094,7208,7353,7479,7553,7598,7656,7736,7809,7848,7859,7866,7867,7845,7795,7750,7762,7854,8001,8132,8179,
+8134,8055,7993,7934,7822,7644,7464,7352,7312,7287,7231,7155,7109,7130,7211,7308,7386,7445,7509,7589,7671,
+7739,7798,7859,7920,7973,8019,8057,8085,8096,8090,8071,8047,8023,8000,7965,7916,7872,7853,7827,7728,7526,
+7258,6964,6624,6234,5895,5775,5924,6196,6379,6393,6333,6327,6410,6516,6572,6571,6558,6568,6587,6571,6501,
+6403,6309,6230,6158,6097,6055,6025,5984,5923,5848,5775,5708,5646,5593,5546,5494,5428,5357,5293,5241,5192,
+5137,5079,5029,4993,4963,4924,4865,4788,4704,4629,4572,4531,4496,4459,4419,4385,4358,4330,4294,4250,4203,
+4157,4114,4080,4059,4045,4024,3985,3936,3885,3829,3761,3691,3637,3607,3584,3545,3486,3420,3360,3311,3268,
+3226,3183,3141,3104,3072,3035,2993,2960,2951,2953,2936,2894,2849,2816,2784,2746,2721,2725,2737,2715,2655,
+2597,2571,2560,2533,2487,2442,2404,2363,2311,2254,2204,2164,2133,2107,2085,2061,2041,2027,2017,2003,1982,
+1957,1927,1887,1852,1850,1888,1926,1912,1845,1775,1750,1762,1777,1790,1826,1880,1903,1866,1799,1758,1747,
+1726,1677,1630,1620,1635,1648,1653,1659,1668,1673,1673,1676,1679,1677,1674,1676,1674,1663,1653,1663,1689,
+1707,1705,1700,1707,1717,1711,1688,1661,1636,1609,1580,1559,1549,1542,1528,1508,1483,1457,1434,1417,1403,
+1385,1368,1364,1381,1407,1420,1407,1376,1345,1329,1327,1329,1326,1320,1320,1327,1333,1329,1314,1298,1293,
+1298,1302,1294,1278,1266,1263,1262,1253,1231,1200,1175,1165,1173,1186,1192,1184,1170,1156,1142,1124,1102,
+1081,1062,1041,1020,1001,982,964,947,933,919,905,888,868,839,799,753,709,676,652,634,617,
+598,575,548,519,491,464,439,416,394,371,348,323,299,275,250,222,191,158,126,93,60,
+29,3,-19,-44,-74,-107,-140,-174,-209,-242,-274,-305,-337,-370,-403,-440,-476,-507,-530,-549,-570,
+-591,-609,-628,-655,-687,-718,-743,-769,-799,-832,-861,-885,-907,-927,-946,-968,-994,-1023,-1052,-1081,-1107,
+-1127,-1142,-1157,-1178,-1202,-1220,-1230,-1239,-1251,-1271,-1296,-1320,-1341,-1357,-1372,-1391,-1415,-1436,-1453,-1465,-1477,
+-1490,-1505,-1520,-1533,-1543,-1549,-1556,-1567,-1583,-1602,-1622,-1639,-1653,-1664,-1676,-1691,-1708,-1721,-1728,-1730,-1733,
+-1736,-1739,-1739,-1738,-1737,-1736,-1733,-1730,-1728,-1726,-1723,-1719,-1716,-1713,-1709,-1704,-1699,-1692,-1684,-1675,-1667,
+-1657,-1644,-1632,-1625,-1621,-1614,-1602,-1587,-1573,-1559,-1544,-1530,-1519,-1510,-1501,-1490,-1480,-1472,-1467,-1462,-1456,
+-1452,-1451,-1450,-1444,-1434,-1425,-1421,-1419,-1416,-1412,-1410,-1408,-1405,-1403,-1404,-1409,-1414,-1417,-1418,-1417,-1415,
+-1414,-1417,-1420,-1418,-1413,-1412,-1415,-1422,-1430,-1438,-1442,-1440,-1436,-1431,-1424,-1414,-1406,-1406,-1409,-1406,-1399,
+-1396,-1398,-1395,-1388,-1383,-1382,-1378,-1367,-1359,-1355,-1350,-1340,-1330,-1321,-1307,-1287,-1270,-1261,-1252,-1234,-1214,
+-1197,-1179,-1158,-1137,-1118,-1095,-1066,-1038,-1015,-988,-956,-926,-902,-875,-838,-800,-767,-729,-682,-636,-599,
+-559,-509,-461,-423,-380,-322,-266,-228,-193,-139,-83,-49,-23,24,85,124,138,138,98,-8,-99,
+-13,313,751,1112,1337,1495,1650,1785,1858,1848,1750,1582,1399,1260,1173,1106,1041,995,975,968,974,
+1015,1098,1191,1264,1328,1407,1508,1619,1731,1837,1923,1986,2035,2079,2108,2111,2094,2077,2072,2080,2096,
+2105,2085,2027,1955,1901,1878,1875,1868,1835,1765,1666,1562,1468,1386,1312,1245,1186,1124,1056,991,938,
+890,828,742,632,495,332,159,0,-133,-245,-339,-414,-470,-513,-537,-532,-506,-492,-514,-559,-583,
+-569,-552,-580,-662,-756,-822,-865,-922,-1014,-1131,-1246,-1349,-1442,-1531,-1619,-1705,-1784,-1852,-1915,-1980,-2044,
+-2081,-2076,-2039,-2003,-1998,-2028,-2078,-2124,-2154,-2169,-2179,-2188,-2194,-2196,-2200,-2209,-2220,-2231,-2241,-2258,-2288,
+-2342,-2421,-2503,-2548,-2536,-2492,-2456,-2440,-2432,-2429,-2450,-2509,-2592,-2668,-2715,-2732,-2720,-2688,-2651,-2624,-2608,
+-2587,-2542,-2475,-2403,-2341,-2289,-2241,-2193,-2148,-2105,-2056,-1991,-1906,-1803,-1688,-1582,-1510,-1474,-1443,-1377,-1273,
+-1167,-1086,-1022,-953,-885,-841,-822,-807,-789,-781,-796,-823,-837,-831,-813,-792,-776,-781,-818,-871,-904,
+-894,-852,-805,-768,-742,-730,-729,-729,-717,-695,-677,-670,-659,-631,-588,-543,-501,-465,-438,-423,-415,
+-409,-401,-392,-382,-366,-348,-328,-306,-278,-246,-215,-188,-159,-132,-108,-86,-63,-40,-20,-2,24,
+62,102,139,178,223,272,316,353,387,422,459,499,541,585,630,678,728,778,826,873,921,
+967,1010,1049,1091,1136,1182,1227,1274,1323,1370,1414,1452,1483,1509,1531,1555,1581,1609,1635,1658,1683,
+1716,1756,1795,1826,1849,1869,1884,1886,1876,1863,1855,1853,1850,1847,1845,1845,1846,1846,1840,1829,1817,
+1812,1812,1811,1806,1802,1797,1790,1780,1774,1770,1762,1752,1747,1748,1747,1742,1741,1747,1753,1751,1750,
+1757,1767,1766,1757,1752,1755,1758,1754,1745,1734,1723,1714,1708,1692,1678,1651,1613,1575,1537,1492,1441,
+1393,1349,1301,1247,1199,1161,1127,1091,1057,1030,1005,977,951,926,901,878,858,839,816,794,777,
+765,754,744,742,740,724,691,651,612,566,509,453,422,434,489,553,572,513,412,344,348,
+389,410,398,372,345,312,275,244,216,180,129,71,16,-22,-43,-61,-107,-197,-314,-432,-532,
+-610,-664,-704,-757,-834,-915,-971,-1002,-1036,-1086,-1138,-1185,-1230,-1276,-1316,-1347,-1374,-1398,-1415,-1439,-1486,
+-1551,-1604,-1625,-1623,-1623,-1638,-1667,-1696,-1708,-1701,-1689,-1685,-1679,-1660,-1642,-1641,-1637,-1602,-1552,-1530,-1520,
+-1456,-1331,-1242,-1285,-1423,-1530,-1537,-1481,-1437,-1436,-1465,-1492,-1498,-1499,-1538,-1640,-1769,-1857,-1888,-1903,-1939,
+-1987,-2016,-2016,-1990,-1940,-1880,-1843,-1850,-1881,-1899,-1890,-1861,-1822,-1782,-1769,-1826,-1962,-2125,-2237,-2275,-2303,
+-2407,-2596,-2786,-2898,-2949,-3021,-3151,-3290,-3375,-3413,-3456,-3536,-3639,-3733,-3807,-3869,-3927,-3980,-4022,-4048,-4067,
+-4091,-4124,-4160,-4191,-4213,-4224,-4222,-4218,-4226,-4251,-4284,-4316,-4336,-4338,-4325,-4320,-4339,-4367,-4370,-4350,-4338,
+-4348,-4352,-4332,-4309,-4304,-4301,-4277,-4249,-4247,-4263,-4264,-4248,-4240,-4240,-4220,-4187,-4187,-4233,-4268,-4233,-4147,
+-4077,-4058,-4071,-4091,-4112,-4136,-4162,-4205,-4288,-4419,-4566,-4694,-4789,-4863,-4931,-4998,-5064,-5128,-5191,-5257,-5325,
+-5389,-5444,-5497,-5556,-5623,-5692,-5757,-5820,-5884,-5951,-6015,-6075,-6136,-6206,-6283,-6358,-6424,-6484,-6547,-6612,-6667,
+-6708,-6746,-6796,-6858,-6919,-6973,-7023,-7076,-7131,-7181,-7222,-7251,-7280,-7325,-7388,-7463,-7542,-7629,-7725,-7824,-7914,
+-7995,-8074,-8151,-8218,-8272,-8309,-8318,-8302,-8284,-8295,-8342,-8408,-8489,-8603,-8750,-8892,-8980,-9012,-9025,-9050,-9085,
+-9115,-9137,-9155,-9171,-9180,-9184,-9190,-9198,-9206,-9214,-9228,-9255,-9295,-9332,-9351,-9343,-9320,-9306,-9311,-9324,-9320,
+-9282,-9208,-9112,-9017,-8934,-8860,-8783,-8707,-8659,-8659,-8693,-8718,-8702,-8651,-8589,-8532,-8472,-8393,-8288,-8159,-8027,
+-7911,-7822,-7754,-7693,-7627,-7551,-7461,-7355,-7235,-7105,-6971,-6835,-6710,-6611,-6541,-6485,-6423,-6345,-6252,-6146,-6030,
+-5909,-5796,-5694,-5590,-5469,-5328,-5176,-5014,-4847,-4695,-4579,-4496,-4416,-4315,-4201,-4084,-3947,-3772,-3587,-3444,-3350,
+-3254,-3108,-2926,-2758,-2622,-2491,-2343,-2189,-2052,-1942,-1860,-1815,-1818,-1863,-1908,-1897,-1784,-1581,-1359,-1186,-1074,
+-976,-846,-677,-483,-272,-38,218,485,738,946,1093,1193,1278,1364,1440,1495,1551,1634,1738,1835,1915,
+1993,2081,2170,2250,2323,2393,2456,2515,2581,2658,2730,2779,2811,2851,2914,2994,3073,3139,3199,3264,3341,
+3423,3501,3577,3660,3754,3851,3942,4025,4100,4165,4227,4303,4400,4500,4570,4603,4630,4678,4738,4769,4744,
+4685,4642,4650,4705,4790,4908,5072,5264,5423,5492,5476,5430,5409,5424,5464,5527,5615,5709,5782,5822,5841,
+5837,5782,5665,5538,5477,5506,5571,5613,5632,5662,5709,5750,5776,5801,5829,5843,5830,5809,5798,5794,5783,
+5766,5750,5729,5698,5673,5679,5711,5710,5607,5383,5096,4852,4736,4754,4853,4971,5092,5240,5437,5673,5887,
+5997,5979,5913,5940,6134,6426,6664,6763,6759,6741,6761,6805,6851,6903,6974,7058,7117,7135,7139,7171,7241,
+7317,7378,7442,7530,7628,7693,7711,7717,7767,7892,8074,8245,8329,8300,8214,8136,8069,7960,7791,7616,7501,
+7446,7395,7305,7180,7064,7001,7002,7043,7093,7146,7221,7331,7461,7584,7691,7780,7850,7904,7952,8003,8047,
+8076,8091,8103,8114,8112,8083,8022,7945,7893,7891,7893,7793,7531,7152,6752,6366,5986,5664,5537,5689,6026,
+6333,6459,6425,6363,6374,6459,6552,6601,6613,6615,6618,6599,6540,6451,6359,6277,6204,6143,6102,6077,6048,
+5999,5932,5859,5791,5729,5671,5614,5559,5500,5435,5367,5299,5233,5170,5113,5066,5028,4990,4945,4889,4827,
+4759,4687,4621,4570,4531,4490,4439,4390,4356,4334,4309,4273,4228,4185,4147,4117,4092,4069,4042,4007,3967,
+3920,3863,3795,3728,3675,3637,3601,3554,3497,3442,3397,3358,3321,3284,3249,3217,3187,3154,3115,3074,3035,
+2999,2959,2915,2881,2872,2876,2857,2808,2760,2745,2746,2721,2658,2595,2565,2557,2538,2498,2452,2414,2379,
+2336,2287,2238,2194,2159,2135,2117,2098,2077,2056,2039,2021,2001,1978,1947,1906,1869,1859,1884,1914,1906,
+1855,1796,1766,1764,1773,1793,1837,1891,1910,1871,1809,1768,1748,1720,1675,1643,1643,1656,1658,1654,1658,
+1669,1673,1671,1672,1680,1686,1689,1693,1691,1677,1663,1667,1688,1701,1695,1690,1702,1718,1713,1685,1654,
+1639,1634,1621,1594,1558,1527,1509,1497,1479,1455,1436,1429,1426,1414,1394,1380,1378,1383,1382,1369,1347,
+1324,1309,1306,1307,1304,1297,1291,1292,1293,1289,1279,1269,1264,1263,1260,1255,1245,1237,1232,1233,1233,
+1222,1194,1158,1129,1120,1128,1139,1141,1132,1117,1099,1080,1059,1041,1023,1006,986,965,943,921,899,
+880,864,852,841,828,805,770,728,687,652,625,606,591,575,552,525,498,473,448,422,398,
+378,360,343,321,296,269,242,212,180,148,116,86,57,30,7,-14,-37,-65,-96,-129,-162,
+-197,-229,-260,-292,-326,-361,-397,-433,-469,-502,-528,-551,-574,-598,-618,-637,-659,-687,-714,-738,-761,
+-788,-817,-848,-876,-900,-919,-937,-957,-982,-1009,-1034,-1059,-1081,-1099,-1112,-1128,-1153,-1181,-1204,-1217,-1227,
+-1240,-1259,-1283,-1307,-1328,-1344,-1357,-1374,-1395,-1417,-1435,-1447,-1456,-1467,-1481,-1497,-1509,-1516,-1521,-1528,-1539,
+-1554,-1570,-1587,-1603,-1617,-1630,-1644,-1660,-1676,-1689,-1697,-1702,-1705,-1706,-1707,-1707,-1705,-1702,-1698,-1697,-1698,
+-1698,-1697,-1695,-1692,-1689,-1683,-1677,-1671,-1666,-1660,-1653,-1645,-1636,-1624,-1611,-1599,-1593,-1592,-1587,-1575,-1558,
+-1539,-1523,-1506,-1490,-1478,-1469,-1461,-1453,-1443,-1436,-1432,-1427,-1420,-1416,-1415,-1415,-1410,-1400,-1391,-1386,-1384,
+-1383,-1383,-1386,-1387,-1385,-1384,-1387,-1393,-1397,-1401,-1404,-1406,-1405,-1405,-1409,-1412,-1412,-1408,-1406,-1407,-1411,
+-1418,-1429,-1436,-1436,-1430,-1426,-1422,-1412,-1403,-1402,-1404,-1401,-1394,-1394,-1401,-1401,-1393,-1386,-1384,-1380,-1371,
+-1364,-1362,-1358,-1346,-1334,-1327,-1317,-1301,-1284,-1273,-1262,-1245,-1227,-1212,-1196,-1175,-1152,-1133,-1112,-1085,-1056,
+-1031,-1005,-975,-946,-920,-893,-858,-822,-787,-747,-702,-660,-625,-584,-530,-477,-436,-393,-337,-283,-246,
+-213,-164,-112,-75,-39,14,73,106,113,101,41,-76,-149,-13,363,815,1145,1321,1446,1598,1761,
+1888,1936,1861,1656,1394,1193,1108,1095,1083,1048,1007,979,982,1028,1101,1169,1220,1279,1368,1475,1580,
+1683,1789,1883,1952,2001,2047,2085,2100,2092,2079,2079,2093,2115,2130,2116,2068,1998,1938,1910,1909,1913,
+1891,1826,1727,1621,1528,1449,1380,1318,1258,1192,1119,1050,993,943,884,803,698,561,397,224,64,
+-71,-184,-277,-346,-398,-440,-471,-484,-480,-483,-510,-552,-583,-587,-591,-631,-717,-816,-892,-945,-1004,
+-1088,-1189,-1287,-1375,-1454,-1525,-1593,-1660,-1729,-1795,-1859,-1926,-1994,-2041,-2051,-2030,-2011,-2015,-2044,-2085,-2124,
+-2150,-2163,-2172,-2181,-2187,-2188,-2190,-2200,-2214,-2226,-2235,-2248,-2275,-2327,-2402,-2479,-2522,-2510,-2469,-2439,-2435,
+-2443,-2448,-2468,-2518,-2590,-2659,-2702,-2714,-2695,-2653,-2610,-2586,-2578,-2562,-2515,-2444,-2372,-2319,-2285,-2251,-2206,
+-2155,-2107,-2060,-1999,-1914,-1810,-1701,-1605,-1534,-1484,-1431,-1351,-1248,-1152,-1080,-1020,-951,-880,-832,-812,-801,
+-783,-767,-763,-763,-758,-749,-741,-727,-701,-684,-707,-767,-826,-852,-847,-836,-827,-812,-792,-778,-770,
+-755,-729,-705,-690,-674,-647,-610,-574,-539,-504,-473,-455,-448,-445,-436,-424,-410,-394,-376,-356,-335,
+-310,-281,-250,-217,-184,-156,-136,-119,-98,-74,-51,-30,-3,31,67,103,143,190,236,274,306,
+341,382,426,471,515,560,605,652,701,751,799,847,895,943,988,1030,1073,1118,1165,1212,1259,
+1308,1356,1398,1432,1460,1484,1506,1527,1552,1580,1608,1634,1663,1700,1743,1780,1805,1823,1840,1855,1858,
+1851,1843,1839,1840,1841,1840,1839,1839,1840,1840,1833,1820,1806,1798,1796,1792,1787,1781,1776,1767,1755,
+1746,1739,1730,1722,1719,1720,1716,1707,1706,1714,1720,1718,1714,1715,1718,1716,1714,1721,1733,1740,1739,
+1735,1726,1713,1700,1692,1683,1661,1625,1586,1554,1521,1472,1409,1349,1301,1255,1209,1168,1131,1091,1050,
+1019,998,977,950,924,904,886,864,844,825,803,780,762,753,745,737,734,736,734,724,712,
+698,672,621,553,493,470,500,562,606,587,513,441,413,421,428,423,409,387,351,309,276,
+253,231,202,164,121,73,29,-11,-65,-142,-236,-331,-417,-494,-560,-618,-684,-761,-831,-871,-892,
+-922,-973,-1029,-1080,-1129,-1179,-1228,-1274,-1318,-1355,-1380,-1405,-1446,-1500,-1544,-1566,-1577,-1589,-1604,-1618,-1633,
+-1650,-1660,-1661,-1655,-1642,-1624,-1616,-1626,-1632,-1604,-1554,-1522,-1509,-1465,-1375,-1304,-1328,-1432,-1523,-1532,-1478,
+-1422,-1409,-1435,-1466,-1470,-1462,-1498,-1607,-1750,-1855,-1899,-1916,-1943,-1981,-2010,-2015,-1985,-1927,-1877,-1877,-1922,
+-1956,-1936,-1880,-1833,-1807,-1786,-1781,-1840,-1984,-2158,-2275,-2315,-2358,-2489,-2690,-2854,-2913,-2924,-2993,-3145,-3305,
+-3400,-3442,-3491,-3574,-3671,-3753,-3815,-3866,-3914,-3960,-4001,-4031,-4051,-4071,-4098,-4131,-4159,-4175,-4178,-4177,-4183,
+-4203,-4230,-4254,-4273,-4289,-4296,-4295,-4302,-4328,-4353,-4349,-4323,-4309,-4315,-4314,-4293,-4276,-4276,-4269,-4237,-4208,
+-4208,-4215,-4197,-4177,-4195,-4224,-4202,-4136,-4116,-4189,-4287,-4312,-4259,-4191,-4149,-4122,-4102,-4099,-4114,-4130,-4148,
+-4198,-4301,-4440,-4578,-4694,-4789,-4870,-4942,-5008,-5069,-5128,-5190,-5259,-5330,-5394,-5449,-5502,-5561,-5627,-5694,-5762,
+-5829,-5892,-5950,-6006,-6070,-6144,-6223,-6297,-6364,-6428,-6493,-6554,-6605,-6648,-6694,-6748,-6807,-6863,-6915,-6966,-7019,
+-7073,-7119,-7152,-7176,-7206,-7257,-7328,-7405,-7480,-7561,-7652,-7750,-7845,-7932,-8014,-8084,-8134,-8158,-8156,-8138,-8129,
+-8152,-8212,-8285,-8358,-8446,-8571,-8718,-8838,-8903,-8933,-8962,-9001,-9038,-9066,-9091,-9112,-9124,-9126,-9127,-9132,-9139,
+-9146,-9159,-9183,-9218,-9260,-9296,-9312,-9306,-9292,-9287,-9292,-9295,-9278,-9236,-9168,-9081,-8992,-8914,-8842,-8766,-8695,
+-8657,-8670,-8710,-8731,-8702,-8633,-8553,-8479,-8410,-8329,-8224,-8102,-7979,-7873,-7790,-7724,-7663,-7597,-7521,-7431,-7330,
+-7220,-7100,-6972,-6842,-6723,-6628,-6558,-6499,-6433,-6353,-6260,-6158,-6045,-5922,-5799,-5688,-5581,-5461,-5325,-5182,-5041,
+-4901,-4766,-4652,-4564,-4481,-4384,-4273,-4150,-3999,-3812,-3623,-3486,-3401,-3306,-3153,-2965,-2803,-2680,-2561,-2415,-2254,
+-2109,-1997,-1917,-1865,-1841,-1846,-1875,-1895,-1850,-1706,-1493,-1286,-1130,-1009,-889,-763,-647,-537,-399,-194,93,
+435,762,1005,1150,1239,1322,1403,1467,1521,1595,1695,1799,1887,1967,2053,2141,2219,2287,2353,2420,2489,
+2561,2637,2705,2752,2784,2823,2887,2968,3046,3108,3162,3223,3298,3380,3458,3532,3610,3695,3782,3867,3950,
+4032,4112,4187,4265,4347,4422,4475,4507,4538,4589,4650,4691,4695,4679,4679,4711,4757,4805,4883,5027,5219,
+5377,5432,5397,5342,5320,5330,5360,5419,5519,5632,5711,5739,5741,5735,5707,5645,5579,5557,5579,5602,5600,
+5598,5629,5680,5716,5730,5750,5788,5818,5815,5794,5786,5794,5795,5766,5715,5661,5616,5578,5556,5558,5559,
+5481,5250,4885,4520,4315,4326,4486,4689,4885,5100,5363,5652,5873,5929,5824,5700,5741,6008,6377,6656,6752,
+6722,6680,6692,6751,6823,6889,6945,6988,6999,6972,6932,6925,6964,7023,7084,7160,7272,7400,7506,7578,7645,
+7749,7909,8111,8304,8421,8427,8362,8293,8237,8163,8050,7927,7829,7753,7669,7554,7403,7223,7040,6894,6815,
+6799,6827,6895,7011,7171,7351,7523,7662,7758,7823,7883,7947,8003,8037,8066,8110,8159,8182,8158,8095,8025,
+7981,7970,7933,7762,7400,6914,6443,6069,5779,5559,5475,5614,5951,6318,6526,6520,6398,6318,6357,6478,6591,
+6641,6639,6615,6578,6519,6442,6361,6287,6223,6169,6133,6114,6096,6061,6003,5936,5871,5811,5748,5681,5619,
+5563,5506,5439,5364,5290,5222,5161,5107,5059,5011,4957,4903,4854,4804,4743,4675,4617,4573,4529,4475,4417,
+4374,4347,4321,4288,4248,4211,4181,4155,4125,4090,4055,4022,3988,3945,3888,3822,3762,3711,3665,3613,3557,
+3504,3464,3436,3413,3387,3357,3328,3300,3270,3233,3194,3155,3114,3061,2999,2944,2916,2918,2925,2902,2844,
+2786,2756,2746,2718,2661,2601,2567,2559,2550,2521,2478,2435,2398,2363,2324,2278,2231,2191,2165,2148,2128,
+2103,2076,2049,2025,2002,1981,1957,1926,1894,1878,1882,1891,1884,1857,1825,1803,1790,1784,1794,1824,1858,
+1864,1835,1793,1765,1745,1716,1682,1666,1670,1675,1667,1660,1668,1680,1681,1674,1677,1690,1700,1702,1703,
+1700,1689,1676,1673,1681,1684,1676,1676,1696,1718,1713,1679,1646,1639,1655,1659,1628,1572,1520,1494,1486,
+1475,1454,1436,1434,1436,1431,1415,1400,1388,1375,1358,1340,1323,1305,1291,1286,1287,1285,1278,1268,1260,
+1254,1252,1252,1251,1244,1230,1216,1207,1199,1191,1185,1187,1196,1199,1183,1149,1110,1082,1076,1084,1093,
+1090,1077,1059,1043,1027,1011,993,974,953,930,903,875,847,823,804,791,784,778,764,738,704,
+668,636,609,589,575,558,536,509,482,456,429,401,377,358,343,327,306,280,251,224,197,
+170,142,113,86,59,33,9,-13,-38,-65,-94,-123,-154,-188,-221,-252,-284,-319,-354,-388,-422,
+-457,-492,-523,-550,-576,-601,-623,-642,-664,-688,-712,-735,-757,-781,-808,-837,-865,-890,-909,-925,-944,
+-968,-992,-1015,-1036,-1057,-1073,-1086,-1104,-1131,-1162,-1188,-1205,-1217,-1232,-1250,-1273,-1298,-1319,-1334,-1346,-1361,
+-1380,-1402,-1421,-1434,-1441,-1448,-1458,-1472,-1483,-1489,-1494,-1503,-1516,-1530,-1544,-1558,-1572,-1585,-1598,-1612,-1628,
+-1643,-1656,-1667,-1674,-1675,-1675,-1676,-1676,-1673,-1666,-1661,-1662,-1666,-1669,-1668,-1667,-1665,-1662,-1656,-1647,-1638,
+-1632,-1627,-1621,-1614,-1606,-1595,-1582,-1569,-1561,-1558,-1553,-1541,-1523,-1504,-1487,-1470,-1454,-1440,-1429,-1423,-1417,
+-1409,-1402,-1398,-1394,-1390,-1384,-1381,-1380,-1376,-1369,-1361,-1355,-1352,-1353,-1356,-1361,-1364,-1363,-1364,-1369,-1374,
+-1377,-1378,-1381,-1385,-1389,-1393,-1399,-1405,-1408,-1409,-1409,-1407,-1404,-1407,-1418,-1427,-1427,-1421,-1417,-1414,-1408,
+-1401,-1400,-1402,-1397,-1390,-1390,-1399,-1402,-1394,-1385,-1384,-1382,-1374,-1368,-1367,-1362,-1350,-1337,-1331,-1324,-1311,
+-1297,-1285,-1273,-1255,-1235,-1221,-1207,-1187,-1165,-1146,-1126,-1101,-1072,-1046,-1020,-990,-961,-935,-908,-875,-839,
+-803,-763,-719,-679,-644,-600,-544,-490,-449,-409,-358,-305,-264,-227,-178,-128,-86,-43,11,59,79,
+80,66,-2,-129,-195,-29,376,827,1123,1248,1328,1462,1660,1882,2052,2056,1832,1477,1194,1102,1143,
+1185,1162,1097,1040,1020,1045,1094,1141,1186,1254,1353,1461,1555,1648,1754,1855,1927,1970,2008,2050,2081,
+2094,2099,2110,2128,2147,2158,2153,2120,2062,2000,1960,1952,1957,1939,1873,1773,1671,1586,1514,1448,1383,
+1320,1253,1180,1110,1048,991,925,842,737,606,455,298,150,15,-103,-200,-273,-325,-364,-395,-418,
+-436,-463,-503,-552,-592,-617,-640,-685,-763,-853,-931,-994,-1061,-1140,-1220,-1286,-1343,-1400,-1459,-1518,-1577,
+-1640,-1705,-1773,-1846,-1922,-1981,-2009,-2016,-2021,-2038,-2064,-2093,-2119,-2138,-2149,-2158,-2170,-2180,-2184,-2185,-2192,
+-2205,-2218,-2229,-2244,-2270,-2312,-2373,-2439,-2481,-2480,-2456,-2446,-2459,-2477,-2484,-2493,-2523,-2575,-2630,-2670,-2688,
+-2677,-2640,-2598,-2570,-2555,-2531,-2480,-2410,-2345,-2300,-2271,-2241,-2201,-2156,-2116,-2076,-2017,-1927,-1816,-1705,-1613,
+-1541,-1482,-1416,-1330,-1233,-1148,-1086,-1032,-964,-892,-840,-816,-801,-779,-755,-736,-716,-690,-665,-651,-631,
+-594,-561,-576,-652,-748,-812,-837,-843,-843,-834,-816,-800,-789,-774,-749,-724,-708,-691,-665,-632,-603,
+-577,-548,-516,-493,-485,-483,-478,-467,-453,-437,-418,-395,-371,-347,-321,-290,-252,-213,-180,-159,-143,
+-122,-97,-71,-46,-20,10,43,79,121,168,212,246,276,312,354,399,443,486,528,571,616,
+666,721,775,827,878,929,978,1023,1067,1112,1156,1199,1240,1282,1323,1360,1391,1420,1449,1476,1501,
+1527,1556,1586,1614,1643,1678,1715,1746,1766,1782,1802,1823,1838,1842,1842,1841,1840,1838,1836,1833,1831,
+1829,1826,1818,1806,1794,1784,1778,1770,1762,1757,1752,1743,1730,1717,1706,1696,1690,1687,1683,1672,1657,
+1653,1658,1662,1659,1655,1657,1660,1666,1680,1703,1724,1734,1737,1739,1734,1718,1700,1683,1679,1643,1599,
+1562,1543,1518,1463,1385,1315,1265,1225,1185,1146,1105,1057,1011,985,977,964,937,907,887,873,853,
+832,814,793,767,747,739,737,733,727,726,729,733,739,747,745,719,668,609,566,564,607,
+663,686,654,588,529,491,469,455,442,419,384,346,319,304,292,278,259,225,171,106,42,
+-17,-79,-144,-208,-276,-356,-444,-532,-614,-688,-742,-770,-789,-823,-875,-929,-976,-1024,-1077,-1131,-1183,
+-1233,-1276,-1305,-1334,-1379,-1436,-1485,-1518,-1544,-1566,-1574,-1569,-1569,-1586,-1609,-1621,-1618,-1605,-1593,-1593,-1608,
+-1619,-1603,-1562,-1523,-1493,-1450,-1387,-1344,-1367,-1445,-1517,-1531,-1487,-1426,-1391,-1398,-1422,-1431,-1431,-1468,-1572,
+-1713,-1829,-1892,-1919,-1937,-1957,-1980,-1994,-1977,-1930,-1895,-1919,-1983,-2009,-1955,-1866,-1810,-1797,-1793,-1796,-1855,
+-1995,-2168,-2294,-2362,-2443,-2596,-2783,-2905,-2927,-2928,-3006,-3161,-3311,-3399,-3451,-3519,-3613,-3703,-3770,-3819,-3860,
+-3898,-3937,-3975,-4006,-4026,-4044,-4069,-4101,-4130,-4148,-4155,-4160,-4173,-4194,-4212,-4221,-4226,-4235,-4246,-4250,-4256,
+-4275,-4296,-4297,-4283,-4276,-4277,-4266,-4243,-4232,-4238,-4229,-4195,-4169,-4169,-4160,-4123,-4110,-4162,-4223,-4192,-4083,
+-4028,-4109,-4257,-4347,-4345,-4299,-4247,-4194,-4155,-4149,-4163,-4161,-4145,-4162,-4241,-4363,-4488,-4600,-4700,-4790,-4870,
+-4941,-5006,-5065,-5121,-5185,-5260,-5333,-5391,-5439,-5494,-5561,-5635,-5707,-5773,-5831,-5883,-5939,-6007,-6084,-6160,-6229,
+-6295,-6362,-6428,-6489,-6542,-6593,-6646,-6698,-6750,-6801,-6852,-6905,-6956,-7003,-7043,-7073,-7101,-7138,-7194,-7265,-7339,
+-7413,-7493,-7584,-7683,-7779,-7867,-7946,-8008,-8043,-8042,-8010,-7972,-7970,-8026,-8122,-8218,-8303,-8407,-8549,-8694,-8790,
+-8831,-8859,-8904,-8954,-8988,-9012,-9039,-9064,-9076,-9075,-9076,-9081,-9087,-9094,-9111,-9140,-9176,-9212,-9240,-9251,-9244,
+-9234,-9233,-9238,-9234,-9215,-9178,-9123,-9048,-8965,-8888,-8818,-8746,-8682,-8653,-8671,-8707,-8716,-8676,-8600,-8515,-8435,
+-8358,-8271,-8164,-8044,-7929,-7832,-7755,-7690,-7628,-7563,-7489,-7401,-7303,-7197,-7083,-6959,-6831,-6710,-6611,-6535,-6474,
+-6414,-6344,-6263,-6170,-6063,-5939,-5808,-5685,-5571,-5449,-5313,-5177,-5059,-4953,-4847,-4740,-4641,-4549,-4451,-4339,-4202,
+-4030,-3829,-3646,-3524,-3448,-3349,-3187,-2999,-2847,-2738,-2627,-2487,-2330,-2187,-2068,-1974,-1898,-1840,-1806,-1809,-1839,
+-1847,-1770,-1602,-1395,-1204,-1042,-903,-801,-753,-738,-693,-550,-274,110,520,852,1054,1162,1247,1341,1430,
+1502,1576,1668,1768,1859,1942,2027,2112,2186,2248,2311,2381,2456,2529,2599,2664,2721,2770,2823,2887,2957,
+3025,3083,3136,3191,3255,3327,3401,3475,3549,3623,3699,3779,3865,3959,4054,4141,4215,4276,4328,4376,4423,
+4470,4519,4569,4617,4658,4696,4737,4776,4801,4816,4861,4970,5129,5265,5321,5298,5244,5197,5174,5191,5272,
+5409,5545,5622,5635,5620,5608,5599,5588,5594,5626,5656,5648,5605,5577,5596,5639,5665,5666,5673,5701,5733,
+5747,5751,5762,5779,5774,5731,5667,5616,5580,5533,5471,5430,5421,5367,5145,4729,4266,3973,3951,4135,4395,
+4671,4982,5340,5684,5888,5869,5686,5539,5619,5946,6352,6637,6733,6712,6680,6697,6762,6851,6940,7012,7057,
+7065,7032,6980,6947,6953,6986,7029,7085,7166,7260,7349,7434,7537,7671,7837,8028,8219,8365,8430,8427,8405,
+8386,8356,8304,8239,8167,8083,7985,7881,7750,7547,7264,6972,6761,6664,6649,6683,6766,6908,7098,7298,7469,
+7598,7704,7813,7921,7995,8026,8049,8102,8172,8212,8204,8172,8142,8110,8037,7867,7548,7074,6536,6074,5774,
+5613,5531,5531,5681,6003,6388,6645,6661,6495,6325,6295,6402,6541,6619,6622,6583,6530,6463,6385,6310,6249,
+6201,6165,6144,6137,6128,6099,6047,5985,5929,5876,5814,5743,5676,5621,5568,5505,5434,5363,5297,5231,5167,
+5109,5053,4991,4929,4877,4833,4786,4730,4674,4626,4580,4527,4472,4422,4382,4347,4311,4277,4245,4217,4189,
+4155,4114,4072,4037,4004,3961,3906,3848,3796,3747,3695,3637,3581,3535,3502,3480,3462,3442,3415,3386,3355,
+3320,3279,3240,3207,3171,3125,3075,3036,3011,2990,2955,2904,2848,2802,2773,2752,2720,2671,2616,2578,2566,
+2567,2554,2517,2465,2418,2385,2355,2318,2272,2229,2198,2173,2147,2119,2090,2062,2031,2002,1979,1959,1936,
+1911,1889,1873,1862,1856,1857,1857,1846,1820,1793,1784,1794,1806,1803,1787,1770,1755,1737,1713,1696,1697,
+1703,1696,1679,1672,1682,1692,1687,1677,1681,1698,1711,1712,1712,1714,1710,1698,1685,1673,1660,1650,1657,
+1684,1710,1704,1666,1628,1619,1634,1643,1617,1565,1517,1494,1487,1473,1451,1434,1430,1431,1424,1412,1401,
+1387,1366,1340,1317,1299,1282,1268,1262,1263,1264,1259,1248,1236,1230,1236,1247,1250,1234,1205,1180,1167,
+1159,1149,1141,1142,1153,1162,1158,1138,1104,1068,1047,1046,1055,1056,1042,1024,1011,1000,983,959,933,
+909,884,854,824,798,778,759,742,731,726,718,702,676,646,618,594,575,560,544,523,497,
+470,441,411,382,358,340,324,307,286,262,236,211,190,168,145,121,96,71,44,16,-10,
+-38,-69,-99,-127,-154,-185,-218,-253,-287,-319,-350,-379,-409,-443,-480,-516,-548,-576,-601,-624,-646,
+-667,-690,-711,-733,-755,-778,-802,-829,-856,-881,-899,-914,-932,-952,-973,-994,-1015,-1036,-1053,-1069,-1089,
+-1116,-1147,-1173,-1193,-1208,-1223,-1242,-1265,-1289,-1310,-1325,-1337,-1351,-1369,-1391,-1412,-1426,-1433,-1436,-1441,-1450,
+-1459,-1465,-1471,-1481,-1494,-1507,-1520,-1533,-1545,-1556,-1568,-1582,-1596,-1610,-1623,-1635,-1643,-1644,-1645,-1648,-1651,
+-1648,-1638,-1630,-1630,-1635,-1637,-1636,-1634,-1634,-1632,-1626,-1617,-1607,-1599,-1593,-1587,-1581,-1574,-1566,-1555,-1543,
+-1533,-1524,-1514,-1500,-1483,-1465,-1450,-1436,-1422,-1407,-1395,-1388,-1383,-1377,-1371,-1367,-1366,-1363,-1356,-1350,-1347,
+-1344,-1339,-1333,-1329,-1327,-1328,-1332,-1337,-1339,-1340,-1342,-1348,-1354,-1355,-1353,-1355,-1360,-1367,-1376,-1386,-1396,
+-1403,-1410,-1414,-1411,-1403,-1399,-1407,-1418,-1419,-1412,-1407,-1406,-1403,-1399,-1399,-1400,-1396,-1388,-1389,-1397,-1401,
+-1393,-1386,-1385,-1385,-1378,-1370,-1367,-1363,-1353,-1343,-1336,-1329,-1316,-1303,-1293,-1282,-1263,-1243,-1227,-1213,-1194,
+-1173,-1156,-1138,-1114,-1085,-1058,-1031,-1001,-972,-946,-920,-887,-851,-815,-776,-733,-691,-652,-607,-553,-503,
+-465,-427,-379,-326,-281,-237,-187,-138,-96,-50,2,38,48,52,49,-15,-153,-234,-80,321,771,
+1060,1162,1196,1281,1474,1767,2058,2157,1947,1547,1226,1149,1239,1317,1292,1200,1111,1064,1063,1096,1142,
+1194,1266,1362,1460,1546,1635,1739,1838,1900,1930,1962,2013,2070,2111,2136,2156,2171,2181,2188,2189,2174,
+2135,2080,2038,2024,2024,1998,1925,1824,1729,1654,1586,1512,1438,1369,1302,1234,1167,1104,1038,959,865,
+755,633,504,372,239,107,-17,-122,-199,-252,-289,-315,-338,-370,-417,-475,-535,-587,-630,-665,-706,
+-763,-834,-908,-981,-1062,-1147,-1218,-1262,-1291,-1327,-1376,-1431,-1486,-1542,-1607,-1682,-1768,-1854,-1924,-1968,-1996,
+-2023,-2053,-2079,-2101,-2120,-2136,-2147,-2154,-2165,-2177,-2184,-2186,-2190,-2199,-2211,-2225,-2243,-2269,-2302,-2347,-2398,
+-2436,-2448,-2448,-2461,-2491,-2513,-2515,-2512,-2527,-2562,-2604,-2642,-2666,-2667,-2641,-2602,-2567,-2537,-2497,-2440,-2381,
+-2331,-2294,-2261,-2225,-2186,-2151,-2122,-2087,-2028,-1934,-1817,-1702,-1604,-1527,-1462,-1395,-1313,-1226,-1152,-1102,-1056,
+-994,-921,-862,-826,-799,-767,-736,-712,-687,-652,-618,-594,-568,-526,-489,-505,-590,-704,-789,-825,-831,
+-827,-819,-808,-800,-796,-785,-764,-741,-726,-710,-685,-655,-630,-613,-592,-564,-539,-526,-524,-520,-510,
+-496,-479,-458,-432,-407,-383,-360,-332,-294,-252,-216,-190,-168,-145,-117,-89,-62,-35,-5,27,65,
+108,154,195,229,263,300,341,382,423,465,507,547,588,636,692,749,802,854,906,959,1010,
+1059,1108,1154,1196,1233,1269,1303,1334,1362,1391,1422,1453,1480,1504,1531,1561,1591,1618,1647,1676,1702,
+1722,1743,1771,1803,1830,1846,1851,1848,1839,1828,1820,1817,1815,1812,1807,1801,1792,1783,1772,1759,1746,
+1734,1727,1719,1707,1692,1678,1666,1658,1653,1648,1638,1621,1605,1599,1602,1604,1604,1609,1619,1631,1648,
+1674,1705,1727,1737,1744,1752,1749,1730,1705,1679,1669,1624,1573,1543,1537,1517,1449,1351,1273,1229,1199,
+1166,1130,1089,1037,986,960,958,951,924,891,872,861,842,818,797,778,755,735,728,730,729,
+723,720,724,731,743,760,774,773,752,716,679,664,692,753,809,816,766,686,608,550,514,
+488,459,423,392,376,368,361,353,342,314,259,184,110,48,-2,-45,-87,-141,-223,-329,-436,
+-528,-597,-641,-669,-698,-743,-796,-843,-881,-920,-967,-1020,-1074,-1125,-1166,-1197,-1233,-1291,-1364,-1429,-1476,
+-1514,-1542,-1547,-1531,-1518,-1529,-1555,-1574,-1576,-1571,-1567,-1569,-1579,-1590,-1588,-1566,-1529,-1480,-1420,-1364,-1341,
+-1368,-1429,-1485,-1505,-1481,-1425,-1374,-1359,-1378,-1402,-1423,-1468,-1562,-1687,-1800,-1875,-1912,-1922,-1921,-1928,-1946,
+-1951,-1933,-1927,-1968,-2029,-2038,-1971,-1880,-1828,-1815,-1809,-1813,-1872,-2005,-2166,-2296,-2395,-2512,-2673,-2833,-2923,
+-2943,-2969,-3064,-3204,-3320,-3388,-3451,-3544,-3649,-3729,-3777,-3810,-3843,-3878,-3914,-3949,-3975,-3991,-4008,-4035,-4068,
+-4098,-4118,-4131,-4141,-4154,-4169,-4181,-4186,-4191,-4205,-4218,-4218,-4207,-4204,-4216,-4229,-4236,-4237,-4229,-4206,-4181,
+-4177,-4186,-4176,-4146,-4129,-4130,-4110,-4068,-4068,-4145,-4212,-4157,-4011,-3929,-4004,-4167,-4291,-4332,-4320,-4284,-4242,
+-4226,-4249,-4270,-4242,-4188,-4181,-4249,-4351,-4441,-4521,-4607,-4697,-4781,-4860,-4937,-5003,-5056,-5114,-5188,-5265,-5327,
+-5375,-5430,-5502,-5581,-5653,-5714,-5767,-5818,-5875,-5946,-6021,-6092,-6156,-6220,-6290,-6359,-6422,-6481,-6538,-6592,-6640,
+-6686,-6734,-6788,-6840,-6884,-6921,-6957,-6993,-7030,-7073,-7128,-7191,-7260,-7336,-7425,-7524,-7622,-7715,-7799,-7872,-7924,
+-7946,-7931,-7886,-7839,-7836,-7901,-8010,-8120,-8225,-8357,-8520,-8661,-8732,-8753,-8783,-8842,-8899,-8927,-8944,-8970,-8996,
+-9007,-9008,-9012,-9021,-9028,-9036,-9056,-9086,-9118,-9144,-9164,-9171,-9163,-9154,-9156,-9161,-9154,-9132,-9099,-9053,-8988,
+-8912,-8843,-8785,-8727,-8675,-8653,-8665,-8683,-8673,-8625,-8556,-8480,-8403,-8321,-8224,-8108,-7983,-7870,-7781,-7712,-7651,
+-7591,-7531,-7462,-7378,-7281,-7176,-7062,-6936,-6804,-6678,-6571,-6487,-6427,-6379,-6327,-6259,-6175,-6074,-5956,-5826,-5699,
+-5579,-5450,-5306,-5168,-5066,-4994,-4919,-4820,-4707,-4600,-4500,-4391,-4250,-4068,-3864,-3689,-3579,-3505,-3395,-3224,-3042,
+-2907,-2812,-2705,-2563,-2410,-2273,-2152,-2037,-1930,-1837,-1768,-1741,-1758,-1784,-1761,-1661,-1501,-1316,-1128,-962,-859,
+-842,-878,-892,-810,-585,-219,219,616,881,1021,1115,1224,1346,1455,1548,1642,1740,1830,1910,1991,2073,
+2148,2214,2280,2352,2426,2495,2557,2619,2684,2752,2817,2876,2931,2987,3047,3106,3160,3213,3274,3344,3419,
+3490,3558,3629,3706,3793,3886,3984,4075,4146,4195,4237,4287,4351,4412,4458,4494,4540,4606,4680,4743,4778,
+4787,4791,4820,4891,4992,5094,5168,5196,5168,5095,5025,5025,5125,5285,5422,5488,5495,5481,5466,5456,5472,
+5533,5623,5685,5676,5620,5577,5578,5600,5608,5596,5587,5596,5618,5642,5667,5691,5700,5679,5627,5573,5542,
+5523,5478,5397,5331,5311,5264,5046,4606,4091,3737,3675,3851,4145,4492,4890,5310,5652,5797,5710,5513,5422,
+5586,5961,6356,6608,6696,6699,6696,6719,6773,6858,6955,7041,7100,7126,7114,7071,7024,7002,7010,7039,7082,
+7136,7193,7252,7328,7432,7555,7686,7830,7992,8150,8270,8346,8392,8420,8424,8408,8384,8344,8279,8206,8146,
+8069,7894,7587,7227,6939,6778,6710,6690,6716,6806,6951,7109,7247,7370,7513,7692,7870,7985,8026,8051,8116,
+8205,8260,8260,8240,8214,8139,7944,7600,7134,6615,6132,5770,5569,5499,5498,5554,5723,6047,6456,6775,6852,
+6697,6476,6357,6382,6469,6529,6537,6508,6458,6388,6306,6234,6181,6146,6126,6123,6132,6133,6107,6056,5999,
+5951,5907,5852,5784,5718,5662,5609,5549,5486,5427,5369,5304,5234,5170,5112,5050,4980,4915,4863,4820,4777,
+4730,4680,4629,4577,4527,4478,4429,4384,4350,4323,4295,4261,4223,4186,4146,4104,4064,4024,3978,3926,3875,
+3829,3781,3729,3677,3633,3596,3564,3536,3513,3486,3453,3417,3382,3345,3304,3265,3233,3204,3174,3153,3145,
+3130,3077,2991,2911,2866,2846,2822,2782,2734,2685,2636,2598,2585,2595,2599,2567,2502,2438,2397,2372,2345,
+2306,2266,2232,2198,2164,2133,2107,2081,2049,2015,1987,1966,1945,1922,1895,1868,1847,1848,1874,1899,1890,
+1845,1796,1774,1778,1787,1787,1784,1779,1766,1741,1720,1718,1731,1736,1719,1693,1683,1690,1696,1688,1677,
+1680,1696,1709,1715,1721,1732,1738,1727,1700,1667,1638,1625,1636,1666,1689,1684,1648,1606,1581,1576,1575,
+1562,1540,1520,1508,1497,1476,1451,1436,1432,1426,1409,1390,1374,1358,1336,1309,1285,1264,1246,1232,1227,
+1230,1235,1233,1225,1215,1216,1232,1251,1253,1225,1185,1157,1148,1142,1130,1119,1117,1121,1124,1124,1119,
+1101,1071,1041,1031,1034,1031,1013,990,975,964,944,913,879,852,827,801,776,760,748,732,710,
+689,676,669,659,641,617,593,572,555,541,526,507,484,456,426,395,369,348,328,309,291,
+274,254,230,205,182,161,139,117,96,75,51,25,-2,-32,-67,-102,-132,-157,-184,-217,-255,
+-291,-322,-348,-373,-400,-432,-470,-508,-545,-576,-603,-626,-649,-672,-693,-713,-733,-754,-776,-799,-824,
+-850,-875,-894,-910,-925,-942,-959,-977,-998,-1019,-1039,-1057,-1079,-1105,-1133,-1157,-1176,-1193,-1211,-1232,-1256,
+-1279,-1299,-1313,-1327,-1344,-1362,-1383,-1404,-1420,-1428,-1430,-1432,-1438,-1447,-1453,-1458,-1466,-1476,-1486,-1498,-1509,
+-1520,-1530,-1542,-1555,-1567,-1577,-1588,-1600,-1608,-1610,-1613,-1620,-1629,-1628,-1617,-1606,-1603,-1605,-1604,-1601,-1598,
+-1599,-1598,-1594,-1586,-1577,-1568,-1560,-1553,-1548,-1542,-1536,-1528,-1518,-1506,-1493,-1478,-1461,-1442,-1424,-1411,-1401,
+-1392,-1379,-1366,-1357,-1353,-1348,-1343,-1340,-1339,-1337,-1331,-1323,-1316,-1313,-1309,-1305,-1303,-1303,-1305,-1309,-1314,
+-1318,-1319,-1323,-1329,-1335,-1337,-1337,-1339,-1344,-1351,-1361,-1373,-1385,-1396,-1405,-1412,-1411,-1401,-1394,-1398,-1406,
+-1408,-1402,-1397,-1397,-1397,-1394,-1395,-1397,-1394,-1387,-1388,-1396,-1399,-1393,-1387,-1387,-1387,-1380,-1371,-1365,-1361,
+-1354,-1347,-1341,-1333,-1318,-1304,-1296,-1287,-1270,-1250,-1234,-1219,-1201,-1182,-1164,-1147,-1123,-1095,-1067,-1040,-1009,
+-981,-956,-929,-895,-858,-824,-788,-746,-701,-658,-614,-566,-521,-482,-442,-392,-341,-296,-250,-200,-154,
+-113,-68,-18,13,21,32,41,-13,-156,-264,-151,218,666,979,1096,1099,1115,1250,1543,1887,2052,
+1894,1539,1278,1267,1400,1478,1427,1306,1196,1129,1111,1135,1181,1232,1291,1365,1450,1538,1631,1731,1816,
+1862,1883,1919,1989,2072,2137,2175,2194,2204,2209,2215,2222,2221,2200,2163,2131,2119,2110,2072,1991,1891,
+1805,1735,1659,1571,1483,1408,1345,1283,1221,1159,1087,997,890,775,661,550,437,314,183,58,-42,
+-114,-166,-204,-230,-254,-293,-353,-425,-495,-558,-613,-656,-691,-730,-785,-853,-932,-1021,-1114,-1187,-1226,
+-1244,-1269,-1313,-1364,-1412,-1463,-1528,-1614,-1713,-1810,-1885,-1936,-1975,-2014,-2051,-2079,-2099,-2119,-2137,-2148,-2153,
+-2160,-2170,-2177,-2181,-2186,-2195,-2204,-2217,-2237,-2261,-2290,-2326,-2367,-2401,-2418,-2432,-2461,-2499,-2522,-2521,-2516,
+-2529,-2559,-2593,-2623,-2646,-2649,-2628,-2592,-2555,-2514,-2460,-2399,-2351,-2319,-2293,-2257,-2214,-2175,-2146,-2120,-2084,
+-2021,-1929,-1816,-1701,-1595,-1507,-1433,-1365,-1292,-1215,-1155,-1117,-1082,-1024,-947,-875,-824,-785,-747,-715,-692,
+-671,-639,-604,-575,-548,-512,-482,-497,-574,-684,-773,-814,-818,-808,-797,-791,-792,-796,-794,-780,-761,
+-746,-732,-711,-685,-664,-650,-634,-612,-589,-574,-568,-563,-552,-535,-514,-490,-464,-440,-419,-398,-371,
+-337,-299,-264,-232,-203,-173,-141,-110,-81,-54,-23,12,51,92,133,172,212,251,290,328,366,
+406,450,493,532,570,614,666,723,776,827,878,931,986,1040,1094,1146,1192,1230,1264,1294,1323,
+1349,1375,1402,1431,1455,1476,1499,1528,1560,1590,1617,1644,1671,1696,1721,1753,1789,1823,1846,1852,1844,
+1827,1808,1796,1792,1793,1792,1788,1782,1775,1764,1748,1729,1710,1695,1684,1671,1655,1640,1629,1622,1618,
+1613,1606,1592,1576,1566,1567,1573,1578,1587,1604,1625,1644,1665,1692,1718,1732,1738,1748,1757,1751,1728,
+1700,1669,1652,1606,1552,1528,1533,1510,1421,1302,1221,1192,1176,1149,1115,1079,1032,979,947,940,933,
+905,874,858,850,829,800,776,760,743,726,719,722,724,722,721,725,730,738,753,773,787,
+790,780,767,766,797,864,937,969,935,851,753,672,615,574,535,495,464,447,439,434,431,
+425,399,345,270,196,134,87,51,19,-27,-106,-209,-315,-403,-469,-519,-562,-610,-667,-722,-764,
+-793,-821,-858,-903,-956,-1010,-1057,-1095,-1141,-1214,-1303,-1381,-1435,-1476,-1508,-1520,-1509,-1493,-1497,-1517,-1535,
+-1541,-1542,-1543,-1545,-1551,-1561,-1570,-1568,-1542,-1485,-1408,-1341,-1312,-1324,-1358,-1393,-1419,-1419,-1387,-1343,-1327,
+-1352,-1394,-1433,-1484,-1566,-1673,-1774,-1848,-1888,-1895,-1881,-1872,-1882,-1901,-1921,-1955,-2012,-2061,-2054,-1992,-1923,
+-1881,-1853,-1826,-1828,-1898,-2030,-2173,-2294,-2406,-2542,-2697,-2829,-2908,-2956,-3026,-3139,-3256,-3333,-3382,-3451,-3556,
+-3664,-3734,-3768,-3790,-3817,-3852,-3890,-3922,-3942,-3952,-3969,-3996,-4026,-4048,-4065,-4080,-4096,-4110,-4126,-4143,-4159,
+-4176,-4199,-4219,-4214,-4186,-4161,-4163,-4186,-4206,-4206,-4182,-4146,-4122,-4124,-4133,-4122,-4096,-4086,-4089,-4070,-4037,
+-4052,-4126,-4167,-4086,-3938,-3870,-3945,-4084,-4190,-4240,-4257,-4251,-4242,-4271,-4337,-4369,-4316,-4236,-4227,-4302,-4385,
+-4427,-4457,-4517,-4601,-4686,-4771,-4860,-4937,-4993,-5047,-5119,-5199,-5263,-5314,-5373,-5450,-5529,-5595,-5650,-5700,-5753,
+-5814,-5883,-5956,-6022,-6081,-6144,-6215,-6287,-6352,-6413,-6471,-6525,-6571,-6617,-6668,-6721,-6768,-6803,-6837,-6876,-6920,
+-6964,-7007,-7054,-7106,-7172,-7258,-7359,-7464,-7560,-7649,-7732,-7799,-7836,-7838,-7810,-7761,-7715,-7709,-7768,-7877,-8001,
+-8132,-8292,-8467,-8599,-8651,-8662,-8699,-8770,-8829,-8852,-8863,-8887,-8911,-8918,-8918,-8928,-8942,-8950,-8958,-8981,-9013,
+-9040,-9060,-9076,-9082,-9075,-9067,-9070,-9075,-9065,-9038,-9004,-8962,-8904,-8838,-8781,-8738,-8698,-8661,-8642,-8640,-8634,
+-8604,-8554,-8497,-8436,-8365,-8279,-8173,-8048,-7918,-7806,-7727,-7668,-7613,-7556,-7498,-7435,-7357,-7265,-7161,-7041,-6906,
+-6766,-6635,-6525,-6439,-6382,-6346,-6310,-6255,-6178,-6083,-5973,-5852,-5730,-5608,-5473,-5319,-5173,-5074,-5019,-4964,-4871,
+-4746,-4626,-4526,-4428,-4302,-4131,-3937,-3769,-3657,-3568,-3442,-3263,-3090,-2975,-2896,-2790,-2640,-2482,-2348,-2229,-2100,
+-1964,-1840,-1748,-1697,-1689,-1704,-1709,-1676,-1591,-1453,-1272,-1088,-964,-933,-969,-1005,-977,-829,-528,-107,323,
+646,829,943,1067,1216,1361,1486,1602,1714,1809,1882,1947,2020,2100,2177,2249,2319,2390,2457,2517,2575,
+2639,2707,2771,2824,2868,2918,2980,3049,3112,3168,3229,3300,3375,3446,3513,3586,3666,3746,3826,3909,3993,
+4066,4120,4163,4216,4283,4348,4394,4424,4465,4534,4618,4683,4711,4716,4728,4758,4793,4832,4897,4998,5094,
+5112,5035,4940,4931,5033,5177,5277,5318,5333,5343,5334,5311,5321,5401,5527,5623,5643,5609,5575,5564,5560,
+5546,5521,5501,5493,5501,5523,5552,5570,5563,5529,5482,5441,5419,5406,5372,5310,5252,5220,5147,4907,4459,
+3943,3583,3508,3680,3996,4387,4816,5217,5488,5554,5452,5332,5370,5636,6030,6377,6574,6649,6680,6709,6741,
+6783,6851,6936,7012,7064,7095,7101,7074,7024,6981,6973,7001,7054,7114,7169,7221,7287,7371,7456,7530,7612,
+7726,7865,8004,8124,8224,8293,8321,8324,8326,8325,8306,8278,8264,8240,8127,7881,7563,7280,7082,6949,6861,
+6837,6889,6984,7062,7104,7149,7263,7458,7672,7823,7897,7962,8077,8215,8296,8288,8219,8112,7923,7595,7138,
+6644,6212,5895,5692,5574,5507,5468,5479,5608,5916,6361,6782,6996,6950,6753,6563,6458,6422,6413,6408,6394,
+6356,6290,6215,6152,6105,6070,6052,6060,6087,6103,6086,6043,5995,5956,5920,5870,5805,5739,5679,5623,5565,
+5512,5469,5425,5368,5299,5233,5174,5115,5047,4974,4909,4859,4819,4780,4732,4675,4621,4574,4527,4475,4428,
+4398,4380,4353,4310,4262,4223,4187,4147,4102,4055,4004,3952,3906,3864,3819,3770,3728,3696,3667,3634,3601,
+3570,3534,3488,3441,3404,3371,3333,3296,3263,3231,3200,3192,3209,3213,3159,3056,2971,2945,2945,2914,2844,
+2769,2714,2672,2638,2625,2641,2655,2626,2551,2468,2414,2386,2361,2327,2292,2259,2225,2187,2154,2129,2101,
+2068,2034,2009,1989,1966,1940,1913,1884,1862,1866,1902,1937,1926,1865,1800,1776,1790,1813,1825,1830,1826,
+1803,1765,1737,1737,1752,1754,1733,1705,1690,1689,1689,1684,1678,1680,1690,1701,1713,1729,1747,1757,1746,
+1712,1667,1627,1610,1618,1641,1657,1654,1630,1593,1555,1524,1509,1509,1517,1523,1519,1500,1473,1451,1442,
+1438,1424,1396,1362,1333,1310,1288,1267,1246,1225,1205,1192,1189,1195,1201,1203,1199,1193,1196,1215,1234,
+1231,1198,1158,1139,1139,1137,1123,1111,1106,1101,1092,1086,1091,1091,1072,1042,1022,1017,1010,986,957,
+937,923,901,865,828,800,778,757,740,729,723,708,680,650,628,618,610,598,580,560,542,
+527,515,502,486,465,440,412,386,365,346,325,304,286,269,250,223,193,164,138,115,94,
+77,62,46,28,7,-20,-57,-96,-131,-157,-182,-213,-251,-290,-322,-348,-372,-398,-429,-466,-505,
+-543,-576,-605,-629,-653,-676,-698,-718,-737,-756,-776,-797,-821,-847,-873,-894,-911,-926,-940,-954,-969,
+-989,-1011,-1031,-1050,-1071,-1095,-1118,-1139,-1158,-1175,-1195,-1218,-1243,-1266,-1284,-1299,-1316,-1337,-1358,-1377,-1395,
+-1411,-1421,-1424,-1427,-1435,-1444,-1451,-1454,-1458,-1465,-1474,-1483,-1492,-1501,-1510,-1521,-1534,-1542,-1548,-1554,-1564,
+-1572,-1574,-1577,-1588,-1601,-1604,-1595,-1583,-1578,-1577,-1574,-1570,-1567,-1567,-1565,-1561,-1555,-1548,-1539,-1529,-1522,
+-1516,-1511,-1506,-1499,-1490,-1478,-1464,-1446,-1426,-1404,-1385,-1372,-1364,-1358,-1349,-1337,-1328,-1324,-1320,-1316,-1313,
+-1312,-1310,-1305,-1297,-1290,-1284,-1279,-1276,-1276,-1279,-1282,-1286,-1292,-1299,-1304,-1307,-1312,-1317,-1323,-1327,-1332,
+-1337,-1342,-1351,-1362,-1374,-1384,-1393,-1399,-1400,-1394,-1387,-1388,-1393,-1394,-1389,-1386,-1387,-1388,-1388,-1389,-1390,
+-1388,-1384,-1385,-1391,-1394,-1391,-1387,-1387,-1386,-1379,-1370,-1363,-1357,-1351,-1347,-1343,-1335,-1319,-1304,-1296,-1288,
+-1273,-1256,-1241,-1226,-1209,-1190,-1173,-1154,-1129,-1101,-1075,-1048,-1019,-991,-966,-937,-901,-864,-831,-799,-759,
+-714,-670,-627,-583,-540,-498,-451,-399,-350,-308,-265,-217,-173,-136,-93,-42,-6,3,13,24,-22,
+-159,-282,-211,114,556,905,1059,1055,1014,1076,1316,1643,1833,1752,1521,1396,1478,1632,1677,1581,1434,
+1313,1234,1196,1200,1231,1267,1303,1358,1437,1532,1630,1721,1787,1821,1844,1891,1977,2075,2151,2193,2212,
+2223,2233,2247,2261,2266,2254,2231,2213,2207,2193,2145,2061,1968,1888,1814,1725,1620,1523,1448,1389,1330,
+1270,1208,1132,1036,924,811,706,604,495,372,245,131,47,-9,-55,-97,-133,-169,-221,-294,-374,
+-446,-509,-565,-611,-646,-682,-732,-797,-872,-957,-1049,-1127,-1174,-1198,-1226,-1272,-1325,-1374,-1423,-1490,-1581,
+-1686,-1784,-1857,-1909,-1952,-1996,-2036,-2064,-2084,-2104,-2125,-2138,-2144,-2149,-2155,-2161,-2167,-2175,-2185,-2194,-2205,
+-2222,-2245,-2273,-2307,-2346,-2376,-2391,-2403,-2429,-2463,-2486,-2491,-2498,-2522,-2554,-2581,-2602,-2615,-2612,-2588,-2554,
+-2521,-2479,-2420,-2356,-2312,-2294,-2280,-2251,-2211,-2174,-2145,-2114,-2068,-2000,-1914,-1813,-1703,-1592,-1489,-1405,-1333,
+-1264,-1198,-1151,-1127,-1102,-1045,-956,-867,-803,-763,-732,-706,-683,-659,-625,-588,-558,-535,-512,-493,-504,
+-564,-660,-752,-809,-824,-814,-797,-786,-787,-796,-802,-797,-785,-771,-759,-744,-724,-705,-689,-674,-656,
+-637,-623,-615,-608,-595,-575,-551,-525,-499,-477,-457,-434,-406,-374,-341,-310,-278,-243,-207,-170,-135,
+-102,-73,-42,-7,30,67,103,142,187,233,272,306,342,384,429,472,510,547,591,645,706,
+764,817,866,916,969,1022,1075,1126,1172,1210,1241,1269,1298,1325,1351,1376,1401,1424,1444,1465,1494,
+1531,1567,1598,1628,1658,1686,1711,1738,1772,1806,1829,1835,1825,1807,1787,1772,1766,1767,1766,1760,1751,
+1739,1724,1703,1680,1660,1646,1634,1620,1605,1596,1593,1593,1592,1587,1577,1563,1552,1552,1563,1575,1586,
+1603,1629,1655,1676,1693,1711,1723,1726,1728,1738,1743,1727,1699,1677,1652,1641,1597,1540,1519,1529,1500,
+1392,1257,1178,1164,1158,1127,1088,1058,1022,976,941,927,918,893,864,851,843,820,786,760,745,
+733,718,711,714,718,720,723,726,727,730,743,765,785,798,807,820,848,898,972,1047,1086,
+1065,992,897,811,747,699,654,606,559,524,508,508,517,518,493,438,366,297,237,187,148,
+114,70,2,-85,-171,-247,-316,-386,-456,-523,-586,-642,-686,-716,-738,-762,-796,-846,-910,-974,-1031,
+-1094,-1176,-1267,-1340,-1387,-1422,-1458,-1485,-1492,-1488,-1489,-1499,-1507,-1509,-1509,-1514,-1527,-1543,-1560,-1574,-1580,
+-1564,-1512,-1429,-1344,-1285,-1256,-1249,-1260,-1289,-1317,-1320,-1307,-1311,-1349,-1398,-1436,-1477,-1547,-1640,-1730,-1797,
+-1836,-1847,-1836,-1821,-1822,-1846,-1892,-1961,-2034,-2074,-2059,-2013,-1973,-1939,-1891,-1846,-1855,-1944,-2075,-2198,-2303,
+-2421,-2560,-2698,-2804,-2881,-2959,-3063,-3184,-3283,-3340,-3381,-3449,-3550,-3651,-3717,-3749,-3769,-3793,-3826,-3863,-3894,
+-3909,-3918,-3933,-3959,-3979,-3989,-3999,-4018,-4044,-4070,-4096,-4122,-4144,-4164,-4188,-4211,-4212,-4183,-4152,-4148,-4171,
+-4188,-4176,-4136,-4095,-4077,-4083,-4088,-4072,-4046,-4036,-4036,-4023,-4010,-4036,-4088,-4088,-4000,-3903,-3900,-3985,-4073,
+-4117,-4145,-4177,-4196,-4213,-4276,-4371,-4409,-4342,-4259,-4273,-4368,-4435,-4426,-4406,-4438,-4514,-4596,-4683,-4780,-4868,
+-4930,-4982,-5053,-5134,-5199,-5252,-5316,-5395,-5471,-5529,-5579,-5631,-5688,-5750,-5818,-5888,-5952,-6012,-6073,-6142,-6212,
+-6276,-6336,-6394,-6448,-6497,-6545,-6597,-6647,-6688,-6722,-6761,-6807,-6855,-6897,-6934,-6972,-7020,-7088,-7182,-7292,-7397,
+-7488,-7575,-7662,-7729,-7748,-7722,-7674,-7625,-7589,-7588,-7646,-7756,-7893,-8045,-8217,-8389,-8508,-8551,-8565,-8612,-8691,
+-8749,-8769,-8780,-8805,-8826,-8828,-8827,-8840,-8857,-8863,-8869,-8892,-8925,-8950,-8965,-8979,-8986,-8982,-8975,-8979,-8985,
+-8972,-8939,-8902,-8863,-8812,-8752,-8700,-8664,-8633,-8605,-8586,-8575,-8553,-8514,-8466,-8419,-8367,-8299,-8212,-8107,-7986,
+-7859,-7754,-7684,-7635,-7585,-7527,-7466,-7403,-7330,-7246,-7145,-7018,-6869,-6717,-6585,-6481,-6403,-6352,-6325,-6303,-6260,
+-6188,-6095,-5991,-5880,-5765,-5649,-5516,-5359,-5205,-5094,-5033,-4979,-4887,-4761,-4638,-4542,-4459,-4355,-4208,-4028,-3859,
+-3732,-3625,-3484,-3302,-3134,-3031,-2965,-2864,-2707,-2538,-2401,-2284,-2147,-1988,-1840,-1734,-1673,-1647,-1643,-1654,-1666,
+-1652,-1577,-1431,-1249,-1099,-1026,-1022,-1048,-1055,-980,-762,-399,17,367,599,761,919,1091,1254,1402,1549,
+1689,1798,1862,1904,1958,2034,2115,2188,2253,2320,2389,2455,2513,2569,2629,2690,2745,2791,2839,2898,2968,
+3040,3110,3181,3255,3327,3395,3467,3547,3632,3709,3775,3841,3915,3993,4060,4115,4167,4225,4284,4333,4370,
+4412,4476,4553,4612,4637,4647,4673,4709,4721,4711,4737,4844,4979,5036,4980,4899,4901,4992,5086,5126,5142,
+5184,5237,5246,5207,5185,5239,5354,5459,5508,5515,5512,5507,5491,5463,5435,5416,5406,5406,5419,5436,5438,
+5418,5385,5349,5313,5283,5265,5254,5235,5203,5146,5010,4720,4274,3803,3494,3451,3642,3970,4356,4739,5048,
+5219,5250,5218,5247,5429,5754,6116,6392,6541,6613,6667,6719,6760,6802,6863,6931,6981,7010,7032,7050,7044,
+7006,6961,6943,6970,7033,7106,7171,7227,7285,7346,7392,7420,7457,7528,7629,7738,7851,7967,8064,8118,8140,
+8166,8204,8231,8238,8243,8241,8189,8051,7853,7638,7423,7209,7038,6973,7024,7112,7136,7071,6987,6982,7087,
+7248,7389,7495,7622,7810,8013,8132,8112,7971,7750,7453,7072,6651,6284,6048,5942,5893,5825,5704,5545,5411,
+5403,5616,6052,6572,6972,7122,7043,6849,6644,6483,6384,6338,6306,6250,6172,6102,6056,6019,5978,5952,5963,
+6004,6039,6043,6021,5994,5970,5940,5894,5832,5764,5698,5637,5582,5537,5504,5472,5428,5367,5299,5233,5173,
+5113,5048,4978,4915,4869,4832,4788,4731,4675,4629,4585,4533,4483,4453,4434,4405,4357,4306,4265,4229,4188,
+4141,4092,4040,3988,3943,3905,3864,3820,3781,3751,3720,3684,3652,3623,3583,3527,3473,3435,3407,3376,3343,
+3311,3269,3218,3190,3207,3233,3208,3130,3064,3051,3055,3014,2921,2829,2770,2733,2699,2680,2688,2701,2676,
+2603,2516,2452,2414,2381,2342,2305,2274,2245,2214,2183,2152,2117,2080,2050,2033,2017,1994,1968,1944,1917,
+1889,1880,1905,1939,1932,1873,1809,1789,1814,1847,1867,1874,1867,1837,1791,1755,1745,1749,1747,1732,1712,
+1694,1682,1677,1678,1681,1684,1687,1695,1711,1732,1750,1756,1744,1714,1670,1628,1605,1603,1610,1616,1617,
+1611,1591,1553,1510,1485,1487,1505,1514,1502,1475,1450,1437,1433,1427,1409,1377,1338,1302,1273,1253,1237,
+1221,1201,1181,1167,1163,1166,1171,1176,1177,1171,1169,1177,1187,1178,1147,1117,1110,1119,1119,1106,1093,
+1089,1080,1062,1049,1055,1067,1059,1031,1004,992,983,962,932,907,888,866,832,795,765,744,726,
+710,697,685,667,639,606,580,566,558,550,538,521,504,492,483,473,459,441,420,399,380,
+363,345,326,305,285,264,238,205,172,142,118,97,77,62,52,43,32,15,-9,-44,-84,
+-120,-150,-176,-207,-244,-283,-317,-346,-372,-401,-433,-469,-505,-541,-575,-605,-631,-656,-680,-704,-727,
+-747,-765,-781,-799,-821,-847,-872,-893,-910,-926,-940,-953,-969,-987,-1008,-1028,-1047,-1067,-1088,-1108,-1126,
+-1143,-1160,-1180,-1204,-1230,-1252,-1268,-1282,-1303,-1330,-1353,-1370,-1383,-1397,-1407,-1413,-1420,-1430,-1441,-1447,-1450,
+-1453,-1460,-1468,-1477,-1483,-1488,-1495,-1507,-1518,-1523,-1524,-1527,-1535,-1540,-1541,-1543,-1553,-1566,-1570,-1564,-1555,
+-1551,-1550,-1548,-1545,-1543,-1541,-1536,-1530,-1524,-1517,-1508,-1498,-1490,-1485,-1481,-1477,-1469,-1459,-1447,-1432,-1414,
+-1393,-1372,-1351,-1336,-1328,-1322,-1315,-1306,-1298,-1293,-1291,-1287,-1283,-1282,-1280,-1277,-1271,-1264,-1258,-1252,-1249,
+-1251,-1256,-1261,-1265,-1271,-1281,-1288,-1291,-1293,-1298,-1306,-1314,-1321,-1327,-1333,-1341,-1353,-1364,-1372,-1376,-1379,
+-1381,-1381,-1379,-1379,-1382,-1382,-1378,-1375,-1375,-1378,-1379,-1381,-1382,-1382,-1379,-1379,-1382,-1386,-1385,-1384,-1383,
+-1381,-1375,-1368,-1363,-1357,-1350,-1345,-1342,-1334,-1320,-1306,-1296,-1285,-1272,-1257,-1245,-1231,-1214,-1196,-1180,-1160,
+-1133,-1105,-1080,-1055,-1028,-1000,-974,-944,-906,-869,-837,-805,-766,-723,-681,-640,-596,-551,-507,-459,-407,
+-360,-322,-281,-233,-188,-152,-113,-62,-21,-7,-2,0,-43,-164,-285,-244,40,466,841,1033,1043,
+977,989,1173,1461,1663,1672,1588,1600,1746,1881,1870,1727,1558,1426,1330,1268,1247,1260,1284,1316,1372,
+1456,1555,1648,1724,1776,1806,1835,1887,1970,2062,2138,2189,2220,2244,2268,2292,2311,2314,2299,2277,2265,
+2263,2252,2206,2127,2039,1959,1876,1775,1663,1567,1495,1437,1376,1312,1245,1165,1067,962,861,767,666,
+553,430,312,216,153,114,79,37,-13,-76,-158,-255,-343,-406,-451,-493,-535,-575,-617,-670,-733,
+-801,-875,-959,-1039,-1100,-1142,-1185,-1243,-1307,-1366,-1423,-1491,-1579,-1675,-1763,-1830,-1881,-1928,-1975,-2015,-2044,
+-2064,-2084,-2104,-2119,-2129,-2137,-2143,-2146,-2151,-2161,-2173,-2183,-2193,-2208,-2229,-2255,-2287,-2325,-2353,-2361,-2360,
+-2369,-2391,-2413,-2433,-2461,-2499,-2532,-2551,-2564,-2572,-2565,-2538,-2503,-2472,-2436,-2381,-2319,-2277,-2264,-2262,-2245,
+-2214,-2181,-2150,-2111,-2053,-1979,-1895,-1802,-1698,-1584,-1474,-1381,-1307,-1242,-1184,-1148,-1135,-1119,-1061,-963,-860,
+-789,-754,-737,-718,-690,-651,-602,-553,-518,-501,-492,-487,-496,-539,-623,-726,-809,-846,-841,-819,-803,
+-798,-803,-810,-814,-810,-800,-789,-778,-765,-748,-729,-711,-694,-678,-665,-657,-649,-636,-617,-593,-565,
+-538,-514,-492,-467,-435,-403,-373,-346,-317,-284,-247,-208,-167,-129,-96,-65,-32,3,36,70,112,
+161,209,248,280,316,359,403,442,477,516,564,625,694,761,819,868,915,963,1012,1058,1101,
+1140,1172,1197,1223,1253,1287,1317,1344,1371,1398,1421,1444,1475,1515,1555,1588,1617,1645,1671,1692,1715,
+1746,1778,1798,1802,1793,1780,1765,1750,1739,1733,1727,1717,1701,1685,1668,1647,1626,1611,1604,1596,1586,
+1579,1580,1587,1592,1590,1583,1572,1559,1552,1558,1573,1590,1605,1626,1652,1675,1689,1701,1711,1712,1706,
+1706,1715,1712,1688,1661,1652,1641,1644,1598,1532,1505,1514,1483,1368,1231,1157,1149,1140,1096,1045,1017,
+997,966,936,922,914,892,867,851,840,817,783,756,740,727,713,706,708,713,717,721,722,
+720,721,734,759,781,797,816,851,906,978,1058,1129,1165,1153,1096,1017,939,877,831,787,730,
+662,601,570,576,603,616,592,536,467,403,345,291,244,206,163,105,36,-28,-94,-171,-264,
+-357,-435,-497,-551,-600,-642,-670,-687,-708,-751,-824,-913,-1000,-1082,-1166,-1243,-1297,-1326,-1351,-1386,-1424,
+-1452,-1463,-1467,-1469,-1467,-1461,-1460,-1476,-1513,-1557,-1589,-1600,-1599,-1585,-1544,-1465,-1361,-1262,-1186,-1142,-1137,
+-1174,-1228,-1265,-1283,-1310,-1356,-1399,-1419,-1438,-1490,-1574,-1660,-1724,-1760,-1774,-1774,-1771,-1778,-1806,-1863,-1945,
+-2025,-2065,-2056,-2031,-2014,-1987,-1935,-1893,-1921,-2021,-2140,-2237,-2333,-2458,-2597,-2711,-2788,-2858,-2949,-3061,-3174,
+-3262,-3323,-3375,-3444,-3535,-3626,-3693,-3733,-3756,-3775,-3800,-3831,-3860,-3877,-3888,-3905,-3927,-3940,-3943,-3953,-3982,
+-4021,-4059,-4093,-4122,-4140,-4151,-4169,-4195,-4207,-4189,-4157,-4142,-4147,-4145,-4117,-4074,-4043,-4036,-4043,-4040,-4019,
+-3993,-3976,-3965,-3956,-3963,-4001,-4032,-4004,-3935,-3918,-3992,-4083,-4105,-4078,-4081,-4125,-4158,-4181,-4250,-4353,-4391,
+-4323,-4256,-4302,-4418,-4473,-4428,-4372,-4383,-4446,-4518,-4600,-4701,-4797,-4863,-4917,-4987,-5067,-5131,-5185,-5251,-5331,
+-5403,-5456,-5503,-5559,-5620,-5682,-5748,-5818,-5885,-5946,-6006,-6071,-6136,-6197,-6257,-6316,-6373,-6423,-6472,-6520,-6565,
+-6606,-6647,-6694,-6743,-6784,-6817,-6849,-6888,-6940,-7012,-7110,-7221,-7320,-7404,-7491,-7584,-7653,-7659,-7608,-7546,-7505,
+-7490,-7506,-7568,-7681,-7824,-7979,-8141,-8296,-8404,-8449,-8473,-8528,-8607,-8664,-8685,-8701,-8730,-8752,-8753,-8752,-8767,
+-8784,-8787,-8788,-8807,-8837,-8857,-8868,-8880,-8890,-8888,-8880,-8881,-8883,-8866,-8830,-8794,-8760,-8714,-8654,-8596,-8554,
+-8522,-8496,-8479,-8467,-8447,-8411,-8370,-8329,-8279,-8209,-8124,-8030,-7925,-7815,-7722,-7661,-7616,-7566,-7503,-7435,-7366,
+-7295,-7216,-7119,-6989,-6827,-6664,-6534,-6443,-6378,-6336,-6316,-6306,-6274,-6205,-6110,-6006,-5901,-5796,-5689,-5565,-5414,
+-5254,-5125,-5041,-4972,-4881,-4767,-4657,-4569,-4492,-4399,-4267,-4098,-3927,-3790,-3676,-3538,-3358,-3186,-3077,-3014,-2921,
+-2763,-2585,-2442,-2325,-2185,-2008,-1838,-1722,-1662,-1633,-1619,-1624,-1652,-1675,-1648,-1547,-1393,-1237,-1121,-1059,-1047,
+-1054,-1020,-880,-617,-286,31,303,547,780,989,1162,1322,1494,1666,1794,1855,1880,1913,1973,2043,2105,
+2159,2217,2284,2353,2413,2468,2528,2597,2669,2729,2778,2827,2887,2961,3042,3121,3193,3261,3329,3405,3490,
+3575,3649,3714,3779,3851,3930,4009,4078,4133,4179,4226,4276,4327,4377,4435,4502,4558,4589,4611,4651,4696,
+4702,4664,4653,4729,4854,4923,4902,4864,4891,4960,4994,4979,4988,5066,5163,5193,5143,5087,5093,5159,5237,
+5296,5337,5370,5386,5378,5357,5341,5336,5337,5339,5344,5344,5329,5302,5275,5248,5214,5178,5162,5178,5199,
+5177,5076,4866,4533,4113,3720,3497,3513,3726,4041,4370,4653,4851,4963,5037,5144,5333,5604,5913,6195,6401,
+6528,6610,6675,6727,6768,6817,6883,6946,6979,6990,7008,7038,7055,7040,7006,6986,7001,7050,7113,7173,7226,
+7276,7320,7345,7355,7379,7432,7498,7562,7635,7736,7845,7925,7971,8016,8075,8123,8141,8136,8127,8110,8075,
+8011,7892,7683,7397,7135,7020,7071,7175,7184,7047,6838,6677,6628,6674,6762,6876,7042,7269,7502,7645,7632,
+7471,7214,6914,6615,6361,6203,6164,6207,6249,6209,6053,5799,5516,5322,5355,5680,6211,6748,7102,7206,7105,
+6899,6683,6523,6421,6330,6210,6082,5994,5955,5926,5885,5854,5865,5908,5949,5968,5975,5980,5979,5965,5930,
+5877,5812,5745,5684,5631,5585,5545,5509,5472,5423,5358,5286,5221,5171,5123,5060,4989,4930,4889,4849,4797,
+4743,4701,4662,4613,4559,4516,4484,4447,4399,4351,4310,4269,4221,4174,4130,4081,4029,3982,3946,3910,3870,
+3830,3792,3752,3711,3679,3655,3619,3566,3515,3480,3454,3424,3395,3368,3322,3249,3187,3178,3206,3209,3162,
+3113,3102,3103,3063,2976,2890,2835,2797,2756,2722,2712,2713,2693,2637,2565,2504,2458,2413,2362,2316,2283,
+2261,2240,2213,2178,2135,2094,2066,2053,2039,2017,1994,1976,1951,1909,1874,1877,1906,1914,1876,1824,1807,
+1830,1862,1879,1882,1873,1849,1812,1778,1757,1745,1736,1728,1718,1700,1677,1665,1670,1681,1686,1685,1692,
+1710,1729,1738,1738,1729,1708,1674,1637,1609,1593,1583,1576,1580,1588,1584,1554,1512,1485,1483,1488,1479,
+1452,1425,1411,1408,1403,1390,1370,1345,1316,1287,1262,1244,1231,1215,1194,1173,1158,1149,1145,1146,1152,
+1157,1152,1141,1133,1130,1118,1093,1072,1071,1081,1082,1070,1061,1058,1050,1030,1014,1018,1034,1033,1006,
+973,954,947,936,913,885,862,839,809,773,739,713,694,676,656,634,612,588,561,535,516,
+506,500,491,476,460,449,444,438,427,411,396,382,369,354,337,321,303,281,252,218,183,
+153,132,114,96,78,62,53,48,39,21,-5,-37,-71,-105,-137,-167,-199,-235,-273,-309,-341,
+-370,-401,-436,-472,-505,-536,-568,-599,-628,-655,-682,-709,-736,-760,-779,-794,-808,-827,-849,-871,-889,
+-906,-922,-937,-951,-967,-987,-1009,-1029,-1047,-1066,-1086,-1105,-1121,-1137,-1152,-1170,-1194,-1219,-1240,-1252,-1264,
+-1287,-1317,-1344,-1360,-1370,-1379,-1388,-1395,-1404,-1416,-1427,-1433,-1437,-1442,-1452,-1463,-1472,-1476,-1479,-1484,-1494,
+-1504,-1508,-1508,-1511,-1516,-1519,-1516,-1514,-1521,-1530,-1532,-1526,-1521,-1520,-1521,-1521,-1520,-1518,-1515,-1508,-1500,
+-1492,-1485,-1476,-1466,-1457,-1452,-1450,-1448,-1440,-1427,-1411,-1394,-1376,-1357,-1339,-1322,-1307,-1296,-1287,-1281,-1273,
+-1267,-1262,-1259,-1255,-1251,-1249,-1248,-1247,-1243,-1237,-1230,-1225,-1224,-1229,-1236,-1242,-1245,-1251,-1261,-1269,-1271,
+-1272,-1277,-1285,-1293,-1300,-1307,-1317,-1329,-1343,-1356,-1362,-1361,-1359,-1362,-1367,-1370,-1371,-1372,-1373,-1371,-1367,
+-1366,-1367,-1369,-1372,-1374,-1375,-1375,-1374,-1375,-1378,-1381,-1382,-1381,-1376,-1371,-1366,-1363,-1358,-1351,-1344,-1339,
+-1330,-1319,-1306,-1295,-1283,-1269,-1258,-1247,-1234,-1216,-1199,-1183,-1163,-1135,-1107,-1083,-1061,-1035,-1007,-979,-947,
+-911,-875,-843,-807,-766,-725,-688,-647,-600,-554,-514,-472,-422,-375,-336,-296,-247,-198,-162,-127,-79,
+-35,-15,-11,-14,-53,-160,-276,-261,-22,377,763,988,1024,960,950,1095,1357,1588,1694,1734,1823,
+1964,2043,1975,1799,1608,1454,1339,1267,1245,1264,1302,1354,1430,1524,1617,1696,1758,1804,1837,1868,1912,
+1973,2045,2117,2184,2238,2280,2312,2341,2360,2359,2334,2302,2283,2284,2284,2254,2185,2097,2006,1914,1811,
+1705,1616,1546,1483,1416,1347,1274,1190,1095,1001,916,831,729,614,499,399,320,267,236,212,176,
+116,23,-99,-228,-326,-374,-392,-413,-448,-492,-539,-593,-654,-719,-788,-866,-949,-1022,-1083,-1143,-1214,
+-1291,-1364,-1432,-1503,-1582,-1663,-1738,-1801,-1854,-1905,-1952,-1993,-2025,-2049,-2070,-2087,-2102,-2115,-2128,-2136,-2138,
+-2142,-2150,-2162,-2172,-2184,-2202,-2221,-2240,-2265,-2297,-2323,-2326,-2313,-2304,-2313,-2338,-2377,-2425,-2470,-2496,-2506,
+-2515,-2527,-2526,-2498,-2457,-2424,-2394,-2352,-2302,-2266,-2256,-2256,-2245,-2219,-2187,-2153,-2109,-2047,-1967,-1879,-1785,
+-1681,-1567,-1455,-1361,-1288,-1227,-1177,-1149,-1143,-1130,-1076,-979,-876,-805,-776,-765,-748,-710,-651,-582,-517,
+-473,-457,-461,-469,-478,-507,-583,-697,-804,-862,-866,-847,-832,-826,-823,-824,-830,-834,-829,-819,-810,
+-802,-789,-770,-750,-731,-714,-699,-688,-678,-668,-653,-632,-604,-573,-545,-520,-492,-461,-429,-402,-378,
+-352,-324,-292,-255,-212,-169,-132,-99,-66,-30,4,39,81,132,180,219,253,293,339,381,416,
+448,488,541,605,677,748,809,858,905,955,1003,1044,1079,1110,1138,1161,1186,1220,1259,1294,1324,
+1353,1383,1410,1437,1470,1511,1550,1578,1599,1619,1639,1659,1682,1713,1743,1757,1753,1743,1736,1730,1717,
+1703,1692,1682,1670,1653,1638,1624,1610,1596,1589,1585,1581,1574,1573,1581,1592,1596,1591,1583,1573,1563,
+1559,1566,1582,1600,1617,1637,1655,1668,1675,1684,1691,1688,1680,1682,1691,1685,1659,1640,1646,1644,1642,
+1582,1500,1461,1465,1437,1334,1210,1145,1135,1116,1059,1000,974,966,950,929,918,912,896,873,854,
+839,815,785,761,744,729,715,709,712,716,717,718,717,715,717,731,755,777,795,821,871,
+945,1030,1113,1180,1217,1214,1173,1108,1038,980,939,900,843,762,682,638,647,687,710,688,630,
+563,503,444,385,333,292,251,200,143,89,29,-53,-159,-262,-340,-397,-448,-505,-563,-604,-624,
+-636,-670,-745,-850,-960,-1056,-1133,-1191,-1227,-1246,-1263,-1291,-1327,-1360,-1383,-1393,-1394,-1388,-1385,-1395,-1432,
+-1499,-1571,-1616,-1623,-1610,-1594,-1561,-1486,-1367,-1237,-1127,-1061,-1054,-1103,-1178,-1239,-1275,-1309,-1352,-1387,-1396,
+-1401,-1435,-1506,-1588,-1650,-1681,-1689,-1693,-1708,-1738,-1778,-1833,-1909,-1989,-2041,-2053,-2050,-2046,-2027,-1990,-1977,
+-2029,-2127,-2215,-2282,-2373,-2506,-2637,-2721,-2771,-2835,-2928,-3031,-3124,-3206,-3283,-3358,-3435,-3519,-3604,-3673,-3718,
+-3742,-3755,-3770,-3793,-3820,-3842,-3860,-3880,-3900,-3912,-3919,-3938,-3974,-4017,-4056,-4090,-4121,-4145,-4164,-4191,-4228,
+-4251,-4236,-4190,-4141,-4101,-4061,-4019,-3988,-3978,-3983,-3986,-3976,-3959,-3940,-3917,-3889,-3873,-3898,-3953,-3981,-3946,
+-3906,-3947,-4063,-4137,-4103,-4034,-4036,-4097,-4136,-4147,-4203,-4301,-4340,-4281,-4232,-4296,-4421,-4472,-4421,-4361,-4361,
+-4403,-4452,-4522,-4623,-4724,-4793,-4849,-4921,-5000,-5061,-5113,-5180,-5260,-5329,-5380,-5429,-5488,-5551,-5610,-5675,-5746,
+-5816,-5878,-5937,-5999,-6062,-6123,-6184,-6246,-6303,-6351,-6394,-6437,-6482,-6529,-6578,-6629,-6672,-6701,-6726,-6760,-6807,
+-6866,-6942,-7040,-7149,-7244,-7323,-7405,-7498,-7563,-7560,-7501,-7444,-7427,-7442,-7477,-7543,-7653,-7788,-7927,-8066,-8201,
+-8304,-8358,-8390,-8444,-8518,-8575,-8601,-8623,-8655,-8681,-8685,-8688,-8705,-8722,-8722,-8718,-8733,-8757,-8771,-8777,-8788,
+-8800,-8797,-8783,-8775,-8768,-8747,-8711,-8677,-8648,-8604,-8540,-8474,-8424,-8389,-8363,-8348,-8342,-8330,-8305,-8273,-8236,
+-8184,-8113,-8034,-7955,-7871,-7781,-7702,-7646,-7601,-7546,-7477,-7403,-7330,-7255,-7178,-7085,-6957,-6793,-6626,-6499,-6421,
+-6370,-6335,-6320,-6316,-6291,-6222,-6121,-6015,-5917,-5823,-5724,-5605,-5459,-5300,-5159,-5053,-4966,-4878,-4783,-4694,-4613,
+-4529,-4427,-4292,-4128,-3966,-3838,-3739,-3617,-3443,-3259,-3131,-3059,-2970,-2816,-2633,-2485,-2369,-2229,-2043,-1858,-1735,
+-1680,-1657,-1639,-1634,-1648,-1666,-1652,-1590,-1485,-1355,-1221,-1111,-1045,-1017,-984,-902,-762,-581,-360,-85,240,
+566,833,1038,1229,1443,1654,1807,1881,1908,1933,1973,2017,2057,2096,2142,2195,2253,2309,2368,2434,2513,
+2595,2664,2714,2757,2814,2889,2973,3050,3118,3186,3263,3345,3424,3496,3564,3636,3713,3789,3865,3944,4024,
+4088,4130,4161,4204,4258,4313,4366,4423,4481,4528,4570,4624,4680,4693,4649,4610,4644,4736,4810,4833,4851,
+4899,4937,4914,4865,4876,4973,5081,5113,5064,5001,4980,5004,5050,5103,5160,5211,5241,5248,5244,5244,5252,
+5264,5272,5273,5260,5232,5198,5174,5158,5138,5116,5115,5144,5164,5116,4967,4721,4402,4056,3769,3635,3696,
+3905,4170,4412,4594,4723,4845,5016,5262,5553,5834,6070,6261,6418,6546,6643,6704,6738,6768,6819,6890,6953,
+6983,6994,7013,7046,7072,7070,7050,7032,7035,7062,7104,7150,7199,7248,7288,7308,7320,7351,7404,7456,7489,
+7527,7602,7704,7793,7851,7900,7956,8000,8013,7995,7970,7961,7982,8016,7995,7837,7539,7221,7044,7053,7134,
+7119,6931,6633,6354,6185,6139,6187,6301,6470,6679,6881,7015,7032,6930,6753,6570,6437,6378,6388,6449,6526,
+6576,6553,6423,6175,5838,5511,5350,5477,5882,6414,6882,7159,7218,7110,6931,6766,6631,6484,6296,6106,5978,
+5920,5884,5842,5810,5809,5826,5839,5849,5873,5908,5937,5949,5941,5914,5867,5809,5753,5702,5648,5587,5528,
+5480,5439,5387,5321,5259,5218,5186,5138,5068,4999,4948,4905,4857,4808,4771,4740,4699,4644,4589,4539,4490,
+4442,4400,4360,4312,4257,4209,4170,4125,4070,4020,3982,3949,3910,3870,3829,3783,3736,3700,3677,3649,3609,
+3570,3543,3517,3482,3449,3426,3385,3305,3218,3176,3179,3178,3143,3100,3084,3081,3051,2989,2925,2880,2843,
+2798,2754,2724,2706,2682,2642,2591,2542,2497,2449,2395,2342,2305,2285,2270,2246,2209,2162,2118,2090,2073,
+2056,2032,2014,2004,1981,1931,1877,1861,1888,1912,1893,1851,1830,1845,1871,1884,1882,1873,1860,1841,1819,
+1795,1769,1748,1736,1727,1705,1675,1656,1662,1677,1682,1680,1687,1703,1716,1717,1714,1711,1702,1679,1649,
+1622,1598,1575,1558,1556,1563,1558,1530,1494,1473,1468,1457,1429,1396,1379,1381,1382,1370,1347,1327,1313,
+1299,1282,1264,1247,1229,1208,1184,1163,1147,1133,1120,1114,1120,1131,1131,1118,1102,1091,1079,1061,1043,
+1037,1041,1041,1034,1027,1024,1018,1000,984,985,999,1002,977,936,906,897,895,883,858,830,805,
+778,743,705,674,653,635,612,585,561,541,520,495,472,458,452,444,428,412,402,400,398,
+388,375,365,357,347,332,317,305,292,269,236,199,165,139,119,100,81,61,45,39,39,
+35,17,-11,-41,-67,-92,-122,-155,-190,-225,-263,-300,-333,-364,-396,-433,-469,-500,-527,-557,-589,
+-620,-650,-678,-708,-740,-769,-792,-809,-822,-838,-856,-874,-890,-904,-919,-934,-949,-968,-990,-1012,-1031,
+-1048,-1066,-1086,-1105,-1123,-1137,-1150,-1165,-1187,-1211,-1229,-1238,-1247,-1268,-1300,-1330,-1348,-1357,-1362,-1367,-1374,
+-1383,-1394,-1404,-1411,-1417,-1425,-1437,-1450,-1460,-1465,-1467,-1472,-1481,-1490,-1495,-1498,-1503,-1507,-1505,-1498,-1495,
+-1498,-1502,-1499,-1493,-1489,-1489,-1490,-1490,-1489,-1488,-1485,-1478,-1470,-1461,-1453,-1444,-1435,-1426,-1420,-1419,-1418,
+-1410,-1394,-1372,-1352,-1333,-1317,-1304,-1292,-1281,-1268,-1257,-1249,-1242,-1237,-1232,-1228,-1223,-1218,-1216,-1217,-1216,
+-1212,-1205,-1200,-1197,-1200,-1206,-1215,-1221,-1224,-1230,-1239,-1245,-1248,-1251,-1258,-1266,-1271,-1275,-1284,-1299,-1315,
+-1331,-1344,-1349,-1347,-1343,-1345,-1353,-1358,-1359,-1361,-1363,-1364,-1361,-1358,-1358,-1360,-1362,-1364,-1366,-1367,-1367,
+-1367,-1370,-1375,-1379,-1378,-1372,-1366,-1361,-1359,-1356,-1351,-1344,-1335,-1324,-1313,-1302,-1293,-1282,-1271,-1261,-1251,
+-1236,-1217,-1200,-1184,-1163,-1136,-1109,-1086,-1065,-1040,-1012,-982,-950,-916,-883,-850,-811,-767,-727,-693,-653,
+-603,-557,-521,-487,-440,-390,-348,-309,-262,-212,-173,-140,-97,-54,-27,-16,-15,-45,-139,-259,-282,
+-102,254,642,904,980,935,913,1027,1274,1544,1740,1862,1966,2053,2066,1964,1776,1562,1372,1239,1186,
+1205,1262,1331,1410,1503,1602,1689,1762,1823,1872,1908,1936,1968,2008,2060,2125,2201,2271,2318,2346,2367,
+2383,2380,2350,2306,2276,2277,2292,2282,2225,2133,2032,1935,1840,1747,1664,1592,1523,1453,1382,1307,1221,
+1128,1042,966,884,783,675,580,502,431,371,332,311,285,225,115,-34,-185,-288,-327,-329,-338,
+-372,-419,-467,-518,-577,-644,-716,-795,-878,-959,-1033,-1103,-1179,-1259,-1339,-1416,-1491,-1566,-1639,-1708,-1772,
+-1831,-1884,-1929,-1968,-2003,-2034,-2058,-2075,-2086,-2099,-2113,-2123,-2128,-2132,-2140,-2148,-2158,-2172,-2193,-2212,-2226,
+-2243,-2269,-2293,-2297,-2279,-2261,-2265,-2296,-2349,-2408,-2451,-2466,-2464,-2472,-2491,-2497,-2471,-2426,-2387,-2362,-2339,
+-2311,-2289,-2278,-2271,-2252,-2222,-2187,-2151,-2109,-2047,-1964,-1868,-1767,-1661,-1547,-1435,-1339,-1266,-1209,-1168,-1146,
+-1141,-1127,-1079,-997,-910,-847,-817,-800,-774,-724,-653,-572,-496,-443,-424,-436,-455,-465,-485,-551,-670,
+-793,-865,-878,-869,-866,-867,-862,-854,-856,-863,-864,-856,-846,-840,-831,-814,-793,-770,-749,-730,-714,
+-701,-690,-679,-664,-639,-606,-572,-542,-515,-487,-459,-433,-409,-384,-358,-332,-301,-262,-219,-179,-143,
+-106,-66,-29,6,47,95,142,182,222,269,320,364,399,434,478,530,591,658,725,783,832,
+882,936,988,1029,1060,1088,1117,1145,1175,1212,1253,1289,1316,1340,1367,1395,1422,1456,1497,1534,1557,
+1570,1583,1599,1619,1642,1671,1695,1701,1690,1679,1679,1682,1676,1664,1655,1650,1643,1631,1621,1614,1606,
+1599,1593,1588,1579,1569,1565,1570,1577,1577,1570,1564,1561,1557,1557,1565,1582,1602,1620,1637,1646,1648,
+1649,1655,1663,1662,1656,1661,1672,1667,1646,1636,1648,1642,1602,1524,1430,1381,1376,1352,1272,1177,1125,
+1110,1082,1023,970,951,950,939,920,909,904,893,873,854,834,811,786,767,754,740,729,727,
+730,731,726,721,721,722,726,737,755,774,795,830,889,969,1057,1140,1208,1250,1258,1229,1173,
+1108,1053,1017,986,940,866,784,736,741,779,802,780,721,653,590,527,462,406,364,327,283,
+233,183,125,45,-55,-154,-231,-288,-341,-403,-471,-526,-556,-571,-600,-667,-770,-880,-973,-1040,-1086,
+-1119,-1142,-1159,-1174,-1192,-1217,-1244,-1265,-1276,-1284,-1302,-1339,-1402,-1487,-1568,-1614,-1617,-1601,-1586,-1557,-1482,
+-1358,-1215,-1091,-1012,-998,-1051,-1145,-1229,-1277,-1301,-1328,-1358,-1381,-1397,-1423,-1471,-1534,-1590,-1618,-1617,-1613,
+-1637,-1687,-1739,-1788,-1852,-1935,-2012,-2054,-2065,-2061,-2046,-2034,-2060,-2135,-2223,-2281,-2327,-2413,-2539,-2644,-2695,
+-2731,-2803,-2905,-2998,-3071,-3148,-3239,-3333,-3420,-3503,-3583,-3649,-3691,-3713,-3726,-3739,-3757,-3780,-3805,-3829,-3854,
+-3875,-3892,-3907,-3931,-3964,-3997,-4027,-4062,-4110,-4163,-4215,-4268,-4320,-4348,-4329,-4262,-4169,-4069,-3977,-3915,-3897,
+-3910,-3925,-3920,-3907,-3899,-3892,-3865,-3818,-3791,-3824,-3899,-3941,-3917,-3893,-3948,-4055,-4098,-4037,-3971,-3997,-4076,
+-4110,-4102,-4139,-4230,-4274,-4227,-4185,-4243,-4356,-4413,-4392,-4363,-4368,-4383,-4398,-4447,-4541,-4640,-4713,-4776,-4854,
+-4934,-4992,-5041,-5106,-5185,-5251,-5303,-5355,-5417,-5477,-5535,-5599,-5672,-5741,-5802,-5862,-5925,-5989,-6051,-6114,-6176,
+-6230,-6274,-6313,-6358,-6407,-6459,-6509,-6553,-6587,-6611,-6637,-6678,-6734,-6799,-6876,-6974,-7083,-7179,-7255,-7329,-7408,
+-7458,-7445,-7391,-7356,-7371,-7417,-7467,-7532,-7631,-7752,-7872,-7990,-8111,-8214,-8276,-8310,-8356,-8425,-8485,-8518,-8543,
+-8575,-8603,-8613,-8619,-8636,-8652,-8653,-8651,-8663,-8683,-8693,-8697,-8709,-8723,-8717,-8694,-8672,-8655,-8628,-8591,-8557,
+-8528,-8484,-8418,-8353,-8307,-8276,-8252,-8233,-8224,-8217,-8201,-8178,-8146,-8096,-8027,-7955,-7888,-7821,-7749,-7681,-7627,
+-7578,-7518,-7447,-7372,-7298,-7220,-7142,-7054,-6937,-6782,-6621,-6499,-6428,-6386,-6357,-6343,-6338,-6310,-6233,-6125,-6021,
+-5934,-5850,-5749,-5623,-5477,-5325,-5188,-5076,-4981,-4893,-4811,-4736,-4656,-4560,-4439,-4295,-4141,-4001,-3898,-3816,-3704,
+-3529,-3335,-3193,-3111,-3019,-2864,-2676,-2525,-2413,-2282,-2101,-1917,-1794,-1743,-1721,-1698,-1676,-1661,-1642,-1609,-1567,
+-1514,-1434,-1318,-1190,-1087,-1015,-954,-898,-860,-830,-740,-518,-174,198,515,783,1059,1363,1645,1844,1954,
+2010,2045,2066,2075,2086,2110,2145,2182,2221,2269,2329,2396,2461,2520,2569,2612,2661,2729,2811,2893,2964,
+3030,3108,3198,3286,3354,3406,3464,3543,3635,3718,3785,3854,3935,4010,4056,4078,4106,4151,4200,4244,4293,
+4355,4420,4483,4546,4601,4614,4572,4524,4537,4619,4717,4797,4868,4929,4940,4884,4820,4825,4898,4963,4966,
+4926,4893,4889,4907,4942,4993,5050,5097,5123,5133,5138,5143,5149,5157,5165,5164,5146,5111,5075,5056,5057,
+5064,5070,5079,5087,5063,4971,4806,4593,4361,4134,3958,3890,3961,4132,4327,4489,4614,4738,4912,5169,5485,
+5794,6033,6196,6327,6460,6590,6687,6735,6750,6769,6815,6882,6941,6975,6992,7010,7029,7038,7031,7018,7010,
+7017,7037,7071,7116,7171,7227,7269,7291,7307,7342,7398,7448,7475,7500,7552,7628,7698,7747,7787,7827,7861,
+7872,7858,7827,7805,7828,7902,7965,7909,7690,7401,7193,7134,7134,7041,6783,6419,6081,5866,5799,5850,5978,
+6145,6319,6473,6584,6636,6626,6577,6538,6550,6611,6690,6752,6787,6795,6770,6691,6521,6243,5904,5629,5557,
+5744,6125,6565,6931,7132,7154,7059,6938,6826,6688,6497,6290,6132,6039,5977,5921,5877,5843,5799,5744,5709,
+5722,5772,5825,5867,5897,5910,5896,5858,5814,5768,5710,5632,5548,5481,5435,5393,5342,5289,5252,5227,5193,
+5135,5069,5013,4965,4915,4867,4831,4803,4768,4718,4660,4600,4542,4491,4450,4411,4360,4302,4253,4213,4166,
+4110,4057,4018,3982,3942,3903,3866,3824,3776,3736,3711,3689,3661,3636,3619,3594,3555,3516,3488,3451,3379,
+3288,3221,3189,3164,3126,3091,3075,3063,3032,2983,2939,2910,2886,2855,2817,2773,2728,2685,2643,2602,2561,
+2521,2482,2438,2392,2353,2329,2311,2284,2244,2196,2154,2124,2102,2079,2056,2042,2037,2020,1974,1921,1904,
+1931,1957,1940,1891,1857,1865,1893,1911,1910,1900,1890,1881,1871,1851,1819,1782,1755,1732,1704,1672,1654,
+1659,1672,1677,1677,1682,1691,1694,1691,1691,1697,1696,1682,1663,1644,1622,1593,1567,1554,1546,1524,1487,
+1456,1447,1447,1430,1395,1368,1366,1377,1374,1351,1324,1306,1297,1287,1272,1255,1236,1213,1187,1162,1143,
+1127,1109,1089,1076,1079,1092,1102,1098,1085,1074,1066,1053,1034,1018,1011,1010,1008,1002,997,989,975,
+959,955,965,970,949,902,856,834,835,833,815,786,757,730,697,660,627,606,591,572,548,
+525,506,486,460,435,419,411,402,385,367,357,356,354,345,335,328,324,315,302,291,283,
+272,250,218,182,148,115,83,53,28,8,-4,-5,2,8,-1,-26,-53,-72,-88,-112,-146,
+-183,-220,-257,-295,-327,-356,-388,-425,-461,-493,-520,-549,-581,-613,-643,-671,-702,-735,-768,-797,-819,
+-835,-850,-867,-885,-900,-913,-926,-940,-957,-977,-999,-1020,-1037,-1051,-1066,-1085,-1105,-1124,-1138,-1150,-1163,
+-1182,-1203,-1218,-1224,-1230,-1249,-1281,-1313,-1334,-1343,-1345,-1348,-1354,-1363,-1373,-1382,-1389,-1396,-1407,-1419,-1432,
+-1443,-1449,-1453,-1456,-1463,-1472,-1478,-1485,-1492,-1495,-1490,-1482,-1479,-1481,-1481,-1475,-1467,-1462,-1460,-1459,-1456,
+-1453,-1451,-1448,-1444,-1438,-1430,-1421,-1412,-1404,-1396,-1391,-1389,-1387,-1378,-1358,-1334,-1312,-1293,-1278,-1267,-1259,
+-1251,-1240,-1229,-1220,-1213,-1207,-1201,-1197,-1193,-1188,-1185,-1185,-1185,-1180,-1174,-1170,-1171,-1175,-1182,-1190,-1195,
+-1199,-1206,-1214,-1220,-1224,-1229,-1240,-1249,-1254,-1257,-1266,-1283,-1301,-1315,-1325,-1330,-1328,-1325,-1327,-1335,-1342,
+-1344,-1345,-1349,-1352,-1351,-1348,-1348,-1350,-1350,-1349,-1349,-1351,-1352,-1353,-1357,-1364,-1370,-1371,-1366,-1359,-1354,
+-1351,-1349,-1346,-1340,-1330,-1318,-1306,-1298,-1290,-1282,-1272,-1264,-1253,-1237,-1216,-1198,-1181,-1161,-1136,-1112,-1091,
+-1069,-1044,-1014,-983,-951,-919,-889,-857,-816,-771,-732,-700,-661,-611,-565,-531,-499,-453,-400,-356,-321,
+-280,-233,-191,-154,-113,-71,-41,-24,-14,-30,-108,-232,-299,-195,98,474,776,911,905,882,967,
+1195,1490,1746,1913,2000,2029,2002,1902,1722,1481,1241,1086,1064,1144,1254,1351,1441,1539,1639,1731,1817,
+1895,1956,1992,2016,2044,2079,2121,2176,2242,2303,2339,2353,2362,2374,2373,2345,2299,2264,2261,2280,2281,
+2234,2145,2042,1949,1864,1781,1702,1631,1564,1498,1430,1352,1261,1165,1079,1003,920,824,734,665,606,
+536,458,401,374,353,298,189,40,-105,-204,-243,-251,-270,-313,-365,-412,-458,-517,-588,-665,-744,
+-826,-910,-989,-1063,-1135,-1209,-1287,-1368,-1449,-1528,-1603,-1674,-1743,-1807,-1861,-1904,-1939,-1974,-2008,-2036,-2055,
+-2066,-2077,-2089,-2099,-2106,-2114,-2123,-2130,-2138,-2152,-2174,-2195,-2209,-2226,-2252,-2278,-2285,-2271,-2256,-2261,-2295,
+-2351,-2408,-2444,-2450,-2444,-2450,-2469,-2478,-2456,-2412,-2373,-2355,-2349,-2345,-2335,-2318,-2293,-2258,-2218,-2180,-2145,
+-2105,-2045,-1959,-1858,-1755,-1649,-1535,-1418,-1313,-1234,-1182,-1151,-1135,-1126,-1107,-1065,-1003,-939,-888,-851,-817,
+-773,-713,-639,-561,-486,-430,-407,-418,-441,-451,-466,-530,-656,-794,-878,-897,-893,-901,-914,-913,-902,
+-898,-903,-905,-899,-889,-882,-872,-856,-833,-808,-783,-761,-741,-724,-710,-702,-692,-673,-640,-602,-568,
+-541,-516,-492,-467,-441,-413,-385,-360,-334,-303,-266,-228,-190,-147,-103,-62,-26,12,56,102,145,
+190,243,298,346,388,430,478,530,585,646,708,764,813,863,918,970,1008,1035,1061,1092,1127,
+1164,1205,1245,1277,1298,1314,1334,1357,1384,1419,1459,1496,1518,1531,1544,1561,1579,1599,1621,1639,1642,
+1632,1625,1633,1645,1648,1642,1639,1641,1641,1636,1629,1623,1616,1607,1598,1588,1574,1557,1546,1544,1543,
+1539,1533,1533,1537,1542,1548,1560,1578,1597,1615,1628,1633,1630,1627,1631,1637,1637,1635,1641,1650,1645,
+1629,1622,1625,1602,1522,1439,1351,1299,1282,1255,1196,1133,1098,1080,1046,996,959,949,946,932,911,
+896,890,883,869,851,830,807,787,775,767,758,752,752,754,751,741,734,734,738,744,752,
+764,780,804,846,909,986,1068,1145,1214,1262,1279,1259,1212,1156,1109,1080,1059,1028,976,912,868,
+865,888,901,874,812,739,668,598,528,467,423,390,353,311,264,210,140,55,-33,-110,-176,
+-236,-301,-370,-432,-476,-504,-536,-594,-678,-767,-842,-898,-944,-987,-1023,-1043,-1043,-1038,-1049,-1080,-1118,
+-1154,-1193,-1247,-1318,-1400,-1483,-1550,-1585,-1586,-1574,-1561,-1532,-1461,-1348,-1218,-1094,-995,-950,-989,-1102,-1225,
+-1296,-1305,-1294,-1309,-1357,-1410,-1445,-1466,-1495,-1538,-1570,-1572,-1564,-1584,-1633,-1682,-1720,-1777,-1873,-1977,-2040,
+-2052,-2038,-2026,-2039,-2094,-2185,-2271,-2324,-2371,-2453,-2552,-2616,-2637,-2675,-2769,-2886,-2974,-3036,-3110,-3210,-3312,
+-3403,-3485,-3561,-3616,-3649,-3671,-3693,-3713,-3730,-3746,-3768,-3795,-3823,-3849,-3871,-3890,-3911,-3936,-3961,-3990,-4034,
+-4101,-4178,-4248,-4305,-4350,-4376,-4367,-4313,-4211,-4076,-3940,-3850,-3829,-3853,-3872,-3864,-3850,-3850,-3850,-3818,-3756,
+-3715,-3746,-3832,-3893,-3890,-3871,-3909,-3981,-4001,-3952,-3921,-3973,-4054,-4072,-4049,-4073,-4155,-4201,-4164,-4121,-4156,
+-4243,-4307,-4334,-4357,-4380,-4375,-4358,-4379,-4456,-4545,-4619,-4693,-4782,-4864,-4919,-4965,-5029,-5103,-5168,-5221,-5277,
+-5339,-5397,-5455,-5522,-5596,-5663,-5721,-5781,-5847,-5913,-5975,-6037,-6097,-6148,-6190,-6232,-6283,-6337,-6387,-6428,-6464,
+-6495,-6524,-6558,-6605,-6664,-6732,-6813,-6913,-7023,-7119,-7194,-7261,-7322,-7350,-7324,-7274,-7259,-7301,-7369,-7428,-7491,
+-7583,-7696,-7807,-7915,-8030,-8135,-8200,-8230,-8269,-8334,-8398,-8436,-8460,-8490,-8519,-8532,-8537,-8551,-8568,-8574,-8577,
+-8590,-8609,-8619,-8626,-8642,-8658,-8652,-8623,-8591,-8566,-8534,-8492,-8452,-8416,-8370,-8310,-8258,-8228,-8207,-8180,-8148,
+-8127,-8116,-8106,-8091,-8066,-8022,-7959,-7892,-7833,-7776,-7714,-7653,-7601,-7549,-7486,-7413,-7342,-7270,-7193,-7114,-7033,
+-6931,-6795,-6647,-6531,-6466,-6429,-6403,-6386,-6373,-6332,-6243,-6128,-6028,-5953,-5873,-5762,-5622,-5474,-5335,-5213,-5109,
+-5015,-4927,-4845,-4767,-4682,-4575,-4445,-4302,-4168,-4058,-3974,-3888,-3757,-3569,-3375,-3240,-3161,-3064,-2899,-2705,-2552,
+-2448,-2332,-2169,-2000,-1888,-1838,-1809,-1772,-1731,-1684,-1622,-1554,-1509,-1493,-1468,-1395,-1288,-1183,-1091,-1002,-935,
+-935,-989,-1002,-872,-601,-279,34,366,761,1193,1573,1842,2012,2124,2187,2196,2168,2146,2158,2192,2225,
+2260,2310,2377,2437,2469,2475,2477,2498,2552,2631,2716,2791,2855,2926,3013,3108,3191,3252,3298,3354,3437,
+3536,3623,3684,3739,3809,3888,3947,3977,4001,4039,4081,4115,4155,4214,4286,4351,4402,4431,4420,4370,4323,
+4342,4440,4576,4708,4820,4896,4909,4864,4815,4811,4831,4823,4782,4751,4761,4793,4825,4861,4912,4966,5002,
+5019,5029,5039,5041,5033,5025,5024,5022,5005,4973,4941,4932,4951,4980,4996,4988,4952,4884,4781,4656,4531,
+4414,4302,4211,4179,4235,4356,4490,4607,4724,4881,5105,5390,5695,5962,6156,6290,6405,6525,6637,6712,6743,
+6752,6770,6811,6869,6923,6961,6984,6994,6992,6979,6963,6957,6965,6984,7012,7051,7102,7162,7221,7262,7282,
+7298,7331,7383,7433,7467,7495,7531,7573,7609,7637,7665,7695,7723,7742,7746,7723,7682,7671,7736,7848,7904,
+7826,7651,7491,7406,7331,7143,6794,6360,5979,5746,5676,5733,5870,6047,6223,6371,6483,6562,6612,6644,6683,
+6753,6845,6928,6973,6976,6948,6902,6838,6733,6555,6302,6035,5854,5838,6006,6307,6645,6902,7006,6985,6929,
+6888,6835,6724,6569,6420,6303,6212,6137,6071,5991,5872,5732,5631,5605,5638,5695,5756,5819,5872,5896,5890,
+5867,5833,5781,5707,5619,5536,5470,5418,5368,5316,5271,5240,5213,5179,5137,5095,5052,5004,4951,4905,4864,
+4822,4772,4717,4659,4598,4541,4496,4456,4410,4355,4303,4255,4202,4144,4094,4056,4018,3974,3934,3901,3865,
+3822,3783,3759,3741,3719,3698,3684,3667,3634,3594,3559,3519,3458,3379,3305,3245,3197,3163,3152,3147,3120,
+3062,3002,2969,2964,2967,2961,2934,2878,2803,2729,2672,2627,2585,2547,2518,2489,2455,2417,2386,2359,2326,
+2282,2237,2198,2169,2144,2120,2098,2087,2082,2068,2033,1995,1987,2012,2030,1999,1933,1884,1883,1915,1944,
+1952,1944,1930,1920,1912,1896,1864,1819,1774,1735,1700,1671,1658,1662,1672,1677,1681,1685,1685,1675,1667,
+1671,1684,1689,1684,1677,1670,1654,1623,1591,1568,1543,1501,1455,1431,1435,1440,1420,1385,1369,1378,1387,
+1371,1338,1313,1303,1293,1274,1249,1226,1205,1182,1159,1140,1125,1108,1087,1064,1048,1045,1057,1074,1082,
+1077,1066,1056,1045,1026,1004,990,988,988,982,972,964,953,939,928,930,937,924,877,818,778,
+769,772,764,738,707,679,650,618,589,567,551,537,519,499,477,454,428,404,388,377,364,
+346,328,318,315,312,305,297,292,288,281,271,263,257,245,222,192,159,125,87,48,17,
+-2,-17,-30,-38,-36,-28,-30,-47,-69,-84,-95,-113,-144,-182,-221,-260,-296,-327,-355,-385,-420,
+-457,-490,-520,-552,-584,-613,-640,-667,-696,-727,-760,-792,-819,-840,-857,-876,-896,-914,-929,-942,-955,
+-972,-993,-1015,-1034,-1048,-1059,-1071,-1087,-1105,-1123,-1138,-1151,-1163,-1178,-1194,-1206,-1211,-1217,-1236,-1266,-1297,
+-1319,-1327,-1329,-1331,-1337,-1346,-1356,-1363,-1370,-1380,-1391,-1402,-1414,-1425,-1432,-1435,-1437,-1441,-1447,-1453,-1461,
+-1469,-1473,-1468,-1461,-1460,-1463,-1462,-1455,-1446,-1440,-1435,-1428,-1422,-1417,-1413,-1409,-1405,-1401,-1394,-1385,-1376,
+-1370,-1365,-1362,-1359,-1354,-1342,-1320,-1297,-1277,-1260,-1244,-1231,-1223,-1216,-1207,-1197,-1188,-1181,-1174,-1169,-1167,
+-1165,-1159,-1155,-1154,-1154,-1151,-1146,-1144,-1147,-1152,-1157,-1162,-1167,-1172,-1179,-1188,-1196,-1201,-1207,-1218,-1229,
+-1236,-1242,-1253,-1270,-1286,-1297,-1304,-1308,-1308,-1306,-1310,-1319,-1326,-1330,-1332,-1335,-1338,-1337,-1337,-1338,-1340,
+-1337,-1332,-1330,-1331,-1334,-1337,-1343,-1351,-1357,-1359,-1356,-1351,-1346,-1342,-1339,-1336,-1332,-1324,-1313,-1303,-1294,
+-1287,-1278,-1268,-1259,-1247,-1230,-1211,-1193,-1175,-1156,-1135,-1113,-1093,-1069,-1042,-1012,-982,-951,-920,-890,-858,
+-820,-776,-738,-706,-669,-622,-577,-541,-508,-462,-409,-365,-332,-297,-254,-210,-167,-122,-79,-50,-33,
+-20,-22,-76,-188,-287,-262,-55,281,610,811,867,871,948,1154,1444,1718,1901,1978,1982,1948,1870,
+1705,1436,1138,944,934,1060,1213,1329,1422,1518,1622,1729,1841,1947,2024,2061,2082,2114,2159,2204,2247,
+2290,2326,2344,2348,2352,2360,2361,2340,2303,2270,2257,2262,2256,2214,2137,2048,1964,1884,1802,1726,1664,
+1612,1559,1492,1406,1303,1196,1102,1022,943,862,794,748,703,633,544,473,434,404,347,248,122,
+2,-84,-132,-164,-204,-258,-312,-358,-404,-463,-538,-617,-696,-776,-860,-943,-1019,-1088,-1156,-1230,-1312,
+-1400,-1486,-1565,-1639,-1709,-1773,-1829,-1873,-1909,-1942,-1974,-2003,-2025,-2041,-2054,-2064,-2072,-2080,-2091,-2103,-2112,
+-2118,-2129,-2147,-2168,-2188,-2212,-2243,-2272,-2285,-2281,-2275,-2284,-2315,-2360,-2405,-2434,-2442,-2442,-2449,-2466,-2473,
+-2456,-2420,-2387,-2374,-2382,-2393,-2388,-2359,-2311,-2256,-2207,-2167,-2132,-2091,-2029,-1942,-1843,-1744,-1644,-1531,-1405,
+-1289,-1204,-1156,-1133,-1122,-1110,-1086,-1047,-1000,-955,-911,-863,-806,-742,-675,-608,-543,-481,-428,-399,-401,
+-417,-425,-442,-515,-659,-821,-923,-944,-932,-934,-952,-962,-956,-949,-948,-947,-941,-932,-921,-907,-888,
+-865,-840,-815,-791,-768,-748,-732,-724,-718,-704,-674,-635,-599,-571,-547,-524,-500,-472,-441,-408,-381,
+-357,-333,-304,-271,-232,-187,-139,-94,-53,-12,32,78,123,171,224,278,329,376,425,476,528,
+582,640,701,757,807,854,903,947,979,1000,1020,1049,1085,1125,1169,1211,1243,1261,1272,1285,1305,
+1333,1368,1409,1446,1471,1489,1509,1531,1549,1563,1577,1591,1599,1600,1604,1619,1635,1642,1640,1639,1643,
+1644,1638,1629,1619,1607,1594,1581,1570,1557,1542,1529,1522,1518,1514,1511,1516,1526,1537,1548,1561,1576,
+1589,1600,1609,1614,1613,1609,1609,1612,1613,1614,1617,1619,1610,1593,1581,1566,1522,1440,1369,1308,1268,
+1236,1191,1139,1101,1080,1059,1022,981,956,950,943,925,903,889,882,876,866,851,830,809,793,
+787,784,780,776,776,775,770,760,753,753,757,763,771,782,798,825,868,929,1000,1070,1138,
+1200,1247,1267,1256,1225,1189,1161,1144,1130,1111,1081,1043,1011,1000,1004,1002,969,904,824,743,665,
+592,529,481,446,413,377,337,290,232,163,87,7,-68,-138,-204,-269,-333,-388,-432,-474,-526,
+-587,-650,-705,-754,-806,-860,-904,-924,-914,-894,-894,-929,-989,-1059,-1137,-1227,-1322,-1410,-1480,-1527,-1547,
+-1543,-1527,-1508,-1476,-1419,-1340,-1245,-1133,-1008,-915,-926,-1058,-1237,-1349,-1344,-1277,-1245,-1297,-1394,-1463,-1478,
+-1475,-1494,-1529,-1549,-1554,-1569,-1601,-1626,-1645,-1697,-1801,-1914,-1976,-1979,-1965,-1973,-2015,-2088,-2182,-2273,-2347,
+-2417,-2496,-2562,-2587,-2593,-2643,-2751,-2867,-2946,-3005,-3089,-3199,-3306,-3394,-3473,-3542,-3587,-3611,-3636,-3669,-3698,
+-3711,-3718,-3732,-3758,-3789,-3819,-3842,-3861,-3882,-3908,-3942,-3986,-4042,-4106,-4158,-4184,-4189,-4193,-4213,-4243,-4252,
+-4205,-4090,-3942,-3827,-3786,-3801,-3819,-3813,-3798,-3798,-3799,-3769,-3704,-3655,-3673,-3753,-3827,-3845,-3834,-3848,-3889,
+-3909,-3894,-3900,-3958,-4020,-4024,-4000,-4022,-4090,-4128,-4101,-4064,-4081,-4141,-4201,-4260,-4325,-4370,-4362,-4328,-4329,
+-4380,-4449,-4518,-4600,-4696,-4779,-4834,-4881,-4944,-5015,-5077,-5134,-5195,-5256,-5310,-5368,-5442,-5520,-5586,-5641,-5700,
+-5767,-5832,-5891,-5950,-6008,-6059,-6104,-6152,-6208,-6262,-6302,-6334,-6367,-6405,-6444,-6484,-6530,-6587,-6659,-6750,-6855,
+-6961,-7051,-7123,-7186,-7237,-7250,-7214,-7165,-7159,-7212,-7289,-7355,-7422,-7517,-7632,-7744,-7848,-7958,-8060,-8124,-8153,
+-8187,-8249,-8313,-8351,-8373,-8401,-8430,-8445,-8449,-8461,-8479,-8492,-8501,-8517,-8537,-8551,-8563,-8584,-8604,-8601,-8573,
+-8540,-8511,-8475,-8425,-8374,-8329,-8284,-8236,-8203,-8189,-8175,-8141,-8093,-8057,-8041,-8035,-8028,-8009,-7970,-7910,-7845,
+-7788,-7736,-7679,-7622,-7570,-7518,-7454,-7383,-7313,-7245,-7170,-7093,-7018,-6929,-6810,-6676,-6569,-6510,-6479,-6454,-6433,
+-6409,-6354,-6252,-6129,-6032,-5964,-5885,-5766,-5620,-5477,-5351,-5241,-5145,-5056,-4970,-4881,-4788,-4690,-4579,-4453,-4327,
+-4219,-4135,-4054,-3939,-3765,-3557,-3375,-3267,-3203,-3103,-2928,-2728,-2578,-2483,-2382,-2239,-2092,-1994,-1943,-1899,-1843,
+-1781,-1712,-1619,-1518,-1458,-1454,-1465,-1439,-1375,-1303,-1225,-1128,-1038,-1014,-1064,-1108,-1060,-912,-713,-468,-121,
+349,871,1327,1663,1905,2089,2203,2225,2183,2145,2153,2197,2246,2297,2368,2454,2518,2528,2490,2449,2445,
+2490,2561,2630,2689,2753,2833,2920,2997,3060,3120,3184,3254,3332,3418,3500,3559,3599,3647,3716,3790,3849,
+3895,3940,3981,4010,4039,4084,4139,4181,4194,4178,4134,4070,4025,4050,4157,4306,4451,4574,4668,4718,4729,
+4732,4743,4737,4685,4619,4596,4630,4681,4714,4742,4785,4834,4867,4889,4914,4942,4951,4936,4915,4902,4897,
+4883,4857,4830,4826,4846,4868,4860,4813,4745,4681,4632,4596,4565,4528,4477,4425,4409,4451,4538,4640,4746,
+4882,5072,5317,5582,5832,6043,6214,6358,6483,6588,6665,6709,6729,6741,6760,6796,6847,6902,6945,6968,6971,
+6959,6944,6936,6942,6960,6985,7016,7054,7102,7156,7205,7238,7256,7274,7307,7355,7404,7445,7481,7511,7528,
+7534,7542,7562,7587,7612,7638,7659,7647,7594,7548,7581,7699,7823,7868,7835,7793,7774,7708,7486,7076,6577,
+6137,5853,5731,5737,5842,6020,6226,6414,6556,6653,6716,6757,6794,6847,6922,7003,7068,7096,7076,7014,6928,
+6834,6723,6575,6395,6218,6102,6100,6235,6460,6673,6782,6797,6798,6840,6888,6881,6803,6690,6575,6473,6389,
+6313,6209,6049,5860,5702,5619,5602,5628,5683,5754,5825,5880,5915,5928,5913,5870,5809,5734,5648,5559,5478,
+5410,5346,5285,5238,5214,5205,5199,5187,5163,5124,5071,5011,4948,4884,4821,4764,4710,4653,4593,4542,4501,
+4460,4410,4355,4296,4235,4176,4130,4095,4058,4012,3969,3934,3899,3860,3828,3809,3793,3769,3743,3728,3718,
+3700,3669,3631,3587,3534,3473,3404,3330,3267,3243,3260,3272,3228,3136,3060,3040,3063,3088,3089,3057,2986,
+2887,2793,2726,2679,2634,2592,2563,2542,2514,2476,2439,2406,2370,2327,2286,2253,2227,2203,2179,2159,2144,
+2132,2113,2084,2057,2054,2072,2077,2038,1967,1911,1899,1922,1952,1970,1974,1964,1948,1932,1914,1887,1845,
+1795,1748,1710,1685,1674,1672,1675,1680,1691,1698,1692,1671,1655,1657,1671,1680,1684,1690,1693,1679,1646,
+1612,1585,1550,1498,1449,1434,1447,1449,1416,1378,1371,1390,1393,1359,1314,1292,1292,1284,1257,1221,1193,
+1171,1153,1138,1127,1114,1093,1069,1048,1034,1030,1038,1055,1068,1064,1047,1033,1022,1007,986,971,967,
+967,959,948,940,934,922,906,900,906,901,866,807,753,726,721,718,700,671,640,613,588,
+562,538,518,504,490,472,448,421,395,374,358,343,326,307,291,283,279,276,272,266,262,
+256,249,242,235,227,210,185,155,128,104,85,73,69,69,59,29,-10,-41,-54,-60,-70,
+-86,-99,-110,-126,-153,-189,-229,-268,-303,-332,-360,-390,-425,-461,-495,-530,-565,-596,-622,-645,-670,
+-698,-725,-753,-782,-811,-835,-855,-876,-899,-922,-940,-954,-968,-985,-1005,-1026,-1044,-1057,-1068,-1080,-1093,
+-1108,-1124,-1139,-1153,-1165,-1176,-1186,-1194,-1200,-1210,-1229,-1257,-1284,-1302,-1310,-1313,-1315,-1322,-1331,-1339,-1345,
+-1353,-1364,-1375,-1387,-1398,-1408,-1414,-1414,-1414,-1415,-1419,-1423,-1428,-1436,-1440,-1438,-1434,-1435,-1438,-1437,-1432,
+-1425,-1420,-1412,-1402,-1393,-1387,-1380,-1373,-1367,-1363,-1357,-1345,-1335,-1330,-1328,-1326,-1323,-1315,-1301,-1279,-1259,
+-1243,-1229,-1213,-1197,-1186,-1178,-1169,-1160,-1154,-1147,-1140,-1136,-1136,-1136,-1130,-1123,-1121,-1123,-1122,-1120,-1120,
+-1123,-1127,-1130,-1134,-1140,-1145,-1152,-1162,-1173,-1180,-1186,-1194,-1205,-1215,-1224,-1237,-1255,-1272,-1284,-1292,-1297,
+-1298,-1298,-1302,-1311,-1319,-1324,-1327,-1328,-1328,-1326,-1326,-1329,-1330,-1327,-1321,-1318,-1319,-1322,-1326,-1334,-1342,
+-1347,-1347,-1344,-1341,-1338,-1335,-1332,-1327,-1321,-1315,-1308,-1300,-1291,-1281,-1270,-1258,-1247,-1234,-1218,-1201,-1184,
+-1167,-1148,-1128,-1108,-1087,-1061,-1032,-1003,-976,-949,-919,-888,-856,-820,-781,-742,-709,-674,-633,-590,-551,
+-514,-471,-424,-382,-346,-309,-268,-223,-177,-127,-81,-50,-36,-25,-20,-46,-129,-239,-282,-171,97,
+422,674,802,864,963,1154,1414,1672,1863,1960,1977,1952,1886,1729,1445,1102,861,829,964,1140,1272,
+1370,1466,1573,1691,1824,1957,2055,2103,2126,2162,2216,2269,2306,2328,2341,2350,2359,2369,2376,2372,2354,
+2329,2303,2280,2258,2231,2187,2127,2058,1985,1904,1818,1744,1696,1665,1626,1558,1459,1339,1218,1114,1032,
+965,906,862,832,795,730,645,571,519,470,399,303,201,109,33,-27,-81,-137,-194,-247,-294,
+-343,-406,-480,-560,-640,-723,-811,-897,-975,-1045,-1112,-1185,-1267,-1356,-1445,-1527,-1602,-1670,-1732,-1789,-1839,
+-1880,-1913,-1942,-1967,-1991,-2013,-2032,-2044,-2051,-2058,-2068,-2082,-2094,-2102,-2110,-2121,-2139,-2162,-2194,-2230,-2262,
+-2279,-2287,-2294,-2308,-2329,-2356,-2384,-2409,-2426,-2439,-2454,-2469,-2476,-2465,-2438,-2411,-2402,-2415,-2433,-2427,-2384,
+-2315,-2245,-2187,-2143,-2103,-2057,-1992,-1908,-1815,-1723,-1628,-1515,-1388,-1270,-1189,-1145,-1126,-1114,-1098,-1072,-1037,
+-1000,-961,-914,-851,-776,-699,-632,-578,-533,-489,-443,-408,-396,-397,-399,-420,-505,-670,-857,-979,-1004,
+-978,-962,-974,-992,-998,-992,-986,-981,-976,-967,-951,-930,-907,-887,-868,-844,-818,-791,-769,-753,-745,
+-740,-727,-699,-663,-629,-602,-579,-556,-532,-505,-473,-440,-409,-383,-360,-337,-308,-270,-224,-174,-125,
+-76,-27,22,71,117,164,214,265,315,365,414,465,515,568,625,685,741,789,833,874,911,
+939,958,975,999,1032,1072,1115,1159,1194,1216,1228,1241,1263,1297,1337,1378,1413,1439,1463,1490,1515,
+1533,1542,1551,1566,1583,1596,1607,1622,1635,1640,1637,1632,1630,1626,1616,1602,1587,1572,1557,1545,1540,
+1536,1530,1523,1517,1512,1510,1510,1516,1528,1543,1556,1567,1573,1575,1576,1580,1586,1590,1588,1585,1585,
+1588,1592,1592,1585,1570,1552,1531,1497,1440,1384,1337,1314,1294,1247,1176,1114,1085,1073,1050,1010,975,
+957,947,934,915,899,890,883,876,867,854,837,819,809,806,804,801,797,796,794,790,784,
+780,778,779,783,792,805,823,848,888,942,1004,1064,1119,1167,1204,1223,1225,1218,1213,1213,1213,
+1205,1189,1169,1147,1126,1111,1102,1088,1051,986,900,810,728,657,598,549,506,469,435,401,362,
+314,256,188,111,30,-45,-113,-177,-241,-302,-356,-407,-456,-504,-549,-594,-645,-701,-756,-799,-819,
+-811,-790,-785,-818,-892,-992,-1103,-1215,-1315,-1396,-1457,-1495,-1504,-1484,-1448,-1412,-1379,-1346,-1313,-1266,-1177,
+-1039,-911,-896,-1042,-1271,-1429,-1421,-1293,-1186,-1204,-1329,-1457,-1509,-1500,-1489,-1505,-1534,-1561,-1586,-1603,-1599,
+-1590,-1621,-1706,-1795,-1835,-1838,-1858,-1921,-2007,-2092,-2176,-2266,-2360,-2452,-2530,-2573,-2580,-2590,-2649,-2750,-2842,
+-2903,-2967,-3070,-3196,-3308,-3394,-3469,-3532,-3570,-3590,-3615,-3653,-3683,-3691,-3689,-3697,-3720,-3749,-3778,-3803,-3824,
+-3850,-3889,-3945,-4008,-4065,-4096,-4081,-4019,-3942,-3900,-3926,-4010,-4100,-4131,-4071,-3943,-3816,-3748,-3740,-3750,-3747,
+-3736,-3733,-3738,-3724,-3680,-3633,-3630,-3686,-3760,-3798,-3795,-3789,-3807,-3835,-3856,-3883,-3926,-3960,-3962,-3956,-3983,
+-4032,-4054,-4039,-4027,-4050,-4092,-4135,-4192,-4268,-4326,-4333,-4309,-4303,-4328,-4368,-4421,-4500,-4596,-4678,-4735,-4789,
+-4855,-4923,-4986,-5049,-5115,-5171,-5219,-5277,-5357,-5442,-5508,-5561,-5620,-5686,-5749,-5806,-5863,-5921,-5974,-6022,-6074,
+-6128,-6175,-6209,-6238,-6275,-6319,-6362,-6400,-6442,-6500,-6583,-6685,-6793,-6890,-6969,-7035,-7096,-7143,-7155,-7123,-7081,
+-7079,-7132,-7210,-7284,-7360,-7462,-7580,-7691,-7790,-7890,-7984,-8046,-8077,-8112,-8168,-8225,-8258,-8278,-8307,-8338,-8353,
+-8358,-8372,-8396,-8415,-8428,-8446,-8469,-8488,-8504,-8528,-8553,-8556,-8533,-8503,-8474,-8435,-8377,-8316,-8267,-8227,-8195,
+-8177,-8172,-8158,-8116,-8059,-8017,-8000,-7997,-7994,-7977,-7937,-7875,-7807,-7750,-7700,-7645,-7587,-7535,-7484,-7424,-7354,
+-7285,-7218,-7147,-7073,-7002,-6918,-6807,-6684,-6587,-6537,-6512,-6489,-6463,-6431,-6365,-6251,-6122,-6025,-5962,-5887,-5771,
+-5633,-5503,-5386,-5276,-5178,-5095,-5016,-4922,-4810,-4692,-4577,-4464,-4360,-4276,-4209,-4123,-3976,-3767,-3545,-3382,-3299,
+-3246,-3141,-2962,-2766,-2625,-2539,-2449,-2322,-2192,-2104,-2049,-1989,-1913,-1833,-1748,-1640,-1521,-1443,-1431,-1450,-1448,
+-1420,-1386,-1341,-1264,-1169,-1111,-1113,-1132,-1117,-1064,-981,-828,-534,-92,407,854,1210,1506,1763,1951,2034,
+2036,2028,2060,2126,2198,2272,2366,2474,2555,2574,2536,2488,2476,2506,2551,2591,2637,2712,2811,2894,2939,
+2971,3032,3124,3207,3264,3314,3376,3431,3457,3472,3513,3590,3677,3752,3810,3853,3881,3903,3930,3957,3965,
+3943,3901,3846,3788,3749,3768,3851,3965,4072,4167,4259,4346,4422,4491,4553,4581,4554,4504,4489,4526,4575,
+4600,4612,4637,4674,4708,4742,4790,4844,4877,4874,4850,4829,4817,4800,4770,4737,4718,4716,4706,4659,4582,
+4521,4514,4559,4615,4642,4628,4587,4548,4543,4586,4667,4764,4879,5034,5242,5483,5715,5911,6078,6236,6388,
+6518,6609,6663,6693,6714,6728,6741,6767,6813,6870,6915,6934,6932,6925,6926,6937,6953,6971,6992,7018,7049,
+7086,7127,7164,7190,7210,7237,7277,7326,7374,7419,7462,7493,7501,7493,7489,7500,7516,7532,7556,7582,7577,
+7524,7466,7475,7572,7700,7795,7860,7947,8058,8096,7934,7541,7019,6529,6173,5965,5882,5916,6058,6269,6484,
+6654,6765,6823,6839,6834,6837,6870,6941,7034,7112,7140,7100,7014,6916,6826,6741,6648,6540,6431,6360,6370,
+6464,6577,6643,6663,6700,6791,6892,6937,6904,6818,6713,6613,6532,6465,6383,6255,6091,5927,5794,5709,5677,
+5693,5730,5771,5824,5897,5965,5985,5949,5888,5821,5740,5641,5542,5459,5387,5317,5261,5234,5235,5246,5251,
+5243,5216,5170,5107,5035,4958,4882,4816,4763,4711,4656,4604,4560,4519,4470,4410,4345,4279,4219,4169,4130,
+4092,4051,4012,3975,3936,3897,3870,3856,3841,3815,3786,3767,3759,3748,3727,3692,3647,3600,3553,3497,3420,
+3344,3317,3345,3366,3316,3213,3139,3139,3178,3197,3175,3119,3034,2933,2840,2778,2737,2693,2646,2611,2589,
+2562,2525,2486,2453,2420,2383,2346,2317,2294,2271,2248,2224,2202,2178,2151,2121,2095,2084,2086,2080,2049,
+2000,1959,1940,1942,1953,1972,1991,1996,1980,1954,1927,1899,1865,1822,1780,1746,1723,1707,1694,1685,1687,
+1701,1713,1708,1683,1659,1652,1659,1669,1680,1696,1704,1689,1655,1621,1594,1558,1505,1461,1454,1467,1454,
+1402,1357,1360,1393,1397,1349,1288,1260,1264,1265,1242,1207,1175,1150,1131,1118,1108,1091,1063,1036,1022,
+1018,1018,1023,1036,1044,1034,1012,995,988,981,966,952,945,943,935,925,921,919,911,896,883,
+882,882,865,823,767,718,691,681,670,646,615,587,566,542,515,490,473,460,442,417,389,
+364,344,326,306,286,267,254,249,246,245,243,241,237,228,218,210,202,189,167,139,112,
+94,98,125,167,204,216,191,129,48,-25,-71,-90,-96,-105,-116,-128,-142,-165,-198,-237,-277,
+-311,-340,-369,-402,-437,-471,-506,-543,-581,-611,-632,-652,-677,-705,-731,-754,-777,-802,-825,-846,-869,
+-894,-920,-940,-957,-972,-989,-1008,-1026,-1044,-1059,-1072,-1085,-1099,-1112,-1126,-1141,-1155,-1166,-1173,-1179,-1185,
+-1194,-1208,-1228,-1250,-1270,-1284,-1292,-1297,-1301,-1308,-1315,-1321,-1326,-1333,-1345,-1357,-1369,-1380,-1390,-1394,-1393,
+-1391,-1391,-1392,-1393,-1395,-1400,-1405,-1406,-1404,-1405,-1407,-1406,-1403,-1401,-1399,-1391,-1379,-1369,-1362,-1353,-1343,
+-1335,-1330,-1323,-1310,-1296,-1288,-1286,-1283,-1278,-1269,-1254,-1234,-1217,-1204,-1191,-1177,-1162,-1151,-1141,-1132,-1123,
+-1118,-1114,-1107,-1103,-1104,-1105,-1099,-1091,-1088,-1090,-1092,-1091,-1092,-1094,-1097,-1100,-1105,-1113,-1120,-1126,-1136,
+-1149,-1160,-1167,-1173,-1182,-1192,-1203,-1218,-1240,-1263,-1281,-1293,-1299,-1302,-1304,-1308,-1315,-1321,-1325,-1327,-1327,
+-1324,-1321,-1321,-1323,-1323,-1319,-1314,-1312,-1314,-1317,-1321,-1329,-1335,-1338,-1335,-1332,-1329,-1329,-1328,-1324,-1318,
+-1311,-1305,-1301,-1294,-1283,-1271,-1260,-1248,-1236,-1221,-1206,-1191,-1175,-1157,-1138,-1118,-1097,-1074,-1047,-1019,-991,
+-968,-945,-918,-887,-854,-822,-787,-749,-713,-679,-644,-603,-561,-521,-484,-445,-403,-359,-315,-272,-230,
+-185,-137,-88,-51,-31,-22,-14,-22,-76,-180,-270,-241,-46,251,530,717,843,979,1159,1374,1602,
+1813,1961,2016,1992,1912,1756,1484,1142,873,803,917,1091,1230,1328,1417,1516,1632,1771,1925,2054,2128,
+2161,2192,2241,2295,2332,2348,2353,2365,2391,2419,2428,2413,2387,2368,2350,2323,2281,2231,2181,2130,2075,
+2011,1931,1843,1772,1734,1715,1684,1615,1508,1377,1245,1132,1051,998,961,934,911,879,826,757,689,
+627,556,467,367,275,196,125,55,-11,-72,-127,-178,-229,-286,-350,-422,-501,-587,-677,-767,-852,
+-931,-1003,-1073,-1145,-1222,-1306,-1393,-1478,-1556,-1626,-1687,-1743,-1795,-1842,-1879,-1908,-1932,-1957,-1981,-2002,-2016,
+-2025,-2030,-2038,-2051,-2066,-2079,-2087,-2094,-2107,-2134,-2174,-2215,-2247,-2268,-2286,-2303,-2318,-2328,-2336,-2350,-2371,
+-2395,-2417,-2437,-2454,-2463,-2457,-2435,-2409,-2399,-2412,-2430,-2422,-2372,-2295,-2218,-2156,-2103,-2052,-1997,-1933,-1856,
+-1770,-1680,-1583,-1471,-1353,-1252,-1185,-1148,-1124,-1103,-1082,-1058,-1029,-995,-954,-898,-824,-742,-667,-610,-573,
+-547,-518,-480,-442,-418,-408,-405,-425,-509,-674,-868,-1005,-1043,-1016,-987,-989,-1009,-1022,-1021,-1014,-1010,
+-1008,-1001,-980,-951,-925,-908,-894,-872,-842,-809,-785,-771,-764,-758,-742,-715,-683,-655,-632,-611,-588,
+-564,-538,-508,-476,-444,-416,-391,-368,-341,-306,-262,-213,-161,-106,-50,5,56,103,149,195,242,
+292,343,393,441,490,541,594,648,701,749,791,830,866,897,921,941,966,997,1034,1074,1115,
+1152,1179,1197,1216,1249,1295,1345,1387,1418,1442,1466,1492,1515,1529,1535,1541,1556,1575,1590,1600,1608,
+1614,1615,1608,1599,1591,1583,1572,1558,1544,1531,1518,1511,1511,1515,1518,1515,1510,1505,1503,1504,1510,
+1523,1540,1554,1560,1559,1554,1550,1552,1558,1564,1565,1561,1559,1563,1569,1567,1554,1537,1520,1493,1445,
+1384,1346,1319,1329,1327,1271,1177,1101,1071,1063,1040,1004,975,960,947,928,909,899,892,884,877,
+869,860,848,835,828,826,823,819,816,815,815,813,812,811,809,809,812,821,833,849,870,
+903,947,997,1047,1089,1121,1145,1164,1182,1204,1234,1266,1288,1289,1269,1242,1218,1198,1182,1166,1146,
+1110,1047,959,862,775,711,664,620,573,528,492,462,430,387,333,269,197,119,43,-27,-94,
+-160,-222,-277,-329,-378,-423,-465,-512,-567,-623,-671,-709,-735,-744,-735,-727,-752,-826,-940,-1068,-1182,
+-1273,-1346,-1406,-1445,-1444,-1397,-1331,-1278,-1254,-1250,-1254,-1245,-1188,-1070,-946,-926,-1070,-1314,-1500,-1502,-1341,
+-1162,-1119,-1242,-1432,-1560,-1582,-1544,-1515,-1524,-1563,-1609,-1629,-1608,-1569,-1559,-1592,-1630,-1648,-1676,-1760,-1898,
+-2032,-2125,-2191,-2267,-2360,-2454,-2526,-2563,-2579,-2607,-2671,-2752,-2816,-2864,-2935,-3052,-3188,-3303,-3390,-3462,-3518,
+-3551,-3570,-3596,-3630,-3655,-3661,-3660,-3667,-3683,-3704,-3726,-3750,-3778,-3814,-3865,-3930,-3998,-4044,-4036,-3957,-3824,
+-3703,-3662,-3726,-3857,-3986,-4049,-4020,-3916,-3793,-3706,-3672,-3671,-3673,-3668,-3670,-3686,-3701,-3690,-3652,-3626,-3651,
+-3718,-3771,-3772,-3741,-3730,-3758,-3805,-3845,-3869,-3880,-3886,-3904,-3936,-3965,-3970,-3969,-3993,-4041,-4083,-4105,-4137,
+-4196,-4258,-4290,-4295,-4295,-4299,-4307,-4336,-4401,-4486,-4564,-4629,-4695,-4766,-4832,-4895,-4964,-5034,-5086,-5126,-5183,
+-5268,-5357,-5425,-5478,-5538,-5604,-5667,-5725,-5784,-5844,-5898,-5947,-5995,-6043,-6084,-6117,-6153,-6194,-6236,-6272,-6306,
+-6351,-6419,-6513,-6622,-6726,-6812,-6880,-6938,-6992,-7035,-7050,-7035,-7015,-7024,-7076,-7154,-7234,-7322,-7426,-7541,-7645,
+-7734,-7822,-7904,-7964,-7999,-8034,-8082,-8127,-8156,-8179,-8211,-8243,-8259,-8267,-8288,-8319,-8342,-8356,-8376,-8403,-8424,
+-8441,-8465,-8492,-8499,-8480,-8450,-8420,-8379,-8320,-8258,-8213,-8184,-8163,-8152,-8146,-8128,-8085,-8031,-7993,-7978,-7974,
+-7969,-7950,-7907,-7841,-7770,-7712,-7664,-7610,-7551,-7497,-7448,-7392,-7325,-7257,-7192,-7124,-7054,-6982,-6896,-6784,-6665,
+-6579,-6541,-6524,-6501,-6472,-6433,-6359,-6237,-6104,-6010,-5956,-5891,-5785,-5660,-5543,-5431,-5316,-5210,-5131,-5061,-4962,
+-4830,-4692,-4572,-4472,-4386,-4317,-4258,-4172,-4018,-3804,-3589,-3436,-3356,-3292,-3177,-3003,-2823,-2697,-2620,-2538,-2423,
+-2305,-2220,-2159,-2088,-1996,-1900,-1803,-1688,-1563,-1471,-1437,-1437,-1429,-1407,-1388,-1368,-1322,-1254,-1196,-1172,-1162,
+-1145,-1122,-1087,-993,-782,-457,-87,256,562,860,1158,1419,1601,1711,1793,1887,1993,2093,2186,2288,2402,
+2498,2545,2543,2528,2532,2557,2581,2600,2644,2743,2869,2957,2978,2987,3051,3162,3246,3268,3272,3310,3363,
+3378,3357,3356,3410,3497,3574,3632,3675,3709,3733,3753,3767,3761,3738,3710,3688,3664,3644,3653,3700,3760,
+3804,3840,3895,3977,4074,4182,4299,4397,4438,4426,4415,4444,4496,4533,4547,4558,4578,4601,4633,4684,4750,
+4804,4821,4803,4773,4744,4709,4658,4597,4548,4515,4480,4421,4353,4328,4385,4500,4606,4654,4645,4614,4596,
+4612,4666,4753,4862,4993,5163,5376,5607,5814,5976,6107,6236,6369,6486,6570,6627,6673,6709,6724,6725,6737,
+6777,6833,6874,6884,6877,6878,6893,6913,6931,6947,6968,6995,7026,7058,7091,7121,7146,7170,7203,7248,7300,
+7349,7397,7444,7481,7493,7485,7476,7474,7473,7476,7492,7513,7508,7462,7412,7419,7493,7587,7666,7762,7934,
+8170,8343,8302,7995,7516,7026,6640,6384,6250,6230,6319,6482,6667,6831,6951,7014,7013,6964,6900,6859,6868,
+6926,7012,7083,7106,7075,7009,6933,6867,6819,6781,6733,6674,6631,6627,6645,6657,6668,6717,6811,6904,6942,
+6910,6828,6719,6602,6503,6440,6404,6369,6308,6204,6062,5923,5834,5795,5760,5712,5701,5777,5902,5982,5973,
+5911,5842,5770,5683,5595,5525,5465,5402,5342,5303,5285,5273,5259,5241,5215,5175,5126,5073,5013,4945,4880,
+4827,4782,4735,4686,4640,4595,4541,4476,4408,4343,4281,4221,4168,4125,4090,4059,4026,3989,3952,3924,3906,
+3888,3865,3842,3824,3808,3790,3766,3733,3690,3644,3608,3568,3501,3419,3373,3385,3403,3361,3275,3221,3235,
+3267,3255,3195,3119,3040,2953,2873,2818,2781,2741,2694,2655,2631,2608,2576,2543,2514,2485,2450,2413,2382,
+2358,2335,2310,2281,2250,2217,2185,2155,2127,2104,2085,2069,2054,2045,2042,2034,2014,1994,1994,2013,2030,
+2022,1992,1955,1921,1889,1855,1822,1794,1772,1752,1731,1711,1703,1710,1721,1719,1698,1673,1657,1653,1658,
+1672,1690,1698,1682,1648,1617,1590,1554,1505,1472,1471,1479,1451,1386,1338,1352,1401,1414,1360,1281,1237,
+1238,1248,1238,1211,1178,1144,1111,1086,1066,1041,1011,985,976,980,987,994,1001,1001,987,966,954,
+956,957,947,932,922,917,912,907,905,905,902,892,877,865,860,859,844,800,734,678,650,
+641,626,598,569,546,523,494,465,444,428,409,384,358,335,314,293,271,248,229,217,213,
+212,212,213,213,209,198,186,174,162,143,119,93,70,66,101,177,263,313,304,242,154,
+57,-31,-94,-122,-127,-127,-134,-146,-160,-178,-206,-244,-284,-318,-348,-380,-416,-452,-485,-518,-555,
+-592,-620,-639,-657,-683,-715,-742,-763,-780,-800,-821,-841,-864,-889,-914,-936,-955,-972,-989,-1006,-1022,
+-1037,-1052,-1067,-1082,-1096,-1110,-1124,-1140,-1156,-1167,-1173,-1176,-1181,-1192,-1208,-1226,-1241,-1253,-1264,-1274,-1281,
+-1288,-1293,-1299,-1303,-1307,-1313,-1324,-1336,-1348,-1359,-1369,-1373,-1372,-1369,-1369,-1369,-1366,-1365,-1369,-1374,-1375,
+-1373,-1372,-1372,-1372,-1371,-1372,-1373,-1367,-1355,-1344,-1337,-1329,-1318,-1310,-1306,-1298,-1283,-1266,-1254,-1247,-1239,
+-1229,-1218,-1204,-1188,-1173,-1161,-1150,-1137,-1127,-1119,-1111,-1100,-1090,-1085,-1082,-1077,-1072,-1072,-1073,-1067,-1059,
+-1055,-1057,-1059,-1059,-1061,-1065,-1068,-1070,-1077,-1087,-1096,-1101,-1108,-1122,-1136,-1147,-1154,-1162,-1171,-1182,-1199,
+-1225,-1254,-1279,-1294,-1302,-1307,-1312,-1317,-1320,-1321,-1321,-1322,-1323,-1320,-1317,-1317,-1319,-1317,-1312,-1307,-1307,
+-1309,-1311,-1313,-1318,-1322,-1323,-1321,-1318,-1316,-1315,-1316,-1314,-1308,-1299,-1294,-1290,-1283,-1271,-1258,-1250,-1241,
+-1229,-1214,-1198,-1183,-1167,-1150,-1131,-1109,-1085,-1060,-1035,-1009,-983,-960,-940,-917,-887,-854,-824,-794,-758,
+-720,-685,-653,-616,-572,-530,-495,-461,-421,-372,-322,-276,-233,-192,-150,-105,-60,-27,-9,-2,-4,
+-42,-138,-251,-277,-137,134,425,655,832,996,1157,1323,1520,1756,1965,2058,2016,1901,1747,1526,1238,
+984,889,968,1117,1239,1319,1389,1472,1575,1713,1883,2048,2159,2209,2229,2254,2292,2327,2347,2357,2380,
+2428,2478,2496,2471,2431,2405,2391,2368,2322,2263,2203,2148,2095,2038,1968,1890,1823,1781,1757,1724,1656,
+1551,1419,1282,1166,1086,1042,1017,996,975,949,911,859,798,729,648,550,447,353,274,200,127,
+56,-7,-63,-119,-179,-242,-306,-375,-454,-543,-636,-724,-805,-882,-955,-1027,-1096,-1167,-1243,-1326,-1413,
+-1498,-1574,-1637,-1691,-1740,-1787,-1829,-1863,-1891,-1917,-1940,-1957,-1970,-1980,-1987,-1994,-2005,-2022,-2040,-2051,-2058,
+-2073,-2110,-2165,-2218,-2255,-2278,-2296,-2313,-2321,-2319,-2314,-2319,-2333,-2351,-2369,-2386,-2401,-2410,-2406,-2386,-2360,
+-2347,-2354,-2367,-2358,-2312,-2243,-2176,-2116,-2054,-1987,-1919,-1854,-1784,-1703,-1610,-1507,-1399,-1301,-1226,-1180,-1147,
+-1115,-1085,-1060,-1037,-1010,-974,-926,-867,-797,-724,-662,-620,-595,-579,-557,-524,-489,-465,-456,-454,-468,
+-533,-669,-843,-986,-1049,-1044,-1022,-1017,-1029,-1040,-1042,-1040,-1042,-1046,-1041,-1016,-979,-947,-927,-914,-891,
+-857,-821,-797,-786,-781,-772,-753,-728,-703,-681,-663,-644,-622,-596,-568,-538,-508,-477,-448,-422,-400,
+-374,-341,-300,-254,-204,-149,-92,-36,15,63,109,153,199,251,305,358,408,457,508,559,609,
+660,709,755,795,834,871,903,931,959,993,1027,1059,1091,1124,1154,1179,1209,1256,1316,1375,1418,
+1447,1469,1488,1505,1519,1526,1528,1531,1540,1554,1564,1567,1567,1566,1564,1556,1546,1539,1533,1526,1516,
+1507,1498,1490,1486,1488,1495,1500,1497,1490,1484,1481,1483,1489,1503,1520,1533,1536,1531,1527,1526,1529,
+1533,1539,1544,1543,1540,1541,1544,1538,1521,1503,1488,1461,1406,1346,1305,1287,1307,1312,1254,1156,1079,
+1051,1042,1022,993,973,964,951,930,911,900,892,884,878,876,871,862,853,848,844,839,835,
+836,839,841,841,841,843,844,847,852,860,870,882,900,924,954,990,1028,1058,1078,1093,1113,
+1148,1197,1258,1321,1369,1382,1359,1315,1271,1241,1222,1204,1182,1148,1089,1001,896,802,742,711,683,
+642,593,552,525,497,457,403,341,273,200,126,53,-17,-85,-145,-197,-247,-296,-342,-389,-441,
+-497,-547,-587,-624,-664,-696,-705,-700,-715,-781,-895,-1022,-1129,-1209,-1277,-1341,-1379,-1358,-1280,-1191,-1139,
+-1136,-1158,-1181,-1190,-1167,-1100,-1025,-1018,-1139,-1350,-1528,-1552,-1403,-1192,-1085,-1169,-1385,-1585,-1660,-1618,-1545,
+-1519,-1556,-1619,-1657,-1638,-1579,-1522,-1493,-1486,-1503,-1575,-1720,-1903,-2055,-2144,-2197,-2255,-2332,-2412,-2477,-2523,
+-2562,-2610,-2675,-2744,-2801,-2857,-2937,-3052,-3176,-3283,-3368,-3437,-3486,-3514,-3534,-3562,-3595,-3618,-3627,-3632,-3640,
+-3647,-3654,-3667,-3692,-3726,-3767,-3816,-3872,-3929,-3963,-3936,-3823,-3663,-3551,-3567,-3703,-3874,-3989,-4012,-3960,-3862,
+-3752,-3663,-3616,-3609,-3619,-3627,-3637,-3661,-3692,-3699,-3664,-3619,-3626,-3695,-3765,-3768,-3709,-3661,-3677,-3738,-3789,
+-3806,-3803,-3811,-3839,-3872,-3885,-3878,-3885,-3934,-4007,-4059,-4074,-4085,-4124,-4185,-4240,-4273,-4282,-4272,-4257,-4265,
+-4309,-4375,-4445,-4518,-4598,-4676,-4740,-4800,-4870,-4940,-4991,-5031,-5091,-5179,-5269,-5336,-5391,-5452,-5520,-5587,-5649,
+-5713,-5774,-5826,-5871,-5915,-5955,-5993,-6032,-6077,-6120,-6152,-6179,-6217,-6278,-6361,-6458,-6557,-6648,-6727,-6792,-6844,
+-6884,-6912,-6928,-6936,-6945,-6972,-7026,-7101,-7188,-7281,-7385,-7491,-7588,-7671,-7750,-7823,-7877,-7913,-7945,-7984,-8023,
+-8052,-8082,-8119,-8151,-8168,-8182,-8211,-8245,-8267,-8282,-8305,-8334,-8354,-8366,-8385,-8408,-8415,-8393,-8359,-8327,-8289,
+-8237,-8185,-8150,-8129,-8113,-8099,-8087,-8067,-8031,-7990,-7961,-7946,-7936,-7923,-7901,-7857,-7791,-7721,-7665,-7619,-7569,
+-7511,-7458,-7411,-7357,-7294,-7229,-7166,-7101,-7034,-6960,-6869,-6752,-6634,-6559,-6533,-6524,-6503,-6471,-6428,-6346,-6216,
+-6081,-5997,-5959,-5906,-5806,-5685,-5575,-5470,-5355,-5246,-5166,-5092,-4984,-4836,-4686,-4569,-4480,-4402,-4336,-4279,-4201,
+-4067,-3879,-3684,-3531,-3426,-3330,-3203,-3041,-2885,-2775,-2704,-2628,-2526,-2418,-2333,-2266,-2187,-2087,-1980,-1872,-1753,
+-1628,-1526,-1467,-1431,-1392,-1350,-1321,-1303,-1278,-1242,-1215,-1206,-1203,-1192,-1168,-1125,-1037,-884,-680,-463,-256,
+-47,190,463,749,1012,1236,1427,1602,1764,1905,2023,2133,2246,2352,2428,2472,2500,2534,2567,2587,2602,
+2654,2773,2922,3021,3044,3053,3124,3242,3320,3318,3301,3336,3399,3415,3371,3331,3346,3400,3452,3497,3547,
+3597,3635,3661,3679,3690,3694,3705,3727,3744,3748,3758,3789,3819,3818,3796,3793,3829,3896,3993,4126,4266,
+4351,4356,4331,4347,4414,4485,4525,4540,4551,4565,4582,4615,4671,4731,4761,4747,4700,4637,4558,4460,4352,
+4265,4217,4194,4171,4152,4172,4255,4378,4488,4550,4575,4593,4622,4667,4733,4828,4952,5104,5284,5492,5709,
+5899,6038,6136,6224,6317,6410,6494,6571,6644,6699,6719,6715,6720,6754,6802,6832,6835,6829,6834,6851,6868,
+6884,6906,6940,6981,7019,7049,7074,7099,7122,7145,7175,7217,7268,7320,7372,7423,7465,7486,7487,7477,7464,
+7449,7442,7453,7469,7460,7418,7379,7390,7447,7503,7544,7629,7833,8143,8422,8501,8307,7917,7484,7129,6899,
+6787,6770,6824,6921,7041,7172,7295,7369,7364,7281,7152,7019,6917,6873,6893,6957,7025,7062,7054,7012,6964,
+6942,6950,6959,6938,6892,6843,6804,6776,6770,6806,6874,6934,6951,6917,6836,6708,6547,6391,6292,6277,6334,
+6402,6399,6294,6145,6035,5966,5862,5695,5560,5572,5718,5869,5926,5904,5855,5801,5741,5685,5643,5600,5541,
+5472,5410,5353,5292,5233,5186,5145,5105,5072,5052,5033,4997,4949,4902,4862,4818,4769,4723,4676,4619,4550,
+4480,4417,4357,4293,4229,4175,4137,4109,4082,4052,4021,3992,3965,3940,3919,3906,3891,3864,3830,3798,3767,
+3724,3676,3640,3616,3572,3498,3435,3420,3425,3396,3335,3299,3308,3316,3274,3198,3130,3073,3005,2925,2860,
+2820,2785,2743,2706,2683,2666,2642,2614,2589,2561,2524,2480,2442,2412,2387,2358,2325,2287,2250,2219,2194,
+2171,2144,2111,2084,2079,2105,2144,2159,2131,2078,2041,2038,2051,2050,2027,1992,1956,1921,1888,1858,1834,
+1812,1792,1770,1748,1728,1719,1718,1716,1705,1686,1667,1654,1651,1657,1669,1673,1658,1629,1597,1567,1530,
+1493,1475,1483,1488,1456,1391,1347,1364,1416,1433,1381,1296,1239,1229,1241,1240,1219,1184,1139,1089,1044,
+1012,992,974,958,947,942,944,951,957,952,935,920,919,929,933,923,905,891,885,886,887,
+886,882,881,880,869,845,827,832,843,822,756,677,629,615,606,584,556,532,507,478,447,
+421,399,376,352,331,310,288,265,241,217,194,178,172,172,173,174,176,172,162,150,136,
+119,97,73,51,34,38,89,188,284,315,263,170,83,12,-54,-113,-148,-156,-152,-155,-167,
+-180,-195,-219,-254,-292,-327,-360,-394,-430,-466,-497,-528,-561,-596,-624,-643,-662,-690,-724,-754,-776,
+-793,-810,-828,-848,-868,-889,-911,-932,-952,-971,-988,-1005,-1019,-1032,-1044,-1056,-1070,-1084,-1099,-1114,-1133,
+-1152,-1167,-1176,-1179,-1183,-1192,-1207,-1220,-1228,-1234,-1242,-1254,-1265,-1272,-1276,-1279,-1283,-1286,-1292,-1300,-1311,
+-1323,-1335,-1346,-1351,-1351,-1349,-1349,-1347,-1343,-1341,-1343,-1347,-1347,-1343,-1340,-1339,-1338,-1337,-1339,-1341,-1337,
+-1327,-1316,-1308,-1301,-1293,-1287,-1283,-1275,-1259,-1241,-1226,-1214,-1199,-1184,-1170,-1157,-1144,-1132,-1121,-1111,-1101,
+-1094,-1090,-1084,-1072,-1061,-1055,-1052,-1047,-1042,-1040,-1040,-1036,-1029,-1025,-1025,-1026,-1028,-1033,-1040,-1044,-1046,
+-1051,-1062,-1072,-1077,-1082,-1093,-1108,-1122,-1133,-1142,-1151,-1162,-1180,-1209,-1241,-1268,-1283,-1291,-1297,-1305,-1313,
+-1315,-1312,-1309,-1310,-1312,-1311,-1310,-1311,-1312,-1310,-1303,-1299,-1298,-1299,-1300,-1299,-1300,-1301,-1302,-1303,-1304,
+-1302,-1300,-1300,-1299,-1294,-1287,-1281,-1277,-1269,-1256,-1246,-1240,-1234,-1221,-1205,-1189,-1174,-1159,-1144,-1127,-1105,
+-1078,-1052,-1030,-1007,-981,-955,-935,-915,-887,-854,-825,-797,-763,-723,-687,-658,-625,-581,-537,-501,-469,
+-430,-383,-335,-288,-239,-195,-157,-119,-73,-26,3,12,10,-20,-107,-229,-288,-185,67,370,637,
+854,1034,1175,1295,1460,1705,1945,2046,1977,1830,1691,1540,1336,1129,1031,1078,1192,1282,1335,1387,1460,
+1558,1691,1867,2056,2203,2273,2283,2278,2289,2313,2336,2356,2392,2458,2529,2561,2536,2482,2442,2424,2407,
+2369,2310,2242,2174,2114,2063,2012,1953,1889,1835,1794,1751,1684,1583,1454,1320,1207,1133,1093,1067,1043,
+1020,1001,978,940,882,811,731,640,540,442,354,277,204,131,61,-3,-67,-133,-201,-268,-336,
+-413,-499,-588,-670,-748,-826,-902,-975,-1044,-1113,-1187,-1266,-1351,-1436,-1515,-1581,-1634,-1680,-1723,-1765,-1804,
+-1840,-1871,-1893,-1906,-1915,-1925,-1935,-1943,-1955,-1973,-1994,-2008,-2016,-2040,-2096,-2176,-2253,-2301,-2321,-2327,-2328,
+-2320,-2306,-2295,-2294,-2299,-2303,-2305,-2310,-2318,-2322,-2317,-2299,-2278,-2263,-2262,-2264,-2252,-2218,-2173,-2128,-2076,
+-2006,-1919,-1832,-1759,-1693,-1617,-1525,-1424,-1329,-1253,-1203,-1171,-1141,-1107,-1074,-1049,-1025,-991,-946,-895,-844,
+-793,-741,-694,-656,-631,-612,-589,-560,-531,-514,-511,-515,-527,-571,-671,-814,-954,-1043,-1075,-1074,-1068,
+-1066,-1065,-1062,-1063,-1072,-1081,-1077,-1051,-1010,-971,-943,-922,-896,-862,-828,-805,-796,-792,-782,-765,-746,
+-728,-712,-694,-673,-650,-623,-591,-559,-529,-501,-474,-449,-429,-405,-372,-331,-287,-243,-195,-143,-90,
+-37,13,62,107,153,205,263,320,375,430,485,538,589,642,696,747,790,831,871,908,939,
+970,1005,1037,1062,1085,1112,1143,1173,1211,1265,1331,1391,1433,1461,1483,1499,1507,1509,1508,1509,1510,
+1513,1519,1523,1522,1517,1512,1508,1501,1494,1490,1490,1488,1482,1476,1471,1468,1467,1470,1477,1481,1478,
+1469,1463,1462,1465,1472,1485,1501,1509,1507,1500,1499,1504,1508,1511,1516,1525,1528,1525,1520,1516,1503,
+1480,1459,1444,1417,1363,1305,1262,1238,1247,1243,1189,1106,1047,1028,1021,1000,975,963,960,950,931,
+914,902,893,887,888,891,890,881,874,869,866,860,857,861,867,869,870,870,873,878,886,
+897,906,916,928,945,962,978,997,1022,1047,1063,1075,1096,1141,1210,1294,1379,1445,1471,1446,1386,
+1323,1280,1258,1240,1216,1180,1124,1038,928,825,762,743,734,705,659,617,589,564,527,473,411,
+345,275,203,130,58,-8,-67,-119,-168,-217,-266,-316,-368,-420,-465,-502,-542,-594,-642,-667,-672,
+-690,-752,-858,-976,-1072,-1146,-1213,-1274,-1298,-1252,-1149,-1054,-1021,-1048,-1090,-1121,-1140,-1152,-1149,-1138,-1153,
+-1234,-1376,-1513,-1553,-1452,-1260,-1110,-1124,-1305,-1525,-1645,-1627,-1548,-1507,-1537,-1605,-1654,-1648,-1589,-1509,-1446,
+-1429,-1478,-1594,-1757,-1920,-2039,-2110,-2162,-2219,-2285,-2350,-2414,-2475,-2533,-2589,-2652,-2724,-2803,-2889,-2982,-3079,
+-3173,-3260,-3337,-3400,-3440,-3462,-3485,-3518,-3552,-3577,-3591,-3602,-3607,-3606,-3603,-3612,-3636,-3672,-3711,-3752,-3797,
+-3849,-3885,-3854,-3721,-3539,-3439,-3517,-3734,-3947,-4036,-3994,-3888,-3779,-3688,-3619,-3580,-3577,-3598,-3621,-3636,-3650,
+-3662,-3653,-3607,-3558,-3569,-3657,-3752,-3767,-3695,-3620,-3617,-3677,-3735,-3750,-3741,-3744,-3771,-3802,-3810,-3800,-3806,
+-3854,-3931,-3992,-4015,-4025,-4058,-4119,-4187,-4233,-4246,-4231,-4209,-4206,-4230,-4271,-4325,-4400,-4494,-4582,-4647,-4702,
+-4766,-4833,-4887,-4935,-5004,-5095,-5181,-5247,-5303,-5366,-5436,-5505,-5573,-5639,-5698,-5746,-5789,-5829,-5866,-5902,-5946,
+-5998,-6043,-6072,-6100,-6150,-6229,-6319,-6404,-6482,-6557,-6631,-6699,-6748,-6773,-6783,-6797,-6825,-6863,-6905,-6959,-7031,
+-7118,-7214,-7313,-7414,-7509,-7596,-7673,-7740,-7788,-7819,-7847,-7881,-7918,-7953,-7990,-8030,-8063,-8084,-8106,-8138,-8171,
+-8191,-8206,-8230,-8259,-8274,-8278,-8288,-8304,-8304,-8276,-8238,-8205,-8174,-8135,-8097,-8070,-8051,-8029,-8007,-7990,-7974,
+-7953,-7928,-7908,-7891,-7871,-7849,-7822,-7780,-7719,-7655,-7603,-7562,-7518,-7466,-7417,-7370,-7317,-7255,-7193,-7133,-7073,
+-7009,-6936,-6840,-6718,-6602,-6536,-6523,-6524,-6507,-6473,-6424,-6333,-6195,-6061,-5990,-5968,-5924,-5822,-5695,-5587,-5494,
+-5392,-5287,-5195,-5104,-4980,-4828,-4686,-4581,-4498,-4416,-4340,-4280,-4216,-4113,-3961,-3786,-3625,-3486,-3357,-3219,-3074,
+-2942,-2845,-2776,-2706,-2615,-2515,-2428,-2353,-2269,-2168,-2055,-1938,-1815,-1692,-1588,-1508,-1437,-1361,-1291,-1243,-1213,
+-1185,-1159,-1151,-1167,-1196,-1217,-1209,-1158,-1056,-919,-777,-652,-540,-421,-273,-83,153,419,683,926,1150,
+1360,1550,1711,1849,1981,2110,2221,2306,2371,2427,2471,2498,2522,2584,2707,2857,2963,3003,3032,3116,3237,
+3316,3325,3327,3387,3475,3508,3469,3418,3407,3427,3456,3505,3580,3657,3703,3722,3740,3768,3798,3831,3870,
+3904,3927,3953,3995,4028,4017,3965,3918,3908,3933,3989,4084,4197,4261,4240,4183,4180,4256,4357,4426,4461,
+4492,4525,4550,4575,4618,4674,4708,4689,4614,4499,4354,4186,4020,3899,3853,3872,3922,3975,4035,4114,4210,
+4307,4400,4492,4586,4673,4747,4824,4927,5066,5230,5409,5598,5790,5958,6078,6153,6209,6271,6345,6426,6514,
+6601,6668,6698,6702,6711,6739,6772,6791,6795,6798,6808,6821,6835,6857,6895,6948,7001,7040,7061,7073,7085,
+7100,7119,7144,7180,7228,7283,7340,7395,7441,7470,7480,7475,7458,7438,7429,7440,7456,7450,7413,7377,7377,
+7407,7427,7434,7499,7704,8038,8372,8539,8454,8171,7820,7522,7339,7271,7287,7338,7397,7471,7574,7690,7765,
+7752,7654,7499,7317,7134,6991,6919,6920,6958,6995,7013,7015,7018,7038,7075,7105,7102,7064,7010,6956,6910,
+6884,6888,6917,6950,6966,6952,6889,6755,6554,6336,6173,6130,6218,6363,6443,6389,6262,6174,6130,6020,5779,
+5516,5406,5499,5682,5828,5897,5913,5898,5866,5837,5811,5766,5688,5596,5508,5420,5325,5238,5172,5120,5072,
+5040,5037,5049,5047,5022,4985,4942,4889,4831,4784,4747,4700,4633,4558,4492,4435,4377,4314,4254,4204,4165,
+4134,4110,4086,4060,4026,3992,3969,3958,3943,3911,3869,3836,3812,3774,3719,3675,3656,3634,3580,3514,3478,
+3469,3446,3400,3366,3359,3345,3295,3232,3192,3161,3099,3004,2920,2872,2843,2809,2772,2746,2729,2709,2684,
+2660,2632,2593,2546,2501,2464,2433,2400,2362,2323,2285,2256,2237,2224,2205,2173,2139,2132,2169,2229,2263,
+2235,2162,2091,2056,2050,2051,2042,2023,1995,1961,1925,1894,1866,1840,1817,1797,1776,1751,1727,1710,1703,
+1697,1688,1674,1658,1646,1640,1638,1635,1622,1597,1563,1525,1492,1474,1478,1496,1502,1474,1421,1380,1383,
+1413,1423,1381,1309,1253,1235,1238,1233,1209,1171,1121,1061,1006,978,985,1006,1009,983,943,919,918,
+924,915,894,882,888,900,901,888,869,855,849,853,860,857,847,843,850,847,819,787,788,
+816,821,768,686,624,599,588,570,546,523,497,466,434,405,377,349,325,307,288,265,239,
+215,189,161,139,130,128,129,131,133,130,121,110,97,80,56,34,16,1,2,47,139,
+227,245,181,94,36,2,-42,-106,-158,-178,-178,-179,-189,-201,-216,-238,-268,-304,-339,-373,-408,
+-443,-476,-506,-534,-564,-596,-625,-649,-672,-701,-736,-767,-791,-808,-825,-842,-861,-878,-895,-911,-929,
+-948,-968,-986,-1003,-1017,-1028,-1037,-1046,-1057,-1069,-1082,-1098,-1119,-1143,-1165,-1177,-1183,-1186,-1191,-1201,-1209,
+-1212,-1214,-1219,-1231,-1242,-1248,-1250,-1252,-1256,-1261,-1265,-1273,-1283,-1294,-1306,-1318,-1326,-1328,-1328,-1328,-1326,
+-1323,-1321,-1322,-1324,-1321,-1315,-1311,-1310,-1307,-1303,-1303,-1305,-1303,-1295,-1285,-1276,-1269,-1263,-1259,-1255,-1245,
+-1228,-1210,-1195,-1181,-1164,-1145,-1128,-1115,-1104,-1094,-1086,-1078,-1069,-1063,-1060,-1055,-1044,-1032,-1024,-1021,-1017,
+-1011,-1009,-1009,-1007,-1002,-998,-997,-997,-1000,-1008,-1017,-1023,-1025,-1030,-1040,-1051,-1057,-1062,-1070,-1082,-1097,
+-1110,-1120,-1129,-1142,-1162,-1191,-1222,-1248,-1261,-1267,-1273,-1282,-1290,-1294,-1293,-1293,-1296,-1299,-1299,-1297,-1299,
+-1302,-1301,-1296,-1291,-1290,-1291,-1291,-1289,-1286,-1283,-1283,-1287,-1291,-1290,-1285,-1282,-1281,-1277,-1271,-1266,-1262,
+-1255,-1243,-1234,-1229,-1222,-1208,-1191,-1176,-1162,-1148,-1135,-1123,-1103,-1075,-1047,-1027,-1008,-982,-954,-931,-911,
+-885,-852,-821,-794,-761,-721,-684,-655,-625,-585,-542,-506,-472,-434,-392,-352,-306,-250,-196,-156,-123,
+-79,-27,9,22,22,3,-68,-189,-273,-213,9,315,616,875,1078,1213,1307,1440,1655,1871,1953,
+1869,1724,1616,1526,1391,1236,1152,1179,1260,1324,1367,1422,1501,1594,1711,1874,2067,2237,2331,2346,2325,
+2311,2320,2341,2368,2413,2486,2567,2612,2597,2543,2493,2466,2447,2413,2356,2282,2204,2138,2093,2059,2014,
+1954,1889,1833,1781,1712,1610,1483,1354,1252,1188,1149,1117,1082,1056,1044,1035,1006,950,880,808,729,
+636,533,437,356,283,208,130,56,-10,-77,-147,-219,-293,-371,-453,-533,-609,-686,-769,-850,-927,
+-999,-1074,-1153,-1230,-1304,-1378,-1451,-1517,-1573,-1621,-1664,-1703,-1742,-1782,-1818,-1844,-1859,-1867,-1876,-1887,-1896,
+-1909,-1929,-1952,-1968,-1979,-2010,-2083,-2190,-2292,-2353,-2367,-2353,-2329,-2304,-2281,-2268,-2264,-2260,-2251,-2240,-2234,
+-2233,-2230,-2221,-2207,-2192,-2178,-2168,-2159,-2146,-2126,-2104,-2077,-2031,-1951,-1844,-1737,-1652,-1588,-1524,-1449,-1367,
+-1294,-1239,-1203,-1175,-1146,-1115,-1086,-1062,-1034,-992,-940,-890,-853,-824,-792,-751,-706,-667,-638,-615,-591,
+-568,-553,-548,-553,-570,-613,-698,-822,-953,-1056,-1111,-1127,-1122,-1108,-1092,-1080,-1078,-1085,-1093,-1089,-1067,
+-1032,-991,-955,-924,-894,-864,-836,-815,-805,-798,-788,-775,-763,-753,-739,-717,-692,-667,-639,-606,-572,
+-543,-518,-492,-468,-447,-424,-390,-347,-303,-264,-225,-182,-132,-76,-17,38,87,135,187,243,301,
+358,418,479,535,588,644,701,753,796,838,879,918,950,982,1016,1047,1069,1088,1113,1144,1177,
+1215,1266,1325,1376,1413,1443,1468,1485,1487,1480,1477,1479,1481,1481,1483,1484,1481,1474,1467,1463,1459,
+1457,1457,1458,1457,1452,1447,1446,1447,1451,1456,1464,1469,1466,1458,1454,1455,1460,1468,1479,1493,1497,
+1490,1478,1476,1481,1485,1485,1491,1502,1510,1506,1497,1484,1464,1435,1408,1389,1364,1316,1262,1224,1189,
+1175,1155,1106,1049,1017,1013,1008,985,960,949,946,937,923,911,904,899,898,904,913,912,903,
+896,893,891,887,886,891,897,900,902,904,907,913,924,939,953,966,981,999,1013,1018,1023,
+1040,1067,1089,1103,1125,1174,1254,1348,1438,1506,1534,1510,1447,1380,1336,1314,1296,1266,1225,1170,1089,
+981,875,808,789,786,765,722,680,652,627,590,539,479,414,344,271,200,133,69,10,-42,
+-93,-144,-194,-244,-294,-343,-389,-433,-480,-533,-583,-615,-638,-672,-739,-835,-938,-1024,-1091,-1149,-1192,
+-1193,-1129,-1022,-939,-929,-980,-1041,-1086,-1125,-1173,-1221,-1256,-1285,-1328,-1397,-1473,-1511,-1460,-1315,-1158,-1105,
+-1207,-1384,-1509,-1524,-1481,-1460,-1492,-1548,-1589,-1591,-1550,-1484,-1438,-1458,-1559,-1706,-1843,-1936,-1994,-2048,-2115,
+-2188,-2253,-2313,-2377,-2445,-2507,-2558,-2614,-2696,-2809,-2935,-3046,-3130,-3193,-3254,-3318,-3371,-3400,-3415,-3437,-3473,
+-3509,-3533,-3548,-3556,-3559,-3555,-3555,-3564,-3584,-3613,-3647,-3687,-3738,-3802,-3854,-3825,-3670,-3450,-3326,-3420,-3681,
+-3930,-4017,-3936,-3788,-3669,-3602,-3568,-3552,-3554,-3578,-3609,-3627,-3618,-3588,-3540,-3482,-3447,-3481,-3589,-3706,-3744,
+-3688,-3613,-3595,-3634,-3678,-3690,-3681,-3683,-3707,-3739,-3754,-3751,-3751,-3784,-3845,-3905,-3940,-3961,-3999,-4061,-4129,
+-4175,-4188,-4178,-4165,-4162,-4168,-4179,-4209,-4279,-4384,-4488,-4563,-4617,-4671,-4729,-4785,-4845,-4922,-5012,-5095,-5160,
+-5220,-5286,-5355,-5423,-5491,-5557,-5613,-5656,-5696,-5737,-5774,-5809,-5853,-5909,-5960,-5998,-6038,-6100,-6183,-6264,-6330,
+-6389,-6454,-6527,-6595,-6639,-6654,-6656,-6673,-6716,-6772,-6824,-6877,-6944,-7028,-7120,-7215,-7313,-7413,-7508,-7590,-7653,
+-7695,-7722,-7748,-7780,-7817,-7856,-7897,-7938,-7972,-8000,-8029,-8064,-8093,-8110,-8126,-8151,-8176,-8183,-8180,-8183,-8193,
+-8185,-8152,-8113,-8084,-8060,-8032,-8003,-7978,-7953,-7921,-7891,-7876,-7870,-7864,-7853,-7838,-7818,-7792,-7762,-7729,-7687,
+-7633,-7576,-7531,-7494,-7455,-7410,-7365,-7318,-7262,-7201,-7142,-7088,-7031,-6972,-6902,-6806,-6683,-6570,-6512,-6511,-6522,
+-6510,-6477,-6421,-6321,-6175,-6042,-5980,-5967,-5926,-5820,-5691,-5589,-5511,-5425,-5322,-5213,-5098,-4965,-4828,-4712,-4620,
+-4527,-4423,-4330,-4270,-4223,-4148,-4023,-3861,-3691,-3531,-3384,-3245,-3114,-3000,-2914,-2848,-2782,-2697,-2601,-2507,-2421,
+-2331,-2227,-2111,-1988,-1862,-1744,-1644,-1556,-1461,-1358,-1269,-1209,-1167,-1123,-1080,-1057,-1069,-1113,-1166,-1195,-1168,
+-1077,-947,-819,-715,-630,-553,-474,-370,-221,-29,177,377,579,794,1012,1210,1386,1557,1729,1886,2010,
+2098,2164,2213,2253,2299,2377,2497,2633,2737,2796,2851,2947,3067,3153,3191,3234,3328,3438,3494,3485,3461,
+3459,3476,3513,3593,3711,3808,3834,3813,3801,3822,3856,3886,3919,3959,3999,4047,4107,4151,4143,4085,4027,
+4003,4005,4017,4042,4075,4074,4012,3932,3918,3992,4101,4187,4254,4331,4418,4486,4529,4571,4619,4646,4612,
+4508,4344,4136,3907,3696,3555,3521,3586,3704,3830,3934,4020,4103,4205,4335,4487,4638,4764,4863,4958,5075,
+5221,5379,5532,5684,5837,5977,6081,6147,6194,6247,6310,6382,6464,6549,6620,6663,6684,6700,6719,6734,6741,
+6749,6763,6779,6794,6813,6849,6902,6961,7011,7044,7058,7060,7061,7070,7089,7115,7149,7194,7248,7307,7366,
+7416,7451,7468,7468,7455,7437,7428,7439,7461,7468,7446,7408,7381,7365,7341,7319,7364,7550,7873,8221,8446,
+8462,8293,8033,7782,7611,7548,7568,7622,7677,7742,7836,7936,7986,7955,7863,7742,7598,7433,7275,7158,7086,
+7032,6986,6967,6994,7061,7134,7184,7195,7171,7130,7089,7050,7006,6963,6934,6924,6932,6949,6957,6923,6813,
+6626,6398,6199,6104,6149,6283,6376,6341,6233,6177,6193,6153,5943,5630,5402,5373,5507,5698,5865,5970,6005,
+5995,5976,5950,5888,5782,5664,5565,5479,5394,5318,5265,5220,5167,5120,5105,5115,5122,5108,5075,5024,4952,
+4877,4828,4807,4783,4729,4650,4572,4510,4458,4406,4348,4286,4229,4186,4158,4137,4113,4081,4044,4015,3997,
+3981,3952,3917,3891,3875,3844,3788,3733,3705,3688,3647,3586,3540,3518,3493,3451,3413,3394,3372,3330,3289,
+3271,3254,3194,3090,2995,2943,2918,2885,2842,2806,2782,2761,2737,2713,2687,2652,2608,2564,2524,2487,2447,
+2406,2368,2334,2307,2291,2284,2277,2254,2221,2205,2229,2281,2314,2289,2217,2139,2088,2066,2059,2056,2049,
+2031,2003,1969,1936,1903,1867,1834,1807,1785,1759,1730,1705,1691,1685,1681,1671,1656,1639,1622,1608,1596,
+1583,1561,1524,1483,1458,1462,1487,1511,1514,1490,1449,1410,1385,1378,1370,1345,1302,1262,1241,1231,1211,
+1176,1132,1084,1027,980,974,1027,1101,1129,1079,988,920,903,906,894,867,852,859,869,864,849,
+834,823,818,821,828,823,806,798,809,816,793,757,749,778,797,765,694,628,591,569,550,
+531,513,488,457,425,397,366,333,308,289,267,239,211,187,161,131,106,94,90,88,89,
+91,88,78,66,56,42,22,2,-12,-29,-41,-19,53,142,187,170,131,104,76,13,-80,
+-161,-200,-207,-206,-212,-222,-235,-256,-284,-317,-351,-386,-420,-452,-483,-512,-539,-567,-597,-627,-657,
+-685,-716,-748,-779,-802,-820,-836,-853,-871,-887,-900,-912,-926,-944,-963,-982,-999,-1013,-1024,-1033,-1040,
+-1049,-1058,-1067,-1080,-1101,-1128,-1154,-1171,-1179,-1181,-1183,-1187,-1192,-1193,-1193,-1196,-1204,-1213,-1215,-1215,-1216,
+-1221,-1227,-1232,-1239,-1249,-1261,-1272,-1284,-1293,-1299,-1302,-1305,-1306,-1306,-1304,-1303,-1302,-1298,-1292,-1289,-1286,
+-1280,-1272,-1268,-1268,-1267,-1262,-1253,-1244,-1236,-1229,-1223,-1217,-1205,-1188,-1170,-1156,-1143,-1127,-1109,-1092,-1077,
+-1065,-1055,-1050,-1044,-1036,-1028,-1024,-1020,-1012,-1001,-992,-988,-984,-980,-978,-979,-978,-975,-972,-971,-972,
+-975,-981,-990,-997,-1002,-1008,-1018,-1030,-1039,-1046,-1053,-1064,-1076,-1089,-1099,-1110,-1125,-1147,-1175,-1203,-1226,
+-1239,-1245,-1249,-1254,-1260,-1266,-1270,-1277,-1285,-1289,-1287,-1283,-1283,-1287,-1289,-1288,-1286,-1286,-1287,-1287,-1286,
+-1281,-1274,-1271,-1274,-1278,-1276,-1269,-1263,-1261,-1258,-1253,-1248,-1245,-1240,-1231,-1225,-1219,-1209,-1191,-1174,-1162,
+-1150,-1135,-1123,-1113,-1097,-1071,-1042,-1021,-1004,-981,-951,-926,-906,-880,-848,-816,-788,-756,-718,-682,-652,
+-622,-585,-547,-512,-477,-436,-396,-361,-320,-263,-202,-156,-122,-79,-28,9,22,27,24,-22,-129,
+-234,-232,-69,213,535,836,1075,1231,1327,1435,1595,1753,1814,1761,1672,1610,1552,1455,1340,1277,1289,
+1337,1383,1435,1511,1596,1670,1751,1880,2060,2242,2365,2407,2392,2367,2360,2376,2406,2450,2513,2586,2636,
+2638,2601,2557,2525,2498,2457,2396,2320,2243,2181,2141,2112,2070,2009,1941,1882,1830,1760,1655,1528,1406,
+1316,1260,1218,1173,1126,1096,1091,1092,1071,1018,950,883,813,724,617,514,428,354,275,193,118,
+53,-10,-83,-165,-249,-331,-410,-484,-554,-632,-717,-802,-878,-950,-1026,-1106,-1183,-1253,-1319,-1384,-1447,
+-1504,-1555,-1602,-1642,-1679,-1716,-1753,-1782,-1799,-1809,-1819,-1829,-1839,-1852,-1874,-1901,-1922,-1939,-1976,-2057,-2177,
+-2293,-2361,-2369,-2338,-2296,-2261,-2237,-2225,-2218,-2209,-2194,-2179,-2170,-2165,-2155,-2139,-2123,-2109,-2097,-2083,-2069,
+-2058,-2045,-2029,-2003,-1953,-1866,-1749,-1632,-1545,-1491,-1452,-1406,-1355,-1306,-1266,-1233,-1204,-1174,-1144,-1114,-1085,
+-1054,-1015,-968,-924,-894,-876,-852,-810,-753,-699,-662,-642,-629,-612,-590,-572,-573,-601,-665,-763,-882,
+-998,-1086,-1136,-1152,-1147,-1130,-1110,-1092,-1083,-1082,-1081,-1075,-1060,-1037,-1006,-969,-933,-903,-877,-852,-831,
+-816,-805,-794,-783,-775,-769,-753,-726,-696,-669,-642,-611,-579,-553,-529,-503,-475,-450,-423,-387,-342,
+-299,-263,-230,-192,-145,-88,-24,40,98,150,201,253,306,362,423,486,542,593,644,698,747,
+788,829,873,914,948,980,1013,1044,1069,1090,1118,1150,1182,1215,1256,1302,1344,1377,1410,1442,1459,
+1457,1448,1445,1450,1452,1451,1449,1448,1444,1435,1427,1426,1430,1434,1436,1436,1431,1425,1422,1426,1433,
+1441,1449,1456,1460,1456,1448,1442,1443,1448,1455,1467,1481,1486,1477,1462,1455,1457,1459,1459,1462,1472,
+1479,1476,1466,1450,1426,1392,1361,1341,1319,1277,1224,1191,1148,1118,1085,1041,1003,993,1002,1000,979,
+956,944,936,925,913,908,908,908,911,920,930,929,921,916,917,918,916,916,921,927,932,
+937,944,949,954,964,982,1001,1018,1034,1051,1062,1062,1063,1082,1117,1150,1170,1193,1243,1326,1419,
+1499,1551,1568,1547,1499,1449,1417,1402,1384,1349,1301,1242,1166,1068,968,899,870,855,827,783,741,
+710,681,643,595,539,476,406,333,265,202,143,86,32,-20,-71,-122,-172,-223,-279,-339,-400,
+-458,-509,-550,-585,-623,-674,-743,-826,-912,-985,-1034,-1063,-1074,-1058,-999,-914,-851,-852,-911,-991,-1064,
+-1136,-1213,-1282,-1332,-1362,-1383,-1404,-1426,-1438,-1408,-1313,-1184,-1106,-1137,-1243,-1332,-1356,-1351,-1367,-1409,-1449,
+-1465,-1459,-1434,-1406,-1413,-1499,-1657,-1818,-1914,-1941,-1957,-2012,-2105,-2197,-2265,-2318,-2374,-2433,-2482,-2521,-2571,
+-2661,-2800,-2960,-3098,-3184,-3233,-3274,-3321,-3358,-3372,-3376,-3394,-3427,-3460,-3482,-3493,-3498,-3500,-3502,-3511,-3522,
+-3533,-3546,-3575,-3623,-3686,-3761,-3819,-3797,-3646,-3421,-3279,-3347,-3590,-3834,-3921,-3834,-3675,-3556,-3514,-3518,-3522,
+-3516,-3522,-3550,-3572,-3552,-3487,-3410,-3357,-3351,-3405,-3511,-3623,-3679,-3662,-3616,-3591,-3598,-3611,-3612,-3611,-3623,
+-3652,-3685,-3708,-3714,-3716,-3736,-3783,-3836,-3874,-3903,-3944,-4006,-4069,-4111,-4126,-4128,-4132,-4133,-4122,-4103,-4107,
+-4168,-4282,-4404,-4495,-4553,-4599,-4648,-4703,-4767,-4844,-4929,-5006,-5074,-5142,-5210,-5275,-5339,-5406,-5471,-5522,-5560,
+-5600,-5643,-5682,-5716,-5758,-5815,-5875,-5928,-5980,-6043,-6113,-6176,-6229,-6284,-6350,-6421,-6483,-6520,-6532,-6539,-6565,
+-6618,-6681,-6738,-6793,-6858,-6937,-7022,-7109,-7206,-7311,-7413,-7498,-7558,-7598,-7625,-7651,-7684,-7721,-7760,-7800,-7840,
+-7877,-7911,-7944,-7977,-8004,-8022,-8041,-8065,-8082,-8084,-8079,-8081,-8086,-8073,-8041,-8006,-7983,-7965,-7942,-7915,-7887,
+-7854,-7815,-7784,-7774,-7780,-7783,-7778,-7764,-7741,-7712,-7677,-7640,-7595,-7544,-7496,-7458,-7424,-7386,-7343,-7298,-7250,
+-7192,-7133,-7080,-7031,-6980,-6924,-6858,-6766,-6646,-6538,-6489,-6498,-6517,-6508,-6473,-6411,-6304,-6157,-6026,-5965,-5950,
+-5907,-5807,-5689,-5599,-5531,-5449,-5340,-5217,-5089,-4964,-4855,-4766,-4675,-4554,-4416,-4307,-4255,-4231,-4177,-4062,-3900,
+-3726,-3566,-3422,-3290,-3168,-3066,-2991,-2932,-2867,-2781,-2680,-2579,-2481,-2381,-2272,-2154,-2026,-1898,-1785,-1696,-1611,
+-1509,-1393,-1295,-1231,-1183,-1127,-1059,-1002,-979,-997,-1046,-1095,-1107,-1059,-967,-862,-763,-673,-594,-528,-461,
+-372,-262,-151,-44,85,257,455,646,826,1015,1221,1414,1562,1655,1712,1761,1822,1907,2019,2151,2281,
+2387,2466,2544,2644,2752,2835,2889,2956,3064,3182,3260,3294,3318,3353,3394,3457,3573,3720,3815,3800,3720,
+3664,3670,3706,3743,3789,3855,3931,4001,4059,4091,4072,4010,3950,3922,3911,3883,3836,3785,3726,3651,3589,
+3596,3681,3799,3907,4012,4136,4267,4369,4428,4464,4490,4490,4436,4317,4143,3926,3693,3487,3361,3347,3441,
+3603,3783,3938,4057,4161,4281,4431,4598,4757,4892,5010,5129,5261,5397,5523,5633,5742,5860,5975,6067,6129,
+6177,6226,6282,6342,6414,6498,6578,6636,6668,6685,6692,6690,6688,6695,6713,6732,6751,6781,6828,6881,6928,
+6964,6996,7022,7036,7042,7051,7071,7101,7137,7178,7227,7283,7344,7401,7442,7462,7463,7452,7437,7428,7437,
+7464,7489,7486,7446,7384,7315,7248,7200,7222,7373,7654,7984,8244,8355,8312,8159,7959,7783,7683,7667,7699,
+7745,7807,7892,7970,7987,7933,7856,7793,7736,7661,7572,7488,7395,7268,7126,7040,7060,7156,7248,7277,7241,
+7178,7129,7104,7087,7056,7010,6961,6922,6900,6895,6897,6877,6811,6687,6521,6346,6220,6196,6260,6315,6271,
+6163,6109,6154,6192,6088,5835,5562,5407,5422,5574,5781,5948,6021,6022,6005,5983,5919,5804,5685,5601,5546,
+5498,5458,5434,5406,5355,5295,5255,5241,5231,5210,5176,5120,5034,4941,4881,4866,4863,4831,4760,4675,4599,
+4541,4490,4434,4367,4300,4248,4212,4183,4157,4129,4098,4066,4042,4026,4008,3982,3955,3934,3907,3860,3805,
+3765,3737,3696,3638,3586,3554,3524,3482,3443,3421,3401,3367,3333,3318,3307,3260,3173,3085,3027,2990,2946,
+2894,2851,2826,2807,2786,2762,2736,2703,2664,2625,2588,2549,2504,2460,2425,2398,2377,2363,2358,2356,2343,
+2314,2289,2290,2313,2328,2307,2257,2206,2170,2144,2120,2098,2079,2059,2034,2006,1977,1943,1901,1856,1816,
+1785,1759,1732,1709,1691,1681,1673,1662,1646,1627,1606,1586,1569,1554,1533,1499,1463,1449,1470,1507,1526,
+1515,1488,1457,1420,1373,1330,1306,1293,1277,1255,1236,1218,1186,1138,1087,1041,994,960,979,1070,1187,
+1234,1165,1030,924,890,889,873,841,825,833,841,834,819,809,802,795,794,798,793,773,759,
+768,782,772,741,726,742,759,741,688,630,582,547,522,509,498,475,443,414,389,360,326,
+295,271,243,210,180,157,133,106,83,71,62,54,51,53,50,37,22,15,6,-8,-25,
+-39,-58,-84,-91,-42,53,151,210,230,217,161,56,-68,-167,-217,-233,-235,-237,-241,-253,-273,
+-299,-328,-360,-395,-429,-460,-489,-519,-547,-572,-599,-629,-661,-694,-726,-757,-785,-807,-824,-839,-854,
+-872,-888,-902,-913,-926,-942,-959,-976,-992,-1006,-1018,-1028,-1037,-1044,-1049,-1053,-1062,-1081,-1107,-1133,-1151,
+-1160,-1163,-1163,-1165,-1169,-1171,-1170,-1171,-1175,-1179,-1179,-1177,-1178,-1183,-1188,-1193,-1201,-1213,-1225,-1235,-1246,
+-1256,-1264,-1271,-1277,-1283,-1286,-1285,-1282,-1279,-1276,-1272,-1269,-1264,-1256,-1245,-1236,-1232,-1230,-1226,-1218,-1210,
+-1201,-1192,-1183,-1173,-1160,-1143,-1125,-1112,-1101,-1087,-1071,-1056,-1042,-1027,-1016,-1010,-1006,-997,-987,-981,-980,
+-976,-967,-958,-953,-950,-948,-947,-948,-948,-947,-945,-947,-950,-953,-955,-959,-966,-974,-983,-994,-1006,
+-1018,-1028,-1038,-1049,-1060,-1072,-1083,-1097,-1116,-1140,-1166,-1191,-1210,-1224,-1230,-1231,-1231,-1235,-1242,-1251,-1262,
+-1273,-1277,-1273,-1268,-1267,-1271,-1275,-1277,-1278,-1280,-1281,-1281,-1280,-1275,-1267,-1261,-1261,-1261,-1257,-1248,-1242,
+-1240,-1238,-1233,-1228,-1225,-1221,-1216,-1212,-1207,-1196,-1178,-1161,-1150,-1138,-1121,-1106,-1097,-1085,-1061,-1032,-1010,
+-994,-973,-944,-917,-895,-871,-841,-810,-783,-752,-717,-682,-652,-620,-584,-549,-517,-482,-438,-395,-358,
+-320,-269,-212,-164,-125,-80,-29,6,19,26,33,11,-71,-184,-239,-157,72,393,726,1005,1196,
+1317,1416,1528,1641,1720,1758,1770,1759,1711,1631,1557,1519,1505,1499,1512,1571,1664,1740,1772,1801,1887,
+2047,2236,2386,2459,2462,2435,2417,2425,2453,2489,2533,2585,2629,2648,2638,2614,2590,2558,2509,2441,2367,
+2302,2251,2214,2179,2132,2069,2003,1949,1900,1835,1735,1614,1501,1416,1356,1298,1234,1175,1143,1144,1154,
+1140,1091,1025,960,891,803,694,586,497,420,340,256,180,115,48,-30,-119,-208,-295,-374,-445,
+-511,-584,-668,-751,-819,-872,-927,-996,-1077,-1164,-1247,-1319,-1374,-1418,-1462,-1510,-1558,-1597,-1631,-1661,-1685,
+-1699,-1708,-1719,-1733,-1746,-1760,-1782,-1815,-1848,-1880,-1925,-2008,-2125,-2240,-2308,-2313,-2279,-2238,-2207,-2186,-2172,
+-2161,-2150,-2135,-2122,-2114,-2107,-2092,-2066,-2038,-2018,-2003,-1991,-1981,-1970,-1951,-1920,-1879,-1823,-1744,-1641,-1538,
+-1466,-1434,-1423,-1409,-1383,-1351,-1317,-1282,-1249,-1218,-1181,-1137,-1095,-1066,-1047,-1023,-986,-946,-917,-890,-850,
+-789,-726,-684,-671,-671,-663,-639,-613,-612,-656,-745,-860,-974,-1062,-1115,-1137,-1139,-1133,-1123,-1111,-1097,
+-1086,-1077,-1067,-1055,-1044,-1033,-1014,-984,-950,-922,-899,-874,-849,-830,-817,-803,-790,-779,-770,-753,-723,
+-690,-662,-637,-610,-581,-558,-535,-506,-473,-441,-409,-372,-328,-285,-250,-218,-182,-138,-84,-20,48,
+114,173,224,271,318,371,432,494,546,591,637,685,729,767,805,849,894,932,964,996,1026,
+1052,1078,1109,1142,1172,1202,1237,1276,1313,1348,1387,1423,1441,1436,1423,1420,1423,1424,1420,1416,1413,
+1407,1396,1388,1392,1405,1416,1421,1418,1411,1406,1408,1417,1429,1438,1443,1444,1442,1436,1427,1420,1417,
+1418,1424,1435,1449,1456,1451,1439,1432,1432,1435,1435,1434,1436,1439,1436,1426,1409,1383,1350,1322,1304,
+1283,1243,1191,1160,1121,1093,1057,1012,979,975,987,990,977,962,951,940,924,912,911,915,917,
+921,929,938,940,936,935,938,940,939,941,948,955,962,971,984,994,1000,1009,1028,1052,1071,
+1084,1096,1106,1112,1119,1144,1186,1227,1253,1278,1329,1412,1502,1566,1596,1598,1582,1555,1528,1513,1507,
+1495,1462,1411,1346,1268,1177,1089,1022,978,940,892,840,798,764,729,687,641,591,532,464,392,
+326,267,211,158,106,55,3,-48,-100,-158,-229,-313,-400,-473,-525,-562,-598,-644,-697,-755,-820,
+-889,-945,-965,-952,-931,-913,-887,-838,-790,-785,-839,-931,-1033,-1133,-1222,-1290,-1332,-1359,-1380,-1390,-1381,
+-1357,-1316,-1250,-1168,-1115,-1125,-1177,-1212,-1213,-1218,-1262,-1326,-1365,-1359,-1325,-1289,-1281,-1342,-1494,-1697,-1863,
+-1930,-1929,-1944,-2021,-2135,-2234,-2298,-2341,-2380,-2417,-2446,-2475,-2524,-2617,-2767,-2948,-3112,-3219,-3272,-3305,-3334,
+-3349,-3341,-3329,-3338,-3370,-3403,-3425,-3438,-3444,-3448,-3456,-3470,-3480,-3478,-3479,-3504,-3556,-3615,-3668,-3701,-3687,
+-3596,-3454,-3361,-3405,-3572,-3745,-3806,-3727,-3581,-3474,-3456,-3491,-3504,-3472,-3438,-3449,-3481,-3469,-3397,-3316,-3286,
+-3315,-3377,-3450,-3519,-3571,-3592,-3588,-3574,-3558,-3542,-3535,-3546,-3573,-3606,-3634,-3655,-3666,-3676,-3699,-3742,-3790,
+-3825,-3853,-3893,-3952,-4013,-4055,-4078,-4093,-4108,-4109,-4083,-4042,-4030,-4085,-4200,-4330,-4428,-4488,-4532,-4579,-4635,
+-4698,-4769,-4843,-4916,-4989,-5064,-5134,-5196,-5256,-5320,-5383,-5432,-5468,-5506,-5551,-5594,-5631,-5672,-5727,-5790,-5849,
+-5904,-5959,-6012,-6063,-6118,-6184,-6257,-6325,-6376,-6405,-6421,-6439,-6474,-6529,-6592,-6650,-6709,-6778,-6852,-6927,-7008,
+-7103,-7212,-7317,-7400,-7459,-7498,-7527,-7556,-7591,-7630,-7668,-7706,-7744,-7782,-7818,-7851,-7881,-7907,-7928,-7949,-7970,
+-7982,-7982,-7980,-7985,-7989,-7975,-7948,-7922,-7906,-7891,-7868,-7839,-7809,-7772,-7733,-7707,-7704,-7713,-7718,-7709,-7690,
+-7665,-7636,-7602,-7562,-7513,-7463,-7421,-7391,-7361,-7322,-7277,-7229,-7176,-7119,-7065,-7021,-6980,-6933,-6881,-6818,-6728,
+-6613,-6513,-6473,-6487,-6508,-6500,-6462,-6396,-6288,-6145,-6020,-5956,-5932,-5887,-5800,-5703,-5622,-5548,-5454,-5337,-5212,
+-5092,-4987,-4905,-4830,-4725,-4571,-4405,-4289,-4251,-4246,-4202,-4084,-3913,-3739,-3593,-3469,-3350,-3233,-3136,-3070,-3018,
+-2951,-2857,-2750,-2642,-2535,-2423,-2308,-2190,-2064,-1938,-1832,-1754,-1680,-1579,-1459,-1355,-1286,-1233,-1168,-1085,-1002,
+-938,-905,-909,-939,-968,-969,-941,-895,-834,-756,-669,-585,-505,-420,-338,-277,-229,-159,-41,102,238,
+370,528,722,910,1044,1110,1140,1181,1267,1398,1553,1708,1847,1968,2076,2178,2276,2358,2415,2460,2525,
+2629,2748,2847,2923,2996,3068,3134,3212,3334,3475,3547,3502,3393,3327,3347,3416,3499,3599,3724,3848,3933,
+3971,3967,3919,3835,3748,3684,3633,3562,3463,3363,3283,3232,3227,3288,3418,3578,3733,3874,4008,4123,4198,
+4230,4233,4218,4178,4106,4007,3884,3741,3589,3459,3392,3413,3524,3701,3905,4095,4248,4377,4506,4646,4789,
+4921,5046,5174,5307,5435,5543,5627,5699,5780,5881,5984,6066,6119,6158,6196,6238,6288,6358,6451,6548,6620,
+6656,6666,6661,6650,6642,6647,6663,6683,6710,6749,6796,6837,6863,6888,6929,6982,7025,7047,7058,7074,7101,
+7136,7174,7216,7267,7328,7391,7438,7460,7461,7451,7441,7433,7438,7462,7492,7492,7440,7345,7240,7149,7088,
+7089,7194,7415,7701,7973,8163,8246,8218,8101,7948,7827,7772,7759,7762,7785,7841,7899,7902,7839,7765,7726,
+7719,7716,7711,7702,7654,7530,7360,7240,7229,7294,7343,7320,7242,7164,7121,7109,7100,7074,7032,6984,6936,
+6890,6851,6822,6793,6754,6695,6607,6491,6373,6306,6315,6346,6321,6230,6154,6151,6184,6153,6005,5775,5556,
+5449,5508,5689,5872,5960,5961,5944,5933,5892,5803,5709,5654,5632,5614,5595,5584,5567,5524,5465,5415,5381,
+5350,5317,5281,5232,5150,5048,4966,4930,4925,4913,4870,4798,4716,4642,4577,4512,4442,4375,4322,4280,4240,
+4204,4178,4154,4125,4098,4085,4077,4054,4013,3973,3943,3910,3868,3825,3787,3743,3687,3633,3592,3555,3513,
+3474,3450,3430,3397,3355,3332,3328,3312,3262,3189,3116,3051,2990,2936,2901,2883,2871,2853,2827,2795,2756,
+2715,2679,2648,2612,2566,2518,2482,2462,2452,2446,2444,2443,2433,2409,2378,2358,2351,2342,2323,2303,2292,
+2286,2265,2220,2164,2114,2079,2051,2026,2000,1970,1932,1885,1837,1795,1764,1742,1723,1705,1690,1675,1657,
+1635,1614,1594,1575,1557,1539,1520,1495,1471,1469,1498,1533,1539,1512,1478,1453,1422,1368,1307,1269,1255,
+1246,1230,1215,1202,1172,1119,1061,1012,973,948,970,1065,1186,1238,1166,1022,908,868,864,843,808,
+795,809,822,814,797,786,780,771,766,769,766,749,731,733,749,750,729,710,709,712,699,
+666,623,576,530,499,488,481,460,427,397,374,348,314,281,252,221,186,154,130,108,85,
+67,55,41,25,16,17,14,0,-16,-22,-26,-39,-55,-66,-83,-118,-149,-132,-47,77,187,
+245,235,160,45,-68,-151,-202,-236,-257,-265,-267,-275,-293,-316,-342,-372,-406,-439,-468,-497,-528,
+-555,-579,-602,-629,-661,-695,-727,-757,-782,-803,-819,-834,-849,-866,-884,-899,-912,-925,-938,-953,-968,
+-982,-995,-1009,-1021,-1031,-1038,-1040,-1040,-1045,-1061,-1083,-1105,-1122,-1132,-1135,-1134,-1135,-1139,-1144,-1145,-1144,
+-1145,-1146,-1145,-1143,-1144,-1148,-1152,-1156,-1164,-1176,-1189,-1199,-1208,-1218,-1227,-1235,-1243,-1251,-1257,-1256,-1253,
+-1251,-1251,-1250,-1247,-1241,-1232,-1221,-1210,-1201,-1194,-1186,-1179,-1173,-1164,-1153,-1140,-1129,-1115,-1099,-1082,-1068,
+-1056,-1043,-1029,-1017,-1005,-992,-980,-972,-967,-958,-947,-940,-938,-937,-932,-923,-918,-916,-915,-915,-916,
+-917,-917,-918,-923,-930,-935,-936,-936,-940,-949,-960,-969,-979,-991,-1005,-1018,-1030,-1043,-1055,-1070,-1088,
+-1112,-1139,-1164,-1183,-1198,-1210,-1215,-1216,-1215,-1219,-1228,-1238,-1248,-1256,-1259,-1257,-1254,-1254,-1257,-1259,-1261,
+-1263,-1265,-1265,-1263,-1260,-1257,-1250,-1244,-1241,-1239,-1233,-1224,-1219,-1219,-1219,-1214,-1208,-1204,-1200,-1196,-1194,
+-1190,-1180,-1164,-1148,-1138,-1126,-1108,-1090,-1079,-1067,-1047,-1020,-997,-980,-960,-932,-903,-879,-856,-829,-801,
+-773,-743,-711,-681,-652,-618,-581,-546,-516,-482,-439,-391,-349,-310,-266,-218,-174,-131,-82,-30,7,
+23,29,34,24,-31,-133,-225,-220,-60,234,581,890,1117,1268,1375,1471,1584,1730,1892,2011,2036,
+1985,1927,1909,1901,1850,1766,1725,1774,1869,1921,1905,1880,1927,2067,2252,2411,2500,2513,2485,2459,2464,
+2491,2523,2551,2582,2617,2643,2653,2651,2640,2615,2566,2501,2435,2382,2340,2302,2260,2211,2151,2088,2033,
+1983,1923,1836,1730,1626,1540,1462,1377,1290,1221,1193,1203,1218,1208,1162,1098,1035,969,881,772,662,
+570,491,410,325,245,172,94,8,-81,-167,-252,-334,-405,-467,-535,-618,-699,-751,-769,-782,-825,
+-917,-1044,-1171,-1263,-1306,-1318,-1337,-1379,-1436,-1488,-1525,-1547,-1557,-1559,-1561,-1575,-1598,-1621,-1638,-1660,-1696,
+-1744,-1796,-1857,-1942,-2053,-2159,-2222,-2230,-2207,-2183,-2166,-2148,-2127,-2110,-2096,-2083,-2068,-2057,-2046,-2025,-1988,
+-1946,-1914,-1897,-1890,-1884,-1865,-1826,-1771,-1718,-1674,-1627,-1564,-1495,-1450,-1440,-1449,-1451,-1437,-1410,-1375,-1335,
+-1298,-1261,-1213,-1150,-1095,-1076,-1089,-1095,-1060,-995,-938,-903,-872,-821,-758,-709,-694,-702,-707,-697,-683,
+-696,-757,-858,-970,-1061,-1114,-1130,-1124,-1111,-1105,-1104,-1104,-1100,-1092,-1082,-1067,-1049,-1036,-1028,-1015,-991,
+-961,-936,-914,-889,-862,-841,-827,-813,-794,-776,-761,-743,-716,-685,-659,-637,-612,-587,-564,-542,-512,
+-475,-438,-403,-365,-323,-281,-243,-207,-169,-126,-78,-21,44,114,178,231,276,320,372,433,492,
+541,582,625,672,716,751,785,825,869,909,943,973,999,1023,1049,1079,1111,1143,1176,1213,1251,
+1287,1325,1369,1408,1427,1421,1408,1400,1399,1395,1389,1385,1382,1375,1364,1357,1363,1379,1395,1402,1401,
+1396,1395,1402,1413,1425,1431,1430,1424,1417,1411,1406,1400,1395,1393,1395,1401,1408,1412,1411,1407,1405,
+1409,1413,1413,1408,1401,1396,1391,1381,1362,1333,1304,1285,1273,1251,1209,1160,1147,1125,1109,1074,1021,
+976,963,972,979,977,971,964,952,935,923,922,927,929,932,938,946,950,951,954,958,959,
+959,964,973,982,989,1000,1017,1032,1043,1055,1076,1103,1123,1133,1143,1157,1174,1193,1222,1265,1306,
+1334,1361,1412,1493,1577,1631,1648,1644,1631,1615,1598,1589,1591,1593,1579,1538,1470,1381,1287,1205,1142,
+1086,1025,958,899,856,818,776,729,685,639,586,521,454,390,332,278,228,179,129,75,22,
+-32,-97,-186,-294,-403,-490,-547,-588,-630,-675,-716,-750,-792,-845,-884,-877,-832,-796,-800,-815,-797,
+-750,-728,-771,-868,-981,-1086,-1174,-1237,-1278,-1310,-1342,-1361,-1345,-1294,-1229,-1169,-1127,-1120,-1147,-1178,-1177,
+-1147,-1142,-1201,-1301,-1372,-1369,-1300,-1217,-1188,-1269,-1462,-1692,-1853,-1905,-1906,-1942,-2041,-2161,-2253,-2311,-2348,
+-2373,-2388,-2402,-2428,-2477,-2567,-2710,-2895,-3075,-3202,-3271,-3311,-3334,-3328,-3292,-3258,-3260,-3298,-3341,-3373,-3392,
+-3404,-3410,-3415,-3424,-3430,-3424,-3422,-3448,-3496,-3531,-3531,-3510,-3494,-3490,-3491,-3500,-3535,-3600,-3665,-3683,-3624,
+-3515,-3433,-3436,-3490,-3506,-3443,-3367,-3354,-3390,-3390,-3321,-3249,-3247,-3310,-3375,-3406,-3420,-3446,-3485,-3518,-3526,
+-3510,-3486,-3481,-3501,-3536,-3567,-3586,-3598,-3608,-3623,-3653,-3699,-3746,-3779,-3804,-3844,-3904,-3967,-4013,-4043,-4065,
+-4080,-4074,-4038,-3991,-3977,-4027,-4132,-4247,-4331,-4384,-4430,-4489,-4557,-4625,-4691,-4758,-4830,-4907,-4985,-5056,-5118,
+-5175,-5236,-5295,-5342,-5379,-5417,-5464,-5511,-5553,-5595,-5644,-5698,-5751,-5802,-5851,-5900,-5952,-6016,-6093,-6170,-6233,
+-6278,-6307,-6331,-6358,-6398,-6449,-6505,-6562,-6625,-6695,-6766,-6833,-6909,-7005,-7116,-7221,-7302,-7359,-7398,-7429,-7460,
+-7497,-7539,-7579,-7617,-7655,-7692,-7727,-7757,-7784,-7810,-7834,-7855,-7871,-7880,-7883,-7887,-7895,-7898,-7886,-7866,-7850,
+-7840,-7826,-7803,-7774,-7742,-7708,-7676,-7659,-7660,-7666,-7662,-7645,-7621,-7595,-7568,-7538,-7500,-7449,-7396,-7355,-7329,
+-7304,-7266,-7219,-7168,-7112,-7057,-7011,-6978,-6946,-6907,-6859,-6797,-6707,-6595,-6502,-6467,-6481,-6497,-6487,-6452,-6388,
+-6282,-6145,-6027,-5962,-5929,-5882,-5808,-5725,-5642,-5549,-5438,-5323,-5214,-5116,-5030,-4959,-4882,-4762,-4591,-4416,-4302,
+-4269,-4267,-4220,-4093,-3913,-3741,-3614,-3518,-3418,-3306,-3209,-3145,-3094,-3020,-2917,-2802,-2690,-2574,-2452,-2334,-2222,
+-2109,-1996,-1902,-1835,-1768,-1669,-1547,-1436,-1357,-1291,-1213,-1121,-1025,-933,-853,-802,-787,-798,-817,-840,-864,
+-872,-842,-776,-692,-601,-498,-396,-314,-256,-192,-102,-5,71,139,238,381,524,611,629,624,656,
+758,915,1087,1244,1388,1532,1676,1803,1892,1941,1961,1982,2036,2136,2261,2381,2489,2591,2684,2760,2832,
+2928,3033,3086,3048,2973,2954,3031,3167,3320,3489,3674,3839,3936,3957,3923,3847,3729,3584,3443,3320,3201,
+3077,2965,2893,2879,2932,3056,3247,3472,3685,3846,3941,3975,3967,3940,3903,3855,3791,3727,3681,3658,3644,
+3628,3616,3633,3697,3818,3989,4184,4369,4522,4648,4764,4880,4990,5095,5206,5329,5452,5557,5631,5684,5737,
+5814,5914,6014,6087,6125,6146,6167,6193,6232,6302,6406,6518,6600,6634,6632,6619,6606,6601,6606,6623,6651,
+6688,6733,6776,6804,6818,6841,6891,6962,7025,7059,7068,7074,7092,7126,7167,7209,7254,7310,7375,7429,7456,
+7458,7452,7447,7444,7447,7459,7469,7442,7361,7243,7129,7043,6986,6972,7033,7192,7428,7690,7929,8109,8195,
+8175,8084,7993,7935,7888,7826,7775,7779,7824,7843,7796,7714,7650,7622,7625,7656,7704,7718,7652,7528,7423,
+7386,7387,7363,7293,7214,7162,7143,7131,7107,7069,7030,6997,6959,6908,6849,6792,6744,6700,6656,6604,6531,
+6440,6373,6374,6434,6486,6474,6400,6311,6239,6176,6084,5923,5709,5533,5507,5642,5822,5920,5922,5900,5897,
+5882,5830,5770,5738,5726,5708,5683,5664,5645,5610,5566,5527,5493,5454,5411,5377,5344,5285,5190,5086,5008,
+4970,4961,4949,4912,4848,4769,4690,4609,4528,4458,4405,4359,4311,4266,4237,4216,4187,4156,4140,4133,4109,
+4057,4003,3970,3948,3916,3875,3836,3798,3750,3695,3647,3605,3560,3517,3487,3464,3428,3380,3347,3347,3360,
+3345,3285,3197,3111,3044,3002,2979,2965,2950,2930,2900,2861,2815,2770,2734,2706,2675,2631,2580,2538,2517,
+2515,2521,2529,2531,2525,2504,2473,2440,2410,2380,2357,2349,2362,2375,2358,2300,2219,2147,2099,2069,2043,
+2014,1984,1953,1915,1868,1821,1784,1759,1741,1723,1707,1690,1666,1637,1609,1590,1576,1558,1537,1519,1504,
+1494,1502,1531,1559,1554,1516,1477,1457,1436,1386,1319,1269,1243,1222,1199,1186,1185,1169,1120,1057,1006,
+972,947,951,1008,1094,1134,1078,965,877,847,840,814,778,766,785,802,794,772,755,744,736,
+732,736,738,725,708,705,715,720,708,689,675,665,653,637,613,575,527,489,473,465,444,
+410,377,351,324,292,261,234,206,173,141,113,87,63,48,36,19,-2,-16,-18,-22,-35,
+-50,-54,-56,-69,-87,-97,-109,-141,-185,-200,-152,-50,57,124,125,75,11,-38,-76,-127,-195,
+-255,-287,-296,-304,-320,-340,-362,-388,-420,-451,-479,-508,-537,-564,-585,-605,-629,-659,-691,-723,-751,
+-774,-792,-810,-827,-843,-860,-878,-895,-908,-918,-928,-941,-954,-967,-980,-994,-1008,-1019,-1026,-1027,-1027,
+-1031,-1043,-1060,-1077,-1091,-1100,-1104,-1102,-1102,-1107,-1114,-1118,-1118,-1118,-1120,-1120,-1118,-1117,-1118,-1120,-1123,
+-1130,-1142,-1155,-1164,-1173,-1183,-1192,-1198,-1203,-1210,-1216,-1216,-1215,-1216,-1219,-1222,-1220,-1215,-1208,-1199,-1187,
+-1174,-1161,-1148,-1139,-1133,-1125,-1113,-1099,-1085,-1071,-1054,-1038,-1023,-1011,-997,-983,-974,-966,-958,-947,-938,
+-932,-924,-913,-904,-901,-900,-895,-887,-882,-882,-882,-882,-883,-886,-889,-892,-898,-907,-916,-920,-921,
+-924,-931,-941,-948,-956,-966,-980,-994,-1008,-1022,-1038,-1056,-1079,-1107,-1136,-1160,-1176,-1186,-1193,-1197,-1199,
+-1203,-1211,-1222,-1230,-1234,-1237,-1239,-1239,-1241,-1243,-1244,-1243,-1241,-1242,-1243,-1242,-1238,-1234,-1230,-1225,-1220,
+-1217,-1214,-1208,-1200,-1196,-1197,-1197,-1194,-1188,-1183,-1179,-1175,-1171,-1167,-1159,-1145,-1131,-1122,-1111,-1095,-1077,
+-1063,-1049,-1030,-1006,-984,-965,-944,-917,-888,-862,-838,-814,-788,-759,-728,-698,-671,-644,-613,-577,-541,
+-509,-476,-437,-393,-348,-305,-263,-221,-178,-134,-86,-36,7,35,44,41,30,-3,-80,-185,-242,
+-158,88,425,750,1002,1182,1310,1421,1571,1802,2071,2260,2294,2234,2207,2252,2281,2204,2062,1979,2013,
+2095,2116,2058,1995,2010,2123,2287,2437,2525,2540,2510,2485,2493,2529,2565,2588,2608,2632,2654,2667,2670,
+2667,2651,2616,2566,2516,2471,2429,2384,2339,2296,2248,2190,2127,2067,2005,1930,1840,1747,1657,1563,1456,
+1349,1274,1252,1269,1285,1271,1224,1165,1110,1049,965,855,744,650,568,486,399,314,231,143,51,
+-35,-116,-200,-286,-360,-420,-486,-570,-650,-686,-665,-633,-654,-763,-936,-1109,-1219,-1248,-1227,-1215,-1244,
+-1305,-1370,-1416,-1436,-1434,-1421,-1415,-1431,-1466,-1500,-1523,-1542,-1577,-1634,-1705,-1783,-1876,-1984,-2083,-2141,-2154,
+-2147,-2144,-2141,-2123,-2093,-2068,-2054,-2041,-2021,-2000,-1982,-1955,-1909,-1855,-1817,-1802,-1801,-1791,-1755,-1692,-1623,
+-1578,-1568,-1571,-1557,-1525,-1502,-1503,-1514,-1514,-1497,-1469,-1431,-1385,-1338,-1291,-1234,-1162,-1105,-1102,-1145,-1175,
+-1136,-1043,-956,-912,-892,-858,-800,-745,-720,-728,-746,-758,-774,-813,-886,-978,-1062,-1116,-1138,-1136,-1121,
+-1104,-1096,-1097,-1101,-1101,-1097,-1089,-1074,-1055,-1037,-1024,-1010,-987,-960,-936,-916,-893,-868,-848,-834,-819,
+-796,-771,-751,-733,-712,-688,-667,-648,-628,-605,-582,-558,-529,-492,-454,-417,-378,-335,-293,-251,-209,
+-165,-121,-76,-27,32,99,165,222,270,316,367,423,477,522,562,607,658,705,742,773,808,
+849,889,924,951,973,993,1014,1041,1072,1106,1144,1184,1222,1256,1294,1338,1380,1404,1404,1392,1382,
+1374,1367,1362,1360,1360,1354,1343,1336,1338,1351,1367,1378,1382,1385,1388,1395,1403,1410,1411,1406,1397,
+1391,1393,1397,1398,1393,1388,1387,1384,1379,1373,1372,1377,1383,1388,1390,1389,1381,1370,1358,1349,1337,
+1315,1288,1268,1262,1255,1230,1187,1147,1161,1159,1152,1111,1043,985,962,967,977,980,979,974,963,
+948,938,939,943,946,947,953,961,965,968,973,979,981,982,989,1001,1012,1019,1029,1046,1067,
+1083,1097,1119,1147,1170,1182,1195,1218,1247,1276,1306,1343,1379,1406,1431,1477,1550,1629,1682,1702,1700,
+1687,1663,1635,1620,1628,1653,1668,1649,1585,1487,1383,1299,1236,1176,1104,1027,964,917,873,823,774,
+731,690,640,579,516,456,398,344,296,248,195,138,82,28,-40,-139,-262,-382,-474,-534,-580,
+-627,-671,-697,-706,-723,-757,-782,-764,-718,-701,-739,-786,-777,-716,-678,-715,-810,-911,-1000,-1084,-1164,
+-1226,-1271,-1307,-1331,-1318,-1260,-1182,-1121,-1098,-1116,-1157,-1187,-1180,-1143,-1132,-1199,-1335,-1464,-1502,-1425,-1292,
+-1211,-1271,-1467,-1695,-1842,-1882,-1887,-1939,-2044,-2156,-2238,-2295,-2334,-2355,-2360,-2368,-2393,-2439,-2513,-2635,-2803,
+-2977,-3109,-3195,-3259,-3298,-3287,-3225,-3166,-3165,-3216,-3276,-3317,-3344,-3362,-3370,-3368,-3368,-3372,-3372,-3377,-3403,
+-3444,-3460,-3422,-3353,-3322,-3369,-3470,-3552,-3571,-3544,-3522,-3524,-3513,-3463,-3413,-3424,-3482,-3499,-3425,-3324,-3288,
+-3310,-3304,-3233,-3168,-3189,-3280,-3354,-3365,-3343,-3344,-3380,-3426,-3453,-3453,-3442,-3443,-3464,-3497,-3526,-3543,-3552,
+-3558,-3571,-3598,-3642,-3689,-3725,-3756,-3800,-3862,-3927,-3976,-4009,-4030,-4039,-4025,-3986,-3942,-3930,-3972,-4055,-4138,
+-4192,-4228,-4278,-4354,-4446,-4531,-4606,-4677,-4749,-4825,-4902,-4976,-5041,-5098,-5152,-5203,-5248,-5289,-5332,-5380,-5429,
+-5473,-5514,-5553,-5593,-5637,-5685,-5739,-5796,-5858,-5928,-6002,-6072,-6132,-6181,-6220,-6253,-6288,-6329,-6377,-6426,-6478,
+-6540,-6609,-6675,-6737,-6811,-6909,-7021,-7125,-7205,-7260,-7300,-7332,-7365,-7405,-7448,-7490,-7528,-7565,-7600,-7633,-7662,
+-7690,-7718,-7741,-7759,-7773,-7783,-7790,-7797,-7806,-7808,-7801,-7787,-7776,-7769,-7757,-7735,-7706,-7676,-7648,-7628,-7622,
+-7623,-7621,-7609,-7588,-7563,-7538,-7514,-7489,-7453,-7400,-7341,-7294,-7265,-7240,-7207,-7164,-7115,-7063,-7012,-6975,-6952,
+-6932,-6903,-6861,-6800,-6708,-6597,-6508,-6472,-6477,-6484,-6474,-6448,-6392,-6287,-6151,-6036,-5973,-5937,-5889,-5818,-5735,
+-5639,-5528,-5414,-5317,-5239,-5163,-5084,-5006,-4917,-4791,-4626,-4462,-4351,-4306,-4286,-4227,-4097,-3918,-3754,-3647,-3577,
+-3496,-3388,-3287,-3218,-3162,-3079,-2966,-2845,-2726,-2602,-2473,-2355,-2256,-2164,-2075,-2000,-1942,-1875,-1772,-1646,-1530,
+-1440,-1356,-1260,-1154,-1045,-933,-825,-737,-681,-653,-648,-680,-748,-822,-856,-839,-794,-731,-640,-520,-397,
+-296,-209,-122,-42,8,43,98,192,287,332,322,306,343,452,601,743,867,997,1158,1335,1478,
+1551,1560,1543,1542,1587,1680,1803,1929,2044,2152,2249,2327,2388,2454,2526,2575,2579,2574,2631,2778,2979,
+3188,3400,3619,3812,3935,3973,3947,3865,3720,3518,3299,3109,2955,2822,2711,2649,2661,2752,2919,3150,3414,
+3652,3800,3832,3777,3695,3632,3592,3556,3518,3499,3527,3607,3712,3814,3902,3985,4081,4203,4352,4512,4655,
+4770,4866,4959,5056,5150,5243,5342,5448,5546,5623,5675,5718,5772,5850,5948,6042,6105,6132,6142,6152,6169,
+6199,6260,6361,6478,6565,6595,6583,6560,6546,6543,6553,6578,6616,6663,6710,6749,6776,6796,6825,6875,6942,
+7005,7040,7047,7044,7058,7099,7153,7201,7240,7287,7347,7405,7441,7453,7452,7451,7448,7445,7441,7418,7351,
+7238,7113,7016,6954,6907,6877,6899,7007,7197,7436,7688,7913,8063,8111,8086,8055,8042,8005,7909,7794,7742,
+7769,7808,7785,7701,7602,7531,7504,7524,7576,7612,7593,7527,7463,7423,7381,7314,7237,7190,7180,7177,7151,
+7099,7046,7012,6992,6966,6917,6853,6788,6728,6665,6599,6535,6469,6399,6346,6355,6449,6589,6689,6679,6552,
+6372,6218,6110,5986,5796,5596,5516,5617,5805,5935,5957,5935,5924,5917,5888,5849,5822,5801,5768,5730,5701,
+5680,5653,5624,5602,5580,5541,5493,5458,5438,5407,5335,5225,5111,5030,4998,4995,4988,4954,4895,4821,4735,
+4641,4558,4497,4447,4393,4342,4308,4285,4254,4215,4185,4167,4139,4093,4050,4024,4001,3961,3913,3878,3851,
+3811,3755,3702,3660,3617,3570,3531,3505,3474,3425,3381,3371,3390,3396,3351,3267,3184,3131,3104,3084,3057,
+3026,2994,2960,2922,2879,2838,2803,2774,2744,2704,2654,2607,2579,2577,2593,2609,2616,2612,2597,2571,2533,
+2488,2442,2405,2389,2393,2400,2381,2322,2242,2171,2128,2105,2079,2044,2007,1975,1942,1900,1851,1810,1782,
+1760,1740,1723,1708,1684,1649,1613,1592,1580,1563,1539,1520,1512,1514,1526,1551,1574,1567,1528,1490,1474,
+1459,1415,1349,1292,1254,1219,1185,1168,1173,1166,1122,1059,1010,983,958,936,940,971,989,958,895,
+849,835,827,798,759,743,757,772,765,742,719,705,698,697,700,702,694,683,680,686,688,
+678,660,641,625,613,607,600,574,529,483,456,442,423,392,358,326,295,264,239,219,197,
+168,135,101,67,39,22,12,-3,-26,-45,-53,-61,-73,-84,-86,-88,-101,-120,-131,-139,-163,
+-204,-238,-231,-179,-106,-50,-27,-21,-3,28,38,-13,-116,-221,-284,-310,-326,-345,-364,-382,-405,
+-434,-463,-492,-520,-549,-574,-593,-610,-632,-658,-688,-718,-743,-763,-780,-800,-820,-837,-853,-871,-889,
+-901,-908,-914,-924,-936,-948,-961,-975,-990,-1001,-1009,-1013,-1015,-1020,-1028,-1040,-1052,-1063,-1071,-1073,-1072,
+-1071,-1076,-1085,-1090,-1092,-1094,-1098,-1101,-1100,-1097,-1095,-1095,-1096,-1102,-1113,-1124,-1132,-1140,-1149,-1157,-1161,
+-1163,-1168,-1172,-1174,-1174,-1176,-1181,-1185,-1185,-1184,-1180,-1174,-1163,-1149,-1133,-1117,-1105,-1096,-1089,-1077,-1062,
+-1045,-1029,-1011,-993,-979,-966,-952,-937,-928,-925,-920,-913,-904,-899,-893,-883,-873,-868,-865,-860,-852,
+-847,-848,-850,-851,-853,-858,-863,-867,-871,-879,-890,-899,-904,-909,-916,-923,-930,-937,-946,-959,-974,
+-988,-1004,-1023,-1044,-1069,-1098,-1127,-1150,-1163,-1170,-1174,-1177,-1182,-1191,-1203,-1215,-1221,-1222,-1222,-1223,-1225,
+-1228,-1231,-1231,-1227,-1221,-1220,-1222,-1221,-1216,-1211,-1208,-1203,-1198,-1195,-1192,-1186,-1178,-1173,-1172,-1172,-1169,
+-1165,-1161,-1159,-1154,-1148,-1141,-1133,-1123,-1112,-1103,-1095,-1083,-1066,-1049,-1032,-1012,-990,-968,-947,-926,-901,
+-874,-847,-824,-800,-774,-745,-713,-683,-657,-632,-604,-572,-538,-503,-468,-434,-398,-358,-313,-268,-225,
+-180,-135,-90,-47,-1,40,61,56,42,25,-22,-122,-224,-219,-44,253,571,840,1049,1209,1355,
+1552,1844,2168,2379,2404,2342,2346,2441,2506,2446,2317,2247,2276,2322,2295,2200,2114,2104,2182,2314,2449,
+2537,2558,2536,2518,2536,2579,2621,2645,2659,2675,2690,2696,2691,2679,2663,2640,2612,2581,2544,2498,2445,
+2399,2365,2332,2284,2219,2149,2082,2011,1930,1847,1764,1669,1554,1438,1358,1336,1353,1364,1340,1289,1234,
+1188,1135,1051,940,826,730,646,560,469,381,295,204,110,21,-62,-152,-245,-324,-384,-448,-531,
+-605,-622,-572,-514,-531,-658,-858,-1048,-1163,-1185,-1156,-1134,-1153,-1210,-1275,-1324,-1347,-1345,-1328,-1318,-1333,
+-1372,-1411,-1434,-1450,-1485,-1549,-1632,-1723,-1823,-1931,-2024,-2077,-2089,-2090,-2100,-2105,-2086,-2050,-2022,-2010,-1998,
+-1973,-1946,-1923,-1891,-1838,-1778,-1739,-1731,-1732,-1712,-1660,-1586,-1525,-1509,-1541,-1588,-1609,-1600,-1587,-1587,-1586,
+-1570,-1542,-1511,-1473,-1419,-1357,-1296,-1234,-1169,-1126,-1140,-1201,-1242,-1202,-1093,-985,-929,-913,-893,-847,-796,
+-769,-773,-797,-829,-871,-932,-1007,-1076,-1120,-1138,-1142,-1141,-1135,-1123,-1113,-1108,-1106,-1102,-1095,-1086,-1073,
+-1054,-1035,-1019,-1003,-980,-954,-932,-914,-896,-874,-855,-841,-824,-800,-772,-749,-732,-716,-698,-682,-668,
+-653,-633,-609,-583,-555,-521,-484,-444,-402,-358,-313,-269,-223,-175,-129,-85,-38,16,79,145,207,
+263,313,363,412,457,495,534,580,632,681,721,755,789,826,864,898,925,946,965,986,1011,
+1039,1073,1112,1153,1189,1221,1255,1298,1342,1372,1380,1373,1361,1350,1342,1339,1340,1339,1334,1326,1318,
+1316,1322,1336,1350,1362,1370,1376,1381,1383,1382,1379,1372,1366,1365,1376,1389,1394,1392,1389,1387,1380,
+1363,1346,1344,1355,1367,1369,1365,1359,1351,1339,1325,1313,1300,1282,1265,1260,1263,1256,1226,1185,1161,
+1174,1185,1178,1127,1050,990,969,977,988,990,988,982,973,963,956,957,961,963,966,972,977,
+981,984,990,1000,1007,1011,1019,1033,1046,1055,1065,1082,1104,1123,1138,1157,1183,1209,1228,1250,1280,
+1316,1349,1379,1412,1444,1466,1486,1523,1586,1657,1715,1748,1756,1738,1694,1645,1621,1638,1682,1721,1722,
+1670,1574,1465,1375,1310,1249,1177,1101,1037,985,930,872,821,783,744,695,636,576,519,461,407,
+358,311,255,193,135,82,14,-87,-215,-337,-425,-479,-521,-569,-613,-632,-625,-616,-626,-638,-629,
+-616,-642,-716,-774,-754,-677,-633,-671,-757,-835,-904,-994,-1108,-1206,-1262,-1289,-1301,-1290,-1241,-1172,-1120,
+-1103,-1117,-1144,-1171,-1180,-1166,-1158,-1212,-1353,-1533,-1647,-1620,-1484,-1362,-1374,-1529,-1723,-1843,-1871,-1879,-1936,
+-2039,-2142,-2222,-2282,-2324,-2342,-2344,-2353,-2376,-2407,-2456,-2548,-2686,-2829,-2942,-3036,-3136,-3220,-3228,-3155,-3076,
+-3068,-3128,-3197,-3242,-3272,-3299,-3313,-3309,-3304,-3311,-3321,-3327,-3344,-3378,-3402,-3377,-3311,-3267,-3305,-3406,-3482,
+-3466,-3387,-3336,-3363,-3415,-3422,-3390,-3386,-3428,-3447,-3388,-3289,-3234,-3225,-3195,-3120,-3068,-3109,-3217,-3302,-3317,
+-3293,-3284,-3308,-3345,-3373,-3387,-3392,-3400,-3418,-3445,-3474,-3500,-3517,-3524,-3529,-3544,-3578,-3624,-3668,-3709,-3759,
+-3821,-3884,-3933,-3966,-3985,-3991,-3975,-3937,-3893,-3874,-3898,-3954,-4006,-4034,-4055,-4103,-4191,-4302,-4411,-4508,-4593,
+-4669,-4740,-4813,-4890,-4962,-5021,-5065,-5104,-5148,-5197,-5247,-5295,-5340,-5379,-5412,-5444,-5478,-5522,-5576,-5639,-5706,
+-5774,-5841,-5903,-5963,-6022,-6080,-6132,-6174,-6213,-6257,-6304,-6349,-6397,-6454,-6520,-6584,-6646,-6721,-6818,-6929,-7029,
+-7107,-7164,-7206,-7240,-7276,-7316,-7359,-7399,-7435,-7469,-7502,-7533,-7563,-7595,-7625,-7646,-7661,-7675,-7688,-7698,-7705,
+-7712,-7716,-7713,-7704,-7694,-7686,-7676,-7656,-7628,-7599,-7579,-7572,-7576,-7576,-7567,-7549,-7531,-7513,-7493,-7471,-7447,
+-7410,-7353,-7286,-7230,-7192,-7164,-7133,-7099,-7063,-7023,-6984,-6954,-6938,-6925,-6905,-6872,-6814,-6722,-6612,-6524,-6483,
+-6474,-6469,-6462,-6449,-6401,-6291,-6147,-6031,-5974,-5943,-5896,-5819,-5724,-5614,-5498,-5399,-5333,-5286,-5224,-5141,-5046,
+-4942,-4814,-4664,-4519,-4408,-4339,-4292,-4224,-4105,-3945,-3797,-3705,-3651,-3581,-3474,-3365,-3289,-3226,-3138,-3018,-2889,
+-2763,-2632,-2501,-2389,-2304,-2233,-2168,-2113,-2061,-1986,-1873,-1742,-1624,-1525,-1428,-1319,-1200,-1073,-938,-809,-705,
+-625,-555,-504,-510,-591,-706,-790,-821,-823,-813,-768,-669,-542,-426,-335,-253,-177,-122,-89,-51,13,
+87,134,147,164,230,346,469,565,642,751,919,1111,1253,1300,1272,1227,1213,1244,1314,1405,1502,
+1595,1689,1782,1862,1923,1976,2034,2091,2135,2187,2295,2480,2709,2936,3154,3380,3605,3786,3888,3907,3844,
+3695,3474,3232,3023,2861,2722,2602,2537,2563,2681,2867,3093,3332,3532,3636,3622,3535,3448,3411,3418,3444,
+3475,3529,3628,3771,3936,4091,4220,4326,4428,4539,4659,4773,4865,4933,4997,5073,5162,5253,5340,5426,5512,
+5589,5653,5705,5753,5809,5880,5966,6047,6102,6125,6133,6145,6162,6186,6233,6319,6430,6519,6551,6532,6498,
+6476,6472,6484,6514,6557,6604,6646,6683,6718,6757,6799,6846,6900,6952,6985,6990,6986,7004,7059,7129,7184,
+7219,7255,7307,7368,7416,7443,7451,7446,7432,7416,7394,7348,7257,7136,7029,6965,6927,6881,6827,6811,6875,
+7020,7222,7450,7669,7827,7896,7909,7936,7995,8026,7968,7848,7760,7751,7774,7757,7679,7577,7494,7448,7443,
+7460,7469,7449,7411,7383,7362,7324,7265,7212,7193,7192,7175,7125,7062,7015,6993,6976,6940,6879,6810,6753,
+6703,6640,6559,6478,6407,6343,6287,6270,6331,6474,6633,6708,6636,6456,6272,6148,6039,5868,5655,5531,5593,
+5784,5954,6018,6007,5984,5965,5935,5899,5867,5838,5803,5772,5754,5742,5721,5697,5680,5663,5628,5576,5530,
+5508,5491,5448,5361,5247,5141,5072,5040,5026,5009,4979,4933,4862,4772,4682,4612,4554,4492,4431,4386,4358,
+4329,4287,4241,4200,4163,4131,4111,4097,4065,4004,3942,3906,3886,3849,3791,3739,3704,3669,3623,3579,3552,
+3528,3484,3433,3410,3424,3438,3410,3342,3277,3240,3218,3186,3139,3091,3049,3010,2973,2940,2911,2880,2847,
+2814,2781,2741,2697,2663,2657,2671,2686,2690,2684,2674,2654,2620,2571,2517,2467,2432,2412,2396,2366,2311,
+2242,2185,2154,2142,2125,2090,2046,2005,1966,1922,1874,1834,1806,1782,1757,1737,1721,1697,1657,1616,1590,
+1576,1557,1531,1513,1513,1522,1535,1555,1574,1570,1539,1506,1493,1481,1440,1377,1322,1286,1251,1208,1177,
+1167,1153,1110,1051,1009,990,968,930,894,880,877,865,842,825,822,815,789,754,731,730,736,
+733,716,697,683,676,671,667,661,655,653,658,663,659,644,625,607,591,580,576,574,558,
+518,467,428,407,392,369,337,301,265,236,216,202,183,156,122,86,49,17,-2,-14,-27,
+-47,-69,-86,-100,-114,-122,-124,-126,-136,-151,-163,-173,-192,-222,-254,-270,-259,-225,-187,-152,-106,
+-30,60,109,70,-41,-164,-249,-297,-330,-359,-381,-397,-418,-444,-474,-504,-536,-565,-587,-605,-621,
+-641,-663,-689,-715,-737,-753,-769,-789,-810,-828,-843,-861,-880,-893,-898,-904,-914,-925,-935,-944,-956,
+-969,-981,-991,-1000,-1007,-1011,-1015,-1020,-1029,-1037,-1044,-1047,-1046,-1047,-1052,-1059,-1064,-1067,-1072,-1080,-1086,
+-1085,-1081,-1077,-1076,-1077,-1082,-1090,-1098,-1102,-1106,-1113,-1119,-1123,-1126,-1130,-1135,-1137,-1138,-1138,-1140,-1142,
+-1144,-1145,-1144,-1139,-1130,-1119,-1105,-1091,-1077,-1066,-1057,-1044,-1028,-1010,-991,-972,-953,-938,-926,-913,-898,
+-889,-885,-882,-876,-869,-864,-860,-852,-843,-836,-832,-826,-818,-814,-815,-819,-822,-825,-831,-837,-841,
+-843,-847,-856,-868,-877,-886,-893,-902,-910,-919,-930,-942,-956,-972,-990,-1010,-1032,-1057,-1085,-1113,-1134,
+-1146,-1152,-1155,-1160,-1168,-1179,-1190,-1199,-1204,-1206,-1209,-1211,-1213,-1214,-1216,-1215,-1211,-1204,-1202,-1202,-1202,
+-1198,-1194,-1192,-1189,-1183,-1176,-1171,-1164,-1155,-1147,-1145,-1146,-1144,-1140,-1137,-1137,-1134,-1126,-1117,-1109,-1102,
+-1094,-1086,-1079,-1069,-1055,-1037,-1016,-994,-973,-951,-929,-908,-886,-861,-835,-811,-787,-761,-733,-704,-676,
+-649,-621,-593,-567,-537,-499,-460,-428,-399,-366,-323,-278,-234,-186,-137,-94,-59,-17,31,66,68,
+57,56,38,-43,-168,-234,-151,70,350,624,867,1074,1264,1495,1807,2136,2345,2381,2345,2379,2495,
+2588,2592,2559,2562,2589,2565,2461,2327,2228,2197,2235,2333,2456,2553,2590,2581,2569,2586,2625,2660,2681,
+2695,2715,2736,2743,2728,2697,2665,2642,2628,2614,2588,2543,2488,2439,2409,2386,2349,2293,2227,2162,2095,
+2023,1953,1884,1801,1691,1572,1485,1455,1463,1465,1432,1377,1325,1282,1228,1139,1024,911,816,730,636,
+537,445,361,271,172,75,-19,-118,-218,-301,-363,-424,-498,-555,-549,-479,-418,-448,-589,-786,-959,
+-1062,-1095,-1092,-1093,-1117,-1160,-1208,-1250,-1278,-1287,-1280,-1272,-1284,-1314,-1344,-1359,-1375,-1419,-1498,-1595,-1695,
+-1796,-1898,-1983,-2025,-2027,-2020,-2025,-2027,-2010,-1979,-1958,-1952,-1941,-1917,-1892,-1871,-1836,-1777,-1712,-1675,-1670,
+-1668,-1639,-1582,-1520,-1486,-1502,-1562,-1628,-1662,-1662,-1652,-1648,-1635,-1598,-1551,-1511,-1473,-1419,-1347,-1275,-1212,
+-1162,-1137,-1163,-1230,-1279,-1249,-1142,-1022,-946,-920,-908,-885,-854,-838,-844,-870,-911,-967,-1034,-1098,-1139,
+-1150,-1144,-1141,-1145,-1148,-1142,-1130,-1119,-1110,-1100,-1088,-1075,-1061,-1044,-1026,-1011,-996,-976,-953,-933,-918,
+-904,-885,-866,-850,-833,-810,-783,-760,-743,-728,-713,-699,-687,-674,-655,-631,-605,-578,-547,-511,-468,
+-423,-378,-334,-289,-243,-196,-150,-104,-56,-4,55,120,186,250,307,358,402,438,472,509,551,
+598,643,684,722,758,793,826,855,882,905,930,957,986,1014,1044,1080,1120,1156,1189,1223,1265,
+1309,1341,1354,1350,1336,1322,1315,1314,1314,1312,1307,1301,1295,1291,1294,1306,1322,1335,1345,1351,1353,
+1351,1346,1340,1335,1332,1336,1349,1363,1370,1369,1371,1376,1371,1351,1328,1325,1339,1352,1349,1334,1321,
+1314,1306,1295,1284,1276,1269,1266,1271,1272,1254,1216,1182,1174,1147,1163,1152,1100,1032,988,980,993,
+1003,1004,1000,995,989,981,977,976,977,979,982,987,992,994,998,1007,1021,1034,1042,1052,1067,
+1084,1097,1110,1127,1147,1164,1177,1193,1216,1243,1270,1298,1331,1365,1398,1432,1467,1498,1517,1532,1562,
+1615,1680,1742,1789,1807,1783,1723,1661,1640,1669,1720,1758,1762,1722,1640,1537,1444,1373,1311,1244,1174,
+1113,1056,992,927,874,837,799,748,690,633,577,520,464,416,369,313,250,191,138,70,-30,
+-159,-280,-363,-407,-438,-478,-520,-538,-523,-495,-481,-485,-497,-528,-599,-693,-748,-718,-640,-600,-638,
+-710,-768,-827,-932,-1077,-1200,-1257,-1265,-1260,-1247,-1213,-1168,-1139,-1134,-1135,-1138,-1156,-1187,-1203,-1189,-1191,
+-1282,-1474,-1674,-1759,-1694,-1574,-1531,-1611,-1741,-1829,-1854,-1873,-1938,-2044,-2152,-2239,-2303,-2338,-2345,-2340,-2347,
+-2364,-2379,-2403,-2468,-2571,-2671,-2744,-2829,-2963,-3105,-3158,-3095,-3002,-2979,-3034,-3103,-3146,-3180,-3217,-3243,-3245,
+-3240,-3251,-3266,-3266,-3263,-3287,-3332,-3358,-3338,-3304,-3310,-3358,-3388,-3346,-3262,-3225,-3278,-3363,-3391,-3353,-3319,
+-3333,-3355,-3325,-3247,-3177,-3130,-3079,-3019,-3000,-3060,-3165,-3243,-3262,-3251,-3249,-3265,-3286,-3305,-3321,-3336,-3350,
+-3365,-3388,-3418,-3451,-3477,-3488,-3489,-3494,-3521,-3565,-3614,-3660,-3710,-3768,-3828,-3878,-3913,-3935,-3947,-3940,-3906,
+-3853,-3809,-3803,-3833,-3872,-3897,-3916,-3958,-4040,-4154,-4279,-4400,-4503,-4584,-4649,-4717,-4797,-4876,-4935,-4973,-5006,
+-5051,-5106,-5161,-5204,-5237,-5263,-5287,-5317,-5360,-5417,-5484,-5553,-5622,-5686,-5746,-5800,-5855,-5918,-5985,-6042,-6086,
+-6125,-6170,-6217,-6261,-6306,-6362,-6430,-6498,-6564,-6642,-6738,-6843,-6939,-7014,-7070,-7114,-7152,-7191,-7231,-7271,-7306,
+-7339,-7371,-7402,-7431,-7463,-7498,-7528,-7548,-7562,-7577,-7593,-7603,-7607,-7612,-7619,-7620,-7613,-7602,-7594,-7585,-7568,
+-7541,-7515,-7501,-7504,-7512,-7511,-7497,-7479,-7467,-7459,-7446,-7426,-7398,-7354,-7291,-7220,-7160,-7118,-7084,-7053,-7030,
+-7013,-6992,-6967,-6944,-6929,-6916,-6899,-6871,-6816,-6726,-6620,-6535,-6491,-6471,-6457,-6454,-6451,-6404,-6283,-6127,-6012,
+-5967,-5946,-5899,-5813,-5705,-5589,-5481,-5405,-5367,-5338,-5280,-5187,-5076,-4956,-4824,-4686,-4556,-4447,-4360,-4289,-4218,
+-4118,-3985,-3859,-3779,-3729,-3657,-3543,-3428,-3349,-3286,-3196,-3071,-2933,-2799,-2669,-2547,-2447,-2373,-2315,-2265,-2221,
+-2168,-2080,-1955,-1820,-1701,-1598,-1496,-1386,-1266,-1126,-967,-817,-700,-604,-501,-408,-385,-467,-604,-711,-757,
+-777,-798,-799,-748,-658,-571,-505,-443,-374,-316,-284,-262,-217,-143,-63,8,85,188,308,413,480,
+534,628,788,970,1095,1118,1071,1021,1009,1029,1063,1100,1147,1208,1285,1371,1452,1515,1569,1627,1691,
+1752,1819,1930,2105,2317,2523,2717,2936,3196,3452,3636,3708,3670,3542,3358,3169,3008,2868,2723,2583,2509,
+2550,2692,2875,3053,3208,3326,3382,3371,3328,3309,3342,3416,3510,3613,3734,3876,4038,4202,4352,4475,4575,
+4666,4758,4850,4925,4978,5018,5067,5138,5222,5307,5383,5454,5526,5596,5663,5723,5778,5832,5892,5963,6034,
+6084,6104,6110,6122,6144,6169,6206,6276,6377,6470,6511,6493,6449,6417,6408,6420,6448,6487,6526,6560,6594,
+6638,6694,6751,6802,6850,6894,6920,6919,6912,6935,7002,7083,7142,7175,7207,7259,7324,7384,7429,7449,7438,
+7404,7366,7330,7278,7193,7092,7020,6991,6971,6920,6845,6798,6817,6907,7048,7222,7399,7532,7595,7624,7690,
+7817,7939,7977,7923,7844,7795,7771,7732,7664,7584,7515,7466,7434,7411,7381,7340,7306,7295,7298,7288,7259,
+7227,7202,7172,7121,7060,7013,6992,6979,6946,6880,6799,6736,6708,6693,6659,6592,6512,6440,6374,6299,6224,
+6186,6221,6323,6423,6445,6372,6272,6211,6164,6045,5842,5669,5655,5796,5967,6058,6061,6026,5982,5932,5882,
+5845,5823,5813,5816,5829,5833,5814,5781,5757,5741,5712,5659,5602,5564,5544,5521,5472,5394,5298,5201,5120,
+5062,5029,5013,4995,4956,4892,4821,4757,4695,4621,4540,4474,4434,4408,4374,4322,4260,4204,4171,4160,4149,
+4107,4035,3968,3932,3910,3872,3818,3773,3746,3716,3669,3621,3593,3574,3543,3507,3497,3522,3543,3521,3457,
+3393,3350,3314,3266,3211,3164,3121,3075,3028,2994,2972,2945,2908,2874,2851,2827,2792,2757,2742,2747,2752,
+2743,2729,2718,2707,2681,2638,2587,2537,2492,2451,2412,2366,2308,2243,2188,2160,2152,2145,2120,2079,2033,
+1987,1939,1891,1854,1830,1807,1779,1750,1724,1695,1653,1612,1584,1565,1539,1508,1493,1503,1521,1536,1550,
+1564,1563,1540,1516,1506,1495,1456,1398,1353,1331,1305,1257,1203,1164,1131,1086,1036,1003,987,967,925,
+877,842,826,818,810,802,798,793,780,756,730,712,706,705,701,691,681,671,657,639,621,
+613,620,633,639,629,605,582,566,555,546,540,536,524,491,441,396,368,355,339,311,274,
+237,208,190,176,157,129,96,63,31,0,-24,-41,-55,-72,-94,-117,-137,-152,-162,-166,-169,
+-173,-179,-191,-207,-228,-249,-271,-289,-298,-292,-277,-254,-208,-122,-10,70,68,-12,-118,-206,-270,
+-321,-363,-390,-409,-428,-452,-481,-515,-550,-581,-604,-621,-639,-657,-675,-695,-717,-735,-749,-762,-780,
+-800,-816,-829,-847,-868,-883,-892,-901,-913,-924,-929,-934,-943,-953,-963,-975,-989,-999,-1002,-1000,-1002,
+-1008,-1016,-1023,-1026,-1029,-1031,-1035,-1038,-1040,-1043,-1050,-1061,-1070,-1071,-1066,-1062,-1061,-1061,-1065,-1071,-1076,
+-1076,-1075,-1076,-1080,-1085,-1090,-1096,-1102,-1105,-1105,-1103,-1101,-1099,-1100,-1101,-1101,-1096,-1088,-1079,-1071,-1060,
+-1047,-1036,-1026,-1012,-995,-976,-958,-939,-921,-906,-894,-882,-868,-857,-852,-847,-841,-834,-830,-826,-820,
+-811,-805,-800,-794,-787,-783,-785,-790,-794,-798,-803,-809,-814,-816,-818,-824,-834,-844,-854,-864,-876,
+-887,-899,-910,-922,-936,-954,-975,-996,-1019,-1044,-1071,-1097,-1116,-1126,-1130,-1135,-1144,-1154,-1164,-1171,-1176,
+-1179,-1184,-1190,-1196,-1198,-1197,-1197,-1196,-1193,-1188,-1186,-1185,-1182,-1179,-1176,-1176,-1174,-1168,-1159,-1150,-1141,
+-1131,-1123,-1121,-1122,-1121,-1115,-1111,-1111,-1109,-1103,-1093,-1086,-1082,-1078,-1070,-1061,-1052,-1041,-1024,-1002,-979,
+-958,-936,-914,-892,-870,-846,-821,-797,-773,-748,-721,-696,-674,-647,-614,-581,-556,-530,-496,-455,-422,
+-395,-364,-323,-281,-242,-196,-143,-95,-62,-27,21,63,75,72,82,89,38,-79,-189,-197,-78,
+130,386,659,919,1157,1409,1710,2017,2232,2318,2350,2422,2537,2644,2731,2833,2933,2950,2838,2651,2486,
+2385,2333,2326,2378,2483,2585,2634,2632,2615,2615,2631,2649,2665,2688,2726,2772,2799,2787,2740,2686,2651,
+2637,2627,2608,2574,2527,2479,2442,2415,2385,2344,2293,2242,2192,2139,2085,2029,1954,1849,1728,1634,1593,
+1591,1585,1551,1497,1445,1397,1330,1230,1112,1005,917,828,723,611,512,425,332,226,120,19,-81,
+-183,-270,-338,-400,-464,-501,-473,-394,-342,-389,-533,-707,-847,-933,-984,-1023,-1062,-1097,-1126,-1152,-1182,
+-1213,-1235,-1242,-1240,-1247,-1262,-1275,-1281,-1303,-1368,-1475,-1595,-1703,-1798,-1886,-1954,-1982,-1968,-1940,-1922,-1913,
+-1899,-1886,-1883,-1883,-1872,-1851,-1834,-1820,-1786,-1721,-1651,-1614,-1607,-1600,-1569,-1523,-1487,-1481,-1515,-1579,-1644,
+-1677,-1679,-1673,-1671,-1652,-1597,-1523,-1463,-1423,-1379,-1315,-1245,-1187,-1149,-1138,-1167,-1234,-1293,-1283,-1189,-1058,
+-955,-910,-904,-906,-901,-897,-907,-937,-985,-1046,-1108,-1155,-1173,-1166,-1150,-1143,-1144,-1144,-1135,-1121,-1110,
+-1102,-1093,-1079,-1064,-1050,-1034,-1018,-1002,-988,-972,-954,-938,-924,-910,-893,-873,-855,-839,-821,-799,-777,
+-759,-745,-730,-714,-699,-684,-665,-642,-618,-593,-565,-528,-484,-440,-397,-353,-308,-263,-219,-174,-127,
+-78,-26,29,90,156,223,286,341,387,423,457,492,530,568,606,645,686,723,753,778,802,
+825,852,885,922,958,988,1015,1047,1084,1123,1161,1199,1240,1280,1311,1325,1321,1306,1290,1283,1283,
+1283,1280,1275,1272,1269,1265,1265,1273,1284,1293,1298,1304,1310,1310,1306,1301,1300,1302,1308,1319,1329,
+1334,1335,1343,1355,1356,1338,1316,1311,1326,1336,1326,1301,1282,1274,1271,1268,1264,1262,1264,1267,1266,
+1251,1215,1170,1143,1147,1089,1102,1091,1054,1014,995,999,1010,1016,1015,1014,1012,1008,1003,997,994,
+992,993,996,1001,1006,1011,1019,1030,1046,1061,1073,1085,1102,1121,1139,1155,1171,1188,1203,1215,1229,
+1250,1277,1307,1337,1366,1396,1427,1466,1509,1544,1563,1577,1605,1653,1712,1773,1828,1852,1825,1757,1700,
+1699,1743,1788,1803,1791,1758,1697,1609,1514,1433,1366,1301,1236,1178,1120,1055,988,933,893,853,802,
+744,689,634,576,519,470,424,371,311,252,196,128,28,-96,-217,-301,-341,-361,-386,-417,-430,
+-411,-375,-352,-360,-396,-458,-548,-643,-694,-672,-614,-587,-619,-675,-725,-791,-908,-1057,-1173,-1216,-1211,
+-1201,-1191,-1171,-1148,-1147,-1163,-1168,-1162,-1178,-1228,-1263,-1225,-1148,-1149,-1311,-1577,-1788,-1835,-1753,-1667,-1663,
+-1723,-1785,-1822,-1865,-1946,-2060,-2179,-2280,-2348,-2375,-2365,-2348,-2347,-2355,-2357,-2367,-2414,-2489,-2544,-2569,-2629,
+-2781,-2975,-3081,-3043,-2942,-2898,-2940,-3008,-3056,-3095,-3139,-3172,-3176,-3171,-3181,-3200,-3200,-3188,-3200,-3251,-3309,
+-3333,-3324,-3317,-3330,-3335,-3304,-3252,-3234,-3276,-3336,-3347,-3296,-3243,-3237,-3261,-3260,-3209,-3132,-3058,-3002,-2979,
+-3006,-3077,-3153,-3194,-3199,-3197,-3209,-3228,-3243,-3256,-3272,-3291,-3309,-3326,-3345,-3369,-3397,-3422,-3437,-3442,-3450,
+-3474,-3516,-3563,-3606,-3648,-3700,-3759,-3813,-3854,-3885,-3909,-3919,-3895,-3832,-3758,-3714,-3719,-3759,-3800,-3830,-3865,
+-3928,-4028,-4158,-4295,-4413,-4497,-4558,-4622,-4700,-4779,-4838,-4877,-4914,-4963,-5019,-5068,-5100,-5119,-5133,-5151,-5187,
+-5246,-5322,-5400,-5469,-5530,-5587,-5644,-5701,-5763,-5831,-5898,-5953,-5992,-6027,-6068,-6112,-6153,-6200,-6263,-6339,-6415,
+-6488,-6569,-6665,-6767,-6857,-6928,-6981,-7023,-7062,-7101,-7141,-7177,-7209,-7243,-7276,-7307,-7334,-7365,-7401,-7432,-7451,
+-7465,-7481,-7497,-7505,-7505,-7509,-7518,-7521,-7514,-7503,-7497,-7490,-7476,-7451,-7428,-7419,-7426,-7435,-7432,-7417,-7402,
+-7396,-7395,-7388,-7368,-7333,-7278,-7210,-7143,-7092,-7054,-7018,-6988,-6974,-6973,-6971,-6956,-6935,-6914,-6895,-6876,-6848,
+-6792,-6702,-6599,-6520,-6480,-6460,-6448,-6450,-6450,-6396,-6263,-6102,-5996,-5966,-5953,-5902,-5808,-5695,-5583,-5488,-5429,
+-5403,-5374,-5310,-5208,-5088,-4959,-4823,-4692,-4579,-4480,-4385,-4296,-4214,-4122,-4013,-3911,-3843,-3791,-3708,-3586,-3470,
+-3394,-3336,-3246,-3114,-2966,-2828,-2707,-2603,-2520,-2455,-2400,-2354,-2311,-2249,-2145,-2010,-1876,-1761,-1657,-1555,-1454,
+-1343,-1199,-1023,-853,-723,-613,-490,-375,-343,-430,-575,-679,-709,-707,-720,-736,-722,-677,-628,-586,-537,
+-476,-425,-408,-409,-386,-313,-205,-87,26,139,249,341,405,459,540,666,807,902,915,880,855,
+870,901,918,922,939,988,1064,1148,1223,1282,1334,1394,1461,1522,1580,1665,1800,1965,2119,2264,2456,
+2726,3027,3261,3365,3348,3261,3158,3072,3001,2910,2774,2626,2552,2607,2755,2906,3006,3062,3107,3150,3191,
+3239,3313,3415,3535,3666,3807,3958,4111,4260,4400,4526,4632,4720,4799,4873,4938,4987,5021,5054,5103,5174,
+5255,5330,5393,5451,5514,5583,5654,5718,5774,5826,5883,5952,6020,6066,6078,6072,6075,6097,6128,6164,6222,
+6313,6409,6462,6452,6407,6370,6361,6376,6402,6434,6467,6498,6533,6580,6642,6706,6763,6812,6850,6863,6846,
+6829,6852,6923,7007,7066,7104,7145,7205,7275,7345,7406,7440,7430,7379,7320,7273,7226,7161,7091,7050,7043,
+7034,6987,6915,6857,6841,6868,6931,7031,7148,7244,7296,7333,7416,7570,7750,7879,7921,7897,7847,7793,7741,
+7689,7635,7575,7509,7446,7394,7349,7307,7275,7264,7269,7272,7259,7231,7188,7130,7067,7019,6996,6984,6950,
+6879,6789,6721,6706,6740,6778,6774,6720,6638,6559,6486,6405,6300,6180,6079,6041,6069,6120,6151,6177,6242,
+6326,6335,6206,6010,5889,5909,6005,6071,6067,6014,5938,5853,5777,5736,5736,5768,5818,5865,5885,5866,5825,
+5795,5785,5772,5734,5677,5626,5594,5575,5554,5519,5454,5357,5241,5138,5072,5043,5030,5010,4977,4942,4905,
+4854,4777,4680,4589,4525,4487,4455,4407,4341,4272,4223,4196,4170,4123,4059,4002,3967,3940,3904,3863,3830,
+3801,3760,3706,3655,3622,3604,3592,3600,3642,3703,3733,3696,3611,3524,3457,3398,3335,3280,3244,3209,3155,
+3091,3046,3024,3000,2963,2930,2914,2901,2871,2831,2806,2800,2792,2771,2749,2738,2731,2714,2681,2642,2602,
+2558,2509,2456,2396,2328,2256,2192,2153,2140,2136,2123,2092,2050,2003,1955,1910,1875,1851,1828,1797,1759,
+1721,1682,1642,1610,1589,1564,1523,1480,1466,1487,1517,1534,1542,1550,1551,1536,1519,1513,1504,1469,1416,
+1378,1364,1344,1292,1219,1155,1107,1067,1030,1003,983,957,917,872,837,816,805,796,785,774,769,
+767,758,733,703,684,680,684,684,678,666,644,613,585,576,585,600,603,586,556,530,519,
+517,514,506,497,483,457,416,372,342,324,308,282,246,211,182,163,148,128,100,67,37,
+10,-16,-44,-69,-88,-104,-124,-147,-167,-182,-193,-204,-212,-213,-211,-219,-239,-263,-280,-293,-308,
+-322,-331,-335,-337,-319,-256,-150,-50,-13,-48,-121,-197,-263,-322,-369,-401,-422,-440,-462,-488,-522,
+-559,-591,-615,-636,-657,-677,-693,-708,-725,-741,-752,-763,-779,-796,-808,-819,-836,-856,-873,-884,-898,
+-912,-923,-926,-928,-935,-943,-951,-961,-976,-987,-989,-985,-985,-992,-1001,-1009,-1014,-1018,-1022,-1024,-1022,
+-1020,-1021,-1029,-1041,-1051,-1053,-1050,-1045,-1042,-1042,-1044,-1049,-1053,-1052,-1047,-1044,-1043,-1047,-1054,-1063,-1070,
+-1072,-1071,-1069,-1066,-1062,-1059,-1058,-1056,-1051,-1043,-1036,-1029,-1020,-1009,-1000,-990,-976,-958,-940,-923,-907,
+-891,-877,-865,-853,-841,-830,-822,-817,-810,-804,-799,-795,-788,-780,-774,-770,-764,-758,-755,-757,-762,
+-768,-772,-776,-781,-787,-791,-795,-799,-805,-814,-824,-835,-849,-863,-876,-887,-898,-914,-934,-956,-979,
+-1002,-1027,-1056,-1081,-1099,-1105,-1107,-1112,-1123,-1136,-1145,-1149,-1149,-1150,-1155,-1162,-1170,-1174,-1175,-1174,-1173,
+-1172,-1170,-1169,-1167,-1163,-1158,-1155,-1155,-1155,-1150,-1140,-1129,-1119,-1109,-1102,-1101,-1103,-1102,-1094,-1085,-1082,
+-1081,-1077,-1069,-1064,-1062,-1058,-1050,-1039,-1031,-1022,-1007,-986,-965,-944,-923,-901,-878,-855,-831,-805,-782,
+-759,-734,-707,-684,-666,-643,-608,-570,-541,-518,-488,-453,-420,-392,-358,-316,-276,-243,-204,-149,-94,
+-55,-21,22,66,88,92,106,126,106,21,-93,-166,-151,-37,171,452,752,1031,1298,1581,1866,
+2099,2261,2387,2511,2624,2731,2879,3085,3255,3263,3093,2868,2708,2619,2545,2480,2473,2539,2626,2671,2663,
+2633,2610,2600,2604,2622,2660,2722,2795,2847,2846,2797,2736,2693,2669,2648,2624,2599,2571,2533,2489,2449,
+2416,2383,2348,2314,2287,2259,2224,2172,2093,1984,1864,1770,1725,1716,1708,1677,1629,1575,1513,1428,1318,
+1202,1105,1024,932,817,693,586,492,392,281,172,74,-21,-122,-218,-297,-368,-432,-461,-427,-352,
+-315,-373,-512,-663,-773,-843,-900,-962,-1020,-1062,-1084,-1098,-1120,-1152,-1181,-1195,-1198,-1201,-1207,-1211,-1217,
+-1252,-1341,-1477,-1618,-1732,-1814,-1879,-1927,-1942,-1916,-1867,-1822,-1793,-1784,-1793,-1811,-1821,-1809,-1788,-1778,-1772,
+-1738,-1672,-1604,-1569,-1563,-1555,-1532,-1506,-1494,-1501,-1529,-1580,-1634,-1664,-1666,-1663,-1668,-1654,-1590,-1488,-1398,
+-1348,-1320,-1282,-1229,-1181,-1151,-1146,-1177,-1246,-1317,-1327,-1239,-1090,-959,-899,-902,-922,-926,-920,-927,-963,
+-1024,-1093,-1148,-1178,-1181,-1168,-1154,-1145,-1137,-1125,-1109,-1095,-1087,-1083,-1077,-1067,-1055,-1044,-1030,-1014,-995,
+-978,-962,-948,-935,-922,-907,-889,-869,-850,-835,-822,-807,-789,-774,-761,-747,-728,-707,-687,-667,-646,
+-625,-603,-576,-540,-497,-456,-416,-374,-327,-280,-236,-193,-146,-94,-42,9,65,125,188,250,309,
+361,404,441,478,514,547,579,615,654,690,717,737,757,779,807,843,886,927,960,987,1016,
+1050,1089,1129,1168,1208,1246,1275,1291,1290,1275,1259,1250,1250,1251,1250,1248,1246,1241,1234,1230,1232,
+1234,1234,1235,1244,1258,1266,1267,1267,1273,1282,1291,1300,1307,1311,1314,1323,1335,1338,1324,1307,1304,
+1316,1321,1305,1274,1249,1239,1240,1244,1247,1248,1246,1240,1224,1193,1147,1103,1082,1089,1054,1055,1047,
+1031,1020,1020,1026,1028,1026,1026,1027,1027,1025,1020,1015,1010,1009,1011,1015,1019,1026,1035,1047,1060,
+1074,1088,1102,1117,1135,1156,1177,1195,1210,1224,1237,1250,1266,1287,1314,1343,1371,1395,1418,1447,1490,
+1540,1581,1603,1620,1651,1697,1748,1803,1857,1883,1854,1787,1745,1770,1832,1868,1857,1827,1802,1764,1691,
+1593,1500,1422,1352,1286,1227,1173,1112,1048,991,946,904,854,799,746,691,631,573,522,475,424,
+367,310,252,184,91,-25,-142,-229,-274,-289,-300,-313,-312,-289,-259,-250,-277,-332,-402,-483,-562,
+-612,-616,-592,-581,-606,-654,-715,-798,-914,-1036,-1116,-1139,-1134,-1132,-1134,-1127,-1122,-1140,-1174,-1195,-1203,
+-1234,-1300,-1341,-1280,-1140,-1061,-1175,-1459,-1748,-1881,-1839,-1730,-1667,-1681,-1736,-1798,-1870,-1964,-2081,-2201,-2308,
+-2382,-2410,-2399,-2376,-2366,-2364,-2356,-2357,-2392,-2445,-2467,-2451,-2480,-2631,-2855,-3005,-2990,-2883,-2820,-2854,-2933,
+-2994,-3033,-3068,-3093,-3094,-3085,-3092,-3116,-3133,-3138,-3150,-3186,-3231,-3261,-3268,-3267,-3273,-3282,-3282,-3271,-3264,
+-3269,-3276,-3260,-3217,-3174,-3165,-3188,-3206,-3181,-3111,-3033,-2992,-3008,-3065,-3126,-3156,-3149,-3134,-3136,-3158,-3187,
+-3210,-3227,-3244,-3263,-3282,-3300,-3315,-3328,-3342,-3359,-3378,-3394,-3411,-3437,-3473,-3511,-3546,-3581,-3627,-3685,-3744,
+-3791,-3829,-3865,-3894,-3892,-3837,-3747,-3669,-3644,-3676,-3731,-3778,-3810,-3853,-3934,-4060,-4205,-4329,-4413,-4471,-4532,
+-4606,-4679,-4736,-4782,-4830,-4883,-4930,-4962,-4980,-4991,-5003,-5026,-5071,-5143,-5229,-5310,-5375,-5427,-5481,-5542,-5608,
+-5679,-5750,-5813,-5861,-5894,-5926,-5961,-5998,-6038,-6091,-6165,-6251,-6334,-6412,-6496,-6592,-6691,-6777,-6843,-6891,-6928,
+-6964,-7001,-7039,-7072,-7105,-7142,-7180,-7213,-7240,-7270,-7306,-7337,-7356,-7371,-7388,-7401,-7404,-7403,-7407,-7416,-7418,
+-7411,-7402,-7399,-7394,-7379,-7357,-7341,-7337,-7344,-7351,-7349,-7339,-7329,-7327,-7327,-7321,-7299,-7255,-7190,-7120,-7065,
+-7033,-7009,-6980,-6953,-6945,-6954,-6957,-6941,-6913,-6886,-6865,-6844,-6812,-6749,-6649,-6541,-6466,-6436,-6431,-6437,-6450,
+-6450,-6387,-6245,-6087,-5993,-5971,-5956,-5896,-5798,-5693,-5595,-5513,-5457,-5424,-5382,-5306,-5200,-5080,-4954,-4825,-4708,
+-4615,-4529,-4431,-4321,-4213,-4111,-4012,-3934,-3884,-3834,-3743,-3614,-3501,-3434,-3378,-3284,-3143,-2988,-2852,-2742,-2656,
+-2588,-2530,-2478,-2433,-2384,-2307,-2188,-2049,-1923,-1820,-1720,-1620,-1525,-1420,-1273,-1087,-906,-769,-655,-531,-422,
+-399,-488,-622,-704,-705,-671,-653,-654,-648,-624,-590,-547,-489,-423,-376,-367,-377,-364,-297,-186,-64,
+40,126,203,280,350,406,458,521,593,647,661,653,669,724,790,827,841,868,935,1029,1120,
+1189,1240,1288,1347,1414,1475,1526,1589,1684,1794,1885,1968,2104,2338,2624,2858,2970,2979,2950,2938,2956,
+2973,2941,2840,2718,2662,2718,2836,2925,2947,2941,2966,3043,3155,3286,3424,3562,3696,3831,3974,4120,4261,
+4390,4508,4615,4707,4786,4855,4913,4956,4986,5013,5050,5106,5180,5262,5336,5395,5444,5499,5565,5634,5695,
+5749,5803,5866,5937,6002,6042,6042,6020,6009,6028,6065,6104,6154,6232,6324,6386,6389,6351,6319,6317,6337,
+6365,6394,6428,6465,6507,6557,6614,6672,6726,6773,6803,6800,6767,6741,6763,6834,6915,6975,7021,7077,7148,
+7223,7295,7365,7412,7410,7355,7284,7228,7184,7136,7090,7066,7064,7058,7029,6985,6944,6913,6890,6885,6912,
+6967,7022,7061,7099,7173,7301,7465,7621,7731,7780,7778,7754,7733,7721,7696,7634,7541,7448,7384,7350,7326,
+7298,7270,7248,7233,7217,7191,7150,7102,7061,7035,7009,6957,6867,6758,6681,6679,6759,6873,6950,6945,6868,
+6759,6658,6579,6518,6449,6338,6179,6020,5924,5905,5936,6010,6160,6375,6545,6544,6373,6161,6036,6009,6011,
+5984,5917,5818,5701,5600,5552,5570,5635,5716,5791,5833,5831,5799,5778,5787,5802,5793,5753,5706,5667,5640,
+5622,5607,5574,5501,5389,5271,5180,5125,5087,5053,5026,5012,5003,4980,4926,4841,4740,4645,4571,4520,4476,
+4425,4366,4309,4261,4215,4168,4119,4070,4021,3978,3947,3929,3908,3865,3805,3746,3703,3672,3647,3646,3696,
+3794,3890,3918,3858,3750,3651,3575,3500,3417,3346,3304,3271,3218,3153,3109,3091,3072,3035,2998,2979,2965,
+2932,2885,2849,2831,2814,2788,2766,2756,2750,2735,2709,2680,2649,2612,2563,2505,2439,2365,2287,2217,2167,
+2143,2134,2122,2097,2060,2018,1976,1934,1895,1862,1832,1799,1759,1712,1667,1634,1622,1618,1591,1531,1468,
+1446,1472,1511,1529,1531,1534,1537,1530,1521,1518,1511,1481,1433,1393,1371,1342,1285,1208,1139,1092,1062,
+1038,1013,983,945,904,867,838,818,806,797,785,769,758,757,752,729,692,662,651,653,657,
+658,648,624,588,557,545,550,557,554,535,507,484,477,483,488,482,466,447,423,392,358,
+330,308,286,257,225,193,165,143,127,108,81,47,15,-9,-34,-63,-94,-118,-135,-152,-172,
+-190,-203,-216,-234,-250,-256,-253,-256,-272,-292,-305,-312,-323,-338,-350,-361,-377,-385,-352,-272,-180,
+-129,-139,-187,-243,-297,-345,-387,-417,-439,-458,-476,-499,-530,-566,-597,-621,-645,-672,-695,-712,-725,
+-740,-753,-762,-771,-785,-800,-811,-820,-833,-850,-864,-876,-889,-904,-914,-917,-921,-929,-937,-942,-949,
+-961,-971,-973,-969,-971,-980,-991,-998,-1004,-1009,-1012,-1011,-1007,-1003,-1003,-1010,-1019,-1027,-1030,-1027,-1022,
+-1017,-1014,-1014,-1019,-1025,-1026,-1024,-1018,-1014,-1015,-1022,-1032,-1038,-1038,-1037,-1036,-1036,-1032,-1025,-1019,-1016,
+-1011,-1005,-997,-987,-976,-966,-958,-950,-936,-918,-900,-885,-872,-857,-843,-830,-820,-809,-800,-791,-785,
+-780,-775,-770,-764,-757,-751,-745,-740,-734,-730,-729,-731,-736,-742,-747,-752,-756,-760,-766,-771,-775,
+-781,-788,-797,-809,-822,-837,-852,-864,-876,-892,-914,-937,-960,-982,-1007,-1035,-1061,-1077,-1082,-1083,-1087,
+-1098,-1112,-1121,-1123,-1121,-1119,-1121,-1126,-1135,-1142,-1147,-1147,-1147,-1146,-1147,-1147,-1147,-1144,-1139,-1136,-1135,
+-1135,-1130,-1120,-1109,-1100,-1092,-1087,-1085,-1086,-1082,-1072,-1060,-1054,-1053,-1051,-1047,-1043,-1040,-1035,-1025,-1014,
+-1006,-998,-986,-967,-947,-928,-909,-888,-865,-840,-815,-789,-768,-747,-722,-693,-668,-652,-633,-602,-562,
+-529,-505,-479,-449,-420,-393,-358,-313,-271,-239,-204,-153,-95,-49,-13,29,77,110,124,136,154,
+153,106,16,-84,-149,-130,6,258,567,873,1158,1437,1711,1963,2192,2407,2590,2717,2820,2981,3211,
+3394,3398,3233,3044,2933,2869,2773,2654,2589,2611,2668,2695,2677,2637,2601,2579,2578,2601,2649,2720,2802,
+2863,2874,2838,2791,2756,2724,2684,2645,2626,2619,2598,2555,2508,2472,2442,2411,2384,2367,2353,2323,2264,
+2174,2064,1954,1873,1833,1821,1810,1780,1734,1678,1605,1509,1395,1285,1198,1121,1027,905,778,668,571,
+467,354,246,152,56,-50,-157,-251,-334,-405,-445,-428,-377,-360,-427,-562,-700,-796,-851,-892,-939,
+-988,-1025,-1044,-1057,-1077,-1106,-1133,-1148,-1152,-1157,-1168,-1180,-1200,-1252,-1356,-1502,-1647,-1756,-1823,-1866,-1895,
+-1901,-1870,-1810,-1743,-1696,-1687,-1712,-1748,-1765,-1756,-1739,-1732,-1726,-1695,-1637,-1583,-1563,-1568,-1571,-1564,-1557,
+-1556,-1554,-1560,-1589,-1632,-1657,-1652,-1643,-1652,-1650,-1590,-1471,-1354,-1292,-1276,-1261,-1229,-1192,-1170,-1171,-1206,
+-1282,-1366,-1386,-1293,-1121,-968,-906,-922,-947,-940,-914,-914,-958,-1034,-1109,-1157,-1171,-1164,-1153,-1147,-1141,
+-1127,-1107,-1088,-1075,-1067,-1061,-1055,-1048,-1040,-1032,-1023,-1009,-989,-967,-949,-936,-925,-912,-897,-880,-860,
+-840,-825,-815,-805,-793,-781,-772,-760,-740,-716,-692,-670,-649,-629,-608,-581,-546,-506,-469,-434,-393,
+-344,-295,-251,-208,-159,-107,-54,-4,46,99,153,210,269,327,376,417,454,491,525,556,589,
+625,659,687,710,733,757,786,820,861,903,938,967,994,1025,1057,1091,1127,1166,1205,1237,1258,
+1261,1249,1231,1219,1217,1218,1219,1218,1214,1206,1195,1187,1184,1181,1177,1179,1193,1215,1231,1238,1245,
+1256,1271,1284,1292,1297,1299,1300,1304,1310,1311,1303,1296,1298,1308,1309,1290,1258,1230,1216,1216,1222,
+1226,1221,1207,1187,1166,1141,1108,1076,1057,1054,1071,1053,1043,1042,1048,1053,1051,1044,1040,1040,1041,
+1039,1036,1033,1030,1028,1028,1033,1039,1043,1048,1060,1075,1090,1102,1115,1131,1148,1166,1187,1208,1229,
+1245,1259,1273,1288,1307,1330,1355,1382,1406,1426,1443,1467,1507,1558,1602,1629,1653,1687,1729,1772,1819,
+1871,1900,1873,1810,1781,1826,1901,1935,1911,1878,1866,1850,1792,1694,1589,1497,1415,1338,1273,1218,1161,
+1100,1042,994,950,902,851,797,740,680,622,570,520,469,414,359,303,239,156,53,-54,-140,
+-189,-207,-211,-207,-192,-167,-154,-175,-227,-290,-349,-405,-464,-515,-544,-551,-558,-586,-645,-729,-829,
+-929,-1007,-1048,-1057,-1057,-1067,-1082,-1094,-1107,-1132,-1168,-1198,-1229,-1286,-1368,-1412,-1348,-1194,-1086,-1160,-1417,
+-1707,-1860,-1834,-1718,-1637,-1642,-1710,-1800,-1897,-2001,-2110,-2215,-2309,-2383,-2426,-2434,-2424,-2414,-2403,-2385,-2373,
+-2390,-2423,-2425,-2389,-2397,-2535,-2763,-2930,-2928,-2817,-2744,-2784,-2881,-2950,-2970,-2976,-2987,-2995,-2994,-2999,-3024,
+-3061,-3095,-3121,-3141,-3158,-3173,-3183,-3184,-3177,-3173,-3185,-3206,-3215,-3201,-3174,-3150,-3130,-3111,-3102,-3114,-3135,
+-3132,-3090,-3036,-3019,-3054,-3111,-3141,-3129,-3097,-3080,-3089,-3118,-3152,-3183,-3207,-3224,-3237,-3249,-3263,-3275,-3282,
+-3288,-3301,-3325,-3352,-3377,-3401,-3428,-3459,-3490,-3522,-3564,-3619,-3678,-3727,-3765,-3805,-3850,-3878,-3855,-3777,-3681,
+-3622,-3625,-3672,-3724,-3757,-3790,-3860,-3981,-4125,-4248,-4329,-4385,-4445,-4515,-4580,-4636,-4690,-4746,-4797,-4829,-4843,
+-4852,-4865,-4887,-4924,-4979,-5053,-5134,-5208,-5267,-5319,-5375,-5440,-5514,-5589,-5659,-5716,-5758,-5790,-5820,-5853,-5887,
+-5930,-5992,-6075,-6167,-6252,-6332,-6418,-6512,-6606,-6687,-6749,-6793,-6826,-6857,-6892,-6928,-6962,-6996,-7037,-7079,-7114,
+-7144,-7175,-7211,-7242,-7262,-7277,-7293,-7303,-7303,-7301,-7306,-7314,-7315,-7308,-7302,-7300,-7292,-7275,-7257,-7249,-7253,
+-7263,-7270,-7272,-7269,-7265,-7262,-7258,-7247,-7219,-7168,-7099,-7035,-6999,-6989,-6984,-6967,-6948,-6945,-6952,-6945,-6913,
+-6873,-6844,-6829,-6815,-6780,-6704,-6584,-6459,-6380,-6362,-6385,-6420,-6453,-6456,-6384,-6237,-6081,-5988,-5959,-5929,-5860,
+-5769,-5685,-5611,-5538,-5477,-5428,-5370,-5284,-5175,-5063,-4951,-4840,-4742,-4664,-4587,-4483,-4352,-4213,-4089,-3992,-3934,
+-3906,-3865,-3771,-3643,-3536,-3473,-3414,-3311,-3165,-3014,-2887,-2787,-2710,-2647,-2591,-2541,-2496,-2443,-2354,-2225,-2087,
+-1975,-1886,-1798,-1702,-1605,-1491,-1332,-1139,-962,-833,-732,-629,-550,-546,-624,-720,-763,-739,-687,-643,-615,
+-591,-563,-523,-464,-387,-309,-253,-229,-218,-190,-123,-26,71,146,197,245,308,379,431,448,442,
+440,448,453,461,496,573,666,736,781,834,922,1033,1135,1209,1260,1308,1366,1432,1494,1547,1604,
+1677,1749,1795,1824,1900,2070,2302,2510,2631,2683,2719,2778,2857,2922,2936,2887,2819,2796,2844,2913,2939,
+2917,2908,2968,3099,3261,3420,3567,3702,3831,3961,4092,4222,4344,4457,4561,4651,4726,4792,4851,4896,4924,
+4942,4966,5007,5069,5150,5243,5328,5391,5436,5485,5547,5614,5674,5727,5783,5845,5909,5962,5991,5984,5955,
+5936,5951,5991,6034,6080,6145,6228,6293,6307,6281,6258,6266,6294,6323,6349,6384,6430,6481,6532,6579,6624,
+6666,6704,6727,6721,6688,6664,6685,6750,6825,6886,6941,7009,7088,7165,7236,7305,7357,7362,7314,7241,7175,
+7127,7089,7061,7049,7048,7044,7033,7021,7006,6974,6927,6884,6868,6877,6894,6913,6940,6988,7060,7156,7272,
+7389,7482,7540,7578,7622,7667,7681,7634,7538,7442,7385,7370,7366,7341,7290,7231,7186,7160,7142,7121,7097,
+7074,7041,6972,6856,6717,6609,6590,6681,6848,7009,7079,7031,6907,6769,6651,6572,6540,6542,6517,6404,6214,
+6026,5902,5844,5854,5972,6210,6461,6558,6433,6186,5969,5853,5809,5780,5732,5648,5533,5425,5368,5375,5425,
+5496,5584,5670,5723,5737,5744,5775,5819,5839,5823,5792,5760,5728,5697,5676,5660,5622,5543,5441,5346,5268,
+5193,5119,5061,5034,5032,5035,5023,4981,4900,4789,4677,4594,4546,4516,4485,4442,4389,4338,4296,4255,4196,
+4112,4037,4004,4004,3989,3932,3864,3827,3820,3802,3760,3739,3787,3894,3988,3999,3926,3827,3754,3704,3635,
+3531,3424,3349,3301,3255,3211,3188,3184,3168,3125,3075,3041,3018,2983,2935,2893,2861,2832,2804,2787,2782,
+2775,2755,2729,2705,2680,2647,2602,2549,2488,2416,2339,2268,2213,2179,2159,2142,2114,2074,2032,1993,1954,
+1909,1862,1820,1785,1746,1698,1652,1628,1637,1653,1633,1562,1480,1444,1465,1502,1515,1509,1508,1515,1518,
+1515,1514,1512,1493,1451,1403,1359,1311,1250,1184,1128,1092,1068,1048,1021,981,934,891,859,834,814,
+803,801,796,781,762,750,737,711,673,639,620,615,618,622,619,598,566,536,521,516,511,
+503,493,478,461,452,456,463,459,440,413,385,359,336,315,293,267,237,209,182,153,128,
+109,93,69,34,0,-28,-52,-79,-110,-137,-157,-175,-195,-213,-225,-239,-260,-283,-297,-299,-300,
+-309,-319,-324,-327,-336,-348,-356,-362,-376,-392,-384,-340,-283,-250,-258,-291,-325,-354,-383,-412,-439,
+-462,-482,-500,-521,-549,-581,-610,-633,-657,-685,-710,-728,-743,-757,-768,-775,-782,-794,-808,-819,-828,
+-839,-852,-862,-870,-881,-894,-903,-908,-914,-924,-932,-936,-940,-948,-956,-958,-956,-960,-970,-979,-986,
+-990,-994,-995,-993,-989,-988,-990,-994,-998,-1002,-1003,-1001,-996,-988,-983,-981,-985,-992,-998,-1000,-997,
+-992,-991,-997,-1006,-1010,-1009,-1006,-1008,-1010,-1006,-996,-986,-980,-976,-971,-962,-949,-936,-924,-916,-908,
+-896,-880,-862,-847,-833,-818,-804,-792,-782,-774,-765,-757,-750,-746,-743,-738,-732,-725,-721,-717,-711,
+-705,-702,-704,-706,-708,-712,-720,-728,-732,-735,-738,-744,-750,-756,-764,-774,-785,-797,-811,-827,-842,
+-856,-873,-895,-919,-942,-963,-985,-1008,-1031,-1047,-1054,-1057,-1063,-1074,-1085,-1091,-1091,-1090,-1089,-1088,-1091,
+-1098,-1108,-1116,-1118,-1117,-1117,-1118,-1120,-1122,-1122,-1121,-1118,-1116,-1113,-1107,-1097,-1088,-1081,-1077,-1074,-1070,
+-1066,-1060,-1049,-1037,-1030,-1029,-1029,-1028,-1024,-1019,-1012,-1002,-991,-982,-973,-960,-942,-924,-908,-891,-870,
+-847,-822,-797,-773,-751,-732,-709,-680,-653,-634,-618,-593,-558,-524,-497,-471,-442,-414,-388,-356,-314,
+-270,-233,-198,-153,-99,-51,-12,30,81,129,159,175,186,190,168,109,11,-94,-150,-94,94,
+377,691,1001,1299,1581,1848,2117,2390,2632,2796,2902,3030,3204,3339,3337,3222,3111,3066,3027,2923,2784,
+2696,2693,2723,2727,2696,2653,2617,2593,2591,2613,2656,2717,2785,2839,2858,2846,2826,2809,2779,2726,2676,
+2660,2667,2661,2628,2587,2558,2537,2508,2472,2440,2408,2360,2286,2191,2090,2000,1937,1907,1896,1880,1847,
+1798,1741,1669,1576,1469,1370,1290,1214,1117,994,870,763,668,564,450,341,240,135,18,-98,-200,
+-289,-369,-427,-442,-430,-444,-526,-664,-804,-897,-937,-950,-965,-990,-1017,-1033,-1042,-1054,-1074,-1097,-1111,
+-1119,-1133,-1156,-1186,-1229,-1298,-1404,-1537,-1666,-1762,-1820,-1851,-1866,-1862,-1827,-1761,-1684,-1627,-1613,-1639,-1678,
+-1702,-1702,-1694,-1690,-1684,-1659,-1620,-1594,-1597,-1618,-1639,-1652,-1660,-1655,-1633,-1611,-1618,-1647,-1660,-1640,-1616,
+-1622,-1631,-1583,-1465,-1340,-1271,-1259,-1253,-1227,-1194,-1179,-1191,-1237,-1323,-1419,-1442,-1337,-1145,-982,-930,-960,
+-985,-960,-919,-918,-972,-1054,-1123,-1157,-1157,-1141,-1130,-1130,-1130,-1118,-1099,-1082,-1070,-1059,-1047,-1036,-1028,
+-1020,-1013,-1007,-998,-982,-961,-940,-926,-914,-902,-889,-875,-857,-837,-819,-808,-801,-793,-785,-777,-766,
+-749,-725,-700,-675,-651,-628,-605,-578,-544,-508,-474,-443,-405,-358,-311,-267,-224,-175,-122,-70,-20,
+28,77,124,173,229,288,341,384,422,461,498,531,563,597,630,662,691,722,752,781,813,
+849,889,925,957,984,1010,1034,1059,1090,1129,1170,1205,1227,1232,1220,1201,1186,1180,1180,1180,1178,
+1170,1160,1150,1146,1145,1144,1143,1149,1167,1190,1210,1222,1231,1244,1260,1272,1281,1284,1283,1279,1276,
+1276,1277,1277,1279,1287,1295,1293,1275,1248,1222,1207,1202,1203,1199,1185,1162,1142,1138,1143,1142,1125,
+1097,1071,1109,1075,1063,1066,1073,1073,1066,1058,1056,1057,1055,1050,1047,1048,1049,1048,1049,1055,1062,
+1066,1070,1081,1098,1115,1129,1143,1160,1177,1194,1213,1235,1259,1280,1297,1312,1330,1351,1376,1402,1426,
+1448,1464,1476,1492,1523,1565,1605,1636,1666,1702,1740,1776,1822,1881,1921,1904,1849,1827,1876,1953,1986,
+1963,1939,1944,1948,1906,1815,1705,1599,1499,1405,1327,1264,1205,1144,1086,1036,992,946,894,837,778,
+720,666,615,563,511,458,407,353,294,220,131,36,-42,-90,-112,-116,-108,-87,-69,-79,-128,
+-196,-254,-295,-331,-374,-421,-457,-481,-507,-557,-642,-750,-851,-923,-963,-984,-996,-1004,-1017,-1040,-1072,
+-1104,-1128,-1145,-1171,-1222,-1307,-1404,-1452,-1400,-1271,-1180,-1239,-1454,-1700,-1828,-1795,-1682,-1605,-1619,-1703,-1816,
+-1935,-2052,-2157,-2242,-2308,-2367,-2419,-2456,-2474,-2476,-2460,-2428,-2396,-2391,-2406,-2401,-2367,-2371,-2493,-2703,-2860,
+-2858,-2747,-2680,-2732,-2837,-2888,-2866,-2835,-2848,-2890,-2922,-2935,-2950,-2984,-3030,-3068,-3089,-3103,-3122,-3141,-3134,
+-3092,-3043,-3035,-3073,-3115,-3119,-3092,-3067,-3057,-3045,-3024,-3011,-3021,-3034,-3030,-3018,-3029,-3068,-3101,-3098,-3067,
+-3041,-3044,-3068,-3097,-3126,-3155,-3180,-3194,-3196,-3196,-3203,-3213,-3223,-3231,-3248,-3277,-3312,-3340,-3359,-3379,-3408,
+-3442,-3477,-3516,-3565,-3620,-3666,-3698,-3733,-3785,-3841,-3861,-3819,-3729,-3642,-3603,-3618,-3654,-3685,-3717,-3786,-3906,
+-4049,-4167,-4243,-4298,-4359,-4426,-4488,-4543,-4598,-4653,-4693,-4712,-4719,-4729,-4753,-4791,-4843,-4905,-4973,-5038,-5098,
+-5155,-5212,-5273,-5341,-5414,-5488,-5555,-5607,-5646,-5677,-5709,-5744,-5783,-5833,-5904,-5992,-6083,-6168,-6250,-6336,-6425,
+-6509,-6582,-6640,-6684,-6716,-6746,-6781,-6820,-6856,-6893,-6933,-6976,-7015,-7048,-7083,-7119,-7148,-7166,-7181,-7195,-7203,
+-7202,-7201,-7207,-7215,-7214,-7208,-7203,-7199,-7186,-7167,-7155,-7158,-7172,-7186,-7196,-7203,-7204,-7199,-7191,-7180,-7161,
+-7124,-7070,-7009,-6964,-6951,-6962,-6972,-6968,-6962,-6963,-6960,-6931,-6877,-6825,-6800,-6798,-6793,-6758,-6667,-6525,-6378,
+-6290,-6285,-6337,-6404,-6454,-6457,-6379,-6226,-6065,-5962,-5914,-5868,-5800,-5731,-5678,-5627,-5560,-5489,-5427,-5358,-5266,
+-5159,-5055,-4959,-4866,-4778,-4701,-4619,-4510,-4368,-4213,-4071,-3971,-3927,-3916,-3883,-3792,-3669,-3571,-3510,-3444,-3335,
+-3194,-3061,-2952,-2862,-2784,-2714,-2650,-2593,-2542,-2483,-2392,-2265,-2134,-2031,-1952,-1872,-1783,-1682,-1552,-1378,-1183,
+-1021,-914,-836,-766,-725,-742,-798,-840,-834,-789,-732,-674,-619,-570,-527,-478,-411,-328,-244,-175,-121,
+-72,-16,54,133,208,269,316,363,426,497,547,549,509,460,427,410,407,431,495,582,662,
+721,782,868,975,1080,1165,1230,1284,1339,1398,1457,1513,1573,1643,1708,1745,1759,1801,1919,2100,2282,
+2421,2521,2611,2707,2798,2868,2901,2898,2889,2906,2955,2996,2998,2983,3012,3120,3280,3440,3570,3679,3787,
+3904,4031,4155,4272,4381,4484,4574,4644,4697,4746,4796,4837,4858,4871,4894,4938,5003,5092,5199,5300,5370,
+5413,5456,5518,5589,5651,5704,5756,5809,5857,5894,5913,5908,5884,5866,5879,5921,5968,6015,6075,6149,6210,
+6227,6212,6204,6224,6257,6284,6304,6335,6382,6436,6484,6523,6552,6577,6603,6626,6632,6619,6606,6622,6672,
+6738,6800,6862,6936,7020,7100,7172,7235,7280,7288,7249,7180,7107,7048,7014,7006,7016,7024,7023,7021,7023,
+7017,6984,6929,6880,6854,6845,6837,6835,6847,6872,6900,6934,6990,7070,7154,7229,7301,7386,7473,7526,7517,
+7459,7395,7364,7370,7384,7371,7318,7247,7188,7157,7137,7108,7067,7013,6933,6813,6666,6543,6499,6562,6716,
+6902,7034,7047,6947,6799,6666,6563,6490,6470,6518,6579,6558,6420,6224,6045,5905,5810,5809,5937,6124,6214,
+6117,5893,5682,5565,5535,5546,5553,5524,5450,5361,5291,5244,5208,5206,5282,5433,5590,5690,5740,5788,5845,
+5881,5880,5863,5847,5820,5780,5748,5738,5729,5685,5606,5516,5429,5333,5223,5123,5061,5042,5052,5068,5063,
+5013,4916,4804,4716,4669,4647,4627,4595,4552,4515,4491,4460,4384,4263,4151,4102,4098,4075,4010,3961,3979,
+4030,4034,3967,3894,3888,3946,3998,3987,3924,3863,3837,3826,3779,3677,3550,3442,3367,3312,3275,3262,3263,
+3246,3194,3129,3081,3050,3019,2979,2935,2889,2843,2808,2796,2798,2790,2766,2740,2720,2700,2670,2632,2592,
+2544,2479,2403,2328,2266,2222,2193,2170,2139,2092,2040,1994,1953,1907,1854,1805,1766,1728,1683,1638,1618,
+1635,1664,1655,1590,1505,1460,1467,1490,1491,1476,1472,1484,1496,1498,1499,1504,1498,1468,1416,1353,1287,
+1225,1172,1132,1102,1076,1049,1016,972,923,881,851,825,802,791,793,797,788,765,741,719,690,
+655,623,601,588,584,586,586,572,545,519,501,486,471,464,468,471,458,438,425,425,425,
+410,380,347,319,298,282,262,236,210,188,166,139,110,88,72,50,17,-20,-49,-72,-96,
+-125,-153,-177,-199,-222,-242,-255,-267,-284,-305,-323,-332,-337,-342,-346,-348,-351,-359,-371,-377,-378,
+-383,-395,-402,-390,-370,-361,-371,-388,-400,-408,-420,-441,-467,-492,-514,-534,-557,-584,-613,-639,-659,
+-680,-703,-725,-743,-758,-772,-782,-788,-793,-803,-815,-826,-836,-846,-856,-863,-868,-877,-889,-899,-905,
+-912,-920,-927,-930,-932,-938,-944,-947,-948,-952,-959,-965,-969,-972,-973,-973,-971,-971,-975,-979,-981,
+-981,-980,-979,-976,-971,-964,-958,-955,-956,-962,-969,-974,-975,-972,-971,-977,-985,-988,-985,-981,-983,
+-985,-981,-969,-956,-948,-943,-937,-928,-915,-900,-887,-876,-868,-857,-844,-829,-812,-796,-780,-766,-755,
+-748,-741,-733,-724,-715,-711,-708,-704,-697,-692,-690,-689,-682,-675,-673,-676,-679,-678,-680,-689,-700,
+-707,-710,-713,-718,-726,-733,-742,-752,-761,-772,-786,-803,-819,-835,-852,-874,-900,-925,-945,-961,-977,
+-994,-1009,-1021,-1029,-1038,-1048,-1055,-1056,-1055,-1056,-1060,-1062,-1064,-1070,-1079,-1088,-1090,-1089,-1089,-1090,-1091,
+-1092,-1095,-1097,-1095,-1091,-1086,-1080,-1072,-1064,-1060,-1061,-1061,-1057,-1047,-1035,-1024,-1015,-1009,-1008,-1009,-1008,
+-1004,-998,-990,-981,-971,-961,-949,-934,-917,-901,-887,-871,-850,-825,-801,-777,-754,-731,-710,-689,-665,
+-640,-619,-602,-581,-552,-521,-493,-466,-434,-401,-373,-346,-312,-270,-228,-190,-149,-103,-57,-15,26,
+77,132,180,209,223,227,219,184,107,-5,-105,-120,-7,224,527,858,1188,1497,1782,2069,2375,
+2667,2884,3006,3086,3167,3224,3209,3142,3095,3090,3069,2983,2869,2803,2800,2808,2783,2732,2684,2648,2623,
+2613,2625,2657,2702,2754,2800,2828,2839,2845,2844,2819,2769,2721,2706,2716,2715,2690,2663,2653,2651,2632,
+2586,2521,2443,2355,2262,2172,2089,2018,1968,1947,1939,1922,1885,1837,1787,1730,1653,1562,1475,1400,1324,
+1225,1105,984,880,783,677,560,444,336,228,114,4,-96,-190,-282,-361,-410,-441,-492,-597,-747,
+-897,-995,-1026,-1017,-1009,-1022,-1043,-1051,-1042,-1033,-1040,-1059,-1078,-1098,-1123,-1158,-1202,-1261,-1342,-1445,-1559,
+-1667,-1755,-1816,-1850,-1857,-1836,-1785,-1711,-1633,-1578,-1560,-1573,-1600,-1625,-1641,-1649,-1651,-1644,-1631,-1620,-1624,
+-1645,-1677,-1709,-1737,-1752,-1740,-1701,-1660,-1647,-1654,-1647,-1610,-1574,-1573,-1581,-1540,-1434,-1323,-1266,-1259,-1249,
+-1213,-1175,-1164,-1186,-1243,-1341,-1444,-1470,-1357,-1156,-998,-962,-1006,-1031,-1002,-965,-978,-1040,-1112,-1160,-1174,
+-1161,-1137,-1121,-1118,-1118,-1109,-1092,-1077,-1064,-1048,-1032,-1021,-1015,-1007,-996,-986,-981,-972,-955,-935,-918,
+-905,-893,-883,-874,-861,-841,-820,-806,-799,-793,-785,-777,-767,-753,-732,-707,-680,-652,-624,-599,-572,
+-539,-504,-473,-445,-411,-369,-327,-287,-246,-197,-144,-93,-44,5,54,97,139,190,249,303,349,
+390,432,472,508,540,573,608,642,675,710,743,774,806,841,878,915,948,975,998,1017,1037,
+1066,1103,1142,1172,1187,1187,1174,1158,1144,1138,1137,1136,1132,1124,1116,1113,1116,1122,1129,1135,1145,
+1160,1179,1196,1209,1219,1229,1239,1252,1264,1271,1269,1262,1258,1262,1268,1271,1271,1271,1272,1269,1257,
+1240,1223,1210,1200,1190,1177,1157,1138,1134,1156,1193,1215,1202,1158,1109,1121,1088,1078,1081,1084,1080,
+1073,1069,1071,1072,1068,1062,1062,1069,1072,1070,1069,1074,1083,1088,1092,1103,1120,1139,1155,1172,1189,
+1206,1220,1238,1261,1286,1311,1332,1351,1371,1395,1422,1449,1473,1494,1510,1521,1530,1546,1573,1604,1633,
+1664,1699,1735,1774,1830,1904,1963,1964,1923,1904,1945,2010,2036,2017,2000,2014,2031,2007,1932,1827,1711,
+1592,1482,1390,1315,1248,1184,1127,1079,1034,985,931,872,812,756,706,657,607,554,504,455,404,
+347,278,197,112,43,1,-19,-27,-24,-13,-13,-49,-115,-181,-223,-247,-275,-311,-346,-373,-402,
+-451,-534,-645,-758,-841,-881,-901,-927,-958,-977,-985,-1008,-1055,-1099,-1112,-1104,-1121,-1194,-1309,-1417,-1462,
+-1416,-1314,-1250,-1316,-1512,-1730,-1839,-1798,-1681,-1600,-1612,-1699,-1823,-1958,-2094,-2210,-2285,-2326,-2360,-2406,-2460,
+-2502,-2517,-2499,-2454,-2406,-2383,-2388,-2390,-2373,-2387,-2492,-2668,-2797,-2788,-2690,-2641,-2701,-2789,-2796,-2719,-2658,
+-2686,-2778,-2861,-2895,-2902,-2918,-2951,-2989,-3021,-3053,-3094,-3128,-3119,-3051,-2966,-2930,-2969,-3037,-3070,-3054,-3019,
+-2989,-2960,-2921,-2890,-2886,-2906,-2933,-2961,-2999,-3036,-3049,-3027,-2997,-2992,-3016,-3050,-3076,-3096,-3117,-3138,-3146,
+-3141,-3133,-3133,-3143,-3158,-3172,-3193,-3224,-3260,-3290,-3308,-3326,-3355,-3395,-3436,-3474,-3518,-3567,-3609,-3636,-3662,
+-3710,-3778,-3833,-3834,-3771,-3677,-3601,-3571,-3578,-3599,-3636,-3712,-3835,-3975,-4088,-4161,-4216,-4275,-4340,-4400,-4453,
+-4503,-4545,-4573,-4589,-4603,-4624,-4658,-4705,-4765,-4831,-4890,-4940,-4990,-5048,-5112,-5178,-5243,-5312,-5383,-5446,-5495,
+-5531,-5563,-5597,-5636,-5684,-5744,-5819,-5905,-5993,-6079,-6166,-6252,-6333,-6404,-6467,-6522,-6567,-6602,-6634,-6673,-6716,
+-6757,-6795,-6836,-6878,-6919,-6957,-6994,-7029,-7054,-7070,-7084,-7099,-7106,-7105,-7104,-7110,-7117,-7118,-7113,-7108,-7099,
+-7082,-7066,-7063,-7076,-7097,-7116,-7129,-7134,-7131,-7120,-7107,-7090,-7062,-7019,-6967,-6926,-6909,-6921,-6947,-6966,-6974,
+-6979,-6982,-6965,-6912,-6839,-6784,-6767,-6774,-6774,-6734,-6632,-6474,-6313,-6221,-6229,-6304,-6389,-6443,-6438,-6351,-6195,
+-6028,-5913,-5852,-5805,-5755,-5716,-5693,-5656,-5587,-5505,-5432,-5360,-5269,-5164,-5066,-4981,-4895,-4802,-4708,-4613,-4504,
+-4371,-4217,-4067,-3958,-3914,-3911,-3886,-3801,-3687,-3599,-3544,-3478,-3372,-3247,-3139,-3054,-2974,-2890,-2805,-2721,-2642,
+-2571,-2502,-2416,-2304,-2186,-2086,-2003,-1924,-1840,-1739,-1602,-1425,-1243,-1103,-1017,-957,-910,-899,-930,-964,-957,
+-903,-836,-774,-711,-640,-572,-517,-464,-399,-320,-239,-160,-83,-6,68,136,200,265,334,407,478,
+548,616,670,688,662,608,553,516,499,507,544,605,670,724,775,839,924,1020,1111,1187,1246,
+1296,1347,1400,1456,1521,1599,1679,1735,1767,1808,1900,2044,2202,2342,2463,2575,2678,2762,2822,2863,2895,
+2933,2992,3063,3116,3139,3160,3225,3347,3487,3603,3682,3746,3826,3930,4049,4166,4272,4371,4464,4540,4591,
+4624,4662,4713,4758,4783,4796,4816,4856,4920,5016,5136,5251,5327,5368,5407,5466,5536,5597,5646,5694,5742,
+5783,5814,5835,5838,5823,5810,5822,5863,5918,5974,6037,6105,6154,6167,6159,6164,6196,6233,6256,6272,6300,
+6344,6391,6429,6455,6471,6482,6496,6519,6543,6555,6554,6558,6587,6642,6709,6779,6856,6943,7030,7106,7162,
+7195,7201,7173,7111,7031,6960,6926,6937,6970,6995,7001,6997,6996,6983,6943,6886,6841,6822,6813,6799,6784,
+6784,6796,6809,6822,6846,6884,6926,6967,7018,7093,7178,7244,7270,7261,7244,7243,7270,7312,7336,7321,7275,
+7227,7191,7146,7070,6962,6838,6706,6573,6466,6429,6485,6615,6771,6898,6947,6895,6772,6646,6558,6491,6421,
+6383,6428,6532,6593,6540,6398,6236,6080,5931,5822,5797,5833,5835,5738,5578,5446,5394,5414,5470,5527,5546,
+5517,5454,5368,5238,5064,4930,4957,5171,5453,5663,5767,5828,5886,5924,5925,5913,5909,5898,5862,5825,5816,
+5821,5798,5732,5649,5568,5477,5363,5247,5162,5121,5114,5116,5104,5062,4997,4934,4891,4862,4826,4776,4723,
+4685,4672,4681,4673,4603,4472,4342,4270,4238,4187,4116,4098,4176,4281,4303,4210,4082,4005,3992,3997,3983,
+3953,3931,3926,3924,3898,3831,3736,3632,3530,3431,3350,3304,3288,3267,3218,3154,3102,3067,3037,3001,2956,
+2900,2841,2800,2790,2795,2788,2764,2740,2726,2710,2683,2651,2623,2589,2532,2455,2375,2305,2250,2213,2186,
+2154,2104,2039,1978,1930,1888,1842,1796,1754,1717,1675,1632,1607,1614,1636,1636,1591,1526,1483,1477,1481,
+1468,1445,1439,1452,1468,1474,1478,1488,1493,1477,1430,1363,1290,1226,1179,1142,1109,1075,1042,1006,962,
+915,875,846,818,790,772,771,778,774,756,732,706,678,648,621,597,577,562,557,554,543,
+524,504,484,461,439,434,451,465,451,415,383,374,377,374,352,317,280,252,231,211,190,
+170,155,139,116,88,65,46,22,-11,-47,-78,-102,-125,-152,-181,-208,-234,-256,-274,-286,-293,
+-302,-316,-333,-347,-358,-367,-376,-383,-390,-400,-414,-426,-430,-431,-436,-443,-446,-444,-442,-445,-447,
+-446,-447,-457,-478,-504,-528,-552,-576,-601,-627,-653,-676,-696,-713,-729,-745,-759,-773,-786,-796,-802,
+-806,-814,-823,-831,-839,-848,-856,-861,-866,-875,-888,-900,-908,-913,-918,-923,-925,-928,-932,-937,-941,
+-944,-948,-951,-953,-956,-957,-958,-956,-954,-956,-962,-968,-970,-967,-963,-960,-957,-953,-949,-944,-940,
+-938,-939,-944,-949,-950,-949,-949,-955,-963,-966,-962,-958,-958,-958,-954,-943,-930,-920,-912,-903,-892,
+-880,-867,-853,-839,-828,-818,-808,-796,-780,-762,-746,-734,-726,-720,-715,-707,-696,-686,-680,-677,-673,
+-666,-660,-660,-660,-654,-645,-643,-648,-652,-650,-650,-657,-670,-679,-685,-691,-699,-706,-713,-721,-730,
+-738,-747,-761,-778,-795,-811,-829,-852,-879,-905,-925,-939,-949,-960,-974,-987,-999,-1010,-1019,-1023,-1021,
+-1021,-1027,-1037,-1044,-1047,-1050,-1057,-1064,-1066,-1065,-1065,-1066,-1064,-1064,-1066,-1068,-1067,-1062,-1056,-1052,-1046,
+-1039,-1037,-1042,-1047,-1043,-1030,-1014,-1002,-995,-991,-990,-989,-986,-982,-975,-968,-960,-951,-939,-926,-911,
+-894,-880,-867,-852,-830,-803,-778,-757,-735,-710,-685,-665,-647,-628,-607,-587,-565,-540,-514,-489,-462,
+-429,-391,-357,-329,-301,-265,-223,-184,-147,-106,-59,-12,31,76,129,183,228,254,265,267,251,
+200,104,-7,-72,-29,139,410,742,1095,1434,1744,2045,2368,2697,2961,3109,3160,3172,3175,3157,3120,
+3094,3090,3074,3020,2957,2929,2930,2913,2854,2782,2726,2689,2654,2627,2626,2653,2693,2734,2774,2811,2842,
+2864,2870,2852,2814,2778,2763,2763,2757,2739,2725,2732,2747,2745,2702,2611,2484,2351,2241,2160,2094,2030,
+1981,1960,1958,1947,1913,1872,1838,1805,1754,1680,1603,1531,1454,1356,1238,1120,1013,909,793,669,552,
+453,371,294,212,117,7,-110,-216,-298,-365,-449,-577,-744,-910,-1022,-1056,-1039,-1026,-1043,-1069,-1068,
+-1036,-1003,-996,-1014,-1042,-1074,-1110,-1149,-1195,-1256,-1342,-1446,-1553,-1653,-1743,-1816,-1857,-1856,-1813,-1739,-1653,
+-1582,-1541,-1528,-1530,-1540,-1562,-1594,-1619,-1624,-1616,-1613,-1626,-1650,-1676,-1703,-1736,-1768,-1784,-1769,-1727,-1682,
+-1653,-1637,-1608,-1560,-1521,-1510,-1503,-1455,-1362,-1277,-1247,-1254,-1243,-1197,-1150,-1136,-1161,-1223,-1324,-1428,-1453,
+-1342,-1150,-1011,-999,-1058,-1089,-1068,-1051,-1080,-1141,-1189,-1208,-1205,-1186,-1158,-1132,-1118,-1109,-1096,-1077,-1057,
+-1038,-1018,-1003,-1001,-1007,-1004,-989,-973,-965,-959,-947,-930,-914,-900,-887,-877,-872,-862,-844,-821,-805,
+-797,-791,-782,-773,-764,-752,-735,-711,-683,-653,-624,-598,-571,-539,-505,-474,-446,-414,-377,-340,-305,
+-266,-219,-167,-117,-68,-18,29,71,111,158,213,269,317,362,407,449,487,522,557,593,627,
+660,693,725,757,790,826,863,899,930,956,977,995,1015,1043,1076,1105,1123,1126,1120,1112,1103,
+1098,1096,1098,1099,1097,1091,1088,1090,1098,1109,1121,1132,1144,1156,1167,1180,1193,1202,1208,1215,1232,
+1254,1269,1270,1266,1271,1287,1301,1297,1279,1260,1250,1247,1244,1239,1233,1222,1206,1187,1168,1152,1144,
+1155,1189,1231,1251,1229,1176,1121,1106,1089,1089,1091,1090,1085,1081,1081,1083,1083,1079,1076,1081,1090,
+1093,1090,1088,1094,1104,1112,1119,1131,1147,1164,1181,1199,1217,1232,1247,1265,1288,1313,1337,1361,1383,
+1405,1431,1460,1488,1513,1536,1557,1572,1579,1584,1596,1616,1640,1667,1697,1733,1781,1852,1943,2016,2035,
+2009,1993,2022,2070,2089,2070,2053,2061,2080,2072,2020,1927,1806,1675,1555,1454,1368,1290,1223,1169,1123,
+1075,1022,966,909,850,794,742,692,641,590,542,495,445,387,319,241,162,100,66,51,42,
+35,27,0,-56,-127,-179,-200,-213,-241,-276,-298,-314,-348,-420,-528,-647,-747,-801,-818,-834,-876,
+-929,-957,-964,-986,-1036,-1077,-1075,-1055,-1081,-1183,-1323,-1432,-1459,-1400,-1302,-1255,-1339,-1553,-1788,-1910,-1870,
+-1738,-1634,-1625,-1702,-1826,-1968,-2113,-2237,-2316,-2349,-2367,-2399,-2450,-2498,-2517,-2496,-2445,-2390,-2362,-2369,-2385,
+-2393,-2421,-2512,-2648,-2740,-2726,-2654,-2633,-2694,-2751,-2708,-2586,-2499,-2527,-2640,-2754,-2818,-2843,-2861,-2889,-2925,
+-2963,-3002,-3038,-3064,-3060,-3013,-2943,-2896,-2909,-2961,-2998,-2986,-2936,-2879,-2832,-2795,-2772,-2772,-2796,-2837,-2888,
+-2941,-2981,-2988,-2967,-2947,-2952,-2982,-3015,-3038,-3053,-3068,-3082,-3088,-3085,-3078,-3076,-3084,-3098,-3114,-3133,-3162,
+-3199,-3231,-3253,-3271,-3300,-3343,-3388,-3428,-3469,-3515,-3554,-3578,-3598,-3636,-3700,-3769,-3802,-3774,-3694,-3601,-3535,
+-3510,-3522,-3569,-3657,-3780,-3912,-4018,-4089,-4143,-4198,-4256,-4311,-4359,-4399,-4429,-4451,-4473,-4502,-4536,-4571,-4615,
+-4674,-4739,-4795,-4839,-4887,-4949,-5019,-5086,-5149,-5213,-5279,-5338,-5385,-5422,-5456,-5494,-5539,-5592,-5658,-5734,-5816,
+-5900,-5987,-6078,-6166,-6240,-6300,-6353,-6406,-6452,-6489,-6524,-6566,-6613,-6657,-6697,-6738,-6781,-6824,-6866,-6904,-6937,
+-6959,-6975,-6991,-7006,-7014,-7012,-7010,-7015,-7023,-7026,-7023,-7015,-7002,-6987,-6978,-6986,-7005,-7027,-7045,-7057,-7059,
+-7047,-7029,-7013,-6996,-6964,-6917,-6875,-6858,-6872,-6903,-6935,-6957,-6972,-6983,-6981,-6948,-6878,-6800,-6752,-6746,-6756,
+-6748,-6698,-6588,-6425,-6263,-6176,-6197,-6285,-6372,-6412,-6388,-6293,-6141,-5981,-5868,-5810,-5780,-5757,-5746,-5736,-5699,
+-5620,-5527,-5448,-5376,-5289,-5188,-5093,-5011,-4922,-4814,-4699,-4591,-4490,-4375,-4230,-4072,-3947,-3897,-3898,-3884,-3809,
+-3705,-3630,-3587,-3532,-3437,-3330,-3245,-3180,-3109,-3020,-2917,-2807,-2697,-2597,-2512,-2430,-2337,-2237,-2139,-2049,-1964,
+-1880,-1784,-1656,-1495,-1338,-1223,-1148,-1090,-1046,-1042,-1074,-1092,-1052,-966,-878,-807,-741,-667,-595,-533,-474,
+-407,-330,-248,-162,-73,13,89,151,204,265,348,448,541,608,656,705,751,765,734,678,637,
+629,648,682,726,777,828,874,924,989,1071,1157,1230,1286,1331,1378,1431,1488,1556,1643,1738,1817,
+1871,1922,2002,2114,2232,2337,2432,2529,2625,2711,2782,2844,2907,2986,3085,3191,3276,3331,3378,3445,3535,
+3625,3692,3740,3789,3858,3949,4052,4152,4243,4328,4408,4471,4508,4534,4571,4627,4680,4711,4725,4739,4769,
+4828,4928,5061,5189,5273,5314,5347,5394,5449,5498,5543,5596,5654,5706,5747,5776,5786,5777,5767,5779,5821,
+5883,5953,6026,6089,6123,6123,6115,6129,6166,6202,6223,6240,6272,6314,6350,6371,6382,6389,6393,6398,6416,
+6448,6477,6485,6482,6496,6547,6621,6701,6780,6866,6958,7036,7085,7108,7111,7090,7034,6949,6869,6836,6857,
+6905,6940,6950,6945,6937,6917,6874,6821,6782,6766,6760,6746,6726,6714,6714,6723,6739,6758,6775,6780,6780,
+6793,6831,6884,6932,6964,6980,6987,7001,7041,7109,7179,7216,7212,7187,7149,7078,6951,6785,6620,6487,6401,
+6378,6438,6566,6712,6821,6866,6842,6762,6660,6581,6538,6490,6408,6334,6350,6465,6587,6617,6545,6426,6295,
+6155,6013,5901,5822,5747,5653,5565,5522,5532,5577,5637,5687,5703,5678,5626,5530,5334,5031,4751,4694,4927,
+5303,5614,5779,5862,5929,5973,5973,5958,5959,5962,5939,5902,5888,5892,5876,5818,5744,5679,5612,5524,5426,
+5348,5303,5272,5229,5165,5094,5048,5046,5070,5068,5007,4905,4811,4765,4774,4812,4833,4792,4689,4572,4485,
+4416,4329,4248,4249,4354,4475,4494,4386,4229,4108,4047,4033,4045,4065,4067,4042,4003,3972,3953,3924,3859,
+3742,3584,3429,3325,3280,3263,3235,3194,3151,3111,3066,3016,2965,2913,2863,2826,2812,2807,2792,2763,2740,
+2730,2716,2687,2654,2628,2599,2549,2478,2403,2335,2276,2229,2193,2158,2107,2036,1962,1904,1865,1832,1793,
+1752,1713,1678,1642,1611,1593,1590,1585,1564,1529,1501,1489,1479,1458,1433,1423,1431,1444,1452,1460,1473,
+1483,1474,1437,1378,1310,1246,1191,1145,1103,1066,1033,1000,959,915,877,846,816,784,759,751,752,
+749,738,721,700,675,649,624,601,574,550,533,524,515,504,490,471,443,415,407,422,434,
+416,373,334,322,331,339,328,296,252,211,180,158,142,129,119,106,89,69,49,26,-3,
+-41,-80,-113,-140,-164,-188,-215,-244,-270,-289,-302,-309,-314,-319,-328,-343,-361,-378,-394,-409,-422,
+-432,-440,-455,-473,-485,-486,-481,-479,-481,-480,-477,-473,-471,-473,-481,-499,-523,-547,-568,-590,-615,
+-640,-664,-686,-707,-727,-743,-755,-767,-780,-792,-803,-811,-818,-823,-829,-834,-839,-844,-850,-855,-858,
+-862,-871,-885,-899,-908,-913,-917,-921,-925,-927,-929,-932,-937,-943,-946,-947,-947,-948,-951,-951,-949,
+-946,-947,-951,-955,-957,-954,-949,-945,-943,-942,-941,-938,-933,-928,-925,-925,-926,-926,-924,-925,-930,
+-936,-938,-934,-931,-929,-927,-921,-913,-905,-896,-885,-873,-860,-848,-835,-820,-804,-789,-778,-770,-760,
+-746,-729,-715,-706,-699,-694,-688,-681,-671,-659,-652,-650,-646,-638,-631,-630,-631,-626,-617,-615,-621,
+-627,-627,-626,-630,-640,-650,-659,-669,-679,-686,-690,-696,-705,-714,-724,-736,-753,-770,-787,-807,-831,
+-858,-884,-904,-917,-927,-938,-949,-959,-969,-979,-988,-992,-991,-992,-1002,-1017,-1026,-1029,-1030,-1035,-1041,
+-1043,-1042,-1043,-1043,-1042,-1041,-1042,-1044,-1041,-1034,-1027,-1024,-1021,-1015,-1013,-1019,-1027,-1026,-1012,-995,-982,
+-976,-973,-970,-967,-963,-958,-951,-944,-937,-927,-916,-904,-890,-875,-861,-848,-834,-812,-784,-758,-738,
+-719,-695,-667,-646,-631,-616,-597,-573,-550,-527,-502,-479,-455,-427,-389,-350,-317,-289,-258,-221,-186,
+-152,-113,-62,-8,40,84,129,180,231,271,296,308,308,282,214,112,23,12,118,336,636,
+982,1336,1672,1993,2325,2666,2957,3127,3179,3182,3192,3202,3187,3152,3122,3100,3074,3050,3045,3045,3010,
+2935,2857,2809,2774,2726,2673,2653,2675,2711,2739,2761,2796,2839,2873,2885,2877,2857,2835,2817,2805,2798,
+2792,2791,2800,2816,2825,2795,2698,2544,2381,2260,2188,2131,2064,2004,1977,1976,1968,1938,1905,1890,1880,
+1849,1791,1723,1654,1577,1479,1365,1252,1144,1030,902,769,659,593,570,559,522,430,291,136,-1,
+-111,-206,-313,-456,-638,-825,-959,-1005,-992,-985,-1016,-1054,-1054,-1013,-972,-961,-977,-1003,-1038,-1080,-1120,
+-1159,-1211,-1294,-1403,-1517,-1624,-1720,-1797,-1836,-1823,-1762,-1672,-1583,-1525,-1508,-1515,-1519,-1523,-1545,-1588,-1623,
+-1624,-1606,-1602,-1624,-1652,-1670,-1686,-1712,-1741,-1755,-1742,-1711,-1674,-1641,-1607,-1564,-1515,-1475,-1450,-1421,-1360,
+-1277,-1217,-1213,-1235,-1231,-1186,-1135,-1114,-1131,-1187,-1280,-1376,-1395,-1290,-1124,-1022,-1041,-1117,-1156,-1145,-1141,
+-1176,-1223,-1244,-1239,-1228,-1212,-1185,-1149,-1120,-1099,-1079,-1054,-1027,-998,-971,-956,-963,-982,-992,-982,-965,
+-953,-946,-936,-924,-912,-899,-886,-875,-868,-859,-842,-820,-804,-794,-787,-778,-769,-762,-752,-736,-713,
+-686,-656,-629,-604,-579,-548,-512,-480,-451,-419,-384,-348,-316,-281,-237,-186,-136,-88,-39,8,51,
+91,136,187,239,288,334,379,421,460,498,537,576,612,643,672,701,732,765,802,839,872,
+900,924,945,965,986,1011,1037,1055,1061,1057,1053,1053,1056,1060,1063,1068,1073,1076,1074,1073,1076,
+1083,1094,1106,1121,1135,1146,1154,1165,1178,1187,1191,1199,1222,1252,1270,1270,1267,1283,1316,1338,1328,
+1291,1256,1240,1242,1248,1249,1245,1233,1211,1186,1168,1162,1166,1177,1196,1214,1214,1186,1142,1106,1097,
+1098,1101,1101,1098,1097,1096,1095,1095,1094,1093,1095,1101,1107,1110,1109,1111,1119,1129,1137,1147,1160,
+1173,1187,1201,1219,1237,1253,1271,1293,1317,1339,1360,1384,1408,1431,1457,1485,1514,1540,1565,1593,1617,
+1628,1629,1634,1648,1668,1687,1711,1747,1805,1888,1984,2059,2084,2067,2054,2075,2114,2132,2118,2097,2094,
+2106,2108,2076,1995,1875,1740,1617,1513,1418,1331,1261,1210,1164,1111,1053,999,946,890,831,770,711,
+653,601,556,512,461,404,338,263,187,129,99,89,80,64,36,-10,-79,-147,-181,-185,-192,
+-222,-257,-275,-288,-333,-421,-534,-639,-715,-750,-762,-784,-834,-892,-925,-938,-966,-1014,-1045,-1037,-1032,
+-1092,-1225,-1368,-1452,-1446,-1366,-1265,-1230,-1337,-1584,-1855,-2003,-1968,-1820,-1689,-1658,-1726,-1848,-1984,-2114,-2226,
+-2306,-2349,-2371,-2395,-2432,-2469,-2482,-2458,-2406,-2355,-2335,-2348,-2375,-2404,-2449,-2531,-2630,-2688,-2675,-2636,-2646,
+-2709,-2745,-2678,-2537,-2421,-2402,-2471,-2569,-2657,-2724,-2776,-2823,-2874,-2922,-2945,-2932,-2909,-2907,-2922,-2915,-2870,
+-2817,-2796,-2803,-2797,-2753,-2689,-2643,-2633,-2651,-2680,-2717,-2764,-2822,-2879,-2919,-2930,-2920,-2910,-2914,-2934,-2960,
+-2985,-3004,-3017,-3026,-3033,-3038,-3039,-3037,-3038,-3045,-3059,-3077,-3104,-3139,-3173,-3197,-3216,-3244,-3285,-3331,-3373,
+-3414,-3455,-3492,-3518,-3538,-3569,-3622,-3686,-3733,-3733,-3676,-3582,-3496,-3454,-3470,-3535,-3635,-3752,-3864,-3953,-4019,
+-4072,-4121,-4168,-4212,-4253,-4287,-4314,-4339,-4372,-4413,-4450,-4480,-4515,-4568,-4630,-4686,-4734,-4788,-4856,-4929,-4996,
+-5056,-5116,-5175,-5228,-5274,-5317,-5360,-5405,-5453,-5509,-5577,-5653,-5732,-5814,-5900,-5990,-6075,-6143,-6197,-6246,-6296,
+-6342,-6381,-6419,-6461,-6508,-6552,-6592,-6634,-6679,-6725,-6768,-6806,-6838,-6863,-6882,-6899,-6914,-6920,-6919,-6918,-6923,
+-6931,-6936,-6933,-6923,-6909,-6897,-6898,-6914,-6933,-6949,-6963,-6973,-6972,-6954,-6933,-6920,-6905,-6874,-6830,-6801,-6808,
+-6844,-6886,-6918,-6940,-6956,-6964,-6951,-6901,-6822,-6752,-6724,-6733,-6742,-6720,-6653,-6536,-6376,-6222,-6145,-6176,-6271,
+-6351,-6370,-6325,-6227,-6090,-5953,-5857,-5815,-5804,-5801,-5799,-5786,-5739,-5652,-5552,-5470,-5397,-5311,-5213,-5119,-5032,
+-4935,-4815,-4687,-4575,-4483,-4383,-4246,-4081,-3945,-3890,-3901,-3900,-3836,-3739,-3672,-3643,-3604,-3523,-3427,-3354,-3302,
+-3239,-3145,-3027,-2894,-2759,-2635,-2534,-2449,-2369,-2284,-2197,-2109,-2022,-1937,-1845,-1731,-1597,-1469,-1371,-1298,-1232,
+-1180,-1166,-1183,-1185,-1131,-1033,-932,-851,-783,-716,-649,-580,-506,-427,-344,-257,-165,-73,10,83,146,
+200,261,348,461,560,610,624,653,712,762,755,707,677,699,754,808,853,903,965,1026,1082,
+1143,1214,1289,1349,1392,1431,1479,1536,1596,1665,1754,1853,1941,2005,2063,2136,2221,2295,2347,2393,2457,
+2544,2643,2741,2835,2935,3051,3186,3320,3425,3492,3537,3581,3628,3673,3715,3763,3824,3897,3976,4057,4134,
+4207,4278,4344,4397,4430,4455,4493,4549,4603,4640,4656,4665,4682,4734,4838,4983,5124,5217,5262,5288,5318,
+5351,5386,5432,5497,5573,5642,5695,5729,5740,5732,5725,5739,5783,5849,5931,6016,6080,6102,6088,6073,6085,
+6116,6144,6160,6182,6221,6264,6288,6291,6291,6297,6302,6305,6315,6344,6380,6399,6401,6415,6467,6550,6635,
+6714,6797,6887,6963,7006,7020,7018,6993,6931,6842,6767,6744,6774,6822,6855,6866,6865,6856,6837,6803,6765,
+6735,6718,6706,6689,6664,6639,6621,6616,6625,6641,6650,6645,6634,6632,6647,6671,6693,6712,6725,6731,6737,
+6766,6833,6915,6973,6990,6980,6951,6882,6758,6604,6475,6408,6403,6455,6557,6686,6795,6845,6836,6791,6729,
+6668,6624,6592,6534,6428,6322,6307,6418,6581,6680,6667,6576,6460,6345,6233,6128,6031,5941,5870,5833,5835,
+5858,5883,5904,5907,5875,5818,5758,5670,5464,5101,4717,4555,4737,5134,5506,5733,5861,5957,6021,6032,6015,
+6014,6025,6012,5976,5950,5946,5931,5886,5828,5780,5735,5675,5608,5556,5524,5483,5405,5291,5180,5122,5139,
+5190,5199,5123,4993,4883,4840,4858,4901,4926,4907,4842,4758,4677,4588,4482,4396,4392,4476,4564,4561,4453,
+4302,4172,4095,4082,4132,4204,4228,4176,4085,4022,4015,4027,3998,3886,3705,3517,3386,3334,3323,3314,3292,
+3262,3217,3147,3070,3013,2983,2962,2938,2909,2874,2828,2779,2745,2730,2717,2688,2650,2615,2581,2533,2474,
+2417,2367,2316,2261,2208,2161,2109,2040,1963,1898,1857,1828,1795,1753,1713,1685,1663,1633,1593,1555,1532,
+1521,1512,1501,1492,1481,1462,1439,1422,1418,1423,1434,1449,1465,1472,1462,1431,1384,1327,1263,1196,1135,
+1085,1050,1025,999,963,922,884,852,821,788,762,747,740,733,722,709,693,671,647,625,602,
+573,542,518,502,493,486,478,460,430,398,381,380,377,354,318,290,284,295,305,299,273,
+231,184,146,122,111,103,92,77,62,50,37,14,-21,-64,-107,-145,-173,-193,-211,-234,-266,
+-296,-315,-325,-333,-341,-349,-358,-375,-397,-417,-432,-446,-457,-461,-461,-468,-485,-500,-501,-490,-481,
+-480,-481,-480,-482,-490,-504,-523,-546,-570,-589,-605,-624,-648,-671,-691,-708,-728,-747,-762,-774,-787,
+-802,-815,-823,-829,-835,-841,-845,-848,-851,-855,-858,-860,-861,-864,-871,-882,-894,-903,-909,-914,-922,
+-928,-931,-929,-929,-934,-941,-944,-944,-943,-945,-948,-949,-947,-944,-941,-940,-942,-943,-941,-936,-932,
+-933,-935,-937,-934,-928,-921,-915,-911,-907,-905,-903,-904,-907,-908,-906,-902,-899,-896,-891,-884,-878,
+-875,-869,-859,-846,-832,-818,-804,-788,-771,-755,-741,-731,-722,-709,-695,-683,-675,-669,-664,-657,-651,
+-642,-631,-623,-621,-618,-611,-603,-600,-600,-597,-590,-589,-595,-603,-607,-607,-609,-615,-622,-630,-640,
+-651,-657,-661,-667,-677,-688,-699,-711,-727,-745,-764,-785,-811,-837,-860,-879,-894,-908,-922,-933,-940,
+-945,-951,-959,-964,-966,-969,-980,-994,-1002,-1003,-1003,-1009,-1016,-1018,-1017,-1017,-1018,-1019,-1020,-1022,-1023,
+-1019,-1011,-1002,-999,-997,-992,-989,-992,-999,-1000,-989,-973,-961,-957,-954,-950,-945,-940,-935,-928,-920,
+-911,-902,-892,-881,-869,-856,-841,-828,-814,-796,-769,-742,-721,-705,-685,-659,-636,-620,-605,-585,-562,
+-539,-516,-490,-463,-440,-418,-388,-350,-314,-284,-254,-223,-191,-160,-122,-72,-14,39,87,131,179,
+231,281,319,341,351,345,307,229,138,91,138,288,527,836,1186,1542,1881,2216,2553,2848,3037,
+3117,3159,3220,3276,3276,3221,3161,3128,3111,3100,3102,3108,3086,3031,2980,2961,2942,2880,2792,2736,2736,
+2751,2746,2734,2753,2802,2848,2870,2877,2881,2877,2861,2847,2852,2871,2885,2886,2886,2890,2869,2780,2619,
+2446,2323,2259,2207,2136,2065,2026,2016,2001,1966,1934,1923,1920,1898,1854,1801,1744,1669,1569,1458,1355,
+1254,1139,999,857,756,728,769,828,835,747,585,403,245,116,0,-123,-272,-459,-661,-817,-882,
+-880,-884,-932,-991,-1008,-982,-956,-953,-961,-970,-991,-1031,-1076,-1112,-1155,-1230,-1340,-1463,-1579,-1674,-1738,
+-1757,-1729,-1662,-1576,-1497,-1457,-1468,-1503,-1529,-1543,-1572,-1622,-1657,-1646,-1609,-1589,-1601,-1620,-1627,-1633,-1654,
+-1679,-1689,-1681,-1666,-1649,-1626,-1591,-1549,-1501,-1453,-1407,-1356,-1294,-1229,-1187,-1188,-1211,-1216,-1184,-1137,-1106,
+-1107,-1147,-1225,-1303,-1311,-1218,-1089,-1031,-1082,-1170,-1211,-1202,-1199,-1226,-1255,-1256,-1240,-1229,-1219,-1192,-1151,
+-1111,-1082,-1057,-1030,-998,-962,-927,-905,-908,-930,-951,-955,-949,-940,-933,-924,-917,-911,-903,-890,-877,
+-867,-857,-841,-820,-804,-794,-786,-777,-770,-763,-753,-737,-715,-688,-660,-635,-612,-588,-557,-521,-487,
+-457,-425,-389,-353,-322,-291,-251,-204,-155,-107,-59,-11,33,77,122,169,216,261,304,346,386,
+424,464,506,547,584,616,645,673,703,735,771,806,838,865,890,913,936,958,980,998,1008,
+1009,1008,1011,1021,1032,1038,1040,1044,1051,1057,1059,1059,1061,1066,1074,1086,1102,1120,1134,1145,1158,
+1172,1182,1187,1197,1219,1243,1251,1239,1231,1252,1297,1330,1323,1286,1254,1247,1256,1262,1258,1248,1232,
+1209,1183,1169,1171,1179,1180,1173,1161,1146,1126,1107,1097,1114,1118,1116,1110,1108,1109,1111,1110,1109,
+1110,1113,1117,1121,1124,1127,1131,1138,1147,1153,1160,1169,1182,1193,1203,1214,1232,1251,1270,1291,1316,
+1341,1361,1380,1403,1428,1451,1474,1501,1529,1554,1580,1612,1642,1658,1662,1669,1687,1708,1723,1742,1781,
+1849,1939,2028,2089,2104,2088,2078,2098,2138,2165,2163,2145,2133,2137,2142,2119,2045,1925,1789,1668,1563,
+1462,1369,1296,1245,1197,1140,1080,1029,982,927,863,791,718,648,591,548,508,459,403,342,275,
+204,147,115,102,88,62,23,-30,-96,-153,-174,-170,-176,-208,-245,-267,-290,-346,-437,-534,-613,
+-668,-700,-722,-751,-795,-839,-868,-894,-938,-992,-1024,-1034,-1072,-1179,-1323,-1433,-1462,-1417,-1328,-1242,-1228,
+-1356,-1618,-1899,-2055,-2026,-1881,-1744,-1703,-1766,-1887,-2013,-2116,-2196,-2263,-2317,-2355,-2381,-2406,-2429,-2434,-2409,
+-2363,-2322,-2307,-2317,-2343,-2384,-2448,-2533,-2612,-2650,-2645,-2637,-2672,-2739,-2775,-2723,-2593,-2445,-2345,-2323,-2372,
+-2465,-2559,-2629,-2689,-2765,-2844,-2867,-2805,-2724,-2718,-2797,-2857,-2800,-2652,-2526,-2491,-2504,-2492,-2441,-2405,-2425,
+-2491,-2565,-2631,-2694,-2759,-2816,-2852,-2867,-2869,-2868,-2870,-2879,-2901,-2930,-2956,-2971,-2979,-2988,-3000,-3007,-3002,
+-2994,-2994,-3007,-3027,-3052,-3082,-3112,-3137,-3158,-3184,-3222,-3266,-3307,-3345,-3381,-3416,-3447,-3476,-3510,-3554,-3607,
+-3654,-3665,-3621,-3531,-3442,-3405,-3441,-3531,-3640,-3740,-3819,-3882,-3937,-3989,-4035,-4072,-4105,-4140,-4175,-4208,-4241,
+-4279,-4320,-4351,-4375,-4406,-4455,-4515,-4573,-4628,-4691,-4763,-4837,-4903,-4962,-5019,-5071,-5117,-5163,-5214,-5269,-5321,
+-5371,-5427,-5495,-5574,-5655,-5735,-5817,-5901,-5979,-6043,-6095,-6142,-6190,-6236,-6277,-6317,-6361,-6405,-6447,-6486,-6529,
+-6576,-6623,-6666,-6703,-6737,-6766,-6790,-6808,-6819,-6824,-6824,-6825,-6830,-6837,-6841,-6839,-6828,-6814,-6806,-6814,-6832,
+-6848,-6858,-6869,-6878,-6876,-6858,-6839,-6828,-6815,-6786,-6750,-6740,-6767,-6815,-6859,-6890,-6910,-6924,-6923,-6893,-6831,
+-6753,-6699,-6694,-6720,-6729,-6693,-6610,-6486,-6330,-6185,-6116,-6156,-6255,-6329,-6332,-6273,-6178,-6065,-5957,-5884,-5857,
+-5854,-5850,-5838,-5813,-5759,-5673,-5577,-5493,-5416,-5329,-5229,-5128,-5029,-4919,-4793,-4666,-4559,-4475,-4385,-4258,-4100,
+-3967,-3916,-3935,-3944,-3885,-3787,-3720,-3699,-3672,-3600,-3507,-3438,-3397,-3343,-3248,-3116,-2970,-2825,-2695,-2585,-2490,
+-2406,-2330,-2260,-2188,-2109,-2021,-1929,-1829,-1721,-1616,-1526,-1449,-1379,-1324,-1298,-1292,-1273,-1213,-1118,-1017,-930,
+-858,-796,-730,-651,-561,-469,-381,-291,-197,-110,-34,37,110,177,242,329,442,541,577,565,572,
+634,703,713,672,652,698,782,853,903,958,1034,1115,1186,1252,1321,1387,1433,1462,1493,1538,1593,
+1652,1719,1803,1899,1987,2057,2126,2206,2285,2338,2361,2378,2420,2498,2600,2712,2826,2950,3094,3251,3394,
+3498,3557,3591,3621,3651,3681,3718,3774,3843,3912,3975,4033,4093,4156,4219,4279,4328,4363,4391,4426,4472,
+4522,4563,4587,4595,4605,4651,4758,4911,5057,5155,5204,5229,5249,5270,5301,5354,5430,5512,5585,5642,5678,
+5688,5681,5676,5692,5734,5800,5887,5981,6051,6070,6047,6024,6027,6049,6066,6076,6099,6139,6178,6193,6188,
+6185,6196,6211,6217,6222,6243,6279,6309,6324,6346,6402,6486,6573,6653,6735,6820,6892,6932,6943,6929,6884,
+6800,6705,6648,6652,6694,6738,6764,6780,6787,6782,6762,6739,6720,6708,6695,6677,6653,6623,6589,6556,6533,
+6524,6524,6526,6524,6524,6530,6543,6555,6565,6575,6583,6582,6572,6572,6600,6644,6675,6681,6675,6667,6637,
+6570,6493,6455,6480,6549,6631,6714,6789,6838,6844,6819,6786,6756,6726,6691,6646,6575,6462,6343,6295,6372,
+6535,6679,6718,6649,6532,6426,6353,6298,6238,6173,6122,6099,6096,6093,6084,6073,6043,5976,5886,5814,5745,
+5578,5235,4814,4554,4626,4962,5348,5635,5824,5964,6058,6088,6077,6073,6084,6079,6046,6013,5997,5983,5953,
+5912,5874,5837,5790,5742,5710,5690,5655,5580,5463,5339,5252,5229,5242,5232,5161,5057,4980,4959,4975,4989,
+4984,4956,4912,4859,4799,4723,4631,4554,4533,4566,4593,4559,4462,4340,4225,4142,4122,4182,4281,4334,4291,
+4183,4085,4039,4029,4002,3917,3778,3634,3538,3499,3482,3457,3427,3398,3352,3270,3175,3117,3113,3126,3110,
+3054,2971,2879,2795,2739,2715,2706,2686,2649,2608,2564,2514,2462,2419,2388,2354,2301,2235,2170,2111,2049,
+1980,1916,1868,1835,1799,1754,1712,1689,1680,1658,1607,1541,1492,1474,1475,1478,1477,1474,1464,1443,1418,
+1399,1397,1413,1438,1458,1461,1443,1412,1374,1326,1264,1190,1118,1063,1031,1012,993,964,929,894,863,
+831,801,777,760,747,731,714,699,683,665,644,623,601,573,541,512,490,477,471,464,447,
+419,387,363,343,319,290,266,257,260,266,268,261,241,209,169,132,108,97,88,71,47,
+28,19,12,-7,-42,-85,-127,-163,-191,-205,-215,-235,-272,-312,-339,-354,-368,-384,-397,-408,-425,
+-448,-466,-474,-476,-477,-472,-463,-461,-473,-486,-487,-478,-473,-476,-484,-492,-505,-523,-544,-565,-588,
+-610,-628,-641,-658,-679,-701,-717,-732,-749,-765,-777,-787,-802,-821,-836,-843,-846,-850,-855,-858,-860,
+-865,-871,-874,-874,-873,-874,-878,-885,-893,-900,-905,-913,-923,-932,-933,-929,-927,-931,-937,-941,-940,
+-940,-941,-944,-946,-946,-943,-937,-933,-931,-930,-928,-923,-921,-925,-929,-930,-926,-919,-911,-905,-898,
+-891,-886,-885,-886,-887,-884,-877,-871,-866,-862,-855,-847,-842,-839,-835,-826,-815,-803,-788,-770,-753,
+-738,-724,-709,-696,-686,-674,-661,-649,-641,-636,-630,-623,-617,-610,-601,-593,-590,-588,-582,-575,-570,
+-570,-568,-565,-565,-570,-578,-583,-585,-589,-592,-596,-601,-608,-616,-623,-629,-639,-652,-664,-674,-685,
+-701,-719,-738,-761,-786,-811,-833,-850,-867,-886,-903,-916,-922,-925,-930,-936,-942,-945,-948,-957,-967,
+-973,-973,-973,-979,-988,-992,-990,-988,-989,-993,-996,-999,-1000,-997,-989,-981,-976,-974,-971,-966,-964,
+-967,-968,-961,-949,-940,-936,-934,-929,-923,-918,-914,-906,-896,-886,-876,-866,-856,-847,-835,-821,-807,
+-795,-780,-756,-727,-703,-688,-673,-651,-628,-609,-592,-571,-548,-526,-505,-478,-447,-420,-400,-378,-347,
+-314,-283,-256,-227,-196,-164,-126,-81,-30,22,76,128,180,235,292,341,370,385,392,382,336,
+259,196,193,272,437,692,1023,1386,1736,2071,2402,2706,2927,3058,3157,3265,3343,3334,3254,3177,3140,
+3119,3098,3099,3128,3150,3144,3137,3156,3161,3095,2970,2864,2816,2786,2736,2690,2694,2747,2800,2828,2851,
+2881,2904,2904,2904,2932,2979,3007,3001,2982,2974,2950,2860,2699,2525,2405,2344,2297,2228,2155,2108,2083,
+2052,2006,1964,1940,1922,1895,1863,1837,1803,1737,1635,1524,1429,1341,1229,1084,934,835,830,914,1018,
+1054,975,812,635,480,342,202,60,-89,-264,-460,-626,-708,-726,-752,-828,-914,-956,-955,-953,-963,
+-962,-943,-938,-971,-1024,-1068,-1109,-1174,-1277,-1399,-1516,-1603,-1644,-1634,-1589,-1527,-1462,-1404,-1381,-1413,-1479,
+-1539,-1576,-1615,-1664,-1692,-1667,-1609,-1567,-1558,-1562,-1559,-1560,-1577,-1596,-1602,-1600,-1602,-1608,-1606,-1593,-1569,
+-1525,-1458,-1379,-1313,-1268,-1234,-1207,-1197,-1206,-1212,-1195,-1157,-1117,-1100,-1122,-1178,-1232,-1229,-1153,-1065,-1048,
+-1116,-1199,-1232,-1219,-1214,-1234,-1251,-1244,-1226,-1217,-1208,-1182,-1137,-1092,-1059,-1032,-1006,-975,-939,-899,-866,
+-855,-866,-888,-907,-918,-921,-916,-910,-907,-906,-901,-889,-876,-866,-856,-841,-822,-806,-796,-788,-780,
+-773,-766,-757,-741,-720,-694,-665,-639,-616,-592,-562,-527,-494,-463,-430,-393,-357,-326,-296,-261,-218,
+-173,-128,-84,-37,11,59,107,152,194,236,277,315,351,387,426,467,508,545,578,611,642,
+672,705,738,772,805,836,868,897,924,946,963,974,980,982,986,996,1011,1023,1026,1023,1022,
+1027,1034,1038,1040,1044,1051,1059,1069,1085,1105,1125,1142,1157,1172,1185,1195,1204,1218,1228,1220,1198,
+1186,1207,1255,1293,1296,1274,1259,1263,1272,1268,1253,1239,1228,1213,1193,1179,1179,1182,1171,1148,1124,
+1109,1106,1108,1114,1141,1137,1128,1120,1118,1122,1124,1125,1126,1130,1135,1138,1140,1142,1147,1155,1165,
+1172,1175,1178,1186,1199,1209,1217,1228,1246,1266,1286,1307,1331,1355,1375,1395,1419,1443,1464,1486,1512,
+1539,1561,1585,1616,1646,1664,1672,1687,1716,1744,1762,1784,1833,1915,2008,2083,2119,2117,2095,2088,2112,
+2157,2195,2207,2196,2183,2181,2182,2157,2079,1955,1820,1701,1597,1496,1403,1331,1278,1226,1167,1109,1060,
+1014,959,892,815,729,645,579,538,503,458,403,347,288,226,171,134,111,84,48,7,-38,
+-88,-130,-147,-147,-158,-193,-234,-266,-304,-367,-449,-523,-576,-613,-645,-676,-708,-740,-767,-791,-832,
+-899,-972,-1025,-1077,-1172,-1315,-1441,-1485,-1447,-1373,-1300,-1252,-1269,-1403,-1646,-1898,-2039,-2026,-1911,-1791,-1742,
+-1789,-1905,-2030,-2120,-2175,-2222,-2275,-2323,-2353,-2370,-2383,-2385,-2365,-2330,-2298,-2281,-2275,-2287,-2334,-2420,-2522,
+-2599,-2634,-2643,-2660,-2706,-2771,-2817,-2801,-2702,-2537,-2371,-2278,-2290,-2370,-2436,-2453,-2468,-2550,-2683,-2759,-2711,
+-2610,-2600,-2709,-2796,-2711,-2476,-2262,-2193,-2228,-2246,-2206,-2168,-2199,-2294,-2405,-2505,-2596,-2680,-2743,-2778,-2794,
+-2804,-2813,-2818,-2825,-2845,-2876,-2906,-2925,-2937,-2951,-2965,-2969,-2959,-2943,-2939,-2951,-2972,-2994,-3015,-3037,-3061,
+-3087,-3118,-3153,-3192,-3228,-3261,-3292,-3327,-3367,-3408,-3451,-3496,-3546,-3587,-3593,-3543,-3453,-3375,-3361,-3425,-3533,
+-3638,-3714,-3761,-3799,-3843,-3894,-3940,-3973,-4001,-4034,-4073,-4112,-4149,-4184,-4214,-4237,-4259,-4292,-4342,-4402,-4463,
+-4526,-4596,-4669,-4739,-4802,-4862,-4917,-4965,-5008,-5056,-5116,-5178,-5234,-5283,-5338,-5406,-5488,-5572,-5653,-5731,-5807,
+-5879,-5941,-5992,-6038,-6084,-6130,-6174,-6217,-6262,-6306,-6347,-6387,-6431,-6479,-6526,-6567,-6604,-6639,-6672,-6698,-6714,
+-6722,-6724,-6726,-6729,-6733,-6736,-6738,-6736,-6728,-6715,-6710,-6719,-6738,-6752,-6761,-6772,-6783,-6781,-6765,-6747,-6734,
+-6718,-6692,-6671,-6683,-6726,-6779,-6821,-6850,-6869,-6876,-6861,-6818,-6752,-6684,-6648,-6662,-6699,-6710,-6666,-6573,-6443,
+-6289,-6150,-6087,-6132,-6235,-6309,-6305,-6239,-6148,-6055,-5975,-5926,-5908,-5898,-5877,-5844,-5805,-5753,-5681,-5597,-5513,
+-5431,-5340,-5237,-5124,-5004,-4876,-4746,-4629,-4533,-4456,-4375,-4268,-4137,-4024,-3979,-3994,-3999,-3937,-3835,-3764,-3744,
+-3721,-3651,-3556,-3492,-3464,-3426,-3333,-3192,-3037,-2896,-2773,-2661,-2553,-2455,-2377,-2320,-2267,-2197,-2108,-2014,-1926,
+-1843,-1759,-1673,-1592,-1524,-1476,-1445,-1417,-1374,-1307,-1220,-1125,-1035,-957,-889,-817,-729,-630,-537,-450,-358,
+-265,-187,-126,-64,12,91,164,249,361,463,502,488,492,558,637,659,625,610,660,747,818,
+867,924,1008,1099,1179,1250,1319,1381,1421,1444,1467,1504,1549,1599,1663,1746,1839,1927,2007,2095,2196,
+2291,2356,2389,2415,2459,2527,2614,2709,2815,2940,3088,3246,3384,3476,3526,3563,3606,3651,3690,3727,3771,
+3822,3869,3910,3952,4003,4064,4128,4191,4246,4290,4326,4358,4395,4439,4486,4521,4534,4540,4583,4689,4840,
+4981,5075,5128,5162,5190,5217,5254,5311,5383,5455,5520,5578,5621,5637,5632,5626,5640,5675,5732,5814,5911,
+5986,6007,5983,5956,5954,5972,5988,5999,6018,6050,6079,6090,6088,6089,6105,6127,6139,6145,6161,6192,6224,
+6248,6277,6333,6415,6503,6587,6671,6758,6831,6874,6884,6858,6783,6669,6567,6531,6566,6624,6664,6688,6713,
+6735,6732,6705,6677,6668,6672,6672,6659,6635,6604,6569,6537,6511,6492,6477,6468,6467,6474,6484,6493,6500,
+6508,6521,6534,6535,6519,6495,6479,6471,6460,6444,6440,6455,6473,6478,6484,6526,6613,6714,6791,6833,6854,
+6857,6842,6815,6791,6773,6748,6707,6657,6599,6517,6410,6323,6323,6432,6584,6674,6650,6547,6446,6392,6368,
+6335,6283,6232,6197,6170,6142,6119,6108,6087,6027,5932,5850,5788,5665,5382,4978,4648,4589,4824,5196,5537,
+5785,5959,6072,6121,6123,6119,6126,6127,6107,6077,6056,6040,6018,5988,5952,5911,5865,5823,5794,5775,5748,
+5698,5621,5521,5417,5334,5280,5239,5189,5138,5113,5114,5116,5091,5043,4992,4949,4912,4874,4827,4768,4711,
+4674,4654,4625,4569,4490,4404,4312,4221,4166,4185,4264,4338,4344,4276,4173,4077,4009,3959,3907,3840,3773,
+3729,3700,3655,3587,3525,3488,3450,3373,3276,3221,3232,3260,3242,3157,3033,2904,2791,2716,2685,2681,2672,
+2645,2605,2562,2516,2466,2424,2397,2373,2332,2267,2191,2122,2061,2002,1943,1893,1851,1810,1760,1714,1689,
+1685,1671,1618,1538,1467,1433,1429,1437,1445,1450,1446,1427,1395,1369,1366,1387,1419,1441,1441,1419,1386,
+1349,1306,1248,1175,1103,1046,1013,994,978,957,931,902,873,843,815,794,776,758,736,713,694,
+678,662,644,624,602,575,544,511,483,465,456,448,432,409,384,358,327,287,252,234,234,
+239,238,229,219,206,186,158,125,97,80,66,44,13,-12,-24,-29,-43,-73,-109,-144,-176,
+-202,-215,-223,-244,-287,-336,-372,-393,-412,-431,-443,-451,-463,-482,-494,-493,-485,-477,-470,-463,-461,
+-470,-484,-490,-491,-495,-505,-517,-529,-544,-563,-582,-600,-621,-645,-666,-681,-696,-716,-735,-750,-764,
+-779,-791,-797,-803,-818,-839,-855,-860,-861,-863,-865,-866,-869,-876,-885,-890,-890,-889,-890,-893,-896,
+-900,-902,-905,-911,-921,-930,-931,-927,-925,-929,-934,-937,-937,-938,-940,-941,-943,-943,-941,-934,-927,
+-923,-921,-917,-911,-910,-915,-919,-917,-911,-904,-898,-890,-882,-873,-869,-868,-869,-869,-864,-855,-846,
+-839,-834,-826,-817,-811,-805,-798,-788,-779,-770,-755,-736,-718,-705,-693,-679,-665,-654,-643,-631,-617,
+-608,-603,-597,-591,-585,-580,-573,-565,-560,-557,-554,-549,-545,-543,-542,-540,-540,-544,-550,-554,-559,
+-564,-570,-573,-575,-579,-585,-594,-604,-617,-631,-641,-650,-660,-674,-692,-711,-732,-756,-781,-803,-821,
+-839,-857,-876,-890,-899,-905,-911,-919,-924,-926,-928,-935,-943,-948,-948,-947,-952,-959,-964,-963,-961,
+-962,-965,-969,-970,-970,-969,-965,-961,-958,-956,-952,-945,-939,-936,-936,-933,-926,-919,-915,-912,-906,
+-898,-894,-890,-883,-872,-860,-850,-840,-829,-821,-812,-801,-788,-776,-762,-740,-711,-685,-668,-654,-635,
+-614,-594,-575,-553,-528,-507,-488,-463,-433,-406,-385,-366,-341,-313,-286,-261,-234,-201,-163,-122,-82,
+-42,3,58,120,180,241,303,360,396,416,433,446,434,385,322,285,301,394,590,888,1241,
+1587,1916,2252,2587,2871,3080,3242,3372,3432,3387,3287,3217,3193,3164,3115,3097,3143,3211,3251,3281,3332,
+3368,3316,3176,3024,2915,2826,2733,2667,2672,2729,2779,2802,2828,2878,2927,2953,2977,3026,3088,3122,3113,
+3090,3074,3037,2937,2771,2600,2481,2419,2373,2312,2246,2195,2158,2115,2062,2011,1966,1920,1875,1851,1852,
+1848,1797,1697,1585,1493,1409,1302,1157,1004,902,902,999,1121,1169,1101,956,804,668,521,350,179,
+28,-121,-288,-440,-532,-576,-637,-745,-856,-915,-930,-946,-966,-957,-916,-888,-910,-967,-1022,-1068,-1127,
+-1215,-1325,-1434,-1513,-1538,-1506,-1449,-1397,-1355,-1319,-1309,-1356,-1450,-1545,-1609,-1654,-1696,-1712,-1674,-1601,-1540,
+-1512,-1501,-1490,-1484,-1491,-1501,-1505,-1512,-1531,-1556,-1578,-1596,-1603,-1571,-1482,-1366,-1283,-1257,-1260,-1254,-1236,
+-1225,-1226,-1219,-1190,-1149,-1120,-1123,-1154,-1182,-1172,-1120,-1072,-1079,-1141,-1202,-1220,-1209,-1210,-1229,-1243,-1234,
+-1216,-1205,-1195,-1168,-1123,-1075,-1037,-1009,-984,-956,-923,-885,-847,-822,-817,-832,-857,-881,-894,-893,-888,
+-887,-889,-887,-877,-867,-860,-852,-839,-822,-807,-796,-786,-778,-772,-767,-759,-747,-729,-704,-673,-643,
+-618,-593,-565,-533,-499,-468,-434,-398,-363,-331,-300,-266,-227,-187,-148,-108,-63,-14,36,84,128,
+169,211,251,289,324,359,397,436,473,509,543,579,614,648,681,715,748,783,821,862,899,
+928,947,958,964,967,970,977,989,1003,1013,1014,1008,1004,1005,1011,1017,1023,1030,1041,1051,1059,
+1072,1092,1116,1137,1155,1171,1187,1202,1212,1219,1220,1213,1204,1207,1232,1270,1296,1297,1284,1279,1284,
+1282,1263,1240,1234,1243,1246,1231,1210,1196,1186,1170,1147,1128,1123,1130,1138,1141,1162,1154,1145,1138,
+1137,1138,1139,1140,1145,1150,1152,1153,1155,1161,1168,1176,1183,1190,1193,1196,1205,1216,1227,1235,1247,
+1266,1285,1303,1321,1342,1364,1384,1404,1428,1451,1472,1495,1522,1547,1566,1586,1612,1639,1655,1667,1691,
+1730,1767,1793,1829,1899,1997,2089,2142,2149,2125,2099,2097,2127,2178,2222,2240,2234,2221,2215,2207,2168,
+2080,1953,1820,1705,1607,1515,1430,1363,1310,1255,1197,1143,1095,1044,987,922,846,752,653,577,535,
+507,467,414,360,307,254,204,165,133,95,51,15,-13,-42,-72,-93,-106,-128,-171,-221,-266,
+-315,-378,-450,-507,-542,-562,-580,-604,-632,-661,-685,-713,-767,-853,-947,-1032,-1133,-1275,-1430,-1517,-1493,
+-1405,-1328,-1289,-1280,-1318,-1442,-1647,-1855,-1982,-1996,-1927,-1829,-1760,-1769,-1866,-2000,-2105,-2161,-2199,-2244,-2288,
+-2314,-2323,-2329,-2329,-2316,-2292,-2268,-2244,-2223,-2224,-2279,-2389,-2510,-2593,-2635,-2662,-2697,-2739,-2787,-2833,-2847,
+-2785,-2635,-2461,-2364,-2382,-2442,-2432,-2330,-2245,-2301,-2487,-2655,-2683,-2614,-2600,-2691,-2760,-2649,-2378,-2127,-2036,
+-2067,-2087,-2041,-1992,-2014,-2110,-2230,-2350,-2469,-2580,-2661,-2703,-2720,-2733,-2747,-2759,-2770,-2789,-2816,-2846,-2872,
+-2893,-2911,-2921,-2917,-2900,-2882,-2876,-2885,-2901,-2915,-2927,-2945,-2974,-3008,-3044,-3078,-3112,-3142,-3170,-3198,-3236,
+-3283,-3333,-3383,-3438,-3496,-3535,-3523,-3453,-3359,-3304,-3324,-3408,-3512,-3597,-3648,-3678,-3708,-3749,-3798,-3844,-3879,
+-3910,-3944,-3985,-4024,-4056,-4080,-4098,-4116,-4140,-4178,-4231,-4293,-4359,-4429,-4501,-4570,-4633,-4692,-4751,-4806,-4854,
+-4900,-4954,-5019,-5084,-5141,-5190,-5245,-5313,-5393,-5478,-5560,-5636,-5708,-5776,-5836,-5887,-5933,-5979,-6026,-6071,-6116,
+-6161,-6206,-6249,-6291,-6336,-6383,-6430,-6471,-6508,-6544,-6576,-6601,-6616,-6622,-6623,-6624,-6627,-6629,-6628,-6627,-6626,
+-6621,-6613,-6610,-6620,-6638,-6656,-6670,-6684,-6695,-6694,-6678,-6659,-6641,-6620,-6599,-6598,-6631,-6686,-6736,-6772,-6798,
+-6814,-6810,-6780,-6732,-6675,-6625,-6605,-6626,-6665,-6674,-6627,-6529,-6397,-6246,-6111,-6054,-6103,-6211,-6286,-6278,-6205,
+-6113,-6033,-5976,-5949,-5939,-5920,-5876,-5819,-5768,-5725,-5674,-5606,-5524,-5436,-5345,-5245,-5126,-4987,-4838,-4703,-4595,
+-4509,-4431,-4354,-4273,-4185,-4105,-4064,-4062,-4049,-3982,-3880,-3808,-3786,-3762,-3691,-3596,-3539,-3527,-3505,-3418,-3271,
+-3111,-2972,-2854,-2741,-2624,-2513,-2429,-2373,-2327,-2263,-2175,-2085,-2013,-1957,-1895,-1817,-1733,-1664,-1619,-1586,-1542,
+-1478,-1399,-1314,-1224,-1134,-1050,-974,-894,-803,-707,-619,-532,-436,-340,-272,-233,-192,-128,-51,20,102,
+208,312,364,370,392,466,550,579,557,549,596,674,737,785,846,932,1025,1107,1179,1247,1305,
+1345,1371,1398,1430,1467,1511,1575,1660,1753,1842,1932,2038,2157,2269,2354,2416,2470,2528,2590,2654,2725,
+2811,2920,3053,3195,3317,3398,3449,3500,3567,3638,3691,3722,3743,3762,3782,3804,3836,3883,3941,4006,4072,
+4139,4200,4251,4291,4327,4371,4424,4467,4481,4481,4516,4616,4760,4890,4978,5035,5087,5136,5178,5220,5272,
+5329,5384,5442,5508,5567,5595,5592,5584,5591,5615,5657,5725,5814,5887,5910,5889,5864,5865,5888,5914,5932,
+5949,5969,5989,6003,6009,6015,6029,6049,6067,6081,6096,6120,6146,6170,6203,6261,6343,6431,6515,6602,6691,
+6769,6821,6837,6804,6709,6574,6467,6445,6498,6561,6597,6620,6657,6693,6695,6658,6617,6600,6607,6619,6621,
+6607,6581,6551,6530,6517,6504,6487,6473,6468,6469,6468,6466,6466,6474,6489,6503,6508,6497,6470,6439,6411,
+6386,6368,6370,6400,6446,6494,6545,6619,6716,6809,6867,6883,6879,6867,6846,6814,6783,6756,6722,6675,6631,
+6605,6577,6506,6391,6306,6329,6454,6583,6621,6564,6483,6434,6409,6372,6314,6254,6210,6174,6140,6117,6114,
+6115,6084,6010,5922,5844,5735,5507,5145,4779,4613,4751,5108,5496,5785,5961,6067,6127,6150,6153,6153,6157,
+6154,6138,6117,6095,6072,6045,6010,5968,5923,5883,5853,5825,5795,5763,5724,5661,5565,5456,5366,5312,5282,
+5264,5257,5253,5233,5184,5120,5061,5016,4980,4947,4917,4883,4842,4793,4739,4678,4613,4553,4498,4428,4330,
+4226,4168,4185,4255,4319,4327,4263,4155,4051,3984,3947,3914,3874,3835,3793,3728,3640,3563,3522,3490,3422,
+3329,3271,3278,3303,3276,3177,3038,2901,2787,2712,2679,2674,2663,2631,2589,2555,2527,2492,2451,2417,2392,
+2361,2307,2231,2151,2083,2026,1974,1923,1875,1826,1773,1722,1691,1681,1667,1619,1539,1458,1408,1393,1398,
+1408,1415,1411,1392,1365,1347,1349,1369,1394,1410,1408,1388,1357,1319,1276,1222,1156,1088,1033,995,973,
+958,942,923,900,874,848,824,802,782,761,739,717,698,682,667,648,625,600,572,542,507,
+474,452,441,433,420,402,385,364,330,286,247,226,219,215,205,193,181,169,154,133,105,
+74,50,34,13,-17,-48,-63,-68,-81,-107,-139,-168,-195,-222,-242,-255,-278,-321,-370,-405,-425,
+-440,-454,-460,-460,-464,-477,-486,-483,-473,-468,-468,-471,-477,-492,-509,-522,-531,-541,-553,-562,-570,
+-582,-598,-614,-630,-653,-680,-703,-720,-736,-755,-772,-786,-800,-813,-823,-826,-830,-843,-861,-874,-877,
+-876,-876,-876,-875,-877,-886,-896,-902,-903,-903,-904,-906,-907,-909,-909,-909,-911,-918,-924,-926,-926,
+-927,-930,-933,-934,-936,-939,-941,-941,-942,-942,-938,-930,-922,-918,-915,-908,-900,-898,-901,-901,-896,
+-889,-885,-880,-872,-862,-854,-850,-849,-849,-848,-843,-835,-826,-818,-811,-804,-797,-791,-781,-767,-753,
+-744,-737,-724,-704,-686,-673,-663,-649,-635,-625,-616,-603,-589,-579,-574,-569,-563,-557,-553,-548,-542,
+-535,-532,-529,-526,-522,-519,-517,-515,-516,-518,-522,-525,-530,-538,-545,-549,-551,-555,-562,-572,-583,
+-596,-609,-620,-628,-637,-651,-667,-684,-703,-725,-750,-774,-794,-812,-828,-844,-858,-870,-881,-891,-900,
+-905,-906,-908,-914,-924,-930,-931,-929,-928,-932,-937,-938,-936,-936,-939,-941,-939,-936,-936,-939,-941,
+-942,-941,-936,-926,-915,-909,-909,-909,-904,-898,-894,-891,-883,-873,-867,-863,-855,-844,-833,-824,-814,
+-802,-792,-786,-780,-768,-754,-739,-720,-695,-669,-649,-632,-614,-594,-575,-557,-535,-509,-485,-465,-446,
+-424,-404,-385,-364,-340,-315,-292,-268,-241,-207,-167,-123,-82,-46,-5,50,116,182,243,306,367,
+412,440,467,499,517,498,452,401,374,403,536,786,1106,1430,1743,2082,2455,2817,3120,3357,3514,
+3553,3477,3373,3331,3334,3298,3206,3146,3181,3269,3342,3403,3485,3558,3544,3424,3255,3093,2940,2801,2719,
+2727,2786,2827,2836,2854,2900,2951,2988,3031,3096,3161,3189,3178,3161,3145,3101,2992,2831,2671,2558,2492,
+2443,2389,2331,2277,2227,2175,2121,2066,2006,1937,1875,1851,1865,1877,1839,1750,1643,1551,1465,1359,1219,
+1072,970,966,1060,1181,1232,1171,1043,915,791,630,422,215,53,-73,-200,-323,-411,-476,-566,-695,
+-814,-876,-898,-922,-948,-939,-890,-849,-858,-908,-964,-1015,-1074,-1151,-1243,-1338,-1412,-1433,-1396,-1335,-1291,
+-1268,-1252,-1257,-1318,-1435,-1559,-1646,-1697,-1727,-1728,-1678,-1593,-1517,-1474,-1452,-1433,-1417,-1409,-1410,-1419,-1442,
+-1476,-1511,-1544,-1587,-1625,-1611,-1513,-1369,-1262,-1237,-1261,-1276,-1264,-1245,-1236,-1228,-1208,-1178,-1153,-1144,-1148,
+-1151,-1138,-1111,-1096,-1116,-1159,-1194,-1205,-1206,-1219,-1239,-1245,-1231,-1210,-1195,-1183,-1157,-1114,-1066,-1026,-995,
+-969,-940,-907,-873,-841,-814,-799,-804,-826,-852,-866,-865,-861,-863,-868,-868,-862,-855,-851,-846,-835,
+-819,-803,-789,-778,-769,-764,-761,-756,-748,-734,-712,-682,-651,-623,-597,-570,-539,-505,-472,-438,-405,
+-374,-343,-311,-274,-235,-198,-163,-126,-85,-38,10,57,100,141,184,226,266,303,341,380,418,
+454,488,523,560,597,634,670,703,736,774,819,867,907,934,948,953,954,954,958,966,977,
+988,996,998,995,991,992,999,1007,1015,1024,1036,1046,1054,1063,1081,1106,1131,1149,1164,1182,1201,
+1215,1222,1229,1245,1273,1309,1342,1360,1356,1336,1315,1306,1303,1290,1263,1244,1253,1282,1301,1288,1255,
+1222,1200,1183,1168,1160,1159,1163,1165,1162,1176,1173,1168,1164,1161,1157,1155,1158,1163,1167,1165,1164,
+1169,1179,1186,1189,1194,1201,1209,1216,1224,1235,1245,1255,1268,1285,1302,1318,1334,1353,1373,1391,1412,
+1435,1457,1477,1501,1529,1553,1569,1585,1608,1632,1648,1663,1693,1737,1778,1815,1873,1968,2079,2160,2181,
+2155,2115,2090,2096,2135,2189,2233,2250,2243,2226,2208,2183,2128,2033,1910,1789,1686,1600,1521,1451,1393,
+1339,1283,1228,1177,1128,1073,1014,953,878,776,662,575,534,513,481,431,378,328,281,238,203,
+170,129,85,57,46,33,9,-19,-47,-83,-137,-200,-257,-311,-371,-436,-491,-520,-525,-519,-522,
+-543,-577,-611,-649,-712,-806,-914,-1025,-1159,-1324,-1467,-1510,-1443,-1341,-1285,-1278,-1290,-1328,-1434,-1609,-1793,
+-1918,-1960,-1927,-1841,-1747,-1715,-1786,-1924,-2052,-2129,-2174,-2216,-2252,-2266,-2261,-2254,-2250,-2241,-2227,-2210,-2188,
+-2166,-2175,-2250,-2379,-2503,-2581,-2623,-2664,-2712,-2748,-2772,-2804,-2832,-2804,-2696,-2570,-2521,-2569,-2609,-2523,-2317,
+-2144,-2160,-2367,-2602,-2708,-2685,-2659,-2702,-2733,-2625,-2379,-2139,-2024,-2014,-2002,-1944,-1891,-1903,-1977,-2079,-2197,
+-2333,-2470,-2574,-2628,-2650,-2663,-2677,-2693,-2710,-2730,-2754,-2781,-2812,-2843,-2862,-2861,-2846,-2826,-2811,-2806,-2809,
+-2816,-2822,-2832,-2854,-2890,-2932,-2969,-3002,-3034,-3062,-3087,-3114,-3153,-3201,-3251,-3305,-3371,-3442,-3480,-3445,-3347,
+-3251,-3226,-3282,-3377,-3459,-3510,-3544,-3577,-3618,-3663,-3709,-3751,-3789,-3825,-3863,-3900,-3932,-3954,-3969,-3982,-4002,
+-4031,-4073,-4126,-4188,-4258,-4333,-4403,-4464,-4518,-4572,-4630,-4686,-4737,-4790,-4852,-4920,-4986,-5044,-5098,-5155,-5221,
+-5297,-5378,-5459,-5535,-5605,-5670,-5729,-5781,-5829,-5876,-5924,-5970,-6014,-6059,-6105,-6150,-6193,-6236,-6282,-6327,-6370,
+-6410,-6445,-6474,-6497,-6511,-6517,-6517,-6517,-6518,-6518,-6516,-6514,-6514,-6513,-6511,-6513,-6525,-6546,-6568,-6588,-6604,
+-6615,-6612,-6598,-6578,-6555,-6532,-6521,-6539,-6589,-6646,-6687,-6714,-6735,-6745,-6730,-6690,-6643,-6603,-6575,-6567,-6586,
+-6615,-6618,-6568,-6472,-6341,-6192,-6064,-6014,-6070,-6181,-6255,-6240,-6157,-6059,-5986,-5949,-5943,-5943,-5916,-5851,-5771,
+-5711,-5677,-5648,-5595,-5515,-5424,-5340,-5258,-5153,-5009,-4845,-4702,-4596,-4506,-4413,-4327,-4266,-4223,-4182,-4147,-4123,
+-4093,-4024,-3930,-3861,-3836,-3810,-3741,-3651,-3600,-3599,-3587,-3507,-3361,-3197,-3052,-2928,-2809,-2689,-2577,-2487,-2424,
+-2373,-2313,-2237,-2161,-2106,-2072,-2034,-1968,-1881,-1799,-1741,-1698,-1646,-1570,-1480,-1387,-1296,-1208,-1124,-1045,-963,
+-873,-783,-697,-606,-502,-405,-347,-330,-315,-273,-211,-149,-78,14,113,180,216,262,341,418,448,
+443,455,509,581,641,692,758,844,936,1019,1093,1158,1209,1248,1283,1321,1361,1399,1447,1516,1604,
+1696,1785,1880,1997,2125,2243,2336,2412,2484,2552,2611,2665,2728,2809,2910,3025,3142,3242,3315,3371,3433,
+3513,3597,3657,3684,3688,3689,3697,3715,3744,3783,3829,3884,3947,4020,4097,4167,4222,4267,4317,4377,4425,
+4436,4424,4443,4533,4668,4792,4875,4938,5006,5076,5132,5176,5216,5258,5304,5364,5443,5516,5553,5551,5539,
+5540,5556,5584,5636,5710,5774,5796,5781,5764,5771,5801,5835,5860,5877,5891,5907,5925,5938,5945,5950,5965,
+5989,6014,6036,6056,6076,6101,6141,6206,6288,6370,6445,6525,6612,6694,6755,6781,6754,6660,6526,6419,6396,
+6443,6499,6530,6554,6595,6637,6645,6611,6564,6533,6527,6538,6552,6554,6539,6516,6503,6502,6500,6490,6476,
+6468,6463,6455,6445,6443,6449,6457,6462,6461,6453,6438,6420,6408,6402,6402,6412,6442,6492,6552,6614,6683,
+6760,6828,6867,6875,6868,6858,6837,6801,6759,6720,6679,6628,6587,6581,6596,6568,6461,6332,6288,6373,6511,
+6591,6580,6527,6484,6452,6405,6344,6290,6254,6225,6195,6167,6153,6153,6147,6108,6032,5936,5817,5623,5304,
+4928,4687,4751,5098,5525,5834,5987,6062,6126,6176,6192,6186,6185,6192,6191,6173,6145,6117,6090,6059,6022,
+5982,5947,5916,5883,5846,5813,5783,5738,5665,5576,5502,5460,5436,5410,5378,5344,5305,5257,5206,5160,5119,
+5076,5034,4999,4967,4927,4872,4807,4739,4675,4625,4584,4526,4424,4283,4158,4111,4162,4262,4335,4328,4251,
+4158,4091,4043,3978,3887,3797,3733,3687,3639,3593,3558,3518,3447,3358,3298,3294,3305,3268,3165,3031,2911,
+2826,2778,2758,2746,2713,2651,2583,2540,2525,2516,2494,2461,2430,2398,2351,2279,2194,2117,2057,2008,1958,
+1905,1847,1789,1735,1696,1676,1656,1613,1542,1463,1405,1379,1375,1379,1378,1370,1356,1347,1349,1360,1369,
+1371,1370,1365,1353,1329,1292,1247,1195,1135,1072,1016,976,950,935,922,906,885,862,840,819,796,
+772,751,734,718,702,687,670,649,621,590,562,533,500,466,441,430,422,410,397,385,367,
+337,299,263,236,212,188,171,160,146,125,103,84,64,40,19,6,-8,-36,-69,-90,-97,
+-110,-139,-172,-200,-224,-251,-276,-295,-316,-350,-390,-417,-428,-433,-440,-444,-443,-446,-458,-468,-470,
+-468,-471,-480,-491,-504,-522,-543,-560,-570,-578,-584,-590,-597,-610,-627,-644,-663,-687,-713,-735,-752,
+-770,-789,-807,-819,-830,-843,-853,-858,-863,-874,-888,-895,-895,-893,-892,-890,-887,-888,-895,-904,-910,
+-913,-914,-914,-913,-914,-916,-916,-915,-915,-917,-921,-924,-927,-930,-933,-933,-932,-935,-939,-941,-941,
+-941,-940,-935,-925,-916,-912,-908,-900,-890,-886,-885,-880,-872,-867,-865,-861,-851,-840,-833,-831,-829,
+-825,-821,-818,-814,-807,-799,-791,-784,-781,-776,-764,-746,-727,-716,-710,-697,-677,-657,-643,-632,-619,
+-605,-595,-587,-576,-563,-553,-548,-544,-537,-531,-528,-525,-520,-514,-509,-507,-504,-501,-497,-494,-492,
+-492,-494,-497,-500,-505,-511,-519,-524,-528,-533,-542,-551,-560,-571,-583,-597,-608,-619,-632,-647,-661,
+-677,-696,-720,-746,-769,-786,-800,-813,-827,-841,-856,-868,-877,-881,-882,-886,-893,-903,-911,-914,-911,
+-907,-907,-910,-911,-909,-908,-910,-912,-909,-904,-904,-910,-917,-921,-922,-916,-904,-890,-883,-884,-886,
+-882,-876,-872,-869,-861,-849,-841,-835,-827,-815,-805,-798,-788,-774,-763,-758,-754,-743,-726,-709,-693,
+-674,-652,-631,-613,-595,-575,-558,-541,-520,-495,-469,-448,-432,-420,-409,-394,-372,-346,-322,-298,-272,
+-243,-212,-177,-135,-91,-50,-5,52,121,186,243,301,362,415,455,494,538,575,584,563,520,
+471,453,522,709,976,1262,1551,1878,2261,2665,3043,3363,3581,3648,3581,3490,3474,3500,3461,3338,3237,
+3248,3347,3458,3562,3682,3792,3826,3753,3605,3420,3212,3016,2895,2875,2911,2935,2936,2940,2953,2961,2973,
+3020,3103,3177,3200,3183,3163,3146,3102,3008,2880,2757,2662,2595,2543,2493,2438,2374,2300,2228,2165,2108,
+2043,1964,1896,1866,1873,1878,1846,1773,1685,1600,1511,1406,1277,1143,1047,1034,1114,1222,1268,1210,1094,
+979,859,685,446,204,22,-98,-199,-293,-369,-437,-529,-652,-760,-821,-852,-887,-919,-913,-867,-824,
+-821,-851,-895,-948,-1015,-1090,-1166,-1243,-1307,-1330,-1300,-1245,-1209,-1202,-1206,-1230,-1304,-1436,-1579,-1684,-1744,
+-1770,-1759,-1695,-1593,-1499,-1440,-1409,-1383,-1357,-1339,-1337,-1359,-1402,-1449,-1483,-1513,-1560,-1615,-1621,-1535,-1386,
+-1256,-1206,-1221,-1247,-1250,-1231,-1206,-1185,-1172,-1166,-1161,-1153,-1140,-1124,-1110,-1104,-1113,-1137,-1167,-1192,-1210,
+-1229,-1249,-1261,-1252,-1228,-1203,-1186,-1171,-1146,-1106,-1060,-1022,-992,-964,-928,-890,-859,-837,-819,-804,-802,
+-815,-833,-841,-838,-835,-842,-852,-855,-852,-849,-846,-841,-830,-815,-798,-781,-766,-757,-752,-748,-744,
+-737,-727,-710,-685,-657,-630,-604,-576,-545,-513,-479,-446,-415,-389,-362,-330,-292,-251,-213,-177,-141,
+-101,-56,-9,36,77,118,160,204,247,287,328,370,410,446,480,515,552,590,627,662,695,
+730,772,822,871,909,931,941,942,941,941,946,954,963,971,978,983,984,984,988,997,1008,
+1017,1025,1035,1045,1053,1061,1077,1101,1126,1144,1159,1177,1199,1215,1225,1242,1283,1346,1410,1446,1441,
+1405,1361,1328,1317,1315,1306,1287,1277,1292,1322,1340,1325,1284,1243,1215,1201,1195,1191,1188,1184,1180,
+1176,1194,1194,1192,1186,1179,1174,1172,1175,1182,1185,1181,1178,1184,1194,1199,1200,1202,1212,1224,1233,
+1239,1248,1259,1271,1284,1298,1313,1329,1347,1366,1384,1401,1420,1441,1462,1482,1506,1532,1554,1570,1586,
+1609,1632,1648,1666,1700,1745,1786,1832,1910,2026,2140,2198,2184,2131,2085,2070,2090,2136,2189,2230,2244,
+2232,2202,2163,2112,2043,1951,1847,1748,1664,1592,1527,1469,1417,1363,1307,1253,1205,1155,1100,1042,983,
+902,786,658,564,525,513,490,446,397,351,308,271,243,215,175,136,117,117,113,89,54,
+16,-30,-95,-168,-233,-286,-341,-405,-464,-498,-499,-479,-467,-482,-519,-561,-608,-679,-780,-895,-1017,
+-1158,-1315,-1427,-1433,-1346,-1256,-1227,-1239,-1250,-1274,-1366,-1537,-1724,-1859,-1912,-1888,-1805,-1706,-1663,-1719,-1845,
+-1972,-2060,-2120,-2170,-2203,-2204,-2181,-2157,-2145,-2140,-2136,-2131,-2121,-2119,-2159,-2260,-2395,-2498,-2544,-2567,-2610,
+-2670,-2709,-2725,-2745,-2775,-2775,-2720,-2656,-2655,-2714,-2732,-2616,-2393,-2210,-2206,-2383,-2606,-2732,-2730,-2689,-2685,
+-2689,-2609,-2422,-2209,-2062,-1988,-1934,-1873,-1831,-1835,-1879,-1950,-2056,-2201,-2358,-2481,-2550,-2578,-2591,-2602,-2620,
+-2644,-2671,-2695,-2720,-2751,-2783,-2798,-2787,-2763,-2745,-2738,-2737,-2737,-2736,-2739,-2753,-2782,-2822,-2862,-2896,-2928,
+-2961,-2992,-3016,-3041,-3076,-3121,-3167,-3221,-3297,-3378,-3408,-3343,-3216,-3121,-3128,-3219,-3319,-3378,-3403,-3430,-3475,
+-3530,-3579,-3620,-3657,-3695,-3736,-3774,-3806,-3830,-3845,-3858,-3877,-3904,-3940,-3982,-4031,-4091,-4162,-4234,-4298,-4350,
+-4399,-4453,-4512,-4569,-4624,-4684,-4752,-4821,-4886,-4947,-5007,-5069,-5133,-5204,-5281,-5360,-5435,-5503,-5566,-5623,-5675,
+-5725,-5775,-5824,-5871,-5915,-5960,-6005,-6049,-6091,-6132,-6174,-6219,-6264,-6306,-6340,-6367,-6386,-6399,-6406,-6407,-6405,
+-6405,-6405,-6404,-6403,-6405,-6409,-6414,-6422,-6440,-6465,-6490,-6512,-6528,-6535,-6532,-6519,-6499,-6477,-6458,-6458,-6491,
+-6549,-6603,-6636,-6655,-6670,-6675,-6652,-6609,-6569,-6545,-6533,-6531,-6542,-6556,-6546,-6496,-6403,-6276,-6131,-6011,-5973,
+-6038,-6150,-6217,-6192,-6101,-6001,-5934,-5913,-5924,-5932,-5897,-5812,-5712,-5644,-5619,-5607,-5568,-5490,-5397,-5325,-5275,
+-5204,-5076,-4908,-4755,-4638,-4530,-4408,-4301,-4248,-4242,-4237,-4210,-4174,-4132,-4068,-3985,-3920,-3891,-3864,-3802,-3721,
+-3672,-3669,-3657,-3583,-3446,-3287,-3136,-2998,-2868,-2751,-2647,-2557,-2484,-2427,-2379,-2329,-2275,-2230,-2202,-2176,-2122,
+-2033,-1930,-1845,-1786,-1731,-1657,-1561,-1459,-1363,-1279,-1202,-1127,-1044,-952,-857,-761,-661,-559,-475,-437,-436,
+-437,-412,-366,-316,-258,-178,-86,-5,61,131,208,267,295,312,353,422,492,546,595,659,741,
+829,915,992,1053,1097,1132,1174,1225,1275,1322,1376,1451,1540,1629,1717,1819,1947,2086,2208,2302,2378,
+2447,2511,2565,2621,2696,2794,2902,3007,3101,3179,3243,3300,3367,3450,3534,3594,3620,3623,3624,3637,3663,
+3694,3724,3754,3791,3842,3911,3993,4074,4140,4196,4258,4332,4391,4401,4375,4373,4445,4572,4693,4775,4839,
+4914,4997,5066,5114,5151,5188,5234,5299,5383,5458,5493,5491,5480,5481,5492,5512,5551,5612,5669,5693,5687,
+5680,5694,5725,5758,5784,5801,5813,5828,5844,5855,5857,5858,5872,5904,5940,5971,5993,6015,6047,6098,6171,
+6250,6319,6378,6441,6520,6603,6673,6712,6703,6631,6513,6407,6365,6389,6433,6467,6496,6533,6567,6577,6559,
+6527,6493,6468,6460,6472,6486,6484,6470,6461,6464,6467,6460,6449,6443,6440,6434,6429,6433,6440,6441,6433,
+6422,6412,6404,6401,6409,6424,6439,6451,6474,6516,6575,6636,6695,6752,6801,6831,6838,6833,6823,6802,6765,
+6718,6673,6629,6578,6536,6531,6559,6563,6490,6373,6313,6363,6475,6551,6556,6523,6492,6464,6425,6380,6343,
+6317,6294,6265,6229,6195,6182,6193,6199,6158,6067,5946,5775,5490,5105,4798,4790,5118,5570,5897,6031,6079,
+6143,6215,6245,6234,6223,6232,6238,6223,6193,6163,6138,6112,6079,6044,6009,5978,5946,5910,5870,5828,5780,
+5725,5673,5636,5611,5578,5524,5458,5401,5359,5324,5289,5254,5215,5168,5117,5070,5029,4984,4930,4870,4809,
+4750,4698,4651,4590,4484,4330,4183,4115,4155,4261,4353,4376,4334,4269,4211,4140,4020,3858,3712,3642,3645,
+3668,3665,3628,3566,3490,3415,3370,3362,3356,3302,3188,3055,2956,2914,2916,2930,2922,2870,2773,2658,2568,
+2524,2517,2518,2503,2470,2428,2376,2307,2225,2146,2084,2038,1992,1934,1868,1803,1747,1704,1673,1646,1606,
+1545,1476,1418,1383,1369,1361,1350,1336,1331,1345,1371,1387,1377,1350,1328,1321,1317,1300,1265,1220,1169,
+1112,1052,995,952,926,910,898,881,859,837,819,800,777,751,731,719,709,696,682,667,646,
+615,581,551,525,496,464,439,424,412,400,388,378,361,335,308,284,254,211,168,145,137,
+120,84,47,27,20,10,0,-5,-17,-48,-91,-120,-129,-140,-170,-207,-234,-252,-273,-296,-313,
+-327,-349,-378,-398,-402,-403,-410,-422,-434,-447,-463,-478,-487,-494,-502,-513,-522,-534,-552,-573,-589,
+-595,-596,-598,-604,-616,-635,-657,-678,-698,-720,-741,-758,-774,-794,-816,-834,-845,-855,-867,-878,-887,
+-896,-906,-915,-917,-915,-912,-910,-906,-902,-901,-905,-911,-917,-921,-924,-923,-919,-919,-921,-923,-923,
+-922,-923,-925,-927,-930,-934,-934,-931,-928,-931,-934,-936,-935,-936,-937,-931,-920,-910,-906,-902,-893,
+-883,-877,-872,-864,-855,-851,-850,-845,-832,-819,-814,-812,-806,-797,-791,-789,-788,-784,-775,-766,-759,
+-757,-754,-745,-727,-708,-695,-686,-673,-652,-631,-615,-603,-590,-576,-566,-558,-548,-536,-528,-523,-518,
+-512,-506,-503,-502,-498,-493,-488,-484,-480,-477,-474,-472,-471,-471,-473,-476,-479,-482,-488,-494,-499,
+-504,-511,-521,-529,-534,-541,-556,-575,-591,-603,-613,-626,-640,-653,-669,-690,-716,-739,-757,-771,-785,
+-800,-817,-833,-845,-852,-854,-855,-860,-868,-878,-886,-890,-889,-885,-883,-885,-884,-879,-875,-877,-880,
+-879,-874,-872,-877,-886,-892,-894,-890,-880,-866,-859,-861,-864,-860,-853,-849,-846,-839,-827,-817,-811,
+-802,-789,-777,-771,-763,-749,-735,-728,-724,-713,-695,-677,-663,-649,-631,-612,-595,-579,-561,-542,-524,
+-506,-486,-465,-444,-428,-419,-413,-401,-378,-352,-327,-303,-272,-238,-209,-181,-146,-102,-55,-3,57,
+125,189,242,295,355,415,468,518,570,615,642,646,625,579,535,549,664,868,1113,1380,1684,
+2036,2417,2811,3196,3510,3666,3652,3576,3550,3569,3538,3433,3342,3360,3480,3639,3799,3957,4087,4148,4128,
+4038,3882,3663,3423,3238,3142,3104,3083,3068,3054,3017,2952,2908,2946,3054,3153,3181,3152,3112,3080,3041,
+2984,2919,2854,2792,2733,2683,2639,2583,2498,2389,2283,2198,2130,2060,1982,1916,1880,1869,1855,1820,1766,
+1704,1633,1550,1451,1339,1223,1131,1103,1151,1229,1258,1204,1106,1009,897,720,469,206,2,-134,-233,
+-314,-375,-428,-498,-590,-679,-746,-801,-857,-894,-888,-846,-808,-797,-807,-834,-887,-966,-1047,-1112,-1166,
+-1214,-1236,-1215,-1171,-1144,-1150,-1174,-1216,-1302,-1437,-1585,-1703,-1777,-1810,-1795,-1718,-1597,-1480,-1403,-1362,-1333,
+-1303,-1281,-1283,-1317,-1373,-1426,-1458,-1479,-1516,-1567,-1585,-1527,-1403,-1270,-1188,-1170,-1187,-1199,-1180,-1135,-1094,
+-1085,-1105,-1128,-1130,-1112,-1092,-1085,-1092,-1110,-1135,-1165,-1197,-1231,-1263,-1281,-1277,-1252,-1222,-1197,-1180,-1160,
+-1130,-1091,-1050,-1018,-993,-963,-921,-877,-847,-835,-826,-815,-808,-813,-821,-822,-815,-814,-824,-836,-842,
+-842,-841,-839,-833,-822,-809,-792,-773,-756,-747,-741,-734,-725,-716,-707,-695,-678,-659,-637,-611,-582,
+-552,-523,-491,-458,-428,-404,-381,-351,-313,-273,-232,-193,-153,-111,-67,-20,24,65,105,147,191,
+235,277,320,363,403,439,473,509,545,581,616,649,683,722,768,820,866,899,918,927,931,
+931,932,937,945,953,961,969,975,979,982,989,1002,1016,1025,1031,1039,1050,1059,1067,1079,1100,
+1125,1146,1163,1183,1204,1221,1230,1248,1293,1361,1426,1453,1433,1385,1337,1310,1308,1320,1328,1326,1321,
+1323,1332,1333,1314,1279,1246,1226,1218,1215,1211,1204,1197,1193,1194,1214,1212,1205,1197,1191,1189,1189,
+1194,1200,1203,1200,1197,1200,1208,1212,1212,1216,1227,1238,1245,1249,1256,1269,1283,1296,1309,1323,1340,
+1359,1379,1396,1411,1427,1446,1465,1485,1507,1531,1552,1570,1589,1613,1635,1652,1676,1713,1755,1793,1845,
+1937,2063,2168,2200,2158,2094,2059,2066,2103,2149,2193,2226,2237,2221,2176,2110,2033,1953,1872,1795,1724,
+1659,1598,1541,1488,1436,1383,1328,1275,1227,1177,1124,1073,1013,922,790,650,553,518,511,496,463,
+424,385,346,313,288,260,220,183,169,173,171,146,108,67,16,-52,-128,-192,-242,-293,-354,
+-416,-458,-468,-458,-451,-464,-495,-537,-596,-687,-806,-928,-1044,-1166,-1289,-1360,-1334,-1241,-1165,-1152,-1167,
+-1168,-1178,-1265,-1443,-1649,-1796,-1844,-1806,-1725,-1654,-1643,-1704,-1804,-1897,-1971,-2039,-2105,-2143,-2136,-2096,-2056,
+-2039,-2043,-2055,-2064,-2071,-2097,-2172,-2295,-2419,-2485,-2485,-2474,-2504,-2569,-2625,-2655,-2678,-2710,-2728,-2716,-2698,
+-2714,-2752,-2747,-2653,-2501,-2384,-2379,-2486,-2625,-2706,-2700,-2654,-2629,-2623,-2573,-2433,-2237,-2055,-1927,-1844,-1791,
+-1765,-1762,-1777,-1822,-1919,-2073,-2245,-2382,-2461,-2497,-2513,-2525,-2544,-2575,-2610,-2638,-2660,-2686,-2712,-2723,-2709,
+-2686,-2674,-2675,-2679,-2679,-2678,-2683,-2698,-2726,-2761,-2792,-2819,-2849,-2886,-2919,-2943,-2965,-2998,-3041,-3086,-3145,
+-3228,-3307,-3315,-3215,-3063,-2973,-3007,-3123,-3231,-3284,-3304,-3334,-3388,-3447,-3493,-3529,-3563,-3602,-3641,-3675,-3702,
+-3721,-3738,-3757,-3784,-3819,-3859,-3900,-3945,-4001,-4066,-4132,-4187,-4234,-4284,-4344,-4406,-4465,-4524,-4589,-4659,-4726,
+-4787,-4849,-4913,-4978,-5043,-5112,-5188,-5267,-5341,-5406,-5465,-5521,-5573,-5624,-5674,-5724,-5771,-5818,-5864,-5908,-5950,
+-5989,-6028,-6068,-6111,-6157,-6200,-6234,-6256,-6271,-6283,-6290,-6293,-6292,-6292,-6294,-6296,-6299,-6305,-6315,-6326,-6341,
+-6363,-6391,-6418,-6438,-6449,-6453,-6449,-6437,-6420,-6402,-6390,-6400,-6441,-6502,-6556,-6587,-6603,-6614,-6614,-6591,-6554,
+-6522,-6505,-6497,-6491,-6489,-6485,-6464,-6414,-6328,-6207,-6069,-5961,-5941,-6016,-6123,-6178,-6144,-6051,-5957,-5900,-5892,
+-5914,-5922,-5876,-5774,-5661,-5589,-5571,-5571,-5540,-5460,-5365,-5306,-5289,-5260,-5161,-4999,-4835,-4702,-4574,-4430,-4305,
+-4252,-4263,-4274,-4250,-4206,-4161,-4106,-4036,-3975,-3944,-3919,-3865,-3792,-3740,-3722,-3701,-3632,-3515,-3372,-3221,-3070,
+-2931,-2818,-2727,-2641,-2561,-2504,-2477,-2461,-2429,-2381,-2340,-2309,-2265,-2179,-2061,-1951,-1876,-1821,-1754,-1660,-1554,
+-1459,-1381,-1314,-1244,-1160,-1057,-941,-822,-711,-623,-573,-563,-573,-574,-551,-512,-469,-418,-346,-256,-161,
+-69,19,93,140,170,211,279,356,415,454,493,550,623,704,787,865,927,969,1003,1047,1102,
+1157,1209,1267,1341,1426,1513,1605,1720,1863,2018,2153,2254,2327,2385,2433,2479,2539,2631,2752,2875,2977,
+3053,3112,3166,3226,3298,3382,3463,3522,3550,3559,3568,3590,3625,3659,3686,3707,3731,3771,3830,3903,3977,
+4040,4100,4177,4274,4356,4377,4340,4315,4364,4480,4598,4676,4731,4802,4893,4978,5039,5083,5123,5173,5240,
+5320,5386,5416,5414,5407,5410,5418,5432,5464,5519,5574,5603,5609,5616,5637,5668,5695,5716,5732,5745,5754,
+5760,5761,5758,5762,5784,5823,5865,5900,5927,5957,5998,6057,6131,6206,6265,6310,6361,6431,6512,6589,6645,
+6663,6624,6530,6423,6354,6343,6373,6415,6454,6483,6500,6508,6512,6510,6488,6449,6416,6409,6420,6425,6420,
+6416,6420,6423,6416,6408,6406,6407,6408,6412,6420,6430,6431,6423,6412,6402,6392,6389,6398,6415,6430,6439,
+6454,6490,6544,6603,6656,6706,6750,6782,6794,6790,6777,6753,6712,6659,6606,6561,6521,6491,6490,6515,6525,
+6481,6403,6361,6393,6462,6502,6497,6474,6458,6444,6425,6403,6380,6352,6319,6289,6258,6225,6209,6233,6278,
+6281,6217,6113,5968,5707,5303,4916,4812,5087,5550,5913,6072,6127,6196,6272,6301,6283,6268,6276,6284,6271,
+6244,6218,6195,6167,6135,6100,6064,6029,5999,5968,5930,5880,5825,5778,5746,5726,5700,5652,5582,5511,5461,
+5429,5399,5361,5319,5277,5232,5184,5136,5090,5043,4994,4947,4897,4842,4785,4727,4656,4546,4404,4280,4233,
+4278,4364,4426,4433,4397,4348,4294,4214,4078,3899,3744,3683,3715,3767,3763,3693,3599,3529,3494,3483,3479,
+3451,3370,3235,3092,3007,3009,3069,3129,3146,3105,3007,2863,2704,2580,2522,2517,2521,2500,2451,2389,2319,
+2239,2159,2096,2052,2009,1952,1881,1812,1755,1710,1674,1640,1600,1549,1490,1437,1399,1375,1357,1335,1316,
+1316,1344,1381,1394,1368,1321,1287,1278,1277,1260,1225,1184,1139,1087,1030,975,932,904,888,874,856,
+833,811,793,775,752,728,711,701,691,678,667,659,645,616,580,548,524,499,472,446,424,
+404,388,377,369,352,329,311,299,271,216,161,137,138,124,78,28,5,3,0,-9,-16,
+-30,-69,-124,-163,-174,-178,-202,-236,-259,-270,-282,-297,-308,-314,-328,-352,-370,-376,-379,-394,-423,
+-454,-480,-500,-516,-528,-537,-546,-551,-556,-564,-581,-603,-618,-621,-617,-616,-624,-641,-663,-685,-705,
+-726,-746,-764,-778,-794,-814,-836,-853,-865,-876,-888,-899,-910,-921,-931,-936,-936,-934,-933,-930,-924,
+-919,-917,-918,-919,-923,-929,-933,-931,-926,-924,-927,-930,-931,-931,-931,-931,-930,-932,-935,-935,-930,
+-926,-926,-928,-927,-925,-927,-929,-924,-913,-903,-899,-896,-888,-880,-873,-866,-856,-846,-841,-839,-831,
+-817,-804,-797,-794,-785,-773,-764,-761,-760,-755,-746,-736,-728,-724,-722,-714,-701,-684,-671,-661,-646,
+-626,-605,-589,-576,-564,-551,-539,-528,-518,-509,-501,-496,-490,-485,-481,-480,-478,-474,-470,-465,-461,
+-457,-454,-453,-453,-453,-454,-455,-458,-460,-463,-468,-474,-479,-483,-490,-500,-507,-511,-516,-531,-552,
+-571,-581,-590,-602,-617,-630,-643,-661,-684,-706,-723,-738,-756,-776,-796,-814,-826,-830,-829,-828,-833,
+-842,-851,-858,-863,-864,-862,-861,-860,-857,-849,-843,-843,-848,-849,-844,-842,-846,-853,-857,-861,-861,
+-857,-847,-840,-841,-843,-840,-831,-826,-824,-817,-806,-797,-791,-782,-767,-753,-745,-738,-725,-710,-700,
+-693,-681,-665,-650,-638,-625,-608,-590,-576,-563,-547,-528,-508,-491,-479,-466,-450,-433,-422,-415,-402,
+-379,-353,-331,-307,-274,-235,-201,-174,-142,-99,-49,3,61,125,186,238,291,352,418,481,542,
+599,649,686,709,712,686,639,615,663,798,1003,1257,1548,1858,2178,2533,2944,3349,3622,3691,3623,
+3548,3523,3508,3473,3457,3516,3658,3847,4047,4223,4344,4404,4426,4422,4359,4207,3985,3754,3554,3389,3267,
+3198,3151,3067,2940,2849,2877,3001,3120,3155,3113,3048,2994,2959,2944,2944,2938,2908,2861,2817,2780,2721,
+2617,2478,2342,2235,2151,2072,1991,1926,1886,1861,1831,1793,1752,1710,1654,1580,1493,1401,1305,1217,1167,
+1170,1195,1194,1148,1083,1018,924,752,505,240,22,-134,-246,-327,-380,-418,-463,-525,-597,-675,-757,
+-832,-870,-859,-822,-795,-787,-789,-807,-861,-947,-1029,-1082,-1113,-1140,-1156,-1144,-1112,-1094,-1108,-1144,-1200,
+-1291,-1421,-1565,-1688,-1774,-1818,-1806,-1725,-1593,-1461,-1370,-1321,-1290,-1262,-1240,-1242,-1276,-1330,-1381,-1414,-1435,
+-1461,-1492,-1508,-1481,-1405,-1299,-1202,-1149,-1144,-1154,-1133,-1073,-1016,-1007,-1040,-1075,-1080,-1067,-1060,-1069,-1085,
+-1102,-1126,-1161,-1205,-1251,-1285,-1294,-1277,-1246,-1219,-1199,-1180,-1153,-1116,-1076,-1041,-1014,-991,-958,-913,-869,
+-844,-837,-833,-821,-810,-807,-808,-804,-798,-797,-805,-812,-814,-815,-817,-817,-810,-801,-791,-778,-761,
+-746,-738,-731,-720,-706,-693,-684,-676,-667,-655,-638,-613,-584,-557,-532,-503,-471,-440,-414,-389,-360,
+-324,-285,-244,-201,-159,-116,-72,-25,20,61,100,141,185,229,271,313,354,393,427,461,496,
+532,567,599,631,667,710,759,809,850,878,897,911,921,924,926,930,937,945,953,963,973,
+980,986,995,1010,1024,1033,1038,1047,1059,1069,1076,1084,1102,1127,1153,1176,1198,1220,1235,1242,1253,
+1282,1329,1370,1382,1360,1324,1298,1291,1304,1326,1347,1355,1348,1331,1312,1294,1277,1259,1246,1237,1234,
+1232,1227,1219,1213,1212,1214,1232,1225,1215,1208,1208,1211,1212,1213,1216,1219,1219,1217,1217,1221,1226,
+1231,1237,1245,1252,1255,1259,1267,1280,1295,1309,1323,1337,1354,1373,1392,1408,1421,1434,1450,1467,1485,
+1505,1524,1544,1564,1587,1612,1634,1657,1688,1729,1768,1804,1859,1957,2080,2169,2178,2123,2065,2054,2090,
+2143,2185,2211,2228,2235,2218,2164,2079,1982,1898,1830,1775,1722,1669,1614,1559,1506,1454,1402,1349,1298,
+1248,1197,1149,1105,1047,949,809,665,569,531,522,509,487,463,434,401,369,341,306,260,220,
+206,209,203,174,135,96,49,-13,-81,-138,-184,-234,-294,-352,-396,-423,-439,-453,-468,-490,-531,
+-613,-740,-887,-1014,-1111,-1194,-1269,-1298,-1254,-1166,-1104,-1096,-1107,-1098,-1096,-1167,-1337,-1550,-1709,-1758,-1712,
+-1640,-1611,-1651,-1729,-1801,-1850,-1897,-1964,-2041,-2088,-2081,-2033,-1985,-1969,-1989,-2019,-2040,-2059,-2104,-2198,-2322,
+-2424,-2458,-2429,-2391,-2396,-2449,-2516,-2570,-2608,-2641,-2666,-2680,-2691,-2708,-2718,-2701,-2654,-2598,-2561,-2558,-2584,
+-2620,-2638,-2621,-2585,-2562,-2553,-2507,-2379,-2182,-1980,-1828,-1739,-1698,-1683,-1677,-1675,-1702,-1794,-1953,-2133,-2278,
+-2365,-2411,-2437,-2455,-2476,-2507,-2543,-2572,-2591,-2609,-2630,-2643,-2638,-2624,-2617,-2622,-2631,-2636,-2639,-2644,-2654,
+-2671,-2692,-2713,-2733,-2761,-2797,-2831,-2857,-2882,-2917,-2963,-3015,-3084,-3171,-3233,-3203,-3066,-2902,-2825,-2881,-3010,
+-3124,-3186,-3221,-3262,-3315,-3365,-3404,-3439,-3476,-3515,-3550,-3577,-3599,-3620,-3643,-3670,-3702,-3738,-3776,-3815,-3856,
+-3906,-3965,-4025,-4077,-4125,-4181,-4245,-4311,-4374,-4437,-4505,-4572,-4633,-4689,-4747,-4811,-4878,-4945,-5018,-5096,-5175,
+-5248,-5312,-5370,-5424,-5475,-5524,-5573,-5621,-5668,-5718,-5766,-5809,-5848,-5887,-5926,-5967,-6007,-6049,-6090,-6122,-6142,
+-6155,-6165,-6173,-6178,-6180,-6183,-6188,-6193,-6201,-6213,-6230,-6246,-6263,-6286,-6315,-6341,-6358,-6366,-6369,-6366,-6355,
+-6340,-6327,-6325,-6344,-6388,-6448,-6504,-6542,-6560,-6566,-6559,-6538,-6509,-6485,-6467,-6449,-6429,-6409,-6390,-6363,-6318,
+-6242,-6131,-6005,-5919,-5922,-6006,-6103,-6140,-6097,-6010,-5926,-5881,-5884,-5913,-5920,-5864,-5752,-5636,-5567,-5552,-5553,
+-5520,-5437,-5339,-5287,-5293,-5297,-5226,-5076,-4908,-4766,-4634,-4492,-4370,-4316,-4316,-4310,-4266,-4208,-4166,-4129,-4078,
+-4029,-4000,-3979,-3931,-3859,-3797,-3762,-3728,-3665,-3569,-3449,-3306,-3148,-3004,-2896,-2815,-2737,-2657,-2605,-2597,-2605,
+-2585,-2529,-2468,-2428,-2389,-2314,-2197,-2077,-1991,-1932,-1865,-1773,-1670,-1582,-1513,-1453,-1387,-1304,-1193,-1052,-902,
+-777,-707,-693,-711,-725,-715,-682,-642,-600,-549,-479,-391,-292,-188,-89,-10,42,85,145,223,292,
+330,352,384,439,508,582,657,732,796,844,883,928,981,1036,1090,1150,1220,1301,1388,1487,1609,
+1760,1923,2070,2181,2255,2303,2337,2376,2441,2549,2687,2820,2920,2983,3029,3077,3140,3218,3307,3389,3448,
+3479,3494,3511,3540,3577,3615,3646,3670,3696,3732,3784,3844,3900,3946,3997,4079,4197,4306,4345,4307,4263,
+4290,4393,4507,4578,4621,4681,4775,4875,4953,5005,5049,5100,5166,5240,5300,5330,5332,5329,5331,5335,5345,
+5374,5425,5479,5513,5531,5552,5586,5619,5642,5656,5669,5679,5681,5675,5666,5664,5678,5710,5753,5793,5826,
+5857,5894,5940,6000,6071,6144,6204,6252,6300,6361,6436,6514,6587,6635,6635,6574,6476,6385,6341,6347,6385,
+6426,6449,6452,6456,6477,6502,6500,6461,6411,6378,6368,6364,6358,6357,6362,6364,6360,6356,6359,6366,6371,
+6376,6384,6392,6397,6399,6399,6396,6388,6380,6381,6389,6395,6400,6414,6446,6493,6542,6588,6634,6684,6726,
+6749,6748,6730,6699,6651,6587,6525,6481,6464,6469,6487,6505,6501,6464,6418,6403,6430,6463,6468,6453,6440,
+6436,6431,6425,6421,6408,6370,6321,6290,6278,6262,6249,6272,6324,6349,6312,6240,6135,5905,5483,5013,4791,
+4981,5433,5852,6087,6199,6283,6345,6350,6319,6306,6320,6327,6314,6293,6276,6253,6219,6184,6154,6121,6082,
+6046,6017,5984,5939,5886,5840,5807,5777,5737,5679,5615,5563,5531,5508,5472,5421,5366,5320,5282,5243,5199,
+5153,5108,5066,5028,4987,4937,4881,4824,4753,4653,4536,4449,4434,4477,4524,4533,4503,4457,4409,4356,4287,
+4186,4058,3943,3890,3900,3908,3844,3711,3584,3529,3538,3560,3554,3503,3398,3249,3104,3036,3074,3177,3270,
+3314,3309,3256,3132,2938,2733,2598,2560,2572,2569,2527,2458,2377,2282,2183,2102,2049,2007,1953,1884,1814,
+1757,1713,1675,1637,1597,1553,1505,1458,1421,1393,1367,1337,1309,1303,1327,1360,1366,1332,1283,1251,1243,
+1234,1207,1169,1134,1102,1061,1011,961,922,894,873,856,837,814,791,772,754,734,715,701,689,
+674,657,648,649,645,622,586,553,528,506,482,458,432,405,383,373,368,352,329,315,310,
+284,225,168,153,172,172,131,79,50,36,12,-20,-42,-60,-98,-155,-199,-209,-208,-221,-248,
+-267,-275,-284,-296,-304,-307,-317,-339,-360,-370,-380,-406,-447,-490,-521,-540,-552,-561,-567,-571,-573,
+-576,-587,-607,-631,-649,-654,-650,-648,-655,-671,-690,-706,-722,-742,-765,-786,-803,-818,-835,-852,-866,
+-879,-892,-904,-914,-924,-936,-947,-951,-951,-951,-951,-948,-942,-936,-935,-934,-932,-932,-936,-940,-938,
+-933,-931,-934,-936,-938,-938,-938,-935,-931,-931,-934,-934,-931,-927,-927,-926,-922,-918,-918,-919,-914,
+-904,-895,-890,-886,-882,-877,-872,-864,-852,-841,-834,-828,-819,-806,-794,-786,-779,-769,-757,-748,-742,
+-736,-729,-719,-708,-698,-690,-684,-676,-666,-653,-641,-629,-615,-598,-580,-564,-551,-539,-527,-514,-501,
+-491,-482,-475,-468,-462,-457,-456,-455,-453,-448,-444,-441,-437,-434,-432,-433,-435,-437,-438,-440,-442,
+-443,-446,-451,-458,-462,-465,-471,-481,-490,-494,-498,-510,-528,-544,-554,-562,-576,-592,-607,-620,-637,
+-658,-676,-692,-707,-728,-753,-776,-795,-806,-809,-805,-803,-807,-816,-824,-830,-834,-837,-836,-834,-832,
+-828,-822,-816,-816,-819,-820,-817,-816,-820,-825,-827,-829,-834,-836,-830,-823,-821,-822,-819,-812,-806,
+-802,-795,-785,-778,-774,-766,-750,-733,-722,-714,-703,-690,-677,-665,-652,-638,-627,-618,-606,-589,-571,
+-557,-547,-534,-516,-496,-480,-471,-465,-454,-439,-426,-416,-402,-379,-353,-332,-312,-280,-238,-198,-164,
+-129,-83,-33,16,67,122,178,231,286,349,419,488,556,621,677,721,754,776,776,746,709,
+703,766,918,1156,1447,1741,2018,2326,2726,3184,3558,3720,3680,3561,3479,3470,3512,3582,3679,3812,3987,
+4185,4356,4458,4505,4558,4639,4701,4677,4548,4334,4058,3758,3497,3326,3221,3107,2967,2872,2892,3000,3096,
+3115,3067,2996,2936,2907,2917,2954,2979,2967,2927,2887,2852,2790,2678,2529,2385,2272,2182,2093,2004,1933,
+1890,1861,1829,1791,1756,1718,1666,1596,1521,1449,1374,1295,1228,1185,1153,1116,1078,1052,1021,938,765,
+522,270,57,-104,-224,-309,-363,-401,-439,-486,-547,-626,-720,-801,-836,-823,-796,-785,-791,-802,-824,
+-877,-956,-1024,-1057,-1066,-1076,-1087,-1083,-1064,-1055,-1071,-1111,-1173,-1266,-1392,-1529,-1649,-1736,-1784,-1779,-1707,
+-1585,-1455,-1359,-1305,-1273,-1246,-1226,-1223,-1245,-1283,-1325,-1361,-1388,-1406,-1414,-1416,-1412,-1388,-1330,-1245,-1174,
+-1148,-1148,-1125,-1063,-1003,-990,-1013,-1028,-1019,-1011,-1030,-1064,-1090,-1106,-1129,-1170,-1220,-1265,-1291,-1292,-1272,
+-1244,-1222,-1205,-1182,-1149,-1110,-1073,-1041,-1013,-984,-947,-904,-868,-848,-842,-835,-820,-805,-796,-791,-785,
+-780,-781,-783,-780,-775,-774,-779,-779,-773,-767,-762,-754,-743,-732,-727,-720,-707,-691,-678,-671,-664,
+-655,-646,-631,-609,-581,-555,-532,-506,-476,-444,-415,-386,-355,-319,-282,-243,-200,-157,-116,-74,-29,
+15,56,95,135,178,222,262,302,341,379,413,446,480,515,550,583,615,653,697,745,790,
+824,851,874,894,908,914,917,921,927,935,944,956,970,983,992,1003,1017,1028,1034,1040,1052,
+1067,1078,1085,1092,1108,1134,1163,1190,1215,1236,1251,1258,1263,1277,1300,1317,1317,1303,1291,1292,1302,
+1317,1332,1348,1355,1346,1320,1289,1267,1257,1257,1258,1257,1254,1249,1244,1239,1235,1234,1232,1249,1241,
+1233,1231,1235,1239,1238,1233,1231,1233,1235,1234,1234,1237,1244,1252,1259,1263,1266,1269,1275,1284,1294,
+1306,1320,1336,1352,1369,1387,1405,1422,1434,1445,1458,1472,1487,1500,1513,1528,1548,1573,1601,1629,1662,
+1704,1748,1783,1817,1876,1975,2087,2156,2151,2096,2053,2065,2123,2189,2227,2236,2233,2230,2214,2161,2071,
+1970,1887,1828,1781,1733,1682,1630,1577,1524,1471,1420,1372,1322,1270,1218,1173,1134,1080,986,853,717,
+622,574,552,535,521,509,492,463,429,394,350,298,257,241,238,222,184,142,107,70,23,
+-27,-73,-121,-177,-238,-290,-332,-372,-416,-454,-475,-494,-543,-653,-813,-977,-1095,-1160,-1200,-1230,-1234,
+-1197,-1138,-1101,-1101,-1107,-1088,-1063,-1091,-1213,-1403,-1576,-1655,-1632,-1579,-1580,-1651,-1742,-1799,-1823,-1853,-1917,
+-1997,-2051,-2051,-2008,-1961,-1951,-1982,-2027,-2057,-2079,-2126,-2213,-2314,-2390,-2417,-2400,-2363,-2340,-2354,-2405,-2472,
+-2527,-2561,-2584,-2610,-2643,-2669,-2675,-2664,-2654,-2656,-2660,-2649,-2623,-2596,-2574,-2552,-2528,-2510,-2488,-2422,-2283,
+-2086,-1888,-1738,-1650,-1614,-1611,-1615,-1614,-1627,-1698,-1844,-2024,-2175,-2271,-2328,-2367,-2397,-2420,-2445,-2474,-2500,
+-2515,-2529,-2548,-2566,-2572,-2569,-2565,-2569,-2578,-2588,-2595,-2599,-2601,-2605,-2614,-2627,-2645,-2670,-2701,-2734,-2766,
+-2803,-2846,-2895,-2954,-3034,-3118,-3148,-3068,-2899,-2741,-2695,-2774,-2906,-3017,-3090,-3142,-3192,-3239,-3279,-3315,-3355,
+-3397,-3435,-3465,-3486,-3505,-3529,-3559,-3590,-3619,-3648,-3680,-3715,-3753,-3799,-3854,-3914,-3971,-4027,-4086,-4149,-4214,
+-4278,-4345,-4415,-4480,-4536,-4587,-4644,-4706,-4774,-4845,-4921,-5001,-5078,-5150,-5216,-5275,-5328,-5376,-5423,-5469,-5514,
+-5561,-5611,-5660,-5702,-5740,-5779,-5821,-5863,-5900,-5936,-5972,-6002,-6022,-6034,-6046,-6057,-6065,-6071,-6079,-6087,-6096,
+-6108,-6128,-6150,-6169,-6183,-6203,-6231,-6256,-6271,-6278,-6283,-6284,-6276,-6265,-6259,-6267,-6292,-6335,-6392,-6451,-6495,
+-6515,-6512,-6492,-6466,-6442,-6421,-6395,-6361,-6321,-6285,-6258,-6237,-6205,-6143,-6044,-5937,-5879,-5909,-6002,-6085,-6104,
+-6055,-5974,-5899,-5861,-5871,-5908,-5918,-5861,-5749,-5639,-5575,-5558,-5547,-5503,-5416,-5320,-5271,-5284,-5302,-5249,-5111,
+-4948,-4811,-4697,-4585,-4489,-4434,-4401,-4344,-4259,-4185,-4152,-4138,-4113,-4084,-4067,-4047,-3997,-3920,-3848,-3798,-3755,
+-3697,-3619,-3518,-3386,-3230,-3084,-2979,-2906,-2837,-2765,-2718,-2714,-2725,-2707,-2648,-2582,-2540,-2506,-2441,-2335,-2219,
+-2127,-2053,-1971,-1874,-1779,-1702,-1639,-1577,-1512,-1437,-1333,-1184,-1013,-875,-813,-822,-855,-866,-841,-797,-753,
+-711,-659,-589,-506,-414,-314,-212,-121,-47,16,84,152,198,218,233,271,335,409,479,545,611,
+674,730,778,826,877,934,993,1056,1126,1205,1295,1398,1520,1661,1814,1957,2071,2146,2190,2221,2264,
+2342,2466,2616,2753,2847,2902,2943,2992,3058,3139,3227,3309,3368,3404,3428,3453,3487,3526,3567,3606,3641,
+3676,3718,3769,3824,3866,3892,3922,3992,4110,4230,4284,4254,4206,4221,4314,4423,4489,4521,4569,4658,4763,
+4847,4903,4947,5000,5066,5139,5201,5235,5244,5243,5244,5248,5258,5286,5333,5383,5419,5447,5482,5527,5564,
+5582,5586,5589,5594,5593,5584,5575,5578,5601,5639,5682,5721,5755,5789,5829,5876,5933,6002,6078,6148,6206,
+6258,6312,6373,6444,6525,6599,6639,6623,6556,6471,6407,6381,6390,6411,6421,6418,6423,6451,6490,6504,6478,
+6428,6381,6346,6319,6297,6287,6285,6283,6282,6284,6292,6302,6310,6318,6325,6330,6336,6345,6356,6361,6360,
+6359,6361,6364,6364,6368,6383,6411,6445,6480,6517,6562,6614,6662,6690,6689,6664,6623,6571,6508,6448,6416,
+6427,6469,6507,6513,6484,6442,6419,6431,6459,6471,6459,6446,6445,6443,6428,6416,6421,6421,6386,6330,6297,
+6294,6287,6263,6256,6280,6299,6282,6255,6208,6028,5619,5100,4781,4875,5289,5748,6072,6263,6377,6418,6390,
+6345,6339,6360,6366,6348,6333,6326,6306,6266,6229,6208,6186,6148,6102,6063,6029,5991,5946,5903,5863,5821,
+5770,5714,5663,5623,5595,5567,5525,5470,5416,5373,5338,5300,5255,5207,5163,5127,5094,5057,5012,4964,4919,
+4865,4787,4698,4636,4627,4647,4648,4613,4564,4520,4477,4426,4372,4319,4259,4193,4142,4108,4049,3916,3728,
+3572,3518,3541,3568,3548,3478,3368,3227,3097,3045,3099,3211,3305,3352,3376,3381,3320,3158,2942,2776,2716,
+2728,2739,2709,2639,2535,2400,2254,2132,2053,2001,1946,1877,1808,1752,1709,1672,1635,1598,1560,1519,1479,
+1443,1413,1384,1347,1310,1290,1298,1318,1318,1288,1251,1230,1220,1197,1154,1112,1085,1066,1036,994,953,
+919,892,867,846,825,802,778,759,744,730,716,703,688,667,645,637,641,641,622,590,560,
+537,515,494,473,450,420,394,383,379,363,338,325,320,293,235,183,184,223,242,215,171,
+141,108,48,-22,-70,-90,-113,-155,-193,-207,-208,-218,-239,-256,-268,-283,-300,-308,-311,-320,-341,
+-365,-383,-403,-434,-476,-513,-537,-551,-561,-567,-569,-569,-571,-580,-598,-623,-650,-671,-682,-682,-681,
+-687,-699,-712,-723,-737,-758,-785,-810,-830,-844,-857,-869,-880,-893,-906,-916,-923,-933,-946,-957,-961,
+-960,-961,-963,-960,-955,-951,-951,-950,-946,-943,-944,-945,-942,-939,-939,-942,-943,-942,-942,-941,-936,
+-930,-928,-931,-934,-932,-931,-931,-929,-923,-917,-912,-909,-902,-893,-885,-879,-875,-873,-871,-868,-860,
+-848,-835,-826,-817,-808,-798,-788,-779,-770,-761,-753,-744,-734,-722,-712,-702,-690,-677,-664,-651,-641,
+-631,-620,-608,-594,-582,-569,-555,-540,-526,-513,-502,-490,-477,-466,-458,-451,-443,-435,-431,-430,-430,
+-427,-422,-418,-415,-414,-412,-412,-414,-417,-419,-421,-423,-425,-427,-430,-436,-443,-446,-447,-452,-462,
+-473,-480,-483,-490,-503,-516,-526,-537,-552,-569,-585,-600,-618,-639,-656,-668,-683,-705,-730,-753,-770,
+-780,-782,-779,-777,-782,-790,-796,-800,-803,-806,-806,-802,-798,-795,-792,-791,-792,-795,-794,-791,-793,
+-799,-803,-802,-802,-808,-813,-810,-801,-797,-798,-798,-792,-785,-781,-775,-768,-762,-758,-750,-735,-718,
+-704,-694,-684,-671,-658,-643,-628,-616,-608,-601,-591,-575,-558,-544,-532,-522,-510,-494,-478,-467,-460,
+-452,-439,-426,-415,-401,-379,-352,-330,-311,-282,-242,-200,-161,-120,-71,-19,29,74,122,173,226,
+283,347,416,486,558,629,694,746,785,819,841,840,812,776,772,851,1042,1322,1626,1910,2204,
+2576,3029,3453,3709,3752,3657,3552,3528,3593,3698,3797,3891,4020,4193,4354,4449,4493,4560,4687,4833,4923,
+4909,4770,4497,4131,3768,3496,3321,3187,3070,3004,3011,3053,3068,3039,2991,2948,2916,2902,2917,2952,2973,
+2960,2921,2883,2843,2776,2664,2523,2389,2286,2202,2115,2023,1946,1899,1870,1842,1810,1776,1736,1677,1605,
+1536,1475,1414,1347,1277,1208,1136,1071,1036,1033,1016,920,729,488,260,73,-73,-186,-270,-332,-383,
+-431,-476,-525,-593,-679,-755,-790,-787,-775,-780,-802,-828,-863,-913,-971,-1009,-1015,-1005,-1004,-1014,-1020,
+-1018,-1019,-1038,-1078,-1143,-1240,-1364,-1494,-1603,-1680,-1723,-1726,-1677,-1582,-1470,-1375,-1315,-1280,-1256,-1240,-1236,
+-1247,-1269,-1297,-1328,-1355,-1364,-1353,-1339,-1345,-1362,-1352,-1297,-1228,-1187,-1173,-1145,-1088,-1034,-1015,-1012,-990,
+-957,-956,-1004,-1068,-1107,-1127,-1154,-1198,-1244,-1276,-1291,-1288,-1272,-1247,-1223,-1201,-1174,-1140,-1105,-1075,-1046,
+-1012,-973,-932,-893,-864,-847,-837,-825,-808,-792,-779,-769,-761,-759,-762,-762,-753,-743,-742,-745,-744,
+-738,-733,-733,-731,-724,-717,-714,-708,-696,-681,-671,-665,-656,-644,-632,-618,-597,-571,-546,-523,-498,
+-470,-440,-411,-380,-346,-311,-275,-238,-196,-155,-116,-77,-35,7,47,85,126,169,211,249,286,
+325,365,401,434,467,501,536,569,602,641,684,729,767,798,825,853,877,893,901,907,916,
+924,930,937,949,965,981,995,1008,1018,1025,1029,1038,1053,1072,1087,1097,1108,1124,1147,1173,1199,
+1223,1243,1257,1266,1273,1284,1297,1304,1301,1297,1302,1315,1327,1330,1328,1329,1331,1325,1307,1284,1271,
+1270,1278,1283,1281,1273,1267,1263,1261,1258,1255,1249,1268,1262,1259,1259,1263,1265,1261,1253,1248,1248,
+1251,1253,1253,1257,1265,1273,1278,1279,1281,1286,1293,1299,1305,1313,1326,1344,1363,1382,1400,1419,1437,
+1450,1459,1469,1481,1490,1496,1499,1508,1527,1555,1588,1626,1672,1723,1767,1798,1833,1897,1993,2088,2140,
+2132,2092,2068,2091,2155,2225,2263,2261,2241,2225,2205,2156,2072,1976,1898,1843,1795,1744,1692,1643,1594,
+1542,1488,1438,1391,1344,1293,1241,1195,1156,1107,1026,912,793,701,642,602,575,561,556,542,513,
+476,436,390,341,303,285,271,239,188,141,110,87,61,29,-8,-60,-126,-190,-239,-281,-334,
+-400,-458,-491,-518,-582,-707,-872,-1018,-1104,-1134,-1141,-1147,-1151,-1147,-1140,-1144,-1156,-1156,-1124,-1069,-1034,
+-1074,-1211,-1392,-1523,-1555,-1535,-1545,-1617,-1706,-1764,-1793,-1828,-1890,-1964,-2019,-2033,-2005,-1966,-1959,-1996,-2047,
+-2080,-2103,-2143,-2205,-2268,-2320,-2366,-2400,-2396,-2347,-2299,-2305,-2367,-2437,-2479,-2500,-2530,-2575,-2617,-2638,-2645,
+-2650,-2658,-2657,-2638,-2606,-2574,-2548,-2523,-2497,-2470,-2426,-2338,-2193,-2014,-1840,-1697,-1599,-1556,-1568,-1602,-1613,
+-1603,-1631,-1745,-1919,-2083,-2190,-2253,-2303,-2345,-2374,-2392,-2411,-2430,-2446,-2459,-2476,-2496,-2508,-2509,-2503,-2503,
+-2511,-2522,-2530,-2532,-2529,-2528,-2533,-2546,-2565,-2589,-2615,-2646,-2689,-2741,-2792,-2841,-2903,-2988,-3061,-3047,-2911,
+-2715,-2580,-2582,-2691,-2824,-2926,-2998,-3057,-3106,-3147,-3185,-3228,-3274,-3316,-3350,-3377,-3396,-3415,-3439,-3471,-3501,
+-3525,-3546,-3571,-3602,-3638,-3682,-3738,-3803,-3870,-3933,-3992,-4048,-4106,-4169,-4239,-4310,-4374,-4429,-4482,-4540,-4603,
+-4672,-4745,-4823,-4901,-4975,-5047,-5116,-5178,-5230,-5275,-5320,-5365,-5408,-5452,-5500,-5548,-5589,-5625,-5665,-5710,-5752,
+-5786,-5817,-5849,-5878,-5898,-5913,-5928,-5942,-5953,-5964,-5977,-5991,-6003,-6020,-6044,-6071,-6090,-6101,-6117,-6141,-6164,
+-6177,-6185,-6195,-6203,-6202,-6197,-6200,-6218,-6247,-6286,-6335,-6391,-6438,-6456,-6441,-6405,-6366,-6336,-6308,-6272,-6221,
+-6165,-6120,-6098,-6093,-6083,-6037,-5950,-5862,-5835,-5894,-5995,-6069,-6075,-6026,-5949,-5876,-5835,-5846,-5890,-5907,-5854,
+-5747,-5645,-5588,-5565,-5539,-5481,-5391,-5302,-5256,-5266,-5281,-5233,-5106,-4951,-4826,-4737,-4667,-4607,-4554,-4481,-4369,
+-4244,-4161,-4141,-4148,-4146,-4137,-4129,-4107,-4049,-3965,-3889,-3835,-3789,-3733,-3663,-3576,-3457,-3311,-3169,-3065,-2997,
+-2937,-2876,-2831,-2817,-2814,-2793,-2745,-2694,-2658,-2624,-2561,-2464,-2358,-2260,-2166,-2061,-1955,-1869,-1804,-1738,-1663,
+-1591,-1527,-1442,-1306,-1137,-998,-941,-956,-989,-992,-958,-908,-862,-820,-768,-699,-619,-533,-442,-340,-233,
+-134,-50,15,62,88,101,120,165,236,313,383,442,499,557,614,668,719,771,830,897,966,
+1038,1117,1210,1316,1433,1560,1694,1825,1936,2015,2065,2106,2164,2264,2406,2563,2695,2779,2831,2878,2935,
+3002,3078,3159,3235,3295,3335,3367,3401,3439,3481,3526,3574,3619,3661,3707,3766,3828,3872,3886,3892,3931,
+4022,4128,4187,4176,4143,4161,4248,4349,4409,4434,4471,4546,4640,4718,4773,4821,4878,4948,5021,5083,5122,
+5137,5141,5147,5159,5177,5205,5246,5291,5330,5367,5413,5464,5501,5511,5502,5492,5490,5491,5489,5489,5498,
+5523,5560,5603,5646,5687,5725,5765,5811,5870,5942,6020,6093,6158,6214,6265,6314,6373,6450,6536,6607,6636,
+6619,6571,6514,6465,6432,6413,6400,6391,6396,6423,6461,6484,6477,6447,6406,6362,6317,6278,6249,6230,6218,
+6212,6214,6221,6228,6237,6249,6260,6268,6275,6285,6296,6305,6314,6326,6338,6342,6339,6341,6355,6375,6397,
+6422,6457,6503,6553,6593,6610,6598,6561,6515,6471,6429,6395,6388,6423,6479,6513,6497,6447,6406,6409,6443,
+6472,6469,6451,6445,6449,6432,6388,6355,6362,6381,6362,6307,6267,6259,6244,6200,6156,6142,6145,6149,6171,
+6188,6073,5717,5216,4864,4888,5237,5675,6031,6275,6420,6460,6416,6367,6371,6402,6404,6378,6363,6366,6352,
+6312,6274,6258,6245,6209,6157,6108,6068,6029,5988,5948,5910,5868,5821,5775,5730,5686,5643,5602,5561,5518,
+5476,5438,5399,5354,5301,5251,5210,5178,5149,5114,5070,5025,4989,4951,4897,4828,4772,4745,4730,4697,4646,
+4605,4579,4547,4497,4447,4417,4394,4358,4309,4256,4174,4026,3826,3653,3574,3571,3576,3540,3464,3360,3230,
+3103,3037,3065,3147,3218,3256,3289,3326,3322,3234,3094,2981,2942,2954,2962,2936,2863,2734,2553,2355,2191,
+2085,2014,1947,1871,1800,1743,1701,1665,1631,1598,1564,1527,1489,1453,1421,1389,1351,1310,1280,1274,1282,
+1279,1258,1234,1221,1207,1171,1117,1072,1051,1039,1015,977,941,913,888,863,839,816,791,768,751,
+742,734,722,708,692,670,647,636,636,631,614,590,570,552,530,508,491,474,447,419,404,
+397,379,351,333,324,296,240,197,208,255,282,265,235,215,181,104,6,-62,-82,-88,-109,
+-143,-170,-186,-201,-217,-233,-250,-272,-291,-300,-303,-313,-337,-366,-394,-425,-459,-492,-513,-525,-536,
+-549,-560,-561,-559,-563,-579,-604,-632,-658,-682,-699,-707,-710,-714,-724,-738,-751,-765,-786,-810,-833,
+-851,-866,-880,-891,-902,-913,-923,-929,-933,-942,-955,-966,-969,-966,-966,-966,-965,-961,-961,-962,-960,
+-955,-952,-951,-949,-946,-945,-947,-950,-948,-944,-943,-942,-937,-930,-927,-929,-932,-931,-931,-930,-928,
+-923,-915,-908,-901,-893,-885,-878,-871,-866,-863,-863,-860,-852,-840,-828,-818,-808,-798,-791,-782,-771,
+-762,-755,-751,-744,-731,-716,-704,-694,-683,-668,-650,-632,-617,-604,-592,-578,-563,-551,-541,-530,-515,
+-498,-484,-475,-466,-454,-444,-436,-429,-421,-413,-409,-407,-406,-403,-399,-395,-392,-391,-392,-394,-396,
+-398,-399,-401,-403,-406,-408,-412,-418,-424,-427,-428,-432,-442,-454,-462,-466,-472,-483,-496,-508,-519,
+-533,-548,-563,-580,-602,-624,-640,-650,-663,-683,-706,-726,-739,-747,-750,-751,-753,-760,-767,-769,-769,
+-771,-774,-774,-769,-763,-760,-760,-761,-765,-768,-767,-766,-769,-776,-780,-778,-776,-780,-786,-783,-775,
+-771,-772,-774,-770,-764,-760,-757,-752,-747,-742,-734,-721,-706,-692,-680,-668,-655,-642,-628,-613,-600,
+-593,-586,-577,-565,-550,-534,-521,-512,-505,-495,-480,-465,-454,-444,-432,-418,-406,-393,-374,-348,-323,
+-299,-270,-233,-195,-158,-117,-68,-15,33,79,127,177,229,286,350,417,486,557,631,703,762,
+809,850,888,915,913,876,831,832,938,1166,1469,1787,2101,2446,2842,3251,3584,3765,3788,3725,3680,
+3710,3790,3866,3932,4030,4181,4337,4434,4480,4539,4651,4792,4912,4966,4914,4724,4415,4068,3767,3539,3372,
+3260,3204,3173,3113,3014,2920,2877,2883,2899,2910,2921,2935,2936,2914,2877,2837,2790,2717,2610,2480,2357,
+2260,2185,2113,2034,1962,1912,1880,1854,1828,1802,1764,1703,1628,1554,1490,1429,1366,1301,1228,1142,1064,
+1023,1016,981,855,642,409,215,67,-53,-153,-233,-300,-363,-419,-462,-500,-553,-626,-698,-742,-756,
+-759,-771,-797,-834,-879,-926,-960,-968,-953,-933,-927,-938,-956,-971,-989,-1017,-1063,-1133,-1229,-1344,-1460,
+-1554,-1619,-1659,-1675,-1655,-1594,-1501,-1405,-1333,-1293,-1274,-1268,-1271,-1282,-1296,-1312,-1328,-1341,-1337,-1313,-1291,
+-1300,-1336,-1356,-1330,-1275,-1228,-1195,-1151,-1093,-1047,-1026,-1002,-953,-908,-922,-999,-1087,-1140,-1165,-1196,-1238,
+-1273,-1288,-1291,-1286,-1272,-1247,-1216,-1186,-1155,-1123,-1096,-1071,-1042,-1002,-955,-913,-879,-853,-832,-814,-799,
+-786,-773,-759,-744,-734,-736,-744,-747,-741,-732,-730,-729,-724,-715,-712,-715,-717,-713,-708,-705,-699,
+-687,-674,-666,-660,-648,-632,-616,-602,-584,-561,-537,-513,-487,-460,-433,-406,-377,-343,-308,-274,-237,
+-197,-156,-119,-83,-44,-3,37,76,117,160,201,237,273,312,353,391,425,457,490,523,555,
+588,626,669,711,746,776,807,840,866,883,894,907,922,933,936,937,944,959,976,993,1008,
+1018,1023,1028,1040,1059,1081,1100,1116,1132,1147,1162,1179,1200,1222,1240,1251,1259,1271,1287,1303,1311,
+1311,1311,1318,1328,1331,1321,1309,1303,1303,1303,1297,1289,1287,1293,1300,1303,1298,1290,1284,1282,1282,
+1280,1274,1268,1287,1284,1284,1283,1282,1281,1279,1275,1271,1270,1272,1274,1276,1280,1286,1292,1295,1296,
+1298,1302,1307,1311,1313,1320,1334,1353,1374,1394,1414,1434,1450,1462,1470,1478,1488,1493,1491,1488,1496,
+1518,1551,1589,1633,1688,1742,1783,1812,1851,1921,2011,2087,2125,2130,2123,2126,2153,2205,2265,2300,2294,
+2262,2229,2199,2149,2069,1980,1907,1854,1804,1752,1700,1655,1610,1562,1509,1458,1410,1363,1316,1266,1219,
+1178,1131,1063,970,870,785,719,667,629,609,600,583,550,508,466,426,387,357,335,307,258,
+196,146,119,108,98,80,48,-6,-75,-140,-190,-238,-305,-390,-467,-520,-567,-645,-767,-901,-1000,
+-1041,-1044,-1040,-1046,-1066,-1100,-1144,-1183,-1202,-1193,-1152,-1078,-991,-952,-1023,-1194,-1371,-1467,-1487,-1502,-1557,
+-1632,-1694,-1743,-1796,-1858,-1922,-1975,-2000,-1989,-1960,-1955,-1992,-2044,-2078,-2103,-2139,-2178,-2203,-2235,-2311,-2411,
+-2451,-2385,-2274,-2225,-2273,-2359,-2418,-2445,-2471,-2512,-2556,-2591,-2613,-2622,-2615,-2595,-2575,-2564,-2555,-2536,-2503,
+-2462,-2416,-2355,-2261,-2135,-1994,-1849,-1705,-1581,-1520,-1544,-1609,-1634,-1599,-1577,-1654,-1826,-2006,-2124,-2187,-2238,
+-2291,-2329,-2346,-2357,-2372,-2388,-2400,-2413,-2429,-2442,-2441,-2432,-2427,-2431,-2439,-2444,-2445,-2445,-2446,-2453,-2468,
+-2492,-2518,-2543,-2575,-2626,-2689,-2745,-2791,-2855,-2943,-3000,-2940,-2750,-2534,-2430,-2482,-2621,-2755,-2850,-2917,-2972,
+-3013,-3048,-3091,-3144,-3193,-3227,-3254,-3279,-3301,-3320,-3342,-3371,-3399,-3419,-3435,-3457,-3488,-3524,-3567,-3624,-3694,
+-3767,-3833,-3890,-3942,-3994,-4055,-4124,-4195,-4259,-4317,-4376,-4439,-4504,-4572,-4646,-4723,-4796,-4868,-4941,-5016,-5082,
+-5134,-5178,-5222,-5267,-5306,-5345,-5389,-5435,-5476,-5512,-5551,-5596,-5637,-5669,-5698,-5728,-5756,-5777,-5796,-5815,-5832,
+-5844,-5858,-5877,-5898,-5915,-5933,-5959,-5987,-6006,-6016,-6031,-6053,-6074,-6085,-6093,-6107,-6122,-6130,-6134,-6146,-6171,
+-6202,-6235,-6275,-6324,-6367,-6382,-6361,-6313,-6259,-6212,-6168,-6117,-6055,-5991,-5946,-5936,-5954,-5966,-5934,-5857,-5786,
+-5787,-5872,-5985,-6057,-6060,-6011,-5937,-5858,-5808,-5815,-5861,-5882,-5830,-5727,-5634,-5584,-5558,-5519,-5451,-5364,-5285,
+-5245,-5250,-5256,-5204,-5080,-4928,-4807,-4738,-4704,-4678,-4629,-4530,-4385,-4245,-4168,-4159,-4174,-4179,-4177,-4170,-4141,
+-4074,-3988,-3919,-3872,-3826,-3767,-3699,-3621,-3520,-3392,-3263,-3161,-3092,-3036,-2983,-2939,-2911,-2893,-2870,-2839,-2810,
+-2782,-2740,-2668,-2573,-2472,-2371,-2260,-2139,-2032,-1960,-1904,-1831,-1737,-1650,-1589,-1522,-1408,-1259,-1134,-1084,-1097,
+-1121,-1117,-1079,-1029,-983,-942,-892,-822,-736,-644,-551,-448,-331,-212,-114,-51,-17,1,16,39,77,
+134,203,273,335,390,442,495,549,601,653,712,782,856,929,1006,1096,1201,1319,1444,1573,1698,
+1809,1899,1968,2032,2113,2230,2381,2536,2656,2729,2781,2838,2907,2977,3044,3115,3186,3245,3287,3318,3352,
+3392,3438,3492,3550,3600,3642,3687,3751,3827,3884,3900,3887,3889,3935,4009,4065,4077,4075,4108,4187,4273,
+4324,4345,4374,4433,4507,4574,4629,4687,4753,4824,4894,4952,4992,5012,5024,5042,5068,5096,5126,5161,5203,
+5249,5297,5351,5404,5438,5442,5424,5404,5397,5399,5404,5410,5422,5441,5473,5517,5569,5617,5657,5693,5741,
+5808,5887,5961,6024,6083,6144,6203,6254,6306,6374,6458,6538,6595,6620,6619,6594,6548,6491,6435,6391,6366,
+6365,6385,6417,6443,6453,6449,6432,6401,6360,6318,6278,6243,6215,6199,6193,6189,6183,6181,6189,6203,6215,
+6225,6237,6249,6259,6273,6293,6311,6316,6310,6309,6319,6331,6341,6362,6403,6455,6499,6521,6519,6491,6448,
+6406,6378,6365,6367,6391,6441,6492,6504,6461,6398,6371,6397,6445,6466,6448,6423,6416,6411,6370,6296,6244,
+6251,6282,6275,6225,6183,6173,6162,6117,6056,6018,6009,6025,6073,6121,6052,5766,5350,5056,5071,5347,5694,
+5987,6214,6376,6441,6419,6386,6403,6444,6447,6416,6396,6399,6392,6357,6319,6298,6282,6246,6196,6147,6104,
+6061,6017,5979,5945,5911,5874,5835,5791,5740,5685,5639,5603,5570,5535,5495,5451,5401,5349,5302,5265,5235,
+5207,5171,5126,5078,5036,5000,4957,4901,4843,4799,4761,4718,4673,4644,4629,4601,4550,4497,4466,4447,4417,
+4374,4334,4281,4177,4012,3841,3731,3690,3672,3634,3562,3453,3304,3138,3006,2953,2970,3015,3063,3113,3157,
+3170,3143,3104,3089,3099,3106,3090,3051,2975,2837,2636,2419,2245,2132,2049,1964,1875,1798,1740,1696,1659,
+1625,1593,1559,1522,1483,1444,1407,1373,1340,1306,1278,1266,1265,1259,1241,1222,1210,1191,1148,1092,1049,
+1032,1021,994,957,924,900,878,855,832,810,784,760,746,741,735,723,709,694,676,656,642,
+634,623,606,592,584,572,549,524,507,494,472,444,426,415,393,361,336,321,291,240,203,
+213,249,263,242,223,227,219,161,71,3,-16,-15,-30,-69,-116,-156,-181,-194,-205,-222,-244,
+-261,-268,-273,-289,-318,-353,-390,-429,-465,-489,-497,-502,-516,-538,-554,-558,-556,-563,-585,-613,-639,
+-663,-688,-713,-730,-737,-742,-754,-773,-791,-807,-823,-840,-856,-870,-886,-904,-919,-931,-940,-946,-949,
+-952,-958,-968,-975,-975,-971,-969,-968,-966,-965,-967,-968,-965,-959,-954,-953,-951,-949,-951,-955,-957,
+-952,-946,-944,-943,-940,-934,-930,-929,-929,-927,-926,-923,-919,-915,-909,-903,-895,-888,-882,-876,-869,
+-861,-857,-855,-850,-840,-830,-821,-811,-800,-790,-781,-771,-759,-748,-744,-742,-736,-723,-708,-698,-690,
+-678,-662,-644,-624,-606,-589,-574,-557,-539,-524,-514,-504,-489,-472,-458,-450,-443,-433,-423,-415,-408,
+-402,-396,-392,-389,-386,-384,-381,-377,-373,-372,-373,-377,-379,-379,-379,-380,-381,-383,-385,-389,-394,
+-400,-404,-409,-414,-422,-432,-442,-449,-458,-471,-485,-497,-508,-519,-531,-545,-564,-587,-609,-624,-631,
+-641,-659,-680,-696,-707,-714,-719,-726,-734,-744,-750,-748,-742,-741,-744,-745,-741,-735,-731,-728,-729,
+-734,-740,-742,-741,-742,-748,-752,-751,-750,-752,-755,-754,-750,-748,-750,-752,-749,-744,-741,-739,-737,
+-733,-726,-718,-707,-695,-683,-670,-656,-643,-630,-617,-604,-592,-582,-573,-563,-552,-541,-527,-512,-502,
+-498,-492,-479,-461,-447,-438,-426,-410,-393,-378,-361,-339,-312,-283,-248,-212,-177,-144,-107,-62,-12,
+36,83,133,186,241,298,362,430,499,569,641,713,779,836,886,933,975,998,986,938,889,
+903,1035,1290,1619,1961,2284,2606,2959,3333,3658,3847,3882,3841,3822,3862,3931,4009,4114,4256,4395,4481,
+4518,4552,4612,4689,4763,4817,4822,4747,4586,4373,4138,3896,3673,3509,3404,3301,3139,2941,2795,2755,2794,
+2847,2880,2895,2896,2883,2856,2823,2783,2729,2656,2558,2441,2321,2221,2150,2094,2037,1979,1929,1889,1859,
+1838,1824,1800,1747,1672,1591,1516,1442,1371,1304,1235,1151,1066,1009,975,905,751,533,326,172,59,
+-39,-130,-205,-269,-331,-384,-421,-452,-500,-570,-642,-693,-719,-726,-731,-749,-789,-841,-887,-908,-902,
+-883,-865,-863,-878,-906,-938,-972,-1015,-1075,-1151,-1240,-1333,-1422,-1500,-1562,-1607,-1638,-1644,-1608,-1529,-1429,
+-1345,-1297,-1282,-1286,-1298,-1315,-1332,-1342,-1344,-1338,-1319,-1290,-1268,-1273,-1303,-1328,-1319,-1282,-1236,-1184,-1120,
+-1057,-1021,-1009,-983,-928,-888,-919,-1019,-1125,-1188,-1218,-1248,-1283,-1303,-1302,-1292,-1281,-1264,-1235,-1201,-1169,
+-1138,-1108,-1081,-1056,-1024,-981,-933,-894,-864,-836,-808,-785,-772,-765,-757,-742,-724,-713,-715,-727,-735,
+-736,-733,-730,-726,-716,-706,-705,-710,-713,-710,-705,-701,-694,-682,-670,-662,-654,-640,-622,-605,-591,
+-575,-556,-534,-510,-483,-455,-428,-403,-375,-342,-309,-275,-239,-199,-159,-123,-88,-51,-12,28,68,
+109,151,192,229,264,302,341,378,414,448,481,512,541,572,610,653,695,730,762,796,832,
+861,880,896,916,936,947,945,942,945,957,974,993,1011,1024,1030,1038,1053,1074,1097,1118,1138,
+1155,1164,1169,1176,1193,1214,1230,1238,1245,1259,1280,1299,1311,1314,1315,1319,1320,1313,1302,1293,1293,
+1296,1296,1293,1293,1298,1305,1310,1312,1309,1304,1300,1300,1301,1298,1292,1287,1305,1304,1304,1302,1299,
+1298,1299,1299,1297,1293,1293,1295,1298,1303,1307,1311,1314,1316,1318,1320,1321,1322,1326,1336,1350,1368,
+1388,1408,1429,1446,1458,1466,1472,1480,1488,1492,1488,1486,1499,1529,1568,1607,1650,1703,1757,1797,1830,
+1879,1955,2036,2090,2118,2147,2188,2229,2261,2289,2322,2341,2327,2285,2238,2195,2139,2060,1975,1904,1852,
+1804,1755,1708,1666,1625,1581,1531,1480,1430,1383,1339,1294,1249,1204,1157,1096,1017,931,856,795,742,
+696,665,644,619,579,534,494,462,435,411,384,345,289,227,178,151,140,134,121,92,41,
+-21,-80,-130,-187,-267,-363,-454,-530,-606,-701,-814,-911,-963,-970,-960,-960,-975,-1008,-1061,-1126,-1177,
+-1191,-1176,-1141,-1078,-980,-897,-912,-1051,-1239,-1375,-1432,-1458,-1498,-1552,-1607,-1667,-1735,-1802,-1860,-1909,-1940,
+-1939,-1920,-1919,-1957,-2008,-2043,-2072,-2109,-2136,-2138,-2157,-2257,-2407,-2485,-2413,-2260,-2172,-2207,-2305,-2380,-2415,
+-2437,-2464,-2495,-2530,-2567,-2589,-2581,-2555,-2536,-2533,-2528,-2499,-2447,-2386,-2324,-2255,-2174,-2085,-1989,-1873,-1725,
+-1573,-1486,-1508,-1589,-1627,-1579,-1527,-1580,-1751,-1944,-2069,-2127,-2174,-2232,-2280,-2302,-2309,-2321,-2335,-2343,-2350,
+-2363,-2375,-2373,-2360,-2350,-2351,-2355,-2356,-2355,-2359,-2365,-2374,-2391,-2420,-2453,-2481,-2512,-2562,-2627,-2687,-2739,
+-2808,-2897,-2934,-2834,-2607,-2387,-2311,-2396,-2548,-2680,-2773,-2844,-2897,-2930,-2960,-3008,-3068,-3112,-3135,-3153,-3179,
+-3204,-3222,-3241,-3267,-3293,-3311,-3327,-3350,-3382,-3418,-3461,-3517,-3586,-3657,-3724,-3782,-3836,-3890,-3950,-4015,-4082,
+-4145,-4208,-4274,-4342,-4408,-4473,-4544,-4619,-4691,-4762,-4838,-4919,-4990,-5045,-5091,-5136,-5178,-5213,-5247,-5287,-5330,
+-5369,-5403,-5441,-5483,-5522,-5553,-5582,-5612,-5638,-5661,-5683,-5706,-5725,-5738,-5753,-5778,-5804,-5824,-5843,-5868,-5896,
+-5916,-5929,-5946,-5970,-5989,-5997,-6004,-6020,-6042,-6059,-6073,-6094,-6122,-6151,-6179,-6212,-6252,-6288,-6302,-6283,-6237,
+-6174,-6109,-6044,-5978,-5908,-5841,-5800,-5800,-5835,-5864,-5842,-5774,-5718,-5741,-5849,-5975,-6048,-6047,-5995,-5916,-5833,
+-5779,-5783,-5826,-5843,-5790,-5689,-5604,-5562,-5538,-5495,-5423,-5339,-5270,-5240,-5246,-5245,-5185,-5054,-4897,-4777,-4722,
+-4714,-4711,-4666,-4556,-4406,-4279,-4219,-4215,-4222,-4218,-4211,-4199,-4159,-4084,-4004,-3950,-3914,-3868,-3801,-3730,-3660,
+-3578,-3475,-3364,-3269,-3196,-3137,-3086,-3042,-3008,-2982,-2960,-2943,-2925,-2896,-2842,-2761,-2665,-2566,-2464,-2348,-2227,
+-2129,-2068,-2019,-1942,-1836,-1739,-1671,-1607,-1508,-1381,-1279,-1235,-1238,-1248,-1236,-1200,-1151,-1105,-1065,-1018,-947,
+-849,-740,-638,-537,-422,-299,-194,-125,-87,-62,-39,-19,0,28,81,151,223,283,334,384,439,
+492,542,598,665,742,817,888,967,1066,1188,1325,1463,1593,1710,1815,1914,2009,2112,2237,2384,2525,
+2629,2693,2745,2813,2890,2959,3019,3082,3151,3211,3249,3273,3300,3339,3393,3460,3529,3584,3622,3662,3724,
+3805,3870,3890,3871,3848,3852,3887,3930,3965,3996,4045,4115,4180,4219,4239,4267,4317,4377,4433,4490,4555,
+4627,4697,4761,4817,4860,4888,4908,4935,4971,5007,5038,5071,5115,5169,5227,5286,5340,5376,5382,5366,5345,
+5334,5333,5336,5341,5349,5363,5389,5432,5487,5539,5576,5608,5660,5740,5825,5891,5935,5984,6052,6129,6194,
+6248,6310,6386,6462,6520,6559,6587,6600,6584,6535,6464,6393,6342,6324,6337,6368,6399,6422,6436,6440,6432,
+6413,6386,6350,6308,6270,6245,6232,6215,6191,6168,6157,6157,6162,6172,6190,6210,6225,6240,6260,6277,6280,
+6274,6275,6285,6292,6293,6309,6351,6405,6443,6451,6435,6404,6369,6341,6330,6335,6355,6396,6454,6500,6494,
+6436,6371,6354,6391,6435,6444,6417,6385,6366,6341,6279,6197,6147,6157,6188,6184,6144,6119,6134,6154,6134,
+6079,6025,5992,5984,6006,6027,5955,5729,5435,5271,5351,5586,5814,5975,6121,6274,6382,6409,6404,6429,6475,
+6490,6464,6438,6431,6422,6394,6360,6334,6307,6268,6223,6183,6143,6097,6049,6011,5981,5950,5915,5876,5834,
+5786,5737,5696,5661,5624,5580,5535,5491,5448,5405,5365,5329,5294,5258,5219,5174,5123,5074,5032,4990,4940,
+4884,4834,4796,4763,4729,4699,4672,4635,4585,4535,4502,4478,4445,4404,4375,4356,4307,4198,4054,3935,3876,
+3857,3831,3761,3631,3442,3215,2993,2822,2736,2741,2815,2914,2980,2992,2982,3002,3054,3093,3079,3026,2966,
+2892,2768,2586,2397,2256,2164,2082,1987,1889,1809,1749,1701,1659,1622,1586,1549,1511,1471,1427,1384,1349,
+1325,1304,1284,1269,1259,1246,1224,1200,1182,1158,1116,1066,1030,1015,1002,975,939,910,888,867,847,
+829,809,783,757,743,737,729,715,703,694,681,661,644,632,619,604,596,594,586,563,536,
+520,509,488,461,441,428,405,369,339,317,287,241,205,204,218,208,174,158,179,203,188,
+139,98,86,87,66,15,-54,-116,-155,-169,-177,-192,-214,-229,-237,-248,-272,-304,-337,-373,-413,
+-449,-471,-480,-488,-508,-533,-549,-553,-554,-566,-590,-619,-642,-664,-693,-725,-750,-761,-768,-784,-810,
+-834,-851,-862,-872,-882,-895,-912,-932,-948,-957,-961,-967,-972,-976,-979,-982,-983,-982,-979,-977,-974,
+-972,-972,-975,-975,-970,-961,-956,-954,-952,-951,-954,-960,-962,-956,-948,-945,-945,-945,-941,-936,-932,
+-927,-924,-921,-916,-909,-903,-900,-897,-891,-883,-878,-874,-867,-859,-852,-847,-839,-828,-819,-812,-804,
+-792,-780,-770,-758,-743,-730,-726,-724,-717,-705,-693,-686,-678,-666,-652,-637,-620,-601,-582,-565,-545,
+-523,-505,-492,-482,-468,-452,-440,-432,-425,-415,-405,-396,-389,-384,-381,-378,-374,-370,-367,-366,-363,
+-358,-356,-357,-360,-361,-360,-360,-361,-361,-361,-363,-367,-370,-375,-382,-390,-397,-404,-413,-422,-432,
+-443,-456,-471,-485,-497,-509,-522,-537,-555,-576,-596,-607,-612,-619,-633,-652,-668,-679,-687,-694,-704,
+-717,-730,-735,-730,-720,-715,-717,-720,-719,-716,-711,-706,-703,-707,-715,-721,-721,-719,-720,-723,-724,
+-724,-725,-727,-728,-728,-731,-734,-733,-730,-726,-724,-723,-720,-717,-712,-705,-696,-687,-677,-664,-649,
+-634,-621,-609,-596,-585,-574,-562,-550,-539,-530,-519,-506,-495,-488,-481,-468,-452,-440,-433,-423,-405,
+-383,-363,-345,-326,-301,-270,-232,-193,-157,-123,-86,-43,1,45,90,141,197,255,314,378,448,
+521,592,661,730,800,868,928,979,1022,1057,1075,1056,1002,952,980,1139,1423,1762,2077,2356,2662,
+3045,3461,3783,3923,3920,3892,3921,4010,4127,4259,4392,4497,4550,4567,4577,4596,4618,4641,4668,4690,4692,
+4673,4622,4504,4289,4016,3765,3570,3380,3144,2897,2730,2683,2714,2760,2797,2823,2832,2820,2793,2762,2723,
+2672,2607,2529,2432,2321,2220,2148,2098,2051,2000,1950,1907,1872,1853,1848,1837,1796,1723,1640,1556,1470,
+1384,1308,1236,1153,1059,978,907,806,642,446,277,161,70,-20,-107,-177,-232,-282,-325,-359,-396,
+-452,-522,-587,-633,-655,-657,-652,-660,-698,-755,-804,-827,-826,-819,-816,-824,-849,-887,-930,-974,-1029,
+-1103,-1188,-1266,-1330,-1390,-1454,-1519,-1572,-1609,-1622,-1599,-1531,-1434,-1345,-1293,-1280,-1289,-1303,-1320,-1339,-1353,
+-1355,-1340,-1312,-1280,-1254,-1245,-1251,-1259,-1253,-1232,-1194,-1137,-1068,-1013,-997,-1003,-985,-930,-889,-924,-1034,
+-1154,-1232,-1271,-1299,-1324,-1333,-1322,-1301,-1278,-1250,-1218,-1187,-1161,-1133,-1100,-1066,-1035,-1002,-961,-919,-884,
+-854,-823,-792,-769,-760,-758,-749,-732,-713,-702,-704,-713,-722,-728,-731,-729,-722,-713,-707,-708,-713,
+-715,-713,-709,-705,-697,-686,-674,-665,-655,-640,-623,-606,-590,-573,-554,-535,-514,-488,-458,-429,-402,
+-374,-343,-310,-276,-240,-201,-162,-127,-93,-58,-19,19,59,98,139,179,218,255,291,327,363,
+400,438,474,505,533,562,599,641,683,718,750,784,821,855,880,902,926,946,953,950,945,
+949,963,981,1001,1020,1034,1044,1054,1070,1091,1112,1132,1151,1165,1170,1169,1173,1188,1207,1220,1226,
+1234,1249,1271,1289,1301,1307,1312,1314,1311,1303,1297,1300,1309,1314,1308,1300,1299,1306,1315,1319,1321,
+1320,1318,1316,1314,1315,1313,1309,1305,1323,1323,1324,1322,1319,1320,1323,1324,1321,1315,1313,1315,1319,
+1323,1328,1332,1335,1338,1341,1341,1339,1340,1346,1358,1370,1384,1401,1421,1439,1451,1458,1461,1467,1476,
+1485,1490,1490,1495,1517,1556,1597,1630,1666,1715,1771,1819,1864,1928,2013,2085,2118,2136,2182,2265,2343,
+2381,2383,2376,2365,2334,2283,2230,2180,2122,2046,1966,1898,1846,1802,1758,1715,1674,1634,1594,1550,1503,
+1452,1405,1363,1322,1278,1233,1186,1127,1054,976,912,861,814,765,723,689,655,610,562,523,498,
+478,456,427,390,344,296,250,214,188,172,155,127,83,31,-18,-67,-127,-205,-298,-394,-492,
+-597,-712,-826,-909,-943,-936,-920,-919,-938,-972,-1022,-1080,-1122,-1132,-1125,-1117,-1089,-1016,-928,-908,-1003,
+-1162,-1296,-1368,-1406,-1439,-1471,-1507,-1563,-1639,-1718,-1781,-1830,-1861,-1865,-1852,-1858,-1900,-1951,-1988,-2020,-2060,
+-2083,-2074,-2090,-2202,-2378,-2477,-2407,-2244,-2142,-2168,-2261,-2339,-2381,-2406,-2426,-2446,-2479,-2531,-2578,-2594,-2580,
+-2556,-2529,-2485,-2417,-2338,-2261,-2190,-2122,-2060,-2006,-1949,-1860,-1719,-1556,-1447,-1448,-1523,-1571,-1540,-1491,-1533,
+-1692,-1884,-2012,-2071,-2114,-2173,-2227,-2253,-2262,-2272,-2281,-2283,-2284,-2297,-2313,-2312,-2293,-2276,-2273,-2277,-2277,
+-2276,-2283,-2292,-2301,-2317,-2352,-2395,-2428,-2454,-2494,-2555,-2622,-2686,-2764,-2844,-2855,-2725,-2488,-2284,-2233,-2327,
+-2467,-2585,-2681,-2767,-2829,-2860,-2885,-2933,-2990,-3027,-3042,-3058,-3086,-3113,-3130,-3148,-3174,-3200,-3216,-3230,-3253,
+-3286,-3321,-3361,-3413,-3477,-3543,-3608,-3672,-3735,-3796,-3855,-3915,-3975,-4037,-4103,-4175,-4247,-4312,-4374,-4442,-4515,
+-4588,-4661,-4740,-4824,-4901,-4961,-5011,-5055,-5095,-5126,-5158,-5196,-5237,-5271,-5300,-5334,-5373,-5408,-5438,-5466,-5494,
+-5521,-5544,-5569,-5596,-5617,-5632,-5651,-5678,-5707,-5728,-5746,-5771,-5799,-5821,-5838,-5860,-5886,-5906,-5914,-5920,-5937,
+-5963,-5989,-6014,-6041,-6068,-6094,-6119,-6150,-6183,-6209,-6219,-6208,-6175,-6118,-6044,-5965,-5887,-5813,-5746,-5704,-5705,
+-5741,-5774,-5760,-5703,-5662,-5703,-5826,-5962,-6033,-6019,-5948,-5861,-5782,-5739,-5748,-5787,-5797,-5742,-5648,-5571,-5534,
+-5513,-5473,-5403,-5322,-5261,-5242,-5254,-5251,-5179,-5035,-4873,-4763,-4729,-4744,-4750,-4697,-4580,-4439,-4337,-4298,-4294,
+-4287,-4270,-4256,-4236,-4186,-4107,-4035,-3995,-3966,-3915,-3840,-3765,-3701,-3634,-3552,-3462,-3377,-3304,-3241,-3188,-3145,
+-3111,-3085,-3065,-3047,-3024,-2986,-2925,-2843,-2751,-2656,-2557,-2448,-2337,-2248,-2190,-2139,-2062,-1960,-1864,-1790,-1719,
+-1623,-1515,-1429,-1386,-1370,-1359,-1340,-1307,-1261,-1209,-1166,-1124,-1055,-949,-826,-718,-628,-534,-428,-326,-249,
+-197,-155,-119,-97,-90,-77,-36,34,114,180,232,283,340,398,448,499,566,647,728,795,859,
+946,1070,1219,1369,1503,1624,1747,1875,2004,2128,2255,2389,2511,2601,2660,2714,2784,2861,2925,2978,3035,
+3101,3159,3196,3217,3243,3285,3349,3428,3507,3568,3607,3642,3695,3763,3819,3839,3824,3793,3772,3772,3797,
+3841,3896,3958,4019,4066,4096,4121,4157,4209,4264,4314,4365,4426,4493,4558,4620,4682,4735,4772,4799,4830,
+4870,4908,4940,4975,5025,5086,5151,5212,5269,5310,5326,5318,5301,5288,5279,5274,5273,5279,5293,5316,5353,
+5403,5453,5488,5522,5578,5664,5752,5810,5843,5888,5965,6057,6134,6191,6252,6327,6399,6448,6480,6511,6547,
+6566,6546,6481,6392,6315,6277,6285,6323,6365,6397,6417,6431,6439,6442,6434,6411,6372,6333,6307,6293,6276,
+6245,6208,6174,6146,6127,6124,6140,6166,6187,6202,6217,6230,6235,6235,6244,6260,6268,6264,6271,6304,6353,
+6385,6388,6371,6349,6331,6322,6322,6329,6346,6383,6438,6481,6473,6416,6357,6343,6373,6406,6410,6385,6349,
+6311,6260,6192,6128,6103,6123,6151,6150,6134,6147,6203,6259,6263,6212,6136,6061,5997,5951,5901,5794,5608,
+5436,5426,5615,5862,6005,6036,6077,6200,6343,6421,6437,6453,6490,6517,6509,6484,6462,6443,6420,6396,6372,
+6341,6299,6257,6221,6183,6136,6087,6051,6023,5992,5952,5909,5867,5828,5791,5757,5719,5670,5618,5571,5533,
+5497,5460,5421,5381,5335,5286,5240,5199,5156,5110,5066,5024,4978,4924,4875,4843,4821,4794,4754,4709,4664,
+4620,4581,4552,4528,4495,4449,4411,4392,4372,4314,4213,4113,4058,4048,4034,3962,3817,3614,3372,3100,2821,
+2597,2503,2563,2712,2835,2875,2870,2892,2947,2973,2927,2839,2763,2697,2598,2457,2320,2227,2166,2093,1997,
+1900,1825,1766,1715,1667,1625,1585,1543,1503,1464,1419,1373,1336,1318,1307,1292,1271,1250,1228,1200,1170,
+1144,1116,1078,1037,1009,997,984,960,932,909,888,866,846,831,815,789,761,742,732,721,709,
+702,698,683,658,636,625,618,607,599,596,589,569,548,537,528,505,473,448,433,410,375,
+343,321,293,252,217,203,195,166,123,102,119,150,164,161,164,177,182,157,99,21,-55,
+-110,-139,-156,-177,-202,-220,-233,-253,-283,-312,-335,-359,-392,-427,-455,-474,-493,-514,-530,-537,-538,
+-542,-559,-586,-613,-634,-656,-687,-726,-759,-775,-786,-807,-839,-869,-887,-897,-904,-915,-928,-946,-964,
+-975,-976,-975,-980,-989,-997,-999,-996,-994,-994,-994,-991,-987,-983,-983,-986,-986,-978,-969,-961,-957,
+-953,-951,-955,-961,-963,-958,-951,-947,-947,-948,-947,-941,-934,-927,-924,-921,-914,-903,-895,-893,-891,
+-884,-876,-871,-867,-861,-852,-845,-838,-828,-816,-807,-801,-793,-782,-770,-759,-746,-730,-716,-709,-705,
+-696,-684,-674,-666,-657,-644,-632,-621,-608,-591,-573,-555,-536,-513,-493,-478,-467,-455,-441,-430,-421,
+-412,-401,-392,-383,-374,-368,-366,-364,-359,-353,-349,-348,-347,-344,-342,-344,-345,-343,-342,-343,-346,
+-346,-345,-347,-349,-352,-354,-361,-370,-379,-386,-394,-403,-413,-421,-433,-448,-466,-484,-500,-515,-530,
+-545,-561,-577,-589,-596,-601,-611,-626,-642,-656,-665,-673,-682,-696,-709,-714,-708,-697,-689,-689,-692,
+-695,-696,-694,-689,-685,-688,-697,-705,-705,-700,-697,-697,-699,-700,-700,-701,-703,-708,-715,-718,-716,
+-713,-711,-711,-708,-703,-700,-699,-696,-689,-680,-671,-659,-644,-628,-614,-600,-587,-574,-563,-552,-539,
+-528,-519,-510,-499,-487,-477,-467,-455,-440,-430,-424,-416,-398,-374,-349,-329,-310,-287,-258,-223,-184,
+-146,-107,-65,-21,22,61,102,151,209,270,330,393,462,538,612,681,747,818,894,966,1020,
+1059,1093,1128,1145,1120,1057,1009,1054,1235,1518,1824,2114,2426,2813,3249,3618,3824,3882,3897,3955,4071,
+4216,4362,4483,4557,4582,4584,4588,4597,4607,4621,4639,4651,4663,4696,4739,4720,4565,4292,3993,3725,3463,
+3182,2925,2763,2701,2687,2681,2691,2721,2747,2743,2718,2689,2660,2624,2582,2532,2463,2375,2285,2213,2153,
+2090,2028,1979,1943,1914,1894,1886,1873,1834,1765,1683,1599,1510,1415,1328,1245,1152,1045,940,840,722,
+569,407,279,187,104,12,-71,-132,-176,-217,-259,-301,-353,-418,-481,-529,-557,-570,-568,-558,-562,
+-600,-661,-715,-744,-756,-766,-779,-802,-843,-898,-952,-997,-1052,-1130,-1220,-1289,-1332,-1371,-1428,-1494,-1545,
+-1568,-1567,-1544,-1491,-1411,-1331,-1282,-1272,-1282,-1292,-1301,-1318,-1341,-1356,-1348,-1319,-1278,-1239,-1206,-1180,-1159,
+-1145,-1132,-1110,-1069,-1022,-999,-1015,-1039,-1019,-947,-881,-896,-1003,-1141,-1248,-1307,-1340,-1360,-1364,-1349,-1320,
+-1283,-1242,-1204,-1176,-1154,-1127,-1089,-1050,-1016,-985,-951,-915,-882,-853,-822,-793,-774,-767,-762,-748,-728,
+-710,-701,-699,-701,-708,-717,-724,-724,-718,-713,-713,-717,-720,-720,-719,-718,-716,-709,-699,-690,-682,
+-672,-657,-640,-621,-601,-578,-557,-538,-520,-497,-468,-438,-408,-379,-348,-315,-281,-246,-209,-172,-137,
+-103,-68,-31,7,45,83,121,160,201,242,278,312,348,387,429,468,502,531,562,596,636,
+674,707,736,768,805,843,877,906,931,949,953,949,947,955,971,989,1008,1027,1041,1053,1064,
+1080,1099,1117,1134,1149,1162,1168,1171,1179,1192,1204,1212,1218,1230,1248,1265,1277,1287,1297,1306,1312,
+1311,1306,1307,1318,1334,1339,1330,1317,1315,1324,1334,1337,1336,1335,1332,1329,1326,1326,1327,1325,1323,
+1342,1341,1342,1342,1340,1341,1344,1345,1341,1336,1334,1336,1339,1343,1348,1352,1357,1360,1363,1363,1361,
+1361,1367,1377,1386,1394,1408,1425,1440,1447,1450,1455,1463,1473,1482,1490,1498,1513,1541,1582,1619,1645,
+1675,1726,1793,1860,1926,2005,2097,2165,2187,2194,2239,2333,2424,2461,2441,2397,2351,2300,2245,2194,2149,
+2097,2030,1959,1897,1847,1803,1762,1722,1681,1641,1603,1565,1522,1474,1427,1386,1346,1303,1259,1213,1157,
+1087,1014,957,916,875,826,776,733,692,644,594,555,532,515,494,469,445,420,387,341,288,
+241,208,182,151,111,68,27,-14,-66,-131,-212,-309,-424,-551,-679,-798,-889,-933,-931,-905,-890,
+-898,-927,-967,-1010,-1043,-1063,-1087,-1118,-1128,-1083,-1007,-973,-1026,-1132,-1224,-1277,-1313,-1346,-1371,-1392,-1439,
+-1521,-1614,-1693,-1750,-1783,-1788,-1778,-1788,-1832,-1888,-1931,-1967,-2002,-2015,-2001,-2023,-2147,-2331,-2433,-2371,-2220,
+-2124,-2139,-2213,-2280,-2329,-2371,-2401,-2418,-2445,-2499,-2562,-2604,-2608,-2577,-2511,-2413,-2301,-2197,-2112,-2040,-1979,
+-1935,-1907,-1873,-1804,-1682,-1529,-1406,-1372,-1425,-1490,-1500,-1476,-1506,-1635,-1809,-1942,-2013,-2061,-2117,-2168,-2196,
+-2210,-2223,-2231,-2228,-2225,-2239,-2257,-2253,-2224,-2198,-2196,-2205,-2210,-2211,-2219,-2232,-2243,-2259,-2297,-2348,-2385,
+-2405,-2433,-2490,-2564,-2640,-2715,-2773,-2751,-2603,-2378,-2207,-2178,-2263,-2375,-2474,-2575,-2680,-2755,-2788,-2810,-2851,
+-2902,-2933,-2948,-2970,-3003,-3029,-3044,-3064,-3094,-3120,-3133,-3144,-3167,-3198,-3229,-3263,-3311,-3370,-3432,-3496,-3566,
+-3638,-3703,-3760,-3813,-3869,-3931,-4000,-4075,-4149,-4214,-4275,-4340,-4415,-4491,-4566,-4645,-4729,-4808,-4873,-4925,-4969,
+-5005,-5037,-5071,-5111,-5149,-5177,-5201,-5231,-5268,-5300,-5326,-5350,-5378,-5404,-5429,-5455,-5484,-5509,-5528,-5551,-5580,
+-5607,-5627,-5647,-5674,-5704,-5727,-5747,-5771,-5799,-5820,-5830,-5839,-5860,-5891,-5926,-5960,-5991,-6015,-6036,-6060,-6090,
+-6116,-6129,-6132,-6129,-6115,-6074,-6005,-5925,-5847,-5775,-5709,-5661,-5649,-5671,-5696,-5687,-5643,-5617,-5669,-5801,-5940,
+-6002,-5965,-5871,-5777,-5715,-5697,-5716,-5748,-5751,-5700,-5617,-5546,-5510,-5491,-5456,-5393,-5317,-5262,-5249,-5265,-5253,
+-5166,-5011,-4858,-4777,-4778,-4812,-4809,-4733,-4601,-4473,-4398,-4378,-4373,-4354,-4328,-4310,-4284,-4227,-4147,-4083,-4048,
+-4016,-3959,-3882,-3810,-3752,-3692,-3621,-3546,-3474,-3407,-3344,-3291,-3249,-3219,-3193,-3169,-3140,-3101,-3052,-2991,-2919,
+-2836,-2748,-2657,-2561,-2464,-2377,-2307,-2243,-2167,-2077,-1991,-1916,-1837,-1744,-1649,-1576,-1527,-1488,-1457,-1433,-1406,
+-1361,-1302,-1250,-1206,-1143,-1036,-908,-802,-731,-672,-601,-519,-444,-379,-319,-264,-223,-198,-175,-131,-62,
+14,80,130,181,240,301,353,403,470,558,644,711,769,851,977,1132,1285,1419,1543,1680,1834,
+1990,2132,2260,2379,2484,2563,2619,2674,2742,2813,2872,2918,2967,3023,3075,3115,3146,3184,3237,3309,3393,
+3476,3541,3584,3620,3661,3706,3739,3753,3747,3726,3698,3678,3683,3722,3785,3853,3908,3946,3973,4004,4050,
+4110,4167,4213,4254,4300,4352,4409,4475,4548,4614,4662,4695,4730,4771,4810,4844,4883,4939,5006,5073,5136,
+5196,5244,5267,5264,5249,5234,5221,5211,5208,5217,5234,5256,5286,5328,5373,5412,5449,5506,5589,5672,5728,
+5764,5816,5901,5997,6071,6125,6187,6270,6350,6399,6420,6442,6482,6521,6526,6474,6379,6283,6227,6231,6278,
+6334,6375,6398,6414,6429,6443,6449,6436,6407,6374,6354,6349,6342,6322,6288,6245,6196,6149,6120,6121,6139,
+6154,6161,6167,6177,6185,6193,6208,6229,6241,6239,6241,6265,6306,6337,6341,6326,6309,6303,6307,6316,6321,
+6327,6350,6391,6424,6417,6369,6321,6307,6327,6352,6361,6348,6311,6251,6176,6110,6077,6083,6111,6137,6150,
+6170,6223,6302,6362,6361,6301,6209,6107,6002,5902,5798,5666,5512,5430,5532,5812,6097,6214,6168,6124,6201,
+6356,6467,6492,6483,6496,6526,6538,6523,6493,6464,6442,6427,6411,6382,6341,6298,6259,6217,6169,6123,6089,
+6063,6031,5991,5947,5905,5867,5834,5801,5760,5710,5660,5619,5583,5544,5500,5456,5412,5361,5305,5254,5217,
+5185,5147,5105,5063,5018,4964,4912,4877,4855,4828,4784,4737,4699,4668,4635,4604,4579,4551,4505,4451,4413,
+4396,4371,4313,4239,4191,4180,4162,4089,3957,3797,3619,3380,3047,2679,2414,2366,2505,2692,2804,2834,2848,
+2869,2859,2786,2683,2600,2538,2458,2350,2252,2191,2146,2079,1989,1902,1834,1777,1722,1673,1631,1589,1543,
+1501,1463,1421,1374,1337,1318,1308,1289,1260,1232,1208,1182,1150,1118,1085,1050,1018,998,988,976,957,
+936,919,900,875,854,839,823,796,766,745,730,717,708,708,708,689,655,630,623,623,616,
+606,600,594,582,572,570,563,533,489,451,427,402,370,344,328,309,276,241,220,200,166,
+124,97,91,96,104,128,169,208,221,200,154,90,17,-50,-103,-142,-177,-206,-228,-248,-276,
+-310,-338,-354,-370,-395,-426,-457,-485,-509,-524,-526,-521,-519,-528,-548,-573,-597,-617,-639,-672,-715,
+-753,-778,-795,-822,-858,-892,-912,-921,-930,-942,-959,-977,-993,-999,-993,-987,-990,-1001,-1011,-1014,-1012,
+-1010,-1011,-1011,-1009,-1002,-996,-995,-996,-995,-988,-977,-969,-962,-956,-953,-955,-961,-963,-959,-953,-949,
+-948,-949,-948,-942,-934,-927,-925,-924,-916,-904,-894,-890,-887,-878,-867,-860,-856,-850,-840,-832,-826,
+-817,-805,-796,-789,-781,-769,-758,-749,-737,-722,-708,-699,-692,-681,-667,-656,-646,-634,-619,-607,-597,
+-585,-570,-555,-540,-523,-501,-482,-468,-457,-446,-434,-423,-412,-399,-388,-380,-372,-362,-354,-351,-350,
+-345,-335,-330,-329,-330,-328,-329,-332,-333,-329,-326,-328,-332,-333,-333,-335,-338,-338,-338,-342,-349,
+-357,-365,-375,-386,-394,-400,-409,-427,-450,-471,-487,-498,-506,-514,-526,-543,-563,-578,-586,-593,-604,
+-618,-632,-642,-649,-656,-665,-675,-679,-674,-665,-660,-659,-661,-666,-670,-673,-672,-670,-672,-680,-688,
+-689,-683,-678,-675,-676,-676,-677,-677,-680,-688,-697,-700,-698,-696,-697,-699,-695,-688,-685,-686,-686,
+-681,-673,-663,-652,-637,-621,-606,-591,-576,-562,-551,-541,-530,-518,-508,-497,-485,-473,-463,-454,-443,
+-430,-418,-408,-397,-380,-358,-334,-311,-289,-266,-239,-208,-172,-135,-96,-52,-7,35,75,116,165,
+224,288,350,410,476,549,625,695,760,829,907,985,1046,1088,1123,1165,1205,1216,1177,1103,1056,
+1106,1278,1545,1862,2220,2622,3037,3387,3618,3749,3845,3955,4084,4224,4363,4479,4549,4574,4582,4592,4605,
+4623,4653,4681,4681,4657,4658,4705,4734,4654,4452,4189,3912,3610,3293,3028,2872,2797,2729,2653,2611,2624,
+2650,2649,2625,2608,2604,2602,2595,2574,2531,2465,2392,2320,2240,2148,2064,2015,1998,1985,1964,1939,1911,
+1866,1798,1720,1640,1552,1457,1360,1263,1153,1030,910,797,678,545,416,317,238,154,62,-15,-66,
+-103,-145,-195,-254,-321,-387,-435,-462,-478,-494,-500,-494,-498,-534,-593,-646,-679,-701,-723,-747,-782,
+-843,-923,-993,-1040,-1084,-1152,-1233,-1292,-1323,-1354,-1408,-1470,-1505,-1503,-1480,-1454,-1418,-1364,-1303,-1263,-1259,
+-1275,-1285,-1285,-1294,-1323,-1354,-1360,-1330,-1278,-1221,-1165,-1111,-1064,-1032,-1017,-1008,-995,-989,-1010,-1057,-1089,
+-1056,-956,-857,-842,-938,-1095,-1236,-1325,-1369,-1388,-1389,-1371,-1336,-1289,-1239,-1194,-1161,-1134,-1102,-1063,-1024,
+-994,-969,-941,-910,-881,-853,-827,-803,-788,-778,-766,-747,-727,-713,-705,-698,-692,-695,-705,-715,-717,
+-714,-714,-720,-725,-726,-725,-727,-731,-732,-727,-720,-714,-709,-700,-686,-669,-648,-622,-594,-569,-549,
+-531,-509,-482,-452,-422,-392,-360,-327,-293,-259,-225,-190,-155,-119,-83,-46,-7,32,70,106,144,
+187,230,269,304,341,381,423,462,498,532,565,598,632,667,698,726,755,790,830,870,904,
+931,948,953,951,951,958,972,989,1006,1024,1040,1053,1066,1081,1097,1112,1126,1138,1150,1163,1177,
+1191,1200,1203,1207,1220,1239,1254,1261,1266,1275,1289,1301,1305,1304,1304,1310,1326,1343,1349,1341,1329,
+1329,1340,1351,1354,1351,1347,1344,1340,1338,1340,1343,1344,1342,1360,1358,1357,1357,1356,1357,1360,1362,
+1361,1359,1359,1358,1359,1362,1367,1373,1376,1378,1381,1383,1383,1383,1386,1392,1397,1403,1413,1426,1436,
+1439,1444,1453,1464,1472,1479,1491,1507,1529,1557,1592,1623,1649,1682,1744,1831,1921,2006,2095,2188,2258,
+2281,2281,2310,2383,2457,2481,2447,2382,2312,2248,2194,2153,2118,2074,2016,1954,1900,1853,1809,1769,1731,
+1692,1652,1615,1579,1539,1493,1450,1411,1372,1329,1284,1239,1187,1121,1052,997,959,921,874,822,775,
+730,680,631,595,573,555,537,520,508,496,466,412,344,282,237,202,163,121,84,55,27,
+-11,-65,-144,-254,-387,-521,-641,-751,-851,-918,-930,-898,-861,-852,-871,-902,-933,-965,-1010,-1074,-1142,
+-1175,-1146,-1083,-1049,-1073,-1120,-1143,-1144,-1161,-1202,-1242,-1273,-1323,-1409,-1515,-1609,-1677,-1716,-1723,-1713,-1721,
+-1765,-1827,-1880,-1917,-1935,-1927,-1909,-1948,-2091,-2280,-2378,-2320,-2187,-2103,-2111,-2165,-2221,-2281,-2345,-2389,-2400,
+-2400,-2423,-2467,-2510,-2525,-2496,-2414,-2290,-2160,-2054,-1975,-1912,-1865,-1839,-1821,-1790,-1727,-1623,-1488,-1358,-1293,
+-1326,-1412,-1469,-1472,-1483,-1572,-1724,-1866,-1955,-2010,-2059,-2103,-2132,-2152,-2171,-2183,-2180,-2175,-2186,-2201,-2191,
+-2152,-2119,-2118,-2136,-2148,-2152,-2164,-2183,-2199,-2217,-2253,-2303,-2341,-2358,-2381,-2435,-2510,-2582,-2638,-2660,-2609,
+-2461,-2269,-2135,-2119,-2187,-2274,-2365,-2477,-2596,-2678,-2709,-2727,-2764,-2809,-2839,-2861,-2891,-2924,-2944,-2955,-2976,
+-3010,-3037,-3048,-3059,-3083,-3114,-3140,-3168,-3212,-3269,-3330,-3394,-3466,-3541,-3606,-3658,-3708,-3763,-3826,-3897,-3973,
+-4048,-4115,-4175,-4241,-4317,-4396,-4473,-4550,-4630,-4707,-4772,-4824,-4866,-4902,-4937,-4976,-5020,-5056,-5080,-5100,-5130,
+-5167,-5200,-5223,-5245,-5271,-5296,-5321,-5347,-5375,-5402,-5427,-5454,-5484,-5508,-5526,-5549,-5581,-5613,-5638,-5658,-5684,
+-5712,-5733,-5745,-5760,-5789,-5828,-5871,-5912,-5944,-5964,-5980,-6002,-6031,-6050,-6052,-6048,-6052,-6053,-6029,-5974,-5904,
+-5837,-5775,-5713,-5660,-5630,-5629,-5637,-5626,-5591,-5575,-5632,-5765,-5903,-5957,-5900,-5790,-5702,-5667,-5674,-5697,-5715,
+-5709,-5665,-5595,-5528,-5488,-5467,-5441,-5390,-5323,-5271,-5257,-5262,-5233,-5128,-4973,-4849,-4813,-4851,-4890,-4862,-4753,
+-4610,-4499,-4452,-4448,-4442,-4414,-4381,-4355,-4323,-4265,-4192,-4133,-4093,-4049,-3986,-3919,-3864,-3815,-3757,-3687,-3620,
+-3559,-3500,-3442,-3391,-3352,-3322,-3294,-3261,-3218,-3164,-3105,-3046,-2984,-2910,-2829,-2749,-2670,-2587,-2498,-2413,-2333,
+-2255,-2173,-2094,-2016,-1934,-1846,-1766,-1704,-1651,-1599,-1556,-1530,-1508,-1463,-1396,-1333,-1283,-1219,-1116,-990,-887,
+-831,-803,-772,-723,-662,-595,-522,-447,-377,-319,-268,-213,-148,-78,-17,32,80,135,194,248,301,
+369,454,538,605,671,766,903,1062,1211,1343,1476,1630,1802,1973,2123,2248,2353,2439,2507,2561,2614,
+2677,2745,2804,2851,2893,2936,2979,3022,3070,3126,3191,3268,3351,3431,3495,3541,3578,3611,3636,3648,3653,
+3657,3653,3633,3606,3598,3627,3684,3747,3799,3835,3864,3897,3945,4007,4069,4117,4153,4185,4223,4274,4341,
+4420,4495,4551,4595,4640,4687,4727,4761,4802,4861,4929,4995,5059,5122,5175,5199,5195,5179,5168,5160,5155,
+5155,5167,5188,5210,5236,5271,5315,5356,5395,5446,5516,5589,5646,5694,5760,5851,5943,6008,6056,6120,6213,
+6306,6362,6382,6396,6429,6469,6483,6442,6351,6246,6177,6173,6223,6289,6340,6370,6390,6410,6428,6438,6433,
+6417,6399,6393,6397,6400,6394,6374,6339,6289,6229,6183,6164,6161,6155,6138,6125,6127,6137,6149,6163,6181,
+6195,6199,6205,6230,6269,6301,6308,6291,6270,6261,6270,6287,6299,6305,6315,6334,6346,6332,6295,6262,6254,
+6269,6289,6304,6300,6262,6186,6100,6044,6034,6054,6079,6101,6131,6180,6245,6301,6321,6294,6235,6165,6091,
+6005,5910,5808,5692,5573,5530,5658,5952,6251,6375,6309,6214,6243,6384,6512,6547,6523,6511,6531,6554,6551,
+6525,6494,6471,6457,6442,6415,6377,6333,6289,6244,6198,6157,6122,6092,6060,6025,5987,5947,5905,5865,5829,
+5793,5751,5710,5674,5634,5584,5528,5480,5441,5397,5342,5291,5254,5225,5187,5141,5094,5048,4997,4945,4902,
+4871,4838,4796,4759,4736,4717,4682,4638,4606,4584,4550,4496,4447,4426,4417,4386,4328,4277,4250,4221,4153,
+4053,3963,3882,3728,3409,2944,2500,2272,2318,2523,2717,2818,2848,2848,2816,2737,2634,2547,2480,2405,2312,
+2229,2173,2124,2056,1972,1896,1833,1773,1716,1670,1635,1595,1546,1497,1458,1419,1376,1339,1316,1299,1272,
+1238,1211,1194,1176,1146,1109,1073,1041,1016,1003,995,983,963,944,928,911,888,867,850,830,801,
+771,748,730,714,706,711,714,695,661,638,636,639,631,620,616,615,610,607,610,603,566,
+508,455,417,387,358,339,332,321,297,268,246,224,195,162,135,106,72,52,72,123,165,
+173,158,141,120,78,13,-57,-119,-167,-200,-223,-247,-283,-327,-365,-392,-412,-434,-458,-483,-507,
+-526,-530,-520,-510,-511,-522,-538,-557,-577,-598,-621,-654,-699,-744,-777,-801,-830,-867,-901,-921,-931,
+-941,-955,-973,-993,-1010,-1018,-1013,-1006,-1006,-1014,-1022,-1027,-1029,-1030,-1030,-1028,-1023,-1016,-1010,-1007,-1005,
+-1001,-993,-983,-974,-967,-961,-957,-957,-960,-962,-959,-954,-950,-948,-947,-945,-941,-933,-927,-925,-924,
+-917,-906,-896,-891,-886,-876,-864,-855,-849,-840,-828,-819,-813,-805,-795,-785,-777,-767,-755,-744,-735,
+-726,-714,-702,-693,-684,-671,-657,-644,-631,-616,-600,-585,-573,-559,-544,-532,-520,-504,-485,-468,-455,
+-445,-433,-422,-412,-399,-384,-373,-366,-359,-349,-340,-337,-337,-331,-321,-314,-313,-314,-314,-315,-319,
+-321,-318,-314,-315,-318,-321,-322,-324,-328,-328,-327,-327,-331,-337,-345,-358,-371,-380,-385,-396,-417,
+-439,-455,-460,-462,-463,-468,-479,-500,-528,-554,-569,-577,-585,-595,-607,-616,-622,-628,-633,-638,-639,
+-636,-632,-630,-632,-635,-638,-642,-646,-648,-648,-652,-658,-664,-667,-665,-660,-657,-656,-657,-659,-660,
+-663,-670,-679,-683,-682,-681,-684,-686,-683,-675,-671,-673,-674,-670,-662,-652,-640,-625,-610,-596,-583,
+-569,-554,-541,-531,-520,-507,-494,-480,-466,-454,-445,-439,-430,-418,-401,-384,-368,-351,-333,-313,-291,
+-267,-242,-215,-185,-151,-116,-80,-42,-1,41,85,131,184,244,309,372,432,493,559,630,700,
+766,834,907,983,1051,1107,1156,1205,1255,1291,1290,1235,1147,1086,1124,1295,1589,1966,2376,2763,3090,
+3350,3571,3768,3935,4065,4179,4299,4416,4502,4548,4575,4596,4609,4625,4658,4694,4689,4635,4589,4600,4636,
+4623,4528,4368,4143,3832,3472,3172,3004,2920,2823,2692,2591,2559,2562,2550,2528,2527,2556,2592,2618,2622,
+2597,2545,2482,2411,2320,2207,2107,2060,2060,2063,2041,2000,1954,1902,1836,1760,1677,1589,1494,1393,1281,
+1154,1021,896,785,674,557,450,368,294,209,119,48,4,-31,-78,-139,-210,-283,-342,-376,-392,
+-415,-449,-473,-476,-479,-507,-556,-599,-629,-656,-686,-718,-761,-837,-939,-1031,-1087,-1122,-1168,-1224,-1268,
+-1292,-1320,-1369,-1421,-1442,-1425,-1394,-1371,-1352,-1320,-1278,-1250,-1254,-1277,-1289,-1285,-1285,-1311,-1349,-1361,-1331,
+-1271,-1203,-1138,-1071,-1008,-959,-932,-926,-936,-966,-1017,-1075,-1103,-1061,-955,-846,-813,-893,-1048,-1206,-1318,
+-1379,-1403,-1400,-1373,-1330,-1280,-1230,-1182,-1139,-1097,-1057,-1019,-988,-964,-944,-920,-895,-871,-849,-828,-810,
+-795,-782,-765,-744,-729,-720,-712,-699,-687,-686,-696,-706,-709,-708,-713,-721,-727,-726,-726,-732,-740,
+-744,-741,-737,-734,-731,-724,-712,-696,-674,-646,-616,-590,-568,-547,-523,-497,-467,-435,-402,-369,-335,
+-302,-270,-240,-208,-172,-134,-97,-59,-19,24,65,102,140,182,227,269,306,344,383,421,457,
+494,532,569,601,631,663,696,725,752,782,820,861,898,927,946,955,956,954,956,964,979,
+996,1015,1033,1050,1065,1079,1093,1105,1116,1125,1135,1152,1175,1193,1199,1198,1208,1234,1260,1269,1263,
+1265,1285,1307,1312,1302,1290,1289,1300,1316,1330,1336,1333,1328,1330,1341,1353,1358,1356,1354,1352,1350,
+1351,1355,1360,1362,1360,1376,1375,1375,1373,1370,1371,1375,1380,1382,1383,1382,1380,1377,1380,1386,1392,
+1394,1394,1398,1402,1404,1403,1405,1410,1414,1419,1427,1435,1438,1439,1445,1457,1467,1470,1474,1488,1511,
+1535,1559,1587,1617,1649,1695,1773,1879,1989,2085,2172,2256,2322,2352,2357,2372,2412,2454,2462,2425,2358,
+2283,2214,2165,2134,2106,2064,2008,1952,1903,1859,1816,1776,1741,1706,1669,1633,1597,1557,1515,1475,1440,
+1403,1359,1312,1266,1216,1154,1089,1035,994,955,908,859,812,767,720,677,646,626,608,591,580,
+573,555,514,449,376,314,266,223,174,128,99,87,75,44,-16,-116,-253,-401,-527,-620,-705,
+-805,-898,-940,-917,-869,-842,-845,-860,-875,-904,-969,-1066,-1160,-1204,-1183,-1133,-1110,-1121,-1119,-1068,-1005,
+-993,-1044,-1117,-1179,-1243,-1333,-1442,-1543,-1618,-1661,-1670,-1660,-1662,-1699,-1761,-1819,-1849,-1844,-1811,-1795,-1864,
+-2039,-2236,-2326,-2267,-2145,-2073,-2080,-2125,-2181,-2252,-2326,-2366,-2350,-2303,-2267,-2262,-2279,-2295,-2282,-2219,-2116,
+-2009,-1927,-1869,-1825,-1795,-1780,-1758,-1707,-1628,-1528,-1409,-1285,-1212,-1242,-1351,-1444,-1463,-1457,-1515,-1655,-1806,
+-1905,-1957,-1998,-2037,-2067,-2088,-2111,-2127,-2126,-2120,-2126,-2136,-2122,-2081,-2047,-2049,-2072,-2087,-2093,-2108,-2136,
+-2159,-2176,-2203,-2243,-2278,-2298,-2323,-2373,-2435,-2480,-2495,-2479,-2418,-2300,-2160,-2066,-2056,-2107,-2184,-2283,-2410,
+-2533,-2606,-2627,-2641,-2680,-2726,-2759,-2785,-2817,-2846,-2856,-2858,-2877,-2911,-2938,-2950,-2967,-2999,-3033,-3056,-3079,
+-3120,-3177,-3237,-3300,-3371,-3443,-3503,-3551,-3599,-3659,-3727,-3799,-3874,-3948,-4015,-4076,-4142,-4220,-4301,-4377,-4451,
+-4526,-4597,-4660,-4711,-4753,-4790,-4827,-4869,-4912,-4947,-4971,-4994,-5027,-5068,-5105,-5131,-5153,-5176,-5199,-5221,-5244,
+-5271,-5299,-5329,-5360,-5389,-5410,-5427,-5452,-5488,-5523,-5549,-5572,-5600,-5629,-5647,-5660,-5682,-5721,-5771,-5822,-5867,
+-5898,-5914,-5926,-5946,-5973,-5989,-5986,-5982,-5991,-5999,-5984,-5940,-5887,-5837,-5791,-5740,-5685,-5639,-5612,-5596,-5574,
+-5541,-5529,-5586,-5718,-5855,-5905,-5843,-5734,-5665,-5658,-5679,-5690,-5685,-5668,-5630,-5569,-5504,-5457,-5436,-5417,-5380,
+-5325,-5278,-5256,-5239,-5184,-5070,-4935,-4856,-4866,-4925,-4950,-4885,-4750,-4609,-4525,-4505,-4512,-4500,-4462,-4419,-4384,
+-4345,-4291,-4231,-4177,-4126,-4065,-4001,-3954,-3925,-3889,-3831,-3760,-3695,-3639,-3584,-3528,-3480,-3444,-3412,-3378,-3337,
+-3285,-3222,-3157,-3097,-3037,-2967,-2891,-2821,-2756,-2685,-2598,-2506,-2421,-2343,-2264,-2182,-2099,-2014,-1932,-1863,-1809,
+-1758,-1705,-1658,-1629,-1605,-1559,-1489,-1417,-1357,-1288,-1188,-1068,-967,-913,-897,-888,-864,-820,-760,-688,-610,
+-527,-447,-376,-314,-253,-187,-121,-66,-18,30,86,144,205,273,348,418,484,568,693,851,1012,
+1154,1287,1435,1606,1788,1959,2104,2219,2308,2376,2431,2481,2532,2590,2656,2722,2779,2822,2856,2891,2937,
+2997,3065,3139,3221,3306,3384,3443,3484,3518,3546,3561,3563,3566,3576,3582,3569,3545,3534,3553,3596,3647,
+3696,3737,3769,3801,3842,3898,3961,4017,4060,4093,4127,4171,4233,4307,4379,4442,4499,4559,4616,4659,4691,
+4731,4787,4851,4912,4972,5036,5090,5115,5112,5099,5097,5102,5108,5113,5127,5149,5174,5202,5238,5280,5319,
+5353,5394,5450,5513,5571,5629,5703,5796,5885,5949,5997,6063,6160,6258,6320,6342,6352,6376,6410,6426,6396,
+6316,6213,6134,6115,6157,6226,6285,6325,6354,6379,6397,6406,6406,6406,6411,6422,6432,6437,6433,6423,6403,
+6368,6319,6274,6246,6226,6194,6147,6106,6090,6098,6112,6125,6138,6149,6156,6167,6194,6234,6267,6273,6256,
+6232,6224,6236,6260,6282,6291,6292,6288,6278,6257,6233,6220,6222,6231,6239,6247,6243,6208,6136,6058,6015,
+6014,6029,6042,6062,6101,6149,6180,6174,6137,6093,6066,6061,6061,6041,5998,5940,5867,5782,5736,5815,6039,
+6298,6426,6377,6272,6267,6384,6518,6573,6558,6539,6552,6573,6574,6555,6531,6510,6489,6465,6436,6400,6360,
+6316,6273,6234,6198,6160,6120,6083,6052,6023,5986,5942,5899,5864,5832,5796,5758,5718,5673,5617,5560,5514,
+5480,5442,5392,5343,5305,5270,5223,5166,5114,5074,5035,4992,4948,4908,4864,4817,4780,4764,4750,4715,4664,
+4623,4603,4581,4538,4492,4470,4463,4441,4390,4335,4298,4264,4207,4133,4080,4050,3961,3695,3222,2678,2289,
+2199,2362,2601,2770,2840,2849,2822,2756,2660,2565,2484,2405,2319,2238,2173,2114,2044,1965,1892,1827,1762,
+1704,1665,1640,1605,1551,1494,1448,1410,1371,1335,1309,1285,1253,1217,1194,1185,1174,1146,1108,1071,1043,
+1025,1017,1011,997,973,950,932,915,897,878,860,835,804,774,751,729,707,696,700,705,694,
+671,659,660,657,641,630,634,641,638,631,628,616,579,519,463,421,389,362,348,343,333,
+311,285,265,244,220,197,175,138,81,35,34,63,76,57,40,59,100,115,78,7,-66,
+-123,-160,-185,-214,-260,-320,-380,-429,-464,-486,-499,-509,-520,-527,-523,-512,-508,-516,-526,-532,-540,
+-558,-582,-608,-640,-685,-735,-776,-804,-831,-862,-892,-912,-925,-938,-954,-972,-993,-1013,-1027,-1030,-1028,
+-1027,-1030,-1034,-1040,-1045,-1048,-1046,-1039,-1033,-1029,-1025,-1021,-1015,-1009,-999,-988,-977,-971,-966,-962,-960,
+-961,-961,-958,-955,-952,-949,-947,-944,-940,-934,-928,-925,-921,-914,-905,-897,-892,-886,-876,-865,-857,
+-848,-835,-821,-810,-803,-795,-786,-776,-766,-754,-740,-728,-718,-709,-699,-691,-683,-674,-661,-646,-633,
+-620,-605,-589,-572,-555,-537,-523,-512,-501,-484,-465,-449,-438,-428,-416,-406,-397,-385,-369,-356,-349,
+-343,-333,-324,-323,-324,-319,-309,-302,-301,-301,-300,-300,-304,-308,-307,-303,-302,-304,-307,-309,-312,
+-317,-319,-319,-320,-322,-325,-331,-343,-357,-367,-375,-390,-409,-424,-426,-422,-421,-428,-440,-455,-476,
+-502,-527,-544,-555,-563,-572,-581,-589,-595,-601,-605,-607,-606,-604,-604,-608,-613,-616,-617,-619,-620,
+-622,-625,-629,-635,-640,-644,-646,-645,-643,-643,-646,-651,-654,-655,-657,-664,-669,-670,-669,-670,-673,
+-671,-665,-660,-660,-661,-658,-650,-639,-626,-610,-594,-582,-573,-563,-548,-533,-518,-504,-490,-476,-460,
+-446,-436,-428,-422,-412,-398,-378,-357,-339,-323,-309,-292,-273,-250,-225,-197,-164,-128,-93,-60,-28,
+6,48,96,149,204,263,326,389,449,507,566,628,695,763,833,903,973,1042,1112,1183,1246,
+1300,1346,1375,1361,1288,1181,1111,1154,1343,1653,2020,2383,2717,3039,3363,3662,3885,4019,4111,4215,4331,
+4424,4483,4529,4569,4590,4599,4618,4647,4646,4597,4542,4533,4560,4579,4569,4519,4377,4086,3687,3330,3128,
+3037,2935,2778,2628,2542,2503,2471,2447,2453,2490,2534,2571,2592,2588,2556,2507,2448,2368,2264,2166,2118,
+2120,2129,2108,2057,1999,1941,1875,1795,1705,1611,1517,1416,1298,1162,1025,904,798,691,581,485,413,
+343,258,168,99,57,21,-27,-92,-166,-236,-286,-310,-330,-371,-429,-471,-481,-482,-500,-531,-557,
+-578,-611,-654,-695,-741,-818,-927,-1035,-1103,-1137,-1164,-1196,-1226,-1248,-1276,-1316,-1354,-1370,-1361,-1345,-1335,
+-1329,-1313,-1288,-1271,-1278,-1299,-1307,-1296,-1287,-1304,-1334,-1343,-1310,-1251,-1190,-1131,-1070,-1003,-943,-903,-891,
+-909,-951,-1004,-1049,-1064,-1031,-955,-872,-835,-880,-995,-1133,-1254,-1342,-1392,-1399,-1366,-1311,-1258,-1215,-1170,
+-1115,-1058,-1009,-974,-949,-929,-910,-891,-874,-858,-843,-827,-811,-797,-780,-761,-744,-734,-729,-721,-705,
+-690,-685,-690,-697,-698,-699,-705,-713,-718,-719,-722,-729,-738,-742,-742,-741,-740,-737,-732,-724,-710,
+-688,-661,-632,-606,-582,-558,-532,-504,-472,-436,-400,-365,-333,-301,-272,-243,-212,-176,-137,-99,-62,
+-21,23,67,105,143,185,231,275,314,352,390,426,460,496,536,574,605,634,666,701,732,
+756,781,814,853,890,918,938,952,956,954,951,955,969,990,1011,1031,1049,1065,1078,1090,1102,
+1112,1118,1124,1139,1163,1182,1186,1190,1213,1254,1284,1283,1271,1283,1326,1362,1357,1320,1286,1279,1291,
+1305,1314,1319,1320,1320,1323,1331,1343,1353,1357,1359,1359,1361,1364,1370,1375,1376,1376,1391,1394,1396,
+1395,1391,1391,1395,1400,1402,1403,1401,1397,1395,1397,1404,1410,1411,1411,1415,1420,1422,1423,1426,1433,
+1439,1443,1448,1452,1452,1451,1456,1467,1474,1473,1474,1489,1513,1536,1555,1580,1614,1657,1717,1807,1926,
+2048,2147,2219,2280,2332,2366,2382,2396,2418,2438,2436,2406,2349,2278,2210,2161,2134,2109,2067,2010,1954,
+1909,1867,1826,1786,1752,1720,1687,1654,1619,1579,1537,1498,1464,1429,1386,1339,1290,1239,1180,1119,1066,
+1023,982,937,890,845,801,760,727,704,684,664,649,641,629,598,542,474,410,359,316,268,
+214,166,142,139,131,91,6,-120,-272,-415,-517,-578,-641,-744,-867,-949,-958,-919,-878,-858,-847,
+-844,-867,-939,-1050,-1156,-1208,-1197,-1166,-1159,-1168,-1135,-1036,-926,-888,-943,-1040,-1127,-1203,-1294,-1400,-1499,
+-1570,-1608,-1616,-1607,-1605,-1630,-1679,-1723,-1737,-1713,-1673,-1677,-1787,-1995,-2198,-2277,-2211,-2094,-2030,-2041,-2090,
+-2150,-2219,-2277,-2286,-2231,-2140,-2057,-2009,-1998,-2011,-2018,-1992,-1933,-1871,-1827,-1794,-1765,-1741,-1719,-1675,-1590,
+-1482,-1375,-1271,-1171,-1121,-1174,-1305,-1415,-1439,-1428,-1483,-1623,-1773,-1863,-1903,-1939,-1980,-2011,-2025,-2039,-2053,
+-2055,-2050,-2052,-2062,-2053,-2020,-1990,-1991,-2011,-2025,-2032,-2051,-2085,-2113,-2125,-2138,-2167,-2199,-2225,-2254,-2296,
+-2329,-2323,-2279,-2224,-2173,-2114,-2050,-2008,-2011,-2055,-2131,-2241,-2374,-2487,-2538,-2543,-2556,-2600,-2653,-2687,-2710,
+-2738,-2759,-2761,-2757,-2772,-2804,-2831,-2848,-2873,-2913,-2950,-2973,-2995,-3035,-3090,-3148,-3208,-3275,-3343,-3397,-3440,
+-3492,-3558,-3633,-3708,-3782,-3854,-3920,-3980,-4046,-4122,-4201,-4275,-4344,-4413,-4480,-4540,-4593,-4639,-4678,-4715,-4753,
+-4793,-4827,-4855,-4884,-4923,-4969,-5011,-5043,-5066,-5086,-5103,-5119,-5140,-5167,-5198,-5230,-5264,-5291,-5310,-5327,-5355,
+-5393,-5429,-5457,-5484,-5517,-5547,-5564,-5576,-5604,-5654,-5716,-5775,-5821,-5850,-5863,-5873,-5893,-5918,-5933,-5934,-5937,
+-5950,-5957,-5939,-5901,-5863,-5835,-5808,-5769,-5717,-5660,-5608,-5565,-5524,-5485,-5473,-5532,-5665,-5804,-5853,-5793,-5698,
+-5652,-5664,-5684,-5675,-5648,-5621,-5587,-5530,-5462,-5411,-5389,-5374,-5346,-5304,-5266,-5238,-5199,-5123,-5015,-4921,-4895,
+-4939,-4993,-4984,-4884,-4738,-4618,-4566,-4565,-4569,-4546,-4498,-4449,-4405,-4361,-4315,-4269,-4222,-4159,-4083,-4020,-3994,
+-3990,-3967,-3908,-3835,-3772,-3717,-3660,-3602,-3554,-3518,-3484,-3444,-3397,-3341,-3276,-3209,-3147,-3086,-3017,-2944,-2879,
+-2822,-2756,-2674,-2588,-2509,-2437,-2359,-2273,-2186,-2102,-2023,-1956,-1902,-1855,-1805,-1757,-1720,-1685,-1635,-1567,-1492,
+-1422,-1346,-1251,-1143,-1048,-984,-952,-934,-910,-872,-823,-772,-720,-657,-582,-509,-447,-390,-325,-252,-186,
+-134,-86,-30,35,108,181,248,309,379,488,645,823,985,1119,1253,1412,1592,1771,1929,2060,2163,
+2238,2292,2339,2388,2441,2497,2561,2632,2698,2747,2779,2812,2860,2924,2996,3077,3168,3264,3346,3399,3430,
+3454,3477,3493,3500,3505,3513,3514,3499,3477,3467,3478,3507,3547,3596,3646,3688,3720,3751,3796,3857,3921,
+3977,4022,4059,4097,4146,4206,4269,4331,4397,4470,4537,4586,4622,4662,4716,4772,4823,4873,4930,4982,5011,
+5015,5013,5023,5043,5061,5074,5089,5112,5143,5180,5221,5260,5291,5318,5352,5401,5459,5515,5573,5645,5734,
+5821,5889,5943,6012,6104,6198,6261,6286,6295,6312,6342,6363,6351,6291,6198,6111,6075,6099,6160,6222,6270,
+6307,6336,6353,6356,6358,6372,6398,6426,6441,6440,6431,6422,6414,6396,6368,6337,6314,6288,6240,6169,6103,
+6070,6074,6094,6114,6126,6132,6132,6138,6159,6192,6218,6221,6208,6200,6209,6234,6262,6281,6285,6274,6253,
+6230,6211,6204,6210,6217,6212,6198,6187,6180,6158,6110,6054,6020,6013,6020,6035,6065,6104,6120,6084,6006,
+5930,5897,5921,5985,6052,6091,6094,6074,6037,5979,5920,5928,6050,6234,6356,6348,6280,6279,6383,6511,6577,
+6577,6569,6581,6598,6596,6581,6565,6548,6522,6488,6456,6424,6387,6345,6306,6275,6245,6207,6159,6116,6082,
+6054,6020,5980,5941,5909,5876,5836,5790,5745,5701,5653,5603,5558,5517,5473,5423,5377,5342,5305,5254,5196,
+5151,5123,5100,5067,5024,4978,4923,4861,4807,4777,4761,4737,4697,4658,4631,4605,4568,4528,4504,4493,4472,
+4431,4385,4351,4323,4279,4217,4154,4101,4014,3795,3381,2841,2375,2172,2261,2496,2702,2809,2844,2840,2793,
+2701,2592,2497,2416,2336,2256,2184,2119,2050,1973,1896,1824,1755,1699,1667,1649,1618,1562,1496,1442,1402,
+1365,1332,1304,1276,1241,1206,1185,1177,1166,1141,1106,1074,1051,1037,1031,1025,1010,985,958,935,917,
+900,883,864,837,805,776,752,728,700,682,681,684,679,672,673,674,658,631,621,637,653,
+646,625,607,590,558,513,474,447,426,409,401,397,378,341,302,273,249,225,206,191,157,
+99,45,25,22,-6,-62,-87,-40,54,123,125,73,4,-55,-97,-130,-166,-219,-291,-367,-432,
+-477,-498,-504,-505,-509,-511,-506,-502,-510,-524,-530,-526,-527,-546,-575,-601,-630,-672,-724,-769,-800,
+-824,-850,-875,-894,-912,-932,-952,-971,-991,-1011,-1029,-1039,-1043,-1045,-1046,-1048,-1053,-1059,-1062,-1056,-1047,
+-1042,-1042,-1041,-1036,-1029,-1022,-1012,-998,-986,-978,-975,-970,-966,-963,-961,-958,-956,-954,-953,-951,-947,
+-942,-937,-932,-926,-919,-911,-904,-898,-892,-885,-876,-866,-857,-846,-833,-819,-807,-798,-789,-779,-768,
+-757,-743,-729,-715,-703,-691,-681,-674,-668,-659,-645,-631,-618,-606,-593,-579,-563,-544,-525,-509,-499,
+-486,-468,-448,-433,-423,-411,-398,-389,-383,-372,-356,-342,-334,-327,-317,-309,-308,-310,-305,-295,-289,
+-288,-288,-284,-283,-287,-292,-292,-289,-289,-291,-294,-297,-303,-308,-312,-315,-317,-320,-321,-325,-332,
+-341,-350,-361,-376,-389,-393,-387,-387,-402,-430,-456,-474,-486,-496,-505,-515,-526,-538,-549,-557,-562,
+-567,-573,-578,-580,-581,-582,-585,-592,-599,-603,-605,-605,-606,-607,-610,-614,-619,-624,-629,-633,-635,
+-635,-636,-642,-650,-654,-651,-648,-651,-657,-659,-658,-657,-658,-658,-654,-650,-648,-648,-644,-636,-624,
+-610,-594,-578,-567,-558,-550,-538,-521,-502,-485,-470,-456,-442,-430,-420,-412,-402,-388,-369,-349,-331,
+-316,-302,-288,-272,-254,-233,-209,-181,-148,-112,-77,-45,-13,20,62,113,168,223,277,334,394,
+454,510,563,619,681,751,827,901,968,1034,1110,1196,1275,1336,1382,1421,1442,1415,1330,1222,1158,
+1199,1362,1621,1934,2281,2665,3073,3449,3722,3880,3982,4088,4201,4288,4348,4410,4481,4533,4552,4563,4582,
+4589,4567,4538,4533,4546,4560,4583,4610,4554,4312,3905,3504,3259,3150,3048,2883,2699,2563,2480,2424,2388,
+2376,2376,2374,2382,2414,2454,2473,2463,2435,2389,2320,2243,2191,2181,2185,2165,2113,2047,1978,1902,1810,
+1709,1611,1522,1428,1314,1181,1049,934,827,715,603,514,451,388,303,211,140,95,58,9,-53,
+-124,-190,-234,-256,-281,-334,-406,-459,-477,-482,-493,-508,-515,-528,-567,-625,-677,-722,-785,-881,-985,
+-1060,-1100,-1125,-1154,-1188,-1221,-1252,-1279,-1302,-1318,-1330,-1337,-1343,-1346,-1345,-1342,-1340,-1344,-1347,-1335,-1310,
+-1292,-1296,-1311,-1307,-1272,-1223,-1179,-1139,-1092,-1034,-975,-929,-908,-917,-950,-983,-1000,-1000,-985,-954,-907,
+-863,-852,-893,-983,-1105,-1239,-1349,-1398,-1374,-1309,-1247,-1202,-1156,-1093,-1024,-971,-938,-915,-894,-876,-864,
+-858,-849,-838,-824,-810,-795,-778,-760,-745,-736,-732,-726,-713,-699,-690,-687,-688,-688,-691,-696,-703,
+-708,-712,-717,-724,-729,-733,-736,-739,-739,-736,-732,-726,-713,-692,-664,-635,-609,-583,-556,-531,-503,
+-469,-429,-389,-354,-323,-294,-265,-236,-204,-167,-127,-89,-54,-15,27,70,109,147,189,236,282,
+322,362,402,440,473,507,545,582,612,639,671,707,736,756,776,807,846,881,905,922,937,
+948,949,947,952,970,994,1016,1035,1052,1067,1078,1089,1102,1114,1120,1122,1133,1153,1171,1177,1185,
+1216,1263,1290,1282,1272,1305,1376,1426,1412,1351,1298,1286,1298,1308,1310,1312,1317,1321,1323,1328,1339,
+1351,1360,1365,1367,1370,1375,1381,1386,1389,1391,1406,1411,1416,1416,1413,1411,1414,1418,1419,1418,1416,
+1415,1415,1417,1422,1427,1429,1430,1433,1436,1439,1441,1448,1457,1463,1466,1469,1472,1474,1473,1476,1483,
+1487,1487,1490,1504,1525,1544,1561,1587,1627,1678,1746,1842,1967,2092,2187,2242,2275,2305,2335,2361,2385,
+2407,2420,2418,2397,2353,2288,2218,2163,2131,2106,2068,2016,1965,1922,1882,1842,1803,1768,1737,1705,1674,
+1641,1602,1558,1514,1476,1441,1402,1359,1311,1257,1198,1140,1091,1049,1009,967,923,878,833,797,773,
+753,730,706,691,684,668,628,569,511,465,431,396,354,304,256,223,200,166,97,-10,-140,
+-265,-362,-421,-459,-520,-633,-777,-894,-939,-923,-882,-846,-822,-815,-844,-922,-1035,-1140,-1196,-1198,-1183,
+-1185,-1193,-1155,-1053,-941,-896,-941,-1028,-1106,-1177,-1264,-1368,-1461,-1521,-1547,-1549,-1543,-1540,-1552,-1573,-1588,
+-1584,-1560,-1545,-1589,-1736,-1959,-2155,-2218,-2145,-2030,-1969,-1984,-2037,-2095,-2143,-2160,-2126,-2043,-1941,-1853,-1796,
+-1776,-1788,-1808,-1809,-1789,-1766,-1752,-1735,-1705,-1665,-1615,-1538,-1422,-1292,-1178,-1089,-1028,-1028,-1120,-1268,-1379,
+-1404,-1404,-1475,-1621,-1758,-1826,-1851,-1886,-1935,-1965,-1967,-1964,-1972,-1977,-1975,-1979,-1991,-1992,-1969,-1943,-1938,
+-1951,-1961,-1970,-1994,-2030,-2055,-2062,-2070,-2095,-2129,-2158,-2189,-2218,-2218,-2155,-2046,-1948,-1906,-1911,-1934,-1961,
+-1998,-2051,-2125,-2228,-2346,-2433,-2459,-2450,-2462,-2513,-2570,-2601,-2617,-2637,-2656,-2661,-2660,-2675,-2705,-2731,-2752,
+-2782,-2824,-2861,-2883,-2907,-2948,-3003,-3058,-3116,-3179,-3240,-3289,-3332,-3387,-3460,-3542,-3620,-3694,-3764,-3828,-3887,
+-3950,-4023,-4098,-4167,-4231,-4294,-4358,-4418,-4474,-4524,-4568,-4604,-4638,-4675,-4711,-4745,-4781,-4824,-4872,-4917,-4952,
+-4975,-4988,-4997,-5008,-5030,-5061,-5095,-5129,-5161,-5188,-5208,-5229,-5260,-5301,-5338,-5367,-5397,-5433,-5464,-5481,-5496,
+-5531,-5592,-5662,-5725,-5770,-5796,-5809,-5820,-5840,-5863,-5878,-5886,-5899,-5915,-5916,-5892,-5857,-5833,-5822,-5810,-5782,
+-5734,-5670,-5598,-5529,-5468,-5418,-5405,-5468,-5608,-5749,-5798,-5740,-5655,-5626,-5648,-5660,-5635,-5598,-5572,-5539,-5479,
+-5407,-5354,-5330,-5313,-5288,-5260,-5238,-5209,-5152,-5066,-4981,-4940,-4964,-5023,-5053,-5002,-4877,-4737,-4646,-4620,-4625,
+-4614,-4576,-4524,-4475,-4429,-4381,-4340,-4307,-4266,-4196,-4109,-4049,-4040,-4052,-4035,-3976,-3903,-3843,-3789,-3729,-3668,
+-3619,-3581,-3542,-3495,-3444,-3387,-3322,-3256,-3195,-3137,-3074,-3006,-2943,-2884,-2818,-2740,-2661,-2592,-2524,-2447,-2361,
+-2277,-2199,-2123,-2051,-1992,-1943,-1897,-1848,-1799,-1751,-1697,-1633,-1559,-1480,-1396,-1308,-1220,-1137,-1063,-999,-943,
+-892,-844,-808,-792,-783,-756,-697,-625,-565,-517,-464,-397,-330,-274,-225,-167,-96,-16,63,139,213,
+304,438,618,807,968,1099,1232,1390,1563,1726,1866,1984,2079,2147,2196,2244,2300,2361,2419,2482,2553,
+2621,2671,2703,2733,2779,2842,2917,3005,3108,3216,3304,3354,3377,3394,3415,3437,3453,3462,3461,3446,3418,
+3391,3381,3389,3411,3447,3503,3567,3621,3655,3680,3715,3770,3838,3904,3960,4001,4034,4069,4111,4160,4215,
+4281,4357,4432,4492,4540,4590,4646,4698,4739,4777,4821,4866,4897,4912,4925,4946,4977,5009,5035,5058,5085,
+5122,5167,5212,5245,5267,5287,5320,5370,5426,5478,5530,5593,5673,5757,5826,5884,5948,6030,6118,6183,6214,
+6228,6246,6277,6309,6318,6283,6205,6116,6061,6062,6104,6158,6208,6253,6288,6304,6304,6306,6327,6365,6402,
+6420,6417,6406,6399,6396,6390,6375,6356,6338,6312,6261,6184,6109,6068,6070,6096,6125,6141,6141,6129,6121,
+6129,6148,6160,6155,6150,6166,6205,6248,6275,6281,6271,6248,6218,6190,6175,6179,6193,6198,6180,6144,6117,
+6110,6110,6093,6056,6016,5995,6003,6043,6102,6139,6109,6007,5883,5802,5799,5861,5953,6041,6095,6107,6094,
+6069,6030,5975,5942,5985,6100,6215,6266,6278,6330,6442,6551,6595,6587,6582,6602,6619,6615,6599,6589,6577,
+6550,6514,6483,6455,6419,6375,6335,6307,6282,6248,6204,6160,6122,6087,6050,6013,5980,5946,5907,5861,5812,
+5769,5731,5692,5647,5597,5543,5487,5435,5396,5370,5343,5304,5263,5236,5222,5201,5158,5102,5045,4986,4916,
+4843,4789,4763,4751,4734,4705,4669,4628,4586,4551,4527,4511,4493,4469,4441,4414,4389,4357,4305,4225,4124,
+3995,3787,3431,2941,2464,2200,2227,2437,2652,2782,2842,2863,2832,2738,2615,2510,2430,2355,2274,2200,2136,
+2068,1988,1903,1823,1754,1703,1674,1657,1628,1572,1503,1443,1400,1365,1332,1303,1273,1239,1205,1182,1171,
+1158,1136,1110,1086,1067,1052,1042,1033,1019,995,968,942,918,897,880,862,836,806,778,754,728,
+700,679,671,668,663,661,667,664,639,607,603,629,650,638,605,575,552,525,497,483,483,
+487,494,508,516,491,428,354,294,251,218,197,183,156,107,57,31,8,-47,-126,-165,-116,
+-9,80,107,81,35,-10,-52,-89,-128,-177,-242,-314,-377,-420,-443,-453,-463,-477,-486,-490,-496,
+-513,-532,-537,-531,-534,-557,-587,-609,-630,-664,-712,-757,-791,-817,-842,-865,-886,-907,-933,-958,-979,
+-999,-1020,-1037,-1048,-1055,-1059,-1061,-1062,-1065,-1070,-1071,-1065,-1057,-1054,-1056,-1055,-1049,-1044,-1040,-1032,-1017,
+-1002,-994,-989,-983,-974,-967,-963,-961,-959,-959,-959,-958,-952,-946,-942,-936,-928,-919,-911,-905,-900,
+-892,-882,-871,-861,-851,-841,-829,-818,-808,-798,-786,-775,-763,-751,-737,-722,-708,-694,-680,-667,-659,
+-651,-641,-627,-612,-599,-588,-577,-565,-550,-533,-515,-500,-488,-473,-454,-436,-423,-411,-398,-384,-375,
+-369,-359,-344,-331,-323,-316,-306,-298,-296,-296,-290,-280,-274,-273,-273,-270,-268,-272,-276,-277,-276,
+-277,-280,-284,-289,-296,-301,-306,-309,-313,-318,-320,-321,-323,-327,-332,-342,-352,-358,-357,-357,-375,
+-413,-458,-490,-504,-504,-497,-490,-489,-498,-514,-528,-536,-538,-540,-544,-549,-554,-560,-566,-573,-581,
+-588,-594,-598,-602,-604,-606,-607,-610,-614,-618,-623,-626,-628,-629,-631,-638,-646,-649,-645,-640,-639,
+-644,-646,-645,-643,-643,-642,-639,-635,-632,-631,-627,-618,-605,-592,-578,-564,-550,-540,-531,-520,-505,
+-485,-466,-449,-435,-422,-409,-399,-391,-379,-362,-340,-320,-305,-294,-282,-268,-250,-229,-207,-183,-156,
+-127,-97,-67,-35,0,38,82,132,185,238,290,342,396,452,506,558,611,670,739,820,901,
+975,1041,1116,1205,1295,1365,1411,1445,1475,1485,1452,1371,1267,1192,1197,1307,1524,1831,2214,2640,3043,
+3355,3561,3709,3848,3977,4072,4147,4236,4345,4436,4482,4505,4527,4546,4548,4545,4549,4546,4538,4560,4625,
+4639,4468,4100,3693,3418,3282,3167,2993,2788,2614,2488,2396,2331,2279,2216,2137,2092,2129,2230,2329,2381,
+2394,2389,2364,2315,2265,2241,2239,2226,2180,2107,2020,1924,1816,1703,1600,1515,1430,1326,1204,1084,975,
+863,740,624,541,491,437,356,263,189,139,97,45,-18,-88,-153,-197,-220,-247,-300,-371,-428,
+-458,-473,-487,-493,-489,-499,-542,-607,-662,-701,-749,-824,-909,-978,-1024,-1062,-1111,-1169,-1225,-1262,-1278,
+-1285,-1298,-1322,-1345,-1358,-1369,-1388,-1413,-1430,-1428,-1405,-1366,-1324,-1295,-1286,-1281,-1260,-1226,-1195,-1175,-1154,
+-1123,-1080,-1032,-986,-954,-945,-955,-964,-958,-947,-943,-937,-907,-847,-787,-765,-811,-933,-1111,-1290,-1396,
+-1397,-1327,-1248,-1187,-1131,-1062,-992,-942,-913,-890,-865,-847,-842,-843,-839,-826,-812,-801,-789,-774,-757,
+-741,-730,-723,-719,-714,-706,-695,-685,-681,-682,-687,-693,-698,-703,-710,-718,-724,-727,-731,-738,-744,
+-746,-744,-740,-734,-721,-697,-666,-636,-606,-578,-551,-526,-499,-464,-422,-380,-344,-314,-285,-256,-227,
+-195,-156,-114,-76,-41,-6,33,75,113,151,194,242,289,331,373,416,456,490,522,555,589,
+618,644,674,706,731,747,765,797,838,871,889,900,915,933,943,947,957,979,1006,1028,1045,
+1059,1072,1081,1089,1101,1116,1126,1130,1139,1158,1176,1184,1191,1216,1253,1271,1261,1258,1305,1389,1444,
+1426,1359,1305,1295,1309,1317,1314,1314,1322,1330,1332,1335,1344,1356,1366,1371,1375,1380,1387,1394,1399,
+1402,1406,1420,1423,1427,1428,1425,1425,1428,1432,1433,1433,1434,1437,1439,1440,1442,1445,1448,1450,1451,
+1452,1454,1459,1469,1478,1483,1485,1488,1494,1498,1500,1501,1505,1511,1516,1523,1536,1553,1569,1589,1618,
+1660,1712,1782,1881,2005,2126,2209,2248,2263,2277,2302,2333,2365,2392,2407,2407,2391,2356,2298,2224,2159,
+2117,2090,2061,2022,1980,1941,1903,1863,1826,1791,1759,1726,1695,1662,1624,1578,1529,1485,1448,1414,1378,
+1333,1276,1212,1154,1109,1074,1041,1005,964,918,871,835,812,791,762,732,715,706,686,643,594,
+557,534,515,494,469,434,381,313,236,148,43,-70,-165,-221,-239,-245,-270,-337,-451,-587,-703,
+-768,-780,-761,-739,-732,-754,-814,-910,-1022,-1120,-1175,-1183,-1170,-1165,-1168,-1146,-1086,-1018,-990,-1014,-1057,
+-1096,-1144,-1223,-1326,-1415,-1463,-1476,-1473,-1469,-1468,-1465,-1456,-1443,-1434,-1438,-1470,-1556,-1717,-1925,-2096,-2146,
+-2072,-1957,-1892,-1902,-1952,-1999,-2014,-1987,-1920,-1834,-1754,-1693,-1652,-1634,-1642,-1663,-1677,-1678,-1678,-1682,-1670,
+-1626,-1555,-1468,-1363,-1237,-1105,-994,-920,-899,-951,-1082,-1237,-1338,-1364,-1385,-1479,-1627,-1746,-1792,-1806,-1841,
+-1893,-1918,-1910,-1898,-1903,-1912,-1915,-1922,-1936,-1942,-1924,-1896,-1883,-1888,-1897,-1909,-1934,-1967,-1988,-1995,-2009,
+-2043,-2082,-2110,-2133,-2151,-2131,-2034,-1880,-1745,-1696,-1737,-1823,-1917,-2002,-2076,-2143,-2218,-2297,-2352,-2362,-2349,
+-2362,-2414,-2470,-2497,-2505,-2519,-2543,-2562,-2574,-2594,-2621,-2645,-2665,-2692,-2729,-2762,-2786,-2814,-2858,-2913,-2968,
+-3023,-3081,-3137,-3184,-3229,-3289,-3368,-3453,-3532,-3605,-3672,-3733,-3790,-3852,-3921,-3991,-4056,-4116,-4177,-4238,-4297,
+-4354,-4408,-4455,-4494,-4529,-4567,-4608,-4648,-4689,-4733,-4780,-4822,-4855,-4874,-4881,-4884,-4895,-4920,-4956,-4991,-5025,
+-5056,-5085,-5110,-5137,-5174,-5216,-5254,-5285,-5315,-5350,-5380,-5401,-5423,-5467,-5535,-5608,-5669,-5710,-5733,-5747,-5761,
+-5782,-5802,-5817,-5831,-5852,-5870,-5867,-5839,-5809,-5795,-5795,-5789,-5764,-5718,-5649,-5566,-5479,-5401,-5341,-5326,-5394,
+-5542,-5687,-5735,-5676,-5596,-5574,-5597,-5605,-5577,-5545,-5526,-5494,-5429,-5354,-5303,-5278,-5255,-5230,-5217,-5212,-5182,
+-5108,-5018,-4964,-4976,-5038,-5095,-5092,-5008,-4872,-4746,-4681,-4672,-4673,-4645,-4594,-4542,-4499,-4453,-4402,-4361,-4335,
+-4302,-4232,-4143,-4085,-4082,-4101,-4088,-4033,-3965,-3908,-3856,-3797,-3737,-3688,-3645,-3597,-3543,-3486,-3427,-3361,-3295,
+-3238,-3188,-3135,-3075,-3013,-2953,-2886,-2811,-2736,-2668,-2598,-2519,-2434,-2357,-2287,-2216,-2142,-2076,-2024,-1979,-1929,
+-1874,-1817,-1762,-1702,-1629,-1542,-1451,-1369,-1300,-1233,-1153,-1060,-963,-875,-810,-783,-795,-818,-808,-744,-657,
+-592,-561,-540,-503,-452,-399,-348,-293,-233,-165,-85,10,122,252,413,599,787,950,1086,1220,1367,
+1517,1655,1777,1889,1984,2055,2108,2163,2228,2298,2365,2431,2502,2567,2610,2633,2655,2693,2752,2829,2925,
+3035,3145,3230,3281,3307,3328,3354,3381,3404,3416,3407,3375,3332,3298,3288,3298,3323,3367,3434,3509,3568,
+3601,3622,3652,3703,3769,3838,3897,3940,3969,3994,4022,4056,4099,4158,4234,4313,4385,4448,4511,4575,4628,
+4666,4697,4727,4760,4789,4815,4842,4875,4915,4960,5003,5042,5077,5116,5160,5200,5226,5241,5260,5294,5341,
+5392,5440,5489,5548,5622,5701,5769,5822,5874,5941,6021,6091,6136,6162,6187,6225,6268,6295,6282,6223,6139,
+6069,6041,6054,6092,6140,6191,6234,6257,6259,6262,6286,6326,6364,6384,6385,6379,6375,6376,6373,6364,6348,
+6330,6303,6255,6186,6121,6084,6084,6108,6135,6152,6148,6128,6109,6108,6119,6121,6108,6103,6131,6183,6231,
+6252,6250,6236,6212,6180,6147,6128,6129,6141,6144,6123,6082,6047,6042,6058,6063,6033,5980,5943,5961,6036,
+6124,6157,6093,5958,5830,5776,5800,5867,5941,6005,6044,6045,6019,5990,5966,5935,5904,5909,5974,6074,6173,
+6274,6403,6545,6635,6639,6597,6581,6604,6628,6627,6613,6605,6597,6572,6538,6509,6484,6448,6401,6357,6327,
+6302,6272,6237,6202,6164,6121,6077,6039,6005,5966,5921,5878,5842,5808,5770,5725,5677,5626,5571,5514,5465,
+5434,5419,5406,5387,5369,5359,5347,5309,5236,5149,5076,5021,4962,4890,4821,4778,4765,4762,4744,4702,4652,
+4609,4580,4560,4544,4531,4521,4505,4477,4444,4418,4385,4316,4198,4034,3806,3460,2987,2511,2225,2224,2418,
+2633,2773,2851,2891,2872,2778,2647,2536,2456,2380,2296,2220,2156,2087,1999,1903,1820,1756,1709,1679,1657,
+1625,1571,1505,1447,1404,1369,1333,1299,1268,1236,1205,1182,1168,1157,1143,1126,1108,1089,1069,1051,1036,
+1019,999,974,947,918,892,872,855,835,809,783,757,730,705,687,679,671,658,652,653,645,
+618,592,597,629,649,633,599,570,545,515,490,487,506,534,573,626,669,656,573,454,346,
+270,220,191,173,146,102,59,36,13,-45,-130,-186,-169,-101,-38,-11,-9,-17,-32,-57,-87,
+-117,-149,-190,-239,-285,-322,-351,-377,-408,-440,-466,-483,-500,-523,-544,-554,-556,-569,-596,-621,-634,
+-645,-670,-709,-748,-781,-812,-843,-869,-891,-913,-940,-966,-991,-1015,-1038,-1056,-1064,-1068,-1072,-1076,-1077,
+-1077,-1080,-1080,-1075,-1069,-1067,-1068,-1064,-1058,-1056,-1057,-1053,-1038,-1022,-1014,-1008,-999,-986,-976,-972,-969,
+-965,-965,-966,-964,-958,-951,-945,-940,-932,-921,-913,-908,-902,-892,-879,-867,-856,-845,-834,-826,-818,
+-808,-797,-784,-773,-762,-749,-735,-721,-707,-693,-676,-660,-648,-638,-626,-611,-595,-581,-570,-558,-547,
+-534,-520,-505,-490,-476,-460,-442,-427,-415,-402,-386,-371,-361,-354,-344,-331,-320,-313,-307,-298,-289,
+-285,-282,-275,-266,-261,-260,-260,-258,-258,-261,-264,-264,-265,-268,-272,-276,-281,-288,-293,-296,-299,
+-303,-309,-314,-316,-317,-317,-320,-327,-334,-338,-340,-355,-389,-432,-467,-484,-488,-488,-484,-477,-473,
+-480,-495,-510,-518,-518,-517,-519,-525,-535,-546,-558,-567,-576,-583,-590,-596,-603,-609,-612,-612,-612,
+-614,-618,-620,-621,-622,-622,-624,-627,-632,-635,-634,-630,-628,-629,-631,-631,-629,-627,-624,-619,-612,
+-608,-607,-602,-593,-580,-568,-558,-548,-534,-521,-510,-500,-488,-470,-450,-432,-415,-398,-382,-370,-362,
+-352,-336,-316,-296,-281,-269,-258,-243,-224,-202,-177,-150,-123,-97,-74,-50,-20,16,58,103,151,
+200,252,303,355,406,456,507,561,617,676,741,817,902,984,1058,1133,1217,1308,1387,1440,1470,
+1492,1511,1514,1482,1401,1288,1192,1172,1258,1452,1740,2093,2462,2790,3052,3265,3460,3634,3777,3901,4038,
+4184,4303,4376,4424,4471,4509,4528,4533,4536,4522,4499,4514,4590,4646,4541,4242,3881,3613,3459,3325,3142,
+2928,2728,2551,2395,2272,2173,2063,1930,1842,1877,2027,2197,2304,2348,2368,2373,2352,2311,2284,2284,2283,
+2249,2176,2079,1970,1847,1721,1609,1519,1434,1335,1223,1115,1013,899,768,650,575,536,492,419,330,
+254,197,144,84,16,-56,-122,-168,-195,-223,-271,-336,-395,-435,-463,-482,-489,-490,-507,-552,-608,
+-650,-682,-727,-795,-867,-924,-969,-1021,-1090,-1171,-1241,-1282,-1290,-1286,-1293,-1317,-1343,-1360,-1380,-1418,-1465,
+-1494,-1488,-1449,-1393,-1338,-1298,-1271,-1244,-1212,-1186,-1180,-1186,-1182,-1161,-1129,-1093,-1051,-1005,-971,-956,-949,
+-935,-921,-915,-906,-871,-808,-747,-723,-760,-870,-1045,-1236,-1367,-1387,-1319,-1228,-1153,-1088,-1021,-959,-920,
+-898,-875,-848,-829,-825,-826,-819,-804,-791,-783,-775,-763,-747,-731,-716,-707,-704,-705,-702,-692,-681,
+-676,-680,-688,-694,-697,-703,-713,-723,-729,-734,-741,-752,-760,-763,-762,-759,-752,-736,-710,-679,-647,
+-615,-584,-555,-528,-499,-463,-419,-376,-337,-304,-273,-244,-215,-184,-146,-104,-66,-31,3,42,83,
+122,160,203,251,299,343,385,428,468,501,530,561,594,621,645,670,698,722,738,757,790,
+831,862,874,880,895,920,941,953,967,992,1020,1042,1057,1070,1082,1087,1089,1096,1112,1128,1139,
+1151,1171,1193,1203,1206,1217,1237,1246,1238,1240,1284,1355,1399,1382,1330,1294,1296,1313,1319,1314,1314,
+1324,1333,1336,1339,1349,1362,1373,1379,1385,1394,1403,1412,1417,1418,1420,1434,1433,1435,1436,1436,1437,
+1441,1447,1451,1453,1456,1460,1464,1464,1463,1466,1469,1471,1470,1469,1472,1480,1492,1502,1507,1510,1514,
+1521,1526,1529,1530,1534,1542,1551,1561,1573,1589,1608,1633,1664,1704,1753,1824,1927,2049,2155,2218,2240,
+2247,2263,2289,2321,2354,2383,2398,2396,2379,2349,2299,2231,2161,2109,2078,2056,2028,1994,1957,1919,1881,
+1847,1815,1784,1751,1717,1682,1644,1600,1553,1509,1471,1439,1407,1363,1302,1230,1166,1121,1094,1072,1045,
+1009,964,917,879,852,826,793,761,740,722,690,645,608,593,594,594,593,589,563,490,369,
+225,84,-40,-137,-181,-162,-107,-68,-80,-142,-229,-319,-399,-462,-503,-526,-546,-584,-655,-759,-880,
+-997,-1090,-1142,-1150,-1129,-1107,-1098,-1099,-1097,-1094,-1098,-1102,-1098,-1092,-1115,-1182,-1275,-1354,-1394,-1404,-1404,
+-1404,-1402,-1386,-1356,-1332,-1338,-1382,-1460,-1567,-1711,-1881,-2022,-2068,-2004,-1890,-1810,-1801,-1840,-1872,-1860,-1803,
+-1724,-1657,-1611,-1576,-1540,-1513,-1509,-1525,-1544,-1558,-1574,-1590,-1580,-1522,-1423,-1309,-1196,-1084,-973,-875,-816,
+-823,-912,-1063,-1212,-1297,-1328,-1373,-1486,-1631,-1733,-1766,-1774,-1804,-1845,-1862,-1851,-1841,-1850,-1863,-1871,-1879,
+-1893,-1896,-1876,-1845,-1828,-1829,-1837,-1848,-1870,-1897,-1916,-1929,-1958,-2006,-2047,-2064,-2070,-2078,-2058,-1964,-1806,
+-1661,-1603,-1646,-1752,-1876,-1995,-2086,-2143,-2182,-2219,-2250,-2258,-2254,-2272,-2321,-2372,-2396,-2401,-2415,-2446,-2479,
+-2504,-2524,-2545,-2563,-2578,-2599,-2629,-2659,-2686,-2720,-2767,-2823,-2877,-2928,-2981,-3032,-3081,-3133,-3202,-3284,-3367,
+-3442,-3509,-3572,-3630,-3685,-3745,-3812,-3881,-3946,-4007,-4067,-4126,-4182,-4236,-4288,-4337,-4381,-4424,-4468,-4514,-4558,
+-4600,-4644,-4686,-4721,-4746,-4760,-4767,-4773,-4789,-4819,-4856,-4891,-4922,-4955,-4989,-5022,-5055,-5094,-5137,-5176,-5207,
+-5238,-5270,-5299,-5324,-5356,-5408,-5478,-5548,-5602,-5637,-5657,-5673,-5692,-5713,-5732,-5747,-5766,-5793,-5814,-5810,-5783,
+-5756,-5746,-5746,-5737,-5711,-5664,-5595,-5507,-5412,-5325,-5258,-5241,-5313,-5467,-5617,-5667,-5610,-5534,-5515,-5537,-5543,
+-5518,-5496,-5486,-5455,-5388,-5315,-5271,-5248,-5224,-5202,-5200,-5199,-5155,-5061,-4970,-4949,-5007,-5091,-5136,-5105,-5003,
+-4869,-4761,-4714,-4714,-4710,-4671,-4611,-4559,-4520,-4474,-4419,-4376,-4357,-4333,-4271,-4184,-4124,-4118,-4137,-4132,-4087,
+-4028,-3974,-3923,-3866,-3809,-3760,-3711,-3654,-3591,-3530,-3467,-3399,-3332,-3278,-3235,-3190,-3135,-3076,-3017,-2955,-2886,
+-2813,-2742,-2666,-2583,-2500,-2426,-2361,-2294,-2222,-2156,-2101,-2053,-2002,-1945,-1887,-1831,-1771,-1698,-1607,-1513,-1433,
+-1373,-1316,-1239,-1134,-1013,-900,-819,-790,-810,-836,-811,-718,-602,-530,-522,-542,-544,-515,-465,-410,-361,
+-322,-282,-218,-108,44,220,403,586,763,927,1075,1211,1341,1462,1574,1683,1792,1892,1971,2035,2097,
+2165,2237,2311,2387,2463,2526,2561,2573,2581,2607,2660,2740,2840,2948,3046,3122,3175,3216,3253,3286,3318,
+3347,3364,3353,3311,3255,3216,3207,3225,3262,3319,3394,3469,3522,3548,3566,3595,3644,3708,3775,3834,3878,
+3907,3926,3942,3963,3998,4054,4131,4215,4293,4364,4433,4500,4557,4599,4629,4651,4670,4695,4729,4771,4816,
+4863,4918,4978,5033,5077,5115,5151,5182,5202,5215,5235,5267,5306,5346,5388,5439,5502,5577,5655,5723,5773,
+5812,5860,5926,5997,6055,6098,6136,6182,6231,6266,6270,6231,6159,6081,6025,6005,6020,6063,6121,6173,6202,
+6209,6217,6243,6283,6320,6342,6350,6350,6348,6347,6346,6343,6334,6318,6290,6244,6187,6137,6109,6106,6118,
+6135,6146,6140,6119,6101,6105,6122,6126,6109,6094,6107,6141,6169,6179,6179,6178,6167,6137,6099,6070,6061,
+6068,6076,6066,6035,5999,5986,6001,6013,5987,5929,5892,5924,6018,6111,6128,6049,5926,5838,5825,5861,5905,
+5939,5972,5997,5993,5960,5927,5916,5912,5899,5889,5907,5964,6058,6197,6384,6571,6677,6672,6613,6584,6604,
+6632,6634,6625,6621,6614,6590,6556,6528,6503,6468,6424,6384,6353,6322,6288,6258,6231,6197,6150,6101,6062,
+6027,5983,5937,5904,5883,5854,5802,5741,5691,5656,5621,5575,5526,5492,5480,5477,5471,5462,5450,5424,5363,
+5265,5156,5075,5030,4996,4944,4875,4817,4789,4781,4766,4730,4684,4649,4631,4616,4598,4586,4581,4568,4534,
+4490,4462,4447,4406,4308,4143,3892,3512,3011,2518,2229,2232,2427,2638,2774,2856,2909,2903,2817,2688,2576,
+2493,2412,2323,2244,2178,2102,2002,1899,1817,1760,1716,1680,1650,1614,1563,1503,1452,1414,1378,1336,1294,
+1259,1228,1201,1179,1167,1161,1155,1145,1130,1108,1082,1056,1033,1012,992,972,949,919,888,864,848,
+832,812,787,760,731,707,694,689,681,667,654,647,634,611,595,608,636,646,628,604,589,
+570,535,497,485,503,539,598,686,770,788,707,561,413,304,237,202,180,149,102,58,35,
+17,-28,-106,-178,-209,-206,-195,-184,-162,-132,-109,-109,-125,-143,-159,-176,-196,-221,-251,-286,-326,
+-370,-415,-455,-487,-515,-541,-564,-580,-596,-620,-648,-664,-667,-671,-691,-720,-747,-774,-807,-844,-875,
+-898,-920,-946,-971,-997,-1025,-1054,-1074,-1082,-1082,-1085,-1089,-1090,-1090,-1090,-1090,-1086,-1082,-1080,-1078,-1072,
+-1066,-1068,-1074,-1071,-1057,-1041,-1033,-1028,-1017,-1002,-992,-988,-983,-977,-973,-973,-971,-964,-956,-950,-945,
+-936,-925,-917,-910,-903,-891,-879,-868,-857,-844,-833,-824,-815,-805,-792,-780,-769,-759,-746,-732,-719,
+-707,-693,-675,-657,-642,-630,-618,-602,-585,-569,-556,-544,-532,-520,-508,-495,-481,-465,-448,-432,-419,
+-406,-392,-376,-361,-350,-340,-328,-316,-307,-302,-297,-289,-281,-274,-268,-261,-255,-251,-250,-250,-250,
+-251,-253,-253,-254,-256,-261,-264,-266,-269,-275,-280,-283,-285,-289,-295,-301,-306,-309,-311,-316,-323,
+-330,-336,-348,-374,-408,-431,-432,-420,-418,-433,-454,-464,-466,-470,-482,-493,-500,-500,-501,-505,-515,
+-530,-546,-559,-568,-576,-584,-590,-597,-604,-611,-614,-613,-611,-613,-616,-617,-616,-615,-615,-614,-613,
+-613,-615,-618,-619,-617,-614,-613,-613,-613,-610,-605,-596,-588,-582,-579,-575,-566,-554,-543,-534,-526,
+-516,-503,-492,-482,-470,-453,-433,-414,-395,-374,-354,-339,-331,-324,-313,-297,-278,-261,-246,-232,-217,
+-199,-177,-152,-125,-97,-72,-50,-26,3,40,82,126,170,216,265,318,372,423,470,518,573,
+635,697,758,824,902,989,1073,1151,1230,1312,1392,1456,1495,1515,1526,1537,1536,1498,1413,1301,1211,
+1182,1232,1364,1579,1858,2160,2446,2708,2954,3184,3395,3596,3795,3981,4124,4222,4304,4390,4462,4501,4512,
+4510,4493,4468,4478,4547,4609,4546,4327,4053,3842,3706,3571,3392,3188,2977,2743,2494,2280,2131,2008,1872,
+1769,1788,1940,2130,2256,2307,2330,2346,2341,2312,2289,2290,2297,2277,2221,2141,2041,1918,1782,1658,1556,
+1460,1352,1238,1135,1042,935,810,697,625,587,546,478,396,320,252,185,114,43,-25,-88,-136,
+-170,-203,-252,-313,-371,-415,-447,-469,-484,-504,-541,-589,-624,-642,-668,-728,-814,-893,-946,-986,-1037,
+-1107,-1183,-1247,-1280,-1284,-1279,-1285,-1308,-1335,-1360,-1392,-1439,-1487,-1513,-1506,-1469,-1415,-1356,-1303,-1255,-1210,
+-1174,-1165,-1188,-1217,-1222,-1199,-1168,-1140,-1102,-1045,-987,-949,-932,-924,-917,-908,-883,-839,-799,-797,-839,
+-903,-978,-1075,-1190,-1279,-1296,-1243,-1166,-1100,-1044,-988,-940,-911,-894,-873,-846,-827,-819,-812,-799,-783,
+-771,-765,-757,-745,-733,-720,-706,-694,-688,-689,-688,-682,-673,-670,-676,-686,-692,-697,-704,-714,-725,
+-734,-743,-755,-766,-773,-776,-776,-775,-767,-749,-724,-696,-667,-636,-603,-570,-537,-502,-462,-418,-373,
+-330,-290,-254,-224,-197,-168,-132,-94,-57,-24,11,51,94,135,174,217,264,311,355,396,435,
+471,501,531,563,596,622,642,664,692,720,743,765,797,834,862,871,874,890,920,949,967,
+983,1006,1033,1053,1066,1079,1091,1095,1091,1092,1105,1125,1142,1157,1178,1202,1218,1222,1225,1233,1239,
+1237,1241,1267,1308,1332,1322,1296,1285,1296,1311,1314,1309,1310,1318,1326,1330,1338,1352,1367,1380,1390,
+1400,1410,1421,1429,1434,1435,1434,1451,1448,1449,1453,1456,1459,1465,1471,1475,1476,1478,1482,1486,1486,
+1486,1488,1491,1491,1489,1488,1493,1505,1518,1530,1539,1545,1550,1554,1557,1559,1562,1568,1576,1585,1595,
+1609,1627,1650,1678,1709,1742,1787,1862,1973,2094,2182,2215,2215,2220,2246,2282,2316,2347,2374,2389,2383,
+2361,2333,2296,2244,2183,2130,2094,2069,2043,2009,1970,1930,1893,1861,1832,1803,1771,1735,1698,1661,1624,
+1586,1549,1514,1482,1449,1401,1331,1250,1178,1132,1109,1095,1076,1046,1006,961,924,894,866,834,803,
+775,743,696,645,616,622,646,669,686,689,651,541,366,176,19,-92,-156,-162,-106,-19,42,
+46,9,-31,-62,-97,-151,-217,-284,-352,-436,-549,-685,-825,-950,-1045,-1101,-1114,-1090,-1053,-1033,-1046,
+-1087,-1135,-1164,-1160,-1129,-1103,-1112,-1161,-1225,-1278,-1311,-1331,-1348,-1358,-1354,-1330,-1296,-1278,-1306,-1382,-1480,
+-1580,-1687,-1814,-1937,-1994,-1949,-1835,-1732,-1698,-1720,-1740,-1712,-1641,-1569,-1528,-1509,-1481,-1431,-1379,-1355,-1365,
+-1390,-1415,-1444,-1470,-1462,-1396,-1280,-1155,-1052,-973,-897,-824,-780,-804,-909,-1057,-1186,-1257,-1298,-1370,-1495,
+-1631,-1720,-1748,-1755,-1772,-1794,-1800,-1791,-1790,-1803,-1816,-1823,-1833,-1844,-1842,-1820,-1792,-1779,-1780,-1785,-1791,
+-1806,-1829,-1849,-1873,-1914,-1968,-2005,-2005,-1992,-1988,-1972,-1897,-1765,-1642,-1598,-1641,-1735,-1848,-1961,-2051,-2097,
+-2110,-2122,-2144,-2163,-2174,-2195,-2239,-2287,-2313,-2322,-2339,-2374,-2414,-2440,-2456,-2467,-2477,-2487,-2504,-2531,-2563,
+-2594,-2630,-2677,-2731,-2783,-2830,-2876,-2925,-2978,-3042,-3118,-3201,-3277,-3345,-3407,-3467,-3522,-3576,-3635,-3701,-3769,
+-3836,-3899,-3959,-4017,-4070,-4121,-4172,-4222,-4270,-4320,-4370,-4418,-4463,-4506,-4548,-4584,-4609,-4625,-4638,-4652,-4670,
+-4694,-4726,-4761,-4793,-4825,-4861,-4903,-4943,-4979,-5015,-5053,-5090,-5124,-5157,-5190,-5220,-5249,-5288,-5344,-5412,-5474,
+-5519,-5548,-5567,-5586,-5609,-5634,-5655,-5673,-5697,-5728,-5750,-5744,-5717,-5691,-5680,-5674,-5660,-5632,-5588,-5520,-5430,
+-5332,-5243,-5176,-5160,-5235,-5393,-5548,-5603,-5555,-5487,-5472,-5491,-5490,-5465,-5449,-5446,-5419,-5355,-5290,-5256,-5241,
+-5220,-5202,-5199,-5185,-5114,-4999,-4919,-4935,-5028,-5118,-5145,-5096,-4993,-4874,-4782,-4747,-4749,-4742,-4697,-4631,-4578,
+-4540,-4495,-4439,-4398,-4384,-4369,-4316,-4233,-4167,-4151,-4166,-4169,-4140,-4093,-4041,-3986,-3928,-3874,-3824,-3770,-3705,
+-3637,-3573,-3510,-3441,-3374,-3319,-3278,-3234,-3180,-3122,-3067,-3012,-2950,-2881,-2807,-2730,-2650,-2570,-2498,-2432,-2366,
+-2299,-2234,-2176,-2122,-2067,-2010,-1952,-1892,-1828,-1754,-1668,-1578,-1497,-1434,-1378,-1308,-1209,-1085,-960,-865,-826,
+-836,-847,-800,-685,-558,-490,-501,-546,-569,-547,-492,-426,-373,-346,-333,-293,-186,-9,200,400,577,
+742,903,1056,1189,1298,1392,1485,1585,1691,1793,1883,1960,2029,2092,2156,2229,2312,2395,2460,2497,2509,
+2513,2531,2577,2655,2754,2853,2935,3000,3059,3118,3172,3216,3257,3297,3324,3314,3262,3194,3149,3144,3174,
+3225,3292,3367,3434,3475,3493,3507,3537,3587,3649,3714,3771,3817,3847,3863,3870,3881,3913,3977,4064,4154,
+4233,4303,4369,4432,4487,4531,4562,4580,4591,4612,4654,4709,4762,4813,4871,4941,5008,5061,5102,5136,5161,
+5177,5190,5212,5240,5268,5295,5331,5383,5449,5524,5604,5679,5734,5770,5803,5853,5916,5980,6035,6088,6143,
+6194,6230,6239,6217,6163,6087,6012,5962,5955,5991,6052,6107,6137,6146,6155,6182,6222,6263,6294,6311,6316,
+6310,6302,6302,6311,6319,6315,6290,6246,6194,6152,6129,6122,6124,6129,6134,6128,6110,6099,6115,6149,6167,
+6152,6122,6103,6098,6093,6089,6097,6112,6112,6085,6043,6011,5998,6003,6016,6022,6006,5970,5941,5937,5942,
+5922,5882,5868,5918,6009,6073,6059,5981,5901,5875,5902,5938,5952,5953,5967,5992,5996,5971,5943,5941,5953,
+5951,5925,5891,5872,5895,5998,6195,6433,6607,6659,6631,6607,6619,6639,6641,6634,6634,6628,6605,6572,6545,
+6521,6488,6450,6419,6391,6354,6311,6277,6253,6222,6173,6123,6087,6056,6015,5971,5941,5922,5885,5816,5745,
+5708,5704,5694,5650,5584,5529,5506,5504,5499,5478,5441,5390,5319,5228,5133,5065,5035,5022,4992,4933,4867,
+4822,4801,4786,4760,4728,4704,4691,4676,4656,4640,4631,4618,4585,4542,4514,4500,4472,4398,4252,3995,3580,
+3036,2523,2246,2272,2475,2671,2783,2848,2899,2906,2837,2724,2619,2534,2448,2355,2272,2200,2114,2005,1899,
+1820,1768,1725,1684,1647,1609,1560,1508,1466,1433,1394,1344,1292,1249,1217,1191,1173,1164,1162,1161,1155,
+1142,1120,1092,1059,1027,1001,982,969,952,925,890,860,839,823,806,784,758,728,702,688,684,
+681,673,662,649,631,607,596,607,623,618,596,583,588,582,546,499,473,478,503,557,648,
+749,793,736,602,451,334,265,236,222,193,138,76,37,16,-17,-81,-157,-221,-266,-295,-302,
+-277,-231,-190,-176,-186,-206,-222,-228,-230,-237,-257,-288,-325,-365,-408,-455,-499,-537,-566,-589,-610,
+-636,-667,-692,-700,-696,-700,-717,-738,-753,-769,-797,-836,-870,-897,-921,-948,-972,-995,-1023,-1054,-1077,
+-1086,-1089,-1093,-1099,-1102,-1100,-1099,-1098,-1095,-1091,-1089,-1086,-1081,-1078,-1083,-1090,-1087,-1073,-1059,-1053,-1049,
+-1037,-1023,-1014,-1010,-1005,-994,-986,-983,-981,-974,-966,-960,-954,-944,-932,-922,-913,-903,-892,-882,-873,
+-863,-849,-834,-822,-811,-797,-783,-772,-763,-753,-740,-726,-713,-702,-689,-672,-654,-638,-626,-614,-599,
+-581,-564,-550,-537,-525,-512,-499,-487,-473,-456,-438,-423,-410,-397,-383,-367,-354,-343,-331,-317,-305,
+-295,-289,-282,-276,-269,-261,-254,-247,-243,-242,-240,-239,-239,-241,-241,-240,-242,-247,-252,-254,-253,
+-255,-260,-265,-269,-272,-275,-279,-284,-291,-297,-305,-314,-323,-331,-339,-356,-383,-407,-405,-377,-348,
+-349,-384,-426,-452,-459,-461,-466,-474,-480,-486,-493,-502,-517,-534,-551,-562,-568,-574,-581,-587,-592,
+-598,-604,-607,-607,-606,-608,-610,-609,-606,-604,-605,-605,-600,-595,-595,-599,-603,-601,-596,-592,-591,
+-591,-588,-582,-575,-567,-560,-554,-550,-544,-534,-521,-510,-500,-492,-483,-473,-462,-448,-430,-411,-392,
+-374,-354,-335,-319,-308,-300,-290,-277,-261,-244,-227,-211,-194,-175,-154,-131,-108,-84,-58,-30,0,
+32,69,109,150,193,235,281,332,385,438,486,532,586,651,719,781,841,911,994,1082,1165,
+1238,1307,1375,1441,1497,1531,1545,1551,1557,1552,1515,1441,1349,1263,1203,1192,1254,1403,1621,1873,2135,
+2402,2671,2937,3201,3460,3696,3882,4021,4144,4269,4382,4456,4492,4502,4488,4463,4464,4512,4560,4523,4382,
+4217,4102,4021,3912,3759,3589,3392,3121,2783,2470,2265,2140,2022,1912,1887,1981,2129,2234,2274,2290,2305,
+2305,2282,2258,2252,2254,2241,2212,2169,2101,1995,1860,1729,1618,1511,1388,1261,1154,1070,981,876,773,
+697,645,593,524,446,366,286,206,130,63,3,-52,-101,-144,-189,-242,-300,-352,-392,-421,-443,
+-467,-509,-570,-623,-641,-638,-664,-747,-863,-963,-1024,-1062,-1103,-1152,-1202,-1240,-1259,-1261,-1260,-1271,-1297,
+-1333,-1373,-1417,-1459,-1487,-1497,-1492,-1472,-1433,-1374,-1307,-1244,-1192,-1162,-1170,-1212,-1250,-1250,-1214,-1177,-1155,
+-1128,-1074,-1002,-944,-916,-914,-923,-918,-882,-832,-821,-892,-1018,-1120,-1149,-1133,-1127,-1140,-1143,-1119,-1082,
+-1049,-1017,-979,-942,-915,-898,-878,-856,-838,-826,-811,-792,-775,-764,-755,-742,-727,-717,-711,-701,-688,
+-678,-673,-670,-666,-662,-663,-670,-679,-688,-696,-705,-714,-722,-731,-744,-759,-768,-770,-770,-772,-773,
+-767,-751,-729,-707,-683,-655,-623,-587,-548,-505,-460,-415,-370,-323,-277,-238,-207,-181,-152,-119,-84,
+-52,-20,15,56,101,146,187,230,276,322,365,403,438,470,499,530,564,598,623,640,659,
+691,729,763,790,819,852,877,886,888,903,934,965,985,1001,1021,1042,1057,1066,1078,1092,1098,
+1094,1092,1103,1126,1147,1162,1180,1202,1223,1234,1239,1245,1252,1256,1259,1267,1281,1291,1291,1288,1293,
+1302,1308,1306,1305,1308,1315,1320,1327,1341,1360,1377,1391,1403,1415,1427,1435,1442,1449,1452,1451,1471,
+1469,1471,1477,1484,1489,1493,1497,1499,1499,1499,1503,1507,1508,1507,1508,1509,1508,1505,1507,1516,1531,
+1546,1560,1573,1584,1590,1589,1588,1590,1596,1603,1609,1616,1628,1645,1664,1687,1713,1738,1764,1806,1885,
+2005,2128,2201,2207,2184,2184,2220,2268,2306,2338,2368,2388,2382,2355,2326,2301,2271,2228,2179,2138,2103,
+2068,2029,1987,1947,1909,1874,1842,1813,1783,1750,1714,1681,1650,1621,1592,1561,1529,1491,1436,1361,1273,
+1196,1148,1125,1113,1096,1070,1035,998,965,935,906,874,840,806,764,710,660,639,659,702,742,
+762,748,672,518,315,125,-4,-73,-104,-100,-52,23,85,108,104,103,109,99,52,-26,-118,
+-218,-329,-461,-608,-756,-890,-996,-1064,-1087,-1070,-1034,-1011,-1025,-1077,-1140,-1178,-1174,-1145,-1125,-1133,-1156,
+-1174,-1184,-1203,-1241,-1287,-1319,-1324,-1304,-1277,-1271,-1312,-1395,-1488,-1564,-1635,-1731,-1845,-1918,-1894,-1783,-1663,
+-1607,-1614,-1626,-1589,-1512,-1446,-1424,-1422,-1395,-1328,-1254,-1214,-1218,-1245,-1277,-1312,-1339,-1328,-1252,-1127,-1003,
+-921,-878,-842,-797,-772,-809,-914,-1045,-1150,-1215,-1277,-1375,-1507,-1629,-1701,-1726,-1733,-1741,-1747,-1745,-1739,
+-1742,-1751,-1759,-1764,-1774,-1782,-1777,-1757,-1739,-1736,-1742,-1742,-1739,-1750,-1774,-1802,-1832,-1876,-1928,-1958,-1951,
+-1928,-1913,-1885,-1807,-1687,-1593,-1585,-1652,-1743,-1829,-1907,-1971,-2004,-2009,-2017,-2043,-2075,-2097,-2119,-2157,-2202,
+-2233,-2250,-2271,-2306,-2341,-2363,-2373,-2380,-2389,-2400,-2416,-2443,-2475,-2508,-2544,-2587,-2637,-2685,-2727,-2769,-2817,
+-2877,-2951,-3031,-3110,-3180,-3243,-3304,-3363,-3418,-3471,-3528,-3591,-3658,-3724,-3787,-3847,-3903,-3958,-4011,-4063,-4115,
+-4165,-4218,-4270,-4318,-4362,-4405,-4445,-4474,-4489,-4498,-4515,-4542,-4574,-4606,-4637,-4668,-4698,-4731,-4774,-4823,-4868,
+-4902,-4930,-4959,-4993,-5031,-5071,-5109,-5143,-5175,-5215,-5270,-5332,-5386,-5424,-5448,-5468,-5492,-5520,-5549,-5574,-5599,
+-5628,-5659,-5674,-5662,-5630,-5604,-5593,-5587,-5575,-5551,-5509,-5442,-5350,-5250,-5161,-5099,-5091,-5173,-5333,-5488,-5548,
+-5510,-5456,-5445,-5457,-5445,-5413,-5400,-5404,-5386,-5331,-5274,-5248,-5240,-5225,-5206,-5188,-5145,-5049,-4933,-4882,-4939,
+-5052,-5133,-5137,-5077,-4985,-4888,-4813,-4781,-4781,-4768,-4717,-4648,-4595,-4560,-4520,-4469,-4430,-4418,-4407,-4361,-4282,
+-4213,-4185,-4191,-4197,-4182,-4148,-4100,-4041,-3980,-3924,-3871,-3813,-3745,-3677,-3613,-3551,-3484,-3418,-3363,-3319,-3273,
+-3218,-3161,-3108,-3056,-2996,-2928,-2856,-2783,-2712,-2641,-2572,-2504,-2437,-2372,-2310,-2249,-2189,-2130,-2071,-2009,-1941,
+-1871,-1800,-1726,-1646,-1565,-1493,-1433,-1370,-1282,-1162,-1031,-923,-870,-867,-868,-822,-722,-618,-570,-588,-627,
+-638,-603,-534,-454,-387,-352,-344,-320,-227,-49,173,385,562,718,871,1018,1137,1224,1298,1380,1476,
+1576,1674,1770,1860,1935,1993,2045,2110,2193,2278,2349,2399,2429,2448,2469,2509,2578,2664,2747,2814,2875,
+2944,3019,3087,3144,3201,3261,3300,3287,3219,3135,3084,3088,3134,3200,3271,3340,3396,3427,3440,3452,3480,
+3527,3586,3647,3702,3749,3782,3797,3798,3802,3836,3913,4014,4111,4191,4258,4321,4377,4423,4462,4492,4510,
+4520,4540,4584,4644,4702,4753,4810,4882,4955,5019,5069,5110,5137,5150,5162,5183,5210,5231,5250,5281,5330,
+5392,5460,5537,5617,5682,5724,5755,5796,5853,5917,5980,6046,6111,6163,6192,6197,6183,6146,6082,6002,5933,
+5906,5931,5990,6047,6077,6084,6091,6114,6153,6200,6244,6275,6284,6271,6256,6257,6277,6302,6312,6295,6253,
+6201,6157,6131,6120,6119,6122,6125,6116,6098,6092,6120,6169,6200,6188,6147,6105,6069,6040,6027,6038,6055,
+6048,6014,5979,5961,5956,5954,5958,5969,5968,5941,5901,5874,5861,5844,5830,5851,5922,6000,6023,5974,5903,
+5871,5898,5952,5984,5982,5971,5981,6006,6019,6009,5995,5999,6013,6007,5965,5887,5787,5711,5734,5911,6199,
+6470,6620,6652,6643,6644,6650,6646,6640,6641,6637,6615,6587,6565,6544,6510,6473,6446,6422,6385,6338,6300,
+6277,6246,6195,6142,6109,6088,6056,6012,5974,5942,5892,5819,5758,5746,5768,5769,5712,5615,5531,5491,5484,
+5470,5424,5351,5272,5203,5143,5093,5060,5048,5043,5022,4971,4906,4853,4824,4810,4795,4775,4756,4741,4725,
+4706,4687,4671,4655,4634,4611,4590,4566,4527,4461,4335,4081,3639,3062,2545,2297,2359,2573,2743,2811,2836,
+2866,2876,2829,2742,2654,2573,2484,2386,2299,2220,2127,2017,1912,1837,1784,1738,1694,1654,1615,1569,1524,
+1487,1455,1411,1351,1290,1241,1208,1185,1171,1167,1167,1165,1158,1148,1132,1104,1066,1026,995,979,972,
+961,935,895,856,826,805,788,769,748,722,695,675,668,668,667,661,646,621,592,575,575,
+574,556,531,524,539,542,512,467,439,436,446,475,536,615,662,636,547,436,348,303,302,
+316,302,235,139,60,17,-11,-56,-120,-188,-246,-287,-306,-298,-270,-242,-233,-249,-282,-314,-330,
+-327,-321,-327,-344,-366,-389,-423,-469,-518,-559,-591,-616,-640,-670,-700,-723,-729,-727,-731,-746,-759,
+-765,-772,-793,-826,-859,-887,-916,-946,-971,-992,-1015,-1042,-1064,-1077,-1084,-1094,-1104,-1108,-1106,-1104,-1103,
+-1101,-1099,-1097,-1095,-1092,-1091,-1096,-1102,-1099,-1086,-1075,-1071,-1068,-1058,-1045,-1038,-1035,-1028,-1016,-1005,-1000,
+-997,-991,-982,-974,-966,-956,-943,-931,-919,-906,-896,-889,-882,-870,-853,-837,-822,-807,-792,-778,-768,
+-759,-748,-733,-718,-706,-695,-681,-666,-649,-634,-621,-610,-597,-580,-562,-547,-534,-520,-506,-492,-480,
+-466,-449,-431,-415,-401,-389,-375,-362,-351,-338,-324,-311,-299,-288,-278,-268,-262,-257,-249,-241,-234,
+-231,-230,-228,-226,-226,-227,-226,-225,-228,-234,-240,-241,-240,-243,-248,-253,-258,-262,-265,-267,-269,
+-275,-285,-298,-310,-320,-326,-331,-344,-364,-380,-372,-345,-325,-336,-376,-417,-438,-442,-443,-447,-454,
+-462,-474,-488,-502,-517,-534,-549,-556,-558,-561,-568,-575,-581,-585,-591,-595,-598,-598,-599,-599,-596,
+-591,-590,-593,-595,-591,-583,-578,-580,-582,-580,-574,-569,-566,-565,-561,-557,-553,-549,-543,-535,-529,
+-525,-518,-505,-488,-475,-466,-459,-450,-438,-422,-404,-385,-368,-352,-336,-321,-307,-294,-281,-268,-254,
+-240,-225,-208,-190,-171,-150,-128,-108,-91,-71,-45,-12,24,61,97,135,175,217,259,301,346,
+396,450,501,548,599,661,732,801,865,931,1008,1093,1176,1247,1302,1352,1407,1469,1523,1553,1563,
+1569,1577,1577,1550,1492,1412,1318,1228,1173,1183,1271,1428,1642,1898,2178,2464,2752,3043,3327,3575,3772,
+3935,4088,4234,4359,4450,4499,4500,4470,4455,4483,4521,4507,4438,4373,4354,4340,4272,4153,4025,3869,3612,
+3247,2882,2631,2488,2363,2218,2114,2108,2170,2227,2250,2260,2271,2271,2252,2227,2210,2195,2177,2164,2155,
+2121,2036,1909,1784,1678,1571,1439,1298,1184,1107,1041,962,873,788,712,638,561,481,397,307,217,
+141,82,31,-20,-73,-128,-185,-241,-290,-331,-366,-394,-418,-448,-503,-577,-636,-651,-645,-677,-776,
+-911,-1028,-1101,-1145,-1178,-1207,-1230,-1244,-1249,-1246,-1245,-1256,-1285,-1331,-1385,-1434,-1462,-1466,-1460,-1460,-1458,
+-1433,-1374,-1301,-1236,-1191,-1171,-1184,-1222,-1250,-1232,-1181,-1139,-1128,-1124,-1089,-1022,-952,-909,-905,-926,-933,
+-896,-836,-827,-926,-1089,-1205,-1201,-1113,-1030,-1002,-1010,-1018,-1016,-1006,-990,-965,-938,-916,-898,-880,-863,
+-849,-836,-816,-793,-775,-762,-748,-729,-710,-702,-700,-694,-681,-667,-657,-652,-648,-647,-651,-659,-668,
+-680,-693,-704,-711,-716,-723,-738,-752,-758,-755,-751,-754,-759,-756,-745,-729,-712,-691,-665,-634,-600,
+-559,-512,-465,-419,-373,-323,-274,-234,-203,-177,-147,-115,-84,-55,-24,11,54,101,149,195,239,
+284,329,370,407,440,471,501,534,569,601,625,640,659,694,741,784,815,841,870,895,907,
+911,924,949,978,999,1013,1028,1043,1053,1059,1068,1084,1096,1099,1101,1114,1138,1161,1177,1190,1207,
+1228,1244,1254,1261,1268,1273,1275,1274,1276,1281,1289,1298,1304,1305,1301,1298,1301,1309,1316,1322,1333,
+1352,1374,1392,1404,1417,1432,1444,1450,1456,1463,1470,1471,1491,1489,1490,1497,1506,1512,1516,1518,1519,
+1519,1520,1524,1528,1528,1525,1522,1522,1521,1521,1527,1541,1558,1574,1589,1605,1620,1626,1625,1623,1627,
+1634,1639,1641,1648,1662,1681,1698,1714,1732,1753,1776,1814,1891,2012,2136,2204,2198,2162,2158,2202,2261,
+2307,2343,2380,2409,2409,2382,2351,2332,2314,2283,2238,2189,2142,2097,2051,2009,1971,1933,1893,1856,1824,
+1797,1770,1742,1713,1684,1655,1627,1598,1567,1528,1470,1393,1305,1228,1177,1152,1136,1116,1089,1058,1028,
+1000,972,938,898,854,812,772,732,699,688,709,750,786,790,741,623,448,257,109,29,0,
+-13,-18,0,46,101,141,165,183,195,189,151,82,-8,-116,-239,-375,-522,-676,-825,-950,-1030,
+-1061,-1053,-1029,-1015,-1028,-1072,-1124,-1154,-1152,-1137,-1136,-1147,-1143,-1110,-1073,-1072,-1124,-1203,-1269,-1300,-1299,
+-1286,-1289,-1327,-1397,-1472,-1528,-1575,-1648,-1750,-1830,-1822,-1723,-1600,-1533,-1534,-1543,-1501,-1416,-1344,-1322,-1328,
+-1308,-1243,-1167,-1121,-1117,-1137,-1163,-1190,-1206,-1181,-1093,-963,-848,-791,-783,-779,-758,-750,-793,-893,-1008,
+-1101,-1176,-1267,-1391,-1522,-1621,-1671,-1689,-1698,-1706,-1708,-1703,-1697,-1695,-1697,-1699,-1704,-1714,-1720,-1712,-1697,
+-1689,-1696,-1705,-1702,-1695,-1705,-1734,-1769,-1802,-1840,-1883,-1912,-1916,-1906,-1891,-1844,-1735,-1591,-1498,-1519,-1624,
+-1734,-1804,-1843,-1870,-1888,-1897,-1914,-1948,-1986,-2013,-2034,-2065,-2105,-2137,-2158,-2180,-2212,-2242,-2259,-2268,-2281,
+-2299,-2317,-2335,-2360,-2390,-2421,-2454,-2493,-2539,-2584,-2624,-2664,-2714,-2781,-2858,-2937,-3010,-3077,-3141,-3204,-3264,
+-3320,-3372,-3426,-3485,-3548,-3610,-3669,-3727,-3785,-3844,-3903,-3959,-4012,-4064,-4116,-4168,-4215,-4258,-4300,-4336,-4359,
+-4368,-4378,-4403,-4442,-4484,-4519,-4548,-4575,-4603,-4638,-4686,-4741,-4788,-4819,-4839,-4861,-4894,-4937,-4984,-5029,-5067,
+-5101,-5140,-5190,-5244,-5291,-5323,-5347,-5371,-5399,-5431,-5464,-5494,-5524,-5554,-5579,-5582,-5558,-5522,-5500,-5499,-5504,
+-5501,-5483,-5444,-5375,-5278,-5173,-5083,-5027,-5033,-5126,-5288,-5439,-5498,-5469,-5426,-5419,-5421,-5395,-5357,-5349,-5366,
+-5362,-5315,-5263,-5240,-5236,-5223,-5193,-5151,-5081,-4979,-4892,-4888,-4978,-5091,-5144,-5120,-5055,-4980,-4906,-4844,-4813,
+-4804,-4781,-4724,-4655,-4607,-4581,-4550,-4505,-4465,-4448,-4434,-4392,-4321,-4254,-4218,-4212,-4213,-4206,-4184,-4144,-4088,
+-4024,-3963,-3906,-3847,-3780,-3713,-3650,-3588,-3522,-3459,-3404,-3358,-3310,-3257,-3202,-3150,-3096,-3034,-2964,-2892,-2824,
+-2760,-2699,-2635,-2567,-2500,-2437,-2376,-2314,-2251,-2190,-2130,-2065,-1991,-1915,-1848,-1787,-1719,-1640,-1563,-1500,-1440,
+-1360,-1243,-1106,-989,-925,-912,-913,-887,-825,-763,-735,-743,-751,-730,-675,-599,-515,-438,-386,-362,-334,
+-250,-83,138,355,535,685,827,957,1055,1123,1185,1265,1358,1451,1540,1633,1728,1808,1866,1914,1976,
+2056,2139,2214,2280,2337,2381,2414,2450,2502,2565,2625,2679,2741,2822,2909,2989,3062,3141,3221,3264,3238,
+3150,3055,3009,3031,3100,3180,3253,3313,3356,3381,3391,3400,3421,3461,3513,3570,3623,3671,3709,3728,3728,
+3730,3767,3850,3958,4058,4137,4205,4268,4319,4355,4386,4417,4444,4461,4482,4522,4578,4635,4687,4746,4817,
+4892,4960,5022,5073,5105,5116,5121,5138,5162,5183,5200,5229,5276,5332,5392,5460,5535,5604,5653,5692,5740,
+5802,5868,5935,6008,6082,6136,6157,6150,6134,6109,6064,5992,5914,5868,5876,5927,5986,6026,6041,6048,6064,
+6098,6148,6203,6245,6258,6245,6228,6229,6249,6273,6284,6273,6239,6190,6143,6111,6095,6094,6100,6102,6090,
+6068,6062,6096,6152,6187,6176,6134,6088,6048,6016,6003,6008,6007,5978,5934,5915,5929,5940,5923,5897,5895,
+5910,5908,5878,5838,5803,5775,5769,5811,5897,5969,5970,5908,5848,5845,5895,5952,5982,5984,5981,5991,6009,
+6022,6024,6026,6034,6038,6024,5977,5879,5730,5578,5535,5692,6021,6372,6597,6669,6666,6658,6658,6654,6649,
+6648,6641,6620,6597,6582,6565,6531,6488,6456,6433,6401,6359,6325,6304,6273,6219,6161,6127,6110,6084,6040,
+5992,5945,5891,5828,5788,5794,5823,5821,5754,5643,5543,5488,5466,5437,5369,5269,5166,5093,5057,5047,5050,
+5058,5057,5034,4986,4925,4875,4847,4835,4827,4814,4796,4780,4768,4757,4739,4716,4693,4682,4682,4675,4645,
+4595,4531,4413,4148,3671,3063,2552,2348,2457,2686,2838,2864,2842,2835,2831,2798,2738,2674,2602,2512,2410,
+2318,2236,2144,2039,1939,1862,1803,1751,1704,1664,1626,1583,1541,1506,1469,1417,1351,1287,1239,1209,1195,
+1194,1198,1195,1182,1168,1158,1147,1121,1078,1031,998,983,978,966,937,894,850,815,789,769,752,
+736,717,693,671,659,657,656,650,633,605,570,543,528,516,494,471,464,471,469,441,406,
+386,383,384,390,413,452,483,481,445,393,352,350,394,454,467,391,251,118,40,5,-26,
+-76,-134,-184,-220,-245,-264,-274,-276,-279,-298,-339,-388,-420,-425,-419,-416,-420,-426,-438,-463,-500,
+-540,-575,-608,-641,-673,-699,-724,-745,-759,-766,-772,-780,-784,-784,-787,-802,-827,-853,-879,-908,-940,
+-966,-986,-1005,-1027,-1047,-1062,-1074,-1089,-1102,-1107,-1106,-1104,-1106,-1108,-1108,-1108,-1107,-1103,-1102,-1105,-1109,
+-1105,-1095,-1086,-1085,-1083,-1075,-1064,-1058,-1054,-1047,-1036,-1027,-1022,-1019,-1013,-1003,-992,-980,-969,-958,-946,
+-932,-918,-908,-902,-894,-879,-861,-843,-828,-812,-796,-783,-773,-762,-746,-729,-714,-701,-688,-675,-661,
+-646,-629,-614,-603,-592,-577,-560,-543,-528,-514,-498,-484,-471,-458,-442,-423,-407,-393,-381,-368,-357,
+-346,-332,-317,-305,-295,-285,-271,-259,-252,-248,-241,-231,-224,-221,-219,-216,-214,-215,-216,-214,-213,
+-216,-223,-227,-229,-231,-236,-242,-246,-250,-255,-259,-260,-261,-266,-278,-292,-305,-314,-317,-316,-319,
+-331,-344,-349,-347,-350,-369,-395,-412,-417,-417,-421,-429,-438,-449,-466,-483,-497,-510,-523,-535,-540,
+-540,-541,-548,-558,-567,-574,-579,-583,-586,-588,-587,-585,-579,-574,-573,-578,-583,-583,-576,-568,-563,
+-561,-558,-553,-547,-544,-540,-535,-531,-530,-529,-524,-515,-507,-504,-499,-487,-468,-451,-441,-434,-425,
+-411,-396,-381,-365,-348,-331,-316,-304,-293,-280,-264,-247,-231,-217,-201,-185,-167,-148,-126,-104,-85,
+-68,-49,-22,12,50,88,123,158,196,239,283,325,366,410,462,516,567,616,673,742,815,
+887,957,1028,1105,1181,1249,1300,1339,1380,1434,1493,1539,1562,1576,1592,1607,1609,1589,1547,1481,1387,
+1277,1183,1139,1177,1309,1527,1793,2068,2341,2629,2935,3231,3476,3664,3825,3994,4177,4349,4467,4501,4472,
+4442,4456,4495,4508,4488,4485,4524,4557,4522,4429,4329,4218,4024,3723,3395,3144,2974,2807,2602,2411,2298,
+2260,2249,2238,2232,2237,2239,2231,2220,2207,2182,2151,2134,2135,2117,2045,1929,1813,1718,1618,1488,1346,
+1230,1158,1106,1047,970,879,783,688,601,518,430,333,239,163,107,58,4,-57,-126,-192,-247,
+-285,-315,-349,-387,-420,-454,-507,-578,-639,-664,-672,-713,-810,-939,-1056,-1140,-1196,-1235,-1259,-1271,-1275,
+-1269,-1253,-1237,-1239,-1266,-1316,-1371,-1412,-1425,-1414,-1404,-1411,-1418,-1395,-1336,-1268,-1217,-1187,-1172,-1176,-1193,
+-1199,-1166,-1107,-1068,-1072,-1092,-1086,-1038,-969,-915,-901,-922,-938,-907,-838,-804,-866,-994,-1084,-1069,-986,
+-923,-926,-964,-987,-976,-944,-912,-894,-890,-893,-890,-878,-863,-849,-833,-810,-784,-764,-750,-733,-712,
+-695,-688,-686,-679,-667,-653,-641,-633,-629,-629,-635,-644,-655,-667,-682,-696,-704,-708,-715,-729,-743,
+-746,-741,-737,-740,-746,-746,-739,-728,-714,-693,-667,-639,-610,-573,-528,-479,-432,-383,-330,-280,-240,
+-211,-184,-154,-123,-95,-68,-36,2,46,95,146,196,243,288,331,372,408,441,473,505,538,
+571,602,627,644,665,700,747,791,823,846,871,895,912,921,932,952,977,997,1010,1023,1037,
+1046,1053,1063,1080,1098,1111,1121,1136,1159,1182,1200,1212,1225,1242,1257,1267,1272,1275,1276,1277,1276,
+1276,1281,1289,1297,1300,1297,1291,1291,1298,1308,1317,1326,1341,1364,1388,1405,1417,1433,1451,1465,1471,
+1474,1481,1489,1491,1509,1507,1506,1511,1519,1526,1530,1533,1535,1536,1539,1544,1547,1545,1538,1534,1533,
+1536,1541,1551,1567,1586,1604,1621,1639,1655,1664,1667,1668,1672,1676,1675,1674,1679,1693,1710,1721,1730,
+1745,1768,1792,1825,1889,1996,2114,2187,2187,2158,2160,2215,2286,2340,2377,2416,2452,2462,2442,2412,2391,
+2371,2335,2282,2223,2166,2112,2064,2023,1989,1956,1918,1881,1849,1826,1806,1786,1762,1731,1696,1663,1635,
+1607,1567,1508,1430,1344,1268,1215,1186,1166,1142,1112,1082,1056,1033,1005,966,914,856,808,780,767,
+760,754,756,767,771,742,661,528,373,237,149,111,96,77,54,49,76,126,177,214,235,
+243,239,222,181,110,6,-118,-252,-397,-561,-733,-882,-974,-1005,-1002,-994,-999,-1021,-1056,-1090,-1108,
+-1108,-1106,-1117,-1126,-1103,-1038,-971,-955,-1012,-1115,-1213,-1277,-1304,-1309,-1315,-1344,-1397,-1455,-1498,-1532,-1582,
+-1660,-1729,-1731,-1650,-1539,-1472,-1472,-1486,-1448,-1356,-1267,-1229,-1229,-1218,-1170,-1107,-1061,-1044,-1043,-1050,-1059,
+-1058,-1015,-918,-793,-699,-669,-685,-701,-696,-695,-740,-834,-947,-1052,-1156,-1280,-1418,-1535,-1604,-1629,-1639,
+-1651,-1665,-1671,-1665,-1656,-1650,-1648,-1651,-1659,-1667,-1669,-1660,-1647,-1645,-1655,-1664,-1660,-1655,-1667,-1700,-1738,
+-1767,-1794,-1827,-1857,-1878,-1893,-1896,-1852,-1726,-1557,-1443,-1461,-1580,-1705,-1768,-1779,-1776,-1780,-1796,-1823,-1861,
+-1899,-1926,-1947,-1975,-2007,-2034,-2052,-2074,-2103,-2128,-2142,-2154,-2175,-2202,-2228,-2248,-2270,-2296,-2325,-2357,-2396,
+-2440,-2483,-2522,-2563,-2618,-2688,-2764,-2837,-2906,-2973,-3040,-3106,-3167,-3220,-3271,-3324,-3381,-3439,-3496,-3552,-3610,
+-3670,-3732,-3794,-3853,-3908,-3962,-4016,-4068,-4114,-4154,-4191,-4222,-4241,-4252,-4269,-4303,-4349,-4393,-4429,-4457,-4482,
+-4509,-4545,-4595,-4653,-4700,-4729,-4745,-4767,-4803,-4850,-4901,-4949,-4989,-5024,-5062,-5107,-5155,-5196,-5228,-5255,-5283,
+-5315,-5349,-5384,-5417,-5449,-5476,-5489,-5476,-5441,-5407,-5399,-5417,-5441,-5448,-5433,-5391,-5318,-5215,-5103,-5007,-4955,
+-4975,-5082,-5248,-5393,-5448,-5424,-5390,-5381,-5373,-5337,-5299,-5302,-5335,-5344,-5304,-5252,-5229,-5226,-5209,-5162,-5094,
+-5013,-4935,-4900,-4943,-5045,-5130,-5143,-5095,-5031,-4975,-4920,-4869,-4836,-4818,-4786,-4726,-4661,-4623,-4606,-4582,-4539,
+-4496,-4471,-4452,-4413,-4352,-4291,-4250,-4232,-4224,-4219,-4207,-4179,-4130,-4068,-4003,-3941,-3881,-3817,-3752,-3687,-3622,
+-3557,-3496,-3441,-3392,-3344,-3294,-3243,-3191,-3135,-3071,-3002,-2933,-2866,-2803,-2744,-2683,-2620,-2556,-2496,-2437,-2375,
+-2310,-2247,-2185,-2119,-2043,-1967,-1902,-1848,-1787,-1713,-1637,-1576,-1522,-1447,-1334,-1198,-1081,-1012,-991,-986,-969,
+-935,-898,-874,-857,-829,-779,-713,-642,-570,-499,-438,-392,-342,-248,-86,125,335,509,649,773,882,
+960,1014,1071,1151,1246,1334,1413,1495,1584,1664,1725,1782,1853,1936,2016,2089,2162,2235,2299,2344,2380,
+2418,2457,2494,2538,2603,2693,2788,2877,2964,3061,3147,3181,3136,3038,2950,2927,2977,3069,3163,3237,3286,
+3317,3334,3341,3344,3356,3386,3432,3485,3537,3587,3632,3660,3667,3675,3713,3793,3893,3984,4057,4124,4186,
+4233,4263,4294,4337,4381,4414,4437,4470,4518,4574,4632,4695,4765,4834,4900,4966,5025,5061,5068,5065,5075,
+5098,5117,5134,5163,5212,5271,5330,5392,5456,5515,5564,5614,5679,5755,5828,5897,5970,6046,6101,6115,6097,
+6074,6059,6034,5979,5901,5835,5816,5851,5913,5968,5999,6013,6026,6055,6102,6159,6201,6215,6205,6194,6197,
+6207,6213,6211,6201,6179,6145,6104,6069,6050,6046,6052,6056,6045,6023,6018,6051,6104,6135,6122,6085,6049,
+6021,5999,5988,5982,5958,5904,5857,5867,5923,5954,5916,5849,5825,5853,5886,5883,5847,5797,5749,5727,5763,
+5848,5926,5940,5900,5865,5873,5910,5943,5961,5974,5989,5999,6002,6006,6017,6032,6040,6033,6012,5970,5879,
+5718,5532,5454,5602,5953,6337,6583,6658,6650,6648,6662,6669,6664,6657,6645,6623,6600,6588,6575,6544,6499,
+6462,6438,6411,6375,6343,6323,6295,6244,6185,6145,6122,6094,6049,5997,5948,5899,5848,5815,5814,5831,5827,
+5777,5689,5597,5526,5477,5426,5349,5244,5133,5049,5008,5006,5027,5051,5061,5042,4996,4940,4894,4869,4859,
+4853,4844,4830,4818,4813,4811,4797,4768,4739,4730,4739,4738,4707,4659,4601,4477,4174,3640,3000,2509,2357,
+2513,2761,2909,2919,2870,2829,2799,2763,2722,2680,2621,2532,2428,2334,2252,2166,2068,1971,1887,1818,1759,
+1711,1670,1630,1589,1550,1513,1470,1413,1351,1296,1256,1234,1235,1253,1267,1255,1219,1185,1169,1160,1135,
+1090,1041,1007,989,977,956,922,879,839,809,786,766,747,731,715,697,679,667,661,654,641,
+620,591,557,522,496,479,466,457,449,438,415,382,351,337,333,330,326,328,341,356,368,
+370,361,355,383,467,572,616,539,367,191,80,33,0,-50,-110,-156,-184,-210,-248,-288,-315,
+-325,-336,-368,-417,-459,-480,-485,-487,-489,-492,-503,-525,-548,-563,-581,-617,-666,-707,-726,-734,-751,
+-779,-802,-814,-815,-812,-810,-811,-821,-837,-857,-879,-904,-932,-956,-976,-995,-1015,-1034,-1048,-1063,-1079,
+-1093,-1099,-1100,-1103,-1108,-1114,-1118,-1119,-1117,-1114,-1111,-1113,-1114,-1109,-1099,-1091,-1090,-1089,-1083,-1075,-1069,
+-1066,-1060,-1052,-1045,-1043,-1041,-1035,-1024,-1010,-995,-984,-975,-966,-952,-937,-927,-922,-912,-895,-875,-858,
+-843,-826,-808,-796,-785,-770,-750,-730,-714,-700,-685,-671,-658,-645,-628,-610,-596,-586,-574,-556,-538,
+-521,-506,-491,-476,-463,-450,-434,-416,-400,-386,-372,-359,-348,-336,-322,-308,-298,-290,-281,-267,-254,
+-247,-242,-235,-225,-218,-215,-212,-210,-209,-210,-210,-208,-207,-211,-216,-219,-221,-226,-234,-240,-242,
+-245,-251,-258,-260,-260,-266,-277,-290,-301,-308,-310,-308,-306,-311,-324,-341,-358,-377,-393,-401,-398,
+-393,-396,-407,-419,-430,-442,-459,-476,-488,-497,-508,-518,-524,-524,-525,-532,-544,-557,-564,-567,-569,
+-571,-573,-572,-568,-563,-559,-560,-564,-569,-572,-567,-558,-549,-543,-539,-535,-530,-526,-521,-515,-509,
+-505,-504,-499,-490,-481,-476,-472,-461,-444,-428,-417,-409,-398,-385,-373,-362,-350,-333,-313,-295,-282,
+-271,-259,-244,-228,-213,-196,-179,-161,-144,-127,-108,-88,-69,-49,-24,5,39,75,111,146,180,
+215,256,302,347,388,428,476,530,585,638,693,757,828,902,974,1042,1106,1169,1231,1285,1328,
+1367,1411,1462,1510,1545,1572,1598,1621,1634,1637,1632,1614,1562,1465,1335,1212,1149,1185,1328,1544,1784,
+2028,2292,2590,2895,3153,3343,3502,3688,3929,4189,4391,4480,4469,4433,4436,4476,4503,4501,4511,4560,4611,
+4599,4520,4422,4331,4209,4024,3807,3609,3429,3222,2973,2732,2551,2428,2330,2251,2202,2188,2192,2205,2224,
+2235,2219,2181,2153,2145,2127,2062,1955,1843,1747,1647,1526,1398,1294,1225,1173,1117,1045,956,852,746,
+652,566,475,374,276,197,137,82,21,-48,-126,-200,-254,-286,-312,-353,-408,-457,-497,-543,-604,
+-661,-695,-716,-760,-841,-946,-1050,-1142,-1219,-1275,-1307,-1322,-1322,-1303,-1266,-1227,-1215,-1237,-1280,-1323,-1346,
+-1347,-1337,-1335,-1346,-1350,-1321,-1264,-1210,-1178,-1160,-1144,-1134,-1134,-1125,-1089,-1036,-1003,-1013,-1044,-1058,-1036,
+-985,-932,-905,-912,-925,-903,-839,-783,-785,-834,-867,-850,-822,-843,-922,-999,-1012,-948,-851,-779,-765,
+-803,-855,-884,-881,-861,-839,-818,-792,-765,-743,-727,-710,-693,-681,-676,-671,-661,-648,-635,-625,-616,
+-609,-608,-615,-627,-639,-651,-665,-679,-690,-699,-708,-721,-733,-738,-736,-733,-736,-739,-738,-733,-725,
+-711,-690,-663,-638,-615,-585,-544,-497,-447,-394,-338,-287,-247,-218,-191,-162,-135,-110,-83,-49,-8,
+37,86,138,189,238,283,327,368,404,437,470,504,536,568,598,627,650,673,703,743,783,
+812,831,850,873,895,912,928,947,969,987,1001,1014,1029,1045,1058,1071,1088,1108,1128,1145,1161,
+1179,1200,1221,1237,1250,1260,1270,1277,1278,1275,1273,1273,1274,1276,1278,1281,1284,1285,1284,1285,1288,
+1296,1305,1314,1326,1344,1370,1396,1416,1432,1451,1471,1486,1492,1494,1499,1506,1509,1527,1529,1529,1531,
+1536,1540,1544,1546,1549,1551,1555,1559,1561,1558,1552,1549,1551,1559,1568,1580,1597,1617,1638,1657,1676,
+1691,1703,1710,1716,1719,1718,1713,1709,1710,1717,1726,1733,1743,1763,1791,1817,1840,1883,1967,2075,2155,
+2176,2167,2186,2253,2335,2393,2427,2460,2497,2516,2508,2483,2455,2420,2367,2300,2231,2168,2111,2062,2023,
+1994,1968,1940,1913,1889,1870,1854,1839,1820,1790,1751,1715,1687,1660,1618,1553,1470,1382,1305,1250,1219,
+1199,1176,1143,1110,1083,1061,1036,998,943,881,833,817,828,839,828,796,757,713,648,552,438,
+338,273,240,219,192,156,122,111,131,174,224,261,281,292,303,311,299,248,155,42,-76,
+-211,-382,-582,-762,-871,-905,-905,-915,-945,-983,-1016,-1039,-1052,-1056,-1061,-1070,-1072,-1041,-975,-909,-895,
+-955,-1064,-1178,-1262,-1309,-1329,-1341,-1364,-1403,-1447,-1481,-1502,-1529,-1576,-1626,-1633,-1572,-1474,-1409,-1408,-1432,
+-1412,-1327,-1226,-1164,-1148,-1138,-1105,-1054,-1005,-966,-933,-910,-897,-879,-827,-732,-627,-560,-554,-585,-610,
+-615,-622,-667,-759,-883,-1019,-1162,-1311,-1445,-1535,-1574,-1581,-1587,-1604,-1622,-1630,-1624,-1612,-1605,-1606,-1614,
+-1624,-1630,-1627,-1618,-1606,-1603,-1609,-1615,-1616,-1617,-1634,-1667,-1701,-1724,-1741,-1761,-1782,-1801,-1822,-1843,-1829,
+-1743,-1601,-1489,-1484,-1574,-1678,-1726,-1719,-1700,-1700,-1720,-1751,-1785,-1814,-1837,-1861,-1890,-1920,-1941,-1957,-1978,
+-2007,-2030,-2040,-2048,-2066,-2092,-2119,-2143,-2166,-2192,-2221,-2255,-2296,-2340,-2382,-2421,-2466,-2524,-2593,-2664,-2733,
+-2800,-2870,-2940,-3006,-3063,-3113,-3163,-3218,-3275,-3332,-3387,-3442,-3501,-3563,-3625,-3685,-3743,-3801,-3859,-3917,-3969,
+-4012,-4047,-4077,-4102,-4121,-4141,-4169,-4210,-4255,-4297,-4333,-4364,-4391,-4418,-4453,-4505,-4564,-4611,-4636,-4653,-4679,
+-4720,-4771,-4820,-4865,-4905,-4942,-4981,-5023,-5067,-5106,-5140,-5173,-5207,-5242,-5276,-5309,-5343,-5373,-5392,-5391,-5366,
+-5330,-5308,-5320,-5360,-5399,-5412,-5391,-5341,-5261,-5153,-5033,-4931,-4880,-4913,-5035,-5206,-5345,-5397,-5377,-5347,-5335,
+-5318,-5277,-5244,-5259,-5305,-5323,-5287,-5237,-5213,-5208,-5180,-5114,-5031,-4962,-4928,-4947,-5018,-5103,-5146,-5121,-5062,
+-5009,-4970,-4929,-4884,-4852,-4829,-4793,-4734,-4676,-4645,-4633,-4612,-4571,-4527,-4497,-4475,-4441,-4389,-4332,-4286,-4256,
+-4241,-4234,-4227,-4206,-4166,-4108,-4042,-3978,-3915,-3853,-3790,-3725,-3658,-3594,-3534,-3479,-3427,-3375,-3325,-3275,-3223,
+-3167,-3107,-3046,-2983,-2919,-2853,-2790,-2730,-2672,-2615,-2560,-2503,-2440,-2370,-2299,-2231,-2163,-2088,-2015,-1951,-1897,
+-1840,-1771,-1702,-1646,-1598,-1532,-1430,-1307,-1200,-1132,-1098,-1075,-1048,-1015,-979,-943,-899,-845,-781,-715,-654,
+-597,-542,-481,-413,-327,-206,-39,156,344,495,613,714,802,868,916,971,1052,1147,1234,1306,1378,
+1454,1527,1594,1665,1750,1839,1915,1980,2045,2116,2180,2231,2273,2313,2347,2377,2419,2487,2577,2669,2757,
+2851,2952,3029,3043,2986,2899,2843,2854,2928,3033,3133,3206,3249,3270,3279,3282,3281,3285,3305,3344,3395,
+3448,3501,3551,3588,3611,3631,3672,3744,3827,3900,3961,4020,4077,4119,4151,4192,4254,4321,4369,4398,4428,
+4472,4528,4590,4654,4717,4776,4836,4902,4966,5006,5015,5010,5016,5034,5049,5060,5087,5139,5208,5277,5338,
+5392,5440,5486,5543,5622,5711,5792,5860,5928,6000,6052,6063,6040,6014,6005,6000,5967,5897,5817,5770,5779,
+5832,5891,5932,5951,5965,5991,6035,6084,6118,6126,6120,6117,6123,6124,6113,6097,6087,6079,6062,6036,6008,
+5987,5981,5987,5997,5998,5990,5993,6022,6061,6078,6062,6032,6007,5988,5967,5951,5934,5892,5826,5787,5831,
+5928,5978,5924,5824,5780,5816,5875,5897,5873,5824,5767,5725,5735,5804,5889,5940,5956,5967,5985,5989,5973,
+5961,5974,6000,6010,5999,5991,6006,6032,6040,6024,5999,5967,5892,5734,5533,5430,5559,5900,6278,6517,6590,
+6597,6625,6669,6688,6677,6661,6648,6628,6603,6585,6573,6550,6513,6478,6454,6429,6392,6356,6329,6304,6264,
+6213,6167,6131,6094,6049,6003,5961,5917,5865,5816,5788,5783,5784,5767,5721,5646,5558,5474,5399,5323,5234,
+5137,5052,4997,4981,4998,5032,5058,5054,5017,4965,4922,4897,4886,4880,4875,4867,4861,4859,4858,4845,4816,
+4789,4780,4783,4771,4732,4685,4626,4473,4111,3525,2883,2442,2352,2535,2780,2924,2948,2910,2857,2801,2748,
+2711,2685,2639,2556,2453,2359,2278,2194,2098,1997,1904,1826,1763,1712,1667,1624,1583,1546,1510,1465,1416,
+1371,1333,1302,1284,1293,1325,1344,1318,1256,1198,1170,1159,1137,1097,1054,1020,994,968,935,897,858,
+826,804,789,774,756,739,723,708,694,683,673,658,635,609,583,553,517,482,463,465,474,
+472,447,404,363,337,323,312,301,292,289,292,301,318,335,340,338,366,456,579,644,581,
+413,230,110,53,7,-59,-134,-188,-212,-230,-266,-316,-354,-369,-373,-390,-425,-464,-495,-518,-532,
+-540,-550,-570,-594,-604,-592,-588,-625,-691,-741,-746,-731,-737,-775,-817,-838,-841,-838,-838,-839,-842,
+-851,-867,-888,-910,-931,-950,-967,-985,-1004,-1022,-1037,-1052,-1067,-1081,-1090,-1096,-1102,-1111,-1118,-1123,-1124,
+-1123,-1120,-1119,-1120,-1119,-1111,-1100,-1092,-1089,-1088,-1083,-1076,-1072,-1069,-1065,-1060,-1057,-1056,-1055,-1051,-1041,
+-1026,-1009,-998,-992,-985,-972,-956,-946,-941,-932,-914,-895,-878,-861,-840,-821,-807,-796,-780,-757,-736,
+-719,-704,-686,-670,-659,-647,-631,-611,-595,-584,-571,-554,-534,-517,-502,-486,-471,-457,-443,-428,-411,
+-396,-381,-365,-351,-338,-326,-313,-300,-291,-284,-274,-262,-251,-244,-238,-230,-220,-213,-211,-208,-206,
+-206,-207,-206,-204,-204,-208,-212,-214,-216,-223,-232,-237,-237,-240,-249,-257,-261,-264,-270,-279,-287,
+-294,-300,-306,-310,-312,-316,-325,-340,-357,-374,-383,-383,-378,-379,-390,-406,-418,-427,-437,-452,-467,
+-478,-487,-497,-508,-516,-517,-518,-524,-535,-547,-552,-551,-548,-550,-554,-556,-555,-552,-551,-550,-551,
+-553,-554,-551,-542,-531,-524,-520,-516,-510,-506,-504,-499,-490,-481,-475,-470,-463,-455,-448,-441,-431,
+-416,-402,-392,-382,-371,-359,-349,-340,-330,-314,-295,-276,-260,-247,-234,-223,-211,-197,-180,-160,-142,
+-125,-109,-92,-74,-55,-32,-3,29,62,94,130,166,200,233,269,314,362,405,444,486,538,
+596,654,712,773,838,907,977,1041,1095,1142,1191,1246,1303,1354,1400,1444,1486,1524,1561,1597,1627,
+1646,1659,1675,1691,1689,1645,1552,1427,1310,1249,1280,1399,1577,1788,2032,2312,2599,2842,3021,3178,3384,
+3672,4002,4283,4438,4465,4434,4424,4452,4476,4471,4465,4496,4549,4560,4496,4389,4285,4196,4104,3996,3866,
+3698,3483,3243,3020,2830,2650,2462,2291,2176,2130,2131,2160,2204,2242,2246,2217,2186,2173,2158,2105,2009,
+1895,1783,1671,1556,1452,1372,1309,1247,1180,1106,1020,920,813,715,625,531,427,326,239,168,102,
+35,-37,-118,-197,-256,-290,-321,-372,-442,-507,-558,-606,-661,-712,-744,-764,-797,-854,-932,-1025,-1129,
+-1230,-1307,-1351,-1367,-1361,-1325,-1263,-1205,-1181,-1198,-1230,-1251,-1255,-1252,-1253,-1264,-1277,-1273,-1241,-1194,-1154,
+-1130,-1112,-1092,-1079,-1079,-1076,-1050,-1009,-982,-985,-1005,-1022,-1020,-997,-959,-923,-903,-896,-876,-831,-777,
+-741,-720,-695,-673,-697,-800,-946,-1053,-1049,-934,-778,-668,-659,-735,-831,-887,-887,-858,-826,-801,-775,
+-749,-727,-709,-691,-676,-666,-662,-655,-642,-627,-616,-608,-599,-589,-586,-593,-607,-622,-633,-645,-658,
+-674,-687,-699,-711,-723,-731,-735,-736,-737,-736,-731,-724,-715,-702,-681,-656,-633,-612,-586,-551,-508,
+-459,-405,-347,-293,-250,-219,-191,-164,-140,-118,-91,-56,-15,29,76,126,177,224,269,313,356,
+394,427,460,494,527,558,590,622,651,675,700,732,768,796,814,829,850,878,906,931,953,
+973,989,1002,1015,1032,1052,1072,1089,1104,1123,1146,1168,1184,1197,1213,1234,1254,1266,1273,1276,1279,
+1278,1274,1270,1270,1272,1275,1275,1274,1274,1276,1281,1288,1294,1299,1305,1314,1329,1349,1375,1403,1428,
+1449,1469,1487,1499,1503,1505,1510,1519,1527,1550,1559,1562,1562,1563,1563,1563,1563,1565,1567,1570,1573,
+1575,1574,1572,1572,1577,1586,1598,1611,1627,1646,1669,1691,1710,1724,1735,1746,1755,1758,1756,1752,1748,
+1744,1741,1742,1748,1765,1791,1819,1838,1850,1876,1944,2046,2137,2181,2193,2224,2295,2377,2433,2461,2490,
+2527,2556,2557,2535,2498,2446,2376,2297,2224,2161,2105,2057,2020,1995,1976,1960,1947,1933,1917,1900,1887,
+1872,1849,1816,1784,1758,1727,1675,1599,1509,1418,1338,1280,1249,1235,1217,1184,1144,1110,1086,1066,1038,
+996,946,906,897,914,927,903,840,758,673,583,487,405,360,350,347,325,283,237,206,200,
+216,247,281,309,329,351,378,403,402,359,283,197,111,1,-167,-388,-597,-730,-778,-792,-821,
+-875,-926,-959,-978,-993,-1006,-1014,-1014,-1002,-971,-925,-890,-898,-964,-1067,-1173,-1254,-1305,-1334,-1357,-1382,
+-1410,-1438,-1457,-1466,-1475,-1498,-1530,-1537,-1489,-1401,-1331,-1325,-1359,-1365,-1306,-1211,-1136,-1102,-1084,-1055,-1009,
+-951,-883,-811,-752,-715,-685,-633,-554,-476,-435,-440,-472,-504,-528,-555,-609,-703,-838,-1003,-1179,-1338,
+-1452,-1510,-1527,-1530,-1540,-1559,-1576,-1582,-1576,-1566,-1561,-1565,-1574,-1581,-1582,-1578,-1570,-1562,-1556,-1557,-1563,
+-1571,-1584,-1608,-1641,-1669,-1683,-1688,-1694,-1696,-1687,-1676,-1682,-1697,-1685,-1631,-1570,-1555,-1596,-1649,-1670,-1659,
+-1644,-1648,-1670,-1696,-1716,-1729,-1742,-1764,-1798,-1831,-1855,-1874,-1898,-1928,-1951,-1958,-1955,-1957,-1970,-1993,-2021,
+-2053,-2085,-2117,-2153,-2195,-2239,-2281,-2322,-2370,-2428,-2492,-2557,-2622,-2690,-2762,-2833,-2897,-2951,-3002,-3054,-3112,
+-3173,-3232,-3286,-3341,-3400,-3460,-3519,-3574,-3631,-3694,-3759,-3820,-3869,-3907,-3936,-3961,-3983,-4007,-4036,-4074,-4117,
+-4159,-4198,-4236,-4273,-4304,-4333,-4369,-4422,-4482,-4525,-4547,-4563,-4594,-4642,-4693,-4739,-4778,-4816,-4854,-4894,-4937,
+-4980,-5020,-5058,-5097,-5137,-5173,-5204,-5236,-5267,-5292,-5300,-5289,-5262,-5237,-5235,-5268,-5323,-5368,-5378,-5347,-5285,
+-5195,-5082,-4959,-4855,-4811,-4858,-4993,-5166,-5299,-5346,-5329,-5301,-5285,-5263,-5222,-5196,-5220,-5272,-5293,-5261,-5213,
+-5189,-5176,-5133,-5052,-4970,-4929,-4942,-4999,-5072,-5123,-5124,-5079,-5025,-4989,-4965,-4933,-4893,-4861,-4836,-4800,-4745,
+-4693,-4666,-4657,-4640,-4604,-4562,-4531,-4509,-4480,-4435,-4379,-4326,-4288,-4266,-4256,-4246,-4224,-4185,-4133,-4073,-4008,
+-3944,-3882,-3821,-3758,-3694,-3632,-3575,-3520,-3465,-3408,-3354,-3301,-3248,-3192,-3137,-3084,-3031,-2972,-2907,-2843,-2784,
+-2730,-2680,-2629,-2574,-2510,-2433,-2352,-2274,-2200,-2126,-2054,-1991,-1938,-1885,-1824,-1762,-1710,-1665,-1606,-1518,-1412,
+-1317,-1250,-1204,-1165,-1125,-1087,-1049,-1001,-941,-874,-805,-737,-675,-620,-567,-502,-411,-289,-140,29,202,
+355,475,569,651,729,794,846,903,980,1070,1153,1222,1285,1350,1417,1487,1568,1660,1748,1817,1870,
+1923,1978,2031,2079,2130,2183,2233,2280,2335,2407,2487,2561,2636,2726,2821,2884,2881,2826,2770,2758,2801,
+2881,2978,3072,3145,3187,3204,3208,3210,3209,3209,3219,3249,3296,3351,3406,3458,3503,3541,3578,3627,3690,
+3756,3813,3863,3916,3967,4008,4047,4102,4179,4257,4313,4350,4385,4433,4489,4545,4598,4650,4701,4761,4831,
+4901,4949,4964,4966,4974,4987,4992,4994,5015,5069,5145,5220,5284,5337,5383,5431,5494,5578,5673,5758,5828,
+5891,5953,5999,6010,5991,5966,5959,5965,5955,5905,5827,5763,5745,5773,5816,5846,5860,5873,5900,5940,5980,
+6002,6004,5998,5999,6005,6003,5990,5977,5972,5973,5966,5950,5932,5917,5911,5918,5938,5961,5979,5997,6021,
+6042,6042,6019,5994,5973,5949,5918,5891,5864,5815,5747,5721,5792,5916,5976,5912,5794,5741,5781,5848,5878,
+5866,5832,5786,5740,5727,5773,5856,5942,6017,6085,6125,6107,6038,5978,5972,6001,6015,5998,5983,5998,6028,
+6039,6021,5994,5970,5905,5747,5528,5386,5466,5766,6124,6370,6475,6530,6606,6679,6699,6674,6649,6643,6636,
+6613,6587,6570,6551,6524,6495,6472,6447,6408,6363,6326,6300,6272,6232,6186,6139,6092,6048,6012,5979,5934,
+5871,5800,5745,5720,5720,5722,5700,5634,5533,5424,5330,5253,5182,5112,5049,5002,4979,4985,5018,5056,5071,
+5049,5004,4961,4932,4917,4911,4910,4909,4907,4902,4894,4878,4856,4839,4836,4829,4797,4739,4677,4586,4373,
+3946,3344,2766,2434,2416,2592,2784,2899,2942,2943,2905,2833,2760,2720,2703,2668,2591,2491,2395,2310,2220,
+2116,2007,1908,1828,1765,1712,1659,1610,1568,1534,1499,1458,1423,1401,1383,1355,1329,1332,1363,1379,1341,
+1262,1193,1160,1149,1132,1101,1068,1037,1003,965,926,889,852,818,795,784,778,769,757,742,725,
+708,694,679,657,626,595,570,546,511,469,445,454,479,486,455,405,367,351,344,329,305,
+285,274,267,268,280,297,298,282,285,347,448,512,473,344,198,98,42,-14,-94,-180,-240,
+-262,-270,-292,-334,-376,-403,-416,-428,-448,-474,-504,-534,-557,-570,-586,-618,-653,-660,-631,-609,-642,
+-715,-767,-761,-726,-721,-760,-812,-843,-853,-860,-868,-871,-867,-869,-883,-905,-925,-941,-953,-965,-979,
+-995,-1012,-1029,-1046,-1061,-1074,-1085,-1095,-1104,-1113,-1119,-1122,-1123,-1122,-1122,-1123,-1124,-1121,-1112,-1101,-1093,
+-1090,-1087,-1082,-1075,-1070,-1067,-1065,-1062,-1060,-1058,-1057,-1056,-1050,-1036,-1020,-1009,-1003,-996,-982,-966,-955,
+-950,-943,-928,-910,-893,-873,-848,-826,-813,-803,-787,-764,-743,-726,-709,-690,-672,-660,-650,-635,-616,
+-599,-586,-571,-552,-533,-517,-502,-487,-471,-456,-441,-425,-411,-396,-381,-364,-347,-334,-323,-310,-298,
+-287,-278,-267,-255,-246,-241,-235,-225,-216,-209,-206,-204,-202,-204,-204,-202,-198,-199,-205,-209,-210,
+-212,-220,-228,-231,-231,-235,-245,-255,-261,-266,-273,-281,-285,-287,-292,-302,-312,-321,-328,-334,-341,
+-347,-354,-360,-364,-371,-382,-397,-409,-417,-423,-432,-444,-456,-467,-478,-491,-503,-510,-513,-514,-517,
+-525,-533,-535,-529,-525,-528,-536,-542,-544,-543,-542,-540,-535,-532,-530,-526,-515,-504,-498,-497,-493,
+-485,-480,-481,-480,-472,-458,-447,-442,-438,-432,-424,-415,-403,-389,-374,-363,-353,-342,-331,-322,-312,
+-300,-286,-272,-258,-242,-226,-212,-202,-192,-179,-162,-143,-126,-109,-90,-69,-49,-28,-5,23,54,
+83,112,146,184,220,251,283,323,370,415,454,495,544,600,660,721,781,842,904,969,1030,
+1080,1117,1155,1205,1268,1332,1389,1435,1474,1510,1548,1588,1625,1653,1674,1697,1726,1753,1764,1739,1669,
+1555,1430,1344,1337,1421,1582,1807,2076,2348,2575,2748,2912,3139,3458,3829,4163,4377,4453,4440,4416,4422,
+4437,4431,4413,4424,4471,4504,4469,4366,4241,4142,4074,4010,3909,3752,3556,3364,3200,3040,2835,2580,2331,
+2161,2088,2084,2114,2160,2203,2220,2206,2185,2178,2174,2142,2066,1955,1829,1701,1589,1507,1450,1395,1327,
+1248,1169,1086,992,889,788,693,595,488,383,288,202,122,46,-29,-110,-191,-256,-299,-338,-397,
+-473,-548,-610,-669,-728,-773,-794,-799,-812,-846,-905,-994,-1110,-1232,-1325,-1375,-1387,-1368,-1317,-1240,-1170,
+-1140,-1147,-1164,-1165,-1158,-1160,-1178,-1201,-1215,-1210,-1186,-1155,-1125,-1096,-1066,-1042,-1038,-1054,-1067,-1058,-1034,
+-1013,-1004,-1003,-1007,-1013,-1013,-992,-950,-902,-862,-830,-796,-756,-711,-659,-607,-590,-649,-792,-963,-1077,
+-1070,-949,-783,-667,-659,-741,-839,-888,-878,-840,-808,-785,-763,-740,-718,-698,-676,-657,-644,-637,-629,
+-617,-603,-593,-586,-578,-571,-568,-573,-586,-602,-615,-627,-641,-658,-675,-689,-701,-714,-726,-735,-740,
+-740,-737,-729,-720,-709,-696,-678,-656,-632,-609,-584,-551,-511,-467,-417,-362,-307,-261,-224,-193,-166,
+-142,-119,-92,-57,-18,22,65,112,161,206,250,296,341,380,414,447,483,519,550,581,613,
+643,667,690,719,753,785,806,823,846,880,919,952,977,996,1011,1024,1035,1048,1066,1088,1106,
+1120,1137,1159,1184,1202,1214,1226,1243,1261,1271,1272,1271,1271,1271,1269,1266,1265,1266,1269,1272,1273,
+1273,1276,1283,1292,1300,1305,1312,1324,1340,1361,1386,1415,1444,1467,1484,1496,1505,1509,1513,1521,1535,
+1550,1577,1589,1593,1593,1589,1586,1582,1582,1583,1585,1588,1591,1593,1596,1598,1600,1605,1613,1625,1640,
+1655,1673,1695,1719,1739,1753,1764,1776,1786,1790,1791,1792,1792,1786,1776,1772,1782,1802,1823,1837,1843,
+1848,1875,1946,2055,2162,2227,2251,2275,2328,2394,2441,2470,2502,2547,2584,2591,2566,2519,2453,2374,2293,
+2222,2162,2110,2066,2034,2014,2001,1991,1984,1977,1963,1946,1931,1920,1905,1882,1858,1834,1796,1732,1647,
+1554,1463,1380,1317,1285,1276,1267,1236,1189,1145,1117,1100,1084,1063,1034,1007,995,1001,1002,969,895,
+798,698,601,514,454,433,436,433,405,362,326,308,308,318,333,349,364,383,411,444,464,
+455,410,348,292,241,157,0,-223,-445,-594,-660,-693,-742,-810,-865,-895,-913,-935,-957,-966,-953,
+-925,-893,-872,-877,-921,-1000,-1094,-1178,-1241,-1285,-1322,-1357,-1386,-1405,-1414,-1419,-1419,-1418,-1422,-1435,-1437,
+-1398,-1317,-1243,-1227,-1264,-1293,-1268,-1198,-1129,-1084,-1054,-1022,-977,-910,-816,-705,-608,-547,-510,-467,-408,
+-354,-326,-327,-352,-394,-452,-518,-589,-682,-817,-995,-1185,-1338,-1426,-1458,-1466,-1476,-1495,-1513,-1523,-1526,
+-1524,-1521,-1518,-1518,-1521,-1521,-1519,-1515,-1512,-1507,-1503,-1503,-1511,-1529,-1556,-1591,-1623,-1639,-1636,-1623,-1612,
+-1595,-1557,-1504,-1470,-1479,-1517,-1549,-1560,-1562,-1572,-1584,-1591,-1591,-1597,-1613,-1633,-1648,-1651,-1648,-1648,-1665,
+-1698,-1736,-1766,-1788,-1811,-1840,-1863,-1870,-1861,-1849,-1848,-1866,-1900,-1943,-1982,-2017,-2053,-2095,-2139,-2182,-2227,
+-2277,-2332,-2388,-2445,-2509,-2579,-2651,-2720,-2782,-2839,-2893,-2950,-3013,-3078,-3138,-3191,-3242,-3297,-3353,-3407,-3461,
+-3521,-3590,-3660,-3720,-3763,-3796,-3823,-3849,-3875,-3905,-3942,-3985,-4028,-4066,-4103,-4145,-4189,-4226,-4258,-4297,-4350,
+-4406,-4444,-4461,-4477,-4512,-4563,-4615,-4657,-4692,-4727,-4765,-4807,-4853,-4897,-4940,-4981,-5023,-5064,-5099,-5129,-5157,
+-5183,-5198,-5197,-5182,-5166,-5163,-5185,-5232,-5289,-5330,-5332,-5291,-5217,-5119,-5001,-4880,-4786,-4761,-4826,-4968,-5133,
+-5252,-5291,-5274,-5249,-5234,-5213,-5179,-5161,-5187,-5237,-5257,-5229,-5184,-5155,-5129,-5072,-4987,-4921,-4913,-4962,-5032,
+-5086,-5101,-5075,-5027,-4987,-4968,-4955,-4929,-4892,-4860,-4834,-4799,-4748,-4701,-4677,-4674,-4666,-4638,-4597,-4562,-4539,
+-4516,-4480,-4426,-4368,-4322,-4296,-4282,-4263,-4231,-4190,-4144,-4092,-4032,-3968,-3905,-3846,-3787,-3725,-3665,-3610,-3557,
+-3501,-3442,-3384,-3330,-3276,-3221,-3167,-3117,-3068,-3013,-2953,-2892,-2836,-2785,-2737,-2688,-2635,-2571,-2493,-2407,-2322,
+-2242,-2166,-2094,-2033,-1986,-1945,-1896,-1838,-1783,-1734,-1676,-1593,-1493,-1400,-1332,-1284,-1244,-1209,-1181,-1151,-1105,
+-1038,-959,-877,-796,-717,-644,-575,-494,-384,-244,-88,66,208,329,429,511,591,673,750,816,878,
+948,1025,1097,1158,1214,1272,1334,1404,1485,1572,1649,1707,1755,1802,1851,1894,1934,1983,2045,2113,2184,
+2261,2340,2406,2457,2512,2592,2679,2730,2722,2684,2667,2697,2759,2831,2908,2988,3060,3105,3121,3123,3125,
+3126,3124,3123,3140,3182,3240,3299,3354,3404,3455,3509,3567,3626,3680,3728,3774,3824,3873,3918,3966,4028,
+4103,4175,4231,4277,4327,4385,4437,4478,4514,4556,4609,4678,4758,4834,4886,4911,4923,4936,4946,4943,4937,
+4953,5004,5079,5155,5221,5280,5337,5397,5465,5547,5639,5728,5805,5868,5920,5956,5969,5956,5933,5921,5928,
+5933,5909,5853,5790,5756,5757,5773,5784,5787,5796,5819,5853,5882,5896,5894,5887,5885,5887,5886,5884,5888,
+5898,5901,5890,5871,5857,5849,5846,5852,5876,5916,5958,5993,6018,6025,6011,5984,5959,5938,5906,5865,5830,
+5800,5749,5683,5666,5750,5883,5938,5859,5733,5682,5729,5799,5826,5816,5797,5772,5738,5721,5748,5817,5905,
+6006,6117,6194,6182,6086,5985,5951,5980,6010,6006,5991,5999,6025,6036,6017,5990,5967,5906,5750,5513,5324,
+5338,5583,5925,6203,6368,6483,6597,6681,6693,6655,6626,6631,6640,6625,6596,6572,6553,6526,6496,6471,6448,
+6414,6369,6328,6297,6271,6236,6191,6140,6090,6049,6021,5991,5944,5875,5797,5734,5696,5681,5669,5640,5575,
+5478,5366,5262,5174,5103,5053,5025,5011,5001,5000,5021,5059,5088,5083,5045,4998,4962,4944,4941,4945,4949,
+4949,4943,4931,4913,4895,4888,4889,4879,4836,4765,4672,4516,4210,3717,3142,2692,2516,2578,2720,2821,2872,
+2918,2955,2942,2870,2788,2747,2735,2704,2627,2525,2425,2330,2228,2113,1999,1901,1826,1767,1712,1654,1597,
+1552,1517,1479,1440,1416,1411,1404,1374,1334,1321,1338,1343,1303,1231,1173,1149,1141,1125,1102,1080,1054,
+1018,978,948,921,884,836,795,776,774,777,774,764,744,719,695,672,644,609,573,548,528,
+498,454,423,425,451,460,431,383,353,354,363,355,328,296,267,240,221,219,227,224,199,
+180,201,258,300,279,200,109,42,-6,-62,-136,-214,-270,-295,-302,-313,-342,-382,-423,-455,-479,
+-493,-505,-523,-548,-568,-580,-598,-640,-690,-707,-680,-650,-670,-732,-780,-775,-742,-737,-772,-818,-846,
+-862,-881,-900,-906,-900,-899,-910,-930,-946,-956,-964,-971,-979,-990,-1006,-1026,-1047,-1063,-1075,-1084,-1093,
+-1102,-1110,-1115,-1118,-1121,-1122,-1123,-1124,-1124,-1120,-1112,-1104,-1099,-1096,-1092,-1085,-1077,-1070,-1066,-1063,-1060,
+-1056,-1053,-1050,-1050,-1048,-1040,-1027,-1014,-1006,-997,-982,-965,-953,-948,-941,-930,-915,-897,-876,-850,-828,
+-815,-805,-790,-768,-748,-732,-715,-694,-675,-661,-650,-635,-618,-601,-586,-569,-550,-533,-519,-506,-491,
+-474,-457,-441,-426,-412,-399,-383,-366,-350,-337,-325,-312,-299,-286,-274,-261,-250,-243,-239,-234,-224,
+-214,-208,-203,-200,-199,-202,-202,-198,-194,-195,-201,-205,-206,-209,-215,-221,-223,-225,-230,-240,-249,
+-255,-262,-272,-280,-283,-285,-289,-298,-308,-319,-329,-336,-339,-340,-343,-351,-362,-376,-390,-400,-405,
+-410,-419,-430,-439,-446,-456,-470,-484,-495,-500,-503,-504,-506,-510,-515,-515,-510,-507,-512,-523,-531,
+-532,-530,-527,-522,-515,-509,-506,-500,-486,-473,-469,-471,-468,-459,-451,-452,-454,-448,-435,-424,-419,
+-416,-411,-403,-393,-380,-364,-348,-335,-323,-314,-305,-296,-284,-270,-255,-244,-234,-222,-208,-194,-184,
+-173,-158,-141,-123,-107,-89,-67,-41,-15,6,28,54,81,108,134,165,201,237,269,301,337,
+379,422,464,509,558,609,662,720,780,841,900,958,1015,1066,1106,1142,1188,1247,1312,1372,1422,
+1464,1499,1534,1571,1613,1653,1687,1715,1743,1775,1811,1841,1838,1773,1647,1499,1386,1356,1429,1604,1851,
+2117,2347,2531,2716,2968,3307,3695,4053,4308,4428,4438,4406,4392,4403,4410,4400,4399,4430,4474,4473,4399,
+4277,4158,4067,3983,3867,3705,3526,3373,3251,3111,2897,2612,2335,2149,2076,2075,2100,2130,2156,2167,2159,
+2146,2145,2149,2135,2082,1990,1869,1740,1631,1560,1515,1468,1400,1319,1237,1155,1063,963,862,763,659,
+550,444,344,245,145,51,-35,-119,-200,-269,-321,-368,-428,-501,-573,-640,-707,-774,-818,-828,-817,
+-812,-831,-881,-967,-1087,-1215,-1314,-1361,-1365,-1336,-1278,-1199,-1127,-1089,-1082,-1081,-1071,-1065,-1079,-1113,-1147,
+-1165,-1166,-1158,-1143,-1117,-1078,-1036,-1013,-1022,-1052,-1079,-1086,-1080,-1071,-1058,-1039,-1023,-1022,-1027,-1014,-969,
+-902,-837,-784,-741,-699,-652,-603,-572,-594,-688,-837,-986,-1074,-1069,-980,-857,-767,-755,-806,-862,-875,
+-847,-809,-783,-767,-748,-725,-702,-680,-655,-632,-615,-605,-598,-588,-577,-567,-559,-555,-554,-554,-557,
+-567,-581,-597,-612,-627,-644,-662,-677,-690,-706,-723,-736,-742,-743,-742,-737,-728,-718,-706,-691,-670,
+-645,-618,-589,-555,-516,-476,-432,-383,-331,-281,-240,-205,-176,-148,-120,-89,-54,-18,17,57,102,
+149,194,238,285,331,371,406,442,481,518,550,578,606,633,657,680,707,742,776,804,827,
+854,894,938,977,1004,1023,1040,1055,1064,1071,1083,1102,1122,1138,1153,1173,1196,1215,1227,1238,1250,
+1261,1265,1263,1261,1261,1262,1261,1258,1256,1256,1259,1265,1271,1275,1278,1282,1291,1300,1309,1320,1336,
+1355,1376,1400,1428,1458,1482,1498,1508,1517,1526,1534,1546,1561,1577,1604,1611,1613,1611,1606,1601,1598,
+1598,1601,1605,1609,1612,1615,1619,1624,1628,1630,1637,1650,1668,1684,1700,1720,1745,1770,1788,1803,1815,
+1825,1828,1829,1834,1838,1834,1821,1816,1827,1843,1850,1846,1843,1856,1899,1985,2107,2230,2310,2337,2341,
+2359,2394,2429,2461,2505,2560,2603,2611,2583,2531,2463,2386,2309,2242,2185,2136,2097,2074,2062,2052,2041,
+2033,2027,2018,2004,1990,1979,1965,1946,1925,1901,1858,1788,1701,1613,1525,1438,1364,1325,1320,1318,1291,
+1241,1193,1163,1148,1138,1127,1113,1095,1077,1065,1049,1013,948,863,772,685,611,561,535,518,494,
+459,427,410,406,408,413,418,424,431,446,470,494,497,468,413,351,303,262,191,51,-152,
+-357,-501,-573,-619,-679,-748,-799,-823,-843,-871,-898,-902,-876,-836,-806,-806,-847,-925,-1018,-1104,-1167,
+-1211,-1250,-1295,-1340,-1372,-1383,-1381,-1378,-1375,-1364,-1348,-1339,-1332,-1301,-1234,-1163,-1136,-1164,-1205,-1209,-1170,
+-1114,-1063,-1022,-986,-947,-881,-768,-625,-498,-419,-380,-346,-303,-262,-234,-225,-242,-302,-400,-506,-597,
+-687,-814,-991,-1179,-1318,-1384,-1399,-1407,-1426,-1448,-1461,-1465,-1467,-1472,-1473,-1469,-1462,-1457,-1456,-1454,-1451,
+-1450,-1450,-1450,-1453,-1465,-1492,-1531,-1573,-1599,-1594,-1559,-1510,-1468,-1435,-1396,-1345,-1302,-1294,-1328,-1385,-1433,
+-1459,-1469,-1476,-1492,-1519,-1548,-1571,-1583,-1587,-1587,-1585,-1586,-1599,-1625,-1658,-1684,-1699,-1711,-1728,-1746,-1758,
+-1755,-1744,-1738,-1754,-1794,-1844,-1888,-1923,-1959,-1999,-2042,-2087,-2135,-2186,-2237,-2286,-2338,-2401,-2472,-2542,-2608,
+-2669,-2730,-2791,-2853,-2918,-2985,-3045,-3096,-3142,-3189,-3240,-3292,-3348,-3413,-3486,-3555,-3608,-3645,-3677,-3710,-3745,
+-3779,-3814,-3854,-3898,-3941,-3980,-4019,-4064,-4111,-4152,-4189,-4230,-4281,-4328,-4359,-4375,-4395,-4434,-4486,-4535,-4575,
+-4609,-4642,-4680,-4724,-4773,-4823,-4868,-4908,-4948,-4987,-5021,-5048,-5071,-5088,-5093,-5086,-5077,-5080,-5103,-5146,-5199,
+-5249,-5276,-5267,-5218,-5137,-5032,-4914,-4803,-4732,-4733,-4816,-4957,-5102,-5198,-5224,-5207,-5187,-5179,-5166,-5142,-5132,
+-5158,-5201,-5218,-5190,-5145,-5107,-5069,-5007,-4933,-4893,-4913,-4977,-5039,-5067,-5057,-5022,-4981,-4952,-4942,-4935,-4915,
+-4883,-4851,-4822,-4787,-4742,-4702,-4685,-4690,-4693,-4672,-4629,-4586,-4558,-4541,-4516,-4468,-4407,-4356,-4326,-4307,-4280,
+-4239,-4194,-4152,-4109,-4054,-3991,-3929,-3872,-3815,-3754,-3693,-3636,-3582,-3526,-3468,-3410,-3357,-3307,-3257,-3205,-3152,
+-3098,-3044,-2989,-2934,-2881,-2830,-2780,-2730,-2676,-2615,-2543,-2460,-2375,-2292,-2212,-2141,-2087,-2054,-2030,-1995,-1940,
+-1877,-1816,-1749,-1661,-1555,-1456,-1386,-1343,-1315,-1295,-1283,-1269,-1230,-1155,-1053,-943,-835,-731,-635,-545,-450,
+-336,-204,-70,52,163,266,362,453,544,639,733,816,887,951,1011,1065,1114,1160,1210,1267,1333,
+1407,1482,1545,1596,1645,1702,1759,1805,1839,1876,1926,1992,2072,2163,2248,2308,2345,2388,2459,2537,2580,
+2575,2560,2581,2642,2715,2778,2839,2910,2979,3022,3033,3030,3031,3034,3029,3020,3028,3066,3128,3194,3252,
+3307,3368,3436,3503,3560,3607,3649,3693,3740,3788,3836,3887,3946,4007,4063,4115,4175,4246,4315,4362,4388,
+4412,4452,4517,4600,4687,4762,4814,4845,4868,4888,4896,4888,4878,4892,4941,5013,5087,5157,5227,5302,5377,
+5449,5524,5608,5700,5785,5852,5896,5922,5934,5929,5907,5886,5883,5895,5895,5866,5819,5781,5768,5769,5769,
+5767,5771,5786,5808,5825,5831,5829,5823,5817,5814,5814,5825,5850,5874,5876,5852,5820,5800,5794,5791,5790,
+5805,5840,5889,5935,5965,5970,5953,5927,5906,5887,5855,5817,5789,5762,5710,5642,5631,5724,5858,5899,5802,
+5666,5622,5684,5761,5784,5769,5753,5741,5722,5714,5737,5780,5833,5911,6030,6145,6175,6093,5976,5923,5953,
+6008,6032,6027,6025,6035,6034,6011,5982,5957,5901,5754,5517,5299,5256,5450,5783,6098,6317,6468,6587,6663,
+6671,6635,6611,6621,6635,6625,6600,6577,6557,6527,6491,6462,6440,6415,6380,6341,6306,6272,6233,6188,6138,
+6090,6051,6022,5992,5945,5881,5815,5759,5716,5678,5639,5594,5535,5456,5358,5249,5141,5054,5009,5009,5028,
+5035,5028,5030,5059,5097,5108,5077,5025,4982,4965,4968,4979,4986,4987,4984,4977,4962,4944,4931,4926,4915,
+4881,4814,4690,4450,4033,3473,2939,2634,2618,2758,2869,2882,2866,2895,2946,2948,2886,2818,2789,2780,2738,
+2647,2534,2428,2327,2217,2097,1983,1890,1823,1771,1719,1658,1597,1547,1505,1459,1413,1386,1382,1376,1344,
+1297,1271,1271,1266,1230,1181,1151,1142,1134,1115,1095,1081,1061,1030,1002,993,986,953,892,831,796,
+786,784,780,770,749,719,685,654,625,589,552,525,510,488,450,413,400,411,414,385,339,
+313,320,341,347,330,300,265,225,188,167,162,156,134,109,103,117,127,109,66,17,-28,
+-73,-123,-178,-231,-278,-312,-332,-345,-363,-393,-437,-484,-522,-541,-546,-551,-564,-577,-585,-601,-643,
+-701,-736,-728,-703,-705,-744,-781,-788,-781,-790,-821,-850,-866,-879,-901,-922,-932,-931,-934,-946,-958,
+-965,-968,-973,-979,-983,-989,-1003,-1025,-1048,-1064,-1073,-1078,-1084,-1092,-1101,-1108,-1115,-1121,-1125,-1128,-1128,
+-1126,-1121,-1114,-1110,-1108,-1106,-1101,-1093,-1086,-1079,-1071,-1064,-1058,-1053,-1047,-1042,-1040,-1041,-1038,-1030,-1017,
+-1005,-992,-977,-961,-948,-939,-931,-921,-909,-893,-873,-850,-832,-818,-806,-789,-767,-748,-733,-717,-697,
+-678,-660,-645,-629,-613,-598,-582,-564,-547,-533,-520,-508,-493,-477,-461,-444,-428,-414,-400,-385,-368,
+-353,-341,-327,-313,-299,-287,-275,-261,-249,-243,-240,-235,-226,-217,-210,-203,-199,-198,-201,-202,-198,
+-193,-194,-199,-202,-203,-206,-212,-217,-219,-222,-229,-237,-243,-249,-256,-266,-274,-280,-285,-292,-297,
+-301,-307,-316,-326,-333,-338,-345,-354,-366,-379,-389,-393,-396,-403,-416,-430,-435,-437,-444,-458,-472,
+-479,-482,-484,-487,-489,-491,-496,-498,-497,-497,-504,-513,-518,-516,-511,-506,-500,-492,-488,-487,-480,
+-464,-448,-444,-449,-449,-438,-427,-424,-425,-420,-410,-402,-398,-393,-387,-379,-370,-358,-343,-326,-310,
+-298,-288,-281,-275,-264,-249,-232,-218,-207,-197,-187,-179,-169,-157,-140,-120,-101,-83,-64,-42,-16,
+8,31,52,76,103,131,158,186,218,253,288,322,357,394,434,478,529,581,627,670,718,
+777,841,900,952,1000,1049,1096,1143,1193,1247,1300,1351,1399,1444,1483,1518,1554,1598,1647,1693,1730,
+1759,1787,1823,1869,1909,1909,1844,1717,1562,1430,1378,1448,1636,1888,2133,2348,2570,2855,3216,3610,3972,
+4245,4395,4427,4392,4362,4370,4395,4404,4400,4413,4450,4473,4440,4350,4234,4118,4002,3864,3700,3529,3376,
+3239,3075,2845,2563,2302,2139,2087,2104,2134,2153,2158,2149,2130,2112,2103,2099,2084,2044,1976,1882,1777,
+1682,1614,1569,1522,1459,1382,1301,1216,1124,1027,929,826,714,601,497,397,290,172,54,-50,-143,
+-228,-301,-359,-410,-467,-531,-592,-652,-718,-787,-833,-842,-826,-813,-824,-865,-941,-1051,-1171,-1263,-1305,
+-1303,-1270,-1217,-1148,-1081,-1034,-1010,-994,-982,-985,-1013,-1059,-1101,-1124,-1131,-1130,-1122,-1098,-1059,-1021,-1007,
+-1027,-1064,-1095,-1111,-1118,-1117,-1100,-1066,-1033,-1018,-1013,-997,-953,-888,-820,-758,-701,-643,-586,-552,-571,
+-662,-805,-948,-1041,-1071,-1048,-992,-924,-873,-859,-871,-877,-855,-816,-785,-767,-750,-726,-698,-673,-650,
+-627,-605,-589,-579,-572,-565,-557,-547,-539,-537,-541,-546,-548,-552,-563,-580,-597,-614,-631,-649,-665,
+-681,-699,-718,-732,-739,-742,-744,-745,-740,-732,-722,-709,-689,-663,-634,-602,-565,-525,-484,-444,-401,
+-354,-306,-263,-226,-193,-160,-125,-89,-52,-17,18,56,98,144,190,236,283,328,370,407,445,
+486,526,558,583,606,630,654,678,704,735,767,797,825,857,898,943,984,1014,1038,1060,1079,
+1089,1093,1100,1116,1138,1158,1174,1189,1206,1222,1234,1244,1252,1256,1255,1252,1252,1254,1255,1254,1252,
+1251,1251,1253,1260,1269,1275,1276,1278,1287,1300,1312,1326,1343,1364,1387,1412,1440,1470,1496,1515,1530,
+1544,1559,1572,1584,1595,1604,1625,1626,1625,1621,1616,1612,1610,1611,1616,1622,1627,1631,1634,1639,1646,
+1651,1655,1661,1677,1699,1719,1735,1754,1780,1810,1835,1853,1867,1876,1876,1875,1878,1883,1879,1867,1860,
+1867,1876,1874,1867,1874,1906,1966,2055,2176,2302,2391,2418,2405,2391,2396,2417,2448,2494,2550,2594,2605,
+2583,2540,2484,2419,2353,2293,2239,2191,2157,2140,2134,2127,2115,2104,2100,2095,2085,2070,2052,2029,2004,
+1980,1953,1910,1843,1764,1684,1597,1499,1410,1361,1357,1361,1338,1291,1245,1218,1204,1192,1180,1167,1149,
+1125,1099,1072,1037,987,920,847,779,722,679,640,597,549,509,490,487,488,488,490,497,504,
+510,519,533,541,525,476,401,318,248,192,123,6,-158,-326,-446,-510,-557,-615,-675,-715,-736,
+-760,-793,-814,-803,-766,-728,-716,-746,-820,-922,-1023,-1098,-1141,-1170,-1207,-1257,-1306,-1336,-1344,-1342,-1342,
+-1338,-1315,-1279,-1251,-1238,-1219,-1171,-1105,-1065,-1075,-1112,-1136,-1123,-1078,-1020,-968,-934,-908,-850,-730,-567,
+-421,-334,-296,-267,-227,-184,-150,-134,-156,-236,-364,-497,-601,-694,-824,-1001,-1180,-1300,-1345,-1350,-1358,
+-1379,-1400,-1407,-1406,-1410,-1418,-1420,-1411,-1400,-1396,-1398,-1398,-1395,-1393,-1399,-1406,-1413,-1426,-1456,-1501,-1543,
+-1558,-1530,-1456,-1353,-1249,-1179,-1157,-1175,-1205,-1229,-1247,-1268,-1296,-1323,-1345,-1368,-1404,-1450,-1488,-1502,-1498,
+-1498,-1513,-1538,-1563,-1581,-1597,-1612,-1620,-1619,-1612,-1610,-1619,-1636,-1646,-1646,-1645,-1662,-1702,-1752,-1796,-1833,
+-1869,-1909,-1952,-1995,-2043,-2094,-2143,-2188,-2239,-2302,-2372,-2439,-2499,-2560,-2624,-2690,-2754,-2820,-2886,-2947,-2995,
+-3037,-3080,-3128,-3180,-3238,-3306,-3378,-3441,-3485,-3519,-3557,-3602,-3648,-3689,-3726,-3765,-3809,-3853,-3896,-3939,-3985,
+-4031,-4074,-4116,-4160,-4205,-4243,-4268,-4288,-4316,-4359,-4408,-4454,-4493,-4528,-4562,-4598,-4644,-4698,-4755,-4803,-4840,
+-4873,-4907,-4939,-4964,-4979,-4986,-4984,-4979,-4982,-5007,-5053,-5108,-5159,-5194,-5204,-5182,-5127,-5044,-4939,-4828,-4735,
+-4691,-4718,-4811,-4941,-5061,-5132,-5147,-5131,-5118,-5118,-5115,-5103,-5099,-5122,-5155,-5163,-5131,-5081,-5038,-4998,-4947,
+-4898,-4886,-4924,-4984,-5026,-5032,-5010,-4977,-4944,-4921,-4911,-4908,-4897,-4871,-4837,-4806,-4773,-4737,-4707,-4698,-4710,
+-4721,-4706,-4661,-4609,-4576,-4564,-4547,-4506,-4444,-4388,-4354,-4332,-4301,-4256,-4208,-4167,-4125,-4072,-4011,-3951,-3896,
+-3841,-3781,-3717,-3657,-3600,-3543,-3485,-3428,-3377,-3333,-3289,-3241,-3188,-3132,-3077,-3025,-2974,-2923,-2871,-2817,-2763,
+-2707,-2647,-2579,-2503,-2420,-2337,-2258,-2193,-2151,-2135,-2126,-2101,-2046,-1973,-1898,-1819,-1723,-1610,-1506,-1437,-1402,
+-1384,-1373,-1371,-1365,-1326,-1233,-1095,-944,-804,-683,-576,-479,-386,-287,-183,-82,11,104,203,305,406,
+507,612,717,813,893,957,1007,1049,1084,1119,1158,1204,1261,1326,1390,1443,1489,1542,1611,1686,1747,
+1787,1814,1843,1887,1952,2035,2119,2182,2225,2270,2335,2400,2435,2438,2448,2498,2582,2664,2727,2783,2848,
+2909,2942,2943,2933,2931,2936,2932,2923,2929,2968,3033,3102,3163,3222,3291,3369,3442,3499,3541,3578,3615,
+3654,3696,3741,3791,3842,3887,3930,3985,4062,4152,4228,4270,4288,4311,4361,4443,4538,4625,4692,4740,4777,
+4810,4835,4841,4828,4817,4830,4877,4946,5022,5100,5186,5278,5365,5439,5506,5581,5670,5759,5827,5864,5882,
+5894,5896,5880,5855,5843,5852,5865,5856,5825,5792,5778,5780,5784,5786,5787,5793,5801,5807,5807,5804,5800,
+5798,5798,5804,5821,5853,5883,5883,5847,5797,5763,5751,5747,5739,5736,5751,5785,5826,5857,5866,5854,5839,
+5830,5821,5802,5778,5763,5742,5686,5617,5614,5723,5866,5903,5792,5649,5610,5682,5763,5780,5754,5730,5718,
+5709,5714,5739,5760,5761,5784,5881,6024,6112,6079,5975,5909,5932,6003,6058,6073,6069,6059,6038,6003,5969,
+5942,5894,5767,5548,5324,5243,5391,5707,6044,6297,6456,6559,6620,6636,6623,6614,6619,6621,6608,6589,6576,
+6561,6534,6499,6467,6444,6420,6390,6356,6320,6280,6236,6192,6147,6100,6055,6018,5982,5937,5882,5827,5779,
+5731,5680,5629,5586,5540,5474,5378,5260,5141,5049,5008,5018,5047,5056,5039,5026,5048,5092,5117,5096,5043,
+4998,4986,5000,5017,5022,5020,5020,5023,5018,4997,4968,4946,4933,4914,4857,4704,4381,3858,3237,2736,2539,
+2639,2840,2944,2921,2875,2886,2925,2926,2884,2850,2845,2831,2761,2641,2514,2406,2308,2203,2088,1978,1889,
+1825,1778,1731,1674,1613,1559,1510,1454,1396,1355,1339,1327,1296,1254,1228,1219,1205,1175,1146,1137,1136,
+1122,1097,1079,1071,1057,1030,1015,1026,1040,1021,965,901,857,831,808,782,759,735,703,666,633,
+606,575,540,512,498,486,458,420,393,386,379,351,307,273,267,280,289,286,276,260,235,
+201,170,148,129,107,85,70,60,45,21,-8,-42,-83,-132,-178,-215,-247,-285,-330,-368,-390,
+-403,-422,-457,-504,-549,-576,-584,-585,-589,-596,-601,-612,-644,-696,-743,-761,-754,-750,-761,-781,-798,
+-818,-845,-873,-889,-894,-902,-917,-929,-935,-942,-958,-977,-986,-984,-981,-985,-991,-994,-997,-1006,-1024,
+-1044,-1057,-1064,-1067,-1072,-1079,-1089,-1100,-1112,-1122,-1130,-1135,-1135,-1132,-1128,-1122,-1119,-1116,-1113,-1109,-1105,
+-1102,-1096,-1086,-1074,-1064,-1056,-1049,-1042,-1037,-1038,-1039,-1034,-1022,-1007,-993,-979,-964,-947,-932,-921,-910,
+-898,-884,-867,-849,-834,-820,-804,-783,-763,-746,-732,-716,-697,-678,-659,-641,-624,-608,-592,-576,-559,
+-543,-530,-517,-504,-490,-477,-462,-445,-429,-414,-399,-383,-366,-353,-340,-326,-310,-298,-289,-280,-266,
+-254,-246,-243,-238,-230,-222,-215,-207,-201,-199,-201,-202,-198,-195,-196,-199,-202,-202,-206,-213,-218,
+-222,-226,-233,-239,-243,-247,-254,-261,-266,-272,-282,-292,-297,-297,-298,-304,-314,-325,-335,-345,-353,
+-362,-371,-380,-386,-390,-399,-413,-425,-427,-426,-430,-443,-455,-460,-462,-464,-468,-469,-471,-477,-484,
+-488,-491,-495,-500,-500,-494,-488,-483,-478,-473,-473,-475,-468,-450,-431,-425,-430,-431,-422,-410,-401,
+-396,-389,-382,-377,-375,-370,-361,-353,-345,-334,-320,-305,-290,-276,-264,-257,-252,-247,-234,-216,-196,
+-180,-170,-165,-162,-155,-142,-124,-102,-79,-56,-35,-17,0,19,39,60,84,113,145,176,204,
+235,269,306,344,381,417,454,498,549,602,646,681,720,776,842,904,951,989,1030,1079,1136,
+1193,1245,1288,1327,1368,1413,1459,1500,1542,1588,1640,1690,1735,1771,1803,1835,1874,1921,1966,1980,1930,
+1800,1613,1439,1371,1457,1667,1926,2183,2458,2787,3173,3569,3921,4191,4352,4399,4367,4327,4327,4361,4387,
+4389,4393,4421,4454,4453,4398,4300,4183,4060,3930,3787,3627,3449,3252,3028,2772,2507,2282,2148,2117,2153,
+2201,2225,2217,2187,2150,2115,2088,2059,2020,1969,1912,1850,1786,1723,1669,1621,1572,1512,1440,1359,1271,
+1180,1089,994,885,760,637,533,438,331,201,66,-55,-159,-252,-334,-400,-455,-508,-561,-609,-656,
+-713,-777,-826,-843,-833,-821,-824,-851,-907,-994,-1096,-1180,-1222,-1223,-1196,-1153,-1098,-1039,-988,-950,-926,
+-915,-926,-963,-1016,-1064,-1089,-1092,-1084,-1069,-1048,-1022,-1005,-1013,-1048,-1092,-1123,-1137,-1137,-1121,-1085,-1034,
+-988,-963,-950,-930,-891,-841,-792,-746,-696,-630,-561,-530,-589,-744,-936,-1076,-1116,-1079,-1022,-977,-944,
+-919,-904,-892,-871,-839,-807,-785,-766,-739,-705,-671,-644,-622,-601,-584,-573,-563,-555,-549,-546,-540,
+-532,-529,-535,-543,-545,-546,-554,-569,-586,-603,-620,-639,-657,-673,-689,-707,-720,-728,-731,-735,-738,
+-737,-731,-722,-709,-689,-665,-639,-609,-572,-530,-489,-451,-413,-370,-326,-285,-248,-212,-174,-134,-93,
+-53,-14,23,59,98,142,188,236,283,327,369,409,449,491,530,562,587,608,631,657,683,
+709,734,761,789,817,850,890,934,977,1013,1045,1074,1097,1110,1113,1117,1131,1153,1176,1193,1205,
+1215,1225,1235,1244,1249,1248,1244,1243,1246,1249,1250,1249,1250,1253,1255,1258,1263,1271,1275,1277,1281,
+1292,1308,1321,1333,1349,1372,1399,1426,1454,1483,1511,1535,1555,1572,1590,1605,1616,1622,1625,1637,1637,
+1635,1631,1627,1623,1621,1623,1627,1634,1642,1648,1651,1656,1665,1674,1682,1691,1709,1735,1760,1780,1800,
+1826,1856,1882,1900,1915,1924,1926,1922,1923,1925,1921,1909,1901,1903,1910,1915,1927,1960,2012,2070,2138,
+2229,2339,2428,2461,2446,2419,2409,2417,2436,2469,2511,2548,2566,2562,2543,2511,2466,2415,2365,2320,2278,
+2245,2229,2224,2220,2212,2206,2202,2196,2181,2156,2124,2087,2052,2022,1993,1953,1896,1827,1752,1661,1552,
+1452,1397,1394,1402,1381,1334,1289,1265,1251,1234,1214,1195,1175,1149,1118,1088,1055,1013,958,899,847,
+808,774,732,675,616,576,565,569,571,568,570,581,592,595,595,595,588,558,493,393,277,
+175,104,46,-36,-161,-296,-394,-447,-487,-537,-585,-615,-636,-666,-697,-703,-672,-630,-615,-647,-724,
+-834,-954,-1051,-1105,-1123,-1134,-1163,-1208,-1250,-1276,-1287,-1293,-1298,-1291,-1259,-1214,-1181,-1173,-1169,-1134,-1067,
+-1007,-993,-1023,-1061,-1065,-1023,-955,-897,-873,-866,-822,-701,-528,-374,-287,-248,-213,-160,-101,-58,-47,
+-88,-191,-332,-468,-576,-686,-838,-1026,-1193,-1287,-1310,-1305,-1311,-1331,-1348,-1353,-1352,-1357,-1363,-1361,-1350,
+-1340,-1341,-1345,-1342,-1334,-1333,-1347,-1364,-1373,-1384,-1412,-1458,-1498,-1508,-1474,-1385,-1232,-1039,-883,-852,-963,
+-1138,-1268,-1301,-1275,-1250,-1253,-1275,-1306,-1345,-1387,-1413,-1408,-1386,-1383,-1417,-1476,-1531,-1559,-1562,-1552,-1540,
+-1528,-1516,-1507,-1510,-1528,-1548,-1559,-1565,-1580,-1614,-1659,-1702,-1741,-1781,-1824,-1864,-1905,-1950,-2000,-2048,-2094,
+-2145,-2208,-2275,-2337,-2392,-2451,-2518,-2586,-2651,-2716,-2782,-2842,-2889,-2930,-2972,-3020,-3072,-3132,-3199,-3265,-3320,
+-3361,-3398,-3446,-3502,-3556,-3599,-3636,-3674,-3716,-3763,-3810,-3856,-3901,-3943,-3986,-4032,-4078,-4119,-4151,-4176,-4204,
+-4241,-4285,-4330,-4372,-4410,-4447,-4481,-4517,-4563,-4624,-4687,-4738,-4771,-4798,-4827,-4857,-4878,-4885,-4883,-4881,-4885,
+-4907,-4949,-5005,-5061,-5102,-5121,-5114,-5080,-5021,-4940,-4843,-4745,-4671,-4650,-4693,-4788,-4903,-5002,-5058,-5069,-5058,
+-5050,-5054,-5059,-5054,-5053,-5069,-5090,-5085,-5044,-4989,-4948,-4921,-4895,-4877,-4888,-4931,-4979,-5000,-4990,-4967,-4941,
+-4915,-4894,-4884,-4885,-4880,-4858,-4825,-4792,-4765,-4740,-4720,-4716,-4730,-4743,-4733,-4691,-4640,-4605,-4591,-4577,-4538,
+-4477,-4418,-4379,-4353,-4321,-4277,-4229,-4183,-4136,-4081,-4021,-3964,-3910,-3856,-3796,-3734,-3674,-3617,-3560,-3502,-3446,
+-3394,-3349,-3309,-3267,-3219,-3166,-3115,-3066,-3016,-2964,-2909,-2854,-2799,-2739,-2675,-2606,-2531,-2450,-2369,-2297,-2246,
+-2221,-2217,-2214,-2189,-2129,-2046,-1958,-1868,-1768,-1658,-1559,-1495,-1466,-1453,-1445,-1443,-1434,-1383,-1261,-1081,-891,
+-730,-610,-515,-432,-354,-278,-200,-117,-30,62,162,263,364,465,569,675,775,862,934,989,1029,
+1059,1083,1109,1142,1186,1241,1297,1343,1382,1430,1500,1586,1667,1725,1759,1781,1804,1842,1899,1970,2038,
+2096,2154,2214,2265,2295,2313,2350,2424,2519,2606,2672,2729,2787,2833,2852,2844,2831,2829,2836,2839,2838,
+2850,2890,2953,3019,3078,3139,3212,3294,3371,3429,3471,3505,3536,3567,3601,3643,3692,3737,3774,3814,3875,
+3965,4065,4140,4178,4195,4225,4291,4388,4492,4577,4638,4685,4728,4769,4794,4794,4775,4759,4769,4810,4874,
+4952,5041,5140,5244,5339,5419,5485,5554,5636,5721,5785,5817,5831,5844,5855,5852,5833,5819,5823,5835,5833,
+5811,5786,5776,5783,5796,5803,5804,5804,5806,5808,5804,5797,5794,5803,5821,5839,5858,5881,5901,5896,5853,
+5788,5736,5713,5707,5698,5685,5680,5692,5716,5738,5744,5740,5739,5750,5758,5751,5738,5730,5713,5658,5593,
+5605,5737,5902,5950,5841,5695,5652,5716,5783,5784,5744,5712,5698,5693,5705,5733,5741,5709,5685,5750,5900,
+6034,6056,5982,5910,5909,5969,6037,6079,6092,6079,6044,5995,5952,5924,5884,5780,5588,5368,5250,5333,5600,
+5934,6213,6393,6496,6555,6588,6605,6615,6616,6604,6585,6571,6565,6556,6537,6511,6486,6457,6423,6388,6356,
+6326,6289,6247,6205,6163,6113,6060,6012,5971,5926,5872,5815,5760,5708,5659,5619,5590,5549,5470,5352,5222,
+5114,5048,5026,5035,5051,5048,5025,5009,5030,5079,5116,5106,5060,5020,5015,5038,5060,5062,5052,5050,5061,
+5066,5047,5008,4971,4952,4938,4876,4682,4280,3678,3023,2550,2416,2569,2797,2917,2914,2883,2888,2907,2898,
+2877,2878,2890,2860,2755,2608,2474,2375,2291,2199,2097,1993,1903,1834,1786,1743,1692,1635,1582,1531,1473,
+1409,1354,1321,1299,1272,1242,1224,1213,1193,1163,1140,1133,1126,1104,1076,1062,1059,1046,1019,1005,1020,
+1044,1040,1004,961,929,898,853,801,758,724,688,649,616,592,569,538,508,491,482,463,429,
+395,374,360,337,298,258,232,219,213,211,219,235,244,235,207,169,130,97,73,55,36,
+10,-18,-44,-73,-114,-167,-213,-243,-267,-301,-348,-393,-424,-442,-460,-488,-525,-565,-597,-614,-619,
+-622,-629,-635,-642,-657,-691,-736,-777,-798,-800,-796,-798,-811,-837,-866,-888,-900,-910,-922,-931,-929,
+-924,-934,-962,-992,-1006,-1005,-1003,-1007,-1014,-1017,-1018,-1022,-1032,-1043,-1052,-1058,-1063,-1069,-1075,-1084,-1096,
+-1108,-1121,-1131,-1138,-1140,-1139,-1136,-1133,-1129,-1124,-1120,-1118,-1118,-1120,-1117,-1106,-1091,-1077,-1067,-1059,-1051,
+-1043,-1041,-1043,-1041,-1031,-1016,-1002,-989,-974,-955,-935,-917,-904,-890,-875,-859,-845,-834,-819,-800,-779,
+-761,-748,-734,-717,-697,-678,-660,-642,-625,-609,-591,-572,-554,-539,-524,-509,-494,-482,-471,-458,-441,
+-425,-411,-396,-379,-362,-349,-337,-323,-308,-297,-292,-285,-272,-260,-252,-248,-242,-234,-226,-220,-213,
+-205,-201,-201,-200,-198,-196,-199,-203,-205,-206,-211,-218,-224,-228,-233,-240,-245,-248,-252,-258,-262,
+-262,-265,-275,-288,-295,-296,-297,-301,-309,-319,-330,-339,-345,-350,-358,-372,-384,-391,-396,-404,-412,
+-414,-413,-418,-428,-438,-443,-444,-447,-450,-451,-454,-462,-471,-477,-479,-481,-481,-478,-471,-466,-462,
+-459,-457,-460,-462,-455,-435,-415,-406,-409,-410,-402,-391,-379,-368,-357,-350,-349,-349,-344,-337,-330,
+-322,-311,-297,-283,-271,-257,-243,-232,-228,-224,-215,-198,-176,-158,-148,-144,-141,-132,-119,-102,-83,
+-58,-31,-7,7,18,32,51,71,94,122,154,188,220,252,288,325,364,403,443,481,521,
+566,614,658,693,730,780,843,905,953,988,1021,1064,1118,1176,1227,1266,1300,1337,1384,1434,1484,
+1533,1584,1633,1679,1721,1765,1809,1849,1882,1920,1974,2034,2058,1992,1813,1573,1386,1351,1487,1737,2038,
+2373,2749,3153,3543,3875,4129,4290,4351,4332,4293,4286,4316,4350,4364,4376,4405,4442,4452,4412,4329,4223,
+4118,4019,3914,3772,3568,3308,3025,2751,2509,2316,2198,2169,2210,2271,2305,2293,2248,2195,2150,2108,2052,
+1975,1889,1817,1772,1749,1733,1710,1677,1631,1573,1503,1422,1334,1248,1164,1070,949,806,667,557,465,
+362,231,89,-39,-150,-253,-350,-432,-494,-543,-584,-620,-656,-703,-761,-813,-841,-842,-831,-825,-832,
+-861,-919,-998,-1077,-1130,-1148,-1137,-1108,-1065,-1013,-959,-913,-882,-869,-881,-921,-977,-1029,-1053,-1045,-1019,
+-993,-975,-968,-976,-1011,-1069,-1131,-1169,-1171,-1140,-1084,-1012,-942,-890,-863,-851,-834,-803,-765,-738,-725,
+-709,-661,-584,-535,-590,-767,-989,-1137,-1158,-1092,-1019,-976,-954,-932,-907,-882,-856,-830,-808,-789,-762,
+-724,-685,-654,-630,-604,-580,-565,-557,-548,-537,-532,-536,-540,-537,-532,-535,-542,-546,-548,-555,-569,
+-584,-600,-617,-638,-657,-669,-680,-692,-705,-713,-715,-717,-718,-717,-711,-702,-687,-667,-645,-624,-600,
+-569,-530,-491,-454,-419,-380,-340,-302,-266,-228,-187,-144,-102,-60,-16,24,60,96,136,182,229,
+275,318,360,402,444,483,520,553,580,603,626,654,684,712,737,761,787,815,848,885,928,
+974,1018,1056,1090,1115,1130,1134,1137,1145,1163,1184,1202,1214,1221,1227,1234,1242,1245,1242,1238,1237,
+1242,1245,1244,1244,1249,1257,1264,1268,1272,1277,1280,1283,1291,1305,1322,1335,1346,1361,1386,1416,1445,
+1471,1497,1524,1549,1568,1583,1597,1612,1625,1633,1637,1637,1640,1642,1641,1637,1633,1632,1633,1637,1646,
+1657,1668,1674,1679,1688,1702,1715,1728,1748,1777,1809,1834,1855,1877,1900,1919,1933,1946,1959,1964,1964,
+1964,1967,1966,1958,1953,1957,1972,1995,2032,2088,2145,2184,2212,2260,2340,2421,2464,2463,2446,2437,2436,
+2437,2447,2470,2499,2523,2536,2540,2531,2508,2475,2442,2411,2382,2354,2336,2329,2329,2330,2330,2324,2304,
+2269,2224,2177,2132,2092,2059,2030,1995,1945,1882,1807,1712,1600,1502,1453,1452,1458,1432,1379,1330,1303,
+1285,1262,1234,1208,1186,1163,1138,1111,1080,1038,986,935,895,868,843,806,752,696,664,661,672,
+677,674,673,678,680,672,656,640,621,583,507,388,245,125,63,39,-4,-104,-229,-323,-370,
+-403,-448,-492,-520,-542,-572,-596,-583,-537,-504,-530,-622,-756,-901,-1031,-1116,-1142,-1128,-1112,-1119,-1148,
+-1179,-1203,-1221,-1233,-1235,-1219,-1186,-1149,-1131,-1137,-1142,-1109,-1032,-951,-916,-942,-990,-1004,-960,-881,-821,
+-813,-828,-800,-685,-513,-360,-269,-222,-170,-95,-15,36,35,-33,-158,-301,-425,-533,-667,-852,-1053,
+-1202,-1264,-1264,-1252,-1258,-1275,-1289,-1296,-1300,-1304,-1305,-1300,-1290,-1286,-1289,-1287,-1272,-1255,-1257,-1283,-1311,
+-1322,-1328,-1352,-1397,-1437,-1458,-1455,-1396,-1228,-946,-671,-581,-751,-1067,-1325,-1406,-1352,-1279,-1251,-1259,-1276,
+-1296,-1320,-1330,-1313,-1280,-1269,-1304,-1373,-1438,-1465,-1451,-1421,-1400,-1400,-1408,-1415,-1424,-1441,-1464,-1480,-1487,
+-1499,-1526,-1564,-1605,-1647,-1692,-1737,-1778,-1816,-1860,-1909,-1957,-2003,-2054,-2115,-2178,-2234,-2286,-2344,-2410,-2479,
+-2545,-2612,-2678,-2735,-2782,-2823,-2868,-2918,-2971,-3028,-3091,-3152,-3202,-3244,-3290,-3349,-3411,-3465,-3506,-3543,-3582,
+-3625,-3672,-3721,-3769,-3812,-3850,-3891,-3938,-3986,-4027,-4059,-4088,-4124,-4167,-4210,-4251,-4289,-4328,-4365,-4400,-4435,
+-4483,-4548,-4615,-4667,-4698,-4721,-4747,-4774,-4790,-4792,-4788,-4792,-4811,-4848,-4897,-4948,-4992,-5019,-5024,-5005,-4963,
+-4904,-4830,-4744,-4661,-4603,-4597,-4647,-4737,-4840,-4928,-4983,-4999,-4993,-4987,-4992,-4999,-4999,-4997,-5004,-5011,-4993,
+-4945,-4891,-4860,-4853,-4855,-4863,-4887,-4927,-4961,-4968,-4951,-4929,-4909,-4890,-4872,-4864,-4866,-4863,-4842,-4809,-4779,
+-4759,-4744,-4733,-4731,-4742,-4753,-4746,-4714,-4671,-4636,-4616,-4597,-4561,-4507,-4449,-4403,-4367,-4332,-4290,-4244,-4196,
+-4142,-4084,-4024,-3967,-3911,-3854,-3795,-3737,-3682,-3629,-3575,-3521,-3467,-3415,-3367,-3325,-3285,-3243,-3196,-3150,-3104,
+-3054,-2998,-2940,-2884,-2829,-2768,-2699,-2627,-2551,-2473,-2398,-2337,-2302,-2290,-2289,-2281,-2249,-2183,-2092,-1993,-1894,
+-1795,-1695,-1608,-1552,-1527,-1519,-1517,-1513,-1490,-1411,-1251,-1036,-825,-670,-573,-509,-450,-390,-327,-256,-169,
+-72,28,124,216,309,406,506,606,702,794,879,950,1001,1031,1049,1062,1082,1114,1158,1204,1241,
+1270,1305,1364,1447,1537,1615,1673,1707,1727,1744,1775,1825,1890,1961,2028,2086,2130,2165,2207,2272,2361,
+2457,2539,2604,2659,2706,2738,2746,2737,2728,2727,2733,2740,2748,2769,2809,2866,2926,2985,3047,3121,3203,
+3281,3342,3388,3425,3458,3488,3523,3566,3616,3661,3697,3739,3805,3897,3992,4061,4094,4113,4152,4233,4344,
+4457,4545,4606,4654,4702,4742,4759,4747,4719,4699,4704,4735,4790,4866,4961,5067,5175,5278,5368,5446,5518,
+5594,5669,5727,5760,5775,5791,5811,5822,5817,5805,5802,5806,5804,5789,5771,5763,5771,5786,5798,5800,5799,
+5803,5809,5806,5794,5789,5808,5846,5880,5896,5902,5905,5894,5849,5777,5710,5673,5662,5656,5644,5633,5633,
+5643,5652,5650,5647,5660,5689,5709,5703,5682,5671,5659,5619,5574,5606,5756,5936,5998,5898,5753,5698,5738,
+5777,5756,5706,5678,5671,5668,5674,5695,5703,5669,5634,5672,5801,5943,6005,5977,5918,5891,5909,5958,6018,
+6067,6084,6057,6001,5945,5905,5865,5781,5621,5411,5245,5226,5392,5682,5991,6235,6390,6475,6524,6561,6589,
+6598,6586,6568,6557,6551,6539,6521,6506,6491,6462,6419,6375,6346,6324,6294,6253,6211,6168,6118,6062,6012,
+5970,5923,5861,5791,5725,5671,5629,5601,5573,5515,5404,5257,5126,5052,5031,5033,5035,5030,5019,5004,5000,
+5025,5074,5114,5114,5080,5047,5045,5071,5096,5100,5089,5085,5096,5105,5091,5055,5017,4994,4969,4873,4616,
+4141,3495,2852,2427,2334,2495,2715,2849,2884,2889,2898,2897,2875,2861,2875,2881,2823,2694,2544,2425,2344,
+2277,2202,2116,2022,1928,1849,1793,1750,1703,1649,1598,1553,1504,1445,1385,1339,1307,1280,1258,1246,1237,
+1217,1184,1154,1136,1118,1091,1066,1055,1053,1036,1004,981,985,999,999,982,968,961,947,908,853,
+800,753,703,652,610,585,566,541,511,488,475,458,429,393,363,343,324,296,261,226,194,
+166,149,155,182,212,224,206,164,114,71,40,19,-2,-29,-55,-76,-99,-135,-184,-231,-264,
+-290,-322,-361,-401,-436,-468,-498,-525,-547,-571,-600,-627,-645,-656,-666,-677,-684,-689,-703,-736,-783,
+-824,-842,-840,-833,-835,-848,-861,-868,-879,-903,-932,-947,-940,-928,-934,-962,-993,-1013,-1021,-1026,-1034,
+-1040,-1044,-1047,-1051,-1055,-1059,-1065,-1071,-1078,-1083,-1086,-1092,-1100,-1111,-1122,-1132,-1138,-1141,-1141,-1140,-1139,
+-1136,-1133,-1130,-1129,-1133,-1136,-1135,-1125,-1109,-1093,-1080,-1071,-1062,-1053,-1049,-1048,-1048,-1041,-1028,-1015,-1003,
+-988,-968,-946,-926,-910,-893,-873,-854,-841,-832,-819,-800,-781,-768,-757,-743,-722,-699,-679,-662,-647,
+-632,-614,-594,-572,-553,-536,-520,-502,-486,-474,-464,-451,-433,-418,-406,-393,-377,-361,-349,-338,-324,
+-309,-300,-295,-288,-276,-265,-258,-254,-248,-238,-231,-225,-218,-211,-206,-203,-202,-200,-201,-205,-210,
+-212,-213,-217,-223,-228,-233,-239,-246,-250,-252,-258,-265,-268,-266,-266,-274,-285,-292,-296,-300,-305,
+-311,-318,-326,-334,-339,-342,-352,-369,-384,-388,-388,-390,-397,-402,-405,-409,-417,-424,-428,-430,-433,
+-436,-438,-442,-449,-457,-460,-461,-461,-460,-454,-448,-444,-443,-443,-443,-445,-445,-436,-416,-396,-387,
+-386,-384,-377,-367,-355,-342,-328,-321,-320,-321,-318,-314,-309,-301,-288,-273,-261,-251,-238,-223,-210,
+-203,-198,-188,-173,-155,-139,-128,-121,-113,-100,-84,-71,-56,-36,-10,14,30,42,57,78,98,
+117,140,168,201,234,270,307,343,380,421,467,511,549,584,624,669,710,748,790,842,899,
+949,989,1024,1061,1104,1150,1195,1235,1272,1312,1360,1414,1469,1523,1575,1623,1662,1696,1737,1789,1842,
+1885,1919,1962,2026,2086,2084,1966,1738,1486,1336,1369,1579,1909,2300,2719,3132,3506,3816,4055,4216,4293,
+4298,4276,4272,4295,4325,4346,4369,4406,4442,4449,4411,4337,4248,4167,4098,4018,3883,3657,3356,3040,2766,
+2551,2386,2273,2232,2262,2323,2359,2343,2290,2233,2190,2146,2073,1962,1835,1732,1683,1685,1711,1731,1725,
+1692,1637,1567,1489,1408,1330,1250,1151,1016,855,701,581,486,382,252,112,-14,-127,-240,-355,-455,
+-526,-570,-600,-626,-655,-695,-748,-802,-838,-848,-840,-827,-818,-821,-845,-899,-971,-1039,-1082,-1095,-1082,
+-1048,-999,-942,-888,-847,-828,-838,-878,-937,-988,-1005,-984,-945,-914,-900,-901,-921,-974,-1061,-1153,-1205,
+-1190,-1117,-1015,-916,-838,-788,-764,-755,-745,-722,-692,-678,-696,-725,-712,-633,-547,-557,-709,-932,-1096,
+-1137,-1094,-1043,-1014,-991,-956,-916,-881,-853,-828,-805,-780,-744,-701,-666,-643,-622,-592,-561,-543,-538,
+-531,-520,-517,-528,-542,-545,-541,-540,-545,-551,-557,-566,-580,-594,-606,-623,-644,-663,-672,-676,-683,
+-695,-703,-705,-702,-699,-695,-689,-677,-661,-640,-620,-603,-584,-560,-528,-493,-459,-423,-385,-347,-312,
+-277,-238,-195,-153,-113,-72,-27,15,52,85,124,168,215,258,299,341,384,426,463,499,532,
+561,587,612,641,674,707,736,763,791,821,854,891,934,981,1028,1071,1107,1133,1149,1155,1156,
+1160,1170,1185,1202,1216,1225,1230,1234,1239,1242,1241,1238,1238,1241,1243,1243,1244,1250,1260,1270,1276,
+1281,1285,1288,1294,1304,1320,1336,1349,1362,1381,1407,1437,1464,1486,1507,1531,1553,1569,1579,1589,1603,
+1618,1630,1637,1631,1636,1641,1646,1646,1644,1643,1646,1652,1663,1678,1693,1703,1709,1718,1735,1753,1770,
+1792,1823,1859,1889,1910,1928,1943,1954,1963,1974,1989,1998,2002,2004,2012,2020,2026,2033,2048,2073,2107,
+2154,2210,2255,2271,2269,2284,2337,2407,2456,2475,2478,2477,2469,2454,2447,2461,2488,2513,2530,2542,2546,
+2538,2522,2504,2490,2476,2461,2448,2443,2445,2451,2452,2435,2395,2337,2275,2221,2179,2142,2110,2078,2041,
+1992,1929,1852,1757,1655,1573,1534,1532,1529,1493,1435,1383,1350,1325,1294,1258,1225,1200,1180,1162,1141,
+1110,1067,1018,974,944,924,904,874,831,791,772,779,797,806,801,788,772,749,718,681,647,
+616,575,500,374,222,108,75,96,84,-8,-140,-238,-280,-308,-357,-414,-451,-472,-494,-505,-482,
+-439,-432,-507,-653,-826,-986,-1111,-1180,-1184,-1142,-1096,-1075,-1083,-1107,-1137,-1162,-1172,-1161,-1135,-1105,-1087,
+-1087,-1103,-1109,-1073,-989,-894,-849,-875,-932,-950,-896,-804,-742,-746,-781,-771,-673,-516,-366,-265,-199,
+-129,-39,52,108,96,4,-139,-281,-391,-499,-654,-863,-1066,-1189,-1221,-1206,-1196,-1204,-1218,-1229,-1238,
+-1245,-1247,-1244,-1237,-1233,-1234,-1234,-1222,-1193,-1168,-1174,-1211,-1246,-1257,-1258,-1279,-1319,-1361,-1404,-1451,-1453,
+-1306,-974,-602,-442,-622,-1013,-1346,-1456,-1389,-1290,-1242,-1234,-1229,-1225,-1234,-1246,-1238,-1211,-1193,-1209,-1255,
+-1300,-1311,-1282,-1241,-1225,-1249,-1292,-1326,-1344,-1361,-1382,-1400,-1409,-1419,-1441,-1475,-1513,-1554,-1599,-1646,-1689,
+-1730,-1775,-1825,-1873,-1918,-1967,-2023,-2082,-2135,-2187,-2244,-2308,-2374,-2442,-2511,-2577,-2633,-2678,-2721,-2769,-2821,
+-2873,-2927,-2985,-3041,-3090,-3136,-3192,-3258,-3320,-3369,-3409,-3448,-3491,-3535,-3582,-3631,-3680,-3723,-3759,-3796,-3841,
+-3890,-3933,-3969,-4005,-4046,-4089,-4130,-4168,-4207,-4246,-4285,-4319,-4354,-4403,-4468,-4535,-4587,-4617,-4638,-4661,-4686,
+-4702,-4705,-4705,-4719,-4751,-4795,-4839,-4875,-4900,-4910,-4904,-4879,-4839,-4786,-4721,-4646,-4574,-4530,-4534,-4585,-4669,
+-4764,-4851,-4912,-4937,-4935,-4928,-4932,-4942,-4944,-4940,-4937,-4932,-4908,-4863,-4819,-4802,-4811,-4831,-4852,-4880,-4914,
+-4937,-4936,-4917,-4897,-4881,-4868,-4856,-4850,-4849,-4841,-4818,-4788,-4766,-4754,-4746,-4740,-4740,-4749,-4757,-4753,-4729,
+-4692,-4656,-4630,-4608,-4579,-4536,-4483,-4427,-4375,-4330,-4290,-4251,-4206,-4151,-4091,-4030,-3972,-3911,-3847,-3785,-3727,
+-3675,-3624,-3575,-3529,-3483,-3436,-3389,-3346,-3307,-3266,-3223,-3180,-3136,-3084,-3023,-2959,-2901,-2846,-2785,-2716,-2645,
+-2575,-2505,-2439,-2388,-2359,-2348,-2340,-2322,-2285,-2222,-2131,-2025,-1918,-1821,-1734,-1659,-1608,-1585,-1583,-1585,-1571,
+-1518,-1396,-1200,-968,-768,-645,-590,-560,-522,-470,-407,-329,-231,-123,-23,63,145,236,338,438,529,
+617,710,809,900,967,1003,1016,1021,1030,1050,1081,1115,1143,1163,1189,1234,1303,1388,1474,1549,1603,
+1634,1651,1669,1705,1761,1831,1900,1958,2007,2057,2124,2209,2302,2387,2457,2517,2570,2610,2633,2639,2636,
+2630,2626,2624,2626,2638,2662,2702,2755,2816,2881,2950,3028,3110,3188,3253,3304,3347,3385,3422,3462,3508,
+3557,3602,3643,3690,3756,3840,3922,3982,4014,4039,4089,4181,4302,4423,4516,4580,4631,4677,4709,4712,4684,
+4648,4627,4629,4653,4699,4770,4863,4965,5069,5173,5274,5369,5454,5531,5601,5658,5695,5716,5735,5759,5781,
+5790,5784,5774,5768,5765,5757,5745,5736,5739,5755,5772,5781,5784,5791,5801,5800,5784,5774,5794,5840,5882,
+5895,5887,5877,5862,5823,5755,5683,5634,5611,5598,5585,5578,5583,5596,5601,5593,5588,5609,5648,5669,5650,
+5611,5592,5592,5583,5569,5618,5768,5942,6003,5906,5760,5693,5714,5738,5710,5666,5652,5659,5656,5644,5644,
+5651,5639,5619,5638,5719,5827,5911,5946,5941,5914,5884,5880,5927,6008,6072,6082,6037,5968,5904,5846,5771,
+5649,5465,5259,5119,5134,5333,5656,5992,6246,6388,6455,6498,6536,6559,6562,6554,6548,6540,6520,6496,6482,
+6474,6453,6413,6372,6346,6327,6294,6246,6197,6154,6110,6062,6019,5979,5928,5858,5780,5713,5662,5619,5576,
+5521,5433,5301,5155,5049,5015,5025,5033,5018,4999,4994,5002,5017,5045,5085,5119,5126,5102,5074,5068,5089,
+5117,5132,5132,5131,5137,5142,5131,5105,5078,5057,5010,4861,4524,3979,3318,2727,2385,2343,2501,2694,2818,
+2874,2901,2912,2894,2857,2833,2827,2799,2712,2583,2460,2374,2313,2257,2195,2128,2047,1953,1864,1798,1752,
+1705,1649,1599,1562,1527,1478,1421,1370,1332,1302,1279,1267,1259,1241,1209,1173,1144,1119,1093,1071,1059,
+1050,1029,995,966,953,950,940,927,927,941,955,951,925,882,826,757,683,622,585,563,543,
+517,492,472,454,428,393,356,326,302,281,259,233,200,162,128,114,122,139,147,135,104,
+65,28,-1,-26,-51,-77,-99,-116,-135,-165,-206,-249,-285,-315,-345,-376,-408,-445,-490,-533,-558,
+-562,-564,-584,-621,-659,-683,-698,-711,-723,-730,-737,-755,-789,-828,-855,-864,-864,-866,-868,-863,-854,
+-859,-887,-927,-955,-961,-958,-962,-977,-994,-1008,-1021,-1035,-1046,-1052,-1057,-1067,-1079,-1086,-1089,-1093,-1100,
+-1105,-1106,-1105,-1107,-1113,-1122,-1131,-1138,-1143,-1143,-1140,-1139,-1140,-1141,-1142,-1143,-1145,-1147,-1147,-1144,-1136,
+-1123,-1107,-1091,-1080,-1071,-1063,-1056,-1053,-1051,-1047,-1037,-1024,-1012,-999,-982,-962,-945,-929,-910,-885,-860,
+-844,-835,-824,-808,-792,-780,-769,-752,-729,-704,-682,-664,-650,-636,-619,-598,-575,-554,-538,-522,-503,
+-485,-472,-461,-446,-428,-413,-403,-392,-378,-363,-352,-342,-329,-314,-304,-299,-291,-279,-269,-264,-261,
+-254,-245,-237,-231,-225,-218,-213,-210,-208,-207,-209,-214,-218,-220,-220,-222,-226,-230,-234,-241,-248,
+-252,-255,-261,-269,-274,-274,-276,-282,-289,-293,-296,-302,-309,-313,-317,-324,-332,-337,-342,-351,-365,
+-375,-376,-374,-378,-389,-399,-404,-406,-409,-413,-415,-417,-420,-424,-427,-432,-438,-441,-440,-438,-438,
+-438,-433,-426,-423,-424,-427,-428,-429,-425,-413,-394,-377,-368,-364,-359,-351,-342,-332,-319,-305,-298,
+-296,-296,-293,-291,-288,-280,-266,-251,-240,-229,-217,-203,-192,-183,-173,-159,-146,-133,-120,-107,-95,
+-82,-66,-50,-37,-26,-12,8,29,46,62,82,105,125,142,162,188,218,250,285,322,358,
+393,435,486,537,576,606,641,686,732,770,804,843,887,934,980,1021,1058,1093,1128,1165,1203,
+1244,1289,1341,1397,1452,1504,1557,1605,1644,1674,1707,1754,1813,1871,1917,1956,2003,2063,2105,2066,1899,
+1634,1391,1306,1448,1782,2221,2676,3095,3455,3751,3983,4149,4245,4280,4285,4290,4306,4323,4336,4358,4393,
+4424,4426,4395,4343,4286,4231,4175,4090,3935,3682,3356,3029,2766,2576,2433,2327,2277,2295,2347,2378,2358,
+2304,2253,2219,2180,2103,1978,1831,1707,1644,1648,1693,1738,1754,1731,1678,1610,1538,1466,1394,1315,1208,
+1063,893,732,605,501,391,260,123,0,-113,-232,-360,-474,-551,-591,-611,-628,-653,-691,-740,-792,
+-830,-847,-846,-835,-819,-804,-801,-825,-882,-955,-1018,-1052,-1052,-1026,-980,-921,-860,-811,-788,-799,-841,
+-897,-937,-939,-905,-864,-838,-827,-820,-832,-892,-1005,-1127,-1189,-1153,-1043,-917,-822,-761,-721,-692,-677,
+-673,-665,-650,-650,-694,-762,-784,-708,-585,-540,-644,-842,-1009,-1075,-1069,-1049,-1035,-1008,-966,-927,-900,
+-876,-844,-809,-774,-735,-692,-658,-636,-615,-581,-547,-529,-528,-526,-518,-517,-531,-548,-555,-552,-552,
+-559,-565,-571,-581,-596,-610,-621,-633,-652,-670,-678,-679,-683,-692,-699,-699,-693,-688,-683,-676,-663,
+-645,-624,-605,-588,-571,-550,-524,-494,-461,-424,-385,-348,-314,-280,-242,-200,-160,-123,-85,-44,-2,
+35,70,110,154,198,238,277,318,361,403,440,475,509,542,571,597,626,660,696,730,762,
+792,825,861,899,940,985,1032,1077,1116,1144,1161,1170,1174,1176,1180,1189,1202,1216,1227,1231,1232,
+1234,1239,1242,1243,1244,1246,1249,1253,1256,1262,1270,1278,1286,1291,1296,1301,1309,1321,1336,1350,1364,
+1381,1403,1428,1453,1476,1494,1513,1533,1553,1569,1579,1588,1600,1615,1626,1631,1628,1631,1641,1653,1659,
+1659,1660,1665,1673,1684,1701,1718,1732,1741,1753,1773,1795,1815,1836,1867,1903,1935,1958,1976,1991,2002,
+2011,2019,2030,2037,2040,2045,2060,2085,2111,2137,2163,2190,2217,2248,2284,2312,2318,2311,2316,2353,2410,
+2460,2493,2511,2514,2498,2471,2460,2477,2509,2533,2544,2550,2558,2563,2560,2554,2551,2551,2551,2551,2551,
+2552,2552,2543,2513,2460,2393,2330,2283,2248,2215,2180,2141,2097,2043,1975,1895,1805,1717,1650,1616,1603,
+1583,1543,1493,1452,1422,1392,1352,1307,1265,1232,1211,1197,1179,1146,1101,1057,1025,1006,991,975,954,
+930,909,902,913,929,934,917,882,836,785,728,671,619,576,533,464,346,203,104,99,152,
+160,71,-63,-155,-184,-209,-273,-356,-411,-431,-437,-434,-414,-397,-433,-552,-725,-898,-1038,-1138,-1189,
+-1181,-1128,-1064,-1022,-1016,-1040,-1079,-1112,-1115,-1089,-1054,-1032,-1026,-1032,-1043,-1046,-1015,-937,-844,-797,-825,
+-887,-905,-838,-730,-658,-663,-707,-717,-647,-515,-372,-254,-161,-77,9,91,139,118,16,-131,-268,
+-373,-486,-656,-872,-1060,-1156,-1168,-1153,-1152,-1162,-1170,-1174,-1180,-1187,-1188,-1181,-1174,-1173,-1178,-1177,-1161,
+-1129,-1103,-1109,-1144,-1175,-1181,-1177,-1193,-1230,-1274,-1333,-1414,-1457,-1336,-1003,-611,-434,-613,-1006,-1330,-1421,
+-1337,-1233,-1184,-1166,-1144,-1125,-1132,-1158,-1174,-1168,-1154,-1152,-1168,-1187,-1184,-1151,-1111,-1103,-1141,-1201,-1246,
+-1266,-1278,-1298,-1320,-1334,-1346,-1365,-1396,-1432,-1469,-1509,-1555,-1601,-1646,-1692,-1741,-1787,-1831,-1878,-1932,-1987,
+-2041,-2094,-2151,-2212,-2275,-2343,-2414,-2481,-2536,-2580,-2625,-2676,-2728,-2778,-2828,-2882,-2935,-2985,-3036,-3097,-3164,
+-3223,-3266,-3304,-3347,-3395,-3443,-3490,-3540,-3591,-3634,-3669,-3704,-3746,-3793,-3837,-3879,-3920,-3963,-4005,-4044,-4082,
+-4122,-4164,-4201,-4235,-4272,-4321,-4382,-4446,-4495,-4526,-4546,-4568,-4592,-4611,-4622,-4632,-4654,-4691,-4732,-4764,-4782,
+-4788,-4785,-4771,-4747,-4714,-4674,-4620,-4555,-4494,-4462,-4474,-4527,-4604,-4692,-4779,-4847,-4880,-4879,-4870,-4873,-4886,
+-4891,-4883,-4872,-4861,-4842,-4810,-4782,-4777,-4795,-4820,-4844,-4869,-4896,-4911,-4905,-4886,-4868,-4858,-4850,-4843,-4838,
+-4830,-4813,-4789,-4767,-4757,-4754,-4752,-4749,-4752,-4760,-4767,-4762,-4741,-4707,-4668,-4636,-4614,-4595,-4566,-4517,-4451,
+-4382,-4326,-4285,-4253,-4215,-4164,-4104,-4044,-3984,-3919,-3849,-3779,-3718,-3662,-3610,-3562,-3520,-3482,-3443,-3404,-3368,
+-3333,-3295,-3251,-3206,-3161,-3110,-3046,-2978,-2916,-2860,-2800,-2734,-2670,-2612,-2556,-2500,-2451,-2416,-2391,-2366,-2338,
+-2304,-2254,-2175,-2070,-1962,-1868,-1792,-1728,-1679,-1653,-1647,-1637,-1593,-1494,-1329,-1117,-900,-738,-659,-641,-634,
+-605,-552,-483,-398,-297,-192,-102,-26,53,154,268,372,456,531,621,729,837,921,968,984,986,
+987,995,1011,1031,1052,1073,1100,1139,1195,1264,1340,1414,1478,1524,1556,1583,1618,1666,1727,1792,1852,
+1910,1975,2054,2143,2228,2298,2358,2416,2469,2508,2531,2541,2545,2542,2530,2515,2507,2514,2537,2575,2628,
+2696,2773,2853,2937,3023,3106,3178,3235,3281,3323,3364,3404,3443,3484,3528,3577,3634,3700,3774,3843,3896,
+3934,3970,4032,4131,4256,4379,4475,4543,4596,4640,4664,4654,4616,4575,4554,4556,4576,4616,4681,4766,4856,
+4946,5040,5143,5252,5353,5439,5513,5574,5618,5646,5667,5691,5719,5737,5739,5727,5717,5714,5715,5708,5694,
+5690,5706,5736,5759,5769,5773,5779,5777,5761,5747,5759,5796,5830,5839,5828,5817,5806,5777,5722,5658,5604,
+5562,5528,5503,5498,5516,5542,5553,5546,5541,5562,5601,5618,5589,5542,5524,5542,5560,5568,5618,5748,5899,
+5947,5849,5701,5629,5654,5695,5694,5675,5679,5695,5685,5648,5616,5610,5616,5617,5620,5643,5697,5787,5897,
+5984,6002,5946,5878,5872,5944,6040,6097,6088,6028,5942,5853,5770,5677,5535,5321,5083,4943,5014,5310,5718,
+6079,6299,6394,6439,6481,6515,6528,6528,6529,6528,6511,6483,6464,6456,6442,6413,6381,6358,6333,6288,6229,
+6175,6137,6104,6066,6027,5985,5928,5855,5782,5726,5679,5617,5534,5435,5325,5208,5105,5047,5041,5050,5037,
+5001,4977,4987,5017,5047,5073,5103,5131,5139,5122,5096,5084,5099,5129,5157,5173,5178,5178,5176,5166,5151,
+5139,5122,5052,4841,4419,3808,3147,2631,2392,2420,2586,2749,2847,2895,2921,2924,2894,2845,2801,2758,2689,
+2585,2475,2392,2337,2287,2230,2176,2125,2057,1965,1869,1797,1749,1701,1642,1591,1558,1533,1495,1445,1395,
+1356,1323,1295,1278,1269,1254,1224,1186,1153,1129,1108,1086,1065,1046,1023,996,969,948,929,909,890,
+886,903,935,965,975,955,900,818,727,648,593,561,541,522,501,479,457,432,399,359,318,
+283,257,240,226,204,172,135,104,85,72,59,43,27,11,-7,-31,-58,-86,-112,-135,-157,
+-181,-212,-250,-286,-317,-344,-372,-399,-429,-469,-518,-563,-582,-570,-555,-567,-614,-670,-708,-724,-732,
+-744,-760,-774,-786,-801,-821,-842,-859,-874,-887,-894,-887,-873,-866,-881,-911,-944,-969,-988,-1002,-1006,
+-1002,-1002,-1012,-1030,-1042,-1046,-1052,-1069,-1089,-1103,-1111,-1118,-1126,-1129,-1126,-1123,-1123,-1128,-1135,-1143,-1150,
+-1154,-1152,-1146,-1142,-1143,-1146,-1151,-1156,-1159,-1157,-1151,-1145,-1140,-1132,-1117,-1100,-1087,-1080,-1074,-1066,-1058,
+-1054,-1050,-1042,-1029,-1016,-1003,-991,-978,-965,-952,-933,-905,-877,-856,-844,-834,-821,-807,-792,-776,-756,
+-733,-709,-688,-668,-652,-637,-621,-601,-579,-560,-545,-530,-511,-493,-478,-464,-447,-429,-414,-404,-393,
+-379,-366,-357,-347,-333,-319,-309,-304,-297,-286,-277,-273,-269,-262,-252,-245,-239,-232,-225,-221,-219,
+-217,-215,-216,-220,-224,-224,-223,-225,-227,-230,-234,-241,-250,-256,-259,-264,-270,-276,-279,-284,-290,
+-295,-296,-298,-303,-309,-313,-316,-321,-329,-336,-341,-347,-355,-360,-360,-363,-373,-387,-398,-401,-401,
+-402,-403,-404,-405,-407,-411,-416,-421,-425,-423,-418,-416,-418,-418,-413,-406,-404,-406,-408,-409,-409,
+-404,-391,-373,-358,-350,-345,-338,-329,-320,-310,-298,-286,-280,-278,-275,-271,-269,-267,-260,-247,-233,
+-221,-208,-193,-180,-171,-163,-150,-134,-123,-113,-100,-83,-66,-53,-41,-26,-11,1,14,29,44,
+59,75,96,119,137,156,180,210,239,266,297,333,371,408,451,503,556,596,628,663,707,
+750,786,816,847,881,917,957,1000,1041,1076,1108,1141,1179,1220,1267,1321,1379,1433,1482,1530,1580,
+1626,1663,1693,1730,1783,1848,1912,1960,1996,2039,2096,2117,2021,1778,1475,1285,1345,1663,2130,2618,3049,
+3403,3690,3920,4095,4213,4279,4308,4318,4322,4321,4321,4333,4355,4374,4375,4362,4350,4340,4316,4259,4146,
+3953,3668,3325,2995,2740,2564,2434,2334,2284,2298,2347,2375,2352,2299,2255,2229,2198,2130,2017,1884,1766,
+1697,1685,1714,1750,1762,1736,1680,1611,1542,1478,1412,1331,1220,1072,905,747,617,505,389,257,123,
+1,-111,-232,-362,-479,-559,-598,-615,-630,-654,-690,-735,-781,-816,-835,-839,-835,-825,-807,-789,-791,
+-826,-888,-951,-989,-994,-973,-933,-881,-825,-780,-762,-778,-821,-864,-878,-853,-807,-771,-756,-745,-726,
+-726,-788,-919,-1056,-1110,-1045,-909,-784,-718,-692,-667,-630,-605,-610,-630,-646,-673,-743,-841,-890,-824,
+-685,-600,-654,-805,-942,-999,-998,-982,-958,-921,-889,-886,-901,-899,-865,-820,-784,-753,-715,-672,-637,
+-609,-579,-551,-536,-535,-537,-535,-538,-549,-560,-563,-563,-570,-581,-585,-581,-584,-600,-620,-634,-645,
+-660,-675,-683,-683,-684,-689,-692,-690,-684,-679,-674,-665,-651,-633,-614,-595,-577,-558,-538,-515,-488,
+-457,-421,-383,-346,-313,-280,-244,-204,-166,-130,-94,-57,-18,19,58,100,143,185,224,261,301,
+343,385,424,461,496,531,563,592,621,653,688,724,758,791,824,862,901,941,983,1027,1075,
+1118,1149,1168,1179,1186,1191,1194,1197,1205,1217,1226,1230,1229,1231,1237,1244,1250,1252,1255,1261,1270,
+1278,1284,1288,1293,1300,1306,1312,1319,1330,1343,1356,1368,1382,1401,1422,1443,1463,1482,1500,1518,1536,
+1557,1576,1590,1601,1612,1622,1627,1628,1633,1636,1650,1667,1678,1680,1682,1688,1698,1708,1722,1739,1757,
+1773,1790,1813,1837,1857,1878,1907,1942,1975,2001,2024,2047,2066,2074,2077,2079,2080,2083,2093,2119,2161,
+2206,2244,2269,2282,2287,2292,2306,2325,2337,2342,2351,2378,2420,2467,2508,2534,2535,2508,2472,2459,2483,
+2521,2545,2550,2553,2567,2587,2600,2605,2610,2620,2633,2643,2644,2637,2621,2595,2558,2509,2457,2411,2377,
+2345,2307,2260,2210,2157,2096,2023,1939,1852,1773,1713,1672,1639,1603,1567,1541,1528,1513,1484,1437,1382,
+1331,1290,1265,1250,1232,1197,1152,1113,1092,1083,1074,1062,1051,1044,1039,1038,1041,1043,1031,996,939,
+869,797,725,652,582,522,473,410,308,183,99,106,169,190,116,0,-74,-91,-118,-202,-311,
+-384,-403,-395,-385,-380,-402,-485,-632,-798,-934,-1024,-1082,-1113,-1104,-1057,-994,-948,-938,-967,-1016,-1051,
+-1048,-1013,-978,-963,-961,-956,-954,-956,-940,-882,-799,-754,-783,-848,-865,-790,-670,-585,-578,-619,-641,
+-599,-496,-359,-220,-101,-9,61,115,141,110,13,-120,-245,-351,-479,-664,-876,-1042,-1115,-1120,-1113,
+-1119,-1127,-1125,-1121,-1126,-1133,-1130,-1120,-1112,-1111,-1117,-1121,-1113,-1092,-1070,-1066,-1081,-1090,-1076,-1059,-1069,
+-1111,-1168,-1240,-1323,-1360,-1242,-942,-613,-496,-687,-1036,-1289,-1327,-1231,-1138,-1098,-1077,-1045,-1021,-1029,-1062,
+-1095,-1111,-1113,-1114,-1121,-1132,-1133,-1113,-1083,-1076,-1106,-1153,-1183,-1190,-1197,-1218,-1247,-1266,-1279,-1298,-1328,
+-1361,-1394,-1428,-1469,-1514,-1559,-1603,-1648,-1691,-1734,-1782,-1836,-1891,-1946,-2001,-2059,-2119,-2180,-2246,-2317,-2385,
+-2440,-2485,-2532,-2584,-2635,-2682,-2728,-2779,-2833,-2886,-2942,-3004,-3068,-3120,-3160,-3197,-3244,-3296,-3347,-3397,-3449,
+-3499,-3543,-3578,-3614,-3654,-3698,-3742,-3786,-3832,-3877,-3917,-3955,-3994,-4036,-4078,-4115,-4149,-4187,-4234,-4291,-4350,
+-4398,-4430,-4451,-4472,-4497,-4520,-4539,-4558,-4584,-4617,-4647,-4667,-4673,-4669,-4659,-4643,-4623,-4603,-4576,-4536,-4481,
+-4430,-4410,-4431,-4485,-4555,-4635,-4720,-4791,-4826,-4824,-4812,-4815,-4830,-4836,-4824,-4807,-4796,-4788,-4775,-4765,-4768,
+-4787,-4812,-4836,-4859,-4877,-4882,-4871,-4853,-4840,-4835,-4833,-4830,-4823,-4808,-4784,-4761,-4750,-4753,-4760,-4762,-4761,
+-4765,-4774,-4781,-4775,-4755,-4721,-4680,-4644,-4621,-4607,-4584,-4539,-4471,-4396,-4330,-4285,-4253,-4218,-4170,-4111,-4051,
+-3992,-3929,-3858,-3785,-3718,-3659,-3604,-3554,-3511,-3475,-3441,-3410,-3383,-3358,-3324,-3278,-3229,-3183,-3133,-3072,-3005,
+-2942,-2887,-2829,-2766,-2708,-2663,-2622,-2577,-2527,-2479,-2434,-2388,-2348,-2316,-2280,-2219,-2126,-2025,-1939,-1873,-1816,
+-1767,-1734,-1709,-1663,-1568,-1422,-1240,-1051,-885,-771,-721,-712,-706,-675,-621,-553,-470,-376,-282,-202,-132,
+-48,65,190,297,374,440,524,634,750,848,911,940,947,945,943,945,953,969,996,1030,1071,
+1117,1169,1229,1293,1355,1411,1462,1509,1553,1598,1649,1708,1772,1835,1903,1978,2056,2128,2189,2244,2299,
+2351,2392,2419,2438,2452,2454,2442,2423,2410,2411,2428,2459,2510,2582,2666,2751,2836,2926,3019,3104,3172,
+3224,3269,3308,3338,3361,3388,3431,3494,3565,3636,3701,3759,3810,3856,3908,3981,4083,4203,4320,4418,4493,
+4553,4599,4619,4604,4566,4526,4503,4500,4514,4548,4604,4678,4754,4826,4903,4998,5107,5218,5318,5402,5472,
+5524,5558,5581,5603,5632,5660,5672,5668,5660,5662,5669,5667,5650,5638,5654,5694,5734,5752,5752,5747,5740,
+5727,5715,5716,5734,5752,5757,5754,5751,5746,5726,5686,5636,5581,5522,5464,5424,5417,5440,5472,5488,5483,
+5479,5496,5529,5546,5527,5497,5496,5526,5547,5546,5572,5672,5803,5851,5762,5618,5546,5585,5666,5717,5736,
+5754,5768,5747,5686,5621,5588,5591,5599,5591,5571,5579,5663,5829,6009,6104,6070,5966,5894,5909,5986,6066,
+6108,6093,6022,5916,5810,5719,5606,5409,5131,4882,4827,5050,5471,5903,6197,6336,6396,6442,6479,6492,6489,
+6492,6504,6503,6482,6458,6443,6430,6409,6382,6356,6321,6270,6211,6165,6138,6111,6072,6024,5971,5910,5842,
+5782,5734,5679,5589,5464,5334,5226,5151,5108,5093,5092,5079,5039,4992,4974,4996,5035,5066,5090,5118,5145,
+5154,5139,5115,5104,5117,5148,5182,5204,5211,5208,5203,5197,5195,5196,5181,5084,4810,4305,3636,2984,2547,
+2411,2510,2690,2829,2897,2924,2935,2926,2891,2839,2782,2714,2620,2513,2423,2367,2323,2268,2204,2152,2109,
+2047,1954,1855,1784,1737,1691,1632,1581,1550,1530,1499,1454,1410,1374,1343,1313,1290,1277,1260,1230,1192,
+1162,1143,1126,1102,1071,1044,1022,1003,980,956,932,909,888,875,880,907,945,970,962,917,846,
+763,682,613,563,535,521,506,484,458,431,402,366,323,279,243,218,202,186,164,138,109,
+79,47,18,-1,-10,-16,-30,-56,-86,-114,-139,-164,-195,-230,-269,-305,-335,-356,-374,-395,-423,
+-457,-499,-546,-585,-598,-584,-566,-577,-626,-691,-735,-746,-738,-740,-761,-791,-812,-821,-825,-833,-847,
+-866,-888,-906,-914,-911,-903,-897,-901,-917,-948,-985,-1014,-1020,-1009,-1000,-1008,-1028,-1043,-1047,-1053,-1069,
+-1089,-1105,-1116,-1127,-1138,-1143,-1140,-1137,-1138,-1141,-1144,-1149,-1157,-1163,-1164,-1158,-1153,-1152,-1155,-1158,-1162,
+-1165,-1161,-1152,-1144,-1140,-1137,-1126,-1110,-1096,-1090,-1086,-1078,-1067,-1059,-1054,-1046,-1031,-1015,-1003,-994,-986,
+-977,-966,-950,-925,-897,-873,-857,-845,-832,-817,-799,-778,-756,-734,-715,-696,-676,-656,-639,-623,-605,
+-585,-567,-552,-538,-520,-501,-485,-470,-452,-434,-420,-408,-395,-381,-369,-360,-350,-336,-322,-314,-310,
+-305,-296,-287,-282,-277,-270,-261,-254,-248,-240,-233,-228,-226,-223,-220,-219,-222,-224,-224,-224,-227,
+-231,-233,-236,-243,-252,-260,-265,-270,-274,-277,-280,-284,-290,-295,-297,-299,-304,-310,-313,-315,-319,
+-325,-331,-336,-342,-347,-350,-352,-359,-372,-384,-389,-390,-390,-392,-393,-392,-391,-393,-396,-400,-405,
+-406,-403,-398,-397,-400,-401,-396,-389,-386,-386,-386,-384,-383,-380,-369,-352,-338,-329,-322,-314,-306,
+-297,-287,-275,-264,-259,-258,-255,-252,-250,-247,-239,-227,-215,-203,-187,-169,-154,-146,-138,-124,-110,
+-101,-94,-79,-58,-40,-30,-23,-10,8,25,39,51,63,76,91,111,130,148,169,200,234,
+262,283,309,345,387,430,474,523,570,611,648,687,726,759,786,816,851,883,910,937,972,
+1013,1053,1089,1126,1165,1205,1250,1303,1362,1417,1463,1506,1553,1603,1649,1687,1723,1767,1828,1899,1960,
+1994,2019,2065,2114,2077,1878,1560,1303,1291,1576,2053,2566,3009,3357,3627,3845,4028,4178,4281,4331,4336,
+4320,4304,4299,4306,4316,4322,4324,4333,4359,4388,4385,4320,4176,3949,3644,3299,2975,2724,2548,2417,2316,
+2264,2279,2330,2357,2330,2273,2229,2211,2194,2148,2067,1970,1881,1815,1780,1770,1768,1754,1713,1649,1576,
+1509,1449,1389,1311,1200,1056,897,746,616,500,382,256,128,7,-108,-228,-352,-462,-540,-582,-605,
+-626,-655,-693,-734,-773,-802,-817,-819,-817,-811,-801,-788,-785,-805,-846,-889,-912,-908,-886,-856,-822,
+-787,-760,-755,-777,-812,-830,-809,-753,-695,-663,-656,-648,-628,-630,-702,-839,-967,-995,-900,-747,-631,
+-593,-599,-593,-562,-541,-561,-612,-667,-729,-825,-944,-1012,-964,-829,-721,-723,-807,-885,-908,-890,-853,
+-799,-739,-718,-762,-833,-863,-831,-780,-757,-752,-730,-683,-635,-605,-588,-571,-554,-541,-536,-539,-551,
+-565,-571,-568,-572,-588,-602,-594,-571,-558,-575,-609,-638,-656,-668,-678,-683,-681,-679,-678,-678,-674,
+-669,-665,-660,-651,-636,-619,-602,-584,-564,-543,-521,-499,-475,-447,-416,-383,-348,-315,-281,-247,-210,
+-173,-135,-98,-62,-26,12,54,97,138,178,218,257,297,338,379,420,459,494,529,562,594,
+624,655,688,724,759,791,824,862,903,943,982,1025,1075,1122,1156,1176,1187,1196,1203,1206,1206,
+1209,1217,1227,1232,1234,1237,1243,1252,1258,1262,1264,1272,1283,1295,1301,1303,1307,1314,1321,1326,1334,
+1347,1363,1375,1384,1398,1417,1436,1453,1468,1487,1507,1525,1541,1560,1582,1600,1613,1623,1631,1635,1633,
+1648,1653,1667,1686,1697,1699,1701,1710,1723,1735,1746,1762,1784,1806,1829,1853,1877,1898,1921,1953,1990,
+2025,2053,2080,2108,2129,2134,2127,2121,2123,2134,2155,2193,2245,2296,2329,2337,2325,2305,2293,2299,2319,
+2342,2357,2369,2387,2418,2462,2508,2541,2542,2510,2467,2448,2467,2504,2530,2541,2551,2576,2609,2640,2661,
+2679,2698,2716,2725,2719,2697,2665,2630,2598,2570,2545,2523,2495,2454,2399,2337,2276,2216,2150,2073,1987,
+1901,1824,1761,1707,1657,1612,1586,1587,1601,1602,1575,1524,1465,1409,1363,1335,1320,1301,1267,1223,1192,
+1179,1174,1163,1150,1145,1148,1152,1147,1136,1117,1085,1034,965,887,808,730,646,558,477,413,352,
+272,175,108,115,174,204,156,69,11,-9,-50,-149,-270,-349,-368,-359,-354,-373,-432,-544,-693,
+-827,-908,-941,-956,-965,-958,-926,-880,-848,-848,-884,-935,-967,-957,-921,-894,-887,-881,-864,-852,-860,
+-863,-823,-750,-704,-732,-796,-813,-741,-622,-534,-515,-541,-561,-534,-448,-316,-165,-30,67,124,149,
+143,95,7,-98,-201,-311,-462,-664,-870,-1013,-1070,-1076,-1077,-1084,-1083,-1073,-1068,-1075,-1081,-1076,-1063,
+-1053,-1051,-1056,-1065,-1071,-1065,-1045,-1021,-997,-957,-897,-845,-845,-909,-1010,-1118,-1203,-1213,-1089,-845,-623,
+-593,-790,-1062,-1220,-1208,-1116,-1048,-1020,-996,-960,-936,-941,-966,-993,-1017,-1039,-1057,-1073,-1093,-1109,-1109,
+-1093,-1082,-1092,-1112,-1122,-1119,-1124,-1149,-1181,-1201,-1213,-1232,-1262,-1296,-1327,-1357,-1391,-1430,-1470,-1509,-1548,
+-1588,-1632,-1682,-1737,-1793,-1848,-1905,-1965,-2025,-2086,-2151,-2221,-2288,-2344,-2391,-2439,-2491,-2539,-2581,-2624,-2675,
+-2733,-2793,-2852,-2913,-2970,-3017,-3056,-3097,-3147,-3202,-3255,-3307,-3359,-3408,-3449,-3485,-3523,-3566,-3609,-3651,-3696,
+-3745,-3792,-3833,-3870,-3909,-3951,-3992,-4028,-4063,-4101,-4146,-4199,-4254,-4303,-4338,-4361,-4381,-4404,-4428,-4451,-4474,
+-4498,-4524,-4544,-4554,-4556,-4552,-4543,-4530,-4518,-4508,-4495,-4466,-4421,-4382,-4372,-4400,-4453,-4517,-4591,-4674,-4745,
+-4779,-4774,-4759,-4760,-4775,-4780,-4766,-4747,-4740,-4744,-4748,-4750,-4757,-4775,-4800,-4826,-4848,-4858,-4852,-4835,-4819,
+-4812,-4811,-4810,-4807,-4799,-4782,-4757,-4736,-4733,-4747,-4762,-4769,-4769,-4773,-4781,-4786,-4782,-4764,-4732,-4690,-4650,
+-4621,-4602,-4579,-4541,-4484,-4416,-4350,-4296,-4254,-4213,-4163,-4103,-4043,-3987,-3930,-3863,-3791,-3724,-3665,-3612,-3564,
+-3521,-3485,-3451,-3421,-3398,-3378,-3348,-3302,-3250,-3200,-3152,-3097,-3036,-2979,-2928,-2873,-2812,-2757,-2717,-2688,-2654,
+-2611,-2559,-2501,-2437,-2378,-2336,-2302,-2254,-2180,-2096,-2021,-1961,-1907,-1856,-1812,-1757,-1662,-1514,-1339,-1178,-1048,
+-947,-869,-817,-787,-763,-729,-682,-624,-553,-469,-385,-311,-242,-154,-38,89,198,276,343,423,524,
+636,740,818,866,887,891,887,881,880,893,921,960,1000,1038,1079,1130,1187,1245,1304,1366,1428,
+1481,1525,1571,1628,1693,1757,1816,1878,1944,2009,2065,2115,2162,2208,2248,2283,2315,2346,2366,2369,2362,
+2354,2354,2362,2384,2427,2493,2571,2648,2725,2812,2912,3011,3096,3161,3213,3251,3271,3278,3294,3340,3414,
+3498,3572,3631,3680,3729,3783,3848,3931,4031,4141,4250,4351,4441,4514,4562,4579,4565,4533,4500,4475,4462,
+4464,4486,4531,4591,4653,4714,4779,4859,4958,5067,5174,5270,5350,5412,5454,5481,5505,5534,5568,5593,5601,
+5601,5607,5621,5628,5617,5603,5612,5652,5699,5726,5726,5713,5700,5689,5680,5677,5679,5683,5688,5697,5706,
+5706,5688,5656,5613,5556,5486,5415,5370,5363,5382,5405,5415,5414,5414,5427,5450,5467,5471,5476,5500,5532,
+5533,5499,5488,5562,5690,5762,5704,5571,5489,5522,5628,5727,5787,5818,5828,5799,5728,5643,5582,5561,5559,
+5545,5511,5494,5558,5730,5954,6125,6168,6100,6002,5944,5948,5998,6066,6113,6103,6025,5911,5799,5680,5498,
+5222,4928,4780,4906,5278,5727,6074,6263,6352,6410,6453,6466,6457,6455,6470,6481,6469,6444,6423,6406,6385,
+6357,6326,6289,6244,6200,6170,6148,6116,6064,6003,5945,5889,5831,5774,5715,5637,5524,5387,5264,5183,5146,
+5134,5128,5113,5078,5028,4990,4987,5014,5047,5072,5098,5134,5167,5174,5156,5134,5130,5149,5180,5209,5226,
+5230,5226,5223,5226,5237,5250,5231,5098,4756,4176,3468,2844,2488,2442,2590,2772,2887,2930,2938,2934,2915,
+2877,2829,2774,2702,2607,2506,2425,2369,2317,2252,2183,2130,2086,2020,1924,1826,1757,1714,1671,1618,1571,
+1543,1524,1495,1454,1416,1387,1361,1335,1311,1290,1267,1233,1196,1171,1157,1142,1115,1081,1052,1033,1016,
+992,965,941,922,903,884,874,881,898,908,896,865,824,775,713,640,573,531,513,500,477,
+446,416,391,365,329,286,242,206,178,156,138,122,106,84,55,28,8,-3,-21,-53,-94,
+-130,-154,-171,-195,-229,-270,-311,-347,-373,-390,-402,-418,-445,-482,-522,-562,-594,-612,-612,-607,-618,
+-657,-714,-755,-760,-738,-724,-741,-783,-823,-844,-849,-850,-855,-865,-879,-899,-923,-943,-947,-934,-914,
+-903,-917,-951,-986,-1002,-1000,-999,-1014,-1041,-1063,-1074,-1080,-1091,-1102,-1110,-1118,-1129,-1141,-1148,-1148,-1148,
+-1150,-1150,-1147,-1148,-1156,-1167,-1172,-1170,-1167,-1166,-1165,-1164,-1164,-1165,-1163,-1155,-1146,-1143,-1141,-1134,-1121,
+-1108,-1102,-1098,-1090,-1078,-1067,-1060,-1050,-1033,-1015,-1002,-995,-988,-980,-969,-956,-938,-915,-891,-869,-852,
+-837,-821,-802,-780,-756,-735,-720,-704,-685,-663,-643,-625,-608,-589,-572,-556,-542,-525,-507,-490,-473,
+-456,-440,-426,-413,-400,-385,-373,-363,-352,-338,-326,-319,-316,-311,-304,-297,-292,-286,-279,-271,-265,
+-257,-248,-241,-237,-234,-229,-224,-222,-224,-225,-226,-227,-233,-239,-242,-243,-247,-254,-263,-270,-276,
+-279,-281,-283,-285,-289,-293,-297,-302,-307,-311,-314,-316,-319,-322,-325,-331,-339,-345,-348,-352,-360,
+-371,-376,-374,-373,-376,-380,-380,-377,-377,-379,-382,-383,-384,-385,-382,-380,-381,-385,-385,-379,-372,
+-367,-363,-358,-355,-354,-354,-346,-332,-318,-307,-297,-289,-281,-273,-262,-248,-236,-232,-232,-231,-230,
+-229,-226,-216,-204,-193,-182,-166,-147,-132,-123,-112,-96,-82,-76,-70,-56,-34,-17,-9,-3,10,
+29,46,58,69,83,97,115,135,155,174,195,225,257,283,303,328,364,409,455,500,544,
+586,628,672,715,748,764,777,805,847,885,910,930,958,996,1036,1076,1118,1161,1200,1241,1291,
+1349,1404,1450,1489,1530,1574,1622,1671,1718,1762,1812,1877,1941,1978,1991,2018,2070,2076,1934,1645,1364,
+1300,1543,2013,2539,2989,3317,3546,3732,3919,4113,4272,4349,4345,4306,4281,4283,4294,4298,4296,4300,4325,
+4368,4405,4398,4316,4152,3911,3612,3285,2979,2735,2556,2416,2304,2245,2258,2310,2333,2292,2218,2170,2166,
+2175,2159,2112,2049,1987,1928,1872,1823,1780,1736,1682,1613,1538,1470,1413,1359,1288,1182,1043,888,742,
+613,496,381,264,144,24,-96,-217,-332,-429,-500,-547,-580,-612,-649,-690,-731,-765,-789,-799,-794,
+-783,-774,-771,-772,-780,-797,-822,-841,-840,-818,-788,-765,-752,-745,-743,-751,-770,-786,-776,-725,-650,
+-585,-554,-550,-546,-539,-561,-645,-773,-873,-873,-767,-619,-513,-484,-503,-518,-512,-513,-551,-622,-703,
+-791,-902,-1028,-1107,-1077,-953,-825,-766,-773,-796,-803,-794,-758,-681,-589,-553,-609,-701,-735,-690,-632,
+-627,-661,-676,-647,-608,-593,-597,-590,-559,-519,-496,-502,-532,-561,-573,-572,-579,-600,-611,-587,-538,
+-508,-525,-578,-631,-662,-674,-678,-678,-672,-666,-662,-660,-657,-653,-650,-645,-636,-622,-606,-590,-573,
+-552,-529,-507,-484,-461,-435,-409,-382,-351,-316,-280,-247,-213,-177,-137,-98,-61,-25,14,57,100,
+139,178,220,262,303,342,382,424,462,496,528,561,595,627,657,690,727,763,795,827,866,
+909,949,986,1028,1080,1130,1166,1185,1197,1207,1215,1215,1212,1212,1220,1231,1241,1247,1252,1257,1263,
+1267,1270,1272,1277,1288,1299,1305,1309,1313,1321,1329,1334,1342,1355,1370,1382,1391,1405,1424,1443,1457,
+1470,1489,1511,1528,1542,1560,1581,1599,1611,1621,1634,1643,1648,1663,1671,1682,1698,1708,1711,1717,1732,
+1751,1766,1778,1795,1819,1846,1871,1896,1920,1946,1977,2017,2060,2094,2119,2140,2164,2180,2179,2166,2160,
+2171,2197,2230,2271,2317,2357,2372,2357,2321,2287,2273,2282,2307,2334,2351,2361,2373,2400,2443,2495,2537,
+2549,2526,2486,2458,2460,2483,2510,2532,2556,2589,2629,2671,2711,2747,2777,2793,2791,2771,2740,2705,2677,
+2661,2659,2661,2654,2623,2564,2487,2410,2342,2277,2205,2124,2037,1953,1877,1809,1746,1687,1644,1629,1645,
+1670,1673,1643,1591,1534,1479,1434,1403,1386,1368,1338,1303,1282,1276,1269,1249,1226,1215,1217,1218,1206,
+1181,1145,1100,1042,975,901,825,743,651,550,451,372,314,261,202,161,167,212,241,215,150,
+91,48,-14,-114,-222,-292,-316,-321,-339,-384,-463,-576,-699,-787,-818,-810,-796,-789,-780,-762,-743,
+-740,-760,-803,-850,-873,-858,-826,-805,-801,-792,-770,-758,-774,-787,-756,-686,-641,-661,-716,-729,-667,
+-566,-490,-467,-477,-481,-447,-365,-242,-102,28,128,185,196,158,82,-3,-79,-152,-261,-434,-651,
+-847,-968,-1014,-1027,-1036,-1040,-1030,-1017,-1016,-1026,-1029,-1018,-1004,-998,-997,-999,-1007,-1018,-1017,-994,-946,
+-871,-761,-624,-510,-489,-587,-767,-952,-1077,-1094,-994,-827,-708,-734,-890,-1054,-1117,-1076,-1009,-971,-950,
+-920,-887,-872,-876,-884,-892,-911,-943,-973,-997,-1021,-1046,-1058,-1051,-1037,-1035,-1042,-1046,-1046,-1058,-1086,
+-1116,-1135,-1146,-1166,-1198,-1232,-1261,-1288,-1317,-1350,-1384,-1419,-1455,-1494,-1538,-1589,-1645,-1700,-1753,-1809,-1869,
+-1932,-1993,-2057,-2124,-2190,-2247,-2297,-2347,-2396,-2441,-2479,-2520,-2572,-2636,-2701,-2764,-2820,-2870,-2913,-2955,-3004,
+-3059,-3115,-3168,-3221,-3273,-3319,-3357,-3393,-3434,-3479,-3523,-3564,-3610,-3661,-3711,-3753,-3789,-3827,-3868,-3909,-3946,
+-3980,-4017,-4060,-4110,-4164,-4215,-4253,-4278,-4297,-4316,-4337,-4358,-4379,-4401,-4420,-4433,-4438,-4440,-4440,-4438,-4433,
+-4429,-4428,-4424,-4403,-4368,-4338,-4335,-4365,-4416,-4479,-4553,-4635,-4703,-4732,-4724,-4709,-4711,-4724,-4727,-4713,-4698,
+-4699,-4714,-4727,-4734,-4740,-4756,-4783,-4814,-4837,-4841,-4825,-4804,-4790,-4787,-4786,-4780,-4772,-4763,-4748,-4727,-4711,
+-4712,-4732,-4753,-4765,-4770,-4774,-4780,-4782,-4777,-4762,-4734,-4693,-4648,-4611,-4582,-4556,-4526,-4487,-4437,-4376,-4313,
+-4257,-4207,-4153,-4091,-4029,-3975,-3920,-3857,-3787,-3721,-3666,-3620,-3579,-3544,-3515,-3485,-3452,-3423,-3398,-3368,-3323,
+-3267,-3213,-3165,-3117,-3066,-3019,-2974,-2922,-2863,-2807,-2768,-2743,-2719,-2687,-2646,-2591,-2520,-2444,-2380,-2332,-2287,
+-2232,-2168,-2105,-2045,-1985,-1928,-1870,-1786,-1647,-1461,-1281,-1156,-1087,-1033,-964,-889,-830,-792,-762,-728,-685,
+-629,-558,-482,-412,-345,-261,-150,-25,87,177,253,329,416,512,609,695,760,798,816,821,818,
+814,822,846,881,915,944,979,1028,1084,1141,1199,1261,1326,1383,1428,1473,1531,1596,1655,1704,1755,
+1816,1880,1934,1974,2009,2048,2092,2140,2191,2242,2286,2314,2328,2334,2338,2344,2360,2395,2452,2517,2580,
+2642,2717,2810,2912,3006,3088,3153,3197,3213,3214,3227,3273,3350,3434,3503,3556,3601,3648,3707,3781,3871,
+3968,4069,4174,4285,4393,4477,4522,4529,4514,4492,4470,4446,4426,4418,4428,4458,4501,4553,4609,4671,4740,
+4822,4918,5022,5122,5209,5279,5333,5373,5404,5436,5472,5506,5525,5532,5541,5562,5585,5592,5585,5585,5609,
+5649,5682,5691,5679,5661,5647,5639,5635,5632,5633,5642,5661,5680,5683,5667,5637,5592,5526,5445,5373,5337,
+5335,5345,5349,5352,5363,5380,5395,5402,5409,5423,5452,5493,5520,5503,5447,5417,5479,5617,5724,5706,5586,
+5476,5469,5558,5676,5768,5820,5837,5815,5755,5674,5600,5551,5524,5501,5468,5444,5475,5599,5802,6015,6161,
+6204,6160,6073,5993,5961,5992,6063,6117,6109,6034,5921,5786,5604,5344,5044,4833,4853,5133,5551,5929,6169,
+6294,6369,6423,6447,6443,6436,6442,6448,6436,6411,6389,6371,6349,6320,6288,6256,6222,6191,6165,6138,6094,
+6035,5975,5930,5890,5838,5764,5670,5562,5446,5340,5263,5219,5193,5167,5135,5095,5050,5009,4991,5005,5035,
+5061,5082,5117,5165,5201,5201,5175,5154,5159,5185,5215,5237,5246,5247,5244,5243,5251,5270,5287,5252,5071,
+4654,4012,3298,2735,2477,2504,2674,2833,2917,2941,2940,2927,2898,2854,2807,2757,2694,2610,2517,2433,2366,
+2302,2233,2166,2112,2059,1987,1892,1800,1733,1689,1647,1601,1562,1537,1517,1486,1446,1411,1388,1371,1352,
+1330,1303,1271,1233,1201,1181,1171,1156,1128,1097,1072,1054,1034,1009,983,964,948,926,897,870,853,
+841,823,797,775,766,756,722,658,584,530,504,488,464,430,396,372,350,322,284,241,199,
+163,134,116,105,94,78,57,37,24,9,-24,-79,-139,-179,-196,-204,-223,-255,-292,-327,-360,
+-390,-414,-431,-447,-471,-504,-539,-571,-599,-624,-643,-654,-663,-685,-723,-758,-766,-744,-721,-728,-770,
+-823,-859,-875,-881,-883,-883,-883,-893,-920,-954,-978,-977,-953,-927,-917,-929,-953,-973,-984,-996,-1019,
+-1052,-1081,-1101,-1114,-1123,-1128,-1128,-1129,-1134,-1143,-1149,-1151,-1152,-1155,-1154,-1149,-1149,-1158,-1170,-1177,-1177,
+-1176,-1176,-1175,-1171,-1168,-1168,-1169,-1165,-1156,-1151,-1149,-1145,-1134,-1122,-1113,-1108,-1100,-1089,-1078,-1069,-1056,
+-1038,-1020,-1006,-999,-991,-981,-969,-958,-945,-929,-907,-882,-857,-837,-821,-804,-782,-758,-737,-721,-707,
+-689,-667,-645,-625,-607,-590,-573,-558,-543,-528,-511,-493,-477,-461,-446,-433,-421,-407,-393,-381,-369,
+-357,-344,-335,-328,-323,-317,-310,-305,-301,-296,-289,-282,-275,-267,-259,-253,-249,-246,-240,-235,-233,
+-233,-234,-234,-237,-243,-249,-252,-252,-254,-258,-264,-270,-277,-283,-287,-291,-293,-293,-295,-299,-304,
+-309,-311,-312,-315,-319,-320,-321,-326,-336,-344,-347,-351,-358,-365,-366,-361,-360,-364,-366,-363,-359,
+-360,-365,-367,-366,-365,-365,-364,-364,-365,-367,-366,-359,-351,-345,-339,-332,-327,-328,-330,-324,-312,
+-298,-286,-275,-264,-256,-248,-236,-221,-208,-203,-203,-204,-203,-203,-199,-189,-176,-164,-153,-140,-126,
+-114,-104,-90,-70,-54,-46,-41,-28,-11,2,11,22,39,55,63,69,80,97,116,136,160,
+184,205,224,247,273,299,324,353,390,432,477,522,566,609,654,703,748,774,777,777,798,
+838,877,904,928,959,996,1032,1069,1111,1156,1197,1236,1282,1336,1388,1436,1478,1516,1551,1592,1647,
+1709,1760,1802,1853,1913,1955,1964,1976,2022,2056,1969,1723,1443,1344,1550,2005,2536,2981,3274,3444,3581,
+3769,4014,4237,4351,4347,4295,4269,4278,4290,4285,4278,4290,4325,4366,4384,4352,4251,4079,3847,3568,3267,
+2982,2747,2566,2418,2297,2233,2247,2298,2311,2248,2152,2101,2117,2157,2168,2138,2089,2040,1986,1920,1845,
+1774,1713,1656,1594,1526,1459,1402,1351,1285,1183,1044,890,746,620,504,391,278,163,42,-83,-206,
+-313,-397,-460,-509,-550,-590,-632,-675,-715,-747,-770,-779,-771,-752,-735,-730,-740,-758,-780,-799,-805,
+-788,-750,-710,-685,-683,-693,-705,-717,-728,-727,-699,-638,-562,-500,-469,-461,-461,-470,-512,-595,-696,
+-760,-751,-672,-566,-483,-451,-463,-491,-514,-538,-582,-655,-744,-844,-957,-1076,-1152,-1134,-1022,-874,-761,
+-706,-701,-732,-776,-782,-711,-593,-516,-533,-588,-586,-509,-434,-439,-507,-562,-569,-559,-573,-600,-599,
+-550,-481,-439,-448,-495,-546,-574,-580,-589,-608,-613,-576,-511,-469,-487,-553,-622,-663,-675,-675,-669,
+-660,-651,-646,-645,-645,-642,-639,-634,-625,-613,-598,-582,-563,-541,-517,-494,-471,-447,-421,-397,-373,
+-344,-308,-270,-237,-207,-173,-134,-93,-56,-20,20,64,106,143,182,225,270,310,346,385,425,
+463,495,524,557,592,625,657,692,731,767,798,831,871,915,954,988,1029,1080,1132,1169,1191,
+1206,1219,1226,1225,1220,1220,1227,1239,1249,1259,1266,1270,1272,1274,1277,1280,1284,1291,1300,1306,1309,
+1315,1323,1332,1338,1344,1355,1368,1379,1388,1404,1425,1444,1456,1468,1487,1510,1528,1541,1557,1577,1593,
+1603,1614,1632,1651,1663,1673,1682,1692,1706,1718,1726,1737,1758,1782,1801,1815,1834,1860,1889,1917,1945,
+1974,2007,2048,2095,2139,2167,2179,2188,2204,2218,2218,2208,2209,2232,2266,2296,2320,2344,2363,2364,2336,
+2293,2259,2248,2261,2285,2307,2323,2335,2351,2378,2419,2473,2526,2559,2560,2535,2503,2485,2490,2512,2544,
+2578,2614,2654,2700,2752,2802,2839,2851,2838,2809,2778,2756,2746,2751,2767,2785,2782,2743,2666,2574,2487,
+2413,2341,2262,2175,2088,2006,1929,1856,1789,1732,1696,1690,1708,1726,1720,1685,1635,1584,1534,1489,1455,
+1433,1415,1391,1368,1359,1360,1352,1323,1287,1263,1255,1245,1223,1188,1143,1092,1036,976,911,838,756,
+662,560,459,378,329,304,287,273,274,293,304,279,218,146,77,2,-82,-162,-216,-249,-281,
+-328,-394,-475,-566,-644,-686,-686,-663,-641,-625,-612,-606,-617,-647,-689,-735,-773,-787,-772,-745,-727,
+-720,-706,-686,-680,-699,-710,-677,-612,-567,-575,-607,-605,-552,-478,-426,-409,-408,-392,-342,-256,-149,
+-41,59,153,224,237,174,65,-28,-77,-120,-223,-410,-631,-808,-904,-945,-970,-990,-994,-980,-967,
+-970,-976,-969,-951,-939,-941,-947,-948,-947,-947,-940,-910,-844,-728,-547,-320,-128,-72,-201,-463,-743,
+-940,-1012,-977,-901,-857,-885,-957,-1005,-992,-946,-909,-890,-868,-836,-815,-817,-825,-822,-816,-829,-860,
+-891,-911,-928,-947,-958,-952,-941,-940,-952,-966,-979,-997,-1023,-1049,-1066,-1080,-1103,-1134,-1165,-1190,-1214,
+-1241,-1271,-1304,-1339,-1376,-1414,-1456,-1506,-1561,-1614,-1665,-1720,-1780,-1842,-1903,-1964,-2027,-2091,-2150,-2203,-2253,
+-2300,-2341,-2378,-2420,-2475,-2542,-2610,-2672,-2724,-2768,-2809,-2857,-2914,-2974,-3030,-3082,-3135,-3187,-3232,-3267,-3303,
+-3346,-3393,-3438,-3480,-3528,-3580,-3630,-3671,-3706,-3743,-3784,-3826,-3864,-3899,-3935,-3975,-4023,-4076,-4128,-4168,-4196,
+-4215,-4232,-4249,-4266,-4284,-4304,-4320,-4329,-4330,-4332,-4336,-4342,-4347,-4351,-4357,-4356,-4341,-4313,-4291,-4291,-4318,
+-4367,-4432,-4511,-4594,-4655,-4677,-4669,-4658,-4664,-4678,-4680,-4668,-4660,-4671,-4693,-4712,-4719,-4722,-4735,-4762,-4795,
+-4818,-4818,-4799,-4777,-4766,-4763,-4757,-4744,-4729,-4718,-4708,-4693,-4683,-4688,-4709,-4734,-4753,-4766,-4775,-4779,-4778,
+-4771,-4756,-4729,-4689,-4643,-4600,-4563,-4532,-4505,-4480,-4444,-4392,-4328,-4265,-4210,-4151,-4085,-4020,-3962,-3907,-3842,
+-3769,-3703,-3649,-3607,-3573,-3552,-3542,-3526,-3496,-3457,-3421,-3385,-3340,-3282,-3224,-3175,-3135,-3097,-3058,-3017,-2968,
+-2912,-2859,-2820,-2792,-2768,-2743,-2716,-2677,-2614,-2532,-2448,-2382,-2332,-2287,-2241,-2187,-2124,-2053,-1982,-1907,-1799,
+-1633,-1430,-1255,-1155,-1111,-1063,-983,-894,-830,-800,-780,-754,-719,-675,-620,-559,-498,-436,-357,-251,-127,
+-7,94,177,250,321,397,481,565,637,690,728,751,760,757,758,773,800,826,848,877,923,
+978,1033,1087,1146,1209,1266,1315,1365,1425,1488,1540,1582,1631,1693,1758,1805,1834,1862,1904,1963,2028,
+2094,2160,2219,2264,2295,2315,2332,2349,2373,2409,2460,2517,2572,2624,2683,2755,2838,2927,3014,3090,3142,
+3162,3166,3181,3227,3295,3365,3422,3469,3513,3562,3625,3704,3798,3895,3992,4097,4217,4339,4428,4464,4458,
+4441,4430,4421,4403,4383,4373,4379,4396,4421,4460,4515,4580,4643,4708,4783,4874,4969,5056,5133,5201,5259,
+5305,5342,5380,5418,5446,5458,5468,5491,5527,5557,5565,5561,5565,5588,5619,5638,5635,5616,5597,5585,5581,
+5581,5587,5602,5627,5649,5658,5650,5625,5576,5497,5404,5334,5307,5307,5303,5288,5291,5326,5374,5401,5395,
+5379,5379,5403,5440,5464,5453,5414,5396,5458,5595,5720,5737,5633,5496,5428,5466,5571,5681,5758,5792,5789,
+5758,5707,5646,5583,5527,5481,5443,5414,5411,5466,5601,5804,6026,6199,6273,6237,6130,6018,5959,5974,6034,
+6087,6090,6031,5918,5751,5514,5218,4953,4861,5023,5380,5772,6063,6226,6315,6375,6413,6426,6426,6425,6419,
+6401,6376,6354,6336,6315,6287,6260,6233,6204,6171,6135,6095,6047,5997,5960,5937,5908,5844,5737,5603,5476,
+5382,5332,5313,5296,5257,5196,5130,5072,5027,4997,4994,5017,5050,5078,5105,5149,5202,5234,5225,5192,5171,
+5182,5212,5241,5259,5268,5270,5268,5264,5266,5279,5284,5215,4968,4475,3793,3112,2651,2505,2597,2764,2885,
+2936,2948,2945,2926,2886,2833,2780,2730,2672,2599,2514,2429,2353,2286,2222,2160,2100,2038,1964,1880,1798,
+1730,1677,1629,1588,1556,1533,1508,1471,1429,1396,1378,1368,1358,1339,1309,1270,1231,1204,1191,1183,1166,
+1140,1115,1094,1076,1055,1037,1028,1024,1009,971,918,867,829,795,755,715,693,697,707,694,645,
+580,527,498,479,455,420,384,354,328,298,262,223,184,149,122,107,97,84,61,33,14,
+6,-4,-39,-101,-166,-207,-221,-227,-244,-275,-306,-333,-361,-396,-433,-462,-483,-503,-530,-558,-584,
+-607,-633,-661,-681,-689,-695,-717,-749,-771,-766,-747,-746,-776,-821,-859,-881,-895,-907,-911,-909,-908,
+-923,-953,-985,-1002,-998,-980,-961,-952,-958,-971,-985,-1000,-1019,-1044,-1070,-1092,-1112,-1127,-1137,-1139,-1137,
+-1139,-1144,-1147,-1149,-1149,-1151,-1152,-1151,-1154,-1164,-1176,-1181,-1180,-1179,-1180,-1181,-1178,-1174,-1173,-1176,-1175,
+-1168,-1161,-1158,-1156,-1149,-1137,-1126,-1118,-1112,-1103,-1093,-1082,-1067,-1049,-1031,-1017,-1008,-999,-987,-974,-961,
+-950,-937,-918,-892,-863,-837,-818,-802,-784,-761,-737,-719,-703,-687,-666,-642,-621,-604,-589,-574,-560,
+-547,-532,-516,-500,-483,-468,-455,-441,-428,-415,-402,-390,-377,-364,-354,-347,-340,-332,-323,-316,-312,
+-309,-304,-297,-290,-283,-276,-270,-267,-264,-260,-255,-250,-249,-249,-248,-247,-249,-254,-258,-261,-262,
+-263,-265,-267,-270,-275,-281,-289,-297,-301,-302,-301,-303,-307,-308,-307,-307,-311,-316,-317,-316,-321,
+-331,-338,-341,-343,-349,-355,-356,-353,-352,-353,-351,-344,-341,-344,-351,-353,-351,-349,-349,-348,-346,
+-345,-345,-342,-337,-330,-324,-318,-310,-307,-308,-309,-302,-289,-277,-266,-254,-242,-232,-223,-211,-197,
+-185,-181,-180,-178,-175,-173,-169,-161,-147,-135,-123,-112,-102,-95,-88,-73,-51,-31,-19,-12,-2,
+9,20,31,48,67,77,78,80,92,112,132,152,175,202,224,241,259,283,313,346,382,
+418,455,495,541,592,642,689,734,771,790,790,790,806,834,862,888,920,961,999,1030,1061,
+1102,1146,1185,1224,1270,1321,1368,1414,1462,1508,1543,1578,1633,1703,1762,1798,1834,1889,1939,1956,1962,
+2002,2047,1992,1776,1501,1381,1561,2003,2532,2966,3221,3335,3428,3612,3895,4171,4322,4332,4286,4268,4280,
+4280,4259,4247,4270,4312,4340,4332,4277,4170,4006,3790,3529,3243,2965,2729,2544,2394,2276,2219,2239,2293,
+2297,2216,2105,2055,2092,2155,2178,2146,2095,2048,1998,1927,1839,1752,1685,1636,1592,1539,1478,1420,1365,
+1297,1192,1052,900,761,640,525,408,290,173,50,-77,-198,-296,-370,-428,-477,-522,-565,-607,-648,
+-683,-711,-734,-750,-751,-736,-715,-702,-707,-725,-748,-767,-773,-755,-715,-668,-635,-623,-626,-633,-640,
+-644,-640,-615,-566,-504,-453,-421,-406,-403,-419,-464,-530,-594,-631,-635,-614,-575,-530,-498,-497,-524,
+-557,-585,-620,-683,-777,-886,-995,-1095,-1159,-1150,-1058,-915,-781,-701,-696,-761,-857,-910,-864,-741,-631,
+-594,-593,-547,-442,-353,-350,-420,-488,-517,-534,-570,-610,-610,-554,-476,-426,-435,-488,-548,-584,-595,
+-602,-615,-616,-581,-521,-482,-499,-561,-626,-662,-670,-667,-660,-650,-639,-634,-634,-635,-632,-627,-621,
+-614,-603,-587,-569,-547,-523,-499,-477,-455,-431,-404,-378,-354,-325,-289,-252,-219,-190,-158,-120,-80,
+-45,-10,28,71,113,151,189,231,274,313,347,383,422,459,490,520,555,591,627,661,698,
+736,770,800,834,876,919,955,986,1025,1076,1128,1166,1191,1210,1227,1235,1233,1230,1232,1239,1246,
+1252,1260,1270,1274,1275,1276,1281,1288,1293,1299,1305,1310,1313,1316,1324,1334,1342,1348,1356,1367,1377,
+1389,1406,1428,1446,1457,1468,1487,1511,1531,1547,1563,1582,1595,1601,1611,1632,1657,1673,1680,1691,1703,
+1720,1737,1751,1767,1789,1813,1833,1850,1872,1902,1935,1967,2000,2036,2074,2116,2160,2197,2213,2212,2212,
+2228,2252,2265,2265,2272,2296,2323,2332,2322,2313,2313,2312,2295,2265,2239,2232,2240,2254,2268,2286,2308,
+2334,2363,2400,2451,2511,2563,2591,2586,2559,2531,2521,2537,2573,2615,2657,2699,2746,2799,2850,2885,2893,
+2876,2849,2828,2821,2827,2843,2864,2882,2878,2834,2751,2653,2564,2485,2405,2315,2221,2133,2050,1970,1890,
+1819,1766,1739,1738,1754,1763,1748,1710,1665,1622,1579,1534,1493,1465,1443,1423,1409,1410,1418,1410,1377,
+1334,1301,1279,1257,1223,1180,1132,1080,1029,977,922,856,779,696,612,532,465,427,420,427,425,
+409,388,361,317,252,174,97,27,-34,-86,-130,-176,-233,-302,-377,-450,-510,-547,-556,-545,-528,
+-512,-496,-483,-489,-523,-574,-621,-657,-682,-695,-692,-678,-663,-649,-632,-615,-614,-628,-629,-595,-538,
+-496,-485,-483,-460,-413,-365,-337,-330,-327,-303,-240,-146,-55,12,72,153,236,258,178,41,-60,
+-88,-105,-203,-396,-609,-758,-829,-867,-908,-941,-947,-931,-919,-920,-918,-900,-877,-871,-884,-896,-895,
+-882,-866,-847,-814,-748,-618,-396,-108,146,237,100,-204,-542,-796,-927,-964,-961,-956,-958,-949,-918,
+-873,-838,-821,-806,-777,-749,-744,-760,-772,-767,-759,-773,-802,-828,-841,-851,-863,-870,-864,-858,-865,
+-884,-906,-923,-939,-959,-979,-998,-1019,-1045,-1071,-1094,-1115,-1138,-1165,-1196,-1230,-1267,-1305,-1341,-1379,-1426,
+-1479,-1533,-1584,-1637,-1696,-1757,-1815,-1872,-1930,-1992,-2053,-2108,-2157,-2200,-2239,-2278,-2326,-2384,-2451,-2518,-2577,
+-2627,-2669,-2711,-2763,-2824,-2886,-2941,-2993,-3046,-3099,-3144,-3180,-3216,-3260,-3308,-3354,-3400,-3449,-3501,-3546,-3582,
+-3614,-3652,-3695,-3738,-3778,-3815,-3850,-3889,-3934,-3985,-4036,-4077,-4107,-4129,-4148,-4164,-4180,-4197,-4214,-4228,-4233,
+-4233,-4235,-4242,-4254,-4267,-4281,-4291,-4291,-4279,-4258,-4242,-4242,-4263,-4307,-4374,-4458,-4541,-4595,-4611,-4605,-4604,
+-4618,-4633,-4632,-4622,-4622,-4643,-4674,-4696,-4703,-4704,-4713,-4736,-4766,-4787,-4787,-4769,-4748,-4738,-4734,-4724,-4705,
+-4686,-4675,-4667,-4659,-4657,-4667,-4689,-4716,-4740,-4760,-4776,-4782,-4777,-4766,-4749,-4723,-4685,-4642,-4599,-4559,-4521,
+-4489,-4461,-4431,-4387,-4331,-4273,-4216,-4152,-4081,-4010,-3947,-3886,-3813,-3734,-3664,-3611,-3570,-3541,-3534,-3545,-3552,
+-3531,-3487,-3440,-3400,-3355,-3296,-3234,-3185,-3152,-3125,-3094,-3054,-3008,-2960,-2918,-2883,-2850,-2815,-2783,-2759,-2735,
+-2690,-2617,-2530,-2452,-2394,-2351,-2311,-2260,-2191,-2106,-2015,-1920,-1795,-1621,-1421,-1254,-1154,-1095,-1025,-933,-855,
+-821,-817,-806,-774,-732,-695,-658,-617,-569,-513,-435,-329,-203,-79,25,109,176,236,299,371,447,
+519,583,640,686,708,707,699,703,721,743,761,785,822,871,921,971,1026,1088,1148,1204,1262,
+1327,1387,1434,1475,1526,1593,1655,1695,1718,1748,1803,1878,1954,2023,2085,2142,2189,2226,2259,2297,2340,
+2385,2430,2479,2533,2589,2643,2693,2742,2797,2865,2944,3022,3079,3106,3118,3141,3185,3242,3295,3340,3382,
+3428,3480,3544,3627,3724,3824,3919,4022,4144,4268,4358,4389,4380,4367,4365,4364,4353,4337,4333,4340,4348,
+4356,4382,4435,4502,4562,4612,4668,4742,4826,4908,4985,5063,5140,5205,5254,5296,5337,5373,5393,5405,5425,
+5463,5504,5527,5527,5522,5529,5551,5572,5577,5563,5542,5526,5520,5524,5536,5556,5580,5603,5618,5621,5606,
+5558,5472,5374,5304,5276,5265,5239,5208,5214,5273,5350,5392,5386,5358,5342,5346,5363,5382,5395,5397,5406,
+5458,5566,5681,5724,5655,5520,5410,5392,5464,5571,5661,5709,5723,5721,5712,5685,5631,5557,5483,5427,5388,
+5364,5364,5423,5569,5793,6037,6222,6297,6259,6147,6019,5930,5914,5962,6023,6047,6008,5901,5714,5441,5135,
+4930,4957,5225,5608,5943,6151,6256,6313,6352,6377,6392,6399,6394,6375,6347,6319,6295,6271,6246,6223,6202,
+6174,6136,6094,6051,6011,5979,5958,5940,5898,5807,5668,5516,5396,5337,5334,5349,5336,5277,5193,5116,5061,
+5023,4998,4994,5017,5056,5093,5130,5177,5226,5249,5233,5199,5184,5199,5231,5259,5276,5286,5291,5288,5278,
+5267,5258,5225,5092,4762,4202,3515,2914,2584,2553,2693,2843,2925,2952,2961,2959,2934,2883,2822,2764,2710,
+2652,2586,2510,2431,2358,2293,2233,2168,2099,2029,1961,1894,1823,1750,1680,1623,1582,1554,1529,1495,1453,
+1410,1379,1363,1357,1351,1337,1308,1267,1228,1204,1194,1186,1171,1149,1130,1112,1090,1071,1067,1085,1103,
+1090,1033,950,874,818,774,728,681,650,641,641,630,598,555,516,491,471,449,419,383,345,
+307,269,230,192,157,126,105,95,90,76,42,0,-29,-38,-41,-65,-116,-175,-215,-233,-245,
+-268,-300,-330,-353,-377,-411,-452,-489,-514,-532,-552,-576,-599,-619,-640,-665,-688,-698,-702,-715,-746,
+-780,-795,-790,-786,-800,-827,-851,-869,-888,-914,-936,-943,-937,-934,-944,-968,-997,-1019,-1025,-1017,-1004,
+-998,-1003,-1013,-1021,-1025,-1027,-1033,-1044,-1062,-1085,-1106,-1119,-1124,-1128,-1136,-1143,-1147,-1146,-1146,-1147,-1150,
+-1156,-1166,-1177,-1181,-1178,-1174,-1175,-1177,-1176,-1173,-1172,-1174,-1174,-1170,-1165,-1163,-1164,-1161,-1151,-1139,-1130,
+-1126,-1120,-1111,-1099,-1084,-1067,-1050,-1034,-1021,-1010,-998,-983,-967,-953,-941,-925,-901,-871,-842,-819,-801,
+-784,-762,-738,-718,-701,-684,-664,-642,-621,-604,-591,-579,-566,-553,-539,-523,-506,-491,-477,-463,-447,
+-432,-418,-407,-395,-382,-371,-363,-358,-351,-341,-331,-324,-320,-315,-308,-300,-293,-287,-282,-280,-279,
+-278,-273,-268,-265,-264,-263,-261,-261,-262,-264,-266,-268,-271,-274,-277,-277,-277,-278,-281,-288,-296,
+-303,-305,-304,-305,-307,-307,-304,-302,-306,-311,-312,-311,-315,-323,-330,-331,-331,-335,-342,-346,-344,
+-343,-341,-336,-329,-327,-333,-339,-340,-338,-336,-336,-333,-328,-324,-322,-320,-317,-313,-309,-302,-295,
+-291,-291,-288,-277,-262,-250,-241,-231,-218,-207,-198,-188,-176,-166,-163,-161,-157,-151,-146,-143,-137,
+-126,-113,-99,-86,-77,-73,-68,-55,-35,-14,0,10,20,29,39,52,71,88,94,93,98,
+116,138,156,171,192,216,236,253,274,301,335,371,408,445,480,520,570,628,685,728,755,
+768,773,780,798,824,844,855,871,907,954,992,1019,1048,1090,1132,1167,1205,1255,1308,1349,1387,
+1437,1493,1539,1577,1632,1705,1765,1795,1820,1871,1929,1957,1966,2002,2049,2004,1797,1521,1388,1555,1988,
+2509,2929,3161,3247,3316,3493,3788,4088,4264,4298,4277,4277,4291,4276,4239,4222,4247,4283,4291,4263,4205,
+4111,3966,3763,3509,3224,2938,2690,2495,2347,2240,2195,2224,2280,2281,2195,2086,2046,2096,2167,2186,2145,
+2090,2045,1998,1922,1821,1721,1650,1612,1588,1557,1509,1450,1386,1307,1198,1059,914,783,667,549,424,
+297,174,51,-72,-185,-274,-341,-397,-449,-497,-539,-579,-616,-645,-667,-688,-711,-728,-728,-712,-694,
+-688,-695,-712,-731,-743,-736,-706,-661,-617,-582,-557,-539,-532,-536,-543,-538,-511,-469,-428,-397,-377,
+-369,-380,-413,-457,-495,-521,-547,-575,-590,-579,-556,-551,-573,-598,-609,-625,-684,-792,-916,-1020,-1096,
+-1142,-1145,-1091,-990,-885,-822,-825,-890,-981,-1038,-1011,-912,-810,-754,-726,-668,-567,-479,-457,-492,-532,
+-551,-568,-603,-638,-637,-590,-527,-487,-491,-528,-573,-600,-607,-608,-616,-621,-605,-569,-545,-558,-602,
+-643,-661,-661,-657,-652,-643,-633,-626,-626,-626,-621,-614,-607,-599,-586,-568,-546,-523,-499,-475,-454,
+-434,-412,-386,-359,-333,-303,-269,-233,-200,-169,-137,-99,-61,-28,3,39,80,122,160,198,238,
+277,312,345,380,417,453,487,521,559,598,634,671,708,745,776,804,839,882,923,956,985,
+1026,1080,1132,1168,1191,1212,1230,1238,1236,1235,1241,1247,1248,1247,1253,1264,1272,1273,1274,1281,1291,
+1298,1303,1308,1313,1315,1316,1322,1332,1342,1350,1359,1371,1384,1399,1417,1437,1454,1465,1477,1496,1522,
+1545,1562,1577,1594,1605,1611,1619,1638,1662,1680,1691,1705,1721,1740,1761,1780,1799,1819,1840,1860,1881,
+1909,1943,1980,2017,2055,2091,2123,2155,2187,2215,2226,2224,2227,2253,2291,2317,2325,2331,2347,2359,2344,
+2302,2262,2248,2254,2258,2249,2236,2229,2228,2231,2241,2262,2295,2328,2356,2387,2433,2495,2559,2603,2615,
+2599,2576,2566,2579,2614,2662,2715,2769,2820,2866,2901,2923,2928,2918,2904,2895,2896,2903,2910,2918,2923,
+2913,2871,2796,2707,2624,2544,2457,2358,2258,2166,2081,1994,1908,1835,1785,1764,1767,1781,1787,1770,1735,
+1696,1659,1620,1575,1530,1496,1471,1451,1441,1444,1452,1444,1411,1367,1330,1298,1263,1218,1171,1124,1078,
+1034,992,947,894,834,777,726,679,634,602,592,592,575,529,462,393,327,261,195,136,87,
+44,2,-43,-101,-169,-245,-317,-377,-415,-430,-426,-419,-416,-413,-404,-398,-415,-458,-505,-532,-539,
+-547,-565,-585,-595,-592,-578,-561,-548,-548,-555,-550,-520,-475,-432,-397,-363,-324,-286,-259,-246,-247,
+-252,-232,-164,-60,28,70,97,160,245,268,173,19,-81,-90,-93,-192,-389,-588,-706,-755,-792,
+-844,-884,-889,-871,-859,-857,-849,-827,-807,-809,-826,-838,-831,-810,-783,-756,-726,-676,-564,-355,-68,
+196,302,185,-101,-427,-680,-827,-895,-922,-924,-902,-859,-812,-778,-762,-749,-724,-692,-674,-682,-702,
+-711,-705,-705,-723,-752,-773,-786,-798,-811,-818,-816,-816,-827,-846,-863,-873,-882,-895,-913,-935,-961,
+-985,-1004,-1021,-1040,-1065,-1094,-1127,-1162,-1199,-1235,-1267,-1300,-1343,-1395,-1450,-1503,-1556,-1614,-1674,-1730,-1784,
+-1839,-1898,-1958,-2013,-2060,-2100,-2137,-2180,-2234,-2297,-2362,-2425,-2482,-2532,-2578,-2623,-2676,-2736,-2796,-2850,-2902,
+-2957,-3011,-3057,-3094,-3131,-3176,-3226,-3275,-3325,-3374,-3420,-3457,-3487,-3518,-3557,-3603,-3648,-3690,-3729,-3766,-3803,
+-3844,-3891,-3939,-3982,-4015,-4042,-4064,-4083,-4100,-4115,-4129,-4137,-4140,-4140,-4146,-4158,-4175,-4195,-4214,-4228,-4229,
+-4218,-4202,-4191,-4189,-4201,-4237,-4303,-4392,-4476,-4527,-4541,-4541,-4552,-4574,-4589,-4586,-4577,-4584,-4613,-4649,-4675,
+-4683,-4684,-4691,-4709,-4734,-4751,-4751,-4734,-4716,-4705,-4699,-4687,-4668,-4650,-4638,-4632,-4629,-4634,-4651,-4675,-4701,
+-4726,-4750,-4770,-4777,-4770,-4756,-4737,-4712,-4678,-4639,-4602,-4563,-4520,-4476,-4438,-4404,-4367,-4322,-4271,-4214,-4145,
+-4067,-3993,-3926,-3855,-3768,-3676,-3601,-3550,-3516,-3497,-3503,-3533,-3558,-3550,-3508,-3458,-3416,-3371,-3309,-3240,-3187,
+-3158,-3140,-3116,-3079,-3038,-3003,-2978,-2955,-2921,-2875,-2828,-2797,-2775,-2743,-2686,-2609,-2533,-2469,-2417,-2370,-2313,
+-2234,-2132,-2016,-1895,-1756,-1589,-1412,-1263,-1156,-1068,-971,-878,-828,-834,-856,-844,-795,-740,-705,-686,-664,
+-630,-578,-501,-395,-270,-149,-47,32,97,154,212,276,344,414,487,562,626,660,658,641,634,
+645,664,680,700,730,770,814,860,912,969,1028,1090,1159,1233,1297,1345,1389,1445,1513,1574,1610,
+1633,1671,1735,1812,1882,1936,1981,2022,2060,2096,2141,2203,2277,2346,2401,2448,2500,2563,2628,2683,2722,
+2757,2804,2870,2942,3000,3035,3061,3096,3145,3198,3241,3277,3316,3362,3414,3478,3560,3659,3760,3854,3952,
+4065,4183,4271,4308,4310,4307,4312,4313,4302,4290,4290,4298,4300,4299,4317,4367,4432,4488,4529,4573,4634,
+4706,4778,4851,4934,5026,5109,5171,5218,5263,5307,5340,5358,5374,5401,5436,5466,5480,5482,5485,5495,5509,
+5516,5510,5494,5477,5467,5470,5484,5505,5529,5550,5567,5576,5567,5524,5445,5356,5290,5252,5217,5166,5122,
+5128,5194,5276,5326,5334,5326,5322,5317,5312,5320,5347,5377,5393,5411,5466,5557,5632,5625,5531,5417,5361,
+5393,5479,5559,5603,5620,5636,5659,5669,5643,5574,5488,5414,5365,5333,5310,5315,5384,5536,5750,5974,6154,
+6250,6243,6140,5993,5878,5848,5892,5957,5992,5973,5876,5667,5363,5075,4962,5104,5428,5779,6036,6177,6244,
+6278,6301,6322,6340,6347,6335,6305,6269,6235,6206,6183,6165,6148,6125,6097,6067,6037,6006,5973,5938,5892,
+5817,5702,5560,5427,5341,5314,5325,5331,5297,5225,5146,5088,5054,5027,5001,4994,5016,5059,5103,5145,5189,
+5228,5243,5226,5200,5193,5214,5248,5275,5291,5297,5296,5289,5275,5253,5208,5103,4869,4446,3846,3208,2732,
+2546,2613,2777,2900,2951,2968,2979,2974,2939,2880,2819,2763,2708,2649,2587,2522,2452,2382,2317,2254,2183,
+2106,2034,1974,1919,1854,1773,1690,1624,1581,1551,1519,1479,1434,1394,1365,1347,1339,1334,1323,1299,1262,
+1223,1197,1185,1178,1167,1153,1140,1123,1099,1077,1081,1113,1146,1137,1073,976,886,822,778,737,693,
+650,613,583,558,538,518,497,478,460,442,420,387,345,298,250,208,169,132,99,75,67,
+66,57,25,-22,-61,-79,-83,-98,-136,-185,-226,-252,-272,-298,-330,-363,-389,-412,-439,-473,-508,
+-534,-550,-564,-585,-609,-630,-647,-667,-690,-707,-716,-727,-752,-787,-814,-822,-822,-827,-840,-851,-861,
+-882,-917,-951,-963,-952,-933,-926,-941,-974,-1011,-1035,-1039,-1029,-1024,-1031,-1044,-1048,-1040,-1023,-1008,-1001,
+-1009,-1029,-1055,-1075,-1087,-1098,-1115,-1133,-1144,-1145,-1143,-1143,-1147,-1152,-1159,-1167,-1171,-1169,-1164,-1161,-1162,
+-1162,-1160,-1158,-1158,-1159,-1159,-1157,-1158,-1161,-1162,-1155,-1145,-1138,-1136,-1133,-1125,-1114,-1101,-1087,-1070,-1052,
+-1035,-1021,-1009,-994,-977,-960,-946,-931,-911,-884,-854,-828,-808,-789,-769,-746,-725,-707,-690,-671,-649,
+-629,-613,-600,-587,-573,-559,-545,-528,-511,-496,-483,-469,-451,-433,-418,-407,-397,-386,-376,-369,-364,
+-356,-346,-337,-331,-327,-319,-309,-301,-294,-290,-288,-289,-290,-288,-283,-278,-276,-276,-274,-271,-271,
+-274,-275,-275,-276,-279,-284,-286,-287,-288,-289,-290,-291,-296,-301,-303,-303,-304,-307,-308,-305,-304,
+-306,-310,-309,-307,-310,-318,-324,-324,-322,-325,-330,-333,-333,-332,-330,-326,-322,-322,-326,-329,-328,
+-326,-325,-324,-318,-311,-307,-305,-304,-302,-299,-296,-288,-278,-271,-269,-264,-251,-235,-223,-215,-205,
+-193,-182,-174,-166,-155,-147,-143,-141,-136,-130,-125,-122,-118,-109,-97,-82,-68,-56,-50,-45,-34,
+-16,1,14,25,37,48,61,76,94,106,110,113,126,148,170,186,202,223,244,260,277,
+303,335,367,396,429,470,513,557,608,669,728,762,763,742,728,744,789,837,859,858,864,
+897,943,976,999,1033,1080,1121,1149,1184,1240,1299,1337,1363,1406,1468,1526,1574,1630,1702,1759,1782,
+1800,1848,1912,1949,1966,2005,2051,2006,1798,1518,1380,1539,1963,2474,2889,3121,3210,3277,3443,3726,4022,
+4210,4272,4282,4303,4319,4297,4253,4234,4247,4256,4235,4196,4151,4081,3949,3746,3490,3203,2914,2657,2457,
+2313,2218,2180,2203,2248,2244,2166,2074,2051,2108,2176,2186,2143,2091,2053,2003,1916,1801,1690,1614,1579,
+1571,1562,1532,1476,1401,1308,1194,1062,929,808,692,567,431,297,171,51,-64,-166,-245,-308,-366,
+-424,-474,-514,-550,-585,-613,-631,-649,-675,-701,-714,-706,-689,-677,-677,-688,-704,-717,-719,-702,-667,
+-621,-566,-508,-457,-429,-431,-452,-467,-459,-433,-401,-375,-356,-346,-349,-370,-402,-435,-467,-504,-543,
+-568,-569,-562,-571,-596,-611,-601,-604,-666,-792,-928,-1024,-1076,-1106,-1123,-1112,-1072,-1025,-1000,-1006,-1033,
+-1065,-1080,-1059,-1004,-945,-909,-888,-849,-781,-711,-672,-661,-655,-644,-643,-659,-674,-668,-637,-602,-580,
+-575,-585,-601,-610,-608,-604,-610,-622,-628,-620,-613,-621,-642,-658,-658,-652,-650,-648,-641,-630,-624,
+-624,-623,-616,-606,-597,-586,-570,-548,-526,-503,-480,-456,-433,-414,-394,-371,-344,-316,-285,-252,-217,
+-184,-151,-116,-78,-41,-8,21,54,92,132,171,208,244,280,314,347,381,417,453,490,528,
+569,608,645,682,720,755,785,813,849,892,931,962,995,1042,1099,1149,1179,1197,1214,1230,1236,
+1233,1232,1239,1246,1244,1239,1243,1256,1267,1269,1270,1277,1285,1290,1293,1298,1306,1310,1312,1318,1328,
+1340,1350,1361,1377,1395,1413,1429,1447,1465,1478,1492,1511,1536,1559,1577,1591,1606,1619,1627,1636,1651,
+1672,1691,1707,1723,1739,1759,1780,1801,1822,1843,1865,1887,1914,1947,1983,2021,2059,2095,2125,2145,2160,
+2182,2211,2234,2249,2266,2300,2341,2368,2373,2374,2384,2390,2364,2306,2247,2221,2228,2244,2248,2242,2235,
+2232,2231,2239,2261,2295,2329,2355,2383,2427,2491,2559,2609,2629,2627,2622,2625,2642,2672,2718,2780,2846,
+2901,2934,2946,2951,2956,2961,2964,2965,2965,2959,2944,2924,2904,2882,2846,2790,2723,2653,2579,2491,2388,
+2284,2189,2100,2010,1924,1855,1813,1797,1801,1814,1819,1803,1770,1732,1697,1659,1615,1571,1535,1510,1490,
+1478,1477,1478,1464,1430,1386,1347,1309,1264,1213,1165,1124,1088,1053,1020,988,952,916,888,870,853,
+826,794,765,735,685,603,501,404,327,271,231,201,174,141,98,43,-19,-87,-156,-220,-270,
+-300,-310,-312,-316,-326,-333,-334,-342,-369,-407,-429,-417,-388,-378,-402,-444,-479,-493,-489,-479,-470,
+-469,-472,-470,-454,-421,-373,-314,-256,-214,-189,-176,-167,-171,-186,-177,-106,12,112,150,159,204,
+275,282,172,12,-79,-76,-79,-189,-388,-569,-662,-696,-731,-783,-818,-816,-797,-787,-785,-777,-760,
+-750,-756,-767,-767,-753,-730,-702,-674,-648,-615,-542,-391,-170,43,137,53,-167,-422,-620,-736,-789,
+-806,-797,-769,-735,-714,-708,-702,-680,-644,-616,-614,-632,-648,-649,-646,-654,-676,-698,-715,-728,-744,
+-759,-769,-774,-782,-794,-806,-812,-816,-821,-833,-851,-875,-899,-919,-933,-948,-971,-1001,-1032,-1063,-1098,
+-1133,-1165,-1193,-1223,-1263,-1314,-1368,-1420,-1474,-1532,-1591,-1647,-1701,-1754,-1811,-1868,-1921,-1966,-2003,-2040,-2087,
+-2147,-2213,-2276,-2333,-2387,-2440,-2491,-2541,-2593,-2649,-2705,-2760,-2815,-2872,-2926,-2970,-3007,-3047,-3094,-3147,-3200,
+-3251,-3298,-3337,-3366,-3392,-3425,-3467,-3513,-3559,-3602,-3644,-3683,-3719,-3756,-3799,-3845,-3889,-3926,-3956,-3980,-4000,
+-4017,-4031,-4041,-4044,-4045,-4051,-4064,-4082,-4103,-4126,-4150,-4165,-4165,-4154,-4140,-4132,-4127,-4129,-4155,-4221,-4316,
+-4406,-4460,-4478,-4485,-4505,-4533,-4550,-4547,-4541,-4552,-4585,-4624,-4651,-4661,-4663,-4668,-4683,-4704,-4719,-4718,-4704,
+-4686,-4674,-4666,-4655,-4638,-4621,-4609,-4603,-4604,-4616,-4638,-4664,-4688,-4710,-4734,-4754,-4760,-4751,-4736,-4718,-4695,
+-4664,-4627,-4593,-4556,-4513,-4465,-4420,-4382,-4346,-4307,-4260,-4202,-4131,-4054,-3982,-3913,-3829,-3723,-3611,-3525,-3475,
+-3452,-3448,-3470,-3516,-3557,-3561,-3527,-3479,-3436,-3388,-3319,-3240,-3178,-3146,-3133,-3117,-3089,-3059,-3038,-3029,-3019,
+-2993,-2946,-2893,-2851,-2820,-2786,-2737,-2674,-2608,-2544,-2480,-2415,-2341,-2246,-2123,-1978,-1827,-1676,-1527,-1387,-1267,
+-1164,-1060,-948,-859,-831,-857,-884,-864,-801,-740,-710,-704,-697,-676,-634,-566,-469,-353,-238,-137,-53,
+16,76,130,185,245,315,398,487,565,607,607,585,569,572,585,599,617,644,680,720,762,
+806,853,903,964,1042,1129,1206,1264,1313,1371,1439,1498,1537,1567,1609,1668,1729,1775,1805,1828,1851,
+1877,1911,1965,2045,2139,2223,2285,2331,2384,2456,2538,2609,2658,2692,2732,2787,2851,2909,2953,2993,3042,
+3102,3158,3199,3232,3266,3309,3359,3420,3499,3595,3695,3789,3882,3984,4090,4176,4225,4243,4250,4256,4255,
+4245,4235,4234,4237,4235,4235,4255,4305,4366,4417,4453,4491,4544,4607,4672,4741,4825,4923,5017,5089,5142,
+5189,5238,5281,5309,5325,5339,5360,5390,5419,5441,5452,5455,5457,5460,5460,5451,5435,5421,5417,5429,5452,
+5477,5499,5513,5518,5506,5467,5406,5340,5284,5236,5178,5111,5066,5072,5125,5186,5224,5249,5280,5310,5316,
+5298,5289,5309,5336,5330,5301,5306,5385,5501,5566,5528,5427,5350,5350,5408,5468,5498,5508,5525,5558,5589,
+5590,5551,5482,5410,5355,5319,5292,5275,5284,5342,5462,5640,5852,6060,6200,6222,6125,5979,5868,5832,5853,
+5897,5937,5935,5829,5591,5285,5061,5042,5235,5535,5821,6027,6147,6204,6227,6242,6258,6270,6263,6235,6198,
+6165,6142,6125,6108,6089,6070,6056,6047,6029,5990,5928,5851,5767,5671,5562,5453,5368,5324,5311,5304,5275,
+5215,5143,5087,5057,5040,5020,4998,4996,5023,5068,5113,5153,5193,5226,5237,5222,5202,5201,5226,5261,5291,
+5304,5300,5287,5273,5260,5226,5128,4917,4554,4040,3445,2917,2607,2563,2697,2855,2944,2971,2985,2997,2984,
+2935,2871,2816,2767,2712,2652,2591,2532,2467,2397,2326,2258,2187,2113,2045,1990,1938,1870,1785,1698,1629,
+1582,1545,1505,1460,1416,1380,1352,1330,1314,1305,1297,1282,1254,1218,1188,1170,1161,1155,1149,1143,1128,
+1103,1078,1072,1093,1117,1109,1054,970,888,830,793,764,728,678,614,552,509,491,484,475,458,
+442,430,416,391,350,301,251,206,165,125,85,53,35,31,25,4,-31,-69,-97,-115,-137,
+-168,-207,-244,-275,-299,-322,-350,-384,-418,-446,-468,-493,-524,-551,-566,-575,-588,-611,-634,-652,-670,
+-692,-713,-727,-735,-753,-784,-815,-833,-839,-845,-853,-861,-871,-893,-927,-958,-963,-942,-916,-907,-925,
+-961,-998,-1018,-1015,-1002,-1000,-1018,-1044,-1058,-1053,-1035,-1016,-1003,-1001,-1010,-1026,-1040,-1049,-1062,-1084,-1111,
+-1130,-1136,-1135,-1138,-1144,-1148,-1150,-1152,-1155,-1156,-1151,-1146,-1144,-1143,-1142,-1138,-1137,-1139,-1141,-1141,-1142,
+-1146,-1147,-1144,-1138,-1134,-1133,-1133,-1127,-1118,-1108,-1098,-1083,-1065,-1046,-1030,-1017,-1003,-987,-971,-955,-941,
+-923,-900,-874,-847,-824,-804,-783,-762,-741,-722,-704,-685,-665,-646,-630,-614,-598,-581,-566,-551,-534,
+-516,-501,-488,-475,-457,-437,-421,-411,-402,-392,-382,-375,-368,-359,-349,-342,-337,-331,-322,-312,-305,
+-301,-298,-297,-299,-301,-300,-295,-290,-289,-288,-284,-281,-282,-286,-287,-287,-287,-289,-290,-290,-292,
+-297,-302,-304,-303,-302,-304,-306,-306,-306,-309,-311,-310,-309,-310,-310,-308,-306,-309,-315,-320,-320,
+-318,-320,-323,-324,-323,-323,-323,-322,-321,-321,-322,-320,-317,-314,-312,-309,-302,-296,-294,-294,-292,
+-288,-285,-281,-271,-258,-248,-245,-241,-230,-216,-203,-194,-185,-173,-164,-157,-149,-138,-127,-121,-117,
+-113,-108,-105,-102,-97,-89,-78,-64,-50,-38,-30,-23,-12,3,19,30,40,52,67,84,102,
+117,126,129,137,154,174,192,209,233,260,279,289,305,335,370,395,414,446,497,552,598,
+640,692,747,777,762,716,686,708,775,841,866,860,861,892,933,959,978,1015,1069,1111,1133,
+1164,1223,1289,1329,1349,1384,1446,1510,1564,1622,1690,1742,1760,1774,1822,1888,1933,1957,2002,2050,2003,
+1790,1506,1364,1519,1940,2455,2885,3141,3247,3313,3458,3712,3992,4188,4274,4311,4344,4362,4338,4297,4275,
+4268,4243,4195,4156,4134,4077,3935,3708,3438,3159,2886,2639,2447,2315,2232,2192,2192,2207,2188,2120,2050,
+2046,2106,2166,2171,2133,2092,2058,2003,1905,1782,1668,1590,1554,1551,1557,1545,1495,1409,1300,1179,1056,
+940,828,710,575,429,290,165,49,-59,-151,-221,-279,-340,-402,-452,-486,-516,-550,-582,-605,-624,
+-649,-675,-689,-685,-671,-663,-665,-676,-688,-695,-695,-686,-665,-629,-571,-494,-418,-368,-358,-377,-397,
+-399,-380,-356,-341,-335,-333,-335,-347,-375,-417,-460,-494,-512,-515,-514,-528,-564,-602,-610,-588,-583,
+-651,-785,-922,-1007,-1042,-1064,-1090,-1106,-1104,-1098,-1103,-1108,-1096,-1067,-1040,-1024,-1011,-995,-980,-967,-948,
+-913,-869,-827,-790,-755,-726,-710,-705,-699,-683,-664,-651,-641,-630,-617,-610,-608,-605,-601,-605,-620,
+-636,-643,-645,-649,-656,-657,-651,-646,-647,-648,-641,-630,-625,-625,-624,-615,-602,-589,-576,-557,-535,
+-515,-497,-476,-451,-425,-402,-380,-357,-329,-299,-267,-234,-200,-166,-133,-97,-60,-22,10,41,73,
+109,146,183,218,252,286,318,352,387,423,459,499,540,582,619,654,690,728,764,796,827,
+864,905,943,975,1012,1063,1120,1163,1184,1196,1211,1228,1233,1227,1223,1229,1237,1237,1233,1237,1250,
+1261,1264,1264,1268,1273,1275,1276,1283,1295,1305,1311,1318,1330,1341,1351,1363,1382,1403,1421,1435,1451,
+1470,1489,1505,1521,1542,1563,1582,1598,1616,1634,1648,1659,1672,1689,1707,1722,1738,1755,1772,1793,1817,
+1842,1866,1890,1918,1951,1986,2021,2054,2087,2118,2140,2150,2156,2177,2218,2266,2306,2338,2369,2397,2412,
+2411,2409,2419,2426,2403,2344,2278,2240,2238,2248,2251,2244,2238,2239,2243,2253,2272,2301,2331,2356,2385,
+2432,2499,2571,2623,2649,2660,2673,2694,2718,2744,2781,2836,2902,2954,2974,2970,2964,2973,2994,3013,3021,
+3017,2996,2955,2901,2850,2811,2780,2746,2704,2654,2589,2503,2401,2298,2203,2112,2025,1948,1895,1866,1856,
+1858,1867,1870,1855,1819,1776,1735,1695,1653,1613,1581,1557,1537,1522,1514,1508,1487,1449,1404,1362,1322,
+1274,1220,1172,1136,1107,1077,1048,1023,1003,989,983,983,979,961,928,884,823,738,628,510,408,
+336,296,278,271,259,232,188,133,73,11,-52,-110,-155,-183,-199,-213,-230,-249,-263,-275,-297,
+-330,-358,-353,-308,-256,-235,-259,-306,-348,-372,-382,-384,-381,-377,-379,-388,-391,-370,-314,-235,-162,
+-120,-105,-95,-83,-86,-108,-105,-29,103,215,253,254,282,327,308,183,28,-52,-51,-72,-199,
+-395,-553,-625,-650,-683,-727,-749,-739,-723,-719,-721,-714,-704,-702,-707,-703,-686,-665,-646,-627,-601,
+-574,-549,-511,-431,-305,-176,-115,-165,-304,-468,-595,-665,-689,-687,-670,-650,-640,-644,-651,-640,-605,
+-565,-548,-562,-587,-601,-604,-608,-621,-639,-651,-657,-665,-677,-688,-698,-710,-724,-737,-743,-745,-749,
+-759,-773,-792,-814,-835,-852,-866,-885,-913,-944,-972,-1001,-1033,-1068,-1098,-1124,-1152,-1191,-1239,-1290,-1340,
+-1394,-1450,-1508,-1565,-1619,-1673,-1727,-1780,-1831,-1876,-1914,-1953,-2002,-2065,-2132,-2192,-2245,-2296,-2349,-2402,-2453,
+-2506,-2560,-2616,-2673,-2731,-2789,-2840,-2882,-2920,-2963,-3015,-3070,-3124,-3173,-3216,-3249,-3274,-3301,-3338,-3383,-3429,
+-3473,-3516,-3560,-3600,-3635,-3670,-3711,-3757,-3803,-3841,-3871,-3894,-3912,-3928,-3942,-3950,-3953,-3958,-3971,-3992,-4015,
+-4037,-4060,-4084,-4099,-4096,-4082,-4069,-4060,-4051,-4046,-4067,-4136,-4241,-4342,-4403,-4424,-4436,-4461,-4495,-4517,-4520,
+-4519,-4531,-4562,-4599,-4625,-4636,-4638,-4643,-4656,-4674,-4688,-4688,-4675,-4659,-4648,-4641,-4629,-4612,-4595,-4584,-4582,
+-4588,-4604,-4628,-4652,-4674,-4695,-4718,-4736,-4739,-4728,-4712,-4696,-4675,-4643,-4605,-4569,-4535,-4496,-4452,-4409,-4369,
+-4331,-4289,-4241,-4186,-4125,-4060,-3995,-3925,-3831,-3709,-3579,-3476,-3416,-3392,-3397,-3434,-3494,-3552,-3572,-3550,-3505,
+-3455,-3395,-3316,-3230,-3162,-3128,-3116,-3108,-3094,-3078,-3068,-3066,-3065,-3049,-3015,-2968,-2922,-2879,-2832,-2779,-2724,
+-2669,-2607,-2532,-2445,-2349,-2235,-2090,-1917,-1740,-1583,-1454,-1352,-1264,-1175,-1070,-957,-872,-842,-858,-869,-839,
+-778,-725,-705,-708,-710,-699,-672,-623,-546,-448,-341,-237,-143,-62,0,48,91,144,216,308,409,
+497,547,554,535,515,508,511,520,537,562,595,632,670,707,741,778,832,913,1013,1108,1181,
+1236,1291,1352,1409,1453,1490,1531,1576,1613,1633,1641,1647,1658,1678,1713,1773,1858,1953,2036,2099,2150,
+2212,2296,2394,2485,2555,2606,2651,2702,2759,2814,2864,2916,2978,3046,3106,3149,3180,3211,3251,3300,3358,
+3431,3521,3619,3715,3807,3901,3996,4079,4137,4168,4181,4183,4181,4175,4170,4165,4159,4152,4158,4189,4241,
+4297,4341,4375,4413,4464,4523,4584,4652,4735,4831,4926,5004,5064,5114,5163,5210,5245,5263,5271,5282,5307,
+5347,5389,5414,5418,5411,5406,5405,5400,5386,5367,5357,5366,5390,5419,5443,5457,5454,5432,5395,5352,5312,
+5272,5218,5147,5079,5048,5066,5107,5135,5146,5169,5222,5278,5295,5272,5249,5255,5264,5232,5171,5157,5246,
+5402,5513,5504,5404,5312,5295,5341,5392,5416,5421,5432,5457,5484,5498,5492,5461,5411,5356,5312,5285,5267,
+5254,5253,5287,5379,5544,5768,5997,6157,6196,6126,6010,5905,5839,5821,5849,5892,5884,5756,5510,5237,5065,
+5069,5236,5494,5761,5971,6098,6154,6172,6180,6184,6175,6152,6125,6105,6095,6082,6058,6023,5991,5973,5965,
+5942,5883,5790,5687,5595,5517,5449,5390,5350,5328,5310,5275,5218,5149,5092,5058,5041,5024,5002,4988,5000,
+5037,5081,5119,5157,5199,5235,5246,5230,5209,5206,5228,5264,5298,5312,5301,5274,5254,5240,5185,5014,4674,
+4176,3597,3060,2691,2560,2635,2799,2928,2982,2994,3007,3014,2988,2928,2863,2812,2765,2707,2640,2579,2522,
+2458,2384,2308,2240,2176,2114,2054,1999,1940,1869,1787,1707,1641,1588,1540,1494,1447,1405,1369,1339,1313,
+1290,1274,1265,1258,1243,1215,1183,1158,1145,1139,1134,1129,1119,1101,1077,1058,1051,1048,1031,991,934,
+875,830,802,783,756,705,628,546,490,467,462,452,433,415,407,401,384,351,306,257,211,
+169,132,96,61,30,8,-6,-18,-35,-58,-90,-129,-168,-202,-230,-256,-284,-310,-332,-355,-389,
+-430,-467,-491,-514,-543,-574,-591,-594,-596,-611,-634,-653,-670,-689,-709,-722,-729,-744,-775,-810,-834,
+-846,-853,-862,-870,-882,-905,-936,-958,-953,-927,-904,-907,-937,-977,-1005,-1006,-983,-958,-955,-982,-1021,
+-1049,-1056,-1052,-1048,-1045,-1041,-1038,-1037,-1039,-1041,-1048,-1065,-1087,-1106,-1113,-1118,-1128,-1141,-1149,-1148,-1145,
+-1144,-1145,-1142,-1136,-1133,-1132,-1131,-1128,-1126,-1126,-1128,-1127,-1125,-1125,-1126,-1125,-1122,-1119,-1119,-1120,-1117,
+-1110,-1102,-1093,-1081,-1066,-1049,-1034,-1019,-1006,-992,-978,-965,-950,-933,-913,-891,-867,-844,-822,-801,-779,
+-758,-738,-718,-699,-681,-664,-647,-630,-610,-591,-575,-559,-543,-525,-509,-497,-484,-467,-448,-432,-422,
+-412,-402,-392,-383,-375,-365,-356,-349,-345,-338,-329,-320,-315,-313,-311,-309,-311,-314,-313,-310,-306,
+-305,-303,-299,-295,-295,-297,-299,-299,-299,-300,-298,-293,-293,-300,-310,-315,-314,-313,-314,-316,-314,
+-313,-313,-314,-313,-312,-311,-310,-307,-306,-309,-313,-315,-315,-315,-318,-320,-319,-316,-316,-318,-318,
+-317,-316,-315,-311,-306,-302,-298,-292,-285,-282,-284,-284,-279,-271,-267,-263,-254,-241,-230,-225,-223,
+-215,-202,-191,-181,-171,-160,-150,-143,-133,-121,-110,-101,-94,-88,-84,-82,-80,-74,-64,-54,-42,
+-29,-17,-9,-2,8,23,38,50,59,70,86,105,124,137,145,150,161,178,193,205,223,
+252,284,301,307,321,354,389,411,429,470,533,593,625,644,679,731,766,754,705,673,699,
+773,841,863,852,853,885,925,945,959,995,1051,1095,1116,1145,1205,1274,1319,1343,1380,1443,1508,
+1561,1616,1678,1723,1738,1752,1801,1871,1920,1950,1996,2041,1986,1767,1478,1335,1492,1925,2468,2937,3225,
+3340,3385,3492,3710,3972,4173,4281,4339,4383,4401,4377,4337,4311,4287,4239,4183,4162,4162,4100,3916,3637,
+3342,3075,2833,2616,2447,2339,2276,2235,2207,2185,2144,2080,2027,2030,2083,2130,2131,2100,2070,2040,1983,
+1886,1772,1669,1595,1553,1544,1554,1553,1508,1412,1284,1153,1037,938,839,721,578,426,286,162,46,
+-59,-144,-205,-256,-317,-380,-428,-455,-477,-507,-544,-576,-601,-625,-646,-656,-651,-642,-641,-652,-667,
+-677,-677,-668,-658,-646,-624,-579,-505,-420,-353,-322,-323,-335,-335,-322,-307,-306,-321,-339,-348,-355,
+-376,-419,-465,-491,-490,-479,-485,-522,-578,-617,-612,-578,-572,-641,-773,-903,-982,-1015,-1039,-1066,-1081,
+-1077,-1072,-1079,-1083,-1061,-1016,-981,-975,-984,-984,-969,-949,-932,-915,-891,-860,-826,-792,-764,-746,-730,
+-709,-684,-667,-660,-653,-637,-617,-605,-605,-607,-607,-609,-620,-634,-642,-643,-645,-647,-647,-644,-644,
+-647,-648,-640,-629,-624,-624,-621,-609,-594,-578,-563,-543,-523,-505,-491,-474,-450,-422,-393,-366,-338,
+-309,-277,-244,-210,-175,-142,-110,-76,-40,-4,30,63,96,130,164,198,231,263,295,327,361,
+396,432,470,511,554,594,630,663,699,739,777,813,847,885,925,962,994,1031,1077,1123,1154,
+1168,1178,1196,1217,1226,1221,1215,1219,1229,1234,1234,1238,1248,1257,1260,1260,1262,1265,1266,1268,1277,
+1292,1307,1317,1326,1337,1348,1357,1369,1388,1409,1425,1437,1452,1474,1497,1514,1526,1540,1559,1581,1603,
+1626,1650,1669,1683,1694,1706,1722,1733,1751,1769,1789,1813,1840,1867,1893,1920,1951,1986,2021,2051,2079,
+2108,2135,2155,2164,2172,2199,2253,2320,2378,2415,2435,2447,2453,2452,2451,2455,2453,2427,2373,2309,2265,
+2251,2251,2246,2237,2232,2238,2250,2262,2278,2301,2328,2355,2386,2434,2505,2583,2644,2677,2695,2716,2749,
+2783,2809,2835,2875,2928,2972,2990,2984,2982,2998,3029,3054,3065,3056,3023,2961,2879,2799,2741,2709,2691,
+2670,2635,2577,2494,2398,2301,2211,2125,2046,1983,1946,1929,1922,1920,1924,1925,1910,1872,1821,1773,1730,
+1691,1657,1631,1609,1588,1568,1555,1544,1522,1482,1436,1393,1353,1308,1255,1205,1165,1131,1096,1064,1043,
+1036,1039,1043,1043,1034,1016,985,937,862,755,630,510,418,361,334,327,328,323,302,267,225,
+176,118,53,-6,-50,-78,-99,-123,-151,-176,-196,-218,-250,-285,-303,-283,-231,-180,-162,-180,-212,
+-238,-257,-274,-288,-289,-282,-282,-302,-326,-319,-260,-167,-82,-32,-10,8,26,22,0,8,92,
+227,334,365,355,362,378,333,205,64,-7,-25,-80,-224,-404,-531,-581,-602,-635,-669,-678,-666,
+-659,-666,-670,-662,-653,-653,-651,-633,-602,-578,-567,-557,-536,-506,-480,-459,-431,-384,-333,-306,-331,
+-402,-489,-557,-591,-598,-592,-585,-581,-585,-594,-595,-574,-534,-500,-495,-517,-545,-564,-574,-586,-600,
+-609,-609,-607,-608,-610,-611,-619,-636,-656,-668,-672,-676,-686,-701,-716,-734,-754,-775,-792,-809,-833,
+-862,-888,-910,-934,-966,-1002,-1032,-1056,-1084,-1122,-1167,-1214,-1263,-1316,-1371,-1426,-1480,-1536,-1591,-1642,-1692,
+-1741,-1789,-1831,-1872,-1922,-1985,-2052,-2112,-2162,-2209,-2258,-2309,-2361,-2415,-2472,-2530,-2587,-2644,-2700,-2749,-2791,
+-2832,-2881,-2937,-2994,-3046,-3091,-3128,-3157,-3184,-3215,-3257,-3304,-3349,-3390,-3431,-3474,-3513,-3549,-3585,-3627,-3673,
+-3718,-3756,-3784,-3805,-3820,-3836,-3851,-3865,-3875,-3888,-3908,-3933,-3955,-3975,-3997,-4019,-4031,-4025,-4008,-3994,-3983,
+-3969,-3961,-3984,-4063,-4180,-4288,-4351,-4372,-4385,-4414,-4455,-4486,-4498,-4500,-4511,-4537,-4568,-4593,-4604,-4606,-4609,
+-4620,-4638,-4651,-4652,-4641,-4628,-4621,-4616,-4605,-4588,-4571,-4564,-4567,-4579,-4597,-4617,-4638,-4659,-4681,-4704,-4719,
+-4719,-4705,-4688,-4673,-4652,-4621,-4581,-4542,-4507,-4471,-4432,-4394,-4356,-4314,-4267,-4219,-4174,-4129,-4079,-4022,-3953,
+-3861,-3741,-3610,-3494,-3412,-3368,-3364,-3400,-3468,-3540,-3580,-3573,-3531,-3466,-3386,-3297,-3213,-3152,-3121,-3111,-3109,
+-3107,-3103,-3099,-3098,-3097,-3090,-3068,-3034,-2991,-2941,-2885,-2826,-2772,-2720,-2655,-2564,-2455,-2339,-2210,-2053,-1866,
+-1676,-1520,-1410,-1334,-1266,-1187,-1090,-986,-902,-857,-843,-830,-795,-747,-712,-701,-705,-708,-701,-684,-651,
+-596,-520,-428,-330,-232,-145,-79,-34,2,50,123,219,326,420,479,497,488,471,456,449,450,
+462,484,511,542,577,611,641,669,714,792,898,1009,1096,1157,1205,1252,1300,1344,1384,1422,1455,
+1475,1481,1479,1479,1488,1513,1558,1624,1705,1785,1852,1909,1966,2040,2134,2242,2347,2438,2511,2571,2624,
+2675,2725,2776,2833,2900,2972,3033,3077,3107,3140,3183,3235,3292,3357,3437,3532,3631,3726,3814,3898,3978,
+4044,4085,4101,4101,4098,4099,4100,4091,4075,4065,4077,4115,4165,4212,4251,4287,4332,4386,4446,4509,4579,
+4659,4746,4833,4912,4980,5040,5093,5140,5177,5198,5206,5211,5230,5271,5322,5360,5372,5363,5350,5343,5337,
+5323,5304,5292,5298,5319,5349,5375,5388,5381,5354,5318,5288,5268,5242,5190,5116,5055,5041,5075,5114,5122,
+5106,5107,5147,5196,5212,5189,5166,5167,5167,5127,5066,5063,5174,5350,5466,5444,5325,5221,5207,5265,5328,
+5360,5370,5378,5387,5395,5405,5418,5420,5394,5344,5294,5266,5254,5244,5232,5231,5261,5346,5499,5710,5932,
+6099,6165,6131,6032,5918,5829,5794,5815,5847,5819,5679,5439,5177,4999,4981,5136,5402,5681,5896,6020,6076,
+6096,6098,6085,6061,6038,6021,6007,5983,5941,5884,5828,5789,5763,5728,5664,5578,5498,5446,5419,5399,5375,
+5349,5322,5287,5236,5176,5121,5085,5064,5042,5012,4985,4980,5006,5047,5085,5118,5158,5209,5250,5260,5240,
+5215,5207,5223,5256,5291,5310,5298,5267,5241,5215,5118,4855,4386,3780,3186,2753,2558,2583,2733,2893,2986,
+3014,3020,3029,3026,2988,2923,2861,2810,2758,2690,2618,2556,2502,2440,2365,2288,2222,2165,2111,2054,1995,
+1930,1860,1789,1721,1658,1599,1544,1494,1448,1404,1364,1331,1303,1278,1255,1240,1236,1232,1216,1188,1159,
+1139,1126,1113,1101,1092,1084,1072,1050,1023,995,966,933,895,856,821,796,779,756,706,629,545,
+486,458,447,429,404,381,371,367,356,333,298,253,205,165,139,122,99,61,15,-23,-40,
+-38,-38,-64,-118,-181,-225,-246,-261,-287,-320,-348,-371,-401,-444,-485,-514,-537,-565,-597,-616,-616,
+-611,-619,-638,-657,-674,-690,-706,-716,-723,-741,-774,-813,-841,-853,-858,-863,-869,-879,-900,-930,-953,
+-952,-935,-924,-939,-976,-1014,-1031,-1018,-984,-951,-946,-974,-1016,-1046,-1058,-1065,-1078,-1090,-1091,-1081,-1072,
+-1071,-1074,-1078,-1085,-1093,-1099,-1101,-1103,-1115,-1134,-1149,-1151,-1145,-1140,-1139,-1139,-1136,-1134,-1132,-1132,-1130,
+-1128,-1127,-1125,-1121,-1115,-1111,-1111,-1110,-1108,-1105,-1104,-1103,-1101,-1095,-1086,-1075,-1065,-1054,-1043,-1030,-1014,
+-999,-985,-974,-963,-949,-932,-914,-897,-878,-857,-835,-813,-791,-769,-747,-727,-708,-691,-675,-659,-642,
+-622,-602,-584,-568,-552,-535,-520,-507,-494,-479,-462,-448,-436,-425,-414,-403,-395,-387,-377,-368,-362,
+-357,-350,-340,-332,-327,-326,-324,-322,-323,-326,-327,-325,-322,-321,-319,-315,-312,-310,-309,-308,-308,
+-311,-313,-310,-303,-301,-307,-315,-320,-320,-321,-324,-326,-324,-320,-318,-318,-316,-314,-311,-308,-306,
+-307,-310,-312,-312,-310,-312,-317,-319,-316,-312,-310,-310,-310,-309,-308,-308,-304,-299,-292,-285,-277,
+-270,-269,-272,-271,-264,-255,-250,-247,-240,-229,-219,-214,-209,-200,-188,-176,-166,-156,-145,-135,-125,
+-113,-101,-92,-85,-77,-68,-61,-59,-57,-51,-43,-34,-23,-9,3,12,18,27,41,56,69,
+79,90,105,122,139,152,160,169,183,201,215,224,240,268,296,311,316,333,367,403,426,
+452,505,574,622,630,625,646,698,742,740,703,682,713,783,841,854,840,842,876,916,936,
+947,979,1031,1075,1100,1132,1192,1260,1308,1342,1389,1456,1520,1569,1619,1673,1711,1723,1740,1793,1866,
+1918,1949,1989,2020,1950,1722,1432,1291,1459,1920,2506,3020,3330,3432,3440,3501,3683,3922,4119,4241,4325,
+4394,4423,4400,4357,4326,4295,4243,4200,4203,4217,4133,3888,3542,3212,2954,2749,2570,2434,2358,2322,2290,
+2247,2198,2141,2076,2027,2021,2051,2076,2067,2040,2018,1996,1948,1867,1774,1691,1623,1575,1554,1559,1559,
+1515,1410,1267,1124,1011,925,840,729,586,433,292,167,50,-56,-136,-187,-229,-284,-347,-396,-422,
+-439,-466,-503,-539,-569,-594,-614,-622,-619,-615,-619,-633,-650,-661,-660,-646,-629,-617,-603,-572,-511,
+-430,-353,-302,-283,-283,-285,-279,-273,-285,-320,-362,-388,-395,-403,-428,-463,-484,-486,-491,-522,-576,
+-626,-637,-604,-559,-559,-635,-765,-889,-969,-1010,-1039,-1062,-1061,-1032,-1002,-993,-997,-989,-964,-945,-947,
+-957,-952,-927,-900,-881,-870,-857,-840,-819,-798,-779,-761,-741,-716,-688,-667,-654,-642,-624,-607,-600,
+-606,-614,-617,-619,-625,-632,-635,-634,-635,-639,-641,-641,-641,-644,-644,-636,-626,-620,-617,-609,-595,
+-578,-561,-544,-524,-503,-486,-472,-457,-437,-411,-381,-348,-316,-284,-252,-219,-183,-149,-117,-85,-52,
+-17,17,51,85,118,151,183,216,248,280,311,343,376,411,447,484,525,567,607,642,677,
+715,756,798,836,873,910,948,983,1014,1045,1078,1108,1129,1141,1155,1178,1203,1217,1216,1212,1217,
+1229,1238,1242,1245,1252,1260,1262,1261,1263,1266,1270,1274,1284,1299,1312,1322,1330,1340,1352,1364,1377,
+1396,1417,1433,1444,1460,1485,1511,1528,1536,1546,1565,1590,1616,1641,1666,1687,1700,1709,1718,1733,1745,
+1766,1790,1816,1844,1873,1900,1925,1952,1984,2018,2050,2078,2103,2130,2157,2182,2200,2219,2252,2308,2378,
+2438,2471,2481,2484,2493,2500,2495,2475,2444,2404,2355,2303,2263,2243,2237,2233,2227,2224,2232,2246,2260,
+2274,2294,2321,2349,2379,2425,2497,2585,2662,2706,2725,2744,2777,2817,2847,2869,2898,2940,2983,3010,3020,
+3032,3057,3088,3110,3112,3095,3052,2978,2879,2779,2705,2666,2650,2635,2605,2549,2472,2385,2302,2224,2149,
+2079,2026,1998,1984,1974,1967,1965,1965,1952,1914,1861,1809,1766,1732,1706,1687,1667,1642,1615,1596,1584,
+1564,1527,1481,1438,1400,1361,1313,1261,1212,1166,1123,1088,1073,1079,1093,1099,1087,1062,1035,1008,967,
+891,774,641,524,445,402,383,376,375,371,359,341,317,282,226,155,89,43,16,-6,-36,
+-70,-102,-129,-159,-193,-224,-233,-213,-174,-145,-141,-154,-162,-161,-165,-184,-205,-209,-197,-195,-222,
+-262,-271,-220,-125,-28,42,91,130,153,145,124,143,234,360,448,463,438,422,403,338,222,
+110,46,0,-95,-251,-403,-489,-517,-536,-571,-598,-601,-594,-602,-618,-623,-611,-599,-595,-586,-558,
+-522,-498,-493,-491,-475,-447,-420,-404,-397,-393,-387,-385,-395,-423,-459,-488,-500,-503,-508,-520,-533,
+-541,-543,-535,-513,-483,-460,-461,-483,-509,-530,-545,-557,-565,-564,-560,-557,-554,-548,-543,-552,-573,
+-596,-606,-608,-615,-630,-646,-659,-675,-697,-721,-742,-762,-787,-812,-831,-846,-868,-901,-937,-964,-986,
+-1014,-1050,-1092,-1137,-1186,-1240,-1294,-1345,-1396,-1451,-1507,-1558,-1605,-1652,-1700,-1746,-1790,-1842,-1904,-1971,-2031,
+-2081,-2126,-2171,-2218,-2269,-2327,-2388,-2447,-2502,-2554,-2606,-2654,-2699,-2746,-2801,-2861,-2918,-2967,-3006,-3039,-3067,
+-3096,-3133,-3178,-3226,-3268,-3308,-3349,-3389,-3427,-3463,-3502,-3545,-3590,-3630,-3665,-3694,-3715,-3730,-3746,-3766,-3790,
+-3813,-3835,-3858,-3881,-3900,-3917,-3936,-3956,-3965,-3958,-3942,-3927,-3913,-3896,-3887,-3919,-4009,-4133,-4240,-4295,-4311,
+-4325,-4361,-4411,-4451,-4468,-4472,-4479,-4500,-4528,-4552,-4563,-4566,-4568,-4578,-4595,-4608,-4609,-4600,-4590,-4586,-4585,
+-4578,-4563,-4549,-4545,-4554,-4569,-4586,-4604,-4623,-4643,-4666,-4686,-4697,-4694,-4679,-4661,-4645,-4625,-4595,-4558,-4519,
+-4480,-4440,-4402,-4367,-4333,-4293,-4246,-4201,-4165,-4131,-4089,-4033,-3965,-3886,-3793,-3686,-3577,-3481,-3412,-3384,-3404,
+-3464,-3537,-3588,-3595,-3553,-3474,-3375,-3276,-3200,-3154,-3133,-3126,-3125,-3127,-3129,-3129,-3129,-3130,-3126,-3111,-3082,
+-3043,-2996,-2942,-2885,-2830,-2769,-2686,-2573,-2442,-2311,-2179,-2025,-1843,-1658,-1509,-1412,-1346,-1283,-1206,-1118,-1029,
+-949,-888,-845,-811,-777,-746,-725,-717,-714,-706,-689,-666,-635,-593,-541,-478,-403,-319,-235,-164,-111,
+-69,-21,45,135,238,333,401,434,439,427,409,394,389,397,412,431,454,484,521,555,582,
+620,688,792,910,1010,1077,1119,1150,1182,1216,1252,1285,1314,1333,1344,1349,1356,1376,1416,1477,1552,
+1626,1688,1736,1782,1840,1917,2013,2118,2226,2328,2418,2493,2552,2601,2645,2692,2750,2818,2888,2948,2990,
+3023,3062,3114,3172,3229,3286,3356,3446,3546,3639,3718,3791,3868,3943,3998,4022,4022,4018,4022,4025,4016,
+3995,3982,3994,4029,4070,4107,4142,4186,4242,4304,4370,4439,4512,4589,4666,4742,4819,4896,4968,5032,5084,
+5122,5145,5152,5153,5163,5196,5245,5290,5312,5309,5296,5284,5274,5261,5244,5234,5238,5255,5278,5299,5310,
+5303,5277,5243,5220,5211,5197,5156,5088,5027,5012,5044,5082,5087,5059,5037,5048,5075,5085,5071,5058,5063,
+5061,5027,4984,5004,5128,5299,5396,5351,5217,5112,5112,5188,5269,5314,5332,5341,5341,5335,5335,5349,5361,
+5345,5302,5257,5233,5227,5222,5216,5218,5234,5266,5333,5460,5652,5867,6035,6107,6082,5995,5891,5807,5770,
+5778,5794,5753,5601,5342,5062,4882,4885,5062,5326,5578,5764,5879,5939,5958,5945,5913,5872,5827,5780,5728,
+5672,5613,5557,5512,5481,5453,5420,5387,5370,5376,5393,5397,5376,5337,5291,5242,5192,5147,5114,5093,5074,
+5045,5010,4985,4988,5015,5050,5078,5109,5157,5216,5257,5261,5237,5212,5207,5220,5247,5276,5295,5288,5261,
+5229,5171,5004,4636,4061,3404,2857,2559,2520,2651,2827,2959,3021,3039,3046,3048,3031,2983,2919,2860,2807,
+2745,2671,2598,2540,2490,2431,2360,2286,2219,2159,2102,2043,1980,1915,1850,1789,1731,1671,1609,1552,1504,
+1460,1413,1367,1330,1305,1281,1252,1228,1219,1220,1215,1195,1168,1144,1122,1097,1072,1057,1055,1053,1040,
+1011,974,937,903,871,837,804,776,752,724,676,608,537,485,457,438,412,379,350,332,321,
+312,297,273,234,187,151,138,142,138,102,36,-27,-56,-43,-19,-28,-88,-173,-238,-266,-280,
+-307,-349,-386,-410,-433,-468,-508,-539,-560,-582,-608,-625,-630,-630,-639,-658,-678,-696,-713,-728,-737,
+-743,-759,-790,-825,-849,-858,-860,-861,-861,-864,-879,-910,-942,-959,-963,-969,-988,-1017,-1044,-1056,-1046,
+-1020,-994,-992,-1017,-1051,-1071,-1074,-1078,-1095,-1115,-1121,-1113,-1109,-1118,-1134,-1142,-1141,-1136,-1130,-1123,-1116,
+-1118,-1129,-1143,-1148,-1144,-1137,-1136,-1138,-1140,-1140,-1139,-1139,-1140,-1138,-1135,-1129,-1121,-1113,-1108,-1107,-1106,
+-1103,-1098,-1093,-1090,-1086,-1079,-1068,-1056,-1046,-1039,-1033,-1023,-1006,-988,-972,-961,-951,-938,-922,-906,-891,
+-876,-859,-839,-818,-796,-774,-752,-732,-715,-698,-681,-665,-649,-631,-611,-592,-574,-558,-543,-528,-515,
+-502,-488,-474,-461,-449,-437,-425,-414,-406,-399,-390,-382,-375,-370,-362,-351,-342,-336,-335,-334,-334,
+-336,-338,-339,-338,-335,-332,-331,-330,-328,-326,-323,-319,-318,-321,-323,-322,-319,-318,-322,-325,-326,
+-325,-328,-332,-333,-331,-327,-326,-325,-324,-320,-314,-310,-308,-310,-314,-316,-313,-310,-313,-317,-318,
+-312,-306,-302,-301,-300,-301,-303,-305,-301,-293,-283,-275,-266,-260,-258,-258,-257,-251,-243,-238,-234,
+-228,-219,-211,-204,-195,-183,-170,-158,-148,-137,-127,-117,-105,-90,-78,-72,-69,-62,-51,-41,-36,
+-34,-32,-28,-22,-13,2,19,31,37,44,56,70,84,96,109,123,138,152,164,175,185,
+202,222,240,253,268,289,309,322,334,357,391,423,447,480,537,598,627,616,603,627,682,
+725,726,700,693,729,790,834,841,829,835,867,905,928,944,974,1019,1059,1089,1130,1193,1259,
+1308,1348,1402,1470,1532,1578,1624,1672,1706,1718,1740,1798,1875,1928,1956,1986,1998,1910,1674,1387,1257,
+1442,1930,2552,3091,3400,3476,3452,3486,3641,3849,4021,4144,4259,4371,4430,4416,4370,4338,4311,4266,4231,
+4245,4259,4148,3845,3435,3067,2817,2647,2510,2408,2361,2349,2331,2288,2232,2171,2108,2055,2029,2027,2023,
+2001,1974,1960,1950,1918,1857,1783,1714,1652,1600,1569,1561,1553,1505,1400,1253,1106,993,914,840,739,
+602,451,309,181,60,-45,-121,-162,-194,-241,-301,-352,-383,-406,-435,-471,-507,-537,-563,-583,-594,
+-598,-597,-599,-606,-620,-635,-641,-631,-610,-591,-575,-549,-496,-418,-335,-273,-243,-243,-255,-261,-263,
+-278,-322,-383,-430,-448,-448,-455,-472,-488,-506,-539,-593,-647,-665,-634,-577,-539,-562,-653,-783,-902,
+-980,-1023,-1050,-1063,-1047,-1003,-957,-936,-939,-944,-940,-933,-932,-929,-915,-893,-874,-863,-854,-843,-831,
+-819,-804,-786,-767,-747,-725,-700,-676,-655,-635,-618,-606,-605,-612,-618,-621,-624,-629,-634,-634,-634,
+-635,-639,-639,-637,-635,-636,-636,-631,-622,-614,-606,-594,-578,-562,-545,-526,-504,-482,-462,-444,-427,
+-408,-386,-359,-325,-291,-258,-227,-194,-159,-125,-95,-63,-28,7,42,74,106,139,171,203,236,
+270,304,337,368,401,436,470,506,543,582,621,658,694,734,778,820,859,894,927,962,996,
+1027,1052,1074,1094,1114,1133,1153,1177,1199,1214,1218,1218,1224,1236,1248,1254,1256,1261,1267,1269,1268,
+1268,1273,1280,1287,1296,1305,1313,1319,1325,1336,1350,1366,1383,1405,1428,1446,1461,1479,1506,1534,1552,
+1562,1572,1591,1616,1640,1662,1682,1700,1712,1719,1729,1745,1766,1790,1817,1846,1876,1906,1932,1957,1985,
+2018,2050,2080,2107,2132,2158,2186,2216,2248,2280,2318,2368,2427,2480,2509,2515,2519,2534,2544,2522,2465,
+2399,2350,2320,2290,2255,2226,2215,2217,2222,2225,2230,2242,2255,2268,2288,2314,2342,2370,2411,2482,2580,
+2674,2734,2758,2773,2801,2840,2872,2893,2917,2957,3007,3049,3079,3108,3142,3171,3182,3170,3139,3087,3008,
+2905,2797,2711,2659,2633,2612,2579,2525,2456,2383,2315,2252,2189,2130,2084,2055,2036,2019,2004,1997,1995,
+1981,1946,1896,1846,1805,1777,1758,1745,1728,1701,1668,1642,1624,1604,1569,1524,1479,1444,1413,1376,1330,
+1280,1231,1189,1162,1157,1170,1185,1182,1153,1110,1073,1048,1013,940,820,682,566,494,457,439,428,
+424,423,421,416,406,379,327,254,183,131,99,73,43,7,-28,-62,-94,-124,-143,-144,-127,
+-107,-103,-116,-131,-127,-108,-99,-113,-136,-141,-127,-124,-155,-205,-231,-200,-118,-13,88,177,240,
+264,249,231,260,352,464,534,539,505,460,401,317,222,150,100,26,-106,-266,-384,-429,-437,
+-457,-494,-521,-526,-530,-548,-568,-568,-553,-539,-532,-515,-482,-445,-425,-421,-420,-409,-389,-368,-353,
+-350,-359,-373,-382,-387,-394,-404,-410,-409,-410,-426,-453,-477,-488,-487,-480,-468,-451,-437,-438,-454,
+-476,-493,-503,-507,-505,-501,-498,-499,-495,-485,-480,-491,-515,-536,-542,-543,-554,-572,-588,-600,-617,
+-644,-672,-694,-714,-737,-759,-774,-787,-809,-842,-876,-899,-917,-944,-979,-1018,-1060,-1108,-1162,-1216,-1265,
+-1314,-1369,-1425,-1475,-1519,-1563,-1611,-1658,-1706,-1761,-1826,-1891,-1949,-1996,-2039,-2083,-2129,-2181,-2242,-2305,-2364,
+-2415,-2461,-2510,-2559,-2609,-2662,-2721,-2784,-2840,-2884,-2919,-2948,-2977,-3011,-3052,-3099,-3145,-3186,-3227,-3269,-3310,
+-3347,-3383,-3423,-3465,-3505,-3539,-3571,-3602,-3628,-3646,-3663,-3688,-3721,-3757,-3787,-3810,-3828,-3842,-3857,-3874,-3892,
+-3901,-3897,-3885,-3873,-3857,-3836,-3830,-3870,-3967,-4090,-4186,-4229,-4240,-4259,-4305,-4363,-4408,-4426,-4429,-4436,-4456,
+-4483,-4506,-4519,-4522,-4526,-4537,-4554,-4566,-4568,-4560,-4552,-4549,-4550,-4548,-4538,-4529,-4527,-4536,-4551,-4567,-4585,
+-4605,-4627,-4647,-4662,-4667,-4660,-4646,-4630,-4613,-4592,-4566,-4534,-4498,-4455,-4409,-4366,-4333,-4307,-4276,-4235,-4192,
+-4155,-4120,-4075,-4014,-3947,-3883,-3821,-3752,-3672,-3587,-3516,-3477,-3478,-3513,-3564,-3605,-3613,-3574,-3491,-3383,-3280,
+-3210,-3174,-3159,-3150,-3143,-3140,-3141,-3146,-3154,-3164,-3166,-3151,-3119,-3079,-3039,-2997,-2948,-2888,-2810,-2701,-2563,
+-2414,-2278,-2152,-2012,-1846,-1676,-1540,-1448,-1380,-1310,-1231,-1152,-1079,-1008,-938,-875,-828,-798,-780,-768,-756,
+-737,-707,-668,-625,-586,-553,-525,-497,-458,-401,-327,-249,-177,-120,-70,-15,57,145,234,307,352,
+370,367,352,337,331,337,351,365,381,407,442,478,507,540,599,694,811,918,991,1029,1049,
+1065,1086,1112,1143,1177,1209,1238,1263,1290,1326,1380,1450,1527,1597,1652,1695,1738,1795,1868,1954,2047,
+2144,2242,2336,2419,2484,2533,2573,2616,2671,2739,2807,2863,2902,2936,2983,3045,3111,3167,3217,3279,3361,
+3456,3541,3610,3672,3745,3828,3900,3937,3943,3936,3936,3939,3932,3915,3903,3909,3932,3960,3987,4023,4075,
+4140,4211,4283,4358,4437,4516,4590,4662,4737,4816,4895,4969,5031,5075,5100,5105,5101,5103,5125,5166,5211,
+5241,5251,5244,5234,5223,5209,5193,5183,5187,5201,5217,5227,5229,5222,5201,5172,5149,5143,5144,5124,5070,
+5003,4961,4964,4989,4998,4978,4951,4943,4958,4974,4978,4977,4979,4970,4940,4912,4942,5059,5211,5296,5256,
+5136,5046,5050,5128,5212,5265,5288,5299,5299,5292,5291,5301,5305,5284,5244,5212,5204,5206,5199,5190,5198,
+5224,5251,5274,5328,5451,5634,5821,5951,6001,5986,5929,5851,5777,5738,5742,5749,5683,5495,5219,4963,4833,
+4867,5021,5219,5406,5554,5652,5694,5686,5644,5580,5500,5416,5345,5300,5279,5268,5257,5250,5255,5273,5303,
+5341,5379,5402,5396,5359,5305,5250,5201,5161,5131,5108,5090,5068,5041,5015,5003,5011,5032,5051,5071,5104,
+5160,5221,5255,5248,5219,5200,5204,5223,5242,5259,5269,5266,5248,5205,5092,4824,4342,3696,3058,2621,2474,
+2561,2743,2906,3003,3047,3065,3073,3064,3030,2975,2915,2857,2798,2729,2653,2585,2530,2482,2426,2360,2290,
+2220,2151,2085,2022,1962,1901,1841,1785,1732,1674,1614,1559,1516,1475,1427,1378,1339,1315,1292,1258,1224,
+1206,1206,1207,1196,1176,1153,1127,1094,1058,1032,1023,1022,1015,993,960,923,886,851,816,781,747,
+714,676,630,575,523,484,458,435,404,367,333,305,285,272,262,245,214,172,139,131,145,
+151,119,46,-33,-73,-57,-16,-6,-60,-157,-245,-293,-314,-340,-380,-417,-439,-457,-485,-523,-556,
+-578,-596,-613,-628,-639,-652,-671,-694,-714,-732,-750,-767,-776,-780,-789,-810,-835,-851,-857,-860,-862,
+-860,-858,-866,-892,-928,-961,-985,-1004,-1022,-1039,-1053,-1063,-1067,-1061,-1053,-1056,-1077,-1102,-1109,-1098,-1089,
+-1099,-1119,-1131,-1132,-1139,-1161,-1184,-1191,-1181,-1170,-1167,-1165,-1157,-1145,-1139,-1142,-1145,-1142,-1136,-1134,-1137,
+-1141,-1142,-1142,-1144,-1146,-1146,-1141,-1132,-1123,-1116,-1112,-1109,-1106,-1101,-1095,-1088,-1082,-1076,-1066,-1055,-1043,
+-1034,-1029,-1026,-1018,-1003,-984,-967,-953,-942,-929,-915,-900,-885,-871,-855,-837,-819,-798,-778,-759,-742,
+-725,-707,-687,-669,-653,-637,-619,-599,-580,-564,-550,-536,-522,-508,-494,-482,-470,-460,-448,-436,-426,
+-417,-410,-402,-393,-386,-380,-372,-361,-349,-343,-343,-345,-348,-350,-352,-353,-351,-346,-341,-339,-342,
+-344,-344,-339,-334,-332,-332,-333,-332,-333,-336,-340,-341,-338,-336,-339,-342,-340,-337,-334,-334,-336,
+-334,-330,-323,-316,-312,-314,-319,-321,-317,-314,-315,-317,-315,-308,-301,-297,-295,-294,-296,-301,-302,
+-296,-284,-272,-264,-257,-250,-245,-242,-241,-239,-234,-228,-221,-212,-204,-197,-191,-180,-167,-154,-143,
+-132,-119,-109,-102,-90,-74,-58,-51,-50,-46,-36,-24,-16,-12,-10,-10,-9,-2,12,31,44,
+51,59,70,83,96,109,124,139,153,166,180,192,202,216,235,256,274,289,304,321,339,
+360,389,419,442,464,498,548,591,604,595,600,641,696,725,717,698,704,742,788,818,824,
+823,833,860,892,919,946,981,1020,1054,1088,1138,1207,1274,1324,1365,1417,1480,1536,1581,1625,1672,
+1705,1723,1755,1821,1898,1949,1974,1995,1991,1886,1642,1362,1246,1452,1962,2598,3131,3416,3470,3441,3483,
+3628,3798,3924,4031,4173,4330,4424,4423,4385,4366,4353,4311,4267,4269,4270,4137,3795,3335,2935,2689,2555,
+2462,2390,2358,2355,2344,2307,2257,2205,2151,2097,2052,2023,1996,1964,1938,1929,1926,1905,1855,1788,1723,
+1664,1614,1578,1554,1528,1473,1374,1241,1103,991,911,840,747,617,468,324,192,70,-34,-107,-144,
+-169,-205,-254,-301,-336,-368,-406,-448,-485,-516,-541,-561,-574,-580,-579,-573,-569,-576,-595,-612,-611,
+-593,-571,-552,-523,-469,-388,-302,-237,-209,-219,-245,-265,-271,-280,-318,-382,-445,-482,-494,-498,-503,
+-514,-536,-580,-636,-670,-655,-601,-554,-554,-617,-727,-850,-953,-1017,-1047,-1056,-1052,-1030,-991,-952,-933,
+-935,-942,-941,-929,-914,-897,-881,-870,-866,-862,-852,-836,-823,-813,-799,-780,-760,-744,-730,-711,-686,
+-660,-638,-624,-617,-617,-620,-621,-621,-624,-630,-635,-636,-636,-637,-638,-634,-628,-623,-624,-625,-622,
+-615,-606,-593,-579,-563,-548,-530,-509,-486,-463,-442,-418,-394,-373,-352,-327,-295,-262,-231,-202,-169,
+-134,-101,-73,-43,-6,32,67,98,128,160,192,225,260,297,335,368,400,432,466,499,532,
+566,602,638,674,710,750,793,835,871,901,929,961,998,1032,1057,1075,1097,1126,1158,1183,1201,
+1215,1225,1230,1232,1237,1247,1258,1263,1265,1267,1271,1272,1271,1272,1279,1289,1296,1301,1306,1312,1318,
+1324,1335,1351,1370,1391,1414,1438,1460,1479,1500,1526,1555,1578,1592,1607,1626,1649,1669,1686,1702,1717,
+1729,1737,1748,1766,1793,1817,1843,1870,1899,1929,1957,1986,2018,2053,2085,2113,2140,2165,2190,2216,2250,
+2293,2338,2381,2423,2471,2516,2544,2550,2555,2567,2565,2517,2427,2345,2316,2325,2325,2285,2230,2198,2202,
+2220,2231,2236,2244,2256,2270,2289,2315,2345,2374,2413,2481,2581,2686,2762,2800,2822,2849,2882,2905,2919,
+2939,2980,3034,3084,3125,3165,3208,3239,3244,3219,3175,3119,3043,2945,2838,2743,2677,2636,2605,2569,2522,
+2465,2405,2349,2296,2245,2197,2157,2127,2102,2078,2057,2044,2034,2015,1981,1935,1888,1850,1823,1806,1796,
+1784,1760,1726,1693,1665,1638,1602,1556,1512,1480,1458,1437,1411,1376,1341,1314,1303,1304,1310,1304,1276,
+1226,1169,1126,1102,1074,1006,887,747,631,559,521,498,483,480,487,494,497,490,468,422,353,
+277,212,167,136,108,77,42,6,-24,-44,-49,-41,-27,-19,-31,-57,-81,-82,-64,-50,-56,
+-73,-78,-68,-68,-99,-153,-194,-190,-132,-28,101,225,309,332,312,299,337,425,523,586,598,
+565,493,392,287,217,186,151,56,-100,-256,-343,-359,-359,-385,-429,-460,-473,-485,-505,-517,-508,
+-489,-476,-467,-445,-407,-372,-354,-350,-346,-337,-325,-312,-302,-301,-312,-330,-340,-342,-340,-341,-340,
+-336,-338,-358,-390,-418,-432,-435,-435,-431,-420,-408,-408,-422,-440,-449,-449,-443,-438,-436,-439,-441,
+-435,-423,-417,-428,-449,-463,-466,-469,-485,-508,-527,-542,-563,-593,-620,-640,-658,-682,-706,-721,-734,
+-756,-787,-816,-834,-852,-879,-914,-950,-987,-1031,-1084,-1137,-1186,-1236,-1291,-1345,-1391,-1432,-1476,-1524,-1574,
+-1628,-1688,-1753,-1814,-1862,-1902,-1942,-1987,-2037,-2093,-2154,-2218,-2274,-2321,-2366,-2414,-2466,-2520,-2578,-2640,-2701,
+-2754,-2795,-2826,-2854,-2886,-2924,-2971,-3019,-3063,-3103,-3144,-3190,-3233,-3270,-3304,-3342,-3382,-3416,-3446,-3477,-3513,
+-3545,-3567,-3586,-3614,-3654,-3697,-3732,-3754,-3767,-3778,-3791,-3808,-3825,-3835,-3837,-3833,-3825,-3808,-3786,-3783,-3830,
+-3929,-4043,-4124,-4156,-4167,-4193,-4248,-4311,-4356,-4374,-4379,-4388,-4410,-4437,-4459,-4472,-4478,-4487,-4501,-4517,-4528,
+-4530,-4524,-4516,-4513,-4515,-4517,-4514,-4509,-4506,-4511,-4523,-4540,-4560,-4584,-4608,-4626,-4634,-4633,-4625,-4614,-4600,
+-4582,-4560,-4534,-4506,-4472,-4429,-4379,-4333,-4304,-4287,-4267,-4232,-4187,-4141,-4098,-4049,-3989,-3925,-3867,-3819,-3775,
+-3727,-3676,-3632,-3605,-3599,-3607,-3620,-3629,-3623,-3588,-3517,-3418,-3320,-3249,-3209,-3188,-3170,-3153,-3141,-3139,-3148,
+-3168,-3192,-3203,-3189,-3152,-3110,-3075,-3042,-2994,-2923,-2823,-2693,-2541,-2388,-2255,-2137,-2011,-1864,-1712,-1586,-1496,
+-1422,-1344,-1262,-1191,-1129,-1065,-990,-916,-862,-836,-827,-820,-802,-766,-710,-644,-583,-539,-517,-512,-511,
+-501,-469,-406,-320,-231,-159,-109,-68,-18,47,123,191,240,266,273,268,259,259,272,293,314,
+331,352,379,407,432,462,516,604,714,817,889,926,940,949,963,986,1019,1062,1112,1162,1210,
+1256,1303,1355,1412,1473,1536,1599,1661,1724,1792,1866,1945,2025,2105,2185,2267,2344,2409,2459,2499,2540,
+2595,2663,2729,2779,2813,2846,2897,2965,3035,3091,3137,3192,3267,3353,3431,3494,3552,3622,3707,3786,3836,
+3851,3845,3838,3838,3835,3826,3818,3818,3828,3845,3868,3904,3959,4028,4103,4180,4259,4341,4427,4512,4595,
+4672,4745,4818,4893,4964,5019,5047,5051,5043,5040,5053,5083,5123,5159,5181,5190,5190,5182,5165,5142,5129,
+5134,5152,5164,5161,5149,5138,5123,5101,5076,5069,5082,5091,5059,4987,4911,4874,4880,4898,4896,4878,4867,
+4881,4910,4930,4933,4921,4899,4868,4848,4875,4969,5097,5186,5184,5110,5040,5033,5086,5156,5209,5238,5251,
+5253,5252,5261,5275,5273,5241,5196,5173,5183,5199,5195,5179,5182,5214,5251,5273,5300,5370,5494,5641,5764,
+5844,5885,5894,5866,5806,5743,5713,5713,5689,5582,5381,5147,4959,4870,4877,4953,5066,5186,5279,5325,5323,
+5288,5232,5159,5080,5027,5022,5061,5113,5153,5181,5215,5266,5325,5374,5400,5396,5367,5320,5268,5219,5179,
+5148,5122,5099,5074,5050,5031,5022,5024,5034,5044,5052,5067,5105,5165,5223,5249,5233,5201,5187,5201,5226,
+5239,5238,5234,5235,5226,5164,4971,4575,3979,3304,2749,2469,2477,2652,2847,2978,3045,3079,3099,3101,3077,
+3030,2973,2915,2856,2789,2713,2637,2572,2517,2464,2407,2346,2281,2210,2135,2064,2002,1947,1889,1830,1775,
+1723,1670,1615,1565,1524,1486,1442,1395,1356,1328,1300,1262,1223,1199,1193,1193,1188,1174,1157,1132,1096,
+1056,1023,1002,991,979,960,932,897,858,821,786,752,716,676,632,588,545,508,478,453,427,
+395,361,327,297,272,254,242,229,203,168,136,123,128,129,98,31,-46,-95,-88,-45,-19,
+-55,-145,-242,-304,-329,-343,-367,-398,-425,-451,-482,-519,-554,-584,-608,-627,-642,-656,-674,-699,-723,
+-741,-754,-770,-785,-794,-798,-804,-818,-836,-849,-856,-863,-870,-872,-871,-876,-894,-922,-952,-982,-1008,
+-1027,-1038,-1046,-1058,-1073,-1083,-1086,-1093,-1110,-1129,-1130,-1111,-1093,-1095,-1114,-1134,-1148,-1164,-1185,-1195,-1182,
+-1154,-1140,-1154,-1180,-1193,-1185,-1170,-1161,-1157,-1152,-1145,-1139,-1139,-1140,-1139,-1139,-1142,-1146,-1146,-1140,-1130,
+-1122,-1117,-1113,-1108,-1103,-1098,-1092,-1086,-1078,-1068,-1058,-1047,-1037,-1031,-1027,-1023,-1017,-1006,-991,-975,-960,
+-947,-934,-919,-904,-887,-869,-852,-835,-819,-802,-785,-770,-757,-742,-721,-698,-677,-660,-646,-629,-610,
+-592,-577,-563,-549,-534,-518,-504,-492,-481,-471,-461,-450,-439,-430,-422,-414,-405,-397,-390,-382,-372,
+-361,-356,-358,-363,-367,-368,-368,-368,-366,-360,-353,-350,-354,-359,-360,-356,-351,-350,-349,-345,-342,
+-343,-349,-355,-354,-351,-350,-353,-353,-349,-344,-342,-343,-345,-343,-339,-331,-323,-318,-318,-321,-322,
+-319,-315,-314,-314,-312,-306,-300,-296,-292,-289,-291,-294,-293,-284,-269,-256,-249,-243,-236,-228,-224,
+-224,-224,-223,-216,-205,-193,-185,-181,-174,-164,-152,-142,-133,-119,-104,-95,-92,-84,-68,-48,-36,
+-31,-27,-19,-9,0,7,12,13,11,15,27,43,54,62,73,86,98,109,121,136,152,
+166,179,194,209,219,227,240,259,277,292,306,325,350,377,404,427,447,470,502,540,569,
+580,589,622,674,716,722,706,701,726,764,792,804,809,820,838,860,884,914,953,995,1032,
+1060,1094,1150,1225,1297,1349,1389,1435,1488,1538,1583,1628,1674,1711,1740,1785,1856,1929,1974,1995,2010,
+1992,1869,1617,1342,1247,1478,2006,2640,3144,3391,3429,3421,3495,3645,3778,3855,3939,4097,4285,4400,4412,
+4391,4399,4409,4369,4307,4285,4270,4124,3758,3265,2840,2596,2494,2440,2392,2362,2352,2337,2305,2265,2229,
+2191,2143,2093,2050,2012,1975,1947,1932,1923,1899,1850,1785,1722,1668,1623,1583,1542,1492,1426,1337,1226,
+1106,997,912,837,746,622,475,329,196,75,-26,-97,-137,-161,-189,-222,-254,-283,-318,-364,-413,
+-457,-493,-521,-540,-550,-552,-547,-535,-524,-526,-546,-569,-576,-563,-546,-528,-499,-441,-358,-275,-217,
+-199,-218,-254,-282,-290,-292,-313,-363,-426,-479,-513,-533,-541,-544,-556,-587,-623,-632,-604,-567,-570,
+-633,-740,-855,-955,-1028,-1068,-1077,-1063,-1040,-1012,-985,-963,-954,-955,-956,-947,-926,-900,-875,-858,-851,
+-848,-841,-824,-805,-792,-784,-774,-760,-746,-738,-730,-715,-690,-664,-644,-634,-631,-631,-630,-627,-626,
+-628,-632,-635,-634,-632,-631,-629,-622,-615,-610,-609,-608,-605,-600,-591,-578,-562,-545,-528,-508,-484,
+-460,-440,-420,-394,-364,-336,-312,-287,-257,-227,-200,-172,-140,-105,-74,-48,-19,17,56,92,122,
+154,187,221,254,289,328,365,397,426,458,491,524,555,588,622,656,688,721,758,801,842,
+877,904,930,963,1004,1043,1072,1092,1117,1154,1192,1219,1230,1235,1241,1246,1247,1248,1254,1263,1268,
+1267,1265,1267,1268,1268,1271,1280,1292,1299,1303,1308,1318,1329,1338,1349,1365,1384,1404,1425,1448,1472,
+1493,1514,1539,1568,1594,1614,1632,1652,1673,1691,1706,1721,1738,1751,1762,1775,1793,1814,1837,1861,1886,
+1914,1945,1976,2009,2046,2082,2114,2142,2169,2197,2222,2248,2283,2334,2388,2433,2469,2509,2550,2578,2585,
+2583,2581,2558,2485,2379,2308,2318,2378,2404,2352,2258,2195,2191,2217,2236,2242,2248,2262,2278,2299,2328,
+2364,2400,2439,2500,2591,2694,2780,2836,2874,2908,2934,2945,2947,2962,3001,3053,3098,3135,3178,3229,3268,
+3272,3240,3189,3133,3066,2979,2875,2776,2700,2650,2614,2579,2540,2496,2448,2399,2351,2308,2271,2240,2211,
+2182,2153,2129,2111,2092,2066,2029,1986,1943,1903,1868,1845,1833,1825,1810,1783,1747,1709,1671,1631,1589,
+1550,1522,1510,1508,1506,1497,1484,1478,1478,1476,1454,1407,1337,1260,1193,1152,1137,1119,1063,954,820,
+706,633,590,559,539,539,556,574,581,573,554,516,453,370,288,225,188,166,142,111,76,
+51,42,48,60,70,68,50,17,-15,-28,-20,-7,-5,-14,-19,-17,-22,-50,-100,-150,-172,
+-142,-48,94,240,333,354,337,338,388,471,555,616,644,621,533,401,285,235,235,210,101,
+-66,-213,-281,-288,-296,-334,-385,-421,-441,-457,-469,-464,-441,-419,-409,-401,-377,-340,-308,-292,-286,
+-278,-267,-256,-248,-243,-247,-262,-278,-283,-275,-266,-266,-270,-274,-282,-303,-334,-363,-380,-389,-392,
+-388,-374,-363,-367,-384,-397,-396,-385,-376,-376,-382,-388,-388,-380,-368,-363,-371,-385,-392,-393,-400,
+-420,-446,-467,-485,-510,-539,-563,-581,-601,-628,-653,-668,-680,-700,-728,-752,-769,-787,-816,-850,-883,
+-916,-956,-1006,-1058,-1108,-1160,-1215,-1264,-1305,-1344,-1389,-1443,-1499,-1558,-1621,-1683,-1734,-1770,-1800,-1837,-1887,
+-1944,-2003,-2065,-2125,-2178,-2224,-2269,-2319,-2375,-2433,-2494,-2556,-2615,-2662,-2698,-2727,-2758,-2794,-2840,-2890,-2940,
+-2982,-3019,-3060,-3108,-3153,-3190,-3221,-3255,-3291,-3323,-3352,-3385,-3424,-3461,-3489,-3511,-3542,-3585,-3630,-3665,-3686,
+-3699,-3711,-3725,-3741,-3757,-3769,-3776,-3779,-3773,-3757,-3738,-3743,-3796,-3892,-3993,-4058,-4083,-4097,-4131,-4190,-4253,
+-4298,-4319,-4328,-4341,-4363,-4389,-4410,-4423,-4434,-4447,-4464,-4478,-4485,-4485,-4482,-4477,-4476,-4479,-4483,-4486,-4485,
+-4483,-4486,-4496,-4513,-4536,-4561,-4583,-4598,-4604,-4601,-4595,-4587,-4575,-4557,-4532,-4504,-4475,-4442,-4400,-4352,-4310,
+-4284,-4272,-4257,-4226,-4178,-4125,-4077,-4034,-3986,-3931,-3873,-3820,-3777,-3743,-3719,-3705,-3700,-3699,-3692,-3676,-3653,
+-3628,-3594,-3540,-3464,-3378,-3303,-3249,-3211,-3182,-3157,-3140,-3136,-3148,-3176,-3210,-3231,-3222,-3188,-3147,-3113,-3074,
+-3013,-2919,-2797,-2657,-2510,-2367,-2242,-2131,-2016,-1885,-1751,-1638,-1551,-1474,-1391,-1309,-1238,-1179,-1115,-1037,-959,
+-903,-878,-873,-869,-848,-799,-724,-640,-571,-532,-522,-528,-536,-534,-512,-457,-373,-279,-202,-153,-124,
+-93,-48,4,55,95,122,138,144,148,160,186,222,260,289,310,326,339,356,385,438,521,
+618,707,769,802,817,830,847,874,912,963,1022,1082,1140,1191,1234,1265,1290,1322,1374,1453,1549,
+1648,1742,1832,1915,1989,2054,2113,2174,2237,2299,2352,2398,2446,2508,2581,2648,2694,2722,2752,2801,2867,
+2936,2992,3038,3090,3156,3234,3312,3382,3447,3515,3592,3667,3722,3746,3744,3734,3728,3727,3724,3717,3713,
+3717,3730,3754,3790,3842,3910,3987,4068,4147,4229,4319,4421,4522,4609,4676,4736,4805,4882,4946,4980,4984,
+4975,4972,4981,5002,5033,5068,5102,5130,5146,5146,5125,5093,5072,5079,5101,5111,5093,5064,5045,5038,5024,
+4999,4988,5008,5038,5029,4958,4862,4800,4799,4833,4853,4845,4833,4843,4873,4895,4892,4867,4837,4813,4804,
+4824,4888,4988,5081,5121,5098,5050,5025,5045,5096,5151,5190,5205,5203,5202,5219,5245,5251,5220,5170,5142,
+5154,5182,5194,5188,5188,5210,5243,5271,5297,5346,5429,5529,5620,5691,5749,5796,5819,5806,5762,5714,5682,
+5655,5596,5484,5327,5160,5016,4916,4871,4879,4923,4970,4995,4998,4994,4988,4973,4951,4947,4987,5067,5152,
+5213,5252,5288,5334,5378,5400,5391,5358,5317,5277,5238,5201,5166,5136,5110,5084,5057,5033,5020,5021,5029,
+5037,5042,5048,5066,5106,5164,5219,5243,5227,5195,5180,5197,5223,5231,5214,5197,5200,5197,5102,4810,4276,
+3584,2926,2505,2404,2547,2775,2955,3051,3095,3121,3134,3123,3086,3033,2978,2923,2860,2785,2704,2627,2561,
+2501,2441,2381,2324,2264,2196,2121,2050,1989,1936,1879,1818,1761,1712,1666,1617,1569,1528,1492,1454,1414,
+1374,1338,1301,1261,1225,1199,1186,1179,1173,1166,1153,1130,1095,1055,1020,994,973,951,927,896,861,
+822,785,753,721,686,645,602,562,525,491,462,435,407,378,348,318,292,268,250,236,221,
+198,167,136,112,98,83,54,2,-63,-115,-126,-99,-69,-80,-144,-227,-287,-305,-302,-308,-338,
+-387,-439,-481,-513,-540,-572,-609,-643,-664,-675,-687,-704,-722,-734,-742,-751,-762,-773,-782,-795,-814,
+-834,-851,-864,-875,-884,-891,-896,-903,-915,-930,-947,-968,-993,-1015,-1028,-1038,-1052,-1070,-1085,-1093,-1100,
+-1115,-1131,-1132,-1112,-1091,-1089,-1110,-1139,-1164,-1182,-1189,-1173,-1130,-1082,-1064,-1095,-1152,-1199,-1214,-1207,-1195,
+-1186,-1178,-1167,-1156,-1149,-1142,-1136,-1134,-1136,-1140,-1139,-1131,-1122,-1116,-1112,-1107,-1099,-1092,-1089,-1089,-1086,
+-1078,-1067,-1054,-1043,-1035,-1031,-1027,-1021,-1014,-1006,-997,-986,-972,-958,-944,-930,-913,-893,-872,-852,-836,
+-821,-806,-793,-782,-771,-757,-737,-714,-692,-675,-659,-643,-625,-610,-596,-582,-567,-551,-535,-520,-506,
+-495,-484,-475,-465,-455,-446,-438,-429,-419,-409,-400,-394,-387,-381,-379,-382,-388,-389,-387,-384,-384,
+-382,-376,-367,-363,-367,-373,-373,-368,-364,-366,-367,-362,-356,-355,-360,-365,-364,-361,-361,-364,-363,
+-357,-351,-350,-350,-350,-346,-342,-336,-328,-321,-319,-320,-320,-316,-312,-311,-310,-308,-305,-300,-294,
+-287,-281,-280,-282,-280,-269,-254,-242,-236,-231,-223,-214,-209,-208,-209,-207,-201,-189,-178,-171,-166,
+-158,-146,-134,-126,-117,-103,-87,-79,-79,-76,-62,-41,-24,-15,-10,-4,2,10,21,30,33,
+31,33,43,56,66,74,86,102,115,124,134,149,165,176,187,203,221,233,241,252,267,
+283,296,311,333,359,382,400,419,444,476,510,540,562,584,617,662,702,712,696,686,710,
+759,799,808,801,803,823,849,871,892,923,967,1014,1050,1077,1111,1168,1244,1317,1370,1410,1449,
+1495,1541,1587,1635,1682,1723,1762,1815,1884,1947,1982,1998,2008,1979,1841,1580,1313,1242,1503,2049,2670,
+3129,3328,3349,3364,3473,3631,3737,3782,3857,4027,4232,4357,4378,4376,4413,4447,4415,4343,4302,4268,4106,
+3725,3217,2785,2549,2472,2444,2409,2375,2354,2334,2307,2278,2257,2236,2201,2155,2107,2063,2019,1979,1947,
+1920,1887,1839,1781,1725,1677,1635,1590,1533,1463,1385,1301,1208,1103,999,909,828,737,617,475,331,
+200,87,-6,-74,-119,-151,-179,-202,-218,-236,-265,-307,-353,-399,-441,-476,-497,-504,-500,-492,-482,
+-475,-480,-500,-522,-529,-519,-504,-487,-455,-398,-324,-258,-221,-217,-240,-276,-305,-318,-318,-327,-357,
+-405,-458,-508,-545,-563,-564,-563,-572,-585,-581,-564,-570,-635,-756,-888,-992,-1059,-1100,-1119,-1111,-1080,
+-1040,-1005,-983,-971,-968,-967,-962,-947,-924,-895,-869,-850,-837,-825,-808,-788,-771,-762,-758,-753,-745,
+-740,-738,-733,-717,-692,-668,-652,-644,-641,-640,-638,-635,-633,-633,-634,-632,-628,-624,-621,-616,-608,
+-602,-597,-593,-587,-581,-576,-570,-558,-540,-520,-499,-476,-449,-426,-409,-392,-366,-333,-301,-274,-248,
+-220,-191,-167,-142,-112,-77,-47,-21,6,42,80,114,146,181,219,254,286,320,356,389,417,
+444,473,507,540,571,604,639,673,702,731,767,810,854,892,922,952,989,1033,1074,1103,1122,
+1143,1174,1206,1228,1235,1239,1246,1252,1252,1251,1255,1264,1269,1267,1262,1261,1263,1266,1271,1282,1294,
+1302,1307,1317,1333,1349,1360,1369,1383,1401,1420,1438,1458,1480,1501,1521,1545,1573,1600,1621,1638,1656,
+1676,1695,1712,1730,1749,1766,1780,1795,1814,1823,1848,1874,1901,1930,1962,1994,2028,2064,2101,2133,2161,
+2191,2224,2255,2285,2323,2375,2432,2477,2509,2542,2580,2607,2609,2597,2579,2537,2452,2345,2288,2327,2416,
+2456,2396,2283,2203,2193,2220,2240,2244,2251,2268,2289,2314,2349,2394,2439,2480,2531,2605,2695,2778,2841,
+2891,2932,2959,2966,2966,2981,3020,3065,3099,3129,3171,3227,3271,3273,3233,3176,3122,3065,2988,2889,2790,
+2713,2664,2629,2597,2565,2532,2497,2456,2413,2376,2349,2325,2296,2260,2226,2202,2182,2159,2127,2090,2051,
+2009,1963,1917,1882,1864,1858,1851,1831,1796,1750,1702,1659,1623,1596,1579,1577,1591,1609,1620,1623,1626,
+1628,1613,1559,1465,1349,1242,1166,1132,1132,1136,1104,1016,896,788,714,666,628,601,601,625,652,
+664,658,642,612,552,462,363,287,247,231,214,184,149,129,131,143,153,151,138,114,81,
+48,30,30,39,42,36,29,24,15,-6,-45,-96,-136,-130,-49,95,245,335,354,349,378,
+447,526,590,641,678,669,583,447,334,299,309,279,161,-5,-140,-201,-219,-245,-295,-348,-384,
+-405,-419,-418,-396,-364,-342,-338,-334,-315,-283,-256,-243,-235,-224,-210,-197,-187,-184,-193,-212,-224,
+-218,-197,-180,-180,-193,-209,-225,-247,-277,-305,-325,-337,-341,-333,-319,-313,-324,-343,-349,-335,-316,
+-309,-316,-326,-331,-330,-325,-321,-322,-328,-336,-340,-343,-351,-369,-390,-408,-427,-450,-477,-499,-519,
+-543,-572,-595,-607,-618,-637,-663,-686,-704,-723,-751,-782,-810,-841,-881,-928,-979,-1030,-1084,-1137,-1182,
+-1218,-1256,-1305,-1366,-1428,-1489,-1549,-1603,-1643,-1670,-1696,-1736,-1792,-1856,-1919,-1978,-2033,-2082,-2127,-2175,-2228,
+-2286,-2347,-2411,-2473,-2526,-2568,-2600,-2631,-2667,-2710,-2759,-2813,-2862,-2903,-2938,-2978,-3025,-3070,-3106,-3134,-3164,
+-3197,-3229,-3259,-3293,-3334,-3374,-3407,-3436,-3471,-3514,-3558,-3592,-3614,-3631,-3648,-3665,-3681,-3696,-3708,-3717,-3719,
+-3713,-3699,-3690,-3707,-3768,-3858,-3943,-3994,-4014,-4032,-4071,-4131,-4193,-4241,-4269,-4283,-4296,-4316,-4340,-4361,-4377,
+-4391,-4407,-4423,-4433,-4435,-4434,-4433,-4434,-4436,-4441,-4447,-4454,-4457,-4460,-4465,-4477,-4494,-4513,-4532,-4549,-4562,
+-4569,-4569,-4565,-4558,-4546,-4528,-4503,-4474,-4443,-4410,-4372,-4330,-4293,-4267,-4251,-4234,-4204,-4158,-4107,-4063,-4031,
+-4001,-3962,-3909,-3850,-3799,-3761,-3737,-3725,-3722,-3725,-3722,-3706,-3675,-3640,-3604,-3562,-3502,-3426,-3347,-3279,-3227,
+-3187,-3159,-3143,-3143,-3159,-3190,-3226,-3251,-3249,-3222,-3187,-3149,-3097,-3010,-2888,-2747,-2604,-2469,-2342,-2226,-2120,
+-2015,-1902,-1791,-1695,-1616,-1541,-1459,-1376,-1301,-1235,-1166,-1088,-1012,-956,-928,-921,-917,-898,-848,-768,-679,
+-611,-578,-569,-568,-562,-548,-524,-477,-406,-325,-256,-211,-186,-164,-138,-109,-83,-61,-42,-25,-8,
+9,35,73,124,181,230,261,272,272,279,306,360,436,519,590,638,666,685,704,727,757,
+795,840,890,940,988,1030,1059,1070,1068,1076,1121,1209,1327,1451,1569,1677,1772,1850,1908,1955,2002,
+2059,2122,2187,2251,2319,2398,2481,2553,2601,2630,2659,2703,2762,2825,2880,2929,2980,3039,3111,3193,3278,
+3357,3426,3489,3551,3604,3636,3640,3626,3611,3604,3601,3596,3591,3596,3613,3640,3677,3726,3792,3875,3961,
+4040,4116,4204,4313,4430,4528,4596,4652,4719,4799,4868,4904,4910,4905,4906,4914,4928,4949,4982,5025,5068,
+5101,5110,5090,5051,5024,5029,5051,5055,5021,4975,4949,4946,4939,4914,4895,4911,4946,4947,4882,4785,4724,
+4734,4788,4829,4832,4817,4816,4832,4843,4830,4801,4776,4768,4774,4791,4828,4893,4972,5031,5043,5017,4989,
+4991,5033,5094,5144,5162,5153,5141,5152,5184,5207,5194,5153,5116,5111,5133,5159,5175,5185,5200,5219,5239,
+5265,5306,5368,5444,5517,5579,5632,5683,5730,5757,5751,5713,5663,5618,5579,5528,5449,5335,5200,5065,4959,
+4896,4872,4867,4866,4874,4903,4952,5003,5043,5084,5143,5218,5287,5330,5351,5366,5385,5396,5386,5354,5313,
+5277,5248,5219,5183,5146,5113,5088,5066,5042,5020,5008,5008,5014,5021,5029,5042,5065,5104,5155,5205,5233,
+5225,5196,5179,5192,5217,5220,5191,5162,5163,5152,5007,4607,3953,3210,2624,2366,2433,2672,2910,3056,3120,
+3149,3165,3164,3137,3090,3038,2986,2931,2863,2783,2700,2624,2555,2490,2427,2367,2310,2253,2187,2114,2043,
+1981,1924,1864,1803,1748,1702,1660,1617,1571,1528,1493,1460,1426,1385,1340,1296,1257,1226,1201,1180,1165,
+1157,1154,1146,1123,1086,1048,1015,989,964,936,905,869,830,791,755,724,693,659,623,587,550,
+512,475,441,412,385,357,327,300,276,257,242,228,212,191,164,134,100,67,38,9,-26,
+-75,-125,-155,-152,-130,-124,-157,-216,-264,-276,-262,-260,-299,-376,-458,-507,-518,-515,-532,-578,-632,
+-668,-679,-679,-683,-695,-706,-713,-719,-727,-741,-759,-783,-810,-836,-858,-876,-889,-898,-906,-915,-927,
+-940,-948,-955,-966,-985,-1006,-1022,-1034,-1048,-1066,-1081,-1091,-1101,-1117,-1132,-1134,-1118,-1099,-1097,-1117,-1148,
+-1174,-1189,-1184,-1155,-1102,-1049,-1029,-1060,-1125,-1188,-1222,-1228,-1221,-1212,-1203,-1193,-1181,-1168,-1154,-1142,-1135,
+-1134,-1134,-1129,-1120,-1112,-1108,-1103,-1095,-1085,-1079,-1081,-1086,-1087,-1082,-1069,-1054,-1041,-1034,-1030,-1026,-1018,
+-1009,-1002,-995,-987,-976,-963,-950,-935,-918,-898,-877,-858,-841,-826,-811,-799,-789,-778,-764,-745,-726,
+-708,-691,-674,-658,-641,-627,-614,-599,-583,-567,-552,-538,-523,-509,-497,-487,-478,-469,-460,-453,-444,
+-432,-420,-411,-407,-405,-405,-406,-409,-412,-410,-402,-396,-395,-394,-389,-380,-376,-380,-386,-384,-377,
+-373,-376,-380,-378,-373,-370,-373,-375,-371,-367,-367,-369,-368,-362,-358,-357,-356,-352,-346,-341,-335,
+-329,-322,-319,-318,-316,-312,-308,-306,-306,-304,-302,-297,-289,-278,-269,-268,-271,-269,-259,-246,-236,
+-230,-223,-214,-206,-202,-199,-196,-192,-186,-177,-167,-159,-153,-143,-128,-111,-100,-91,-79,-67,-60,
+-59,-56,-44,-26,-11,-2,4,9,13,20,30,40,42,40,42,54,69,79,87,99,116,
+130,138,149,165,180,190,197,210,226,241,255,272,292,308,319,335,359,382,394,399,414,
+448,491,527,551,576,613,662,701,710,687,661,669,721,786,823,821,804,806,832,867,894,
+917,947,987,1031,1069,1102,1140,1195,1264,1330,1381,1417,1452,1491,1537,1586,1640,1693,1738,1780,1831,
+1890,1938,1963,1975,1981,1945,1799,1539,1287,1242,1530,2085,2680,3085,3227,3222,3249,3378,3540,3637,3678,
+3765,3955,4175,4310,4342,4353,4401,4445,4424,4358,4303,4234,4033,3638,3147,2749,2545,2488,2467,2431,2392,
+2367,2350,2329,2310,2299,2290,2268,2227,2176,2121,2064,2006,1954,1910,1870,1829,1784,1738,1693,1648,1597,
+1530,1449,1364,1280,1193,1096,994,900,816,724,610,476,341,221,120,41,-18,-66,-108,-144,-170,
+-187,-203,-227,-253,-280,-309,-347,-388,-418,-427,-423,-417,-416,-419,-431,-452,-472,-479,-468,-448,-419,
+-378,-325,-273,-242,-236,-249,-271,-300,-330,-351,-362,-370,-387,-416,-458,-506,-550,-577,-581,-576,-576,
+-578,-576,-579,-624,-732,-878,-1009,-1091,-1130,-1149,-1156,-1139,-1097,-1046,-1005,-982,-973,-969,-964,-955,-940,
+-918,-894,-871,-850,-832,-814,-796,-779,-768,-762,-757,-751,-745,-744,-743,-735,-717,-694,-674,-659,-650,
+-644,-640,-638,-636,-633,-630,-627,-622,-618,-614,-610,-604,-596,-590,-584,-576,-563,-553,-549,-546,-536,
+-515,-493,-471,-448,-422,-398,-380,-363,-338,-305,-273,-247,-221,-192,-164,-139,-116,-87,-55,-24,2,
+32,67,103,135,168,206,247,283,314,345,379,410,434,459,489,523,557,589,623,658,691,
+720,750,786,830,876,919,958,997,1038,1079,1116,1140,1153,1163,1178,1196,1210,1219,1228,1240,1248,
+1250,1249,1255,1266,1272,1269,1263,1263,1266,1271,1277,1288,1299,1308,1317,1330,1348,1364,1373,1380,1394,
+1413,1432,1449,1469,1491,1511,1529,1551,1577,1601,1618,1629,1643,1662,1683,1701,1720,1741,1762,1781,1800,
+1823,1831,1860,1890,1921,1953,1985,2015,2045,2078,2113,2146,2176,2209,2247,2286,2322,2362,2414,2469,2513,
+2545,2577,2612,2636,2633,2610,2579,2530,2444,2340,2281,2310,2388,2426,2377,2283,2221,2217,2241,2252,2251,
+2258,2277,2301,2328,2369,2422,2473,2513,2555,2616,2693,2767,2824,2870,2909,2940,2958,2971,2997,3038,3080,
+3110,3137,3182,3241,3282,3273,3218,3150,3092,3040,2971,2880,2787,2719,2677,2645,2614,2584,2563,2543,2515,
+2480,2449,2426,2403,2368,2323,2283,2258,2240,2217,2186,2154,2121,2081,2031,1977,1934,1909,1896,1885,1864,
+1828,1777,1720,1674,1647,1635,1635,1648,1676,1707,1727,1730,1726,1719,1690,1613,1485,1336,1205,1121,1093,
+1110,1141,1142,1085,983,879,803,751,708,676,670,693,725,742,742,731,704,643,547,441,364,
+328,317,297,261,223,208,217,232,235,219,192,161,131,107,95,93,93,88,78,66,56,
+47,33,7,-37,-86,-96,-24,118,268,354,374,387,445,533,606,645,675,708,709,641,523,
+426,393,389,340,215,60,-59,-122,-157,-198,-250,-296,-326,-344,-352,-343,-315,-283,-267,-268,-267,
+-254,-232,-214,-202,-192,-179,-164,-150,-141,-139,-148,-164,-169,-152,-122,-102,-104,-123,-145,-165,-188,
+-216,-243,-264,-278,-281,-274,-266,-268,-284,-299,-294,-271,-250,-245,-254,-261,-260,-258,-261,-268,-276,
+-285,-294,-302,-309,-317,-326,-337,-349,-364,-384,-408,-431,-455,-481,-507,-525,-536,-550,-573,-601,-625,
+-644,-665,-689,-712,-736,-766,-806,-854,-902,-952,-1006,-1059,-1102,-1135,-1173,-1226,-1292,-1356,-1413,-1462,-1505,
+-1539,-1566,-1598,-1647,-1710,-1776,-1839,-1895,-1944,-1989,-2035,-2085,-2141,-2202,-2265,-2328,-2388,-2437,-2475,-2508,-2545,
+-2587,-2633,-2681,-2732,-2782,-2825,-2862,-2901,-2945,-2988,-3022,-3049,-3077,-3110,-3142,-3173,-3206,-3245,-3286,-3324,-3360,
+-3400,-3444,-3485,-3519,-3545,-3568,-3591,-3611,-3628,-3641,-3651,-3656,-3654,-3646,-3635,-3637,-3669,-3737,-3822,-3892,-3931,
+-3948,-3971,-4015,-4076,-4141,-4194,-4228,-4244,-4253,-4268,-4292,-4317,-4337,-4352,-4367,-4382,-4390,-4390,-4387,-4387,-4392,
+-4398,-4406,-4415,-4424,-4432,-4440,-4451,-4466,-4481,-4493,-4502,-4510,-4521,-4530,-4534,-4531,-4521,-4507,-4489,-4467,-4442,
+-4413,-4381,-4347,-4312,-4278,-4249,-4223,-4200,-4171,-4134,-4092,-4054,-4028,-4008,-3982,-3943,-3895,-3847,-3804,-3763,-3725,
+-3699,-3693,-3703,-3709,-3699,-3672,-3637,-3593,-3531,-3453,-3370,-3296,-3238,-3193,-3163,-3152,-3159,-3182,-3215,-3249,-3271,
+-3271,-3249,-3215,-3171,-3102,-2995,-2853,-2698,-2554,-2425,-2308,-2200,-2102,-2011,-1923,-1836,-1757,-1688,-1618,-1541,-1457,
+-1374,-1296,-1221,-1146,-1078,-1024,-990,-974,-968,-954,-914,-844,-762,-697,-659,-636,-609,-575,-542,-511,-474,
+-424,-366,-315,-278,-253,-234,-218,-208,-202,-198,-191,-179,-160,-132,-97,-52,4,73,141,189,206,
+202,201,224,275,345,414,471,510,536,556,576,596,619,644,671,697,721,746,773,795,804,
+803,814,860,946,1056,1174,1289,1401,1502,1585,1646,1695,1747,1811,1888,1973,2064,2161,2264,2361,2440,
+2495,2533,2568,2611,2662,2715,2769,2822,2874,2927,2991,3073,3168,3259,3330,3384,3435,3485,3519,3524,3505,
+3482,3467,3461,3459,3460,3472,3495,3525,3561,3609,3678,3767,3860,3942,4015,4096,4201,4318,4422,4498,4563,
+4636,4720,4790,4827,4838,4841,4849,4857,4865,4880,4911,4957,5010,5052,5071,5056,5019,4989,4988,5004,4999,
+4957,4902,4872,4868,4858,4822,4785,4783,4806,4806,4750,4669,4624,4650,4717,4772,4788,4781,4777,4782,4782,
+4764,4736,4718,4720,4735,4753,4774,4809,4860,4909,4936,4934,4924,4934,4975,5038,5094,5120,5112,5089,5082,
+5100,5131,5147,5132,5098,5070,5066,5083,5111,5138,5159,5176,5193,5213,5242,5289,5354,5429,5498,5550,5593,
+5636,5679,5701,5685,5639,5592,5563,5543,5508,5438,5336,5222,5122,5050,5005,4979,4967,4977,5017,5082,5153,
+5212,5261,5308,5352,5383,5395,5393,5391,5388,5377,5352,5317,5284,5258,5233,5203,5164,5125,5092,5069,5050,
+5029,5008,4993,4989,4995,5006,5022,5042,5069,5102,5144,5190,5220,5219,5194,5176,5187,5212,5210,5172,5131,
+5119,5076,4860,4360,3631,2903,2437,2348,2543,2823,3033,3138,3178,3198,3205,3189,3149,3098,3046,2994,2932,
+2858,2778,2697,2622,2551,2485,2422,2363,2306,2246,2180,2110,2039,1972,1908,1847,1789,1736,1690,1648,1606,
+1565,1526,1491,1460,1426,1384,1335,1287,1249,1222,1196,1169,1147,1139,1141,1137,1115,1078,1039,1008,983,
+957,926,889,849,808,769,733,701,669,637,609,580,547,506,464,430,404,381,352,317,283,
+257,240,228,217,202,184,161,132,94,51,11,-18,-44,-77,-120,-160,-178,-173,-168,-186,-230,
+-273,-287,-275,-272,-314,-402,-492,-534,-515,-474,-464,-507,-579,-636,-658,-657,-657,-668,-686,-701,-710,
+-719,-735,-759,-788,-816,-839,-860,-880,-896,-906,-913,-923,-938,-953,-963,-969,-978,-992,-1008,-1022,-1033,
+-1046,-1063,-1080,-1095,-1109,-1126,-1140,-1144,-1137,-1126,-1127,-1142,-1164,-1182,-1189,-1184,-1167,-1138,-1107,-1093,-1108,
+-1148,-1192,-1221,-1230,-1226,-1220,-1216,-1213,-1207,-1193,-1176,-1160,-1149,-1145,-1140,-1130,-1119,-1112,-1106,-1099,-1088,
+-1076,-1072,-1076,-1082,-1085,-1081,-1069,-1055,-1041,-1033,-1029,-1026,-1018,-1007,-997,-990,-982,-972,-960,-948,-934,
+-918,-900,-882,-866,-850,-833,-817,-804,-793,-780,-763,-746,-731,-717,-703,-686,-669,-653,-639,-625,-609,
+-593,-577,-564,-551,-537,-522,-508,-498,-489,-481,-472,-463,-453,-441,-429,-422,-420,-422,-424,-426,-428,
+-428,-423,-413,-404,-402,-402,-398,-390,-387,-393,-399,-397,-388,-382,-384,-390,-390,-387,-385,-385,-384,
+-379,-374,-373,-374,-372,-368,-365,-363,-361,-355,-347,-340,-333,-327,-321,-318,-317,-314,-309,-306,-303,
+-301,-298,-296,-291,-281,-269,-261,-262,-265,-262,-251,-239,-230,-223,-214,-204,-197,-192,-187,-181,-177,
+-171,-163,-152,-143,-137,-128,-111,-91,-75,-65,-56,-49,-44,-40,-31,-17,-4,4,10,16,22,
+27,32,42,51,53,49,50,63,81,94,103,115,130,143,152,163,180,197,208,214,223,
+234,247,265,290,317,333,343,359,387,413,418,410,417,452,499,531,551,579,628,683,710,
+696,662,648,677,739,795,818,812,803,815,846,885,918,945,972,1004,1043,1085,1128,1173,1225,
+1284,1341,1385,1417,1445,1479,1522,1577,1641,1704,1756,1796,1835,1877,1913,1932,1943,1946,1906,1763,1516,
+1285,1264,1571,2128,2693,3041,3126,3090,3113,3252,3422,3528,3586,3697,3903,4133,4279,4325,4339,4375,4410,
+4400,4348,4272,4137,3868,3461,3030,2720,2578,2535,2499,2446,2402,2384,2376,2362,2347,2341,2338,2324,2287,
+2232,2166,2095,2025,1963,1911,1870,1834,1798,1755,1707,1655,1597,1529,1449,1362,1273,1183,1085,985,891,
+804,713,607,487,367,261,175,111,61,16,-28,-73,-111,-143,-175,-203,-215,-211,-209,-227,-267,
+-303,-319,-319,-319,-326,-338,-354,-376,-402,-419,-418,-392,-347,-292,-245,-224,-233,-257,-279,-297,-321,
+-354,-388,-414,-430,-446,-467,-498,-538,-581,-612,-624,-626,-628,-633,-641,-663,-725,-838,-972,-1081,-1141,
+-1165,-1176,-1175,-1149,-1097,-1039,-997,-978,-972,-967,-958,-946,-930,-910,-889,-869,-850,-833,-818,-804,-793,
+-784,-775,-764,-752,-744,-741,-736,-726,-709,-691,-676,-662,-649,-639,-634,-633,-630,-626,-620,-613,-608,
+-604,-602,-599,-593,-583,-575,-567,-557,-542,-530,-525,-523,-512,-491,-468,-449,-430,-407,-381,-359,-338,
+-312,-281,-251,-227,-202,-171,-139,-112,-87,-59,-29,0,28,60,95,129,158,190,228,270,306,
+337,368,402,433,459,484,516,552,587,619,652,688,721,751,782,819,860,903,948,996,1043,
+1085,1118,1144,1162,1172,1175,1178,1184,1194,1206,1221,1237,1247,1251,1253,1260,1271,1277,1274,1271,1273,
+1279,1284,1290,1299,1310,1321,1331,1345,1359,1370,1376,1383,1399,1421,1441,1460,1483,1507,1527,1543,1560,
+1582,1600,1610,1616,1627,1646,1666,1685,1704,1728,1754,1779,1804,1831,1855,1887,1919,1950,1982,2013,2041,
+2067,2097,2131,2164,2193,2224,2263,2305,2345,2386,2435,2491,2540,2580,2617,2653,2675,2666,2634,2595,2545,
+2469,2371,2296,2285,2322,2346,2322,2275,2251,2261,2276,2275,2268,2274,2293,2313,2337,2378,2434,2487,2525,
+2563,2621,2697,2770,2819,2852,2881,2913,2944,2975,3012,3055,3095,3128,3164,3217,3275,3306,3282,3209,3125,
+3059,3006,2943,2862,2782,2726,2693,2665,2632,2603,2591,2587,2573,2546,2516,2492,2465,2422,2369,2324,2298,
+2282,2261,2235,2211,2187,2153,2105,2053,2010,1978,1950,1920,1887,1844,1788,1726,1675,1653,1659,1681,1717,
+1763,1804,1822,1812,1790,1766,1725,1636,1494,1331,1191,1103,1076,1103,1156,1190,1165,1081,977,893,836,
+791,757,745,762,791,812,818,811,785,722,623,520,450,423,410,381,333,292,282,297,312,
+307,281,243,208,181,167,164,162,151,133,115,101,91,84,77,60,20,-32,-50,16,163,
+318,412,443,472,545,637,696,711,718,737,742,694,603,521,478,442,366,238,101,-1,-64,
+-109,-152,-194,-227,-252,-269,-274,-262,-238,-217,-208,-206,-202,-192,-180,-170,-160,-146,-131,-119,-111,
+-107,-106,-111,-117,-111,-88,-60,-46,-52,-72,-93,-113,-137,-165,-191,-209,-219,-222,-219,-218,-224,
+-236,-241,-231,-210,-195,-193,-197,-194,-187,-185,-193,-206,-217,-228,-243,-260,-271,-276,-278,-283,-291,
+-304,-321,-341,-364,-388,-412,-431,-446,-461,-485,-516,-546,-569,-589,-611,-633,-651,-668,-696,-737,-784,
+-828,-874,-926,-980,-1024,-1058,-1097,-1151,-1216,-1277,-1326,-1365,-1400,-1432,-1468,-1514,-1572,-1637,-1700,-1757,-1808,
+-1854,-1897,-1944,-1998,-2058,-2121,-2183,-2244,-2299,-2345,-2382,-2420,-2464,-2511,-2556,-2598,-2645,-2695,-2744,-2787,-2826,
+-2868,-2907,-2940,-2967,-2996,-3029,-3062,-3092,-3124,-3161,-3202,-3243,-3284,-3328,-3372,-3414,-3449,-3480,-3509,-3535,-3557,
+-3574,-3586,-3592,-3593,-3587,-3576,-3567,-3576,-3620,-3694,-3776,-3836,-3868,-3887,-3917,-3967,-4032,-4098,-4154,-4190,-4203,
+-4206,-4217,-4244,-4276,-4301,-4314,-4326,-4339,-4349,-4352,-4350,-4350,-4356,-4366,-4377,-4390,-4402,-4413,-4424,-4437,-4452,
+-4465,-4471,-4472,-4474,-4482,-4492,-4498,-4495,-4483,-4466,-4449,-4431,-4410,-4385,-4355,-4324,-4294,-4264,-4232,-4198,-4167,
+-4139,-4112,-4081,-4049,-4020,-3996,-3974,-3948,-3919,-3889,-3851,-3800,-3740,-3690,-3669,-3679,-3700,-3713,-3708,-3684,-3637,
+-3564,-3471,-3379,-3306,-3250,-3207,-3176,-3166,-3179,-3209,-3245,-3278,-3296,-3292,-3265,-3221,-3162,-3081,-2966,-2819,-2663,
+-2518,-2391,-2276,-2173,-2087,-2018,-1956,-1891,-1823,-1757,-1692,-1621,-1539,-1450,-1361,-1279,-1210,-1152,-1104,-1066,-1042,
+-1030,-1020,-991,-935,-864,-799,-747,-698,-641,-581,-531,-496,-467,-436,-403,-373,-347,-322,-302,-291,-289,
+-294,-299,-302,-298,-282,-251,-212,-169,-115,-43,37,101,129,126,119,135,182,245,308,359,397,
+422,440,453,464,474,484,490,491,490,495,511,535,558,581,616,673,750,833,919,1009,1106,
+1202,1285,1352,1414,1481,1560,1650,1753,1869,1994,2118,2227,2313,2377,2428,2475,2521,2566,2612,2664,2720,
+2774,2823,2877,2952,3046,3138,3210,3264,3311,3358,3388,3388,3365,3339,3323,3319,3323,3334,3356,3384,3415,
+3450,3498,3569,3660,3757,3845,3922,4002,4097,4204,4306,4392,4470,4554,4639,4708,4749,4770,4786,4800,4808,
+4811,4821,4851,4898,4950,4995,5019,5013,4982,4952,4945,4952,4945,4907,4862,4838,4830,4803,4739,4669,4632,
+4632,4627,4590,4540,4519,4550,4612,4666,4697,4711,4720,4728,4725,4707,4683,4665,4664,4678,4698,4719,4740,
+4768,4798,4823,4841,4857,4884,4926,4982,5038,5077,5086,5067,5040,5030,5048,5079,5096,5082,5046,5011,5000,
+5016,5049,5087,5123,5152,5173,5189,5215,5268,5347,5428,5490,5529,5563,5601,5630,5628,5598,5563,5545,5538,
+5517,5466,5393,5318,5258,5218,5193,5176,5168,5177,5205,5246,5289,5324,5351,5375,5392,5398,5393,5384,5376,
+5365,5346,5320,5292,5267,5243,5214,5180,5145,5112,5084,5060,5038,5015,4992,4977,4974,4986,5005,5026,5048,
+5072,5102,5141,5183,5211,5208,5183,5167,5182,5206,5198,5148,5093,5056,4961,4666,4090,3344,2694,2376,2428,
+2692,2962,3126,3195,3225,3243,3240,3211,3163,3112,3061,3002,2930,2851,2772,2695,2621,2548,2478,2415,2356,
+2297,2234,2170,2104,2035,1965,1896,1833,1778,1728,1678,1630,1589,1555,1524,1492,1458,1421,1378,1328,1280,
+1241,1211,1181,1151,1128,1122,1128,1127,1107,1072,1035,1004,976,947,913,875,833,791,752,717,682,
+648,619,596,574,541,499,459,434,420,402,370,325,281,248,227,215,205,193,178,158,132,
+96,52,8,-25,-50,-75,-108,-146,-177,-193,-203,-225,-266,-311,-335,-333,-328,-355,-420,-490,-515,
+-479,-418,-390,-425,-504,-580,-622,-634,-639,-656,-684,-712,-729,-740,-755,-780,-807,-828,-842,-855,-874,
+-893,-907,-915,-925,-938,-953,-966,-977,-990,-1005,-1018,-1028,-1039,-1052,-1068,-1085,-1101,-1118,-1133,-1146,-1153,
+-1155,-1157,-1164,-1176,-1187,-1194,-1194,-1193,-1198,-1205,-1209,-1207,-1205,-1209,-1219,-1228,-1228,-1223,-1219,-1221,-1227,
+-1227,-1218,-1201,-1185,-1174,-1167,-1159,-1147,-1135,-1127,-1120,-1110,-1096,-1083,-1078,-1077,-1078,-1076,-1071,-1063,-1052,
+-1041,-1032,-1029,-1027,-1021,-1011,-1000,-991,-983,-973,-961,-948,-934,-918,-901,-886,-873,-858,-840,-823,-809,
+-796,-780,-762,-745,-732,-720,-707,-690,-674,-660,-647,-632,-616,-599,-584,-571,-560,-547,-533,-520,-509,
+-500,-491,-482,-471,-459,-449,-441,-437,-437,-438,-438,-438,-437,-436,-431,-422,-415,-412,-411,-407,-400,
+-398,-404,-411,-411,-402,-395,-395,-399,-401,-398,-395,-394,-391,-386,-382,-381,-382,-380,-376,-373,-370,
+-366,-359,-350,-341,-332,-324,-319,-317,-315,-312,-307,-303,-299,-294,-290,-287,-283,-273,-260,-253,-254,
+-255,-248,-234,-221,-213,-206,-196,-185,-176,-170,-165,-160,-157,-154,-144,-130,-119,-115,-112,-99,-79,
+-60,-47,-42,-39,-36,-29,-15,2,16,21,24,30,37,43,49,59,71,76,74,73,83,
+100,115,125,136,150,162,170,180,194,210,223,234,244,252,259,273,298,323,335,339,356,
+394,430,437,422,419,447,490,519,534,560,609,658,676,662,649,668,718,768,792,792,789,
+801,829,864,900,934,963,988,1013,1048,1095,1147,1196,1244,1295,1347,1388,1417,1439,1468,1511,1571,
+1645,1719,1777,1812,1836,1863,1890,1910,1919,1917,1874,1738,1509,1299,1301,1630,2198,2753,3066,3105,3034,
+3043,3184,3369,3501,3590,3714,3910,4122,4266,4321,4332,4348,4369,4371,4332,4222,3997,3648,3244,2908,2719,
+2646,2599,2525,2444,2398,2391,2394,2386,2374,2369,2368,2356,2322,2266,2195,2120,2049,1988,1938,1897,1859,
+1819,1772,1717,1659,1599,1533,1455,1366,1271,1172,1072,974,882,796,708,612,510,409,316,240,183,
+139,98,55,10,-32,-78,-128,-168,-177,-150,-115,-107,-131,-163,-179,-182,-187,-201,-217,-234,-259,
+-298,-341,-365,-353,-305,-247,-213,-222,-259,-295,-310,-315,-335,-376,-423,-462,-489,-512,-539,-571,-609,
+-651,-686,-708,-719,-729,-743,-761,-792,-851,-942,-1040,-1114,-1154,-1172,-1181,-1173,-1137,-1077,-1019,-983,-971,
+-970,-965,-954,-940,-924,-907,-887,-868,-851,-837,-824,-811,-799,-786,-773,-758,-743,-732,-724,-715,-703,
+-690,-678,-668,-655,-641,-631,-628,-628,-624,-617,-610,-603,-596,-591,-589,-585,-577,-565,-554,-546,-535,
+-521,-507,-500,-494,-481,-458,-436,-419,-404,-381,-353,-326,-300,-273,-243,-215,-191,-166,-135,-101,-71,
+-44,-16,12,41,69,99,133,164,192,221,258,298,333,364,397,433,468,496,525,558,594,
+629,660,693,727,760,792,825,860,894,928,970,1023,1075,1114,1137,1152,1168,1181,1187,1187,1190,
+1199,1213,1230,1245,1255,1260,1264,1271,1278,1282,1281,1282,1287,1295,1301,1306,1315,1326,1338,1348,1359,
+1370,1377,1383,1394,1413,1434,1454,1474,1498,1525,1545,1558,1571,1587,1601,1607,1611,1623,1644,1666,1684,
+1705,1734,1767,1798,1826,1855,1895,1927,1958,1986,2014,2043,2069,2094,2121,2152,2182,2208,2235,2270,2311,
+2351,2391,2438,2495,2554,2605,2649,2690,2714,2707,2670,2622,2571,2505,2417,2334,2289,2285,2294,2291,2284,
+2290,2305,2310,2300,2291,2298,2313,2324,2338,2374,2430,2483,2520,2557,2620,2708,2792,2847,2875,2894,2920,
+2954,2991,3029,3066,3103,3142,3191,3251,3306,3327,3290,3207,3113,3037,2980,2922,2852,2785,2738,2711,2686,
+2655,2629,2623,2628,2623,2598,2566,2537,2506,2460,2404,2356,2329,2312,2292,2271,2256,2243,2219,2179,2135,
+2098,2062,2017,1965,1914,1864,1806,1740,1687,1669,1689,1736,1796,1858,1905,1915,1887,1843,1803,1752,1660,
+1519,1359,1224,1138,1107,1129,1188,1243,1245,1176,1069,971,906,863,833,819,828,851,872,883,880,
+853,787,688,592,533,511,491,447,390,352,350,369,380,367,335,296,261,237,228,229,225,
+207,180,158,147,141,135,130,115,76,18,-8,52,202,374,493,548,589,654,726,764,763,
+757,765,764,724,654,585,528,461,359,233,114,27,-32,-74,-106,-130,-154,-181,-203,-209,-198,
+-181,-169,-161,-150,-136,-124,-121,-120,-113,-99,-85,-76,-75,-76,-77,-76,-70,-55,-33,-13,-7,
+-16,-33,-51,-73,-99,-128,-151,-163,-167,-168,-168,-168,-170,-171,-169,-162,-154,-151,-151,-148,-139,
+-130,-131,-138,-146,-154,-167,-187,-208,-221,-224,-225,-232,-244,-257,-269,-283,-301,-322,-340,-355,-371,
+-395,-427,-460,-485,-504,-525,-553,-579,-596,-609,-632,-670,-714,-756,-798,-846,-898,-944,-982,-1023,-1075,
+-1135,-1191,-1235,-1268,-1300,-1336,-1383,-1440,-1504,-1565,-1621,-1670,-1717,-1762,-1806,-1855,-1913,-1977,-2041,-2101,-2157,
+-2208,-2251,-2291,-2334,-2382,-2431,-2472,-2511,-2556,-2610,-2664,-2710,-2748,-2785,-2821,-2855,-2885,-2916,-2949,-2983,-3015,
+-3047,-3084,-3124,-3165,-3208,-3252,-3298,-3342,-3381,-3416,-3448,-3476,-3499,-3515,-3526,-3531,-3530,-3522,-3508,-3498,-3509,
+-3557,-3635,-3716,-3775,-3807,-3833,-3872,-3930,-3996,-4059,-4112,-4144,-4153,-4152,-4161,-4192,-4230,-4258,-4270,-4279,-4294,
+-4309,-4316,-4315,-4315,-4321,-4334,-4351,-4368,-4384,-4397,-4406,-4416,-4427,-4438,-4443,-4443,-4444,-4449,-4457,-4462,-4459,
+-4449,-4434,-4417,-4399,-4378,-4354,-4325,-4296,-4270,-4244,-4215,-4180,-4144,-4114,-4091,-4071,-4045,-4015,-3983,-3955,-3931,
+-3911,-3891,-3865,-3826,-3776,-3728,-3696,-3684,-3686,-3696,-3709,-3712,-3681,-3603,-3496,-3394,-3322,-3275,-3237,-3206,-3192,
+-3204,-3236,-3274,-3306,-3322,-3313,-3274,-3212,-3134,-3040,-2923,-2785,-2638,-2498,-2371,-2257,-2160,-2090,-2044,-2005,-1954,
+-1889,-1820,-1756,-1692,-1617,-1527,-1433,-1349,-1284,-1238,-1202,-1168,-1140,-1121,-1105,-1077,-1027,-961,-892,-824,-752,
+-673,-597,-539,-500,-475,-458,-444,-432,-413,-388,-366,-356,-359,-367,-375,-382,-385,-372,-342,-305,-267,
+-219,-149,-61,14,49,44,28,36,76,135,197,250,291,319,336,347,355,363,369,366,355,
+340,334,345,370,406,450,508,577,647,708,763,827,904,988,1066,1138,1211,1290,1374,1466,1573,
+1700,1840,1977,2094,2184,2255,2318,2377,2428,2471,2513,2563,2620,2675,2723,2772,2838,2922,3008,3080,3136,
+3185,3226,3245,3238,3215,3195,3187,3190,3201,3222,3251,3282,3313,3348,3399,3471,3559,3653,3744,3829,3913,
+4002,4098,4195,4288,4378,4467,4550,4618,4669,4707,4738,4757,4762,4760,4768,4795,4838,4884,4925,4952,4955,
+4934,4906,4892,4892,4887,4866,4844,4836,4830,4785,4689,4574,4491,4456,4448,4442,4437,4446,4473,4509,4546,
+4582,4617,4647,4662,4662,4649,4629,4611,4604,4614,4637,4666,4694,4717,4738,4757,4778,4804,4838,4877,4922,
+4974,5026,5061,5060,5026,4989,4980,5004,5037,5046,5019,4973,4937,4931,4957,5007,5065,5114,5141,5149,5160,
+5199,5273,5358,5427,5470,5501,5533,5558,5560,5540,5517,5505,5500,5482,5442,5389,5345,5321,5315,5316,5315,
+5314,5318,5329,5344,5355,5360,5365,5373,5379,5378,5371,5362,5353,5337,5314,5288,5266,5244,5215,5181,5149,
+5124,5103,5080,5052,5023,4996,4973,4960,4962,4982,5008,5030,5045,5064,5096,5143,5187,5207,5194,5167,5157,
+5176,5194,5171,5106,5037,4971,4821,4455,3838,3129,2597,2421,2567,2844,3071,3190,3240,3271,3286,3271,3228,
+3177,3129,3077,3011,2932,2849,2772,2699,2623,2546,2472,2405,2343,2281,2218,2157,2098,2035,1964,1892,1826,
+1772,1721,1668,1615,1574,1547,1524,1496,1459,1418,1374,1327,1279,1235,1197,1162,1132,1113,1109,1113,1110,
+1091,1062,1031,1001,971,938,904,866,824,781,741,704,667,632,603,582,560,527,486,454,442,
+439,426,390,338,288,249,223,206,193,180,166,148,124,93,56,17,-19,-48,-73,-100,-131,
+-166,-199,-229,-259,-297,-338,-370,-380,-375,-378,-404,-439,-452,-425,-380,-356,-382,-452,-531,-586,-611,
+-621,-640,-674,-713,-740,-757,-772,-795,-821,-839,-846,-853,-867,-885,-902,-914,-926,-939,-952,-965,-979,
+-997,-1014,-1028,-1040,-1053,-1069,-1084,-1098,-1111,-1124,-1135,-1144,-1152,-1161,-1174,-1187,-1199,-1207,-1209,-1206,-1208,
+-1222,-1248,-1271,-1279,-1270,-1256,-1247,-1243,-1238,-1232,-1228,-1232,-1239,-1242,-1235,-1221,-1207,-1197,-1190,-1181,-1170,
+-1158,-1150,-1143,-1133,-1119,-1106,-1095,-1086,-1077,-1067,-1061,-1057,-1051,-1042,-1034,-1031,-1029,-1024,-1016,-1007,-999,
+-990,-978,-965,-951,-937,-920,-903,-888,-876,-862,-846,-829,-815,-802,-785,-767,-749,-735,-722,-707,-692,
+-678,-665,-653,-638,-623,-607,-593,-579,-568,-557,-545,-532,-520,-510,-501,-492,-481,-471,-464,-461,-460,
+-459,-458,-453,-449,-446,-444,-442,-436,-430,-426,-423,-418,-411,-409,-414,-421,-422,-416,-410,-410,-413,
+-414,-411,-406,-402,-398,-394,-391,-390,-390,-389,-385,-381,-376,-370,-361,-352,-341,-331,-322,-317,-314,
+-311,-307,-302,-297,-292,-286,-281,-278,-274,-263,-250,-241,-239,-237,-225,-208,-195,-189,-185,-175,-162,
+-151,-143,-137,-135,-137,-136,-125,-109,-96,-94,-95,-87,-69,-50,-35,-28,-25,-24,-20,-6,13,
+29,37,40,46,54,59,63,73,89,101,104,103,109,122,135,146,158,172,183,192,199,
+207,217,229,246,264,277,282,290,307,324,327,323,339,386,435,451,435,424,447,491,523,
+537,555,588,618,626,623,642,698,761,794,787,771,777,809,850,884,914,945,974,995,1017,
+1053,1104,1157,1202,1243,1291,1345,1389,1417,1437,1465,1510,1575,1655,1735,1795,1824,1836,1852,1875,1894,
+1899,1888,1841,1713,1499,1308,1332,1695,2305,2889,3202,3214,3106,3085,3216,3417,3587,3708,3827,3976,4129,
+4242,4298,4317,4328,4345,4356,4319,4166,3860,3453,3076,2847,2765,2733,2655,2530,2423,2381,2389,2403,2403,
+2396,2394,2391,2376,2342,2288,2220,2148,2081,2027,1981,1938,1891,1842,1789,1733,1674,1613,1546,1467,1372,
+1267,1160,1058,964,877,794,712,630,546,461,378,304,245,199,158,119,82,46,3,-51,-99,
+-112,-80,-30,0,0,-10,-13,-13,-25,-52,-79,-102,-132,-185,-255,-314,-331,-304,-261,-246,-274,
+-320,-345,-337,-324,-339,-388,-448,-499,-538,-575,-616,-659,-705,-752,-794,-823,-841,-856,-875,-899,-931,
+-976,-1033,-1090,-1128,-1148,-1158,-1162,-1150,-1112,-1054,-1002,-974,-966,-965,-959,-947,-933,-919,-906,-889,-872,
+-856,-842,-827,-809,-791,-775,-762,-749,-735,-720,-706,-691,-678,-666,-658,-650,-639,-628,-622,-623,-623,
+-618,-609,-602,-597,-590,-582,-575,-568,-557,-541,-528,-518,-508,-493,-477,-465,-454,-438,-414,-390,-371,
+-352,-326,-294,-263,-235,-207,-177,-149,-125,-100,-70,-39,-12,13,41,70,98,124,152,183,213,
+239,267,301,338,373,404,438,475,510,540,570,602,636,668,700,733,767,799,831,865,898,
+926,953,990,1042,1096,1132,1147,1158,1175,1195,1206,1207,1208,1217,1231,1246,1257,1266,1273,1278,1282,
+1286,1289,1291,1296,1303,1311,1317,1324,1333,1344,1354,1364,1373,1383,1390,1399,1413,1434,1453,1469,1487,
+1513,1541,1561,1571,1582,1597,1611,1620,1629,1646,1671,1694,1714,1739,1772,1809,1840,1867,1895,1935,1966,
+1993,2016,2039,2065,2092,2115,2140,2167,2194,2217,2241,2273,2313,2352,2388,2432,2490,2554,2610,2659,2705,
+2739,2742,2709,2654,2594,2529,2453,2375,2320,2299,2300,2307,2314,2325,2334,2331,2320,2314,2321,2329,2331,
+2337,2366,2419,2473,2512,2552,2617,2713,2815,2889,2928,2946,2964,2988,3018,3049,3079,3113,3155,3209,3270,
+3318,3332,3293,3212,3116,3035,2974,2919,2857,2797,2753,2726,2704,2679,2659,2656,2663,2658,2633,2600,2571,
+2539,2493,2435,2386,2355,2335,2315,2298,2293,2291,2275,2243,2207,2178,2144,2092,2028,1967,1915,1858,1792,
+1739,1726,1758,1819,1889,1953,1992,1987,1941,1883,1839,1795,1714,1586,1440,1316,1232,1187,1186,1230,1290,
+1312,1259,1150,1039,964,925,903,891,893,908,926,939,939,911,842,745,657,605,583,552,496,
+434,405,414,435,437,413,377,342,312,291,281,280,274,254,227,209,203,199,193,184,168,
+128,66,27,70,212,396,549,641,695,740,776,790,788,787,788,771,726,667,612,554,469,
+352,228,125,48,-5,-39,-54,-63,-83,-116,-146,-154,-143,-130,-121,-111,-91,-69,-58,-61,-69,
+-68,-59,-47,-41,-41,-43,-42,-35,-23,-6,9,20,23,19,9,-7,-31,-61,-89,-108,-115,
+-116,-116,-116,-113,-107,-100,-96,-98,-102,-105,-102,-94,-87,-86,-91,-97,-99,-103,-117,-138,-157,
+-166,-168,-174,-188,-203,-213,-219,-227,-241,-259,-275,-291,-311,-339,-370,-396,-413,-428,-453,-487,-519,
+-538,-550,-570,-602,-643,-683,-723,-768,-817,-864,-906,-949,-997,-1050,-1100,-1141,-1176,-1211,-1254,-1308,-1370,
+-1433,-1489,-1537,-1583,-1628,-1673,-1720,-1772,-1832,-1897,-1960,-2017,-2069,-2118,-2162,-2204,-2249,-2298,-2345,-2386,-2428,
+-2479,-2536,-2589,-2630,-2662,-2694,-2730,-2766,-2800,-2835,-2869,-2904,-2939,-2975,-3013,-3052,-3091,-3131,-3175,-3221,-3267,
+-3311,-3350,-3385,-3414,-3436,-3452,-3464,-3471,-3471,-3462,-3445,-3430,-3437,-3482,-3562,-3647,-3711,-3750,-3785,-3833,-3894,
+-3957,-4013,-4058,-4086,-4093,-4092,-4103,-4135,-4177,-4207,-4222,-4233,-4249,-4267,-4276,-4276,-4277,-4286,-4302,-4322,-4342,
+-4361,-4373,-4380,-4384,-4392,-4401,-4409,-4412,-4414,-4416,-4420,-4422,-4420,-4414,-4402,-4385,-4365,-4342,-4316,-4289,-4262,
+-4239,-4219,-4196,-4165,-4127,-4092,-4068,-4054,-4038,-4015,-3983,-3949,-3916,-3887,-3862,-3839,-3819,-3804,-3788,-3762,-3722,
+-3677,-3656,-3672,-3706,-3709,-3647,-3538,-3431,-3360,-3320,-3287,-3254,-3235,-3240,-3265,-3297,-3325,-3341,-3332,-3286,-3209,
+-3112,-3005,-2886,-2755,-2618,-2486,-2363,-2252,-2162,-2106,-2080,-2059,-2018,-1952,-1878,-1813,-1755,-1689,-1607,-1517,-1436,
+-1378,-1343,-1322,-1300,-1274,-1247,-1219,-1182,-1129,-1061,-985,-904,-816,-726,-644,-581,-539,-513,-501,-499,-496,
+-480,-451,-426,-418,-427,-441,-452,-461,-465,-452,-423,-386,-351,-307,-235,-142,-62,-29,-43,-70,-75,
+-46,7,68,127,177,215,242,264,287,309,326,329,317,300,290,295,315,349,397,461,534,
+601,653,697,747,812,884,956,1029,1105,1185,1264,1346,1443,1566,1708,1848,1968,2062,2139,2209,2274,
+2329,2372,2412,2459,2515,2572,2624,2676,2739,2815,2892,2960,3015,3061,3091,3098,3085,3069,3062,3067,3076,
+3092,3116,3148,3181,3214,3254,3313,3389,3474,3562,3651,3738,3821,3904,3991,4087,4187,4284,4372,4450,4521,
+4585,4643,4688,4713,4716,4712,4718,4742,4776,4813,4848,4877,4889,4879,4855,4838,4832,4828,4819,4816,4827,
+4832,4790,4680,4531,4399,4322,4306,4331,4374,4409,4425,4427,4435,4467,4514,4555,4577,4580,4575,4566,4557,
+4553,4559,4580,4612,4653,4696,4730,4749,4757,4767,4789,4821,4860,4908,4964,5013,5030,5006,4963,4934,4939,
+4963,4978,4966,4931,4892,4874,4888,4937,5003,5060,5091,5099,5106,5140,5206,5284,5352,5399,5434,5467,5491,
+5497,5483,5461,5447,5438,5426,5401,5367,5339,5327,5333,5345,5352,5352,5350,5354,5363,5369,5367,5363,5362,
+5363,5359,5350,5338,5324,5303,5275,5250,5231,5210,5180,5145,5117,5101,5086,5061,5028,4997,4973,4955,4944,
+4949,4974,5005,5024,5031,5045,5083,5141,5189,5202,5180,5152,5150,5170,5174,5129,5048,4969,4881,4685,4267,
+3642,3001,2591,2529,2723,2978,3156,3244,3290,3322,3328,3297,3244,3191,3142,3087,3016,2934,2852,2776,2703,
+2627,2548,2470,2397,2331,2269,2207,2147,2090,2032,1966,1893,1825,1767,1714,1659,1605,1565,1541,1523,1497,
+1459,1416,1374,1329,1281,1230,1183,1143,1115,1100,1097,1096,1086,1068,1045,1021,993,961,930,900,866,
+825,780,737,698,658,620,589,567,542,506,466,439,434,437,424,387,336,288,250,221,197,
+178,162,145,124,101,77,50,20,-13,-47,-77,-102,-129,-163,-205,-244,-275,-300,-327,-355,-377,
+-383,-380,-380,-388,-398,-398,-388,-383,-401,-449,-509,-559,-584,-589,-600,-632,-680,-722,-749,-768,-791,
+-819,-840,-849,-855,-865,-881,-896,-912,-929,-946,-961,-972,-985,-1002,-1021,-1037,-1053,-1071,-1090,-1106,-1116,
+-1125,-1133,-1141,-1146,-1151,-1160,-1174,-1190,-1203,-1214,-1220,-1222,-1224,-1233,-1252,-1271,-1280,-1275,-1265,-1260,-1259,
+-1258,-1254,-1250,-1250,-1252,-1251,-1245,-1234,-1223,-1213,-1205,-1195,-1184,-1173,-1166,-1161,-1154,-1144,-1131,-1117,-1102,
+-1085,-1071,-1064,-1061,-1057,-1049,-1041,-1035,-1031,-1026,-1018,-1012,-1006,-995,-980,-963,-950,-938,-923,-905,-889,
+-877,-866,-852,-837,-823,-809,-793,-775,-759,-743,-728,-711,-695,-683,-671,-658,-644,-631,-618,-605,-591,
+-578,-568,-558,-545,-530,-519,-511,-504,-495,-488,-485,-485,-485,-483,-478,-472,-466,-462,-460,-458,-455,
+-450,-444,-437,-429,-422,-421,-425,-430,-431,-425,-421,-422,-427,-429,-426,-421,-415,-409,-405,-401,-399,
+-397,-394,-391,-386,-380,-372,-362,-352,-342,-331,-321,-315,-310,-305,-298,-292,-288,-283,-277,-273,-270,
+-265,-252,-236,-226,-223,-219,-207,-190,-179,-176,-173,-165,-153,-141,-130,-123,-121,-123,-122,-113,-97,
+-86,-82,-79,-69,-53,-37,-23,-11,-2,0,-1,4,21,39,50,55,62,70,75,75,79,
+92,107,115,118,122,132,145,158,171,184,196,208,217,222,225,231,248,273,294,305,312,
+326,338,337,330,344,391,446,468,455,444,468,519,560,577,584,597,608,607,609,642,709,
+774,799,785,771,786,827,870,901,927,956,983,1003,1026,1064,1116,1162,1197,1230,1279,1337,1384,
+1412,1433,1466,1519,1588,1668,1747,1804,1828,1832,1841,1860,1874,1871,1852,1804,1685,1485,1308,1356,1760,
+2428,3066,3405,3408,3268,3210,3319,3525,3724,3868,3969,4050,4121,4186,4243,4288,4317,4336,4340,4281,4085,
+3732,3316,2994,2853,2834,2801,2681,2518,2404,2376,2399,2422,2431,2435,2436,2427,2402,2363,2312,2248,2178,
+2112,2059,2015,1969,1916,1862,1810,1758,1702,1638,1566,1481,1381,1269,1155,1050,960,880,803,727,654,
+582,509,433,361,300,250,206,166,135,111,83,41,-1,-18,3,49,89,115,137,159,165,
+141,90,37,-5,-47,-106,-188,-269,-316,-316,-295,-291,-321,-360,-369,-344,-318,-330,-386,-459,-526,
+-585,-643,-702,-759,-814,-868,-915,-947,-964,-977,-994,-1017,-1043,-1072,-1103,-1129,-1141,-1141,-1136,-1130,-1116,
+-1085,-1042,-1001,-975,-962,-954,-943,-930,-917,-906,-896,-883,-867,-852,-837,-821,-801,-783,-771,-764,-755,
+-739,-717,-694,-674,-657,-646,-638,-632,-624,-617,-615,-616,-613,-604,-593,-587,-584,-578,-568,-556,-545,
+-532,-514,-497,-485,-472,-456,-436,-420,-407,-390,-366,-339,-314,-289,-257,-222,-188,-159,-130,-100,-70,
+-45,-21,4,29,52,73,99,128,157,182,209,238,267,294,321,352,386,419,450,482,517,
+550,580,609,639,669,699,730,763,797,828,858,892,926,954,979,1013,1063,1114,1148,1163,1175,
+1195,1217,1227,1226,1225,1232,1245,1257,1266,1274,1282,1288,1291,1294,1299,1306,1313,1320,1327,1333,1341,
+1351,1360,1369,1377,1387,1398,1407,1418,1432,1451,1468,1482,1500,1525,1552,1572,1584,1598,1617,1638,1655,
+1671,1694,1721,1745,1767,1793,1827,1862,1888,1910,1935,1961,1989,2013,2031,2050,2076,2103,2127,2150,2175,
+2200,2224,2249,2282,2321,2356,2388,2428,2484,2546,2601,2649,2701,2751,2774,2751,2691,2617,2542,2467,2397,
+2347,2330,2335,2343,2347,2348,2349,2346,2341,2338,2340,2342,2338,2340,2364,2413,2469,2515,2558,2619,2709,
+2816,2910,2971,2999,3010,3022,3044,3071,3101,3134,3175,3227,3281,3322,3331,3297,3223,3132,3047,2981,2927,
+2872,2815,2768,2737,2717,2700,2688,2687,2689,2681,2658,2632,2608,2580,2533,2472,2418,2381,2357,2338,2328,
+2332,2337,2325,2295,2264,2241,2216,2173,2115,2057,2005,1949,1886,1840,1835,1871,1925,1979,2021,2037,2010,
+1951,1895,1870,1859,1814,1715,1587,1468,1374,1300,1260,1274,1329,1367,1332,1228,1108,1026,989,975,965,
+961,967,979,991,990,960,891,799,718,673,647,606,539,477,454,472,494,485,449,408,376,
+352,332,319,314,306,289,269,257,254,251,241,229,213,177,117,65,81,193,371,551,684,
+760,790,793,789,796,813,814,779,719,665,627,578,489,367,247,154,87,38,10,4,3,
+-14,-50,-82,-89,-78,-65,-58,-48,-28,-9,-4,-12,-23,-27,-24,-19,-14,-10,-6,0,10,
+22,32,39,44,50,54,52,37,12,-14,-38,-52,-59,-61,-61,-61,-56,-47,-39,-38,-43,
+-50,-49,-40,-31,-32,-41,-53,-57,-57,-63,-78,-98,-110,-113,-115,-126,-142,-155,-159,-159,-165,
+-179,-198,-217,-236,-258,-283,-308,-328,-344,-363,-390,-424,-455,-476,-490,-507,-534,-569,-609,-650,-694,
+-741,-787,-832,-875,-919,-964,-1009,-1051,-1092,-1133,-1180,-1236,-1297,-1356,-1408,-1453,-1497,-1544,-1591,-1640,-1694,
+-1754,-1816,-1875,-1931,-1984,-2034,-2080,-2124,-2167,-2213,-2259,-2306,-2357,-2415,-2471,-2515,-2545,-2570,-2600,-2638,-2679,
+-2719,-2756,-2793,-2829,-2867,-2906,-2945,-2981,-3017,-3055,-3096,-3141,-3188,-3234,-3279,-3319,-3349,-3371,-3388,-3402,-3411,
+-3411,-3401,-3379,-3356,-3357,-3399,-3480,-3573,-3646,-3695,-3736,-3788,-3847,-3905,-3955,-3996,-4025,-4036,-4039,-4050,-4081,
+-4122,-4156,-4176,-4192,-4211,-4228,-4237,-4239,-4244,-4256,-4274,-4292,-4311,-4328,-4341,-4346,-4348,-4353,-4362,-4372,-4378,
+-4381,-4381,-4381,-4379,-4377,-4372,-4363,-4346,-4325,-4302,-4279,-4255,-4231,-4209,-4191,-4173,-4147,-4111,-4073,-4045,-4030,
+-4022,-4009,-3984,-3951,-3913,-3873,-3833,-3799,-3785,-3798,-3820,-3818,-3768,-3688,-3633,-3640,-3692,-3725,-3691,-3599,-3500,
+-3433,-3392,-3356,-3317,-3290,-3285,-3297,-3317,-3337,-3352,-3345,-3300,-3218,-3112,-2996,-2872,-2739,-2606,-2480,-2364,-2258,
+-2176,-2130,-2117,-2108,-2075,-2011,-1935,-1868,-1811,-1752,-1680,-1599,-1525,-1475,-1451,-1444,-1438,-1421,-1393,-1356,-1312,
+-1256,-1186,-1104,-1014,-919,-824,-738,-669,-618,-585,-572,-572,-569,-550,-516,-487,-481,-496,-517,-536,-549,
+-552,-538,-507,-469,-431,-383,-307,-212,-134,-107,-129,-167,-186,-173,-132,-75,-10,54,110,157,200,
+244,288,321,335,330,315,304,304,318,344,384,439,503,565,615,659,708,766,829,894,962,
+1038,1115,1189,1263,1352,1465,1596,1727,1841,1936,2018,2093,2160,2216,2259,2298,2343,2398,2458,2517,2578,
+2648,2721,2790,2846,2891,2925,2943,2942,2932,2929,2940,2958,2974,2990,3012,3042,3074,3111,3162,3233,3318,
+3404,3487,3568,3648,3723,3796,3879,3977,4083,4183,4268,4343,4418,4494,4567,4623,4655,4664,4666,4674,4693,
+4717,4742,4771,4801,4821,4822,4808,4792,4783,4774,4762,4762,4781,4802,4784,4694,4542,4378,4261,4225,4265,
+4336,4383,4381,4347,4329,4352,4404,4452,4480,4491,4498,4504,4510,4514,4517,4522,4543,4594,4673,4747,4781,
+4769,4741,4735,4761,4804,4850,4898,4941,4964,4959,4933,4907,4897,4899,4901,4894,4875,4851,4832,4837,4876,
+4937,4992,5022,5032,5045,5081,5141,5210,5273,5323,5364,5399,5428,5443,5438,5418,5395,5381,5377,5373,5357,
+5331,5311,5310,5324,5336,5335,5327,5329,5343,5358,5362,5356,5347,5340,5330,5317,5302,5285,5262,5234,5211,
+5194,5177,5152,5120,5095,5078,5059,5028,4994,4968,4954,4942,4932,4936,4962,4994,5012,5013,5024,5067,5132,
+5181,5189,5163,5141,5147,5164,5150,5085,4995,4914,4811,4576,4122,3505,2935,2629,2644,2855,3081,3225,3299,
+3345,3372,3364,3321,3265,3212,3158,3093,3016,2933,2850,2771,2697,2625,2551,2471,2393,2323,2260,2197,2134,
+2074,2019,1960,1894,1825,1761,1705,1652,1601,1561,1535,1516,1490,1453,1410,1368,1326,1277,1223,1169,1125,
+1097,1084,1079,1073,1060,1043,1025,1004,977,945,916,892,864,826,781,737,697,656,614,580,554,
+527,489,448,419,410,407,391,357,315,277,245,217,190,167,146,125,100,75,54,34,13,
+-15,-50,-83,-111,-136,-169,-210,-250,-275,-284,-290,-309,-339,-368,-382,-383,-380,-386,-402,-422,-439,
+-455,-480,-514,-545,-557,-548,-544,-570,-625,-684,-725,-751,-775,-803,-828,-843,-853,-864,-877,-892,-909,
+-930,-954,-973,-985,-995,-1009,-1026,-1043,-1060,-1082,-1104,-1122,-1131,-1138,-1145,-1152,-1156,-1159,-1164,-1174,-1185,
+-1197,-1209,-1222,-1231,-1237,-1242,-1248,-1255,-1258,-1258,-1258,-1262,-1268,-1271,-1271,-1268,-1266,-1263,-1259,-1253,-1246,
+-1236,-1225,-1214,-1201,-1187,-1175,-1166,-1162,-1159,-1153,-1143,-1131,-1116,-1100,-1088,-1080,-1075,-1070,-1062,-1052,-1045,
+-1037,-1029,-1022,-1017,-1010,-996,-976,-957,-944,-936,-925,-909,-894,-882,-873,-862,-848,-833,-816,-800,-783,
+-769,-754,-738,-721,-706,-694,-681,-667,-652,-641,-631,-619,-604,-591,-581,-571,-557,-541,-528,-521,-517,
+-512,-508,-505,-504,-502,-498,-493,-491,-488,-485,-481,-477,-474,-468,-460,-449,-438,-432,-432,-438,-443,
+-442,-436,-431,-432,-437,-441,-439,-433,-427,-422,-418,-413,-408,-402,-397,-392,-388,-380,-370,-360,-351,
+-341,-330,-319,-310,-304,-297,-289,-282,-277,-273,-269,-266,-263,-255,-241,-225,-216,-215,-213,-203,-189,
+-179,-176,-172,-165,-155,-144,-134,-124,-118,-114,-111,-102,-92,-85,-80,-68,-51,-37,-28,-19,-3,
+14,21,18,18,31,48,58,62,69,81,91,90,87,90,100,109,113,119,130,145,160,
+172,182,194,210,227,239,242,242,250,271,294,309,321,336,353,360,361,374,413,459,478,
+468,462,489,541,582,598,603,617,634,641,643,662,706,757,785,788,790,811,845,878,904,
+931,962,990,1012,1038,1080,1129,1167,1190,1218,1267,1328,1376,1403,1429,1471,1534,1607,1683,1755,1807,
+1829,1830,1835,1849,1857,1847,1823,1777,1668,1480,1317,1382,1812,2515,3189,3555,3573,3434,3363,3450,3640,
+3836,3981,4061,4088,4096,4124,4190,4268,4318,4326,4292,4185,3953,3596,3219,2961,2873,2868,2816,2675,2513,
+2419,2410,2440,2464,2477,2487,2489,2469,2430,2383,2332,2272,2201,2132,2076,2030,1984,1931,1880,1834,1787,
+1731,1662,1583,1496,1396,1282,1164,1057,970,895,823,748,675,606,539,470,406,352,306,262,219,
+184,162,146,124,98,85,96,126,164,208,256,298,310,275,201,117,44,-15,-78,-154,-232,
+-288,-303,-291,-284,-302,-332,-343,-326,-308,-324,-382,-466,-556,-644,-729,-805,-871,-929,-984,-1029,-1056,
+-1066,-1070,-1079,-1093,-1110,-1128,-1147,-1161,-1162,-1147,-1124,-1103,-1086,-1066,-1039,-1008,-977,-953,-935,-921,-909,
+-896,-884,-871,-858,-843,-828,-813,-799,-785,-775,-771,-769,-760,-740,-711,-683,-660,-643,-631,-623,-617,
+-611,-607,-605,-604,-596,-582,-567,-559,-557,-553,-543,-531,-518,-503,-484,-466,-450,-435,-416,-395,-378,
+-365,-350,-325,-296,-267,-238,-205,-169,-134,-104,-73,-41,-11,13,36,60,83,103,123,147,176,
+205,231,257,286,315,341,367,395,426,457,487,517,548,579,608,638,667,696,724,755,789,
+822,851,879,911,947,978,1007,1042,1086,1130,1161,1178,1194,1216,1234,1240,1235,1235,1243,1256,1266,
+1273,1281,1290,1297,1300,1305,1313,1322,1330,1335,1339,1345,1354,1364,1373,1380,1389,1402,1415,1426,1435,
+1446,1463,1482,1499,1517,1542,1567,1587,1603,1622,1648,1676,1700,1722,1747,1775,1799,1820,1845,1876,1903,
+1922,1938,1961,1973,1998,2020,2035,2054,2081,2111,2138,2161,2186,2212,2236,2262,2295,2331,2363,2390,2426,
+2476,2534,2586,2638,2700,2767,2807,2794,2729,2642,2555,2475,2405,2359,2348,2360,2372,2372,2366,2365,2368,
+2369,2365,2358,2353,2351,2355,2374,2415,2471,2528,2578,2629,2699,2794,2898,2980,3022,3033,3039,3060,3094,
+3130,3164,3201,3248,3298,3336,3345,3314,3244,3152,3060,2988,2934,2885,2834,2785,2749,2730,2721,2719,2719,
+2717,2705,2686,2668,2651,2626,2578,2515,2456,2415,2391,2378,2375,2384,2389,2376,2344,2315,2301,2291,2267,
+2224,2173,2120,2060,2002,1969,1975,2007,2038,2056,2062,2049,2005,1940,1895,1905,1947,1957,1897,1782,1653,
+1530,1415,1333,1319,1370,1425,1411,1315,1192,1102,1062,1049,1038,1028,1027,1034,1041,1033,998,931,848,
+778,740,715,669,595,527,503,521,538,523,480,435,403,381,360,342,332,325,313,299,291,
+290,286,275,264,252,227,177,122,109,177,326,512,679,783,813,798,786,809,848,855,807,
+735,681,652,607,513,388,274,195,141,97,70,63,63,48,17,-8,-13,-3,5,9,17,
+28,36,34,26,19,14,10,8,11,21,33,45,58,67,69,67,68,76,86,87,73,
+52,32,17,5,-4,-10,-11,-9,-4,1,5,5,3,3,9,19,22,13,-1,-11,-13,
+-13,-21,-37,-53,-60,-61,-64,-75,-88,-93,-92,-93,-102,-118,-138,-159,-181,-203,-224,-244,-266,
+-293,-321,-347,-370,-391,-411,-429,-447,-469,-498,-536,-580,-625,-670,-716,-762,-805,-845,-883,-923,-967,
+-1014,-1061,-1111,-1165,-1221,-1275,-1323,-1367,-1412,-1459,-1509,-1562,-1618,-1676,-1733,-1788,-1844,-1900,-1953,-2001,-2043,
+-2086,-2131,-2179,-2233,-2293,-2353,-2403,-2435,-2455,-2477,-2510,-2553,-2599,-2642,-2682,-2721,-2761,-2800,-2838,-2874,-2908,
+-2942,-2978,-3018,-3060,-3105,-3155,-3206,-3250,-3283,-3304,-3320,-3336,-3347,-3347,-3332,-3303,-3274,-3270,-3311,-3395,-3494,
+-3578,-3637,-3684,-3735,-3789,-3843,-3892,-3936,-3970,-3988,-3994,-4004,-4032,-4071,-4106,-4131,-4152,-4173,-4190,-4201,-4209,
+-4220,-4236,-4251,-4265,-4278,-4293,-4306,-4313,-4316,-4321,-4330,-4339,-4346,-4349,-4349,-4347,-4343,-4338,-4330,-4319,-4303,
+-4286,-4269,-4251,-4231,-4206,-4180,-4160,-4143,-4123,-4093,-4057,-4026,-4009,-4000,-3989,-3969,-3940,-3908,-3872,-3827,-3780,
+-3751,-3761,-3799,-3823,-3796,-3725,-3662,-3656,-3701,-3740,-3727,-3664,-3590,-3533,-3489,-3441,-3391,-3356,-3341,-3340,-3345,
+-3354,-3361,-3351,-3304,-3223,-3119,-3003,-2876,-2741,-2606,-2482,-2372,-2274,-2199,-2160,-2153,-2151,-2124,-2065,-1991,-1921,
+-1859,-1798,-1731,-1659,-1594,-1549,-1533,-1538,-1548,-1545,-1524,-1492,-1452,-1401,-1335,-1254,-1162,-1066,-970,-880,-801,
+-736,-692,-669,-660,-649,-623,-586,-556,-550,-565,-589,-613,-631,-638,-625,-593,-553,-510,-456,-379,-289,
+-217,-191,-208,-242,-265,-267,-246,-199,-132,-54,18,81,137,194,251,298,327,333,324,314,313,
+325,347,379,420,467,515,560,605,654,707,761,817,881,955,1037,1119,1201,1291,1393,1502,1608,
+1705,1793,1877,1956,2027,2085,2129,2167,2210,2263,2324,2390,2459,2535,2610,2672,2715,2744,2765,2778,2782,
+2785,2799,2827,2857,2879,2894,2912,2937,2968,3011,3073,3155,3246,3330,3408,3481,3553,3620,3689,3770,3871,
+3979,4077,4159,4234,4313,4396,4474,4536,4577,4601,4614,4627,4640,4655,4672,4696,4725,4749,4760,4757,4750,
+4743,4731,4712,4699,4709,4736,4747,4699,4576,4409,4264,4203,4235,4310,4351,4323,4260,4221,4239,4294,4349,
+4387,4414,4435,4453,4468,4476,4472,4456,4458,4517,4639,4767,4825,4793,4721,4682,4702,4753,4803,4838,4866,
+4887,4898,4898,4890,4877,4859,4843,4832,4824,4810,4793,4789,4816,4870,4924,4956,4970,4985,5019,5073,5138,
+5203,5259,5302,5335,5364,5390,5402,5390,5362,5341,5343,5356,5354,5325,5288,5275,5293,5317,5323,5313,5306,
+5316,5331,5336,5325,5310,5296,5284,5271,5258,5244,5225,5202,5179,5163,5148,5127,5101,5076,5056,5031,4998,
+4967,4949,4942,4935,4925,4927,4952,4984,4999,4997,5007,5050,5115,5162,5166,5143,5129,5140,5153,5128,5056,
+4970,4892,4771,4498,4015,3411,2903,2673,2736,2948,3150,3276,3346,3391,3408,3388,3345,3296,3246,3183,3103,
+3017,2932,2847,2761,2683,2616,2549,2471,2388,2313,2249,2185,2117,2051,1996,1948,1893,1826,1758,1698,1645,
+1597,1557,1528,1506,1479,1441,1397,1353,1311,1265,1212,1157,1110,1078,1062,1054,1046,1033,1018,1004,985,
+957,924,895,873,848,814,773,735,698,657,613,573,545,518,482,439,403,381,366,346,318,
+289,262,238,212,187,164,143,119,91,63,40,22,5,-18,-50,-85,-116,-143,-172,-208,-243,
+-264,-266,-262,-271,-304,-351,-390,-403,-394,-385,-395,-427,-465,-494,-511,-527,-541,-541,-522,-505,-523,
+-579,-648,-701,-732,-755,-781,-806,-824,-838,-854,-872,-889,-906,-928,-955,-977,-992,-1002,-1015,-1030,-1045,
+-1062,-1083,-1107,-1126,-1137,-1143,-1150,-1158,-1164,-1168,-1174,-1182,-1190,-1198,-1207,-1218,-1230,-1241,-1249,-1255,-1258,
+-1259,-1259,-1260,-1263,-1266,-1269,-1272,-1274,-1274,-1271,-1268,-1265,-1261,-1253,-1241,-1226,-1210,-1193,-1175,-1160,-1151,
+-1147,-1143,-1136,-1128,-1120,-1112,-1104,-1096,-1088,-1081,-1072,-1064,-1056,-1048,-1039,-1032,-1027,-1019,-1003,-981,-959,
+-947,-940,-932,-918,-904,-893,-885,-876,-861,-843,-823,-805,-789,-776,-764,-751,-736,-723,-710,-697,-681,
+-665,-654,-645,-634,-620,-606,-596,-585,-570,-553,-540,-534,-532,-528,-524,-521,-516,-511,-505,-504,-506,
+-508,-505,-498,-492,-488,-482,-472,-459,-447,-442,-444,-451,-456,-455,-449,-444,-444,-448,-449,-446,-441,
+-435,-431,-427,-422,-414,-405,-397,-391,-384,-375,-364,-354,-347,-339,-328,-315,-304,-297,-291,-285,-278,
+-271,-266,-263,-261,-258,-248,-233,-220,-215,-216,-213,-203,-190,-180,-173,-164,-154,-146,-141,-135,-125,
+-114,-104,-95,-87,-83,-82,-78,-63,-43,-32,-33,-32,-16,7,21,22,23,35,51,58,58,
+65,84,104,110,106,102,105,111,116,122,134,151,166,175,180,187,204,229,253,264,261,
+259,266,280,293,303,319,342,364,381,398,425,452,463,457,456,479,515,541,551,567,609,
+666,705,712,706,713,742,777,802,819,834,851,869,892,924,960,991,1016,1048,1093,1139,1170,
+1186,1211,1260,1321,1369,1401,1437,1492,1562,1633,1700,1762,1810,1831,1833,1838,1853,1862,1851,1823,1772,
+1661,1480,1329,1405,1835,2526,3188,3566,3625,3541,3507,3590,3745,3900,4017,4083,4098,4093,4117,4191,4279,
+4323,4294,4201,4040,3792,3467,3149,2939,2863,2843,2782,2661,2542,2484,2485,2505,2516,2524,2530,2524,2492,
+2442,2388,2337,2280,2212,2145,2089,2042,1994,1943,1896,1855,1812,1753,1678,1596,1510,1415,1304,1187,1081,
+997,925,851,769,686,611,545,484,433,393,361,324,279,235,204,189,183,180,181,189,204,
+232,275,329,376,390,357,281,185,87,3,-67,-132,-193,-237,-251,-236,-220,-229,-262,-297,-313,
+-321,-346,-405,-496,-607,-724,-831,-918,-983,-1036,-1083,-1118,-1133,-1129,-1122,-1121,-1126,-1135,-1149,-1169,-1187,
+-1188,-1165,-1127,-1092,-1070,-1057,-1041,-1014,-978,-944,-920,-906,-894,-880,-863,-846,-829,-811,-793,-777,-764,
+-756,-751,-752,-750,-739,-716,-688,-663,-644,-628,-616,-607,-602,-597,-593,-590,-587,-578,-561,-542,-529,
+-523,-518,-510,-500,-488,-474,-455,-436,-419,-403,-383,-362,-345,-332,-316,-291,-260,-230,-202,-172,-138,
+-105,-72,-40,-8,20,44,67,92,117,140,161,186,215,244,270,295,322,350,375,400,426,
+454,484,512,541,571,601,631,662,693,723,752,782,816,848,877,903,933,967,1002,1036,1070,
+1107,1142,1168,1187,1206,1226,1239,1241,1239,1244,1257,1270,1279,1285,1293,1302,1309,1313,1319,1327,1336,
+1342,1346,1349,1355,1363,1373,1382,1392,1404,1419,1435,1447,1455,1466,1484,1506,1527,1548,1570,1593,1613,
+1632,1654,1682,1711,1736,1759,1783,1809,1833,1854,1878,1904,1925,1939,1953,1973,1984,2006,2025,2041,2063,
+2093,2126,2156,2182,2207,2230,2251,2272,2302,2335,2366,2392,2424,2470,2523,2575,2633,2707,2786,2832,2814,
+2740,2646,2560,2485,2419,2373,2361,2377,2395,2397,2391,2391,2398,2401,2391,2376,2369,2372,2380,2394,2424,
+2477,2542,2600,2643,2690,2765,2867,2963,3021,3038,3045,3072,3117,3161,3195,3228,3273,3327,3371,3382,3350,
+3276,3173,3068,2984,2929,2890,2848,2802,2764,2745,2745,2754,2760,2755,2739,2719,2702,2687,2661,2614,2554,
+2500,2465,2447,2440,2441,2448,2449,2430,2399,2375,2372,2378,2372,2343,2296,2238,2175,2125,2109,2126,2149,
+2151,2133,2111,2085,2038,1976,1944,1982,2068,2126,2096,1982,1828,1664,1511,1400,1372,1429,1501,1506,1418,
+1290,1189,1138,1116,1100,1087,1084,1089,1089,1071,1028,963,890,834,806,787,743,668,591,553,556,
+567,551,510,466,432,405,379,356,342,334,324,315,311,314,314,308,300,293,278,245,198,
+169,197,304,473,652,778,819,803,793,828,886,903,856,779,721,685,626,520,392,289,229,
+191,155,126,114,111,99,76,58,53,57,60,63,68,73,73,67,62,62,58,49,42,
+45,59,76,92,104,111,110,104,102,110,118,117,104,88,76,66,53,38,29,30,37,
+42,44,45,46,49,52,55,54,48,37,27,24,28,30,24,13,2,-3,-7,-14,-22,
+-28,-29,-30,-36,-50,-66,-82,-102,-125,-148,-166,-185,-212,-247,-279,-298,-306,-318,-340,-366,-388,
+-407,-431,-466,-510,-556,-600,-645,-691,-734,-771,-806,-845,-891,-941,-992,-1042,-1093,-1144,-1193,-1238,-1281,
+-1324,-1371,-1424,-1482,-1541,-1599,-1652,-1704,-1760,-1817,-1871,-1917,-1960,-2005,-2054,-2108,-2166,-2226,-2280,-2320,-2344,
+-2363,-2390,-2430,-2477,-2524,-2568,-2610,-2652,-2694,-2732,-2768,-2799,-2830,-2864,-2901,-2940,-2980,-3024,-3077,-3133,-3182,
+-3214,-3232,-3247,-3265,-3277,-3276,-3254,-3219,-3187,-3184,-3227,-3313,-3417,-3509,-3578,-3631,-3679,-3728,-3777,-3829,-3879,
+-3920,-3941,-3948,-3958,-3983,-4020,-4054,-4079,-4101,-4123,-4143,-4160,-4175,-4192,-4210,-4223,-4234,-4246,-4262,-4277,-4288,
+-4293,-4299,-4306,-4314,-4320,-4323,-4324,-4322,-4316,-4306,-4294,-4281,-4268,-4256,-4243,-4226,-4201,-4168,-4135,-4111,-4098,
+-4087,-4069,-4042,-4014,-3994,-3980,-3965,-3940,-3913,-3890,-3870,-3839,-3790,-3740,-3721,-3744,-3783,-3793,-3763,-3721,-3707,
+-3726,-3747,-3742,-3711,-3674,-3639,-3594,-3535,-3475,-3432,-3410,-3398,-3390,-3385,-3380,-3356,-3299,-3214,-3114,-3008,-2888,
+-2754,-2617,-2493,-2386,-2298,-2233,-2199,-2192,-2189,-2165,-2113,-2043,-1970,-1898,-1828,-1761,-1695,-1637,-1596,-1582,-1595,
+-1617,-1628,-1619,-1597,-1567,-1526,-1468,-1392,-1306,-1217,-1129,-1040,-954,-879,-822,-785,-759,-733,-700,-665,-640,
+-632,-640,-658,-679,-699,-709,-700,-671,-631,-586,-530,-461,-386,-326,-294,-286,-289,-295,-299,-290,-256,
+-193,-114,-39,21,72,125,185,244,291,315,317,310,305,312,327,349,374,403,436,473,517,
+567,617,666,717,780,859,952,1051,1150,1247,1338,1420,1494,1564,1639,1720,1803,1880,1944,1992,2031,
+2072,2123,2182,2246,2315,2391,2465,2524,2560,2580,2596,2616,2636,2658,2687,2723,2759,2787,2805,2821,2842,
+2875,2926,2997,3081,3163,3236,3303,3373,3445,3519,3595,3683,3783,3884,3975,4054,4133,4215,4296,4369,4431,
+4482,4520,4545,4560,4569,4579,4595,4617,4646,4672,4689,4697,4700,4701,4694,4676,4654,4644,4658,4681,4672,
+4593,4445,4289,4202,4216,4281,4312,4267,4185,4134,4146,4197,4254,4302,4344,4376,4397,4411,4419,4411,4386,
+4380,4449,4604,4771,4846,4797,4690,4626,4641,4700,4754,4786,4806,4827,4847,4860,4864,4854,4831,4805,4792,
+4789,4779,4758,4742,4757,4805,4862,4902,4920,4934,4959,5004,5068,5141,5205,5247,5272,5296,5329,5358,5358,
+5331,5304,5305,5327,5334,5304,5258,5237,5258,5296,5316,5310,5295,5292,5296,5294,5280,5264,5252,5242,5231,
+5220,5209,5196,5176,5153,5134,5116,5096,5074,5051,5031,5007,4979,4953,4939,4932,4923,4915,4921,4946,4972,
+4981,4976,4985,5029,5091,5134,5137,5118,5110,5122,5131,5104,5041,4968,4888,4740,4429,3927,3348,2899,2728,
+2817,3020,3200,3311,3378,3419,3428,3403,3365,3327,3281,3209,3118,3026,2940,2852,2759,2675,2608,2546,2470,
+2383,2303,2238,2177,2106,2036,1982,1941,1896,1832,1761,1695,1641,1594,1553,1521,1497,1469,1429,1380,1332,
+1289,1247,1201,1149,1100,1063,1041,1028,1016,1003,991,981,965,939,904,873,847,822,790,756,725,
+696,658,612,568,536,510,478,436,393,358,332,310,287,267,247,227,206,186,167,147,123,
+95,67,42,21,4,-14,-41,-74,-109,-140,-167,-195,-221,-242,-249,-250,-258,-288,-338,-388,-409,
+-392,-361,-353,-387,-445,-493,-516,-525,-532,-532,-518,-502,-512,-559,-624,-678,-711,-733,-757,-780,-798,
+-815,-837,-863,-885,-904,-924,-947,-969,-986,-1001,-1016,-1033,-1049,-1064,-1084,-1108,-1127,-1137,-1142,-1147,-1155,
+-1164,-1173,-1183,-1195,-1205,-1212,-1215,-1219,-1226,-1237,-1250,-1263,-1271,-1273,-1271,-1267,-1263,-1260,-1260,-1265,-1273,
+-1276,-1276,-1275,-1275,-1275,-1269,-1258,-1245,-1229,-1210,-1186,-1164,-1148,-1137,-1128,-1120,-1115,-1114,-1113,-1108,-1099,
+-1090,-1082,-1077,-1071,-1065,-1058,-1051,-1045,-1040,-1033,-1018,-998,-977,-964,-956,-946,-932,-918,-908,-899,-888,
+-873,-853,-832,-813,-796,-784,-773,-762,-749,-737,-725,-713,-698,-683,-671,-661,-650,-636,-623,-611,-599,
+-585,-569,-556,-550,-546,-542,-539,-535,-529,-521,-515,-515,-519,-521,-518,-510,-503,-499,-493,-484,-472,
+-461,-455,-456,-461,-465,-465,-462,-459,-459,-460,-458,-452,-445,-439,-435,-430,-424,-415,-404,-395,-387,
+-378,-368,-357,-348,-343,-338,-328,-314,-301,-295,-294,-292,-285,-274,-266,-262,-261,-256,-246,-232,-224,
+-221,-217,-207,-192,-179,-169,-158,-143,-128,-121,-121,-121,-115,-105,-93,-81,-71,-67,-71,-72,-62,
+-46,-38,-42,-45,-32,-9,5,9,15,31,50,55,52,57,79,106,122,125,126,131,138,
+143,148,157,169,182,189,192,194,204,227,254,273,275,268,266,274,282,287,294,313,344,
+377,402,421,433,437,437,444,459,475,479,482,512,587,685,758,774,751,732,746,786,824,
+842,843,840,848,873,910,950,986,1017,1055,1102,1146,1173,1187,1209,1254,1312,1366,1411,1462,1527,
+1596,1656,1709,1759,1798,1818,1824,1837,1864,1886,1884,1851,1780,1647,1459,1322,1412,1831,2477,3091,3460,
+3575,3584,3626,3728,3842,3934,4010,4074,4118,4146,4186,4250,4306,4304,4223,4082,3896,3663,3388,3122,2930,
+2834,2788,2736,2665,2602,2572,2567,2565,2558,2553,2548,2529,2487,2432,2377,2325,2270,2211,2154,2105,2058,
+2007,1954,1908,1869,1827,1768,1693,1611,1528,1436,1330,1218,1117,1036,964,883,789,692,608,540,486,
+444,417,397,371,330,280,240,221,226,245,266,280,288,301,328,366,398,411,394,346,264,
+157,47,-42,-103,-142,-166,-175,-165,-156,-172,-222,-285,-336,-370,-406,-468,-566,-692,-823,-936,-1018,
+-1072,-1111,-1142,-1161,-1161,-1147,-1133,-1127,-1129,-1136,-1152,-1177,-1200,-1202,-1175,-1130,-1090,-1069,-1062,-1052,-1026,
+-988,-949,-923,-908,-895,-878,-859,-840,-820,-797,-771,-749,-732,-722,-717,-715,-709,-697,-677,-655,-637,
+-621,-606,-592,-582,-578,-574,-569,-565,-563,-557,-543,-523,-505,-493,-485,-478,-469,-459,-445,-427,-408,
+-391,-373,-353,-330,-311,-296,-277,-250,-219,-189,-162,-134,-102,-71,-40,-9,20,47,70,93,118,
+146,172,197,223,251,279,303,326,351,377,402,427,454,482,510,538,567,597,627,657,687,
+720,751,781,810,842,875,905,933,960,991,1025,1060,1094,1126,1154,1177,1198,1217,1233,1241,1242,
+1245,1257,1272,1284,1291,1298,1307,1316,1324,1330,1336,1343,1349,1353,1357,1362,1367,1373,1382,1394,1407,
+1421,1438,1455,1469,1481,1496,1517,1541,1563,1583,1604,1625,1645,1664,1684,1708,1734,1756,1775,1797,1820,
+1843,1864,1885,1909,1930,1947,1964,1984,1995,2016,2034,2054,2079,2111,2144,2175,2203,2227,2245,2259,2275,
+2302,2338,2372,2401,2433,2474,2521,2572,2635,2717,2799,2838,2802,2709,2608,2534,2484,2440,2402,2389,2402,
+2422,2429,2423,2420,2425,2425,2413,2396,2390,2398,2409,2418,2439,2486,2553,2614,2652,2685,2745,2843,2947,
+3015,3039,3052,3087,3143,3195,3228,3257,3303,3364,3417,3432,3397,3313,3196,3074,2977,2918,2885,2853,2813,
+2775,2758,2767,2789,2804,2800,2779,2753,2731,2710,2682,2637,2586,2545,2523,2515,2512,2511,2510,2502,2482,
+2456,2443,2452,2469,2473,2452,2408,2350,2291,2253,2252,2275,2288,2269,2231,2203,2185,2153,2104,2081,2130,
+2230,2302,2275,2147,1964,1771,1597,1477,1451,1514,1598,1614,1531,1397,1280,1210,1173,1149,1136,1137,1142,
+1134,1105,1055,991,927,883,865,856,824,754,670,609,588,584,571,539,501,466,431,396,368,
+350,341,333,327,329,338,348,350,345,337,326,306,275,248,254,322,457,622,753,808,804,
+804,848,913,938,898,823,759,706,627,509,386,299,257,232,203,175,159,152,141,123,107,
+99,96,95,98,104,109,107,102,100,101,96,84,78,86,104,122,135,144,150,151,148,
+146,151,155,151,139,128,120,111,94,76,68,73,82,86,85,84,88,93,93,84,71,
+59,52,52,56,61,66,69,67,62,54,45,37,31,27,23,15,2,-10,-21,-32,-50,
+-76,-100,-117,-130,-150,-176,-199,-209,-213,-227,-260,-297,-324,-343,-364,-398,-441,-485,-527,-571,-616,
+-658,-694,-729,-770,-819,-870,-921,-970,-1019,-1067,-1112,-1155,-1196,-1240,-1287,-1343,-1406,-1470,-1528,-1578,-1627,
+-1680,-1736,-1787,-1832,-1877,-1927,-1984,-2043,-2101,-2154,-2197,-2228,-2250,-2276,-2312,-2359,-2407,-2452,-2495,-2538,-2582,
+-2622,-2659,-2691,-2720,-2751,-2785,-2824,-2863,-2903,-2950,-3006,-3065,-3113,-3141,-3157,-3174,-3194,-3207,-3201,-3173,-3135,
+-3108,-3112,-3159,-3245,-3348,-3444,-3521,-3580,-3627,-3670,-3715,-3767,-3822,-3866,-3889,-3897,-3907,-3933,-3969,-4000,-4024,
+-4043,-4066,-4089,-4111,-4131,-4150,-4168,-4182,-4195,-4212,-4233,-4252,-4266,-4274,-4279,-4285,-4291,-4296,-4298,-4299,-4295,
+-4287,-4274,-4260,-4248,-4239,-4230,-4214,-4185,-4141,-4094,-4055,-4037,-4036,-4042,-4041,-4026,-4004,-3984,-3968,-3949,-3920,
+-3889,-3867,-3858,-3846,-3809,-3754,-3709,-3703,-3731,-3761,-3769,-3756,-3743,-3738,-3736,-3731,-3728,-3728,-3718,-3684,-3625,
+-3565,-3520,-3491,-3467,-3444,-3427,-3408,-3369,-3299,-3206,-3110,-3014,-2905,-2776,-2639,-2512,-2407,-2327,-2272,-2242,-2230,
+-2220,-2196,-2151,-2090,-2014,-1932,-1854,-1785,-1726,-1673,-1631,-1614,-1625,-1652,-1670,-1669,-1653,-1629,-1593,-1538,-1466,
+-1390,-1316,-1242,-1162,-1082,-1009,-952,-906,-864,-823,-785,-756,-741,-736,-737,-743,-753,-764,-769,-759,-734,
+-697,-653,-603,-549,-498,-454,-415,-374,-333,-301,-283,-268,-235,-177,-108,-48,-7,24,66,127,200,
+267,309,319,308,291,278,272,273,279,294,318,353,399,451,506,559,616,687,777,881,993,
+1101,1198,1278,1338,1387,1437,1499,1574,1658,1740,1811,1864,1906,1947,1996,2052,2110,2170,2238,2309,2368,
+2405,2426,2448,2482,2522,2561,2594,2628,2661,2691,2714,2734,2759,2800,2861,2936,3012,3077,3130,3184,3251,
+3333,3424,3518,3615,3711,3799,3880,3959,4043,4127,4201,4263,4318,4371,4416,4445,4459,4466,4478,4500,4530,
+4563,4594,4619,4635,4643,4648,4650,4645,4625,4601,4591,4606,4619,4578,4455,4292,4178,4168,4224,4257,4217,
+4136,4083,4087,4126,4172,4218,4264,4300,4319,4328,4337,4337,4322,4322,4396,4558,4730,4803,4744,4629,4562,
+4579,4640,4695,4729,4756,4783,4804,4816,4819,4811,4791,4769,4759,4761,4755,4731,4705,4706,4744,4799,4845,
+4869,4883,4903,4944,5009,5086,5152,5189,5203,5221,5258,5298,5310,5287,5256,5253,5275,5289,5268,5224,5200,
+5218,5260,5291,5293,5280,5269,5265,5259,5248,5236,5227,5218,5205,5191,5177,5164,5147,5125,5103,5083,5062,
+5040,5020,5001,4982,4962,4942,4926,4912,4901,4898,4912,4938,4957,4955,4945,4957,5005,5065,5103,5106,5091,
+5085,5094,5098,5075,5023,4956,4861,4677,4334,3833,3301,2923,2811,2919,3104,3252,3339,3395,3433,3440,3415,
+3377,3342,3296,3222,3128,3037,2954,2867,2769,2678,2607,2545,2471,2383,2302,2238,2178,2110,2041,1987,1946,
+1902,1839,1766,1698,1641,1591,1549,1517,1491,1462,1418,1364,1312,1269,1232,1191,1144,1096,1057,1029,1009,
+990,972,959,951,942,920,888,853,824,796,766,736,711,687,654,609,562,525,497,467,429,
+385,345,312,287,266,247,227,208,191,176,162,144,122,96,70,45,23,5,-9,-28,-57,
+-93,-130,-157,-176,-190,-205,-221,-237,-255,-283,-326,-372,-395,-378,-337,-316,-348,-414,-472,-493,-492,
+-495,-509,-519,-519,-526,-558,-607,-653,-684,-708,-733,-759,-778,-795,-818,-848,-876,-897,-916,-936,-957,
+-977,-995,-1015,-1035,-1053,-1069,-1088,-1110,-1129,-1139,-1142,-1145,-1153,-1165,-1177,-1190,-1204,-1218,-1227,-1231,-1230,
+-1231,-1237,-1249,-1263,-1273,-1275,-1272,-1266,-1260,-1257,-1258,-1265,-1274,-1278,-1278,-1277,-1278,-1280,-1278,-1272,-1264,
+-1252,-1234,-1210,-1185,-1166,-1149,-1133,-1118,-1111,-1111,-1111,-1105,-1094,-1084,-1080,-1077,-1074,-1069,-1064,-1059,-1054,
+-1050,-1043,-1031,-1016,-1000,-986,-975,-961,-946,-932,-920,-910,-897,-882,-864,-845,-825,-808,-794,-783,-771,
+-758,-745,-734,-725,-714,-701,-688,-676,-665,-653,-641,-628,-614,-600,-585,-573,-564,-557,-553,-552,-551,
+-546,-538,-531,-530,-532,-531,-526,-518,-513,-510,-505,-497,-486,-477,-471,-468,-467,-468,-470,-470,-471,
+-472,-471,-467,-459,-452,-446,-440,-434,-425,-415,-403,-393,-384,-376,-367,-357,-350,-346,-341,-332,-318,
+-305,-300,-303,-304,-297,-284,-273,-268,-265,-258,-245,-234,-229,-225,-214,-192,-171,-160,-157,-149,-131,
+-111,-102,-105,-109,-108,-101,-93,-80,-66,-58,-60,-64,-60,-48,-39,-38,-36,-25,-10,-2,-1,
+6,27,48,56,53,55,72,96,115,126,137,152,165,172,176,179,185,194,203,210,211,
+212,222,241,261,270,270,273,288,303,308,305,312,339,377,411,429,437,443,455,472,487,
+493,488,490,524,602,699,770,785,760,740,755,797,834,844,834,823,830,856,894,937,979,
+1019,1062,1108,1150,1179,1196,1217,1254,1307,1365,1425,1490,1556,1613,1655,1691,1726,1757,1776,1789,1814,
+1858,1901,1914,1882,1787,1620,1417,1297,1417,1839,2441,2995,3339,3494,3586,3704,3832,3920,3964,4007,4078,
+4162,4232,4281,4307,4297,4229,4106,3952,3780,3586,3362,3134,2944,2818,2749,2710,2682,2657,2634,2611,2591,
+2576,2566,2549,2516,2468,2414,2360,2306,2252,2202,2160,2120,2074,2018,1960,1911,1870,1829,1776,1709,1633,
+1552,1460,1356,1250,1155,1077,1002,914,810,705,615,543,488,448,424,409,390,355,309,269,252,
+267,303,343,367,374,373,377,386,394,401,406,395,340,231,97,-13,-72,-89,-93,-101,-115,
+-138,-182,-251,-328,-391,-437,-485,-558,-667,-799,-927,-1027,-1088,-1121,-1140,-1153,-1156,-1144,-1126,-1113,-1110,
+-1116,-1128,-1149,-1177,-1199,-1196,-1165,-1122,-1090,-1079,-1080,-1076,-1054,-1016,-976,-946,-925,-907,-888,-868,-850,
+-829,-801,-768,-737,-714,-699,-688,-679,-670,-657,-641,-623,-606,-590,-573,-557,-547,-542,-539,-535,-531,
+-530,-528,-519,-502,-483,-468,-458,-450,-441,-430,-417,-399,-379,-359,-338,-315,-290,-268,-248,-227,-201,
+-170,-139,-110,-80,-48,-18,8,34,61,87,111,132,155,180,206,232,259,287,313,336,357,
+379,404,430,458,487,516,543,570,600,631,661,688,716,746,778,808,835,864,897,930,960,
+987,1014,1045,1079,1114,1144,1170,1194,1217,1236,1247,1249,1251,1258,1273,1286,1294,1298,1306,1318,1330,
+1339,1346,1352,1358,1361,1365,1372,1379,1384,1389,1398,1411,1427,1442,1457,1473,1491,1509,1527,1549,1572,
+1592,1610,1629,1651,1672,1689,1705,1726,1748,1767,1783,1800,1821,1842,1861,1880,1902,1926,1950,1973,1995,
+2002,2023,2044,2068,2095,2124,2153,2183,2212,2236,2252,2263,2279,2311,2353,2394,2428,2462,2501,2543,2588,
+2647,2729,2810,2840,2784,2666,2550,2483,2460,2449,2434,2424,2434,2452,2459,2452,2442,2440,2439,2430,2417,
+2413,2422,2433,2441,2458,2500,2563,2622,2657,2686,2742,2839,2945,3016,3043,3060,3102,3167,3227,3262,3288,
+3331,3393,3448,3467,3432,3345,3220,3088,2981,2917,2884,2856,2818,2781,2767,2785,2818,2840,2838,2815,2787,
+2762,2736,2702,2657,2614,2586,2578,2579,2577,2568,2554,2537,2517,2502,2502,2520,2540,2548,2533,2499,2454,
+2410,2384,2388,2408,2411,2383,2345,2327,2328,2321,2296,2288,2335,2421,2469,2417,2267,2069,1872,1704,1592,
+1568,1626,1705,1722,1643,1506,1374,1281,1226,1195,1184,1188,1190,1175,1136,1081,1020,962,923,913,918,
+904,846,757,674,622,600,586,565,536,499,458,415,382,363,355,350,349,356,372,389,398,
+396,384,369,353,337,324,328,371,465,594,712,779,801,820,867,924,942,903,833,766,703,
+619,508,402,332,299,276,249,222,207,198,184,163,146,135,129,125,127,135,142,142,138,
+136,133,124,113,114,130,152,167,174,178,184,189,190,190,191,193,189,181,174,168,157,
+140,124,119,125,130,128,122,120,125,130,124,108,90,82,84,90,91,91,97,111,123,
+124,114,103,95,89,80,66,51,39,32,26,14,-6,-33,-54,-64,-64,-66,-73,-83,-92,
+-108,-140,-185,-227,-255,-273,-296,-331,-373,-413,-453,-495,-539,-580,-616,-654,-698,-747,-797,-845,-893,
+-941,-987,-1030,-1072,-1116,-1163,-1214,-1273,-1338,-1404,-1463,-1511,-1557,-1606,-1657,-1705,-1751,-1800,-1857,-1920,-1980,
+-2034,-2077,-2110,-2136,-2161,-2196,-2241,-2291,-2338,-2382,-2425,-2469,-2511,-2547,-2579,-2610,-2641,-2674,-2710,-2748,-2788,
+-2831,-2882,-2941,-2998,-3041,-3066,-3084,-3105,-3128,-3137,-3123,-3090,-3056,-3040,-3058,-3111,-3195,-3292,-3386,-3467,-3531,
+-3578,-3616,-3656,-3705,-3761,-3808,-3835,-3847,-3861,-3888,-3923,-3953,-3975,-3993,-4016,-4041,-4064,-4084,-4102,-4119,-4136,
+-4154,-4176,-4201,-4223,-4240,-4250,-4257,-4261,-4265,-4269,-4271,-4268,-4261,-4248,-4233,-4220,-4212,-4208,-4198,-4171,-4120,
+-4054,-3992,-3957,-3955,-3977,-4003,-4017,-4011,-3994,-3976,-3961,-3945,-3917,-3882,-3853,-3840,-3835,-3817,-3777,-3730,-3702,
+-3704,-3722,-3738,-3742,-3736,-3725,-3714,-3711,-3725,-3748,-3759,-3740,-3697,-3649,-3609,-3573,-3534,-3496,-3467,-3441,-3395,
+-3319,-3223,-3129,-3040,-2940,-2815,-2676,-2544,-2439,-2363,-2314,-2283,-2263,-2244,-2220,-2184,-2130,-2054,-1965,-1881,-1815,
+-1765,-1716,-1670,-1642,-1642,-1661,-1676,-1676,-1664,-1642,-1606,-1550,-1478,-1406,-1341,-1279,-1213,-1148,-1093,-1050,-1011,
+-967,-920,-881,-860,-855,-856,-857,-854,-850,-843,-829,-806,-778,-745,-706,-665,-627,-598,-575,-539,-479,
+-402,-329,-274,-229,-178,-115,-56,-15,4,21,57,125,211,289,337,344,320,281,238,199,169,
+157,165,189,226,275,332,396,465,540,628,729,837,943,1039,1121,1187,1240,1285,1333,1391,1459,
+1536,1614,1686,1745,1793,1838,1891,1948,2004,2056,2113,2176,2233,2273,2300,2330,2376,2430,2476,2507,2531,
+2557,2588,2620,2651,2688,2739,2805,2877,2942,2992,3033,3081,3148,3237,3340,3446,3547,3636,3715,3791,3875,
+3964,4045,4107,4152,4194,4241,4285,4312,4323,4332,4353,4388,4431,4476,4519,4556,4579,4587,4588,4594,4602,
+4595,4566,4538,4540,4563,4549,4442,4266,4118,4075,4123,4170,4153,4092,4048,4049,4075,4103,4135,4175,4211,
+4229,4236,4247,4258,4257,4266,4332,4468,4611,4671,4624,4538,4499,4527,4584,4631,4666,4701,4734,4754,4759,
+4759,4755,4743,4728,4721,4725,4725,4707,4679,4668,4690,4733,4776,4806,4827,4856,4903,4972,5046,5102,5127,
+5133,5150,5190,5235,5253,5236,5208,5201,5219,5237,5229,5199,5176,5184,5216,5248,5259,5253,5244,5240,5236,
+5229,5219,5209,5198,5181,5160,5141,5126,5112,5096,5077,5057,5036,5013,4991,4971,4952,4936,4920,4903,4885,
+4871,4874,4898,4928,4941,4931,4919,4936,4988,5046,5078,5076,5060,5055,5061,5062,5039,4988,4909,4782,4555,
+4187,3707,3242,2951,2906,3039,3206,3314,3364,3400,3436,3448,3424,3380,3337,3289,3219,3131,3044,2962,2876,
+2779,2685,2609,2544,2473,2390,2310,2243,2182,2117,2052,1999,1955,1906,1842,1771,1704,1646,1594,1548,1514,
+1487,1455,1409,1353,1301,1259,1223,1185,1140,1094,1054,1023,996,969,945,928,921,915,899,871,837,
+807,779,749,719,694,671,642,601,555,513,480,448,413,373,335,302,275,250,226,203,183,
+169,158,146,129,108,86,63,40,17,-1,-13,-25,-47,-81,-120,-150,-162,-163,-166,-183,-213,
+-244,-274,-309,-349,-378,-375,-345,-327,-355,-416,-460,-458,-432,-426,-457,-499,-525,-538,-557,-592,-629,
+-658,-682,-711,-740,-763,-781,-800,-826,-855,-880,-902,-925,-947,-968,-989,-1012,-1034,-1053,-1071,-1089,-1110,
+-1128,-1140,-1145,-1150,-1159,-1172,-1186,-1198,-1209,-1221,-1232,-1241,-1246,-1249,-1252,-1259,-1268,-1273,-1273,-1268,-1263,
+-1261,-1262,-1267,-1273,-1278,-1279,-1278,-1276,-1277,-1279,-1279,-1278,-1274,-1266,-1252,-1234,-1216,-1201,-1184,-1163,-1142,
+-1128,-1123,-1119,-1109,-1095,-1086,-1083,-1082,-1078,-1072,-1067,-1064,-1060,-1053,-1044,-1033,-1022,-1011,-999,-986,-971,
+-956,-941,-929,-917,-904,-890,-876,-860,-843,-825,-809,-795,-782,-766,-751,-740,-734,-727,-717,-704,-692,
+-682,-672,-661,-647,-631,-615,-601,-588,-576,-567,-563,-565,-568,-566,-558,-550,-546,-545,-541,-534,-528,
+-526,-524,-518,-509,-500,-494,-487,-481,-476,-474,-475,-476,-476,-476,-474,-470,-464,-459,-455,-450,-443,
+-433,-421,-409,-397,-388,-380,-374,-366,-359,-354,-348,-339,-326,-313,-308,-310,-311,-304,-291,-280,-274,
+-268,-256,-239,-229,-228,-226,-209,-179,-156,-152,-160,-160,-145,-125,-115,-116,-119,-117,-111,-106,-96,
+-80,-65,-58,-59,-57,-47,-33,-20,-9,1,8,6,1,6,25,48,60,60,61,70,83,
+96,109,125,145,162,172,177,178,179,184,197,211,218,216,214,222,238,252,262,280,312,
+346,362,357,351,365,398,434,456,469,484,507,534,556,568,574,583,608,653,705,738,740,
+725,723,750,794,826,835,827,823,832,853,885,927,977,1026,1071,1111,1149,1184,1213,1240,1271,
+1314,1371,1436,1503,1559,1598,1624,1648,1676,1703,1725,1747,1782,1833,1886,1915,1892,1789,1599,1384,1286,
+1447,1889,2469,2971,3279,3441,3574,3736,3887,3975,4007,4039,4111,4210,4295,4332,4309,4228,4107,3968,3829,
+3687,3527,3339,3140,2960,2825,2744,2708,2692,2674,2641,2605,2583,2577,2569,2543,2500,2450,2400,2348,2292,
+2238,2195,2163,2128,2081,2023,1962,1908,1860,1816,1769,1715,1652,1576,1485,1382,1279,1187,1107,1028,937,
+834,730,638,561,499,455,429,412,394,366,331,302,294,317,362,410,440,445,433,417,401,
+388,389,406,417,376,264,113,-9,-59,-52,-37,-50,-97,-164,-243,-324,-398,-455,-503,-564,-656,
+-778,-907,-1016,-1087,-1120,-1129,-1129,-1127,-1119,-1104,-1088,-1080,-1083,-1094,-1112,-1139,-1168,-1184,-1176,-1145,-1111,
+-1093,-1094,-1103,-1104,-1086,-1050,-1010,-974,-946,-921,-897,-876,-857,-834,-802,-763,-727,-700,-680,-664,-650,
+-637,-624,-608,-589,-569,-550,-532,-516,-506,-502,-500,-497,-494,-493,-491,-483,-469,-454,-442,-432,-421,
+-410,-398,-383,-365,-343,-319,-294,-268,-242,-217,-197,-176,-152,-123,-92,-59,-26,6,34,57,80,
+105,132,156,177,197,218,242,267,293,321,346,369,389,411,434,461,491,522,553,580,606,
+635,666,696,721,746,774,805,835,861,887,917,952,984,1010,1034,1062,1096,1131,1162,1188,1213,
+1238,1257,1265,1265,1266,1275,1289,1299,1303,1308,1318,1331,1343,1351,1357,1364,1369,1373,1378,1386,1396,
+1403,1408,1419,1435,1451,1464,1476,1492,1512,1531,1550,1569,1588,1605,1623,1643,1666,1687,1703,1718,1738,
+1762,1781,1795,1809,1826,1846,1864,1879,1897,1921,1950,1978,2002,2004,2027,2051,2078,2104,2128,2152,2179,
+2209,2237,2257,2275,2300,2338,2384,2427,2463,2502,2547,2592,2633,2682,2753,2829,2857,2796,2660,2520,2441,
+2429,2445,2453,2452,2458,2471,2478,2469,2454,2446,2446,2445,2441,2437,2441,2449,2460,2479,2518,2574,2626,
+2663,2697,2759,2857,2959,3025,3048,3063,3106,3177,3243,3281,3304,3337,3391,3444,3468,3440,3360,3240,3110,
+3002,2936,2901,2870,2831,2796,2788,2812,2848,2870,2865,2844,2820,2800,2775,2735,2684,2640,2620,2623,2631,
+2627,2607,2580,2555,2539,2535,2546,2567,2585,2591,2584,2568,2545,2521,2503,2502,2510,2508,2486,2460,2452,
+2464,2477,2483,2501,2552,2610,2616,2526,2358,2166,1989,1845,1745,1714,1750,1808,1818,1744,1610,1468,1357,
+1285,1249,1240,1242,1236,1210,1166,1112,1053,997,961,958,976,979,932,838,733,655,613,596,582,
+560,526,481,436,402,385,381,382,387,398,416,435,447,447,434,413,395,388,393,407,435,
+490,573,667,745,799,844,890,923,918,870,803,744,689,620,536,455,399,363,332,301,276,
+262,249,229,204,186,175,168,162,160,165,170,172,169,165,159,150,146,154,175,196,207,
+209,212,219,226,229,228,227,227,226,223,220,212,201,187,179,179,181,178,168,157,153,
+157,159,151,135,123,125,135,141,135,127,135,160,183,189,180,168,162,153,134,110,94,
+90,90,83,65,43,24,15,16,23,29,28,18,-3,-39,-86,-133,-169,-188,-204,-229,-266,
+-307,-344,-381,-422,-465,-504,-541,-582,-628,-677,-723,-768,-814,-862,-907,-949,-991,-1039,-1092,-1149,-1209,
+-1273,-1336,-1393,-1441,-1485,-1531,-1579,-1627,-1675,-1729,-1790,-1853,-1911,-1957,-1993,-2021,-2047,-2078,-2120,-2170,-2221,
+-2269,-2315,-2361,-2403,-2440,-2470,-2499,-2531,-2567,-2604,-2640,-2677,-2718,-2766,-2821,-2879,-2929,-2964,-2989,-3013,-3042,
+-3064,-3066,-3043,-3009,-2985,-2985,-3017,-3078,-3158,-3247,-3334,-3413,-3477,-3526,-3561,-3597,-3644,-3701,-3753,-3788,-3807,
+-3824,-3850,-3883,-3911,-3933,-3953,-3976,-4001,-4024,-4044,-4061,-4078,-4096,-4117,-4139,-4163,-4186,-4207,-4222,-4230,-4231,
+-4232,-4235,-4239,-4236,-4224,-4207,-4190,-4180,-4176,-4173,-4160,-4123,-4058,-3979,-3914,-3889,-3906,-3947,-3985,-4004,-4002,
+-3986,-3968,-3954,-3940,-3919,-3886,-3851,-3826,-3816,-3809,-3791,-3763,-3733,-3713,-3704,-3703,-3706,-3709,-3706,-3700,-3701,
+-3719,-3747,-3767,-3765,-3743,-3717,-3688,-3649,-3596,-3544,-3506,-3476,-3431,-3357,-3265,-3175,-3090,-2993,-2871,-2731,-2596,
+-2490,-2415,-2365,-2328,-2296,-2269,-2245,-2215,-2165,-2088,-1994,-1912,-1855,-1813,-1767,-1713,-1669,-1652,-1656,-1664,-1663,
+-1657,-1645,-1617,-1563,-1489,-1412,-1342,-1279,-1219,-1167,-1131,-1109,-1087,-1055,-1017,-985,-969,-968,-973,-976,-972,
+-959,-931,-890,-847,-810,-780,-749,-714,-685,-671,-663,-642,-588,-504,-408,-317,-230,-146,-69,-10,20,
+34,52,98,176,269,347,386,380,342,285,220,154,104,81,89,117,155,201,260,333,418,
+513,615,719,817,898,964,1020,1073,1126,1183,1243,1306,1368,1431,1497,1563,1625,1680,1733,1794,1861,
+1923,1976,2023,2074,2123,2161,2192,2227,2277,2334,2381,2410,2428,2451,2486,2531,2579,2630,2685,2746,2806,
+2861,2908,2955,3009,3080,3168,3268,3370,3466,3550,3627,3709,3799,3888,3958,4002,4028,4056,4093,4132,4158,
+4171,4187,4218,4266,4323,4383,4442,4495,4528,4536,4531,4534,4549,4555,4532,4498,4492,4520,4520,4420,4228,
+4044,3969,4003,4061,4068,4029,4001,4009,4032,4047,4063,4093,4129,4151,4157,4165,4175,4180,4190,4236,4331,
+4433,4482,4467,4437,4444,4488,4536,4570,4600,4639,4674,4693,4697,4702,4707,4704,4690,4678,4678,4680,4670,
+4647,4633,4642,4673,4710,4741,4771,4812,4874,4951,5021,5064,5074,5075,5093,5134,5178,5198,5190,5172,5165,
+5176,5191,5193,5179,5162,5161,5181,5208,5224,5224,5216,5211,5209,5203,5192,5179,5165,5148,5127,5106,5090,
+5080,5071,5056,5037,5015,4993,4969,4943,4919,4902,4890,4877,4859,4845,4852,4881,4916,4930,4919,4909,4930,
+4984,5038,5061,5049,5028,5022,5028,5026,4998,4934,4828,4660,4391,4001,3542,3140,2933,2963,3135,3301,3377,
+3386,3395,3426,3446,3424,3371,3318,3271,3213,3134,3045,2958,2871,2779,2688,2609,2540,2471,2394,2315,2242,
+2173,2108,2051,2003,1959,1907,1843,1777,1715,1658,1602,1553,1515,1484,1449,1403,1351,1302,1261,1223,1182,
+1137,1092,1051,1016,985,955,927,907,898,891,876,851,822,795,769,739,706,675,650,624,589,
+546,502,463,428,393,357,323,293,265,236,206,180,160,149,140,127,109,88,68,48,26,
+3,-16,-29,-38,-54,-81,-117,-147,-160,-154,-146,-157,-190,-228,-259,-285,-319,-355,-374,-370,-367,
+-394,-439,-459,-426,-369,-347,-384,-452,-503,-526,-542,-569,-604,-633,-657,-683,-714,-742,-761,-778,-798,
+-825,-854,-883,-910,-935,-959,-981,-1004,-1027,-1047,-1065,-1082,-1102,-1121,-1135,-1145,-1153,-1165,-1180,-1194,-1204,
+-1212,-1219,-1229,-1243,-1257,-1268,-1275,-1281,-1287,-1288,-1284,-1278,-1273,-1272,-1275,-1279,-1281,-1282,-1281,-1280,-1279,
+-1279,-1280,-1280,-1279,-1277,-1271,-1260,-1249,-1241,-1235,-1223,-1202,-1178,-1160,-1150,-1139,-1124,-1109,-1099,-1096,-1093,
+-1087,-1079,-1075,-1072,-1066,-1056,-1043,-1030,-1020,-1011,-1001,-990,-978,-964,-950,-937,-923,-910,-899,-889,-877,
+-862,-844,-827,-813,-799,-782,-766,-754,-748,-743,-735,-723,-711,-702,-694,-683,-667,-648,-632,-619,-606,
+-591,-580,-576,-581,-586,-583,-573,-563,-559,-557,-552,-545,-541,-541,-538,-531,-520,-512,-506,-500,-493,
+-488,-486,-485,-484,-480,-477,-475,-471,-468,-464,-462,-459,-454,-446,-435,-423,-409,-398,-389,-383,-377,
+-370,-361,-353,-344,-332,-321,-314,-310,-305,-296,-284,-277,-273,-263,-244,-224,-216,-220,-222,-206,-177,
+-156,-159,-175,-184,-174,-156,-147,-147,-145,-137,-127,-121,-114,-100,-81,-67,-62,-58,-49,-32,-13,
+1,12,15,10,4,7,22,42,57,64,68,73,79,86,96,110,124,136,146,154,159,
+159,161,172,191,205,208,205,211,226,241,256,280,322,369,399,400,389,391,412,442,465,
+483,504,532,559,583,604,627,651,669,680,683,680,677,681,701,739,781,815,837,853,867,
+874,878,890,925,981,1038,1080,1110,1142,1185,1233,1273,1305,1340,1388,1446,1500,1540,1566,1588,1614,
+1645,1679,1710,1741,1774,1812,1853,1886,1878,1783,1588,1371,1293,1494,1965,2535,2999,3273,3424,3566,3744,
+3913,4022,4071,4107,4166,4247,4316,4332,4273,4151,4005,3871,3751,3621,3461,3281,3106,2957,2842,2762,2714,
+2684,2653,2612,2577,2564,2569,2565,2534,2483,2433,2389,2341,2288,2237,2199,2167,2129,2080,2024,1966,1907,
+1847,1791,1744,1703,1656,1590,1505,1406,1305,1211,1125,1042,955,861,764,670,587,521,475,448,430,
+412,388,365,350,353,379,423,467,493,492,470,439,408,386,383,401,411,365,243,87,-28,
+-60,-32,-6,-31,-107,-208,-309,-395,-461,-514,-569,-648,-756,-880,-993,-1073,-1111,-1117,-1107,-1097,-1089,
+-1080,-1066,-1054,-1048,-1053,-1065,-1087,-1117,-1145,-1158,-1149,-1124,-1101,-1094,-1101,-1113,-1116,-1100,-1068,-1027,-988,
+-956,-927,-900,-874,-849,-821,-786,-746,-708,-678,-654,-634,-616,-601,-588,-571,-551,-530,-512,-496,-482,
+-471,-464,-461,-460,-459,-457,-450,-439,-426,-417,-409,-400,-387,-372,-358,-343,-323,-299,-273,-247,-223,
+-198,-175,-154,-134,-112,-85,-54,-22,11,43,70,93,114,139,166,191,212,232,253,276,301,
+328,354,379,402,424,446,470,495,524,555,586,613,639,667,697,727,752,775,802,834,865,
+891,915,943,975,1006,1032,1056,1083,1117,1152,1181,1206,1230,1254,1273,1280,1280,1281,1291,1305,1315,
+1319,1325,1336,1348,1356,1360,1365,1372,1377,1381,1387,1396,1407,1417,1427,1440,1457,1473,1486,1498,1514,
+1533,1551,1566,1582,1599,1616,1634,1654,1677,1697,1712,1729,1751,1777,1798,1811,1823,1840,1860,1877,1889,
+1903,1925,1953,1980,2004,2009,2034,2062,2090,2114,2134,2155,2180,2210,2241,2269,2298,2333,2377,2421,2457,
+2490,2534,2592,2648,2689,2722,2771,2832,2862,2811,2679,2529,2434,2417,2443,2466,2472,2475,2482,2486,2477,
+2460,2450,2452,2459,2461,2458,2457,2462,2475,2497,2534,2584,2633,2674,2718,2786,2884,2981,3042,3060,3069,
+3104,3168,3232,3272,3292,3317,3362,3415,3448,3433,3362,3249,3126,3027,2967,2933,2901,2863,2835,2836,2864,
+2894,2904,2891,2869,2853,2840,2817,2772,2715,2667,2648,2658,2673,2667,2637,2598,2570,2561,2571,2591,2611,
+2623,2626,2625,2625,2624,2615,2599,2588,2587,2589,2582,2570,2563,2570,2590,2622,2671,2729,2764,2729,2610,
+2439,2267,2120,2000,1908,1861,1869,1900,1901,1833,1705,1558,1433,1351,1314,1305,1301,1283,1247,1200,1150,
+1094,1038,1003,1007,1037,1047,998,891,768,672,619,599,588,571,541,500,457,427,413,415,424,
+436,452,468,483,495,500,491,469,448,443,458,483,503,525,565,632,716,799,864,905,913,
+884,827,767,721,685,642,586,527,475,432,392,359,335,317,298,273,248,231,221,212,202,
+194,193,195,196,194,191,187,185,188,201,219,233,240,244,251,261,270,273,271,268,266,
+266,265,262,253,241,232,229,231,229,219,204,193,189,189,188,180,169,164,173,187,192,
+184,178,191,223,251,258,248,239,233,220,193,164,152,157,159,147,127,114,118,127,131,
+125,111,92,65,28,-17,-63,-98,-118,-128,-142,-169,-206,-244,-279,-314,-354,-395,-433,-469,-512,
+-560,-608,-651,-693,-739,-788,-832,-871,-913,-964,-1023,-1083,-1141,-1200,-1258,-1312,-1361,-1407,-1454,-1502,-1551,
+-1603,-1660,-1720,-1778,-1829,-1869,-1901,-1930,-1960,-1998,-2045,-2098,-2151,-2200,-2249,-2295,-2336,-2367,-2394,-2424,-2460,
+-2501,-2540,-2576,-2613,-2655,-2706,-2762,-2815,-2857,-2886,-2913,-2945,-2978,-2997,-2990,-2963,-2936,-2925,-2940,-2981,-3045,
+-3125,-3209,-3289,-3359,-3419,-3466,-3503,-3539,-3586,-3645,-3703,-3745,-3769,-3788,-3811,-3840,-3868,-3890,-3910,-3932,-3957,
+-3982,-4004,-4024,-4043,-4062,-4081,-4100,-4121,-4145,-4171,-4192,-4201,-4198,-4193,-4195,-4202,-4203,-4192,-4174,-4157,-4148,
+-4144,-4140,-4124,-4086,-4025,-3954,-3902,-3890,-3914,-3953,-3984,-3997,-3994,-3979,-3961,-3944,-3929,-3911,-3885,-3853,-3822,
+-3802,-3795,-3792,-3784,-3767,-3743,-3718,-3701,-3696,-3699,-3702,-3700,-3701,-3714,-3738,-3759,-3768,-3768,-3764,-3750,-3715,
+-3660,-3602,-3558,-3522,-3476,-3405,-3318,-3231,-3146,-3052,-2934,-2799,-2668,-2563,-2487,-2432,-2383,-2338,-2302,-2275,-2245,
+-2193,-2113,-2022,-1947,-1899,-1861,-1811,-1749,-1695,-1667,-1660,-1661,-1662,-1667,-1673,-1663,-1622,-1550,-1466,-1384,-1311,
+-1246,-1195,-1163,-1147,-1135,-1118,-1097,-1078,-1066,-1061,-1059,-1061,-1061,-1048,-1010,-952,-891,-846,-818,-793,-763,
+-736,-724,-725,-719,-686,-619,-524,-414,-297,-186,-95,-34,0,22,58,123,214,312,386,416,402,
+360,304,238,171,120,102,116,149,183,222,275,349,438,535,633,723,798,851,888,921,963,
+1017,1083,1155,1224,1284,1335,1388,1447,1509,1569,1629,1696,1773,1846,1904,1947,1984,2021,2056,2090,2129,
+2178,2233,2279,2309,2330,2356,2398,2454,2518,2579,2633,2680,2724,2772,2828,2891,2961,3036,3117,3203,3290,
+3374,3455,3540,3632,3726,3807,3860,3885,3897,3915,3944,3978,4005,4026,4051,4091,4147,4215,4286,4359,4424,
+4467,4481,4477,4481,4500,4515,4501,4468,4458,4481,4482,4383,4182,3980,3886,3911,3972,3988,3959,3940,3957,
+3984,3994,3998,4019,4057,4085,4093,4090,4089,4094,4107,4142,4204,4270,4311,4328,4349,4392,4445,4484,4509,
+4538,4577,4610,4627,4635,4650,4667,4670,4654,4635,4626,4624,4613,4595,4583,4594,4625,4662,4691,4718,4759,
+4828,4915,4990,5028,5032,5031,5049,5087,5123,5141,5143,5140,5140,5143,5149,5152,5148,5138,5136,5151,5177,
+5195,5195,5183,5175,5172,5168,5155,5140,5127,5116,5100,5080,5063,5054,5046,5030,5007,4985,4966,4944,4917,
+4887,4866,4858,4852,4839,4825,4829,4860,4899,4920,4913,4905,4928,4983,5036,5051,5029,5000,4990,4997,4993,
+4953,4869,4736,4534,4231,3820,3364,3000,2856,2954,3179,3367,3431,3408,3388,3407,3429,3409,3353,3295,3253,
+3209,3139,3045,2947,2856,2772,2690,2611,2537,2466,2393,2314,2233,2154,2087,2036,1997,1957,1907,1846,1785,
+1727,1671,1615,1563,1519,1481,1443,1400,1355,1313,1272,1230,1184,1138,1093,1049,1010,975,945,919,899,
+884,870,853,830,807,785,761,730,693,658,630,604,573,534,490,449,411,375,341,309,281,
+253,223,191,163,144,133,124,110,90,69,49,30,10,-10,-30,-47,-60,-73,-92,-118,-146,
+-163,-161,-153,-158,-187,-223,-247,-260,-281,-317,-351,-369,-381,-409,-449,-459,-410,-331,-289,-320,-395,
+-461,-491,-506,-531,-568,-602,-625,-647,-676,-707,-732,-750,-768,-792,-823,-856,-887,-915,-941,-966,-991,
+-1015,-1036,-1054,-1072,-1092,-1112,-1128,-1141,-1151,-1162,-1176,-1191,-1205,-1214,-1221,-1229,-1242,-1259,-1276,-1289,-1299,
+-1307,-1310,-1308,-1301,-1294,-1290,-1290,-1289,-1288,-1288,-1288,-1290,-1290,-1288,-1285,-1283,-1281,-1278,-1272,-1262,-1255,
+-1252,-1250,-1242,-1225,-1205,-1189,-1177,-1163,-1146,-1129,-1119,-1113,-1108,-1100,-1092,-1088,-1084,-1077,-1064,-1049,-1036,
+-1025,-1015,-1006,-998,-989,-976,-961,-946,-930,-917,-908,-901,-894,-881,-865,-848,-833,-821,-806,-791,-778,
+-770,-764,-756,-744,-732,-724,-717,-705,-687,-668,-653,-642,-630,-615,-601,-598,-602,-605,-599,-584,-573,
+-569,-569,-566,-560,-556,-554,-551,-542,-532,-523,-517,-510,-503,-498,-497,-496,-492,-487,-484,-482,-480,
+-476,-470,-467,-465,-461,-455,-448,-438,-425,-410,-397,-388,-380,-372,-362,-352,-343,-335,-326,-318,-308,
+-294,-280,-271,-269,-267,-256,-234,-211,-204,-213,-219,-209,-185,-168,-173,-189,-197,-190,-177,-171,-170,
+-164,-149,-134,-126,-123,-114,-97,-81,-71,-67,-60,-48,-34,-22,-12,-6,-3,-2,2,13,30,
+46,60,69,77,85,94,104,111,113,115,122,135,145,149,149,155,171,188,198,204,216,
+233,249,260,276,308,350,382,392,386,385,396,413,430,447,470,494,512,527,546,578,615,
+640,645,636,632,643,669,704,740,775,816,864,913,946,949,928,914,935,991,1053,1092,1111,
+1137,1186,1248,1302,1339,1369,1408,1453,1493,1522,1546,1577,1617,1660,1702,1743,1780,1805,1817,1828,1848,
+1847,1760,1563,1346,1288,1525,2021,2584,3021,3274,3425,3578,3763,3940,4066,4138,4182,4226,4281,4329,4334,
+4265,4133,3987,3865,3755,3612,3419,3214,3048,2934,2850,2774,2708,2657,2617,2580,2554,2548,2555,2549,2515,
+2464,2417,2377,2335,2290,2246,2210,2171,2124,2072,2022,1973,1911,1836,1765,1714,1681,1647,1594,1520,1429,
+1332,1234,1142,1057,975,890,798,703,617,552,510,487,470,451,431,417,414,424,449,484,519,
+535,524,491,450,413,389,385,395,390,328,201,56,-37,-48,-10,7,-35,-131,-246,-351,-437,
+-508,-575,-650,-743,-851,-958,-1044,-1093,-1105,-1092,-1073,-1060,-1055,-1052,-1043,-1031,-1023,-1024,-1034,-1054,-1081,
+-1106,-1119,-1115,-1100,-1088,-1084,-1089,-1097,-1098,-1085,-1056,-1018,-981,-951,-924,-895,-864,-834,-803,-768,-728,
+-688,-654,-626,-601,-581,-564,-550,-534,-516,-498,-482,-468,-453,-436,-424,-419,-420,-422,-419,-409,-395,
+-382,-374,-368,-360,-345,-327,-311,-294,-274,-250,-226,-205,-186,-166,-144,-122,-100,-76,-49,-20,10,
+41,70,97,121,145,170,195,218,240,263,287,312,338,364,389,414,437,461,484,507,531,
+557,586,615,644,670,697,725,754,780,805,832,863,894,921,944,969,998,1027,1054,1079,1108,
+1143,1178,1207,1229,1249,1271,1288,1295,1294,1294,1303,1317,1329,1336,1342,1352,1361,1366,1368,1372,1379,
+1386,1391,1397,1406,1418,1430,1443,1457,1473,1489,1502,1517,1534,1552,1567,1581,1597,1616,1633,1650,1669,
+1690,1709,1725,1743,1766,1792,1811,1823,1835,1854,1877,1895,1907,1919,1937,1961,1986,2009,2022,2050,2080,
+2107,2130,2150,2170,2195,2221,2250,2281,2319,2364,2411,2453,2484,2512,2555,2617,2678,2715,2730,2745,2775,
+2796,2762,2660,2532,2446,2430,2459,2488,2497,2495,2495,2495,2484,2467,2457,2461,2471,2477,2476,2475,2479,
+2491,2512,2547,2595,2644,2690,2739,2810,2907,3004,3067,3086,3088,3107,3153,3206,3244,3267,3293,3340,3400,
+3443,3434,3362,3246,3126,3039,2994,2970,2945,2917,2903,2914,2939,2955,2948,2924,2901,2886,2874,2849,2802,
+2742,2695,2679,2693,2710,2703,2665,2620,2595,2601,2627,2657,2677,2683,2682,2683,2691,2698,2696,2680,2664,
+2662,2673,2684,2681,2668,2660,2674,2716,2779,2839,2855,2800,2677,2522,2375,2249,2140,2046,1987,1974,1986,
+1979,1914,1790,1639,1504,1417,1380,1372,1361,1332,1289,1244,1199,1145,1090,1058,1069,1102,1106,1038,911,
+773,672,620,600,589,574,549,516,482,457,448,455,472,493,512,526,537,548,557,555,537,
+514,505,520,544,556,555,566,614,699,794,868,902,896,860,809,762,730,709,684,645,594,
+538,488,449,419,396,373,346,318,295,280,268,255,242,232,228,226,224,221,218,219,224,
+235,247,257,264,271,283,297,311,320,324,325,324,321,318,316,311,299,285,274,271,269,
+262,250,239,231,228,226,223,219,214,211,218,231,241,243,249,269,301,324,327,318,312,
+307,293,264,237,230,236,233,216,201,211,240,260,249,210,159,113,73,37,2,-27,-48,
+-60,-70,-88,-116,-151,-184,-217,-251,-290,-327,-361,-397,-439,-488,-535,-577,-620,-667,-716,-761,-799,
+-840,-892,-952,-1013,-1067,-1119,-1172,-1226,-1278,-1328,-1377,-1427,-1478,-1532,-1589,-1645,-1696,-1739,-1775,-1806,-1839,
+-1876,-1923,-1976,-2032,-2085,-2133,-2179,-2222,-2260,-2291,-2321,-2357,-2398,-2440,-2479,-2516,-2553,-2597,-2647,-2700,-2748,
+-2783,-2811,-2841,-2877,-2910,-2924,-2916,-2896,-2881,-2881,-2898,-2937,-3001,-3084,-3172,-3249,-3310,-3360,-3404,-3443,-3483,
+-3533,-3594,-3653,-3697,-3724,-3742,-3765,-3794,-3822,-3845,-3862,-3881,-3905,-3933,-3960,-3982,-4002,-4022,-4042,-4060,-4079,
+-4102,-4131,-4156,-4166,-4160,-4150,-4149,-4156,-4162,-4156,-4141,-4127,-4118,-4112,-4103,-4087,-4059,-4018,-3974,-3944,-3940,
+-3955,-3972,-3980,-3979,-3976,-3970,-3957,-3937,-3914,-3894,-3873,-3851,-3825,-3802,-3788,-3785,-3786,-3783,-3770,-3750,-3732,
+-3722,-3718,-3713,-3706,-3701,-3709,-3726,-3746,-3763,-3777,-3789,-3790,-3769,-3726,-3675,-3630,-3587,-3533,-3460,-3374,-3288,
+-3204,-3112,-3001,-2876,-2753,-2651,-2572,-2506,-2444,-2386,-2340,-2306,-2269,-2209,-2128,-2045,-1983,-1941,-1897,-1836,-1768,
+-1716,-1692,-1686,-1684,-1686,-1699,-1719,-1727,-1704,-1645,-1564,-1480,-1401,-1330,-1271,-1225,-1195,-1175,-1163,-1156,-1150,
+-1139,-1123,-1110,-1106,-1112,-1107,-1075,-1015,-950,-901,-872,-851,-825,-799,-784,-784,-786,-770,-726,-648,-542,
+-421,-307,-220,-164,-127,-87,-28,55,158,262,341,379,376,348,309,263,217,187,185,211,245,
+275,303,344,405,479,555,626,691,743,781,808,837,875,926,988,1061,1135,1198,1250,1298,1353,
+1414,1476,1536,1602,1680,1758,1821,1862,1890,1919,1956,1998,2045,2095,2146,2190,2223,2249,2280,2327,2389,
+2459,2525,2575,2612,2648,2696,2762,2840,2920,2996,3069,3142,3213,3284,3361,3452,3552,3646,3713,3749,3764,
+3773,3790,3816,3846,3874,3901,3932,3976,4036,4109,4189,4268,4339,4391,4416,4424,4437,4462,4483,4474,4442,
+4423,4432,4418,4312,4113,3915,3824,3853,3917,3933,3902,3882,3900,3928,3933,3925,3937,3976,4015,4027,4016,
+4006,4017,4051,4101,4153,4193,4218,4241,4279,4333,4381,4414,4441,4477,4518,4548,4562,4574,4595,4617,4622,
+4607,4588,4575,4564,4546,4524,4516,4535,4579,4625,4654,4668,4692,4752,4843,4930,4978,4986,4985,5002,5035,
+5063,5078,5088,5097,5104,5105,5103,5103,5103,5099,5099,5113,5140,5160,5159,5144,5135,5137,5138,5128,5111,
+5100,5091,5077,5057,5038,5026,5015,4995,4968,4944,4929,4914,4889,4858,4836,4829,4828,4819,4803,4802,4830,
+4873,4901,4898,4890,4911,4970,5027,5043,5015,4977,4964,4970,4960,4907,4805,4655,4437,4114,3680,3214,2861,
+2755,2905,3180,3399,3469,3430,3385,3385,3402,3385,3330,3271,3233,3200,3138,3043,2937,2844,2768,2695,2617,
+2538,2463,2389,2311,2226,2142,2074,2025,1990,1953,1905,1848,1791,1736,1682,1627,1573,1523,1477,1434,1395,
+1359,1323,1283,1237,1190,1144,1099,1052,1008,970,941,917,895,873,850,828,808,790,773,750,719,
+681,644,613,586,554,516,476,437,400,364,327,294,267,241,212,180,150,128,115,103,88,
+69,49,31,13,-5,-22,-40,-58,-76,-91,-104,-118,-139,-160,-170,-171,-178,-202,-232,-249,-250,
+-256,-281,-314,-337,-355,-388,-434,-455,-414,-330,-270,-283,-351,-418,-450,-461,-482,-519,-557,-585,-608,
+-637,-671,-701,-722,-738,-759,-788,-822,-854,-885,-914,-944,-973,-1000,-1022,-1041,-1061,-1081,-1102,-1119,-1133,
+-1143,-1153,-1165,-1181,-1200,-1216,-1226,-1235,-1245,-1260,-1276,-1290,-1302,-1313,-1323,-1326,-1321,-1314,-1308,-1305,-1303,
+-1301,-1301,-1303,-1304,-1303,-1298,-1292,-1287,-1285,-1282,-1275,-1266,-1258,-1252,-1247,-1238,-1226,-1213,-1203,-1193,-1181,
+-1164,-1148,-1138,-1131,-1124,-1116,-1109,-1105,-1099,-1089,-1076,-1064,-1053,-1042,-1031,-1022,-1014,-1005,-992,-976,-957,
+-939,-925,-916,-911,-906,-897,-883,-867,-853,-841,-830,-817,-804,-793,-785,-775,-763,-752,-745,-738,-726,
+-709,-691,-679,-671,-661,-646,-632,-626,-628,-628,-617,-600,-587,-583,-584,-582,-576,-571,-567,-563,-555,
+-546,-538,-530,-522,-512,-505,-502,-500,-496,-494,-496,-499,-499,-491,-482,-475,-471,-465,-458,-452,-446,
+-436,-421,-403,-387,-376,-369,-361,-351,-343,-337,-332,-325,-312,-294,-278,-269,-270,-271,-262,-240,-219,
+-212,-220,-228,-221,-203,-188,-188,-196,-199,-192,-181,-176,-175,-168,-152,-136,-128,-126,-121,-109,-94,
+-84,-79,-75,-69,-62,-54,-45,-33,-21,-11,-3,6,21,41,58,72,81,92,104,116,120,
+116,112,117,132,148,157,158,161,171,185,198,212,230,251,266,273,278,292,315,337,351,
+358,363,371,377,385,398,418,439,450,453,464,493,535,572,594,606,623,655,694,727,751,
+776,819,885,959,1008,1010,975,943,952,1004,1065,1104,1121,1144,1192,1258,1315,1352,1380,1412,1451,
+1486,1515,1549,1596,1651,1701,1744,1789,1829,1848,1840,1827,1830,1817,1717,1506,1288,1258,1537,2057,2611,
+3022,3269,3441,3619,3809,3974,4093,4172,4226,4269,4312,4351,4355,4289,4161,4027,3926,3828,3669,3432,3183,
+3000,2899,2833,2757,2675,2612,2576,2555,2538,2529,2527,2518,2489,2446,2404,2367,2329,2290,2252,2213,2165,
+2109,2056,2014,1972,1910,1829,1751,1697,1666,1638,1594,1530,1451,1360,1264,1170,1083,1002,916,823,728,
+646,589,555,533,514,493,476,469,475,490,514,544,571,578,559,518,472,431,404,393,388,
+362,286,162,39,-23,-13,23,22,-43,-152,-266,-364,-452,-541,-636,-732,-826,-915,-992,-1051,-1082,
+-1085,-1067,-1045,-1033,-1033,-1035,-1028,-1014,-1001,-998,-1006,-1023,-1043,-1062,-1075,-1080,-1079,-1074,-1068,-1062,-1059,
+-1057,-1047,-1023,-990,-959,-935,-912,-884,-851,-820,-792,-761,-722,-680,-641,-610,-584,-562,-543,-524,-506,
+-486,-469,-453,-436,-416,-396,-380,-374,-376,-378,-374,-364,-350,-338,-330,-322,-312,-296,-278,-260,-242,
+-221,-200,-182,-167,-153,-135,-113,-89,-62,-35,-7,20,48,75,102,130,157,184,208,231,252,
+274,298,324,350,375,399,424,448,472,496,521,545,568,591,616,644,673,700,726,753,782,
+808,834,859,887,915,942,966,990,1017,1045,1071,1098,1130,1167,1204,1234,1256,1275,1294,1310,1315,
+1311,1307,1312,1325,1338,1346,1352,1359,1366,1373,1377,1384,1392,1400,1407,1413,1421,1433,1446,1459,1472,
+1486,1499,1513,1529,1547,1563,1578,1594,1613,1634,1651,1665,1681,1702,1723,1742,1760,1780,1801,1817,1829,
+1843,1864,1888,1907,1920,1933,1951,1974,1998,2022,2038,2069,2098,2124,2146,2168,2191,2213,2233,2256,2286,
+2329,2381,2437,2486,2521,2547,2577,2620,2664,2687,2681,2663,2656,2655,2634,2574,2499,2452,2454,2487,2515,
+2523,2518,2512,2506,2494,2478,2469,2474,2485,2492,2494,2496,2501,2510,2528,2562,2610,2662,2708,2755,2822,
+2916,3017,3090,3118,3117,3119,3143,3184,3222,3253,3289,3345,3413,3461,3448,3362,3232,3110,3036,3011,3007,
+3000,2990,2991,3004,3016,3010,2986,2957,2935,2919,2900,2870,2824,2772,2731,2719,2733,2749,2738,2698,2655,
+2640,2663,2705,2742,2760,2763,2761,2762,2768,2774,2770,2757,2744,2747,2766,2784,2785,2766,2746,2749,2783,
+2836,2882,2887,2836,2736,2613,2488,2367,2252,2152,2087,2068,2072,2058,1990,1864,1709,1571,1481,1444,1433,
+1417,1382,1338,1297,1258,1207,1154,1127,1143,1173,1159,1065,916,771,676,632,612,596,578,559,537,
+514,497,493,504,527,552,574,588,597,606,617,620,606,582,565,567,577,577,566,571,618,
+705,799,867,895,892,870,839,806,780,764,746,713,660,598,544,508,485,462,434,402,374,
+353,335,317,300,288,282,278,273,265,257,252,254,263,277,288,295,300,311,331,351,365,
+372,379,386,389,386,382,378,371,357,338,322,311,302,291,280,274,271,268,265,266,271,
+274,271,272,282,301,321,340,361,385,400,402,397,395,393,381,359,341,336,334,319,297,
+292,318,354,362,322,249,177,126,97,81,67,51,31,9,-15,-41,-69,-99,-128,-158,-192,
+-227,-260,-291,-324,-365,-412,-458,-500,-543,-592,-642,-688,-728,-772,-824,-882,-939,-990,-1039,-1090,-1144,
+-1199,-1252,-1304,-1355,-1407,-1460,-1513,-1564,-1609,-1648,-1683,-1717,-1755,-1802,-1857,-1917,-1974,-2023,-2065,-2104,-2141,
+-2176,-2212,-2252,-2296,-2340,-2381,-2419,-2456,-2495,-2537,-2584,-2632,-2675,-2710,-2739,-2771,-2806,-2836,-2850,-2850,-2845,
+-2843,-2842,-2847,-2873,-2935,-3030,-3131,-3213,-3268,-3308,-3345,-3384,-3428,-3483,-3545,-3604,-3647,-3671,-3690,-3716,-3751,
+-3783,-3804,-3817,-3832,-3856,-3886,-3916,-3939,-3957,-3977,-3999,-4020,-4038,-4057,-4082,-4106,-4118,-4114,-4103,-4099,-4103,
+-4108,-4106,-4099,-4090,-4082,-4073,-4061,-4046,-4030,-4013,-3998,-3989,-3988,-3985,-3975,-3958,-3947,-3947,-3953,-3950,-3931,
+-3903,-3876,-3856,-3841,-3826,-3808,-3792,-3781,-3779,-3782,-3782,-3777,-3770,-3761,-3750,-3734,-3717,-3708,-3711,-3724,-3740,
+-3756,-3774,-3793,-3806,-3801,-3779,-3745,-3706,-3660,-3601,-3526,-3441,-3357,-3272,-3181,-3075,-2957,-2841,-2740,-2655,-2577,
+-2500,-2431,-2376,-2333,-2282,-2212,-2130,-2060,-2012,-1972,-1915,-1840,-1770,-1729,-1719,-1720,-1719,-1719,-1731,-1753,-1767,
+-1757,-1718,-1657,-1588,-1517,-1448,-1382,-1322,-1271,-1234,-1214,-1208,-1206,-1194,-1170,-1147,-1140,-1148,-1154,-1135,-1085,
+-1023,-973,-942,-920,-898,-876,-862,-859,-859,-851,-822,-766,-680,-577,-483,-416,-376,-341,-291,-220,-129,
+-26,79,172,235,261,262,251,236,223,220,237,270,303,324,339,361,397,443,491,539,588,
+634,677,718,760,803,848,899,964,1040,1115,1178,1231,1285,1345,1404,1460,1520,1591,1667,1730,1769,
+1794,1823,1867,1921,1978,2033,2082,2125,2160,2190,2224,2270,2331,2401,2465,2515,2553,2592,2647,2719,2800,
+2878,2951,3021,3087,3146,3205,3275,3366,3466,3552,3606,3631,3646,3665,3689,3715,3740,3765,3793,3827,3871,
+3930,4005,4087,4169,4243,4302,4342,4368,4395,4426,4447,4438,4405,4380,4372,4338,4218,4018,3829,3751,3791,
+3863,3883,3851,3825,3837,3861,3861,3843,3847,3886,3935,3956,3944,3934,3961,4031,4114,4174,4193,4187,4189,
+4217,4261,4302,4335,4370,4416,4460,4486,4498,4512,4534,4553,4556,4546,4534,4524,4508,4480,4450,4439,4464,
+4520,4581,4618,4624,4627,4667,4754,4850,4911,4926,4926,4942,4974,5002,5018,5031,5046,5057,5060,5058,5061,
+5065,5064,5063,5073,5096,5114,5112,5100,5097,5107,5114,5107,5090,5075,5065,5050,5028,5008,4996,4983,4962,
+4933,4908,4894,4882,4861,4833,4811,4804,4802,4792,4774,4768,4793,4838,4869,4868,4858,4880,4943,5010,5031,
+5000,4959,4944,4949,4932,4862,4746,4591,4371,4038,3585,3103,2755,2673,2853,3155,3395,3477,3437,3377,3359,
+3368,3356,3308,3251,3211,3177,3122,3034,2933,2843,2769,2700,2622,2540,2460,2384,2307,2225,2144,2076,2024,
+1983,1943,1896,1845,1792,1741,1689,1636,1581,1524,1469,1421,1385,1356,1326,1286,1240,1193,1149,1106,1058,
+1010,971,941,917,891,860,829,803,785,771,757,735,703,667,632,600,570,536,499,462,427,
+392,353,314,278,251,228,203,171,137,108,89,75,61,46,30,13,-4,-21,-36,-49,-64,
+-84,-101,-110,-114,-125,-144,-164,-178,-191,-215,-244,-262,-263,-263,-278,-301,-317,-330,-362,-416,-455,
+-433,-356,-284,-276,-330,-393,-424,-428,-437,-466,-506,-541,-572,-605,-643,-674,-693,-706,-723,-750,-782,
+-815,-847,-882,-918,-953,-981,-1003,-1023,-1043,-1065,-1086,-1105,-1121,-1134,-1145,-1157,-1174,-1194,-1214,-1229,-1240,
+-1251,-1264,-1278,-1290,-1300,-1312,-1323,-1331,-1331,-1327,-1324,-1322,-1321,-1319,-1318,-1318,-1317,-1313,-1306,-1299,-1295,
+-1292,-1290,-1284,-1276,-1267,-1255,-1242,-1230,-1220,-1213,-1208,-1202,-1191,-1177,-1164,-1155,-1147,-1140,-1133,-1128,-1122,
+-1113,-1100,-1089,-1080,-1073,-1064,-1052,-1040,-1030,-1020,-1007,-990,-970,-952,-936,-925,-919,-915,-908,-896,-881,
+-867,-856,-846,-835,-823,-812,-801,-791,-779,-769,-762,-756,-747,-733,-719,-709,-703,-695,-681,-666,-658,
+-656,-653,-641,-623,-608,-602,-602,-600,-594,-587,-582,-577,-570,-562,-555,-547,-536,-524,-513,-505,-500,
+-497,-500,-507,-514,-513,-504,-494,-488,-482,-473,-460,-450,-447,-443,-431,-410,-389,-375,-369,-365,-357,
+-348,-341,-338,-336,-327,-310,-294,-286,-288,-290,-283,-266,-249,-242,-245,-248,-241,-226,-213,-207,-206,
+-203,-196,-187,-181,-177,-171,-159,-146,-138,-134,-129,-119,-107,-97,-91,-86,-79,-72,-64,-52,-37,
+-21,-9,-1,7,24,46,66,79,85,92,102,111,114,112,111,119,135,153,167,174,180,
+187,196,207,222,240,261,277,288,293,297,303,313,327,343,359,370,373,376,387,407,429,
+443,449,457,479,514,554,588,617,648,684,719,743,756,771,806,869,944,999,1012,989,963,
+969,1013,1070,1113,1137,1165,1210,1267,1316,1345,1368,1398,1438,1477,1515,1561,1621,1682,1730,1767,1806,
+1847,1869,1862,1846,1837,1802,1669,1433,1222,1236,1569,2114,2650,3029,3269,3468,3675,3865,4003,4096,4172,
+4237,4282,4311,4329,4319,4252,4135,4026,3961,3894,3737,3467,3169,2950,2839,2776,2702,2617,2556,2534,2526,
+2512,2495,2483,2476,2459,2429,2393,2356,2319,2282,2242,2197,2143,2086,2038,2001,1962,1902,1826,1754,1703,
+1670,1637,1592,1534,1466,1385,1295,1203,1115,1027,932,833,741,671,625,594,567,539,514,500,501,
+514,536,565,597,620,622,598,558,513,470,433,402,373,326,240,124,25,-10,17,55,41,
+-40,-156,-266,-360,-455,-564,-679,-782,-859,-917,-967,-1016,-1053,-1067,-1056,-1037,-1025,-1025,-1025,-1016,-998,
+-984,-982,-992,-1008,-1023,-1037,-1052,-1069,-1081,-1080,-1065,-1041,-1021,-1009,-999,-982,-957,-933,-916,-897,-869,
+-835,-805,-780,-754,-718,-675,-635,-604,-581,-557,-531,-505,-479,-454,-432,-412,-392,-372,-355,-343,-339,
+-337,-335,-328,-318,-307,-296,-285,-273,-261,-246,-230,-211,-191,-171,-154,-141,-130,-116,-95,-69,-41,
+-13,14,40,66,91,116,143,171,199,226,251,272,292,314,337,362,385,408,430,455,480,
+505,529,554,579,603,625,648,673,701,728,754,780,806,833,859,882,905,930,956,981,1006,
+1033,1060,1087,1114,1145,1182,1221,1254,1279,1299,1317,1331,1336,1330,1322,1323,1333,1346,1355,1360,1365,
+1373,1382,1391,1400,1408,1417,1425,1432,1442,1453,1464,1476,1487,1498,1510,1522,1537,1552,1566,1582,1600,
+1622,1642,1657,1669,1687,1710,1734,1755,1771,1788,1805,1820,1834,1851,1872,1894,1912,1926,1942,1963,1986,
+2011,2038,2050,2081,2110,2133,2155,2179,2203,2223,2239,2258,2290,2337,2396,2460,2521,2568,2592,2600,2606,
+2615,2617,2601,2570,2540,2520,2503,2480,2458,2455,2478,2511,2532,2536,2532,2527,2519,2506,2493,2490,2497,
+2505,2509,2510,2514,2521,2528,2544,2577,2628,2682,2726,2765,2823,2912,3015,3097,3134,3134,3127,3138,3170,
+3211,3251,3296,3355,3422,3465,3446,3350,3214,3096,3040,3039,3060,3075,3084,3091,3094,3076,3038,2996,2968,
+2955,2943,2921,2889,2850,2810,2780,2772,2784,2797,2786,2750,2715,2712,2746,2793,2825,2835,2834,2833,2836,
+2839,2839,2833,2825,2821,2829,2848,2864,2865,2849,2831,2827,2842,2868,2890,2888,2854,2789,2699,2591,2467,
+2341,2235,2173,2156,2158,2135,2057,1924,1768,1630,1542,1503,1489,1469,1433,1393,1359,1324,1278,1228,1206,
+1222,1243,1210,1096,935,793,708,670,645,618,593,577,566,556,548,549,564,589,615,637,651,
+660,669,678,681,670,646,621,603,589,572,564,587,656,753,842,897,920,927,927,914,888,
+860,841,828,802,751,683,625,588,565,540,507,471,443,420,397,373,355,348,347,341,329,
+315,304,298,298,306,319,332,341,351,368,392,413,423,429,437,449,455,452,445,440,434,
+419,396,374,356,341,327,317,314,314,312,310,319,336,349,348,342,350,376,409,437,455,
+469,481,489,493,494,491,482,473,469,467,454,424,394,389,410,426,401,332,251,192,168,
+166,169,165,147,114,74,34,1,-24,-49,-76,-105,-136,-168,-198,-227,-259,-296,-338,-382,-423,
+-466,-513,-562,-610,-656,-704,-756,-811,-863,-913,-962,-1015,-1070,-1125,-1178,-1231,-1284,-1337,-1387,-1435,-1480,
+-1522,-1562,-1600,-1640,-1685,-1739,-1801,-1862,-1916,-1958,-1992,-2024,-2057,-2093,-2136,-2186,-2236,-2281,-2319,-2354,-2392,
+-2433,-2474,-2515,-2558,-2600,-2636,-2668,-2699,-2730,-2757,-2778,-2793,-2804,-2807,-2796,-2780,-2792,-2855,-2964,-3081,-3172,
+-3228,-3262,-3292,-3327,-3372,-3430,-3498,-3560,-3601,-3622,-3640,-3669,-3709,-3744,-3764,-3774,-3787,-3813,-3846,-3876,-3897,
+-3913,-3933,-3957,-3980,-3995,-4006,-4020,-4039,-4054,-4060,-4055,-4049,-4048,-4049,-4049,-4048,-4045,-4040,-4031,-4020,-4008,
+-4001,-3998,-3999,-4000,-3996,-3980,-3954,-3929,-3915,-3919,-3928,-3930,-3916,-3890,-3862,-3840,-3827,-3818,-3809,-3797,-3786,
+-3780,-3780,-3784,-3788,-3791,-3788,-3778,-3761,-3744,-3734,-3735,-3742,-3750,-3759,-3773,-3790,-3805,-3811,-3806,-3789,-3762,
+-3722,-3667,-3599,-3523,-3442,-3356,-3262,-3156,-3041,-2927,-2823,-2729,-2639,-2550,-2471,-2410,-2357,-2291,-2206,-2122,-2062,
+-2027,-1987,-1921,-1837,-1770,-1742,-1743,-1747,-1744,-1741,-1749,-1766,-1778,-1775,-1753,-1717,-1669,-1613,-1553,-1491,-1430,
+-1372,-1323,-1291,-1275,-1264,-1247,-1221,-1196,-1187,-1195,-1205,-1193,-1153,-1098,-1049,-1014,-991,-972,-956,-946,-944,
+-943,-938,-920,-881,-818,-739,-667,-622,-596,-569,-523,-458,-383,-301,-207,-107,-18,43,78,101,120,
+139,161,187,215,237,244,240,238,250,279,324,381,445,508,569,628,685,735,775,815,872,
+952,1039,1116,1176,1228,1281,1335,1387,1442,1507,1579,1640,1681,1708,1739,1787,1848,1912,1971,2024,2070,
+2109,2144,2180,2227,2286,2351,2413,2463,2507,2554,2615,2687,2763,2836,2907,2979,3044,3098,3148,3209,3292,
+3383,3455,3495,3514,3534,3567,3603,3630,3650,3672,3700,3735,3778,3831,3899,3978,4061,4140,4210,4266,4310,
+4347,4378,4393,4380,4349,4328,4317,4272,4139,3930,3739,3661,3705,3786,3816,3789,3759,3762,3782,3783,3767,
+3768,3808,3862,3891,3884,3876,3913,4007,4117,4187,4192,4157,4133,4147,4186,4228,4266,4308,4356,4396,4418,
+4430,4449,4473,4490,4491,4484,4478,4469,4447,4412,4378,4364,4385,4443,4516,4569,4585,4582,4608,4684,4781,
+4846,4862,4859,4874,4911,4948,4969,4983,4997,5009,5015,5019,5030,5041,5045,5041,5042,5054,5063,5061,5053,
+5056,5070,5080,5074,5058,5043,5032,5018,4998,4980,4968,4956,4937,4912,4889,4872,4856,4834,4810,4791,4782,
+4776,4762,4743,4737,4759,4800,4829,4831,4825,4852,4922,4993,5012,4977,4934,4924,4931,4905,4820,4693,4539,
+4321,3975,3501,3010,2674,2615,2809,3110,3349,3443,3418,3360,3328,3326,3318,3285,3236,3188,3145,3092,3019,
+2935,2853,2779,2705,2626,2542,2458,2379,2301,2224,2150,2082,2023,1972,1926,1882,1837,1791,1744,1695,1644,
+1586,1521,1457,1405,1371,1347,1321,1283,1239,1194,1152,1109,1063,1016,976,944,916,885,849,812,782,
+763,751,738,717,688,653,619,587,556,522,488,453,418,380,338,295,259,233,215,194,164,
+125,90,65,49,37,26,13,0,-18,-38,-53,-64,-74,-89,-105,-110,-107,-108,-123,-146,-167,
+-186,-210,-242,-268,-282,-290,-305,-323,-331,-335,-357,-408,-455,-451,-388,-316,-296,-336,-391,-416,-411,
+-406,-424,-459,-498,-535,-574,-614,-644,-660,-670,-685,-711,-743,-775,-807,-845,-887,-927,-957,-979,-998,
+-1020,-1043,-1064,-1083,-1101,-1120,-1139,-1156,-1173,-1191,-1209,-1225,-1238,-1251,-1267,-1282,-1294,-1303,-1313,-1323,-1330,
+-1334,-1335,-1335,-1335,-1334,-1331,-1329,-1327,-1324,-1320,-1315,-1312,-1309,-1305,-1301,-1296,-1290,-1282,-1270,-1253,-1237,
+-1226,-1221,-1217,-1209,-1198,-1187,-1177,-1170,-1162,-1154,-1148,-1144,-1138,-1127,-1114,-1103,-1095,-1088,-1079,-1066,-1053,
+-1040,-1029,-1016,-1001,-985,-968,-951,-937,-929,-923,-917,-907,-892,-878,-867,-857,-848,-839,-829,-819,-809,
+-798,-788,-781,-776,-770,-760,-749,-740,-734,-728,-716,-702,-691,-685,-680,-670,-653,-637,-628,-623,-618,
+-611,-604,-599,-594,-587,-579,-570,-562,-552,-541,-529,-518,-509,-505,-508,-515,-517,-512,-503,-498,-499,
+-498,-486,-466,-450,-446,-448,-441,-422,-399,-384,-380,-378,-371,-359,-349,-346,-346,-341,-330,-317,-311,
+-311,-312,-307,-295,-283,-276,-273,-268,-259,-247,-236,-227,-221,-216,-211,-204,-198,-192,-184,-175,-165,
+-156,-149,-141,-133,-122,-113,-103,-92,-79,-65,-52,-38,-24,-10,-2,2,10,27,51,73,84,
+86,86,89,92,94,96,103,115,132,149,165,179,190,197,203,212,225,241,259,278,297,
+312,320,321,323,333,352,372,387,394,400,412,432,457,482,501,517,536,561,590,620,646,
+670,694,718,738,753,765,787,826,879,931,963,972,971,984,1021,1071,1118,1155,1191,1236,1282,
+1318,1337,1353,1381,1424,1471,1518,1570,1630,1688,1731,1761,1794,1833,1861,1867,1863,1853,1795,1629,1374,
+1184,1253,1640,2198,2702,3039,3265,3482,3713,3902,4021,4100,4181,4249,4270,4241,4192,4136,4061,3971,3908,
+3895,3868,3727,3443,3112,2864,2743,2689,2629,2556,2506,2492,2489,2474,2450,2437,2435,2429,2406,2372,2335,
+2298,2259,2215,2165,2113,2065,2026,1992,1951,1894,1829,1770,1724,1684,1639,1588,1531,1469,1395,1311,1223,
+1133,1037,933,831,748,692,655,621,582,542,514,504,512,534,565,601,634,650,644,620,589,
+556,515,463,406,349,284,195,88,3,-18,19,62,48,-33,-150,-261,-361,-466,-584,-700,-785,
+-831,-859,-895,-952,-1012,-1051,-1058,-1045,-1032,-1027,-1022,-1009,-992,-981,-985,-1001,-1019,-1035,-1051,-1073,-1099,
+-1119,-1115,-1084,-1037,-994,-969,-958,-947,-933,-917,-903,-883,-852,-814,-781,-756,-731,-697,-656,-619,-590,
+-566,-538,-505,-472,-441,-414,-390,-370,-352,-337,-327,-320,-315,-308,-298,-286,-276,-268,-257,-243,-227,
+-214,-202,-188,-169,-149,-131,-118,-107,-94,-74,-47,-16,13,40,66,89,113,136,161,186,212,
+238,263,287,309,330,352,375,397,418,439,461,486,511,535,558,583,609,634,657,678,701,
+726,753,778,802,827,853,878,901,923,946,972,999,1027,1054,1082,1108,1133,1160,1193,1229,1264,
+1292,1314,1331,1344,1349,1345,1338,1338,1348,1361,1372,1378,1382,1390,1399,1409,1417,1424,1431,1439,1448,
+1458,1468,1478,1488,1499,1511,1523,1534,1544,1555,1567,1583,1602,1623,1640,1654,1669,1690,1716,1740,1759,
+1774,1789,1806,1824,1841,1860,1880,1900,1916,1933,1953,1975,1997,2021,2050,2056,2087,2116,2139,2161,2185,
+2209,2227,2242,2265,2305,2359,2420,2484,2546,2593,2611,2598,2571,2551,2542,2533,2514,2490,2468,2455,2450,
+2457,2476,2503,2525,2533,2533,2533,2534,2529,2518,2511,2514,2524,2528,2525,2521,2524,2532,2539,2554,2588,
+2642,2696,2737,2771,2821,2901,2997,3077,3118,3124,3120,3129,3160,3202,3245,3286,3335,3390,3426,3409,3324,
+3204,3108,3074,3094,3134,3166,3185,3190,3169,3113,3038,2977,2951,2951,2951,2937,2913,2887,2862,2843,2839,
+2854,2870,2866,2838,2812,2814,2844,2876,2887,2880,2873,2877,2885,2887,2881,2874,2873,2881,2894,2908,2919,
+2925,2925,2923,2918,2914,2912,2911,2903,2880,2834,2761,2661,2540,2414,2310,2253,2240,2238,2203,2109,1966,
+1809,1678,1595,1558,1541,1521,1489,1455,1427,1396,1353,1307,1285,1296,1306,1260,1139,981,849,772,734,
+700,659,626,609,607,606,605,612,630,656,681,701,716,727,737,743,743,733,712,681,644,
+604,573,575,629,730,843,927,969,986,1002,1017,1014,986,950,929,925,912,869,803,741,697,
+667,633,591,550,518,491,461,435,421,420,419,407,388,371,362,359,358,362,374,389,403,
+418,438,463,482,490,494,503,515,519,512,503,497,490,474,450,426,407,391,376,367,368,
+372,373,374,386,409,429,432,424,429,456,495,526,543,555,570,587,597,593,581,571,574,
+586,589,567,523,484,469,469,453,398,322,261,239,247,261,262,245,213,168,120,78,47,
+24,0,-27,-56,-86,-115,-145,-174,-203,-236,-273,-313,-354,-395,-438,-484,-532,-582,-634,-686,-737,
+-787,-837,-890,-945,-999,-1052,-1104,-1158,-1212,-1265,-1313,-1356,-1396,-1438,-1482,-1526,-1573,-1624,-1682,-1744,-1800,
+-1845,-1879,-1909,-1939,-1975,-2017,-2066,-2122,-2175,-2218,-2252,-2286,-2325,-2367,-2406,-2444,-2483,-2525,-2564,-2597,-2625,
+-2652,-2679,-2708,-2737,-2760,-2762,-2738,-2708,-2712,-2779,-2897,-3023,-3120,-3179,-3215,-3244,-3274,-3313,-3372,-3447,-3517,
+-3561,-3578,-3590,-3616,-3654,-3688,-3706,-3716,-3732,-3762,-3799,-3831,-3852,-3870,-3890,-3915,-3936,-3948,-3952,-3957,-3970,
+-3988,-4003,-4007,-4002,-3995,-3993,-3996,-3999,-3999,-3996,-3990,-3986,-3984,-3983,-3982,-3981,-3978,-3969,-3950,-3927,-3907,
+-3899,-3900,-3901,-3897,-3884,-3866,-3845,-3825,-3812,-3805,-3802,-3798,-3793,-3789,-3786,-3786,-3790,-3796,-3801,-3800,-3793,
+-3784,-3779,-3779,-3780,-3781,-3783,-3788,-3797,-3805,-3811,-3813,-3809,-3794,-3765,-3722,-3668,-3604,-3529,-3442,-3345,-3237,
+-3123,-3009,-2902,-2800,-2698,-2598,-2513,-2445,-2381,-2300,-2201,-2110,-2056,-2030,-1997,-1933,-1853,-1795,-1774,-1775,-1772,
+-1762,-1758,-1769,-1786,-1797,-1796,-1785,-1761,-1725,-1677,-1625,-1575,-1526,-1476,-1427,-1386,-1355,-1331,-1307,-1280,-1257,
+-1245,-1248,-1252,-1242,-1209,-1162,-1117,-1083,-1060,-1041,-1028,-1023,-1027,-1032,-1034,-1026,-1000,-951,-886,-824,-785,
+-766,-747,-715,-674,-633,-588,-522,-430,-330,-244,-179,-126,-76,-32,1,22,36,40,31,11,-3,
+5,51,133,237,342,431,503,566,625,674,712,747,800,880,973,1056,1118,1165,1210,1257,1304,
+1356,1419,1489,1552,1598,1632,1666,1712,1769,1830,1892,1953,2008,2057,2099,2142,2192,2252,2316,2376,2427,
+2473,2522,2581,2648,2720,2793,2868,2944,3012,3065,3112,3168,3241,3316,3370,3394,3406,3432,3475,3521,3552,
+3570,3590,3621,3660,3701,3746,3800,3868,3949,4037,4121,4192,4247,4289,4317,4321,4300,4272,4263,4267,4228,
+4095,3881,3682,3594,3631,3714,3755,3734,3694,3680,3692,3703,3704,3715,3753,3805,3838,3836,3826,3856,3944,
+4056,4128,4128,4082,4050,4064,4111,4163,4208,4251,4294,4325,4342,4357,4382,4411,4430,4432,4426,4417,4400,
+4370,4333,4302,4288,4302,4352,4428,4500,4538,4547,4570,4638,4729,4793,4807,4798,4810,4850,4894,4922,4936,
+4948,4961,4970,4980,4996,5015,5024,5022,5017,5016,5015,5010,5006,5012,5025,5033,5028,5018,5009,5003,4992,
+4976,4959,4944,4929,4911,4893,4875,4856,4834,4810,4789,4775,4765,4752,4736,4721,4718,4736,4767,4792,4799,
+4806,4845,4918,4982,4989,4944,4902,4899,4908,4872,4772,4639,4489,4269,3904,3404,2907,2595,2565,2766,3052,
+3283,3396,3405,3361,3312,3283,3269,3252,3220,3171,3115,3059,3001,2939,2870,2795,2715,2632,2547,2462,2378,
+2297,2222,2151,2084,2019,1960,1910,1868,1830,1790,1747,1701,1650,1588,1517,1448,1394,1360,1337,1312,1279,
+1240,1200,1158,1114,1067,1022,981,945,913,880,844,805,771,746,732,720,703,676,642,607,573,
+541,512,482,449,410,364,317,272,236,212,197,182,156,118,80,52,34,22,11,0,-12,
+-29,-51,-70,-82,-89,-98,-108,-110,-102,-96,-105,-127,-151,-171,-193,-224,-256,-282,-303,-326,-347,
+-354,-351,-361,-398,-442,-451,-410,-355,-335,-362,-401,-415,-401,-388,-395,-419,-450,-483,-521,-563,-596,
+-616,-629,-649,-678,-710,-740,-770,-808,-853,-896,-929,-953,-973,-996,-1021,-1042,-1061,-1081,-1105,-1129,-1152,
+-1171,-1189,-1204,-1218,-1231,-1246,-1262,-1279,-1294,-1305,-1314,-1322,-1328,-1332,-1335,-1337,-1337,-1335,-1332,-1329,-1329,
+-1329,-1328,-1327,-1327,-1325,-1319,-1312,-1305,-1302,-1298,-1288,-1272,-1256,-1244,-1236,-1229,-1219,-1207,-1196,-1188,-1180,
+-1172,-1163,-1157,-1153,-1148,-1140,-1128,-1117,-1107,-1098,-1087,-1075,-1061,-1048,-1036,-1024,-1012,-999,-985,-969,-955,
+-945,-937,-930,-919,-906,-893,-882,-873,-865,-857,-850,-843,-835,-824,-814,-806,-801,-796,-789,-780,-770,
+-763,-757,-748,-737,-725,-717,-710,-701,-687,-672,-659,-649,-639,-628,-619,-613,-609,-603,-594,-584,-576,
+-569,-562,-552,-541,-532,-526,-525,-524,-517,-505,-496,-497,-507,-511,-500,-477,-457,-452,-455,-452,-437,
+-417,-403,-398,-396,-388,-373,-360,-355,-353,-350,-342,-332,-327,-326,-324,-318,-311,-305,-299,-291,-281,
+-270,-261,-253,-245,-237,-232,-229,-226,-220,-212,-204,-195,-185,-174,-164,-156,-149,-141,-131,-118,-102,
+-84,-66,-50,-36,-24,-13,-6,-3,4,20,42,63,75,78,78,78,79,80,85,97,112,
+126,140,155,171,185,193,199,208,221,237,254,274,298,320,335,339,340,346,359,375,391,
+405,419,434,451,472,500,531,557,577,594,613,633,652,665,680,700,727,753,770,781,794,
+822,864,911,949,975,999,1031,1076,1125,1171,1214,1258,1297,1325,1338,1349,1376,1421,1473,1522,1570,
+1620,1668,1707,1738,1772,1809,1837,1849,1854,1843,1770,1586,1335,1183,1304,1722,2266,2724,3018,3230,3459,
+3704,3900,4025,4124,4227,4288,4245,4104,3941,3818,3739,3692,3687,3720,3721,3592,3311,2981,2740,2636,2608,
+2575,2519,2473,2458,2452,2436,2415,2407,2409,2403,2376,2337,2300,2267,2229,2181,2130,2085,2051,2023,1990,
+1946,1891,1837,1788,1744,1694,1638,1580,1522,1461,1389,1307,1221,1131,1031,925,828,759,716,683,642,
+592,547,520,517,531,557,591,626,650,651,631,606,589,574,542,481,404,330,260,177,77,
+-6,-33,-2,39,33,-38,-151,-267,-378,-492,-608,-705,-758,-772,-779,-813,-884,-968,-1030,-1055,-1052,
+-1040,-1031,-1022,-1012,-1002,-1002,-1014,-1035,-1057,-1079,-1101,-1126,-1152,-1165,-1152,-1106,-1040,-980,-946,-936,-934,
+-928,-915,-897,-871,-834,-791,-752,-721,-695,-663,-626,-591,-559,-528,-494,-458,-426,-400,-379,-361,-345,
+-332,-319,-308,-296,-284,-271,-257,-244,-235,-227,-216,-200,-185,-173,-164,-153,-136,-116,-99,-87,-76,
+-59,-34,-2,29,59,85,110,133,157,181,206,229,251,272,295,318,341,364,386,408,431,
+454,475,496,519,542,565,588,611,637,662,685,706,729,753,777,801,823,846,871,895,919,
+942,968,996,1025,1054,1083,1111,1137,1160,1181,1207,1239,1273,1303,1325,1342,1353,1359,1358,1356,1357,
+1367,1381,1394,1401,1406,1411,1418,1425,1431,1437,1443,1450,1458,1467,1475,1484,1493,1505,1518,1530,1541,
+1550,1560,1572,1587,1604,1622,1638,1655,1674,1698,1722,1743,1758,1773,1791,1810,1830,1849,1868,1888,1907,
+1926,1946,1968,1989,2008,2029,2056,2060,2093,2124,2150,2174,2198,2219,2234,2251,2281,2330,2389,2446,2498,
+2542,2571,2574,2549,2512,2487,2483,2491,2497,2495,2489,2483,2483,2491,2507,2522,2527,2523,2521,2527,2536,
+2536,2528,2525,2533,2544,2544,2534,2525,2527,2536,2544,2559,2594,2646,2700,2741,2776,2822,2891,2969,3037,
+3079,3097,3107,3122,3151,3190,3227,3259,3291,3329,3359,3353,3297,3213,3148,3134,3165,3209,3244,3263,3258,
+3216,3131,3029,2953,2927,2936,2951,2954,2948,2937,2925,2916,2923,2948,2976,2981,2960,2936,2932,2943,2947,
+2929,2902,2890,2899,2914,2917,2908,2901,2908,2925,2941,2953,2966,2986,3012,3031,3031,3012,2989,2972,2956,
+2924,2866,2786,2690,2585,2475,2380,2326,2312,2306,2260,2150,1992,1832,1711,1642,1611,1596,1577,1551,1524,
+1500,1470,1428,1382,1356,1357,1354,1302,1185,1040,920,849,808,766,717,676,659,658,662,665,674,
+695,721,746,767,784,799,809,811,807,798,780,748,698,640,602,616,697,823,945,1022,1051,
+1063,1082,1105,1106,1077,1037,1015,1016,1014,985,931,873,825,784,736,681,631,592,560,529,505,
+496,497,492,473,449,435,434,436,434,433,442,459,476,493,512,534,552,560,566,574,583,
+583,572,560,553,545,527,502,480,466,453,439,431,437,450,459,460,465,482,502,511,509,
+515,541,579,611,630,643,661,680,684,667,640,623,632,654,661,635,584,538,515,500,466,
+406,347,320,328,346,346,322,282,239,197,158,126,101,78,51,19,-11,-40,-68,-97,-126,
+-154,-182,-215,-252,-292,-331,-371,-413,-459,-510,-563,-615,-665,-714,-765,-821,-877,-929,-979,-1029,-1084,
+-1140,-1193,-1239,-1279,-1318,-1361,-1409,-1460,-1513,-1568,-1626,-1681,-1727,-1762,-1790,-1819,-1856,-1899,-1949,-2003,-2059,
+-2111,-2151,-2183,-2216,-2255,-2297,-2337,-2374,-2413,-2454,-2493,-2525,-2552,-2577,-2605,-2640,-2677,-2705,-2708,-2683,-2654,
+-2663,-2731,-2844,-2960,-3053,-3118,-3165,-3200,-3225,-3254,-3309,-3389,-3469,-3517,-3531,-3535,-3552,-3584,-3615,-3632,-3644,
+-3664,-3697,-3735,-3769,-3796,-3819,-3843,-3866,-3885,-3896,-3902,-3907,-3916,-3933,-3949,-3957,-3953,-3946,-3943,-3947,-3950,
+-3944,-3935,-3932,-3944,-3961,-3973,-3972,-3962,-3949,-3935,-3920,-3906,-3899,-3896,-3891,-3878,-3861,-3846,-3835,-3824,-3812,
+-3801,-3794,-3793,-3794,-3796,-3798,-3799,-3797,-3797,-3802,-3812,-3822,-3825,-3822,-3820,-3821,-3824,-3826,-3828,-3828,-3825,
+-3821,-3819,-3821,-3822,-3813,-3792,-3761,-3722,-3670,-3601,-3516,-3419,-3315,-3205,-3093,-2983,-2875,-2764,-2655,-2559,-2482,
+-2407,-2312,-2198,-2101,-2051,-2036,-2016,-1964,-1896,-1848,-1831,-1825,-1811,-1792,-1789,-1806,-1830,-1844,-1846,-1836,-1813,
+-1774,-1725,-1677,-1637,-1601,-1562,-1516,-1470,-1431,-1399,-1371,-1344,-1318,-1299,-1290,-1287,-1278,-1253,-1216,-1179,-1152,
+-1132,-1114,-1100,-1097,-1107,-1123,-1134,-1133,-1113,-1070,-1010,-948,-906,-885,-874,-859,-845,-836,-825,-789,-717,
+-625,-536,-459,-388,-320,-263,-231,-221,-224,-229,-239,-250,-249,-210,-117,23,182,322,424,489,538,
+584,627,664,702,755,831,918,996,1054,1098,1137,1176,1216,1264,1324,1395,1463,1518,1561,1600,1641,
+1688,1742,1804,1873,1940,1999,2048,2096,2150,2213,2279,2340,2394,2441,2487,2540,2602,2674,2752,2832,2909,
+2975,3030,3080,3136,3200,3257,3289,3300,3310,3340,3390,3443,3478,3499,3520,3552,3595,3637,3676,3717,3773,
+3851,3945,4039,4117,4177,4221,4246,4242,4213,4184,4184,4203,4183,4068,3869,3675,3580,3607,3690,3741,3722,
+3663,3615,3603,3619,3643,3670,3706,3752,3787,3794,3784,3793,3851,3939,4005,4011,3978,3956,3978,4035,4094,
+4144,4187,4226,4252,4267,4283,4309,4340,4361,4367,4363,4349,4322,4282,4245,4221,4211,4220,4259,4331,4412,
+4466,4489,4516,4583,4673,4739,4753,4743,4751,4789,4832,4859,4872,4886,4904,4920,4933,4948,4968,4982,4986,
+4982,4974,4965,4959,4959,4968,4980,4988,4989,4988,4987,4982,4971,4955,4937,4916,4894,4874,4862,4853,4837,
+4813,4790,4775,4765,4752,4736,4720,4713,4716,4728,4747,4764,4777,4801,4853,4926,4976,4965,4911,4870,4873,
+4878,4825,4708,4571,4428,4204,3816,3290,2792,2513,2521,2734,3008,3238,3385,3442,3418,3344,3266,3223,3211,
+3197,3156,3092,3030,2981,2936,2881,2809,2725,2639,2555,2471,2385,2302,2226,2157,2089,2020,1955,1902,1859,
+1822,1783,1742,1700,1651,1588,1515,1444,1389,1354,1329,1304,1276,1245,1211,1169,1122,1074,1028,985,943,
+906,875,843,807,769,738,718,707,692,667,633,594,556,525,500,476,443,399,346,296,253,
+218,193,177,164,144,113,78,49,30,14,-1,-16,-27,-40,-59,-81,-97,-105,-110,-113,-111,
+-101,-90,-93,-112,-137,-158,-176,-201,-230,-259,-287,-316,-342,-355,-354,-355,-378,-412,-431,-419,-392,
+-382,-397,-414,-412,-395,-383,-385,-396,-405,-419,-446,-486,-526,-557,-584,-615,-650,-684,-712,-741,-777,
+-822,-866,-902,-928,-951,-977,-1005,-1030,-1051,-1071,-1093,-1117,-1141,-1163,-1182,-1199,-1214,-1227,-1239,-1253,-1268,
+-1283,-1297,-1309,-1317,-1322,-1326,-1329,-1331,-1332,-1330,-1329,-1329,-1332,-1335,-1337,-1338,-1338,-1336,-1329,-1319,-1311,
+-1307,-1305,-1298,-1286,-1271,-1258,-1248,-1239,-1227,-1215,-1204,-1195,-1186,-1177,-1167,-1160,-1156,-1152,-1146,-1137,-1126,
+-1115,-1103,-1092,-1081,-1070,-1058,-1045,-1034,-1023,-1013,-1000,-987,-975,-965,-957,-947,-936,-926,-916,-906,-896,
+-887,-881,-876,-872,-865,-856,-846,-837,-831,-826,-819,-810,-798,-788,-782,-775,-767,-757,-747,-740,-733,
+-722,-708,-693,-678,-663,-647,-634,-625,-621,-617,-610,-601,-594,-589,-585,-579,-570,-560,-553,-548,-540,
+-528,-513,-505,-508,-518,-522,-512,-491,-473,-467,-469,-467,-455,-439,-426,-419,-413,-403,-389,-378,-371,
+-367,-361,-352,-343,-337,-334,-330,-325,-322,-320,-316,-305,-291,-280,-273,-268,-262,-254,-248,-246,-243,
+-239,-231,-224,-214,-202,-188,-178,-172,-168,-160,-148,-133,-115,-98,-82,-68,-57,-46,-35,-26,-19,
+-10,2,21,38,51,60,67,73,78,81,89,101,114,125,135,147,162,175,184,191,202,
+218,237,255,273,294,312,325,332,337,345,353,362,375,394,417,434,445,458,479,508,535,
+555,570,587,609,629,646,663,688,721,754,776,785,789,804,839,888,936,974,1003,1037,1080,
+1129,1177,1221,1262,1299,1324,1338,1350,1377,1422,1475,1521,1558,1591,1626,1664,1704,1747,1783,1803,1810,
+1811,1795,1713,1532,1309,1207,1371,1794,2301,2707,2969,3177,3413,3661,3858,4000,4134,4265,4312,4194,3938,
+3667,3484,3406,3394,3425,3474,3479,3361,3108,2822,2627,2564,2566,2553,2504,2455,2432,2424,2412,2400,2399,
+2401,2387,2350,2304,2267,2236,2200,2152,2102,2064,2039,2016,1983,1938,1888,1841,1797,1750,1693,1631,1571,
+1512,1448,1374,1292,1209,1119,1021,921,836,780,746,714,669,619,580,561,563,579,602,628,648,
+651,631,598,574,569,569,547,491,415,343,279,204,109,20,-23,-13,14,9,-53,-158,-277,
+-399,-519,-627,-699,-723,-716,-717,-757,-837,-931,-1005,-1042,-1049,-1040,-1029,-1021,-1019,-1024,-1037,-1057,-1080,
+-1106,-1132,-1155,-1173,-1183,-1181,-1158,-1109,-1043,-983,-950,-945,-948,-942,-921,-891,-856,-815,-770,-727,-692,
+-662,-632,-598,-561,-522,-482,-443,-410,-388,-373,-360,-347,-333,-319,-300,-276,-249,-227,-211,-201,-194,
+-187,-179,-167,-153,-141,-133,-127,-117,-100,-80,-63,-50,-36,-17,7,36,65,91,116,141,166,
+193,220,246,268,287,306,327,351,376,398,419,442,467,492,515,535,554,574,595,618,641,
+665,689,712,734,757,782,806,828,849,871,894,917,941,966,993,1023,1053,1082,1110,1138,1163,
+1184,1203,1224,1251,1285,1317,1343,1361,1371,1376,1377,1377,1379,1386,1396,1407,1415,1420,1423,1427,1432,
+1438,1445,1452,1458,1464,1471,1478,1486,1494,1504,1516,1528,1540,1551,1564,1579,1595,1611,1626,1643,1661,
+1683,1705,1724,1741,1757,1776,1797,1818,1836,1853,1872,1893,1915,1937,1961,1983,2002,2016,2034,2060,2066,
+2100,2134,2164,2191,2216,2236,2251,2269,2303,2353,2412,2463,2499,2517,2517,2499,2470,2445,2437,2446,2463,
+2481,2496,2508,2514,2513,2512,2515,2518,2516,2509,2508,2519,2532,2536,2532,2531,2540,2550,2549,2537,2528,
+2531,2540,2550,2566,2599,2647,2700,2744,2784,2829,2882,2939,2992,3038,3076,3105,3127,3150,3180,3212,3238,
+3259,3282,3303,3306,3275,3223,3185,3186,3218,3255,3280,3287,3272,3221,3132,3030,2954,2927,2941,2967,2987,
+2999,3001,2996,2995,3015,3057,3099,3110,3088,3056,3037,3026,3004,2963,2924,2912,2926,2945,2948,2938,2933,
+2944,2965,2983,2995,3014,3053,3106,3146,3148,3118,3081,3053,3024,2969,2882,2784,2696,2614,2526,2438,2378,
+2361,2357,2309,2186,2013,1847,1736,1683,1665,1654,1637,1615,1593,1570,1540,1497,1451,1418,1404,1386,1328,
+1219,1089,982,918,878,834,782,739,719,718,721,724,734,755,783,811,834,854,870,878,877,
+870,860,844,811,755,691,654,680,777,910,1027,1092,1110,1117,1137,1163,1169,1146,1109,1087,1085,
+1085,1069,1036,996,955,907,844,774,713,667,632,604,584,576,575,566,545,523,514,516,518,
+512,509,518,537,556,572,586,604,620,630,638,645,650,646,633,622,614,603,583,559,542,
+536,528,514,505,516,540,558,557,548,549,565,585,599,615,641,675,705,722,730,739,746,
+739,713,677,656,662,681,684,653,603,562,543,530,502,460,429,424,435,433,402,351,300,
+262,233,209,186,162,134,100,66,34,6,-20,-49,-77,-103,-129,-160,-195,-233,-270,-307,-346,
+-391,-441,-494,-546,-595,-646,-699,-754,-808,-857,-905,-956,-1012,-1069,-1120,-1164,-1204,-1244,-1289,-1341,-1397,
+-1454,-1511,-1565,-1612,-1648,-1675,-1700,-1734,-1779,-1832,-1887,-1943,-1998,-2045,-2083,-2114,-2145,-2183,-2225,-2267,-2307,
+-2346,-2386,-2423,-2455,-2482,-2509,-2538,-2573,-2612,-2643,-2654,-2643,-2632,-2652,-2717,-2808,-2899,-2977,-3047,-3111,-3156,
+-3178,-3195,-3241,-3324,-3412,-3466,-3479,-3477,-3489,-3519,-3548,-3566,-3580,-3601,-3632,-3666,-3701,-3734,-3765,-3792,-3812,
+-3828,-3844,-3858,-3869,-3876,-3886,-3897,-3906,-3905,-3900,-3899,-3899,-3891,-3867,-3841,-3838,-3868,-3915,-3952,-3962,-3952,
+-3934,-3917,-3905,-3899,-3899,-3899,-3888,-3865,-3840,-3821,-3811,-3804,-3797,-3791,-3789,-3789,-3790,-3794,-3803,-3812,-3815,
+-3815,-3819,-3832,-3846,-3853,-3850,-3846,-3848,-3859,-3873,-3883,-3882,-3869,-3854,-3844,-3842,-3842,-3832,-3812,-3786,-3756,
+-3714,-3655,-3578,-3490,-3396,-3293,-3183,-3071,-2957,-2840,-2722,-2616,-2526,-2436,-2327,-2203,-2103,-2057,-2055,-2049,-2010,
+-1953,-1911,-1896,-1886,-1865,-1840,-1834,-1851,-1877,-1895,-1900,-1891,-1864,-1821,-1769,-1725,-1694,-1665,-1628,-1580,-1531,
+-1490,-1462,-1438,-1413,-1381,-1350,-1328,-1318,-1312,-1297,-1270,-1242,-1223,-1210,-1196,-1183,-1179,-1191,-1212,-1225,-1223,
+-1202,-1163,-1110,-1055,-1014,-995,-990,-989,-990,-996,-997,-977,-927,-855,-781,-710,-639,-570,-516,-491,-490,
+-493,-485,-466,-437,-387,-296,-152,27,207,349,438,486,518,551,589,631,678,734,801,871,934,
+987,1032,1073,1107,1140,1180,1236,1305,1377,1441,1494,1538,1578,1619,1667,1728,1800,1873,1935,1987,2037,
+2092,2155,2223,2290,2350,2402,2449,2500,2561,2635,2717,2795,2864,2921,2974,3028,3085,3139,3177,3195,3202,
+3218,3255,3311,3368,3408,3432,3453,3483,3525,3571,3611,3650,3702,3777,3870,3963,4040,4099,4146,4173,4169,
+4135,4101,4100,4124,4119,4030,3862,3688,3594,3611,3694,3760,3754,3679,3586,3531,3532,3569,3613,3652,3691,
+3729,3752,3750,3742,3763,3817,3872,3892,3881,3876,3906,3962,4020,4069,4114,4155,4185,4200,4213,4234,4261,
+4282,4292,4292,4278,4248,4205,4168,4147,4139,4146,4178,4242,4318,4372,4399,4431,4501,4595,4667,4689,4684,
+4693,4727,4765,4786,4796,4812,4838,4863,4881,4895,4909,4924,4932,4931,4923,4912,4907,4912,4926,4942,4954,
+4963,4968,4968,4958,4940,4921,4903,4882,4856,4835,4827,4824,4814,4794,4776,4765,4757,4743,4724,4714,4716,
+4725,4733,4739,4748,4765,4800,4861,4930,4966,4943,4886,4850,4853,4844,4766,4626,4483,4342,4115,3708,3165,
+2678,2441,2494,2727,2997,3231,3411,3517,3518,3422,3293,3204,3177,3169,3137,3074,3007,2958,2920,2872,2804,
+2721,2637,2555,2474,2393,2314,2240,2171,2101,2029,1961,1902,1854,1811,1770,1731,1693,1648,1587,1515,1445,
+1391,1354,1325,1298,1273,1250,1221,1181,1132,1082,1034,987,940,900,870,844,811,772,736,712,697,
+682,657,622,580,540,507,485,464,432,385,331,283,245,211,181,159,145,130,106,75,49,
+29,11,-9,-30,-43,-50,-63,-83,-103,-115,-120,-122,-118,-105,-90,-87,-102,-127,-149,-166,-185,
+-210,-237,-265,-295,-324,-343,-348,-350,-363,-388,-411,-419,-418,-421,-428,-429,-418,-405,-404,-410,-408,
+-392,-378,-384,-414,-457,-498,-538,-579,-620,-657,-688,-720,-757,-801,-842,-875,-902,-928,-958,-990,-1020,
+-1046,-1068,-1088,-1108,-1128,-1149,-1170,-1191,-1209,-1223,-1234,-1244,-1256,-1270,-1286,-1299,-1309,-1315,-1319,-1324,-1329,
+-1331,-1333,-1335,-1338,-1342,-1345,-1345,-1344,-1344,-1341,-1335,-1326,-1317,-1310,-1305,-1299,-1289,-1276,-1265,-1255,-1245,
+-1235,-1224,-1212,-1201,-1191,-1181,-1172,-1164,-1158,-1152,-1146,-1139,-1129,-1117,-1106,-1096,-1089,-1080,-1070,-1058,-1047,
+-1037,-1026,-1015,-1003,-994,-985,-976,-966,-956,-948,-942,-934,-923,-913,-905,-901,-898,-893,-886,-877,-869,
+-863,-857,-850,-840,-827,-815,-806,-799,-791,-782,-774,-767,-760,-751,-739,-725,-709,-691,-672,-654,-641,
+-634,-631,-629,-624,-619,-614,-610,-604,-596,-586,-577,-569,-562,-552,-542,-536,-536,-539,-536,-525,-509,
+-496,-491,-490,-485,-476,-463,-451,-441,-430,-418,-407,-400,-396,-392,-384,-373,-364,-357,-351,-346,-343,
+-344,-345,-341,-327,-310,-297,-292,-289,-284,-276,-269,-264,-260,-255,-250,-244,-235,-222,-207,-196,-191,
+-186,-175,-159,-142,-127,-114,-102,-91,-81,-70,-58,-46,-35,-25,-13,1,15,28,40,54,68,
+80,88,98,109,119,127,134,143,156,170,180,189,202,219,240,260,277,289,296,301,309,
+321,335,344,351,363,385,410,429,437,443,455,474,493,507,522,545,574,604,631,655,681,
+709,736,755,769,782,804,837,879,920,955,988,1026,1070,1118,1164,1204,1242,1277,1304,1323,1340,
+1369,1413,1464,1508,1537,1556,1579,1614,1663,1713,1749,1763,1761,1756,1731,1642,1473,1295,1256,1466,1884,
+2346,2704,2947,3160,3398,3629,3802,3935,4077,4216,4248,4089,3779,3461,3251,3162,3146,3167,3203,3207,3118,
+2928,2717,2584,2554,2565,2548,2492,2437,2410,2404,2400,2397,2400,2399,2379,2336,2286,2247,2214,2176,2129,
+2083,2048,2023,1996,1960,1917,1875,1834,1792,1741,1682,1622,1563,1503,1434,1359,1280,1200,1112,1016,924,
+852,807,778,747,708,670,646,637,643,655,669,677,673,652,618,585,567,567,569,554,514,
+458,399,337,258,160,69,16,9,18,4,-53,-148,-265,-392,-518,-621,-679,-691,-681,-689,-739,
+-823,-916,-990,-1032,-1045,-1039,-1026,-1019,-1025,-1044,-1068,-1091,-1113,-1137,-1162,-1179,-1182,-1172,-1156,-1134,-1099,
+-1051,-1005,-979,-975,-974,-958,-922,-877,-833,-792,-751,-710,-672,-639,-607,-574,-535,-491,-445,-406,-381,
+-368,-358,-344,-326,-306,-286,-259,-223,-186,-158,-145,-142,-141,-134,-124,-112,-103,-96,-90,-82,-69,
+-51,-31,-12,3,17,33,53,76,98,120,141,164,190,218,247,274,296,315,335,359,385,
+410,432,452,475,501,528,551,569,585,603,625,649,673,694,714,736,760,785,811,835,857,
+879,901,923,946,969,994,1020,1049,1077,1103,1128,1153,1177,1198,1216,1235,1260,1293,1329,1360,1382,
+1393,1398,1399,1399,1399,1401,1404,1409,1415,1421,1424,1427,1432,1440,1449,1456,1461,1466,1472,1480,1487,
+1495,1503,1512,1523,1535,1550,1567,1586,1603,1618,1634,1651,1669,1687,1703,1718,1735,1755,1779,1801,1820,
+1836,1853,1874,1897,1922,1946,1969,1991,2007,2021,2039,2066,2074,2107,2141,2174,2204,2231,2254,2274,2295,
+2327,2372,2424,2470,2496,2496,2471,2433,2403,2393,2403,2421,2435,2447,2465,2488,2504,2506,2499,2493,2492,
+2492,2490,2493,2505,2519,2527,2527,2529,2539,2549,2549,2540,2535,2539,2549,2561,2578,2609,2654,2705,2753,
+2798,2839,2876,2912,2956,3013,3074,3119,3142,3154,3174,3204,3234,3252,3263,3270,3265,3240,3205,3185,3195,
+3228,3259,3272,3264,3239,3191,3119,3040,2982,2962,2975,3005,3038,3062,3069,3063,3065,3096,3155,3207,3220,
+3189,3144,3108,3079,3040,2991,2953,2947,2967,2988,2991,2981,2978,2989,3007,3019,3027,3051,3109,3185,3240,
+3243,3201,3147,3104,3057,2978,2869,2765,2692,2635,2561,2469,2398,2379,2384,2344,2217,2032,1862,1759,1723,
+1718,1710,1693,1671,1650,1627,1596,1554,1509,1472,1444,1407,1338,1232,1115,1023,969,936,897,848,805,
+783,779,782,785,794,815,845,875,901,920,934,940,936,928,917,899,863,806,746,720,758,
+859,987,1090,1142,1154,1159,1175,1198,1206,1191,1165,1144,1136,1134,1130,1121,1106,1079,1028,954,871,
+800,748,713,686,666,655,650,641,626,611,604,602,597,590,589,602,625,645,657,668,680,
+692,700,705,710,711,705,692,680,671,658,639,619,611,612,609,595,585,598,630,655,652,
+629,615,628,663,701,733,760,785,804,809,802,792,784,774,756,732,715,710,711,697,663,
+624,598,591,588,572,547,529,524,517,486,433,375,333,309,293,274,248,218,183,148,114,
+85,58,30,2,-24,-50,-78,-109,-143,-177,-211,-245,-283,-327,-375,-425,-476,-528,-580,-634,-687,
+-737,-784,-832,-885,-941,-995,-1043,-1085,-1126,-1171,-1220,-1275,-1333,-1391,-1447,-1497,-1537,-1567,-1591,-1619,-1659,
+-1712,-1771,-1829,-1884,-1933,-1976,-2011,-2041,-2073,-2110,-2152,-2196,-2239,-2279,-2317,-2352,-2385,-2418,-2448,-2478,-2509,
+-2544,-2578,-2603,-2616,-2630,-2663,-2720,-2785,-2846,-2906,-2977,-3052,-3107,-3126,-3134,-3171,-3254,-3348,-3410,-3427,-3426,
+-3440,-3472,-3503,-3522,-3534,-3552,-3578,-3608,-3639,-3674,-3709,-3737,-3754,-3769,-3788,-3810,-3825,-3830,-3834,-3843,-3856,
+-3863,-3864,-3862,-3854,-3826,-3776,-3728,-3718,-3764,-3842,-3911,-3946,-3948,-3934,-3918,-3906,-3901,-3900,-3899,-3886,-3863,
+-3837,-3816,-3801,-3788,-3780,-3781,-3787,-3792,-3792,-3796,-3809,-3826,-3836,-3836,-3840,-3854,-3872,-3880,-3873,-3864,-3866,
+-3885,-3909,-3926,-3926,-3910,-3891,-3879,-3875,-3869,-3852,-3826,-3800,-3775,-3744,-3696,-3634,-3562,-3481,-3386,-3277,-3161,
+-3044,-2924,-2801,-2686,-2582,-2478,-2357,-2225,-2123,-2083,-2091,-2097,-2066,-2011,-1969,-1954,-1948,-1929,-1904,-1890,-1897,
+-1912,-1926,-1932,-1927,-1903,-1861,-1814,-1779,-1756,-1732,-1691,-1637,-1584,-1547,-1527,-1513,-1492,-1457,-1415,-1381,-1364,
+-1358,-1347,-1326,-1303,-1291,-1289,-1284,-1275,-1271,-1280,-1293,-1297,-1283,-1256,-1223,-1186,-1151,-1124,-1113,-1115,-1121,
+-1125,-1126,-1122,-1103,-1066,-1015,-960,-903,-842,-782,-738,-718,-711,-694,-650,-582,-495,-387,-250,-83,91,
+243,352,417,454,481,513,553,603,660,721,777,826,870,916,965,1012,1050,1081,1117,1170,1238,
+1310,1375,1431,1479,1520,1561,1608,1668,1739,1809,1871,1924,1975,2031,2093,2160,2228,2293,2352,2405,2460,
+2523,2599,2678,2749,2805,2851,2897,2948,3001,3044,3071,3086,3101,3131,3179,3237,3292,3334,3361,3379,3404,
+3442,3491,3540,3588,3642,3715,3803,3890,3961,4020,4070,4105,4106,4074,4038,4030,4049,4049,3980,3838,3678,
+3576,3574,3654,3748,3778,3713,3589,3483,3452,3490,3547,3592,3627,3668,3705,3715,3701,3695,3721,3767,3799,
+3808,3816,3847,3897,3949,3996,4043,4088,4120,4135,4145,4162,4186,4207,4218,4219,4209,4184,4147,4112,4088,
+4077,4082,4112,4170,4235,4281,4306,4341,4415,4512,4588,4617,4621,4637,4673,4708,4725,4731,4743,4772,4806,
+4833,4849,4860,4869,4877,4880,4875,4864,4858,4865,4884,4905,4921,4933,4939,4935,4918,4894,4876,4865,4852,
+4831,4810,4799,4796,4791,4777,4764,4757,4748,4733,4717,4713,4722,4734,4737,4735,4738,4755,4794,4855,4919,
+4946,4918,4864,4836,4838,4812,4705,4538,4378,4228,3990,3571,3031,2576,2392,2495,2746,3003,3221,3408,3545,
+3579,3492,3343,3221,3164,3143,3111,3055,2992,2939,2894,2842,2775,2697,2617,2540,2464,2390,2318,2250,2183,
+2113,2041,1971,1909,1854,1804,1759,1720,1686,1645,1587,1516,1448,1397,1360,1328,1298,1272,1250,1224,1185,
+1136,1086,1038,989,940,899,869,845,815,777,740,712,691,669,641,607,567,527,493,470,449,
+418,372,321,278,246,214,179,148,129,116,96,70,45,28,12,-9,-32,-47,-53,-62,-80,
+-103,-120,-129,-132,-129,-115,-98,-89,-97,-118,-141,-160,-180,-205,-233,-261,-290,-317,-338,-350,-358,
+-369,-387,-405,-417,-427,-440,-449,-449,-442,-442,-455,-469,-461,-429,-393,-378,-393,-426,-465,-506,-548,
+-588,-626,-663,-702,-746,-788,-823,-850,-875,-902,-935,-970,-1006,-1038,-1064,-1085,-1101,-1118,-1137,-1157,-1178,
+-1197,-1213,-1226,-1236,-1248,-1263,-1279,-1293,-1304,-1311,-1318,-1324,-1331,-1337,-1343,-1348,-1352,-1354,-1353,-1351,-1349,
+-1348,-1347,-1343,-1336,-1326,-1315,-1306,-1298,-1290,-1281,-1271,-1261,-1252,-1243,-1234,-1222,-1210,-1199,-1189,-1181,-1173,
+-1165,-1157,-1149,-1140,-1131,-1120,-1111,-1103,-1097,-1090,-1081,-1071,-1061,-1052,-1041,-1030,-1019,-1010,-1001,-991,-980,
+-971,-967,-965,-959,-949,-937,-927,-922,-918,-914,-909,-904,-899,-893,-887,-879,-869,-857,-844,-832,-822,
+-813,-804,-795,-788,-782,-774,-762,-748,-734,-720,-703,-684,-666,-654,-650,-650,-650,-648,-643,-637,-630,
+-620,-608,-596,-588,-582,-578,-575,-572,-569,-564,-555,-542,-531,-524,-521,-516,-508,-498,-488,-478,-465,
+-451,-437,-429,-427,-427,-424,-417,-408,-398,-388,-379,-373,-373,-377,-379,-372,-355,-336,-322,-316,-315,
+-311,-303,-294,-286,-279,-273,-270,-266,-259,-245,-229,-216,-208,-199,-185,-166,-148,-135,-125,-115,-103,
+-92,-80,-69,-58,-46,-35,-22,-8,3,15,27,42,59,75,89,101,113,123,131,137,144,
+156,170,185,198,210,224,242,262,279,286,285,284,290,307,325,339,349,363,385,408,424,
+433,441,451,460,467,475,491,517,550,583,613,640,663,681,694,708,727,755,790,826,861,
+892,924,961,1002,1045,1088,1127,1164,1201,1238,1269,1294,1317,1346,1388,1438,1483,1514,1531,1549,1581,
+1630,1683,1717,1728,1727,1719,1682,1580,1421,1294,1333,1602,2024,2445,2760,2987,3206,3440,3640,3767,3853,
+3955,4059,4071,3916,3635,3347,3143,3026,2964,2942,2960,2984,2954,2848,2715,2626,2597,2583,2541,2473,2417,
+2395,2394,2394,2393,2395,2392,2371,2330,2281,2236,2196,2155,2110,2069,2036,2004,1967,1926,1887,1851,1815,
+1772,1721,1666,1612,1555,1490,1418,1343,1271,1194,1108,1015,931,871,834,807,779,753,734,726,724,
+727,732,736,728,703,666,634,613,604,598,589,576,558,528,477,396,292,184,102,64,60,
+61,38,-18,-105,-217,-348,-482,-590,-650,-665,-668,-693,-754,-839,-925,-994,-1036,-1053,-1048,-1032,-1022,
+-1030,-1052,-1078,-1098,-1114,-1132,-1151,-1158,-1148,-1129,-1114,-1106,-1093,-1065,-1030,-1004,-993,-983,-957,-911,-856,
+-807,-767,-728,-689,-650,-615,-582,-548,-509,-466,-422,-386,-363,-349,-333,-309,-280,-251,-226,-199,-167,
+-136,-115,-106,-102,-95,-81,-68,-60,-58,-54,-45,-30,-11,8,27,45,61,73,84,97,114,
+135,155,173,190,211,237,265,290,312,333,356,383,412,438,460,481,503,528,554,578,597,
+614,633,656,681,704,723,740,760,784,812,839,863,884,906,929,952,975,998,1020,1045,1071,
+1096,1120,1142,1163,1185,1206,1225,1244,1266,1296,1331,1365,1391,1405,1410,1413,1415,1416,1414,1411,1411,
+1415,1420,1424,1426,1430,1438,1446,1453,1458,1463,1471,1480,1489,1497,1506,1514,1524,1536,1552,1571,1590,
+1607,1622,1639,1656,1672,1684,1695,1709,1729,1753,1776,1795,1811,1829,1850,1876,1903,1929,1952,1973,1992,
+2010,2026,2047,2074,2085,2114,2145,2177,2208,2239,2268,2296,2324,2356,2393,2436,2475,2497,2489,2451,2402,
+2368,2364,2382,2401,2407,2411,2426,2453,2477,2482,2473,2464,2463,2468,2472,2477,2488,2501,2512,2519,2527,
+2539,2551,2554,2550,2548,2551,2561,2573,2592,2623,2665,2714,2766,2813,2849,2872,2895,2937,3008,3086,3141,
+3157,3154,3162,3192,3227,3248,3251,3240,3219,3187,3156,3146,3167,3206,3238,3243,3225,3191,3148,3099,3052,
+3018,3007,3018,3048,3087,3117,3124,3112,3112,3150,3219,3278,3288,3249,3192,3143,3102,3056,3009,2981,2985,
+3010,3031,3034,3028,3027,3036,3045,3044,3043,3069,3140,3236,3308,3313,3256,3175,3100,3024,2926,2815,2725,
+2676,2638,2568,2469,2391,2375,2392,2362,2235,2045,1874,1780,1757,1760,1755,1737,1714,1692,1665,1632,1594,
+1556,1521,1482,1426,1341,1232,1125,1049,1009,984,952,909,869,846,841,842,846,856,878,908,939,
+964,981,991,994,992,985,973,951,911,855,806,796,847,950,1066,1154,1198,1210,1213,1222,1232,
+1233,1224,1209,1198,1192,1193,1199,1207,1209,1190,1140,1062,973,894,838,799,769,744,727,718,713,
+708,701,693,686,678,676,684,702,724,741,750,757,765,771,773,774,773,770,760,745,730,
+717,705,690,679,679,687,688,678,669,681,715,745,747,722,700,711,754,809,852,877,887,
+886,873,850,827,816,818,824,825,815,795,768,735,701,678,672,676,672,653,626,603,583,
+556,511,458,415,390,376,359,332,299,263,229,197,168,143,117,89,59,30,0,-30,-63,
+-96,-126,-156,-189,-226,-268,-312,-359,-408,-459,-512,-565,-616,-664,-711,-759,-812,-866,-916,-959,-1001,
+-1046,-1096,-1149,-1205,-1263,-1321,-1374,-1420,-1455,-1484,-1513,-1548,-1595,-1653,-1714,-1771,-1820,-1861,-1898,-1932,-1964,
+-1999,-2038,-2082,-2127,-2171,-2210,-2245,-2280,-2317,-2355,-2391,-2421,-2448,-2478,-2514,-2551,-2585,-2620,-2664,-2715,-2762,
+-2800,-2846,-2912,-2990,-3047,-3065,-3066,-3098,-3180,-3280,-3350,-3375,-3380,-3398,-3432,-3463,-3479,-3489,-3504,-3528,-3553,
+-3580,-3611,-3645,-3671,-3686,-3699,-3719,-3743,-3760,-3765,-3769,-3785,-3810,-3829,-3837,-3834,-3815,-3770,-3700,-3634,-3617,
+-3669,-3768,-3864,-3924,-3944,-3938,-3924,-3910,-3901,-3899,-3896,-3884,-3865,-3843,-3822,-3799,-3777,-3765,-3771,-3789,-3802,
+-3805,-3809,-3823,-3843,-3854,-3853,-3853,-3868,-3890,-3902,-3896,-3884,-3885,-3902,-3927,-3943,-3945,-3934,-3922,-3915,-3912,
+-3899,-3873,-3839,-3810,-3788,-3763,-3727,-3680,-3625,-3559,-3473,-3366,-3251,-3134,-3014,-2890,-2768,-2655,-2541,-2411,-2274,
+-2170,-2132,-2145,-2158,-2131,-2078,-2035,-2021,-2020,-2008,-1985,-1965,-1955,-1952,-1952,-1954,-1952,-1935,-1902,-1864,-1838,
+-1825,-1806,-1768,-1713,-1659,-1621,-1601,-1590,-1574,-1542,-1496,-1453,-1425,-1412,-1400,-1380,-1361,-1356,-1364,-1372,-1371,
+-1366,-1366,-1365,-1352,-1324,-1291,-1266,-1250,-1238,-1228,-1226,-1232,-1240,-1242,-1236,-1222,-1198,-1164,-1122,-1076,-1025,
+-972,-921,-883,-859,-832,-781,-694,-579,-447,-303,-149,4,138,238,305,353,394,433,471,514,568,
+633,699,751,786,815,852,902,953,996,1032,1074,1130,1196,1262,1321,1371,1416,1459,1503,1553,1614,
+1682,1751,1813,1871,1929,1989,2051,2113,2174,2234,2292,2349,2408,2474,2548,2622,2686,2735,2774,2813,2856,
+2900,2935,2960,2983,3014,3060,3114,3168,3216,3255,3283,3302,3323,3358,3409,3466,3521,3577,3644,3724,3806,
+3878,3940,3998,4040,4049,4024,3992,3982,3994,3990,3925,3791,3627,3499,3464,3536,3662,3749,3722,3594,3454,
+3390,3419,3485,3536,3569,3606,3645,3663,3650,3634,3649,3690,3728,3747,3761,3792,3838,3888,3933,3978,4021,
+4050,4063,4072,4091,4121,4144,4153,4148,4136,4117,4091,4062,4037,4024,4028,4059,4113,4170,4210,4237,4278,
+4354,4450,4525,4559,4571,4591,4628,4665,4684,4687,4693,4715,4749,4785,4809,4820,4824,4828,4835,4836,4827,
+4818,4822,4841,4863,4879,4887,4889,4883,4867,4846,4834,4832,4830,4816,4796,4780,4773,4767,4758,4749,4742,
+4734,4721,4711,4712,4723,4731,4729,4721,4722,4739,4779,4839,4896,4916,4885,4836,4815,4818,4780,4649,4455,
+4267,4090,3828,3402,2885,2484,2367,2518,2776,3003,3172,3324,3461,3530,3493,3381,3260,3175,3122,3077,3030,
+2979,2927,2870,2805,2735,2663,2590,2516,2444,2374,2308,2244,2181,2115,2048,1981,1919,1861,1808,1759,1719,
+1684,1643,1586,1516,1451,1404,1371,1339,1305,1273,1247,1218,1180,1133,1085,1038,991,944,903,873,848,
+817,779,743,714,687,659,626,592,556,518,482,456,435,405,360,312,274,247,218,180,144,
+120,106,89,62,38,23,13,-2,-22,-39,-47,-57,-77,-103,-125,-137,-141,-139,-128,-111,-98,
+-101,-117,-138,-158,-180,-207,-239,-270,-299,-324,-344,-359,-372,-388,-403,-412,-416,-425,-442,-460,-470,
+-474,-485,-508,-529,-527,-499,-461,-438,-437,-454,-479,-509,-540,-570,-601,-639,-685,-735,-776,-805,-826,
+-848,-877,-912,-949,-987,-1022,-1052,-1075,-1093,-1111,-1129,-1147,-1164,-1181,-1198,-1213,-1227,-1241,-1258,-1275,-1289,
+-1300,-1309,-1317,-1325,-1332,-1340,-1348,-1354,-1358,-1358,-1356,-1354,-1354,-1355,-1354,-1351,-1344,-1333,-1320,-1309,-1302,
+-1297,-1291,-1282,-1271,-1262,-1254,-1246,-1236,-1224,-1213,-1202,-1194,-1185,-1176,-1167,-1157,-1148,-1138,-1129,-1120,-1113,
+-1107,-1100,-1092,-1083,-1074,-1066,-1056,-1045,-1034,-1023,-1012,-1000,-989,-982,-981,-982,-978,-969,-957,-947,-940,
+-935,-931,-928,-925,-922,-917,-910,-903,-894,-883,-871,-859,-848,-837,-826,-816,-808,-802,-793,-779,-765,
+-753,-745,-736,-720,-700,-682,-673,-673,-676,-676,-671,-663,-654,-644,-631,-618,-607,-602,-599,-598,-595,
+-591,-584,-574,-564,-556,-552,-548,-541,-531,-521,-513,-505,-493,-479,-467,-460,-458,-457,-453,-448,-442,
+-433,-421,-408,-400,-400,-405,-406,-397,-378,-358,-345,-340,-337,-333,-325,-316,-306,-297,-290,-287,-284,
+-277,-263,-246,-230,-219,-207,-193,-176,-161,-150,-140,-128,-113,-99,-87,-77,-67,-56,-43,-29,-14,
+-1,9,20,34,50,68,85,101,116,129,138,145,151,161,175,192,208,219,229,242,258,
+274,281,281,279,285,299,314,327,342,361,381,396,406,417,431,444,449,448,452,469,498,
+530,558,583,609,631,645,654,665,689,724,765,803,835,866,901,942,983,1020,1053,1086,1123,
+1163,1202,1236,1265,1293,1323,1362,1409,1458,1499,1526,1547,1579,1626,1674,1705,1716,1717,1707,1652,1526,
+1368,1294,1421,1761,2197,2578,2845,3051,3273,3509,3689,3773,3798,3826,3858,3833,3703,3497,3286,3111,2967,
+2851,2792,2809,2871,2906,2870,2788,2710,2655,2602,2531,2456,2407,2392,2392,2391,2387,2385,2380,2360,2322,
+2273,2224,2177,2133,2092,2057,2023,1984,1939,1894,1857,1824,1787,1743,1694,1648,1600,1544,1473,1396,1323,
+1256,1184,1100,1013,941,892,860,832,807,793,793,796,793,786,784,782,767,733,694,670,663,
+657,639,615,603,603,589,528,413,274,161,107,107,124,123,91,31,-50,-159,-294,-438,-558,
+-629,-658,-678,-717,-785,-866,-942,-1003,-1044,-1065,-1063,-1048,-1033,-1032,-1046,-1064,-1077,-1085,-1094,-1103,-1103,
+-1091,-1076,-1071,-1076,-1075,-1053,-1017,-986,-969,-958,-936,-895,-843,-790,-740,-695,-653,-615,-583,-553,-521,
+-486,-448,-408,-371,-341,-316,-291,-259,-222,-188,-161,-140,-123,-109,-98,-88,-71,-45,-18,-3,-5,
+-14,-16,-2,20,44,62,77,92,105,114,120,129,147,171,193,210,222,237,259,284,308,
+330,353,379,407,435,460,483,505,528,551,575,599,623,645,666,689,712,735,753,770,789,
+812,839,866,888,908,928,950,973,996,1018,1039,1062,1087,1112,1136,1157,1178,1199,1221,1243,1262,
+1282,1304,1333,1363,1388,1404,1413,1418,1423,1426,1424,1420,1417,1419,1423,1427,1429,1431,1436,1443,1449,
+1455,1462,1471,1481,1492,1502,1513,1523,1532,1542,1556,1572,1589,1604,1620,1638,1656,1670,1680,1690,1707,
+1729,1751,1768,1782,1798,1822,1851,1881,1909,1935,1958,1980,1999,2017,2037,2059,2085,2096,2122,2150,2180,
+2211,2243,2275,2311,2348,2385,2419,2451,2478,2489,2475,2434,2384,2351,2347,2364,2380,2386,2390,2407,2435,
+2459,2466,2458,2450,2449,2454,2460,2465,2474,2487,2501,2515,2529,2545,2558,2564,2564,2563,2565,2572,2584,
+2605,2634,2673,2721,2774,2823,2857,2873,2889,2934,3014,3103,3159,3166,3147,3142,3165,3201,3225,3227,3211,
+3182,3146,3117,3112,3138,3180,3212,3215,3192,3154,3114,3081,3057,3042,3034,3040,3067,3108,3145,3154,3141,
+3138,3176,3247,3306,3312,3268,3204,3148,3101,3057,3019,3003,3016,3042,3061,3065,3064,3068,3075,3075,3061,
+3051,3077,3159,3274,3367,3383,3315,3199,3075,2957,2841,2738,2673,2646,2621,2557,2462,2392,2382,2399,2363,
+2232,2043,1879,1795,1778,1786,1784,1769,1749,1724,1693,1658,1626,1599,1570,1524,1449,1346,1232,1135,1074,
+1046,1029,1003,967,934,913,906,904,907,918,940,971,1000,1022,1035,1043,1048,1049,1045,1031,1004,
+961,911,879,889,952,1053,1155,1227,1264,1277,1282,1283,1279,1268,1259,1257,1261,1268,1275,1285,1296,
+1298,1280,1232,1158,1072,991,927,880,844,815,794,784,783,786,784,777,770,770,780,798,817,
+831,839,843,848,852,853,851,845,840,831,816,796,776,761,752,744,740,744,755,762,760,
+758,769,800,834,848,835,815,817,852,903,945,963,958,939,915,889,869,867,885,912,928,
+918,883,833,788,761,756,763,765,748,713,672,637,607,573,533,496,471,456,439,413,378,
+341,308,278,250,226,202,177,149,117,84,50,14,-19,-50,-79,-108,-140,-176,-213,-253,-296,
+-341,-389,-439,-491,-543,-593,-640,-688,-738,-788,-833,-875,-918,-967,-1022,-1079,-1135,-1190,-1245,-1294,-1335,
+-1369,-1401,-1438,-1483,-1538,-1599,-1658,-1709,-1749,-1782,-1814,-1849,-1887,-1928,-1971,-2016,-2062,-2104,-2141,-2174,-2208,
+-2247,-2290,-2329,-2361,-2387,-2415,-2451,-2492,-2535,-2581,-2632,-2684,-2724,-2754,-2790,-2849,-2923,-2980,-2998,-2997,-3024,
+-3102,-3204,-3283,-3320,-3333,-3352,-3384,-3411,-3425,-3434,-3449,-3471,-3493,-3513,-3536,-3563,-3586,-3600,-3612,-3632,-3658,
+-3677,-3689,-3703,-3730,-3766,-3795,-3807,-3801,-3777,-3726,-3651,-3581,-3561,-3613,-3715,-3820,-3893,-3926,-3928,-3915,-3900,
+-3892,-3891,-3891,-3882,-3865,-3846,-3825,-3800,-3772,-3758,-3769,-3794,-3814,-3820,-3825,-3841,-3861,-3870,-3863,-3858,-3870,
+-3894,-3911,-3910,-3901,-3900,-3911,-3927,-3939,-3943,-3943,-3944,-3947,-3945,-3930,-3898,-3860,-3827,-3803,-3778,-3747,-3711,
+-3671,-3619,-3546,-3449,-3340,-3228,-3111,-2986,-2859,-2740,-2623,-2493,-2357,-2251,-2210,-2220,-2232,-2209,-2160,-2121,-2110,
+-2111,-2103,-2082,-2057,-2036,-2014,-1995,-1985,-1981,-1972,-1948,-1917,-1897,-1890,-1881,-1855,-1810,-1759,-1714,-1682,-1661,
+-1643,-1616,-1575,-1528,-1489,-1466,-1449,-1433,-1422,-1425,-1441,-1457,-1461,-1455,-1446,-1432,-1408,-1374,-1344,-1329,-1328,
+-1329,-1326,-1325,-1329,-1336,-1337,-1328,-1309,-1280,-1242,-1196,-1144,-1088,-1035,-988,-950,-912,-856,-768,-649,-510,
+-364,-217,-76,44,133,190,234,282,338,391,434,473,523,588,658,715,752,781,815,860,907,
+950,992,1041,1100,1164,1222,1270,1312,1353,1397,1444,1499,1562,1631,1700,1768,1834,1901,1968,2029,2084,
+2132,2179,2229,2285,2346,2411,2478,2546,2608,2660,2700,2734,2769,2805,2839,2870,2905,2950,3005,3062,3110,
+3149,3182,3208,3230,3252,3288,3340,3399,3454,3503,3558,3627,3704,3782,3856,3922,3971,3987,3970,3944,3935,
+3941,3927,3856,3718,3541,3387,3322,3382,3530,3662,3680,3570,3421,3339,3357,3424,3479,3509,3536,3569,3586,
+3580,3572,3593,3637,3676,3692,3703,3731,3779,3831,3875,3916,3952,3976,3987,3996,4021,4056,4083,4088,4074,
+4054,4037,4021,4003,3985,3975,3983,4014,4065,4117,4157,4189,4237,4315,4408,4487,4531,4550,4566,4592,4622,
+4643,4652,4656,4669,4697,4734,4765,4778,4778,4781,4791,4800,4795,4782,4782,4800,4823,4836,4836,4831,4826,
+4817,4806,4800,4802,4804,4797,4779,4761,4749,4743,4736,4729,4723,4716,4707,4703,4707,4715,4716,4708,4698,
+4698,4718,4760,4820,4872,4883,4845,4798,4784,4789,4744,4596,4376,4155,3937,3642,3212,2735,2406,2361,2555,
+2813,2999,3104,3194,3302,3395,3426,3385,3297,3194,3102,3035,2993,2961,2916,2851,2774,2700,2633,2566,2494,
+2422,2354,2290,2229,2169,2109,2049,1988,1928,1871,1817,1767,1723,1682,1637,1579,1511,1450,1407,1379,1351,
+1314,1274,1238,1205,1168,1125,1079,1035,991,947,909,878,849,815,777,743,714,685,651,615,581,
+547,509,472,443,420,391,348,302,267,244,219,182,144,118,103,85,59,32,17,9,0,
+-14,-29,-41,-55,-78,-107,-130,-143,-147,-146,-138,-124,-113,-113,-124,-141,-159,-181,-208,-241,-274,
+-304,-329,-347,-363,-380,-399,-415,-421,-419,-423,-440,-464,-483,-494,-507,-529,-553,-563,-555,-538,-523,
+-517,-521,-534,-551,-569,-584,-600,-628,-672,-721,-761,-785,-801,-823,-853,-890,-930,-969,-1005,-1036,-1060,
+-1080,-1101,-1121,-1139,-1154,-1170,-1186,-1202,-1218,-1233,-1250,-1267,-1282,-1294,-1305,-1314,-1322,-1328,-1334,-1342,-1350,
+-1355,-1355,-1355,-1356,-1358,-1359,-1358,-1353,-1345,-1334,-1321,-1311,-1306,-1304,-1300,-1292,-1281,-1271,-1264,-1258,-1251,
+-1242,-1231,-1219,-1207,-1197,-1188,-1180,-1171,-1161,-1151,-1141,-1132,-1124,-1117,-1110,-1102,-1094,-1085,-1075,-1066,-1056,
+-1045,-1033,-1021,-1008,-997,-991,-990,-992,-989,-982,-971,-962,-955,-949,-945,-942,-940,-937,-933,-927,-919,
+-911,-902,-892,-882,-872,-861,-849,-837,-829,-822,-814,-800,-783,-771,-767,-765,-756,-737,-716,-702,-700,
+-703,-703,-697,-687,-678,-668,-656,-642,-631,-624,-619,-614,-608,-604,-600,-594,-587,-580,-575,-570,-563,
+-552,-543,-536,-530,-522,-513,-503,-497,-491,-485,-478,-472,-467,-460,-447,-432,-422,-421,-424,-422,-411,
+-393,-376,-365,-360,-356,-349,-341,-331,-321,-312,-304,-300,-296,-288,-275,-258,-242,-229,-217,-205,-193,
+-182,-173,-162,-148,-133,-117,-104,-92,-81,-68,-53,-38,-23,-10,2,15,30,47,65,84,103,
+120,135,147,155,161,167,178,193,209,221,229,237,248,260,269,274,279,285,291,295,303,
+320,345,365,373,375,385,404,420,423,419,424,447,479,508,531,552,576,601,620,635,652,
+678,712,748,782,815,851,894,939,979,1011,1037,1068,1106,1147,1184,1216,1247,1279,1311,1347,1391,
+1443,1493,1531,1560,1594,1640,1684,1711,1720,1721,1700,1617,1463,1308,1291,1508,1918,2363,2702,2917,3100,
+3323,3565,3742,3804,3785,3740,3688,3609,3493,3362,3236,3106,2958,2816,2742,2766,2851,2916,2911,2849,2769,
+2692,2610,2524,2451,2409,2396,2392,2387,2381,2378,2370,2347,2306,2256,2205,2156,2111,2072,2039,2004,1961,
+1913,1868,1830,1796,1755,1709,1665,1627,1587,1531,1458,1377,1304,1237,1167,1089,1014,958,921,890,856,
+830,824,836,844,834,815,803,800,788,757,720,699,695,686,658,627,618,624,603,515,365,
+211,120,111,152,185,175,126,56,-26,-133,-269,-417,-543,-626,-670,-703,-750,-813,-881,-942,-992,
+-1030,-1056,-1062,-1051,-1033,-1022,-1023,-1030,-1038,-1042,-1045,-1046,-1042,-1032,-1024,-1022,-1023,-1013,-984,-946,-917,
+-907,-910,-907,-884,-841,-783,-717,-655,-606,-573,-550,-528,-501,-471,-437,-399,-357,-314,-276,-244,-211,
+-175,-137,-104,-83,-75,-74,-70,-52,-15,32,71,82,66,41,31,43,68,90,102,109,119,
+130,139,144,152,171,197,223,240,253,267,288,313,337,359,383,410,437,462,485,508,532,
+554,576,598,624,651,677,700,720,741,763,784,802,820,842,867,892,913,932,949,969,990,
+1011,1032,1053,1076,1101,1127,1153,1176,1198,1221,1246,1270,1293,1311,1327,1346,1369,1391,1408,1418,1424,
+1427,1428,1426,1423,1420,1421,1425,1429,1433,1436,1440,1446,1453,1461,1469,1478,1487,1497,1508,1520,1530,
+1537,1544,1554,1568,1583,1597,1612,1630,1649,1665,1678,1693,1713,1735,1752,1764,1776,1797,1826,1857,1885,
+1912,1939,1968,1994,2014,2032,2051,2073,2096,2106,2129,2156,2186,2217,2248,2281,2320,2364,2408,2442,2463,
+2469,2459,2431,2393,2357,2336,2336,2349,2363,2374,2386,2406,2429,2448,2453,2450,2445,2445,2449,2454,2460,
+2469,2482,2498,2516,2535,2553,2566,2573,2574,2575,2577,2584,2599,2619,2645,2678,2721,2774,2826,2861,2875,
+2890,2937,3021,3114,3171,3174,3145,3124,3133,3162,3190,3202,3198,3180,3154,3131,3126,3144,3174,3196,3195,
+3173,3139,3106,3082,3067,3054,3041,3036,3055,3098,3144,3166,3161,3159,3192,3252,3299,3297,3248,3183,3128,
+3087,3053,3030,3026,3042,3064,3078,3082,3086,3097,3105,3100,3078,3064,3091,3183,3318,3436,3474,3408,3267,
+3097,2935,2797,2699,2649,2633,2613,2559,2485,2433,2423,2418,2355,2211,2030,1882,1807,1791,1797,1799,1793,
+1778,1754,1721,1688,1664,1648,1624,1571,1479,1361,1244,1156,1108,1087,1073,1052,1026,1004,988,977,968,
+967,977,1000,1028,1054,1073,1085,1094,1100,1103,1099,1084,1053,1012,976,966,998,1072,1165,1247,1300,
+1325,1337,1345,1346,1336,1319,1310,1317,1335,1352,1362,1367,1367,1360,1338,1296,1234,1158,1080,1010,955,
+916,887,866,856,856,860,861,859,860,872,895,918,931,935,934,934,936,937,934,927,918,
+908,893,875,852,831,817,812,811,813,816,824,835,844,852,864,889,923,951,956,940,926,
+935,967,1000,1013,1001,976,953,939,935,944,964,988,997,977,931,875,832,814,816,823,816,
+785,739,693,658,631,603,575,551,534,518,492,457,421,390,363,335,307,280,257,232,203,
+170,134,98,62,29,0,-31,-62,-95,-127,-160,-195,-234,-276,-319,-364,-415,-470,-523,-571,-616,
+-662,-708,-752,-795,-842,-896,-954,-1011,-1065,-1116,-1165,-1209,-1247,-1282,-1321,-1368,-1424,-1484,-1544,-1598,-1640,
+-1672,-1700,-1732,-1771,-1816,-1863,-1910,-1956,-2000,-2039,-2073,-2104,-2137,-2174,-2216,-2257,-2292,-2322,-2353,-2387,-2424,
+-2464,-2510,-2563,-2617,-2661,-2692,-2726,-2781,-2852,-2912,-2937,-2939,-2959,-3024,-3121,-3207,-3256,-3279,-3300,-3330,-3358,
+-3375,-3386,-3401,-3418,-3431,-3441,-3454,-3475,-3495,-3509,-3522,-3542,-3571,-3598,-3621,-3646,-3681,-3721,-3752,-3765,-3759,
+-3735,-3687,-3619,-3558,-3542,-3590,-3682,-3779,-3849,-3886,-3894,-3887,-3876,-3873,-3878,-3882,-3876,-3860,-3844,-3827,-3806,
+-3781,-3768,-3779,-3804,-3823,-3828,-3834,-3852,-3874,-3883,-3874,-3864,-3871,-3891,-3906,-3909,-3905,-3905,-3913,-3921,-3929,
+-3936,-3945,-3956,-3964,-3965,-3953,-3927,-3892,-3858,-3827,-3796,-3762,-3729,-3699,-3662,-3605,-3526,-3434,-3334,-3222,-3095,
+-2962,-2838,-2720,-2596,-2469,-2369,-2324,-2324,-2323,-2292,-2244,-2211,-2204,-2205,-2193,-2167,-2142,-2118,-2087,-2050,-2023,
+-2012,-2007,-1992,-1968,-1948,-1943,-1943,-1933,-1905,-1862,-1813,-1766,-1726,-1698,-1671,-1638,-1595,-1554,-1525,-1508,-1498,
+-1496,-1505,-1522,-1536,-1538,-1528,-1514,-1498,-1478,-1454,-1436,-1432,-1436,-1439,-1434,-1426,-1423,-1424,-1422,-1411,-1388,
+-1353,-1306,-1248,-1184,-1122,-1068,-1023,-978,-920,-833,-717,-580,-440,-305,-179,-67,23,85,128,173,233,
+301,361,402,434,474,533,601,665,716,759,799,838,877,915,959,1013,1072,1129,1178,1219,1258,
+1300,1347,1399,1458,1523,1592,1664,1736,1808,1879,1945,2002,2049,2088,2128,2176,2232,2293,2352,2409,2466,
+2527,2584,2630,2663,2693,2726,2764,2803,2845,2895,2955,3015,3064,3098,3123,3144,3165,3190,3228,3280,3339,
+3391,3432,3474,3529,3601,3680,3761,3836,3891,3912,3901,3879,3868,3865,3840,3761,3619,3440,3280,3206,3256,
+3402,3545,3585,3500,3367,3287,3297,3354,3404,3432,3457,3486,3505,3510,3522,3560,3612,3644,3648,3647,3671,
+3720,3773,3815,3851,3885,3911,3924,3935,3957,3990,4014,4016,3998,3974,3956,3945,3936,3929,3929,3942,3974,
+4020,4069,4110,4148,4196,4271,4366,4461,4532,4566,4570,4565,4569,4585,4606,4621,4633,4654,4688,4721,4735,
+4733,4735,4749,4762,4758,4742,4740,4761,4791,4803,4794,4778,4771,4770,4766,4760,4758,4761,4760,4750,4737,
+4727,4721,4717,4711,4703,4695,4690,4689,4694,4697,4694,4683,4673,4675,4698,4746,4808,4853,4852,4806,4761,
+4753,4759,4701,4535,4292,4038,3779,3449,3021,2595,2347,2375,2603,2857,3010,3066,3101,3169,3263,3339,3359,
+3309,3201,3078,2987,2947,2929,2895,2828,2748,2676,2612,2545,2470,2397,2332,2272,2213,2156,2102,2047,1990,
+1930,1874,1821,1770,1722,1676,1628,1570,1505,1446,1405,1381,1355,1317,1269,1226,1189,1153,1113,1071,1030,
+988,948,911,879,847,810,771,736,707,678,644,607,571,536,497,459,428,403,375,335,293,
+261,241,219,185,147,119,103,86,61,33,12,2,-5,-17,-30,-43,-60,-84,-112,-134,-147,
+-152,-150,-144,-135,-128,-129,-137,-149,-164,-182,-205,-234,-266,-298,-327,-348,-365,-382,-402,-421,-429,
+-428,-431,-447,-471,-489,-497,-503,-516,-538,-559,-574,-581,-583,-584,-586,-595,-609,-622,-626,-627,-640,
+-671,-712,-746,-766,-778,-796,-825,-863,-907,-951,-990,-1020,-1043,-1064,-1087,-1109,-1128,-1145,-1163,-1181,-1198,
+-1213,-1226,-1242,-1259,-1275,-1289,-1301,-1311,-1319,-1324,-1329,-1335,-1344,-1350,-1352,-1353,-1356,-1359,-1359,-1356,-1350,
+-1343,-1334,-1323,-1314,-1309,-1307,-1304,-1297,-1287,-1279,-1273,-1269,-1264,-1257,-1247,-1234,-1220,-1207,-1197,-1190,-1182,
+-1172,-1161,-1150,-1140,-1131,-1122,-1115,-1109,-1100,-1090,-1079,-1068,-1060,-1051,-1041,-1030,-1018,-1008,-1001,-997,-996,
+-994,-989,-980,-972,-966,-961,-957,-953,-950,-947,-943,-938,-932,-924,-915,-905,-897,-890,-881,-869,-857,
+-848,-843,-837,-824,-807,-794,-790,-790,-785,-769,-748,-734,-731,-733,-731,-722,-710,-700,-691,-679,-667,
+-656,-650,-643,-634,-625,-619,-617,-615,-610,-602,-594,-588,-582,-573,-565,-558,-554,-549,-544,-538,-532,
+-524,-513,-501,-493,-487,-481,-471,-457,-447,-444,-443,-437,-424,-409,-396,-388,-382,-375,-367,-358,-349,
+-339,-329,-320,-313,-307,-299,-288,-274,-260,-247,-235,-225,-216,-207,-196,-184,-171,-157,-144,-130,-115,
+-99,-81,-64,-48,-34,-22,-9,6,24,43,62,82,103,121,136,147,155,161,166,172,182,
+196,210,219,226,231,239,247,259,271,279,278,273,276,296,325,346,350,348,357,377,395,
+399,398,408,436,471,500,521,542,565,589,611,632,657,685,713,742,771,804,844,890,938,
+981,1015,1046,1080,1118,1155,1184,1209,1238,1273,1310,1346,1388,1439,1491,1531,1564,1601,1649,1692,1715,
+1721,1714,1676,1567,1394,1257,1304,1605,2070,2516,2817,2995,3161,3381,3615,3776,3821,3775,3682,3563,3432,
+3317,3242,3190,3112,2981,2836,2751,2761,2827,2877,2874,2827,2761,2685,2599,2513,2448,2414,2399,2389,2380,
+2375,2372,2360,2329,2282,2230,2180,2132,2086,2045,2009,1972,1930,1885,1844,1807,1769,1725,1678,1638,1606,
+1572,1521,1450,1370,1296,1227,1157,1086,1026,984,955,920,878,848,846,864,874,857,827,808,805,
+798,771,732,703,689,675,652,631,625,616,563,438,275,144,103,145,209,231,193,116,31,
+-55,-157,-284,-423,-545,-631,-686,-729,-775,-826,-874,-916,-951,-984,-1011,-1026,-1023,-1007,-989,-980,-983,
+-992,-1000,-1003,-1000,-995,-988,-980,-968,-947,-915,-877,-846,-833,-841,-861,-877,-874,-841,-780,-700,-623,
+-568,-539,-525,-509,-485,-458,-427,-389,-342,-289,-242,-206,-176,-141,-97,-54,-23,-12,-13,-9,16,
+67,128,171,178,151,114,94,99,117,130,132,131,136,148,160,169,177,193,216,240,259,
+275,294,318,345,370,393,418,445,470,492,513,536,561,584,606,627,653,681,707,729,747,
+766,789,811,831,848,868,891,915,937,955,972,991,1011,1033,1053,1074,1096,1121,1146,1172,1196,
+1220,1244,1270,1296,1320,1338,1352,1366,1383,1404,1422,1432,1434,1431,1427,1425,1423,1421,1422,1427,1434,
+1441,1447,1453,1459,1466,1474,1482,1489,1495,1502,1511,1522,1530,1535,1539,1548,1562,1577,1591,1605,1622,
+1640,1658,1676,1696,1720,1741,1757,1769,1787,1813,1842,1867,1887,1910,1942,1978,2009,2031,2048,2065,2085,
+2106,2115,2136,2161,2191,2224,2257,2293,2335,2383,2428,2458,2465,2446,2408,2366,2335,2323,2327,2337,2347,
+2357,2372,2390,2409,2422,2429,2433,2436,2439,2442,2445,2451,2461,2473,2487,2503,2522,2542,2559,2570,2575,
+2577,2581,2587,2599,2616,2635,2656,2681,2718,2770,2822,2859,2874,2888,2933,3016,3109,3171,3180,3151,3120,
+3111,3128,3156,3183,3201,3206,3199,3188,3183,3189,3198,3201,3194,3177,3155,3133,3115,3098,3077,3050,3029,
+3035,3076,3133,3173,3184,3187,3208,3246,3271,3254,3201,3140,3096,3072,3060,3055,3061,3075,3088,3094,3095,
+3102,3116,3127,3121,3099,3086,3120,3221,3371,3511,3575,3531,3392,3204,3014,2858,2753,2700,2675,2647,2601,
+2548,2512,2489,2444,2342,2186,2021,1896,1829,1807,1805,1810,1812,1806,1787,1759,1735,1723,1714,1688,1624,
+1517,1388,1272,1193,1154,1136,1120,1101,1085,1074,1063,1047,1032,1027,1037,1057,1080,1101,1118,1131,1140,
+1146,1149,1144,1128,1098,1066,1049,1063,1116,1197,1280,1342,1373,1383,1390,1401,1409,1404,1390,1383,1392,
+1411,1426,1430,1424,1413,1398,1375,1340,1291,1227,1154,1085,1030,993,968,948,936,933,937,941,945,
+955,977,1006,1027,1035,1033,1031,1030,1029,1023,1015,1005,992,977,958,939,919,901,888,885,891,
+897,898,901,913,933,953,966,981,1009,1043,1059,1045,1012,994,1006,1035,1051,1042,1020,1006,1007,
+1017,1026,1031,1029,1015,984,939,894,863,849,846,840,821,787,749,717,694,674,653,631,611,
+593,571,539,503,473,449,425,395,361,329,304,280,251,216,179,145,113,84,53,20,-13,
+-45,-74,-103,-136,-173,-212,-250,-291,-340,-395,-450,-498,-540,-583,-627,-673,-720,-772,-829,-889,-944,
+-994,-1040,-1083,-1123,-1160,-1201,-1249,-1306,-1367,-1427,-1482,-1528,-1564,-1592,-1620,-1656,-1701,-1752,-1802,-1849,-1894,
+-1935,-1972,-2004,-2034,-2065,-2100,-2138,-2177,-2217,-2255,-2290,-2322,-2351,-2380,-2417,-2464,-2518,-2568,-2607,-2647,-2703,
+-2779,-2849,-2887,-2895,-2905,-2952,-3034,-3121,-3180,-3214,-3240,-3275,-3311,-3339,-3356,-3365,-3369,-3369,-3370,-3381,-3401,
+-3422,-3437,-3448,-3468,-3500,-3536,-3568,-3599,-3634,-3672,-3703,-3720,-3721,-3701,-3657,-3597,-3547,-3540,-3585,-3663,-3742,
+-3800,-3836,-3852,-3856,-3855,-3858,-3866,-3872,-3866,-3853,-3841,-3833,-3820,-3802,-3792,-3799,-3817,-3828,-3829,-3834,-3854,
+-3879,-3892,-3887,-3878,-3881,-3891,-3898,-3898,-3899,-3905,-3914,-3921,-3926,-3936,-3948,-3960,-3967,-3969,-3964,-3950,-3925,
+-3895,-3861,-3824,-3786,-3751,-3723,-3694,-3653,-3595,-3526,-3446,-3347,-3224,-3086,-2952,-2828,-2707,-2595,-2512,-2474,-2463,
+-2439,-2382,-2318,-2282,-2278,-2277,-2256,-2222,-2194,-2172,-2142,-2098,-2058,-2039,-2036,-2030,-2013,-1995,-1989,-1992,-1992,
+-1979,-1950,-1908,-1856,-1803,-1759,-1727,-1698,-1666,-1632,-1604,-1589,-1584,-1586,-1591,-1597,-1598,-1591,-1577,-1564,-1557,
+-1552,-1548,-1547,-1551,-1557,-1558,-1550,-1537,-1527,-1520,-1509,-1491,-1460,-1416,-1359,-1292,-1222,-1158,-1106,-1059,-1002,
+-921,-808,-673,-535,-407,-293,-193,-105,-34,21,72,131,202,274,333,373,403,438,484,540,601,
+663,721,772,811,846,884,933,990,1047,1096,1138,1177,1219,1265,1317,1375,1437,1502,1570,1641,1716,
+1789,1857,1913,1959,1998,2037,2083,2138,2201,2263,2314,2356,2400,2455,2514,2564,2600,2630,2666,2708,2749,
+2789,2836,2898,2965,3021,3055,3074,3087,3103,3127,3164,3217,3278,3334,3376,3414,3460,3521,3594,3672,3748,
+3805,3830,3822,3800,3784,3775,3743,3659,3516,3342,3195,3130,3176,3298,3417,3454,3394,3297,3238,3241,3278,
+3315,3346,3381,3419,3447,3465,3496,3550,3604,3626,3612,3599,3618,3667,3718,3755,3786,3822,3858,3883,3896,
+3909,3927,3943,3944,3929,3908,3889,3875,3867,3867,3876,3896,3929,3972,4021,4067,4106,4148,4211,4308,4429,
+4539,4599,4595,4551,4515,4516,4546,4579,4600,4619,4649,4681,4697,4696,4698,4712,4725,4717,4697,4694,4722,
+4760,4776,4760,4735,4721,4718,4715,4706,4702,4705,4712,4713,4707,4702,4699,4696,4689,4680,4672,4668,4668,
+4671,4672,4668,4661,4656,4663,4691,4744,4803,4836,4820,4770,4733,4732,4727,4643,4449,4186,3911,3620,3264,
+2845,2478,2315,2409,2660,2901,3034,3071,3081,3117,3186,3263,3307,3279,3177,3044,2943,2902,2889,2859,2796,
+2721,2655,2592,2520,2439,2366,2307,2255,2202,2147,2095,2042,1985,1924,1867,1815,1765,1715,1667,1620,1566,
+1504,1445,1403,1379,1355,1316,1264,1214,1175,1140,1103,1063,1023,984,946,909,874,841,804,764,726,
+695,665,631,594,558,522,485,448,416,388,358,322,285,258,240,219,187,150,121,105,91,
+69,40,16,0,-11,-24,-38,-53,-71,-93,-116,-136,-150,-156,-156,-151,-145,-141,-143,-149,-156,
+-165,-179,-199,-222,-251,-285,-321,-351,-373,-390,-409,-428,-440,-445,-450,-463,-482,-496,-501,-501,-507,
+-523,-545,-569,-589,-604,-612,-618,-630,-649,-666,-671,-668,-671,-689,-716,-740,-753,-761,-774,-797,-834,
+-881,-930,-974,-1005,-1027,-1047,-1069,-1091,-1110,-1129,-1151,-1175,-1196,-1210,-1223,-1239,-1257,-1274,-1287,-1300,-1312,
+-1321,-1326,-1329,-1335,-1342,-1348,-1351,-1352,-1354,-1355,-1355,-1352,-1349,-1346,-1339,-1330,-1320,-1313,-1309,-1306,-1300,
+-1293,-1286,-1280,-1273,-1267,-1262,-1255,-1243,-1227,-1212,-1202,-1196,-1189,-1179,-1166,-1154,-1143,-1132,-1122,-1114,-1108,
+-1100,-1090,-1078,-1068,-1061,-1054,-1047,-1038,-1029,-1020,-1011,-1004,-1000,-997,-994,-988,-982,-977,-973,-970,-965,
+-959,-954,-950,-946,-941,-934,-925,-915,-907,-901,-893,-884,-873,-865,-861,-857,-848,-834,-820,-814,-813,
+-808,-794,-775,-762,-759,-760,-756,-745,-733,-722,-713,-701,-688,-678,-674,-669,-661,-650,-642,-639,-638,
+-632,-622,-613,-606,-601,-594,-586,-580,-575,-571,-567,-562,-557,-550,-539,-527,-516,-510,-505,-497,-487,
+-478,-473,-467,-458,-444,-430,-419,-412,-404,-395,-386,-378,-370,-360,-349,-338,-330,-322,-315,-307,-297,
+-286,-272,-259,-248,-239,-228,-215,-200,-188,-177,-166,-152,-136,-117,-97,-76,-58,-45,-33,-20,-3,
+15,34,53,74,95,113,126,135,142,149,153,156,163,175,189,199,204,207,211,220,235,
+251,261,260,254,260,282,312,331,334,333,343,365,383,391,398,417,449,483,510,532,553,
+574,592,608,629,656,687,715,741,770,803,841,883,929,977,1023,1065,1104,1140,1168,1188,1206,
+1233,1271,1312,1352,1395,1444,1492,1529,1558,1595,1643,1685,1706,1706,1689,1633,1506,1335,1236,1352,1721,
+2222,2664,2948,3120,3288,3493,3683,3790,3795,3726,3608,3454,3296,3188,3158,3164,3127,3007,2850,2734,2698,
+2717,2740,2743,2729,2697,2641,2563,2488,2439,2420,2410,2395,2378,2366,2357,2338,2300,2250,2199,2151,2103,
+2054,2007,1967,1930,1895,1859,1823,1787,1748,1703,1657,1619,1587,1553,1508,1446,1374,1302,1232,1163,1099,
+1048,1014,985,946,900,868,867,887,897,877,841,817,811,803,773,725,681,655,644,640,640,
+634,595,494,341,191,114,134,209,265,251,171,64,-36,-126,-222,-331,-447,-552,-633,-694,-742,
+-783,-820,-850,-874,-897,-921,-946,-964,-968,-957,-939,-928,-933,-949,-964,-970,-969,-965,-961,-951,-926,
+-883,-835,-795,-776,-779,-797,-820,-840,-846,-824,-770,-692,-613,-555,-523,-505,-485,-458,-430,-401,-365,
+-318,-264,-214,-176,-144,-107,-60,-10,26,41,44,51,80,134,195,238,245,220,185,163,161,
+170,174,169,161,163,174,188,200,208,220,237,256,274,293,316,343,372,399,423,447,472,
+496,519,541,565,591,616,638,660,684,710,734,754,772,792,815,838,856,872,890,913,938,
+961,981,999,1020,1043,1066,1088,1109,1131,1153,1175,1197,1219,1241,1263,1286,1309,1332,1350,1364,1377,
+1394,1415,1435,1446,1445,1438,1432,1430,1431,1432,1434,1439,1448,1457,1464,1469,1472,1477,1483,1489,1493,
+1497,1502,1510,1519,1526,1530,1536,1547,1563,1579,1593,1605,1619,1635,1654,1676,1699,1724,1746,1764,1782,
+1804,1831,1854,1871,1886,1909,1944,1983,2016,2038,2056,2075,2095,2115,2124,2144,2167,2195,2228,2267,2312,
+2361,2409,2448,2467,2458,2418,2361,2310,2290,2303,2332,2353,2361,2365,2378,2397,2411,2414,2411,2414,2424,
+2435,2442,2446,2453,2466,2481,2496,2512,2531,2552,2567,2574,2576,2578,2584,2595,2610,2629,2648,2664,2683,
+2714,2761,2813,2849,2865,2878,2917,2994,3088,3159,3182,3162,3126,3103,3103,3124,3157,3191,3216,3231,3238,
+3244,3249,3248,3242,3232,3222,3211,3199,3183,3160,3127,3084,3046,3038,3071,3129,3182,3208,3217,3227,3241,
+3242,3211,3157,3106,3081,3079,3088,3096,3105,3114,3121,3123,3122,3126,3138,3146,3141,3124,3122,3168,3279,
+3434,3580,3661,3647,3539,3367,3176,3008,2888,2816,2770,2723,2673,2629,2594,2548,2461,2327,2170,2029,1929,
+1869,1838,1828,1832,1839,1837,1825,1811,1804,1803,1795,1759,1680,1562,1430,1316,1243,1209,1191,1172,1152,
+1140,1134,1125,1108,1093,1089,1099,1116,1131,1146,1162,1176,1184,1188,1191,1190,1178,1156,1134,1134,1169,
+1237,1321,1396,1443,1458,1456,1458,1471,1485,1488,1480,1473,1476,1485,1488,1481,1468,1454,1439,1416,1382,
+1337,1281,1219,1159,1113,1081,1057,1035,1018,1011,1014,1023,1034,1050,1075,1103,1122,1130,1133,1135,1135,
+1127,1113,1099,1088,1074,1055,1034,1017,1001,984,969,963,971,982,986,986,998,1026,1057,1073,1081,
+1097,1127,1145,1127,1080,1045,1048,1082,1108,1105,1084,1071,1076,1086,1085,1067,1038,1005,971,940,914,
+894,879,862,841,816,791,771,756,744,728,707,683,662,641,616,585,554,528,507,482,448,
+410,377,351,327,297,260,224,193,165,137,105,71,37,7,-20,-47,-79,-115,-150,-184,-221,
+-267,-320,-373,-419,-461,-503,-549,-598,-648,-703,-761,-820,-874,-921,-963,-1002,-1040,-1081,-1129,-1186,-1249,
+-1309,-1363,-1409,-1448,-1481,-1511,-1544,-1588,-1639,-1692,-1741,-1786,-1827,-1866,-1900,-1931,-1961,-1993,-2027,-2064,-2104,
+-2148,-2192,-2230,-2259,-2279,-2296,-2318,-2353,-2401,-2453,-2502,-2553,-2617,-2698,-2779,-2832,-2848,-2852,-2880,-2945,-3025,
+-3090,-3131,-3164,-3206,-3254,-3294,-3314,-3314,-3303,-3293,-3295,-3315,-3345,-3373,-3389,-3399,-3417,-3449,-3487,-3522,-3551,
+-3583,-3620,-3656,-3684,-3696,-3683,-3643,-3589,-3549,-3551,-3597,-3663,-3724,-3769,-3801,-3826,-3842,-3852,-3857,-3862,-3863,
+-3856,-3847,-3843,-3843,-3838,-3827,-3820,-3824,-3835,-3839,-3835,-3837,-3855,-3879,-3893,-3894,-3893,-3896,-3900,-3897,-3893,
+-3896,-3908,-3920,-3925,-3930,-3940,-3953,-3961,-3963,-3964,-3966,-3963,-3949,-3925,-3895,-3859,-3820,-3781,-3748,-3719,-3686,
+-3645,-3598,-3543,-3467,-3361,-3226,-3081,-2939,-2809,-2707,-2648,-2634,-2628,-2584,-2493,-2397,-2343,-2335,-2332,-2304,-2259,
+-2223,-2204,-2181,-2142,-2101,-2077,-2073,-2072,-2061,-2048,-2043,-2045,-2045,-2037,-2022,-1999,-1960,-1906,-1849,-1804,-1774,
+-1752,-1728,-1705,-1690,-1684,-1682,-1677,-1664,-1644,-1620,-1601,-1594,-1600,-1613,-1626,-1634,-1640,-1643,-1643,-1640,-1633,
+-1624,-1611,-1592,-1563,-1523,-1472,-1409,-1340,-1271,-1210,-1157,-1101,-1024,-919,-790,-652,-523,-411,-315,-232,-161,
+-99,-40,23,96,172,240,295,341,382,421,457,494,538,595,657,713,757,796,844,905,971,
+1029,1075,1114,1153,1196,1243,1298,1359,1426,1493,1560,1628,1703,1777,1840,1885,1917,1948,1991,2047,2113,
+2181,2239,2282,2313,2347,2395,2451,2503,2544,2581,2622,2667,2706,2738,2779,2839,2912,2973,3008,3022,3030,
+3042,3063,3097,3149,3215,3282,3337,3381,3426,3479,3542,3612,3680,3733,3755,3745,3721,3705,3698,3669,3582,
+3433,3260,3124,3074,3115,3208,3291,3316,3284,3232,3201,3198,3212,3236,3275,3329,3383,3418,3443,3484,3543,
+3591,3596,3568,3548,3569,3621,3670,3701,3726,3762,3808,3844,3862,3868,3873,3877,3877,3868,3851,3829,3808,
+3795,3795,3809,3834,3869,3915,3971,4026,4068,4100,4147,4237,4375,4520,4610,4608,4541,4473,4455,4487,4531,
+4559,4579,4606,4637,4657,4662,4668,4683,4694,4682,4658,4652,4681,4723,4741,4724,4694,4674,4666,4660,4651,
+4647,4654,4666,4672,4670,4667,4665,4663,4657,4650,4645,4644,4645,4644,4643,4641,4641,4644,4660,4697,4751,
+4800,4813,4781,4733,4709,4711,4680,4552,4323,4046,3764,3458,3086,2685,2384,2309,2463,2721,2937,3049,3084,
+3096,3113,3147,3194,3227,3209,3122,3000,2905,2864,2849,2816,2755,2688,2630,2569,2491,2405,2333,2282,2239,
+2189,2136,2085,2034,1977,1916,1860,1809,1759,1708,1661,1617,1568,1509,1449,1406,1382,1359,1321,1267,1214,
+1172,1136,1098,1057,1019,982,943,902,864,830,796,758,718,682,650,617,580,543,509,477,446,
+413,379,345,311,281,258,240,218,187,153,127,111,98,78,51,25,6,-9,-25,-43,-63,
+-83,-101,-119,-135,-150,-160,-164,-161,-156,-155,-157,-159,-159,-161,-170,-187,-207,-233,-267,-308,-349,
+-380,-403,-421,-440,-454,-464,-471,-483,-497,-509,-516,-519,-525,-537,-552,-571,-589,-605,-616,-624,-638,
+-659,-682,-697,-703,-707,-717,-732,-746,-754,-759,-768,-786,-819,-865,-914,-956,-986,-1007,-1028,-1051,-1071,
+-1087,-1105,-1130,-1159,-1185,-1203,-1217,-1235,-1254,-1270,-1283,-1295,-1307,-1319,-1326,-1329,-1333,-1339,-1344,-1347,-1348,
+-1349,-1350,-1350,-1350,-1351,-1350,-1346,-1338,-1327,-1320,-1315,-1310,-1305,-1299,-1291,-1281,-1270,-1260,-1254,-1248,-1239,
+-1225,-1210,-1201,-1197,-1191,-1183,-1172,-1160,-1148,-1135,-1122,-1112,-1106,-1098,-1088,-1077,-1069,-1065,-1060,-1055,-1048,
+-1041,-1033,-1024,-1015,-1008,-1005,-1003,-999,-995,-991,-989,-985,-979,-971,-964,-958,-953,-947,-940,-932,-924,
+-917,-910,-905,-897,-889,-880,-875,-871,-865,-855,-844,-837,-834,-828,-816,-799,-787,-783,-781,-775,-764,
+-752,-744,-735,-724,-710,-699,-694,-692,-687,-678,-669,-664,-660,-653,-643,-634,-627,-621,-614,-606,-599,
+-594,-589,-582,-576,-572,-568,-562,-552,-542,-534,-528,-521,-513,-505,-498,-490,-477,-463,-449,-439,-431,
+-421,-411,-402,-396,-388,-378,-366,-355,-347,-339,-331,-324,-318,-308,-295,-280,-268,-258,-247,-233,-218,
+-204,-194,-183,-170,-154,-136,-115,-94,-73,-56,-43,-29,-11,6,24,41,61,83,100,111,118,
+123,130,136,141,146,156,166,173,176,176,181,193,209,223,231,234,237,251,275,298,310,
+312,316,332,355,374,388,405,433,467,496,519,541,564,584,597,607,625,653,686,718,750,
+784,818,850,884,925,976,1029,1076,1115,1145,1167,1183,1202,1231,1272,1316,1360,1405,1454,1499,1531,
+1557,1591,1635,1673,1688,1680,1651,1579,1444,1287,1233,1410,1825,2341,2782,3076,3276,3461,3639,3757,3781,
+3732,3642,3515,3351,3189,3101,3114,3162,3140,3005,2809,2644,2560,2544,2563,2594,2621,2623,2582,2512,2454,
+2434,2442,2445,2426,2391,2359,2331,2301,2261,2216,2169,2121,2069,2014,1964,1925,1893,1865,1836,1804,1770,
+1732,1691,1648,1607,1569,1530,1487,1436,1377,1313,1248,1183,1125,1078,1042,1008,968,924,894,892,907,
+912,893,860,833,817,797,756,697,641,608,604,621,639,630,562,430,273,159,139,199,275,
+297,239,126,0,-112,-209,-300,-390,-478,-559,-631,-693,-743,-778,-801,-818,-834,-850,-868,-888,-905,
+-913,-908,-896,-890,-900,-921,-941,-948,-946,-946,-947,-940,-912,-863,-812,-776,-763,-766,-773,-781,-790,
+-794,-783,-747,-687,-617,-556,-511,-475,-444,-413,-383,-354,-319,-275,-225,-180,-143,-110,-73,-28,14,
+44,58,63,74,105,153,206,246,259,249,229,217,217,222,223,217,209,207,214,225,234,
+241,250,264,282,300,318,340,366,394,422,447,470,494,518,542,568,595,622,647,670,693,
+717,741,763,783,803,824,847,867,884,899,918,942,968,991,1012,1031,1053,1078,1103,1126,1148,
+1169,1189,1207,1224,1242,1260,1279,1299,1318,1337,1354,1368,1381,1399,1421,1442,1454,1453,1447,1445,1448,
+1453,1456,1457,1461,1469,1476,1480,1479,1478,1480,1484,1487,1490,1493,1499,1506,1514,1521,1529,1539,1553,
+1569,1584,1597,1608,1621,1637,1656,1678,1703,1729,1753,1774,1796,1818,1839,1856,1870,1887,1913,1945,1979,
+2007,2032,2055,2080,2104,2124,2132,2155,2179,2203,2232,2271,2322,2378,2426,2456,2464,2446,2400,2338,2286,
+2272,2299,2341,2369,2375,2374,2383,2401,2412,2410,2405,2410,2426,2442,2450,2454,2463,2477,2493,2508,2524,
+2544,2564,2577,2580,2579,2581,2588,2600,2615,2632,2649,2664,2680,2706,2748,2797,2835,2854,2866,2900,2970,
+3062,3143,3182,3175,3140,3105,3087,3093,3118,3152,3187,3219,3249,3276,3299,3312,3315,3311,3304,3297,3285,
+3266,3237,3196,3146,3102,3082,3099,3144,3194,3227,3241,3246,3247,3235,3200,3152,3114,3105,3117,3133,3142,
+3145,3154,3167,3178,3181,3179,3178,3175,3167,3160,3178,3245,3364,3509,3636,3711,3714,3643,3507,3331,3158,
+3022,2931,2864,2803,2744,2696,2651,2582,2467,2319,2173,2058,1979,1923,1888,1873,1877,1884,1881,1873,1872,
+1882,1888,1873,1823,1733,1612,1482,1371,1300,1266,1247,1227,1205,1191,1183,1173,1159,1150,1153,1165,1176,
+1184,1194,1210,1224,1231,1235,1242,1252,1253,1240,1226,1235,1280,1357,1443,1514,1554,1564,1558,1557,1568,
+1584,1589,1580,1567,1561,1557,1549,1535,1522,1511,1496,1469,1427,1379,1330,1282,1239,1205,1177,1150,1122,
+1098,1088,1093,1106,1120,1139,1163,1190,1212,1225,1234,1241,1239,1225,1205,1190,1181,1169,1149,1126,1109,
+1097,1079,1057,1046,1054,1070,1078,1078,1088,1122,1163,1187,1194,1202,1223,1234,1210,1157,1116,1122,1161,
+1191,1186,1158,1135,1130,1128,1112,1078,1036,999,972,954,943,932,915,888,860,837,824,816,808,
+795,776,752,728,705,684,660,631,603,578,555,527,493,458,428,403,377,345,309,275,245,
+217,187,155,121,90,60,31,1,-29,-61,-91,-122,-158,-200,-247,-295,-339,-383,-428,-477,-527,
+-579,-633,-689,-745,-797,-844,-886,-926,-967,-1012,-1067,-1129,-1191,-1245,-1289,-1326,-1361,-1396,-1432,-1474,-1525,
+-1580,-1633,-1679,-1719,-1758,-1794,-1826,-1856,-1887,-1922,-1960,-2001,-2044,-2090,-2135,-2173,-2199,-2213,-2220,-2227,-2245,
+-2281,-2332,-2390,-2450,-2519,-2601,-2686,-2749,-2778,-2785,-2804,-2853,-2923,-2987,-3034,-3074,-3121,-3176,-3221,-3240,-3233,
+-3215,-3205,-3217,-3252,-3295,-3329,-3347,-3358,-3377,-3409,-3444,-3474,-3500,-3529,-3567,-3610,-3648,-3671,-3669,-3638,-3594,
+-3565,-3575,-3622,-3682,-3730,-3763,-3790,-3818,-3844,-3859,-3865,-3863,-3857,-3849,-3844,-3846,-3850,-3850,-3846,-3844,-3851,
+-3858,-3857,-3851,-3851,-3863,-3878,-3886,-3889,-3896,-3906,-3909,-3902,-3895,-3900,-3915,-3927,-3930,-3933,-3943,-3957,-3965,
+-3965,-3965,-3970,-3971,-3961,-3941,-3918,-3891,-3856,-3814,-3773,-3736,-3703,-3668,-3636,-3603,-3557,-3478,-3360,-3210,-3046,
+-2896,-2787,-2744,-2758,-2777,-2739,-2631,-2504,-2422,-2397,-2390,-2358,-2304,-2259,-2240,-2227,-2202,-2166,-2140,-2128,-2122,
+-2113,-2106,-2106,-2108,-2104,-2094,-2087,-2084,-2067,-2023,-1961,-1904,-1868,-1848,-1830,-1810,-1794,-1787,-1783,-1767,-1732,
+-1684,-1640,-1615,-1615,-1634,-1659,-1677,-1684,-1681,-1676,-1675,-1679,-1686,-1688,-1680,-1658,-1623,-1577,-1522,-1460,-1394,
+-1330,-1271,-1212,-1138,-1040,-917,-783,-654,-542,-444,-358,-281,-217,-160,-100,-28,51,126,187,238,291,
+349,402,440,464,491,533,587,640,688,737,798,871,946,1009,1059,1102,1143,1184,1225,1275,1339,
+1412,1485,1552,1618,1692,1769,1831,1869,1890,1915,1959,2021,2089,2152,2201,2238,2267,2299,2343,2394,2444,
+2490,2535,2585,2633,2669,2697,2733,2791,2861,2919,2951,2963,2972,2988,3009,3041,3091,3162,3239,3306,3358,
+3405,3458,3520,3585,3644,3683,3693,3675,3649,3638,3639,3615,3525,3366,3188,3059,3020,3059,3128,3180,3196,
+3188,3175,3166,3160,3161,3184,3237,3308,3367,3399,3421,3461,3515,3551,3542,3505,3487,3515,3574,3625,3652,
+3671,3703,3747,3787,3810,3818,3819,3817,3812,3802,3784,3760,3735,3719,3720,3736,3763,3799,3850,3916,3982,
+4030,4056,4087,4163,4299,4456,4563,4575,4510,4437,4412,4439,4481,4510,4527,4550,4580,4605,4619,4634,4653,
+4666,4656,4634,4626,4648,4681,4696,4681,4653,4632,4621,4613,4607,4607,4616,4626,4629,4625,4621,4621,4622,
+4619,4616,4617,4621,4624,4622,4617,4615,4618,4631,4659,4706,4761,4794,4784,4738,4696,4685,4678,4604,4420,
+4154,3870,3592,3281,2905,2534,2308,2323,2532,2787,2966,3049,3082,3100,3109,3113,3126,3142,3127,3055,2951,
+2868,2830,2812,2773,2711,2648,2596,2538,2461,2377,2310,2264,2222,2173,2120,2072,2026,1973,1915,1860,1809,
+1757,1702,1653,1611,1567,1513,1455,1412,1390,1370,1333,1278,1224,1180,1142,1101,1058,1019,981,940,893,
+851,817,788,753,713,674,639,606,568,531,499,474,449,416,378,339,306,280,259,239,215,
+186,158,136,120,105,84,58,34,14,-2,-20,-43,-67,-90,-106,-117,-129,-144,-158,-166,-167,
+-166,-167,-170,-167,-159,-152,-156,-170,-190,-212,-243,-285,-332,-374,-405,-428,-448,-465,-478,-487,-498,
+-512,-525,-537,-548,-559,-570,-580,-591,-604,-617,-626,-633,-641,-657,-680,-703,-721,-734,-744,-753,-759,
+-765,-773,-784,-803,-833,-871,-910,-941,-963,-982,-1005,-1031,-1052,-1066,-1082,-1107,-1138,-1165,-1185,-1201,-1219,
+-1239,-1254,-1264,-1275,-1289,-1303,-1312,-1316,-1321,-1327,-1334,-1339,-1341,-1343,-1345,-1346,-1347,-1349,-1349,-1346,-1338,
+-1330,-1324,-1320,-1314,-1307,-1299,-1290,-1277,-1261,-1248,-1240,-1235,-1228,-1215,-1202,-1195,-1193,-1191,-1185,-1177,-1168,
+-1157,-1144,-1130,-1118,-1111,-1103,-1093,-1083,-1077,-1074,-1071,-1066,-1060,-1054,-1047,-1039,-1031,-1024,-1020,-1017,-1014,
+-1011,-1009,-1006,-1002,-994,-985,-976,-968,-959,-950,-943,-938,-934,-929,-924,-919,-914,-907,-898,-889,-883,
+-876,-869,-861,-855,-851,-846,-836,-822,-810,-802,-797,-789,-779,-769,-762,-756,-746,-733,-721,-714,-711,
+-707,-700,-692,-685,-679,-673,-666,-659,-652,-643,-634,-625,-618,-613,-606,-597,-589,-585,-583,-581,-574,
+-564,-554,-546,-537,-527,-520,-513,-504,-491,-475,-462,-453,-444,-434,-424,-415,-408,-399,-388,-377,-368,
+-361,-354,-345,-336,-329,-320,-308,-295,-284,-276,-267,-254,-240,-227,-216,-204,-190,-173,-155,-136,-115,
+-93,-73,-56,-38,-18,1,19,34,51,70,86,96,102,107,115,123,130,137,144,150,151,
+149,148,156,169,182,191,197,204,219,242,265,279,281,282,292,314,338,357,374,399,434,
+469,495,514,534,559,582,596,609,629,660,695,730,768,808,843,871,897,932,981,1031,1071,
+1100,1122,1143,1167,1195,1231,1275,1320,1365,1412,1460,1503,1535,1562,1594,1632,1660,1666,1649,1609,1522,
+1379,1237,1221,1439,1878,2395,2839,3160,3401,3604,3749,3795,3749,3662,3565,3438,3267,3105,3039,3087,3159,
+3132,2962,2720,2517,2412,2398,2437,2498,2549,2560,2521,2462,2430,2445,2482,2496,2468,2412,2353,2305,2265,
+2228,2192,2150,2099,2038,1979,1930,1894,1868,1842,1814,1784,1753,1720,1684,1644,1599,1551,1506,1463,1420,
+1372,1319,1263,1208,1156,1109,1069,1030,990,951,924,914,916,913,896,868,839,810,771,715,647,
+587,552,550,573,595,581,505,378,251,185,203,269,316,297,210,86,-43,-165,-274,-366,-441,
+-503,-564,-630,-692,-739,-764,-775,-784,-798,-815,-834,-852,-868,-878,-879,-874,-875,-891,-916,-936,-942,
+-937,-936,-940,-937,-916,-876,-832,-799,-780,-767,-753,-740,-732,-731,-726,-706,-665,-607,-540,-476,-422,
+-382,-354,-330,-299,-257,-209,-166,-134,-108,-81,-49,-13,17,36,46,54,72,104,147,190,223,
+241,247,248,252,260,268,271,269,264,263,266,270,274,279,287,302,321,339,354,369,389,
+415,443,471,495,519,543,572,601,631,657,682,705,728,752,775,797,818,840,861,882,900,
+916,933,954,979,1004,1027,1046,1065,1085,1108,1131,1153,1174,1195,1214,1231,1245,1260,1276,1295,1315,
+1334,1354,1371,1385,1398,1414,1434,1453,1463,1463,1461,1464,1472,1477,1477,1475,1476,1482,1486,1484,1479,
+1477,1480,1484,1487,1488,1492,1498,1505,1512,1521,1532,1546,1560,1572,1583,1595,1608,1623,1640,1660,1682,
+1707,1733,1760,1784,1806,1824,1839,1854,1873,1896,1921,1945,1968,1992,2020,2052,2082,2108,2132,2133,2170,
+2204,2226,2242,2268,2311,2361,2404,2431,2443,2437,2405,2350,2295,2273,2293,2335,2365,2372,2370,2377,2392,
+2402,2402,2400,2410,2430,2448,2457,2463,2473,2489,2505,2519,2536,2556,2575,2586,2587,2586,2588,2595,2603,
+2612,2625,2640,2654,2670,2694,2731,2778,2820,2846,2863,2895,2958,3047,3133,3185,3189,3158,3115,3083,3072,
+3082,3109,3145,3186,3230,3278,3325,3366,3392,3401,3396,3381,3360,3335,3303,3266,3224,3185,3160,3159,3180,
+3212,3239,3257,3266,3267,3255,3226,3188,3161,3158,3170,3178,3174,3170,3185,3222,3260,3276,3266,3245,3223,
+3210,3213,3252,3339,3461,3581,3666,3706,3704,3656,3551,3395,3223,3079,2982,2915,2855,2795,2740,2681,2593,
+2466,2319,2189,2096,2033,1985,1953,1944,1949,1950,1939,1929,1935,1951,1956,1930,1869,1779,1665,1541,1431,
+1357,1320,1302,1284,1261,1243,1230,1219,1210,1209,1219,1231,1237,1240,1249,1266,1281,1287,1292,1309,1334,
+1348,1342,1331,1343,1394,1474,1561,1629,1669,1681,1678,1677,1685,1696,1694,1677,1656,1640,1628,1614,1597,
+1583,1571,1551,1515,1465,1416,1377,1347,1322,1297,1271,1242,1209,1182,1170,1175,1187,1201,1219,1245,1275,
+1301,1318,1328,1334,1330,1315,1296,1285,1281,1271,1249,1224,1208,1199,1183,1159,1144,1151,1170,1180,1178,
+1187,1223,1272,1306,1318,1323,1335,1337,1306,1252,1214,1221,1258,1280,1264,1224,1189,1169,1152,1122,1081,
+1042,1012,992,980,974,967,952,928,904,889,882,875,861,842,820,798,777,754,730,705,678,
+651,624,598,570,538,508,481,456,427,395,361,331,302,272,238,204,174,145,113,79,45,
+16,-9,-34,-64,-99,-139,-179,-220,-263,-310,-360,-409,-457,-507,-560,-614,-666,-716,-764,-811,-856,
+-902,-952,-1010,-1071,-1127,-1172,-1206,-1238,-1273,-1312,-1356,-1406,-1462,-1520,-1571,-1615,-1653,-1688,-1722,-1752,-1782,
+-1815,-1855,-1900,-1945,-1990,-2034,-2075,-2110,-2135,-2149,-2152,-2151,-2155,-2178,-2223,-2283,-2346,-2412,-2486,-2566,-2636,
+-2679,-2700,-2721,-2763,-2826,-2890,-2945,-2993,-3045,-3100,-3142,-3159,-3153,-3140,-3139,-3162,-3203,-3246,-3276,-3293,-3308,
+-3332,-3365,-3398,-3424,-3447,-3477,-3517,-3560,-3600,-3626,-3634,-3620,-3595,-3580,-3597,-3642,-3696,-3737,-3763,-3786,-3812,
+-3839,-3857,-3862,-3858,-3851,-3845,-3842,-3844,-3847,-3850,-3854,-3864,-3877,-3883,-3877,-3869,-3870,-3879,-3884,-3880,-3880,
+-3892,-3911,-3918,-3908,-3899,-3905,-3923,-3935,-3936,-3937,-3949,-3966,-3975,-3975,-3975,-3979,-3978,-3966,-3946,-3928,-3909,
+-3880,-3839,-3793,-3751,-3714,-3678,-3647,-3625,-3602,-3555,-3465,-3327,-3156,-2984,-2853,-2799,-2823,-2870,-2865,-2774,-2636,
+-2524,-2470,-2448,-2413,-2358,-2311,-2290,-2286,-2273,-2245,-2213,-2189,-2170,-2157,-2155,-2163,-2171,-2167,-2154,-2149,-2155,
+-2154,-2125,-2067,-2006,-1964,-1940,-1920,-1900,-1889,-1891,-1891,-1867,-1808,-1731,-1669,-1641,-1650,-1678,-1705,-1719,-1714,
+-1698,-1682,-1677,-1687,-1707,-1725,-1728,-1711,-1675,-1626,-1569,-1509,-1449,-1391,-1332,-1265,-1177,-1063,-931,-800,-684,
+-587,-498,-413,-336,-273,-220,-162,-89,-9,60,110,153,206,276,346,398,427,450,484,532,585,
+638,693,757,830,903,969,1031,1090,1142,1182,1214,1253,1312,1389,1468,1538,1604,1676,1752,1814,1850,
+1867,1889,1933,1996,2059,2111,2151,2185,2220,2257,2298,2340,2383,2429,2480,2537,2589,2627,2657,2695,2751,
+2814,2862,2887,2899,2913,2934,2960,2995,3048,3124,3208,3278,3331,3378,3435,3504,3571,3623,3648,3642,3614,
+3586,3577,3575,3542,3440,3276,3106,2997,2975,3013,3062,3089,3096,3099,3104,3106,3103,3112,3153,3226,3303,
+3350,3363,3373,3408,3457,3485,3470,3434,3424,3460,3522,3575,3605,3624,3651,3685,3718,3741,3754,3759,3757,
+3746,3728,3707,3683,3664,3655,3660,3679,3704,3738,3789,3857,3929,3980,4007,4033,4098,4218,4360,4462,4484,
+4442,4390,4377,4402,4438,4460,4475,4494,4522,4548,4569,4591,4616,4633,4633,4619,4613,4626,4644,4649,4634,
+4611,4592,4580,4573,4570,4576,4585,4590,4586,4580,4578,4582,4585,4584,4584,4589,4599,4606,4605,4599,4594,
+4597,4615,4655,4713,4766,4783,4753,4700,4666,4660,4630,4504,4263,3963,3672,3395,3080,2713,2388,2248,2352,
+2607,2852,2994,3049,3075,3094,3096,3082,3080,3091,3079,3013,2911,2827,2790,2772,2735,2671,2605,2551,2497,
+2429,2356,2295,2249,2203,2151,2101,2058,2016,1967,1912,1859,1807,1750,1689,1637,1597,1560,1511,1456,1415,
+1396,1378,1342,1287,1232,1187,1149,1107,1061,1020,982,938,888,842,807,780,748,709,669,634,600,
+562,522,491,469,448,418,378,337,305,281,261,238,213,189,166,147,129,109,86,61,38,
+19,3,-15,-39,-65,-88,-102,-110,-118,-133,-150,-162,-167,-169,-174,-177,-172,-158,-144,-143,-156,
+-175,-196,-223,-261,-308,-354,-392,-422,-446,-466,-482,-496,-509,-524,-538,-553,-567,-582,-597,-608,-619,
+-631,-643,-653,-659,-662,-670,-684,-706,-729,-748,-762,-769,-775,-783,-795,-813,-834,-860,-888,-914,-931,
+-942,-958,-983,-1011,-1034,-1049,-1066,-1090,-1119,-1144,-1161,-1176,-1192,-1210,-1224,-1234,-1246,-1261,-1276,-1287,-1294,
+-1302,-1312,-1321,-1329,-1334,-1338,-1340,-1341,-1341,-1342,-1342,-1339,-1333,-1328,-1324,-1320,-1312,-1303,-1293,-1284,-1272,
+-1256,-1242,-1232,-1226,-1219,-1208,-1197,-1191,-1190,-1189,-1185,-1180,-1173,-1164,-1153,-1140,-1131,-1123,-1115,-1104,-1092,
+-1085,-1083,-1081,-1078,-1073,-1067,-1061,-1056,-1049,-1043,-1038,-1033,-1029,-1026,-1024,-1020,-1012,-1004,-997,-990,-981,
+-969,-957,-948,-946,-945,-943,-940,-936,-931,-925,-915,-905,-895,-888,-881,-874,-868,-864,-860,-854,-844,
+-833,-822,-813,-803,-793,-784,-778,-773,-767,-757,-747,-737,-730,-724,-719,-712,-705,-699,-693,-689,-684,
+-677,-668,-657,-648,-641,-635,-627,-616,-607,-602,-599,-596,-589,-580,-569,-558,-546,-536,-528,-523,-516,
+-503,-488,-474,-466,-460,-451,-441,-430,-421,-410,-398,-387,-380,-376,-370,-360,-348,-338,-330,-320,-309,
+-299,-292,-285,-275,-262,-251,-241,-229,-213,-193,-173,-154,-134,-113,-93,-74,-53,-28,-3,17,33,
+46,59,71,80,86,94,103,114,122,130,135,138,135,130,129,137,150,160,165,169,182,
+204,231,250,256,254,257,274,300,324,341,358,386,423,459,485,503,523,546,569,589,609,
+635,669,704,741,781,821,854,879,902,937,981,1023,1050,1067,1083,1107,1141,1182,1227,1274,1321,
+1366,1411,1455,1494,1525,1554,1588,1621,1639,1636,1613,1564,1465,1315,1183,1197,1445,1894,2406,2854,3198,
+3469,3676,3786,3781,3701,3610,3520,3385,3192,3016,2958,3029,3114,3076,2882,2621,2416,2326,2333,2389,2452,
+2494,2495,2461,2429,2434,2479,2524,2529,2484,2412,2340,2282,2240,2209,2179,2140,2084,2017,1955,1910,1878,
+1851,1822,1791,1763,1736,1710,1680,1640,1591,1538,1489,1448,1410,1369,1324,1277,1232,1188,1145,1102,1059,
+1018,980,948,925,911,900,885,863,831,788,730,662,594,537,500,489,497,505,487,424,332,
+257,236,269,315,323,276,186,73,-50,-180,-302,-399,-464,-511,-563,-629,-693,-735,-749,-748,-751,
+-766,-789,-812,-832,-848,-859,-863,-865,-873,-895,-925,-948,-955,-948,-940,-937,-932,-916,-887,-852,-819,
+-789,-758,-727,-702,-686,-677,-668,-649,-613,-557,-483,-404,-340,-304,-289,-274,-238,-183,-127,-89,-75,
+-70,-60,-37,-9,16,33,45,60,84,119,156,190,214,231,245,261,279,296,308,313,315,
+315,317,320,323,326,329,338,353,370,385,395,404,417,438,467,498,525,551,578,608,640,
+670,695,718,740,763,787,810,831,852,873,894,913,930,948,968,990,1014,1038,1059,1077,1095,
+1112,1131,1150,1169,1190,1210,1229,1246,1260,1275,1294,1315,1337,1360,1383,1404,1420,1434,1448,1463,1476,
+1481,1479,1478,1483,1490,1492,1487,1481,1480,1484,1485,1480,1475,1476,1483,1490,1492,1492,1496,1503,1510,
+1515,1523,1536,1550,1562,1570,1578,1591,1607,1625,1642,1661,1682,1707,1734,1762,1789,1811,1828,1841,1858,
+1881,1906,1927,1943,1959,1985,2018,2052,2078,2102,2133,2131,2189,2238,2262,2266,2271,2289,2317,2348,2381,
+2420,2451,2448,2400,2328,2276,2273,2306,2341,2356,2358,2361,2371,2379,2381,2385,2399,2421,2440,2452,2462,
+2477,2494,2510,2525,2542,2563,2580,2588,2589,2589,2593,2599,2602,2605,2612,2626,2643,2660,2682,2716,2762,
+2808,2842,2866,2898,2955,3038,3123,3180,3194,3169,3128,3090,3068,3068,3088,3122,3163,3208,3261,3324,3391,
+3446,3472,3468,3443,3410,3379,3350,3324,3297,3272,3250,3235,3231,3239,3255,3272,3285,3292,3286,3265,3235,
+3213,3210,3215,3211,3192,3182,3209,3273,3342,3376,3363,3323,3283,3262,3272,3323,3418,3530,3617,3652,3646,
+3620,3577,3493,3356,3194,3059,2975,2925,2879,2822,2758,2682,2580,2448,2309,2198,2126,2080,2047,2028,2028,
+2033,2025,2001,1984,1989,2004,2003,1968,1907,1825,1724,1607,1493,1411,1370,1353,1339,1319,1299,1285,1275,
+1271,1274,1285,1296,1299,1300,1310,1327,1341,1348,1360,1389,1425,1445,1440,1431,1449,1508,1594,1680,1746,
+1784,1798,1799,1799,1805,1808,1796,1767,1736,1712,1696,1678,1656,1633,1611,1582,1539,1491,1450,1425,1411,
+1397,1378,1355,1327,1296,1270,1258,1260,1269,1280,1297,1324,1357,1383,1399,1406,1411,1409,1399,1387,1381,
+1380,1369,1345,1318,1303,1299,1290,1272,1259,1264,1281,1288,1286,1297,1335,1388,1425,1437,1438,1439,1430,
+1394,1341,1306,1311,1336,1343,1314,1268,1230,1204,1174,1134,1093,1062,1042,1026,1012,1004,999,990,976,
+961,952,945,933,912,888,869,853,835,810,782,753,726,700,672,644,616,587,558,531,503,
+473,441,411,386,359,327,290,256,228,201,169,130,93,66,45,23,-6,-42,-78,-112,-149,
+-193,-242,-292,-339,-384,-432,-484,-537,-587,-635,-684,-736,-788,-839,-892,-948,-1004,-1054,-1091,-1121,-1151,
+-1188,-1233,-1283,-1337,-1396,-1454,-1506,-1548,-1584,-1618,-1648,-1678,-1709,-1747,-1792,-1841,-1886,-1927,-1965,-2001,-2033,
+-2061,-2080,-2089,-2088,-2087,-2102,-2140,-2194,-2251,-2306,-2367,-2438,-2512,-2570,-2608,-2638,-2681,-2741,-2811,-2878,-2940,
+-2996,-3045,-3080,-3095,-3098,-3100,-3113,-3140,-3173,-3201,-3219,-3230,-3246,-3275,-3310,-3343,-3369,-3396,-3433,-3475,-3515,
+-3545,-3566,-3579,-3583,-3579,-3580,-3598,-3637,-3683,-3720,-3746,-3768,-3793,-3818,-3836,-3843,-3843,-3840,-3837,-3835,-3833,
+-3831,-3837,-3855,-3881,-3900,-3901,-3887,-3878,-3887,-3902,-3904,-3891,-3884,-3898,-3922,-3931,-3918,-3904,-3910,-3931,-3947,
+-3950,-3953,-3966,-3983,-3990,-3987,-3985,-3989,-3987,-3971,-3948,-3930,-3915,-3891,-3853,-3809,-3769,-3732,-3693,-3656,-3632,
+-3619,-3596,-3538,-3432,-3282,-3107,-2947,-2852,-2848,-2904,-2941,-2896,-2773,-2637,-2542,-2491,-2451,-2404,-2362,-2343,-2342,
+-2336,-2312,-2275,-2238,-2207,-2188,-2187,-2202,-2220,-2223,-2212,-2203,-2205,-2208,-2188,-2144,-2092,-2050,-2021,-1997,-1980,
+-1980,-1997,-2002,-1966,-1882,-1782,-1712,-1692,-1712,-1743,-1763,-1763,-1748,-1725,-1702,-1692,-1703,-1731,-1762,-1777,-1766,
+-1729,-1676,-1615,-1556,-1500,-1446,-1389,-1319,-1225,-1105,-972,-845,-736,-644,-559,-474,-396,-334,-283,-228,-158,
+-82,-21,16,45,91,162,243,311,358,394,436,490,550,611,669,727,785,846,914,993,1078,
+1151,1198,1221,1243,1287,1356,1436,1509,1575,1645,1717,1776,1811,1829,1854,1900,1962,2022,2067,2102,2138,
+2177,2218,2255,2289,2323,2365,2416,2474,2528,2571,2609,2652,2707,2763,2804,2825,2834,2848,2869,2899,2942,
+3008,3096,3187,3258,3307,3351,3409,3482,3551,3597,3609,3593,3563,3537,3520,3492,3423,3297,3138,3002,2937,
+2941,2975,2999,3002,3000,3006,3015,3018,3022,3052,3123,3216,3286,3307,3295,3292,3324,3374,3404,3395,3374,
+3375,3413,3469,3519,3554,3581,3608,3634,3655,3672,3687,3697,3695,3681,3659,3636,3619,3609,3610,3621,3640,
+3664,3694,3739,3801,3866,3915,3946,3981,4049,4155,4269,4344,4361,4340,4321,4331,4363,4395,4416,4430,4450,
+4475,4500,4523,4547,4572,4591,4597,4596,4599,4609,4616,4609,4589,4565,4545,4531,4525,4528,4540,4552,4555,
+4549,4544,4546,4553,4557,4555,4555,4561,4572,4581,4584,4580,4576,4579,4603,4652,4716,4764,4766,4723,4671,
+4646,4635,4574,4399,4113,3784,3476,3181,2857,2513,2259,2216,2397,2678,2907,3021,3060,3083,3097,3087,3065,
+3066,3089,3085,3012,2890,2786,2738,2724,2694,2634,2564,2504,2449,2391,2331,2278,2230,2179,2125,2077,2039,
+2000,1950,1895,1844,1793,1733,1668,1614,1579,1548,1504,1449,1407,1387,1373,1340,1286,1230,1185,1148,1107,
+1061,1019,981,939,890,844,807,778,744,704,665,631,599,560,517,482,458,438,411,375,337,
+307,282,258,234,211,191,173,154,132,109,87,65,44,25,7,-11,-33,-56,-77,-90,-97,
+-105,-121,-141,-157,-166,-170,-174,-176,-170,-155,-141,-138,-150,-169,-190,-215,-249,-292,-337,-377,-409,
+-436,-459,-479,-498,-517,-535,-551,-564,-576,-592,-610,-628,-644,-660,-674,-687,-695,-699,-702,-708,-720,
+-738,-756,-771,-782,-791,-802,-818,-836,-856,-876,-896,-912,-922,-931,-945,-968,-994,-1017,-1035,-1054,-1079,
+-1104,-1124,-1137,-1148,-1163,-1179,-1193,-1206,-1221,-1237,-1252,-1264,-1274,-1287,-1300,-1313,-1321,-1327,-1332,-1335,-1335,
+-1334,-1335,-1336,-1335,-1333,-1329,-1324,-1317,-1307,-1296,-1288,-1281,-1272,-1258,-1243,-1232,-1225,-1217,-1207,-1198,-1192,
+-1189,-1186,-1181,-1175,-1170,-1162,-1153,-1143,-1137,-1131,-1124,-1112,-1098,-1089,-1085,-1085,-1084,-1079,-1074,-1069,-1066,
+-1062,-1057,-1051,-1044,-1039,-1037,-1034,-1028,-1018,-1010,-1005,-1002,-996,-984,-971,-962,-959,-960,-959,-955,-950,
+-944,-937,-928,-918,-910,-903,-897,-890,-882,-876,-872,-868,-862,-852,-840,-829,-819,-811,-802,-794,-788,
+-784,-779,-772,-762,-752,-745,-739,-733,-727,-719,-713,-709,-706,-700,-692,-683,-675,-668,-660,-649,-638,
+-628,-621,-616,-610,-602,-593,-584,-573,-560,-548,-542,-539,-534,-522,-504,-490,-483,-479,-473,-462,-450,
+-438,-426,-413,-402,-396,-394,-389,-379,-366,-354,-346,-338,-327,-316,-307,-299,-289,-278,-268,-260,-249,
+-233,-211,-187,-166,-148,-130,-113,-95,-72,-44,-13,11,29,40,48,56,63,70,80,91,101,
+110,116,120,121,120,117,118,125,135,144,150,159,175,199,221,233,236,236,245,267,295,
+319,336,353,380,415,450,478,497,515,534,554,575,600,630,665,701,739,777,813,840,861,
+887,924,967,1003,1023,1034,1049,1078,1118,1165,1215,1266,1315,1360,1402,1439,1470,1498,1529,1565,1595,
+1607,1598,1574,1519,1412,1259,1143,1188,1465,1925,2432,2877,3229,3507,3699,3773,3733,3644,3563,3474,3314,
+3082,2879,2818,2899,2993,2958,2773,2539,2372,2316,2336,2379,2412,2424,2419,2413,2429,2474,2527,2548,2518,
+2450,2372,2305,2254,2216,2189,2162,2123,2065,1997,1938,1896,1864,1833,1800,1769,1746,1728,1708,1679,1638,
+1586,1532,1485,1448,1415,1379,1338,1298,1261,1227,1189,1148,1104,1060,1017,975,939,913,896,883,863,
+828,775,708,637,574,523,483,453,434,418,391,346,294,264,273,306,328,310,255,176,82,
+-33,-168,-299,-398,-459,-503,-557,-628,-696,-735,-740,-731,-728,-742,-767,-794,-816,-833,-843,-846,-849,
+-862,-890,-927,-959,-972,-968,-953,-938,-923,-904,-880,-851,-818,-780,-738,-701,-673,-654,-637,-615,-584,
+-541,-479,-397,-311,-245,-217,-214,-206,-166,-100,-36,-2,-4,-22,-31,-22,0,28,51,70,91,
+118,153,188,216,234,246,261,284,311,336,351,357,357,356,359,366,376,385,392,400,411,
+422,431,438,444,454,473,500,531,561,589,617,647,679,707,731,752,772,795,817,839,859,
+879,899,919,937,956,976,996,1018,1040,1061,1082,1102,1121,1138,1155,1172,1190,1210,1230,1248,1265,
+1282,1300,1320,1342,1365,1390,1416,1440,1458,1473,1486,1499,1507,1505,1499,1494,1497,1501,1500,1492,1485,
+1484,1487,1486,1480,1477,1482,1491,1498,1498,1498,1502,1511,1518,1522,1528,1540,1553,1563,1569,1577,1591,
+1610,1628,1644,1661,1681,1705,1730,1757,1785,1809,1829,1844,1862,1884,1906,1923,1939,1961,1994,2029,2054,
+2068,2089,2131,2140,2213,2272,2299,2299,2290,2283,2281,2294,2338,2416,2496,2524,2474,2370,2279,2247,2273,
+2316,2342,2347,2345,2346,2351,2356,2364,2381,2402,2422,2438,2454,2472,2491,2507,2522,2541,2562,2580,2588,
+2589,2590,2594,2597,2596,2594,2598,2612,2632,2653,2675,2707,2751,2799,2837,2864,2894,2943,3014,3092,3149,
+3171,3160,3131,3098,3075,3070,3087,3118,3153,3188,3232,3299,3384,3465,3511,3512,3482,3443,3411,3387,3369,
+3354,3341,3324,3303,3286,3279,3283,3295,3307,3313,3309,3292,3268,3251,3248,3252,3242,3216,3200,3228,3306,
+3393,3440,3429,3382,3334,3310,3320,3371,3458,3551,3605,3600,3555,3505,3457,3386,3271,3134,3021,2957,2923,
+2882,2819,2737,2641,2524,2390,2267,2181,2138,2119,2107,2103,2106,2106,2086,2054,2034,2039,2053,2048,2013,
+1956,1885,1792,1675,1555,1464,1418,1402,1391,1375,1358,1347,1342,1340,1343,1351,1359,1363,1367,1376,1390,
+1400,1411,1433,1472,1511,1529,1524,1524,1559,1633,1724,1806,1865,1899,1913,1915,1915,1917,1914,1892,1853,
+1813,1785,1767,1745,1713,1676,1639,1600,1559,1520,1493,1480,1472,1460,1443,1425,1404,1380,1358,1346,1346,
+1353,1362,1376,1401,1430,1452,1463,1470,1478,1486,1487,1481,1476,1472,1460,1436,1410,1397,1397,1395,1384,
+1373,1374,1385,1392,1397,1416,1458,1507,1535,1536,1524,1512,1492,1450,1398,1366,1366,1378,1368,1332,1290,
+1261,1237,1202,1156,1116,1094,1083,1070,1055,1045,1043,1039,1030,1017,1009,1001,987,963,940,923,910,
+891,863,830,800,775,749,722,693,665,636,607,578,548,517,486,459,435,410,378,341,308,
+281,255,223,184,148,122,103,80,49,15,-16,-46,-81,-126,-176,-223,-265,-306,-354,-407,-460,
+-509,-556,-606,-662,-718,-773,-825,-878,-929,-974,-1010,-1040,-1072,-1112,-1160,-1213,-1269,-1327,-1382,-1432,-1475,
+-1512,-1543,-1572,-1602,-1639,-1683,-1732,-1779,-1818,-1852,-1883,-1915,-1949,-1981,-2008,-2024,-2030,-2035,-2051,-2084,-2129,
+-2174,-2216,-2265,-2328,-2401,-2468,-2519,-2560,-2605,-2665,-2738,-2817,-2888,-2943,-2979,-3000,-3014,-3030,-3052,-3078,-3105,
+-3129,-3146,-3157,-3166,-3182,-3211,-3247,-3281,-3313,-3349,-3394,-3443,-3481,-3505,-3520,-3533,-3546,-3556,-3566,-3584,-3614,
+-3650,-3682,-3710,-3737,-3766,-3793,-3810,-3817,-3818,-3819,-3822,-3820,-3814,-3809,-3820,-3853,-3894,-3918,-3910,-3888,-3883,
+-3907,-3937,-3942,-3922,-3906,-3919,-3946,-3955,-3936,-3915,-3919,-3944,-3967,-3974,-3979,-3992,-4006,-4007,-3997,-3992,-3995,
+-3995,-3980,-3955,-3933,-3917,-3895,-3861,-3824,-3790,-3758,-3718,-3676,-3646,-3632,-3620,-3589,-3525,-3419,-3268,-3092,-2942,
+-2880,-2916,-2986,-2995,-2903,-2749,-2608,-2521,-2474,-2439,-2408,-2390,-2386,-2381,-2360,-2324,-2283,-2248,-2225,-2222,-2237,
+-2259,-2269,-2262,-2248,-2239,-2232,-2218,-2190,-2156,-2124,-2095,-2071,-2062,-2075,-2099,-2097,-2038,-1932,-1825,-1767,-1767,
+-1798,-1822,-1823,-1807,-1785,-1764,-1744,-1733,-1743,-1775,-1813,-1836,-1828,-1787,-1728,-1663,-1603,-1549,-1497,-1440,-1369,
+-1276,-1159,-1028,-901,-791,-697,-613,-531,-458,-400,-351,-299,-234,-166,-114,-85,-63,-23,42,125,204,
+267,320,376,441,513,584,647,698,744,797,871,970,1081,1175,1227,1240,1240,1259,1311,1384,1460,
+1531,1600,1668,1725,1762,1786,1814,1860,1918,1972,2015,2050,2086,2125,2164,2200,2233,2268,2309,2357,2410,
+2464,2513,2557,2603,2655,2707,2746,2766,2771,2776,2790,2821,2876,2961,3066,3169,3246,3296,3338,3392,3459,
+3519,3553,3554,3535,3513,3494,3464,3395,3272,3113,2968,2886,2877,2906,2925,2919,2908,2916,2940,2956,2954,
+2954,2994,3081,3179,3236,3234,3202,3193,3226,3279,3317,3326,3327,3344,3382,3425,3462,3495,3529,3562,3586,
+3599,3610,3624,3634,3633,3619,3599,3582,3571,3566,3568,3580,3598,3620,3650,3692,3746,3800,3842,3876,3927,
+4010,4114,4203,4246,4244,4230,4236,4267,4309,4343,4365,4384,4406,4430,4453,4477,4501,4523,4535,4542,4553,
+4572,4591,4595,4578,4549,4519,4494,4477,4470,4478,4495,4511,4516,4513,4512,4516,4523,4526,4525,4525,4530,
+4538,4547,4553,4555,4555,4563,4593,4650,4714,4752,4741,4692,4645,4625,4603,4510,4299,3985,3633,3292,2960,
+2623,2324,2167,2227,2465,2745,2943,3035,3073,3099,3105,3080,3052,3064,3106,3113,3029,2881,2747,2680,2662,
+2642,2593,2526,2461,2404,2351,2300,2253,2204,2150,2096,2052,2016,1974,1919,1862,1814,1768,1710,1645,1591,
+1559,1534,1490,1430,1380,1359,1352,1329,1281,1224,1177,1139,1101,1057,1016,978,940,898,855,816,780,
+741,700,661,629,597,559,515,475,446,423,399,369,338,308,278,249,224,204,188,172,151,
+128,106,87,71,54,35,14,-5,-25,-45,-62,-75,-84,-95,-112,-134,-154,-167,-173,-173,-170,
+-163,-151,-143,-144,-155,-173,-193,-217,-248,-287,-328,-365,-397,-424,-449,-473,-497,-522,-546,-565,-578,
+-590,-606,-627,-650,-670,-686,-700,-714,-726,-735,-741,-744,-748,-756,-767,-780,-793,-807,-821,-836,-851,
+-865,-877,-891,-904,-917,-930,-946,-966,-986,-1003,-1022,-1043,-1066,-1087,-1102,-1113,-1125,-1140,-1157,-1172,-1189,
+-1206,-1223,-1237,-1248,-1261,-1277,-1293,-1305,-1313,-1319,-1325,-1328,-1328,-1328,-1330,-1334,-1337,-1337,-1332,-1325,-1316,
+-1305,-1295,-1289,-1284,-1275,-1260,-1244,-1230,-1222,-1215,-1208,-1199,-1192,-1185,-1178,-1171,-1165,-1160,-1153,-1144,-1136,
+-1130,-1126,-1121,-1110,-1096,-1086,-1081,-1081,-1081,-1078,-1073,-1069,-1067,-1065,-1061,-1055,-1050,-1046,-1045,-1042,-1035,
+-1024,-1015,-1011,-1010,-1006,-997,-986,-979,-976,-974,-971,-966,-960,-953,-945,-937,-930,-925,-920,-915,-908,
+-900,-892,-885,-880,-875,-866,-855,-843,-835,-830,-824,-815,-806,-800,-797,-793,-785,-775,-767,-761,-756,
+-749,-741,-734,-729,-724,-719,-712,-706,-700,-693,-683,-671,-659,-649,-641,-634,-626,-618,-610,-602,-592,
+-579,-568,-561,-558,-553,-540,-523,-508,-500,-498,-492,-481,-467,-455,-444,-433,-421,-415,-412,-409,-400,
+-388,-376,-368,-360,-349,-335,-322,-312,-302,-291,-281,-272,-263,-247,-225,-201,-180,-163,-147,-131,-112,
+-90,-63,-34,-6,14,27,36,43,49,56,64,75,85,92,95,95,97,99,103,108,115,
+124,134,146,161,178,195,207,213,217,224,238,261,287,311,332,352,377,407,438,465,487,
+505,522,539,560,586,617,653,692,733,770,799,818,836,863,902,946,980,1001,1017,1037,1067,
+1107,1152,1201,1252,1299,1344,1382,1414,1439,1466,1500,1539,1567,1574,1564,1539,1483,1370,1220,1125,1206,
+1516,1987,2486,2916,3259,3525,3692,3732,3667,3569,3484,3375,3178,2908,2682,2618,2703,2803,2788,2648,2480,
+2377,2357,2373,2380,2367,2351,2356,2394,2464,2540,2581,2559,2482,2388,2309,2255,2214,2180,2151,2122,2082,
+2027,1966,1912,1873,1841,1809,1778,1755,1740,1730,1713,1683,1639,1585,1532,1489,1457,1429,1399,1365,1332,
+1303,1275,1244,1207,1166,1122,1074,1026,984,953,933,917,896,857,800,732,667,612,565,519,470,
+424,383,345,307,277,269,289,316,322,293,238,168,81,-31,-166,-295,-390,-449,-497,-559,-636,
+-703,-739,-743,-731,-725,-733,-752,-776,-798,-815,-823,-824,-826,-839,-869,-911,-950,-972,-973,-958,-936,
+-912,-890,-868,-844,-811,-768,-720,-678,-649,-628,-604,-571,-528,-474,-405,-319,-230,-162,-133,-129,-120,
+-80,-14,48,79,73,48,24,17,28,50,75,98,120,147,180,216,245,263,275,290,315,
+348,381,403,411,405,395,391,397,414,433,449,459,464,468,474,481,491,504,523,547,576,
+605,633,660,687,714,740,763,783,802,823,844,865,885,904,924,944,963,983,1004,1024,1044,
+1063,1083,1104,1127,1148,1167,1185,1203,1223,1244,1263,1280,1297,1316,1337,1358,1377,1396,1418,1442,1466,
+1486,1502,1515,1527,1531,1525,1514,1506,1505,1508,1508,1502,1498,1498,1499,1496,1489,1486,1490,1498,1502,
+1500,1501,1508,1518,1525,1528,1533,1542,1554,1562,1569,1579,1595,1613,1631,1647,1665,1685,1706,1727,1749,
+1775,1801,1823,1839,1855,1871,1890,1911,1936,1970,2009,2039,2052,2060,2085,2140,2164,2231,2280,2305,2312,
+2306,2287,2263,2261,2317,2430,2548,2596,2534,2401,2280,2232,2255,2303,2333,2336,2328,2324,2328,2337,2350,
+2367,2388,2408,2427,2446,2466,2484,2499,2514,2534,2558,2578,2589,2591,2590,2590,2589,2586,2582,2586,2602,
+2625,2649,2675,2706,2746,2790,2828,2855,2879,2915,2968,3029,3081,3114,3126,3121,3104,3084,3075,3084,3110,
+3139,3165,3199,3261,3353,3448,3510,3521,3497,3464,3439,3421,3405,3392,3381,3370,3356,3342,3334,3334,3338,
+3340,3337,3329,3313,3294,3283,3287,3296,3289,3261,3236,3252,3319,3404,3455,3452,3413,3373,3355,3367,3411,
+3481,3549,3578,3547,3479,3410,3354,3292,3203,3099,3013,2958,2915,2855,2768,2664,2550,2425,2300,2199,2146,
+2138,2150,2160,2163,2163,2153,2126,2095,2081,2092,2110,2109,2077,2025,1954,1857,1735,1610,1517,1470,1453,
+1441,1425,1413,1409,1410,1411,1411,1415,1422,1429,1436,1443,1449,1458,1475,1508,1552,1587,1601,1604,1627,
+1689,1780,1870,1938,1982,2007,2018,2019,2018,2017,2009,1982,1938,1895,1867,1850,1826,1785,1733,1682,1638,
+1599,1571,1554,1545,1535,1519,1503,1491,1479,1461,1440,1427,1428,1436,1445,1455,1470,1489,1505,1515,1526,
+1544,1563,1573,1570,1564,1558,1550,1533,1514,1502,1500,1496,1484,1472,1471,1481,1494,1511,1541,1583,1618,
+1626,1609,1584,1563,1534,1486,1434,1403,1400,1400,1379,1339,1305,1288,1271,1235,1187,1149,1135,1133,1126,
+1113,1105,1104,1101,1088,1071,1059,1051,1038,1016,993,974,958,935,905,874,847,823,798,770,741,
+713,685,656,627,598,568,537,508,481,455,424,389,355,327,302,273,239,206,179,157,132,
+102,71,44,16,-18,-64,-112,-154,-192,-232,-279,-333,-385,-433,-481,-533,-590,-648,-703,-754,-803,
+-851,-895,-933,-968,-1005,-1048,-1097,-1150,-1204,-1255,-1304,-1352,-1396,-1434,-1466,-1495,-1527,-1569,-1620,-1671,-1713,
+-1745,-1772,-1802,-1837,-1876,-1912,-1940,-1958,-1968,-1979,-2002,-2037,-2077,-2114,-2149,-2191,-2248,-2315,-2382,-2438,-2485,
+-2532,-2588,-2659,-2735,-2802,-2845,-2862,-2866,-2877,-2904,-2941,-2976,-3004,-3028,-3051,-3072,-3092,-3115,-3146,-3186,-3228,
+-3268,-3311,-3361,-3413,-3454,-3479,-3493,-3505,-3518,-3532,-3547,-3566,-3590,-3616,-3642,-3670,-3704,-3743,-3776,-3792,-3794,
+-3791,-3794,-3802,-3807,-3803,-3799,-3813,-3854,-3904,-3929,-3916,-3889,-3891,-3932,-3977,-3984,-3954,-3928,-3938,-3970,-3984,
+-3965,-3939,-3939,-3964,-3988,-3997,-4001,-4013,-4025,-4022,-4007,-3997,-4000,-4003,-3990,-3965,-3942,-3926,-3904,-3873,-3840,
+-3811,-3784,-3747,-3706,-3675,-3658,-3645,-3625,-3592,-3534,-3425,-3254,-3065,-2943,-2944,-3028,-3083,-3022,-2858,-2678,-2557,
+-2503,-2479,-2456,-2434,-2422,-2415,-2400,-2373,-2340,-2310,-2290,-2283,-2290,-2304,-2312,-2306,-2286,-2265,-2248,-2233,-2218,
+-2201,-2182,-2163,-2149,-2152,-2171,-2184,-2156,-2068,-1949,-1855,-1828,-1856,-1893,-1901,-1876,-1844,-1821,-1807,-1794,-1785,
+-1795,-1828,-1871,-1897,-1888,-1844,-1780,-1714,-1654,-1600,-1546,-1486,-1414,-1323,-1212,-1086,-958,-843,-745,-661,-588,
+-524,-472,-426,-378,-323,-267,-222,-192,-162,-117,-49,32,113,185,250,314,385,463,540,609,664,
+712,771,858,976,1102,1200,1245,1239,1217,1214,1251,1320,1400,1478,1550,1617,1675,1719,1751,1782,1818,
+1861,1902,1939,1973,2005,2037,2072,2112,2159,2208,2257,2304,2355,2411,2467,2516,2560,2603,2648,2687,2708,
+2713,2711,2720,2754,2820,2916,3029,3137,3222,3281,3328,3379,3434,3477,3492,3479,3456,3441,3429,3388,3283,
+3114,2931,2807,2778,2816,2853,2849,2821,2820,2871,2942,2979,2964,2937,2952,3023,3108,3151,3138,3104,3097,
+3133,3189,3234,3262,3287,3321,3359,3389,3410,3433,3463,3495,3520,3535,3547,3561,3570,3568,3556,3543,3533,
+3524,3515,3510,3516,3533,3558,3590,3634,3686,3734,3769,3802,3861,3957,4067,4146,4168,4150,4134,4151,4196,
+4243,4277,4301,4323,4346,4368,4391,4417,4443,4461,4468,4474,4496,4534,4569,4578,4556,4518,4480,4451,4432,
+4425,4432,4449,4464,4471,4471,4471,4474,4478,4482,4486,4492,4498,4504,4509,4517,4523,4529,4544,4583,4646,
+4706,4730,4705,4654,4615,4596,4556,4432,4193,3863,3489,3107,2731,2391,2160,2118,2280,2555,2810,2966,3038,
+3080,3110,3106,3062,3023,3038,3091,3107,3026,2871,2722,2633,2598,2575,2534,2480,2423,2368,2316,2270,2226,
+2178,2123,2069,2026,1989,1943,1884,1827,1783,1742,1689,1623,1569,1539,1513,1465,1396,1337,1315,1318,1312,
+1276,1221,1170,1131,1095,1055,1014,975,939,902,862,821,779,736,694,658,627,596,559,516,475,
+440,412,388,364,339,308,273,237,208,189,177,163,144,122,103,89,76,61,43,22,1,
+-18,-35,-51,-65,-77,-90,-106,-127,-149,-166,-174,-171,-163,-154,-148,-148,-155,-167,-183,-200,-221,
+-250,-284,-320,-354,-384,-413,-441,-468,-496,-525,-554,-578,-597,-614,-633,-655,-677,-696,-710,-722,-734,
+-749,-763,-774,-779,-780,-781,-784,-792,-805,-820,-836,-852,-864,-873,-880,-888,-900,-917,-935,-954,-971,
+-984,-997,-1014,-1034,-1054,-1071,-1083,-1096,-1111,-1128,-1146,-1162,-1180,-1198,-1214,-1226,-1237,-1252,-1268,-1283,-1293,
+-1300,-1307,-1315,-1319,-1319,-1319,-1322,-1329,-1334,-1335,-1330,-1322,-1313,-1304,-1297,-1291,-1284,-1272,-1255,-1237,-1224,
+-1215,-1209,-1203,-1194,-1184,-1173,-1163,-1156,-1152,-1149,-1144,-1136,-1127,-1120,-1115,-1110,-1101,-1090,-1081,-1075,-1074,
+-1074,-1073,-1070,-1067,-1064,-1062,-1059,-1055,-1052,-1051,-1052,-1050,-1043,-1032,-1024,-1019,-1016,-1012,-1004,-998,-993,
+-989,-985,-980,-975,-970,-963,-955,-949,-944,-939,-934,-929,-924,-918,-910,-901,-893,-886,-878,-867,-856,
+-849,-846,-843,-836,-826,-818,-814,-810,-804,-795,-787,-781,-776,-768,-760,-753,-747,-741,-733,-726,-721,
+-716,-709,-700,-690,-678,-668,-660,-653,-645,-638,-631,-623,-613,-601,-588,-579,-572,-566,-554,-538,-525,
+-518,-515,-508,-496,-483,-473,-465,-456,-444,-436,-432,-428,-419,-407,-396,-390,-383,-371,-355,-341,-330,
+-322,-311,-299,-288,-277,-262,-242,-219,-199,-182,-165,-146,-126,-105,-84,-61,-36,-14,4,18,28,
+36,41,47,55,64,71,72,70,70,75,85,96,104,112,124,140,158,173,182,187,191,
+200,213,229,246,267,291,317,342,366,390,416,443,468,488,507,526,550,578,610,649,692,
+737,772,794,806,821,849,887,928,961,988,1013,1040,1071,1107,1147,1191,1234,1276,1314,1351,1382,
+1411,1443,1484,1526,1554,1558,1546,1520,1460,1342,1194,1120,1237,1576,2051,2528,2929,3249,3496,3643,3660,
+3575,3460,3354,3216,2989,2701,2475,2415,2498,2598,2608,2530,2445,2414,2426,2430,2398,2349,2319,2340,2415,
+2521,2610,2632,2570,2456,2340,2257,2206,2168,2132,2098,2065,2025,1975,1920,1872,1835,1804,1778,1757,1744,
+1738,1731,1715,1686,1643,1590,1537,1494,1463,1440,1419,1397,1375,1354,1330,1303,1272,1237,1198,1155,1110,
+1070,1039,1015,992,963,921,864,801,741,689,641,588,526,464,407,359,318,290,284,298,315,
+308,268,204,126,33,-80,-207,-322,-406,-462,-513,-578,-652,-713,-747,-755,-749,-742,-741,-748,-763,
+-780,-796,-804,-805,-806,-817,-844,-883,-922,-949,-956,-946,-926,-903,-883,-864,-842,-810,-763,-709,-660,
+-624,-599,-573,-537,-490,-431,-359,-272,-182,-110,-68,-50,-33,2,55,108,141,150,138,115,92,
+79,80,94,112,134,159,192,228,260,283,299,316,342,379,421,455,469,461,439,421,419,
+436,462,484,498,502,505,511,523,541,560,580,603,628,656,682,706,728,750,773,796,815,
+834,853,875,897,918,938,958,978,998,1018,1038,1058,1078,1097,1115,1136,1159,1181,1201,1221,1241,
+1262,1282,1300,1316,1333,1353,1376,1395,1411,1425,1441,1462,1485,1505,1522,1536,1545,1547,1540,1526,1515,
+1512,1514,1516,1515,1514,1513,1512,1507,1500,1497,1500,1503,1504,1503,1506,1514,1522,1527,1529,1534,1542,
+1551,1557,1563,1574,1591,1611,1630,1648,1670,1692,1713,1729,1747,1768,1792,1813,1828,1839,1853,1873,1901,
+1936,1975,2010,2033,2046,2063,2102,2164,2180,2217,2238,2254,2271,2279,2264,2234,2233,2301,2433,2562,2605,
+2533,2393,2274,2232,2259,2303,2324,2318,2305,2301,2310,2324,2341,2361,2382,2402,2420,2438,2456,2474,2488,
+2503,2524,2550,2575,2590,2594,2591,2585,2581,2576,2574,2579,2595,2620,2649,2679,2710,2746,2785,2820,2846,
+2865,2884,2912,2949,2991,3035,3076,3104,3110,3095,3077,3076,3094,3121,3144,3172,3224,3306,3395,3456,3476,
+3467,3456,3451,3447,3436,3420,3407,3401,3400,3401,3405,3407,3404,3394,3379,3365,3349,3334,3328,3337,3350,
+3348,3320,3288,3286,3330,3398,3448,3457,3438,3418,3414,3432,3471,3524,3569,3574,3524,3439,3356,3292,3237,
+3174,3101,3030,2964,2887,2789,2674,2557,2443,2328,2221,2145,2122,2143,2177,2199,2203,2196,2180,2155,2133,
+2130,2148,2170,2172,2145,2091,2012,1904,1775,1652,1567,1524,1506,1490,1473,1464,1466,1473,1476,1475,1477,
+1485,1496,1503,1506,1507,1516,1541,1583,1627,1656,1670,1693,1750,1843,1943,2019,2062,2084,2099,2106,2105,
+2101,2098,2087,2060,2019,1980,1959,1945,1920,1872,1809,1749,1700,1663,1638,1624,1614,1600,1584,1570,1564,
+1557,1541,1520,1507,1510,1519,1525,1525,1528,1538,1551,1564,1583,1609,1635,1648,1648,1643,1643,1645,1639,
+1628,1617,1608,1595,1578,1567,1571,1589,1612,1637,1666,1695,1707,1693,1664,1639,1621,1592,1539,1480,1445,
+1437,1431,1403,1360,1329,1318,1306,1272,1225,1193,1187,1191,1188,1177,1170,1169,1163,1145,1121,1105,1097,
+1087,1067,1043,1020,998,973,946,920,897,874,846,816,788,763,736,707,678,652,624,592,558,
+526,498,469,436,401,372,347,322,293,262,232,205,178,150,125,102,74,38,-5,-48,-87,
+-124,-165,-213,-263,-312,-360,-410,-465,-524,-581,-635,-685,-732,-777,-821,-863,-905,-946,-991,-1041,-1092,
+-1141,-1185,-1227,-1270,-1316,-1358,-1392,-1421,-1455,-1501,-1555,-1606,-1645,-1672,-1699,-1734,-1778,-1823,-1860,-1882,-1889,
+-1892,-1903,-1929,-1968,-2012,-2055,-2096,-2142,-2196,-2256,-2315,-2371,-2421,-2470,-2522,-2581,-2645,-2698,-2726,-2726,-2721,
+-2732,-2767,-2809,-2843,-2866,-2891,-2926,-2966,-3004,-3039,-3081,-3135,-3194,-3248,-3295,-3338,-3380,-3418,-3447,-3466,-3477,
+-3486,-3499,-3519,-3545,-3571,-3591,-3608,-3633,-3673,-3722,-3761,-3777,-3772,-3763,-3768,-3788,-3808,-3814,-3812,-3823,-3862,
+-3912,-3937,-3923,-3897,-3905,-3954,-4004,-4007,-3965,-3929,-3939,-3980,-4005,-3994,-3970,-3968,-3990,-4009,-4011,-4009,-4019,
+-4032,-4031,-4016,-4005,-4007,-4009,-3998,-3975,-3955,-3940,-3921,-3892,-3859,-3832,-3807,-3775,-3740,-3712,-3695,-3676,-3650,
+-3625,-3594,-3524,-3378,-3181,-3024,-2996,-3080,-3158,-3116,-2946,-2741,-2599,-2543,-2527,-2505,-2473,-2450,-2444,-2439,-2426,
+-2404,-2385,-2372,-2364,-2360,-2358,-2353,-2340,-2318,-2293,-2270,-2253,-2242,-2233,-2227,-2225,-2230,-2244,-2259,-2247,-2184,
+-2072,-1954,-1886,-1891,-1938,-1973,-1964,-1925,-1886,-1864,-1853,-1840,-1831,-1841,-1878,-1924,-1951,-1939,-1892,-1826,-1761,
+-1703,-1650,-1594,-1532,-1460,-1374,-1270,-1151,-1025,-906,-804,-721,-655,-600,-555,-514,-472,-429,-386,-347,-306,
+-257,-192,-114,-30,51,128,200,268,336,408,484,557,622,682,757,862,992,1118,1200,1219,1191,
+1155,1149,1188,1262,1348,1431,1504,1570,1629,1680,1721,1751,1772,1789,1808,1834,1864,1891,1915,1944,1991,
+2056,2127,2188,2240,2294,2360,2428,2486,2525,2556,2589,2624,2650,2660,2664,2680,2723,2793,2883,2982,3078,
+3162,3230,3288,3344,3395,3427,3427,3396,3358,3337,3324,3276,3154,2966,2782,2683,2692,2754,2787,2761,2726,
+2756,2866,2992,3051,3019,2949,2917,2950,3011,3046,3038,3015,3018,3059,3118,3169,3209,3247,3290,3329,3353,
+3364,3374,3391,3415,3437,3458,3480,3499,3508,3504,3493,3484,3478,3468,3452,3440,3442,3460,3487,3520,3565,
+3619,3669,3703,3731,3782,3876,3988,4071,4094,4075,4061,4082,4130,4179,4211,4234,4254,4274,4292,4312,4340,
+4371,4391,4397,4407,4440,4495,4544,4557,4530,4485,4444,4416,4400,4394,4398,4408,4417,4421,4422,4422,4424,
+4427,4434,4446,4459,4469,4474,4479,4487,4495,4503,4523,4571,4638,4692,4700,4662,4613,4585,4565,4498,4335,
+4064,3711,3313,2894,2492,2176,2033,2110,2357,2649,2870,2987,3043,3086,3115,3098,3037,2984,2984,3025,3040,
+2980,2857,2727,2629,2563,2512,2465,2422,2380,2334,2285,2240,2201,2157,2102,2046,1999,1959,1912,1854,1798,
+1757,1719,1668,1603,1547,1514,1485,1433,1356,1289,1265,1278,1288,1267,1217,1165,1125,1093,1057,1014,971,
+932,896,857,815,770,727,689,657,627,596,560,522,482,443,407,379,358,337,309,271,231,
+198,177,163,151,138,122,107,91,76,61,44,25,5,-14,-30,-45,-61,-76,-89,-102,-118,
+-137,-157,-168,-167,-157,-147,-145,-152,-166,-182,-197,-212,-230,-253,-281,-310,-341,-372,-404,-437,-469,
+-499,-529,-559,-587,-613,-637,-659,-681,-700,-717,-730,-741,-754,-769,-784,-796,-804,-807,-807,-807,-809,
+-816,-828,-844,-860,-875,-886,-893,-898,-906,-920,-939,-958,-974,-986,-998,-1015,-1034,-1051,-1064,-1076,-1090,
+-1108,-1127,-1144,-1161,-1177,-1194,-1207,-1218,-1229,-1243,-1258,-1269,-1277,-1284,-1294,-1304,-1309,-1308,-1307,-1309,-1315,
+-1320,-1320,-1316,-1310,-1304,-1298,-1291,-1283,-1273,-1259,-1243,-1228,-1217,-1209,-1202,-1194,-1184,-1172,-1160,-1149,-1142,
+-1140,-1140,-1138,-1132,-1124,-1117,-1110,-1104,-1096,-1087,-1079,-1074,-1071,-1071,-1072,-1071,-1069,-1066,-1062,-1059,-1055,
+-1053,-1055,-1057,-1056,-1051,-1043,-1036,-1031,-1026,-1018,-1012,-1008,-1005,-1000,-994,-988,-984,-981,-976,-969,-964,
+-960,-955,-946,-938,-934,-931,-926,-916,-906,-898,-891,-881,-870,-862,-859,-857,-852,-843,-834,-828,-824,
+-818,-810,-803,-797,-791,-784,-777,-771,-765,-757,-747,-737,-730,-724,-719,-712,-704,-695,-686,-677,-671,
+-665,-658,-649,-639,-629,-618,-606,-594,-584,-575,-565,-554,-544,-538,-534,-527,-515,-503,-494,-488,-481,
+-470,-460,-453,-447,-437,-424,-414,-409,-405,-395,-379,-363,-353,-346,-336,-323,-309,-296,-281,-261,-239,
+-219,-201,-182,-160,-138,-119,-104,-88,-68,-47,-25,-7,8,18,22,24,28,36,46,50,49,
+49,55,67,81,91,99,110,124,140,152,158,163,172,186,203,218,231,247,271,300,328,
+351,371,395,421,448,471,492,515,543,574,610,651,698,741,771,785,792,808,837,874,910,
+943,975,1009,1042,1073,1107,1144,1184,1219,1250,1281,1316,1352,1388,1430,1480,1528,1556,1560,1548,1522,
+1456,1329,1179,1121,1265,1624,2093,2539,2902,3194,3425,3561,3565,3465,3332,3205,3049,2817,2541,2336,2285,
+2360,2452,2480,2456,2442,2467,2500,2493,2439,2373,2345,2380,2472,2585,2665,2666,2583,2452,2326,2235,2175,
+2130,2088,2049,2012,1971,1924,1874,1830,1793,1765,1745,1734,1731,1729,1721,1706,1683,1648,1602,1551,1505,
+1470,1448,1434,1425,1415,1402,1381,1355,1327,1300,1271,1239,1204,1171,1141,1113,1082,1044,998,942,880,
+818,762,708,649,583,515,455,404,362,330,315,313,308,277,213,126,28,-74,-184,-294,-386,
+-451,-498,-544,-601,-663,-715,-749,-768,-774,-771,-764,-758,-761,-772,-786,-795,-796,-796,-802,-822,-855,
+-892,-920,-931,-926,-911,-892,-875,-859,-840,-809,-762,-704,-647,-603,-573,-548,-516,-471,-412,-339,-255,
+-169,-93,-37,0,30,62,98,137,176,209,225,218,190,156,133,128,136,153,175,204,236,
+266,291,310,329,356,395,442,486,511,507,481,453,442,454,478,502,517,525,532,542,559,
+581,605,628,651,676,703,729,750,769,787,809,831,851,869,889,912,937,960,981,1001,1020,
+1039,1058,1077,1097,1118,1138,1157,1175,1196,1217,1238,1257,1277,1296,1314,1330,1345,1361,1381,1402,1420,
+1434,1445,1460,1480,1503,1524,1542,1555,1563,1563,1555,1541,1528,1521,1521,1523,1524,1523,1520,1517,1513,
+1510,1508,1508,1508,1507,1508,1512,1517,1521,1522,1524,1531,1540,1546,1549,1554,1566,1584,1604,1625,1647,
+1672,1697,1718,1735,1751,1771,1792,1809,1820,1829,1844,1868,1900,1935,1967,1993,2015,2041,2079,2130,2180,
+2159,2157,2152,2163,2187,2204,2196,2180,2199,2284,2413,2518,2535,2456,2339,2258,2245,2277,2308,2311,2294,
+2280,2281,2294,2311,2330,2353,2376,2395,2409,2422,2440,2460,2477,2493,2511,2535,2562,2583,2591,2587,2579,
+2572,2569,2569,2577,2594,2621,2653,2685,2715,2745,2779,2813,2841,2858,2865,2869,2880,2907,2957,3022,3082,
+3112,3107,3083,3068,3078,3105,3134,3161,3199,3253,3311,3353,3373,3386,3408,3439,3464,3468,3456,3441,3436,
+3444,3460,3476,3484,3479,3462,3440,3420,3403,3389,3384,3391,3404,3403,3379,3346,3332,3357,3407,3453,3475,
+3476,3475,3486,3512,3549,3587,3606,3583,3510,3409,3315,3249,3205,3164,3112,3042,2949,2831,2699,2573,2466,
+2374,2283,2198,2142,2133,2164,2202,2225,2227,2217,2204,2188,2177,2180,2197,2215,2216,2190,2134,2047,1930,
+1801,1688,1615,1579,1559,1539,1520,1513,1520,1530,1535,1536,1539,1547,1558,1564,1565,1568,1582,1614,1657,
+1696,1721,1744,1794,1886,2000,2097,2149,2164,2169,2175,2180,2176,2169,2163,2153,2130,2095,2063,2045,2031,
+2001,1947,1880,1817,1767,1730,1705,1689,1679,1666,1652,1644,1641,1637,1623,1603,1592,1595,1600,1596,1585,
+1579,1587,1604,1625,1647,1674,1698,1713,1718,1721,1729,1736,1738,1732,1723,1709,1691,1673,1671,1690,1722,
+1751,1771,1783,1787,1775,1746,1717,1705,1703,1680,1621,1547,1498,1481,1472,1443,1400,1367,1356,1345,1314,
+1273,1247,1245,1253,1249,1236,1225,1222,1213,1193,1167,1150,1141,1132,1112,1087,1063,1041,1017,994,971,
+950,924,893,862,837,814,788,757,727,702,676,645,607,572,543,515,484,450,419,395,372,
+346,316,284,254,227,202,180,157,129,94,54,16,-20,-60,-104,-150,-195,-240,-288,-342,-401,
+-458,-514,-567,-618,-664,-707,-751,-797,-844,-891,-936,-984,-1033,-1078,-1116,-1152,-1194,-1241,-1285,-1321,-1350,
+-1385,-1434,-1489,-1539,-1574,-1601,-1632,-1676,-1729,-1779,-1814,-1826,-1818,-1806,-1806,-1829,-1872,-1927,-1986,-2047,-2108,
+-2166,-2219,-2271,-2325,-2380,-2433,-2482,-2533,-2587,-2634,-2658,-2661,-2663,-2684,-2724,-2763,-2781,-2786,-2797,-2829,-2875,
+-2920,-2963,-3015,-3085,-3165,-3236,-3287,-3320,-3347,-3376,-3405,-3429,-3443,-3450,-3461,-3486,-3520,-3551,-3571,-3583,-3604,
+-3647,-3701,-3744,-3758,-3746,-3734,-3745,-3779,-3819,-3839,-3841,-3846,-3875,-3918,-3943,-3934,-3912,-3920,-3966,-4010,-4005,
+-3956,-3916,-3929,-3980,-4018,-4016,-3998,-3997,-4015,-4027,-4021,-4011,-4015,-4028,-4031,-4021,-4010,-4011,-4011,-4000,-3980,
+-3964,-3954,-3939,-3912,-3880,-3854,-3832,-3804,-3773,-3751,-3735,-3711,-3673,-3636,-3607,-3557,-3439,-3261,-3104,-3062,-3136,
+-3214,-3174,-2998,-2782,-2634,-2582,-2573,-2550,-2509,-2478,-2471,-2475,-2470,-2455,-2443,-2437,-2433,-2423,-2405,-2385,-2365,
+-2345,-2325,-2305,-2287,-2272,-2264,-2268,-2285,-2309,-2331,-2332,-2292,-2203,-2085,-1983,-1938,-1957,-2002,-2025,-2009,-1971,
+-1939,-1920,-1902,-1878,-1863,-1876,-1919,-1969,-1994,-1978,-1925,-1858,-1793,-1737,-1686,-1636,-1579,-1514,-1436,-1341,-1229,
+-1105,-984,-879,-798,-738,-692,-652,-614,-578,-543,-509,-471,-418,-346,-260,-171,-85,-1,82,163,234,
+297,359,428,501,570,639,725,844,983,1102,1161,1151,1104,1068,1078,1135,1221,1312,1394,1463,1523,
+1579,1631,1676,1703,1710,1704,1701,1715,1742,1768,1788,1814,1863,1939,2023,2096,2157,2222,2302,2387,2454,
+2491,2511,2532,2561,2591,2614,2635,2669,2722,2790,2862,2934,3006,3078,3148,3216,3284,3344,3380,3375,3330,
+3272,3232,3205,3151,3025,2841,2670,2594,2626,2695,2719,2681,2648,2701,2845,2997,3061,3015,2919,2860,2869,
+2915,2947,2947,2938,2956,3008,3075,3132,3172,3206,3243,3280,3306,3319,3323,3329,3339,3357,3383,3414,3441,
+3451,3444,3432,3424,3420,3409,3391,3378,3381,3401,3425,3449,3486,3543,3605,3650,3676,3710,3784,3888,3979,
+4018,4013,4006,4028,4075,4121,4153,4174,4191,4206,4218,4235,4265,4300,4325,4335,4350,4391,4455,4507,4517,
+4485,4436,4398,4378,4370,4368,4369,4372,4375,4375,4375,4376,4379,4385,4395,4410,4426,4437,4446,4456,4467,
+4476,4483,4506,4559,4627,4671,4662,4615,4575,4560,4537,4439,4224,3901,3510,3082,2647,2259,2005,1965,2141,
+2439,2725,2912,3003,3053,3095,3116,3089,3020,2954,2926,2930,2929,2899,2841,2769,2683,2585,2486,2409,2362,
+2331,2295,2250,2209,2175,2137,2084,2023,1969,1925,1880,1826,1773,1731,1693,1644,1583,1528,1492,1460,1405,
+1326,1255,1227,1240,1258,1247,1205,1155,1117,1089,1057,1012,963,919,881,845,804,759,719,687,660,
+631,599,565,530,493,451,409,374,350,332,308,275,236,201,174,154,141,133,126,113,95,
+74,57,42,26,7,-11,-27,-41,-57,-75,-92,-103,-113,-127,-146,-160,-162,-154,-146,-147,-158,
+-176,-195,-213,-230,-249,-268,-289,-310,-335,-365,-399,-437,-474,-507,-536,-564,-592,-621,-648,-673,-693,
+-711,-727,-742,-758,-774,-788,-799,-808,-817,-825,-830,-831,-830,-831,-837,-848,-864,-882,-898,-909,-915,
+-919,-927,-941,-958,-973,-987,-1003,-1022,-1042,-1058,-1069,-1080,-1096,-1114,-1132,-1148,-1164,-1179,-1193,-1203,-1211,
+-1222,-1235,-1246,-1254,-1261,-1270,-1283,-1294,-1299,-1297,-1295,-1295,-1298,-1299,-1298,-1294,-1291,-1288,-1282,-1275,-1266,
+-1255,-1244,-1232,-1221,-1212,-1203,-1194,-1185,-1176,-1167,-1155,-1144,-1136,-1132,-1131,-1131,-1129,-1127,-1123,-1116,-1108,
+-1098,-1089,-1082,-1077,-1074,-1074,-1075,-1076,-1074,-1071,-1067,-1062,-1058,-1057,-1058,-1061,-1061,-1057,-1052,-1049,-1046,
+-1041,-1033,-1027,-1024,-1021,-1015,-1006,-999,-996,-993,-988,-983,-980,-977,-971,-959,-946,-940,-939,-936,-927,
+-916,-909,-905,-898,-887,-876,-870,-867,-862,-855,-847,-841,-836,-830,-823,-817,-811,-805,-798,-791,-787,
+-781,-773,-761,-750,-741,-734,-727,-720,-714,-706,-697,-688,-682,-678,-672,-662,-649,-639,-630,-621,-609,
+-597,-588,-581,-573,-565,-559,-554,-548,-537,-526,-517,-511,-503,-493,-482,-475,-469,-458,-444,-433,-430,
+-429,-420,-404,-386,-374,-366,-356,-344,-330,-317,-301,-280,-257,-236,-217,-198,-175,-153,-135,-123,-110,
+-93,-73,-53,-35,-18,-6,-2,-4,-3,3,17,28,33,34,40,51,65,76,85,92,102,
+112,122,131,142,157,175,192,206,220,239,264,292,318,339,360,385,412,438,460,480,504,
+534,567,605,648,694,731,751,758,764,785,819,857,892,925,962,1000,1033,1063,1096,1137,1178,
+1210,1235,1262,1298,1339,1381,1429,1484,1535,1565,1571,1563,1538,1466,1327,1172,1123,1288,1660,2122,2542,
+2875,3147,3368,3497,3490,3373,3224,3086,2932,2720,2478,2302,2261,2327,2408,2444,2449,2473,2522,2557,2540,
+2479,2419,2408,2461,2557,2654,2706,2681,2585,2455,2331,2235,2165,2110,2062,2019,1977,1933,1887,1842,1801,
+1766,1738,1721,1716,1717,1714,1705,1692,1677,1655,1621,1577,1531,1494,1469,1456,1451,1448,1439,1421,1394,
+1368,1345,1325,1302,1276,1250,1223,1193,1157,1115,1066,1008,941,871,806,746,684,618,552,497,453,
+418,385,354,321,275,204,108,0,-107,-208,-304,-390,-456,-500,-530,-563,-604,-651,-696,-736,-770,
+-792,-798,-791,-780,-776,-782,-792,-797,-794,-787,-787,-800,-831,-869,-901,-915,-910,-893,-873,-855,-840,
+-823,-797,-756,-703,-645,-597,-563,-537,-507,-466,-411,-342,-265,-184,-107,-40,16,60,92,117,145,
+185,234,277,292,277,244,212,194,189,194,207,225,246,267,287,308,331,359,397,446,495,
+528,531,508,480,468,476,495,514,528,540,553,568,587,610,636,662,687,712,738,764,787,
+805,825,846,869,889,908,929,954,981,1005,1025,1044,1062,1080,1097,1114,1135,1157,1178,1195,1212,
+1231,1252,1274,1293,1309,1325,1341,1356,1370,1385,1403,1421,1437,1451,1463,1479,1498,1521,1543,1561,1574,
+1581,1581,1573,1561,1546,1534,1528,1528,1529,1528,1523,1519,1516,1517,1517,1515,1510,1508,1510,1514,1516,
+1515,1515,1520,1530,1539,1544,1546,1553,1568,1586,1605,1623,1645,1669,1694,1716,1736,1757,1778,1798,1813,
+1823,1834,1850,1874,1900,1926,1949,1974,2007,2051,2101,2141,2159,2094,2070,2067,2089,2118,2129,2124,2134,
+2191,2295,2402,2453,2423,2341,2265,2240,2264,2299,2311,2297,2275,2266,2272,2284,2298,2316,2340,2366,2383,
+2390,2399,2418,2446,2472,2487,2498,2515,2540,2564,2577,2576,2568,2561,2560,2564,2575,2595,2625,2660,2691,
+2717,2741,2769,2800,2830,2850,2855,2849,2843,2856,2902,2976,3054,3104,3111,3088,3064,3064,3088,3124,3159,
+3189,3214,3233,3245,3259,3291,3349,3421,3482,3513,3513,3498,3486,3490,3506,3526,3539,3539,3526,3504,3482,
+3461,3445,3438,3443,3452,3452,3433,3404,3386,3395,3429,3469,3498,3514,3523,3538,3562,3592,3614,3605,3551,
+3456,3348,3258,3203,3174,3149,3104,3025,2906,2762,2619,2505,2425,2363,2297,2230,2182,2173,2195,2226,2244,
+2247,2242,2237,2232,2228,2228,2234,2241,2238,2215,2163,2075,1959,1835,1732,1668,1633,1610,1587,1569,1564,
+1572,1584,1592,1597,1601,1607,1615,1621,1626,1636,1657,1692,1732,1765,1791,1829,1905,2019,2138,2218,2247,
+2245,2243,2250,2254,2248,2236,2228,2219,2198,2166,2135,2112,2090,2052,1996,1933,1877,1832,1796,1769,1753,
+1743,1732,1722,1715,1714,1712,1702,1689,1682,1681,1675,1659,1640,1635,1649,1675,1701,1722,1741,1760,1776,
+1789,1801,1810,1814,1812,1809,1806,1797,1780,1766,1774,1809,1852,1879,1883,1874,1861,1837,1804,1780,1781,
+1792,1775,1707,1614,1543,1515,1506,1484,1444,1411,1396,1385,1360,1326,1305,1306,1311,1305,1287,1272,1265,
+1256,1237,1214,1197,1186,1174,1153,1130,1108,1089,1068,1043,1019,995,968,938,910,888,866,837,803,
+771,745,722,692,656,620,590,563,533,501,471,447,425,398,368,337,309,284,260,237,212,
+183,150,116,81,44,1,-44,-88,-128,-169,-219,-277,-336,-391,-444,-498,-551,-598,-640,-682,-731,
+-783,-832,-877,-921,-966,-1009,-1047,-1082,-1123,-1169,-1213,-1248,-1279,-1317,-1369,-1425,-1471,-1504,-1532,-1569,-1619,
+-1675,-1726,-1757,-1763,-1746,-1723,-1713,-1730,-1774,-1839,-1917,-2000,-2078,-2144,-2195,-2243,-2297,-2357,-2415,-2467,-2517,
+-2572,-2625,-2664,-2687,-2709,-2746,-2791,-2823,-2824,-2806,-2795,-2810,-2841,-2876,-2910,-2955,-3023,-3106,-3186,-3245,-3283,
+-3309,-3338,-3372,-3404,-3423,-3430,-3437,-3459,-3496,-3532,-3556,-3571,-3594,-3637,-3690,-3729,-3738,-3721,-3706,-3719,-3763,
+-3818,-3856,-3867,-3871,-3890,-3927,-3954,-3951,-3932,-3934,-3970,-4006,-4001,-3956,-3921,-3936,-3988,-4029,-4032,-4016,-4015,
+-4032,-4044,-4035,-4020,-4018,-4026,-4028,-4018,-4009,-4009,-4008,-3997,-3978,-3965,-3959,-3949,-3925,-3898,-3878,-3861,-3835,
+-3804,-3782,-3770,-3748,-3703,-3650,-3606,-3556,-3462,-3315,-3181,-3142,-3203,-3264,-3212,-3029,-2810,-2665,-2620,-2618,-2598,
+-2554,-2518,-2510,-2513,-2506,-2487,-2473,-2471,-2471,-2459,-2434,-2405,-2384,-2372,-2363,-2351,-2334,-2316,-2310,-2323,-2354,
+-2387,-2402,-2383,-2324,-2233,-2134,-2057,-2023,-2029,-2048,-2053,-2038,-2015,-1995,-1972,-1939,-1900,-1881,-1900,-1951,-2003,
+-2023,-2001,-1944,-1875,-1810,-1754,-1708,-1667,-1623,-1571,-1503,-1413,-1301,-1177,-1055,-953,-881,-834,-800,-768,-730,
+-689,-651,-613,-568,-504,-417,-319,-223,-136,-51,36,124,199,259,315,378,447,512,577,662,786,
+932,1051,1097,1069,1014,989,1021,1098,1191,1280,1357,1422,1477,1524,1567,1607,1631,1632,1613,1596,1602,
+1629,1661,1685,1711,1759,1835,1924,2006,2079,2156,2247,2340,2411,2448,2464,2478,2503,2535,2570,2611,2663,
+2724,2787,2846,2901,2957,3017,3082,3153,3230,3303,3349,3346,3295,3224,3167,3125,3059,2929,2750,2592,2528,
+2565,2633,2654,2615,2583,2628,2752,2879,2927,2884,2808,2769,2791,2839,2868,2869,2870,2905,2978,3062,3125,
+3155,3169,3186,3214,3245,3265,3274,3275,3279,3292,3318,3352,3381,3393,3386,3373,3365,3362,3353,3337,3326,
+3333,3353,3368,3378,3402,3462,3545,3614,3649,3669,3715,3800,3892,3948,3959,3956,3972,4013,4058,4091,4112,
+4129,4141,4152,4171,4203,4242,4269,4283,4303,4347,4409,4455,4457,4419,4371,4340,4329,4329,4332,4336,4341,
+4343,4341,4337,4337,4342,4351,4364,4378,4390,4400,4413,4431,4449,4459,4466,4490,4544,4609,4640,4617,4566,
+4536,4535,4505,4370,4094,3708,3266,2815,2394,2065,1909,1973,2215,2522,2775,2928,3007,3058,3097,3107,3073,
+3009,2941,2885,2842,2812,2804,2814,2813,2759,2640,2495,2378,2313,2282,2251,2210,2173,2145,2113,2062,1998,
+1939,1892,1849,1800,1748,1702,1663,1620,1568,1518,1479,1443,1388,1312,1241,1207,1213,1229,1223,1187,1142,
+1106,1079,1047,1001,948,903,869,838,800,758,720,690,666,638,606,572,539,504,460,414,373,
+345,324,304,277,246,212,179,149,130,124,123,116,97,74,55,42,29,11,-6,-19,-30,
+-47,-71,-94,-110,-119,-129,-145,-160,-166,-163,-159,-161,-173,-189,-208,-228,-249,-271,-291,-307,-323,
+-341,-367,-401,-441,-480,-514,-543,-569,-596,-624,-651,-676,-697,-715,-732,-751,-772,-791,-804,-812,-818,
+-827,-838,-848,-854,-855,-854,-856,-862,-873,-888,-906,-920,-929,-934,-939,-949,-961,-975,-989,-1007,-1028,
+-1049,-1065,-1076,-1087,-1101,-1117,-1132,-1147,-1163,-1178,-1189,-1195,-1202,-1211,-1223,-1232,-1238,-1245,-1257,-1271,-1282,
+-1285,-1283,-1281,-1282,-1282,-1280,-1276,-1273,-1270,-1266,-1260,-1254,-1247,-1240,-1232,-1223,-1213,-1203,-1192,-1183,-1176,
+-1172,-1167,-1160,-1150,-1139,-1131,-1126,-1123,-1124,-1126,-1128,-1124,-1115,-1104,-1094,-1088,-1083,-1080,-1080,-1080,-1080,
+-1078,-1075,-1072,-1069,-1064,-1062,-1062,-1065,-1065,-1063,-1060,-1059,-1059,-1057,-1051,-1047,-1044,-1040,-1032,-1021,-1014,
+-1010,-1006,-1000,-994,-992,-991,-986,-973,-958,-950,-947,-944,-935,-924,-918,-916,-910,-900,-887,-879,-874,
+-869,-863,-857,-852,-849,-843,-837,-832,-827,-822,-815,-808,-802,-796,-787,-776,-766,-759,-750,-740,-730,
+-721,-712,-702,-693,-687,-685,-681,-671,-658,-648,-641,-635,-624,-612,-604,-598,-592,-583,-574,-568,-563,
+-555,-544,-533,-524,-516,-507,-499,-493,-488,-479,-465,-454,-451,-450,-443,-426,-407,-392,-382,-373,-361,
+-348,-336,-320,-298,-273,-250,-232,-214,-193,-173,-156,-142,-127,-109,-89,-71,-56,-41,-29,-25,-28,
+-31,-26,-11,5,17,22,27,36,48,59,69,76,82,89,98,111,127,144,159,173,189,
+210,235,262,287,309,329,352,379,407,431,451,470,493,522,555,594,637,680,712,725,729,
+739,767,807,847,883,918,956,993,1022,1049,1085,1131,1177,1212,1239,1270,1310,1354,1397,1443,1496,
+1546,1577,1587,1583,1560,1481,1330,1167,1122,1298,1679,2137,2546,2871,3143,3366,3488,3464,3324,3156,3015,
+2876,2696,2491,2343,2311,2371,2447,2485,2500,2528,2570,2592,2563,2503,2462,2480,2557,2657,2730,2739,2676,
+2566,2444,2336,2246,2171,2106,2051,2004,1959,1912,1867,1828,1793,1760,1731,1713,1708,1708,1704,1693,1681,
+1672,1661,1641,1610,1574,1541,1515,1496,1485,1479,1470,1453,1428,1403,1382,1363,1342,1320,1297,1272,1243,
+1208,1165,1113,1049,974,896,824,760,699,635,575,529,500,475,439,382,304,206,92,-25,-135,
+-230,-312,-386,-448,-493,-518,-532,-549,-576,-613,-657,-705,-752,-789,-808,-810,-805,-802,-805,-809,-806,
+-794,-778,-769,-778,-809,-852,-889,-904,-895,-870,-841,-818,-804,-793,-777,-748,-705,-654,-606,-569,-540,
+-512,-477,-431,-373,-304,-227,-148,-70,0,58,98,122,143,175,222,271,304,313,304,286,267,
+250,239,237,243,254,265,280,301,327,359,399,447,498,533,538,519,496,488,497,512,525,
+537,552,571,591,611,634,663,692,719,743,767,793,817,840,862,886,910,932,951,973,998,
+1024,1047,1065,1082,1100,1118,1135,1153,1173,1194,1214,1230,1245,1264,1286,1307,1325,1339,1353,1369,1384,
+1399,1413,1428,1443,1459,1473,1487,1502,1520,1540,1561,1580,1592,1598,1596,1590,1578,1562,1546,1535,1534,
+1537,1537,1532,1525,1522,1523,1523,1517,1509,1505,1508,1513,1513,1512,1515,1525,1536,1543,1547,1552,1565,
+1582,1599,1612,1624,1642,1663,1685,1706,1730,1756,1782,1804,1820,1832,1845,1861,1878,1896,1914,1937,1973,
+2020,2071,2107,2113,2094,2011,2001,2032,2079,2105,2099,2094,2136,2237,2354,2421,2403,2324,2243,2212,2236,
+2282,2312,2309,2287,2268,2266,2274,2281,2289,2304,2330,2357,2371,2373,2379,2403,2442,2476,2491,2492,2496,
+2514,2539,2556,2560,2554,2548,2548,2555,2571,2597,2631,2665,2693,2713,2731,2751,2778,2806,2831,2845,2846,
+2841,2846,2880,2944,3023,3084,3107,3092,3062,3047,3061,3101,3150,3188,3204,3200,3190,3196,3238,3317,3416,
+3508,3566,3584,3572,3551,3537,3540,3553,3569,3577,3575,3559,3535,3508,3489,3483,3489,3498,3497,3482,3457,
+3433,3424,3436,3464,3496,3520,3530,3535,3543,3555,3556,3523,3449,3349,3253,3188,3156,3142,3120,3068,2974,
+2842,2694,2564,2475,2422,2381,2331,2274,2231,2217,2229,2249,2264,2271,2275,2279,2282,2282,2278,2274,2271,
+2267,2251,2208,2126,2014,1895,1796,1729,1688,1659,1636,1620,1617,1624,1636,1648,1657,1663,1667,1672,1682,
+1696,1716,1743,1777,1811,1842,1875,1930,2022,2141,2248,2308,2321,2316,2319,2331,2336,2327,2313,2303,2293,
+2271,2236,2198,2165,2131,2089,2039,1990,1949,1914,1880,1851,1832,1820,1808,1796,1787,1784,1783,1779,1773,
+1769,1763,1748,1723,1703,1704,1727,1759,1785,1801,1812,1824,1841,1861,1878,1883,1878,1870,1872,1881,1882,
+1866,1849,1859,1897,1940,1956,1946,1932,1924,1911,1884,1856,1850,1859,1842,1768,1660,1571,1534,1530,1519,
+1489,1456,1439,1427,1407,1378,1360,1360,1364,1356,1338,1322,1312,1302,1284,1262,1246,1233,1217,1195,1173,
+1155,1138,1116,1088,1059,1034,1010,984,959,937,913,883,847,814,789,766,738,703,669,640,612,
+583,552,524,500,475,446,416,390,368,345,320,293,265,236,205,174,141,103,60,15,-25,
+-63,-104,-156,-214,-271,-322,-373,-427,-483,-531,-572,-614,-664,-719,-770,-813,-852,-893,-935,-975,-1014,
+-1055,-1100,-1139,-1172,-1204,-1249,-1307,-1364,-1408,-1437,-1467,-1509,-1561,-1614,-1658,-1685,-1690,-1677,-1656,-1646,-1661,
+-1706,-1776,-1864,-1957,-2044,-2113,-2165,-2212,-2268,-2331,-2392,-2446,-2499,-2559,-2623,-2679,-2721,-2759,-2805,-2851,-2879,
+-2876,-2854,-2839,-2845,-2865,-2885,-2900,-2919,-2955,-3009,-3077,-3143,-3202,-3251,-3297,-3345,-3388,-3415,-3423,-3426,-3440,
+-3472,-3512,-3544,-3567,-3594,-3635,-3683,-3716,-3720,-3701,-3681,-3686,-3726,-3788,-3844,-3877,-3894,-3915,-3948,-3974,-3975,
+-3958,-3953,-3979,-4013,-4018,-3989,-3962,-3973,-4015,-4046,-4044,-4026,-4022,-4038,-4052,-4050,-4039,-4035,-4036,-4030,-4016,
+-4005,-4004,-4002,-3988,-3969,-3957,-3953,-3945,-3926,-3907,-3897,-3888,-3865,-3831,-3804,-3792,-3777,-3736,-3675,-3615,-3558,
+-3479,-3367,-3266,-3239,-3288,-3327,-3259,-3071,-2853,-2709,-2665,-2666,-2652,-2613,-2579,-2565,-2559,-2540,-2512,-2490,-2485,
+-2484,-2472,-2449,-2426,-2413,-2410,-2410,-2402,-2386,-2373,-2377,-2401,-2435,-2455,-2444,-2400,-2338,-2272,-2213,-2166,-2132,
+-2109,-2092,-2076,-2062,-2050,-2032,-1999,-1950,-1904,-1888,-1915,-1970,-2019,-2034,-2008,-1954,-1889,-1826,-1771,-1727,-1694,
+-1663,-1622,-1560,-1469,-1352,-1223,-1104,-1014,-962,-940,-927,-904,-863,-810,-753,-698,-638,-561,-465,-360,-260,
+-170,-85,3,89,162,219,272,332,397,454,506,581,704,856,982,1029,999,948,937,986,1069,
+1156,1235,1309,1379,1435,1473,1500,1525,1544,1544,1522,1500,1499,1527,1567,1604,1639,1690,1766,1857,1948,
+2033,2117,2206,2290,2354,2393,2414,2431,2452,2484,2526,2580,2643,2708,2770,2829,2889,2948,3005,3062,3128,
+3205,3281,3326,3318,3263,3193,3137,3089,3010,2868,2684,2528,2464,2496,2559,2583,2553,2520,2536,2605,2677,
+2702,2680,2656,2673,2727,2780,2801,2796,2805,2863,2964,3069,3134,3148,3135,3129,3146,3177,3204,3217,3220,
+3224,3234,3256,3285,3311,3324,3321,3311,3304,3300,3293,3279,3272,3282,3300,3308,3305,3319,3383,3490,3592,
+3647,3661,3682,3742,3824,3886,3904,3899,3905,3935,3977,4014,4039,4056,4071,4087,4113,4150,4190,4218,4233,
+4257,4303,4361,4399,4394,4356,4313,4288,4280,4282,4287,4297,4309,4316,4313,4306,4303,4307,4318,4333,4345,
+4355,4365,4381,4404,4425,4435,4442,4468,4522,4580,4599,4566,4516,4494,4496,4448,4270,3935,3489,3005,2548,
+2170,1933,1893,2050,2327,2607,2808,2925,2996,3051,3084,3081,3043,2990,2932,2863,2783,2719,2709,2755,2802,
+2779,2661,2494,2351,2270,2234,2206,2170,2135,2109,2081,2036,1975,1915,1868,1826,1778,1725,1675,1635,1597,
+1557,1514,1472,1429,1372,1302,1237,1200,1197,1206,1200,1170,1129,1092,1063,1028,982,932,891,863,839,
+808,767,728,696,671,645,613,581,548,512,468,421,378,345,319,297,275,252,224,188,149,
+121,112,114,111,95,74,57,46,33,17,1,-7,-15,-32,-62,-93,-116,-130,-141,-157,-173,
+-182,-185,-186,-191,-200,-211,-224,-241,-264,-287,-308,-324,-337,-353,-376,-408,-446,-485,-519,-548,-573,
+-599,-627,-654,-680,-704,-724,-743,-763,-784,-802,-816,-824,-831,-840,-853,-866,-875,-880,-883,-885,-889,
+-894,-903,-916,-931,-942,-951,-958,-966,-975,-984,-995,-1010,-1030,-1050,-1066,-1077,-1087,-1097,-1108,-1121,-1136,
+-1152,-1167,-1175,-1180,-1185,-1196,-1207,-1215,-1220,-1228,-1242,-1257,-1265,-1266,-1264,-1264,-1267,-1266,-1262,-1258,-1254,
+-1250,-1244,-1238,-1234,-1232,-1230,-1223,-1211,-1198,-1185,-1174,-1167,-1165,-1166,-1165,-1161,-1153,-1144,-1135,-1127,-1120,
+-1119,-1122,-1125,-1124,-1116,-1105,-1096,-1091,-1088,-1087,-1085,-1084,-1081,-1078,-1076,-1076,-1075,-1072,-1069,-1068,-1069,
+-1071,-1069,-1067,-1066,-1066,-1066,-1063,-1060,-1057,-1053,-1045,-1036,-1029,-1025,-1020,-1012,-1004,-1001,-1001,-997,-987,
+-973,-964,-959,-954,-945,-935,-929,-925,-917,-905,-893,-885,-881,-876,-871,-866,-864,-861,-857,-852,-848,
+-846,-841,-834,-826,-818,-810,-800,-790,-784,-778,-770,-758,-744,-732,-721,-710,-700,-694,-694,-692,-683,
+-670,-660,-653,-646,-635,-624,-617,-613,-607,-596,-584,-576,-573,-567,-556,-543,-532,-525,-517,-511,-508,
+-505,-498,-487,-476,-470,-466,-459,-444,-428,-414,-404,-394,-381,-368,-356,-339,-317,-291,-269,-251,-234,
+-215,-195,-177,-162,-143,-121,-99,-82,-69,-56,-45,-40,-44,-50,-47,-34,-16,-1,6,11,18,
+28,39,51,61,68,74,83,97,114,127,137,148,168,196,227,254,275,293,314,340,367,
+393,416,437,460,487,517,550,587,629,669,698,712,721,739,772,814,854,890,926,962,995,
+1021,1049,1089,1140,1190,1228,1259,1295,1341,1385,1425,1466,1514,1561,1591,1602,1601,1575,1488,1324,1152,
+1103,1280,1659,2112,2522,2858,3148,3384,3505,3464,3301,3116,2973,2850,2696,2517,2383,2355,2415,2493,2537,
+2555,2577,2607,2614,2578,2521,2495,2537,2637,2742,2790,2754,2652,2528,2421,2336,2261,2184,2109,2047,1998,
+1952,1905,1862,1828,1799,1768,1736,1713,1705,1704,1699,1688,1676,1669,1664,1654,1638,1619,1598,1573,1549,
+1529,1515,1502,1485,1462,1440,1419,1397,1372,1345,1319,1295,1268,1233,1188,1132,1062,983,902,828,762,
+699,636,584,554,541,524,476,385,259,117,-20,-136,-226,-293,-350,-403,-450,-481,-494,-498,-507,
+-528,-562,-606,-657,-711,-758,-790,-807,-814,-819,-822,-821,-811,-792,-770,-755,-761,-791,-834,-871,-885,
+-869,-836,-801,-776,-766,-764,-761,-745,-712,-668,-624,-587,-556,-529,-502,-469,-423,-361,-283,-198,-113,
+-36,28,78,110,131,153,182,218,253,282,302,310,302,282,262,251,254,262,270,282,300,
+327,362,404,455,506,541,546,527,506,501,512,525,536,547,567,591,616,639,666,699,732,
+759,779,799,823,850,876,902,928,954,977,997,1017,1040,1064,1086,1103,1119,1136,1155,1174,1194,
+1214,1235,1252,1267,1282,1301,1322,1341,1355,1367,1381,1397,1414,1430,1443,1457,1473,1490,1506,1521,1534,
+1547,1563,1583,1601,1612,1614,1609,1601,1590,1574,1555,1541,1539,1545,1548,1543,1534,1528,1527,1526,1519,
+1511,1508,1513,1518,1520,1522,1527,1536,1542,1544,1547,1558,1577,1594,1605,1611,1620,1635,1655,1674,1694,
+1720,1751,1781,1807,1826,1841,1855,1870,1883,1898,1917,1948,1991,2040,2075,2078,2049,2011,1955,1982,2048,
+2108,2119,2094,2094,2169,2301,2413,2432,2356,2250,2187,2195,2247,2296,2313,2299,2278,2266,2268,2275,2279,
+2283,2298,2323,2349,2361,2361,2368,2397,2444,2483,2495,2486,2480,2491,2514,2534,2541,2539,2535,2537,2547,
+2568,2599,2635,2667,2688,2703,2716,2733,2752,2774,2800,2826,2846,2855,2863,2884,2929,2995,3059,3099,3100,
+3071,3038,3033,3067,3129,3189,3220,3218,3203,3204,3242,3317,3416,3517,3596,3639,3643,3622,3595,3579,3578,
+3590,3603,3609,3597,3567,3532,3508,3504,3514,3525,3525,3511,3487,3455,3426,3414,3426,3458,3486,3494,3482,
+3465,3450,3428,3380,3306,3224,3162,3132,3122,3109,3074,3003,2895,2763,2631,2527,2462,2423,2389,2345,2298,
+2264,2251,2257,2272,2286,2298,2309,2321,2333,2340,2341,2335,2330,2326,2315,2279,2203,2093,1973,1870,1796,
+1746,1711,1687,1675,1673,1679,1690,1705,1718,1725,1729,1736,1752,1779,1809,1839,1869,1899,1930,1971,2036,
+2132,2244,2336,2385,2395,2395,2405,2418,2421,2410,2395,2385,2372,2345,2304,2260,2220,2182,2144,2108,2078,
+2052,2023,1990,1957,1933,1916,1900,1884,1872,1865,1862,1858,1854,1850,1840,1820,1795,1779,1786,1812,1843,
+1865,1875,1881,1890,1907,1929,1947,1950,1940,1935,1950,1974,1980,1957,1926,1924,1956,1991,1995,1977,1969,
+1985,1996,1973,1927,1895,1887,1867,1798,1689,1595,1556,1560,1562,1539,1507,1485,1472,1454,1430,1412,1408,
+1411,1405,1391,1376,1364,1351,1332,1311,1294,1281,1264,1241,1219,1202,1184,1159,1129,1100,1077,1056,1034,
+1009,983,956,925,892,862,836,811,782,749,718,691,664,635,605,577,550,520,488,460,438,
+422,401,374,344,314,286,257,225,192,156,116,75,36,-2,-46,-97,-153,-206,-254,-304,-359,
+-415,-463,-504,-546,-597,-654,-704,-745,-781,-819,-860,-902,-944,-989,-1032,-1067,-1097,-1131,-1182,-1244,-1303,
+-1344,-1374,-1407,-1453,-1505,-1552,-1586,-1606,-1613,-1608,-1599,-1598,-1620,-1669,-1741,-1827,-1917,-1998,-2064,-2116,-2164,
+-2221,-2284,-2345,-2398,-2450,-2510,-2575,-2633,-2680,-2720,-2761,-2801,-2829,-2839,-2841,-2849,-2871,-2899,-2921,-2928,-2921,
+-2913,-2919,-2953,-3014,-3087,-3159,-3223,-3283,-3335,-3372,-3386,-3387,-3397,-3428,-3471,-3511,-3540,-3567,-3603,-3646,-3679,
+-3690,-3677,-3653,-3644,-3669,-3730,-3806,-3872,-3916,-3949,-3981,-4004,-4006,-3989,-3980,-4000,-4036,-4056,-4044,-4023,-4022,
+-4044,-4061,-4055,-4036,-4028,-4039,-4053,-4057,-4055,-4055,-4053,-4041,-4021,-4005,-3999,-3992,-3976,-3955,-3943,-3939,-3933,
+-3919,-3908,-3908,-3909,-3890,-3852,-3819,-3806,-3797,-3765,-3704,-3635,-3572,-3502,-3420,-3352,-3340,-3379,-3398,-3315,-3124,
+-2907,-2759,-2708,-2706,-2697,-2668,-2637,-2618,-2601,-2573,-2538,-2511,-2499,-2492,-2481,-2467,-2459,-2462,-2467,-2465,-2453,
+-2440,-2440,-2460,-2491,-2511,-2496,-2444,-2378,-2328,-2305,-2295,-2277,-2237,-2185,-2137,-2104,-2087,-2073,-2047,-2002,-1946,
+-1903,-1896,-1928,-1979,-2019,-2028,-2007,-1965,-1913,-1858,-1805,-1762,-1730,-1703,-1667,-1606,-1513,-1391,-1258,-1143,-1071,
+-1047,-1054,-1063,-1049,-1006,-940,-865,-789,-709,-617,-510,-396,-285,-186,-95,-9,69,133,183,233,291,
+351,400,443,511,630,783,912,964,944,907,912,969,1046,1117,1183,1258,1337,1398,1427,1434,1440,
+1450,1450,1431,1406,1401,1429,1477,1529,1581,1644,1726,1824,1923,2015,2096,2168,2230,2282,2325,2360,2388,
+2411,2439,2482,2542,2610,2675,2736,2803,2876,2945,3002,3050,3107,3178,3244,3272,3248,3189,3132,3093,3050,
+2959,2800,2607,2451,2387,2412,2470,2500,2487,2459,2454,2475,2501,2509,2512,2537,2599,2676,2726,2733,2720,
+2738,2818,2944,3062,3123,3121,3090,3073,3086,3116,3142,3155,3161,3168,3180,3195,3215,3236,3251,3253,3247,
+3240,3235,3227,3215,3211,3224,3244,3251,3243,3253,3321,3446,3576,3652,3665,3663,3695,3761,3820,3840,3832,
+3828,3850,3892,3934,3965,3986,4004,4026,4058,4098,4134,4159,4177,4207,4258,4315,4349,4343,4310,4275,4254,
+4244,4238,4239,4250,4268,4281,4281,4274,4271,4277,4290,4304,4317,4328,4339,4356,4376,4393,4402,4413,4442,
+4494,4542,4550,4514,4470,4451,4439,4357,4130,3743,3255,2752,2310,1993,1858,1927,2157,2444,2683,2831,2915,
+2980,3037,3064,3047,3004,2960,2916,2850,2755,2665,2629,2660,2709,2701,2604,2450,2309,2222,2183,2160,2131,
+2099,2071,2043,2005,1954,1901,1853,1810,1763,1709,1656,1612,1578,1544,1506,1462,1410,1350,1285,1228,1194,
+1185,1188,1180,1154,1115,1077,1044,1008,966,921,885,862,843,816,777,736,700,671,644,616,586,
+553,516,472,426,385,350,319,292,272,255,234,199,155,120,105,106,105,93,73,58,48,
+37,22,10,4,-2,-20,-52,-88,-116,-135,-151,-170,-188,-201,-209,-216,-225,-233,-240,-246,-258,
+-276,-297,-315,-330,-342,-357,-381,-415,-454,-492,-524,-551,-577,-604,-632,-659,-686,-713,-738,-761,-780,
+-797,-814,-827,-838,-848,-858,-871,-884,-894,-902,-908,-914,-918,-922,-926,-935,-946,-957,-967,-976,-985,
+-992,-997,-1003,-1013,-1029,-1047,-1062,-1073,-1081,-1087,-1095,-1105,-1119,-1136,-1149,-1156,-1161,-1169,-1182,-1194,-1201,
+-1206,-1215,-1230,-1244,-1249,-1247,-1246,-1248,-1251,-1250,-1247,-1244,-1242,-1237,-1228,-1220,-1218,-1220,-1219,-1211,-1196,
+-1182,-1171,-1164,-1160,-1158,-1157,-1155,-1150,-1145,-1141,-1136,-1130,-1122,-1117,-1115,-1116,-1114,-1106,-1098,-1091,-1089,
+-1089,-1089,-1089,-1087,-1083,-1078,-1077,-1080,-1083,-1081,-1077,-1074,-1075,-1077,-1076,-1073,-1070,-1069,-1069,-1066,-1062,
+-1060,-1057,-1052,-1046,-1041,-1037,-1033,-1025,-1017,-1012,-1009,-1005,-997,-988,-980,-974,-966,-957,-948,-942,-936,
+-925,-911,-899,-893,-889,-884,-879,-876,-875,-873,-869,-864,-862,-862,-859,-852,-843,-834,-824,-813,-804,
+-798,-794,-787,-775,-761,-750,-740,-729,-717,-710,-708,-706,-699,-686,-674,-666,-657,-646,-635,-628,-626,
+-620,-609,-596,-589,-586,-581,-570,-556,-545,-539,-534,-528,-525,-523,-519,-510,-499,-489,-481,-472,-460,
+-448,-438,-430,-419,-406,-391,-377,-360,-337,-312,-291,-274,-257,-237,-215,-196,-179,-160,-136,-112,-94,
+-81,-70,-60,-56,-59,-64,-62,-50,-34,-22,-14,-8,-1,7,17,29,41,51,60,70,83,
+97,107,115,128,153,185,216,239,257,277,301,328,353,375,397,424,455,487,519,552,587,
+624,659,687,706,724,750,786,827,865,900,934,968,1000,1029,1065,1113,1167,1214,1249,1280,1318,
+1364,1407,1444,1482,1527,1570,1597,1607,1606,1578,1482,1308,1125,1068,1233,1595,2035,2445,2798,3110,3364,
+3490,3444,3275,3088,2946,2827,2679,2503,2367,2331,2387,2468,2522,2551,2579,2613,2625,2594,2538,2512,2557,
+2664,2769,2802,2738,2612,2486,2397,2337,2274,2193,2108,2040,1993,1953,1910,1867,1832,1803,1772,1738,1712,
+1700,1697,1693,1685,1676,1670,1668,1664,1659,1652,1641,1622,1597,1574,1554,1536,1515,1492,1471,1451,1427,
+1394,1358,1326,1299,1272,1235,1185,1122,1049,972,896,823,753,684,621,580,568,571,554,487,363,
+203,42,-91,-186,-247,-290,-330,-373,-413,-437,-446,-450,-460,-484,-517,-557,-604,-655,-705,-747,-778,
+-798,-811,-817,-816,-804,-785,-763,-749,-752,-776,-813,-844,-853,-836,-803,-768,-746,-742,-750,-755,-745,
+-719,-682,-645,-612,-582,-555,-530,-503,-463,-402,-322,-234,-153,-83,-24,27,69,98,117,132,149,
+173,206,242,270,280,272,258,254,263,278,289,299,314,336,368,410,461,514,550,557,539,
+519,514,525,539,552,567,590,619,647,674,706,743,778,802,817,832,856,886,915,943,969,
+997,1022,1042,1059,1078,1100,1122,1141,1157,1174,1192,1212,1233,1255,1275,1292,1307,1323,1341,1360,1374,
+1385,1396,1410,1427,1444,1459,1473,1488,1505,1524,1543,1558,1568,1578,1591,1608,1624,1631,1627,1617,1608,
+1599,1584,1565,1550,1546,1551,1555,1550,1540,1532,1531,1531,1527,1522,1522,1527,1533,1535,1537,1541,1544,
+1542,1538,1542,1557,1577,1591,1596,1599,1611,1632,1653,1671,1690,1719,1755,1791,1820,1838,1849,1859,1872,
+1892,1918,1948,1978,2009,2033,2039,2017,1977,1955,1954,2004,2073,2113,2097,2061,2077,2180,2320,2404,2377,
+2274,2181,2160,2205,2266,2301,2302,2286,2271,2264,2265,2269,2273,2279,2292,2316,2339,2351,2353,2361,2391,
+2436,2472,2480,2468,2458,2467,2489,2510,2520,2522,2523,2528,2541,2567,2603,2638,2663,2677,2689,2703,2719,
+2732,2745,2766,2799,2834,2860,2873,2886,2914,2964,3029,3085,3111,3094,3053,3025,3042,3104,3180,3233,3249,
+3245,3248,3273,3323,3394,3481,3571,3644,3684,3686,3663,3633,3614,3609,3615,3617,3600,3561,3516,3485,3480,
+3491,3500,3499,3489,3471,3442,3404,3375,3374,3402,3433,3440,3415,3376,3336,3294,3241,3179,3128,3104,3102,
+3099,3071,3009,2917,2803,2683,2576,2496,2445,2410,2375,2337,2304,2283,2277,2280,2291,2307,2325,2343,2364,
+2387,2410,2424,2426,2420,2412,2397,2357,2279,2167,2046,1940,1860,1804,1766,1744,1735,1734,1739,1750,1765,
+1779,1787,1791,1804,1831,1869,1906,1938,1965,1994,2024,2064,2125,2215,2321,2413,2470,2492,2500,2508,2513,
+2508,2493,2479,2468,2451,2419,2375,2330,2290,2257,2228,2205,2187,2167,2138,2102,2068,2042,2023,2004,1986,
+1973,1964,1956,1946,1937,1929,1917,1898,1875,1863,1870,1893,1918,1936,1946,1952,1960,1976,1998,2017,2021,
+2015,2019,2048,2084,2089,2051,2002,1990,2020,2052,2047,2020,2014,2044,2069,2043,1972,1907,1880,1863,1809,
+1714,1628,1594,1604,1614,1596,1562,1535,1520,1505,1483,1465,1459,1459,1454,1441,1425,1412,1397,1377,1356,
+1341,1329,1313,1291,1267,1246,1227,1202,1174,1149,1129,1110,1086,1057,1027,997,968,939,910,883,855,
+823,792,765,741,716,688,658,628,599,565,530,502,484,470,450,421,389,361,336,307,274,
+240,207,173,136,96,54,9,-40,-92,-142,-190,-239,-293,-346,-393,-435,-480,-531,-586,-635,-675,
+-711,-748,-787,-829,-874,-921,-966,-1002,-1031,-1065,-1117,-1180,-1238,-1280,-1312,-1350,-1399,-1451,-1491,-1516,-1530,
+-1535,-1536,-1538,-1550,-1584,-1642,-1716,-1797,-1875,-1946,-2004,-2055,-2106,-2164,-2226,-2283,-2334,-2383,-2436,-2491,-2541,
+-2582,-2615,-2647,-2679,-2708,-2737,-2769,-2809,-2855,-2901,-2939,-2958,-2951,-2922,-2895,-2895,-2932,-2995,-3059,-3115,-3168,
+-3222,-3267,-3291,-3301,-3317,-3353,-3402,-3443,-3468,-3487,-3516,-3559,-3604,-3633,-3637,-3618,-3599,-3608,-3665,-3758,-3855,
+-3930,-3978,-4012,-4035,-4039,-4024,-4011,-4024,-4060,-4089,-4089,-4067,-4050,-4052,-4061,-4060,-4051,-4044,-4047,-4053,-4058,
+-4061,-4066,-4066,-4052,-4029,-4009,-3996,-3982,-3961,-3939,-3928,-3926,-3922,-3911,-3904,-3910,-3918,-3905,-3871,-3836,-3819,
+-3811,-3785,-3729,-3659,-3591,-3527,-3463,-3418,-3418,-3448,-3446,-3348,-3154,-2939,-2788,-2727,-2718,-2712,-2691,-2666,-2645,
+-2624,-2596,-2566,-2544,-2529,-2515,-2501,-2498,-2509,-2527,-2536,-2526,-2507,-2498,-2513,-2546,-2573,-2562,-2501,-2411,-2335,
+-2310,-2332,-2363,-2361,-2312,-2237,-2170,-2127,-2104,-2082,-2046,-1996,-1945,-1913,-1913,-1942,-1982,-2011,-2018,-2006,-1981,
+-1946,-1903,-1855,-1810,-1773,-1742,-1706,-1649,-1558,-1435,-1301,-1192,-1137,-1137,-1166,-1188,-1178,-1133,-1065,-985,-897,
+-801,-692,-572,-444,-318,-204,-103,-17,54,110,155,200,253,307,352,394,463,579,726,849,904,
+897,882,905,966,1035,1091,1146,1219,1300,1358,1373,1360,1348,1348,1348,1331,1308,1304,1334,1390,1455,
+1524,1602,1694,1797,1900,1990,2062,2113,2153,2194,2246,2302,2347,2376,2401,2443,2505,2574,2635,2692,2758,
+2834,2902,2950,2987,3035,3100,3152,3159,3117,3060,3024,3006,2966,2858,2683,2490,2349,2298,2325,2380,2415,
+2415,2399,2392,2398,2409,2415,2430,2473,2545,2621,2664,2662,2645,2666,2752,2879,2992,3044,3037,3010,3005,
+3030,3063,3084,3093,3101,3114,3129,3140,3153,3170,3188,3195,3191,3180,3171,3162,3154,3155,3173,3199,3211,
+3205,3213,3281,3413,3557,3645,3657,3636,3641,3690,3746,3770,3762,3754,3772,3816,3866,3905,3931,3952,3977,
+4009,4044,4073,4093,4114,4152,4209,4267,4298,4293,4267,4241,4224,4211,4199,4194,4202,4219,4233,4239,4241,
+4248,4260,4273,4284,4295,4306,4319,4333,4347,4358,4370,4389,4423,4468,4500,4498,4466,4432,4413,4376,4247,
+3967,3537,3026,2524,2115,1868,1823,1975,2248,2529,2730,2840,2905,2966,3022,3044,3019,2970,2927,2890,2835,
+2745,2644,2575,2560,2576,2571,2507,2393,2271,2182,2135,2114,2094,2065,2032,2000,1968,1931,1887,1840,1793,
+1744,1693,1641,1595,1558,1526,1490,1445,1388,1325,1265,1216,1186,1175,1171,1161,1136,1099,1060,1027,995,
+959,919,884,859,839,814,780,739,699,664,635,610,586,557,520,476,432,392,357,323,293,
+272,259,242,209,164,125,107,106,105,93,75,60,49,38,26,17,12,4,-15,-48,-83,
+-111,-132,-153,-176,-197,-212,-223,-236,-249,-260,-267,-273,-282,-295,-310,-322,-331,-340,-355,-380,-417,
+-459,-498,-530,-556,-582,-610,-637,-663,-688,-717,-746,-773,-795,-812,-827,-841,-854,-865,-877,-890,-902,
+-912,-920,-927,-934,-939,-944,-948,-955,-962,-970,-977,-986,-996,-1004,-1009,-1012,-1019,-1031,-1046,-1058,-1068,
+-1074,-1080,-1087,-1097,-1111,-1126,-1139,-1147,-1154,-1165,-1180,-1192,-1199,-1204,-1213,-1227,-1238,-1240,-1237,-1236,-1239,
+-1242,-1241,-1238,-1237,-1237,-1232,-1221,-1210,-1207,-1209,-1206,-1196,-1183,-1176,-1174,-1173,-1169,-1161,-1152,-1143,-1135,
+-1131,-1130,-1130,-1127,-1119,-1111,-1105,-1102,-1097,-1090,-1083,-1080,-1080,-1082,-1085,-1088,-1088,-1085,-1080,-1078,-1082,
+-1087,-1089,-1085,-1080,-1080,-1082,-1081,-1077,-1074,-1072,-1070,-1067,-1062,-1059,-1058,-1057,-1054,-1049,-1045,-1042,-1037,
+-1030,-1023,-1017,-1011,-1005,-1000,-995,-987,-977,-967,-960,-956,-949,-936,-921,-910,-904,-899,-893,-887,-885,
+-885,-884,-880,-874,-872,-872,-868,-861,-852,-845,-837,-826,-816,-808,-802,-795,-786,-776,-769,-763,-754,
+-741,-730,-725,-721,-713,-701,-689,-681,-673,-662,-651,-644,-641,-635,-624,-613,-607,-605,-600,-588,-575,
+-565,-560,-556,-549,-544,-542,-539,-533,-522,-510,-498,-488,-477,-467,-459,-451,-440,-426,-411,-397,-380,
+-358,-334,-313,-296,-278,-256,-233,-214,-196,-177,-154,-131,-113,-100,-89,-81,-78,-80,-81,-76,-64,
+-51,-42,-36,-29,-20,-11,-3,6,17,29,40,51,64,76,87,98,117,145,178,205,224,
+242,266,296,324,345,364,389,420,455,489,521,553,585,616,644,669,693,719,750,788,827,
+865,900,934,968,1002,1039,1085,1138,1191,1233,1263,1291,1327,1368,1407,1441,1479,1522,1560,1584,1594,
+1594,1563,1462,1281,1094,1030,1178,1518,1941,2348,2709,3031,3290,3423,3393,3247,3076,2936,2803,2634,2438,
+2284,2232,2274,2350,2412,2456,2507,2568,2608,2595,2542,2504,2534,2630,2731,2762,2697,2574,2459,2385,2337,
+2274,2186,2095,2028,1989,1957,1916,1870,1830,1797,1766,1733,1705,1690,1686,1686,1685,1684,1685,1686,1685,
+1681,1673,1662,1645,1626,1607,1589,1566,1537,1508,1486,1467,1441,1403,1358,1319,1289,1260,1219,1163,1095,
+1025,955,888,817,740,661,599,572,578,590,565,474,324,153,0,-110,-178,-220,-254,-292,-334,
+-369,-390,-401,-411,-431,-460,-492,-524,-560,-604,-653,-700,-739,-767,-785,-794,-795,-787,-772,-754,-741,
+-742,-760,-788,-812,-822,-811,-786,-759,-741,-739,-748,-753,-744,-720,-690,-664,-640,-613,-581,-548,-514,
+-470,-405,-324,-242,-175,-127,-86,-44,0,39,66,81,90,102,125,160,197,224,236,240,250,
+268,288,304,317,331,352,378,413,458,508,546,560,550,535,533,544,561,579,600,627,656,
+684,712,745,783,817,838,849,864,889,921,952,980,1007,1037,1064,1084,1098,1114,1135,1158,1180,
+1197,1212,1228,1247,1269,1291,1311,1328,1344,1361,1381,1398,1410,1420,1431,1445,1462,1477,1489,1503,1519,
+1539,1559,1577,1590,1598,1604,1614,1627,1639,1641,1632,1620,1613,1610,1602,1585,1569,1560,1561,1562,1556,
+1546,1540,1541,1542,1541,1538,1538,1541,1543,1542,1541,1542,1540,1534,1529,1536,1553,1572,1581,1585,1594,
+1617,1644,1665,1681,1702,1738,1784,1825,1851,1859,1854,1849,1859,1890,1938,1981,2004,2004,1992,1976,1957,
+1943,1954,2004,2042,2072,2068,2030,2005,2050,2169,2292,2330,2265,2163,2113,2146,2220,2277,2293,2285,2275,
+2268,2262,2257,2258,2266,2276,2289,2306,2326,2340,2346,2354,2376,2408,2434,2440,2432,2430,2443,2466,2485,
+2496,2503,2509,2519,2537,2565,2601,2634,2653,2662,2673,2692,2710,2720,2724,2738,2767,2804,2836,2853,2863,
+2880,2917,2978,3050,3104,3116,3085,3044,3038,3083,3156,3220,3256,3271,3285,3301,3320,3349,3404,3492,3595,
+3679,3719,3711,3674,3631,3600,3585,3575,3550,3504,3452,3416,3406,3410,3410,3404,3399,3398,3389,3363,3334,
+3325,3344,3373,3379,3353,3306,3254,3203,3149,3101,3076,3077,3086,3073,3020,2933,2828,2718,2616,2531,2469,
+2426,2391,2357,2328,2311,2303,2302,2304,2312,2330,2356,2384,2416,2454,2494,2524,2533,2523,2504,2473,2420,
+2332,2217,2097,1995,1917,1861,1824,1803,1796,1798,1803,1814,1828,1840,1846,1854,1875,1912,1956,1995,2026,
+2055,2085,2112,2140,2186,2265,2375,2487,2571,2616,2632,2633,2623,2606,2587,2571,2555,2532,2496,2452,2410,
+2373,2343,2319,2301,2284,2262,2230,2194,2165,2144,2127,2108,2091,2079,2070,2058,2040,2023,2011,1999,1981,
+1960,1949,1954,1971,1991,2008,2021,2031,2041,2056,2078,2098,2105,2102,2112,2147,2187,2187,2137,2078,2067,
+2108,2148,2139,2095,2071,2090,2110,2076,1987,1903,1866,1854,1817,1742,1669,1641,1655,1666,1647,1611,1583,
+1570,1558,1541,1524,1517,1514,1505,1488,1469,1454,1439,1421,1402,1388,1377,1363,1340,1314,1291,1271,1249,
+1225,1202,1182,1160,1133,1102,1070,1042,1014,985,955,926,895,864,835,812,791,767,738,707,676,
+645,610,575,548,530,516,494,465,435,410,386,358,324,291,262,232,197,154,109,64,19,
+-27,-77,-128,-178,-229,-277,-323,-368,-415,-466,-517,-563,-603,-641,-678,-716,-756,-802,-853,-903,-943,
+-972,-1005,-1053,-1114,-1172,-1218,-1255,-1297,-1344,-1391,-1425,-1445,-1455,-1460,-1463,-1470,-1492,-1537,-1605,-1683,-1762,
+-1833,-1895,-1950,-2001,-2054,-2113,-2173,-2228,-2277,-2324,-2370,-2417,-2460,-2498,-2532,-2563,-2591,-2621,-2659,-2707,-2761,
+-2813,-2863,-2913,-2954,-2972,-2963,-2940,-2930,-2947,-2980,-3010,-3033,-3065,-3112,-3163,-3201,-3223,-3249,-3291,-3340,-3375,
+-3388,-3394,-3417,-3462,-3519,-3566,-3588,-3582,-3565,-3570,-3622,-3719,-3829,-3919,-3979,-4019,-4050,-4065,-4058,-4043,-4045,
+-4071,-4100,-4104,-4079,-4047,-4032,-4038,-4051,-4060,-4062,-4062,-4061,-4060,-4062,-4067,-4065,-4052,-4030,-4010,-3995,-3977,
+-3953,-3930,-3919,-3920,-3918,-3909,-3902,-3907,-3916,-3911,-3885,-3855,-3838,-3828,-3802,-3751,-3682,-3610,-3541,-3481,-3447,
+-3452,-3474,-3454,-3339,-3141,-2931,-2784,-2721,-2708,-2702,-2686,-2667,-2651,-2634,-2616,-2601,-2590,-2578,-2560,-2543,-2545,
+-2568,-2595,-2603,-2588,-2568,-2568,-2593,-2626,-2633,-2585,-2488,-2380,-2314,-2316,-2369,-2417,-2412,-2349,-2259,-2182,-2135,
+-2107,-2080,-2043,-1998,-1957,-1933,-1933,-1953,-1982,-2004,-2013,-2010,-1996,-1975,-1943,-1902,-1856,-1811,-1772,-1734,-1682,
+-1600,-1482,-1351,-1249,-1207,-1224,-1264,-1286,-1271,-1226,-1165,-1092,-1003,-895,-770,-636,-500,-368,-245,-138,-49,
+22,78,125,171,218,265,308,358,434,550,686,799,855,864,869,906,968,1030,1077,1126,1191,
+1260,1299,1295,1265,1243,1239,1236,1223,1207,1213,1252,1315,1387,1465,1551,1650,1753,1853,1939,2002,2041,
+2068,2104,2165,2240,2304,2343,2370,2412,2475,2542,2598,2648,2705,2769,2822,2853,2876,2915,2970,3009,3002,
+2957,2916,2904,2898,2845,2712,2523,2343,2232,2210,2251,2307,2339,2341,2330,2329,2346,2368,2384,2397,2426,
+2482,2549,2594,2599,2582,2590,2652,2751,2839,2882,2888,2891,2919,2966,3006,3025,3031,3043,3062,3080,3091,
+3101,3120,3141,3150,3143,3127,3113,3104,3101,3108,3132,3164,3182,3180,3186,3249,3380,3529,3624,3634,3598,
+3583,3616,3670,3701,3697,3685,3697,3739,3795,3843,3876,3900,3925,3955,3984,4007,4025,4050,4094,4153,4206,
+4231,4227,4207,4190,4179,4169,4159,4156,4163,4176,4187,4197,4212,4234,4254,4265,4267,4270,4279,4291,4302,
+4312,4325,4347,4381,4419,4450,4461,4446,4420,4400,4381,4317,4139,3807,3341,2818,2332,1970,1794,1826,2029,
+2314,2573,2744,2835,2894,2953,3004,3020,2993,2943,2896,2856,2806,2730,2634,2544,2488,2471,2469,2446,2378,
+2274,2171,2103,2074,2060,2035,1996,1957,1928,1903,1869,1821,1767,1717,1671,1625,1578,1537,1503,1469,1426,
+1369,1306,1249,1207,1180,1165,1156,1142,1117,1081,1045,1014,988,958,922,884,851,826,803,775,738,
+696,656,623,599,582,562,531,488,442,400,362,327,295,273,260,244,214,170,131,111,108,
+107,97,80,64,51,40,29,20,14,3,-18,-49,-81,-108,-131,-154,-178,-197,-212,-225,-240,
+-258,-274,-287,-298,-309,-322,-331,-337,-340,-343,-353,-376,-413,-457,-498,-531,-558,-584,-612,-639,-663,
+-686,-713,-745,-776,-801,-822,-839,-855,-868,-880,-890,-903,-916,-928,-937,-943,-948,-952,-956,-962,-969,
+-975,-979,-983,-990,-1001,-1012,-1019,-1024,-1029,-1037,-1047,-1056,-1064,-1072,-1081,-1090,-1101,-1115,-1129,-1142,-1151,
+-1160,-1173,-1188,-1199,-1204,-1209,-1218,-1230,-1237,-1236,-1232,-1232,-1236,-1239,-1236,-1233,-1232,-1232,-1226,-1215,-1204,
+-1200,-1199,-1193,-1183,-1176,-1179,-1187,-1189,-1180,-1163,-1146,-1134,-1127,-1123,-1120,-1118,-1112,-1104,-1096,-1091,-1087,
+-1083,-1076,-1071,-1069,-1070,-1073,-1076,-1081,-1085,-1084,-1078,-1075,-1078,-1085,-1089,-1088,-1084,-1083,-1084,-1084,-1080,
+-1077,-1076,-1074,-1071,-1065,-1062,-1062,-1063,-1062,-1057,-1051,-1048,-1045,-1041,-1034,-1026,-1018,-1014,-1012,-1009,-1000,
+-988,-976,-970,-966,-961,-949,-934,-923,-916,-910,-902,-896,-895,-896,-895,-889,-882,-878,-876,-872,-864,
+-857,-851,-845,-835,-823,-813,-805,-798,-790,-784,-782,-779,-772,-759,-746,-737,-730,-722,-711,-701,-695,
+-690,-682,-671,-662,-655,-647,-636,-626,-621,-619,-615,-604,-592,-583,-577,-572,-565,-559,-556,-555,-550,
+-541,-529,-518,-506,-494,-483,-473,-462,-449,-435,-424,-413,-398,-377,-352,-330,-311,-293,-274,-253,-233,
+-214,-193,-170,-150,-135,-124,-114,-106,-102,-102,-101,-92,-79,-67,-60,-55,-46,-35,-25,-20,-14,
+-5,6,19,33,46,58,69,83,106,136,167,193,212,234,263,296,323,344,364,391,424,
+456,486,516,548,580,608,631,653,678,709,744,781,820,859,897,933,968,1003,1043,1090,1140,
+1187,1227,1259,1290,1324,1358,1389,1420,1457,1497,1531,1553,1566,1569,1536,1428,1244,1060,996,1136,1462,
+1873,2276,2634,2944,3189,3324,3326,3228,3090,2945,2776,2562,2333,2162,2097,2126,2191,2249,2304,2382,2480,
+2558,2573,2529,2482,2492,2571,2667,2708,2660,2555,2452,2380,2324,2253,2160,2072,2014,1982,1953,1912,1862,
+1818,1786,1757,1727,1700,1683,1679,1684,1693,1703,1713,1718,1717,1707,1691,1671,1651,1637,1626,1611,1584,
+1546,1510,1485,1468,1445,1405,1355,1310,1277,1245,1203,1144,1076,1010,949,889,819,736,653,596,583,
+601,612,569,452,286,118,-14,-99,-149,-185,-223,-266,-309,-342,-363,-379,-400,-430,-463,-492,-516,
+-543,-578,-623,-668,-707,-735,-755,-769,-774,-771,-758,-741,-727,-725,-738,-761,-785,-800,-801,-790,-771,
+-754,-748,-749,-748,-736,-713,-690,-674,-660,-637,-600,-556,-509,-455,-387,-308,-235,-184,-157,-138,-112,
+-76,-35,1,29,45,56,68,92,127,164,192,211,228,248,270,291,312,335,361,388,418,
+454,496,534,555,558,554,557,571,591,614,639,668,695,720,745,777,812,844,864,877,895,
+923,955,986,1014,1044,1076,1105,1126,1139,1153,1173,1197,1221,1239,1254,1269,1287,1308,1329,1349,1365,
+1381,1399,1418,1436,1449,1460,1472,1487,1501,1512,1523,1537,1554,1573,1591,1605,1616,1621,1623,1627,1635,
+1642,1642,1633,1624,1622,1626,1624,1613,1596,1583,1578,1574,1566,1557,1553,1554,1555,1551,1545,1542,1541,
+1539,1535,1533,1533,1533,1530,1530,1540,1557,1572,1580,1590,1611,1642,1671,1687,1699,1726,1773,1827,1869,
+1886,1877,1852,1826,1825,1861,1923,1977,1991,1969,1941,1932,1946,1972,2004,2072,2066,2043,2006,1972,1981,
+2061,2187,2278,2268,2173,2081,2071,2141,2225,2268,2270,2264,2266,2267,2257,2244,2245,2259,2275,2285,2297,
+2314,2333,2342,2346,2354,2370,2386,2393,2395,2404,2424,2446,2463,2473,2483,2496,2510,2529,2555,2589,2618,
+2635,2644,2658,2680,2700,2708,2708,2715,2737,2767,2793,2809,2819,2830,2855,2905,2981,3062,3111,3108,3072,
+3048,3067,3122,3184,3232,3269,3301,3321,3320,3312,3330,3401,3515,3629,3699,3703,3657,3590,3532,3498,3478,
+3451,3407,3356,3318,3301,3292,3277,3259,3254,3270,3289,3290,3274,3263,3272,3292,3298,3279,3242,3197,3148,
+3099,3062,3051,3061,3065,3033,2958,2856,2750,2652,2567,2498,2448,2412,2382,2356,2338,2333,2335,2336,2337,
+2346,2370,2405,2443,2486,2536,2589,2628,2639,2622,2587,2537,2466,2367,2249,2134,2040,1969,1918,1883,1864,
+1857,1860,1867,1878,1890,1899,1906,1918,1946,1988,2031,2065,2095,2129,2163,2186,2199,2226,2297,2419,2562,
+2682,2752,2776,2769,2747,2722,2698,2676,2652,2619,2577,2533,2492,2455,2423,2396,2376,2357,2331,2300,2271,
+2250,2237,2221,2201,2183,2174,2166,2151,2129,2109,2096,2084,2066,2046,2034,2037,2053,2072,2090,2106,2118,
+2129,2146,2171,2193,2199,2191,2195,2228,2267,2267,2214,2153,2145,2196,2245,2234,2171,2119,2114,2121,2085,
+1998,1911,1869,1858,1831,1771,1711,1689,1701,1708,1688,1654,1631,1623,1617,1602,1587,1580,1574,1560,1535,
+1512,1497,1486,1471,1453,1438,1425,1409,1386,1359,1335,1316,1296,1273,1250,1226,1200,1172,1143,1116,1089,
+1061,1029,997,967,939,911,885,861,839,814,783,750,718,687,655,623,597,577,561,539,511,
+483,459,436,407,374,343,316,288,252,209,164,123,82,36,-15,-68,-119,-165,-209,-254,-303,
+-353,-403,-449,-491,-532,-573,-613,-650,-687,-732,-785,-839,-883,-915,-946,-989,-1047,-1109,-1163,-1208,-1249,
+-1288,-1323,-1349,-1367,-1380,-1389,-1395,-1407,-1436,-1489,-1562,-1644,-1722,-1792,-1851,-1905,-1957,-2013,-2070,-2128,-2182,
+-2231,-2277,-2323,-2366,-2409,-2452,-2494,-2532,-2564,-2596,-2636,-2685,-2733,-2773,-2810,-2854,-2907,-2954,-2981,-2992,-3003,
+-3022,-3039,-3042,-3041,-3057,-3102,-3159,-3204,-3233,-3262,-3302,-3342,-3363,-3363,-3362,-3383,-3428,-3483,-3530,-3558,-3567,
+-3568,-3583,-3632,-3716,-3813,-3894,-3950,-3995,-4038,-4069,-4076,-4063,-4056,-4070,-4094,-4099,-4071,-4030,-4004,-4006,-4028,
+-4052,-4067,-4072,-4070,-4068,-4068,-4066,-4058,-4042,-4022,-4007,-3996,-3978,-3952,-3926,-3912,-3911,-3911,-3907,-3902,-3904,
+-3911,-3908,-3891,-3870,-3855,-3841,-3814,-3764,-3696,-3618,-3536,-3467,-3432,-3443,-3465,-3435,-3308,-3105,-2902,-2766,-2711,
+-2700,-2693,-2678,-2664,-2654,-2648,-2645,-2646,-2649,-2643,-2624,-2606,-2607,-2629,-2655,-2662,-2650,-2640,-2650,-2677,-2695,
+-2672,-2597,-2488,-2391,-2347,-2369,-2425,-2461,-2439,-2362,-2266,-2188,-2140,-2110,-2083,-2051,-2014,-1980,-1957,-1950,-1960,
+-1982,-2003,-2014,-2012,-2003,-1988,-1967,-1935,-1890,-1840,-1792,-1750,-1702,-1627,-1515,-1389,-1295,-1269,-1302,-1350,-1368,
+-1343,-1292,-1235,-1169,-1080,-960,-822,-683,-552,-428,-312,-205,-112,-34,31,89,141,186,228,270,325,
+409,525,654,762,822,845,862,899,953,1004,1047,1093,1148,1195,1210,1189,1155,1135,1130,1126,1116,
+1112,1135,1189,1258,1331,1408,1495,1593,1692,1786,1867,1930,1968,1992,2027,2091,2176,2255,2307,2342,2387,
+2450,2516,2569,2614,2663,2717,2758,2775,2785,2809,2844,2862,2846,2813,2798,2807,2798,2716,2552,2354,2196,
+2123,2135,2193,2251,2277,2269,2250,2253,2290,2341,2372,2374,2371,2399,2460,2521,2546,2533,2518,2537,2589,
+2647,2689,2720,2764,2830,2898,2942,2958,2964,2980,3005,3025,3038,3052,3075,3099,3108,3096,3076,3060,3052,
+3053,3064,3092,3128,3149,3146,3149,3204,3330,3482,3586,3602,3561,3532,3551,3602,3637,3635,3616,3615,3648,
+3703,3756,3794,3821,3847,3879,3911,3939,3962,3992,4036,4089,4134,4155,4153,4140,4129,4123,4119,4118,4125,
+4138,4150,4157,4167,4188,4217,4241,4247,4241,4238,4244,4255,4265,4275,4297,4335,4382,4420,4433,4420,4395,
+4375,4368,4346,4253,4030,3653,3158,2632,2174,1872,1773,1870,2103,2373,2597,2741,2824,2884,2938,2975,2982,
+2958,2916,2867,2817,2761,2694,2610,2520,2445,2412,2423,2438,2407,2309,2182,2083,2039,2029,2010,1968,1923,
+1893,1875,1847,1797,1738,1686,1646,1607,1563,1519,1481,1447,1405,1350,1290,1237,1199,1174,1157,1143,1125,
+1099,1065,1031,1002,980,955,921,879,841,811,788,765,735,695,651,612,588,577,567,544,506,
+459,412,369,329,295,271,256,239,211,171,134,112,106,104,97,84,70,55,40,26,15,
+6,-6,-26,-53,-81,-107,-132,-157,-179,-195,-207,-221,-239,-260,-280,-299,-316,-332,-344,-352,-354,
+-355,-355,-360,-376,-407,-448,-489,-522,-550,-577,-607,-635,-659,-681,-708,-740,-772,-800,-824,-845,-864,
+-879,-889,-898,-909,-923,-938,-949,-956,-960,-961,-964,-969,-977,-984,-988,-990,-995,-1006,-1019,-1030,-1037,
+-1042,-1047,-1052,-1058,-1065,-1075,-1087,-1099,-1111,-1123,-1137,-1149,-1160,-1170,-1182,-1194,-1203,-1208,-1213,-1221,-1230,
+-1233,-1229,-1225,-1227,-1232,-1234,-1230,-1223,-1218,-1215,-1210,-1201,-1195,-1193,-1191,-1183,-1174,-1172,-1181,-1190,-1188,
+-1171,-1150,-1135,-1129,-1127,-1123,-1116,-1106,-1095,-1086,-1082,-1082,-1083,-1080,-1075,-1071,-1071,-1072,-1073,-1073,-1077,
+-1080,-1081,-1076,-1072,-1073,-1080,-1086,-1087,-1084,-1083,-1084,-1084,-1082,-1080,-1080,-1079,-1076,-1071,-1067,-1068,-1070,
+-1069,-1065,-1058,-1053,-1051,-1048,-1043,-1035,-1028,-1024,-1023,-1020,-1012,-999,-987,-979,-975,-969,-958,-945,-934,
+-927,-921,-913,-908,-908,-909,-907,-898,-889,-883,-880,-876,-869,-863,-857,-850,-840,-828,-817,-808,-801,
+-793,-787,-785,-783,-777,-765,-753,-743,-736,-728,-718,-710,-706,-703,-697,-686,-674,-663,-652,-640,-631,
+-626,-624,-621,-613,-602,-592,-584,-577,-570,-565,-564,-563,-559,-551,-541,-530,-518,-506,-494,-482,-469,
+-455,-442,-432,-425,-413,-393,-367,-341,-320,-304,-289,-272,-254,-233,-209,-185,-169,-158,-150,-140,-130,
+-124,-122,-119,-109,-95,-83,-76,-70,-59,-46,-37,-32,-29,-22,-10,4,19,33,46,57,71,
+93,122,153,181,204,231,263,294,320,342,366,396,428,454,479,509,545,580,606,625,646,
+674,709,745,780,816,854,893,928,961,995,1031,1069,1108,1148,1190,1232,1272,1306,1334,1360,1389,
+1424,1461,1493,1519,1540,1547,1507,1387,1198,1019,964,1107,1430,1839,2239,2582,2862,3078,3214,3258,3221,
+3119,2959,2735,2466,2211,2041,1985,2013,2064,2110,2168,2266,2395,2506,2549,2521,2476,2475,2538,2623,2666,
+2634,2546,2448,2366,2293,2212,2125,2049,2001,1971,1939,1895,1847,1807,1778,1752,1723,1698,1683,1683,1694,
+1710,1726,1740,1747,1744,1730,1708,1681,1658,1644,1637,1623,1592,1549,1510,1487,1475,1455,1416,1363,1313,
+1275,1242,1199,1142,1075,1011,953,895,826,745,669,624,623,645,643,577,439,265,105,-9,-80,
+-127,-168,-212,-258,-300,-334,-360,-384,-414,-448,-481,-507,-527,-549,-579,-617,-655,-688,-714,-734,-750,
+-762,-764,-754,-736,-718,-712,-721,-742,-767,-787,-799,-799,-787,-770,-756,-748,-741,-725,-703,-685,-675,
+-667,-648,-612,-565,-512,-454,-384,-308,-240,-196,-177,-168,-156,-133,-101,-62,-23,8,27,40,56,
+85,120,150,170,185,203,228,256,286,319,354,387,419,454,492,529,557,572,578,587,602,
+622,646,673,701,726,747,769,796,828,859,882,902,926,956,989,1019,1049,1082,1117,1148,1170,
+1184,1198,1218,1241,1264,1284,1301,1317,1335,1355,1375,1394,1410,1425,1441,1458,1474,1488,1501,1514,1526,
+1537,1546,1556,1570,1586,1601,1614,1625,1635,1641,1642,1642,1645,1650,1651,1646,1640,1640,1644,1643,1633,
+1617,1602,1593,1584,1573,1564,1561,1561,1557,1549,1540,1536,1535,1532,1529,1528,1532,1537,1540,1544,1555,
+1569,1582,1592,1609,1637,1669,1689,1697,1709,1744,1798,1850,1880,1886,1872,1844,1813,1800,1822,1873,1920,
+1932,1917,1912,1944,2002,2051,2072,2109,2056,2001,1966,1963,2014,2121,2245,2309,2268,2157,2069,2070,2140,
+2211,2238,2236,2240,2254,2258,2242,2224,2226,2246,2266,2276,2285,2304,2327,2338,2336,2333,2338,2349,2360,
+2371,2388,2412,2433,2446,2455,2467,2485,2501,2517,2537,2564,2591,2610,2625,2643,2667,2686,2692,2691,2697,
+2714,2735,2753,2766,2777,2786,2798,2830,2897,2991,3074,3108,3091,3062,3061,3095,3144,3194,3244,3295,3332,
+3334,3311,3301,3344,3442,3554,3625,3628,3571,3489,3418,3378,3359,3339,3303,3255,3215,3190,3166,3132,3097,
+3082,3100,3135,3159,3163,3159,3164,3176,3182,3175,3156,3128,3094,3057,3034,3032,3043,3034,2982,2891,2785,
+2685,2600,2528,2472,2433,2409,2391,2378,2371,2375,2383,2387,2391,2405,2435,2477,2522,2570,2626,2684,2726,
+2735,2710,2661,2595,2509,2400,2280,2169,2081,2017,1971,1940,1923,1918,1920,1928,1939,1950,1957,1965,1983,
+2016,2058,2093,2118,2144,2182,2222,2244,2247,2263,2334,2471,2642,2790,2879,2908,2897,2871,2843,2815,2787,
+2752,2708,2660,2613,2569,2529,2490,2459,2436,2417,2394,2369,2347,2334,2322,2304,2280,2261,2252,2245,2231,
+2211,2193,2181,2170,2151,2129,2119,2125,2142,2163,2180,2195,2205,2215,2234,2263,2289,2293,2277,2271,2300,
+2343,2352,2303,2236,2215,2254,2297,2280,2207,2137,2117,2121,2095,2024,1945,1898,1880,1852,1802,1756,1740,
+1747,1747,1725,1698,1685,1685,1681,1666,1650,1641,1634,1616,1587,1562,1549,1541,1528,1508,1488,1470,1452,
+1428,1403,1381,1362,1342,1317,1290,1263,1237,1211,1186,1163,1139,1109,1073,1039,1012,988,964,938,910,
+884,856,824,790,758,728,699,670,644,622,604,583,557,531,506,481,452,421,391,365,337,
+303,262,221,183,144,97,43,-10,-59,-101,-142,-189,-241,-294,-341,-383,-423,-464,-509,-552,-590,
+-627,-669,-720,-774,-821,-855,-887,-927,-983,-1048,-1111,-1162,-1201,-1228,-1249,-1267,-1286,-1305,-1322,-1338,-1359,
+-1395,-1452,-1525,-1604,-1680,-1747,-1807,-1861,-1914,-1968,-2024,-2079,-2131,-2181,-2229,-2276,-2319,-2362,-2408,-2456,-2500,
+-2538,-2573,-2616,-2665,-2709,-2740,-2763,-2796,-2845,-2900,-2949,-2990,-3032,-3074,-3103,-3114,-3119,-3143,-3194,-3253,-3296,
+-3321,-3345,-3375,-3401,-3409,-3403,-3405,-3431,-3471,-3509,-3536,-3561,-3588,-3620,-3657,-3705,-3766,-3830,-3883,-3922,-3960,
+-4005,-4045,-4063,-4058,-4051,-4061,-4082,-4089,-4066,-4024,-3992,-3988,-4007,-4032,-4050,-4060,-4067,-4073,-4076,-4071,-4055,
+-4033,-4014,-4003,-3994,-3975,-3942,-3907,-3884,-3879,-3885,-3894,-3900,-3906,-3907,-3900,-3886,-3872,-3860,-3843,-3812,-3762,
+-3695,-3609,-3511,-3425,-3385,-3404,-3437,-3411,-3280,-3074,-2876,-2753,-2709,-2701,-2691,-2675,-2663,-2664,-2671,-2680,-2692,
+-2704,-2705,-2692,-2677,-2676,-2692,-2710,-2716,-2713,-2717,-2736,-2756,-2750,-2701,-2616,-2522,-2454,-2434,-2455,-2488,-2495,
+-2454,-2374,-2286,-2215,-2168,-2137,-2111,-2084,-2054,-2022,-1993,-1978,-1982,-1999,-2016,-2022,-2016,-2005,-1994,-1983,-1960,
+-1921,-1868,-1814,-1768,-1720,-1648,-1540,-1418,-1332,-1320,-1369,-1428,-1447,-1414,-1355,-1294,-1225,-1129,-1000,-856,-722,
+-605,-499,-393,-289,-191,-104,-24,47,109,157,196,235,290,375,491,617,726,794,826,842,865,
+898,935,974,1017,1062,1091,1090,1066,1041,1032,1034,1031,1025,1035,1077,1145,1218,1287,1358,1440,1531,
+1623,1708,1787,1853,1898,1927,1960,2020,2108,2195,2261,2308,2359,2423,2490,2545,2592,2644,2698,2738,2754,
+2754,2755,2757,2745,2719,2700,2708,2723,2692,2574,2387,2197,2070,2032,2068,2136,2195,2216,2198,2173,2187,
+2255,2344,2393,2377,2330,2316,2363,2440,2489,2486,2458,2443,2460,2496,2540,2596,2672,2761,2835,2875,2886,
+2894,2914,2941,2963,2978,2997,3027,3054,3062,3049,3027,3012,3006,3009,3024,3055,3093,3114,3106,3097,3137,
+3251,3403,3520,3554,3523,3489,3495,3535,3570,3571,3549,3538,3560,3610,3663,3701,3726,3753,3791,3836,3877,
+3909,3940,3978,4023,4064,4088,4095,4093,4087,4079,4074,4076,4090,4111,4127,4135,4142,4160,4186,4206,4210,
+4205,4205,4213,4224,4233,4247,4278,4328,4379,4408,4403,4375,4346,4334,4329,4293,4164,3895,3479,2967,2452,
+2040,1812,1795,1952,2198,2440,2620,2737,2816,2879,2922,2939,2933,2913,2885,2842,2782,2713,2644,2571,2486,
+2407,2367,2385,2425,2419,2327,2182,2058,2002,1995,1986,1948,1899,1866,1849,1823,1774,1713,1661,1624,1590,
+1549,1504,1464,1425,1381,1327,1270,1223,1189,1166,1146,1128,1107,1081,1048,1014,985,963,940,909,869,
+828,796,773,753,728,692,649,609,582,571,565,550,517,471,422,376,332,294,265,246,229,
+206,174,141,116,103,96,90,82,70,55,36,16,0,-10,-19,-33,-53,-78,-105,-133,-158,
+-178,-191,-202,-218,-238,-261,-284,-306,-327,-345,-356,-361,-364,-368,-371,-374,-382,-403,-436,-472,-505,
+-534,-563,-594,-625,-653,-679,-707,-738,-769,-796,-821,-844,-866,-884,-894,-902,-912,-925,-939,-953,-963,
+-968,-969,-969,-973,-981,-991,-998,-1001,-1005,-1014,-1026,-1038,-1047,-1054,-1058,-1060,-1063,-1070,-1081,-1095,-1108,
+-1118,-1128,-1139,-1150,-1161,-1172,-1184,-1194,-1202,-1207,-1213,-1220,-1226,-1225,-1220,-1216,-1218,-1224,-1225,-1217,-1206,
+-1196,-1190,-1185,-1181,-1180,-1182,-1182,-1175,-1167,-1167,-1174,-1177,-1167,-1146,-1126,-1119,-1122,-1126,-1123,-1113,-1101,
+-1091,-1084,-1084,-1090,-1095,-1095,-1091,-1088,-1088,-1089,-1087,-1083,-1081,-1083,-1084,-1081,-1077,-1077,-1082,-1088,-1089,
+-1087,-1085,-1086,-1087,-1087,-1086,-1085,-1084,-1081,-1076,-1073,-1072,-1074,-1074,-1072,-1067,-1061,-1056,-1053,-1050,-1045,
+-1039,-1034,-1031,-1028,-1021,-1011,-1000,-992,-986,-978,-966,-953,-943,-936,-932,-928,-924,-924,-923,-918,-909,
+-898,-892,-888,-886,-881,-875,-867,-857,-845,-832,-823,-816,-809,-800,-792,-786,-781,-774,-763,-752,-745,
+-740,-733,-723,-714,-709,-706,-700,-690,-678,-666,-654,-643,-633,-628,-626,-624,-618,-610,-600,-590,-580,
+-574,-570,-570,-568,-562,-553,-543,-532,-520,-509,-499,-490,-479,-465,-452,-442,-436,-425,-406,-379,-351,
+-328,-312,-299,-287,-272,-252,-227,-204,-189,-182,-176,-165,-152,-144,-141,-138,-127,-112,-99,-91,-83,
+-72,-59,-49,-44,-41,-33,-21,-6,9,24,38,50,65,85,114,146,177,204,233,263,291,
+316,339,366,398,426,449,473,505,543,577,598,613,633,665,702,737,767,796,828,861,892,
+924,960,997,1030,1061,1096,1141,1192,1237,1269,1292,1317,1350,1389,1426,1461,1496,1529,1537,1484,1345,
+1147,974,934,1089,1416,1826,2218,2535,2776,2959,3100,3194,3218,3147,2962,2682,2366,2105,1961,1936,1973,
+2014,2047,2102,2211,2359,2489,2549,2536,2498,2493,2538,2600,2628,2596,2518,2425,2336,2251,2167,2090,2030,
+1989,1957,1920,1877,1836,1804,1776,1748,1718,1695,1687,1694,1710,1727,1742,1751,1755,1753,1742,1723,1698,
+1675,1660,1648,1630,1597,1554,1520,1503,1495,1477,1437,1382,1329,1287,1251,1208,1151,1085,1017,954,891,
+824,753,694,666,673,690,672,587,440,269,119,11,-60,-115,-165,-213,-259,-300,-337,-371,-402,
+-434,-466,-495,-519,-540,-562,-589,-621,-653,-680,-701,-720,-738,-754,-763,-761,-747,-730,-721,-726,-741,
+-762,-781,-794,-798,-791,-775,-759,-747,-736,-720,-700,-683,-673,-665,-649,-619,-579,-532,-476,-409,-335,
+-268,-223,-200,-189,-178,-163,-140,-106,-63,-21,10,31,49,73,100,121,134,147,170,203,240,
+272,303,334,369,407,448,492,536,572,596,610,620,632,649,670,695,721,745,764,784,807,
+834,864,891,919,950,984,1017,1048,1081,1117,1153,1185,1208,1225,1242,1261,1281,1302,1322,1342,1361,
+1380,1399,1419,1439,1456,1471,1484,1497,1509,1522,1535,1547,1557,1566,1574,1584,1596,1607,1616,1625,1637,
+1651,1663,1668,1670,1672,1678,1681,1677,1669,1662,1658,1650,1637,1621,1608,1597,1585,1571,1561,1557,1556,
+1552,1543,1535,1534,1537,1538,1538,1541,1548,1556,1560,1564,1573,1585,1597,1609,1627,1652,1673,1684,1691,
+1710,1751,1797,1825,1829,1827,1834,1844,1842,1830,1823,1832,1845,1852,1864,1909,1994,2082,2126,2109,2082,
+2004,1954,1946,1978,2051,2162,2278,2336,2296,2190,2102,2088,2132,2178,2194,2198,2213,2234,2236,2215,2194,
+2199,2223,2246,2256,2267,2289,2313,2324,2319,2312,2317,2331,2345,2359,2378,2402,2421,2432,2440,2455,2475,
+2491,2502,2515,2535,2561,2584,2606,2631,2655,2671,2674,2673,2679,2694,2709,2720,2732,2747,2757,2761,2774,
+2825,2920,3025,3091,3101,3083,3074,3090,3120,3155,3200,3262,3321,3348,3338,3320,3336,3398,3478,3527,3518,
+3456,3374,3309,3276,3266,3253,3220,3170,3121,3083,3045,2997,2943,2910,2912,2941,2973,2993,3005,3019,3036,
+3048,3052,3048,3037,3021,3005,2999,3009,3017,2994,2926,2825,2721,2631,2557,2497,2453,2430,2423,2422,2421,
+2423,2431,2442,2451,2461,2481,2516,2560,2606,2656,2714,2774,2814,2818,2785,2726,2649,2552,2438,2317,2208,
+2123,2063,2022,1996,1983,1979,1982,1988,1998,2008,2015,2024,2045,2082,2121,2148,2163,2184,2222,2266,2288,
+2289,2305,2385,2539,2726,2887,2983,3015,3007,2983,2956,2926,2891,2847,2795,2740,2689,2642,2597,2554,2519,
+2495,2478,2461,2441,2424,2411,2398,2378,2353,2334,2326,2320,2307,2289,2275,2265,2253,2233,2212,2204,2215,
+2236,2257,2273,2282,2287,2293,2311,2346,2379,2388,2370,2359,2386,2437,2459,2416,2337,2286,2289,2305,2279,
+2206,2138,2118,2128,2118,2063,1991,1938,1907,1877,1839,1807,1797,1799,1790,1767,1747,1745,1751,1747,1728,
+1709,1699,1690,1671,1643,1619,1606,1598,1583,1559,1534,1513,1493,1471,1447,1427,1408,1386,1360,1331,1304,
+1280,1256,1233,1211,1186,1154,1118,1085,1060,1039,1015,985,952,923,895,866,833,801,772,744,716,
+688,664,644,625,603,578,552,525,497,467,438,411,383,351,315,278,241,200,153,100,49,
+4,-36,-78,-126,-179,-231,-277,-317,-356,-400,-448,-496,-537,-574,-613,-660,-713,-762,-802,-836,-874,
+-924,-986,-1049,-1103,-1139,-1159,-1172,-1187,-1209,-1235,-1261,-1288,-1322,-1368,-1428,-1497,-1567,-1635,-1699,-1757,-1811,
+-1862,-1914,-1968,-2021,-2072,-2123,-2173,-2221,-2264,-2304,-2346,-2392,-2437,-2477,-2516,-2562,-2614,-2664,-2702,-2728,-2757,
+-2796,-2841,-2886,-2934,-2989,-3050,-3104,-3141,-3173,-3217,-3274,-3328,-3363,-3383,-3401,-3425,-3441,-3442,-3439,-3452,-3486,
+-3521,-3541,-3551,-3576,-3629,-3697,-3760,-3807,-3844,-3874,-3898,-3917,-3940,-3972,-4006,-4026,-4030,-4032,-4048,-4072,-4085,
+-4070,-4036,-4008,-4001,-4009,-4019,-4025,-4032,-4044,-4062,-4076,-4075,-4058,-4034,-4013,-3997,-3980,-3949,-3903,-3853,-3819,
+-3811,-3827,-3857,-3885,-3901,-3900,-3886,-3871,-3861,-3853,-3834,-3798,-3747,-3680,-3590,-3480,-3378,-3330,-3353,-3400,-3386,
+-3259,-3054,-2860,-2744,-2708,-2703,-2692,-2673,-2665,-2675,-2693,-2711,-2727,-2741,-2749,-2748,-2744,-2748,-2761,-2772,-2774,
+-2776,-2788,-2809,-2817,-2792,-2731,-2654,-2590,-2554,-2545,-2549,-2546,-2522,-2471,-2402,-2331,-2269,-2223,-2190,-2166,-2143,
+-2117,-2086,-2056,-2039,-2039,-2048,-2054,-2050,-2037,-2025,-2017,-2010,-1991,-1955,-1905,-1853,-1807,-1758,-1687,-1580,-1461,
+-1377,-1368,-1422,-1487,-1510,-1478,-1416,-1349,-1274,-1174,-1044,-905,-782,-680,-584,-482,-373,-268,-172,-82,2,
+74,126,161,193,243,326,441,569,683,757,789,795,798,810,834,867,905,941,960,956,940,
+932,938,949,953,957,982,1039,1114,1186,1249,1312,1386,1469,1549,1625,1698,1767,1820,1855,1891,1951,
+2038,2129,2204,2261,2318,2386,2456,2517,2571,2628,2687,2731,2748,2740,2719,2689,2652,2618,2606,2616,2612,
+2544,2396,2209,2050,1966,1958,2002,2067,2123,2143,2127,2112,2152,2264,2395,2459,2418,2318,2253,2272,2348,
+2413,2427,2407,2388,2393,2419,2463,2530,2620,2713,2781,2811,2819,2829,2851,2878,2898,2915,2941,2976,3007,
+3016,3004,2986,2974,2969,2972,2988,3024,3066,3088,3074,3047,3059,3147,3289,3420,3483,3475,3444,3436,3463,
+3495,3504,3492,3486,3510,3559,3611,3645,3662,3683,3722,3776,3827,3863,3888,3916,3954,3997,4033,4056,4067,
+4065,4053,4038,4031,4040,4062,4083,4097,4108,4123,4141,4157,4165,4170,4179,4191,4200,4208,4226,4264,4317,
+4361,4376,4358,4327,4303,4295,4280,4210,4030,3709,3259,2745,2266,1923,1781,1844,2048,2294,2501,2641,2733,
+2809,2873,2907,2905,2885,2868,2853,2818,2753,2672,2599,2530,2451,2364,2309,2315,2360,2373,2300,2160,2030,
+1965,1956,1954,1925,1879,1844,1823,1796,1749,1691,1642,1606,1574,1535,1492,1448,1405,1357,1303,1252,1211,
+1181,1156,1132,1108,1085,1058,1025,990,960,937,915,887,852,815,782,756,736,714,685,649,611,
+582,565,555,539,509,468,424,381,338,297,262,236,219,203,181,154,128,106,90,80,72,
+63,48,26,2,-16,-27,-34,-41,-54,-74,-101,-130,-156,-175,-188,-200,-216,-236,-258,-282,-306,
+-330,-348,-356,-360,-364,-373,-381,-386,-391,-403,-426,-458,-490,-520,-550,-583,-616,-647,-677,-708,-740,
+-768,-792,-814,-837,-860,-880,-894,-904,-913,-924,-936,-949,-961,-968,-970,-969,-972,-981,-994,-1005,-1012,
+-1015,-1020,-1029,-1040,-1050,-1059,-1066,-1069,-1073,-1079,-1089,-1102,-1113,-1122,-1128,-1136,-1146,-1158,-1169,-1182,-1193,
+-1201,-1206,-1211,-1216,-1219,-1217,-1211,-1208,-1211,-1215,-1214,-1205,-1191,-1180,-1172,-1167,-1165,-1167,-1170,-1171,-1166,
+-1161,-1161,-1164,-1160,-1145,-1126,-1113,-1112,-1116,-1117,-1114,-1109,-1106,-1103,-1101,-1103,-1108,-1113,-1115,-1113,-1110,
+-1112,-1113,-1110,-1103,-1096,-1094,-1096,-1095,-1093,-1093,-1096,-1101,-1102,-1099,-1096,-1096,-1098,-1098,-1097,-1094,-1092,
+-1089,-1085,-1082,-1079,-1078,-1078,-1078,-1075,-1069,-1063,-1059,-1056,-1053,-1049,-1043,-1037,-1031,-1026,-1019,-1011,-1004,
+-997,-988,-975,-962,-952,-948,-947,-945,-942,-938,-934,-929,-921,-912,-905,-900,-897,-894,-889,-880,-867,
+-852,-840,-831,-826,-820,-810,-800,-790,-782,-772,-761,-751,-746,-742,-737,-727,-717,-709,-703,-698,-689,
+-679,-668,-657,-647,-638,-632,-629,-627,-623,-616,-608,-597,-588,-581,-578,-577,-574,-567,-555,-543,-530,
+-517,-506,-499,-495,-488,-476,-463,-451,-443,-433,-415,-390,-362,-337,-319,-305,-295,-284,-268,-247,-226,
+-212,-204,-198,-186,-173,-164,-160,-155,-144,-129,-115,-106,-97,-86,-74,-64,-57,-51,-41,-28,-15,
+-1,14,30,46,64,87,116,149,179,207,233,261,288,313,338,365,394,420,442,468,501,
+536,561,573,582,600,633,669,700,725,750,776,801,826,859,904,954,999,1034,1068,1110,1154,
+1191,1215,1237,1270,1314,1360,1401,1440,1485,1526,1531,1459,1300,1094,933,915,1091,1430,1839,2213,2495,
+2689,2845,2996,3136,3211,3157,2950,2631,2298,2054,1949,1955,2001,2033,2055,2110,2226,2380,2510,2567,2555,
+2521,2513,2539,2569,2569,2528,2460,2382,2301,2215,2131,2059,2008,1972,1939,1902,1864,1831,1802,1771,1735,
+1703,1687,1691,1707,1727,1742,1749,1752,1751,1750,1745,1735,1719,1699,1681,1664,1639,1605,1567,1539,1524,
+1514,1492,1450,1396,1344,1302,1265,1222,1165,1094,1015,938,868,804,750,712,700,709,715,683,590,
+447,290,150,42,-40,-109,-168,-218,-262,-303,-344,-381,-413,-440,-466,-491,-517,-541,-566,-592,-621,
+-649,-674,-694,-709,-724,-741,-757,-766,-765,-756,-747,-747,-754,-766,-777,-786,-788,-783,-772,-758,-745,
+-734,-721,-705,-689,-677,-665,-648,-623,-590,-551,-502,-440,-372,-310,-266,-238,-218,-198,-177,-154,-124,
+-85,-41,-2,28,55,82,106,120,129,145,178,225,268,297,314,331,357,395,441,491,540,
+583,614,633,645,654,667,685,708,733,757,778,798,818,840,864,892,925,962,999,1034,1067,
+1102,1138,1172,1201,1225,1246,1268,1288,1305,1322,1341,1362,1384,1403,1422,1443,1464,1484,1500,1513,1525,
+1536,1549,1562,1575,1585,1594,1602,1611,1621,1627,1630,1636,1651,1673,1693,1704,1708,1711,1715,1715,1707,
+1692,1676,1660,1645,1630,1616,1606,1597,1585,1570,1559,1555,1555,1552,1544,1540,1543,1549,1553,1554,1558,
+1566,1574,1577,1579,1586,1599,1613,1625,1637,1652,1665,1676,1693,1723,1761,1781,1769,1742,1740,1785,1857,
+1909,1915,1883,1840,1806,1795,1828,1915,2033,2123,2139,2082,2002,1932,1910,1933,1976,2035,2122,2226,2296,
+2285,2207,2125,2093,2109,2136,2150,2161,2183,2204,2203,2181,2164,2172,2198,2220,2231,2244,2267,2290,2297,
+2292,2290,2302,2321,2336,2348,2366,2389,2409,2420,2429,2443,2463,2478,2486,2494,2511,2535,2561,2588,2616,
+2642,2657,2659,2656,2660,2671,2681,2688,2699,2717,2732,2734,2738,2777,2865,2979,3068,3107,3109,3106,3111,
+3118,3124,3148,3205,3283,3344,3365,3357,3355,3379,3417,3436,3416,3361,3295,3245,3225,3221,3208,3169,3110,
+3050,2999,2951,2894,2830,2778,2756,2762,2782,2806,2833,2867,2901,2927,2941,2947,2947,2945,2946,2956,2972,
+2974,2938,2860,2760,2666,2591,2533,2486,2456,2446,2455,2467,2476,2483,2492,2505,2518,2535,2561,2598,2640,
+2684,2733,2792,2849,2885,2883,2843,2777,2693,2591,2475,2355,2248,2165,2108,2071,2052,2044,2044,2046,2051,
+2059,2067,2072,2080,2101,2138,2176,2199,2210,2228,2265,2305,2326,2329,2355,2447,2611,2803,2963,3059,3096,
+3097,3082,3057,3026,2987,2938,2882,2823,2767,2715,2667,2622,2584,2559,2542,2526,2508,2492,2480,2467,2449,
+2430,2415,2407,2400,2387,2372,2359,2350,2336,2315,2297,2294,2308,2330,2349,2363,2370,2370,2371,2388,2427,
+2472,2491,2479,2465,2487,2538,2566,2527,2438,2357,2322,2311,2277,2212,2153,2136,2146,2141,2095,2027,1970,
+1933,1905,1879,1861,1855,1851,1835,1810,1797,1802,1811,1807,1788,1768,1757,1747,1727,1700,1678,1665,1652,
+1631,1603,1577,1557,1539,1517,1494,1473,1453,1430,1402,1374,1350,1327,1304,1279,1253,1227,1197,1164,1133,
+1107,1085,1057,1023,987,958,934,909,879,848,819,791,762,732,705,684,666,647,624,597,571,
+544,516,488,459,431,401,369,333,294,251,205,158,112,71,29,-14,-63,-114,-163,-207,-248,
+-290,-337,-389,-442,-488,-526,-563,-605,-657,-713,-762,-801,-835,-873,-922,-976,-1025,-1059,-1080,-1094,-1114,
+-1141,-1172,-1205,-1241,-1286,-1341,-1404,-1467,-1528,-1588,-1648,-1704,-1756,-1805,-1855,-1908,-1961,-2014,-2065,-2116,-2165,
+-2208,-2246,-2285,-2328,-2372,-2414,-2453,-2498,-2551,-2605,-2653,-2692,-2728,-2764,-2798,-2832,-2868,-2917,-2976,-3036,-3089,
+-3138,-3192,-3247,-3291,-3319,-3339,-3364,-3390,-3406,-3407,-3408,-3430,-3469,-3503,-3518,-3531,-3573,-3654,-3750,-3825,-3864,
+-3879,-3889,-3902,-3918,-3936,-3958,-3981,-3998,-4009,-4021,-4043,-4069,-4084,-4079,-4060,-4044,-4039,-4037,-4028,-4013,-4004,
+-4011,-4032,-4054,-4062,-4055,-4036,-4015,-3989,-3954,-3902,-3837,-3775,-3732,-3722,-3747,-3795,-3844,-3873,-3873,-3855,-3840,
+-3838,-3838,-3822,-3784,-3731,-3666,-3578,-3464,-3351,-3291,-3309,-3360,-3355,-3239,-3041,-2852,-2743,-2712,-2711,-2700,-2681,
+-2676,-2691,-2716,-2737,-2753,-2767,-2781,-2794,-2807,-2822,-2837,-2842,-2837,-2833,-2842,-2857,-2857,-2824,-2767,-2710,-2674,
+-2659,-2650,-2632,-2600,-2556,-2504,-2447,-2387,-2330,-2282,-2248,-2227,-2210,-2191,-2166,-2144,-2131,-2129,-2129,-2124,-2113,
+-2101,-2092,-2083,-2066,-2037,-1998,-1954,-1913,-1875,-1830,-1759,-1655,-1536,-1446,-1420,-1455,-1507,-1528,-1502,-1447,-1383,
+-1311,-1218,-1101,-978,-869,-773,-675,-565,-449,-338,-236,-138,-45,32,86,115,138,182,262,380,515,
+633,708,734,728,717,718,734,761,791,816,829,830,827,834,851,871,886,906,946,1010,1084,
+1150,1204,1260,1328,1401,1472,1538,1606,1673,1731,1776,1821,1886,1974,2064,2139,2199,2262,2336,2414,2482,
+2541,2598,2652,2689,2697,2679,2644,2602,2560,2531,2519,2508,2461,2347,2181,2019,1914,1882,1900,1942,1994,
+2039,2059,2052,2055,2126,2276,2436,2505,2440,2302,2197,2190,2254,2323,2353,2352,2348,2357,2378,2415,2481,
+2572,2662,2723,2745,2751,2764,2789,2814,2832,2851,2883,2924,2958,2970,2963,2951,2942,2935,2935,2950,2989,
+3038,3065,3050,3008,2989,3040,3160,3298,3392,3416,3396,3377,3385,3413,3436,3446,3459,3494,3552,3608,3639,
+3646,3655,3687,3739,3788,3818,3831,3847,3880,3925,3970,4005,4026,4033,4025,4006,3988,3983,3994,4016,4039,
+4060,4078,4095,4111,4127,4143,4159,4168,4171,4178,4203,4249,4299,4330,4330,4306,4279,4263,4250,4208,4087,
+3846,3470,2995,2499,2081,1826,1775,1904,2134,2369,2542,2649,2724,2796,2859,2888,2876,2848,2831,2820,2788,
+2721,2637,2564,2503,2427,2331,2252,2233,2270,2301,2261,2148,2022,1942,1918,1912,1892,1855,1820,1791,1759,
+1716,1667,1625,1590,1557,1519,1477,1435,1389,1338,1286,1241,1206,1177,1147,1116,1086,1061,1033,999,963,
+931,907,885,861,830,797,766,739,717,697,676,649,617,586,561,541,518,488,452,415,379,
+343,303,264,232,211,199,185,166,141,114,90,73,62,52,38,17,-6,-26,-39,-47,-53,
+-63,-80,-103,-131,-157,-177,-191,-204,-218,-234,-251,-272,-298,-324,-343,-351,-353,-358,-370,-382,-390,
+-395,-404,-424,-452,-483,-514,-546,-580,-614,-645,-675,-707,-738,-766,-788,-808,-828,-850,-871,-889,-903,
+-914,-924,-934,-945,-956,-965,-969,-969,-970,-979,-993,-1008,-1017,-1022,-1026,-1033,-1042,-1052,-1062,-1070,-1075,
+-1079,-1084,-1092,-1103,-1113,-1121,-1128,-1136,-1145,-1157,-1169,-1182,-1194,-1201,-1205,-1206,-1207,-1207,-1205,-1202,-1201,
+-1203,-1207,-1204,-1195,-1184,-1175,-1169,-1165,-1162,-1160,-1159,-1158,-1155,-1153,-1153,-1153,-1147,-1135,-1124,-1118,-1117,
+-1113,-1105,-1100,-1103,-1114,-1121,-1120,-1115,-1115,-1119,-1125,-1127,-1127,-1129,-1132,-1130,-1122,-1114,-1110,-1111,-1113,
+-1112,-1111,-1112,-1116,-1119,-1118,-1115,-1113,-1113,-1113,-1110,-1107,-1104,-1101,-1099,-1097,-1093,-1089,-1086,-1085,-1084,
+-1080,-1073,-1067,-1064,-1063,-1061,-1054,-1045,-1037,-1032,-1026,-1019,-1011,-1003,-994,-984,-973,-966,-964,-965,-964,
+-959,-951,-943,-938,-933,-927,-919,-912,-906,-903,-898,-890,-877,-863,-850,-840,-834,-827,-819,-809,-798,
+-788,-776,-764,-754,-749,-745,-740,-732,-721,-712,-704,-698,-691,-682,-672,-660,-649,-640,-634,-630,-626,
+-622,-616,-610,-602,-594,-588,-584,-582,-578,-570,-559,-547,-533,-519,-507,-499,-496,-490,-481,-468,-457,
+-447,-437,-420,-398,-373,-348,-326,-309,-298,-289,-279,-264,-247,-232,-221,-210,-199,-187,-180,-175,-169,
+-157,-142,-131,-124,-116,-105,-92,-81,-72,-63,-50,-35,-22,-9,4,21,40,61,87,118,149,
+176,200,223,250,280,308,335,361,386,410,434,463,495,525,544,552,562,582,610,638,664,
+693,728,761,784,801,828,877,939,998,1042,1075,1105,1131,1150,1166,1193,1241,1301,1354,1394,1432,
+1479,1518,1510,1416,1238,1033,895,915,1127,1490,1899,2245,2477,2620,2747,2908,3079,3181,3131,2911,2588,
+2275,2071,2002,2023,2064,2085,2102,2161,2280,2426,2536,2572,2547,2511,2502,2513,2516,2490,2441,2387,2335,
+2272,2192,2104,2030,1980,1947,1917,1884,1852,1822,1790,1751,1710,1684,1680,1696,1720,1739,1750,1753,1752,
+1750,1749,1748,1743,1732,1716,1697,1676,1650,1618,1585,1558,1539,1519,1487,1444,1396,1354,1319,1285,1242,
+1181,1100,1006,913,837,782,749,732,728,729,718,671,577,447,305,175,64,-29,-108,-172,-223,
+-265,-305,-345,-381,-409,-430,-452,-476,-503,-531,-557,-583,-610,-638,-664,-685,-699,-709,-722,-741,-761,
+-773,-773,-767,-763,-764,-769,-774,-777,-776,-773,-765,-755,-744,-733,-722,-710,-696,-682,-666,-644,-618,
+-589,-556,-514,-461,-403,-353,-315,-288,-260,-228,-194,-162,-130,-95,-57,-18,19,58,97,129,149,
+160,179,215,266,313,343,359,373,395,427,465,505,545,583,614,636,649,660,673,692,715,
+740,767,793,818,840,857,874,896,927,965,1004,1041,1075,1109,1141,1171,1197,1221,1246,1272,1294,
+1311,1326,1344,1365,1387,1408,1428,1449,1471,1492,1511,1527,1543,1558,1574,1590,1604,1616,1626,1635,1644,
+1651,1655,1657,1664,1681,1706,1728,1739,1741,1740,1738,1731,1716,1694,1671,1653,1639,1627,1618,1612,1605,
+1594,1580,1570,1569,1569,1566,1557,1551,1552,1556,1558,1558,1562,1571,1579,1581,1582,1590,1607,1624,1635,
+1641,1651,1667,1692,1724,1761,1786,1778,1735,1689,1690,1760,1868,1956,1982,1947,1881,1820,1793,1824,1915,
+2026,2093,2077,2002,1914,1878,1893,1932,1961,1982,2030,2114,2195,2219,2176,2111,2075,2079,2099,2115,2130,
+2149,2165,2164,2148,2140,2153,2178,2197,2207,2221,2243,2262,2268,2265,2271,2290,2311,2325,2335,2353,2379,
+2402,2413,2420,2432,2449,2463,2469,2477,2494,2518,2543,2568,2596,2623,2640,2644,2640,2640,2646,2650,2652,
+2661,2680,2699,2706,2712,2745,2825,2934,3033,3094,3123,3136,3141,3130,3110,3108,3153,3238,3323,3371,3377,
+3367,3363,3369,3369,3348,3308,3264,3232,3218,3212,3193,3151,3089,3025,2969,2917,2857,2789,2727,2685,2664,
+2658,2668,2696,2743,2798,2843,2871,2885,2890,2894,2900,2911,2919,2907,2861,2784,2698,2626,2574,2535,2503,
+2483,2483,2497,2515,2528,2538,2548,2562,2579,2604,2638,2678,2718,2755,2798,2849,2901,2930,2923,2879,2810,
+2723,2621,2506,2390,2288,2209,2154,2122,2109,2107,2109,2111,2114,2120,2126,2128,2133,2151,2186,2224,2249,
+2263,2283,2318,2353,2369,2374,2408,2509,2673,2856,3005,3099,3147,3164,3163,3145,3115,3076,3029,2972,2909,
+2848,2793,2744,2698,2658,2627,2606,2588,2572,2557,2546,2537,2527,2516,2505,2496,2486,2472,2458,2447,2436,
+2421,2401,2388,2389,2403,2421,2438,2451,2460,2461,2461,2477,2521,2575,2607,2599,2576,2577,2609,2628,2590,
+2501,2410,2359,2335,2303,2248,2195,2171,2169,2155,2111,2049,1996,1963,1940,1922,1909,1903,1895,1875,1853,
+1843,1849,1859,1856,1842,1827,1818,1806,1785,1759,1737,1722,1703,1676,1646,1622,1607,1590,1567,1541,1518,
+1497,1473,1445,1417,1394,1373,1348,1319,1291,1267,1242,1213,1182,1153,1125,1094,1059,1025,997,976,954,
+927,897,868,840,809,777,747,724,706,689,666,641,616,591,566,538,508,479,450,418,382,
+341,299,257,217,178,137,93,46,-1,-48,-92,-135,-179,-225,-275,-331,-386,-435,-475,-510,-551,
+-605,-668,-727,-772,-803,-828,-861,-901,-942,-976,-1001,-1024,-1051,-1083,-1117,-1152,-1193,-1245,-1307,-1372,-1432,
+-1487,-1542,-1598,-1652,-1702,-1750,-1800,-1852,-1906,-1959,-2010,-2061,-2111,-2155,-2195,-2236,-2281,-2328,-2372,-2411,-2451,
+-2497,-2547,-2597,-2643,-2686,-2728,-2765,-2797,-2828,-2864,-2906,-2952,-2997,-3045,-3095,-3142,-3177,-3204,-3232,-3269,-3305,
+-3325,-3327,-3329,-3351,-3389,-3423,-3446,-3477,-3542,-3643,-3745,-3812,-3831,-3827,-3829,-3850,-3885,-3923,-3957,-3985,-4004,
+-4018,-4032,-4052,-4072,-4085,-4086,-4081,-4078,-4079,-4072,-4051,-4020,-3993,-3985,-3995,-4013,-4027,-4033,-4028,-4011,-3977,
+-3922,-3851,-3774,-3709,-3665,-3654,-3676,-3725,-3779,-3814,-3818,-3802,-3793,-3804,-3819,-3812,-3776,-3721,-3658,-3575,-3464,
+-3347,-3275,-3278,-3321,-3320,-3217,-3035,-2860,-2758,-2732,-2734,-2724,-2705,-2699,-2716,-2744,-2769,-2787,-2805,-2826,-2850,
+-2875,-2897,-2910,-2907,-2891,-2875,-2874,-2883,-2881,-2856,-2814,-2777,-2757,-2748,-2733,-2700,-2653,-2603,-2552,-2497,-2438,
+-2378,-2328,-2298,-2284,-2277,-2268,-2255,-2245,-2242,-2242,-2239,-2232,-2227,-2228,-2227,-2210,-2170,-2116,-2065,-2027,-2001,
+-1973,-1932,-1863,-1764,-1648,-1548,-1492,-1485,-1501,-1504,-1479,-1433,-1381,-1321,-1244,-1150,-1048,-949,-851,-744,-626,
+-507,-396,-294,-193,-95,-13,37,60,75,113,195,317,457,577,649,667,653,637,637,652,673,
+691,705,715,724,735,750,773,800,829,866,917,980,1046,1101,1149,1200,1263,1331,1398,1462,1526,
+1590,1648,1700,1757,1832,1920,2002,2068,2125,2192,2275,2361,2438,2503,2558,2599,2616,2602,2566,2525,2491,
+2468,2450,2429,2381,2280,2126,1960,1840,1797,1815,1854,1891,1927,1960,1977,1973,1984,2064,2217,2373,2434,
+2363,2225,2124,2116,2174,2237,2271,2283,2291,2301,2315,2345,2408,2501,2592,2649,2668,2674,2690,2716,2741,
+2759,2781,2819,2865,2902,2918,2917,2910,2903,2894,2887,2896,2930,2981,3018,3014,2974,2939,2957,3047,3180,
+3297,3353,3349,3323,3315,3335,3367,3394,3422,3468,3534,3597,3633,3638,3639,3662,3708,3753,3777,3783,3792,
+3819,3858,3896,3926,3949,3967,3977,3973,3959,3946,3944,3959,3985,4013,4038,4059,4080,4103,4123,4133,4131,
+4127,4137,4173,4226,4270,4287,4275,4251,4229,4212,4180,4097,3920,3619,3200,2715,2256,1917,1760,1793,1968,
+2202,2415,2562,2649,2712,2776,2834,2860,2849,2821,2801,2785,2748,2678,2598,2534,2484,2416,2317,2220,2179,
+2206,2253,2247,2165,2042,1938,1882,1862,1848,1825,1794,1758,1719,1678,1641,1609,1577,1541,1502,1462,1421,
+1375,1323,1273,1233,1202,1172,1136,1098,1065,1038,1011,977,939,906,880,858,833,805,775,747,722,
+700,683,666,646,620,589,558,530,501,468,433,400,371,341,305,266,230,205,190,180,166,
+145,120,94,72,57,44,30,11,-9,-29,-46,-60,-71,-83,-99,-119,-143,-167,-187,-203,-216,
+-227,-237,-248,-265,-289,-315,-335,-344,-347,-353,-365,-379,-390,-398,-410,-430,-455,-484,-515,-549,-585,
+-619,-649,-677,-706,-735,-762,-784,-803,-821,-842,-862,-882,-899,-915,-927,-937,-946,-956,-966,-971,-972,
+-974,-980,-993,-1007,-1018,-1027,-1035,-1043,-1051,-1058,-1064,-1070,-1076,-1079,-1083,-1089,-1098,-1108,-1118,-1128,-1139,
+-1150,-1161,-1173,-1185,-1195,-1201,-1201,-1198,-1195,-1193,-1190,-1188,-1188,-1191,-1192,-1189,-1182,-1175,-1170,-1168,-1165,
+-1160,-1154,-1149,-1144,-1140,-1139,-1140,-1139,-1134,-1129,-1126,-1126,-1123,-1111,-1095,-1090,-1101,-1119,-1129,-1121,-1107,
+-1100,-1108,-1122,-1132,-1137,-1142,-1146,-1146,-1140,-1132,-1128,-1128,-1130,-1129,-1125,-1123,-1125,-1128,-1131,-1130,-1128,
+-1125,-1123,-1121,-1118,-1115,-1114,-1113,-1112,-1109,-1105,-1101,-1099,-1098,-1095,-1089,-1083,-1079,-1078,-1075,-1068,-1059,
+-1052,-1046,-1039,-1028,-1015,-1005,-998,-992,-985,-980,-980,-982,-981,-974,-962,-951,-946,-943,-939,-930,-919,
+-910,-905,-901,-895,-886,-873,-860,-848,-838,-830,-823,-816,-808,-797,-785,-773,-764,-757,-752,-746,-739,
+-730,-720,-711,-703,-695,-686,-675,-661,-648,-638,-632,-627,-622,-616,-610,-605,-599,-593,-588,-584,-581,
+-576,-569,-560,-551,-541,-528,-515,-505,-497,-490,-481,-471,-461,-452,-440,-423,-402,-379,-356,-335,-316,
+-303,-294,-287,-276,-261,-245,-230,-216,-204,-194,-188,-184,-177,-165,-154,-148,-144,-137,-125,-110,-98,
+-88,-76,-60,-41,-25,-12,0,15,32,53,78,108,138,162,182,204,232,266,298,326,350,
+375,402,431,463,495,526,552,576,602,627,647,662,685,728,790,848,879,884,888,916,967,
+1024,1067,1094,1111,1120,1128,1145,1185,1249,1319,1372,1406,1436,1473,1496,1463,1343,1153,959,858,930,
+1195,1592,2001,2309,2479,2566,2668,2832,3015,3116,3053,2833,2539,2282,2130,2086,2103,2127,2136,2154,2215,
+2328,2455,2537,2545,2503,2463,2453,2459,2448,2407,2357,2318,2289,2245,2171,2081,2003,1952,1922,1895,1866,
+1834,1802,1765,1723,1688,1673,1681,1704,1727,1741,1748,1751,1751,1750,1748,1745,1740,1730,1715,1698,1679,
+1655,1627,1597,1569,1542,1512,1474,1433,1395,1365,1338,1307,1261,1192,1099,990,889,816,779,769,766,
+759,740,703,640,545,425,295,172,62,-33,-113,-177,-226,-268,-307,-344,-376,-400,-420,-442,-468,
+-495,-521,-545,-567,-591,-617,-644,-668,-684,-695,-706,-724,-747,-766,-772,-769,-763,-762,-766,-770,-770,
+-767,-763,-759,-752,-744,-733,-720,-708,-695,-679,-658,-632,-604,-577,-550,-518,-477,-431,-390,-358,-331,
+-300,-261,-218,-177,-141,-107,-75,-41,-1,47,102,153,188,207,221,244,280,323,366,406,446,
+484,517,541,558,574,592,611,628,641,655,674,697,722,748,777,810,843,870,888,900,915,
+941,975,1013,1048,1080,1110,1139,1165,1189,1214,1241,1269,1293,1313,1330,1349,1370,1392,1416,1439,1461,
+1483,1502,1521,1542,1564,1586,1604,1621,1636,1649,1660,1668,1676,1683,1689,1695,1705,1722,1743,1759,1763,
+1758,1750,1742,1729,1709,1684,1663,1650,1642,1635,1629,1625,1619,1610,1598,1591,1591,1591,1584,1572,1561,
+1557,1556,1554,1552,1556,1567,1577,1580,1581,1589,1607,1624,1634,1640,1654,1684,1723,1762,1791,1800,1784,
+1747,1717,1724,1780,1860,1925,1952,1940,1905,1866,1842,1856,1912,1979,2008,1976,1914,1855,1865,1912,1957,
+1966,1951,1961,2019,2094,2132,2114,2071,2047,2055,2076,2091,2102,2113,2124,2124,2119,2120,2137,2159,2174,
+2184,2198,2219,2237,2244,2247,2259,2281,2301,2314,2326,2348,2377,2401,2411,2416,2425,2440,2451,2458,2467,
+2487,2512,2534,2553,2574,2599,2619,2626,2624,2623,2625,2626,2625,2629,2643,2663,2677,2690,2721,2787,2879,
+2972,3046,3100,3138,3156,3143,3112,3096,3128,3206,3293,3350,3363,3351,3337,3329,3323,3310,3288,3263,3242,
+3226,3210,3186,3148,3098,3047,2998,2947,2888,2822,2759,2708,2668,2635,2619,2631,2676,2741,2804,2849,2872,
+2879,2878,2874,2868,2855,2824,2772,2707,2647,2604,2577,2555,2534,2521,2523,2536,2553,2568,2581,2596,2615,
+2640,2677,2723,2768,2804,2827,2851,2884,2920,2940,2930,2889,2824,2741,2641,2531,2421,2326,2253,2203,2175,
+2166,2169,2174,2176,2178,2181,2184,2183,2186,2201,2234,2271,2298,2318,2343,2377,2407,2419,2424,2463,2564,
+2717,2878,3008,3097,3158,3200,3220,3215,3191,3157,3114,3059,2994,2930,2875,2828,2783,2739,2701,2674,2656,
+2641,2628,2619,2614,2610,2604,2594,2582,2570,2558,2547,2536,2522,2506,2490,2483,2488,2499,2510,2522,2536,
+2551,2559,2563,2580,2625,2684,2718,2706,2666,2638,2639,2639,2599,2518,2435,2387,2368,2345,2300,2247,2210,
+2189,2163,2120,2069,2029,2004,1985,1968,1954,1945,1935,1918,1900,1891,1895,1901,1900,1894,1887,1881,1867,
+1843,1816,1795,1777,1755,1724,1694,1673,1660,1642,1615,1586,1561,1541,1518,1489,1460,1436,1414,1389,1359,
+1332,1310,1289,1263,1230,1196,1164,1134,1102,1070,1043,1021,999,974,945,916,888,856,822,789,764,
+745,726,705,681,658,635,610,582,552,523,494,463,428,388,350,314,279,242,199,152,105,
+60,18,-24,-68,-115,-165,-218,-273,-327,-377,-417,-453,-494,-550,-617,-682,-731,-760,-780,-804,-836,
+-872,-906,-936,-965,-998,-1032,-1065,-1101,-1144,-1199,-1265,-1330,-1390,-1443,-1495,-1547,-1599,-1648,-1696,-1745,-1798,
+-1852,-1903,-1954,-2005,-2054,-2099,-2140,-2183,-2231,-2282,-2330,-2371,-2407,-2446,-2489,-2535,-2581,-2628,-2675,-2722,-2766,
+-2804,-2838,-2868,-2897,-2929,-2968,-3013,-3054,-3087,-3117,-3153,-3198,-3239,-3261,-3265,-3268,-3284,-3314,-3346,-3377,-3423,
+-3502,-3604,-3695,-3743,-3744,-3727,-3725,-3755,-3811,-3878,-3942,-3992,-4024,-4042,-4053,-4065,-4076,-4084,-4088,-4090,-4094,
+-4098,-4092,-4070,-4036,-4003,-3980,-3972,-3975,-3985,-3998,-4006,-3998,-3962,-3897,-3817,-3740,-3681,-3644,-3630,-3640,-3673,
+-3716,-3748,-3754,-3747,-3749,-3773,-3802,-3806,-3774,-3717,-3652,-3571,-3465,-3349,-3270,-3258,-3289,-3287,-3198,-3037,-2879,
+-2786,-2761,-2760,-2748,-2727,-2719,-2737,-2770,-2803,-2833,-2862,-2892,-2921,-2946,-2962,-2966,-2952,-2925,-2901,-2893,-2900,
+-2906,-2895,-2871,-2847,-2831,-2816,-2790,-2748,-2698,-2647,-2597,-2541,-2480,-2421,-2379,-2361,-2362,-2369,-2372,-2372,-2374,
+-2379,-2383,-2381,-2382,-2393,-2413,-2421,-2393,-2327,-2246,-2179,-2142,-2122,-2099,-2056,-1988,-1898,-1793,-1689,-1604,-1548,
+-1514,-1483,-1444,-1398,-1351,-1301,-1241,-1167,-1082,-990,-888,-776,-657,-543,-441,-343,-243,-145,-64,-17,2,
+17,56,135,253,385,498,565,583,570,556,557,570,584,592,600,614,634,656,680,708,742,
+784,834,889,947,1001,1049,1093,1142,1201,1269,1338,1406,1470,1529,1582,1636,1702,1782,1866,1938,1993,
+2046,2115,2203,2296,2382,2456,2516,2552,2550,2510,2454,2409,2387,2379,2363,2317,2223,2078,1908,1765,1696,
+1706,1759,1808,1840,1865,1891,1905,1899,1903,1961,2079,2198,2241,2185,2090,2035,2052,2110,2159,2183,2195,
+2205,2212,2218,2244,2312,2413,2509,2565,2581,2586,2603,2631,2656,2676,2705,2748,2798,2837,2854,2857,2855,
+2850,2840,2828,2828,2850,2893,2936,2953,2936,2906,2905,2966,3081,3206,3287,3302,3278,3260,3270,3300,3329,
+3356,3398,3461,3529,3574,3589,3596,3622,3671,3723,3756,3771,3785,3807,3832,3847,3853,3862,3884,3915,3938,
+3946,3940,3934,3940,3958,3983,4009,4034,4060,4086,4102,4100,4086,4077,4095,4140,4193,4225,4227,4208,4187,
+4167,4134,4065,3931,3702,3361,2922,2452,2047,1794,1731,1833,2032,2254,2441,2569,2648,2705,2758,2804,2827,
+2819,2796,2772,2747,2702,2633,2559,2503,2461,2402,2308,2209,2157,2174,2224,2239,2177,2057,1932,1846,1809,
+1800,1791,1767,1726,1681,1643,1617,1597,1569,1531,1487,1445,1404,1358,1307,1259,1222,1193,1161,1120,1078,
+1044,1019,993,959,921,886,858,834,807,779,751,727,706,687,671,657,640,616,585,553,522,
+490,456,420,386,357,329,298,264,229,202,182,169,156,139,118,96,74,56,41,26,8,
+-12,-33,-54,-74,-92,-110,-126,-144,-164,-184,-203,-220,-233,-242,-249,-257,-269,-289,-313,-331,-342,
+-348,-356,-368,-382,-396,-409,-426,-446,-468,-492,-519,-554,-592,-629,-659,-685,-710,-736,-761,-782,-801,
+-820,-840,-861,-880,-898,-914,-928,-939,-949,-959,-968,-975,-979,-981,-986,-994,-1005,-1017,-1030,-1044,-1056,
+-1063,-1065,-1065,-1067,-1071,-1075,-1079,-1085,-1093,-1104,-1117,-1130,-1144,-1156,-1167,-1177,-1186,-1194,-1197,-1197,-1193,
+-1188,-1185,-1182,-1180,-1179,-1178,-1176,-1170,-1163,-1158,-1155,-1154,-1151,-1146,-1141,-1136,-1131,-1126,-1123,-1122,-1120,
+-1118,-1117,-1118,-1121,-1117,-1104,-1089,-1088,-1102,-1121,-1124,-1108,-1088,-1083,-1098,-1121,-1140,-1149,-1154,-1159,-1162,
+-1159,-1153,-1149,-1151,-1155,-1155,-1147,-1137,-1131,-1130,-1133,-1134,-1134,-1132,-1130,-1129,-1128,-1125,-1122,-1120,-1120,
+-1121,-1120,-1119,-1118,-1118,-1116,-1111,-1104,-1099,-1095,-1090,-1083,-1075,-1069,-1064,-1056,-1042,-1025,-1011,-1003,-999,
+-996,-994,-994,-996,-995,-986,-973,-961,-953,-949,-943,-932,-920,-910,-904,-901,-896,-890,-880,-868,-854,
+-841,-832,-828,-824,-818,-808,-796,-786,-778,-769,-761,-753,-746,-739,-730,-719,-708,-699,-690,-679,-664,
+-650,-639,-633,-628,-621,-614,-607,-601,-596,-590,-585,-581,-578,-573,-565,-557,-551,-545,-537,-526,-513,
+-501,-491,-483,-475,-468,-457,-443,-423,-401,-380,-361,-343,-327,-313,-302,-293,-283,-270,-255,-240,-224,
+-210,-201,-196,-193,-186,-177,-169,-165,-163,-155,-141,-125,-113,-103,-91,-72,-50,-29,-13,0,12,
+25,42,65,93,122,147,167,191,221,255,287,313,338,367,401,437,472,505,543,587,638,
+688,723,733,733,751,813,908,998,1040,1031,1000,986,1004,1039,1072,1094,1107,1115,1129,1159,1213,
+1285,1353,1398,1423,1442,1462,1457,1391,1248,1056,887,834,966,1285,1712,2111,2371,2478,2521,2614,2790,
+2975,3053,2962,2741,2492,2302,2201,2169,2167,2168,2168,2186,2243,2339,2440,2498,2489,2438,2392,2379,2382,
+2367,2325,2279,2251,2236,2205,2139,2054,1980,1933,1906,1880,1849,1814,1779,1743,1707,1682,1678,1691,1710,
+1723,1730,1733,1735,1736,1734,1730,1726,1720,1710,1696,1682,1667,1649,1626,1597,1568,1538,1505,1468,1433,
+1403,1378,1351,1315,1259,1179,1075,963,867,811,798,805,805,780,731,665,585,488,374,254,138,
+35,-51,-123,-181,-230,-275,-316,-352,-382,-406,-429,-454,-479,-502,-522,-540,-556,-574,-594,-618,-645,
+-668,-684,-697,-713,-733,-753,-763,-762,-757,-756,-760,-763,-762,-757,-753,-752,-751,-747,-736,-722,-704,
+-686,-665,-640,-612,-585,-563,-546,-525,-496,-458,-418,-383,-353,-321,-284,-243,-200,-159,-123,-90,-58,
+-20,30,94,162,216,245,252,251,260,287,337,405,480,547,595,618,622,620,620,625,633,
+645,662,686,713,741,767,796,830,867,900,923,937,951,972,1001,1033,1062,1089,1116,1144,1172,
+1197,1222,1248,1275,1301,1326,1348,1369,1390,1414,1440,1468,1494,1515,1531,1549,1572,1599,1623,1641,1654,
+1667,1679,1689,1695,1701,1709,1717,1726,1738,1753,1769,1778,1776,1765,1754,1746,1734,1715,1693,1674,1664,
+1658,1652,1644,1637,1630,1622,1613,1607,1606,1604,1595,1581,1569,1563,1561,1558,1556,1561,1574,1584,1586,
+1585,1591,1605,1619,1627,1634,1656,1693,1734,1759,1765,1763,1766,1779,1798,1817,1827,1826,1821,1827,1852,
+1887,1910,1912,1906,1910,1919,1912,1882,1855,1834,1882,1947,1990,1986,1954,1942,1973,2025,2053,2045,2024,
+2021,2040,2063,2074,2077,2081,2088,2092,2092,2099,2115,2135,2149,2158,2171,2192,2211,2223,2234,2250,2271,
+2291,2306,2323,2349,2378,2398,2406,2411,2423,2439,2450,2456,2467,2489,2516,2536,2548,2561,2580,2598,2607,
+2607,2605,2608,2611,2609,2608,2614,2630,2650,2670,2698,2745,2811,2885,2961,3034,3099,3139,3141,3117,3100,
+3123,3185,3257,3305,3320,3312,3301,3293,3289,3284,3275,3261,3242,3217,3189,3159,3128,3097,3068,3035,2992,
+2937,2877,2823,2776,2731,2685,2649,2641,2675,2740,2810,2864,2891,2893,2879,2855,2824,2787,2743,2694,2648,
+2614,2593,2581,2569,2557,2551,2554,2565,2580,2597,2618,2643,2672,2710,2761,2819,2870,2898,2901,2897,2902,
+2916,2924,2912,2876,2819,2743,2650,2546,2444,2358,2293,2250,2227,2223,2230,2239,2242,2242,2242,2240,2238,
+2241,2258,2289,2323,2350,2371,2398,2432,2458,2466,2474,2517,2616,2753,2887,2992,3072,3144,3209,3252,3265,
+3252,3224,3187,3136,3073,3010,2958,2915,2870,2822,2778,2748,2730,2717,2705,2695,2690,2689,2685,2677,2666,
+2656,2648,2639,2626,2608,2590,2579,2579,2588,2595,2599,2607,2624,2647,2664,2671,2687,2726,2776,2803,2783,
+2728,2680,2659,2645,2603,2528,2452,2408,2394,2380,2343,2292,2245,2209,2176,2137,2099,2071,2051,2034,2015,
+1998,1988,1980,1969,1955,1947,1946,1947,1948,1947,1946,1941,1925,1899,1871,1851,1833,1809,1778,1749,1729,
+1714,1693,1663,1632,1607,1588,1565,1535,1505,1479,1457,1432,1404,1378,1358,1338,1309,1273,1237,1206,1178,
+1150,1119,1091,1066,1043,1019,992,963,933,900,864,831,803,782,764,744,722,700,677,650,621,
+591,564,538,510,478,443,409,375,341,301,256,208,164,123,83,40,-7,-59,-111,-162,-213,
+-264,-311,-353,-393,-438,-494,-558,-619,-666,-697,-720,-746,-779,-817,-853,-886,-918,-951,-983,-1015,-1050,
+-1095,-1152,-1218,-1284,-1344,-1397,-1447,-1497,-1546,-1594,-1641,-1691,-1743,-1794,-1845,-1896,-1946,-1993,-2037,-2077,-2119,
+-2166,-2217,-2266,-2309,-2346,-2383,-2426,-2472,-2520,-2567,-2615,-2666,-2719,-2770,-2811,-2843,-2869,-2898,-2936,-2980,-3022,
+-3057,-3090,-3128,-3171,-3209,-3231,-3239,-3246,-3261,-3284,-3310,-3340,-3388,-3462,-3551,-3628,-3669,-3673,-3661,-3659,-3684,
+-3738,-3812,-3892,-3961,-4010,-4038,-4053,-4064,-4075,-4083,-4088,-4091,-4095,-4097,-4091,-4076,-4052,-4025,-4000,-3978,-3964,
+-3962,-3972,-3985,-3983,-3951,-3886,-3805,-3732,-3681,-3650,-3635,-3633,-3647,-3675,-3701,-3713,-3716,-3729,-3761,-3797,-3807,
+-3777,-3718,-3647,-3563,-3459,-3348,-3268,-3248,-3267,-3263,-3185,-3043,-2901,-2814,-2784,-2777,-2760,-2738,-2730,-2751,-2792,
+-2839,-2884,-2926,-2964,-2991,-3005,-3007,-2997,-2976,-2948,-2926,-2921,-2931,-2942,-2942,-2929,-2910,-2890,-2864,-2826,-2777,
+-2726,-2679,-2634,-2587,-2537,-2495,-2475,-2478,-2497,-2518,-2532,-2542,-2551,-2559,-2563,-2562,-2566,-2587,-2616,-2628,-2595,
+-2515,-2418,-2340,-2293,-2265,-2233,-2184,-2120,-2044,-1958,-1860,-1760,-1667,-1586,-1513,-1445,-1381,-1324,-1273,-1219,-1156,
+-1082,-996,-896,-785,-672,-567,-472,-382,-290,-201,-130,-83,-54,-25,21,92,185,287,379,441,468,
+470,465,466,474,480,485,495,518,550,585,620,657,702,754,810,864,915,962,1006,1050,1097,
+1154,1220,1292,1362,1425,1477,1523,1575,1643,1725,1805,1869,1919,1972,2042,2127,2218,2306,2391,2465,2508,
+2500,2446,2378,2328,2305,2288,2245,2156,2020,1859,1709,1613,1596,1642,1707,1753,1777,1798,1823,1840,1837,
+1832,1860,1930,2002,2028,2000,1962,1960,1999,2047,2076,2087,2096,2106,2109,2111,2139,2215,2324,2422,2475,
+2489,2494,2513,2543,2570,2595,2630,2680,2733,2770,2786,2788,2788,2787,2782,2773,2766,2773,2798,2837,2872,
+2886,2878,2873,2907,2995,3111,3204,3240,3231,3216,3224,3248,3269,3281,3303,3350,3414,3467,3497,3520,3562,
+3628,3701,3760,3800,3831,3856,3868,3858,3835,3819,3828,3861,3900,3927,3937,3938,3941,3949,3964,3984,4009,
+4037,4061,4070,4060,4041,4037,4062,4108,4148,4162,4150,4131,4114,4085,4020,3898,3708,3439,3081,2655,2224,
+1887,1719,1736,1887,2095,2296,2457,2572,2649,2703,2745,2776,2791,2785,2765,2739,2707,2660,2595,2528,2474,
+2430,2373,2288,2195,2137,2136,2170,2183,2134,2028,1906,1811,1765,1755,1753,1734,1695,1648,1614,1598,1587,
+1564,1523,1473,1426,1383,1338,1289,1245,1212,1185,1152,1109,1063,1026,1000,975,943,905,869,839,813,
+786,757,731,709,690,673,658,645,628,605,575,541,509,477,445,411,377,345,315,285,255,
+226,201,179,162,146,130,113,95,76,59,43,26,7,-15,-39,-64,-88,-112,-134,-154,-172,
+-189,-205,-221,-237,-250,-261,-268,-275,-285,-301,-320,-338,-351,-362,-373,-386,-400,-415,-432,-451,-471,
+-489,-505,-528,-560,-599,-638,-670,-696,-719,-742,-763,-782,-800,-820,-842,-864,-883,-899,-913,-926,-937,
+-948,-958,-968,-977,-983,-987,-991,-995,-1002,-1014,-1030,-1048,-1062,-1067,-1066,-1062,-1061,-1065,-1071,-1078,-1086,
+-1096,-1107,-1120,-1134,-1146,-1158,-1167,-1175,-1183,-1189,-1193,-1195,-1193,-1190,-1187,-1185,-1183,-1181,-1175,-1166,-1155,
+-1146,-1140,-1136,-1132,-1127,-1123,-1122,-1123,-1121,-1116,-1111,-1108,-1107,-1106,-1106,-1106,-1106,-1102,-1095,-1088,-1092,
+-1106,-1119,-1117,-1100,-1084,-1085,-1106,-1133,-1151,-1158,-1161,-1167,-1173,-1175,-1172,-1171,-1178,-1188,-1194,-1187,-1170,
+-1152,-1139,-1135,-1136,-1137,-1138,-1140,-1141,-1141,-1137,-1129,-1123,-1121,-1124,-1128,-1131,-1133,-1132,-1131,-1127,-1122,
+-1117,-1111,-1103,-1094,-1087,-1082,-1080,-1073,-1059,-1040,-1022,-1012,-1008,-1006,-1006,-1007,-1008,-1006,-998,-985,-971,
+-959,-950,-939,-928,-917,-910,-905,-901,-896,-891,-884,-874,-861,-848,-839,-836,-832,-826,-815,-804,-795,
+-787,-776,-764,-754,-749,-744,-736,-722,-708,-698,-691,-683,-671,-657,-645,-638,-633,-626,-618,-610,-602,
+-595,-588,-584,-582,-580,-574,-564,-553,-547,-544,-539,-530,-516,-501,-491,-483,-477,-469,-457,-441,-420,
+-400,-381,-365,-350,-337,-324,-313,-302,-290,-278,-265,-252,-238,-224,-214,-209,-207,-203,-195,-187,-181,
+-175,-165,-151,-136,-124,-116,-104,-86,-63,-40,-21,-5,6,18,32,54,82,112,139,163,190,
+222,254,282,306,331,366,407,448,483,515,555,611,680,746,784,787,774,787,855,968,1074,
+1124,1106,1053,1010,1000,1018,1046,1072,1096,1120,1152,1197,1258,1325,1379,1411,1428,1439,1439,1403,1305,
+1147,970,843,847,1034,1391,1825,2193,2399,2460,2495,2617,2831,3025,3071,2938,2706,2489,2350,2280,2239,
+2207,2183,2176,2192,2234,2302,2376,2421,2412,2363,2313,2290,2286,2273,2241,2205,2185,2175,2150,2094,2023,
+1961,1922,1895,1867,1833,1798,1766,1737,1711,1695,1694,1703,1711,1714,1713,1713,1711,1706,1698,1691,1689,
+1687,1681,1669,1657,1645,1631,1610,1582,1554,1527,1500,1469,1437,1405,1373,1334,1283,1215,1126,1023,921,
+846,815,822,835,821,766,683,591,499,404,299,189,85,-4,-78,-139,-194,-247,-297,-343,-381,
+-411,-437,-463,-489,-510,-526,-538,-551,-564,-575,-588,-607,-633,-661,-683,-696,-708,-724,-743,-756,-759,
+-756,-753,-754,-755,-751,-744,-741,-743,-748,-750,-743,-727,-705,-680,-654,-626,-597,-572,-554,-542,-529,
+-508,-473,-431,-390,-355,-325,-295,-260,-219,-175,-131,-91,-57,-23,21,81,153,219,261,272,261,
+248,254,289,352,431,511,575,616,635,640,641,645,653,666,688,716,749,780,807,833,860,
+892,924,952,975,995,1017,1041,1065,1088,1111,1138,1168,1199,1227,1252,1275,1299,1325,1353,1381,1404,
+1425,1447,1475,1506,1535,1555,1569,1586,1611,1640,1663,1678,1687,1697,1708,1716,1721,1724,1730,1737,1746,
+1756,1769,1783,1791,1787,1777,1768,1764,1758,1744,1724,1705,1692,1682,1671,1658,1648,1640,1632,1624,1617,
+1613,1608,1599,1588,1580,1579,1581,1580,1579,1584,1593,1600,1600,1597,1600,1612,1623,1628,1635,1655,1688,
+1713,1712,1693,1686,1719,1790,1862,1890,1854,1776,1704,1690,1747,1844,1926,1957,1939,1900,1864,1837,1822,
+1834,1837,1900,1963,1995,1983,1951,1933,1948,1976,1992,1989,1988,2004,2032,2052,2057,2055,2059,2066,2071,
+2072,2077,2092,2111,2125,2133,2145,2163,2184,2202,2217,2235,2256,2277,2297,2320,2347,2372,2386,2393,2403,
+2422,2443,2457,2463,2475,2498,2526,2545,2554,2561,2573,2587,2592,2589,2587,2591,2596,2594,2588,2587,2598,
+2619,2644,2671,2701,2741,2793,2862,2947,3032,3095,3118,3110,3101,3117,3162,3214,3253,3269,3270,3265,3260,
+3254,3251,3246,3234,3210,3174,3134,3097,3069,3052,3041,3026,2998,2957,2909,2864,2825,2785,2741,2703,2692,
+2720,2779,2846,2894,2911,2899,2867,2823,2775,2726,2680,2641,2613,2596,2586,2578,2571,2567,2570,2579,2591,
+2605,2626,2656,2693,2736,2785,2846,2910,2961,2979,2966,2940,2921,2914,2908,2890,2855,2803,2733,2646,2550,
+2459,2385,2332,2297,2280,2280,2291,2302,2307,2305,2300,2296,2294,2301,2321,2352,2382,2404,2423,2448,2478,
+2499,2505,2518,2569,2671,2800,2914,2997,3065,3137,3214,3274,3301,3298,3279,3247,3201,3142,3085,3037,2996,
+2951,2900,2853,2821,2805,2793,2779,2767,2761,2761,2762,2759,2753,2748,2744,2736,2718,2694,2674,2668,2675,
+2687,2693,2694,2702,2724,2753,2773,2778,2783,2805,2838,2853,2828,2776,2729,2708,2692,2649,2573,2492,2439,
+2418,2405,2374,2327,2278,2237,2200,2164,2132,2108,2091,2074,2057,2042,2034,2029,2020,2009,2001,1998,1999,
+2001,2003,2003,1996,1978,1951,1925,1905,1888,1866,1836,1807,1786,1768,1745,1714,1683,1658,1637,1613,1582,
+1550,1523,1500,1476,1450,1426,1404,1381,1350,1313,1278,1249,1224,1196,1164,1133,1106,1084,1061,1036,1006,
+973,939,904,872,845,823,804,786,768,746,721,691,661,633,609,587,562,534,504,472,439,
+401,358,312,266,225,187,147,102,50,-4,-58,-107,-151,-196,-242,-289,-338,-390,-445,-499,-548,
+-588,-621,-651,-686,-725,-766,-806,-842,-875,-906,-936,-967,-1005,-1051,-1108,-1172,-1236,-1296,-1350,-1401,-1449,
+-1496,-1543,-1591,-1640,-1689,-1738,-1787,-1838,-1888,-1935,-1977,-2017,-2059,-2105,-2154,-2201,-2242,-2280,-2319,-2364,-2414,
+-2466,-2514,-2560,-2608,-2661,-2715,-2766,-2807,-2840,-2875,-2916,-2961,-3003,-3039,-3072,-3108,-3145,-3178,-3199,-3213,-3228,
+-3248,-3271,-3295,-3321,-3360,-3417,-3487,-3555,-3609,-3644,-3662,-3671,-3683,-3711,-3759,-3824,-3891,-3947,-3989,-4022,-4050,
+-4073,-4089,-4096,-4098,-4097,-4094,-4087,-4077,-4064,-4049,-4029,-4006,-3985,-3972,-3973,-3980,-3979,-3951,-3892,-3814,-3739,
+-3685,-3652,-3634,-3627,-3634,-3654,-3679,-3698,-3712,-3733,-3767,-3802,-3813,-3786,-3729,-3653,-3563,-3458,-3350,-3274,-3251,
+-3263,-3256,-3185,-3061,-2936,-2856,-2825,-2812,-2793,-2772,-2768,-2792,-2838,-2890,-2942,-2988,-3024,-3044,-3047,-3038,-3022,
+-3004,-2987,-2979,-2981,-2992,-2999,-2995,-2981,-2962,-2939,-2906,-2861,-2808,-2759,-2720,-2691,-2666,-2645,-2632,-2635,-2656,
+-2686,-2715,-2737,-2752,-2763,-2769,-2767,-2759,-2755,-2767,-2788,-2795,-2764,-2691,-2597,-2510,-2445,-2394,-2343,-2288,-2231,
+-2175,-2110,-2029,-1929,-1819,-1708,-1600,-1498,-1406,-1327,-1261,-1201,-1139,-1071,-992,-902,-801,-695,-593,-500,-416,
+-339,-271,-215,-165,-114,-56,4,61,113,168,227,287,333,359,369,371,372,375,383,402,435,
+477,522,567,615,670,728,784,836,883,928,973,1018,1064,1115,1176,1244,1312,1370,1416,1457,1507,
+1576,1657,1736,1801,1855,1913,1980,2055,2132,2214,2302,2386,2438,2435,2384,2318,2267,2230,2178,2083,1944,
+1784,1640,1542,1508,1535,1598,1658,1693,1708,1724,1750,1772,1779,1778,1792,1830,1872,1892,1890,1892,1916,
+1952,1977,1985,1989,2001,2014,2014,2012,2041,2121,2233,2330,2381,2397,2408,2432,2463,2490,2518,2560,2616,
+2671,2705,2717,2717,2717,2721,2725,2725,2719,2715,2720,2744,2782,2819,2836,2838,2854,2912,3007,3100,3155,
+3170,3174,3192,3220,3235,3232,3231,3254,3299,3349,3388,3428,3487,3572,3667,3754,3825,3880,3919,3931,3913,
+3875,3840,3826,3837,3862,3887,3906,3917,3924,3929,3937,3951,3974,3999,4018,4022,4011,3999,4005,4034,4071,
+4092,4088,4071,4056,4037,3986,3872,3689,3446,3149,2798,2409,2040,1778,1689,1769,1952,2158,2334,2470,2572,
+2647,2700,2733,2752,2757,2747,2725,2697,2662,2618,2563,2502,2446,2393,2332,2255,2171,2107,2078,2077,2072,
+2036,1963,1873,1793,1742,1722,1714,1697,1663,1622,1591,1579,1572,1552,1510,1457,1406,1361,1318,1275,1238,
+1211,1188,1156,1110,1058,1015,984,957,927,891,855,824,797,770,743,717,694,673,654,639,626,
+611,591,562,528,493,460,429,400,370,338,305,272,243,218,197,177,157,138,122,106,90,
+73,58,43,26,5,-20,-47,-74,-101,-128,-155,-179,-199,-215,-229,-242,-256,-269,-279,-287,-293,
+-301,-315,-333,-353,-371,-388,-403,-418,-430,-443,-459,-479,-497,-513,-526,-544,-572,-607,-645,-677,-704,
+-728,-749,-767,-783,-799,-819,-843,-867,-886,-899,-910,-921,-932,-944,-955,-965,-974,-981,-987,-992,-995,
+-1001,-1011,-1026,-1043,-1055,-1060,-1058,-1055,-1056,-1061,-1069,-1080,-1091,-1104,-1116,-1127,-1136,-1144,-1152,-1159,-1166,
+-1173,-1180,-1186,-1189,-1188,-1185,-1182,-1183,-1185,-1183,-1174,-1159,-1143,-1134,-1130,-1127,-1119,-1109,-1104,-1106,-1113,
+-1116,-1112,-1106,-1103,-1105,-1106,-1104,-1099,-1094,-1092,-1091,-1092,-1098,-1108,-1116,-1114,-1105,-1100,-1108,-1128,-1146,
+-1155,-1155,-1155,-1163,-1174,-1181,-1183,-1184,-1193,-1208,-1223,-1224,-1210,-1186,-1163,-1150,-1147,-1149,-1152,-1155,-1157,
+-1157,-1151,-1140,-1129,-1124,-1126,-1131,-1135,-1136,-1134,-1132,-1130,-1128,-1124,-1119,-1112,-1103,-1095,-1091,-1089,-1085,
+-1074,-1056,-1037,-1022,-1015,-1014,-1015,-1018,-1019,-1016,-1008,-995,-980,-965,-951,-936,-924,-917,-913,-909,-903,
+-896,-891,-887,-881,-870,-858,-849,-843,-837,-827,-815,-804,-796,-787,-774,-759,-748,-745,-744,-738,-723,
+-706,-694,-689,-684,-673,-659,-647,-638,-632,-625,-618,-610,-603,-594,-585,-580,-580,-580,-576,-565,-553,
+-544,-540,-535,-524,-509,-494,-483,-476,-469,-459,-446,-431,-416,-400,-384,-368,-354,-343,-333,-324,-312,
+-298,-285,-273,-262,-249,-236,-226,-223,-223,-222,-216,-205,-194,-182,-170,-158,-146,-136,-127,-115,-98,
+-79,-59,-39,-21,-6,7,24,47,77,107,135,162,192,225,256,281,302,329,367,412,455,
+487,513,545,594,659,722,759,760,744,751,808,908,1005,1052,1040,995,959,955,978,1015,1056,
+1097,1141,1189,1242,1297,1347,1381,1402,1414,1418,1398,1331,1209,1053,911,844,909,1139,1507,1915,2233,
+2389,2432,2500,2691,2967,3179,3195,3017,2763,2559,2442,2372,2303,2232,2183,2169,2178,2200,2235,2284,2322,
+2323,2282,2229,2194,2184,2180,2166,2147,2133,2120,2093,2045,1988,1940,1905,1877,1846,1814,1787,1765,1745,
+1726,1713,1710,1711,1710,1706,1701,1698,1690,1675,1658,1649,1651,1655,1652,1642,1630,1620,1607,1584,1556,
+1530,1509,1489,1462,1426,1382,1334,1278,1213,1136,1049,960,883,838,830,843,841,796,705,592,485,
+392,305,214,118,28,-48,-112,-170,-227,-285,-341,-391,-430,-459,-485,-510,-533,-550,-560,-568,-578,
+-589,-598,-607,-622,-645,-672,-693,-703,-709,-719,-737,-753,-761,-760,-754,-749,-744,-737,-730,-728,-733,
+-742,-749,-745,-731,-709,-682,-653,-624,-595,-570,-550,-536,-523,-503,-471,-430,-388,-352,-324,-298,-267,
+-227,-180,-130,-83,-45,-12,23,71,132,198,251,282,289,285,282,291,316,357,412,474,532,
+576,605,623,639,659,684,713,747,784,821,855,882,904,925,949,978,1009,1040,1067,1090,1109,
+1129,1153,1182,1214,1247,1277,1302,1323,1344,1367,1395,1423,1447,1466,1484,1509,1539,1568,1587,1600,1616,
+1641,1670,1693,1707,1717,1728,1741,1749,1752,1753,1757,1763,1768,1775,1786,1802,1812,1811,1801,1791,1787,
+1784,1773,1754,1733,1716,1703,1689,1676,1665,1658,1651,1642,1632,1624,1617,1610,1602,1598,1601,1606,1608,
+1607,1608,1612,1615,1613,1610,1616,1629,1640,1643,1645,1659,1682,1693,1677,1647,1642,1691,1784,1867,1887,
+1826,1720,1633,1620,1690,1805,1905,1947,1928,1877,1826,1797,1800,1837,1846,1903,1947,1960,1941,1914,1905,
+1917,1938,1951,1959,1973,1999,2025,2038,2037,2037,2045,2055,2059,2057,2061,2075,2095,2110,2117,2125,2141,
+2161,2181,2198,2216,2238,2262,2288,2314,2339,2359,2370,2379,2396,2421,2447,2464,2473,2486,2508,2534,2553,
+2562,2568,2576,2583,2583,2577,2572,2573,2575,2573,2565,2560,2567,2588,2615,2641,2664,2689,2726,2785,2869,
+2962,3038,3079,3090,3092,3107,3140,3180,3212,3232,3239,3236,3225,3211,3199,3189,3173,3144,3104,3059,3020,
+2994,2982,2980,2981,2974,2953,2917,2874,2830,2786,2747,2724,2728,2764,2821,2875,2905,2903,2873,2828,2776,
+2726,2682,2644,2617,2600,2589,2580,2572,2569,2576,2591,2609,2623,2636,2658,2695,2743,2796,2851,2912,2971,
+3013,3025,3006,2975,2949,2931,2913,2884,2841,2786,2718,2636,2550,2472,2412,2371,2346,2335,2337,2349,2361,
+2367,2364,2357,2352,2352,2363,2387,2417,2442,2459,2473,2495,2520,2536,2541,2560,2624,2738,2869,2977,3047,
+3100,3162,3233,3293,3325,3329,3317,3293,3253,3202,3150,3106,3065,3019,2967,2921,2892,2878,2867,2853,2840,
+2836,2840,2846,2848,2847,2845,2842,2831,2809,2782,2762,2758,2769,2782,2789,2794,2806,2833,2862,2876,2870,
+2858,2860,2876,2884,2864,2825,2792,2779,2766,2723,2642,2550,2481,2446,2427,2401,2361,2315,2271,2232,2195,
+2161,2136,2118,2105,2094,2086,2081,2075,2065,2053,2047,2047,2052,2056,2057,2055,2046,2028,2003,1979,1960,
+1944,1923,1896,1868,1845,1824,1800,1770,1739,1712,1686,1657,1624,1592,1565,1542,1518,1493,1468,1445,1419,
+1387,1353,1322,1296,1271,1241,1206,1171,1143,1122,1100,1074,1043,1009,975,944,916,890,868,849,832,
+814,792,764,734,704,680,659,639,616,590,562,531,497,458,414,370,327,287,248,207,160,
+107,50,-3,-50,-91,-131,-178,-232,-293,-352,-404,-448,-485,-518,-552,-589,-630,-673,-715,-756,-793,
+-828,-859,-891,-926,-967,-1017,-1072,-1131,-1191,-1250,-1306,-1357,-1405,-1452,-1499,-1547,-1593,-1638,-1683,-1730,-1781,
+-1830,-1877,-1920,-1964,-2010,-2059,-2109,-2155,-2195,-2231,-2267,-2309,-2359,-2412,-2463,-2509,-2554,-2602,-2655,-2709,-2757,
+-2798,-2836,-2877,-2919,-2958,-2993,-3027,-3062,-3097,-3127,-3148,-3166,-3188,-3214,-3243,-3271,-3298,-3329,-3367,-3414,-3473,
+-3541,-3611,-3671,-3708,-3723,-3730,-3746,-3778,-3822,-3873,-3926,-3981,-4034,-4076,-4102,-4112,-4114,-4111,-4105,-4097,-4086,
+-4076,-4065,-4052,-4035,-4016,-4000,-3990,-3988,-3984,-3964,-3917,-3844,-3763,-3693,-3647,-3623,-3617,-3625,-3644,-3669,-3693,
+-3716,-3744,-3780,-3814,-3827,-3807,-3755,-3679,-3585,-3477,-3372,-3298,-3272,-3278,-3269,-3210,-3108,-3007,-2943,-2919,-2909,
+-2892,-2874,-2870,-2891,-2929,-2974,-3016,-3052,-3078,-3091,-3091,-3082,-3074,-3070,-3070,-3076,-3083,-3087,-3079,-3060,-3035,
+-3012,-2990,-2961,-2921,-2875,-2836,-2813,-2806,-2808,-2814,-2823,-2838,-2861,-2888,-2915,-2936,-2951,-2960,-2960,-2951,-2933,
+-2916,-2908,-2909,-2906,-2883,-2828,-2749,-2660,-2574,-2493,-2419,-2357,-2309,-2268,-2222,-2156,-2068,-1963,-1846,-1723,-1599,
+-1482,-1379,-1292,-1215,-1145,-1075,-1004,-926,-836,-735,-632,-536,-456,-395,-349,-306,-251,-176,-91,-17,25,
+40,52,84,142,209,260,285,289,286,289,304,333,374,421,470,521,575,633,691,744,793,
+841,889,936,981,1024,1070,1124,1186,1247,1301,1345,1387,1438,1504,1582,1660,1732,1798,1863,1928,1990,
+2052,2121,2204,2284,2335,2335,2296,2244,2196,2138,2039,1888,1710,1554,1455,1422,1444,1497,1558,1606,1632,
+1644,1656,1677,1699,1713,1724,1743,1774,1807,1830,1845,1862,1884,1901,1904,1901,1907,1926,1938,1931,1922,
+1948,2026,2135,2229,2283,2308,2328,2357,2385,2410,2440,2487,2548,2603,2635,2645,2645,2648,2656,2667,2676,
+2678,2671,2661,2666,2695,2738,2772,2787,2799,2836,2907,2989,3051,3087,3116,3154,3195,3219,3216,3202,3202,
+3221,3252,3286,3329,3394,3484,3587,3690,3783,3862,3922,3951,3948,3923,3892,3867,3851,3845,3847,3857,3869,
+3879,3886,3893,3905,3923,3941,3953,3955,3953,3956,3973,3999,4022,4028,4018,4005,3992,3957,3867,3697,3458,
+3176,2868,2539,2200,1902,1718,1698,1823,2022,2217,2369,2481,2568,2638,2689,2718,2728,2724,2708,2680,2647,
+2611,2570,2521,2466,2408,2350,2290,2221,2148,2078,2023,1985,1959,1935,1904,1858,1802,1746,1704,1677,1658,
+1634,1604,1577,1562,1550,1530,1491,1440,1389,1343,1303,1265,1234,1211,1192,1163,1118,1063,1013,975,945,
+916,882,848,815,786,759,732,705,679,655,632,614,599,587,571,549,518,481,445,413,387,
+362,333,299,262,230,206,187,168,148,128,110,94,79,64,49,35,19,-1,-28,-56,-84,
+-113,-142,-172,-200,-223,-239,-251,-263,-276,-289,-299,-304,-308,-314,-327,-346,-369,-393,-415,-435,-451,
+-463,-473,-485,-501,-519,-536,-552,-569,-593,-622,-652,-681,-708,-732,-753,-771,-785,-800,-818,-840,-862,
+-880,-893,-903,-914,-926,-940,-952,-962,-970,-978,-984,-989,-994,-999,-1008,-1020,-1033,-1042,-1046,-1047,-1048,
+-1052,-1059,-1068,-1079,-1093,-1107,-1120,-1128,-1132,-1135,-1139,-1143,-1150,-1158,-1167,-1173,-1173,-1166,-1156,-1149,-1152,
+-1159,-1162,-1155,-1138,-1122,-1117,-1120,-1122,-1116,-1103,-1094,-1096,-1106,-1112,-1110,-1104,-1104,-1108,-1111,-1106,-1097,
+-1090,-1091,-1095,-1100,-1103,-1106,-1109,-1111,-1113,-1118,-1127,-1139,-1145,-1143,-1138,-1138,-1149,-1167,-1182,-1188,-1187,
+-1188,-1197,-1213,-1225,-1224,-1209,-1188,-1172,-1166,-1167,-1169,-1168,-1166,-1164,-1160,-1152,-1144,-1138,-1137,-1138,-1137,
+-1133,-1128,-1125,-1124,-1124,-1122,-1119,-1114,-1107,-1101,-1097,-1096,-1094,-1085,-1069,-1050,-1032,-1022,-1019,-1022,-1025,
+-1027,-1023,-1014,-1001,-987,-972,-957,-942,-930,-923,-921,-918,-911,-902,-897,-894,-890,-882,-870,-859,-849,
+-838,-825,-811,-801,-794,-785,-771,-754,-743,-741,-742,-737,-722,-705,-692,-685,-677,-666,-651,-638,-629,
+-623,-617,-611,-605,-598,-589,-579,-573,-572,-574,-572,-563,-552,-543,-537,-528,-514,-496,-481,-470,-463,
+-454,-442,-428,-417,-409,-400,-387,-370,-353,-341,-335,-330,-321,-307,-291,-277,-265,-252,-240,-231,-228,
+-231,-233,-230,-220,-206,-192,-180,-170,-161,-151,-139,-124,-109,-93,-76,-57,-38,-20,-3,15,41,
+71,101,128,155,186,221,254,279,301,329,368,413,455,484,504,525,557,603,652,686,696,
+691,696,733,799,866,904,907,895,895,919,963,1015,1067,1119,1172,1224,1274,1316,1346,1365,1377,
+1384,1378,1336,1243,1110,973,883,884,1009,1267,1622,1979,2235,2348,2398,2521,2787,3120,3342,3331,3119,
+2853,2657,2549,2465,2360,2250,2178,2158,2163,2168,2176,2200,2229,2234,2200,2148,2110,2101,2109,2115,2110,
+2096,2074,2040,1995,1948,1909,1877,1848,1818,1795,1780,1769,1754,1737,1725,1720,1718,1712,1702,1694,1687,
+1674,1653,1631,1622,1625,1631,1628,1618,1607,1598,1582,1555,1522,1496,1479,1463,1435,1389,1331,1268,1202,
+1131,1055,980,916,871,854,856,856,823,740,618,488,378,290,213,134,52,-26,-96,-159,-220,
+-282,-344,-400,-447,-484,-510,-532,-553,-571,-585,-594,-600,-608,-617,-625,-634,-648,-670,-693,-709,-713,
+-713,-719,-735,-752,-763,-762,-754,-744,-734,-726,-720,-720,-726,-734,-739,-737,-727,-709,-686,-660,-633,
+-605,-578,-553,-531,-511,-489,-461,-426,-389,-355,-325,-297,-264,-224,-178,-129,-82,-41,-5,27,64,
+109,162,218,271,317,351,371,375,368,363,377,415,467,515,550,575,603,640,681,721,758,
+796,841,888,927,953,968,983,1008,1044,1084,1118,1143,1165,1188,1216,1249,1281,1311,1339,1364,1387,
+1406,1427,1450,1475,1496,1511,1525,1544,1570,1596,1614,1625,1640,1662,1689,1712,1729,1744,1760,1774,1782,
+1784,1786,1792,1799,1804,1808,1818,1834,1846,1843,1828,1811,1800,1792,1780,1761,1742,1728,1718,1708,1697,
+1689,1684,1677,1666,1653,1643,1637,1632,1625,1622,1623,1628,1630,1628,1625,1624,1623,1621,1621,1629,1643,
+1653,1654,1654,1665,1688,1705,1701,1685,1686,1726,1789,1833,1822,1756,1674,1623,1630,1691,1776,1849,1884,
+1879,1846,1810,1791,1803,1846,1845,1888,1913,1909,1886,1868,1870,1891,1917,1937,1954,1976,1999,2015,2018,
+2016,2020,2033,2045,2047,2045,2049,2065,2086,2101,2107,2114,2128,2148,2167,2184,2201,2224,2251,2280,2306,
+2329,2346,2360,2375,2395,2421,2446,2466,2481,2498,2518,2538,2553,2562,2569,2578,2583,2581,2573,2565,2560,
+2557,2552,2545,2543,2551,2570,2595,2623,2649,2674,2705,2753,2823,2906,2982,3035,3064,3082,3103,3131,3162,
+3189,3208,3214,3207,3187,3162,3139,3120,3099,3070,3036,3002,2973,2952,2941,2940,2949,2958,2952,2921,2864,
+2795,2734,2695,2690,2719,2772,2828,2868,2878,2859,2820,2775,2731,2694,2662,2635,2614,2599,2589,2580,2575,
+2578,2594,2619,2642,2656,2667,2689,2729,2783,2841,2896,2946,2990,3020,3028,3015,2995,2975,2957,2930,2891,
+2840,2779,2710,2634,2556,2489,2441,2412,2396,2390,2394,2404,2415,2419,2416,2410,2408,2412,2427,2450,2476,
+2496,2509,2522,2542,2565,2579,2587,2612,2686,2809,2946,3055,3120,3161,3204,3256,3304,3331,3339,3334,3319,
+3289,3246,3201,3160,3121,3077,3030,2990,2966,2954,2944,2933,2925,2925,2932,2939,2940,2938,2935,2931,2919,
+2897,2873,2855,2851,2860,2872,2881,2891,2908,2933,2953,2955,2935,2911,2902,2911,2920,2910,2882,2854,2838,
+2819,2773,2690,2594,2515,2471,2449,2427,2394,2352,2307,2264,2224,2189,2162,2145,2136,2131,2129,2126,2118,
+2106,2095,2092,2097,2105,2110,2108,2101,2091,2077,2058,2037,2017,1999,1979,1955,1929,1903,1880,1855,1826,
+1795,1764,1731,1698,1665,1635,1608,1584,1559,1533,1508,1482,1455,1425,1396,1370,1346,1319,1286,1249,1213,
+1184,1161,1137,1109,1077,1044,1014,987,962,938,915,894,875,855,832,803,774,749,729,711,691,
+667,640,613,583,550,512,471,430,389,347,304,259,213,162,107,53,6,-35,-77,-127,-188,
+-254,-315,-364,-400,-429,-461,-498,-540,-585,-627,-667,-705,-742,-776,-810,-846,-888,-937,-990,-1043,-1095,
+-1149,-1204,-1260,-1313,-1362,-1409,-1456,-1502,-1545,-1585,-1627,-1673,-1723,-1771,-1816,-1860,-1907,-1959,-2013,-2066,-2114,
+-2156,-2191,-2223,-2259,-2302,-2352,-2405,-2454,-2501,-2549,-2602,-2657,-2706,-2748,-2787,-2825,-2864,-2901,-2936,-2972,-3010,
+-3046,-3075,-3097,-3115,-3138,-3167,-3201,-3235,-3268,-3298,-3324,-3350,-3388,-3449,-3532,-3620,-3690,-3732,-3750,-3760,-3772,
+-3794,-3829,-3879,-3942,-4009,-4064,-4100,-4117,-4123,-4124,-4121,-4112,-4099,-4085,-4072,-4059,-4047,-4033,-4018,-4003,-3994,
+-3990,-3981,-3953,-3894,-3812,-3728,-3666,-3635,-3630,-3641,-3659,-3680,-3702,-3728,-3762,-3803,-3841,-3860,-3849,-3804,-3732,
+-3636,-3526,-3420,-3343,-3310,-3307,-3297,-3252,-3179,-3108,-3067,-3054,-3049,-3036,-3017,-3008,-3019,-3044,-3075,-3105,-3131,
+-3151,-3164,-3170,-3173,-3178,-3186,-3196,-3206,-3211,-3204,-3181,-3145,-3110,-3083,-3064,-3046,-3021,-2993,-2973,-2969,-2980,
+-2998,-3014,-3026,-3036,-3046,-3061,-3077,-3091,-3101,-3103,-3097,-3084,-3063,-3038,-3015,-2998,-2985,-2967,-2933,-2874,-2790,
+-2691,-2587,-2495,-2423,-2374,-2336,-2294,-2237,-2163,-2075,-1973,-1858,-1733,-1607,-1490,-1384,-1289,-1202,-1121,-1047,-972,
+-887,-789,-684,-586,-509,-457,-420,-380,-319,-233,-140,-67,-34,-35,-40,-16,43,121,185,219,225,
+222,226,248,285,331,379,428,479,533,588,641,690,740,791,843,892,935,974,1015,1064,1120,
+1177,1231,1280,1326,1376,1433,1501,1576,1654,1733,1807,1872,1928,1982,2047,2122,2190,2227,2223,2191,2152,
+2103,2019,1874,1681,1492,1364,1321,1345,1400,1456,1503,1540,1566,1583,1596,1610,1625,1640,1659,1686,1720,
+1753,1780,1800,1818,1833,1839,1837,1838,1851,1869,1872,1855,1840,1864,1939,2042,2131,2187,2220,2248,2277,
+2301,2322,2354,2407,2471,2525,2557,2569,2575,2583,2594,2607,2622,2634,2635,2623,2614,2626,2661,2700,2728,
+2746,2774,2825,2888,2943,2986,3028,3082,3141,3185,3202,3198,3191,3189,3193,3206,3235,3288,3365,3458,3557,
+3657,3752,3831,3886,3916,3927,3925,3913,3890,3862,3839,3830,3831,3835,3838,3843,3852,3863,3872,3876,3881,
+3893,3913,3935,3952,3959,3957,3952,3946,3924,3857,3718,3500,3228,2933,2632,2329,2040,1809,1697,1732,1885,
+2085,2264,2395,2487,2561,2622,2668,2693,2698,2689,2668,2637,2600,2559,2515,2467,2413,2357,2302,2246,2189,
+2127,2060,1991,1931,1891,1876,1876,1868,1830,1766,1697,1649,1626,1614,1597,1572,1547,1526,1502,1468,1423,
+1375,1330,1289,1252,1222,1199,1181,1155,1115,1064,1014,973,942,913,880,845,812,781,751,722,692,
+664,638,613,591,572,557,546,533,511,478,438,401,372,349,324,290,252,219,194,175,156,
+134,112,93,77,62,47,32,17,0,-20,-45,-72,-99,-127,-156,-187,-216,-238,-253,-266,-278,
+-293,-307,-317,-321,-322,-327,-340,-360,-384,-410,-435,-459,-478,-492,-501,-509,-521,-538,-558,-578,-597,
+-617,-640,-664,-688,-712,-736,-757,-775,-790,-803,-818,-835,-853,-868,-880,-891,-903,-918,-933,-947,-958,
+-966,-973,-979,-984,-988,-994,-1002,-1012,-1020,-1027,-1031,-1035,-1041,-1048,-1055,-1063,-1073,-1087,-1102,-1114,-1121,
+-1123,-1123,-1124,-1127,-1134,-1143,-1151,-1156,-1151,-1135,-1114,-1100,-1100,-1111,-1120,-1118,-1105,-1093,-1093,-1104,-1115,
+-1113,-1102,-1092,-1093,-1102,-1109,-1109,-1106,-1106,-1110,-1111,-1104,-1095,-1091,-1096,-1105,-1108,-1104,-1099,-1098,-1103,
+-1112,-1120,-1126,-1130,-1130,-1127,-1125,-1129,-1143,-1166,-1188,-1198,-1194,-1180,-1171,-1176,-1190,-1202,-1204,-1196,-1186,
+-1181,-1181,-1178,-1170,-1161,-1157,-1160,-1163,-1164,-1162,-1157,-1151,-1144,-1137,-1130,-1127,-1125,-1124,-1120,-1115,-1110,
+-1106,-1103,-1102,-1102,-1100,-1094,-1081,-1063,-1045,-1032,-1027,-1027,-1030,-1031,-1026,-1016,-1003,-991,-979,-967,-955,
+-944,-938,-935,-932,-925,-917,-911,-908,-905,-898,-886,-872,-857,-843,-828,-815,-806,-799,-789,-774,-757,
+-743,-738,-736,-731,-719,-704,-691,-680,-669,-654,-638,-626,-620,-616,-612,-608,-604,-598,-589,-579,-571,
+-567,-567,-564,-558,-549,-541,-532,-520,-503,-485,-471,-461,-453,-441,-426,-412,-403,-399,-394,-383,-365,
+-345,-332,-327,-326,-322,-311,-295,-280,-266,-254,-243,-234,-229,-230,-234,-235,-230,-220,-207,-196,-188,
+-180,-169,-153,-136,-118,-102,-85,-65,-45,-26,-9,9,34,65,94,121,148,179,216,250,279,
+304,333,371,413,451,481,501,518,539,569,606,642,667,681,691,712,747,785,815,833,853,
+885,933,989,1044,1097,1148,1198,1244,1282,1310,1328,1339,1346,1346,1323,1258,1147,1016,913,884,954,
+1132,1405,1727,2022,2213,2295,2357,2523,2832,3177,3382,3345,3122,2870,2702,2613,2526,2399,2262,2173,2146,
+2150,2150,2144,2149,2162,2160,2129,2081,2049,2047,2064,2077,2074,2054,2021,1979,1936,1899,1871,1846,1820,
+1797,1782,1777,1770,1756,1739,1730,1729,1727,1716,1699,1683,1672,1658,1638,1619,1610,1611,1612,1605,1594,
+1585,1576,1555,1518,1477,1448,1433,1418,1386,1332,1266,1198,1132,1064,997,938,899,883,883,882,855,
+786,673,536,406,301,219,146,70,-6,-79,-148,-214,-282,-347,-405,-454,-494,-525,-548,-565,-578,
+-592,-604,-614,-621,-625,-630,-636,-647,-664,-685,-706,-718,-721,-721,-726,-738,-753,-763,-763,-755,-743,
+-732,-722,-718,-719,-724,-728,-729,-725,-718,-706,-689,-668,-644,-618,-590,-562,-533,-507,-482,-457,-427,
+-394,-360,-327,-292,-255,-216,-176,-136,-95,-53,-12,26,59,91,128,174,236,312,391,455,488,
+488,473,466,479,506,528,538,548,575,623,678,725,758,791,838,899,957,995,1013,1024,1045,
+1080,1123,1162,1193,1220,1252,1287,1322,1351,1376,1400,1427,1454,1476,1494,1512,1530,1548,1560,1572,1587,
+1608,1631,1648,1660,1672,1689,1711,1731,1750,1769,1787,1801,1805,1804,1807,1818,1831,1840,1845,1853,1865,
+1873,1867,1847,1824,1805,1792,1777,1760,1746,1738,1734,1728,1720,1713,1708,1701,1688,1673,1662,1658,1655,
+1650,1646,1645,1647,1648,1644,1639,1636,1634,1633,1633,1638,1646,1651,1650,1651,1667,1700,1737,1759,1768,
+1776,1794,1807,1794,1748,1691,1655,1656,1684,1720,1752,1780,1806,1822,1821,1807,1797,1809,1845,1820,1854,
+1872,1865,1848,1841,1854,1882,1912,1936,1955,1973,1988,1995,1995,1996,2005,2020,2031,2032,2032,2039,2056,
+2076,2089,2096,2105,2122,2143,2163,2179,2196,2219,2248,2276,2300,2320,2338,2358,2380,2402,2423,2445,2467,
+2488,2509,2526,2539,2548,2556,2565,2574,2580,2580,2575,2567,2557,2546,2539,2537,2543,2555,2571,2593,2623,
+2659,2695,2730,2767,2815,2874,2937,2993,3037,3071,3100,3126,3149,3168,3182,3186,3176,3153,3124,3095,3070,
+3046,3022,3000,2983,2969,2954,2937,2927,2930,2939,2936,2899,2825,2734,2658,2623,2638,2688,2751,2802,2826,
+2823,2799,2766,2734,2708,2687,2667,2646,2626,2609,2598,2593,2593,2601,2620,2646,2669,2683,2695,2716,2756,
+2811,2867,2916,2954,2983,3001,3006,3001,2991,2981,2965,2938,2896,2843,2782,2714,2641,2569,2510,2471,2451,
+2444,2444,2449,2457,2464,2466,2464,2462,2464,2472,2487,2508,2527,2542,2551,2565,2587,2613,2631,2644,2675,
+2750,2869,3003,3110,3174,3207,3236,3269,3301,3322,3329,3329,3321,3302,3272,3236,3201,3167,3131,3095,3065,
+3045,3033,3024,3017,3016,3021,3028,3030,3024,3017,3011,3006,2998,2983,2967,2953,2947,2949,2957,2968,2982,
+2998,3012,3017,3006,2981,2956,2949,2961,2976,2971,2941,2899,2862,2825,2774,2698,2610,2536,2490,2468,2451,
+2423,2383,2338,2293,2252,2219,2196,2182,2176,2174,2172,2169,2163,2154,2147,2147,2153,2160,2161,2154,2144,
+2136,2127,2114,2097,2076,2055,2034,2012,1986,1959,1932,1905,1877,1846,1811,1775,1741,1710,1683,1657,1630,
+1602,1575,1548,1521,1493,1465,1439,1416,1393,1365,1330,1294,1259,1229,1202,1174,1144,1114,1084,1057,1032,
+1009,985,962,939,916,893,868,841,816,795,779,761,740,714,688,662,635,603,567,530,491,
+450,404,357,309,264,216,166,113,62,15,-33,-89,-151,-214,-268,-310,-342,-373,-408,-451,-497,
+-544,-586,-623,-658,-690,-722,-757,-799,-850,-906,-961,-1011,-1057,-1105,-1157,-1211,-1263,-1312,-1358,-1405,-1451,
+-1492,-1530,-1571,-1617,-1666,-1712,-1754,-1796,-1843,-1896,-1951,-2004,-2054,-2099,-2139,-2174,-2207,-2245,-2291,-2343,-2395,
+-2447,-2499,-2554,-2608,-2657,-2698,-2735,-2775,-2816,-2856,-2893,-2930,-2969,-3006,-3037,-3059,-3077,-3098,-3126,-3160,-3197,
+-3235,-3269,-3292,-3305,-3322,-3360,-3426,-3513,-3602,-3675,-3727,-3760,-3779,-3794,-3812,-3844,-3894,-3953,-4010,-4055,-4084,
+-4102,-4109,-4109,-4103,-4093,-4081,-4068,-4055,-4043,-4031,-4017,-4002,-3991,-3989,-3993,-3985,-3948,-3879,-3798,-3733,-3700,
+-3697,-3709,-3723,-3735,-3749,-3772,-3809,-3855,-3899,-3924,-3918,-3878,-3808,-3714,-3606,-3501,-3419,-3374,-3356,-3338,-3301,
+-3247,-3198,-3172,-3165,-3161,-3146,-3126,-3113,-3117,-3138,-3169,-3203,-3234,-3260,-3280,-3296,-3311,-3323,-3332,-3338,-3339,
+-3336,-3323,-3296,-3259,-3220,-3192,-3175,-3164,-3153,-3143,-3140,-3149,-3165,-3181,-3192,-3196,-3195,-3195,-3197,-3203,-3208,
+-3208,-3201,-3189,-3172,-3152,-3127,-3099,-3073,-3052,-3036,-3015,-2975,-2908,-2815,-2709,-2607,-2524,-2461,-2409,-2355,-2295,
+-2229,-2158,-2078,-1985,-1876,-1759,-1644,-1533,-1427,-1323,-1226,-1135,-1048,-955,-854,-749,-653,-579,-525,-479,-426,
+-358,-278,-201,-146,-119,-112,-102,-69,-8,64,124,159,169,170,178,204,245,294,344,392,441,
+490,540,590,639,691,747,801,850,890,927,965,1010,1060,1114,1170,1226,1277,1323,1368,1421,1489,
+1572,1660,1742,1810,1867,1925,1993,2064,2119,2140,2126,2092,2051,1987,1872,1693,1484,1310,1224,1232,1291,
+1354,1397,1427,1457,1489,1517,1536,1548,1558,1572,1595,1624,1658,1688,1711,1729,1745,1758,1768,1774,1784,
+1799,1810,1804,1783,1772,1799,1870,1960,2039,2093,2130,2161,2188,2208,2229,2267,2325,2392,2444,2475,2492,
+2507,2523,2537,2551,2569,2592,2609,2610,2599,2596,2611,2640,2670,2695,2723,2762,2807,2847,2881,2919,2973,
+3041,3108,3159,3188,3197,3191,3177,3165,3170,3198,3249,3316,3396,3489,3588,3681,3759,3820,3868,3904,3921,
+3914,3889,3861,3839,3826,3815,3806,3802,3803,3804,3801,3799,3809,3835,3868,3890,3894,3884,3876,3876,3868,
+3823,3715,3532,3292,3020,2738,2454,2173,1923,1750,1698,1776,1943,2132,2291,2404,2484,2548,2600,2636,2655,
+2657,2645,2624,2594,2556,2511,2460,2406,2351,2299,2249,2200,2151,2099,2042,1978,1913,1867,1855,1871,1884,
+1860,1790,1701,1633,1602,1596,1588,1565,1533,1501,1473,1443,1405,1360,1315,1272,1234,1202,1176,1155,1131,
+1097,1054,1010,972,941,910,876,841,807,776,745,711,677,647,623,602,578,553,531,518,511,
+499,474,436,394,358,330,303,272,238,207,185,168,148,124,98,75,57,41,26,10,-7,
+-26,-48,-71,-95,-118,-143,-169,-197,-223,-244,-259,-273,-287,-302,-315,-325,-332,-337,-345,-359,-378,
+-400,-422,-447,-474,-499,-518,-530,-537,-547,-562,-582,-602,-621,-638,-657,-678,-701,-724,-746,-766,-783,
+-797,-809,-820,-833,-846,-858,-869,-881,-893,-907,-921,-935,-947,-957,-965,-970,-974,-977,-983,-991,-999,
+-1006,-1012,-1017,-1024,-1032,-1041,-1048,-1056,-1065,-1078,-1092,-1103,-1110,-1112,-1112,-1114,-1116,-1121,-1129,-1138,-1143,
+-1138,-1120,-1095,-1074,-1069,-1079,-1092,-1095,-1088,-1079,-1081,-1094,-1107,-1110,-1103,-1096,-1096,-1104,-1111,-1113,-1111,
+-1112,-1114,-1111,-1103,-1095,-1097,-1106,-1114,-1112,-1100,-1089,-1086,-1094,-1105,-1112,-1114,-1115,-1118,-1122,-1128,-1135,
+-1148,-1170,-1196,-1214,-1213,-1194,-1169,-1155,-1159,-1173,-1184,-1186,-1185,-1186,-1186,-1179,-1165,-1151,-1147,-1157,-1173,
+-1183,-1183,-1175,-1165,-1157,-1151,-1147,-1145,-1142,-1136,-1127,-1116,-1107,-1103,-1102,-1103,-1104,-1103,-1098,-1089,-1076,
+-1061,-1049,-1040,-1035,-1033,-1031,-1025,-1015,-1003,-992,-984,-976,-968,-959,-953,-949,-947,-943,-936,-930,-925,
+-922,-916,-906,-893,-878,-863,-848,-834,-823,-813,-801,-785,-766,-749,-736,-728,-720,-710,-700,-690,-678,
+-663,-646,-631,-622,-619,-618,-616,-612,-609,-605,-598,-589,-580,-572,-567,-562,-556,-548,-538,-526,-510,
+-494,-478,-466,-457,-448,-434,-417,-402,-391,-385,-378,-367,-351,-332,-318,-312,-312,-312,-307,-296,-283,
+-272,-263,-254,-243,-233,-228,-229,-234,-235,-230,-220,-210,-202,-194,-182,-166,-147,-128,-109,-89,-66,
+-44,-26,-10,7,32,62,92,119,147,180,217,252,283,312,344,379,415,448,477,503,527,
+549,575,607,645,682,710,730,748,770,796,823,850,884,928,979,1030,1077,1121,1166,1209,1245,
+1271,1289,1301,1310,1313,1300,1255,1168,1048,935,878,914,1050,1270,1544,1824,2052,2187,2246,2319,2502,
+2805,3113,3269,3204,2992,2780,2661,2610,2545,2424,2280,2176,2136,2133,2131,2123,2119,2119,2105,2072,2031,
+2006,2007,2022,2029,2018,1990,1951,1910,1874,1851,1837,1824,1806,1789,1778,1773,1765,1750,1736,1732,1738,
+1738,1723,1699,1677,1662,1650,1634,1617,1605,1599,1591,1578,1566,1557,1545,1515,1467,1417,1385,1371,1356,
+1321,1264,1198,1137,1078,1017,958,913,894,895,900,884,828,731,604,472,354,258,177,99,20,
+-57,-129,-197,-267,-337,-400,-451,-489,-521,-548,-568,-580,-587,-594,-605,-616,-624,-627,-628,-632,-645,
+-664,-686,-704,-715,-721,-725,-733,-743,-754,-762,-764,-760,-750,-738,-726,-720,-720,-723,-724,-721,-717,
+-712,-704,-692,-673,-651,-627,-601,-572,-541,-511,-485,-460,-432,-400,-365,-329,-292,-254,-216,-181,-148,
+-111,-70,-24,19,56,83,108,141,194,273,371,467,537,573,584,590,601,609,603,583,572,
+592,642,703,749,774,798,840,906,977,1029,1056,1068,1085,1117,1157,1196,1230,1263,1300,1341,1377,
+1403,1422,1444,1473,1505,1532,1551,1566,1580,1595,1607,1618,1631,1650,1672,1691,1706,1719,1732,1746,1760,
+1774,1792,1809,1819,1818,1813,1815,1828,1846,1859,1865,1869,1875,1878,1871,1854,1834,1818,1804,1789,1773,
+1763,1758,1755,1748,1739,1731,1726,1719,1705,1688,1677,1673,1672,1669,1666,1665,1667,1666,1660,1653,1650,
+1652,1653,1652,1650,1648,1646,1643,1648,1671,1712,1759,1793,1810,1816,1814,1796,1755,1702,1666,1669,1703,
+1736,1743,1731,1727,1748,1782,1803,1800,1789,1793,1820,1776,1807,1827,1829,1825,1831,1851,1879,1905,1925,
+1940,1952,1961,1967,1971,1979,1992,2005,2013,2016,2020,2031,2049,2065,2077,2087,2101,2122,2146,2166,2181,
+2198,2221,2249,2277,2298,2315,2335,2359,2384,2407,2426,2445,2468,2495,2518,2533,2540,2545,2553,2563,2572,
+2577,2578,2576,2569,2556,2541,2531,2535,2550,2567,2582,2600,2632,2678,2729,2772,2804,2832,2867,2911,2960,
+3007,3047,3080,3104,3121,3135,3147,3153,3150,3133,3109,3081,3055,3032,3013,2999,2988,2973,2947,2912,2882,
+2868,2866,2856,2817,2745,2661,2601,2589,2624,2685,2741,2775,2781,2770,2751,2732,2718,2709,2701,2689,2671,
+2650,2633,2624,2621,2624,2632,2647,2668,2689,2705,2720,2743,2781,2829,2877,2916,2945,2965,2979,2983,2981,
+2974,2965,2952,2928,2891,2844,2787,2722,2652,2585,2532,2501,2488,2487,2492,2501,2509,2515,2515,2513,2514,
+2520,2530,2544,2560,2573,2583,2591,2606,2631,2662,2688,2710,2743,2809,2912,3029,3127,3191,3226,3251,3277,
+3299,3313,3317,3316,3312,3303,3287,3264,3239,3212,3187,3163,3144,3127,3111,3099,3095,3101,3111,3116,3111,
+3100,3089,3083,3079,3074,3069,3063,3056,3048,3043,3046,3059,3074,3084,3083,3072,3054,3032,3016,3013,3024,
+3035,3025,2985,2924,2863,2810,2757,2694,2622,2557,2513,2491,2473,2446,2405,2359,2315,2279,2253,2236,2226,
+2221,2217,2213,2209,2206,2205,2205,2208,2212,2213,2209,2199,2189,2183,2179,2172,2156,2133,2108,2086,2064,
+2040,2011,1980,1950,1922,1891,1857,1821,1788,1760,1735,1708,1678,1648,1619,1590,1561,1531,1504,1480,1458,
+1433,1403,1369,1336,1304,1274,1243,1212,1182,1154,1127,1100,1075,1051,1028,1004,981,957,933,908,884,
+864,848,832,814,789,763,738,715,690,660,625,588,550,509,462,412,363,317,273,227,176,
+122,65,6,-54,-113,-164,-206,-240,-273,-311,-353,-400,-449,-497,-541,-578,-610,-638,-669,-706,-754,
+-810,-869,-924,-970,-1011,-1055,-1104,-1157,-1208,-1255,-1301,-1348,-1394,-1436,-1475,-1517,-1564,-1613,-1659,-1698,-1737,
+-1782,-1833,-1885,-1934,-1982,-2030,-2075,-2116,-2153,-2192,-2238,-2289,-2341,-2393,-2446,-2502,-2555,-2602,-2642,-2681,-2725,
+-2772,-2817,-2856,-2891,-2926,-2962,-2994,-3019,-3040,-3063,-3089,-3120,-3154,-3191,-3228,-3257,-3275,-3286,-3304,-3344,-3409,
+-3490,-3575,-3651,-3711,-3753,-3777,-3789,-3803,-3829,-3869,-3921,-3974,-4017,-4043,-4052,-4049,-4045,-4046,-4050,-4049,-4042,
+-4031,-4020,-4009,-3999,-3990,-3990,-3998,-4003,-3988,-3946,-3889,-3839,-3813,-3812,-3822,-3832,-3839,-3847,-3864,-3896,-3940,
+-3982,-4007,-4002,-3963,-3896,-3811,-3715,-3621,-3539,-3480,-3440,-3404,-3360,-3310,-3266,-3239,-3227,-3217,-3203,-3185,-3178,
+-3189,-3222,-3269,-3320,-3366,-3402,-3428,-3448,-3464,-3475,-3475,-3467,-3454,-3443,-3431,-3414,-3388,-3359,-3334,-3316,-3303,
+-3294,-3289,-3290,-3299,-3310,-3317,-3319,-3317,-3314,-3311,-3308,-3305,-3301,-3292,-3276,-3255,-3231,-3206,-3181,-3153,-3124,
+-3098,-3078,-3061,-3037,-2993,-2926,-2838,-2744,-2655,-2577,-2504,-2431,-2357,-2286,-2220,-2155,-2082,-1997,-1902,-1803,-1703,
+-1601,-1495,-1385,-1275,-1165,-1052,-939,-831,-739,-666,-603,-537,-462,-383,-314,-264,-231,-206,-179,-143,-96,
+-43,11,58,92,113,125,142,171,213,264,315,362,407,453,500,550,603,659,716,769,815,
+853,890,928,968,1011,1059,1115,1175,1231,1276,1313,1355,1418,1502,1596,1685,1758,1820,1883,1952,2017,
+2061,2068,2042,1997,1937,1845,1701,1507,1308,1169,1127,1168,1241,1298,1328,1348,1376,1412,1445,1468,1484,
+1499,1520,1545,1574,1603,1627,1644,1657,1669,1683,1696,1708,1718,1728,1732,1726,1717,1719,1749,1808,1878,
+1941,1991,2032,2068,2096,2117,2140,2182,2243,2309,2359,2390,2412,2436,2460,2479,2495,2517,2552,2589,2612,
+2612,2601,2594,2600,2617,2642,2673,2710,2748,2777,2798,2821,2861,2922,2998,3077,3145,3187,3198,3182,3156,
+3139,3144,3167,3207,3263,3338,3430,3526,3616,3696,3767,3827,3869,3886,3883,3870,3855,3837,3814,3792,3775,
+3765,3755,3741,3732,3743,3776,3812,3830,3821,3798,3783,3775,3750,3673,3528,3325,3091,2844,2586,2316,2049,
+1828,1705,1707,1820,1991,2163,2300,2400,2472,2528,2571,2597,2608,2605,2593,2572,2544,2506,2459,2402,2343,
+2289,2241,2196,2149,2102,2057,2013,1963,1906,1858,1842,1861,1887,1878,1816,1719,1632,1584,1570,1564,1543,
+1510,1475,1446,1417,1382,1338,1291,1248,1211,1181,1157,1134,1108,1074,1035,997,964,933,900,863,827,
+797,770,739,703,664,632,610,593,572,542,513,493,485,479,461,427,384,343,308,278,249,
+220,196,179,164,145,119,88,60,37,19,3,-12,-31,-52,-75,-98,-119,-139,-159,-181,-204,
+-227,-247,-265,-281,-294,-306,-316,-325,-335,-347,-362,-380,-399,-417,-436,-458,-486,-516,-542,-558,-568,
+-576,-589,-606,-623,-638,-652,-669,-691,-715,-740,-761,-779,-794,-806,-815,-824,-834,-845,-856,-867,-878,
+-889,-899,-909,-921,-932,-944,-952,-958,-961,-964,-970,-978,-987,-995,-1002,-1009,-1016,-1025,-1034,-1043,-1052,
+-1063,-1075,-1086,-1096,-1103,-1107,-1109,-1111,-1112,-1113,-1118,-1127,-1136,-1139,-1130,-1112,-1093,-1084,-1089,-1100,-1106,
+-1103,-1096,-1094,-1101,-1109,-1112,-1109,-1105,-1108,-1114,-1119,-1122,-1123,-1124,-1123,-1118,-1110,-1107,-1110,-1118,-1120,
+-1110,-1093,-1080,-1080,-1090,-1102,-1109,-1110,-1111,-1117,-1128,-1137,-1144,-1151,-1165,-1190,-1216,-1229,-1222,-1200,-1179,
+-1169,-1171,-1175,-1178,-1181,-1186,-1190,-1185,-1168,-1151,-1148,-1161,-1181,-1193,-1190,-1179,-1169,-1166,-1167,-1168,-1166,
+-1161,-1153,-1142,-1129,-1116,-1108,-1104,-1103,-1103,-1100,-1095,-1089,-1082,-1074,-1065,-1054,-1044,-1036,-1030,-1023,-1014,
+-1003,-993,-986,-980,-975,-968,-961,-958,-957,-955,-950,-943,-937,-934,-931,-926,-917,-905,-892,-878,-863,
+-846,-830,-815,-799,-781,-761,-742,-726,-714,-705,-698,-690,-679,-663,-645,-630,-621,-618,-616,-614,-611,
+-608,-605,-602,-596,-587,-578,-570,-564,-558,-550,-537,-521,-502,-486,-473,-463,-454,-442,-426,-410,-394,
+-381,-369,-359,-347,-334,-319,-306,-298,-296,-298,-298,-293,-286,-279,-274,-266,-254,-239,-228,-225,-229,
+-234,-233,-226,-216,-206,-198,-188,-172,-153,-134,-114,-93,-68,-46,-28,-12,6,32,62,92,120,
+150,183,220,256,288,321,354,388,418,444,471,502,535,566,596,629,666,703,734,758,780,
+805,835,865,895,930,970,1013,1053,1091,1130,1172,1210,1239,1255,1265,1275,1284,1281,1249,1177,1069,
+952,872,873,978,1173,1422,1680,1908,2070,2158,2208,2296,2483,2753,2998,3094,3005,2814,2650,2584,2580,
+2553,2460,2325,2208,2139,2110,2097,2090,2086,2079,2057,2021,1985,1965,1963,1966,1962,1945,1918,1885,1851,
+1826,1815,1815,1814,1804,1789,1775,1765,1754,1740,1732,1734,1744,1746,1732,1709,1690,1680,1670,1653,1631,
+1610,1592,1572,1550,1532,1519,1499,1460,1404,1350,1319,1306,1290,1253,1195,1135,1082,1032,979,926,891,
+882,890,887,849,768,657,533,417,316,229,145,60,-24,-102,-171,-237,-305,-373,-431,-473,-503,
+-530,-555,-574,-583,-584,-585,-593,-606,-616,-620,-622,-628,-642,-662,-681,-695,-704,-712,-720,-730,-741,
+-749,-756,-761,-763,-758,-747,-733,-723,-719,-719,-716,-712,-708,-706,-702,-693,-677,-656,-633,-608,-579,
+-547,-516,-488,-462,-434,-404,-372,-339,-306,-270,-233,-196,-158,-119,-77,-33,10,48,78,104,131,
+172,235,319,411,492,552,594,628,657,672,665,642,629,647,697,754,794,812,827,863,925,
+997,1055,1089,1107,1126,1155,1190,1225,1256,1289,1326,1367,1402,1427,1446,1467,1497,1532,1562,1584,1600,
+1616,1631,1645,1656,1669,1686,1708,1731,1751,1768,1781,1789,1795,1802,1815,1829,1838,1835,1826,1822,1831,
+1848,1861,1867,1868,1868,1868,1864,1857,1848,1839,1828,1813,1798,1788,1782,1776,1765,1753,1746,1743,1737,
+1723,1706,1693,1688,1686,1683,1681,1682,1685,1682,1673,1662,1661,1667,1673,1672,1665,1658,1655,1657,1666,
+1690,1726,1762,1782,1782,1771,1757,1738,1711,1684,1676,1699,1737,1758,1745,1715,1702,1722,1758,1780,1773,
+1756,1754,1776,1736,1762,1782,1792,1803,1820,1843,1866,1885,1899,1910,1919,1928,1937,1948,1962,1975,1985,
+1993,2001,2013,2028,2045,2060,2073,2088,2107,2131,2155,2174,2190,2206,2228,2255,2282,2303,2320,2337,2360,
+2386,2409,2428,2448,2472,2499,2521,2534,2539,2545,2556,2568,2574,2574,2571,2570,2565,2554,2537,2528,2535,
+2555,2576,2590,2606,2637,2687,2745,2794,2828,2851,2874,2903,2936,2971,3003,3034,3060,3082,3101,3117,3129,
+3132,3124,3105,3082,3061,3045,3030,3013,2986,2944,2889,2829,2780,2752,2740,2728,2700,2656,2614,2599,2622,
+2672,2726,2760,2768,2757,2741,2731,2726,2725,2725,2722,2716,2703,2687,2673,2666,2664,2666,2669,2676,2690,
+2708,2728,2748,2774,2807,2845,2881,2910,2933,2953,2968,2975,2974,2965,2953,2938,2917,2886,2843,2790,2728,
+2663,2603,2559,2535,2527,2530,2538,2549,2559,2566,2567,2566,2568,2575,2586,2598,2609,2619,2627,2636,2653,
+2680,2714,2748,2778,2813,2868,2949,3044,3131,3196,3238,3268,3293,3313,3323,3322,3316,3312,3310,3307,3298,
+3281,3260,3243,3231,3221,3206,3187,3172,3170,3182,3194,3196,3188,3177,3169,3163,3157,3152,3153,3160,3162,
+3154,3143,3140,3152,3169,3175,3165,3145,3126,3110,3096,3085,3078,3072,3051,3004,2934,2862,2803,2754,2704,
+2645,2587,2544,2517,2494,2462,2417,2370,2330,2302,2284,2273,2267,2263,2258,2251,2246,2246,2251,2256,2260,
+2261,2259,2254,2246,2238,2233,2230,2224,2208,2183,2156,2133,2112,2089,2061,2028,1996,1966,1936,1903,1868,
+1836,1809,1782,1753,1721,1689,1660,1630,1600,1569,1542,1519,1496,1468,1435,1402,1372,1344,1315,1284,1252,
+1224,1197,1171,1142,1113,1087,1064,1042,1020,998,976,955,936,919,904,888,867,841,814,790,770,
+747,718,682,645,608,568,522,471,421,375,332,289,239,181,115,48,-15,-67,-105,-134,-165,
+-204,-249,-298,-346,-394,-442,-486,-524,-555,-584,-618,-661,-714,-772,-829,-878,-919,-957,-1000,-1049,-1102,
+-1152,-1198,-1243,-1289,-1336,-1380,-1420,-1462,-1510,-1560,-1606,-1646,-1685,-1728,-1778,-1829,-1877,-1923,-1969,-2015,-2058,
+-2099,-2143,-2191,-2243,-2293,-2342,-2392,-2445,-2497,-2543,-2582,-2621,-2668,-2719,-2766,-2804,-2836,-2868,-2902,-2936,-2965,
+-2991,-3018,-3047,-3075,-3103,-3134,-3170,-3208,-3240,-3262,-3281,-3307,-3348,-3405,-3473,-3545,-3615,-3674,-3718,-3742,-3754,
+-3767,-3794,-3840,-3896,-3945,-3971,-3970,-3957,-3954,-3969,-3994,-4015,-4019,-4014,-4008,-4006,-4006,-4004,-4002,-4005,-4011,
+-4012,-4000,-3977,-3952,-3935,-3929,-3932,-3940,-3948,-3958,-3973,-3996,-4027,-4058,-4074,-4065,-4028,-3971,-3905,-3835,-3764,
+-3694,-3629,-3572,-3517,-3460,-3403,-3354,-3319,-3299,-3287,-3277,-3272,-3279,-3305,-3352,-3412,-3474,-3525,-3559,-3578,-3590,
+-3599,-3603,-3597,-3580,-3559,-3542,-3532,-3524,-3512,-3496,-3477,-3458,-3440,-3423,-3411,-3406,-3406,-3407,-3406,-3403,-3402,
+-3400,-3397,-3389,-3377,-3363,-3347,-3324,-3295,-3260,-3224,-3192,-3162,-3132,-3104,-3078,-3058,-3041,-3018,-2980,-2922,-2850,
+-2770,-2689,-2608,-2524,-2437,-2353,-2280,-2217,-2157,-2091,-2018,-1939,-1858,-1774,-1681,-1577,-1460,-1332,-1197,-1063,-941,
+-841,-760,-685,-602,-509,-423,-359,-324,-302,-274,-231,-178,-129,-90,-57,-20,19,56,86,113,147,
+192,244,295,339,380,422,468,520,575,631,685,733,775,815,854,893,930,966,1007,1059,1121,
+1182,1231,1269,1309,1368,1452,1552,1651,1737,1807,1869,1926,1973,1998,1992,1953,1889,1799,1674,1510,1324,
+1160,1066,1060,1116,1186,1236,1263,1284,1312,1345,1374,1396,1418,1445,1476,1505,1531,1554,1573,1588,1600,
+1610,1621,1632,1638,1640,1641,1643,1648,1656,1670,1694,1732,1778,1829,1882,1934,1980,2013,2035,2057,2096,
+2152,2213,2262,2296,2325,2356,2388,2412,2432,2459,2503,2557,2602,2620,2612,2592,2575,2572,2587,2620,2662,
+2703,2734,2751,2764,2786,2828,2893,2975,3060,3128,3161,3158,3135,3114,3108,3118,3140,3175,3231,3307,3397,
+3489,3574,3650,3715,3767,3802,3825,3840,3845,3835,3811,3781,3757,3740,3722,3699,3681,3682,3705,3735,3746,
+3731,3701,3674,3645,3589,3481,3319,3123,2916,2698,2456,2191,1933,1743,1670,1724,1866,2036,2187,2303,2389,
+2456,2505,2538,2554,2558,2552,2538,2515,2483,2443,2392,2333,2274,2224,2182,2141,2096,2049,2008,1974,1936,
+1887,1838,1814,1829,1864,1876,1832,1741,1641,1570,1536,1522,1505,1479,1450,1423,1394,1358,1313,1264,1219,
+1184,1161,1144,1125,1095,1056,1013,976,948,920,886,845,807,779,757,731,695,653,618,595,580,
+562,534,501,476,461,453,438,409,370,329,291,258,228,203,185,171,158,140,113,80,47,
+19,-2,-19,-34,-50,-70,-92,-115,-136,-155,-173,-193,-213,-234,-256,-276,-294,-307,-314,-318,-325,
+-336,-352,-372,-394,-415,-433,-452,-473,-500,-531,-559,-580,-592,-602,-613,-627,-640,-651,-662,-678,-699,
+-724,-750,-772,-789,-803,-814,-823,-832,-842,-852,-864,-875,-886,-895,-902,-908,-916,-925,-934,-942,-948,
+-952,-956,-963,-973,-983,-993,-1001,-1009,-1017,-1025,-1034,-1044,-1056,-1068,-1079,-1088,-1095,-1102,-1109,-1113,-1115,
+-1113,-1112,-1112,-1118,-1129,-1139,-1143,-1138,-1128,-1120,-1119,-1125,-1129,-1128,-1122,-1117,-1116,-1118,-1118,-1117,-1118,
+-1121,-1125,-1129,-1131,-1133,-1135,-1135,-1130,-1125,-1124,-1126,-1126,-1119,-1104,-1088,-1079,-1082,-1093,-1105,-1114,-1119,
+-1122,-1126,-1133,-1140,-1143,-1144,-1149,-1166,-1193,-1221,-1236,-1234,-1220,-1206,-1195,-1187,-1182,-1185,-1194,-1203,-1201,
+-1186,-1168,-1163,-1173,-1188,-1192,-1182,-1168,-1163,-1170,-1180,-1183,-1177,-1168,-1159,-1153,-1145,-1135,-1123,-1114,-1107,
+-1101,-1094,-1088,-1082,-1079,-1077,-1072,-1062,-1050,-1038,-1029,-1022,-1014,-1004,-994,-987,-982,-977,-971,-964,-961,
+-961,-960,-955,-947,-940,-937,-936,-934,-930,-922,-913,-901,-885,-865,-844,-827,-814,-801,-784,-763,-742,
+-726,-714,-706,-697,-684,-667,-649,-633,-620,-611,-606,-601,-597,-594,-592,-589,-585,-578,-569,-561,-556,
+-554,-548,-537,-519,-499,-482,-470,-461,-450,-435,-419,-405,-391,-377,-361,-347,-334,-324,-314,-302,-293,
+-289,-290,-292,-291,-287,-282,-278,-272,-261,-245,-230,-225,-228,-233,-234,-227,-217,-208,-200,-189,-173,
+-153,-135,-117,-98,-77,-57,-38,-19,2,30,61,89,117,147,182,219,253,286,321,358,392,
+420,442,466,498,537,575,610,644,678,709,735,758,783,814,848,881,911,943,980,1018,1054,
+1089,1128,1170,1207,1231,1240,1246,1256,1263,1249,1193,1093,972,871,839,909,1083,1326,1585,1811,1975,
+2072,2123,2176,2287,2481,2719,2905,2953,2853,2688,2567,2539,2570,2580,2521,2404,2272,2165,2095,2059,2046,
+2042,2033,2008,1971,1937,1918,1910,1903,1893,1880,1865,1845,1820,1800,1794,1801,1808,1804,1788,1770,1754,
+1742,1731,1726,1731,1740,1743,1736,1727,1724,1724,1717,1697,1667,1636,1606,1574,1540,1508,1480,1448,1401,
+1344,1296,1271,1261,1242,1199,1140,1082,1035,991,942,895,865,859,861,840,780,683,571,462,366,
+280,195,107,18,-65,-139,-203,-264,-328,-389,-440,-475,-501,-524,-548,-567,-576,-576,-576,-582,-594,
+-605,-611,-616,-626,-642,-662,-678,-688,-693,-699,-707,-718,-728,-736,-744,-752,-758,-758,-750,-738,-726,
+-717,-711,-705,-699,-695,-695,-695,-690,-678,-660,-638,-613,-584,-551,-519,-489,-461,-435,-409,-383,-357,
+-330,-298,-260,-216,-169,-122,-78,-36,1,37,71,105,139,178,227,287,353,416,470,519,569,
+618,656,674,677,682,708,754,802,835,851,866,898,951,1014,1069,1109,1136,1162,1192,1225,1255,
+1282,1309,1340,1377,1412,1440,1462,1484,1512,1544,1574,1599,1620,1640,1660,1677,1691,1704,1720,1739,1762,
+1785,1806,1821,1828,1830,1831,1839,1853,1863,1862,1851,1842,1842,1852,1864,1870,1871,1869,1868,1868,1868,
+1866,1860,1848,1832,1818,1808,1802,1793,1779,1767,1761,1760,1756,1744,1729,1718,1711,1706,1699,1695,1697,
+1701,1698,1684,1671,1668,1676,1683,1681,1673,1670,1674,1685,1699,1718,1741,1758,1757,1736,1706,1685,1678,
+1680,1686,1699,1722,1744,1748,1730,1704,1697,1715,1741,1751,1738,1719,1717,1736,1716,1732,1746,1760,1780,
+1805,1828,1847,1861,1873,1885,1895,1903,1913,1926,1940,1952,1962,1973,1988,2008,2028,2046,2062,2080,2100,
+2123,2146,2168,2188,2205,2222,2242,2268,2295,2318,2335,2349,2366,2388,2411,2433,2454,2476,2500,2519,2531,
+2537,2545,2558,2569,2573,2568,2561,2558,2557,2551,2542,2537,2545,2564,2585,2600,2616,2643,2685,2735,2780,
+2816,2845,2872,2896,2914,2929,2947,2975,3012,3049,3081,3104,3117,3119,3112,3096,3080,3070,3065,3054,3025,
+2969,2890,2804,2730,2683,2660,2652,2644,2631,2621,2625,2652,2698,2745,2778,2785,2772,2753,2740,2738,2741,
+2745,2746,2747,2746,2743,2735,2725,2717,2712,2709,2706,2707,2715,2731,2752,2777,2806,2838,2869,2895,2915,
+2934,2953,2972,2984,2986,2979,2967,2951,2928,2895,2850,2794,2734,2675,2626,2594,2577,2572,2574,2581,2592,
+2605,2614,2619,2621,2625,2633,2645,2655,2664,2671,2679,2690,2708,2736,2771,2810,2847,2885,2933,2998,3076,
+3154,3218,3264,3297,3323,3343,3352,3349,3340,3335,3340,3348,3347,3333,3312,3298,3295,3295,3285,3266,3252,
+3253,3266,3277,3275,3266,3260,3259,3255,3243,3233,3238,3256,3269,3261,3239,3224,3231,3249,3258,3249,3231,
+3215,3200,3176,3140,3103,3074,3046,3002,2939,2868,2808,2762,2719,2669,2615,2570,2537,2506,2467,2420,2375,
+2342,2322,2310,2304,2301,2301,2298,2292,2285,2284,2289,2295,2299,2299,2298,2296,2294,2288,2281,2274,2265,
+2249,2225,2198,2174,2155,2134,2107,2075,2043,2012,1982,1950,1915,1881,1851,1822,1791,1759,1727,1698,1669,
+1638,1608,1581,1559,1534,1503,1468,1434,1407,1382,1354,1323,1293,1266,1240,1213,1181,1149,1122,1099,1078,
+1057,1038,1020,1004,989,973,957,938,916,891,865,843,823,802,774,741,705,669,629,583,532,
+481,435,392,348,295,231,160,89,29,-13,-41,-65,-98,-144,-195,-245,-291,-336,-382,-426,-463,
+-495,-529,-571,-623,-680,-736,-785,-827,-864,-901,-944,-995,-1048,-1098,-1142,-1184,-1229,-1276,-1320,-1361,-1402,
+-1448,-1498,-1546,-1589,-1629,-1673,-1723,-1776,-1828,-1875,-1919,-1960,-2000,-2041,-2088,-2140,-2194,-2245,-2292,-2340,-2390,
+-2441,-2486,-2524,-2563,-2609,-2659,-2706,-2744,-2776,-2808,-2844,-2879,-2910,-2938,-2967,-2999,-3029,-3055,-3081,-3113,-3153,
+-3195,-3233,-3262,-3289,-3319,-3354,-3394,-3443,-3500,-3565,-3626,-3674,-3702,-3721,-3746,-3789,-3844,-3889,-3907,-3897,-3878,
+-3876,-3901,-3940,-3972,-3986,-3988,-3991,-4002,-4016,-4022,-4019,-4014,-4015,-4023,-4034,-4040,-4036,-4022,-4006,-3996,-3999,
+-4013,-4032,-4049,-4064,-4079,-4093,-4098,-4085,-4054,-4013,-3972,-3933,-3891,-3842,-3787,-3729,-3669,-3610,-3553,-3503,-3468,
+-3447,-3437,-3436,-3443,-3461,-3495,-3542,-3596,-3646,-3681,-3698,-3701,-3700,-3702,-3704,-3701,-3687,-3666,-3646,-3632,-3621,
+-3610,-3599,-3585,-3569,-3549,-3526,-3506,-3492,-3483,-3476,-3470,-3464,-3461,-3456,-3445,-3426,-3401,-3377,-3355,-3331,-3299,
+-3258,-3213,-3173,-3140,-3112,-3084,-3056,-3030,-3010,-2994,-2974,-2942,-2894,-2835,-2771,-2702,-2624,-2536,-2446,-2365,-2300,
+-2246,-2193,-2133,-2066,-1997,-1929,-1857,-1773,-1670,-1544,-1398,-1240,-1088,-956,-850,-758,-668,-575,-490,-427,-391,
+-367,-333,-283,-230,-189,-164,-140,-104,-53,0,44,81,121,172,228,279,320,356,394,439,490,
+542,593,641,684,725,765,807,849,887,920,956,1002,1061,1125,1183,1228,1270,1326,1408,1514,1632,
+1741,1826,1883,1916,1932,1932,1911,1858,1769,1643,1485,1312,1152,1037,990,1010,1067,1126,1168,1197,1226,
+1256,1285,1307,1328,1356,1393,1428,1455,1474,1491,1509,1525,1538,1549,1560,1569,1572,1568,1563,1567,1582,
+1600,1614,1625,1640,1671,1720,1784,1850,1906,1942,1961,1977,2005,2049,2102,2151,2192,2229,2268,2304,2335,
+2361,2394,2443,2505,2563,2598,2604,2586,2559,2541,2545,2572,2616,2663,2701,2725,2741,2757,2782,2823,2882,
+2952,3018,3062,3076,3070,3060,3060,3072,3091,3117,3157,3215,3291,3375,3457,3529,3590,3644,3692,3738,3778,
+3805,3808,3791,3764,3741,3724,3703,3674,3641,3622,3624,3637,3641,3625,3590,3544,3483,3394,3268,3113,2945,
+2768,2568,2329,2065,1825,1677,1660,1759,1919,2079,2207,2303,2379,2438,2480,2502,2510,2509,2502,2485,2457,
+2418,2371,2317,2258,2202,2156,2120,2086,2045,2001,1963,1932,1898,1852,1800,1767,1772,1805,1831,1812,1741,
+1645,1559,1505,1479,1464,1449,1430,1407,1378,1341,1294,1242,1193,1156,1136,1127,1114,1084,1038,988,950,
+926,905,873,831,789,758,738,716,684,644,607,581,564,546,521,491,463,442,426,410,387,
+356,319,281,245,215,192,175,162,148,128,103,72,38,5,-21,-41,-56,-69,-84,-102,-122,
+-144,-165,-187,-207,-226,-246,-267,-289,-307,-319,-324,-327,-332,-342,-357,-378,-400,-424,-447,-469,-491,
+-516,-545,-572,-594,-610,-621,-632,-643,-654,-664,-674,-687,-706,-728,-751,-773,-793,-809,-823,-835,-846,
+-857,-868,-878,-889,-899,-908,-914,-919,-923,-928,-935,-940,-945,-950,-958,-967,-978,-988,-996,-1005,-1013,
+-1022,-1030,-1040,-1052,-1065,-1078,-1086,-1093,-1099,-1106,-1115,-1121,-1124,-1123,-1120,-1118,-1118,-1123,-1132,-1140,-1144,
+-1143,-1138,-1134,-1134,-1134,-1132,-1128,-1124,-1122,-1122,-1123,-1125,-1127,-1130,-1133,-1135,-1138,-1140,-1142,-1141,-1139,
+-1136,-1135,-1133,-1128,-1117,-1104,-1094,-1088,-1087,-1092,-1102,-1117,-1132,-1140,-1140,-1138,-1138,-1141,-1142,-1142,-1147,
+-1164,-1191,-1219,-1236,-1238,-1229,-1215,-1202,-1195,-1197,-1209,-1220,-1219,-1205,-1187,-1180,-1185,-1192,-1188,-1172,-1159,
+-1162,-1179,-1194,-1195,-1179,-1161,-1151,-1150,-1150,-1145,-1133,-1119,-1107,-1098,-1091,-1085,-1079,-1075,-1073,-1070,-1063,
+-1052,-1040,-1030,-1022,-1014,-1005,-996,-989,-984,-979,-972,-966,-963,-962,-961,-956,-947,-938,-933,-931,-928,
+-924,-919,-914,-906,-891,-870,-850,-836,-829,-823,-811,-792,-770,-752,-737,-725,-712,-698,-682,-664,-646,
+-629,-614,-603,-597,-591,-585,-579,-573,-567,-559,-550,-542,-538,-538,-538,-531,-517,-499,-483,-472,-462,
+-450,-435,-421,-409,-399,-385,-368,-350,-336,-325,-316,-306,-297,-293,-294,-295,-294,-289,-283,-279,-274,
+-266,-252,-240,-234,-236,-239,-238,-231,-222,-213,-204,-191,-172,-151,-133,-118,-105,-90,-72,-53,-30,
+-4,25,54,81,109,141,177,214,248,279,314,353,391,421,445,471,503,541,579,615,649,
+682,711,733,753,778,810,844,875,905,937,975,1015,1050,1084,1121,1162,1197,1217,1224,1230,1240,
+1243,1212,1133,1013,894,828,859,1003,1237,1508,1755,1931,2026,2062,2086,2149,2283,2484,2695,2839,2861,
+2770,2640,2555,2549,2591,2618,2580,2477,2337,2201,2095,2033,2009,2003,1992,1963,1925,1892,1872,1860,1848,
+1839,1835,1833,1824,1806,1786,1780,1789,1800,1800,1785,1764,1746,1732,1723,1718,1719,1723,1725,1727,1735,
+1748,1761,1759,1740,1711,1680,1649,1611,1563,1513,1465,1417,1364,1311,1271,1252,1243,1219,1171,1108,1048,
+1001,957,910,865,836,824,808,765,687,587,487,399,320,240,154,63,-23,-100,-167,-225,-282,
+-338,-390,-433,-464,-487,-508,-530,-550,-562,-567,-570,-576,-585,-593,-600,-608,-619,-636,-654,-669,-678,
+-682,-686,-693,-703,-714,-724,-732,-739,-746,-749,-746,-739,-728,-717,-706,-695,-686,-682,-682,-685,-683,
+-674,-659,-640,-617,-589,-558,-525,-494,-465,-438,-414,-392,-370,-346,-315,-276,-229,-179,-127,-78,-36,
+0,33,68,106,148,193,239,288,336,378,416,456,504,560,615,659,690,717,751,792,831,
+860,879,900,931,975,1026,1074,1116,1153,1188,1223,1256,1285,1309,1332,1357,1388,1423,1456,1483,1508,
+1532,1559,1588,1615,1640,1665,1689,1710,1729,1744,1757,1772,1789,1809,1831,1849,1859,1861,1862,1870,1885,
+1897,1898,1887,1873,1867,1872,1881,1888,1891,1891,1891,1891,1891,1886,1876,1860,1843,1832,1826,1822,1812,
+1798,1785,1779,1776,1770,1760,1750,1745,1742,1735,1723,1716,1718,1723,1721,1707,1692,1687,1692,1694,1685,
+1673,1672,1684,1703,1717,1728,1740,1751,1748,1726,1694,1673,1674,1690,1710,1725,1732,1732,1724,1709,1697,
+1700,1716,1729,1727,1713,1700,1702,1716,1709,1716,1724,1740,1765,1794,1815,1830,1842,1855,1869,1879,1884,
+1891,1903,1917,1930,1943,1960,1983,2007,2029,2047,2066,2089,2114,2138,2159,2181,2204,2227,2246,2264,2284,
+2309,2334,2352,2364,2376,2393,2415,2438,2458,2477,2497,2514,2526,2532,2540,2550,2561,2565,2560,2551,2547,
+2550,2553,2554,2556,2564,2579,2596,2613,2631,2655,2683,2713,2742,2772,2808,2845,2872,2882,2883,2891,2921,
+2971,3025,3069,3095,3105,3106,3100,3091,3084,3084,3086,3075,3033,2954,2853,2759,2698,2675,2676,2678,2671,
+2661,2664,2686,2725,2765,2792,2800,2791,2775,2762,2758,2763,2769,2773,2775,2778,2783,2786,2784,2776,2765,
+2754,2747,2742,2741,2744,2756,2776,2805,2840,2876,2906,2929,2943,2956,2972,2989,3003,3011,3011,3004,2989,
+2961,2919,2864,2803,2743,2692,2654,2630,2620,2618,2619,2625,2635,2649,2662,2670,2675,2683,2695,2709,2721,
+2729,2734,2740,2752,2769,2795,2829,2869,2912,2955,3003,3061,3130,3201,3261,3304,3334,3357,3378,3392,3393,
+3387,3385,3394,3406,3407,3390,3365,3351,3355,3364,3362,3348,3337,3342,3355,3362,3355,3346,3347,3354,3352,
+3334,3318,3325,3353,3374,3361,3321,3285,3278,3295,3310,3309,3297,3284,3265,3227,3168,3107,3063,3035,3000,
+2945,2876,2813,2765,2724,2678,2629,2585,2548,2511,2467,2419,2379,2355,2344,2337,2332,2330,2333,2336,2332,
+2325,2320,2322,2328,2331,2331,2332,2335,2336,2331,2321,2308,2295,2280,2260,2236,2213,2194,2174,2149,2118,
+2086,2056,2027,1995,1959,1923,1889,1858,1827,1796,1766,1738,1709,1678,1648,1621,1597,1570,1537,1502,1469,
+1443,1419,1392,1362,1333,1307,1282,1252,1219,1187,1160,1138,1116,1096,1078,1065,1053,1038,1019,1000,981,
+962,940,917,896,877,857,833,803,770,733,691,642,591,542,498,455,405,344,271,195,127,
+75,42,19,-6,-45,-95,-148,-195,-237,-279,-323,-365,-402,-435,-475,-527,-586,-644,-693,-733,-770,
+-806,-846,-891,-942,-995,-1044,-1086,-1126,-1167,-1212,-1256,-1297,-1338,-1383,-1433,-1484,-1529,-1570,-1612,-1660,-1714,
+-1769,-1819,-1863,-1902,-1939,-1980,-2028,-2083,-2139,-2192,-2240,-2288,-2338,-2388,-2433,-2471,-2510,-2554,-2603,-2650,-2691,
+-2727,-2763,-2801,-2836,-2865,-2891,-2920,-2954,-2987,-3016,-3041,-3071,-3108,-3152,-3195,-3232,-3264,-3293,-3318,-3342,-3368,
+-3406,-3462,-3528,-3590,-3636,-3669,-3701,-3742,-3790,-3830,-3848,-3844,-3837,-3844,-3871,-3905,-3931,-3942,-3947,-3960,-3983,
+-4008,-4023,-4022,-4012,-4004,-4010,-4030,-4052,-4062,-4052,-4027,-4005,-4003,-4022,-4050,-4073,-4084,-4089,-4090,-4086,-4073,
+-4051,-4026,-4004,-3987,-3968,-3939,-3903,-3860,-3815,-3769,-3723,-3684,-3656,-3641,-3635,-3637,-3646,-3664,-3690,-3722,-3755,
+-3781,-3794,-3795,-3788,-3782,-3782,-3787,-3789,-3783,-3767,-3744,-3720,-3696,-3675,-3658,-3646,-3633,-3616,-3593,-3570,-3551,
+-3536,-3524,-3513,-3502,-3490,-3476,-3453,-3421,-3385,-3354,-3331,-3310,-3283,-3245,-3199,-3156,-3122,-3096,-3072,-3044,-3015,
+-2989,-2969,-2952,-2929,-2897,-2858,-2816,-2771,-2714,-2642,-2560,-2483,-2422,-2376,-2330,-2274,-2207,-2137,-2072,-2013,-1952,
+-1875,-1770,-1631,-1460,-1273,-1094,-944,-826,-733,-650,-577,-518,-475,-441,-403,-357,-312,-278,-253,-223,-176,
+-115,-55,-6,34,80,138,201,255,297,331,367,409,455,501,546,590,633,675,716,757,798,
+838,874,909,950,1002,1064,1125,1178,1225,1278,1357,1469,1607,1742,1845,1897,1905,1889,1865,1830,1763,
+1648,1486,1301,1127,997,931,927,964,1015,1060,1094,1124,1157,1190,1218,1240,1266,1301,1340,1371,1389,
+1400,1414,1432,1450,1462,1472,1484,1500,1510,1511,1508,1512,1525,1541,1548,1548,1554,1582,1637,1709,1781,
+1837,1871,1888,1898,1916,1949,1994,2042,2088,2132,2174,2215,2253,2290,2331,2382,2443,2502,2547,2567,2563,
+2543,2523,2518,2535,2571,2614,2654,2688,2717,2743,2767,2792,2821,2859,2904,2943,2968,2978,2982,2992,3011,
+3036,3063,3094,3138,3196,3265,3336,3403,3463,3521,3583,3646,3703,3742,3755,3747,3731,3717,3705,3685,3648,
+3602,3561,3538,3531,3525,3504,3457,3384,3287,3171,3045,2918,2787,2636,2441,2201,1948,1748,1659,1695,1823,
+1980,2118,2223,2302,2368,2420,2452,2464,2464,2460,2451,2432,2399,2354,2302,2246,2189,2136,2093,2060,2030,
+1996,1957,1919,1884,1848,1802,1750,1709,1695,1711,1734,1735,1697,1628,1550,1486,1447,1430,1422,1412,1391,
+1362,1326,1282,1230,1177,1133,1109,1102,1094,1067,1017,963,923,903,889,863,821,775,738,714,695,
+669,636,602,574,553,532,508,481,453,427,405,387,369,346,314,275,235,203,182,168,154,
+137,115,89,61,30,-3,-35,-60,-78,-89,-98,-110,-127,-148,-173,-199,-223,-243,-261,-279,-299,
+-316,-328,-335,-341,-348,-359,-372,-389,-410,-434,-460,-485,-508,-532,-558,-585,-609,-627,-640,-649,-658,
+-667,-678,-689,-702,-717,-734,-754,-775,-796,-816,-834,-850,-864,-877,-887,-896,-904,-913,-922,-929,-934,
+-936,-939,-942,-945,-950,-956,-966,-977,-986,-993,-998,-1004,-1012,-1021,-1031,-1043,-1056,-1070,-1082,-1090,-1095,
+-1101,-1111,-1122,-1132,-1137,-1140,-1139,-1137,-1132,-1127,-1124,-1126,-1130,-1133,-1133,-1130,-1126,-1123,-1120,-1118,-1118,
+-1121,-1124,-1128,-1131,-1134,-1137,-1139,-1141,-1144,-1146,-1147,-1145,-1142,-1140,-1137,-1133,-1126,-1120,-1117,-1115,-1108,
+-1094,-1083,-1086,-1109,-1139,-1158,-1158,-1148,-1142,-1146,-1154,-1155,-1151,-1153,-1167,-1190,-1211,-1222,-1222,-1217,-1210,
+-1207,-1210,-1220,-1228,-1226,-1213,-1197,-1189,-1193,-1197,-1190,-1175,-1166,-1174,-1196,-1213,-1208,-1184,-1156,-1139,-1137,
+-1139,-1135,-1122,-1107,-1096,-1090,-1089,-1087,-1083,-1078,-1072,-1067,-1061,-1052,-1043,-1033,-1023,-1014,-1005,-997,-991,
+-986,-981,-975,-970,-967,-967,-966,-960,-951,-941,-932,-925,-917,-911,-906,-903,-898,-885,-867,-848,-837,
+-833,-831,-822,-806,-787,-771,-757,-745,-732,-719,-706,-693,-677,-658,-640,-627,-619,-612,-602,-589,-578,
+-568,-558,-547,-535,-527,-524,-524,-520,-511,-498,-485,-475,-466,-455,-443,-431,-421,-412,-399,-382,-363,
+-345,-331,-320,-311,-304,-302,-302,-302,-299,-293,-288,-284,-281,-275,-266,-257,-252,-250,-249,-244,-235,
+-226,-218,-207,-192,-171,-150,-134,-122,-112,-100,-84,-64,-40,-13,16,45,72,102,137,175,212,
+244,274,307,346,385,420,451,481,514,548,580,611,644,678,710,734,756,781,811,843,873,
+902,937,976,1015,1048,1078,1111,1149,1182,1200,1207,1213,1222,1215,1167,1070,948,853,841,943,1152,
+1424,1698,1912,2033,2067,2059,2069,2141,2287,2480,2662,2774,2788,2724,2638,2587,2588,2618,2629,2587,2486,
+2348,2205,2090,2020,1991,1980,1963,1930,1890,1859,1840,1828,1815,1805,1802,1804,1802,1789,1774,1769,1777,
+1789,1792,1780,1761,1742,1728,1716,1707,1702,1700,1700,1705,1719,1739,1757,1761,1751,1734,1717,1695,1661,
+1609,1549,1487,1426,1366,1310,1269,1248,1234,1206,1156,1091,1030,979,932,884,837,802,773,735,671,
+585,493,413,346,277,198,108,18,-60,-126,-185,-240,-292,-340,-382,-417,-445,-468,-490,-509,-528,
+-543,-555,-565,-571,-577,-582,-588,-596,-607,-620,-636,-651,-663,-670,-675,-681,-692,-705,-717,-724,-729,
+-732,-736,-739,-737,-729,-717,-703,-690,-681,-676,-676,-677,-676,-669,-656,-638,-617,-594,-567,-537,-505,
+-473,-443,-416,-392,-367,-339,-306,-269,-227,-182,-131,-79,-30,10,45,77,112,152,197,246,295,
+341,380,413,448,491,544,600,651,694,733,773,814,852,883,909,935,967,1004,1043,1083,1124,
+1165,1205,1243,1279,1310,1336,1358,1380,1408,1441,1476,1507,1534,1557,1582,1610,1638,1665,1691,1717,1741,
+1764,1781,1794,1804,1816,1832,1853,1872,1886,1893,1900,1912,1927,1939,1939,1928,1913,1905,1906,1913,1919,
+1922,1924,1925,1924,1920,1911,1896,1879,1865,1858,1855,1851,1841,1826,1814,1804,1796,1784,1773,1769,1772,
+1776,1770,1757,1747,1750,1757,1756,1744,1731,1727,1730,1724,1705,1684,1677,1688,1705,1714,1717,1722,1737,
+1749,1747,1732,1719,1719,1732,1744,1746,1734,1717,1699,1689,1690,1701,1714,1720,1713,1702,1696,1700,1709,
+1696,1702,1712,1731,1759,1785,1803,1813,1823,1837,1850,1858,1862,1868,1882,1901,1919,1938,1960,1986,2012,
+2032,2049,2070,2096,2124,2147,2167,2191,2221,2252,2274,2288,2301,2320,2343,2360,2371,2380,2395,2417,2439,
+2457,2471,2488,2507,2521,2528,2531,2537,2546,2554,2554,2548,2545,2548,2558,2568,2575,2581,2589,2602,2619,
+2641,2663,2681,2692,2702,2722,2756,2797,2828,2840,2839,2845,2874,2927,2987,3035,3066,3085,3098,3108,3113,
+3113,3110,3103,3081,3031,2950,2856,2781,2750,2758,2778,2784,2767,2745,2738,2752,2778,2799,2806,2803,2796,
+2792,2792,2795,2800,2804,2807,2809,2814,2821,2826,2825,2816,2801,2789,2782,2779,2779,2781,2788,2806,2837,
+2878,2919,2952,2972,2984,2993,3003,3015,3028,3038,3045,3044,3029,2995,2943,2881,2817,2760,2714,2682,2663,
+2657,2658,2664,2672,2685,2699,2713,2722,2730,2742,2759,2780,2796,2803,2806,2810,2818,2833,2855,2885,2923,
+2968,3016,3065,3122,3187,3254,3312,3352,3377,3398,3421,3442,3452,3451,3450,3458,3468,3466,3445,3418,3406,
+3414,3429,3432,3423,3419,3429,3445,3449,3438,3429,3436,3452,3453,3433,3412,3420,3454,3477,3455,3396,3338,
+3315,3325,3338,3335,3322,3308,3287,3244,3178,3111,3065,3040,3010,2957,2885,2817,2766,2726,2684,2639,2596,
+2557,2518,2471,2425,2391,2376,2372,2368,2360,2356,2359,2364,2363,2356,2350,2352,2357,2360,2359,2360,2363,
+2366,2362,2349,2335,2323,2311,2295,2274,2251,2229,2208,2182,2152,2122,2093,2065,2034,1998,1961,1927,1896,
+1866,1835,1806,1778,1749,1718,1687,1658,1631,1601,1569,1536,1507,1482,1457,1430,1401,1373,1348,1321,1290,
+1256,1226,1201,1180,1159,1139,1123,1112,1100,1083,1060,1038,1021,1007,992,974,953,934,915,894,869,
+837,798,752,700,649,604,563,518,460,387,305,227,166,125,98,73,41,-3,-54,-102,-143,
+-181,-222,-266,-308,-344,-380,-426,-484,-544,-596,-636,-670,-706,-747,-792,-840,-890,-941,-990,-1031,-1068,
+-1106,-1149,-1193,-1237,-1279,-1324,-1375,-1427,-1475,-1517,-1556,-1600,-1651,-1703,-1752,-1797,-1838,-1878,-1923,-1972,-2027,
+-2083,-2135,-2185,-2233,-2283,-2331,-2375,-2415,-2455,-2499,-2549,-2597,-2640,-2680,-2719,-2758,-2793,-2821,-2847,-2875,-2908,
+-2943,-2975,-3004,-3035,-3073,-3115,-3155,-3192,-3226,-3257,-3285,-3306,-3325,-3349,-3389,-3443,-3501,-3550,-3589,-3624,-3663,
+-3706,-3745,-3774,-3795,-3814,-3837,-3860,-3875,-3880,-3880,-3886,-3906,-3937,-3969,-3991,-3995,-3985,-3969,-3962,-3972,-3997,
+-4018,-4021,-4005,-3986,-3983,-4002,-4034,-4060,-4072,-4073,-4068,-4061,-4050,-4036,-4023,-4012,-4003,-3989,-3971,-3949,-3927,
+-3903,-3875,-3845,-3819,-3801,-3792,-3789,-3788,-3789,-3795,-3807,-3822,-3835,-3844,-3848,-3849,-3849,-3849,-3850,-3853,-3853,
+-3846,-3830,-3805,-3773,-3739,-3708,-3684,-3669,-3657,-3642,-3622,-3598,-3577,-3558,-3542,-3526,-3508,-3487,-3463,-3432,-3395,
+-3357,-3326,-3305,-3289,-3270,-3240,-3200,-3158,-3123,-3095,-3072,-3046,-3017,-2989,-2965,-2944,-2921,-2892,-2861,-2832,-2805,
+-2770,-2720,-2658,-2598,-2551,-2516,-2478,-2425,-2353,-2273,-2200,-2140,-2090,-2037,-1962,-1849,-1686,-1483,-1267,-1074,-924,
+-819,-741,-675,-616,-566,-523,-484,-444,-407,-373,-338,-291,-230,-163,-105,-59,-19,30,94,161,219,
+264,303,342,382,422,460,500,545,594,639,678,713,750,790,831,869,907,950,1003,1065,1126,
+1181,1238,1314,1426,1570,1717,1825,1869,1858,1822,1785,1742,1664,1526,1337,1133,966,867,841,866,913,
+959,994,1022,1050,1081,1113,1143,1173,1209,1248,1282,1304,1316,1330,1353,1380,1397,1399,1395,1402,1422,
+1445,1458,1459,1459,1464,1471,1474,1474,1484,1517,1574,1643,1707,1754,1785,1805,1820,1840,1869,1908,1952,
+1996,2038,2078,2120,2166,2215,2269,2325,2382,2435,2478,2506,2517,2513,2502,2496,2504,2527,2557,2590,2625,
+2664,2705,2742,2769,2787,2806,2832,2864,2892,2908,2916,2924,2942,2968,2997,3027,3061,3104,3156,3213,3273,
+3334,3402,3476,3551,3614,3656,3674,3678,3677,3675,3667,3644,3600,3543,3487,3445,3419,3397,3358,3287,3182,
+3056,2932,2827,2740,2645,2509,2315,2082,1864,1725,1700,1778,1911,2046,2155,2236,2303,2361,2405,2427,2430,
+2421,2410,2394,2370,2333,2287,2236,2182,2128,2077,2035,2003,1976,1947,1911,1870,1828,1787,1746,1703,1660,
+1625,1609,1612,1623,1623,1595,1538,1471,1418,1393,1388,1384,1366,1335,1299,1261,1218,1168,1120,1088,1077,
+1070,1046,996,939,898,880,871,850,811,763,722,694,673,652,627,601,576,552,530,506,479,
+448,417,390,371,358,342,314,273,228,192,171,160,147,128,103,76,49,20,-11,-44,-73,
+-94,-107,-114,-121,-134,-155,-182,-211,-237,-258,-275,-293,-311,-328,-341,-352,-362,-373,-385,-397,-411,
+-429,-452,-477,-502,-525,-547,-573,-601,-627,-648,-660,-667,-674,-682,-694,-708,-722,-736,-750,-767,-786,
+-806,-826,-845,-863,-880,-895,-906,-913,-919,-927,-936,-943,-946,-947,-948,-950,-953,-957,-964,-974,-985,
+-993,-996,-997,-999,-1005,-1015,-1025,-1037,-1050,-1064,-1077,-1086,-1092,-1101,-1114,-1128,-1140,-1149,-1155,-1159,-1159,
+-1153,-1142,-1130,-1123,-1123,-1127,-1130,-1131,-1128,-1124,-1121,-1121,-1124,-1129,-1136,-1140,-1142,-1143,-1144,-1147,-1150,
+-1154,-1155,-1155,-1152,-1148,-1144,-1139,-1132,-1127,-1129,-1137,-1143,-1133,-1105,-1077,-1072,-1099,-1142,-1173,-1176,-1160,
+-1148,-1152,-1162,-1167,-1162,-1156,-1160,-1175,-1190,-1201,-1207,-1212,-1215,-1217,-1219,-1222,-1224,-1221,-1210,-1197,-1192,
+-1196,-1202,-1200,-1190,-1185,-1193,-1212,-1225,-1219,-1193,-1161,-1139,-1128,-1123,-1115,-1102,-1088,-1080,-1079,-1083,-1087,
+-1086,-1081,-1073,-1065,-1058,-1051,-1043,-1033,-1023,-1013,-1005,-998,-993,-988,-983,-978,-975,-973,-973,-971,-967,
+-959,-949,-939,-927,-916,-906,-901,-898,-894,-882,-863,-844,-831,-825,-820,-810,-796,-781,-771,-764,-756,
+-747,-738,-730,-721,-708,-691,-675,-663,-656,-647,-634,-618,-603,-592,-582,-570,-555,-540,-527,-518,-511,
+-502,-493,-483,-474,-465,-455,-445,-434,-423,-412,-398,-382,-364,-347,-331,-319,-310,-306,-304,-302,-300,
+-297,-294,-292,-291,-289,-284,-277,-271,-266,-261,-255,-246,-234,-223,-213,-201,-186,-168,-151,-137,-126,
+-116,-103,-87,-66,-43,-17,10,38,67,99,136,175,211,242,271,302,338,377,414,450,485,
+519,549,574,600,629,663,696,725,750,778,810,843,875,906,941,979,1014,1043,1070,1102,1138,
+1169,1187,1194,1199,1201,1180,1115,1010,903,852,904,1070,1321,1603,1853,2023,2095,2094,2071,2083,2164,
+2308,2478,2625,2711,2727,2695,2652,2627,2622,2619,2591,2521,2413,2284,2159,2060,2001,1976,1964,1944,1909,
+1869,1840,1826,1816,1803,1788,1776,1772,1771,1767,1762,1761,1767,1774,1775,1767,1753,1739,1724,1711,1699,
+1690,1684,1682,1683,1691,1705,1717,1722,1720,1715,1712,1703,1680,1639,1586,1528,1466,1399,1331,1274,1235,
+1207,1176,1130,1074,1018,967,917,864,811,762,714,654,577,491,413,351,296,231,149,59,-23,
+-90,-145,-198,-250,-298,-339,-370,-398,-425,-452,-475,-494,-509,-526,-542,-554,-562,-566,-570,-577,-588,
+-598,-608,-619,-633,-648,-659,-666,-672,-683,-698,-712,-720,-722,-723,-727,-731,-732,-725,-712,-698,-688,
+-681,-678,-676,-674,-671,-664,-650,-633,-614,-594,-572,-546,-514,-479,-444,-413,-385,-354,-320,-284,-247,
+-212,-173,-128,-76,-22,25,65,97,126,159,197,241,288,335,378,418,459,505,555,605,651,
+692,735,781,829,874,911,944,975,1007,1039,1071,1105,1141,1180,1220,1258,1294,1328,1357,1382,1405,
+1431,1462,1495,1526,1554,1579,1605,1633,1662,1688,1712,1735,1760,1783,1802,1816,1827,1839,1855,1876,1896,
+1913,1927,1943,1961,1978,1986,1983,1971,1958,1951,1950,1951,1953,1953,1954,1955,1954,1949,1940,1928,1914,
+1904,1897,1892,1884,1873,1860,1849,1841,1829,1814,1801,1797,1804,1810,1806,1794,1785,1787,1794,1792,1780,
+1770,1772,1779,1775,1752,1721,1703,1705,1714,1716,1712,1713,1728,1749,1762,1762,1755,1753,1754,1752,1739,
+1716,1691,1670,1662,1667,1683,1699,1706,1700,1690,1686,1690,1696,1680,1692,1706,1725,1750,1771,1784,1791,
+1799,1811,1822,1828,1833,1845,1867,1893,1918,1941,1965,1993,2019,2038,2055,2076,2104,2133,2157,2179,2206,
+2242,2276,2299,2309,2314,2326,2343,2357,2366,2375,2391,2414,2436,2450,2460,2475,2494,2512,2520,2521,2524,
+2534,2547,2554,2553,2550,2553,2564,2577,2587,2590,2592,2598,2612,2632,2653,2668,2674,2677,2687,2712,2747,
+2778,2796,2802,2808,2829,2868,2917,2966,3012,3057,3102,3139,3155,3147,3121,3087,3051,3005,2946,2883,2839,
+2831,2850,2871,2868,2840,2807,2790,2795,2811,2823,2827,2830,2836,2844,2848,2847,2843,2841,2841,2843,2847,
+2852,2855,2853,2844,2831,2823,2821,2824,2827,2828,2834,2851,2883,2922,2959,2987,3003,3013,3022,3032,3041,
+3051,3061,3070,3070,3052,3013,2956,2893,2834,2784,2743,2712,2694,2689,2696,2710,2725,2741,2756,2768,2778,
+2788,2803,2826,2852,2872,2881,2883,2884,2890,2901,2917,2941,2976,3020,3069,3119,3173,3235,3303,3364,3408,
+3435,3458,3484,3509,3522,3522,3516,3517,3521,3516,3497,3476,3469,3481,3496,3499,3493,3496,3516,3540,3547,
+3536,3526,3537,3558,3561,3539,3515,3521,3553,3573,3545,3477,3410,3379,3379,3377,3355,3324,3300,3281,3247,
+3191,3130,3085,3056,3022,2966,2895,2829,2782,2746,2706,2659,2612,2571,2530,2486,2443,2415,2406,2406,2402,
+2391,2382,2380,2382,2380,2373,2369,2373,2380,2384,2381,2378,2380,2383,2382,2373,2362,2353,2345,2331,2310,
+2285,2261,2236,2209,2179,2150,2123,2097,2068,2033,1998,1964,1934,1905,1874,1844,1815,1787,1758,1727,1696,
+1665,1633,1602,1571,1544,1520,1494,1466,1438,1412,1387,1359,1326,1293,1265,1243,1224,1203,1184,1170,1159,
+1146,1126,1100,1078,1064,1056,1046,1030,1011,991,973,954,930,898,857,809,757,708,665,624,574,
+506,422,337,264,213,180,154,123,81,33,-14,-55,-90,-126,-167,-211,-252,-290,-331,-381,-438,
+-493,-536,-568,-600,-641,-689,-739,-788,-836,-886,-934,-976,-1012,-1050,-1092,-1139,-1185,-1229,-1274,-1323,-1376,
+-1426,-1469,-1509,-1551,-1597,-1645,-1690,-1733,-1777,-1823,-1872,-1923,-1975,-2026,-2076,-2125,-2174,-2222,-2269,-2312,-2353,
+-2394,-2439,-2488,-2537,-2582,-2622,-2660,-2698,-2733,-2765,-2795,-2825,-2858,-2892,-2923,-2954,-2989,-3031,-3075,-3116,-3150,
+-3182,-3215,-3247,-3276,-3298,-3320,-3348,-3385,-3426,-3464,-3499,-3531,-3566,-3603,-3641,-3681,-3723,-3765,-3799,-3815,-3814,
+-3803,-3798,-3808,-3834,-3869,-3904,-3932,-3945,-3937,-3913,-3887,-3879,-3897,-3929,-3957,-3967,-3964,-3965,-3979,-4005,-4029,
+-4043,-4045,-4040,-4032,-4022,-4014,-4008,-4002,-3992,-3974,-3954,-3938,-3928,-3920,-3906,-3888,-3872,-3864,-3864,-3863,-3859,
+-3851,-3846,-3846,-3850,-3854,-3859,-3867,-3878,-3890,-3897,-3896,-3888,-3875,-3858,-3836,-3809,-3778,-3745,-3715,-3690,-3672,
+-3657,-3639,-3618,-3594,-3570,-3549,-3530,-3510,-3488,-3464,-3436,-3402,-3366,-3333,-3306,-3289,-3276,-3260,-3235,-3200,-3159,
+-3121,-3089,-3063,-3037,-3011,-2985,-2961,-2938,-2912,-2881,-2848,-2820,-2798,-2775,-2743,-2702,-2661,-2628,-2604,-2575,-2527,
+-2456,-2373,-2291,-2223,-2171,-2128,-2079,-2001,-1872,-1689,-1475,-1266,-1094,-967,-872,-792,-717,-650,-595,-551,-515,
+-483,-449,-405,-346,-276,-207,-150,-107,-65,-12,52,119,178,228,273,317,359,394,426,463,510,
+563,611,647,676,707,747,793,836,872,909,957,1020,1094,1167,1235,1310,1409,1533,1661,1753,1785,
+1765,1723,1683,1635,1545,1390,1185,981,833,765,768,808,857,898,931,958,985,1012,1041,1072,1109,
+1151,1190,1216,1231,1247,1280,1330,1376,1394,1377,1347,1333,1346,1374,1395,1399,1393,1390,1392,1397,1404,
+1421,1456,1507,1563,1613,1652,1683,1712,1741,1772,1806,1843,1880,1916,1949,1982,2021,2070,2130,2195,2260,
+2317,2365,2401,2429,2448,2458,2462,2465,2473,2490,2511,2534,2560,2594,2637,2684,2723,2751,2772,2798,2830,
+2859,2874,2875,2871,2875,2893,2920,2949,2979,3012,3053,3099,3152,3213,3286,3367,3446,3509,3550,3575,3592,
+3606,3613,3604,3572,3521,3460,3398,3343,3294,3241,3169,3066,2936,2803,2696,2630,2584,2517,2389,2199,1990,
+1826,1758,1791,1891,2010,2113,2193,2256,2313,2361,2394,2407,2402,2386,2364,2336,2301,2260,2214,2166,2116,
+2065,2017,1975,1944,1919,1893,1858,1813,1765,1724,1694,1668,1633,1585,1539,1518,1530,1558,1563,1522,1447,
+1376,1341,1341,1347,1332,1297,1257,1225,1195,1157,1113,1079,1062,1051,1025,976,917,874,856,848,831,
+794,748,708,678,657,637,616,595,574,554,534,511,484,452,415,382,360,350,341,318,277,
+229,188,164,151,138,118,92,64,36,9,-19,-50,-79,-102,-117,-126,-133,-145,-166,-194,-224,
+-249,-269,-287,-307,-330,-351,-368,-381,-393,-405,-418,-429,-442,-458,-478,-500,-521,-541,-562,-587,-615,
+-642,-663,-676,-684,-690,-699,-712,-727,-743,-756,-770,-786,-804,-822,-839,-855,-872,-890,-907,-919,-927,
+-933,-941,-950,-955,-956,-955,-956,-959,-963,-967,-972,-981,-992,-1000,-1003,-1001,-1001,-1006,-1013,-1022,-1030,
+-1040,-1052,-1065,-1076,-1087,-1099,-1115,-1131,-1145,-1155,-1163,-1169,-1172,-1170,-1161,-1150,-1141,-1138,-1140,-1144,-1147,
+-1148,-1147,-1145,-1144,-1147,-1151,-1154,-1155,-1154,-1153,-1154,-1157,-1161,-1164,-1166,-1165,-1162,-1158,-1153,-1146,-1137,
+-1132,-1137,-1152,-1163,-1154,-1124,-1091,-1081,-1107,-1150,-1182,-1184,-1166,-1149,-1145,-1151,-1155,-1154,-1154,-1163,-1177,
+-1189,-1197,-1203,-1213,-1223,-1227,-1225,-1221,-1218,-1215,-1208,-1199,-1194,-1197,-1206,-1209,-1206,-1201,-1203,-1213,-1221,
+-1217,-1198,-1174,-1152,-1136,-1123,-1110,-1097,-1085,-1078,-1076,-1077,-1079,-1079,-1075,-1068,-1060,-1052,-1045,-1037,-1028,
+-1019,-1011,-1005,-1000,-994,-989,-984,-980,-978,-977,-977,-975,-972,-968,-961,-951,-939,-926,-914,-908,-905,
+-899,-886,-866,-846,-830,-819,-808,-795,-781,-771,-767,-765,-762,-754,-745,-737,-728,-716,-702,-689,-678,
+-671,-662,-650,-635,-622,-613,-606,-597,-582,-563,-541,-520,-504,-492,-483,-475,-465,-454,-442,-431,-419,
+-404,-388,-372,-357,-344,-332,-319,-310,-304,-301,-298,-293,-288,-286,-287,-290,-291,-288,-283,-277,-272,
+-268,-262,-253,-241,-227,-215,-203,-192,-178,-163,-148,-134,-122,-108,-93,-76,-56,-33,-9,15,41,
+69,101,136,173,208,239,269,300,334,368,404,441,477,512,540,563,586,614,645,676,704,
+732,763,799,836,870,903,938,972,1002,1030,1060,1096,1135,1164,1179,1184,1186,1178,1141,1063,960,
+881,881,990,1200,1467,1732,1942,2066,2106,2093,2081,2114,2207,2345,2489,2603,2670,2690,2680,2660,2641,
+2618,2578,2510,2413,2299,2185,2085,2010,1966,1947,1937,1919,1888,1853,1829,1819,1814,1802,1781,1759,1746,
+1745,1749,1753,1754,1752,1748,1743,1738,1733,1727,1718,1706,1695,1687,1683,1681,1678,1676,1676,1676,1672,
+1666,1662,1659,1655,1643,1620,1590,1552,1502,1433,1351,1270,1205,1158,1122,1086,1046,1004,959,908,850,
+787,722,654,581,501,422,355,299,243,175,93,9,-61,-117,-163,-211,-260,-303,-336,-359,-382,
+-410,-440,-465,-483,-497,-510,-526,-539,-546,-550,-557,-569,-584,-595,-602,-609,-622,-638,-651,-659,-664,
+-674,-689,-705,-714,-717,-717,-721,-724,-723,-715,-702,-691,-685,-682,-678,-675,-671,-667,-660,-647,-630,
+-611,-592,-572,-546,-514,-477,-441,-409,-378,-345,-306,-265,-227,-192,-157,-117,-69,-18,30,74,111,
+144,177,210,244,281,320,361,406,455,508,560,606,645,683,727,779,835,885,928,964,998,
+1032,1065,1097,1128,1162,1198,1235,1272,1308,1343,1375,1403,1428,1454,1482,1512,1542,1569,1595,1623,1650,
+1676,1699,1719,1739,1762,1784,1804,1820,1836,1855,1877,1900,1921,1939,1958,1981,2005,2023,2029,2022,2010,
+2000,1995,1992,1988,1983,1980,1979,1980,1979,1976,1971,1963,1954,1943,1933,1923,1912,1901,1892,1886,1882,
+1873,1860,1848,1842,1843,1845,1839,1830,1823,1824,1824,1815,1801,1793,1801,1818,1822,1803,1771,1745,1736,
+1738,1739,1737,1736,1743,1754,1759,1756,1748,1740,1730,1714,1693,1669,1646,1629,1621,1625,1642,1664,1677,
+1678,1670,1666,1670,1680,1675,1692,1706,1718,1733,1749,1761,1770,1778,1787,1794,1801,1810,1828,1857,1889,
+1918,1942,1968,1996,2024,2046,2064,2085,2113,2144,2171,2197,2227,2262,2295,2315,2322,2323,2330,2342,2352,
+2357,2364,2381,2406,2429,2442,2449,2461,2480,2499,2509,2512,2515,2526,2542,2555,2559,2559,2564,2574,2588,
+2597,2600,2600,2601,2607,2617,2630,2644,2657,2667,2676,2691,2713,2739,2762,2775,2780,2784,2800,2832,2882,
+2947,3023,3095,3145,3156,3125,3070,3016,2980,2960,2942,2917,2894,2883,2886,2889,2876,2850,2824,2817,2830,
+2852,2870,2884,2897,2911,2920,2917,2904,2888,2877,2873,2873,2874,2876,2878,2876,2871,2864,2861,2864,2870,
+2875,2879,2888,2907,2937,2968,2991,3003,3009,3018,3033,3048,3061,3069,3077,3083,3079,3057,3014,2959,2903,
+2855,2815,2779,2749,2730,2727,2740,2759,2779,2796,2811,2824,2836,2850,2869,2894,2922,2944,2954,2957,2959,
+2965,2975,2987,3006,3037,3079,3125,3173,3223,3284,3353,3421,3474,3510,3536,3561,3583,3592,3586,3573,3565,
+3565,3562,3552,3541,3543,3557,3570,3571,3568,3581,3615,3649,3661,3650,3640,3649,3668,3670,3646,3618,3616,
+3639,3651,3620,3557,3499,3475,3469,3447,3395,3335,3295,3276,3254,3212,3157,3106,3067,3026,2970,2907,2854,
+2817,2783,2738,2681,2626,2581,2544,2507,2471,2448,2442,2442,2436,2422,2408,2400,2397,2392,2385,2383,2389,
+2398,2402,2397,2392,2391,2395,2398,2395,2389,2383,2375,2361,2338,2312,2286,2261,2233,2203,2174,2150,2126,
+2100,2068,2034,2003,1974,1945,1913,1881,1851,1824,1797,1768,1736,1703,1671,1640,1610,1583,1556,1529,1501,
+1475,1451,1426,1396,1363,1330,1305,1285,1267,1248,1229,1214,1201,1186,1164,1140,1122,1112,1106,1096,1080,
+1061,1043,1026,1007,982,950,911,865,816,768,721,672,610,533,448,369,310,271,242,210,170,
+122,73,30,-6,-39,-74,-115,-158,-199,-239,-283,-334,-387,-434,-469,-498,-532,-578,-631,-684,-733,
+-780,-829,-876,-918,-956,-994,-1039,-1089,-1137,-1181,-1224,-1271,-1322,-1371,-1416,-1458,-1503,-1549,-1595,-1637,-1677,
+-1721,-1769,-1820,-1871,-1919,-1966,-2014,-2063,-2112,-2160,-2207,-2250,-2292,-2334,-2379,-2427,-2476,-2520,-2559,-2596,-2632,
+-2668,-2705,-2740,-2776,-2809,-2840,-2869,-2899,-2936,-2981,-3029,-3071,-3106,-3136,-3168,-3202,-3236,-3267,-3293,-3320,-3349,
+-3378,-3407,-3436,-3464,-3493,-3521,-3552,-3587,-3630,-3673,-3706,-3717,-3711,-3703,-3706,-3727,-3760,-3795,-3830,-3863,-3883,
+-3882,-3855,-3817,-3796,-3809,-3852,-3901,-3934,-3946,-3947,-3953,-3967,-3986,-4002,-4008,-4004,-3994,-3983,-3976,-3976,-3974,
+-3965,-3944,-3921,-3904,-3897,-3895,-3889,-3879,-3874,-3878,-3888,-3895,-3891,-3880,-3869,-3863,-3861,-3862,-3866,-3876,-3891,
+-3905,-3909,-3900,-3880,-3854,-3826,-3800,-3774,-3748,-3724,-3702,-3682,-3662,-3641,-3618,-3593,-3568,-3545,-3522,-3502,-3482,
+-3461,-3437,-3407,-3373,-3337,-3306,-3284,-3269,-3256,-3239,-3213,-3177,-3136,-3097,-3063,-3035,-3010,-2984,-2959,-2935,-2913,
+-2887,-2855,-2820,-2788,-2764,-2743,-2720,-2690,-2659,-2633,-2613,-2587,-2547,-2486,-2411,-2332,-2259,-2200,-2156,-2120,-2073,
+-1990,-1858,-1687,-1502,-1331,-1186,-1062,-948,-840,-743,-664,-606,-566,-535,-504,-463,-405,-335,-264,-205,-156,
+-107,-50,15,82,141,194,244,294,338,372,401,435,481,534,581,616,642,670,709,757,803,
+844,882,933,1006,1097,1190,1271,1342,1414,1499,1585,1647,1666,1647,1612,1574,1518,1412,1241,1033,844,
+724,687,709,753,794,828,862,896,929,956,981,1010,1048,1091,1126,1145,1157,1183,1239,1316,1383,
+1403,1372,1317,1278,1275,1298,1321,1327,1320,1314,1316,1324,1337,1355,1383,1422,1467,1510,1547,1582,1618,
+1657,1698,1740,1780,1815,1844,1870,1897,1932,1980,2040,2109,2177,2238,2285,2318,2344,2366,2387,2405,2422,
+2441,2465,2489,2509,2523,2539,2566,2605,2649,2689,2724,2758,2795,2827,2843,2841,2829,2821,2826,2843,2866,
+2893,2924,2962,3005,3053,3110,3181,3261,3340,3403,3448,3481,3509,3531,3539,3522,3481,3425,3363,3299,3230,
+3149,3052,2934,2796,2656,2541,2474,2455,2446,2395,2274,2099,1932,1835,1834,1909,2013,2108,2180,2236,2285,
+2328,2361,2380,2384,2375,2355,2323,2282,2235,2188,2142,2096,2048,1999,1953,1913,1881,1855,1829,1796,1751,
+1702,1663,1644,1637,1616,1569,1509,1472,1481,1521,1541,1502,1413,1323,1280,1286,1304,1296,1258,1214,1184,
+1165,1141,1106,1072,1049,1031,1000,947,888,846,828,822,805,771,728,690,663,642,622,601,581,
+562,546,530,513,491,459,420,382,355,344,337,320,286,240,197,166,145,128,107,82,54,
+27,1,-24,-50,-77,-101,-120,-133,-143,-157,-180,-209,-237,-260,-277,-295,-319,-348,-377,-399,-416,
+-429,-441,-452,-463,-476,-491,-509,-527,-543,-559,-577,-599,-623,-646,-666,-680,-692,-704,-717,-731,-745,
+-758,-771,-784,-801,-820,-838,-852,-866,-881,-899,-916,-929,-937,-944,-953,-963,-968,-968,-966,-967,-970,
+-974,-977,-981,-989,-1001,-1011,-1016,-1016,-1017,-1021,-1026,-1031,-1034,-1038,-1046,-1057,-1071,-1084,-1100,-1117,-1133,
+-1147,-1157,-1164,-1170,-1175,-1178,-1177,-1174,-1169,-1165,-1163,-1163,-1165,-1168,-1169,-1170,-1169,-1169,-1169,-1168,-1165,
+-1163,-1161,-1163,-1166,-1171,-1174,-1175,-1173,-1171,-1167,-1162,-1153,-1143,-1135,-1138,-1151,-1165,-1165,-1147,-1125,-1118,
+-1134,-1163,-1182,-1180,-1165,-1149,-1142,-1140,-1138,-1138,-1149,-1170,-1191,-1203,-1205,-1208,-1216,-1228,-1233,-1230,-1224,
+-1222,-1222,-1218,-1209,-1200,-1199,-1206,-1214,-1215,-1210,-1205,-1205,-1207,-1205,-1197,-1184,-1169,-1154,-1139,-1126,-1116,
+-1108,-1099,-1088,-1078,-1070,-1066,-1064,-1060,-1053,-1046,-1037,-1029,-1020,-1013,-1008,-1004,-1001,-996,-989,-984,-981,
+-980,-980,-979,-977,-976,-974,-971,-963,-952,-938,-926,-918,-912,-905,-893,-875,-857,-841,-828,-815,-801,
+-789,-782,-780,-778,-771,-759,-744,-729,-715,-702,-689,-676,-666,-657,-648,-638,-628,-618,-610,-604,-597,
+-586,-569,-545,-518,-494,-478,-469,-462,-452,-438,-423,-409,-394,-377,-357,-339,-326,-317,-309,-301,-296,
+-294,-293,-290,-283,-276,-274,-278,-282,-282,-277,-270,-266,-264,-262,-256,-247,-235,-223,-211,-199,-188,
+-175,-160,-143,-124,-106,-90,-74,-57,-37,-14,9,33,57,81,108,139,171,204,236,269,301,
+332,363,396,430,466,499,528,554,580,608,637,664,690,718,752,790,826,859,891,923,954,
+983,1014,1051,1093,1132,1157,1168,1170,1168,1153,1104,1019,926,878,924,1078,1314,1578,1813,1980,2064,
+2081,2071,2081,2140,2249,2382,2505,2597,2649,2665,2656,2633,2601,2557,2494,2409,2308,2203,2105,2024,1962,
+1921,1901,1891,1879,1858,1830,1810,1802,1801,1793,1773,1746,1728,1726,1734,1741,1738,1725,1709,1698,1696,
+1701,1705,1704,1699,1693,1690,1690,1690,1687,1680,1670,1657,1641,1622,1605,1591,1581,1572,1563,1554,1538,
+1504,1443,1356,1259,1172,1108,1066,1038,1014,986,949,899,834,757,674,593,516,444,377,315,253,
+188,114,37,-34,-93,-140,-183,-227,-271,-307,-333,-352,-372,-400,-430,-456,-473,-485,-496,-511,-523,
+-532,-537,-545,-560,-577,-589,-595,-602,-614,-630,-646,-654,-660,-668,-683,-699,-710,-714,-716,-718,-719,
+-716,-706,-695,-687,-684,-681,-676,-670,-664,-660,-655,-644,-629,-610,-591,-570,-542,-509,-474,-439,-408,
+-376,-340,-299,-255,-214,-176,-139,-102,-62,-20,22,65,109,154,197,234,266,293,322,357,400,
+451,507,560,605,642,679,722,774,828,877,917,953,990,1029,1068,1105,1140,1174,1210,1247,1284,
+1319,1353,1386,1416,1444,1473,1502,1531,1559,1586,1611,1635,1658,1678,1696,1714,1735,1758,1781,1801,1820,
+1842,1869,1898,1923,1942,1959,1979,2005,2033,2053,2057,2051,2041,2033,2029,2024,2017,2011,2007,2007,2008,
+2007,2005,2001,1995,1985,1971,1959,1950,1945,1940,1932,1925,1918,1911,1903,1895,1889,1884,1879,1872,1864,
+1860,1859,1853,1838,1820,1813,1822,1840,1847,1834,1806,1779,1767,1767,1773,1779,1782,1779,1770,1756,1742,
+1729,1715,1693,1665,1639,1621,1612,1604,1594,1589,1598,1620,1642,1651,1649,1649,1658,1675,1678,1697,1705,
+1709,1716,1729,1745,1757,1766,1773,1778,1785,1797,1820,1851,1885,1915,1940,1966,1996,2026,2052,2073,2095,
+2122,2152,2183,2212,2242,2274,2301,2317,2322,2325,2332,2342,2347,2348,2352,2367,2393,2417,2433,2441,2451,
+2466,2483,2495,2501,2507,2519,2535,2551,2562,2571,2582,2594,2604,2610,2613,2616,2618,2617,2614,2615,2625,
+2645,2666,2681,2689,2698,2716,2738,2755,2756,2747,2743,2762,2812,2887,2969,3039,3073,3063,3013,2952,2909,
+2905,2929,2954,2955,2931,2896,2867,2850,2838,2830,2832,2849,2879,2912,2939,2958,2973,2984,2986,2975,2954,
+2932,2917,2909,2905,2904,2905,2908,2910,2909,2905,2901,2901,2904,2909,2916,2931,2957,2986,3008,3014,3010,
+3007,3015,3033,3055,3071,3081,3087,3090,3082,3056,3013,2963,2917,2881,2850,2819,2791,2774,2774,2789,2810,
+2830,2845,2860,2877,2894,2914,2937,2965,2992,3013,3024,3028,3033,3042,3053,3066,3083,3110,3148,3191,3236,
+3283,3341,3411,3483,3542,3582,3608,3629,3645,3649,3638,3623,3613,3613,3614,3612,3613,3622,3639,3651,3654,
+3659,3683,3726,3765,3777,3763,3749,3755,3770,3769,3741,3709,3698,3706,3704,3666,3608,3566,3557,3554,3521,
+3447,3363,3307,3285,3270,3235,3180,3121,3072,3027,2977,2927,2886,2853,2815,2758,2690,2628,2585,2555,2528,
+2502,2483,2476,2475,2467,2452,2434,2422,2415,2408,2401,2399,2405,2414,2417,2412,2406,2404,2408,2412,2413,
+2410,2404,2394,2377,2354,2329,2306,2282,2256,2227,2199,2177,2157,2134,2106,2075,2046,2019,1989,1957,1924,
+1893,1866,1838,1809,1777,1744,1713,1682,1652,1622,1592,1564,1538,1514,1491,1465,1435,1402,1372,1348,1329,
+1311,1291,1270,1253,1237,1220,1199,1180,1168,1161,1154,1140,1121,1104,1090,1078,1059,1033,1002,966,925,
+878,825,766,701,626,545,468,406,364,334,304,265,217,168,123,85,50,14,-23,-63,-104,
+-145,-188,-234,-282,-329,-369,-401,-432,-470,-518,-572,-625,-674,-721,-769,-816,-857,-896,-937,-984,-1035,
+-1083,-1127,-1170,-1216,-1264,-1311,-1354,-1396,-1442,-1492,-1540,-1583,-1623,-1664,-1711,-1760,-1808,-1855,-1902,-1951,-2001,
+-2051,-2100,-2147,-2193,-2238,-2282,-2326,-2373,-2420,-2466,-2507,-2544,-2579,-2615,-2652,-2691,-2728,-2764,-2796,-2825,-2855,
+-2891,-2934,-2980,-3022,-3057,-3087,-3118,-3151,-3186,-3221,-3254,-3286,-3317,-3347,-3375,-3402,-3427,-3451,-3472,-3491,-3512,
+-3538,-3566,-3588,-3599,-3603,-3611,-3631,-3662,-3696,-3726,-3756,-3787,-3812,-3819,-3801,-3771,-3755,-3772,-3819,-3872,-3908,
+-3917,-3912,-3909,-3915,-3932,-3949,-3960,-3960,-3949,-3936,-3929,-3930,-3933,-3929,-3912,-3890,-3872,-3865,-3862,-3859,-3857,
+-3861,-3877,-3897,-3911,-3910,-3899,-3885,-3876,-3871,-3870,-3870,-3874,-3879,-3880,-3872,-3853,-3827,-3799,-3773,-3748,-3725,
+-3705,-3689,-3674,-3658,-3637,-3612,-3584,-3558,-3534,-3512,-3491,-3470,-3450,-3431,-3409,-3380,-3345,-3308,-3277,-3256,-3242,
+-3228,-3207,-3176,-3137,-3097,-3061,-3032,-3008,-2983,-2955,-2926,-2899,-2876,-2852,-2824,-2791,-2759,-2732,-2709,-2687,-2659,
+-2628,-2599,-2573,-2545,-2509,-2461,-2402,-2336,-2269,-2207,-2158,-2122,-2090,-2042,-1961,-1846,-1708,-1565,-1424,-1285,-1145,
+-1007,-880,-774,-695,-640,-602,-572,-534,-482,-414,-343,-277,-219,-162,-99,-28,42,107,166,222,275,
+321,356,386,419,461,511,558,594,621,648,683,726,774,822,873,936,1021,1124,1227,1310,1366,
+1406,1446,1490,1526,1539,1530,1507,1472,1408,1287,1106,900,727,634,621,655,696,725,750,783,826,
+868,899,922,948,984,1026,1060,1078,1090,1118,1180,1265,1337,1359,1325,1263,1214,1204,1223,1246,1255,
+1251,1246,1250,1260,1272,1286,1305,1336,1374,1416,1455,1490,1525,1564,1610,1659,1704,1742,1770,1796,1827,
+1866,1913,1968,2029,2092,2151,2199,2233,2259,2284,2311,2341,2372,2405,2442,2478,2502,2512,2514,2521,2543,
+2578,2617,2654,2689,2725,2759,2782,2790,2787,2781,2780,2784,2795,2815,2846,2886,2930,2975,3025,3089,3166,
+3245,3313,3364,3401,3432,3453,3454,3430,3385,3330,3272,3204,3116,2997,2849,2682,2515,2376,2290,2269,2292,
+2310,2271,2162,2019,1907,1877,1932,2032,2129,2197,2242,2279,2311,2337,2349,2351,2348,2341,2321,2283,2231,
+2176,2125,2078,2032,1984,1936,1893,1854,1820,1788,1759,1727,1687,1641,1604,1589,1589,1581,1543,1485,1444,
+1451,1493,1519,1481,1384,1283,1230,1232,1251,1247,1213,1173,1151,1141,1125,1094,1058,1028,1002,965,910,
+851,810,795,792,777,743,700,663,639,623,606,586,564,544,527,515,504,489,465,429,389,
+357,338,328,315,291,254,213,175,145,121,99,76,52,25,0,-23,-47,-73,-98,-121,-138,
+-151,-169,-194,-224,-252,-271,-285,-301,-325,-356,-388,-416,-437,-455,-470,-484,-497,-510,-524,-540,-554,
+-567,-580,-595,-612,-629,-646,-661,-678,-695,-714,-732,-748,-761,-771,-780,-793,-810,-831,-851,-867,-880,
+-894,-911,-928,-941,-948,-955,-964,-975,-982,-984,-982,-983,-986,-989,-991,-994,-1001,-1013,-1025,-1032,-1035,
+-1038,-1043,-1049,-1053,-1052,-1050,-1053,-1062,-1074,-1089,-1104,-1120,-1135,-1149,-1158,-1165,-1171,-1177,-1183,-1188,-1192,
+-1192,-1189,-1183,-1176,-1173,-1173,-1175,-1177,-1177,-1176,-1175,-1173,-1170,-1169,-1169,-1172,-1176,-1180,-1183,-1183,-1181,
+-1177,-1172,-1166,-1158,-1148,-1139,-1136,-1143,-1156,-1165,-1166,-1162,-1160,-1165,-1172,-1174,-1170,-1166,-1167,-1168,-1163,
+-1154,-1151,-1164,-1190,-1214,-1222,-1217,-1212,-1215,-1226,-1234,-1235,-1235,-1238,-1241,-1236,-1223,-1210,-1204,-1210,-1219,
+-1223,-1219,-1211,-1205,-1201,-1197,-1194,-1189,-1181,-1169,-1156,-1145,-1139,-1134,-1124,-1107,-1088,-1071,-1063,-1060,-1058,
+-1053,-1044,-1034,-1024,-1014,-1008,-1004,-1002,-999,-994,-988,-983,-982,-982,-982,-981,-980,-980,-980,-978,-971,
+-960,-947,-934,-924,-916,-907,-897,-885,-873,-861,-850,-839,-827,-818,-811,-806,-798,-785,-765,-744,-723,
+-706,-692,-679,-667,-655,-642,-631,-622,-614,-604,-593,-581,-572,-564,-552,-532,-505,-479,-461,-453,-449,
+-440,-426,-410,-395,-381,-364,-345,-327,-313,-303,-295,-289,-287,-289,-290,-286,-279,-271,-270,-273,-275,
+-272,-264,-257,-254,-254,-253,-247,-239,-230,-221,-211,-201,-191,-178,-162,-141,-115,-91,-73,-59,-43,
+-23,1,27,51,73,94,118,144,172,203,236,269,301,331,360,392,425,458,489,517,547,
+578,608,636,660,685,716,751,786,817,846,874,905,936,966,1000,1041,1084,1119,1138,1143,1145,
+1143,1123,1067,981,902,886,972,1162,1415,1674,1884,2015,2064,2060,2050,2078,2162,2284,2413,2520,2591,
+2626,2629,2604,2560,2507,2450,2386,2311,2227,2140,2057,1983,1920,1872,1843,1832,1827,1815,1793,1773,1764,
+1765,1763,1749,1726,1709,1707,1715,1718,1709,1687,1666,1653,1654,1663,1673,1679,1682,1684,1686,1691,1695,
+1695,1689,1676,1657,1633,1605,1578,1553,1533,1518,1509,1503,1493,1468,1416,1338,1243,1152,1079,1031,1002,
+982,959,925,872,796,704,605,516,443,386,334,277,210,136,61,-6,-66,-116,-161,-202,-242,
+-279,-308,-330,-349,-369,-394,-422,-445,-461,-472,-485,-500,-515,-525,-531,-539,-551,-566,-578,-586,-593,
+-606,-624,-641,-652,-659,-669,-683,-699,-710,-715,-717,-717,-716,-711,-703,-694,-689,-686,-682,-675,-666,
+-659,-653,-647,-637,-624,-608,-590,-567,-538,-506,-473,-442,-411,-377,-336,-292,-247,-205,-165,-127,-90,
+-54,-21,13,53,100,152,204,249,286,316,346,380,423,473,525,573,615,651,686,727,772,
+818,859,895,931,971,1016,1061,1103,1140,1177,1214,1251,1288,1322,1354,1386,1418,1451,1484,1517,1547,
+1574,1599,1621,1641,1658,1673,1690,1710,1736,1764,1790,1811,1832,1857,1888,1919,1943,1959,1973,1993,2020,
+2048,2068,2074,2070,2064,2058,2054,2047,2040,2036,2037,2039,2041,2040,2038,2033,2024,2009,1995,1989,1995,
+2006,2010,1998,1973,1948,1932,1927,1927,1925,1920,1913,1906,1902,1900,1897,1889,1875,1862,1857,1861,1868,
+1865,1850,1828,1808,1798,1798,1806,1815,1819,1810,1790,1768,1753,1743,1727,1697,1659,1632,1627,1637,1638,
+1621,1595,1583,1593,1614,1630,1636,1642,1656,1678,1673,1691,1698,1699,1705,1720,1739,1753,1760,1764,1770,
+1779,1794,1817,1848,1882,1915,1943,1970,2000,2030,2058,2081,2103,2127,2155,2184,2213,2241,2267,2288,2303,
+2311,2318,2327,2334,2337,2336,2337,2349,2373,2399,2419,2432,2442,2455,2469,2482,2491,2500,2512,2528,2547,
+2568,2589,2607,2619,2621,2618,2618,2623,2630,2631,2624,2618,2624,2646,2673,2692,2697,2698,2708,2726,2741,
+2740,2725,2714,2726,2769,2830,2889,2925,2929,2903,2863,2831,2833,2875,2937,2985,2989,2948,2886,2834,2808,
+2809,2827,2856,2894,2936,2973,2999,3014,3022,3027,3025,3014,2997,2979,2963,2952,2946,2944,2948,2956,2962,
+2961,2953,2942,2933,2928,2928,2937,2958,2988,3018,3035,3034,3022,3015,3022,3039,3060,3077,3089,3098,3101,
+3092,3065,3024,2980,2942,2912,2885,2857,2832,2820,2823,2839,2859,2877,2892,2909,2929,2952,2977,3005,3034,
+3062,3083,3094,3100,3107,3119,3134,3149,3166,3190,3224,3264,3306,3352,3408,3474,3542,3598,3636,3660,3676,
+3688,3692,3685,3676,3670,3672,3676,3678,3684,3699,3719,3735,3745,3760,3791,3834,3866,3869,3850,3834,3838,
+3852,3848,3820,3787,3770,3765,3744,3690,3624,3584,3583,3590,3561,3485,3395,3330,3302,3286,3252,3197,3136,
+3085,3043,3001,2958,2918,2878,2829,2764,2693,2633,2595,2573,2554,2533,2516,2508,2502,2492,2475,2457,2444,
+2436,2429,2422,2419,2423,2430,2432,2427,2421,2419,2421,2424,2424,2421,2415,2403,2384,2363,2343,2325,2306,
+2281,2253,2226,2206,2190,2171,2147,2120,2093,2067,2039,2007,1974,1942,1912,1882,1850,1816,1785,1755,1725,
+1693,1661,1629,1600,1575,1552,1529,1502,1473,1442,1415,1392,1372,1351,1330,1308,1289,1271,1253,1235,1223,
+1215,1209,1197,1178,1160,1150,1145,1139,1122,1095,1063,1029,989,938,874,800,719,637,560,497,453,
+424,398,362,315,264,220,184,151,115,75,33,-7,-48,-91,-136,-181,-224,-264,-300,-334,-371,
+-413,-460,-511,-563,-613,-663,-711,-755,-796,-836,-880,-928,-978,-1024,-1067,-1111,-1160,-1210,-1255,-1294,-1331,
+-1374,-1424,-1476,-1523,-1566,-1606,-1650,-1695,-1742,-1789,-1839,-1890,-1942,-1991,-2038,-2086,-2135,-2184,-2230,-2274,-2319,
+-2367,-2415,-2460,-2499,-2535,-2570,-2605,-2640,-2677,-2714,-2750,-2785,-2819,-2854,-2892,-2931,-2970,-3005,-3037,-3069,-3102,
+-3135,-3169,-3203,-3237,-3273,-3307,-3337,-3363,-3387,-3410,-3429,-3445,-3458,-3470,-3483,-3496,-3510,-3527,-3552,-3583,-3615,
+-3642,-3662,-3681,-3704,-3726,-3739,-3737,-3731,-3737,-3765,-3808,-3846,-3863,-3860,-3848,-3843,-3851,-3867,-3887,-3901,-3906,
+-3900,-3890,-3882,-3883,-3887,-3888,-3880,-3865,-3850,-3839,-3833,-3828,-3828,-3837,-3857,-3880,-3894,-3893,-3881,-3865,-3854,
+-3847,-3845,-3843,-3839,-3831,-3815,-3793,-3767,-3744,-3727,-3711,-3695,-3677,-3659,-3644,-3632,-3618,-3598,-3572,-3544,-3519,
+-3498,-3479,-3459,-3437,-3416,-3397,-3376,-3351,-3319,-3285,-3256,-3235,-3221,-3205,-3180,-3145,-3104,-3066,-3036,-3014,-2995,
+-2972,-2942,-2908,-2877,-2851,-2828,-2803,-2774,-2744,-2717,-2693,-2668,-2638,-2603,-2568,-2535,-2501,-2465,-2425,-2379,-2329,
+-2274,-2217,-2165,-2123,-2088,-2049,-1994,-1917,-1823,-1718,-1605,-1481,-1347,-1208,-1075,-956,-858,-781,-724,-679,-633,
+-576,-505,-429,-358,-295,-234,-165,-87,-6,71,142,207,264,311,348,378,411,452,500,549,590,
+619,643,668,703,751,810,878,958,1050,1148,1239,1303,1335,1344,1351,1368,1391,1407,1410,1399,1370,
+1305,1182,1002,802,640,558,555,593,631,655,674,706,753,800,834,855,877,911,955,994,1017,
+1029,1050,1097,1163,1221,1241,1216,1169,1134,1130,1152,1176,1187,1185,1181,1185,1195,1209,1222,1238,1262,
+1295,1333,1369,1400,1431,1468,1515,1568,1617,1655,1684,1716,1759,1813,1871,1925,1975,2025,2074,2117,2150,
+2176,2201,2233,2270,2312,2357,2405,2451,2486,2502,2505,2508,2521,2544,2570,2592,2612,2635,2664,2694,2719,
+2736,2744,2745,2743,2743,2754,2780,2819,2861,2901,2944,3001,3076,3158,3231,3285,3321,3346,3359,3356,3331,
+3290,3241,3185,3113,3008,2861,2676,2474,2286,2148,2085,2094,2142,2174,2148,2063,1964,1912,1940,2032,2140,
+2222,2268,2291,2310,2325,2330,2323,2312,2305,2298,2279,2237,2180,2120,2068,2021,1974,1927,1882,1842,1804,
+1764,1723,1688,1657,1624,1584,1546,1525,1521,1517,1488,1437,1396,1399,1443,1480,1462,1381,1279,1207,1181,
+1178,1167,1142,1121,1118,1122,1111,1076,1033,996,966,928,874,816,776,761,759,746,713,670,632,
+609,597,587,571,550,528,509,497,489,481,465,437,402,367,340,321,306,287,260,225,186,
+150,120,97,76,54,29,3,-20,-44,-71,-99,-125,-145,-160,-178,-204,-235,-264,-284,-296,-310,
+-330,-357,-386,-413,-439,-464,-488,-508,-524,-539,-555,-569,-582,-593,-604,-616,-629,-640,-650,-662,-678,
+-698,-720,-742,-760,-775,-785,-794,-806,-823,-844,-865,-883,-897,-911,-927,-944,-957,-964,-969,-977,-988,
+-998,-1002,-1003,-1004,-1006,-1008,-1009,-1012,-1018,-1030,-1041,-1048,-1052,-1055,-1062,-1070,-1075,-1075,-1072,-1072,-1077,
+-1087,-1098,-1111,-1124,-1137,-1149,-1160,-1168,-1174,-1179,-1185,-1191,-1199,-1203,-1202,-1194,-1184,-1176,-1172,-1172,-1174,
+-1175,-1175,-1176,-1177,-1178,-1179,-1180,-1182,-1186,-1190,-1193,-1194,-1191,-1184,-1176,-1169,-1163,-1157,-1150,-1145,-1146,
+-1155,-1167,-1179,-1185,-1186,-1180,-1170,-1162,-1162,-1175,-1196,-1212,-1212,-1200,-1193,-1202,-1223,-1241,-1242,-1230,-1217,
+-1215,-1223,-1233,-1242,-1251,-1259,-1262,-1254,-1238,-1222,-1216,-1221,-1230,-1233,-1231,-1225,-1218,-1211,-1204,-1197,-1192,
+-1186,-1176,-1164,-1152,-1145,-1141,-1134,-1120,-1101,-1084,-1074,-1070,-1067,-1060,-1050,-1037,-1024,-1013,-1005,-1000,-997,
+-995,-991,-986,-983,-982,-983,-983,-984,-985,-986,-986,-983,-976,-965,-953,-941,-930,-920,-910,-901,-893,
+-885,-877,-869,-860,-851,-843,-835,-825,-812,-795,-775,-753,-733,-717,-705,-696,-685,-671,-654,-639,-627,
+-618,-605,-587,-567,-551,-542,-533,-518,-494,-468,-450,-442,-438,-432,-420,-405,-393,-382,-370,-354,-338,
+-322,-308,-296,-288,-285,-287,-288,-285,-278,-271,-269,-270,-269,-263,-254,-248,-246,-245,-241,-233,-225,
+-220,-214,-206,-197,-188,-179,-165,-143,-116,-90,-71,-57,-43,-22,3,30,54,75,97,121,148,
+176,205,236,268,298,326,355,387,421,452,480,508,538,571,602,628,651,677,709,745,777,
+802,827,854,887,920,952,987,1027,1067,1096,1110,1113,1116,1115,1092,1032,947,883,896,1019,1241,
+1512,1770,1963,2064,2081,2055,2041,2084,2187,2320,2442,2529,2577,2592,2577,2534,2472,2406,2347,2292,2233,
+2163,2087,2011,1939,1874,1821,1788,1775,1772,1763,1743,1721,1710,1713,1717,1711,1697,1685,1684,1691,1692,
+1679,1656,1634,1622,1620,1625,1633,1642,1651,1659,1667,1674,1682,1687,1686,1676,1658,1635,1609,1583,1556,
+1530,1504,1481,1460,1438,1407,1361,1297,1221,1144,1076,1023,982,948,912,867,805,721,618,510,418,
+353,313,278,231,166,92,22,-36,-86,-133,-178,-220,-254,-282,-306,-328,-349,-370,-392,-413,-432,
+-448,-462,-477,-494,-510,-523,-531,-538,-548,-561,-572,-582,-591,-604,-621,-638,-651,-661,-673,-687,-701,
+-712,-717,-718,-716,-713,-708,-701,-695,-690,-687,-681,-674,-666,-657,-648,-636,-624,-611,-599,-583,-560,
+-531,-500,-473,-448,-419,-382,-337,-290,-244,-202,-163,-123,-85,-49,-17,14,51,95,145,196,245,
+288,327,367,410,458,507,554,595,629,662,696,734,776,817,855,892,932,975,1022,1067,1109,
+1146,1182,1217,1252,1285,1317,1347,1378,1413,1450,1486,1520,1550,1576,1599,1620,1639,1657,1674,1695,1721,
+1753,1786,1814,1838,1859,1883,1910,1937,1958,1974,1988,2009,2036,2063,2082,2091,2091,2089,2084,2078,2071,
+2065,2064,2067,2071,2073,2073,2072,2066,2054,2036,2024,2031,2058,2090,2102,2079,2031,1980,1950,1944,1952,
+1959,1957,1951,1946,1945,1943,1939,1931,1924,1923,1925,1925,1916,1898,1878,1862,1853,1849,1846,1844,1842,
+1836,1821,1800,1784,1780,1782,1771,1739,1698,1677,1690,1717,1725,1694,1640,1597,1586,1600,1618,1627,1635,
+1650,1673,1656,1675,1686,1692,1703,1721,1739,1749,1752,1755,1766,1781,1800,1822,1851,1886,1923,1955,1982,
+2007,2034,2062,2087,2110,2131,2153,2177,2200,2222,2243,2263,2281,2294,2305,2313,2317,2319,2318,2320,2330,
+2350,2375,2398,2416,2430,2444,2459,2473,2486,2498,2512,2530,2553,2580,2608,2629,2638,2633,2621,2612,2614,
+2622,2628,2629,2629,2638,2659,2684,2701,2707,2708,2715,2728,2738,2734,2719,2708,2716,2743,2777,2800,2804,
+2793,2779,2774,2790,2834,2900,2967,3005,2993,2938,2867,2813,2796,2811,2846,2890,2935,2978,3012,3034,3043,
+3046,3047,3048,3045,3038,3026,3012,2999,2992,2993,3001,3013,3019,3016,3004,2987,2971,2959,2954,2960,2980,
+3009,3036,3051,3051,3043,3038,3042,3054,3069,3087,3105,3121,3128,3118,3091,3052,3013,2979,2948,2919,2891,
+2870,2862,2869,2887,2907,2927,2945,2965,2988,3012,3037,3066,3099,3130,3154,3169,3178,3187,3201,3218,3235,
+3254,3276,3305,3341,3381,3427,3480,3540,3598,3646,3679,3700,3715,3727,3734,3735,3734,3735,3738,3741,3746,
+3758,3778,3803,3823,3839,3858,3889,3924,3943,3934,3910,3897,3904,3918,3913,3885,3855,3840,3829,3793,3719,
+3632,3576,3568,3579,3564,3503,3421,3356,3321,3298,3264,3212,3158,3113,3076,3037,2992,2944,2894,2839,2775,
+2711,2659,2626,2605,2586,2566,2548,2537,2527,2513,2493,2475,2462,2455,2449,2443,2439,2440,2443,2444,2440,
+2435,2431,2430,2431,2431,2429,2423,2411,2393,2375,2359,2347,2332,2309,2282,2257,2239,2225,2209,2188,2163,
+2137,2112,2086,2056,2025,1993,1961,1927,1891,1856,1825,1796,1767,1734,1700,1668,1639,1614,1591,1565,1538,
+1509,1481,1454,1430,1407,1384,1363,1343,1324,1307,1290,1276,1267,1261,1251,1235,1216,1205,1207,1213,1212,
+1195,1165,1131,1094,1049,988,911,824,738,660,595,546,513,487,457,414,362,314,278,250,221,
+183,138,94,51,9,-35,-82,-125,-162,-196,-231,-270,-312,-357,-403,-451,-502,-554,-605,-653,-696,
+-737,-780,-826,-875,-921,-963,-1004,-1050,-1103,-1155,-1201,-1238,-1271,-1309,-1357,-1411,-1463,-1509,-1551,-1592,-1634,
+-1679,-1728,-1780,-1833,-1884,-1930,-1975,-2023,-2073,-2123,-2170,-2214,-2258,-2305,-2353,-2399,-2441,-2480,-2515,-2549,-2583,
+-2617,-2655,-2694,-2735,-2773,-2810,-2845,-2881,-2917,-2953,-2987,-3022,-3057,-3090,-3122,-3152,-3184,-3218,-3252,-3281,-3306,
+-3328,-3352,-3377,-3400,-3418,-3429,-3437,-3447,-3463,-3486,-3514,-3543,-3567,-3584,-3595,-3605,-3617,-3631,-3643,-3655,-3672,
+-3700,-3735,-3767,-3782,-3780,-3769,-3762,-3767,-3780,-3797,-3812,-3824,-3833,-3836,-3834,-3831,-3830,-3833,-3837,-3837,-3832,
+-3823,-3810,-3797,-3786,-3782,-3789,-3806,-3824,-3834,-3831,-3817,-3799,-3785,-3778,-3776,-3776,-3772,-3759,-3734,-3704,-3676,
+-3659,-3652,-3649,-3641,-3626,-3609,-3594,-3582,-3570,-3554,-3531,-3506,-3483,-3465,-3449,-3431,-3410,-3386,-3363,-3341,-3319,
+-3295,-3270,-3246,-3226,-3209,-3190,-3163,-3127,-3088,-3051,-3024,-3005,-2987,-2965,-2935,-2901,-2870,-2842,-2818,-2792,-2764,
+-2735,-2709,-2684,-2657,-2625,-2591,-2554,-2518,-2481,-2443,-2404,-2365,-2324,-2278,-2227,-2175,-2128,-2085,-2039,-1984,-1919,
+-1848,-1774,-1697,-1609,-1508,-1399,-1288,-1180,-1078,-984,-900,-825,-754,-678,-596,-512,-436,-369,-305,-234,-153,
+-64,26,111,188,251,300,336,364,396,437,487,538,582,612,630,647,676,727,800,886,975,
+1060,1134,1191,1221,1224,1213,1207,1216,1236,1256,1265,1262,1242,1189,1081,917,728,570,487,481,519,
+562,590,611,643,688,733,765,784,803,835,878,922,951,966,980,1007,1046,1083,1098,1088,1066,
+1054,1063,1088,1111,1120,1116,1109,1110,1123,1142,1163,1182,1202,1225,1252,1280,1307,1338,1378,1428,1480,
+1525,1555,1580,1616,1675,1752,1830,1894,1942,1980,2015,2046,2071,2090,2111,2142,2184,2234,2290,2347,2402,
+2446,2477,2495,2510,2527,2546,2558,2561,2559,2563,2577,2603,2633,2662,2683,2695,2698,2697,2704,2725,2756,
+2790,2822,2859,2912,2985,3068,3141,3194,3226,3244,3254,3252,3233,3197,3149,3089,3012,2904,2754,2565,2357,
+2166,2029,1971,1986,2036,2069,2053,1997,1945,1944,2009,2115,2215,2279,2307,2318,2324,2326,2316,2297,2278,
+2266,2257,2235,2190,2130,2069,2014,1965,1915,1867,1825,1790,1753,1709,1661,1620,1591,1565,1531,1492,1462,
+1451,1444,1417,1367,1321,1316,1360,1419,1439,1394,1305,1214,1147,1104,1072,1053,1054,1073,1090,1080,1041,
+991,951,923,892,845,791,750,732,727,717,687,646,607,583,571,563,551,533,513,495,483,
+477,470,459,439,412,381,350,323,301,280,257,228,193,156,124,99,78,55,29,3,-21,
+-45,-73,-103,-132,-154,-170,-187,-212,-243,-272,-293,-308,-321,-339,-360,-383,-407,-434,-464,-495,-522,
+-544,-562,-580,-597,-610,-621,-630,-640,-649,-658,-665,-674,-687,-704,-724,-745,-766,-786,-803,-816,-830,
+-846,-867,-886,-902,-914,-926,-942,-960,-974,-981,-986,-994,-1006,-1018,-1025,-1027,-1027,-1027,-1029,-1030,-1033,
+-1039,-1048,-1057,-1062,-1065,-1069,-1076,-1085,-1091,-1093,-1092,-1091,-1095,-1102,-1110,-1120,-1129,-1140,-1150,-1160,-1168,
+-1174,-1177,-1180,-1185,-1192,-1200,-1202,-1199,-1191,-1183,-1178,-1176,-1175,-1174,-1175,-1178,-1183,-1188,-1190,-1191,-1191,
+-1192,-1196,-1201,-1203,-1201,-1194,-1185,-1178,-1175,-1173,-1171,-1168,-1168,-1172,-1181,-1189,-1194,-1191,-1180,-1165,-1155,
+-1160,-1181,-1211,-1234,-1239,-1231,-1223,-1228,-1244,-1257,-1257,-1244,-1230,-1224,-1227,-1236,-1249,-1263,-1274,-1276,-1266,
+-1250,-1237,-1233,-1237,-1242,-1242,-1239,-1236,-1232,-1225,-1215,-1204,-1197,-1191,-1182,-1168,-1153,-1142,-1136,-1132,-1124,
+-1111,-1098,-1089,-1083,-1077,-1067,-1055,-1041,-1027,-1014,-1003,-996,-993,-990,-988,-986,-983,-982,-982,-983,-986,
+-988,-990,-989,-985,-978,-969,-960,-952,-943,-932,-921,-911,-902,-894,-885,-877,-869,-861,-852,-842,-830,
+-815,-800,-785,-770,-756,-744,-735,-727,-719,-705,-688,-670,-655,-642,-625,-601,-574,-552,-539,-531,-518,
+-497,-472,-452,-441,-434,-426,-414,-401,-390,-382,-373,-361,-346,-330,-314,-299,-288,-283,-283,-283,-279,
+-271,-264,-262,-262,-259,-252,-244,-239,-236,-231,-222,-211,-205,-202,-199,-192,-183,-175,-169,-162,-146,
+-123,-100,-81,-66,-50,-28,-2,21,43,65,90,119,149,177,204,234,263,292,318,347,379,
+412,443,470,497,528,561,590,614,635,660,693,727,756,778,802,834,871,907,939,972,1010,
+1047,1073,1086,1091,1097,1096,1069,1002,917,866,906,1062,1312,1599,1855,2031,2103,2090,2044,2031,2088,
+2210,2350,2463,2530,2556,2554,2528,2478,2412,2346,2289,2238,2179,2106,2025,1948,1883,1828,1782,1751,1736,
+1727,1713,1690,1667,1657,1663,1672,1672,1663,1656,1659,1668,1670,1658,1638,1619,1605,1596,1592,1593,1600,
+1611,1620,1629,1637,1649,1660,1664,1658,1644,1629,1614,1598,1575,1545,1509,1470,1430,1387,1341,1292,1242,
+1190,1138,1083,1025,963,900,835,770,699,613,512,408,320,265,237,216,180,123,55,-6,-57,
+-103,-149,-195,-234,-261,-282,-303,-328,-352,-372,-388,-403,-420,-437,-454,-471,-487,-504,-518,-530,-539,
+-549,-562,-576,-589,-600,-611,-624,-638,-652,-664,-675,-688,-700,-709,-714,-716,-714,-709,-703,-696,-691,
+-686,-680,-675,-670,-665,-657,-643,-625,-608,-595,-585,-571,-548,-517,-489,-467,-450,-427,-393,-350,-303,
+-257,-213,-170,-127,-86,-48,-13,21,58,98,141,187,234,280,326,374,425,479,531,575,611,
+640,669,703,742,785,829,871,914,958,1002,1046,1087,1125,1160,1194,1226,1256,1285,1313,1343,1375,
+1411,1449,1486,1518,1545,1569,1592,1616,1641,1667,1693,1720,1752,1786,1819,1848,1871,1891,1911,1932,1953,
+1972,1989,2008,2031,2058,2084,2103,2114,2119,2119,2116,2109,2101,2096,2096,2098,2101,2102,2103,2104,2100,
+2086,2067,2057,2072,2111,2154,2169,2139,2077,2015,1979,1976,1990,2002,2003,1997,1992,1990,1987,1979,1970,
+1968,1976,1986,1986,1970,1945,1923,1914,1915,1916,1907,1891,1871,1850,1826,1805,1793,1796,1803,1794,1763,
+1726,1716,1742,1780,1788,1745,1671,1609,1586,1595,1612,1620,1623,1635,1656,1644,1666,1681,1692,1706,1723,
+1736,1742,1744,1752,1770,1793,1815,1835,1861,1896,1935,1968,1991,2011,2032,2059,2087,2111,2131,2149,2166,
+2182,2198,2216,2237,2260,2280,2292,2297,2297,2297,2300,2307,2319,2335,2354,2376,2397,2417,2435,2453,2470,
+2486,2502,2519,2538,2561,2586,2610,2629,2639,2640,2634,2626,2619,2616,2619,2626,2638,2655,2674,2691,2704,
+2713,2722,2733,2742,2743,2733,2718,2708,2710,2723,2735,2741,2742,2747,2764,2795,2838,2888,2938,2975,2983,
+2956,2903,2848,2814,2813,2837,2875,2918,2960,3000,3033,3055,3064,3068,3070,3075,3078,3075,3067,3055,3045,
+3040,3043,3050,3058,3061,3057,3048,3037,3025,3013,3005,3005,3015,3033,3052,3063,3067,3066,3064,3066,3072,
+3086,3108,3137,3161,3170,3157,3126,3088,3052,3019,2986,2954,2925,2908,2904,2914,2932,2955,2979,3003,3026,
+3048,3069,3093,3122,3157,3192,3222,3245,3260,3273,3289,3307,3327,3347,3369,3394,3426,3464,3508,3558,3610,
+3658,3697,3727,3748,3763,3774,3781,3786,3790,3795,3799,3806,3819,3842,3873,3902,3921,3932,3946,3970,3994,
+4002,3988,3966,3958,3968,3978,3965,3935,3908,3900,3894,3855,3768,3661,3583,3559,3567,3560,3515,3444,3379,
+3337,3308,3273,3229,3183,3145,3110,3069,3020,2966,2911,2857,2801,2748,2703,2669,2643,2620,2598,2580,2566,
+2552,2533,2512,2494,2483,2477,2471,2463,2456,2454,2455,2455,2451,2446,2441,2439,2439,2439,2438,2434,2423,
+2407,2392,2380,2371,2358,2339,2314,2293,2277,2263,2247,2225,2200,2175,2152,2126,2098,2069,2039,2008,1974,
+1936,1901,1869,1841,1811,1777,1742,1709,1680,1654,1628,1601,1572,1544,1517,1490,1463,1436,1413,1392,1375,
+1359,1343,1329,1319,1311,1303,1289,1270,1257,1257,1271,1286,1285,1265,1231,1193,1151,1097,1024,935,845,
+765,700,649,609,577,546,509,461,411,368,338,314,285,245,198,153,110,66,20,-25,-65,
+-97,-128,-164,-208,-255,-302,-347,-394,-445,-497,-547,-592,-634,-677,-724,-773,-820,-863,-902,-942,-987,
+-1039,-1092,-1138,-1176,-1210,-1249,-1296,-1349,-1403,-1453,-1496,-1535,-1574,-1617,-1666,-1720,-1774,-1824,-1870,-1914,-1961,
+-2010,-2059,-2106,-2149,-2192,-2237,-2282,-2327,-2370,-2411,-2450,-2488,-2524,-2559,-2596,-2635,-2676,-2716,-2753,-2790,-2827,
+-2864,-2900,-2935,-2972,-3009,-3044,-3077,-3107,-3136,-3167,-3198,-3225,-3247,-3268,-3293,-3323,-3355,-3381,-3398,-3408,-3418,
+-3433,-3453,-3474,-3491,-3505,-3516,-3525,-3533,-3539,-3545,-3553,-3568,-3594,-3628,-3660,-3678,-3679,-3671,-3667,-3676,-3695,
+-3714,-3725,-3729,-3733,-3741,-3753,-3761,-3765,-3764,-3765,-3769,-3776,-3781,-3778,-3766,-3748,-3731,-3723,-3727,-3740,-3755,
+-3762,-3759,-3745,-3725,-3707,-3697,-3696,-3701,-3702,-3690,-3665,-3633,-3608,-3595,-3594,-3596,-3590,-3577,-3559,-3543,-3532,
+-3523,-3511,-3494,-3473,-3451,-3434,-3421,-3409,-3392,-3369,-3340,-3313,-3290,-3271,-3254,-3235,-3214,-3192,-3168,-3141,-3110,
+-3075,-3041,-3012,-2989,-2969,-2947,-2920,-2891,-2862,-2835,-2808,-2780,-2750,-2721,-2695,-2669,-2642,-2611,-2579,-2547,-2513,
+-2477,-2437,-2397,-2358,-2317,-2271,-2221,-2171,-2125,-2082,-2033,-1975,-1910,-1846,-1789,-1735,-1676,-1609,-1536,-1460,-1380,
+-1292,-1194,-1091,-987,-888,-792,-697,-604,-518,-440,-369,-296,-217,-130,-38,55,141,214,265,299,324,
+352,392,442,493,535,561,576,592,625,685,771,866,951,1014,1050,1063,1058,1042,1027,1025,1039,
+1063,1082,1093,1095,1086,1049,961,817,644,494,411,403,443,492,529,558,590,631,670,698,715,
+733,762,802,844,875,894,907,925,950,974,989,991,989,993,1008,1030,1047,1052,1045,1034,1032,
+1045,1071,1102,1127,1145,1159,1173,1193,1221,1258,1302,1352,1397,1430,1448,1467,1506,1577,1672,1770,1849,
+1903,1938,1964,1984,1997,2005,2018,2043,2085,2142,2207,2275,2338,2393,2438,2473,2504,2532,2552,2558,2552,
+2538,2526,2523,2530,2545,2567,2591,2612,2628,2639,2651,2669,2692,2716,2742,2778,2831,2903,2982,3050,3098,
+3127,3146,3159,3161,3145,3106,3048,2978,2897,2799,2672,2512,2330,2156,2027,1967,1969,2002,2023,2013,1983,
+1969,2001,2078,2174,2254,2299,2317,2322,2324,2320,2304,2277,2252,2234,2218,2191,2147,2089,2028,1968,1910,
+1852,1800,1758,1726,1691,1646,1596,1554,1527,1505,1477,1440,1409,1394,1385,1359,1305,1248,1227,1264,1334,
+1388,1385,1325,1237,1151,1082,1032,1004,1002,1019,1033,1021,981,932,894,871,850,817,772,731,708,
+699,689,666,630,593,565,547,535,521,505,488,476,470,467,461,450,433,413,390,363,334,
+305,278,252,225,194,160,128,101,77,51,24,-2,-25,-48,-75,-106,-136,-159,-177,-196,-221,
+-251,-277,-297,-312,-328,-348,-369,-388,-409,-434,-466,-500,-531,-556,-578,-600,-620,-637,-649,-658,-666,
+-673,-680,-686,-693,-703,-716,-730,-748,-770,-795,-820,-841,-859,-877,-896,-913,-925,-933,-941,-955,-972,
+-988,-998,-1005,-1014,-1027,-1039,-1047,-1048,-1047,-1047,-1049,-1051,-1053,-1057,-1062,-1069,-1075,-1079,-1083,-1089,-1095,
+-1100,-1103,-1104,-1105,-1109,-1115,-1122,-1130,-1139,-1147,-1155,-1162,-1167,-1171,-1172,-1172,-1175,-1181,-1190,-1196,-1196,
+-1193,-1188,-1185,-1183,-1181,-1177,-1175,-1176,-1182,-1189,-1193,-1193,-1192,-1193,-1197,-1203,-1208,-1208,-1204,-1198,-1193,
+-1192,-1192,-1193,-1195,-1198,-1201,-1204,-1204,-1200,-1192,-1181,-1169,-1163,-1167,-1182,-1202,-1218,-1222,-1219,-1217,-1224,
+-1240,-1254,-1259,-1255,-1247,-1240,-1238,-1243,-1254,-1268,-1281,-1283,-1274,-1261,-1251,-1249,-1250,-1248,-1242,-1237,-1236,
+-1235,-1230,-1220,-1208,-1201,-1197,-1191,-1178,-1161,-1146,-1138,-1133,-1126,-1117,-1106,-1097,-1088,-1079,-1067,-1054,-1042,
+-1029,-1016,-1004,-995,-990,-989,-989,-988,-986,-983,-981,-982,-985,-988,-990,-988,-983,-977,-971,-966,-961,
+-955,-947,-936,-925,-913,-902,-892,-882,-874,-865,-856,-845,-832,-818,-806,-796,-786,-776,-765,-756,-749,
+-742,-731,-717,-700,-684,-668,-649,-622,-592,-567,-550,-540,-528,-510,-487,-465,-449,-436,-423,-408,-393,
+-380,-370,-361,-349,-336,-321,-306,-292,-282,-277,-275,-271,-265,-256,-251,-249,-249,-245,-238,-232,-228,
+-224,-215,-203,-191,-185,-185,-183,-176,-166,-158,-154,-151,-141,-124,-104,-87,-70,-52,-29,-6,14,
+34,57,87,119,149,176,202,230,260,287,313,338,368,400,432,460,489,521,554,582,604,
+625,649,680,711,736,757,784,821,862,898,929,960,996,1032,1058,1072,1081,1091,1089,1056,982,
+897,858,921,1102,1371,1663,1908,2058,2100,2063,2011,2007,2083,2219,2361,2462,2511,2523,2516,2492,2447,
+2385,2322,2267,2212,2143,2056,1966,1891,1839,1802,1772,1745,1723,1702,1677,1647,1623,1616,1624,1634,1633,
+1624,1618,1625,1639,1647,1643,1628,1610,1593,1578,1566,1560,1561,1566,1570,1573,1581,1596,1613,1621,1618,
+1610,1604,1603,1598,1579,1544,1501,1454,1404,1348,1287,1230,1185,1153,1124,1083,1021,935,837,740,655,
+578,500,414,326,252,206,185,168,137,86,25,-30,-76,-120,-165,-209,-243,-265,-283,-304,-331,
+-356,-372,-382,-393,-409,-430,-449,-464,-478,-493,-508,-521,-533,-545,-561,-579,-595,-608,-618,-630,-642,
+-655,-667,-677,-686,-695,-703,-710,-713,-711,-705,-698,-690,-684,-678,-672,-667,-664,-662,-655,-640,-619,
+-600,-587,-577,-562,-537,-505,-476,-458,-445,-430,-404,-368,-326,-280,-232,-182,-133,-89,-50,-13,23,
+61,100,141,185,232,280,327,375,426,483,539,587,623,651,679,714,756,802,848,894,939,
+982,1024,1063,1099,1136,1172,1206,1237,1266,1293,1322,1353,1386,1421,1457,1492,1522,1547,1570,1596,1626,
+1659,1694,1727,1759,1791,1823,1851,1877,1898,1916,1934,1951,1969,1987,2007,2031,2057,2084,2108,2126,2140,
+2148,2151,2148,2142,2134,2130,2129,2130,2130,2130,2131,2133,2131,2118,2099,2088,2100,2134,2169,2179,2152,
+2098,2048,2023,2026,2041,2051,2049,2041,2036,2034,2030,2020,2008,2001,2005,2014,2016,2004,1983,1966,1961,
+1964,1962,1949,1926,1900,1873,1845,1818,1799,1792,1788,1771,1737,1704,1697,1724,1760,1764,1720,1650,1596,
+1581,1597,1615,1620,1619,1626,1644,1649,1669,1683,1692,1704,1718,1730,1737,1745,1761,1787,1815,1836,1853,
+1874,1906,1942,1972,1991,2006,2025,2051,2078,2102,2120,2136,2151,2165,2177,2193,2215,2242,2267,2281,2283,
+2279,2280,2289,2302,2316,2330,2346,2364,2386,2408,2431,2454,2476,2496,2512,2528,2543,2559,2574,2586,2600,
+2620,2646,2670,2678,2668,2646,2629,2630,2646,2668,2685,2694,2702,2715,2732,2746,2749,2739,2722,2706,2698,
+2700,2709,2721,2737,2761,2796,2837,2878,2910,2932,2944,2944,2931,2904,2871,2845,2836,2847,2872,2903,2938,
+2976,3015,3051,3077,3092,3100,3105,3109,3110,3107,3101,3094,3090,3089,3088,3087,3083,3080,3081,3084,3088,
+3088,3082,3072,3063,3062,3066,3074,3081,3087,3091,3092,3092,3095,3110,3141,3178,3205,3209,3188,3153,3117,
+3085,3054,3021,2988,2964,2953,2954,2963,2978,3000,3026,3054,3079,3100,3120,3144,3175,3211,3249,3284,3314,
+3338,3359,3378,3397,3419,3441,3464,3488,3517,3553,3595,3640,3684,3722,3756,3784,3806,3821,3828,3831,3836,
+3842,3849,3857,3871,3899,3941,3986,4016,4025,4020,4019,4032,4049,4054,4042,4027,4024,4031,4028,4001,3961,
+3935,3935,3938,3905,3819,3707,3617,3579,3577,3570,3531,3466,3401,3353,3319,3286,3248,3207,3170,3132,3090,
+3040,2987,2935,2884,2833,2785,2741,2705,2675,2651,2631,2615,2599,2581,2558,2536,2520,2511,2505,2496,2484,
+2474,2470,2469,2468,2464,2459,2454,2451,2450,2451,2451,2447,2437,2424,2411,2402,2395,2384,2368,2348,2331,
+2316,2302,2282,2258,2234,2211,2189,2165,2137,2109,2081,2052,2020,1985,1951,1919,1889,1856,1820,1783,1750,
+1721,1694,1666,1638,1609,1581,1553,1524,1494,1467,1444,1426,1410,1394,1379,1368,1361,1355,1345,1326,1307,
+1299,1310,1333,1350,1345,1318,1280,1240,1194,1133,1050,956,869,802,753,713,675,636,596,554,509,
+465,428,400,375,342,300,253,207,164,121,76,33,-3,-33,-64,-103,-149,-198,-245,-291,-338,
+-389,-439,-485,-527,-569,-615,-664,-712,-757,-798,-838,-879,-925,-973,-1021,-1065,-1105,-1144,-1186,-1234,-1287,
+-1342,-1392,-1436,-1475,-1512,-1553,-1601,-1655,-1710,-1763,-1811,-1857,-1903,-1950,-1998,-2043,-2087,-2130,-2174,-2217,-2259,
+-2301,-2344,-2388,-2431,-2471,-2508,-2544,-2581,-2620,-2657,-2695,-2733,-2772,-2810,-2845,-2879,-2914,-2952,-2990,-3026,-3059,
+-3089,-3119,-3150,-3178,-3201,-3223,-3248,-3280,-3313,-3341,-3360,-3372,-3384,-3398,-3414,-3426,-3434,-3441,-3449,-3460,-3470,
+-3477,-3480,-3484,-3496,-3518,-3544,-3564,-3574,-3574,-3575,-3587,-3611,-3638,-3657,-3661,-3656,-3653,-3659,-3672,-3686,-3694,
+-3695,-3694,-3699,-3709,-3718,-3719,-3708,-3691,-3675,-3669,-3675,-3690,-3705,-3715,-3714,-3701,-3680,-3658,-3643,-3641,-3648,
+-3652,-3643,-3620,-3591,-3570,-3561,-3561,-3561,-3553,-3537,-3518,-3502,-3490,-3482,-3473,-3460,-3441,-3419,-3401,-3390,-3384,
+-3376,-3357,-3327,-3293,-3263,-3243,-3228,-3212,-3190,-3164,-3138,-3113,-3088,-3060,-3028,-2996,-2969,-2946,-2925,-2902,-2877,
+-2850,-2822,-2793,-2762,-2732,-2705,-2679,-2653,-2625,-2595,-2566,-2537,-2507,-2472,-2433,-2391,-2349,-2304,-2255,-2202,-2154,
+-2114,-2079,-2040,-1990,-1932,-1874,-1822,-1774,-1724,-1671,-1617,-1568,-1516,-1450,-1362,-1255,-1141,-1032,-929,-831,-732,
+-632,-535,-445,-363,-286,-210,-127,-37,52,130,187,223,249,278,318,363,405,436,456,472,497,
+543,614,703,792,859,891,890,868,840,821,817,830,853,877,895,907,917,918,891,814,683,
+527,396,328,331,376,430,471,502,535,572,607,632,650,670,699,735,770,797,816,833,852,
+876,898,916,926,932,939,951,966,979,985,979,969,963,973,1000,1035,1066,1085,1095,1106,1124,
+1155,1194,1238,1279,1313,1334,1348,1368,1411,1486,1585,1688,1774,1835,1876,1903,1920,1928,1930,1936,1954,
+1992,2049,2120,2197,2270,2336,2391,2437,2477,2510,2534,2544,2542,2531,2516,2500,2484,2475,2476,2489,2512,
+2537,2560,2581,2600,2620,2642,2671,2711,2767,2836,2907,2968,3013,3046,3070,3086,3088,3066,3016,2944,2862,
+2778,2692,2593,2472,2333,2196,2090,2034,2022,2030,2032,2020,2010,2023,2070,2143,2216,2268,2296,2308,2314,
+2317,2310,2289,2256,2221,2192,2167,2140,2102,2053,1994,1930,1860,1791,1731,1687,1653,1619,1576,1529,1489,
+1462,1442,1417,1386,1360,1349,1343,1319,1265,1200,1161,1176,1231,1289,1311,1291,1246,1195,1145,1094,1043,
+1002,977,961,942,910,872,840,819,803,780,747,714,689,674,663,643,613,578,547,523,504,
+486,468,453,447,450,454,451,438,421,404,388,370,344,312,279,249,220,191,160,130,100,
+72,44,17,-7,-28,-49,-75,-105,-134,-158,-179,-202,-230,-259,-282,-297,-311,-329,-353,-377,-399,
+-419,-444,-474,-508,-538,-565,-590,-615,-640,-661,-676,-686,-694,-701,-707,-712,-718,-725,-734,-745,-758,
+-778,-804,-833,-859,-882,-903,-922,-938,-947,-952,-957,-968,-983,-999,-1011,-1022,-1033,-1047,-1058,-1064,-1064,
+-1062,-1063,-1067,-1070,-1071,-1071,-1073,-1078,-1085,-1092,-1098,-1103,-1107,-1109,-1109,-1111,-1114,-1119,-1126,-1134,-1143,
+-1153,-1161,-1166,-1170,-1173,-1176,-1177,-1177,-1178,-1181,-1186,-1190,-1191,-1189,-1187,-1188,-1189,-1186,-1180,-1174,-1171,
+-1174,-1182,-1188,-1191,-1192,-1194,-1199,-1206,-1212,-1215,-1215,-1214,-1212,-1211,-1209,-1210,-1213,-1219,-1224,-1224,-1218,
+-1207,-1197,-1191,-1187,-1186,-1185,-1187,-1191,-1195,-1197,-1198,-1203,-1214,-1229,-1244,-1255,-1260,-1260,-1257,-1252,-1252,
+-1258,-1270,-1282,-1286,-1281,-1271,-1263,-1260,-1257,-1250,-1241,-1236,-1235,-1235,-1230,-1219,-1208,-1203,-1201,-1197,-1187,
+-1173,-1160,-1150,-1142,-1132,-1119,-1106,-1096,-1086,-1076,-1064,-1053,-1043,-1032,-1020,-1007,-996,-992,-992,-994,-993,
+-990,-985,-982,-982,-984,-987,-988,-985,-981,-976,-971,-967,-963,-958,-952,-944,-935,-924,-912,-901,-890,
+-881,-872,-863,-853,-841,-828,-816,-806,-797,-786,-774,-762,-753,-745,-736,-726,-713,-699,-683,-663,-638,
+-609,-582,-562,-549,-537,-521,-500,-479,-459,-441,-424,-406,-389,-374,-360,-348,-334,-320,-306,-293,-283,
+-275,-269,-265,-258,-249,-241,-238,-238,-238,-234,-227,-220,-217,-214,-206,-194,-182,-175,-173,-171,-163,
+-152,-143,-138,-134,-124,-109,-93,-78,-63,-44,-22,-1,17,37,62,92,124,152,176,200,228,
+258,286,309,332,359,390,422,453,483,516,548,577,600,622,648,678,706,728,750,781,821,
+863,898,925,954,990,1026,1053,1069,1081,1092,1088,1049,971,887,860,940,1139,1413,1696,1918,2038,
+2056,2010,1967,1984,2080,2222,2355,2440,2476,2485,2482,2464,2422,2361,2296,2237,2179,2105,2016,1930,1867,
+1830,1809,1786,1758,1727,1694,1658,1621,1593,1584,1590,1597,1592,1578,1569,1576,1595,1613,1618,1610,1595,
+1578,1559,1543,1531,1524,1518,1509,1503,1507,1525,1545,1557,1556,1553,1558,1570,1575,1559,1523,1479,1435,
+1387,1327,1256,1190,1144,1121,1104,1070,1001,897,774,656,557,478,410,343,276,220,184,163,143,
+108,56,0,-51,-94,-134,-177,-216,-246,-267,-286,-309,-335,-357,-369,-375,-385,-404,-425,-445,-459,
+-471,-484,-499,-513,-525,-538,-555,-574,-593,-608,-621,-634,-648,-661,-672,-680,-686,-692,-700,-707,-712,
+-710,-703,-694,-685,-679,-674,-668,-663,-660,-659,-653,-641,-623,-605,-592,-580,-562,-535,-502,-473,-452,
+-438,-423,-403,-375,-341,-298,-246,-190,-136,-90,-51,-16,20,59,98,140,186,236,285,330,374,
+423,480,541,595,636,667,698,735,779,824,867,908,948,987,1025,1060,1097,1135,1174,1212,1246,
+1279,1310,1343,1376,1408,1441,1474,1506,1535,1562,1588,1617,1652,1689,1727,1762,1793,1821,1848,1872,1895,
+1916,1935,1953,1971,1988,2006,2028,2053,2080,2106,2129,2147,2162,2172,2177,2176,2170,2164,2161,2161,2162,
+2161,2160,2160,2162,2160,2151,2137,2125,2127,2141,2157,2159,2140,2109,2082,2072,2077,2087,2090,2085,2076,
+2072,2071,2070,2062,2047,2032,2022,2020,2020,2015,2005,1995,1987,1980,1970,1955,1938,1921,1902,1876,1843,
+1810,1783,1761,1733,1698,1664,1651,1663,1682,1680,1648,1604,1578,1584,1609,1627,1630,1627,1632,1649,1659,
+1674,1682,1686,1694,1709,1726,1740,1756,1778,1808,1835,1855,1868,1885,1912,1942,1967,1983,1998,2017,2041,
+2065,2083,2098,2114,2132,2150,2163,2177,2197,2224,2250,2265,2268,2266,2270,2283,2301,2317,2332,2347,2366,
+2387,2411,2436,2464,2491,2514,2528,2536,2544,2552,2558,2561,2571,2601,2652,2709,2742,2735,2698,2659,2645,
+2658,2681,2697,2701,2704,2715,2731,2740,2733,2713,2693,2683,2686,2698,2717,2743,2780,2827,2876,2915,2937,
+2940,2931,2920,2908,2896,2883,2870,2864,2867,2881,2901,2925,2955,2991,3032,3071,3103,3125,3138,3144,3145,
+3142,3138,3135,3135,3137,3136,3128,3114,3100,3095,3101,3118,3134,3143,3139,3128,3116,3107,3103,3104,3110,
+3118,3124,3125,3122,3123,3141,3174,3210,3230,3222,3194,3161,3133,3110,3083,3053,3025,3009,3006,3010,3016,
+3025,3041,3065,3092,3116,3138,3162,3192,3227,3265,3301,3338,3375,3410,3440,3462,3482,3503,3527,3552,3578,
+3606,3641,3680,3720,3754,3785,3813,3841,3864,3877,3882,3883,3887,3895,3903,3914,3936,3978,4037,4091,4118,
+4111,4087,4072,4076,4091,4098,4091,4081,4076,4073,4055,4014,3968,3942,3946,3952,3922,3841,3734,3647,3606,
+3598,3586,3546,3483,3419,3372,3339,3308,3273,3233,3191,3150,3108,3061,3013,2963,2912,2860,2811,2768,2733,
+2707,2687,2671,2656,2638,2614,2588,2566,2552,2544,2536,2523,2508,2496,2489,2488,2486,2482,2477,2472,2468,
+2466,2464,2463,2460,2452,2442,2433,2426,2420,2411,2398,2382,2368,2355,2339,2317,2293,2269,2249,2229,2205,
+2177,2148,2120,2093,2065,2033,2001,1969,1936,1900,1861,1823,1789,1761,1733,1705,1675,1647,1619,1589,1558,
+1528,1501,1482,1466,1450,1432,1416,1407,1404,1402,1390,1369,1349,1344,1360,1386,1401,1390,1356,1314,1271,
+1223,1156,1069,977,900,847,812,778,736,689,641,598,559,523,491,462,432,396,352,306,261,
+218,175,132,92,58,28,-5,-46,-93,-140,-187,-233,-282,-332,-378,-420,-461,-505,-554,-603,-647,
+-687,-726,-770,-817,-866,-912,-955,-996,-1037,-1079,-1123,-1171,-1223,-1277,-1328,-1373,-1411,-1449,-1490,-1537,-1591,
+-1646,-1699,-1749,-1797,-1844,-1890,-1936,-1981,-2026,-2071,-2115,-2158,-2200,-2242,-2286,-2331,-2375,-2416,-2454,-2491,-2528,
+-2566,-2603,-2640,-2679,-2718,-2756,-2791,-2823,-2857,-2893,-2932,-2970,-3003,-3034,-3064,-3096,-3127,-3155,-3181,-3208,-3237,
+-3267,-3291,-3308,-3322,-3337,-3355,-3372,-3384,-3390,-3394,-3401,-3412,-3422,-3429,-3432,-3436,-3445,-3459,-3475,-3488,-3498,
+-3507,-3522,-3545,-3572,-3597,-3611,-3615,-3611,-3609,-3614,-3625,-3637,-3644,-3646,-3647,-3652,-3660,-3666,-3665,-3654,-3639,
+-3629,-3629,-3642,-3660,-3677,-3688,-3689,-3678,-3657,-3633,-3618,-3615,-3622,-3624,-3613,-3590,-3565,-3549,-3545,-3544,-3539,
+-3526,-3508,-3488,-3472,-3458,-3448,-3438,-3426,-3408,-3385,-3364,-3352,-3349,-3348,-3336,-3309,-3272,-3237,-3213,-3199,-3184,
+-3163,-3137,-3113,-3092,-3072,-3047,-3016,-2983,-2954,-2932,-2913,-2892,-2866,-2837,-2808,-2779,-2751,-2724,-2699,-2674,-2647,
+-2617,-2585,-2555,-2527,-2497,-2462,-2423,-2381,-2339,-2295,-2245,-2192,-2145,-2109,-2083,-2056,-2020,-1975,-1927,-1880,-1831,
+-1778,-1722,-1671,-1630,-1593,-1544,-1471,-1375,-1271,-1172,-1083,-996,-901,-792,-676,-563,-463,-380,-307,-235,-155,
+-71,7,68,113,150,188,230,268,296,312,325,347,386,444,518,598,667,710,716,690,652,
+621,612,624,648,671,685,694,707,726,737,715,640,516,382,283,249,274,327,378,414,442,
+474,509,542,567,588,613,645,679,708,728,743,759,779,802,826,846,859,867,871,877,888,
+903,915,919,914,909,914,935,966,997,1020,1035,1049,1071,1101,1137,1172,1202,1226,1245,1265,1294,
+1343,1413,1499,1589,1670,1735,1785,1821,1844,1856,1861,1866,1882,1914,1966,2037,2118,2200,2274,2336,2386,
+2427,2461,2488,2507,2518,2519,2509,2489,2460,2432,2415,2413,2426,2447,2469,2491,2513,2539,2570,2609,2656,
+2711,2771,2830,2884,2932,2973,3003,3019,3012,2978,2920,2843,2758,2671,2587,2499,2403,2303,2212,2145,2107,
+2090,2076,2058,2043,2047,2080,2137,2198,2246,2274,2287,2294,2300,2300,2287,2259,2219,2174,2132,2099,2072,
+2043,2006,1954,1887,1809,1733,1668,1619,1581,1544,1503,1459,1421,1394,1372,1351,1328,1312,1306,1302,1282,
+1234,1171,1122,1107,1124,1151,1173,1188,1208,1234,1244,1215,1139,1039,949,891,863,848,831,807,783,
+762,741,718,693,670,651,635,614,585,551,518,493,473,455,435,420,415,422,432,434,423,
+405,389,377,364,343,312,276,242,213,185,157,128,98,69,40,15,-6,-25,-46,-71,-100,
+-128,-153,-176,-202,-233,-262,-283,-296,-309,-329,-356,-385,-410,-432,-457,-486,-518,-548,-574,-599,-626,
+-654,-678,-698,-713,-724,-731,-736,-740,-745,-752,-760,-767,-777,-792,-814,-840,-868,-894,-918,-939,-954,
+-963,-968,-972,-981,-994,-1008,-1022,-1035,-1049,-1063,-1072,-1075,-1073,-1072,-1076,-1083,-1088,-1089,-1087,-1087,-1090,
+-1097,-1106,-1114,-1119,-1121,-1121,-1120,-1122,-1126,-1131,-1139,-1148,-1158,-1169,-1177,-1182,-1185,-1189,-1194,-1198,-1200,
+-1199,-1198,-1198,-1196,-1192,-1188,-1187,-1190,-1193,-1194,-1188,-1179,-1174,-1175,-1182,-1190,-1196,-1200,-1204,-1210,-1216,
+-1221,-1225,-1229,-1231,-1232,-1229,-1224,-1220,-1221,-1225,-1229,-1227,-1219,-1208,-1203,-1204,-1208,-1211,-1209,-1204,-1201,
+-1201,-1205,-1211,-1219,-1228,-1238,-1248,-1258,-1265,-1270,-1271,-1267,-1264,-1266,-1272,-1281,-1285,-1283,-1276,-1270,-1265,
+-1260,-1254,-1248,-1245,-1245,-1242,-1233,-1221,-1211,-1205,-1202,-1197,-1188,-1177,-1168,-1160,-1150,-1136,-1119,-1105,-1094,
+-1086,-1076,-1066,-1055,-1046,-1038,-1027,-1014,-1003,-998,-998,-1000,-999,-995,-989,-985,-985,-987,-988,-987,-985,
+-981,-978,-973,-967,-961,-955,-950,-945,-938,-930,-919,-907,-897,-887,-878,-869,-860,-849,-838,-826,-813,
+-801,-790,-777,-764,-751,-739,-730,-721,-712,-702,-689,-672,-649,-622,-596,-574,-557,-542,-526,-507,-487,
+-467,-449,-432,-414,-397,-381,-365,-350,-335,-319,-305,-292,-282,-275,-268,-260,-250,-239,-232,-230,-231,
+-231,-225,-216,-209,-206,-205,-201,-191,-180,-171,-164,-158,-149,-138,-129,-121,-111,-98,-84,-70,-59,
+-47,-30,-10,10,29,48,71,99,127,153,175,200,228,257,282,304,326,353,385,418,450,
+480,510,540,566,591,617,646,678,705,729,754,788,830,871,903,928,957,992,1028,1055,1071,
+1083,1094,1086,1042,962,883,868,962,1165,1432,1693,1886,1982,1989,1952,1932,1977,2089,2231,2350,2419,
+2447,2457,2458,2440,2392,2320,2244,2180,2122,2056,1981,1913,1867,1843,1825,1799,1764,1727,1689,1649,1605,
+1569,1552,1551,1554,1546,1529,1516,1521,1542,1564,1577,1577,1567,1552,1533,1513,1496,1479,1459,1437,1421,
+1422,1440,1461,1473,1474,1478,1494,1519,1533,1522,1491,1454,1419,1379,1322,1248,1176,1126,1102,1085,1046,
+970,858,731,610,508,426,358,298,246,206,178,155,126,83,28,-25,-71,-109,-145,-183,-219,
+-248,-269,-290,-314,-338,-356,-367,-376,-389,-408,-428,-444,-456,-468,-483,-500,-514,-525,-537,-553,-573,
+-592,-610,-625,-640,-654,-667,-676,-682,-687,-693,-701,-708,-712,-709,-701,-690,-680,-675,-671,-666,-662,
+-659,-657,-654,-647,-634,-619,-604,-588,-567,-540,-509,-480,-455,-432,-411,-389,-366,-338,-301,-250,-193,
+-137,-90,-50,-13,23,61,100,141,187,236,284,327,368,416,474,538,596,641,676,712,753,
+799,842,879,913,946,982,1018,1055,1093,1133,1174,1215,1253,1291,1329,1367,1402,1433,1462,1492,1523,
+1554,1583,1611,1642,1677,1715,1751,1782,1809,1834,1859,1883,1906,1929,1951,1972,1992,2009,2025,2045,2069,
+2095,2121,2143,2162,2178,2190,2197,2199,2196,2191,2189,2190,2191,2191,2190,2189,2189,2189,2186,2180,2172,
+2167,2164,2161,2156,2147,2135,2125,2120,2118,2117,2115,2111,2105,2101,2100,2100,2097,2085,2065,2044,2029,
+2024,2025,2025,2018,2004,1986,1967,1952,1943,1938,1929,1907,1870,1826,1787,1757,1731,1701,1670,1646,1635,
+1631,1622,1605,1588,1588,1605,1627,1638,1637,1635,1643,1659,1662,1671,1674,1677,1689,1710,1733,1753,1772,
+1795,1821,1846,1864,1879,1895,1917,1939,1957,1971,1987,2009,2033,2052,2063,2073,2090,2113,2136,2153,2166,
+2183,2206,2230,2247,2254,2258,2267,2282,2300,2316,2334,2355,2379,2402,2424,2449,2480,2512,2536,2545,2545,
+2549,2561,2577,2588,2597,2619,2665,2724,2766,2766,2728,2683,2662,2673,2698,2714,2716,2714,2717,2722,2718,
+2701,2678,2665,2673,2696,2726,2758,2795,2840,2887,2924,2942,2939,2924,2911,2907,2908,2909,2905,2898,2893,
+2894,2902,2917,2940,2972,3011,3054,3096,3132,3160,3178,3186,3185,3179,3175,3175,3179,3181,3174,3158,3138,
+3124,3124,3137,3157,3173,3177,3172,3160,3150,3142,3138,3138,3144,3153,3160,3158,3151,3151,3167,3196,3221,
+3227,3209,3181,3158,3146,3134,3114,3086,3064,3057,3062,3069,3071,3073,3083,3103,3126,3147,3168,3196,3234,
+3277,3316,3353,3391,3435,3479,3515,3540,3558,3577,3602,3630,3657,3686,3719,3756,3790,3818,3841,3864,3890,
+3914,3927,3932,3936,3943,3953,3961,3969,3992,4039,4104,4160,4180,4162,4128,4107,4110,4125,4131,4123,4109,
+4099,4085,4056,4010,3967,3947,3952,3952,3913,3830,3731,3655,3621,3612,3596,3556,3497,3440,3398,3367,3338,
+3302,3260,3215,3172,3130,3086,3040,2990,2937,2885,2837,2799,2770,2749,2733,2717,2699,2676,2648,2621,2600,
+2586,2577,2566,2549,2532,2520,2513,2510,2507,2503,2498,2493,2488,2484,2480,2478,2476,2472,2466,2461,2456,
+2450,2442,2430,2416,2403,2390,2374,2353,2330,2308,2289,2270,2246,2218,2188,2159,2132,2105,2077,2047,2015,
+1980,1941,1900,1862,1829,1801,1773,1744,1713,1684,1655,1624,1591,1562,1539,1523,1509,1492,1472,1455,1448,
+1450,1451,1439,1415,1393,1387,1404,1429,1441,1426,1388,1341,1292,1237,1167,1084,1002,939,900,873,840,
+794,740,690,648,614,583,553,521,487,448,405,360,317,274,232,191,153,119,86,50,8,
+-37,-83,-128,-175,-224,-272,-316,-356,-398,-447,-498,-546,-584,-618,-655,-702,-755,-808,-855,-897,-937,
+-978,-1020,-1063,-1109,-1160,-1213,-1264,-1310,-1350,-1388,-1431,-1480,-1532,-1585,-1635,-1684,-1731,-1778,-1824,-1870,-1915,
+-1961,-2006,-2051,-2095,-2139,-2182,-2227,-2271,-2314,-2353,-2391,-2429,-2468,-2507,-2546,-2584,-2622,-2661,-2700,-2737,-2772,
+-2808,-2844,-2881,-2915,-2945,-2972,-3001,-3032,-3065,-3097,-3127,-3156,-3186,-3213,-3235,-3252,-3268,-3286,-3309,-3332,-3350,
+-3360,-3367,-3373,-3379,-3386,-3391,-3396,-3401,-3409,-3420,-3432,-3445,-3460,-3480,-3503,-3526,-3545,-3560,-3572,-3581,-3590,
+-3597,-3603,-3608,-3613,-3618,-3622,-3627,-3632,-3636,-3635,-3627,-3612,-3599,-3594,-3600,-3615,-3632,-3647,-3655,-3656,-3648,
+-3631,-3613,-3601,-3600,-3604,-3603,-3587,-3563,-3540,-3528,-3526,-3525,-3516,-3499,-3480,-3463,-3447,-3432,-3418,-3405,-3393,
+-3376,-3354,-3331,-3314,-3309,-3308,-3301,-3279,-3245,-3213,-3190,-3176,-3164,-3146,-3124,-3102,-3085,-3066,-3041,-3008,-2974,
+-2946,-2926,-2909,-2887,-2858,-2827,-2797,-2772,-2750,-2729,-2706,-2680,-2651,-2618,-2585,-2552,-2520,-2487,-2450,-2410,-2371,
+-2335,-2298,-2255,-2208,-2162,-2126,-2098,-2074,-2044,-2009,-1970,-1929,-1883,-1829,-1770,-1715,-1671,-1633,-1588,-1527,-1449,
+-1367,-1292,-1225,-1157,-1075,-972,-852,-726,-608,-508,-424,-349,-275,-200,-129,-65,-10,43,95,140,171,
+184,190,203,235,286,350,417,478,524,546,538,507,471,450,456,480,503,509,497,482,483,
+503,520,504,438,334,232,177,182,230,288,332,359,384,416,451,483,506,529,558,594,628,
+653,667,676,685,700,720,742,763,779,788,792,797,808,825,844,857,860,859,862,877,901,
+927,951,971,990,1014,1042,1073,1101,1125,1146,1168,1197,1236,1287,1347,1413,1482,1552,1619,1680,1727,
+1758,1774,1784,1794,1812,1844,1893,1961,2044,2131,2211,2276,2325,2364,2397,2427,2453,2472,2482,2479,2462,
+2435,2405,2382,2368,2365,2368,2378,2397,2425,2463,2509,2557,2605,2649,2689,2730,2776,2828,2880,2917,2930,
+2915,2875,2818,2747,2665,2573,2475,2380,2294,2227,2183,2160,2147,2130,2100,2067,2052,2072,2124,2187,2238,
+2265,2274,2275,2275,2273,2264,2242,2209,2165,2115,2065,2023,1992,1967,1937,1890,1825,1748,1672,1607,1554,
+1510,1469,1427,1386,1350,1322,1300,1283,1271,1263,1260,1253,1232,1191,1139,1090,1055,1032,1019,1018,1046,
+1114,1206,1278,1283,1202,1063,923,829,794,794,797,785,759,731,709,691,671,649,627,606,581,
+550,514,480,457,443,430,414,396,386,389,399,405,398,384,369,359,349,329,299,263,229,
+201,177,152,126,97,69,42,20,1,-15,-36,-63,-93,-121,-145,-168,-194,-225,-254,-278,-294,
+-312,-335,-365,-395,-420,-444,-469,-499,-531,-559,-584,-609,-635,-663,-690,-714,-733,-748,-758,-764,-768,
+-772,-779,-787,-793,-799,-809,-824,-846,-872,-899,-924,-945,-961,-972,-978,-983,-991,-1002,-1015,-1030,-1045,
+-1061,-1074,-1080,-1080,-1078,-1080,-1088,-1099,-1106,-1109,-1107,-1107,-1110,-1117,-1124,-1131,-1136,-1138,-1139,-1139,-1141,
+-1145,-1150,-1157,-1166,-1175,-1184,-1191,-1195,-1200,-1208,-1217,-1224,-1227,-1226,-1222,-1218,-1213,-1207,-1202,-1199,-1201,
+-1205,-1206,-1202,-1195,-1191,-1192,-1198,-1206,-1212,-1216,-1220,-1226,-1231,-1235,-1239,-1242,-1245,-1246,-1243,-1235,-1228,
+-1225,-1224,-1223,-1217,-1208,-1201,-1202,-1209,-1218,-1223,-1223,-1222,-1223,-1229,-1238,-1247,-1254,-1259,-1262,-1264,-1268,
+-1273,-1279,-1283,-1283,-1280,-1277,-1276,-1277,-1278,-1277,-1275,-1271,-1268,-1264,-1261,-1260,-1260,-1258,-1250,-1238,-1226,
+-1216,-1209,-1202,-1193,-1182,-1173,-1168,-1163,-1153,-1137,-1121,-1108,-1100,-1093,-1083,-1071,-1060,-1051,-1044,-1035,-1024,
+-1013,-1007,-1007,-1007,-1006,-1001,-995,-991,-991,-992,-992,-990,-986,-984,-982,-977,-970,-961,-953,-948,-945,
+-940,-932,-921,-909,-898,-887,-876,-866,-856,-848,-838,-826,-814,-802,-791,-781,-768,-753,-738,-726,-717,
+-710,-703,-693,-679,-660,-638,-614,-591,-571,-553,-534,-514,-493,-474,-458,-444,-428,-412,-396,-379,-364,
+-349,-332,-316,-302,-290,-281,-272,-261,-249,-237,-229,-225,-225,-222,-214,-204,-195,-192,-192,-190,-185,
+-175,-164,-153,-142,-132,-122,-112,-102,-89,-75,-61,-50,-41,-30,-14,6,26,42,57,75,97,
+122,147,172,199,227,253,276,297,321,351,386,420,451,479,507,533,557,582,609,641,674,
+704,730,759,797,841,881,910,935,963,997,1032,1057,1072,1084,1091,1078,1029,951,883,881,982,
+1179,1424,1653,1818,1898,1909,1894,1905,1975,2100,2240,2350,2413,2440,2451,2451,2424,2361,2274,2188,2119,
+2061,2003,1943,1893,1862,1844,1822,1789,1749,1712,1679,1640,1592,1545,1515,1506,1507,1502,1488,1475,1476,
+1491,1511,1526,1530,1525,1514,1497,1476,1453,1427,1397,1367,1345,1340,1353,1370,1380,1384,1395,1421,1453,
+1474,1471,1449,1424,1402,1371,1320,1249,1177,1125,1094,1066,1017,936,830,715,606,505,415,335,269,
+221,189,166,141,103,53,-2,-51,-91,-123,-155,-190,-224,-252,-274,-295,-317,-339,-356,-371,-386,
+-404,-423,-438,-448,-458,-472,-489,-507,-521,-532,-545,-562,-583,-603,-620,-636,-650,-663,-673,-679,-684,
+-690,-697,-705,-710,-712,-709,-700,-688,-677,-669,-664,-660,-656,-654,-653,-654,-652,-645,-632,-614,-594,
+-570,-544,-517,-488,-459,-430,-401,-375,-352,-327,-294,-250,-197,-143,-94,-51,-9,32,72,109,148,
+190,235,280,321,361,409,467,530,587,633,672,712,759,806,848,882,912,944,981,1021,1060,
+1100,1139,1178,1216,1256,1297,1340,1381,1418,1449,1477,1506,1538,1569,1598,1627,1658,1692,1728,1761,1789,
+1815,1840,1867,1893,1918,1942,1966,1989,2009,2025,2039,2055,2076,2102,2128,2150,2169,2185,2200,2212,2220,
+2222,2221,2219,2219,2220,2221,2219,2216,2214,2215,2218,2219,2217,2210,2200,2190,2184,2182,2181,2174,2161,
+2147,2139,2138,2140,2138,2131,2123,2118,2116,2110,2095,2074,2055,2047,2049,2051,2044,2026,2001,1979,1965,
+1959,1957,1948,1925,1888,1846,1810,1787,1773,1755,1729,1697,1666,1643,1628,1618,1616,1622,1632,1639,1638,
+1634,1636,1647,1662,1662,1668,1672,1680,1699,1725,1751,1771,1788,1807,1830,1852,1871,1888,1905,1923,1938,
+1949,1959,1975,1999,2023,2040,2048,2056,2073,2098,2123,2142,2156,2172,2193,2216,2234,2246,2257,2271,2288,
+2304,2320,2341,2370,2401,2425,2443,2464,2496,2533,2558,2561,2553,2559,2594,2645,2685,2698,2694,2696,2714,
+2736,2740,2720,2693,2682,2696,2719,2734,2733,2724,2717,2710,2697,2678,2665,2672,2702,2745,2788,2825,2858,
+2890,2917,2931,2929,2918,2909,2913,2928,2943,2949,2943,2931,2919,2913,2917,2931,2958,2995,3039,3085,3130,
+3171,3204,3226,3235,3233,3226,3220,3219,3219,3214,3199,3180,3164,3161,3172,3188,3201,3203,3195,3183,3173,
+3167,3164,3163,3166,3173,3182,3185,3180,3171,3170,3184,3206,3220,3213,3191,3169,3163,3166,3164,3146,3121,
+3105,3106,3118,3125,3125,3124,3132,3149,3168,3183,3200,3229,3272,3320,3364,3403,3446,3497,3547,3587,3612,
+3629,3649,3676,3704,3730,3756,3788,3823,3856,3879,3896,3915,3939,3961,3975,3982,3988,3999,4010,4014,4017,
+4035,4080,4142,4193,4208,4185,4153,4137,4144,4155,4153,4136,4115,4096,4076,4043,4001,3970,3962,3967,3957,
+3904,3815,3721,3657,3631,3624,3606,3568,3517,3469,3431,3401,3368,3328,3283,3236,3192,3150,3107,3062,3013,
+2962,2915,2875,2845,2821,2801,2781,2759,2735,2709,2682,2657,2638,2623,2610,2595,2576,2560,2548,2541,2536,
+2531,2525,2521,2516,2510,2504,2500,2499,2500,2500,2497,2493,2488,2482,2474,2461,2446,2432,2420,2406,2389,
+2369,2348,2328,2307,2283,2255,2226,2198,2170,2143,2115,2087,2056,2021,1981,1940,1902,1870,1842,1814,1784,
+1752,1721,1690,1658,1625,1597,1576,1562,1549,1532,1513,1498,1494,1497,1497,1483,1457,1432,1426,1442,1466,
+1477,1462,1422,1368,1310,1246,1175,1100,1035,988,959,933,898,849,794,746,707,675,644,611,575,
+537,498,456,415,374,333,293,253,215,180,145,106,63,18,-25,-70,-116,-165,-211,-253,-293,
+-338,-390,-443,-488,-523,-554,-590,-636,-690,-743,-791,-835,-876,-918,-960,-1002,-1047,-1098,-1151,-1202,-1247,
+-1287,-1328,-1374,-1424,-1475,-1525,-1571,-1616,-1662,-1709,-1757,-1803,-1849,-1894,-1938,-1982,-2026,-2072,-2118,-2164,-2209,
+-2250,-2289,-2327,-2365,-2405,-2445,-2485,-2524,-2563,-2602,-2642,-2682,-2723,-2763,-2802,-2836,-2865,-2890,-2914,-2940,-2970,
+-3003,-3036,-3068,-3100,-3130,-3159,-3183,-3202,-3219,-3238,-3261,-3286,-3310,-3328,-3340,-3348,-3354,-3358,-3363,-3369,-3376,
+-3385,-3395,-3406,-3420,-3441,-3466,-3489,-3506,-3516,-3523,-3534,-3551,-3569,-3583,-3590,-3590,-3590,-3593,-3599,-3608,-3616,
+-3618,-3611,-3597,-3581,-3569,-3566,-3574,-3586,-3598,-3607,-3612,-3614,-3610,-3600,-3588,-3580,-3579,-3579,-3572,-3554,-3529,
+-3510,-3502,-3501,-3497,-3485,-3467,-3449,-3436,-3425,-3411,-3395,-3378,-3363,-3348,-3330,-3309,-3290,-3279,-3273,-3265,-3247,
+-3220,-3194,-3175,-3162,-3150,-3132,-3111,-3092,-3076,-3058,-3032,-2998,-2963,-2937,-2919,-2902,-2879,-2848,-2816,-2790,-2771,
+-2756,-2738,-2715,-2688,-2657,-2624,-2589,-2554,-2518,-2480,-2440,-2402,-2367,-2338,-2310,-2279,-2241,-2199,-2160,-2125,-2092,
+-2059,-2022,-1985,-1948,-1907,-1859,-1804,-1748,-1697,-1649,-1601,-1546,-1486,-1428,-1376,-1328,-1277,-1212,-1129,-1026,-908,
+-786,-670,-566,-476,-397,-325,-258,-192,-127,-62,-2,42,67,74,81,103,147,208,271,325,368,
+396,406,396,370,344,337,355,385,402,387,343,292,263,263,274,267,224,158,103,91,126,
+187,243,281,305,330,363,397,426,447,470,501,537,571,593,603,608,613,623,639,659,681,
+701,716,725,732,743,759,776,789,795,800,808,822,841,861,880,899,920,943,970,999,1028,
+1054,1077,1101,1132,1174,1225,1278,1329,1383,1443,1513,1583,1639,1674,1690,1698,1709,1732,1768,1821,1891,
+1977,2066,2147,2211,2259,2296,2329,2359,2386,2404,2412,2409,2398,2381,2362,2345,2328,2313,2302,2302,2321,
+2358,2410,2465,2516,2553,2576,2590,2609,2643,2696,2757,2804,2823,2809,2770,2715,2645,2557,2451,2338,2238,
+2170,2139,2141,2154,2157,2134,2091,2052,2046,2083,2150,2216,2257,2269,2263,2254,2245,2230,2207,2176,2142,
+2103,2056,2004,1953,1912,1881,1850,1807,1748,1678,1608,1544,1488,1437,1391,1350,1313,1279,1252,1231,1220,
+1216,1215,1210,1193,1164,1125,1083,1044,1007,968,929,904,918,986,1093,1194,1233,1179,1050,901,790,
+739,734,741,736,717,694,677,663,645,621,597,575,552,522,485,449,425,413,407,395,377,
+362,357,361,365,362,352,341,334,325,308,280,246,214,188,167,146,123,98,72,49,30,
+14,-1,-22,-50,-82,-112,-137,-159,-182,-209,-237,-264,-288,-313,-343,-374,-404,-430,-454,-482,-513,
+-545,-573,-596,-619,-643,-671,-698,-724,-746,-764,-776,-784,-789,-795,-802,-810,-816,-821,-827,-838,-855,
+-877,-901,-924,-945,-961,-974,-984,-992,-1001,-1010,-1022,-1036,-1052,-1067,-1078,-1082,-1081,-1081,-1088,-1099,-1112,
+-1121,-1125,-1126,-1129,-1134,-1139,-1144,-1148,-1153,-1156,-1159,-1162,-1165,-1169,-1174,-1180,-1187,-1193,-1199,-1203,-1206,
+-1211,-1220,-1230,-1239,-1242,-1241,-1237,-1235,-1234,-1232,-1228,-1224,-1221,-1221,-1220,-1218,-1214,-1213,-1215,-1220,-1225,
+-1228,-1230,-1233,-1237,-1241,-1244,-1246,-1248,-1250,-1249,-1245,-1239,-1233,-1229,-1225,-1219,-1209,-1200,-1196,-1200,-1209,
+-1217,-1221,-1222,-1226,-1234,-1246,-1256,-1264,-1268,-1270,-1272,-1272,-1274,-1277,-1284,-1292,-1296,-1295,-1288,-1280,-1274,
+-1271,-1272,-1273,-1273,-1271,-1269,-1267,-1267,-1266,-1261,-1251,-1239,-1228,-1220,-1214,-1206,-1194,-1182,-1174,-1170,-1166,
+-1156,-1141,-1127,-1116,-1110,-1102,-1090,-1076,-1063,-1055,-1049,-1042,-1033,-1024,-1019,-1017,-1017,-1014,-1008,-1002,-998,
+-998,-998,-997,-994,-990,-987,-985,-980,-973,-965,-957,-952,-948,-942,-933,-922,-910,-898,-885,-871,-858,
+-846,-836,-827,-817,-807,-797,-790,-782,-771,-757,-742,-729,-720,-714,-707,-697,-684,-668,-649,-629,-608,
+-588,-567,-545,-521,-499,-480,-466,-453,-438,-422,-405,-389,-375,-360,-343,-326,-310,-296,-285,-275,-263,
+-250,-238,-229,-222,-216,-209,-200,-190,-183,-178,-175,-174,-170,-163,-153,-141,-129,-117,-106,-96,-85,
+-72,-59,-49,-39,-29,-15,4,25,42,53,61,72,89,112,139,169,199,227,251,273,296,
+324,358,394,426,456,485,513,539,562,586,612,643,675,705,734,767,807,850,888,916,940,
+968,1000,1031,1054,1069,1079,1081,1062,1011,941,890,904,1007,1184,1393,1583,1721,1796,1823,1834,1872,
+1959,2090,2231,2344,2413,2446,2458,2448,2408,2334,2241,2153,2082,2023,1966,1911,1868,1843,1826,1801,1764,
+1723,1691,1664,1629,1578,1523,1482,1465,1464,1464,1455,1445,1441,1448,1460,1469,1474,1475,1471,1460,1442,
+1418,1389,1356,1323,1296,1283,1282,1287,1292,1299,1318,1349,1383,1404,1405,1395,1384,1373,1352,1306,1242,
+1177,1126,1089,1048,987,905,810,713,617,518,416,322,246,197,167,145,115,72,19,-32,-75,
+-107,-136,-167,-200,-233,-260,-282,-302,-321,-341,-359,-379,-401,-423,-440,-450,-456,-465,-479,-498,-514,
+-527,-539,-555,-575,-597,-616,-632,-647,-661,-672,-679,-683,-689,-698,-706,-712,-715,-714,-711,-705,-695,
+-681,-668,-659,-652,-648,-646,-646,-649,-650,-646,-634,-614,-590,-566,-541,-515,-487,-456,-425,-395,-368,
+-344,-319,-288,-248,-201,-153,-104,-57,-10,35,78,117,155,196,240,283,322,363,410,466,525,
+580,626,667,711,759,806,847,880,911,947,987,1029,1070,1108,1145,1180,1216,1254,1295,1339,1381,
+1418,1451,1482,1515,1549,1581,1610,1638,1668,1703,1737,1769,1797,1824,1851,1879,1905,1928,1950,1974,1997,
+2018,2033,2045,2059,2080,2105,2131,2152,2169,2185,2203,2223,2240,2250,2254,2254,2254,2255,2254,2251,2245,
+2240,2239,2242,2246,2245,2238,2228,2220,2219,2222,2222,2211,2192,2172,2163,2168,2177,2178,2167,2149,2135,
+2129,2127,2122,2110,2098,2090,2085,2078,2061,2037,2011,1991,1979,1970,1962,1948,1927,1898,1868,1845,1831,
+1824,1813,1789,1754,1716,1684,1665,1657,1655,1655,1651,1644,1637,1634,1639,1651,1662,1670,1673,1680,1696,
+1719,1745,1767,1782,1798,1817,1840,1863,1882,1898,1914,1929,1940,1947,1953,1965,1986,2009,2026,2036,2046,
+2062,2084,2106,2125,2142,2162,2186,2209,2227,2242,2259,2280,2301,2317,2334,2359,2394,2429,2452,2464,2481,
+2512,2551,2575,2571,2556,2566,2626,2719,2797,2821,2789,2734,2696,2687,2695,2703,2706,2713,2727,2742,2747,
+2739,2725,2713,2705,2698,2694,2701,2727,2771,2820,2861,2888,2905,2917,2922,2921,2916,2914,2923,2942,2963,
+2976,2976,2966,2952,2941,2936,2940,2956,2987,3030,3080,3132,3180,3223,3259,3283,3292,3289,3279,3271,3265,
+3257,3242,3221,3203,3197,3206,3223,3236,3236,3223,3204,3188,3179,3175,3175,3176,3181,3191,3200,3201,3193,
+3183,3183,3199,3219,3226,3214,3191,3178,3182,3193,3193,3175,3153,3144,3153,3170,3178,3177,3176,3185,3203,
+3218,3229,3242,3270,3314,3364,3410,3453,3501,3556,3609,3648,3674,3694,3720,3751,3778,3799,3821,3850,3886,
+3919,3940,3954,3969,3990,4012,4025,4030,4036,4048,4059,4062,4063,4078,4120,4177,4221,4230,4207,4179,4169,
+4176,4180,4165,4136,4107,4085,4062,4031,3996,3976,3977,3984,3966,3905,3814,3729,3676,3656,3647,3627,3590,
+3546,3505,3469,3433,3391,3344,3297,3251,3207,3165,3122,3078,3034,2991,2953,2922,2898,2875,2850,2821,2791,
+2764,2739,2717,2698,2681,2664,2645,2626,2607,2592,2581,2573,2566,2557,2550,2545,2541,2534,2528,2526,2528,
+2533,2534,2531,2524,2517,2511,2502,2489,2472,2457,2446,2436,2423,2407,2386,2364,2341,2316,2291,2264,2237,
+2208,2179,2150,2121,2091,2057,2019,1978,1941,1910,1883,1855,1824,1791,1759,1727,1696,1665,1637,1616,1601,
+1588,1572,1556,1545,1542,1543,1538,1519,1490,1466,1461,1477,1501,1513,1499,1458,1398,1330,1260,1192,1131,
+1083,1048,1021,990,949,899,849,806,769,736,702,665,626,587,547,507,469,432,395,357,318,
+279,243,206,167,124,80,35,-10,-57,-104,-149,-191,-232,-278,-329,-379,-422,-458,-491,-529,-574,
+-624,-672,-718,-761,-805,-848,-891,-934,-981,-1033,-1086,-1135,-1178,-1218,-1261,-1310,-1363,-1415,-1462,-1507,-1551,
+-1597,-1645,-1694,-1742,-1787,-1830,-1872,-1915,-1959,-2007,-2056,-2104,-2149,-2191,-2232,-2272,-2311,-2350,-2389,-2428,-2467,
+-2506,-2544,-2584,-2627,-2671,-2714,-2753,-2786,-2814,-2837,-2861,-2888,-2919,-2952,-2985,-3017,-3048,-3079,-3109,-3136,-3158,
+-3176,-3192,-3211,-3235,-3261,-3285,-3304,-3316,-3324,-3331,-3339,-3349,-3360,-3369,-3377,-3386,-3400,-3419,-3441,-3461,-3475,
+-3482,-3489,-3501,-3519,-3539,-3553,-3558,-3557,-3555,-3557,-3565,-3575,-3582,-3584,-3577,-3565,-3553,-3545,-3544,-3550,-3557,
+-3563,-3567,-3570,-3574,-3574,-3569,-3561,-3552,-3546,-3541,-3530,-3513,-3493,-3479,-3474,-3473,-3468,-3454,-3436,-3421,-3413,
+-3406,-3394,-3376,-3355,-3337,-3323,-3310,-3295,-3278,-3264,-3252,-3240,-3222,-3201,-3179,-3162,-3148,-3131,-3110,-3087,-3069,
+-3055,-3039,-3015,-2984,-2952,-2927,-2910,-2893,-2869,-2839,-2808,-2786,-2772,-2761,-2744,-2721,-2692,-2662,-2630,-2595,-2557,
+-2516,-2475,-2435,-2399,-2368,-2344,-2323,-2299,-2270,-2233,-2193,-2153,-2113,-2072,-2029,-1987,-1946,-1905,-1862,-1814,-1762,
+-1707,-1652,-1599,-1550,-1506,-1468,-1431,-1393,-1349,-1298,-1237,-1163,-1072,-966,-850,-736,-632,-541,-461,-386,-310,
+-235,-163,-103,-63,-41,-27,-8,27,81,142,198,241,272,290,295,286,266,248,250,275,311,
+331,313,257,181,115,77,63,53,36,14,5,25,72,130,180,216,245,275,307,337,361,
+382,408,442,477,506,522,530,535,543,555,571,591,614,637,656,671,683,695,706,714,719,
+722,731,746,764,781,794,807,823,843,867,894,926,959,989,1014,1035,1062,1104,1158,1213,1262,
+1308,1362,1431,1507,1571,1608,1619,1617,1621,1641,1681,1741,1818,1908,1998,2078,2140,2186,2224,2259,2290,
+2313,2323,2322,2314,2304,2296,2290,2282,2270,2254,2243,2247,2271,2316,2371,2424,2464,2483,2485,2477,2477,
+2498,2548,2614,2674,2707,2704,2668,2604,2515,2402,2277,2163,2086,2060,2081,2122,2153,2151,2113,2060,2025,
+2034,2088,2163,2225,2254,2254,2241,2225,2207,2179,2141,2103,2071,2040,1999,1946,1887,1834,1795,1762,1723,
+1672,1612,1548,1484,1423,1366,1318,1279,1247,1217,1190,1169,1160,1160,1160,1149,1122,1082,1039,1001,972,
+946,917,880,845,832,862,937,1032,1100,1102,1028,909,793,713,674,661,654,646,640,635,627,
+609,583,558,539,524,502,469,432,403,387,379,369,354,338,328,325,323,318,310,303,300,
+295,283,259,229,200,175,154,134,115,94,74,55,38,24,9,-10,-37,-69,-102,-129,-151,
+-172,-195,-221,-249,-278,-309,-343,-376,-405,-432,-459,-491,-526,-559,-586,-609,-631,-654,-681,-707,-732,
+-753,-771,-784,-794,-803,-811,-820,-830,-838,-844,-850,-858,-870,-886,-904,-923,-943,-961,-977,-992,-1004,
+-1014,-1023,-1032,-1043,-1057,-1070,-1080,-1083,-1084,-1087,-1096,-1110,-1122,-1129,-1133,-1137,-1144,-1152,-1157,-1160,-1162,
+-1165,-1170,-1176,-1181,-1185,-1190,-1196,-1202,-1207,-1211,-1214,-1215,-1216,-1219,-1224,-1232,-1239,-1242,-1242,-1243,-1246,
+-1251,-1254,-1253,-1249,-1244,-1239,-1235,-1232,-1230,-1230,-1232,-1234,-1235,-1233,-1232,-1234,-1237,-1241,-1243,-1244,-1245,
+-1244,-1242,-1238,-1234,-1232,-1231,-1229,-1223,-1213,-1204,-1202,-1206,-1212,-1215,-1215,-1216,-1220,-1230,-1240,-1247,-1250,
+-1253,-1257,-1262,-1267,-1271,-1277,-1285,-1294,-1301,-1302,-1295,-1285,-1276,-1273,-1275,-1279,-1280,-1278,-1274,-1270,-1266,
+-1262,-1255,-1245,-1234,-1226,-1221,-1216,-1207,-1197,-1187,-1181,-1177,-1171,-1161,-1147,-1135,-1126,-1119,-1109,-1095,-1080,
+-1068,-1060,-1055,-1048,-1039,-1032,-1027,-1026,-1025,-1022,-1016,-1009,-1005,-1004,-1004,-1004,-1001,-996,-990,-985,-979,
+-973,-966,-960,-956,-951,-943,-933,-921,-909,-898,-885,-870,-853,-837,-823,-812,-803,-795,-787,-782,-776,
+-768,-757,-746,-737,-729,-721,-710,-697,-682,-666,-651,-635,-618,-601,-580,-556,-529,-504,-484,-468,-454,
+-438,-421,-404,-389,-376,-362,-345,-327,-311,-296,-284,-272,-261,-250,-240,-230,-219,-207,-197,-188,-182,
+-177,-171,-164,-158,-153,-147,-140,-131,-120,-108,-96,-84,-71,-60,-51,-44,-34,-21,-1,20,39,
+52,58,61,68,82,105,134,167,199,227,252,276,304,336,371,404,433,462,492,524,554,
+579,603,627,656,686,715,744,778,818,858,893,921,945,972,1002,1028,1047,1061,1069,1068,1045,
+996,939,909,939,1037,1185,1348,1497,1615,1696,1747,1787,1843,1935,2063,2203,2323,2405,2446,2455,2434,
+2381,2303,2216,2138,2075,2018,1959,1901,1856,1830,1813,1788,1750,1711,1680,1655,1622,1572,1515,1469,1445,
+1438,1435,1427,1417,1411,1411,1413,1416,1420,1425,1431,1431,1422,1403,1378,1349,1318,1289,1264,1246,1234,
+1231,1239,1261,1293,1323,1339,1342,1340,1340,1338,1322,1283,1227,1171,1123,1081,1029,961,878,791,703,
+610,506,397,297,222,175,148,123,89,43,-6,-52,-88,-118,-147,-179,-212,-242,-267,-289,-308,
+-327,-346,-366,-389,-412,-434,-449,-458,-465,-475,-491,-508,-521,-531,-543,-561,-583,-603,-619,-634,-650,
+-666,-679,-686,-691,-699,-710,-719,-723,-720,-717,-716,-715,-708,-695,-678,-664,-653,-646,-642,-640,-640,
+-641,-636,-623,-603,-580,-555,-530,-503,-473,-442,-413,-388,-365,-340,-313,-281,-244,-204,-161,-116,-68,
+-20,26,70,112,154,200,247,291,330,370,416,469,527,581,631,677,722,768,810,848,881,
+915,953,995,1037,1076,1113,1148,1183,1218,1254,1294,1335,1375,1413,1448,1484,1521,1557,1591,1622,1651,
+1683,1717,1750,1780,1808,1835,1863,1889,1911,1931,1950,1973,1997,2019,2035,2049,2065,2086,2112,2137,2156,
+2171,2188,2209,2235,2259,2278,2288,2292,2294,2294,2290,2282,2273,2266,2263,2263,2263,2259,2252,2245,2242,
+2244,2247,2245,2232,2214,2197,2192,2198,2208,2211,2200,2181,2162,2151,2149,2151,2151,2149,2140,2123,2095,
+2062,2031,2008,1993,1981,1966,1947,1929,1914,1901,1889,1877,1865,1852,1835,1810,1777,1742,1713,1695,1687,
+1682,1676,1667,1658,1652,1653,1658,1665,1670,1680,1682,1693,1712,1734,1755,1770,1784,1801,1826,1853,1877,
+1894,1906,1919,1932,1944,1952,1957,1966,1981,1997,2012,2023,2035,2051,2069,2087,2104,2124,2151,2180,2205,
+2223,2239,2260,2289,2316,2338,2358,2385,2421,2456,2478,2486,2499,2529,2569,2592,2584,2561,2568,2635,2746,
+2845,2875,2827,2740,2669,2646,2665,2699,2727,2746,2755,2758,2750,2736,2722,2717,2721,2734,2752,2777,2811,
+2849,2884,2909,2920,2924,2923,2920,2917,2919,2930,2949,2969,2982,2983,2977,2971,2968,2968,2970,2975,2991,
+3025,3074,3132,3188,3239,3283,3318,3341,3350,3346,3336,3324,3313,3299,3278,3255,3239,3237,3247,3261,3267,
+3259,3239,3216,3198,3186,3178,3175,3179,3191,3209,3224,3226,3216,3206,3208,3226,3245,3249,3235,3215,3206,
+3212,3221,3217,3200,3182,3182,3198,3218,3226,3224,3224,3236,3254,3270,3280,3294,3322,3366,3415,3460,3504,
+3554,3608,3658,3695,3722,3749,3783,3817,3842,3858,3876,3905,3943,3976,3994,4004,4018,4041,4064,4076,4079,
+4083,4094,4107,4114,4119,4135,4175,4226,4261,4262,4235,4206,4194,4193,4185,4159,4124,4094,4075,4055,4026,
+3995,3979,3982,3988,3966,3906,3825,3754,3713,3696,3683,3657,3621,3581,3544,3505,3460,3409,3358,3310,3267,
+3225,3183,3142,3103,3065,3029,2997,2970,2946,2920,2890,2857,2824,2797,2777,2760,2744,2725,2704,2680,2657,
+2639,2626,2617,2609,2599,2589,2580,2575,2570,2564,2558,2557,2562,2568,2568,2561,2551,2542,2535,2527,2513,
+2495,2479,2469,2462,2454,2440,2421,2399,2375,2353,2329,2304,2277,2246,2214,2181,2151,2121,2088,2052,2014,
+1978,1948,1922,1895,1864,1831,1798,1768,1739,1710,1684,1662,1645,1629,1615,1603,1595,1591,1586,1572,1547,
+1518,1499,1498,1516,1538,1548,1533,1491,1429,1358,1289,1229,1181,1145,1114,1082,1041,994,945,902,865,
+830,794,756,717,679,640,600,561,524,490,457,421,382,343,305,269,232,190,145,98,50,
+3,-43,-88,-132,-175,-219,-265,-308,-348,-385,-424,-467,-513,-560,-604,-646,-688,-732,-775,-818,-864,
+-914,-967,-1019,-1066,-1106,-1147,-1192,-1244,-1299,-1351,-1398,-1443,-1489,-1536,-1585,-1634,-1681,-1725,-1767,-1808,-1851,
+-1898,-1948,-1999,-2046,-2090,-2133,-2175,-2218,-2258,-2297,-2336,-2375,-2414,-2454,-2492,-2530,-2571,-2614,-2656,-2695,-2728,
+-2756,-2781,-2806,-2834,-2867,-2901,-2936,-2968,-2998,-3026,-3055,-3085,-3110,-3131,-3147,-3165,-3187,-3214,-3240,-3262,-3276,
+-3286,-3297,-3311,-3327,-3341,-3352,-3359,-3366,-3375,-3389,-3406,-3423,-3438,-3451,-3463,-3476,-3491,-3505,-3514,-3519,-3521,
+-3522,-3525,-3530,-3536,-3540,-3541,-3538,-3532,-3527,-3525,-3526,-3529,-3532,-3533,-3534,-3536,-3540,-3542,-3539,-3530,-3519,
+-3509,-3498,-3486,-3472,-3460,-3452,-3450,-3448,-3441,-3427,-3412,-3400,-3394,-3388,-3377,-3358,-3335,-3314,-3299,-3288,-3277,
+-3265,-3252,-3238,-3221,-3202,-3181,-3162,-3145,-3128,-3108,-3084,-3061,-3042,-3029,-3016,-2996,-2970,-2942,-2920,-2904,-2887,
+-2864,-2835,-2807,-2787,-2775,-2763,-2746,-2721,-2692,-2662,-2631,-2596,-2555,-2512,-2471,-2434,-2402,-2374,-2351,-2330,-2308,
+-2282,-2248,-2209,-2168,-2125,-2081,-2034,-1985,-1937,-1893,-1851,-1808,-1761,-1709,-1655,-1604,-1561,-1527,-1500,-1470,-1435,
+-1393,-1349,-1305,-1256,-1194,-1116,-1021,-919,-818,-721,-627,-531,-434,-343,-264,-204,-163,-132,-103,-66,-20,
+30,79,121,154,179,195,199,190,174,162,168,195,235,269,274,238,166,79,0,-54,-82,
+-88,-81,-62,-31,10,56,102,144,182,216,245,268,288,313,346,385,418,439,448,454,463,
+477,493,511,530,551,572,592,610,628,643,653,655,651,649,658,677,697,712,721,731,747,
+770,796,824,855,889,920,943,961,988,1036,1100,1166,1218,1258,1302,1364,1441,1512,1555,1563,1552,
+1543,1553,1589,1650,1732,1824,1915,1993,2055,2104,2147,2188,2221,2240,2243,2235,2222,2211,2204,2201,2198,
+2194,2189,2190,2205,2236,2277,2319,2351,2368,2368,2356,2339,2329,2341,2381,2444,2511,2559,2571,2537,2456,
+2336,2194,2062,1972,1948,1987,2062,2130,2157,2134,2076,2020,1997,2025,2090,2163,2213,2229,2222,2207,2191,
+2168,2131,2085,2042,2009,1979,1939,1884,1821,1764,1723,1690,1656,1611,1555,1492,1425,1359,1299,1251,1217,
+1191,1164,1136,1112,1101,1098,1094,1076,1040,993,946,909,885,869,857,837,807,776,765,796,870,
+960,1019,1013,941,832,727,651,609,589,582,583,584,580,563,538,513,496,486,474,451,419,
+388,364,349,337,324,310,300,294,286,277,267,261,261,262,255,238,212,184,157,134,114,
+96,81,66,51,35,20,4,-14,-37,-65,-95,-122,-146,-168,-190,-214,-241,-271,-304,-337,-369,
+-398,-427,-459,-496,-534,-570,-598,-622,-645,-669,-694,-719,-742,-760,-776,-790,-802,-813,-825,-837,-849,
+-861,-871,-879,-887,-894,-903,-915,-929,-946,-965,-984,-1003,-1019,-1032,-1040,-1047,-1055,-1065,-1075,-1083,-1088,
+-1091,-1097,-1109,-1121,-1131,-1136,-1140,-1146,-1155,-1163,-1168,-1170,-1171,-1174,-1180,-1187,-1193,-1199,-1205,-1211,-1216,
+-1220,-1223,-1224,-1225,-1225,-1225,-1227,-1232,-1236,-1240,-1243,-1247,-1254,-1261,-1266,-1268,-1265,-1261,-1258,-1254,-1251,
+-1248,-1246,-1244,-1241,-1236,-1232,-1229,-1229,-1232,-1235,-1236,-1237,-1237,-1237,-1235,-1231,-1228,-1228,-1230,-1232,-1229,
+-1222,-1216,-1214,-1217,-1220,-1220,-1218,-1217,-1220,-1226,-1232,-1234,-1235,-1238,-1244,-1253,-1262,-1270,-1277,-1285,-1294,
+-1301,-1302,-1298,-1291,-1285,-1284,-1286,-1289,-1289,-1285,-1278,-1271,-1264,-1257,-1250,-1241,-1232,-1225,-1218,-1211,-1203,
+-1194,-1187,-1182,-1178,-1170,-1160,-1149,-1139,-1131,-1123,-1113,-1100,-1088,-1078,-1070,-1061,-1052,-1043,-1037,-1033,-1032,
+-1031,-1028,-1022,-1017,-1013,-1011,-1011,-1011,-1008,-1003,-994,-985,-977,-970,-965,-960,-956,-950,-941,-930,-918,
+-906,-894,-882,-867,-849,-830,-814,-800,-789,-781,-776,-771,-766,-761,-754,-748,-742,-735,-724,-710,-693,
+-677,-662,-649,-637,-625,-610,-590,-565,-537,-509,-485,-466,-449,-432,-415,-399,-386,-374,-361,-344,-327,
+-311,-297,-283,-269,-256,-246,-238,-228,-215,-200,-187,-180,-177,-175,-169,-158,-147,-137,-130,-124,-117,
+-108,-97,-86,-73,-61,-51,-44,-38,-28,-13,7,27,42,51,54,58,65,80,103,132,165,
+197,227,255,283,315,349,382,411,437,466,498,533,565,592,616,641,670,699,729,759,792,
+829,866,898,926,952,981,1008,1030,1046,1057,1064,1060,1034,990,946,934,974,1062,1178,1299,1413,
+1519,1615,1697,1766,1837,1928,2048,2181,2304,2392,2436,2438,2405,2343,2266,2190,2128,2079,2032,1979,1923,
+1878,1848,1825,1798,1762,1723,1691,1664,1631,1585,1534,1489,1459,1441,1426,1410,1396,1388,1385,1384,1381,
+1381,1387,1398,1406,1407,1397,1382,1363,1342,1317,1287,1257,1230,1216,1219,1238,1265,1288,1300,1304,1308,
+1312,1312,1296,1260,1213,1165,1120,1073,1013,939,855,766,673,570,458,348,256,194,157,132,105,
+69,25,-17,-56,-90,-123,-156,-189,-220,-247,-269,-291,-312,-333,-353,-374,-395,-416,-436,-451,-461,
+-473,-487,-504,-519,-528,-537,-550,-569,-589,-605,-617,-631,-649,-669,-685,-693,-700,-709,-722,-731,-732,
+-726,-720,-720,-721,-718,-707,-691,-675,-663,-654,-645,-637,-632,-628,-620,-605,-586,-564,-541,-515,-485,
+-453,-423,-398,-379,-359,-335,-304,-271,-238,-204,-167,-125,-79,-32,12,55,99,147,197,247,292,
+333,373,417,469,527,585,641,691,737,779,817,853,889,927,966,1005,1044,1083,1120,1157,1194,
+1229,1266,1304,1343,1382,1419,1456,1493,1531,1567,1601,1633,1666,1699,1732,1762,1789,1815,1841,1866,1889,
+1909,1927,1947,1972,1998,2023,2044,2061,2081,2105,2131,2155,2173,2188,2204,2226,2253,2280,2301,2316,2325,
+2330,2329,2321,2309,2297,2289,2286,2286,2284,2278,2272,2269,2269,2270,2268,2260,2249,2237,2228,2223,2223,
+2224,2224,2219,2209,2195,2182,2177,2180,2188,2192,2182,2153,2111,2069,2040,2028,2022,2009,1981,1947,1918,
+1903,1901,1901,1895,1879,1858,1834,1807,1780,1754,1732,1718,1709,1703,1697,1692,1687,1684,1683,1683,1681,
+1680,1687,1692,1704,1721,1739,1755,1767,1781,1803,1832,1863,1887,1901,1910,1919,1932,1946,1958,1967,1975,
+1982,1991,2000,2009,2023,2039,2056,2072,2088,2111,2141,2174,2200,2219,2237,2263,2299,2334,2362,2384,2409,
+2443,2476,2497,2505,2517,2545,2585,2611,2606,2583,2581,2631,2720,2800,2821,2772,2690,2628,2617,2651,2698,
+2736,2756,2761,2758,2751,2742,2738,2747,2768,2798,2831,2860,2885,2903,2914,2919,2921,2921,2922,2922,2923,
+2930,2944,2961,2974,2978,2974,2971,2976,2987,2997,3001,3006,3023,3061,3119,3184,3245,3297,3338,3370,3393,
+3403,3401,3390,3377,3361,3344,3324,3303,3287,3280,3281,3285,3284,3275,3260,3241,3220,3199,3182,3176,3186,
+3213,3246,3271,3276,3266,3253,3253,3267,3281,3282,3266,3248,3240,3244,3248,3242,3225,3214,3221,3241,3261,
+3268,3266,3268,3281,3301,3318,3333,3353,3386,3429,3474,3515,3556,3603,3653,3698,3732,3762,3796,3835,3871,
+3893,3906,3925,3958,3997,4026,4037,4041,4056,4085,4115,4131,4133,4134,4147,4165,4178,4185,4199,4230,4269,
+4293,4285,4252,4217,4196,4185,4167,4137,4103,4079,4066,4051,4026,3997,3980,3980,3979,3955,3901,3836,3784,
+3756,3742,3723,3692,3655,3618,3580,3537,3485,3429,3378,3334,3295,3256,3217,3181,3147,3114,3080,3047,3016,
+2989,2962,2932,2900,2870,2845,2826,2809,2791,2768,2742,2714,2690,2672,2660,2652,2643,2633,2623,2615,2609,
+2605,2599,2594,2593,2597,2600,2597,2587,2575,2565,2558,2548,2534,2517,2501,2492,2488,2482,2470,2453,2434,
+2413,2393,2371,2345,2316,2283,2248,2214,2182,2152,2121,2086,2051,2017,1987,1961,1934,1904,1873,1841,1812,
+1784,1758,1732,1709,1690,1673,1660,1651,1644,1636,1623,1602,1574,1549,1537,1543,1561,1579,1582,1561,1518,
+1458,1393,1332,1281,1242,1210,1176,1135,1088,1039,995,957,922,886,846,806,768,732,696,658,619,
+583,550,518,482,443,404,367,333,297,255,208,158,109,61,15,-29,-74,-118,-161,-201,-238,
+-274,-311,-353,-400,-449,-496,-541,-583,-625,-667,-709,-752,-799,-850,-904,-954,-999,-1040,-1083,-1131,-1183,
+-1236,-1286,-1333,-1380,-1427,-1475,-1522,-1569,-1614,-1657,-1698,-1741,-1786,-1837,-1890,-1941,-1986,-2027,-2067,-2110,-2154,
+-2197,-2238,-2278,-2319,-2360,-2400,-2438,-2476,-2515,-2556,-2596,-2634,-2667,-2696,-2722,-2747,-2774,-2805,-2841,-2877,-2911,
+-2941,-2967,-2995,-3025,-3054,-3079,-3100,-3120,-3144,-3173,-3200,-3220,-3231,-3240,-3252,-3271,-3292,-3311,-3324,-3332,-3339,
+-3347,-3358,-3372,-3387,-3405,-3423,-3440,-3453,-3463,-3471,-3479,-3487,-3494,-3500,-3504,-3506,-3506,-3506,-3504,-3503,-3503,
+-3504,-3506,-3508,-3509,-3508,-3506,-3505,-3506,-3506,-3506,-3502,-3495,-3485,-3474,-3462,-3451,-3441,-3434,-3429,-3426,-3421,
+-3413,-3402,-3390,-3381,-3375,-3367,-3355,-3338,-3317,-3297,-3280,-3267,-3256,-3246,-3234,-3219,-3201,-3180,-3159,-3140,-3124,
+-3108,-3089,-3068,-3047,-3028,-3013,-2999,-2979,-2955,-2931,-2911,-2896,-2881,-2861,-2835,-2809,-2790,-2776,-2762,-2741,-2714,
+-2683,-2653,-2621,-2587,-2548,-2508,-2471,-2439,-2410,-2383,-2358,-2333,-2308,-2279,-2245,-2204,-2161,-2118,-2074,-2027,-1976,
+-1926,-1878,-1837,-1799,-1759,-1715,-1668,-1622,-1583,-1552,-1526,-1499,-1468,-1433,-1396,-1359,-1320,-1275,-1220,-1156,-1083,
+-1002,-911,-808,-693,-575,-465,-373,-301,-244,-191,-139,-88,-44,-11,13,36,60,83,101,107,104,
+96,93,100,122,159,203,237,238,193,105,1,-88,-140,-152,-138,-113,-86,-57,-20,24,73,
+119,155,180,198,219,250,290,330,360,373,377,382,394,412,431,448,463,479,497,514,533,
+553,574,588,591,586,582,589,606,624,636,643,654,675,703,732,759,787,818,846,868,888,
+919,975,1051,1126,1181,1213,1243,1293,1366,1441,1490,1503,1489,1471,1472,1502,1560,1640,1731,1820,1897,
+1961,2015,2064,2110,2144,2164,2167,2160,2148,2136,2126,2118,2114,2116,2123,2139,2163,2192,2220,2237,2237,
+2223,2202,2178,2159,2147,2149,2172,2218,2277,2329,2353,2327,2245,2118,1979,1868,1825,1861,1957,2064,2136,
+2145,2100,2033,1984,1981,2022,2087,2145,2177,2182,2173,2162,2150,2127,2088,2040,1994,1956,1920,1875,1818,
+1758,1707,1671,1640,1605,1557,1497,1430,1359,1291,1232,1188,1159,1136,1111,1082,1057,1041,1033,1020,994,
+954,907,864,829,804,789,782,775,757,724,695,698,750,840,926,962,931,849,755,679,626,
+590,562,540,526,518,507,490,470,453,441,431,416,394,368,344,324,306,290,276,267,260,
+252,240,229,223,223,225,222,210,188,162,134,109,88,70,57,46,34,19,1,-16,-36,
+-56,-77,-100,-123,-145,-168,-191,-216,-243,-272,-303,-334,-364,-393,-423,-458,-498,-538,-575,-605,-631,
+-656,-682,-708,-733,-754,-772,-787,-800,-813,-827,-841,-856,-872,-886,-900,-911,-919,-925,-930,-938,-948,
+-961,-977,-993,-1011,-1030,-1045,-1056,-1064,-1070,-1077,-1086,-1093,-1099,-1104,-1112,-1123,-1135,-1144,-1150,-1154,-1161,
+-1170,-1177,-1180,-1180,-1180,-1183,-1189,-1195,-1202,-1208,-1214,-1219,-1223,-1226,-1228,-1229,-1230,-1231,-1232,-1234,-1236,
+-1241,-1245,-1251,-1257,-1263,-1268,-1271,-1272,-1273,-1274,-1276,-1276,-1274,-1270,-1264,-1258,-1249,-1240,-1232,-1228,-1227,
+-1228,-1229,-1229,-1230,-1232,-1234,-1233,-1230,-1225,-1224,-1226,-1229,-1230,-1226,-1222,-1221,-1223,-1225,-1226,-1225,-1225,
+-1227,-1230,-1233,-1236,-1238,-1244,-1252,-1260,-1267,-1274,-1281,-1289,-1296,-1300,-1301,-1299,-1296,-1294,-1293,-1293,-1291,
+-1289,-1285,-1279,-1272,-1264,-1257,-1249,-1241,-1233,-1225,-1216,-1206,-1195,-1186,-1179,-1173,-1166,-1158,-1150,-1142,-1135,
+-1129,-1121,-1112,-1104,-1096,-1089,-1079,-1066,-1054,-1045,-1040,-1038,-1036,-1033,-1030,-1027,-1024,-1021,-1018,-1017,-1016,
+-1014,-1008,-998,-987,-977,-970,-966,-961,-956,-948,-939,-927,-914,-900,-887,-873,-858,-842,-825,-808,-793,
+-782,-774,-770,-766,-763,-758,-753,-748,-743,-735,-723,-707,-691,-676,-664,-653,-643,-631,-617,-598,-574,
+-546,-516,-488,-464,-443,-424,-408,-394,-383,-371,-357,-342,-326,-312,-299,-283,-266,-250,-238,-229,-220,
+-207,-191,-177,-170,-167,-165,-159,-148,-135,-124,-115,-107,-99,-91,-83,-75,-64,-53,-44,-36,-30,
+-20,-6,11,27,37,43,47,53,64,81,103,132,164,196,228,258,289,322,355,387,415,
+443,472,504,536,566,593,619,648,678,709,740,772,806,841,875,905,933,964,994,1022,1042,
+1055,1066,1072,1065,1036,992,954,951,994,1073,1166,1258,1351,1454,1565,1675,1771,1857,1950,2061,2185,
+2301,2384,2422,2416,2375,2310,2237,2171,2121,2086,2055,2018,1974,1930,1894,1863,1831,1794,1757,1724,1694,
+1660,1619,1573,1531,1497,1467,1439,1413,1395,1386,1383,1379,1372,1363,1361,1365,1374,1380,1381,1378,1374,
+1367,1355,1334,1304,1273,1249,1241,1248,1265,1281,1292,1299,1303,1306,1299,1277,1243,1204,1164,1121,1067,
+999,917,827,731,625,510,393,290,214,167,140,116,88,53,17,-18,-53,-90,-127,-164,-197,
+-224,-247,-267,-289,-312,-336,-357,-377,-396,-416,-434,-450,-464,-480,-496,-513,-526,-537,-548,-565,-584,
+-602,-614,-623,-635,-654,-676,-692,-700,-705,-714,-727,-737,-737,-731,-724,-722,-723,-719,-709,-695,-682,
+-672,-661,-648,-635,-624,-615,-604,-587,-566,-545,-522,-497,-467,-435,-406,-384,-367,-349,-324,-292,-260,
+-231,-202,-170,-130,-86,-40,3,47,92,141,191,241,286,328,369,413,464,521,583,642,695,
+740,780,818,858,900,941,979,1017,1054,1093,1134,1174,1212,1249,1287,1325,1365,1404,1442,1479,1515,
+1548,1579,1610,1641,1674,1707,1738,1766,1792,1817,1843,1868,1889,1909,1930,1955,1984,2015,2042,2064,2086,
+2109,2134,2159,2181,2199,2215,2232,2252,2275,2298,2318,2334,2345,2351,2350,2340,2327,2315,2309,2309,2310,
+2309,2305,2302,2302,2304,2301,2292,2281,2273,2268,2264,2255,2243,2231,2226,2226,2225,2217,2204,2194,2196,
+2208,2215,2205,2173,2131,2101,2095,2107,2117,2103,2060,2002,1950,1918,1907,1904,1897,1882,1861,1838,1817,
+1796,1776,1759,1745,1735,1729,1726,1723,1719,1713,1705,1697,1690,1687,1699,1705,1716,1730,1744,1758,1771,
+1787,1808,1835,1863,1885,1900,1909,1919,1930,1944,1956,1966,1975,1982,1988,1992,1999,2012,2030,2050,2068,
+2085,2107,2136,2168,2196,2219,2243,2276,2317,2356,2387,2408,2431,2460,2490,2511,2521,2531,2556,2593,2625,
+2635,2625,2619,2639,2679,2711,2707,2667,2618,2596,2612,2654,2697,2725,2739,2747,2754,2761,2770,2783,2804,
+2834,2867,2896,2915,2923,2921,2915,2910,2911,2918,2926,2931,2933,2936,2943,2954,2964,2968,2970,2976,2989,
+3004,3015,3020,3027,3050,3097,3163,3234,3296,3345,3382,3412,3436,3449,3449,3438,3420,3400,3381,3364,3347,
+3332,3318,3307,3300,3296,3294,3288,3275,3251,3221,3196,3190,3210,3253,3302,3336,3345,3333,3316,3309,3313,
+3317,3310,3293,3276,3270,3274,3276,3269,3256,3251,3261,3282,3300,3308,3309,3315,3330,3350,3369,3389,3415,
+3452,3495,3536,3572,3610,3653,3700,3741,3774,3805,3843,3884,3919,3940,3957,3982,4020,4058,4079,4079,4078,
+4095,4131,4169,4188,4189,4191,4206,4228,4243,4245,4245,4257,4278,4290,4278,4243,4206,4179,4160,4140,4112,
+4084,4068,4059,4048,4027,4003,3988,3983,3975,3947,3900,3851,3816,3799,3785,3761,3726,3687,3650,3611,3564,
+3508,3454,3408,3371,3337,3302,3266,3233,3203,3172,3137,3100,3065,3035,3008,2980,2951,2923,2899,2879,2859,
+2836,2810,2781,2752,2728,2710,2697,2688,2679,2669,2659,2651,2647,2643,2638,2634,2632,2631,2629,2621,2608,
+2594,2584,2576,2566,2553,2537,2525,2519,2515,2509,2498,2485,2470,2454,2435,2412,2383,2352,2320,2287,2255,
+2224,2194,2163,2131,2097,2063,2032,2003,1975,1946,1916,1887,1859,1831,1804,1777,1753,1733,1717,1705,1696,
+1687,1675,1656,1631,1605,1587,1583,1594,1611,1620,1613,1586,1541,1487,1431,1380,1336,1299,1263,1224,1179,
+1133,1089,1051,1016,978,937,894,854,820,788,755,718,680,644,610,576,540,501,463,429,396,
+359,314,263,211,162,117,75,32,-11,-55,-96,-134,-169,-203,-240,-283,-330,-380,-430,-478,-523,
+-565,-607,-648,-691,-740,-791,-843,-891,-936,-980,-1026,-1076,-1126,-1175,-1222,-1269,-1317,-1365,-1412,-1457,-1501,
+-1545,-1589,-1632,-1675,-1722,-1775,-1828,-1878,-1922,-1960,-1999,-2041,-2086,-2131,-2174,-2216,-2258,-2300,-2341,-2380,-2418,
+-2458,-2499,-2540,-2577,-2610,-2639,-2664,-2688,-2712,-2741,-2777,-2816,-2852,-2883,-2908,-2934,-2964,-2995,-3023,-3047,-3070,
+-3097,-3127,-3156,-3175,-3185,-3192,-3204,-3226,-3250,-3271,-3286,-3296,-3306,-3318,-3331,-3344,-3359,-3377,-3396,-3413,-3425,
+-3432,-3437,-3445,-3456,-3467,-3476,-3481,-3483,-3482,-3479,-3476,-3474,-3475,-3479,-3483,-3485,-3483,-3479,-3477,-3476,-3475,
+-3473,-3469,-3465,-3461,-3456,-3449,-3439,-3428,-3420,-3414,-3408,-3402,-3393,-3383,-3374,-3367,-3361,-3353,-3343,-3331,-3317,
+-3302,-3286,-3269,-3254,-3240,-3227,-3214,-3199,-3180,-3159,-3138,-3118,-3103,-3089,-3075,-3060,-3042,-3023,-3004,-2984,-2962,
+-2939,-2916,-2898,-2884,-2871,-2853,-2831,-2807,-2788,-2772,-2755,-2731,-2700,-2666,-2634,-2604,-2574,-2542,-2509,-2478,-2450,
+-2422,-2392,-2362,-2331,-2301,-2268,-2229,-2186,-2140,-2095,-2051,-2006,-1960,-1913,-1869,-1829,-1794,-1760,-1724,-1685,-1645,
+-1607,-1572,-1541,-1516,-1495,-1474,-1449,-1417,-1376,-1331,-1286,-1243,-1198,-1142,-1066,-967,-850,-725,-603,-493,-395,
+-306,-224,-151,-96,-64,-54,-53,-46,-29,-5,14,25,33,41,52,64,78,102,142,188,214,
+191,112,0,-105,-168,-184,-172,-154,-138,-119,-87,-40,11,57,90,113,134,161,197,238,273,
+296,305,308,315,328,347,364,379,393,408,422,437,453,473,495,513,522,522,520,526,538,
+552,562,571,586,611,642,673,699,724,753,782,806,828,862,918,994,1069,1122,1149,1172,1213,
+1279,1350,1402,1418,1408,1392,1394,1424,1484,1564,1653,1738,1812,1874,1927,1976,2018,2051,2071,2081,2083,
+2080,2072,2059,2046,2041,2046,2061,2082,2107,2131,2146,2144,2118,2074,2025,1983,1953,1931,1916,1911,1923,
+1955,1998,2033,2035,1991,1910,1820,1763,1769,1843,1954,2057,2109,2098,2044,1986,1958,1974,2022,2076,2114,
+2127,2123,2115,2107,2097,2075,2037,1991,1945,1902,1859,1809,1754,1703,1663,1632,1599,1554,1495,1426,1354,
+1283,1217,1163,1124,1098,1076,1050,1022,997,980,966,945,911,869,828,794,766,741,720,707,701,
+691,670,646,640,669,729,792,827,819,783,744,713,682,635,569,501,452,431,431,435,431,
+417,400,383,368,353,336,318,297,274,252,235,223,217,210,202,192,186,185,185,183,172,
+154,130,106,82,61,44,31,21,10,-3,-21,-42,-64,-83,-101,-118,-134,-153,-173,-195,-220,
+-248,-277,-308,-337,-365,-394,-424,-459,-497,-536,-572,-604,-633,-661,-689,-718,-745,-769,-789,-806,-819,
+-832,-845,-860,-877,-894,-911,-925,-937,-946,-953,-961,-969,-977,-986,-994,-1003,-1015,-1030,-1047,-1063,-1074,
+-1083,-1091,-1099,-1107,-1114,-1119,-1126,-1135,-1146,-1156,-1165,-1174,-1182,-1190,-1195,-1196,-1196,-1195,-1197,-1201,-1206,
+-1210,-1215,-1220,-1225,-1228,-1230,-1231,-1233,-1236,-1239,-1242,-1246,-1250,-1254,-1259,-1264,-1268,-1271,-1273,-1273,-1274,
+-1277,-1283,-1289,-1292,-1290,-1285,-1279,-1271,-1261,-1251,-1241,-1234,-1232,-1232,-1231,-1229,-1229,-1231,-1233,-1233,-1230,
+-1224,-1221,-1222,-1225,-1226,-1224,-1220,-1219,-1220,-1222,-1225,-1227,-1229,-1231,-1233,-1236,-1241,-1249,-1258,-1265,-1269,
+-1272,-1276,-1283,-1292,-1298,-1301,-1300,-1298,-1296,-1295,-1291,-1286,-1281,-1277,-1275,-1274,-1270,-1264,-1255,-1246,-1239,
+-1232,-1224,-1214,-1203,-1192,-1182,-1172,-1163,-1154,-1146,-1139,-1134,-1129,-1122,-1114,-1107,-1102,-1098,-1092,-1080,-1065,
+-1053,-1046,-1044,-1043,-1039,-1034,-1030,-1029,-1030,-1028,-1024,-1020,-1017,-1014,-1008,-999,-988,-979,-974,-970,-966,
+-958,-948,-937,-925,-912,-897,-881,-865,-850,-836,-822,-809,-796,-785,-778,-773,-770,-767,-762,-756,-750,
+-742,-733,-721,-708,-695,-683,-672,-660,-647,-633,-617,-599,-577,-551,-521,-491,-463,-440,-419,-403,-388,
+-376,-362,-347,-332,-318,-306,-294,-279,-260,-242,-227,-216,-206,-195,-181,-168,-158,-153,-148,-141,-132,
+-124,-117,-108,-98,-88,-79,-74,-68,-61,-52,-42,-33,-24,-14,-1,11,23,31,36,42,51,
+65,83,106,135,168,202,234,265,295,325,355,387,418,450,481,511,539,565,591,621,653,
+685,716,746,779,814,850,881,910,940,973,1007,1036,1057,1071,1083,1089,1079,1046,997,958,954,
+997,1073,1160,1246,1334,1437,1555,1675,1785,1884,1984,2094,2209,2311,2378,2403,2390,2349,2293,2231,2175,
+2133,2109,2092,2073,2042,2001,1957,1914,1875,1839,1804,1770,1735,1696,1652,1607,1564,1526,1491,1459,1431,
+1412,1402,1397,1389,1374,1355,1338,1329,1331,1341,1353,1363,1371,1375,1376,1370,1355,1330,1304,1285,1278,
+1283,1292,1302,1309,1311,1306,1290,1264,1231,1198,1163,1118,1056,975,881,782,678,565,446,334,244,
+183,146,120,94,65,37,9,-19,-53,-94,-134,-171,-200,-223,-244,-265,-288,-312,-335,-357,-377,
+-396,-415,-435,-453,-470,-486,-501,-516,-530,-543,-559,-580,-601,-618,-628,-636,-648,-666,-685,-699,-705,
+-710,-718,-730,-740,-742,-738,-733,-730,-726,-719,-707,-694,-683,-674,-662,-647,-631,-617,-605,-591,-572,
+-549,-526,-504,-480,-452,-421,-392,-370,-353,-333,-307,-277,-248,-222,-196,-166,-129,-87,-44,-2,41,
+88,137,187,235,281,325,369,414,463,517,577,635,688,732,773,814,859,905,947,985,1020,
+1058,1099,1142,1184,1224,1262,1302,1344,1386,1426,1465,1501,1534,1563,1588,1614,1642,1673,1706,1738,1768,
+1798,1828,1856,1880,1901,1921,1947,1979,2013,2044,2070,2093,2116,2140,2164,2186,2206,2223,2240,2257,2275,
+2293,2311,2328,2344,2355,2361,2360,2352,2342,2334,2331,2332,2332,2330,2327,2325,2326,2326,2322,2312,2302,
+2297,2298,2296,2285,2266,2248,2239,2239,2238,2227,2210,2197,2199,2211,2219,2207,2177,2148,2143,2168,2208,
+2234,2221,2169,2092,2017,1960,1926,1908,1896,1884,1871,1857,1841,1824,1806,1787,1770,1759,1753,1751,1748,
+1741,1729,1715,1704,1698,1699,1722,1727,1732,1740,1754,1771,1788,1804,1820,1836,1855,1873,1891,1906,1919,
+1930,1937,1943,1950,1961,1973,1983,1989,1995,2006,2024,2046,2067,2086,2106,2133,2165,2198,2230,2262,2300,
+2341,2380,2410,2432,2453,2479,2507,2527,2538,2546,2565,2597,2634,2659,2668,2665,2658,2651,2637,2616,2597,
+2596,2620,2660,2698,2720,2727,2732,2744,2765,2790,2815,2838,2863,2889,2912,2928,2935,2932,2923,2912,2907,
+2911,2922,2936,2943,2941,2937,2936,2943,2955,2967,2977,2987,2998,3010,3020,3031,3050,3086,3141,3210,3279,
+3338,3383,3418,3446,3469,3482,3483,3470,3448,3426,3408,3395,3384,3370,3352,3332,3318,3313,3315,3315,3304,
+3279,3246,3222,3222,3252,3303,3357,3392,3401,3389,3370,3357,3352,3346,3332,3313,3298,3294,3297,3298,3293,
+3284,3284,3298,3320,3340,3352,3361,3373,3392,3412,3431,3452,3479,3515,3556,3595,3631,3669,3712,3757,3796,
+3828,3860,3897,3938,3972,3997,4020,4053,4095,4130,4142,4135,4132,4151,4191,4228,4244,4241,4241,4257,4281,
+4293,4284,4264,4252,4253,4257,4246,4219,4187,4160,4141,4122,4101,4082,4070,4062,4051,4034,4016,4006,4000,
+3986,3955,3912,3873,3850,3838,3822,3794,3755,3714,3675,3635,3587,3534,3485,3447,3417,3387,3354,3319,3287,
+3258,3227,3191,3152,3115,3083,3054,3024,2994,2966,2943,2924,2903,2880,2852,2824,2797,2774,2755,2740,2728,
+2717,2706,2696,2688,2683,2680,2678,2674,2669,2662,2652,2638,2622,2607,2597,2588,2579,2567,2556,2548,2545,
+2543,2537,2528,2518,2507,2495,2476,2450,2419,2388,2359,2331,2302,2273,2244,2214,2183,2150,2115,2080,2047,
+2017,1988,1960,1933,1907,1879,1850,1821,1796,1777,1762,1751,1739,1725,1708,1686,1663,1644,1634,1636,1647,
+1658,1659,1643,1610,1567,1518,1471,1427,1386,1347,1306,1264,1222,1181,1145,1110,1074,1032,987,944,908,
+877,848,816,779,742,705,670,633,595,558,523,491,458,416,365,310,259,214,175,138,99,
+59,18,-20,-58,-95,-132,-171,-214,-261,-311,-363,-413,-459,-501,-541,-584,-630,-680,-731,-781,-827,
+-873,-920,-969,-1019,-1066,-1111,-1157,-1206,-1256,-1305,-1351,-1394,-1437,-1482,-1528,-1573,-1618,-1665,-1716,-1767,-1815,
+-1858,-1896,-1936,-1980,-2027,-2073,-2117,-2158,-2199,-2240,-2279,-2319,-2359,-2401,-2443,-2483,-2519,-2550,-2579,-2606,-2630,
+-2655,-2684,-2720,-2760,-2798,-2829,-2855,-2881,-2910,-2941,-2969,-2992,-3015,-3041,-3073,-3103,-3125,-3138,-3148,-3163,-3186,
+-3211,-3232,-3247,-3259,-3272,-3288,-3304,-3318,-3333,-3349,-3366,-3382,-3392,-3398,-3402,-3409,-3419,-3430,-3439,-3445,-3449,
+-3451,-3449,-3445,-3442,-3443,-3448,-3453,-3454,-3451,-3447,-3445,-3446,-3447,-3446,-3441,-3436,-3434,-3433,-3428,-3419,-3407,
+-3398,-3392,-3387,-3378,-3367,-3356,-3348,-3344,-3340,-3333,-3321,-3308,-3297,-3287,-3276,-3261,-3244,-3228,-3213,-3199,-3183,
+-3164,-3143,-3121,-3101,-3084,-3070,-3059,-3046,-3031,-3011,-2989,-2966,-2943,-2921,-2902,-2885,-2871,-2858,-2842,-2822,-2801,
+-2781,-2762,-2742,-2715,-2682,-2647,-2615,-2590,-2567,-2544,-2518,-2490,-2460,-2428,-2394,-2357,-2321,-2285,-2248,-2209,-2165,
+-2120,-2074,-2031,-1989,-1948,-1908,-1869,-1832,-1797,-1764,-1731,-1698,-1662,-1624,-1584,-1549,-1526,-1516,-1511,-1500,-1471,
+-1426,-1377,-1334,-1300,-1269,-1227,-1166,-1084,-985,-872,-749,-619,-486,-359,-248,-165,-117,-102,-107,-116,-113,
+-97,-74,-55,-39,-21,3,28,46,55,69,100,144,172,151,70,-42,-143,-199,-209,-198,-187,
+-182,-168,-136,-89,-42,-5,20,44,74,110,148,182,207,222,231,238,249,264,282,299,315,
+331,347,362,375,387,401,420,439,452,457,459,464,475,488,500,513,531,557,587,615,641,
+669,702,736,764,786,814,858,920,985,1034,1066,1092,1132,1189,1250,1293,1308,1304,1299,1312,1353,
+1420,1505,1593,1675,1744,1799,1844,1883,1916,1942,1962,1978,1992,2000,1999,1991,1982,1980,1988,2002,2017,
+2035,2055,2070,2065,2030,1965,1888,1817,1762,1717,1673,1630,1599,1595,1624,1675,1725,1755,1759,1752,1756,
+1792,1861,1944,2007,2028,2006,1962,1929,1928,1963,2014,2057,2080,2081,2072,2063,2055,2041,2014,1974,1928,
+1883,1839,1795,1745,1696,1652,1617,1585,1545,1490,1422,1348,1275,1208,1148,1100,1065,1039,1015,987,958,
+932,913,895,868,829,788,753,730,711,690,665,645,634,631,626,618,611,614,625,635,635,
+630,636,660,690,694,648,556,448,366,331,338,361,377,376,362,342,323,306,292,276,258,
+236,211,189,174,166,161,155,149,143,141,140,136,126,110,90,70,52,36,21,8,-3,
+-14,-26,-41,-60,-82,-104,-125,-142,-158,-173,-189,-207,-228,-252,-280,-310,-339,-368,-395,-425,-458,
+-494,-530,-566,-599,-630,-661,-691,-722,-753,-783,-809,-828,-843,-854,-866,-881,-899,-918,-934,-948,-958,
+-967,-976,-987,-998,-1008,-1013,-1014,-1014,-1017,-1027,-1043,-1061,-1077,-1090,-1100,-1110,-1119,-1126,-1131,-1136,-1143,
+-1152,-1164,-1176,-1188,-1198,-1206,-1211,-1213,-1213,-1213,-1214,-1216,-1218,-1221,-1224,-1229,-1233,-1237,-1240,-1242,-1245,
+-1248,-1252,-1258,-1263,-1269,-1273,-1275,-1277,-1278,-1279,-1279,-1279,-1279,-1283,-1288,-1292,-1293,-1290,-1286,-1282,-1278,
+-1273,-1265,-1256,-1249,-1246,-1245,-1243,-1240,-1237,-1236,-1235,-1232,-1227,-1221,-1218,-1219,-1221,-1222,-1221,-1217,-1215,
+-1214,-1215,-1217,-1220,-1222,-1224,-1227,-1232,-1240,-1251,-1261,-1268,-1270,-1271,-1274,-1281,-1291,-1297,-1299,-1297,-1295,
+-1293,-1290,-1284,-1275,-1268,-1266,-1266,-1267,-1265,-1258,-1248,-1238,-1230,-1224,-1218,-1211,-1203,-1195,-1186,-1176,-1165,
+-1155,-1145,-1138,-1132,-1126,-1117,-1108,-1101,-1097,-1094,-1087,-1075,-1061,-1051,-1047,-1048,-1046,-1041,-1034,-1030,-1031,
+-1033,-1033,-1028,-1021,-1015,-1011,-1005,-997,-987,-980,-976,-974,-968,-958,-945,-933,-922,-911,-897,-881,-864,
+-848,-835,-823,-813,-803,-793,-786,-781,-777,-773,-766,-759,-751,-743,-735,-725,-715,-704,-693,-679,-663,
+-645,-627,-609,-592,-573,-550,-522,-492,-463,-438,-417,-399,-382,-367,-350,-334,-318,-304,-292,-281,-268,
+-252,-234,-218,-205,-194,-184,-173,-162,-152,-143,-134,-126,-122,-119,-117,-111,-101,-89,-80,-74,-69,
+-63,-54,-43,-32,-21,-10,0,11,21,28,35,43,54,69,89,115,145,179,213,245,274,
+301,326,354,384,418,452,484,512,537,562,591,625,658,688,716,744,777,814,850,881,910,
+940,975,1012,1043,1067,1084,1098,1104,1091,1054,1001,958,952,995,1077,1176,1276,1374,1477,1585,1695,
+1800,1904,2012,2126,2235,2320,2365,2372,2352,2321,2286,2247,2211,2182,2167,2162,2153,2129,2086,2030,1974,
+1925,1884,1846,1805,1760,1710,1660,1610,1565,1524,1490,1463,1442,1426,1414,1403,1389,1369,1342,1315,1297,
+1296,1312,1334,1353,1363,1367,1369,1372,1371,1362,1344,1324,1311,1306,1308,1312,1314,1312,1302,1282,1255,
+1224,1193,1155,1100,1022,925,819,711,603,492,382,285,211,161,127,97,66,39,17,-1,-26,
+-61,-102,-140,-171,-195,-217,-239,-264,-288,-311,-333,-355,-376,-397,-418,-438,-458,-476,-492,-505,-518,
+-532,-549,-569,-591,-612,-627,-638,-647,-660,-676,-693,-705,-713,-720,-728,-738,-745,-747,-746,-744,-742,
+-737,-726,-712,-698,-687,-676,-662,-644,-625,-609,-595,-578,-557,-533,-510,-489,-468,-442,-411,-381,-355,
+-334,-312,-286,-259,-232,-207,-181,-152,-120,-86,-51,-14,28,76,127,177,226,275,324,372,419,
+466,518,574,631,683,728,769,811,856,901,941,976,1010,1049,1092,1136,1178,1217,1258,1302,1347,
+1390,1428,1465,1499,1532,1560,1585,1610,1638,1671,1706,1741,1777,1813,1849,1879,1903,1921,1942,1971,2006,
+2041,2071,2096,2118,2141,2165,2187,2205,2222,2240,2258,2276,2292,2307,2324,2342,2357,2367,2370,2369,2366,
+2363,2360,2358,2356,2351,2344,2336,2329,2326,2325,2322,2318,2314,2314,2317,2316,2308,2293,2281,2275,2272,
+2262,2241,2216,2202,2206,2219,2222,2205,2175,2155,2165,2203,2249,2276,2265,2219,2150,2075,2010,1959,1924,
+1904,1892,1883,1873,1860,1844,1826,1807,1790,1777,1770,1767,1763,1753,1739,1725,1718,1718,1722,1747,1747,
+1746,1750,1763,1783,1804,1819,1830,1838,1848,1861,1879,1899,1917,1930,1934,1933,1935,1945,1961,1978,1989,
+1995,2003,2017,2038,2061,2082,2104,2132,2168,2208,2248,2286,2324,2362,2398,2428,2453,2477,2503,2530,2551,
+2562,2570,2584,2609,2642,2671,2687,2684,2663,2632,2603,2591,2609,2656,2717,2767,2788,2783,2768,2763,2776,
+2802,2830,2855,2877,2897,2915,2929,2936,2938,2937,2933,2926,2921,2922,2930,2941,2947,2945,2938,2935,2942,
+2956,2972,2983,2990,2995,3006,3024,3050,3087,3135,3192,3254,3314,3366,3410,3445,3473,3493,3503,3501,3488,
+3469,3451,3438,3431,3424,3411,3390,3364,3342,3331,3330,3329,3319,3297,3272,3256,3263,3294,3340,3385,3414,
+3421,3411,3395,3382,3372,3362,3347,3330,3317,3312,3313,3312,3308,3305,3313,3334,3362,3388,3408,3425,3444,
+3466,3488,3506,3523,3547,3580,3619,3659,3698,3738,3781,3822,3858,3888,3920,3957,3997,4032,4060,4086,4120,
+4159,4190,4202,4200,4204,4226,4261,4286,4290,4279,4275,4290,4312,4319,4301,4268,4241,4230,4229,4223,4206,
+4181,4159,4140,4124,4109,4096,4088,4079,4065,4049,4036,4031,4025,4008,3973,3931,3898,3879,3868,3850,3817,
+3774,3732,3693,3654,3610,3565,3525,3495,3469,3441,3408,3373,3340,3309,3275,3238,3199,3163,3130,3097,3062,
+3028,3000,2980,2963,2944,2920,2892,2865,2841,2819,2801,2784,2770,2756,2743,2731,2721,2715,2713,2711,2708,
+2701,2689,2672,2653,2634,2619,2608,2600,2591,2581,2574,2570,2570,2568,2564,2557,2551,2544,2534,2515,2487,
+2456,2426,2400,2376,2350,2322,2292,2262,2232,2198,2162,2125,2090,2057,2028,2001,1977,1952,1926,1898,1870,
+1845,1825,1811,1797,1781,1761,1738,1717,1701,1691,1689,1692,1697,1698,1690,1668,1635,1595,1552,1511,1471,
+1432,1391,1349,1308,1269,1235,1202,1166,1126,1082,1039,1001,969,942,912,877,840,802,765,729,690,
+652,616,584,553,516,468,412,357,310,273,241,208,172,134,96,60,23,-16,-57,-101,-147,
+-196,-247,-299,-348,-392,-432,-473,-518,-568,-620,-670,-716,-760,-806,-856,-906,-954,-999,-1043,-1091,-1143,
+-1197,-1247,-1292,-1333,-1376,-1423,-1471,-1519,-1566,-1613,-1661,-1709,-1753,-1794,-1834,-1878,-1925,-1974,-2020,-2063,-2103,
+-2142,-2182,-2221,-2260,-2302,-2345,-2386,-2424,-2457,-2486,-2515,-2543,-2572,-2600,-2632,-2668,-2706,-2742,-2773,-2800,-2828,
+-2858,-2890,-2917,-2940,-2961,-2987,-3018,-3050,-3075,-3093,-3108,-3127,-3151,-3176,-3196,-3211,-3223,-3238,-3255,-3272,-3287,
+-3301,-3316,-3333,-3348,-3360,-3367,-3372,-3377,-3385,-3392,-3399,-3406,-3413,-3417,-3416,-3412,-3409,-3410,-3416,-3423,-3424,
+-3419,-3413,-3412,-3416,-3421,-3421,-3417,-3412,-3409,-3408,-3403,-3393,-3380,-3371,-3367,-3364,-3357,-3346,-3334,-3327,-3324,
+-3322,-3315,-3303,-3290,-3278,-3269,-3258,-3243,-3226,-3210,-3196,-3183,-3168,-3150,-3129,-3107,-3085,-3066,-3050,-3038,-3026,
+-3011,-2991,-2969,-2947,-2927,-2909,-2893,-2877,-2862,-2847,-2831,-2813,-2792,-2771,-2749,-2725,-2696,-2664,-2633,-2606,-2586,
+-2569,-2549,-2523,-2491,-2456,-2420,-2381,-2341,-2301,-2261,-2224,-2187,-2149,-2109,-2068,-2028,-1988,-1949,-1913,-1877,-1840,
+-1804,-1769,-1736,-1705,-1673,-1637,-1597,-1560,-1538,-1532,-1536,-1531,-1506,-1465,-1419,-1381,-1353,-1324,-1284,-1231,-1168,
+-1096,-1007,-890,-741,-573,-410,-279,-196,-161,-159,-169,-172,-160,-138,-116,-100,-85,-63,-33,-3,16,
+27,44,79,123,144,110,16,-100,-192,-233,-233,-221,-218,-218,-206,-171,-126,-89,-67,-50,-25,
+14,58,95,119,132,142,154,168,184,201,220,240,259,277,293,306,317,326,337,352,368,
+382,390,394,400,411,427,445,464,485,508,533,559,587,620,659,698,728,748,766,795,838,
+889,936,974,1010,1051,1099,1144,1175,1186,1188,1196,1224,1277,1353,1442,1532,1611,1674,1723,1760,1791,
+1815,1836,1855,1874,1892,1906,1913,1915,1919,1927,1936,1942,1945,1953,1972,1994,1999,1965,1890,1792,1697,
+1616,1543,1466,1385,1317,1287,1313,1389,1493,1599,1686,1749,1793,1828,1861,1890,1906,1902,1881,1858,1854,
+1879,1930,1988,2033,2054,2053,2043,2032,2018,1995,1958,1911,1861,1816,1775,1733,1688,1640,1595,1555,1515,
+1468,1411,1347,1279,1213,1153,1099,1055,1022,995,967,934,898,867,843,819,790,753,717,689,671,
+658,640,616,595,586,588,596,599,593,576,548,511,475,459,477,530,591,621,594,512,407,
+317,268,261,277,297,309,309,300,283,264,244,225,207,187,166,145,129,118,112,106,99,
+93,90,89,87,78,62,43,26,14,5,-3,-14,-27,-39,-50,-61,-75,-95,-119,-145,-169,
+-189,-204,-217,-228,-241,-259,-282,-309,-338,-367,-395,-424,-455,-489,-524,-560,-595,-628,-660,-692,-724,
+-757,-791,-823,-848,-864,-875,-886,-902,-921,-941,-958,-970,-980,-987,-996,-1007,-1019,-1029,-1035,-1034,-1030,
+-1028,-1032,-1043,-1059,-1076,-1091,-1105,-1117,-1128,-1136,-1140,-1144,-1148,-1156,-1168,-1180,-1192,-1203,-1212,-1220,-1226,
+-1230,-1231,-1232,-1232,-1233,-1236,-1239,-1243,-1248,-1252,-1257,-1261,-1263,-1266,-1269,-1274,-1281,-1286,-1289,-1288,-1286,
+-1285,-1285,-1286,-1287,-1288,-1289,-1290,-1290,-1288,-1283,-1279,-1279,-1280,-1281,-1279,-1274,-1270,-1267,-1266,-1264,-1260,
+-1255,-1249,-1243,-1236,-1227,-1220,-1217,-1218,-1221,-1223,-1221,-1217,-1213,-1210,-1209,-1207,-1208,-1210,-1213,-1218,-1226,
+-1235,-1246,-1256,-1263,-1266,-1268,-1272,-1280,-1289,-1294,-1295,-1294,-1292,-1290,-1286,-1280,-1273,-1268,-1266,-1266,-1264,
+-1259,-1250,-1239,-1230,-1222,-1216,-1211,-1207,-1202,-1196,-1190,-1182,-1173,-1162,-1152,-1143,-1134,-1125,-1116,-1106,-1098,
+-1094,-1090,-1083,-1072,-1060,-1052,-1049,-1048,-1046,-1040,-1034,-1031,-1033,-1035,-1033,-1026,-1018,-1012,-1008,-1003,-996,
+-987,-980,-975,-971,-964,-951,-936,-923,-912,-904,-894,-882,-866,-850,-835,-823,-814,-805,-798,-791,-784,
+-778,-772,-764,-756,-749,-743,-738,-732,-723,-711,-698,-682,-665,-646,-627,-609,-593,-574,-552,-524,-493,
+-463,-438,-417,-398,-381,-363,-346,-330,-314,-299,-285,-272,-259,-247,-233,-218,-203,-189,-178,-169,-160,
+-151,-140,-129,-121,-118,-118,-117,-112,-101,-90,-80,-72,-66,-58,-48,-36,-24,-13,-2,8,17,
+24,32,39,49,62,80,103,130,160,192,222,252,279,303,327,352,381,413,446,476,502,
+527,554,588,624,658,685,709,736,770,808,844,876,905,937,974,1012,1045,1071,1092,1107,1112,
+1096,1057,1004,962,957,1004,1097,1216,1340,1455,1557,1647,1731,1818,1916,2030,2150,2253,2320,2341,2329,
+2305,2287,2279,2274,2268,2262,2263,2267,2262,2235,2181,2108,2033,1968,1913,1859,1802,1742,1686,1634,1586,
+1541,1500,1468,1448,1435,1423,1409,1391,1372,1350,1324,1298,1280,1282,1304,1335,1357,1361,1351,1343,1343,
+1350,1355,1352,1343,1333,1325,1318,1310,1302,1294,1285,1272,1250,1220,1181,1127,1054,958,846,729,617,
+510,408,314,236,178,137,104,70,38,13,-2,-17,-39,-73,-109,-141,-164,-184,-207,-235,-263,
+-288,-309,-331,-354,-379,-402,-422,-441,-461,-479,-496,-510,-523,-538,-557,-578,-599,-617,-631,-643,-654,
+-667,-682,-697,-710,-722,-733,-742,-748,-751,-750,-750,-752,-752,-749,-738,-724,-710,-697,-683,-666,-644,
+-622,-602,-584,-564,-541,-518,-498,-482,-463,-439,-408,-374,-343,-317,-293,-269,-245,-221,-195,-167,-138,
+-110,-85,-60,-30,9,57,109,161,212,264,316,368,417,464,516,573,631,684,729,768,807,
+847,887,924,958,994,1035,1078,1121,1160,1199,1243,1291,1337,1377,1410,1442,1475,1509,1541,1570,1599,
+1632,1670,1710,1750,1789,1830,1868,1899,1922,1939,1960,1989,2025,2060,2088,2111,2135,2160,2183,2202,2218,
+2235,2255,2277,2296,2312,2328,2347,2367,2382,2388,2386,2383,2383,2386,2388,2385,2377,2366,2354,2342,2330,
+2322,2317,2317,2319,2323,2326,2327,2325,2321,2318,2320,2322,2316,2297,2266,2238,2227,2233,2243,2239,2215,
+2183,2162,2166,2187,2210,2220,2210,2185,2148,2102,2049,1996,1952,1922,1905,1894,1882,1869,1856,1843,1829,
+1815,1802,1791,1783,1775,1764,1752,1743,1741,1744,1747,1760,1756,1753,1757,1770,1787,1804,1818,1830,1840,
+1849,1859,1871,1888,1908,1926,1935,1936,1935,1940,1955,1973,1987,1995,2001,2012,2031,2055,2080,2107,2140,
+2181,2227,2271,2310,2345,2379,2412,2444,2474,2502,2530,2555,2576,2591,2604,2619,2638,2660,2677,2682,2670,
+2645,2617,2605,2626,2683,2763,2838,2880,2880,2854,2827,2818,2829,2849,2866,2879,2892,2907,2921,2933,2941,
+2947,2953,2956,2952,2942,2934,2934,2940,2947,2949,2946,2946,2953,2966,2978,2984,2985,2990,3006,3038,3082,
+3133,3184,3233,3282,3331,3381,3428,3468,3496,3511,3515,3511,3503,3494,3487,3483,3480,3473,3457,3430,3396,
+3365,3345,3334,3329,3321,3309,3297,3292,3299,3321,3350,3378,3397,3402,3397,3386,3375,3367,3359,3349,3339,
+3331,3327,3326,3325,3325,3330,3348,3379,3416,3449,3474,3494,3516,3542,3566,3585,3601,3622,3651,3689,3731,
+3773,3813,3850,3884,3915,3945,3978,4017,4057,4092,4118,4139,4163,4190,4216,4236,4253,4273,4299,4321,4327,
+4317,4302,4299,4312,4327,4326,4303,4270,4243,4231,4229,4225,4213,4194,4173,4154,4136,4124,4117,4113,4104,
+4089,4071,4058,4053,4047,4026,3990,3948,3915,3899,3887,3868,3833,3789,3747,3709,3674,3637,3602,3572,3548,
+3524,3496,3463,3427,3393,3359,3321,3281,3242,3206,3172,3137,3100,3066,3040,3023,3006,2985,2956,2925,2897,
+2876,2858,2841,2824,2807,2792,2777,2763,2751,2744,2741,2739,2736,2728,2713,2694,2672,2653,2638,2627,2619,
+2611,2603,2597,2594,2593,2591,2588,2584,2581,2577,2568,2550,2523,2494,2467,2443,2420,2393,2363,2332,2302,
+2271,2237,2202,2166,2131,2099,2069,2042,2017,1995,1972,1948,1922,1897,1876,1859,1841,1820,1795,1770,1753,
+1744,1743,1745,1745,1740,1730,1715,1692,1661,1625,1587,1549,1512,1475,1437,1398,1360,1324,1289,1255,1216,
+1174,1132,1094,1063,1037,1010,977,939,899,861,824,787,748,709,674,643,609,566,514,458,409,
+373,345,318,285,246,206,169,134,98,57,14,-32,-81,-133,-187,-239,-286,-327,-366,-408,-456,
+-509,-561,-608,-650,-693,-739,-790,-841,-888,-932,-977,-1027,-1082,-1137,-1186,-1229,-1270,-1313,-1360,-1409,-1459,
+-1507,-1555,-1603,-1648,-1689,-1728,-1768,-1813,-1863,-1914,-1961,-2004,-2043,-2082,-2122,-2163,-2203,-2245,-2287,-2328,-2364,
+-2395,-2424,-2452,-2481,-2511,-2543,-2575,-2610,-2644,-2677,-2707,-2736,-2767,-2801,-2835,-2865,-2889,-2913,-2940,-2971,-3002,
+-3029,-3049,-3068,-3089,-3114,-3138,-3157,-3172,-3186,-3202,-3219,-3236,-3250,-3264,-3279,-3297,-3314,-3328,-3337,-3343,-3349,
+-3356,-3364,-3371,-3378,-3384,-3387,-3386,-3382,-3379,-3382,-3388,-3394,-3395,-3388,-3381,-3379,-3383,-3389,-3391,-3387,-3382,
+-3379,-3377,-3372,-3362,-3350,-3342,-3339,-3339,-3334,-3324,-3312,-3304,-3302,-3299,-3293,-3282,-3269,-3257,-3245,-3232,-3217,
+-3200,-3185,-3173,-3161,-3148,-3130,-3110,-3088,-3066,-3047,-3031,-3019,-3007,-2993,-2974,-2952,-2932,-2915,-2901,-2886,-2869,
+-2852,-2836,-2821,-2804,-2783,-2758,-2733,-2706,-2678,-2651,-2625,-2604,-2586,-2569,-2544,-2512,-2473,-2434,-2397,-2360,-2321,
+-2281,-2240,-2202,-2169,-2138,-2105,-2070,-2031,-1992,-1954,-1919,-1885,-1850,-1813,-1777,-1744,-1714,-1686,-1653,-1615,-1580,
+-1556,-1548,-1548,-1542,-1521,-1489,-1457,-1434,-1413,-1385,-1342,-1290,-1240,-1190,-1124,-1016,-856,-662,-474,-329,-248,
+-222,-224,-227,-215,-189,-160,-139,-126,-114,-95,-70,-47,-32,-18,9,60,114,131,83,-24,-148,
+-236,-268,-262,-252,-255,-259,-245,-207,-164,-136,-126,-117,-90,-46,1,34,49,55,62,77,96,
+117,139,162,185,204,219,228,237,246,256,269,283,298,311,320,325,332,344,363,387,412,
+435,457,478,503,533,569,610,649,679,698,712,732,763,804,847,888,925,963,1000,1033,1055,
+1068,1079,1097,1134,1193,1271,1362,1452,1530,1591,1637,1673,1704,1730,1751,1768,1783,1796,1808,1819,1833,
+1851,1869,1878,1875,1867,1869,1891,1921,1931,1897,1816,1710,1605,1512,1422,1324,1222,1142,1115,1157,1262,
+1404,1549,1673,1761,1808,1820,1811,1794,1779,1767,1758,1757,1774,1816,1880,1950,2005,2034,2038,2028,2012,
+1992,1960,1915,1859,1804,1758,1720,1683,1640,1589,1534,1479,1428,1380,1332,1282,1229,1174,1121,1072,1030,
+996,964,928,888,846,807,774,747,720,692,666,645,627,610,589,567,551,547,555,566,571,
+562,537,497,447,399,369,371,405,454,494,504,478,423,357,294,246,216,208,216,231,242,
+239,224,200,176,155,137,119,102,87,76,68,60,50,41,38,38,39,33,18,-2,-19,
+-29,-31,-33,-39,-51,-65,-78,-89,-102,-119,-143,-170,-197,-220,-237,-248,-255,-261,-272,-290,-314,
+-342,-371,-399,-428,-457,-489,-523,-559,-597,-633,-666,-696,-726,-758,-793,-828,-859,-880,-894,-907,-922,
+-942,-962,-981,-995,-1005,-1012,-1018,-1026,-1034,-1044,-1051,-1053,-1052,-1048,-1047,-1052,-1062,-1077,-1093,-1109,-1125,
+-1137,-1145,-1149,-1151,-1156,-1164,-1174,-1185,-1195,-1205,-1216,-1227,-1237,-1244,-1248,-1250,-1251,-1254,-1257,-1262,-1266,
+-1270,-1274,-1278,-1281,-1282,-1283,-1284,-1287,-1292,-1297,-1298,-1295,-1292,-1291,-1292,-1295,-1296,-1296,-1295,-1295,-1293,
+-1289,-1284,-1281,-1281,-1284,-1288,-1290,-1289,-1289,-1288,-1287,-1284,-1279,-1273,-1266,-1258,-1248,-1237,-1228,-1224,-1225,
+-1226,-1226,-1223,-1218,-1213,-1209,-1204,-1200,-1198,-1199,-1205,-1214,-1223,-1232,-1242,-1250,-1257,-1264,-1270,-1276,-1283,
+-1288,-1291,-1290,-1289,-1289,-1288,-1286,-1283,-1280,-1277,-1275,-1271,-1264,-1253,-1242,-1233,-1225,-1219,-1213,-1207,-1201,
+-1196,-1191,-1187,-1181,-1174,-1164,-1153,-1142,-1132,-1123,-1115,-1106,-1099,-1093,-1088,-1082,-1073,-1063,-1054,-1047,-1044,
+-1040,-1037,-1034,-1034,-1034,-1034,-1029,-1021,-1013,-1009,-1006,-1003,-997,-988,-979,-972,-966,-957,-943,-927,-912,
+-901,-893,-885,-875,-862,-847,-832,-820,-810,-802,-795,-788,-781,-774,-766,-758,-751,-746,-743,-740,-735,
+-725,-712,-699,-687,-676,-662,-645,-625,-605,-583,-557,-527,-493,-462,-436,-416,-399,-383,-366,-350,-336,
+-322,-307,-290,-273,-260,-249,-238,-224,-207,-189,-175,-164,-155,-146,-134,-124,-117,-114,-111,-105,-96,
+-85,-74,-65,-56,-47,-37,-27,-16,-5,6,17,26,33,39,45,53,64,80,100,125,151,
+177,202,225,250,276,303,328,353,380,410,440,468,493,518,549,585,622,655,683,709,739,
+775,812,847,878,910,945,982,1019,1052,1080,1102,1117,1118,1099,1059,1012,978,981,1032,1133,1269,
+1415,1546,1648,1720,1776,1839,1928,2043,2165,2263,2313,2314,2287,2259,2253,2269,2295,2319,2340,2360,2375,
+2372,2339,2270,2178,2083,1996,1918,1840,1762,1690,1635,1594,1560,1521,1480,1446,1425,1416,1408,1393,1372,
+1351,1332,1312,1291,1278,1282,1308,1342,1364,1362,1341,1320,1313,1319,1331,1339,1342,1339,1331,1313,1288,
+1265,1252,1249,1247,1234,1201,1146,1070,975,865,746,628,517,416,325,246,183,139,106,76,44,
+14,-7,-21,-34,-56,-86,-115,-138,-155,-174,-201,-233,-263,-286,-306,-328,-354,-382,-405,-422,-438,
+-456,-475,-493,-508,-524,-541,-562,-583,-603,-619,-633,-646,-660,-674,-688,-701,-716,-731,-744,-753,-755,
+-754,-752,-753,-757,-759,-756,-747,-734,-720,-707,-691,-671,-647,-623,-600,-578,-554,-529,-508,-492,-480,
+-465,-442,-411,-376,-342,-312,-286,-264,-244,-223,-199,-170,-139,-110,-86,-64,-37,0,46,97,148,
+198,251,305,358,408,457,510,569,629,683,727,764,799,834,871,906,942,981,1024,1067,1107,
+1143,1183,1229,1279,1324,1359,1387,1415,1449,1487,1524,1559,1593,1632,1674,1717,1757,1796,1835,1873,1906,
+1930,1950,1973,2004,2039,2072,2099,2123,2148,2173,2196,2213,2227,2246,2272,2300,2323,2341,2357,2376,2396,
+2409,2410,2403,2397,2398,2403,2406,2401,2390,2378,2367,2357,2345,2333,2326,2326,2332,2340,2343,2340,2333,
+2330,2334,2345,2353,2346,2322,2290,2265,2257,2264,2270,2261,2236,2206,2185,2175,2169,2160,2149,2143,2142,
+2139,2121,2081,2029,1979,1944,1924,1910,1897,1885,1878,1873,1867,1854,1837,1819,1804,1792,1780,1769,1763,
+1761,1761,1760,1756,1753,1755,1763,1774,1783,1790,1799,1817,1840,1860,1870,1874,1880,1895,1918,1937,1946,
+1946,1947,1956,1971,1986,1996,2004,2017,2038,2065,2094,2126,2164,2208,2255,2299,2337,2369,2401,2434,2468,
+2500,2528,2553,2576,2598,2619,2639,2659,2676,2685,2684,2671,2650,2631,2624,2643,2695,2774,2858,2918,2936,
+2916,2881,2856,2855,2868,2882,2888,2889,2894,2908,2925,2939,2951,2960,2969,2973,2967,2954,2940,2934,2938,
+2948,2956,2960,2964,2970,2978,2985,2987,2988,2998,3023,3065,3116,3167,3211,3251,3291,3337,3390,3444,3489,
+3517,3528,3526,3522,3520,3522,3526,3527,3524,3511,3488,3454,3415,3376,3347,3330,3322,3321,3321,3321,3321,
+3323,3328,3338,3349,3360,3365,3361,3352,3342,3335,3332,3332,3333,3335,3340,3345,3351,3358,3373,3401,3439,
+3481,3516,3540,3558,3580,3607,3636,3661,3681,3701,3729,3767,3808,3847,3880,3908,3936,3965,3997,4033,4073,
+4113,4147,4169,4180,4185,4194,4213,4244,4283,4320,4344,4350,4339,4323,4315,4321,4333,4336,4321,4294,4267,
+4252,4247,4245,4239,4228,4212,4193,4172,4152,4139,4134,4133,4127,4110,4090,4075,4069,4062,4042,4006,3965,
+3934,3919,3910,3893,3860,3816,3770,3730,3696,3666,3639,3617,3597,3573,3545,3511,3477,3443,3406,3365,3322,
+3282,3246,3213,3180,3146,3117,3094,3076,3054,3024,2987,2952,2926,2908,2893,2878,2860,2841,2824,2807,2792,
+2780,2772,2768,2766,2762,2753,2739,2721,2700,2682,2668,2658,2650,2643,2636,2629,2624,2620,2617,2613,2610,
+2607,2603,2595,2579,2557,2532,2509,2486,2461,2434,2403,2371,2339,2306,2272,2238,2205,2175,2146,2116,2086,
+2059,2037,2018,1997,1973,1947,1922,1900,1877,1853,1828,1807,1795,1793,1796,1796,1790,1776,1759,1740,1718,
+1692,1660,1623,1587,1552,1519,1486,1451,1415,1377,1341,1303,1265,1225,1188,1156,1129,1104,1075,1039,999,
+957,918,881,844,806,768,732,696,657,611,560,511,473,447,426,400,364,320,276,236,199,
+162,121,76,29,-19,-71,-124,-175,-221,-261,-300,-344,-395,-449,-499,-543,-583,-625,-674,-726,-777,
+-825,-869,-914,-965,-1019,-1071,-1119,-1163,-1205,-1248,-1295,-1344,-1393,-1442,-1490,-1538,-1582,-1621,-1659,-1699,-1746,
+-1798,-1849,-1897,-1939,-1978,-2018,-2059,-2101,-2143,-2185,-2226,-2267,-2305,-2339,-2368,-2396,-2423,-2453,-2484,-2517,-2550,
+-2581,-2610,-2639,-2669,-2703,-2739,-2775,-2808,-2837,-2866,-2896,-2927,-2955,-2979,-3000,-3022,-3047,-3073,-3097,-3116,-3131,
+-3146,-3164,-3182,-3199,-3213,-3227,-3242,-3260,-3278,-3294,-3304,-3311,-3318,-3328,-3338,-3347,-3353,-3356,-3356,-3354,-3353,
+-3353,-3356,-3360,-3363,-3361,-3355,-3348,-3345,-3347,-3351,-3353,-3350,-3346,-3344,-3343,-3340,-3332,-3323,-3316,-3313,-3312,
+-3307,-3298,-3288,-3279,-3275,-3271,-3265,-3256,-3244,-3233,-3222,-3208,-3192,-3176,-3161,-3150,-3139,-3125,-3107,-3087,-3066,
+-3045,-3027,-3013,-3003,-2993,-2979,-2961,-2940,-2920,-2904,-2889,-2873,-2855,-2838,-2822,-2809,-2793,-2771,-2744,-2715,-2688,
+-2663,-2640,-2619,-2600,-2580,-2556,-2524,-2485,-2444,-2405,-2372,-2341,-2307,-2269,-2230,-2193,-2162,-2133,-2102,-2067,-2029,
+-1991,-1954,-1921,-1890,-1858,-1825,-1790,-1757,-1728,-1699,-1668,-1634,-1601,-1577,-1565,-1559,-1549,-1531,-1509,-1492,-1482,
+-1472,-1447,-1403,-1350,-1305,-1267,-1216,-1121,-967,-770,-572,-418,-328,-293,-282,-268,-239,-202,-170,-150,-141,
+-132,-116,-97,-83,-75,-62,-28,28,83,96,38,-76,-201,-287,-316,-310,-303,-308,-312,-296,-258,
+-217,-194,-187,-179,-151,-105,-58,-30,-21,-19,-12,2,23,46,72,100,126,144,150,151,156,
+167,184,201,215,227,239,249,257,266,278,297,322,350,376,400,422,448,479,514,550,584,
+611,632,649,670,698,734,773,810,844,874,902,927,949,968,988,1014,1053,1111,1189,1279,1368,
+1446,1505,1551,1589,1624,1656,1681,1697,1705,1709,1714,1727,1749,1776,1797,1803,1795,1787,1798,1831,1868,
+1874,1828,1737,1628,1527,1439,1350,1251,1156,1097,1104,1183,1311,1456,1589,1691,1754,1777,1763,1729,1692,
+1668,1662,1668,1684,1714,1765,1834,1910,1971,2005,2011,1998,1978,1954,1920,1873,1816,1758,1710,1673,1640,
+1598,1543,1477,1410,1353,1309,1272,1236,1195,1149,1102,1058,1018,978,935,888,839,792,751,718,690,
+668,650,634,618,595,567,538,515,505,509,520,526,522,506,480,447,411,375,341,317,311,
+328,368,420,465,482,455,387,297,212,157,140,151,170,181,177,160,139,116,95,74,56,
+41,31,23,15,4,-6,-11,-10,-7,-10,-22,-42,-61,-71,-71,-66,-66,-75,-91,-109,-126,
+-142,-160,-181,-206,-230,-252,-268,-278,-283,-287,-294,-308,-330,-357,-388,-418,-446,-472,-499,-529,-564,
+-604,-644,-679,-708,-733,-759,-791,-827,-862,-890,-911,-927,-943,-961,-981,-1001,-1017,-1029,-1038,-1043,-1047,
+-1052,-1058,-1066,-1072,-1075,-1072,-1068,-1066,-1070,-1081,-1098,-1116,-1134,-1147,-1154,-1158,-1161,-1167,-1175,-1185,-1195,
+-1204,-1213,-1224,-1236,-1249,-1258,-1264,-1268,-1272,-1277,-1284,-1290,-1294,-1297,-1298,-1300,-1300,-1300,-1299,-1298,-1299,
+-1301,-1303,-1303,-1301,-1300,-1301,-1304,-1307,-1308,-1307,-1307,-1306,-1306,-1303,-1298,-1294,-1292,-1292,-1294,-1296,-1298,
+-1300,-1301,-1299,-1294,-1287,-1280,-1275,-1270,-1263,-1254,-1245,-1241,-1238,-1236,-1231,-1224,-1217,-1212,-1208,-1203,-1199,
+-1196,-1197,-1203,-1211,-1220,-1227,-1233,-1240,-1248,-1258,-1269,-1279,-1285,-1287,-1287,-1286,-1285,-1286,-1286,-1285,-1284,
+-1284,-1283,-1280,-1273,-1261,-1248,-1236,-1229,-1223,-1217,-1210,-1201,-1193,-1187,-1182,-1178,-1173,-1166,-1157,-1146,-1134,
+-1125,-1118,-1112,-1105,-1098,-1091,-1085,-1079,-1072,-1063,-1052,-1043,-1036,-1034,-1034,-1035,-1036,-1035,-1030,-1023,-1015,
+-1008,-1004,-1003,-1000,-995,-987,-978,-969,-961,-950,-938,-923,-908,-895,-884,-875,-866,-855,-843,-831,-819,
+-809,-800,-792,-784,-778,-772,-765,-758,-752,-748,-746,-744,-738,-726,-713,-703,-697,-691,-680,-659,-632,
+-603,-576,-548,-517,-484,-453,-428,-411,-396,-382,-366,-351,-340,-328,-314,-296,-277,-262,-252,-242,-228,
+-210,-191,-174,-161,-150,-138,-126,-116,-110,-105,-99,-88,-75,-62,-52,-44,-34,-23,-12,-3,5,
+14,26,38,48,55,60,66,75,88,105,126,150,174,194,212,230,252,279,308,336,362,
+389,419,449,477,503,530,562,598,634,668,699,731,767,804,840,871,902,935,972,1008,1040,
+1068,1094,1117,1130,1127,1103,1066,1031,1012,1026,1082,1186,1329,1486,1627,1727,1784,1818,1862,1941,2053,
+2171,2261,2299,2289,2255,2228,2229,2256,2296,2336,2373,2408,2435,2441,2408,2333,2231,2122,2021,1926,1830,
+1735,1655,1601,1572,1551,1519,1475,1433,1407,1397,1392,1380,1360,1339,1321,1304,1288,1276,1281,1305,1338,
+1361,1361,1342,1319,1305,1305,1311,1318,1324,1326,1316,1288,1248,1210,1190,1191,1197,1186,1144,1071,975,
+867,754,639,529,427,335,254,188,137,102,75,50,23,-2,-23,-37,-52,-73,-98,-121,-139,
+-153,-174,-203,-236,-263,-283,-301,-323,-351,-378,-399,-414,-426,-442,-462,-481,-497,-513,-531,-554,-577,
+-598,-614,-629,-645,-663,-679,-694,-707,-722,-736,-748,-756,-758,-757,-758,-762,-766,-767,-762,-752,-740,
+-727,-713,-696,-675,-652,-628,-604,-579,-553,-528,-507,-492,-481,-467,-446,-417,-384,-351,-321,-294,-271,
+-253,-236,-215,-187,-154,-120,-90,-62,-31,6,51,99,148,196,248,301,354,405,455,508,566,
+624,677,721,757,790,825,861,898,936,978,1022,1063,1100,1135,1174,1220,1267,1309,1342,1371,1403,
+1442,1486,1526,1564,1600,1640,1683,1725,1762,1796,1833,1871,1907,1937,1964,1993,2026,2060,2089,2114,2136,
+2161,2185,2205,2218,2233,2255,2287,2322,2350,2369,2385,2402,2419,2428,2425,2414,2406,2406,2412,2415,2410,
+2399,2390,2385,2381,2373,2361,2352,2351,2357,2364,2365,2357,2346,2340,2343,2352,2357,2349,2326,2299,2279,
+2275,2280,2281,2272,2253,2234,2220,2205,2185,2162,2146,2148,2162,2170,2152,2106,2047,1996,1965,1949,1938,
+1927,1917,1913,1911,1905,1890,1868,1845,1826,1812,1800,1788,1778,1769,1762,1756,1734,1732,1744,1763,1780,
+1786,1783,1785,1805,1840,1873,1889,1888,1884,1891,1913,1939,1955,1959,1960,1965,1978,1994,2008,2023,2042,
+2068,2097,2128,2161,2198,2242,2287,2330,2367,2400,2434,2468,2500,2528,2551,2573,2595,2619,2644,2668,2688,
+2700,2701,2689,2671,2655,2652,2670,2713,2777,2848,2906,2934,2926,2895,2864,2851,2861,2880,2893,2895,2893,
+2897,2911,2929,2944,2953,2959,2963,2964,2959,2948,2938,2936,2944,2956,2968,2975,2980,2985,2991,2996,3000,
+3008,3025,3055,3095,3139,3181,3219,3254,3294,3344,3403,3463,3511,3538,3544,3539,3533,3533,3539,3545,3544,
+3534,3515,3487,3451,3410,3370,3338,3319,3314,3319,3329,3336,3337,3332,3324,3320,3322,3329,3332,3328,3316,
+3302,3293,3293,3302,3315,3331,3350,3370,3390,3409,3432,3464,3504,3545,3577,3598,3613,3634,3664,3700,3733,
+3758,3781,3809,3844,3881,3913,3936,3957,3981,4012,4048,4086,4123,4161,4195,4217,4222,4212,4203,4213,4249,
+4301,4345,4361,4348,4324,4313,4324,4347,4359,4345,4311,4276,4257,4255,4259,4257,4246,4232,4220,4206,4189,
+4169,4153,4147,4145,4138,4119,4097,4083,4079,4077,4062,4031,3993,3965,3954,3950,3938,3908,3861,3809,3762,
+3722,3692,3669,3651,3633,3611,3583,3550,3516,3482,3444,3403,3360,3320,3285,3254,3225,3198,3173,3152,3129,
+3099,3062,3022,2988,2965,2949,2935,2918,2897,2876,2856,2837,2821,2809,2802,2799,2796,2791,2781,2767,2750,
+2732,2716,2703,2693,2686,2680,2673,2666,2660,2655,2650,2645,2639,2633,2627,2618,2604,2587,2567,2547,2526,
+2502,2474,2445,2414,2381,2346,2309,2275,2245,2219,2194,2166,2135,2107,2084,2065,2045,2020,1990,1959,1931,
+1907,1885,1866,1852,1846,1847,1848,1843,1830,1810,1790,1772,1753,1730,1699,1664,1628,1595,1565,1535,1502,
+1465,1426,1387,1350,1316,1283,1252,1222,1194,1166,1134,1097,1057,1015,974,936,900,863,825,787,747,
+703,657,613,576,549,529,507,478,437,391,345,303,263,222,177,131,85,39,-9,-58,-106,
+-150,-191,-233,-280,-331,-384,-431,-473,-514,-559,-609,-662,-714,-762,-807,-853,-902,-953,-1003,-1050,-1096,
+-1142,-1190,-1237,-1285,-1331,-1378,-1426,-1472,-1515,-1555,-1595,-1638,-1686,-1738,-1790,-1836,-1877,-1915,-1954,-1995,-2037,
+-2079,-2121,-2164,-2206,-2246,-2283,-2315,-2342,-2368,-2396,-2428,-2462,-2496,-2526,-2553,-2581,-2611,-2645,-2680,-2716,-2750,
+-2783,-2816,-2848,-2877,-2901,-2923,-2946,-2973,-3003,-3033,-3058,-3076,-3091,-3106,-3124,-3144,-3163,-3179,-3193,-3208,-3225,
+-3242,-3257,-3267,-3274,-3282,-3293,-3305,-3314,-3318,-3317,-3315,-3316,-3320,-3325,-3327,-3327,-3324,-3321,-3317,-3314,-3312,
+-3312,-3313,-3312,-3311,-3310,-3310,-3310,-3308,-3302,-3295,-3289,-3285,-3282,-3278,-3271,-3263,-3256,-3250,-3245,-3237,-3228,
+-3219,-3210,-3200,-3188,-3173,-3157,-3143,-3131,-3119,-3105,-3087,-3067,-3046,-3026,-3008,-2995,-2985,-2976,-2962,-2944,-2923,
+-2904,-2888,-2873,-2857,-2839,-2822,-2808,-2796,-2780,-2758,-2730,-2700,-2673,-2651,-2631,-2611,-2589,-2564,-2534,-2498,-2458,
+-2419,-2384,-2355,-2328,-2298,-2265,-2230,-2197,-2166,-2135,-2100,-2063,-2025,-1989,-1957,-1927,-1898,-1869,-1837,-1804,-1771,
+-1739,-1709,-1678,-1647,-1619,-1598,-1585,-1577,-1568,-1552,-1534,-1521,-1516,-1511,-1493,-1455,-1405,-1358,-1320,-1276,-1200,
+-1072,-900,-715,-556,-444,-375,-329,-287,-241,-197,-165,-150,-146,-141,-130,-112,-98,-89,-76,-49,-6,
+28,22,-45,-160,-279,-359,-387,-381,-373,-373,-374,-358,-324,-288,-265,-254,-239,-207,-162,-121,-97,
+-90,-89,-83,-70,-51,-27,2,35,62,76,77,76,83,103,126,144,154,160,169,181,194,
+205,217,233,256,285,314,341,367,395,424,455,484,512,537,559,581,605,633,666,704,740,
+773,799,823,846,871,896,922,951,990,1047,1125,1215,1305,1381,1436,1477,1512,1547,1581,1609,1625,
+1629,1628,1631,1646,1672,1699,1714,1713,1704,1709,1744,1801,1847,1844,1779,1672,1560,1466,1389,1311,1229,
+1164,1152,1211,1328,1464,1582,1661,1705,1720,1712,1685,1645,1609,1591,1594,1614,1645,1685,1738,1804,1873,
+1928,1956,1956,1940,1918,1895,1866,1823,1769,1712,1661,1623,1590,1551,1497,1432,1366,1312,1273,1243,1211,
+1173,1131,1091,1054,1015,966,905,840,782,737,704,677,653,633,618,606,588,560,521,484,462,
+459,470,481,481,464,437,408,384,367,347,319,282,247,236,267,337,423,487,497,448,357,
+258,179,131,112,108,111,114,112,104,87,63,35,10,-7,-17,-24,-31,-40,-51,-59,-61,
+-59,-58,-66,-81,-97,-107,-108,-102,-98,-104,-120,-142,-165,-187,-208,-229,-250,-269,-286,-299,-310,
+-316,-321,-327,-337,-356,-383,-416,-448,-476,-498,-518,-541,-573,-613,-656,-695,-724,-746,-767,-793,-826,
+-863,-896,-923,-944,-961,-980,-999,-1018,-1035,-1050,-1061,-1068,-1071,-1074,-1078,-1084,-1090,-1094,-1092,-1088,-1083,
+-1084,-1091,-1106,-1125,-1142,-1156,-1164,-1168,-1173,-1181,-1192,-1203,-1213,-1220,-1228,-1237,-1248,-1259,-1270,-1277,-1283,
+-1289,-1297,-1306,-1314,-1319,-1321,-1322,-1321,-1321,-1320,-1319,-1319,-1317,-1316,-1314,-1311,-1310,-1311,-1315,-1321,-1324,
+-1326,-1326,-1326,-1326,-1325,-1322,-1316,-1310,-1305,-1303,-1302,-1302,-1304,-1306,-1307,-1303,-1295,-1286,-1280,-1276,-1274,
+-1271,-1265,-1260,-1256,-1253,-1247,-1238,-1227,-1218,-1213,-1210,-1208,-1206,-1203,-1202,-1204,-1208,-1212,-1215,-1218,-1224,
+-1233,-1246,-1259,-1271,-1278,-1281,-1281,-1280,-1280,-1282,-1282,-1281,-1280,-1279,-1278,-1273,-1265,-1253,-1240,-1231,-1224,
+-1218,-1211,-1202,-1193,-1185,-1179,-1174,-1169,-1164,-1158,-1149,-1137,-1126,-1117,-1112,-1107,-1101,-1093,-1084,-1076,-1071,
+-1065,-1057,-1047,-1037,-1030,-1029,-1032,-1035,-1034,-1031,-1025,-1018,-1011,-1006,-1001,-997,-993,-989,-983,-975,-966,
+-955,-944,-934,-922,-909,-895,-882,-871,-861,-853,-845,-836,-826,-816,-805,-794,-785,-779,-775,-772,-768,
+-762,-758,-756,-754,-748,-737,-725,-715,-708,-698,-677,-643,-602,-565,-536,-514,-491,-465,-439,-417,-403,
+-391,-378,-362,-347,-336,-325,-312,-296,-278,-263,-253,-243,-229,-212,-194,-180,-169,-157,-142,-128,-117,
+-111,-106,-98,-86,-71,-59,-50,-40,-28,-15,-4,3,8,16,28,42,55,65,74,84,95,
+110,126,146,169,191,211,228,247,270,298,327,355,382,411,442,475,506,535,564,597,632,
+667,701,734,771,810,847,878,906,937,972,1008,1038,1062,1083,1107,1131,1143,1135,1109,1077,1056,
+1055,1083,1144,1246,1386,1543,1685,1781,1826,1846,1879,1951,2056,2165,2244,2274,2261,2232,2212,2216,2242,
+2277,2313,2350,2392,2432,2453,2435,2371,2275,2170,2070,1976,1877,1776,1685,1622,1586,1560,1525,1474,1424,
+1391,1380,1379,1371,1353,1330,1309,1292,1275,1264,1266,1288,1322,1350,1358,1348,1329,1312,1300,1292,1288,
+1289,1290,1281,1251,1205,1160,1135,1131,1131,1109,1050,960,852,741,634,532,435,346,268,201,148,
+107,77,54,32,8,-15,-35,-51,-67,-87,-109,-130,-145,-161,-182,-210,-240,-265,-282,-297,-317,
+-341,-365,-383,-395,-407,-424,-444,-463,-478,-492,-511,-535,-561,-583,-600,-617,-635,-655,-675,-694,-711,
+-726,-741,-751,-758,-761,-764,-770,-776,-779,-777,-770,-759,-747,-734,-720,-702,-681,-658,-635,-611,-587,
+-561,-536,-514,-497,-481,-464,-443,-418,-390,-361,-332,-303,-278,-259,-243,-224,-198,-163,-125,-88,-54,
+-20,18,61,107,155,204,255,308,361,411,461,512,566,621,671,715,754,790,826,863,901,
+941,983,1025,1065,1101,1137,1175,1218,1261,1299,1333,1366,1406,1453,1501,1544,1582,1618,1657,1697,1735,
+1769,1801,1836,1876,1915,1951,1984,2017,2050,2082,2109,2131,2151,2173,2194,2210,2222,2236,2261,2297,2336,
+2368,2390,2405,2421,2434,2440,2435,2424,2416,2416,2422,2426,2423,2416,2410,2409,2409,2404,2394,2385,2380,
+2382,2385,2384,2375,2363,2353,2350,2352,2351,2341,2321,2300,2286,2282,2283,2282,2276,2266,2258,2250,2238,
+2218,2199,2193,2203,2216,2210,2172,2110,2047,2005,1987,1982,1976,1964,1953,1947,1941,1930,1909,1884,1861,
+1845,1831,1816,1798,1779,1762,1746,1734,1703,1702,1723,1762,1801,1823,1824,1820,1829,1856,1889,1907,1907,
+1901,1905,1923,1947,1964,1972,1977,1988,2004,2023,2040,2059,2082,2111,2141,2171,2200,2234,2274,2317,2357,
+2394,2428,2463,2498,2527,2550,2569,2590,2615,2642,2667,2686,2696,2699,2696,2690,2685,2689,2708,2744,2792,
+2844,2888,2914,2915,2896,2868,2848,2846,2859,2877,2890,2893,2895,2902,2915,2930,2940,2942,2941,2939,2937,
+2936,2935,2937,2944,2955,2967,2977,2985,2990,2996,3003,3011,3022,3037,3060,3088,3120,3153,3187,3222,3260,
+3306,3361,3422,3483,3531,3558,3562,3552,3542,3538,3539,3538,3530,3513,3490,3463,3432,3396,3358,3326,3306,
+3303,3311,3325,3334,3334,3326,3316,3311,3313,3318,3321,3314,3298,3281,3271,3271,3283,3304,3331,3364,3399,
+3433,3463,3492,3524,3561,3599,3630,3652,3668,3691,3725,3765,3804,3834,3858,3885,3916,3947,3972,3988,4005,
+4031,4066,4103,4136,4166,4197,4232,4260,4268,4253,4233,4233,4267,4320,4361,4365,4336,4304,4301,4332,4371,
+4383,4356,4305,4263,4250,4257,4265,4259,4241,4225,4217,4212,4202,4185,4169,4160,4155,4143,4122,4099,4087,
+4090,4096,4088,4061,4027,4003,3996,3998,3991,3963,3914,3854,3798,3752,3719,3695,3678,3662,3641,3614,3582,
+3548,3512,3475,3435,3395,3358,3326,3297,3272,3249,3227,3204,3176,3141,3103,3066,3038,3018,3001,2983,2960,
+2936,2912,2890,2869,2851,2838,2832,2829,2826,2820,2809,2795,2779,2763,2748,2735,2726,2720,2715,2710,2705,
+2701,2696,2690,2682,2673,2664,2654,2644,2632,2617,2600,2581,2561,2539,2514,2487,2458,2425,2389,2351,2315,
+2284,2259,2236,2211,2183,2157,2134,2114,2092,2063,2029,1994,1964,1941,1926,1915,1909,1907,1905,1899,1887,
+1869,1848,1828,1811,1793,1770,1740,1707,1673,1642,1613,1583,1549,1511,1471,1433,1400,1371,1345,1318,1288,
+1256,1223,1189,1153,1113,1071,1029,990,954,918,881,839,795,751,710,676,650,630,608,580,543,
+499,454,412,372,330,284,234,185,139,95,50,5,-39,-82,-124,-169,-217,-267,-317,-363,-405,
+-448,-494,-545,-598,-649,-697,-744,-791,-840,-888,-936,-985,-1034,-1084,-1133,-1182,-1230,-1276,-1321,-1366,-1409,
+-1451,-1492,-1536,-1583,-1633,-1684,-1734,-1779,-1819,-1855,-1892,-1931,-1974,-2018,-2061,-2103,-2145,-2185,-2222,-2254,-2281,
+-2307,-2336,-2371,-2409,-2445,-2475,-2502,-2528,-2558,-2592,-2627,-2661,-2696,-2732,-2767,-2799,-2824,-2844,-2864,-2890,-2923,
+-2961,-2995,-3021,-3039,-3051,-3065,-3082,-3104,-3125,-3144,-3160,-3175,-3190,-3206,-3220,-3230,-3238,-3247,-3258,-3269,-3276,
+-3276,-3272,-3271,-3276,-3286,-3295,-3296,-3291,-3283,-3279,-3279,-3280,-3279,-3276,-3274,-3273,-3275,-3277,-3278,-3276,-3272,
+-3265,-3259,-3254,-3252,-3250,-3248,-3244,-3239,-3234,-3229,-3222,-3214,-3204,-3195,-3186,-3177,-3165,-3152,-3137,-3123,-3111,
+-3099,-3085,-3069,-3050,-3029,-3009,-2991,-2976,-2964,-2953,-2938,-2921,-2902,-2886,-2873,-2861,-2847,-2830,-2813,-2798,-2784,
+-2766,-2743,-2715,-2687,-2663,-2642,-2622,-2599,-2572,-2541,-2508,-2473,-2438,-2404,-2373,-2345,-2318,-2289,-2259,-2230,-2202,
+-2174,-2141,-2103,-2063,-2027,-1996,-1968,-1940,-1910,-1878,-1845,-1812,-1779,-1747,-1716,-1687,-1661,-1637,-1619,-1607,-1600,
+-1592,-1577,-1557,-1540,-1530,-1527,-1518,-1494,-1452,-1403,-1357,-1312,-1254,-1165,-1038,-885,-730,-590,-474,-380,-300,
+-233,-180,-148,-136,-137,-141,-137,-123,-103,-83,-64,-43,-25,-24,-59,-140,-253,-363,-438,-466,-460,
+-447,-440,-436,-422,-397,-368,-342,-321,-295,-259,-218,-184,-165,-157,-154,-148,-136,-120,-97,-66,-33,
+-6,5,7,12,29,56,82,96,97,97,104,120,138,151,161,173,194,223,254,284,311,
+338,364,391,416,441,465,489,512,535,561,594,633,673,710,741,766,792,819,847,874,902,
+939,995,1073,1164,1254,1326,1377,1411,1438,1467,1498,1526,1543,1551,1554,1563,1583,1609,1631,1635,1624,
+1616,1638,1698,1778,1833,1825,1747,1628,1511,1420,1349,1283,1223,1195,1228,1330,1468,1592,1665,1684,1670,
+1645,1620,1593,1563,1536,1526,1540,1573,1619,1672,1728,1786,1838,1874,1889,1884,1867,1848,1828,1803,1766,
+1716,1659,1606,1563,1530,1496,1453,1401,1348,1303,1268,1237,1202,1160,1118,1084,1055,1017,957,878,796,
+730,691,669,652,630,605,583,566,545,512,471,433,413,414,428,438,432,407,372,340,319,
+308,299,280,245,204,177,186,234,304,366,396,391,358,310,254,191,127,74,42,37,48,
+57,53,32,3,-25,-46,-59,-67,-75,-84,-94,-105,-112,-114,-114,-117,-125,-137,-147,-149,-145,
+-142,-146,-160,-182,-206,-231,-255,-277,-296,-313,-327,-339,-350,-359,-366,-370,-377,-392,-416,-448,-482,
+-510,-529,-543,-560,-587,-626,-670,-710,-741,-762,-780,-801,-830,-865,-900,-930,-955,-976,-996,-1016,-1035,
+-1053,-1068,-1080,-1088,-1094,-1096,-1099,-1101,-1104,-1106,-1106,-1104,-1101,-1102,-1107,-1118,-1133,-1149,-1163,-1173,-1182,
+-1191,-1203,-1216,-1228,-1237,-1242,-1246,-1251,-1259,-1269,-1279,-1288,-1296,-1303,-1310,-1317,-1325,-1332,-1337,-1340,-1341,
+-1342,-1343,-1344,-1344,-1342,-1336,-1329,-1323,-1321,-1323,-1329,-1336,-1341,-1345,-1348,-1349,-1349,-1345,-1338,-1329,-1322,
+-1318,-1316,-1314,-1312,-1311,-1311,-1310,-1306,-1298,-1289,-1281,-1276,-1272,-1269,-1266,-1263,-1262,-1260,-1254,-1245,-1233,
+-1223,-1217,-1216,-1216,-1215,-1212,-1209,-1206,-1205,-1204,-1205,-1207,-1213,-1223,-1235,-1248,-1260,-1267,-1271,-1271,-1272,
+-1274,-1276,-1278,-1278,-1275,-1271,-1265,-1258,-1250,-1240,-1231,-1223,-1217,-1209,-1201,-1193,-1185,-1178,-1172,-1166,-1161,
+-1156,-1149,-1141,-1131,-1121,-1113,-1107,-1101,-1094,-1084,-1074,-1067,-1061,-1057,-1049,-1040,-1031,-1027,-1028,-1031,-1031,
+-1028,-1023,-1018,-1015,-1012,-1007,-1000,-992,-985,-980,-976,-970,-960,-948,-937,-927,-918,-908,-898,-886,-875,
+-867,-860,-854,-847,-839,-827,-814,-800,-788,-783,-782,-782,-779,-774,-769,-766,-765,-762,-754,-743,-732,
+-719,-698,-663,-614,-562,-520,-495,-482,-470,-453,-433,-416,-404,-395,-383,-367,-351,-338,-326,-314,-298,
+-282,-269,-259,-248,-234,-218,-203,-194,-187,-177,-163,-147,-135,-128,-124,-117,-106,-94,-82,-72,-60,
+-44,-28,-17,-11,-7,0,12,27,42,57,72,88,104,120,136,155,179,204,227,250,274,
+301,330,358,384,410,440,474,509,541,571,601,636,672,706,738,769,805,842,875,903,930,
+961,997,1031,1056,1072,1089,1114,1139,1152,1140,1112,1084,1076,1092,1131,1194,1290,1421,1571,1706,1796,
+1835,1850,1880,1949,2047,2145,2212,2237,2230,2214,2206,2214,2233,2254,2276,2304,2346,2398,2440,2448,2408,
+2329,2237,2149,2068,1979,1879,1775,1688,1625,1577,1528,1470,1414,1377,1364,1363,1358,1340,1315,1290,1269,
+1252,1242,1246,1269,1304,1335,1350,1346,1328,1306,1283,1262,1247,1241,1243,1238,1218,1181,1141,1114,1098,
+1077,1028,944,835,720,613,516,426,344,271,210,162,123,91,64,41,19,-3,-26,-46,-63,
+-79,-98,-119,-139,-156,-172,-192,-217,-244,-267,-283,-298,-313,-331,-348,-361,-373,-387,-405,-425,-443,
+-457,-471,-490,-515,-541,-563,-582,-599,-617,-639,-663,-686,-708,-728,-744,-755,-762,-766,-771,-778,-784,
+-786,-782,-774,-764,-754,-743,-728,-710,-688,-665,-641,-618,-594,-569,-544,-521,-499,-477,-456,-433,-411,
+-388,-363,-335,-305,-277,-253,-233,-212,-184,-150,-111,-74,-41,-9,26,68,114,163,213,264,315,
+367,417,465,515,566,618,668,714,756,796,834,873,912,952,993,1035,1075,1113,1150,1188,1228,
+1266,1302,1336,1374,1419,1469,1517,1561,1599,1635,1674,1713,1750,1783,1816,1853,1892,1932,1968,2001,2033,
+2066,2097,2123,2143,2162,2182,2201,2217,2230,2246,2272,2308,2347,2381,2406,2424,2439,2450,2454,2450,2441,
+2434,2434,2438,2443,2444,2443,2441,2440,2438,2433,2425,2416,2409,2405,2402,2397,2389,2378,2368,2361,2357,
+2352,2344,2330,2315,2304,2299,2298,2297,2293,2288,2282,2273,2257,2237,2222,2220,2228,2229,2205,2153,2091,
+2043,2021,2019,2020,2012,1998,1985,1977,1968,1950,1924,1896,1873,1854,1831,1803,1775,1750,1732,1715,1703,
+1710,1713,1738,1794,1864,1918,1939,1931,1916,1910,1915,1920,1920,1920,1928,1945,1965,1980,1990,2002,2021,
+2045,2066,2083,2100,2123,2152,2183,2211,2237,2268,2305,2345,2381,2414,2445,2479,2513,2542,2564,2583,2606,
+2634,2661,2681,2688,2686,2682,2684,2694,2712,2737,2770,2808,2845,2874,2892,2897,2893,2882,2870,2863,2862,
+2867,2875,2882,2889,2897,2908,2921,2930,2933,2930,2924,2919,2919,2924,2933,2944,2956,2967,2977,2985,2992,
+3001,3010,3019,3031,3046,3066,3090,3116,3142,3170,3201,3238,3280,3328,3383,3443,3504,3552,3578,3580,3566,
+3549,3537,3529,3521,3506,3487,3466,3446,3422,3391,3356,3323,3301,3294,3299,3307,3313,3313,3311,3311,3315,
+3322,3328,3329,3320,3304,3289,3281,3284,3297,3320,3352,3390,3434,3476,3512,3543,3575,3610,3648,3683,3710,
+3734,3761,3798,3839,3878,3907,3931,3955,3983,4009,4028,4042,4059,4089,4127,4163,4188,4206,4229,4262,4296,
+4310,4297,4271,4263,4290,4339,4376,4373,4336,4301,4303,4342,4386,4397,4362,4305,4263,4254,4266,4273,4261,
+4237,4218,4213,4215,4213,4203,4191,4182,4173,4157,4133,4110,4102,4109,4117,4110,4082,4047,4023,4018,4025,
+4022,3998,3951,3892,3836,3788,3753,3727,3707,3690,3670,3644,3613,3579,3542,3506,3469,3434,3401,3372,3345,
+3322,3301,3279,3254,3223,3187,3151,3120,3096,3074,3051,3025,2997,2972,2948,2925,2902,2882,2867,2860,2859,
+2856,2849,2837,2823,2808,2794,2780,2767,2758,2752,2748,2745,2743,2740,2735,2729,2720,2709,2698,2687,2677,
+2665,2650,2632,2614,2595,2574,2552,2526,2498,2467,2432,2395,2358,2325,2298,2274,2250,2226,2202,2180,2158,
+2132,2101,2067,2034,2007,1989,1979,1975,1973,1970,1962,1949,1930,1909,1888,1869,1851,1830,1805,1777,1747,
+1717,1688,1659,1627,1593,1555,1518,1483,1454,1429,1406,1380,1349,1314,1278,1242,1206,1167,1126,1084,1044,
+1008,972,932,888,842,800,767,743,725,706,679,642,598,553,511,472,434,392,343,292,242,
+195,152,110,66,22,-21,-66,-112,-160,-209,-256,-301,-345,-389,-436,-485,-534,-583,-632,-681,-729,
+-778,-825,-874,-923,-974,-1023,-1072,-1119,-1168,-1216,-1263,-1307,-1348,-1389,-1433,-1479,-1528,-1577,-1625,-1672,-1716,
+-1755,-1792,-1828,-1868,-1912,-1960,-2006,-2049,-2088,-2124,-2158,-2188,-2215,-2243,-2275,-2313,-2353,-2390,-2420,-2446,-2472,
+-2503,-2538,-2575,-2612,-2650,-2688,-2723,-2752,-2773,-2790,-2809,-2837,-2875,-2915,-2951,-2978,-2995,-3007,-3020,-3037,-3059,
+-3082,-3103,-3121,-3136,-3152,-3167,-3182,-3194,-3203,-3212,-3223,-3234,-3240,-3239,-3234,-3233,-3240,-3254,-3264,-3265,-3258,
+-3249,-3245,-3247,-3249,-3247,-3240,-3234,-3234,-3239,-3244,-3245,-3240,-3231,-3223,-3217,-3215,-3214,-3215,-3215,-3214,-3211,
+-3206,-3201,-3195,-3189,-3181,-3171,-3160,-3148,-3136,-3123,-3110,-3097,-3085,-3073,-3060,-3046,-3030,-3012,-2992,-2974,-2958,
+-2945,-2931,-2916,-2899,-2883,-2870,-2861,-2852,-2840,-2823,-2805,-2787,-2769,-2748,-2724,-2697,-2673,-2651,-2631,-2609,-2581,
+-2550,-2517,-2484,-2452,-2421,-2392,-2364,-2338,-2310,-2281,-2253,-2227,-2203,-2176,-2143,-2105,-2067,-2033,-2006,-1979,-1949,
+-1915,-1879,-1846,-1814,-1783,-1753,-1726,-1701,-1680,-1659,-1641,-1626,-1617,-1608,-1594,-1573,-1548,-1532,-1528,-1529,-1522,
+-1495,-1449,-1395,-1345,-1299,-1243,-1163,-1049,-907,-751,-596,-457,-341,-250,-184,-141,-120,-117,-124,-131,-128,
+-110,-82,-54,-33,-32,-57,-117,-211,-322,-427,-499,-530,-529,-516,-504,-497,-488,-471,-446,-416,-383,
+-347,-310,-276,-251,-234,-224,-216,-206,-196,-182,-161,-132,-101,-77,-64,-57,-44,-20,9,31,39,
+37,37,48,68,88,100,107,118,137,165,195,222,247,271,295,320,346,371,398,424,448,
+470,494,524,563,605,645,679,709,739,771,802,830,857,890,941,1012,1097,1182,1252,1302,1335,
+1361,1387,1415,1441,1461,1474,1484,1499,1523,1551,1569,1568,1554,1548,1576,1644,1729,1784,1776,1699,1584,
+1471,1379,1307,1245,1198,1191,1247,1357,1483,1576,1609,1589,1548,1512,1491,1477,1463,1453,1457,1484,1533,
+1597,1662,1720,1766,1797,1813,1816,1810,1797,1781,1762,1736,1701,1654,1600,1547,1503,1471,1445,1417,1381,
+1342,1304,1271,1236,1195,1149,1106,1075,1048,1009,944,857,768,702,668,652,636,609,575,545,522,
+499,468,431,396,377,376,382,384,370,343,309,279,259,249,244,232,208,175,144,127,128,
+144,166,194,233,280,315,313,259,164,62,-8,-31,-20,-2,1,-11,-33,-55,-72,-87,-101,
+-115,-126,-136,-145,-155,-162,-166,-170,-178,-189,-199,-203,-201,-198,-201,-213,-232,-255,-278,-301,-322,
+-342,-358,-371,-383,-395,-407,-416,-422,-427,-437,-456,-485,-515,-541,-559,-572,-587,-611,-645,-686,-725,
+-755,-776,-794,-813,-839,-871,-903,-934,-961,-985,-1008,-1031,-1052,-1070,-1085,-1096,-1106,-1113,-1117,-1118,-1117,
+-1114,-1113,-1114,-1117,-1119,-1122,-1126,-1132,-1142,-1155,-1170,-1185,-1198,-1213,-1228,-1244,-1257,-1265,-1267,-1267,-1267,
+-1271,-1279,-1289,-1300,-1309,-1315,-1319,-1323,-1328,-1334,-1342,-1349,-1355,-1359,-1362,-1364,-1364,-1360,-1353,-1343,-1335,
+-1331,-1332,-1336,-1342,-1348,-1355,-1362,-1366,-1365,-1359,-1348,-1338,-1332,-1330,-1331,-1330,-1326,-1322,-1318,-1315,-1311,
+-1305,-1297,-1288,-1280,-1273,-1266,-1262,-1259,-1259,-1259,-1255,-1248,-1238,-1229,-1224,-1221,-1219,-1217,-1214,-1210,-1206,
+-1203,-1201,-1202,-1207,-1214,-1224,-1235,-1245,-1253,-1259,-1262,-1263,-1263,-1266,-1269,-1273,-1273,-1270,-1262,-1252,-1242,
+-1233,-1226,-1220,-1215,-1209,-1202,-1194,-1187,-1180,-1173,-1165,-1158,-1151,-1145,-1140,-1134,-1125,-1117,-1109,-1102,-1095,
+-1087,-1077,-1069,-1062,-1057,-1051,-1042,-1033,-1027,-1025,-1026,-1028,-1026,-1020,-1015,-1013,-1014,-1013,-1009,-1000,-989,
+-981,-975,-971,-965,-955,-943,-931,-921,-914,-906,-899,-892,-885,-878,-872,-865,-857,-848,-837,-822,-806,
+-794,-788,-788,-789,-786,-778,-770,-765,-765,-765,-763,-757,-749,-736,-712,-674,-623,-571,-531,-507,-496,
+-486,-470,-451,-435,-424,-416,-405,-391,-374,-360,-347,-332,-316,-300,-288,-277,-266,-249,-231,-216,-207,
+-203,-196,-184,-169,-157,-150,-145,-138,-129,-118,-108,-97,-82,-65,-48,-36,-28,-22,-13,0,15,
+32,50,71,92,112,129,146,166,192,221,249,276,303,333,362,390,415,441,471,505,539,
+568,595,626,662,700,734,762,788,818,851,881,908,933,965,1001,1033,1056,1071,1089,1117,1145,
+1156,1140,1108,1083,1084,1111,1157,1220,1307,1426,1564,1688,1769,1806,1824,1859,1929,2023,2110,2168,2193,
+2197,2197,2203,2216,2231,2244,2256,2277,2318,2378,2437,2467,2448,2385,2302,2222,2150,2072,1975,1862,1751,
+1660,1588,1527,1466,1409,1369,1350,1345,1338,1321,1296,1270,1248,1232,1224,1231,1254,1288,1318,1331,1325,
+1305,1278,1250,1224,1206,1199,1201,1203,1195,1175,1149,1122,1091,1041,960,848,723,603,500,411,332,
+263,206,163,132,107,81,55,31,7,-14,-36,-56,-74,-90,-108,-129,-149,-167,-183,-200,-222,
+-247,-270,-288,-301,-313,-324,-335,-345,-357,-371,-388,-405,-421,-435,-450,-470,-494,-519,-542,-562,-581,
+-602,-625,-649,-674,-699,-722,-741,-755,-763,-768,-772,-777,-781,-781,-778,-772,-764,-755,-745,-732,-715,
+-695,-672,-648,-622,-596,-570,-545,-520,-495,-471,-447,-425,-403,-382,-358,-330,-301,-271,-242,-215,-187,
+-155,-120,-84,-52,-23,4,36,77,124,174,224,273,321,370,418,466,514,564,616,666,714,
+758,798,837,878,920,963,1007,1050,1091,1131,1169,1208,1245,1282,1317,1353,1393,1436,1481,1526,1567,
+1607,1646,1687,1726,1764,1799,1835,1873,1910,1945,1977,2006,2036,2069,2100,2128,2151,2172,2192,2212,2230,
+2248,2268,2293,2325,2360,2393,2421,2443,2459,2469,2473,2470,2464,2457,2454,2455,2458,2464,2468,2470,2468,
+2464,2458,2451,2445,2437,2427,2418,2409,2401,2392,2382,2374,2368,2365,2362,2354,2344,2335,2330,2328,2328,
+2326,2321,2312,2297,2274,2247,2226,2213,2206,2191,2159,2116,2079,2060,2060,2065,2060,2044,2028,2020,2017,
+2007,1980,1944,1909,1879,1845,1802,1753,1716,1702,1705,1711,1710,1838,1839,1850,1897,1978,2056,2096,2087,
+2044,1994,1956,1933,1924,1928,1944,1966,1986,1998,2009,2025,2050,2078,2100,2115,2131,2154,2185,2218,2247,
+2273,2303,2339,2375,2407,2433,2458,2487,2521,2552,2576,2595,2616,2640,2661,2673,2673,2668,2670,2686,2713,
+2747,2782,2813,2839,2857,2866,2870,2871,2874,2880,2886,2887,2883,2876,2872,2875,2885,2901,2917,2930,2936,
+2935,2930,2925,2922,2925,2933,2945,2958,2969,2978,2985,2994,3004,3017,3030,3042,3055,3072,3094,3118,3143,
+3170,3200,3235,3275,3317,3360,3408,3463,3520,3568,3593,3592,3573,3550,3532,3520,3508,3492,3475,3460,3447,
+3429,3402,3367,3333,3308,3296,3291,3289,3287,3288,3295,3309,3326,3340,3345,3342,3331,3319,3311,3312,3324,
+3344,3370,3402,3439,3482,3526,3565,3599,3630,3663,3701,3740,3775,3808,3842,3879,3918,3952,3978,3999,4021,
+4044,4065,4080,4093,4113,4147,4189,4225,4246,4256,4271,4299,4332,4347,4333,4303,4287,4306,4350,4386,4386,
+4354,4321,4320,4353,4388,4392,4356,4304,4269,4265,4277,4282,4267,4241,4222,4220,4226,4229,4225,4219,4212,
+4203,4186,4160,4138,4130,4135,4138,4123,4087,4046,4020,4015,4023,4024,4007,3969,3922,3875,3834,3798,3767,
+3740,3716,3694,3670,3642,3610,3575,3541,3508,3477,3448,3422,3398,3377,3358,3336,3309,3276,3240,3206,3176,
+3149,3122,3092,3060,3031,3007,2986,2963,2938,2915,2899,2892,2890,2887,2880,2869,2856,2843,2830,2815,2802,
+2791,2784,2781,2778,2775,2772,2768,2761,2752,2742,2732,2724,2714,2701,2684,2665,2647,2630,2612,2590,2564,
+2534,2504,2472,2439,2405,2373,2342,2316,2291,2268,2245,2221,2195,2167,2137,2107,2082,2062,2049,2042,2037,
+2032,2025,2012,1993,1971,1948,1929,1910,1889,1865,1837,1810,1783,1757,1730,1699,1666,1633,1601,1570,1540,
+1513,1488,1463,1435,1404,1368,1331,1293,1257,1220,1181,1142,1103,1066,1026,982,935,890,852,825,808,
+791,769,736,695,650,607,566,527,487,444,397,348,301,257,215,172,128,82,36,-10,-58,
+-105,-152,-198,-244,-289,-335,-381,-427,-473,-521,-571,-620,-669,-716,-763,-813,-863,-913,-960,-1004,-1049,
+-1098,-1149,-1200,-1247,-1290,-1331,-1376,-1423,-1471,-1517,-1562,-1605,-1648,-1688,-1726,-1763,-1805,-1853,-1905,-1954,-1997,
+-2033,-2065,-2096,-2127,-2156,-2186,-2219,-2257,-2296,-2331,-2361,-2387,-2414,-2447,-2485,-2524,-2564,-2604,-2643,-2678,-2705,
+-2723,-2738,-2759,-2789,-2827,-2867,-2901,-2926,-2944,-2959,-2974,-2991,-3012,-3035,-3057,-3077,-3093,-3108,-3124,-3140,-3152,
+-3162,-3172,-3183,-3194,-3203,-3204,-3201,-3200,-3206,-3217,-3228,-3231,-3227,-3222,-3220,-3222,-3221,-3215,-3204,-3198,-3198,
+-3205,-3210,-3210,-3203,-3193,-3184,-3179,-3178,-3179,-3180,-3181,-3178,-3173,-3167,-3163,-3160,-3159,-3154,-3145,-3131,-3117,
+-3104,-3092,-3081,-3069,-3056,-3044,-3032,-3020,-3005,-2989,-2972,-2955,-2941,-2928,-2915,-2899,-2882,-2868,-2857,-2848,-2839,
+-2826,-2809,-2789,-2769,-2749,-2727,-2703,-2679,-2657,-2637,-2616,-2590,-2560,-2527,-2494,-2463,-2433,-2405,-2379,-2355,-2332,
+-2308,-2282,-2254,-2227,-2200,-2172,-2139,-2103,-2067,-2037,-2010,-1981,-1948,-1911,-1876,-1845,-1818,-1791,-1764,-1739,-1719,
+-1701,-1682,-1660,-1639,-1624,-1615,-1603,-1583,-1557,-1535,-1527,-1532,-1538,-1527,-1493,-1444,-1393,-1352,-1314,-1265,-1185,
+-1064,-909,-737,-573,-432,-323,-240,-178,-132,-105,-98,-107,-118,-118,-99,-71,-50,-53,-91,-164,-263,
+-373,-472,-543,-579,-586,-578,-568,-563,-558,-546,-522,-488,-448,-408,-374,-347,-326,-309,-292,-277,-265,
+-254,-242,-223,-198,-170,-147,-132,-120,-103,-80,-55,-38,-32,-29,-21,-2,20,38,48,55,65,
+84,109,133,154,174,196,221,248,275,303,334,364,393,417,441,468,500,535,569,601,634,
+670,709,748,782,810,839,879,935,1004,1077,1144,1199,1241,1276,1306,1334,1358,1376,1390,1403,1421,
+1448,1478,1501,1510,1506,1507,1532,1586,1652,1695,1689,1630,1537,1438,1347,1265,1193,1141,1130,1171,1252,
+1338,1393,1402,1377,1346,1328,1327,1335,1346,1361,1389,1437,1504,1580,1650,1703,1733,1743,1741,1736,1730,
+1721,1706,1682,1652,1616,1576,1530,1484,1445,1418,1400,1383,1357,1323,1285,1249,1213,1172,1127,1083,1047,
+1016,976,914,835,757,700,668,649,624,587,545,511,489,470,444,410,376,352,339,330,316,
+294,265,236,213,197,190,186,180,167,146,119,89,59,28,8,17,69,157,247,290,260,
+166,55,-27,-61,-61,-54,-59,-73,-87,-96,-102,-115,-135,-155,-168,-175,-179,-186,-195,-204,-215,
+-229,-245,-259,-265,-263,-258,-259,-269,-287,-308,-328,-347,-366,-385,-402,-415,-426,-438,-451,-463,-472,
+-479,-489,-505,-527,-551,-572,-588,-602,-618,-642,-673,-707,-740,-766,-787,-805,-826,-851,-881,-912,-941,
+-967,-991,-1015,-1039,-1062,-1082,-1097,-1110,-1121,-1130,-1136,-1137,-1132,-1126,-1122,-1123,-1129,-1135,-1140,-1143,-1147,
+-1154,-1166,-1181,-1198,-1214,-1231,-1249,-1267,-1282,-1291,-1292,-1289,-1286,-1286,-1292,-1302,-1314,-1323,-1329,-1330,-1330,
+-1331,-1336,-1344,-1353,-1361,-1367,-1371,-1372,-1372,-1368,-1361,-1352,-1345,-1341,-1340,-1341,-1344,-1350,-1357,-1366,-1372,
+-1372,-1366,-1355,-1346,-1341,-1342,-1344,-1343,-1339,-1332,-1325,-1320,-1316,-1311,-1305,-1298,-1288,-1278,-1269,-1262,-1259,
+-1257,-1256,-1252,-1246,-1239,-1233,-1228,-1223,-1218,-1213,-1208,-1205,-1202,-1200,-1199,-1202,-1209,-1218,-1228,-1237,-1244,
+-1250,-1254,-1256,-1256,-1256,-1256,-1259,-1263,-1264,-1260,-1251,-1239,-1228,-1220,-1214,-1210,-1207,-1202,-1197,-1191,-1185,
+-1178,-1170,-1160,-1150,-1142,-1136,-1131,-1125,-1118,-1110,-1103,-1096,-1088,-1080,-1072,-1065,-1060,-1054,-1047,-1037,-1027,
+-1022,-1021,-1023,-1023,-1019,-1015,-1011,-1010,-1011,-1010,-1005,-996,-987,-980,-975,-969,-961,-951,-941,-931,-922,
+-914,-907,-902,-898,-895,-890,-883,-873,-863,-854,-844,-832,-818,-806,-799,-797,-795,-789,-777,-764,-755,
+-752,-754,-756,-756,-756,-753,-743,-719,-683,-640,-603,-574,-551,-530,-506,-484,-468,-458,-450,-439,-424,
+-408,-393,-378,-363,-345,-328,-315,-303,-289,-270,-248,-229,-215,-206,-199,-188,-176,-165,-157,-150,-141,
+-131,-121,-111,-100,-86,-69,-53,-40,-29,-16,-1,15,33,51,71,94,118,139,155,173,196,
+225,255,283,308,333,361,390,418,443,469,500,533,562,586,610,640,678,718,751,775,797,
+823,853,883,908,932,961,995,1027,1050,1069,1093,1124,1151,1156,1133,1097,1074,1081,1116,1167,1230,
+1313,1423,1548,1657,1727,1758,1779,1821,1896,1987,2066,2119,2148,2164,2178,2194,2211,2227,2239,2253,2275,
+2315,2374,2436,2473,2463,2406,2322,2238,2164,2090,1997,1883,1765,1663,1585,1523,1467,1413,1370,1344,1331,
+1320,1304,1282,1261,1243,1230,1223,1227,1244,1270,1292,1301,1292,1271,1246,1223,1204,1189,1181,1180,1181,
+1178,1167,1148,1119,1072,997,891,762,630,511,412,331,262,204,160,131,111,92,69,42,17,
+-4,-25,-46,-66,-85,-102,-119,-137,-157,-175,-192,-210,-229,-252,-274,-292,-303,-311,-319,-328,-338,
+-349,-360,-371,-383,-396,-411,-428,-448,-469,-492,-514,-538,-563,-588,-613,-637,-661,-685,-709,-729,-745,
+-755,-763,-768,-773,-776,-776,-774,-769,-761,-752,-740,-728,-715,-700,-680,-655,-627,-599,-571,-543,-517,
+-491,-466,-444,-423,-401,-377,-351,-324,-295,-266,-235,-202,-166,-130,-94,-61,-33,-7,19,52,93,
+141,192,241,288,334,380,427,474,521,569,618,667,713,755,794,833,876,922,970,1017,1061,
+1102,1142,1181,1219,1256,1293,1330,1369,1410,1450,1489,1527,1567,1608,1651,1693,1733,1772,1810,1847,1884,
+1918,1948,1976,2003,2034,2068,2102,2134,2161,2184,2205,2226,2248,2271,2293,2317,2342,2370,2400,2429,2454,
+2472,2483,2488,2489,2486,2480,2472,2466,2465,2471,2479,2484,2483,2476,2470,2466,2462,2455,2443,2431,2421,
+2414,2406,2396,2386,2379,2378,2378,2376,2369,2362,2358,2357,2356,2353,2345,2335,2320,2299,2271,2241,2213,
+2188,2163,2137,2115,2106,2110,2119,2116,2097,2075,2063,2064,2063,2043,2001,1950,1907,1873,1831,1774,1714,
+1684,1703,1758,1812,1838,2097,2085,2052,2049,2095,2161,2204,2196,2141,2067,1999,1952,1929,1930,1951,1979,
+2002,2016,2025,2039,2062,2089,2112,2130,2148,2176,2211,2247,2277,2303,2331,2365,2400,2428,2449,2469,2495,
+2527,2558,2582,2597,2611,2625,2639,2649,2654,2661,2678,2708,2746,2782,2810,2828,2840,2845,2846,2845,2847,
+2855,2869,2883,2889,2885,2875,2869,2873,2887,2907,2925,2937,2942,2941,2938,2936,2937,2942,2952,2963,2974,
+2984,2991,2998,3008,3022,3038,3054,3069,3085,3104,3125,3149,3175,3207,3245,3287,3329,3365,3397,3432,3476,
+3525,3567,3587,3582,3561,3538,3521,3509,3497,3483,3470,3461,3453,3439,3414,3381,3349,3325,3310,3297,3283,
+3270,3269,3283,3310,3337,3354,3356,3346,3333,3325,3329,3346,3375,3408,3441,3472,3506,3544,3586,3629,3667,
+3699,3728,3760,3798,3838,3879,3920,3959,3994,4023,4045,4064,4083,4101,4117,4128,4140,4162,4199,4244,4282,
+4305,4314,4325,4346,4371,4381,4364,4331,4309,4316,4350,4382,4388,4368,4343,4339,4357,4375,4369,4336,4295,
+4271,4271,4284,4287,4274,4254,4241,4241,4248,4252,4251,4249,4246,4238,4221,4196,4174,4165,4165,4159,4135,
+4094,4050,4021,4015,4021,4025,4013,3988,3955,3920,3884,3847,3809,3772,3740,3713,3689,3665,3637,3607,3577,
+3547,3519,3494,3471,3450,3433,3415,3393,3365,3331,3294,3259,3227,3196,3164,3132,3100,3073,3050,3028,3002,
+2976,2953,2938,2931,2928,2923,2915,2905,2895,2883,2869,2853,2835,2822,2813,2809,2806,2803,2800,2795,2788,
+2780,2772,2764,2756,2746,2732,2715,2697,2680,2666,2650,2628,2600,2568,2536,2507,2480,2452,2423,2393,2365,
+2340,2315,2290,2262,2232,2202,2175,2153,2137,2125,2115,2105,2095,2084,2070,2053,2032,2009,1988,1969,1951,
+1929,1903,1874,1848,1823,1799,1770,1737,1704,1673,1648,1625,1600,1573,1545,1516,1486,1455,1420,1382,1345,
+1309,1274,1240,1205,1167,1126,1080,1030,981,940,908,886,867,845,816,781,742,702,662,622,580,
+536,491,446,403,361,320,278,235,190,143,95,47,0,-47,-93,-138,-185,-232,-278,-323,-368,
+-413,-462,-512,-561,-608,-653,-698,-748,-800,-851,-898,-941,-984,-1033,-1086,-1139,-1188,-1233,-1277,-1323,-1370,
+-1417,-1461,-1503,-1545,-1586,-1627,-1666,-1705,-1749,-1800,-1853,-1903,-1943,-1975,-2005,-2037,-2070,-2103,-2135,-2167,-2202,
+-2239,-2273,-2304,-2333,-2364,-2399,-2438,-2477,-2517,-2555,-2593,-2624,-2648,-2666,-2683,-2709,-2743,-2783,-2820,-2850,-2873,
+-2892,-2909,-2927,-2946,-2967,-2990,-3012,-3032,-3049,-3065,-3080,-3095,-3107,-3116,-3124,-3135,-3147,-3159,-3164,-3164,-3162,
+-3165,-3174,-3184,-3191,-3194,-3194,-3195,-3196,-3192,-3183,-3173,-3167,-3168,-3172,-3175,-3172,-3165,-3158,-3152,-3149,-3148,
+-3147,-3147,-3146,-3142,-3135,-3128,-3124,-3125,-3127,-3125,-3116,-3103,-3088,-3076,-3067,-3056,-3044,-3030,-3016,-3004,-2991,
+-2977,-2961,-2946,-2932,-2921,-2910,-2897,-2881,-2865,-2851,-2840,-2830,-2818,-2803,-2786,-2767,-2748,-2729,-2708,-2685,-2663,
+-2642,-2621,-2598,-2570,-2538,-2506,-2476,-2448,-2420,-2392,-2368,-2348,-2331,-2313,-2290,-2262,-2231,-2198,-2165,-2132,-2098,
+-2066,-2037,-2009,-1978,-1943,-1908,-1877,-1852,-1829,-1805,-1778,-1753,-1732,-1714,-1694,-1670,-1645,-1627,-1618,-1611,-1597,
+-1573,-1548,-1531,-1530,-1537,-1538,-1522,-1490,-1451,-1416,-1385,-1348,-1287,-1189,-1050,-883,-712,-561,-441,-346,-265,
+-189,-126,-89,-84,-102,-122,-127,-114,-99,-105,-148,-226,-327,-432,-524,-589,-626,-638,-636,-631,-627,
+-624,-614,-592,-560,-522,-486,-456,-430,-407,-384,-361,-342,-327,-316,-304,-286,-263,-238,-215,-198,-183,
+-167,-150,-133,-121,-111,-99,-81,-57,-35,-18,-8,1,15,32,50,65,79,97,121,150,179,
+208,237,270,305,340,371,397,421,445,470,496,523,555,593,638,684,725,758,787,819,859,
+909,965,1024,1081,1133,1178,1215,1244,1265,1280,1292,1306,1326,1354,1389,1425,1452,1469,1482,1503,1536,
+1575,1603,1603,1570,1508,1426,1332,1232,1136,1062,1026,1032,1066,1105,1129,1135,1132,1134,1148,1172,1203,
+1240,1286,1344,1413,1489,1564,1625,1662,1673,1665,1649,1637,1631,1622,1604,1576,1543,1511,1481,1448,1414,
+1383,1360,1346,1330,1304,1266,1224,1186,1154,1121,1082,1039,997,958,917,868,810,755,712,680,650,
+610,561,516,484,467,451,426,389,351,318,294,272,247,217,186,160,140,127,121,119,117,
+109,97,81,60,31,-7,-46,-63,-37,32,115,169,164,108,35,-19,-43,-54,-72,-102,-134,
+-152,-154,-152,-160,-178,-198,-210,-212,-210,-211,-219,-231,-249,-271,-295,-315,-324,-321,-312,-310,-318,
+-336,-355,-373,-389,-406,-423,-440,-454,-465,-477,-491,-504,-517,-527,-539,-554,-573,-591,-607,-620,-634,
+-652,-676,-704,-732,-758,-780,-799,-818,-840,-866,-895,-926,-955,-979,-1000,-1020,-1041,-1063,-1084,-1103,-1119,
+-1133,-1145,-1153,-1155,-1151,-1144,-1138,-1138,-1143,-1150,-1156,-1160,-1165,-1173,-1185,-1199,-1213,-1227,-1243,-1261,-1281,
+-1299,-1311,-1314,-1311,-1307,-1305,-1308,-1316,-1326,-1336,-1342,-1343,-1342,-1342,-1344,-1349,-1356,-1364,-1370,-1374,-1375,
+-1375,-1372,-1367,-1363,-1359,-1357,-1356,-1355,-1356,-1359,-1364,-1370,-1374,-1374,-1369,-1361,-1354,-1351,-1351,-1352,-1352,
+-1349,-1343,-1335,-1328,-1321,-1315,-1309,-1303,-1294,-1285,-1276,-1269,-1264,-1260,-1256,-1250,-1244,-1238,-1234,-1230,-1224,
+-1217,-1209,-1203,-1201,-1199,-1198,-1197,-1199,-1204,-1212,-1222,-1230,-1236,-1241,-1244,-1247,-1248,-1247,-1246,-1247,-1249,
+-1249,-1245,-1238,-1228,-1219,-1212,-1208,-1205,-1201,-1197,-1192,-1188,-1184,-1177,-1167,-1157,-1147,-1139,-1133,-1127,-1120,
+-1112,-1103,-1096,-1089,-1081,-1073,-1066,-1060,-1055,-1049,-1041,-1031,-1022,-1017,-1016,-1017,-1016,-1014,-1011,-1009,-1008,
+-1006,-1002,-996,-990,-985,-981,-976,-967,-957,-947,-939,-933,-926,-917,-909,-903,-901,-899,-895,-886,-875,
+-864,-857,-852,-845,-835,-825,-816,-811,-805,-795,-780,-764,-751,-744,-742,-743,-746,-751,-758,-762,-755,
+-735,-704,-667,-629,-592,-558,-529,-507,-495,-488,-482,-471,-454,-436,-420,-406,-390,-372,-354,-338,-325,
+-309,-289,-265,-242,-223,-208,-195,-183,-171,-161,-152,-142,-129,-117,-105,-95,-83,-70,-55,-40,-25,
+-7,13,36,58,77,95,116,140,163,182,198,216,241,271,300,323,343,364,390,418,445,
+469,493,522,552,579,601,624,654,693,732,763,785,805,832,864,894,917,937,962,994,1027,
+1054,1077,1103,1133,1155,1152,1123,1084,1063,1074,1115,1173,1242,1330,1439,1554,1647,1698,1718,1737,1784,
+1863,1952,2028,2077,2108,2132,2153,2171,2186,2200,2218,2240,2269,2307,2355,2403,2432,2420,2363,2276,2186,
+2106,2028,1938,1832,1722,1629,1561,1511,1465,1417,1375,1345,1328,1316,1301,1283,1265,1253,1244,1237,1233,
+1237,1249,1262,1268,1263,1248,1232,1219,1209,1199,1189,1179,1170,1158,1140,1112,1069,1004,914,800,673,
+548,439,349,275,215,167,133,110,93,73,49,24,2,-16,-34,-54,-75,-95,-112,-127,-143,
+-161,-180,-199,-217,-237,-257,-276,-290,-298,-304,-311,-320,-331,-340,-346,-350,-356,-368,-386,-406,-426,
+-445,-463,-485,-511,-540,-569,-596,-620,-644,-667,-690,-710,-727,-741,-753,-763,-770,-775,-778,-777,-772,
+-762,-749,-735,-724,-714,-703,-687,-663,-635,-606,-577,-548,-520,-492,-468,-447,-427,-404,-377,-349,-320,
+-293,-264,-232,-195,-157,-119,-85,-56,-28,-1,28,64,107,156,206,257,305,353,401,449,495,
+538,582,626,672,715,755,792,831,875,923,973,1019,1062,1103,1143,1182,1219,1254,1290,1329,1371,
+1413,1451,1488,1524,1564,1608,1652,1694,1734,1772,1811,1848,1883,1914,1943,1971,2001,2035,2070,2106,2140,
+2171,2197,2219,2240,2263,2287,2312,2333,2353,2374,2400,2429,2456,2477,2489,2496,2501,2504,2500,2489,2475,
+2468,2471,2481,2487,2485,2479,2473,2471,2468,2461,2450,2438,2432,2428,2422,2410,2396,2386,2383,2383,2382,
+2377,2373,2371,2370,2366,2357,2345,2337,2330,2320,2300,2272,2240,2211,2187,2170,2161,2162,2169,2170,2156,
+2131,2110,2103,2104,2090,2047,1982,1925,1896,1888,1871,1828,1779,1768,1827,1939,2047,2097,2357,2318,2229,
+2155,2135,2160,2189,2189,2152,2093,2032,1982,1951,1943,1959,1989,2018,2035,2042,2050,2067,2091,2116,2139,
+2163,2194,2230,2265,2292,2313,2336,2366,2400,2429,2451,2470,2492,2519,2545,2564,2576,2585,2598,2615,2634,
+2653,2676,2705,2740,2775,2801,2816,2823,2829,2833,2836,2834,2832,2835,2845,2858,2869,2873,2872,2873,2880,
+2894,2911,2925,2934,2937,2938,2939,2941,2946,2954,2965,2978,2990,3001,3009,3017,3028,3042,3059,3076,3096,
+3117,3139,3162,3186,3214,3249,3293,3341,3383,3412,3431,3448,3474,3506,3534,3547,3542,3526,3510,3499,3491,
+3480,3467,3456,3451,3447,3436,3413,3385,3360,3343,3329,3310,3286,3265,3260,3278,3311,3342,3359,3357,3343,
+3330,3328,3345,3379,3426,3475,3515,3546,3573,3606,3650,3699,3744,3776,3799,3821,3852,3894,3943,3990,4031,
+4063,4089,4109,4128,4145,4161,4173,4183,4195,4217,4253,4295,4331,4353,4361,4368,4381,4397,4403,4390,4361,
+4335,4328,4341,4359,4365,4357,4345,4343,4350,4353,4340,4312,4285,4274,4280,4290,4292,4284,4273,4268,4272,
+4277,4280,4278,4277,4275,4267,4250,4227,4208,4198,4194,4185,4160,4121,4081,4055,4047,4049,4050,4041,4022,
+3997,3968,3933,3893,3849,3806,3767,3736,3711,3687,3663,3638,3611,3585,3559,3536,3516,3499,3484,3467,3445,
+3416,3381,3344,3308,3274,3242,3211,3180,3151,3125,3100,3072,3043,3015,2994,2982,2975,2969,2961,2950,2941,
+2932,2922,2906,2886,2864,2847,2837,2832,2831,2829,2826,2822,2815,2807,2798,2789,2780,2770,2756,2740,2723,
+2709,2696,2681,2659,2630,2597,2567,2540,2516,2493,2469,2443,2416,2390,2363,2335,2304,2273,2245,2222,2206,
+2196,2189,2179,2165,2149,2131,2112,2092,2070,2048,2028,2011,1992,1971,1945,1918,1892,1868,1842,1813,1779,
+1746,1719,1698,1680,1658,1630,1598,1565,1534,1503,1470,1434,1398,1365,1334,1303,1269,1228,1180,1125,1072,
+1026,991,967,947,924,893,856,818,782,748,713,673,628,582,538,497,457,417,376,334,290,
+245,199,151,104,56,11,-33,-78,-125,-172,-218,-263,-308,-354,-403,-453,-502,-547,-588,-632,-680,
+-734,-788,-838,-883,-929,-977,-1030,-1082,-1131,-1176,-1222,-1270,-1318,-1365,-1408,-1449,-1489,-1530,-1570,-1610,-1652,
+-1700,-1753,-1805,-1851,-1886,-1914,-1942,-1975,-2010,-2046,-2078,-2110,-2144,-2179,-2215,-2250,-2283,-2318,-2355,-2393,-2431,
+-2467,-2502,-2535,-2564,-2586,-2605,-2627,-2658,-2698,-2740,-2776,-2804,-2824,-2842,-2860,-2880,-2900,-2922,-2944,-2967,-2989,
+-3007,-3023,-3038,-3052,-3064,-3073,-3080,-3089,-3101,-3113,-3121,-3123,-3123,-3124,-3131,-3141,-3151,-3159,-3164,-3166,-3165,
+-3159,-3150,-3143,-3140,-3141,-3141,-3138,-3131,-3125,-3122,-3121,-3121,-3119,-3117,-3116,-3115,-3112,-3105,-3099,-3096,-3097,
+-3099,-3096,-3087,-3074,-3062,-3053,-3045,-3034,-3019,-3003,-2988,-2976,-2964,-2950,-2933,-2916,-2903,-2894,-2885,-2873,-2858,
+-2842,-2829,-2819,-2809,-2797,-2781,-2764,-2748,-2731,-2713,-2692,-2670,-2648,-2627,-2605,-2579,-2550,-2519,-2490,-2464,-2439,
+-2413,-2386,-2362,-2343,-2329,-2314,-2293,-2265,-2230,-2195,-2161,-2128,-2097,-2067,-2039,-2010,-1979,-1946,-1914,-1886,-1863,
+-1841,-1818,-1791,-1764,-1740,-1718,-1695,-1669,-1644,-1627,-1619,-1615,-1607,-1589,-1564,-1540,-1525,-1522,-1525,-1526,-1518,
+-1501,-1477,-1447,-1411,-1360,-1280,-1162,-1009,-841,-684,-556,-456,-369,-280,-192,-124,-95,-105,-134,-156,-162,
+-160,-174,-222,-306,-409,-509,-592,-648,-678,-690,-690,-685,-679,-671,-660,-643,-619,-592,-565,-538,-510,
+-481,-452,-426,-407,-393,-381,-367,-348,-326,-303,-282,-264,-249,-235,-223,-211,-199,-185,-168,-148,-126,
+-107,-90,-74,-56,-39,-25,-16,-10,0,21,51,85,116,144,171,204,243,281,315,342,364,
+386,411,437,464,492,525,565,609,653,695,732,766,798,833,872,919,971,1023,1072,1111,1139,
+1159,1175,1191,1210,1235,1266,1305,1346,1386,1420,1447,1469,1492,1515,1534,1543,1533,1496,1424,1320,1195,
+1072,975,917,896,899,910,923,942,970,1006,1046,1087,1132,1187,1255,1331,1407,1476,1532,1571,1590,
+1586,1568,1545,1530,1521,1512,1494,1467,1437,1413,1394,1373,1346,1316,1291,1271,1249,1217,1174,1130,1095,
+1071,1050,1021,980,935,892,854,819,783,749,716,682,639,586,530,485,457,442,424,391,346,
+299,260,232,210,188,162,132,102,76,57,48,46,45,39,28,19,13,6,-13,-45,-79,
+-93,-76,-37,-1,11,2,-11,-15,-13,-23,-58,-114,-170,-203,-214,-213,-217,-229,-242,-248,-246,
+-243,-244,-250,-263,-280,-305,-334,-359,-373,-371,-362,-357,-364,-380,-398,-414,-427,-440,-455,-472,-488,
+-504,-519,-533,-546,-558,-569,-582,-599,-619,-636,-650,-661,-674,-691,-712,-736,-758,-779,-799,-818,-837,
+-858,-883,-911,-943,-972,-996,-1014,-1029,-1045,-1064,-1086,-1107,-1126,-1143,-1157,-1168,-1172,-1171,-1166,-1161,-1160,
+-1163,-1169,-1174,-1180,-1187,-1198,-1211,-1224,-1234,-1244,-1256,-1272,-1293,-1313,-1328,-1335,-1335,-1332,-1329,-1329,-1332,
+-1338,-1345,-1351,-1356,-1358,-1359,-1359,-1360,-1364,-1369,-1375,-1380,-1383,-1384,-1383,-1382,-1381,-1380,-1380,-1380,-1380,
+-1381,-1382,-1384,-1384,-1382,-1378,-1373,-1367,-1363,-1360,-1359,-1358,-1358,-1358,-1355,-1349,-1340,-1330,-1320,-1312,-1304,
+-1297,-1289,-1282,-1276,-1271,-1266,-1260,-1252,-1244,-1238,-1234,-1230,-1225,-1218,-1210,-1206,-1204,-1203,-1201,-1198,-1196,
+-1197,-1202,-1209,-1216,-1221,-1225,-1229,-1233,-1235,-1236,-1235,-1234,-1233,-1231,-1228,-1223,-1217,-1212,-1208,-1205,-1201,
+-1196,-1190,-1185,-1181,-1176,-1170,-1162,-1153,-1146,-1140,-1134,-1127,-1117,-1107,-1097,-1089,-1081,-1073,-1065,-1057,-1051,
+-1047,-1041,-1033,-1025,-1018,-1014,-1012,-1011,-1009,-1007,-1005,-1005,-1004,-1000,-994,-988,-984,-983,-980,-974,-963,
+-950,-941,-935,-932,-926,-917,-907,-900,-896,-893,-887,-877,-866,-858,-855,-855,-854,-849,-840,-831,-824,
+-817,-806,-792,-776,-762,-753,-746,-742,-738,-738,-741,-743,-740,-725,-699,-662,-622,-582,-547,-522,-508,
+-504,-504,-501,-491,-475,-457,-440,-424,-408,-391,-373,-356,-339,-322,-303,-282,-261,-240,-221,-203,-187,
+-174,-163,-151,-137,-121,-106,-93,-80,-67,-52,-35,-18,0,23,50,78,102,121,138,158,180,
+201,219,233,251,277,306,333,353,371,392,419,447,471,490,510,534,562,589,613,637,668,
+705,741,769,790,813,842,875,903,922,940,965,999,1035,1064,1088,1112,1136,1152,1144,1111,1071,
+1051,1065,1110,1175,1254,1351,1464,1574,1653,1687,1693,1707,1757,1841,1933,2006,2053,2082,2104,2122,2133,
+2139,2149,2169,2200,2236,2272,2306,2335,2347,2328,2272,2188,2098,2013,1932,1843,1745,1649,1573,1522,1485,
+1450,1411,1375,1352,1339,1329,1312,1291,1274,1264,1258,1251,1240,1230,1228,1233,1240,1242,1238,1231,1225,
+1220,1213,1201,1183,1160,1130,1091,1039,973,891,795,689,579,473,378,299,233,180,140,111,90,
+71,50,26,4,-12,-26,-41,-60,-83,-105,-121,-134,-146,-162,-181,-202,-222,-241,-259,-273,-283,
+-288,-292,-298,-307,-316,-321,-322,-322,-327,-341,-364,-390,-412,-430,-446,-464,-487,-514,-542,-568,-594,
+-620,-645,-668,-688,-705,-721,-737,-752,-763,-770,-774,-774,-770,-761,-748,-735,-724,-716,-706,-690,-667,
+-640,-612,-585,-558,-528,-500,-474,-453,-433,-409,-382,-352,-323,-296,-267,-232,-193,-153,-119,-90,-64,
+-38,-8,26,66,110,160,212,264,317,370,422,471,516,556,595,635,679,722,762,799,838,
+881,927,973,1017,1058,1099,1140,1181,1217,1249,1282,1318,1359,1401,1440,1477,1516,1558,1604,1648,1689,
+1728,1767,1806,1844,1877,1907,1936,1967,2002,2038,2074,2109,2144,2177,2206,2229,2249,2271,2296,2321,2342,
+2358,2375,2398,2429,2459,2482,2496,2505,2513,2519,2517,2505,2489,2478,2479,2488,2493,2491,2484,2479,2477,
+2475,2467,2455,2445,2442,2442,2438,2425,2408,2393,2386,2382,2378,2373,2370,2372,2372,2365,2350,2335,2326,
+2325,2323,2311,2290,2267,2247,2233,2221,2211,2202,2197,2189,2175,2156,2141,2132,2120,2084,2020,1950,1912,
+1928,1977,2012,2003,1968,1964,2037,2171,2301,2357,2427,2372,2254,2139,2076,2069,2088,2102,2101,2084,2058,
+2026,1995,1976,1980,2005,2036,2058,2067,2071,2082,2103,2130,2157,2183,2211,2242,2270,2291,2306,2323,2348,
+2379,2411,2436,2455,2471,2489,2506,2521,2535,2554,2581,2615,2650,2683,2713,2741,2767,2787,2799,2805,2811,
+2819,2829,2834,2831,2822,2816,2820,2833,2851,2867,2878,2886,2894,2902,2909,2916,2920,2925,2930,2936,2943,
+2951,2962,2975,2992,3008,3023,3034,3043,3052,3064,3079,3098,3122,3150,3178,3203,3227,3253,3287,3330,3375,
+3413,3434,3440,3442,3449,3462,3477,3486,3486,3481,3476,3472,3464,3451,3438,3431,3429,3429,3420,3402,3380,
+3363,3353,3341,3320,3291,3266,3261,3279,3311,3341,3356,3353,3343,3336,3343,3371,3418,3477,3535,3578,3606,
+3628,3660,3709,3767,3819,3851,3867,3879,3906,3951,4007,4060,4100,4129,4150,4170,4189,4208,4223,4236,4248,
+4265,4288,4320,4353,4378,4390,4390,4386,4386,4393,4399,4395,4380,4358,4339,4330,4327,4326,4326,4329,4334,
+4338,4333,4318,4300,4289,4290,4300,4307,4307,4300,4294,4294,4299,4303,4304,4302,4300,4296,4288,4272,4252,
+4235,4226,4221,4213,4194,4165,4135,4114,4104,4101,4097,4087,4069,4044,4013,3976,3934,3889,3846,3807,3773,
+3744,3719,3695,3672,3647,3622,3598,3577,3561,3547,3533,3515,3490,3460,3425,3389,3354,3321,3289,3259,3230,
+3203,3175,3146,3114,3082,3056,3037,3026,3018,3007,2993,2981,2972,2964,2954,2937,2913,2889,2871,2861,2857,
+2858,2858,2857,2853,2845,2834,2821,2809,2798,2788,2776,2761,2747,2732,2718,2700,2678,2652,2624,2598,2574,
+2553,2531,2509,2485,2460,2433,2404,2374,2345,2318,2294,2276,2263,2255,2247,2237,2221,2200,2178,2156,2134,
+2112,2091,2071,2052,2033,2012,1987,1960,1934,1909,1884,1856,1826,1796,1771,1750,1730,1707,1677,1645,1611,
+1580,1550,1519,1486,1454,1422,1392,1359,1320,1271,1216,1158,1106,1067,1041,1023,1003,975,937,895,855,
+820,788,753,712,669,625,585,547,509,468,424,380,336,293,249,203,156,109,64,19,-24,
+-69,-115,-161,-206,-251,-297,-346,-395,-443,-487,-528,-570,-617,-669,-723,-776,-826,-875,-924,-974,-1024,
+-1071,-1117,-1165,-1214,-1263,-1309,-1352,-1391,-1430,-1469,-1509,-1552,-1599,-1652,-1708,-1759,-1800,-1829,-1852,-1878,-1910,
+-1946,-1981,-2014,-2047,-2082,-2119,-2157,-2194,-2229,-2266,-2304,-2342,-2379,-2413,-2446,-2478,-2505,-2528,-2549,-2574,-2608,
+-2650,-2692,-2728,-2755,-2774,-2791,-2809,-2829,-2851,-2874,-2897,-2921,-2943,-2962,-2978,-2994,-3010,-3024,-3034,-3043,-3051,
+-3062,-3073,-3081,-3085,-3086,-3089,-3095,-3105,-3116,-3126,-3132,-3133,-3129,-3122,-3115,-3111,-3112,-3112,-3109,-3101,-3091,
+-3086,-3086,-3089,-3090,-3089,-3087,-3087,-3087,-3085,-3080,-3075,-3072,-3073,-3072,-3066,-3054,-3042,-3034,-3029,-3022,-3008,
+-2989,-2970,-2957,-2948,-2938,-2924,-2905,-2887,-2874,-2865,-2857,-2846,-2831,-2816,-2805,-2798,-2791,-2780,-2765,-2749,-2732,
+-2716,-2697,-2675,-2652,-2628,-2606,-2584,-2559,-2531,-2502,-2475,-2452,-2430,-2408,-2383,-2360,-2340,-2323,-2306,-2283,-2255,
+-2222,-2188,-2157,-2127,-2097,-2068,-2039,-2011,-1982,-1952,-1921,-1892,-1867,-1845,-1823,-1800,-1775,-1747,-1719,-1689,-1661,
+-1637,-1621,-1613,-1609,-1603,-1591,-1572,-1549,-1527,-1513,-1509,-1515,-1524,-1526,-1515,-1489,-1453,-1406,-1342,-1243,-1105,
+-939,-772,-633,-530,-448,-367,-281,-204,-157,-151,-171,-196,-208,-216,-240,-297,-387,-493,-591,-665,-712,
+-737,-745,-742,-732,-717,-701,-684,-668,-654,-640,-621,-597,-567,-535,-507,-486,-473,-461,-448,-429,-408,
+-385,-365,-347,-331,-317,-304,-292,-279,-266,-251,-236,-221,-206,-189,-167,-143,-119,-103,-95,-94,-90,
+-75,-46,-10,25,54,79,105,139,178,216,246,270,293,321,356,392,422,444,462,484,519,
+565,618,668,710,743,770,799,835,879,926,970,1007,1035,1057,1079,1104,1133,1165,1199,1232,1267,
+1304,1342,1378,1410,1435,1456,1473,1486,1486,1457,1387,1274,1136,1002,902,847,830,835,849,872,908,
+957,1013,1064,1109,1155,1212,1281,1351,1412,1457,1485,1502,1507,1499,1481,1460,1446,1438,1431,1417,1395,
+1374,1357,1343,1326,1299,1264,1229,1198,1166,1128,1085,1045,1017,1000,985,960,921,875,833,799,773,
+748,721,689,649,599,541,486,443,418,401,378,338,285,231,189,164,150,140,124,98,64,
+26,-5,-23,-26,-25,-30,-41,-52,-54,-48,-48,-65,-99,-136,-158,-159,-148,-132,-114,-90,-56,
+-27,-22,-53,-111,-175,-225,-252,-266,-274,-281,-284,-282,-279,-280,-287,-297,-306,-318,-337,-363,-391,
+-411,-416,-412,-408,-413,-428,-445,-460,-470,-477,-487,-500,-518,-539,-561,-579,-592,-600,-608,-620,-640,
+-663,-684,-701,-713,-724,-737,-752,-768,-784,-802,-822,-843,-863,-883,-904,-929,-958,-988,-1013,-1031,-1045,
+-1059,-1076,-1095,-1116,-1135,-1152,-1166,-1178,-1185,-1187,-1186,-1185,-1186,-1188,-1192,-1196,-1202,-1211,-1224,-1238,-1251,
+-1261,-1269,-1279,-1293,-1312,-1331,-1347,-1357,-1361,-1361,-1359,-1356,-1355,-1354,-1357,-1361,-1368,-1374,-1377,-1379,-1378,
+-1379,-1382,-1386,-1392,-1396,-1398,-1399,-1400,-1401,-1401,-1402,-1403,-1404,-1406,-1407,-1406,-1402,-1394,-1386,-1380,-1375,
+-1372,-1370,-1367,-1366,-1366,-1367,-1366,-1361,-1351,-1339,-1327,-1317,-1309,-1302,-1294,-1287,-1280,-1276,-1271,-1265,-1257,
+-1248,-1240,-1235,-1230,-1225,-1219,-1214,-1211,-1209,-1208,-1206,-1202,-1198,-1197,-1198,-1202,-1206,-1209,-1211,-1213,-1215,
+-1218,-1220,-1221,-1220,-1218,-1215,-1212,-1208,-1205,-1202,-1200,-1196,-1192,-1186,-1179,-1173,-1168,-1164,-1159,-1153,-1146,
+-1141,-1136,-1130,-1123,-1113,-1102,-1092,-1083,-1074,-1065,-1056,-1048,-1043,-1039,-1034,-1027,-1020,-1015,-1011,-1009,-1006,
+-1002,-999,-998,-998,-998,-995,-989,-983,-980,-978,-975,-966,-954,-942,-934,-930,-927,-921,-912,-901,-893,
+-887,-881,-873,-862,-852,-846,-845,-847,-848,-845,-839,-833,-826,-820,-812,-802,-791,-780,-771,-762,-751,
+-738,-725,-712,-700,-686,-667,-641,-610,-578,-549,-525,-510,-503,-503,-505,-506,-501,-490,-474,-456,-438,
+-421,-404,-386,-368,-350,-331,-313,-297,-280,-262,-243,-222,-204,-188,-174,-160,-143,-125,-108,-94,-79,
+-62,-42,-21,0,21,47,76,104,127,144,159,177,197,217,233,247,266,291,319,344,365,
+386,412,442,470,491,505,520,542,569,597,622,647,677,712,745,770,791,815,844,875,899,
+915,933,961,999,1038,1068,1089,1109,1131,1143,1133,1099,1059,1039,1053,1098,1164,1247,1349,1465,1574,
+1646,1671,1671,1684,1739,1830,1929,2004,2046,2068,2081,2089,2090,2087,2091,2111,2146,2186,2221,2246,2260,
+2257,2230,2173,2094,2007,1923,1839,1751,1660,1577,1515,1477,1451,1423,1392,1368,1356,1354,1347,1326,1296,
+1272,1260,1257,1251,1236,1217,1205,1206,1216,1226,1229,1227,1223,1220,1213,1199,1174,1137,1086,1021,942,
+854,762,671,581,493,406,325,254,194,148,114,89,69,49,29,9,-7,-20,-32,-48,-68,
+-90,-112,-128,-140,-152,-167,-186,-206,-225,-242,-255,-266,-274,-279,-282,-285,-289,-293,-294,-293,-293,
+-301,-319,-347,-376,-403,-422,-438,-454,-472,-492,-513,-537,-563,-592,-621,-645,-665,-682,-699,-716,-732,
+-744,-750,-754,-756,-756,-752,-743,-734,-725,-716,-705,-687,-663,-636,-612,-589,-564,-536,-507,-481,-459,
+-438,-414,-387,-358,-331,-305,-274,-237,-196,-157,-125,-100,-76,-49,-16,23,66,113,164,218,273,
+329,383,436,485,529,567,604,643,686,730,772,811,849,890,932,974,1014,1054,1096,1141,1183,
+1218,1248,1276,1308,1346,1386,1425,1463,1503,1548,1596,1641,1682,1721,1762,1803,1841,1875,1904,1934,1969,
+2006,2042,2074,2106,2141,2177,2210,2234,2254,2274,2299,2326,2348,2364,2380,2403,2435,2468,2494,2509,2518,
+2525,2531,2530,2518,2503,2494,2496,2504,2510,2507,2500,2496,2495,2492,2482,2467,2456,2453,2454,2450,2437,
+2418,2402,2392,2384,2375,2367,2363,2366,2369,2364,2351,2336,2327,2323,2317,2302,2283,2268,2262,2258,2247,
+2226,2203,2187,2181,2177,2167,2152,2133,2107,2065,2010,1967,1971,2035,2130,2199,2203,2160,2130,2169,2274,
+2385,2427,2260,2219,2129,2041,1994,1992,2015,2044,2068,2085,2091,2078,2048,2019,2009,2026,2057,2085,2097,
+2101,2110,2131,2160,2188,2210,2230,2252,2275,2294,2309,2324,2344,2372,2401,2426,2442,2451,2460,2471,2489,
+2516,2553,2599,2648,2693,2728,2753,2768,2779,2786,2790,2795,2804,2814,2824,2826,2818,2806,2799,2805,2823,
+2848,2871,2888,2898,2903,2905,2907,2909,2914,2923,2934,2945,2954,2964,2975,2990,3010,3030,3048,3061,3070,
+3078,3089,3104,3125,3153,3184,3215,3242,3264,3286,3313,3346,3379,3405,3418,3418,3412,3410,3414,3423,3432,
+3440,3445,3446,3442,3430,3415,3403,3400,3403,3406,3401,3387,3372,3362,3356,3344,3322,3294,3271,3268,3285,
+3313,3337,3349,3352,3352,3358,3376,3411,3462,3523,3581,3624,3652,3676,3712,3767,3832,3886,3916,3927,3938,
+3968,4020,4082,4135,4171,4192,4207,4224,4244,4263,4279,4293,4311,4334,4363,4393,4419,4433,4434,4420,4400,
+4382,4374,4374,4377,4375,4364,4344,4322,4306,4301,4308,4321,4333,4336,4328,4314,4304,4304,4314,4325,4330,
+4326,4318,4312,4313,4318,4322,4323,4322,4320,4315,4307,4293,4277,4262,4252,4246,4237,4223,4204,4184,4168,
+4158,4151,4144,4133,4115,4089,4054,4014,3972,3931,3892,3855,3820,3788,3760,3734,3709,3684,3659,3636,3617,
+3604,3593,3579,3559,3532,3500,3465,3430,3396,3362,3329,3297,3267,3239,3210,3181,3150,3121,3097,3080,3066,
+3052,3036,3020,3007,2999,2992,2980,2962,2939,2916,2900,2891,2888,2889,2891,2890,2885,2874,2860,2844,2830,
+2819,2809,2799,2786,2772,2756,2737,2717,2695,2673,2653,2635,2616,2595,2572,2548,2522,2495,2466,2436,2408,
+2384,2364,2347,2332,2319,2309,2300,2287,2270,2247,2222,2198,2175,2154,2133,2112,2091,2071,2048,2023,1996,
+1968,1943,1920,1897,1873,1848,1823,1798,1773,1746,1717,1687,1656,1626,1596,1566,1536,1505,1472,1436,1395,
+1346,1292,1236,1184,1141,1111,1091,1073,1051,1019,980,938,899,862,826,787,745,704,666,631,595,
+556,513,468,424,382,341,299,254,208,161,115,70,25,-19,-64,-109,-154,-199,-245,-292,-339,
+-386,-431,-475,-518,-563,-610,-660,-712,-764,-815,-865,-914,-961,-1009,-1058,-1108,-1159,-1208,-1252,-1292,-1329,
+-1366,-1404,-1445,-1491,-1544,-1603,-1660,-1710,-1746,-1771,-1793,-1818,-1849,-1884,-1919,-1952,-1987,-2026,-2066,-2104,-2139,
+-2172,-2207,-2245,-2285,-2322,-2357,-2389,-2420,-2450,-2476,-2501,-2528,-2560,-2597,-2636,-2670,-2696,-2717,-2737,-2757,-2779,
+-2803,-2828,-2852,-2876,-2896,-2914,-2930,-2946,-2963,-2979,-2992,-3004,-3014,-3024,-3035,-3043,-3048,-3052,-3057,-3063,-3072,
+-3083,-3092,-3099,-3101,-3096,-3088,-3081,-3078,-3080,-3081,-3077,-3068,-3059,-3054,-3055,-3058,-3060,-3059,-3059,-3059,-3059,
+-3056,-3050,-3045,-3043,-3043,-3041,-3032,-3020,-3010,-3006,-3004,-2997,-2980,-2958,-2938,-2927,-2922,-2915,-2900,-2879,-2859,
+-2846,-2840,-2833,-2822,-2806,-2792,-2783,-2778,-2773,-2763,-2749,-2732,-2715,-2697,-2678,-2655,-2630,-2606,-2584,-2562,-2539,
+-2513,-2486,-2461,-2439,-2420,-2401,-2380,-2358,-2337,-2316,-2294,-2269,-2241,-2211,-2181,-2153,-2124,-2095,-2064,-2034,-2006,
+-1980,-1952,-1921,-1890,-1862,-1840,-1823,-1807,-1787,-1758,-1722,-1685,-1654,-1631,-1616,-1606,-1597,-1589,-1581,-1572,-1559,
+-1540,-1519,-1505,-1505,-1516,-1527,-1524,-1503,-1471,-1433,-1383,-1305,-1182,-1019,-844,-689,-575,-496,-430,-363,-298,
+-251,-233,-239,-253,-265,-279,-312,-377,-471,-576,-668,-736,-777,-797,-803,-797,-781,-756,-729,-704,-687,
+-676,-668,-655,-634,-606,-579,-558,-546,-539,-530,-514,-491,-465,-443,-424,-408,-393,-379,-366,-353,-339,
+-325,-312,-303,-295,-283,-264,-237,-208,-186,-177,-177,-177,-167,-141,-104,-65,-33,-9,14,42,78,
+117,151,176,196,221,257,302,346,375,387,389,396,424,473,534,593,638,669,694,722,759,
+802,847,888,921,949,974,1002,1034,1069,1103,1132,1156,1179,1206,1243,1287,1331,1366,1388,1398,1401,
+1393,1362,1295,1190,1064,950,877,854,869,903,939,976,1020,1073,1128,1177,1217,1257,1303,1354,1401,
+1434,1449,1454,1455,1454,1448,1435,1420,1408,1402,1397,1388,1372,1355,1340,1326,1307,1278,1240,1199,1159,
+1120,1080,1041,1007,984,968,948,917,875,828,786,752,723,692,658,619,574,523,469,420,383,
+362,346,323,284,232,178,134,108,96,91,81,59,20,-27,-71,-97,-102,-96,-93,-102,-117,
+-126,-125,-121,-126,-147,-178,-206,-223,-228,-226,-214,-189,-151,-111,-88,-94,-130,-181,-231,-273,-305,
+-327,-337,-335,-327,-321,-324,-335,-347,-354,-359,-369,-389,-416,-440,-454,-457,-457,-463,-478,-496,-511,
+-520,-523,-524,-529,-543,-566,-594,-619,-636,-644,-649,-660,-679,-705,-731,-753,-768,-780,-789,-797,-804,
+-813,-828,-849,-873,-895,-914,-930,-950,-975,-1002,-1029,-1050,-1067,-1082,-1097,-1114,-1131,-1147,-1161,-1174,-1186,
+-1194,-1199,-1202,-1205,-1209,-1213,-1216,-1220,-1225,-1234,-1246,-1261,-1275,-1288,-1299,-1309,-1321,-1335,-1350,-1363,-1375,
+-1383,-1388,-1389,-1387,-1383,-1378,-1375,-1376,-1381,-1388,-1395,-1399,-1400,-1400,-1400,-1402,-1405,-1408,-1410,-1411,-1413,
+-1415,-1417,-1417,-1418,-1418,-1420,-1421,-1419,-1413,-1405,-1396,-1390,-1385,-1382,-1379,-1376,-1374,-1373,-1373,-1371,-1366,
+-1356,-1344,-1334,-1325,-1319,-1312,-1303,-1294,-1287,-1280,-1276,-1271,-1265,-1256,-1247,-1239,-1232,-1226,-1222,-1217,-1214,
+-1211,-1209,-1206,-1204,-1201,-1199,-1199,-1200,-1201,-1201,-1200,-1199,-1199,-1200,-1202,-1203,-1202,-1200,-1197,-1194,-1192,
+-1189,-1186,-1183,-1179,-1174,-1169,-1163,-1158,-1153,-1149,-1145,-1140,-1135,-1129,-1123,-1118,-1111,-1104,-1095,-1086,-1077,
+-1067,-1058,-1049,-1042,-1038,-1034,-1029,-1023,-1016,-1011,-1008,-1005,-1002,-998,-994,-992,-992,-992,-990,-986,-981,
+-976,-971,-963,-954,-943,-935,-930,-927,-923,-916,-906,-896,-888,-881,-874,-864,-852,-842,-835,-832,-831,
+-830,-826,-822,-817,-813,-810,-804,-798,-791,-785,-779,-770,-756,-737,-714,-690,-665,-642,-619,-595,-573,
+-555,-540,-528,-519,-512,-506,-503,-503,-502,-497,-486,-468,-446,-424,-406,-389,-373,-354,-335,-318,-304,
+-291,-276,-257,-236,-217,-200,-185,-169,-151,-132,-115,-101,-85,-65,-41,-16,6,29,55,84,111,
+134,151,165,181,200,218,234,250,270,294,320,345,367,392,422,455,482,501,514,529,552,
+580,607,630,654,682,715,746,771,793,817,845,871,891,904,923,953,994,1032,1058,1077,1098,
+1122,1136,1125,1088,1045,1025,1040,1086,1149,1227,1322,1434,1542,1617,1647,1652,1670,1731,1829,1933,2009,
+2047,2058,2060,2059,2055,2049,2049,2065,2097,2136,2169,2190,2197,2185,2149,2087,2007,1922,1839,1757,1674,
+1591,1520,1471,1441,1419,1394,1366,1348,1347,1352,1348,1324,1286,1254,1240,1238,1233,1217,1194,1178,1180,
+1194,1208,1215,1213,1209,1205,1197,1178,1142,1086,1013,926,830,735,647,568,497,427,354,281,215,
+162,124,96,74,54,36,19,4,-8,-21,-36,-54,-75,-98,-119,-136,-150,-164,-179,-196,-213,
+-227,-239,-248,-257,-265,-272,-275,-275,-274,-273,-273,-273,-277,-287,-305,-330,-358,-384,-406,-424,-439,
+-455,-470,-487,-508,-534,-564,-594,-619,-639,-657,-674,-693,-708,-719,-725,-728,-732,-736,-737,-734,-728,
+-720,-711,-698,-679,-656,-631,-609,-589,-566,-540,-512,-486,-464,-442,-418,-391,-364,-339,-313,-284,-247,
+-205,-166,-135,-110,-84,-53,-15,28,75,126,180,237,294,348,400,449,496,539,578,615,655,
+697,741,782,820,857,895,935,974,1012,1051,1094,1138,1179,1213,1242,1269,1300,1337,1376,1413,1452,
+1494,1541,1590,1636,1677,1718,1760,1804,1845,1880,1910,1942,1977,2012,2044,2072,2101,2136,2175,2210,2236,
+2256,2276,2302,2330,2354,2371,2386,2410,2443,2477,2504,2519,2527,2533,2537,2535,2524,2511,2506,2511,2520,
+2525,2522,2516,2514,2514,2511,2499,2481,2467,2461,2460,2455,2441,2424,2409,2399,2389,2376,2363,2355,2356,
+2360,2360,2354,2346,2341,2334,2318,2292,2267,2256,2258,2260,2246,2215,2185,2172,2175,2179,2166,2137,2105,
+2080,2065,2055,2058,2090,2159,2240,2288,2269,2195,2123,2108,2159,2230,2260,2012,2008,1984,1968,1979,2010,
+2043,2068,2089,2109,2123,2118,2091,2057,2040,2052,2083,2113,2129,2135,2146,2169,2199,2226,2244,2258,2276,
+2300,2326,2348,2365,2381,2401,2423,2441,2453,2460,2469,2486,2515,2554,2602,2652,2698,2734,2759,2771,2777,
+2780,2783,2788,2795,2803,2809,2809,2803,2792,2784,2786,2802,2829,2856,2879,2893,2900,2904,2908,2912,2918,
+2927,2940,2953,2965,2975,2983,2994,3010,3030,3051,3069,3083,3093,3103,3115,3133,3156,3184,3214,3244,3270,
+3291,3309,3326,3344,3360,3372,3378,3377,3375,3376,3382,3393,3406,3417,3423,3420,3409,3392,3377,3369,3372,
+3381,3386,3383,3374,3365,3359,3353,3340,3319,3295,3281,3283,3298,3318,3334,3344,3354,3369,3390,3418,3455,
+3502,3556,3611,3658,3694,3729,3775,3834,3895,3941,3966,3978,3997,4040,4102,4166,4214,4239,4250,4259,4274,
+4292,4308,4320,4333,4353,4382,4416,4450,4478,4493,4492,4475,4444,4408,4377,4360,4356,4357,4355,4344,4326,
+4313,4312,4324,4341,4354,4353,4341,4325,4317,4319,4330,4340,4342,4338,4331,4327,4329,4334,4339,4343,4344,
+4342,4338,4331,4320,4307,4294,4282,4270,4257,4242,4228,4215,4203,4194,4187,4181,4172,4156,4131,4095,4054,
+4013,3974,3937,3900,3864,3830,3800,3774,3749,3722,3695,3671,3654,3642,3632,3619,3597,3568,3534,3499,3464,
+3428,3391,3354,3319,3287,3259,3232,3206,3182,3159,3138,3119,3099,3079,3059,3043,3033,3026,3018,3004,2986,
+2966,2947,2934,2926,2922,2922,2922,2921,2915,2903,2886,2870,2857,2847,2839,2829,2817,2802,2785,2766,2744,
+2723,2704,2689,2674,2658,2636,2611,2584,2556,2527,2497,2468,2444,2426,2413,2402,2389,2375,2361,2348,2333,
+2314,2290,2262,2236,2214,2193,2173,2151,2129,2106,2083,2059,2032,2004,1978,1956,1936,1916,1894,1867,1838,
+1808,1780,1754,1728,1701,1672,1642,1611,1579,1546,1508,1463,1412,1357,1304,1257,1218,1189,1165,1144,1120,
+1091,1057,1021,983,946,908,868,824,782,743,709,677,641,600,556,511,470,430,391,350,307,
+263,217,171,125,78,32,-13,-58,-104,-150,-196,-241,-286,-332,-378,-425,-470,-514,-559,-604,-653,
+-704,-756,-805,-853,-900,-949,-1000,-1054,-1107,-1155,-1198,-1235,-1270,-1305,-1344,-1388,-1438,-1495,-1554,-1610,-1654,
+-1686,-1709,-1731,-1758,-1791,-1826,-1862,-1898,-1936,-1977,-2018,-2055,-2087,-2118,-2152,-2191,-2231,-2269,-2301,-2330,-2360,
+-2392,-2425,-2456,-2484,-2513,-2544,-2576,-2607,-2635,-2660,-2684,-2708,-2733,-2759,-2786,-2811,-2833,-2851,-2867,-2883,-2898,
+-2915,-2930,-2944,-2957,-2969,-2981,-2992,-3002,-3010,-3016,-3023,-3029,-3036,-3045,-3055,-3063,-3068,-3066,-3059,-3051,-3048,
+-3049,-3050,-3047,-3040,-3032,-3028,-3028,-3030,-3031,-3031,-3031,-3031,-3030,-3024,-3017,-3011,-3011,-3012,-3009,-2999,-2986,
+-2978,-2977,-2978,-2971,-2952,-2929,-2910,-2902,-2900,-2894,-2878,-2855,-2834,-2821,-2815,-2810,-2798,-2782,-2767,-2758,-2754,
+-2751,-2742,-2728,-2711,-2694,-2677,-2659,-2639,-2615,-2591,-2568,-2545,-2523,-2499,-2474,-2450,-2428,-2409,-2391,-2373,-2354,
+-2334,-2312,-2288,-2262,-2234,-2205,-2176,-2148,-2119,-2089,-2058,-2027,-1998,-1972,-1946,-1917,-1886,-1858,-1837,-1823,-1812,
+-1793,-1763,-1723,-1684,-1653,-1635,-1625,-1613,-1599,-1584,-1574,-1572,-1568,-1556,-1534,-1511,-1500,-1503,-1512,-1513,-1499,
+-1475,-1449,-1416,-1359,-1258,-1109,-935,-770,-641,-552,-489,-436,-387,-348,-327,-322,-327,-337,-358,-403,-475,
+-568,-664,-746,-803,-836,-850,-852,-844,-825,-799,-769,-741,-721,-709,-700,-690,-673,-650,-629,-615,-608,
+-603,-593,-574,-549,-522,-498,-478,-460,-444,-430,-418,-406,-394,-382,-373,-366,-359,-346,-324,-295,-270,
+-257,-257,-261,-255,-233,-196,-154,-118,-92,-71,-47,-15,21,58,87,109,129,156,195,242,284,
+308,313,309,315,345,398,460,513,548,569,591,625,673,727,777,816,846,872,898,927,959,
+991,1020,1043,1063,1084,1113,1157,1213,1269,1309,1326,1322,1304,1279,1244,1191,1115,1030,961,932,950,
+1002,1063,1117,1159,1195,1233,1273,1311,1345,1376,1408,1438,1460,1468,1463,1453,1445,1440,1434,1423,1409,
+1397,1390,1384,1376,1361,1342,1323,1306,1287,1264,1234,1200,1163,1124,1084,1047,1015,990,966,935,894,
+845,796,750,708,665,619,570,521,473,425,378,338,309,292,281,264,233,189,140,96,63,
+42,29,16,-7,-46,-97,-145,-176,-183,-174,-164,-166,-177,-190,-196,-197,-198,-206,-220,-235,-250,
+-264,-278,-287,-283,-263,-231,-201,-187,-194,-217,-251,-292,-333,-370,-393,-398,-390,-380,-376,-382,-390,
+-395,-397,-403,-418,-443,-468,-486,-495,-498,-504,-518,-539,-558,-570,-572,-567,-564,-570,-589,-618,-647,
+-669,-682,-690,-702,-720,-745,-770,-794,-813,-829,-839,-844,-846,-850,-861,-880,-905,-928,-948,-963,-978,
+-997,-1020,-1044,-1067,-1087,-1104,-1119,-1133,-1146,-1159,-1171,-1183,-1193,-1202,-1209,-1215,-1222,-1228,-1233,-1237,-1241,
+-1246,-1254,-1265,-1280,-1296,-1312,-1326,-1337,-1346,-1354,-1363,-1373,-1383,-1394,-1403,-1409,-1411,-1410,-1405,-1400,-1397,
+-1398,-1402,-1409,-1416,-1419,-1420,-1418,-1417,-1416,-1416,-1416,-1416,-1419,-1422,-1426,-1428,-1428,-1428,-1427,-1426,-1424,
+-1420,-1415,-1409,-1404,-1399,-1394,-1388,-1384,-1381,-1380,-1378,-1375,-1368,-1360,-1351,-1344,-1337,-1332,-1325,-1317,-1307,
+-1298,-1290,-1284,-1279,-1273,-1266,-1257,-1248,-1239,-1233,-1227,-1222,-1215,-1209,-1204,-1201,-1200,-1200,-1198,-1196,-1194,
+-1193,-1192,-1191,-1188,-1186,-1185,-1185,-1185,-1183,-1180,-1177,-1174,-1173,-1171,-1168,-1164,-1161,-1157,-1153,-1149,-1144,
+-1139,-1136,-1133,-1128,-1122,-1114,-1106,-1100,-1096,-1092,-1087,-1079,-1070,-1061,-1051,-1044,-1038,-1035,-1031,-1025,-1018,
+-1010,-1004,-1001,-1000,-999,-997,-994,-992,-990,-989,-987,-983,-978,-971,-962,-952,-943,-935,-931,-929,-926,
+-920,-911,-901,-892,-885,-879,-872,-864,-853,-844,-835,-827,-820,-813,-806,-800,-795,-792,-788,-784,-780,
+-775,-771,-767,-760,-747,-727,-703,-677,-652,-629,-607,-587,-569,-557,-549,-545,-539,-529,-516,-505,-498,
+-496,-494,-484,-464,-438,-412,-392,-378,-364,-348,-331,-315,-302,-289,-275,-256,-236,-218,-203,-188,-172,
+-153,-134,-118,-104,-88,-67,-43,-18,4,27,52,81,111,136,156,171,187,204,221,237,255,
+275,299,323,346,370,397,428,458,483,501,517,538,565,594,618,637,658,686,718,749,774,
+796,820,847,872,890,903,922,953,991,1023,1046,1065,1090,1118,1133,1117,1073,1028,1012,1037,1090,
+1151,1215,1293,1392,1498,1584,1630,1647,1672,1734,1831,1934,2007,2039,2041,2034,2030,2029,2028,2030,2040,
+2060,2085,2109,2124,2126,2109,2066,1998,1916,1832,1753,1680,1608,1539,1482,1443,1419,1397,1367,1336,1316,
+1314,1322,1320,1297,1260,1228,1214,1212,1208,1191,1168,1154,1158,1174,1190,1196,1194,1188,1183,1170,1138,
+1082,1003,909,810,715,630,558,498,442,382,315,248,188,144,113,90,70,50,32,18,8,
+-3,-18,-38,-60,-83,-105,-126,-145,-162,-177,-192,-206,-218,-227,-233,-238,-245,-254,-263,-268,-269,
+-266,-265,-266,-272,-279,-289,-301,-317,-336,-356,-375,-393,-409,-426,-443,-462,-484,-510,-539,-567,-591,
+-611,-631,-651,-672,-689,-700,-707,-712,-718,-725,-727,-724,-717,-709,-701,-689,-673,-652,-631,-610,-591,
+-569,-544,-517,-492,-469,-446,-420,-392,-364,-339,-313,-284,-249,-210,-174,-143,-115,-85,-49,-7,38,
+87,141,199,259,316,368,415,461,506,551,593,632,672,712,753,792,828,862,899,936,974,
+1011,1049,1087,1127,1165,1198,1228,1258,1293,1332,1372,1411,1450,1494,1542,1591,1636,1677,1717,1760,1806,
+1849,1886,1919,1951,1984,2017,2044,2069,2096,2130,2169,2205,2233,2253,2275,2302,2332,2357,2376,2392,2416,
+2448,2481,2506,2520,2528,2534,2538,2536,2526,2515,2510,2516,2526,2530,2526,2520,2518,2520,2517,2505,2488,
+2473,2466,2463,2455,2441,2423,2410,2402,2393,2378,2362,2350,2346,2348,2349,2348,2348,2348,2341,2320,2289,
+2260,2249,2253,2255,2239,2208,2184,2182,2195,2198,2169,2116,2073,2066,2095,2136,2166,2184,2199,2211,2203,
+2154,2068,1982,1936,1945,1984,2012,1879,1903,1933,1979,2038,2091,2121,2127,2124,2126,2133,2131,2112,2087,
+2075,2087,2118,2147,2164,2172,2184,2209,2242,2269,2287,2300,2320,2350,2384,2414,2432,2443,2451,2461,2471,
+2481,2495,2517,2550,2593,2639,2681,2713,2736,2751,2760,2767,2772,2778,2784,2791,2796,2798,2795,2786,2774,
+2764,2765,2781,2809,2841,2868,2886,2895,2900,2906,2915,2927,2938,2951,2963,2974,2984,2992,3001,3013,3029,
+3049,3069,3086,3098,3109,3122,3138,3158,3182,3207,3233,3258,3281,3300,3315,3326,3333,3337,3340,3343,3346,
+3351,3359,3371,3385,3398,3406,3405,3395,3377,3359,3347,3347,3355,3365,3370,3368,3363,3359,3354,3347,3332,
+3314,3299,3296,3304,3318,3329,3336,3345,3362,3390,3424,3460,3497,3538,3586,3638,3690,3741,3793,3849,3905,
+3952,3983,4001,4020,4058,4118,4190,4251,4288,4301,4305,4312,4327,4344,4355,4361,4368,4385,4412,4447,4483,
+4515,4538,4549,4541,4512,4466,4417,4378,4357,4350,4350,4348,4343,4341,4346,4361,4378,4386,4381,4365,4346,
+4333,4330,4334,4339,4341,4340,4339,4341,4346,4352,4358,4363,4366,4368,4366,4360,4352,4341,4328,4312,4294,
+4276,4260,4247,4238,4231,4225,4221,4216,4208,4193,4168,4134,4095,4055,4016,3978,3940,3902,3869,3840,3814,
+3787,3759,3730,3706,3688,3676,3665,3649,3626,3596,3562,3526,3489,3450,3410,3371,3335,3302,3274,3249,3227,
+3208,3190,3172,3151,3127,3103,3083,3069,3061,3053,3043,3027,3009,2992,2978,2968,2959,2954,2951,2951,2949,
+2942,2928,2911,2896,2886,2880,2872,2862,2849,2835,2821,2805,2786,2765,2745,2726,2709,2690,2668,2642,2614,
+2587,2560,2533,2509,2490,2477,2468,2458,2445,2428,2411,2394,2378,2357,2330,2302,2275,2253,2233,2212,2189,
+2165,2141,2119,2097,2073,2046,2020,1996,1976,1955,1931,1903,1872,1842,1816,1794,1771,1746,1716,1682,1647,
+1612,1574,1531,1482,1428,1375,1330,1296,1271,1249,1226,1199,1166,1130,1094,1059,1025,990,951,909,867,
+826,791,758,724,686,643,598,556,516,478,438,397,356,314,272,228,180,132,85,40,-4,
+-51,-99,-147,-193,-236,-280,-326,-374,-421,-466,-510,-554,-601,-652,-703,-751,-797,-843,-892,-945,-1000,
+-1054,-1102,-1143,-1178,-1213,-1250,-1291,-1339,-1393,-1450,-1506,-1554,-1592,-1619,-1641,-1664,-1695,-1730,-1769,-1807,-1846,
+-1886,-1928,-1968,-2003,-2035,-2067,-2103,-2144,-2184,-2218,-2246,-2270,-2298,-2332,-2370,-2407,-2440,-2468,-2494,-2521,-2551,
+-2581,-2610,-2636,-2663,-2689,-2717,-2744,-2768,-2788,-2805,-2821,-2838,-2856,-2872,-2887,-2899,-2910,-2923,-2936,-2948,-2960,
+-2970,-2979,-2987,-2994,-2999,-3006,-3015,-3025,-3033,-3035,-3031,-3024,-3020,-3020,-3020,-3017,-3011,-3004,-3000,-2999,-3000,
+-3000,-3000,-3000,-3001,-2999,-2993,-2986,-2983,-2984,-2985,-2980,-2968,-2955,-2947,-2947,-2948,-2941,-2923,-2900,-2884,-2879,
+-2879,-2873,-2857,-2832,-2810,-2797,-2791,-2784,-2772,-2756,-2741,-2732,-2729,-2726,-2719,-2707,-2691,-2676,-2662,-2647,-2630,
+-2609,-2585,-2560,-2535,-2511,-2488,-2466,-2443,-2420,-2399,-2381,-2363,-2346,-2327,-2306,-2283,-2257,-2229,-2199,-2169,-2140,
+-2112,-2084,-2055,-2026,-1996,-1968,-1942,-1915,-1889,-1863,-1842,-1825,-1810,-1788,-1757,-1719,-1684,-1661,-1652,-1647,-1638,
+-1619,-1598,-1583,-1578,-1576,-1566,-1544,-1518,-1500,-1495,-1498,-1499,-1491,-1476,-1462,-1445,-1409,-1333,-1211,-1056,-897,
+-759,-654,-579,-522,-477,-441,-418,-405,-404,-416,-448,-505,-584,-673,-757,-822,-862,-880,-881,-874,-861,
+-847,-830,-811,-791,-773,-759,-750,-740,-727,-709,-690,-674,-664,-654,-642,-623,-599,-573,-548,-525,-504,
+-487,-475,-467,-461,-453,-443,-433,-424,-413,-396,-372,-348,-332,-329,-335,-335,-321,-288,-246,-207,-177,
+-154,-132,-105,-73,-39,-8,17,40,63,92,128,167,201,224,233,239,257,294,346,399,434,
+450,457,474,514,572,635,689,727,754,778,804,834,865,894,921,947,975,1010,1056,1114,1180,
+1239,1276,1283,1263,1230,1197,1167,1137,1100,1063,1040,1049,1093,1163,1234,1287,1319,1336,1351,1370,1395,
+1421,1446,1466,1481,1487,1483,1471,1456,1443,1432,1419,1403,1386,1370,1359,1349,1338,1320,1298,1275,1257,
+1243,1233,1221,1204,1179,1146,1107,1067,1030,997,962,921,874,822,770,718,665,607,546,486,431,
+382,337,296,261,237,222,210,194,166,128,86,44,7,-23,-48,-70,-96,-131,-173,-215,-247,
+-260,-257,-247,-243,-245,-252,-258,-261,-262,-265,-270,-277,-287,-302,-322,-341,-350,-346,-332,-314,-300,
+-291,-286,-289,-306,-340,-385,-428,-454,-459,-449,-437,-431,-430,-432,-436,-443,-458,-480,-504,-522,-531,
+-534,-538,-550,-568,-590,-605,-611,-608,-603,-606,-621,-646,-674,-697,-713,-727,-742,-760,-780,-801,-823,
+-844,-865,-881,-890,-892,-893,-900,-916,-938,-961,-980,-996,-1009,-1024,-1041,-1061,-1081,-1101,-1118,-1133,-1146,
+-1157,-1167,-1179,-1190,-1200,-1209,-1217,-1226,-1236,-1245,-1252,-1256,-1260,-1265,-1273,-1285,-1299,-1315,-1332,-1346,-1358,
+-1365,-1370,-1374,-1380,-1388,-1398,-1408,-1417,-1425,-1431,-1432,-1428,-1422,-1418,-1417,-1421,-1427,-1431,-1432,-1430,-1426,
+-1423,-1420,-1418,-1418,-1421,-1426,-1432,-1436,-1438,-1437,-1434,-1431,-1428,-1426,-1424,-1422,-1419,-1413,-1405,-1397,-1391,
+-1388,-1388,-1387,-1383,-1378,-1372,-1366,-1359,-1353,-1346,-1338,-1331,-1323,-1314,-1304,-1295,-1287,-1280,-1273,-1266,-1257,
+-1248,-1241,-1235,-1228,-1219,-1209,-1201,-1197,-1196,-1196,-1194,-1190,-1186,-1183,-1182,-1180,-1178,-1175,-1173,-1171,-1169,
+-1166,-1161,-1157,-1155,-1155,-1155,-1155,-1153,-1150,-1147,-1144,-1140,-1135,-1130,-1126,-1123,-1118,-1111,-1102,-1093,-1087,
+-1083,-1081,-1077,-1070,-1062,-1054,-1046,-1040,-1035,-1030,-1025,-1019,-1011,-1004,-999,-996,-997,-998,-999,-997,-993,
+-990,-986,-983,-980,-975,-968,-959,-949,-941,-935,-932,-929,-925,-917,-907,-896,-886,-879,-874,-870,-865,
+-859,-851,-842,-831,-819,-806,-795,-786,-778,-772,-766,-761,-756,-753,-750,-747,-740,-729,-711,-689,-667,
+-647,-629,-610,-589,-567,-549,-540,-539,-541,-538,-528,-513,-499,-490,-481,-467,-446,-419,-394,-375,-362,
+-351,-338,-322,-307,-295,-282,-268,-250,-232,-216,-202,-188,-172,-152,-133,-117,-104,-88,-68,-44,-21,
+1,23,49,79,111,139,160,178,194,210,226,244,262,283,305,327,349,373,400,430,458,
+480,498,518,544,574,601,622,639,660,688,720,749,771,791,815,843,870,890,907,929,960,
+994,1021,1041,1062,1091,1120,1129,1102,1051,1007,1003,1046,1111,1170,1218,1272,1353,1455,1552,1616,1649,
+1680,1737,1825,1919,1986,2012,2010,2001,2001,2010,2020,2026,2028,2029,2031,2033,2032,2025,2002,1958,1893,
+1816,1739,1672,1612,1554,1500,1455,1425,1403,1378,1343,1303,1275,1267,1271,1271,1255,1227,1202,1192,1191,
+1186,1170,1149,1138,1144,1160,1173,1175,1169,1160,1149,1125,1076,998,900,797,702,623,559,506,458,
+408,350,286,223,172,137,113,93,72,50,32,20,11,0,-15,-38,-63,-88,-112,-136,-157,
+-175,-189,-200,-209,-216,-222,-224,-226,-231,-240,-251,-259,-262,-262,-263,-269,-279,-289,-298,-304,-311,
+-319,-330,-343,-357,-373,-391,-412,-436,-462,-490,-517,-542,-565,-586,-608,-631,-653,-671,-684,-693,-702,
+-711,-718,-719,-714,-706,-698,-690,-681,-668,-650,-630,-612,-594,-574,-550,-524,-498,-474,-450,-423,-393,
+-362,-333,-305,-274,-240,-204,-170,-140,-110,-78,-41,0,42,88,141,201,262,320,372,418,464,
+511,559,604,645,684,723,763,801,836,870,905,940,976,1011,1046,1082,1119,1154,1188,1220,1255,
+1293,1335,1376,1415,1456,1500,1549,1596,1639,1678,1716,1758,1803,1847,1886,1920,1952,1985,2015,2041,2063,
+2089,2123,2162,2198,2226,2249,2273,2303,2334,2361,2381,2399,2423,2452,2482,2504,2517,2526,2535,2542,2541,
+2531,2517,2511,2515,2523,2527,2523,2517,2515,2516,2514,2504,2489,2477,2471,2467,2458,2441,2423,2410,2402,
+2394,2383,2368,2357,2350,2347,2343,2339,2338,2338,2333,2314,2284,2257,2246,2249,2250,2237,2216,2207,2222,
+2243,2239,2191,2119,2071,2079,2137,2198,2218,2189,2134,2085,2048,2010,1958,1898,1854,1841,1855,1879,1902,
+1928,1973,2034,2099,2147,2162,2148,2126,2115,2119,2124,2121,2110,2108,2123,2151,2178,2195,2205,2219,2245,
+2279,2308,2328,2345,2369,2402,2440,2469,2483,2485,2481,2479,2483,2497,2522,2562,2614,2667,2711,2737,2746,
+2745,2743,2747,2756,2768,2777,2783,2786,2785,2783,2776,2767,2757,2753,2761,2783,2815,2849,2877,2894,2902,
+2908,2916,2927,2941,2954,2966,2977,2986,2994,3004,3016,3033,3052,3073,3091,3104,3114,3124,3137,3154,3175,
+3198,3220,3241,3261,3279,3294,3307,3315,3320,3324,3326,3330,3336,3345,3356,3369,3382,3392,3395,3389,3374,
+3356,3341,3335,3339,3348,3356,3359,3358,3355,3353,3348,3338,3325,3312,3308,3315,3329,3341,3346,3347,3355,
+3377,3413,3458,3503,3545,3584,3627,3676,3732,3794,3860,3922,3971,4002,4017,4033,4066,4127,4206,4282,4335,
+4357,4360,4361,4372,4390,4407,4415,4418,4422,4435,4456,4482,4509,4535,4559,4576,4578,4557,4514,4461,4413,
+4381,4367,4364,4365,4366,4369,4377,4390,4402,4408,4403,4389,4371,4355,4344,4339,4338,4339,4343,4349,4356,
+4362,4367,4372,4378,4384,4389,4391,4388,4380,4368,4352,4333,4313,4293,4277,4266,4260,4257,4256,4254,4250,
+4241,4224,4199,4168,4132,4094,4056,4017,3979,3943,3911,3882,3855,3826,3795,3766,3741,3723,3709,3694,3674,
+3648,3617,3584,3548,3510,3469,3427,3388,3352,3320,3291,3265,3243,3225,3210,3194,3175,3152,3129,3110,3097,
+3088,3078,3065,3048,3031,3018,3007,2997,2987,2980,2977,2977,2975,2966,2950,2932,2919,2912,2909,2903,2892,
+2879,2868,2859,2849,2834,2812,2786,2761,2738,2716,2694,2671,2646,2623,2600,2580,2561,2546,2534,2524,2511,
+2495,2476,2457,2439,2420,2397,2371,2344,2319,2297,2276,2253,2226,2199,2174,2153,2135,2114,2091,2065,2039,
+2015,1991,1965,1937,1908,1882,1858,1837,1814,1786,1752,1714,1674,1635,1595,1553,1506,1459,1415,1380,1353,
+1331,1307,1279,1245,1207,1169,1132,1097,1062,1026,987,947,908,871,838,805,769,728,684,641,600,
+561,521,478,436,395,357,318,276,230,182,135,91,47,1,-47,-97,-144,-189,-232,-277,-324,
+-372,-417,-461,-505,-552,-602,-652,-700,-744,-789,-836,-888,-942,-994,-1041,-1080,-1116,-1151,-1189,-1234,-1286,
+-1342,-1398,-1449,-1492,-1524,-1548,-1571,-1596,-1628,-1666,-1707,-1749,-1790,-1830,-1870,-1907,-1943,-1978,-2014,-2054,-2095,
+-2133,-2164,-2189,-2212,-2241,-2277,-2318,-2359,-2394,-2422,-2447,-2473,-2502,-2533,-2563,-2591,-2617,-2643,-2670,-2695,-2717,
+-2735,-2752,-2771,-2792,-2814,-2834,-2848,-2860,-2870,-2882,-2895,-2908,-2920,-2932,-2944,-2954,-2962,-2968,-2972,-2979,-2987,
+-2995,-2998,-2997,-2993,-2991,-2990,-2989,-2985,-2977,-2970,-2967,-2966,-2967,-2967,-2967,-2967,-2966,-2965,-2962,-2959,-2959,
+-2961,-2960,-2953,-2938,-2923,-2915,-2915,-2915,-2907,-2889,-2869,-2855,-2851,-2852,-2848,-2833,-2812,-2791,-2778,-2769,-2760,
+-2746,-2730,-2717,-2710,-2707,-2706,-2700,-2690,-2677,-2663,-2649,-2636,-2621,-2603,-2579,-2552,-2525,-2499,-2477,-2457,-2435,
+-2413,-2390,-2370,-2351,-2333,-2314,-2293,-2270,-2246,-2219,-2190,-2159,-2129,-2103,-2080,-2056,-2029,-1998,-1967,-1939,-1915,
+-1893,-1871,-1848,-1826,-1802,-1777,-1747,-1716,-1691,-1676,-1672,-1671,-1662,-1644,-1620,-1601,-1590,-1583,-1572,-1552,-1529,
+-1510,-1501,-1498,-1495,-1488,-1479,-1474,-1467,-1445,-1393,-1301,-1177,-1039,-908,-795,-705,-635,-582,-540,-509,-487,
+-480,-493,-534,-601,-685,-771,-842,-889,-909,-906,-888,-865,-846,-837,-836,-836,-832,-822,-812,-803,-796,
+-786,-769,-748,-725,-706,-691,-677,-661,-640,-617,-593,-570,-550,-536,-529,-527,-524,-518,-505,-490,-473,
+-455,-436,-415,-400,-394,-397,-401,-395,-373,-338,-301,-271,-246,-223,-197,-166,-136,-108,-82,-57,-30,
+-3,23,50,79,108,137,162,185,214,253,298,337,359,363,361,371,403,454,512,562,600,
+629,658,691,728,765,801,838,878,925,978,1039,1103,1164,1211,1236,1235,1214,1187,1164,1151,1144,
+1137,1131,1133,1157,1205,1268,1329,1371,1388,1388,1384,1387,1400,1417,1434,1445,1451,1450,1445,1435,1422,
+1406,1389,1369,1348,1328,1309,1294,1281,1265,1246,1224,1201,1184,1177,1178,1184,1187,1177,1153,1115,1070,
+1023,978,933,886,837,787,734,677,615,549,482,420,367,320,277,238,205,179,158,136,107,
+69,27,-12,-49,-81,-112,-140,-167,-191,-215,-243,-272,-298,-318,-327,-329,-328,-325,-324,-323,-324,
+-327,-332,-338,-345,-354,-366,-379,-388,-391,-391,-392,-396,-397,-387,-361,-328,-308,-316,-357,-416,-469,
+-501,-507,-498,-487,-482,-483,-488,-496,-509,-527,-545,-561,-570,-574,-577,-584,-596,-612,-625,-633,-637,
+-642,-652,-670,-691,-710,-727,-741,-757,-776,-795,-813,-829,-847,-868,-892,-913,-927,-933,-935,-940,-951,
+-969,-988,-1007,-1023,-1038,-1051,-1064,-1078,-1092,-1109,-1125,-1140,-1153,-1164,-1174,-1184,-1194,-1202,-1210,-1220,-1233,
+-1249,-1262,-1271,-1276,-1280,-1286,-1295,-1308,-1322,-1336,-1350,-1363,-1374,-1383,-1388,-1391,-1395,-1399,-1405,-1412,-1423,
+-1435,-1447,-1455,-1456,-1450,-1441,-1434,-1433,-1435,-1436,-1435,-1432,-1427,-1423,-1421,-1420,-1421,-1424,-1430,-1435,-1440,
+-1442,-1442,-1438,-1434,-1431,-1428,-1428,-1427,-1425,-1421,-1413,-1405,-1400,-1398,-1399,-1399,-1397,-1393,-1388,-1383,-1376,
+-1367,-1357,-1349,-1342,-1336,-1329,-1318,-1305,-1293,-1284,-1277,-1270,-1262,-1253,-1245,-1238,-1230,-1220,-1209,-1200,-1195,
+-1194,-1194,-1191,-1186,-1180,-1176,-1173,-1172,-1169,-1165,-1161,-1159,-1157,-1153,-1148,-1143,-1141,-1142,-1145,-1146,-1146,
+-1145,-1143,-1140,-1135,-1129,-1123,-1119,-1115,-1110,-1104,-1095,-1087,-1080,-1076,-1072,-1067,-1060,-1054,-1047,-1042,-1036,
+-1030,-1023,-1017,-1011,-1006,-1001,-997,-995,-995,-997,-998,-997,-993,-989,-984,-980,-976,-973,-968,-961,-954,
+-947,-941,-935,-930,-923,-914,-903,-890,-879,-871,-865,-863,-861,-859,-853,-844,-832,-820,-808,-796,-784,
+-772,-761,-752,-744,-739,-735,-732,-729,-723,-713,-696,-675,-655,-639,-625,-608,-582,-551,-522,-506,-507,
+-519,-531,-533,-521,-502,-482,-463,-445,-426,-406,-388,-374,-362,-350,-336,-320,-305,-292,-280,-266,-250,
+-234,-219,-206,-191,-173,-154,-135,-120,-106,-90,-70,-46,-21,2,26,53,83,113,140,161,179,
+196,214,232,250,269,288,308,328,348,372,399,429,455,477,497,519,546,576,601,620,637,
+660,689,719,743,759,776,799,829,859,883,905,932,966,1000,1026,1044,1064,1091,1114,1114,1079,
+1025,989,1001,1059,1132,1186,1215,1246,1307,1402,1504,1583,1631,1670,1727,1808,1891,1949,1971,1967,1963,
+1972,1992,2013,2022,2018,2002,1980,1955,1932,1908,1879,1838,1784,1721,1660,1606,1558,1513,1470,1433,1407,
+1385,1357,1316,1270,1233,1218,1219,1221,1214,1197,1182,1175,1174,1168,1153,1137,1129,1135,1148,1154,1150,
+1138,1123,1101,1060,992,900,799,707,634,580,535,492,442,385,321,257,201,159,131,112,93,
+71,49,31,20,12,2,-14,-37,-63,-90,-118,-145,-170,-187,-197,-202,-205,-210,-214,-217,-217,
+-220,-227,-239,-249,-255,-257,-260,-268,-280,-292,-301,-305,-307,-311,-317,-325,-335,-347,-364,-387,-414,
+-443,-472,-498,-521,-544,-566,-588,-610,-630,-647,-660,-672,-684,-696,-703,-705,-701,-694,-688,-682,-673,
+-659,-641,-622,-606,-592,-576,-556,-531,-505,-479,-454,-427,-396,-363,-330,-297,-263,-228,-193,-161,-131,
+-101,-68,-32,3,40,81,131,188,249,308,361,410,458,508,557,603,645,685,726,768,808,
+845,879,912,945,978,1012,1046,1083,1122,1161,1198,1233,1269,1307,1347,1387,1426,1466,1510,1556,1602,
+1642,1679,1715,1755,1799,1841,1879,1913,1946,1978,2009,2036,2060,2087,2121,2158,2194,2224,2249,2276,2307,
+2339,2366,2387,2407,2431,2459,2486,2506,2519,2530,2542,2550,2548,2536,2519,2510,2513,2522,2527,2525,2521,
+2520,2521,2519,2512,2500,2490,2484,2477,2466,2448,2429,2415,2408,2402,2393,2384,2377,2373,2367,2357,2344,
+2334,2329,2322,2305,2280,2256,2245,2245,2246,2239,2233,2243,2272,2298,2290,2233,2156,2106,2115,2167,2210,
+2199,2133,2054,2007,2004,2021,2022,1993,1948,1911,1895,1902,1982,2000,2034,2077,2118,2145,2146,2128,2107,
+2099,2107,2119,2125,2122,2123,2136,2161,2187,2206,2219,2237,2263,2295,2324,2347,2368,2394,2427,2460,2483,
+2490,2484,2473,2467,2471,2489,2525,2575,2633,2686,2722,2736,2734,2727,2727,2737,2752,2766,2773,2773,2769,
+2766,2765,2765,2765,2763,2763,2768,2784,2810,2843,2874,2898,2914,2923,2929,2936,2946,2958,2971,2982,2993,
+3005,3019,3038,3060,3084,3104,3120,3130,3137,3145,3155,3170,3187,3206,3226,3245,3261,3274,3284,3292,3301,
+3310,3319,3328,3335,3341,3348,3356,3366,3376,3384,3384,3378,3365,3350,3339,3334,3336,3342,3347,3350,3351,
+3349,3346,3340,3330,3321,3317,3323,3338,3354,3365,3369,3369,3377,3400,3441,3493,3550,3602,3647,3688,3730,
+3783,3848,3920,3985,4030,4050,4059,4079,4131,4212,4304,4378,4417,4425,4420,4422,4437,4458,4475,4483,4487,
+4494,4508,4524,4538,4548,4557,4567,4574,4572,4553,4518,4475,4436,4410,4396,4392,4391,4390,4391,4394,4401,
+4410,4416,4415,4408,4395,4380,4366,4355,4350,4350,4355,4363,4371,4376,4378,4380,4384,4391,4399,4403,4402,
+4392,4376,4357,4337,4318,4301,4287,4277,4273,4272,4275,4276,4273,4264,4246,4222,4194,4162,4128,4093,4056,
+4021,3988,3957,3928,3896,3863,3830,3802,3781,3763,3746,3725,3699,3669,3638,3605,3570,3532,3490,3448,3409,
+3374,3341,3309,3280,3255,3237,3224,3212,3197,3178,3157,3139,3124,3112,3099,3084,3068,3053,3042,3031,3021,
+3010,3002,2999,2999,2996,2985,2967,2948,2935,2931,2931,2929,2921,2911,2903,2897,2891,2877,2853,2824,2795,
+2771,2751,2733,2714,2694,2673,2654,2637,2620,2605,2590,2574,2556,2537,2518,2498,2479,2458,2436,2412,2388,
+2365,2342,2319,2292,2262,2233,2208,2188,2170,2152,2130,2106,2080,2054,2028,2002,1976,1950,1925,1901,1877,
+1849,1817,1779,1737,1696,1656,1618,1580,1543,1507,1473,1443,1414,1385,1352,1315,1277,1241,1206,1171,1136,
+1098,1059,1020,982,946,911,878,842,804,764,722,682,643,604,562,518,474,433,395,358,317,
+272,225,179,137,95,50,2,-47,-95,-141,-186,-232,-279,-326,-370,-413,-456,-501,-550,-599,-646,
+-691,-736,-783,-832,-883,-931,-975,-1014,-1049,-1085,-1125,-1172,-1225,-1281,-1335,-1383,-1422,-1454,-1480,-1504,-1532,
+-1564,-1603,-1645,-1689,-1731,-1771,-1808,-1844,-1881,-1919,-1959,-1999,-2038,-2072,-2103,-2130,-2159,-2192,-2231,-2272,-2310,
+-2344,-2372,-2398,-2426,-2456,-2486,-2515,-2542,-2567,-2593,-2620,-2644,-2664,-2681,-2697,-2717,-2742,-2768,-2791,-2809,-2821,
+-2832,-2844,-2856,-2868,-2879,-2891,-2905,-2920,-2931,-2938,-2942,-2946,-2950,-2954,-2955,-2954,-2954,-2955,-2956,-2955,-2950,
+-2941,-2934,-2932,-2934,-2938,-2939,-2936,-2932,-2929,-2927,-2926,-2927,-2930,-2932,-2929,-2920,-2905,-2892,-2885,-2885,-2883,
+-2874,-2857,-2838,-2825,-2822,-2822,-2819,-2808,-2792,-2776,-2763,-2752,-2739,-2724,-2710,-2699,-2694,-2692,-2690,-2685,-2677,
+-2664,-2650,-2635,-2620,-2606,-2588,-2566,-2539,-2511,-2485,-2464,-2444,-2423,-2401,-2378,-2358,-2339,-2320,-2299,-2277,-2253,
+-2231,-2207,-2180,-2150,-2120,-2095,-2073,-2052,-2026,-1995,-1962,-1933,-1911,-1893,-1874,-1851,-1825,-1798,-1770,-1744,-1721,
+-1703,-1692,-1687,-1683,-1673,-1656,-1636,-1618,-1605,-1594,-1581,-1565,-1548,-1535,-1524,-1515,-1503,-1491,-1483,-1482,-1480,
+-1467,-1428,-1359,-1264,-1154,-1041,-934,-838,-759,-697,-648,-608,-578,-565,-579,-624,-696,-780,-859,-918,-949,
+-951,-928,-890,-851,-824,-817,-827,-844,-855,-857,-852,-847,-843,-835,-819,-794,-767,-744,-727,-714,-700,
+-682,-660,-638,-619,-605,-599,-598,-598,-594,-581,-561,-536,-512,-490,-472,-458,-451,-452,-457,-457,-446,
+-421,-391,-363,-341,-321,-296,-266,-234,-205,-178,-150,-119,-86,-59,-41,-26,-7,23,62,101,135,
+165,196,231,266,290,298,291,284,289,312,350,397,445,492,538,584,632,680,731,786,845,
+908,970,1028,1078,1116,1140,1151,1151,1148,1146,1149,1157,1164,1167,1167,1172,1190,1225,1272,1318,1349,
+1360,1355,1344,1339,1342,1349,1355,1357,1355,1352,1349,1344,1334,1319,1300,1281,1262,1245,1230,1214,1197,
+1180,1161,1140,1121,1106,1102,1109,1124,1140,1145,1132,1100,1054,1000,943,888,834,781,728,671,610,
+543,476,413,358,310,268,227,189,155,124,93,54,6,-47,-98,-138,-167,-190,-213,-238,-262,
+-282,-297,-309,-323,-341,-362,-382,-397,-405,-406,-403,-399,-399,-402,-408,-415,-423,-431,-438,-441,-437,
+-429,-425,-433,-451,-467,-462,-425,-366,-312,-290,-314,-375,-446,-504,-536,-546,-546,-547,-550,-555,-561,
+-567,-575,-586,-597,-606,-612,-618,-624,-632,-639,-644,-649,-657,-673,-697,-722,-743,-755,-761,-768,-782,
+-803,-825,-844,-859,-875,-894,-916,-936,-951,-959,-964,-971,-981,-995,-1011,-1028,-1045,-1062,-1076,-1087,-1095,
+-1104,-1115,-1129,-1145,-1160,-1173,-1183,-1192,-1198,-1202,-1208,-1220,-1237,-1258,-1277,-1289,-1296,-1301,-1308,-1319,-1332,
+-1345,-1356,-1366,-1377,-1389,-1400,-1408,-1413,-1416,-1417,-1419,-1423,-1432,-1446,-1462,-1475,-1479,-1475,-1465,-1456,-1450,
+-1446,-1442,-1436,-1428,-1423,-1420,-1420,-1422,-1426,-1430,-1434,-1438,-1440,-1440,-1439,-1436,-1432,-1427,-1423,-1421,-1420,
+-1420,-1419,-1416,-1412,-1409,-1408,-1409,-1408,-1404,-1399,-1394,-1389,-1383,-1373,-1363,-1355,-1349,-1345,-1338,-1326,-1312,
+-1298,-1287,-1280,-1272,-1262,-1251,-1241,-1233,-1225,-1216,-1206,-1197,-1191,-1189,-1188,-1186,-1181,-1175,-1171,-1167,-1163,
+-1158,-1152,-1148,-1147,-1146,-1144,-1139,-1134,-1132,-1133,-1135,-1137,-1138,-1137,-1135,-1133,-1129,-1124,-1118,-1113,-1109,
+-1104,-1098,-1091,-1085,-1079,-1074,-1068,-1060,-1052,-1046,-1041,-1037,-1031,-1024,-1016,-1010,-1006,-1003,-1000,-997,-995,
+-994,-994,-994,-993,-989,-985,-981,-978,-974,-970,-966,-962,-957,-951,-944,-936,-928,-920,-913,-903,-891,
+-879,-869,-863,-861,-860,-856,-848,-837,-827,-818,-810,-801,-789,-775,-761,-748,-738,-730,-722,-717,-712,
+-707,-697,-682,-661,-642,-627,-616,-602,-578,-544,-509,-486,-484,-499,-518,-527,-518,-495,-467,-443,-425,
+-412,-403,-395,-387,-376,-362,-344,-327,-311,-297,-284,-271,-256,-241,-226,-211,-194,-175,-157,-141,-127,
+-112,-95,-73,-47,-21,4,31,59,88,115,138,158,177,197,218,239,258,276,294,311,328,
+347,370,397,426,454,477,499,523,550,577,600,619,638,663,692,718,737,750,766,791,822,
+853,878,902,932,967,1002,1027,1043,1058,1079,1095,1089,1053,1007,984,1009,1074,1144,1188,1203,1219,
+1266,1351,1449,1533,1594,1648,1714,1794,1866,1909,1920,1915,1917,1938,1969,1995,2005,1995,1969,1934,1893,
+1852,1815,1780,1742,1699,1652,1604,1560,1519,1480,1443,1412,1388,1365,1334,1289,1239,1197,1176,1174,1181,
+1182,1175,1166,1160,1156,1149,1137,1124,1119,1123,1132,1135,1128,1112,1087,1048,988,904,809,720,655,
+613,583,549,501,437,364,292,227,176,141,119,104,88,69,50,34,23,14,1,-16,-38,
+-63,-91,-121,-153,-179,-196,-203,-203,-204,-208,-213,-215,-215,-216,-222,-233,-244,-251,-253,-255,-262,
+-273,-285,-295,-301,-304,-308,-314,-321,-328,-338,-353,-374,-400,-427,-455,-480,-503,-525,-547,-568,-587,
+-603,-617,-631,-644,-659,-672,-681,-684,-683,-681,-678,-673,-662,-645,-624,-605,-592,-583,-573,-556,-534,
+-508,-482,-456,-430,-400,-367,-332,-296,-259,-223,-189,-157,-126,-94,-60,-25,8,43,81,127,181,
+240,298,353,404,453,503,552,597,639,681,724,768,810,848,882,915,947,979,1013,1050,1091,
+1135,1180,1221,1258,1292,1327,1364,1402,1441,1480,1522,1565,1607,1647,1683,1720,1760,1800,1838,1873,1906,
+1939,1974,2008,2038,2066,2095,2129,2166,2201,2231,2258,2285,2315,2344,2369,2389,2409,2433,2462,2489,2510,
+2525,2538,2550,2557,2552,2537,2521,2512,2516,2527,2536,2538,2537,2538,2541,2541,2535,2524,2512,2503,2492,
+2477,2459,2442,2431,2425,2419,2411,2404,2401,2401,2398,2386,2368,2351,2340,2332,2318,2296,2274,2259,2255,
+2255,2255,2259,2279,2311,2335,2325,2271,2200,2152,2150,2175,2186,2155,2096,2053,2064,2125,2190,2213,2176,
+2102,2031,1990,1982,2037,2057,2080,2099,2114,2122,2122,2113,2105,2105,2113,2121,2122,2116,2113,2122,2143,
+2169,2191,2209,2228,2252,2279,2305,2330,2355,2383,2415,2442,2459,2461,2453,2445,2444,2455,2481,2520,2568,
+2618,2658,2683,2694,2698,2704,2717,2735,2751,2759,2758,2752,2747,2748,2756,2768,2779,2785,2785,2783,2785,
+2798,2824,2858,2893,2919,2933,2938,2940,2946,2958,2974,2992,3008,3024,3042,3065,3092,3117,3138,3152,3159,
+3165,3170,3178,3187,3199,3214,3231,3248,3263,3272,3277,3282,3291,3304,3319,3332,3340,3345,3349,3355,3363,
+3372,3377,3377,3371,3362,3350,3339,3332,3329,3330,3335,3340,3343,3343,3338,3330,3324,3322,3329,3344,3361,
+3378,3389,3395,3400,3410,3432,3473,3531,3599,3665,3719,3759,3793,3837,3899,3974,4043,4087,4106,4116,4146,
+4213,4307,4401,4467,4492,4489,4481,4485,4502,4521,4532,4536,4540,4551,4568,4584,4593,4594,4589,4582,4572,
+4555,4529,4496,4465,4441,4429,4424,4422,4419,4415,4411,4411,4415,4422,4428,4430,4426,4416,4404,4391,4382,
+4377,4376,4379,4384,4389,4391,4391,4389,4389,4391,4396,4400,4398,4387,4370,4351,4333,4318,4306,4294,4284,
+4277,4275,4278,4282,4284,4278,4264,4244,4218,4190,4158,4125,4092,4060,4030,4001,3968,3933,3897,3866,3842,
+3824,3806,3784,3756,3724,3691,3659,3627,3592,3553,3511,3469,3430,3394,3361,3328,3297,3272,3254,3242,3232,
+3221,3205,3186,3166,3148,3133,3118,3104,3089,3076,3064,3052,3040,3028,3018,3014,3012,3008,2997,2980,2963,
+2953,2950,2953,2955,2952,2946,2940,2934,2926,2911,2888,2860,2835,2816,2803,2792,2777,2758,2737,2716,2698,
+2680,2661,2641,2619,2597,2576,2557,2538,2518,2497,2476,2454,2432,2409,2384,2357,2328,2299,2273,2250,2230,
+2210,2189,2167,2144,2120,2095,2070,2044,2019,1993,1967,1939,1909,1876,1840,1802,1761,1721,1683,1648,1617,
+1588,1560,1532,1502,1468,1429,1387,1345,1306,1272,1241,1210,1174,1136,1096,1057,1020,985,949,911,873,
+834,796,759,723,686,647,605,562,519,478,438,398,356,312,266,222,180,138,94,48,1,
+-45,-91,-138,-186,-234,-281,-326,-368,-409,-453,-498,-546,-593,-640,-688,-735,-782,-828,-873,-914,-952,
+-989,-1026,-1068,-1115,-1168,-1221,-1271,-1315,-1352,-1383,-1412,-1440,-1470,-1503,-1542,-1585,-1630,-1673,-1713,-1749,-1785,
+-1824,-1865,-1906,-1944,-1978,-2009,-2041,-2074,-2110,-2148,-2186,-2224,-2258,-2290,-2320,-2348,-2377,-2408,-2438,-2466,-2492,
+-2518,-2545,-2571,-2596,-2615,-2631,-2646,-2667,-2692,-2720,-2745,-2765,-2779,-2792,-2803,-2813,-2823,-2833,-2845,-2861,-2878,
+-2893,-2902,-2907,-2910,-2912,-2913,-2913,-2912,-2913,-2917,-2921,-2921,-2916,-2907,-2900,-2900,-2905,-2910,-2911,-2907,-2900,
+-2893,-2890,-2890,-2892,-2895,-2895,-2892,-2883,-2872,-2864,-2860,-2859,-2856,-2845,-2828,-2812,-2800,-2796,-2793,-2789,-2781,
+-2771,-2761,-2750,-2738,-2723,-2707,-2694,-2685,-2680,-2678,-2674,-2669,-2662,-2650,-2636,-2620,-2603,-2588,-2571,-2550,-2525,
+-2498,-2472,-2450,-2429,-2407,-2384,-2362,-2343,-2327,-2310,-2289,-2265,-2241,-2219,-2199,-2176,-2148,-2117,-2088,-2064,-2042,
+-2017,-1987,-1955,-1926,-1904,-1888,-1871,-1851,-1826,-1799,-1772,-1748,-1727,-1712,-1702,-1695,-1688,-1678,-1664,-1648,-1634,
+-1622,-1609,-1596,-1582,-1572,-1563,-1553,-1538,-1518,-1499,-1489,-1489,-1490,-1481,-1449,-1394,-1320,-1233,-1139,-1043,-952,
+-871,-806,-755,-714,-685,-674,-690,-736,-807,-884,-951,-995,-1010,-998,-962,-911,-860,-826,-817,-831,-855,
+-875,-883,-885,-884,-883,-877,-862,-837,-811,-789,-775,-763,-748,-728,-706,-686,-673,-668,-667,-668,-665,
+-653,-632,-604,-573,-546,-525,-512,-506,-506,-512,-516,-514,-500,-476,-449,-424,-404,-384,-362,-334,-305,
+-274,-240,-201,-160,-124,-102,-94,-90,-75,-41,3,46,76,96,116,148,189,224,236,220,183,
+147,134,158,217,297,380,452,510,560,612,673,744,818,887,943,984,1009,1021,1027,1032,1043,
+1062,1089,1116,1136,1144,1142,1135,1132,1140,1161,1193,1227,1254,1268,1270,1264,1256,1251,1247,1240,1231,
+1222,1215,1213,1210,1204,1192,1177,1164,1155,1148,1140,1128,1112,1094,1075,1057,1040,1027,1021,1027,1043,
+1063,1079,1080,1062,1025,972,910,844,779,714,649,582,512,442,377,321,274,233,194,155,117,
+81,46,7,-42,-100,-161,-213,-251,-274,-291,-308,-328,-349,-366,-376,-381,-386,-397,-415,-437,-457,
+-472,-478,-479,-479,-480,-484,-487,-488,-490,-494,-498,-498,-492,-482,-475,-482,-501,-521,-520,-486,-425,
+-359,-318,-320,-363,-427,-492,-542,-574,-594,-608,-619,-626,-629,-630,-629,-630,-632,-635,-641,-650,-661,
+-671,-674,-673,-671,-677,-697,-729,-761,-784,-793,-793,-794,-805,-826,-850,-872,-888,-903,-919,-936,-952,
+-963,-972,-981,-993,-1007,-1020,-1034,-1049,-1068,-1087,-1103,-1113,-1117,-1120,-1126,-1138,-1154,-1171,-1185,-1196,-1204,
+-1208,-1210,-1214,-1224,-1243,-1267,-1289,-1305,-1315,-1322,-1331,-1343,-1355,-1366,-1375,-1383,-1392,-1403,-1414,-1423,-1430,
+-1433,-1434,-1435,-1438,-1445,-1458,-1474,-1487,-1493,-1492,-1486,-1479,-1471,-1463,-1452,-1440,-1429,-1422,-1420,-1423,-1429,
+-1435,-1441,-1445,-1446,-1444,-1440,-1436,-1432,-1428,-1422,-1416,-1411,-1409,-1410,-1413,-1415,-1416,-1415,-1415,-1413,-1409,
+-1402,-1394,-1387,-1381,-1376,-1370,-1363,-1356,-1351,-1346,-1339,-1328,-1314,-1301,-1291,-1282,-1274,-1262,-1249,-1238,-1229,
+-1221,-1213,-1203,-1192,-1184,-1179,-1177,-1174,-1170,-1165,-1161,-1157,-1152,-1145,-1139,-1135,-1135,-1136,-1136,-1133,-1129,
+-1126,-1126,-1126,-1127,-1126,-1124,-1122,-1121,-1119,-1116,-1111,-1107,-1101,-1096,-1090,-1086,-1082,-1078,-1073,-1066,-1056,
+-1047,-1040,-1036,-1032,-1026,-1019,-1012,-1006,-1002,-999,-996,-994,-992,-992,-992,-990,-987,-983,-980,-978,-976,
+-972,-966,-960,-955,-951,-946,-938,-929,-921,-915,-911,-906,-898,-888,-878,-873,-870,-866,-858,-845,-831,
+-820,-814,-810,-803,-793,-778,-763,-750,-738,-726,-712,-700,-690,-683,-675,-661,-642,-623,-609,-602,-595,
+-581,-556,-525,-500,-491,-496,-507,-510,-499,-475,-447,-423,-409,-404,-403,-401,-395,-383,-368,-350,-332,
+-317,-302,-288,-273,-259,-245,-230,-214,-197,-178,-162,-147,-134,-118,-99,-75,-49,-23,3,31,60,
+88,113,134,155,177,201,225,247,266,283,299,315,331,349,370,396,424,451,476,501,527,
+555,582,605,625,646,670,696,719,737,754,777,807,841,869,890,909,935,967,997,1018,1030,
+1042,1059,1073,1069,1043,1010,1000,1031,1094,1158,1197,1212,1228,1270,1342,1427,1505,1573,1644,1723,1800,
+1852,1867,1853,1840,1850,1884,1926,1955,1961,1946,1918,1883,1843,1800,1757,1719,1682,1645,1605,1563,1522,
+1484,1450,1420,1394,1372,1349,1317,1270,1217,1171,1146,1142,1152,1160,1160,1154,1146,1140,1132,1122,1112,
+1106,1108,1114,1118,1115,1100,1067,1010,929,833,740,670,631,616,601,568,509,429,343,264,199,
+152,122,104,92,81,69,55,42,29,16,-1,-21,-44,-67,-94,-124,-156,-184,-201,-207,-207,
+-208,-213,-219,-222,-221,-220,-225,-235,-245,-252,-253,-253,-258,-269,-282,-293,-300,-304,-309,-315,-322,
+-329,-337,-349,-367,-389,-414,-439,-462,-485,-506,-526,-544,-561,-576,-591,-605,-620,-636,-649,-658,-663,
+-664,-663,-661,-655,-644,-626,-605,-588,-577,-570,-562,-549,-528,-503,-478,-453,-426,-397,-364,-328,-292,
+-257,-222,-189,-156,-124,-90,-55,-19,15,51,90,134,184,240,296,350,401,452,501,548,594,
+638,683,727,770,810,846,880,914,949,984,1021,1060,1103,1149,1195,1237,1274,1308,1342,1379,1417,
+1456,1495,1535,1576,1616,1656,1695,1733,1771,1807,1841,1873,1905,1940,1977,2014,2047,2077,2109,2143,2180,
+2214,2243,2268,2293,2320,2345,2367,2384,2403,2426,2456,2486,2512,2532,2548,2559,2562,2556,2541,2527,2522,
+2528,2539,2548,2552,2554,2558,2563,2565,2560,2549,2535,2522,2507,2490,2473,2461,2454,2450,2444,2434,2426,
+2424,2426,2426,2416,2399,2382,2370,2364,2354,2337,2316,2299,2291,2288,2288,2294,2308,2328,2339,2324,2279,
+2224,2184,2173,2176,2167,2139,2114,2126,2193,2285,2351,2345,2269,2162,2076,2035,2037,2077,2106,2119,2117,
+2113,2112,2115,2117,2117,2117,2117,2114,2107,2098,2096,2107,2129,2156,2178,2194,2208,2224,2245,2270,2296,
+2326,2357,2387,2411,2423,2425,2423,2425,2436,2459,2491,2530,2569,2601,2624,2639,2652,2668,2690,2713,2732,
+2740,2740,2734,2730,2731,2738,2752,2769,2787,2800,2804,2800,2794,2795,2810,2842,2880,2915,2936,2945,2948,
+2954,2968,2989,3011,3030,3047,3065,3089,3117,3144,3164,3177,3183,3188,3194,3201,3207,3214,3222,3235,3251,
+3265,3274,3279,3283,3292,3306,3320,3331,3337,3340,3345,3353,3363,3370,3372,3369,3362,3354,3344,3333,3322,
+3316,3316,3323,3331,3336,3334,3327,3320,3320,3330,3346,3365,3382,3397,3410,3423,3436,3451,3474,3513,3573,
+3648,3723,3784,3824,3855,3894,3955,4030,4100,4146,4165,4181,4219,4294,4392,4481,4536,4550,4542,4536,4543,
+4559,4571,4573,4566,4562,4569,4584,4601,4614,4619,4618,4609,4591,4562,4525,4489,4462,4448,4444,4445,4445,
+4443,4440,4439,4441,4447,4454,4459,4458,4451,4440,4430,4422,4418,4417,4416,4415,4415,4416,4417,4415,4410,
+4403,4396,4392,4391,4388,4381,4368,4354,4341,4333,4325,4316,4304,4292,4285,4284,4288,4292,4291,4282,4266,
+4244,4217,4187,4155,4124,4094,4066,4036,4003,3969,3937,3910,3890,3872,3850,3821,3787,3750,3715,3682,3648,
+3612,3572,3531,3490,3452,3417,3383,3351,3322,3298,3279,3265,3253,3241,3226,3208,3188,3170,3153,3139,3125,
+3111,3097,3084,3071,3057,3044,3032,3024,3018,3014,3007,2998,2988,2982,2980,2982,2984,2983,2979,2973,2967,
+2957,2942,2922,2899,2881,2869,2862,2854,2841,2821,2798,2774,2753,2734,2712,2689,2664,2641,2620,2601,2583,
+2563,2541,2519,2497,2475,2450,2421,2392,2364,2340,2321,2303,2284,2260,2235,2210,2186,2163,2140,2115,2088,
+2060,2032,2001,1969,1934,1898,1863,1827,1791,1755,1720,1688,1659,1632,1606,1578,1546,1510,1469,1425,1382,
+1344,1311,1280,1248,1212,1173,1134,1097,1061,1025,986,945,904,866,831,797,761,724,685,646,606,
+567,526,484,441,397,354,311,268,224,179,134,90,46,3,-40,-87,-136,-185,-232,-277,-320,
+-364,-408,-452,-498,-545,-594,-643,-691,-736,-777,-817,-856,-895,-935,-977,-1021,-1069,-1120,-1169,-1214,-1252,
+-1284,-1314,-1343,-1375,-1408,-1444,-1483,-1526,-1570,-1614,-1654,-1691,-1730,-1770,-1812,-1853,-1888,-1919,-1950,-1984,-2023,
+-2062,-2101,-2136,-2169,-2202,-2235,-2268,-2300,-2331,-2361,-2390,-2418,-2445,-2472,-2498,-2523,-2546,-2566,-2583,-2601,-2623,
+-2649,-2676,-2700,-2720,-2735,-2748,-2760,-2769,-2778,-2787,-2799,-2816,-2835,-2851,-2861,-2867,-2871,-2874,-2876,-2877,-2877,
+-2879,-2883,-2887,-2888,-2883,-2874,-2867,-2867,-2871,-2877,-2878,-2874,-2866,-2859,-2856,-2857,-2860,-2862,-2861,-2857,-2850,
+-2844,-2839,-2838,-2835,-2829,-2817,-2803,-2790,-2781,-2775,-2769,-2762,-2754,-2748,-2741,-2734,-2722,-2706,-2691,-2678,-2671,
+-2666,-2662,-2657,-2652,-2645,-2636,-2623,-2607,-2590,-2574,-2557,-2537,-2512,-2485,-2460,-2438,-2416,-2392,-2368,-2346,-2329,
+-2316,-2303,-2283,-2258,-2233,-2211,-2192,-2172,-2146,-2115,-2084,-2056,-2032,-2008,-1982,-1954,-1927,-1904,-1886,-1869,-1850,
+-1828,-1803,-1775,-1748,-1725,-1708,-1701,-1698,-1696,-1690,-1678,-1664,-1651,-1638,-1624,-1609,-1596,-1587,-1581,-1573,-1557,
+-1534,-1511,-1499,-1498,-1501,-1496,-1473,-1429,-1370,-1300,-1222,-1137,-1052,-974,-910,-862,-828,-808,-806,-829,-876,
+-937,-998,-1044,-1068,-1068,-1046,-1006,-953,-901,-864,-852,-863,-886,-906,-918,-923,-926,-928,-924,-910,-888,
+-865,-846,-833,-819,-801,-778,-755,-739,-731,-729,-728,-724,-714,-696,-670,-640,-610,-587,-572,-567,-568,
+-573,-579,-583,-579,-564,-538,-506,-475,-449,-430,-413,-394,-370,-336,-292,-242,-195,-162,-147,-145,-142,
+-123,-87,-44,-11,6,16,32,63,105,138,138,98,30,-35,-60,-24,70,198,322,415,472,
+510,553,616,697,779,845,887,907,913,914,917,928,949,982,1019,1050,1066,1067,1057,1045,1039,
+1043,1057,1079,1105,1131,1150,1160,1160,1151,1138,1122,1105,1087,1072,1061,1056,1052,1044,1033,1022,1015,
+1016,1021,1024,1021,1011,995,979,963,947,934,926,926,937,957,977,991,988,966,923,863,792,
+715,636,557,476,398,325,262,210,167,128,89,51,13,-23,-60,-103,-153,-208,-259,-301,-330,
+-351,-367,-385,-404,-423,-438,-448,-455,-463,-473,-488,-507,-524,-538,-546,-550,-554,-560,-564,-565,-560,
+-554,-551,-552,-556,-557,-552,-545,-545,-555,-569,-574,-558,-520,-470,-428,-411,-423,-458,-505,-552,-592,
+-623,-648,-667,-681,-691,-697,-698,-694,-685,-676,-672,-676,-689,-703,-710,-709,-703,-705,-721,-751,-785,
+-809,-819,-819,-820,-830,-850,-874,-895,-912,-927,-940,-953,-965,-975,-985,-999,-1017,-1034,-1049,-1062,-1076,
+-1094,-1114,-1132,-1141,-1143,-1143,-1146,-1156,-1171,-1187,-1202,-1213,-1221,-1226,-1229,-1232,-1241,-1258,-1279,-1301,-1318,
+-1331,-1342,-1353,-1365,-1377,-1388,-1396,-1404,-1411,-1419,-1427,-1434,-1440,-1444,-1448,-1450,-1453,-1459,-1468,-1480,-1490,
+-1497,-1500,-1499,-1496,-1491,-1481,-1467,-1452,-1440,-1433,-1433,-1437,-1444,-1451,-1458,-1463,-1463,-1457,-1449,-1441,-1435,
+-1431,-1426,-1419,-1412,-1408,-1409,-1412,-1416,-1418,-1419,-1418,-1415,-1410,-1400,-1389,-1379,-1372,-1368,-1364,-1359,-1354,
+-1348,-1342,-1335,-1325,-1313,-1302,-1292,-1284,-1275,-1264,-1252,-1241,-1232,-1225,-1217,-1206,-1193,-1181,-1173,-1166,-1161,
+-1156,-1151,-1147,-1144,-1139,-1134,-1130,-1128,-1128,-1130,-1130,-1128,-1124,-1121,-1119,-1119,-1117,-1115,-1112,-1109,-1108,
+-1107,-1105,-1102,-1097,-1092,-1086,-1081,-1077,-1075,-1072,-1067,-1060,-1050,-1041,-1035,-1030,-1026,-1020,-1014,-1008,-1003,
+-999,-994,-990,-987,-987,-988,-989,-987,-982,-976,-974,-974,-974,-971,-963,-953,-946,-940,-935,-928,-919,
+-911,-907,-906,-905,-902,-895,-889,-885,-882,-876,-865,-848,-832,-819,-812,-807,-799,-786,-771,-758,-746,
+-735,-721,-702,-683,-667,-656,-647,-634,-617,-599,-585,-578,-576,-572,-561,-543,-525,-511,-504,-500,-492,
+-477,-455,-432,-415,-405,-401,-399,-395,-386,-373,-357,-343,-329,-316,-302,-287,-271,-257,-244,-232,-218,
+-201,-184,-169,-154,-140,-121,-99,-74,-49,-25,0,26,55,82,107,129,151,175,200,224,245,
+262,279,296,314,332,351,371,394,420,446,472,499,528,559,587,612,632,652,674,696,718,
+739,762,793,830,864,890,906,920,939,963,986,1002,1014,1029,1051,1071,1073,1055,1033,1031,1065,
+1126,1189,1234,1263,1291,1334,1393,1456,1519,1587,1666,1751,1816,1835,1807,1760,1733,1750,1803,1861,1895,
+1897,1877,1849,1821,1790,1754,1714,1675,1637,1601,1561,1521,1483,1450,1423,1400,1379,1359,1336,1305,1262,
+1212,1166,1137,1131,1139,1149,1152,1147,1138,1130,1124,1116,1107,1099,1097,1101,1109,1112,1098,1057,986,
+888,782,692,635,611,606,595,558,492,408,320,241,179,134,106,90,82,76,68,58,45,
+30,12,-8,-31,-53,-76,-100,-129,-160,-187,-205,-213,-216,-219,-226,-232,-235,-234,-233,-236,-243,
+-251,-255,-256,-257,-263,-276,-290,-302,-310,-314,-318,-323,-329,-335,-340,-349,-362,-380,-401,-424,-446,
+-466,-485,-503,-519,-536,-551,-567,-582,-597,-611,-624,-632,-636,-637,-634,-631,-625,-615,-600,-584,-570,
+-559,-551,-541,-527,-508,-487,-464,-441,-414,-384,-351,-316,-282,-249,-215,-181,-148,-115,-81,-47,-12,
+24,60,98,139,185,235,289,343,395,446,496,544,592,640,688,733,774,809,843,878,916,
+957,998,1039,1079,1121,1165,1208,1247,1282,1316,1352,1391,1432,1472,1511,1550,1590,1630,1670,1708,1745,
+1780,1813,1845,1876,1910,1946,1985,2023,2057,2088,2121,2156,2192,2225,2252,2275,2298,2321,2344,2364,2380,
+2397,2420,2449,2483,2514,2539,2558,2568,2571,2565,2554,2545,2543,2547,2553,2557,2559,2561,2567,2574,2577,
+2573,2563,2550,2536,2522,2505,2490,2479,2475,2473,2469,2461,2454,2451,2452,2452,2443,2428,2411,2401,2397,
+2392,2381,2365,2349,2338,2333,2328,2324,2323,2323,2317,2298,2266,2230,2206,2198,2194,2183,2166,2164,2199,
+2268,2338,2361,2315,2217,2116,2056,2050,2077,2128,2151,2146,2125,2107,2101,2104,2109,2109,2104,2097,2091,
+2088,2091,2104,2128,2156,2180,2193,2197,2197,2204,2220,2247,2280,2315,2348,2376,2394,2403,2406,2411,2422,
+2445,2478,2515,2552,2580,2598,2608,2617,2631,2655,2683,2706,2718,2718,2713,2712,2716,2725,2734,2744,2756,
+2774,2795,2812,2820,2818,2813,2818,2838,2871,2908,2937,2954,2963,2974,2990,3012,3034,3052,3067,3084,3107,
+3135,3163,3184,3195,3201,3207,3214,3222,3227,3230,3234,3242,3254,3268,3279,3288,3296,3306,3316,3325,3329,
+3331,3333,3340,3351,3362,3366,3362,3353,3345,3339,3333,3325,3315,3310,3311,3320,3329,3332,3326,3317,3313,
+3321,3340,3363,3383,3399,3412,3429,3451,3475,3500,3528,3568,3627,3700,3775,3836,3878,3913,3957,4020,4094,
+4159,4200,4219,4240,4286,4365,4459,4538,4581,4589,4581,4579,4589,4604,4611,4604,4588,4575,4570,4576,4588,
+4603,4618,4628,4629,4615,4586,4548,4512,4486,4473,4469,4468,4467,4466,4467,4471,4479,4487,4494,4496,4492,
+4483,4473,4466,4465,4469,4472,4470,4464,4457,4453,4452,4450,4442,4427,4411,4399,4394,4392,4390,4384,4376,
+4368,4363,4358,4350,4338,4325,4314,4308,4307,4307,4304,4296,4283,4265,4242,4215,4187,4157,4128,4099,4069,
+4038,4009,3985,3965,3947,3924,3894,3858,3819,3782,3747,3712,3675,3634,3594,3554,3517,3482,3446,3411,3380,
+3352,3329,3308,3288,3270,3252,3236,3219,3203,3187,3171,3158,3144,3130,3116,3102,3090,3079,3066,3053,3040,
+3030,3025,3024,3025,3024,3022,3019,3015,3012,3008,3004,2999,2994,2987,2976,2961,2945,2931,2921,2914,2905,
+2891,2871,2847,2822,2800,2780,2759,2736,2712,2689,2669,2651,2632,2610,2587,2564,2541,2517,2490,2460,2430,
+2405,2388,2375,2361,2340,2313,2283,2255,2230,2208,2184,2157,2127,2096,2063,2028,1992,1956,1921,1889,1857,
+1826,1795,1763,1732,1703,1673,1643,1611,1578,1543,1506,1468,1428,1391,1356,1322,1287,1249,1209,1170,1133,
+1098,1062,1022,981,940,903,869,834,797,758,718,681,645,608,569,526,481,438,397,357,314,
+269,221,175,131,91,50,7,-37,-84,-131,-176,-221,-267,-314,-362,-408,-454,-500,-548,-597,-644,
+-686,-724,-759,-797,-838,-882,-927,-974,-1023,-1071,-1117,-1158,-1191,-1219,-1246,-1276,-1311,-1348,-1387,-1428,-1469,
+-1512,-1553,-1594,-1633,-1674,-1716,-1757,-1795,-1829,-1861,-1895,-1933,-1974,-2013,-2048,-2080,-2110,-2144,-2181,-2219,-2254,
+-2285,-2314,-2342,-2370,-2399,-2426,-2450,-2471,-2491,-2510,-2530,-2553,-2579,-2606,-2632,-2655,-2674,-2690,-2705,-2717,-2727,
+-2736,-2746,-2760,-2778,-2797,-2813,-2823,-2829,-2833,-2838,-2843,-2846,-2848,-2849,-2851,-2853,-2853,-2847,-2839,-2833,-2831,
+-2833,-2837,-2837,-2835,-2830,-2826,-2826,-2828,-2831,-2833,-2831,-2827,-2822,-2817,-2815,-2814,-2810,-2801,-2789,-2777,-2768,
+-2762,-2756,-2748,-2738,-2729,-2723,-2720,-2715,-2705,-2690,-2674,-2662,-2654,-2649,-2645,-2640,-2635,-2629,-2621,-2609,-2594,
+-2578,-2562,-2545,-2523,-2497,-2470,-2445,-2423,-2402,-2380,-2356,-2335,-2318,-2306,-2294,-2276,-2252,-2225,-2201,-2181,-2161,
+-2137,-2109,-2079,-2051,-2026,-2004,-1981,-1957,-1932,-1909,-1886,-1865,-1846,-1826,-1802,-1773,-1741,-1713,-1696,-1694,-1703,
+-1710,-1709,-1697,-1680,-1663,-1650,-1636,-1620,-1604,-1593,-1588,-1584,-1573,-1554,-1531,-1514,-1509,-1512,-1512,-1499,-1471,
+-1428,-1375,-1312,-1240,-1163,-1090,-1029,-984,-957,-946,-954,-981,-1022,-1068,-1105,-1125,-1126,-1113,-1088,-1052,-1007,
+-963,-930,-917,-924,-941,-957,-966,-971,-974,-976,-973,-962,-944,-923,-904,-887,-869,-848,-825,-805,-793,
+-786,-782,-776,-766,-752,-732,-708,-681,-657,-641,-635,-637,-644,-650,-652,-650,-641,-622,-592,-554,-516,
+-485,-466,-455,-444,-422,-385,-334,-282,-241,-218,-210,-203,-187,-157,-121,-90,-73,-67,-61,-46,-22,
+-1,0,-30,-92,-164,-213,-207,-128,12,178,324,418,460,478,509,572,660,746,806,833,835,
+831,833,844,862,886,911,934,949,952,943,931,922,922,929,941,956,976,997,1018,1031,1031,
+1020,1000,976,953,932,914,901,892,882,870,855,842,835,839,851,864,872,871,863,852,840,
+828,816,806,802,806,819,837,853,859,847,813,759,690,612,529,444,361,281,210,149,97,
+53,12,-27,-64,-100,-136,-174,-216,-261,-303,-339,-367,-390,-410,-432,-453,-472,-487,-500,-513,-526,
+-540,-556,-572,-588,-602,-611,-617,-621,-627,-635,-643,-646,-643,-634,-626,-623,-625,-628,-626,-620,-613,
+-612,-620,-631,-637,-629,-607,-577,-552,-539,-543,-563,-590,-619,-645,-667,-687,-710,-734,-757,-771,-773,
+-761,-741,-722,-714,-719,-730,-739,-741,-737,-737,-749,-774,-803,-827,-839,-843,-846,-857,-876,-898,-918,
+-933,-946,-959,-971,-982,-993,-1008,-1026,-1048,-1068,-1083,-1094,-1105,-1121,-1139,-1155,-1165,-1167,-1167,-1171,-1181,
+-1196,-1211,-1223,-1233,-1242,-1249,-1255,-1261,-1269,-1281,-1297,-1315,-1332,-1347,-1360,-1373,-1385,-1397,-1408,-1419,-1428,
+-1435,-1439,-1442,-1444,-1449,-1455,-1461,-1466,-1468,-1471,-1476,-1483,-1491,-1498,-1504,-1508,-1509,-1506,-1498,-1486,-1473,
+-1464,-1461,-1462,-1465,-1469,-1473,-1478,-1482,-1481,-1475,-1465,-1454,-1447,-1443,-1438,-1432,-1425,-1420,-1418,-1419,-1421,
+-1422,-1421,-1421,-1419,-1415,-1407,-1394,-1382,-1372,-1365,-1360,-1354,-1348,-1341,-1334,-1328,-1320,-1311,-1301,-1291,-1282,
+-1273,-1263,-1254,-1246,-1239,-1233,-1224,-1212,-1199,-1186,-1175,-1167,-1159,-1152,-1145,-1139,-1135,-1131,-1129,-1127,-1126,
+-1125,-1124,-1122,-1119,-1115,-1112,-1111,-1110,-1108,-1105,-1102,-1100,-1097,-1095,-1093,-1089,-1085,-1081,-1075,-1071,-1067,
+-1063,-1060,-1055,-1048,-1040,-1033,-1028,-1024,-1019,-1013,-1007,-1002,-999,-995,-989,-984,-981,-982,-986,-987,-984,
+-977,-970,-968,-970,-973,-971,-962,-951,-941,-934,-928,-921,-912,-904,-899,-898,-899,-897,-893,-889,-885,
+-882,-876,-865,-851,-836,-824,-815,-805,-792,-775,-758,-745,-735,-726,-713,-694,-673,-654,-641,-630,-618,
+-603,-585,-568,-556,-549,-546,-543,-538,-530,-521,-509,-496,-481,-464,-447,-431,-418,-409,-401,-393,-383,
+-370,-355,-342,-331,-322,-312,-299,-283,-267,-254,-244,-234,-223,-208,-191,-175,-159,-141,-120,-95,-70,
+-47,-25,-3,21,48,74,97,118,140,164,188,210,229,246,264,284,306,327,347,368,390,
+414,438,464,491,522,554,585,611,632,650,668,686,704,725,751,783,819,852,877,895,912,
+932,954,974,990,1009,1036,1069,1093,1096,1078,1057,1060,1099,1164,1233,1290,1332,1372,1416,1463,1508,
+1556,1617,1695,1774,1818,1803,1735,1657,1620,1646,1716,1790,1832,1835,1813,1786,1761,1735,1702,1664,1624,
+1585,1547,1509,1472,1441,1418,1400,1381,1359,1335,1311,1285,1255,1218,1182,1156,1145,1147,1151,1150,1142,
+1132,1125,1121,1118,1110,1100,1094,1096,1104,1108,1091,1042,957,850,741,652,598,573,561,542,503,
+442,368,291,221,163,120,94,80,75,70,63,51,36,20,1,-19,-41,-64,-87,-112,-139,
+-168,-193,-212,-222,-229,-235,-242,-249,-253,-254,-253,-254,-258,-262,-264,-265,-268,-278,-292,-307,-319,
+-326,-331,-336,-341,-344,-346,-346,-349,-357,-370,-388,-408,-427,-446,-462,-478,-494,-509,-524,-538,-550,
+-561,-572,-583,-592,-597,-598,-594,-589,-583,-575,-566,-555,-543,-531,-518,-505,-490,-475,-458,-441,-421,
+-397,-368,-336,-304,-272,-239,-204,-168,-131,-97,-65,-33,0,33,68,103,139,179,224,276,331,
+386,437,486,535,584,636,688,735,776,811,845,882,924,970,1016,1060,1102,1143,1184,1223,1260,
+1294,1329,1366,1406,1447,1487,1526,1565,1605,1645,1683,1718,1750,1781,1813,1845,1879,1916,1955,1994,2032,
+2065,2097,2129,2164,2200,2233,2259,2281,2301,2323,2346,2366,2383,2401,2423,2452,2486,2520,2548,2567,2578,
+2581,2579,2574,2570,2569,2568,2566,2562,2560,2563,2570,2578,2580,2576,2567,2557,2548,2538,2524,2510,2498,
+2493,2492,2492,2490,2486,2485,2484,2482,2471,2455,2437,2426,2420,2417,2410,2400,2389,2380,2373,2362,2348,
+2333,2318,2304,2288,2270,2254,2246,2244,2241,2230,2215,2208,2221,2249,2267,2249,2191,2117,2065,2057,2088,
+2128,2162,2162,2138,2107,2086,2081,2084,2088,2086,2080,2076,2078,2090,2112,2144,2180,2211,2227,2225,2211,
+2197,2196,2213,2247,2289,2330,2363,2385,2396,2402,2407,2417,2437,2465,2500,2535,2566,2588,2599,2603,2609,
+2623,2645,2669,2685,2690,2689,2689,2697,2711,2725,2732,2732,2736,2752,2781,2815,2840,2849,2844,2839,2845,
+2869,2904,2938,2964,2981,2994,3009,3029,3050,3068,3085,3103,3126,3155,3182,3202,3213,3217,3222,3230,3239,
+3246,3249,3251,3256,3266,3279,3294,3306,3317,3325,3331,3333,3331,3328,3330,3337,3348,3355,3354,3346,3335,
+3328,3326,3325,3322,3317,3314,3317,3324,3330,3329,3321,3312,3313,3328,3353,3378,3398,3411,3425,3447,3477,
+3514,3553,3593,3640,3696,3758,3819,3873,3919,3966,4024,4094,4163,4217,4248,4268,4297,4353,4433,4518,4582,
+4613,4615,4608,4609,4620,4633,4639,4633,4617,4601,4589,4584,4587,4598,4613,4628,4633,4623,4600,4570,4543,
+4525,4513,4506,4500,4495,4494,4498,4505,4511,4516,4519,4520,4518,4514,4512,4513,4519,4527,4532,4528,4516,
+4502,4491,4484,4479,4468,4452,4433,4419,4412,4412,4413,4410,4403,4394,4387,4381,4374,4366,4355,4345,4337,
+4330,4322,4312,4300,4288,4274,4258,4240,4218,4192,4164,4134,4103,4075,4052,4035,4022,4003,3976,3938,3896,
+3856,3821,3787,3750,3709,3665,3625,3589,3555,3521,3483,3446,3411,3383,3358,3334,3308,3282,3260,3241,3227,
+3213,3199,3184,3170,3157,3145,3133,3123,3115,3108,3099,3086,3071,3058,3051,3052,3057,3061,3060,3054,3046,
+3038,3032,3027,3024,3022,3020,3016,3008,2996,2982,2969,2957,2946,2933,2914,2891,2866,2843,2822,2801,2780,
+2758,2737,2717,2698,2677,2654,2629,2604,2580,2557,2531,2504,2478,2457,2441,2428,2411,2386,2356,2324,2296,
+2271,2248,2222,2192,2159,2125,2090,2053,2017,1981,1948,1919,1891,1862,1833,1804,1774,1745,1712,1677,1641,
+1606,1573,1541,1507,1471,1434,1398,1363,1327,1288,1247,1205,1166,1129,1094,1057,1018,979,942,907,870,
+831,791,751,714,680,646,607,565,521,479,439,400,359,314,267,220,177,136,95,51,6,
+-38,-80,-121,-164,-210,-260,-311,-360,-406,-452,-500,-548,-594,-634,-669,-704,-741,-784,-830,-877,-923,
+-968,-1014,-1058,-1097,-1130,-1158,-1186,-1217,-1255,-1296,-1339,-1381,-1421,-1460,-1499,-1539,-1580,-1622,-1663,-1701,-1736,
+-1768,-1803,-1841,-1883,-1925,-1962,-1994,-2023,-2054,-2091,-2131,-2170,-2203,-2231,-2258,-2286,-2317,-2349,-2378,-2401,-2420,
+-2436,-2453,-2475,-2500,-2528,-2556,-2581,-2603,-2623,-2642,-2659,-2673,-2685,-2695,-2706,-2722,-2741,-2761,-2776,-2786,-2792,
+-2797,-2802,-2808,-2813,-2815,-2816,-2817,-2817,-2814,-2809,-2803,-2798,-2796,-2797,-2799,-2799,-2797,-2794,-2793,-2794,-2797,
+-2801,-2802,-2801,-2797,-2792,-2790,-2789,-2789,-2786,-2778,-2766,-2755,-2747,-2742,-2736,-2727,-2716,-2707,-2702,-2700,-2696,
+-2687,-2673,-2658,-2646,-2638,-2632,-2628,-2624,-2619,-2612,-2602,-2589,-2574,-2559,-2544,-2527,-2505,-2478,-2450,-2425,-2405,
+-2388,-2369,-2349,-2328,-2311,-2298,-2285,-2267,-2243,-2217,-2191,-2168,-2146,-2124,-2100,-2075,-2049,-2024,-2001,-1978,-1955,
+-1932,-1908,-1883,-1859,-1838,-1819,-1798,-1769,-1736,-1705,-1689,-1693,-1710,-1725,-1724,-1708,-1686,-1667,-1656,-1647,-1634,
+-1617,-1603,-1596,-1594,-1590,-1575,-1553,-1531,-1519,-1518,-1521,-1519,-1505,-1479,-1442,-1395,-1340,-1279,-1218,-1164,-1123,
+-1099,-1092,-1103,-1126,-1155,-1180,-1191,-1187,-1172,-1151,-1128,-1100,-1069,-1036,-1011,-1001,-1005,-1016,-1024,-1025,-1022,
+-1019,-1019,-1018,-1011,-996,-975,-952,-930,-907,-886,-867,-853,-844,-836,-828,-818,-805,-792,-775,-755,-732,
+-711,-700,-700,-709,-719,-722,-716,-702,-683,-659,-628,-591,-555,-526,-508,-499,-486,-459,-416,-366,-323,
+-296,-285,-275,-254,-220,-181,-152,-140,-140,-141,-133,-124,-126,-150,-198,-257,-306,-327,-303,-225,-94,
+71,239,370,442,463,468,494,562,656,744,796,807,794,780,779,790,805,817,822,821,815,
+804,791,783,783,791,804,817,828,840,855,870,879,876,861,838,814,793,776,761,748,735,
+721,703,683,663,650,649,658,673,686,692,692,687,680,673,665,656,650,648,653,662,671,
+671,657,624,574,512,443,371,299,229,161,99,42,-8,-55,-98,-137,-171,-202,-234,-269,-307,
+-346,-380,-406,-427,-448,-472,-498,-521,-539,-552,-563,-577,-595,-615,-635,-652,-666,-679,-687,-692,-695,
+-698,-706,-716,-726,-730,-726,-717,-708,-702,-699,-695,-689,-681,-676,-680,-692,-707,-716,-713,-697,-676,
+-657,-649,-651,-660,-670,-677,-683,-695,-716,-746,-778,-805,-818,-815,-800,-782,-768,-762,-762,-764,-763,
+-763,-766,-779,-801,-827,-849,-862,-868,-874,-886,-903,-924,-942,-957,-969,-981,-994,-1007,-1021,-1039,-1060,
+-1083,-1103,-1117,-1126,-1134,-1145,-1158,-1170,-1178,-1182,-1186,-1195,-1209,-1225,-1239,-1250,-1257,-1263,-1270,-1279,-1288,
+-1297,-1307,-1319,-1333,-1349,-1364,-1379,-1392,-1403,-1414,-1426,-1439,-1450,-1458,-1460,-1458,-1458,-1462,-1469,-1477,-1482,
+-1482,-1481,-1483,-1488,-1496,-1505,-1512,-1518,-1521,-1522,-1518,-1512,-1505,-1502,-1502,-1503,-1502,-1499,-1495,-1494,-1495,
+-1494,-1490,-1481,-1472,-1464,-1459,-1455,-1449,-1441,-1435,-1430,-1428,-1427,-1425,-1424,-1425,-1426,-1424,-1418,-1406,-1392,
+-1378,-1368,-1359,-1350,-1341,-1333,-1327,-1323,-1318,-1310,-1300,-1288,-1277,-1267,-1258,-1251,-1245,-1239,-1232,-1224,-1212,
+-1201,-1190,-1181,-1174,-1167,-1158,-1150,-1141,-1135,-1131,-1129,-1128,-1126,-1123,-1118,-1112,-1106,-1102,-1100,-1100,-1099,
+-1098,-1095,-1092,-1090,-1087,-1084,-1081,-1078,-1075,-1071,-1067,-1062,-1057,-1052,-1046,-1040,-1034,-1028,-1023,-1020,-1017,
+-1012,-1006,-999,-994,-992,-989,-985,-981,-978,-980,-984,-985,-981,-974,-967,-966,-969,-973,-971,-963,-951,
+-941,-934,-928,-921,-912,-902,-895,-892,-891,-889,-885,-879,-874,-869,-863,-856,-847,-838,-830,-820,-807,
+-789,-769,-751,-736,-726,-716,-704,-689,-673,-658,-645,-635,-625,-613,-597,-578,-558,-540,-528,-523,-523,
+-522,-518,-507,-491,-474,-458,-445,-432,-420,-408,-397,-387,-375,-363,-349,-337,-326,-318,-308,-295,-279,
+-263,-251,-242,-234,-223,-209,-192,-174,-156,-137,-115,-91,-67,-45,-25,-4,18,41,64,85,104,
+125,147,170,191,212,232,254,278,301,323,343,363,385,407,430,454,480,510,543,574,601,
+622,638,653,666,679,694,714,739,767,797,826,855,886,918,947,971,994,1023,1061,1099,1121,
+1114,1087,1065,1073,1123,1198,1273,1333,1378,1421,1467,1513,1556,1601,1657,1729,1794,1819,1782,1697,1609,
+1570,1597,1671,1746,1789,1792,1772,1745,1719,1690,1653,1612,1571,1533,1495,1458,1426,1404,1392,1380,1361,
+1329,1294,1264,1245,1234,1221,1204,1186,1172,1165,1159,1149,1135,1122,1116,1117,1118,1113,1103,1094,1093,
+1099,1098,1074,1014,920,809,701,614,554,514,484,453,415,368,314,256,198,145,104,79,68,
+65,61,52,37,21,5,-10,-28,-49,-73,-99,-126,-153,-181,-205,-224,-237,-245,-251,-259,-266,
+-271,-274,-276,-277,-278,-279,-280,-283,-289,-300,-313,-325,-335,-342,-349,-355,-360,-361,-358,-353,-349,
+-351,-358,-371,-387,-404,-419,-434,-450,-466,-482,-496,-506,-512,-518,-524,-534,-544,-552,-554,-552,-546,
+-540,-534,-528,-518,-506,-492,-478,-463,-450,-437,-425,-412,-395,-375,-351,-326,-299,-270,-237,-199,-159,
+-119,-83,-51,-20,11,45,78,111,143,178,221,272,328,383,434,481,527,576,628,682,732,
+776,815,852,892,935,981,1027,1070,1113,1155,1196,1236,1273,1308,1345,1383,1422,1461,1500,1538,1577,
+1618,1657,1692,1721,1749,1778,1810,1845,1884,1923,1964,2004,2042,2076,2108,2141,2174,2209,2240,2266,2288,
+2308,2330,2352,2373,2391,2409,2431,2459,2492,2525,2553,2572,2584,2591,2593,2595,2595,2592,2587,2578,2570,
+2566,2568,2576,2582,2583,2578,2570,2563,2560,2555,2546,2533,2520,2512,2511,2514,2517,2517,2516,2513,2508,
+2497,2482,2465,2451,2442,2436,2431,2426,2422,2418,2411,2398,2379,2359,2342,2330,2321,2314,2307,2302,2298,
+2290,2274,2249,2224,2205,2190,2171,2141,2104,2076,2073,2098,2136,2162,2149,2133,2109,2089,2080,2082,2088,
+2092,2093,2093,2095,2104,2120,2147,2183,2219,2246,2253,2240,2215,2194,2191,2212,2252,2299,2341,2370,2386,
+2393,2400,2411,2430,2457,2487,2518,2547,2570,2586,2595,2599,2605,2615,2630,2645,2654,2658,2661,2669,2686,
+2708,2724,2730,2729,2732,2749,2781,2819,2850,2863,2859,2851,2852,2871,2904,2940,2970,2988,3000,3013,3031,
+3054,3078,3101,3124,3148,3173,3198,3216,3226,3231,3235,3242,3252,3260,3266,3270,3277,3287,3302,3316,3328,
+3336,3341,3341,3339,3335,3331,3331,3335,3341,3343,3339,3331,3324,3322,3324,3326,3324,3321,3319,3321,3326,
+3329,3325,3318,3314,3321,3340,3366,3392,3411,3426,3442,3466,3502,3549,3604,3663,3720,3773,3818,3857,3897,
+3946,4011,4089,4167,4231,4273,4298,4323,4366,4431,4508,4577,4621,4637,4635,4629,4631,4640,4651,4657,4655,
+4646,4635,4623,4615,4612,4615,4623,4629,4627,4616,4597,4579,4565,4556,4548,4538,4528,4522,4522,4527,4533,
+4534,4531,4528,4528,4533,4540,4549,4560,4571,4580,4583,4576,4560,4540,4521,4506,4494,4481,4465,4450,4439,
+4435,4436,4437,4435,4429,4420,4411,4402,4392,4383,4373,4365,4357,4347,4334,4319,4303,4290,4279,4270,4258,
+4242,4221,4195,4166,4136,4111,4093,4081,4069,4050,4019,3978,3936,3897,3864,3831,3793,3749,3705,3666,3633,
+3601,3565,3523,3480,3442,3411,3385,3360,3331,3301,3275,3254,3239,3224,3209,3193,3179,3167,3159,3152,3147,
+3145,3142,3136,3126,3113,3099,3089,3086,3087,3087,3084,3078,3071,3066,3062,3060,3059,3059,3061,3061,3057,
+3046,3030,3013,3000,2988,2977,2960,2938,2913,2887,2864,2842,2820,2799,2778,2759,2739,2717,2692,2665,2639,
+2616,2596,2575,2555,2534,2515,2497,2477,2453,2422,2390,2359,2333,2309,2284,2255,2222,2187,2151,2116,2079,
+2044,2011,1981,1954,1927,1898,1868,1839,1811,1781,1748,1711,1673,1637,1605,1574,1541,1505,1468,1433,1400,
+1367,1330,1288,1243,1200,1162,1128,1094,1057,1019,980,942,904,866,826,788,752,719,684,647,605,
+562,520,480,441,400,357,312,268,225,182,138,92,46,3,-36,-74,-114,-159,-208,-258,-308,
+-356,-403,-451,-500,-545,-585,-621,-657,-697,-742,-789,-833,-875,-914,-955,-996,-1036,-1072,-1104,-1134,-1168,
+-1208,-1253,-1298,-1341,-1380,-1416,-1454,-1494,-1536,-1578,-1616,-1649,-1680,-1711,-1747,-1788,-1832,-1873,-1909,-1940,-1969,
+-2002,-2040,-2079,-2114,-2143,-2167,-2193,-2223,-2260,-2297,-2330,-2356,-2374,-2390,-2406,-2426,-2450,-2476,-2501,-2525,-2547,
+-2569,-2591,-2611,-2627,-2640,-2651,-2663,-2679,-2698,-2718,-2735,-2747,-2754,-2759,-2763,-2768,-2772,-2776,-2778,-2779,-2778,
+-2774,-2770,-2766,-2765,-2767,-2770,-2772,-2771,-2768,-2764,-2762,-2762,-2765,-2768,-2770,-2769,-2766,-2763,-2762,-2764,-2767,
+-2768,-2762,-2751,-2739,-2730,-2723,-2717,-2708,-2698,-2689,-2683,-2680,-2676,-2668,-2656,-2642,-2630,-2621,-2616,-2612,-2608,
+-2602,-2593,-2581,-2566,-2549,-2535,-2521,-2505,-2484,-2459,-2431,-2407,-2389,-2374,-2359,-2342,-2323,-2306,-2291,-2275,-2257,
+-2235,-2210,-2184,-2160,-2137,-2114,-2093,-2071,-2047,-2021,-1994,-1968,-1944,-1923,-1902,-1878,-1853,-1831,-1812,-1792,-1767,
+-1737,-1710,-1696,-1702,-1721,-1735,-1732,-1712,-1687,-1670,-1665,-1663,-1655,-1637,-1619,-1608,-1605,-1604,-1593,-1570,-1544,
+-1526,-1521,-1524,-1526,-1518,-1499,-1471,-1439,-1403,-1364,-1323,-1283,-1251,-1230,-1224,-1231,-1246,-1261,-1267,-1260,-1240,
+-1216,-1194,-1175,-1156,-1135,-1112,-1096,-1090,-1094,-1100,-1100,-1090,-1075,-1063,-1058,-1055,-1050,-1036,-1015,-989,-962,
+-939,-920,-906,-896,-888,-879,-869,-858,-848,-839,-826,-808,-785,-764,-754,-758,-770,-779,-777,-761,-735,
+-707,-680,-653,-625,-598,-575,-559,-545,-523,-487,-440,-394,-362,-347,-338,-320,-283,-238,-202,-191,-200,
+-213,-214,-207,-213,-254,-331,-417,-469,-457,-377,-246,-92,65,214,339,427,470,479,482,513,584,
+678,761,804,801,771,740,723,717,714,704,688,671,656,644,637,635,642,656,672,686,695,
+701,708,714,714,706,689,669,651,638,628,618,607,594,578,559,535,511,491,480,480,486,
+493,498,497,494,489,484,479,473,467,464,463,464,460,448,421,382,333,279,227,176,127,
+79,29,-19,-67,-114,-160,-201,-237,-267,-293,-318,-348,-381,-414,-444,-468,-490,-513,-539,-566,-589,
+-606,-619,-632,-649,-670,-690,-707,-721,-734,-746,-756,-763,-766,-767,-771,-780,-792,-803,-806,-801,-790,
+-777,-767,-761,-757,-754,-751,-752,-757,-765,-771,-770,-763,-752,-743,-740,-741,-742,-737,-727,-718,-715,
+-722,-736,-753,-767,-779,-790,-801,-809,-813,-811,-804,-795,-788,-786,-793,-810,-833,-857,-877,-889,-896,
+-902,-913,-930,-950,-969,-984,-998,-1010,-1023,-1037,-1053,-1071,-1092,-1113,-1131,-1145,-1154,-1161,-1168,-1175,-1182,
+-1188,-1193,-1200,-1214,-1232,-1251,-1267,-1277,-1281,-1283,-1288,-1297,-1308,-1321,-1334,-1346,-1358,-1371,-1386,-1400,-1412,
+-1422,-1431,-1442,-1455,-1467,-1474,-1476,-1473,-1472,-1476,-1484,-1492,-1494,-1491,-1488,-1489,-1497,-1507,-1517,-1525,-1531,
+-1536,-1542,-1545,-1546,-1546,-1546,-1546,-1544,-1537,-1526,-1514,-1506,-1503,-1504,-1503,-1499,-1492,-1485,-1479,-1473,-1466,
+-1457,-1448,-1441,-1436,-1433,-1431,-1430,-1431,-1432,-1431,-1425,-1414,-1399,-1385,-1373,-1362,-1351,-1341,-1332,-1326,-1322,
+-1317,-1310,-1299,-1286,-1273,-1262,-1252,-1244,-1237,-1230,-1221,-1212,-1202,-1193,-1185,-1179,-1175,-1171,-1165,-1157,-1148,
+-1140,-1135,-1131,-1129,-1125,-1119,-1111,-1103,-1096,-1092,-1090,-1090,-1089,-1087,-1084,-1080,-1078,-1076,-1074,-1073,-1071,
+-1069,-1065,-1060,-1053,-1046,-1040,-1034,-1028,-1022,-1017,-1014,-1012,-1010,-1004,-997,-989,-984,-982,-982,-981,-979,
+-977,-978,-980,-981,-977,-972,-968,-968,-971,-973,-971,-963,-952,-943,-936,-931,-923,-914,-903,-896,-891,
+-889,-885,-879,-871,-863,-855,-849,-845,-841,-838,-832,-823,-810,-792,-774,-757,-741,-728,-715,-703,-691,
+-681,-672,-664,-655,-648,-639,-627,-610,-588,-564,-544,-531,-526,-522,-514,-499,-480,-460,-445,-432,-420,
+-407,-394,-384,-377,-373,-366,-355,-341,-328,-317,-306,-294,-279,-263,-249,-238,-227,-216,-201,-183,-164,
+-145,-127,-107,-86,-66,-45,-26,-6,14,34,53,72,91,111,133,156,179,203,228,254,279,
+301,319,337,355,377,399,422,445,469,497,528,557,583,603,619,633,644,655,665,678,696,
+719,748,782,824,870,916,956,987,1016,1048,1086,1118,1128,1108,1074,1055,1076,1139,1222,1296,1347,
+1385,1428,1486,1553,1619,1680,1741,1803,1852,1864,1826,1749,1673,1636,1650,1698,1744,1765,1759,1738,1714,
+1688,1655,1615,1574,1537,1502,1467,1431,1399,1380,1372,1364,1341,1300,1252,1214,1199,1201,1209,1211,1204,
+1192,1181,1168,1151,1131,1115,1108,1110,1113,1109,1099,1090,1088,1092,1086,1054,986,888,778,673,585,
+515,457,408,366,331,300,267,225,175,124,83,59,51,51,48,38,23,8,-4,-17,-33,
+-56,-82,-111,-139,-166,-191,-215,-235,-249,-258,-265,-270,-277,-284,-291,-296,-300,-301,-302,-305,-311,
+-320,-330,-341,-348,-353,-357,-363,-369,-372,-371,-364,-356,-349,-346,-349,-356,-365,-376,-388,-403,-420,
+-438,-457,-472,-482,-487,-490,-494,-501,-510,-517,-520,-518,-513,-507,-500,-492,-482,-469,-456,-442,-430,
+-418,-406,-394,-380,-365,-348,-331,-313,-293,-269,-238,-200,-159,-119,-82,-48,-15,19,56,92,125,
+156,190,231,281,336,389,437,481,525,572,624,677,729,775,818,858,900,943,985,1027,1068,
+1109,1151,1192,1233,1271,1309,1348,1388,1428,1467,1504,1543,1583,1624,1662,1694,1721,1747,1776,1810,1848,
+1888,1928,1969,2010,2050,2086,2119,2150,2181,2212,2242,2269,2292,2313,2335,2356,2376,2395,2413,2435,2462,
+2493,2524,2551,2572,2587,2597,2605,2612,2615,2615,2609,2600,2589,2583,2583,2588,2592,2592,2587,2580,2576,
+2576,2575,2570,2559,2548,2540,2538,2539,2540,2538,2533,2527,2521,2514,2506,2496,2485,2475,2466,2460,2457,
+2458,2457,2453,2441,2423,2405,2391,2383,2378,2369,2357,2341,2323,2302,2278,2248,2217,2187,2160,2136,2116,
+2103,2101,2113,2132,2148,2149,2124,2115,2109,2110,2116,2123,2130,2137,2143,2148,2152,2154,2158,2169,2189,
+2214,2234,2240,2230,2209,2192,2190,2210,2245,2284,2318,2341,2353,2362,2376,2399,2431,2467,2502,2531,2554,
+2572,2585,2594,2600,2606,2611,2618,2625,2632,2638,2646,2659,2677,2697,2714,2727,2737,2750,2769,2794,2820,
+2838,2846,2846,2845,2853,2875,2907,2941,2967,2983,2992,3003,3022,3050,3083,3114,3140,3162,3183,3203,3220,
+3232,3240,3246,3252,3260,3268,3275,3284,3294,3308,3323,3336,3344,3346,3344,3341,3337,3334,3332,3331,3331,
+3331,3330,3327,3324,3324,3325,3327,3327,3324,3321,3320,3322,3325,3325,3322,3320,3324,3337,3358,3383,3407,
+3429,3447,3466,3491,3528,3581,3651,3728,3799,3848,3875,3891,3917,3970,4052,4147,4233,4292,4327,4353,4388,
+4443,4511,4575,4621,4644,4648,4646,4645,4649,4655,4660,4663,4662,4658,4650,4641,4633,4629,4631,4635,4634,
+4625,4610,4595,4584,4577,4570,4558,4543,4528,4522,4526,4535,4541,4541,4536,4532,4535,4546,4564,4582,4598,
+4610,4617,4618,4611,4596,4575,4551,4527,4504,4482,4464,4451,4446,4448,4457,4468,4479,4489,4494,4490,4478,
+4456,4431,4407,4389,4376,4364,4351,4335,4320,4306,4296,4286,4275,4259,4240,4216,4191,4167,4147,4132,4121,
+4107,4085,4054,4015,3975,3938,3906,3872,3834,3792,3751,3714,3681,3647,3606,3560,3513,3472,3440,3414,3389,
+3360,3330,3303,3280,3260,3242,3222,3204,3190,3181,3176,3174,3173,3173,3171,3168,3163,3154,3143,3132,3123,
+3116,3109,3104,3101,3101,3103,3104,3104,3103,3104,3105,3105,3100,3088,3071,3054,3042,3033,3023,3008,2986,
+2959,2931,2905,2881,2858,2835,2815,2795,2776,2755,2730,2704,2679,2658,2642,2627,2611,2594,2574,2551,2523,
+2491,2457,2425,2397,2372,2348,2320,2288,2252,2214,2178,2142,2106,2073,2043,2017,1993,1966,1936,1904,1872,
+1842,1813,1780,1744,1707,1673,1642,1611,1578,1540,1502,1468,1437,1406,1370,1327,1281,1237,1199,1166,1134,
+1098,1058,1016,976,938,901,865,829,794,758,723,686,646,604,561,519,477,436,394,352,310,
+267,224,178,132,87,44,4,-34,-73,-115,-161,-209,-259,-308,-358,-407,-454,-498,-538,-576,-615,
+-660,-707,-754,-797,-834,-869,-904,-942,-981,-1019,-1054,-1088,-1124,-1166,-1211,-1258,-1301,-1339,-1375,-1412,-1452,
+-1493,-1534,-1570,-1600,-1629,-1659,-1695,-1736,-1779,-1818,-1853,-1884,-1916,-1950,-1987,-2023,-2054,-2079,-2103,-2130,-2164,
+-2204,-2245,-2282,-2310,-2331,-2348,-2365,-2385,-2406,-2429,-2452,-2474,-2497,-2521,-2544,-2565,-2582,-2596,-2608,-2621,-2636,
+-2653,-2672,-2689,-2702,-2712,-2719,-2723,-2727,-2731,-2735,-2740,-2742,-2740,-2736,-2732,-2731,-2734,-2741,-2747,-2749,-2748,
+-2743,-2738,-2735,-2735,-2737,-2740,-2742,-2742,-2739,-2737,-2736,-2740,-2746,-2749,-2745,-2735,-2722,-2711,-2704,-2698,-2692,
+-2683,-2673,-2665,-2659,-2654,-2646,-2636,-2624,-2613,-2605,-2599,-2594,-2589,-2583,-2573,-2560,-2544,-2527,-2512,-2499,-2484,
+-2466,-2443,-2419,-2396,-2377,-2361,-2346,-2331,-2314,-2297,-2281,-2263,-2245,-2224,-2202,-2179,-2155,-2131,-2108,-2086,-2064,
+-2041,-2014,-1984,-1956,-1932,-1914,-1896,-1875,-1851,-1827,-1806,-1786,-1764,-1739,-1717,-1706,-1713,-1730,-1742,-1739,-1720,
+-1696,-1682,-1680,-1680,-1673,-1655,-1632,-1617,-1612,-1610,-1600,-1578,-1552,-1533,-1527,-1529,-1527,-1514,-1489,-1460,-1434,
+-1412,-1392,-1372,-1351,-1331,-1318,-1314,-1319,-1327,-1331,-1325,-1307,-1283,-1258,-1239,-1224,-1210,-1195,-1179,-1169,-1168,
+-1173,-1177,-1171,-1154,-1131,-1111,-1098,-1091,-1081,-1065,-1041,-1014,-989,-969,-955,-945,-936,-927,-917,-908,-900,
+-894,-886,-873,-854,-831,-812,-804,-808,-818,-824,-816,-793,-762,-732,-706,-685,-665,-645,-625,-606,-585,
+-556,-517,-474,-435,-409,-394,-377,-346,-303,-262,-243,-251,-274,-289,-286,-283,-311,-387,-494,-578,-579,
+-474,-285,-69,121,259,353,417,462,491,505,520,556,621,702,769,797,780,734,683,641,609,
+580,550,524,506,498,497,499,504,513,527,543,557,566,570,569,565,556,541,524,508,497,
+491,486,480,470,457,442,426,405,382,359,341,329,324,320,316,309,301,291,282,274,266,
+262,260,260,257,246,223,188,144,98,55,19,-11,-40,-71,-106,-145,-185,-226,-265,-301,-332,
+-359,-383,-407,-433,-460,-487,-513,-536,-558,-582,-606,-630,-650,-666,-682,-700,-721,-743,-761,-775,-784,
+-793,-803,-815,-825,-830,-831,-832,-835,-844,-855,-862,-862,-855,-843,-834,-828,-828,-830,-830,-828,-825,
+-820,-816,-810,-804,-800,-801,-806,-810,-808,-799,-786,-774,-765,-755,-739,-716,-692,-683,-698,-737,-787,
+-829,-851,-851,-839,-827,-823,-830,-846,-867,-888,-906,-918,-925,-932,-942,-957,-976,-996,-1013,-1027,-1041,
+-1055,-1070,-1086,-1103,-1120,-1137,-1153,-1167,-1178,-1186,-1192,-1196,-1200,-1203,-1207,-1216,-1231,-1251,-1272,-1289,-1299,
+-1301,-1301,-1302,-1310,-1325,-1343,-1360,-1375,-1387,-1399,-1411,-1424,-1436,-1445,-1454,-1463,-1473,-1483,-1489,-1491,-1489,
+-1488,-1492,-1499,-1503,-1502,-1498,-1495,-1499,-1509,-1522,-1532,-1539,-1545,-1553,-1564,-1575,-1581,-1583,-1582,-1579,-1573,
+-1563,-1547,-1531,-1519,-1513,-1513,-1516,-1516,-1513,-1508,-1502,-1495,-1486,-1476,-1465,-1456,-1448,-1443,-1440,-1439,-1439,
+-1439,-1435,-1428,-1417,-1404,-1391,-1380,-1369,-1358,-1347,-1336,-1328,-1322,-1314,-1305,-1294,-1281,-1270,-1259,-1249,-1240,
+-1230,-1220,-1210,-1200,-1191,-1181,-1174,-1168,-1165,-1163,-1159,-1154,-1146,-1139,-1133,-1130,-1127,-1123,-1117,-1108,-1099,
+-1093,-1089,-1088,-1087,-1085,-1080,-1075,-1070,-1067,-1066,-1066,-1066,-1066,-1063,-1058,-1050,-1042,-1034,-1029,-1024,-1020,
+-1014,-1009,-1005,-1002,-999,-994,-987,-980,-975,-974,-975,-976,-976,-975,-975,-975,-974,-973,-970,-969,-969,
+-970,-970,-967,-960,-952,-945,-939,-934,-926,-917,-908,-901,-896,-892,-887,-880,-871,-861,-852,-846,-842,
+-839,-836,-831,-822,-810,-795,-782,-769,-757,-742,-727,-712,-702,-695,-690,-683,-674,-664,-655,-645,-633,
+-615,-595,-575,-561,-550,-537,-518,-493,-466,-443,-427,-416,-403,-389,-376,-368,-368,-370,-369,-360,-345,
+-328,-316,-306,-297,-284,-268,-251,-235,-221,-208,-193,-176,-157,-138,-120,-101,-83,-65,-46,-27,-8,
+8,25,42,60,80,101,123,144,167,192,219,247,271,290,305,321,340,363,388,412,436,
+459,485,512,538,561,581,598,615,630,644,658,674,695,721,752,789,835,886,937,980,1014,
+1040,1068,1096,1115,1113,1087,1055,1045,1079,1150,1233,1298,1338,1371,1423,1506,1611,1717,1808,1879,1934,
+1970,1975,1944,1887,1828,1789,1776,1775,1769,1748,1719,1692,1670,1648,1618,1584,1552,1526,1501,1469,1429,
+1390,1365,1354,1347,1325,1283,1230,1189,1171,1177,1192,1202,1203,1198,1190,1180,1165,1144,1125,1114,1111,
+1109,1103,1090,1080,1077,1079,1072,1037,968,872,766,664,575,496,425,365,320,291,273,251,215,
+164,108,63,38,30,30,29,22,10,0,-10,-21,-39,-63,-91,-120,-147,-172,-196,-219,-240,
+-256,-267,-273,-277,-283,-292,-302,-312,-319,-324,-328,-333,-341,-352,-363,-370,-374,-375,-376,-377,-378,
+-376,-371,-363,-355,-350,-348,-348,-348,-350,-355,-364,-378,-396,-417,-437,-455,-469,-479,-485,-491,-496,
+-500,-502,-501,-497,-490,-483,-475,-465,-454,-442,-430,-419,-408,-396,-382,-366,-350,-334,-320,-307,-294,
+-278,-258,-231,-198,-161,-124,-88,-52,-14,25,67,105,139,171,205,245,292,342,392,438,482,
+527,575,627,680,729,775,819,861,904,946,986,1025,1063,1102,1141,1180,1218,1256,1294,1335,1378,
+1420,1460,1498,1537,1577,1618,1654,1686,1714,1742,1774,1810,1848,1885,1922,1961,2002,2044,2083,2117,2147,
+2174,2203,2232,2260,2287,2311,2333,2354,2374,2393,2412,2434,2460,2489,2519,2546,2570,2589,2604,2616,2625,
+2632,2636,2635,2629,2621,2612,2607,2606,2606,2606,2604,2600,2597,2596,2595,2592,2585,2577,2571,2567,2565,
+2561,2554,2543,2534,2528,2527,2527,2526,2520,2511,2501,2493,2490,2489,2488,2483,2471,2454,2438,2426,2417,
+2406,2389,2364,2334,2303,2275,2250,2228,2208,2191,2177,2167,2158,2152,2148,2144,2140,2133,2124,2145,2148,
+2155,2162,2167,2170,2173,2179,2188,2196,2196,2186,2172,2163,2166,2181,2200,2214,2218,2212,2205,2203,2213,
+2231,2254,2275,2291,2303,2317,2337,2369,2410,2456,2498,2532,2556,2574,2587,2598,2606,2611,2614,2617,2622,
+2631,2641,2653,2664,2674,2685,2700,2720,2744,2768,2788,2800,2804,2806,2809,2817,2832,2854,2882,2912,2940,
+2960,2973,2983,2995,3018,3050,3087,3122,3148,3167,3183,3200,3218,3235,3247,3255,3260,3264,3270,3277,3288,
+3301,3317,3333,3343,3347,3344,3337,3331,3328,3327,3327,3326,3323,3320,3317,3318,3321,3324,3327,3326,3323,
+3321,3322,3325,3329,3329,3326,3324,3328,3340,3358,3380,3403,3427,3452,3477,3501,3527,3562,3618,3697,3787,
+3865,3913,3927,3929,3950,4009,4104,4209,4294,4347,4378,4407,4451,4510,4568,4611,4632,4637,4638,4641,4647,
+4653,4655,4655,4653,4650,4644,4632,4619,4610,4609,4615,4623,4626,4621,4612,4603,4595,4586,4571,4549,4523,
+4503,4494,4497,4506,4516,4523,4527,4534,4547,4567,4590,4611,4628,4639,4645,4646,4643,4633,4616,4590,4555,
+4516,4479,4452,4440,4445,4467,4501,4544,4591,4635,4667,4674,4654,4608,4548,4489,4442,4411,4391,4376,4362,
+4348,4335,4323,4310,4294,4275,4253,4232,4214,4200,4187,4175,4160,4140,4114,4083,4048,4012,3978,3945,3910,
+3874,3835,3798,3762,3726,3687,3643,3594,3547,3506,3473,3445,3418,3391,3363,3337,3313,3290,3268,3245,3224,
+3208,3199,3195,3195,3195,3195,3195,3194,3192,3189,3183,3175,3164,3153,3144,3140,3142,3148,3153,3155,3154,
+3151,3150,3150,3148,3141,3127,3110,3095,3084,3076,3065,3048,3025,2998,2972,2947,2922,2897,2872,2849,2829,
+2811,2792,2771,2749,2729,2712,2699,2685,2668,2648,2623,2595,2562,2528,2494,2464,2438,2414,2387,2355,2319,
+2280,2241,2204,2168,2133,2102,2076,2054,2032,2006,1975,1940,1906,1875,1844,1811,1776,1741,1709,1681,1652,
+1620,1584,1546,1510,1477,1444,1406,1362,1316,1274,1238,1206,1174,1137,1095,1052,1011,975,940,905,869,
+831,794,757,720,681,640,597,554,511,470,429,387,344,300,255,211,169,128,87,46,5,
+-35,-76,-120,-165,-214,-266,-317,-365,-409,-449,-487,-527,-569,-616,-665,-713,-755,-791,-825,-857,-892,
+-930,-967,-1004,-1041,-1081,-1124,-1171,-1217,-1260,-1298,-1334,-1370,-1408,-1448,-1485,-1519,-1550,-1579,-1611,-1647,-1686,
+-1725,-1761,-1794,-1826,-1860,-1896,-1932,-1966,-1995,-2021,-2048,-2078,-2115,-2154,-2194,-2229,-2257,-2279,-2298,-2317,-2338,
+-2360,-2383,-2407,-2431,-2455,-2478,-2501,-2521,-2539,-2554,-2570,-2585,-2600,-2616,-2631,-2645,-2659,-2670,-2679,-2685,-2689,
+-2694,-2700,-2706,-2709,-2707,-2701,-2696,-2696,-2702,-2711,-2719,-2722,-2720,-2715,-2711,-2710,-2712,-2716,-2719,-2721,-2721,
+-2718,-2714,-2713,-2716,-2720,-2722,-2718,-2709,-2697,-2688,-2682,-2679,-2674,-2667,-2657,-2647,-2638,-2631,-2624,-2616,-2607,
+-2598,-2590,-2583,-2576,-2569,-2562,-2553,-2541,-2526,-2509,-2494,-2479,-2464,-2447,-2427,-2406,-2386,-2367,-2349,-2332,-2316,
+-2300,-2284,-2268,-2250,-2229,-2208,-2187,-2166,-2145,-2122,-2098,-2075,-2053,-2030,-2004,-1976,-1948,-1925,-1908,-1892,-1874,
+-1850,-1825,-1801,-1779,-1757,-1735,-1717,-1709,-1716,-1733,-1748,-1749,-1735,-1715,-1701,-1695,-1692,-1682,-1661,-1638,-1621,
+-1614,-1610,-1600,-1582,-1560,-1545,-1540,-1539,-1530,-1508,-1474,-1438,-1410,-1393,-1383,-1375,-1368,-1361,-1357,-1359,-1364,
+-1368,-1364,-1351,-1331,-1307,-1287,-1272,-1261,-1252,-1241,-1230,-1223,-1224,-1229,-1231,-1224,-1206,-1183,-1162,-1145,-1130,
+-1112,-1088,-1061,-1036,-1017,-1004,-995,-986,-976,-967,-960,-954,-949,-941,-928,-911,-892,-874,-863,-859,-861,
+-864,-860,-847,-824,-797,-771,-748,-729,-709,-686,-661,-637,-612,-586,-557,-526,-497,-471,-445,-415,-377,
+-339,-315,-315,-335,-355,-361,-354,-359,-404,-493,-587,-622,-544,-350,-94,144,309,389,416,433,462,
+501,538,571,608,658,713,755,763,730,670,600,535,480,432,393,367,358,362,372,382,388,
+394,405,419,434,444,447,443,432,416,397,378,364,355,351,346,338,326,313,300,287,271,
+253,232,212,196,183,172,161,148,132,115,96,77,63,56,57,61,60,50,27,-6,-44,
+-80,-110,-133,-153,-174,-199,-229,-263,-299,-333,-364,-392,-420,-447,-475,-503,-530,-554,-575,-593,-611,
+-630,-650,-671,-690,-707,-722,-739,-759,-780,-801,-819,-832,-842,-850,-859,-869,-879,-887,-891,-891,-892,
+-895,-902,-909,-913,-911,-905,-899,-895,-896,-898,-898,-895,-888,-880,-871,-862,-855,-851,-851,-852,-853,
+-849,-842,-837,-837,-836,-823,-786,-726,-662,-622,-628,-681,-760,-833,-879,-893,-887,-878,-875,-881,-892,
+-904,-916,-929,-941,-953,-964,-976,-990,-1007,-1024,-1040,-1054,-1068,-1083,-1099,-1117,-1133,-1148,-1161,-1174,-1186,
+-1197,-1207,-1214,-1218,-1221,-1224,-1229,-1238,-1252,-1270,-1290,-1306,-1316,-1318,-1315,-1314,-1321,-1337,-1360,-1384,-1403,
+-1416,-1426,-1436,-1448,-1460,-1471,-1481,-1489,-1497,-1503,-1508,-1509,-1509,-1510,-1513,-1516,-1516,-1513,-1509,-1509,-1516,
+-1527,-1539,-1548,-1554,-1561,-1572,-1585,-1597,-1603,-1603,-1599,-1594,-1589,-1580,-1566,-1549,-1533,-1524,-1522,-1524,-1526,
+-1525,-1522,-1516,-1510,-1504,-1495,-1486,-1475,-1466,-1459,-1454,-1452,-1449,-1446,-1439,-1430,-1420,-1408,-1398,-1388,-1377,
+-1366,-1353,-1341,-1330,-1320,-1309,-1298,-1286,-1276,-1267,-1258,-1250,-1239,-1229,-1218,-1207,-1197,-1186,-1175,-1165,-1157,
+-1152,-1148,-1145,-1140,-1133,-1126,-1121,-1119,-1118,-1117,-1113,-1106,-1099,-1094,-1091,-1090,-1089,-1084,-1077,-1069,-1062,
+-1059,-1057,-1058,-1058,-1057,-1053,-1046,-1037,-1028,-1021,-1018,-1015,-1013,-1008,-1002,-996,-990,-986,-981,-977,-972,
+-969,-969,-970,-971,-972,-971,-970,-969,-969,-968,-966,-965,-964,-962,-961,-958,-955,-952,-949,-945,-939,
+-931,-922,-915,-908,-903,-898,-891,-883,-875,-868,-860,-854,-848,-843,-837,-830,-819,-806,-794,-785,-778,
+-770,-759,-745,-731,-721,-714,-707,-696,-680,-663,-647,-634,-623,-612,-601,-591,-583,-573,-556,-529,-497,
+-465,-442,-428,-417,-404,-388,-372,-364,-365,-369,-369,-359,-342,-325,-314,-309,-305,-296,-280,-259,-240,
+-224,-211,-199,-184,-166,-145,-123,-103,-84,-65,-46,-28,-10,4,18,33,50,70,91,110,127,
+145,166,191,217,240,259,274,293,317,346,376,404,429,453,476,499,520,541,561,583,607,
+630,652,675,702,732,765,799,833,871,914,959,998,1028,1050,1069,1087,1098,1094,1073,1051,1051,
+1088,1157,1232,1290,1328,1368,1435,1542,1678,1816,1934,2023,2082,2114,2116,2090,2042,1987,1937,1892,1845,
+1789,1729,1677,1641,1620,1602,1581,1558,1538,1525,1510,1481,1437,1389,1352,1333,1323,1306,1272,1227,1190,
+1172,1173,1183,1191,1195,1197,1200,1200,1190,1171,1148,1130,1120,1112,1101,1084,1069,1062,1061,1051,1018,
+954,865,765,667,578,496,424,366,327,308,295,273,231,170,105,53,22,11,9,7,2,
+-3,-10,-16,-26,-44,-69,-97,-125,-150,-174,-198,-222,-244,-262,-273,-281,-286,-292,-302,-314,-327,
+-338,-346,-352,-358,-366,-376,-385,-391,-394,-393,-390,-387,-381,-374,-366,-359,-354,-353,-353,-351,-348,
+-345,-347,-356,-371,-389,-409,-427,-445,-461,-475,-487,-496,-500,-501,-498,-492,-485,-476,-467,-457,-446,
+-435,-424,-414,-403,-391,-376,-359,-341,-325,-310,-298,-286,-274,-258,-240,-217,-190,-160,-127,-92,-53,
+-10,34,78,117,151,183,217,255,298,344,390,435,482,532,584,637,688,734,778,820,862,
+905,946,986,1025,1063,1101,1139,1174,1209,1244,1282,1322,1365,1407,1446,1484,1521,1560,1598,1634,1667,
+1699,1732,1766,1803,1838,1871,1905,1941,1982,2024,2064,2098,2127,2153,2181,2212,2243,2274,2301,2326,2348,
+2369,2390,2411,2434,2459,2486,2513,2540,2566,2588,2607,2622,2633,2642,2649,2655,2657,2652,2643,2634,2627,
+2624,2624,2625,2623,2620,2616,2613,2610,2606,2601,2596,2590,2585,2578,2569,2559,2550,2546,2545,2545,2544,
+2539,2530,2519,2510,2502,2496,2488,2476,2460,2443,2427,2413,2400,2383,2360,2332,2303,2276,2254,2239,2228,
+2222,2220,2219,2218,2214,2205,2191,2175,2160,2149,2145,2208,2207,2203,2196,2185,2176,2172,2177,2185,2191,
+2187,2174,2156,2144,2144,2157,2179,2202,2219,2227,2228,2226,2225,2229,2240,2254,2270,2285,2299,2317,2345,
+2384,2430,2477,2517,2546,2566,2580,2592,2601,2608,2613,2617,2626,2639,2655,2669,2676,2678,2680,2690,2712,
+2741,2769,2784,2785,2777,2771,2777,2798,2828,2861,2890,2914,2934,2952,2967,2984,3003,3029,3062,3097,3129,
+3153,3171,3186,3202,3220,3238,3252,3261,3264,3267,3270,3277,3288,3301,3316,3329,3336,3338,3333,3326,3319,
+3315,3315,3315,3313,3310,3307,3307,3310,3314,3318,3319,3318,3318,3322,3331,3340,3343,3339,3332,3329,3338,
+3358,3383,3406,3428,3452,3481,3514,3545,3576,3613,3669,3749,3840,3918,3962,3974,3979,4008,4078,4178,4279,
+4354,4395,4420,4451,4497,4550,4591,4612,4614,4611,4613,4621,4628,4630,4627,4623,4621,4618,4609,4593,4574,
+4563,4564,4575,4588,4597,4600,4601,4601,4600,4592,4576,4552,4526,4502,4485,4473,4466,4466,4475,4494,4522,
+4555,4587,4615,4638,4655,4667,4673,4675,4675,4669,4655,4627,4583,4527,4474,4439,4434,4463,4523,4604,4695,
+4786,4863,4911,4918,4880,4803,4705,4608,4529,4472,4436,4411,4391,4373,4357,4344,4330,4313,4291,4269,4250,
+4238,4232,4225,4214,4194,4168,4138,4107,4076,4046,4013,3979,3944,3909,3875,3840,3803,3763,3719,3673,3627,
+3583,3542,3506,3473,3444,3418,3394,3372,3350,3327,3303,3279,3256,3235,3220,3211,3207,3208,3211,3215,3218,
+3220,3221,3221,3218,3214,3209,3207,3210,3216,3221,3221,3214,3205,3198,3197,3199,3197,3189,3174,3156,3141,
+3130,3119,3103,3082,3058,3035,3013,2991,2966,2938,2909,2883,2862,2845,2829,2812,2796,2782,2770,2757,2740,
+2718,2690,2658,2626,2593,2561,2531,2503,2477,2450,2420,2384,2345,2304,2266,2230,2195,2163,2135,2112,2091,
+2069,2042,2010,1975,1941,1910,1879,1846,1811,1776,1746,1719,1693,1664,1630,1594,1557,1520,1481,1440,1396,
+1352,1312,1277,1244,1209,1170,1129,1088,1051,1015,981,944,906,866,826,788,751,713,673,631,588,
+546,506,465,422,377,329,282,240,202,166,129,88,45,1,-39,-81,-124,-172,-224,-274,-321,
+-361,-398,-435,-475,-520,-568,-616,-661,-702,-739,-774,-808,-842,-878,-915,-954,-996,-1040,-1086,-1133,-1178,
+-1220,-1258,-1294,-1330,-1367,-1403,-1438,-1470,-1501,-1532,-1566,-1602,-1638,-1672,-1705,-1737,-1770,-1805,-1841,-1876,-1908,
+-1938,-1968,-2000,-2034,-2071,-2108,-2143,-2174,-2199,-2220,-2239,-2260,-2283,-2308,-2335,-2362,-2388,-2412,-2434,-2455,-2473,
+-2491,-2509,-2528,-2548,-2566,-2582,-2595,-2606,-2618,-2630,-2640,-2648,-2654,-2660,-2667,-2673,-2676,-2674,-2668,-2663,-2664,
+-2671,-2680,-2688,-2690,-2687,-2683,-2682,-2685,-2690,-2696,-2699,-2699,-2697,-2694,-2691,-2689,-2690,-2690,-2689,-2685,-2677,
+-2668,-2662,-2659,-2657,-2654,-2647,-2638,-2628,-2619,-2612,-2605,-2599,-2592,-2584,-2575,-2566,-2557,-2549,-2541,-2532,-2520,
+-2506,-2490,-2474,-2458,-2442,-2425,-2407,-2389,-2372,-2355,-2337,-2319,-2301,-2286,-2271,-2256,-2237,-2215,-2191,-2168,-2148,
+-2129,-2108,-2085,-2061,-2038,-2016,-1993,-1968,-1943,-1921,-1902,-1885,-1866,-1845,-1821,-1797,-1775,-1753,-1731,-1714,-1708,
+-1717,-1735,-1753,-1759,-1750,-1733,-1716,-1705,-1696,-1683,-1663,-1642,-1626,-1617,-1611,-1601,-1587,-1571,-1559,-1554,-1548,
+-1535,-1510,-1476,-1440,-1411,-1391,-1377,-1368,-1363,-1363,-1368,-1376,-1383,-1383,-1375,-1360,-1340,-1321,-1305,-1295,-1288,
+-1283,-1277,-1271,-1267,-1266,-1266,-1263,-1255,-1241,-1224,-1207,-1191,-1170,-1145,-1115,-1088,-1067,-1056,-1049,-1042,-1032,
+-1021,-1013,-1010,-1008,-1002,-988,-966,-944,-929,-923,-923,-924,-920,-911,-896,-878,-859,-839,-819,-798,-775,
+-749,-720,-689,-662,-639,-622,-607,-590,-565,-533,-494,-453,-417,-394,-389,-399,-413,-420,-415,-410,-428,
+-481,-551,-591,-545,-387,-143,114,310,407,420,403,404,442,504,563,608,643,677,709,726,710,
+659,581,496,418,352,300,262,242,240,250,263,272,275,277,283,295,310,321,326,323,311,
+294,274,254,239,229,222,214,203,188,173,159,146,133,118,101,84,67,53,39,26,10,
+-8,-33,-61,-89,-111,-121,-119,-112,-108,-113,-130,-154,-179,-200,-218,-234,-252,-273,-300,-331,-364,
+-396,-425,-450,-473,-498,-526,-560,-594,-624,-647,-663,-675,-686,-700,-717,-735,-752,-768,-783,-798,-813,
+-829,-846,-864,-882,-897,-908,-916,-921,-928,-936,-944,-949,-951,-952,-955,-959,-964,-967,-965,-960,-955,
+-952,-950,-949,-946,-942,-937,-933,-926,-918,-908,-900,-893,-886,-879,-875,-879,-892,-905,-903,-869,-803,
+-726,-671,-664,-709,-784,-856,-902,-919,-919,-918,-923,-932,-937,-937,-937,-943,-957,-976,-997,-1015,-1030,
+-1044,-1057,-1069,-1081,-1093,-1107,-1124,-1142,-1159,-1173,-1184,-1193,-1202,-1212,-1222,-1229,-1235,-1240,-1244,-1251,-1261,
+-1275,-1292,-1310,-1325,-1333,-1333,-1328,-1324,-1328,-1344,-1368,-1396,-1419,-1435,-1445,-1455,-1466,-1480,-1493,-1504,-1512,
+-1517,-1522,-1526,-1529,-1532,-1534,-1536,-1536,-1534,-1531,-1529,-1531,-1538,-1548,-1557,-1564,-1570,-1580,-1592,-1604,-1611,
+-1610,-1604,-1598,-1596,-1596,-1594,-1585,-1567,-1548,-1532,-1525,-1523,-1524,-1522,-1518,-1513,-1510,-1508,-1505,-1501,-1494,
+-1485,-1478,-1472,-1467,-1461,-1454,-1444,-1433,-1422,-1411,-1401,-1390,-1379,-1367,-1355,-1343,-1331,-1319,-1306,-1293,-1282,
+-1273,-1266,-1260,-1252,-1243,-1232,-1222,-1211,-1199,-1186,-1173,-1160,-1150,-1143,-1137,-1131,-1123,-1114,-1107,-1102,-1101,
+-1103,-1104,-1103,-1099,-1095,-1091,-1088,-1087,-1084,-1078,-1071,-1063,-1056,-1051,-1049,-1048,-1047,-1044,-1039,-1032,-1024,
+-1017,-1011,-1009,-1007,-1005,-1002,-995,-988,-981,-975,-971,-968,-967,-966,-966,-966,-967,-967,-967,-967,-967,
+-966,-964,-961,-958,-954,-951,-949,-949,-950,-952,-953,-950,-944,-936,-928,-923,-918,-912,-904,-895,-887,
+-881,-876,-872,-866,-859,-851,-843,-833,-820,-807,-795,-787,-782,-777,-771,-762,-751,-740,-730,-717,-700,
+-677,-652,-627,-607,-593,-584,-581,-582,-584,-581,-567,-543,-514,-487,-469,-457,-446,-430,-408,-387,-374,
+-371,-372,-369,-358,-341,-325,-317,-316,-315,-308,-292,-271,-250,-235,-224,-215,-203,-185,-161,-137,-113,
+-92,-71,-51,-31,-13,0,12,24,40,59,78,94,107,121,138,160,185,207,226,244,267,
+298,333,369,401,427,450,470,489,507,527,551,579,610,641,669,697,730,766,802,834,861,
+888,919,954,989,1016,1035,1050,1066,1080,1085,1077,1067,1070,1103,1163,1233,1297,1349,1403,1479,1588,
+1722,1865,1997,2108,2192,2242,2252,2223,2162,2088,2014,1943,1870,1793,1716,1653,1612,1589,1573,1557,1540,
+1527,1519,1508,1482,1438,1385,1339,1311,1295,1279,1253,1220,1192,1177,1176,1181,1186,1190,1198,1209,1216,
+1211,1191,1164,1141,1126,1116,1102,1083,1063,1049,1040,1026,995,938,858,765,672,584,505,441,394,
+369,356,343,312,258,186,114,57,22,5,-2,-8,-13,-18,-21,-24,-33,-49,-72,-99,-126,
+-152,-178,-204,-229,-252,-270,-284,-294,-302,-310,-320,-331,-344,-357,-367,-375,-380,-386,-390,-395,-397,
+-397,-395,-391,-385,-376,-367,-359,-354,-354,-355,-354,-351,-345,-342,-347,-360,-379,-399,-415,-428,-440,
+-453,-467,-480,-491,-497,-498,-495,-489,-480,-469,-456,-443,-431,-421,-411,-401,-389,-373,-355,-337,-320,
+-307,-296,-286,-274,-260,-243,-224,-204,-182,-157,-126,-89,-47,0,46,90,128,163,196,230,267,
+307,349,392,438,488,541,596,649,698,742,784,825,867,908,948,987,1026,1065,1105,1143,1179,
+1213,1247,1283,1321,1360,1398,1434,1468,1503,1539,1575,1611,1646,1680,1717,1753,1789,1823,1855,1888,1924,
+1964,2004,2042,2074,2103,2132,2162,2196,2229,2261,2290,2316,2340,2364,2388,2413,2437,2461,2484,2508,2532,
+2557,2582,2604,2621,2634,2644,2654,2664,2672,2675,2670,2660,2651,2645,2643,2642,2639,2634,2628,2624,2622,
+2621,2618,2612,2604,2595,2587,2581,2575,2569,2563,2555,2547,2537,2525,2515,2505,2497,2488,2476,2459,2439,
+2418,2398,2381,2366,2352,2336,2318,2302,2289,2281,2275,2271,2267,2262,2259,2256,2253,2249,2242,2233,2223,
+2214,2209,2208,2252,2233,2210,2185,2164,2151,2146,2148,2151,2150,2145,2138,2132,2132,2141,2156,2176,2197,
+2217,2231,2238,2239,2239,2245,2261,2284,2309,2326,2335,2340,2350,2374,2411,2453,2492,2521,2540,2552,2563,
+2572,2582,2591,2601,2615,2633,2652,2668,2678,2681,2683,2692,2711,2736,2757,2766,2763,2755,2755,2771,2802,
+2838,2870,2892,2907,2923,2942,2967,2995,3024,3053,3082,3111,3137,3159,3176,3191,3206,3223,3238,3250,3256,
+3260,3263,3269,3278,3288,3299,3309,3317,3322,3323,3321,3316,3310,3304,3301,3299,3297,3296,3296,3297,3300,
+3304,3306,3307,3309,3315,3327,3342,3352,3353,3343,3333,3333,3348,3376,3407,3433,3455,3480,3513,3554,3597,
+3639,3683,3740,3814,3893,3959,3998,4017,4039,4088,4171,4270,4356,4409,4434,4452,4482,4525,4568,4594,4599,
+4593,4589,4591,4596,4595,4587,4578,4576,4579,4579,4570,4553,4536,4530,4536,4549,4557,4559,4557,4559,4567,
+4578,4587,4592,4594,4590,4578,4550,4507,4459,4423,4417,4443,4491,4546,4594,4631,4657,4678,4692,4701,4702,
+4699,4692,4676,4644,4593,4528,4468,4436,4451,4518,4628,4760,4892,5004,5083,5118,5104,5045,4951,4841,4734,
+4644,4573,4519,4473,4432,4395,4367,4348,4335,4322,4305,4285,4268,4257,4252,4248,4237,4215,4185,4154,4125,
+4099,4072,4040,4005,3969,3935,3902,3869,3831,3787,3742,3697,3655,3615,3575,3536,3500,3470,3446,3426,3408,
+3388,3367,3345,3323,3299,3272,3247,3226,3215,3215,3224,3236,3246,3253,3257,3261,3266,3274,3284,3297,3310,
+3319,3318,3305,3284,3263,3252,3250,3253,3253,3243,3226,3207,3191,3178,3162,3142,3119,3095,3074,3056,3035,
+3009,2978,2947,2921,2900,2883,2868,2852,2839,2828,2817,2804,2783,2754,2720,2685,2652,2621,2593,2565,2538,
+2510,2480,2446,2409,2369,2330,2293,2260,2228,2199,2173,2149,2126,2100,2070,2036,2003,1973,1945,1917,1885,
+1850,1815,1783,1756,1730,1703,1672,1638,1600,1561,1520,1477,1434,1393,1355,1319,1282,1242,1202,1163,1126,
+1091,1056,1019,980,940,899,860,823,785,746,707,666,624,583,543,503,460,413,364,317,274,
+238,204,167,126,81,36,-5,-44,-84,-129,-179,-228,-272,-311,-347,-386,-429,-476,-523,-567,-607,
+-645,-683,-720,-756,-793,-829,-868,-909,-955,-1003,-1051,-1097,-1140,-1179,-1217,-1254,-1292,-1329,-1364,-1398,-1429,
+-1460,-1492,-1525,-1558,-1591,-1622,-1653,-1686,-1720,-1754,-1788,-1820,-1851,-1882,-1916,-1951,-1989,-2027,-2063,-2095,-2123,
+-2146,-2166,-2185,-2206,-2230,-2258,-2286,-2313,-2338,-2361,-2383,-2403,-2421,-2440,-2459,-2480,-2502,-2523,-2541,-2555,-2567,
+-2578,-2590,-2601,-2610,-2618,-2625,-2631,-2637,-2639,-2638,-2634,-2632,-2635,-2644,-2653,-2659,-2659,-2655,-2652,-2653,-2658,
+-2666,-2671,-2672,-2671,-2668,-2666,-2666,-2666,-2666,-2665,-2662,-2657,-2652,-2646,-2642,-2638,-2634,-2628,-2622,-2615,-2608,
+-2602,-2596,-2589,-2582,-2575,-2567,-2558,-2547,-2537,-2528,-2520,-2511,-2500,-2485,-2470,-2454,-2439,-2424,-2407,-2390,-2372,
+-2357,-2341,-2326,-2308,-2291,-2274,-2260,-2246,-2228,-2204,-2178,-2154,-2132,-2114,-2096,-2074,-2050,-2026,-2003,-1982,-1961,
+-1938,-1915,-1894,-1873,-1855,-1836,-1818,-1798,-1777,-1755,-1733,-1717,-1713,-1722,-1741,-1758,-1765,-1757,-1740,-1722,-1708,
+-1698,-1686,-1670,-1651,-1634,-1621,-1613,-1605,-1594,-1582,-1571,-1561,-1551,-1538,-1520,-1499,-1475,-1451,-1424,-1398,-1376,
+-1362,-1361,-1369,-1381,-1389,-1389,-1381,-1368,-1355,-1342,-1331,-1323,-1318,-1315,-1313,-1313,-1311,-1307,-1299,-1288,-1275,
+-1263,-1251,-1240,-1226,-1206,-1179,-1150,-1127,-1112,-1106,-1102,-1093,-1080,-1067,-1061,-1061,-1061,-1053,-1032,-1006,-984,
+-976,-982,-991,-993,-982,-960,-936,-916,-900,-884,-865,-840,-813,-785,-757,-730,-705,-687,-674,-664,-648,
+-619,-576,-526,-481,-452,-442,-446,-453,-453,-446,-441,-451,-486,-534,-561,-525,-397,-185,57,265,385,
+413,385,359,371,423,493,554,595,625,652,673,673,639,569,476,381,299,237,192,162,148,
+146,152,159,161,159,158,161,171,184,196,204,204,197,184,166,147,131,119,111,103,91,
+75,58,40,25,10,-4,-20,-37,-54,-72,-89,-105,-122,-142,-167,-197,-227,-251,-263,-262,-255,
+-249,-251,-261,-274,-287,-298,-309,-323,-342,-365,-391,-419,-449,-478,-505,-528,-549,-572,-601,-635,-671,
+-702,-725,-739,-747,-756,-767,-782,-799,-817,-835,-852,-865,-875,-882,-892,-908,-930,-951,-966,-973,-973,
+-974,-979,-989,-998,-1004,-1006,-1007,-1011,-1015,-1019,-1019,-1014,-1007,-1001,-996,-992,-989,-989,-989,-988,-984,
+-975,-963,-950,-940,-932,-924,-919,-921,-934,-953,-963,-949,-908,-853,-810,-800,-825,-870,-908,-926,-926,
+-923,-930,-947,-964,-969,-962,-951,-950,-965,-994,-1025,-1052,-1071,-1084,-1094,-1104,-1112,-1121,-1131,-1144,-1159,
+-1175,-1189,-1201,-1210,-1219,-1228,-1237,-1245,-1251,-1255,-1260,-1267,-1279,-1296,-1315,-1334,-1349,-1354,-1352,-1343,-1335,
+-1335,-1345,-1367,-1394,-1419,-1439,-1454,-1466,-1479,-1493,-1507,-1518,-1525,-1529,-1532,-1537,-1543,-1550,-1555,-1557,-1555,
+-1552,-1550,-1550,-1553,-1558,-1563,-1568,-1575,-1585,-1600,-1615,-1624,-1623,-1612,-1600,-1594,-1597,-1604,-1608,-1601,-1582,
+-1558,-1538,-1527,-1523,-1521,-1517,-1510,-1503,-1498,-1498,-1500,-1501,-1500,-1497,-1493,-1489,-1483,-1474,-1463,-1449,-1435,
+-1421,-1408,-1396,-1384,-1372,-1361,-1352,-1343,-1333,-1321,-1308,-1295,-1284,-1275,-1269,-1262,-1254,-1246,-1237,-1227,-1216,
+-1203,-1187,-1172,-1159,-1149,-1142,-1134,-1125,-1113,-1102,-1093,-1087,-1086,-1087,-1089,-1089,-1087,-1083,-1080,-1077,-1074,
+-1070,-1065,-1059,-1053,-1049,-1045,-1043,-1040,-1036,-1031,-1026,-1021,-1016,-1011,-1006,-1001,-998,-995,-992,-988,-982,
+-976,-969,-964,-962,-961,-961,-962,-962,-961,-962,-963,-965,-966,-966,-963,-959,-954,-949,-946,-945,-946,
+-949,-952,-953,-950,-943,-936,-931,-927,-924,-919,-909,-899,-890,-885,-883,-881,-876,-869,-861,-852,-843,
+-833,-821,-808,-797,-789,-784,-779,-772,-762,-750,-735,-718,-696,-671,-643,-616,-592,-574,-564,-562,-567,
+-573,-575,-568,-553,-535,-519,-507,-497,-482,-460,-432,-407,-390,-382,-379,-374,-363,-347,-333,-325,-323,
+-321,-314,-299,-278,-259,-245,-236,-229,-217,-198,-174,-148,-125,-104,-84,-62,-39,-19,-4,7,17,
+31,48,67,83,98,112,130,153,176,196,214,233,258,291,329,367,399,425,446,463,479,
+497,518,547,581,617,649,676,701,730,763,796,823,844,864,890,922,956,984,1005,1022,1043,
+1066,1083,1089,1086,1090,1118,1176,1255,1338,1415,1485,1556,1641,1743,1863,1996,2132,2257,2346,2377,2344,
+2258,2149,2042,1949,1869,1792,1719,1655,1610,1582,1564,1547,1530,1515,1503,1489,1465,1427,1379,1335,1301,
+1276,1252,1225,1197,1176,1168,1170,1176,1180,1185,1195,1207,1216,1211,1191,1163,1138,1123,1114,1103,1085,
+1063,1042,1026,1008,979,929,858,771,680,593,519,463,430,414,404,384,343,279,204,132,76,
+39,17,2,-10,-19,-25,-28,-33,-42,-57,-78,-102,-129,-157,-186,-214,-239,-260,-278,-294,-308,
+-321,-331,-340,-349,-359,-371,-383,-393,-400,-403,-404,-402,-399,-394,-389,-382,-375,-367,-360,-354,-352,
+-352,-352,-348,-341,-334,-334,-343,-363,-386,-408,-423,-432,-439,-447,-457,-468,-478,-486,-490,-491,-486,
+-476,-461,-443,-426,-413,-404,-396,-387,-373,-356,-337,-320,-306,-296,-286,-275,-262,-247,-229,-212,-194,
+-174,-149,-119,-81,-37,9,55,97,136,173,209,246,283,320,358,399,446,498,552,606,657,
+703,747,791,835,877,917,955,991,1028,1067,1107,1146,1184,1220,1255,1290,1325,1360,1393,1426,1459,
+1492,1526,1561,1595,1630,1666,1704,1741,1777,1812,1847,1883,1921,1960,1997,2030,2060,2089,2120,2154,2188,
+2222,2252,2280,2306,2333,2360,2387,2415,2441,2464,2484,2503,2523,2546,2572,2598,2620,2637,2649,2659,2671,
+2681,2688,2689,2684,2675,2667,2660,2653,2646,2638,2634,2633,2636,2638,2636,2628,2615,2601,2590,2581,2573,
+2564,2552,2537,2519,2502,2488,2479,2473,2470,2463,2450,2431,2407,2384,2364,2349,2336,2324,2312,2304,2302,
+2305,2312,2317,2317,2310,2298,2284,2271,2263,2260,2261,2264,2267,2268,2263,2252,2247,2218,2188,2164,2150,
+2144,2142,2139,2132,2122,2114,2114,2123,2137,2151,2163,2174,2186,2201,2216,2228,2238,2249,2270,2304,2344,
+2380,2400,2401,2391,2385,2393,2415,2445,2472,2490,2500,2506,2513,2523,2536,2551,2566,2583,2602,2621,2639,
+2655,2667,2681,2697,2716,2734,2746,2749,2747,2747,2759,2784,2817,2850,2873,2886,2896,2911,2936,2971,3009,
+3044,3074,3098,3119,3138,3156,3172,3186,3200,3213,3224,3232,3238,3244,3251,3262,3274,3286,3295,3300,3303,
+3305,3307,3308,3307,3302,3295,3288,3284,3284,3286,3288,3290,3292,3294,3297,3301,3308,3319,3332,3345,3352,
+3349,3339,3332,3337,3360,3396,3432,3462,3486,3512,3549,3598,3654,3712,3769,3828,3891,3950,3996,4028,4056,
+4101,4174,4268,4359,4424,4454,4464,4477,4505,4545,4579,4595,4594,4587,4583,4582,4578,4567,4555,4552,4558,
+4567,4564,4547,4525,4514,4523,4545,4560,4556,4533,4507,4493,4499,4522,4558,4601,4647,4684,4695,4663,4587,
+4488,4406,4370,4391,4451,4524,4587,4632,4664,4690,4710,4721,4720,4711,4695,4673,4637,4584,4520,4465,4447,
+4488,4592,4741,4903,5045,5144,5191,5191,5153,5091,5017,4939,4864,4796,4730,4662,4589,4513,4442,4386,4349,
+4330,4320,4310,4295,4278,4265,4257,4251,4240,4220,4193,4164,4138,4115,4090,4059,4021,3983,3948,3916,3883,
+3845,3802,3758,3716,3679,3642,3604,3565,3529,3501,3480,3463,3445,3424,3403,3385,3369,3348,3320,3285,3251,
+3230,3227,3240,3259,3278,3291,3300,3311,3325,3346,3370,3397,3419,3429,3422,3399,3365,3335,3315,3309,3307,
+3301,3287,3267,3247,3231,3217,3201,3180,3156,3134,3115,3097,3074,3045,3014,2985,2963,2947,2933,2917,2899,
+2883,2869,2855,2837,2812,2779,2745,2712,2683,2656,2629,2600,2571,2541,2508,2473,2435,2397,2361,2327,2296,
+2267,2239,2213,2187,2159,2129,2095,2060,2028,2001,1977,1951,1921,1888,1853,1821,1793,1766,1738,1707,1673,
+1637,1597,1556,1515,1475,1437,1401,1363,1322,1280,1239,1200,1165,1130,1093,1053,1012,971,933,896,859,
+820,781,741,700,659,617,576,536,495,451,406,360,317,279,243,205,162,116,70,28,-8,
+-45,-86,-131,-178,-222,-261,-300,-342,-388,-436,-482,-522,-559,-593,-630,-668,-708,-747,-786,-827,-871,
+-918,-966,-1013,-1056,-1095,-1132,-1168,-1207,-1246,-1286,-1324,-1359,-1391,-1422,-1453,-1483,-1514,-1544,-1575,-1607,-1640,
+-1674,-1707,-1738,-1767,-1796,-1828,-1864,-1903,-1942,-1980,-2016,-2050,-2079,-2102,-2122,-2140,-2161,-2185,-2212,-2239,-2264,
+-2286,-2307,-2329,-2351,-2373,-2392,-2411,-2430,-2451,-2473,-2493,-2511,-2526,-2538,-2550,-2562,-2572,-2581,-2588,-2594,-2598,
+-2601,-2601,-2600,-2601,-2607,-2617,-2627,-2632,-2632,-2627,-2624,-2626,-2632,-2638,-2642,-2642,-2640,-2638,-2639,-2642,-2646,
+-2647,-2646,-2642,-2638,-2634,-2630,-2625,-2618,-2610,-2601,-2594,-2590,-2588,-2584,-2579,-2572,-2564,-2555,-2546,-2536,-2526,
+-2517,-2510,-2504,-2496,-2484,-2468,-2452,-2437,-2425,-2413,-2398,-2380,-2361,-2344,-2329,-2315,-2299,-2281,-2263,-2248,-2233,
+-2216,-2195,-2170,-2144,-2122,-2104,-2087,-2067,-2044,-2018,-1993,-1972,-1952,-1932,-1911,-1888,-1867,-1848,-1832,-1818,-1801,
+-1781,-1758,-1736,-1721,-1719,-1730,-1748,-1764,-1768,-1758,-1741,-1723,-1710,-1702,-1693,-1678,-1658,-1638,-1621,-1612,-1607,
+-1603,-1595,-1582,-1566,-1550,-1540,-1535,-1534,-1528,-1511,-1479,-1437,-1396,-1368,-1359,-1364,-1374,-1380,-1381,-1377,-1374,
+-1372,-1370,-1365,-1356,-1348,-1345,-1346,-1350,-1353,-1348,-1336,-1319,-1301,-1285,-1273,-1262,-1250,-1232,-1209,-1187,-1171,
+-1161,-1157,-1150,-1138,-1122,-1108,-1102,-1103,-1103,-1094,-1074,-1051,-1036,-1036,-1048,-1058,-1056,-1038,-1011,-985,-966,
+-950,-931,-905,-876,-849,-827,-810,-793,-774,-755,-737,-718,-691,-650,-597,-542,-499,-477,-472,-473,-468,
+-456,-446,-453,-485,-530,-559,-533,-427,-246,-26,174,309,360,349,322,319,352,408,462,499,521,
+542,565,583,577,531,450,352,259,185,134,100,79,66,61,59,57,53,49,48,52,60,
+70,80,87,90,88,78,62,43,25,14,8,4,-3,-16,-35,-55,-76,-94,-110,-126,-145,
+-167,-192,-217,-241,-261,-280,-300,-323,-347,-368,-379,-381,-378,-376,-380,-387,-395,-401,-408,-418,-433,
+-452,-473,-492,-511,-532,-556,-582,-607,-630,-653,-679,-710,-743,-771,-793,-806,-817,-827,-838,-852,-866,
+-883,-902,-921,-936,-944,-947,-951,-962,-980,-1002,-1018,-1025,-1023,-1021,-1023,-1030,-1039,-1044,-1046,-1048,-1052,
+-1058,-1063,-1064,-1061,-1055,-1050,-1045,-1041,-1038,-1036,-1036,-1036,-1033,-1025,-1014,-1004,-998,-995,-990,-982,-975,
+-974,-984,-997,-1003,-994,-975,-957,-953,-963,-974,-973,-955,-930,-918,-929,-956,-982,-992,-983,-967,-962,
+-977,-1010,-1049,-1082,-1104,-1118,-1129,-1138,-1148,-1155,-1161,-1167,-1175,-1186,-1200,-1213,-1225,-1237,-1249,-1260,-1268,
+-1273,-1276,-1278,-1284,-1296,-1315,-1337,-1357,-1372,-1377,-1373,-1364,-1355,-1350,-1353,-1367,-1388,-1412,-1436,-1457,-1474,
+-1490,-1505,-1518,-1529,-1535,-1538,-1541,-1546,-1555,-1564,-1572,-1574,-1573,-1570,-1569,-1570,-1572,-1573,-1572,-1572,-1579,
+-1595,-1616,-1636,-1644,-1638,-1622,-1606,-1599,-1604,-1614,-1618,-1609,-1588,-1564,-1546,-1538,-1536,-1534,-1528,-1516,-1503,
+-1494,-1489,-1489,-1491,-1494,-1495,-1497,-1496,-1492,-1483,-1470,-1454,-1437,-1420,-1405,-1391,-1378,-1367,-1359,-1352,-1345,
+-1336,-1324,-1311,-1298,-1288,-1279,-1270,-1261,-1252,-1244,-1236,-1228,-1217,-1204,-1188,-1174,-1163,-1156,-1150,-1142,-1131,
+-1118,-1105,-1095,-1089,-1085,-1083,-1081,-1079,-1076,-1073,-1069,-1064,-1059,-1054,-1050,-1046,-1044,-1042,-1041,-1038,-1034,
+-1028,-1022,-1017,-1013,-1010,-1006,-1000,-993,-986,-981,-979,-978,-976,-972,-965,-958,-954,-952,-953,-955,-956,
+-956,-957,-959,-961,-963,-963,-961,-958,-956,-953,-952,-952,-952,-953,-953,-951,-947,-940,-934,-930,-928,
+-926,-921,-912,-900,-891,-886,-885,-884,-882,-876,-869,-863,-858,-851,-841,-828,-815,-803,-794,-787,-778,
+-766,-750,-731,-711,-690,-668,-645,-622,-601,-583,-572,-566,-565,-567,-566,-561,-554,-546,-539,-533,-523,
+-505,-480,-450,-424,-406,-396,-390,-384,-373,-360,-346,-337,-331,-324,-314,-299,-281,-263,-249,-239,-229,
+-214,-195,-172,-150,-131,-115,-96,-74,-48,-24,-6,5,14,26,43,62,82,101,121,142,166,
+187,205,220,237,260,291,326,360,389,413,433,450,468,487,511,541,576,610,639,662,682,
+705,731,759,783,803,825,853,888,923,953,975,996,1023,1053,1078,1090,1090,1095,1125,1191,1288,
+1395,1494,1573,1634,1691,1758,1851,1977,2131,2291,2417,2474,2445,2344,2207,2072,1961,1875,1800,1728,1662,
+1608,1572,1549,1531,1513,1493,1475,1458,1437,1408,1373,1336,1301,1269,1236,1202,1173,1154,1149,1156,1165,
+1172,1177,1183,1192,1198,1194,1179,1156,1134,1120,1112,1103,1088,1067,1045,1026,1007,981,937,872,789,
+699,613,542,493,465,451,437,409,361,295,224,159,108,69,40,16,-2,-15,-24,-30,-39,
+-52,-70,-90,-112,-137,-164,-192,-219,-241,-261,-278,-297,-316,-332,-344,-352,-358,-366,-377,-390,-402,
+-412,-417,-417,-413,-406,-397,-388,-379,-371,-365,-360,-357,-356,-354,-349,-341,-330,-322,-322,-334,-354,
+-378,-399,-414,-423,-431,-439,-448,-457,-464,-471,-475,-477,-473,-460,-441,-418,-398,-384,-377,-372,-366,
+-355,-340,-325,-311,-298,-286,-274,-259,-243,-227,-211,-194,-176,-155,-130,-99,-63,-23,19,62,104,
+144,183,222,259,294,327,362,403,451,505,560,611,658,703,748,795,843,889,929,966,1000,
+1036,1074,1112,1150,1186,1222,1257,1292,1327,1359,1391,1423,1456,1490,1523,1556,1588,1622,1658,1695,1733,
+1770,1807,1846,1886,1927,1964,1998,2028,2056,2085,2118,2153,2187,2218,2247,2274,2301,2329,2358,2388,2417,
+2444,2469,2489,2506,2523,2544,2570,2599,2626,2647,2662,2674,2684,2693,2700,2704,2702,2696,2687,2676,2664,
+2654,2647,2646,2650,2657,2662,2659,2648,2630,2609,2588,2569,2551,2533,2516,2500,2485,2473,2464,2460,2458,
+2457,2452,2442,2426,2407,2388,2371,2358,2346,2336,2328,2323,2323,2328,2333,2335,2330,2319,2302,2284,2268,
+2260,2259,2265,2275,2282,2281,2270,2247,2228,2204,2185,2173,2170,2171,2168,2158,2140,2121,2111,2114,2129,
+2147,2161,2167,2171,2177,2190,2207,2223,2239,2260,2293,2340,2391,2433,2454,2454,2443,2435,2438,2451,2464,
+2470,2468,2462,2460,2465,2477,2493,2511,2529,2547,2565,2582,2599,2617,2638,2663,2689,2711,2725,2730,2730,
+2732,2740,2760,2788,2820,2847,2866,2877,2888,2906,2935,2974,3015,3052,3081,3101,3115,3127,3139,3152,3165,
+3177,3188,3198,3207,3214,3223,3234,3248,3264,3277,3285,3288,3288,3288,3290,3294,3295,3292,3285,3278,3275,
+3278,3283,3287,3288,3288,3290,3296,3306,3318,3329,3337,3343,3345,3343,3340,3341,3353,3381,3418,3458,3492,
+3520,3551,3592,3647,3715,3786,3856,3918,3969,4006,4032,4055,4092,4156,4245,4343,4424,4470,4485,4487,4498,
+4526,4560,4586,4595,4591,4583,4577,4570,4561,4555,4561,4582,4607,4615,4593,4548,4506,4495,4522,4565,4589,
+4575,4526,4469,4430,4424,4449,4498,4564,4640,4709,4742,4715,4626,4503,4394,4341,4356,4420,4500,4568,4617,
+4655,4687,4714,4729,4727,4711,4688,4660,4622,4571,4512,4466,4459,4514,4631,4787,4946,5069,5136,5149,5126,
+5089,5057,5035,5020,5001,4969,4915,4838,4741,4631,4523,4432,4369,4334,4319,4310,4299,4284,4268,4256,4248,
+4238,4221,4198,4173,4150,4128,4103,4070,4031,3991,3955,3923,3893,3857,3817,3775,3735,3700,3666,3630,3595,
+3564,3540,3521,3501,3477,3451,3430,3417,3410,3398,3372,3334,3292,3262,3253,3264,3287,3312,3334,3354,3376,
+3402,3432,3464,3494,3517,3526,3518,3490,3453,3415,3386,3368,3354,3339,3318,3296,3277,3262,3249,3233,3213,
+3192,3173,3154,3133,3106,3074,3044,3021,3008,2999,2989,2973,2953,2932,2912,2890,2865,2834,2801,2770,2743,
+2719,2693,2665,2633,2601,2568,2535,2501,2465,2430,2397,2367,2338,2309,2279,2249,2220,2191,2158,2124,2089,
+2058,2030,2005,1978,1948,1916,1884,1854,1826,1799,1770,1738,1703,1666,1628,1588,1549,1511,1476,1440,1403,
+1363,1321,1281,1243,1207,1168,1127,1084,1042,1003,967,931,892,851,810,771,731,690,647,604,563,
+524,485,446,404,362,321,283,243,200,154,107,65,28,-5,-42,-83,-127,-170,-213,-254,-297,
+-343,-390,-434,-473,-508,-542,-578,-618,-660,-702,-745,-788,-832,-879,-925,-968,-1007,-1043,-1078,-1115,-1153,
+-1194,-1236,-1275,-1312,-1346,-1378,-1408,-1438,-1468,-1498,-1530,-1563,-1598,-1631,-1662,-1690,-1717,-1747,-1781,-1819,-1859,
+-1897,-1935,-1970,-2004,-2033,-2058,-2078,-2096,-2117,-2141,-2168,-2193,-2215,-2234,-2254,-2278,-2304,-2329,-2351,-2369,-2386,
+-2404,-2426,-2448,-2469,-2486,-2500,-2512,-2524,-2535,-2545,-2553,-2559,-2562,-2565,-2565,-2567,-2570,-2577,-2587,-2596,-2602,
+-2603,-2600,-2599,-2601,-2606,-2612,-2616,-2616,-2614,-2614,-2617,-2623,-2628,-2629,-2627,-2622,-2618,-2615,-2612,-2606,-2598,
+-2587,-2577,-2572,-2570,-2570,-2568,-2561,-2552,-2542,-2533,-2524,-2515,-2506,-2499,-2495,-2492,-2487,-2474,-2456,-2437,-2422,
+-2412,-2404,-2391,-2372,-2350,-2330,-2314,-2302,-2288,-2270,-2250,-2231,-2215,-2200,-2182,-2159,-2134,-2112,-2093,-2077,-2060,
+-2037,-2011,-1985,-1963,-1944,-1927,-1909,-1888,-1867,-1848,-1832,-1818,-1801,-1779,-1753,-1730,-1717,-1717,-1731,-1751,-1767,
+-1771,-1762,-1744,-1727,-1714,-1706,-1697,-1681,-1658,-1634,-1617,-1610,-1612,-1616,-1613,-1599,-1576,-1556,-1547,-1554,-1569,
+-1579,-1568,-1532,-1478,-1423,-1381,-1360,-1354,-1353,-1351,-1348,-1348,-1356,-1367,-1376,-1378,-1372,-1364,-1362,-1367,-1378,
+-1386,-1386,-1376,-1358,-1337,-1317,-1300,-1284,-1269,-1252,-1235,-1221,-1210,-1202,-1195,-1185,-1171,-1156,-1145,-1140,-1140,
+-1139,-1131,-1117,-1103,-1098,-1102,-1111,-1114,-1103,-1081,-1056,-1034,-1018,-1000,-976,-946,-917,-896,-884,-877,-866,
+-845,-817,-786,-752,-713,-664,-610,-559,-524,-507,-502,-496,-482,-466,-463,-486,-529,-566,-560,-485,-338,
+-148,35,170,237,248,240,245,280,335,384,412,418,416,422,436,445,428,377,298,211,134,
+78,40,16,-1,-14,-24,-31,-36,-41,-43,-42,-36,-29,-23,-19,-16,-15,-17,-26,-43,-64,
+-83,-95,-98,-97,-100,-109,-127,-148,-171,-190,-207,-224,-244,-270,-302,-336,-367,-392,-411,-426,-442,
+-459,-475,-486,-492,-496,-501,-510,-519,-527,-533,-539,-549,-564,-581,-596,-607,-615,-627,-645,-668,-693,
+-716,-739,-763,-789,-816,-840,-860,-875,-890,-904,-918,-929,-939,-950,-965,-984,-1001,-1013,-1016,-1017,-1021,
+-1031,-1047,-1061,-1069,-1071,-1070,-1071,-1074,-1077,-1077,-1076,-1077,-1083,-1092,-1100,-1105,-1105,-1104,-1102,-1100,-1096,
+-1090,-1086,-1084,-1083,-1082,-1077,-1069,-1063,-1061,-1062,-1059,-1050,-1035,-1023,-1021,-1029,-1042,-1050,-1053,-1054,-1057,
+-1060,-1055,-1033,-996,-958,-939,-948,-978,-1009,-1023,-1015,-998,-990,-1003,-1034,-1072,-1104,-1125,-1138,-1150,-1164,
+-1179,-1191,-1197,-1199,-1201,-1206,-1217,-1230,-1245,-1259,-1272,-1285,-1295,-1301,-1303,-1304,-1307,-1317,-1334,-1355,-1375,
+-1388,-1393,-1392,-1388,-1383,-1378,-1377,-1381,-1393,-1412,-1435,-1459,-1480,-1498,-1514,-1528,-1540,-1548,-1553,-1557,-1563,
+-1572,-1583,-1592,-1596,-1596,-1593,-1593,-1593,-1593,-1589,-1582,-1578,-1583,-1601,-1626,-1649,-1658,-1652,-1635,-1619,-1613,
+-1615,-1620,-1619,-1607,-1589,-1572,-1562,-1561,-1564,-1563,-1555,-1540,-1522,-1506,-1494,-1487,-1484,-1484,-1485,-1487,-1489,
+-1487,-1481,-1470,-1455,-1440,-1424,-1409,-1395,-1382,-1372,-1364,-1357,-1348,-1336,-1322,-1308,-1297,-1287,-1278,-1268,-1256,
+-1245,-1234,-1227,-1220,-1212,-1201,-1189,-1178,-1171,-1167,-1162,-1154,-1144,-1132,-1121,-1113,-1107,-1101,-1094,-1087,-1081,
+-1075,-1071,-1065,-1059,-1052,-1046,-1041,-1039,-1038,-1037,-1035,-1031,-1026,-1019,-1013,-1008,-1005,-1002,-997,-990,-981,
+-972,-966,-965,-966,-967,-965,-958,-951,-945,-943,-945,-948,-951,-952,-953,-955,-957,-958,-959,-958,-957,
+-958,-959,-960,-960,-959,-958,-956,-953,-949,-942,-936,-931,-928,-925,-921,-913,-902,-892,-886,-884,-884,
+-883,-880,-875,-872,-868,-864,-856,-845,-830,-817,-805,-794,-782,-767,-748,-728,-707,-689,-674,-659,-645,
+-629,-615,-601,-590,-580,-571,-563,-555,-550,-548,-547,-544,-535,-518,-495,-470,-447,-429,-416,-407,-398,
+-388,-377,-365,-354,-343,-331,-317,-301,-283,-266,-250,-236,-221,-203,-183,-162,-144,-130,-118,-101,-79,
+-51,-24,-4,8,17,27,42,62,84,105,127,149,172,192,208,222,237,258,285,316,345,
+370,392,413,434,456,479,503,530,559,587,613,634,655,678,704,730,753,774,799,830,866,
+901,929,951,975,1005,1037,1060,1069,1067,1075,1113,1191,1299,1415,1517,1596,1655,1707,1768,1852,1969,
+2115,2273,2406,2478,2466,2376,2243,2104,1985,1890,1807,1727,1650,1585,1540,1514,1497,1481,1461,1441,1422,
+1404,1383,1357,1327,1295,1261,1226,1190,1160,1142,1139,1147,1158,1165,1167,1168,1171,1176,1177,1172,1159,
+1144,1130,1119,1108,1095,1077,1059,1041,1023,997,956,894,815,727,643,575,530,504,487,464,428,
+376,315,254,198,148,103,63,29,4,-11,-20,-29,-42,-61,-83,-104,-124,-145,-167,-191,-214,
+-234,-252,-271,-292,-314,-332,-346,-354,-361,-368,-379,-392,-404,-414,-420,-422,-420,-413,-405,-395,-386,
+-379,-374,-371,-368,-366,-361,-353,-340,-327,-316,-314,-322,-338,-356,-372,-385,-395,-406,-419,-430,-439,
+-445,-448,-450,-448,-441,-425,-403,-378,-358,-346,-341,-339,-336,-329,-320,-310,-300,-289,-275,-258,-240,
+-222,-206,-190,-172,-151,-126,-99,-68,-34,2,41,80,121,161,201,240,274,305,334,367,407,
+457,512,567,618,662,705,749,797,846,893,935,973,1011,1048,1086,1122,1156,1189,1222,1257,1292,
+1327,1361,1393,1424,1457,1490,1522,1553,1584,1617,1652,1690,1728,1767,1805,1845,1887,1928,1965,1998,2028,
+2057,2088,2121,2156,2188,2218,2246,2273,2300,2329,2358,2388,2417,2446,2473,2496,2516,2534,2553,2576,2602,
+2629,2653,2673,2688,2699,2707,2713,2717,2716,2713,2706,2696,2686,2678,2674,2675,2679,2683,2683,2676,2662,
+2642,2618,2592,2564,2536,2513,2498,2491,2490,2492,2493,2489,2482,2474,2464,2454,2442,2429,2416,2402,2389,
+2377,2367,2359,2352,2347,2340,2333,2324,2313,2301,2288,2276,2267,2262,2263,2268,2272,2273,2266,2251,2228,
+2234,2221,2212,2206,2202,2197,2188,2172,2151,2133,2124,2128,2141,2157,2168,2173,2177,2188,2205,2225,2242,
+2257,2277,2309,2354,2405,2446,2471,2480,2485,2493,2506,2515,2510,2490,2464,2444,2438,2446,2461,2477,2493,
+2510,2528,2547,2563,2575,2589,2608,2634,2663,2687,2701,2705,2704,2706,2718,2741,2771,2802,2830,2853,2870,
+2887,2908,2936,2971,3010,3046,3073,3091,3101,3109,3116,3126,3138,3151,3164,3176,3188,3199,3209,3221,3234,
+3248,3262,3271,3274,3274,3274,3276,3279,3280,3278,3272,3269,3271,3279,3288,3293,3292,3289,3291,3301,3317,
+3332,3341,3344,3345,3346,3350,3356,3365,3381,3406,3441,3481,3522,3559,3597,3643,3702,3775,3855,3930,3991,
+4031,4051,4062,4081,4124,4198,4292,4384,4452,4486,4496,4501,4515,4541,4567,4582,4583,4575,4563,4550,4536,
+4530,4542,4582,4641,4688,4692,4639,4552,4479,4459,4496,4558,4595,4581,4521,4447,4395,4376,4389,4423,4475,
+4538,4602,4640,4626,4557,4455,4365,4326,4347,4409,4483,4545,4591,4630,4668,4700,4719,4719,4702,4677,4647,
+4611,4564,4510,4465,4455,4498,4595,4723,4850,4943,4989,4993,4980,4975,4992,5028,5066,5087,5076,5029,4948,
+4841,4719,4596,4487,4403,4351,4325,4314,4305,4292,4277,4263,4252,4241,4226,4206,4183,4160,4137,4111,4079,
+4040,4001,3966,3937,3909,3877,3839,3798,3758,3722,3689,3656,3626,3600,3578,3557,3532,3503,3473,3452,3445,
+3445,3439,3418,3380,3337,3304,3293,3302,3325,3355,3386,3420,3457,3495,3530,3560,3584,3600,3606,3598,3576,
+3541,3503,3467,3436,3410,3386,3363,3342,3326,3311,3295,3276,3254,3234,3216,3197,3172,3140,3105,3076,3057,
+3048,3042,3032,3016,2995,2973,2950,2923,2891,2855,2822,2794,2771,2750,2723,2691,2655,2621,2589,2558,2527,
+2494,2463,2434,2407,2379,2348,2315,2281,2250,2220,2191,2159,2127,2095,2065,2036,2006,1973,1939,1908,1879,
+1853,1826,1797,1764,1729,1693,1656,1618,1579,1542,1506,1472,1436,1399,1360,1322,1285,1246,1205,1161,1117,
+1076,1039,1003,965,923,879,837,799,761,721,678,632,589,551,516,480,441,398,356,316,277,
+237,193,148,106,69,36,2,-34,-76,-121,-166,-209,-251,-295,-338,-380,-419,-455,-490,-527,-567,
+-610,-655,-701,-746,-790,-834,-877,-917,-955,-992,-1028,-1064,-1103,-1144,-1184,-1223,-1260,-1294,-1327,-1358,-1389,
+-1420,-1452,-1486,-1521,-1555,-1588,-1617,-1645,-1673,-1705,-1742,-1781,-1820,-1856,-1891,-1924,-1955,-1985,-2009,-2030,-2048,
+-2069,-2094,-2120,-2145,-2167,-2186,-2205,-2229,-2257,-2284,-2308,-2327,-2345,-2364,-2386,-2409,-2430,-2446,-2459,-2472,-2485,
+-2499,-2511,-2521,-2527,-2530,-2532,-2533,-2535,-2540,-2547,-2557,-2566,-2573,-2576,-2576,-2576,-2578,-2582,-2588,-2591,-2593,
+-2593,-2595,-2599,-2604,-2608,-2609,-2605,-2600,-2596,-2593,-2591,-2586,-2578,-2568,-2560,-2556,-2556,-2556,-2552,-2543,-2532,
+-2522,-2514,-2507,-2499,-2490,-2483,-2481,-2481,-2477,-2466,-2446,-2423,-2405,-2394,-2387,-2375,-2357,-2333,-2312,-2297,-2286,
+-2275,-2258,-2237,-2215,-2197,-2183,-2168,-2148,-2125,-2101,-2081,-2065,-2048,-2028,-2003,-1978,-1955,-1938,-1922,-1905,-1886,
+-1866,-1846,-1830,-1813,-1794,-1771,-1744,-1721,-1708,-1710,-1725,-1747,-1766,-1773,-1767,-1751,-1733,-1719,-1707,-1696,-1679,
+-1656,-1633,-1618,-1615,-1623,-1634,-1634,-1619,-1593,-1570,-1561,-1572,-1595,-1612,-1605,-1569,-1512,-1452,-1403,-1370,-1349,
+-1330,-1312,-1299,-1296,-1306,-1325,-1343,-1353,-1356,-1358,-1365,-1379,-1398,-1412,-1417,-1411,-1397,-1378,-1358,-1338,-1317,
+-1298,-1281,-1267,-1255,-1246,-1236,-1226,-1214,-1203,-1193,-1188,-1186,-1185,-1182,-1175,-1167,-1162,-1160,-1161,-1160,-1151,
+-1133,-1111,-1089,-1072,-1057,-1039,-1016,-991,-971,-960,-953,-943,-923,-890,-849,-806,-763,-719,-672,-626,-589,
+-566,-556,-551,-542,-528,-521,-532,-564,-599,-608,-562,-452,-297,-137,-10,62,87,93,112,160,229,
+296,337,347,334,317,306,300,285,251,194,127,63,14,-20,-45,-66,-83,-97,-106,-113,-117,
+-120,-119,-115,-108,-103,-101,-104,-107,-110,-115,-125,-143,-165,-185,-197,-200,-199,-199,-206,-220,-239,
+-258,-276,-293,-311,-332,-360,-394,-430,-465,-496,-520,-539,-555,-571,-586,-597,-606,-614,-625,-637,-650,
+-661,-669,-677,-686,-699,-712,-722,-728,-733,-740,-752,-769,-787,-806,-824,-844,-866,-889,-910,-928,-944,
+-961,-979,-996,-1008,-1015,-1020,-1028,-1042,-1059,-1073,-1079,-1079,-1079,-1082,-1090,-1100,-1110,-1117,-1122,-1124,-1123,
+-1119,-1112,-1107,-1107,-1114,-1125,-1135,-1142,-1146,-1148,-1150,-1150,-1146,-1139,-1133,-1131,-1133,-1136,-1135,-1129,-1122,
+-1119,-1118,-1116,-1108,-1095,-1082,-1076,-1078,-1087,-1095,-1099,-1103,-1108,-1112,-1108,-1089,-1055,-1021,-1001,-1006,-1030,
+-1057,-1070,-1065,-1049,-1040,-1048,-1072,-1102,-1126,-1140,-1147,-1158,-1175,-1198,-1218,-1231,-1236,-1237,-1241,-1248,-1260,
+-1272,-1284,-1295,-1307,-1318,-1327,-1332,-1334,-1336,-1343,-1356,-1372,-1386,-1394,-1399,-1402,-1406,-1411,-1413,-1413,-1412,
+-1415,-1426,-1445,-1467,-1487,-1505,-1520,-1534,-1549,-1562,-1571,-1578,-1585,-1594,-1606,-1617,-1624,-1625,-1623,-1622,-1621,
+-1619,-1613,-1604,-1597,-1599,-1614,-1636,-1655,-1663,-1657,-1643,-1630,-1623,-1621,-1619,-1613,-1602,-1591,-1584,-1585,-1590,
+-1594,-1590,-1579,-1563,-1544,-1527,-1512,-1500,-1490,-1483,-1478,-1476,-1474,-1472,-1467,-1461,-1453,-1443,-1431,-1418,-1405,
+-1393,-1383,-1373,-1363,-1351,-1335,-1319,-1305,-1294,-1286,-1278,-1267,-1252,-1237,-1223,-1213,-1206,-1200,-1192,-1184,-1177,
+-1173,-1171,-1167,-1161,-1152,-1143,-1136,-1132,-1128,-1121,-1112,-1101,-1092,-1084,-1078,-1071,-1062,-1053,-1046,-1041,-1038,
+-1035,-1031,-1026,-1020,-1014,-1008,-1003,-998,-995,-992,-988,-981,-973,-964,-958,-955,-956,-957,-955,-950,-943,
+-938,-938,-942,-946,-950,-951,-951,-952,-953,-954,-954,-954,-955,-956,-958,-960,-960,-959,-959,-959,-958,
+-956,-951,-944,-936,-931,-927,-923,-916,-908,-899,-892,-889,-888,-887,-885,-881,-878,-874,-869,-861,-850,
+-836,-823,-811,-800,-787,-771,-751,-730,-712,-698,-689,-682,-674,-664,-652,-637,-620,-602,-585,-571,-561,
+-556,-555,-556,-553,-546,-533,-516,-498,-479,-461,-444,-429,-418,-408,-399,-390,-377,-362,-346,-328,-310,
+-292,-273,-254,-236,-217,-197,-175,-155,-139,-126,-114,-98,-75,-47,-20,0,12,19,28,43,61,
+80,99,117,136,157,176,194,210,228,250,275,302,327,350,373,397,424,451,474,495,515,
+536,558,582,608,635,664,693,719,741,762,787,817,850,879,903,926,951,982,1010,1024,1022,
+1016,1028,1077,1164,1271,1374,1459,1529,1597,1676,1766,1865,1969,2076,2185,2282,2345,2353,2301,2205,2091,
+1980,1882,1792,1705,1623,1556,1508,1481,1463,1447,1428,1407,1387,1369,1350,1326,1298,1268,1239,1210,1182,
+1158,1143,1140,1147,1157,1163,1161,1156,1153,1157,1165,1171,1169,1159,1145,1131,1120,1110,1099,1086,1070,
+1049,1019,975,914,836,751,673,612,571,545,523,493,451,399,346,294,244,192,137,83,37,
+7,-8,-16,-25,-41,-64,-88,-110,-129,-145,-163,-183,-204,-224,-244,-265,-286,-307,-325,-339,-350,
+-360,-371,-383,-395,-404,-411,-415,-417,-416,-413,-407,-400,-394,-389,-386,-383,-380,-376,-369,-358,-343,
+-327,-314,-308,-309,-317,-327,-336,-345,-355,-369,-385,-400,-410,-415,-416,-414,-410,-401,-384,-362,-339,
+-321,-311,-307,-305,-302,-298,-292,-287,-282,-273,-260,-243,-224,-207,-190,-172,-150,-125,-96,-65,-33,
+1,37,76,116,155,194,232,268,301,330,359,390,430,478,532,585,632,675,715,757,802,
+847,891,932,972,1012,1054,1094,1130,1162,1192,1225,1260,1298,1334,1368,1399,1429,1459,1489,1519,1549,
+1579,1613,1650,1689,1729,1768,1806,1845,1885,1925,1963,1998,2030,2062,2095,2128,2162,2193,2221,2247,2273,
+2299,2326,2353,2381,2409,2439,2468,2496,2520,2542,2561,2579,2598,2619,2643,2666,2688,2706,2719,2727,2731,
+2732,2732,2730,2725,2720,2714,2711,2709,2707,2702,2693,2680,2665,2650,2633,2612,2586,2561,2543,2536,2542,
+2555,2565,2565,2553,2531,2507,2486,2471,2461,2451,2440,2425,2411,2398,2389,2383,2377,2368,2354,2338,2321,
+2307,2297,2291,2286,2283,2280,2278,2277,2274,2268,2259,2247,2234,2259,2252,2242,2229,2215,2201,2188,2174,
+2159,2148,2143,2148,2159,2171,2180,2186,2195,2211,2233,2254,2269,2279,2292,2317,2355,2400,2440,2471,2496,
+2522,2552,2577,2582,2560,2519,2478,2455,2457,2474,2493,2505,2512,2521,2537,2557,2573,2582,2586,2594,2611,
+2636,2660,2676,2681,2681,2684,2696,2719,2750,2783,2815,2843,2866,2886,2906,2931,2962,2998,3033,3061,3078,
+3088,3093,3100,3110,3123,3137,3151,3166,3180,3193,3204,3213,3223,3235,3247,3258,3264,3265,3265,3264,3265,
+3264,3261,3257,3257,3265,3279,3292,3299,3297,3292,3294,3305,3323,3339,3348,3350,3350,3356,3367,3381,3394,
+3408,3430,3463,3506,3554,3601,3646,3697,3759,3833,3914,3986,4039,4067,4076,4082,4104,4153,4228,4314,4391,
+4445,4475,4489,4503,4523,4544,4559,4562,4555,4542,4526,4506,4485,4479,4505,4570,4653,4714,4711,4636,4522,
+4428,4400,4439,4508,4554,4546,4494,4431,4386,4368,4367,4371,4378,4395,4421,4444,4445,4416,4370,4333,4329,
+4363,4418,4474,4520,4556,4593,4631,4666,4687,4689,4676,4657,4633,4603,4562,4510,4462,4437,4450,4504,4585,
+4670,4736,4775,4794,4810,4840,4891,4953,5006,5032,5019,4971,4896,4806,4707,4605,4508,4427,4370,4339,4325,
+4317,4307,4292,4277,4262,4249,4232,4212,4188,4164,4141,4116,4086,4051,4016,3985,3958,3931,3901,3864,3823,
+3782,3745,3711,3682,3654,3630,3607,3582,3555,3525,3499,3484,3480,3480,3473,3450,3413,3375,3349,3342,3354,
+3379,3411,3450,3496,3546,3593,3631,3656,3669,3676,3678,3673,3659,3634,3601,3564,3529,3498,3472,3452,3436,
+3421,3403,3379,3351,3322,3297,3276,3253,3224,3187,3149,3117,3095,3082,3069,3053,3032,3010,2991,2970,2944,
+2912,2875,2843,2817,2796,2773,2742,2706,2668,2635,2607,2580,2552,2523,2495,2470,2446,2419,2386,2348,2311,
+2278,2251,2225,2197,2166,2134,2103,2072,2040,2005,1969,1935,1904,1876,1848,1818,1786,1752,1718,1683,1647,
+1609,1571,1535,1500,1466,1431,1394,1357,1319,1280,1239,1195,1153,1114,1078,1041,1001,956,910,867,829,
+794,755,712,667,624,586,551,515,473,428,383,342,306,269,229,187,145,108,76,45,11,
+-30,-75,-122,-166,-207,-248,-289,-330,-370,-407,-443,-480,-519,-563,-609,-656,-701,-744,-785,-826,-865,
+-904,-943,-981,-1019,-1057,-1097,-1137,-1176,-1211,-1245,-1276,-1308,-1341,-1374,-1408,-1443,-1477,-1511,-1543,-1573,-1602,
+-1633,-1668,-1705,-1744,-1781,-1815,-1846,-1877,-1907,-1936,-1962,-1983,-2003,-2024,-2048,-2075,-2101,-2124,-2144,-2163,-2185,
+-2210,-2235,-2258,-2280,-2302,-2325,-2350,-2373,-2392,-2405,-2416,-2428,-2444,-2461,-2478,-2490,-2496,-2499,-2500,-2501,-2505,
+-2512,-2521,-2532,-2541,-2549,-2554,-2556,-2557,-2558,-2561,-2565,-2569,-2571,-2573,-2576,-2581,-2586,-2589,-2589,-2586,-2581,
+-2577,-2575,-2573,-2569,-2562,-2553,-2547,-2544,-2544,-2542,-2536,-2525,-2514,-2505,-2499,-2495,-2487,-2478,-2470,-2466,-2466,
+-2463,-2453,-2433,-2409,-2388,-2375,-2367,-2356,-2339,-2316,-2295,-2280,-2270,-2261,-2246,-2225,-2203,-2184,-2170,-2156,-2139,
+-2118,-2094,-2072,-2053,-2036,-2017,-1995,-1972,-1950,-1932,-1916,-1899,-1879,-1858,-1838,-1821,-1805,-1787,-1765,-1741,-1719,
+-1705,-1705,-1719,-1739,-1759,-1770,-1768,-1755,-1736,-1719,-1706,-1694,-1680,-1662,-1643,-1630,-1629,-1637,-1647,-1648,-1633,
+-1607,-1583,-1574,-1584,-1605,-1621,-1615,-1583,-1533,-1478,-1430,-1392,-1358,-1323,-1289,-1261,-1248,-1253,-1269,-1289,-1306,
+-1322,-1340,-1363,-1391,-1416,-1433,-1438,-1433,-1423,-1411,-1397,-1382,-1364,-1345,-1327,-1312,-1300,-1288,-1275,-1262,-1252,
+-1245,-1242,-1242,-1242,-1239,-1234,-1227,-1221,-1217,-1212,-1204,-1192,-1174,-1154,-1134,-1116,-1100,-1084,-1067,-1053,-1043,
+-1038,-1032,-1020,-995,-956,-909,-861,-815,-771,-727,-685,-649,-626,-616,-614,-611,-605,-601,-611,-640,-677,
+-698,-677,-600,-476,-338,-218,-139,-100,-79,-50,3,78,158,221,253,256,241,219,196,167,126,
+72,14,-37,-75,-98,-114,-130,-148,-164,-176,-181,-183,-185,-186,-184,-180,-174,-171,-174,-181,-188,
+-194,-199,-207,-221,-239,-257,-269,-275,-276,-278,-284,-293,-304,-316,-329,-345,-366,-391,-421,-454,-489,
+-526,-564,-600,-634,-664,-688,-705,-716,-722,-728,-737,-751,-767,-783,-795,-805,-814,-824,-834,-843,-850,
+-855,-861,-869,-877,-886,-894,-905,-920,-939,-960,-978,-993,-1007,-1023,-1042,-1062,-1077,-1086,-1090,-1094,-1102,
+-1114,-1126,-1134,-1136,-1135,-1135,-1138,-1146,-1156,-1165,-1173,-1177,-1174,-1167,-1156,-1148,-1145,-1150,-1158,-1167,-1174,
+-1178,-1183,-1187,-1188,-1185,-1180,-1176,-1177,-1183,-1189,-1190,-1185,-1176,-1169,-1166,-1164,-1160,-1153,-1145,-1140,-1139,
+-1141,-1142,-1140,-1139,-1141,-1147,-1149,-1142,-1123,-1099,-1083,-1083,-1098,-1117,-1128,-1125,-1113,-1105,-1109,-1124,-1143,
+-1157,-1162,-1163,-1168,-1184,-1209,-1235,-1255,-1267,-1273,-1279,-1287,-1296,-1305,-1312,-1320,-1329,-1341,-1354,-1362,-1365,
+-1367,-1370,-1378,-1387,-1395,-1399,-1401,-1406,-1416,-1431,-1443,-1449,-1449,-1449,-1455,-1468,-1485,-1500,-1513,-1524,-1537,
+-1553,-1569,-1584,-1594,-1602,-1612,-1624,-1637,-1646,-1650,-1650,-1648,-1647,-1645,-1641,-1634,-1629,-1630,-1638,-1651,-1660,
+-1662,-1655,-1643,-1633,-1627,-1622,-1616,-1608,-1601,-1599,-1602,-1609,-1614,-1612,-1603,-1588,-1572,-1557,-1544,-1532,-1520,
+-1507,-1495,-1485,-1476,-1469,-1462,-1457,-1453,-1449,-1445,-1437,-1426,-1413,-1400,-1388,-1378,-1367,-1355,-1339,-1323,-1310,
+-1300,-1292,-1284,-1272,-1256,-1238,-1222,-1208,-1198,-1188,-1180,-1172,-1166,-1163,-1161,-1157,-1152,-1145,-1139,-1136,-1135,
+-1134,-1129,-1120,-1111,-1102,-1094,-1086,-1077,-1067,-1057,-1049,-1044,-1039,-1034,-1027,-1018,-1009,-1002,-997,-994,-992,
+-989,-986,-982,-978,-971,-964,-958,-954,-952,-951,-948,-944,-940,-937,-938,-942,-946,-949,-950,-950,-950,
+-951,-953,-955,-955,-955,-954,-954,-954,-954,-954,-955,-958,-961,-963,-960,-953,-944,-937,-931,-928,-924,
+-919,-913,-907,-902,-899,-896,-893,-889,-885,-879,-872,-862,-850,-837,-826,-815,-805,-793,-777,-758,-738,
+-722,-712,-707,-705,-702,-695,-682,-664,-644,-622,-603,-588,-579,-576,-576,-575,-571,-564,-553,-541,-528,
+-512,-493,-473,-455,-442,-433,-426,-417,-404,-386,-367,-347,-326,-306,-285,-264,-243,-222,-199,-177,-156,
+-138,-123,-109,-92,-69,-43,-19,-1,9,16,25,38,54,71,85,100,115,134,154,175,195,
+217,241,266,291,314,337,362,391,421,448,470,486,500,514,534,559,589,621,654,683,707,
+727,748,771,799,827,850,870,892,919,948,967,967,951,939,960,1026,1126,1231,1315,1376,1434,
+1517,1634,1770,1895,1984,2038,2074,2107,2140,2158,2144,2093,2013,1920,1830,1746,1671,1604,1550,1511,1483,
+1459,1434,1407,1380,1356,1336,1314,1289,1260,1233,1210,1192,1174,1158,1146,1142,1148,1157,1162,1157,1147,
+1140,1141,1152,1163,1168,1162,1149,1138,1133,1132,1132,1124,1107,1080,1042,992,929,853,773,700,645,
+609,584,558,524,479,429,382,338,293,239,177,112,57,20,1,-7,-18,-35,-59,-85,-106,
+-124,-139,-155,-174,-195,-216,-237,-257,-278,-296,-312,-326,-340,-355,-371,-385,-396,-402,-404,-405,-406,
+-407,-405,-402,-399,-396,-394,-392,-390,-386,-380,-371,-359,-342,-323,-306,-294,-289,-290,-295,-300,-307,
+-316,-330,-347,-362,-372,-377,-379,-378,-375,-366,-351,-331,-310,-293,-283,-279,-277,-273,-268,-263,-259,
+-254,-247,-235,-220,-204,-188,-170,-149,-124,-95,-64,-33,0,35,75,117,158,197,233,267,302,
+336,369,401,434,471,514,560,606,649,689,729,770,813,854,893,930,968,1008,1051,1092,1129,
+1162,1195,1230,1269,1310,1348,1382,1410,1437,1465,1493,1522,1552,1583,1617,1654,1694,1735,1774,1812,1850,
+1887,1925,1962,1998,2032,2066,2099,2132,2164,2194,2220,2244,2267,2289,2313,2338,2364,2392,2420,2450,2479,
+2509,2536,2558,2575,2589,2604,2624,2650,2679,2705,2726,2739,2745,2749,2752,2753,2751,2746,2739,2732,2725,
+2718,2708,2697,2686,2677,2671,2666,2657,2644,2630,2620,2619,2627,2637,2639,2627,2600,2565,2530,2503,2486,
+2475,2466,2454,2438,2421,2409,2403,2401,2399,2393,2380,2363,2346,2333,2324,2318,2312,2306,2300,2294,2287,
+2281,2274,2268,2263,2259,2277,2270,2257,2237,2218,2202,2193,2186,2180,2175,2173,2177,2186,2195,2200,2204,
+2211,2224,2244,2264,2278,2287,2300,2322,2357,2398,2435,2468,2501,2539,2580,2609,2609,2577,2528,2489,2480,
+2504,2541,2570,2579,2574,2570,2577,2593,2608,2611,2605,2600,2606,2625,2650,2671,2681,2685,2690,2702,2724,
+2753,2786,2817,2845,2867,2884,2901,2923,2953,2988,3024,3052,3069,3077,3084,3093,3107,3122,3137,3150,3164,
+3178,3192,3203,3211,3218,3227,3237,3247,3254,3257,3257,3256,3255,3253,3249,3245,3246,3256,3273,3291,3301,
+3301,3297,3297,3308,3324,3339,3348,3352,3356,3365,3381,3398,3414,3431,3455,3492,3540,3593,3645,3694,3749,
+3815,3891,3968,4031,4068,4082,4085,4097,4130,4187,4258,4326,4381,4419,4445,4470,4496,4521,4537,4540,4532,
+4520,4508,4492,4468,4440,4426,4445,4504,4581,4634,4626,4550,4442,4357,4334,4373,4436,4478,4476,4443,4407,
+4389,4386,4382,4364,4332,4302,4287,4288,4297,4305,4313,4327,4356,4394,4433,4465,4490,4516,4549,4586,4619,
+4638,4641,4636,4627,4615,4595,4560,4513,4463,4424,4410,4424,4460,4506,4550,4587,4618,4650,4690,4738,4787,
+4821,4828,4805,4760,4706,4651,4596,4540,4480,4424,4380,4352,4339,4332,4322,4307,4288,4270,4252,4234,4213,
+4190,4166,4143,4119,4093,4064,4034,4005,3979,3953,3922,3885,3844,3803,3766,3734,3706,3679,3652,3625,3598,
+3572,3550,3536,3529,3528,3522,3505,3474,3437,3406,3391,3395,3413,3442,3477,3522,3576,3635,3687,3725,3744,
+3750,3750,3749,3749,3744,3731,3709,3679,3648,3620,3598,3581,3568,3551,3527,3493,3453,3415,3382,3353,3323,
+3286,3242,3199,3164,3138,3117,3093,3065,3035,3010,2991,2975,2954,2926,2894,2865,2841,2820,2794,2759,2720,
+2682,2653,2630,2609,2584,2556,2529,2505,2482,2454,2419,2379,2340,2309,2283,2260,2232,2201,2168,2137,2108,
+2079,2045,2009,1971,1936,1903,1871,1839,1806,1773,1741,1708,1674,1638,1601,1564,1529,1495,1460,1423,1385,
+1346,1307,1267,1227,1187,1149,1112,1074,1033,988,943,901,863,827,789,747,704,664,627,592,553,
+509,459,411,369,333,298,262,222,182,146,115,85,51,12,-32,-78,-122,-164,-204,-245,-286,
+-327,-365,-402,-440,-480,-523,-569,-614,-656,-696,-734,-773,-814,-854,-893,-931,-969,-1007,-1048,-1090,-1130,
+-1166,-1198,-1229,-1260,-1294,-1329,-1365,-1401,-1434,-1466,-1498,-1530,-1562,-1596,-1632,-1669,-1705,-1739,-1770,-1800,-1830,
+-1861,-1891,-1919,-1943,-1964,-1986,-2009,-2035,-2061,-2086,-2108,-2129,-2149,-2169,-2190,-2212,-2235,-2261,-2289,-2316,-2338,
+-2353,-2363,-2372,-2385,-2404,-2426,-2446,-2459,-2466,-2467,-2467,-2470,-2476,-2486,-2497,-2509,-2520,-2528,-2534,-2537,-2539,
+-2540,-2542,-2545,-2548,-2551,-2555,-2559,-2564,-2569,-2572,-2572,-2570,-2566,-2562,-2560,-2558,-2553,-2546,-2538,-2532,-2529,
+-2529,-2526,-2520,-2509,-2498,-2490,-2485,-2483,-2477,-2468,-2459,-2452,-2449,-2446,-2436,-2418,-2396,-2376,-2362,-2353,-2342,
+-2326,-2304,-2283,-2267,-2255,-2245,-2231,-2212,-2191,-2173,-2159,-2146,-2130,-2110,-2087,-2065,-2044,-2026,-2007,-1986,-1965,
+-1946,-1929,-1912,-1893,-1872,-1850,-1829,-1812,-1797,-1781,-1764,-1743,-1723,-1709,-1706,-1714,-1732,-1751,-1765,-1766,-1755,
+-1736,-1718,-1705,-1696,-1688,-1677,-1662,-1649,-1644,-1646,-1651,-1649,-1635,-1611,-1589,-1579,-1586,-1602,-1613,-1606,-1579,
+-1537,-1493,-1453,-1416,-1377,-1335,-1291,-1255,-1233,-1227,-1234,-1249,-1268,-1292,-1324,-1363,-1401,-1431,-1446,-1446,-1439,
+-1431,-1427,-1425,-1421,-1412,-1398,-1382,-1365,-1350,-1335,-1321,-1310,-1303,-1300,-1301,-1302,-1299,-1294,-1286,-1279,-1271,
+-1262,-1249,-1232,-1213,-1195,-1180,-1168,-1154,-1137,-1118,-1104,-1099,-1102,-1104,-1096,-1069,-1026,-975,-926,-884,-846,
+-804,-759,-716,-684,-669,-667,-668,-665,-662,-670,-701,-749,-795,-810,-773,-684,-568,-454,-366,-306,-262,
+-214,-150,-72,6,69,108,123,119,107,87,59,19,-33,-90,-141,-177,-196,-204,-209,-219,-232,
+-244,-249,-249,-247,-247,-248,-248,-245,-242,-241,-245,-252,-260,-265,-266,-268,-275,-285,-297,-307,-313,
+-318,-324,-329,-332,-333,-333,-338,-352,-376,-407,-440,-473,-508,-548,-597,-652,-709,-761,-800,-823,-831,
+-832,-832,-837,-850,-869,-889,-906,-919,-928,-937,-945,-953,-961,-968,-974,-979,-981,-981,-982,-987,-997,
+-1014,-1032,-1049,-1060,-1069,-1080,-1095,-1114,-1132,-1146,-1154,-1158,-1163,-1170,-1178,-1185,-1189,-1191,-1193,-1195,-1200,
+-1207,-1216,-1223,-1227,-1226,-1220,-1210,-1201,-1195,-1194,-1196,-1198,-1201,-1205,-1210,-1215,-1219,-1220,-1219,-1219,-1223,
+-1230,-1236,-1237,-1233,-1226,-1221,-1219,-1219,-1218,-1213,-1206,-1199,-1196,-1194,-1191,-1187,-1184,-1185,-1188,-1192,-1190,
+-1180,-1166,-1154,-1151,-1159,-1172,-1182,-1184,-1179,-1174,-1174,-1182,-1193,-1199,-1200,-1197,-1197,-1207,-1226,-1249,-1270,
+-1286,-1296,-1305,-1315,-1325,-1334,-1341,-1349,-1360,-1374,-1388,-1397,-1399,-1396,-1394,-1397,-1402,-1408,-1411,-1412,-1417,
+-1429,-1447,-1465,-1477,-1482,-1484,-1488,-1498,-1511,-1521,-1528,-1534,-1542,-1556,-1573,-1589,-1601,-1610,-1619,-1631,-1644,
+-1655,-1662,-1664,-1664,-1664,-1664,-1664,-1663,-1663,-1665,-1669,-1673,-1672,-1665,-1655,-1645,-1638,-1633,-1627,-1619,-1610,
+-1606,-1609,-1618,-1625,-1627,-1619,-1604,-1587,-1573,-1563,-1554,-1544,-1533,-1522,-1511,-1501,-1491,-1480,-1470,-1462,-1457,
+-1454,-1449,-1442,-1429,-1414,-1400,-1388,-1379,-1371,-1362,-1350,-1337,-1323,-1312,-1303,-1293,-1281,-1267,-1250,-1233,-1217,
+-1203,-1189,-1177,-1166,-1157,-1151,-1146,-1140,-1134,-1127,-1122,-1120,-1119,-1119,-1117,-1112,-1106,-1099,-1093,-1087,-1078,
+-1068,-1059,-1052,-1046,-1042,-1036,-1028,-1017,-1007,-1000,-996,-993,-991,-989,-986,-983,-979,-974,-969,-963,-957,
+-953,-949,-946,-942,-939,-938,-939,-942,-945,-947,-947,-946,-947,-949,-953,-956,-959,-959,-958,-956,-955,
+-954,-954,-956,-960,-964,-966,-965,-959,-952,-944,-938,-934,-933,-931,-929,-925,-921,-915,-910,-904,-899,
+-894,-888,-879,-868,-855,-842,-830,-820,-811,-799,-785,-767,-749,-734,-726,-723,-724,-723,-716,-702,-682,
+-658,-635,-617,-606,-601,-601,-601,-598,-592,-584,-574,-564,-553,-538,-520,-500,-483,-469,-460,-452,-441,
+-426,-407,-386,-364,-343,-321,-299,-276,-253,-230,-206,-182,-158,-138,-121,-105,-87,-67,-44,-24,-10,
+0,6,15,27,42,57,71,84,100,118,139,161,184,208,232,257,280,304,328,355,385,
+415,440,458,471,482,496,516,542,572,603,633,659,680,700,721,746,773,798,818,835,855,
+881,904,911,894,866,854,889,981,1105,1221,1300,1346,1392,1481,1625,1794,1940,2022,2037,2014,1991,
+1989,2000,1998,1966,1903,1824,1748,1686,1640,1606,1578,1551,1522,1488,1447,1403,1362,1329,1303,1280,1256,
+1232,1211,1196,1184,1173,1160,1148,1143,1146,1154,1160,1155,1144,1133,1131,1139,1150,1155,1151,1141,1136,
+1140,1152,1160,1157,1137,1103,1060,1008,946,875,800,731,678,643,618,592,555,508,460,416,378,
+337,287,226,159,100,56,29,11,-5,-27,-52,-77,-98,-115,-131,-148,-166,-185,-204,-223,-242,
+-260,-277,-293,-308,-324,-342,-360,-374,-383,-388,-390,-391,-393,-395,-396,-395,-393,-393,-393,-393,-390,
+-385,-378,-368,-354,-336,-314,-291,-272,-260,-255,-256,-261,-268,-278,-292,-308,-322,-331,-336,-338,-339,
+-338,-331,-317,-297,-276,-259,-250,-247,-247,-244,-240,-233,-226,-218,-208,-196,-182,-167,-150,-131,-107,
+-80,-50,-21,7,38,73,113,155,195,230,262,293,327,365,403,440,475,509,544,580,618,
+656,696,739,784,829,871,908,942,976,1013,1052,1091,1128,1163,1198,1237,1280,1324,1365,1399,1427,
+1453,1480,1509,1538,1568,1598,1629,1664,1702,1742,1782,1820,1856,1891,1926,1960,1994,2027,2058,2089,2119,
+2149,2179,2207,2230,2251,2271,2293,2319,2347,2376,2404,2431,2459,2489,2520,2549,2571,2586,2599,2617,2642,
+2672,2702,2725,2740,2748,2754,2759,2762,2759,2750,2738,2726,2718,2715,2714,2714,2715,2718,2722,2725,2724,
+2718,2709,2701,2695,2689,2680,2662,2634,2599,2563,2533,2513,2501,2493,2484,2471,2455,2440,2428,2423,2421,
+2420,2414,2403,2389,2375,2363,2352,2341,2329,2317,2306,2298,2291,2286,2281,2279,2279,2277,2284,2277,2264,
+2248,2233,2224,2221,2219,2215,2208,2204,2205,2212,2219,2221,2219,2217,2222,2236,2254,2271,2286,2303,2328,
+2361,2396,2426,2451,2477,2511,2550,2577,2578,2548,2507,2483,2497,2548,2611,2657,2671,2659,2642,2637,2643,
+2650,2646,2632,2618,2616,2633,2660,2687,2705,2715,2723,2737,2758,2784,2813,2839,2860,2875,2888,2902,2923,
+2952,2987,3020,3045,3059,3068,3078,3093,3112,3131,3146,3157,3168,3181,3194,3207,3215,3220,3226,3232,3239,
+3244,3247,3248,3249,3252,3252,3250,3245,3244,3251,3267,3286,3299,3305,3305,3307,3315,3329,3342,3350,3355,
+3361,3374,3391,3410,3432,3458,3494,3540,3593,3644,3691,3738,3796,3868,3949,4020,4067,4084,4083,4087,4114,
+4167,4235,4299,4345,4373,4392,4415,4448,4485,4513,4523,4516,4499,4485,4476,4465,4446,4417,4393,4391,4419,
+4462,4490,4476,4420,4347,4297,4292,4328,4375,4404,4404,4389,4380,4388,4403,4406,4383,4340,4293,4259,4247,
+4256,4279,4311,4349,4387,4417,4435,4445,4455,4476,4508,4544,4573,4589,4594,4595,4597,4596,4584,4557,4516,
+4471,4432,4407,4399,4406,4425,4452,4481,4509,4534,4557,4579,4596,4603,4595,4571,4538,4508,4485,4469,4453,
+4431,4405,4380,4363,4354,4346,4335,4317,4295,4273,4254,4236,4217,4196,4172,4149,4125,4101,4075,4048,4022,
+3997,3970,3939,3901,3860,3821,3786,3757,3730,3703,3672,3641,3612,3590,3578,3576,3579,3579,3568,3541,3503,
+3465,3438,3430,3441,3465,3498,3540,3593,3655,3718,3772,3807,3821,3822,3818,3818,3821,3823,3821,3811,3794,
+3771,3747,3726,3709,3692,3672,3643,3604,3559,3513,3472,3433,3391,3342,3290,3243,3206,3179,3155,3125,3089,
+3051,3020,2999,2983,2964,2940,2912,2887,2866,2845,2817,2781,2740,2704,2678,2660,2642,2619,2592,2565,2540,
+2515,2485,2449,2408,2371,2342,2320,2297,2268,2234,2198,2166,2139,2112,2081,2045,2006,1968,1933,1899,1865,
+1830,1795,1762,1730,1697,1662,1625,1589,1555,1521,1486,1449,1410,1371,1333,1295,1257,1218,1178,1138,1098,
+1058,1016,975,934,895,857,817,776,736,699,664,629,589,544,494,445,402,364,329,294,257,
+219,185,153,122,88,50,8,-33,-75,-116,-157,-199,-241,-282,-322,-361,-401,-444,-488,-532,-573,
+-610,-646,-682,-722,-764,-805,-843,-879,-914,-952,-994,-1038,-1080,-1117,-1150,-1180,-1212,-1247,-1286,-1324,-1360,
+-1392,-1423,-1455,-1488,-1524,-1561,-1597,-1632,-1664,-1695,-1725,-1754,-1784,-1815,-1846,-1875,-1901,-1925,-1948,-1971,-1996,
+-2023,-2049,-2074,-2097,-2118,-2138,-2157,-2177,-2201,-2227,-2255,-2281,-2301,-2314,-2323,-2333,-2348,-2369,-2392,-2412,-2426,
+-2433,-2435,-2436,-2440,-2448,-2459,-2472,-2484,-2494,-2503,-2509,-2514,-2517,-2520,-2522,-2525,-2529,-2534,-2539,-2545,-2550,
+-2554,-2556,-2555,-2552,-2548,-2544,-2541,-2539,-2535,-2529,-2522,-2515,-2512,-2511,-2510,-2505,-2496,-2486,-2476,-2471,-2468,
+-2465,-2459,-2451,-2443,-2436,-2429,-2417,-2401,-2383,-2365,-2352,-2342,-2331,-2315,-2295,-2274,-2257,-2243,-2230,-2216,-2198,
+-2179,-2162,-2147,-2133,-2117,-2098,-2078,-2057,-2037,-2017,-1997,-1977,-1958,-1941,-1925,-1909,-1891,-1870,-1848,-1827,-1809,
+-1794,-1778,-1761,-1742,-1724,-1710,-1704,-1710,-1725,-1746,-1762,-1766,-1757,-1739,-1720,-1707,-1702,-1699,-1692,-1680,-1665,
+-1655,-1652,-1652,-1648,-1634,-1612,-1592,-1582,-1586,-1597,-1603,-1595,-1571,-1538,-1502,-1468,-1435,-1398,-1355,-1312,-1274,
+-1248,-1235,-1233,-1239,-1253,-1278,-1315,-1360,-1404,-1436,-1451,-1449,-1440,-1434,-1436,-1443,-1450,-1450,-1442,-1426,-1408,
+-1390,-1376,-1366,-1360,-1359,-1360,-1361,-1359,-1353,-1344,-1335,-1327,-1317,-1302,-1282,-1258,-1237,-1225,-1220,-1217,-1209,
+-1193,-1174,-1161,-1158,-1161,-1156,-1133,-1090,-1036,-988,-955,-930,-903,-863,-812,-764,-733,-723,-723,-720,-711,
+-705,-723,-771,-839,-896,-912,-872,-787,-686,-593,-517,-452,-381,-298,-208,-125,-65,-34,-28,-37,-51,
+-68,-87,-112,-147,-187,-229,-264,-287,-299,-305,-308,-314,-320,-324,-323,-320,-316,-315,-317,-317,-316,
+-313,-312,-315,-321,-326,-327,-325,-323,-323,-327,-331,-335,-339,-344,-350,-355,-354,-345,-334,-328,-335,
+-357,-389,-424,-459,-495,-540,-601,-677,-758,-832,-886,-917,-926,-925,-923,-928,-943,-964,-987,-1006,-1019,
+-1030,-1038,-1045,-1052,-1059,-1064,-1068,-1071,-1072,-1072,-1072,-1075,-1083,-1096,-1111,-1124,-1133,-1139,-1145,-1154,-1167,
+-1184,-1200,-1211,-1218,-1222,-1225,-1230,-1235,-1242,-1247,-1251,-1254,-1257,-1260,-1266,-1271,-1276,-1277,-1275,-1270,-1262,
+-1254,-1248,-1242,-1238,-1235,-1236,-1240,-1245,-1250,-1255,-1259,-1264,-1270,-1277,-1281,-1281,-1279,-1277,-1277,-1279,-1281,
+-1280,-1273,-1263,-1253,-1247,-1244,-1243,-1243,-1242,-1241,-1239,-1237,-1233,-1225,-1215,-1207,-1203,-1207,-1216,-1226,-1233,
+-1235,-1234,-1234,-1237,-1242,-1246,-1247,-1246,-1245,-1250,-1260,-1276,-1291,-1303,-1311,-1318,-1327,-1337,-1348,-1360,-1374,
+-1390,-1408,-1424,-1431,-1428,-1419,-1411,-1410,-1417,-1427,-1435,-1439,-1444,-1454,-1469,-1486,-1500,-1507,-1511,-1516,-1525,
+-1536,-1544,-1549,-1551,-1556,-1566,-1580,-1595,-1607,-1617,-1625,-1634,-1645,-1656,-1664,-1668,-1671,-1674,-1677,-1681,-1685,
+-1689,-1694,-1696,-1695,-1688,-1677,-1667,-1659,-1655,-1651,-1643,-1632,-1621,-1616,-1619,-1626,-1632,-1630,-1620,-1604,-1589,
+-1577,-1567,-1558,-1547,-1535,-1525,-1518,-1513,-1507,-1499,-1490,-1480,-1473,-1467,-1460,-1449,-1434,-1417,-1401,-1388,-1380,
+-1375,-1369,-1360,-1348,-1333,-1319,-1306,-1294,-1283,-1272,-1260,-1247,-1233,-1218,-1202,-1187,-1174,-1162,-1152,-1144,-1134,
+-1124,-1114,-1105,-1099,-1096,-1095,-1094,-1092,-1088,-1084,-1080,-1075,-1069,-1062,-1055,-1049,-1044,-1041,-1037,-1030,-1022,
+-1014,-1007,-1001,-998,-995,-992,-988,-985,-981,-976,-971,-965,-959,-953,-949,-945,-942,-939,-937,-938,-940,
+-942,-944,-945,-944,-944,-946,-950,-955,-960,-963,-964,-965,-965,-966,-966,-967,-967,-968,-968,-967,-964,
+-959,-952,-944,-939,-937,-937,-939,-939,-935,-929,-922,-915,-908,-903,-898,-891,-880,-867,-853,-841,-830,
+-820,-809,-796,-780,-764,-750,-741,-739,-739,-739,-732,-718,-696,-671,-647,-631,-622,-621,-623,-624,-621,
+-614,-605,-596,-586,-574,-560,-543,-525,-510,-497,-485,-473,-457,-438,-418,-398,-378,-358,-335,-311,-286,
+-261,-236,-210,-184,-159,-137,-119,-103,-87,-70,-52,-37,-25,-17,-10,-1,11,25,40,56,72,
+89,108,128,149,170,194,218,242,265,288,313,342,371,398,419,434,446,459,477,500,525,
+551,577,601,624,646,668,693,720,749,772,790,805,822,842,855,850,823,789,784,839,959,
+1112,1250,1337,1377,1411,1490,1630,1804,1957,2041,2049,2010,1967,1944,1937,1920,1876,1805,1729,1668,1634,
+1621,1618,1611,1593,1563,1521,1467,1409,1352,1305,1269,1242,1223,1208,1198,1192,1187,1178,1165,1151,1144,
+1146,1154,1160,1157,1146,1133,1128,1132,1140,1142,1136,1128,1127,1138,1156,1168,1164,1142,1105,1063,1017,
+965,903,835,769,715,678,650,622,583,535,485,441,405,370,328,276,217,160,113,76,46,
+18,-10,-38,-63,-84,-102,-119,-137,-154,-170,-184,-200,-216,-235,-253,-271,-288,-305,-321,-336,-346,
+-352,-356,-360,-365,-371,-376,-380,-381,-382,-384,-386,-386,-383,-377,-369,-359,-346,-327,-302,-274,-248,
+-228,-217,-213,-215,-222,-233,-247,-262,-275,-284,-288,-289,-289,-287,-279,-265,-244,-223,-207,-200,-200,
+-203,-204,-201,-194,-183,-170,-157,-142,-127,-111,-93,-72,-46,-18,10,37,63,91,122,157,193,
+227,255,282,312,346,386,427,466,501,532,563,594,627,663,704,749,798,848,894,934,969,
+1001,1035,1070,1105,1139,1173,1208,1248,1291,1337,1379,1416,1448,1476,1504,1532,1560,1588,1614,1642,1672,
+1706,1744,1783,1821,1856,1889,1921,1952,1983,2012,2040,2066,2093,2122,2153,2183,2210,2233,2254,2278,2307,
+2340,2372,2400,2424,2448,2475,2507,2540,2567,2587,2602,2619,2640,2666,2690,2707,2717,2724,2731,2740,2747,
+2747,2737,2723,2712,2709,2717,2733,2751,2767,2780,2787,2788,2784,2773,2760,2743,2725,2702,2674,2640,2605,
+2574,2550,2536,2528,2523,2518,2509,2497,2482,2468,2457,2448,2441,2432,2420,2406,2392,2380,2369,2358,2344,
+2329,2315,2304,2297,2293,2290,2287,2286,2285,2284,2293,2288,2279,2269,2260,2256,2254,2250,2241,2229,2221,
+2221,2228,2234,2234,2228,2221,2222,2234,2253,2273,2290,2308,2332,2360,2387,2405,2416,2430,2455,2491,2523,
+2532,2515,2485,2472,2499,2563,2642,2702,2725,2716,2694,2679,2675,2673,2664,2645,2628,2625,2640,2670,2701,
+2726,2743,2757,2772,2793,2816,2840,2860,2876,2889,2901,2915,2934,2960,2989,3015,3034,3045,3056,3071,3094,
+3121,3145,3162,3172,3181,3192,3205,3217,3225,3229,3231,3232,3234,3235,3237,3240,3247,3256,3263,3266,3263,
+3259,3261,3271,3285,3300,3310,3317,3324,3334,3345,3355,3362,3367,3375,3388,3406,3429,3458,3496,3545,3601,
+3654,3699,3737,3781,3842,3920,3999,4058,4082,4076,4065,4079,4129,4208,4290,4347,4371,4372,4373,4391,4427,
+4469,4497,4502,4486,4463,4446,4439,4434,4423,4402,4378,4363,4362,4368,4367,4349,4316,4284,4272,4286,4317,
+4347,4362,4362,4361,4370,4388,4407,4411,4394,4362,4326,4298,4284,4285,4302,4332,4367,4398,4415,4418,4415,
+4419,4440,4475,4511,4538,4552,4559,4566,4575,4580,4572,4549,4515,4479,4450,4430,4418,4414,4419,4434,4454,
+4473,4485,4488,4485,4481,4474,4464,4449,4429,4412,4403,4400,4401,4398,4391,4381,4373,4367,4358,4345,4324,
+4300,4278,4259,4243,4226,4206,4182,4157,4132,4107,4083,4059,4035,4011,3985,3952,3915,3875,3838,3806,3780,
+3754,3727,3696,3664,3635,3616,3608,3610,3616,3616,3603,3576,3539,3502,3475,3465,3472,3494,3532,3584,3650,
+3722,3791,3843,3872,3882,3881,3877,3877,3882,3889,3894,3894,3886,3870,3847,3822,3798,3777,3755,3727,3690,
+3645,3597,3547,3497,3442,3382,3322,3271,3234,3210,3189,3161,3125,3087,3053,3029,3010,2989,2963,2934,2909,
+2888,2866,2839,2803,2765,2731,2707,2690,2672,2650,2623,2596,2570,2544,2514,2477,2437,2403,2377,2357,2335,
+2306,2269,2231,2196,2167,2139,2107,2070,2031,1994,1960,1927,1892,1856,1819,1784,1751,1718,1682,1646,1610,
+1575,1543,1510,1474,1436,1398,1361,1325,1288,1248,1205,1162,1120,1080,1041,1003,965,925,884,843,802,
+763,727,692,656,617,573,527,481,438,399,363,328,293,259,225,192,159,123,86,47,9,
+-29,-68,-110,-152,-195,-236,-276,-318,-362,-409,-454,-496,-532,-564,-596,-633,-675,-720,-763,-801,-834,
+-867,-903,-944,-989,-1031,-1068,-1100,-1131,-1165,-1204,-1246,-1287,-1323,-1354,-1384,-1415,-1450,-1487,-1525,-1560,-1592,
+-1621,-1651,-1681,-1711,-1741,-1771,-1799,-1827,-1854,-1880,-1906,-1931,-1956,-1982,-2007,-2034,-2060,-2084,-2106,-2126,-2147,
+-2170,-2195,-2220,-2243,-2261,-2274,-2285,-2297,-2313,-2333,-2355,-2374,-2387,-2394,-2399,-2404,-2411,-2421,-2433,-2445,-2455,
+-2464,-2472,-2479,-2485,-2491,-2496,-2499,-2503,-2508,-2514,-2521,-2529,-2534,-2537,-2537,-2535,-2530,-2524,-2520,-2517,-2516,
+-2515,-2512,-2507,-2501,-2497,-2496,-2495,-2493,-2486,-2476,-2465,-2456,-2452,-2449,-2447,-2442,-2435,-2425,-2413,-2398,-2382,
+-2366,-2351,-2339,-2327,-2315,-2300,-2282,-2264,-2247,-2232,-2217,-2202,-2186,-2169,-2153,-2136,-2120,-2102,-2085,-2067,-2049,
+-2030,-2011,-1990,-1970,-1951,-1935,-1919,-1904,-1887,-1868,-1849,-1831,-1813,-1795,-1777,-1757,-1738,-1720,-1706,-1700,-1705,
+-1721,-1744,-1765,-1774,-1768,-1750,-1730,-1716,-1710,-1708,-1702,-1691,-1676,-1665,-1660,-1660,-1655,-1640,-1618,-1597,-1586,
+-1589,-1599,-1605,-1599,-1578,-1549,-1517,-1487,-1456,-1421,-1382,-1342,-1306,-1281,-1265,-1257,-1255,-1262,-1281,-1314,-1357,
+-1401,-1436,-1455,-1458,-1453,-1449,-1452,-1461,-1470,-1473,-1466,-1451,-1433,-1417,-1407,-1404,-1406,-1412,-1417,-1417,-1413,
+-1403,-1392,-1383,-1374,-1363,-1345,-1321,-1295,-1275,-1267,-1270,-1273,-1270,-1256,-1238,-1224,-1216,-1208,-1187,-1146,-1092,
+-1040,-1005,-989,-979,-958,-915,-860,-813,-787,-781,-780,-770,-753,-748,-776,-842,-923,-983,-991,-943,-857,
+-764,-682,-609,-532,-441,-339,-246,-179,-148,-148,-166,-191,-215,-237,-259,-281,-301,-320,-339,-359,-378,
+-393,-403,-407,-407,-405,-403,-400,-396,-394,-392,-392,-391,-389,-386,-385,-386,-388,-390,-390,-389,-389,
+-389,-390,-388,-384,-380,-380,-385,-388,-385,-371,-350,-333,-329,-342,-370,-403,-436,-474,-524,-596,-688,
+-788,-880,-947,-985,-999,-1002,-1006,-1017,-1037,-1059,-1079,-1095,-1107,-1116,-1125,-1134,-1141,-1145,-1147,-1148,-1151,
+-1155,-1160,-1165,-1170,-1175,-1182,-1191,-1201,-1209,-1214,-1218,-1223,-1231,-1242,-1256,-1268,-1276,-1279,-1281,-1284,-1288,
+-1294,-1299,-1303,-1306,-1308,-1310,-1314,-1319,-1324,-1327,-1329,-1328,-1323,-1316,-1307,-1298,-1290,-1284,-1281,-1280,-1281,
+-1284,-1289,-1297,-1306,-1316,-1323,-1328,-1329,-1329,-1330,-1333,-1336,-1338,-1336,-1329,-1320,-1312,-1306,-1303,-1304,-1305,
+-1305,-1301,-1294,-1285,-1276,-1268,-1262,-1256,-1252,-1251,-1255,-1262,-1271,-1277,-1280,-1280,-1280,-1282,-1286,-1290,-1293,
+-1295,-1299,-1305,-1315,-1325,-1331,-1333,-1333,-1334,-1339,-1348,-1361,-1378,-1397,-1417,-1432,-1439,-1435,-1426,-1418,-1420,
+-1432,-1449,-1465,-1475,-1482,-1488,-1498,-1510,-1521,-1528,-1531,-1535,-1542,-1551,-1561,-1567,-1571,-1575,-1583,-1595,-1608,
+-1620,-1629,-1636,-1642,-1649,-1656,-1663,-1669,-1676,-1682,-1689,-1695,-1701,-1707,-1712,-1715,-1713,-1705,-1695,-1687,-1683,
+-1681,-1678,-1668,-1654,-1639,-1630,-1630,-1634,-1637,-1633,-1622,-1609,-1596,-1586,-1575,-1562,-1546,-1531,-1521,-1516,-1515,
+-1513,-1509,-1503,-1495,-1488,-1481,-1472,-1459,-1443,-1424,-1407,-1394,-1385,-1378,-1370,-1360,-1346,-1330,-1312,-1297,-1284,
+-1274,-1266,-1259,-1250,-1239,-1226,-1213,-1200,-1189,-1178,-1168,-1157,-1144,-1130,-1116,-1102,-1090,-1083,-1079,-1076,-1073,
+-1070,-1066,-1062,-1058,-1054,-1049,-1044,-1039,-1034,-1031,-1028,-1025,-1021,-1016,-1009,-1003,-999,-995,-992,-989,-985,
+-981,-976,-970,-965,-959,-953,-948,-944,-940,-937,-935,-936,-939,-942,-946,-947,-947,-945,-945,-947,-952,
+-957,-963,-968,-972,-976,-980,-981,-980,-977,-974,-972,-971,-970,-967,-960,-952,-944,-940,-940,-943,-945,
+-943,-938,-930,-922,-916,-912,-908,-903,-894,-883,-870,-857,-845,-835,-824,-812,-798,-784,-770,-760,-756,
+-754,-752,-746,-732,-711,-687,-666,-651,-643,-642,-644,-645,-643,-638,-631,-622,-611,-597,-581,-564,-547,
+-533,-518,-503,-485,-465,-445,-426,-408,-390,-369,-346,-320,-294,-267,-240,-212,-185,-160,-139,-122,-108,
+-94,-81,-68,-57,-48,-39,-31,-21,-8,5,21,39,59,78,97,114,132,152,175,200,224,
+246,268,292,319,347,372,391,404,418,435,458,482,505,526,546,568,593,619,645,672,700,
+726,749,766,779,791,802,806,794,766,741,753,828,971,1144,1297,1390,1423,1440,1490,1600,1749,
+1890,1979,2003,1984,1957,1937,1919,1881,1816,1732,1657,1611,1600,1609,1619,1617,1598,1566,1523,1470,1408,
+1342,1280,1230,1197,1179,1175,1177,1182,1183,1177,1165,1152,1145,1147,1156,1162,1160,1149,1136,1129,1130,
+1134,1133,1126,1117,1116,1127,1144,1154,1148,1123,1088,1051,1015,977,928,870,808,754,712,680,647,
+606,555,502,456,420,389,357,317,270,221,175,133,95,59,25,-4,-28,-49,-68,-88,-108,
+-126,-142,-155,-170,-187,-207,-229,-249,-266,-281,-293,-302,-307,-310,-313,-319,-327,-336,-345,-351,-356,
+-360,-364,-367,-367,-364,-357,-349,-340,-327,-309,-284,-254,-224,-200,-184,-175,-173,-176,-184,-196,-209,
+-221,-229,-231,-230,-226,-220,-210,-194,-176,-158,-145,-141,-143,-147,-149,-146,-137,-126,-112,-96,-80,
+-64,-47,-28,-6,18,45,72,99,125,151,179,207,234,260,284,309,339,374,414,454,491,
+526,558,589,621,654,690,729,774,823,872,919,960,995,1028,1060,1094,1128,1161,1193,1226,1262,
+1303,1347,1392,1433,1468,1499,1526,1551,1575,1599,1622,1648,1676,1708,1744,1781,1818,1851,1881,1911,1940,
+1970,2000,2027,2051,2076,2103,2134,2167,2197,2223,2246,2271,2300,2334,2369,2398,2422,2443,2466,2494,2524,
+2551,2573,2590,2607,2625,2644,2659,2669,2674,2680,2691,2707,2722,2730,2729,2722,2719,2724,2740,2764,2789,
+2811,2825,2829,2823,2809,2788,2766,2742,2717,2688,2656,2623,2594,2574,2563,2559,2557,2552,2542,2530,2516,
+2501,2488,2475,2462,2448,2432,2415,2399,2384,2373,2363,2353,2342,2329,2318,2311,2308,2306,2304,2301,2298,
+2296,2293,2313,2308,2299,2289,2280,2273,2269,2261,2250,2237,2228,2228,2234,2240,2242,2237,2235,2240,2256,
+2276,2293,2307,2320,2338,2361,2381,2391,2394,2402,2427,2469,2514,2538,2531,2503,2482,2496,2548,2620,2681,
+2709,2704,2683,2665,2658,2656,2650,2637,2624,2623,2639,2668,2703,2733,2757,2775,2791,2809,2828,2847,2867,
+2885,2903,2919,2934,2950,2968,2987,3004,3017,3029,3044,3066,3097,3130,3159,3179,3192,3200,3209,3220,3229,
+3236,3238,3238,3237,3235,3234,3234,3238,3248,3263,3278,3288,3290,3288,3287,3289,3296,3305,3316,3327,3341,
+3355,3368,3376,3381,3387,3397,3412,3433,3459,3492,3535,3589,3647,3700,3743,3782,3828,3891,3965,4029,4063,
+4059,4035,4024,4056,4135,4238,4328,4376,4381,4363,4352,4366,4402,4442,4467,4467,4449,4424,4406,4396,4391,
+4385,4375,4362,4350,4338,4325,4307,4287,4271,4267,4278,4301,4325,4343,4352,4359,4369,4384,4398,4405,4399,
+4386,4369,4353,4339,4326,4319,4322,4338,4363,4387,4399,4397,4391,4394,4415,4450,4484,4509,4523,4532,4543,
+4555,4561,4553,4531,4503,4479,4463,4453,4445,4439,4438,4447,4463,4479,4488,4485,4475,4464,4457,4451,4442,
+4429,4414,4401,4395,4394,4394,4392,4387,4382,4374,4364,4348,4328,4305,4284,4267,4251,4235,4215,4190,4163,
+4136,4110,4087,4065,4043,4021,3994,3963,3927,3890,3855,3826,3801,3778,3753,3726,3697,3672,3654,3645,3641,
+3640,3635,3622,3599,3570,3539,3512,3495,3493,3511,3551,3614,3692,3772,3841,3889,3913,3922,3923,3925,3930,
+3937,3945,3951,3953,3949,3934,3910,3879,3849,3824,3802,3778,3746,3702,3650,3592,3532,3469,3404,3342,3290,
+3254,3230,3212,3189,3158,3124,3094,3070,3049,3025,2995,2963,2933,2908,2885,2859,2827,2792,2761,2737,2719,
+2700,2677,2650,2623,2598,2572,2542,2506,2468,2435,2409,2388,2367,2338,2303,2265,2230,2197,2164,2127,2088,
+2048,2013,1981,1950,1916,1880,1842,1807,1775,1742,1707,1670,1632,1597,1564,1533,1499,1463,1426,1389,1354,
+1317,1278,1235,1190,1147,1106,1068,1031,992,951,910,869,829,791,754,717,679,639,598,555,513,
+472,432,395,361,328,296,264,231,195,157,119,81,45,8,-31,-72,-115,-157,-198,-240,-283,
+-330,-377,-421,-460,-492,-521,-553,-592,-637,-684,-728,-767,-800,-833,-869,-909,-951,-991,-1026,-1058,-1090,
+-1126,-1167,-1210,-1252,-1287,-1318,-1347,-1378,-1413,-1450,-1486,-1519,-1548,-1576,-1605,-1637,-1670,-1701,-1731,-1757,-1783,
+-1809,-1837,-1866,-1894,-1919,-1943,-1967,-1992,-2017,-2043,-2067,-2089,-2111,-2133,-2156,-2179,-2200,-2217,-2231,-2244,-2259,
+-2276,-2294,-2313,-2329,-2341,-2351,-2361,-2371,-2383,-2396,-2409,-2419,-2428,-2435,-2441,-2449,-2458,-2465,-2471,-2474,-2477,
+-2480,-2486,-2494,-2503,-2510,-2514,-2514,-2511,-2507,-2503,-2499,-2497,-2497,-2498,-2498,-2495,-2490,-2484,-2480,-2478,-2476,
+-2472,-2464,-2454,-2443,-2435,-2431,-2430,-2428,-2422,-2412,-2397,-2381,-2365,-2350,-2337,-2324,-2310,-2296,-2281,-2266,-2251,
+-2237,-2222,-2207,-2192,-2177,-2162,-2146,-2129,-2111,-2092,-2074,-2059,-2043,-2027,-2008,-1988,-1968,-1949,-1932,-1915,-1898,
+-1880,-1863,-1847,-1832,-1816,-1798,-1780,-1760,-1741,-1724,-1709,-1702,-1705,-1721,-1745,-1770,-1784,-1782,-1766,-1746,-1729,
+-1721,-1716,-1709,-1697,-1683,-1673,-1670,-1671,-1666,-1651,-1627,-1603,-1592,-1595,-1607,-1618,-1616,-1600,-1573,-1544,-1515,
+-1486,-1455,-1421,-1386,-1355,-1330,-1313,-1302,-1295,-1294,-1304,-1327,-1361,-1400,-1435,-1460,-1473,-1477,-1478,-1479,-1483,
+-1486,-1484,-1477,-1465,-1451,-1441,-1437,-1440,-1448,-1458,-1465,-1467,-1461,-1451,-1439,-1429,-1420,-1410,-1393,-1370,-1345,
+-1327,-1319,-1321,-1323,-1319,-1306,-1289,-1272,-1257,-1238,-1205,-1157,-1103,-1059,-1033,-1023,-1013,-985,-939,-887,-849,
+-833,-830,-824,-808,-792,-801,-852,-938,-1024,-1068,-1047,-970,-869,-773,-696,-626,-546,-452,-356,-281,-243,
+-241,-260,-285,-310,-333,-358,-383,-403,-414,-420,-427,-442,-463,-484,-496,-496,-488,-479,-474,-473,-473,
+-471,-468,-463,-460,-458,-457,-456,-455,-454,-454,-457,-462,-469,-475,-476,-470,-458,-445,-437,-437,-439,
+-436,-421,-396,-371,-357,-362,-381,-408,-439,-477,-532,-613,-716,-829,-931,-1006,-1049,-1067,-1076,-1087,-1106,
+-1129,-1150,-1166,-1175,-1182,-1190,-1201,-1213,-1222,-1226,-1227,-1227,-1230,-1238,-1249,-1260,-1266,-1269,-1269,-1271,-1276,
+-1283,-1290,-1295,-1298,-1302,-1309,-1319,-1329,-1336,-1340,-1341,-1342,-1344,-1347,-1350,-1353,-1354,-1356,-1359,-1363,-1367,
+-1371,-1373,-1375,-1375,-1374,-1370,-1364,-1357,-1349,-1343,-1338,-1333,-1328,-1325,-1326,-1332,-1342,-1355,-1366,-1374,-1380,
+-1383,-1386,-1387,-1387,-1386,-1384,-1382,-1380,-1378,-1376,-1373,-1371,-1369,-1365,-1358,-1348,-1336,-1326,-1319,-1315,-1311,
+-1306,-1300,-1296,-1297,-1303,-1310,-1314,-1315,-1313,-1313,-1316,-1321,-1326,-1331,-1337,-1345,-1356,-1366,-1371,-1369,-1363,
+-1356,-1353,-1354,-1359,-1367,-1377,-1389,-1400,-1409,-1414,-1415,-1419,-1430,-1449,-1472,-1492,-1505,-1512,-1516,-1523,-1531,
+-1539,-1544,-1546,-1548,-1553,-1561,-1572,-1581,-1588,-1594,-1601,-1610,-1621,-1632,-1643,-1650,-1655,-1658,-1660,-1664,-1670,
+-1679,-1688,-1696,-1703,-1709,-1715,-1721,-1725,-1724,-1719,-1712,-1707,-1705,-1705,-1703,-1694,-1679,-1664,-1654,-1650,-1651,
+-1650,-1644,-1633,-1620,-1609,-1599,-1588,-1573,-1555,-1538,-1525,-1518,-1515,-1512,-1508,-1503,-1498,-1493,-1488,-1479,-1467,
+-1450,-1433,-1417,-1402,-1390,-1378,-1365,-1351,-1335,-1318,-1300,-1284,-1271,-1262,-1256,-1249,-1241,-1231,-1221,-1210,-1201,
+-1194,-1187,-1179,-1169,-1157,-1143,-1127,-1111,-1097,-1087,-1079,-1074,-1070,-1064,-1057,-1051,-1046,-1042,-1038,-1033,-1026,
+-1019,-1014,-1010,-1009,-1007,-1004,-999,-994,-990,-988,-986,-985,-983,-979,-974,-970,-965,-960,-955,-949,-943,
+-938,-935,-934,-936,-940,-945,-950,-953,-953,-951,-950,-950,-953,-958,-964,-970,-976,-982,-987,-990,-990,
+-986,-982,-978,-976,-975,-973,-968,-961,-953,-948,-947,-949,-950,-948,-942,-935,-929,-925,-922,-919,-915,
+-908,-899,-889,-878,-867,-856,-844,-832,-819,-805,-791,-779,-771,-766,-761,-755,-743,-726,-706,-688,-675,
+-668,-665,-665,-665,-664,-660,-655,-646,-632,-615,-596,-578,-561,-547,-531,-513,-493,-471,-451,-434,-417,
+-400,-379,-354,-327,-299,-272,-244,-217,-191,-168,-149,-134,-121,-110,-100,-91,-83,-75,-65,-54,-41,
+-27,-12,5,26,48,69,87,102,118,137,162,187,211,230,247,268,293,320,345,364,379,
+394,414,438,462,482,499,518,542,572,602,630,654,678,701,724,742,753,759,760,755,742,
+726,723,762,861,1019,1199,1352,1439,1460,1453,1468,1534,1641,1754,1835,1874,1883,1883,1884,1873,1833,
+1763,1680,1613,1580,1580,1593,1597,1583,1554,1520,1484,1442,1388,1322,1251,1191,1151,1136,1139,1152,1164,
+1170,1167,1157,1146,1141,1145,1153,1160,1158,1149,1136,1128,1127,1129,1128,1120,1110,1107,1114,1127,1134,
+1127,1104,1072,1040,1013,985,949,902,848,795,750,711,672,627,575,523,477,442,414,387,355,
+317,276,234,194,154,116,81,52,28,8,-10,-32,-56,-79,-100,-118,-136,-156,-177,-198,-216,
+-231,-242,-250,-257,-261,-264,-269,-276,-285,-296,-307,-315,-322,-327,-331,-333,-333,-330,-325,-319,-310,
+-297,-278,-252,-224,-196,-173,-158,-148,-142,-140,-143,-149,-158,-167,-172,-172,-167,-159,-148,-135,-120,
+-106,-95,-88,-85,-85,-85,-83,-77,-68,-56,-44,-30,-14,2,21,40,60,81,105,129,155,
+182,208,233,257,279,301,324,351,383,420,458,496,531,566,601,635,669,703,736,773,813,
+856,901,943,980,1012,1044,1076,1110,1145,1179,1212,1244,1277,1315,1356,1401,1444,1483,1514,1539,1559,
+1578,1599,1623,1650,1681,1714,1748,1783,1816,1848,1876,1905,1934,1966,1998,2028,2054,2077,2103,2131,2162,
+2192,2218,2239,2260,2284,2314,2347,2378,2406,2429,2452,2475,2498,2519,2538,2556,2573,2591,2607,2620,2628,
+2635,2645,2663,2686,2709,2726,2736,2742,2748,2758,2773,2791,2809,2824,2833,2832,2821,2801,2775,2749,2725,
+2702,2680,2658,2637,2620,2609,2602,2595,2586,2571,2553,2534,2517,2501,2486,2472,2457,2443,2430,2417,2404,
+2392,2382,2373,2364,2355,2345,2338,2334,2332,2331,2328,2323,2319,2316,2313,2331,2325,2314,2301,2288,2279,
+2272,2266,2259,2251,2245,2243,2247,2251,2254,2257,2263,2275,2293,2310,2323,2332,2343,2361,2383,2401,2408,
+2410,2420,2453,2507,2564,2596,2587,2547,2504,2491,2518,2571,2620,2643,2637,2616,2601,2601,2611,2621,2624,
+2622,2627,2644,2674,2711,2747,2775,2794,2807,2817,2828,2842,2862,2886,2912,2934,2951,2962,2971,2981,2991,
+3004,3018,3038,3064,3098,3134,3167,3192,3208,3217,3224,3230,3236,3240,3244,3245,3245,3244,3242,3241,3245,
+3255,3270,3287,3302,3313,3319,3320,3319,3317,3317,3321,3334,3352,3372,3387,3395,3400,3408,3424,3447,3473,
+3500,3528,3562,3608,3663,3719,3773,3824,3879,3940,3996,4030,4031,4003,3973,3977,4035,4138,4252,4335,4367,
+4354,4326,4313,4329,4364,4400,4419,4419,4404,4386,4370,4357,4347,4339,4335,4335,4335,4328,4312,4290,4270,
+4263,4271,4291,4313,4331,4343,4356,4373,4394,4411,4416,4408,4392,4379,4372,4370,4364,4351,4335,4325,4332,
+4352,4376,4390,4391,4386,4388,4404,4431,4460,4481,4494,4505,4518,4530,4536,4528,4509,4487,4472,4466,4464,
+4461,4455,4452,4458,4473,4491,4503,4504,4497,4487,4479,4473,4465,4452,4436,4422,4412,4408,4405,4402,4395,
+4385,4373,4360,4344,4325,4307,4289,4274,4258,4241,4219,4193,4165,4137,4111,4088,4067,4045,4022,3996,3965,
+3933,3901,3871,3845,3822,3800,3778,3756,3736,3718,3704,3690,3677,3663,3647,3629,3611,3591,3571,3550,3535,
+3531,3546,3587,3651,3728,3803,3862,3901,3922,3935,3949,3964,3979,3989,3995,3997,3996,3991,3976,3950,3916,
+3883,3855,3833,3809,3774,3724,3664,3599,3536,3476,3418,3364,3317,3281,3254,3233,3209,3181,3152,3126,3105,
+3086,3063,3033,2998,2965,2935,2910,2884,2856,2826,2798,2774,2754,2733,2708,2681,2654,2628,2601,2571,2537,
+2500,2466,2437,2412,2387,2358,2325,2291,2258,2225,2190,2150,2107,2067,2031,2000,1968,1935,1898,1862,1829,
+1799,1770,1736,1699,1660,1623,1589,1557,1524,1488,1450,1412,1376,1340,1302,1262,1220,1177,1136,1097,1057,
+1017,975,934,894,857,820,784,746,706,665,624,583,543,503,463,425,390,358,327,297,264,
+228,189,151,113,75,37,-2,-44,-88,-131,-173,-215,-260,-305,-349,-389,-424,-454,-484,-519,-560,
+-606,-652,-694,-732,-767,-803,-841,-880,-920,-957,-991,-1024,-1058,-1095,-1135,-1176,-1214,-1248,-1279,-1309,-1341,
+-1377,-1413,-1448,-1478,-1505,-1530,-1559,-1592,-1628,-1663,-1694,-1721,-1746,-1773,-1802,-1832,-1861,-1887,-1910,-1931,-1953,
+-1976,-2000,-2024,-2046,-2068,-2091,-2115,-2137,-2157,-2173,-2188,-2202,-2219,-2237,-2256,-2272,-2287,-2299,-2310,-2323,-2337,
+-2353,-2368,-2382,-2393,-2401,-2408,-2414,-2422,-2431,-2440,-2445,-2446,-2446,-2447,-2452,-2461,-2472,-2481,-2486,-2489,-2489,
+-2488,-2487,-2486,-2484,-2483,-2483,-2483,-2481,-2476,-2469,-2461,-2455,-2453,-2452,-2448,-2441,-2430,-2419,-2412,-2409,-2407,
+-2403,-2395,-2381,-2366,-2352,-2339,-2328,-2315,-2300,-2283,-2267,-2252,-2239,-2226,-2211,-2195,-2179,-2164,-2151,-2137,-2121,
+-2103,-2085,-2068,-2053,-2039,-2024,-2007,-1988,-1970,-1952,-1935,-1916,-1896,-1875,-1857,-1842,-1829,-1816,-1801,-1784,-1768,
+-1752,-1737,-1722,-1712,-1710,-1722,-1745,-1772,-1791,-1793,-1780,-1760,-1742,-1731,-1724,-1715,-1701,-1685,-1674,-1671,-1672,
+-1669,-1654,-1630,-1607,-1594,-1598,-1614,-1629,-1633,-1622,-1600,-1573,-1547,-1524,-1501,-1477,-1451,-1425,-1403,-1384,-1369,
+-1357,-1350,-1349,-1358,-1375,-1400,-1428,-1455,-1477,-1494,-1503,-1507,-1506,-1502,-1495,-1488,-1482,-1477,-1476,-1478,-1482,
+-1489,-1496,-1502,-1504,-1499,-1490,-1479,-1468,-1460,-1451,-1439,-1422,-1402,-1385,-1375,-1369,-1364,-1353,-1337,-1317,-1298,
+-1280,-1258,-1226,-1185,-1141,-1104,-1079,-1059,-1034,-997,-951,-910,-885,-875,-866,-848,-827,-825,-866,-953,-1059,
+-1136,-1144,-1076,-958,-836,-741,-673,-613,-540,-453,-372,-322,-312,-332,-362,-385,-400,-416,-438,-464,-484,
+-495,-500,-509,-527,-552,-573,-578,-568,-551,-539,-536,-540,-543,-539,-531,-522,-518,-518,-519,-519,-516,
+-513,-515,-523,-536,-550,-561,-563,-554,-537,-519,-507,-505,-508,-507,-494,-470,-444,-426,-425,-438,-461,
+-489,-527,-586,-672,-783,-902,-1007,-1083,-1125,-1143,-1154,-1169,-1192,-1216,-1236,-1247,-1252,-1256,-1263,-1276,-1290,
+-1301,-1307,-1308,-1308,-1312,-1322,-1336,-1349,-1357,-1359,-1356,-1355,-1356,-1361,-1367,-1371,-1373,-1376,-1380,-1387,-1394,
+-1400,-1402,-1402,-1402,-1402,-1402,-1403,-1403,-1404,-1406,-1410,-1415,-1419,-1419,-1418,-1416,-1416,-1416,-1415,-1412,-1408,
+-1404,-1400,-1396,-1392,-1385,-1379,-1374,-1375,-1381,-1391,-1403,-1415,-1426,-1436,-1441,-1443,-1440,-1436,-1435,-1437,-1442,
+-1446,-1446,-1442,-1435,-1428,-1421,-1414,-1404,-1392,-1381,-1374,-1370,-1366,-1360,-1351,-1343,-1339,-1340,-1345,-1349,-1350,
+-1347,-1345,-1344,-1346,-1349,-1353,-1360,-1372,-1386,-1400,-1410,-1411,-1407,-1400,-1394,-1388,-1380,-1371,-1362,-1356,-1359,
+-1369,-1386,-1405,-1425,-1447,-1470,-1492,-1509,-1520,-1525,-1529,-1534,-1542,-1550,-1557,-1561,-1563,-1568,-1576,-1587,-1599,
+-1608,-1614,-1619,-1624,-1632,-1642,-1652,-1661,-1667,-1669,-1669,-1671,-1675,-1682,-1690,-1697,-1702,-1707,-1713,-1719,-1725,
+-1728,-1727,-1723,-1719,-1719,-1719,-1718,-1711,-1701,-1689,-1681,-1677,-1675,-1672,-1664,-1652,-1640,-1630,-1621,-1610,-1595,
+-1578,-1561,-1547,-1537,-1527,-1518,-1509,-1500,-1495,-1492,-1488,-1481,-1469,-1455,-1439,-1424,-1410,-1395,-1379,-1361,-1344,
+-1326,-1309,-1292,-1277,-1264,-1254,-1246,-1238,-1229,-1218,-1208,-1198,-1190,-1184,-1179,-1173,-1166,-1158,-1149,-1138,-1126,
+-1114,-1103,-1095,-1089,-1083,-1075,-1065,-1056,-1048,-1042,-1036,-1030,-1021,-1010,-1001,-995,-992,-989,-986,-982,-978,
+-976,-976,-978,-978,-977,-974,-971,-968,-965,-961,-956,-949,-943,-938,-936,-936,-939,-943,-947,-952,-955,
+-957,-958,-959,-960,-963,-966,-970,-975,-980,-985,-990,-994,-996,-994,-990,-986,-984,-983,-981,-977,-973,
+-968,-965,-963,-961,-958,-953,-947,-942,-939,-937,-935,-933,-928,-922,-916,-909,-902,-892,-880,-867,-853,
+-838,-823,-808,-793,-781,-771,-764,-756,-746,-732,-716,-702,-691,-685,-681,-679,-678,-677,-674,-669,-659,
+-643,-623,-602,-584,-569,-555,-541,-523,-502,-482,-463,-446,-429,-410,-388,-362,-335,-308,-281,-254,-228,
+-204,-183,-166,-152,-139,-128,-120,-113,-108,-100,-89,-74,-58,-42,-25,-5,17,42,64,83,97,
+112,131,155,180,201,216,229,246,270,298,324,343,359,375,396,420,442,461,477,497,525,
+558,589,614,633,652,674,698,719,729,726,715,700,689,690,717,789,916,1088,1271,1416,1493,
+1500,1473,1460,1488,1556,1633,1692,1723,1740,1758,1781,1793,1775,1723,1655,1598,1569,1564,1566,1553,1522,
+1481,1445,1416,1386,1344,1285,1218,1160,1124,1116,1127,1146,1160,1166,1161,1149,1139,1133,1136,1143,1150,
+1152,1146,1137,1131,1130,1131,1129,1121,1111,1105,1108,1117,1123,1118,1100,1072,1044,1020,999,972,937,
+892,844,797,752,708,661,613,567,528,497,471,443,411,374,335,296,257,218,179,142,111,
+85,64,44,21,-2,-27,-52,-74,-95,-115,-134,-151,-164,-173,-181,-188,-195,-203,-212,-220,-230,
+-242,-254,-266,-276,-282,-286,-288,-288,-288,-286,-284,-280,-272,-258,-237,-211,-184,-160,-143,-133,-127,
+-121,-116,-112,-110,-111,-113,-113,-109,-99,-86,-71,-56,-44,-36,-32,-30,-29,-26,-21,-13,-3,
+6,16,27,40,56,75,95,115,133,151,169,189,212,237,262,287,309,331,354,380,410,
+444,479,515,549,583,617,652,685,717,746,775,808,845,885,926,964,997,1026,1054,1084,1117,
+1152,1188,1223,1256,1289,1322,1359,1399,1441,1480,1512,1537,1555,1573,1595,1622,1653,1686,1719,1751,1784,
+1815,1846,1874,1902,1930,1961,1994,2026,2055,2080,2104,2128,2155,2181,2204,2223,2240,2258,2283,2313,2346,
+2378,2406,2430,2451,2469,2486,2502,2519,2538,2557,2576,2592,2606,2621,2640,2663,2688,2712,2731,2747,2760,
+2772,2783,2793,2801,2807,2813,2818,2817,2809,2792,2768,2743,2721,2703,2689,2676,2664,2652,2642,2631,2615,
+2595,2571,2547,2526,2508,2493,2477,2463,2451,2442,2437,2433,2427,2419,2409,2399,2389,2380,2373,2367,2363,
+2360,2357,2352,2346,2340,2336,2331,2342,2335,2326,2313,2301,2291,2287,2285,2283,2280,2275,2272,2271,2274,
+2280,2289,2301,2316,2331,2344,2355,2367,2384,2407,2430,2442,2442,2439,2450,2488,2548,2605,2630,2608,2551,
+2493,2465,2481,2526,2568,2585,2574,2552,2543,2556,2585,2616,2636,2645,2654,2672,2702,2742,2781,2811,2828,
+2834,2833,2834,2841,2859,2886,2916,2942,2959,2968,2972,2978,2989,3003,3021,3041,3066,3098,3134,3169,3198,
+3218,3227,3231,3233,3237,3243,3249,3254,3257,3257,3257,3258,3261,3267,3277,3290,3306,3325,3342,3352,3353,
+3345,3335,3331,3341,3362,3385,3403,3411,3416,3429,3455,3490,3525,3550,3566,3584,3614,3662,3726,3796,3865,
+3926,3974,4003,4003,3978,3945,3931,3964,4047,4160,4262,4321,4327,4299,4269,4263,4285,4320,4349,4363,4363,
+4357,4350,4342,4331,4316,4305,4303,4310,4318,4318,4305,4283,4265,4262,4274,4296,4316,4330,4342,4358,4382,
+4408,4426,4429,4417,4401,4392,4392,4396,4391,4374,4350,4333,4334,4352,4376,4393,4397,4394,4393,4403,4422,
+4443,4460,4472,4482,4495,4507,4513,4507,4493,4478,4470,4468,4470,4470,4466,4464,4467,4479,4495,4508,4511,
+4506,4495,4484,4474,4464,4452,4440,4430,4424,4421,4417,4410,4398,4382,4366,4349,4334,4319,4305,4292,4279,
+4263,4244,4221,4194,4166,4138,4112,4088,4065,4043,4019,3992,3964,3936,3910,3887,3865,3842,3819,3797,3779,
+3766,3758,3751,3741,3723,3699,3671,3646,3626,3612,3603,3595,3592,3596,3615,3653,3706,3764,3817,3855,3881,
+3902,3927,3960,3994,4021,4035,4037,4033,4028,4021,4007,3983,3951,3917,3887,3860,3827,3781,3719,3648,3580,
+3522,3475,3435,3397,3360,3326,3296,3269,3241,3211,3180,3153,3133,3115,3096,3071,3040,3006,2975,2947,2921,
+2894,2866,2840,2816,2795,2773,2748,2720,2690,2660,2631,2599,2565,2529,2495,2462,2432,2402,2371,2338,2306,
+2276,2244,2210,2171,2130,2090,2053,2020,1987,1952,1916,1881,1849,1821,1793,1762,1725,1687,1649,1614,1581,
+1547,1510,1470,1430,1392,1355,1319,1282,1244,1204,1164,1123,1082,1040,997,957,919,883,849,814,776,
+736,695,654,613,573,534,495,457,421,387,355,323,290,255,218,181,143,105,66,25,-16,
+-60,-104,-148,-193,-237,-280,-319,-354,-386,-417,-452,-492,-535,-578,-619,-657,-693,-730,-769,-808,-848,
+-885,-921,-956,-991,-1028,-1065,-1102,-1138,-1171,-1203,-1235,-1269,-1305,-1342,-1378,-1411,-1440,-1465,-1490,-1518,-1551,
+-1587,-1623,-1656,-1685,-1711,-1739,-1768,-1798,-1827,-1853,-1875,-1896,-1918,-1940,-1963,-1985,-2006,-2028,-2051,-2075,-2098,
+-2118,-2134,-2148,-2164,-2183,-2203,-2223,-2240,-2253,-2264,-2275,-2288,-2304,-2322,-2338,-2353,-2365,-2373,-2380,-2386,-2394,
+-2402,-2410,-2414,-2414,-2413,-2414,-2421,-2432,-2444,-2455,-2461,-2465,-2467,-2469,-2471,-2472,-2471,-2469,-2467,-2465,-2464,
+-2459,-2451,-2441,-2433,-2429,-2430,-2430,-2428,-2419,-2408,-2397,-2391,-2387,-2384,-2377,-2366,-2353,-2341,-2330,-2321,-2309,
+-2293,-2275,-2257,-2241,-2227,-2213,-2197,-2180,-2163,-2148,-2136,-2123,-2109,-2093,-2077,-2061,-2046,-2032,-2017,-2001,-1985,
+-1969,-1954,-1939,-1920,-1899,-1878,-1859,-1843,-1829,-1815,-1800,-1785,-1772,-1760,-1748,-1734,-1721,-1715,-1722,-1744,-1772,
+-1794,-1800,-1788,-1768,-1749,-1737,-1729,-1720,-1704,-1684,-1668,-1662,-1662,-1662,-1652,-1632,-1610,-1597,-1600,-1617,-1636,
+-1646,-1641,-1624,-1602,-1581,-1565,-1554,-1543,-1529,-1511,-1490,-1469,-1449,-1433,-1420,-1409,-1401,-1396,-1397,-1407,-1427,
+-1456,-1487,-1513,-1528,-1531,-1524,-1516,-1510,-1510,-1515,-1521,-1525,-1526,-1526,-1526,-1527,-1527,-1524,-1517,-1508,-1498,
+-1491,-1486,-1480,-1471,-1457,-1442,-1427,-1413,-1399,-1381,-1359,-1335,-1314,-1294,-1275,-1251,-1221,-1187,-1154,-1123,-1091,
+-1055,-1017,-981,-955,-939,-923,-897,-864,-844,-864,-940,-1057,-1166,-1216,-1176,-1059,-914,-792,-716,-673,-630,
+-564,-481,-408,-373,-382,-418,-456,-478,-489,-499,-516,-540,-560,-571,-579,-591,-613,-636,-649,-642,-621,
+-599,-589,-592,-601,-603,-595,-581,-569,-565,-569,-572,-571,-565,-561,-564,-577,-597,-618,-631,-634,-625,
+-610,-595,-588,-590,-597,-600,-592,-572,-548,-530,-527,-538,-557,-582,-619,-677,-764,-874,-992,-1095,-1167,
+-1205,-1222,-1233,-1250,-1274,-1300,-1320,-1331,-1335,-1339,-1346,-1358,-1370,-1380,-1385,-1387,-1388,-1393,-1402,-1415,-1428,
+-1437,-1442,-1443,-1442,-1443,-1446,-1448,-1448,-1447,-1447,-1449,-1454,-1459,-1462,-1463,-1461,-1460,-1459,-1459,-1458,-1457,
+-1457,-1459,-1465,-1470,-1472,-1471,-1466,-1461,-1459,-1459,-1458,-1455,-1451,-1448,-1447,-1448,-1450,-1448,-1443,-1437,-1432,
+-1431,-1435,-1442,-1452,-1466,-1480,-1493,-1499,-1500,-1498,-1496,-1498,-1503,-1507,-1505,-1499,-1490,-1482,-1478,-1474,-1467,
+-1455,-1441,-1428,-1420,-1415,-1410,-1403,-1396,-1390,-1389,-1390,-1392,-1391,-1387,-1382,-1377,-1374,-1373,-1374,-1379,-1389,
+-1404,-1420,-1434,-1443,-1448,-1450,-1452,-1449,-1437,-1416,-1391,-1369,-1360,-1368,-1390,-1419,-1448,-1473,-1492,-1507,-1517,
+-1524,-1529,-1534,-1541,-1550,-1559,-1568,-1575,-1581,-1589,-1599,-1611,-1622,-1632,-1637,-1641,-1643,-1647,-1654,-1661,-1669,
+-1675,-1679,-1681,-1682,-1685,-1688,-1692,-1694,-1695,-1696,-1699,-1706,-1714,-1721,-1725,-1725,-1724,-1724,-1725,-1724,-1721,
+-1714,-1707,-1702,-1699,-1696,-1692,-1685,-1676,-1667,-1658,-1650,-1639,-1625,-1610,-1594,-1580,-1567,-1552,-1536,-1520,-1507,
+-1499,-1494,-1490,-1483,-1472,-1458,-1444,-1431,-1417,-1401,-1383,-1364,-1344,-1326,-1309,-1292,-1276,-1261,-1248,-1237,-1227,
+-1218,-1207,-1196,-1186,-1178,-1170,-1163,-1157,-1151,-1147,-1143,-1139,-1134,-1127,-1119,-1112,-1105,-1099,-1091,-1081,-1070,
+-1060,-1052,-1045,-1036,-1026,-1015,-1005,-996,-989,-984,-978,-972,-968,-967,-969,-971,-972,-970,-967,-964,-962,
+-961,-960,-955,-949,-942,-938,-937,-938,-941,-943,-946,-949,-953,-957,-962,-966,-970,-973,-976,-979,-982,
+-985,-989,-994,-998,-1000,-1001,-1000,-999,-997,-996,-995,-993,-991,-989,-987,-984,-979,-971,-963,-956,-953,
+-952,-952,-951,-948,-942,-937,-932,-928,-923,-915,-904,-890,-875,-859,-842,-825,-807,-791,-777,-765,-755,
+-743,-729,-716,-704,-695,-689,-684,-681,-678,-677,-676,-671,-661,-646,-626,-607,-591,-579,-567,-554,-537,
+-518,-498,-479,-462,-443,-422,-399,-375,-350,-325,-299,-273,-247,-223,-204,-187,-172,-157,-145,-135,-129,
+-124,-117,-104,-88,-71,-54,-37,-17,6,33,57,77,92,107,126,149,172,190,201,213,230,
+255,284,309,328,342,358,379,404,428,448,466,487,516,549,578,599,613,629,652,680,701,
+707,694,671,648,638,653,704,803,953,1140,1329,1474,1545,1546,1510,1484,1495,1540,1592,1624,1632,
+1632,1647,1681,1718,1732,1709,1658,1603,1563,1541,1524,1497,1456,1411,1373,1346,1321,1287,1240,1186,1143,
+1122,1126,1144,1164,1174,1173,1162,1147,1133,1125,1123,1128,1136,1142,1144,1143,1142,1143,1145,1142,1134,
+1122,1111,1108,1111,1117,1116,1104,1083,1058,1037,1019,1000,974,940,899,853,808,763,721,682,647,
+617,591,565,534,496,455,412,370,329,286,242,197,155,119,90,66,44,24,3,-15,-34,
+-52,-69,-84,-97,-105,-111,-115,-121,-129,-140,-151,-163,-175,-188,-202,-215,-226,-234,-237,-236,-234,
+-233,-234,-235,-234,-227,-213,-192,-167,-142,-121,-108,-101,-97,-93,-86,-77,-67,-58,-50,-43,-33,
+-20,-4,10,24,33,36,37,36,37,40,47,56,66,77,88,100,115,132,151,170,189,
+206,223,239,257,277,299,323,346,369,393,419,449,480,512,544,573,602,631,660,689,714,
+736,757,781,811,849,892,935,976,1012,1042,1069,1095,1122,1153,1188,1223,1258,1289,1318,1347,1380,
+1416,1454,1489,1517,1541,1562,1587,1617,1649,1682,1713,1743,1773,1805,1838,1868,1895,1919,1944,1973,2003,
+2034,2062,2086,2109,2132,2156,2179,2200,2219,2239,2262,2291,2324,2357,2387,2412,2432,2449,2465,2482,2500,
+2520,2540,2560,2580,2601,2625,2651,2676,2698,2715,2728,2740,2753,2768,2780,2788,2792,2795,2801,2808,2813,
+2812,2800,2782,2760,2739,2721,2705,2689,2675,2661,2647,2630,2610,2585,2559,2537,2520,2507,2495,2483,2471,
+2461,2457,2457,2457,2453,2445,2433,2421,2410,2402,2396,2390,2386,2381,2376,2369,2361,2354,2348,2342,2348,
+2344,2339,2332,2323,2315,2310,2309,2308,2306,2303,2300,2300,2306,2316,2329,2342,2355,2366,2377,2392,2413,
+2438,2461,2472,2466,2448,2434,2442,2482,2539,2585,2593,2553,2485,2426,2408,2438,2494,2544,2564,2555,2538,
+2537,2563,2606,2649,2676,2687,2693,2707,2736,2774,2813,2842,2856,2857,2851,2846,2849,2865,2889,2918,2942,
+2959,2968,2975,2984,2999,3016,3035,3053,3075,3102,3136,3172,3204,3226,3236,3239,3240,3245,3253,3262,3268,
+3271,3273,3275,3280,3285,3290,3293,3299,3313,3335,3361,3381,3387,3377,3361,3352,3359,3381,3407,3425,3432,
+3437,3454,3489,3537,3580,3606,3612,3613,3630,3674,3743,3824,3898,3952,3979,3979,3958,3931,3917,3937,4003,
+4101,4204,4277,4299,4278,4241,4217,4222,4250,4283,4305,4311,4310,4310,4313,4314,4309,4298,4289,4290,4300,
+4310,4309,4294,4272,4255,4256,4273,4298,4319,4334,4345,4361,4384,4408,4425,4430,4424,4417,4417,4423,4429,
+4423,4404,4377,4357,4352,4362,4380,4393,4397,4394,4394,4403,4419,4437,4453,4465,4475,4486,4497,4502,4500,
+4491,4480,4473,4472,4475,4478,4480,4481,4484,4491,4500,4506,4506,4500,4490,4478,4466,4455,4446,4439,4434,
+4430,4427,4421,4410,4395,4377,4359,4342,4327,4315,4303,4292,4280,4264,4244,4219,4192,4163,4134,4109,4085,
+4063,4041,4017,3991,3965,3941,3920,3900,3880,3857,3831,3806,3788,3780,3781,3785,3783,3770,3745,3713,3681,
+3656,3642,3637,3639,3647,3662,3685,3717,3752,3785,3810,3827,3843,3868,3908,3959,4010,4048,4065,4065,4057,
+4050,4044,4035,4017,3990,3959,3926,3890,3845,3785,3711,3634,3567,3518,3485,3461,3436,3408,3376,3346,3318,
+3290,3258,3225,3193,3166,3145,3127,3106,3081,3052,3021,2991,2961,2931,2902,2875,2851,2830,2810,2786,2759,
+2727,2693,2659,2625,2590,2555,2522,2490,2458,2425,2391,2355,2321,2288,2256,2223,2188,2150,2111,2075,2041,
+2007,1973,1938,1903,1870,1839,1809,1777,1743,1706,1670,1635,1601,1566,1529,1490,1449,1409,1371,1335,1300,
+1263,1226,1186,1146,1105,1064,1024,985,948,913,878,842,805,766,725,684,643,603,566,529,493,
+457,420,384,348,313,279,244,209,172,135,96,56,15,-27,-72,-119,-165,-210,-250,-285,-315,
+-346,-381,-421,-465,-509,-550,-587,-621,-656,-694,-735,-775,-813,-848,-882,-918,-955,-994,-1031,-1065,-1096,
+-1127,-1160,-1195,-1232,-1270,-1307,-1342,-1374,-1402,-1428,-1454,-1482,-1513,-1547,-1582,-1615,-1644,-1672,-1700,-1730,-1759,
+-1787,-1813,-1836,-1858,-1882,-1906,-1929,-1951,-1971,-1992,-2014,-2039,-2062,-2082,-2098,-2114,-2131,-2152,-2174,-2195,-2211,
+-2222,-2231,-2242,-2255,-2272,-2290,-2307,-2321,-2333,-2343,-2350,-2357,-2364,-2371,-2376,-2380,-2381,-2383,-2387,-2397,-2411,
+-2425,-2436,-2441,-2442,-2442,-2444,-2448,-2451,-2452,-2451,-2449,-2447,-2446,-2443,-2436,-2427,-2418,-2413,-2413,-2415,-2415,
+-2410,-2400,-2389,-2381,-2375,-2371,-2364,-2353,-2339,-2327,-2317,-2308,-2298,-2284,-2267,-2248,-2231,-2215,-2200,-2185,-2167,
+-2151,-2136,-2123,-2111,-2098,-2083,-2068,-2054,-2041,-2027,-2012,-1996,-1981,-1967,-1955,-1941,-1925,-1906,-1886,-1868,-1852,
+-1836,-1819,-1800,-1783,-1770,-1761,-1751,-1739,-1727,-1720,-1726,-1747,-1776,-1800,-1806,-1794,-1772,-1751,-1737,-1730,-1722,
+-1706,-1684,-1664,-1654,-1654,-1657,-1653,-1639,-1620,-1605,-1605,-1620,-1642,-1659,-1664,-1654,-1638,-1622,-1612,-1609,-1609,
+-1603,-1590,-1570,-1545,-1523,-1504,-1489,-1472,-1449,-1421,-1395,-1382,-1390,-1420,-1465,-1510,-1543,-1558,-1557,-1549,-1545,
+-1548,-1556,-1564,-1567,-1563,-1555,-1549,-1547,-1546,-1545,-1540,-1532,-1524,-1520,-1519,-1518,-1514,-1504,-1488,-1469,-1450,
+-1431,-1410,-1386,-1361,-1337,-1314,-1293,-1271,-1245,-1215,-1182,-1147,-1113,-1081,-1054,-1034,-1019,-1002,-973,-931,-891,
+-879,-922,-1018,-1134,-1216,-1217,-1129,-987,-849,-761,-730,-724,-699,-636,-548,-473,-442,-459,-504,-548,-574,
+-586,-595,-611,-630,-645,-652,-657,-668,-685,-701,-703,-687,-661,-640,-636,-645,-656,-655,-642,-623,-611,
+-609,-615,-618,-614,-605,-600,-605,-623,-648,-673,-691,-697,-694,-687,-681,-683,-692,-704,-712,-707,-690,
+-669,-653,-649,-658,-675,-699,-733,-787,-866,-968,-1076,-1170,-1236,-1273,-1293,-1309,-1330,-1357,-1385,-1406,-1420,
+-1428,-1434,-1441,-1449,-1456,-1461,-1464,-1466,-1468,-1473,-1480,-1490,-1500,-1510,-1517,-1522,-1525,-1527,-1527,-1525,-1521,
+-1517,-1514,-1514,-1516,-1519,-1521,-1520,-1519,-1518,-1518,-1517,-1516,-1513,-1511,-1512,-1516,-1521,-1524,-1523,-1519,-1515,
+-1512,-1509,-1505,-1499,-1491,-1486,-1486,-1492,-1501,-1507,-1508,-1505,-1500,-1494,-1490,-1489,-1493,-1504,-1519,-1536,-1550,
+-1557,-1559,-1558,-1558,-1559,-1559,-1556,-1549,-1542,-1539,-1539,-1540,-1535,-1522,-1504,-1486,-1473,-1466,-1462,-1458,-1452,
+-1447,-1443,-1440,-1438,-1434,-1428,-1421,-1415,-1409,-1404,-1401,-1401,-1406,-1416,-1429,-1442,-1455,-1469,-1484,-1499,-1509,
+-1507,-1491,-1465,-1439,-1425,-1427,-1444,-1467,-1488,-1503,-1511,-1516,-1522,-1530,-1540,-1552,-1562,-1571,-1578,-1584,-1590,
+-1598,-1607,-1619,-1631,-1643,-1654,-1661,-1667,-1670,-1672,-1674,-1676,-1679,-1682,-1685,-1688,-1691,-1694,-1697,-1697,-1696,
+-1692,-1689,-1688,-1692,-1700,-1709,-1717,-1722,-1725,-1726,-1727,-1728,-1726,-1723,-1719,-1714,-1711,-1708,-1704,-1699,-1694,
+-1690,-1685,-1678,-1667,-1653,-1637,-1623,-1610,-1597,-1581,-1563,-1543,-1526,-1514,-1507,-1500,-1491,-1479,-1465,-1451,-1438,
+-1425,-1410,-1392,-1372,-1352,-1334,-1316,-1298,-1279,-1260,-1243,-1229,-1218,-1208,-1199,-1189,-1179,-1170,-1161,-1152,-1143,
+-1137,-1133,-1132,-1131,-1129,-1126,-1120,-1113,-1107,-1101,-1094,-1086,-1077,-1068,-1060,-1053,-1046,-1038,-1029,-1019,-1011,
+-1002,-993,-984,-976,-971,-969,-969,-970,-969,-965,-960,-956,-955,-955,-954,-951,-946,-940,-938,-938,-940,
+-943,-944,-946,-948,-952,-959,-965,-971,-975,-978,-981,-983,-986,-990,-993,-997,-1000,-1003,-1005,-1007,-1010,
+-1011,-1013,-1013,-1012,-1011,-1009,-1007,-1002,-996,-987,-979,-972,-969,-969,-968,-966,-960,-953,-947,-943,-940,
+-936,-930,-921,-909,-895,-880,-863,-844,-825,-806,-788,-773,-758,-742,-727,-713,-702,-693,-686,-680,-674,
+-671,-670,-670,-668,-662,-649,-634,-618,-606,-596,-586,-573,-557,-538,-519,-500,-481,-461,-439,-416,-394,
+-372,-348,-323,-295,-269,-246,-227,-211,-195,-178,-161,-148,-140,-133,-126,-114,-99,-83,-68,-53,-34,
+-11,15,41,62,80,96,116,139,160,175,187,200,219,245,274,297,313,326,342,365,394,
+421,443,463,486,514,544,570,587,600,616,639,664,680,678,657,627,602,596,618,678,787,
+946,1141,1336,1487,1562,1564,1529,1505,1522,1572,1623,1644,1628,1599,1590,1617,1666,1704,1706,1667,1605,
+1546,1502,1469,1437,1398,1357,1321,1293,1268,1239,1202,1165,1140,1135,1148,1166,1179,1180,1169,1154,1138,
+1125,1115,1111,1112,1119,1129,1139,1147,1152,1157,1159,1158,1150,1137,1122,1111,1108,1111,1111,1105,1090,
+1070,1052,1037,1024,1007,983,950,911,870,833,801,773,749,726,702,673,638,596,551,505,460,
+414,366,312,255,197,144,99,64,39,20,7,-3,-13,-25,-37,-50,-62,-70,-75,-78,-80,
+-85,-91,-100,-109,-119,-130,-142,-155,-168,-176,-180,-180,-178,-176,-176,-176,-175,-169,-157,-139,-118,
+-97,-79,-66,-56,-49,-42,-33,-21,-7,8,22,36,49,61,72,82,89,93,95,96,97,
+99,102,107,113,122,133,149,166,184,201,216,229,243,259,277,297,318,340,361,381,401,
+421,445,474,505,538,569,596,618,638,658,678,696,710,723,736,755,783,821,866,914,963,
+1009,1049,1082,1109,1131,1154,1182,1215,1249,1279,1304,1325,1348,1376,1412,1450,1485,1516,1543,1571,1602,
+1635,1667,1696,1725,1756,1790,1826,1858,1884,1904,1922,1943,1970,2001,2032,2059,2083,2105,2128,2154,2181,
+2208,2235,2263,2291,2321,2350,2376,2398,2416,2433,2450,2469,2490,2510,2529,2548,2568,2591,2619,2648,2673,
+2692,2702,2709,2716,2727,2740,2753,2763,2772,2782,2793,2806,2815,2817,2811,2797,2779,2760,2739,2715,2691,
+2668,2649,2633,2619,2600,2579,2556,2538,2527,2520,2514,2506,2496,2487,2482,2480,2477,2471,2459,2446,2434,
+2425,2418,2413,2408,2402,2397,2390,2382,2372,2362,2354,2348,2358,2357,2356,2352,2345,2335,2327,2322,2320,
+2320,2321,2324,2331,2342,2356,2369,2380,2389,2398,2412,2433,2458,2481,2489,2478,2448,2414,2397,2412,2457,
+2511,2543,2530,2472,2398,2346,2345,2394,2467,2530,2560,2563,2558,2569,2603,2648,2686,2705,2708,2708,2718,
+2744,2781,2817,2843,2855,2857,2855,2855,2862,2876,2897,2919,2940,2956,2968,2980,2995,3013,3033,3052,3069,
+3089,3114,3146,3182,3214,3236,3246,3250,3253,3261,3272,3282,3287,3288,3289,3294,3304,3315,3321,3322,3322,
+3330,3352,3383,3409,3419,3410,3393,3383,3391,3415,3441,3457,3460,3462,3480,3521,3576,3624,3651,3654,3652,
+3666,3709,3778,3854,3915,3947,3949,3931,3910,3903,3925,3982,4068,4163,4240,4276,4268,4232,4196,4183,4198,
+4228,4256,4270,4271,4268,4270,4276,4281,4282,4279,4281,4289,4302,4308,4300,4278,4253,4239,4245,4269,4300,
+4327,4345,4358,4372,4389,4407,4420,4426,4428,4430,4437,4446,4451,4446,4430,4408,4389,4378,4377,4381,4383,
+4382,4382,4386,4399,4417,4438,4456,4470,4481,4490,4498,4503,4502,4496,4488,4480,4477,4479,4484,4491,4497,
+4501,4503,4503,4502,4499,4494,4487,4479,4469,4460,4452,4446,4441,4434,4426,4416,4403,4388,4372,4356,4340,
+4325,4311,4299,4287,4274,4257,4236,4210,4182,4152,4125,4100,4079,4059,4040,4019,3995,3970,3946,3924,3903,
+3881,3856,3828,3803,3787,3783,3790,3802,3810,3805,3787,3758,3726,3697,3677,3667,3667,3674,3689,3710,3734,
+3756,3773,3782,3789,3803,3834,3885,3949,4011,4057,4080,4083,4077,4070,4066,4061,4050,4030,4002,3969,3928,
+3875,3806,3727,3649,3585,3542,3515,3495,3470,3439,3406,3377,3354,3332,3307,3276,3241,3208,3181,3159,3139,
+3117,3091,3060,3028,2996,2963,2931,2902,2877,2857,2838,2817,2791,2760,2725,2688,2651,2615,2580,2548,2517,
+2487,2455,2420,2383,2344,2307,2272,2238,2204,2168,2132,2095,2060,2027,1996,1963,1929,1894,1859,1824,1790,
+1757,1723,1689,1654,1618,1582,1545,1507,1469,1430,1392,1355,1319,1282,1245,1206,1166,1127,1089,1054,1018,
+983,946,908,870,832,793,752,711,670,632,596,563,529,494,455,415,376,339,304,270,235,
+199,161,123,83,43,0,-45,-92,-138,-182,-219,-251,-281,-312,-348,-391,-436,-481,-521,-556,-591,
+-627,-666,-707,-746,-781,-813,-846,-881,-919,-957,-993,-1025,-1056,-1088,-1124,-1162,-1201,-1237,-1270,-1301,-1331,
+-1360,-1389,-1418,-1448,-1479,-1511,-1543,-1575,-1604,-1633,-1663,-1693,-1722,-1750,-1774,-1797,-1820,-1845,-1871,-1896,-1918,
+-1938,-1957,-1978,-2001,-2024,-2045,-2064,-2082,-2101,-2124,-2146,-2165,-2178,-2186,-2194,-2206,-2222,-2241,-2259,-2275,-2289,
+-2301,-2311,-2321,-2329,-2336,-2342,-2346,-2349,-2353,-2358,-2366,-2378,-2394,-2409,-2420,-2423,-2421,-2418,-2417,-2421,-2427,
+-2432,-2434,-2434,-2433,-2432,-2430,-2425,-2418,-2410,-2404,-2403,-2403,-2403,-2399,-2392,-2383,-2376,-2371,-2365,-2356,-2343,
+-2327,-2312,-2301,-2292,-2284,-2272,-2257,-2240,-2223,-2208,-2194,-2179,-2164,-2148,-2134,-2121,-2108,-2095,-2081,-2067,-2054,
+-2043,-2030,-2016,-2001,-1985,-1970,-1957,-1943,-1927,-1911,-1894,-1879,-1864,-1848,-1829,-1808,-1788,-1773,-1764,-1756,-1745,
+-1734,-1727,-1734,-1756,-1786,-1810,-1817,-1803,-1777,-1752,-1737,-1730,-1723,-1710,-1689,-1668,-1656,-1656,-1661,-1662,-1652,
+-1634,-1618,-1615,-1627,-1652,-1676,-1691,-1692,-1683,-1672,-1665,-1665,-1666,-1661,-1646,-1622,-1596,-1574,-1558,-1546,-1528,
+-1498,-1454,-1407,-1374,-1369,-1397,-1448,-1507,-1555,-1582,-1590,-1587,-1584,-1586,-1592,-1596,-1595,-1587,-1578,-1571,-1569,
+-1569,-1568,-1564,-1556,-1550,-1548,-1551,-1554,-1551,-1540,-1522,-1500,-1480,-1462,-1444,-1425,-1401,-1375,-1347,-1318,-1289,
+-1257,-1224,-1192,-1162,-1136,-1116,-1102,-1090,-1075,-1049,-1010,-966,-936,-944,-999,-1085,-1163,-1187,-1132,-1015,-884,
+-792,-766,-788,-813,-797,-728,-634,-557,-529,-550,-597,-640,-666,-678,-689,-705,-721,-730,-731,-729,-733,
+-743,-750,-745,-724,-698,-681,-680,-690,-698,-695,-679,-661,-652,-654,-661,-663,-657,-646,-641,-648,-670,
+-700,-731,-756,-772,-780,-783,-786,-793,-804,-816,-824,-821,-807,-787,-773,-770,-780,-799,-824,-857,-906,
+-975,-1062,-1154,-1235,-1295,-1333,-1359,-1382,-1409,-1439,-1466,-1489,-1505,-1519,-1530,-1540,-1546,-1548,-1548,-1548,-1549,
+-1553,-1557,-1562,-1567,-1573,-1580,-1587,-1592,-1595,-1596,-1594,-1590,-1584,-1579,-1575,-1573,-1574,-1577,-1579,-1579,-1580,
+-1580,-1581,-1581,-1577,-1571,-1565,-1561,-1562,-1566,-1571,-1573,-1572,-1570,-1567,-1564,-1557,-1548,-1537,-1530,-1529,-1536,
+-1547,-1557,-1564,-1566,-1563,-1558,-1553,-1548,-1546,-1550,-1560,-1574,-1589,-1600,-1605,-1606,-1605,-1605,-1605,-1604,-1601,
+-1599,-1598,-1599,-1599,-1595,-1583,-1567,-1549,-1536,-1527,-1522,-1516,-1509,-1500,-1492,-1485,-1479,-1474,-1467,-1461,-1454,
+-1447,-1441,-1435,-1430,-1429,-1431,-1436,-1445,-1456,-1472,-1493,-1517,-1539,-1552,-1554,-1545,-1532,-1523,-1522,-1527,-1533,
+-1535,-1532,-1525,-1523,-1528,-1542,-1563,-1584,-1601,-1610,-1612,-1611,-1611,-1614,-1622,-1632,-1643,-1654,-1665,-1677,-1689,
+-1698,-1703,-1704,-1700,-1696,-1692,-1690,-1691,-1694,-1697,-1701,-1703,-1703,-1701,-1697,-1694,-1695,-1699,-1706,-1714,-1720,
+-1724,-1726,-1728,-1729,-1730,-1729,-1727,-1724,-1721,-1716,-1712,-1708,-1706,-1704,-1701,-1695,-1685,-1671,-1656,-1644,-1634,
+-1623,-1611,-1593,-1573,-1554,-1538,-1526,-1516,-1505,-1491,-1477,-1462,-1449,-1435,-1419,-1401,-1382,-1363,-1345,-1328,-1309,
+-1289,-1269,-1249,-1232,-1218,-1207,-1196,-1186,-1175,-1166,-1156,-1146,-1137,-1128,-1121,-1117,-1114,-1112,-1108,-1102,-1096,
+-1090,-1085,-1079,-1073,-1067,-1061,-1056,-1052,-1048,-1043,-1037,-1031,-1024,-1016,-1006,-996,-986,-979,-976,-975,-975,
+-972,-967,-960,-954,-951,-950,-949,-946,-943,-939,-938,-939,-942,-945,-948,-950,-952,-957,-963,-969,-974,
+-977,-979,-980,-983,-988,-992,-996,-999,-1000,-1001,-1003,-1007,-1012,-1017,-1022,-1025,-1025,-1024,-1022,-1019,-1015,
+-1010,-1004,-998,-993,-989,-985,-980,-973,-964,-957,-951,-946,-943,-939,-933,-926,-918,-907,-894,-879,-860,
+-840,-821,-802,-784,-766,-747,-729,-714,-703,-694,-685,-677,-668,-663,-662,-664,-665,-663,-656,-645,-633,
+-623,-613,-603,-591,-575,-558,-541,-523,-504,-483,-461,-438,-416,-395,-371,-345,-317,-291,-269,-253,-238,
+-223,-204,-184,-167,-153,-144,-134,-123,-110,-97,-85,-72,-55,-32,-5,20,42,61,81,103,126,
+146,162,174,188,209,235,261,282,297,310,328,355,385,414,438,459,483,510,538,561,577,
+590,605,625,642,648,635,609,581,565,568,593,650,749,898,1089,1287,1444,1524,1530,1501,1490,
+1528,1607,1684,1715,1688,1629,1584,1583,1622,1666,1679,1647,1582,1509,1450,1409,1377,1345,1310,1278,1251,
+1229,1207,1182,1160,1148,1148,1158,1168,1168,1157,1141,1126,1116,1110,1105,1100,1099,1103,1113,1126,1138,
+1148,1155,1159,1161,1157,1147,1133,1121,1113,1112,1112,1109,1098,1082,1066,1054,1044,1033,1015,990,960,
+931,905,883,865,846,823,797,765,728,687,644,599,555,509,459,403,339,270,202,140,88,
+49,21,3,-7,-15,-24,-35,-48,-60,-70,-74,-75,-74,-72,-73,-76,-79,-84,-90,-98,-108,
+-118,-127,-132,-132,-130,-126,-122,-118,-112,-102,-90,-75,-60,-45,-29,-13,1,15,28,40,53,
+67,82,98,111,120,124,124,122,119,118,119,123,128,132,135,137,139,147,162,183,208,
+230,246,255,261,268,281,301,327,355,380,401,416,429,443,461,487,519,553,585,611,629,
+643,654,664,674,683,693,705,722,746,778,817,864,919,979,1038,1087,1122,1145,1162,1182,1209,
+1242,1274,1298,1315,1330,1352,1384,1423,1462,1497,1527,1557,1589,1623,1658,1691,1722,1753,1788,1825,1859,
+1885,1903,1917,1934,1957,1987,2018,2046,2070,2091,2113,2140,2171,2204,2236,2266,2294,2320,2343,2363,2381,
+2397,2413,2430,2450,2471,2491,2510,2528,2548,2572,2599,2626,2650,2667,2678,2685,2692,2701,2711,2723,2735,
+2748,2764,2780,2794,2801,2800,2794,2785,2775,2761,2742,2715,2685,2658,2640,2630,2623,2611,2594,2574,2557,
+2547,2542,2539,2533,2524,2513,2505,2499,2492,2483,2472,2460,2450,2443,2438,2432,2425,2417,2410,2402,2394,
+2383,2372,2363,2358,2376,2374,2373,2368,2359,2347,2337,2332,2334,2340,2349,2360,2372,2384,2395,2403,2409,
+2414,2424,2440,2461,2481,2489,2478,2449,2413,2388,2390,2425,2480,2529,2544,2510,2439,2362,2315,2319,2370,
+2442,2506,2544,2560,2572,2593,2626,2660,2682,2688,2685,2686,2701,2731,2767,2799,2821,2834,2843,2852,2863,
+2876,2891,2908,2926,2943,2960,2976,2992,3009,3028,3047,3067,3086,3107,3133,3164,3197,3225,3244,3254,3259,
+3265,3276,3290,3301,3306,3306,3308,3317,3331,3346,3354,3354,3352,3359,3380,3410,3437,3447,3439,3423,3416,
+3427,3453,3479,3491,3491,3490,3506,3545,3597,3644,3671,3680,3687,3710,3757,3819,3875,3906,3908,3891,3873,
+3872,3898,3954,4031,4114,4185,4228,4236,4215,4183,4160,4158,4177,4203,4223,4232,4233,4233,4238,4245,4251,
+4255,4261,4272,4288,4301,4301,4284,4256,4230,4221,4234,4265,4302,4333,4357,4373,4388,4402,4415,4426,4432,
+4437,4442,4448,4454,4457,4454,4446,4434,4422,4409,4397,4386,4376,4370,4369,4377,4393,4415,4438,4460,4477,
+4490,4498,4504,4507,4508,4506,4501,4495,4491,4490,4494,4499,4504,4505,4502,4497,4492,4490,4488,4485,4480,
+4473,4465,4458,4451,4443,4433,4420,4405,4391,4378,4366,4351,4335,4318,4301,4286,4273,4259,4242,4221,4195,
+4166,4137,4111,4088,4070,4054,4038,4020,3997,3971,3942,3915,3888,3862,3836,3811,3792,3781,3783,3793,3806,
+3815,3814,3802,3781,3757,3734,3714,3699,3690,3687,3693,3705,3722,3738,3749,3755,3760,3774,3805,3857,3924,
+3994,4051,4087,4102,4103,4098,4091,4084,4073,4057,4035,4007,3968,3913,3843,3764,3687,3625,3582,3552,3524,
+3489,3448,3408,3377,3358,3346,3331,3308,3277,3244,3215,3191,3170,3147,3120,3090,3058,3025,2993,2962,2933,
+2907,2885,2865,2843,2818,2788,2754,2718,2681,2644,2607,2572,2539,2508,2477,2445,2409,2370,2331,2293,2259,
+2225,2191,2154,2117,2080,2048,2018,1988,1955,1919,1880,1843,1808,1776,1744,1710,1673,1634,1595,1557,1520,
+1484,1447,1409,1372,1336,1299,1262,1222,1182,1144,1109,1077,1046,1013,976,937,896,856,817,777,738,
+698,660,626,593,560,524,485,445,404,366,331,296,260,223,185,145,104,63,19,-26,-71,
+-115,-156,-191,-224,-255,-288,-325,-367,-409,-451,-489,-525,-561,-599,-639,-679,-716,-750,-782,-814,-848,
+-884,-920,-954,-987,-1020,-1056,-1095,-1135,-1172,-1205,-1233,-1259,-1287,-1317,-1348,-1380,-1412,-1445,-1477,-1509,-1540,
+-1569,-1599,-1630,-1662,-1692,-1720,-1744,-1765,-1788,-1813,-1839,-1865,-1888,-1907,-1925,-1945,-1966,-1988,-2010,-2031,-2051,
+-2073,-2096,-2117,-2132,-2141,-2147,-2156,-2171,-2191,-2212,-2230,-2244,-2255,-2265,-2278,-2291,-2302,-2310,-2315,-2319,-2324,
+-2330,-2338,-2348,-2360,-2374,-2388,-2399,-2403,-2402,-2398,-2396,-2399,-2406,-2415,-2421,-2423,-2422,-2419,-2416,-2412,-2408,
+-2404,-2399,-2397,-2395,-2393,-2389,-2383,-2377,-2372,-2367,-2361,-2351,-2336,-2320,-2305,-2293,-2285,-2278,-2268,-2254,-2239,
+-2224,-2210,-2196,-2182,-2167,-2152,-2139,-2126,-2114,-2102,-2088,-2075,-2063,-2052,-2041,-2028,-2013,-1997,-1980,-1965,-1949,
+-1932,-1916,-1901,-1888,-1876,-1861,-1843,-1823,-1803,-1788,-1778,-1769,-1758,-1746,-1739,-1744,-1764,-1794,-1819,-1826,-1813,
+-1787,-1759,-1741,-1733,-1727,-1716,-1697,-1678,-1665,-1664,-1669,-1673,-1666,-1650,-1634,-1627,-1638,-1662,-1690,-1712,-1722,
+-1722,-1717,-1713,-1712,-1709,-1699,-1679,-1651,-1624,-1605,-1596,-1590,-1576,-1546,-1498,-1443,-1401,-1386,-1406,-1452,-1509,
+-1560,-1594,-1610,-1614,-1614,-1615,-1616,-1615,-1610,-1603,-1597,-1595,-1596,-1597,-1594,-1586,-1577,-1571,-1572,-1578,-1583,
+-1581,-1568,-1548,-1526,-1508,-1495,-1484,-1470,-1449,-1422,-1389,-1353,-1315,-1278,-1245,-1216,-1194,-1178,-1166,-1152,-1134,
+-1106,-1071,-1034,-1006,-1002,-1028,-1078,-1126,-1141,-1099,-1006,-893,-809,-786,-823,-881,-912,-883,-802,-706,-638,
+-622,-649,-693,-727,-744,-752,-763,-781,-799,-807,-804,-797,-796,-800,-802,-794,-771,-745,-726,-720,-725,
+-729,-725,-713,-702,-699,-705,-713,-715,-709,-701,-698,-708,-731,-763,-799,-834,-863,-884,-896,-900,-903,
+-907,-913,-918,-916,-906,-893,-884,-887,-903,-930,-961,-997,-1043,-1102,-1173,-1247,-1314,-1365,-1401,-1428,-1452,
+-1477,-1501,-1524,-1546,-1568,-1591,-1614,-1632,-1642,-1644,-1641,-1639,-1640,-1642,-1645,-1646,-1646,-1648,-1651,-1655,-1657,
+-1657,-1654,-1650,-1646,-1642,-1637,-1634,-1632,-1632,-1635,-1639,-1642,-1645,-1647,-1647,-1645,-1640,-1630,-1620,-1612,-1609,
+-1611,-1616,-1620,-1621,-1621,-1619,-1616,-1610,-1602,-1593,-1585,-1583,-1588,-1596,-1605,-1612,-1615,-1616,-1616,-1614,-1611,
+-1607,-1606,-1609,-1616,-1625,-1633,-1637,-1638,-1638,-1640,-1645,-1650,-1653,-1654,-1652,-1649,-1645,-1639,-1631,-1622,-1612,
+-1604,-1596,-1587,-1576,-1563,-1549,-1536,-1527,-1520,-1514,-1508,-1502,-1495,-1488,-1480,-1472,-1464,-1457,-1453,-1452,-1455,
+-1463,-1474,-1492,-1514,-1538,-1561,-1580,-1592,-1600,-1603,-1605,-1603,-1595,-1582,-1565,-1549,-1541,-1546,-1563,-1590,-1618,
+-1639,-1650,-1651,-1646,-1641,-1640,-1644,-1650,-1657,-1663,-1672,-1684,-1700,-1715,-1727,-1731,-1729,-1721,-1712,-1705,-1699,
+-1697,-1697,-1700,-1705,-1711,-1716,-1718,-1718,-1718,-1719,-1721,-1723,-1726,-1727,-1727,-1728,-1729,-1731,-1733,-1735,-1735,
+-1734,-1731,-1726,-1720,-1715,-1711,-1707,-1701,-1692,-1681,-1670,-1660,-1653,-1647,-1637,-1623,-1604,-1584,-1565,-1550,-1536,
+-1522,-1507,-1492,-1476,-1461,-1446,-1430,-1413,-1394,-1375,-1358,-1342,-1325,-1308,-1289,-1270,-1253,-1237,-1221,-1207,-1192,
+-1179,-1167,-1156,-1146,-1135,-1124,-1113,-1103,-1095,-1089,-1083,-1077,-1071,-1065,-1060,-1054,-1050,-1045,-1042,-1039,-1037,
+-1035,-1033,-1030,-1026,-1022,-1016,-1008,-999,-990,-983,-979,-978,-979,-977,-973,-967,-960,-955,-951,-949,-946,
+-943,-940,-939,-941,-944,-948,-952,-955,-958,-962,-967,-972,-976,-979,-981,-984,-988,-993,-998,-1002,-1004,
+-1004,-1004,-1004,-1006,-1010,-1014,-1019,-1023,-1026,-1026,-1025,-1023,-1021,-1019,-1017,-1014,-1010,-1004,-995,-984,-972,
+-962,-954,-949,-945,-941,-936,-930,-923,-916,-908,-896,-881,-864,-846,-829,-812,-794,-775,-754,-735,-720,
+-708,-698,-688,-676,-666,-659,-658,-662,-665,-666,-661,-653,-643,-634,-626,-616,-604,-590,-575,-561,-546,
+-528,-508,-485,-462,-440,-417,-393,-366,-338,-312,-292,-277,-265,-250,-232,-211,-190,-173,-160,-148,-136,
+-125,-114,-102,-88,-69,-46,-20,3,24,43,64,88,112,133,149,162,177,197,221,245,264,
+280,296,319,347,376,402,423,444,469,498,526,547,562,574,590,606,616,611,589,560,540,
+537,551,580,627,710,842,1022,1218,1377,1462,1470,1446,1449,1516,1633,1748,1804,1776,1692,1605,1563,
+1572,1604,1619,1593,1531,1458,1396,1353,1322,1291,1257,1226,1203,1190,1181,1171,1161,1154,1152,1153,1150,
+1139,1121,1103,1092,1090,1093,1095,1093,1091,1092,1100,1113,1127,1137,1145,1151,1157,1160,1158,1152,1143,
+1136,1133,1133,1130,1121,1108,1093,1081,1071,1060,1046,1026,1005,985,969,956,942,922,896,865,831,
+795,758,720,679,638,597,552,503,446,380,309,237,169,112,65,29,3,-15,-31,-44,-56,
+-65,-71,-72,-70,-66,-64,-63,-65,-67,-70,-72,-76,-81,-88,-94,-96,-96,-92,-87,-80,-71,
+-59,-44,-28,-12,1,15,30,47,67,88,107,123,137,149,161,172,178,179,173,162,150,
+139,132,129,131,135,137,136,133,133,139,156,182,211,238,256,266,270,276,288,309,337,
+367,393,413,425,431,436,446,464,492,525,559,587,607,621,631,640,650,663,679,697,715,
+733,752,777,814,869,940,1017,1087,1138,1169,1185,1201,1224,1257,1291,1319,1338,1352,1371,1398,1434,
+1472,1506,1536,1566,1599,1637,1677,1715,1749,1780,1812,1846,1878,1905,1925,1940,1955,1975,2000,2026,2050,
+2070,2089,2109,2134,2163,2194,2225,2253,2278,2302,2323,2343,2360,2376,2392,2408,2426,2445,2465,2487,2509,
+2532,2557,2581,2604,2624,2641,2655,2667,2678,2686,2693,2700,2709,2722,2738,2754,2763,2764,2758,2752,2748,
+2746,2741,2727,2704,2677,2655,2645,2645,2647,2641,2626,2605,2585,2572,2566,2562,2555,2544,2532,2522,2515,
+2509,2502,2493,2484,2477,2471,2465,2456,2444,2433,2424,2417,2409,2400,2390,2381,2376,2403,2398,2393,2385,
+2374,2364,2359,2361,2370,2383,2397,2410,2419,2423,2425,2423,2422,2426,2437,2452,2467,2474,2466,2446,2423,
+2409,2418,2452,2504,2555,2583,2572,2522,2450,2381,2342,2342,2377,2429,2478,2515,2543,2568,2594,2619,2636,
+2642,2640,2640,2654,2683,2722,2760,2789,2808,2821,2836,2854,2873,2892,2908,2922,2938,2957,2977,2996,3013,
+3029,3046,3063,3083,3105,3128,3154,3181,3208,3232,3248,3258,3265,3274,3287,3302,3315,3323,3328,3334,3345,
+3359,3372,3378,3379,3381,3391,3414,3442,3464,3470,3461,3448,3444,3458,3484,3507,3518,3518,3519,3534,3567,
+3609,3647,3672,3690,3712,3750,3800,3848,3875,3873,3849,3826,3823,3853,3911,3986,4059,4118,4154,4166,4158,
+4140,4124,4118,4126,4142,4158,4170,4178,4185,4195,4208,4220,4228,4236,4248,4265,4284,4295,4289,4266,4237,
+4216,4215,4236,4270,4308,4340,4365,4385,4403,4418,4431,4441,4448,4454,4458,4461,4461,4460,4458,4457,4455,
+4449,4437,4420,4400,4383,4373,4372,4380,4395,4415,4438,4462,4482,4497,4506,4510,4512,4515,4519,4520,4520,
+4517,4513,4511,4509,4505,4499,4491,4483,4478,4476,4477,4475,4470,4462,4454,4448,4443,4437,4426,4412,4396,
+4380,4367,4354,4340,4323,4305,4288,4273,4259,4245,4227,4205,4179,4151,4125,4100,4079,4062,4047,4031,4013,
+3989,3960,3927,3894,3862,3833,3808,3788,3777,3774,3781,3790,3798,3798,3790,3778,3765,3758,3754,3753,3751,
+3747,3742,3742,3747,3757,3767,3773,3771,3766,3766,3782,3821,3882,3954,4024,4079,4112,4125,4123,4112,4098,
+4083,4068,4052,4030,3996,3945,3876,3797,3721,3659,3615,3581,3547,3506,3458,3412,3377,3356,3344,3332,3314,
+3289,3261,3236,3214,3194,3170,3143,3112,3081,3051,3022,2995,2968,2943,2919,2896,2872,2843,2811,2778,2744,
+2710,2674,2636,2596,2556,2520,2487,2455,2422,2386,2348,2312,2278,2247,2215,2180,2142,2104,2069,2038,2008,
+1975,1939,1900,1862,1828,1797,1766,1731,1691,1649,1606,1567,1529,1493,1456,1418,1381,1346,1311,1274,1235,
+1193,1154,1119,1089,1060,1030,995,956,915,876,838,802,765,727,690,654,619,583,546,508,468,
+430,393,357,321,284,246,207,167,125,82,37,-6,-50,-90,-127,-162,-197,-233,-271,-309,-348,
+-387,-424,-460,-495,-531,-568,-606,-644,-681,-716,-750,-783,-818,-852,-886,-919,-952,-988,-1027,-1067,-1106,
+-1141,-1171,-1197,-1223,-1251,-1281,-1313,-1346,-1379,-1412,-1445,-1477,-1508,-1538,-1567,-1598,-1630,-1661,-1690,-1714,-1736,
+-1758,-1783,-1810,-1837,-1860,-1880,-1898,-1917,-1937,-1958,-1980,-2001,-2023,-2046,-2068,-2087,-2100,-2108,-2116,-2127,-2146,
+-2168,-2189,-2204,-2213,-2219,-2228,-2242,-2258,-2272,-2281,-2286,-2290,-2298,-2308,-2320,-2331,-2341,-2352,-2362,-2373,-2380,
+-2383,-2382,-2381,-2383,-2391,-2402,-2410,-2413,-2411,-2405,-2400,-2396,-2395,-2395,-2395,-2395,-2393,-2389,-2383,-2377,-2371,
+-2365,-2360,-2353,-2343,-2331,-2317,-2305,-2297,-2290,-2283,-2273,-2260,-2246,-2231,-2218,-2204,-2189,-2174,-2159,-2146,-2135,
+-2125,-2113,-2101,-2087,-2075,-2063,-2051,-2039,-2024,-2008,-1992,-1976,-1960,-1944,-1928,-1913,-1900,-1888,-1875,-1858,-1839,
+-1822,-1807,-1796,-1785,-1773,-1759,-1749,-1752,-1770,-1798,-1823,-1834,-1824,-1800,-1772,-1751,-1740,-1732,-1722,-1706,-1688,
+-1676,-1673,-1678,-1683,-1680,-1668,-1653,-1646,-1652,-1673,-1699,-1722,-1737,-1743,-1745,-1746,-1746,-1742,-1728,-1703,-1674,
+-1648,-1633,-1628,-1626,-1617,-1591,-1550,-1502,-1463,-1445,-1454,-1485,-1527,-1567,-1598,-1617,-1627,-1632,-1632,-1630,-1626,
+-1620,-1617,-1618,-1622,-1626,-1626,-1619,-1607,-1595,-1589,-1591,-1598,-1604,-1602,-1590,-1572,-1553,-1539,-1530,-1522,-1511,
+-1492,-1464,-1429,-1391,-1353,-1318,-1288,-1266,-1249,-1236,-1220,-1196,-1164,-1127,-1091,-1068,-1064,-1082,-1112,-1137,-1133,
+-1087,-1002,-904,-831,-813,-854,-928,-988,-993,-934,-837,-746,-699,-703,-739,-778,-800,-805,-807,-819,-841,
+-863,-875,-874,-867,-864,-866,-866,-855,-832,-803,-779,-766,-763,-764,-763,-760,-758,-762,-770,-777,-781,
+-780,-779,-782,-794,-814,-843,-880,-921,-959,-988,-1003,-1004,-998,-992,-992,-996,-1001,-1001,-999,-1002,-1018,
+-1046,-1082,-1122,-1161,-1204,-1252,-1307,-1364,-1414,-1453,-1479,-1494,-1504,-1512,-1522,-1536,-1559,-1593,-1635,-1677,-1711,
+-1730,-1736,-1735,-1732,-1731,-1731,-1729,-1724,-1720,-1718,-1720,-1723,-1723,-1720,-1715,-1709,-1705,-1702,-1700,-1696,-1693,
+-1693,-1696,-1701,-1706,-1710,-1711,-1710,-1707,-1701,-1692,-1681,-1671,-1666,-1664,-1667,-1669,-1671,-1670,-1668,-1666,-1664,
+-1660,-1655,-1651,-1649,-1651,-1655,-1660,-1662,-1664,-1664,-1665,-1667,-1667,-1667,-1666,-1666,-1668,-1671,-1672,-1671,-1668,
+-1667,-1669,-1676,-1686,-1695,-1699,-1698,-1692,-1684,-1677,-1672,-1669,-1667,-1664,-1659,-1649,-1636,-1619,-1603,-1589,-1578,
+-1570,-1562,-1554,-1547,-1539,-1531,-1523,-1514,-1504,-1494,-1487,-1483,-1483,-1487,-1493,-1502,-1515,-1532,-1553,-1577,-1601,
+-1621,-1637,-1645,-1646,-1640,-1628,-1612,-1597,-1586,-1584,-1593,-1612,-1635,-1657,-1670,-1675,-1675,-1674,-1677,-1681,-1686,
+-1687,-1687,-1687,-1692,-1704,-1720,-1735,-1746,-1751,-1749,-1743,-1735,-1725,-1715,-1707,-1704,-1706,-1714,-1725,-1735,-1742,
+-1745,-1745,-1743,-1740,-1737,-1734,-1732,-1730,-1731,-1733,-1737,-1741,-1745,-1748,-1747,-1744,-1737,-1728,-1719,-1712,-1705,
+-1698,-1690,-1681,-1674,-1667,-1661,-1654,-1643,-1627,-1609,-1590,-1573,-1557,-1541,-1525,-1509,-1492,-1476,-1460,-1444,-1427,
+-1408,-1390,-1372,-1355,-1340,-1325,-1310,-1295,-1280,-1264,-1248,-1230,-1212,-1195,-1179,-1165,-1153,-1141,-1127,-1113,-1100,
+-1087,-1077,-1068,-1061,-1054,-1048,-1041,-1035,-1029,-1024,-1020,-1017,-1014,-1012,-1010,-1008,-1007,-1005,-1002,-998,-991,
+-983,-977,-974,-974,-976,-978,-978,-975,-969,-964,-959,-955,-952,-949,-946,-944,-944,-947,-951,-956,-959,
+-962,-965,-968,-973,-979,-985,-991,-996,-1001,-1006,-1011,-1015,-1018,-1020,-1020,-1019,-1017,-1016,-1016,-1017,-1018,
+-1020,-1022,-1022,-1022,-1022,-1021,-1021,-1021,-1017,-1010,-999,-985,-971,-961,-953,-949,-945,-940,-933,-926,-919,
+-912,-903,-891,-876,-861,-846,-833,-820,-804,-786,-766,-747,-731,-718,-706,-694,-681,-669,-662,-662,-665,
+-669,-669,-664,-657,-649,-642,-635,-627,-616,-604,-591,-578,-564,-548,-529,-508,-486,-464,-442,-418,-390,
+-362,-335,-315,-299,-287,-273,-256,-236,-215,-196,-179,-165,-153,-142,-130,-116,-98,-76,-51,-28,-7,
+9,26,47,70,95,116,132,147,163,183,206,229,249,267,288,313,341,367,387,405,425,
+452,483,510,530,542,555,571,589,597,586,559,529,514,519,542,573,615,686,806,977,1169,
+1328,1413,1422,1402,1416,1504,1652,1798,1874,1847,1742,1621,1540,1518,1533,1546,1526,1474,1410,1354,1312,
+1277,1239,1199,1164,1144,1140,1145,1150,1150,1146,1141,1136,1128,1114,1095,1079,1070,1073,1081,1088,1090,
+1089,1091,1100,1115,1131,1143,1152,1160,1169,1178,1185,1186,1182,1177,1173,1171,1168,1161,1150,1137,1124,
+1112,1099,1084,1066,1048,1034,1023,1013,999,977,949,917,883,850,815,778,739,699,661,625,588,
+545,492,428,358,285,216,153,99,55,21,-2,-18,-26,-29,-27,-23,-18,-15,-17,-21,-28,
+-34,-38,-40,-41,-43,-45,-46,-45,-42,-40,-37,-35,-29,-19,-3,16,37,56,73,91,111,
+135,162,188,211,230,245,255,261,261,256,245,229,213,197,182,170,159,150,140,131,122,
+118,123,137,161,190,218,242,259,273,286,302,323,347,373,398,418,432,441,446,452,463,
+483,510,540,569,594,615,632,650,670,694,720,745,765,778,784,793,814,859,929,1014,1097,
+1162,1202,1223,1239,1261,1293,1330,1362,1386,1403,1422,1448,1481,1516,1547,1575,1603,1635,1674,1716,1755,
+1789,1819,1846,1874,1904,1931,1954,1972,1987,2002,2018,2035,2051,2067,2084,2103,2126,2152,2178,2203,2226,
+2249,2272,2295,2318,2339,2358,2376,2392,2408,2427,2448,2472,2500,2528,2554,2576,2593,2608,2622,2637,2652,
+2665,2674,2677,2679,2684,2694,2708,2720,2726,2723,2716,2711,2712,2717,2718,2711,2694,2675,2663,2663,2670,
+2677,2673,2657,2635,2613,2599,2591,2585,2577,2565,2553,2544,2539,2535,2531,2524,2517,2509,2502,2493,2482,
+2468,2455,2445,2438,2432,2425,2417,2409,2403,2436,2429,2421,2412,2404,2400,2402,2410,2421,2433,2442,2446,
+2446,2441,2434,2427,2424,2429,2441,2455,2461,2456,2441,2426,2424,2445,2488,2540,2583,2602,2589,2549,2494,
+2441,2403,2385,2388,2406,2433,2464,2498,2533,2567,2596,2612,2615,2609,2606,2615,2642,2682,2726,2762,2787,
+2803,2817,2836,2859,2883,2904,2921,2937,2956,2979,3004,3026,3044,3059,3072,3088,3108,3130,3152,3174,3195,
+3215,3235,3252,3265,3275,3285,3297,3312,3328,3343,3355,3366,3376,3384,3390,3394,3397,3406,3423,3448,3472,
+3486,3487,3476,3466,3466,3481,3504,3524,3536,3542,3551,3570,3598,3628,3652,3672,3695,3731,3779,3827,3855,
+3852,3823,3788,3774,3797,3857,3936,4012,4067,4094,4098,4088,4075,4066,4066,4074,4086,4097,4105,4110,4117,
+4129,4147,4168,4186,4202,4217,4235,4257,4277,4286,4280,4260,4238,4228,4237,4262,4297,4331,4359,4383,4403,
+4421,4437,4449,4458,4465,4472,4476,4477,4474,4469,4466,4466,4467,4464,4454,4435,4415,4398,4390,4391,4399,
+4411,4426,4447,4470,4492,4508,4517,4519,4520,4523,4529,4536,4540,4538,4533,4524,4515,4504,4491,4480,4471,
+4467,4467,4467,4464,4457,4447,4439,4435,4434,4430,4422,4407,4389,4372,4357,4343,4329,4313,4296,4281,4269,
+4256,4240,4220,4195,4167,4140,4115,4093,4074,4056,4039,4021,4000,3974,3943,3909,3874,3841,3812,3788,3771,
+3763,3765,3772,3778,3776,3762,3742,3722,3715,3726,3752,3787,3820,3845,3861,3870,3876,3880,3879,3867,3844,
+3812,3782,3767,3779,3820,3886,3962,4033,4086,4116,4125,4118,4104,4089,4075,4061,4041,4007,3955,3885,3808,
+3734,3676,3636,3607,3579,3545,3503,3460,3422,3392,3368,3345,3319,3292,3266,3244,3226,3208,3186,3160,3130,
+3100,3071,3044,3018,2993,2969,2947,2924,2898,2867,2831,2795,2761,2730,2698,2662,2620,2576,2533,2495,2461,
+2429,2395,2359,2323,2290,2261,2232,2201,2166,2128,2092,2057,2025,1991,1954,1915,1878,1843,1811,1779,1744,
+1704,1661,1620,1580,1543,1504,1465,1424,1386,1350,1317,1283,1245,1204,1164,1128,1098,1070,1040,1007,969,
+929,891,856,822,788,752,715,677,639,601,563,525,488,452,417,381,342,303,263,225,186,
+146,104,61,18,-22,-59,-95,-132,-171,-212,-254,-294,-332,-368,-403,-438,-472,-507,-541,-575,-610,
+-646,-682,-719,-755,-790,-824,-858,-891,-926,-963,-1001,-1039,-1074,-1106,-1136,-1164,-1194,-1226,-1258,-1290,-1321,
+-1352,-1383,-1415,-1447,-1477,-1506,-1533,-1562,-1592,-1623,-1653,-1679,-1703,-1726,-1752,-1780,-1807,-1832,-1853,-1872,-1891,
+-1911,-1932,-1953,-1973,-1994,-2016,-2038,-2058,-2073,-2084,-2095,-2110,-2130,-2152,-2169,-2179,-2183,-2187,-2195,-2210,-2228,
+-2242,-2249,-2253,-2258,-2268,-2284,-2302,-2316,-2324,-2330,-2337,-2346,-2356,-2363,-2366,-2367,-2371,-2378,-2388,-2398,-2402,
+-2399,-2392,-2385,-2382,-2383,-2387,-2391,-2394,-2392,-2388,-2381,-2373,-2365,-2358,-2350,-2342,-2333,-2323,-2314,-2307,-2301,
+-2295,-2288,-2277,-2264,-2250,-2238,-2226,-2214,-2200,-2184,-2169,-2157,-2147,-2137,-2127,-2114,-2099,-2084,-2070,-2057,-2043,
+-2028,-2013,-1998,-1984,-1972,-1959,-1945,-1930,-1916,-1902,-1888,-1872,-1854,-1836,-1821,-1808,-1796,-1783,-1769,-1760,-1762,
+-1778,-1804,-1828,-1841,-1834,-1813,-1786,-1764,-1750,-1741,-1731,-1716,-1700,-1688,-1685,-1690,-1696,-1696,-1687,-1675,-1667,
+-1670,-1685,-1707,-1729,-1745,-1755,-1762,-1768,-1771,-1767,-1754,-1731,-1704,-1680,-1666,-1660,-1657,-1650,-1632,-1605,-1575,
+-1550,-1537,-1538,-1550,-1569,-1590,-1610,-1626,-1638,-1644,-1644,-1641,-1637,-1635,-1639,-1646,-1653,-1657,-1655,-1645,-1631,
+-1619,-1612,-1613,-1618,-1621,-1619,-1610,-1596,-1582,-1570,-1561,-1551,-1537,-1516,-1488,-1455,-1421,-1389,-1360,-1337,-1318,
+-1300,-1281,-1257,-1226,-1192,-1159,-1137,-1131,-1140,-1158,-1168,-1153,-1104,-1025,-938,-872,-857,-899,-977,-1052,-1080,
+-1042,-949,-842,-764,-739,-763,-807,-842,-855,-854,-855,-869,-896,-921,-936,-936,-930,-926,-927,-925,-915,
+-894,-866,-840,-825,-820,-823,-828,-834,-839,-845,-852,-859,-866,-873,-882,-893,-906,-922,-945,-976,-1014,
+-1053,-1083,-1096,-1092,-1081,-1073,-1076,-1088,-1103,-1118,-1132,-1151,-1181,-1220,-1264,-1306,-1342,-1375,-1408,-1446,-1485,
+-1520,-1543,-1552,-1546,-1531,-1514,-1503,-1508,-1536,-1588,-1654,-1721,-1774,-1806,-1818,-1820,-1818,-1817,-1814,-1807,-1797,
+-1787,-1783,-1784,-1787,-1788,-1784,-1778,-1772,-1768,-1766,-1764,-1760,-1757,-1756,-1759,-1765,-1770,-1773,-1772,-1768,-1765,
+-1761,-1755,-1747,-1738,-1730,-1726,-1726,-1726,-1725,-1723,-1721,-1719,-1719,-1719,-1719,-1717,-1716,-1717,-1719,-1721,-1721,
+-1718,-1715,-1712,-1711,-1713,-1716,-1720,-1723,-1726,-1728,-1726,-1720,-1712,-1704,-1701,-1705,-1714,-1726,-1735,-1739,-1736,
+-1730,-1723,-1719,-1716,-1715,-1714,-1710,-1703,-1693,-1681,-1668,-1656,-1643,-1631,-1618,-1605,-1593,-1583,-1575,-1567,-1559,
+-1550,-1540,-1532,-1527,-1526,-1528,-1531,-1534,-1537,-1542,-1553,-1569,-1590,-1611,-1630,-1645,-1655,-1662,-1665,-1664,-1658,
+-1648,-1637,-1630,-1630,-1639,-1652,-1664,-1674,-1682,-1691,-1703,-1714,-1724,-1726,-1723,-1717,-1713,-1715,-1723,-1736,-1748,
+-1759,-1767,-1771,-1769,-1761,-1748,-1732,-1718,-1712,-1714,-1722,-1734,-1745,-1752,-1755,-1754,-1750,-1747,-1743,-1741,-1742,
+-1743,-1745,-1747,-1750,-1754,-1758,-1760,-1759,-1754,-1745,-1734,-1725,-1718,-1711,-1704,-1695,-1685,-1675,-1667,-1660,-1651,
+-1640,-1625,-1609,-1592,-1575,-1559,-1542,-1524,-1506,-1489,-1473,-1458,-1441,-1423,-1403,-1383,-1364,-1348,-1333,-1320,-1308,
+-1295,-1283,-1269,-1253,-1236,-1218,-1200,-1184,-1169,-1155,-1142,-1127,-1113,-1098,-1084,-1072,-1062,-1053,-1045,-1037,-1030,
+-1023,-1016,-1009,-1003,-998,-994,-990,-988,-987,-987,-986,-984,-979,-973,-967,-963,-964,-968,-973,-977,-978,
+-977,-974,-972,-969,-967,-963,-959,-955,-954,-957,-961,-967,-971,-973,-974,-976,-981,-989,-999,-1008,-1015,
+-1019,-1023,-1026,-1031,-1036,-1040,-1044,-1044,-1041,-1036,-1030,-1025,-1023,-1023,-1024,-1025,-1024,-1022,-1020,-1020,-1019,
+-1017,-1012,-1004,-992,-980,-971,-963,-957,-951,-944,-936,-928,-920,-913,-903,-892,-878,-865,-853,-843,-832,
+-819,-803,-785,-768,-753,-739,-725,-710,-694,-682,-675,-674,-676,-676,-674,-668,-660,-655,-651,-646,-639,
+-629,-617,-604,-591,-578,-564,-546,-527,-508,-490,-470,-448,-421,-393,-365,-341,-322,-307,-292,-276,-257,
+-237,-219,-201,-186,-173,-161,-147,-130,-107,-81,-56,-34,-17,-4,9,28,51,74,95,113,130,
+149,172,196,219,238,258,282,309,337,360,377,393,415,444,476,501,517,525,536,554,577,
+589,581,553,522,506,513,537,570,612,682,799,966,1153,1307,1387,1394,1374,1394,1493,1653,1810,
+1890,1859,1740,1599,1497,1460,1468,1481,1468,1427,1372,1323,1283,1245,1201,1153,1113,1091,1091,1104,1116,
+1119,1116,1111,1108,1104,1095,1082,1067,1060,1062,1072,1082,1089,1093,1099,1112,1132,1153,1172,1186,1198,
+1210,1221,1230,1233,1230,1223,1217,1213,1210,1205,1196,1185,1172,1159,1144,1127,1108,1090,1075,1064,1052,
+1038,1018,992,963,932,901,866,827,786,745,708,677,647,613,569,514,451,384,317,254,197,
+148,110,83,69,65,69,75,80,83,81,74,64,54,46,43,42,43,44,44,45,47,
+49,48,43,36,29,29,39,59,84,110,134,157,182,210,242,276,310,339,361,375,381,
+380,373,362,349,331,309,282,250,217,187,162,144,134,131,135,145,162,183,208,235,262,
+288,313,337,357,377,396,417,439,463,484,502,516,529,543,560,582,608,635,664,694,724,
+756,789,822,853,875,887,887,884,890,917,970,1043,1120,1186,1231,1258,1277,1300,1331,1368,1402,
+1428,1449,1470,1496,1527,1560,1591,1618,1644,1673,1707,1744,1780,1811,1838,1863,1889,1917,1945,1970,1989,
+2004,2015,2024,2032,2043,2055,2072,2093,2116,2139,2161,2183,2203,2225,2248,2272,2296,2319,2341,2361,2380,
+2399,2419,2441,2467,2496,2525,2551,2571,2585,2596,2607,2620,2635,2647,2653,2655,2656,2659,2669,2681,2692,
+2697,2696,2693,2693,2699,2707,2712,2708,2697,2686,2683,2688,2698,2703,2696,2679,2657,2638,2626,2620,2613,
+2604,2593,2583,2577,2574,2572,2567,2559,2549,2540,2532,2523,2512,2500,2488,2477,2469,2462,2456,2449,2442,
+2436,2469,2462,2455,2448,2445,2446,2452,2459,2464,2464,2459,2452,2445,2438,2432,2428,2430,2438,2452,2463,
+2463,2451,2434,2426,2441,2480,2531,2572,2583,2558,2507,2452,2414,2399,2405,2418,2430,2437,2447,2466,2499,
+2541,2583,2613,2626,2622,2613,2609,2620,2645,2679,2714,2743,2765,2783,2804,2831,2860,2889,2914,2936,2957,
+2981,3008,3035,3059,3078,3093,3107,3124,3143,3161,3177,3191,3205,3222,3241,3261,3279,3293,3303,3312,3325,
+3342,3361,3380,3393,3401,3403,3403,3405,3414,3431,3454,3478,3495,3501,3496,3487,3482,3487,3501,3518,3535,
+3550,3566,3587,3613,3638,3655,3667,3680,3705,3747,3796,3832,3839,3813,3772,3743,3750,3802,3884,3969,4034,
+4066,4068,4052,4033,4021,4018,4025,4038,4052,4063,4069,4071,4074,4082,4097,4117,4139,4161,4184,4211,4238,
+4262,4276,4277,4269,4261,4264,4280,4307,4339,4368,4394,4416,4436,4452,4463,4470,4474,4479,4485,4490,4491,
+4488,4481,4476,4475,4475,4471,4461,4445,4429,4419,4418,4424,4432,4442,4453,4468,4487,4507,4522,4529,4529,
+4526,4526,4530,4535,4538,4536,4528,4518,4507,4495,4483,4472,4464,4461,4461,4461,4457,4450,4441,4435,4433,
+4432,4429,4419,4403,4385,4367,4353,4340,4326,4312,4298,4285,4273,4259,4241,4216,4187,4157,4129,4105,4085,
+4068,4050,4032,4012,3988,3960,3929,3897,3866,3837,3810,3786,3767,3755,3753,3756,3757,3748,3724,3692,3663,
+3654,3674,3722,3789,3860,3923,3969,4000,4015,4017,4003,3972,3924,3863,3803,3756,3736,3751,3796,3863,3936,
+4002,4052,4084,4098,4101,4095,4083,4065,4035,3992,3932,3861,3789,3725,3680,3653,3638,3625,3607,3581,3550,
+3516,3481,3444,3403,3359,3317,3282,3256,3236,3219,3199,3174,3147,3118,3089,3058,3028,2999,2975,2956,2938,
+2918,2889,2852,2812,2774,2741,2712,2680,2642,2599,2554,2512,2476,2443,2409,2373,2335,2301,2270,2242,2214,
+2182,2147,2111,2075,2040,2005,1968,1930,1892,1855,1821,1786,1750,1712,1673,1635,1598,1562,1523,1481,1437,
+1396,1359,1325,1292,1256,1219,1181,1146,1115,1086,1056,1022,984,945,908,873,839,806,771,734,696,
+658,619,580,543,508,474,438,400,358,316,274,235,199,162,123,83,42,3,-33,-70,-109,
+-150,-194,-237,-277,-313,-349,-384,-420,-456,-490,-522,-554,-586,-621,-656,-693,-729,-764,-799,-834,-871,
+-908,-944,-979,-1012,-1042,-1071,-1100,-1132,-1167,-1203,-1239,-1271,-1302,-1330,-1359,-1388,-1418,-1447,-1474,-1499,-1526,
+-1555,-1585,-1615,-1643,-1669,-1694,-1720,-1748,-1774,-1799,-1821,-1841,-1862,-1884,-1906,-1926,-1946,-1965,-1986,-2009,-2030,
+-2050,-2065,-2080,-2096,-2114,-2132,-2146,-2154,-2158,-2163,-2173,-2189,-2205,-2216,-2220,-2222,-2227,-2241,-2262,-2284,-2301,
+-2309,-2313,-2316,-2323,-2333,-2342,-2349,-2353,-2357,-2364,-2375,-2384,-2390,-2388,-2382,-2375,-2371,-2372,-2377,-2383,-2386,
+-2386,-2382,-2376,-2368,-2360,-2351,-2342,-2333,-2324,-2315,-2308,-2303,-2298,-2292,-2283,-2272,-2259,-2248,-2238,-2230,-2220,
+-2209,-2195,-2182,-2169,-2159,-2148,-2136,-2121,-2104,-2088,-2073,-2059,-2045,-2030,-2015,-2001,-1989,-1978,-1968,-1956,-1942,
+-1927,-1913,-1898,-1882,-1865,-1848,-1832,-1817,-1804,-1791,-1780,-1775,-1779,-1794,-1818,-1839,-1850,-1843,-1823,-1797,-1775,
+-1761,-1752,-1743,-1730,-1715,-1703,-1700,-1704,-1710,-1712,-1704,-1693,-1684,-1685,-1698,-1719,-1741,-1759,-1771,-1779,-1785,
+-1789,-1788,-1778,-1760,-1738,-1716,-1699,-1688,-1680,-1673,-1665,-1655,-1647,-1641,-1636,-1633,-1631,-1631,-1634,-1641,-1649,
+-1656,-1658,-1657,-1654,-1654,-1659,-1667,-1678,-1685,-1686,-1681,-1672,-1661,-1652,-1646,-1643,-1642,-1642,-1639,-1632,-1622,
+-1609,-1596,-1582,-1568,-1550,-1527,-1500,-1471,-1443,-1416,-1393,-1372,-1351,-1328,-1303,-1277,-1251,-1230,-1216,-1209,-1207,
+-1205,-1194,-1165,-1114,-1045,-974,-924,-915,-956,-1033,-1113,-1160,-1144,-1066,-954,-849,-787,-780,-813,-858,-890,
+-902,-903,-908,-926,-951,-974,-985,-983,-976,-971,-969,-967,-959,-943,-923,-906,-898,-899,-906,-915,-923,
+-930,-936,-943,-952,-965,-983,-1003,-1022,-1038,-1052,-1069,-1093,-1125,-1158,-1182,-1191,-1188,-1181,-1181,-1195,-1220,
+-1248,-1275,-1301,-1331,-1369,-1414,-1458,-1493,-1518,-1535,-1552,-1572,-1595,-1615,-1624,-1617,-1593,-1555,-1515,-1487,-1486,
+-1520,-1589,-1676,-1763,-1830,-1870,-1886,-1892,-1894,-1897,-1896,-1887,-1872,-1857,-1847,-1845,-1846,-1846,-1842,-1835,-1828,
+-1824,-1823,-1822,-1819,-1816,-1816,-1820,-1827,-1832,-1834,-1830,-1825,-1822,-1820,-1818,-1813,-1805,-1797,-1791,-1788,-1788,
+-1787,-1784,-1780,-1777,-1776,-1776,-1777,-1777,-1777,-1778,-1781,-1784,-1784,-1779,-1770,-1761,-1755,-1753,-1756,-1764,-1772,
+-1780,-1786,-1787,-1782,-1772,-1760,-1750,-1745,-1748,-1757,-1769,-1779,-1784,-1784,-1781,-1776,-1770,-1766,-1762,-1759,-1755,
+-1751,-1746,-1738,-1726,-1711,-1694,-1675,-1657,-1641,-1629,-1620,-1614,-1607,-1600,-1592,-1585,-1580,-1579,-1580,-1581,-1580,
+-1577,-1572,-1571,-1575,-1584,-1597,-1611,-1626,-1642,-1659,-1678,-1693,-1700,-1696,-1683,-1667,-1653,-1647,-1647,-1651,-1658,
+-1666,-1679,-1695,-1715,-1734,-1746,-1751,-1750,-1747,-1744,-1745,-1748,-1753,-1761,-1771,-1779,-1785,-1783,-1772,-1755,-1736,
+-1720,-1712,-1712,-1719,-1729,-1738,-1745,-1749,-1749,-1749,-1749,-1752,-1757,-1762,-1766,-1767,-1767,-1767,-1768,-1770,-1771,
+-1769,-1762,-1753,-1745,-1738,-1732,-1724,-1713,-1700,-1686,-1675,-1667,-1660,-1651,-1638,-1623,-1606,-1589,-1572,-1554,-1535,
+-1516,-1497,-1481,-1465,-1449,-1432,-1412,-1390,-1370,-1351,-1335,-1321,-1308,-1295,-1284,-1272,-1261,-1248,-1233,-1217,-1201,
+-1186,-1172,-1161,-1149,-1136,-1122,-1107,-1091,-1077,-1065,-1055,-1047,-1039,-1031,-1023,-1015,-1007,-999,-992,-987,-984,
+-982,-980,-979,-977,-972,-966,-960,-956,-956,-960,-966,-973,-978,-981,-984,-986,-987,-986,-983,-979,-975,
+-974,-978,-985,-992,-998,-1000,-1001,-1003,-1007,-1015,-1024,-1032,-1037,-1040,-1041,-1042,-1045,-1051,-1057,-1062,-1064,
+-1063,-1058,-1051,-1045,-1041,-1039,-1038,-1036,-1033,-1028,-1024,-1021,-1021,-1021,-1021,-1017,-1010,-1001,-991,-982,-973,
+-964,-953,-943,-934,-927,-920,-913,-904,-894,-883,-871,-860,-848,-834,-819,-805,-792,-780,-767,-752,-734,
+-716,-701,-693,-689,-688,-685,-680,-672,-666,-662,-660,-657,-651,-640,-627,-615,-603,-591,-577,-562,-546,
+-531,-515,-499,-479,-454,-426,-397,-371,-349,-330,-313,-296,-278,-260,-242,-225,-210,-196,-182,-166,-145,
+-119,-91,-66,-46,-32,-21,-7,10,33,56,75,93,111,134,160,187,209,229,249,273,301,
+330,354,372,389,412,443,474,497,507,512,520,540,566,584,580,555,524,506,510,533,568,
+615,691,812,979,1159,1302,1372,1372,1350,1370,1469,1626,1776,1847,1807,1682,1538,1436,1401,1412,1429,
+1422,1386,1336,1290,1254,1218,1174,1125,1083,1060,1059,1070,1079,1081,1076,1072,1072,1075,1074,1066,1055,
+1049,1053,1067,1083,1096,1105,1115,1130,1153,1181,1207,1229,1246,1261,1272,1278,1278,1272,1263,1254,1248,
+1245,1241,1234,1224,1211,1197,1183,1167,1148,1129,1111,1096,1082,1068,1051,1030,1006,980,949,914,874,
+832,791,756,725,695,660,616,564,507,450,395,345,300,261,231,211,201,199,201,203,201,
+195,185,172,160,150,146,146,150,154,157,157,157,156,154,150,141,129,117,112,117,135,
+161,191,221,249,278,310,347,389,430,466,494,511,518,518,512,503,489,467,434,390,336,
+282,237,205,190,187,192,200,209,219,232,250,274,304,338,371,400,423,440,453,468,489,
+517,550,583,611,632,646,659,674,694,722,755,793,830,867,902,937,970,997,1014,1019,1014,
+1010,1018,1046,1092,1148,1201,1244,1274,1299,1326,1359,1394,1426,1452,1474,1494,1519,1548,1580,1611,1638,
+1663,1688,1716,1746,1775,1803,1830,1856,1883,1911,1939,1965,1986,2002,2013,2021,2028,2037,2049,2066,2087,
+2109,2130,2150,2170,2190,2211,2233,2255,2276,2296,2318,2341,2365,2390,2415,2440,2465,2491,2516,2540,2558,
+2573,2585,2595,2607,2618,2627,2632,2635,2639,2646,2656,2668,2678,2682,2684,2687,2693,2703,2713,2718,2716,
+2710,2707,2709,2716,2722,2721,2710,2693,2676,2663,2656,2651,2645,2636,2627,2620,2616,2614,2611,2603,2592,
+2581,2571,2563,2557,2549,2538,2526,2514,2504,2495,2487,2481,2475,2469,2502,2494,2485,2479,2479,2484,2491,
+2495,2491,2479,2464,2452,2446,2446,2448,2451,2456,2464,2475,2483,2480,2465,2445,2436,2447,2478,2513,2529,
+2511,2464,2406,2365,2358,2382,2421,2452,2465,2464,2462,2476,2510,2556,2602,2635,2649,2648,2639,2633,2633,
+2641,2656,2676,2699,2727,2760,2796,2834,2872,2908,2940,2969,2996,3023,3049,3072,3093,3111,3128,3146,3164,
+3180,3192,3200,3206,3215,3231,3253,3278,3300,3314,3322,3328,3338,3354,3375,3395,3408,3414,3414,3415,3421,
+3436,3459,3482,3500,3508,3506,3501,3498,3501,3511,3524,3536,3549,3566,3591,3622,3652,3672,3680,3681,3689,
+3713,3753,3793,3813,3801,3766,3730,3723,3760,3835,3925,4001,4046,4057,4046,4028,4012,4002,4000,4004,4016,
+4032,4047,4058,4061,4059,4057,4061,4073,4094,4120,4149,4181,4213,4241,4263,4276,4284,4291,4303,4322,4348,
+4376,4405,4432,4457,4477,4491,4497,4496,4494,4494,4498,4503,4506,4503,4497,4492,4490,4489,4485,4476,4465,
+4455,4452,4458,4468,4478,4485,4490,4498,4509,4521,4531,4533,4530,4525,4522,4521,4521,4518,4512,4504,4495,
+4487,4479,4471,4462,4454,4449,4447,4447,4446,4443,4439,4436,4434,4431,4424,4412,4397,4381,4367,4355,4343,
+4329,4313,4297,4282,4268,4252,4231,4205,4175,4145,4119,4096,4078,4062,4046,4029,4009,3984,3956,3925,3896,
+3869,3845,3822,3798,3775,3757,3747,3743,3740,3728,3701,3664,3629,3612,3625,3671,3742,3824,3901,3965,4009,
+4035,4041,4027,3993,3939,3872,3802,3742,3702,3691,3709,3752,3811,3876,3940,3995,4037,4063,4072,4063,4036,
+3992,3933,3865,3796,3736,3693,3670,3663,3664,3665,3661,3650,3634,3612,3584,3546,3497,3440,3384,3335,3297,
+3267,3243,3219,3194,3169,3143,3113,3080,3042,3005,2974,2954,2942,2929,2907,2874,2832,2790,2753,2721,2691,
+2657,2617,2574,2533,2496,2463,2430,2395,2357,2319,2285,2255,2226,2195,2161,2124,2087,2051,2016,1980,1943,
+1905,1868,1831,1794,1758,1721,1685,1649,1614,1578,1539,1498,1456,1414,1375,1339,1304,1270,1235,1202,1170,
+1140,1109,1077,1041,1003,965,928,893,858,824,788,752,715,678,640,602,565,529,493,457,417,
+373,328,285,245,209,173,137,99,60,21,-16,-55,-96,-137,-179,-218,-254,-289,-325,-361,-400,
+-437,-472,-504,-535,-567,-600,-634,-668,-702,-736,-772,-811,-850,-889,-926,-958,-987,-1013,-1039,-1068,-1100,
+-1136,-1174,-1211,-1246,-1277,-1305,-1332,-1359,-1387,-1414,-1441,-1468,-1496,-1524,-1554,-1583,-1611,-1638,-1664,-1690,-1716,
+-1741,-1764,-1786,-1809,-1832,-1856,-1880,-1902,-1922,-1941,-1962,-1984,-2008,-2030,-2048,-2063,-2077,-2091,-2106,-2118,-2128,
+-2136,-2146,-2158,-2173,-2187,-2195,-2198,-2200,-2207,-2222,-2243,-2266,-2284,-2293,-2297,-2299,-2304,-2312,-2322,-2331,-2337,
+-2344,-2352,-2362,-2371,-2377,-2377,-2372,-2366,-2362,-2361,-2363,-2366,-2369,-2370,-2369,-2366,-2361,-2354,-2346,-2337,-2328,
+-2318,-2309,-2302,-2295,-2289,-2282,-2273,-2262,-2250,-2240,-2233,-2227,-2220,-2211,-2200,-2187,-2174,-2161,-2148,-2133,-2116,
+-2099,-2083,-2071,-2060,-2048,-2035,-2020,-2005,-1992,-1980,-1969,-1957,-1943,-1928,-1914,-1902,-1889,-1876,-1862,-1846,-1830,
+-1816,-1804,-1795,-1792,-1798,-1813,-1833,-1852,-1859,-1852,-1832,-1807,-1787,-1774,-1766,-1758,-1746,-1730,-1718,-1714,-1717,
+-1722,-1723,-1714,-1701,-1690,-1692,-1707,-1731,-1757,-1777,-1788,-1793,-1796,-1798,-1799,-1795,-1785,-1768,-1747,-1726,-1708,
+-1694,-1686,-1685,-1689,-1698,-1706,-1710,-1707,-1699,-1690,-1684,-1682,-1683,-1682,-1679,-1674,-1673,-1676,-1686,-1697,-1705,
+-1707,-1704,-1699,-1694,-1690,-1686,-1682,-1676,-1671,-1667,-1664,-1660,-1651,-1637,-1618,-1598,-1579,-1559,-1538,-1515,-1490,
+-1465,-1441,-1420,-1400,-1377,-1352,-1327,-1306,-1292,-1286,-1284,-1277,-1257,-1219,-1163,-1096,-1028,-973,-946,-956,-1007,
+-1086,-1172,-1231,-1239,-1187,-1088,-974,-881,-834,-836,-869,-909,-939,-953,-961,-971,-988,-1007,-1020,-1024,-1020,
+-1012,-1007,-1004,-1001,-994,-986,-978,-975,-978,-987,-996,-1005,-1010,-1014,-1020,-1030,-1046,-1070,-1099,-1129,-1156,
+-1176,-1192,-1210,-1233,-1262,-1291,-1311,-1320,-1321,-1324,-1338,-1364,-1398,-1432,-1462,-1490,-1520,-1557,-1597,-1633,-1658,
+-1671,-1675,-1677,-1684,-1694,-1704,-1704,-1689,-1657,-1612,-1564,-1530,-1526,-1563,-1637,-1732,-1823,-1891,-1931,-1948,-1955,
+-1963,-1972,-1976,-1970,-1953,-1933,-1918,-1909,-1905,-1901,-1893,-1883,-1875,-1872,-1871,-1871,-1870,-1869,-1871,-1877,-1886,
+-1892,-1894,-1890,-1885,-1881,-1880,-1879,-1875,-1866,-1858,-1852,-1851,-1853,-1855,-1852,-1846,-1840,-1835,-1833,-1834,-1834,
+-1835,-1837,-1841,-1844,-1844,-1839,-1829,-1816,-1804,-1798,-1798,-1803,-1812,-1822,-1833,-1841,-1845,-1843,-1834,-1822,-1811,
+-1804,-1804,-1810,-1818,-1827,-1832,-1834,-1832,-1827,-1822,-1817,-1814,-1812,-1810,-1806,-1798,-1786,-1770,-1751,-1732,-1714,
+-1698,-1684,-1674,-1666,-1659,-1653,-1646,-1639,-1635,-1633,-1632,-1632,-1629,-1623,-1614,-1605,-1600,-1599,-1601,-1606,-1613,
+-1624,-1640,-1661,-1681,-1698,-1705,-1703,-1695,-1684,-1675,-1667,-1659,-1653,-1649,-1652,-1663,-1682,-1705,-1730,-1750,-1766,
+-1777,-1783,-1785,-1784,-1780,-1777,-1776,-1779,-1782,-1782,-1776,-1762,-1743,-1723,-1709,-1702,-1704,-1712,-1725,-1737,-1746,
+-1750,-1752,-1753,-1758,-1766,-1776,-1784,-1788,-1787,-1784,-1783,-1783,-1783,-1782,-1777,-1769,-1763,-1757,-1753,-1747,-1737,
+-1724,-1710,-1698,-1689,-1680,-1669,-1655,-1637,-1618,-1600,-1582,-1564,-1544,-1523,-1502,-1484,-1467,-1451,-1434,-1415,-1395,
+-1375,-1356,-1339,-1323,-1307,-1291,-1277,-1265,-1254,-1244,-1233,-1220,-1206,-1193,-1182,-1172,-1164,-1155,-1143,-1128,-1112,
+-1097,-1083,-1072,-1063,-1056,-1049,-1041,-1033,-1024,-1015,-1007,-1000,-995,-990,-987,-983,-979,-974,-968,-963,-959,
+-959,-961,-966,-972,-979,-985,-992,-998,-1002,-1004,-1002,-999,-997,-999,-1005,-1015,-1025,-1033,-1038,-1040,-1043,
+-1046,-1051,-1056,-1060,-1062,-1062,-1062,-1062,-1063,-1065,-1068,-1072,-1074,-1075,-1074,-1071,-1067,-1064,-1061,-1059,-1055,
+-1050,-1044,-1038,-1034,-1034,-1036,-1037,-1036,-1031,-1023,-1013,-1003,-992,-981,-968,-956,-945,-936,-930,-925,-920,
+-914,-905,-892,-876,-858,-840,-824,-813,-804,-797,-786,-771,-752,-733,-718,-709,-703,-699,-694,-686,-680,
+-675,-673,-671,-667,-659,-648,-636,-626,-616,-606,-595,-581,-566,-552,-538,-522,-504,-480,-454,-427,-401,
+-378,-357,-337,-318,-300,-282,-265,-249,-234,-220,-204,-186,-163,-135,-107,-82,-64,-51,-40,-25,-4,
+18,39,56,72,90,114,142,171,194,213,233,258,288,319,345,365,383,406,434,463,484,
+494,499,508,529,555,572,570,548,519,501,503,524,560,615,701,832,1000,1174,1304,1360,1349,
+1322,1339,1433,1581,1719,1779,1734,1610,1473,1380,1352,1368,1387,1378,1339,1287,1242,1209,1180,1145,1104,
+1066,1043,1039,1045,1050,1049,1043,1039,1042,1048,1050,1047,1041,1041,1053,1076,1102,1122,1134,1143,1156,
+1178,1207,1238,1264,1284,1296,1302,1302,1297,1289,1280,1274,1271,1271,1268,1261,1250,1238,1226,1215,1204,
+1190,1172,1153,1135,1119,1104,1088,1071,1050,1024,994,958,919,880,843,811,781,750,712,667,617,
+566,518,475,438,405,378,357,343,336,331,325,315,301,284,265,247,232,223,220,222,229,
+235,238,237,234,229,226,224,223,221,222,227,239,260,287,318,351,383,416,452,491,532,
+570,602,625,637,640,637,631,620,602,571,526,467,402,341,297,273,270,280,295,308,318,
+326,335,348,368,395,427,462,495,522,541,551,557,566,583,610,643,676,703,723,737,751,
+771,798,833,870,906,939,970,1001,1034,1066,1093,1109,1114,1111,1109,1117,1137,1169,1206,1243,1278,
+1313,1349,1387,1424,1455,1478,1497,1513,1532,1556,1582,1609,1636,1660,1685,1709,1735,1761,1786,1812,1839,
+1866,1894,1921,1946,1969,1988,2004,2018,2030,2042,2056,2072,2091,2109,2126,2143,2161,2181,2202,2223,2242,
+2259,2276,2295,2320,2349,2381,2411,2439,2463,2486,2507,2527,2546,2563,2578,2591,2601,2609,2615,2621,2628,
+2638,2650,2663,2674,2680,2682,2684,2690,2699,2710,2719,2722,2721,2720,2721,2727,2732,2734,2729,2718,2705,
+2696,2691,2689,2685,2677,2667,2658,2652,2649,2646,2640,2631,2619,2609,2602,2597,2591,2584,2575,2563,2551,
+2539,2529,2520,2514,2508,2502,2537,2524,2510,2499,2497,2502,2512,2517,2514,2501,2486,2478,2479,2487,2495,
+2498,2497,2497,2499,2502,2498,2484,2463,2446,2442,2452,2466,2468,2448,2414,2382,2372,2392,2433,2475,2498,
+2500,2490,2485,2499,2534,2578,2620,2650,2665,2667,2662,2652,2641,2632,2632,2648,2681,2728,2781,2832,2877,
+2916,2953,2988,3022,3053,3079,3098,3114,3128,3144,3163,3182,3198,3209,3214,3215,3219,3230,3250,3276,3302,
+3323,3336,3341,3345,3353,3367,3385,3402,3413,3419,3422,3429,3442,3463,3487,3506,3515,3515,3511,3509,3514,
+3525,3539,3551,3561,3572,3593,3622,3655,3682,3694,3693,3688,3693,3715,3747,3772,3773,3749,3715,3700,3724,
+3790,3879,3963,4020,4041,4038,4025,4015,4009,4004,3999,3997,4002,4017,4038,4055,4062,4058,4049,4046,4055,
+4077,4106,4137,4168,4199,4228,4255,4279,4299,4316,4333,4352,4375,4403,4433,4464,4492,4514,4526,4530,4526,
+4522,4522,4525,4529,4531,4530,4525,4521,4519,4517,4513,4506,4498,4494,4497,4507,4519,4528,4532,4532,4532,
+4533,4535,4535,4531,4524,4518,4513,4511,4507,4501,4492,4482,4474,4469,4464,4456,4447,4437,4429,4426,4426,
+4428,4430,4430,4428,4425,4420,4412,4402,4390,4379,4368,4357,4342,4324,4303,4281,4261,4243,4226,4207,4185,
+4161,4137,4114,4094,4076,4060,4044,4028,4010,3986,3959,3929,3900,3876,3857,3837,3816,3792,3770,3752,3742,
+3735,3723,3700,3667,3631,3605,3601,3623,3666,3722,3779,3830,3872,3901,3918,3919,3904,3871,3826,3774,3723,
+3683,3658,3653,3668,3703,3752,3809,3867,3919,3957,3976,3972,3944,3897,3835,3770,3711,3670,3650,3650,3661,
+3675,3684,3685,3680,3672,3663,3649,3624,3585,3534,3478,3424,3377,3334,3295,3258,3224,3195,3170,3145,3114,
+3075,3030,2989,2959,2941,2929,2914,2888,2850,2808,2769,2734,2703,2670,2632,2590,2549,2512,2480,2450,2418,
+2383,2346,2310,2276,2244,2210,2174,2136,2097,2060,2024,1989,1953,1916,1878,1841,1804,1768,1732,1695,1657,
+1620,1583,1546,1509,1472,1433,1395,1357,1319,1284,1250,1219,1190,1160,1128,1093,1055,1018,983,949,916,
+881,846,810,774,738,702,664,625,585,546,508,471,432,390,346,302,261,224,188,153,116,
+78,39,-1,-42,-84,-124,-162,-197,-229,-262,-297,-334,-372,-409,-443,-475,-507,-539,-573,-606,-639,
+-672,-706,-744,-784,-825,-864,-899,-930,-957,-984,-1012,-1041,-1072,-1106,-1141,-1178,-1213,-1245,-1274,-1300,-1325,
+-1351,-1378,-1407,-1437,-1467,-1496,-1526,-1554,-1582,-1609,-1636,-1662,-1687,-1711,-1735,-1757,-1781,-1806,-1832,-1858,-1882,
+-1903,-1923,-1944,-1967,-1991,-2013,-2031,-2044,-2055,-2065,-2078,-2091,-2105,-2118,-2130,-2142,-2154,-2164,-2172,-2178,-2185,
+-2195,-2210,-2230,-2249,-2265,-2275,-2280,-2284,-2290,-2298,-2307,-2315,-2324,-2332,-2341,-2350,-2358,-2362,-2363,-2361,-2357,
+-2353,-2351,-2351,-2353,-2355,-2358,-2360,-2360,-2357,-2351,-2343,-2334,-2324,-2314,-2304,-2294,-2286,-2278,-2270,-2262,-2253,
+-2243,-2234,-2226,-2219,-2212,-2203,-2192,-2180,-2166,-2152,-2137,-2121,-2104,-2089,-2076,-2067,-2059,-2050,-2038,-2025,-2010,
+-1996,-1983,-1971,-1957,-1942,-1927,-1914,-1904,-1896,-1887,-1876,-1863,-1848,-1834,-1821,-1811,-1807,-1812,-1825,-1844,-1860,
+-1867,-1861,-1842,-1820,-1802,-1790,-1782,-1774,-1760,-1743,-1729,-1723,-1726,-1732,-1733,-1723,-1708,-1695,-1695,-1712,-1739,
+-1768,-1788,-1797,-1798,-1796,-1797,-1801,-1805,-1803,-1793,-1774,-1750,-1726,-1706,-1695,-1695,-1705,-1721,-1737,-1745,-1745,
+-1739,-1730,-1724,-1720,-1717,-1711,-1703,-1697,-1695,-1701,-1710,-1718,-1720,-1715,-1709,-1706,-1709,-1713,-1715,-1712,-1705,
+-1698,-1695,-1695,-1693,-1684,-1666,-1641,-1614,-1592,-1575,-1559,-1540,-1517,-1492,-1469,-1450,-1433,-1416,-1396,-1375,-1358,
+-1348,-1342,-1330,-1302,-1250,-1175,-1087,-1005,-948,-930,-956,-1022,-1113,-1208,-1283,-1314,-1292,-1219,-1116,-1013,-936,
+-900,-903,-931,-964,-992,-1010,-1023,-1035,-1047,-1058,-1063,-1063,-1061,-1058,-1057,-1055,-1051,-1045,-1041,-1042,-1051,
+-1065,-1078,-1087,-1090,-1090,-1090,-1097,-1114,-1141,-1176,-1214,-1250,-1279,-1302,-1324,-1348,-1380,-1416,-1449,-1473,-1487,
+-1496,-1509,-1533,-1564,-1599,-1629,-1652,-1672,-1694,-1721,-1751,-1775,-1790,-1795,-1793,-1791,-1792,-1796,-1797,-1793,-1778,
+-1752,-1716,-1678,-1651,-1650,-1683,-1749,-1833,-1912,-1969,-2000,-2012,-2018,-2028,-2042,-2051,-2049,-2034,-2013,-1994,-1980,
+-1971,-1961,-1949,-1935,-1925,-1921,-1921,-1921,-1921,-1920,-1922,-1930,-1940,-1949,-1952,-1950,-1944,-1940,-1938,-1936,-1930,
+-1922,-1914,-1911,-1914,-1921,-1926,-1925,-1917,-1907,-1900,-1897,-1897,-1898,-1899,-1900,-1901,-1902,-1900,-1895,-1885,-1873,
+-1861,-1852,-1847,-1846,-1848,-1855,-1866,-1881,-1896,-1909,-1913,-1909,-1899,-1885,-1873,-1866,-1863,-1864,-1868,-1871,-1875,
+-1877,-1877,-1876,-1874,-1871,-1866,-1858,-1847,-1834,-1819,-1804,-1789,-1776,-1763,-1750,-1737,-1725,-1714,-1706,-1699,-1692,
+-1687,-1683,-1680,-1677,-1673,-1667,-1658,-1648,-1640,-1634,-1630,-1628,-1625,-1625,-1627,-1635,-1648,-1666,-1684,-1700,-1712,
+-1719,-1719,-1713,-1699,-1680,-1662,-1648,-1644,-1651,-1668,-1692,-1720,-1749,-1778,-1801,-1816,-1822,-1819,-1810,-1800,-1793,
+-1788,-1783,-1774,-1760,-1742,-1722,-1705,-1696,-1698,-1709,-1727,-1747,-1762,-1769,-1769,-1765,-1765,-1769,-1779,-1789,-1797,
+-1799,-1799,-1798,-1797,-1797,-1794,-1788,-1780,-1773,-1769,-1767,-1764,-1759,-1750,-1739,-1728,-1718,-1707,-1692,-1674,-1653,
+-1632,-1612,-1594,-1576,-1556,-1533,-1510,-1489,-1470,-1453,-1436,-1418,-1399,-1381,-1364,-1348,-1332,-1314,-1294,-1276,-1260,
+-1248,-1237,-1227,-1216,-1204,-1192,-1181,-1173,-1166,-1158,-1149,-1138,-1124,-1110,-1097,-1086,-1077,-1070,-1063,-1056,-1048,
+-1040,-1031,-1023,-1015,-1009,-1003,-998,-993,-987,-982,-978,-974,-973,-972,-974,-977,-981,-986,-993,-1000,-1007,
+-1012,-1014,-1013,-1012,-1012,-1017,-1025,-1036,-1048,-1058,-1065,-1071,-1075,-1079,-1081,-1082,-1082,-1081,-1081,-1082,-1082,
+-1083,-1082,-1081,-1081,-1082,-1084,-1086,-1088,-1088,-1086,-1084,-1080,-1077,-1072,-1066,-1061,-1058,-1056,-1055,-1054,-1051,
+-1044,-1035,-1026,-1018,-1009,-1000,-988,-975,-962,-951,-943,-939,-936,-932,-923,-908,-886,-862,-838,-820,-808,
+-801,-794,-785,-772,-755,-739,-727,-719,-714,-709,-704,-698,-693,-691,-690,-687,-680,-669,-658,-648,-640,
+-633,-625,-614,-600,-585,-571,-557,-542,-524,-501,-477,-452,-428,-406,-384,-362,-341,-321,-302,-285,-269,
+-255,-241,-225,-206,-181,-154,-126,-102,-85,-73,-61,-44,-22,0,21,36,49,66,89,119,149,
+174,195,217,242,273,305,332,353,370,389,414,440,462,476,487,501,522,546,560,555,534,
+507,488,488,506,541,601,698,841,1016,1189,1311,1355,1335,1300,1311,1397,1536,1666,1723,1681,1566,
+1439,1352,1325,1337,1348,1331,1285,1229,1183,1154,1134,1111,1081,1050,1029,1021,1023,1026,1025,1021,1020,
+1024,1031,1034,1034,1034,1043,1067,1101,1135,1161,1175,1182,1192,1212,1241,1271,1295,1308,1308,1300,1287,
+1275,1265,1261,1263,1270,1277,1280,1277,1269,1260,1254,1249,1245,1237,1225,1208,1190,1173,1157,1140,1122,
+1098,1069,1035,998,959,922,890,862,836,809,777,741,701,660,622,586,552,521,495,473,458,
+446,434,420,400,377,353,330,310,293,280,273,272,276,281,284,283,277,271,269,275,290,
+310,334,358,384,410,438,469,502,539,578,617,654,687,712,728,734,732,725,715,704,689,
+665,629,579,518,457,408,379,371,380,395,409,420,428,437,449,465,484,505,531,562,597,
+630,654,665,664,657,653,660,678,703,729,750,768,786,809,840,875,910,940,964,986,1011,
+1041,1075,1108,1135,1151,1157,1159,1162,1170,1187,1212,1245,1286,1332,1381,1429,1471,1503,1524,1539,1550,
+1562,1576,1593,1612,1634,1657,1682,1708,1734,1759,1782,1805,1828,1852,1876,1900,1924,1948,1970,1991,2010,
+2027,2044,2060,2077,2094,2109,2123,2137,2153,2172,2193,2214,2234,2251,2269,2289,2314,2344,2377,2409,2438,
+2462,2483,2503,2522,2540,2558,2575,2588,2598,2605,2611,2618,2630,2646,2664,2680,2689,2691,2690,2690,2694,
+2702,2711,2716,2717,2717,2718,2723,2729,2734,2734,2729,2723,2719,2720,2723,2723,2717,2707,2695,2684,2678,
+2673,2666,2657,2646,2637,2631,2627,2624,2619,2612,2603,2593,2585,2576,2569,2561,2555,2547,2537,2576,2557,
+2535,2516,2506,2509,2520,2531,2534,2528,2520,2518,2524,2536,2543,2540,2528,2513,2503,2500,2499,2493,2479,
+2462,2449,2446,2450,2454,2452,2447,2447,2460,2486,2514,2534,2537,2528,2520,2524,2547,2581,2617,2646,2664,
+2674,2678,2676,2666,2651,2640,2645,2676,2732,2802,2870,2923,2959,2983,3007,3037,3070,3102,3126,3140,3149,
+3159,3174,3192,3209,3219,3223,3223,3225,3234,3253,3280,3309,3334,3351,3361,3365,3368,3375,3385,3398,3409,
+3418,3424,3433,3447,3467,3490,3510,3523,3527,3524,3522,3524,3534,3549,3564,3576,3589,3606,3630,3660,3688,
+3705,3707,3700,3694,3700,3718,3737,3742,3723,3690,3667,3677,3731,3819,3913,3984,4017,4019,4007,3999,4002,
+4008,4008,4000,3989,3987,3998,4019,4039,4048,4047,4043,4046,4063,4091,4124,4155,4182,4206,4232,4261,4291,
+4318,4341,4360,4379,4402,4430,4461,4493,4521,4541,4552,4556,4557,4558,4562,4568,4573,4575,4573,4569,4565,
+4561,4556,4549,4542,4536,4537,4544,4556,4567,4574,4574,4570,4566,4561,4555,4546,4535,4523,4514,4510,4508,
+4504,4498,4487,4476,4466,4459,4452,4444,4434,4423,4416,4413,4415,4418,4419,4418,4415,4410,4405,4400,4394,
+4387,4378,4367,4352,4333,4310,4285,4261,4239,4219,4201,4183,4166,4148,4132,4115,4097,4079,4060,4043,4026,
+4009,3988,3962,3933,3906,3883,3865,3849,3832,3811,3790,3770,3755,3744,3732,3713,3687,3657,3631,3613,3608,
+3614,3626,3644,3665,3689,3716,3743,3764,3775,3774,3759,3734,3704,3675,3652,3638,3637,3647,3668,3695,3726,
+3756,3783,3803,3813,3809,3789,3755,3714,3675,3650,3643,3653,3673,3692,3701,3699,3691,3682,3676,3670,3658,
+3636,3603,3563,3521,3476,3427,3372,3314,3258,3213,3181,3160,3139,3108,3065,3017,2972,2940,2918,2902,2882,
+2855,2821,2786,2753,2722,2690,2653,2611,2569,2531,2497,2467,2436,2404,2369,2334,2299,2263,2226,2187,2146,
+2106,2067,2030,1994,1957,1920,1882,1846,1811,1777,1741,1703,1663,1622,1584,1548,1515,1482,1448,1412,1374,
+1335,1298,1265,1234,1204,1172,1138,1100,1063,1027,995,965,935,902,867,831,795,760,723,685,643,
+600,558,518,480,442,404,363,322,281,242,205,170,135,98,60,19,-23,-65,-105,-141,-173,
+-204,-237,-272,-309,-345,-379,-410,-440,-472,-506,-542,-576,-610,-643,-679,-718,-759,-798,-833,-864,-893,
+-923,-954,-987,-1019,-1051,-1082,-1114,-1148,-1183,-1215,-1244,-1269,-1291,-1315,-1343,-1373,-1405,-1436,-1466,-1494,-1522,
+-1550,-1578,-1606,-1633,-1659,-1685,-1710,-1734,-1759,-1785,-1811,-1836,-1860,-1882,-1905,-1927,-1951,-1975,-1996,-2013,-2025,
+-2034,-2044,-2056,-2071,-2087,-2102,-2113,-2122,-2129,-2136,-2145,-2157,-2171,-2186,-2202,-2218,-2232,-2245,-2256,-2265,-2274,
+-2282,-2290,-2298,-2307,-2316,-2325,-2334,-2342,-2348,-2351,-2353,-2353,-2353,-2352,-2351,-2351,-2353,-2358,-2364,-2368,-2369,
+-2364,-2355,-2343,-2331,-2320,-2309,-2297,-2286,-2276,-2267,-2260,-2254,-2246,-2237,-2228,-2219,-2210,-2202,-2192,-2181,-2168,
+-2155,-2141,-2127,-2114,-2100,-2088,-2076,-2067,-2059,-2050,-2039,-2028,-2016,-2005,-1994,-1982,-1969,-1953,-1938,-1925,-1915,
+-1907,-1899,-1890,-1879,-1867,-1853,-1840,-1829,-1822,-1823,-1833,-1850,-1867,-1876,-1873,-1859,-1838,-1820,-1808,-1800,-1791,
+-1776,-1758,-1742,-1735,-1738,-1745,-1748,-1741,-1725,-1710,-1706,-1719,-1744,-1772,-1792,-1800,-1799,-1796,-1797,-1805,-1814,
+-1818,-1813,-1797,-1773,-1747,-1725,-1711,-1710,-1719,-1735,-1752,-1763,-1767,-1765,-1761,-1756,-1752,-1747,-1739,-1730,-1723,
+-1721,-1725,-1730,-1732,-1727,-1719,-1714,-1715,-1723,-1732,-1737,-1735,-1728,-1722,-1723,-1727,-1727,-1716,-1692,-1662,-1632,
+-1611,-1597,-1585,-1569,-1546,-1520,-1497,-1483,-1474,-1465,-1451,-1431,-1407,-1384,-1358,-1323,-1271,-1200,-1114,-1031,-969,
+-945,-966,-1027,-1116,-1213,-1298,-1350,-1358,-1318,-1239,-1143,-1053,-991,-963,-968,-992,-1021,-1046,-1064,-1077,-1087,
+-1094,-1100,-1103,-1107,-1112,-1120,-1126,-1128,-1126,-1120,-1118,-1124,-1139,-1158,-1174,-1181,-1180,-1175,-1173,-1182,-1204,
+-1238,-1279,-1320,-1356,-1383,-1408,-1435,-1470,-1515,-1563,-1607,-1640,-1662,-1680,-1699,-1726,-1756,-1784,-1805,-1820,-1831,
+-1845,-1861,-1878,-1891,-1897,-1899,-1899,-1901,-1903,-1903,-1900,-1892,-1881,-1867,-1849,-1832,-1820,-1825,-1852,-1902,-1964,
+-2022,-2062,-2081,-2086,-2088,-2096,-2109,-2120,-2119,-2107,-2089,-2070,-2056,-2044,-2030,-2015,-1999,-1987,-1981,-1980,-1980,
+-1977,-1975,-1976,-1982,-1993,-2003,-2009,-2008,-2004,-1999,-1996,-1992,-1986,-1978,-1972,-1972,-1978,-1988,-1995,-1996,-1989,
+-1979,-1971,-1967,-1968,-1969,-1969,-1966,-1961,-1956,-1951,-1945,-1937,-1928,-1919,-1910,-1902,-1894,-1888,-1887,-1893,-1909,
+-1931,-1955,-1974,-1984,-1983,-1973,-1957,-1940,-1925,-1913,-1907,-1906,-1909,-1915,-1920,-1923,-1923,-1918,-1911,-1901,-1889,
+-1876,-1864,-1853,-1844,-1835,-1825,-1813,-1798,-1784,-1771,-1760,-1751,-1743,-1735,-1727,-1721,-1715,-1710,-1705,-1698,-1691,
+-1684,-1679,-1675,-1671,-1663,-1653,-1643,-1635,-1635,-1645,-1665,-1692,-1719,-1742,-1755,-1757,-1748,-1730,-1709,-1689,-1673,
+-1664,-1662,-1667,-1682,-1705,-1736,-1769,-1799,-1821,-1832,-1834,-1831,-1825,-1818,-1808,-1795,-1777,-1755,-1731,-1712,-1701,
+-1702,-1717,-1742,-1769,-1790,-1800,-1799,-1791,-1782,-1779,-1783,-1791,-1798,-1803,-1805,-1807,-1808,-1808,-1805,-1799,-1791,
+-1783,-1778,-1776,-1775,-1772,-1765,-1756,-1746,-1735,-1722,-1707,-1687,-1667,-1646,-1627,-1610,-1591,-1570,-1546,-1523,-1501,
+-1482,-1464,-1447,-1428,-1408,-1390,-1373,-1358,-1342,-1325,-1306,-1286,-1268,-1252,-1239,-1228,-1216,-1204,-1191,-1179,-1169,
+-1160,-1152,-1143,-1134,-1124,-1114,-1103,-1093,-1083,-1074,-1066,-1059,-1051,-1044,-1036,-1028,-1021,-1016,-1011,-1006,-1002,
+-998,-994,-992,-991,-991,-993,-994,-996,-999,-1002,-1007,-1012,-1017,-1020,-1021,-1019,-1018,-1019,-1024,-1031,-1041,
+-1051,-1061,-1070,-1079,-1086,-1091,-1094,-1093,-1090,-1088,-1089,-1091,-1094,-1095,-1094,-1092,-1090,-1090,-1094,-1098,-1102,
+-1103,-1102,-1100,-1098,-1096,-1093,-1089,-1085,-1080,-1075,-1071,-1066,-1059,-1050,-1041,-1034,-1028,-1024,-1018,-1010,-999,
+-985,-972,-963,-956,-952,-947,-937,-919,-895,-868,-842,-820,-805,-795,-785,-775,-762,-749,-739,-733,-729,
+-727,-722,-717,-713,-712,-712,-711,-707,-697,-685,-673,-664,-657,-651,-643,-630,-616,-602,-589,-577,-563,
+-544,-522,-498,-474,-452,-430,-409,-386,-363,-341,-322,-304,-289,-275,-261,-245,-226,-202,-175,-148,-125,
+-108,-95,-82,-65,-43,-20,0,15,29,46,69,99,131,158,181,204,229,259,290,316,336,
+353,370,392,417,441,462,480,500,523,543,553,546,524,498,478,472,482,511,571,674,827,
+1013,1191,1314,1357,1334,1294,1298,1373,1501,1623,1681,1649,1549,1433,1350,1317,1315,1312,1284,1231,1173,
+1130,1107,1097,1084,1064,1038,1016,1005,1003,1005,1006,1007,1009,1014,1019,1023,1026,1032,1050,1082,1123,
+1163,1192,1209,1218,1232,1254,1284,1312,1328,1327,1308,1279,1248,1223,1209,1209,1220,1239,1258,1273,1280,
+1282,1281,1280,1281,1281,1278,1271,1259,1246,1231,1217,1199,1177,1149,1115,1076,1035,995,958,926,901,
+880,863,846,827,805,780,751,718,682,645,610,581,557,537,518,496,472,448,425,406,389,
+374,361,352,347,348,352,354,352,345,339,339,350,374,409,447,483,513,539,563,590,624,
+663,707,749,785,810,823,824,813,796,776,756,736,715,689,654,609,560,516,486,475,479,
+490,499,503,503,507,518,538,561,582,598,615,637,668,703,733,750,750,739,726,723,731,
+748,766,782,796,813,839,873,911,947,975,994,1010,1028,1051,1079,1109,1136,1157,1173,1185,1194,
+1202,1214,1232,1262,1305,1359,1418,1475,1521,1553,1574,1587,1597,1606,1615,1623,1633,1647,1666,1691,1719,
+1746,1771,1791,1808,1825,1843,1864,1886,1909,1932,1955,1975,1994,2012,2030,2049,2069,2087,2105,2120,2135,
+2150,2168,2188,2210,2233,2254,2276,2299,2324,2351,2378,2406,2432,2456,2478,2497,2515,2531,2547,2562,2575,
+2586,2595,2603,2613,2629,2648,2668,2684,2692,2693,2690,2689,2692,2698,2703,2706,2706,2706,2710,2718,2726,
+2732,2732,2731,2732,2738,2746,2753,2753,2745,2731,2717,2706,2699,2691,2680,2668,2657,2650,2646,2645,2642,
+2637,2629,2623,2620,2618,2616,2612,2606,2599,2590,2576,2613,2596,2571,2546,2528,2522,2528,2537,2541,2538,
+2532,2530,2537,2549,2555,2548,2528,2504,2486,2479,2483,2489,2490,2485,2479,2477,2481,2491,2504,2517,2530,
+2544,2555,2560,2557,2549,2544,2552,2575,2608,2641,2664,2675,2679,2682,2686,2688,2685,2678,2681,2705,2760,
+2838,2921,2988,3026,3038,3039,3045,3065,3095,3127,3150,3163,3172,3182,3197,3213,3225,3229,3229,3228,3236,
+3255,3284,3316,3344,3365,3378,3385,3390,3394,3400,3406,3412,3417,3424,3433,3447,3467,3488,3509,3525,3534,
+3538,3538,3540,3545,3554,3566,3580,3596,3616,3642,3672,3699,3718,3723,3718,3711,3710,3720,3731,3732,3712,
+3675,3637,3625,3658,3734,3834,3924,3979,3996,3986,3973,3972,3983,3997,3999,3989,3974,3966,3972,3989,4007,
+4019,4024,4031,4048,4078,4116,4152,4181,4202,4222,4246,4277,4312,4344,4370,4390,4411,4434,4464,4495,4525,
+4549,4565,4574,4581,4587,4595,4604,4612,4618,4621,4621,4619,4616,4610,4601,4590,4582,4578,4583,4593,4605,
+4613,4615,4611,4604,4597,4591,4583,4571,4554,4538,4524,4517,4513,4510,4502,4491,4477,4465,4455,4447,4438,
+4430,4423,4419,4420,4423,4424,4422,4415,4408,4401,4398,4397,4395,4388,4377,4360,4340,4320,4300,4282,4265,
+4246,4224,4200,4175,4153,4135,4122,4110,4096,4078,4059,4039,4020,4001,3982,3959,3933,3907,3884,3866,3852,
+3838,3824,3807,3790,3774,3760,3745,3729,3710,3690,3670,3651,3633,3614,3597,3583,3578,3586,3607,3636,3668,
+3694,3709,3711,3701,3686,3670,3657,3649,3645,3641,3633,3619,3603,3593,3596,3619,3658,3704,3743,3764,3763,
+3747,3726,3713,3714,3725,3738,3744,3739,3726,3711,3696,3684,3670,3653,3633,3611,3588,3558,3515,3453,3375,
+3292,3221,3171,3145,3131,3115,3086,3042,2991,2946,2912,2889,2870,2850,2826,2798,2771,2743,2714,2681,2642,
+2601,2560,2521,2486,2453,2419,2385,2348,2312,2274,2235,2195,2154,2114,2075,2037,1999,1961,1923,1885,1849,
+1814,1781,1747,1710,1671,1630,1591,1555,1521,1489,1457,1422,1386,1349,1313,1280,1248,1216,1182,1146,1108,
+1071,1036,1006,976,946,914,879,842,806,770,733,694,652,609,566,525,486,449,411,374,335,
+295,257,219,183,148,113,77,37,-3,-45,-84,-119,-152,-183,-217,-252,-288,-322,-353,-382,-412,
+-444,-480,-517,-553,-587,-623,-660,-699,-738,-774,-804,-830,-858,-889,-925,-964,-1000,-1032,-1062,-1092,-1125,
+-1159,-1191,-1219,-1242,-1264,-1287,-1314,-1345,-1377,-1407,-1435,-1463,-1491,-1521,-1550,-1579,-1607,-1633,-1660,-1686,-1713,
+-1739,-1763,-1787,-1810,-1834,-1858,-1882,-1908,-1933,-1957,-1978,-1995,-2008,-2018,-2028,-2040,-2055,-2072,-2086,-2097,-2103,
+-2107,-2113,-2124,-2140,-2159,-2177,-2192,-2204,-2215,-2226,-2239,-2253,-2267,-2279,-2288,-2297,-2305,-2315,-2325,-2334,-2340,
+-2345,-2348,-2351,-2354,-2358,-2359,-2360,-2362,-2366,-2373,-2382,-2387,-2387,-2378,-2364,-2347,-2331,-2317,-2304,-2292,-2280,
+-2269,-2260,-2253,-2246,-2239,-2230,-2220,-2211,-2204,-2196,-2188,-2177,-2165,-2152,-2140,-2129,-2120,-2110,-2099,-2087,-2075,
+-2064,-2053,-2043,-2033,-2025,-2017,-2010,-2001,-1990,-1977,-1962,-1948,-1936,-1925,-1915,-1904,-1894,-1885,-1875,-1865,-1854,
+-1845,-1841,-1846,-1859,-1875,-1887,-1888,-1876,-1857,-1838,-1825,-1816,-1808,-1795,-1778,-1762,-1754,-1755,-1763,-1767,-1762,
+-1747,-1730,-1722,-1729,-1749,-1775,-1796,-1807,-1809,-1809,-1811,-1817,-1825,-1830,-1826,-1813,-1793,-1770,-1750,-1737,-1734,
+-1742,-1758,-1776,-1790,-1798,-1798,-1795,-1789,-1782,-1775,-1766,-1757,-1751,-1748,-1748,-1749,-1746,-1740,-1733,-1730,-1733,
+-1742,-1750,-1753,-1750,-1746,-1745,-1749,-1754,-1753,-1739,-1712,-1680,-1653,-1635,-1624,-1612,-1594,-1569,-1543,-1523,-1513,
+-1509,-1501,-1483,-1452,-1411,-1366,-1318,-1268,-1214,-1156,-1101,-1060,-1044,-1058,-1101,-1165,-1239,-1310,-1363,-1388,-1377,
+-1328,-1252,-1165,-1090,-1041,-1025,-1036,-1061,-1087,-1106,-1118,-1124,-1130,-1135,-1141,-1149,-1159,-1173,-1189,-1203,-1211,
+-1212,-1210,-1211,-1219,-1235,-1254,-1271,-1279,-1279,-1274,-1272,-1281,-1303,-1336,-1375,-1413,-1444,-1469,-1495,-1530,-1576,
+-1634,-1694,-1747,-1788,-1816,-1838,-1859,-1884,-1910,-1932,-1947,-1957,-1965,-1974,-1985,-1993,-1997,-1997,-1998,-2002,-2009,
+-2015,-2016,-2010,-2001,-1993,-1989,-1988,-1990,-1993,-2002,-2022,-2055,-2095,-2133,-2159,-2169,-2169,-2169,-2174,-2183,-2190,
+-2189,-2178,-2161,-2145,-2131,-2119,-2104,-2087,-2070,-2058,-2051,-2048,-2045,-2041,-2036,-2034,-2038,-2047,-2058,-2065,-2067,
+-2065,-2061,-2058,-2055,-2050,-2044,-2039,-2038,-2043,-2051,-2057,-2058,-2054,-2047,-2042,-2040,-2040,-2039,-2035,-2027,-2017,
+-2007,-1999,-1993,-1987,-1981,-1975,-1967,-1958,-1947,-1935,-1926,-1925,-1934,-1953,-1977,-2002,-2022,-2034,-2037,-2032,-2020,
+-2004,-1986,-1969,-1957,-1951,-1950,-1950,-1950,-1949,-1945,-1941,-1935,-1927,-1918,-1909,-1899,-1890,-1881,-1872,-1861,-1849,
+-1837,-1825,-1815,-1805,-1795,-1783,-1771,-1759,-1750,-1743,-1738,-1733,-1728,-1723,-1720,-1718,-1716,-1712,-1702,-1689,-1674,
+-1665,-1665,-1675,-1695,-1720,-1743,-1760,-1769,-1771,-1768,-1762,-1752,-1739,-1722,-1703,-1684,-1671,-1671,-1684,-1708,-1739,
+-1770,-1797,-1818,-1834,-1844,-1849,-1847,-1838,-1820,-1797,-1770,-1746,-1730,-1727,-1738,-1760,-1787,-1811,-1824,-1827,-1820,
+-1812,-1805,-1804,-1806,-1808,-1810,-1810,-1811,-1813,-1815,-1815,-1811,-1805,-1799,-1794,-1791,-1787,-1782,-1773,-1762,-1750,
+-1738,-1725,-1710,-1694,-1676,-1658,-1641,-1623,-1603,-1581,-1558,-1535,-1515,-1498,-1482,-1465,-1446,-1425,-1405,-1386,-1370,
+-1355,-1339,-1321,-1303,-1284,-1267,-1252,-1238,-1224,-1211,-1198,-1185,-1172,-1160,-1148,-1138,-1128,-1120,-1111,-1103,-1093,
+-1082,-1072,-1063,-1055,-1048,-1041,-1034,-1027,-1022,-1019,-1017,-1015,-1013,-1010,-1008,-1007,-1008,-1010,-1012,-1015,-1017,
+-1019,-1021,-1024,-1028,-1031,-1032,-1031,-1029,-1026,-1026,-1028,-1032,-1037,-1044,-1053,-1063,-1073,-1083,-1090,-1093,-1092,
+-1089,-1086,-1086,-1088,-1090,-1092,-1091,-1090,-1090,-1091,-1095,-1100,-1103,-1105,-1106,-1107,-1108,-1109,-1108,-1105,-1100,
+-1093,-1086,-1080,-1073,-1066,-1057,-1049,-1042,-1037,-1034,-1030,-1025,-1017,-1007,-996,-987,-979,-972,-963,-949,-931,
+-907,-881,-856,-834,-816,-801,-787,-773,-761,-751,-746,-744,-744,-741,-736,-731,-728,-729,-731,-731,-727,
+-717,-704,-692,-683,-676,-669,-658,-644,-630,-618,-608,-598,-585,-567,-544,-520,-496,-475,-454,-433,-411,
+-388,-366,-346,-329,-313,-298,-283,-267,-249,-226,-200,-173,-148,-129,-114,-101,-84,-63,-40,-18,0,
+17,36,60,90,120,147,170,192,215,241,269,294,315,335,355,379,405,431,455,478,501,
+524,542,549,541,522,498,477,464,463,481,532,633,788,979,1166,1301,1358,1347,1315,1315,1376,
+1484,1590,1641,1615,1528,1425,1346,1307,1293,1276,1239,1183,1126,1087,1072,1070,1066,1052,1030,1008,994,
+989,991,994,997,1000,1003,1007,1010,1014,1025,1048,1085,1129,1171,1203,1224,1240,1259,1287,1319,1346,
+1356,1343,1311,1266,1220,1184,1163,1161,1175,1200,1229,1256,1275,1287,1292,1294,1293,1291,1288,1283,1279,
+1274,1268,1257,1241,1218,1187,1151,1112,1072,1033,996,964,940,923,915,910,906,898,883,861,829,
+792,751,711,675,644,617,591,566,542,520,503,490,481,474,469,466,466,470,475,477,473,
+463,453,448,454,475,505,539,569,592,608,624,644,673,711,754,797,834,860,873,873,860,
+837,807,775,744,716,688,658,625,594,568,555,555,563,571,572,567,562,564,581,608,636,
+658,669,675,685,704,732,760,780,788,789,793,806,828,852,869,875,876,881,898,930,970,
+1010,1041,1061,1076,1089,1105,1123,1142,1161,1181,1200,1219,1235,1246,1256,1268,1292,1332,1388,1450,1508,
+1553,1583,1603,1618,1633,1647,1659,1665,1669,1674,1686,1707,1733,1760,1782,1799,1812,1824,1840,1860,1884,
+1908,1930,1950,1968,1983,1999,2015,2035,2056,2077,2099,2119,2138,2155,2174,2193,2214,2237,2260,2285,2309,
+2332,2354,2375,2397,2419,2442,2464,2483,2497,2509,2520,2533,2548,2562,2576,2588,2600,2615,2632,2649,2663,
+2670,2671,2670,2671,2675,2681,2687,2690,2692,2697,2705,2716,2727,2734,2737,2740,2746,2758,2770,2777,2774,
+2763,2747,2733,2724,2717,2708,2697,2683,2672,2666,2664,2662,2658,2651,2645,2642,2643,2645,2646,2643,2638,
+2631,2624,2613,2640,2633,2616,2592,2568,2551,2543,2540,2535,2525,2514,2509,2515,2528,2538,2536,2519,2494,
+2472,2463,2469,2483,2499,2509,2514,2518,2525,2535,2547,2559,2568,2572,2569,2561,2551,2547,2556,2581,2616,
+2651,2676,2686,2686,2684,2687,2697,2708,2716,2725,2746,2790,2861,2947,3026,3078,3096,3088,3074,3072,3089,
+3120,3151,3174,3188,3197,3208,3222,3235,3243,3244,3243,3248,3263,3289,3320,3348,3369,3382,3390,3398,3406,
+3413,3417,3419,3420,3423,3431,3445,3465,3486,3506,3521,3532,3541,3547,3553,3559,3564,3571,3579,3593,3615,
+3643,3676,3705,3726,3734,3733,3729,3730,3739,3750,3750,3730,3687,3635,3598,3600,3652,3741,3841,3921,3964,
+3970,3957,3946,3948,3961,3973,3974,3964,3950,3944,3949,3963,3979,3992,4004,4021,4050,4089,4130,4165,4190,
+4209,4230,4258,4295,4334,4369,4397,4418,4439,4464,4494,4525,4553,4574,4588,4598,4606,4615,4624,4631,4637,
+4641,4646,4652,4659,4663,4662,4655,4645,4637,4636,4643,4655,4665,4667,4661,4649,4636,4627,4621,4614,4603,
+4586,4567,4550,4538,4529,4521,4511,4497,4483,4470,4460,4453,4446,4440,4435,4433,4434,4435,4433,4427,4417,
+4408,4403,4403,4404,4401,4391,4372,4348,4327,4312,4305,4303,4297,4282,4255,4218,4178,4143,4118,4103,4094,
+4086,4073,4055,4033,4011,3990,3969,3947,3924,3899,3876,3857,3842,3830,3820,3810,3799,3787,3773,3759,3743,
+3729,3715,3703,3689,3671,3649,3624,3602,3589,3590,3605,3629,3656,3678,3689,3689,3679,3667,3658,3655,3657,
+3659,3651,3625,3582,3529,3486,3472,3501,3573,3672,3772,3849,3887,3886,3860,3827,3804,3794,3794,3796,3793,
+3782,3765,3743,3718,3692,3664,3641,3624,3614,3601,3574,3521,3439,3340,3244,3171,3128,3111,3104,3090,3060,
+3018,2971,2931,2900,2877,2855,2832,2805,2778,2752,2725,2697,2663,2626,2585,2545,2505,2468,2431,2394,2356,
+2317,2277,2236,2196,2156,2117,2079,2043,2006,1969,1931,1893,1856,1821,1786,1752,1717,1680,1642,1604,1567,
+1530,1494,1459,1424,1391,1358,1327,1295,1262,1228,1192,1155,1119,1085,1052,1019,987,954,919,882,845,
+807,770,732,693,654,614,574,534,494,455,416,378,341,304,266,228,192,156,122,86,49,
+9,-30,-68,-102,-133,-164,-197,-232,-267,-301,-332,-362,-392,-426,-463,-500,-536,-570,-605,-642,-680,
+-717,-750,-777,-801,-828,-862,-900,-941,-979,-1012,-1041,-1071,-1104,-1138,-1170,-1197,-1220,-1241,-1266,-1294,-1325,
+-1356,-1384,-1410,-1437,-1467,-1498,-1530,-1558,-1584,-1609,-1634,-1662,-1690,-1717,-1742,-1764,-1785,-1809,-1835,-1863,-1891,
+-1917,-1941,-1962,-1979,-1994,-2005,-2016,-2027,-2040,-2054,-2068,-2080,-2087,-2094,-2101,-2114,-2130,-2149,-2166,-2179,-2189,
+-2197,-2208,-2223,-2241,-2259,-2274,-2285,-2294,-2304,-2315,-2325,-2334,-2340,-2344,-2348,-2353,-2359,-2363,-2366,-2367,-2368,
+-2374,-2384,-2394,-2401,-2398,-2387,-2368,-2348,-2330,-2315,-2303,-2291,-2279,-2268,-2259,-2251,-2243,-2234,-2224,-2214,-2205,
+-2200,-2195,-2189,-2180,-2168,-2156,-2145,-2137,-2129,-2122,-2112,-2100,-2087,-2074,-2063,-2053,-2045,-2038,-2032,-2026,-2018,
+-2009,-1999,-1987,-1975,-1963,-1950,-1936,-1923,-1912,-1904,-1898,-1892,-1884,-1873,-1865,-1862,-1869,-1883,-1895,-1899,-1891,
+-1873,-1853,-1837,-1829,-1823,-1814,-1801,-1786,-1776,-1773,-1778,-1781,-1777,-1764,-1747,-1735,-1736,-1753,-1778,-1803,-1822,
+-1831,-1834,-1834,-1835,-1836,-1834,-1828,-1816,-1801,-1784,-1770,-1760,-1760,-1769,-1786,-1807,-1825,-1834,-1834,-1827,-1816,
+-1806,-1797,-1790,-1784,-1779,-1776,-1773,-1771,-1768,-1765,-1762,-1761,-1762,-1764,-1765,-1763,-1760,-1759,-1763,-1769,-1772,
+-1768,-1752,-1727,-1702,-1681,-1667,-1655,-1640,-1618,-1591,-1566,-1548,-1538,-1529,-1510,-1477,-1428,-1371,-1314,-1264,-1224,
+-1194,-1176,-1172,-1184,-1213,-1253,-1298,-1342,-1382,-1415,-1435,-1435,-1410,-1356,-1281,-1203,-1142,-1109,-1109,-1130,-1157,
+-1178,-1186,-1186,-1184,-1185,-1191,-1201,-1213,-1227,-1243,-1260,-1276,-1289,-1296,-1301,-1305,-1314,-1328,-1345,-1361,-1371,
+-1376,-1377,-1379,-1388,-1406,-1433,-1463,-1492,-1519,-1546,-1578,-1622,-1681,-1749,-1816,-1873,-1915,-1943,-1964,-1985,-2008,
+-2030,-2048,-2061,-2069,-2078,-2087,-2097,-2102,-2102,-2099,-2099,-2103,-2114,-2124,-2128,-2124,-2117,-2112,-2114,-2121,-2131,
+-2140,-2149,-2162,-2183,-2209,-2234,-2251,-2259,-2259,-2259,-2261,-2266,-2269,-2264,-2252,-2235,-2218,-2204,-2191,-2177,-2160,
+-2143,-2131,-2123,-2120,-2116,-2110,-2103,-2097,-2097,-2104,-2113,-2121,-2125,-2127,-2127,-2127,-2127,-2125,-2120,-2114,-2110,
+-2108,-2109,-2112,-2113,-2112,-2110,-2109,-2108,-2106,-2101,-2093,-2082,-2070,-2061,-2053,-2047,-2041,-2035,-2029,-2022,-2012,
+-2000,-1987,-1975,-1967,-1966,-1973,-1986,-2004,-2024,-2044,-2063,-2077,-2083,-2081,-2069,-2051,-2031,-2012,-1996,-1982,-1972,
+-1964,-1960,-1959,-1960,-1960,-1956,-1949,-1939,-1928,-1918,-1910,-1902,-1894,-1886,-1877,-1869,-1860,-1848,-1833,-1817,-1801,
+-1789,-1779,-1772,-1767,-1761,-1755,-1751,-1750,-1751,-1752,-1750,-1744,-1733,-1722,-1714,-1711,-1714,-1721,-1730,-1739,-1748,
+-1759,-1772,-1786,-1796,-1799,-1790,-1769,-1740,-1710,-1688,-1677,-1680,-1694,-1715,-1740,-1767,-1794,-1820,-1843,-1860,-1868,
+-1865,-1854,-1835,-1813,-1794,-1782,-1781,-1789,-1803,-1819,-1830,-1837,-1838,-1838,-1837,-1837,-1835,-1832,-1827,-1822,-1819,
+-1819,-1821,-1823,-1823,-1821,-1817,-1813,-1809,-1803,-1795,-1784,-1770,-1756,-1742,-1729,-1715,-1700,-1684,-1667,-1649,-1630,
+-1610,-1588,-1566,-1546,-1529,-1514,-1500,-1484,-1465,-1445,-1424,-1404,-1387,-1371,-1356,-1339,-1322,-1304,-1286,-1269,-1252,
+-1237,-1223,-1210,-1198,-1185,-1172,-1158,-1144,-1132,-1121,-1112,-1103,-1093,-1083,-1073,-1064,-1057,-1050,-1044,-1037,-1031,
+-1028,-1026,-1026,-1026,-1025,-1023,-1021,-1020,-1021,-1023,-1027,-1030,-1032,-1033,-1035,-1038,-1042,-1045,-1046,-1046,-1044,
+-1041,-1039,-1038,-1038,-1040,-1044,-1051,-1061,-1071,-1081,-1089,-1092,-1093,-1091,-1088,-1086,-1085,-1084,-1083,-1081,-1080,
+-1080,-1082,-1085,-1087,-1089,-1091,-1095,-1101,-1107,-1112,-1113,-1110,-1104,-1097,-1091,-1087,-1083,-1078,-1071,-1062,-1053,
+-1044,-1036,-1029,-1024,-1019,-1015,-1010,-1005,-999,-990,-977,-961,-941,-919,-896,-875,-855,-837,-820,-803,-788,
+-776,-768,-764,-763,-760,-755,-748,-742,-739,-741,-745,-747,-744,-735,-724,-712,-703,-696,-687,-675,-661,
+-647,-637,-628,-619,-606,-587,-564,-540,-518,-497,-477,-457,-436,-414,-395,-377,-360,-343,-326,-308,-291,
+-273,-251,-226,-199,-172,-149,-131,-115,-99,-79,-56,-32,-9,11,32,56,83,110,134,156,176,
+195,217,241,265,289,313,341,370,400,428,452,475,497,518,535,542,537,523,504,484,467,
+456,460,497,585,731,919,1111,1264,1349,1369,1361,1368,1415,1494,1568,1597,1564,1483,1391,1320,1281,
+1261,1237,1194,1137,1083,1047,1035,1036,1037,1028,1010,992,980,979,984,990,995,997,996,996,996,
+1001,1015,1042,1081,1127,1170,1205,1230,1251,1273,1302,1333,1358,1368,1357,1327,1284,1239,1201,1177,1168,
+1175,1194,1220,1246,1267,1280,1284,1280,1272,1262,1255,1253,1256,1262,1265,1262,1249,1227,1199,1169,1138,
+1107,1076,1044,1016,993,979,973,971,968,960,944,920,889,854,816,778,742,708,677,648,623,
+600,580,566,557,553,554,560,568,579,591,599,600,593,579,561,546,539,544,557,574,589,
+600,607,615,628,650,680,718,758,797,833,860,876,876,859,826,785,741,704,674,651,632,
+617,607,604,608,617,625,627,624,622,631,652,683,714,735,743,743,742,747,758,772,783,
+792,809,840,887,943,992,1020,1023,1009,994,993,1012,1047,1086,1119,1143,1159,1172,1183,1194,1205,
+1217,1231,1249,1269,1287,1299,1306,1314,1332,1367,1417,1475,1528,1568,1596,1617,1638,1661,1685,1702,1710,
+1711,1709,1714,1728,1748,1771,1790,1804,1814,1826,1843,1866,1891,1917,1940,1959,1974,1989,2004,2020,2038,
+2057,2077,2099,2120,2143,2164,2184,2204,2222,2242,2263,2284,2306,2327,2345,2362,2381,2402,2425,2447,2465,
+2476,2482,2489,2499,2515,2533,2551,2565,2577,2588,2599,2611,2621,2628,2631,2634,2638,2646,2656,2666,2673,
+2680,2689,2702,2716,2728,2737,2742,2748,2758,2772,2785,2791,2787,2774,2758,2745,2737,2732,2725,2715,2703,
+2694,2689,2687,2684,2678,2669,2662,2659,2660,2661,2659,2652,2645,2640,2640,2640,2651,2656,2649,2631,2606,
+2582,2564,2549,2535,2519,2504,2498,2505,2521,2537,2543,2532,2511,2487,2474,2475,2488,2507,2523,2534,2541,
+2546,2551,2558,2563,2567,2567,2563,2558,2555,2560,2576,2602,2632,2657,2671,2675,2676,2682,2697,2719,2742,
+2765,2790,2827,2883,2956,3032,3094,3127,3132,3121,3113,3121,3145,3178,3207,3225,3235,3241,3250,3260,3269,
+3275,3277,3282,3294,3314,3338,3360,3375,3383,3387,3393,3403,3415,3425,3429,3428,3428,3433,3447,3468,3491,
+3511,3526,3534,3540,3547,3556,3566,3575,3582,3588,3597,3615,3641,3672,3702,3724,3733,3735,3735,3742,3757,
+3774,3780,3763,3719,3659,3603,3579,3601,3669,3764,3857,3924,3954,3955,3942,3932,3931,3937,3941,3938,3930,
+3923,3924,3934,3949,3965,3980,3997,4022,4056,4095,4132,4163,4186,4207,4234,4270,4313,4356,4391,4417,4436,
+4456,4481,4510,4541,4570,4593,4609,4622,4632,4640,4645,4646,4646,4648,4655,4668,4686,4702,4711,4712,4708,
+4703,4703,4709,4719,4725,4722,4709,4691,4673,4660,4652,4646,4637,4624,4606,4589,4572,4558,4543,4528,4512,
+4499,4489,4482,4476,4469,4459,4449,4441,4435,4431,4425,4418,4411,4406,4407,4411,4414,4409,4392,4366,4338,
+4317,4309,4314,4323,4325,4310,4276,4227,4175,4131,4101,4086,4081,4077,4068,4052,4030,4005,3979,3955,3931,
+3908,3884,3861,3840,3823,3809,3800,3793,3787,3781,3773,3763,3751,3739,3727,3717,3706,3692,3676,3658,3644,
+3636,3638,3646,3659,3672,3679,3679,3670,3657,3644,3636,3636,3644,3649,3642,3613,3562,3501,3451,3434,3469,
+3554,3674,3799,3899,3955,3964,3937,3893,3853,3825,3813,3810,3811,3809,3802,3787,3763,3729,3690,3654,3629,
+3618,3615,3605,3573,3509,3417,3315,3225,3161,3125,3109,3098,3078,3047,3008,2969,2935,2905,2877,2846,2814,
+2781,2750,2722,2694,2663,2628,2589,2549,2509,2471,2435,2399,2362,2322,2280,2238,2195,2154,2115,2078,2044,
+2010,1976,1942,1906,1870,1833,1795,1757,1721,1685,1649,1612,1574,1535,1495,1458,1425,1396,1369,1341,1310,
+1275,1237,1199,1163,1131,1100,1069,1036,1000,963,925,887,849,811,771,732,693,656,621,585,547,
+506,465,424,386,351,316,279,242,204,166,130,95,59,22,-15,-51,-84,-114,-144,-174,-208,
+-243,-277,-311,-343,-377,-412,-449,-485,-520,-552,-585,-620,-656,-691,-722,-750,-776,-805,-839,-878,-919,
+-955,-987,-1017,-1047,-1080,-1114,-1145,-1172,-1196,-1219,-1245,-1275,-1306,-1336,-1362,-1387,-1414,-1445,-1478,-1510,-1538,
+-1561,-1584,-1608,-1637,-1668,-1697,-1723,-1746,-1768,-1792,-1821,-1851,-1880,-1907,-1929,-1949,-1966,-1981,-1993,-2003,-2011,
+-2021,-2034,-2047,-2061,-2073,-2084,-2095,-2108,-2123,-2139,-2153,-2164,-2172,-2180,-2192,-2208,-2227,-2246,-2261,-2274,-2285,
+-2296,-2307,-2317,-2326,-2332,-2338,-2344,-2351,-2359,-2363,-2365,-2364,-2366,-2373,-2384,-2395,-2401,-2397,-2383,-2364,-2345,
+-2328,-2315,-2304,-2293,-2282,-2272,-2263,-2255,-2246,-2235,-2223,-2212,-2203,-2198,-2194,-2189,-2181,-2170,-2159,-2149,-2141,
+-2134,-2127,-2117,-2107,-2096,-2086,-2077,-2070,-2063,-2056,-2048,-2040,-2031,-2022,-2013,-2005,-1996,-1987,-1975,-1960,-1945,
+-1932,-1924,-1920,-1918,-1911,-1900,-1886,-1876,-1875,-1884,-1897,-1905,-1901,-1887,-1867,-1850,-1840,-1835,-1829,-1819,-1806,
+-1793,-1787,-1787,-1789,-1787,-1776,-1759,-1745,-1743,-1755,-1781,-1810,-1836,-1852,-1858,-1857,-1852,-1844,-1836,-1826,-1816,
+-1804,-1792,-1781,-1776,-1778,-1790,-1810,-1832,-1851,-1861,-1858,-1847,-1834,-1823,-1816,-1814,-1812,-1809,-1804,-1799,-1797,
+-1798,-1801,-1802,-1801,-1796,-1789,-1780,-1774,-1772,-1775,-1780,-1784,-1782,-1774,-1760,-1744,-1730,-1719,-1708,-1694,-1672,
+-1644,-1616,-1593,-1575,-1557,-1532,-1494,-1444,-1388,-1335,-1294,-1268,-1258,-1262,-1280,-1312,-1354,-1401,-1445,-1480,-1505,
+-1521,-1531,-1534,-1522,-1487,-1428,-1352,-1280,-1229,-1211,-1224,-1253,-1280,-1292,-1289,-1277,-1268,-1267,-1275,-1289,-1302,
+-1314,-1325,-1338,-1352,-1367,-1379,-1388,-1396,-1403,-1413,-1425,-1439,-1452,-1464,-1474,-1485,-1497,-1513,-1532,-1552,-1574,
+-1598,-1628,-1670,-1727,-1797,-1873,-1943,-1998,-2035,-2058,-2075,-2094,-2116,-2137,-2154,-2164,-2170,-2176,-2185,-2195,-2202,
+-2203,-2200,-2198,-2201,-2211,-2223,-2232,-2235,-2233,-2233,-2236,-2244,-2254,-2261,-2267,-2275,-2288,-2306,-2326,-2341,-2349,
+-2351,-2351,-2352,-2353,-2351,-2343,-2328,-2310,-2292,-2276,-2262,-2248,-2232,-2218,-2206,-2199,-2195,-2191,-2184,-2174,-2165,
+-2160,-2161,-2166,-2174,-2181,-2186,-2191,-2197,-2201,-2202,-2200,-2193,-2185,-2176,-2170,-2166,-2164,-2165,-2167,-2170,-2170,
+-2166,-2158,-2148,-2137,-2128,-2122,-2117,-2111,-2104,-2095,-2085,-2075,-2064,-2053,-2040,-2028,-2017,-2008,-2003,-2003,-2007,
+-2018,-2036,-2059,-2086,-2109,-2125,-2130,-2124,-2108,-2087,-2063,-2038,-2015,-1997,-1986,-1982,-1982,-1984,-1982,-1977,-1969,
+-1962,-1956,-1952,-1948,-1943,-1936,-1928,-1918,-1908,-1897,-1883,-1867,-1850,-1835,-1823,-1814,-1806,-1797,-1788,-1780,-1776,
+-1776,-1780,-1784,-1786,-1783,-1777,-1767,-1757,-1746,-1737,-1730,-1727,-1729,-1738,-1755,-1778,-1802,-1820,-1828,-1823,-1807,
+-1784,-1761,-1742,-1728,-1720,-1718,-1720,-1729,-1745,-1768,-1797,-1827,-1855,-1876,-1889,-1891,-1884,-1872,-1858,-1845,-1836,
+-1831,-1830,-1832,-1835,-1841,-1847,-1854,-1858,-1858,-1854,-1846,-1838,-1832,-1829,-1829,-1830,-1830,-1829,-1826,-1823,-1820,
+-1815,-1807,-1797,-1785,-1771,-1757,-1742,-1727,-1709,-1691,-1671,-1652,-1633,-1614,-1595,-1576,-1560,-1544,-1529,-1514,-1497,
+-1479,-1459,-1440,-1423,-1406,-1390,-1375,-1358,-1342,-1324,-1306,-1288,-1271,-1254,-1240,-1228,-1217,-1206,-1194,-1179,-1164,
+-1149,-1136,-1124,-1112,-1101,-1091,-1082,-1074,-1068,-1061,-1055,-1048,-1043,-1039,-1038,-1038,-1038,-1037,-1034,-1031,-1030,
+-1030,-1033,-1036,-1038,-1040,-1041,-1042,-1045,-1049,-1053,-1057,-1060,-1062,-1061,-1059,-1056,-1054,-1054,-1057,-1063,-1071,
+-1080,-1088,-1094,-1098,-1101,-1102,-1103,-1102,-1098,-1094,-1088,-1083,-1080,-1079,-1078,-1077,-1075,-1075,-1077,-1083,-1092,
+-1101,-1108,-1110,-1108,-1104,-1100,-1097,-1097,-1096,-1093,-1086,-1076,-1062,-1047,-1032,-1021,-1012,-1008,-1008,-1009,-1010,
+-1007,-1000,-988,-971,-952,-931,-911,-893,-876,-860,-844,-828,-814,-802,-794,-788,-783,-777,-769,-760,-754,
+-752,-756,-761,-763,-760,-752,-740,-730,-721,-714,-706,-696,-683,-670,-658,-648,-636,-621,-602,-580,-558,
+-538,-519,-500,-480,-460,-440,-424,-408,-393,-376,-357,-336,-316,-297,-276,-252,-225,-198,-172,-150,-132,
+-115,-95,-72,-46,-21,2,24,47,71,95,118,139,158,176,195,215,237,261,289,321,355,
+389,419,445,468,489,509,524,533,532,524,511,496,478,460,452,473,542,670,847,1040,1210,
+1326,1385,1409,1428,1463,1510,1546,1545,1497,1417,1334,1271,1236,1215,1190,1148,1093,1041,1005,990,988,
+988,981,970,960,959,966,979,991,997,998,995,992,991,997,1013,1042,1083,1130,1176,1214,1241,
+1262,1281,1304,1331,1355,1370,1372,1358,1334,1305,1276,1253,1239,1233,1235,1243,1253,1260,1262,1255,1242,
+1226,1211,1202,1204,1213,1226,1235,1236,1226,1209,1189,1170,1154,1137,1117,1094,1070,1050,1036,1028,1020,
+1009,990,964,934,902,870,839,806,771,736,703,674,651,631,616,603,594,591,593,604,619,
+638,655,667,669,661,643,620,597,577,564,558,557,560,562,566,571,581,596,617,645,680,
+720,765,808,843,860,853,822,775,725,681,653,638,634,634,636,640,649,660,671,679,684,
+690,704,727,759,791,816,829,834,833,832,828,821,813,810,827,873,948,1037,1117,1168,1181,
+1163,1135,1116,1117,1137,1167,1197,1220,1236,1248,1259,1268,1275,1283,1293,1306,1322,1336,1346,1351,1358,
+1373,1402,1445,1495,1542,1581,1612,1640,1669,1700,1727,1745,1750,1747,1742,1743,1752,1768,1786,1801,1813,
+1823,1837,1855,1879,1905,1930,1951,1971,1988,2006,2024,2041,2058,2073,2087,2103,2122,2144,2168,2191,2212,
+2229,2245,2260,2276,2293,2309,2325,2342,2361,2384,2409,2432,2449,2458,2462,2465,2473,2487,2505,2523,2536,
+2545,2552,2559,2568,2578,2587,2594,2602,2611,2624,2639,2653,2665,2676,2687,2699,2712,2723,2731,2738,2745,
+2758,2775,2790,2799,2798,2788,2774,2762,2754,2748,2742,2733,2723,2715,2711,2710,2706,2698,2688,2678,2673,
+2671,2668,2661,2650,2640,2637,2642,2651,2647,2654,2652,2640,2620,2599,2580,2566,2554,2543,2534,2533,2541,
+2557,2572,2577,2568,2547,2523,2505,2499,2504,2516,2529,2539,2544,2547,2550,2554,2559,2564,2568,2572,2575,
+2580,2589,2602,2619,2635,2647,2656,2665,2678,2701,2731,2767,2802,2835,2872,2917,2973,3035,3092,3131,3149,
+3151,3151,3161,3186,3220,3254,3277,3288,3291,3293,3298,3305,3313,3319,3326,3339,3358,3379,3398,3409,3410,
+3407,3406,3413,3426,3441,3451,3454,3454,3457,3468,3487,3512,3535,3550,3558,3560,3560,3564,3572,3581,3591,
+3600,3611,3626,3648,3674,3699,3717,3725,3727,3730,3742,3765,3791,3806,3797,3755,3690,3623,3578,3577,3625,
+3708,3803,3884,3935,3953,3948,3934,3921,3914,3911,3908,3903,3900,3902,3910,3925,3941,3959,3977,4001,4030,
+4065,4102,4134,4161,4186,4213,4248,4290,4336,4377,4409,4433,4451,4470,4493,4522,4552,4582,4607,4627,4643,
+4657,4668,4675,4679,4681,4685,4692,4705,4721,4737,4749,4752,4749,4743,4739,4739,4743,4746,4743,4734,4720,
+4705,4694,4687,4683,4677,4667,4652,4634,4613,4591,4569,4549,4532,4521,4515,4511,4504,4493,4475,4455,4436,
+4422,4412,4405,4399,4395,4395,4400,4408,4412,4407,4388,4361,4332,4312,4306,4312,4319,4318,4298,4261,4212,
+4163,4124,4099,4087,4082,4076,4066,4049,4026,3999,3970,3942,3916,3891,3867,3845,3824,3804,3787,3773,3764,
+3758,3755,3752,3749,3743,3734,3724,3712,3699,3685,3673,3664,3660,3659,3660,3662,3662,3659,3654,3647,3638,
+3627,3616,3609,3607,3609,3610,3602,3578,3539,3492,3455,3445,3474,3542,3635,3735,3820,3875,3896,3888,3864,
+3834,3808,3789,3779,3779,3785,3793,3797,3790,3768,3731,3688,3652,3630,3624,3624,3613,3578,3514,3427,3335,
+3253,3191,3147,3116,3087,3056,3022,2987,2954,2923,2892,2860,2826,2791,2759,2727,2695,2661,2623,2581,2539,
+2499,2462,2429,2397,2363,2327,2286,2244,2200,2157,2116,2078,2043,2009,1977,1946,1914,1880,1843,1803,1761,
+1721,1682,1646,1610,1574,1536,1499,1464,1434,1409,1386,1360,1328,1288,1246,1204,1168,1138,1110,1081,1048,
+1010,971,933,897,861,823,782,741,700,663,629,596,559,519,477,437,399,366,333,299,261,
+221,182,145,110,76,41,5,-30,-63,-93,-122,-153,-185,-221,-257,-292,-327,-362,-397,-433,-467,
+-500,-532,-564,-597,-630,-663,-694,-722,-750,-781,-817,-857,-896,-931,-962,-992,-1023,-1056,-1089,-1120,-1147,
+-1170,-1195,-1222,-1253,-1284,-1313,-1339,-1363,-1390,-1421,-1454,-1485,-1512,-1534,-1557,-1583,-1614,-1648,-1681,-1709,-1733,
+-1756,-1781,-1810,-1841,-1870,-1896,-1917,-1935,-1951,-1965,-1978,-1988,-1996,-2005,-2016,-2030,-2045,-2060,-2074,-2088,-2101,
+-2115,-2129,-2140,-2150,-2158,-2168,-2180,-2196,-2213,-2230,-2245,-2258,-2270,-2282,-2293,-2302,-2310,-2317,-2326,-2336,-2347,
+-2356,-2361,-2362,-2362,-2365,-2373,-2385,-2394,-2397,-2390,-2375,-2357,-2339,-2326,-2316,-2306,-2295,-2284,-2274,-2266,-2259,
+-2251,-2241,-2229,-2217,-2208,-2201,-2196,-2190,-2182,-2172,-2162,-2155,-2148,-2141,-2133,-2124,-2114,-2106,-2100,-2094,-2089,
+-2082,-2073,-2064,-2055,-2045,-2036,-2028,-2021,-2015,-2009,-1999,-1986,-1971,-1956,-1946,-1942,-1940,-1935,-1923,-1905,-1889,
+-1881,-1885,-1898,-1910,-1914,-1905,-1887,-1869,-1856,-1848,-1842,-1833,-1820,-1807,-1798,-1796,-1799,-1798,-1791,-1776,-1762,
+-1756,-1764,-1787,-1817,-1846,-1867,-1877,-1878,-1872,-1863,-1853,-1843,-1832,-1820,-1808,-1798,-1794,-1797,-1810,-1830,-1852,
+-1869,-1876,-1872,-1861,-1849,-1842,-1840,-1841,-1841,-1837,-1830,-1824,-1823,-1829,-1839,-1846,-1847,-1838,-1824,-1811,-1802,
+-1800,-1802,-1803,-1800,-1791,-1779,-1769,-1764,-1764,-1762,-1754,-1736,-1710,-1681,-1654,-1630,-1604,-1570,-1524,-1470,-1416,
+-1375,-1354,-1353,-1367,-1389,-1413,-1439,-1470,-1505,-1541,-1572,-1597,-1615,-1631,-1645,-1651,-1639,-1600,-1535,-1456,-1385,
+-1341,-1332,-1351,-1380,-1401,-1405,-1394,-1377,-1367,-1367,-1377,-1388,-1399,-1406,-1414,-1424,-1438,-1452,-1465,-1475,-1481,
+-1485,-1490,-1498,-1510,-1526,-1544,-1564,-1584,-1604,-1621,-1638,-1655,-1673,-1698,-1733,-1784,-1850,-1927,-2005,-2074,-2123,
+-2153,-2169,-2182,-2197,-2218,-2239,-2254,-2262,-2263,-2264,-2270,-2279,-2288,-2293,-2294,-2292,-2294,-2301,-2312,-2324,-2333,
+-2339,-2344,-2349,-2356,-2361,-2365,-2369,-2374,-2383,-2398,-2414,-2428,-2436,-2438,-2437,-2436,-2434,-2429,-2419,-2404,-2385,
+-2366,-2350,-2335,-2322,-2308,-2295,-2285,-2278,-2273,-2267,-2259,-2248,-2236,-2226,-2221,-2222,-2227,-2235,-2244,-2253,-2261,
+-2268,-2272,-2272,-2267,-2258,-2247,-2235,-2225,-2219,-2218,-2220,-2223,-2224,-2221,-2213,-2204,-2196,-2191,-2188,-2184,-2178,
+-2169,-2156,-2142,-2128,-2115,-2103,-2092,-2080,-2069,-2058,-2048,-2039,-2032,-2030,-2036,-2051,-2074,-2101,-2127,-2148,-2160,
+-2163,-2156,-2140,-2117,-2090,-2063,-2041,-2025,-2015,-2008,-2001,-1995,-1990,-1988,-1990,-1993,-1994,-1990,-1982,-1971,-1959,
+-1948,-1938,-1926,-1913,-1898,-1884,-1871,-1861,-1851,-1841,-1830,-1818,-1809,-1804,-1804,-1808,-1812,-1815,-1814,-1808,-1799,
+-1788,-1776,-1764,-1754,-1748,-1748,-1755,-1769,-1788,-1809,-1828,-1841,-1847,-1847,-1841,-1831,-1817,-1799,-1779,-1759,-1743,
+-1735,-1739,-1755,-1781,-1813,-1847,-1877,-1900,-1913,-1917,-1913,-1903,-1889,-1875,-1861,-1851,-1845,-1845,-1848,-1854,-1858,
+-1860,-1857,-1852,-1847,-1843,-1842,-1841,-1840,-1837,-1833,-1828,-1824,-1820,-1815,-1810,-1803,-1795,-1784,-1772,-1757,-1740,
+-1719,-1697,-1675,-1654,-1636,-1619,-1605,-1591,-1578,-1563,-1547,-1528,-1508,-1488,-1469,-1451,-1435,-1420,-1405,-1389,-1374,
+-1359,-1344,-1328,-1312,-1295,-1279,-1264,-1252,-1241,-1231,-1220,-1206,-1191,-1176,-1160,-1145,-1131,-1118,-1106,-1097,-1088,
+-1081,-1074,-1067,-1060,-1054,-1050,-1049,-1048,-1047,-1045,-1041,-1038,-1037,-1039,-1042,-1045,-1047,-1048,-1048,-1048,-1050,
+-1054,-1059,-1065,-1071,-1076,-1079,-1079,-1078,-1076,-1076,-1078,-1082,-1089,-1095,-1100,-1105,-1110,-1115,-1121,-1126,-1127,
+-1125,-1119,-1113,-1106,-1102,-1099,-1095,-1090,-1085,-1081,-1082,-1086,-1094,-1101,-1105,-1106,-1105,-1103,-1104,-1107,-1110,
+-1110,-1106,-1097,-1084,-1068,-1051,-1033,-1018,-1005,-998,-996,-997,-1000,-1002,-999,-991,-978,-962,-945,-928,-912,
+-897,-883,-869,-856,-843,-831,-821,-812,-804,-795,-786,-778,-773,-773,-776,-780,-780,-775,-765,-753,-742,
+-734,-729,-723,-715,-705,-692,-679,-666,-651,-634,-616,-596,-577,-559,-542,-523,-503,-483,-465,-451,-439,
+-426,-410,-390,-367,-345,-323,-301,-278,-252,-225,-199,-175,-154,-135,-114,-91,-65,-38,-13,9,32,
+54,77,101,123,145,165,183,201,220,242,269,301,336,371,404,433,459,482,503,518,527,
+530,527,520,509,491,469,451,459,511,622,785,974,1153,1291,1376,1419,1443,1466,1488,1497,1477,
+1423,1348,1273,1216,1182,1160,1134,1097,1050,1004,970,951,944,940,935,931,932,942,960,979,993,
+1000,1000,997,994,994,1003,1021,1050,1091,1138,1184,1222,1250,1269,1285,1303,1326,1351,1373,1387,1390,
+1384,1372,1358,1343,1328,1314,1299,1284,1269,1253,1236,1218,1200,1182,1169,1163,1167,1179,1192,1200,1201,
+1195,1184,1175,1169,1165,1158,1144,1124,1101,1080,1065,1053,1039,1019,990,956,921,888,860,832,802,
+767,731,697,671,653,641,632,624,615,609,610,618,633,652,669,681,685,680,666,644,619,
+592,567,547,533,526,525,529,535,544,555,569,588,613,647,689,735,775,798,797,771,727,
+678,638,616,612,620,633,647,660,674,689,703,715,725,735,750,774,807,844,879,906,924,
+935,937,930,911,887,869,874,915,994,1098,1201,1278,1315,1313,1289,1263,1249,1253,1270,1290,1309,
+1323,1334,1344,1352,1358,1361,1365,1369,1374,1378,1382,1385,1390,1403,1427,1461,1502,1546,1591,1634,1676,
+1714,1746,1766,1773,1770,1763,1760,1764,1777,1793,1809,1821,1831,1842,1857,1877,1899,1921,1942,1961,1979,
+1998,2018,2038,2056,2072,2084,2095,2106,2121,2140,2163,2187,2209,2228,2243,2255,2267,2279,2291,2305,2320,
+2339,2363,2389,2414,2433,2443,2447,2450,2456,2467,2482,2496,2506,2513,2518,2526,2537,2550,2564,2576,2589,
+2603,2620,2638,2656,2670,2682,2691,2701,2710,2718,2724,2729,2736,2750,2768,2788,2803,2809,2805,2795,2784,
+2775,2767,2758,2748,2738,2731,2728,2725,2721,2712,2701,2690,2683,2680,2676,2668,2656,2644,2637,2639,2647,
+2638,2638,2636,2628,2615,2602,2592,2587,2586,2587,2589,2593,2599,2607,2611,2608,2595,2576,2554,2537,2528,
+2528,2533,2539,2545,2548,2552,2556,2561,2568,2575,2582,2589,2596,2605,2615,2626,2637,2647,2657,2671,2690,
+2719,2756,2797,2838,2875,2910,2948,2991,3038,3083,3118,3138,3145,3149,3161,3186,3223,3261,3290,3307,3313,
+3315,3320,3328,3338,3347,3356,3370,3389,3413,3437,3454,3460,3458,3455,3456,3466,3480,3494,3502,3506,3509,
+3516,3532,3553,3574,3591,3600,3601,3599,3597,3598,3601,3607,3615,3626,3642,3662,3683,3701,3712,3714,3713,
+3716,3732,3761,3797,3824,3824,3788,3722,3645,3583,3562,3590,3661,3753,3841,3905,3938,3943,3932,3915,3900,
+3888,3880,3876,3875,3880,3890,3903,3918,3933,3951,3974,4003,4038,4075,4109,4141,4169,4198,4232,4272,4315,
+4357,4394,4423,4447,4467,4489,4514,4542,4570,4597,4621,4641,4661,4681,4706,4733,4760,4781,4795,4798,4795,
+4788,4780,4772,4764,4753,4740,4728,4719,4715,4715,4718,4719,4718,4716,4715,4715,4717,4716,4710,4695,4672,
+4643,4613,4584,4559,4542,4532,4526,4519,4508,4492,4470,4449,4431,4418,4408,4399,4388,4378,4372,4372,4378,
+4384,4383,4372,4352,4329,4311,4302,4300,4297,4286,4262,4228,4191,4158,4134,4118,4106,4093,4078,4059,4038,
+4014,3990,3963,3935,3906,3879,3855,3833,3813,3793,3773,3754,3738,3726,3719,3716,3715,3715,3711,3704,3691,
+3676,3660,3648,3642,3641,3642,3640,3634,3624,3612,3602,3596,3593,3590,3586,3581,3575,3568,3559,3546,3527,
+3502,3477,3459,3456,3469,3499,3541,3589,3639,3687,3731,3768,3792,3801,3796,3781,3763,3752,3754,3768,3787,
+3800,3796,3773,3736,3695,3663,3646,3642,3640,3626,3590,3529,3449,3361,3276,3201,3138,3086,3040,3000,2964,
+2932,2905,2880,2856,2831,2806,2779,2750,2717,2678,2634,2587,2539,2494,2454,2419,2387,2356,2322,2286,2246,
+2205,2164,2124,2085,2047,2011,1976,1942,1910,1877,1841,1803,1761,1719,1679,1641,1606,1573,1540,1508,1479,
+1453,1429,1406,1378,1343,1301,1255,1212,1175,1144,1116,1087,1053,1015,976,939,904,871,835,795,753,
+711,673,639,605,569,530,488,449,413,381,350,316,278,237,197,160,127,95,63,28,-7,
+-41,-74,-105,-136,-170,-206,-243,-279,-313,-346,-379,-412,-445,-478,-511,-544,-577,-609,-640,-669,-696,
+-725,-757,-793,-832,-871,-906,-938,-969,-1000,-1033,-1066,-1096,-1123,-1147,-1172,-1200,-1231,-1262,-1292,-1318,-1343,
+-1370,-1400,-1431,-1461,-1487,-1511,-1535,-1565,-1598,-1634,-1668,-1697,-1721,-1744,-1769,-1797,-1827,-1855,-1879,-1899,-1915,
+-1931,-1945,-1958,-1971,-1982,-1993,-2006,-2021,-2037,-2053,-2068,-2082,-2095,-2109,-2121,-2132,-2141,-2150,-2161,-2173,-2188,
+-2204,-2219,-2232,-2245,-2257,-2269,-2279,-2288,-2297,-2306,-2317,-2331,-2346,-2357,-2363,-2365,-2367,-2372,-2381,-2392,-2399,
+-2398,-2387,-2371,-2353,-2338,-2327,-2318,-2308,-2297,-2285,-2275,-2268,-2262,-2256,-2249,-2239,-2229,-2220,-2213,-2205,-2197,
+-2188,-2180,-2174,-2170,-2165,-2159,-2151,-2141,-2132,-2125,-2120,-2114,-2107,-2099,-2089,-2081,-2073,-2066,-2059,-2051,-2043,
+-2036,-2030,-2023,-2012,-1998,-1983,-1972,-1968,-1967,-1964,-1952,-1932,-1911,-1896,-1894,-1904,-1919,-1928,-1925,-1910,-1892,
+-1876,-1865,-1857,-1848,-1835,-1821,-1811,-1808,-1811,-1813,-1809,-1798,-1783,-1775,-1780,-1800,-1829,-1860,-1885,-1899,-1904,
+-1902,-1897,-1890,-1881,-1869,-1855,-1842,-1831,-1827,-1830,-1842,-1859,-1877,-1891,-1896,-1893,-1884,-1875,-1870,-1869,-1868,
+-1864,-1857,-1847,-1841,-1843,-1855,-1871,-1885,-1890,-1885,-1873,-1861,-1853,-1849,-1845,-1837,-1823,-1806,-1791,-1785,-1788,
+-1795,-1798,-1792,-1776,-1755,-1733,-1710,-1682,-1642,-1586,-1520,-1459,-1420,-1414,-1440,-1486,-1533,-1568,-1587,-1594,-1600,
+-1608,-1622,-1639,-1659,-1682,-1711,-1739,-1757,-1749,-1709,-1639,-1558,-1489,-1450,-1445,-1464,-1488,-1502,-1500,-1487,-1473,
+-1465,-1464,-1468,-1472,-1475,-1480,-1490,-1506,-1525,-1541,-1552,-1556,-1556,-1556,-1560,-1568,-1581,-1599,-1621,-1646,-1672,
+-1699,-1723,-1746,-1769,-1794,-1826,-1868,-1923,-1991,-2065,-2138,-2199,-2241,-2264,-2274,-2281,-2292,-2310,-2330,-2344,-2349,
+-2348,-2344,-2346,-2353,-2365,-2375,-2381,-2382,-2384,-2389,-2398,-2411,-2424,-2434,-2442,-2449,-2454,-2458,-2461,-2464,-2468,
+-2475,-2485,-2498,-2509,-2515,-2516,-2513,-2510,-2506,-2501,-2493,-2480,-2464,-2446,-2429,-2414,-2400,-2387,-2375,-2364,-2355,
+-2347,-2340,-2332,-2321,-2308,-2297,-2289,-2286,-2289,-2296,-2305,-2314,-2322,-2328,-2332,-2333,-2330,-2324,-2314,-2300,-2287,
+-2276,-2270,-2269,-2271,-2272,-2270,-2265,-2258,-2253,-2249,-2247,-2243,-2236,-2224,-2210,-2195,-2181,-2168,-2155,-2142,-2130,
+-2119,-2109,-2099,-2088,-2077,-2067,-2060,-2059,-2067,-2084,-2107,-2134,-2160,-2181,-2195,-2198,-2190,-2172,-2147,-2121,-2096,
+-2073,-2053,-2034,-2020,-2011,-2008,-2011,-2017,-2020,-2019,-2012,-2002,-1991,-1982,-1974,-1965,-1954,-1941,-1928,-1915,-1906,
+-1897,-1888,-1878,-1865,-1853,-1844,-1839,-1837,-1839,-1840,-1841,-1839,-1836,-1831,-1826,-1818,-1810,-1801,-1792,-1786,-1784,
+-1789,-1799,-1814,-1832,-1848,-1860,-1868,-1871,-1867,-1856,-1839,-1819,-1796,-1777,-1765,-1762,-1770,-1787,-1810,-1836,-1862,
+-1885,-1904,-1917,-1924,-1924,-1919,-1908,-1896,-1885,-1875,-1869,-1864,-1860,-1856,-1852,-1849,-1848,-1849,-1851,-1852,-1850,
+-1846,-1841,-1834,-1827,-1821,-1815,-1809,-1802,-1795,-1787,-1777,-1764,-1747,-1728,-1706,-1683,-1662,-1643,-1628,-1615,-1604,
+-1593,-1579,-1563,-1543,-1521,-1499,-1479,-1460,-1444,-1428,-1413,-1398,-1384,-1371,-1359,-1347,-1334,-1320,-1305,-1290,-1276,
+-1264,-1252,-1240,-1227,-1214,-1200,-1185,-1169,-1154,-1139,-1125,-1113,-1103,-1094,-1085,-1077,-1069,-1063,-1059,-1057,-1055,
+-1053,-1050,-1047,-1045,-1046,-1049,-1053,-1056,-1058,-1058,-1058,-1059,-1060,-1063,-1068,-1073,-1080,-1086,-1091,-1095,-1096,
+-1096,-1096,-1099,-1103,-1109,-1114,-1118,-1122,-1126,-1133,-1141,-1148,-1152,-1152,-1148,-1142,-1138,-1134,-1132,-1128,-1123,
+-1117,-1112,-1110,-1111,-1112,-1112,-1110,-1107,-1105,-1107,-1112,-1119,-1122,-1120,-1113,-1102,-1089,-1076,-1062,-1048,-1032,
+-1017,-1004,-995,-991,-991,-992,-991,-987,-980,-969,-957,-944,-930,-917,-905,-893,-880,-867,-854,-842,-831,
+-821,-812,-804,-797,-793,-792,-793,-794,-790,-782,-771,-758,-748,-742,-738,-735,-730,-721,-709,-695,-680,
+-665,-649,-632,-615,-598,-582,-565,-546,-526,-507,-490,-478,-468,-457,-442,-423,-399,-374,-350,-326,-302,
+-277,-251,-225,-201,-180,-159,-138,-114,-87,-60,-34,-9,13,36,59,84,109,133,155,175,193,
+212,233,258,288,321,355,389,421,451,477,499,515,526,531,532,530,521,503,477,452,449,
+491,590,744,928,1106,1247,1335,1377,1393,1401,1409,1411,1394,1354,1296,1233,1179,1138,1107,1079,1046,
+1010,976,951,936,927,923,921,924,934,952,974,993,1005,1007,1005,1002,1001,1006,1017,1036,1063,
+1099,1141,1184,1220,1247,1265,1281,1299,1322,1348,1372,1389,1397,1397,1394,1392,1390,1387,1376,1355,1324,
+1287,1250,1218,1192,1175,1163,1156,1154,1157,1164,1172,1178,1180,1180,1180,1181,1182,1181,1172,1153,1126,
+1097,1072,1052,1037,1019,995,962,924,887,856,829,803,774,741,706,676,654,643,638,635,629,
+622,615,612,615,625,637,647,653,654,649,638,622,599,573,546,522,505,496,495,501,511,
+522,532,542,552,566,585,610,639,667,684,684,665,632,596,569,556,560,576,597,619,639,
+659,678,696,710,722,736,756,787,830,878,925,965,993,1011,1020,1017,1003,980,959,953,979,
+1044,1140,1248,1343,1406,1430,1424,1404,1385,1378,1382,1395,1410,1425,1437,1448,1456,1460,1459,1454,1445,
+1435,1426,1419,1416,1418,1425,1439,1461,1494,1538,1592,1652,1708,1753,1778,1783,1773,1761,1755,1761,1778,
+1801,1822,1836,1846,1855,1866,1882,1902,1921,1940,1956,1971,1987,2003,2020,2037,2052,2066,2079,2091,2104,
+2117,2134,2153,2175,2197,2216,2233,2248,2260,2271,2281,2292,2304,2321,2342,2367,2392,2413,2427,2436,2441,
+2448,2458,2470,2482,2491,2497,2504,2514,2527,2544,2560,2575,2590,2607,2626,2646,2666,2681,2693,2702,2709,
+2716,2722,2725,2728,2732,2742,2759,2779,2798,2810,2813,2808,2799,2790,2780,2770,2759,2750,2742,2738,2735,
+2730,2721,2709,2697,2690,2686,2684,2680,2671,2658,2646,2639,2638,2639,2635,2633,2630,2624,2617,2614,2614,
+2619,2626,2632,2635,2634,2630,2623,2613,2600,2586,2574,2564,2559,2558,2559,2561,2563,2566,2569,2574,2579,
+2584,2588,2592,2596,2603,2613,2628,2643,2659,2673,2688,2708,2735,2773,2816,2861,2900,2932,2959,2986,3016,
+3048,3076,3096,3106,3112,3122,3143,3175,3211,3244,3267,3279,3287,3297,3312,3331,3348,3362,3375,3391,3413,
+3439,3464,3484,3495,3501,3506,3514,3527,3540,3550,3556,3561,3570,3583,3601,3619,3633,3641,3644,3644,3645,
+3646,3648,3648,3650,3655,3666,3682,3700,3714,3717,3711,3701,3698,3711,3743,3786,3824,3836,3811,3749,3668,
+3594,3554,3562,3617,3700,3788,3859,3902,3916,3910,3894,3875,3858,3846,3842,3845,3855,3871,3887,3901,3913,
+3927,3946,3973,4008,4046,4084,4118,4149,4180,4214,4252,4291,4330,4365,4397,4426,4454,4481,4509,4537,4565,
+4592,4615,4635,4653,4673,4704,4749,4807,4870,4921,4949,4946,4916,4871,4826,4790,4766,4749,4735,4720,4706,
+4696,4693,4694,4697,4700,4702,4706,4714,4724,4731,4729,4714,4687,4651,4614,4582,4558,4541,4529,4515,4499,
+4480,4461,4448,4443,4445,4449,4447,4432,4406,4374,4345,4328,4325,4332,4341,4344,4338,4326,4313,4302,4292,
+4280,4262,4238,4212,4189,4171,4157,4143,4125,4101,4072,4044,4020,4000,3982,3961,3935,3905,3874,3846,3822,
+3802,3784,3766,3746,3726,3707,3692,3682,3677,3676,3674,3668,3658,3643,3628,3616,3609,3606,3604,3598,3587,
+3572,3557,3547,3545,3547,3551,3553,3550,3543,3531,3517,3499,3481,3464,3453,3448,3448,3449,3448,3447,3452,
+3473,3519,3588,3671,3749,3804,3829,3825,3805,3784,3775,3783,3801,3820,3826,3815,3787,3748,3710,3680,3662,
+3652,3640,3617,3575,3512,3433,3344,3256,3174,3102,3041,2990,2946,2910,2880,2857,2838,2821,2804,2783,2758,
+2726,2688,2646,2599,2552,2505,2460,2418,2380,2344,2308,2272,2235,2198,2162,2127,2092,2056,2017,1977,1937,
+1899,1863,1829,1794,1757,1718,1679,1641,1607,1576,1548,1521,1494,1468,1441,1413,1381,1345,1304,1261,1220,
+1182,1150,1119,1087,1052,1013,974,937,903,870,835,798,758,718,681,647,612,576,538,497,459,
+425,393,362,327,289,249,210,174,142,112,81,47,11,-23,-57,-89,-122,-157,-193,-230,-264,
+-296,-326,-356,-387,-420,-454,-488,-524,-558,-590,-621,-648,-675,-703,-734,-769,-807,-845,-881,-914,-946,
+-977,-1010,-1043,-1074,-1101,-1127,-1153,-1181,-1212,-1245,-1276,-1304,-1332,-1359,-1387,-1415,-1443,-1470,-1496,-1524,-1555,
+-1589,-1624,-1656,-1684,-1708,-1731,-1755,-1782,-1811,-1838,-1862,-1881,-1897,-1911,-1925,-1938,-1952,-1967,-1983,-2001,-2018,
+-2035,-2051,-2066,-2080,-2094,-2107,-2118,-2127,-2135,-2144,-2155,-2168,-2184,-2199,-2213,-2225,-2237,-2249,-2261,-2272,-2282,
+-2292,-2303,-2317,-2333,-2349,-2361,-2368,-2371,-2375,-2381,-2391,-2401,-2406,-2402,-2390,-2372,-2355,-2342,-2333,-2325,-2315,
+-2304,-2292,-2281,-2274,-2269,-2264,-2258,-2251,-2244,-2238,-2231,-2223,-2213,-2203,-2195,-2191,-2189,-2187,-2182,-2173,-2164,
+-2156,-2150,-2145,-2138,-2128,-2116,-2105,-2098,-2094,-2091,-2086,-2077,-2068,-2059,-2052,-2046,-2037,-2025,-2011,-2001,-1997,
+-1998,-1998,-1989,-1969,-1943,-1921,-1912,-1917,-1930,-1941,-1940,-1928,-1911,-1895,-1884,-1876,-1867,-1854,-1839,-1826,-1820,
+-1821,-1824,-1822,-1813,-1800,-1793,-1798,-1817,-1848,-1880,-1908,-1927,-1936,-1938,-1935,-1929,-1919,-1905,-1891,-1878,-1869,
+-1866,-1870,-1880,-1892,-1905,-1915,-1921,-1921,-1916,-1909,-1900,-1892,-1883,-1874,-1864,-1855,-1853,-1860,-1874,-1894,-1911,
+-1922,-1924,-1920,-1914,-1909,-1902,-1893,-1877,-1857,-1836,-1821,-1815,-1817,-1821,-1822,-1818,-1811,-1804,-1796,-1780,-1746,
+-1687,-1610,-1532,-1477,-1466,-1501,-1569,-1643,-1698,-1723,-1719,-1701,-1684,-1678,-1682,-1696,-1717,-1746,-1782,-1817,-1838,
+-1829,-1785,-1714,-1636,-1574,-1544,-1546,-1565,-1584,-1591,-1586,-1574,-1563,-1555,-1548,-1538,-1527,-1520,-1524,-1542,-1571,
+-1600,-1621,-1628,-1625,-1619,-1616,-1621,-1634,-1651,-1671,-1694,-1719,-1746,-1776,-1807,-1842,-1880,-1922,-1969,-2022,-2080,
+-2141,-2203,-2261,-2309,-2343,-2361,-2368,-2372,-2379,-2392,-2408,-2421,-2427,-2426,-2422,-2422,-2429,-2441,-2455,-2465,-2471,
+-2476,-2481,-2491,-2503,-2515,-2525,-2533,-2539,-2544,-2549,-2553,-2555,-2557,-2560,-2565,-2572,-2578,-2583,-2583,-2581,-2578,
+-2575,-2572,-2567,-2558,-2546,-2530,-2513,-2497,-2482,-2468,-2456,-2443,-2431,-2421,-2412,-2403,-2394,-2384,-2374,-2366,-2362,
+-2362,-2367,-2373,-2379,-2383,-2385,-2385,-2384,-2384,-2381,-2374,-2363,-2349,-2335,-2325,-2319,-2318,-2318,-2317,-2314,-2308,
+-2303,-2298,-2294,-2288,-2280,-2269,-2257,-2245,-2233,-2221,-2208,-2194,-2180,-2167,-2156,-2147,-2138,-2128,-2115,-2102,-2091,
+-2086,-2089,-2100,-2120,-2145,-2173,-2198,-2216,-2224,-2222,-2212,-2196,-2176,-2153,-2128,-2101,-2074,-2051,-2035,-2026,-2025,
+-2026,-2027,-2027,-2024,-2021,-2017,-2011,-2003,-1992,-1979,-1965,-1954,-1946,-1940,-1934,-1926,-1915,-1903,-1892,-1883,-1878,
+-1875,-1873,-1871,-1869,-1867,-1866,-1865,-1864,-1860,-1854,-1844,-1832,-1822,-1815,-1813,-1816,-1822,-1828,-1834,-1838,-1842,
+-1845,-1848,-1850,-1848,-1843,-1834,-1824,-1814,-1806,-1802,-1803,-1809,-1820,-1838,-1860,-1885,-1909,-1930,-1945,-1951,-1950,
+-1944,-1933,-1920,-1906,-1892,-1878,-1867,-1860,-1856,-1855,-1856,-1857,-1857,-1855,-1852,-1847,-1841,-1834,-1825,-1815,-1805,
+-1795,-1786,-1776,-1765,-1752,-1736,-1718,-1697,-1676,-1656,-1638,-1622,-1610,-1598,-1587,-1573,-1556,-1536,-1515,-1494,-1474,
+-1456,-1439,-1423,-1408,-1393,-1380,-1368,-1357,-1345,-1333,-1319,-1305,-1290,-1276,-1262,-1249,-1237,-1225,-1213,-1201,-1187,
+-1172,-1157,-1142,-1129,-1118,-1108,-1099,-1090,-1082,-1076,-1071,-1067,-1063,-1059,-1056,-1053,-1053,-1056,-1059,-1063,-1065,
+-1066,-1067,-1068,-1070,-1072,-1075,-1078,-1082,-1086,-1092,-1099,-1105,-1109,-1111,-1113,-1117,-1122,-1128,-1134,-1139,-1143,
+-1147,-1153,-1160,-1166,-1169,-1170,-1167,-1164,-1162,-1161,-1160,-1159,-1157,-1154,-1151,-1149,-1146,-1141,-1133,-1125,-1117,
+-1114,-1117,-1124,-1131,-1133,-1129,-1119,-1108,-1098,-1090,-1083,-1073,-1060,-1044,-1028,-1014,-1003,-996,-992,-988,-983,
+-977,-970,-961,-951,-941,-931,-920,-909,-897,-883,-868,-853,-841,-830,-821,-815,-809,-805,-802,-800,-797,
+-792,-783,-772,-761,-752,-748,-746,-745,-740,-732,-721,-707,-693,-679,-665,-650,-634,-617,-601,-583,-566,
+-548,-531,-516,-503,-492,-481,-466,-446,-423,-398,-372,-348,-323,-298,-273,-249,-227,-206,-186,-165,-140,
+-113,-85,-58,-32,-9,14,37,61,86,111,134,156,178,200,224,251,280,312,344,377,410,
+442,470,493,509,521,528,534,536,530,511,481,450,439,472,564,711,889,1063,1198,1278,1309,
+1311,1306,1308,1315,1316,1302,1268,1220,1167,1116,1072,1033,1001,974,954,941,934,931,930,933,944,
+962,986,1009,1025,1031,1029,1024,1022,1025,1033,1046,1062,1085,1114,1148,1183,1215,1239,1257,1274,1293,
+1317,1342,1361,1370,1369,1364,1363,1371,1386,1401,1404,1388,1352,1304,1254,1213,1186,1173,1168,1167,1166,
+1164,1165,1168,1174,1183,1192,1201,1207,1207,1197,1175,1142,1104,1066,1036,1012,993,972,944,908,868,
+829,795,767,742,716,689,664,643,630,624,619,613,602,588,574,564,559,558,557,552,542,
+529,513,497,480,462,443,425,412,406,409,419,435,454,471,485,494,499,501,503,508,517,
+529,538,540,533,518,501,489,487,496,513,535,557,580,603,626,648,668,688,712,748,798,
+861,927,986,1029,1055,1067,1071,1072,1070,1063,1052,1047,1059,1100,1171,1264,1361,1440,1487,1502,1492,
+1473,1458,1455,1463,1479,1498,1516,1532,1545,1553,1554,1546,1529,1508,1487,1470,1459,1454,1453,1456,1466,
+1490,1532,1593,1662,1726,1769,1783,1774,1754,1740,1744,1767,1800,1833,1855,1866,1871,1877,1888,1904,1922,
+1939,1954,1968,1982,1998,2012,2023,2033,2041,2052,2067,2084,2102,2118,2133,2148,2165,2183,2203,2223,2241,
+2256,2269,2280,2291,2302,2316,2333,2355,2378,2399,2416,2429,2439,2449,2462,2475,2489,2499,2507,2515,2524,
+2537,2551,2567,2582,2597,2613,2632,2652,2671,2686,2698,2708,2717,2725,2731,2734,2734,2734,2739,2749,2766,
+2783,2796,2802,2801,2795,2788,2782,2775,2767,2759,2752,2747,2743,2738,2729,2717,2705,2696,2690,2688,2686,
+2680,2669,2656,2645,2639,2657,2657,2660,2661,2659,2655,2650,2648,2649,2652,2652,2649,2640,2629,2617,2608,
+2602,2598,2596,2593,2591,2589,2587,2587,2587,2588,2589,2591,2592,2593,2593,2593,2596,2604,2618,2637,2659,
+2678,2694,2708,2726,2753,2791,2838,2884,2923,2948,2964,2974,2987,3003,3023,3042,3059,3076,3098,3126,3158,
+3189,3213,3229,3240,3253,3272,3298,3326,3350,3367,3380,3394,3412,3435,3458,3479,3496,3511,3525,3540,3554,
+3564,3572,3579,3589,3604,3624,3643,3657,3663,3665,3667,3673,3683,3694,3701,3704,3706,3710,3721,3735,3746,
+3746,3733,3713,3697,3698,3722,3764,3807,3830,3816,3764,3687,3609,3557,3549,3587,3656,3736,3804,3849,3868,
+3867,3854,3836,3819,3804,3798,3802,3817,3841,3866,3887,3902,3912,3926,3948,3980,4018,4058,4093,4125,4155,
+4188,4224,4261,4297,4330,4359,4388,4419,4452,4486,4519,4550,4578,4605,4627,4646,4661,4682,4717,4775,4855,
+4943,5017,5053,5043,4992,4920,4852,4804,4782,4779,4782,4784,4781,4775,4766,4753,4736,4715,4694,4682,4681,
+4691,4703,4707,4696,4669,4634,4601,4577,4563,4552,4536,4510,4476,4444,4426,4429,4453,4487,4516,4523,4500,
+4450,4386,4327,4288,4274,4283,4300,4316,4323,4320,4311,4300,4288,4273,4255,4235,4214,4197,4184,4171,4154,
+4128,4096,4061,4030,4009,3994,3981,3964,3937,3903,3865,3831,3803,3783,3769,3757,3744,3727,3707,3686,3667,
+3652,3642,3634,3627,3617,3605,3592,3580,3573,3569,3565,3558,3546,3532,3519,3511,3510,3513,3517,3519,3517,
+3513,3504,3492,3476,3458,3443,3434,3432,3434,3432,3421,3402,3389,3397,3440,3519,3623,3729,3813,3861,3876,
+3868,3854,3848,3853,3865,3876,3877,3863,3837,3800,3760,3720,3684,3655,3629,3602,3568,3522,3462,3392,3317,
+3243,3173,3109,3051,2996,2946,2901,2863,2832,2805,2779,2751,2719,2685,2650,2616,2583,2548,2510,2468,2425,
+2381,2338,2297,2257,2218,2181,2147,2116,2086,2055,2020,1980,1936,1891,1851,1815,1783,1751,1717,1680,1643,
+1608,1578,1552,1527,1500,1470,1437,1402,1367,1331,1295,1259,1222,1186,1151,1117,1082,1046,1009,970,933,
+896,861,827,791,755,719,685,651,617,581,544,506,470,436,404,373,339,303,264,227,193,
+161,130,98,64,28,-6,-40,-72,-105,-139,-175,-209,-242,-272,-301,-330,-362,-395,-430,-466,-502,
+-536,-569,-600,-629,-657,-685,-716,-750,-787,-823,-858,-891,-923,-955,-987,-1020,-1052,-1081,-1108,-1134,-1163,
+-1194,-1227,-1260,-1291,-1320,-1347,-1373,-1401,-1428,-1457,-1486,-1517,-1549,-1581,-1613,-1643,-1669,-1695,-1719,-1744,-1771,
+-1799,-1825,-1849,-1870,-1887,-1900,-1912,-1924,-1938,-1955,-1975,-1995,-2015,-2033,-2049,-2065,-2080,-2095,-2108,-2118,-2124,
+-2129,-2136,-2147,-2162,-2179,-2195,-2209,-2221,-2232,-2244,-2257,-2269,-2281,-2291,-2303,-2318,-2334,-2350,-2362,-2369,-2373,
+-2378,-2386,-2396,-2406,-2411,-2407,-2394,-2378,-2362,-2350,-2342,-2334,-2325,-2315,-2305,-2296,-2289,-2282,-2275,-2268,-2262,
+-2258,-2254,-2250,-2242,-2232,-2221,-2213,-2208,-2206,-2203,-2197,-2189,-2181,-2175,-2172,-2169,-2163,-2151,-2138,-2125,-2118,
+-2116,-2114,-2110,-2101,-2090,-2080,-2073,-2068,-2061,-2051,-2038,-2028,-2025,-2028,-2030,-2023,-2004,-1975,-1948,-1933,-1932,
+-1942,-1951,-1952,-1942,-1925,-1910,-1900,-1894,-1887,-1874,-1857,-1841,-1832,-1830,-1831,-1830,-1822,-1812,-1806,-1812,-1833,
+-1865,-1900,-1930,-1952,-1962,-1964,-1959,-1949,-1935,-1920,-1906,-1897,-1895,-1897,-1902,-1908,-1915,-1922,-1931,-1940,-1946,
+-1945,-1937,-1922,-1905,-1889,-1878,-1872,-1871,-1875,-1884,-1897,-1912,-1926,-1937,-1945,-1948,-1948,-1945,-1940,-1931,-1917,
+-1901,-1886,-1874,-1865,-1857,-1850,-1842,-1837,-1840,-1849,-1855,-1843,-1799,-1724,-1633,-1554,-1517,-1537,-1607,-1697,-1775,
+-1814,-1813,-1785,-1754,-1738,-1740,-1755,-1777,-1801,-1828,-1860,-1888,-1901,-1885,-1836,-1765,-1694,-1645,-1629,-1640,-1663,
+-1680,-1684,-1676,-1664,-1654,-1642,-1625,-1599,-1571,-1553,-1554,-1578,-1617,-1656,-1681,-1689,-1683,-1675,-1674,-1684,-1703,
+-1725,-1748,-1770,-1792,-1815,-1844,-1880,-1924,-1979,-2041,-2107,-2172,-2232,-2284,-2329,-2369,-2403,-2429,-2446,-2455,-2460,
+-2464,-2473,-2485,-2497,-2505,-2508,-2507,-2508,-2513,-2523,-2535,-2547,-2557,-2565,-2575,-2586,-2598,-2609,-2617,-2622,-2625,
+-2629,-2633,-2638,-2641,-2641,-2640,-2640,-2641,-2645,-2648,-2649,-2647,-2645,-2642,-2640,-2637,-2633,-2624,-2611,-2596,-2580,
+-2565,-2553,-2541,-2528,-2515,-2502,-2490,-2480,-2471,-2463,-2455,-2448,-2443,-2441,-2442,-2445,-2447,-2446,-2443,-2439,-2437,
+-2435,-2434,-2431,-2423,-2411,-2396,-2384,-2376,-2372,-2370,-2368,-2364,-2357,-2350,-2343,-2337,-2330,-2321,-2312,-2302,-2293,
+-2283,-2273,-2262,-2247,-2232,-2217,-2203,-2192,-2183,-2174,-2164,-2153,-2141,-2132,-2127,-2127,-2133,-2145,-2162,-2181,-2199,
+-2214,-2224,-2231,-2235,-2235,-2229,-2214,-2190,-2158,-2122,-2088,-2062,-2045,-2038,-2037,-2040,-2045,-2048,-2048,-2044,-2036,
+-2025,-2013,-2002,-1994,-1988,-1983,-1977,-1969,-1959,-1948,-1938,-1929,-1923,-1917,-1911,-1905,-1900,-1895,-1892,-1890,-1889,
+-1887,-1884,-1878,-1871,-1862,-1854,-1846,-1838,-1830,-1821,-1811,-1802,-1797,-1798,-1806,-1819,-1835,-1849,-1859,-1862,-1859,
+-1850,-1838,-1826,-1817,-1814,-1819,-1835,-1858,-1888,-1918,-1946,-1967,-1982,-1988,-1988,-1981,-1970,-1956,-1939,-1922,-1906,
+-1892,-1881,-1872,-1866,-1862,-1860,-1859,-1857,-1855,-1849,-1840,-1829,-1816,-1803,-1790,-1778,-1767,-1755,-1742,-1727,-1710,
+-1691,-1670,-1650,-1631,-1615,-1603,-1591,-1580,-1566,-1549,-1530,-1509,-1489,-1471,-1454,-1437,-1421,-1405,-1389,-1374,-1359,
+-1345,-1332,-1319,-1306,-1292,-1277,-1262,-1248,-1236,-1226,-1216,-1206,-1194,-1181,-1167,-1154,-1143,-1134,-1125,-1117,-1108,
+-1100,-1093,-1086,-1080,-1073,-1067,-1062,-1060,-1061,-1064,-1069,-1071,-1072,-1071,-1071,-1073,-1076,-1081,-1085,-1087,-1089,
+-1092,-1097,-1104,-1111,-1117,-1122,-1126,-1130,-1136,-1143,-1151,-1157,-1161,-1165,-1168,-1172,-1176,-1179,-1180,-1179,-1178,
+-1177,-1177,-1178,-1180,-1181,-1181,-1182,-1181,-1177,-1170,-1159,-1147,-1137,-1133,-1134,-1139,-1144,-1144,-1138,-1130,-1120,
+-1113,-1108,-1103,-1096,-1086,-1073,-1058,-1044,-1031,-1019,-1008,-997,-987,-978,-970,-962,-954,-946,-938,-929,-919,
+-906,-891,-875,-859,-844,-833,-824,-817,-811,-807,-804,-803,-801,-796,-789,-778,-768,-760,-757,-755,-754,
+-751,-743,-732,-719,-706,-694,-681,-667,-650,-632,-614,-597,-582,-567,-552,-538,-524,-509,-493,-476,-456,
+-434,-411,-388,-365,-342,-319,-296,-274,-254,-236,-217,-196,-171,-143,-114,-86,-60,-36,-14,9,32,
+57,82,106,130,154,181,209,240,271,303,334,365,397,428,457,480,497,509,519,528,534,
+532,514,481,444,424,446,525,661,831,1001,1136,1218,1249,1247,1236,1233,1240,1251,1254,1240,1208,
+1161,1108,1055,1008,971,946,933,928,928,931,935,944,960,984,1013,1039,1058,1066,1066,1065,1066,
+1071,1080,1091,1103,1119,1140,1167,1196,1222,1243,1259,1275,1293,1313,1331,1341,1338,1327,1316,1315,1330,
+1358,1387,1403,1394,1359,1308,1254,1212,1188,1180,1181,1183,1181,1177,1174,1177,1187,1202,1219,1231,1232,
+1220,1194,1155,1108,1062,1020,987,960,936,909,874,832,787,743,705,673,647,625,609,597,592,
+590,588,580,563,537,504,472,444,422,404,385,362,334,303,271,244,223,209,202,203,210,
+226,248,275,306,336,362,382,393,395,392,388,386,390,400,412,422,428,427,424,424,429,
+440,456,475,494,514,535,557,581,606,637,678,735,811,898,985,1056,1101,1119,1118,1112,1111,
+1118,1127,1132,1133,1136,1154,1196,1264,1348,1428,1488,1516,1515,1497,1477,1468,1472,1489,1512,1537,1560,
+1582,1599,1608,1607,1594,1571,1545,1523,1507,1498,1492,1488,1490,1506,1542,1598,1664,1721,1756,1763,1750,
+1735,1735,1759,1801,1845,1878,1893,1894,1891,1893,1903,1919,1934,1946,1957,1970,1987,2007,2024,2036,2041,
+2045,2052,2066,2085,2106,2124,2138,2150,2164,2180,2199,2219,2238,2255,2269,2283,2296,2309,2324,2341,2360,
+2379,2397,2414,2427,2440,2453,2469,2486,2503,2517,2526,2533,2540,2549,2561,2574,2588,2603,2618,2634,2651,
+2667,2681,2692,2702,2712,2721,2728,2733,2733,2733,2735,2742,2754,2768,2778,2783,2783,2780,2778,2778,2778,
+2776,2771,2764,2758,2753,2748,2741,2731,2719,2707,2697,2691,2687,2682,2675,2667,2660,2657,2683,2688,2693,
+2696,2696,2691,2685,2680,2676,2673,2667,2657,2644,2632,2623,2620,2621,2623,2622,2618,2612,2607,2604,2604,
+2605,2604,2602,2599,2597,2597,2600,2604,2610,2619,2633,2652,2670,2686,2695,2701,2710,2731,2767,2815,2865,
+2906,2928,2935,2932,2933,2943,2966,2997,3033,3069,3104,3137,3167,3190,3207,3218,3229,3245,3268,3296,3325,
+3348,3364,3375,3386,3400,3416,3434,3452,3470,3488,3506,3523,3538,3549,3557,3567,3582,3603,3626,3645,3656,
+3659,3661,3667,3682,3702,3722,3737,3747,3754,3764,3778,3790,3794,3783,3759,3732,3717,3723,3752,3789,3815,
+3811,3770,3700,3623,3565,3547,3571,3628,3697,3758,3797,3814,3814,3804,3791,3778,3765,3757,3758,3772,3798,
+3831,3863,3886,3900,3911,3926,3952,3988,4028,4065,4096,4124,4152,4186,4222,4259,4291,4318,4345,4375,4410,
+4449,4487,4520,4550,4579,4607,4633,4655,4672,4689,4719,4772,4847,4933,5005,5039,5025,4971,4899,4839,4807,
+4810,4837,4874,4909,4934,4945,4940,4913,4865,4802,4735,4681,4652,4646,4653,4658,4650,4630,4606,4591,4588,
+4594,4593,4573,4531,4477,4429,4409,4425,4473,4534,4582,4594,4561,4490,4403,4325,4273,4256,4265,4286,4304,
+4311,4306,4294,4280,4267,4255,4241,4224,4206,4190,4175,4160,4141,4116,4086,4056,4031,4012,3998,3983,3961,
+3930,3889,3845,3805,3775,3756,3747,3743,3740,3732,3717,3695,3670,3645,3624,3607,3594,3581,3569,3556,3547,
+3541,3538,3536,3532,3524,3513,3503,3496,3493,3492,3491,3490,3489,3488,3486,3482,3472,3458,3442,3430,3426,
+3428,3429,3422,3406,3392,3394,3426,3492,3583,3680,3764,3823,3859,3880,3898,3918,3940,3954,3956,3942,3915,
+3879,3838,3794,3747,3700,3654,3613,3576,3543,3508,3470,3427,3379,3328,3276,3221,3161,3097,3030,2966,2908,
+2857,2811,2767,2720,2671,2624,2583,2552,2528,2508,2485,2455,2419,2379,2338,2297,2256,2214,2171,2131,2096,
+2066,2040,2011,1977,1935,1890,1846,1808,1775,1745,1713,1678,1640,1604,1573,1547,1523,1496,1464,1427,1387,
+1350,1315,1283,1252,1219,1183,1145,1108,1072,1037,1002,966,929,892,856,820,786,753,720,687,653,
+619,585,549,514,480,448,417,385,353,319,285,251,218,185,152,118,82,46,10,-23,-56,
+-89,-122,-155,-188,-219,-249,-279,-311,-345,-382,-418,-453,-486,-517,-548,-578,-609,-640,-671,-704,-737,
+-772,-807,-841,-873,-904,-935,-967,-999,-1031,-1061,-1089,-1116,-1145,-1175,-1207,-1240,-1272,-1301,-1327,-1353,-1379,
+-1408,-1439,-1473,-1506,-1539,-1570,-1599,-1627,-1654,-1681,-1709,-1736,-1763,-1789,-1816,-1840,-1863,-1881,-1896,-1908,-1920,
+-1933,-1951,-1970,-1991,-2010,-2027,-2044,-2061,-2079,-2097,-2111,-2119,-2122,-2124,-2129,-2139,-2156,-2176,-2194,-2208,-2219,
+-2229,-2240,-2253,-2267,-2280,-2292,-2304,-2317,-2332,-2347,-2359,-2367,-2373,-2380,-2389,-2400,-2410,-2416,-2413,-2402,-2388,
+-2373,-2360,-2350,-2342,-2335,-2328,-2321,-2315,-2308,-2299,-2289,-2279,-2272,-2269,-2268,-2266,-2261,-2252,-2242,-2233,-2227,
+-2223,-2219,-2212,-2203,-2196,-2193,-2193,-2193,-2188,-2179,-2166,-2154,-2146,-2143,-2140,-2135,-2125,-2114,-2105,-2100,-2096,
+-2089,-2077,-2063,-2052,-2048,-2051,-2054,-2049,-2030,-2002,-1973,-1955,-1952,-1960,-1968,-1967,-1956,-1939,-1924,-1914,-1908,
+-1901,-1889,-1872,-1855,-1845,-1843,-1845,-1845,-1839,-1829,-1822,-1826,-1844,-1875,-1911,-1944,-1967,-1979,-1980,-1972,-1957,
+-1938,-1922,-1911,-1907,-1911,-1917,-1922,-1924,-1924,-1928,-1937,-1950,-1963,-1967,-1960,-1942,-1921,-1905,-1898,-1901,-1910,
+-1919,-1925,-1929,-1933,-1938,-1945,-1952,-1958,-1961,-1961,-1960,-1957,-1953,-1949,-1945,-1938,-1926,-1909,-1889,-1872,-1866,
+-1874,-1890,-1899,-1883,-1829,-1744,-1650,-1581,-1566,-1612,-1700,-1793,-1856,-1873,-1849,-1811,-1786,-1787,-1810,-1843,-1873,
+-1896,-1917,-1939,-1959,-1964,-1941,-1887,-1816,-1749,-1710,-1705,-1726,-1755,-1773,-1775,-1765,-1752,-1740,-1727,-1705,-1672,
+-1634,-1606,-1600,-1621,-1659,-1700,-1729,-1742,-1743,-1742,-1748,-1764,-1788,-1814,-1838,-1859,-1879,-1899,-1925,-1961,-2010,
+-2073,-2148,-2227,-2302,-2362,-2407,-2438,-2462,-2483,-2505,-2523,-2537,-2546,-2551,-2558,-2568,-2580,-2591,-2598,-2600,-2601,
+-2603,-2609,-2618,-2628,-2638,-2649,-2661,-2674,-2687,-2697,-2703,-2704,-2704,-2706,-2710,-2715,-2718,-2719,-2716,-2714,-2714,
+-2717,-2720,-2721,-2718,-2713,-2707,-2703,-2701,-2698,-2693,-2684,-2671,-2659,-2648,-2638,-2630,-2620,-2606,-2591,-2575,-2561,
+-2550,-2541,-2534,-2527,-2520,-2516,-2514,-2513,-2512,-2508,-2503,-2498,-2494,-2492,-2491,-2489,-2484,-2474,-2461,-2449,-2439,
+-2433,-2428,-2423,-2417,-2409,-2400,-2392,-2384,-2377,-2369,-2360,-2351,-2342,-2333,-2324,-2313,-2300,-2285,-2270,-2254,-2241,
+-2229,-2219,-2211,-2204,-2198,-2192,-2186,-2180,-2175,-2172,-2173,-2176,-2182,-2190,-2201,-2215,-2233,-2251,-2266,-2272,-2264,
+-2242,-2208,-2168,-2131,-2101,-2081,-2071,-2068,-2069,-2069,-2068,-2064,-2057,-2050,-2043,-2038,-2035,-2031,-2026,-2018,-2008,
+-1997,-1986,-1976,-1968,-1962,-1955,-1948,-1941,-1933,-1926,-1919,-1913,-1908,-1904,-1901,-1898,-1894,-1889,-1883,-1875,-1865,
+-1853,-1838,-1822,-1807,-1795,-1789,-1790,-1798,-1811,-1826,-1840,-1850,-1856,-1857,-1853,-1847,-1840,-1835,-1836,-1842,-1856,
+-1875,-1898,-1923,-1947,-1969,-1988,-2002,-2012,-2017,-2016,-2009,-1997,-1980,-1961,-1940,-1919,-1901,-1886,-1876,-1870,-1865,
+-1861,-1855,-1847,-1836,-1823,-1809,-1795,-1780,-1765,-1750,-1737,-1724,-1711,-1697,-1681,-1664,-1647,-1631,-1617,-1605,-1592,
+-1577,-1560,-1540,-1519,-1500,-1482,-1466,-1451,-1436,-1419,-1401,-1382,-1364,-1347,-1332,-1319,-1305,-1292,-1277,-1261,-1247,
+-1234,-1223,-1214,-1204,-1194,-1182,-1171,-1160,-1152,-1146,-1140,-1133,-1126,-1118,-1109,-1101,-1092,-1084,-1076,-1070,-1067,
+-1069,-1074,-1079,-1082,-1082,-1080,-1078,-1079,-1082,-1088,-1092,-1096,-1098,-1100,-1104,-1111,-1118,-1124,-1129,-1133,-1138,
+-1144,-1152,-1159,-1164,-1168,-1169,-1171,-1173,-1176,-1179,-1182,-1184,-1186,-1186,-1188,-1189,-1191,-1194,-1198,-1201,-1202,
+-1199,-1192,-1181,-1170,-1160,-1154,-1154,-1155,-1157,-1156,-1151,-1144,-1136,-1129,-1123,-1116,-1108,-1100,-1091,-1082,-1072,
+-1061,-1047,-1031,-1015,-999,-986,-976,-968,-961,-954,-947,-939,-929,-917,-903,-886,-869,-852,-838,-826,-818,
+-812,-809,-809,-811,-812,-811,-804,-794,-782,-772,-767,-765,-764,-761,-755,-744,-733,-721,-710,-697,-683,
+-665,-646,-627,-611,-597,-584,-571,-557,-540,-521,-501,-481,-461,-441,-421,-402,-383,-363,-343,-323,-304,
+-286,-269,-250,-229,-203,-174,-144,-115,-89,-65,-43,-19,6,33,60,85,110,136,163,194,226,
+258,289,319,349,380,411,440,464,483,495,506,517,526,526,512,481,441,412,417,475,588,
+741,905,1047,1147,1199,1212,1205,1193,1187,1185,1185,1178,1162,1133,1094,1048,1001,960,931,914,910,
+914,920,929,942,962,990,1023,1056,1082,1100,1110,1117,1122,1129,1135,1141,1147,1155,1170,1190,1214,
+1237,1255,1270,1283,1297,1311,1321,1322,1312,1295,1282,1281,1297,1327,1356,1371,1361,1328,1279,1232,1197,
+1179,1177,1182,1185,1184,1181,1178,1183,1194,1210,1224,1228,1217,1190,1149,1099,1046,997,956,921,889,
+858,821,779,733,686,641,602,569,544,527,520,522,531,543,551,545,523,483,430,373,320,
+274,237,206,177,147,117,89,66,53,51,58,74,94,117,141,168,195,223,247,266,276,
+280,280,283,293,311,336,361,381,390,390,385,381,383,391,403,417,430,443,456,471,490,
+514,549,599,671,765,874,981,1069,1125,1148,1147,1138,1137,1149,1169,1187,1196,1197,1202,1224,1272,
+1340,1415,1477,1511,1516,1501,1480,1467,1469,1484,1507,1532,1557,1581,1603,1619,1625,1618,1599,1575,1554,
+1539,1531,1527,1524,1524,1534,1560,1601,1648,1689,1713,1718,1716,1722,1749,1796,1852,1899,1924,1925,1914,
+1904,1904,1914,1929,1940,1946,1952,1963,1983,2009,2034,2051,2060,2064,2070,2082,2098,2116,2131,2144,2156,
+2170,2188,2207,2226,2242,2254,2266,2280,2296,2314,2332,2349,2366,2382,2397,2410,2422,2435,2448,2465,2484,
+2502,2517,2527,2534,2539,2547,2559,2574,2590,2605,2620,2633,2646,2658,2668,2677,2685,2693,2701,2708,2713,
+2717,2721,2727,2736,2748,2759,2767,2770,2771,2771,2775,2782,2789,2792,2789,2781,2772,2765,2760,2755,2749,
+2739,2726,2713,2702,2695,2690,2686,2683,2682,2683,2704,2705,2706,2707,2706,2704,2701,2699,2697,2693,2684,
+2672,2658,2647,2642,2643,2645,2644,2637,2626,2614,2607,2607,2612,2616,2617,2613,2609,2609,2616,2627,2639,
+2648,2654,2660,2667,2675,2682,2685,2686,2690,2707,2739,2786,2835,2874,2894,2896,2890,2889,2904,2938,2985,
+3036,3082,3119,3146,3167,3183,3196,3209,3223,3241,3263,3286,3307,3325,3339,3352,3365,3379,3395,3411,3426,
+3441,3457,3475,3493,3510,3524,3536,3549,3566,3586,3607,3624,3635,3641,3648,3659,3678,3700,3723,3741,3756,
+3771,3789,3806,3819,3819,3805,3781,3759,3752,3764,3789,3810,3810,3777,3714,3640,3578,3549,3562,3608,3669,
+3724,3758,3770,3765,3754,3744,3736,3731,3727,3726,3734,3755,3787,3823,3855,3877,3890,3902,3920,3949,3986,
+4024,4057,4085,4110,4140,4174,4211,4246,4275,4301,4329,4364,4406,4449,4488,4520,4546,4573,4603,4636,4665,
+4686,4701,4720,4752,4803,4863,4914,4937,4925,4884,4835,4801,4797,4823,4873,4933,4995,5050,5090,5105,5084,
+5023,4930,4824,4730,4665,4633,4622,4618,4608,4595,4587,4595,4619,4645,4655,4631,4573,4497,4431,4400,4417,
+4471,4539,4590,4600,4562,4489,4403,4329,4284,4271,4280,4297,4305,4299,4282,4260,4239,4224,4213,4202,4189,
+4173,4157,4143,4131,4118,4102,4084,4063,4042,4021,3998,3972,3940,3901,3857,3813,3776,3749,3734,3730,3732,
+3736,3735,3725,3706,3679,3650,3622,3599,3579,3562,3545,3530,3519,3514,3514,3517,3517,3514,3506,3497,3490,
+3485,3482,3478,3475,3473,3474,3477,3480,3477,3468,3454,3440,3434,3434,3436,3435,3427,3417,3414,3430,3470,
+3529,3597,3663,3721,3773,3825,3881,3937,3985,4012,4011,3986,3943,3893,3843,3794,3745,3695,3645,3597,3555,
+3520,3491,3464,3436,3406,3373,3334,3285,3225,3154,3078,3004,2939,2887,2842,2797,2745,2684,2620,2561,2514,
+2481,2457,2436,2412,2384,2354,2324,2294,2261,2223,2178,2130,2085,2048,2020,1994,1967,1932,1890,1846,1805,
+1769,1737,1706,1671,1634,1597,1564,1537,1514,1489,1458,1422,1382,1344,1309,1278,1248,1215,1178,1138,1099,
+1061,1027,994,962,927,893,858,824,792,760,727,693,659,623,589,555,522,490,458,426,394,
+362,331,300,269,237,205,170,134,97,60,24,-10,-45,-79,-112,-144,-175,-204,-234,-266,-302,
+-341,-380,-417,-450,-479,-505,-531,-560,-591,-624,-658,-693,-727,-760,-794,-827,-858,-889,-920,-950,-981,
+-1012,-1043,-1072,-1101,-1130,-1160,-1191,-1223,-1253,-1281,-1307,-1331,-1358,-1387,-1421,-1457,-1493,-1526,-1556,-1584,-1611,
+-1639,-1668,-1698,-1726,-1754,-1780,-1805,-1830,-1854,-1875,-1892,-1907,-1921,-1936,-1954,-1973,-1991,-2007,-2022,-2038,-2057,
+-2079,-2100,-2116,-2124,-2125,-2124,-2127,-2138,-2156,-2178,-2197,-2211,-2221,-2229,-2240,-2253,-2268,-2282,-2295,-2306,-2318,
+-2332,-2347,-2360,-2370,-2378,-2386,-2395,-2406,-2417,-2422,-2420,-2412,-2399,-2385,-2371,-2360,-2351,-2344,-2340,-2336,-2332,
+-2326,-2317,-2305,-2293,-2285,-2282,-2283,-2284,-2281,-2275,-2267,-2259,-2254,-2250,-2245,-2238,-2230,-2222,-2218,-2218,-2218,
+-2215,-2207,-2197,-2187,-2180,-2176,-2172,-2165,-2156,-2146,-2139,-2135,-2131,-2122,-2108,-2090,-2076,-2070,-2073,-2077,-2073,
+-2056,-2029,-2001,-1983,-1979,-1985,-1990,-1988,-1974,-1954,-1936,-1924,-1917,-1910,-1898,-1882,-1868,-1861,-1861,-1867,-1870,
+-1865,-1855,-1844,-1842,-1854,-1880,-1915,-1950,-1978,-1995,-1999,-1992,-1975,-1955,-1937,-1927,-1926,-1932,-1939,-1942,-1939,
+-1936,-1937,-1947,-1964,-1982,-1990,-1984,-1969,-1951,-1941,-1943,-1955,-1968,-1975,-1974,-1967,-1959,-1956,-1958,-1963,-1969,
+-1973,-1974,-1976,-1980,-1986,-1992,-1995,-1992,-1981,-1962,-1942,-1926,-1921,-1928,-1940,-1940,-1914,-1854,-1769,-1686,-1635,
+-1636,-1690,-1774,-1853,-1896,-1897,-1869,-1840,-1832,-1854,-1893,-1933,-1962,-1979,-1993,-2011,-2030,-2034,-2011,-1955,-1882,
+-1815,-1777,-1776,-1801,-1832,-1852,-1853,-1841,-1828,-1819,-1810,-1795,-1767,-1732,-1700,-1685,-1693,-1720,-1755,-1786,-1807,
+-1821,-1833,-1849,-1870,-1894,-1918,-1940,-1961,-1981,-2003,-2030,-2064,-2112,-2175,-2252,-2335,-2411,-2471,-2510,-2533,-2548,
+-2562,-2580,-2599,-2616,-2627,-2635,-2643,-2654,-2668,-2680,-2689,-2693,-2693,-2693,-2696,-2702,-2711,-2721,-2731,-2742,-2754,
+-2765,-2774,-2779,-2779,-2778,-2777,-2779,-2783,-2786,-2788,-2788,-2788,-2790,-2794,-2797,-2798,-2793,-2783,-2773,-2765,-2760,
+-2758,-2755,-2750,-2742,-2733,-2726,-2720,-2715,-2707,-2695,-2678,-2659,-2642,-2628,-2618,-2610,-2603,-2596,-2589,-2583,-2579,
+-2575,-2570,-2564,-2559,-2555,-2553,-2552,-2550,-2545,-2536,-2525,-2514,-2503,-2495,-2487,-2479,-2471,-2462,-2453,-2446,-2439,
+-2432,-2424,-2415,-2405,-2395,-2385,-2374,-2364,-2352,-2340,-2327,-2312,-2297,-2283,-2271,-2262,-2256,-2252,-2249,-2244,-2237,
+-2228,-2219,-2210,-2202,-2195,-2191,-2192,-2198,-2212,-2233,-2257,-2278,-2290,-2289,-2273,-2247,-2215,-2184,-2156,-2134,-2116,
+-2103,-2093,-2084,-2077,-2072,-2070,-2069,-2070,-2071,-2069,-2063,-2053,-2042,-2029,-2018,-2009,-2001,-1993,-1986,-1979,-1973,
+-1967,-1961,-1954,-1947,-1939,-1931,-1924,-1918,-1912,-1906,-1899,-1892,-1883,-1874,-1865,-1855,-1845,-1835,-1826,-1818,-1811,
+-1808,-1807,-1808,-1812,-1818,-1825,-1832,-1839,-1844,-1848,-1850,-1852,-1855,-1860,-1868,-1881,-1897,-1918,-1941,-1965,-1989,
+-2010,-2028,-2040,-2045,-2042,-2031,-2013,-1991,-1967,-1943,-1923,-1904,-1889,-1874,-1861,-1849,-1837,-1825,-1813,-1798,-1781,
+-1763,-1745,-1729,-1716,-1705,-1695,-1685,-1674,-1662,-1649,-1635,-1621,-1606,-1588,-1569,-1547,-1526,-1507,-1489,-1475,-1461,
+-1446,-1431,-1413,-1394,-1375,-1357,-1342,-1328,-1314,-1300,-1284,-1268,-1252,-1238,-1226,-1215,-1205,-1194,-1183,-1172,-1163,
+-1157,-1152,-1148,-1143,-1136,-1128,-1121,-1113,-1105,-1096,-1088,-1082,-1080,-1083,-1088,-1095,-1099,-1100,-1097,-1094,-1093,
+-1095,-1099,-1104,-1108,-1110,-1112,-1116,-1120,-1126,-1131,-1135,-1139,-1143,-1149,-1156,-1162,-1166,-1167,-1167,-1165,-1166,
+-1168,-1173,-1179,-1184,-1187,-1190,-1192,-1194,-1197,-1202,-1206,-1210,-1212,-1210,-1204,-1195,-1186,-1178,-1173,-1170,-1169,
+-1169,-1167,-1164,-1159,-1153,-1145,-1135,-1124,-1114,-1106,-1100,-1095,-1088,-1078,-1063,-1045,-1027,-1010,-998,-988,-981,
+-973,-965,-958,-950,-941,-932,-920,-905,-888,-869,-852,-836,-824,-817,-815,-818,-823,-827,-827,-821,-809,
+-795,-784,-778,-776,-776,-774,-769,-760,-748,-737,-725,-711,-696,-678,-659,-640,-624,-611,-599,-586,-572,
+-555,-536,-515,-494,-474,-454,-436,-419,-403,-387,-370,-352,-335,-318,-300,-281,-258,-231,-201,-170,-140,
+-114,-91,-68,-43,-14,17,49,78,104,129,154,182,213,244,274,302,330,360,390,420,446,
+466,480,491,502,513,517,509,484,448,414,404,435,516,638,784,927,1047,1129,1171,1179,1165,
+1140,1114,1096,1087,1085,1082,1071,1046,1008,965,927,902,893,897,910,927,947,972,1002,1039,1077,
+1111,1137,1156,1167,1175,1180,1183,1184,1185,1188,1196,1210,1228,1245,1261,1273,1284,1294,1302,1306,1303,
+1291,1275,1262,1259,1267,1283,1296,1296,1279,1247,1208,1173,1150,1141,1142,1147,1150,1150,1149,1148,1152,
+1158,1164,1164,1155,1132,1096,1051,1001,951,904,861,821,782,741,698,654,613,576,545,519,500,
+486,479,481,494,515,539,560,568,554,517,459,388,315,251,205,177,165,165,171,182,196,
+214,236,258,275,283,280,269,256,246,243,245,248,251,254,260,276,304,344,387,425,447,
+449,433,407,381,361,351,347,347,347,348,349,353,363,381,412,463,538,638,757,879,985,
+1063,1105,1121,1125,1132,1150,1177,1205,1225,1236,1246,1265,1305,1363,1429,1487,1522,1531,1520,1504,1494,
+1498,1514,1535,1556,1573,1589,1602,1612,1615,1608,1593,1572,1555,1545,1543,1546,1549,1553,1560,1573,1594,
+1618,1638,1650,1659,1673,1705,1756,1821,1882,1925,1941,1935,1920,1912,1916,1930,1945,1952,1953,1954,1961,
+1980,2007,2035,2058,2072,2082,2091,2102,2115,2127,2137,2147,2159,2177,2198,2219,2235,2246,2253,2260,2272,
+2287,2306,2324,2341,2356,2370,2383,2396,2408,2420,2432,2447,2464,2481,2495,2505,2512,2519,2529,2545,2564,
+2583,2600,2614,2625,2634,2643,2651,2658,2664,2669,2674,2679,2685,2692,2701,2713,2726,2740,2751,2758,2762,
+2765,2771,2781,2795,2808,2814,2811,2801,2787,2777,2770,2767,2763,2756,2745,2732,2721,2714,2709,2707,2706,
+2704,2704,2716,2711,2707,2706,2706,2706,2707,2708,2707,2702,2691,2678,2664,2655,2653,2656,2657,2652,2640,
+2624,2612,2610,2616,2628,2636,2638,2634,2632,2639,2656,2678,2695,2701,2696,2684,2674,2672,2676,2684,2692,
+2701,2716,2742,2777,2815,2845,2861,2863,2861,2869,2894,2936,2987,3035,3069,3090,3100,3107,3117,3133,3154,
+3177,3199,3219,3237,3253,3268,3284,3303,3325,3349,3371,3391,3407,3421,3436,3453,3474,3494,3513,3529,3543,
+3558,3573,3590,3606,3621,3634,3647,3661,3676,3692,3707,3722,3738,3756,3775,3790,3798,3796,3785,3772,3768,
+3776,3795,3812,3813,3786,3730,3659,3594,3555,3555,3590,3644,3697,3731,3741,3733,3716,3703,3697,3697,3699,
+3701,3707,3719,3742,3774,3808,3837,3858,3872,3886,3908,3938,3974,4008,4038,4063,4090,4121,4157,4194,4227,
+4254,4280,4311,4351,4399,4446,4485,4514,4538,4562,4595,4633,4669,4697,4714,4726,4743,4769,4801,4829,4841,
+4833,4811,4788,4776,4783,4809,4849,4899,4959,5026,5089,5132,5138,5095,5008,4898,4790,4707,4654,4625,4605,
+4589,4579,4585,4614,4658,4700,4713,4682,4609,4514,4429,4382,4382,4421,4473,4511,4516,4485,4430,4371,4325,
+4302,4299,4307,4312,4304,4283,4253,4222,4196,4178,4166,4156,4145,4132,4120,4111,4106,4102,4097,4087,4071,
+4048,4018,3983,3943,3900,3857,3817,3783,3756,3739,3731,3730,3734,3738,3738,3728,3710,3685,3657,3631,3608,
+3586,3564,3541,3519,3502,3493,3494,3499,3503,3502,3496,3487,3479,3475,3474,3474,3473,3472,3473,3476,3480,
+3481,3477,3468,3458,3450,3447,3448,3448,3444,3437,3432,3436,3455,3488,3529,3576,3625,3681,3747,3821,3895,
+3955,3989,3989,3959,3910,3854,3800,3753,3708,3664,3620,3576,3536,3500,3468,3437,3405,3373,3338,3297,3246,
+3181,3104,3024,2952,2898,2867,2850,2834,2804,2753,2683,2606,2534,2476,2432,2396,2363,2331,2302,2279,2261,
+2243,2219,2183,2138,2088,2043,2007,1979,1952,1922,1884,1842,1799,1761,1727,1696,1663,1628,1591,1558,1529,
+1504,1480,1452,1420,1383,1345,1310,1277,1245,1211,1174,1134,1095,1058,1023,991,959,927,895,864,834,
+805,774,741,706,669,633,598,565,533,500,466,432,399,367,336,307,277,247,214,180,143,
+106,69,32,-4,-40,-75,-108,-139,-168,-196,-226,-259,-296,-336,-377,-413,-445,-471,-493,-517,-543,
+-574,-608,-644,-679,-713,-746,-779,-811,-843,-874,-904,-933,-964,-994,-1026,-1058,-1089,-1120,-1150,-1180,-1210,
+-1240,-1267,-1293,-1318,-1345,-1375,-1409,-1445,-1481,-1514,-1544,-1571,-1598,-1626,-1656,-1686,-1716,-1745,-1771,-1797,-1821,
+-1844,-1865,-1884,-1901,-1919,-1938,-1958,-1976,-1993,-2006,-2019,-2035,-2057,-2082,-2106,-2124,-2132,-2132,-2129,-2132,-2142,
+-2161,-2183,-2202,-2216,-2225,-2233,-2244,-2258,-2273,-2288,-2300,-2312,-2324,-2338,-2352,-2365,-2376,-2384,-2392,-2401,-2411,
+-2421,-2426,-2425,-2418,-2407,-2394,-2382,-2372,-2364,-2358,-2354,-2353,-2350,-2345,-2336,-2324,-2311,-2303,-2300,-2301,-2303,
+-2303,-2298,-2292,-2285,-2281,-2278,-2275,-2270,-2263,-2256,-2251,-2247,-2244,-2240,-2233,-2226,-2219,-2214,-2211,-2207,-2199,
+-2191,-2182,-2177,-2173,-2168,-2156,-2139,-2118,-2103,-2098,-2101,-2106,-2104,-2089,-2063,-2036,-2017,-2009,-2011,-2012,-2005,
+-1988,-1967,-1948,-1936,-1929,-1922,-1910,-1896,-1883,-1876,-1879,-1886,-1892,-1889,-1879,-1866,-1859,-1865,-1886,-1919,-1956,
+-1990,-2016,-2028,-2027,-2013,-1992,-1973,-1961,-1958,-1962,-1967,-1967,-1963,-1958,-1959,-1971,-1989,-2007,-2015,-2012,-2000,
+-1989,-1987,-1996,-2011,-2022,-2023,-2013,-1999,-1987,-1981,-1983,-1988,-1993,-1996,-1999,-2004,-2011,-2019,-2026,-2028,-2024,
+-2017,-2009,-2003,-2001,-2003,-2005,-2004,-1989,-1954,-1900,-1834,-1776,-1744,-1749,-1790,-1847,-1896,-1920,-1918,-1903,-1895,
+-1908,-1942,-1984,-2017,-2037,-2047,-2058,-2079,-2102,-2111,-2092,-2039,-1966,-1899,-1859,-1856,-1879,-1908,-1925,-1924,-1912,
+-1900,-1896,-1897,-1896,-1883,-1859,-1831,-1811,-1807,-1819,-1844,-1872,-1900,-1926,-1949,-1971,-1991,-2008,-2024,-2041,-2061,
+-2086,-2114,-2146,-2185,-2233,-2293,-2366,-2443,-2515,-2571,-2607,-2627,-2639,-2650,-2665,-2682,-2697,-2708,-2716,-2725,-2737,
+-2752,-2765,-2773,-2775,-2774,-2774,-2778,-2788,-2799,-2810,-2818,-2825,-2832,-2839,-2846,-2851,-2852,-2850,-2848,-2847,-2847,
+-2849,-2851,-2853,-2856,-2860,-2866,-2870,-2870,-2864,-2854,-2841,-2831,-2825,-2822,-2820,-2817,-2812,-2805,-2798,-2793,-2789,
+-2782,-2771,-2755,-2737,-2719,-2705,-2695,-2687,-2681,-2674,-2666,-2658,-2650,-2642,-2635,-2628,-2622,-2618,-2615,-2612,-2609,
+-2603,-2595,-2585,-2575,-2564,-2555,-2545,-2536,-2527,-2518,-2510,-2503,-2497,-2490,-2482,-2473,-2463,-2452,-2440,-2429,-2418,
+-2407,-2396,-2385,-2373,-2359,-2344,-2330,-2318,-2309,-2303,-2298,-2293,-2286,-2277,-2268,-2259,-2249,-2238,-2227,-2216,-2208,
+-2207,-2216,-2233,-2254,-2276,-2291,-2297,-2293,-2279,-2258,-2233,-2207,-2182,-2158,-2138,-2122,-2111,-2104,-2100,-2100,-2099,
+-2098,-2095,-2088,-2079,-2069,-2058,-2048,-2039,-2030,-2022,-2013,-2006,-2001,-1997,-1994,-1990,-1984,-1976,-1966,-1955,-1944,
+-1934,-1924,-1914,-1904,-1896,-1890,-1886,-1884,-1881,-1877,-1870,-1859,-1845,-1830,-1816,-1804,-1795,-1792,-1794,-1801,-1811,
+-1822,-1831,-1835,-1835,-1832,-1829,-1828,-1832,-1841,-1855,-1874,-1896,-1921,-1948,-1975,-2001,-2024,-2040,-2048,-2047,-2039,
+-2024,-2006,-1985,-1962,-1938,-1913,-1889,-1868,-1851,-1837,-1825,-1812,-1797,-1779,-1759,-1740,-1723,-1709,-1697,-1686,-1675,
+-1663,-1651,-1638,-1623,-1608,-1591,-1573,-1554,-1534,-1515,-1498,-1482,-1467,-1453,-1438,-1422,-1406,-1389,-1373,-1357,-1343,
+-1328,-1313,-1297,-1280,-1264,-1250,-1237,-1226,-1216,-1204,-1193,-1181,-1172,-1165,-1159,-1154,-1148,-1142,-1135,-1129,-1124,
+-1118,-1113,-1107,-1102,-1100,-1102,-1108,-1114,-1120,-1122,-1121,-1118,-1115,-1115,-1117,-1120,-1124,-1126,-1129,-1131,-1134,
+-1137,-1140,-1143,-1146,-1151,-1156,-1162,-1168,-1172,-1172,-1170,-1168,-1166,-1168,-1171,-1176,-1181,-1185,-1189,-1192,-1195,
+-1200,-1205,-1210,-1213,-1214,-1212,-1208,-1202,-1195,-1190,-1185,-1182,-1179,-1178,-1176,-1175,-1173,-1168,-1159,-1148,-1135,
+-1124,-1115,-1109,-1104,-1096,-1083,-1066,-1047,-1030,-1016,-1006,-999,-991,-981,-971,-961,-952,-946,-941,-933,-922,
+-906,-888,-869,-851,-837,-828,-824,-826,-830,-834,-834,-829,-819,-808,-799,-795,-795,-795,-794,-788,-778,
+-765,-751,-737,-721,-704,-686,-667,-649,-632,-618,-605,-593,-580,-566,-551,-534,-515,-495,-474,-454,-436,
+-421,-407,-392,-375,-357,-339,-321,-302,-280,-254,-225,-195,-165,-139,-115,-91,-64,-32,3,39,72,
+99,124,148,173,202,231,259,286,312,339,368,397,425,446,463,476,488,499,507,505,490,
+464,434,417,425,469,550,659,784,907,1013,1088,1126,1127,1101,1062,1029,1014,1019,1037,1050,1046,
+1019,975,927,891,876,882,903,933,966,1001,1039,1080,1121,1157,1185,1203,1213,1218,1220,1222,1224,
+1226,1229,1233,1239,1247,1255,1262,1267,1272,1276,1278,1276,1269,1256,1241,1227,1218,1213,1209,1200,1183,
+1158,1128,1100,1078,1063,1056,1052,1051,1050,1050,1051,1052,1051,1047,1039,1024,1002,975,941,903,862,
+818,773,728,683,639,597,558,525,502,490,488,494,506,520,536,554,575,600,630,659,681,
+685,665,619,553,479,414,371,360,381,426,488,556,624,688,741,776,785,765,716,649,575,
+510,461,430,413,405,403,410,430,468,519,573,618,641,635,604,554,496,440,391,351,320,
+295,278,269,267,273,290,320,369,441,538,654,776,888,978,1038,1071,1088,1103,1125,1155,1189,
+1221,1249,1275,1307,1349,1401,1457,1503,1531,1538,1532,1523,1523,1534,1555,1577,1594,1603,1605,1604,1601,
+1595,1585,1571,1555,1543,1539,1543,1553,1563,1572,1578,1584,1589,1593,1597,1602,1614,1639,1682,1743,1809,
+1867,1906,1922,1922,1920,1925,1939,1959,1974,1979,1977,1974,1977,1991,2011,2034,2054,2071,2086,2102,2117,
+2130,2139,2144,2150,2162,2180,2203,2225,2240,2248,2252,2257,2266,2279,2293,2306,2318,2329,2341,2356,2372,
+2388,2401,2413,2425,2439,2453,2466,2476,2484,2493,2506,2524,2546,2567,2585,2598,2606,2614,2621,2629,2637,
+2642,2646,2649,2653,2659,2668,2680,2694,2708,2721,2731,2739,2745,2752,2764,2780,2798,2815,2824,2822,2812,
+2799,2787,2779,2775,2771,2765,2755,2745,2737,2732,2731,2730,2727,2722,2716,2727,2722,2720,2721,2723,2725,
+2723,2718,2708,2695,2678,2663,2651,2647,2651,2659,2664,2664,2656,2646,2641,2645,2656,2668,2673,2669,2662,
+2661,2674,2698,2726,2744,2742,2721,2692,2669,2663,2672,2692,2713,2730,2744,2759,2778,2801,2820,2834,2841,
+2849,2866,2895,2934,2972,2999,3009,3006,2998,2995,3006,3029,3059,3091,3118,3140,3157,3172,3190,3213,3241,
+3272,3306,3336,3361,3381,3396,3411,3429,3450,3475,3498,3518,3533,3546,3559,3576,3596,3619,3641,3659,3672,
+3681,3687,3695,3704,3717,3731,3741,3744,3740,3731,3725,3729,3746,3772,3797,3804,3785,3736,3669,3603,3557,
+3546,3569,3617,3669,3708,3724,3718,3699,3679,3667,3664,3668,3674,3680,3688,3702,3723,3751,3782,3809,3830,
+3849,3870,3897,3928,3961,3992,4018,4043,4071,4104,4141,4176,4207,4233,4259,4292,4334,4383,4430,4469,4497,
+4519,4544,4577,4618,4659,4693,4717,4733,4747,4765,4783,4798,4803,4799,4789,4780,4775,4774,4776,4781,4794,
+4824,4874,4937,4995,5026,5014,4959,4877,4789,4716,4662,4624,4596,4575,4569,4586,4629,4686,4732,4743,4704,
+4619,4513,4416,4352,4329,4339,4363,4381,4384,4371,4349,4331,4322,4322,4326,4327,4317,4295,4264,4229,4196,
+4169,4150,4136,4124,4114,4104,4097,4094,4094,4095,4093,4083,4064,4035,3997,3952,3905,3860,3820,3789,3767,
+3754,3747,3746,3747,3749,3749,3743,3729,3709,3685,3661,3640,3622,3604,3581,3552,3521,3495,3479,3474,3479,
+3484,3484,3478,3469,3463,3462,3468,3475,3481,3483,3482,3482,3483,3485,3485,3481,3474,3467,3462,3460,3458,
+3454,3449,3444,3445,3455,3476,3505,3540,3580,3628,3683,3745,3805,3853,3877,3874,3847,3805,3760,3718,3683,
+3651,3620,3586,3551,3515,3478,3438,3395,3350,3304,3258,3209,3151,3080,2997,2910,2835,2787,2771,2781,2798,
+2800,2773,2715,2638,2557,2487,2430,2383,2340,2296,2255,2223,2203,2192,2181,2162,2130,2087,2041,1999,1965,
+1936,1906,1871,1831,1788,1749,1714,1684,1655,1624,1591,1557,1526,1497,1470,1443,1413,1379,1343,1307,1272,
+1238,1204,1169,1133,1097,1062,1027,993,959,927,897,868,842,814,785,752,716,680,645,611,578,
+545,511,476,440,406,375,345,316,286,254,219,183,146,109,72,35,0,-34,-67,-99,-128,
+-157,-185,-215,-248,-283,-322,-360,-395,-426,-452,-475,-498,-525,-557,-592,-629,-664,-698,-729,-761,-792,
+-824,-856,-886,-916,-946,-977,-1010,-1043,-1077,-1109,-1140,-1169,-1197,-1226,-1254,-1282,-1311,-1340,-1370,-1403,-1438,
+-1472,-1504,-1534,-1562,-1588,-1616,-1646,-1677,-1708,-1738,-1767,-1793,-1816,-1837,-1856,-1874,-1893,-1912,-1933,-1954,-1973,
+-1988,-2000,-2013,-2030,-2053,-2080,-2107,-2126,-2136,-2137,-2137,-2140,-2151,-2168,-2188,-2206,-2218,-2228,-2237,-2249,-2263,
+-2278,-2293,-2305,-2317,-2330,-2343,-2357,-2369,-2379,-2386,-2393,-2402,-2412,-2421,-2427,-2427,-2422,-2413,-2403,-2393,-2385,
+-2379,-2375,-2372,-2370,-2368,-2364,-2356,-2345,-2334,-2326,-2322,-2321,-2322,-2321,-2317,-2310,-2304,-2299,-2297,-2295,-2292,
+-2288,-2283,-2279,-2274,-2270,-2264,-2258,-2252,-2248,-2245,-2243,-2238,-2231,-2222,-2214,-2209,-2205,-2198,-2186,-2167,-2147,
+-2132,-2128,-2132,-2138,-2137,-2124,-2100,-2073,-2051,-2039,-2033,-2027,-2016,-1999,-1980,-1965,-1955,-1950,-1944,-1933,-1918,
+-1903,-1895,-1896,-1902,-1907,-1905,-1896,-1884,-1875,-1877,-1893,-1922,-1960,-1998,-2032,-2054,-2061,-2053,-2035,-2016,-2001,
+-1993,-1993,-1994,-1992,-1988,-1985,-1989,-2002,-2020,-2035,-2042,-2038,-2029,-2023,-2026,-2036,-2048,-2054,-2049,-2037,-2024,
+-2016,-2014,-2018,-2023,-2027,-2030,-2037,-2046,-2057,-2063,-2062,-2055,-2047,-2046,-2054,-2069,-2083,-2088,-2078,-2055,-2023,
+-1989,-1956,-1928,-1908,-1899,-1902,-1915,-1933,-1947,-1953,-1954,-1958,-1971,-1998,-2034,-2069,-2092,-2104,-2112,-2126,-2148,
+-2172,-2182,-2165,-2118,-2055,-1997,-1963,-1959,-1976,-1998,-2008,-2003,-1989,-1978,-1978,-1987,-1997,-2000,-1991,-1974,-1958,
+-1951,-1955,-1971,-1995,-2021,-2048,-2072,-2092,-2106,-2116,-2125,-2138,-2159,-2190,-2228,-2271,-2318,-2371,-2432,-2498,-2566,
+-2626,-2673,-2703,-2721,-2733,-2746,-2760,-2775,-2787,-2794,-2800,-2808,-2819,-2833,-2844,-2849,-2848,-2845,-2846,-2854,-2869,
+-2886,-2900,-2908,-2911,-2912,-2915,-2920,-2925,-2927,-2926,-2922,-2918,-2915,-2913,-2914,-2916,-2919,-2923,-2929,-2933,-2934,
+-2931,-2922,-2912,-2902,-2896,-2892,-2889,-2886,-2880,-2873,-2866,-2860,-2854,-2848,-2838,-2825,-2810,-2795,-2782,-2772,-2765,
+-2760,-2754,-2747,-2738,-2727,-2716,-2705,-2696,-2688,-2682,-2678,-2673,-2668,-2661,-2653,-2644,-2635,-2626,-2616,-2607,-2597,
+-2588,-2579,-2571,-2563,-2555,-2547,-2538,-2529,-2520,-2510,-2500,-2488,-2476,-2464,-2452,-2441,-2430,-2418,-2405,-2390,-2376,
+-2364,-2353,-2345,-2337,-2328,-2320,-2313,-2306,-2298,-2289,-2276,-2261,-2246,-2234,-2228,-2231,-2242,-2258,-2275,-2290,-2299,
+-2302,-2297,-2286,-2270,-2251,-2231,-2213,-2196,-2182,-2169,-2157,-2145,-2134,-2125,-2116,-2108,-2100,-2092,-2085,-2076,-2068,
+-2058,-2049,-2040,-2032,-2026,-2023,-2020,-2016,-2011,-2003,-1993,-1982,-1970,-1959,-1948,-1938,-1928,-1919,-1911,-1906,-1902,
+-1899,-1896,-1891,-1883,-1873,-1861,-1847,-1832,-1817,-1803,-1794,-1790,-1791,-1795,-1800,-1803,-1803,-1799,-1796,-1794,-1796,
+-1802,-1811,-1821,-1832,-1845,-1861,-1881,-1905,-1931,-1956,-1978,-1995,-2006,-2013,-2015,-2011,-2001,-1983,-1960,-1934,-1908,
+-1886,-1868,-1855,-1843,-1831,-1816,-1798,-1779,-1758,-1737,-1716,-1695,-1676,-1657,-1640,-1625,-1611,-1597,-1584,-1571,-1556,
+-1540,-1523,-1506,-1489,-1472,-1456,-1442,-1428,-1414,-1400,-1385,-1370,-1355,-1340,-1325,-1310,-1296,-1282,-1269,-1258,-1247,
+-1237,-1226,-1214,-1202,-1190,-1180,-1171,-1163,-1156,-1149,-1143,-1138,-1135,-1132,-1130,-1126,-1123,-1121,-1122,-1126,-1132,
+-1138,-1141,-1142,-1140,-1137,-1136,-1136,-1138,-1141,-1144,-1147,-1150,-1153,-1155,-1157,-1159,-1161,-1164,-1168,-1174,-1179,
+-1184,-1186,-1185,-1184,-1182,-1181,-1182,-1184,-1187,-1190,-1192,-1196,-1200,-1204,-1209,-1214,-1216,-1216,-1214,-1211,-1207,
+-1204,-1200,-1195,-1191,-1187,-1184,-1183,-1182,-1182,-1179,-1172,-1163,-1152,-1141,-1133,-1126,-1118,-1106,-1090,-1072,-1053,
+-1037,-1026,-1017,-1009,-997,-983,-968,-954,-946,-941,-938,-933,-925,-912,-896,-879,-863,-850,-841,-836,-834,
+-835,-836,-836,-834,-831,-827,-825,-824,-825,-824,-820,-811,-798,-781,-763,-744,-724,-704,-684,-665,-648,
+-631,-616,-602,-589,-578,-568,-558,-546,-531,-511,-489,-467,-449,-433,-420,-405,-389,-370,-351,-333,-315,
+-298,-277,-252,-223,-194,-166,-140,-114,-85,-52,-15,21,55,84,110,136,162,191,219,246,270,
+293,318,344,373,400,424,445,462,477,490,500,501,493,476,455,438,433,447,484,547,633,
+738,850,954,1034,1076,1079,1054,1021,1000,999,1017,1037,1042,1021,978,927,883,861,866,892,933,
+980,1029,1079,1128,1172,1208,1233,1245,1249,1250,1251,1257,1265,1273,1280,1284,1283,1280,1274,1266,1259,
+1251,1242,1232,1219,1202,1184,1166,1151,1137,1123,1107,1085,1058,1029,1002,979,960,943,927,913,901,
+894,894,898,900,897,885,863,837,809,782,757,729,697,660,619,576,536,502,476,459,453,
+459,479,513,557,609,661,707,745,772,793,813,833,853,866,863,838,791,732,678,646,649,
+691,765,861,967,1071,1165,1239,1284,1291,1255,1180,1079,970,873,800,753,726,711,704,706,721,
+753,801,856,908,941,947,922,868,794,706,616,532,461,408,375,362,364,379,404,439,488,
+554,637,732,833,926,1002,1056,1087,1102,1111,1121,1139,1164,1196,1233,1273,1319,1369,1420,1466,1500,
+1519,1521,1516,1511,1516,1532,1555,1578,1594,1600,1597,1588,1578,1569,1559,1549,1540,1533,1531,1536,1547,
+1559,1571,1579,1583,1584,1583,1583,1587,1601,1628,1670,1722,1777,1825,1863,1889,1910,1931,1955,1981,2002,
+2014,2015,2011,2007,2009,2016,2027,2039,2050,2064,2081,2101,2122,2138,2147,2151,2156,2165,2182,2202,2222,
+2236,2245,2250,2257,2266,2275,2284,2289,2292,2298,2310,2328,2348,2367,2382,2394,2405,2417,2430,2443,2453,
+2462,2471,2484,2503,2525,2546,2564,2577,2585,2592,2599,2606,2613,2618,2621,2625,2629,2637,2648,2660,2673,
+2684,2694,2703,2711,2719,2729,2742,2760,2778,2795,2807,2810,2807,2799,2792,2786,2781,2775,2767,2758,2749,
+2743,2742,2743,2743,2740,2734,2727,2733,2735,2740,2748,2753,2752,2742,2724,2702,2679,2659,2646,2641,2647,
+2660,2676,2690,2698,2700,2701,2704,2711,2719,2722,2716,2701,2685,2679,2690,2713,2739,2751,2740,2711,2675,
+2649,2645,2662,2691,2719,2738,2748,2754,2764,2778,2797,2814,2830,2845,2863,2886,2909,2926,2931,2923,2908,
+2896,2896,2912,2941,2975,3007,3034,3055,3075,3096,3120,3150,3182,3217,3251,3282,3308,3329,3345,3360,3377,
+3399,3424,3450,3474,3494,3511,3528,3550,3577,3607,3635,3656,3668,3673,3677,3684,3695,3707,3714,3711,3695,
+3674,3657,3656,3675,3710,3747,3769,3762,3722,3660,3593,3541,3521,3535,3576,3628,3673,3699,3703,3689,3667,
+3647,3636,3635,3640,3648,3657,3668,3682,3701,3725,3751,3778,3804,3830,3859,3890,3922,3952,3979,4004,4028,
+4056,4089,4124,4157,4186,4212,4240,4273,4314,4359,4402,4438,4467,4492,4520,4554,4594,4634,4671,4700,4725,
+4747,4768,4785,4795,4797,4792,4785,4779,4773,4761,4741,4715,4692,4685,4703,4742,4788,4820,4825,4800,4754,
+4702,4655,4617,4586,4558,4539,4537,4562,4610,4668,4711,4716,4672,4589,4487,4392,4324,4287,4275,4277,4283,
+4290,4300,4314,4331,4349,4360,4359,4345,4318,4284,4248,4214,4184,4159,4139,4121,4106,4094,4086,4082,4083,
+4084,4083,4076,4060,4035,4001,3960,3916,3872,3833,3802,3781,3770,3765,3765,3767,3768,3766,3759,3747,3728,
+3705,3680,3659,3643,3630,3616,3596,3566,3531,3498,3474,3463,3463,3466,3467,3462,3456,3452,3456,3467,3482,
+3493,3497,3496,3492,3490,3491,3492,3492,3488,3481,3474,3468,3464,3460,3455,3451,3452,3459,3476,3501,3531,
+3563,3596,3629,3662,3690,3710,3717,3709,3691,3668,3646,3628,3613,3599,3580,3556,3528,3494,3455,3410,3358,
+3303,3248,3196,3145,3088,3017,2929,2831,2739,2673,2642,2646,2667,2681,2671,2632,2573,2510,2459,2422,2391,
+2357,2310,2255,2201,2159,2134,2124,2115,2099,2070,2030,1988,1949,1916,1886,1853,1816,1776,1736,1701,1672,
+1646,1621,1592,1559,1525,1492,1461,1432,1402,1370,1336,1299,1262,1226,1192,1160,1130,1099,1066,1032,996,
+961,928,897,869,842,815,784,752,718,684,652,620,588,554,519,484,450,419,389,360,330,
+296,260,222,183,145,107,70,35,2,-27,-56,-83,-111,-141,-171,-203,-236,-270,-304,-338,-371,
+-401,-429,-455,-482,-512,-545,-581,-618,-652,-684,-714,-744,-775,-808,-841,-872,-903,-933,-964,-997,-1032,
+-1066,-1098,-1127,-1153,-1179,-1206,-1235,-1267,-1300,-1332,-1365,-1397,-1430,-1462,-1495,-1525,-1554,-1581,-1609,-1637,-1668,
+-1700,-1733,-1763,-1790,-1813,-1833,-1850,-1867,-1885,-1904,-1925,-1945,-1963,-1976,-1988,-2001,-2019,-2043,-2070,-2097,-2118,
+-2131,-2137,-2141,-2148,-2160,-2176,-2193,-2207,-2218,-2227,-2237,-2250,-2265,-2280,-2294,-2306,-2319,-2332,-2346,-2360,-2372,
+-2380,-2387,-2395,-2404,-2416,-2427,-2433,-2435,-2430,-2423,-2414,-2406,-2400,-2394,-2390,-2387,-2386,-2384,-2381,-2375,-2367,
+-2357,-2348,-2342,-2338,-2337,-2335,-2331,-2326,-2320,-2315,-2311,-2308,-2305,-2303,-2301,-2298,-2296,-2293,-2288,-2283,-2279,
+-2277,-2275,-2273,-2268,-2259,-2250,-2241,-2235,-2231,-2224,-2213,-2196,-2177,-2164,-2158,-2161,-2166,-2165,-2154,-2133,-2108,
+-2085,-2068,-2056,-2045,-2031,-2015,-1999,-1988,-1982,-1979,-1973,-1962,-1946,-1931,-1921,-1918,-1922,-1925,-1924,-1917,-1905,
+-1895,-1893,-1902,-1924,-1957,-1996,-2034,-2064,-2081,-2082,-2071,-2054,-2039,-2028,-2022,-2018,-2014,-2010,-2010,-2018,-2033,
+-2052,-2067,-2073,-2068,-2059,-2053,-2053,-2059,-2066,-2067,-2063,-2056,-2051,-2052,-2056,-2060,-2061,-2063,-2069,-2082,-2101,
+-2118,-2124,-2115,-2097,-2083,-2086,-2106,-2135,-2154,-2148,-2114,-2062,-2013,-1985,-1985,-2006,-2033,-2052,-2055,-2045,-2028,
+-2015,-2011,-2018,-2034,-2057,-2085,-2113,-2138,-2158,-2173,-2187,-2202,-2219,-2231,-2229,-2209,-2171,-2127,-2090,-2071,-2072,
+-2083,-2094,-2094,-2082,-2067,-2057,-2059,-2071,-2087,-2099,-2104,-2102,-2099,-2100,-2106,-2118,-2134,-2152,-2170,-2188,-2203,
+-2216,-2226,-2237,-2254,-2281,-2319,-2366,-2418,-2474,-2531,-2589,-2647,-2700,-2744,-2775,-2795,-2809,-2822,-2837,-2855,-2871,
+-2882,-2888,-2891,-2895,-2903,-2914,-2922,-2924,-2920,-2916,-2917,-2928,-2946,-2967,-2983,-2992,-2993,-2992,-2992,-2995,-3000,
+-3003,-3003,-2999,-2993,-2987,-2983,-2982,-2983,-2985,-2988,-2992,-2995,-2997,-2996,-2991,-2983,-2974,-2966,-2960,-2955,-2950,
+-2945,-2938,-2931,-2925,-2920,-2914,-2906,-2896,-2884,-2869,-2856,-2845,-2837,-2831,-2826,-2821,-2813,-2803,-2790,-2778,-2767,
+-2758,-2751,-2745,-2738,-2730,-2721,-2712,-2703,-2696,-2689,-2681,-2672,-2663,-2653,-2643,-2633,-2623,-2612,-2602,-2591,-2582,
+-2574,-2567,-2558,-2546,-2533,-2518,-2504,-2491,-2480,-2469,-2457,-2445,-2431,-2418,-2406,-2396,-2386,-2376,-2366,-2357,-2348,
+-2340,-2331,-2320,-2307,-2294,-2280,-2269,-2263,-2261,-2263,-2269,-2277,-2286,-2295,-2301,-2304,-2305,-2302,-2298,-2291,-2281,
+-2268,-2250,-2228,-2205,-2182,-2163,-2149,-2138,-2130,-2122,-2113,-2103,-2093,-2083,-2074,-2066,-2058,-2051,-2044,-2039,-2033,
+-2027,-2019,-2011,-2002,-1993,-1984,-1976,-1968,-1959,-1950,-1941,-1931,-1921,-1912,-1904,-1898,-1893,-1889,-1885,-1878,-1868,
+-1852,-1834,-1815,-1799,-1788,-1783,-1782,-1782,-1782,-1782,-1781,-1782,-1785,-1789,-1792,-1794,-1793,-1791,-1791,-1795,-1804,
+-1817,-1834,-1852,-1872,-1893,-1917,-1941,-1962,-1977,-1981,-1975,-1960,-1939,-1918,-1899,-1885,-1873,-1863,-1852,-1838,-1820,
+-1799,-1774,-1747,-1719,-1692,-1667,-1645,-1626,-1610,-1595,-1582,-1569,-1555,-1540,-1524,-1507,-1490,-1474,-1460,-1447,-1435,
+-1423,-1410,-1395,-1380,-1365,-1351,-1339,-1327,-1316,-1305,-1293,-1283,-1273,-1263,-1252,-1239,-1226,-1212,-1199,-1188,-1178,
+-1169,-1161,-1154,-1149,-1146,-1144,-1142,-1140,-1138,-1136,-1136,-1139,-1144,-1151,-1156,-1159,-1159,-1158,-1157,-1157,-1158,
+-1161,-1165,-1169,-1173,-1177,-1180,-1182,-1183,-1183,-1183,-1184,-1186,-1190,-1195,-1200,-1203,-1204,-1204,-1203,-1202,-1202,
+-1203,-1204,-1207,-1210,-1214,-1218,-1222,-1224,-1225,-1225,-1223,-1222,-1220,-1218,-1214,-1209,-1202,-1195,-1190,-1187,-1187,
+-1187,-1187,-1183,-1177,-1169,-1161,-1154,-1147,-1138,-1126,-1110,-1093,-1077,-1063,-1051,-1039,-1025,-1008,-988,-969,-954,
+-944,-939,-934,-928,-918,-905,-892,-880,-870,-863,-857,-852,-849,-847,-847,-848,-851,-854,-857,-860,-861,
+-859,-853,-843,-829,-812,-792,-771,-748,-724,-701,-679,-659,-642,-626,-610,-595,-581,-569,-561,-554,-545,
+-532,-515,-494,-474,-456,-442,-429,-415,-398,-379,-360,-343,-329,-316,-300,-279,-253,-223,-193,-163,-134,
+-104,-72,-37,-2,31,61,90,119,148,178,206,231,253,274,297,323,350,378,403,427,449,
+469,486,497,499,491,476,460,446,437,433,436,454,495,567,671,795,918,1016,1071,1082,1063,
+1036,1019,1017,1025,1027,1012,977,930,886,860,858,882,924,978,1037,1096,1151,1199,1234,1256,1265,
+1265,1264,1266,1274,1285,1298,1308,1311,1306,1294,1276,1255,1233,1210,1186,1160,1133,1105,1079,1057,1042,
+1032,1022,1010,992,969,943,918,893,869,843,815,789,770,762,765,775,782,779,762,733,700,
+668,642,619,596,568,535,499,467,445,436,442,461,490,529,578,640,713,795,876,946,996,
+1021,1027,1021,1015,1014,1019,1021,1012,986,947,908,883,886,924,992,1081,1180,1280,1372,1449,1499,
+1515,1491,1430,1344,1251,1170,1110,1073,1053,1042,1034,1029,1034,1054,1092,1144,1203,1255,1290,1296,1268,
+1206,1116,1010,904,813,749,716,711,727,756,792,832,877,929,986,1046,1105,1157,1198,1225,1235,
+1230,1213,1190,1170,1159,1164,1188,1230,1284,1344,1401,1448,1481,1498,1500,1495,1489,1490,1499,1515,1533,
+1547,1554,1554,1548,1542,1536,1530,1525,1518,1511,1506,1504,1507,1515,1525,1535,1544,1550,1556,1565,1578,
+1600,1631,1669,1711,1754,1795,1835,1876,1920,1964,2003,2033,2049,2052,2046,2039,2037,2041,2047,2053,2056,
+2059,2065,2078,2097,2118,2135,2144,2149,2154,2163,2177,2194,2209,2221,2230,2239,2249,2260,2269,2273,2273,
+2272,2276,2288,2306,2328,2346,2360,2370,2380,2391,2406,2420,2432,2441,2450,2462,2480,2502,2524,2544,2559,
+2568,2575,2581,2585,2589,2591,2592,2596,2603,2613,2627,2640,2652,2663,2672,2682,2691,2700,2710,2720,2731,
+2744,2758,2771,2781,2787,2790,2791,2790,2787,2781,2772,2762,2754,2749,2748,2747,2746,2742,2736,2733,2729,
+2734,2743,2753,2757,2751,2735,2712,2688,2669,2659,2658,2666,2681,2699,2718,2733,2742,2748,2752,2756,2761,
+2763,2758,2743,2720,2696,2681,2680,2690,2701,2703,2688,2660,2631,2615,2619,2641,2671,2696,2710,2715,2718,
+2727,2745,2770,2794,2814,2828,2837,2844,2850,2851,2848,2841,2834,2835,2846,2868,2895,2922,2944,2964,2983,
+3006,3034,3066,3099,3131,3159,3185,3209,3231,3251,3269,3285,3302,3322,3347,3374,3402,3428,3452,3475,3502,
+3531,3561,3588,3607,3619,3627,3638,3653,3672,3688,3691,3678,3650,3620,3602,3607,3637,3678,3711,3719,3692,
+3636,3568,3510,3480,3485,3519,3569,3617,3652,3666,3662,3645,3625,3608,3599,3599,3606,3619,3633,3649,3666,
+3684,3705,3729,3756,3785,3817,3850,3883,3913,3940,3964,3987,4011,4039,4069,4101,4132,4161,4189,4219,4253,
+4290,4329,4366,4400,4431,4462,4495,4531,4568,4603,4635,4666,4696,4725,4752,4771,4779,4776,4768,4759,4753,
+4746,4734,4710,4675,4639,4612,4603,4610,4627,4639,4639,4626,4605,4584,4565,4546,4525,4501,4482,4480,4501,
+4542,4588,4618,4614,4573,4503,4424,4353,4303,4275,4264,4265,4275,4295,4326,4362,4397,4419,4421,4401,4364,
+4319,4275,4236,4204,4177,4153,4129,4107,4088,4074,4067,4064,4064,4063,4055,4040,4017,3987,3953,3916,3880,
+3847,3819,3799,3786,3781,3780,3780,3780,3777,3771,3760,3744,3722,3697,3671,3649,3634,3623,3612,3597,3572,
+3540,3507,3480,3463,3458,3457,3457,3455,3451,3451,3458,3472,3488,3501,3506,3506,3502,3500,3500,3502,3501,
+3496,3488,3479,3472,3467,3463,3460,3456,3455,3460,3473,3494,3518,3542,3562,3575,3582,3583,3580,3573,3565,
+3558,3555,3557,3561,3564,3561,3550,3530,3503,3471,3432,3386,3334,3276,3221,3170,3124,3075,3012,2927,2823,
+2714,2618,2553,2522,2517,2517,2506,2476,2436,2401,2384,2385,2391,2385,2351,2289,2214,2145,2097,2073,2067,
+2061,2045,2014,1973,1931,1894,1863,1834,1803,1767,1729,1693,1662,1636,1613,1588,1558,1524,1488,1454,1423,
+1393,1363,1330,1293,1255,1217,1182,1150,1122,1093,1063,1030,995,960,927,896,867,838,808,776,743,
+711,681,651,622,591,558,523,490,460,431,402,371,336,298,256,215,175,136,99,64,32,
+3,-21,-44,-68,-95,-125,-160,-195,-230,-263,-294,-325,-356,-387,-418,-448,-478,-509,-543,-578,-612,
+-645,-675,-704,-733,-763,-796,-830,-864,-895,-926,-957,-990,-1025,-1059,-1090,-1117,-1141,-1164,-1190,-1219,-1253,
+-1289,-1324,-1358,-1390,-1422,-1454,-1486,-1518,-1548,-1576,-1604,-1632,-1662,-1693,-1725,-1755,-1782,-1805,-1825,-1843,-1861,
+-1880,-1901,-1921,-1940,-1955,-1967,-1978,-1992,-2009,-2031,-2057,-2081,-2102,-2118,-2131,-2142,-2155,-2169,-2184,-2196,-2206,
+-2215,-2224,-2235,-2250,-2265,-2281,-2295,-2307,-2320,-2334,-2350,-2364,-2376,-2386,-2394,-2403,-2414,-2427,-2439,-2447,-2449,
+-2445,-2438,-2430,-2422,-2415,-2409,-2404,-2401,-2399,-2398,-2396,-2393,-2387,-2378,-2368,-2359,-2353,-2350,-2348,-2347,-2345,
+-2342,-2338,-2334,-2329,-2324,-2321,-2318,-2318,-2317,-2316,-2314,-2311,-2308,-2306,-2304,-2302,-2297,-2289,-2280,-2271,-2264,
+-2259,-2253,-2243,-2229,-2212,-2198,-2191,-2189,-2190,-2188,-2179,-2162,-2141,-2119,-2101,-2086,-2071,-2055,-2039,-2026,-2016,
+-2009,-2004,-1997,-1985,-1971,-1958,-1950,-1948,-1950,-1953,-1951,-1944,-1932,-1919,-1911,-1911,-1925,-1951,-1987,-2028,-2066,
+-2092,-2104,-2102,-2091,-2077,-2065,-2055,-2045,-2037,-2031,-2032,-2042,-2062,-2085,-2104,-2112,-2108,-2097,-2085,-2079,-2076,
+-2077,-2077,-2077,-2079,-2086,-2095,-2102,-2104,-2101,-2101,-2109,-2131,-2159,-2183,-2189,-2176,-2152,-2135,-2140,-2165,-2196,
+-2205,-2177,-2112,-2031,-1970,-1953,-1987,-2055,-2125,-2170,-2179,-2158,-2127,-2105,-2102,-2115,-2136,-2156,-2172,-2187,-2204,
+-2226,-2252,-2275,-2290,-2292,-2280,-2255,-2223,-2192,-2168,-2157,-2158,-2166,-2173,-2173,-2164,-2150,-2136,-2131,-2135,-2148,
+-2165,-2181,-2194,-2206,-2218,-2230,-2244,-2256,-2267,-2277,-2289,-2304,-2322,-2342,-2364,-2389,-2419,-2456,-2500,-2549,-2602,
+-2656,-2708,-2757,-2800,-2835,-2860,-2875,-2883,-2891,-2902,-2920,-2942,-2961,-2974,-2979,-2979,-2980,-2984,-2991,-2997,-3000,
+-2998,-2995,-2997,-3006,-3022,-3041,-3058,-3068,-3071,-3071,-3071,-3073,-3076,-3078,-3078,-3074,-3068,-3063,-3060,-3059,-3059,
+-3060,-3061,-3063,-3064,-3065,-3064,-3060,-3053,-3043,-3033,-3025,-3018,-3012,-3008,-3003,-2998,-2994,-2989,-2983,-2976,-2966,
+-2954,-2939,-2923,-2909,-2898,-2891,-2887,-2884,-2878,-2870,-2859,-2847,-2837,-2828,-2822,-2815,-2808,-2797,-2786,-2774,-2764,
+-2756,-2750,-2744,-2736,-2727,-2717,-2706,-2694,-2682,-2669,-2657,-2645,-2634,-2625,-2617,-2608,-2596,-2582,-2566,-2550,-2536,
+-2525,-2514,-2504,-2492,-2481,-2469,-2459,-2449,-2440,-2430,-2419,-2407,-2394,-2381,-2369,-2357,-2347,-2337,-2328,-2318,-2309,
+-2300,-2292,-2285,-2281,-2282,-2286,-2293,-2302,-2312,-2321,-2328,-2332,-2332,-2324,-2309,-2287,-2262,-2238,-2218,-2202,-2189,
+-2178,-2165,-2150,-2135,-2122,-2110,-2101,-2094,-2086,-2078,-2068,-2059,-2050,-2042,-2035,-2028,-2021,-2013,-2006,-1998,-1991,
+-1984,-1976,-1967,-1957,-1945,-1933,-1921,-1912,-1906,-1903,-1901,-1898,-1890,-1876,-1857,-1835,-1814,-1798,-1789,-1785,-1786,
+-1787,-1789,-1789,-1789,-1790,-1790,-1789,-1785,-1778,-1769,-1760,-1753,-1748,-1745,-1745,-1747,-1754,-1769,-1793,-1825,-1862,
+-1896,-1923,-1937,-1938,-1930,-1916,-1901,-1888,-1876,-1867,-1857,-1846,-1833,-1816,-1796,-1773,-1750,-1727,-1705,-1684,-1663,
+-1642,-1621,-1600,-1580,-1560,-1541,-1523,-1506,-1490,-1476,-1465,-1455,-1446,-1435,-1423,-1408,-1393,-1379,-1367,-1358,-1349,
+-1340,-1329,-1317,-1305,-1293,-1281,-1269,-1257,-1243,-1229,-1216,-1205,-1196,-1187,-1180,-1173,-1167,-1161,-1157,-1154,-1152,
+-1149,-1148,-1148,-1151,-1156,-1163,-1170,-1176,-1178,-1179,-1179,-1179,-1181,-1184,-1188,-1193,-1198,-1203,-1207,-1209,-1209,
+-1207,-1204,-1202,-1200,-1202,-1205,-1211,-1216,-1221,-1223,-1223,-1223,-1221,-1221,-1222,-1225,-1229,-1233,-1237,-1240,-1241,
+-1241,-1240,-1239,-1239,-1238,-1236,-1232,-1225,-1215,-1204,-1196,-1191,-1189,-1190,-1191,-1190,-1187,-1182,-1177,-1172,-1166,
+-1160,-1151,-1139,-1126,-1112,-1098,-1083,-1066,-1047,-1026,-1005,-987,-973,-963,-954,-943,-930,-915,-900,-887,-879,
+-875,-873,-872,-871,-870,-869,-870,-874,-879,-886,-891,-893,-891,-884,-873,-857,-839,-820,-798,-775,-750,
+-723,-698,-675,-656,-639,-623,-607,-591,-575,-561,-551,-543,-535,-525,-511,-494,-478,-464,-452,-440,-426,
+-409,-389,-371,-356,-344,-334,-321,-302,-276,-245,-213,-181,-149,-119,-88,-56,-25,5,36,67,100,
+132,163,189,211,231,252,277,304,332,360,385,409,434,460,483,498,500,491,474,457,443,
+433,421,406,393,397,436,522,651,805,951,1060,1116,1121,1095,1060,1034,1022,1015,1003,978,942,
+905,878,872,890,929,982,1042,1100,1153,1195,1224,1242,1251,1253,1254,1256,1261,1267,1272,1275,1272,
+1262,1245,1222,1194,1164,1134,1103,1071,1039,1008,981,962,954,955,963,971,973,969,956,938,914,
+887,856,825,798,781,778,787,802,813,812,795,765,728,693,662,635,607,576,542,510,488,
+482,497,529,576,631,692,759,834,918,1009,1097,1170,1216,1230,1214,1180,1144,1118,1106,1105,1103,
+1091,1069,1041,1020,1016,1036,1078,1136,1203,1274,1343,1404,1452,1479,1480,1455,1413,1365,1324,1296,1281,
+1274,1269,1262,1256,1254,1265,1293,1337,1395,1457,1513,1551,1560,1533,1474,1392,1306,1234,1189,1177,1192,
+1226,1269,1312,1353,1391,1424,1452,1474,1490,1501,1507,1507,1495,1464,1411,1340,1261,1192,1147,1138,1163,
+1214,1279,1343,1396,1435,1457,1465,1464,1457,1450,1448,1451,1460,1471,1483,1491,1495,1494,1491,1486,1479,
+1468,1456,1442,1431,1426,1427,1434,1445,1457,1471,1487,1509,1538,1576,1619,1664,1708,1750,1793,1839,1892,
+1950,2005,2050,2076,2083,2075,2062,2054,2054,2062,2072,2079,2081,2080,2081,2087,2097,2109,2120,2126,2132,
+2139,2150,2163,2178,2189,2198,2206,2216,2228,2242,2252,2257,2257,2258,2264,2277,2295,2313,2327,2336,2343,
+2351,2363,2378,2394,2406,2415,2424,2437,2455,2478,2502,2524,2541,2553,2560,2565,2567,2566,2564,2564,2568,
+2577,2590,2606,2621,2635,2648,2661,2675,2688,2699,2706,2709,2712,2716,2725,2738,2752,2766,2777,2783,2786,
+2785,2782,2776,2770,2765,2761,2757,2752,2745,2737,2730,2729,2723,2723,2726,2727,2723,2712,2696,2680,2671,
+2672,2684,2703,2724,2744,2759,2768,2770,2768,2763,2757,2754,2754,2753,2749,2738,2719,2695,2673,2655,2644,
+2634,2623,2607,2590,2578,2579,2594,2618,2642,2659,2665,2665,2668,2680,2702,2729,2753,2768,2772,2768,2763,
+2759,2759,2763,2770,2781,2797,2817,2839,2860,2875,2887,2900,2919,2946,2980,3017,3050,3075,3095,3111,3129,
+3149,3171,3193,3214,3233,3253,3277,3304,3333,3361,3388,3413,3437,3460,3483,3501,3516,3529,3543,3562,3587,
+3613,3632,3635,3620,3594,3571,3564,3581,3614,3649,3666,3651,3603,3538,3476,3436,3430,3455,3499,3546,3583,
+3603,3608,3600,3586,3572,3561,3556,3560,3572,3590,3612,3634,3655,3674,3693,3716,3743,3774,3808,3842,3872,
+3897,3920,3942,3965,3989,4016,4045,4073,4101,4129,4159,4191,4224,4258,4292,4325,4359,4395,4432,4470,4506,
+4538,4566,4592,4620,4651,4684,4714,4734,4741,4736,4725,4714,4708,4704,4697,4680,4654,4623,4595,4574,4562,
+4554,4546,4536,4525,4518,4515,4513,4506,4489,4464,4440,4428,4433,4452,4473,4480,4465,4427,4378,4332,4299,
+4285,4285,4296,4315,4341,4377,4419,4460,4488,4493,4471,4425,4367,4308,4258,4219,4189,4164,4140,4114,4089,
+4068,4053,4045,4042,4039,4032,4017,3995,3967,3935,3903,3874,3848,3827,3810,3799,3793,3790,3788,3784,3779,
+3771,3759,3746,3729,3709,3685,3660,3637,3619,3606,3595,3583,3565,3542,3515,3490,3471,3460,3454,3451,3448,
+3446,3449,3456,3469,3483,3495,3502,3504,3505,3506,3508,3510,3507,3500,3489,3479,3471,3469,3468,3469,3468,
+3467,3470,3478,3491,3507,3520,3528,3528,3521,3511,3500,3492,3489,3491,3499,3511,3524,3532,3531,3519,3498,
+3471,3439,3403,3362,3312,3257,3201,3149,3103,3059,3006,2933,2837,2727,2619,2532,2474,2443,2423,2400,2367,
+2330,2304,2301,2322,2351,2366,2347,2290,2208,2124,2062,2030,2024,2028,2023,2000,1961,1917,1876,1843,1818,
+1793,1763,1728,1690,1656,1627,1602,1578,1550,1518,1483,1447,1414,1383,1354,1322,1287,1249,1211,1174,1142,
+1112,1083,1053,1021,987,953,921,891,861,831,799,767,735,705,677,650,622,592,560,528,497,
+469,440,408,371,328,283,239,198,161,127,94,62,32,6,-15,-34,-54,-80,-112,-149,-189,
+-227,-261,-292,-322,-353,-386,-419,-452,-483,-514,-545,-576,-608,-639,-669,-696,-725,-755,-789,-823,-858,
+-890,-921,-951,-984,-1018,-1053,-1085,-1113,-1138,-1161,-1186,-1216,-1249,-1285,-1321,-1355,-1387,-1418,-1450,-1482,-1513,
+-1543,-1572,-1600,-1629,-1658,-1689,-1720,-1748,-1773,-1795,-1815,-1835,-1857,-1879,-1901,-1922,-1939,-1953,-1965,-1977,-1991,
+-2008,-2028,-2049,-2069,-2088,-2106,-2123,-2139,-2156,-2172,-2185,-2195,-2203,-2210,-2220,-2234,-2250,-2267,-2283,-2297,-2310,
+-2324,-2338,-2354,-2370,-2384,-2395,-2405,-2415,-2427,-2439,-2450,-2458,-2461,-2458,-2453,-2446,-2438,-2432,-2425,-2420,-2417,
+-2415,-2414,-2413,-2411,-2406,-2398,-2388,-2379,-2371,-2366,-2365,-2365,-2366,-2368,-2367,-2365,-2360,-2353,-2347,-2343,-2341,
+-2341,-2341,-2339,-2337,-2334,-2332,-2331,-2330,-2327,-2321,-2314,-2306,-2299,-2293,-2286,-2277,-2264,-2249,-2236,-2226,-2221,
+-2219,-2215,-2207,-2193,-2174,-2154,-2135,-2117,-2100,-2083,-2067,-2053,-2042,-2032,-2022,-2012,-2000,-1989,-1981,-1976,-1976,
+-1978,-1979,-1976,-1968,-1955,-1941,-1929,-1924,-1931,-1953,-1988,-2031,-2073,-2107,-2126,-2130,-2124,-2113,-2100,-2087,-2073,
+-2060,-2051,-2051,-2063,-2086,-2114,-2137,-2149,-2147,-2135,-2119,-2105,-2096,-2092,-2092,-2097,-2108,-2122,-2136,-2145,-2146,
+-2143,-2142,-2153,-2178,-2209,-2232,-2236,-2220,-2195,-2181,-2190,-2217,-2240,-2235,-2184,-2097,-2004,-1945,-1948,-2012,-2113,
+-2209,-2269,-2282,-2260,-2230,-2213,-2220,-2241,-2263,-2275,-2277,-2279,-2292,-2319,-2354,-2383,-2391,-2373,-2333,-2282,-2236,
+-2206,-2197,-2204,-2219,-2232,-2237,-2233,-2222,-2211,-2205,-2207,-2217,-2231,-2247,-2263,-2279,-2297,-2317,-2338,-2357,-2373,
+-2387,-2401,-2419,-2443,-2475,-2512,-2552,-2593,-2634,-2677,-2721,-2764,-2807,-2846,-2882,-2914,-2940,-2959,-2970,-2974,-2975,
+-2977,-2986,-3002,-3023,-3043,-3056,-3060,-3059,-3055,-3055,-3060,-3067,-3074,-3079,-3081,-3084,-3090,-3101,-3115,-3129,-3141,
+-3148,-3153,-3155,-3156,-3157,-3156,-3154,-3150,-3146,-3142,-3140,-3139,-3139,-3139,-3139,-3139,-3138,-3137,-3134,-3129,-3122,
+-3112,-3101,-3091,-3083,-3078,-3074,-3071,-3067,-3063,-3057,-3049,-3041,-3030,-3017,-3002,-2985,-2969,-2957,-2949,-2944,-2942,
+-2938,-2931,-2921,-2910,-2901,-2894,-2890,-2885,-2878,-2867,-2852,-2838,-2825,-2816,-2809,-2803,-2797,-2788,-2778,-2767,-2756,
+-2744,-2731,-2717,-2702,-2688,-2675,-2663,-2651,-2637,-2622,-2607,-2592,-2579,-2568,-2558,-2548,-2537,-2526,-2515,-2505,-2496,
+-2488,-2479,-2470,-2458,-2444,-2429,-2414,-2400,-2387,-2377,-2368,-2360,-2351,-2340,-2328,-2316,-2306,-2299,-2297,-2298,-2302,
+-2308,-2315,-2322,-2328,-2331,-2331,-2325,-2314,-2301,-2287,-2274,-2262,-2250,-2236,-2218,-2198,-2178,-2161,-2149,-2141,-2134,
+-2125,-2114,-2101,-2088,-2076,-2066,-2059,-2052,-2044,-2035,-2024,-2014,-2004,-1996,-1989,-1982,-1975,-1967,-1959,-1950,-1940,
+-1932,-1925,-1919,-1913,-1904,-1892,-1875,-1856,-1837,-1821,-1811,-1807,-1807,-1808,-1808,-1806,-1802,-1797,-1792,-1787,-1782,
+-1776,-1770,-1764,-1757,-1749,-1739,-1727,-1715,-1707,-1708,-1720,-1744,-1776,-1812,-1843,-1866,-1879,-1881,-1877,-1869,-1860,
+-1852,-1844,-1836,-1827,-1816,-1805,-1793,-1781,-1769,-1758,-1746,-1731,-1712,-1689,-1662,-1634,-1605,-1579,-1556,-1535,-1517,
+-1501,-1487,-1475,-1465,-1456,-1445,-1433,-1419,-1405,-1393,-1383,-1375,-1367,-1357,-1344,-1330,-1315,-1300,-1287,-1275,-1262,
+-1250,-1238,-1228,-1219,-1213,-1209,-1204,-1198,-1191,-1184,-1178,-1173,-1169,-1166,-1165,-1165,-1168,-1173,-1180,-1187,-1193,
+-1197,-1199,-1200,-1200,-1202,-1206,-1210,-1215,-1220,-1224,-1228,-1230,-1231,-1229,-1226,-1222,-1219,-1219,-1221,-1225,-1231,
+-1237,-1241,-1242,-1241,-1239,-1237,-1237,-1239,-1242,-1246,-1251,-1254,-1255,-1256,-1256,-1256,-1257,-1257,-1255,-1249,-1241,
+-1229,-1215,-1204,-1196,-1192,-1191,-1192,-1192,-1191,-1189,-1186,-1184,-1181,-1178,-1173,-1165,-1154,-1141,-1124,-1105,-1085,
+-1065,-1046,-1030,-1016,-1004,-992,-977,-959,-940,-920,-904,-893,-887,-884,-884,-884,-885,-887,-891,-898,-905,
+-913,-919,-921,-920,-914,-904,-891,-873,-853,-832,-807,-781,-754,-726,-699,-676,-657,-641,-625,-609,-591,
+-573,-557,-544,-534,-526,-518,-508,-496,-484,-472,-461,-448,-434,-418,-401,-385,-373,-362,-351,-336,-315,
+-289,-260,-228,-196,-165,-134,-105,-76,-49,-22,6,38,74,110,142,168,189,208,229,256,287,
+318,345,367,389,414,444,474,497,505,498,480,460,444,433,420,399,373,355,367,429,547,
+708,880,1029,1127,1166,1156,1121,1083,1053,1032,1013,989,958,926,904,903,926,969,1025,1082,1131,
+1167,1190,1204,1212,1219,1225,1230,1233,1231,1226,1217,1205,1191,1174,1153,1127,1098,1069,1042,1018,997,
+978,960,945,938,943,961,991,1026,1059,1082,1094,1093,1083,1065,1044,1022,1005,996,998,1010,1027,
+1040,1042,1031,1006,973,937,901,865,828,788,747,711,686,678,689,719,763,816,877,943,1017,
+1096,1178,1255,1314,1345,1343,1312,1264,1214,1176,1156,1150,1149,1145,1131,1112,1095,1090,1099,1125,1162,
+1205,1249,1294,1336,1372,1398,1411,1411,1400,1387,1375,1368,1365,1363,1359,1353,1348,1348,1356,1375,1406,
+1447,1496,1547,1593,1623,1632,1617,1585,1548,1520,1513,1530,1567,1616,1670,1721,1767,1806,1833,1848,1850,
+1844,1836,1828,1817,1795,1746,1662,1545,1410,1281,1183,1131,1125,1154,1199,1245,1281,1305,1320,1328,1331,
+1328,1323,1318,1318,1327,1344,1366,1386,1401,1405,1401,1391,1376,1359,1343,1327,1316,1310,1312,1321,1335,
+1353,1373,1399,1432,1475,1528,1587,1646,1702,1754,1804,1858,1916,1977,2032,2073,2094,2094,2081,2066,2057,
+2060,2071,2085,2097,2103,2104,2103,2103,2103,2104,2105,2108,2113,2123,2136,2151,2163,2172,2178,2184,2195,
+2208,2223,2235,2244,2249,2255,2265,2279,2294,2306,2314,2318,2322,2329,2342,2357,2371,2382,2391,2401,2414,
+2434,2456,2479,2500,2516,2528,2538,2544,2548,2548,2547,2548,2552,2562,2577,2593,2608,2622,2637,2654,2672,
+2690,2703,2708,2708,2705,2704,2710,2722,2737,2751,2761,2767,2769,2769,2769,2769,2770,2770,2769,2765,2758,
+2749,2738,2729,2723,2738,2728,2716,2700,2682,2663,2649,2644,2654,2677,2709,2744,2773,2792,2800,2796,2784,
+2766,2744,2723,2707,2699,2698,2701,2703,2698,2684,2661,2632,2603,2576,2556,2542,2537,2542,2557,2577,2599,
+2615,2621,2620,2617,2618,2628,2645,2664,2678,2682,2677,2669,2662,2663,2673,2689,2708,2730,2752,2773,2792,
+2807,2818,2829,2844,2866,2896,2930,2965,2993,3013,3027,3041,3058,3082,3110,3139,3165,3187,3209,3231,3257,
+3284,3311,3335,3355,3371,3384,3396,3409,3421,3436,3455,3478,3504,3527,3541,3543,3534,3522,3519,3531,3558,
+3589,3609,3602,3565,3506,3443,3397,3381,3396,3433,3475,3510,3531,3538,3537,3532,3527,3523,3521,3522,3530,
+3545,3567,3594,3620,3643,3662,3681,3704,3732,3764,3798,3830,3856,3878,3897,3918,3942,3968,3995,4022,4047,
+4071,4097,4125,4155,4187,4220,4252,4285,4320,4358,4398,4436,4469,4496,4519,4542,4569,4601,4636,4667,4687,
+4693,4689,4680,4671,4667,4664,4659,4647,4628,4606,4584,4565,4549,4535,4521,4509,4502,4503,4508,4512,4508,
+4491,4463,4432,4409,4396,4391,4384,4368,4339,4303,4269,4249,4247,4262,4289,4322,4359,4400,4443,4484,4514,
+4523,4505,4460,4397,4330,4269,4221,4187,4162,4139,4116,4091,4068,4048,4033,4024,4017,4009,3996,3977,3951,
+3922,3893,3866,3844,3827,3814,3805,3799,3794,3789,3784,3776,3765,3751,3736,3721,3706,3690,3671,3650,3628,
+3607,3590,3575,3563,3549,3532,3513,3493,3475,3461,3450,3442,3436,3433,3433,3439,3450,3462,3474,3484,3492,
+3499,3505,3510,3512,3507,3498,3485,3474,3468,3468,3472,3477,3482,3485,3488,3494,3501,3506,3508,3503,3494,
+3483,3474,3469,3469,3472,3479,3486,3495,3501,3501,3494,3478,3454,3426,3398,3367,3332,3288,3235,3175,3115,
+3061,3012,2962,2900,2821,2727,2631,2548,2488,2450,2423,2393,2352,2304,2262,2240,2243,2260,2272,2257,2208,
+2134,2056,1997,1971,1975,1991,2000,1988,1955,1909,1863,1828,1802,1781,1757,1725,1689,1652,1618,1590,1566,
+1540,1510,1476,1440,1404,1371,1339,1307,1274,1238,1202,1168,1136,1105,1075,1043,1010,976,943,912,883,
+854,825,794,762,732,704,677,651,623,594,564,534,506,478,447,409,364,315,266,223,187,
+158,131,103,74,44,18,-3,-21,-39,-64,-97,-136,-179,-219,-255,-288,-319,-352,-387,-422,-456,
+-487,-516,-544,-573,-603,-633,-662,-691,-720,-751,-784,-819,-853,-885,-915,-945,-976,-1009,-1045,-1079,-1110,
+-1137,-1163,-1189,-1218,-1250,-1284,-1319,-1352,-1385,-1416,-1447,-1478,-1508,-1538,-1566,-1595,-1625,-1657,-1688,-1718,-1744,
+-1767,-1787,-1807,-1829,-1852,-1877,-1900,-1920,-1936,-1950,-1963,-1977,-1993,-2011,-2030,-2048,-2065,-2081,-2097,-2114,-2132,
+-2150,-2166,-2178,-2188,-2196,-2206,-2218,-2234,-2252,-2270,-2287,-2301,-2314,-2327,-2342,-2358,-2375,-2390,-2403,-2414,-2424,
+-2434,-2444,-2453,-2460,-2463,-2464,-2461,-2457,-2452,-2447,-2442,-2438,-2436,-2435,-2435,-2433,-2430,-2425,-2419,-2411,-2403,
+-2395,-2389,-2385,-2384,-2385,-2388,-2390,-2389,-2386,-2381,-2375,-2370,-2367,-2366,-2365,-2364,-2361,-2357,-2355,-2354,-2354,
+-2354,-2352,-2347,-2340,-2333,-2326,-2318,-2308,-2296,-2283,-2270,-2261,-2255,-2252,-2248,-2240,-2228,-2210,-2189,-2167,-2146,
+-2127,-2110,-2094,-2080,-2067,-2055,-2043,-2032,-2021,-2013,-2006,-2003,-2001,-1999,-1996,-1990,-1981,-1970,-1958,-1948,-1943,
+-1950,-1970,-2004,-2047,-2090,-2124,-2145,-2152,-2147,-2137,-2124,-2110,-2095,-2080,-2070,-2068,-2079,-2101,-2129,-2155,-2169,
+-2170,-2160,-2146,-2132,-2123,-2119,-2121,-2128,-2139,-2154,-2169,-2179,-2183,-2183,-2187,-2199,-2221,-2244,-2257,-2254,-2236,
+-2216,-2210,-2223,-2247,-2260,-2239,-2176,-2087,-2005,-1970,-2003,-2095,-2215,-2319,-2378,-2386,-2361,-2334,-2328,-2345,-2374,
+-2398,-2405,-2400,-2395,-2406,-2435,-2472,-2499,-2499,-2465,-2406,-2340,-2286,-2255,-2250,-2262,-2280,-2292,-2296,-2292,-2285,
+-2282,-2286,-2296,-2310,-2325,-2340,-2355,-2372,-2391,-2413,-2437,-2462,-2487,-2513,-2543,-2580,-2623,-2672,-2723,-2772,-2819,
+-2862,-2901,-2937,-2968,-2995,-3017,-3035,-3049,-3060,-3068,-3073,-3075,-3074,-3075,-3079,-3089,-3104,-3119,-3129,-3133,-3130,
+-3125,-3122,-3126,-3135,-3147,-3158,-3166,-3171,-3174,-3178,-3187,-3199,-3213,-3226,-3235,-3241,-3242,-3240,-3237,-3233,-3229,
+-3226,-3223,-3221,-3220,-3218,-3217,-3215,-3214,-3211,-3209,-3204,-3199,-3192,-3183,-3173,-3164,-3155,-3149,-3144,-3140,-3135,
+-3128,-3121,-3112,-3102,-3091,-3078,-3064,-3049,-3034,-3021,-3012,-3007,-3002,-2996,-2988,-2977,-2965,-2956,-2951,-2950,-2948,
+-2943,-2934,-2920,-2904,-2890,-2879,-2871,-2865,-2859,-2852,-2843,-2833,-2823,-2811,-2798,-2783,-2765,-2746,-2727,-2709,-2692,
+-2675,-2660,-2645,-2632,-2620,-2610,-2601,-2592,-2581,-2570,-2558,-2547,-2537,-2527,-2519,-2511,-2502,-2492,-2479,-2465,-2449,
+-2433,-2418,-2405,-2394,-2384,-2374,-2364,-2353,-2344,-2335,-2329,-2324,-2320,-2316,-2312,-2310,-2310,-2311,-2314,-2317,-2318,
+-2317,-2315,-2312,-2306,-2297,-2283,-2266,-2246,-2228,-2213,-2203,-2196,-2188,-2178,-2165,-2148,-2132,-2116,-2104,-2093,-2083,
+-2072,-2060,-2048,-2035,-2023,-2012,-2003,-1997,-1992,-1987,-1983,-1978,-1971,-1963,-1953,-1944,-1935,-1927,-1917,-1905,-1891,
+-1875,-1860,-1848,-1840,-1835,-1832,-1827,-1820,-1812,-1802,-1794,-1788,-1784,-1782,-1781,-1781,-1780,-1776,-1769,-1758,-1744,
+-1731,-1723,-1722,-1730,-1747,-1767,-1788,-1806,-1818,-1824,-1827,-1827,-1827,-1825,-1822,-1817,-1810,-1800,-1790,-1780,-1772,
+-1766,-1761,-1755,-1745,-1729,-1708,-1682,-1655,-1629,-1606,-1585,-1566,-1547,-1528,-1509,-1491,-1475,-1461,-1447,-1435,-1422,
+-1410,-1400,-1391,-1383,-1373,-1361,-1347,-1331,-1314,-1299,-1286,-1274,-1263,-1252,-1242,-1235,-1230,-1228,-1227,-1226,-1222,
+-1217,-1210,-1203,-1198,-1194,-1192,-1191,-1191,-1193,-1196,-1201,-1206,-1210,-1214,-1215,-1216,-1217,-1220,-1223,-1228,-1233,
+-1237,-1241,-1244,-1246,-1248,-1249,-1249,-1247,-1245,-1244,-1244,-1248,-1252,-1258,-1262,-1264,-1263,-1260,-1257,-1254,-1252,
+-1254,-1257,-1260,-1264,-1267,-1269,-1270,-1271,-1271,-1272,-1270,-1265,-1257,-1245,-1232,-1218,-1207,-1200,-1196,-1194,-1194,
+-1194,-1193,-1193,-1192,-1192,-1191,-1188,-1182,-1170,-1155,-1136,-1115,-1096,-1080,-1066,-1054,-1042,-1027,-1008,-986,-963,
+-942,-927,-917,-911,-907,-903,-898,-894,-894,-899,-910,-923,-936,-946,-951,-952,-949,-943,-934,-923,-906,
+-885,-859,-829,-796,-764,-733,-706,-683,-664,-646,-629,-611,-592,-572,-555,-541,-530,-521,-514,-506,-497,
+-488,-477,-465,-452,-438,-424,-412,-401,-391,-380,-366,-347,-324,-299,-272,-245,-216,-185,-154,-125,-98,
+-75,-53,-28,3,40,80,116,144,165,183,205,235,269,303,331,351,369,390,420,455,487,
+506,507,492,471,452,438,425,405,377,349,342,378,469,613,785,952,1084,1163,1191,1181,1152,
+1119,1085,1050,1012,973,941,928,941,981,1042,1108,1166,1203,1219,1217,1207,1200,1200,1207,1217,1222,
+1219,1207,1188,1168,1147,1125,1100,1071,1039,1011,989,978,977,980,985,990,999,1018,1051,1098,1155,
+1214,1265,1305,1330,1343,1347,1345,1339,1334,1330,1333,1341,1355,1371,1382,1385,1376,1356,1325,1287,1243,
+1194,1143,1092,1045,1003,972,954,949,959,982,1020,1070,1130,1197,1264,1323,1365,1382,1373,1342,1300,
+1259,1228,1212,1206,1205,1201,1192,1179,1171,1173,1188,1214,1248,1283,1316,1345,1369,1387,1400,1405,1404,
+1400,1395,1392,1390,1387,1382,1376,1370,1368,1372,1381,1394,1409,1427,1449,1476,1508,1540,1568,1587,1598,
+1604,1614,1634,1665,1709,1762,1822,1886,1949,2007,2052,2081,2094,2095,2093,2092,2089,2069,2016,1918,1778,
+1613,1452,1321,1234,1188,1168,1154,1135,1106,1077,1054,1044,1045,1052,1059,1066,1077,1097,1127,1162,1195,
+1218,1225,1218,1201,1181,1162,1148,1138,1135,1138,1150,1170,1196,1228,1264,1306,1355,1413,1479,1549,1619,
+1685,1746,1804,1862,1922,1981,2033,2070,2090,2092,2082,2070,2063,2064,2073,2086,2098,2107,2113,2115,2114,
+2111,2108,2105,2106,2112,2124,2138,2151,2161,2167,2172,2179,2190,2205,2220,2233,2243,2251,2261,2272,2285,
+2296,2302,2305,2306,2310,2318,2330,2343,2354,2362,2370,2381,2397,2417,2438,2457,2472,2485,2497,2509,2521,
+2532,2538,2542,2546,2553,2563,2576,2590,2602,2614,2627,2643,2664,2684,2699,2706,2706,2703,2701,2706,2715,
+2727,2736,2741,2742,2742,2743,2747,2753,2759,2764,2765,2765,2762,2758,2753,2746,2738,2766,2749,2723,2690,
+2657,2629,2613,2614,2632,2663,2700,2736,2764,2781,2786,2781,2767,2744,2716,2685,2658,2641,2637,2644,2657,
+2666,2663,2646,2618,2585,2554,2533,2523,2524,2534,2547,2561,2571,2576,2575,2570,2564,2562,2565,2572,2578,
+2581,2579,2575,2574,2579,2593,2613,2637,2659,2679,2697,2713,2730,2747,2765,2785,2807,2831,2858,2886,2911,
+2932,2950,2966,2984,3008,3037,3069,3101,3128,3152,3175,3197,3222,3248,3272,3290,3304,3312,3319,3328,3340,
+3355,3374,3394,3413,3430,3441,3446,3446,3445,3450,3465,3491,3520,3541,3541,3515,3466,3409,3361,3337,3343,
+3371,3409,3442,3463,3471,3471,3471,3475,3482,3490,3496,3503,3512,3528,3550,3576,3602,3625,3645,3664,3687,
+3716,3749,3783,3813,3837,3857,3875,3895,3919,3946,3974,3999,4022,4044,4067,4092,4121,4151,4183,4216,4250,
+4287,4325,4362,4396,4423,4445,4466,4489,4517,4551,4585,4612,4629,4634,4632,4627,4623,4623,4621,4615,4603,
+4585,4566,4549,4536,4525,4515,4505,4498,4497,4502,4510,4514,4510,4493,4467,4440,4415,4397,4380,4358,4328,
+4289,4250,4220,4206,4211,4230,4259,4293,4329,4368,4405,4436,4453,4447,4417,4368,4309,4251,4203,4167,4141,
+4119,4099,4078,4056,4036,4019,4006,3995,3985,3973,3957,3937,3913,3887,3864,3844,3829,3818,3810,3803,3796,
+3787,3777,3766,3754,3740,3724,3708,3694,3680,3668,3655,3639,3620,3599,3578,3559,3543,3529,3516,3503,3489,
+3476,3463,3450,3439,3429,3422,3419,3421,3428,3438,3450,3463,3475,3486,3496,3503,3506,3501,3491,3479,3469,
+3463,3464,3469,3477,3485,3492,3498,3503,3505,3502,3492,3478,3464,3454,3451,3456,3466,3475,3481,3481,3478,
+3471,3461,3447,3428,3404,3379,3354,3330,3302,3265,3216,3155,3088,3024,2966,2912,2856,2791,2715,2635,2564,
+2509,2473,2446,2415,2370,2311,2248,2197,2167,2157,2150,2132,2090,2029,1966,1919,1903,1916,1944,1966,1967,
+1942,1900,1854,1815,1786,1765,1744,1717,1683,1646,1611,1581,1555,1529,1502,1470,1434,1397,1361,1326,1292,
+1259,1226,1194,1162,1132,1102,1071,1038,1003,968,935,904,875,848,820,791,762,733,705,677,649,
+620,591,563,536,510,482,448,405,356,305,258,221,194,172,150,124,94,61,33,10,-8,
+-26,-51,-85,-126,-170,-212,-249,-282,-314,-348,-384,-421,-457,-488,-517,-543,-570,-599,-629,-659,-688,
+-718,-749,-782,-817,-851,-883,-913,-942,-972,-1003,-1037,-1070,-1102,-1132,-1159,-1186,-1214,-1245,-1278,-1312,-1345,
+-1379,-1412,-1443,-1474,-1502,-1530,-1558,-1587,-1619,-1652,-1686,-1716,-1742,-1763,-1782,-1802,-1824,-1848,-1873,-1895,-1914,
+-1929,-1943,-1958,-1975,-1994,-2014,-2033,-2050,-2066,-2080,-2094,-2110,-2126,-2141,-2156,-2169,-2182,-2194,-2207,-2223,-2240,
+-2257,-2275,-2290,-2304,-2318,-2331,-2346,-2361,-2378,-2394,-2409,-2421,-2432,-2441,-2449,-2456,-2462,-2466,-2469,-2469,-2466,
+-2462,-2458,-2455,-2454,-2454,-2455,-2455,-2453,-2449,-2444,-2440,-2435,-2430,-2424,-2418,-2412,-2407,-2404,-2405,-2406,-2407,
+-2406,-2403,-2398,-2395,-2393,-2393,-2393,-2391,-2388,-2384,-2381,-2380,-2381,-2381,-2381,-2378,-2373,-2366,-2358,-2350,-2340,
+-2328,-2315,-2303,-2293,-2288,-2285,-2283,-2277,-2266,-2249,-2228,-2204,-2180,-2159,-2141,-2125,-2111,-2099,-2087,-2076,-2066,
+-2057,-2050,-2044,-2038,-2031,-2023,-2014,-2005,-1997,-1988,-1980,-1974,-1973,-1980,-1998,-2028,-2066,-2105,-2137,-2157,-2163,
+-2160,-2151,-2140,-2127,-2114,-2100,-2089,-2086,-2094,-2112,-2136,-2158,-2172,-2178,-2175,-2169,-2165,-2163,-2163,-2166,-2170,
+-2176,-2184,-2194,-2203,-2212,-2220,-2230,-2243,-2257,-2268,-2269,-2259,-2243,-2231,-2232,-2245,-2260,-2256,-2220,-2152,-2076,
+-2025,-2029,-2099,-2216,-2345,-2444,-2491,-2488,-2458,-2433,-2432,-2456,-2490,-2515,-2523,-2518,-2513,-2523,-2549,-2581,-2601,
+-2596,-2560,-2503,-2441,-2391,-2361,-2352,-2355,-2362,-2366,-2366,-2363,-2362,-2365,-2374,-2387,-2403,-2420,-2438,-2457,-2478,
+-2501,-2526,-2554,-2586,-2624,-2667,-2717,-2773,-2832,-2889,-2942,-2987,-3025,-3057,-3085,-3110,-3131,-3147,-3156,-3161,-3163,
+-3164,-3167,-3170,-3173,-3173,-3172,-3172,-3174,-3180,-3189,-3197,-3202,-3202,-3198,-3196,-3198,-3207,-3221,-3236,-3247,-3252,
+-3252,-3252,-3256,-3267,-3282,-3299,-3313,-3321,-3323,-3320,-3316,-3312,-3309,-3308,-3306,-3304,-3301,-3298,-3295,-3293,-3290,
+-3286,-3281,-3275,-3268,-3261,-3253,-3245,-3237,-3228,-3220,-3212,-3205,-3198,-3191,-3183,-3174,-3164,-3154,-3142,-3130,-3116,
+-3103,-3091,-3080,-3072,-3064,-3055,-3043,-3030,-3017,-3008,-3003,-3002,-3003,-3002,-2996,-2986,-2972,-2959,-2947,-2938,-2931,
+-2924,-2917,-2908,-2898,-2888,-2877,-2864,-2849,-2830,-2808,-2785,-2762,-2740,-2721,-2703,-2687,-2673,-2661,-2651,-2642,-2633,
+-2624,-2614,-2603,-2590,-2577,-2565,-2554,-2545,-2538,-2531,-2522,-2510,-2495,-2477,-2459,-2442,-2428,-2417,-2407,-2398,-2390,
+-2381,-2373,-2365,-2358,-2350,-2341,-2331,-2322,-2315,-2312,-2312,-2315,-2318,-2321,-2323,-2323,-2320,-2314,-2304,-2293,-2281,
+-2270,-2262,-2256,-2252,-2245,-2236,-2223,-2208,-2191,-2174,-2158,-2142,-2127,-2113,-2100,-2088,-2077,-2065,-2054,-2042,-2031,
+-2021,-2014,-2009,-2004,-1998,-1991,-1982,-1972,-1964,-1958,-1952,-1945,-1934,-1920,-1905,-1889,-1876,-1865,-1855,-1846,-1836,
+-1825,-1814,-1805,-1799,-1797,-1796,-1797,-1798,-1799,-1799,-1797,-1792,-1785,-1777,-1769,-1764,-1762,-1764,-1769,-1776,-1782,
+-1787,-1792,-1797,-1804,-1811,-1817,-1820,-1819,-1814,-1804,-1791,-1777,-1764,-1754,-1745,-1736,-1725,-1710,-1693,-1673,-1654,
+-1637,-1622,-1609,-1594,-1577,-1555,-1531,-1507,-1484,-1465,-1450,-1437,-1427,-1418,-1409,-1399,-1388,-1376,-1361,-1346,-1330,
+-1315,-1302,-1291,-1280,-1270,-1259,-1250,-1242,-1238,-1237,-1237,-1237,-1236,-1232,-1228,-1223,-1220,-1219,-1219,-1220,-1222,
+-1223,-1226,-1228,-1231,-1234,-1236,-1236,-1237,-1238,-1240,-1243,-1247,-1251,-1255,-1259,-1262,-1266,-1270,-1274,-1276,-1277,
+-1276,-1274,-1272,-1273,-1276,-1280,-1285,-1289,-1290,-1288,-1284,-1280,-1277,-1275,-1276,-1278,-1281,-1284,-1285,-1286,-1287,
+-1287,-1287,-1287,-1284,-1278,-1269,-1257,-1243,-1231,-1220,-1213,-1208,-1205,-1203,-1201,-1200,-1200,-1200,-1199,-1196,-1188,
+-1176,-1160,-1142,-1124,-1109,-1098,-1088,-1077,-1060,-1036,-1006,-975,-950,-934,-930,-932,-937,-937,-930,-919,-910,
+-907,-914,-930,-950,-968,-981,-986,-985,-983,-980,-976,-969,-954,-931,-899,-861,-822,-784,-751,-724,-700,
+-680,-660,-639,-618,-597,-577,-559,-545,-533,-522,-514,-505,-498,-489,-480,-469,-457,-445,-434,-426,-417,
+-408,-395,-377,-355,-331,-307,-285,-263,-237,-207,-174,-142,-116,-97,-81,-62,-35,2,45,85,118,
+140,159,180,210,247,285,317,339,354,372,397,431,467,494,504,497,479,459,442,427,408,
+380,348,326,335,391,498,644,803,951,1065,1138,1172,1177,1161,1130,1090,1043,1000,970,967,996,
+1054,1129,1204,1262,1291,1291,1272,1246,1226,1220,1226,1237,1245,1245,1236,1221,1204,1186,1165,1139,1105,
+1069,1035,1013,1006,1015,1032,1053,1072,1092,1118,1157,1211,1276,1348,1416,1475,1522,1558,1583,1600,1608,
+1610,1607,1604,1606,1618,1639,1664,1688,1702,1700,1681,1644,1595,1539,1479,1420,1362,1305,1251,1201,1158,
+1128,1114,1121,1147,1189,1241,1294,1338,1368,1379,1373,1354,1330,1310,1296,1290,1288,1287,1283,1277,1273,
+1275,1288,1312,1342,1375,1403,1426,1442,1451,1453,1450,1443,1434,1425,1420,1418,1417,1416,1411,1405,1399,
+1399,1403,1412,1421,1427,1430,1433,1441,1459,1485,1517,1549,1577,1599,1617,1635,1656,1685,1726,1782,1852,
+1933,2016,2090,2148,2188,2214,2235,2254,2267,2262,2221,2135,2008,1857,1707,1578,1475,1391,1307,1210,1095,
+976,870,797,763,761,778,800,821,839,862,890,924,954,973,976,963,940,915,894,877,867,
+862,866,879,906,948,1003,1072,1149,1234,1323,1412,1499,1580,1653,1719,1781,1841,1902,1960,2012,2054,
+2080,2092,2093,2087,2081,2076,2075,2077,2082,2090,2098,2104,2109,2110,2111,2112,2116,2125,2137,2149,2158,
+2164,2168,2174,2184,2197,2213,2226,2237,2245,2253,2262,2272,2281,2287,2289,2289,2290,2295,2304,2316,2327,
+2335,2342,2350,2363,2381,2403,2423,2438,2449,2459,2471,2488,2506,2523,2535,2543,2549,2556,2566,2578,2589,
+2598,2606,2616,2630,2650,2670,2687,2697,2699,2698,2697,2699,2705,2712,2716,2718,2718,2721,2728,2737,2747,
+2753,2755,2756,2756,2760,2766,2772,2773,2766,2767,2746,2712,2671,2631,2601,2585,2584,2598,2620,2645,2668,
+2687,2700,2709,2714,2712,2703,2683,2657,2629,2607,2599,2605,2619,2633,2637,2629,2609,2584,2561,2545,2536,
+2533,2531,2528,2523,2517,2510,2505,2501,2498,2495,2493,2491,2490,2489,2491,2497,2509,2528,2552,2577,2599,
+2617,2630,2642,2656,2675,2700,2728,2757,2783,2805,2824,2841,2858,2876,2896,2919,2945,2975,3006,3036,3064,
+3089,3112,3134,3158,3182,3207,3227,3242,3252,3259,3266,3277,3294,3314,3335,3353,3365,3371,3372,3370,3371,
+3377,3393,3415,3440,3459,3462,3446,3411,3366,3324,3297,3294,3313,3344,3375,3398,3409,3411,3413,3420,3433,
+3450,3465,3477,3486,3497,3511,3532,3558,3584,3607,3627,3647,3670,3697,3729,3761,3789,3813,3832,3849,3869,
+3891,3917,3943,3968,3991,4013,4035,4060,4087,4117,4150,4185,4221,4259,4295,4328,4355,4377,4396,4416,4441,
+4470,4501,4529,4547,4555,4554,4550,4548,4550,4553,4554,4550,4538,4523,4507,4494,4484,4477,4470,4464,4460,
+4460,4465,4472,4475,4471,4459,4443,4426,4413,4403,4389,4368,4336,4296,4255,4220,4197,4186,4184,4189,4198,
+4212,4232,4254,4273,4282,4277,4256,4225,4190,4158,4131,4110,4090,4070,4048,4026,4006,3989,3976,3965,3956,
+3946,3934,3920,3902,3882,3862,3844,3830,3821,3814,3807,3798,3785,3770,3754,3738,3724,3710,3696,3683,3669,
+3656,3645,3633,3621,3605,3587,3567,3546,3528,3513,3501,3492,3484,3478,3471,3463,3454,3444,3434,3427,3424,
+3426,3431,3440,3449,3460,3470,3480,3487,3490,3488,3482,3473,3466,3462,3462,3466,3472,3478,3484,3488,3490,
+3488,3478,3463,3444,3428,3421,3425,3438,3453,3463,3465,3457,3442,3425,3409,3392,3374,3354,3333,3313,3295,
+3274,3245,3203,3148,3083,3016,2955,2901,2848,2791,2724,2651,2579,2519,2474,2439,2403,2356,2295,2228,2166,
+2122,2097,2084,2068,2036,1987,1932,1888,1867,1873,1897,1922,1931,1918,1885,1843,1804,1772,1748,1726,1702,
+1672,1638,1603,1571,1544,1518,1492,1463,1430,1395,1359,1323,1288,1254,1222,1191,1161,1131,1101,1069,1035,
+999,964,930,899,870,843,816,789,761,732,703,673,642,611,581,554,528,503,474,437,393,
+343,295,254,224,203,185,164,137,103,68,37,13,-5,-24,-50,-85,-127,-172,-214,-250,-282,
+-312,-345,-382,-420,-457,-491,-521,-548,-574,-601,-629,-658,-687,-716,-747,-781,-816,-851,-885,-916,-946,
+-975,-1004,-1034,-1065,-1095,-1124,-1151,-1179,-1207,-1238,-1270,-1304,-1338,-1373,-1408,-1441,-1471,-1499,-1525,-1552,-1581,
+-1613,-1646,-1679,-1709,-1734,-1756,-1776,-1797,-1821,-1846,-1870,-1892,-1910,-1925,-1939,-1955,-1973,-1994,-2015,-2035,-2053,
+-2069,-2084,-2098,-2112,-2126,-2140,-2155,-2170,-2186,-2202,-2219,-2235,-2251,-2267,-2281,-2296,-2311,-2325,-2340,-2354,-2369,
+-2385,-2401,-2417,-2432,-2444,-2454,-2462,-2469,-2475,-2480,-2483,-2482,-2479,-2473,-2468,-2465,-2465,-2468,-2472,-2473,-2471,
+-2467,-2463,-2460,-2459,-2457,-2455,-2450,-2443,-2437,-2432,-2430,-2431,-2431,-2430,-2427,-2424,-2421,-2421,-2422,-2423,-2423,
+-2420,-2417,-2414,-2413,-2413,-2413,-2412,-2410,-2405,-2400,-2394,-2387,-2379,-2367,-2353,-2339,-2327,-2320,-2317,-2316,-2313,
+-2306,-2292,-2272,-2248,-2224,-2201,-2181,-2163,-2149,-2135,-2124,-2113,-2105,-2098,-2093,-2087,-2080,-2070,-2059,-2048,-2038,
+-2029,-2022,-2016,-2012,-2011,-2015,-2028,-2050,-2080,-2113,-2143,-2164,-2175,-2178,-2173,-2164,-2153,-2140,-2127,-2118,-2114,
+-2118,-2131,-2147,-2164,-2177,-2186,-2192,-2197,-2204,-2210,-2215,-2216,-2214,-2211,-2210,-2213,-2222,-2234,-2250,-2266,-2280,
+-2290,-2292,-2287,-2276,-2265,-2262,-2268,-2276,-2274,-2250,-2199,-2133,-2077,-2062,-2105,-2205,-2336,-2462,-2548,-2582,-2571,
+-2542,-2522,-2526,-2551,-2584,-2609,-2617,-2614,-2612,-2620,-2640,-2664,-2680,-2677,-2654,-2618,-2577,-2542,-2515,-2496,-2481,
+-2468,-2456,-2447,-2443,-2443,-2449,-2459,-2472,-2491,-2514,-2541,-2572,-2605,-2637,-2671,-2707,-2748,-2797,-2853,-2914,-2977,
+-3036,-3088,-3130,-3161,-3184,-3203,-3220,-3237,-3252,-3264,-3270,-3270,-3267,-3262,-3260,-3261,-3262,-3261,-3258,-3253,-3250,
+-3251,-3256,-3265,-3273,-3277,-3277,-3276,-3277,-3285,-3297,-3312,-3324,-3329,-3329,-3327,-3329,-3337,-3352,-3370,-3385,-3394,
+-3397,-3394,-3391,-3389,-3388,-3389,-3388,-3386,-3382,-3379,-3376,-3374,-3371,-3365,-3358,-3349,-3339,-3330,-3322,-3315,-3306,
+-3297,-3287,-3277,-3267,-3260,-3253,-3245,-3237,-3227,-3217,-3206,-3195,-3182,-3170,-3157,-3146,-3134,-3124,-3113,-3100,-3087,
+-3073,-3063,-3056,-3053,-3053,-3053,-3051,-3045,-3035,-3025,-3014,-3004,-2994,-2985,-2974,-2963,-2952,-2941,-2930,-2919,-2905,
+-2888,-2868,-2846,-2824,-2801,-2780,-2760,-2741,-2724,-2708,-2695,-2683,-2674,-2666,-2658,-2648,-2637,-2623,-2609,-2595,-2582,
+-2573,-2565,-2556,-2546,-2532,-2515,-2498,-2482,-2468,-2456,-2446,-2435,-2424,-2412,-2401,-2392,-2385,-2379,-2372,-2365,-2357,
+-2349,-2342,-2337,-2333,-2330,-2328,-2325,-2322,-2318,-2312,-2307,-2301,-2297,-2293,-2290,-2289,-2287,-2284,-2279,-2272,-2263,
+-2252,-2239,-2223,-2206,-2189,-2173,-2159,-2149,-2140,-2131,-2119,-2103,-2086,-2068,-2054,-2043,-2035,-2028,-2020,-2012,-2003,
+-1995,-1988,-1983,-1976,-1967,-1954,-1939,-1923,-1908,-1895,-1883,-1872,-1860,-1848,-1837,-1829,-1823,-1821,-1820,-1819,-1817,
+-1814,-1813,-1812,-1812,-1812,-1811,-1809,-1806,-1804,-1801,-1798,-1797,-1795,-1795,-1796,-1800,-1807,-1815,-1823,-1828,-1830,
+-1826,-1817,-1803,-1787,-1771,-1755,-1742,-1728,-1714,-1699,-1682,-1664,-1648,-1634,-1623,-1613,-1601,-1585,-1565,-1542,-1518,
+-1496,-1478,-1466,-1457,-1450,-1443,-1433,-1421,-1406,-1389,-1371,-1354,-1339,-1327,-1316,-1306,-1297,-1286,-1275,-1264,-1255,
+-1249,-1246,-1245,-1245,-1244,-1241,-1239,-1237,-1237,-1239,-1243,-1247,-1251,-1255,-1258,-1262,-1265,-1267,-1269,-1270,-1270,
+-1269,-1270,-1271,-1273,-1276,-1278,-1282,-1287,-1292,-1299,-1305,-1309,-1311,-1310,-1308,-1304,-1302,-1302,-1305,-1309,-1313,
+-1317,-1318,-1317,-1314,-1311,-1309,-1308,-1308,-1309,-1310,-1311,-1310,-1309,-1308,-1308,-1308,-1307,-1304,-1298,-1289,-1278,
+-1266,-1255,-1245,-1237,-1229,-1223,-1217,-1212,-1208,-1204,-1200,-1195,-1187,-1175,-1162,-1148,-1136,-1127,-1121,-1112,-1097,
+-1073,-1038,-1000,-965,-942,-935,-942,-957,-969,-971,-962,-946,-931,-926,-935,-956,-980,-1002,-1015,-1019,-1018,
+-1015,-1015,-1014,-1010,-997,-973,-938,-897,-854,-815,-783,-755,-732,-709,-685,-660,-636,-613,-592,-574,-559,
+-544,-531,-519,-509,-501,-494,-488,-481,-472,-463,-453,-444,-434,-421,-404,-381,-356,-333,-312,-295,-277,
+-254,-225,-190,-157,-131,-114,-103,-90,-67,-32,12,56,92,117,134,153,181,218,260,298,326,
+345,360,380,409,442,472,490,492,481,465,448,432,411,384,349,316,301,319,378,476,600,
+732,854,955,1029,1077,1100,1101,1087,1063,1040,1030,1043,1081,1142,1213,1280,1327,1349,1346,1327,1305,
+1289,1286,1293,1304,1312,1313,1307,1298,1287,1275,1257,1232,1196,1155,1115,1086,1073,1076,1089,1107,1126,
+1146,1172,1209,1259,1321,1389,1457,1519,1575,1623,1663,1693,1711,1717,1713,1707,1705,1716,1741,1778,1818,
+1850,1864,1857,1828,1781,1725,1665,1607,1550,1493,1435,1376,1319,1271,1237,1224,1232,1257,1294,1332,1365,
+1386,1396,1395,1389,1383,1379,1379,1381,1383,1383,1382,1384,1391,1405,1427,1452,1476,1495,1507,1513,1514,
+1512,1508,1501,1492,1482,1475,1472,1474,1479,1484,1485,1481,1476,1472,1472,1475,1480,1483,1484,1486,1492,
+1506,1529,1556,1584,1607,1622,1628,1627,1625,1629,1647,1684,1743,1819,1906,1992,2067,2129,2179,2224,2266,
+2301,2320,2310,2264,2187,2090,1989,1892,1798,1691,1559,1395,1209,1027,876,780,741,748,777,807,823,
+826,823,819,819,819,813,797,771,738,703,669,637,605,574,548,534,542,578,644,740,859,
+992,1131,1266,1391,1501,1596,1675,1745,1808,1868,1926,1982,2030,2070,2097,2112,2114,2106,2092,2076,2063,
+2056,2057,2064,2073,2083,2091,2097,2104,2112,2123,2133,2142,2147,2150,2155,2164,2178,2194,2209,2220,2227,
+2232,2238,2246,2256,2263,2266,2266,2264,2265,2272,2284,2297,2308,2315,2321,2330,2345,2366,2388,2408,2422,
+2433,2443,2458,2477,2499,2517,2529,2536,2539,2545,2554,2565,2576,2585,2592,2600,2612,2629,2649,2666,2678,
+2682,2683,2682,2684,2687,2690,2693,2697,2704,2715,2731,2746,2756,2758,2752,2743,2739,2742,2753,2766,2773,
+2767,2709,2686,2651,2614,2582,2560,2550,2551,2557,2565,2572,2576,2580,2586,2597,2611,2625,2632,2630,2618,
+2601,2585,2578,2581,2590,2600,2603,2598,2584,2568,2553,2541,2530,2516,2497,2474,2451,2433,2423,2421,2423,
+2426,2427,2424,2420,2419,2421,2430,2444,2464,2488,2512,2535,2553,2567,2578,2590,2607,2630,2660,2692,2723,
+2748,2766,2779,2791,2807,2829,2856,2887,2919,2950,2978,3002,3025,3046,3068,3090,3114,3138,3159,3175,3187,
+3196,3203,3214,3229,3250,3272,3291,3305,3312,3313,3311,3311,3317,3329,3345,3361,3372,3373,3362,3340,3311,
+3284,3265,3259,3267,3287,3310,3332,3347,3356,3363,3372,3385,3403,3421,3437,3450,3461,3473,3490,3514,3541,
+3569,3594,3617,3637,3659,3682,3708,3735,3761,3782,3801,3818,3836,3855,3877,3900,3924,3947,3971,3995,4021,
+4048,4079,4112,4149,4187,4225,4260,4289,4313,4332,4351,4372,4397,4424,4448,4465,4472,4469,4461,4454,4452,
+4455,4461,4465,4464,4457,4448,4438,4429,4421,4414,4405,4398,4392,4392,4395,4400,4403,4401,4396,4388,4383,
+4381,4380,4374,4359,4333,4298,4260,4222,4188,4157,4129,4102,4081,4067,4063,4068,4078,4087,4092,4092,4088,
+4083,4077,4071,4060,4044,4022,3997,3974,3954,3940,3930,3923,3916,3909,3901,3890,3876,3860,3843,3828,3816,
+3808,3801,3794,3783,3766,3746,3725,3707,3693,3681,3671,3660,3647,3633,3620,3607,3595,3583,3570,3554,3538,
+3521,3505,3493,3485,3481,3481,3483,3485,3484,3480,3473,3464,3456,3450,3446,3444,3444,3445,3448,3453,3457,
+3461,3463,3462,3460,3459,3459,3462,3467,3472,3475,3477,3476,3471,3462,3447,3428,3409,3395,3390,3396,3408,
+3421,3427,3422,3406,3385,3363,3344,3328,3314,3299,3284,3269,3255,3240,3218,3185,3138,3081,3021,2964,2914,
+2868,2819,2759,2688,2611,2537,2473,2420,2371,2319,2261,2201,2148,2112,2096,2094,2091,2073,2036,1982,1928,
+1886,1867,1869,1881,1890,1885,1864,1831,1795,1761,1733,1709,1685,1657,1626,1593,1561,1530,1502,1475,1448,
+1419,1389,1356,1324,1290,1257,1225,1193,1162,1131,1098,1065,1030,995,960,927,896,868,840,813,786,
+758,729,698,666,634,601,571,544,519,492,461,422,376,327,282,245,219,200,181,159,129,
+93,58,29,6,-12,-32,-59,-95,-137,-181,-221,-255,-284,-313,-344,-381,-420,-460,-496,-527,-555,
+-581,-606,-631,-657,-684,-713,-744,-778,-814,-850,-886,-920,-951,-980,-1008,-1036,-1064,-1092,-1120,-1149,-1178,
+-1208,-1239,-1271,-1305,-1339,-1374,-1408,-1441,-1471,-1499,-1526,-1553,-1582,-1613,-1645,-1675,-1702,-1726,-1748,-1770,-1794,
+-1820,-1847,-1872,-1894,-1912,-1927,-1943,-1960,-1979,-2000,-2020,-2039,-2058,-2075,-2091,-2107,-2121,-2134,-2148,-2163,-2179,
+-2198,-2217,-2235,-2251,-2265,-2277,-2291,-2306,-2323,-2340,-2356,-2370,-2384,-2398,-2412,-2428,-2443,-2457,-2468,-2477,-2485,
+-2493,-2499,-2502,-2501,-2496,-2489,-2482,-2479,-2481,-2485,-2490,-2493,-2492,-2489,-2486,-2484,-2483,-2483,-2482,-2479,-2474,
+-2470,-2467,-2466,-2466,-2464,-2461,-2456,-2451,-2448,-2448,-2449,-2451,-2451,-2450,-2448,-2447,-2447,-2448,-2448,-2446,-2442,
+-2438,-2435,-2432,-2428,-2422,-2411,-2396,-2379,-2364,-2353,-2349,-2348,-2347,-2342,-2332,-2315,-2294,-2270,-2246,-2224,-2204,
+-2186,-2170,-2156,-2145,-2137,-2131,-2126,-2122,-2118,-2111,-2103,-2093,-2084,-2075,-2067,-2061,-2055,-2051,-2050,-2056,-2069,
+-2090,-2118,-2148,-2175,-2195,-2206,-2208,-2202,-2191,-2176,-2163,-2153,-2149,-2152,-2160,-2172,-2184,-2196,-2207,-2218,-2230,
+-2242,-2251,-2255,-2253,-2246,-2238,-2231,-2231,-2239,-2254,-2273,-2293,-2310,-2320,-2321,-2317,-2311,-2308,-2311,-2317,-2317,
+-2302,-2265,-2210,-2156,-2126,-2142,-2212,-2323,-2449,-2557,-2623,-2643,-2631,-2611,-2603,-2615,-2643,-2673,-2693,-2699,-2697,
+-2696,-2703,-2720,-2740,-2756,-2764,-2762,-2752,-2736,-2715,-2688,-2655,-2619,-2583,-2555,-2538,-2531,-2534,-2541,-2554,-2572,
+-2597,-2631,-2673,-2717,-2762,-2805,-2846,-2889,-2937,-2991,-3048,-3106,-3160,-3206,-3242,-3269,-3288,-3302,-3314,-3325,-3338,
+-3350,-3361,-3367,-3368,-3364,-3358,-3351,-3346,-3343,-3340,-3335,-3330,-3326,-3326,-3331,-3339,-3349,-3355,-3357,-3357,-3357,
+-3363,-3373,-3387,-3400,-3407,-3409,-3408,-3408,-3414,-3426,-3442,-3456,-3465,-3469,-3468,-3466,-3466,-3466,-3467,-3466,-3463,
+-3459,-3456,-3455,-3454,-3451,-3445,-3435,-3422,-3410,-3400,-3391,-3384,-3375,-3364,-3352,-3340,-3330,-3322,-3315,-3307,-3298,
+-3288,-3277,-3265,-3254,-3244,-3232,-3220,-3208,-3196,-3184,-3173,-3162,-3151,-3138,-3126,-3116,-3108,-3103,-3099,-3096,-3092,
+-3087,-3079,-3070,-3060,-3049,-3037,-3024,-3010,-2996,-2984,-2972,-2962,-2951,-2939,-2925,-2908,-2890,-2870,-2849,-2828,-2806,
+-2785,-2765,-2747,-2731,-2718,-2709,-2700,-2692,-2683,-2671,-2656,-2641,-2626,-2613,-2601,-2591,-2579,-2566,-2552,-2538,-2524,
+-2513,-2502,-2491,-2477,-2461,-2444,-2428,-2416,-2407,-2403,-2400,-2398,-2394,-2387,-2380,-2371,-2362,-2353,-2345,-2337,-2330,
+-2323,-2317,-2312,-2308,-2304,-2301,-2299,-2298,-2297,-2296,-2296,-2297,-2297,-2295,-2290,-2280,-2267,-2252,-2236,-2224,-2214,
+-2205,-2195,-2182,-2164,-2143,-2122,-2103,-2088,-2078,-2069,-2060,-2050,-2039,-2027,-2017,-2007,-1998,-1987,-1975,-1963,-1951,
+-1939,-1929,-1918,-1905,-1892,-1878,-1866,-1858,-1853,-1851,-1849,-1846,-1842,-1836,-1832,-1829,-1829,-1832,-1834,-1837,-1839,
+-1839,-1838,-1837,-1834,-1832,-1829,-1827,-1827,-1828,-1830,-1833,-1834,-1834,-1830,-1823,-1813,-1803,-1792,-1781,-1771,-1760,
+-1747,-1731,-1711,-1688,-1666,-1645,-1627,-1612,-1598,-1585,-1570,-1554,-1537,-1523,-1511,-1503,-1497,-1491,-1482,-1470,-1454,
+-1435,-1413,-1393,-1374,-1358,-1345,-1334,-1324,-1314,-1303,-1291,-1281,-1273,-1267,-1264,-1263,-1262,-1261,-1259,-1257,-1256,
+-1257,-1260,-1265,-1271,-1277,-1283,-1288,-1293,-1298,-1301,-1304,-1305,-1306,-1305,-1304,-1303,-1302,-1302,-1303,-1306,-1311,
+-1318,-1326,-1334,-1340,-1344,-1345,-1344,-1342,-1340,-1338,-1339,-1341,-1344,-1346,-1348,-1348,-1347,-1346,-1344,-1343,-1343,
+-1343,-1342,-1341,-1338,-1336,-1334,-1333,-1332,-1332,-1331,-1328,-1322,-1314,-1305,-1294,-1284,-1273,-1262,-1251,-1239,-1228,
+-1218,-1208,-1199,-1190,-1181,-1171,-1160,-1151,-1145,-1141,-1137,-1129,-1111,-1083,-1047,-1009,-978,-962,-964,-978,-996,
+-1008,-1006,-992,-970,-953,-948,-959,-982,-1009,-1031,-1044,-1047,-1045,-1041,-1040,-1039,-1034,-1022,-998,-966,-927,
+-888,-852,-823,-797,-773,-748,-721,-692,-665,-640,-619,-601,-583,-566,-549,-534,-521,-513,-509,-506,-502,
+-496,-487,-476,-463,-448,-429,-407,-381,-354,-331,-313,-299,-285,-266,-240,-208,-177,-151,-135,-125,-114,
+-93,-59,-14,31,69,95,112,128,152,187,230,273,307,332,349,366,389,417,446,469,481,
+482,475,464,450,431,405,372,335,305,291,303,345,412,498,592,686,774,850,914,964,1002,
+1031,1058,1088,1125,1171,1223,1273,1316,1345,1359,1362,1360,1360,1366,1378,1395,1409,1417,1415,1406,1391,
+1373,1353,1330,1300,1264,1225,1187,1157,1137,1128,1126,1130,1138,1151,1173,1207,1251,1304,1359,1415,1469,
+1520,1570,1616,1654,1681,1694,1695,1691,1689,1698,1721,1756,1795,1830,1851,1852,1834,1800,1756,1709,1663,
+1620,1578,1535,1491,1447,1407,1376,1359,1358,1370,1392,1416,1437,1451,1457,1459,1459,1460,1462,1467,1471,
+1474,1477,1483,1494,1511,1534,1559,1579,1590,1591,1585,1575,1567,1564,1564,1566,1565,1562,1559,1557,1560,
+1565,1572,1576,1575,1570,1563,1556,1551,1550,1551,1555,1562,1573,1588,1606,1625,1642,1653,1657,1653,1643,
+1630,1619,1615,1625,1652,1698,1757,1824,1891,1955,2016,2076,2135,2191,2237,2267,2275,2263,2235,2197,2147,
+2077,1975,1833,1657,1465,1288,1155,1084,1073,1101,1141,1166,1163,1132,1083,1028,976,930,888,846,804,
+760,715,668,614,552,482,408,341,295,281,309,382,498,648,822,1005,1185,1349,1491,1607,1700,
+1773,1834,1889,1943,1995,2044,2086,2114,2126,2120,2099,2071,2044,2026,2020,2024,2036,2048,2059,2067,2074,
+2081,2090,2097,2103,2107,2112,2119,2132,2149,2167,2182,2191,2197,2202,2209,2220,2233,2242,2247,2246,2245,
+2247,2255,2269,2284,2296,2303,2310,2319,2333,2352,2373,2391,2405,2416,2428,2444,2464,2484,2500,2508,2511,
+2512,2517,2526,2539,2551,2561,2568,2575,2584,2598,2614,2629,2640,2646,2650,2653,2657,2661,2665,2669,2676,
+2688,2705,2726,2743,2751,2746,2732,2715,2702,2700,2706,2716,2719,2709,2614,2589,2560,2535,2518,2512,2514,
+2519,2522,2521,2514,2504,2497,2495,2501,2515,2533,2549,2559,2560,2556,2550,2547,2547,2548,2547,2541,2529,
+2513,2497,2484,2471,2457,2436,2410,2382,2357,2343,2340,2347,2358,2367,2370,2368,2364,2364,2370,2382,2398,
+2417,2435,2454,2472,2488,2505,2521,2539,2561,2586,2615,2644,2671,2693,2710,2726,2744,2767,2795,2828,2862,
+2893,2920,2943,2964,2985,3008,3031,3055,3077,3095,3109,3120,3128,3137,3148,3162,3180,3200,3219,3234,3243,
+3248,3250,3254,3261,3273,3285,3294,3296,3290,3277,3261,3246,3237,3234,3236,3243,3252,3262,3273,3284,3297,
+3311,3327,3344,3361,3376,3390,3402,3414,3428,3446,3468,3495,3525,3555,3583,3608,3630,3650,3670,3690,3710,
+3731,3750,3768,3785,3802,3818,3836,3856,3878,3901,3925,3950,3975,4002,4032,4064,4100,4137,4174,4207,4235,
+4259,4279,4299,4321,4344,4366,4382,4391,4390,4383,4374,4367,4365,4368,4371,4374,4374,4371,4366,4362,4357,
+4351,4343,4333,4323,4316,4316,4320,4326,4331,4332,4331,4328,4327,4327,4327,4323,4311,4291,4264,4233,4199,
+4164,4126,4084,4041,4002,3971,3952,3946,3949,3958,3970,3982,3995,4007,4016,4020,4016,4002,3981,3956,3934,
+3916,3904,3897,3892,3887,3882,3876,3868,3856,3841,3825,3809,3796,3786,3779,3771,3759,3742,3722,3700,3681,
+3667,3656,3647,3637,3625,3611,3597,3584,3573,3564,3556,3546,3534,3520,3505,3492,3482,3479,3483,3492,3504,
+3514,3519,3518,3511,3499,3485,3469,3452,3437,3424,3416,3412,3412,3415,3419,3423,3427,3433,3440,3450,3461,
+3470,3475,3475,3468,3456,3439,3420,3401,3383,3370,3364,3365,3370,3374,3372,3360,3340,3315,3292,3271,3256,
+3244,3233,3222,3213,3204,3193,3177,3149,3109,3057,3002,2950,2905,2865,2825,2775,2714,2641,2564,2489,2421,
+2358,2298,2238,2181,2136,2108,2102,2111,2122,2120,2095,2046,1985,1925,1880,1857,1851,1853,1852,1841,1818,
+1787,1754,1722,1693,1667,1641,1613,1583,1551,1519,1487,1457,1428,1400,1372,1345,1317,1288,1258,1227,1195,
+1162,1129,1095,1061,1027,993,960,928,898,868,840,811,783,755,726,695,663,630,599,569,543,
+518,491,458,418,372,323,279,242,214,192,169,144,113,79,47,20,0,-19,-41,-69,-104,
+-145,-185,-222,-254,-282,-311,-344,-381,-421,-461,-498,-530,-558,-583,-607,-631,-657,-683,-713,-744,-779,
+-815,-851,-886,-919,-950,-978,-1006,-1034,-1061,-1090,-1120,-1150,-1182,-1214,-1247,-1280,-1313,-1345,-1377,-1409,-1440,
+-1469,-1498,-1527,-1557,-1587,-1618,-1649,-1677,-1702,-1724,-1747,-1770,-1796,-1823,-1850,-1875,-1895,-1913,-1930,-1948,-1967,
+-1988,-2008,-2027,-2045,-2062,-2080,-2097,-2113,-2128,-2143,-2157,-2172,-2190,-2209,-2229,-2246,-2261,-2273,-2286,-2301,-2318,
+-2337,-2356,-2373,-2387,-2399,-2410,-2423,-2437,-2451,-2464,-2476,-2485,-2494,-2503,-2510,-2516,-2518,-2516,-2511,-2506,-2504,
+-2505,-2510,-2514,-2517,-2517,-2515,-2513,-2511,-2511,-2510,-2508,-2504,-2501,-2499,-2498,-2498,-2498,-2495,-2490,-2483,-2476,
+-2473,-2472,-2473,-2474,-2474,-2473,-2473,-2474,-2477,-2479,-2480,-2477,-2473,-2468,-2465,-2465,-2464,-2461,-2452,-2437,-2418,
+-2401,-2388,-2382,-2380,-2379,-2376,-2367,-2352,-2332,-2309,-2285,-2261,-2239,-2220,-2202,-2187,-2175,-2165,-2158,-2153,-2151,
+-2150,-2148,-2145,-2138,-2129,-2119,-2110,-2101,-2095,-2091,-2088,-2089,-2094,-2107,-2128,-2156,-2188,-2216,-2237,-2246,-2243,
+-2231,-2214,-2199,-2189,-2185,-2188,-2195,-2204,-2215,-2226,-2238,-2250,-2263,-2273,-2279,-2280,-2275,-2268,-2260,-2255,-2256,
+-2264,-2279,-2298,-2320,-2338,-2351,-2357,-2357,-2354,-2354,-2357,-2361,-2357,-2340,-2308,-2270,-2242,-2241,-2282,-2361,-2464,
+-2564,-2639,-2678,-2684,-2673,-2666,-2674,-2699,-2731,-2758,-2773,-2777,-2776,-2779,-2791,-2810,-2834,-2857,-2877,-2892,-2899,
+-2896,-2879,-2846,-2799,-2746,-2698,-2663,-2646,-2645,-2654,-2668,-2688,-2714,-2749,-2794,-2844,-2895,-2943,-2987,-3029,-3073,
+-3121,-3172,-3223,-3268,-3304,-3332,-3354,-3371,-3387,-3401,-3413,-3422,-3431,-3438,-3446,-3452,-3454,-3453,-3448,-3440,-3432,
+-3425,-3420,-3416,-3413,-3412,-3413,-3417,-3423,-3430,-3435,-3437,-3436,-3437,-3441,-3451,-3464,-3477,-3487,-3491,-3491,-3491,
+-3494,-3503,-3515,-3527,-3537,-3543,-3545,-3545,-3544,-3543,-3540,-3536,-3531,-3527,-3525,-3525,-3525,-3523,-3516,-3506,-3493,
+-3481,-3471,-3462,-3454,-3445,-3433,-3419,-3405,-3394,-3385,-3376,-3367,-3356,-3344,-3332,-3321,-3312,-3304,-3296,-3285,-3273,
+-3260,-3247,-3237,-3228,-3219,-3208,-3195,-3180,-3166,-3153,-3143,-3136,-3131,-3126,-3121,-3115,-3107,-3097,-3086,-3073,-3059,
+-3045,-3031,-3018,-3007,-2996,-2986,-2975,-2962,-2948,-2932,-2913,-2893,-2872,-2850,-2828,-2807,-2788,-2772,-2758,-2746,-2736,
+-2726,-2714,-2700,-2685,-2670,-2655,-2642,-2629,-2617,-2604,-2592,-2580,-2570,-2560,-2551,-2539,-2525,-2508,-2489,-2470,-2454,
+-2442,-2435,-2430,-2425,-2421,-2414,-2407,-2398,-2389,-2380,-2371,-2362,-2354,-2346,-2338,-2331,-2324,-2318,-2312,-2307,-2303,
+-2300,-2299,-2300,-2302,-2306,-2309,-2310,-2307,-2301,-2291,-2279,-2268,-2257,-2247,-2236,-2222,-2206,-2188,-2170,-2154,-2140,
+-2129,-2119,-2109,-2097,-2083,-2069,-2054,-2039,-2026,-2013,-2001,-1992,-1984,-1976,-1968,-1957,-1943,-1927,-1910,-1897,-1887,
+-1882,-1881,-1880,-1877,-1873,-1868,-1863,-1860,-1859,-1860,-1863,-1866,-1869,-1872,-1873,-1873,-1873,-1871,-1868,-1865,-1861,
+-1857,-1853,-1849,-1844,-1838,-1833,-1828,-1824,-1821,-1819,-1818,-1816,-1812,-1803,-1789,-1768,-1742,-1713,-1684,-1659,-1639,
+-1625,-1615,-1606,-1597,-1587,-1576,-1565,-1555,-1545,-1535,-1523,-1507,-1488,-1467,-1444,-1422,-1402,-1383,-1367,-1352,-1338,
+-1325,-1313,-1303,-1296,-1292,-1291,-1291,-1293,-1294,-1294,-1292,-1290,-1288,-1288,-1290,-1294,-1299,-1304,-1309,-1313,-1317,
+-1320,-1322,-1325,-1328,-1330,-1331,-1331,-1330,-1329,-1328,-1328,-1330,-1334,-1340,-1347,-1355,-1362,-1368,-1373,-1377,-1379,
+-1381,-1382,-1382,-1382,-1382,-1380,-1379,-1377,-1376,-1375,-1374,-1374,-1374,-1373,-1371,-1369,-1366,-1363,-1360,-1358,-1357,
+-1357,-1356,-1354,-1350,-1344,-1336,-1327,-1316,-1305,-1291,-1277,-1262,-1246,-1231,-1216,-1203,-1191,-1180,-1170,-1161,-1155,
+-1151,-1149,-1146,-1137,-1120,-1096,-1066,-1038,-1018,-1012,-1019,-1034,-1047,-1050,-1038,-1016,-990,-972,-968,-979,-1003,
+-1030,-1053,-1067,-1071,-1068,-1064,-1060,-1055,-1046,-1032,-1010,-981,-948,-915,-886,-860,-836,-813,-787,-759,-731,
+-703,-678,-657,-637,-619,-600,-581,-563,-548,-539,-534,-531,-528,-522,-511,-497,-480,-460,-437,-412,-385,
+-358,-334,-315,-301,-289,-275,-255,-230,-204,-182,-165,-153,-138,-115,-81,-38,7,46,74,92,108,
+129,160,199,241,279,308,329,348,368,393,420,446,466,478,483,482,476,464,447,421,390,
+358,329,310,306,318,347,392,449,517,592,671,752,834,915,994,1070,1141,1203,1255,1294,1320,
+1337,1348,1358,1373,1395,1424,1457,1490,1516,1530,1529,1513,1483,1445,1401,1356,1313,1276,1245,1220,1202,
+1188,1176,1166,1159,1158,1167,1188,1221,1262,1306,1349,1390,1431,1473,1518,1564,1607,1642,1665,1676,1679,
+1680,1686,1698,1718,1741,1763,1778,1782,1776,1760,1736,1709,1682,1656,1633,1612,1591,1570,1547,1527,1512,
+1504,1505,1513,1523,1533,1541,1544,1544,1545,1546,1549,1552,1555,1559,1563,1572,1587,1607,1630,1651,1664,
+1666,1657,1643,1631,1626,1629,1639,1650,1657,1657,1652,1644,1637,1634,1635,1637,1637,1635,1629,1622,1615,
+1610,1609,1612,1618,1628,1640,1651,1661,1668,1672,1675,1676,1675,1671,1663,1651,1639,1634,1640,1660,1694,
+1738,1788,1843,1900,1960,2022,2083,2140,2188,2227,2253,2264,2253,2212,2135,2022,1886,1747,1631,1559,1539,
+1564,1610,1652,1668,1646,1590,1512,1425,1341,1267,1204,1150,1103,1059,1016,970,915,847,761,659,547,
+435,336,266,239,266,351,492,678,891,1110,1315,1490,1627,1726,1797,1849,1894,1942,1992,2041,2081,
+2103,2103,2083,2051,2019,1997,1990,1996,2010,2024,2034,2039,2042,2044,2047,2052,2056,2060,2066,2076,2090,
+2108,2127,2142,2153,2161,2169,2181,2197,2214,2228,2235,2238,2238,2241,2250,2263,2278,2290,2298,2304,2311,
+2322,2336,2351,2366,2377,2388,2400,2415,2432,2449,2461,2468,2472,2475,2483,2495,2509,2523,2534,2541,2547,
+2553,2562,2571,2580,2587,2594,2601,2610,2620,2628,2634,2638,2641,2648,2660,2675,2687,2691,2684,2669,2652,
+2639,2634,2634,2635,2630,2614,2530,2507,2486,2472,2468,2472,2480,2487,2490,2486,2477,2466,2457,2453,2456,
+2464,2476,2487,2496,2499,2498,2494,2488,2480,2469,2454,2434,2411,2388,2368,2353,2341,2329,2314,2296,2280,
+2270,2270,2280,2296,2311,2319,2321,2318,2315,2316,2323,2334,2348,2361,2374,2387,2403,2423,2445,2470,2494,
+2518,2542,2565,2589,2612,2635,2658,2683,2710,2740,2772,2803,2830,2854,2874,2895,2918,2945,2973,3001,3023,
+3040,3050,3057,3063,3071,3082,3097,3115,3134,3152,3167,3178,3185,3191,3197,3206,3219,3230,3237,3236,3225,
+3207,3189,3179,3180,3193,3211,3227,3236,3237,3233,3231,3236,3251,3273,3298,3321,3338,3349,3358,3368,3382,
+3401,3424,3451,3478,3506,3534,3562,3588,3612,3633,3652,3668,3684,3700,3718,3736,3753,3770,3786,3802,3819,
+3839,3860,3883,3906,3930,3954,3980,4009,4040,4072,4104,4134,4161,4185,4207,4229,4250,4271,4288,4299,4304,
+4304,4301,4298,4296,4297,4297,4297,4294,4290,4286,4283,4281,4279,4275,4267,4258,4250,4246,4248,4254,4262,
+4269,4272,4272,4270,4268,4266,4263,4256,4244,4226,4206,4183,4158,4130,4098,4061,4021,3984,3953,3931,3920,
+3918,3921,3927,3935,3945,3955,3964,3969,3967,3956,3940,3921,3904,3890,3879,3872,3865,3860,3853,3847,3838,
+3828,3815,3800,3785,3771,3761,3752,3743,3733,3718,3699,3679,3659,3643,3629,3618,3608,3599,3588,3578,3569,
+3561,3554,3547,3540,3531,3520,3506,3493,3483,3479,3485,3499,3518,3536,3550,3555,3550,3535,3514,3487,3458,
+3430,3405,3385,3373,3369,3369,3373,3377,3382,3389,3399,3413,3430,3445,3453,3453,3444,3429,3410,3392,3375,
+3360,3348,3339,3332,3327,3320,3311,3297,3277,3253,3228,3205,3186,3171,3160,3152,3147,3143,3137,3123,3099,
+3062,3015,2961,2909,2862,2822,2784,2742,2692,2632,2566,2497,2429,2362,2295,2229,2167,2115,2081,2067,2072,
+2084,2090,2078,2044,1992,1933,1882,1846,1828,1823,1823,1818,1803,1778,1746,1712,1679,1651,1626,1601,1575,
+1545,1513,1480,1446,1414,1385,1358,1333,1307,1281,1254,1224,1194,1162,1129,1096,1063,1031,999,967,936,
+905,874,843,813,783,754,725,695,663,630,599,571,545,521,495,464,427,384,338,294,255,
+222,194,166,137,106,74,45,19,-3,-24,-49,-78,-112,-148,-185,-219,-250,-281,-313,-349,-387,
+-426,-463,-497,-527,-555,-581,-606,-632,-660,-689,-720,-753,-788,-824,-858,-890,-919,-946,-972,-998,-1025,
+-1054,-1084,-1116,-1149,-1183,-1217,-1251,-1284,-1316,-1347,-1377,-1407,-1435,-1464,-1494,-1524,-1556,-1590,-1622,-1653,-1681,
+-1706,-1729,-1752,-1776,-1802,-1828,-1853,-1874,-1892,-1909,-1926,-1946,-1969,-1992,-2013,-2033,-2050,-2066,-2082,-2099,-2115,
+-2132,-2147,-2163,-2180,-2198,-2217,-2235,-2252,-2266,-2279,-2293,-2310,-2329,-2350,-2369,-2385,-2397,-2408,-2419,-2431,-2445,
+-2459,-2471,-2482,-2490,-2499,-2508,-2517,-2525,-2531,-2534,-2534,-2533,-2534,-2536,-2539,-2541,-2542,-2542,-2541,-2541,-2541,
+-2540,-2538,-2535,-2530,-2525,-2523,-2523,-2523,-2522,-2517,-2510,-2503,-2499,-2497,-2498,-2500,-2500,-2498,-2495,-2495,-2498,
+-2503,-2507,-2509,-2507,-2501,-2496,-2493,-2493,-2494,-2493,-2485,-2471,-2453,-2437,-2425,-2419,-2417,-2416,-2413,-2404,-2389,
+-2369,-2345,-2320,-2295,-2274,-2255,-2239,-2226,-2215,-2205,-2196,-2189,-2186,-2185,-2186,-2185,-2179,-2169,-2157,-2144,-2136,
+-2132,-2131,-2132,-2131,-2131,-2135,-2146,-2168,-2199,-2231,-2259,-2275,-2276,-2266,-2251,-2236,-2226,-2223,-2225,-2230,-2237,
+-2246,-2257,-2271,-2285,-2297,-2304,-2306,-2304,-2300,-2296,-2295,-2297,-2301,-2308,-2319,-2334,-2353,-2373,-2389,-2398,-2398,
+-2394,-2390,-2388,-2390,-2390,-2386,-2376,-2365,-2366,-2390,-2441,-2515,-2595,-2663,-2704,-2717,-2711,-2703,-2707,-2728,-2762,
+-2798,-2825,-2839,-2845,-2851,-2863,-2885,-2914,-2946,-2977,-3004,-3025,-3037,-3033,-3010,-2969,-2914,-2858,-2812,-2786,-2781,
+-2793,-2814,-2838,-2865,-2897,-2937,-2983,-3032,-3078,-3118,-3153,-3187,-3225,-3270,-3316,-3358,-3392,-3414,-3429,-3443,-3459,
+-3477,-3496,-3511,-3519,-3521,-3522,-3524,-3529,-3534,-3538,-3536,-3529,-3520,-3511,-3506,-3503,-3503,-3504,-3504,-3506,-3508,
+-3511,-3515,-3517,-3519,-3521,-3526,-3533,-3544,-3555,-3563,-3568,-3568,-3568,-3570,-3575,-3585,-3596,-3606,-3615,-3619,-3621,
+-3619,-3615,-3609,-3601,-3594,-3589,-3587,-3587,-3587,-3585,-3580,-3571,-3560,-3550,-3542,-3535,-3526,-3515,-3501,-3485,-3469,
+-3456,-3445,-3436,-3425,-3413,-3400,-3388,-3379,-3373,-3368,-3362,-3353,-3341,-3327,-3313,-3302,-3293,-3284,-3274,-3260,-3243,
+-3223,-3204,-3188,-3176,-3168,-3163,-3158,-3153,-3148,-3142,-3135,-3126,-3116,-3104,-3090,-3075,-3060,-3044,-3029,-3016,-3002,
+-2988,-2974,-2958,-2942,-2924,-2906,-2888,-2869,-2850,-2833,-2816,-2800,-2786,-2771,-2756,-2741,-2725,-2709,-2694,-2680,-2667,
+-2655,-2643,-2632,-2622,-2612,-2603,-2594,-2584,-2572,-2558,-2543,-2527,-2511,-2496,-2482,-2470,-2458,-2448,-2438,-2429,-2422,
+-2414,-2408,-2401,-2393,-2386,-2377,-2368,-2359,-2350,-2341,-2334,-2328,-2324,-2320,-2317,-2314,-2312,-2310,-2310,-2309,-2308,
+-2306,-2300,-2292,-2282,-2271,-2261,-2252,-2243,-2234,-2224,-2214,-2203,-2191,-2180,-2168,-2155,-2142,-2128,-2114,-2099,-2083,
+-2068,-2055,-2043,-2033,-2025,-2016,-2006,-1993,-1977,-1959,-1942,-1928,-1918,-1913,-1912,-1911,-1910,-1907,-1905,-1902,-1900,
+-1899,-1900,-1901,-1902,-1904,-1905,-1905,-1905,-1904,-1902,-1899,-1896,-1893,-1890,-1885,-1878,-1870,-1862,-1855,-1851,-1848,
+-1848,-1849,-1850,-1851,-1849,-1843,-1832,-1815,-1793,-1768,-1744,-1723,-1708,-1699,-1694,-1689,-1682,-1671,-1655,-1637,-1618,
+-1599,-1582,-1565,-1548,-1530,-1511,-1491,-1471,-1451,-1430,-1409,-1387,-1365,-1345,-1329,-1318,-1313,-1313,-1316,-1322,-1327,
+-1330,-1332,-1331,-1329,-1327,-1326,-1327,-1330,-1333,-1337,-1339,-1340,-1339,-1338,-1338,-1338,-1340,-1344,-1348,-1351,-1354,
+-1356,-1357,-1359,-1361,-1363,-1366,-1370,-1374,-1379,-1384,-1390,-1396,-1403,-1409,-1414,-1417,-1417,-1416,-1413,-1410,-1406,
+-1404,-1402,-1401,-1400,-1400,-1399,-1397,-1394,-1391,-1387,-1385,-1382,-1381,-1381,-1380,-1378,-1374,-1368,-1360,-1351,-1340,
+-1327,-1313,-1298,-1282,-1265,-1249,-1233,-1217,-1203,-1190,-1179,-1171,-1166,-1163,-1162,-1158,-1150,-1136,-1116,-1096,-1078,
+-1069,-1070,-1078,-1088,-1091,-1083,-1063,-1036,-1009,-991,-987,-998,-1020,-1045,-1067,-1082,-1090,-1091,-1087,-1081,-1071,
+-1056,-1037,-1014,-987,-959,-932,-908,-886,-865,-845,-823,-800,-776,-751,-727,-705,-684,-665,-646,-627,-609,
+-593,-581,-572,-565,-558,-549,-536,-519,-499,-477,-453,-427,-400,-372,-347,-325,-307,-294,-281,-267,-250,
+-231,-212,-195,-179,-160,-135,-102,-62,-21,17,47,71,91,112,139,172,208,244,275,301,324,
+345,369,393,417,440,458,472,482,487,487,482,470,452,429,403,376,351,331,321,322,338,
+369,416,476,550,635,731,835,942,1046,1140,1218,1277,1317,1343,1359,1373,1390,1414,1448,1488,1532,
+1572,1599,1608,1593,1554,1497,1429,1362,1305,1266,1245,1238,1240,1242,1242,1237,1233,1234,1247,1271,1306,
+1344,1382,1415,1445,1474,1507,1545,1588,1630,1667,1696,1715,1726,1733,1737,1741,1746,1751,1755,1757,1757,
+1755,1748,1738,1726,1714,1705,1700,1698,1698,1694,1684,1669,1651,1633,1620,1614,1613,1615,1618,1621,1622,
+1623,1625,1627,1631,1634,1638,1644,1651,1662,1676,1689,1700,1704,1700,1692,1682,1677,1678,1687,1699,1711,
+1716,1712,1701,1686,1671,1659,1654,1654,1657,1661,1664,1664,1663,1659,1657,1656,1659,1665,1671,1677,1681,
+1684,1689,1697,1710,1725,1737,1741,1734,1717,1696,1680,1676,1687,1711,1745,1783,1823,1863,1907,1957,2011,
+2068,2124,2170,2202,2211,2193,2149,2084,2011,1943,1897,1881,1897,1935,1979,2011,2018,1995,1945,1877,1802,
+1729,1666,1612,1569,1533,1502,1475,1448,1417,1377,1320,1239,1125,978,805,620,448,318,256,280,392,
+577,811,1061,1295,1491,1637,1736,1799,1844,1884,1929,1977,2020,2050,2060,2048,2024,1997,1980,1978,1990,
+2007,2023,2032,2033,2030,2026,2024,2026,2029,2033,2038,2045,2057,2073,2091,2107,2121,2132,2144,2157,2174,
+2192,2208,2219,2225,2229,2233,2241,2251,2262,2271,2277,2282,2287,2294,2304,2316,2328,2338,2348,2358,2370,
+2383,2397,2409,2420,2430,2441,2454,2470,2486,2500,2512,2521,2529,2535,2541,2544,2545,2544,2546,2553,2565,
+2580,2592,2598,2597,2590,2584,2580,2580,2583,2583,2579,2572,2565,2561,2560,2561,2558,2548,2530,2478,2461,
+2446,2437,2435,2438,2442,2445,2445,2443,2440,2440,2441,2444,2447,2451,2453,2454,2452,2445,2435,2421,2403,
+2382,2358,2331,2303,2276,2252,2234,2222,2215,2211,2208,2206,2207,2212,2224,2239,2254,2265,2270,2268,2264,
+2262,2265,2273,2284,2296,2306,2316,2329,2348,2372,2399,2428,2455,2478,2499,2519,2540,2564,2591,2621,2653,
+2685,2716,2743,2766,2784,2800,2818,2840,2869,2902,2934,2962,2981,2991,2996,2999,3006,3018,3034,3053,3072,
+3090,3105,3118,3129,3138,3148,3157,3168,3177,3183,3182,3171,3154,3135,3122,3123,3139,3166,3193,3212,3216,
+3207,3193,3184,3188,3206,3235,3266,3291,3307,3316,3325,3337,3357,3382,3409,3435,3459,3482,3504,3529,3556,
+3582,3605,3623,3639,3652,3666,3682,3700,3718,3735,3752,3768,3785,3804,3824,3845,3866,3887,3907,3929,3952,
+3977,4002,4028,4052,4076,4099,4122,4144,4165,4184,4197,4206,4211,4214,4217,4221,4225,4229,4229,4226,4220,
+4213,4206,4202,4200,4199,4197,4194,4189,4186,4186,4189,4195,4201,4206,4208,4209,4208,4206,4204,4199,4190,
+4177,4161,4144,4126,4108,4089,4067,4042,4014,3989,3967,3950,3939,3931,3925,3919,3914,3911,3910,3911,3912,
+3910,3904,3893,3881,3868,3856,3845,3836,3827,3819,3810,3802,3794,3785,3776,3766,3755,3745,3735,3725,3715,
+3704,3690,3674,3656,3637,3618,3601,3588,3578,3572,3568,3564,3559,3552,3545,3536,3528,3520,3510,3501,3491,
+3485,3484,3492,3509,3531,3554,3573,3581,3578,3563,3540,3510,3477,3445,3415,3391,3375,3367,3364,3363,3361,
+3359,3357,3360,3367,3379,3392,3401,3402,3395,3382,3369,3357,3348,3341,3332,3321,3308,3293,3280,3267,3254,
+3237,3216,3191,3163,3137,3116,3101,3092,3088,3084,3078,3065,3044,3012,2971,2924,2874,2825,2778,2732,2686,
+2637,2584,2529,2472,2413,2353,2289,2223,2157,2096,2047,2015,2001,2000,2003,2000,1982,1951,1909,1867,1832,
+1809,1798,1794,1790,1780,1760,1732,1700,1666,1636,1610,1587,1564,1538,1510,1479,1446,1415,1386,1359,1334,
+1309,1283,1256,1226,1196,1164,1132,1101,1070,1040,1010,980,948,915,882,848,815,784,753,723,693,
+660,627,596,566,540,516,492,465,432,395,354,313,273,236,202,168,136,103,72,43,16,
+-9,-35,-63,-92,-123,-155,-187,-219,-252,-288,-325,-364,-401,-437,-469,-498,-525,-552,-580,-609,-638,
+-668,-700,-732,-766,-801,-836,-869,-899,-925,-948,-970,-993,-1019,-1047,-1078,-1111,-1145,-1179,-1214,-1248,-1281,
+-1314,-1346,-1377,-1407,-1436,-1464,-1493,-1524,-1556,-1589,-1622,-1653,-1681,-1706,-1730,-1755,-1780,-1807,-1832,-1853,-1872,
+-1887,-1903,-1921,-1942,-1966,-1991,-2015,-2036,-2053,-2069,-2085,-2101,-2118,-2135,-2152,-2170,-2188,-2207,-2226,-2244,-2260,
+-2275,-2289,-2305,-2322,-2341,-2360,-2377,-2391,-2402,-2414,-2426,-2441,-2457,-2471,-2484,-2494,-2503,-2511,-2520,-2530,-2539,
+-2546,-2551,-2555,-2558,-2561,-2563,-2565,-2566,-2565,-2564,-2564,-2566,-2569,-2570,-2569,-2565,-2559,-2554,-2551,-2550,-2549,
+-2546,-2540,-2533,-2527,-2525,-2527,-2531,-2534,-2533,-2529,-2525,-2523,-2525,-2531,-2536,-2539,-2536,-2531,-2526,-2524,-2525,
+-2527,-2525,-2518,-2505,-2489,-2474,-2465,-2461,-2461,-2461,-2458,-2450,-2434,-2413,-2389,-2362,-2336,-2314,-2296,-2283,-2273,
+-2264,-2255,-2245,-2237,-2232,-2230,-2230,-2229,-2222,-2209,-2193,-2179,-2171,-2170,-2175,-2179,-2180,-2175,-2170,-2171,-2184,
+-2209,-2242,-2273,-2296,-2304,-2301,-2290,-2279,-2270,-2266,-2264,-2264,-2267,-2274,-2286,-2303,-2320,-2334,-2341,-2343,-2341,
+-2340,-2343,-2348,-2354,-2358,-2361,-2366,-2376,-2392,-2412,-2430,-2439,-2437,-2427,-2416,-2413,-2420,-2436,-2454,-2469,-2480,
+-2495,-2520,-2560,-2612,-2667,-2710,-2734,-2737,-2731,-2729,-2740,-2767,-2804,-2840,-2868,-2886,-2899,-2914,-2938,-2971,-3010,
+-3048,-3083,-3111,-3131,-3140,-3132,-3107,-3065,-3015,-2968,-2937,-2928,-2940,-2965,-2994,-3024,-3053,-3084,-3120,-3160,-3201,
+-3236,-3264,-3288,-3313,-3344,-3383,-3425,-3462,-3489,-3506,-3517,-3528,-3545,-3567,-3588,-3603,-3609,-3607,-3603,-3603,-3608,
+-3617,-3624,-3626,-3620,-3610,-3599,-3592,-3589,-3589,-3589,-3588,-3586,-3586,-3588,-3593,-3600,-3607,-3612,-3616,-3621,-3625,
+-3630,-3635,-3638,-3640,-3640,-3642,-3646,-3654,-3664,-3674,-3683,-3688,-3689,-3687,-3681,-3673,-3664,-3657,-3652,-3649,-3649,
+-3649,-3647,-3642,-3635,-3628,-3620,-3614,-3607,-3597,-3583,-3566,-3548,-3531,-3517,-3506,-3496,-3486,-3474,-3461,-3449,-3440,
+-3434,-3430,-3425,-3417,-3405,-3392,-3378,-3367,-3357,-3348,-3337,-3322,-3302,-3281,-3259,-3240,-3226,-3215,-3206,-3199,-3193,
+-3187,-3183,-3179,-3175,-3170,-3161,-3149,-3132,-3112,-3090,-3068,-3048,-3030,-3015,-3000,-2987,-2974,-2962,-2949,-2936,-2923,
+-2909,-2894,-2877,-2860,-2843,-2824,-2806,-2787,-2768,-2749,-2731,-2715,-2700,-2688,-2676,-2666,-2656,-2646,-2637,-2628,-2620,
+-2612,-2603,-2594,-2583,-2571,-2556,-2539,-2522,-2504,-2489,-2476,-2466,-2457,-2450,-2442,-2434,-2426,-2416,-2407,-2397,-2387,
+-2378,-2370,-2365,-2361,-2358,-2355,-2352,-2346,-2339,-2330,-2323,-2316,-2311,-2307,-2301,-2293,-2283,-2274,-2267,-2262,-2261,
+-2262,-2262,-2259,-2252,-2241,-2226,-2209,-2193,-2178,-2164,-2151,-2138,-2125,-2111,-2097,-2085,-2073,-2063,-2052,-2039,-2023,
+-2007,-1990,-1975,-1963,-1956,-1951,-1949,-1947,-1945,-1944,-1942,-1942,-1942,-1942,-1943,-1943,-1943,-1943,-1941,-1939,-1937,
+-1934,-1930,-1928,-1927,-1926,-1926,-1924,-1920,-1914,-1906,-1899,-1893,-1888,-1884,-1881,-1876,-1871,-1864,-1857,-1848,-1838,
+-1826,-1814,-1803,-1795,-1791,-1790,-1790,-1787,-1779,-1764,-1742,-1717,-1691,-1667,-1646,-1629,-1614,-1600,-1588,-1574,-1559,
+-1542,-1521,-1495,-1467,-1436,-1408,-1384,-1367,-1359,-1357,-1359,-1364,-1368,-1370,-1370,-1369,-1367,-1366,-1365,-1367,-1369,
+-1372,-1374,-1375,-1374,-1372,-1370,-1368,-1367,-1368,-1371,-1375,-1380,-1385,-1390,-1394,-1398,-1401,-1404,-1405,-1406,-1406,
+-1407,-1408,-1410,-1412,-1416,-1421,-1425,-1429,-1432,-1433,-1434,-1433,-1431,-1429,-1428,-1427,-1426,-1425,-1424,-1421,-1418,
+-1415,-1412,-1409,-1408,-1408,-1407,-1406,-1404,-1400,-1393,-1385,-1374,-1363,-1349,-1335,-1320,-1304,-1288,-1272,-1256,-1240,
+-1224,-1210,-1199,-1191,-1187,-1186,-1185,-1183,-1176,-1164,-1148,-1132,-1120,-1114,-1115,-1119,-1121,-1116,-1102,-1079,-1053,
+-1030,-1016,-1013,-1021,-1037,-1057,-1076,-1091,-1102,-1107,-1106,-1098,-1085,-1065,-1041,-1015,-988,-963,-939,-919,-901,
+-886,-872,-858,-842,-824,-803,-780,-757,-736,-716,-698,-681,-665,-649,-634,-621,-609,-597,-584,-568,-548,
+-526,-501,-475,-447,-420,-391,-364,-339,-317,-300,-286,-274,-262,-248,-232,-215,-197,-176,-152,-124,-91,
+-56,-20,12,42,69,95,121,149,178,209,239,269,296,321,344,365,385,405,425,444,462,
+478,489,496,497,492,483,468,449,427,404,383,368,360,361,374,397,433,485,556,646,756,
+879,1006,1126,1230,1311,1367,1400,1417,1426,1435,1453,1481,1520,1562,1597,1614,1607,1572,1513,1442,1371,
+1314,1278,1266,1272,1288,1305,1318,1327,1335,1348,1368,1398,1433,1468,1499,1525,1548,1571,1598,1629,1664,
+1699,1731,1756,1776,1791,1803,1812,1818,1820,1819,1815,1808,1798,1787,1773,1759,1747,1741,1743,1754,1771,
+1788,1798,1795,1779,1753,1724,1697,1679,1669,1668,1671,1675,1679,1682,1685,1689,1695,1702,1710,1719,1727,
+1734,1739,1739,1737,1732,1725,1719,1715,1715,1718,1722,1724,1724,1720,1712,1701,1689,1678,1669,1666,1667,
+1673,1681,1691,1698,1701,1700,1697,1694,1695,1699,1707,1714,1720,1725,1732,1743,1760,1781,1801,1814,1815,
+1806,1790,1776,1772,1780,1798,1821,1843,1859,1872,1886,1907,1937,1976,2019,2059,2088,2102,2100,2086,2066,
+2046,2034,2032,2042,2063,2087,2111,2127,2131,2121,2099,2069,2035,2001,1971,1946,1924,1904,1885,1869,1857,
+1852,1850,1843,1816,1747,1621,1429,1179,898,625,404,272,252,344,529,772,1035,1280,1483,1632,1733,
+1797,1843,1883,1923,1963,1995,2013,2014,2004,1992,1985,1991,2006,2025,2039,2045,2042,2033,2025,2021,2021,
+2023,2025,2027,2031,2037,2049,2066,2083,2100,2114,2126,2136,2148,2162,2176,2188,2197,2204,2209,2214,2219,
+2224,2228,2232,2236,2241,2250,2260,2273,2285,2297,2307,2317,2327,2337,2349,2362,2377,2394,2413,2432,2450,
+2465,2479,2493,2507,2521,2535,2543,2545,2539,2531,2525,2526,2536,2550,2562,2566,2559,2544,2525,2508,2496,
+2490,2487,2487,2488,2490,2495,2500,2504,2503,2494,2478,2443,2430,2417,2408,2401,2396,2391,2387,2385,2387,
+2394,2405,2417,2427,2433,2432,2426,2416,2401,2383,2361,2335,2307,2278,2250,2224,2200,2180,2165,2155,2150,
+2149,2152,2157,2163,2170,2179,2188,2198,2206,2210,2210,2208,2207,2209,2214,2223,2233,2243,2253,2264,2280,
+2301,2328,2357,2385,2411,2433,2454,2475,2499,2526,2557,2589,2621,2651,2677,2698,2715,2730,2746,2767,2794,
+2827,2860,2890,2912,2925,2931,2936,2943,2956,2974,2993,3011,3026,3039,3050,3063,3078,3093,3106,3117,3124,
+3126,3124,3116,3103,3088,3077,3075,3085,3107,3136,3161,3176,3175,3162,3146,3138,3145,3166,3197,3228,3253,
+3269,3279,3291,3309,3334,3364,3392,3417,3437,3454,3473,3496,3521,3547,3569,3587,3600,3611,3624,3639,3656,
+3674,3692,3710,3727,3745,3764,3785,3805,3824,3843,3861,3879,3897,3917,3936,3956,3976,3997,4018,4040,4063,
+4083,4099,4111,4119,4124,4129,4134,4141,4147,4152,4154,4151,4147,4140,4134,4130,4127,4126,4126,4127,4128,
+4130,4133,4137,4139,4141,4141,4141,4141,4141,4142,4140,4136,4127,4114,4099,4082,4066,4051,4036,4019,4002,
+3985,3969,3955,3943,3933,3922,3910,3896,3882,3870,3861,3856,3854,3851,3847,3839,3829,3817,3805,3794,3784,
+3775,3767,3759,3752,3745,3739,3734,3729,3723,3716,3708,3697,3685,3672,3659,3645,3630,3613,3596,3580,3566,
+3557,3552,3551,3549,3545,3537,3526,3514,3503,3496,3492,3488,3486,3486,3489,3500,3519,3544,3569,3590,3601,
+3602,3593,3575,3553,3528,3502,3477,3456,3441,3431,3425,3418,3408,3393,3375,3360,3349,3346,3347,3349,3349,
+3347,3342,3339,3340,3342,3343,3338,3326,3308,3287,3268,3253,3240,3226,3206,3180,3150,3119,3093,3075,3063,
+3054,3045,3031,3012,2989,2962,2933,2900,2863,2820,2772,2718,2662,2604,2548,2493,2439,2387,2333,2276,2217,
+2156,2096,2042,1999,1969,1952,1945,1940,1932,1915,1889,1856,1823,1795,1774,1762,1754,1745,1731,1710,1683,
+1652,1622,1595,1570,1547,1523,1498,1471,1444,1418,1393,1369,1346,1322,1295,1266,1234,1201,1168,1135,1103,
+1073,1044,1015,985,954,920,885,849,814,780,748,717,686,654,621,589,558,530,503,478,451,
+422,389,353,316,278,239,201,164,127,92,60,29,0,-28,-56,-84,-112,-138,-165,-193,-224,
+-259,-298,-339,-380,-417,-448,-476,-501,-527,-555,-586,-617,-649,-680,-710,-740,-773,-807,-842,-875,-905,
+-931,-952,-973,-994,-1019,-1047,-1079,-1113,-1147,-1181,-1215,-1248,-1281,-1315,-1348,-1381,-1413,-1444,-1473,-1502,-1531,
+-1561,-1592,-1622,-1650,-1677,-1702,-1727,-1753,-1780,-1807,-1833,-1855,-1873,-1889,-1904,-1922,-1943,-1968,-1993,-2017,-2039,
+-2058,-2074,-2090,-2106,-2123,-2141,-2159,-2179,-2199,-2219,-2238,-2256,-2273,-2288,-2303,-2319,-2336,-2353,-2369,-2384,-2396,
+-2408,-2421,-2436,-2453,-2470,-2486,-2499,-2510,-2519,-2529,-2540,-2550,-2558,-2565,-2569,-2572,-2577,-2581,-2586,-2589,-2589,
+-2588,-2587,-2588,-2590,-2594,-2597,-2597,-2594,-2590,-2586,-2584,-2584,-2582,-2578,-2572,-2565,-2559,-2558,-2561,-2566,-2569,
+-2567,-2563,-2558,-2555,-2557,-2562,-2566,-2568,-2566,-2561,-2559,-2559,-2562,-2565,-2564,-2557,-2544,-2528,-2515,-2507,-2505,
+-2507,-2508,-2507,-2500,-2487,-2467,-2442,-2414,-2386,-2360,-2340,-2326,-2317,-2310,-2302,-2293,-2284,-2279,-2278,-2278,-2277,
+-2270,-2255,-2237,-2220,-2211,-2211,-2219,-2226,-2227,-2219,-2208,-2202,-2207,-2226,-2257,-2290,-2317,-2333,-2336,-2331,-2324,
+-2316,-2309,-2302,-2296,-2294,-2299,-2313,-2333,-2354,-2371,-2381,-2383,-2383,-2385,-2392,-2401,-2408,-2409,-2406,-2404,-2410,
+-2425,-2446,-2465,-2473,-2467,-2453,-2443,-2450,-2478,-2522,-2567,-2602,-2617,-2618,-2614,-2619,-2638,-2669,-2703,-2730,-2747,
+-2755,-2764,-2780,-2807,-2840,-2873,-2902,-2926,-2948,-2974,-3006,-3044,-3084,-3122,-3154,-3179,-3197,-3207,-3204,-3188,-3159,
+-3125,-3095,-3080,-3084,-3105,-3135,-3166,-3193,-3218,-3243,-3272,-3304,-3338,-3366,-3388,-3406,-3424,-3449,-3481,-3517,-3550,
+-3575,-3592,-3603,-3615,-3632,-3651,-3670,-3682,-3685,-3683,-3681,-3683,-3691,-3702,-3711,-3713,-3707,-3695,-3683,-3675,-3671,
+-3669,-3668,-3665,-3661,-3659,-3662,-3670,-3681,-3692,-3700,-3704,-3704,-3703,-3703,-3705,-3709,-3713,-3716,-3720,-3725,-3730,
+-3737,-3744,-3750,-3752,-3752,-3747,-3741,-3733,-3726,-3720,-3716,-3715,-3713,-3712,-3709,-3704,-3699,-3694,-3689,-3684,-3677,
+-3666,-3652,-3634,-3616,-3599,-3585,-3574,-3564,-3553,-3540,-3527,-3513,-3502,-3493,-3486,-3480,-3473,-3464,-3454,-3444,-3435,
+-3427,-3416,-3403,-3385,-3364,-3341,-3320,-3301,-3286,-3274,-3263,-3253,-3242,-3232,-3225,-3219,-3215,-3211,-3204,-3193,-3177,
+-3155,-3131,-3105,-3082,-3061,-3044,-3030,-3018,-3008,-2998,-2988,-2979,-2969,-2959,-2947,-2933,-2918,-2900,-2881,-2860,-2839,
+-2817,-2796,-2775,-2755,-2738,-2722,-2709,-2697,-2687,-2677,-2668,-2660,-2652,-2646,-2640,-2634,-2627,-2617,-2606,-2592,-2576,
+-2561,-2546,-2534,-2523,-2512,-2501,-2489,-2476,-2464,-2452,-2440,-2430,-2421,-2412,-2404,-2398,-2394,-2392,-2390,-2388,-2383,
+-2375,-2366,-2355,-2345,-2336,-2328,-2319,-2309,-2299,-2291,-2286,-2287,-2292,-2299,-2306,-2308,-2302,-2290,-2271,-2251,-2230,
+-2212,-2197,-2184,-2171,-2157,-2144,-2130,-2117,-2104,-2093,-2080,-2067,-2053,-2039,-2026,-2015,-2007,-2001,-1997,-1993,-1989,
+-1986,-1984,-1983,-1984,-1985,-1986,-1987,-1987,-1986,-1985,-1982,-1980,-1976,-1972,-1969,-1966,-1965,-1966,-1967,-1966,-1963,
+-1959,-1952,-1945,-1939,-1932,-1925,-1916,-1905,-1894,-1882,-1872,-1864,-1857,-1852,-1848,-1845,-1845,-1846,-1849,-1851,-1849,
+-1842,-1828,-1809,-1787,-1765,-1745,-1729,-1717,-1707,-1699,-1691,-1683,-1674,-1662,-1645,-1622,-1593,-1561,-1528,-1499,-1477,
+-1461,-1451,-1445,-1441,-1437,-1432,-1426,-1421,-1417,-1414,-1412,-1412,-1412,-1412,-1412,-1412,-1413,-1414,-1416,-1418,-1420,
+-1421,-1423,-1424,-1425,-1426,-1429,-1432,-1436,-1440,-1444,-1447,-1449,-1451,-1451,-1451,-1449,-1446,-1443,-1440,-1438,-1437,
+-1439,-1441,-1445,-1447,-1450,-1451,-1451,-1451,-1450,-1449,-1447,-1444,-1441,-1438,-1436,-1435,-1436,-1437,-1437,-1437,-1434,
+-1430,-1423,-1415,-1405,-1393,-1380,-1365,-1349,-1332,-1315,-1298,-1281,-1265,-1248,-1234,-1222,-1214,-1210,-1209,-1210,-1209,
+-1204,-1194,-1181,-1167,-1155,-1147,-1143,-1141,-1136,-1127,-1111,-1092,-1072,-1055,-1046,-1044,-1048,-1057,-1069,-1082,-1095,
+-1106,-1113,-1115,-1108,-1094,-1072,-1046,-1019,-992,-968,-946,-928,-914,-903,-896,-888,-879,-865,-846,-823,-798,
+-776,-757,-742,-729,-716,-701,-686,-670,-655,-640,-625,-608,-586,-559,-529,-497,-466,-436,-407,-380,-355,
+-333,-313,-297,-284,-271,-259,-244,-228,-209,-189,-168,-145,-120,-91,-59,-24,10,43,73,100,125,
+150,176,205,235,265,293,317,337,355,373,393,415,439,462,481,496,505,511,512,510,505,
+496,484,472,460,450,442,435,430,430,440,469,524,609,723,859,1004,1143,1263,1353,1412,1443,
+1455,1458,1464,1477,1500,1527,1551,1562,1555,1527,1483,1431,1381,1343,1322,1318,1327,1343,1361,1378,1396,
+1415,1438,1466,1498,1530,1560,1586,1608,1629,1651,1677,1704,1732,1757,1777,1793,1806,1819,1833,1848,1864,
+1878,1887,1889,1883,1867,1843,1813,1783,1759,1748,1753,1773,1803,1833,1853,1855,1840,1811,1777,1746,1723,
+1712,1710,1714,1719,1722,1723,1723,1725,1731,1742,1757,1775,1791,1802,1805,1800,1790,1778,1770,1766,1767,
+1768,1768,1762,1750,1735,1720,1710,1705,1705,1707,1710,1713,1715,1718,1723,1729,1733,1734,1730,1725,1720,
+1720,1726,1737,1750,1762,1771,1778,1786,1798,1814,1832,1846,1854,1855,1852,1851,1856,1869,1888,1907,1920,
+1925,1921,1916,1915,1923,1940,1963,1986,2005,2017,2026,2033,2042,2055,2071,2087,2100,2110,2117,2122,2127,
+2134,2140,2145,2147,2146,2144,2141,2136,2130,2118,2100,2080,2064,2060,2073,2096,2114,2102,2032,1884,1654,
+1358,1032,721,471,320,286,365,539,774,1031,1275,1480,1636,1743,1812,1857,1892,1924,1953,1975,1990,
+1997,2000,2006,2016,2030,2044,2052,2051,2042,2029,2018,2013,2013,2016,2019,2021,2023,2027,2037,2053,2073,
+2093,2108,2117,2122,2127,2133,2141,2153,2164,2174,2180,2182,2183,2183,2183,2187,2192,2201,2213,2226,2240,
+2254,2268,2280,2291,2301,2310,2321,2334,2351,2372,2394,2414,2431,2445,2457,2471,2490,2512,2533,2549,2553,
+2547,2534,2522,2518,2523,2534,2545,2549,2541,2525,2503,2483,2468,2458,2453,2451,2451,2452,2456,2460,2462,
+2461,2454,2443,2404,2392,2380,2368,2355,2343,2333,2326,2326,2333,2346,2363,2377,2386,2385,2376,2361,2342,
+2320,2296,2271,2245,2219,2195,2174,2159,2148,2140,2136,2133,2132,2132,2133,2136,2138,2141,2143,2144,2146,
+2146,2147,2149,2151,2155,2161,2167,2174,2181,2188,2198,2211,2230,2253,2280,2307,2332,2356,2379,2403,2429,
+2458,2490,2521,2552,2579,2604,2625,2644,2663,2683,2707,2734,2765,2796,2824,2845,2859,2866,2873,2882,2897,
+2917,2938,2955,2967,2973,2978,2987,3002,3021,3042,3058,3067,3068,3062,3054,3045,3037,3033,3033,3039,3053,
+3073,3095,3113,3121,3120,3111,3102,3102,3113,3136,3165,3192,3214,3230,3244,3260,3282,3310,3340,3368,3392,
+3412,3430,3449,3471,3493,3515,3532,3544,3553,3561,3572,3587,3605,3624,3643,3662,3681,3701,3721,3742,3763,
+3781,3798,3814,3830,3846,3864,3881,3899,3918,3936,3956,3977,3996,4014,4028,4039,4047,4053,4058,4063,4068,
+4073,4077,4080,4081,4080,4077,4074,4069,4065,4062,4062,4065,4070,4077,4083,4086,4086,4085,4082,4080,4079,
+4080,4081,4079,4074,4065,4052,4036,4020,4005,3990,3975,3961,3947,3932,3919,3907,3896,3886,3874,3861,3847,
+3832,3819,3809,3802,3798,3794,3789,3781,3770,3758,3746,3736,3729,3725,3722,3719,3714,3708,3702,3696,3692,
+3689,3684,3676,3665,3652,3638,3626,3615,3606,3595,3583,3570,3557,3547,3540,3536,3531,3523,3512,3498,3485,
+3477,3473,3474,3477,3479,3482,3488,3499,3518,3544,3572,3596,3614,3623,3624,3619,3611,3600,3587,3573,3558,
+3546,3537,3528,3517,3500,3474,3442,3408,3378,3356,3344,3339,3340,3342,3347,3354,3362,3370,3374,3368,3353,
+3329,3301,3276,3257,3241,3225,3205,3179,3149,3120,3097,3080,3068,3055,3036,3008,2976,2944,2917,2896,2879,
+2861,2834,2796,2746,2688,2626,2564,2503,2445,2387,2330,2272,2216,2161,2110,2062,2020,1985,1959,1941,1930,
+1920,1908,1887,1859,1823,1787,1754,1729,1712,1701,1691,1678,1659,1636,1609,1581,1554,1528,1503,1478,1454,
+1430,1409,1389,1370,1350,1328,1302,1272,1239,1204,1168,1133,1099,1067,1037,1008,978,948,915,880,844,
+807,772,738,705,674,643,612,582,552,522,493,464,435,404,372,338,304,269,231,193,153,
+113,75,39,7,-23,-51,-78,-104,-129,-152,-175,-200,-230,-265,-304,-346,-387,-422,-453,-480,-505,
+-533,-564,-598,-631,-662,-691,-717,-743,-772,-804,-839,-873,-904,-931,-954,-975,-997,-1022,-1052,-1086,-1122,
+-1157,-1192,-1224,-1256,-1287,-1319,-1352,-1386,-1419,-1451,-1482,-1513,-1542,-1570,-1598,-1625,-1650,-1675,-1699,-1724,-1751,
+-1779,-1807,-1833,-1857,-1877,-1894,-1912,-1930,-1951,-1974,-1998,-2022,-2043,-2063,-2080,-2097,-2114,-2131,-2149,-2168,-2187,
+-2208,-2228,-2248,-2266,-2283,-2299,-2315,-2331,-2348,-2363,-2378,-2391,-2404,-2418,-2433,-2449,-2467,-2482,-2496,-2507,-2518,
+-2530,-2544,-2558,-2570,-2579,-2584,-2587,-2589,-2593,-2600,-2607,-2612,-2615,-2615,-2615,-2615,-2617,-2620,-2622,-2622,-2620,
+-2618,-2616,-2617,-2618,-2618,-2615,-2609,-2602,-2595,-2593,-2594,-2596,-2597,-2596,-2592,-2589,-2588,-2590,-2594,-2597,-2597,
+-2594,-2591,-2590,-2593,-2599,-2603,-2603,-2596,-2583,-2569,-2556,-2549,-2547,-2549,-2551,-2551,-2546,-2536,-2519,-2496,-2467,
+-2437,-2409,-2385,-2369,-2358,-2350,-2342,-2334,-2326,-2321,-2321,-2324,-2324,-2319,-2304,-2285,-2266,-2255,-2255,-2261,-2269,
+-2270,-2262,-2249,-2238,-2238,-2252,-2279,-2311,-2339,-2357,-2365,-2365,-2360,-2352,-2343,-2332,-2322,-2318,-2323,-2338,-2362,
+-2386,-2405,-2415,-2417,-2418,-2422,-2430,-2440,-2445,-2442,-2435,-2430,-2435,-2452,-2474,-2493,-2498,-2490,-2478,-2481,-2512,
+-2573,-2654,-2728,-2774,-2777,-2742,-2690,-2646,-2628,-2642,-2679,-2725,-2765,-2793,-2812,-2829,-2849,-2876,-2906,-2938,-2969,
+-3000,-3033,-3070,-3107,-3142,-3173,-3198,-3220,-3240,-3257,-3269,-3271,-3264,-3250,-3237,-3231,-3238,-3258,-3284,-3311,-3335,
+-3355,-3375,-3399,-3427,-3457,-3484,-3505,-3521,-3535,-3552,-3575,-3602,-3629,-3653,-3671,-3686,-3699,-3713,-3727,-3739,-3747,
+-3750,-3750,-3752,-3759,-3770,-3781,-3789,-3789,-3781,-3770,-3759,-3753,-3751,-3750,-3748,-3744,-3739,-3736,-3738,-3746,-3758,
+-3769,-3776,-3779,-3778,-3775,-3775,-3779,-3785,-3792,-3798,-3804,-3808,-3811,-3814,-3817,-3817,-3816,-3812,-3806,-3799,-3792,
+-3786,-3782,-3780,-3778,-3776,-3773,-3769,-3765,-3760,-3757,-3753,-3749,-3743,-3734,-3722,-3708,-3692,-3677,-3664,-3651,-3639,
+-3626,-3611,-3596,-3580,-3565,-3553,-3543,-3535,-3528,-3522,-3518,-3513,-3507,-3499,-3488,-3472,-3451,-3428,-3406,-3385,-3368,
+-3355,-3343,-3332,-3319,-3305,-3291,-3278,-3266,-3257,-3249,-3241,-3229,-3214,-3195,-3172,-3149,-3126,-3106,-3090,-3076,-3064,
+-3053,-3043,-3032,-3022,-3012,-3002,-2991,-2979,-2965,-2948,-2931,-2911,-2891,-2871,-2850,-2829,-2809,-2789,-2770,-2754,-2739,
+-2727,-2717,-2707,-2698,-2690,-2681,-2674,-2666,-2658,-2651,-2642,-2633,-2624,-2615,-2607,-2597,-2587,-2575,-2560,-2544,-2528,
+-2512,-2498,-2487,-2476,-2467,-2456,-2446,-2435,-2427,-2421,-2417,-2415,-2412,-2408,-2402,-2395,-2387,-2378,-2370,-2360,-2350,
+-2341,-2333,-2329,-2330,-2335,-2343,-2351,-2354,-2350,-2339,-2323,-2303,-2283,-2264,-2247,-2231,-2215,-2198,-2181,-2165,-2150,
+-2138,-2126,-2115,-2104,-2092,-2081,-2070,-2062,-2055,-2050,-2045,-2041,-2036,-2032,-2029,-2029,-2030,-2031,-2032,-2033,-2032,
+-2030,-2028,-2026,-2024,-2021,-2018,-2015,-2012,-2010,-2008,-2007,-2004,-1999,-1993,-1987,-1980,-1974,-1968,-1961,-1953,-1942,
+-1931,-1919,-1909,-1901,-1894,-1888,-1882,-1876,-1871,-1868,-1866,-1866,-1864,-1860,-1853,-1843,-1832,-1821,-1811,-1803,-1795,
+-1789,-1782,-1777,-1772,-1768,-1763,-1755,-1742,-1724,-1703,-1678,-1654,-1632,-1613,-1596,-1581,-1565,-1550,-1535,-1521,-1509,
+-1500,-1492,-1485,-1478,-1470,-1462,-1456,-1452,-1452,-1457,-1464,-1473,-1480,-1485,-1485,-1483,-1479,-1475,-1472,-1471,-1472,
+-1475,-1478,-1483,-1489,-1495,-1501,-1505,-1506,-1503,-1496,-1486,-1477,-1469,-1465,-1463,-1465,-1467,-1470,-1473,-1474,-1475,
+-1475,-1474,-1472,-1468,-1465,-1462,-1461,-1461,-1464,-1466,-1468,-1468,-1466,-1461,-1455,-1448,-1439,-1428,-1415,-1399,-1381,
+-1361,-1342,-1323,-1305,-1289,-1273,-1259,-1247,-1237,-1230,-1227,-1226,-1224,-1220,-1212,-1202,-1190,-1179,-1170,-1163,-1156,
+-1147,-1136,-1122,-1106,-1092,-1081,-1075,-1073,-1074,-1078,-1083,-1091,-1100,-1109,-1117,-1119,-1114,-1101,-1081,-1056,-1030,
+-1004,-980,-959,-942,-929,-920,-915,-911,-903,-890,-871,-846,-820,-797,-779,-766,-756,-747,-735,-720,-704,
+-689,-675,-661,-644,-621,-591,-556,-519,-483,-451,-424,-400,-378,-357,-336,-316,-299,-283,-269,-254,-238,
+-220,-201,-181,-161,-138,-113,-83,-50,-15,18,49,75,99,121,144,171,201,231,260,285,307,
+327,347,369,394,421,447,470,489,504,517,528,537,543,547,548,547,545,543,540,534,524,
+512,501,499,517,561,638,743,868,1001,1126,1233,1316,1376,1417,1446,1469,1489,1506,1515,1515,1502,
+1479,1450,1420,1396,1381,1375,1376,1381,1388,1395,1403,1414,1430,1453,1481,1511,1541,1568,1591,1612,1633,
+1657,1683,1711,1739,1764,1783,1795,1803,1809,1818,1830,1849,1872,1898,1921,1938,1942,1931,1905,1867,1826,
+1790,1769,1766,1782,1808,1835,1853,1856,1844,1822,1798,1778,1766,1763,1765,1768,1768,1763,1754,1743,1735,
+1734,1744,1763,1789,1816,1835,1844,1842,1833,1822,1817,1819,1827,1834,1835,1825,1805,1781,1760,1748,1748,
+1756,1768,1778,1783,1783,1779,1775,1771,1766,1760,1751,1741,1732,1730,1737,1750,1766,1781,1792,1799,1805,
+1811,1822,1836,1851,1862,1870,1874,1877,1884,1896,1912,1929,1943,1951,1953,1951,1949,1950,1955,1965,1975,
+1986,1998,2011,2029,2050,2075,2099,2118,2130,2136,2139,2142,2149,2160,2174,2188,2198,2206,2210,2214,2216,
+2214,2204,2184,2157,2128,2110,2109,2127,2154,2170,2150,2068,1912,1684,1402,1098,811,578,429,383,442,
+592,807,1051,1291,1497,1654,1760,1826,1865,1893,1919,1944,1968,1989,2006,2020,2032,2042,2047,2047,2039,
+2026,2011,1999,1994,1995,2001,2007,2013,2017,2024,2036,2054,2076,2097,2112,2120,2121,2119,2119,2123,2132,
+2143,2153,2159,2161,2160,2160,2162,2168,2178,2190,2202,2214,2227,2240,2253,2267,2280,2292,2302,2311,2324,
+2340,2361,2383,2404,2420,2431,2440,2452,2469,2491,2514,2532,2540,2537,2527,2516,2511,2515,2525,2535,2541,
+2537,2525,2509,2492,2479,2468,2460,2452,2444,2437,2432,2428,2425,2420,2414,2404,2360,2348,2334,2319,2304,
+2290,2279,2275,2278,2288,2303,2318,2327,2326,2315,2296,2273,2248,2224,2203,2184,2165,2150,2137,2128,2122,
+2120,2118,2115,2110,2105,2099,2094,2090,2087,2086,2084,2083,2083,2085,2090,2096,2103,2110,2116,2120,2123,
+2127,2133,2143,2160,2181,2205,2230,2254,2276,2298,2323,2351,2383,2418,2453,2486,2514,2537,2557,2576,2597,
+2620,2647,2677,2708,2738,2764,2784,2797,2805,2812,2822,2838,2859,2881,2900,2912,2916,2917,2920,2931,2949,
+2973,2995,3010,3014,3009,2999,2989,2984,2986,2992,3001,3012,3023,3036,3048,3057,3063,3064,3064,3066,3074,
+3090,3112,3137,3161,3181,3197,3213,3231,3254,3281,3310,3337,3362,3385,3407,3429,3450,3469,3483,3491,3496,
+3500,3507,3518,3535,3554,3575,3595,3615,3635,3656,3678,3700,3720,3739,3755,3770,3786,3802,3821,3840,3860,
+3879,3898,3915,3932,3946,3959,3970,3979,3988,3995,4002,4006,4009,4011,4013,4016,4019,4022,4023,4022,4017,
+4011,4005,4003,4006,4012,4021,4028,4032,4033,4031,4029,4027,4027,4026,4025,4020,4013,4003,3990,3977,3964,
+3950,3936,3922,3908,3893,3879,3865,3851,3839,3827,3815,3804,3793,3781,3770,3759,3750,3743,3736,3730,3722,
+3713,3703,3694,3688,3686,3688,3691,3692,3689,3681,3672,3662,3655,3649,3644,3638,3629,3619,3608,3598,3592,
+3587,3582,3574,3564,3551,3539,3527,3518,3508,3497,3485,3473,3465,3461,3464,3468,3472,3474,3474,3476,3485,
+3503,3529,3559,3589,3612,3629,3639,3645,3648,3648,3644,3636,3626,3617,3609,3602,3593,3576,3548,3511,3468,
+3427,3396,3378,3373,3376,3384,3394,3404,3411,3415,3411,3397,3373,3341,3306,3275,3250,3230,3211,3190,3165,
+3140,3117,3102,3093,3085,3072,3046,3008,2963,2920,2887,2868,2859,2853,2842,2818,2781,2732,2677,2619,2558,
+2495,2428,2358,2289,2223,2164,2113,2069,2030,1996,1967,1943,1926,1913,1901,1884,1858,1824,1783,1742,1706,
+1680,1663,1653,1644,1634,1618,1597,1572,1545,1517,1489,1462,1436,1413,1393,1375,1357,1339,1318,1293,1265,
+1233,1198,1162,1126,1090,1056,1024,994,965,936,905,872,837,801,764,728,693,661,630,601,573,
+546,518,488,457,424,390,356,324,291,258,224,186,145,103,61,22,-11,-42,-69,-94,-118,
+-141,-164,-186,-211,-240,-273,-311,-351,-389,-425,-456,-485,-514,-545,-578,-612,-645,-675,-701,-724,-747,
+-774,-805,-838,-872,-903,-930,-953,-975,-998,-1025,-1057,-1094,-1132,-1169,-1204,-1236,-1265,-1294,-1323,-1354,-1385,
+-1418,-1451,-1484,-1516,-1546,-1576,-1603,-1629,-1653,-1677,-1701,-1726,-1753,-1781,-1808,-1834,-1858,-1879,-1898,-1918,-1938,
+-1959,-1982,-2005,-2027,-2048,-2069,-2088,-2106,-2123,-2140,-2158,-2176,-2195,-2215,-2235,-2254,-2272,-2289,-2305,-2321,-2338,
+-2355,-2371,-2386,-2400,-2414,-2430,-2446,-2464,-2480,-2494,-2504,-2514,-2524,-2537,-2553,-2570,-2586,-2596,-2603,-2606,-2608,
+-2613,-2620,-2628,-2636,-2640,-2642,-2642,-2643,-2645,-2648,-2650,-2650,-2648,-2647,-2647,-2649,-2651,-2653,-2652,-2647,-2640,
+-2634,-2629,-2627,-2627,-2626,-2624,-2623,-2622,-2624,-2627,-2631,-2632,-2630,-2626,-2623,-2623,-2627,-2633,-2637,-2637,-2631,
+-2619,-2606,-2595,-2589,-2587,-2588,-2590,-2590,-2586,-2578,-2564,-2543,-2516,-2487,-2458,-2435,-2418,-2406,-2397,-2388,-2379,
+-2370,-2365,-2365,-2368,-2370,-2366,-2353,-2333,-2314,-2302,-2300,-2306,-2314,-2316,-2309,-2295,-2282,-2277,-2284,-2304,-2330,
+-2356,-2375,-2386,-2389,-2388,-2381,-2371,-2359,-2348,-2343,-2350,-2368,-2393,-2419,-2437,-2446,-2447,-2448,-2453,-2462,-2471,
+-2475,-2470,-2462,-2458,-2465,-2484,-2508,-2525,-2527,-2519,-2514,-2534,-2594,-2692,-2807,-2903,-2949,-2931,-2857,-2757,-2671,
+-2626,-2633,-2680,-2744,-2803,-2843,-2863,-2873,-2883,-2903,-2931,-2967,-3006,-3045,-3085,-3123,-3160,-3192,-3219,-3240,-3260,
+-3281,-3305,-3330,-3351,-3364,-3368,-3367,-3366,-3372,-3386,-3407,-3432,-3455,-3475,-3495,-3516,-3540,-3567,-3592,-3612,-3626,
+-3636,-3646,-3659,-3678,-3699,-3722,-3743,-3761,-3775,-3787,-3796,-3803,-3808,-3812,-3815,-3821,-3830,-3840,-3849,-3853,-3851,
+-3844,-3836,-3831,-3829,-3830,-3831,-3830,-3827,-3822,-3819,-3819,-3824,-3832,-3840,-3845,-3847,-3848,-3848,-3852,-3857,-3865,
+-3872,-3878,-3882,-3884,-3885,-3885,-3884,-3882,-3878,-3872,-3865,-3857,-3851,-3845,-3842,-3839,-3836,-3834,-3830,-3827,-3823,
+-3819,-3815,-3812,-3809,-3805,-3799,-3791,-3782,-3770,-3757,-3744,-3730,-3715,-3700,-3683,-3666,-3649,-3634,-3619,-3607,-3597,
+-3589,-3583,-3579,-3576,-3571,-3564,-3552,-3536,-3516,-3495,-3474,-3455,-3439,-3427,-3416,-3404,-3391,-3376,-3360,-3343,-3326,
+-3311,-3298,-3285,-3271,-3256,-3239,-3221,-3201,-3182,-3164,-3148,-3133,-3120,-3107,-3095,-3082,-3070,-3057,-3045,-3033,-3019,
+-3004,-2988,-2970,-2953,-2936,-2920,-2904,-2887,-2870,-2852,-2833,-2814,-2797,-2781,-2768,-2756,-2745,-2735,-2723,-2712,-2700,
+-2689,-2680,-2673,-2667,-2663,-2659,-2655,-2648,-2639,-2627,-2612,-2595,-2579,-2564,-2552,-2541,-2532,-2522,-2510,-2496,-2482,
+-2468,-2457,-2450,-2445,-2442,-2440,-2436,-2432,-2427,-2422,-2416,-2411,-2405,-2398,-2393,-2388,-2386,-2387,-2390,-2394,-2396,
+-2395,-2389,-2380,-2367,-2353,-2338,-2323,-2306,-2287,-2267,-2246,-2226,-2208,-2192,-2178,-2165,-2154,-2142,-2131,-2121,-2112,
+-2105,-2099,-2093,-2088,-2084,-2081,-2079,-2079,-2080,-2081,-2081,-2081,-2079,-2076,-2073,-2070,-2068,-2065,-2062,-2059,-2055,
+-2051,-2046,-2041,-2034,-2027,-2020,-2013,-2007,-2002,-1997,-1992,-1986,-1979,-1972,-1965,-1958,-1951,-1944,-1934,-1923,-1910,
+-1897,-1886,-1878,-1872,-1868,-1865,-1862,-1858,-1853,-1848,-1843,-1837,-1831,-1824,-1818,-1812,-1808,-1807,-1808,-1810,-1811,
+-1810,-1807,-1801,-1792,-1780,-1766,-1748,-1729,-1707,-1685,-1664,-1645,-1630,-1617,-1605,-1593,-1578,-1561,-1542,-1525,-1512,
+-1506,-1507,-1514,-1524,-1535,-1542,-1545,-1545,-1542,-1539,-1535,-1533,-1531,-1529,-1528,-1528,-1532,-1538,-1547,-1555,-1561,
+-1562,-1558,-1548,-1537,-1525,-1515,-1509,-1505,-1504,-1504,-1505,-1507,-1508,-1508,-1506,-1502,-1498,-1493,-1489,-1487,-1488,
+-1491,-1494,-1496,-1496,-1494,-1489,-1483,-1476,-1468,-1458,-1444,-1426,-1405,-1383,-1361,-1342,-1325,-1311,-1299,-1287,-1276,
+-1264,-1254,-1245,-1238,-1231,-1226,-1219,-1211,-1203,-1195,-1188,-1181,-1173,-1164,-1153,-1140,-1126,-1115,-1105,-1099,-1096,
+-1095,-1096,-1098,-1103,-1109,-1116,-1121,-1122,-1117,-1105,-1087,-1064,-1040,-1015,-991,-970,-953,-940,-932,-927,-924,
+-917,-904,-884,-858,-832,-808,-790,-778,-769,-759,-747,-732,-717,-702,-690,-678,-664,-644,-616,-582,-545,
+-510,-479,-454,-431,-410,-387,-362,-338,-314,-294,-277,-261,-246,-229,-211,-190,-168,-144,-118,-90,-61,
+-31,-2,24,48,70,91,114,139,166,195,223,249,273,297,321,347,373,399,424,446,468,
+488,509,530,550,568,581,589,595,599,604,610,617,620,619,613,605,601,609,637,686,755,
+840,932,1025,1115,1200,1280,1353,1418,1470,1502,1511,1496,1462,1421,1384,1361,1357,1368,1389,1412,1428,
+1436,1439,1440,1446,1460,1482,1508,1534,1558,1578,1595,1613,1634,1660,1690,1722,1752,1778,1798,1812,1821,
+1829,1837,1847,1862,1883,1908,1935,1959,1974,1976,1961,1934,1899,1864,1838,1823,1820,1823,1827,1827,1821,
+1812,1804,1800,1803,1812,1823,1831,1833,1826,1809,1785,1759,1737,1725,1726,1742,1768,1797,1821,1834,1837,
+1832,1827,1829,1841,1859,1876,1885,1881,1864,1839,1817,1802,1800,1807,1818,1827,1830,1826,1818,1809,1800,
+1791,1780,1768,1755,1745,1742,1746,1758,1774,1790,1803,1812,1819,1827,1838,1853,1870,1884,1893,1897,1896,
+1895,1897,1905,1919,1936,1954,1970,1982,1989,1994,1997,2000,2005,2013,2025,2040,2059,2080,2103,2123,2141,
+2155,2166,2177,2189,2203,2218,2232,2242,2247,2247,2246,2245,2246,2245,2240,2227,2204,2176,2150,2134,2130,
+2137,2144,2135,2094,2006,1864,1669,1433,1175,922,705,554,492,530,660,860,1094,1325,1523,1670,1766,
+1824,1859,1887,1915,1944,1973,1996,2013,2023,2029,2030,2027,2019,2008,1996,1985,1981,1982,1989,1998,2007,
+2017,2028,2043,2061,2082,2102,2117,2125,2125,2121,2117,2117,2122,2130,2138,2144,2147,2148,2151,2157,2168,
+2180,2193,2203,2211,2218,2227,2239,2254,2271,2285,2297,2308,2319,2334,2354,2377,2401,2419,2431,2438,2443,
+2451,2464,2480,2494,2504,2506,2503,2498,2497,2501,2510,2518,2522,2519,2510,2496,2482,2468,2456,2445,2433,
+2421,2409,2399,2390,2384,2378,2370,2360,2314,2301,2287,2271,2255,2241,2232,2229,2234,2245,2258,2269,2273,
+2267,2251,2228,2202,2177,2155,2138,2123,2112,2102,2094,2088,2083,2077,2069,2060,2048,2035,2024,2016,2011,
+2009,2010,2013,2018,2024,2032,2041,2050,2059,2065,2069,2070,2072,2076,2084,2098,2118,2142,2166,2189,2209,
+2228,2248,2273,2303,2340,2379,2418,2452,2479,2500,2518,2536,2557,2582,2611,2641,2670,2696,2716,2731,2742,
+2752,2763,2779,2798,2819,2838,2852,2859,2863,2867,2876,2893,2915,2938,2956,2965,2963,2954,2945,2940,2943,
+2951,2963,2974,2983,2989,2994,2998,3003,3008,3013,3020,3030,3044,3063,3086,3109,3131,3151,3168,3185,3204,
+3226,3250,3276,3303,3329,3354,3379,3403,3422,3437,3444,3447,3447,3449,3457,3470,3489,3510,3530,3550,3570,
+3590,3611,3633,3655,3676,3694,3711,3728,3745,3764,3786,3808,3830,3852,3870,3886,3898,3907,3914,3920,3927,
+3936,3944,3951,3956,3957,3956,3955,3957,3960,3965,3969,3969,3966,3961,3955,3953,3954,3960,3966,3972,3976,
+3977,3976,3975,3975,3975,3972,3968,3961,3952,3942,3933,3924,3915,3904,3891,3877,3862,3847,3833,3819,3806,
+3793,3781,3771,3762,3753,3742,3729,3714,3700,3686,3677,3670,3666,3662,3659,3656,3655,3656,3660,3664,3665,
+3662,3652,3639,3625,3613,3605,3601,3597,3593,3587,3581,3575,3572,3569,3566,3559,3549,3536,3521,3507,3494,
+3483,3473,3465,3459,3456,3459,3464,3469,3471,3469,3465,3463,3469,3484,3508,3537,3564,3586,3602,3611,3618,
+3620,3619,3614,3604,3593,3584,3579,3579,3579,3574,3556,3527,3489,3452,3424,3409,3408,3416,3428,3439,3444,
+3443,3434,3418,3392,3359,3321,3282,3248,3220,3198,3179,3160,3139,3118,3102,3092,3088,3084,3072,3048,3009,
+2962,2917,2881,2861,2852,2849,2842,2825,2796,2759,2716,2669,2618,2558,2489,2411,2329,2248,2176,2115,2064,
+2021,1982,1948,1918,1894,1878,1867,1856,1840,1814,1780,1741,1702,1669,1645,1631,1623,1616,1607,1593,1573,
+1547,1518,1487,1456,1428,1403,1381,1361,1341,1320,1298,1273,1245,1215,1183,1150,1116,1081,1046,1014,983,
+954,927,899,869,836,802,765,728,691,656,622,591,563,535,508,479,448,414,378,344,310,
+278,247,214,177,136,92,48,7,-27,-57,-82,-105,-128,-152,-176,-202,-230,-260,-292,-328,-364,
+-401,-436,-468,-499,-530,-561,-593,-625,-656,-683,-708,-731,-755,-783,-814,-846,-878,-908,-934,-957,-979,
+-1004,-1033,-1066,-1103,-1141,-1177,-1211,-1242,-1270,-1298,-1327,-1356,-1387,-1418,-1451,-1483,-1516,-1547,-1577,-1604,-1630,
+-1654,-1679,-1704,-1731,-1758,-1786,-1812,-1837,-1859,-1879,-1900,-1921,-1944,-1967,-1990,-2013,-2035,-2056,-2076,-2097,-2116,
+-2134,-2152,-2170,-2188,-2206,-2225,-2244,-2263,-2280,-2297,-2313,-2330,-2347,-2364,-2380,-2395,-2410,-2424,-2441,-2459,-2477,
+-2494,-2508,-2519,-2528,-2538,-2551,-2567,-2584,-2600,-2613,-2620,-2625,-2629,-2635,-2642,-2650,-2657,-2662,-2664,-2666,-2668,
+-2672,-2677,-2680,-2683,-2683,-2683,-2683,-2685,-2688,-2690,-2690,-2687,-2682,-2676,-2672,-2669,-2668,-2666,-2664,-2663,-2663,
+-2665,-2668,-2671,-2672,-2670,-2666,-2663,-2663,-2666,-2670,-2673,-2671,-2664,-2654,-2643,-2634,-2629,-2627,-2628,-2629,-2629,
+-2627,-2620,-2608,-2589,-2564,-2536,-2509,-2487,-2472,-2461,-2452,-2442,-2431,-2420,-2413,-2411,-2414,-2416,-2412,-2399,-2381,
+-2362,-2349,-2347,-2353,-2361,-2365,-2360,-2347,-2331,-2320,-2320,-2331,-2349,-2371,-2391,-2406,-2415,-2418,-2414,-2405,-2391,
+-2379,-2375,-2382,-2401,-2427,-2452,-2469,-2477,-2479,-2481,-2487,-2497,-2507,-2510,-2506,-2499,-2498,-2508,-2529,-2552,-2567,
+-2567,-2559,-2564,-2602,-2686,-2810,-2943,-3046,-3082,-3039,-2932,-2802,-2694,-2643,-2656,-2717,-2795,-2861,-2898,-2908,-2905,
+-2905,-2919,-2949,-2990,-3034,-3078,-3120,-3161,-3200,-3236,-3268,-3292,-3313,-3334,-3357,-3385,-3413,-3438,-3454,-3463,-3468,
+-3475,-3488,-3509,-3533,-3559,-3582,-3602,-3621,-3640,-3660,-3680,-3697,-3709,-3718,-3725,-3734,-3747,-3767,-3789,-3812,-3832,
+-3847,-3858,-3865,-3870,-3875,-3880,-3886,-3893,-3901,-3907,-3912,-3913,-3912,-3909,-3906,-3904,-3905,-3906,-3907,-3905,-3903,
+-3900,-3899,-3900,-3903,-3908,-3912,-3917,-3920,-3924,-3929,-3935,-3941,-3947,-3950,-3951,-3950,-3949,-3948,-3947,-3946,-3944,
+-3940,-3934,-3926,-3918,-3910,-3904,-3899,-3895,-3891,-3889,-3887,-3885,-3883,-3880,-3876,-3873,-3869,-3865,-3860,-3855,-3849,
+-3840,-3829,-3816,-3801,-3785,-3768,-3752,-3736,-3721,-3706,-3691,-3677,-3663,-3651,-3641,-3633,-3625,-3618,-3611,-3601,-3590,
+-3576,-3561,-3545,-3528,-3513,-3499,-3485,-3471,-3457,-3442,-3426,-3409,-3390,-3372,-3354,-3337,-3321,-3306,-3290,-3274,-3258,
+-3240,-3223,-3206,-3190,-3174,-3160,-3146,-3133,-3119,-3106,-3092,-3078,-3062,-3044,-3026,-3008,-2990,-2974,-2961,-2949,-2938,
+-2926,-2912,-2896,-2878,-2860,-2842,-2825,-2810,-2797,-2783,-2769,-2754,-2740,-2726,-2715,-2706,-2699,-2695,-2692,-2688,-2682,
+-2673,-2662,-2649,-2636,-2623,-2611,-2601,-2592,-2584,-2574,-2562,-2549,-2535,-2522,-2510,-2500,-2493,-2488,-2483,-2477,-2472,
+-2466,-2462,-2460,-2459,-2458,-2457,-2455,-2451,-2446,-2442,-2439,-2438,-2438,-2439,-2439,-2437,-2433,-2427,-2419,-2409,-2396,
+-2380,-2360,-2338,-2315,-2292,-2270,-2250,-2233,-2218,-2204,-2190,-2178,-2167,-2158,-2151,-2145,-2140,-2136,-2134,-2132,-2132,
+-2132,-2133,-2133,-2132,-2129,-2125,-2121,-2116,-2112,-2107,-2103,-2098,-2093,-2087,-2080,-2073,-2065,-2058,-2051,-2044,-2038,
+-2032,-2026,-2020,-2014,-2009,-2004,-2000,-1997,-1993,-1987,-1978,-1967,-1953,-1939,-1927,-1916,-1907,-1900,-1893,-1886,-1879,
+-1870,-1861,-1853,-1844,-1836,-1829,-1822,-1817,-1814,-1813,-1816,-1821,-1829,-1839,-1848,-1857,-1863,-1864,-1860,-1850,-1835,
+-1817,-1798,-1780,-1763,-1750,-1738,-1728,-1715,-1700,-1680,-1658,-1634,-1614,-1598,-1589,-1587,-1590,-1596,-1603,-1609,-1615,
+-1621,-1626,-1630,-1632,-1631,-1625,-1617,-1608,-1601,-1598,-1600,-1604,-1609,-1612,-1610,-1603,-1594,-1583,-1573,-1565,-1559,
+-1555,-1553,-1553,-1553,-1553,-1552,-1549,-1543,-1536,-1529,-1522,-1519,-1519,-1521,-1523,-1524,-1523,-1520,-1514,-1507,-1500,
+-1490,-1478,-1462,-1443,-1421,-1398,-1377,-1358,-1344,-1333,-1324,-1315,-1305,-1294,-1281,-1269,-1258,-1247,-1239,-1231,-1223,
+-1217,-1211,-1205,-1199,-1193,-1185,-1176,-1165,-1153,-1141,-1131,-1122,-1117,-1113,-1112,-1112,-1114,-1117,-1119,-1120,-1117,
+-1109,-1096,-1079,-1059,-1036,-1012,-989,-968,-951,-939,-932,-929,-928,-923,-913,-896,-873,-847,-824,-804,-789,
+-776,-762,-747,-730,-713,-698,-686,-676,-666,-651,-631,-605,-576,-547,-519,-495,-470,-445,-416,-385,-353,
+-324,-300,-280,-265,-252,-237,-219,-197,-172,-145,-119,-93,-69,-46,-24,-3,18,40,62,86,111,
+136,162,187,213,239,265,292,319,345,368,389,410,431,455,484,514,545,572,593,607,616,
+623,631,645,663,684,702,715,720,717,711,708,711,727,755,797,852,920,1001,1092,1190,1286,
+1369,1429,1458,1455,1426,1385,1349,1328,1329,1350,1383,1416,1442,1459,1468,1476,1488,1505,1528,1551,1572,
+1588,1601,1614,1630,1651,1678,1709,1741,1771,1798,1823,1844,1864,1880,1894,1905,1914,1923,1934,1949,1965,
+1980,1989,1991,1984,1970,1951,1930,1909,1888,1865,1841,1818,1799,1790,1793,1808,1832,1857,1879,1892,1892,
+1880,1856,1825,1793,1764,1743,1736,1742,1758,1778,1795,1806,1809,1807,1808,1816,1835,1859,1883,1898,1900,
+1888,1868,1847,1832,1826,1829,1835,1840,1841,1838,1833,1826,1818,1810,1800,1788,1776,1767,1763,1767,1778,
+1793,1809,1823,1835,1845,1856,1871,1888,1907,1923,1934,1937,1933,1927,1921,1923,1932,1950,1972,1995,2014,
+2026,2032,2034,2035,2040,2049,2062,2077,2094,2110,2125,2139,2153,2168,2185,2203,2221,2239,2255,2268,2276,
+2279,2279,2276,2273,2272,2272,2271,2268,2259,2246,2229,2211,2193,2176,2157,2131,2092,2033,1945,1821,1657,
+1454,1226,993,786,638,577,615,745,940,1164,1379,1558,1688,1774,1827,1864,1895,1925,1952,1974,1989,
+1996,1999,2001,2002,2002,2000,1996,1990,1986,1984,1987,1995,2005,2017,2031,2046,2063,2081,2098,2111,2119,
+2121,2118,2114,2111,2113,2117,2123,2129,2133,2136,2141,2149,2160,2172,2183,2191,2195,2199,2207,2219,2236,
+2256,2274,2289,2300,2310,2324,2344,2370,2397,2420,2435,2441,2441,2439,2440,2446,2455,2465,2473,2477,2478,
+2479,2481,2483,2483,2480,2471,2457,2441,2424,2408,2395,2383,2374,2365,2357,2350,2344,2339,2332,2325,2314,
+2262,2250,2237,2223,2210,2199,2191,2188,2191,2199,2208,2216,2219,2214,2202,2184,2164,2143,2124,2108,2093,
+2080,2068,2056,2044,2031,2017,2002,1987,1972,1959,1950,1944,1943,1945,1951,1959,1969,1979,1990,2000,2008,
+2013,2017,2018,2020,2025,2033,2047,2065,2087,2111,2134,2154,2172,2188,2206,2230,2260,2298,2339,2379,2415,
+2443,2464,2481,2498,2517,2541,2568,2596,2622,2643,2661,2675,2689,2705,2723,2742,2760,2776,2788,2797,2804,
+2813,2826,2845,2867,2888,2904,2912,2911,2906,2900,2898,2903,2914,2926,2937,2944,2946,2947,2948,2950,2955,
+2961,2969,2979,2992,3010,3031,3056,3081,3104,3124,3142,3158,3176,3197,3220,3244,3270,3296,3322,3346,3368,
+3384,3395,3400,3402,3403,3409,3419,3434,3452,3472,3491,3509,3527,3545,3565,3586,3607,3627,3646,3664,3683,
+3703,3726,3750,3774,3797,3819,3838,3852,3862,3868,3873,3877,3883,3890,3898,3904,3907,3906,3902,3898,3897,
+3899,3904,3910,3914,3915,3914,3912,3911,3914,3918,3922,3925,3926,3926,3926,3926,3925,3923,3919,3912,3903,
+3894,3887,3881,3876,3869,3859,3846,3830,3814,3800,3787,3776,3765,3755,3745,3737,3729,3720,3708,3691,3672,
+3651,3633,3621,3616,3617,3622,3626,3628,3629,3630,3631,3633,3632,3628,3618,3604,3588,3575,3566,3561,3560,
+3559,3558,3555,3552,3549,3546,3541,3534,3523,3510,3495,3482,3472,3463,3457,3453,3451,3451,3454,3458,3461,
+3461,3458,3454,3452,3456,3467,3483,3500,3514,3523,3525,3524,3520,3513,3503,3488,3470,3453,3442,3440,3449,
+3464,3475,3477,3466,3445,3420,3401,3393,3397,3408,3420,3428,3427,3418,3401,3377,3347,3311,3273,3235,3202,
+3176,3157,3142,3128,3113,3096,3081,3070,3063,3056,3044,3023,2991,2953,2915,2886,2868,2859,2853,2843,2824,
+2796,2762,2725,2689,2650,2604,2546,2475,2395,2311,2231,2160,2097,2042,1991,1943,1899,1863,1838,1823,1814,
+1805,1792,1770,1740,1705,1672,1645,1627,1617,1612,1607,1597,1579,1554,1522,1487,1452,1420,1393,1369,1347,
+1325,1301,1274,1246,1217,1187,1158,1129,1099,1068,1038,1007,978,951,924,898,870,841,809,775,738,
+701,663,625,589,555,524,494,464,433,398,362,325,290,255,222,188,152,111,68,25,-13,
+-47,-74,-96,-116,-138,-162,-190,-220,-251,-284,-317,-351,-385,-420,-454,-487,-518,-548,-577,-605,-632,
+-659,-684,-709,-734,-762,-791,-823,-856,-887,-916,-941,-965,-990,-1017,-1047,-1081,-1116,-1150,-1183,-1214,-1243,
+-1272,-1302,-1333,-1364,-1396,-1428,-1460,-1491,-1522,-1551,-1579,-1605,-1630,-1653,-1678,-1705,-1733,-1762,-1791,-1817,-1841,
+-1862,-1882,-1904,-1927,-1951,-1976,-2000,-2023,-2044,-2064,-2085,-2105,-2125,-2145,-2164,-2182,-2200,-2219,-2238,-2257,-2275,
+-2293,-2309,-2325,-2342,-2359,-2376,-2392,-2407,-2421,-2435,-2450,-2468,-2487,-2506,-2522,-2537,-2549,-2560,-2572,-2586,-2601,
+-2615,-2626,-2635,-2642,-2648,-2655,-2663,-2671,-2677,-2682,-2685,-2689,-2693,-2699,-2706,-2713,-2717,-2720,-2721,-2723,-2725,
+-2727,-2729,-2729,-2727,-2724,-2721,-2719,-2718,-2716,-2714,-2711,-2709,-2707,-2707,-2709,-2711,-2711,-2711,-2709,-2707,-2708,
+-2710,-2712,-2712,-2708,-2701,-2692,-2682,-2673,-2668,-2666,-2666,-2668,-2669,-2669,-2665,-2654,-2636,-2612,-2584,-2558,-2537,
+-2522,-2512,-2503,-2493,-2480,-2468,-2460,-2458,-2459,-2461,-2458,-2446,-2428,-2410,-2396,-2393,-2398,-2407,-2413,-2410,-2398,
+-2382,-2368,-2360,-2363,-2375,-2393,-2413,-2433,-2448,-2456,-2455,-2445,-2429,-2415,-2408,-2413,-2431,-2455,-2479,-2496,-2505,
+-2509,-2513,-2522,-2534,-2544,-2548,-2546,-2542,-2544,-2556,-2578,-2599,-2610,-2609,-2604,-2617,-2670,-2771,-2907,-3043,-3137,
+-3155,-3088,-2960,-2818,-2710,-2669,-2700,-2777,-2864,-2929,-2957,-2954,-2939,-2933,-2947,-2981,-3026,-3071,-3113,-3151,-3190,
+-3233,-3278,-3320,-3354,-3379,-3398,-3415,-3436,-3462,-3489,-3514,-3533,-3547,-3559,-3574,-3594,-3619,-3645,-3668,-3688,-3704,
+-3719,-3734,-3750,-3766,-3780,-3792,-3802,-3812,-3827,-3845,-3866,-3887,-3905,-3919,-3928,-3934,-3940,-3946,-3954,-3961,-3968,
+-3973,-3976,-3977,-3979,-3980,-3982,-3984,-3985,-3984,-3981,-3978,-3974,-3972,-3972,-3974,-3978,-3982,-3986,-3990,-3994,-3999,
+-4006,-4014,-4020,-4024,-4025,-4023,-4019,-4015,-4012,-4011,-4011,-4010,-4008,-4003,-3997,-3988,-3979,-3970,-3962,-3955,-3950,
+-3946,-3944,-3944,-3945,-3945,-3944,-3941,-3937,-3932,-3927,-3921,-3916,-3910,-3902,-3891,-3879,-3865,-3850,-3835,-3819,-3804,
+-3789,-3774,-3758,-3742,-3726,-3710,-3694,-3680,-3668,-3658,-3650,-3644,-3638,-3633,-3625,-3615,-3601,-3585,-3567,-3549,-3531,
+-3514,-3498,-3482,-3466,-3448,-3429,-3409,-3390,-3372,-3355,-3340,-3325,-3310,-3294,-3277,-3259,-3242,-3226,-3210,-3196,-3183,
+-3170,-3157,-3142,-3126,-3109,-3090,-3070,-3050,-3031,-3014,-3000,-2988,-2979,-2970,-2960,-2948,-2934,-2917,-2900,-2882,-2865,
+-2848,-2833,-2817,-2802,-2786,-2771,-2757,-2745,-2736,-2728,-2722,-2716,-2708,-2700,-2690,-2680,-2670,-2661,-2652,-2644,-2636,
+-2628,-2619,-2609,-2599,-2589,-2579,-2570,-2562,-2554,-2546,-2538,-2529,-2521,-2513,-2507,-2504,-2504,-2506,-2508,-2508,-2506,
+-2501,-2495,-2489,-2485,-2484,-2485,-2487,-2489,-2490,-2490,-2488,-2484,-2478,-2468,-2455,-2436,-2414,-2388,-2363,-2339,-2317,
+-2298,-2282,-2267,-2252,-2239,-2227,-2218,-2210,-2203,-2198,-2194,-2190,-2187,-2185,-2184,-2183,-2182,-2179,-2176,-2171,-2165,
+-2160,-2155,-2150,-2144,-2138,-2131,-2123,-2115,-2106,-2099,-2091,-2084,-2077,-2068,-2060,-2050,-2042,-2035,-2029,-2025,-2021,
+-2018,-2014,-2009,-2003,-1996,-1989,-1981,-1972,-1963,-1953,-1942,-1929,-1915,-1901,-1887,-1873,-1863,-1854,-1848,-1845,-1842,
+-1840,-1837,-1835,-1834,-1836,-1842,-1850,-1860,-1870,-1877,-1880,-1880,-1875,-1868,-1859,-1850,-1842,-1835,-1829,-1824,-1817,
+-1809,-1797,-1782,-1763,-1743,-1723,-1706,-1694,-1686,-1683,-1685,-1691,-1700,-1712,-1725,-1737,-1744,-1746,-1740,-1729,-1714,
+-1699,-1687,-1679,-1674,-1672,-1669,-1664,-1657,-1649,-1640,-1631,-1623,-1617,-1613,-1609,-1607,-1605,-1604,-1601,-1597,-1590,
+-1581,-1572,-1565,-1561,-1559,-1559,-1560,-1559,-1557,-1552,-1545,-1536,-1526,-1513,-1498,-1480,-1460,-1439,-1418,-1398,-1381,
+-1367,-1356,-1346,-1337,-1328,-1318,-1308,-1298,-1288,-1278,-1268,-1259,-1250,-1241,-1233,-1226,-1220,-1215,-1210,-1204,-1195,
+-1185,-1174,-1162,-1151,-1142,-1134,-1129,-1126,-1123,-1120,-1115,-1108,-1099,-1088,-1075,-1059,-1041,-1022,-1000,-978,-957,
+-939,-927,-921,-919,-920,-919,-913,-901,-883,-861,-838,-817,-797,-779,-762,-743,-724,-705,-690,-677,-667,
+-658,-648,-635,-618,-599,-578,-555,-531,-504,-473,-439,-402,-367,-334,-308,-288,-273,-260,-245,-228,-206,
+-180,-153,-128,-104,-85,-68,-51,-34,-14,8,34,61,87,112,136,159,183,209,237,265,292,
+316,338,357,377,398,424,455,490,526,559,586,607,621,633,645,662,685,714,746,776,799,
+814,819,818,813,808,808,814,830,858,902,963,1040,1129,1218,1296,1351,1379,1380,1363,1341,1325,
+1324,1339,1366,1398,1429,1456,1479,1501,1525,1551,1577,1600,1618,1632,1643,1656,1673,1696,1723,1752,1780,
+1807,1832,1858,1885,1912,1936,1956,1968,1972,1971,1966,1963,1963,1967,1975,1984,1992,1997,1997,1989,1973,
+1948,1915,1879,1847,1823,1815,1822,1842,1869,1896,1916,1926,1925,1914,1895,1872,1847,1825,1807,1797,1794,
+1797,1804,1809,1812,1812,1812,1816,1827,1846,1868,1888,1899,1900,1890,1875,1859,1848,1844,1846,1850,1854,
+1856,1855,1853,1849,1843,1835,1825,1814,1803,1794,1791,1793,1802,1814,1827,1839,1851,1862,1873,1887,1904,
+1922,1939,1953,1961,1964,1962,1960,1962,1969,1983,2002,2021,2036,2045,2049,2050,2054,2061,2073,2088,2104,
+2117,2128,2138,2149,2162,2178,2196,2214,2231,2246,2260,2274,2288,2300,2309,2314,2316,2314,2310,2307,2304,
+2302,2298,2290,2278,2259,2233,2198,2157,2107,2049,1977,1886,1767,1614,1427,1217,1005,824,704,669,727,
+866,1057,1267,1460,1616,1728,1802,1850,1884,1912,1935,1953,1964,1969,1971,1975,1982,1991,1999,2003,2002,
+1997,1990,1987,1988,1995,2006,2020,2034,2049,2064,2079,2092,2101,2107,2108,2106,2105,2106,2109,2115,2121,
+2125,2129,2132,2137,2143,2151,2159,2167,2173,2179,2188,2202,2220,2239,2258,2273,2284,2295,2309,2329,2356,
+2385,2410,2427,2431,2427,2419,2413,2414,2423,2436,2449,2457,2460,2457,2450,2441,2431,2418,2403,2386,2367,
+2348,2332,2319,2311,2306,2304,2302,2300,2296,2290,2283,2273,2262,2206,2196,2188,2181,2173,2166,2160,2157,
+2156,2158,2162,2165,2166,2163,2156,2145,2131,2116,2100,2084,2067,2050,2034,2016,1999,1982,1965,1951,1939,
+1930,1925,1923,1922,1923,1925,1928,1934,1942,1951,1960,1967,1971,1974,1975,1978,1983,1992,2004,2020,2039,
+2059,2080,2100,2119,2136,2154,2173,2197,2226,2262,2301,2340,2373,2399,2419,2436,2453,2474,2500,2530,2558,
+2583,2603,2619,2635,2652,2672,2693,2714,2729,2739,2744,2749,2757,2773,2795,2819,2841,2855,2858,2852,2844,
+2839,2842,2853,2870,2887,2900,2906,2906,2904,2903,2907,2913,2922,2930,2938,2946,2959,2978,3002,3031,3059,
+3084,3104,3121,3135,3152,3171,3194,3220,3246,3271,3294,3314,3329,3341,3350,3355,3361,3367,3377,3390,3406,
+3424,3441,3457,3473,3490,3508,3526,3544,3562,3579,3596,3615,3635,3658,3682,3707,3731,3753,3773,3791,3805,
+3816,3824,3831,3836,3843,3850,3857,3863,3864,3861,3856,3849,3846,3845,3849,3854,3860,3864,3867,3869,3872,
+3877,3881,3884,3886,3886,3886,3886,3886,3885,3882,3875,3866,3856,3847,3841,3837,3833,3825,3814,3798,3781,
+3765,3752,3742,3734,3726,3718,3708,3699,3689,3679,3665,3648,3627,3606,3588,3577,3576,3582,3591,3599,3604,
+3604,3602,3600,3599,3597,3593,3585,3573,3559,3547,3537,3532,3531,3531,3531,3530,3527,3524,3519,3513,3505,
+3494,3482,3471,3461,3454,3450,3447,3445,3442,3440,3439,3439,3439,3439,3438,3438,3438,3440,3442,3442,3438,
+3430,3418,3404,3390,3377,3364,3346,3324,3297,3271,3254,3252,3265,3289,3316,3337,3345,3340,3329,3318,3314,
+3318,3327,3336,3340,3337,3328,3312,3293,3269,3240,3210,3178,3151,3130,3116,3107,3100,3091,3079,3065,3050,
+3036,3023,3007,2986,2960,2930,2901,2879,2866,2859,2853,2842,2821,2791,2755,2720,2688,2657,2625,2585,2534,
+2472,2402,2330,2259,2192,2127,2062,1997,1934,1877,1832,1800,1780,1768,1757,1742,1720,1692,1664,1639,1622,
+1614,1612,1611,1603,1585,1556,1518,1476,1434,1398,1370,1347,1326,1304,1278,1249,1216,1183,1152,1124,1098,
+1073,1049,1024,1000,975,950,924,898,870,841,811,779,746,710,673,633,593,555,518,484,452,
+418,382,343,302,262,222,185,149,112,74,34,-4,-38,-68,-91,-110,-128,-148,-172,-201,-233,
+-268,-302,-335,-369,-402,-436,-468,-500,-530,-558,-584,-610,-635,-659,-684,-710,-737,-766,-797,-828,-860,
+-890,-918,-944,-971,-998,-1028,-1061,-1095,-1128,-1159,-1188,-1215,-1243,-1272,-1304,-1339,-1373,-1408,-1440,-1471,-1501,
+-1530,-1557,-1583,-1608,-1631,-1654,-1678,-1705,-1734,-1764,-1794,-1820,-1844,-1866,-1887,-1909,-1933,-1959,-1985,-2009,-2031,
+-2051,-2070,-2089,-2110,-2131,-2152,-2173,-2192,-2210,-2229,-2248,-2268,-2287,-2305,-2323,-2339,-2356,-2373,-2390,-2406,-2420,
+-2434,-2447,-2460,-2476,-2494,-2514,-2532,-2550,-2565,-2578,-2591,-2603,-2616,-2628,-2638,-2648,-2656,-2665,-2674,-2683,-2692,
+-2701,-2708,-2713,-2718,-2724,-2731,-2738,-2744,-2748,-2752,-2754,-2756,-2759,-2761,-2763,-2764,-2763,-2762,-2761,-2760,-2760,
+-2759,-2758,-2755,-2751,-2748,-2746,-2746,-2747,-2748,-2748,-2749,-2749,-2749,-2750,-2751,-2750,-2747,-2740,-2732,-2722,-2712,
+-2704,-2700,-2698,-2701,-2706,-2710,-2710,-2702,-2685,-2660,-2632,-2604,-2582,-2567,-2556,-2548,-2537,-2525,-2514,-2506,-2503,
+-2505,-2508,-2506,-2496,-2480,-2461,-2446,-2440,-2442,-2449,-2455,-2455,-2448,-2435,-2421,-2411,-2407,-2412,-2424,-2442,-2462,
+-2480,-2491,-2492,-2482,-2465,-2447,-2437,-2438,-2453,-2475,-2498,-2516,-2527,-2535,-2543,-2554,-2567,-2578,-2583,-2583,-2582,
+-2587,-2602,-2622,-2640,-2646,-2643,-2641,-2663,-2727,-2838,-2979,-3112,-3193,-3192,-3107,-2966,-2821,-2720,-2694,-2740,-2830,
+-2924,-2988,-3010,-3000,-2982,-2978,-2999,-3041,-3091,-3136,-3171,-3200,-3231,-3272,-3321,-3372,-3416,-3447,-3465,-3477,-3490,
+-3510,-3537,-3567,-3594,-3617,-3634,-3650,-3667,-3687,-3709,-3730,-3749,-3765,-3780,-3797,-3815,-3835,-3855,-3872,-3888,-3903,
+-3918,-3934,-3951,-3966,-3978,-3988,-3994,-4001,-4009,-4018,-4027,-4035,-4040,-4041,-4041,-4041,-4045,-4051,-4059,-4065,-4067,
+-4065,-4058,-4051,-4045,-4043,-4045,-4050,-4056,-4060,-4064,-4067,-4071,-4077,-4084,-4092,-4097,-4099,-4097,-4093,-4089,-4085,
+-4084,-4083,-4082,-4080,-4075,-4069,-4061,-4052,-4043,-4034,-4024,-4016,-4009,-4004,-4002,-4002,-4003,-4005,-4005,-4003,-4000,
+-3995,-3989,-3983,-3977,-3970,-3961,-3952,-3941,-3929,-3917,-3903,-3888,-3872,-3854,-3836,-3819,-3801,-3784,-3767,-3750,-3733,
+-3719,-3706,-3697,-3691,-3688,-3686,-3682,-3675,-3663,-3646,-3627,-3606,-3586,-3567,-3550,-3534,-3517,-3499,-3479,-3459,-3438,
+-3419,-3402,-3386,-3372,-3358,-3343,-3327,-3311,-3294,-3278,-3263,-3249,-3235,-3222,-3207,-3191,-3174,-3155,-3136,-3117,-3098,
+-3079,-3061,-3045,-3030,-3018,-3008,-2999,-2990,-2979,-2966,-2951,-2934,-2917,-2901,-2885,-2869,-2854,-2838,-2822,-2806,-2792,
+-2780,-2770,-2760,-2751,-2742,-2732,-2723,-2714,-2706,-2698,-2690,-2683,-2676,-2668,-2661,-2653,-2646,-2638,-2631,-2623,-2616,
+-2609,-2601,-2593,-2585,-2575,-2567,-2560,-2555,-2553,-2553,-2554,-2554,-2552,-2548,-2542,-2536,-2532,-2531,-2532,-2534,-2535,
+-2536,-2536,-2536,-2537,-2536,-2534,-2528,-2516,-2499,-2478,-2456,-2434,-2415,-2398,-2383,-2368,-2353,-2338,-2322,-2308,-2296,
+-2285,-2275,-2266,-2257,-2248,-2241,-2236,-2233,-2230,-2227,-2223,-2219,-2213,-2209,-2205,-2201,-2198,-2193,-2186,-2177,-2168,
+-2158,-2149,-2139,-2130,-2120,-2110,-2098,-2088,-2078,-2069,-2061,-2055,-2048,-2042,-2037,-2032,-2030,-2027,-2025,-2021,-2016,
+-2008,-1997,-1986,-1973,-1959,-1946,-1933,-1921,-1912,-1905,-1903,-1902,-1902,-1899,-1894,-1885,-1875,-1865,-1857,-1853,-1854,
+-1856,-1861,-1865,-1869,-1873,-1876,-1878,-1880,-1880,-1879,-1877,-1875,-1874,-1874,-1874,-1871,-1865,-1855,-1842,-1827,-1812,
+-1800,-1791,-1787,-1788,-1791,-1798,-1805,-1812,-1817,-1819,-1816,-1810,-1802,-1793,-1785,-1778,-1771,-1765,-1757,-1748,-1737,
+-1726,-1714,-1703,-1693,-1684,-1676,-1669,-1664,-1659,-1655,-1650,-1644,-1636,-1628,-1620,-1614,-1610,-1608,-1607,-1606,-1604,
+-1600,-1595,-1587,-1576,-1563,-1547,-1529,-1509,-1488,-1469,-1450,-1433,-1418,-1402,-1387,-1372,-1358,-1347,-1338,-1332,-1328,
+-1323,-1318,-1310,-1300,-1289,-1277,-1266,-1256,-1249,-1244,-1241,-1237,-1231,-1223,-1212,-1199,-1186,-1173,-1161,-1152,-1143,
+-1133,-1122,-1110,-1097,-1083,-1071,-1059,-1048,-1036,-1021,-1002,-981,-958,-937,-919,-908,-902,-900,-899,-895,-887,
+-874,-858,-839,-819,-799,-779,-760,-741,-722,-705,-689,-675,-663,-652,-642,-631,-620,-607,-592,-573,-550,
+-523,-491,-456,-420,-385,-354,-328,-307,-290,-274,-257,-239,-217,-193,-169,-146,-126,-109,-95,-81,-64,
+-43,-18,9,39,66,91,114,136,158,183,210,239,267,292,316,337,358,381,407,436,469,
+503,538,570,599,623,644,663,683,706,734,768,803,839,871,898,918,933,943,949,950,948,
+946,950,965,998,1049,1117,1191,1262,1317,1351,1363,1361,1352,1347,1350,1365,1388,1417,1448,1480,1512,
+1544,1574,1603,1628,1650,1668,1686,1706,1729,1755,1782,1807,1831,1851,1871,1892,1916,1941,1964,1984,1996,
+1999,1994,1984,1973,1965,1961,1962,1969,1979,1989,1996,1997,1989,1973,1949,1922,1899,1883,1877,1882,1894,
+1909,1921,1928,1930,1926,1920,1913,1905,1898,1890,1883,1876,1871,1866,1862,1858,1855,1854,1856,1863,1875,
+1890,1905,1914,1917,1912,1903,1893,1886,1883,1884,1888,1892,1895,1896,1894,1891,1886,1879,1869,1858,1846,
+1835,1826,1822,1821,1824,1829,1835,1842,1849,1856,1865,1875,1888,1903,1920,1937,1952,1964,1973,1978,1984,
+1991,2001,2013,2025,2035,2043,2049,2055,2064,2076,2090,2105,2118,2127,2135,2144,2156,2172,2190,2208,2223,
+2235,2245,2257,2274,2295,2318,2339,2353,2359,2357,2350,2341,2332,2324,2315,2304,2291,2274,2252,2225,2189,
+2143,2086,2016,1932,1830,1705,1555,1381,1195,1016,872,790,788,868,1015,1200,1391,1559,1688,1776,1832,
+1868,1894,1917,1935,1948,1955,1960,1964,1972,1983,1995,2003,2003,1996,1985,1974,1969,1971,1979,1992,2006,
+2020,2034,2048,2063,2075,2085,2091,2094,2095,2098,2103,2110,2118,2124,2126,2126,2124,2123,2127,2134,2143,
+2154,2164,2175,2186,2198,2212,2226,2240,2252,2266,2283,2305,2331,2359,2382,2395,2397,2390,2379,2371,2372,
+2383,2399,2415,2425,2425,2416,2400,2382,2364,2348,2335,2322,2309,2295,2284,2275,2269,2267,2265,2263,2259,
+2251,2241,2228,2216,2206,2156,2151,2148,2146,2143,2141,2137,2133,2130,2126,2121,2115,2109,2102,2094,2085,
+2075,2064,2052,2038,2023,2007,1991,1975,1959,1945,1934,1927,1926,1928,1933,1937,1939,1937,1933,1928,1926,
+1927,1931,1937,1943,1947,1950,1952,1957,1965,1976,1989,2003,2018,2034,2051,2069,2089,2110,2132,2156,2181,
+2211,2243,2277,2309,2336,2357,2373,2388,2407,2433,2465,2501,2535,2562,2582,2595,2608,2624,2645,2667,2687,
+2700,2706,2707,2710,2721,2741,2768,2795,2813,2817,2808,2793,2780,2778,2790,2813,2839,2861,2872,2873,2870,
+2867,2871,2881,2895,2907,2915,2920,2925,2935,2954,2981,3014,3045,3071,3090,3104,3117,3132,3152,3177,3204,
+3231,3254,3272,3286,3296,3303,3310,3317,3325,3336,3349,3363,3379,3396,3412,3428,3445,3461,3478,3494,3509,
+3522,3535,3549,3566,3587,3610,3635,3659,3681,3702,3720,3736,3751,3764,3774,3784,3792,3800,3808,3816,3822,
+3825,3824,3820,3815,3810,3808,3809,3811,3814,3817,3819,3823,3828,3833,3839,3843,3846,3847,3849,3850,3851,
+3851,3848,3841,3831,3821,3812,3806,3801,3795,3786,3772,3755,3738,3724,3714,3707,3702,3694,3683,3670,3655,
+3641,3628,3615,3600,3584,3568,3556,3549,3550,3556,3565,3572,3574,3573,3569,3566,3565,3564,3562,3557,3548,
+3536,3524,3515,3509,3507,3506,3506,3505,3503,3499,3493,3486,3478,3468,3458,3449,3443,3440,3438,3437,3433,
+3428,3422,3415,3411,3410,3410,3413,3414,3413,3407,3395,3376,3351,3322,3294,3271,3254,3243,3234,3220,3197,
+3167,3135,3109,3099,3107,3130,3161,3190,3208,3214,3209,3201,3195,3194,3196,3199,3200,3198,3193,3187,3179,
+3169,3154,3136,3115,3095,3079,3070,3067,3066,3064,3058,3048,3035,3022,3007,2991,2970,2944,2915,2886,2863,
+2848,2840,2835,2827,2811,2784,2751,2714,2681,2651,2624,2597,2564,2523,2475,2420,2362,2301,2236,2165,2090,
+2012,1936,1867,1812,1771,1742,1720,1701,1679,1654,1629,1608,1596,1592,1596,1599,1594,1577,1545,1502,1452,
+1406,1366,1337,1316,1298,1278,1254,1223,1189,1154,1121,1093,1067,1045,1025,1005,986,965,943,918,891,
+861,829,797,766,734,701,666,629,590,551,513,478,443,408,369,327,281,235,190,149,111,
+76,42,7,-25,-55,-82,-103,-122,-140,-161,-185,-214,-247,-281,-315,-349,-382,-414,-445,-476,-506,
+-535,-562,-588,-614,-640,-666,-692,-720,-747,-776,-805,-836,-865,-893,-920,-946,-973,-1001,-1032,-1066,-1101,
+-1134,-1165,-1193,-1219,-1246,-1275,-1307,-1341,-1376,-1410,-1442,-1472,-1501,-1530,-1558,-1585,-1610,-1634,-1658,-1682,-1708,
+-1737,-1767,-1796,-1822,-1846,-1867,-1889,-1912,-1937,-1963,-1989,-2013,-2034,-2053,-2072,-2092,-2113,-2136,-2158,-2179,-2199,
+-2217,-2236,-2256,-2276,-2297,-2317,-2336,-2353,-2370,-2387,-2403,-2420,-2435,-2449,-2463,-2476,-2491,-2507,-2524,-2542,-2559,
+-2575,-2591,-2605,-2619,-2633,-2645,-2656,-2666,-2675,-2683,-2693,-2704,-2715,-2726,-2736,-2746,-2753,-2760,-2766,-2771,-2774,
+-2777,-2779,-2782,-2784,-2788,-2791,-2794,-2795,-2795,-2794,-2794,-2794,-2795,-2795,-2794,-2792,-2789,-2786,-2785,-2784,-2785,
+-2786,-2787,-2787,-2787,-2786,-2786,-2785,-2785,-2783,-2779,-2773,-2764,-2753,-2743,-2735,-2732,-2734,-2741,-2748,-2753,-2749,
+-2734,-2711,-2682,-2654,-2631,-2616,-2605,-2597,-2588,-2577,-2565,-2557,-2554,-2555,-2558,-2557,-2550,-2536,-2518,-2502,-2492,
+-2489,-2492,-2496,-2499,-2497,-2491,-2481,-2470,-2462,-2458,-2462,-2472,-2488,-2504,-2517,-2521,-2514,-2498,-2480,-2468,-2467,
+-2477,-2497,-2518,-2537,-2552,-2563,-2575,-2588,-2601,-2611,-2616,-2618,-2620,-2629,-2645,-2664,-2677,-2679,-2673,-2671,-2698,
+-2769,-2887,-3032,-3164,-3241,-3232,-3138,-2991,-2841,-2739,-2714,-2762,-2854,-2950,-3016,-3041,-3036,-3025,-3031,-3063,-3115,
+-3171,-3218,-3250,-3271,-3294,-3327,-3373,-3424,-3471,-3504,-3524,-3533,-3543,-3560,-3587,-3619,-3652,-3679,-3700,-3714,-3727,
+-3741,-3757,-3776,-3795,-3814,-3833,-3855,-3880,-3906,-3931,-3954,-3974,-3990,-4004,-4017,-4028,-4038,-4045,-4052,-4058,-4065,
+-4075,-4086,-4097,-4104,-4106,-4104,-4100,-4100,-4104,-4113,-4124,-4133,-4138,-4136,-4130,-4123,-4119,-4118,-4122,-4127,-4132,
+-4135,-4136,-4138,-4140,-4145,-4152,-4157,-4161,-4161,-4159,-4157,-4156,-4156,-4156,-4156,-4154,-4149,-4141,-4133,-4125,-4118,
+-4110,-4103,-4094,-4085,-4077,-4070,-4066,-4064,-4064,-4063,-4061,-4059,-4055,-4051,-4047,-4042,-4036,-4028,-4020,-4011,-4002,
+-3993,-3984,-3972,-3957,-3940,-3920,-3899,-3879,-3860,-3844,-3829,-3814,-3798,-3782,-3768,-3756,-3746,-3739,-3733,-3727,-3718,
+-3706,-3691,-3674,-3656,-3639,-3622,-3606,-3590,-3572,-3553,-3532,-3511,-3489,-3469,-3450,-3433,-3418,-3404,-3390,-3376,-3360,
+-3345,-3330,-3315,-3301,-3287,-3272,-3256,-3238,-3218,-3199,-3180,-3163,-3146,-3130,-3114,-3097,-3081,-3065,-3052,-3041,-3031,
+-3021,-3010,-2997,-2983,-2967,-2951,-2936,-2921,-2906,-2891,-2876,-2860,-2845,-2832,-2819,-2808,-2798,-2787,-2776,-2765,-2754,
+-2744,-2736,-2728,-2721,-2715,-2709,-2703,-2697,-2690,-2682,-2674,-2665,-2657,-2650,-2644,-2639,-2634,-2629,-2623,-2617,-2612,
+-2608,-2605,-2603,-2601,-2597,-2592,-2586,-2581,-2577,-2576,-2576,-2576,-2576,-2575,-2573,-2572,-2572,-2573,-2574,-2572,-2567,
+-2557,-2545,-2532,-2520,-2510,-2500,-2491,-2480,-2466,-2450,-2433,-2416,-2400,-2384,-2369,-2354,-2339,-2324,-2312,-2302,-2294,
+-2288,-2282,-2275,-2268,-2260,-2254,-2250,-2246,-2243,-2239,-2234,-2226,-2217,-2208,-2198,-2189,-2179,-2169,-2158,-2147,-2136,
+-2128,-2119,-2111,-2102,-2091,-2080,-2070,-2061,-2056,-2052,-2048,-2044,-2037,-2029,-2020,-2011,-2004,-1998,-1993,-1988,-1981,
+-1975,-1971,-1968,-1968,-1967,-1964,-1957,-1946,-1930,-1914,-1897,-1884,-1874,-1868,-1865,-1865,-1868,-1873,-1881,-1889,-1896,
+-1900,-1901,-1899,-1896,-1896,-1898,-1903,-1908,-1913,-1914,-1912,-1907,-1902,-1896,-1891,-1887,-1882,-1875,-1867,-1858,-1848,
+-1841,-1835,-1833,-1835,-1839,-1846,-1853,-1860,-1863,-1862,-1858,-1849,-1838,-1824,-1809,-1793,-1778,-1763,-1749,-1737,-1726,
+-1718,-1710,-1702,-1694,-1685,-1677,-1669,-1664,-1660,-1657,-1655,-1652,-1649,-1646,-1641,-1634,-1624,-1611,-1593,-1572,-1549,
+-1528,-1510,-1494,-1480,-1465,-1448,-1429,-1409,-1390,-1376,-1367,-1363,-1362,-1362,-1359,-1352,-1342,-1330,-1317,-1305,-1294,
+-1287,-1281,-1277,-1272,-1266,-1258,-1247,-1234,-1219,-1204,-1190,-1175,-1161,-1146,-1129,-1112,-1095,-1081,-1071,-1065,-1060,
+-1055,-1046,-1031,-1009,-983,-956,-930,-909,-894,-883,-875,-868,-861,-852,-842,-829,-815,-799,-783,-766,-749,
+-732,-716,-701,-685,-670,-655,-641,-628,-617,-606,-593,-577,-556,-532,-503,-472,-441,-411,-384,-358,-334,
+-311,-290,-268,-248,-227,-206,-186,-167,-150,-136,-121,-106,-88,-65,-38,-9,20,48,71,92,112,
+133,155,181,209,238,266,292,317,342,367,392,419,448,479,513,550,587,623,656,686,712,
+737,763,792,825,862,900,939,976,1011,1043,1069,1087,1094,1091,1082,1074,1076,1096,1136,1193,1259,
+1320,1367,1395,1404,1401,1394,1392,1400,1417,1441,1470,1499,1527,1554,1581,1608,1635,1664,1693,1722,1752,
+1780,1807,1832,1854,1872,1888,1902,1917,1932,1949,1964,1978,1987,1992,1993,1991,1987,1984,1982,1982,1983,
+1985,1987,1988,1986,1980,1971,1961,1951,1943,1940,1939,1941,1942,1940,1936,1929,1921,1915,1912,1912,1914,
+1917,1919,1920,1919,1916,1910,1904,1897,1893,1893,1898,1908,1920,1933,1942,1945,1943,1938,1933,1930,1931,
+1934,1938,1941,1942,1941,1937,1932,1927,1920,1912,1903,1893,1884,1876,1869,1864,1860,1856,1852,1850,1850,
+1853,1857,1864,1873,1883,1896,1911,1927,1943,1958,1969,1976,1982,1987,1993,2002,2012,2024,2036,2049,2063,
+2078,2094,2107,2118,2124,2128,2134,2144,2160,2181,2202,2220,2233,2241,2248,2260,2279,2304,2331,2355,2370,
+2377,2377,2374,2368,2361,2349,2331,2309,2286,2267,2253,2242,2228,2200,2154,2087,2001,1901,1789,1663,1521,
+1363,1199,1046,931,879,904,1005,1161,1341,1511,1648,1744,1804,1840,1868,1894,1920,1943,1959,1967,1970,
+1974,1980,1987,1993,1993,1985,1971,1956,1944,1940,1944,1954,1966,1978,1991,2005,2021,2035,2048,2056,2059,
+2060,2061,2065,2073,2082,2090,2094,2092,2088,2084,2085,2092,2104,2117,2129,2136,2140,2143,2148,2156,2168,
+2185,2205,2228,2254,2282,2307,2327,2336,2335,2326,2314,2306,2307,2318,2335,2350,2358,2354,2340,2318,2297,
+2280,2270,2266,2265,2264,2261,2256,2251,2246,2241,2236,2229,2219,2205,2190,2176,2164,2156,2116,2115,2114,
+2113,2111,2108,2104,2100,2094,2085,2073,2059,2043,2028,2015,2005,1996,1989,1981,1973,1964,1953,1943,1932,
+1922,1914,1910,1912,1919,1931,1943,1952,1954,1949,1939,1928,1919,1915,1917,1922,1929,1934,1939,1945,1952,
+1961,1972,1985,1996,2007,2020,2034,2053,2075,2101,2128,2156,2185,2214,2245,2273,2298,2317,2329,2338,2349,
+2367,2396,2434,2476,2514,2543,2561,2570,2579,2591,2609,2631,2651,2663,2668,2669,2673,2686,2710,2741,2770,
+2787,2787,2772,2753,2739,2739,2756,2784,2813,2834,2843,2844,2842,2844,2854,2871,2889,2902,2907,2907,2908,
+2916,2935,2965,3000,3033,3058,3075,3087,3098,3114,3135,3162,3190,3216,3236,3250,3259,3266,3271,3277,3285,
+3295,3306,3320,3334,3350,3366,3383,3400,3417,3434,3449,3462,3473,3483,3492,3503,3518,3538,3561,3585,3609,
+3631,3651,3669,3685,3699,3713,3724,3734,3743,3752,3761,3771,3779,3785,3788,3787,3784,3781,3778,3776,3775,
+3774,3774,3774,3777,3781,3786,3792,3797,3800,3803,3804,3807,3809,3810,3808,3804,3797,3788,3780,3773,3767,
+3758,3747,3733,3716,3701,3690,3682,3677,3672,3663,3649,3631,3612,3594,3579,3567,3557,3549,3541,3535,3532,
+3532,3535,3538,3540,3539,3536,3534,3532,3533,3534,3532,3528,3519,3507,3496,3487,3482,3481,3481,3481,3480,
+3478,3473,3467,3459,3451,3441,3433,3426,3422,3421,3420,3419,3415,3408,3399,3390,3384,3381,3381,3382,3381,
+3373,3358,3333,3300,3262,3224,3192,3171,3163,3164,3167,3165,3151,3125,3092,3061,3040,3036,3049,3071,3095,
+3112,3117,3112,3101,3088,3078,3072,3068,3065,3062,3061,3061,3063,3063,3062,3056,3048,3037,3029,3024,3024,
+3025,3027,3026,3024,3020,3016,3012,3003,2988,2963,2931,2895,2862,2837,2821,2814,2809,2799,2780,2751,2715,
+2677,2642,2611,2584,2558,2530,2497,2458,2415,2366,2310,2245,2172,2091,2007,1925,1851,1790,1742,1705,1673,
+1643,1613,1585,1563,1550,1548,1553,1559,1558,1544,1515,1472,1424,1377,1338,1309,1289,1272,1255,1232,1204,
+1171,1138,1106,1077,1051,1027,1005,984,964,944,923,898,871,839,805,770,736,703,671,638,604,
+568,532,497,463,429,394,354,310,262,212,165,123,86,53,23,-5,-34,-62,-89,-113,-135,
+-157,-180,-206,-236,-267,-300,-334,-366,-399,-430,-460,-490,-517,-544,-570,-596,-622,-651,-679,-708,-737,
+-765,-793,-821,-849,-877,-904,-930,-954,-978,-1005,-1035,-1069,-1104,-1139,-1172,-1201,-1229,-1255,-1283,-1313,-1344,
+-1377,-1408,-1438,-1466,-1495,-1524,-1554,-1584,-1612,-1639,-1665,-1691,-1717,-1745,-1773,-1801,-1826,-1848,-1869,-1890,-1913,
+-1938,-1965,-1992,-2016,-2039,-2059,-2078,-2099,-2121,-2144,-2167,-2189,-2208,-2227,-2245,-2265,-2287,-2309,-2332,-2352,-2371,
+-2388,-2403,-2419,-2434,-2451,-2467,-2482,-2498,-2513,-2528,-2544,-2559,-2575,-2591,-2607,-2624,-2641,-2658,-2673,-2685,-2695,
+-2704,-2711,-2718,-2727,-2738,-2750,-2763,-2775,-2785,-2793,-2800,-2804,-2807,-2809,-2811,-2814,-2817,-2821,-2824,-2827,-2829,
+-2830,-2830,-2830,-2830,-2831,-2832,-2832,-2831,-2830,-2829,-2829,-2829,-2830,-2831,-2831,-2830,-2828,-2826,-2823,-2821,-2821,
+-2820,-2819,-2816,-2810,-2801,-2790,-2781,-2776,-2776,-2783,-2791,-2797,-2795,-2784,-2762,-2736,-2709,-2688,-2673,-2664,-2657,
+-2649,-2639,-2628,-2618,-2612,-2611,-2611,-2610,-2604,-2594,-2579,-2564,-2551,-2544,-2541,-2542,-2545,-2547,-2546,-2541,-2532,
+-2520,-2509,-2503,-2503,-2512,-2525,-2539,-2547,-2546,-2536,-2522,-2510,-2506,-2513,-2528,-2547,-2567,-2584,-2600,-2615,-2630,
+-2643,-2651,-2654,-2654,-2658,-2668,-2686,-2705,-2718,-2717,-2708,-2704,-2729,-2799,-2918,-3066,-3203,-3286,-3286,-3199,-3055,
+-2901,-2788,-2747,-2779,-2860,-2952,-3022,-3058,-3067,-3068,-3083,-3122,-3180,-3242,-3294,-3329,-3352,-3370,-3396,-3432,-3475,
+-3516,-3546,-3565,-3576,-3586,-3604,-3631,-3664,-3699,-3729,-3751,-3767,-3779,-3790,-3804,-3822,-3841,-3863,-3887,-3913,-3941,
+-3971,-3998,-4022,-4042,-4058,-4070,-4080,-4090,-4098,-4106,-4113,-4121,-4130,-4142,-4154,-4163,-4169,-4169,-4164,-4159,-4157,
+-4159,-4167,-4177,-4186,-4191,-4191,-4188,-4185,-4185,-4188,-4193,-4197,-4201,-4202,-4201,-4202,-4204,-4208,-4212,-4215,-4216,
+-4215,-4214,-4214,-4216,-4219,-4221,-4221,-4217,-4210,-4202,-4195,-4189,-4185,-4180,-4175,-4167,-4158,-4150,-4143,-4137,-4133,
+-4128,-4123,-4117,-4111,-4105,-4101,-4098,-4094,-4089,-4082,-4073,-4064,-4056,-4048,-4041,-4033,-4020,-4004,-3985,-3964,-3944,
+-3927,-3911,-3896,-3881,-3865,-3848,-3831,-3815,-3801,-3789,-3778,-3767,-3755,-3742,-3729,-3716,-3703,-3690,-3677,-3663,-3647,
+-3629,-3609,-3589,-3567,-3546,-3524,-3504,-3485,-3468,-3451,-3436,-3421,-3406,-3390,-3376,-3361,-3348,-3334,-3319,-3303,-3284,
+-3264,-3244,-3226,-3210,-3196,-3183,-3169,-3154,-3138,-3121,-3105,-3091,-3078,-3067,-3055,-3042,-3027,-3012,-2996,-2982,-2968,
+-2954,-2940,-2926,-2912,-2897,-2884,-2873,-2862,-2851,-2839,-2827,-2813,-2799,-2787,-2775,-2766,-2759,-2753,-2749,-2744,-2739,
+-2732,-2724,-2715,-2706,-2697,-2690,-2685,-2682,-2681,-2680,-2678,-2675,-2671,-2667,-2664,-2660,-2655,-2650,-2643,-2636,-2629,
+-2624,-2620,-2618,-2616,-2615,-2612,-2608,-2605,-2602,-2600,-2599,-2597,-2594,-2590,-2586,-2582,-2580,-2578,-2577,-2573,-2567,
+-2557,-2544,-2529,-2515,-2500,-2486,-2471,-2455,-2438,-2422,-2408,-2395,-2385,-2375,-2364,-2351,-2336,-2321,-2308,-2296,-2287,
+-2280,-2273,-2266,-2259,-2253,-2247,-2242,-2237,-2230,-2222,-2213,-2203,-2194,-2186,-2179,-2171,-2161,-2148,-2134,-2119,-2106,
+-2096,-2087,-2079,-2070,-2059,-2048,-2039,-2032,-2030,-2031,-2033,-2035,-2033,-2030,-2026,-2022,-2019,-2016,-2012,-2006,-1996,
+-1982,-1967,-1952,-1938,-1926,-1916,-1908,-1903,-1900,-1902,-1907,-1914,-1921,-1925,-1925,-1922,-1918,-1914,-1914,-1916,-1920,
+-1926,-1931,-1935,-1940,-1946,-1952,-1958,-1960,-1957,-1947,-1930,-1907,-1884,-1863,-1848,-1842,-1844,-1854,-1869,-1885,-1900,
+-1912,-1919,-1921,-1919,-1913,-1903,-1889,-1873,-1855,-1837,-1820,-1806,-1794,-1785,-1776,-1768,-1757,-1746,-1733,-1722,-1712,
+-1704,-1697,-1691,-1686,-1682,-1679,-1677,-1674,-1668,-1657,-1640,-1619,-1595,-1572,-1553,-1538,-1525,-1512,-1496,-1477,-1456,
+-1436,-1421,-1411,-1407,-1406,-1404,-1400,-1391,-1379,-1366,-1353,-1342,-1333,-1325,-1318,-1311,-1303,-1294,-1283,-1271,-1257,
+-1243,-1228,-1212,-1194,-1175,-1154,-1132,-1112,-1095,-1083,-1078,-1077,-1080,-1080,-1076,-1063,-1044,-1018,-989,-960,-933,
+-910,-890,-874,-861,-850,-842,-835,-828,-820,-810,-798,-784,-768,-752,-736,-719,-702,-684,-665,-648,-633,
+-620,-608,-597,-583,-565,-544,-519,-493,-467,-441,-415,-388,-360,-332,-304,-278,-255,-236,-218,-203,-189,
+-175,-161,-145,-128,-106,-81,-53,-24,4,29,50,68,85,103,124,149,176,205,234,263,291,
+318,344,369,394,421,450,484,523,567,612,655,695,730,762,792,823,856,891,926,962,998,
+1035,1073,1111,1145,1173,1190,1198,1200,1203,1215,1241,1281,1329,1378,1417,1442,1453,1454,1453,1457,1469,
+1487,1510,1532,1550,1565,1578,1594,1616,1645,1679,1717,1755,1789,1819,1843,1862,1878,1893,1906,1919,1931,
+1942,1952,1961,1969,1977,1984,1992,2001,2008,2015,2019,2021,2019,2014,2006,1997,1987,1977,1970,1966,1965,
+1967,1970,1973,1973,1969,1962,1952,1940,1930,1921,1915,1911,1909,1910,1912,1914,1917,1917,1916,1912,1908,
+1905,1907,1913,1923,1935,1947,1955,1960,1963,1964,1967,1972,1977,1982,1983,1981,1975,1968,1961,1955,1951,
+1946,1941,1935,1929,1924,1921,1917,1913,1907,1899,1891,1884,1880,1881,1886,1894,1904,1916,1928,1940,1952,
+1963,1972,1976,1978,1979,1981,1986,1995,2008,2024,2042,2061,2080,2098,2113,2123,2128,2129,2130,2135,2147,
+2166,2189,2211,2227,2237,2244,2253,2268,2290,2316,2339,2356,2363,2365,2367,2373,2382,2388,2384,2367,2338,
+2305,2279,2266,2265,2265,2254,2219,2157,2073,1976,1875,1770,1654,1519,1364,1201,1056,959,937,998,1130,
+1301,1475,1620,1723,1785,1821,1849,1879,1914,1946,1970,1982,1983,1980,1978,1979,1981,1981,1975,1962,1946,
+1932,1923,1922,1926,1932,1939,1948,1958,1970,1983,1992,1996,1993,1985,1977,1972,1975,1984,1994,2002,2005,
+2003,2001,2002,2008,2020,2033,2042,2045,2043,2039,2037,2043,2057,2078,2105,2134,2164,2192,2216,2233,2241,
+2241,2233,2223,2216,2217,2226,2240,2252,2257,2250,2234,2212,2192,2180,2177,2182,2192,2201,2206,2206,2202,
+2196,2189,2181,2171,2160,2147,2136,2126,2120,2116,2076,2076,2074,2069,2062,2055,2049,2043,2037,2027,2012,
+1994,1974,1954,1938,1927,1920,1915,1911,1908,1903,1898,1893,1887,1882,1879,1880,1887,1899,1915,1932,1944,
+1949,1946,1936,1923,1913,1908,1909,1913,1920,1927,1933,1940,1949,1960,1973,1986,1998,2010,2022,2036,2055,
+2078,2105,2133,2163,2193,2224,2253,2281,2302,2316,2322,2325,2330,2343,2369,2406,2447,2485,2512,2527,2535,
+2541,2552,2570,2592,2612,2624,2628,2628,2633,2647,2674,2709,2741,2761,2763,2750,2732,2719,2720,2736,2761,
+2788,2807,2817,2820,2823,2830,2845,2864,2881,2890,2891,2888,2888,2898,2921,2953,2987,3018,3041,3055,3065,
+3077,3094,3116,3143,3169,3192,3208,3220,3228,3235,3242,3251,3260,3270,3281,3294,3308,3323,3339,3355,3371,
+3386,3400,3412,3423,3431,3439,3447,3457,3471,3489,3511,3534,3558,3580,3601,3620,3637,3652,3665,3676,3685,
+3694,3703,3713,3723,3733,3741,3746,3747,3745,3742,3739,3737,3736,3735,3736,3737,3739,3743,3748,3753,3756,
+3758,3758,3758,3758,3759,3760,3760,3758,3754,3748,3741,3734,3726,3715,3703,3688,3672,3658,3647,3639,3634,
+3627,3618,3604,3588,3570,3553,3540,3532,3527,3523,3521,3519,3517,3515,3513,3511,3508,3505,3503,3503,3504,
+3506,3506,3502,3495,3484,3472,3461,3454,3452,3453,3454,3456,3455,3452,3447,3440,3432,3422,3413,3406,3400,
+3397,3396,3395,3393,3389,3381,3373,3364,3358,3354,3351,3347,3339,3325,3303,3273,3238,3202,3169,3145,3133,
+3134,3146,3160,3170,3169,3154,3129,3100,3076,3063,3063,3072,3082,3088,3085,3073,3056,3037,3021,3008,2998,
+2990,2983,2978,2976,2977,2981,2986,2991,2994,2995,2996,2997,2998,3000,3001,3002,3005,3010,3018,3026,3030,
+3025,3007,2976,2937,2896,2860,2835,2821,2812,2804,2788,2761,2725,2683,2641,2602,2570,2542,2515,2489,2459,
+2426,2387,2342,2287,2223,2149,2069,1986,1907,1836,1777,1726,1682,1642,1603,1566,1534,1512,1501,1499,1501,
+1500,1489,1466,1432,1391,1351,1316,1289,1268,1250,1232,1210,1185,1158,1130,1102,1074,1046,1018,988,960,
+933,909,886,862,836,807,773,738,703,669,636,603,570,537,503,471,439,406,371,331,287,
+239,190,144,102,67,36,9,-17,-44,-72,-99,-126,-152,-177,-203,-230,-260,-290,-322,-354,-387,
+-420,-452,-483,-512,-539,-564,-588,-612,-638,-665,-694,-723,-751,-779,-806,-834,-862,-891,-918,-944,-968,
+-991,-1016,-1045,-1077,-1112,-1148,-1183,-1214,-1242,-1269,-1295,-1322,-1351,-1381,-1410,-1439,-1468,-1496,-1526,-1556,-1587,
+-1617,-1645,-1673,-1700,-1727,-1755,-1783,-1810,-1834,-1856,-1876,-1897,-1919,-1944,-1972,-2000,-2026,-2050,-2071,-2092,-2112,
+-2135,-2158,-2180,-2201,-2221,-2239,-2257,-2278,-2300,-2325,-2349,-2371,-2391,-2407,-2422,-2436,-2450,-2466,-2483,-2500,-2518,
+-2536,-2553,-2569,-2585,-2600,-2615,-2631,-2649,-2667,-2686,-2704,-2719,-2730,-2738,-2744,-2749,-2756,-2765,-2776,-2788,-2800,
+-2812,-2822,-2830,-2837,-2842,-2847,-2851,-2854,-2857,-2859,-2862,-2864,-2866,-2867,-2869,-2870,-2871,-2872,-2873,-2874,-2874,
+-2874,-2874,-2874,-2875,-2876,-2877,-2878,-2877,-2876,-2873,-2870,-2867,-2864,-2863,-2863,-2861,-2857,-2850,-2842,-2833,-2828,
+-2827,-2831,-2838,-2843,-2842,-2831,-2813,-2789,-2765,-2745,-2730,-2721,-2715,-2709,-2700,-2690,-2680,-2672,-2666,-2663,-2660,
+-2656,-2648,-2638,-2626,-2613,-2602,-2595,-2591,-2591,-2594,-2596,-2595,-2588,-2575,-2559,-2545,-2538,-2540,-2550,-2565,-2578,
+-2583,-2579,-2568,-2557,-2551,-2553,-2563,-2579,-2598,-2618,-2637,-2657,-2674,-2687,-2694,-2693,-2690,-2691,-2700,-2719,-2741,
+-2756,-2759,-2749,-2742,-2759,-2818,-2927,-3071,-3214,-3314,-3339,-3280,-3157,-3010,-2888,-2824,-2830,-2888,-2970,-3043,-3092,
+-3115,-3128,-3146,-3181,-3233,-3293,-3348,-3390,-3420,-3444,-3467,-3495,-3527,-3557,-3581,-3597,-3609,-3622,-3642,-3669,-3702,
+-3737,-3769,-3795,-3815,-3832,-3848,-3864,-3881,-3900,-3920,-3944,-3970,-3999,-4028,-4055,-4078,-4097,-4111,-4123,-4133,-4144,
+-4155,-4165,-4176,-4186,-4197,-4208,-4219,-4226,-4230,-4230,-4226,-4221,-4218,-4219,-4223,-4229,-4234,-4237,-4238,-4238,-4240,
+-4243,-4248,-4254,-4258,-4261,-4261,-4262,-4263,-4267,-4270,-4272,-4272,-4270,-4268,-4266,-4268,-4271,-4276,-4278,-4278,-4273,
+-4267,-4260,-4255,-4252,-4249,-4245,-4238,-4229,-4220,-4212,-4205,-4201,-4197,-4192,-4184,-4174,-4164,-4156,-4150,-4147,-4143,
+-4138,-4130,-4119,-4108,-4099,-4092,-4086,-4080,-4072,-4060,-4045,-4028,-4011,-3994,-3977,-3960,-3942,-3923,-3904,-3885,-3869,
+-3855,-3841,-3828,-3815,-3801,-3786,-3773,-3762,-3751,-3740,-3729,-3715,-3699,-3681,-3663,-3644,-3625,-3605,-3585,-3563,-3542,
+-3521,-3501,-3483,-3466,-3450,-3433,-3417,-3402,-3388,-3374,-3361,-3347,-3331,-3313,-3295,-3277,-3261,-3247,-3235,-3223,-3210,
+-3195,-3179,-3163,-3147,-3133,-3119,-3105,-3090,-3074,-3057,-3040,-3025,-3011,-2998,-2985,-2972,-2959,-2946,-2934,-2923,-2913,
+-2903,-2891,-2878,-2864,-2849,-2835,-2822,-2811,-2802,-2795,-2789,-2784,-2779,-2773,-2767,-2761,-2754,-2747,-2740,-2736,-2733,
+-2732,-2731,-2730,-2729,-2727,-2724,-2721,-2718,-2713,-2708,-2700,-2692,-2683,-2675,-2669,-2664,-2661,-2658,-2654,-2650,-2644,
+-2639,-2633,-2628,-2624,-2619,-2616,-2614,-2613,-2613,-2615,-2615,-2614,-2611,-2605,-2598,-2590,-2583,-2576,-2568,-2559,-2548,
+-2536,-2524,-2513,-2503,-2494,-2484,-2470,-2453,-2432,-2410,-2388,-2367,-2349,-2333,-2318,-2307,-2297,-2291,-2288,-2286,-2285,
+-2282,-2276,-2267,-2257,-2247,-2239,-2232,-2224,-2215,-2204,-2191,-2177,-2165,-2154,-2143,-2132,-2119,-2104,-2089,-2076,-2067,
+-2063,-2064,-2067,-2070,-2071,-2070,-2068,-2065,-2062,-2059,-2055,-2049,-2040,-2030,-2019,-2009,-2000,-1991,-1982,-1973,-1965,
+-1958,-1953,-1953,-1955,-1958,-1961,-1961,-1959,-1956,-1953,-1950,-1948,-1946,-1945,-1944,-1946,-1951,-1960,-1973,-1987,-1999,
+-2005,-2002,-1991,-1973,-1952,-1931,-1914,-1904,-1900,-1901,-1906,-1913,-1919,-1925,-1930,-1934,-1936,-1936,-1932,-1925,-1914,
+-1900,-1885,-1871,-1861,-1854,-1850,-1846,-1839,-1829,-1815,-1799,-1782,-1765,-1750,-1736,-1724,-1714,-1705,-1701,-1698,-1698,
+-1696,-1689,-1676,-1657,-1634,-1611,-1591,-1575,-1562,-1550,-1536,-1520,-1502,-1484,-1470,-1461,-1457,-1453,-1448,-1440,-1428,
+-1413,-1398,-1386,-1376,-1368,-1360,-1352,-1341,-1328,-1316,-1303,-1291,-1279,-1266,-1251,-1231,-1207,-1180,-1150,-1122,-1098,
+-1080,-1071,-1070,-1075,-1081,-1086,-1084,-1075,-1060,-1040,-1017,-995,-973,-951,-929,-908,-888,-871,-858,-848,-842,
+-836,-829,-819,-806,-790,-773,-755,-737,-718,-698,-679,-661,-645,-632,-620,-609,-597,-582,-564,-543,-521,
+-497,-473,-447,-418,-387,-355,-323,-295,-270,-251,-235,-223,-211,-199,-184,-168,-148,-124,-98,-70,-42,
+-17,4,22,38,53,71,92,117,146,176,207,237,266,294,320,346,371,396,424,457,494,
+537,583,630,675,718,760,801,841,882,920,955,986,1013,1041,1071,1107,1145,1185,1221,1250,1273,
+1292,1312,1336,1367,1400,1433,1460,1478,1490,1498,1509,1525,1548,1573,1595,1611,1618,1619,1620,1626,1642,
+1669,1705,1744,1783,1816,1842,1862,1877,1891,1905,1919,1932,1944,1955,1963,1970,1977,1986,1995,2006,2016,
+2026,2033,2037,2038,2035,2029,2020,2011,2001,1992,1985,1980,1978,1978,1979,1980,1980,1979,1977,1974,1969,
+1962,1953,1941,1929,1917,1909,1905,1907,1911,1916,1919,1920,1918,1916,1916,1921,1929,1939,1951,1962,1973,
+1984,1995,2007,2017,2024,2025,2021,2012,2001,1992,1986,1983,1981,1979,1976,1971,1965,1959,1955,1951,1946,
+1940,1932,1924,1918,1915,1916,1921,1929,1939,1951,1962,1973,1983,1990,1993,1993,1990,1987,1988,1995,2007,
+2023,2042,2062,2082,2100,2116,2128,2136,2139,2139,2141,2148,2162,2182,2204,2222,2235,2243,2250,2262,2282,
+2309,2336,2356,2363,2361,2355,2354,2365,2385,2405,2413,2402,2373,2334,2301,2282,2277,2278,2269,2238,2182,
+2108,2029,1952,1876,1789,1673,1521,1342,1163,1024,960,989,1103,1272,1454,1611,1724,1791,1827,1853,1882,
+1917,1953,1979,1990,1989,1980,1973,1971,1975,1979,1978,1971,1960,1948,1939,1934,1933,1933,1933,1934,1937,
+1943,1950,1954,1950,1937,1915,1891,1872,1863,1867,1878,1890,1900,1904,1904,1904,1908,1915,1924,1931,1932,
+1929,1925,1924,1931,1948,1971,1998,2026,2052,2075,2094,2108,2117,2120,2118,2112,2109,2110,2118,2130,2140,
+2144,2138,2123,2104,2086,2075,2074,2081,2092,2104,2111,2113,2111,2106,2100,2093,2087,2081,2076,2073,2073,
+2074,2076,2020,2021,2017,2009,1999,1989,1981,1975,1970,1962,1950,1933,1914,1895,1879,1868,1860,1856,1853,
+1851,1848,1846,1844,1842,1841,1841,1844,1852,1866,1884,1903,1919,1928,1930,1924,1915,1907,1902,1902,1906,
+1912,1918,1925,1933,1944,1959,1976,1993,2009,2023,2037,2052,2070,2091,2114,2140,2168,2197,2228,2259,2288,
+2311,2325,2331,2331,2332,2340,2358,2388,2422,2454,2478,2493,2502,2511,2525,2545,2567,2586,2597,2599,2597,
+2600,2614,2641,2676,2709,2730,2736,2728,2713,2703,2705,2720,2743,2767,2786,2798,2804,2810,2820,2834,2849,
+2861,2866,2866,2867,2873,2890,2917,2950,2981,3007,3023,3033,3042,3053,3071,3093,3117,3139,3157,3170,3180,
+3190,3201,3212,3224,3235,3246,3257,3269,3283,3299,3315,3330,3344,3355,3364,3372,3380,3388,3397,3406,3416,
+3429,3444,3463,3483,3505,3526,3547,3567,3585,3601,3615,3626,3637,3647,3657,3668,3679,3689,3697,3700,3700,
+3698,3694,3692,3691,3693,3696,3700,3705,3709,3714,3718,3721,3723,3723,3721,3719,3716,3715,3714,3714,3713,
+3710,3704,3697,3688,3678,3666,3653,3638,3623,3608,3595,3584,3575,3567,3558,3548,3537,3526,3517,3510,3506,
+3504,3503,3502,3501,3498,3494,3490,3486,3482,3480,3480,3482,3484,3484,3481,3474,3463,3450,3438,3430,3426,
+3426,3428,3431,3432,3431,3427,3422,3415,3407,3398,3389,3382,3376,3373,3371,3369,3365,3359,3351,3342,3334,
+3328,3323,3317,3308,3295,3277,3254,3229,3203,3180,3160,3148,3144,3149,3162,3179,3194,3203,3202,3191,3174,
+3156,3142,3133,3129,3125,3117,3103,3082,3059,3037,3017,3002,2990,2979,2968,2956,2945,2938,2938,2943,2953,
+2966,2979,2991,3000,3005,3008,3008,3009,3013,3020,3032,3045,3056,3058,3048,3024,2990,2950,2912,2881,2859,
+2843,2828,2808,2779,2741,2697,2652,2610,2574,2544,2518,2493,2467,2438,2404,2364,2316,2259,2193,2118,2040,
+1963,1891,1826,1770,1719,1671,1623,1577,1534,1499,1474,1458,1449,1442,1431,1412,1387,1357,1325,1296,1270,
+1247,1225,1203,1180,1157,1134,1112,1090,1066,1037,1005,969,932,898,868,841,817,793,767,738,706,
+673,640,608,576,544,512,480,448,415,382,346,306,262,215,168,123,83,48,18,-9,-36,
+-62,-89,-116,-142,-167,-193,-220,-248,-277,-307,-338,-370,-402,-436,-470,-504,-535,-564,-589,-612,-634,
+-657,-682,-708,-734,-760,-785,-811,-838,-866,-895,-924,-952,-979,-1004,-1031,-1060,-1092,-1126,-1161,-1195,-1225,
+-1252,-1277,-1302,-1328,-1356,-1387,-1417,-1448,-1478,-1507,-1537,-1566,-1595,-1623,-1651,-1678,-1706,-1734,-1763,-1793,-1820,
+-1846,-1868,-1889,-1909,-1932,-1957,-1985,-2014,-2041,-2066,-2087,-2108,-2127,-2148,-2169,-2191,-2213,-2233,-2252,-2272,-2292,
+-2315,-2339,-2363,-2386,-2406,-2424,-2439,-2453,-2467,-2482,-2498,-2515,-2534,-2553,-2572,-2591,-2608,-2624,-2639,-2655,-2671,
+-2689,-2708,-2726,-2743,-2756,-2767,-2775,-2782,-2790,-2799,-2809,-2819,-2830,-2841,-2850,-2860,-2869,-2878,-2885,-2891,-2894,
+-2896,-2897,-2898,-2899,-2902,-2904,-2908,-2910,-2913,-2914,-2915,-2916,-2916,-2917,-2917,-2916,-2916,-2917,-2918,-2920,-2922,
+-2924,-2923,-2922,-2919,-2915,-2912,-2910,-2907,-2903,-2897,-2890,-2883,-2878,-2876,-2878,-2882,-2886,-2885,-2877,-2862,-2842,
+-2819,-2799,-2783,-2772,-2765,-2759,-2753,-2745,-2737,-2729,-2721,-2715,-2710,-2706,-2700,-2693,-2684,-2673,-2660,-2649,-2641,
+-2638,-2639,-2642,-2643,-2639,-2627,-2610,-2593,-2580,-2576,-2582,-2595,-2608,-2617,-2617,-2610,-2600,-2592,-2591,-2596,-2607,
+-2623,-2643,-2666,-2690,-2712,-2729,-2736,-2735,-2728,-2723,-2728,-2745,-2769,-2790,-2798,-2793,-2783,-2787,-2828,-2915,-3042,
+-3185,-3305,-3368,-3355,-3275,-3157,-3041,-2962,-2940,-2970,-3033,-3101,-3157,-3191,-3210,-3226,-3250,-3286,-3333,-3384,-3430,
+-3469,-3500,-3528,-3553,-3578,-3600,-3619,-3635,-3649,-3666,-3687,-3714,-3745,-3778,-3810,-3840,-3866,-3890,-3911,-3929,-3946,
+-3963,-3980,-4001,-4026,-4054,-4084,-4111,-4134,-4152,-4166,-4177,-4188,-4199,-4213,-4226,-4240,-4252,-4262,-4272,-4279,-4284,
+-4287,-4287,-4285,-4284,-4283,-4284,-4287,-4290,-4292,-4294,-4295,-4298,-4301,-4307,-4313,-4318,-4321,-4322,-4322,-4323,-4326,
+-4328,-4330,-4330,-4327,-4322,-4318,-4317,-4320,-4325,-4330,-4333,-4332,-4327,-4321,-4316,-4312,-4309,-4305,-4297,-4286,-4273,
+-4260,-4251,-4246,-4245,-4244,-4241,-4235,-4225,-4215,-4206,-4199,-4195,-4191,-4185,-4175,-4163,-4150,-4139,-4130,-4124,-4118,
+-4112,-4104,-4093,-4080,-4065,-4050,-4033,-4014,-3994,-3973,-3953,-3936,-3921,-3910,-3899,-3887,-3873,-3858,-3842,-3827,-3814,
+-3802,-3791,-3778,-3764,-3747,-3731,-3714,-3698,-3683,-3665,-3646,-3624,-3601,-3578,-3557,-3536,-3518,-3499,-3481,-3462,-3444,
+-3428,-3414,-3401,-3389,-3376,-3362,-3346,-3330,-3314,-3300,-3286,-3274,-3260,-3246,-3231,-3216,-3202,-3188,-3174,-3160,-3144,
+-3127,-3110,-3092,-3076,-3061,-3047,-3034,-3020,-3006,-2993,-2981,-2969,-2959,-2949,-2939,-2927,-2914,-2901,-2888,-2876,-2865,
+-2855,-2846,-2837,-2829,-2823,-2818,-2814,-2811,-2807,-2804,-2799,-2795,-2790,-2786,-2783,-2780,-2777,-2775,-2773,-2771,-2768,
+-2765,-2761,-2754,-2747,-2739,-2731,-2724,-2718,-2713,-2709,-2705,-2700,-2694,-2688,-2681,-2674,-2667,-2660,-2655,-2650,-2646,
+-2643,-2641,-2638,-2634,-2630,-2626,-2623,-2621,-2620,-2620,-2619,-2616,-2611,-2605,-2599,-2593,-2589,-2584,-2577,-2567,-2553,
+-2535,-2514,-2492,-2470,-2448,-2427,-2407,-2388,-2373,-2361,-2353,-2347,-2342,-2336,-2326,-2314,-2301,-2289,-2278,-2270,-2263,
+-2256,-2248,-2240,-2232,-2223,-2215,-2206,-2196,-2182,-2166,-2149,-2132,-2118,-2109,-2104,-2102,-2103,-2104,-2106,-2108,-2111,
+-2112,-2112,-2109,-2103,-2094,-2083,-2073,-2065,-2058,-2052,-2045,-2037,-2027,-2018,-2010,-2004,-2002,-2001,-2002,-2003,-2004,
+-2004,-2004,-2002,-1999,-1994,-1987,-1978,-1972,-1969,-1972,-1981,-1995,-2011,-2026,-2037,-2043,-2043,-2039,-2033,-2025,-2016,
+-2007,-1997,-1986,-1975,-1964,-1954,-1947,-1943,-1941,-1941,-1939,-1935,-1927,-1917,-1905,-1897,-1892,-1891,-1894,-1897,-1896,
+-1891,-1880,-1864,-1847,-1828,-1810,-1793,-1775,-1757,-1740,-1727,-1718,-1712,-1708,-1702,-1692,-1676,-1657,-1637,-1618,-1603,
+-1591,-1580,-1568,-1554,-1538,-1524,-1512,-1504,-1500,-1496,-1489,-1479,-1465,-1450,-1434,-1422,-1411,-1403,-1393,-1382,-1369,
+-1355,-1341,-1330,-1320,-1312,-1300,-1283,-1258,-1225,-1187,-1146,-1109,-1080,-1062,-1055,-1057,-1065,-1073,-1078,-1078,-1071,
+-1060,-1048,-1036,-1025,-1014,-1001,-983,-962,-938,-914,-892,-876,-864,-855,-846,-836,-824,-808,-791,-773,-755,
+-736,-717,-698,-680,-663,-648,-636,-624,-612,-599,-584,-567,-548,-528,-506,-481,-453,-421,-388,-355,-324,
+-298,-277,-260,-245,-232,-219,-204,-186,-165,-142,-117,-92,-69,-48,-30,-15,0,16,36,61,91,
+123,156,189,220,250,278,306,332,358,383,410,439,472,509,549,591,636,681,729,778,829,
+880,927,968,1002,1029,1054,1080,1110,1145,1183,1221,1256,1287,1315,1340,1367,1396,1425,1453,1477,1497,
+1514,1532,1555,1582,1611,1638,1659,1669,1669,1664,1660,1663,1677,1701,1732,1767,1801,1830,1854,1876,1895,
+1913,1930,1945,1957,1964,1969,1973,1978,1985,1994,2005,2016,2024,2029,2029,2027,2024,2020,2018,2018,2018,
+2018,2017,2013,2007,1999,1991,1983,1978,1976,1980,1986,1993,1998,1997,1989,1975,1958,1942,1931,1927,1929,
+1935,1941,1945,1946,1943,1940,1938,1941,1947,1957,1969,1984,2001,2019,2038,2055,2068,2074,2072,2063,2049,
+2037,2027,2022,2021,2020,2017,2011,2001,1989,1978,1968,1960,1954,1948,1943,1939,1936,1936,1937,1939,1943,
+1949,1956,1966,1978,1989,1997,2001,2001,1999,1998,2002,2013,2028,2048,2068,2087,2104,2119,2133,2144,2152,
+2156,2160,2164,2173,2188,2207,2226,2242,2251,2257,2264,2278,2302,2332,2361,2381,2387,2381,2371,2366,2374,
+2392,2412,2423,2414,2386,2347,2311,2287,2275,2268,2253,2221,2173,2118,2066,2022,1980,1919,1816,1662,1463,
+1253,1077,979,983,1084,1251,1440,1609,1732,1805,1844,1867,1892,1923,1954,1977,1988,1985,1977,1971,1972,
+1981,1991,1999,2000,1997,1992,1989,1988,1988,1985,1981,1975,1972,1973,1977,1979,1972,1952,1921,1884,1852,
+1831,1827,1835,1849,1861,1868,1867,1864,1861,1862,1865,1869,1872,1873,1873,1877,1886,1901,1919,1938,1954,
+1968,1978,1987,1994,2000,2004,2004,2002,2001,2004,2012,2024,2035,2042,2040,2029,2013,1997,1985,1981,1984,
+1991,1998,2004,2007,2007,2006,2004,2003,2002,2001,2002,2005,2010,2016,2020,1947,1949,1946,1939,1930,1921,
+1914,1909,1905,1900,1892,1880,1865,1850,1836,1824,1815,1809,1804,1801,1799,1798,1799,1801,1803,1805,1810,
+1817,1829,1845,1863,1880,1893,1900,1900,1896,1892,1889,1890,1894,1900,1907,1917,1929,1944,1963,1984,2005,
+2026,2044,2060,2076,2093,2111,2131,2153,2177,2203,2232,2262,2291,2316,2334,2343,2346,2347,2351,2364,2385,
+2411,2437,2458,2474,2487,2500,2518,2538,2559,2576,2585,2586,2584,2586,2599,2621,2651,2678,2697,2703,2698,
+2691,2687,2694,2712,2735,2759,2778,2789,2796,2802,2809,2817,2826,2833,2838,2843,2853,2869,2894,2925,2955,
+2980,2996,3005,3010,3017,3029,3046,3067,3087,3103,3115,3125,3134,3146,3159,3174,3188,3201,3212,3224,3238,
+3254,3272,3289,3304,3316,3325,3331,3338,3346,3354,3364,3374,3384,3394,3406,3420,3436,3454,3473,3493,3511,
+3528,3545,3559,3573,3586,3599,3612,3625,3637,3648,3655,3658,3656,3653,3649,3647,3648,3652,3658,3665,3671,
+3675,3679,3682,3685,3687,3688,3687,3686,3684,3682,3680,3678,3674,3669,3662,3652,3641,3629,3616,3604,3591,
+3577,3562,3547,3532,3518,3507,3497,3491,3486,3484,3482,3482,3481,3480,3478,3477,3474,3471,3468,3464,3461,
+3460,3460,3461,3463,3463,3461,3454,3444,3432,3421,3412,3407,3406,3407,3408,3410,3409,3408,3405,3401,3395,
+3389,3381,3372,3364,3358,3354,3351,3346,3340,3331,3321,3311,3303,3297,3291,3282,3269,3252,3232,3213,3196,
+3183,3176,3171,3170,3171,3175,3182,3194,3208,3221,3229,3232,3227,3218,3206,3193,3179,3163,3144,3120,3093,
+3066,3042,3023,3010,2999,2988,2975,2958,2941,2927,2920,2923,2936,2955,2977,2998,3015,3027,3034,3037,3039,
+3042,3047,3054,3062,3068,3068,3060,3042,3016,2985,2952,2922,2895,2871,2848,2821,2789,2751,2709,2666,2626,
+2591,2561,2536,2512,2488,2461,2430,2392,2347,2293,2230,2159,2084,2007,1934,1866,1805,1748,1695,1643,1592,
+1545,1502,1467,1440,1420,1404,1388,1371,1350,1326,1301,1275,1249,1223,1197,1170,1144,1119,1097,1078,1059,
+1037,1011,979,943,905,868,835,805,778,753,727,699,671,641,612,583,554,524,494,462,430,
+396,361,323,282,238,193,149,106,68,33,2,-27,-55,-81,-107,-131,-155,-178,-203,-230,-259,
+-290,-320,-351,-382,-414,-448,-483,-518,-553,-584,-612,-637,-659,-681,-703,-726,-748,-771,-793,-815,-839,
+-865,-893,-923,-953,-984,-1013,-1043,-1074,-1107,-1140,-1173,-1204,-1231,-1256,-1279,-1302,-1329,-1358,-1389,-1422,-1455,
+-1486,-1517,-1547,-1576,-1603,-1630,-1657,-1683,-1710,-1739,-1769,-1799,-1829,-1856,-1880,-1902,-1923,-1946,-1971,-1998,-2026,
+-2054,-2079,-2101,-2120,-2139,-2159,-2180,-2202,-2225,-2247,-2269,-2290,-2310,-2331,-2353,-2375,-2396,-2417,-2437,-2455,-2472,
+-2488,-2503,-2518,-2534,-2551,-2569,-2589,-2608,-2627,-2645,-2661,-2676,-2691,-2707,-2723,-2741,-2758,-2774,-2789,-2802,-2814,
+-2825,-2836,-2847,-2857,-2866,-2875,-2884,-2894,-2903,-2913,-2921,-2928,-2932,-2933,-2934,-2934,-2936,-2939,-2943,-2947,-2951,
+-2953,-2954,-2956,-2957,-2958,-2960,-2961,-2961,-2960,-2960,-2960,-2961,-2964,-2968,-2971,-2973,-2972,-2969,-2966,-2962,-2957,
+-2952,-2946,-2939,-2932,-2926,-2923,-2923,-2925,-2928,-2929,-2925,-2915,-2899,-2879,-2859,-2841,-2826,-2816,-2809,-2805,-2800,
+-2795,-2788,-2780,-2773,-2766,-2760,-2755,-2749,-2742,-2732,-2720,-2706,-2695,-2688,-2687,-2690,-2693,-2692,-2683,-2667,-2648,
+-2632,-2622,-2622,-2629,-2639,-2646,-2648,-2644,-2637,-2631,-2628,-2630,-2637,-2649,-2666,-2689,-2717,-2745,-2769,-2783,-2785,
+-2778,-2769,-2767,-2778,-2799,-2822,-2837,-2838,-2827,-2821,-2837,-2894,-2995,-3125,-3255,-3354,-3397,-3376,-3306,-3216,-3137,
+-3093,-3092,-3126,-3178,-3229,-3268,-3292,-3307,-3322,-3345,-3378,-3419,-3463,-3505,-3542,-3574,-3601,-3624,-3645,-3664,-3683,
+-3703,-3723,-3746,-3771,-3798,-3827,-3856,-3886,-3915,-3942,-3966,-3985,-4000,-4014,-4029,-4048,-4073,-4103,-4134,-4164,-4188,
+-4207,-4220,-4230,-4241,-4254,-4268,-4284,-4299,-4313,-4324,-4332,-4337,-4341,-4342,-4343,-4343,-4344,-4346,-4349,-4353,-4357,
+-4361,-4364,-4368,-4372,-4378,-4384,-4389,-4392,-4392,-4391,-4389,-4388,-4388,-4388,-4387,-4383,-4377,-4371,-4366,-4366,-4369,
+-4375,-4381,-4383,-4381,-4376,-4370,-4365,-4362,-4359,-4354,-4344,-4328,-4310,-4293,-4281,-4274,-4273,-4273,-4273,-4269,-4263,
+-4255,-4248,-4242,-4238,-4234,-4227,-4217,-4204,-4190,-4178,-4168,-4160,-4153,-4145,-4136,-4126,-4114,-4103,-4090,-4076,-4060,
+-4042,-4023,-4005,-3990,-3978,-3968,-3958,-3946,-3930,-3913,-3895,-3878,-3864,-3852,-3840,-3828,-3814,-3798,-3782,-3768,-3754,
+-3740,-3725,-3707,-3685,-3662,-3638,-3616,-3596,-3577,-3559,-3539,-3518,-3497,-3477,-3460,-3445,-3432,-3419,-3406,-3393,-3378,
+-3363,-3349,-3335,-3321,-3307,-3292,-3277,-3263,-3249,-3237,-3225,-3213,-3199,-3184,-3167,-3151,-3134,-3118,-3103,-3088,-3073,
+-3058,-3043,-3029,-3016,-3004,-2993,-2982,-2971,-2960,-2950,-2940,-2931,-2922,-2912,-2902,-2891,-2882,-2873,-2868,-2865,-2863,
+-2862,-2860,-2857,-2852,-2846,-2840,-2834,-2829,-2825,-2822,-2818,-2815,-2812,-2808,-2804,-2800,-2795,-2790,-2784,-2778,-2773,
+-2768,-2763,-2758,-2753,-2748,-2742,-2736,-2731,-2725,-2718,-2711,-2704,-2697,-2690,-2682,-2674,-2666,-2659,-2653,-2649,-2647,
+-2647,-2647,-2648,-2646,-2644,-2640,-2635,-2632,-2629,-2626,-2623,-2619,-2613,-2605,-2595,-2585,-2573,-2559,-2544,-2525,-2506,
+-2485,-2466,-2448,-2432,-2416,-2401,-2384,-2366,-2348,-2332,-2319,-2308,-2300,-2294,-2289,-2283,-2278,-2273,-2267,-2261,-2252,
+-2241,-2227,-2212,-2196,-2181,-2168,-2157,-2150,-2145,-2145,-2147,-2153,-2159,-2166,-2169,-2168,-2163,-2153,-2142,-2130,-2121,
+-2113,-2107,-2099,-2091,-2081,-2071,-2062,-2054,-2049,-2045,-2043,-2042,-2042,-2044,-2046,-2048,-2048,-2044,-2037,-2026,-2014,
+-2004,-1998,-1999,-2006,-2019,-2036,-2056,-2075,-2093,-2108,-2118,-2123,-2123,-2116,-2105,-2090,-2072,-2052,-2034,-2018,-2005,
+-1994,-1986,-1977,-1968,-1956,-1942,-1928,-1917,-1911,-1910,-1913,-1918,-1922,-1922,-1919,-1913,-1904,-1894,-1882,-1868,-1849,
+-1827,-1801,-1776,-1754,-1737,-1723,-1711,-1699,-1684,-1668,-1651,-1635,-1623,-1613,-1604,-1595,-1583,-1569,-1556,-1545,-1538,
+-1533,-1530,-1526,-1518,-1506,-1491,-1476,-1463,-1451,-1440,-1427,-1414,-1399,-1384,-1372,-1363,-1357,-1352,-1342,-1323,-1294,
+-1255,-1209,-1162,-1121,-1090,-1073,-1069,-1074,-1083,-1091,-1093,-1090,-1082,-1071,-1062,-1055,-1052,-1049,-1043,-1032,-1013,
+-989,-961,-934,-911,-893,-879,-868,-857,-846,-833,-818,-803,-786,-768,-749,-729,-709,-688,-668,-650,-634,
+-620,-606,-593,-580,-566,-551,-534,-512,-487,-458,-426,-394,-364,-336,-312,-291,-273,-255,-238,-220,-201,
+-181,-161,-140,-120,-102,-86,-71,-57,-41,-21,3,32,66,102,137,170,202,232,262,290,319,
+347,374,401,429,458,490,525,562,602,645,691,741,794,847,900,948,992,1030,1064,1096,1129,
+1162,1194,1224,1251,1275,1299,1324,1352,1384,1418,1452,1482,1510,1536,1562,1589,1617,1645,1668,1683,1689,
+1689,1686,1686,1693,1708,1730,1756,1783,1810,1837,1864,1893,1921,1948,1969,1982,1985,1980,1971,1962,1959,
+1963,1973,1988,2002,2013,2019,2020,2018,2014,2014,2016,2022,2031,2038,2043,2042,2034,2022,2006,1992,1982,
+1979,1983,1993,2004,2012,2012,2005,1992,1978,1967,1961,1962,1967,1973,1977,1976,1971,1965,1960,1960,1964,
+1972,1983,1997,2013,2031,2053,2075,2094,2108,2113,2110,2098,2084,2070,2059,2052,2046,2040,2031,2019,2004,
+1989,1976,1964,1956,1950,1946,1944,1944,1947,1950,1953,1954,1954,1954,1957,1964,1976,1988,1999,2005,2007,
+2007,2008,2014,2027,2045,2066,2087,2106,2122,2137,2150,2162,2171,2177,2181,2185,2192,2204,2221,2239,2256,
+2268,2275,2282,2295,2316,2343,2372,2394,2405,2405,2398,2394,2397,2406,2416,2418,2406,2380,2347,2316,2294,
+2281,2269,2250,2218,2177,2135,2103,2079,2052,1998,1895,1730,1517,1289,1097,985,978,1072,1237,1426,1598,
+1725,1803,1844,1869,1893,1921,1951,1974,1986,1988,1986,1987,1995,2008,2022,2034,2040,2043,2046,2052,2059,
+2064,2064,2059,2051,2045,2045,2051,2058,2057,2042,2013,1975,1938,1911,1899,1901,1912,1922,1926,1922,1913,
+1903,1897,1896,1899,1903,1907,1910,1913,1919,1926,1934,1940,1942,1941,1938,1934,1932,1930,1927,1924,1920,
+1917,1919,1925,1936,1948,1957,1960,1954,1943,1929,1918,1912,1911,1913,1917,1920,1922,1925,1927,1930,1932,
+1934,1935,1935,1937,1939,1944,1947,1866,1869,1869,1866,1860,1852,1844,1838,1834,1830,1826,1820,1812,1802,
+1791,1782,1774,1768,1763,1761,1761,1764,1768,1773,1777,1780,1783,1788,1795,1807,1822,1837,1851,1860,1865,
+1867,1868,1871,1875,1883,1892,1904,1918,1934,1953,1975,1999,2023,2045,2066,2084,2103,2121,2140,2160,2180,
+2200,2221,2244,2268,2294,2317,2336,2349,2356,2361,2367,2378,2393,2413,2433,2452,2469,2483,2499,2516,2535,
+2553,2567,2576,2579,2582,2587,2598,2616,2636,2654,2666,2670,2670,2671,2678,2694,2717,2742,2764,2779,2786,
+2789,2790,2791,2796,2801,2809,2818,2831,2849,2873,2902,2931,2954,2970,2978,2980,2983,2990,3003,3021,3039,
+3054,3064,3071,3076,3084,3096,3110,3125,3139,3152,3164,3177,3194,3214,3235,3256,3272,3285,3294,3301,3309,
+3318,3328,3337,3346,3354,3361,3370,3381,3395,3411,3428,3444,3460,3475,3490,3505,3521,3536,3551,3566,3581,
+3594,3605,3614,3618,3619,3618,3615,3614,3615,3618,3623,3628,3632,3634,3636,3637,3639,3642,3645,3648,3650,
+3650,3648,3646,3642,3637,3630,3621,3609,3597,3583,3571,3559,3547,3535,3521,3506,3489,3473,3459,3449,3444,
+3442,3444,3447,3450,3450,3450,3448,3445,3443,3440,3439,3438,3437,3438,3438,3439,3438,3435,3428,3419,3408,
+3398,3391,3386,3386,3386,3387,3387,3386,3384,3383,3382,3381,3379,3374,3367,3358,3350,3343,3337,3332,3327,
+3318,3307,3295,3284,3275,3268,3260,3249,3233,3213,3192,3174,3164,3162,3167,3175,3182,3187,3189,3192,3196,
+3204,3215,3226,3234,3235,3229,3218,3202,3184,3162,3136,3108,3077,3049,3024,3006,2995,2986,2978,2966,2950,
+2932,2916,2907,2909,2922,2944,2969,2994,3015,3031,3041,3048,3053,3055,3057,3057,3054,3050,3042,3030,3015,
+2996,2973,2947,2920,2892,2865,2837,2808,2776,2741,2704,2665,2628,2594,2564,2539,2516,2495,2473,2446,2414,
+2375,2326,2268,2201,2127,2050,1972,1896,1824,1758,1696,1640,1587,1539,1497,1460,1429,1403,1380,1360,1339,
+1319,1299,1278,1255,1231,1205,1176,1146,1115,1086,1060,1037,1016,994,970,942,912,880,847,815,785,
+754,723,692,662,632,603,576,551,525,499,470,440,407,372,335,296,255,213,170,129,91,
+55,22,-9,-39,-69,-96,-122,-145,-168,-191,-216,-244,-275,-308,-340,-372,-403,-433,-465,-499,-534,
+-569,-603,-634,-660,-684,-705,-726,-746,-767,-787,-806,-826,-847,-871,-897,-926,-957,-989,-1021,-1054,-1087,
+-1119,-1152,-1183,-1211,-1237,-1261,-1284,-1308,-1335,-1364,-1395,-1428,-1460,-1492,-1523,-1553,-1582,-1611,-1638,-1664,-1691,
+-1717,-1745,-1775,-1805,-1835,-1864,-1890,-1914,-1936,-1959,-1983,-2009,-2037,-2064,-2090,-2113,-2133,-2153,-2173,-2195,-2218,
+-2242,-2267,-2291,-2313,-2334,-2354,-2373,-2392,-2411,-2432,-2453,-2474,-2494,-2513,-2531,-2546,-2560,-2575,-2591,-2609,-2629,
+-2649,-2668,-2686,-2701,-2716,-2730,-2745,-2761,-2778,-2795,-2812,-2828,-2843,-2858,-2871,-2883,-2893,-2903,-2911,-2920,-2929,
+-2939,-2949,-2958,-2965,-2971,-2974,-2977,-2979,-2983,-2987,-2991,-2994,-2996,-2997,-2998,-2999,-3001,-3005,-3009,-3012,-3014,
+-3013,-3012,-3010,-3009,-3010,-3014,-3017,-3021,-3023,-3023,-3022,-3019,-3016,-3011,-3004,-2997,-2989,-2982,-2977,-2975,-2975,
+-2978,-2979,-2978,-2972,-2961,-2946,-2928,-2909,-2893,-2881,-2872,-2866,-2861,-2857,-2850,-2843,-2834,-2825,-2819,-2814,-2810,
+-2804,-2796,-2783,-2769,-2755,-2746,-2743,-2744,-2748,-2749,-2744,-2731,-2713,-2695,-2681,-2674,-2674,-2677,-2680,-2681,-2679,
+-2675,-2672,-2671,-2671,-2675,-2682,-2695,-2715,-2744,-2777,-2810,-2834,-2844,-2841,-2830,-2821,-2822,-2835,-2856,-2876,-2884,
+-2877,-2865,-2862,-2887,-2952,-3055,-3179,-3298,-3385,-3422,-3409,-3360,-3297,-3245,-3219,-3222,-3248,-3285,-3321,-3349,-3370,
+-3388,-3408,-3435,-3468,-3507,-3546,-3583,-3615,-3643,-3667,-3690,-3714,-3738,-3762,-3787,-3811,-3833,-3856,-3879,-3904,-3931,
+-3958,-3984,-4006,-4024,-4038,-4051,-4066,-4086,-4112,-4142,-4174,-4204,-4228,-4247,-4261,-4273,-4285,-4300,-4317,-4335,-4353,
+-4369,-4382,-4391,-4397,-4400,-4401,-4402,-4402,-4403,-4406,-4411,-4417,-4423,-4430,-4436,-4443,-4449,-4456,-4462,-4466,-4467,
+-4465,-4461,-4456,-4452,-4449,-4446,-4441,-4434,-4426,-4419,-4414,-4413,-4416,-4420,-4424,-4423,-4420,-4414,-4409,-4405,-4405,
+-4405,-4402,-4394,-4380,-4361,-4342,-4325,-4312,-4305,-4301,-4298,-4294,-4288,-4282,-4277,-4274,-4270,-4265,-4258,-4249,-4238,
+-4226,-4216,-4207,-4199,-4190,-4180,-4167,-4154,-4142,-4131,-4121,-4111,-4100,-4087,-4074,-4060,-4047,-4036,-4025,-4012,-3996,
+-3977,-3957,-3937,-3920,-3907,-3897,-3888,-3877,-3865,-3850,-3835,-3820,-3807,-3794,-3779,-3762,-3741,-3719,-3696,-3675,-3655,
+-3638,-3620,-3601,-3580,-3558,-3536,-3515,-3496,-3479,-3465,-3450,-3436,-3422,-3409,-3395,-3382,-3368,-3353,-3338,-3322,-3306,
+-3292,-3279,-3268,-3257,-3246,-3233,-3219,-3204,-3189,-3174,-3159,-3143,-3128,-3112,-3097,-3082,-3067,-3054,-3041,-3028,-3016,
+-3004,-2994,-2986,-2979,-2972,-2964,-2955,-2946,-2937,-2929,-2923,-2920,-2918,-2917,-2914,-2910,-2904,-2897,-2891,-2886,-2882,
+-2878,-2874,-2870,-2865,-2859,-2853,-2848,-2843,-2839,-2835,-2831,-2827,-2822,-2817,-2811,-2806,-2801,-2796,-2793,-2789,-2786,
+-2782,-2778,-2772,-2766,-2758,-2750,-2740,-2731,-2721,-2711,-2701,-2693,-2687,-2683,-2680,-2677,-2674,-2670,-2664,-2658,-2651,
+-2645,-2640,-2636,-2633,-2632,-2633,-2635,-2637,-2638,-2637,-2632,-2623,-2609,-2591,-2571,-2549,-2526,-2503,-2481,-2459,-2437,
+-2418,-2400,-2384,-2371,-2359,-2349,-2341,-2333,-2326,-2319,-2313,-2306,-2298,-2290,-2280,-2269,-2258,-2246,-2234,-2223,-2212,
+-2203,-2198,-2197,-2201,-2207,-2214,-2218,-2219,-2214,-2207,-2197,-2187,-2178,-2169,-2162,-2153,-2144,-2134,-2124,-2114,-2105,
+-2097,-2090,-2083,-2078,-2074,-2073,-2075,-2078,-2082,-2083,-2080,-2074,-2065,-2054,-2045,-2040,-2041,-2048,-2061,-2080,-2101,
+-2124,-2145,-2162,-2174,-2181,-2183,-2181,-2175,-2167,-2157,-2144,-2130,-2114,-2097,-2081,-2063,-2045,-2025,-2004,-1983,-1963,
+-1947,-1936,-1929,-1927,-1928,-1929,-1931,-1934,-1937,-1939,-1938,-1933,-1920,-1900,-1873,-1842,-1812,-1786,-1763,-1744,-1726,
+-1708,-1690,-1672,-1657,-1645,-1636,-1629,-1622,-1612,-1600,-1588,-1576,-1568,-1563,-1560,-1558,-1552,-1543,-1532,-1518,-1504,
+-1490,-1476,-1461,-1445,-1428,-1413,-1400,-1392,-1387,-1382,-1372,-1354,-1326,-1289,-1247,-1205,-1170,-1147,-1135,-1135,-1141,
+-1147,-1150,-1147,-1137,-1122,-1107,-1094,-1085,-1081,-1079,-1075,-1066,-1051,-1030,-1005,-978,-954,-933,-917,-903,-892,
+-881,-871,-859,-846,-831,-814,-794,-772,-747,-720,-693,-668,-644,-624,-607,-594,-583,-572,-562,-548,-532,
+-511,-486,-459,-431,-404,-378,-354,-332,-310,-288,-265,-244,-223,-202,-184,-167,-151,-137,-123,-109,-92,
+-73,-49,-21,11,45,79,113,145,175,204,234,264,295,325,356,386,417,448,480,515,550,
+587,626,667,711,758,807,858,909,959,1008,1054,1098,1139,1175,1205,1230,1249,1266,1285,1309,1339,
+1374,1414,1453,1490,1523,1552,1579,1605,1630,1652,1670,1681,1687,1690,1694,1701,1714,1731,1752,1772,1793,
+1815,1840,1869,1902,1936,1967,1988,1995,1989,1971,1949,1930,1918,1918,1929,1948,1970,1991,2008,2021,2029,
+2035,2039,2044,2049,2055,2059,2060,2057,2049,2036,2022,2009,2001,1999,2004,2012,2020,2023,2019,2010,1999,
+1990,1986,1988,1994,1999,2001,1998,1990,1980,1973,1972,1976,1986,1998,2010,2022,2034,2048,2065,2084,2101,
+2115,2121,2119,2112,2101,2089,2077,2065,2052,2037,2020,2003,1988,1975,1967,1960,1955,1949,1945,1943,1945,
+1950,1958,1967,1973,1976,1978,1981,1988,1999,2011,2020,2025,2025,2023,2021,2026,2037,2055,2076,2097,2115,
+2132,2146,2161,2174,2185,2191,2193,2193,2194,2202,2216,2235,2256,2274,2287,2296,2305,2319,2338,2360,2381,
+2397,2405,2409,2410,2412,2415,2416,2409,2393,2370,2345,2325,2311,2303,2292,2272,2239,2198,2156,2118,2082,
+2036,1960,1836,1659,1446,1230,1057,967,977,1080,1245,1428,1592,1714,1790,1834,1862,1890,1921,1954,1982,
+2000,2011,2017,2026,2037,2051,2062,2070,2073,2076,2082,2093,2106,2116,2119,2114,2104,2096,2096,2106,2119,
+2130,2128,2111,2082,2049,2022,2007,2004,2008,2013,2011,2003,1989,1977,1968,1966,1968,1972,1974,1974,1972,
+1969,1966,1963,1959,1952,1943,1932,1920,1910,1900,1890,1880,1870,1863,1859,1861,1867,1875,1882,1885,1882,
+1875,1867,1861,1858,1858,1859,1859,1859,1859,1860,1863,1867,1871,1872,1871,1868,1865,1863,1864,1866,1782,
+1788,1791,1791,1785,1776,1766,1756,1750,1746,1745,1744,1743,1741,1739,1736,1734,1733,1733,1736,1741,1748,
+1755,1761,1766,1769,1770,1772,1777,1785,1796,1809,1823,1834,1844,1851,1858,1866,1875,1887,1901,1916,1933,
+1952,1973,1996,2020,2044,2067,2089,2110,2131,2153,2175,2196,2215,2233,2248,2264,2280,2298,2317,2334,2349,
+2362,2372,2381,2392,2406,2422,2439,2455,2469,2483,2496,2510,2525,2539,2552,2563,2572,2580,2590,2601,2613,
+2625,2633,2639,2643,2649,2661,2679,2703,2728,2750,2765,2771,2771,2767,2765,2765,2771,2780,2792,2807,2826,
+2849,2875,2900,2922,2938,2946,2949,2951,2956,2966,2981,2997,3011,3020,3024,3025,3027,3033,3042,3055,3069,
+3082,3095,3109,3125,3146,3170,3194,3217,3235,3249,3259,3269,3279,3289,3299,3308,3314,3320,3326,3334,3345,
+3359,3374,3390,3404,3417,3430,3444,3459,3476,3492,3508,3522,3536,3548,3561,3571,3580,3586,3589,3589,3589,
+3588,3589,3591,3593,3595,3595,3595,3595,3596,3599,3603,3607,3609,3610,3608,3604,3599,3594,3587,3579,3569,
+3557,3543,3528,3514,3500,3487,3474,3459,3444,3430,3417,3409,3404,3405,3408,3412,3415,3417,3417,3416,3414,
+3413,3412,3412,3413,3414,3415,3414,3413,3408,3401,3391,3379,3369,3361,3358,3358,3359,3361,3361,3359,3356,
+3354,3354,3357,3359,3360,3357,3351,3342,3333,3326,3320,3316,3310,3301,3289,3274,3260,3248,3237,3227,3214,
+3197,3176,3155,3139,3132,3135,3147,3162,3175,3184,3187,3187,3187,3191,3197,3204,3209,3209,3202,3190,3173,
+3154,3132,3107,3080,3050,3022,2998,2979,2967,2960,2953,2943,2930,2914,2901,2893,2895,2908,2928,2951,2973,
+2991,3003,3011,3016,3018,3018,3016,3011,3002,2991,2979,2967,2954,2939,2922,2901,2877,2850,2822,2794,2767,
+2739,2709,2677,2642,2606,2571,2540,2514,2494,2478,2464,2447,2426,2398,2360,2313,2255,2187,2110,2027,1940,
+1854,1772,1695,1627,1568,1517,1474,1437,1405,1375,1348,1323,1301,1281,1262,1245,1227,1208,1185,1158,1127,
+1095,1062,1030,1001,974,948,924,900,876,851,825,798,767,734,699,662,626,593,563,536,512,
+488,462,435,405,373,338,301,262,221,181,141,104,69,37,5,-24,-55,-86,-115,-143,-167,
+-191,-214,-239,-268,-299,-332,-365,-397,-428,-458,-490,-522,-557,-592,-625,-655,-681,-703,-722,-741,-759,
+-778,-797,-817,-838,-860,-883,-910,-938,-969,-1001,-1033,-1065,-1098,-1129,-1160,-1191,-1219,-1247,-1273,-1300,-1327,
+-1354,-1384,-1413,-1443,-1473,-1503,-1532,-1561,-1591,-1620,-1648,-1675,-1702,-1728,-1755,-1784,-1814,-1844,-1874,-1902,-1927,
+-1951,-1974,-1998,-2024,-2050,-2078,-2104,-2129,-2152,-2173,-2194,-2216,-2239,-2263,-2288,-2313,-2337,-2359,-2379,-2398,-2416,
+-2434,-2454,-2474,-2497,-2519,-2540,-2559,-2576,-2590,-2604,-2618,-2634,-2653,-2673,-2693,-2713,-2730,-2746,-2761,-2775,-2791,
+-2807,-2824,-2841,-2858,-2873,-2888,-2901,-2913,-2924,-2934,-2944,-2954,-2964,-2974,-2985,-2995,-3005,-3013,-3020,-3027,-3032,
+-3038,-3043,-3046,-3048,-3048,-3047,-3046,-3047,-3050,-3055,-3061,-3066,-3069,-3070,-3068,-3066,-3063,-3062,-3064,-3066,-3070,
+-3074,-3077,-3078,-3079,-3077,-3074,-3069,-3062,-3055,-3048,-3042,-3039,-3037,-3036,-3036,-3034,-3029,-3020,-3008,-2993,-2977,
+-2962,-2949,-2938,-2930,-2923,-2917,-2909,-2901,-2892,-2883,-2877,-2873,-2871,-2868,-2862,-2851,-2836,-2821,-2809,-2803,-2802,
+-2805,-2807,-2805,-2796,-2782,-2765,-2749,-2738,-2731,-2727,-2725,-2722,-2719,-2717,-2715,-2716,-2716,-2718,-2721,-2729,-2745,
+-2771,-2806,-2844,-2877,-2896,-2900,-2890,-2875,-2866,-2870,-2885,-2906,-2922,-2925,-2916,-2904,-2905,-2934,-3000,-3097,-3210,
+-3315,-3394,-3432,-3431,-3401,-3361,-3328,-3311,-3314,-3333,-3361,-3392,-3421,-3448,-3474,-3503,-3534,-3567,-3601,-3632,-3660,
+-3685,-3709,-3734,-3760,-3788,-3816,-3843,-3868,-3890,-3911,-3931,-3953,-3976,-4000,-4023,-4043,-4061,-4076,-4091,-4108,-4128,
+-4153,-4180,-4208,-4233,-4255,-4273,-4290,-4306,-4324,-4343,-4364,-4385,-4404,-4421,-4435,-4445,-4453,-4457,-4460,-4461,-4462,
+-4464,-4468,-4473,-4480,-4487,-4494,-4501,-4507,-4514,-4520,-4526,-4529,-4529,-4526,-4521,-4515,-4510,-4506,-4501,-4496,-4489,
+-4480,-4472,-4465,-4461,-4460,-4460,-4460,-4457,-4451,-4445,-4441,-4440,-4443,-4447,-4449,-4447,-4438,-4423,-4404,-4384,-4366,
+-4351,-4339,-4329,-4320,-4312,-4306,-4302,-4298,-4294,-4290,-4283,-4275,-4266,-4258,-4251,-4245,-4239,-4230,-4219,-4205,-4190,
+-4176,-4164,-4154,-4146,-4137,-4129,-4119,-4108,-4097,-4086,-4073,-4058,-4040,-4019,-3997,-3977,-3961,-3949,-3940,-3932,-3922,
+-3910,-3896,-3881,-3866,-3852,-3839,-3825,-3809,-3791,-3770,-3748,-3727,-3708,-3691,-3674,-3656,-3637,-3617,-3596,-3575,-3555,
+-3536,-3518,-3501,-3485,-3470,-3456,-3444,-3432,-3419,-3404,-3388,-3371,-3354,-3337,-3323,-3310,-3298,-3286,-3274,-3261,-3247,
+-3234,-3220,-3207,-3193,-3179,-3165,-3151,-3137,-3124,-3110,-3096,-3082,-3068,-3055,-3043,-3033,-3025,-3018,-3011,-3005,-2997,
+-2991,-2985,-2981,-2978,-2976,-2974,-2970,-2964,-2957,-2950,-2945,-2941,-2938,-2936,-2934,-2930,-2924,-2916,-2908,-2900,-2893,
+-2887,-2882,-2877,-2872,-2867,-2861,-2855,-2849,-2844,-2841,-2838,-2836,-2834,-2832,-2830,-2826,-2821,-2816,-2810,-2803,-2795,
+-2786,-2776,-2765,-2754,-2744,-2735,-2729,-2723,-2719,-2713,-2706,-2698,-2688,-2677,-2667,-2659,-2653,-2650,-2650,-2652,-2655,
+-2659,-2662,-2664,-2663,-2658,-2649,-2636,-2620,-2601,-2582,-2563,-2544,-2526,-2509,-2492,-2476,-2460,-2443,-2428,-2414,-2402,
+-2391,-2380,-2370,-2360,-2350,-2340,-2330,-2322,-2314,-2307,-2298,-2289,-2279,-2269,-2261,-2256,-2255,-2257,-2261,-2263,-2262,
+-2259,-2254,-2247,-2240,-2233,-2227,-2219,-2210,-2200,-2190,-2179,-2169,-2160,-2150,-2140,-2129,-2119,-2110,-2106,-2105,-2107,
+-2111,-2116,-2118,-2118,-2115,-2109,-2104,-2100,-2099,-2102,-2111,-2124,-2139,-2156,-2172,-2186,-2196,-2204,-2211,-2217,-2223,
+-2229,-2232,-2231,-2224,-2212,-2197,-2179,-2160,-2140,-2119,-2096,-2071,-2044,-2018,-1994,-1973,-1957,-1946,-1939,-1937,-1938,
+-1942,-1948,-1953,-1955,-1950,-1938,-1920,-1898,-1874,-1852,-1831,-1812,-1793,-1771,-1747,-1723,-1701,-1683,-1671,-1662,-1654,
+-1646,-1635,-1622,-1610,-1599,-1592,-1588,-1584,-1580,-1573,-1563,-1551,-1538,-1524,-1510,-1495,-1478,-1460,-1443,-1427,-1415,
+-1405,-1396,-1384,-1367,-1345,-1318,-1289,-1262,-1243,-1232,-1229,-1231,-1234,-1234,-1228,-1215,-1197,-1176,-1155,-1137,-1124,
+-1114,-1106,-1099,-1089,-1075,-1058,-1037,-1015,-993,-973,-955,-940,-926,-915,-904,-893,-882,-869,-852,-833,-810,
+-783,-753,-722,-692,-663,-637,-616,-600,-587,-577,-566,-555,-540,-523,-503,-482,-461,-441,-421,-401,-380,
+-357,-332,-306,-280,-256,-235,-216,-199,-184,-169,-153,-135,-114,-90,-63,-33,-2,29,60,90,119,
+148,176,205,235,266,298,330,364,399,435,472,509,547,583,620,656,694,735,779,826,875,
+926,977,1028,1077,1123,1164,1198,1226,1248,1267,1288,1314,1345,1381,1419,1457,1492,1523,1551,1577,1602,
+1626,1647,1665,1679,1688,1696,1704,1715,1729,1745,1763,1779,1796,1813,1834,1859,1888,1918,1943,1960,1964,
+1957,1942,1923,1908,1899,1899,1909,1925,1947,1971,1996,2020,2040,2056,2066,2071,2072,2069,2065,2060,2055,
+2050,2044,2039,2036,2035,2038,2043,2047,2050,2047,2041,2032,2024,2020,2021,2025,2029,2029,2023,2011,1998,
+1989,1987,1993,2005,2020,2032,2039,2042,2043,2045,2050,2060,2071,2082,2089,2094,2096,2097,2096,2091,2082,
+2066,2045,2020,1998,1981,1971,1967,1964,1959,1951,1941,1931,1928,1931,1942,1957,1972,1986,1997,2007,2018,
+2031,2042,2051,2053,2050,2044,2039,2039,2047,2062,2080,2098,2114,2129,2142,2157,2172,2186,2195,2198,2198,
+2196,2200,2211,2229,2253,2275,2294,2306,2315,2322,2332,2345,2361,2376,2389,2399,2406,2410,2410,2406,2395,
+2379,2359,2340,2326,2317,2310,2298,2276,2240,2191,2134,2071,1999,1911,1794,1641,1458,1264,1092,975,942,
+997,1127,1299,1474,1624,1731,1798,1839,1868,1899,1934,1971,2003,2027,2044,2057,2069,2080,2089,2093,2091,
+2086,2083,2087,2098,2112,2124,2126,2118,2104,2090,2086,2093,2108,2124,2132,2127,2109,2086,2064,2049,2042,
+2041,2039,2033,2021,2007,1995,1988,1986,1989,1992,1991,1986,1977,1966,1956,1946,1938,1928,1917,1905,1891,
+1878,1864,1851,1838,1825,1815,1808,1804,1804,1804,1805,1803,1800,1796,1794,1796,1799,1803,1806,1804,1800,
+1795,1791,1790,1791,1793,1794,1792,1787,1782,1778,1779,1782,1697,1706,1714,1717,1713,1703,1691,1679,1669,
+1665,1665,1668,1673,1678,1683,1689,1695,1702,1710,1719,1728,1738,1747,1754,1759,1763,1766,1770,1776,1785,
+1797,1810,1824,1838,1850,1861,1872,1884,1897,1911,1926,1942,1960,1979,2000,2022,2046,2070,2094,2117,2140,
+2163,2186,2209,2230,2248,2263,2275,2286,2297,2309,2324,2341,2357,2373,2387,2400,2413,2426,2439,2453,2466,
+2478,2489,2498,2507,2517,2528,2540,2553,2565,2578,2589,2599,2606,2610,2614,2618,2626,2639,2659,2683,2708,
+2729,2741,2745,2742,2735,2730,2730,2736,2749,2765,2785,2805,2827,2849,2870,2889,2903,2912,2918,2922,2927,
+2937,2950,2965,2978,2986,2988,2985,2981,2980,2983,2991,3002,3015,3028,3042,3059,3079,3104,3130,3156,3179,
+3197,3211,3223,3234,3246,3258,3268,3276,3281,3286,3292,3300,3313,3327,3342,3355,3366,3376,3388,3402,3418,
+3437,3454,3470,3483,3494,3505,3517,3530,3543,3554,3561,3564,3564,3562,3561,3561,3562,3563,3564,3564,3564,
+3564,3565,3568,3570,3570,3568,3564,3559,3554,3550,3546,3540,3533,3521,3506,3488,3468,3450,3433,3418,3405,
+3394,3384,3377,3372,3371,3372,3375,3379,3382,3385,3386,3386,3386,3387,3388,3389,3390,3390,3390,3389,3385,
+3379,3370,3358,3346,3335,3328,3326,3326,3329,3331,3331,3328,3326,3325,3327,3331,3336,3339,3338,3333,3324,
+3316,3310,3305,3302,3296,3287,3272,3254,3235,3218,3203,3190,3176,3160,3142,3125,3111,3107,3111,3124,3139,
+3154,3163,3167,3168,3168,3170,3174,3178,3179,3176,3167,3154,3138,3120,3102,3081,3058,3033,3007,2984,2966,
+2953,2944,2937,2928,2915,2900,2887,2880,2881,2891,2907,2926,2941,2952,2956,2955,2951,2946,2940,2934,2927,
+2919,2911,2903,2896,2889,2880,2867,2848,2825,2797,2769,2742,2716,2691,2665,2637,2605,2571,2538,2509,2487,
+2471,2462,2454,2446,2434,2416,2390,2355,2310,2253,2184,2103,2011,1914,1815,1721,1636,1563,1502,1451,1408,
+1370,1335,1303,1273,1247,1226,1208,1194,1180,1164,1146,1123,1096,1066,1033,1000,968,937,908,881,857,
+835,813,789,763,734,700,663,626,589,556,526,499,474,448,422,394,363,331,297,261,223,
+185,146,108,73,40,8,-21,-51,-83,-115,-146,-176,-203,-227,-250,-273,-298,-326,-355,-386,-418,
+-450,-482,-516,-551,-586,-620,-652,-678,-700,-717,-732,-746,-762,-779,-799,-821,-844,-870,-898,-927,-957,
+-988,-1018,-1049,-1078,-1108,-1137,-1167,-1196,-1226,-1257,-1287,-1317,-1347,-1377,-1407,-1436,-1465,-1492,-1520,-1547,-1575,
+-1603,-1632,-1660,-1688,-1714,-1742,-1770,-1798,-1829,-1860,-1890,-1919,-1946,-1971,-1995,-2019,-2044,-2070,-2097,-2123,-2149,
+-2174,-2197,-2218,-2239,-2260,-2282,-2305,-2329,-2353,-2377,-2400,-2422,-2442,-2461,-2480,-2500,-2521,-2542,-2563,-2582,-2599,
+-2615,-2629,-2643,-2659,-2677,-2697,-2717,-2737,-2755,-2771,-2786,-2801,-2817,-2834,-2852,-2869,-2887,-2903,-2917,-2931,-2943,
+-2955,-2966,-2977,-2987,-2998,-3009,-3020,-3031,-3042,-3053,-3064,-3073,-3082,-3089,-3095,-3098,-3099,-3099,-3099,-3099,-3100,
+-3103,-3108,-3113,-3117,-3120,-3121,-3121,-3120,-3119,-3118,-3119,-3121,-3124,-3128,-3131,-3133,-3134,-3133,-3131,-3127,-3122,
+-3117,-3113,-3110,-3107,-3105,-3101,-3097,-3090,-3082,-3071,-3060,-3047,-3035,-3022,-3010,-2999,-2989,-2980,-2972,-2963,-2954,
+-2945,-2938,-2933,-2931,-2930,-2929,-2925,-2916,-2902,-2887,-2873,-2864,-2861,-2862,-2864,-2864,-2859,-2849,-2835,-2821,-2808,
+-2797,-2788,-2779,-2771,-2764,-2759,-2757,-2757,-2758,-2759,-2761,-2766,-2777,-2798,-2830,-2868,-2905,-2932,-2942,-2936,-2921,
+-2905,-2899,-2907,-2926,-2948,-2962,-2963,-2954,-2943,-2945,-2973,-3031,-3115,-3212,-3304,-3375,-3417,-3430,-3422,-3405,-3391,
+-3386,-3394,-3414,-3440,-3471,-3503,-3534,-3565,-3596,-3626,-3653,-3678,-3701,-3723,-3745,-3768,-3795,-3824,-3854,-3883,-3911,
+-3936,-3958,-3980,-4001,-4022,-4043,-4063,-4082,-4101,-4119,-4138,-4158,-4180,-4203,-4225,-4246,-4265,-4282,-4300,-4319,-4341,
+-4364,-4389,-4412,-4433,-4451,-4465,-4477,-4487,-4496,-4502,-4508,-4512,-4516,-4520,-4526,-4532,-4539,-4546,-4552,-4557,-4562,
+-4566,-4570,-4574,-4576,-4575,-4572,-4568,-4562,-4558,-4554,-4551,-4548,-4542,-4535,-4526,-4517,-4510,-4505,-4501,-4497,-4492,
+-4486,-4480,-4476,-4475,-4478,-4483,-4487,-4487,-4482,-4470,-4454,-4435,-4416,-4397,-4380,-4366,-4353,-4343,-4336,-4330,-4327,
+-4323,-4319,-4313,-4306,-4298,-4292,-4286,-4282,-4277,-4270,-4260,-4248,-4234,-4220,-4207,-4195,-4185,-4175,-4165,-4155,-4144,
+-4134,-4124,-4113,-4099,-4082,-4063,-4042,-4023,-4006,-3992,-3982,-3972,-3962,-3949,-3935,-3921,-3906,-3893,-3880,-3867,-3852,
+-3835,-3816,-3796,-3775,-3754,-3735,-3717,-3699,-3682,-3665,-3647,-3630,-3613,-3596,-3578,-3559,-3541,-3524,-3509,-3496,-3483,
+-3471,-3457,-3441,-3424,-3407,-3389,-3373,-3358,-3343,-3329,-3315,-3301,-3287,-3274,-3262,-3250,-3238,-3227,-3215,-3202,-3190,
+-3178,-3166,-3153,-3140,-3127,-3113,-3101,-3090,-3080,-3072,-3064,-3057,-3051,-3045,-3041,-3038,-3037,-3035,-3033,-3028,-3021,
+-3014,-3006,-3000,-2996,-2994,-2993,-2991,-2989,-2984,-2978,-2970,-2961,-2952,-2944,-2937,-2930,-2923,-2916,-2909,-2903,-2897,
+-2893,-2889,-2886,-2884,-2882,-2880,-2877,-2874,-2871,-2868,-2864,-2861,-2856,-2850,-2842,-2831,-2819,-2807,-2796,-2788,-2781,
+-2776,-2771,-2765,-2757,-2747,-2735,-2724,-2713,-2704,-2695,-2688,-2681,-2675,-2670,-2667,-2665,-2665,-2665,-2664,-2660,-2654,
+-2646,-2636,-2625,-2614,-2603,-2592,-2579,-2565,-2549,-2532,-2515,-2501,-2488,-2476,-2465,-2453,-2439,-2423,-2407,-2392,-2379,
+-2369,-2360,-2352,-2344,-2335,-2327,-2320,-2316,-2314,-2314,-2315,-2315,-2313,-2308,-2303,-2297,-2291,-2285,-2279,-2272,-2264,
+-2255,-2246,-2236,-2226,-2216,-2206,-2194,-2181,-2169,-2159,-2152,-2149,-2149,-2151,-2155,-2158,-2160,-2160,-2160,-2159,-2158,
+-2159,-2162,-2168,-2176,-2187,-2198,-2207,-2215,-2221,-2226,-2231,-2237,-2246,-2255,-2262,-2266,-2264,-2257,-2247,-2235,-2223,
+-2211,-2198,-2182,-2162,-2138,-2110,-2080,-2051,-2023,-2000,-1980,-1964,-1953,-1945,-1942,-1941,-1941,-1939,-1935,-1930,-1923,
+-1916,-1909,-1903,-1893,-1879,-1858,-1831,-1801,-1772,-1746,-1726,-1711,-1699,-1689,-1677,-1663,-1648,-1634,-1623,-1615,-1608,
+-1602,-1595,-1586,-1576,-1566,-1555,-1544,-1531,-1517,-1501,-1483,-1464,-1446,-1429,-1413,-1395,-1377,-1358,-1339,-1323,-1312,
+-1307,-1307,-1310,-1313,-1311,-1302,-1287,-1266,-1243,-1219,-1197,-1179,-1162,-1148,-1133,-1119,-1104,-1088,-1070,-1052,-1032,
+-1011,-991,-971,-952,-936,-922,-911,-900,-890,-879,-865,-848,-828,-804,-778,-749,-720,-691,-664,-641,-621,
+-605,-592,-579,-566,-551,-535,-519,-503,-488,-474,-460,-444,-425,-402,-376,-348,-321,-295,-273,-253,-236,
+-219,-201,-180,-157,-131,-103,-74,-43,-13,16,45,74,103,131,160,188,216,244,273,305,340,
+378,419,461,502,540,576,610,643,678,717,759,804,851,898,946,993,1040,1086,1130,1171,1208,
+1240,1269,1298,1326,1356,1388,1421,1452,1481,1508,1534,1560,1588,1616,1643,1667,1686,1700,1710,1718,1726,
+1736,1747,1760,1773,1787,1802,1819,1837,1857,1876,1893,1906,1915,1920,1925,1929,1934,1939,1944,1948,1952,
+1958,1968,1983,2002,2023,2042,2055,2061,2061,2057,2052,2049,2049,2051,2056,2061,2065,2069,2072,2075,2077,
+2078,2077,2075,2074,2074,2077,2080,2080,2076,2065,2048,2029,2014,2008,2012,2024,2039,2051,2054,2048,2036,
+2020,2007,2000,1999,2001,2006,2012,2020,2032,2047,2062,2074,2077,2067,2047,2020,1993,1973,1962,1959,1959,
+1956,1947,1932,1917,1906,1905,1914,1932,1954,1976,1996,2014,2030,2045,2058,2066,2068,2064,2057,2050,2048,
+2053,2064,2078,2092,2105,2117,2130,2146,2165,2185,2201,2212,2217,2218,2220,2228,2242,2262,2285,2305,2319,
+2329,2335,2341,2348,2358,2369,2380,2389,2395,2397,2396,2389,2377,2360,2341,2322,2304,2289,2273,2253,2222,
+2177,2118,2045,1956,1849,1722,1571,1402,1227,1070,958,913,948,1056,1216,1396,1562,1693,1782,1836,1868,
+1895,1924,1959,1995,2027,2052,2071,2085,2097,2106,2110,2107,2098,2087,2080,2080,2088,2100,2108,2107,2095,
+2074,2053,2039,2037,2044,2055,2062,2060,2049,2033,2017,2004,1997,1992,1986,1976,1963,1948,1936,1930,1929,
+1932,1933,1931,1923,1912,1899,1887,1876,1867,1858,1847,1835,1822,1808,1794,1782,1771,1761,1753,1746,1741,
+1736,1730,1724,1717,1711,1709,1711,1717,1727,1736,1741,1740,1734,1724,1715,1709,1706,1705,1704,1701,1696,
+1691,1688,1691,1697,1618,1630,1642,1649,1650,1645,1635,1624,1616,1611,1610,1613,1618,1625,1634,1643,1655,
+1667,1681,1694,1706,1717,1726,1734,1741,1748,1756,1766,1778,1791,1806,1821,1836,1851,1866,1880,1895,1909,
+1924,1939,1955,1972,1989,2009,2031,2054,2079,2104,2129,2153,2176,2198,2219,2240,2258,2274,2287,2297,2306,
+2316,2329,2343,2360,2378,2396,2412,2427,2440,2454,2466,2478,2489,2498,2505,2511,2516,2522,2530,2539,2550,
+2562,2573,2582,2588,2591,2594,2597,2604,2617,2636,2658,2680,2698,2708,2709,2704,2696,2690,2691,2700,2716,
+2738,2761,2784,2806,2826,2844,2860,2873,2883,2890,2896,2903,2912,2925,2939,2952,2960,2961,2957,2950,2943,
+2940,2942,2949,2959,2971,2984,2999,3018,3042,3068,3095,3121,3142,3158,3172,3185,3199,3213,3227,3239,3247,
+3253,3259,3265,3275,3287,3300,3312,3321,3327,3334,3345,3359,3378,3399,3418,3433,3445,3454,3463,3475,3489,
+3505,3520,3529,3534,3533,3531,3528,3528,3529,3531,3533,3533,3533,3531,3531,3531,3532,3531,3529,3524,3519,
+3513,3508,3504,3500,3494,3482,3466,3446,3424,3402,3384,3369,3358,3351,3346,3344,3342,3343,3344,3346,3347,
+3349,3351,3353,3354,3357,3359,3360,3361,3361,3361,3360,3357,3353,3347,3339,3328,3316,3305,3298,3294,3294,
+3297,3299,3300,3300,3299,3300,3303,3309,3314,3318,3318,3314,3307,3300,3294,3290,3286,3280,3268,3251,3229,
+3206,3185,3168,3153,3141,3129,3117,3105,3097,3094,3097,3106,3117,3127,3133,3137,3139,3141,3145,3150,3154,
+3154,3150,3140,3126,3110,3093,3077,3060,3041,3020,2998,2978,2961,2948,2938,2928,2917,2901,2884,2867,2855,
+2851,2856,2867,2881,2892,2898,2896,2889,2879,2868,2859,2851,2846,2843,2841,2841,2842,2840,2835,2824,2805,
+2781,2752,2722,2693,2667,2643,2618,2592,2565,2538,2513,2494,2480,2471,2465,2458,2448,2434,2415,2392,2365,
+2332,2291,2237,2168,2083,1986,1881,1775,1676,1587,1511,1448,1394,1347,1304,1265,1230,1200,1175,1155,1138,
+1123,1107,1090,1069,1045,1018,990,961,932,902,874,846,819,794,768,741,712,680,647,612,578,
+546,516,489,463,436,409,380,349,317,285,253,220,186,150,113,77,41,8,-23,-54,-86,
+-118,-151,-184,-216,-245,-271,-293,-313,-334,-355,-380,-407,-438,-471,-507,-544,-581,-618,-651,-679,-702,
+-719,-731,-742,-752,-765,-781,-801,-825,-852,-882,-913,-944,-976,-1006,-1036,-1064,-1091,-1118,-1145,-1173,-1202,
+-1232,-1263,-1295,-1327,-1358,-1389,-1420,-1450,-1480,-1508,-1536,-1563,-1591,-1618,-1645,-1672,-1700,-1728,-1757,-1787,-1818,
+-1849,-1881,-1911,-1940,-1967,-1993,-2018,-2043,-2068,-2093,-2119,-2145,-2171,-2196,-2219,-2242,-2262,-2283,-2303,-2323,-2345,
+-2369,-2394,-2419,-2444,-2467,-2488,-2508,-2527,-2545,-2564,-2583,-2602,-2619,-2636,-2651,-2667,-2684,-2702,-2721,-2740,-2758,
+-2774,-2789,-2803,-2817,-2833,-2850,-2870,-2890,-2910,-2929,-2947,-2963,-2977,-2990,-3002,-3014,-3024,-3034,-3044,-3054,-3065,
+-3076,-3088,-3101,-3113,-3123,-3132,-3138,-3143,-3146,-3149,-3152,-3156,-3159,-3163,-3166,-3169,-3170,-3171,-3171,-3172,-3173,
+-3174,-3176,-3178,-3181,-3183,-3186,-3187,-3188,-3187,-3185,-3181,-3177,-3173,-3171,-3171,-3173,-3174,-3174,-3170,-3163,-3152,
+-3140,-3127,-3114,-3102,-3091,-3080,-3069,-3059,-3049,-3040,-3030,-3021,-3012,-3003,-2996,-2990,-2987,-2987,-2986,-2983,-2976,
+-2965,-2951,-2937,-2927,-2921,-2920,-2922,-2923,-2921,-2914,-2904,-2892,-2879,-2866,-2854,-2841,-2828,-2816,-2807,-2801,-2800,
+-2801,-2803,-2806,-2810,-2818,-2835,-2861,-2894,-2930,-2960,-2978,-2979,-2968,-2951,-2938,-2937,-2949,-2970,-2991,-3004,-3004,
+-2995,-2985,-2986,-3007,-3052,-3119,-3197,-3275,-3341,-3390,-3420,-3435,-3442,-3448,-3457,-3472,-3492,-3516,-3544,-3573,-3603,
+-3632,-3659,-3685,-3707,-3728,-3747,-3767,-3790,-3815,-3844,-3876,-3908,-3940,-3971,-3998,-4023,-4044,-4063,-4080,-4096,-4112,
+-4130,-4151,-4174,-4200,-4225,-4248,-4268,-4285,-4300,-4315,-4333,-4354,-4378,-4405,-4430,-4452,-4471,-4485,-4497,-4508,-4518,
+-4528,-4537,-4545,-4552,-4558,-4565,-4572,-4581,-4590,-4597,-4603,-4608,-4611,-4614,-4617,-4619,-4620,-4618,-4614,-4609,-4602,
+-4597,-4594,-4591,-4589,-4586,-4580,-4573,-4564,-4556,-4549,-4544,-4539,-4534,-4529,-4523,-4517,-4513,-4511,-4511,-4510,-4507,
+-4501,-4492,-4478,-4463,-4447,-4431,-4416,-4403,-4391,-4381,-4373,-4368,-4364,-4362,-4359,-4354,-4348,-4340,-4332,-4324,-4316,
+-4309,-4301,-4293,-4284,-4274,-4263,-4251,-4239,-4226,-4213,-4200,-4188,-4176,-4166,-4156,-4147,-4135,-4121,-4104,-4086,-4067,
+-4049,-4033,-4020,-4008,-3997,-3985,-3972,-3960,-3947,-3934,-3921,-3908,-3894,-3877,-3860,-3840,-3820,-3799,-3779,-3758,-3739,
+-3721,-3705,-3691,-3677,-3664,-3650,-3635,-3618,-3600,-3582,-3565,-3549,-3535,-3521,-3507,-3491,-3475,-3459,-3443,-3427,-3411,
+-3396,-3380,-3364,-3348,-3333,-3319,-3307,-3295,-3283,-3272,-3260,-3248,-3236,-3225,-3213,-3202,-3191,-3181,-3170,-3160,-3151,
+-3143,-3135,-3127,-3119,-3111,-3105,-3100,-3097,-3095,-3093,-3090,-3086,-3079,-3071,-3062,-3055,-3049,-3045,-3043,-3042,-3040,
+-3037,-3033,-3028,-3021,-3014,-3006,-2998,-2991,-2984,-2977,-2970,-2963,-2956,-2950,-2945,-2940,-2936,-2932,-2929,-2927,-2924,
+-2922,-2919,-2917,-2915,-2913,-2909,-2903,-2894,-2884,-2872,-2860,-2849,-2841,-2834,-2828,-2823,-2816,-2809,-2801,-2792,-2783,
+-2774,-2763,-2751,-2738,-2723,-2709,-2696,-2687,-2682,-2680,-2680,-2679,-2677,-2672,-2667,-2661,-2654,-2648,-2641,-2633,-2622,
+-2610,-2598,-2587,-2579,-2572,-2567,-2560,-2550,-2535,-2516,-2495,-2473,-2453,-2435,-2420,-2407,-2395,-2385,-2376,-2371,-2368,
+-2368,-2370,-2371,-2371,-2367,-2362,-2354,-2346,-2338,-2332,-2325,-2319,-2313,-2306,-2299,-2291,-2282,-2272,-2262,-2250,-2237,
+-2226,-2217,-2210,-2206,-2203,-2202,-2202,-2201,-2201,-2201,-2202,-2203,-2205,-2207,-2210,-2215,-2221,-2228,-2237,-2245,-2252,
+-2256,-2258,-2259,-2261,-2263,-2266,-2267,-2267,-2265,-2260,-2255,-2250,-2246,-2244,-2241,-2236,-2225,-2209,-2188,-2163,-2136,
+-2108,-2080,-2053,-2027,-2002,-1980,-1962,-1948,-1939,-1932,-1929,-1929,-1931,-1935,-1942,-1947,-1948,-1943,-1929,-1907,-1878,
+-1847,-1818,-1793,-1774,-1759,-1745,-1730,-1714,-1696,-1679,-1663,-1650,-1639,-1630,-1621,-1612,-1602,-1593,-1585,-1578,-1569,
+-1559,-1547,-1532,-1514,-1494,-1472,-1449,-1426,-1402,-1380,-1362,-1350,-1344,-1345,-1349,-1354,-1354,-1348,-1334,-1314,-1291,
+-1268,-1247,-1229,-1213,-1197,-1179,-1160,-1139,-1118,-1098,-1078,-1058,-1038,-1017,-995,-972,-951,-932,-916,-903,-894,
+-885,-875,-864,-851,-835,-816,-795,-772,-747,-722,-697,-675,-655,-637,-621,-605,-589,-573,-556,-540,-525,
+-511,-498,-485,-470,-451,-429,-404,-378,-353,-329,-309,-290,-273,-253,-232,-208,-180,-151,-121,-90,-60,
+-30,0,30,61,92,123,152,178,202,227,252,283,319,360,405,451,494,532,565,595,624,
+657,693,735,779,823,867,908,949,991,1036,1083,1132,1179,1224,1264,1299,1330,1358,1385,1412,1438,
+1464,1490,1517,1545,1576,1607,1639,1667,1691,1708,1720,1727,1732,1736,1742,1751,1762,1776,1792,1807,1822,
+1836,1848,1859,1873,1890,1913,1941,1971,2000,2021,2031,2029,2017,2002,1989,1984,1987,1998,2011,2023,2031,
+2034,2035,2037,2042,2050,2060,2070,2076,2079,2079,2077,2076,2078,2083,2091,2102,2114,2125,2133,2135,2128,
+2111,2086,2058,2033,2016,2011,2016,2026,2033,2032,2018,1995,1967,1941,1922,1910,1904,1900,1895,1890,1889,
+1894,1908,1929,1950,1964,1965,1952,1930,1907,1892,1889,1898,1913,1928,1936,1937,1932,1927,1929,1939,1956,
+1978,2001,2021,2038,2052,2064,2073,2077,2076,2069,2059,2049,2043,2044,2052,2064,2078,2093,2109,2126,2147,
+2171,2197,2220,2238,2249,2254,2256,2261,2270,2285,2302,2320,2334,2345,2352,2358,2363,2369,2376,2381,2385,
+2386,2384,2379,2370,2358,2342,2322,2298,2271,2241,2206,2165,2116,2056,1984,1897,1793,1670,1529,1373,1214,
+1069,959,907,925,1013,1159,1334,1510,1662,1773,1843,1883,1906,1927,1952,1982,2014,2043,2066,2083,2097,
+2109,2117,2120,2116,2107,2096,2088,2087,2092,2099,2103,2097,2080,2055,2028,2006,1993,1988,1988,1987,1980,
+1969,1954,1941,1931,1925,1920,1912,1900,1884,1868,1854,1845,1842,1841,1840,1836,1829,1819,1808,1799,1790,
+1782,1774,1764,1752,1739,1725,1712,1701,1692,1685,1679,1675,1671,1666,1660,1652,1643,1635,1631,1632,1639,
+1650,1660,1668,1670,1666,1658,1649,1642,1636,1632,1627,1621,1614,1607,1605,1609,1618,1553,1566,1580,1591,
+1598,1599,1595,1590,1584,1580,1579,1579,1582,1586,1594,1604,1617,1631,1647,1662,1675,1686,1695,1703,1712,
+1722,1735,1750,1766,1782,1800,1817,1834,1851,1868,1886,1904,1922,1939,1958,1976,1995,2016,2038,2063,2088,
+2115,2142,2167,2191,2213,2234,2252,2269,2284,2296,2306,2315,2325,2336,2349,2365,2383,2402,2420,2437,2452,
+2466,2479,2491,2502,2511,2518,2523,2526,2529,2531,2535,2541,2548,2556,2563,2568,2572,2575,2579,2587,2599,
+2615,2633,2651,2664,2670,2669,2663,2657,2653,2657,2669,2689,2712,2737,2760,2780,2798,2814,2828,2842,2853,
+2863,2870,2877,2886,2896,2908,2920,2929,2933,2932,2925,2918,2912,2910,2913,2920,2929,2939,2951,2966,2985,
+3008,3033,3059,3082,3102,3118,3133,3147,3163,3180,3196,3210,3220,3227,3234,3242,3252,3264,3274,3282,3287,
+3290,3295,3305,3320,3340,3362,3381,3396,3405,3412,3420,3431,3447,3464,3479,3489,3494,3494,3492,3490,3490,
+3492,3494,3495,3494,3490,3487,3486,3486,3488,3490,3490,3486,3480,3473,3465,3458,3451,3443,3432,3416,3398,
+3379,3361,3346,3335,3328,3324,3321,3320,3318,3317,3315,3314,3313,3313,3313,3314,3317,3320,3323,3325,3326,
+3325,3322,3320,3316,3312,3307,3301,3292,3282,3273,3265,3261,3261,3264,3268,3271,3273,3275,3277,3281,3286,
+3291,3294,3295,3292,3286,3279,3273,3267,3261,3253,3240,3222,3200,3177,3156,3139,3126,3116,3108,3101,3094,
+3089,3087,3088,3092,3097,3101,3104,3107,3109,3114,3120,3127,3132,3134,3129,3118,3102,3085,3067,3050,3033,
+3016,2998,2979,2961,2945,2932,2920,2907,2891,2871,2847,2824,2806,2795,2793,2799,2809,2818,2823,2823,2817,
+2810,2801,2795,2791,2791,2792,2795,2798,2800,2799,2792,2778,2759,2733,2705,2675,2647,2621,2596,2573,2551,
+2531,2514,2503,2496,2492,2488,2480,2465,2443,2414,2383,2353,2327,2303,2276,2241,2190,2121,2034,1933,1826,
+1720,1623,1537,1464,1402,1349,1302,1259,1221,1186,1156,1130,1107,1085,1064,1041,1017,993,968,943,919,
+895,871,846,819,791,760,728,695,660,624,589,556,526,499,473,449,424,397,368,336,302,
+269,236,205,174,143,111,77,42,8,-25,-58,-89,-121,-153,-186,-220,-253,-283,-311,-335,-355,
+-374,-394,-416,-441,-471,-504,-541,-578,-615,-649,-678,-701,-720,-733,-743,-753,-764,-777,-794,-815,-840,
+-868,-898,-930,-961,-992,-1022,-1050,-1077,-1102,-1128,-1155,-1183,-1213,-1244,-1275,-1305,-1336,-1366,-1396,-1426,-1456,
+-1487,-1518,-1549,-1578,-1606,-1633,-1660,-1687,-1715,-1745,-1776,-1809,-1842,-1875,-1906,-1936,-1963,-1990,-2016,-2041,-2068,
+-2094,-2120,-2146,-2171,-2195,-2219,-2243,-2266,-2289,-2311,-2332,-2353,-2375,-2398,-2423,-2448,-2473,-2497,-2519,-2539,-2556,
+-2573,-2590,-2607,-2624,-2642,-2659,-2676,-2693,-2711,-2729,-2748,-2767,-2784,-2799,-2813,-2825,-2837,-2850,-2866,-2885,-2906,
+-2928,-2951,-2972,-2991,-3009,-3025,-3039,-3051,-3062,-3072,-3081,-3090,-3100,-3112,-3124,-3138,-3151,-3163,-3173,-3181,-3187,
+-3193,-3200,-3207,-3214,-3221,-3227,-3230,-3231,-3230,-3229,-3228,-3228,-3229,-3232,-3235,-3238,-3241,-3243,-3245,-3246,-3245,
+-3243,-3239,-3234,-3229,-3226,-3226,-3228,-3233,-3237,-3240,-3238,-3232,-3222,-3209,-3195,-3182,-3170,-3159,-3148,-3137,-3126,
+-3116,-3106,-3097,-3088,-3079,-3069,-3059,-3051,-3046,-3043,-3041,-3039,-3034,-3026,-3015,-3003,-2992,-2985,-2983,-2984,-2985,
+-2985,-2981,-2973,-2962,-2950,-2937,-2924,-2909,-2894,-2879,-2866,-2857,-2852,-2852,-2855,-2859,-2863,-2870,-2882,-2902,-2929,
+-2962,-2994,-3019,-3030,-3028,-3016,-3000,-2990,-2991,-3002,-3021,-3039,-3050,-3052,-3046,-3038,-3036,-3049,-3080,-3127,-3186,
+-3250,-3312,-3366,-3410,-3445,-3471,-3492,-3511,-3529,-3547,-3569,-3592,-3618,-3646,-3674,-3701,-3725,-3747,-3767,-3786,-3807,
+-3831,-3858,-3890,-3925,-3961,-3997,-4029,-4057,-4078,-4094,-4107,-4117,-4129,-4145,-4166,-4192,-4221,-4250,-4276,-4298,-4317,
+-4333,-4349,-4368,-4389,-4413,-4437,-4459,-4478,-4494,-4508,-4521,-4534,-4548,-4562,-4573,-4582,-4589,-4594,-4600,-4608,-4617,
+-4627,-4636,-4645,-4651,-4655,-4659,-4662,-4664,-4664,-4662,-4657,-4650,-4642,-4635,-4630,-4626,-4623,-4620,-4616,-4610,-4603,
+-4597,-4592,-4588,-4585,-4581,-4576,-4569,-4561,-4553,-4545,-4539,-4532,-4525,-4516,-4505,-4493,-4481,-4469,-4458,-4448,-4438,
+-4429,-4420,-4413,-4408,-4405,-4404,-4403,-4400,-4395,-4386,-4375,-4361,-4348,-4335,-4324,-4314,-4306,-4299,-4291,-4283,-4273,
+-4262,-4250,-4237,-4225,-4213,-4202,-4192,-4182,-4170,-4156,-4140,-4123,-4104,-4086,-4070,-4055,-4042,-4031,-4021,-4011,-4000,
+-3989,-3976,-3962,-3947,-3931,-3915,-3898,-3882,-3864,-3846,-3827,-3807,-3787,-3768,-3750,-3735,-3722,-3711,-3699,-3686,-3671,
+-3654,-3637,-3620,-3602,-3586,-3569,-3553,-3536,-3520,-3505,-3490,-3476,-3462,-3448,-3433,-3417,-3401,-3385,-3370,-3357,-3344,
+-3332,-3320,-3307,-3294,-3281,-3268,-3256,-3245,-3235,-3227,-3219,-3213,-3208,-3202,-3197,-3191,-3184,-3176,-3169,-3163,-3158,
+-3155,-3152,-3148,-3143,-3136,-3128,-3119,-3111,-3104,-3098,-3094,-3091,-3088,-3085,-3082,-3078,-3074,-3070,-3065,-3061,-3055,
+-3050,-3044,-3038,-3030,-3022,-3013,-3005,-2997,-2991,-2986,-2982,-2979,-2977,-2975,-2972,-2970,-2968,-2966,-2964,-2960,-2955,
+-2947,-2937,-2925,-2913,-2903,-2893,-2886,-2879,-2873,-2867,-2861,-2855,-2849,-2843,-2834,-2824,-2810,-2795,-2779,-2764,-2751,
+-2741,-2734,-2728,-2721,-2714,-2706,-2697,-2688,-2681,-2674,-2667,-2659,-2651,-2643,-2637,-2633,-2633,-2634,-2637,-2636,-2632,
+-2622,-2606,-2587,-2566,-2545,-2525,-2506,-2487,-2469,-2451,-2436,-2425,-2418,-2416,-2417,-2418,-2418,-2415,-2409,-2402,-2393,
+-2385,-2378,-2372,-2366,-2361,-2357,-2351,-2345,-2338,-2328,-2318,-2306,-2295,-2285,-2276,-2270,-2266,-2262,-2257,-2252,-2248,
+-2245,-2244,-2244,-2246,-2249,-2251,-2252,-2254,-2257,-2262,-2269,-2277,-2284,-2289,-2292,-2291,-2288,-2284,-2279,-2274,-2269,
+-2264,-2259,-2256,-2254,-2254,-2255,-2256,-2255,-2251,-2243,-2232,-2218,-2200,-2181,-2159,-2134,-2107,-2079,-2051,-2026,-2004,
+-1986,-1973,-1963,-1957,-1955,-1957,-1961,-1966,-1970,-1969,-1962,-1947,-1926,-1902,-1878,-1857,-1839,-1823,-1809,-1793,-1776,
+-1756,-1737,-1718,-1701,-1686,-1672,-1660,-1648,-1636,-1625,-1616,-1608,-1600,-1592,-1583,-1571,-1557,-1540,-1521,-1498,-1472,
+-1445,-1419,-1396,-1379,-1370,-1367,-1369,-1370,-1368,-1359,-1344,-1324,-1303,-1284,-1267,-1253,-1239,-1224,-1205,-1184,-1161,
+-1138,-1118,-1099,-1082,-1065,-1046,-1024,-1001,-977,-956,-938,-923,-911,-900,-890,-878,-864,-849,-832,-813,-793,
+-772,-750,-729,-708,-689,-672,-656,-639,-622,-604,-585,-566,-548,-532,-516,-500,-483,-464,-443,-421,-399,
+-378,-359,-341,-323,-304,-283,-259,-231,-202,-171,-141,-110,-80,-50,-18,14,48,82,113,142,166,
+188,209,234,264,303,349,399,449,494,532,562,587,611,638,671,709,750,791,830,865,901,
+939,983,1033,1088,1145,1198,1246,1286,1320,1349,1376,1403,1432,1461,1490,1518,1546,1574,1601,1629,1655,
+1680,1700,1716,1727,1735,1740,1745,1752,1763,1777,1794,1811,1827,1840,1852,1864,1879,1901,1933,1972,2014,
+2054,2083,2097,2095,2079,2057,2035,2019,2011,2011,2015,2020,2024,2026,2028,2032,2039,2050,2060,2067,2070,
+2069,2065,2061,2061,2067,2079,2096,2116,2134,2147,2152,2145,2126,2096,2062,2027,2001,1986,1982,1986,1988,
+1982,1964,1932,1895,1860,1836,1826,1826,1829,1827,1814,1792,1764,1741,1728,1727,1735,1744,1747,1742,1730,
+1721,1722,1741,1778,1826,1877,1923,1958,1983,2000,2016,2033,2053,2074,2092,2106,2114,2117,2116,2110,2101,
+2089,2072,2055,2039,2029,2027,2034,2049,2069,2092,2118,2144,2172,2199,2225,2247,2262,2270,2273,2275,2278,
+2287,2300,2317,2334,2348,2358,2364,2368,2371,2374,2377,2378,2377,2374,2368,2360,2351,2340,2326,2306,2280,
+2245,2200,2143,2075,1997,1910,1814,1711,1598,1477,1349,1220,1102,1009,958,962,1027,1146,1303,1472,1630,
+1757,1845,1897,1923,1938,1953,1973,1998,2025,2050,2070,2087,2100,2112,2120,2125,2124,2120,2113,2108,2106,
+2107,2107,2103,2091,2071,2044,2017,1993,1976,1965,1956,1946,1932,1916,1900,1886,1877,1870,1865,1858,1846,
+1831,1814,1798,1785,1776,1770,1764,1757,1748,1739,1730,1722,1716,1710,1704,1696,1686,1675,1663,1651,1640,
+1629,1620,1614,1609,1607,1605,1602,1597,1590,1582,1575,1571,1573,1579,1587,1595,1601,1604,1603,1600,1596,
+1592,1586,1579,1569,1559,1549,1544,1545,1553,1513,1521,1532,1543,1551,1555,1557,1556,1555,1553,1553,1553,
+1554,1558,1565,1575,1589,1605,1622,1638,1651,1662,1671,1679,1689,1701,1715,1731,1749,1767,1785,1804,1824,
+1844,1865,1886,1907,1929,1950,1971,1993,2016,2040,2066,2092,2119,2146,2173,2198,2222,2244,2264,2282,2297,
+2308,2317,2324,2331,2339,2350,2364,2380,2398,2416,2434,2450,2464,2478,2490,2501,2511,2519,2525,2529,2531,
+2532,2533,2535,2538,2541,2544,2548,2551,2555,2560,2569,2581,2595,2609,2622,2630,2632,2628,2622,2618,2618,
+2627,2644,2667,2692,2716,2736,2752,2763,2774,2786,2799,2813,2826,2838,2847,2854,2862,2871,2881,2891,2898,
+2901,2900,2895,2890,2888,2888,2893,2900,2909,2919,2929,2942,2959,2978,3001,3023,3044,3063,3080,3095,3112,
+3129,3147,3163,3176,3186,3195,3202,3211,3222,3233,3243,3251,3256,3260,3266,3276,3292,3312,3332,3349,3360,
+3367,3372,3379,3389,3403,3419,3433,3442,3447,3447,3447,3447,3449,3452,3454,3453,3449,3444,3439,3437,3439,
+3443,3447,3449,3447,3439,3429,3417,3405,3394,3384,3373,3361,3348,3335,3323,3314,3308,3304,3300,3296,3292,
+3288,3283,3279,3276,3273,3272,3272,3273,3276,3280,3283,3286,3286,3285,3281,3276,3271,3267,3263,3258,3252,
+3246,3239,3233,3231,3231,3234,3239,3244,3247,3250,3253,3256,3260,3264,3268,3269,3267,3262,3255,3246,3237,
+3228,3217,3204,3189,3171,3153,3136,3121,3109,3100,3093,3086,3081,3076,3074,3074,3076,3078,3081,3083,3086,
+3089,3094,3100,3107,3111,3111,3104,3092,3076,3057,3038,3019,3002,2985,2969,2952,2935,2919,2903,2887,2868,
+2847,2822,2795,2769,2747,2732,2726,2726,2731,2737,2741,2743,2743,2742,2742,2743,2745,2749,2752,2754,2753,
+2748,2739,2726,2709,2689,2667,2644,2621,2598,2577,2555,2536,2518,2505,2497,2496,2498,2500,2497,2485,2460,
+2424,2381,2337,2299,2270,2248,2229,2205,2168,2112,2036,1944,1842,1738,1640,1554,1479,1417,1365,1320,1279,
+1241,1205,1171,1139,1109,1079,1050,1021,992,963,936,911,887,865,843,820,795,767,735,699,661,
+621,581,544,510,480,454,431,409,385,359,329,295,259,222,187,154,123,93,63,33,1,
+-30,-63,-95,-127,-158,-190,-222,-255,-287,-319,-348,-373,-396,-417,-438,-460,-486,-515,-547,-581,-615,
+-646,-673,-695,-712,-725,-737,-748,-760,-775,-792,-812,-835,-860,-887,-916,-946,-976,-1006,-1035,-1062,-1089,
+-1115,-1143,-1171,-1202,-1233,-1266,-1298,-1328,-1357,-1385,-1413,-1440,-1469,-1500,-1531,-1563,-1595,-1625,-1654,-1681,-1709,
+-1738,-1769,-1802,-1836,-1870,-1903,-1934,-1963,-1989,-2015,-2042,-2070,-2098,-2126,-2154,-2179,-2202,-2225,-2247,-2270,-2295,
+-2320,-2345,-2369,-2393,-2416,-2439,-2462,-2486,-2510,-2533,-2554,-2573,-2590,-2606,-2621,-2637,-2653,-2670,-2688,-2705,-2723,
+-2741,-2760,-2779,-2798,-2816,-2832,-2846,-2858,-2869,-2880,-2894,-2910,-2929,-2950,-2972,-2993,-3014,-3033,-3051,-3068,-3084,
+-3097,-3109,-3119,-3129,-3140,-3151,-3164,-3178,-3193,-3206,-3218,-3227,-3235,-3241,-3249,-3257,-3267,-3276,-3284,-3289,-3291,
+-3291,-3289,-3288,-3287,-3288,-3290,-3292,-3294,-3296,-3298,-3299,-3300,-3301,-3299,-3296,-3292,-3287,-3283,-3282,-3284,-3289,
+-3294,-3297,-3298,-3294,-3287,-3277,-3266,-3255,-3244,-3232,-3220,-3208,-3196,-3185,-3175,-3166,-3158,-3148,-3137,-3125,-3114,
+-3106,-3101,-3100,-3099,-3097,-3091,-3081,-3069,-3058,-3049,-3045,-3045,-3047,-3049,-3048,-3043,-3034,-3023,-3010,-2996,-2981,
+-2965,-2948,-2932,-2919,-2911,-2907,-2907,-2910,-2914,-2920,-2929,-2944,-2967,-2996,-3029,-3059,-3081,-3091,-3087,-3075,-3059,
+-3049,-3047,-3056,-3072,-3090,-3105,-3111,-3111,-3106,-3103,-3107,-3124,-3154,-3196,-3248,-3304,-3361,-3413,-3458,-3495,-3525,
+-3548,-3568,-3587,-3608,-3633,-3661,-3692,-3722,-3751,-3777,-3798,-3817,-3835,-3855,-3879,-3907,-3940,-3976,-4012,-4047,-4078,
+-4102,-4120,-4134,-4145,-4157,-4171,-4191,-4215,-4242,-4269,-4296,-4320,-4341,-4362,-4382,-4403,-4425,-4447,-4467,-4484,-4499,
+-4513,-4528,-4544,-4562,-4581,-4599,-4613,-4623,-4628,-4631,-4634,-4638,-4646,-4655,-4665,-4675,-4683,-4688,-4693,-4697,-4699,
+-4701,-4700,-4698,-4693,-4687,-4680,-4674,-4669,-4663,-4658,-4652,-4645,-4639,-4635,-4632,-4630,-4628,-4625,-4619,-4611,-4602,
+-4593,-4584,-4577,-4569,-4561,-4550,-4538,-4525,-4511,-4499,-4489,-4480,-4472,-4465,-4457,-4450,-4445,-4442,-4441,-4440,-4439,
+-4435,-4427,-4415,-4399,-4381,-4363,-4348,-4334,-4323,-4314,-4307,-4300,-4293,-4286,-4279,-4271,-4263,-4255,-4245,-4234,-4222,
+-4208,-4193,-4178,-4161,-4145,-4128,-4112,-4097,-4084,-4072,-4061,-4051,-4040,-4027,-4013,-3996,-3978,-3961,-3945,-3931,-3918,
+-3906,-3894,-3879,-3863,-3844,-3825,-3806,-3789,-3773,-3759,-3746,-3733,-3719,-3704,-3688,-3671,-3654,-3636,-3618,-3599,-3581,
+-3563,-3547,-3533,-3520,-3507,-3494,-3481,-3467,-3452,-3437,-3423,-3410,-3398,-3386,-3373,-3360,-3347,-3333,-3319,-3307,-3295,
+-3285,-3277,-3270,-3265,-3261,-3258,-3254,-3250,-3245,-3240,-3234,-3228,-3223,-3219,-3214,-3209,-3203,-3195,-3187,-3179,-3171,
+-3164,-3157,-3152,-3146,-3141,-3136,-3131,-3127,-3124,-3121,-3119,-3117,-3115,-3113,-3109,-3103,-3096,-3087,-3077,-3066,-3057,
+-3049,-3044,-3039,-3036,-3033,-3030,-3026,-3023,-3019,-3017,-3016,-3015,-3013,-3009,-3002,-2993,-2983,-2973,-2962,-2953,-2945,
+-2938,-2931,-2925,-2919,-2914,-2908,-2902,-2894,-2884,-2873,-2861,-2848,-2835,-2822,-2809,-2796,-2783,-2769,-2756,-2743,-2731,
+-2721,-2710,-2700,-2690,-2680,-2671,-2665,-2662,-2663,-2667,-2672,-2675,-2675,-2672,-2666,-2658,-2649,-2639,-2627,-2613,-2595,
+-2573,-2550,-2526,-2505,-2488,-2477,-2469,-2464,-2460,-2456,-2450,-2444,-2438,-2432,-2426,-2422,-2418,-2414,-2411,-2406,-2401,
+-2394,-2386,-2376,-2364,-2353,-2343,-2335,-2329,-2323,-2318,-2312,-2305,-2299,-2294,-2293,-2294,-2297,-2300,-2302,-2301,-2300,
+-2298,-2299,-2301,-2306,-2312,-2317,-2319,-2318,-2314,-2307,-2300,-2293,-2287,-2281,-2276,-2272,-2269,-2267,-2265,-2263,-2261,
+-2259,-2256,-2251,-2245,-2238,-2227,-2213,-2195,-2173,-2149,-2125,-2103,-2083,-2066,-2051,-2037,-2025,-2013,-2004,-1997,-1992,
+-1989,-1985,-1978,-1967,-1953,-1936,-1920,-1904,-1890,-1878,-1866,-1853,-1837,-1819,-1799,-1780,-1761,-1743,-1726,-1709,-1693,
+-1677,-1662,-1647,-1634,-1622,-1610,-1600,-1589,-1579,-1567,-1553,-1536,-1515,-1491,-1466,-1441,-1420,-1406,-1397,-1392,-1388,
+-1382,-1371,-1356,-1337,-1317,-1300,-1284,-1271,-1257,-1242,-1224,-1203,-1184,-1166,-1153,-1142,-1134,-1124,-1112,-1094,-1072,
+-1048,-1024,-1001,-980,-962,-945,-928,-911,-894,-875,-856,-837,-817,-796,-776,-756,-737,-720,-705,-690,-674,
+-657,-638,-617,-596,-575,-555,-536,-517,-500,-481,-463,-444,-425,-407,-389,-370,-351,-329,-304,-276,-247,
+-216,-185,-155,-125,-94,-63,-31,3,37,71,103,130,154,176,198,225,258,300,349,402,453,
+499,536,564,587,608,633,663,698,735,772,806,837,868,902,943,992,1048,1107,1165,1217,1262,
+1301,1336,1370,1405,1440,1476,1509,1538,1562,1582,1600,1619,1639,1662,1685,1706,1725,1740,1750,1759,1766,
+1776,1789,1804,1822,1839,1856,1871,1885,1902,1923,1951,1984,2019,2053,2080,2096,2101,2096,2086,2075,2066,
+2059,2054,2049,2042,2034,2026,2020,2018,2020,2026,2034,2040,2045,2049,2054,2062,2074,2090,2109,2126,2140,
+2147,2144,2130,2106,2074,2037,2002,1974,1958,1955,1961,1969,1970,1956,1926,1885,1843,1812,1802,1813,1839,
+1867,1881,1873,1840,1789,1732,1681,1643,1620,1608,1601,1594,1588,1591,1607,1644,1700,1771,1846,1915,1973,
+2016,2049,2075,2100,2126,2150,2171,2183,2186,2178,2163,2142,2118,2093,2070,2051,2036,2029,2031,2042,2062,
+2088,2119,2152,2184,2214,2239,2257,2267,2269,2265,2260,2258,2263,2276,2296,2319,2341,2358,2369,2373,2373,
+2372,2371,2370,2369,2367,2362,2354,2344,2333,2322,2309,2292,2268,2230,2176,2102,2010,1900,1778,1651,1524,
+1402,1290,1191,1110,1054,1030,1045,1103,1202,1333,1481,1627,1753,1848,1909,1942,1955,1962,1969,1982,2001,
+2022,2042,2059,2072,2083,2093,2101,2106,2109,2109,2108,2106,2103,2099,2092,2080,2061,2038,2012,1988,1968,
+1953,1942,1930,1916,1898,1878,1858,1841,1829,1822,1816,1810,1800,1788,1774,1760,1748,1737,1727,1717,1705,
+1693,1681,1670,1661,1654,1649,1645,1642,1637,1631,1622,1611,1599,1584,1571,1560,1553,1551,1553,1555,1556,
+1553,1546,1537,1528,1522,1520,1523,1530,1538,1545,1551,1555,1557,1556,1553,1547,1537,1527,1517,1510,1509,
+1513,1494,1499,1504,1510,1514,1517,1519,1521,1523,1524,1527,1529,1533,1539,1548,1561,1576,1594,1612,1628,
+1642,1654,1664,1674,1685,1698,1712,1729,1747,1766,1787,1808,1831,1854,1878,1901,1924,1947,1969,1992,2016,
+2041,2067,2094,2121,2147,2172,2196,2220,2244,2267,2288,2306,2321,2331,2338,2342,2346,2352,2360,2372,2387,
+2404,2421,2436,2451,2463,2474,2485,2494,2503,2511,2518,2523,2526,2529,2530,2531,2532,2533,2534,2536,2539,
+2544,2552,2562,2573,2584,2592,2596,2594,2589,2582,2579,2583,2596,2618,2645,2673,2698,2715,2725,2729,2732,
+2737,2747,2762,2779,2796,2811,2822,2831,2838,2846,2854,2862,2869,2872,2872,2869,2866,2866,2868,2874,2882,
+2892,2901,2912,2924,2938,2955,2974,2993,3012,3029,3045,3062,3078,3095,3112,3127,3139,3148,3156,3165,3175,
+3186,3198,3209,3218,3226,3234,3244,3257,3274,3292,3309,3322,3331,3336,3340,3345,3354,3366,3378,3389,3396,
+3399,3400,3401,3404,3408,3413,3415,3414,3410,3404,3400,3399,3401,3405,3408,3408,3403,3393,3380,3366,3353,
+3342,3332,3324,3315,3306,3297,3289,3283,3278,3272,3267,3260,3253,3247,3241,3237,3235,3234,3233,3234,3235,
+3237,3240,3244,3247,3248,3247,3243,3238,3232,3227,3223,3220,3218,3215,3211,3209,3207,3208,3211,3215,3219,
+3222,3225,3227,3229,3232,3237,3242,3244,3244,3240,3232,3221,3209,3197,3185,3174,3162,3149,3136,3123,3110,
+3098,3087,3076,3068,3060,3055,3053,3054,3057,3061,3066,3070,3074,3077,3080,3083,3085,3084,3081,3073,3060,
+3044,3026,3008,2990,2974,2958,2943,2927,2911,2893,2874,2852,2829,2803,2776,2751,2727,2709,2696,2688,2685,
+2684,2683,2683,2681,2681,2682,2685,2691,2697,2702,2704,2701,2693,2679,2662,2642,2622,2604,2588,2574,2561,
+2549,2536,2521,2506,2492,2482,2477,2477,2481,2483,2479,2464,2436,2397,2351,2305,2264,2231,2206,2183,2157,
+2119,2066,1995,1909,1815,1719,1629,1548,1480,1423,1377,1336,1299,1263,1228,1192,1157,1122,1087,1053,1020,
+987,955,924,894,866,840,815,791,765,737,706,670,631,589,547,507,470,438,412,389,368,
+347,323,295,262,226,187,148,112,78,47,18,-9,-38,-68,-100,-133,-166,-199,-232,-265,-297,
+-328,-358,-386,-411,-434,-455,-476,-499,-525,-553,-584,-615,-645,-670,-690,-705,-716,-726,-736,-748,-764,
+-782,-804,-827,-851,-877,-903,-932,-961,-991,-1022,-1051,-1080,-1108,-1136,-1165,-1195,-1227,-1260,-1295,-1328,-1360,
+-1390,-1417,-1443,-1468,-1495,-1523,-1553,-1584,-1616,-1648,-1679,-1708,-1737,-1767,-1798,-1831,-1865,-1899,-1933,-1964,-1993,
+-2020,-2048,-2075,-2105,-2134,-2164,-2191,-2216,-2238,-2259,-2279,-2301,-2325,-2350,-2376,-2403,-2428,-2452,-2476,-2499,-2523,
+-2547,-2570,-2592,-2611,-2628,-2644,-2659,-2674,-2689,-2706,-2723,-2741,-2758,-2776,-2794,-2813,-2832,-2850,-2868,-2884,-2897,
+-2909,-2921,-2933,-2947,-2963,-2981,-3000,-3019,-3038,-3057,-3076,-3094,-3112,-3129,-3144,-3157,-3169,-3180,-3192,-3204,-3219,
+-3234,-3249,-3261,-3272,-3280,-3287,-3293,-3301,-3309,-3319,-3328,-3335,-3339,-3342,-3342,-3341,-3341,-3341,-3342,-3343,-3345,
+-3345,-3346,-3347,-3348,-3348,-3347,-3346,-3342,-3339,-3336,-3334,-3335,-3338,-3341,-3345,-3346,-3345,-3341,-3335,-3327,-3318,
+-3308,-3297,-3284,-3272,-3260,-3249,-3241,-3233,-3225,-3215,-3204,-3191,-3179,-3170,-3166,-3166,-3167,-3166,-3162,-3152,-3138,
+-3123,-3111,-3104,-3103,-3107,-3111,-3114,-3112,-3107,-3097,-3084,-3070,-3054,-3036,-3017,-2998,-2981,-2967,-2958,-2954,-2954,
+-2957,-2963,-2971,-2983,-3002,-3027,-3058,-3090,-3119,-3139,-3146,-3141,-3128,-3112,-3101,-3099,-3108,-3125,-3145,-3164,-3176,
+-3181,-3179,-3176,-3176,-3184,-3204,-3238,-3282,-3335,-3390,-3442,-3489,-3527,-3557,-3581,-3603,-3625,-3650,-3680,-3714,-3748,
+-3782,-3811,-3835,-3855,-3871,-3886,-3903,-3923,-3948,-3978,-4011,-4045,-4080,-4112,-4141,-4167,-4191,-4212,-4232,-4252,-4272,
+-4291,-4310,-4328,-4347,-4367,-4388,-4412,-4437,-4462,-4485,-4504,-4520,-4532,-4544,-4558,-4574,-4592,-4612,-4630,-4645,-4655,
+-4661,-4664,-4666,-4670,-4677,-4684,-4693,-4700,-4706,-4710,-4713,-4717,-4720,-4724,-4727,-4731,-4733,-4734,-4733,-4730,-4725,
+-4718,-4708,-4696,-4685,-4676,-4670,-4666,-4664,-4663,-4659,-4654,-4647,-4639,-4632,-4627,-4623,-4619,-4614,-4604,-4590,-4573,
+-4555,-4538,-4524,-4512,-4503,-4496,-4488,-4482,-4476,-4472,-4470,-4469,-4468,-4466,-4460,-4450,-4436,-4420,-4403,-4385,-4368,
+-4353,-4338,-4325,-4314,-4306,-4300,-4296,-4294,-4291,-4288,-4281,-4272,-4261,-4248,-4235,-4222,-4209,-4196,-4183,-4168,-4153,
+-4137,-4122,-4107,-4093,-4078,-4063,-4046,-4027,-4008,-3990,-3974,-3961,-3952,-3943,-3935,-3926,-3913,-3898,-3881,-3863,-3844,
+-3826,-3809,-3793,-3777,-3762,-3747,-3732,-3717,-3702,-3686,-3668,-3649,-3630,-3611,-3594,-3578,-3564,-3552,-3540,-3528,-3516,
+-3504,-3492,-3479,-3467,-3455,-3443,-3430,-3418,-3405,-3392,-3379,-3368,-3357,-3347,-3339,-3331,-3325,-3320,-3315,-3311,-3307,
+-3303,-3299,-3294,-3290,-3286,-3281,-3276,-3270,-3264,-3256,-3248,-3240,-3234,-3228,-3222,-3216,-3209,-3201,-3193,-3186,-3179,
+-3175,-3172,-3170,-3170,-3169,-3168,-3166,-3162,-3156,-3148,-3140,-3131,-3122,-3115,-3109,-3104,-3100,-3095,-3090,-3085,-3079,
+-3074,-3070,-3069,-3068,-3068,-3068,-3066,-3061,-3055,-3047,-3038,-3030,-3021,-3014,-3006,-2999,-2991,-2984,-2977,-2969,-2962,
+-2954,-2944,-2933,-2921,-2906,-2891,-2874,-2858,-2842,-2827,-2815,-2804,-2793,-2783,-2771,-2757,-2742,-2726,-2711,-2699,-2691,
+-2687,-2685,-2686,-2686,-2686,-2687,-2689,-2693,-2698,-2704,-2707,-2706,-2699,-2684,-2663,-2639,-2614,-2590,-2569,-2551,-2536,
+-2522,-2510,-2500,-2491,-2484,-2479,-2475,-2472,-2469,-2466,-2462,-2459,-2454,-2449,-2442,-2434,-2424,-2413,-2403,-2393,-2385,
+-2378,-2372,-2365,-2358,-2352,-2348,-2347,-2348,-2352,-2355,-2357,-2356,-2352,-2348,-2344,-2342,-2342,-2343,-2345,-2345,-2343,
+-2339,-2333,-2327,-2322,-2316,-2312,-2307,-2302,-2297,-2292,-2287,-2282,-2279,-2276,-2273,-2271,-2267,-2261,-2252,-2238,-2222,
+-2203,-2184,-2166,-2151,-2139,-2129,-2119,-2109,-2097,-2083,-2069,-2056,-2044,-2034,-2024,-2013,-2000,-1985,-1968,-1952,-1938,
+-1926,-1916,-1906,-1896,-1884,-1869,-1852,-1833,-1814,-1795,-1776,-1757,-1739,-1721,-1702,-1684,-1665,-1647,-1630,-1614,-1600,
+-1589,-1580,-1571,-1560,-1547,-1531,-1512,-1492,-1473,-1457,-1444,-1434,-1424,-1412,-1397,-1379,-1359,-1339,-1321,-1304,-1289,
+-1274,-1257,-1240,-1223,-1208,-1198,-1192,-1190,-1190,-1188,-1181,-1167,-1147,-1122,-1094,-1066,-1039,-1013,-989,-966,-944,
+-923,-902,-882,-862,-842,-822,-802,-782,-765,-749,-735,-721,-707,-691,-672,-651,-628,-604,-582,-562,-543,
+-525,-508,-491,-474,-456,-437,-417,-395,-371,-345,-316,-287,-256,-226,-196,-166,-136,-105,-73,-40,-6,
+27,60,91,120,147,172,199,230,266,309,356,406,453,496,531,559,583,608,635,667,703,
+741,778,810,839,865,894,928,969,1019,1072,1127,1180,1229,1275,1318,1361,1405,1448,1490,1527,1557,
+1580,1597,1611,1625,1641,1661,1683,1706,1728,1746,1760,1770,1777,1785,1795,1808,1824,1842,1862,1881,1898,
+1916,1932,1949,1967,1985,2002,2016,2028,2038,2044,2048,2050,2050,2046,2039,2027,2013,1998,1986,1979,1978,
+1983,1992,2005,2019,2036,2057,2082,2111,2141,2168,2187,2195,2190,2172,2142,2105,2064,2024,1989,1965,1954,
+1957,1973,1996,2016,2024,2013,1984,1945,1907,1887,1893,1927,1982,2040,2084,2100,2081,2033,1967,1899,1841,
+1797,1767,1748,1734,1725,1723,1732,1757,1797,1845,1895,1938,1969,1988,2000,2012,2030,2057,2090,2123,2148,
+2159,2156,2140,2115,2090,2068,2055,2050,2054,2065,2080,2099,2119,2142,2167,2193,2220,2244,2262,2272,2271,
+2262,2248,2235,2229,2234,2251,2278,2310,2339,2361,2374,2377,2374,2370,2366,2364,2363,2362,2357,2348,2335,
+2319,2304,2289,2272,2249,2215,2161,2083,1978,1850,1705,1555,1411,1284,1185,1118,1087,1092,1130,1200,1295,
+1409,1532,1652,1760,1846,1905,1939,1954,1957,1957,1958,1965,1977,1990,2003,2013,2021,2027,2032,2036,2041,
+2044,2048,2050,2051,2050,2044,2032,2015,1993,1967,1943,1922,1906,1895,1886,1875,1861,1842,1821,1800,1782,
+1768,1758,1750,1744,1737,1728,1720,1711,1703,1696,1688,1678,1666,1652,1637,1624,1612,1602,1596,1592,1590,
+1589,1586,1581,1572,1559,1543,1527,1513,1505,1502,1506,1511,1516,1517,1512,1503,1492,1482,1476,1475,1479,
+1486,1493,1501,1507,1511,1513,1513,1511,1507,1502,1497,1493,1492,1494,1484,1487,1490,1492,1493,1494,1495,
+1497,1500,1504,1509,1515,1522,1530,1541,1554,1569,1586,1604,1621,1636,1651,1664,1678,1692,1708,1725,1743,
+1763,1784,1806,1830,1855,1880,1904,1928,1950,1972,1995,2018,2043,2070,2097,2124,2149,2173,2195,2217,2240,
+2264,2287,2309,2328,2342,2351,2356,2359,2361,2365,2372,2383,2396,2410,2424,2437,2447,2457,2465,2472,2480,
+2489,2497,2504,2511,2517,2521,2525,2527,2528,2528,2530,2532,2536,2541,2548,2555,2561,2564,2564,2559,2552,
+2546,2545,2551,2566,2590,2619,2649,2674,2690,2697,2697,2693,2692,2696,2708,2726,2748,2769,2787,2800,2810,
+2818,2826,2834,2841,2846,2848,2847,2844,2841,2840,2843,2849,2858,2869,2880,2891,2903,2917,2931,2947,2963,
+2979,2995,3010,3025,3041,3057,3072,3087,3099,3110,3121,3131,3141,3153,3165,3176,3187,3198,3209,3222,3238,
+3255,3272,3286,3297,3303,3308,3312,3319,3327,3338,3347,3355,3359,3361,3361,3363,3366,3371,3375,3378,3377,
+3375,3371,3368,3368,3369,3370,3369,3363,3353,3340,3327,3315,3306,3300,3296,3291,3285,3278,3269,3261,3252,
+3245,3237,3229,3221,3213,3206,3202,3200,3200,3200,3200,3200,3199,3199,3201,3204,3207,3209,3210,3208,3204,
+3199,3195,3193,3191,3191,3191,3190,3189,3188,3189,3190,3193,3196,3198,3200,3202,3204,3209,3215,3221,3226,
+3228,3224,3216,3205,3191,3178,3166,3155,3145,3136,3125,3113,3099,3086,3072,3060,3049,3041,3036,3034,3035,
+3040,3046,3052,3058,3062,3064,3063,3060,3056,3050,3043,3034,3022,3008,2992,2974,2958,2942,2927,2914,2901,
+2887,2870,2851,2827,2802,2775,2750,2728,2711,2698,2690,2685,2680,2674,2666,2657,2648,2640,2637,2637,2641,
+2646,2650,2649,2643,2630,2611,2589,2566,2545,2528,2517,2509,2504,2500,2493,2484,2472,2460,2449,2441,2437,
+2436,2434,2428,2415,2394,2363,2327,2289,2251,2216,2182,2148,2109,2062,2003,1934,1856,1772,1689,1610,1538,
+1477,1425,1381,1343,1306,1270,1233,1196,1157,1120,1084,1049,1016,983,950,915,881,847,814,783,753,
+725,695,664,629,591,549,506,464,425,390,362,338,319,301,282,259,230,197,159,120,82,
+48,17,-10,-37,-63,-93,-125,-160,-198,-236,-274,-310,-344,-375,-404,-429,-452,-471,-490,-508,-529,
+-553,-581,-610,-641,-668,-691,-708,-720,-729,-736,-746,-759,-776,-797,-820,-844,-870,-897,-924,-953,-984,
+-1017,-1049,-1082,-1113,-1142,-1170,-1198,-1227,-1257,-1290,-1323,-1357,-1390,-1421,-1450,-1477,-1502,-1527,-1554,-1582,-1613,
+-1645,-1677,-1710,-1741,-1772,-1802,-1833,-1865,-1898,-1932,-1965,-1997,-2028,-2057,-2085,-2114,-2142,-2171,-2199,-2226,-2250,
+-2272,-2293,-2313,-2335,-2358,-2383,-2409,-2435,-2460,-2484,-2508,-2532,-2558,-2583,-2609,-2633,-2655,-2673,-2690,-2705,-2720,
+-2736,-2753,-2771,-2788,-2806,-2822,-2839,-2855,-2872,-2889,-2906,-2922,-2937,-2951,-2964,-2977,-2991,-3006,-3022,-3039,-3056,
+-3073,-3091,-3108,-3127,-3146,-3164,-3181,-3197,-3210,-3222,-3234,-3246,-3260,-3275,-3290,-3304,-3315,-3324,-3331,-3338,-3344,
+-3352,-3361,-3370,-3378,-3384,-3387,-3389,-3389,-3390,-3390,-3392,-3394,-3395,-3396,-3397,-3396,-3395,-3394,-3392,-3389,-3386,
+-3384,-3382,-3381,-3382,-3384,-3387,-3390,-3392,-3392,-3390,-3387,-3381,-3374,-3365,-3354,-3342,-3331,-3321,-3313,-3307,-3302,
+-3296,-3287,-3275,-3262,-3250,-3241,-3238,-3238,-3241,-3242,-3237,-3226,-3210,-3191,-3175,-3165,-3162,-3166,-3173,-3179,-3182,
+-3180,-3172,-3160,-3145,-3128,-3109,-3088,-3066,-3045,-3027,-3013,-3005,-3002,-3004,-3009,-3017,-3028,-3043,-3063,-3089,-3119,
+-3149,-3173,-3189,-3194,-3188,-3176,-3163,-3154,-3154,-3163,-3180,-3200,-3219,-3233,-3241,-3243,-3244,-3248,-3258,-3279,-3310,
+-3351,-3397,-3444,-3488,-3526,-3557,-3582,-3604,-3626,-3652,-3682,-3717,-3753,-3790,-3823,-3851,-3874,-3891,-3905,-3917,-3930,
+-3945,-3965,-3990,-4022,-4059,-4100,-4145,-4191,-4236,-4276,-4309,-4336,-4354,-4366,-4373,-4379,-4386,-4398,-4415,-4437,-4463,
+-4491,-4518,-4541,-4559,-4574,-4585,-4596,-4608,-4622,-4637,-4651,-4665,-4676,-4686,-4694,-4700,-4707,-4713,-4719,-4723,-4726,
+-4728,-4728,-4729,-4730,-4733,-4738,-4746,-4755,-4764,-4774,-4781,-4784,-4782,-4775,-4762,-4745,-4728,-4714,-4703,-4696,-4693,
+-4691,-4687,-4682,-4676,-4670,-4666,-4665,-4665,-4665,-4662,-4654,-4640,-4621,-4600,-4578,-4560,-4545,-4535,-4526,-4520,-4513,
+-4508,-4502,-4498,-4496,-4493,-4491,-4486,-4480,-4472,-4461,-4449,-4434,-4418,-4399,-4380,-4360,-4342,-4327,-4317,-4311,-4308,
+-4307,-4305,-4300,-4294,-4285,-4276,-4268,-4261,-4254,-4246,-4237,-4224,-4208,-4190,-4172,-4154,-4136,-4119,-4102,-4085,-4066,
+-4047,-4028,-4012,-3997,-3986,-3977,-3968,-3959,-3948,-3936,-3922,-3906,-3889,-3872,-3853,-3835,-3817,-3800,-3785,-3772,-3759,
+-3746,-3733,-3718,-3701,-3683,-3665,-3647,-3630,-3616,-3603,-3591,-3580,-3569,-3558,-3548,-3536,-3525,-3513,-3500,-3486,-3473,
+-3460,-3448,-3438,-3429,-3421,-3413,-3406,-3399,-3392,-3385,-3378,-3371,-3365,-3358,-3353,-3348,-3344,-3340,-3336,-3332,-3326,
+-3320,-3313,-3306,-3300,-3295,-3290,-3286,-3280,-3273,-3264,-3255,-3246,-3239,-3233,-3230,-3228,-3226,-3225,-3223,-3220,-3216,
+-3212,-3207,-3202,-3196,-3190,-3183,-3177,-3172,-3166,-3160,-3154,-3147,-3140,-3134,-3129,-3126,-3124,-3124,-3124,-3124,-3123,
+-3119,-3114,-3108,-3100,-3093,-3085,-3077,-3069,-3062,-3054,-3046,-3037,-3028,-3018,-3006,-2993,-2977,-2959,-2941,-2923,-2906,
+-2893,-2882,-2874,-2868,-2861,-2853,-2841,-2824,-2805,-2785,-2765,-2749,-2735,-2725,-2717,-2710,-2704,-2699,-2698,-2700,-2708,
+-2720,-2734,-2748,-2759,-2764,-2762,-2755,-2742,-2726,-2708,-2688,-2666,-2643,-2619,-2595,-2575,-2558,-2545,-2535,-2528,-2522,
+-2516,-2511,-2506,-2503,-2500,-2497,-2493,-2488,-2480,-2471,-2460,-2449,-2439,-2431,-2423,-2416,-2409,-2404,-2400,-2398,-2399,
+-2401,-2403,-2405,-2403,-2400,-2395,-2390,-2385,-2382,-2379,-2377,-2375,-2372,-2368,-2363,-2359,-2354,-2350,-2346,-2342,-2337,
+-2331,-2326,-2321,-2317,-2313,-2310,-2306,-2300,-2292,-2281,-2267,-2249,-2229,-2208,-2189,-2173,-2162,-2154,-2149,-2146,-2142,
+-2137,-2130,-2122,-2113,-2103,-2092,-2080,-2065,-2047,-2026,-2005,-1985,-1967,-1953,-1942,-1933,-1924,-1913,-1900,-1884,-1866,
+-1848,-1829,-1811,-1794,-1778,-1762,-1746,-1728,-1709,-1689,-1668,-1648,-1630,-1614,-1602,-1593,-1584,-1575,-1564,-1551,-1537,
+-1522,-1508,-1495,-1481,-1467,-1451,-1432,-1411,-1390,-1369,-1350,-1333,-1317,-1301,-1285,-1268,-1252,-1239,-1230,-1226,-1224,
+-1224,-1221,-1214,-1200,-1180,-1155,-1127,-1097,-1067,-1039,-1012,-987,-964,-944,-925,-907,-889,-871,-851,-831,-812,
+-794,-778,-764,-751,-737,-720,-701,-679,-656,-633,-610,-589,-570,-552,-535,-517,-498,-478,-457,-434,-410,
+-384,-357,-328,-299,-271,-242,-213,-184,-154,-122,-89,-55,-21,11,44,75,105,135,165,197,232,
+269,310,352,395,437,475,509,540,570,601,634,672,713,755,794,828,857,882,906,933,965,
+1003,1047,1094,1144,1193,1241,1289,1336,1384,1430,1475,1516,1552,1582,1607,1628,1647,1665,1683,1701,1718,
+1733,1746,1756,1765,1773,1781,1791,1804,1820,1839,1859,1879,1897,1911,1921,1926,1926,1922,1918,1913,1911,
+1910,1912,1914,1915,1913,1906,1897,1888,1882,1884,1895,1915,1941,1972,2002,2031,2059,2089,2122,2160,2200,
+2237,2266,2279,2273,2249,2210,2163,2114,2068,2031,2006,1994,1997,2012,2039,2070,2097,2112,2110,2090,2059,
+2032,2021,2037,2085,2157,2239,2312,2361,2377,2361,2324,2277,2232,2197,2172,2154,2138,2122,2105,2090,2079,
+2071,2062,2048,2022,1985,1941,1899,1870,1863,1880,1917,1965,2010,2042,2056,2053,2041,2029,2025,2035,2059,
+2092,2126,2155,2176,2186,2190,2192,2198,2208,2223,2238,2250,2254,2249,2238,2225,2218,2221,2237,2262,2293,
+2322,2345,2358,2361,2358,2353,2349,2348,2349,2349,2346,2337,2321,2302,2281,2260,2240,2217,2186,2139,2070,
+1976,1856,1718,1573,1436,1321,1241,1201,1202,1240,1307,1393,1488,1583,1671,1746,1806,1848,1875,1889,1894,
+1896,1897,1900,1905,1913,1921,1928,1933,1936,1938,1939,1940,1941,1944,1947,1951,1954,1953,1947,1936,1918,
+1895,1871,1848,1829,1814,1804,1795,1786,1774,1759,1743,1727,1712,1700,1690,1682,1674,1667,1659,1653,1647,
+1643,1640,1636,1630,1622,1612,1599,1587,1574,1564,1555,1549,1545,1542,1540,1535,1527,1516,1502,1487,1474,
+1465,1461,1463,1468,1472,1474,1471,1465,1458,1451,1446,1446,1448,1452,1457,1461,1463,1464,1466,1467,1469,
+1471,1473,1476,1478,1481,1484,1465,1469,1473,1475,1477,1479,1481,1484,1488,1494,1500,1507,1515,1523,1533,
+1544,1557,1572,1589,1607,1625,1643,1662,1681,1701,1720,1741,1761,1782,1804,1827,1851,1875,1899,1922,1944,
+1966,1988,2012,2037,2065,2093,2121,2148,2173,2196,2218,2240,2263,2286,2309,2330,2347,2360,2368,2372,2374,
+2376,2380,2387,2395,2405,2415,2425,2433,2439,2445,2451,2457,2464,2472,2480,2488,2495,2502,2508,2512,2516,
+2519,2522,2526,2530,2535,2539,2543,2544,2542,2537,2530,2522,2517,2517,2524,2540,2564,2592,2619,2642,2657,
+2662,2660,2654,2649,2649,2657,2673,2695,2719,2742,2761,2776,2787,2796,2803,2810,2815,2819,2819,2817,2814,
+2811,2811,2814,2821,2830,2841,2852,2863,2874,2886,2898,2911,2924,2937,2950,2964,2977,2992,3007,3024,3040,
+3056,3072,3086,3099,3112,3123,3134,3144,3154,3166,3179,3195,3212,3230,3246,3258,3267,3273,3279,3285,3293,
+3303,3313,3322,3329,3333,3334,3335,3336,3337,3339,3341,3341,3340,3337,3336,3335,3336,3336,3333,3326,3315,
+3300,3285,3272,3265,3261,3262,3264,3263,3260,3253,3243,3233,3223,3214,3206,3198,3190,3183,3178,3174,3173,
+3172,3172,3170,3167,3164,3162,3161,3163,3167,3171,3173,3174,3173,3171,3168,3167,3167,3167,3167,3167,3166,
+3165,3165,3166,3169,3172,3174,3177,3180,3185,3190,3198,3206,3212,3214,3212,3204,3192,3179,3165,3153,3143,
+3134,3125,3114,3102,3088,3074,3061,3049,3040,3033,3028,3025,3025,3027,3030,3035,3038,3040,3038,3034,3027,
+3019,3010,3001,2991,2980,2966,2950,2933,2915,2899,2885,2874,2866,2857,2846,2831,2811,2787,2762,2738,2718,
+2703,2694,2688,2684,2678,2669,2656,2641,2626,2613,2604,2600,2599,2601,2602,2599,2592,2579,2560,2538,2515,
+2493,2476,2463,2455,2450,2447,2442,2436,2426,2414,2402,2390,2380,2372,2365,2358,2348,2334,2316,2292,2264,
+2231,2195,2155,2110,2060,2005,1946,1882,1814,1745,1676,1609,1546,1488,1436,1388,1345,1303,1262,1221,1179,
+1139,1100,1063,1029,997,966,933,898,862,824,785,747,712,677,644,610,573,535,493,450,407,
+367,331,302,278,259,244,228,210,188,160,127,93,58,26,-1,-27,-52,-78,-107,-140,-178,
+-219,-262,-305,-346,-384,-418,-449,-475,-497,-515,-531,-548,-566,-588,-614,-643,-671,-698,-720,-736,-747,
+-755,-762,-772,-785,-803,-825,-849,-875,-902,-930,-959,-991,-1024,-1058,-1093,-1127,-1159,-1188,-1216,-1241,-1267,
+-1293,-1321,-1350,-1382,-1414,-1446,-1477,-1507,-1535,-1562,-1590,-1619,-1650,-1682,-1716,-1750,-1784,-1816,-1847,-1877,-1908,
+-1940,-1973,-2006,-2038,-2070,-2099,-2127,-2154,-2181,-2207,-2233,-2258,-2283,-2306,-2329,-2352,-2376,-2401,-2426,-2451,-2476,
+-2500,-2523,-2547,-2572,-2599,-2627,-2655,-2681,-2705,-2725,-2743,-2759,-2775,-2792,-2810,-2829,-2848,-2866,-2883,-2898,-2913,
+-2927,-2941,-2956,-2970,-2985,-2998,-3012,-3026,-3041,-3056,-3073,-3090,-3106,-3123,-3139,-3155,-3172,-3190,-3208,-3226,-3242,
+-3257,-3271,-3283,-3296,-3309,-3323,-3337,-3350,-3362,-3372,-3380,-3388,-3396,-3405,-3414,-3424,-3432,-3437,-3440,-3441,-3441,
+-3441,-3442,-3445,-3448,-3452,-3454,-3455,-3454,-3451,-3448,-3444,-3441,-3438,-3436,-3435,-3435,-3436,-3438,-3440,-3442,-3445,
+-3446,-3445,-3443,-3438,-3432,-3422,-3412,-3402,-3392,-3385,-3381,-3378,-3376,-3371,-3363,-3352,-3338,-3325,-3315,-3311,-3311,
+-3314,-3315,-3311,-3301,-3285,-3265,-3247,-3234,-3228,-3230,-3237,-3244,-3249,-3250,-3245,-3236,-3222,-3206,-3187,-3166,-3144,
+-3121,-3100,-3083,-3072,-3066,-3065,-3068,-3074,-3083,-3095,-3111,-3131,-3155,-3181,-3206,-3226,-3238,-3241,-3237,-3228,-3220,
+-3215,-3215,-3223,-3236,-3251,-3267,-3281,-3292,-3301,-3310,-3322,-3339,-3361,-3390,-3423,-3458,-3492,-3522,-3547,-3570,-3590,
+-3612,-3636,-3664,-3697,-3732,-3768,-3803,-3834,-3861,-3884,-3901,-3915,-3926,-3937,-3950,-3968,-3994,-4029,-4074,-4128,-4187,
+-4248,-4305,-4354,-4392,-4417,-4431,-4436,-4436,-4436,-4438,-4447,-4462,-4483,-4508,-4535,-4562,-4585,-4604,-4620,-4632,-4642,
+-4651,-4661,-4672,-4685,-4699,-4713,-4727,-4738,-4748,-4754,-4757,-4758,-4756,-4754,-4752,-4751,-4751,-4753,-4757,-4764,-4773,
+-4784,-4796,-4807,-4815,-4818,-4813,-4802,-4786,-4769,-4752,-4739,-4730,-4724,-4721,-4716,-4711,-4704,-4698,-4694,-4693,-4694,
+-4695,-4693,-4687,-4675,-4658,-4639,-4619,-4601,-4587,-4576,-4567,-4560,-4554,-4547,-4540,-4533,-4527,-4521,-4516,-4511,-4507,
+-4502,-4496,-4489,-4480,-4467,-4451,-4431,-4409,-4387,-4366,-4350,-4338,-4329,-4322,-4316,-4309,-4301,-4294,-4288,-4283,-4280,
+-4277,-4273,-4266,-4256,-4242,-4226,-4209,-4193,-4177,-4163,-4148,-4132,-4114,-4096,-4077,-4059,-4042,-4027,-4012,-3999,-3987,
+-3975,-3963,-3951,-3938,-3924,-3909,-3892,-3874,-3857,-3840,-3825,-3813,-3802,-3792,-3781,-3768,-3753,-3736,-3719,-3701,-3685,
+-3670,-3657,-3644,-3633,-3622,-3612,-3602,-3591,-3579,-3567,-3553,-3539,-3525,-3511,-3500,-3490,-3483,-3477,-3472,-3467,-3462,
+-3456,-3449,-3441,-3432,-3423,-3414,-3405,-3398,-3392,-3388,-3384,-3380,-3376,-3371,-3366,-3361,-3356,-3353,-3350,-3346,-3341,
+-3335,-3328,-3319,-3312,-3306,-3301,-3298,-3296,-3293,-3289,-3285,-3280,-3275,-3270,-3266,-3262,-3258,-3253,-3247,-3240,-3233,
+-3226,-3219,-3213,-3207,-3201,-3195,-3189,-3184,-3180,-3178,-3177,-3177,-3176,-3174,-3171,-3165,-3158,-3150,-3141,-3133,-3126,
+-3120,-3113,-3106,-3098,-3089,-3077,-3062,-3046,-3027,-3008,-2990,-2973,-2959,-2948,-2941,-2936,-2932,-2926,-2917,-2904,-2887,
+-2867,-2847,-2828,-2812,-2799,-2787,-2776,-2765,-2754,-2744,-2737,-2734,-2737,-2744,-2756,-2769,-2781,-2792,-2801,-2807,-2811,
+-2812,-2808,-2799,-2783,-2761,-2734,-2705,-2676,-2651,-2630,-2613,-2598,-2585,-2573,-2562,-2553,-2546,-2542,-2540,-2539,-2536,
+-2531,-2523,-2513,-2502,-2492,-2482,-2474,-2467,-2461,-2456,-2451,-2448,-2446,-2446,-2445,-2445,-2443,-2440,-2436,-2431,-2426,
+-2421,-2417,-2413,-2409,-2406,-2402,-2398,-2394,-2391,-2387,-2383,-2379,-2375,-2371,-2366,-2362,-2358,-2353,-2347,-2339,-2329,
+-2316,-2299,-2280,-2259,-2237,-2216,-2197,-2180,-2168,-2159,-2152,-2148,-2146,-2144,-2142,-2141,-2139,-2135,-2128,-2118,-2103,
+-2084,-2061,-2038,-2016,-1996,-1981,-1968,-1957,-1946,-1934,-1919,-1902,-1884,-1865,-1848,-1833,-1820,-1808,-1797,-1786,-1773,
+-1758,-1740,-1721,-1700,-1680,-1662,-1645,-1631,-1618,-1606,-1594,-1581,-1568,-1555,-1542,-1528,-1514,-1498,-1481,-1461,-1441,
+-1421,-1403,-1386,-1372,-1358,-1344,-1328,-1312,-1295,-1279,-1266,-1255,-1246,-1237,-1227,-1214,-1198,-1179,-1156,-1132,-1107,
+-1082,-1057,-1033,-1011,-991,-972,-956,-939,-922,-904,-885,-865,-844,-826,-808,-793,-777,-761,-743,-723,-701,
+-678,-655,-634,-613,-593,-574,-554,-534,-512,-490,-468,-445,-421,-396,-371,-344,-318,-291,-264,-236,-206,
+-175,-141,-107,-72,-39,-6,24,53,83,113,145,178,213,250,288,327,366,405,444,481,518,
+554,591,630,671,713,755,795,832,864,891,916,940,967,997,1033,1072,1115,1160,1204,1249,1292,
+1335,1378,1421,1464,1507,1550,1591,1628,1659,1685,1704,1717,1725,1731,1737,1744,1753,1765,1779,1794,1810,
+1826,1841,1855,1867,1875,1878,1874,1862,1843,1820,1794,1770,1750,1735,1723,1714,1705,1695,1687,1684,1692,
+1716,1757,1816,1887,1962,2034,2094,2142,2179,2208,2235,2264,2294,2320,2337,2340,2325,2295,2253,2208,2165,
+2128,2100,2081,2071,2069,2076,2090,2109,2128,2141,2143,2133,2115,2098,2094,2113,2161,2233,2320,2406,2477,
+2525,2547,2550,2542,2532,2525,2521,2517,2509,2492,2468,2437,2400,2358,2308,2244,2165,2072,1972,1880,1807,
+1767,1764,1794,1845,1901,1947,1977,1988,1989,1990,2001,2029,2072,2121,2167,2198,2210,2202,2181,2158,2141,
+2138,2149,2171,2196,2218,2230,2234,2230,2226,2225,2232,2247,2267,2287,2303,2312,2314,2311,2306,2302,2300,
+2301,2303,2301,2295,2282,2264,2242,2218,2194,2170,2141,2104,2053,1983,1895,1793,1685,1582,1497,1439,1414,
+1422,1456,1509,1568,1625,1672,1708,1731,1745,1753,1759,1766,1774,1785,1797,1809,1820,1830,1838,1844,1848,
+1851,1853,1854,1854,1853,1852,1851,1850,1847,1843,1835,1823,1807,1786,1765,1744,1726,1712,1701,1692,1684,
+1677,1669,1662,1655,1650,1645,1640,1634,1626,1616,1606,1597,1590,1584,1581,1577,1574,1569,1563,1555,1547,
+1537,1528,1520,1513,1507,1503,1500,1496,1490,1483,1472,1461,1449,1439,1432,1428,1427,1427,1428,1427,1426,
+1425,1425,1426,1429,1432,1434,1435,1434,1432,1430,1429,1430,1433,1437,1442,1448,1454,1460,1465,1432,1438,
+1444,1449,1454,1458,1463,1468,1473,1480,1488,1496,1504,1513,1522,1532,1544,1559,1576,1596,1617,1640,1664,
+1688,1711,1734,1756,1777,1799,1820,1843,1865,1888,1910,1932,1953,1975,1998,2022,2048,2077,2105,2134,2161,
+2187,2212,2236,2260,2285,2309,2331,2350,2364,2374,2379,2382,2384,2387,2391,2396,2402,2407,2411,2414,2418,
+2422,2427,2433,2441,2448,2456,2463,2469,2475,2480,2485,2491,2497,2503,2510,2517,2523,2527,2530,2528,2523,
+2515,2506,2497,2492,2493,2501,2517,2539,2564,2587,2605,2616,2619,2616,2609,2603,2602,2607,2620,2639,2661,
+2685,2706,2725,2739,2751,2760,2767,2772,2776,2777,2777,2776,2776,2777,2781,2788,2796,2806,2815,2823,2831,
+2838,2846,2855,2865,2876,2887,2898,2910,2922,2936,2951,2968,2987,3007,3027,3045,3062,3076,3088,3098,3107,
+3117,3129,3144,3162,3181,3200,3216,3228,3236,3242,3248,3255,3264,3275,3286,3296,3304,3310,3313,3315,3315,
+3316,3315,3313,3309,3306,3302,3301,3301,3302,3301,3297,3287,3272,3256,3240,3228,3222,3221,3224,3228,3229,
+3226,3219,3210,3201,3192,3185,3179,3174,3168,3162,3157,3153,3150,3147,3145,3141,3137,3133,3130,3130,3132,
+3136,3141,3145,3148,3149,3148,3147,3147,3147,3147,3146,3144,3142,3141,3141,3143,3146,3150,3155,3159,3164,
+3169,3175,3182,3189,3195,3197,3194,3186,3175,3162,3149,3139,3129,3121,3112,3101,3089,3075,3063,3052,3043,
+3036,3031,3025,3020,3015,3010,3007,3005,3003,3002,2998,2993,2985,2976,2966,2957,2947,2935,2922,2906,2888,
+2870,2854,2842,2836,2832,2830,2826,2816,2800,2779,2753,2728,2705,2688,2675,2667,2659,2651,2640,2626,2611,
+2596,2583,2573,2566,2562,2560,2557,2553,2545,2533,2517,2497,2476,2454,2435,2419,2406,2398,2392,2387,2381,
+2374,2364,2353,2340,2326,2314,2302,2291,2280,2269,2255,2238,2215,2186,2151,2108,2061,2010,1957,1903,1848,
+1793,1736,1679,1620,1561,1502,1446,1392,1340,1292,1244,1198,1154,1111,1070,1033,999,968,937,906,873,
+836,797,756,714,672,631,591,551,511,470,429,387,346,308,273,244,219,200,184,170,154,
+136,113,87,59,30,2,-24,-49,-73,-100,-130,-164,-202,-244,-287,-331,-374,-415,-453,-487,-517,
+-543,-565,-584,-601,-619,-640,-663,-688,-712,-735,-753,-766,-775,-781,-789,-800,-815,-835,-859,-885,-914,
+-943,-974,-1006,-1039,-1074,-1109,-1144,-1177,-1208,-1236,-1262,-1286,-1308,-1331,-1355,-1381,-1409,-1439,-1470,-1503,-1536,
+-1568,-1600,-1631,-1663,-1695,-1730,-1765,-1800,-1836,-1870,-1902,-1933,-1963,-1994,-2025,-2056,-2087,-2117,-2146,-2173,-2199,
+-2224,-2248,-2273,-2297,-2322,-2347,-2372,-2398,-2424,-2451,-2477,-2504,-2529,-2553,-2576,-2599,-2624,-2650,-2677,-2705,-2731,
+-2756,-2777,-2795,-2812,-2829,-2847,-2867,-2888,-2909,-2928,-2946,-2962,-2977,-2991,-3004,-3018,-3032,-3046,-3059,-3072,-3084,
+-3098,-3114,-3130,-3148,-3165,-3182,-3198,-3214,-3229,-3245,-3262,-3279,-3296,-3313,-3328,-3343,-3356,-3368,-3380,-3392,-3402,
+-3412,-3421,-3430,-3439,-3449,-3460,-3472,-3483,-3492,-3498,-3501,-3501,-3500,-3500,-3500,-3503,-3506,-3510,-3513,-3514,-3514,
+-3512,-3509,-3507,-3505,-3503,-3502,-3501,-3499,-3498,-3496,-3496,-3496,-3497,-3498,-3499,-3498,-3495,-3490,-3481,-3472,-3462,
+-3454,-3449,-3446,-3445,-3444,-3440,-3434,-3423,-3410,-3397,-3386,-3380,-3379,-3381,-3382,-3380,-3373,-3359,-3342,-3324,-3309,
+-3300,-3297,-3300,-3305,-3310,-3313,-3313,-3308,-3298,-3285,-3269,-3249,-3228,-3205,-3183,-3163,-3147,-3137,-3131,-3131,-3134,
+-3141,-3151,-3164,-3181,-3200,-3221,-3242,-3260,-3274,-3283,-3286,-3284,-3281,-3277,-3276,-3278,-3283,-3292,-3304,-3317,-3331,
+-3344,-3359,-3374,-3390,-3409,-3430,-3453,-3477,-3501,-3525,-3546,-3567,-3587,-3608,-3632,-3657,-3684,-3714,-3744,-3775,-3805,
+-3834,-3861,-3885,-3907,-3925,-3940,-3954,-3970,-3990,-4019,-4057,-4105,-4161,-4222,-4284,-4340,-4389,-4428,-4457,-4475,-4487,
+-4493,-4497,-4501,-4508,-4518,-4532,-4551,-4573,-4596,-4618,-4638,-4655,-4668,-4678,-4688,-4699,-4712,-4728,-4746,-4762,-4777,
+-4786,-4791,-4791,-4789,-4785,-4783,-4782,-4783,-4785,-4788,-4789,-4791,-4793,-4797,-4803,-4811,-4818,-4824,-4825,-4822,-4814,
+-4803,-4791,-4781,-4772,-4766,-4759,-4753,-4745,-4736,-4728,-4721,-4717,-4715,-4714,-4713,-4709,-4701,-4690,-4677,-4664,-4651,
+-4639,-4629,-4621,-4612,-4604,-4594,-4585,-4575,-4565,-4556,-4547,-4539,-4533,-4527,-4522,-4518,-4512,-4504,-4492,-4477,-4459,
+-4439,-4420,-4401,-4384,-4369,-4354,-4341,-4328,-4315,-4305,-4297,-4291,-4287,-4283,-4278,-4271,-4262,-4251,-4240,-4229,-4219,
+-4210,-4200,-4188,-4175,-4160,-4144,-4126,-4109,-4091,-4074,-4057,-4040,-4025,-4010,-3997,-3985,-3973,-3962,-3949,-3935,-3919,
+-3903,-3887,-3874,-3862,-3851,-3841,-3830,-3818,-3803,-3787,-3770,-3753,-3737,-3723,-3710,-3697,-3685,-3673,-3662,-3651,-3640,
+-3629,-3617,-3605,-3592,-3579,-3566,-3556,-3547,-3539,-3533,-3528,-3523,-3518,-3512,-3506,-3499,-3491,-3482,-3472,-3463,-3454,
+-3446,-3440,-3434,-3430,-3426,-3422,-3418,-3415,-3412,-3410,-3408,-3406,-3402,-3397,-3390,-3384,-3378,-3374,-3371,-3369,-3368,
+-3365,-3360,-3354,-3347,-3340,-3334,-3329,-3325,-3321,-3316,-3309,-3301,-3291,-3282,-3275,-3269,-3264,-3259,-3254,-3247,-3240,
+-3234,-3229,-3226,-3224,-3224,-3223,-3221,-3217,-3210,-3201,-3192,-3183,-3176,-3170,-3165,-3159,-3152,-3142,-3129,-3114,-3097,
+-3080,-3063,-3047,-3034,-3023,-3015,-3008,-3003,-2996,-2988,-2976,-2962,-2946,-2930,-2914,-2900,-2888,-2877,-2867,-2856,-2844,
+-2831,-2818,-2807,-2799,-2796,-2796,-2799,-2804,-2810,-2817,-2826,-2836,-2848,-2860,-2868,-2871,-2866,-2853,-2834,-2809,-2784,
+-2759,-2737,-2716,-2696,-2676,-2655,-2635,-2617,-2603,-2593,-2587,-2584,-2581,-2578,-2572,-2564,-2554,-2544,-2535,-2528,-2521,
+-2515,-2510,-2504,-2500,-2496,-2492,-2490,-2487,-2484,-2480,-2475,-2469,-2463,-2457,-2452,-2447,-2443,-2440,-2437,-2434,-2431,
+-2428,-2426,-2423,-2420,-2416,-2413,-2408,-2402,-2395,-2386,-2376,-2363,-2349,-2333,-2316,-2298,-2280,-2263,-2246,-2230,-2214,
+-2199,-2186,-2173,-2163,-2154,-2148,-2144,-2142,-2140,-2137,-2133,-2125,-2113,-2097,-2080,-2061,-2043,-2027,-2012,-1999,-1986,
+-1972,-1955,-1938,-1919,-1900,-1882,-1867,-1855,-1845,-1837,-1830,-1822,-1812,-1801,-1787,-1771,-1753,-1734,-1716,-1697,-1679,
+-1660,-1642,-1625,-1607,-1591,-1575,-1560,-1545,-1530,-1514,-1497,-1480,-1463,-1447,-1433,-1421,-1410,-1400,-1388,-1374,-1358,
+-1340,-1321,-1302,-1284,-1267,-1250,-1234,-1217,-1200,-1184,-1167,-1151,-1135,-1118,-1100,-1081,-1061,-1041,-1021,-1001,-981,
+-961,-940,-919,-898,-878,-859,-841,-823,-805,-786,-765,-743,-720,-698,-677,-657,-638,-619,-599,-577,-554,
+-531,-507,-484,-460,-437,-413,-387,-361,-334,-306,-278,-249,-219,-186,-152,-117,-82,-48,-16,12,39,
+66,93,122,153,186,221,257,295,334,375,417,460,502,544,584,623,661,699,736,774,810,
+844,877,907,936,965,994,1026,1060,1097,1134,1171,1208,1242,1277,1312,1350,1392,1439,1490,1542,1592,
+1635,1670,1694,1708,1716,1721,1727,1737,1753,1772,1793,1812,1826,1835,1837,1833,1824,1809,1789,1763,1732,
+1697,1661,1628,1599,1578,1563,1554,1548,1543,1540,1542,1556,1589,1644,1724,1825,1938,2050,2150,2229,2284,
+2317,2334,2344,2352,2361,2369,2372,2367,2350,2325,2293,2260,2229,2202,2178,2156,2134,2113,2095,2083,2079,
+2080,2084,2086,2082,2074,2066,2067,2085,2125,2187,2263,2343,2416,2474,2514,2539,2555,2568,2580,2591,2598,
+2598,2589,2572,2548,2519,2486,2443,2386,2310,2215,2107,1999,1907,1844,1818,1827,1862,1908,1951,1979,1992,
+1995,1997,2008,2033,2072,2116,2154,2175,2175,2155,2123,2091,2069,2065,2080,2109,2145,2179,2204,2217,2220,
+2217,2214,2214,2219,2228,2237,2245,2249,2247,2243,2236,2230,2225,2223,2223,2222,2219,2213,2201,2185,2165,
+2142,2118,2091,2061,2026,1984,1934,1876,1814,1755,1703,1665,1644,1639,1648,1664,1679,1688,1688,1681,1668,
+1655,1648,1649,1659,1676,1698,1721,1741,1757,1769,1778,1785,1792,1798,1802,1805,1804,1800,1793,1783,1771,
+1759,1745,1731,1715,1697,1679,1661,1645,1630,1617,1607,1600,1593,1589,1587,1587,1589,1592,1594,1594,1592,
+1586,1577,1566,1555,1545,1537,1530,1524,1518,1512,1506,1499,1492,1485,1479,1474,1469,1466,1465,1464,1464,
+1464,1461,1455,1446,1434,1422,1409,1398,1391,1386,1385,1386,1389,1394,1400,1406,1410,1413,1414,1413,1411,
+1409,1407,1406,1407,1409,1411,1415,1418,1422,1427,1432,1401,1407,1414,1421,1427,1432,1437,1443,1450,1459,
+1469,1480,1491,1502,1514,1527,1541,1558,1577,1599,1623,1649,1675,1701,1726,1749,1771,1793,1816,1839,1862,
+1886,1909,1932,1953,1973,1993,2013,2035,2058,2082,2108,2135,2162,2189,2217,2246,2274,2302,2327,2348,2364,
+2374,2380,2383,2385,2387,2391,2395,2398,2400,2400,2399,2397,2398,2401,2407,2416,2426,2435,2442,2448,2451,
+2454,2458,2463,2470,2479,2488,2497,2505,2510,2511,2508,2502,2493,2482,2473,2468,2469,2477,2492,2512,2533,
+2552,2566,2573,2573,2568,2561,2556,2554,2559,2569,2584,2603,2622,2642,2659,2676,2690,2702,2712,2719,2724,
+2727,2728,2729,2731,2735,2742,2751,2762,2772,2780,2787,2791,2795,2798,2802,2808,2816,2825,2836,2846,2858,
+2869,2882,2897,2914,2934,2955,2976,2997,3015,3031,3043,3054,3064,3075,3089,3106,3127,3148,3169,3186,3200,
+3209,3216,3222,3229,3237,3248,3259,3269,3277,3284,3289,3292,3294,3295,3293,3290,3285,3280,3276,3274,3273,
+3273,3272,3267,3257,3243,3228,3213,3202,3195,3194,3195,3196,3195,3191,3184,3176,3169,3162,3158,3154,3150,
+3145,3140,3134,3129,3125,3122,3118,3115,3113,3111,3110,3111,3115,3119,3123,3127,3130,3131,3132,3133,3134,
+3135,3134,3133,3131,3128,3126,3126,3128,3132,3137,3142,3146,3150,3153,3157,3162,3168,3171,3172,3168,3160,
+3149,3137,3126,3117,3109,3102,3094,3084,3072,3059,3047,3038,3030,3024,3018,3010,3000,2989,2978,2967,2960,
+2954,2951,2947,2943,2937,2929,2920,2911,2902,2892,2880,2866,2852,2837,2826,2818,2815,2815,2816,2813,2805,
+2789,2766,2739,2711,2685,2662,2645,2631,2619,2607,2594,2581,2568,2556,2546,2538,2531,2524,2518,2510,2501,
+2490,2477,2463,2446,2427,2408,2390,2373,2360,2349,2342,2337,2334,2329,2323,2315,2304,2290,2275,2260,2244,
+2228,2212,2194,2174,2151,2122,2088,2049,2005,1959,1911,1863,1814,1765,1714,1661,1605,1547,1488,1430,1373,
+1319,1268,1219,1172,1127,1083,1043,1005,971,939,908,877,845,810,772,731,687,642,595,549,504,
+459,416,374,334,296,261,228,199,173,152,134,118,102,86,66,45,20,-5,-31,-58,-84,
+-112,-141,-172,-207,-244,-283,-323,-364,-405,-445,-484,-521,-555,-585,-611,-633,-653,-672,-691,-711,-731,
+-749,-765,-777,-785,-791,-798,-806,-819,-838,-860,-887,-917,-948,-981,-1015,-1051,-1087,-1123,-1159,-1192,-1223,
+-1251,-1277,-1301,-1323,-1345,-1368,-1391,-1415,-1441,-1469,-1500,-1533,-1567,-1602,-1637,-1672,-1707,-1742,-1778,-1815,-1852,
+-1889,-1926,-1960,-1992,-2023,-2052,-2080,-2109,-2138,-2166,-2194,-2222,-2248,-2274,-2299,-2323,-2348,-2371,-2395,-2419,-2444,
+-2470,-2497,-2525,-2553,-2580,-2606,-2631,-2655,-2679,-2703,-2728,-2753,-2778,-2800,-2821,-2841,-2859,-2878,-2897,-2918,-2940,
+-2961,-2982,-3001,-3018,-3034,-3050,-3066,-3082,-3097,-3111,-3124,-3137,-3149,-3162,-3177,-3194,-3212,-3231,-3249,-3266,-3281,
+-3295,-3309,-3324,-3339,-3356,-3373,-3389,-3404,-3418,-3429,-3439,-3447,-3454,-3461,-3468,-3475,-3484,-3495,-3507,-3520,-3534,
+-3545,-3554,-3560,-3562,-3563,-3564,-3564,-3565,-3567,-3568,-3569,-3569,-3568,-3568,-3568,-3570,-3572,-3575,-3576,-3574,-3571,
+-3565,-3559,-3553,-3549,-3547,-3547,-3548,-3549,-3547,-3544,-3537,-3529,-3520,-3511,-3505,-3502,-3500,-3499,-3496,-3492,-3484,
+-3475,-3465,-3456,-3450,-3447,-3447,-3448,-3447,-3442,-3432,-3419,-3402,-3387,-3374,-3365,-3361,-3362,-3366,-3371,-3374,-3374,
+-3370,-3362,-3348,-3331,-3310,-3287,-3264,-3242,-3222,-3207,-3196,-3190,-3190,-3195,-3205,-3219,-3235,-3253,-3270,-3286,-3299,
+-3308,-3315,-3320,-3322,-3325,-3328,-3331,-3335,-3340,-3347,-3355,-3365,-3376,-3388,-3402,-3416,-3432,-3448,-3466,-3485,-3505,
+-3526,-3547,-3569,-3591,-3613,-3636,-3658,-3680,-3701,-3722,-3744,-3765,-3789,-3815,-3843,-3873,-3902,-3930,-3956,-3977,-3997,
+-4016,-4038,-4064,-4097,-4137,-4183,-4234,-4287,-4340,-4391,-4439,-4481,-4517,-4544,-4564,-4575,-4581,-4584,-4586,-4592,-4603,
+-4618,-4636,-4655,-4673,-4688,-4700,-4711,-4722,-4735,-4751,-4768,-4785,-4799,-4808,-4812,-4812,-4809,-4808,-4808,-4812,-4819,
+-4826,-4831,-4832,-4830,-4825,-4820,-4816,-4815,-4817,-4821,-4826,-4829,-4831,-4830,-4827,-4823,-4818,-4812,-4805,-4796,-4786,
+-4775,-4764,-4755,-4748,-4743,-4740,-4737,-4734,-4729,-4723,-4716,-4708,-4700,-4692,-4683,-4674,-4664,-4653,-4642,-4630,-4619,
+-4608,-4596,-4585,-4574,-4564,-4555,-4547,-4540,-4534,-4527,-4519,-4509,-4497,-4483,-4468,-4453,-4436,-4419,-4401,-4383,-4365,
+-4349,-4335,-4324,-4314,-4306,-4297,-4287,-4277,-4266,-4256,-4248,-4242,-4236,-4230,-4223,-4214,-4203,-4190,-4176,-4163,-4150,
+-4137,-4123,-4108,-4092,-4075,-4059,-4044,-4032,-4020,-4009,-3998,-3985,-3971,-3955,-3940,-3926,-3914,-3902,-3891,-3879,-3866,
+-3851,-3835,-3819,-3804,-3790,-3777,-3764,-3751,-3738,-3726,-3713,-3701,-3690,-3679,-3669,-3659,-3649,-3639,-3630,-3622,-3614,
+-3606,-3599,-3591,-3583,-3576,-3569,-3562,-3556,-3549,-3542,-3535,-3527,-3518,-3510,-3503,-3496,-3490,-3485,-3480,-3476,-3472,
+-3470,-3468,-3467,-3465,-3462,-3458,-3452,-3446,-3440,-3436,-3434,-3433,-3432,-3430,-3426,-3421,-3414,-3407,-3402,-3397,-3394,
+-3390,-3386,-3378,-3369,-3359,-3348,-3339,-3332,-3326,-3321,-3315,-3307,-3298,-3289,-3281,-3275,-3272,-3271,-3271,-3270,-3267,
+-3262,-3254,-3246,-3237,-3230,-3224,-3218,-3212,-3203,-3193,-3180,-3165,-3149,-3134,-3120,-3108,-3098,-3090,-3082,-3075,-3068,
+-3059,-3049,-3038,-3027,-3014,-3002,-2991,-2980,-2970,-2960,-2949,-2936,-2923,-2909,-2896,-2885,-2878,-2873,-2870,-2868,-2866,
+-2864,-2863,-2865,-2869,-2876,-2885,-2895,-2902,-2905,-2902,-2894,-2883,-2869,-2855,-2840,-2823,-2804,-2781,-2755,-2728,-2701,
+-2678,-2659,-2646,-2636,-2630,-2624,-2619,-2612,-2604,-2597,-2590,-2583,-2577,-2570,-2564,-2558,-2552,-2546,-2541,-2536,-2531,
+-2526,-2520,-2514,-2506,-2499,-2491,-2485,-2480,-2476,-2472,-2470,-2467,-2466,-2464,-2463,-2461,-2459,-2456,-2451,-2445,-2437,
+-2427,-2414,-2400,-2385,-2369,-2354,-2340,-2328,-2316,-2305,-2293,-2281,-2267,-2251,-2235,-2218,-2202,-2187,-2174,-2163,-2154,
+-2147,-2140,-2133,-2125,-2116,-2106,-2094,-2083,-2071,-2059,-2047,-2033,-2018,-2001,-1982,-1963,-1945,-1928,-1913,-1901,-1892,
+-1884,-1877,-1869,-1861,-1851,-1839,-1826,-1811,-1796,-1779,-1762,-1743,-1724,-1703,-1682,-1660,-1639,-1618,-1599,-1581,-1564,
+-1547,-1530,-1513,-1497,-1481,-1467,-1456,-1446,-1438,-1428,-1418,-1405,-1390,-1372,-1353,-1333,-1313,-1292,-1273,-1254,-1238,
+-1223,-1211,-1201,-1192,-1184,-1174,-1161,-1144,-1124,-1100,-1075,-1048,-1022,-997,-973,-951,-931,-913,-895,-878,-860,
+-840,-818,-794,-769,-745,-723,-704,-687,-671,-654,-634,-612,-587,-561,-536,-510,-484,-458,-430,-401,-370,
+-339,-308,-279,-249,-219,-188,-155,-121,-85,-50,-17,12,40,66,92,118,147,178,211,245,281,
+320,360,402,445,489,531,571,608,642,675,707,741,775,811,848,884,919,952,985,1017,1049,
+1082,1115,1147,1178,1208,1237,1266,1299,1337,1381,1430,1482,1534,1581,1621,1650,1672,1687,1701,1716,1735,
+1757,1779,1799,1812,1816,1807,1788,1759,1723,1683,1640,1598,1559,1524,1497,1480,1475,1480,1495,1515,1536,
+1556,1575,1597,1628,1673,1739,1825,1928,2039,2147,2240,2311,2358,2382,2391,2391,2390,2389,2388,2385,2377,
+2362,2341,2316,2290,2264,2237,2209,2176,2140,2102,2066,2037,2019,2010,2009,2010,2009,2005,2001,2003,2018,
+2051,2103,2167,2236,2301,2354,2392,2417,2434,2445,2455,2463,2467,2466,2460,2451,2444,2440,2438,2433,2418,
+2385,2329,2252,2163,2076,2005,1960,1944,1952,1974,1998,2015,2020,2018,2014,2017,2030,2054,2081,2105,2117,
+2116,2101,2081,2063,2055,2061,2080,2107,2135,2158,2171,2175,2172,2167,2162,2161,2163,2169,2175,2179,2181,
+2179,2175,2168,2161,2154,2148,2143,2141,2139,2137,2133,2125,2113,2095,2073,2049,2024,2000,1976,1952,1928,
+1901,1873,1844,1817,1793,1774,1759,1745,1732,1716,1696,1675,1655,1640,1633,1636,1648,1667,1689,1710,1727,
+1739,1746,1752,1756,1761,1766,1769,1770,1767,1758,1745,1727,1707,1686,1665,1645,1625,1607,1591,1577,1565,
+1555,1547,1539,1532,1525,1520,1516,1514,1514,1516,1519,1521,1521,1519,1516,1511,1505,1500,1494,1488,1482,
+1474,1464,1454,1443,1433,1424,1418,1414,1412,1414,1418,1425,1431,1436,1438,1435,1427,1414,1398,1381,1366,
+1354,1348,1347,1351,1358,1366,1373,1379,1382,1384,1383,1383,1383,1383,1385,1387,1389,1391,1391,1391,1391,
+1393,1396,1401,1383,1391,1398,1405,1411,1415,1420,1426,1433,1444,1456,1470,1485,1500,1516,1532,1549,1567,
+1588,1611,1636,1662,1688,1713,1737,1760,1783,1807,1832,1858,1886,1913,1939,1963,1983,2000,2015,2029,2044,
+2061,2081,2103,2128,2156,2186,2218,2250,2282,2312,2337,2356,2368,2374,2376,2377,2379,2382,2387,2392,2396,
+2396,2394,2390,2386,2385,2388,2395,2404,2414,2423,2429,2432,2434,2437,2442,2449,2459,2470,2479,2486,2489,
+2488,2482,2474,2464,2453,2446,2442,2443,2451,2465,2482,2499,2515,2526,2530,2528,2522,2515,2510,2509,2513,
+2522,2534,2548,2562,2576,2589,2604,2618,2633,2647,2659,2669,2675,2678,2680,2683,2687,2694,2704,2715,2727,
+2737,2744,2748,2750,2751,2752,2754,2759,2766,2774,2785,2796,2808,2821,2834,2850,2867,2886,2906,2927,2948,
+2967,2984,2998,3010,3022,3035,3050,3069,3091,3113,3135,3154,3170,3182,3191,3199,3208,3217,3227,3236,3244,
+3251,3256,3260,3263,3265,3267,3267,3265,3263,3259,3255,3251,3249,3247,3244,3238,3230,3219,3207,3196,3188,
+3183,3180,3179,3178,3175,3169,3162,3154,3146,3139,3133,3128,3123,3118,3113,3108,3104,3101,3098,3096,3094,
+3093,3093,3094,3096,3099,3102,3105,3107,3109,3111,3114,3118,3122,3126,3128,3128,3127,3124,3122,3122,3124,
+3127,3131,3133,3134,3134,3134,3135,3137,3140,3143,3143,3139,3131,3120,3108,3097,3089,3083,3077,3071,3062,
+3051,3038,3025,3014,3004,2996,2987,2976,2962,2947,2931,2917,2906,2899,2895,2893,2890,2886,2881,2874,2867,
+2859,2851,2842,2834,2825,2817,2810,2806,2805,2804,2802,2795,2782,2763,2738,2710,2682,2656,2634,2615,2598,
+2583,2568,2554,2541,2530,2520,2512,2505,2497,2488,2476,2462,2446,2430,2414,2398,2382,2367,2351,2336,2322,
+2310,2302,2296,2293,2291,2288,2285,2279,2271,2260,2245,2229,2210,2188,2166,2141,2115,2086,2056,2022,1985,
+1945,1901,1855,1806,1756,1704,1651,1597,1542,1487,1433,1381,1331,1283,1237,1192,1149,1107,1066,1027,989,
+954,920,888,857,825,792,756,716,674,628,579,530,480,433,387,344,303,265,229,196,165,
+137,113,92,74,57,40,21,0,-22,-46,-73,-100,-128,-157,-188,-220,-254,-289,-325,-363,-401,
+-439,-478,-516,-552,-586,-616,-642,-665,-685,-703,-721,-739,-755,-770,-782,-791,-798,-804,-812,-824,-840,
+-860,-885,-913,-944,-976,-1012,-1049,-1089,-1130,-1170,-1207,-1240,-1269,-1293,-1314,-1335,-1356,-1377,-1401,-1425,-1451,
+-1478,-1506,-1536,-1568,-1601,-1636,-1672,-1708,-1745,-1782,-1820,-1858,-1898,-1937,-1976,-2012,-2046,-2077,-2106,-2133,-2160,
+-2187,-2214,-2242,-2270,-2299,-2326,-2353,-2379,-2403,-2426,-2447,-2468,-2490,-2513,-2539,-2567,-2596,-2626,-2655,-2682,-2708,
+-2733,-2756,-2779,-2801,-2823,-2844,-2865,-2885,-2905,-2926,-2947,-2969,-2991,-3012,-3032,-3051,-3069,-3085,-3102,-3119,-3135,
+-3152,-3167,-3181,-3195,-3208,-3223,-3240,-3260,-3280,-3301,-3320,-3337,-3351,-3364,-3375,-3387,-3400,-3414,-3429,-3444,-3459,
+-3471,-3482,-3490,-3497,-3502,-3508,-3513,-3520,-3527,-3537,-3548,-3561,-3575,-3588,-3600,-3610,-3617,-3623,-3626,-3629,-3630,
+-3630,-3629,-3626,-3624,-3623,-3624,-3627,-3633,-3640,-3648,-3653,-3656,-3654,-3649,-3641,-3632,-3625,-3619,-3615,-3613,-3611,
+-3609,-3604,-3598,-3590,-3581,-3572,-3565,-3559,-3555,-3553,-3550,-3548,-3545,-3541,-3536,-3531,-3527,-3523,-3521,-3519,-3517,
+-3512,-3505,-3494,-3481,-3466,-3451,-3438,-3430,-3427,-3428,-3433,-3439,-3443,-3443,-3438,-3427,-3411,-3391,-3368,-3345,-3322,
+-3301,-3282,-3268,-3259,-3255,-3259,-3268,-3283,-3301,-3319,-3335,-3347,-3354,-3357,-3357,-3357,-3358,-3362,-3368,-3377,-3386,
+-3396,-3405,-3413,-3421,-3429,-3438,-3447,-3459,-3472,-3487,-3504,-3522,-3542,-3563,-3586,-3608,-3631,-3654,-3676,-3697,-3717,
+-3734,-3750,-3764,-3779,-3796,-3816,-3840,-3869,-3901,-3934,-3966,-3995,-4020,-4042,-4062,-4081,-4102,-4126,-4155,-4189,-4229,
+-4276,-4328,-4386,-4445,-4502,-4554,-4596,-4626,-4644,-4653,-4656,-4657,-4660,-4667,-4678,-4691,-4703,-4714,-4722,-4729,-4736,
+-4744,-4756,-4770,-4785,-4798,-4809,-4816,-4819,-4820,-4823,-4828,-4836,-4846,-4858,-4867,-4872,-4873,-4869,-4861,-4853,-4845,
+-4840,-4838,-4839,-4842,-4846,-4851,-4854,-4855,-4854,-4851,-4845,-4837,-4827,-4817,-4807,-4798,-4791,-4784,-4778,-4773,-4767,
+-4762,-4756,-4750,-4744,-4738,-4731,-4723,-4714,-4703,-4692,-4680,-4669,-4657,-4645,-4634,-4621,-4609,-4597,-4585,-4574,-4563,
+-4553,-4544,-4535,-4526,-4517,-4507,-4497,-4485,-4472,-4457,-4441,-4424,-4408,-4393,-4379,-4368,-4356,-4344,-4331,-4317,-4301,
+-4287,-4275,-4265,-4258,-4252,-4245,-4237,-4227,-4216,-4205,-4195,-4187,-4179,-4172,-4164,-4152,-4138,-4122,-4106,-4091,-4079,
+-4068,-4058,-4048,-4036,-4022,-4007,-3991,-3975,-3961,-3947,-3935,-3923,-3910,-3897,-3883,-3870,-3858,-3846,-3834,-3822,-3810,
+-3796,-3783,-3769,-3756,-3744,-3733,-3724,-3715,-3707,-3700,-3694,-3688,-3682,-3675,-3667,-3658,-3648,-3638,-3628,-3620,-3614,
+-3608,-3603,-3598,-3592,-3585,-3578,-3571,-3564,-3557,-3551,-3544,-3539,-3534,-3530,-3527,-3526,-3524,-3522,-3518,-3513,-3506,
+-3500,-3494,-3490,-3488,-3486,-3485,-3483,-3479,-3475,-3470,-3467,-3465,-3463,-3462,-3459,-3454,-3446,-3436,-3426,-3416,-3407,
+-3400,-3393,-3386,-3377,-3367,-3355,-3344,-3335,-3328,-3324,-3322,-3321,-3319,-3315,-3309,-3303,-3296,-3289,-3283,-3277,-3269,
+-3259,-3248,-3234,-3219,-3204,-3190,-3178,-3167,-3158,-3150,-3142,-3134,-3127,-3120,-3112,-3105,-3097,-3089,-3081,-3072,-3062,
+-3051,-3038,-3024,-3010,-2994,-2980,-2968,-2959,-2953,-2949,-2946,-2944,-2940,-2935,-2928,-2922,-2918,-2915,-2915,-2917,-2919,
+-2922,-2923,-2922,-2921,-2919,-2915,-2909,-2900,-2886,-2867,-2843,-2816,-2788,-2760,-2736,-2716,-2700,-2687,-2676,-2666,-2658,
+-2651,-2644,-2638,-2633,-2627,-2620,-2613,-2606,-2598,-2591,-2584,-2577,-2571,-2564,-2557,-2548,-2540,-2532,-2524,-2518,-2512,
+-2508,-2504,-2501,-2499,-2497,-2496,-2495,-2494,-2492,-2489,-2484,-2477,-2468,-2456,-2444,-2430,-2416,-2403,-2391,-2379,-2369,
+-2359,-2349,-2338,-2326,-2313,-2298,-2282,-2265,-2248,-2232,-2217,-2202,-2188,-2175,-2163,-2153,-2143,-2135,-2127,-2119,-2111,
+-2101,-2090,-2078,-2063,-2047,-2031,-2014,-1998,-1984,-1971,-1961,-1951,-1943,-1935,-1926,-1917,-1905,-1893,-1879,-1864,-1849,
+-1833,-1816,-1799,-1780,-1761,-1740,-1718,-1696,-1675,-1655,-1635,-1616,-1598,-1579,-1559,-1540,-1521,-1504,-1489,-1477,-1466,
+-1456,-1446,-1435,-1423,-1408,-1392,-1374,-1355,-1336,-1316,-1297,-1278,-1262,-1248,-1238,-1231,-1226,-1221,-1215,-1204,-1189,
+-1168,-1142,-1113,-1083,-1053,-1025,-1001,-980,-963,-948,-935,-920,-902,-881,-856,-829,-802,-776,-754,-735,-719,
+-704,-687,-668,-645,-619,-592,-564,-535,-506,-475,-443,-409,-373,-339,-306,-276,-248,-222,-194,-164,-130,
+-94,-57,-20,14,46,76,105,134,164,196,228,260,292,325,358,393,430,469,508,546,582,
+616,648,680,713,747,783,820,858,895,931,965,998,1031,1065,1098,1131,1164,1195,1224,1253,1284,
+1316,1353,1395,1439,1484,1527,1566,1599,1626,1648,1668,1688,1707,1725,1740,1748,1747,1733,1708,1671,1627,
+1580,1534,1492,1459,1437,1429,1437,1459,1496,1544,1599,1655,1707,1753,1791,1825,1857,1894,1940,1997,2062,
+2130,2196,2253,2297,2327,2346,2357,2365,2371,2377,2380,2377,2368,2351,2327,2300,2270,2240,2208,2173,2136,
+2097,2059,2026,2002,1989,1986,1987,1988,1985,1978,1969,1966,1976,2003,2049,2109,2175,2236,2286,2321,2342,
+2352,2355,2355,2351,2345,2336,2325,2316,2312,2317,2330,2348,2361,2360,2338,2293,2230,2158,2089,2035,2001,
+1988,1989,1996,2003,2005,2004,2003,2005,2014,2029,2047,2064,2077,2083,2086,2089,2095,2105,2120,2135,2146,
+2148,2141,2127,2109,2092,2081,2077,2080,2087,2094,2101,2105,2108,2108,2108,2107,2104,2100,2094,2087,2080,
+2075,2072,2070,2066,2060,2048,2032,2013,1993,1976,1962,1951,1942,1932,1918,1900,1877,1852,1827,1804,1784,
+1767,1752,1738,1726,1714,1706,1702,1702,1707,1715,1723,1730,1734,1736,1735,1733,1731,1729,1726,1722,1715,
+1705,1691,1673,1654,1634,1614,1594,1576,1559,1543,1530,1520,1513,1507,1501,1495,1488,1477,1466,1453,1442,
+1433,1426,1423,1422,1422,1424,1426,1429,1433,1437,1441,1443,1442,1437,1429,1417,1404,1390,1376,1366,1360,
+1359,1362,1370,1381,1392,1401,1406,1404,1396,1382,1364,1346,1331,1321,1316,1318,1323,1331,1338,1343,1346,
+1347,1346,1346,1347,1350,1354,1359,1364,1367,1369,1369,1369,1369,1372,1376,1383,1376,1387,1396,1403,1409,
+1413,1418,1424,1433,1444,1457,1473,1489,1506,1523,1540,1558,1577,1598,1621,1646,1671,1696,1721,1744,1767,
+1791,1816,1843,1872,1901,1930,1956,1978,1995,2007,2017,2026,2037,2051,2069,2093,2120,2151,2184,2218,2251,
+2283,2310,2332,2347,2356,2360,2361,2362,2366,2371,2379,2386,2392,2393,2392,2387,2383,2381,2382,2386,2392,
+2399,2404,2408,2410,2413,2419,2426,2437,2448,2458,2464,2464,2459,2449,2437,2425,2415,2409,2409,2414,2423,
+2437,2451,2466,2477,2484,2486,2483,2477,2470,2466,2465,2468,2475,2484,2494,2503,2512,2520,2530,2541,2555,
+2571,2587,2602,2614,2622,2628,2632,2636,2642,2650,2660,2671,2681,2689,2695,2698,2699,2699,2700,2701,2705,
+2711,2719,2730,2742,2756,2772,2788,2806,2824,2843,2863,2884,2905,2925,2943,2959,2974,2987,3001,3017,3035,
+3055,3076,3098,3118,3136,3150,3163,3175,3186,3197,3207,3216,3223,3228,3230,3232,3233,3233,3234,3235,3235,
+3234,3232,3228,3224,3220,3215,3209,3203,3196,3188,3181,3175,3170,3168,3167,3166,3165,3162,3157,3150,3141,
+3132,3123,3114,3106,3099,3093,3088,3085,3082,3080,3077,3075,3072,3070,3069,3069,3070,3072,3073,3075,3076,
+3078,3082,3088,3096,3104,3112,3118,3121,3122,3120,3119,3119,3120,3122,3123,3123,3120,3116,3112,3109,3109,
+3110,3112,3111,3108,3100,3090,3078,3068,3060,3054,3050,3045,3038,3027,3015,3001,2988,2975,2964,2952,2938,
+2923,2906,2888,2872,2860,2851,2846,2844,2842,2840,2836,2831,2826,2820,2814,2808,2802,2796,2791,2787,2783,
+2780,2775,2767,2754,2737,2715,2691,2667,2643,2623,2605,2589,2573,2557,2541,2525,2511,2500,2491,2484,2477,
+2468,2456,2440,2420,2399,2377,2357,2338,2320,2304,2289,2274,2262,2251,2243,2238,2235,2233,2231,2229,2225,
+2220,2212,2202,2188,2171,2149,2123,2094,2062,2029,1995,1960,1923,1883,1839,1791,1739,1684,1627,1570,1515,
+1463,1414,1369,1327,1288,1250,1213,1176,1140,1103,1066,1028,991,955,919,884,850,817,783,748,711,
+671,628,582,533,483,433,384,338,293,250,210,172,137,106,79,55,35,16,-2,-22,-44,
+-67,-92,-117,-142,-167,-193,-220,-249,-280,-313,-349,-387,-425,-464,-503,-540,-575,-607,-634,-658,-679,
+-697,-715,-733,-751,-768,-784,-798,-809,-819,-828,-839,-853,-871,-892,-916,-942,-971,-1002,-1038,-1078,-1121,
+-1167,-1211,-1252,-1286,-1313,-1335,-1352,-1368,-1386,-1406,-1430,-1457,-1485,-1515,-1545,-1576,-1607,-1640,-1674,-1709,-1746,
+-1783,-1821,-1860,-1900,-1941,-1981,-2021,-2058,-2093,-2125,-2154,-2181,-2207,-2233,-2260,-2287,-2315,-2344,-2373,-2401,-2428,
+-2453,-2476,-2497,-2518,-2538,-2561,-2586,-2613,-2643,-2674,-2705,-2734,-2762,-2787,-2810,-2832,-2853,-2873,-2893,-2913,-2934,
+-2955,-2976,-2999,-3022,-3045,-3067,-3088,-3107,-3124,-3140,-3155,-3169,-3183,-3197,-3210,-3224,-3238,-3255,-3273,-3294,-3317,
+-3341,-3363,-3383,-3399,-3411,-3421,-3430,-3439,-3449,-3461,-3474,-3488,-3502,-3514,-3525,-3535,-3543,-3551,-3558,-3565,-3572,
+-3579,-3586,-3595,-3605,-3617,-3629,-3642,-3653,-3664,-3673,-3681,-3686,-3690,-3692,-3693,-3692,-3691,-3692,-3694,-3700,-3710,
+-3721,-3734,-3746,-3756,-3762,-3764,-3761,-3755,-3747,-3737,-3726,-3715,-3704,-3693,-3683,-3672,-3663,-3654,-3646,-3638,-3631,
+-3625,-3620,-3616,-3614,-3612,-3611,-3611,-3609,-3607,-3604,-3600,-3596,-3591,-3586,-3580,-3572,-3561,-3549,-3536,-3523,-3513,
+-3507,-3507,-3510,-3515,-3520,-3522,-3520,-3511,-3497,-3478,-3458,-3436,-3414,-3393,-3374,-3357,-3344,-3337,-3337,-3344,-3357,
+-3375,-3394,-3411,-3424,-3429,-3429,-3425,-3419,-3414,-3412,-3415,-3422,-3432,-3444,-3456,-3466,-3475,-3483,-3490,-3498,-3507,
+-3518,-3532,-3548,-3567,-3587,-3608,-3629,-3650,-3670,-3689,-3708,-3727,-3746,-3763,-3779,-3794,-3809,-3823,-3840,-3859,-3882,
+-3908,-3936,-3965,-3994,-4020,-4044,-4066,-4086,-4106,-4125,-4145,-4167,-4194,-4227,-4268,-4317,-4374,-4435,-4496,-4553,-4602,
+-4641,-4669,-4688,-4702,-4713,-4723,-4733,-4743,-4751,-4756,-4758,-4758,-4758,-4759,-4764,-4772,-4783,-4796,-4808,-4819,-4827,
+-4834,-4839,-4845,-4853,-4862,-4873,-4885,-4895,-4903,-4907,-4908,-4904,-4898,-4890,-4882,-4875,-4871,-4869,-4870,-4872,-4874,
+-4875,-4875,-4872,-4868,-4862,-4855,-4848,-4842,-4836,-4829,-4822,-4813,-4805,-4796,-4787,-4779,-4772,-4765,-4758,-4750,-4742,
+-4732,-4721,-4710,-4698,-4686,-4674,-4662,-4649,-4636,-4624,-4611,-4599,-4586,-4573,-4560,-4548,-4537,-4526,-4517,-4508,-4498,
+-4488,-4477,-4464,-4451,-4439,-4428,-4418,-4408,-4399,-4387,-4373,-4357,-4339,-4322,-4307,-4295,-4284,-4274,-4264,-4253,-4241,
+-4230,-4220,-4213,-4207,-4204,-4199,-4193,-4182,-4169,-4153,-4138,-4124,-4114,-4106,-4099,-4091,-4081,-4068,-4053,-4036,-4019,
+-4002,-3988,-3975,-3963,-3953,-3942,-3932,-3923,-3913,-3904,-3893,-3881,-3868,-3854,-3840,-3826,-3813,-3801,-3790,-3780,-3771,
+-3762,-3755,-3748,-3743,-3738,-3733,-3727,-3719,-3710,-3700,-3691,-3682,-3675,-3668,-3663,-3657,-3652,-3646,-3639,-3633,-3627,
+-3621,-3615,-3609,-3602,-3596,-3592,-3588,-3586,-3584,-3582,-3579,-3575,-3569,-3562,-3554,-3548,-3544,-3541,-3539,-3536,-3534,
+-3531,-3528,-3525,-3524,-3524,-3524,-3524,-3521,-3516,-3508,-3499,-3490,-3482,-3474,-3468,-3462,-3454,-3444,-3433,-3420,-3408,
+-3397,-3389,-3382,-3378,-3374,-3370,-3365,-3361,-3355,-3350,-3344,-3338,-3331,-3321,-3310,-3297,-3283,-3269,-3255,-3242,-3230,
+-3220,-3210,-3201,-3194,-3187,-3182,-3177,-3172,-3167,-3161,-3154,-3145,-3134,-3121,-3108,-3095,-3081,-3068,-3055,-3044,-3035,
+-3028,-3023,-3019,-3015,-3011,-3005,-2998,-2989,-2980,-2971,-2963,-2957,-2952,-2948,-2946,-2944,-2944,-2943,-2942,-2938,-2933,
+-2924,-2911,-2895,-2876,-2856,-2834,-2813,-2792,-2771,-2752,-2734,-2718,-2704,-2693,-2685,-2678,-2673,-2668,-2662,-2655,-2647,
+-2638,-2629,-2621,-2612,-2604,-2595,-2586,-2578,-2570,-2562,-2555,-2550,-2545,-2540,-2536,-2533,-2529,-2527,-2525,-2523,-2521,
+-2518,-2514,-2509,-2502,-2494,-2485,-2476,-2466,-2455,-2445,-2434,-2423,-2412,-2399,-2386,-2372,-2358,-2343,-2328,-2314,-2300,
+-2287,-2273,-2259,-2244,-2229,-2215,-2201,-2189,-2177,-2168,-2159,-2150,-2140,-2129,-2117,-2103,-2089,-2075,-2062,-2050,-2039,
+-2030,-2021,-2012,-2002,-1992,-1982,-1971,-1959,-1947,-1933,-1919,-1903,-1887,-1869,-1850,-1830,-1808,-1787,-1765,-1744,-1724,
+-1705,-1687,-1669,-1652,-1634,-1615,-1595,-1574,-1553,-1534,-1517,-1502,-1488,-1477,-1465,-1453,-1440,-1426,-1411,-1394,-1376,
+-1357,-1337,-1317,-1296,-1278,-1261,-1248,-1239,-1233,-1228,-1222,-1213,-1200,-1182,-1159,-1133,-1104,-1077,-1051,-1029,-1010,
+-995,-982,-970,-955,-937,-915,-889,-861,-832,-806,-782,-762,-744,-727,-708,-686,-661,-634,-605,-576,-546,
+-516,-484,-450,-415,-379,-345,-313,-285,-259,-234,-208,-178,-144,-107,-67,-27,11,48,82,116,150,
+184,218,251,282,311,337,362,388,416,447,481,517,553,590,625,660,694,729,764,800,836,
+871,906,940,974,1009,1046,1083,1121,1158,1194,1227,1258,1287,1317,1349,1384,1421,1459,1497,1531,1560,
+1583,1600,1612,1620,1624,1626,1623,1615,1601,1580,1554,1523,1492,1464,1443,1434,1439,1459,1496,1547,1611,
+1684,1760,1835,1903,1962,2009,2044,2071,2091,2108,2126,2145,2165,2186,2207,2225,2243,2259,2276,2293,2311,
+2327,2338,2341,2335,2318,2292,2262,2229,2196,2165,2134,2104,2074,2045,2021,2005,1998,2000,2007,2014,2015,
+2007,1991,1972,1959,1959,1979,2019,2076,2140,2201,2253,2290,2313,2324,2328,2327,2323,2315,2303,2287,2271,
+2258,2252,2253,2259,2264,2261,2244,2209,2159,2100,2041,1991,1955,1935,1928,1931,1938,1945,1954,1963,1976,
+1991,2008,2026,2042,2055,2067,2079,2093,2110,2126,2139,2144,2137,2117,2088,2056,2026,2005,1996,1997,2004,
+2013,2020,2023,2024,2023,2025,2029,2035,2040,2043,2041,2035,2025,2014,2005,1999,1994,1990,1984,1974,1962,
+1948,1936,1927,1921,1917,1912,1905,1892,1875,1855,1836,1818,1805,1795,1789,1784,1779,1772,1763,1753,1743,
+1734,1726,1720,1715,1710,1706,1701,1696,1689,1680,1668,1653,1636,1616,1596,1577,1559,1544,1531,1519,1507,
+1496,1485,1476,1469,1464,1461,1457,1452,1443,1431,1414,1396,1378,1362,1350,1342,1338,1338,1339,1343,1348,
+1354,1362,1371,1380,1387,1391,1391,1385,1375,1362,1347,1334,1324,1319,1320,1327,1337,1349,1359,1364,1364,
+1357,1344,1329,1315,1303,1295,1293,1295,1300,1305,1308,1310,1310,1309,1310,1311,1315,1321,1327,1332,1337,
+1339,1341,1342,1344,1349,1356,1366,1376,1370,1382,1393,1402,1409,1416,1423,1431,1441,1453,1467,1482,1497,
+1513,1530,1547,1566,1586,1608,1632,1657,1684,1710,1735,1759,1782,1805,1828,1853,1878,1905,1929,1951,1968,
+1981,1990,1997,2006,2018,2035,2057,2085,2116,2149,2182,2213,2242,2267,2289,2306,2318,2326,2331,2335,2339,
+2345,2353,2363,2372,2379,2382,2382,2378,2373,2370,2368,2368,2371,2374,2377,2380,2383,2388,2396,2405,2415,
+2424,2428,2426,2418,2406,2391,2377,2368,2365,2368,2378,2391,2406,2420,2432,2439,2442,2441,2436,2430,2423,
+2418,2416,2417,2422,2429,2437,2444,2450,2456,2462,2469,2479,2492,2507,2523,2538,2551,2562,2570,2577,2584,
+2593,2603,2613,2624,2633,2641,2645,2648,2648,2647,2647,2647,2649,2654,2662,2673,2688,2706,2726,2746,2766,
+2787,2806,2826,2846,2866,2886,2906,2924,2941,2956,2971,2986,3002,3021,3041,3061,3081,3100,3116,3130,3143,
+3155,3167,3178,3188,3196,3201,3204,3206,3206,3205,3204,3204,3203,3202,3199,3196,3191,3185,3179,3173,3166,
+3160,3154,3149,3146,3143,3142,3142,3143,3143,3142,3139,3134,3126,3117,3106,3095,3085,3077,3071,3066,3064,
+3062,3059,3055,3050,3045,3040,3037,3035,3036,3037,3039,3041,3042,3046,3051,3059,3069,3081,3092,3101,3106,
+3109,3109,3109,3109,3111,3112,3112,3110,3106,3099,3092,3087,3084,3083,3083,3083,3079,3072,3062,3051,3041,
+3033,3028,3024,3021,3016,3008,2997,2985,2972,2959,2946,2933,2918,2902,2884,2865,2847,2831,2820,2811,2806,
+2803,2801,2798,2795,2791,2786,2780,2774,2767,2760,2753,2746,2739,2731,2722,2710,2696,2679,2659,2640,2621,
+2605,2591,2578,2565,2551,2534,2517,2500,2486,2475,2467,2460,2453,2443,2429,2410,2387,2362,2337,2313,2291,
+2270,2249,2230,2212,2195,2181,2170,2162,2157,2153,2151,2149,2147,2144,2141,2137,2130,2118,2100,2077,2048,
+2014,1979,1942,1906,1869,1830,1788,1742,1691,1637,1580,1524,1471,1422,1377,1338,1302,1268,1235,1203,1171,
+1139,1106,1072,1037,1001,964,926,888,850,814,779,744,708,670,630,587,541,493,444,394,345,
+296,249,204,162,125,91,62,37,14,-7,-30,-55,-81,-107,-132,-155,-176,-195,-214,-234,-258,
+-285,-317,-353,-392,-432,-474,-514,-553,-589,-621,-648,-672,-693,-713,-732,-752,-772,-792,-810,-826,-840,
+-852,-863,-876,-890,-908,-927,-948,-971,-997,-1026,-1061,-1101,-1146,-1194,-1242,-1285,-1321,-1348,-1368,-1383,-1396,
+-1411,-1430,-1454,-1483,-1515,-1548,-1582,-1616,-1650,-1684,-1719,-1754,-1791,-1829,-1868,-1907,-1947,-1987,-2027,-2066,-2103,
+-2137,-2169,-2198,-2225,-2251,-2276,-2302,-2328,-2354,-2381,-2409,-2437,-2464,-2491,-2517,-2542,-2566,-2590,-2615,-2640,-2668,
+-2696,-2725,-2754,-2783,-2810,-2835,-2858,-2880,-2901,-2921,-2941,-2960,-2979,-3000,-3021,-3043,-3067,-3091,-3116,-3139,-3160,
+-3179,-3195,-3209,-3220,-3229,-3238,-3247,-3258,-3271,-3288,-3309,-3332,-3357,-3382,-3404,-3423,-3437,-3447,-3456,-3463,-3471,
+-3482,-3495,-3509,-3524,-3539,-3553,-3567,-3579,-3590,-3600,-3610,-3619,-3626,-3634,-3641,-3649,-3658,-3668,-3679,-3690,-3701,
+-3711,-3719,-3727,-3734,-3740,-3747,-3754,-3761,-3768,-3776,-3784,-3795,-3808,-3823,-3840,-3858,-3875,-3890,-3900,-3905,-3903,
+-3895,-3880,-3861,-3838,-3814,-3791,-3770,-3754,-3741,-3731,-3724,-3718,-3712,-3704,-3697,-3690,-3685,-3683,-3682,-3682,-3682,
+-3682,-3679,-3676,-3671,-3666,-3661,-3656,-3651,-3644,-3635,-3625,-3615,-3605,-3598,-3595,-3596,-3599,-3603,-3605,-3604,-3598,
+-3587,-3572,-3555,-3535,-3515,-3494,-3473,-3453,-3435,-3422,-3414,-3415,-3423,-3438,-3458,-3477,-3494,-3505,-3510,-3507,-3500,
+-3491,-3483,-3477,-3476,-3479,-3487,-3498,-3510,-3522,-3533,-3543,-3552,-3562,-3573,-3586,-3602,-3620,-3640,-3660,-3678,-3696,
+-3712,-3727,-3743,-3760,-3779,-3798,-3818,-3838,-3856,-3873,-3889,-3904,-3920,-3937,-3955,-3974,-3994,-4015,-4038,-4061,-4085,
+-4109,-4132,-4153,-4173,-4192,-4212,-4236,-4266,-4304,-4349,-4400,-4456,-4511,-4563,-4610,-4650,-4684,-4713,-4738,-4760,-4778,
+-4791,-4801,-4806,-4807,-4805,-4803,-4802,-4804,-4810,-4819,-4830,-4842,-4853,-4862,-4868,-4872,-4874,-4877,-4881,-4888,-4898,
+-4911,-4924,-4935,-4942,-4944,-4940,-4932,-4921,-4909,-4900,-4893,-4889,-4889,-4889,-4890,-4891,-4889,-4887,-4884,-4880,-4875,
+-4870,-4864,-4856,-4847,-4838,-4828,-4818,-4809,-4800,-4793,-4785,-4777,-4769,-4760,-4749,-4737,-4724,-4711,-4697,-4683,-4670,
+-4657,-4644,-4633,-4621,-4608,-4595,-4581,-4567,-4554,-4541,-4531,-4521,-4512,-4502,-4492,-4481,-4470,-4460,-4452,-4444,-4437,
+-4430,-4420,-4408,-4393,-4377,-4361,-4345,-4332,-4319,-4308,-4296,-4283,-4271,-4259,-4249,-4241,-4236,-4231,-4226,-4217,-4206,
+-4192,-4177,-4162,-4151,-4143,-4138,-4134,-4129,-4121,-4110,-4096,-4080,-4063,-4047,-4033,-4020,-4009,-3999,-3990,-3982,-3974,
+-3965,-3957,-3946,-3934,-3921,-3908,-3894,-3882,-3871,-3860,-3850,-3840,-3830,-3820,-3811,-3802,-3795,-3790,-3785,-3781,-3776,
+-3770,-3763,-3755,-3747,-3740,-3732,-3725,-3717,-3709,-3701,-3693,-3687,-3682,-3678,-3675,-3671,-3666,-3661,-3656,-3651,-3648,
+-3646,-3645,-3643,-3640,-3636,-3630,-3623,-3616,-3610,-3605,-3601,-3598,-3594,-3589,-3585,-3581,-3578,-3576,-3575,-3574,-3572,
+-3569,-3563,-3556,-3549,-3542,-3537,-3533,-3529,-3525,-3519,-3510,-3499,-3486,-3474,-3462,-3452,-3445,-3438,-3433,-3428,-3424,
+-3419,-3414,-3409,-3403,-3396,-3388,-3378,-3367,-3355,-3342,-3329,-3316,-3303,-3292,-3281,-3272,-3264,-3257,-3251,-3246,-3240,
+-3234,-3225,-3216,-3205,-3194,-3183,-3172,-3163,-3155,-3146,-3138,-3129,-3119,-3109,-3100,-3092,-3084,-3078,-3071,-3064,-3056,
+-3047,-3037,-3026,-3016,-3006,-2997,-2989,-2982,-2975,-2968,-2960,-2952,-2943,-2934,-2925,-2917,-2909,-2900,-2890,-2877,-2861,
+-2842,-2820,-2797,-2775,-2755,-2738,-2726,-2716,-2710,-2704,-2699,-2692,-2685,-2677,-2667,-2657,-2647,-2636,-2626,-2616,-2607,
+-2599,-2592,-2586,-2581,-2576,-2572,-2568,-2563,-2559,-2556,-2552,-2549,-2545,-2541,-2536,-2530,-2523,-2516,-2509,-2502,-2495,
+-2487,-2478,-2467,-2456,-2442,-2428,-2413,-2398,-2383,-2369,-2355,-2343,-2330,-2318,-2306,-2293,-2279,-2265,-2251,-2237,-2224,
+-2213,-2201,-2190,-2179,-2167,-2154,-2140,-2127,-2115,-2104,-2096,-2088,-2081,-2073,-2064,-2053,-2040,-2026,-2012,-1998,-1986,
+-1973,-1961,-1948,-1934,-1917,-1897,-1876,-1853,-1829,-1805,-1781,-1759,-1739,-1721,-1704,-1689,-1674,-1658,-1642,-1623,-1605,
+-1585,-1566,-1548,-1532,-1517,-1504,-1491,-1478,-1464,-1450,-1435,-1418,-1400,-1380,-1359,-1336,-1313,-1290,-1269,-1251,-1237,
+-1226,-1218,-1211,-1202,-1192,-1179,-1162,-1142,-1121,-1099,-1078,-1058,-1040,-1024,-1009,-994,-977,-958,-935,-910,-883,
+-856,-830,-805,-783,-761,-738,-714,-689,-661,-631,-602,-573,-544,-516,-486,-456,-424,-392,-360,-331,-303,
+-276,-249,-220,-187,-150,-109,-68,-26,12,50,85,120,155,191,226,261,292,320,345,367,389,
+412,438,468,501,535,571,606,641,676,711,746,780,815,849,883,917,952,990,1029,1070,1111,
+1151,1189,1224,1255,1285,1315,1347,1381,1417,1453,1486,1514,1533,1542,1541,1530,1514,1494,1473,1454,1439,
+1427,1419,1416,1418,1426,1442,1468,1506,1557,1619,1692,1772,1854,1933,2005,2066,2114,2149,2174,2190,2201,
+2210,2217,2223,2228,2231,2232,2233,2234,2238,2247,2260,2275,2289,2298,2298,2285,2262,2229,2193,2156,2124,
+2099,2078,2062,2047,2032,2018,2008,2003,2007,2016,2028,2038,2039,2029,2009,1984,1963,1954,1963,1990,2033,
+2085,2137,2182,2217,2241,2257,2267,2275,2280,2281,2276,2266,2250,2231,2212,2194,2179,2163,2142,2114,2076,
+2030,1982,1937,1899,1874,1861,1858,1864,1875,1889,1906,1924,1944,1964,1983,1998,2008,2014,2016,2019,2024,
+2031,2038,2043,2040,2028,2007,1982,1958,1940,1932,1935,1944,1955,1962,1962,1956,1947,1939,1936,1940,1949,
+1960,1968,1970,1964,1952,1938,1924,1914,1907,1903,1900,1895,1888,1879,1869,1861,1855,1851,1848,1844,1837,
+1828,1818,1808,1800,1793,1788,1783,1777,1767,1753,1736,1717,1697,1679,1664,1654,1646,1643,1641,1639,1636,
+1630,1619,1603,1582,1557,1531,1506,1484,1465,1451,1441,1431,1422,1413,1404,1397,1391,1388,1386,1385,1382,
+1375,1365,1352,1337,1323,1312,1305,1301,1300,1299,1298,1295,1292,1289,1289,1292,1299,1309,1320,1328,1333,
+1333,1326,1316,1304,1292,1284,1281,1284,1291,1300,1309,1315,1317,1313,1306,1297,1288,1281,1277,1276,1277,
+1278,1278,1276,1274,1273,1273,1275,1280,1287,1294,1301,1305,1308,1310,1311,1315,1321,1330,1342,1356,1370,
+1360,1373,1384,1394,1404,1415,1426,1438,1450,1463,1476,1489,1503,1519,1536,1555,1575,1597,1621,1647,1674,
+1702,1729,1754,1778,1800,1820,1840,1860,1879,1899,1918,1935,1949,1960,1969,1978,1990,2006,2028,2054,2084,
+2115,2144,2171,2195,2215,2232,2248,2261,2273,2283,2292,2300,2308,2316,2325,2334,2343,2349,2352,2352,2349,
+2345,2341,2338,2338,2339,2343,2347,2352,2357,2363,2370,2376,2381,2382,2378,2368,2355,2340,2327,2319,2318,
+2324,2337,2353,2370,2384,2394,2399,2399,2395,2389,2382,2375,2370,2366,2366,2367,2371,2377,2384,2391,2398,
+2405,2412,2420,2430,2440,2452,2465,2477,2489,2500,2510,2521,2533,2545,2558,2571,2583,2592,2599,2603,2603,
+2602,2599,2596,2595,2595,2600,2610,2624,2644,2666,2690,2715,2737,2758,2777,2794,2812,2830,2849,2869,2888,
+2906,2922,2938,2954,2970,2988,3008,3029,3049,3067,3083,3096,3108,3118,3127,3137,3147,3157,3166,3172,3177,
+3179,3179,3178,3176,3173,3170,3167,3163,3158,3153,3149,3144,3139,3135,3130,3126,3122,3119,3116,3115,3114,
+3114,3113,3112,3108,3102,3093,3083,3071,3061,3052,3046,3042,3040,3037,3033,3028,3021,3014,3008,3004,3003,
+3005,3007,3010,3012,3014,3017,3023,3031,3042,3054,3067,3078,3086,3090,3093,3095,3096,3099,3101,3102,3101,
+3097,3090,3082,3075,3069,3066,3065,3063,3059,3053,3044,3035,3025,3017,3011,3007,3004,2999,2994,2986,2976,
+2966,2955,2944,2931,2917,2900,2881,2860,2840,2821,2805,2792,2782,2775,2770,2766,2762,2758,2753,2746,2738,
+2729,2718,2708,2697,2686,2676,2666,2655,2642,2627,2613,2598,2585,2574,2563,2553,2541,2528,2512,2495,2479,
+2466,2456,2448,2442,2434,2423,2406,2385,2360,2334,2308,2282,2258,2234,2210,2185,2161,2138,2118,2101,2088,
+2078,2071,2066,2062,2059,2058,2058,2058,2056,2051,2039,2021,1995,1964,1929,1894,1859,1825,1791,1756,1718,
+1675,1629,1580,1529,1479,1432,1387,1346,1307,1270,1234,1200,1166,1134,1101,1068,1034,999,961,922,882,
+843,805,768,732,697,660,623,582,539,494,447,399,351,304,258,214,174,139,107,79,53,
+27,0,-30,-63,-96,-127,-154,-177,-195,-210,-225,-242,-263,-289,-321,-358,-397,-438,-479,-520,-560,
+-598,-633,-665,-694,-721,-745,-769,-792,-814,-834,-853,-868,-881,-891,-901,-912,-924,-940,-957,-977,-999,
+-1024,-1052,-1085,-1123,-1166,-1212,-1258,-1300,-1336,-1364,-1385,-1401,-1415,-1431,-1450,-1475,-1505,-1539,-1575,-1613,-1652,
+-1690,-1728,-1766,-1805,-1843,-1881,-1920,-1958,-1997,-2035,-2073,-2109,-2144,-2176,-2206,-2234,-2261,-2286,-2310,-2334,-2358,
+-2383,-2408,-2434,-2461,-2489,-2518,-2548,-2578,-2607,-2636,-2663,-2689,-2715,-2740,-2765,-2790,-2815,-2840,-2864,-2888,-2911,
+-2934,-2955,-2976,-2996,-3016,-3036,-3056,-3077,-3100,-3124,-3148,-3173,-3197,-3218,-3236,-3251,-3262,-3270,-3276,-3282,-3289,
+-3300,-3314,-3333,-3356,-3380,-3403,-3424,-3442,-3455,-3465,-3474,-3483,-3494,-3508,-3524,-3542,-3561,-3579,-3597,-3612,-3626,
+-3638,-3649,-3659,-3668,-3677,-3686,-3696,-3707,-3720,-3734,-3748,-3760,-3770,-3776,-3780,-3783,-3786,-3791,-3800,-3812,-3828,
+-3846,-3864,-3882,-3899,-3915,-3933,-3951,-3969,-3987,-4004,-4017,-4024,-4024,-4014,-3996,-3971,-3940,-3908,-3877,-3850,-3829,
+-3815,-3805,-3799,-3795,-3789,-3782,-3773,-3764,-3756,-3751,-3747,-3747,-3747,-3748,-3748,-3747,-3744,-3740,-3736,-3733,-3729,
+-3724,-3718,-3711,-3702,-3693,-3685,-3680,-3678,-3679,-3681,-3682,-3682,-3678,-3671,-3660,-3647,-3630,-3611,-3591,-3568,-3544,
+-3521,-3500,-3484,-3476,-3477,-3486,-3503,-3524,-3547,-3566,-3579,-3585,-3582,-3573,-3560,-3547,-3536,-3531,-3532,-3539,-3551,
+-3566,-3583,-3598,-3611,-3623,-3635,-3648,-3663,-3681,-3700,-3719,-3738,-3755,-3771,-3786,-3800,-3816,-3834,-3854,-3875,-3897,
+-3918,-3936,-3953,-3967,-3980,-3991,-4002,-4014,-4027,-4042,-4059,-4080,-4103,-4129,-4154,-4178,-4199,-4216,-4230,-4243,-4256,
+-4274,-4299,-4331,-4371,-4416,-4466,-4516,-4564,-4610,-4653,-4692,-4728,-4760,-4789,-4813,-4833,-4847,-4856,-4861,-4862,-4862,
+-4863,-4866,-4873,-4882,-4892,-4901,-4908,-4911,-4909,-4905,-4900,-4898,-4900,-4908,-4920,-4935,-4949,-4959,-4963,-4961,-4953,
+-4943,-4931,-4921,-4914,-4910,-4908,-4908,-4908,-4907,-4906,-4903,-4899,-4894,-4889,-4883,-4876,-4868,-4860,-4852,-4844,-4837,
+-4830,-4823,-4816,-4808,-4800,-4790,-4779,-4767,-4753,-4739,-4724,-4709,-4694,-4681,-4668,-4657,-4645,-4634,-4622,-4609,-4596,
+-4583,-4571,-4561,-4551,-4541,-4531,-4520,-4509,-4497,-4486,-4477,-4470,-4463,-4456,-4448,-4437,-4425,-4412,-4398,-4385,-4373,
+-4362,-4351,-4340,-4327,-4314,-4302,-4290,-4280,-4272,-4264,-4256,-4247,-4236,-4223,-4210,-4199,-4189,-4183,-4178,-4174,-4168,
+-4161,-4152,-4140,-4127,-4114,-4100,-4087,-4074,-4062,-4050,-4040,-4030,-4021,-4013,-4004,-3994,-3983,-3971,-3959,-3948,-3938,
+-3929,-3921,-3914,-3906,-3897,-3887,-3877,-3867,-3859,-3852,-3846,-3841,-3836,-3832,-3826,-3820,-3813,-3806,-3798,-3790,-3780,
+-3770,-3760,-3752,-3745,-3740,-3737,-3736,-3734,-3731,-3727,-3722,-3716,-3712,-3709,-3707,-3706,-3704,-3702,-3698,-3693,-3687,
+-3681,-3675,-3669,-3664,-3658,-3652,-3645,-3638,-3632,-3628,-3625,-3622,-3619,-3615,-3611,-3605,-3599,-3593,-3590,-3587,-3585,
+-3583,-3580,-3574,-3565,-3555,-3544,-3533,-3523,-3516,-3509,-3504,-3499,-3494,-3488,-3483,-3477,-3470,-3463,-3456,-3447,-3437,
+-3425,-3413,-3401,-3389,-3378,-3368,-3358,-3350,-3342,-3335,-3327,-3319,-3310,-3299,-3288,-3276,-3264,-3253,-3243,-3236,-3230,
+-3225,-3220,-3214,-3206,-3197,-3185,-3174,-3162,-3152,-3143,-3135,-3127,-3119,-3110,-3100,-3089,-3078,-3067,-3056,-3045,-3033,
+-3021,-3007,-2992,-2976,-2961,-2948,-2938,-2931,-2928,-2926,-2924,-2919,-2911,-2897,-2879,-2858,-2835,-2813,-2793,-2776,-2763,
+-2753,-2745,-2737,-2730,-2723,-2714,-2704,-2694,-2682,-2671,-2660,-2649,-2640,-2631,-2624,-2619,-2613,-2608,-2603,-2598,-2593,
+-2588,-2584,-2579,-2574,-2568,-2562,-2555,-2548,-2541,-2534,-2527,-2520,-2513,-2505,-2496,-2485,-2474,-2461,-2449,-2436,-2424,
+-2411,-2399,-2387,-2374,-2361,-2348,-2335,-2321,-2307,-2294,-2281,-2268,-2256,-2243,-2231,-2219,-2206,-2193,-2180,-2167,-2156,
+-2146,-2138,-2131,-2124,-2117,-2107,-2095,-2081,-2065,-2048,-2032,-2017,-2004,-1991,-1979,-1966,-1952,-1935,-1915,-1894,-1871,
+-1847,-1823,-1799,-1777,-1755,-1736,-1718,-1701,-1687,-1673,-1659,-1645,-1630,-1614,-1598,-1581,-1565,-1548,-1533,-1517,-1503,
+-1488,-1474,-1458,-1441,-1423,-1402,-1380,-1355,-1330,-1305,-1281,-1260,-1242,-1227,-1215,-1205,-1195,-1185,-1174,-1163,-1149,
+-1135,-1119,-1102,-1084,-1066,-1047,-1028,-1009,-989,-969,-947,-925,-901,-877,-852,-826,-800,-773,-746,-717,-686,
+-656,-625,-595,-567,-539,-513,-486,-460,-433,-405,-378,-350,-322,-293,-261,-226,-188,-146,-103,-60,-18,
+19,55,89,122,155,188,222,255,287,316,342,367,391,416,442,469,497,527,556,587,618,
+651,685,720,756,791,826,861,896,931,969,1009,1050,1092,1133,1171,1206,1239,1271,1303,1338,1375,
+1413,1449,1479,1499,1505,1497,1475,1443,1405,1367,1335,1313,1304,1310,1330,1364,1408,1462,1523,1591,1664,
+1741,1820,1900,1977,2046,2104,2149,2179,2197,2205,2208,2210,2215,2225,2239,2255,2271,2283,2292,2297,2300,
+2303,2306,2311,2313,2310,2297,2273,2238,2193,2145,2100,2064,2040,2027,2024,2025,2026,2024,2019,2013,2009,
+2009,2014,2022,2029,2031,2025,2011,1992,1974,1962,1961,1972,1993,2020,2049,2074,2095,2111,2125,2139,2152,
+2164,2174,2178,2176,2167,2152,2134,2114,2093,2070,2043,2011,1975,1936,1898,1865,1841,1828,1825,1829,1839,
+1852,1867,1883,1900,1916,1931,1942,1947,1945,1936,1922,1907,1895,1886,1882,1879,1878,1874,1870,1866,1865,
+1870,1880,1895,1910,1920,1922,1915,1901,1885,1871,1864,1865,1871,1880,1887,1888,1882,1871,1857,1845,1835,
+1830,1828,1826,1822,1815,1806,1795,1783,1773,1765,1760,1755,1752,1748,1745,1741,1736,1731,1724,1714,1700,
+1683,1663,1641,1619,1600,1584,1572,1564,1561,1559,1560,1561,1560,1556,1548,1535,1517,1494,1469,1443,1419,
+1396,1376,1359,1343,1328,1315,1304,1295,1291,1289,1290,1291,1292,1289,1284,1277,1271,1267,1267,1271,1277,
+1282,1284,1280,1270,1255,1238,1224,1215,1213,1219,1231,1245,1258,1268,1271,1268,1261,1251,1243,1238,1237,
+1241,1247,1255,1261,1264,1265,1263,1260,1257,1256,1255,1255,1254,1252,1248,1244,1239,1237,1238,1242,1250,
+1259,1267,1274,1278,1281,1284,1288,1295,1305,1317,1332,1346,1360,1355,1366,1377,1388,1401,1415,1429,1443,
+1456,1468,1480,1492,1506,1522,1541,1563,1586,1610,1635,1660,1685,1711,1736,1759,1780,1800,1817,1833,1848,
+1864,1880,1897,1913,1929,1943,1956,1970,1986,2005,2027,2052,2078,2103,2125,2144,2159,2173,2185,2198,2211,
+2225,2238,2250,2261,2270,2278,2286,2293,2299,2303,2305,2305,2303,2300,2298,2297,2299,2303,2310,2317,2324,
+2331,2335,2338,2337,2333,2326,2316,2303,2290,2279,2273,2273,2281,2294,2310,2326,2340,2349,2353,2352,2348,
+2342,2336,2331,2327,2325,2323,2322,2323,2325,2329,2336,2345,2355,2366,2377,2387,2396,2405,2413,2421,2430,
+2439,2449,2460,2473,2487,2502,2517,2531,2543,2552,2558,2561,2560,2556,2551,2546,2543,2544,2551,2564,2583,
+2607,2634,2662,2689,2712,2732,2749,2765,2780,2796,2814,2833,2851,2869,2886,2902,2918,2934,2952,2972,2993,
+3013,3032,3047,3060,3069,3077,3084,3092,3101,3111,3122,3132,3140,3146,3149,3149,3146,3143,3138,3134,3130,
+3126,3124,3122,3120,3119,3117,3115,3112,3109,3105,3101,3098,3094,3092,3089,3085,3079,3072,3062,3050,3038,
+3028,3019,3013,3009,3007,3005,3002,2997,2991,2985,2981,2978,2977,2979,2981,2983,2984,2985,2987,2991,2998,
+3009,3022,3036,3049,3060,3067,3072,3077,3081,3085,3089,3092,3092,3090,3085,3078,3071,3065,3060,3057,3054,
+3050,3044,3037,3028,3019,3010,3003,2997,2991,2986,2981,2975,2968,2960,2952,2942,2930,2915,2898,2879,2858,
+2837,2817,2799,2783,2769,2757,2747,2739,2732,2725,2718,2710,2701,2690,2679,2666,2655,2643,2633,2623,2613,
+2601,2589,2577,2564,2553,2543,2535,2526,2516,2505,2492,2478,2466,2455,2446,2439,2432,2422,2409,2390,2366,
+2341,2314,2288,2263,2240,2217,2192,2166,2139,2112,2086,2063,2043,2026,2012,2000,1989,1981,1975,1971,1970,
+1969,1966,1960,1948,1929,1904,1874,1843,1812,1783,1755,1727,1697,1664,1627,1586,1542,1496,1449,1403,1359,
+1315,1274,1234,1195,1158,1122,1086,1051,1015,978,939,900,861,822,785,749,715,680,645,608,570,
+530,488,445,401,358,316,276,240,206,177,149,123,95,63,28,-10,-50,-89,-125,-153,-175,
+-192,-206,-222,-241,-266,-297,-333,-371,-411,-450,-488,-526,-565,-603,-641,-678,-714,-747,-777,-805,-831,
+-854,-875,-893,-907,-918,-927,-936,-945,-957,-972,-991,-1012,-1037,-1063,-1092,-1122,-1156,-1192,-1230,-1268,-1305,
+-1338,-1367,-1391,-1412,-1431,-1451,-1474,-1500,-1531,-1565,-1604,-1644,-1686,-1729,-1771,-1813,-1854,-1893,-1932,-1969,-2005,
+-2041,-2076,-2111,-2144,-2176,-2206,-2234,-2259,-2284,-2307,-2329,-2352,-2374,-2397,-2421,-2446,-2474,-2503,-2534,-2566,-2599,
+-2631,-2661,-2689,-2714,-2738,-2760,-2782,-2804,-2827,-2851,-2875,-2900,-2926,-2951,-2977,-3001,-3025,-3048,-3069,-3090,-3110,
+-3131,-3151,-3172,-3193,-3215,-3236,-3255,-3272,-3286,-3296,-3304,-3310,-3316,-3325,-3336,-3352,-3372,-3393,-3415,-3436,-3454,
+-3469,-3482,-3494,-3508,-3523,-3542,-3562,-3585,-3607,-3629,-3648,-3665,-3680,-3692,-3702,-3711,-3720,-3730,-3742,-3757,-3775,
+-3796,-3819,-3839,-3856,-3868,-3872,-3871,-3867,-3863,-3863,-3869,-3881,-3900,-3923,-3947,-3971,-3992,-4010,-4026,-4041,-4054,
+-4067,-4078,-4085,-4088,-4085,-4074,-4056,-4033,-4006,-3977,-3950,-3926,-3906,-3892,-3882,-3875,-3869,-3863,-3855,-3846,-3836,
+-3827,-3820,-3815,-3813,-3813,-3814,-3816,-3816,-3816,-3815,-3813,-3810,-3806,-3801,-3795,-3788,-3779,-3771,-3763,-3757,-3753,
+-3752,-3752,-3752,-3752,-3749,-3745,-3737,-3727,-3715,-3699,-3681,-3660,-3637,-3612,-3588,-3567,-3551,-3543,-3545,-3555,-3574,
+-3596,-3620,-3640,-3652,-3656,-3651,-3637,-3620,-3603,-3591,-3585,-3589,-3600,-3617,-3636,-3655,-3673,-3687,-3700,-3713,-3726,
+-3742,-3760,-3780,-3801,-3821,-3839,-3855,-3871,-3887,-3903,-3921,-3939,-3958,-3977,-3995,-4012,-4027,-4042,-4055,-4068,-4081,
+-4093,-4106,-4119,-4135,-4152,-4171,-4192,-4213,-4232,-4249,-4262,-4273,-4283,-4294,-4307,-4325,-4349,-4379,-4413,-4450,-4490,
+-4529,-4569,-4609,-4649,-4690,-4731,-4771,-4809,-4842,-4869,-4889,-4900,-4905,-4906,-4905,-4907,-4912,-4920,-4931,-4941,-4949,
+-4951,-4948,-4941,-4932,-4924,-4921,-4923,-4930,-4940,-4951,-4959,-4964,-4965,-4962,-4956,-4949,-4943,-4938,-4934,-4931,-4929,
+-4926,-4922,-4917,-4912,-4905,-4898,-4891,-4884,-4878,-4872,-4867,-4863,-4858,-4854,-4849,-4843,-4836,-4828,-4819,-4809,-4798,
+-4786,-4773,-4759,-4745,-4730,-4716,-4703,-4690,-4678,-4665,-4653,-4642,-4630,-4620,-4610,-4601,-4592,-4582,-4571,-4559,-4546,
+-4533,-4521,-4511,-4503,-4495,-4488,-4480,-4470,-4459,-4446,-4434,-4423,-4413,-4404,-4395,-4385,-4374,-4361,-4348,-4334,-4322,
+-4310,-4301,-4292,-4284,-4276,-4267,-4259,-4250,-4243,-4235,-4227,-4220,-4211,-4203,-4194,-4186,-4177,-4168,-4159,-4148,-4135,
+-4121,-4107,-4092,-4080,-4069,-4060,-4052,-4044,-4036,-4027,-4017,-4008,-3999,-3992,-3986,-3980,-3974,-3967,-3959,-3950,-3941,
+-3932,-3924,-3917,-3910,-3903,-3895,-3888,-3881,-3874,-3867,-3861,-3854,-3847,-3839,-3830,-3821,-3814,-3809,-3806,-3804,-3802,
+-3799,-3794,-3789,-3782,-3776,-3771,-3767,-3765,-3764,-3762,-3759,-3755,-3749,-3743,-3737,-3730,-3724,-3717,-3710,-3703,-3696,
+-3689,-3684,-3679,-3676,-3672,-3668,-3663,-3658,-3652,-3647,-3643,-3641,-3638,-3636,-3632,-3627,-3620,-3612,-3603,-3594,-3587,
+-3581,-3576,-3571,-3566,-3561,-3555,-3549,-3543,-3536,-3530,-3522,-3513,-3502,-3490,-3477,-3465,-3453,-3444,-3435,-3428,-3422,
+-3415,-3407,-3398,-3387,-3376,-3365,-3353,-3341,-3330,-3320,-3311,-3302,-3295,-3288,-3281,-3273,-3264,-3255,-3245,-3234,-3224,
+-3214,-3204,-3195,-3185,-3175,-3164,-3152,-3141,-3129,-3118,-3107,-3096,-3084,-3070,-3054,-3036,-3017,-2997,-2979,-2964,-2953,
+-2947,-2943,-2942,-2941,-2937,-2931,-2920,-2906,-2890,-2871,-2853,-2836,-2820,-2805,-2792,-2780,-2770,-2759,-2749,-2739,-2728,
+-2717,-2707,-2696,-2686,-2678,-2670,-2662,-2656,-2650,-2643,-2637,-2631,-2625,-2619,-2613,-2606,-2599,-2591,-2583,-2574,-2566,
+-2558,-2551,-2544,-2537,-2529,-2520,-2510,-2500,-2489,-2479,-2469,-2460,-2451,-2441,-2430,-2417,-2403,-2388,-2373,-2358,-2345,
+-2332,-2319,-2307,-2296,-2284,-2272,-2259,-2247,-2235,-2223,-2212,-2201,-2191,-2181,-2172,-2163,-2153,-2143,-2131,-2118,-2103,
+-2088,-2072,-2057,-2042,-2028,-2013,-1998,-1982,-1965,-1947,-1928,-1909,-1889,-1869,-1849,-1828,-1806,-1784,-1762,-1741,-1722,
+-1706,-1692,-1680,-1668,-1657,-1644,-1629,-1612,-1594,-1575,-1557,-1539,-1523,-1507,-1492,-1476,-1459,-1439,-1418,-1394,-1369,
+-1343,-1318,-1295,-1274,-1255,-1239,-1224,-1211,-1199,-1187,-1176,-1166,-1155,-1145,-1133,-1119,-1103,-1085,-1065,-1044,-1023,
+-1003,-983,-963,-942,-921,-898,-872,-844,-815,-784,-752,-720,-688,-657,-626,-597,-569,-541,-515,-489,-464,
+-439,-415,-391,-365,-338,-308,-274,-236,-194,-151,-106,-62,-21,17,53,86,119,151,183,214,244,
+273,301,329,356,384,412,439,466,491,515,539,563,590,621,655,691,729,767,803,837,871,
+904,940,978,1018,1059,1100,1140,1178,1214,1250,1286,1324,1363,1402,1435,1460,1473,1471,1455,1425,1387,
+1346,1310,1284,1273,1281,1308,1354,1415,1489,1570,1654,1738,1819,1895,1963,2024,2076,2118,2149,2169,2181,
+2185,2187,2188,2194,2207,2227,2253,2282,2311,2336,2355,2368,2375,2377,2374,2368,2355,2335,2305,2264,2216,
+2163,2112,2068,2036,2019,2014,2019,2028,2034,2036,2031,2022,2011,2002,1997,1996,1998,1999,1997,1992,1984,
+1975,1968,1964,1964,1967,1973,1978,1983,1988,1993,2000,2010,2021,2033,2042,2046,2045,2039,2029,2019,2008,
+1997,1985,1969,1947,1921,1892,1863,1839,1823,1817,1819,1829,1841,1855,1867,1878,1886,1891,1893,1891,1884,
+1870,1852,1830,1808,1788,1774,1767,1765,1768,1775,1784,1795,1808,1823,1838,1852,1863,1867,1864,1855,1842,
+1828,1817,1812,1811,1814,1817,1818,1816,1809,1801,1792,1785,1782,1781,1781,1780,1775,1766,1753,1738,1722,
+1707,1694,1684,1675,1668,1662,1656,1650,1643,1635,1624,1610,1593,1575,1557,1539,1524,1513,1504,1498,1493,
+1488,1483,1479,1475,1471,1468,1464,1458,1450,1437,1420,1400,1376,1351,1324,1298,1274,1252,1234,1220,1212,
+1209,1210,1213,1216,1217,1216,1212,1207,1204,1205,1211,1221,1232,1242,1246,1242,1230,1211,1188,1167,1150,
+1142,1143,1153,1167,1184,1199,1210,1214,1214,1210,1205,1200,1199,1200,1203,1207,1211,1214,1215,1216,1217,
+1218,1220,1223,1224,1225,1223,1219,1214,1210,1208,1210,1215,1223,1232,1241,1248,1253,1259,1265,1273,1284,
+1298,1313,1328,1342,1355,1354,1365,1376,1387,1400,1415,1429,1443,1455,1466,1477,1489,1505,1523,1545,1568,
+1593,1617,1641,1663,1684,1704,1723,1742,1759,1774,1788,1801,1814,1827,1843,1861,1880,1900,1919,1938,1956,
+1974,1992,2012,2032,2052,2071,2088,2103,2117,2129,2142,2156,2170,2185,2198,2210,2219,2226,2233,2238,2244,
+2249,2253,2256,2257,2256,2255,2254,2255,2259,2265,2274,2282,2289,2292,2292,2289,2282,2272,2261,2249,2239,
+2231,2227,2229,2236,2247,2261,2276,2288,2296,2299,2299,2296,2292,2290,2288,2288,2289,2289,2289,2287,2286,
+2286,2290,2296,2307,2319,2333,2346,2357,2367,2374,2380,2385,2392,2399,2409,2419,2432,2445,2459,2473,2486,
+2497,2506,2511,2513,2511,2506,2500,2494,2491,2494,2503,2519,2541,2568,2597,2626,2653,2676,2696,2713,2729,
+2745,2761,2779,2798,2817,2834,2850,2865,2879,2893,2909,2927,2946,2965,2984,3001,3015,3026,3035,3043,3050,
+3059,3069,3079,3089,3099,3106,3110,3112,3110,3107,3102,3098,3093,3090,3088,3088,3088,3090,3092,3094,3095,
+3096,3095,3093,3090,3085,3078,3070,3060,3049,3035,3021,3007,2994,2983,2975,2970,2967,2966,2966,2965,2962,
+2959,2956,2953,2951,2949,2949,2948,2948,2947,2946,2948,2952,2960,2971,2985,2999,3014,3026,3035,3043,3049,
+3055,3061,3067,3072,3075,3075,3074,3070,3065,3060,3056,3051,3047,3042,3036,3029,3020,3010,3001,2991,2983,
+2976,2969,2964,2958,2952,2946,2937,2926,2912,2896,2879,2860,2841,2823,2806,2790,2774,2759,2745,2731,2718,
+2706,2695,2686,2676,2667,2657,2646,2635,2624,2613,2603,2593,2583,2571,2558,2545,2532,2521,2511,2503,2496,
+2489,2481,2473,2463,2453,2445,2437,2430,2422,2411,2396,2377,2354,2329,2303,2279,2257,2236,2216,2194,2170,
+2144,2116,2087,2059,2032,2007,1983,1960,1938,1918,1901,1887,1878,1873,1870,1867,1861,1851,1835,1815,1791,
+1766,1740,1713,1686,1658,1626,1592,1554,1513,1471,1428,1386,1344,1305,1266,1228,1190,1153,1114,1076,1036,
+995,955,914,875,837,801,766,734,701,669,636,601,565,528,490,451,413,376,340,307,276,
+249,223,197,169,137,100,57,12,-33,-74,-109,-135,-153,-166,-179,-196,-220,-251,-288,-329,-371,
+-411,-448,-484,-518,-553,-590,-628,-667,-705,-741,-774,-804,-832,-858,-881,-902,-920,-936,-949,-960,-973,
+-988,-1006,-1029,-1056,-1085,-1115,-1144,-1173,-1200,-1227,-1254,-1281,-1309,-1337,-1365,-1393,-1419,-1446,-1473,-1501,-1532,
+-1566,-1602,-1642,-1685,-1729,-1774,-1818,-1861,-1902,-1941,-1977,-2011,-2044,-2076,-2108,-2139,-2169,-2198,-2225,-2249,-2272,
+-2293,-2313,-2332,-2351,-2372,-2394,-2417,-2443,-2470,-2500,-2531,-2564,-2596,-2628,-2659,-2687,-2713,-2738,-2762,-2785,-2809,
+-2833,-2857,-2883,-2909,-2936,-2964,-2992,-3021,-3049,-3077,-3102,-3126,-3146,-3164,-3180,-3195,-3210,-3225,-3242,-3259,-3276,
+-3292,-3306,-3317,-3326,-3334,-3342,-3353,-3367,-3384,-3404,-3426,-3448,-3469,-3488,-3506,-3524,-3543,-3564,-3588,-3612,-3638,
+-3663,-3687,-3708,-3727,-3742,-3755,-3766,-3775,-3785,-3797,-3811,-3830,-3854,-3880,-3908,-3934,-3955,-3968,-3973,-3970,-3963,
+-3955,-3951,-3952,-3961,-3976,-3997,-4019,-4040,-4059,-4075,-4086,-4095,-4102,-4106,-4109,-4109,-4107,-4101,-4093,-4082,-4069,
+-4054,-4039,-4024,-4009,-3994,-3981,-3968,-3957,-3946,-3937,-3928,-3919,-3911,-3903,-3896,-3891,-3886,-3884,-3882,-3882,-3883,
+-3884,-3884,-3884,-3882,-3879,-3874,-3868,-3860,-3852,-3844,-3837,-3832,-3828,-3825,-3823,-3821,-3819,-3816,-3811,-3806,-3800,
+-3792,-3783,-3771,-3757,-3740,-3719,-3697,-3674,-3654,-3639,-3632,-3633,-3643,-3660,-3681,-3702,-3718,-3727,-3726,-3717,-3701,
+-3683,-3667,-3657,-3656,-3663,-3677,-3695,-3715,-3733,-3749,-3762,-3774,-3786,-3800,-3817,-3836,-3856,-3876,-3896,-3914,-3932,
+-3948,-3964,-3980,-3997,-4013,-4029,-4045,-4062,-4078,-4096,-4114,-4132,-4150,-4166,-4181,-4195,-4207,-4218,-4229,-4240,-4253,
+-4266,-4280,-4294,-4308,-4322,-4336,-4350,-4365,-4381,-4399,-4418,-4438,-4460,-4484,-4510,-4539,-4571,-4608,-4649,-4694,-4741,
+-4787,-4828,-4863,-4887,-4902,-4909,-4910,-4911,-4913,-4921,-4933,-4948,-4965,-4978,-4985,-4986,-4981,-4972,-4962,-4953,-4949,
+-4948,-4952,-4958,-4964,-4969,-4972,-4972,-4971,-4968,-4964,-4960,-4955,-4951,-4946,-4941,-4934,-4927,-4919,-4910,-4902,-4894,
+-4888,-4883,-4879,-4876,-4873,-4870,-4867,-4862,-4856,-4850,-4843,-4836,-4828,-4819,-4809,-4798,-4785,-4772,-4758,-4743,-4729,
+-4714,-4700,-4687,-4675,-4664,-4655,-4647,-4639,-4631,-4621,-4610,-4598,-4585,-4572,-4560,-4550,-4542,-4535,-4527,-4518,-4508,
+-4495,-4482,-4470,-4458,-4448,-4440,-4432,-4424,-4414,-4403,-4390,-4376,-4363,-4351,-4341,-4333,-4327,-4322,-4318,-4313,-4307,
+-4301,-4292,-4282,-4271,-4260,-4250,-4242,-4236,-4232,-4227,-4221,-4213,-4201,-4186,-4170,-4153,-4138,-4126,-4117,-4110,-4104,
+-4098,-4091,-4083,-4075,-4066,-4058,-4051,-4045,-4038,-4032,-4025,-4018,-4011,-4004,-3997,-3990,-3981,-3971,-3960,-3949,-3938,
+-3929,-3923,-3918,-3915,-3912,-3908,-3903,-3898,-3892,-3887,-3882,-3878,-3874,-3869,-3864,-3857,-3849,-3841,-3835,-3829,-3825,
+-3822,-3819,-3815,-3809,-3803,-3795,-3788,-3779,-3772,-3765,-3758,-3752,-3746,-3741,-3737,-3734,-3730,-3727,-3723,-3719,-3714,
+-3709,-3705,-3702,-3699,-3696,-3693,-3689,-3683,-3676,-3668,-3661,-3653,-3647,-3640,-3635,-3629,-3623,-3617,-3611,-3606,-3601,
+-3596,-3591,-3584,-3576,-3564,-3551,-3538,-3524,-3513,-3503,-3496,-3489,-3483,-3476,-3467,-3457,-3446,-3436,-3425,-3416,-3408,
+-3400,-3391,-3382,-3370,-3358,-3345,-3332,-3320,-3309,-3300,-3291,-3283,-3275,-3266,-3256,-3246,-3234,-3222,-3209,-3196,-3183,
+-3170,-3159,-3148,-3136,-3125,-3112,-3097,-3080,-3062,-3042,-3022,-3003,-2987,-2974,-2965,-2959,-2955,-2953,-2950,-2947,-2941,
+-2933,-2921,-2908,-2893,-2876,-2859,-2843,-2827,-2812,-2799,-2786,-2775,-2764,-2754,-2745,-2736,-2728,-2720,-2713,-2706,-2699,
+-2692,-2685,-2677,-2669,-2662,-2653,-2645,-2635,-2625,-2615,-2605,-2595,-2586,-2579,-2572,-2566,-2559,-2551,-2542,-2532,-2521,
+-2511,-2502,-2493,-2484,-2475,-2465,-2452,-2438,-2422,-2406,-2390,-2376,-2364,-2353,-2342,-2331,-2320,-2308,-2296,-2284,-2272,
+-2261,-2252,-2242,-2233,-2223,-2212,-2200,-2187,-2174,-2162,-2149,-2137,-2125,-2113,-2101,-2088,-2073,-2057,-2039,-2020,-2001,
+-1980,-1961,-1943,-1927,-1911,-1896,-1880,-1862,-1841,-1819,-1796,-1773,-1752,-1734,-1720,-1707,-1696,-1685,-1671,-1654,-1635,
+-1614,-1592,-1572,-1553,-1537,-1522,-1507,-1491,-1474,-1453,-1429,-1403,-1376,-1350,-1326,-1305,-1287,-1271,-1256,-1242,-1227,
+-1213,-1199,-1186,-1175,-1164,-1154,-1144,-1132,-1118,-1101,-1083,-1063,-1043,-1023,-1003,-984,-963,-941,-916,-887,-856,
+-823,-790,-756,-724,-694,-665,-638,-611,-583,-556,-529,-502,-476,-451,-428,-404,-379,-353,-323,-289,-251,
+-210,-168,-125,-83,-42,-3,34,71,107,141,173,203,231,257,282,308,334,362,391,420,447,
+472,496,518,542,568,598,633,670,709,746,781,813,844,874,906,941,979,1019,1061,1103,1144,
+1184,1223,1262,1302,1341,1377,1407,1430,1442,1443,1434,1417,1396,1375,1360,1353,1358,1379,1415,1466,1530,
+1605,1685,1766,1843,1912,1972,2020,2057,2086,2108,2126,2141,2155,2170,2186,2203,2224,2247,2273,2300,2328,
+2354,2376,2393,2403,2406,2402,2392,2376,2354,2327,2293,2255,2214,2172,2134,2102,2078,2062,2054,2051,2050,
+2047,2040,2030,2017,2003,1990,1979,1971,1965,1960,1956,1951,1947,1943,1941,1939,1938,1936,1932,1928,1923,
+1920,1920,1923,1929,1937,1943,1945,1943,1935,1925,1914,1907,1904,1904,1904,1903,1896,1882,1863,1842,1823,
+1810,1806,1810,1822,1838,1853,1864,1870,1870,1865,1855,1841,1825,1807,1789,1771,1756,1744,1737,1735,1737,
+1743,1751,1759,1768,1775,1781,1785,1787,1786,1782,1776,1770,1763,1759,1757,1757,1758,1758,1757,1753,1748,
+1742,1738,1735,1736,1738,1740,1740,1736,1728,1717,1702,1687,1672,1657,1644,1631,1619,1606,1593,1580,1567,
+1555,1542,1529,1515,1501,1487,1474,1463,1456,1450,1446,1441,1434,1425,1413,1401,1390,1381,1375,1374,1374,
+1373,1371,1364,1352,1333,1310,1284,1256,1229,1206,1189,1177,1171,1171,1174,1178,1180,1179,1173,1165,1156,
+1149,1145,1147,1153,1161,1170,1175,1174,1167,1153,1136,1118,1103,1094,1093,1099,1111,1126,1143,1157,1168,
+1175,1178,1178,1178,1177,1177,1178,1178,1179,1179,1178,1178,1178,1180,1183,1186,1189,1191,1191,1189,1187,
+1185,1186,1189,1195,1203,1212,1220,1227,1234,1241,1251,1263,1278,1294,1312,1328,1342,1354,1350,1360,1371,
+1381,1394,1407,1420,1433,1446,1458,1471,1486,1503,1525,1549,1574,1600,1623,1645,1664,1682,1698,1713,1728,
+1742,1753,1764,1773,1782,1793,1806,1822,1842,1863,1884,1905,1925,1943,1960,1977,1994,2011,2028,2045,2062,
+2078,2094,2110,2125,2138,2151,2161,2169,2175,2180,2186,2192,2199,2206,2213,2217,2219,2219,2218,2218,2219,
+2223,2229,2235,2240,2242,2241,2235,2226,2215,2204,2194,2186,2180,2179,2181,2187,2195,2206,2217,2228,2236,
+2241,2243,2243,2243,2243,2244,2248,2252,2255,2257,2256,2254,2252,2252,2254,2261,2271,2284,2297,2309,2319,
+2327,2334,2339,2345,2352,2360,2370,2380,2392,2403,2414,2426,2437,2447,2456,2461,2464,2462,2458,2453,2448,
+2446,2450,2460,2476,2498,2524,2551,2578,2603,2626,2647,2667,2685,2704,2723,2743,2762,2780,2798,2813,2827,
+2839,2851,2864,2878,2893,2910,2927,2945,2962,2977,2991,3004,3015,3025,3035,3044,3053,3060,3066,3069,3070,
+3069,3066,3062,3058,3053,3049,3047,3046,3047,3049,3053,3059,3065,3071,3076,3079,3077,3072,3062,3048,3030,
+3011,2991,2971,2955,2941,2931,2924,2920,2919,2919,2920,2920,2920,2920,2919,2917,2915,2914,2912,2910,2909,
+2908,2909,2913,2919,2928,2940,2953,2966,2978,2989,2998,3006,3013,3020,3027,3034,3040,3045,3049,3051,3050,
+3049,3046,3043,3038,3033,3026,3018,3008,2998,2987,2976,2966,2957,2950,2944,2939,2935,2929,2922,2911,2897,
+2880,2861,2842,2823,2807,2793,2781,2770,2758,2745,2731,2716,2701,2687,2675,2664,2655,2647,2637,2627,2617,
+2606,2595,2584,2574,2562,2550,2536,2522,2508,2495,2484,2475,2468,2461,2455,2447,2438,2428,2419,2411,2404,
+2396,2387,2375,2359,2340,2318,2296,2274,2253,2234,2216,2197,2175,2151,2124,2095,2065,2034,2003,1971,1939,
+1907,1876,1847,1822,1802,1789,1781,1778,1776,1773,1767,1756,1740,1719,1695,1666,1634,1600,1563,1524,1483,
+1443,1404,1367,1332,1301,1271,1243,1214,1183,1150,1113,1074,1033,990,947,904,864,827,792,759,727,
+697,666,635,603,571,538,505,471,437,404,372,343,315,290,265,239,209,173,131,84,35,
+-11,-52,-84,-106,-119,-129,-140,-155,-179,-212,-251,-293,-336,-376,-412,-446,-479,-512,-547,-583,-620,
+-655,-690,-722,-754,-784,-815,-845,-874,-901,-924,-945,-963,-982,-1002,-1026,-1055,-1087,-1122,-1157,-1189,-1216,
+-1239,-1258,-1275,-1292,-1311,-1333,-1359,-1387,-1418,-1452,-1487,-1525,-1563,-1604,-1647,-1692,-1738,-1785,-1830,-1874,-1916,
+-1953,-1988,-2019,-2048,-2076,-2103,-2131,-2158,-2185,-2210,-2234,-2255,-2273,-2290,-2305,-2321,-2337,-2355,-2375,-2397,-2421,
+-2448,-2477,-2508,-2539,-2571,-2604,-2635,-2667,-2697,-2726,-2756,-2784,-2812,-2840,-2868,-2895,-2922,-2949,-2977,-3006,-3035,
+-3065,-3095,-3123,-3149,-3170,-3187,-3201,-3212,-3223,-3234,-3247,-3261,-3278,-3294,-3310,-3324,-3336,-3346,-3356,-3368,-3382,
+-3399,-3419,-3441,-3465,-3489,-3512,-3536,-3560,-3585,-3611,-3639,-3668,-3697,-3725,-3750,-3773,-3792,-3808,-3822,-3834,-3845,
+-3857,-3870,-3886,-3904,-3926,-3949,-3973,-3996,-4013,-4025,-4030,-4029,-4025,-4019,-4016,-4017,-4024,-4034,-4048,-4062,-4076,
+-4087,-4096,-4103,-4107,-4110,-4111,-4110,-4108,-4105,-4102,-4099,-4097,-4097,-4096,-4095,-4093,-4087,-4077,-4064,-4049,-4034,
+-4021,-4010,-4002,-3996,-3991,-3986,-3981,-3974,-3965,-3957,-3950,-3945,-3942,-3942,-3943,-3945,-3946,-3946,-3943,-3938,-3932,
+-3925,-3918,-3913,-3908,-3905,-3902,-3898,-3894,-3889,-3884,-3878,-3873,-3868,-3864,-3861,-3856,-3849,-3839,-3825,-3806,-3785,
+-3763,-3743,-3727,-3719,-3720,-3730,-3745,-3764,-3782,-3795,-3801,-3798,-3788,-3774,-3759,-3747,-3740,-3741,-3748,-3761,-3777,
+-3793,-3808,-3822,-3835,-3847,-3860,-3874,-3890,-3907,-3925,-3943,-3962,-3980,-3998,-4016,-4034,-4051,-4069,-4086,-4102,-4119,
+-4135,-4152,-4170,-4188,-4207,-4226,-4244,-4260,-4274,-4285,-4294,-4301,-4308,-4315,-4325,-4336,-4350,-4366,-4383,-4400,-4416,
+-4430,-4442,-4452,-4462,-4472,-4483,-4497,-4514,-4535,-4561,-4592,-4630,-4672,-4717,-4762,-4803,-4837,-4863,-4878,-4886,-4890,
+-4892,-4898,-4910,-4928,-4950,-4973,-4995,-5010,-5018,-5019,-5013,-5003,-4993,-4985,-4980,-4978,-4979,-4982,-4985,-4987,-4988,
+-4987,-4985,-4982,-4978,-4974,-4969,-4963,-4957,-4949,-4941,-4932,-4923,-4914,-4907,-4901,-4897,-4893,-4890,-4887,-4884,-4880,
+-4875,-4870,-4865,-4860,-4854,-4848,-4840,-4831,-4821,-4810,-4797,-4782,-4767,-4752,-4737,-4722,-4710,-4699,-4689,-4682,-4674,
+-4667,-4658,-4648,-4636,-4624,-4612,-4602,-4593,-4585,-4578,-4570,-4561,-4549,-4536,-4522,-4509,-4497,-4486,-4478,-4470,-4463,
+-4455,-4446,-4436,-4425,-4414,-4404,-4394,-4387,-4381,-4377,-4373,-4370,-4365,-4359,-4352,-4342,-4332,-4321,-4311,-4304,-4298,
+-4295,-4291,-4287,-4280,-4270,-4257,-4242,-4226,-4212,-4199,-4190,-4182,-4175,-4169,-4161,-4152,-4143,-4134,-4124,-4116,-4107,
+-4099,-4092,-4085,-4079,-4074,-4069,-4065,-4059,-4052,-4043,-4031,-4018,-4005,-3994,-3985,-3980,-3978,-3977,-3976,-3975,-3972,
+-3968,-3963,-3958,-3953,-3948,-3942,-3936,-3929,-3922,-3914,-3906,-3898,-3892,-3885,-3879,-3873,-3865,-3856,-3847,-3837,-3827,
+-3818,-3809,-3802,-3797,-3792,-3789,-3786,-3783,-3780,-3776,-3772,-3768,-3764,-3760,-3758,-3757,-3756,-3756,-3754,-3751,-3747,
+-3741,-3734,-3726,-3719,-3711,-3703,-3695,-3687,-3678,-3669,-3662,-3657,-3653,-3650,-3647,-3642,-3636,-3626,-3613,-3600,-3587,
+-3575,-3565,-3557,-3550,-3543,-3534,-3523,-3511,-3498,-3487,-3477,-3470,-3465,-3459,-3452,-3443,-3430,-3415,-3399,-3383,-3368,
+-3356,-3345,-3336,-3328,-3319,-3309,-3298,-3286,-3274,-3261,-3249,-3236,-3224,-3212,-3199,-3186,-3173,-3159,-3145,-3131,-3116,
+-3100,-3083,-3065,-3047,-3029,-3013,-2999,-2989,-2981,-2976,-2973,-2971,-2968,-2963,-2956,-2946,-2934,-2920,-2905,-2890,-2874,
+-2859,-2846,-2833,-2821,-2810,-2800,-2790,-2782,-2774,-2767,-2760,-2753,-2745,-2737,-2729,-2720,-2711,-2701,-2691,-2680,-2668,
+-2656,-2643,-2631,-2621,-2612,-2605,-2599,-2593,-2587,-2579,-2570,-2560,-2549,-2539,-2529,-2519,-2509,-2498,-2485,-2471,-2454,
+-2438,-2422,-2407,-2395,-2384,-2374,-2364,-2353,-2341,-2328,-2316,-2304,-2293,-2284,-2276,-2267,-2258,-2247,-2234,-2220,-2206,
+-2192,-2180,-2169,-2159,-2149,-2139,-2127,-2113,-2097,-2078,-2059,-2038,-2017,-1998,-1980,-1964,-1950,-1936,-1923,-1907,-1889,
+-1869,-1847,-1824,-1801,-1781,-1764,-1749,-1736,-1723,-1708,-1691,-1669,-1646,-1621,-1597,-1576,-1559,-1545,-1533,-1521,-1507,
+-1490,-1468,-1442,-1414,-1385,-1359,-1336,-1317,-1301,-1288,-1276,-1263,-1250,-1235,-1220,-1205,-1191,-1178,-1166,-1155,-1144,
+-1131,-1116,-1099,-1081,-1063,-1044,-1024,-1004,-981,-956,-928,-898,-864,-830,-797,-765,-735,-708,-682,-658,-634,
+-608,-582,-555,-527,-501,-474,-448,-422,-395,-365,-332,-297,-258,-219,-179,-140,-101,-63,-26,11,49,
+87,123,158,189,216,241,264,287,311,337,365,394,422,450,476,502,528,557,588,622,658,
+694,729,762,792,822,851,883,916,953,991,1031,1070,1109,1148,1187,1227,1266,1305,1342,1375,1403,
+1426,1444,1457,1468,1477,1487,1497,1510,1525,1546,1572,1606,1649,1700,1759,1820,1881,1937,1985,2023,2051,
+2074,2093,2113,2136,2163,2193,2225,2256,2285,2309,2330,2348,2363,2375,2386,2393,2395,2391,2381,2364,2342,
+2315,2286,2258,2231,2208,2188,2171,2156,2141,2124,2106,2085,2063,2040,2019,2000,1984,1972,1963,1954,1945,
+1934,1922,1909,1897,1888,1882,1880,1881,1883,1883,1881,1876,1870,1864,1862,1863,1867,1873,1877,1876,1870,
+1859,1845,1832,1823,1821,1824,1830,1837,1840,1836,1826,1811,1796,1785,1781,1786,1798,1814,1829,1841,1845,
+1841,1829,1811,1792,1772,1754,1740,1731,1725,1723,1724,1727,1730,1733,1734,1734,1732,1728,1722,1714,1705,
+1696,1689,1683,1680,1680,1682,1686,1688,1689,1687,1683,1677,1671,1667,1666,1667,1670,1673,1672,1668,1659,
+1647,1633,1620,1609,1600,1593,1585,1576,1565,1550,1535,1518,1503,1489,1476,1465,1453,1441,1429,1418,1407,
+1398,1391,1385,1378,1370,1360,1348,1335,1322,1312,1304,1300,1299,1299,1298,1294,1286,1273,1256,1236,1214,
+1194,1177,1164,1157,1154,1155,1158,1160,1160,1155,1147,1136,1124,1112,1103,1097,1096,1098,1102,1106,1107,
+1106,1100,1092,1082,1072,1064,1060,1061,1067,1078,1092,1107,1121,1134,1144,1151,1156,1159,1161,1162,1162,
+1161,1159,1157,1155,1154,1154,1154,1156,1158,1159,1160,1160,1160,1162,1165,1171,1178,1187,1196,1204,1212,
+1220,1228,1239,1253,1270,1288,1306,1323,1338,1350,1340,1349,1358,1368,1380,1393,1409,1425,1442,1459,1477,
+1496,1518,1541,1566,1591,1615,1638,1658,1677,1694,1709,1725,1739,1751,1761,1769,1775,1780,1786,1794,1806,
+1820,1837,1856,1874,1892,1908,1924,1938,1953,1969,1986,2004,2023,2041,2059,2076,2090,2102,2111,2118,2124,
+2130,2136,2144,2153,2163,2173,2180,2185,2187,2187,2187,2187,2189,2192,2196,2198,2199,2195,2187,2177,2164,
+2152,2143,2136,2132,2131,2132,2136,2141,2148,2156,2165,2174,2182,2188,2192,2196,2198,2201,2205,2210,2215,
+2218,2220,2220,2219,2218,2218,2222,2228,2238,2249,2260,2270,2277,2283,2288,2294,2300,2309,2319,2330,2341,
+2352,2362,2372,2382,2392,2402,2411,2417,2420,2419,2415,2411,2407,2407,2411,2421,2437,2457,2481,2506,2531,
+2555,2579,2602,2625,2646,2667,2686,2705,2723,2740,2756,2772,2786,2800,2813,2826,2838,2850,2863,2878,2894,
+2911,2930,2948,2965,2981,2994,3005,3014,3021,3025,3028,3029,3029,3027,3024,3019,3015,3011,3007,3004,3003,
+3003,3005,3010,3017,3026,3036,3045,3051,3052,3046,3033,3015,2991,2966,2942,2921,2904,2891,2883,2878,2875,
+2873,2872,2871,2871,2871,2872,2874,2875,2877,2877,2878,2879,2880,2883,2889,2896,2905,2915,2924,2934,2942,
+2949,2956,2962,2969,2977,2985,2993,3001,3008,3014,3019,3022,3024,3025,3024,3021,3017,3010,3000,2989,2976,
+2963,2950,2938,2928,2920,2914,2911,2908,2905,2901,2893,2880,2863,2843,2821,2800,2782,2767,2757,2749,2742,
+2734,2724,2713,2700,2687,2675,2665,2657,2650,2643,2635,2624,2612,2600,2587,2575,2564,2553,2541,2527,2512,
+2497,2481,2466,2453,2442,2431,2420,2409,2397,2385,2374,2365,2358,2352,2347,2340,2329,2316,2298,2279,2258,
+2238,2219,2201,2182,2162,2139,2114,2086,2057,2026,1994,1962,1927,1892,1855,1820,1786,1756,1733,1716,1706,
+1701,1698,1696,1690,1679,1662,1638,1609,1573,1534,1493,1450,1408,1369,1332,1300,1272,1248,1226,1206,1184,
+1161,1133,1102,1067,1029,989,948,907,868,830,794,759,725,693,661,631,601,573,544,516,487,
+457,427,398,370,345,321,298,273,245,211,170,124,76,29,-12,-45,-69,-85,-97,-109,-124,
+-145,-173,-206,-242,-278,-313,-347,-379,-412,-445,-479,-514,-549,-584,-618,-652,-688,-725,-763,-802,-839,
+-874,-903,-927,-949,-969,-992,-1019,-1052,-1090,-1130,-1169,-1204,-1232,-1254,-1269,-1281,-1292,-1306,-1324,-1348,-1378,
+-1413,-1452,-1496,-1542,-1591,-1642,-1694,-1746,-1797,-1846,-1891,-1932,-1968,-1999,-2027,-2052,-2075,-2099,-2123,-2147,-2171,
+-2195,-2217,-2237,-2253,-2267,-2279,-2290,-2302,-2314,-2328,-2345,-2365,-2388,-2414,-2442,-2472,-2504,-2538,-2573,-2609,-2645,
+-2680,-2716,-2751,-2785,-2817,-2849,-2880,-2909,-2938,-2966,-2994,-3023,-3051,-3080,-3108,-3135,-3159,-3180,-3198,-3213,-3226,
+-3238,-3250,-3264,-3279,-3295,-3312,-3328,-3343,-3356,-3369,-3382,-3396,-3412,-3431,-3452,-3475,-3500,-3525,-3551,-3577,-3605,
+-3634,-3665,-3698,-3730,-3762,-3791,-3817,-3838,-3856,-3871,-3884,-3897,-3909,-3922,-3936,-3950,-3965,-3980,-3995,-4008,-4019,
+-4027,-4032,-4035,-4035,-4035,-4036,-4038,-4042,-4048,-4055,-4061,-4067,-4071,-4073,-4075,-4077,-4079,-4082,-4084,-4087,-4089,
+-4091,-4094,-4098,-4104,-4111,-4120,-4127,-4132,-4133,-4128,-4120,-4108,-4097,-4087,-4082,-4080,-4080,-4082,-4081,-4077,-4068,
+-4054,-4039,-4024,-4011,-4003,-4000,-4000,-4003,-4007,-4009,-4010,-4008,-4003,-3998,-3993,-3988,-3985,-3981,-3978,-3974,-3969,
+-3962,-3955,-3948,-3941,-3937,-3934,-3932,-3931,-3928,-3921,-3910,-3894,-3874,-3851,-3828,-3809,-3796,-3790,-3794,-3805,-3821,
+-3840,-3857,-3870,-3877,-3876,-3869,-3859,-3847,-3836,-3830,-3829,-3833,-3842,-3854,-3868,-3883,-3897,-3912,-3926,-3939,-3953,
+-3967,-3982,-3998,-4014,-4032,-4051,-4070,-4090,-4111,-4131,-4151,-4170,-4188,-4203,-4217,-4231,-4244,-4259,-4275,-4292,-4311,
+-4330,-4347,-4362,-4374,-4383,-4390,-4397,-4405,-4415,-4427,-4442,-4456,-4470,-4481,-4490,-4497,-4503,-4509,-4516,-4525,-4536,
+-4550,-4567,-4587,-4611,-4640,-4674,-4711,-4749,-4786,-4817,-4841,-4857,-4866,-4871,-4876,-4885,-4899,-4920,-4945,-4973,-4999,
+-5020,-5034,-5041,-5041,-5035,-5028,-5020,-5014,-5009,-5007,-5006,-5005,-5005,-5005,-5004,-5003,-5001,-4998,-4995,-4990,-4984,
+-4976,-4968,-4960,-4951,-4944,-4937,-4930,-4925,-4920,-4915,-4910,-4905,-4901,-4896,-4892,-4887,-4883,-4878,-4873,-4867,-4860,
+-4852,-4842,-4832,-4820,-4806,-4792,-4778,-4764,-4750,-4739,-4729,-4721,-4714,-4707,-4699,-4690,-4680,-4669,-4659,-4649,-4640,
+-4632,-4624,-4616,-4607,-4597,-4585,-4573,-4561,-4550,-4540,-4531,-4524,-4517,-4510,-4503,-4496,-4489,-4482,-4474,-4467,-4460,
+-4453,-4446,-4440,-4434,-4429,-4424,-4418,-4411,-4403,-4394,-4385,-4377,-4369,-4363,-4357,-4352,-4346,-4338,-4329,-4318,-4307,
+-4296,-4285,-4275,-4265,-4255,-4245,-4234,-4223,-4213,-4203,-4194,-4186,-4177,-4168,-4159,-4150,-4143,-4137,-4133,-4131,-4128,
+-4125,-4120,-4111,-4100,-4088,-4076,-4065,-4057,-4052,-4049,-4047,-4045,-4042,-4039,-4034,-4029,-4025,-4020,-4016,-4011,-4006,
+-3999,-3991,-3983,-3974,-3964,-3955,-3946,-3936,-3926,-3915,-3904,-3893,-3881,-3871,-3862,-3855,-3849,-3845,-3841,-3838,-3835,
+-3831,-3826,-3820,-3814,-3810,-3806,-3805,-3805,-3807,-3809,-3810,-3809,-3808,-3804,-3799,-3794,-3787,-3780,-3772,-3762,-3752,
+-3740,-3729,-3719,-3711,-3706,-3702,-3699,-3695,-3689,-3681,-3671,-3659,-3648,-3638,-3630,-3622,-3615,-3606,-3595,-3582,-3566,
+-3551,-3536,-3524,-3515,-3508,-3502,-3495,-3486,-3474,-3461,-3446,-3431,-3417,-3405,-3393,-3382,-3371,-3358,-3345,-3331,-3318,
+-3306,-3295,-3286,-3277,-3267,-3256,-3242,-3227,-3211,-3194,-3177,-3162,-3147,-3133,-3119,-3105,-3090,-3075,-3060,-3046,-3034,
+-3023,-3015,-3008,-3001,-2995,-2988,-2980,-2971,-2961,-2950,-2939,-2928,-2917,-2906,-2895,-2884,-2873,-2862,-2851,-2841,-2831,
+-2822,-2814,-2805,-2797,-2788,-2779,-2770,-2760,-2750,-2740,-2729,-2717,-2704,-2690,-2676,-2663,-2652,-2643,-2635,-2629,-2622,
+-2615,-2607,-2598,-2587,-2576,-2564,-2554,-2543,-2532,-2520,-2506,-2491,-2476,-2461,-2446,-2433,-2422,-2411,-2401,-2389,-2377,
+-2363,-2350,-2337,-2325,-2315,-2307,-2298,-2288,-2277,-2265,-2251,-2237,-2223,-2212,-2202,-2193,-2185,-2175,-2162,-2147,-2130,
+-2111,-2091,-2071,-2053,-2036,-2020,-2006,-1993,-1979,-1965,-1949,-1931,-1912,-1890,-1868,-1847,-1827,-1809,-1792,-1778,-1763,
+-1746,-1726,-1703,-1676,-1648,-1621,-1597,-1578,-1563,-1552,-1544,-1534,-1522,-1505,-1483,-1456,-1428,-1400,-1374,-1352,-1335,
+-1321,-1309,-1297,-1285,-1272,-1257,-1241,-1224,-1208,-1193,-1179,-1166,-1154,-1140,-1126,-1112,-1095,-1078,-1060,-1040,-1018,
+-994,-968,-939,-909,-877,-845,-813,-783,-755,-729,-704,-680,-656,-631,-606,-580,-553,-526,-499,-470,-440,
+-407,-372,-334,-294,-253,-212,-173,-137,-102,-69,-36,-2,32,68,104,139,171,201,227,251,274,
+297,321,347,375,404,434,463,493,522,552,582,613,645,678,710,742,775,808,842,877,912,
+947,981,1014,1046,1078,1112,1147,1186,1228,1271,1316,1361,1404,1445,1484,1523,1560,1596,1629,1658,1680,
+1696,1706,1714,1722,1736,1759,1791,1832,1880,1929,1975,2015,2050,2078,2104,2131,2159,2191,2225,2258,2288,
+2312,2329,2340,2346,2350,2353,2357,2360,2361,2358,2347,2328,2301,2270,2239,2211,2190,2177,2172,2170,2167,
+2159,2141,2113,2076,2034,1992,1954,1926,1908,1900,1898,1899,1898,1892,1880,1866,1850,1836,1828,1825,1827,
+1831,1834,1834,1828,1820,1810,1802,1797,1797,1801,1806,1809,1807,1802,1792,1782,1773,1769,1771,1776,1783,
+1789,1790,1786,1778,1767,1757,1753,1754,1760,1771,1782,1789,1791,1785,1771,1753,1733,1714,1699,1689,1684,
+1682,1683,1684,1684,1683,1679,1673,1666,1658,1650,1642,1635,1628,1622,1618,1616,1616,1617,1620,1622,1622,
+1619,1614,1607,1600,1594,1591,1590,1591,1591,1589,1583,1572,1558,1542,1526,1514,1506,1501,1499,1497,1492,
+1485,1475,1463,1452,1442,1434,1428,1423,1416,1406,1393,1377,1360,1343,1329,1317,1309,1303,1298,1294,1288,
+1281,1273,1264,1254,1245,1236,1227,1219,1210,1200,1189,1177,1165,1153,1143,1135,1130,1127,1126,1126,1125,
+1124,1120,1114,1107,1098,1088,1080,1073,1068,1066,1065,1066,1067,1067,1066,1063,1057,1049,1041,1033,1028,
+1027,1031,1039,1052,1067,1082,1096,1108,1117,1125,1130,1134,1138,1140,1141,1141,1140,1139,1138,1137,1136,
+1135,1135,1134,1134,1135,1138,1142,1149,1158,1169,1179,1190,1199,1209,1219,1232,1246,1263,1281,1299,1315,
+1329,1340,1333,1341,1351,1362,1376,1394,1416,1440,1465,1491,1515,1539,1562,1584,1605,1626,1645,1663,1679,
+1695,1711,1726,1740,1754,1766,1776,1784,1789,1793,1797,1802,1809,1818,1830,1843,1856,1870,1882,1895,1906,
+1918,1932,1946,1962,1978,1995,2011,2026,2039,2049,2058,2065,2073,2082,2092,2103,2115,2126,2135,2142,2146,
+2148,2149,2151,2154,2158,2162,2165,2164,2159,2150,2137,2122,2108,2096,2089,2085,2084,2085,2087,2090,2093,
+2098,2105,2114,2123,2134,2143,2150,2155,2159,2163,2166,2170,2175,2179,2182,2184,2185,2186,2188,2193,2200,
+2208,2218,2227,2234,2240,2244,2249,2254,2261,2270,2281,2293,2305,2316,2326,2336,2345,2354,2363,2370,2374,
+2375,2373,2369,2364,2361,2362,2367,2379,2395,2415,2438,2463,2489,2515,2542,2568,2593,2617,2638,2656,2671,
+2685,2698,2712,2728,2744,2762,2779,2795,2809,2821,2833,2844,2857,2872,2889,2907,2926,2944,2959,2972,2981,
+2987,2991,2992,2991,2988,2984,2979,2975,2971,2968,2965,2963,2962,2963,2964,2968,2974,2983,2993,3003,3011,
+3014,3009,2997,2979,2955,2930,2906,2887,2872,2861,2855,2850,2846,2841,2837,2834,2832,2833,2836,2841,2846,
+2851,2856,2859,2862,2865,2871,2878,2887,2897,2906,2914,2919,2922,2925,2928,2933,2940,2949,2959,2969,2979,
+2987,2993,2997,2999,3001,3002,3001,2998,2992,2984,2972,2958,2943,2927,2913,2900,2890,2883,2879,2877,2876,
+2873,2869,2860,2846,2829,2808,2787,2767,2750,2738,2729,2723,2718,2711,2703,2693,2682,2672,2665,2659,2656,
+2652,2647,2639,2628,2614,2599,2584,2570,2558,2547,2535,2522,2506,2488,2468,2448,2428,2410,2394,2378,2363,
+2349,2335,2324,2314,2308,2304,2300,2296,2289,2279,2264,2247,2228,2209,2190,2172,2153,2134,2112,2088,2061,
+2033,2004,1975,1945,1914,1880,1845,1807,1769,1732,1699,1671,1650,1635,1625,1617,1609,1598,1583,1561,1534,
+1502,1466,1428,1390,1353,1318,1286,1257,1232,1209,1188,1167,1147,1125,1100,1074,1045,1013,980,945,908,
+871,833,795,757,719,682,648,616,587,560,535,509,484,457,430,403,377,354,333,313,294,
+272,246,214,176,134,91,49,11,-21,-48,-70,-90,-108,-127,-148,-169,-191,-214,-239,-265,-293,
+-325,-359,-395,-433,-471,-511,-553,-597,-644,-694,-744,-793,-837,-874,-902,-923,-940,-957,-977,-1004,-1038,
+-1078,-1120,-1160,-1195,-1223,-1243,-1257,-1268,-1280,-1296,-1318,-1346,-1381,-1421,-1467,-1517,-1570,-1627,-1685,-1743,-1800,
+-1853,-1900,-1941,-1976,-2004,-2027,-2048,-2067,-2088,-2109,-2133,-2157,-2181,-2204,-2224,-2240,-2252,-2261,-2268,-2273,-2279,
+-2287,-2298,-2312,-2330,-2352,-2378,-2408,-2441,-2477,-2516,-2556,-2597,-2639,-2679,-2719,-2756,-2792,-2828,-2862,-2895,-2929,
+-2962,-2995,-3027,-3057,-3086,-3113,-3139,-3162,-3184,-3204,-3223,-3240,-3257,-3274,-3291,-3308,-3326,-3343,-3360,-3376,-3391,
+-3406,-3421,-3436,-3454,-3473,-3495,-3518,-3542,-3567,-3591,-3617,-3643,-3670,-3700,-3732,-3766,-3799,-3831,-3859,-3883,-3902,
+-3916,-3928,-3939,-3950,-3963,-3976,-3991,-4005,-4018,-4028,-4036,-4040,-4041,-4041,-4039,-4037,-4036,-4037,-4039,-4042,-4046,
+-4049,-4051,-4051,-4049,-4045,-4041,-4037,-4036,-4037,-4041,-4047,-4055,-4063,-4072,-4081,-4090,-4100,-4111,-4123,-4134,-4143,
+-4150,-4154,-4156,-4156,-4157,-4159,-4165,-4173,-4181,-4188,-4191,-4187,-4177,-4161,-4141,-4119,-4100,-4085,-4075,-4071,-4072,
+-4075,-4078,-4079,-4079,-4077,-4073,-4068,-4064,-4060,-4057,-4053,-4050,-4045,-4039,-4032,-4025,-4018,-4013,-4009,-4006,-4004,
+-4000,-3993,-3983,-3969,-3950,-3929,-3908,-3888,-3873,-3865,-3864,-3871,-3884,-3901,-3919,-3937,-3950,-3958,-3959,-3955,-3947,
+-3936,-3926,-3918,-3914,-3916,-3922,-3933,-3946,-3961,-3977,-3992,-4007,-4021,-4035,-4049,-4064,-4079,-4095,-4111,-4129,-4148,
+-4167,-4188,-4209,-4230,-4250,-4267,-4281,-4293,-4303,-4313,-4326,-4341,-4361,-4383,-4406,-4429,-4448,-4463,-4474,-4482,-4489,
+-4496,-4505,-4515,-4526,-4537,-4545,-4552,-4557,-4562,-4567,-4575,-4584,-4594,-4605,-4617,-4628,-4640,-4655,-4674,-4698,-4726,
+-4757,-4789,-4817,-4840,-4856,-4867,-4873,-4879,-4888,-4902,-4921,-4945,-4971,-4996,-5017,-5033,-5043,-5047,-5047,-5045,-5041,
+-5036,-5032,-5029,-5027,-5025,-5025,-5024,-5025,-5025,-5024,-5021,-5017,-5011,-5004,-4996,-4989,-4981,-4975,-4969,-4963,-4957,
+-4950,-4943,-4936,-4930,-4924,-4918,-4914,-4910,-4906,-4902,-4898,-4893,-4887,-4881,-4874,-4867,-4858,-4848,-4836,-4824,-4811,
+-4798,-4787,-4777,-4769,-4761,-4755,-4747,-4739,-4730,-4720,-4709,-4699,-4689,-4680,-4672,-4665,-4657,-4650,-4642,-4635,-4627,
+-4619,-4611,-4603,-4595,-4588,-4580,-4574,-4568,-4563,-4559,-4555,-4550,-4544,-4536,-4527,-4517,-4509,-4501,-4494,-4489,-4483,
+-4477,-4470,-4461,-4450,-4440,-4429,-4420,-4412,-4406,-4400,-4395,-4390,-4385,-4379,-4371,-4362,-4351,-4339,-4327,-4315,-4303,
+-4293,-4284,-4276,-4268,-4260,-4250,-4239,-4228,-4217,-4207,-4200,-4196,-4194,-4193,-4192,-4189,-4183,-4175,-4165,-4154,-4144,
+-4136,-4128,-4122,-4117,-4112,-4106,-4101,-4097,-4093,-4089,-4086,-4083,-4079,-4073,-4066,-4058,-4048,-4037,-4026,-4014,-4002,
+-3990,-3978,-3966,-3954,-3943,-3932,-3923,-3916,-3911,-3908,-3905,-3902,-3899,-3894,-3888,-3880,-3872,-3865,-3859,-3855,-3853,
+-3852,-3853,-3854,-3854,-3853,-3851,-3849,-3847,-3844,-3840,-3835,-3829,-3820,-3809,-3797,-3786,-3775,-3766,-3758,-3751,-3745,
+-3737,-3729,-3720,-3711,-3702,-3695,-3689,-3683,-3676,-3668,-3656,-3641,-3624,-3606,-3589,-3573,-3560,-3549,-3539,-3529,-3519,
+-3508,-3496,-3483,-3471,-3459,-3448,-3436,-3423,-3408,-3393,-3377,-3362,-3348,-3336,-3328,-3320,-3313,-3304,-3294,-3280,-3264,
+-3247,-3228,-3211,-3194,-3180,-3166,-3153,-3141,-3128,-3116,-3104,-3092,-3081,-3071,-3061,-3051,-3041,-3030,-3018,-3007,-2995,
+-2985,-2976,-2968,-2960,-2953,-2945,-2937,-2927,-2917,-2907,-2896,-2886,-2876,-2866,-2856,-2846,-2836,-2826,-2816,-2806,-2796,
+-2786,-2776,-2765,-2753,-2740,-2726,-2712,-2699,-2687,-2677,-2668,-2659,-2651,-2642,-2632,-2621,-2610,-2598,-2586,-2575,-2564,
+-2553,-2541,-2528,-2515,-2502,-2488,-2476,-2464,-2452,-2441,-2428,-2415,-2402,-2388,-2375,-2363,-2353,-2343,-2333,-2322,-2309,
+-2295,-2280,-2265,-2253,-2243,-2235,-2229,-2223,-2215,-2204,-2189,-2171,-2151,-2130,-2110,-2092,-2077,-2064,-2052,-2040,-2027,
+-2012,-1995,-1977,-1957,-1937,-1916,-1895,-1876,-1857,-1840,-1823,-1806,-1787,-1766,-1742,-1715,-1686,-1658,-1632,-1610,-1592,
+-1580,-1570,-1561,-1550,-1536,-1517,-1493,-1467,-1440,-1414,-1390,-1370,-1354,-1340,-1327,-1314,-1301,-1286,-1270,-1254,-1237,
+-1220,-1205,-1190,-1175,-1161,-1148,-1134,-1120,-1105,-1089,-1071,-1051,-1028,-1004,-978,-951,-923,-894,-866,-837,-809,
+-780,-752,-723,-695,-668,-641,-615,-590,-565,-539,-512,-482,-449,-413,-375,-333,-290,-248,-206,-168,-132,
+-99,-69,-39,-10,20,52,86,120,154,185,215,241,266,289,313,338,364,392,422,452,483,
+513,543,571,599,627,656,687,721,757,795,835,874,911,944,975,1002,1027,1053,1083,1118,1160,
+1209,1263,1321,1379,1438,1494,1549,1601,1650,1696,1736,1769,1792,1804,1807,1802,1796,1792,1797,1813,1841,
+1880,1925,1973,2019,2059,2094,2123,2149,2173,2197,2221,2243,2262,2276,2285,2288,2289,2289,2291,2296,2303,
+2310,2313,2309,2294,2269,2236,2199,2164,2135,2115,2104,2100,2097,2088,2069,2037,1994,1942,1889,1842,1807,
+1786,1780,1786,1799,1811,1819,1821,1816,1807,1799,1793,1791,1793,1798,1801,1801,1795,1785,1771,1757,1747,
+1742,1743,1748,1754,1760,1762,1760,1756,1750,1745,1743,1744,1747,1751,1753,1751,1746,1739,1730,1722,1716,
+1714,1714,1715,1715,1713,1706,1696,1683,1670,1657,1646,1639,1634,1631,1628,1624,1618,1609,1599,1589,1579,
+1572,1567,1565,1565,1567,1568,1570,1571,1573,1573,1573,1572,1569,1564,1558,1550,1543,1536,1530,1527,1523,
+1519,1513,1503,1490,1474,1456,1440,1426,1415,1407,1401,1396,1390,1384,1377,1371,1368,1368,1371,1375,1378,
+1378,1371,1358,1339,1316,1292,1271,1254,1244,1241,1242,1245,1248,1247,1242,1231,1216,1199,1181,1164,1150,
+1139,1132,1126,1121,1116,1111,1105,1098,1092,1086,1082,1078,1076,1074,1073,1072,1071,1069,1066,1063,1059,
+1054,1050,1046,1044,1043,1042,1042,1040,1036,1029,1021,1011,1002,996,995,998,1005,1016,1029,1041,1053,
+1064,1074,1083,1092,1100,1108,1114,1119,1122,1123,1123,1122,1121,1120,1119,1118,1117,1118,1119,1123,1130,
+1139,1150,1162,1175,1187,1200,1214,1228,1244,1261,1278,1295,1310,1322,1333,1333,1345,1359,1376,1397,1424,
+1454,1488,1522,1554,1583,1608,1629,1646,1660,1672,1683,1693,1702,1711,1721,1730,1739,1749,1758,1767,1775,
+1781,1787,1793,1799,1806,1813,1822,1831,1840,1849,1858,1866,1875,1883,1892,1902,1914,1926,1939,1952,1964,
+1976,1987,1997,2007,2018,2030,2042,2055,2067,2077,2085,2091,2095,2099,2104,2110,2117,2124,2129,2129,2124,
+2113,2097,2079,2061,2047,2037,2032,2032,2034,2037,2040,2042,2046,2050,2058,2068,2079,2091,2101,2109,2114,
+2117,2120,2124,2128,2134,2140,2146,2151,2154,2156,2159,2163,2168,2175,2183,2191,2198,2203,2207,2212,2218,
+2226,2236,2248,2260,2273,2284,2293,2302,2309,2316,2321,2326,2327,2326,2322,2317,2311,2308,2309,2314,2325,
+2341,2361,2385,2410,2438,2467,2497,2528,2558,2585,2608,2626,2640,2652,2662,2674,2688,2705,2724,2744,2764,
+2781,2795,2807,2817,2828,2840,2853,2869,2886,2903,2919,2933,2944,2951,2956,2956,2954,2950,2944,2937,2932,
+2928,2926,2925,2924,2924,2923,2923,2923,2927,2933,2942,2953,2963,2970,2971,2966,2953,2935,2915,2895,2879,
+2866,2858,2852,2848,2844,2839,2834,2831,2831,2835,2841,2848,2856,2861,2864,2864,2863,2862,2864,2868,2875,
+2884,2891,2898,2901,2903,2904,2905,2910,2918,2928,2940,2953,2964,2972,2978,2981,2983,2983,2983,2981,2977,
+2971,2961,2948,2933,2916,2900,2885,2873,2863,2857,2853,2850,2848,2844,2838,2828,2815,2798,2780,2761,2745,
+2731,2722,2715,2709,2704,2697,2688,2678,2668,2659,2654,2652,2651,2650,2647,2640,2628,2613,2596,2578,2563,
+2549,2536,2522,2507,2488,2467,2442,2418,2393,2371,2351,2334,2318,2304,2292,2281,2272,2265,2260,2256,2251,
+2244,2234,2222,2207,2190,2174,2157,2141,2125,2107,2086,2062,2034,2005,1976,1946,1917,1888,1857,1824,1789,
+1751,1712,1674,1639,1609,1585,1567,1552,1538,1524,1508,1488,1465,1439,1411,1382,1354,1326,1299,1273,1248,
+1223,1198,1174,1150,1126,1102,1078,1052,1026,998,969,937,904,868,829,790,749,709,670,634,600,
+571,544,519,494,470,445,419,393,368,345,325,308,293,278,262,242,218,190,158,123,87,
+51,16,-16,-44,-67,-86,-100,-111,-119,-128,-140,-157,-179,-208,-242,-281,-324,-371,-422,-479,-541,
+-608,-677,-744,-805,-856,-894,-921,-937,-949,-962,-979,-1005,-1038,-1077,-1115,-1150,-1179,-1199,-1214,-1226,-1240,
+-1258,-1284,-1318,-1359,-1405,-1456,-1508,-1563,-1619,-1675,-1733,-1789,-1842,-1891,-1932,-1966,-1992,-2012,-2028,-2043,-2059,
+-2079,-2102,-2128,-2155,-2182,-2206,-2226,-2241,-2250,-2254,-2255,-2255,-2255,-2259,-2266,-2279,-2297,-2321,-2350,-2385,-2424,
+-2467,-2512,-2559,-2606,-2652,-2696,-2737,-2776,-2812,-2848,-2883,-2919,-2956,-2994,-3031,-3068,-3102,-3133,-3161,-3186,-3208,
+-3228,-3248,-3267,-3287,-3307,-3327,-3347,-3368,-3387,-3406,-3424,-3442,-3459,-3476,-3493,-3512,-3533,-3554,-3578,-3602,-3626,
+-3650,-3673,-3696,-3719,-3743,-3768,-3796,-3825,-3854,-3881,-3906,-3927,-3944,-3957,-3968,-3978,-3989,-4002,-4017,-4032,-4047,
+-4061,-4071,-4078,-4081,-4081,-4080,-4077,-4074,-4071,-4069,-4067,-4066,-4063,-4060,-4056,-4050,-4044,-4037,-4031,-4026,-4024,
+-4025,-4029,-4036,-4046,-4057,-4069,-4082,-4094,-4106,-4118,-4131,-4144,-4157,-4172,-4186,-4201,-4216,-4232,-4248,-4264,-4279,
+-4291,-4299,-4302,-4299,-4289,-4274,-4254,-4232,-4210,-4191,-4175,-4165,-4159,-4157,-4156,-4157,-4157,-4155,-4152,-4148,-4143,
+-4139,-4135,-4132,-4128,-4125,-4121,-4116,-4110,-4104,-4098,-4093,-4088,-4084,-4078,-4072,-4063,-4051,-4036,-4019,-4001,-3984,
+-3970,-3960,-3955,-3956,-3962,-3973,-3988,-4004,-4019,-4032,-4040,-4043,-4041,-4035,-4025,-4015,-4008,-4003,-4003,-4008,-4017,
+-4029,-4042,-4056,-4070,-4085,-4100,-4115,-4131,-4147,-4162,-4176,-4189,-4203,-4217,-4233,-4252,-4273,-4295,-4316,-4335,-4351,
+-4364,-4375,-4386,-4399,-4417,-4437,-4461,-4485,-4507,-4525,-4540,-4551,-4561,-4570,-4580,-4591,-4603,-4615,-4625,-4633,-4639,
+-4644,-4650,-4657,-4666,-4676,-4686,-4694,-4700,-4704,-4708,-4715,-4726,-4743,-4765,-4792,-4819,-4845,-4866,-4882,-4892,-4900,
+-4907,-4915,-4926,-4940,-4957,-4975,-4992,-5008,-5022,-5032,-5040,-5045,-5049,-5050,-5049,-5048,-5047,-5045,-5045,-5045,-5045,
+-5046,-5045,-5043,-5040,-5034,-5028,-5021,-5014,-5008,-5003,-4998,-4993,-4986,-4979,-4970,-4962,-4954,-4947,-4942,-4939,-4936,
+-4933,-4931,-4927,-4923,-4918,-4913,-4908,-4903,-4896,-4889,-4880,-4869,-4858,-4847,-4836,-4826,-4818,-4811,-4803,-4796,-4787,
+-4778,-4768,-4757,-4746,-4737,-4728,-4720,-4714,-4709,-4704,-4701,-4698,-4695,-4691,-4687,-4680,-4672,-4664,-4655,-4647,-4641,
+-4636,-4633,-4631,-4628,-4624,-4617,-4608,-4597,-4587,-4577,-4569,-4562,-4556,-4549,-4542,-4532,-4521,-4509,-4496,-4485,-4475,
+-4467,-4462,-4458,-4455,-4452,-4449,-4444,-4439,-4431,-4422,-4413,-4403,-4394,-4385,-4377,-4370,-4362,-4353,-4342,-4329,-4315,
+-4300,-4285,-4273,-4264,-4258,-4255,-4254,-4253,-4251,-4247,-4241,-4234,-4226,-4216,-4207,-4199,-4190,-4182,-4174,-4167,-4161,
+-4155,-4151,-4147,-4143,-4140,-4135,-4129,-4122,-4113,-4103,-4092,-4080,-4067,-4054,-4041,-4028,-4015,-4004,-3994,-3985,-3979,
+-3975,-3974,-3973,-3972,-3970,-3966,-3960,-3952,-3943,-3932,-3922,-3914,-3907,-3901,-3896,-3892,-3889,-3886,-3884,-3883,-3883,
+-3884,-3885,-3885,-3884,-3880,-3874,-3865,-3855,-3843,-3832,-3821,-3810,-3800,-3790,-3779,-3770,-3761,-3752,-3746,-3740,-3734,
+-3728,-3720,-3709,-3695,-3679,-3662,-3644,-3628,-3612,-3598,-3584,-3571,-3558,-3545,-3532,-3520,-3508,-3496,-3484,-3471,-3457,
+-3443,-3427,-3411,-3396,-3383,-3371,-3361,-3352,-3343,-3333,-3320,-3307,-3291,-3275,-3259,-3244,-3229,-3215,-3201,-3187,-3174,
+-3161,-3149,-3138,-3129,-3120,-3113,-3105,-3095,-3084,-3072,-3058,-3045,-3031,-3019,-3009,-3000,-2991,-2982,-2974,-2964,-2955,
+-2945,-2936,-2927,-2919,-2911,-2903,-2894,-2884,-2873,-2862,-2851,-2840,-2830,-2820,-2810,-2799,-2787,-2774,-2761,-2747,-2734,
+-2721,-2710,-2699,-2689,-2678,-2667,-2656,-2643,-2631,-2619,-2607,-2595,-2584,-2572,-2561,-2549,-2537,-2525,-2514,-2502,-2490,
+-2478,-2465,-2452,-2438,-2424,-2412,-2400,-2390,-2380,-2370,-2359,-2345,-2329,-2313,-2296,-2282,-2272,-2265,-2260,-2257,-2253,
+-2246,-2235,-2219,-2201,-2181,-2162,-2144,-2128,-2114,-2101,-2088,-2074,-2058,-2041,-2023,-2005,-1986,-1968,-1950,-1932,-1914,
+-1895,-1875,-1855,-1833,-1810,-1785,-1759,-1732,-1706,-1682,-1661,-1644,-1631,-1619,-1608,-1595,-1578,-1557,-1532,-1503,-1475,
+-1447,-1423,-1402,-1384,-1369,-1354,-1340,-1325,-1309,-1293,-1277,-1261,-1246,-1231,-1216,-1201,-1186,-1171,-1156,-1142,-1128,
+-1113,-1098,-1080,-1059,-1036,-1011,-985,-959,-933,-907,-882,-856,-828,-799,-768,-735,-703,-671,-641,-614,-589,
+-564,-539,-513,-483,-451,-415,-377,-336,-295,-254,-214,-176,-141,-107,-77,-47,-18,9,39,70,103,
+136,168,199,228,255,280,303,327,352,378,406,436,467,497,527,555,582,609,637,667,701,
+738,777,816,856,892,925,955,982,1008,1038,1072,1114,1163,1221,1285,1352,1419,1485,1545,1601,1651,
+1695,1735,1768,1795,1815,1827,1831,1830,1827,1826,1829,1842,1865,1897,1938,1981,2025,2063,2095,2120,2138,
+2152,2164,2175,2185,2195,2204,2209,2211,2212,2212,2213,2219,2227,2238,2248,2253,2249,2232,2203,2164,2119,
+2073,2032,1999,1974,1954,1935,1912,1881,1841,1795,1745,1700,1665,1644,1639,1649,1668,1691,1713,1729,1738,
+1741,1740,1738,1737,1739,1743,1748,1750,1749,1744,1736,1727,1719,1714,1713,1717,1722,1728,1733,1734,1732,
+1727,1720,1714,1710,1707,1707,1706,1705,1703,1698,1690,1681,1671,1661,1653,1645,1639,1633,1628,1623,1618,
+1612,1607,1602,1597,1593,1588,1581,1573,1563,1551,1539,1528,1519,1512,1510,1510,1512,1515,1518,1521,1521,
+1522,1521,1520,1519,1518,1516,1512,1507,1499,1491,1483,1474,1466,1458,1450,1441,1431,1419,1405,1390,1374,
+1358,1343,1327,1313,1301,1290,1283,1279,1280,1286,1294,1304,1313,1317,1314,1305,1288,1265,1241,1217,1199,
+1187,1183,1184,1189,1194,1196,1192,1181,1166,1146,1127,1109,1096,1087,1083,1081,1081,1079,1076,1071,1064,
+1057,1049,1043,1038,1035,1033,1033,1034,1036,1037,1038,1037,1034,1030,1026,1020,1016,1013,1011,1010,1010,
+1009,1006,1001,994,988,982,978,978,980,985,992,999,1007,1016,1026,1036,1048,1060,1071,1082,1090,
+1096,1100,1102,1103,1104,1106,1107,1109,1110,1111,1112,1114,1119,1126,1136,1148,1163,1178,1194,1210,1227,
+1244,1261,1278,1294,1308,1321,1333,1340,1359,1382,1408,1438,1473,1511,1551,1589,1623,1653,1676,1693,1705,
+1713,1718,1722,1726,1729,1731,1733,1734,1736,1737,1740,1744,1749,1755,1763,1770,1777,1785,1791,1798,1805,
+1811,1818,1825,1831,1838,1845,1852,1860,1870,1880,1891,1902,1914,1926,1937,1948,1959,1971,1982,1994,2005,
+2016,2025,2034,2041,2049,2057,2067,2076,2085,2091,2092,2087,2075,2056,2035,2013,1995,1982,1976,1975,1979,
+1984,1989,1994,1998,2002,2009,2017,2028,2039,2050,2058,2064,2067,2069,2072,2077,2085,2094,2104,2112,2118,
+2121,2122,2123,2124,2127,2133,2139,2147,2153,2159,2164,2170,2177,2187,2199,2212,2226,2238,2249,2257,2263,
+2268,2273,2277,2280,2282,2281,2277,2272,2265,2260,2258,2260,2267,2280,2297,2318,2342,2369,2399,2432,2466,
+2500,2533,2562,2586,2605,2620,2632,2644,2657,2672,2689,2708,2726,2743,2758,2771,2782,2793,2805,2818,2832,
+2848,2864,2880,2895,2908,2918,2923,2925,2923,2918,2911,2904,2898,2894,2893,2892,2892,2891,2889,2886,2883,
+2882,2886,2894,2907,2921,2935,2944,2947,2944,2934,2920,2906,2893,2883,2877,2875,2874,2874,2874,2876,2880,
+2886,2894,2903,2910,2915,2914,2909,2899,2888,2879,2873,2872,2875,2882,2889,2894,2897,2898,2897,2897,2900,
+2905,2914,2926,2938,2948,2957,2963,2967,2969,2969,2968,2964,2959,2950,2938,2923,2907,2890,2875,2862,2851,
+2844,2839,2836,2833,2829,2824,2816,2806,2792,2777,2760,2744,2730,2719,2710,2703,2697,2691,2683,2674,2665,
+2655,2648,2644,2642,2642,2642,2639,2632,2621,2606,2589,2570,2553,2536,2520,2503,2484,2463,2438,2412,2385,
+2360,2336,2316,2298,2282,2267,2254,2242,2231,2222,2215,2210,2204,2197,2189,2179,2167,2154,2141,2127,2113,
+2098,2081,2060,2035,2007,1976,1945,1913,1882,1853,1823,1792,1760,1727,1692,1659,1627,1599,1575,1555,1538,
+1522,1506,1488,1469,1447,1424,1401,1378,1355,1333,1311,1288,1265,1241,1217,1192,1166,1141,1116,1090,1063,
+1034,1004,972,938,902,864,824,783,743,702,664,628,594,564,537,511,488,464,441,416,391,
+366,342,320,301,285,272,263,255,248,239,227,210,187,160,129,97,66,41,22,10,4,
+1,0,-5,-16,-33,-58,-91,-129,-175,-227,-288,-358,-437,-522,-611,-696,-772,-834,-880,-912,-932,
+-947,-963,-985,-1014,-1048,-1083,-1116,-1141,-1158,-1168,-1175,-1184,-1200,-1227,-1267,-1317,-1375,-1436,-1497,-1556,-1612,
+-1665,-1716,-1765,-1812,-1857,-1896,-1929,-1955,-1974,-1987,-1998,-2009,-2023,-2041,-2064,-2091,-2120,-2149,-2176,-2198,-2213,
+-2222,-2225,-2225,-2223,-2222,-2224,-2232,-2246,-2267,-2296,-2331,-2371,-2416,-2464,-2514,-2565,-2616,-2665,-2711,-2755,-2795,
+-2833,-2869,-2904,-2939,-2975,-3012,-3049,-3084,-3118,-3150,-3178,-3203,-3226,-3247,-3267,-3287,-3307,-3328,-3349,-3370,-3392,
+-3414,-3437,-3461,-3484,-3507,-3530,-3552,-3573,-3595,-3616,-3637,-3659,-3681,-3702,-3722,-3741,-3760,-3778,-3796,-3815,-3835,
+-3856,-3878,-3898,-3918,-3935,-3950,-3964,-3977,-3990,-4004,-4018,-4033,-4046,-4059,-4071,-4080,-4089,-4096,-4102,-4107,-4111,
+-4113,-4113,-4110,-4104,-4097,-4090,-4083,-4077,-4072,-4069,-4068,-4067,-4068,-4069,-4072,-4077,-4085,-4094,-4105,-4117,-4129,
+-4141,-4154,-4166,-4180,-4196,-4215,-4237,-4261,-4287,-4312,-4335,-4355,-4370,-4380,-4385,-4386,-4383,-4376,-4366,-4352,-4336,
+-4318,-4300,-4282,-4267,-4256,-4248,-4244,-4243,-4243,-4243,-4241,-4238,-4233,-4227,-4222,-4217,-4213,-4209,-4205,-4201,-4197,
+-4191,-4185,-4178,-4172,-4165,-4159,-4152,-4144,-4134,-4123,-4111,-4097,-4084,-4072,-4061,-4053,-4048,-4047,-4050,-4057,-4068,
+-4082,-4096,-4109,-4119,-4124,-4125,-4121,-4115,-4108,-4101,-4098,-4097,-4100,-4105,-4113,-4122,-4133,-4145,-4160,-4177,-4195,
+-4213,-4229,-4244,-4256,-4266,-4276,-4287,-4302,-4319,-4341,-4364,-4386,-4407,-4424,-4439,-4451,-4464,-4478,-4494,-4513,-4533,
+-4553,-4571,-4587,-4600,-4613,-4625,-4639,-4655,-4671,-4687,-4702,-4715,-4726,-4735,-4743,-4752,-4761,-4770,-4779,-4785,-4788,
+-4788,-4787,-4787,-4791,-4799,-4812,-4831,-4852,-4874,-4894,-4912,-4925,-4936,-4944,-4952,-4959,-4967,-4975,-4983,-4992,-5001,
+-5010,-5020,-5029,-5038,-5047,-5053,-5057,-5060,-5061,-5060,-5060,-5060,-5061,-5061,-5061,-5060,-5057,-5053,-5048,-5042,-5038,
+-5033,-5030,-5026,-5021,-5015,-5007,-4999,-4990,-4983,-4977,-4973,-4971,-4970,-4968,-4966,-4962,-4958,-4953,-4948,-4942,-4937,
+-4932,-4926,-4919,-4911,-4902,-4893,-4884,-4875,-4867,-4859,-4851,-4842,-4833,-4823,-4812,-4802,-4793,-4785,-4779,-4773,-4768,
+-4764,-4760,-4758,-4756,-4754,-4752,-4749,-4745,-4739,-4731,-4722,-4713,-4706,-4701,-4698,-4696,-4694,-4692,-4688,-4682,-4673,
+-4664,-4655,-4646,-4638,-4631,-4624,-4616,-4607,-4597,-4586,-4575,-4564,-4553,-4543,-4535,-4527,-4520,-4514,-4509,-4505,-4502,
+-4499,-4496,-4493,-4488,-4483,-4476,-4469,-4462,-4453,-4443,-4433,-4420,-4406,-4391,-4375,-4360,-4347,-4335,-4327,-4321,-4316,
+-4313,-4311,-4307,-4302,-4296,-4289,-4281,-4271,-4262,-4252,-4242,-4232,-4222,-4213,-4205,-4198,-4192,-4187,-4183,-4178,-4174,
+-4168,-4161,-4153,-4143,-4131,-4118,-4104,-4089,-4075,-4062,-4051,-4043,-4037,-4035,-4034,-4036,-4037,-4037,-4035,-4031,-4024,
+-4015,-4004,-3992,-3980,-3968,-3957,-3947,-3938,-3930,-3924,-3919,-3916,-3916,-3918,-3921,-3924,-3927,-3927,-3926,-3921,-3915,
+-3906,-3897,-3886,-3875,-3864,-3853,-3841,-3829,-3818,-3807,-3797,-3789,-3781,-3772,-3763,-3753,-3741,-3728,-3713,-3698,-3683,
+-3669,-3654,-3639,-3625,-3610,-3594,-3579,-3564,-3549,-3535,-3521,-3507,-3493,-3479,-3465,-3450,-3436,-3422,-3409,-3396,-3383,
+-3369,-3354,-3340,-3326,-3312,-3299,-3287,-3275,-3262,-3249,-3235,-3220,-3205,-3191,-3178,-3168,-3160,-3154,-3149,-3143,-3135,
+-3126,-3115,-3102,-3089,-3076,-3062,-3049,-3037,-3024,-3011,-2998,-2985,-2974,-2964,-2956,-2950,-2945,-2940,-2934,-2927,-2919,
+-2909,-2898,-2886,-2875,-2865,-2854,-2843,-2831,-2819,-2805,-2792,-2778,-2764,-2751,-2739,-2727,-2716,-2704,-2692,-2679,-2666,
+-2653,-2641,-2628,-2616,-2605,-2593,-2582,-2571,-2560,-2549,-2538,-2526,-2514,-2502,-2488,-2473,-2458,-2445,-2432,-2422,-2412,
+-2402,-2392,-2380,-2365,-2350,-2333,-2319,-2306,-2297,-2291,-2287,-2283,-2277,-2269,-2258,-2243,-2228,-2212,-2196,-2181,-2167,
+-2152,-2136,-2119,-2101,-2082,-2063,-2046,-2030,-2016,-2002,-1987,-1970,-1951,-1930,-1906,-1881,-1855,-1829,-1803,-1778,-1754,
+-1733,-1716,-1702,-1690,-1681,-1672,-1660,-1642,-1619,-1590,-1557,-1522,-1488,-1459,-1434,-1415,-1399,-1385,-1371,-1356,-1339,
+-1321,-1303,-1286,-1271,-1258,-1245,-1231,-1217,-1201,-1184,-1168,-1151,-1135,-1120,-1104,-1086,-1066,-1043,-1017,-990,-963,
+-936,-911,-887,-862,-835,-806,-775,-742,-709,-677,-646,-619,-593,-569,-543,-516,-485,-451,-415,-377,-339,
+-300,-262,-225,-188,-153,-119,-87,-56,-27,0,28,57,87,118,150,181,211,238,264,288,311,
+334,359,386,415,445,476,507,538,567,596,625,655,687,721,756,791,827,862,897,931,966,
+1002,1043,1088,1138,1195,1256,1321,1387,1451,1511,1566,1613,1652,1685,1712,1735,1754,1771,1786,1799,1810,
+1820,1830,1842,1858,1880,1907,1940,1976,2011,2043,2068,2086,2097,2102,2106,2110,2115,2123,2132,2140,2145,
+2145,2143,2139,2138,2142,2151,2164,2178,2185,2182,2163,2126,2075,2013,1947,1885,1830,1785,1750,1721,1694,
+1665,1633,1600,1567,1540,1523,1517,1525,1543,1566,1592,1614,1630,1639,1642,1641,1639,1638,1640,1645,1652,
+1659,1665,1670,1673,1675,1676,1677,1679,1680,1681,1681,1679,1675,1669,1661,1653,1646,1640,1637,1635,1635,
+1635,1634,1631,1625,1618,1608,1598,1589,1580,1574,1570,1567,1565,1564,1562,1559,1555,1549,1543,1536,1529,
+1520,1512,1503,1494,1486,1480,1475,1471,1468,1465,1462,1458,1455,1451,1448,1447,1448,1450,1452,1452,1450,
+1445,1436,1425,1412,1401,1390,1383,1377,1372,1367,1360,1349,1335,1317,1297,1277,1257,1240,1226,1217,1212,
+1211,1214,1219,1225,1232,1235,1235,1229,1218,1202,1182,1163,1145,1133,1125,1123,1125,1128,1129,1126,1118,
+1106,1092,1078,1066,1057,1053,1051,1051,1051,1049,1045,1040,1033,1026,1019,1015,1011,1009,1008,1007,1006,
+1005,1005,1004,1002,999,996,991,986,981,977,974,974,974,976,977,977,976,974,972,969,968,
+967,968,970,973,978,984,992,1002,1014,1026,1039,1050,1058,1065,1070,1074,1078,1082,1088,1094,1100,
+1104,1107,1109,1112,1115,1121,1129,1141,1155,1171,1188,1205,1222,1238,1255,1272,1289,1306,1323,1340,1351,
+1380,1411,1445,1482,1521,1562,1602,1639,1671,1697,1717,1732,1741,1748,1752,1755,1758,1760,1761,1760,1758,
+1754,1750,1746,1744,1744,1745,1748,1752,1755,1759,1762,1765,1769,1773,1779,1786,1794,1803,1812,1822,1832,
+1842,1854,1865,1877,1889,1901,1911,1922,1931,1941,1950,1960,1971,1981,1992,2004,2015,2027,2038,2049,2057,
+2061,2060,2053,2039,2020,1998,1977,1957,1944,1937,1936,1939,1945,1951,1956,1960,1964,1969,1976,1984,1994,
+2003,2010,2015,2018,2019,2021,2026,2033,2044,2055,2066,2075,2080,2081,2081,2079,2080,2082,2088,2094,2101,
+2107,2113,2118,2124,2133,2144,2158,2173,2188,2200,2209,2215,2220,2224,2228,2234,2240,2245,2247,2244,2238,
+2229,2219,2210,2207,2209,2217,2231,2251,2274,2301,2330,2362,2396,2431,2466,2500,2531,2558,2581,2600,2616,
+2631,2644,2658,2671,2685,2699,2713,2726,2739,2752,2766,2780,2796,2812,2829,2846,2862,2876,2887,2894,2897,
+2895,2890,2883,2876,2871,2868,2867,2868,2869,2869,2867,2863,2860,2858,2861,2869,2883,2901,2920,2936,2946,
+2950,2947,2939,2930,2921,2914,2912,2914,2920,2928,2938,2949,2962,2975,2987,2996,3001,2999,2991,2976,2959,
+2940,2925,2915,2911,2913,2918,2923,2926,2926,2923,2918,2912,2909,2910,2913,2920,2928,2936,2943,2948,2952,
+2954,2954,2952,2947,2939,2927,2912,2894,2875,2857,2842,2831,2823,2819,2818,2817,2816,2814,2810,2803,2793,
+2781,2767,2751,2735,2720,2706,2694,2684,2676,2668,2660,2653,2646,2639,2635,2632,2631,2631,2630,2627,2621,
+2611,2597,2580,2562,2543,2524,2504,2483,2461,2437,2411,2385,2358,2333,2309,2287,2266,2246,2227,2209,2193,
+2179,2169,2161,2157,2154,2151,2147,2140,2131,2119,2106,2091,2075,2058,2039,2019,1995,1969,1941,1911,1882,
+1853,1824,1796,1767,1739,1712,1685,1660,1638,1618,1602,1588,1574,1561,1546,1528,1508,1486,1463,1439,1415,
+1391,1367,1343,1319,1295,1270,1246,1223,1199,1175,1150,1123,1093,1061,1025,988,948,907,865,824,782,
+742,702,664,629,595,565,538,514,492,471,451,431,410,387,363,340,318,301,288,283,283,
+288,296,303,305,300,288,268,242,215,189,168,153,143,136,130,122,110,93,71,44,12,
+-26,-73,-131,-201,-283,-376,-474,-570,-659,-734,-794,-839,-873,-901,-930,-962,-998,-1036,-1072,-1101,-1120,
+-1130,-1134,-1137,-1146,-1166,-1201,-1251,-1312,-1379,-1448,-1513,-1573,-1626,-1673,-1716,-1756,-1795,-1832,-1865,-1893,-1914,
+-1930,-1941,-1948,-1954,-1963,-1976,-1993,-2015,-2040,-2066,-2092,-2115,-2134,-2147,-2156,-2161,-2165,-2170,-2179,-2193,-2214,
+-2241,-2275,-2315,-2359,-2406,-2455,-2505,-2555,-2605,-2655,-2703,-2749,-2793,-2833,-2871,-2906,-2939,-2970,-3001,-3030,-3059,
+-3087,-3114,-3139,-3163,-3186,-3208,-3228,-3248,-3267,-3286,-3305,-3326,-3350,-3377,-3407,-3439,-3472,-3504,-3534,-3560,-3583,
+-3602,-3620,-3636,-3653,-3670,-3687,-3705,-3721,-3735,-3747,-3759,-3769,-3780,-3793,-3808,-3825,-3843,-3862,-3880,-3897,-3913,
+-3927,-3940,-3952,-3963,-3973,-3983,-3993,-4005,-4020,-4036,-4055,-4074,-4092,-4107,-4118,-4124,-4125,-4124,-4121,-4120,-4122,
+-4127,-4134,-4143,-4151,-4157,-4161,-4163,-4164,-4166,-4170,-4177,-4185,-4195,-4205,-4215,-4224,-4235,-4249,-4266,-4288,-4313,
+-4341,-4367,-4391,-4409,-4421,-4427,-4428,-4427,-4425,-4423,-4420,-4416,-4409,-4400,-4388,-4374,-4360,-4348,-4340,-4336,-4336,
+-4338,-4340,-4341,-4339,-4333,-4326,-4317,-4309,-4302,-4296,-4292,-4287,-4282,-4276,-4269,-4261,-4252,-4242,-4233,-4224,-4215,
+-4205,-4196,-4186,-4175,-4165,-4155,-4146,-4137,-4130,-4125,-4123,-4125,-4130,-4140,-4153,-4168,-4182,-4194,-4202,-4205,-4205,
+-4202,-4198,-4194,-4191,-4190,-4191,-4193,-4197,-4203,-4212,-4224,-4239,-4257,-4277,-4297,-4315,-4330,-4342,-4353,-4363,-4374,
+-4388,-4405,-4425,-4445,-4465,-4483,-4498,-4512,-4524,-4536,-4550,-4566,-4584,-4602,-4620,-4636,-4652,-4666,-4680,-4695,-4711,
+-4728,-4745,-4762,-4779,-4795,-4810,-4824,-4837,-4850,-4860,-4869,-4874,-4876,-4876,-4874,-4873,-4875,-4880,-4888,-4900,-4913,
+-4927,-4940,-4952,-4964,-4974,-4985,-4995,-5005,-5013,-5020,-5026,-5029,-5031,-5033,-5036,-5039,-5045,-5051,-5057,-5062,-5065,
+-5068,-5069,-5070,-5071,-5072,-5074,-5075,-5075,-5074,-5072,-5069,-5066,-5064,-5062,-5060,-5057,-5053,-5048,-5042,-5035,-5028,
+-5022,-5017,-5014,-5013,-5011,-5009,-5006,-5001,-4995,-4989,-4983,-4977,-4972,-4968,-4963,-4958,-4953,-4947,-4940,-4933,-4927,
+-4919,-4911,-4902,-4891,-4880,-4870,-4860,-4852,-4846,-4842,-4839,-4836,-4832,-4828,-4822,-4817,-4812,-4807,-4804,-4801,-4798,
+-4793,-4788,-4781,-4774,-4767,-4761,-4757,-4755,-4754,-4753,-4752,-4749,-4745,-4740,-4734,-4727,-4719,-4712,-4704,-4696,-4688,
+-4680,-4672,-4663,-4654,-4644,-4633,-4621,-4608,-4595,-4583,-4573,-4566,-4561,-4560,-4560,-4561,-4560,-4557,-4552,-4545,-4537,
+-4528,-4520,-4512,-4504,-4496,-4487,-4476,-4464,-4450,-4436,-4423,-4411,-4401,-4393,-4387,-4381,-4376,-4369,-4362,-4353,-4344,
+-4334,-4322,-4311,-4299,-4286,-4274,-4262,-4251,-4241,-4233,-4228,-4223,-4220,-4217,-4214,-4209,-4201,-4191,-4179,-4164,-4149,
+-4133,-4119,-4107,-4098,-4092,-4089,-4089,-4090,-4092,-4093,-4093,-4090,-4085,-4078,-4069,-4058,-4046,-4034,-4022,-4009,-3997,
+-3986,-3976,-3968,-3963,-3959,-3958,-3959,-3960,-3962,-3963,-3963,-3961,-3959,-3955,-3950,-3944,-3937,-3929,-3919,-3907,-3895,
+-3881,-3867,-3853,-3840,-3828,-3816,-3805,-3794,-3783,-3772,-3760,-3748,-3736,-3723,-3710,-3696,-3680,-3664,-3647,-3630,-3612,
+-3595,-3578,-3562,-3547,-3532,-3518,-3504,-3489,-3475,-3460,-3444,-3427,-3410,-3393,-3377,-3361,-3347,-3335,-3324,-3314,-3303,
+-3292,-3279,-3265,-3250,-3235,-3221,-3210,-3200,-3193,-3187,-3181,-3175,-3168,-3159,-3148,-3137,-3126,-3114,-3102,-3089,-3074,
+-3059,-3043,-3026,-3011,-2998,-2988,-2980,-2975,-2971,-2967,-2962,-2956,-2948,-2939,-2929,-2919,-2909,-2898,-2888,-2876,-2864,
+-2850,-2836,-2822,-2807,-2794,-2781,-2768,-2756,-2744,-2731,-2718,-2704,-2690,-2676,-2663,-2650,-2638,-2627,-2616,-2605,-2595,
+-2586,-2576,-2566,-2556,-2544,-2531,-2516,-2500,-2485,-2470,-2456,-2444,-2433,-2423,-2412,-2399,-2386,-2373,-2359,-2347,-2337,
+-2329,-2321,-2314,-2305,-2295,-2283,-2270,-2257,-2245,-2233,-2222,-2210,-2197,-2181,-2163,-2143,-2123,-2104,-2087,-2073,-2061,
+-2049,-2037,-2022,-2004,-1982,-1958,-1932,-1906,-1879,-1853,-1828,-1803,-1780,-1759,-1742,-1729,-1721,-1715,-1709,-1700,-1684,
+-1660,-1629,-1592,-1553,-1516,-1483,-1458,-1440,-1426,-1413,-1400,-1384,-1365,-1344,-1324,-1305,-1288,-1274,-1261,-1248,-1233,
+-1215,-1196,-1176,-1156,-1138,-1121,-1105,-1088,-1070,-1048,-1024,-997,-969,-942,-915,-889,-864,-838,-810,-781,-750,
+-719,-689,-661,-635,-610,-584,-558,-528,-494,-458,-419,-379,-339,-300,-263,-226,-191,-157,-124,-92,-63,
+-34,-7,18,45,72,101,131,161,190,218,244,268,292,315,339,365,393,423,455,486,518,
+550,582,613,645,676,708,741,775,810,848,889,932,979,1028,1080,1133,1187,1241,1295,1350,1403,
+1456,1505,1549,1587,1619,1643,1661,1677,1691,1705,1722,1740,1760,1780,1798,1817,1835,1855,1879,1905,1934,
+1964,1992,2014,2030,2039,2043,2045,2047,2051,2059,2069,2078,2083,2083,2077,2069,2062,2060,2066,2081,2099,
+2116,2123,2111,2078,2023,1949,1865,1780,1703,1639,1592,1559,1538,1522,1507,1491,1474,1457,1444,1437,1439,
+1449,1466,1486,1505,1521,1532,1537,1538,1536,1534,1534,1537,1543,1553,1564,1575,1585,1594,1599,1601,1601,
+1599,1596,1592,1588,1584,1579,1574,1569,1564,1559,1555,1554,1554,1556,1559,1561,1562,1561,1558,1552,1545,
+1539,1533,1529,1526,1523,1521,1517,1511,1505,1497,1490,1483,1478,1473,1469,1465,1460,1455,1448,1441,1433,
+1424,1416,1407,1398,1389,1382,1376,1372,1371,1372,1374,1375,1375,1371,1363,1352,1340,1328,1318,1311,1306,
+1305,1303,1299,1293,1282,1267,1250,1232,1215,1201,1189,1181,1174,1169,1166,1163,1161,1160,1158,1156,1153,
+1146,1137,1125,1111,1097,1086,1077,1072,1071,1071,1071,1069,1065,1058,1050,1041,1034,1029,1026,1023,1021,
+1018,1013,1007,1000,994,989,986,985,985,985,983,981,978,975,972,969,968,966,964,961,958,
+953,949,946,944,943,944,946,948,950,951,951,950,950,950,951,952,954,958,963,969,978,
+988,999,1009,1019,1027,1034,1039,1045,1052,1059,1068,1077,1086,1094,1099,1104,1107,1112,1118,1127,1138,
+1152,1167,1183,1198,1213,1229,1245,1262,1281,1302,1325,1351,1367,1402,1439,1477,1516,1556,1594,1630,1664,
+1692,1715,1733,1746,1754,1760,1765,1769,1773,1777,1780,1782,1781,1778,1774,1769,1763,1758,1753,1748,1744,
+1740,1736,1733,1731,1732,1735,1742,1751,1762,1774,1788,1801,1814,1827,1840,1852,1864,1875,1886,1896,1905,
+1914,1923,1933,1943,1955,1969,1983,1997,2010,2021,2029,2034,2033,2027,2016,2001,1983,1964,1947,1933,1924,
+1921,1922,1926,1932,1936,1938,1939,1939,1939,1942,1946,1953,1961,1968,1973,1975,1976,1977,1980,1986,1995,
+2005,2017,2026,2032,2035,2035,2034,2034,2037,2042,2050,2058,2065,2070,2074,2077,2082,2090,2102,2117,2132,
+2147,2158,2166,2171,2175,2180,2186,2195,2204,2212,2214,2209,2197,2181,2162,2147,2138,2140,2152,2172,2200,
+2231,2262,2293,2323,2352,2381,2411,2442,2474,2505,2533,2559,2581,2599,2613,2625,2636,2646,2657,2668,2680,
+2694,2708,2723,2740,2756,2774,2791,2808,2825,2839,2851,2858,2861,2860,2856,2849,2843,2838,2836,2838,2841,
+2846,2850,2853,2854,2854,2856,2862,2872,2887,2905,2925,2944,2958,2967,2969,2968,2963,2959,2957,2958,2963,
+2971,2983,2998,3013,3029,3044,3056,3064,3065,3060,3049,3033,3015,2999,2987,2980,2979,2981,2984,2985,2982,
+2975,2965,2954,2943,2936,2932,2931,2933,2935,2937,2939,2939,2938,2937,2935,2932,2926,2915,2901,2882,2860,
+2837,2816,2799,2787,2780,2778,2779,2781,2783,2784,2784,2781,2776,2769,2760,2748,2734,2718,2701,2684,2667,
+2653,2640,2631,2623,2618,2615,2614,2614,2615,2615,2614,2611,2605,2596,2583,2566,2548,2527,2504,2480,2455,
+2429,2402,2375,2348,2322,2297,2271,2247,2222,2198,2174,2152,2133,2118,2109,2105,2104,2106,2108,2108,2103,
+2093,2079,2061,2041,2019,1998,1978,1959,1939,1920,1901,1880,1857,1833,1808,1782,1755,1728,1702,1678,1657,
+1639,1624,1612,1601,1590,1579,1566,1552,1535,1516,1496,1474,1450,1424,1397,1369,1341,1313,1287,1262,1238,
+1216,1192,1167,1139,1108,1073,1035,995,953,911,869,828,787,747,707,669,633,599,568,542,519,
+500,483,468,453,437,420,401,382,364,349,339,336,339,347,359,370,378,379,372,357,335,
+309,282,256,233,214,196,180,163,145,125,106,86,65,40,9,-32,-86,-156,-239,-331,-426,
+-518,-601,-672,-731,-780,-823,-864,-906,-949,-990,-1027,-1056,-1077,-1090,-1099,-1109,-1125,-1151,-1191,-1242,-1302,
+-1365,-1428,-1486,-1539,-1585,-1627,-1666,-1704,-1742,-1779,-1813,-1843,-1867,-1884,-1895,-1902,-1905,-1908,-1913,-1920,-1932,
+-1947,-1965,-1985,-2005,-2025,-2043,-2060,-2075,-2089,-2105,-2123,-2146,-2173,-2206,-2244,-2285,-2329,-2375,-2422,-2469,-2518,
+-2567,-2616,-2666,-2715,-2762,-2807,-2848,-2886,-2920,-2950,-2977,-3002,-3026,-3048,-3070,-3092,-3114,-3135,-3154,-3172,-3189,
+-3204,-3219,-3236,-3255,-3279,-3309,-3343,-3380,-3418,-3454,-3486,-3512,-3532,-3547,-3560,-3571,-3584,-3598,-3615,-3631,-3647,
+-3660,-3670,-3677,-3683,-3689,-3696,-3706,-3718,-3733,-3749,-3764,-3779,-3793,-3806,-3817,-3827,-3837,-3847,-3858,-3870,-3886,
+-3905,-3929,-3957,-3988,-4020,-4050,-4076,-4098,-4114,-4126,-4137,-4149,-4163,-4181,-4200,-4220,-4238,-4252,-4260,-4263,-4264,
+-4263,-4264,-4267,-4272,-4279,-4286,-4292,-4297,-4302,-4308,-4318,-4332,-4350,-4371,-4393,-4413,-4428,-4438,-4442,-4443,-4443,
+-4443,-4444,-4448,-4451,-4453,-4451,-4447,-4440,-4432,-4425,-4422,-4423,-4428,-4435,-4441,-4444,-4443,-4437,-4428,-4417,-4405,
+-4396,-4388,-4383,-4378,-4374,-4368,-4360,-4351,-4339,-4327,-4314,-4301,-4288,-4275,-4263,-4253,-4243,-4235,-4228,-4222,-4216,
+-4211,-4206,-4202,-4200,-4201,-4206,-4214,-4226,-4240,-4254,-4266,-4274,-4279,-4281,-4281,-4279,-4278,-4277,-4276,-4277,-4278,
+-4280,-4285,-4292,-4302,-4317,-4334,-4354,-4375,-4394,-4412,-4427,-4440,-4452,-4464,-4478,-4492,-4507,-4522,-4536,-4549,-4562,
+-4574,-4588,-4602,-4620,-4639,-4659,-4679,-4699,-4717,-4732,-4746,-4758,-4770,-4781,-4794,-4808,-4825,-4843,-4862,-4882,-4902,
+-4920,-4934,-4944,-4949,-4952,-4952,-4953,-4955,-4960,-4968,-4977,-4986,-4994,-5001,-5005,-5008,-5012,-5017,-5026,-5038,-5052,
+-5067,-5079,-5088,-5092,-5092,-5089,-5084,-5079,-5075,-5073,-5072,-5072,-5074,-5076,-5078,-5081,-5084,-5088,-5091,-5095,-5097,
+-5098,-5098,-5097,-5096,-5095,-5094,-5093,-5092,-5090,-5087,-5083,-5077,-5072,-5068,-5064,-5061,-5058,-5055,-5051,-5046,-5040,
+-5034,-5028,-5022,-5017,-5014,-5010,-5007,-5003,-4999,-4995,-4990,-4985,-4980,-4973,-4965,-4956,-4945,-4934,-4924,-4915,-4909,
+-4906,-4905,-4905,-4905,-4902,-4898,-4891,-4882,-4873,-4865,-4858,-4854,-4850,-4848,-4844,-4840,-4835,-4829,-4823,-4818,-4815,
+-4813,-4812,-4812,-4813,-4812,-4811,-4807,-4802,-4796,-4788,-4780,-4772,-4764,-4757,-4750,-4744,-4738,-4731,-4721,-4710,-4696,
+-4680,-4665,-4651,-4639,-4632,-4628,-4626,-4625,-4623,-4619,-4613,-4605,-4596,-4588,-4582,-4578,-4576,-4574,-4573,-4569,-4562,
+-4553,-4541,-4528,-4515,-4502,-4491,-4481,-4472,-4463,-4454,-4445,-4434,-4423,-4411,-4399,-4386,-4374,-4360,-4347,-4332,-4319,
+-4305,-4294,-4285,-4278,-4273,-4269,-4266,-4261,-4255,-4246,-4235,-4221,-4206,-4191,-4176,-4163,-4153,-4145,-4140,-4137,-4136,
+-4136,-4136,-4136,-4135,-4133,-4129,-4124,-4117,-4108,-4098,-4087,-4075,-4063,-4050,-4038,-4028,-4018,-4011,-4005,-4001,-3997,
+-3995,-3993,-3991,-3990,-3989,-3988,-3987,-3986,-3985,-3981,-3975,-3967,-3955,-3941,-3926,-3909,-3893,-3877,-3863,-3850,-3839,
+-3828,-3818,-3808,-3797,-3786,-3774,-3761,-3746,-3730,-3713,-3695,-3676,-3658,-3639,-3621,-3604,-3587,-3571,-3555,-3539,-3523,
+-3506,-3489,-3471,-3454,-3436,-3420,-3404,-3390,-3377,-3365,-3354,-3342,-3329,-3316,-3302,-3288,-3275,-3262,-3252,-3243,-3235,
+-3228,-3220,-3212,-3202,-3191,-3180,-3169,-3159,-3150,-3141,-3131,-3121,-3108,-3093,-3078,-3061,-3046,-3032,-3021,-3013,-3006,
+-3000,-2994,-2988,-2981,-2973,-2964,-2956,-2948,-2940,-2932,-2922,-2912,-2899,-2885,-2870,-2855,-2841,-2827,-2814,-2801,-2788,
+-2775,-2761,-2746,-2731,-2715,-2700,-2686,-2673,-2660,-2649,-2638,-2628,-2619,-2611,-2603,-2594,-2584,-2573,-2560,-2545,-2530,
+-2514,-2499,-2484,-2471,-2458,-2446,-2433,-2420,-2408,-2396,-2385,-2375,-2366,-2357,-2347,-2336,-2323,-2309,-2294,-2280,-2267,
+-2257,-2248,-2240,-2230,-2218,-2203,-2186,-2168,-2150,-2135,-2122,-2111,-2101,-2089,-2074,-2055,-2033,-2008,-1983,-1958,-1935,
+-1913,-1889,-1864,-1836,-1805,-1776,-1750,-1730,-1718,-1713,-1712,-1711,-1704,-1688,-1662,-1627,-1588,-1549,-1515,-1489,-1471,
+-1459,-1449,-1438,-1423,-1403,-1379,-1354,-1330,-1309,-1291,-1276,-1261,-1244,-1225,-1204,-1181,-1158,-1136,-1118,-1102,-1087,
+-1072,-1054,-1033,-1009,-983,-955,-928,-900,-874,-847,-819,-791,-762,-733,-704,-677,-651,-626,-601,-573,-543,
+-509,-472,-432,-392,-351,-311,-273,-237,-202,-169,-137,-106,-77,-49,-23,2,28,54,82,110,138,
+167,194,220,245,270,295,320,347,375,405,435,465,497,528,561,593,627,661,696,733,772,
+815,861,913,968,1026,1084,1141,1194,1242,1286,1326,1364,1402,1440,1478,1514,1547,1574,1596,1611,1624,
+1635,1648,1665,1685,1707,1729,1750,1769,1786,1803,1821,1843,1868,1896,1924,1949,1969,1981,1987,1988,1988,
+1989,1993,1998,2003,2006,2004,1999,1992,1987,1988,1996,2013,2033,2050,2056,2043,2006,1945,1866,1776,1685,
+1604,1539,1494,1466,1451,1445,1440,1433,1423,1411,1398,1388,1384,1386,1395,1408,1424,1441,1456,1467,1476,
+1481,1484,1486,1487,1489,1492,1495,1499,1503,1506,1507,1507,1505,1502,1499,1497,1497,1498,1500,1501,1502,
+1501,1499,1496,1494,1492,1493,1495,1499,1503,1506,1507,1506,1503,1499,1495,1492,1489,1486,1482,1477,1470,
+1462,1453,1444,1437,1431,1427,1424,1420,1415,1409,1401,1392,1383,1374,1366,1358,1350,1342,1334,1325,1317,
+1309,1304,1300,1298,1296,1292,1288,1281,1273,1264,1256,1250,1245,1242,1239,1235,1229,1221,1210,1198,1187,
+1176,1168,1161,1155,1149,1142,1134,1126,1117,1110,1104,1100,1096,1092,1086,1079,1070,1060,1051,1044,1039,
+1037,1036,1035,1034,1030,1025,1018,1011,1005,999,994,990,985,978,971,963,955,950,947,946,947,
+949,950,949,947,943,940,937,936,937,938,939,939,937,934,930,925,921,918,917,917,918,
+919,920,921,923,925,928,931,934,938,942,947,952,959,966,974,983,992,1000,1009,1017,1025,
+1033,1043,1053,1063,1072,1080,1088,1094,1100,1106,1114,1125,1137,1150,1164,1178,1192,1206,1220,1236,1255,
+1278,1304,1334,1367,1380,1418,1457,1495,1533,1571,1606,1640,1671,1697,1718,1734,1744,1749,1752,1752,1753,
+1754,1756,1758,1761,1763,1764,1763,1760,1755,1748,1741,1732,1724,1715,1707,1702,1699,1699,1703,1711,1723,
+1737,1752,1767,1782,1796,1809,1821,1832,1842,1852,1862,1872,1882,1892,1904,1917,1931,1946,1962,1977,1990,
+2000,2005,2005,1999,1988,1972,1953,1935,1918,1905,1899,1898,1902,1910,1919,1927,1931,1930,1927,1921,1915,
+1911,1910,1913,1919,1925,1931,1935,1937,1938,1941,1945,1951,1960,1970,1978,1984,1986,1986,1985,1985,1988,
+1995,2004,2014,2024,2030,2034,2035,2037,2040,2047,2059,2074,2089,2103,2114,2121,2126,2131,2138,2147,2158,
+2168,2174,2171,2158,2135,2108,2081,2061,2054,2063,2089,2127,2172,2218,2261,2296,2323,2345,2363,2382,2402,
+2427,2454,2482,2510,2535,2556,2573,2586,2596,2606,2615,2625,2636,2648,2661,2675,2690,2705,2721,2738,2755,
+2772,2787,2800,2809,2814,2815,2812,2807,2801,2798,2797,2799,2805,2813,2823,2832,2841,2849,2858,2869,2882,
+2898,2916,2935,2955,2972,2986,2996,3002,3006,3007,3008,3008,3009,3012,3016,3023,3031,3041,3050,3058,3063,
+3065,3062,3057,3050,3044,3040,3040,3043,3047,3050,3049,3044,3033,3019,3003,2989,2978,2971,2968,2968,2967,
+2964,2958,2950,2939,2929,2920,2913,2906,2898,2887,2872,2851,2826,2800,2774,2752,2736,2726,2721,2720,2722,
+2725,2728,2732,2736,2739,2742,2744,2742,2736,2725,2710,2691,2669,2648,2628,2611,2599,2591,2586,2585,2585,
+2587,2587,2587,2584,2578,2569,2556,2539,2518,2494,2468,2439,2409,2378,2348,2319,2291,2264,2238,2213,2188,
+2163,2139,2116,2096,2080,2068,2062,2061,2063,2066,2068,2066,2059,2045,2027,2004,1980,1956,1934,1915,1899,
+1886,1874,1862,1848,1831,1810,1785,1757,1727,1696,1667,1639,1614,1592,1573,1556,1541,1528,1515,1503,1492,
+1482,1472,1461,1449,1433,1414,1391,1365,1337,1308,1280,1254,1229,1205,1181,1155,1126,1095,1060,1024,986,
+948,910,872,835,796,758,720,682,646,613,584,558,536,517,501,486,471,457,443,430,417,
+405,396,390,386,385,386,386,386,381,372,357,336,311,283,254,226,198,172,146,120,96,
+72,51,33,18,7,-4,-18,-41,-75,-124,-187,-262,-345,-430,-511,-585,-651,-708,-757,-802,-844,
+-883,-920,-954,-984,-1009,-1031,-1053,-1076,-1103,-1137,-1176,-1221,-1268,-1316,-1362,-1406,-1448,-1490,-1532,-1575,-1621,
+-1667,-1712,-1754,-1791,-1822,-1846,-1863,-1875,-1882,-1886,-1888,-1891,-1895,-1901,-1909,-1921,-1935,-1951,-1968,-1986,-2005,
+-2023,-2042,-2062,-2084,-2110,-2140,-2175,-2213,-2256,-2301,-2348,-2398,-2448,-2500,-2552,-2604,-2657,-2708,-2757,-2805,-2849,
+-2891,-2929,-2964,-2995,-3024,-3050,-3074,-3096,-3116,-3133,-3149,-3162,-3174,-3184,-3195,-3207,-3222,-3242,-3266,-3294,-3325,
+-3354,-3382,-3404,-3422,-3434,-3444,-3454,-3465,-3480,-3497,-3517,-3536,-3554,-3568,-3578,-3586,-3592,-3597,-3604,-3611,-3620,
+-3629,-3637,-3644,-3651,-3657,-3665,-3676,-3690,-3708,-3728,-3749,-3772,-3795,-3819,-3846,-3875,-3908,-3943,-3978,-4013,-4045,
+-4073,-4099,-4123,-4146,-4171,-4199,-4228,-4256,-4283,-4304,-4319,-4329,-4335,-4339,-4342,-4348,-4356,-4364,-4372,-4377,-4379,
+-4379,-4378,-4378,-4381,-4389,-4401,-4415,-4429,-4442,-4450,-4456,-4458,-4460,-4462,-4466,-4472,-4478,-4483,-4487,-4487,-4486,
+-4485,-4486,-4491,-4500,-4512,-4524,-4535,-4541,-4542,-4536,-4526,-4513,-4501,-4490,-4482,-4477,-4474,-4471,-4467,-4460,-4452,
+-4440,-4427,-4412,-4396,-4380,-4363,-4348,-4334,-4322,-4313,-4307,-4303,-4301,-4299,-4296,-4292,-4288,-4284,-4284,-4286,-4293,
+-4303,-4314,-4326,-4337,-4345,-4350,-4352,-4353,-4354,-4354,-4355,-4356,-4357,-4358,-4359,-4361,-4366,-4373,-4384,-4399,-4417,
+-4437,-4457,-4477,-4495,-4511,-4525,-4538,-4550,-4562,-4574,-4587,-4599,-4612,-4625,-4640,-4656,-4674,-4694,-4715,-4738,-4760,
+-4781,-4799,-4814,-4825,-4834,-4840,-4847,-4857,-4869,-4886,-4907,-4930,-4954,-4976,-4993,-5005,-5012,-5016,-5019,-5023,-5030,
+-5041,-5055,-5070,-5083,-5091,-5095,-5093,-5088,-5083,-5080,-5084,-5093,-5107,-5125,-5142,-5156,-5165,-5167,-5163,-5155,-5143,
+-5132,-5121,-5112,-5105,-5102,-5101,-5102,-5105,-5109,-5113,-5118,-5122,-5124,-5126,-5126,-5125,-5124,-5124,-5124,-5124,-5125,
+-5124,-5123,-5121,-5117,-5114,-5110,-5107,-5103,-5100,-5096,-5092,-5087,-5082,-5077,-5072,-5069,-5066,-5064,-5061,-5058,-5055,
+-5050,-5046,-5041,-5037,-5032,-5027,-5021,-5013,-5004,-4995,-4985,-4977,-4972,-4969,-4969,-4969,-4970,-4969,-4965,-4959,-4950,
+-4941,-4932,-4924,-4918,-4914,-4911,-4908,-4904,-4899,-4894,-4888,-4882,-4878,-4875,-4873,-4872,-4872,-4872,-4871,-4868,-4864,
+-4858,-4851,-4842,-4833,-4825,-4817,-4811,-4807,-4803,-4800,-4795,-4788,-4779,-4768,-4755,-4742,-4730,-4719,-4711,-4704,-4698,
+-4692,-4684,-4675,-4666,-4656,-4647,-4640,-4636,-4635,-4634,-4634,-4633,-4630,-4624,-4617,-4608,-4598,-4589,-4580,-4572,-4564,
+-4555,-4545,-4533,-4521,-4508,-4495,-4483,-4470,-4458,-4445,-4432,-4418,-4403,-4388,-4373,-4359,-4347,-4337,-4329,-4321,-4314,
+-4307,-4298,-4288,-4276,-4262,-4248,-4234,-4220,-4207,-4196,-4187,-4179,-4174,-4171,-4169,-4167,-4167,-4167,-4167,-4165,-4163,
+-4159,-4154,-4146,-4137,-4125,-4113,-4100,-4087,-4075,-4064,-4055,-4047,-4040,-4033,-4028,-4023,-4019,-4017,-4016,-4017,-4019,
+-4020,-4021,-4019,-4014,-4006,-3995,-3980,-3964,-3947,-3931,-3915,-3901,-3889,-3878,-3868,-3858,-3847,-3836,-3823,-3808,-3792,
+-3775,-3756,-3737,-3717,-3697,-3678,-3660,-3642,-3624,-3607,-3589,-3571,-3553,-3534,-3515,-3497,-3480,-3464,-3450,-3437,-3425,
+-3413,-3401,-3387,-3372,-3357,-3341,-3326,-3312,-3300,-3291,-3283,-3277,-3270,-3262,-3252,-3240,-3227,-3213,-3201,-3190,-3181,
+-3173,-3166,-3159,-3150,-3140,-3127,-3113,-3098,-3084,-3072,-3061,-3051,-3042,-3034,-3025,-3016,-3008,-2999,-2992,-2986,-2980,
+-2974,-2967,-2958,-2948,-2935,-2921,-2906,-2890,-2876,-2861,-2848,-2834,-2820,-2805,-2790,-2774,-2758,-2741,-2725,-2710,-2695,
+-2681,-2668,-2656,-2645,-2635,-2626,-2617,-2608,-2598,-2587,-2575,-2561,-2548,-2534,-2520,-2507,-2494,-2481,-2467,-2453,-2439,
+-2425,-2413,-2401,-2391,-2382,-2372,-2362,-2350,-2336,-2322,-2307,-2294,-2284,-2275,-2268,-2260,-2250,-2238,-2224,-2209,-2194,
+-2181,-2171,-2162,-2154,-2143,-2128,-2107,-2082,-2055,-2028,-2004,-1984,-1967,-1950,-1930,-1903,-1867,-1826,-1782,-1742,-1711,
+-1693,-1689,-1694,-1703,-1707,-1701,-1681,-1649,-1609,-1567,-1529,-1501,-1484,-1475,-1471,-1467,-1457,-1440,-1417,-1389,-1360,
+-1334,-1311,-1292,-1275,-1258,-1239,-1216,-1191,-1166,-1142,-1120,-1103,-1088,-1074,-1059,-1043,-1022,-999,-973,-946,-919,
+-892,-865,-838,-810,-781,-751,-722,-693,-665,-638,-612,-585,-557,-526,-494,-460,-424,-388,-352,-316,-281,
+-246,-212,-179,-146,-115,-84,-54,-25,3,31,59,86,113,139,165,190,215,241,269,298,327,
+358,388,417,446,475,504,534,567,601,639,680,725,774,828,886,948,1012,1076,1137,1192,1240,
+1280,1313,1341,1367,1393,1421,1451,1481,1509,1533,1552,1566,1579,1591,1607,1626,1650,1677,1702,1725,1743,
+1756,1766,1777,1791,1809,1832,1857,1883,1904,1918,1926,1927,1923,1918,1913,1909,1907,1906,1905,1904,1906,
+1912,1922,1939,1957,1974,1983,1976,1949,1901,1835,1755,1673,1596,1532,1485,1456,1441,1435,1432,1426,1416,
+1401,1383,1365,1350,1340,1337,1340,1350,1364,1382,1402,1422,1442,1459,1473,1483,1487,1487,1482,1475,1466,
+1458,1450,1443,1438,1434,1431,1431,1433,1438,1444,1452,1460,1466,1469,1469,1466,1462,1457,1454,1453,1453,
+1456,1458,1460,1461,1460,1458,1455,1453,1452,1450,1448,1446,1441,1435,1428,1420,1412,1404,1397,1389,1380,
+1369,1358,1345,1333,1322,1315,1310,1307,1305,1302,1297,1289,1278,1265,1253,1242,1233,1227,1224,1221,1219,
+1216,1212,1206,1201,1195,1189,1184,1177,1170,1162,1154,1145,1137,1130,1124,1119,1115,1110,1104,1096,1088,
+1079,1072,1065,1060,1056,1053,1048,1042,1036,1029,1022,1017,1014,1012,1011,1009,1006,1001,994,986,977,
+970,963,956,950,944,937,929,921,914,909,906,905,906,908,908,908,906,904,902,901,902,
+905,907,910,910,909,906,901,896,892,889,888,888,889,890,892,894,898,902,907,913,919,
+924,929,933,937,941,947,953,962,972,983,994,1005,1016,1026,1036,1045,1054,1062,1069,1077,1084,
+1092,1101,1111,1122,1134,1147,1160,1173,1185,1199,1214,1232,1253,1279,1310,1344,1380,1377,1415,1453,1490,
+1527,1563,1598,1631,1661,1687,1707,1720,1727,1727,1723,1716,1709,1703,1698,1697,1698,1699,1701,1703,1702,
+1700,1697,1692,1687,1682,1677,1674,1673,1673,1677,1684,1694,1705,1719,1734,1749,1763,1776,1787,1797,1806,
+1815,1823,1833,1844,1856,1869,1884,1901,1917,1934,1949,1962,1971,1976,1974,1967,1953,1935,1914,1893,1874,
+1861,1855,1856,1864,1876,1889,1901,1908,1909,1905,1898,1888,1880,1875,1875,1877,1883,1889,1894,1897,1900,
+1902,1905,1911,1918,1927,1934,1940,1942,1942,1939,1937,1938,1942,1949,1959,1970,1978,1983,1985,1985,1986,
+1990,1999,2012,2027,2043,2057,2068,2076,2083,2090,2100,2113,2125,2134,2135,2124,2102,2070,2035,2004,1987,
+1988,2011,2054,2110,2172,2231,2280,2316,2339,2352,2359,2367,2377,2393,2414,2439,2464,2487,2507,2524,2537,
+2548,2557,2567,2576,2586,2597,2607,2617,2628,2640,2654,2669,2685,2703,2720,2736,2749,2758,2764,2766,2765,
+2763,2762,2762,2764,2770,2778,2789,2802,2816,2830,2844,2859,2875,2893,2912,2932,2954,2977,2999,3020,3037,
+3049,3056,3056,3051,3042,3030,3019,3010,3005,3003,3005,3010,3015,3020,3025,3031,3039,3049,3063,3079,3094,
+3107,3114,3112,3102,3086,3066,3047,3032,3023,3021,3022,3023,3021,3012,2997,2975,2952,2928,2908,2893,2882,
+2872,2860,2844,2823,2796,2766,2736,2709,2687,2672,2662,2658,2656,2657,2661,2666,2675,2686,2700,2714,2726,
+2734,2735,2727,2711,2689,2662,2634,2608,2585,2568,2556,2549,2546,2546,2546,2546,2544,2539,2530,2517,2500,
+2477,2451,2421,2389,2356,2323,2290,2260,2231,2204,2179,2155,2132,2111,2093,2076,2062,2052,2045,2040,2038,
+2035,2032,2026,2016,2003,1985,1965,1944,1922,1902,1885,1870,1857,1846,1835,1821,1804,1782,1756,1725,1691,
+1656,1622,1589,1560,1533,1509,1487,1466,1447,1428,1412,1399,1390,1385,1383,1383,1382,1378,1369,1354,1334,
+1310,1284,1258,1232,1207,1183,1158,1132,1103,1073,1040,1007,974,940,907,874,841,807,773,739,706,
+676,648,623,600,578,557,535,513,491,469,449,433,419,409,400,392,384,373,359,343,323,
+301,277,252,226,200,174,148,122,95,69,42,15,-11,-35,-56,-73,-86,-94,-101,-108,-121,
+-141,-173,-218,-274,-340,-412,-485,-556,-621,-678,-727,-767,-800,-828,-853,-876,-899,-925,-953,-984,-1019,
+-1055,-1092,-1128,-1162,-1193,-1221,-1249,-1279,-1314,-1354,-1401,-1454,-1510,-1568,-1624,-1675,-1721,-1760,-1794,-1822,-1846,
+-1866,-1882,-1895,-1905,-1913,-1919,-1925,-1931,-1939,-1948,-1960,-1971,-1982,-1992,-2001,-2009,-2018,-2029,-2045,-2068,-2099,
+-2138,-2184,-2236,-2292,-2350,-2408,-2465,-2520,-2573,-2626,-2677,-2729,-2782,-2835,-2887,-2938,-2985,-3028,-3065,-3096,-3121,
+-3140,-3155,-3167,-3176,-3185,-3193,-3201,-3211,-3222,-3235,-3249,-3263,-3275,-3286,-3294,-3300,-3304,-3310,-3318,-3329,-3347,
+-3368,-3393,-3418,-3441,-3460,-3475,-3487,-3496,-3505,-3515,-3527,-3538,-3548,-3554,-3556,-3554,-3551,-3549,-3553,-3565,-3587,
+-3616,-3652,-3689,-3725,-3757,-3784,-3808,-3830,-3853,-3878,-3907,-3938,-3971,-4003,-4035,-4065,-4095,-4125,-4156,-4189,-4222,
+-4254,-4282,-4307,-4326,-4342,-4356,-4369,-4384,-4399,-4414,-4428,-4438,-4443,-4443,-4440,-4436,-4432,-4432,-4435,-4442,-4451,
+-4460,-4468,-4475,-4480,-4485,-4490,-4496,-4503,-4510,-4516,-4520,-4524,-4526,-4530,-4537,-4548,-4563,-4580,-4598,-4612,-4622,
+-4624,-4620,-4611,-4598,-4586,-4574,-4566,-4561,-4558,-4555,-4553,-4549,-4543,-4535,-4525,-4512,-4498,-4481,-4463,-4443,-4425,
+-4408,-4394,-4385,-4379,-4376,-4375,-4373,-4371,-4367,-4363,-4360,-4359,-4362,-4368,-4377,-4389,-4400,-4410,-4418,-4423,-4427,
+-4429,-4431,-4432,-4434,-4436,-4437,-4437,-4436,-4435,-4436,-4440,-4448,-4461,-4477,-4496,-4516,-4536,-4555,-4572,-4587,-4601,
+-4615,-4628,-4642,-4657,-4671,-4686,-4701,-4715,-4731,-4748,-4766,-4787,-4809,-4831,-4852,-4871,-4886,-4897,-4905,-4912,-4919,
+-4929,-4943,-4961,-4982,-5005,-5027,-5046,-5060,-5070,-5077,-5084,-5094,-5107,-5124,-5145,-5166,-5185,-5197,-5202,-5200,-5192,
+-5181,-5172,-5167,-5169,-5177,-5190,-5206,-5221,-5232,-5238,-5238,-5233,-5224,-5212,-5199,-5186,-5176,-5167,-5160,-5156,-5153,
+-5152,-5152,-5152,-5151,-5150,-5148,-5146,-5144,-5143,-5143,-5144,-5146,-5148,-5149,-5150,-5150,-5148,-5147,-5145,-5143,-5141,
+-5140,-5138,-5136,-5133,-5130,-5128,-5126,-5124,-5123,-5121,-5119,-5115,-5110,-5105,-5099,-5094,-5090,-5086,-5083,-5080,-5076,
+-5071,-5064,-5056,-5049,-5042,-5037,-5033,-5031,-5030,-5028,-5026,-5021,-5016,-5010,-5004,-4998,-4993,-4988,-4983,-4978,-4972,
+-4966,-4960,-4954,-4948,-4943,-4940,-4937,-4935,-4933,-4930,-4927,-4923,-4918,-4912,-4906,-4898,-4890,-4882,-4875,-4868,-4864,
+-4860,-4858,-4857,-4855,-4852,-4847,-4839,-4830,-4820,-4809,-4799,-4789,-4780,-4770,-4761,-4751,-4740,-4730,-4719,-4710,-4701,
+-4694,-4688,-4682,-4677,-4671,-4665,-4660,-4655,-4650,-4647,-4644,-4641,-4637,-4631,-4624,-4615,-4604,-4591,-4579,-4566,-4554,
+-4542,-4530,-4517,-4504,-4489,-4473,-4456,-4439,-4423,-4407,-4393,-4381,-4370,-4360,-4351,-4341,-4331,-4320,-4307,-4293,-4278,
+-4263,-4248,-4234,-4222,-4211,-4203,-4198,-4194,-4193,-4193,-4194,-4195,-4196,-4197,-4195,-4192,-4186,-4178,-4167,-4156,-4143,
+-4131,-4119,-4109,-4099,-4091,-4083,-4075,-4068,-4062,-4057,-4054,-4052,-4052,-4053,-4054,-4054,-4053,-4049,-4041,-4030,-4017,
+-4002,-3986,-3970,-3955,-3942,-3929,-3918,-3906,-3894,-3882,-3868,-3852,-3835,-3816,-3796,-3776,-3755,-3735,-3715,-3696,-3678,
+-3660,-3642,-3623,-3604,-3584,-3564,-3545,-3527,-3511,-3496,-3484,-3472,-3461,-3449,-3436,-3422,-3406,-3390,-3373,-3358,-3345,
+-3335,-3326,-3319,-3312,-3304,-3294,-3283,-3270,-3256,-3243,-3232,-3222,-3215,-3208,-3201,-3194,-3184,-3173,-3160,-3146,-3133,
+-3120,-3109,-3099,-3090,-3081,-3071,-3061,-3051,-3042,-3034,-3027,-3021,-3015,-3008,-3001,-2991,-2979,-2965,-2950,-2935,-2920,
+-2905,-2890,-2875,-2860,-2845,-2829,-2812,-2796,-2780,-2764,-2749,-2733,-2717,-2702,-2686,-2670,-2656,-2642,-2630,-2619,-2608,
+-2597,-2586,-2574,-2563,-2551,-2540,-2530,-2519,-2509,-2497,-2484,-2469,-2453,-2438,-2423,-2410,-2399,-2389,-2380,-2370,-2360,
+-2348,-2337,-2326,-2316,-2307,-2300,-2292,-2283,-2271,-2258,-2243,-2228,-2215,-2206,-2199,-2193,-2186,-2174,-2155,-2130,-2101,
+-2070,-2043,-2021,-2006,-1994,-1981,-1962,-1932,-1890,-1840,-1786,-1737,-1700,-1681,-1679,-1690,-1705,-1715,-1713,-1692,-1655,
+-1607,-1556,-1512,-1480,-1463,-1461,-1466,-1473,-1475,-1468,-1450,-1425,-1395,-1366,-1339,-1317,-1298,-1281,-1262,-1240,-1214,
+-1188,-1161,-1136,-1115,-1097,-1081,-1066,-1050,-1032,-1011,-988,-964,-939,-914,-890,-865,-839,-812,-783,-752,-720,
+-689,-659,-630,-602,-575,-549,-523,-496,-469,-440,-411,-380,-348,-314,-280,-244,-207,-170,-133,-98,-63,
+-30,0,30,57,82,106,130,154,179,207,237,269,302,335,367,397,426,454,481,510,542,
+579,620,667,719,776,837,902,968,1034,1097,1154,1205,1247,1282,1311,1336,1359,1383,1408,1433,1457,
+1478,1495,1508,1520,1533,1549,1573,1603,1639,1676,1711,1739,1757,1767,1769,1767,1767,1770,1779,1793,1810,
+1825,1837,1843,1842,1837,1828,1818,1810,1803,1800,1802,1808,1820,1838,1860,1882,1902,1913,1908,1885,1843,
+1783,1713,1639,1572,1519,1483,1463,1457,1457,1458,1453,1440,1419,1392,1364,1338,1317,1304,1297,1296,1301,
+1310,1324,1342,1363,1388,1414,1437,1456,1468,1473,1469,1460,1448,1434,1421,1410,1402,1397,1394,1393,1395,
+1399,1405,1413,1422,1429,1435,1437,1436,1433,1428,1423,1420,1419,1419,1420,1422,1422,1422,1420,1419,1417,
+1416,1416,1415,1414,1412,1408,1402,1396,1388,1380,1370,1359,1346,1329,1311,1293,1276,1261,1252,1248,1247,
+1249,1251,1250,1245,1235,1222,1206,1191,1178,1169,1163,1160,1158,1156,1153,1148,1142,1135,1128,1120,1113,
+1107,1100,1093,1086,1079,1072,1065,1060,1054,1049,1045,1040,1036,1032,1028,1025,1022,1018,1015,1010,1004,
+998,992,987,984,982,980,978,975,970,963,955,945,936,927,920,914,908,902,895,888,881,
+874,869,866,865,865,865,865,865,864,864,863,864,866,868,870,871,870,867,863,859,856,
+854,854,856,858,861,864,867,870,874,878,884,890,897,903,909,914,918,922,928,936,947,
+959,972,986,1000,1011,1021,1030,1037,1044,1051,1058,1066,1074,1083,1093,1104,1115,1126,1138,1149,1161,
+1173,1186,1202,1222,1245,1273,1305,1340,1377,1356,1393,1430,1466,1502,1537,1570,1601,1629,1652,1670,1680,
+1684,1681,1673,1663,1652,1642,1635,1630,1629,1629,1629,1630,1630,1631,1631,1632,1634,1638,1643,1649,1656,
+1664,1671,1679,1688,1699,1710,1723,1736,1749,1762,1774,1784,1794,1803,1813,1824,1836,1850,1865,1881,1896,
+1911,1925,1936,1944,1948,1949,1944,1935,1920,1903,1882,1862,1845,1832,1825,1825,1831,1840,1851,1860,1866,
+1867,1863,1857,1851,1846,1844,1844,1848,1853,1857,1861,1863,1865,1867,1871,1876,1883,1891,1897,1900,1901,
+1899,1896,1894,1894,1897,1903,1910,1918,1923,1926,1928,1929,1933,1940,1951,1966,1983,1999,2013,2024,2034,
+2043,2054,2068,2082,2095,2102,2098,2083,2057,2024,1992,1970,1963,1978,2015,2070,2134,2198,2255,2298,2325,
+2339,2343,2343,2346,2354,2368,2387,2409,2430,2448,2462,2473,2482,2490,2498,2508,2518,2528,2537,2546,2554,
+2562,2571,2582,2596,2611,2629,2647,2665,2682,2697,2709,2719,2727,2732,2736,2740,2743,2748,2754,2762,2772,
+2785,2800,2816,2833,2851,2870,2891,2915,2941,2970,3000,3029,3055,3073,3082,3081,3070,3052,3029,3007,2988,
+2976,2971,2972,2978,2987,2997,3009,3024,3043,3067,3096,3127,3158,3184,3201,3206,3198,3180,3157,3134,3115,
+3102,3097,3095,3092,3085,3069,3045,3013,2978,2944,2914,2891,2874,2860,2845,2827,2803,2774,2741,2707,2676,
+2651,2632,2620,2612,2609,2608,2609,2614,2622,2636,2654,2675,2696,2714,2725,2727,2718,2699,2672,2639,2606,
+2574,2547,2526,2511,2502,2498,2497,2497,2497,2494,2487,2475,2458,2436,2409,2379,2346,2313,2281,2250,2221,
+2194,2168,2145,2123,2103,2086,2072,2060,2051,2044,2037,2030,2021,2010,1996,1980,1963,1944,1926,1908,1892,
+1878,1864,1851,1838,1823,1806,1786,1762,1733,1700,1665,1628,1591,1557,1527,1502,1482,1465,1451,1438,1423,
+1407,1389,1373,1358,1348,1343,1341,1342,1343,1342,1335,1322,1303,1280,1254,1228,1204,1181,1159,1138,1115,
+1091,1064,1035,1003,972,940,908,876,845,815,786,760,735,713,694,676,657,635,610,580,546,
+511,475,443,414,391,372,355,338,318,296,270,241,211,182,155,131,109,89,69,49,28,
+5,-19,-43,-67,-89,-109,-126,-140,-152,-161,-170,-180,-192,-209,-233,-265,-307,-358,-417,-481,-547,
+-611,-668,-717,-754,-782,-801,-814,-827,-842,-863,-891,-926,-965,-1004,-1041,-1072,-1095,-1112,-1126,-1141,-1161,
+-1189,-1228,-1278,-1335,-1396,-1458,-1517,-1571,-1619,-1663,-1705,-1744,-1782,-1820,-1855,-1886,-1912,-1933,-1948,-1960,-1970,
+-1979,-1987,-1996,-2003,-2007,-2007,-2002,-1994,-1984,-1977,-1975,-1983,-2003,-2036,-2081,-2135,-2196,-2258,-2318,-2374,-2426,
+-2473,-2519,-2566,-2617,-2673,-2733,-2797,-2861,-2922,-2977,-3022,-3057,-3083,-3100,-3112,-3121,-3130,-3139,-3150,-3163,-3176,
+-3189,-3199,-3205,-3207,-3206,-3201,-3195,-3190,-3188,-3193,-3205,-3225,-3251,-3282,-3313,-3341,-3365,-3382,-3395,-3405,-3416,
+-3430,-3448,-3468,-3489,-3507,-3519,-3522,-3519,-3511,-3505,-3506,-3518,-3542,-3578,-3621,-3666,-3708,-3742,-3766,-3782,-3793,
+-3802,-3815,-3833,-3857,-3886,-3918,-3950,-3982,-4013,-4043,-4074,-4106,-4139,-4172,-4204,-4234,-4260,-4284,-4305,-4326,-4347,
+-4368,-4389,-4409,-4425,-4437,-4444,-4447,-4446,-4445,-4445,-4447,-4452,-4459,-4468,-4478,-4488,-4497,-4506,-4516,-4526,-4535,
+-4544,-4551,-4557,-4561,-4566,-4571,-4580,-4592,-4609,-4627,-4646,-4662,-4673,-4677,-4675,-4667,-4655,-4642,-4630,-4620,-4612,
+-4606,-4602,-4600,-4598,-4596,-4595,-4593,-4589,-4583,-4572,-4557,-4537,-4515,-4491,-4470,-4452,-4439,-4431,-4428,-4427,-4428,
+-4428,-4427,-4426,-4425,-4427,-4431,-4439,-4450,-4462,-4474,-4486,-4495,-4501,-4506,-4510,-4513,-4515,-4517,-4519,-4519,-4518,
+-4516,-4515,-4516,-4520,-4528,-4540,-4556,-4573,-4592,-4610,-4626,-4642,-4656,-4670,-4684,-4700,-4716,-4732,-4748,-4762,-4776,
+-4788,-4801,-4815,-4831,-4850,-4871,-4894,-4917,-4939,-4957,-4972,-4983,-4991,-5000,-5010,-5022,-5037,-5055,-5073,-5091,-5107,
+-5122,-5135,-5148,-5163,-5182,-5204,-5228,-5253,-5275,-5292,-5301,-5303,-5297,-5287,-5275,-5265,-5258,-5257,-5260,-5268,-5278,
+-5289,-5298,-5305,-5309,-5309,-5306,-5299,-5291,-5280,-5268,-5255,-5243,-5230,-5219,-5208,-5198,-5189,-5180,-5172,-5166,-5161,
+-5159,-5158,-5160,-5164,-5168,-5172,-5175,-5177,-5178,-5179,-5180,-5181,-5182,-5183,-5185,-5186,-5186,-5186,-5186,-5185,-5185,
+-5184,-5182,-5179,-5175,-5170,-5164,-5158,-5153,-5149,-5146,-5144,-5143,-5142,-5139,-5135,-5130,-5123,-5116,-5109,-5102,-5096,
+-5091,-5087,-5084,-5082,-5079,-5077,-5075,-5073,-5070,-5065,-5059,-5052,-5044,-5035,-5027,-5021,-5015,-5012,-5009,-5006,-5003,
+-5000,-4995,-4990,-4985,-4980,-4975,-4970,-4964,-4959,-4952,-4945,-4938,-4931,-4925,-4920,-4916,-4913,-4911,-4908,-4905,-4899,
+-4892,-4884,-4875,-4865,-4856,-4848,-4840,-4832,-4823,-4814,-4803,-4792,-4779,-4767,-4754,-4742,-4731,-4721,-4713,-4706,-4701,
+-4697,-4695,-4694,-4693,-4692,-4690,-4686,-4679,-4671,-4662,-4650,-4638,-4626,-4613,-4601,-4588,-4574,-4560,-4545,-4528,-4511,
+-4492,-4474,-4457,-4441,-4427,-4415,-4405,-4396,-4387,-4377,-4366,-4353,-4338,-4322,-4305,-4288,-4273,-4259,-4247,-4238,-4230,
+-4225,-4222,-4220,-4220,-4221,-4222,-4224,-4224,-4223,-4219,-4213,-4205,-4196,-4185,-4175,-4165,-4156,-4148,-4141,-4133,-4125,
+-4117,-4109,-4101,-4095,-4090,-4087,-4085,-4084,-4084,-4081,-4078,-4071,-4062,-4050,-4037,-4022,-4007,-3992,-3977,-3963,-3950,
+-3936,-3922,-3906,-3890,-3872,-3853,-3833,-3811,-3790,-3770,-3749,-3730,-3711,-3693,-3675,-3656,-3637,-3617,-3597,-3578,-3561,
+-3544,-3530,-3517,-3506,-3494,-3482,-3470,-3456,-3442,-3427,-3413,-3399,-3388,-3377,-3368,-3358,-3349,-3338,-3326,-3314,-3302,
+-3290,-3280,-3272,-3265,-3258,-3251,-3242,-3231,-3218,-3204,-3190,-3176,-3164,-3153,-3144,-3135,-3127,-3118,-3109,-3099,-3090,
+-3081,-3072,-3065,-3057,-3048,-3039,-3028,-3015,-3001,-2986,-2971,-2956,-2941,-2927,-2911,-2895,-2879,-2861,-2844,-2827,-2811,
+-2796,-2782,-2767,-2752,-2736,-2718,-2700,-2682,-2665,-2649,-2635,-2622,-2611,-2599,-2588,-2577,-2566,-2555,-2546,-2537,-2529,
+-2520,-2509,-2497,-2483,-2468,-2453,-2438,-2425,-2414,-2405,-2396,-2387,-2378,-2368,-2358,-2349,-2340,-2332,-2324,-2315,-2305,
+-2292,-2276,-2260,-2245,-2233,-2224,-2218,-2213,-2206,-2193,-2173,-2147,-2116,-2085,-2058,-2037,-2023,-2012,-2000,-1981,-1951,
+-1910,-1860,-1808,-1762,-1729,-1714,-1715,-1728,-1743,-1749,-1739,-1708,-1658,-1597,-1534,-1480,-1444,-1429,-1433,-1449,-1469,
+-1485,-1490,-1481,-1461,-1433,-1402,-1372,-1347,-1326,-1307,-1289,-1269,-1245,-1219,-1192,-1165,-1141,-1120,-1101,-1083,-1066,
+-1047,-1026,-1005,-982,-960,-939,-918,-897,-876,-852,-825,-796,-764,-730,-697,-665,-634,-606,-580,-556,-533,
+-511,-488,-463,-437,-408,-376,-342,-305,-267,-228,-189,-151,-114,-79,-46,-15,14,41,68,94,120,
+147,175,206,237,270,303,335,367,398,429,461,494,531,573,619,670,726,786,848,911,973,
+1033,1087,1137,1180,1218,1251,1282,1311,1339,1367,1394,1417,1436,1450,1459,1466,1475,1488,1511,1544,1586,
+1635,1684,1728,1760,1779,1784,1777,1762,1746,1732,1723,1720,1722,1726,1731,1733,1732,1728,1722,1715,1709,
+1706,1707,1713,1726,1745,1770,1798,1824,1843,1848,1835,1802,1751,1687,1618,1553,1502,1469,1455,1456,1466,
+1475,1477,1468,1446,1415,1379,1344,1314,1291,1276,1267,1263,1260,1260,1263,1270,1283,1302,1326,1352,1377,
+1397,1410,1416,1415,1410,1401,1393,1384,1377,1371,1365,1360,1356,1354,1354,1357,1362,1369,1375,1381,1384,
+1385,1384,1382,1380,1379,1380,1382,1384,1385,1386,1385,1384,1382,1379,1375,1372,1367,1361,1355,1349,1342,
+1336,1330,1323,1314,1303,1288,1270,1251,1231,1213,1199,1191,1188,1188,1190,1190,1187,1180,1169,1155,1140,
+1126,1115,1106,1100,1095,1090,1084,1077,1068,1060,1051,1044,1039,1034,1030,1026,1021,1016,1009,1002,995,
+989,985,981,979,979,979,979,979,977,975,971,966,961,955,949,945,942,939,937,934,930,
+924,917,908,899,891,883,876,869,863,856,849,841,834,827,823,820,819,819,820,821,822,
+823,824,826,828,830,833,833,833,830,826,822,819,817,818,821,826,831,836,839,842,844,
+846,848,853,858,865,871,878,885,892,900,909,920,933,948,963,977,990,1000,1009,1015,1021,
+1027,1034,1041,1050,1060,1071,1081,1092,1102,1112,1122,1132,1142,1153,1166,1182,1202,1226,1253,1285,1319,
+1356,1332,1368,1405,1440,1473,1504,1533,1558,1579,1596,1607,1614,1615,1612,1605,1598,1591,1585,1582,1580,
+1580,1580,1580,1580,1580,1580,1583,1588,1597,1608,1621,1635,1648,1659,1667,1674,1680,1687,1696,1707,1720,
+1735,1751,1767,1782,1797,1811,1825,1839,1853,1869,1883,1897,1908,1917,1923,1926,1926,1925,1922,1917,1910,
+1900,1887,1871,1853,1835,1819,1806,1798,1795,1797,1802,1809,1814,1818,1820,1820,1819,1819,1819,1821,1824,
+1827,1830,1832,1833,1833,1834,1837,1840,1845,1849,1853,1855,1855,1854,1852,1852,1853,1857,1862,1868,1873,
+1877,1879,1882,1885,1891,1901,1914,1929,1945,1960,1973,1985,1996,2008,2021,2036,2050,2061,2063,2057,2040,
+2016,1991,1973,1967,1980,2012,2062,2121,2183,2237,2279,2304,2315,2315,2312,2311,2316,2329,2348,2369,2390,
+2406,2417,2422,2424,2426,2429,2435,2444,2455,2467,2478,2488,2496,2504,2513,2523,2535,2548,2564,2580,2597,
+2614,2631,2648,2665,2682,2697,2711,2722,2729,2735,2739,2744,2750,2760,2772,2787,2805,2825,2847,2871,2897,
+2925,2956,2988,3018,3045,3063,3071,3069,3057,3038,3018,3000,2990,2988,2994,3006,3022,3038,3053,3067,3083,
+3104,3132,3169,3212,3258,3300,3332,3349,3349,3334,3308,3276,3244,3217,3197,3181,3167,3150,3128,3098,3063,
+3024,2986,2952,2923,2900,2879,2858,2834,2805,2771,2734,2698,2665,2639,2619,2606,2598,2593,2589,2587,2587,
+2589,2597,2609,2626,2646,2664,2679,2685,2682,2669,2647,2618,2585,2552,2521,2495,2475,2461,2453,2451,2451,
+2452,2451,2447,2437,2422,2400,2373,2343,2311,2280,2250,2223,2198,2175,2153,2132,2112,2093,2076,2061,2050,
+2040,2031,2021,2010,1996,1979,1960,1939,1918,1899,1882,1868,1854,1841,1827,1810,1790,1767,1740,1709,1676,
+1640,1603,1567,1533,1504,1480,1464,1455,1452,1455,1458,1461,1460,1455,1444,1431,1416,1402,1391,1382,1374,
+1366,1355,1339,1317,1290,1260,1230,1201,1177,1157,1141,1126,1112,1095,1074,1048,1018,985,950,914,880,
+848,818,793,772,754,739,726,711,693,670,639,602,560,514,467,423,382,346,314,284,254,
+223,191,160,130,104,82,65,52,41,28,13,-7,-31,-58,-86,-110,-131,-146,-156,-162,-167,
+-172,-179,-189,-202,-218,-236,-257,-283,-315,-355,-403,-460,-522,-587,-649,-704,-749,-782,-806,-821,-835,
+-850,-872,-901,-938,-979,-1019,-1056,-1084,-1104,-1116,-1124,-1132,-1145,-1167,-1199,-1240,-1288,-1339,-1389,-1437,-1481,
+-1523,-1563,-1605,-1649,-1695,-1743,-1790,-1834,-1872,-1905,-1932,-1954,-1974,-1993,-2012,-2029,-2044,-2054,-2057,-2053,-2041,
+-2025,-2010,-1999,-1998,-2010,-2036,-2076,-2126,-2180,-2235,-2286,-2330,-2367,-2400,-2432,-2467,-2509,-2560,-2619,-2684,-2750,
+-2813,-2869,-2913,-2945,-2966,-2979,-2987,-2995,-3006,-3020,-3038,-3058,-3079,-3098,-3112,-3120,-3122,-3120,-3115,-3111,-3110,
+-3115,-3129,-3152,-3183,-3219,-3256,-3290,-3320,-3342,-3356,-3366,-3375,-3386,-3404,-3427,-3456,-3487,-3515,-3536,-3548,-3550,
+-3547,-3542,-3541,-3550,-3569,-3600,-3637,-3675,-3710,-3736,-3753,-3761,-3765,-3768,-3775,-3789,-3810,-3838,-3870,-3903,-3935,
+-3965,-3994,-4022,-4051,-4081,-4110,-4139,-4167,-4191,-4212,-4230,-4247,-4263,-4280,-4298,-4316,-4334,-4350,-4364,-4376,-4386,
+-4395,-4404,-4415,-4427,-4441,-4455,-4470,-4485,-4499,-4514,-4528,-4543,-4556,-4567,-4576,-4583,-4587,-4591,-4595,-4601,-4610,
+-4623,-4639,-4655,-4669,-4679,-4684,-4682,-4675,-4665,-4652,-4638,-4626,-4616,-4608,-4603,-4601,-4602,-4608,-4617,-4628,-4640,
+-4650,-4654,-4651,-4639,-4619,-4594,-4566,-4539,-4517,-4502,-4494,-4492,-4493,-4497,-4500,-4501,-4501,-4501,-4501,-4505,-4511,
+-4521,-4533,-4546,-4558,-4569,-4578,-4585,-4591,-4595,-4597,-4599,-4600,-4600,-4600,-4601,-4602,-4606,-4612,-4621,-4634,-4648,
+-4662,-4677,-4690,-4702,-4713,-4724,-4736,-4749,-4763,-4778,-4794,-4809,-4823,-4836,-4849,-4861,-4876,-4893,-4913,-4937,-4962,
+-4987,-5010,-5030,-5046,-5058,-5066,-5073,-5080,-5089,-5099,-5113,-5128,-5144,-5161,-5179,-5198,-5218,-5239,-5262,-5286,-5310,
+-5333,-5352,-5365,-5373,-5375,-5371,-5364,-5354,-5344,-5336,-5330,-5329,-5332,-5339,-5349,-5362,-5374,-5386,-5395,-5399,-5398,
+-5392,-5381,-5366,-5349,-5329,-5310,-5290,-5271,-5253,-5237,-5222,-5210,-5201,-5195,-5193,-5194,-5198,-5203,-5208,-5213,-5218,
+-5221,-5224,-5227,-5230,-5233,-5236,-5240,-5242,-5244,-5245,-5245,-5245,-5244,-5243,-5242,-5240,-5237,-5233,-5229,-5224,-5218,
+-5213,-5209,-5206,-5203,-5201,-5199,-5196,-5193,-5188,-5182,-5176,-5169,-5162,-5155,-5149,-5144,-5141,-5139,-5139,-5139,-5139,
+-5138,-5135,-5130,-5123,-5114,-5105,-5096,-5089,-5083,-5080,-5078,-5076,-5074,-5071,-5067,-5062,-5057,-5052,-5049,-5045,-5042,
+-5038,-5033,-5026,-5017,-5007,-4996,-4985,-4976,-4968,-4963,-4958,-4954,-4950,-4945,-4939,-4933,-4926,-4920,-4914,-4909,-4903,
+-4897,-4890,-4881,-4871,-4860,-4848,-4836,-4823,-4812,-4801,-4791,-4782,-4774,-4766,-4759,-4753,-4748,-4743,-4739,-4735,-4731,
+-4725,-4717,-4707,-4696,-4683,-4670,-4656,-4643,-4630,-4616,-4603,-4589,-4573,-4556,-4537,-4519,-4501,-4485,-4471,-4460,-4450,
+-4441,-4433,-4423,-4411,-4398,-4383,-4367,-4351,-4335,-4321,-4308,-4296,-4284,-4274,-4265,-4257,-4251,-4247,-4246,-4247,-4249,
+-4251,-4253,-4252,-4249,-4243,-4236,-4227,-4218,-4210,-4202,-4195,-4188,-4180,-4172,-4162,-4152,-4141,-4131,-4122,-4116,-4111,
+-4108,-4106,-4103,-4100,-4095,-4087,-4077,-4066,-4052,-4037,-4022,-4006,-3990,-3973,-3957,-3939,-3921,-3903,-3883,-3862,-3841,
+-3820,-3799,-3778,-3758,-3739,-3720,-3702,-3683,-3665,-3646,-3628,-3610,-3593,-3577,-3563,-3550,-3537,-3525,-3512,-3500,-3487,
+-3474,-3462,-3450,-3438,-3427,-3416,-3405,-3394,-3381,-3369,-3356,-3344,-3333,-3324,-3317,-3310,-3303,-3296,-3286,-3275,-3261,
+-3247,-3232,-3218,-3206,-3195,-3186,-3178,-3171,-3162,-3154,-3144,-3135,-3125,-3116,-3107,-3098,-3088,-3077,-3064,-3050,-3035,
+-3019,-3004,-2990,-2976,-2962,-2948,-2933,-2915,-2897,-2878,-2859,-2841,-2825,-2810,-2796,-2781,-2766,-2749,-2731,-2712,-2694,
+-2676,-2661,-2648,-2637,-2626,-2616,-2605,-2594,-2583,-2572,-2562,-2553,-2544,-2535,-2526,-2515,-2503,-2489,-2476,-2464,-2453,
+-2444,-2436,-2428,-2419,-2410,-2399,-2387,-2375,-2364,-2355,-2346,-2337,-2326,-2314,-2299,-2284,-2269,-2256,-2246,-2238,-2232,
+-2223,-2209,-2190,-2165,-2135,-2105,-2077,-2055,-2038,-2026,-2013,-1995,-1970,-1937,-1898,-1858,-1824,-1801,-1793,-1796,-1806,
+-1813,-1809,-1786,-1742,-1681,-1609,-1539,-1481,-1444,-1429,-1436,-1457,-1483,-1505,-1516,-1512,-1494,-1467,-1434,-1403,-1374,
+-1351,-1331,-1314,-1295,-1275,-1253,-1228,-1204,-1180,-1158,-1138,-1119,-1099,-1079,-1057,-1035,-1012,-990,-969,-949,-929,
+-909,-887,-863,-836,-806,-774,-741,-708,-677,-648,-620,-595,-571,-548,-525,-501,-475,-448,-418,-386,-352,
+-317,-282,-248,-213,-180,-146,-113,-79,-45,-11,22,56,89,120,150,179,208,236,265,296,329,
+365,404,447,492,541,592,646,702,759,817,874,930,981,1029,1072,1110,1145,1177,1208,1239,1272,
+1304,1336,1365,1389,1406,1416,1422,1427,1436,1452,1479,1518,1566,1619,1669,1712,1742,1755,1754,1740,1719,
+1695,1672,1653,1639,1629,1623,1619,1616,1613,1611,1611,1612,1615,1621,1630,1643,1661,1684,1710,1738,1763,
+1780,1784,1770,1737,1687,1627,1565,1509,1467,1442,1435,1440,1450,1458,1456,1441,1415,1380,1343,1308,1280,
+1260,1247,1238,1231,1223,1215,1208,1204,1207,1217,1235,1258,1283,1307,1326,1340,1348,1351,1351,1350,1347,
+1343,1338,1330,1321,1311,1302,1296,1293,1294,1299,1306,1313,1318,1321,1322,1322,1320,1320,1320,1322,1326,
+1329,1333,1335,1335,1332,1328,1322,1314,1304,1293,1282,1272,1263,1257,1253,1251,1249,1245,1238,1227,1213,
+1196,1178,1161,1148,1139,1133,1130,1127,1124,1118,1110,1099,1087,1075,1064,1054,1046,1038,1030,1021,1011,
+1001,991,983,976,972,969,968,966,964,961,956,950,944,938,934,931,930,930,931,931,932,
+931,929,926,922,917,912,907,902,898,893,889,883,878,872,866,859,853,846,840,833,825,
+816,807,798,789,782,777,774,773,774,776,778,780,783,785,788,791,795,799,803,805,805,
+803,800,797,795,794,796,800,805,810,814,816,818,818,819,820,823,828,834,841,849,858,
+868,879,891,905,919,934,949,962,972,981,987,993,998,1005,1012,1022,1032,1044,1055,1066,1077,
+1087,1096,1105,1115,1124,1135,1148,1164,1182,1205,1232,1262,1296,1332,1315,1350,1384,1416,1444,1469,1490,
+1507,1520,1529,1535,1537,1537,1536,1534,1532,1532,1534,1537,1540,1544,1547,1548,1548,1548,1549,1552,1559,
+1570,1583,1598,1613,1626,1635,1642,1646,1650,1655,1663,1675,1691,1710,1731,1753,1773,1793,1812,1830,1848,
+1866,1882,1896,1906,1912,1912,1908,1900,1891,1881,1873,1867,1861,1855,1847,1836,1821,1803,1785,1768,1755,
+1747,1745,1748,1755,1764,1773,1780,1785,1789,1790,1791,1792,1794,1795,1797,1798,1798,1799,1799,1799,1800,
+1800,1800,1799,1798,1798,1799,1801,1805,1811,1818,1825,1832,1838,1842,1844,1847,1852,1859,1868,1880,1894,
+1908,1923,1936,1950,1964,1979,1994,2008,2018,2022,2017,2003,1983,1962,1947,1943,1958,1991,2042,2104,2167,
+2224,2267,2293,2301,2297,2288,2281,2281,2291,2309,2332,2354,2372,2382,2385,2381,2375,2371,2371,2376,2386,
+2399,2413,2426,2437,2447,2457,2466,2477,2490,2503,2516,2529,2542,2555,2571,2589,2609,2633,2657,2679,2698,
+2713,2722,2728,2732,2736,2743,2755,2771,2792,2815,2841,2867,2894,2922,2950,2976,3000,3019,3031,3036,3033,
+3025,3016,3010,3013,3025,3049,3080,3115,3149,3177,3197,3211,3224,3240,3264,3299,3345,3397,3450,3494,3522,
+3530,3517,3486,3443,3394,3348,3306,3272,3243,3217,3190,3161,3128,3093,3057,3022,2990,2961,2933,2905,2874,
+2840,2803,2764,2727,2694,2666,2645,2629,2617,2607,2597,2587,2578,2571,2566,2566,2571,2578,2588,2597,2603,
+2603,2597,2585,2566,2543,2517,2490,2465,2443,2425,2414,2408,2407,2409,2411,2410,2403,2390,2369,2342,2311,
+2278,2247,2218,2194,2173,2155,2138,2122,2104,2087,2068,2051,2035,2019,2005,1991,1976,1960,1943,1925,1906,
+1887,1870,1853,1836,1817,1796,1772,1743,1712,1679,1645,1612,1581,1554,1529,1507,1489,1476,1468,1466,1470,
+1480,1494,1509,1522,1531,1533,1529,1518,1503,1485,1467,1450,1433,1414,1393,1366,1335,1300,1263,1227,1196,
+1171,1153,1142,1134,1127,1116,1100,1077,1046,1009,969,927,887,851,820,794,774,758,743,728,710,
+688,659,623,581,534,485,436,387,342,298,257,216,177,139,103,73,49,33,24,19,15,
+9,-3,-25,-56,-93,-131,-167,-194,-210,-214,-209,-198,-185,-176,-173,-178,-188,-204,-223,-244,-267,
+-294,-327,-368,-419,-478,-543,-610,-674,-732,-781,-820,-853,-881,-910,-943,-982,-1026,-1072,-1117,-1158,-1190,
+-1214,-1231,-1242,-1251,-1263,-1279,-1300,-1326,-1354,-1384,-1412,-1438,-1463,-1490,-1519,-1552,-1591,-1634,-1679,-1724,-1767,
+-1807,-1842,-1874,-1904,-1936,-1969,-2004,-2039,-2073,-2101,-2121,-2132,-2133,-2128,-2121,-2116,-2118,-2130,-2154,-2187,-2227,
+-2269,-2309,-2342,-2368,-2387,-2403,-2419,-2440,-2469,-2509,-2558,-2613,-2670,-2723,-2769,-2804,-2828,-2844,-2854,-2863,-2873,
+-2888,-2908,-2933,-2959,-2986,-3009,-3029,-3043,-3052,-3059,-3066,-3074,-3088,-3107,-3134,-3168,-3207,-3250,-3292,-3331,-3364,
+-3390,-3409,-3422,-3434,-3447,-3464,-3487,-3514,-3544,-3573,-3597,-3615,-3625,-3630,-3631,-3634,-3642,-3656,-3676,-3700,-3725,
+-3748,-3765,-3776,-3782,-3786,-3792,-3802,-3818,-3840,-3868,-3899,-3930,-3960,-3989,-4016,-4042,-4068,-4094,-4119,-4142,-4162,
+-4178,-4189,-4196,-4200,-4203,-4206,-4211,-4219,-4229,-4242,-4257,-4273,-4291,-4311,-4332,-4356,-4380,-4404,-4427,-4450,-4470,
+-4489,-4506,-4522,-4537,-4550,-4561,-4569,-4575,-4577,-4578,-4579,-4582,-4587,-4595,-4606,-4618,-4629,-4637,-4640,-4639,-4633,
+-4623,-4611,-4598,-4587,-4577,-4570,-4567,-4569,-4577,-4591,-4614,-4642,-4674,-4706,-4733,-4751,-4757,-4750,-4731,-4704,-4674,
+-4645,-4621,-4606,-4599,-4599,-4602,-4605,-4607,-4605,-4600,-4594,-4588,-4586,-4587,-4594,-4604,-4616,-4630,-4642,-4653,-4661,
+-4668,-4672,-4676,-4678,-4680,-4681,-4682,-4683,-4685,-4688,-4694,-4702,-4712,-4724,-4737,-4749,-4760,-4770,-4779,-4788,-4797,
+-4807,-4818,-4831,-4846,-4861,-4876,-4891,-4906,-4922,-4939,-4958,-4980,-5003,-5027,-5051,-5074,-5093,-5108,-5120,-5128,-5134,
+-5140,-5146,-5155,-5166,-5181,-5197,-5215,-5235,-5255,-5275,-5295,-5316,-5336,-5356,-5375,-5392,-5407,-5417,-5424,-5425,-5423,
+-5416,-5408,-5400,-5394,-5391,-5394,-5403,-5416,-5432,-5449,-5464,-5476,-5482,-5481,-5476,-5465,-5450,-5433,-5415,-5396,-5376,
+-5355,-5335,-5315,-5297,-5282,-5270,-5262,-5259,-5259,-5262,-5267,-5272,-5277,-5282,-5285,-5289,-5292,-5295,-5298,-5301,-5303,
+-5304,-5304,-5304,-5303,-5301,-5300,-5299,-5299,-5298,-5296,-5293,-5289,-5284,-5277,-5271,-5264,-5258,-5252,-5247,-5244,-5241,
+-5238,-5235,-5232,-5228,-5222,-5216,-5209,-5203,-5198,-5194,-5192,-5192,-5193,-5194,-5194,-5192,-5187,-5181,-5172,-5164,-5156,
+-5149,-5145,-5142,-5140,-5138,-5136,-5133,-5130,-5126,-5123,-5120,-5118,-5115,-5112,-5108,-5101,-5091,-5079,-5066,-5052,-5039,
+-5028,-5019,-5011,-5006,-5001,-4997,-4992,-4987,-4982,-4976,-4971,-4966,-4960,-4955,-4948,-4942,-4935,-4927,-4920,-4913,-4906,
+-4899,-4892,-4884,-4875,-4864,-4852,-4839,-4827,-4815,-4805,-4796,-4789,-4783,-4777,-4770,-4761,-4749,-4736,-4722,-4708,-4694,
+-4682,-4671,-4660,-4648,-4635,-4620,-4603,-4584,-4565,-4547,-4531,-4516,-4505,-4494,-4485,-4475,-4465,-4453,-4441,-4427,-4414,
+-4401,-4388,-4376,-4363,-4349,-4334,-4319,-4305,-4292,-4283,-4277,-4276,-4278,-4283,-4287,-4290,-4291,-4288,-4282,-4274,-4265,
+-4255,-4247,-4239,-4232,-4225,-4218,-4209,-4199,-4187,-4175,-4164,-4153,-4145,-4138,-4133,-4129,-4126,-4122,-4117,-4110,-4101,
+-4090,-4076,-4061,-4045,-4027,-4009,-3990,-3970,-3950,-3929,-3908,-3887,-3866,-3844,-3823,-3802,-3781,-3761,-3742,-3723,-3704,
+-3686,-3669,-3652,-3636,-3621,-3607,-3593,-3580,-3567,-3554,-3541,-3528,-3515,-3503,-3490,-3479,-3467,-3456,-3445,-3434,-3422,
+-3410,-3397,-3385,-3375,-3365,-3356,-3348,-3340,-3332,-3322,-3310,-3298,-3284,-3271,-3259,-3249,-3240,-3232,-3225,-3217,-3208,
+-3198,-3187,-3176,-3165,-3155,-3146,-3137,-3128,-3118,-3105,-3091,-3075,-3059,-3043,-3028,-3015,-3002,-2988,-2974,-2958,-2940,
+-2920,-2900,-2880,-2861,-2844,-2828,-2814,-2798,-2782,-2764,-2746,-2727,-2709,-2694,-2681,-2670,-2661,-2653,-2644,-2634,-2622,
+-2610,-2598,-2587,-2577,-2568,-2560,-2550,-2540,-2529,-2517,-2505,-2495,-2486,-2479,-2472,-2465,-2457,-2446,-2433,-2419,-2404,
+-2391,-2379,-2370,-2361,-2352,-2342,-2329,-2315,-2301,-2286,-2273,-2262,-2252,-2241,-2226,-2207,-2183,-2155,-2126,-2097,-2073,
+-2053,-2037,-2023,-2008,-1990,-1968,-1944,-1920,-1900,-1887,-1882,-1884,-1888,-1886,-1872,-1841,-1793,-1732,-1663,-1597,-1542,
+-1506,-1490,-1492,-1507,-1526,-1541,-1547,-1540,-1521,-1493,-1460,-1428,-1399,-1375,-1355,-1338,-1321,-1304,-1285,-1264,-1243,
+-1222,-1202,-1182,-1162,-1143,-1122,-1099,-1076,-1052,-1027,-1003,-980,-957,-933,-909,-884,-858,-830,-801,-773,-744,
+-716,-689,-663,-638,-613,-587,-562,-536,-509,-480,-451,-420,-390,-359,-329,-300,-272,-244,-215,-183,-149,
+-111,-71,-29,12,51,87,120,148,175,201,229,261,300,345,396,452,512,573,635,694,752,
+807,859,907,952,993,1029,1061,1089,1115,1140,1166,1193,1223,1254,1285,1312,1335,1352,1364,1373,1383,
+1397,1420,1452,1492,1537,1582,1622,1652,1669,1673,1665,1650,1630,1609,1591,1575,1561,1549,1537,1526,1515,
+1508,1505,1507,1515,1527,1543,1562,1582,1604,1628,1652,1676,1697,1710,1713,1702,1674,1632,1581,1526,1476,
+1435,1407,1393,1390,1390,1389,1380,1363,1337,1307,1275,1247,1225,1210,1200,1193,1186,1177,1167,1157,1150,
+1149,1156,1170,1189,1211,1233,1251,1266,1276,1282,1287,1290,1291,1292,1290,1285,1277,1267,1257,1249,1244,
+1242,1244,1248,1252,1255,1256,1254,1249,1244,1240,1237,1237,1240,1244,1249,1254,1257,1258,1256,1250,1243,
+1232,1220,1207,1195,1185,1178,1174,1173,1174,1176,1176,1173,1165,1154,1140,1124,1109,1095,1085,1076,1070,
+1064,1058,1051,1043,1034,1025,1016,1007,999,991,983,974,964,955,945,937,931,927,924,923,921,
+919,917,913,908,903,899,894,891,889,888,887,886,885,884,883,881,879,876,872,868,862,
+855,848,840,833,826,820,815,811,807,802,797,790,782,772,762,753,745,739,737,737,739,
+742,746,749,752,754,757,760,764,769,774,779,782,784,785,784,783,782,782,784,788,792,
+796,799,801,802,803,803,805,809,814,820,827,836,845,855,866,878,892,906,919,932,943,
+952,960,966,972,979,987,996,1007,1019,1031,1043,1054,1065,1075,1085,1095,1105,1116,1127,1140,1155,
+1173,1194,1219,1249,1281,1315,1289,1319,1347,1373,1396,1415,1430,1443,1453,1461,1467,1471,1473,1475,1477,
+1479,1482,1487,1493,1499,1505,1510,1514,1517,1520,1523,1527,1534,1544,1555,1567,1577,1586,1592,1596,1599,
+1603,1610,1621,1636,1656,1679,1702,1726,1748,1768,1787,1806,1824,1842,1858,1870,1877,1878,1871,1858,1841,
+1822,1804,1789,1779,1772,1767,1762,1756,1746,1733,1718,1704,1694,1688,1688,1694,1705,1718,1730,1741,1748,
+1752,1753,1753,1752,1751,1752,1754,1756,1758,1759,1758,1756,1752,1747,1741,1736,1733,1732,1735,1741,1749,
+1760,1772,1782,1791,1798,1803,1807,1810,1814,1821,1829,1840,1852,1866,1882,1898,1917,1937,1957,1975,1989,
+1994,1990,1975,1951,1925,1903,1892,1900,1929,1979,2045,2117,2186,2243,2281,2298,2299,2289,2276,2267,2267,
+2278,2296,2317,2336,2348,2351,2346,2338,2328,2323,2324,2330,2342,2356,2370,2382,2393,2402,2411,2423,2436,
+2452,2468,2484,2499,2512,2525,2540,2558,2581,2607,2634,2661,2685,2703,2714,2721,2724,2728,2735,2748,2768,
+2793,2822,2854,2885,2916,2944,2968,2990,3006,3018,3023,3024,3021,3017,3018,3029,3051,3088,3138,3197,3257,
+3313,3359,3392,3413,3426,3439,3457,3485,3525,3573,3623,3666,3695,3703,3688,3651,3598,3537,3474,3416,3366,
+3325,3291,3261,3233,3203,3171,3138,3103,3069,3036,3004,2972,2939,2905,2871,2836,2801,2769,2739,2712,2688,
+2666,2646,2625,2605,2584,2565,2548,2534,2523,2516,2512,2510,2510,2510,2509,2507,2500,2490,2475,2455,2432,
+2409,2387,2371,2360,2357,2359,2365,2370,2371,2365,2350,2326,2296,2264,2232,2204,2182,2166,2155,2146,2137,
+2126,2111,2092,2071,2047,2023,1999,1976,1954,1933,1913,1894,1876,1858,1840,1819,1796,1768,1735,1699,1660,
+1621,1585,1555,1533,1518,1509,1506,1506,1507,1509,1511,1515,1521,1530,1542,1555,1568,1576,1578,1574,1563,
+1546,1526,1505,1484,1463,1443,1420,1394,1364,1331,1295,1261,1230,1205,1188,1177,1170,1164,1154,1137,1111,
+1077,1035,989,942,898,858,824,796,773,753,734,712,686,656,620,579,535,489,442,396,351,
+307,263,219,175,132,93,59,32,14,3,0,-3,-8,-22,-45,-81,-125,-174,-221,-260,-284,
+-291,-281,-258,-227,-195,-168,-150,-144,-148,-160,-178,-200,-225,-252,-285,-324,-371,-427,-490,-557,-625,
+-690,-751,-806,-857,-905,-952,-1002,-1053,-1106,-1160,-1211,-1257,-1297,-1331,-1358,-1380,-1400,-1418,-1436,-1452,-1467,
+-1480,-1491,-1498,-1505,-1513,-1524,-1541,-1563,-1591,-1623,-1658,-1693,-1727,-1759,-1790,-1822,-1856,-1894,-1938,-1985,-2034,
+-2082,-2125,-2161,-2189,-2208,-2220,-2228,-2238,-2251,-2270,-2296,-2327,-2361,-2394,-2423,-2445,-2460,-2469,-2475,-2481,-2492,
+-2510,-2535,-2568,-2605,-2644,-2680,-2711,-2736,-2755,-2770,-2785,-2800,-2820,-2843,-2871,-2900,-2929,-2955,-2979,-2999,-3015,
+-3030,-3045,-3061,-3080,-3103,-3130,-3164,-3202,-3245,-3291,-3340,-3388,-3434,-3475,-3510,-3538,-3560,-3577,-3590,-3602,-3614,
+-3627,-3640,-3654,-3667,-3679,-3690,-3701,-3712,-3725,-3740,-3758,-3776,-3794,-3810,-3824,-3836,-3846,-3856,-3867,-3881,-3897,
+-3917,-3938,-3960,-3984,-4007,-4031,-4056,-4082,-4108,-4135,-4159,-4180,-4196,-4206,-4210,-4209,-4203,-4196,-4189,-4183,-4179,
+-4179,-4183,-4191,-4203,-4221,-4244,-4271,-4301,-4334,-4366,-4397,-4424,-4447,-4466,-4482,-4496,-4507,-4517,-4525,-4530,-4534,
+-4535,-4535,-4535,-4537,-4541,-4548,-4558,-4568,-4578,-4584,-4586,-4583,-4576,-4567,-4555,-4544,-4535,-4528,-4524,-4525,-4531,
+-4545,-4567,-4599,-4640,-4687,-4738,-4785,-4825,-4851,-4862,-4856,-4836,-4808,-4777,-4748,-4727,-4715,-4711,-4712,-4716,-4719,
+-4718,-4712,-4702,-4691,-4681,-4675,-4673,-4677,-4685,-4696,-4708,-4720,-4730,-4739,-4747,-4753,-4758,-4762,-4764,-4763,-4761,
+-4757,-4753,-4750,-4750,-4754,-4763,-4776,-4792,-4809,-4826,-4841,-4853,-4863,-4871,-4879,-4887,-4897,-4909,-4924,-4939,-4955,
+-4972,-4988,-5005,-5022,-5041,-5061,-5083,-5105,-5127,-5147,-5165,-5180,-5191,-5200,-5208,-5215,-5223,-5233,-5246,-5260,-5275,
+-5291,-5307,-5322,-5338,-5354,-5371,-5388,-5406,-5425,-5442,-5457,-5468,-5474,-5475,-5473,-5469,-5464,-5461,-5462,-5468,-5477,
+-5490,-5503,-5516,-5527,-5534,-5537,-5537,-5535,-5530,-5524,-5517,-5507,-5495,-5480,-5462,-5441,-5419,-5397,-5377,-5361,-5350,
+-5343,-5340,-5340,-5343,-5346,-5350,-5353,-5356,-5359,-5362,-5365,-5367,-5369,-5370,-5369,-5368,-5367,-5364,-5362,-5360,-5358,
+-5357,-5354,-5352,-5348,-5343,-5337,-5329,-5321,-5313,-5306,-5299,-5294,-5290,-5288,-5286,-5285,-5283,-5280,-5275,-5269,-5262,
+-5254,-5248,-5243,-5241,-5241,-5242,-5244,-5246,-5245,-5242,-5237,-5230,-5222,-5214,-5206,-5200,-5196,-5192,-5189,-5187,-5184,
+-5182,-5179,-5177,-5175,-5174,-5171,-5168,-5163,-5155,-5146,-5135,-5122,-5110,-5098,-5088,-5079,-5072,-5066,-5060,-5054,-5048,
+-5041,-5034,-5026,-5019,-5011,-5004,-4997,-4990,-4984,-4979,-4975,-4972,-4969,-4967,-4964,-4959,-4952,-4943,-4932,-4919,-4905,
+-4892,-4880,-4869,-4861,-4853,-4845,-4836,-4825,-4812,-4798,-4783,-4768,-4754,-4742,-4731,-4722,-4711,-4700,-4686,-4670,-4651,
+-4631,-4612,-4593,-4576,-4562,-4549,-4538,-4527,-4516,-4504,-4493,-4481,-4469,-4459,-4448,-4437,-4424,-4410,-4395,-4377,-4360,
+-4345,-4333,-4325,-4322,-4323,-4327,-4333,-4337,-4339,-4337,-4332,-4323,-4312,-4300,-4289,-4280,-4272,-4265,-4258,-4251,-4244,
+-4235,-4225,-4214,-4204,-4194,-4184,-4176,-4168,-4161,-4154,-4147,-4138,-4129,-4118,-4105,-4091,-4075,-4057,-4038,-4018,-3997,
+-3976,-3954,-3932,-3910,-3888,-3866,-3844,-3823,-3802,-3781,-3761,-3741,-3722,-3704,-3687,-3671,-3657,-3643,-3631,-3618,-3607,
+-3594,-3582,-3569,-3555,-3542,-3528,-3515,-3503,-3491,-3480,-3470,-3459,-3449,-3439,-3429,-3419,-3410,-3400,-3391,-3382,-3372,
+-3361,-3349,-3336,-3324,-3312,-3302,-3293,-3286,-3280,-3273,-3265,-3256,-3245,-3232,-3219,-3206,-3195,-3185,-3176,-3168,-3160,
+-3150,-3137,-3123,-3107,-3090,-3074,-3058,-3044,-3030,-3015,-3000,-2983,-2964,-2944,-2924,-2904,-2887,-2870,-2855,-2839,-2824,
+-2806,-2788,-2769,-2751,-2735,-2722,-2711,-2702,-2694,-2686,-2676,-2664,-2651,-2638,-2625,-2614,-2605,-2597,-2590,-2581,-2572,
+-2561,-2548,-2536,-2525,-2516,-2509,-2503,-2496,-2489,-2479,-2466,-2452,-2437,-2422,-2410,-2400,-2391,-2383,-2374,-2363,-2349,
+-2333,-2317,-2301,-2286,-2272,-2258,-2243,-2224,-2202,-2175,-2147,-2118,-2091,-2068,-2049,-2034,-2021,-2008,-1995,-1980,-1966,
+-1954,-1945,-1939,-1937,-1934,-1926,-1910,-1883,-1844,-1795,-1741,-1687,-1641,-1607,-1585,-1575,-1574,-1576,-1576,-1570,-1556,
+-1535,-1508,-1479,-1451,-1425,-1403,-1383,-1366,-1349,-1332,-1313,-1294,-1273,-1253,-1233,-1213,-1193,-1173,-1151,-1129,-1106,
+-1082,-1057,-1032,-1006,-980,-952,-925,-898,-870,-844,-818,-794,-770,-747,-725,-702,-678,-653,-627,-600,-572,
+-543,-512,-481,-449,-417,-386,-356,-327,-301,-276,-250,-223,-193,-160,-123,-84,-43,-4,33,68,100,
+131,164,200,243,294,352,416,483,552,619,681,739,791,838,881,920,956,988,1017,1043,1066,
+1086,1106,1125,1146,1168,1191,1215,1236,1256,1272,1288,1303,1322,1347,1378,1415,1456,1496,1531,1556,1570,
+1572,1564,1550,1534,1520,1509,1502,1496,1490,1481,1467,1451,1434,1420,1412,1412,1422,1440,1464,1491,1518,
+1544,1567,1588,1606,1620,1627,1627,1615,1591,1555,1511,1462,1413,1370,1337,1313,1297,1287,1278,1266,1251,
+1231,1209,1188,1169,1155,1145,1139,1133,1127,1119,1111,1103,1099,1099,1106,1118,1134,1151,1167,1180,1190,
+1197,1201,1206,1211,1216,1221,1225,1226,1224,1220,1214,1208,1204,1201,1200,1199,1199,1197,1192,1185,1176,
+1166,1158,1152,1148,1148,1150,1153,1157,1161,1163,1164,1163,1160,1154,1146,1137,1126,1116,1108,1102,1099,
+1098,1100,1101,1101,1099,1093,1085,1073,1061,1049,1037,1027,1019,1011,1004,997,990,983,975,968,960,
+953,946,939,932,924,916,908,901,895,890,886,882,879,876,873,870,866,862,858,855,851,
+848,845,843,840,838,837,836,836,835,834,831,827,821,814,806,797,788,781,775,770,767,
+764,760,755,749,741,733,724,717,713,710,711,714,718,723,728,731,734,737,739,743,747,
+751,756,761,764,767,768,769,769,770,772,775,779,782,785,788,790,791,792,794,798,802,
+807,814,821,828,836,845,855,866,877,889,902,913,924,933,941,949,957,966,976,987,999,
+1011,1023,1034,1046,1056,1067,1078,1088,1099,1110,1122,1134,1148,1164,1183,1205,1231,1259,1289,1233,1255,
+1276,1295,1312,1329,1344,1359,1374,1390,1404,1417,1427,1435,1440,1443,1445,1447,1450,1454,1460,1467,1475,
+1483,1491,1498,1506,1514,1522,1530,1537,1542,1547,1550,1553,1558,1565,1577,1592,1612,1634,1656,1678,1697,
+1713,1727,1740,1753,1766,1779,1792,1802,1807,1806,1797,1781,1761,1737,1715,1696,1683,1674,1670,1667,1665,
+1661,1656,1649,1643,1639,1639,1644,1653,1666,1680,1692,1703,1709,1712,1712,1710,1708,1707,1707,1709,1711,
+1713,1713,1710,1705,1697,1689,1680,1673,1669,1670,1674,1683,1694,1707,1721,1733,1743,1750,1756,1761,1766,
+1771,1778,1787,1798,1811,1827,1845,1866,1890,1915,1940,1961,1975,1977,1966,1944,1914,1883,1860,1852,1866,
+1904,1964,2038,2116,2189,2246,2283,2299,2297,2286,2272,2262,2261,2269,2282,2297,2309,2314,2312,2305,2296,
+2289,2287,2291,2301,2315,2329,2341,2350,2356,2362,2370,2381,2398,2419,2442,2467,2490,2512,2532,2552,2574,
+2597,2623,2650,2674,2694,2708,2716,2718,2719,2721,2729,2744,2768,2800,2837,2877,2917,2955,2989,3018,3042,
+3060,3071,3076,3077,3074,3072,3077,3091,3121,3166,3228,3301,3378,3454,3520,3573,3612,3639,3659,3679,3702,
+3732,3767,3803,3833,3850,3850,3828,3785,3727,3658,3586,3518,3457,3406,3364,3328,3296,3264,3232,3198,3162,
+3127,3093,3061,3031,3003,2976,2950,2923,2895,2865,2834,2803,2770,2738,2707,2676,2647,2619,2592,2567,2542,
+2518,2496,2476,2460,2449,2443,2441,2443,2444,2442,2435,2420,2398,2372,2344,2320,2304,2298,2301,2313,2328,
+2343,2351,2350,2339,2320,2295,2270,2249,2233,2225,2222,2223,2222,2217,2205,2185,2157,2123,2085,2044,2004,
+1966,1932,1900,1873,1848,1824,1801,1775,1747,1714,1677,1639,1601,1567,1539,1522,1514,1516,1525,1538,1550,
+1560,1565,1566,1565,1564,1565,1569,1575,1582,1587,1588,1581,1568,1549,1527,1503,1481,1462,1445,1429,1412,
+1392,1370,1343,1316,1288,1264,1243,1227,1213,1199,1182,1159,1129,1091,1047,999,951,906,866,831,802,
+776,752,728,701,670,635,596,555,512,470,427,386,344,303,261,219,177,138,102,71,47,
+28,15,3,-10,-29,-57,-95,-142,-193,-244,-288,-319,-332,-327,-305,-270,-228,-185,-147,-119,-103,
+-99,-107,-123,-147,-176,-210,-249,-293,-343,-398,-456,-518,-580,-642,-704,-764,-823,-881,-940,-998,-1056,
+-1112,-1165,-1216,-1262,-1306,-1346,-1384,-1420,-1454,-1486,-1515,-1538,-1555,-1566,-1571,-1572,-1572,-1572,-1577,-1586,-1600,
+-1619,-1641,-1666,-1690,-1715,-1740,-1767,-1797,-1831,-1871,-1916,-1965,-2015,-2065,-2112,-2153,-2189,-2218,-2244,-2267,-2289,
+-2314,-2341,-2372,-2404,-2438,-2470,-2498,-2522,-2539,-2552,-2560,-2567,-2574,-2582,-2593,-2606,-2621,-2638,-2654,-2671,-2689,
+-2707,-2728,-2752,-2781,-2813,-2847,-2881,-2914,-2943,-2968,-2989,-3006,-3022,-3036,-3052,-3070,-3089,-3112,-3138,-3168,-3203,
+-3244,-3293,-3350,-3412,-3477,-3541,-3599,-3648,-3683,-3704,-3711,-3707,-3696,-3682,-3669,-3661,-3660,-3665,-3677,-3695,-3715,
+-3737,-3760,-3782,-3803,-3824,-3843,-3862,-3880,-3897,-3913,-3927,-3940,-3950,-3959,-3966,-3974,-3983,-3996,-4013,-4035,-4061,
+-4090,-4120,-4147,-4171,-4188,-4200,-4205,-4206,-4203,-4199,-4193,-4187,-4182,-4178,-4176,-4178,-4183,-4195,-4214,-4239,-4269,
+-4303,-4337,-4370,-4398,-4422,-4441,-4455,-4467,-4476,-4485,-4493,-4499,-4505,-4510,-4514,-4519,-4525,-4534,-4545,-4558,-4571,
+-4582,-4589,-4590,-4586,-4577,-4564,-4551,-4538,-4529,-4522,-4520,-4522,-4529,-4543,-4565,-4596,-4636,-4685,-4738,-4791,-4839,
+-4875,-4896,-4901,-4889,-4865,-4836,-4806,-4782,-4768,-4763,-4767,-4776,-4787,-4795,-4799,-4798,-4794,-4787,-4780,-4775,-4774,
+-4776,-4780,-4787,-4795,-4804,-4813,-4824,-4834,-4845,-4853,-4858,-4857,-4851,-4839,-4824,-4809,-4796,-4790,-4792,-4804,-4824,
+-4850,-4878,-4905,-4927,-4944,-4955,-4962,-4968,-4973,-4981,-4991,-5004,-5019,-5034,-5048,-5062,-5074,-5087,-5102,-5119,-5139,
+-5162,-5186,-5210,-5232,-5251,-5266,-5278,-5287,-5294,-5301,-5308,-5317,-5327,-5339,-5351,-5363,-5375,-5388,-5401,-5416,-5432,
+-5449,-5466,-5483,-5498,-5510,-5519,-5525,-5528,-5530,-5532,-5535,-5539,-5545,-5552,-5559,-5565,-5570,-5574,-5577,-5581,-5585,
+-5590,-5596,-5601,-5604,-5603,-5597,-5585,-5568,-5547,-5524,-5500,-5478,-5460,-5445,-5434,-5427,-5423,-5421,-5420,-5421,-5422,
+-5425,-5428,-5432,-5435,-5438,-5441,-5442,-5442,-5441,-5438,-5434,-5430,-5424,-5419,-5413,-5408,-5403,-5398,-5393,-5388,-5383,
+-5378,-5372,-5366,-5360,-5355,-5351,-5348,-5346,-5344,-5341,-5337,-5332,-5325,-5316,-5308,-5300,-5294,-5291,-5291,-5292,-5294,
+-5297,-5297,-5295,-5291,-5285,-5277,-5268,-5260,-5252,-5246,-5240,-5236,-5232,-5228,-5226,-5224,-5222,-5222,-5221,-5221,-5219,
+-5216,-5212,-5205,-5196,-5186,-5175,-5164,-5154,-5144,-5135,-5126,-5118,-5109,-5100,-5091,-5082,-5072,-5063,-5055,-5047,-5040,
+-5034,-5028,-5023,-5019,-5016,-5013,-5010,-5007,-5004,-4999,-4993,-4986,-4979,-4971,-4963,-4955,-4947,-4938,-4928,-4916,-4902,
+-4887,-4870,-4853,-4836,-4821,-4808,-4796,-4784,-4773,-4761,-4747,-4731,-4713,-4693,-4673,-4654,-4637,-4621,-4606,-4593,-4580,
+-4568,-4555,-4543,-4531,-4520,-4509,-4499,-4488,-4477,-4465,-4451,-4436,-4421,-4407,-4396,-4389,-4386,-4386,-4389,-4393,-4397,
+-4398,-4395,-4388,-4378,-4365,-4351,-4338,-4325,-4315,-4306,-4299,-4293,-4287,-4281,-4275,-4267,-4259,-4249,-4238,-4227,-4215,
+-4203,-4190,-4177,-4163,-4150,-4136,-4122,-4107,-4092,-4075,-4057,-4038,-4018,-3997,-3975,-3953,-3931,-3908,-3886,-3863,-3841,
+-3819,-3798,-3777,-3757,-3738,-3720,-3703,-3687,-3672,-3659,-3647,-3636,-3625,-3614,-3602,-3590,-3578,-3565,-3553,-3541,-3529,
+-3518,-3508,-3499,-3490,-3481,-3472,-3464,-3456,-3447,-3438,-3429,-3420,-3409,-3397,-3386,-3374,-3362,-3352,-3343,-3335,-3328,
+-3321,-3313,-3303,-3292,-3279,-3265,-3252,-3239,-3227,-3218,-3209,-3201,-3192,-3182,-3169,-3154,-3137,-3120,-3103,-3086,-3070,
+-3054,-3037,-3020,-3002,-2982,-2963,-2945,-2927,-2911,-2896,-2882,-2868,-2852,-2836,-2819,-2802,-2786,-2772,-2761,-2751,-2743,
+-2734,-2724,-2711,-2697,-2681,-2666,-2652,-2642,-2634,-2628,-2623,-2616,-2608,-2597,-2583,-2570,-2557,-2546,-2538,-2531,-2526,
+-2520,-2512,-2501,-2489,-2474,-2460,-2447,-2436,-2425,-2416,-2405,-2393,-2379,-2362,-2345,-2328,-2311,-2296,-2282,-2266,-2248,
+-2227,-2202,-2175,-2146,-2118,-2093,-2071,-2054,-2040,-2028,-2016,-2003,-1991,-1978,-1966,-1956,-1948,-1940,-1932,-1919,-1901,
+-1877,-1845,-1808,-1769,-1731,-1696,-1666,-1642,-1623,-1606,-1591,-1575,-1557,-1537,-1515,-1493,-1471,-1450,-1430,-1411,-1391,
+-1372,-1352,-1331,-1310,-1289,-1267,-1246,-1224,-1202,-1180,-1157,-1135,-1113,-1091,-1069,-1046,-1023,-998,-973,-946,-919,
+-892,-865,-841,-818,-796,-774,-753,-731,-707,-682,-656,-628,-599,-569,-537,-503,-468,-431,-394,-358,-324,
+-294,-267,-243,-222,-201,-180,-156,-130,-100,-67,-32,5,45,89,137,190,249,314,382,453,523,
+589,650,704,752,794,831,866,899,931,960,988,1012,1033,1051,1066,1081,1095,1109,1124,1139,1154,
+1168,1183,1200,1220,1247,1279,1319,1362,1404,1443,1471,1487,1489,1480,1462,1442,1424,1412,1406,1406,1408,
+1408,1402,1390,1373,1353,1335,1324,1323,1333,1354,1382,1414,1446,1475,1499,1517,1528,1534,1533,1525,1508,
+1482,1447,1404,1357,1310,1267,1230,1201,1180,1165,1154,1144,1133,1122,1110,1099,1091,1084,1080,1076,1073,
+1068,1062,1055,1049,1046,1046,1051,1060,1071,1082,1092,1099,1104,1107,1110,1114,1120,1128,1138,1148,1155,
+1160,1162,1161,1158,1155,1151,1148,1144,1141,1136,1129,1121,1113,1103,1095,1087,1082,1078,1075,1073,1072,
+1071,1071,1071,1071,1070,1068,1065,1060,1054,1046,1038,1031,1025,1022,1020,1021,1022,1023,1023,1020,1016,
+1009,1001,992,984,975,967,960,952,945,937,930,922,915,907,900,892,885,878,871,864,857,
+851,845,840,835,831,827,824,821,818,816,814,812,810,808,805,802,799,797,795,793,792,
+790,789,786,783,778,772,765,757,751,745,740,735,732,728,723,717,711,704,698,693,689,
+688,689,692,696,701,706,710,715,719,723,727,732,737,741,746,749,751,752,753,755,756,
+759,762,766,769,772,773,774,774,774,774,776,779,783,789,795,802,810,818,827,836,847,
+858,870,882,893,903,913,922,931,941,951,962,974,987,1000,1012,1024,1035,1046,1057,1068,1078,
+1088,1098,1107,1117,1127,1139,1153,1170,1190,1211,1233,1159,1173,1187,1201,1215,1231,1249,1270,1293,1319,
+1344,1366,1385,1398,1406,1409,1409,1407,1406,1408,1413,1421,1432,1445,1459,1473,1485,1495,1504,1510,1515,
+1518,1521,1523,1528,1535,1546,1560,1578,1599,1620,1639,1656,1668,1676,1680,1683,1687,1691,1698,1706,1714,
+1720,1722,1717,1707,1691,1672,1652,1634,1620,1611,1605,1604,1604,1604,1605,1605,1606,1608,1612,1619,1628,
+1638,1649,1658,1665,1670,1672,1671,1670,1668,1667,1666,1666,1665,1664,1660,1654,1647,1638,1630,1622,1618,
+1617,1620,1627,1638,1650,1663,1675,1687,1696,1705,1713,1721,1729,1739,1750,1761,1774,1788,1804,1822,1843,
+1866,1892,1916,1935,1946,1946,1933,1910,1880,1853,1834,1833,1855,1899,1964,2040,2119,2189,2243,2276,2288,
+2284,2271,2256,2245,2242,2247,2257,2269,2277,2280,2278,2271,2264,2261,2263,2271,2284,2300,2315,2327,2335,
+2340,2345,2353,2365,2384,2409,2438,2470,2502,2532,2561,2587,2612,2635,2657,2677,2692,2702,2707,2706,2703,
+2701,2703,2713,2734,2765,2805,2851,2901,2950,2998,3041,3079,3111,3138,3158,3171,3177,3179,3178,3180,3189,
+3210,3247,3301,3370,3449,3533,3613,3686,3748,3796,3835,3865,3892,3917,3940,3961,3974,3977,3963,3932,3884,
+3820,3747,3670,3594,3523,3461,3408,3363,3323,3287,3252,3218,3184,3151,3119,3091,3066,3043,3024,3005,2986,
+2964,2939,2911,2880,2846,2812,2779,2747,2719,2692,2665,2638,2609,2577,2543,2509,2478,2453,2436,2426,2424,
+2425,2425,2420,2406,2383,2352,2319,2287,2264,2253,2257,2273,2298,2327,2352,2370,2378,2377,2368,2358,2348,
+2344,2344,2350,2356,2360,2357,2343,2317,2280,2232,2178,2119,2061,2005,1953,1907,1866,1831,1801,1773,1746,
+1720,1692,1664,1637,1613,1593,1579,1574,1576,1583,1594,1604,1610,1611,1606,1596,1585,1576,1571,1571,1576,
+1584,1590,1592,1586,1572,1551,1525,1498,1473,1452,1437,1426,1417,1407,1393,1375,1351,1323,1294,1265,1237,
+1212,1187,1163,1136,1106,1072,1035,996,956,917,880,848,818,791,765,739,712,683,653,620,586,
+550,512,473,432,390,348,306,266,229,195,166,140,117,96,72,45,13,-26,-71,-121,-171,
+-220,-261,-292,-310,-314,-305,-283,-253,-218,-183,-150,-123,-105,-96,-98,-111,-135,-169,-212,-262,-317,
+-375,-433,-489,-545,-598,-650,-703,-756,-811,-868,-925,-981,-1033,-1082,-1127,-1168,-1206,-1244,-1284,-1326,-1371,
+-1417,-1462,-1504,-1539,-1567,-1587,-1599,-1607,-1611,-1616,-1623,-1632,-1644,-1659,-1674,-1689,-1705,-1721,-1739,-1759,-1784,
+-1813,-1847,-1886,-1927,-1972,-2017,-2062,-2106,-2148,-2189,-2228,-2265,-2300,-2333,-2366,-2398,-2430,-2463,-2495,-2527,-2558,
+-2586,-2610,-2628,-2641,-2648,-2650,-2648,-2644,-2640,-2638,-2639,-2646,-2659,-2680,-2707,-2739,-2776,-2815,-2854,-2891,-2923,
+-2951,-2975,-2994,-3010,-3026,-3041,-3056,-3073,-3090,-3108,-3128,-3153,-3183,-3223,-3274,-3336,-3409,-3489,-3569,-3644,-3707,
+-3751,-3774,-3777,-3761,-3732,-3697,-3664,-3637,-3622,-3618,-3626,-3643,-3666,-3692,-3719,-3745,-3770,-3795,-3821,-3846,-3871,
+-3895,-3916,-3933,-3943,-3947,-3945,-3941,-3936,-3934,-3937,-3948,-3966,-3991,-4019,-4047,-4074,-4097,-4114,-4127,-4136,-4144,
+-4150,-4156,-4162,-4168,-4172,-4174,-4176,-4179,-4184,-4194,-4210,-4232,-4260,-4292,-4325,-4356,-4383,-4407,-4426,-4442,-4457,
+-4472,-4488,-4505,-4521,-4537,-4552,-4565,-4579,-4593,-4608,-4625,-4643,-4661,-4675,-4685,-4687,-4683,-4672,-4657,-4640,-4624,
+-4611,-4601,-4597,-4596,-4600,-4608,-4622,-4641,-4668,-4701,-4739,-4780,-4818,-4848,-4868,-4874,-4866,-4847,-4821,-4795,-4773,
+-4759,-4757,-4765,-4781,-4803,-4825,-4846,-4862,-4873,-4880,-4882,-4882,-4881,-4878,-4876,-4875,-4875,-4878,-4885,-4896,-4911,
+-4927,-4943,-4955,-4959,-4954,-4940,-4918,-4892,-4867,-4848,-4840,-4844,-4860,-4887,-4919,-4952,-4982,-5007,-5024,-5035,-5043,
+-5049,-5058,-5068,-5082,-5097,-5113,-5126,-5138,-5147,-5155,-5164,-5175,-5189,-5208,-5230,-5255,-5280,-5302,-5321,-5336,-5347,
+-5354,-5361,-5367,-5374,-5383,-5393,-5404,-5416,-5427,-5438,-5449,-5459,-5470,-5481,-5494,-5507,-5520,-5533,-5546,-5557,-5568,
+-5578,-5587,-5596,-5604,-5610,-5615,-5619,-5621,-5622,-5623,-5626,-5630,-5637,-5646,-5657,-5668,-5678,-5685,-5688,-5685,-5678,
+-5666,-5650,-5632,-5613,-5594,-5576,-5559,-5544,-5530,-5519,-5511,-5505,-5501,-5500,-5501,-5503,-5506,-5509,-5512,-5514,-5515,
+-5515,-5513,-5509,-5503,-5496,-5487,-5478,-5469,-5461,-5455,-5451,-5448,-5446,-5445,-5442,-5439,-5434,-5428,-5422,-5416,-5411,
+-5407,-5404,-5401,-5397,-5392,-5385,-5377,-5368,-5359,-5352,-5346,-5344,-5343,-5344,-5345,-5345,-5343,-5340,-5335,-5328,-5320,
+-5312,-5304,-5296,-5289,-5283,-5277,-5273,-5270,-5268,-5268,-5270,-5272,-5275,-5276,-5275,-5271,-5264,-5255,-5244,-5232,-5219,
+-5207,-5195,-5184,-5174,-5163,-5154,-5144,-5135,-5127,-5119,-5112,-5106,-5100,-5093,-5087,-5079,-5072,-5064,-5057,-5051,-5047,
+-5044,-5042,-5041,-5041,-5040,-5039,-5037,-5033,-5027,-5018,-5007,-4994,-4979,-4962,-4944,-4926,-4908,-4891,-4875,-4860,-4846,
+-4832,-4817,-4802,-4786,-4768,-4750,-4731,-4713,-4695,-4679,-4663,-4649,-4635,-4621,-4608,-4596,-4584,-4572,-4561,-4550,-4540,
+-4529,-4519,-4507,-4496,-4485,-4476,-4468,-4462,-4460,-4459,-4460,-4460,-4460,-4458,-4453,-4445,-4434,-4421,-4407,-4392,-4377,
+-4364,-4352,-4343,-4334,-4328,-4322,-4316,-4309,-4301,-4292,-4281,-4267,-4252,-4236,-4219,-4201,-4184,-4167,-4150,-4134,-4119,
+-4104,-4088,-4071,-4054,-4035,-4015,-3994,-3972,-3949,-3925,-3902,-3879,-3856,-3834,-3813,-3792,-3773,-3754,-3736,-3719,-3704,
+-3689,-3675,-3662,-3650,-3639,-3628,-3617,-3607,-3597,-3587,-3577,-3567,-3558,-3549,-3540,-3532,-3523,-3514,-3506,-3497,-3488,
+-3479,-3471,-3463,-3454,-3445,-3436,-3426,-3416,-3406,-3396,-3386,-3377,-3367,-3357,-3347,-3336,-3324,-3311,-3298,-3286,-3274,
+-3262,-3252,-3242,-3231,-3219,-3206,-3192,-3176,-3159,-3142,-3125,-3108,-3091,-3074,-3056,-3037,-3018,-2998,-2979,-2961,-2945,
+-2930,-2916,-2903,-2889,-2875,-2860,-2845,-2831,-2819,-2809,-2801,-2794,-2787,-2778,-2766,-2752,-2734,-2716,-2699,-2684,-2672,
+-2664,-2659,-2655,-2649,-2642,-2633,-2621,-2608,-2595,-2585,-2576,-2570,-2564,-2559,-2551,-2542,-2529,-2515,-2501,-2486,-2472,
+-2460,-2448,-2436,-2423,-2409,-2394,-2378,-2362,-2347,-2332,-2318,-2303,-2285,-2264,-2239,-2212,-2184,-2155,-2130,-2107,-2088,
+-2072,-2058,-2044,-2029,-2013,-1996,-1979,-1963,-1950,-1939,-1930,-1921,-1910,-1895,-1875,-1849,-1818,-1783,-1747,-1711,-1678,
+-1647,-1621,-1598,-1577,-1559,-1542,-1525,-1508,-1489,-1469,-1447,-1424,-1401,-1378,-1356,-1334,-1314,-1294,-1273,-1252,-1229,
+-1206,-1181,-1156,-1131,-1108,-1087,-1067,-1048,-1030,-1011,-991,-969,-946,-922,-897,-873,-849,-825,-801,-776,-751,
+-724,-697,-670,-642,-614,-585,-554,-520,-484,-444,-403,-360,-320,-282,-251,-225,-206,-191,-179,-166,-151,
+-131,-104,-69,-25,24,81,144,211,280,349,417,482,541,595,643,685,724,760,795,830,865,
+898,929,956,979,997,1010,1021,1030,1039,1048,1058,1069,1080,1091,1104,1120,1140,1168,1203,1244,1289,
+1333,1371,1399,1412,1411,1397,1375,1351,1329,1313,1305,1304,1306,1308,1306,1297,1284,1267,1252,1242,1242,
+1253,1274,1303,1336,1369,1398,1421,1437,1444,1444,1436,1420,1396,1365,1326,1282,1236,1190,1148,1112,1084,
+1064,1050,1041,1035,1029,1024,1020,1016,1014,1014,1015,1016,1016,1014,1010,1005,1000,996,994,994,998,
+1002,1008,1013,1016,1019,1021,1024,1030,1038,1048,1060,1073,1084,1093,1098,1100,1099,1096,1093,1088,1084,
+1080,1075,1071,1066,1060,1054,1049,1043,1037,1031,1025,1018,1011,1004,999,994,991,989,987,985,983,
+979,973,967,961,955,952,950,951,954,958,961,964,964,963,959,953,946,938,930,922,914,
+906,899,891,883,876,868,860,852,844,836,828,821,813,806,800,794,789,784,781,777,775,
+774,773,773,773,773,772,771,769,766,762,758,754,750,746,742,738,734,729,725,722,718,
+715,712,709,706,702,697,691,685,679,674,670,668,668,669,672,676,679,683,687,692,697,
+703,709,717,724,731,736,740,742,742,742,743,743,745,749,752,756,758,759,758,756,752,
+749,747,747,749,753,759,766,775,784,794,805,816,827,839,851,862,873,882,891,899,908,
+918,928,941,954,968,982,996,1009,1022,1034,1045,1055,1064,1072,1078,1083,1088,1093,1100,1108,1118,
+1130,1144,1159,1104,1115,1126,1137,1150,1164,1183,1205,1231,1260,1288,1315,1337,1353,1361,1364,1363,1360,
+1357,1358,1363,1373,1387,1403,1422,1440,1456,1470,1481,1489,1495,1499,1502,1505,1510,1517,1528,1542,1558,
+1577,1595,1611,1623,1630,1632,1630,1626,1621,1618,1619,1623,1630,1638,1645,1649,1649,1644,1635,1622,1609,
+1596,1585,1578,1573,1572,1573,1575,1579,1584,1589,1594,1600,1606,1612,1618,1623,1626,1629,1630,1631,1630,
+1629,1627,1625,1621,1616,1610,1603,1595,1588,1581,1575,1572,1573,1576,1583,1592,1603,1615,1627,1638,1649,
+1659,1670,1681,1694,1708,1722,1737,1752,1766,1780,1794,1808,1824,1842,1860,1877,1890,1896,1893,1880,1861,
+1840,1823,1818,1830,1862,1915,1982,2058,2131,2194,2238,2262,2266,2255,2237,2219,2208,2206,2214,2227,2243,
+2256,2263,2264,2261,2255,2252,2254,2262,2276,2295,2314,2333,2349,2362,2374,2386,2401,2421,2444,2471,2501,
+2531,2560,2586,2610,2630,2646,2658,2666,2669,2667,2662,2656,2652,2653,2663,2684,2717,2760,2811,2867,2923,
+2978,3029,3075,3116,3153,3186,3215,3238,3254,3265,3272,3276,3282,3296,3320,3359,3412,3479,3556,3638,3719,
+3795,3861,3918,3965,4002,4031,4053,4067,4071,4062,4039,3999,3944,3875,3795,3711,3626,3545,3472,3410,3357,
+3314,3277,3246,3217,3190,3163,3136,3111,3088,3067,3048,3031,3013,2995,2974,2950,2924,2897,2870,2844,2822,
+2802,2784,2765,2743,2717,2684,2645,2604,2564,2528,2500,2482,2472,2469,2466,2459,2444,2419,2386,2348,2311,
+2281,2265,2264,2278,2304,2337,2371,2399,2420,2432,2437,2438,2438,2441,2445,2452,2456,2456,2446,2425,2390,
+2344,2287,2224,2158,2093,2031,1974,1924,1880,1843,1812,1785,1764,1746,1731,1719,1709,1702,1697,1695,1695,
+1695,1695,1691,1683,1670,1651,1629,1606,1585,1571,1564,1566,1574,1584,1594,1598,1593,1578,1555,1527,1497,
+1470,1448,1432,1422,1415,1407,1394,1374,1346,1311,1271,1229,1189,1152,1121,1095,1073,1055,1038,1020,1000,
+977,951,922,893,862,833,805,781,759,740,722,704,683,658,626,587,542,494,444,397,355,
+319,292,269,250,229,204,171,128,78,22,-36,-91,-140,-180,-208,-227,-237,-240,-239,-235,-230,
+-222,-213,-202,-190,-179,-171,-171,-181,-205,-243,-293,-354,-421,-488,-552,-610,-661,-706,-748,-789,-832,
+-877,-925,-974,-1020,-1063,-1100,-1133,-1162,-1190,-1220,-1255,-1296,-1342,-1392,-1443,-1491,-1534,-1570,-1599,-1622,-1641,
+-1658,-1674,-1689,-1705,-1719,-1730,-1739,-1745,-1749,-1752,-1756,-1762,-1771,-1785,-1804,-1829,-1859,-1896,-1939,-1989,-2046,
+-2107,-2171,-2233,-2292,-2344,-2387,-2423,-2452,-2478,-2503,-2530,-2560,-2594,-2629,-2662,-2690,-2710,-2721,-2721,-2714,-2702,
+-2689,-2679,-2676,-2682,-2696,-2718,-2746,-2778,-2810,-2842,-2872,-2898,-2921,-2941,-2960,-2979,-2997,-3016,-3035,-3055,-3074,
+-3093,-3113,-3134,-3160,-3192,-3234,-3287,-3351,-3424,-3503,-3583,-3656,-3716,-3759,-3781,-3782,-3765,-3735,-3699,-3664,-3634,
+-3615,-3607,-3609,-3621,-3638,-3658,-3680,-3702,-3726,-3750,-3777,-3806,-3837,-3867,-3893,-3915,-3929,-3935,-3934,-3929,-3924,
+-3920,-3922,-3930,-3944,-3963,-3984,-4004,-4021,-4034,-4043,-4049,-4055,-4062,-4071,-4084,-4098,-4113,-4128,-4141,-4153,-4165,
+-4179,-4195,-4216,-4242,-4271,-4302,-4332,-4360,-4385,-4406,-4426,-4446,-4468,-4494,-4524,-4556,-4589,-4620,-4649,-4673,-4695,
+-4714,-4733,-4752,-4772,-4792,-4809,-4823,-4830,-4829,-4821,-4808,-4791,-4774,-4759,-4747,-4740,-4736,-4735,-4736,-4740,-4746,
+-4755,-4768,-4785,-4804,-4824,-4842,-4854,-4857,-4852,-4839,-4820,-4800,-4782,-4770,-4767,-4775,-4791,-4814,-4842,-4871,-4898,
+-4923,-4943,-4958,-4968,-4973,-4973,-4969,-4963,-4957,-4954,-4956,-4964,-4978,-4998,-5019,-5039,-5052,-5055,-5047,-5029,-5003,
+-4973,-4947,-4927,-4919,-4922,-4936,-4959,-4985,-5011,-5035,-5054,-5070,-5084,-5098,-5114,-5132,-5152,-5173,-5193,-5209,-5222,
+-5230,-5235,-5238,-5243,-5251,-5263,-5279,-5298,-5318,-5338,-5355,-5369,-5381,-5390,-5398,-5407,-5417,-5429,-5442,-5456,-5469,
+-5482,-5492,-5501,-5508,-5514,-5519,-5526,-5534,-5543,-5555,-5568,-5582,-5597,-5611,-5626,-5639,-5650,-5660,-5668,-5674,-5678,
+-5682,-5685,-5689,-5694,-5700,-5707,-5715,-5723,-5732,-5740,-5748,-5754,-5760,-5763,-5764,-5762,-5756,-5746,-5733,-5716,-5698,
+-5678,-5659,-5642,-5627,-5615,-5606,-5599,-5593,-5589,-5585,-5581,-5578,-5576,-5575,-5574,-5572,-5568,-5563,-5556,-5548,-5538,
+-5528,-5520,-5513,-5509,-5507,-5506,-5505,-5502,-5498,-5492,-5485,-5477,-5470,-5465,-5462,-5461,-5460,-5458,-5455,-5449,-5441,
+-5431,-5421,-5411,-5402,-5396,-5391,-5389,-5388,-5387,-5386,-5384,-5380,-5375,-5369,-5363,-5355,-5347,-5339,-5331,-5325,-5320,
+-5318,-5318,-5320,-5323,-5327,-5330,-5330,-5328,-5322,-5313,-5302,-5289,-5276,-5263,-5251,-5240,-5230,-5221,-5212,-5203,-5194,
+-5187,-5180,-5174,-5169,-5164,-5159,-5153,-5146,-5137,-5127,-5117,-5107,-5099,-5094,-5091,-5090,-5091,-5092,-5092,-5091,-5088,
+-5082,-5074,-5064,-5052,-5039,-5025,-5010,-4994,-4977,-4960,-4943,-4926,-4909,-4893,-4876,-4860,-4844,-4828,-4811,-4794,-4777,
+-4759,-4741,-4725,-4709,-4694,-4680,-4667,-4655,-4644,-4633,-4622,-4610,-4599,-4588,-4577,-4567,-4558,-4550,-4543,-4538,-4534,
+-4531,-4529,-4526,-4523,-4519,-4513,-4506,-4497,-4486,-4474,-4460,-4446,-4431,-4417,-4403,-4390,-4378,-4367,-4357,-4347,-4338,
+-4328,-4316,-4303,-4289,-4273,-4256,-4238,-4221,-4203,-4186,-4170,-4154,-4139,-4123,-4108,-4091,-4073,-4054,-4034,-4012,-3989,
+-3966,-3942,-3917,-3894,-3871,-3849,-3828,-3809,-3791,-3774,-3758,-3742,-3726,-3711,-3697,-3683,-3669,-3657,-3645,-3635,-3625,
+-3616,-3608,-3601,-3594,-3587,-3580,-3572,-3564,-3555,-3546,-3536,-3526,-3515,-3506,-3497,-3490,-3483,-3476,-3469,-3461,-3452,
+-3442,-3432,-3420,-3409,-3397,-3385,-3374,-3363,-3352,-3341,-3330,-3319,-3307,-3294,-3281,-3267,-3253,-3238,-3222,-3206,-3190,
+-3174,-3159,-3144,-3129,-3113,-3096,-3078,-3059,-3039,-3018,-2998,-2979,-2961,-2945,-2929,-2915,-2900,-2887,-2873,-2861,-2851,
+-2842,-2836,-2832,-2828,-2823,-2815,-2805,-2791,-2774,-2755,-2737,-2720,-2707,-2696,-2689,-2683,-2678,-2672,-2665,-2657,-2648,
+-2640,-2632,-2625,-2619,-2612,-2605,-2595,-2583,-2569,-2553,-2537,-2521,-2506,-2492,-2480,-2468,-2456,-2444,-2431,-2417,-2403,
+-2389,-2374,-2359,-2341,-2320,-2297,-2271,-2243,-2214,-2187,-2163,-2142,-2124,-2110,-2096,-2081,-2065,-2047,-2027,-2007,-1987,
+-1970,-1956,-1944,-1933,-1922,-1908,-1890,-1867,-1839,-1806,-1770,-1734,-1699,-1668,-1641,-1618,-1598,-1582,-1565,-1548,-1529,
+-1507,-1481,-1454,-1425,-1397,-1372,-1349,-1329,-1312,-1297,-1281,-1264,-1244,-1221,-1195,-1167,-1139,-1113,-1089,-1068,-1050,
+-1034,-1019,-1003,-987,-968,-948,-926,-903,-879,-854,-828,-800,-772,-743,-714,-685,-657,-629,-601,-573,-542,
+-508,-471,-430,-387,-344,-302,-265,-234,-208,-188,-172,-156,-137,-113,-81,-39,11,69,133,199,265,
+328,386,437,483,524,561,596,632,671,712,756,800,843,882,914,938,954,963,967,969,971,
+976,983,993,1004,1016,1027,1039,1052,1068,1091,1120,1156,1196,1237,1273,1301,1317,1319,1308,1289,1266,
+1244,1226,1215,1211,1211,1212,1211,1207,1199,1189,1180,1176,1178,1189,1208,1233,1262,1291,1316,1337,1350,
+1355,1351,1340,1320,1291,1256,1214,1168,1122,1078,1039,1006,982,966,955,949,945,943,940,938,936,
+937,939,943,948,952,955,956,954,951,947,944,942,941,942,944,946,949,951,954,958,964,
+973,983,996,1008,1020,1030,1037,1040,1041,1040,1037,1032,1028,1024,1020,1016,1012,1009,1005,1001,997,
+992,986,979,971,963,955,947,940,935,930,927,924,921,918,913,909,904,900,898,898,900,
+904,908,913,917,919,919,916,911,904,896,887,879,871,864,857,851,846,840,834,828,822,
+814,807,798,790,782,775,767,761,755,750,746,742,740,739,738,737,737,737,737,736,733,
+730,726,720,714,708,701,694,688,683,679,676,675,675,676,676,676,674,672,668,664,660,
+656,654,654,656,659,662,666,670,673,675,678,682,687,693,701,709,717,724,729,732,733,
+732,731,730,731,733,736,739,742,743,742,738,734,729,724,721,721,723,729,736,746,756,
+768,779,792,804,816,828,839,848,857,864,871,877,885,894,905,917,932,947,963,979,995,
+1009,1023,1035,1046,1054,1060,1063,1065,1066,1066,1068,1071,1077,1085,1094,1104,1093,1103,1113,1123,1134,
+1146,1161,1178,1199,1221,1245,1267,1286,1300,1309,1313,1314,1313,1313,1315,1321,1332,1347,1366,1386,1406,
+1425,1443,1457,1469,1477,1483,1487,1490,1493,1498,1504,1514,1527,1542,1557,1572,1583,1590,1592,1588,1580,
+1571,1562,1556,1555,1558,1567,1578,1589,1599,1606,1607,1603,1595,1584,1572,1561,1553,1547,1546,1548,1553,
+1559,1566,1572,1577,1581,1584,1585,1587,1588,1589,1590,1591,1590,1589,1586,1582,1576,1569,1560,1552,1545,
+1538,1534,1532,1533,1536,1542,1550,1559,1569,1580,1592,1604,1616,1629,1643,1657,1673,1690,1707,1723,1739,
+1753,1766,1779,1791,1803,1815,1827,1837,1843,1845,1841,1832,1821,1813,1811,1822,1850,1895,1955,2025,2096,
+2161,2211,2242,2251,2243,2222,2198,2178,2168,2171,2187,2211,2238,2263,2280,2288,2287,2281,2275,2272,2275,
+2287,2307,2333,2362,2392,2420,2445,2466,2486,2503,2520,2536,2551,2566,2580,2591,2600,2606,2609,2607,2602,
+2594,2585,2576,2572,2575,2588,2614,2653,2704,2763,2826,2890,2949,3001,3046,3083,3115,3144,3171,3199,3227,
+3253,3278,3300,3320,3338,3358,3382,3413,3455,3507,3569,3638,3711,3786,3858,3924,3982,4032,4072,4101,4119,
+4122,4110,4082,4036,3974,3898,3811,3718,3626,3539,3461,3395,3343,3304,3275,3253,3234,3217,3198,3176,3153,
+3129,3105,3081,3060,3039,3020,3000,2979,2958,2937,2916,2898,2883,2871,2861,2850,2836,2817,2791,2758,2720,
+2681,2644,2614,2592,2578,2570,2564,2555,2538,2512,2478,2438,2398,2364,2341,2332,2337,2354,2379,2405,2428,
+2446,2456,2459,2459,2456,2453,2451,2447,2441,2429,2408,2377,2337,2288,2234,2178,2122,2069,2021,1977,1939,
+1905,1876,1851,1832,1817,1808,1804,1805,1810,1817,1823,1827,1827,1820,1807,1786,1759,1725,1689,1653,1620,
+1594,1577,1569,1570,1576,1585,1591,1592,1584,1568,1545,1518,1491,1467,1448,1436,1428,1421,1411,1394,1367,
+1330,1283,1230,1175,1123,1079,1046,1025,1017,1018,1025,1033,1037,1035,1025,1005,977,945,913,884,862,
+848,843,842,843,839,826,799,759,706,645,581,522,471,433,406,388,373,355,329,291,240,
+180,115,52,-2,-44,-73,-90,-100,-107,-116,-132,-154,-182,-210,-235,-254,-265,-269,-271,-276,-290,
+-318,-361,-419,-489,-564,-639,-706,-765,-812,-851,-884,-915,-948,-983,-1021,-1060,-1098,-1131,-1161,-1185,-1208,
+-1231,-1258,-1291,-1330,-1374,-1422,-1469,-1514,-1555,-1592,-1624,-1655,-1684,-1713,-1743,-1771,-1796,-1816,-1828,-1833,-1830,
+-1820,-1806,-1790,-1775,-1761,-1752,-1749,-1754,-1770,-1800,-1845,-1906,-1982,-2070,-2164,-2257,-2343,-2415,-2471,-2510,-2535,
+-2551,-2565,-2582,-2605,-2636,-2672,-2709,-2742,-2767,-2782,-2786,-2782,-2773,-2765,-2763,-2768,-2781,-2801,-2826,-2851,-2873,
+-2890,-2902,-2909,-2914,-2918,-2924,-2934,-2948,-2966,-2988,-3012,-3038,-3064,-3091,-3120,-3151,-3187,-3229,-3278,-3333,-3394,
+-3458,-3523,-3584,-3638,-3682,-3712,-3729,-3732,-3724,-3709,-3689,-3670,-3654,-3644,-3640,-3641,-3646,-3655,-3666,-3678,-3691,
+-3708,-3728,-3752,-3781,-3813,-3846,-3879,-3908,-3931,-3948,-3959,-3966,-3971,-3975,-3982,-3992,-4004,-4016,-4028,-4037,-4041,
+-4041,-4038,-4032,-4028,-4026,-4029,-4036,-4048,-4063,-4080,-4099,-4119,-4141,-4166,-4194,-4225,-4258,-4291,-4322,-4350,-4372,
+-4391,-4407,-4424,-4446,-4474,-4510,-4553,-4601,-4651,-4698,-4739,-4772,-4797,-4816,-4832,-4847,-4864,-4882,-4901,-4919,-4933,
+-4942,-4944,-4940,-4932,-4920,-4908,-4897,-4889,-4883,-4879,-4875,-4872,-4870,-4868,-4868,-4870,-4875,-4882,-4891,-4898,-4903,
+-4904,-4900,-4891,-4879,-4866,-4854,-4847,-4844,-4848,-4859,-4875,-4897,-4921,-4948,-4974,-4999,-5020,-5036,-5046,-5049,-5047,
+-5042,-5037,-5034,-5037,-5046,-5062,-5082,-5105,-5125,-5138,-5143,-5138,-5123,-5103,-5079,-5056,-5038,-5027,-5022,-5024,-5032,
+-5042,-5055,-5069,-5084,-5102,-5123,-5148,-5174,-5202,-5229,-5252,-5271,-5284,-5292,-5296,-5298,-5301,-5305,-5313,-5324,-5338,
+-5353,-5367,-5380,-5392,-5402,-5412,-5423,-5435,-5450,-5467,-5485,-5503,-5520,-5534,-5546,-5554,-5559,-5563,-5567,-5571,-5577,
+-5585,-5595,-5607,-5621,-5635,-5648,-5662,-5674,-5686,-5697,-5708,-5718,-5728,-5738,-5748,-5756,-5762,-5765,-5767,-5766,-5765,
+-5765,-5767,-5773,-5783,-5798,-5816,-5835,-5852,-5866,-5873,-5873,-5866,-5854,-5837,-5819,-5800,-5782,-5766,-5750,-5734,-5717,
+-5699,-5681,-5663,-5647,-5634,-5626,-5621,-5620,-5621,-5621,-5620,-5617,-5610,-5602,-5593,-5584,-5577,-5572,-5569,-5566,-5563,
+-5559,-5553,-5546,-5538,-5530,-5524,-5520,-5519,-5519,-5519,-5519,-5516,-5511,-5502,-5492,-5480,-5468,-5458,-5448,-5441,-5436,
+-5432,-5429,-5427,-5425,-5422,-5419,-5414,-5409,-5402,-5395,-5388,-5381,-5376,-5372,-5371,-5372,-5374,-5378,-5380,-5381,-5379,
+-5374,-5367,-5357,-5347,-5336,-5326,-5318,-5310,-5302,-5294,-5285,-5276,-5266,-5257,-5248,-5241,-5235,-5231,-5227,-5223,-5218,
+-5211,-5203,-5193,-5183,-5173,-5165,-5158,-5153,-5149,-5145,-5141,-5136,-5129,-5121,-5113,-5104,-5095,-5086,-5076,-5066,-5055,
+-5042,-5027,-5011,-4993,-4976,-4958,-4942,-4927,-4912,-4898,-4883,-4868,-4851,-4833,-4814,-4795,-4777,-4761,-4746,-4734,-4722,
+-4712,-4701,-4690,-4678,-4665,-4652,-4640,-4628,-4618,-4611,-4605,-4601,-4597,-4594,-4590,-4585,-4579,-4572,-4564,-4555,-4546,
+-4535,-4524,-4512,-4500,-4486,-4471,-4456,-4441,-4425,-4410,-4395,-4380,-4366,-4351,-4336,-4320,-4305,-4289,-4273,-4257,-4242,
+-4228,-4214,-4199,-4184,-4169,-4152,-4134,-4115,-4095,-4074,-4052,-4030,-4006,-3983,-3959,-3935,-3912,-3890,-3869,-3849,-3831,
+-3814,-3799,-3784,-3769,-3755,-3741,-3726,-3712,-3698,-3685,-3672,-3661,-3650,-3641,-3633,-3626,-3620,-3614,-3608,-3601,-3594,
+-3586,-3577,-3567,-3556,-3546,-3536,-3528,-3520,-3512,-3505,-3497,-3489,-3479,-3468,-3455,-3442,-3429,-3417,-3405,-3395,-3385,
+-3375,-3366,-3355,-3344,-3331,-3316,-3300,-3283,-3266,-3248,-3231,-3215,-3200,-3186,-3173,-3160,-3146,-3132,-3117,-3100,-3081,
+-3062,-3041,-3020,-2999,-2980,-2961,-2943,-2927,-2911,-2897,-2885,-2874,-2866,-2860,-2856,-2853,-2850,-2847,-2841,-2834,-2823,
+-2809,-2794,-2778,-2762,-2747,-2734,-2723,-2715,-2708,-2702,-2698,-2693,-2690,-2686,-2682,-2676,-2669,-2660,-2648,-2634,-2618,
+-2600,-2582,-2564,-2548,-2534,-2520,-2509,-2497,-2486,-2474,-2462,-2449,-2435,-2420,-2403,-2384,-2362,-2338,-2311,-2282,-2253,
+-2225,-2200,-2178,-2161,-2147,-2135,-2124,-2112,-2097,-2080,-2061,-2040,-2019,-2000,-1982,-1966,-1950,-1935,-1917,-1896,-1872,
+-1844,-1814,-1782,-1750,-1721,-1694,-1671,-1651,-1633,-1616,-1598,-1577,-1553,-1526,-1495,-1462,-1429,-1398,-1371,-1348,-1330,
+-1316,-1304,-1293,-1280,-1264,-1243,-1219,-1191,-1162,-1134,-1107,-1084,-1064,-1046,-1031,-1017,-1002,-986,-969,-950,-929,
+-908,-885,-860,-835,-807,-778,-748,-718,-687,-657,-628,-598,-569,-538,-505,-470,-432,-392,-351,-311,-272,
+-236,-202,-169,-135,-99,-58,-12,39,96,156,216,273,324,367,403,432,456,479,504,534,572,
+619,671,728,784,835,876,906,923,928,925,917,909,905,907,914,926,941,955,967,978,987,
+997,1011,1030,1055,1086,1119,1151,1178,1196,1204,1203,1193,1179,1164,1151,1142,1138,1137,1137,1137,1135,
+1131,1126,1122,1121,1126,1136,1152,1172,1194,1217,1237,1252,1262,1265,1260,1247,1225,1195,1158,1115,1069,
+1023,980,944,915,894,882,875,872,871,870,868,866,864,864,865,869,875,882,888,892,895,
+895,894,892,891,890,890,891,893,895,897,900,903,908,915,924,935,946,958,968,977,982,
+985,985,983,979,975,970,965,960,955,951,946,942,938,934,929,925,920,915,910,905,901,
+896,892,888,884,880,876,872,867,864,860,859,858,859,861,863,866,867,867,866,863,857,
+851,843,835,827,819,813,807,803,800,797,794,791,787,782,777,770,762,755,747,739,732,
+726,720,715,711,708,705,702,700,698,696,693,691,688,685,681,676,671,665,658,652,646,
+641,637,635,635,636,638,640,642,643,644,643,643,643,644,646,649,654,660,665,670,674,
+677,679,680,683,686,691,696,702,708,713,715,716,716,714,713,713,714,715,718,720,721,
+721,719,715,711,706,704,703,705,710,718,727,738,749,762,774,786,798,810,820,830,838,
+844,850,856,862,869,878,890,902,917,933,949,966,982,998,1014,1028,1040,1050,1058,1062,1064,
+1063,1063,1063,1064,1068,1074,1083,1093,1105,1116,1126,1135,1144,1152,1160,1170,1182,1196,1212,1227,1242,
+1255,1264,1271,1276,1279,1283,1289,1297,1309,1324,1342,1362,1384,1405,1424,1442,1457,1469,1476,1481,1483,
+1483,1483,1485,1490,1500,1513,1529,1546,1561,1571,1576,1574,1565,1551,1535,1520,1510,1506,1509,1519,1533,
+1549,1563,1574,1578,1577,1570,1559,1547,1536,1528,1524,1524,1527,1532,1539,1545,1549,1552,1554,1554,1555,
+1555,1557,1558,1559,1559,1557,1554,1548,1541,1534,1526,1519,1513,1510,1507,1507,1508,1511,1515,1521,1529,
+1539,1551,1564,1579,1594,1610,1626,1641,1656,1671,1685,1699,1713,1726,1739,1752,1766,1778,1791,1801,1810,
+1815,1817,1817,1814,1814,1819,1834,1861,1903,1958,2023,2092,2157,2211,2247,2263,2258,2236,2206,2176,2154,
+2146,2155,2180,2217,2258,2297,2327,2345,2350,2346,2336,2327,2324,2331,2348,2376,2411,2450,2489,2523,2551,
+2572,2584,2591,2591,2588,2584,2577,2571,2564,2556,2546,2536,2524,2512,2502,2497,2499,2512,2539,2579,2633,
+2697,2768,2839,2907,2965,3011,3046,3069,3086,3099,3113,3132,3158,3190,3229,3271,3314,3357,3398,3437,3476,
+3516,3558,3604,3655,3711,3772,3836,3900,3963,4021,4071,4110,4134,4142,4131,4100,4049,3981,3899,3808,3713,
+3620,3535,3461,3402,3358,3327,3307,3294,3283,3272,3258,3239,3216,3191,3165,3139,3116,3095,3075,3055,3035,
+3013,2991,2969,2948,2931,2917,2906,2897,2887,2875,2858,2836,2809,2780,2751,2727,2707,2693,2682,2673,2660,
+2641,2614,2580,2541,2501,2466,2439,2423,2418,2422,2431,2442,2449,2451,2445,2434,2418,2401,2382,2364,2345,
+2324,2299,2270,2235,2195,2154,2112,2073,2038,2008,1982,1959,1938,1918,1898,1880,1864,1853,1847,1848,1856,
+1869,1883,1896,1904,1904,1894,1874,1844,1807,1765,1722,1682,1647,1620,1602,1591,1586,1584,1583,1579,1571,
+1557,1539,1518,1496,1478,1463,1454,1450,1447,1442,1430,1409,1376,1331,1274,1212,1148,1090,1043,1012,998,
+1001,1019,1045,1074,1098,1112,1112,1099,1073,1039,1005,977,959,955,964,982,1001,1014,1013,992,950,
+889,815,736,662,599,552,520,501,487,470,444,405,352,291,227,167,119,85,67,59,56,
+49,33,4,-37,-89,-144,-197,-241,-274,-297,-314,-332,-358,-396,-449,-516,-592,-672,-747,-814,-869,
+-911,-943,-968,-992,-1016,-1044,-1074,-1105,-1135,-1163,-1187,-1209,-1231,-1255,-1284,-1318,-1356,-1398,-1441,-1481,-1518,
+-1552,-1583,-1614,-1646,-1682,-1722,-1764,-1804,-1840,-1868,-1886,-1891,-1884,-1868,-1844,-1815,-1784,-1753,-1725,-1704,-1693,
+-1696,-1717,-1761,-1827,-1915,-2019,-2133,-2246,-2349,-2434,-2498,-2539,-2562,-2573,-2580,-2591,-2609,-2637,-2672,-2709,-2744,
+-2771,-2789,-2797,-2798,-2798,-2802,-2813,-2832,-2859,-2889,-2918,-2940,-2953,-2954,-2945,-2931,-2914,-2899,-2891,-2892,-2900,
+-2916,-2937,-2963,-2991,-3021,-3055,-3093,-3136,-3185,-3240,-3298,-3357,-3415,-3468,-3514,-3553,-3582,-3604,-3619,-3629,-3635,
+-3639,-3642,-3645,-3647,-3651,-3654,-3658,-3662,-3667,-3671,-3676,-3682,-3691,-3702,-3718,-3738,-3763,-3793,-3826,-3860,-3894,
+-3926,-3955,-3979,-4000,-4017,-4032,-4046,-4058,-4068,-4077,-4083,-4086,-4084,-4078,-4069,-4059,-4048,-4040,-4034,-4032,-4035,
+-4043,-4055,-4072,-4095,-4123,-4156,-4193,-4232,-4272,-4308,-4339,-4363,-4381,-4393,-4404,-4418,-4439,-4470,-4512,-4564,-4623,
+-4684,-4740,-4789,-4826,-4851,-4867,-4876,-4884,-4893,-4906,-4925,-4946,-4969,-4991,-5008,-5019,-5023,-5022,-5017,-5010,-5002,
+-4995,-4988,-4982,-4977,-4971,-4966,-4962,-4960,-4961,-4965,-4971,-4979,-4988,-4995,-5000,-5000,-4996,-4988,-4976,-4962,-4947,
+-4935,-4926,-4923,-4927,-4939,-4958,-4983,-5012,-5043,-5071,-5096,-5113,-5124,-5127,-5126,-5123,-5121,-5123,-5130,-5143,-5161,
+-5181,-5200,-5217,-5227,-5230,-5226,-5215,-5200,-5182,-5162,-5144,-5128,-5115,-5107,-5104,-5107,-5116,-5132,-5154,-5180,-5208,
+-5237,-5263,-5284,-5301,-5312,-5319,-5324,-5329,-5334,-5342,-5353,-5366,-5379,-5392,-5404,-5414,-5423,-5432,-5441,-5453,-5468,
+-5487,-5507,-5529,-5550,-5569,-5585,-5597,-5606,-5612,-5617,-5622,-5628,-5636,-5646,-5657,-5669,-5680,-5691,-5700,-5708,-5716,
+-5724,-5733,-5744,-5757,-5771,-5787,-5801,-5811,-5818,-5818,-5812,-5801,-5788,-5775,-5767,-5766,-5774,-5791,-5816,-5846,-5878,
+-5908,-5931,-5948,-5957,-5959,-5955,-5949,-5941,-5933,-5922,-5909,-5893,-5871,-5843,-5812,-5779,-5747,-5719,-5697,-5683,-5677,
+-5676,-5679,-5682,-5683,-5681,-5676,-5669,-5660,-5651,-5644,-5639,-5635,-5632,-5628,-5623,-5617,-5609,-5601,-5593,-5586,-5581,
+-5578,-5577,-5575,-5574,-5570,-5565,-5558,-5549,-5539,-5528,-5517,-5507,-5497,-5488,-5481,-5474,-5469,-5465,-5461,-5458,-5454,
+-5451,-5446,-5441,-5436,-5431,-5428,-5426,-5426,-5428,-5430,-5433,-5434,-5434,-5431,-5426,-5419,-5412,-5405,-5399,-5393,-5388,
+-5383,-5376,-5368,-5358,-5346,-5334,-5323,-5313,-5305,-5300,-5297,-5295,-5293,-5290,-5285,-5279,-5271,-5262,-5252,-5243,-5233,
+-5223,-5214,-5203,-5193,-5181,-5170,-5159,-5150,-5142,-5135,-5128,-5121,-5112,-5102,-5089,-5073,-5056,-5039,-5023,-5007,-4994,
+-4982,-4971,-4959,-4945,-4930,-4913,-4894,-4875,-4856,-4838,-4823,-4809,-4798,-4787,-4775,-4763,-4749,-4734,-4719,-4703,-4690,
+-4678,-4669,-4662,-4657,-4653,-4650,-4646,-4640,-4633,-4626,-4617,-4607,-4598,-4588,-4577,-4565,-4553,-4539,-4523,-4507,-4490,
+-4472,-4454,-4436,-4418,-4400,-4382,-4364,-4346,-4329,-4313,-4298,-4284,-4271,-4258,-4245,-4231,-4216,-4198,-4179,-4159,-4137,
+-4114,-4091,-4068,-4046,-4023,-4001,-3979,-3958,-3937,-3916,-3896,-3877,-3860,-3843,-3827,-3812,-3798,-3784,-3770,-3756,-3743,
+-3729,-3716,-3703,-3691,-3680,-3669,-3660,-3652,-3645,-3639,-3633,-3627,-3620,-3613,-3605,-3597,-3588,-3579,-3571,-3562,-3554,
+-3545,-3536,-3525,-3514,-3501,-3487,-3473,-3458,-3444,-3431,-3420,-3409,-3399,-3389,-3379,-3367,-3354,-3340,-3324,-3307,-3290,
+-3273,-3256,-3240,-3225,-3211,-3197,-3183,-3169,-3156,-3142,-3128,-3113,-3097,-3080,-3062,-3043,-3024,-3004,-2984,-2966,-2948,
+-2933,-2919,-2908,-2898,-2891,-2885,-2880,-2876,-2872,-2868,-2863,-2857,-2850,-2841,-2831,-2820,-2807,-2794,-2781,-2768,-2757,
+-2748,-2741,-2736,-2734,-2731,-2729,-2725,-2719,-2710,-2696,-2680,-2661,-2641,-2621,-2602,-2585,-2570,-2556,-2543,-2530,-2517,
+-2503,-2489,-2475,-2460,-2445,-2428,-2411,-2391,-2368,-2343,-2315,-2286,-2257,-2230,-2206,-2186,-2170,-2158,-2147,-2137,-2126,
+-2112,-2096,-2078,-2058,-2038,-2018,-1998,-1979,-1961,-1941,-1920,-1897,-1872,-1845,-1818,-1790,-1763,-1739,-1716,-1695,-1676,
+-1657,-1638,-1617,-1595,-1570,-1542,-1512,-1480,-1449,-1419,-1391,-1367,-1347,-1331,-1317,-1304,-1291,-1276,-1258,-1237,-1213,
+-1188,-1162,-1137,-1114,-1094,-1076,-1059,-1044,-1028,-1012,-996,-978,-960,-941,-922,-901,-880,-856,-829,-800,-767,
+-733,-697,-662,-628,-595,-564,-534,-504,-473,-440,-404,-364,-321,-276,-227,-176,-123,-68,-11,47,106,
+164,218,268,310,343,369,387,400,413,429,452,485,529,583,644,707,767,818,855,878,886,
+883,871,858,847,842,844,853,868,884,898,910,917,922,926,932,943,958,979,1004,1029,1052,
+1070,1082,1087,1088,1085,1081,1078,1076,1076,1076,1076,1074,1071,1066,1062,1059,1061,1067,1079,1095,1114,
+1133,1152,1167,1178,1184,1182,1174,1158,1135,1103,1066,1023,978,933,892,858,831,814,804,801,801,
+803,806,807,807,806,806,808,811,816,822,828,833,837,839,840,841,841,842,843,844,845,
+847,847,848,850,853,857,864,873,883,894,904,912,918,922,922,921,917,913,908,903,899,
+894,890,886,882,879,876,873,871,869,868,866,865,863,860,857,853,849,844,840,836,832,
+829,826,823,821,819,817,816,814,812,810,807,804,799,794,788,782,775,767,761,755,750,
+746,743,741,739,736,733,729,724,718,711,705,698,691,685,680,676,672,669,665,662,658,
+655,651,647,643,640,637,635,632,630,627,624,621,617,614,611,609,609,609,611,613,616,
+619,622,625,628,632,636,641,647,653,659,665,670,674,676,678,680,682,683,686,689,691,
+694,695,695,695,694,693,693,693,694,696,697,698,698,696,694,691,688,686,686,688,692,
+698,707,716,727,738,750,762,774,786,797,808,817,826,833,840,846,853,862,872,884,897,
+911,926,941,956,972,988,1005,1021,1036,1049,1059,1067,1072,1073,1074,1075,1076,1080,1086,1095,1105,
+1109,1119,1129,1137,1143,1148,1153,1158,1164,1173,1184,1196,1208,1221,1232,1241,1250,1257,1264,1272,1282,
+1294,1308,1325,1345,1365,1387,1408,1428,1445,1459,1468,1472,1473,1472,1470,1469,1473,1482,1496,1516,1537,
+1558,1575,1585,1585,1576,1558,1535,1511,1490,1475,1469,1472,1484,1501,1519,1536,1549,1555,1555,1549,1540,
+1529,1519,1512,1508,1506,1507,1509,1511,1513,1515,1517,1519,1522,1527,1531,1536,1539,1540,1539,1535,1529,
+1522,1515,1509,1504,1501,1500,1499,1500,1500,1502,1505,1510,1518,1528,1542,1559,1577,1595,1612,1627,1639,
+1649,1658,1666,1675,1685,1697,1711,1727,1742,1758,1772,1783,1792,1798,1803,1807,1814,1825,1844,1873,1914,
+1966,2028,2095,2160,2218,2261,2287,2291,2277,2249,2214,2182,2159,2153,2166,2197,2242,2293,2343,2385,2414,
+2428,2430,2423,2412,2405,2405,2415,2437,2467,2502,2538,2570,2595,2610,2614,2610,2598,2581,2563,2545,2529,
+2515,2504,2495,2487,2480,2474,2471,2472,2479,2496,2525,2566,2618,2681,2749,2818,2883,2939,2983,3013,3032,
+3041,3046,3053,3066,3090,3126,3174,3233,3298,3365,3429,3487,3538,3581,3618,3651,3684,3721,3764,3813,3869,
+3928,3987,4040,4083,4110,4119,4106,4071,4017,3946,3864,3776,3688,3606,3534,3474,3428,3396,3374,3359,3348,
+3337,3324,3307,3287,3264,3240,3216,3195,3176,3158,3141,3123,3101,3077,3049,3020,2992,2967,2946,2931,2919,
+2910,2900,2889,2874,2855,2834,2812,2791,2774,2760,2748,2736,2721,2701,2674,2641,2604,2566,2531,2503,2483,
+2472,2467,2465,2462,2454,2439,2417,2388,2355,2319,2283,2249,2217,2185,2154,2122,2090,2058,2028,2001,1978,
+1960,1946,1934,1923,1910,1895,1877,1858,1840,1826,1819,1820,1830,1846,1865,1884,1897,1901,1894,1876,1848,
+1812,1772,1732,1695,1663,1638,1619,1605,1593,1583,1571,1557,1541,1522,1503,1486,1471,1461,1455,1453,1453,
+1453,1448,1435,1412,1376,1329,1273,1210,1148,1091,1045,1015,1003,1010,1032,1064,1099,1130,1150,1156,1145,
+1121,1088,1055,1029,1017,1021,1040,1071,1104,1130,1139,1126,1087,1026,947,862,779,708,654,616,592,
+574,555,527,488,437,377,317,263,221,194,180,177,174,166,146,109,58,-3,-69,-133,-189,
+-234,-270,-300,-332,-370,-420,-483,-557,-636,-715,-788,-850,-898,-934,-960,-982,-1001,-1023,-1047,-1073,-1100,
+-1125,-1148,-1169,-1189,-1210,-1235,-1264,-1299,-1337,-1376,-1414,-1447,-1477,-1503,-1529,-1556,-1588,-1627,-1671,-1719,-1766,
+-1809,-1842,-1863,-1872,-1868,-1854,-1832,-1806,-1776,-1746,-1718,-1695,-1680,-1678,-1694,-1732,-1792,-1875,-1975,-2084,-2193,
+-2294,-2376,-2438,-2478,-2501,-2513,-2522,-2535,-2556,-2585,-2621,-2658,-2690,-2715,-2730,-2737,-2741,-2746,-2758,-2779,-2809,
+-2847,-2885,-2919,-2942,-2951,-2946,-2929,-2906,-2881,-2861,-2849,-2847,-2855,-2869,-2888,-2911,-2936,-2964,-2997,-3037,-3086,
+-3143,-3206,-3271,-3334,-3391,-3438,-3473,-3496,-3510,-3518,-3523,-3529,-3537,-3550,-3565,-3582,-3599,-3615,-3628,-3639,-3647,
+-3654,-3659,-3665,-3671,-3679,-3689,-3701,-3716,-3735,-3758,-3786,-3818,-3853,-3889,-3926,-3960,-3991,-4017,-4039,-4055,-4068,
+-4077,-4084,-4088,-4090,-4089,-4086,-4081,-4074,-4066,-4058,-4051,-4046,-4044,-4047,-4057,-4072,-4095,-4125,-4161,-4202,-4244,
+-4285,-4322,-4354,-4378,-4395,-4408,-4419,-4434,-4457,-4490,-4534,-4588,-4649,-4711,-4769,-4818,-4855,-4879,-4891,-4896,-4899,
+-4903,-4913,-4930,-4954,-4984,-5015,-5045,-5070,-5087,-5097,-5100,-5096,-5089,-5081,-5072,-5065,-5060,-5056,-5053,-5053,-5053,
+-5055,-5059,-5064,-5070,-5076,-5083,-5088,-5090,-5088,-5081,-5069,-5052,-5032,-5010,-4989,-4972,-4962,-4961,-4970,-4990,-5018,
+-5052,-5089,-5125,-5156,-5180,-5195,-5203,-5205,-5203,-5200,-5201,-5205,-5215,-5231,-5250,-5271,-5291,-5308,-5320,-5324,-5321,
+-5311,-5295,-5274,-5250,-5228,-5208,-5195,-5188,-5190,-5200,-5217,-5238,-5260,-5282,-5300,-5314,-5323,-5329,-5334,-5340,-5347,
+-5359,-5373,-5390,-5408,-5425,-5439,-5451,-5460,-5467,-5475,-5484,-5496,-5512,-5531,-5552,-5574,-5596,-5614,-5630,-5641,-5650,
+-5657,-5664,-5671,-5680,-5691,-5703,-5716,-5728,-5739,-5748,-5754,-5759,-5763,-5768,-5775,-5784,-5797,-5812,-5828,-5842,-5851,
+-5855,-5851,-5839,-5820,-5799,-5778,-5762,-5755,-5758,-5774,-5799,-5832,-5869,-5906,-5939,-5966,-5988,-6004,-6016,-6025,-6034,
+-6041,-6046,-6046,-6039,-6023,-5999,-5966,-5927,-5887,-5847,-5813,-5787,-5769,-5759,-5754,-5752,-5751,-5748,-5743,-5736,-5727,
+-5719,-5712,-5706,-5702,-5700,-5697,-5694,-5688,-5682,-5673,-5664,-5655,-5647,-5640,-5634,-5630,-5626,-5623,-5620,-5616,-5611,
+-5605,-5598,-5589,-5579,-5567,-5555,-5542,-5530,-5520,-5511,-5504,-5499,-5496,-5493,-5490,-5487,-5484,-5481,-5478,-5477,-5478,
+-5480,-5483,-5487,-5490,-5492,-5492,-5490,-5486,-5481,-5475,-5470,-5465,-5461,-5456,-5450,-5443,-5434,-5423,-5411,-5400,-5390,
+-5381,-5376,-5372,-5370,-5369,-5368,-5365,-5361,-5355,-5348,-5340,-5330,-5320,-5309,-5298,-5285,-5272,-5258,-5244,-5230,-5218,
+-5208,-5198,-5190,-5181,-5172,-5160,-5147,-5132,-5115,-5099,-5083,-5070,-5058,-5048,-5039,-5029,-5019,-5006,-4991,-4974,-4955,
+-4937,-4920,-4904,-4889,-4876,-4864,-4851,-4836,-4821,-4804,-4787,-4770,-4754,-4741,-4730,-4721,-4714,-4709,-4704,-4699,-4693,
+-4686,-4678,-4669,-4660,-4651,-4640,-4629,-4616,-4601,-4585,-4568,-4550,-4531,-4512,-4493,-4475,-4456,-4438,-4420,-4401,-4384,
+-4366,-4349,-4333,-4318,-4304,-4289,-4275,-4258,-4241,-4221,-4200,-4177,-4153,-4129,-4106,-4084,-4063,-4042,-4023,-4004,-3985,
+-3966,-3947,-3929,-3910,-3893,-3875,-3859,-3843,-3827,-3812,-3797,-3783,-3769,-3755,-3741,-3729,-3717,-3705,-3695,-3685,-3676,
+-3667,-3659,-3652,-3644,-3637,-3629,-3622,-3614,-3607,-3599,-3592,-3584,-3576,-3568,-3558,-3546,-3533,-3519,-3503,-3488,-3472,
+-3458,-3444,-3432,-3420,-3409,-3397,-3384,-3371,-3356,-3340,-3325,-3309,-3295,-3280,-3266,-3252,-3237,-3222,-3205,-3189,-3172,
+-3156,-3142,-3129,-3118,-3107,-3096,-3083,-3070,-3054,-3036,-3018,-2999,-2982,-2967,-2954,-2943,-2935,-2928,-2921,-2915,-2909,
+-2902,-2895,-2888,-2882,-2877,-2871,-2866,-2859,-2850,-2840,-2828,-2815,-2803,-2791,-2782,-2775,-2770,-2766,-2762,-2755,-2746,
+-2733,-2716,-2696,-2676,-2655,-2636,-2619,-2603,-2589,-2575,-2561,-2545,-2528,-2510,-2491,-2474,-2457,-2441,-2427,-2412,-2396,
+-2378,-2356,-2331,-2305,-2277,-2251,-2227,-2206,-2188,-2174,-2161,-2148,-2134,-2119,-2102,-2084,-2065,-2046,-2027,-2009,-1990,
+-1972,-1952,-1930,-1907,-1882,-1855,-1829,-1802,-1777,-1752,-1728,-1705,-1682,-1661,-1639,-1618,-1596,-1575,-1553,-1530,-1506,
+-1481,-1456,-1430,-1405,-1382,-1360,-1341,-1323,-1306,-1290,-1273,-1255,-1235,-1214,-1193,-1172,-1152,-1133,-1115,-1099,-1082,
+-1066,-1049,-1032,-1014,-996,-978,-960,-943,-925,-904,-881,-853,-821,-785,-746,-707,-668,-632,-598,-569,-541,
+-513,-484,-451,-412,-367,-315,-258,-197,-133,-68,-4,56,113,165,210,249,281,306,325,339,353,
+369,390,419,458,507,562,622,681,734,776,806,822,825,820,810,800,793,793,800,811,826,
+840,853,861,866,869,871,876,884,896,911,929,946,961,973,981,985,988,990,993,997,1001,
+1005,1007,1006,1003,996,989,983,981,985,995,1011,1032,1055,1077,1096,1110,1117,1117,1110,1096,1075,
+1048,1015,977,935,892,851,813,781,757,741,733,731,734,739,745,750,754,758,762,765,770,
+775,780,785,789,793,795,796,797,798,799,801,802,803,803,803,802,802,802,804,808,814,
+822,830,837,843,847,849,848,845,842,839,836,834,833,833,833,833,832,831,830,828,827,
+826,825,823,822,819,817,813,809,805,801,798,796,794,792,791,789,786,783,778,773,768,
+764,759,755,752,749,745,741,736,729,722,714,706,698,691,685,680,676,673,669,666,662,
+657,652,647,641,636,632,628,626,624,622,620,619,616,614,610,607,604,601,598,597,596,
+596,597,597,597,596,595,593,592,591,591,591,593,596,600,604,609,614,620,625,630,636,
+641,646,651,655,659,662,664,666,668,670,671,673,674,674,674,674,673,673,673,674,675,
+676,677,678,677,676,674,671,668,667,666,667,670,674,680,688,696,706,716,728,741,754,
+767,780,792,802,812,820,828,836,844,855,866,879,893,908,923,937,952,967,982,998,1014,
+1029,1043,1055,1064,1070,1074,1076,1077,1080,1084,1090,1099,1109,1092,1103,1112,1119,1125,1129,1133,1137,
+1143,1150,1160,1171,1183,1195,1207,1217,1226,1234,1242,1250,1259,1270,1282,1297,1315,1334,1355,1375,1395,
+1413,1428,1438,1444,1446,1445,1443,1443,1447,1458,1474,1497,1523,1549,1572,1587,1591,1585,1567,1541,1512,
+1483,1460,1446,1442,1448,1463,1482,1502,1519,1532,1538,1537,1531,1522,1510,1499,1488,1479,1472,1467,1464,
+1463,1464,1468,1475,1484,1495,1506,1516,1523,1527,1527,1524,1518,1511,1505,1501,1498,1498,1500,1503,1506,
+1509,1512,1517,1523,1532,1544,1559,1577,1595,1612,1626,1637,1644,1648,1651,1654,1660,1668,1680,1694,1710,
+1726,1740,1752,1761,1767,1772,1778,1787,1801,1824,1855,1898,1949,2009,2074,2139,2201,2252,2290,2311,2315,
+2303,2280,2252,2225,2208,2205,2218,2247,2290,2339,2390,2435,2469,2491,2500,2499,2492,2484,2479,2481,2491,
+2508,2529,2551,2570,2583,2588,2584,2572,2554,2533,2512,2494,2480,2472,2469,2470,2475,2481,2488,2494,2501,
+2509,2521,2539,2565,2599,2643,2693,2748,2804,2856,2901,2936,2962,2979,2992,3005,3023,3051,3093,3148,3216,
+3292,3372,3448,3517,3573,3616,3647,3669,3687,3707,3733,3767,3811,3861,3913,3962,4000,4022,4024,4005,3965,
+3908,3838,3763,3687,3617,3556,3507,3469,3443,3424,3410,3398,3384,3368,3347,3323,3297,3270,3246,3224,3205,
+3188,3173,3156,3138,3116,3090,3062,3033,3007,2985,2967,2955,2947,2940,2931,2919,2902,2880,2855,2830,2806,
+2786,2770,2758,2747,2734,2717,2693,2664,2629,2593,2558,2528,2505,2488,2477,2467,2456,2439,2415,2382,2342,
+2296,2249,2202,2158,2119,2083,2052,2023,1997,1972,1950,1931,1914,1901,1889,1878,1865,1849,1830,1807,1784,
+1762,1746,1737,1739,1750,1770,1794,1818,1838,1849,1849,1837,1815,1785,1751,1716,1683,1654,1630,1610,1592,
+1576,1560,1543,1525,1506,1487,1470,1455,1444,1435,1430,1426,1421,1415,1405,1389,1366,1335,1296,1250,1200,
+1148,1100,1060,1031,1016,1016,1029,1052,1080,1105,1121,1125,1116,1093,1063,1031,1007,994,998,1018,1049,
+1085,1116,1132,1127,1099,1048,981,906,832,767,716,679,653,631,608,577,536,484,426,367,314,
+273,244,227,217,206,189,159,116,59,-4,-71,-134,-189,-235,-272,-307,-343,-388,-442,-508,-582,
+-659,-733,-800,-855,-898,-931,-956,-979,-1002,-1027,-1055,-1084,-1112,-1138,-1161,-1181,-1199,-1219,-1243,-1271,-1304,
+-1340,-1376,-1410,-1440,-1467,-1490,-1513,-1539,-1570,-1608,-1650,-1695,-1739,-1776,-1805,-1822,-1828,-1824,-1814,-1800,-1783,
+-1768,-1753,-1741,-1733,-1731,-1738,-1757,-1792,-1845,-1914,-1996,-2086,-2175,-2256,-2324,-2375,-2410,-2432,-2447,-2462,-2482,
+-2508,-2541,-2577,-2611,-2639,-2657,-2666,-2668,-2668,-2673,-2686,-2710,-2745,-2786,-2828,-2865,-2890,-2902,-2900,-2887,-2869,
+-2852,-2841,-2838,-2844,-2857,-2874,-2893,-2912,-2931,-2952,-2979,-3013,-3058,-3112,-3174,-3240,-3304,-3361,-3407,-3441,-3463,
+-3475,-3483,-3489,-3498,-3511,-3528,-3549,-3571,-3592,-3610,-3625,-3638,-3647,-3655,-3663,-3669,-3676,-3681,-3687,-3692,-3698,
+-3707,-3721,-3742,-3770,-3806,-3847,-3891,-3935,-3976,-4011,-4039,-4059,-4072,-4079,-4083,-4085,-4085,-4085,-4084,-4083,-4080,
+-4076,-4072,-4068,-4066,-4067,-4074,-4086,-4105,-4130,-4162,-4197,-4236,-4276,-4315,-4351,-4383,-4411,-4434,-4455,-4475,-4497,
+-4524,-4558,-4598,-4645,-4697,-4749,-4798,-4840,-4874,-4897,-4911,-4919,-4924,-4930,-4942,-4960,-4986,-5018,-5053,-5088,-5119,
+-5143,-5159,-5166,-5165,-5160,-5152,-5146,-5142,-5142,-5145,-5151,-5159,-5166,-5171,-5173,-5173,-5169,-5164,-5158,-5151,-5144,
+-5137,-5128,-5117,-5102,-5085,-5065,-5044,-5024,-5009,-5001,-5002,-5013,-5034,-5064,-5100,-5138,-5175,-5208,-5233,-5251,-5262,
+-5266,-5268,-5269,-5271,-5278,-5289,-5306,-5326,-5348,-5371,-5390,-5404,-5412,-5412,-5404,-5389,-5370,-5350,-5331,-5316,-5308,
+-5307,-5312,-5323,-5337,-5352,-5364,-5374,-5379,-5381,-5382,-5383,-5387,-5394,-5407,-5422,-5441,-5459,-5476,-5490,-5501,-5509,
+-5515,-5522,-5532,-5544,-5560,-5579,-5599,-5620,-5638,-5654,-5666,-5675,-5682,-5688,-5694,-5702,-5712,-5724,-5737,-5751,-5764,
+-5775,-5784,-5791,-5797,-5802,-5807,-5815,-5824,-5836,-5849,-5862,-5872,-5878,-5878,-5871,-5857,-5838,-5817,-5797,-5782,-5776,
+-5780,-5795,-5820,-5852,-5888,-5924,-5957,-5986,-6010,-6031,-6049,-6066,-6084,-6101,-6117,-6130,-6137,-6136,-6124,-6103,-6074,
+-6038,-6000,-5963,-5928,-5899,-5875,-5856,-5841,-5828,-5816,-5804,-5793,-5782,-5772,-5763,-5757,-5752,-5749,-5746,-5743,-5739,
+-5734,-5728,-5721,-5714,-5707,-5700,-5694,-5688,-5683,-5679,-5676,-5673,-5670,-5667,-5662,-5656,-5647,-5637,-5624,-5609,-5594,
+-5580,-5567,-5556,-5548,-5542,-5537,-5533,-5529,-5526,-5523,-5521,-5521,-5522,-5526,-5532,-5539,-5546,-5551,-5554,-5555,-5553,
+-5549,-5543,-5537,-5532,-5526,-5521,-5516,-5510,-5504,-5496,-5487,-5478,-5470,-5462,-5456,-5451,-5448,-5445,-5441,-5438,-5433,
+-5427,-5421,-5414,-5407,-5399,-5391,-5382,-5371,-5360,-5346,-5332,-5317,-5303,-5288,-5275,-5262,-5250,-5237,-5224,-5210,-5195,
+-5180,-5164,-5150,-5137,-5126,-5116,-5107,-5098,-5089,-5077,-5064,-5049,-5033,-5015,-4998,-4982,-4966,-4951,-4936,-4921,-4905,
+-4888,-4871,-4854,-4837,-4822,-4808,-4796,-4785,-4776,-4768,-4760,-4752,-4743,-4735,-4726,-4717,-4707,-4697,-4686,-4674,-4660,
+-4644,-4626,-4607,-4587,-4567,-4548,-4529,-4511,-4494,-4477,-4461,-4444,-4427,-4409,-4392,-4375,-4357,-4340,-4322,-4304,-4285,
+-4265,-4243,-4221,-4198,-4174,-4151,-4129,-4107,-4087,-4067,-4048,-4030,-4012,-3995,-3977,-3960,-3943,-3927,-3910,-3894,-3877,
+-3861,-3844,-3827,-3811,-3794,-3779,-3764,-3750,-3737,-3725,-3715,-3705,-3695,-3686,-3677,-3667,-3658,-3647,-3637,-3627,-3617,
+-3608,-3600,-3593,-3586,-3580,-3572,-3564,-3554,-3542,-3529,-3515,-3500,-3485,-3471,-3458,-3445,-3432,-3419,-3405,-3391,-3376,
+-3360,-3345,-3330,-3317,-3304,-3292,-3280,-3266,-3251,-3233,-3214,-3194,-3175,-3158,-3144,-3133,-3126,-3121,-3116,-3110,-3102,
+-3090,-3075,-3058,-3039,-3022,-3006,-2993,-2984,-2976,-2970,-2964,-2957,-2949,-2940,-2930,-2921,-2913,-2906,-2900,-2895,-2888,
+-2881,-2871,-2860,-2847,-2834,-2821,-2810,-2801,-2793,-2785,-2778,-2768,-2755,-2740,-2722,-2703,-2683,-2665,-2649,-2635,-2622,
+-2610,-2595,-2579,-2560,-2538,-2516,-2494,-2474,-2457,-2443,-2432,-2421,-2410,-2397,-2380,-2359,-2335,-2310,-2284,-2260,-2237,
+-2218,-2201,-2185,-2170,-2154,-2137,-2119,-2101,-2083,-2065,-2048,-2031,-2014,-1995,-1975,-1952,-1927,-1901,-1873,-1846,-1818,
+-1790,-1763,-1736,-1710,-1685,-1660,-1637,-1616,-1597,-1580,-1563,-1547,-1530,-1512,-1491,-1469,-1445,-1420,-1396,-1374,-1354,
+-1336,-1319,-1303,-1286,-1268,-1248,-1228,-1207,-1186,-1167,-1148,-1131,-1115,-1098,-1081,-1064,-1045,-1026,-1007,-989,-972,
+-955,-937,-917,-894,-867,-836,-801,-765,-728,-692,-658,-626,-596,-566,-533,-496,-453,-403,-346,-285,-220,
+-155,-92,-32,21,70,113,151,184,213,238,262,284,307,333,363,399,441,488,539,590,638,
+680,714,737,750,755,755,752,752,754,761,772,785,799,811,822,829,836,842,850,860,873,
+888,902,915,924,928,927,922,915,910,907,908,912,919,925,930,930,926,919,911,905,903,
+908,922,942,967,995,1020,1041,1054,1058,1053,1040,1019,992,961,926,889,851,813,777,745,718,
+697,682,674,671,672,677,683,690,698,705,713,720,728,735,742,748,753,757,759,760,761,
+762,763,764,765,766,765,763,761,758,756,755,755,757,760,763,767,768,769,767,765,762,
+759,758,758,761,765,770,775,779,783,784,785,784,783,781,778,776,774,771,768,765,762,
+759,756,755,754,754,755,755,755,753,750,745,739,732,725,719,713,708,703,698,693,687,
+680,672,663,653,643,634,625,618,612,607,603,600,597,593,590,586,582,578,575,573,571,
+570,570,571,572,572,572,572,570,568,566,565,563,563,563,563,564,565,566,566,566,566,
+565,565,566,568,571,575,580,586,592,598,604,609,614,618,623,627,630,634,637,641,644,
+646,649,650,652,652,653,653,653,653,654,654,655,656,656,656,656,654,653,651,649,648,
+648,650,652,656,660,666,673,681,690,701,714,728,742,756,770,782,792,800,808,814,821,
+830,841,854,869,885,903,920,937,953,968,982,996,1008,1019,1029,1036,1042,1046,1048,1050,1053,
+1057,1063,1072,1082,1092,1066,1078,1088,1096,1101,1106,1110,1115,1121,1130,1140,1151,1163,1174,1185,1195,
+1203,1211,1218,1225,1233,1242,1253,1265,1279,1295,1311,1329,1347,1364,1379,1390,1398,1403,1405,1405,1407,
+1411,1422,1438,1461,1488,1517,1543,1562,1572,1571,1558,1536,1509,1480,1455,1437,1428,1429,1439,1454,1473,
+1490,1503,1510,1510,1505,1494,1480,1465,1450,1436,1424,1416,1411,1410,1415,1423,1436,1452,1470,1487,1502,
+1512,1518,1519,1516,1510,1504,1499,1497,1498,1503,1509,1517,1525,1532,1538,1545,1552,1561,1572,1584,1598,
+1610,1621,1629,1633,1634,1634,1633,1636,1641,1651,1664,1680,1696,1710,1721,1728,1733,1736,1741,1750,1765,
+1790,1824,1868,1921,1980,2043,2106,2167,2222,2268,2304,2329,2342,2344,2338,2328,2318,2311,2312,2322,2341,
+2369,2403,2438,2471,2498,2516,2526,2528,2525,2518,2511,2507,2507,2511,2518,2527,2534,2537,2536,2529,2516,
+2500,2483,2467,2454,2447,2447,2454,2466,2483,2501,2519,2534,2546,2553,2559,2563,2571,2583,2602,2630,2665,
+2706,2750,2793,2833,2868,2898,2924,2949,2979,3016,3064,3125,3197,3277,3358,3436,3504,3558,3596,3620,3633,
+3640,3648,3662,3685,3717,3757,3799,3836,3863,3874,3865,3837,3791,3733,3668,3604,3546,3499,3464,3442,3431,
+3426,3424,3421,3414,3400,3379,3352,3320,3286,3252,3220,3190,3163,3138,3113,3088,3064,3039,3015,2995,2980,
+2972,2970,2974,2982,2988,2991,2986,2971,2946,2913,2875,2837,2804,2778,2761,2751,2746,2741,2732,2716,2692,
+2660,2623,2585,2548,2517,2491,2471,2453,2434,2411,2380,2342,2296,2245,2193,2141,2094,2053,2017,1987,1961,
+1938,1916,1895,1875,1855,1836,1818,1799,1780,1759,1737,1714,1692,1672,1659,1655,1660,1675,1699,1727,1756,
+1782,1799,1807,1804,1789,1767,1739,1707,1676,1647,1621,1596,1574,1554,1534,1514,1495,1477,1460,1444,1430,
+1417,1404,1391,1378,1363,1348,1332,1314,1295,1275,1251,1225,1195,1162,1127,1094,1065,1043,1031,1028,1033,
+1044,1056,1065,1064,1054,1032,1002,970,941,920,913,919,937,961,985,1001,1003,989,959,916,867,
+818,774,739,712,691,670,646,612,568,516,457,398,345,299,264,235,210,183,148,103,46,
+-18,-87,-154,-214,-264,-304,-337,-367,-400,-441,-491,-552,-619,-689,-756,-816,-866,-906,-939,-968,-996,
+-1027,-1061,-1098,-1136,-1173,-1207,-1236,-1261,-1283,-1306,-1331,-1359,-1392,-1426,-1461,-1495,-1525,-1553,-1578,-1603,-1631,
+-1662,-1696,-1733,-1769,-1801,-1824,-1839,-1842,-1837,-1825,-1811,-1797,-1788,-1784,-1786,-1793,-1805,-1823,-1848,-1880,-1921,
+-1972,-2033,-2100,-2171,-2239,-2300,-2350,-2388,-2415,-2435,-2451,-2468,-2491,-2518,-2550,-2582,-2611,-2632,-2644,-2648,-2647,
+-2645,-2648,-2661,-2685,-2718,-2758,-2798,-2833,-2858,-2872,-2876,-2872,-2866,-2862,-2865,-2876,-2894,-2916,-2939,-2960,-2978,
+-2993,-3008,-3026,-3051,-3086,-3131,-3184,-3243,-3302,-3358,-3405,-3443,-3472,-3494,-3513,-3531,-3550,-3571,-3595,-3619,-3641,
+-3661,-3678,-3691,-3701,-3709,-3715,-3720,-3724,-3724,-3721,-3715,-3706,-3698,-3694,-3697,-3712,-3739,-3779,-3829,-3887,-3946,
+-4003,-4052,-4091,-4119,-4136,-4145,-4147,-4145,-4141,-4135,-4129,-4122,-4115,-4108,-4103,-4100,-4102,-4109,-4123,-4143,-4168,
+-4197,-4229,-4263,-4296,-4329,-4362,-4394,-4426,-4458,-4490,-4521,-4551,-4581,-4610,-4639,-4669,-4700,-4732,-4765,-4798,-4830,
+-4860,-4887,-4909,-4928,-4945,-4961,-4980,-5001,-5027,-5056,-5087,-5117,-5145,-5166,-5181,-5187,-5188,-5185,-5182,-5182,-5187,
+-5198,-5215,-5235,-5256,-5272,-5283,-5285,-5277,-5262,-5242,-5218,-5195,-5176,-5160,-5148,-5140,-5132,-5124,-5113,-5100,-5085,
+-5070,-5059,-5052,-5054,-5065,-5085,-5114,-5148,-5184,-5220,-5253,-5280,-5301,-5317,-5328,-5337,-5345,-5354,-5366,-5381,-5399,
+-5420,-5442,-5462,-5480,-5494,-5501,-5502,-5498,-5489,-5478,-5466,-5457,-5452,-5451,-5455,-5462,-5471,-5479,-5486,-5489,-5490,
+-5488,-5486,-5484,-5484,-5487,-5494,-5503,-5513,-5524,-5533,-5541,-5546,-5552,-5557,-5565,-5575,-5589,-5606,-5624,-5643,-5660,
+-5676,-5687,-5696,-5702,-5707,-5712,-5718,-5726,-5736,-5748,-5760,-5773,-5784,-5795,-5803,-5811,-5818,-5825,-5833,-5842,-5853,
+-5864,-5876,-5887,-5895,-5899,-5897,-5891,-5881,-5867,-5853,-5842,-5835,-5836,-5845,-5863,-5888,-5918,-5950,-5982,-6011,-6036,
+-6057,-6073,-6088,-6101,-6115,-6131,-6147,-6163,-6177,-6186,-6190,-6186,-6174,-6155,-6130,-6101,-6069,-6037,-6005,-5975,-5946,
+-5920,-5897,-5876,-5857,-5841,-5827,-5816,-5806,-5797,-5790,-5783,-5778,-5773,-5769,-5767,-5765,-5763,-5762,-5761,-5758,-5755,
+-5751,-5746,-5741,-5736,-5731,-5727,-5723,-5717,-5711,-5702,-5691,-5679,-5664,-5650,-5635,-5622,-5611,-5601,-5592,-5585,-5579,
+-5573,-5569,-5567,-5567,-5569,-5575,-5583,-5592,-5602,-5611,-5618,-5622,-5622,-5620,-5615,-5609,-5603,-5597,-5592,-5587,-5582,
+-5577,-5571,-5565,-5558,-5550,-5543,-5536,-5529,-5523,-5517,-5511,-5504,-5497,-5490,-5483,-5476,-5470,-5465,-5459,-5454,-5447,
+-5438,-5428,-5415,-5400,-5385,-5368,-5352,-5336,-5321,-5307,-5293,-5279,-5265,-5251,-5238,-5225,-5212,-5201,-5190,-5180,-5170,
+-5159,-5147,-5134,-5120,-5104,-5087,-5070,-5053,-5035,-5018,-5000,-4983,-4966,-4949,-4933,-4917,-4902,-4888,-4875,-4864,-4852,
+-4841,-4830,-4819,-4807,-4795,-4783,-4771,-4759,-4748,-4737,-4725,-4712,-4698,-4682,-4664,-4646,-4626,-4607,-4588,-4570,-4552,
+-4536,-4520,-4503,-4487,-4470,-4453,-4435,-4416,-4397,-4378,-4358,-4338,-4317,-4296,-4275,-4253,-4230,-4207,-4185,-4162,-4140,
+-4119,-4097,-4076,-4056,-4037,-4019,-4001,-3985,-3970,-3955,-3941,-3927,-3912,-3896,-3879,-3862,-3843,-3825,-3806,-3789,-3773,
+-3759,-3747,-3736,-3727,-3719,-3711,-3702,-3693,-3682,-3670,-3657,-3644,-3631,-3619,-3608,-3599,-3591,-3584,-3577,-3569,-3560,
+-3550,-3538,-3524,-3510,-3495,-3482,-3468,-3456,-3443,-3431,-3418,-3404,-3389,-3374,-3359,-3345,-3332,-3319,-3307,-3294,-3280,
+-3264,-3246,-3226,-3206,-3187,-3171,-3159,-3151,-3147,-3146,-3145,-3143,-3138,-3129,-3116,-3099,-3081,-3063,-3047,-3034,-3024,
+-3016,-3011,-3005,-2999,-2990,-2981,-2970,-2959,-2948,-2938,-2929,-2920,-2911,-2901,-2890,-2877,-2863,-2849,-2835,-2823,-2812,
+-2803,-2794,-2784,-2773,-2759,-2744,-2727,-2710,-2693,-2679,-2665,-2653,-2642,-2629,-2613,-2595,-2574,-2550,-2527,-2505,-2486,
+-2470,-2459,-2449,-2441,-2431,-2418,-2401,-2380,-2357,-2332,-2308,-2285,-2265,-2247,-2232,-2218,-2203,-2188,-2172,-2155,-2136,
+-2118,-2099,-2080,-2061,-2039,-2016,-1990,-1962,-1931,-1899,-1867,-1836,-1807,-1779,-1754,-1730,-1707,-1685,-1663,-1643,-1623,
+-1605,-1588,-1572,-1557,-1541,-1524,-1505,-1485,-1464,-1442,-1422,-1403,-1387,-1371,-1357,-1341,-1324,-1304,-1282,-1257,-1232,
+-1207,-1183,-1162,-1144,-1127,-1112,-1096,-1080,-1061,-1042,-1022,-1001,-982,-964,-948,-932,-915,-896,-875,-850,-823,
+-793,-760,-727,-692,-655,-615,-572,-524,-472,-414,-353,-291,-229,-169,-114,-64,-19,20,56,89,121,
+152,183,213,244,274,305,338,373,411,451,493,535,575,611,640,664,680,692,700,707,715,
+725,737,752,767,782,796,809,821,834,848,864,883,902,920,934,941,941,932,916,896,876,
+858,846,840,842,847,855,861,864,863,857,850,844,842,847,860,880,905,931,956,975,985,
+986,977,958,933,902,868,834,799,765,734,706,681,660,643,631,623,619,618,620,623,628,
+634,642,651,660,671,681,691,700,707,713,716,719,720,722,723,723,723,722,720,717,712,
+706,701,695,691,687,685,684,684,683,681,679,677,675,674,676,679,684,691,699,706,713,
+718,721,722,722,722,721,720,719,719,719,718,717,716,715,713,713,712,713,713,714,713,
+712,709,705,699,691,683,675,666,657,649,640,632,624,615,605,596,586,576,567,558,551,
+545,541,537,535,533,531,529,527,525,522,519,517,515,514,514,515,517,519,521,523,524,
+525,524,524,522,521,521,520,521,521,522,523,524,525,526,528,530,532,536,540,545,551,
+557,564,570,576,582,587,592,597,602,606,610,614,618,621,624,627,629,630,631,632,633,
+633,633,633,633,633,631,630,629,628,627,628,629,631,635,640,645,651,658,665,674,683,
+694,706,719,733,748,761,773,783,791,796,800,804,809,816,826,839,856,874,894,914,933,
+951,966,978,987,994,997,999,999,999,998,999,1002,1007,1015,1026,1038,1052,1066,1040,1053,1063,
+1070,1074,1078,1082,1087,1094,1103,1114,1126,1138,1151,1162,1173,1184,1194,1203,1213,1223,1232,1241,1250,
+1260,1270,1281,1293,1307,1321,1335,1348,1358,1366,1371,1374,1377,1382,1391,1406,1426,1451,1479,1506,1528,
+1542,1547,1540,1525,1503,1478,1455,1436,1426,1424,1429,1440,1454,1466,1475,1479,1476,1468,1456,1440,1424,
+1410,1397,1388,1383,1383,1388,1398,1411,1428,1447,1467,1485,1500,1511,1516,1517,1515,1511,1507,1506,1507,
+1512,1521,1531,1542,1553,1562,1570,1576,1582,1588,1595,1601,1607,1612,1615,1615,1614,1611,1609,1609,1612,
+1620,1632,1648,1664,1680,1693,1703,1710,1716,1724,1736,1756,1785,1824,1872,1928,1987,2048,2107,2162,2212,
+2256,2294,2328,2356,2381,2401,2416,2428,2436,2442,2446,2449,2453,2458,2465,2473,2481,2488,2493,2495,2493,
+2488,2481,2474,2468,2464,2463,2464,2468,2472,2476,2479,2478,2474,2467,2459,2450,2444,2441,2444,2453,2468,
+2488,2510,2532,2552,2568,2579,2584,2586,2587,2590,2596,2609,2629,2655,2685,2719,2752,2783,2812,2840,2869,
+2903,2945,2998,3062,3135,3215,3296,3371,3435,3486,3520,3539,3549,3552,3557,3566,3584,3610,3642,3673,3699,
+3714,3712,3692,3655,3605,3547,3488,3436,3394,3367,3355,3356,3367,3381,3395,3404,3405,3395,3376,3347,3312,
+3272,3229,3186,3141,3098,3055,3013,2973,2937,2908,2887,2878,2881,2897,2922,2954,2987,3015,3033,3035,3022,
+2992,2951,2904,2857,2817,2787,2769,2762,2762,2764,2763,2753,2732,2701,2661,2615,2569,2526,2488,2456,2427,
+2398,2368,2332,2290,2243,2190,2137,2085,2038,1997,1961,1932,1905,1881,1856,1831,1805,1778,1752,1726,1703,
+1682,1662,1644,1628,1615,1605,1602,1605,1615,1634,1660,1690,1722,1751,1774,1790,1796,1791,1778,1758,1732,
+1704,1674,1644,1615,1586,1560,1534,1511,1490,1471,1453,1437,1422,1405,1387,1368,1346,1324,1304,1285,1271,
+1261,1254,1249,1242,1232,1217,1195,1168,1138,1109,1083,1064,1052,1047,1047,1046,1042,1030,1009,979,943,
+906,873,848,833,829,833,842,851,856,852,841,824,803,781,763,747,735,722,706,682,649,
+605,553,497,439,386,338,296,258,220,177,125,64,-5,-81,-158,-229,-290,-339,-377,-406,-432,
+-459,-494,-537,-590,-649,-711,-772,-826,-873,-913,-948,-980,-1013,-1050,-1092,-1137,-1184,-1231,-1274,-1314,-1349,
+-1381,-1411,-1442,-1474,-1509,-1545,-1580,-1615,-1647,-1677,-1705,-1734,-1763,-1793,-1825,-1855,-1883,-1904,-1915,-1916,-1907,
+-1890,-1868,-1847,-1830,-1820,-1819,-1829,-1848,-1875,-1910,-1950,-1996,-2047,-2103,-2162,-2223,-2282,-2336,-2383,-2420,-2448,
+-2468,-2483,-2497,-2512,-2531,-2555,-2580,-2605,-2627,-2643,-2651,-2655,-2655,-2657,-2664,-2679,-2703,-2733,-2768,-2802,-2831,
+-2853,-2866,-2872,-2875,-2878,-2886,-2900,-2921,-2948,-2977,-3005,-3029,-3048,-3063,-3075,-3089,-3107,-3133,-3168,-3210,-3258,
+-3308,-3357,-3404,-3446,-3484,-3519,-3552,-3585,-3619,-3652,-3683,-3711,-3735,-3754,-3768,-3778,-3786,-3791,-3795,-3796,-3793,
+-3784,-3769,-3749,-3724,-3700,-3682,-3675,-3684,-3711,-3757,-3818,-3890,-3967,-4042,-4109,-4164,-4205,-4231,-4245,-4249,-4245,
+-4236,-4222,-4206,-4189,-4172,-4157,-4145,-4141,-4144,-4156,-4176,-4203,-4234,-4266,-4297,-4326,-4352,-4376,-4400,-4426,-4456,
+-4491,-4528,-4567,-4604,-4637,-4664,-4685,-4700,-4712,-4724,-4738,-4757,-4782,-4812,-4846,-4882,-4917,-4949,-4978,-5004,-5027,
+-5049,-5070,-5090,-5109,-5125,-5138,-5147,-5151,-5151,-5151,-5153,-5161,-5176,-5199,-5229,-5262,-5295,-5321,-5338,-5342,-5332,
+-5310,-5280,-5247,-5214,-5188,-5170,-5160,-5158,-5159,-5162,-5162,-5157,-5148,-5135,-5121,-5109,-5104,-5107,-5120,-5142,-5173,
+-5208,-5246,-5283,-5317,-5346,-5370,-5390,-5405,-5419,-5432,-5446,-5461,-5479,-5499,-5520,-5541,-5561,-5578,-5592,-5601,-5606,
+-5607,-5605,-5601,-5597,-5594,-5593,-5594,-5597,-5600,-5604,-5607,-5609,-5609,-5608,-5606,-5603,-5601,-5600,-5599,-5598,-5598,
+-5596,-5594,-5592,-5591,-5592,-5595,-5602,-5612,-5626,-5643,-5660,-5677,-5692,-5705,-5715,-5723,-5729,-5736,-5744,-5753,-5764,
+-5776,-5788,-5800,-5810,-5819,-5825,-5830,-5834,-5838,-5843,-5850,-5859,-5870,-5882,-5895,-5906,-5916,-5922,-5925,-5924,-5920,
+-5915,-5909,-5904,-5903,-5907,-5916,-5932,-5953,-5978,-6006,-6033,-6059,-6082,-6101,-6115,-6126,-6135,-6142,-6150,-6158,-6168,
+-6180,-6191,-6202,-6210,-6215,-6213,-6206,-6192,-6172,-6147,-6117,-6085,-6052,-6021,-5991,-5966,-5944,-5925,-5909,-5895,-5881,
+-5869,-5856,-5843,-5832,-5822,-5815,-5812,-5811,-5813,-5817,-5820,-5823,-5823,-5821,-5817,-5811,-5804,-5797,-5790,-5784,-5778,
+-5772,-5766,-5758,-5748,-5737,-5724,-5711,-5698,-5686,-5674,-5664,-5655,-5647,-5640,-5634,-5631,-5630,-5632,-5637,-5644,-5654,
+-5664,-5674,-5682,-5687,-5690,-5689,-5687,-5683,-5679,-5674,-5669,-5665,-5660,-5654,-5648,-5640,-5632,-5623,-5614,-5606,-5598,
+-5590,-5583,-5575,-5568,-5560,-5552,-5544,-5537,-5530,-5525,-5519,-5514,-5508,-5501,-5493,-5482,-5468,-5453,-5437,-5420,-5403,
+-5387,-5371,-5357,-5343,-5330,-5318,-5305,-5293,-5281,-5269,-5258,-5246,-5234,-5222,-5209,-5195,-5181,-5165,-5149,-5131,-5114,
+-5095,-5077,-5058,-5040,-5022,-5005,-4990,-4975,-4961,-4949,-4937,-4926,-4915,-4904,-4892,-4879,-4865,-4850,-4835,-4819,-4805,
+-4790,-4776,-4762,-4748,-4734,-4718,-4702,-4685,-4668,-4649,-4631,-4613,-4595,-4577,-4559,-4542,-4525,-4507,-4490,-4472,-4453,
+-4435,-4415,-4396,-4376,-4355,-4335,-4313,-4292,-4270,-4248,-4225,-4202,-4178,-4154,-4130,-4106,-4083,-4061,-4040,-4021,-4004,
+-3989,-3975,-3962,-3950,-3937,-3924,-3909,-3893,-3876,-3858,-3840,-3822,-3806,-3791,-3779,-3768,-3760,-3754,-3748,-3742,-3735,
+-3727,-3716,-3704,-3690,-3676,-3662,-3649,-3636,-3625,-3615,-3606,-3596,-3585,-3572,-3557,-3541,-3524,-3507,-3492,-3478,-3465,
+-3454,-3444,-3433,-3422,-3410,-3396,-3381,-3366,-3351,-3336,-3321,-3307,-3292,-3277,-3261,-3244,-3228,-3214,-3201,-3192,-3186,
+-3183,-3182,-3182,-3180,-3175,-3167,-3155,-3140,-3123,-3106,-3090,-3077,-3066,-3058,-3051,-3045,-3037,-3029,-3019,-3008,-2996,
+-2984,-2972,-2960,-2948,-2936,-2923,-2909,-2894,-2879,-2865,-2851,-2838,-2827,-2816,-2806,-2796,-2784,-2771,-2756,-2741,-2725,
+-2710,-2696,-2683,-2670,-2656,-2641,-2623,-2604,-2583,-2561,-2541,-2523,-2508,-2496,-2487,-2478,-2468,-2455,-2438,-2418,-2395,
+-2371,-2347,-2326,-2308,-2293,-2281,-2270,-2259,-2247,-2233,-2215,-2196,-2174,-2152,-2127,-2101,-2073,-2042,-2008,-1970,-1929,
+-1886,-1844,-1805,-1770,-1740,-1717,-1698,-1684,-1673,-1661,-1650,-1636,-1621,-1605,-1587,-1568,-1549,-1529,-1510,-1491,-1472,
+-1454,-1438,-1423,-1410,-1399,-1388,-1376,-1362,-1345,-1323,-1297,-1269,-1240,-1211,-1185,-1162,-1143,-1127,-1112,-1098,-1082,
+-1064,-1043,-1021,-998,-975,-955,-937,-923,-910,-897,-884,-869,-849,-825,-795,-760,-720,-675,-625,-570,-512,
+-452,-391,-330,-272,-218,-170,-126,-87,-51,-17,15,50,85,122,158,193,226,257,285,312,338,
+366,397,430,466,503,539,572,602,626,647,664,679,695,711,729,748,769,791,811,832,852,
+872,891,911,930,947,959,965,963,952,932,906,877,848,824,806,796,794,797,804,810,814,
+813,809,803,797,794,797,806,821,841,863,882,897,904,901,890,869,842,810,776,741,707,
+676,649,625,605,590,578,570,564,561,560,561,563,565,570,576,584,593,604,616,627,638,
+647,655,661,664,667,668,669,668,667,664,660,654,647,638,629,620,612,605,599,596,594,
+592,592,592,592,593,595,599,603,609,616,623,630,636,641,644,646,648,649,650,652,654,
+657,660,662,664,665,665,665,663,662,660,658,656,653,651,647,643,637,631,623,613,603,
+592,581,570,558,547,537,527,517,508,499,491,484,478,473,469,465,463,462,462,462,461,
+461,460,459,457,455,454,453,454,455,457,460,463,467,469,471,471,471,471,471,470,471,
+471,473,474,477,479,482,484,487,490,494,498,503,508,514,521,528,535,542,549,556,562,
+568,573,579,583,588,592,595,599,602,605,608,610,611,612,612,612,611,610,608,607,607,
+607,609,612,617,623,630,638,647,656,665,675,685,696,708,720,734,747,760,773,783,792,
+799,804,808,811,816,822,830,841,855,871,888,905,921,935,947,954,958,959,956,952,947,
+943,942,943,949,959,973,990,1007,1025,1040,1022,1032,1038,1041,1042,1042,1044,1049,1056,1065,1077,
+1090,1104,1118,1133,1149,1164,1180,1196,1211,1225,1238,1248,1256,1262,1267,1272,1279,1287,1298,1310,1322,
+1334,1344,1351,1356,1361,1367,1376,1390,1410,1434,1462,1489,1512,1529,1536,1533,1520,1501,1479,1457,1441,
+1431,1429,1435,1445,1457,1468,1475,1476,1472,1462,1448,1433,1419,1407,1399,1396,1397,1402,1411,1422,1436,
+1450,1465,1480,1493,1504,1512,1518,1520,1522,1522,1524,1527,1533,1541,1551,1562,1573,1582,1590,1597,1601,
+1605,1609,1613,1616,1619,1621,1622,1621,1619,1617,1616,1617,1621,1630,1641,1655,1669,1683,1696,1707,1719,
+1734,1753,1780,1817,1863,1918,1978,2039,2099,2154,2201,2240,2272,2299,2325,2350,2378,2407,2438,2468,2495,
+2515,2527,2530,2524,2512,2495,2476,2457,2440,2425,2413,2403,2394,2386,2378,2371,2366,2363,2364,2369,2377,
+2389,2403,2417,2430,2440,2446,2448,2448,2447,2446,2448,2454,2465,2482,2501,2524,2546,2567,2585,2599,2610,
+2619,2628,2637,2649,2662,2678,2694,2709,2723,2735,2746,2759,2776,2800,2836,2884,2945,3016,3094,3172,3245,
+3308,3358,3393,3415,3428,3436,3446,3460,3480,3505,3533,3559,3576,3581,3569,3540,3497,3444,3386,3332,3287,
+3256,3240,3239,3252,3273,3297,3319,3335,3341,3337,3321,3295,3261,3220,3174,3125,3074,3021,2968,2917,2869,
+2828,2797,2778,2774,2786,2813,2852,2898,2944,2985,3015,3028,3023,3002,2967,2925,2882,2843,2814,2795,2786,
+2783,2782,2776,2762,2737,2701,2655,2604,2551,2501,2454,2413,2376,2341,2305,2265,2221,2173,2123,2071,2023,
+1978,1939,1906,1876,1849,1822,1794,1764,1733,1701,1670,1642,1618,1599,1585,1576,1570,1568,1569,1574,1583,
+1597,1617,1641,1669,1699,1729,1755,1776,1790,1796,1793,1783,1767,1745,1718,1689,1659,1627,1596,1566,1539,
+1514,1492,1472,1454,1436,1418,1398,1376,1353,1331,1311,1296,1287,1285,1287,1293,1298,1299,1293,1277,1253,
+1222,1188,1155,1126,1104,1091,1083,1078,1072,1061,1042,1014,978,937,896,859,829,808,796,792,791,
+792,792,789,784,778,772,767,763,758,750,735,712,679,637,587,532,478,426,378,334,292,
+247,197,138,70,-6,-87,-168,-243,-308,-361,-401,-433,-460,-487,-519,-559,-606,-659,-716,-771,-823,
+-868,-908,-944,-978,-1013,-1052,-1096,-1143,-1193,-1244,-1293,-1339,-1382,-1421,-1459,-1495,-1531,-1568,-1604,-1640,-1673,
+-1705,-1734,-1761,-1788,-1815,-1843,-1871,-1898,-1921,-1937,-1945,-1944,-1933,-1915,-1894,-1873,-1856,-1848,-1851,-1864,-1889,
+-1924,-1967,-2015,-2069,-2124,-2182,-2238,-2293,-2343,-2387,-2424,-2453,-2475,-2491,-2504,-2515,-2528,-2543,-2561,-2579,-2598,
+-2614,-2627,-2636,-2643,-2650,-2659,-2672,-2690,-2714,-2742,-2771,-2798,-2820,-2837,-2849,-2856,-2864,-2873,-2888,-2908,-2934,
+-2964,-2994,-3023,-3047,-3068,-3084,-3098,-3113,-3131,-3153,-3181,-3215,-3252,-3292,-3333,-3374,-3416,-3459,-3503,-3547,-3593,
+-3638,-3680,-3717,-3747,-3771,-3787,-3798,-3805,-3811,-3815,-3818,-3818,-3814,-3802,-3782,-3754,-3721,-3689,-3662,-3648,-3653,
+-3679,-3727,-3794,-3875,-3963,-4049,-4128,-4195,-4246,-4281,-4300,-4307,-4302,-4289,-4270,-4247,-4222,-4198,-4178,-4165,-4160,
+-4166,-4182,-4208,-4240,-4273,-4306,-4334,-4358,-4376,-4392,-4409,-4431,-4459,-4494,-4535,-4578,-4620,-4655,-4680,-4696,-4703,
+-4705,-4707,-4714,-4729,-4755,-4791,-4835,-4882,-4929,-4971,-5005,-5031,-5050,-5062,-5072,-5079,-5087,-5094,-5101,-5106,-5110,
+-5112,-5116,-5122,-5134,-5153,-5181,-5216,-5254,-5291,-5322,-5341,-5347,-5338,-5317,-5287,-5254,-5223,-5200,-5187,-5185,-5191,
+-5201,-5212,-5219,-5219,-5212,-5199,-5184,-5170,-5163,-5164,-5176,-5198,-5230,-5267,-5306,-5344,-5378,-5407,-5429,-5446,-5459,
+-5470,-5482,-5494,-5510,-5528,-5550,-5573,-5598,-5622,-5646,-5666,-5684,-5697,-5706,-5711,-5712,-5710,-5707,-5702,-5698,-5694,
+-5691,-5689,-5688,-5688,-5689,-5690,-5691,-5691,-5691,-5690,-5687,-5682,-5675,-5667,-5658,-5649,-5642,-5638,-5638,-5642,-5650,
+-5661,-5675,-5689,-5703,-5716,-5727,-5737,-5747,-5757,-5769,-5782,-5798,-5815,-5832,-5848,-5861,-5871,-5877,-5879,-5878,-5876,
+-5874,-5873,-5875,-5881,-5890,-5901,-5915,-5930,-5945,-5958,-5968,-5975,-5979,-5980,-5977,-5974,-5970,-5967,-5968,-5973,-5983,
+-5998,-6017,-6041,-6066,-6091,-6115,-6135,-6150,-6162,-6169,-6174,-6177,-6180,-6185,-6192,-6201,-6212,-6222,-6231,-6235,-6234,
+-6227,-6212,-6191,-6165,-6137,-6109,-6082,-6058,-6039,-6022,-6008,-5996,-5982,-5968,-5951,-5934,-5916,-5899,-5885,-5875,-5869,
+-5868,-5869,-5872,-5876,-5878,-5877,-5875,-5870,-5864,-5857,-5850,-5843,-5838,-5832,-5826,-5819,-5812,-5803,-5793,-5782,-5772,
+-5762,-5753,-5744,-5737,-5730,-5724,-5719,-5716,-5714,-5713,-5715,-5719,-5724,-5729,-5735,-5739,-5743,-5745,-5745,-5745,-5743,
+-5742,-5740,-5738,-5735,-5730,-5724,-5716,-5706,-5695,-5683,-5672,-5662,-5653,-5645,-5639,-5633,-5627,-5621,-5614,-5607,-5599,
+-5590,-5582,-5575,-5568,-5560,-5553,-5544,-5534,-5523,-5509,-5494,-5478,-5461,-5444,-5428,-5412,-5397,-5383,-5369,-5356,-5344,
+-5331,-5319,-5307,-5294,-5282,-5269,-5256,-5242,-5227,-5212,-5197,-5181,-5164,-5148,-5131,-5113,-5096,-5079,-5062,-5046,-5031,
+-5016,-5003,-4991,-4979,-4968,-4957,-4946,-4933,-4919,-4904,-4888,-4871,-4853,-4836,-4818,-4801,-4785,-4769,-4753,-4737,-4721,
+-4704,-4686,-4667,-4647,-4628,-4608,-4588,-4569,-4550,-4533,-4516,-4499,-4482,-4465,-4448,-4430,-4411,-4392,-4371,-4350,-4329,
+-4307,-4285,-4262,-4239,-4215,-4191,-4166,-4142,-4117,-4093,-4070,-4049,-4029,-4011,-3994,-3979,-3966,-3954,-3942,-3930,-3918,
+-3905,-3892,-3878,-3864,-3849,-3835,-3823,-3812,-3803,-3796,-3790,-3785,-3780,-3773,-3765,-3754,-3741,-3727,-3712,-3697,-3683,
+-3670,-3658,-3646,-3633,-3619,-3603,-3585,-3566,-3545,-3525,-3506,-3490,-3477,-3466,-3458,-3450,-3442,-3432,-3420,-3406,-3390,
+-3372,-3355,-3338,-3322,-3308,-3295,-3284,-3273,-3264,-3255,-3247,-3240,-3235,-3230,-3226,-3222,-3217,-3210,-3202,-3191,-3178,
+-3164,-3150,-3136,-3123,-3111,-3100,-3090,-3080,-3071,-3061,-3050,-3039,-3027,-3016,-3004,-2992,-2980,-2967,-2953,-2939,-2924,
+-2908,-2893,-2878,-2864,-2851,-2839,-2827,-2814,-2802,-2788,-2773,-2758,-2743,-2728,-2712,-2696,-2680,-2662,-2643,-2624,-2604,
+-2585,-2567,-2553,-2541,-2532,-2525,-2519,-2510,-2499,-2484,-2465,-2444,-2421,-2399,-2380,-2364,-2352,-2343,-2335,-2326,-2315,
+-2300,-2280,-2256,-2229,-2200,-2169,-2136,-2102,-2064,-2023,-1976,-1925,-1871,-1815,-1762,-1714,-1675,-1645,-1625,-1615,-1612,
+-1612,-1613,-1612,-1608,-1598,-1584,-1566,-1545,-1523,-1502,-1482,-1463,-1446,-1432,-1420,-1410,-1400,-1392,-1383,-1372,-1358,
+-1340,-1318,-1293,-1266,-1237,-1209,-1183,-1161,-1141,-1124,-1107,-1091,-1072,-1051,-1026,-1000,-973,-946,-922,-902,-885,
+-872,-861,-851,-838,-821,-799,-770,-733,-689,-639,-584,-525,-465,-405,-349,-297,-250,-210,-175,-143,-113,
+-83,-50,-13,28,72,117,161,201,235,263,285,303,319,337,359,386,418,455,494,534,571,
+604,633,659,683,706,731,758,787,819,852,884,913,939,960,977,988,994,994,989,978,961,
+938,911,881,851,823,800,782,771,766,765,767,768,767,763,757,750,744,740,742,748,760,
+775,792,807,817,822,818,806,785,758,727,692,656,621,589,560,535,515,501,491,485,483,
+483,486,489,493,498,504,510,518,527,537,549,560,571,581,589,596,600,603,604,604,603,
+600,597,591,584,576,566,556,546,537,529,523,519,518,517,518,520,522,524,527,530,535,
+540,545,551,557,563,567,571,575,577,579,581,583,586,589,592,595,598,600,601,600,599,
+596,592,588,584,579,575,570,565,559,553,546,537,528,517,506,494,482,470,459,448,438,
+430,422,415,408,402,396,392,388,385,384,384,384,386,388,389,390,391,391,391,391,392,
+393,395,397,400,404,407,410,412,414,415,416,417,418,420,422,424,427,431,434,438,442,
+446,450,454,459,464,470,476,484,491,499,507,514,522,528,535,541,546,551,557,562,567,
+572,577,581,584,587,589,590,591,592,592,593,595,598,601,606,612,619,627,636,645,655,
+665,675,686,697,708,720,732,744,756,769,781,794,805,817,827,836,845,853,860,867,874,
+880,887,894,900,906,911,914,915,914,911,907,902,898,897,900,906,918,933,952,972,992,
+1009,1022,1021,1025,1025,1022,1018,1015,1015,1018,1024,1033,1045,1058,1073,1089,1107,1125,1145,1166,1188,
+1210,1229,1246,1260,1270,1276,1280,1283,1287,1292,1299,1308,1317,1326,1334,1341,1346,1351,1358,1369,1386,
+1409,1436,1467,1497,1522,1540,1548,1544,1531,1511,1489,1468,1453,1447,1449,1460,1477,1495,1512,1524,1529,
+1528,1521,1509,1496,1484,1474,1467,1464,1464,1465,1468,1472,1475,1479,1483,1487,1492,1498,1505,1513,1521,
+1529,1538,1547,1556,1565,1574,1582,1590,1597,1603,1608,1613,1618,1623,1630,1637,1645,1653,1661,1667,1673,
+1677,1680,1684,1688,1694,1701,1709,1718,1728,1738,1749,1763,1780,1803,1833,1873,1922,1977,2038,2098,2155,
+2205,2244,2273,2292,2304,2313,2324,2339,2361,2388,2420,2452,2481,2501,2511,2508,2493,2468,2436,2401,2366,
+2335,2308,2286,2269,2255,2245,2237,2231,2229,2231,2237,2250,2268,2291,2318,2345,2371,2393,2410,2422,2430,
+2435,2438,2443,2451,2463,2480,2502,2526,2553,2580,2606,2630,2653,2674,2693,2711,2727,2740,2749,2752,2750,
+2742,2730,2716,2704,2699,2704,2722,2756,2805,2866,2934,3005,3073,3133,3183,3221,3250,3273,3293,3314,3339,
+3367,3398,3427,3449,3461,3459,3439,3404,3356,3300,3242,3188,3145,3115,3101,3101,3113,3132,3154,3174,3187,
+3192,3187,3172,3149,3118,3082,3043,3002,2960,2918,2877,2838,2801,2769,2744,2728,2722,2728,2746,2774,2810,
+2850,2888,2921,2944,2955,2954,2942,2922,2897,2871,2846,2824,2805,2786,2765,2740,2709,2671,2626,2576,2524,
+2473,2424,2380,2340,2302,2266,2228,2187,2143,2096,2048,2001,1956,1917,1882,1852,1825,1799,1773,1744,1714,
+1682,1650,1620,1594,1574,1559,1551,1548,1548,1552,1559,1567,1577,1590,1606,1626,1648,1672,1697,1720,1740,
+1756,1766,1769,1767,1759,1746,1728,1706,1681,1654,1626,1597,1570,1544,1520,1498,1479,1460,1441,1422,1403,
+1382,1363,1347,1334,1326,1324,1327,1331,1334,1334,1326,1311,1287,1257,1224,1191,1163,1141,1126,1117,1112,
+1106,1097,1080,1056,1025,990,952,918,888,866,851,841,835,831,826,820,812,803,795,787,780,
+772,761,743,718,684,641,590,536,480,426,376,329,284,238,187,130,65,-7,-85,-163,-237,
+-304,-360,-407,-445,-478,-510,-543,-582,-626,-674,-725,-776,-824,-869,-909,-946,-981,-1017,-1056,-1098,-1144,
+-1192,-1241,-1289,-1335,-1378,-1419,-1457,-1494,-1530,-1565,-1599,-1630,-1660,-1687,-1711,-1734,-1756,-1778,-1801,-1825,-1848,
+-1869,-1886,-1897,-1901,-1898,-1889,-1878,-1868,-1862,-1863,-1874,-1895,-1926,-1966,-2013,-2063,-2116,-2168,-2218,-2265,-2308,
+-2346,-2378,-2406,-2430,-2450,-2467,-2482,-2497,-2512,-2528,-2543,-2559,-2574,-2587,-2599,-2611,-2623,-2636,-2652,-2671,-2693,
+-2718,-2743,-2767,-2788,-2806,-2821,-2833,-2844,-2857,-2873,-2892,-2915,-2941,-2968,-2994,-3019,-3041,-3060,-3078,-3096,-3115,
+-3136,-3160,-3187,-3215,-3245,-3275,-3307,-3342,-3379,-3420,-3466,-3515,-3566,-3615,-3659,-3696,-3723,-3740,-3750,-3754,-3755,
+-3758,-3762,-3768,-3773,-3776,-3772,-3760,-3739,-3711,-3682,-3658,-3645,-3649,-3674,-3722,-3789,-3871,-3961,-4050,-4132,-4202,
+-4255,-4290,-4309,-4313,-4304,-4287,-4263,-4236,-4210,-4186,-4169,-4160,-4162,-4176,-4199,-4229,-4263,-4297,-4326,-4349,-4366,
+-4377,-4387,-4400,-4419,-4447,-4484,-4528,-4576,-4622,-4661,-4692,-4712,-4723,-4731,-4739,-4752,-4775,-4810,-4853,-4904,-4955,
+-5002,-5040,-5067,-5083,-5090,-5092,-5091,-5092,-5096,-5104,-5115,-5127,-5139,-5150,-5160,-5171,-5184,-5203,-5227,-5256,-5288,
+-5320,-5346,-5363,-5368,-5360,-5342,-5316,-5289,-5265,-5248,-5242,-5246,-5257,-5271,-5284,-5291,-5291,-5284,-5270,-5255,-5242,
+-5236,-5241,-5257,-5283,-5317,-5355,-5393,-5426,-5452,-5470,-5481,-5485,-5486,-5487,-5490,-5497,-5509,-5528,-5551,-5579,-5609,
+-5640,-5671,-5699,-5725,-5746,-5763,-5774,-5780,-5782,-5779,-5773,-5765,-5757,-5748,-5741,-5736,-5732,-5731,-5732,-5735,-5738,
+-5741,-5743,-5743,-5741,-5736,-5730,-5721,-5713,-5705,-5699,-5695,-5695,-5698,-5704,-5713,-5722,-5732,-5742,-5751,-5761,-5772,
+-5784,-5798,-5815,-5834,-5855,-5876,-5896,-5913,-5925,-5933,-5936,-5935,-5930,-5925,-5920,-5917,-5917,-5922,-5931,-5945,-5962,
+-5981,-6000,-6018,-6034,-6044,-6050,-6050,-6045,-6036,-6025,-6015,-6007,-6004,-6008,-6019,-6037,-6062,-6090,-6120,-6149,-6174,
+-6193,-6206,-6213,-6216,-6216,-6215,-6216,-6219,-6225,-6233,-6241,-6249,-6252,-6251,-6244,-6230,-6212,-6190,-6168,-6146,-6127,
+-6112,-6100,-6090,-6080,-6070,-6057,-6042,-6023,-6003,-5982,-5962,-5945,-5932,-5923,-5918,-5916,-5916,-5917,-5917,-5916,-5915,
+-5911,-5907,-5903,-5897,-5892,-5886,-5880,-5872,-5865,-5857,-5849,-5841,-5835,-5829,-5825,-5821,-5819,-5817,-5814,-5812,-5809,
+-5807,-5804,-5802,-5800,-5798,-5796,-5795,-5793,-5792,-5790,-5789,-5789,-5790,-5791,-5792,-5793,-5793,-5790,-5785,-5777,-5766,
+-5753,-5739,-5726,-5713,-5702,-5694,-5688,-5683,-5679,-5674,-5669,-5662,-5654,-5645,-5635,-5625,-5615,-5606,-5597,-5588,-5579,
+-5569,-5558,-5545,-5531,-5516,-5500,-5483,-5467,-5450,-5434,-5418,-5403,-5388,-5374,-5361,-5348,-5335,-5322,-5308,-5295,-5281,
+-5266,-5252,-5238,-5224,-5210,-5196,-5181,-5167,-5152,-5136,-5119,-5102,-5085,-5068,-5052,-5037,-5024,-5011,-5000,-4989,-4977,
+-4965,-4952,-4936,-4919,-4901,-4882,-4862,-4843,-4824,-4806,-4789,-4771,-4754,-4735,-4716,-4696,-4674,-4652,-4630,-4608,-4588,
+-4569,-4551,-4535,-4520,-4505,-4490,-4475,-4458,-4440,-4420,-4400,-4378,-4357,-4335,-4313,-4291,-4270,-4248,-4227,-4205,-4183,
+-4160,-4137,-4114,-4091,-4068,-4047,-4026,-4008,-3991,-3977,-3965,-3956,-3948,-3940,-3932,-3924,-3913,-3901,-3888,-3874,-3859,
+-3845,-3832,-3821,-3810,-3799,-3788,-3776,-3763,-3747,-3731,-3714,-3698,-3683,-3670,-3659,-3650,-3640,-3630,-3618,-3602,-3585,
+-3565,-3544,-3524,-3506,-3492,-3481,-3472,-3466,-3459,-3452,-3442,-3429,-3414,-3397,-3379,-3361,-3346,-3334,-3325,-3318,-3314,
+-3310,-3307,-3302,-3297,-3290,-3281,-3272,-3262,-3252,-3242,-3232,-3221,-3210,-3198,-3187,-3174,-3161,-3149,-3136,-3123,-3110,
+-3098,-3086,-3074,-3063,-3053,-3043,-3033,-3022,-3012,-3000,-2987,-2973,-2957,-2941,-2925,-2908,-2891,-2874,-2858,-2842,-2827,
+-2813,-2799,-2785,-2771,-2757,-2742,-2726,-2708,-2688,-2667,-2645,-2623,-2603,-2585,-2572,-2562,-2555,-2551,-2547,-2542,-2535,
+-2523,-2508,-2491,-2473,-2456,-2442,-2431,-2425,-2420,-2415,-2408,-2396,-2377,-2351,-2319,-2283,-2245,-2206,-2169,-2132,-2094,
+-2055,-2011,-1962,-1907,-1848,-1787,-1728,-1675,-1632,-1601,-1582,-1575,-1576,-1581,-1587,-1590,-1588,-1579,-1564,-1545,-1524,
+-1503,-1482,-1465,-1450,-1438,-1428,-1420,-1411,-1403,-1393,-1382,-1368,-1352,-1334,-1313,-1289,-1264,-1237,-1211,-1185,-1160,
+-1135,-1112,-1088,-1064,-1038,-1010,-980,-950,-919,-890,-863,-840,-821,-806,-793,-780,-767,-750,-728,-699,-663,
+-621,-573,-521,-467,-413,-363,-318,-278,-245,-217,-193,-169,-144,-113,-76,-31,19,75,131,185,232,
+271,300,320,334,345,357,374,396,426,462,502,544,585,624,660,693,725,758,793,832,875,
+919,965,1007,1043,1071,1089,1096,1092,1078,1057,1029,997,963,928,895,863,835,811,791,775,763,
+753,745,737,728,717,707,696,686,679,677,679,686,698,712,726,738,746,748,742,729,709,
+682,650,615,579,542,507,474,446,423,406,394,388,386,389,394,401,409,418,427,436,446,
+456,467,478,489,500,509,518,524,529,532,533,533,532,530,526,522,516,509,502,494,486,
+479,473,469,466,464,464,464,465,466,467,469,470,473,476,481,486,492,498,504,509,513,
+516,518,518,519,519,519,520,521,523,524,526,527,527,526,523,519,514,508,502,495,488,
+481,474,466,458,449,439,428,417,405,394,383,372,363,354,347,340,333,327,322,317,313,
+310,308,307,308,310,312,316,319,322,325,327,329,330,332,334,336,339,342,345,348,351,
+354,356,358,359,361,364,366,370,373,378,382,388,393,398,404,409,416,422,429,436,444,
+452,460,468,475,483,490,496,503,509,516,522,529,535,542,547,552,557,560,563,565,568,
+571,575,580,587,594,602,611,620,629,638,647,656,666,676,687,697,708,719,730,740,751,
+763,775,789,804,821,839,858,875,892,905,915,921,923,922,918,913,907,901,895,890,886,
+882,879,877,876,878,883,892,905,922,941,962,982,999,1013,1021,1052,1052,1048,1042,1036,1031,
+1030,1031,1036,1045,1055,1067,1080,1094,1110,1128,1148,1171,1195,1220,1244,1267,1286,1301,1312,1321,1327,
+1332,1337,1342,1348,1352,1355,1357,1357,1356,1358,1363,1374,1392,1417,1449,1484,1518,1548,1568,1578,1576,
+1563,1544,1522,1504,1492,1490,1498,1517,1542,1570,1597,1619,1635,1643,1643,1638,1630,1620,1609,1599,1589,
+1579,1567,1554,1540,1525,1511,1499,1491,1487,1489,1496,1508,1522,1538,1553,1568,1580,1589,1597,1602,1606,
+1610,1613,1618,1624,1632,1643,1655,1669,1685,1701,1717,1732,1747,1760,1772,1783,1793,1803,1812,1820,1829,
+1838,1848,1859,1875,1896,1923,1958,2000,2047,2098,2149,2195,2234,2263,2281,2289,2289,2286,2283,2285,2293,
+2310,2334,2362,2389,2411,2424,2426,2414,2391,2358,2319,2279,2239,2204,2174,2149,2130,2114,2103,2095,2091,
+2092,2099,2114,2136,2165,2199,2236,2272,2306,2335,2358,2375,2389,2401,2413,2429,2450,2476,2507,2543,2580,
+2616,2651,2684,2712,2738,2761,2781,2798,2812,2821,2824,2819,2804,2782,2752,2720,2688,2661,2645,2643,2656,
+2684,2726,2777,2833,2890,2943,2990,3032,3070,3104,3139,3175,3213,3253,3290,3322,3345,3353,3345,3319,3278,
+3225,3165,3105,3049,3003,2970,2951,2946,2950,2962,2975,2987,2992,2990,2980,2962,2937,2909,2880,2852,2827,
+2806,2790,2777,2766,2756,2746,2735,2724,2713,2706,2703,2706,2717,2736,2761,2791,2823,2853,2879,2897,2906,
+2906,2896,2876,2847,2812,2770,2723,2673,2621,2568,2515,2465,2418,2376,2337,2302,2269,2236,2201,2163,2121,
+2076,2029,1982,1938,1896,1860,1829,1801,1777,1754,1731,1707,1681,1655,1629,1606,1586,1571,1561,1556,1555,
+1557,1561,1567,1575,1583,1594,1606,1620,1635,1651,1666,1680,1691,1698,1702,1702,1700,1695,1688,1680,1669,
+1656,1641,1623,1603,1582,1559,1538,1516,1496,1478,1460,1443,1425,1408,1392,1376,1362,1351,1342,1335,1328,
+1321,1311,1297,1279,1256,1229,1202,1177,1155,1137,1124,1115,1108,1100,1088,1072,1052,1027,1002,977,956,
+939,928,922,917,912,905,894,879,860,840,820,801,784,768,752,731,704,668,624,571,513,
+452,392,334,280,229,181,131,78,21,-42,-110,-180,-249,-315,-374,-427,-472,-513,-550,-586,-624,
+-664,-707,-751,-795,-839,-880,-920,-959,-997,-1036,-1077,-1120,-1165,-1211,-1257,-1301,-1344,-1384,-1422,-1457,-1491,
+-1524,-1556,-1586,-1614,-1640,-1664,-1685,-1705,-1724,-1742,-1762,-1782,-1803,-1822,-1839,-1852,-1860,-1863,-1863,-1861,-1861,
+-1865,-1877,-1898,-1929,-1968,-2014,-2064,-2115,-2164,-2208,-2247,-2281,-2308,-2332,-2354,-2374,-2394,-2416,-2439,-2462,-2485,
+-2507,-2527,-2545,-2560,-2574,-2586,-2598,-2611,-2627,-2646,-2669,-2693,-2719,-2746,-2770,-2792,-2812,-2828,-2843,-2858,-2874,
+-2892,-2913,-2935,-2959,-2982,-3004,-3024,-3042,-3059,-3076,-3094,-3115,-3139,-3165,-3193,-3221,-3247,-3272,-3295,-3319,-3345,
+-3375,-3411,-3454,-3501,-3550,-3597,-3638,-3669,-3688,-3695,-3694,-3688,-3682,-3679,-3682,-3692,-3706,-3720,-3731,-3735,-3731,
+-3719,-3703,-3688,-3683,-3692,-3720,-3769,-3837,-3920,-4010,-4101,-4184,-4252,-4303,-4334,-4345,-4340,-4322,-4295,-4264,-4233,
+-4206,-4186,-4176,-4176,-4188,-4209,-4238,-4270,-4303,-4331,-4353,-4367,-4374,-4377,-4381,-4389,-4406,-4433,-4471,-4518,-4569,
+-4620,-4667,-4707,-4739,-4765,-4788,-4813,-4842,-4879,-4922,-4971,-5020,-5065,-5101,-5126,-5138,-5139,-5134,-5127,-5123,-5126,
+-5138,-5158,-5184,-5212,-5240,-5264,-5283,-5299,-5314,-5328,-5345,-5365,-5387,-5409,-5428,-5439,-5441,-5433,-5417,-5394,-5370,
+-5350,-5335,-5329,-5331,-5339,-5349,-5357,-5361,-5358,-5349,-5336,-5323,-5315,-5314,-5324,-5345,-5374,-5410,-5446,-5479,-5504,
+-5520,-5525,-5522,-5512,-5500,-5490,-5483,-5483,-5491,-5506,-5528,-5555,-5586,-5619,-5652,-5684,-5715,-5742,-5766,-5785,-5800,
+-5811,-5816,-5818,-5817,-5812,-5806,-5800,-5793,-5787,-5783,-5780,-5779,-5780,-5782,-5784,-5786,-5787,-5787,-5785,-5782,-5777,
+-5772,-5766,-5762,-5759,-5758,-5759,-5762,-5767,-5772,-5779,-5786,-5793,-5800,-5809,-5820,-5833,-5848,-5865,-5885,-5905,-5924,
+-5942,-5956,-5967,-5973,-5974,-5973,-5969,-5965,-5963,-5963,-5968,-5978,-5992,-6010,-6031,-6053,-6073,-6090,-6101,-6107,-6106,
+-6100,-6089,-6078,-6067,-6060,-6060,-6067,-6082,-6104,-6131,-6161,-6191,-6219,-6240,-6256,-6265,-6267,-6266,-6262,-6258,-6256,
+-6256,-6258,-6263,-6267,-6269,-6268,-6263,-6253,-6238,-6221,-6202,-6183,-6167,-6153,-6142,-6134,-6126,-6119,-6110,-6098,-6084,
+-6067,-6048,-6030,-6012,-5996,-5983,-5974,-5967,-5964,-5962,-5961,-5961,-5961,-5959,-5957,-5954,-5949,-5943,-5936,-5928,-5919,
+-5911,-5903,-5897,-5893,-5891,-5891,-5893,-5895,-5898,-5901,-5902,-5903,-5901,-5899,-5895,-5890,-5884,-5878,-5872,-5865,-5859,
+-5853,-5848,-5844,-5842,-5842,-5844,-5847,-5850,-5853,-5853,-5851,-5845,-5835,-5822,-5808,-5792,-5777,-5763,-5752,-5743,-5735,
+-5730,-5724,-5719,-5712,-5704,-5694,-5683,-5671,-5660,-5649,-5638,-5629,-5620,-5612,-5603,-5594,-5584,-5573,-5560,-5545,-5529,
+-5513,-5495,-5477,-5460,-5443,-5427,-5412,-5398,-5384,-5370,-5357,-5343,-5329,-5314,-5300,-5286,-5272,-5258,-5245,-5232,-5219,
+-5205,-5190,-5174,-5156,-5138,-5119,-5100,-5083,-5066,-5052,-5039,-5027,-5016,-5004,-4992,-4978,-4962,-4945,-4927,-4907,-4888,
+-4869,-4850,-4831,-4812,-4792,-4772,-4750,-4728,-4704,-4681,-4657,-4634,-4613,-4594,-4576,-4560,-4545,-4529,-4514,-4497,-4479,
+-4460,-4440,-4419,-4397,-4376,-4354,-4333,-4313,-4294,-4274,-4256,-4237,-4218,-4199,-4179,-4158,-4136,-4114,-4091,-4069,-4049,
+-4030,-4015,-4003,-3993,-3986,-3981,-3976,-3969,-3960,-3948,-3933,-3915,-3895,-3874,-3853,-3832,-3812,-3792,-3772,-3751,-3728,
+-3705,-3682,-3660,-3640,-3623,-3612,-3604,-3601,-3600,-3599,-3597,-3592,-3583,-3570,-3554,-3537,-3520,-3504,-3492,-3482,-3475,
+-3470,-3464,-3456,-3446,-3434,-3419,-3403,-3388,-3375,-3365,-3359,-3355,-3354,-3354,-3353,-3351,-3345,-3336,-3324,-3310,-3295,
+-3280,-3266,-3252,-3240,-3229,-3219,-3209,-3198,-3187,-3175,-3162,-3149,-3136,-3124,-3112,-3101,-3091,-3082,-3072,-3063,-3053,
+-3042,-3030,-3017,-3002,-2985,-2967,-2948,-2928,-2908,-2888,-2868,-2851,-2834,-2820,-2808,-2796,-2786,-2774,-2761,-2745,-2726,
+-2705,-2681,-2656,-2632,-2611,-2594,-2581,-2572,-2566,-2562,-2558,-2551,-2541,-2529,-2515,-2501,-2489,-2481,-2478,-2478,-2481,
+-2484,-2482,-2473,-2454,-2424,-2385,-2339,-2289,-2240,-2195,-2155,-2121,-2090,-2059,-2027,-1989,-1944,-1893,-1839,-1785,-1735,
+-1693,-1662,-1643,-1634,-1632,-1634,-1635,-1632,-1623,-1608,-1588,-1564,-1539,-1516,-1496,-1481,-1469,-1461,-1455,-1448,-1440,
+-1430,-1417,-1401,-1382,-1362,-1339,-1315,-1290,-1263,-1234,-1204,-1172,-1140,-1107,-1074,-1042,-1009,-977,-945,-913,-882,
+-852,-824,-799,-775,-755,-736,-720,-704,-687,-669,-646,-620,-588,-552,-512,-469,-425,-382,-343,-308,-278,
+-253,-232,-212,-190,-163,-128,-85,-33,26,91,156,219,274,320,355,380,397,410,422,437,457,
+483,515,552,592,632,672,711,749,788,828,873,921,973,1027,1080,1129,1170,1199,1215,1217,1204,
+1179,1143,1101,1055,1008,963,922,885,853,826,803,783,764,746,728,709,690,670,651,635,623,
+616,614,618,627,639,653,665,674,678,676,666,649,626,598,566,531,495,459,424,392,363,
+339,319,305,296,292,292,296,304,313,323,334,346,358,370,382,394,405,416,426,434,441,
+447,451,453,454,454,454,452,450,447,443,439,435,431,427,424,421,419,418,417,417,416,
+415,415,415,415,416,419,423,428,434,440,447,452,456,458,459,459,457,456,454,453,453,
+454,456,459,461,463,465,464,462,457,451,443,435,425,415,405,395,385,375,365,354,343,
+332,321,310,300,290,282,275,269,264,260,256,253,251,248,247,246,246,247,249,251,254,
+258,262,265,269,272,275,277,280,282,285,288,290,293,295,297,300,302,304,307,310,314,
+319,324,330,336,343,350,357,365,373,381,389,398,406,415,423,431,439,446,454,461,468,
+476,484,491,499,506,513,519,524,527,530,533,536,539,544,551,559,569,581,593,605,617,
+628,640,651,662,673,685,698,710,722,734,744,754,764,773,784,797,813,831,852,875,897,
+918,935,947,953,954,950,941,931,919,908,898,891,885,882,881,882,886,893,904,919,936,
+957,980,1002,1021,1037,1047,1052,1127,1128,1124,1118,1112,1107,1104,1106,1110,1116,1125,1134,1144,1155,
+1168,1182,1200,1220,1243,1269,1295,1320,1345,1366,1384,1399,1411,1421,1428,1434,1436,1436,1433,1426,1418,
+1409,1403,1401,1406,1420,1442,1473,1508,1544,1577,1602,1618,1623,1618,1607,1592,1580,1573,1576,1587,1608,
+1636,1667,1699,1728,1752,1769,1780,1786,1786,1782,1773,1761,1744,1722,1696,1664,1630,1596,1563,1535,1515,
+1503,1501,1507,1519,1536,1554,1572,1587,1599,1607,1612,1615,1618,1622,1627,1635,1646,1659,1674,1690,1707,
+1725,1743,1761,1779,1798,1816,1835,1854,1872,1890,1907,1924,1939,1954,1970,1987,2007,2032,2060,2093,2129,
+2165,2201,2232,2255,2270,2276,2273,2263,2251,2240,2234,2235,2246,2264,2288,2313,2336,2351,2356,2349,2330,
+2301,2264,2223,2182,2143,2108,2078,2051,2029,2009,1994,1983,1979,1982,1995,2017,2049,2088,2132,2177,2219,
+2256,2286,2309,2327,2343,2362,2385,2417,2457,2506,2562,2619,2676,2727,2771,2806,2831,2849,2861,2868,2873,
+2875,2874,2869,2858,2839,2812,2779,2740,2699,2662,2631,2611,2604,2610,2629,2659,2696,2738,2782,2827,2871,
+2916,2962,3010,3059,3110,3159,3202,3237,3259,3265,3253,3224,3179,3123,3060,2997,2939,2890,2853,2829,2817,
+2815,2819,2826,2830,2829,2821,2806,2783,2757,2729,2703,2684,2672,2669,2675,2688,2704,2719,2730,2734,2729,
+2717,2698,2678,2660,2649,2650,2664,2691,2730,2776,2823,2866,2899,2917,2917,2899,2863,2812,2750,2683,2613,
+2546,2485,2431,2384,2345,2313,2283,2255,2226,2194,2158,2117,2072,2024,1976,1929,1885,1845,1810,1780,1755,
+1732,1711,1692,1673,1654,1637,1621,1607,1596,1588,1583,1580,1580,1581,1583,1587,1593,1600,1609,1620,1631,
+1641,1650,1655,1657,1654,1648,1639,1630,1621,1614,1610,1608,1607,1607,1606,1601,1593,1581,1566,1548,1529,
+1509,1491,1473,1457,1442,1427,1412,1396,1380,1363,1346,1329,1311,1293,1274,1254,1234,1213,1193,1173,1155,
+1138,1124,1110,1097,1083,1066,1047,1025,1003,981,962,949,941,939,941,946,950,949,942,927,905,
+878,849,819,792,769,748,729,709,683,649,607,554,495,430,363,298,237,181,129,80,31,
+-19,-73,-131,-192,-256,-319,-380,-437,-489,-537,-580,-619,-657,-694,-731,-768,-806,-844,-882,-921,-961,
+-1002,-1045,-1089,-1135,-1182,-1228,-1273,-1316,-1357,-1395,-1431,-1465,-1498,-1530,-1561,-1591,-1620,-1647,-1672,-1695,-1717,
+-1738,-1758,-1779,-1800,-1820,-1838,-1853,-1863,-1869,-1870,-1869,-1867,-1868,-1875,-1891,-1918,-1955,-2001,-2054,-2108,-2161,
+-2208,-2247,-2278,-2301,-2317,-2331,-2344,-2360,-2381,-2406,-2435,-2466,-2498,-2526,-2550,-2569,-2583,-2594,-2604,-2615,-2629,
+-2648,-2673,-2701,-2732,-2764,-2794,-2820,-2843,-2862,-2878,-2894,-2910,-2929,-2949,-2972,-2996,-3019,-3039,-3057,-3071,-3084,
+-3097,-3113,-3132,-3156,-3184,-3215,-3247,-3276,-3302,-3323,-3341,-3357,-3376,-3399,-3429,-3467,-3510,-3556,-3599,-3635,-3660,
+-3672,-3671,-3661,-3646,-3633,-3625,-3627,-3639,-3658,-3682,-3706,-3724,-3734,-3736,-3732,-3729,-3731,-3747,-3780,-3834,-3907,
+-3995,-4091,-4187,-4274,-4345,-4396,-4424,-4429,-4415,-4387,-4350,-4310,-4274,-4245,-4227,-4221,-4227,-4245,-4270,-4299,-4329,
+-4354,-4373,-4384,-4387,-4385,-4380,-4377,-4381,-4395,-4420,-4457,-4503,-4554,-4608,-4660,-4709,-4753,-4794,-4833,-4873,-4917,
+-4963,-5012,-5059,-5102,-5136,-5158,-5168,-5168,-5159,-5149,-5142,-5144,-5157,-5182,-5217,-5258,-5302,-5342,-5375,-5401,-5420,
+-5433,-5444,-5455,-5467,-5482,-5497,-5511,-5519,-5521,-5514,-5499,-5478,-5455,-5432,-5413,-5400,-5393,-5391,-5392,-5393,-5392,
+-5387,-5380,-5372,-5367,-5366,-5373,-5389,-5413,-5444,-5478,-5510,-5538,-5557,-5567,-5567,-5559,-5545,-5530,-5516,-5505,-5500,
+-5502,-5510,-5523,-5540,-5561,-5585,-5610,-5636,-5663,-5691,-5718,-5745,-5771,-5795,-5816,-5834,-5848,-5859,-5866,-5869,-5870,
+-5867,-5863,-5858,-5853,-5848,-5843,-5840,-5839,-5838,-5837,-5836,-5835,-5832,-5828,-5823,-5817,-5812,-5807,-5805,-5804,-5806,
+-5809,-5813,-5818,-5822,-5826,-5829,-5832,-5837,-5843,-5852,-5864,-5881,-5900,-5922,-5944,-5965,-5982,-5995,-6003,-6007,-6007,
+-6005,-6002,-6002,-6005,-6013,-6025,-6042,-6062,-6083,-6103,-6121,-6134,-6143,-6147,-6147,-6146,-6145,-6146,-6150,-6159,-6174,
+-6192,-6214,-6237,-6259,-6278,-6294,-6304,-6309,-6310,-6307,-6303,-6298,-6294,-6291,-6290,-6291,-6291,-6291,-6288,-6282,-6273,
+-6261,-6246,-6229,-6213,-6197,-6183,-6171,-6161,-6153,-6146,-6140,-6132,-6124,-6115,-6104,-6093,-6081,-6070,-6060,-6051,-6043,
+-6037,-6033,-6029,-6026,-6023,-6019,-6015,-6009,-6002,-5994,-5985,-5976,-5968,-5960,-5955,-5952,-5952,-5954,-5959,-5965,-5972,
+-5978,-5984,-5987,-5988,-5988,-5986,-5982,-5977,-5972,-5965,-5958,-5951,-5943,-5935,-5927,-5920,-5915,-5912,-5911,-5913,-5916,
+-5919,-5922,-5922,-5919,-5913,-5903,-5890,-5874,-5858,-5842,-5827,-5813,-5802,-5793,-5785,-5777,-5769,-5759,-5748,-5736,-5723,
+-5709,-5696,-5683,-5671,-5661,-5653,-5646,-5640,-5633,-5626,-5617,-5606,-5593,-5577,-5560,-5541,-5522,-5504,-5486,-5469,-5454,
+-5441,-5428,-5415,-5403,-5390,-5376,-5362,-5347,-5332,-5316,-5301,-5286,-5271,-5255,-5239,-5223,-5205,-5187,-5168,-5149,-5131,
+-5114,-5098,-5083,-5070,-5057,-5044,-5031,-5017,-5002,-4986,-4969,-4951,-4933,-4914,-4895,-4876,-4856,-4835,-4813,-4790,-4766,
+-4742,-4718,-4694,-4671,-4650,-4630,-4611,-4592,-4574,-4555,-4536,-4516,-4496,-4475,-4454,-4433,-4413,-4393,-4373,-4354,-4335,
+-4315,-4296,-4277,-4258,-4239,-4220,-4201,-4182,-4163,-4144,-4125,-4105,-4086,-4069,-4054,-4040,-4029,-4020,-4012,-4004,-3995,
+-3984,-3970,-3953,-3934,-3912,-3889,-3866,-3842,-3818,-3794,-3768,-3741,-3712,-3681,-3650,-3620,-3593,-3572,-3557,-3549,-3548,
+-3552,-3559,-3566,-3571,-3571,-3567,-3557,-3544,-3529,-3514,-3500,-3489,-3481,-3475,-3470,-3464,-3456,-3447,-3436,-3423,-3411,
+-3400,-3391,-3386,-3383,-3382,-3382,-3381,-3378,-3371,-3361,-3347,-3331,-3313,-3295,-3278,-3263,-3250,-3238,-3229,-3220,-3212,
+-3203,-3195,-3186,-3177,-3167,-3158,-3149,-3140,-3131,-3121,-3111,-3100,-3088,-3075,-3060,-3044,-3027,-3009,-2989,-2968,-2947,
+-2926,-2905,-2886,-2869,-2854,-2842,-2833,-2825,-2816,-2807,-2794,-2778,-2757,-2732,-2705,-2677,-2650,-2627,-2608,-2594,-2585,
+-2578,-2572,-2565,-2555,-2544,-2531,-2518,-2508,-2503,-2504,-2510,-2520,-2531,-2538,-2537,-2523,-2495,-2453,-2400,-2339,-2278,
+-2220,-2170,-2132,-2104,-2084,-2069,-2054,-2036,-2011,-1980,-1942,-1902,-1864,-1830,-1804,-1785,-1774,-1768,-1763,-1756,-1743,
+-1723,-1697,-1665,-1631,-1598,-1567,-1542,-1522,-1508,-1497,-1488,-1478,-1466,-1451,-1433,-1411,-1386,-1359,-1330,-1300,-1268,
+-1235,-1200,-1163,-1125,-1087,-1049,-1012,-977,-945,-916,-889,-864,-840,-817,-795,-772,-750,-728,-705,-683,-661,
+-639,-616,-592,-565,-537,-505,-472,-437,-403,-369,-338,-310,-286,-265,-245,-225,-201,-171,-134,-87,-32,
+30,97,166,232,292,344,387,420,445,464,480,497,516,540,567,599,634,672,711,751,793,
+836,882,931,983,1037,1093,1147,1197,1239,1272,1292,1299,1292,1272,1241,1200,1152,1100,1047,995,945,
+899,858,821,788,758,730,703,677,651,626,603,584,569,560,557,561,569,580,591,601,606,
+605,597,581,559,530,498,463,428,392,359,328,299,274,252,233,218,207,200,198,199,203,
+211,221,232,245,258,271,284,296,308,319,329,338,346,352,358,362,365,368,369,369,370,
+369,368,367,366,365,365,364,363,363,363,363,363,363,364,364,366,368,371,374,378,382,
+387,392,396,399,402,403,404,404,404,403,403,403,404,405,407,410,412,414,415,415,413,
+408,402,394,385,374,363,351,339,328,317,306,295,284,273,262,252,242,233,225,219,214,
+210,208,207,206,206,206,206,205,205,205,205,206,208,211,214,217,221,225,229,233,236,
+239,242,244,246,248,250,252,255,257,261,264,268,272,277,283,289,295,302,309,316,324,
+331,339,347,356,364,373,382,390,399,407,416,424,433,441,450,459,467,475,482,488,493,
+496,499,501,504,508,514,521,531,542,555,568,582,596,610,625,639,654,670,687,704,721,
+737,751,763,773,782,789,797,807,819,834,852,872,892,912,928,941,948,951,949,944,937,
+929,922,916,911,909,908,909,913,919,929,943,962,985,1011,1038,1064,1088,1107,1120,1127,1238,
+1242,1241,1236,1229,1223,1220,1219,1223,1228,1236,1244,1253,1262,1271,1282,1295,1311,1330,1352,1375,1399,
+1422,1444,1464,1481,1495,1506,1514,1520,1522,1520,1514,1505,1493,1479,1467,1457,1454,1459,1472,1493,1522,
+1554,1586,1616,1641,1659,1670,1674,1675,1675,1676,1681,1691,1705,1725,1748,1772,1796,1819,1841,1859,1874,
+1886,1892,1892,1884,1867,1841,1806,1764,1718,1670,1625,1586,1557,1539,1532,1535,1546,1562,1580,1597,1612,
+1623,1632,1640,1647,1655,1665,1677,1692,1708,1725,1741,1757,1771,1783,1795,1807,1820,1835,1853,1873,1895,
+1918,1942,1966,1989,2011,2032,2052,2073,2096,2120,2147,2174,2201,2225,2244,2257,2261,2257,2246,2229,2211,
+2195,2184,2181,2189,2205,2229,2256,2282,2303,2315,2316,2305,2284,2254,2218,2180,2143,2107,2074,2043,2013,
+1986,1960,1938,1921,1912,1913,1927,1953,1991,2037,2088,2139,2184,2222,2251,2272,2289,2305,2326,2357,2400,
+2456,2524,2599,2675,2747,2810,2858,2891,2908,2913,2908,2898,2886,2875,2864,2855,2843,2829,2809,2782,2750,
+2714,2677,2642,2613,2592,2583,2585,2598,2620,2650,2686,2726,2770,2818,2868,2921,2975,3028,3078,3122,3156,
+3177,3182,3170,3142,3099,3046,2987,2927,2870,2821,2783,2756,2741,2735,2736,2739,2741,2739,2730,2714,2692,
+2665,2638,2614,2597,2590,2593,2608,2630,2657,2683,2704,2715,2714,2702,2680,2654,2629,2612,2608,2620,2649,
+2694,2748,2806,2859,2901,2924,2925,2904,2861,2800,2728,2651,2575,2504,2442,2391,2349,2314,2284,2255,2225,
+2191,2152,2108,2061,2011,1960,1912,1867,1827,1792,1762,1736,1714,1695,1679,1664,1651,1639,1630,1623,1618,
+1615,1612,1610,1608,1606,1605,1604,1605,1609,1615,1624,1634,1645,1653,1658,1657,1651,1638,1622,1603,1584,
+1569,1559,1555,1557,1564,1572,1581,1586,1586,1581,1570,1554,1536,1516,1497,1480,1464,1450,1437,1423,1408,
+1392,1373,1352,1330,1307,1284,1262,1241,1222,1204,1188,1173,1158,1143,1127,1109,1089,1064,1037,1008,979,
+951,927,908,898,894,897,905,913,919,919,911,895,871,841,808,776,746,721,699,680,661,
+637,607,568,520,463,401,335,270,208,151,99,52,7,-37,-84,-135,-189,-247,-307,-368,-427,
+-483,-535,-582,-625,-664,-701,-735,-769,-803,-838,-874,-913,-953,-995,-1039,-1085,-1131,-1177,-1223,-1266,-1308,
+-1348,-1386,-1423,-1459,-1494,-1528,-1562,-1595,-1626,-1656,-1684,-1710,-1735,-1759,-1784,-1808,-1831,-1852,-1871,-1884,-1892,
+-1893,-1889,-1883,-1876,-1873,-1878,-1894,-1923,-1965,-2017,-2075,-2135,-2192,-2241,-2281,-2308,-2327,-2338,-2346,-2355,-2370,
+-2390,-2418,-2451,-2486,-2521,-2551,-2575,-2592,-2603,-2610,-2617,-2626,-2641,-2663,-2691,-2725,-2762,-2798,-2830,-2858,-2880,
+-2897,-2911,-2924,-2939,-2956,-2977,-3001,-3025,-3048,-3069,-3086,-3100,-3112,-3125,-3141,-3161,-3187,-3217,-3250,-3282,-3311,
+-3336,-3354,-3368,-3380,-3393,-3412,-3438,-3472,-3513,-3556,-3598,-3633,-3656,-3666,-3664,-3651,-3635,-3619,-3610,-3610,-3622,
+-3644,-3671,-3699,-3722,-3739,-3747,-3749,-3751,-3757,-3776,-3812,-3868,-3943,-4035,-4135,-4236,-4328,-4404,-4458,-4487,-4491,
+-4474,-4441,-4400,-4356,-4317,-4287,-4269,-4265,-4272,-4290,-4313,-4339,-4364,-4383,-4395,-4400,-4398,-4392,-4386,-4383,-4388,
+-4401,-4426,-4460,-4503,-4553,-4605,-4658,-4710,-4760,-4809,-4857,-4905,-4953,-5001,-5047,-5088,-5121,-5144,-5156,-5158,-5154,
+-5146,-5141,-5143,-5155,-5180,-5215,-5259,-5308,-5355,-5397,-5430,-5455,-5471,-5480,-5488,-5495,-5505,-5518,-5532,-5546,-5557,
+-5562,-5559,-5548,-5530,-5507,-5482,-5458,-5438,-5421,-5410,-5402,-5398,-5395,-5393,-5392,-5392,-5396,-5404,-5418,-5437,-5461,
+-5488,-5516,-5542,-5564,-5580,-5589,-5593,-5592,-5587,-5581,-5575,-5569,-5565,-5563,-5561,-5562,-5563,-5566,-5571,-5579,-5591,
+-5607,-5627,-5651,-5679,-5709,-5741,-5773,-5804,-5833,-5860,-5882,-5901,-5914,-5923,-5928,-5928,-5925,-5920,-5913,-5907,-5900,
+-5895,-5891,-5886,-5882,-5876,-5868,-5859,-5849,-5839,-5829,-5822,-5818,-5816,-5818,-5823,-5828,-5833,-5837,-5839,-5839,-5838,
+-5838,-5841,-5847,-5859,-5876,-5899,-5924,-5951,-5977,-5999,-6016,-6027,-6032,-6033,-6031,-6029,-6028,-6031,-6039,-6051,-6067,
+-6086,-6105,-6125,-6143,-6158,-6172,-6183,-6194,-6205,-6216,-6229,-6243,-6259,-6275,-6291,-6305,-6317,-6326,-6332,-6335,-6336,
+-6335,-6332,-6329,-6327,-6324,-6323,-6322,-6320,-6319,-6316,-6311,-6304,-6296,-6286,-6274,-6261,-6247,-6234,-6221,-6209,-6199,
+-6191,-6185,-6180,-6176,-6173,-6171,-6169,-6167,-6164,-6160,-6155,-6148,-6141,-6133,-6124,-6115,-6105,-6096,-6086,-6076,-6067,
+-6057,-6047,-6038,-6030,-6024,-6020,-6018,-6019,-6023,-6029,-6036,-6044,-6052,-6058,-6063,-6066,-6067,-6066,-6064,-6061,-6057,
+-6053,-6049,-6043,-6036,-6028,-6018,-6008,-5998,-5988,-5981,-5976,-5973,-5974,-5976,-5979,-5981,-5982,-5980,-5975,-5966,-5954,
+-5939,-5924,-5908,-5893,-5879,-5866,-5855,-5844,-5833,-5821,-5808,-5793,-5777,-5761,-5744,-5727,-5713,-5700,-5691,-5683,-5677,
+-5673,-5668,-5661,-5653,-5641,-5627,-5610,-5590,-5570,-5550,-5531,-5514,-5500,-5488,-5478,-5469,-5460,-5450,-5440,-5427,-5412,
+-5395,-5377,-5359,-5339,-5320,-5302,-5283,-5265,-5248,-5231,-5214,-5197,-5180,-5164,-5148,-5133,-5118,-5102,-5087,-5071,-5055,
+-5039,-5022,-5005,-4988,-4970,-4952,-4933,-4913,-4892,-4870,-4847,-4823,-4799,-4775,-4752,-4729,-4708,-4687,-4667,-4646,-4625,
+-4604,-4581,-4558,-4534,-4512,-4490,-4470,-4452,-4435,-4418,-4402,-4385,-4367,-4347,-4325,-4302,-4279,-4255,-4233,-4211,-4192,
+-4174,-4156,-4140,-4124,-4108,-4092,-4077,-4062,-4048,-4034,-4021,-4008,-3995,-3981,-3966,-3950,-3933,-3917,-3901,-3885,-3870,
+-3854,-3837,-3817,-3794,-3766,-3735,-3701,-3666,-3633,-3603,-3580,-3565,-3557,-3556,-3560,-3566,-3572,-3576,-3575,-3569,-3559,
+-3546,-3532,-3519,-3507,-3497,-3490,-3484,-3478,-3471,-3463,-3453,-3442,-3431,-3420,-3411,-3405,-3401,-3398,-3396,-3393,-3388,
+-3381,-3370,-3356,-3339,-3322,-3304,-3287,-3272,-3260,-3249,-3241,-3234,-3228,-3223,-3219,-3214,-3209,-3204,-3198,-3191,-3183,
+-3174,-3164,-3151,-3138,-3122,-3106,-3089,-3071,-3053,-3034,-3015,-2995,-2976,-2957,-2939,-2922,-2908,-2896,-2886,-2877,-2869,
+-2860,-2848,-2832,-2810,-2784,-2754,-2722,-2690,-2661,-2636,-2618,-2605,-2598,-2593,-2590,-2585,-2579,-2571,-2563,-2556,-2552,
+-2554,-2562,-2574,-2589,-2601,-2606,-2599,-2576,-2536,-2480,-2413,-2339,-2265,-2199,-2146,-2108,-2086,-2076,-2076,-2079,-2081,
+-2077,-2067,-2049,-2027,-2002,-1979,-1958,-1943,-1930,-1920,-1908,-1892,-1870,-1840,-1803,-1760,-1714,-1668,-1625,-1587,-1554,
+-1527,-1505,-1485,-1465,-1444,-1422,-1396,-1368,-1338,-1306,-1272,-1238,-1202,-1166,-1129,-1091,-1054,-1019,-986,-957,-932,
+-912,-895,-882,-870,-858,-844,-828,-809,-787,-762,-735,-706,-677,-647,-617,-587,-556,-526,-494,-463,-432,
+-401,-373,-348,-325,-305,-286,-268,-248,-224,-194,-157,-112,-60,-1,62,128,192,254,309,357,397,
+430,458,481,502,523,546,571,600,633,670,711,755,802,851,902,954,1006,1059,1110,1160,1206,
+1247,1283,1310,1329,1337,1334,1318,1290,1249,1199,1140,1075,1009,943,880,824,774,731,694,662,634,
+608,584,561,541,524,511,504,502,505,511,519,526,528,524,513,493,466,433,395,356,317,
+280,246,216,190,168,149,133,119,109,101,97,97,100,107,116,128,142,156,170,183,196,
+208,218,228,237,245,252,259,265,271,275,279,281,284,286,287,289,291,293,295,297,298,
+300,302,304,307,310,314,319,324,330,336,342,347,350,353,355,355,356,356,356,357,358,
+360,362,365,368,370,371,372,372,372,370,368,366,362,358,352,345,337,328,318,307,296,
+285,274,264,254,244,235,226,217,208,200,193,186,182,178,176,176,176,177,179,180,181,
+182,182,182,183,184,186,189,193,197,201,206,210,213,216,219,220,222,223,225,227,229,
+232,236,239,244,248,253,258,262,267,272,276,281,286,291,297,304,312,320,329,338,348,
+358,368,377,387,396,405,414,423,431,439,446,453,458,463,468,472,477,483,489,498,508,
+519,532,545,560,575,591,609,627,647,669,691,714,735,756,774,789,801,810,818,825,832,
+841,852,865,880,895,909,922,933,941,945,948,948,948,947,946,945,945,944,944,945,948,
+954,965,982,1006,1035,1070,1107,1143,1177,1205,1225,1238,1357,1366,1365,1360,1351,1343,1338,1336,1338,
+1344,1352,1361,1370,1378,1385,1392,1400,1410,1421,1434,1448,1462,1477,1489,1500,1509,1516,1521,1524,1526,
+1527,1526,1524,1518,1511,1501,1489,1479,1470,1466,1468,1476,1492,1515,1543,1574,1606,1637,1665,1689,1708,
+1722,1732,1740,1745,1749,1753,1759,1766,1777,1792,1809,1830,1851,1872,1889,1900,1901,1891,1870,1837,1795,
+1747,1698,1651,1611,1581,1562,1556,1559,1572,1589,1610,1632,1653,1672,1691,1710,1730,1751,1774,1798,1823,
+1846,1866,1883,1896,1904,1910,1913,1917,1922,1930,1940,1954,1970,1988,2005,2022,2037,2050,2062,2073,2086,
+2099,2115,2133,2151,2169,2184,2194,2198,2194,2183,2167,2149,2131,2117,2111,2115,2127,2149,2175,2204,2230,
+2250,2261,2262,2253,2235,2210,2183,2155,2127,2101,2076,2050,2024,1996,1968,1940,1917,1900,1895,1902,1924,
+1958,2002,2051,2100,2145,2181,2209,2229,2244,2259,2281,2313,2359,2420,2492,2571,2651,2725,2787,2831,2858,
+2866,2860,2844,2823,2802,2785,2774,2768,2766,2763,2758,2748,2732,2710,2683,2655,2628,2607,2593,2588,2592,
+2606,2628,2655,2688,2724,2763,2803,2845,2887,2928,2966,2999,3025,3041,3046,3038,3017,2985,2944,2897,2849,
+2802,2760,2726,2701,2685,2677,2676,2677,2679,2678,2672,2660,2642,2621,2599,2579,2565,2559,2562,2575,2594,
+2618,2640,2657,2665,2663,2651,2631,2609,2589,2578,2580,2599,2634,2684,2742,2801,2854,2893,2913,2909,2883,
+2835,2772,2699,2623,2549,2482,2424,2375,2334,2297,2262,2224,2183,2136,2084,2028,1972,1917,1866,1821,1782,
+1752,1728,1710,1696,1685,1677,1670,1665,1661,1658,1656,1656,1655,1654,1652,1648,1642,1635,1627,1620,1615,
+1613,1616,1622,1630,1639,1646,1649,1647,1638,1623,1605,1584,1565,1549,1540,1537,1541,1550,1561,1571,1578,
+1580,1574,1563,1546,1526,1505,1484,1466,1450,1436,1424,1412,1399,1384,1366,1347,1325,1303,1280,1259,1239,
+1221,1205,1190,1175,1160,1143,1124,1101,1075,1045,1013,979,945,914,887,865,850,841,838,838,838,
+836,830,817,797,771,740,707,674,642,614,589,565,542,516,484,447,402,351,296,238,180,
+125,74,27,-15,-56,-97,-139,-184,-233,-285,-340,-396,-451,-505,-555,-602,-644,-683,-720,-754,-788,
+-822,-857,-894,-932,-972,-1013,-1055,-1097,-1139,-1180,-1220,-1259,-1297,-1334,-1371,-1408,-1445,-1482,-1519,-1554,-1588,
+-1620,-1649,-1676,-1701,-1725,-1748,-1771,-1795,-1819,-1841,-1860,-1874,-1882,-1884,-1882,-1876,-1871,-1871,-1879,-1900,-1934,
+-1982,-2040,-2104,-2170,-2231,-2283,-2324,-2351,-2367,-2375,-2381,-2387,-2399,-2418,-2445,-2478,-2514,-2548,-2578,-2601,-2617,
+-2627,-2633,-2640,-2650,-2666,-2690,-2722,-2758,-2796,-2831,-2862,-2886,-2904,-2915,-2924,-2933,-2944,-2960,-2981,-3005,-3032,
+-3058,-3081,-3102,-3118,-3132,-3146,-3161,-3180,-3204,-3231,-3260,-3289,-3315,-3335,-3351,-3362,-3372,-3384,-3401,-3426,-3459,
+-3499,-3543,-3585,-3622,-3649,-3664,-3666,-3660,-3648,-3637,-3630,-3633,-3645,-3665,-3690,-3717,-3740,-3756,-3765,-3769,-3772,
+-3779,-3797,-3831,-3884,-3955,-4042,-4137,-4233,-4321,-4394,-4447,-4476,-4482,-4467,-4438,-4400,-4361,-4325,-4297,-4281,-4277,
+-4283,-4298,-4318,-4341,-4362,-4381,-4395,-4405,-4411,-4416,-4421,-4429,-4443,-4463,-4490,-4525,-4566,-4612,-4661,-4712,-4762,
+-4812,-4861,-4908,-4954,-4997,-5037,-5071,-5099,-5119,-5131,-5136,-5137,-5135,-5134,-5140,-5153,-5177,-5210,-5251,-5297,-5343,
+-5386,-5422,-5450,-5469,-5481,-5489,-5496,-5504,-5515,-5530,-5547,-5565,-5581,-5592,-5596,-5592,-5580,-5562,-5540,-5516,-5493,
+-5473,-5457,-5446,-5439,-5437,-5438,-5442,-5449,-5459,-5470,-5483,-5497,-5511,-5525,-5537,-5549,-5560,-5570,-5580,-5590,-5601,
+-5613,-5625,-5636,-5646,-5651,-5653,-5650,-5644,-5635,-5625,-5616,-5611,-5609,-5613,-5623,-5637,-5656,-5678,-5701,-5727,-5752,
+-5778,-5804,-5829,-5854,-5877,-5897,-5914,-5927,-5936,-5942,-5944,-5943,-5941,-5937,-5932,-5926,-5919,-5910,-5898,-5884,-5868,
+-5851,-5836,-5822,-5812,-5807,-5807,-5811,-5818,-5827,-5835,-5842,-5846,-5849,-5850,-5853,-5858,-5867,-5881,-5900,-5923,-5949,
+-5975,-5998,-6017,-6031,-6040,-6045,-6046,-6047,-6048,-6052,-6060,-6072,-6086,-6103,-6121,-6139,-6155,-6171,-6185,-6199,-6214,
+-6229,-6245,-6263,-6281,-6299,-6315,-6329,-6340,-6348,-6352,-6354,-6355,-6354,-6354,-6354,-6355,-6356,-6357,-6358,-6357,-6355,
+-6352,-6346,-6339,-6331,-6322,-6313,-6304,-6294,-6285,-6277,-6268,-6260,-6253,-6248,-6244,-6241,-6241,-6243,-6246,-6250,-6254,
+-6257,-6257,-6255,-6250,-6241,-6229,-6215,-6200,-6184,-6167,-6152,-6138,-6125,-6114,-6105,-6098,-6093,-6090,-6089,-6091,-6095,
+-6100,-6107,-6113,-6120,-6125,-6129,-6131,-6131,-6130,-6127,-6124,-6121,-6118,-6114,-6110,-6104,-6097,-6088,-6077,-6065,-6052,
+-6039,-6028,-6019,-6014,-6011,-6012,-6015,-6018,-6022,-6024,-6023,-6019,-6011,-6001,-5988,-5974,-5959,-5944,-5930,-5915,-5901,
+-5887,-5872,-5856,-5839,-5820,-5801,-5782,-5764,-5747,-5733,-5722,-5713,-5707,-5702,-5697,-5691,-5683,-5672,-5658,-5640,-5621,
+-5600,-5580,-5561,-5544,-5531,-5520,-5513,-5507,-5501,-5495,-5487,-5476,-5462,-5446,-5427,-5406,-5385,-5363,-5342,-5322,-5303,
+-5286,-5269,-5254,-5239,-5224,-5209,-5194,-5178,-5161,-5144,-5126,-5108,-5090,-5072,-5053,-5035,-5017,-4999,-4980,-4960,-4939,
+-4917,-4893,-4869,-4845,-4821,-4798,-4776,-4756,-4736,-4717,-4698,-4678,-4656,-4633,-4608,-4583,-4558,-4534,-4513,-4495,-4479,
+-4466,-4454,-4442,-4429,-4412,-4393,-4369,-4343,-4316,-4287,-4260,-4235,-4212,-4191,-4173,-4156,-4140,-4125,-4109,-4092,-4076,
+-4058,-4041,-4024,-4007,-3991,-3976,-3962,-3949,-3938,-3929,-3923,-3918,-3915,-3911,-3907,-3899,-3886,-3868,-3843,-3813,-3779,
+-3744,-3709,-3678,-3652,-3633,-3620,-3613,-3610,-3609,-3608,-3605,-3600,-3592,-3582,-3570,-3558,-3546,-3536,-3526,-3517,-3508,
+-3499,-3489,-3478,-3467,-3455,-3444,-3435,-3427,-3421,-3416,-3411,-3406,-3400,-3391,-3380,-3367,-3352,-3336,-3321,-3306,-3293,
+-3282,-3273,-3265,-3259,-3254,-3251,-3247,-3244,-3241,-3237,-3233,-3227,-3220,-3210,-3198,-3184,-3168,-3151,-3133,-3115,-3097,
+-3080,-3063,-3047,-3031,-3015,-2999,-2983,-2968,-2954,-2941,-2929,-2917,-2904,-2888,-2870,-2847,-2819,-2787,-2752,-2716,-2683,
+-2654,-2632,-2617,-2609,-2608,-2610,-2615,-2619,-2623,-2625,-2627,-2629,-2634,-2643,-2654,-2668,-2680,-2686,-2682,-2662,-2626,
+-2571,-2501,-2421,-2336,-2254,-2183,-2128,-2091,-2074,-2073,-2084,-2101,-2119,-2132,-2138,-2137,-2127,-2113,-2095,-2076,-2058,
+-2041,-2023,-2002,-1977,-1945,-1906,-1860,-1808,-1752,-1695,-1640,-1588,-1540,-1498,-1460,-1425,-1393,-1363,-1333,-1304,-1274,
+-1243,-1213,-1182,-1151,-1120,-1089,-1059,-1030,-1004,-981,-963,-949,-939,-934,-931,-929,-927,-922,-912,-899,-880,
+-857,-830,-800,-768,-735,-702,-667,-632,-597,-561,-525,-491,-458,-428,-401,-378,-359,-343,-328,-313,-296,
+-274,-247,-213,-172,-125,-73,-17,41,99,156,210,260,305,345,380,411,438,465,490,518,548,
+583,624,670,722,778,837,897,956,1011,1064,1112,1155,1195,1232,1265,1296,1322,1342,1352,1351,1335,
+1303,1256,1194,1120,1039,955,875,802,738,687,646,615,590,570,551,531,512,492,474,459,448,
+442,441,444,446,447,442,430,410,382,346,305,262,218,177,140,107,80,57,38,23,10,
+1,-5,-8,-7,-3,4,16,30,45,60,76,90,102,113,123,131,140,147,155,163,170,
+177,183,189,194,198,203,207,211,216,221,226,231,236,240,244,248,252,257,264,271,279,
+287,296,303,309,314,316,316,314,312,310,309,310,312,316,321,325,329,332,333,332,329,
+325,321,316,311,307,303,299,294,289,282,275,266,257,247,238,228,220,213,206,199,193,
+187,182,176,171,166,163,160,159,158,159,160,162,164,166,168,169,171,174,177,180,184,
+189,193,198,202,205,207,209,210,210,211,212,213,214,216,219,222,225,228,231,234,237,
+240,242,245,247,251,255,260,267,275,284,294,305,316,328,339,350,359,368,376,383,390,
+397,403,410,416,423,430,438,446,455,465,475,487,500,514,529,545,563,581,601,622,646,
+670,696,723,749,775,798,819,837,853,865,876,885,894,904,914,924,935,946,955,963,970,
+976,980,984,987,990,992,994,995,993,991,987,983,982,986,996,1016,1044,1082,1127,1176,1225,
+1271,1310,1339,1357,1446,1457,1457,1451,1441,1431,1425,1423,1426,1433,1442,1452,1461,1469,1474,1477,1479,
+1480,1482,1484,1487,1489,1490,1490,1487,1481,1474,1466,1459,1453,1448,1446,1446,1446,1445,1443,1438,1431,
+1422,1413,1406,1403,1406,1416,1435,1461,1494,1531,1569,1605,1638,1664,1682,1692,1694,1690,1683,1675,1670,
+1669,1675,1687,1707,1732,1758,1783,1802,1812,1812,1799,1775,1742,1703,1662,1623,1592,1570,1559,1559,1570,
+1590,1618,1650,1685,1722,1760,1799,1839,1879,1920,1960,1998,2032,2062,2086,2104,2115,2121,2123,2122,2120,
+2118,2117,2116,2116,2116,2113,2108,2099,2088,2074,2060,2047,2037,2031,2031,2036,2045,2057,2069,2078,2083,
+2083,2078,2068,2057,2046,2039,2039,2045,2059,2079,2102,2126,2147,2163,2172,2172,2166,2155,2141,2126,2113,
+2102,2092,2083,2073,2058,2040,2017,1991,1966,1943,1929,1924,1931,1950,1979,2014,2052,2087,2117,2141,2160,
+2175,2191,2213,2244,2287,2342,2407,2477,2547,2610,2660,2696,2713,2715,2705,2686,2666,2648,2638,2635,2641,
+2652,2666,2679,2687,2690,2685,2675,2660,2645,2632,2623,2620,2624,2634,2648,2666,2685,2704,2723,2740,2757,
+2773,2788,2803,2817,2828,2836,2839,2836,2826,2809,2786,2759,2728,2698,2669,2644,2624,2610,2601,2597,2595,
+2594,2592,2587,2579,2568,2555,2543,2532,2526,2526,2532,2544,2558,2573,2586,2593,2592,2582,2567,2547,2528,
+2516,2514,2527,2556,2599,2654,2715,2774,2824,2859,2875,2869,2841,2796,2736,2670,2601,2535,2475,2423,2376,
+2334,2292,2248,2199,2144,2083,2017,1950,1884,1823,1771,1728,1696,1675,1663,1660,1662,1668,1676,1686,1695,
+1703,1711,1717,1720,1721,1719,1713,1702,1689,1672,1655,1639,1624,1614,1608,1607,1608,1612,1615,1616,1614,
+1607,1596,1583,1569,1556,1547,1543,1544,1549,1557,1565,1571,1573,1569,1558,1542,1521,1497,1474,1451,1431,
+1414,1399,1387,1375,1363,1349,1333,1316,1297,1277,1256,1236,1217,1198,1180,1162,1143,1123,1102,1079,1053,
+1026,997,967,936,905,876,849,824,802,784,768,753,738,722,704,681,655,625,591,556,519,
+482,446,411,376,341,304,266,225,181,135,88,40,-5,-49,-91,-130,-168,-205,-242,-281,-322,
+-366,-411,-457,-503,-549,-593,-634,-672,-709,-743,-776,-809,-842,-877,-913,-950,-988,-1026,-1065,-1103,-1140,
+-1175,-1208,-1240,-1272,-1303,-1334,-1367,-1401,-1437,-1474,-1511,-1547,-1580,-1611,-1637,-1660,-1680,-1698,-1715,-1733,-1752,
+-1771,-1791,-1811,-1827,-1841,-1851,-1858,-1864,-1871,-1884,-1905,-1938,-1982,-2037,-2101,-2169,-2236,-2297,-2347,-2385,-2408,
+-2420,-2425,-2426,-2428,-2437,-2453,-2477,-2509,-2544,-2579,-2611,-2638,-2658,-2673,-2686,-2698,-2714,-2735,-2762,-2795,-2830,
+-2865,-2896,-2921,-2939,-2949,-2955,-2958,-2963,-2971,-2986,-3007,-3034,-3063,-3092,-3119,-3142,-3160,-3174,-3186,-3197,-3210,
+-3226,-3245,-3266,-3287,-3307,-3323,-3336,-3347,-3357,-3370,-3387,-3412,-3445,-3485,-3529,-3573,-3613,-3646,-3669,-3682,-3686,
+-3685,-3683,-3682,-3688,-3699,-3717,-3739,-3761,-3781,-3796,-3807,-3814,-3822,-3834,-3854,-3888,-3936,-3999,-4073,-4153,-4233,
+-4305,-4366,-4409,-4434,-4440,-4431,-4410,-4382,-4353,-4326,-4306,-4293,-4289,-4294,-4305,-4322,-4342,-4365,-4389,-4412,-4436,
+-4459,-4482,-4505,-4530,-4557,-4587,-4619,-4656,-4696,-4739,-4785,-4832,-4880,-4927,-4971,-5013,-5049,-5080,-5104,-5120,-5130,
+-5134,-5133,-5131,-5128,-5129,-5136,-5150,-5174,-5205,-5244,-5288,-5333,-5376,-5415,-5448,-5474,-5494,-5508,-5520,-5531,-5543,
+-5558,-5576,-5596,-5616,-5635,-5651,-5661,-5666,-5663,-5655,-5642,-5625,-5607,-5589,-5574,-5562,-5554,-5551,-5552,-5556,-5562,
+-5568,-5573,-5575,-5574,-5567,-5558,-5546,-5534,-5526,-5522,-5527,-5540,-5562,-5591,-5624,-5658,-5689,-5715,-5734,-5744,-5747,
+-5744,-5738,-5732,-5727,-5726,-5728,-5732,-5737,-5742,-5746,-5748,-5747,-5746,-5745,-5746,-5752,-5762,-5778,-5797,-5819,-5843,
+-5865,-5886,-5903,-5916,-5926,-5932,-5935,-5935,-5932,-5925,-5916,-5903,-5887,-5869,-5852,-5835,-5822,-5813,-5810,-5812,-5819,
+-5829,-5841,-5852,-5862,-5870,-5877,-5882,-5888,-5896,-5907,-5921,-5938,-5957,-5977,-5996,-6012,-6025,-6034,-6041,-6046,-6051,
+-6057,-6066,-6078,-6092,-6108,-6124,-6140,-6154,-6167,-6178,-6188,-6199,-6210,-6224,-6241,-6259,-6280,-6301,-6320,-6337,-6351,
+-6361,-6368,-6372,-6374,-6376,-6378,-6381,-6385,-6390,-6394,-6397,-6398,-6397,-6392,-6386,-6377,-6367,-6357,-6348,-6339,-6332,
+-6325,-6321,-6317,-6314,-6312,-6312,-6313,-6315,-6320,-6326,-6333,-6340,-6347,-6351,-6352,-6349,-6342,-6331,-6315,-6297,-6277,
+-6256,-6236,-6217,-6201,-6188,-6177,-6170,-6165,-6163,-6162,-6163,-6165,-6169,-6172,-6176,-6179,-6182,-6183,-6183,-6181,-6178,
+-6174,-6170,-6164,-6159,-6153,-6148,-6141,-6134,-6126,-6116,-6105,-6093,-6080,-6068,-6058,-6049,-6043,-6040,-6039,-6041,-6044,
+-6047,-6049,-6050,-6048,-6043,-6035,-6025,-6013,-5999,-5984,-5968,-5952,-5936,-5919,-5902,-5884,-5865,-5846,-5827,-5808,-5790,
+-5774,-5760,-5749,-5740,-5733,-5727,-5721,-5714,-5705,-5694,-5681,-5665,-5647,-5628,-5610,-5592,-5577,-5564,-5553,-5545,-5538,
+-5531,-5524,-5515,-5504,-5490,-5474,-5456,-5437,-5416,-5396,-5376,-5356,-5338,-5321,-5305,-5290,-5275,-5260,-5245,-5229,-5213,
+-5195,-5177,-5158,-5139,-5120,-5101,-5083,-5064,-5046,-5027,-5007,-4987,-4964,-4941,-4916,-4891,-4867,-4843,-4821,-4800,-4782,
+-4765,-4748,-4730,-4712,-4691,-4667,-4642,-4616,-4590,-4566,-4544,-4525,-4510,-4498,-4487,-4477,-4466,-4452,-4434,-4413,-4389,
+-4362,-4334,-4306,-4279,-4254,-4231,-4211,-4191,-4173,-4155,-4137,-4118,-4100,-4081,-4063,-4045,-4029,-4014,-4000,-3988,-3977,
+-3969,-3962,-3959,-3957,-3957,-3958,-3959,-3957,-3952,-3941,-3925,-3903,-3875,-3844,-3810,-3777,-3746,-3720,-3697,-3681,-3668,
+-3660,-3653,-3648,-3642,-3636,-3628,-3619,-3609,-3597,-3586,-3574,-3561,-3548,-3535,-3522,-3509,-3496,-3485,-3474,-3465,-3457,
+-3451,-3445,-3439,-3432,-3424,-3414,-3403,-3391,-3377,-3364,-3350,-3338,-3326,-3316,-3306,-3298,-3290,-3284,-3278,-3273,-3269,
+-3266,-3263,-3259,-3254,-3247,-3238,-3226,-3211,-3195,-3177,-3159,-3141,-3124,-3108,-3094,-3080,-3066,-3052,-3037,-3021,-3004,
+-2985,-2966,-2946,-2925,-2903,-2879,-2852,-2823,-2792,-2759,-2725,-2692,-2662,-2638,-2620,-2609,-2606,-2608,-2615,-2625,-2635,
+-2646,-2655,-2664,-2673,-2683,-2693,-2704,-2713,-2717,-2712,-2696,-2664,-2615,-2550,-2473,-2388,-2301,-2220,-2151,-2100,-2069,
+-2057,-2063,-2082,-2108,-2135,-2158,-2173,-2180,-2176,-2164,-2145,-2121,-2095,-2067,-2036,-2003,-1966,-1925,-1878,-1826,-1770,
+-1710,-1649,-1588,-1529,-1474,-1423,-1376,-1335,-1298,-1265,-1235,-1209,-1185,-1163,-1142,-1122,-1102,-1083,-1064,-1046,-1031,
+-1018,-1008,-1002,-999,-999,-999,-1000,-998,-994,-985,-971,-953,-931,-907,-881,-854,-826,-797,-767,-735,-701,
+-664,-625,-585,-546,-510,-477,-449,-427,-409,-395,-383,-369,-354,-334,-308,-277,-241,-201,-158,-112,-65,
+-18,29,77,124,170,215,257,297,334,368,401,434,469,508,553,605,665,731,802,873,943,
+1007,1065,1114,1156,1191,1222,1249,1274,1297,1317,1330,1333,1323,1296,1251,1189,1113,1026,935,847,767,
+699,645,606,579,561,548,536,521,503,482,459,435,415,398,387,380,376,371,364,352,332,
+304,269,228,183,138,95,55,20,-8,-32,-52,-68,-80,-90,-96,-98,-97,-91,-82,-70,-55,
+-39,-22,-7,6,17,27,36,43,51,59,67,75,83,91,99,106,111,117,122,128,134,
+141,149,156,164,171,177,183,187,191,195,200,205,213,221,229,237,244,250,253,254,254,
+252,251,250,251,253,258,263,268,272,275,276,275,272,268,263,259,254,251,249,247,244,
+241,237,230,223,214,205,196,187,180,175,171,168,165,163,161,159,156,153,150,148,146,
+145,144,145,146,148,150,152,155,158,161,165,170,174,179,184,188,191,194,196,198,198,
+199,199,199,199,199,200,200,201,202,202,203,204,205,206,208,211,215,220,225,233,242,
+251,262,274,286,298,310,321,331,339,346,352,357,361,365,370,375,381,389,398,409,423,
+437,454,472,491,512,533,556,580,604,630,656,684,713,742,771,800,828,854,878,899,918,
+935,950,964,976,989,1000,1011,1020,1028,1035,1039,1042,1044,1045,1046,1048,1051,1054,1057,1057,1055,
+1050,1042,1032,1021,1014,1013,1021,1040,1071,1115,1168,1226,1285,1340,1387,1423,1446,1473,1486,1487,1481,
+1471,1462,1456,1455,1459,1468,1478,1489,1499,1505,1508,1509,1507,1504,1500,1497,1494,1490,1485,1477,1465,
+1450,1431,1412,1393,1376,1362,1353,1348,1347,1348,1348,1346,1342,1333,1322,1310,1298,1291,1290,1297,1313,
+1338,1370,1407,1444,1478,1507,1528,1540,1543,1540,1532,1524,1518,1517,1524,1539,1561,1589,1619,1648,1672,
+1689,1696,1692,1679,1658,1633,1606,1582,1563,1552,1551,1561,1581,1611,1649,1695,1747,1804,1863,1925,1987,
+2049,2107,2162,2211,2253,2287,2314,2332,2343,2349,2350,2347,2342,2333,2322,2308,2289,2264,2234,2198,2158,
+2114,2070,2028,1990,1960,1939,1928,1927,1933,1946,1962,1979,1994,2005,2012,2014,2014,2012,2011,2013,2018,
+2027,2039,2052,2065,2076,2083,2086,2085,2080,2074,2069,2066,2067,2072,2079,2087,2093,2095,2091,2080,2062,
+2041,2018,1997,1980,1971,1971,1978,1992,2010,2029,2048,2064,2080,2095,2112,2135,2165,2204,2252,2306,2363,
+2418,2468,2507,2533,2545,2546,2538,2525,2513,2505,2505,2514,2531,2554,2579,2605,2626,2642,2652,2655,2655,
+2652,2650,2650,2653,2659,2667,2675,2683,2687,2688,2685,2678,2669,2659,2650,2643,2637,2635,2634,2634,2634,
+2633,2628,2621,2610,2597,2582,2567,2552,2539,2528,2518,2510,2503,2496,2489,2482,2474,2467,2462,2459,2460,
+2466,2476,2489,2503,2516,2526,2529,2525,2512,2493,2470,2447,2428,2419,2423,2443,2479,2529,2588,2651,2711,
+2761,2797,2814,2810,2788,2750,2701,2645,2588,2533,2483,2438,2396,2355,2312,2263,2208,2146,2075,2000,1923,
+1848,1780,1721,1673,1640,1621,1614,1618,1632,1651,1674,1698,1721,1742,1759,1772,1779,1781,1776,1766,1751,
+1731,1708,1684,1660,1638,1619,1605,1594,1587,1583,1580,1577,1574,1569,1565,1560,1556,1554,1555,1558,1564,
+1571,1577,1581,1581,1575,1563,1546,1524,1498,1472,1446,1422,1400,1382,1366,1352,1339,1326,1312,1298,1282,
+1264,1245,1226,1206,1185,1162,1139,1115,1089,1063,1035,1008,980,953,927,901,876,851,826,801,775,
+749,722,694,667,638,610,580,549,516,481,443,404,361,317,270,223,174,125,77,29,-16,
+-60,-102,-141,-178,-212,-245,-276,-307,-338,-370,-403,-438,-475,-512,-550,-587,-624,-658,-691,-722,-751,
+-778,-806,-834,-863,-893,-925,-960,-995,-1032,-1069,-1105,-1140,-1173,-1204,-1232,-1259,-1284,-1309,-1336,-1364,-1394,
+-1427,-1463,-1499,-1535,-1568,-1599,-1625,-1647,-1664,-1679,-1692,-1704,-1718,-1733,-1751,-1770,-1791,-1812,-1833,-1855,-1877,
+-1903,-1933,-1970,-2015,-2068,-2128,-2193,-2257,-2318,-2371,-2413,-2441,-2457,-2463,-2462,-2458,-2457,-2462,-2475,-2498,-2528,
+-2563,-2600,-2637,-2670,-2699,-2724,-2747,-2770,-2794,-2822,-2853,-2886,-2919,-2950,-2976,-2995,-3008,-3014,-3016,-3017,-3020,
+-3028,-3043,-3065,-3092,-3122,-3152,-3179,-3201,-3218,-3229,-3236,-3242,-3248,-3256,-3267,-3279,-3294,-3308,-3321,-3333,-3343,
+-3354,-3368,-3386,-3410,-3441,-3479,-3521,-3565,-3608,-3646,-3678,-3702,-3719,-3730,-3738,-3745,-3753,-3763,-3777,-3792,-3808,
+-3824,-3839,-3853,-3868,-3885,-3908,-3938,-3977,-4026,-4082,-4145,-4209,-4270,-4324,-4368,-4399,-4418,-4425,-4422,-4412,-4399,
+-4384,-4370,-4360,-4353,-4351,-4353,-4361,-4373,-4391,-4413,-4439,-4470,-4504,-4539,-4575,-4611,-4647,-4681,-4715,-4749,-4785,
+-4823,-4864,-4907,-4953,-5000,-5045,-5087,-5122,-5149,-5167,-5175,-5174,-5166,-5154,-5140,-5129,-5122,-5124,-5135,-5155,-5184,
+-5221,-5263,-5308,-5354,-5397,-5437,-5473,-5503,-5529,-5552,-5572,-5590,-5607,-5625,-5642,-5661,-5679,-5697,-5714,-5729,-5740,
+-5747,-5750,-5748,-5742,-5731,-5719,-5705,-5692,-5681,-5674,-5670,-5670,-5670,-5669,-5664,-5653,-5633,-5606,-5572,-5535,-5499,
+-5468,-5447,-5441,-5451,-5478,-5518,-5569,-5624,-5679,-5729,-5772,-5804,-5828,-5845,-5858,-5868,-5879,-5890,-5901,-5910,-5914,
+-5912,-5900,-5879,-5849,-5815,-5779,-5745,-5718,-5700,-5694,-5699,-5714,-5735,-5761,-5789,-5815,-5838,-5858,-5873,-5886,-5895,
+-5901,-5905,-5905,-5903,-5897,-5889,-5879,-5868,-5858,-5851,-5846,-5846,-5849,-5856,-5865,-5875,-5884,-5893,-5900,-5906,-5911,
+-5917,-5925,-5935,-5948,-5962,-5977,-5991,-6005,-6016,-6025,-6033,-6039,-6046,-6054,-6064,-6076,-6089,-6104,-6118,-6131,-6142,
+-6151,-6158,-6164,-6172,-6181,-6194,-6211,-6232,-6256,-6282,-6307,-6331,-6351,-6367,-6379,-6387,-6392,-6396,-6400,-6404,-6410,
+-6416,-6423,-6429,-6433,-6435,-6434,-6429,-6422,-6413,-6402,-6391,-6381,-6373,-6367,-6363,-6362,-6364,-6367,-6373,-6380,-6389,
+-6399,-6409,-6418,-6426,-6432,-6434,-6432,-6426,-6416,-6401,-6383,-6362,-6341,-6320,-6299,-6282,-6266,-6254,-6245,-6239,-6234,
+-6232,-6230,-6230,-6230,-6231,-6231,-6231,-6230,-6229,-6226,-6223,-6218,-6212,-6205,-6197,-6189,-6181,-6172,-6164,-6155,-6147,
+-6138,-6129,-6120,-6111,-6102,-6094,-6086,-6080,-6075,-6072,-6070,-6069,-6069,-6069,-6069,-6067,-6064,-6058,-6051,-6042,-6031,
+-6018,-6004,-5989,-5973,-5956,-5939,-5922,-5904,-5886,-5868,-5851,-5834,-5818,-5804,-5791,-5779,-5769,-5760,-5752,-5744,-5735,
+-5726,-5716,-5704,-5692,-5678,-5664,-5650,-5636,-5622,-5609,-5597,-5585,-5573,-5561,-5549,-5535,-5521,-5506,-5491,-5474,-5458,
+-5441,-5424,-5407,-5390,-5374,-5357,-5341,-5325,-5309,-5292,-5276,-5259,-5241,-5223,-5205,-5186,-5168,-5149,-5131,-5113,-5095,
+-5077,-5059,-5039,-5019,-4997,-4975,-4951,-4926,-4902,-4878,-4856,-4836,-4818,-4801,-4784,-4768,-4749,-4729,-4707,-4682,-4655,
+-4628,-4601,-4576,-4554,-4534,-4518,-4504,-4492,-4480,-4467,-4452,-4435,-4416,-4395,-4372,-4349,-4326,-4303,-4280,-4259,-4237,
+-4217,-4196,-4176,-4156,-4138,-4120,-4104,-4089,-4076,-4064,-4053,-4042,-4032,-4022,-4012,-4003,-3995,-3988,-3982,-3977,-3972,
+-3965,-3957,-3945,-3929,-3909,-3885,-3859,-3831,-3804,-3778,-3754,-3735,-3719,-3707,-3698,-3691,-3685,-3679,-3673,-3665,-3656,
+-3645,-3632,-3618,-3603,-3587,-3572,-3557,-3544,-3531,-3521,-3512,-3504,-3497,-3491,-3484,-3476,-3468,-3458,-3447,-3435,-3422,
+-3410,-3398,-3386,-3375,-3363,-3352,-3340,-3329,-3318,-3307,-3298,-3291,-3286,-3282,-3279,-3277,-3274,-3269,-3261,-3249,-3234,
+-3215,-3195,-3174,-3154,-3135,-3118,-3104,-3091,-3079,-3066,-3051,-3033,-3011,-2987,-2959,-2928,-2896,-2863,-2830,-2798,-2766,
+-2736,-2706,-2679,-2654,-2633,-2615,-2601,-2592,-2587,-2586,-2587,-2590,-2594,-2598,-2603,-2608,-2613,-2619,-2625,-2630,-2631,
+-2627,-2614,-2590,-2553,-2503,-2441,-2369,-2293,-2217,-2147,-2089,-2046,-2021,-2013,-2020,-2038,-2062,-2088,-2110,-2125,-2131,
+-2126,-2112,-2089,-2059,-2024,-1986,-1945,-1902,-1857,-1810,-1761,-1710,-1657,-1603,-1549,-1495,-1443,-1393,-1348,-1306,-1271,
+-1240,-1215,-1195,-1179,-1167,-1157,-1149,-1140,-1132,-1124,-1115,-1106,-1099,-1092,-1088,-1085,-1083,-1081,-1077,-1070,-1059,
+-1043,-1023,-1000,-974,-948,-923,-900,-879,-859,-838,-816,-791,-761,-727,-688,-647,-606,-567,-533,-503,-480,
+-462,-447,-433,-418,-400,-378,-352,-322,-289,-256,-222,-190,-157,-125,-90,-52,-11,33,82,132,183,
+231,276,318,357,395,435,480,533,594,664,740,820,900,975,1042,1099,1144,1179,1206,1227,1244,
+1258,1270,1277,1277,1266,1241,1200,1142,1070,988,900,814,735,669,617,580,557,544,536,529,519,
+504,483,458,430,401,376,354,336,322,310,296,279,257,229,195,157,115,73,33,-3,-35,
+-62,-85,-103,-119,-131,-140,-147,-151,-151,-148,-141,-130,-117,-103,-89,-75,-63,-53,-45,-37,-30,
+-23,-15,-6,2,11,20,28,35,40,45,49,53,59,65,73,81,90,98,106,112,116,
+119,122,124,128,132,137,144,152,159,166,171,175,177,179,179,180,181,183,187,191,196,
+200,204,206,207,207,206,204,202,201,200,200,199,198,196,192,187,180,172,164,156,149,
+143,140,137,137,137,138,138,139,138,137,135,133,131,130,128,128,128,128,129,131,133,
+136,140,144,149,154,159,164,169,173,176,179,181,183,184,185,186,186,186,186,185,183,
+181,179,177,176,176,177,180,184,190,197,205,215,225,235,245,255,265,274,283,291,298,
+304,310,315,319,323,327,333,339,348,359,372,389,408,431,456,483,512,543,575,609,642,
+677,711,746,780,814,847,877,906,932,955,976,994,1010,1024,1038,1051,1063,1074,1085,1093,1099,
+1102,1103,1100,1096,1091,1087,1085,1084,1086,1089,1092,1093,1091,1084,1073,1059,1044,1032,1026,1030,1047,
+1078,1122,1176,1238,1300,1359,1410,1448,1473,1445,1456,1457,1449,1438,1428,1421,1418,1422,1429,1440,1451,
+1461,1468,1472,1474,1474,1473,1472,1472,1473,1473,1471,1466,1456,1442,1422,1398,1373,1348,1325,1306,1292,
+1282,1276,1271,1267,1260,1251,1239,1225,1210,1197,1189,1186,1192,1204,1223,1247,1273,1298,1321,1338,1351,
+1358,1362,1364,1367,1373,1385,1402,1426,1455,1487,1519,1550,1576,1596,1608,1612,1610,1602,1591,1578,1566,
+1558,1555,1559,1572,1594,1626,1668,1720,1780,1848,1921,1996,2072,2146,2214,2276,2329,2372,2406,2431,2449,
+2460,2465,2466,2463,2456,2442,2423,2396,2360,2316,2264,2206,2145,2083,2023,1970,1925,1892,1872,1864,1869,
+1883,1904,1930,1957,1983,2006,2024,2037,2046,2050,2052,2052,2052,2051,2051,2051,2051,2050,2048,2045,2041,
+2038,2036,2037,2042,2052,2064,2080,2096,2111,2122,2127,2125,2117,2103,2084,2064,2044,2027,2015,2007,2004,
+2004,2008,2014,2021,2031,2043,2059,2081,2110,2145,2186,2231,2278,2322,2361,2391,2412,2423,2426,2424,2420,
+2417,2419,2428,2444,2466,2493,2522,2550,2575,2595,2610,2621,2628,2633,2638,2643,2650,2658,2665,2671,2673,
+2671,2663,2650,2632,2612,2590,2569,2550,2536,2525,2518,2514,2512,2512,2511,2510,2508,2504,2499,2493,2486,
+2478,2469,2459,2448,2436,2423,2410,2397,2387,2380,2378,2381,2390,2404,2421,2440,2456,2469,2474,2470,2456,
+2434,2407,2377,2349,2329,2321,2327,2350,2389,2441,2501,2564,2624,2674,2711,2731,2734,2720,2693,2656,2613,
+2569,2526,2485,2447,2411,2374,2332,2285,2229,2165,2092,2013,1931,1850,1775,1708,1653,1613,1588,1578,1581,
+1595,1618,1646,1676,1705,1732,1754,1769,1778,1781,1777,1767,1752,1733,1712,1690,1667,1645,1625,1607,1592,
+1578,1567,1558,1551,1546,1542,1542,1544,1548,1555,1564,1574,1584,1593,1598,1599,1594,1583,1567,1546,1521,
+1494,1466,1440,1415,1392,1373,1355,1340,1325,1311,1297,1282,1267,1251,1234,1215,1194,1172,1146,1119,1089,
+1057,1024,990,958,927,898,871,847,824,801,778,754,728,700,670,638,605,571,537,502,468,
+432,395,355,313,266,216,162,106,49,-7,-62,-114,-162,-205,-243,-276,-305,-331,-355,-378,-401,
+-425,-451,-479,-509,-540,-571,-603,-635,-666,-696,-724,-752,-778,-804,-829,-855,-881,-909,-938,-969,-1002,
+-1036,-1070,-1105,-1139,-1172,-1202,-1230,-1257,-1281,-1305,-1329,-1355,-1383,-1414,-1448,-1484,-1520,-1556,-1590,-1620,-1646,
+-1667,-1683,-1697,-1710,-1722,-1737,-1755,-1776,-1800,-1829,-1860,-1894,-1931,-1972,-2016,-2064,-2116,-2172,-2230,-2287,-2342,
+-2392,-2432,-2463,-2482,-2491,-2492,-2489,-2484,-2482,-2486,-2498,-2519,-2547,-2581,-2618,-2655,-2692,-2726,-2758,-2789,-2818,
+-2849,-2880,-2913,-2945,-2976,-3004,-3026,-3042,-3052,-3058,-3060,-3062,-3067,-3077,-3092,-3113,-3139,-3167,-3195,-3220,-3240,
+-3255,-3265,-3271,-3275,-3278,-3283,-3290,-3300,-3312,-3324,-3337,-3349,-3360,-3372,-3384,-3400,-3421,-3447,-3479,-3516,-3556,
+-3598,-3639,-3677,-3710,-3738,-3760,-3777,-3790,-3801,-3810,-3818,-3826,-3834,-3844,-3857,-3873,-3893,-3920,-3954,-3994,-4041,
+-4094,-4149,-4205,-4258,-4305,-4346,-4378,-4403,-4420,-4431,-4438,-4443,-4446,-4448,-4451,-4453,-4455,-4457,-4460,-4465,-4473,
+-4486,-4504,-4527,-4556,-4590,-4625,-4661,-4696,-4729,-4760,-4789,-4817,-4848,-4881,-4920,-4963,-5009,-5058,-5104,-5145,-5178,
+-5200,-5210,-5208,-5196,-5177,-5156,-5136,-5122,-5116,-5120,-5135,-5160,-5193,-5232,-5275,-5320,-5364,-5407,-5448,-5486,-5521,
+-5553,-5581,-5606,-5628,-5646,-5661,-5674,-5687,-5699,-5712,-5727,-5743,-5759,-5774,-5786,-5794,-5796,-5792,-5782,-5768,-5752,
+-5737,-5725,-5716,-5711,-5708,-5704,-5696,-5680,-5654,-5617,-5571,-5519,-5466,-5419,-5385,-5367,-5371,-5396,-5439,-5498,-5566,
+-5636,-5703,-5764,-5814,-5856,-5889,-5918,-5944,-5969,-5993,-6015,-6033,-6044,-6042,-6028,-5999,-5957,-5906,-5850,-5795,-5746,
+-5708,-5683,-5672,-5673,-5685,-5704,-5726,-5748,-5768,-5785,-5799,-5812,-5823,-5833,-5844,-5855,-5866,-5875,-5883,-5888,-5891,
+-5891,-5891,-5890,-5890,-5891,-5893,-5896,-5899,-5903,-5905,-5908,-5910,-5912,-5916,-5922,-5930,-5942,-5956,-5972,-5988,-6004,
+-6018,-6029,-6039,-6046,-6052,-6057,-6062,-6068,-6075,-6083,-6090,-6096,-6102,-6106,-6110,-6114,-6121,-6130,-6144,-6163,-6188,
+-6216,-6247,-6279,-6310,-6337,-6361,-6379,-6392,-6401,-6407,-6412,-6417,-6423,-6431,-6439,-6448,-6456,-6462,-6465,-6465,-6460,
+-6453,-6442,-6431,-6419,-6410,-6403,-6399,-6400,-6405,-6414,-6425,-6438,-6452,-6465,-6476,-6484,-6489,-6490,-6486,-6478,-6466,
+-6452,-6434,-6416,-6398,-6380,-6363,-6347,-6334,-6322,-6313,-6304,-6298,-6292,-6287,-6283,-6280,-6277,-6275,-6272,-6270,-6267,
+-6264,-6260,-6254,-6247,-6238,-6229,-6218,-6207,-6197,-6186,-6176,-6167,-6159,-6151,-6145,-6139,-6133,-6128,-6123,-6118,-6113,
+-6108,-6104,-6099,-6095,-6091,-6087,-6083,-6079,-6074,-6068,-6061,-6053,-6044,-6034,-6022,-6009,-5995,-5979,-5964,-5947,-5931,
+-5914,-5898,-5883,-5868,-5853,-5840,-5827,-5814,-5802,-5791,-5780,-5769,-5758,-5748,-5739,-5729,-5720,-5711,-5701,-5692,-5681,
+-5670,-5658,-5644,-5629,-5613,-5597,-5579,-5562,-5545,-5529,-5513,-5498,-5484,-5470,-5456,-5442,-5427,-5411,-5394,-5377,-5359,
+-5341,-5323,-5305,-5287,-5269,-5251,-5233,-5215,-5197,-5178,-5160,-5142,-5124,-5106,-5088,-5070,-5051,-5031,-5011,-4989,-4967,
+-4944,-4922,-4900,-4879,-4859,-4840,-4822,-4803,-4785,-4764,-4742,-4718,-4693,-4666,-4638,-4611,-4585,-4560,-4538,-4518,-4501,
+-4485,-4470,-4455,-4440,-4425,-4409,-4392,-4374,-4356,-4336,-4317,-4296,-4275,-4254,-4233,-4213,-4193,-4176,-4160,-4147,-4136,
+-4126,-4117,-4108,-4098,-4087,-4075,-4061,-4046,-4031,-4016,-4002,-3990,-3978,-3968,-3957,-3947,-3935,-3921,-3904,-3886,-3866,
+-3845,-3824,-3804,-3787,-3772,-3759,-3749,-3742,-3735,-3729,-3722,-3714,-3705,-3693,-3680,-3665,-3650,-3634,-3619,-3605,-3593,
+-3582,-3572,-3564,-3556,-3548,-3539,-3529,-3517,-3504,-3491,-3478,-3465,-3453,-3442,-3431,-3421,-3410,-3398,-3385,-3370,-3354,
+-3337,-3321,-3307,-3296,-3288,-3284,-3282,-3281,-3279,-3274,-3265,-3250,-3230,-3204,-3176,-3146,-3117,-3091,-3069,-3052,-3039,
+-3028,-3017,-3005,-2989,-2968,-2940,-2907,-2870,-2830,-2789,-2749,-2712,-2679,-2650,-2627,-2607,-2591,-2578,-2566,-2556,-2545,
+-2535,-2524,-2513,-2502,-2491,-2481,-2472,-2465,-2459,-2456,-2453,-2450,-2446,-2438,-2424,-2403,-2373,-2334,-2287,-2234,-2177,
+-2120,-2067,-2021,-1984,-1958,-1944,-1940,-1944,-1953,-1964,-1974,-1979,-1978,-1969,-1953,-1929,-1898,-1862,-1823,-1780,-1737,
+-1694,-1651,-1609,-1568,-1528,-1490,-1453,-1417,-1384,-1352,-1323,-1298,-1277,-1260,-1247,-1239,-1234,-1232,-1230,-1229,-1227,
+-1222,-1217,-1209,-1201,-1192,-1184,-1176,-1169,-1162,-1152,-1140,-1125,-1104,-1080,-1052,-1022,-992,-965,-940,-920,-903,
+-889,-874,-858,-837,-810,-778,-741,-701,-661,-623,-590,-562,-538,-519,-502,-485,-465,-440,-412,-380,-347,
+-314,-284,-257,-234,-213,-193,-170,-141,-104,-59,-6,51,112,171,226,275,317,354,389,426,469,
+521,583,655,735,818,900,975,1041,1094,1134,1163,1183,1195,1203,1208,1210,1206,1194,1172,1137,1088,
+1026,954,875,796,721,656,604,565,539,523,513,506,497,483,464,440,412,382,353,326,303,
+281,262,243,221,197,168,136,101,64,27,-6,-37,-64,-86,-105,-120,-133,-145,-155,-163,-168,
+-171,-171,-168,-161,-152,-141,-131,-120,-111,-103,-97,-91,-84,-78,-70,-60,-50,-40,-31,-22,-16,
+-11,-8,-6,-4,-2,1,6,13,21,30,38,45,51,55,58,60,62,65,69,74,80,
+87,94,101,106,110,113,115,117,118,120,122,126,129,134,138,142,145,148,150,152,153,
+154,155,155,155,155,153,151,148,144,139,135,130,126,123,122,120,120,120,120,120,119,
+118,117,115,113,111,109,108,106,105,105,105,106,108,111,115,119,125,131,137,143,148,
+153,157,161,164,167,169,171,173,174,175,174,173,171,168,164,161,159,158,159,162,167,
+173,181,188,196,203,209,215,219,223,226,229,233,238,243,249,256,264,273,284,295,309,
+324,343,364,388,416,447,481,517,556,595,636,678,719,760,801,841,879,915,948,977,1003,
+1024,1041,1055,1066,1075,1083,1091,1098,1106,1113,1119,1123,1123,1120,1114,1104,1092,1081,1070,1063,1060,
+1060,1064,1069,1074,1076,1073,1067,1056,1043,1032,1026,1029,1044,1072,1112,1163,1221,1281,1337,1385,1422,
+1445,1396,1401,1395,1382,1366,1350,1337,1329,1328,1333,1342,1353,1365,1376,1386,1394,1400,1407,1413,1420,
+1428,1435,1441,1443,1440,1431,1416,1396,1372,1346,1320,1296,1275,1258,1244,1233,1223,1214,1204,1192,1179,
+1166,1153,1142,1134,1131,1132,1137,1146,1157,1169,1182,1194,1206,1219,1232,1248,1266,1288,1313,1342,1372,
+1404,1436,1466,1493,1516,1536,1551,1562,1570,1574,1576,1576,1574,1573,1573,1576,1584,1599,1623,1657,1703,
+1759,1824,1897,1973,2049,2121,2187,2244,2291,2328,2356,2376,2389,2399,2405,2408,2408,2403,2391,2372,2343,
+2305,2258,2204,2145,2084,2026,1975,1932,1900,1880,1873,1878,1893,1915,1943,1974,2005,2035,2061,2083,2100,
+2112,2118,2119,2115,2108,2099,2088,2077,2066,2057,2050,2046,2045,2047,2053,2063,2075,2089,2105,2120,2134,
+2146,2155,2159,2158,2153,2144,2133,2119,2105,2092,2080,2071,2063,2057,2052,2050,2050,2054,2061,2072,2089,
+2112,2141,2173,2208,2242,2275,2302,2323,2337,2345,2348,2348,2348,2350,2358,2371,2390,2413,2440,2468,2495,
+2518,2537,2552,2563,2571,2577,2584,2591,2599,2608,2617,2625,2629,2630,2625,2615,2601,2583,2563,2542,2522,
+2503,2488,2474,2464,2455,2449,2445,2441,2439,2437,2435,2433,2431,2427,2421,2412,2401,2387,2370,2354,2338,
+2325,2317,2314,2318,2328,2342,2359,2375,2388,2395,2393,2382,2362,2335,2304,2273,2247,2230,2225,2235,2260,
+2300,2350,2407,2467,2523,2571,2607,2629,2638,2632,2615,2590,2558,2524,2489,2454,2418,2382,2343,2299,2248,
+2190,2124,2051,1973,1892,1813,1739,1673,1618,1577,1551,1538,1539,1550,1570,1594,1620,1645,1668,1685,1698,
+1705,1706,1704,1698,1690,1680,1670,1658,1646,1633,1620,1606,1592,1578,1565,1552,1542,1535,1531,1531,1535,
+1542,1552,1564,1577,1588,1596,1600,1599,1593,1581,1565,1544,1521,1495,1470,1444,1420,1398,1377,1357,1339,
+1322,1306,1290,1275,1260,1244,1228,1210,1191,1168,1143,1114,1083,1049,1013,977,942,908,876,847,819,
+794,769,745,719,693,666,637,606,576,545,514,483,451,418,382,344,301,254,204,149,92,
+35,-22,-77,-129,-176,-218,-254,-286,-314,-339,-362,-384,-406,-428,-451,-475,-500,-527,-554,-583,-614,
+-645,-677,-710,-743,-776,-808,-838,-868,-897,-925,-952,-980,-1010,-1040,-1072,-1106,-1141,-1175,-1209,-1241,-1272,
+-1300,-1326,-1352,-1378,-1406,-1436,-1469,-1505,-1542,-1581,-1618,-1653,-1684,-1711,-1733,-1752,-1768,-1784,-1801,-1821,-1845,
+-1873,-1907,-1944,-1986,-2031,-2078,-2128,-2179,-2230,-2282,-2332,-2380,-2424,-2462,-2494,-2517,-2533,-2542,-2546,-2547,-2548,
+-2550,-2557,-2570,-2589,-2614,-2643,-2675,-2708,-2742,-2774,-2805,-2836,-2865,-2895,-2924,-2953,-2982,-3008,-3030,-3048,-3062,
+-3071,-3076,-3080,-3085,-3091,-3102,-3118,-3138,-3163,-3189,-3215,-3239,-3259,-3275,-3287,-3296,-3303,-3310,-3317,-3326,-3338,
+-3351,-3365,-3379,-3392,-3404,-3415,-3427,-3439,-3454,-3472,-3496,-3524,-3556,-3592,-3630,-3669,-3705,-3739,-3768,-3793,-3811,
+-3825,-3833,-3838,-3841,-3844,-3849,-3857,-3872,-3893,-3923,-3960,-4004,-4054,-4106,-4158,-4208,-4253,-4292,-4325,-4352,-4375,
+-4395,-4415,-4435,-4456,-4477,-4499,-4520,-4538,-4554,-4566,-4576,-4585,-4594,-4606,-4622,-4641,-4665,-4691,-4718,-4745,-4769,
+-4791,-4810,-4827,-4846,-4868,-4896,-4930,-4971,-5016,-5064,-5110,-5150,-5181,-5200,-5206,-5201,-5187,-5169,-5150,-5135,-5127,
+-5129,-5142,-5165,-5195,-5232,-5271,-5312,-5352,-5392,-5429,-5465,-5500,-5533,-5564,-5591,-5615,-5634,-5649,-5659,-5665,-5670,
+-5676,-5685,-5697,-5713,-5732,-5752,-5770,-5782,-5788,-5786,-5775,-5759,-5739,-5720,-5704,-5693,-5689,-5689,-5691,-5690,-5682,
+-5663,-5631,-5587,-5533,-5476,-5423,-5380,-5354,-5349,-5367,-5407,-5465,-5534,-5607,-5679,-5743,-5799,-5844,-5880,-5910,-5936,
+-5961,-5986,-6010,-6030,-6044,-6048,-6040,-6018,-5984,-5940,-5890,-5840,-5795,-5758,-5732,-5718,-5715,-5720,-5729,-5739,-5748,
+-5754,-5756,-5756,-5755,-5755,-5758,-5765,-5777,-5793,-5811,-5831,-5850,-5867,-5882,-5893,-5901,-5907,-5912,-5914,-5916,-5916,
+-5916,-5914,-5912,-5910,-5909,-5910,-5914,-5922,-5934,-5949,-5968,-5989,-6011,-6031,-6048,-6062,-6072,-6079,-6083,-6084,-6084,
+-6083,-6082,-6080,-6079,-6077,-6076,-6075,-6076,-6079,-6087,-6099,-6117,-6141,-6171,-6204,-6240,-6276,-6310,-6340,-6366,-6387,
+-6403,-6414,-6423,-6431,-6439,-6447,-6456,-6465,-6474,-6481,-6485,-6486,-6482,-6474,-6464,-6452,-6441,-6431,-6425,-6424,-6429,
+-6438,-6452,-6469,-6486,-6501,-6514,-6521,-6523,-6519,-6510,-6496,-6479,-6461,-6442,-6425,-6410,-6398,-6388,-6380,-6375,-6369,
+-6364,-6358,-6352,-6344,-6336,-6328,-6320,-6313,-6308,-6303,-6300,-6297,-6294,-6291,-6286,-6280,-6272,-6262,-6251,-6239,-6227,
+-6215,-6204,-6195,-6187,-6180,-6175,-6171,-6167,-6163,-6158,-6153,-6147,-6141,-6134,-6127,-6120,-6113,-6106,-6101,-6096,-6091,
+-6086,-6082,-6077,-6071,-6064,-6056,-6046,-6035,-6022,-6008,-5994,-5978,-5962,-5947,-5931,-5916,-5902,-5888,-5874,-5861,-5848,
+-5836,-5824,-5812,-5800,-5789,-5778,-5769,-5760,-5752,-5744,-5737,-5729,-5720,-5710,-5698,-5685,-5670,-5653,-5636,-5618,-5600,
+-5583,-5567,-5552,-5537,-5523,-5509,-5495,-5479,-5463,-5445,-5427,-5408,-5388,-5369,-5350,-5331,-5313,-5296,-5278,-5260,-5242,
+-5223,-5204,-5184,-5164,-5145,-5127,-5109,-5092,-5076,-5059,-5042,-5024,-5005,-4984,-4963,-4941,-4918,-4896,-4874,-4853,-4833,
+-4813,-4793,-4773,-4752,-4729,-4706,-4682,-4656,-4631,-4606,-4581,-4558,-4536,-4515,-4495,-4477,-4459,-4442,-4426,-4409,-4392,
+-4375,-4358,-4340,-4321,-4302,-4283,-4265,-4246,-4229,-4214,-4200,-4187,-4177,-4167,-4158,-4149,-4138,-4127,-4114,-4099,-4083,
+-4067,-4051,-4035,-4021,-4008,-3997,-3986,-3977,-3967,-3956,-3944,-3931,-3916,-3900,-3884,-3868,-3852,-3838,-3826,-3815,-3806,
+-3798,-3790,-3782,-3773,-3763,-3752,-3738,-3724,-3709,-3694,-3680,-3667,-3654,-3643,-3632,-3620,-3608,-3595,-3580,-3564,-3547,
+-3529,-3512,-3497,-3484,-3472,-3463,-3455,-3446,-3436,-3424,-3408,-3389,-3367,-3344,-3321,-3301,-3284,-3271,-3263,-3258,-3255,
+-3250,-3242,-3227,-3204,-3173,-3136,-3093,-3048,-3005,-2967,-2935,-2912,-2896,-2887,-2881,-2876,-2867,-2853,-2831,-2802,-2766,
+-2725,-2682,-2639,-2600,-2566,-2538,-2518,-2503,-2493,-2485,-2478,-2471,-2461,-2448,-2432,-2413,-2393,-2372,-2351,-2332,-2315,
+-2301,-2289,-2280,-2272,-2266,-2258,-2249,-2236,-2219,-2198,-2171,-2140,-2105,-2067,-2028,-1990,-1953,-1920,-1892,-1868,-1849,
+-1835,-1824,-1815,-1806,-1796,-1784,-1768,-1747,-1722,-1692,-1659,-1624,-1589,-1554,-1521,-1491,-1465,-1443,-1424,-1408,-1394,
+-1382,-1371,-1361,-1353,-1346,-1340,-1337,-1335,-1334,-1334,-1333,-1330,-1325,-1317,-1306,-1294,-1279,-1264,-1249,-1235,-1221,
+-1207,-1193,-1176,-1157,-1135,-1110,-1083,-1056,-1030,-1007,-987,-971,-957,-945,-932,-915,-894,-867,-835,-799,-761,
+-723,-689,-659,-634,-613,-594,-575,-553,-526,-493,-455,-413,-371,-331,-295,-265,-242,-222,-204,-183,-156,
+-120,-73,-17,45,111,176,234,283,322,352,376,400,427,463,511,571,642,721,802,881,952,
+1012,1059,1093,1116,1130,1138,1142,1143,1140,1132,1117,1091,1054,1005,945,877,806,735,669,612,564,
+527,500,479,462,446,428,408,384,358,331,305,281,258,239,220,202,182,159,133,104,73,
+41,9,-21,-48,-71,-90,-106,-120,-132,-142,-152,-160,-167,-171,-173,-172,-168,-162,-155,-146,-139,
+-132,-126,-122,-118,-114,-109,-103,-95,-86,-76,-67,-58,-50,-45,-42,-40,-40,-39,-38,-35,-31,
+-25,-17,-9,-1,5,11,17,21,24,27,31,35,40,46,51,57,62,66,70,72,73,
+74,75,76,78,81,85,89,94,98,103,107,110,112,113,114,114,114,114,113,112,112,
+112,112,112,112,113,113,112,111,109,107,103,100,96,92,89,86,84,82,80,79,79,
+79,79,80,82,84,88,93,99,106,113,120,126,131,135,138,140,142,144,145,147,149,
+151,152,153,154,153,151,149,147,145,144,145,147,150,154,159,163,166,168,169,168,166,
+164,163,164,166,171,179,189,203,218,236,255,277,301,326,355,386,420,456,495,536,578,
+622,666,710,754,797,839,881,920,958,992,1022,1048,1068,1083,1092,1097,1098,1098,1097,1096,1097,
+1100,1104,1107,1110,1110,1106,1098,1087,1072,1057,1043,1031,1024,1022,1025,1031,1039,1046,1050,1052,1050,
+1045,1041,1040,1045,1060,1084,1119,1163,1212,1263,1310,1350,1379,1396,1344,1340,1327,1308,1285,1263,1245,
+1232,1227,1230,1239,1254,1271,1290,1308,1326,1341,1355,1368,1380,1390,1399,1406,1409,1409,1404,1395,1381,
+1363,1343,1321,1301,1281,1264,1249,1236,1225,1214,1204,1193,1182,1170,1159,1147,1137,1128,1121,1116,1114,
+1115,1118,1125,1135,1149,1168,1190,1216,1246,1276,1308,1338,1366,1391,1413,1433,1450,1466,1481,1498,1515,
+1532,1549,1565,1577,1586,1592,1594,1595,1596,1602,1616,1638,1673,1718,1773,1836,1902,1968,2028,2081,2124,
+2156,2179,2194,2204,2211,2217,2225,2233,2240,2245,2245,2239,2225,2202,2171,2135,2096,2058,2023,1995,1975,
+1964,1962,1968,1980,1997,2018,2039,2062,2083,2104,2123,2140,2154,2164,2169,2168,2163,2153,2139,2122,2106,
+2091,2081,2076,2078,2087,2102,2122,2145,2169,2191,2211,2226,2235,2240,2239,2234,2226,2217,2208,2199,2191,
+2185,2181,2177,2174,2170,2166,2162,2158,2155,2154,2155,2161,2170,2184,2201,2220,2239,2257,2271,2280,2284,
+2284,2279,2272,2266,2263,2265,2273,2288,2310,2336,2365,2394,2421,2445,2463,2477,2486,2493,2498,2504,2511,
+2521,2533,2546,2559,2570,2579,2583,2581,2574,2561,2544,2522,2499,2473,2448,2424,2403,2384,2369,2357,2350,
+2345,2344,2345,2347,2349,2349,2346,2340,2330,2317,2302,2285,2270,2257,2248,2243,2244,2250,2258,2267,2274,
+2277,2274,2263,2245,2221,2193,2165,2140,2121,2113,2116,2133,2162,2202,2251,2304,2358,2408,2453,2488,2513,
+2527,2531,2524,2509,2487,2459,2426,2389,2347,2300,2248,2190,2127,2059,1986,1911,1836,1763,1695,1634,1583,
+1543,1516,1500,1495,1500,1511,1527,1544,1561,1575,1585,1592,1595,1595,1594,1592,1591,1591,1593,1595,1598,
+1600,1600,1598,1594,1586,1577,1566,1554,1544,1536,1531,1530,1532,1538,1546,1555,1564,1571,1576,1578,1576,
+1569,1559,1545,1528,1509,1488,1466,1443,1420,1397,1375,1352,1331,1310,1291,1272,1254,1237,1220,1203,1185,
+1166,1144,1120,1094,1065,1033,1001,967,932,899,866,834,803,774,745,717,690,663,637,611,586,
+561,537,514,489,463,435,404,369,330,287,241,191,140,89,37,-12,-59,-105,-148,-188,-226,
+-263,-298,-331,-364,-394,-424,-451,-478,-504,-530,-557,-586,-616,-650,-686,-725,-765,-806,-846,-884,-920,
+-952,-982,-1010,-1036,-1063,-1092,-1122,-1155,-1191,-1228,-1265,-1302,-1338,-1371,-1402,-1432,-1460,-1489,-1519,-1551,-1586,
+-1623,-1662,-1701,-1739,-1775,-1806,-1834,-1859,-1881,-1902,-1923,-1946,-1973,-2004,-2040,-2079,-2122,-2167,-2214,-2260,-2306,
+-2350,-2393,-2433,-2471,-2506,-2538,-2565,-2589,-2609,-2625,-2638,-2650,-2661,-2672,-2686,-2702,-2721,-2743,-2768,-2795,-2822,
+-2850,-2878,-2905,-2931,-2957,-2981,-3004,-3026,-3046,-3063,-3078,-3089,-3096,-3101,-3105,-3109,-3114,-3121,-3133,-3150,-3170,
+-3194,-3220,-3245,-3270,-3292,-3311,-3326,-3338,-3349,-3359,-3369,-3381,-3394,-3408,-3424,-3439,-3454,-3468,-3481,-3492,-3502,
+-3513,-3525,-3540,-3558,-3580,-3606,-3636,-3668,-3701,-3734,-3766,-3794,-3817,-3835,-3847,-3854,-3858,-3861,-3864,-3871,-3883,
+-3902,-3928,-3962,-4001,-4045,-4090,-4134,-4174,-4210,-4242,-4269,-4293,-4317,-4342,-4370,-4402,-4438,-4477,-4517,-4557,-4594,
+-4627,-4656,-4682,-4704,-4724,-4744,-4765,-4787,-4809,-4831,-4851,-4868,-4881,-4891,-4897,-4903,-4911,-4923,-4941,-4967,-5000,
+-5037,-5077,-5115,-5147,-5171,-5185,-5188,-5183,-5173,-5161,-5151,-5148,-5154,-5169,-5194,-5226,-5262,-5301,-5340,-5376,-5410,
+-5441,-5470,-5499,-5526,-5554,-5580,-5604,-5624,-5640,-5650,-5656,-5658,-5659,-5662,-5668,-5680,-5696,-5716,-5737,-5757,-5770,
+-5776,-5772,-5759,-5739,-5716,-5693,-5676,-5666,-5665,-5672,-5683,-5693,-5696,-5689,-5668,-5632,-5583,-5528,-5473,-5425,-5392,
+-5379,-5389,-5421,-5473,-5537,-5607,-5676,-5740,-5793,-5834,-5864,-5886,-5902,-5916,-5928,-5941,-5952,-5960,-5963,-5959,-5946,
+-5926,-5899,-5869,-5839,-5813,-5793,-5781,-5776,-5778,-5782,-5786,-5787,-5783,-5772,-5755,-5735,-5715,-5697,-5684,-5679,-5682,
+-5694,-5713,-5737,-5764,-5792,-5819,-5844,-5865,-5884,-5899,-5911,-5921,-5928,-5932,-5934,-5934,-5932,-5930,-5929,-5930,-5934,
+-5943,-5956,-5974,-5995,-6018,-6041,-6063,-6082,-6097,-6108,-6115,-6118,-6118,-6116,-6112,-6108,-6103,-6097,-6091,-6086,-6082,
+-6080,-6081,-6087,-6098,-6116,-6140,-6169,-6203,-6240,-6278,-6315,-6349,-6378,-6404,-6424,-6441,-6454,-6465,-6475,-6483,-6491,
+-6497,-6501,-6502,-6499,-6494,-6485,-6475,-6464,-6454,-6448,-6447,-6451,-6461,-6476,-6494,-6514,-6532,-6546,-6553,-6553,-6545,
+-6530,-6509,-6484,-6458,-6434,-6414,-6399,-6391,-6388,-6389,-6394,-6400,-6404,-6406,-6405,-6400,-6391,-6380,-6367,-6354,-6343,
+-6334,-6327,-6322,-6319,-6317,-6314,-6310,-6304,-6296,-6287,-6275,-6263,-6252,-6241,-6232,-6224,-6218,-6214,-6210,-6207,-6203,
+-6198,-6192,-6184,-6176,-6166,-6157,-6148,-6139,-6132,-6126,-6121,-6118,-6114,-6111,-6108,-6104,-6099,-6092,-6083,-6073,-6062,
+-6049,-6035,-6019,-6004,-5988,-5972,-5956,-5941,-5927,-5914,-5901,-5890,-5879,-5869,-5859,-5849,-5840,-5830,-5821,-5812,-5802,
+-5793,-5784,-5774,-5764,-5754,-5743,-5731,-5719,-5705,-5691,-5676,-5661,-5646,-5631,-5615,-5600,-5584,-5568,-5550,-5532,-5513,
+-5493,-5472,-5451,-5430,-5409,-5390,-5371,-5353,-5336,-5319,-5302,-5284,-5266,-5246,-5225,-5205,-5184,-5165,-5146,-5130,-5115,
+-5101,-5087,-5073,-5058,-5042,-5023,-5003,-4980,-4956,-4932,-4908,-4885,-4863,-4843,-4824,-4806,-4789,-4772,-4754,-4736,-4716,
+-4695,-4673,-4650,-4627,-4602,-4578,-4554,-4530,-4506,-4483,-4461,-4440,-4419,-4400,-4382,-4365,-4349,-4333,-4319,-4305,-4292,
+-4279,-4266,-4254,-4241,-4228,-4215,-4202,-4188,-4173,-4158,-4143,-4127,-4112,-4097,-4082,-4069,-4056,-4045,-4036,-4027,-4018,
+-4010,-4001,-3991,-3980,-3967,-3954,-3940,-3925,-3910,-3896,-3883,-3871,-3860,-3850,-3840,-3830,-3820,-3808,-3795,-3781,-3765,
+-3749,-3733,-3716,-3700,-3684,-3668,-3652,-3635,-3617,-3598,-3578,-3558,-3537,-3517,-3499,-3484,-3472,-3462,-3455,-3449,-3442,
+-3432,-3419,-3401,-3378,-3352,-3323,-3295,-3268,-3245,-3227,-3215,-3206,-3199,-3190,-3177,-3156,-3126,-3085,-3036,-2981,-2922,
+-2864,-2812,-2769,-2736,-2715,-2704,-2700,-2700,-2700,-2695,-2685,-2666,-2640,-2606,-2569,-2530,-2493,-2460,-2433,-2413,-2399,
+-2390,-2384,-2380,-2375,-2368,-2359,-2346,-2330,-2312,-2292,-2272,-2253,-2235,-2218,-2203,-2191,-2180,-2171,-2164,-2157,-2151,
+-2144,-2136,-2125,-2111,-2093,-2070,-2041,-2007,-1970,-1929,-1888,-1847,-1809,-1775,-1746,-1723,-1704,-1688,-1675,-1661,-1645,
+-1627,-1605,-1579,-1551,-1522,-1495,-1470,-1449,-1433,-1423,-1418,-1417,-1418,-1421,-1424,-1426,-1426,-1426,-1424,-1422,-1419,
+-1416,-1412,-1406,-1399,-1389,-1376,-1360,-1342,-1322,-1301,-1280,-1259,-1239,-1220,-1201,-1182,-1163,-1143,-1123,-1104,-1086,
+-1070,-1057,-1046,-1038,-1030,-1021,-1009,-992,-969,-940,-906,-869,-832,-795,-763,-735,-712,-691,-672,-650,-624,
+-590,-549,-501,-448,-394,-341,-293,-252,-217,-189,-162,-135,-103,-64,-16,39,100,163,223,275,317,
+348,369,382,393,408,430,464,512,572,643,718,794,864,926,976,1014,1040,1058,1069,1077,1081,
+1083,1082,1074,1059,1034,998,951,894,830,764,697,635,578,528,486,450,418,389,360,332,304,
+277,251,228,209,193,180,169,159,147,132,114,92,66,38,10,-17,-43,-65,-84,-100,-113,
+-124,-134,-142,-150,-156,-161,-163,-164,-161,-157,-151,-144,-138,-132,-128,-126,-124,-123,-122,-119,-115,
+-110,-103,-95,-86,-79,-72,-67,-64,-62,-61,-60,-58,-56,-52,-46,-40,-33,-25,-18,-12,-7,
+-2,1,5,8,12,16,20,24,28,32,35,37,38,39,40,41,43,45,48,52,56,
+61,66,70,74,76,77,77,77,76,75,74,74,75,76,79,81,84,86,88,88,86,
+83,78,73,67,62,57,53,50,49,48,49,49,51,52,54,56,59,63,68,74,81,
+88,95,100,105,108,109,108,107,105,104,103,103,105,107,110,113,117,119,120,121,121,
+120,120,120,121,122,123,123,124,123,121,119,116,113,111,112,115,122,132,147,164,185,
+209,236,264,295,327,362,399,439,480,524,568,613,658,702,744,786,826,866,904,942,978,
+1013,1044,1072,1093,1109,1117,1119,1114,1106,1094,1083,1074,1068,1068,1071,1079,1088,1096,1103,1106,1104,
+1097,1087,1075,1064,1054,1048,1047,1050,1057,1065,1073,1080,1086,1089,1091,1095,1102,1114,1133,1159,1190,
+1225,1261,1294,1320,1338,1344,1280,1272,1257,1237,1215,1194,1177,1167,1164,1170,1184,1205,1231,1260,1289,
+1317,1342,1363,1380,1394,1403,1409,1412,1412,1409,1403,1396,1386,1375,1363,1350,1338,1325,1313,1301,1290,
+1280,1269,1258,1246,1234,1221,1208,1194,1180,1167,1154,1144,1136,1132,1133,1139,1152,1171,1196,1226,1258,
+1291,1322,1350,1372,1388,1399,1405,1410,1414,1421,1433,1451,1475,1502,1532,1561,1587,1607,1620,1626,1627,
+1627,1628,1635,1651,1677,1714,1760,1812,1866,1918,1963,1998,2022,2036,2041,2040,2038,2037,2039,2048,2061,
+2078,2095,2112,2124,2130,2129,2123,2113,2102,2091,2084,2082,2084,2092,2103,2116,2128,2139,2148,2154,2159,
+2162,2166,2171,2177,2184,2191,2196,2197,2194,2186,2174,2160,2145,2133,2127,2128,2140,2161,2191,2228,2268,
+2307,2343,2371,2390,2399,2399,2391,2377,2360,2343,2328,2316,2308,2304,2303,2304,2305,2305,2305,2302,2299,
+2295,2291,2290,2290,2293,2298,2303,2308,2310,2307,2300,2286,2267,2245,2221,2198,2180,2168,2166,2173,2190,
+2216,2247,2281,2315,2346,2372,2391,2404,2413,2418,2421,2426,2435,2447,2463,2482,2503,2524,2541,2553,2557,
+2553,2539,2517,2487,2452,2413,2373,2335,2301,2272,2250,2235,2226,2224,2227,2232,2239,2245,2248,2248,2244,
+2236,2224,2210,2196,2182,2170,2162,2157,2155,2155,2156,2155,2151,2142,2128,2109,2086,2060,2035,2013,1996,
+1988,1989,2002,2024,2056,2096,2141,2188,2236,2282,2324,2361,2390,2412,2426,2431,2427,2414,2391,2357,2314,
+2262,2200,2131,2055,1975,1893,1812,1735,1663,1600,1547,1505,1475,1457,1450,1452,1460,1472,1486,1498,1508,
+1514,1515,1513,1507,1499,1492,1487,1485,1487,1493,1504,1516,1530,1543,1555,1562,1566,1566,1562,1556,1549,
+1542,1536,1532,1531,1532,1535,1540,1544,1548,1551,1551,1549,1545,1538,1529,1518,1505,1489,1473,1454,1434,
+1412,1390,1366,1342,1317,1294,1270,1248,1227,1206,1186,1166,1145,1124,1101,1078,1052,1026,998,968,938,
+907,876,844,811,779,747,715,685,656,628,604,581,560,542,524,506,487,466,442,415,384,
+350,313,273,232,190,148,106,64,22,-20,-64,-110,-157,-206,-256,-305,-354,-400,-444,-483,-519,
+-552,-582,-611,-641,-672,-707,-744,-783,-825,-868,-910,-951,-988,-1022,-1052,-1080,-1107,-1133,-1161,-1191,-1224,
+-1260,-1298,-1338,-1378,-1417,-1453,-1488,-1521,-1552,-1582,-1613,-1646,-1681,-1718,-1756,-1796,-1835,-1873,-1908,-1941,-1971,
+-1999,-2027,-2054,-2083,-2114,-2148,-2185,-2224,-2264,-2305,-2344,-2382,-2417,-2450,-2481,-2510,-2538,-2566,-2592,-2619,-2645,
+-2670,-2695,-2718,-2740,-2762,-2783,-2803,-2824,-2846,-2870,-2894,-2920,-2947,-2974,-3001,-3028,-3053,-3076,-3097,-3115,-3129,
+-3140,-3148,-3153,-3155,-3155,-3154,-3154,-3155,-3160,-3168,-3182,-3199,-3221,-3246,-3272,-3298,-3322,-3345,-3363,-3379,-3392,
+-3402,-3411,-3421,-3432,-3445,-3459,-3476,-3493,-3511,-3528,-3544,-3558,-3570,-3580,-3588,-3597,-3607,-3619,-3635,-3654,-3677,
+-3704,-3733,-3763,-3793,-3819,-3842,-3860,-3874,-3884,-3891,-3897,-3905,-3917,-3933,-3955,-3982,-4014,-4048,-4083,-4117,-4148,
+-4176,-4201,-4224,-4246,-4271,-4300,-4334,-4374,-4421,-4472,-4527,-4582,-4636,-4688,-4736,-4780,-4820,-4856,-4890,-4922,-4951,
+-4977,-4999,-5016,-5027,-5032,-5032,-5029,-5025,-5023,-5024,-5032,-5046,-5066,-5090,-5115,-5139,-5158,-5171,-5176,-5174,-5168,
+-5161,-5156,-5156,-5165,-5182,-5208,-5242,-5280,-5320,-5359,-5395,-5427,-5455,-5480,-5504,-5527,-5551,-5575,-5599,-5621,-5641,
+-5655,-5665,-5670,-5672,-5673,-5675,-5681,-5692,-5707,-5727,-5747,-5765,-5778,-5781,-5775,-5760,-5738,-5713,-5689,-5672,-5663,
+-5665,-5675,-5690,-5706,-5716,-5715,-5699,-5667,-5622,-5567,-5509,-5457,-5417,-5396,-5398,-5422,-5466,-5526,-5594,-5663,-5728,
+-5782,-5825,-5855,-5873,-5883,-5886,-5886,-5884,-5881,-5876,-5870,-5860,-5847,-5832,-5814,-5797,-5782,-5772,-5767,-5768,-5773,
+-5780,-5785,-5786,-5780,-5766,-5742,-5712,-5676,-5640,-5608,-5582,-5567,-5563,-5571,-5590,-5617,-5651,-5688,-5726,-5764,-5800,
+-5833,-5863,-5890,-5914,-5933,-5949,-5960,-5968,-5971,-5972,-5970,-5968,-5968,-5970,-5975,-5985,-5999,-6017,-6037,-6057,-6077,
+-6095,-6110,-6122,-6131,-6137,-6140,-6142,-6141,-6139,-6136,-6131,-6125,-6119,-6113,-6108,-6107,-6109,-6117,-6131,-6153,-6180,
+-6213,-6249,-6288,-6326,-6362,-6395,-6424,-6448,-6468,-6484,-6496,-6506,-6513,-6517,-6520,-6519,-6517,-6512,-6506,-6499,-6492,
+-6488,-6488,-6492,-6502,-6516,-6534,-6553,-6572,-6587,-6595,-6596,-6588,-6571,-6546,-6516,-6485,-6455,-6429,-6410,-6400,-6398,
+-6403,-6414,-6428,-6442,-6453,-6459,-6459,-6453,-6442,-6426,-6409,-6391,-6375,-6362,-6353,-6347,-6343,-6341,-6339,-6336,-6331,
+-6324,-6315,-6304,-6293,-6283,-6274,-6266,-6261,-6257,-6253,-6251,-6247,-6243,-6236,-6228,-6219,-6208,-6197,-6187,-6178,-6170,
+-6164,-6159,-6156,-6153,-6150,-6147,-6142,-6136,-6128,-6119,-6108,-6096,-6083,-6069,-6055,-6040,-6025,-6009,-5994,-5979,-5964,
+-5950,-5938,-5926,-5916,-5908,-5900,-5894,-5887,-5881,-5874,-5866,-5857,-5847,-5836,-5825,-5812,-5800,-5787,-5775,-5763,-5751,
+-5739,-5728,-5716,-5703,-5690,-5676,-5660,-5643,-5624,-5604,-5583,-5561,-5538,-5514,-5491,-5469,-5448,-5428,-5409,-5392,-5375,
+-5358,-5342,-5324,-5306,-5287,-5267,-5246,-5226,-5206,-5188,-5172,-5157,-5144,-5132,-5121,-5109,-5096,-5081,-5064,-5044,-5022,
+-4999,-4975,-4951,-4928,-4906,-4887,-4869,-4852,-4837,-4823,-4808,-4793,-4776,-4758,-4738,-4716,-4692,-4667,-4640,-4613,-4584,
+-4555,-4527,-4500,-4474,-4450,-4429,-4411,-4396,-4383,-4374,-4366,-4359,-4353,-4345,-4337,-4326,-4314,-4299,-4281,-4262,-4242,
+-4221,-4199,-4178,-4157,-4137,-4118,-4101,-4086,-4072,-4059,-4048,-4039,-4030,-4022,-4014,-4005,-3995,-3985,-3972,-3959,-3944,
+-3929,-3913,-3897,-3881,-3866,-3851,-3837,-3822,-3808,-3792,-3775,-3756,-3735,-3714,-3691,-3668,-3646,-3623,-3602,-3581,-3561,
+-3542,-3522,-3504,-3485,-3468,-3452,-3437,-3425,-3415,-3407,-3401,-3395,-3387,-3377,-3363,-3344,-3320,-3293,-3263,-3234,-3206,
+-3182,-3163,-3150,-3140,-3133,-3125,-3113,-3093,-3064,-3025,-2975,-2917,-2854,-2791,-2731,-2678,-2636,-2606,-2587,-2578,-2576,
+-2577,-2579,-2576,-2568,-2553,-2531,-2504,-2474,-2443,-2414,-2388,-2367,-2351,-2339,-2331,-2325,-2320,-2315,-2309,-2302,-2292,
+-2282,-2270,-2257,-2242,-2227,-2211,-2195,-2179,-2164,-2150,-2139,-2130,-2124,-2120,-2118,-2116,-2112,-2105,-2093,-2073,-2046,
+-2011,-1970,-1925,-1878,-1832,-1789,-1752,-1722,-1699,-1682,-1668,-1657,-1645,-1630,-1613,-1591,-1567,-1541,-1516,-1493,-1475,
+-1462,-1455,-1454,-1457,-1463,-1469,-1475,-1479,-1479,-1477,-1473,-1467,-1459,-1451,-1443,-1434,-1424,-1413,-1399,-1384,-1366,
+-1345,-1323,-1299,-1274,-1248,-1223,-1199,-1176,-1154,-1135,-1119,-1106,-1096,-1091,-1089,-1089,-1091,-1091,-1089,-1081,-1067,
+-1045,-1015,-980,-941,-901,-863,-827,-796,-770,-746,-722,-696,-665,-627,-581,-527,-468,-406,-345,-287,-235,
+-189,-148,-111,-75,-37,4,51,102,156,209,258,300,332,355,368,376,382,391,408,436,476,
+529,590,657,724,788,845,892,929,956,975,989,999,1007,1013,1016,1014,1005,987,959,920,871,
+815,753,690,627,568,514,464,418,376,337,299,262,227,195,167,144,126,114,107,104,102,
+99,94,85,71,53,31,7,-16,-39,-59,-77,-90,-101,-110,-118,-124,-131,-137,-142,-146,-148,
+-148,-146,-142,-137,-132,-127,-123,-121,-120,-121,-122,-124,-124,-124,-122,-118,-112,-106,-100,-95,-90,
+-86,-83,-81,-80,-78,-76,-73,-69,-64,-59,-53,-48,-43,-38,-35,-31,-29,-26,-23,-20,-17,
+-14,-11,-8,-5,-2,0,1,2,4,6,9,12,16,20,25,29,33,36,38,39,38,
+37,36,35,34,34,35,37,39,41,42,43,43,41,38,35,31,26,23,20,18,18,
+19,20,22,25,27,29,31,34,37,40,44,49,54,59,63,66,67,67,64,60,56,
+52,48,46,46,48,52,57,64,70,75,80,84,86,87,87,86,85,84,82,81,79,
+76,74,73,72,74,78,85,96,111,130,153,178,207,237,270,304,340,379,420,463,508,
+554,601,648,693,736,776,813,847,879,911,942,974,1006,1038,1068,1095,1116,1131,1137,1134,1123,
+1106,1085,1064,1045,1033,1029,1034,1048,1068,1092,1117,1139,1157,1168,1173,1172,1166,1159,1151,1146,1144,
+1145,1149,1155,1161,1166,1171,1174,1176,1178,1182,1189,1200,1214,1230,1247,1263,1275,1281,1280,1206,1201,
+1193,1183,1171,1161,1154,1152,1158,1171,1191,1219,1253,1289,1327,1364,1397,1426,1448,1466,1477,1483,1484,
+1483,1479,1473,1466,1459,1452,1444,1436,1428,1419,1410,1400,1389,1377,1365,1352,1338,1324,1309,1293,1277,
+1261,1244,1229,1216,1206,1201,1202,1211,1226,1248,1276,1308,1340,1371,1397,1416,1427,1430,1428,1421,1415,
+1412,1415,1427,1448,1477,1513,1551,1589,1621,1646,1662,1670,1671,1670,1669,1674,1688,1712,1745,1787,1833,
+1878,1920,1952,1974,1985,1985,1978,1968,1959,1954,1957,1968,1986,2010,2036,2061,2083,2099,2109,2114,2116,
+2117,2120,2127,2139,2155,2174,2194,2211,2225,2232,2233,2229,2220,2210,2201,2194,2191,2192,2197,2203,2209,
+2212,2211,2207,2200,2192,2187,2187,2196,2215,2245,2285,2333,2384,2434,2480,2517,2542,2556,2557,2548,2531,
+2510,2488,2469,2452,2441,2434,2431,2431,2431,2431,2429,2426,2421,2416,2412,2408,2406,2405,2404,2401,2395,
+2383,2365,2340,2307,2269,2228,2187,2150,2120,2102,2096,2103,2123,2152,2189,2228,2266,2299,2326,2344,2356,
+2361,2363,2364,2368,2376,2391,2412,2438,2467,2495,2518,2535,2541,2536,2517,2487,2447,2399,2348,2297,2249,
+2208,2175,2152,2138,2133,2135,2142,2152,2161,2168,2171,2170,2164,2155,2142,2129,2115,2104,2094,2087,2083,
+2080,2077,2072,2065,2054,2039,2020,1998,1974,1951,1931,1915,1906,1904,1910,1925,1947,1974,2007,2043,2081,
+2120,2159,2197,2232,2265,2293,2316,2331,2337,2332,2315,2285,2242,2186,2119,2042,1959,1872,1785,1701,1625,
+1558,1502,1459,1429,1412,1405,1407,1416,1428,1441,1452,1459,1461,1457,1449,1437,1424,1411,1400,1395,1394,
+1400,1412,1428,1447,1467,1486,1503,1516,1524,1528,1529,1527,1524,1521,1519,1519,1521,1524,1527,1531,1533,
+1535,1534,1531,1527,1520,1512,1503,1492,1480,1467,1452,1435,1416,1396,1374,1351,1327,1302,1278,1254,1230,
+1207,1184,1162,1139,1116,1092,1067,1041,1014,987,960,932,903,873,843,811,779,747,714,682,651,
+622,595,572,552,534,519,504,490,474,455,434,409,380,349,316,282,247,212,178,144,110,
+74,35,-6,-53,-103,-158,-216,-276,-336,-393,-448,-497,-542,-582,-619,-652,-684,-716,-749,-784,-821,
+-859,-899,-938,-976,-1012,-1045,-1076,-1105,-1133,-1161,-1191,-1222,-1255,-1292,-1330,-1370,-1410,-1449,-1488,-1524,-1560,
+-1593,-1627,-1660,-1694,-1730,-1767,-1806,-1845,-1884,-1923,-1961,-1997,-2033,-2068,-2103,-2138,-2175,-2214,-2253,-2294,-2333,
+-2372,-2407,-2440,-2468,-2493,-2514,-2533,-2552,-2570,-2590,-2611,-2635,-2660,-2688,-2716,-2744,-2772,-2799,-2824,-2849,-2874,
+-2899,-2925,-2952,-2981,-3011,-3042,-3073,-3103,-3131,-3155,-3176,-3192,-3202,-3208,-3209,-3207,-3203,-3198,-3194,-3192,-3193,
+-3199,-3210,-3226,-3246,-3269,-3294,-3320,-3345,-3368,-3388,-3404,-3417,-3427,-3436,-3444,-3453,-3464,-3478,-3495,-3514,-3535,
+-3557,-3578,-3597,-3612,-3624,-3632,-3638,-3641,-3644,-3649,-3657,-3670,-3688,-3710,-3738,-3768,-3799,-3830,-3858,-3881,-3900,
+-3915,-3926,-3935,-3945,-3956,-3970,-3989,-4012,-4038,-4067,-4096,-4125,-4151,-4175,-4198,-4219,-4241,-4267,-4297,-4335,-4379,
+-4431,-4488,-4551,-4616,-4682,-4747,-4808,-4866,-4919,-4967,-5011,-5048,-5080,-5106,-5125,-5137,-5141,-5140,-5133,-5123,-5112,
+-5103,-5098,-5098,-5104,-5114,-5127,-5141,-5153,-5162,-5166,-5166,-5162,-5156,-5152,-5151,-5158,-5172,-5194,-5224,-5260,-5298,
+-5337,-5373,-5406,-5436,-5462,-5486,-5509,-5533,-5558,-5583,-5608,-5632,-5652,-5667,-5677,-5682,-5684,-5684,-5685,-5690,-5699,
+-5713,-5731,-5749,-5765,-5776,-5779,-5773,-5758,-5737,-5713,-5690,-5673,-5665,-5665,-5674,-5688,-5702,-5710,-5708,-5691,-5659,
+-5613,-5556,-5496,-5438,-5392,-5363,-5355,-5370,-5406,-5459,-5523,-5592,-5660,-5720,-5770,-5808,-5832,-5846,-5849,-5845,-5836,
+-5823,-5807,-5788,-5768,-5747,-5726,-5707,-5692,-5681,-5676,-5678,-5683,-5692,-5700,-5705,-5702,-5691,-5669,-5637,-5598,-5555,
+-5512,-5474,-5445,-5428,-5425,-5437,-5461,-5497,-5540,-5588,-5638,-5688,-5736,-5780,-5820,-5857,-5889,-5917,-5941,-5959,-5973,
+-5983,-5988,-5989,-5989,-5987,-5987,-5988,-5993,-6001,-6012,-6026,-6042,-6059,-6075,-6090,-6104,-6116,-6127,-6136,-6143,-6149,
+-6153,-6155,-6156,-6154,-6150,-6145,-6139,-6134,-6131,-6131,-6138,-6150,-6169,-6194,-6224,-6258,-6294,-6330,-6364,-6396,-6424,
+-6447,-6467,-6483,-6497,-6508,-6517,-6525,-6531,-6536,-6539,-6542,-6543,-6545,-6548,-6554,-6561,-6572,-6585,-6599,-6614,-6626,
+-6634,-6636,-6630,-6616,-6595,-6569,-6538,-6507,-6479,-6456,-6441,-6435,-6436,-6445,-6459,-6474,-6489,-6499,-6504,-6502,-6494,
+-6479,-6460,-6440,-6420,-6402,-6387,-6377,-6370,-6367,-6365,-6364,-6362,-6358,-6352,-6344,-6335,-6324,-6315,-6306,-6299,-6294,
+-6289,-6286,-6283,-6279,-6273,-6266,-6258,-6248,-6238,-6228,-6219,-6211,-6204,-6199,-6195,-6192,-6188,-6184,-6178,-6170,-6161,
+-6150,-6139,-6126,-6114,-6101,-6088,-6076,-6064,-6051,-6038,-6025,-6011,-5997,-5983,-5970,-5957,-5947,-5937,-5930,-5923,-5917,
+-5911,-5905,-5898,-5890,-5880,-5869,-5856,-5843,-5830,-5817,-5805,-5794,-5783,-5773,-5762,-5751,-5739,-5725,-5709,-5691,-5671,
+-5650,-5627,-5603,-5579,-5555,-5531,-5509,-5489,-5469,-5451,-5434,-5417,-5400,-5384,-5366,-5348,-5329,-5309,-5289,-5270,-5251,
+-5233,-5216,-5201,-5188,-5176,-5164,-5153,-5141,-5128,-5114,-5098,-5080,-5061,-5041,-5020,-4999,-4979,-4960,-4941,-4924,-4907,
+-4890,-4873,-4856,-4837,-4818,-4796,-4774,-4750,-4724,-4697,-4669,-4640,-4611,-4581,-4552,-4524,-4498,-4475,-4455,-4439,-4428,
+-4420,-4415,-4412,-4410,-4408,-4405,-4400,-4392,-4380,-4365,-4346,-4325,-4302,-4276,-4250,-4223,-4197,-4170,-4145,-4120,-4098,
+-4077,-4059,-4043,-4029,-4018,-4009,-4001,-3993,-3984,-3974,-3962,-3947,-3929,-3908,-3886,-3862,-3838,-3815,-3791,-3769,-3747,
+-3725,-3703,-3679,-3654,-3627,-3599,-3570,-3540,-3511,-3484,-3459,-3438,-3420,-3404,-3392,-3381,-3372,-3363,-3355,-3347,-3339,
+-3331,-3323,-3315,-3306,-3296,-3284,-3269,-3250,-3229,-3206,-3181,-3157,-3134,-3115,-3100,-3090,-3084,-3081,-3079,-3074,-3063,
+-3045,-3018,-2981,-2936,-2883,-2827,-2771,-2718,-2672,-2634,-2606,-2586,-2575,-2569,-2565,-2561,-2556,-2546,-2531,-2513,-2490,
+-2465,-2440,-2415,-2391,-2371,-2353,-2338,-2326,-2316,-2308,-2301,-2294,-2288,-2282,-2274,-2265,-2254,-2240,-2224,-2206,-2186,
+-2166,-2147,-2130,-2117,-2109,-2106,-2107,-2111,-2116,-2118,-2116,-2107,-2090,-2063,-2028,-1986,-1940,-1893,-1848,-1808,-1774,
+-1747,-1726,-1711,-1699,-1688,-1676,-1662,-1644,-1624,-1602,-1580,-1560,-1542,-1530,-1522,-1518,-1518,-1519,-1521,-1521,-1519,
+-1515,-1507,-1497,-1485,-1473,-1462,-1451,-1442,-1433,-1424,-1414,-1402,-1388,-1371,-1351,-1328,-1302,-1274,-1246,-1217,-1190,
+-1166,-1144,-1128,-1116,-1110,-1110,-1114,-1121,-1129,-1136,-1139,-1135,-1124,-1105,-1076,-1041,-1001,-957,-914,-873,-835,
+-801,-770,-739,-708,-673,-634,-588,-536,-480,-420,-361,-302,-247,-197,-150,-106,-65,-23,20,65,112,
+158,203,243,276,302,321,332,340,348,359,376,403,439,484,536,593,650,704,753,794,827,
+853,873,888,900,909,915,917,913,901,880,850,809,761,706,647,588,530,476,426,381,340,
+301,264,228,192,157,124,95,71,52,40,34,33,34,36,37,35,28,17,3,-13,-30,
+-47,-62,-73,-82,-88,-92,-96,-100,-104,-110,-117,-123,-129,-134,-136,-136,-134,-130,-125,-120,-116,
+-114,-113,-115,-118,-121,-125,-128,-129,-129,-128,-125,-122,-118,-115,-112,-110,-108,-107,-106,-104,-102,
+-100,-97,-93,-89,-86,-83,-80,-79,-77,-76,-75,-73,-71,-68,-65,-62,-58,-55,-52,-49,-47,
+-45,-43,-41,-38,-35,-32,-28,-23,-19,-15,-12,-9,-7,-6,-6,-7,-7,-7,-7,-7,-6,
+-5,-5,-4,-4,-5,-6,-7,-9,-10,-11,-11,-10,-9,-7,-5,-2,0,1,2,3,4,
+6,7,9,11,13,15,15,15,13,10,6,1,-3,-7,-9,-10,-8,-4,1,9,17,
+25,32,38,43,47,49,49,49,48,47,46,44,43,42,42,44,49,56,67,82,101,
+124,151,180,212,245,280,316,354,393,435,478,524,571,619,666,711,752,789,821,847,871,
+891,911,933,957,984,1014,1044,1074,1100,1118,1128,1128,1117,1098,1073,1046,1021,1004,996,1001,1018,
+1047,1083,1125,1167,1205,1236,1259,1272,1278,1276,1270,1262,1255,1250,1247,1246,1246,1247,1246,1243,1238,
+1231,1223,1216,1209,1205,1203,1204,1206,1208,1208,1206,1177,1180,1183,1185,1187,1190,1194,1202,1214,1232,
+1255,1285,1319,1358,1398,1438,1476,1511,1542,1566,1585,1599,1607,1611,1611,1608,1603,1596,1588,1577,1566,
+1553,1539,1524,1509,1494,1479,1466,1453,1442,1431,1421,1410,1399,1387,1375,1362,1351,1342,1337,1337,1344,
+1357,1377,1400,1427,1452,1475,1493,1503,1506,1502,1493,1483,1475,1472,1477,1492,1516,1547,1584,1621,1655,
+1682,1700,1709,1710,1705,1698,1694,1697,1709,1732,1764,1804,1847,1889,1925,1953,1971,1978,1978,1974,1970,
+1970,1976,1992,2015,2044,2076,2106,2131,2148,2154,2151,2141,2127,2112,2102,2098,2103,2117,2136,2160,2184,
+2204,2219,2225,2225,2217,2206,2194,2183,2177,2175,2178,2186,2195,2204,2212,2218,2221,2224,2228,2236,2250,
+2273,2304,2344,2391,2441,2491,2537,2575,2602,2618,2623,2618,2605,2589,2570,2553,2540,2530,2524,2521,2520,
+2519,2517,2514,2509,2503,2496,2489,2483,2478,2473,2468,2459,2446,2427,2400,2365,2322,2274,2225,2176,2134,
+2101,2081,2075,2084,2106,2139,2178,2219,2258,2292,2317,2333,2341,2343,2341,2339,2340,2346,2360,2381,2407,
+2436,2465,2489,2504,2509,2501,2479,2445,2402,2352,2299,2248,2203,2165,2136,2118,2109,2107,2111,2118,2126,
+2131,2134,2132,2125,2115,2103,2089,2076,2065,2055,2049,2044,2041,2039,2036,2031,2024,2013,2000,1984,1967,
+1951,1935,1923,1915,1911,1911,1916,1926,1938,1954,1972,1992,2014,2038,2063,2090,2118,2146,2173,2196,2214,
+2226,2228,2219,2199,2166,2121,2066,2001,1929,1854,1777,1703,1632,1569,1515,1470,1436,1412,1396,1388,1385,
+1385,1387,1387,1385,1380,1371,1360,1347,1335,1325,1318,1318,1323,1335,1352,1373,1397,1420,1442,1461,1475,
+1485,1490,1492,1491,1490,1489,1490,1492,1496,1500,1505,1510,1513,1514,1512,1508,1501,1493,1483,1471,1459,
+1445,1431,1415,1399,1380,1360,1339,1317,1295,1272,1249,1227,1205,1183,1161,1139,1116,1092,1067,1041,1014,
+986,958,928,899,869,838,807,775,743,711,679,648,619,592,569,549,532,517,505,493,480,
+465,448,427,402,374,344,311,278,245,212,181,150,118,86,51,12,-29,-76,-127,-182,-239,
+-297,-354,-409,-461,-509,-552,-592,-629,-663,-697,-730,-764,-799,-836,-873,-910,-948,-984,-1020,-1054,-1088,
+-1121,-1154,-1187,-1222,-1258,-1295,-1333,-1372,-1411,-1450,-1489,-1528,-1566,-1603,-1641,-1678,-1716,-1753,-1791,-1830,-1868,
+-1905,-1943,-1981,-2019,-2058,-2099,-2141,-2185,-2231,-2279,-2326,-2373,-2416,-2456,-2491,-2520,-2543,-2561,-2575,-2586,-2596,
+-2607,-2620,-2637,-2656,-2679,-2704,-2732,-2759,-2787,-2813,-2839,-2863,-2887,-2912,-2937,-2964,-2993,-3024,-3055,-3087,-3118,
+-3147,-3172,-3192,-3207,-3217,-3221,-3221,-3218,-3214,-3209,-3207,-3208,-3213,-3223,-3237,-3256,-3279,-3303,-3328,-3353,-3375,
+-3395,-3412,-3426,-3439,-3450,-3461,-3473,-3488,-3506,-3527,-3551,-3577,-3603,-3627,-3649,-3665,-3676,-3682,-3681,-3677,-3671,
+-3666,-3663,-3666,-3676,-3693,-3718,-3749,-3784,-3821,-3857,-3889,-3916,-3938,-3953,-3963,-3971,-3978,-3986,-3998,-4015,-4036,
+-4061,-4090,-4120,-4149,-4177,-4202,-4226,-4249,-4272,-4298,-4328,-4365,-4410,-4463,-4523,-4589,-4659,-4730,-4800,-4868,-4930,
+-4986,-5034,-5075,-5106,-5130,-5144,-5151,-5150,-5144,-5132,-5118,-5104,-5091,-5083,-5079,-5080,-5087,-5098,-5112,-5126,-5139,
+-5148,-5153,-5155,-5153,-5152,-5151,-5154,-5163,-5179,-5201,-5229,-5261,-5295,-5330,-5363,-5395,-5425,-5452,-5479,-5506,-5534,
+-5562,-5589,-5615,-5638,-5656,-5669,-5677,-5679,-5678,-5676,-5676,-5679,-5687,-5700,-5716,-5734,-5751,-5762,-5767,-5764,-5753,
+-5736,-5715,-5695,-5679,-5670,-5668,-5672,-5681,-5689,-5693,-5688,-5670,-5638,-5592,-5537,-5476,-5417,-5366,-5328,-5309,-5310,
+-5332,-5371,-5423,-5484,-5547,-5608,-5662,-5706,-5739,-5759,-5769,-5768,-5758,-5741,-5719,-5692,-5663,-5635,-5608,-5586,-5570,
+-5562,-5562,-5568,-5580,-5594,-5606,-5613,-5610,-5597,-5572,-5537,-5493,-5447,-5401,-5362,-5334,-5320,-5323,-5342,-5376,-5421,
+-5475,-5533,-5591,-5647,-5698,-5743,-5782,-5815,-5843,-5866,-5885,-5902,-5915,-5926,-5936,-5944,-5952,-5959,-5967,-5976,-5987,
+-6000,-6014,-6029,-6045,-6060,-6075,-6088,-6101,-6111,-6121,-6130,-6138,-6145,-6152,-6158,-6162,-6164,-6164,-6162,-6158,-6154,
+-6150,-6148,-6149,-6155,-6166,-6183,-6205,-6230,-6259,-6289,-6318,-6347,-6373,-6397,-6418,-6438,-6456,-6474,-6492,-6510,-6527,
+-6544,-6559,-6573,-6586,-6596,-6604,-6611,-6618,-6623,-6629,-6634,-6638,-6640,-6640,-6636,-6627,-6614,-6596,-6575,-6553,-6530,
+-6510,-6494,-6483,-6479,-6480,-6486,-6496,-6506,-6515,-6520,-6521,-6516,-6505,-6490,-6472,-6453,-6435,-6419,-6407,-6398,-6393,
+-6391,-6390,-6389,-6387,-6384,-6378,-6370,-6361,-6350,-6340,-6331,-6323,-6316,-6311,-6306,-6302,-6297,-6291,-6285,-6277,-6268,
+-6260,-6251,-6243,-6236,-6231,-6226,-6221,-6217,-6211,-6205,-6197,-6188,-6177,-6165,-6153,-6142,-6130,-6120,-6111,-6101,-6093,
+-6083,-6073,-6062,-6049,-6036,-6021,-6007,-5992,-5979,-5967,-5957,-5948,-5940,-5933,-5926,-5919,-5911,-5901,-5891,-5880,-5869,
+-5857,-5846,-5835,-5824,-5813,-5802,-5791,-5778,-5763,-5746,-5728,-5707,-5685,-5662,-5638,-5614,-5592,-5570,-5550,-5531,-5513,
+-5496,-5480,-5464,-5448,-5431,-5413,-5395,-5376,-5357,-5337,-5318,-5299,-5280,-5263,-5246,-5231,-5216,-5202,-5189,-5175,-5162,
+-5148,-5134,-5119,-5104,-5089,-5073,-5058,-5042,-5025,-5009,-4991,-4973,-4953,-4933,-4911,-4887,-4863,-4838,-4811,-4785,-4758,
+-4731,-4703,-4675,-4648,-4621,-4594,-4568,-4544,-4522,-4502,-4486,-4473,-4462,-4455,-4450,-4446,-4443,-4439,-4434,-4427,-4418,
+-4406,-4392,-4377,-4359,-4339,-4317,-4294,-4269,-4243,-4215,-4187,-4158,-4129,-4102,-4076,-4054,-4035,-4020,-4008,-3997,-3987,
+-3977,-3964,-3948,-3927,-3902,-3873,-3840,-3805,-3769,-3735,-3702,-3671,-3642,-3615,-3589,-3563,-3536,-3507,-3477,-3445,-3413,
+-3383,-3355,-3331,-3312,-3299,-3290,-3285,-3284,-3284,-3283,-3282,-3278,-3272,-3264,-3253,-3241,-3228,-3215,-3201,-3187,-3172,
+-3156,-3140,-3123,-3106,-3090,-3076,-3065,-3057,-3052,-3050,-3049,-3049,-3046,-3040,-3027,-3008,-2982,-2949,-2911,-2869,-2826,
+-2785,-2747,-2713,-2685,-2663,-2645,-2630,-2617,-2604,-2590,-2573,-2554,-2532,-2508,-2482,-2456,-2429,-2404,-2381,-2359,-2340,
+-2324,-2310,-2299,-2289,-2281,-2273,-2266,-2256,-2245,-2231,-2214,-2195,-2174,-2152,-2132,-2115,-2103,-2098,-2098,-2105,-2117,
+-2131,-2145,-2155,-2159,-2154,-2138,-2113,-2078,-2035,-1989,-1940,-1894,-1851,-1815,-1785,-1762,-1744,-1730,-1718,-1707,-1695,
+-1683,-1669,-1655,-1641,-1628,-1617,-1608,-1600,-1593,-1586,-1579,-1571,-1561,-1550,-1536,-1522,-1508,-1494,-1481,-1469,-1459,
+-1451,-1443,-1434,-1425,-1414,-1400,-1383,-1364,-1343,-1319,-1294,-1268,-1243,-1219,-1199,-1182,-1170,-1162,-1159,-1160,-1165,
+-1170,-1174,-1175,-1171,-1160,-1142,-1115,-1082,-1043,-1001,-957,-913,-871,-831,-794,-758,-722,-685,-646,-603,-558,
+-509,-459,-407,-356,-307,-259,-212,-167,-122,-76,-30,16,63,108,151,188,220,244,263,276,286,
+295,308,325,348,379,416,459,505,551,596,638,675,708,735,758,777,791,801,806,803,792,
+770,738,695,643,584,521,458,397,342,294,253,219,190,166,143,120,96,71,47,23,2,
+-14,-25,-32,-34,-33,-30,-27,-25,-27,-31,-39,-48,-58,-67,-74,-79,-82,-82,-81,-80,-81,
+-83,-88,-95,-103,-111,-119,-125,-128,-128,-125,-120,-114,-108,-103,-100,-100,-102,-106,-112,-118,-124,
+-129,-133,-136,-137,-138,-138,-137,-136,-136,-136,-135,-135,-134,-133,-131,-129,-127,-125,-124,-123,-123,
+-124,-125,-126,-127,-127,-127,-125,-123,-120,-117,-114,-111,-108,-106,-104,-102,-100,-98,-95,-92,-88,
+-84,-79,-74,-70,-67,-64,-62,-60,-59,-57,-56,-55,-54,-52,-51,-49,-48,-47,-47,-47,-47,
+-48,-48,-48,-48,-48,-47,-46,-45,-44,-43,-43,-42,-41,-41,-40,-39,-38,-38,-38,-40,-42,
+-44,-48,-51,-55,-57,-58,-58,-56,-52,-47,-40,-33,-26,-19,-13,-7,-3,0,4,7,10,
+13,15,18,21,24,28,33,39,48,61,77,98,123,151,183,217,254,291,329,368,407,
+448,489,533,577,622,665,707,745,777,804,824,837,847,854,861,872,887,908,935,966,1000,
+1032,1059,1078,1087,1086,1074,1054,1030,1007,990,982,987,1005,1037,1080,1131,1184,1234,1279,1315,1340,
+1353,1357,1354,1345,1334,1323,1314,1306,1300,1295,1289,1282,1272,1259,1245,1229,1213,1199,1188,1180,1175,
+1174,1175,1177,1246,1254,1263,1273,1283,1292,1303,1314,1328,1346,1367,1392,1422,1456,1492,1531,1570,1608,
+1644,1677,1706,1730,1748,1762,1769,1771,1767,1758,1743,1725,1702,1677,1651,1626,1602,1581,1565,1553,1546,
+1544,1545,1549,1553,1556,1558,1557,1554,1549,1544,1540,1538,1541,1547,1558,1572,1587,1602,1614,1623,1626,
+1624,1619,1611,1604,1600,1602,1611,1628,1651,1679,1707,1733,1753,1764,1766,1760,1747,1732,1717,1708,1707,
+1718,1739,1769,1806,1845,1883,1916,1941,1960,1973,1983,1995,2012,2036,2071,2114,2164,2216,2265,2304,2328,
+2335,2322,2293,2249,2198,2146,2098,2062,2040,2034,2042,2062,2088,2117,2144,2165,2178,2182,2180,2174,2166,
+2159,2156,2158,2164,2175,2188,2203,2218,2232,2246,2259,2275,2293,2316,2343,2376,2413,2451,2489,2523,2551,
+2572,2585,2590,2588,2581,2572,2563,2556,2552,2551,2554,2558,2562,2566,2567,2566,2561,2554,2546,2536,2526,
+2516,2506,2494,2480,2461,2437,2405,2366,2322,2273,2223,2176,2135,2105,2087,2084,2095,2119,2153,2193,2235,
+2275,2309,2335,2352,2361,2362,2360,2357,2355,2357,2365,2377,2394,2412,2428,2441,2446,2442,2428,2403,2371,
+2331,2289,2246,2207,2173,2146,2127,2115,2109,2108,2109,2110,2109,2106,2100,2091,2080,2067,2054,2043,2033,
+2026,2021,2019,2018,2017,2016,2015,2012,2009,2004,1998,1993,1988,1985,1983,1982,1982,1984,1985,1987,1988,
+1989,1990,1991,1993,1996,2002,2010,2022,2036,2051,2068,2084,2098,2108,2114,2113,2105,2090,2067,2036,1998,
+1953,1902,1846,1786,1725,1663,1603,1546,1494,1447,1408,1376,1351,1332,1319,1308,1301,1294,1287,1281,1275,
+1270,1268,1270,1276,1288,1305,1327,1353,1380,1407,1431,1452,1468,1479,1484,1486,1485,1482,1479,1478,1478,
+1480,1482,1486,1489,1490,1489,1485,1479,1470,1458,1445,1430,1415,1399,1382,1365,1347,1328,1308,1287,1266,
+1244,1222,1199,1178,1156,1135,1114,1093,1072,1049,1026,1002,976,948,919,890,859,827,795,762,729,
+697,666,636,609,584,562,544,529,516,506,497,488,477,464,448,428,404,376,345,311,277,
+242,207,172,138,105,71,37,0,-37,-78,-121,-167,-215,-264,-314,-362,-409,-455,-498,-539,-578,
+-615,-651,-687,-723,-759,-797,-836,-876,-917,-958,-1000,-1042,-1083,-1124,-1165,-1205,-1244,-1283,-1322,-1360,-1399,
+-1439,-1478,-1519,-1560,-1603,-1645,-1688,-1731,-1773,-1814,-1853,-1892,-1928,-1964,-2000,-2037,-2075,-2116,-2160,-2207,-2259,
+-2312,-2367,-2422,-2475,-2523,-2566,-2602,-2630,-2651,-2666,-2675,-2682,-2688,-2694,-2704,-2717,-2733,-2754,-2777,-2803,-2829,
+-2855,-2880,-2903,-2924,-2945,-2965,-2986,-3007,-3030,-3054,-3079,-3105,-3130,-3154,-3175,-3192,-3205,-3213,-3218,-3219,-3218,
+-3217,-3217,-3219,-3225,-3235,-3249,-3267,-3288,-3312,-3336,-3360,-3383,-3404,-3422,-3439,-3455,-3470,-3487,-3506,-3529,-3556,
+-3587,-3621,-3656,-3690,-3722,-3747,-3765,-3775,-3774,-3765,-3748,-3727,-3706,-3687,-3674,-3671,-3678,-3697,-3726,-3763,-3806,
+-3849,-3891,-3927,-3956,-3977,-3990,-3997,-4000,-4003,-4008,-4018,-4033,-4055,-4083,-4115,-4149,-4182,-4214,-4243,-4269,-4292,
+-4315,-4340,-4369,-4404,-4448,-4500,-4561,-4628,-4701,-4774,-4847,-4914,-4975,-5026,-5065,-5093,-5110,-5115,-5111,-5099,-5081,
+-5060,-5038,-5017,-5001,-4990,-4987,-4991,-5002,-5019,-5040,-5064,-5088,-5109,-5127,-5141,-5151,-5157,-5162,-5167,-5174,-5184,
+-5199,-5219,-5243,-5271,-5302,-5335,-5367,-5400,-5432,-5464,-5495,-5526,-5556,-5585,-5612,-5635,-5654,-5667,-5674,-5677,-5675,
+-5671,-5668,-5667,-5671,-5681,-5696,-5715,-5736,-5755,-5771,-5780,-5782,-5776,-5764,-5747,-5730,-5715,-5705,-5700,-5700,-5704,
+-5708,-5709,-5703,-5686,-5658,-5619,-5569,-5514,-5458,-5405,-5362,-5332,-5319,-5322,-5341,-5374,-5418,-5467,-5518,-5567,-5610,
+-5644,-5668,-5680,-5681,-5671,-5651,-5624,-5592,-5558,-5525,-5497,-5476,-5465,-5465,-5476,-5497,-5523,-5552,-5578,-5597,-5605,
+-5599,-5578,-5544,-5501,-5452,-5404,-5363,-5334,-5320,-5323,-5345,-5382,-5431,-5488,-5548,-5606,-5658,-5702,-5737,-5763,-5780,
+-5790,-5796,-5800,-5804,-5809,-5817,-5828,-5843,-5862,-5884,-5909,-5935,-5963,-5992,-6020,-6046,-6070,-6091,-6109,-6123,-6134,
+-6143,-6149,-6155,-6159,-6163,-6168,-6171,-6174,-6176,-6176,-6174,-6171,-6167,-6163,-6160,-6160,-6162,-6169,-6180,-6195,-6214,
+-6236,-6259,-6282,-6305,-6328,-6349,-6370,-6391,-6412,-6434,-6458,-6484,-6509,-6535,-6559,-6581,-6599,-6613,-6623,-6628,-6629,
+-6627,-6622,-6617,-6611,-6606,-6600,-6593,-6587,-6579,-6570,-6560,-6549,-6539,-6528,-6520,-6514,-6510,-6509,-6511,-6513,-6516,
+-6519,-6519,-6516,-6510,-6501,-6489,-6476,-6463,-6450,-6439,-6430,-6424,-6420,-6418,-6416,-6414,-6411,-6406,-6400,-6391,-6381,
+-6371,-6361,-6351,-6343,-6335,-6329,-6324,-6319,-6315,-6309,-6303,-6296,-6288,-6280,-6273,-6265,-6258,-6252,-6247,-6242,-6236,
+-6230,-6223,-6215,-6206,-6196,-6185,-6174,-6163,-6153,-6144,-6135,-6127,-6118,-6109,-6100,-6089,-6077,-6065,-6051,-6037,-6024,
+-6011,-5999,-5989,-5979,-5971,-5963,-5955,-5948,-5939,-5930,-5920,-5910,-5899,-5887,-5875,-5862,-5850,-5836,-5822,-5806,-5790,
+-5772,-5752,-5731,-5710,-5688,-5666,-5645,-5624,-5605,-5588,-5571,-5555,-5540,-5526,-5511,-5495,-5480,-5463,-5446,-5428,-5410,
+-5391,-5373,-5354,-5336,-5318,-5299,-5281,-5263,-5245,-5227,-5210,-5193,-5177,-5162,-5148,-5135,-5123,-5111,-5099,-5086,-5072,
+-5057,-5040,-5021,-5000,-4977,-4953,-4927,-4900,-4873,-4846,-4820,-4793,-4768,-4743,-4718,-4694,-4670,-4646,-4624,-4602,-4581,
+-4562,-4545,-4530,-4516,-4504,-4492,-4481,-4470,-4457,-4444,-4430,-4416,-4401,-4386,-4372,-4359,-4347,-4335,-4323,-4310,-4294,
+-4276,-4254,-4230,-4202,-4172,-4141,-4111,-4083,-4058,-4036,-4017,-4001,-3985,-3968,-3948,-3925,-3896,-3861,-3822,-3780,-3736,
+-3692,-3651,-3613,-3581,-3552,-3528,-3507,-3486,-3466,-3444,-3420,-3393,-3366,-3339,-3314,-3293,-3276,-3264,-3258,-3256,-3257,
+-3259,-3261,-3261,-3257,-3250,-3240,-3228,-3214,-3199,-3186,-3173,-3162,-3152,-3143,-3134,-3124,-3113,-3101,-3088,-3074,-3061,
+-3049,-3039,-3031,-3024,-3019,-3014,-3007,-2998,-2985,-2969,-2948,-2923,-2895,-2865,-2834,-2804,-2774,-2746,-2720,-2695,-2670,
+-2646,-2622,-2596,-2569,-2542,-2513,-2484,-2455,-2427,-2400,-2375,-2352,-2331,-2313,-2297,-2284,-2272,-2262,-2252,-2242,-2232,
+-2220,-2206,-2190,-2173,-2155,-2136,-2120,-2108,-2101,-2101,-2107,-2121,-2141,-2165,-2190,-2213,-2231,-2240,-2239,-2226,-2202,
+-2166,-2121,-2070,-2017,-1963,-1913,-1869,-1831,-1800,-1777,-1760,-1749,-1740,-1734,-1728,-1722,-1714,-1705,-1695,-1683,-1669,
+-1654,-1639,-1622,-1606,-1590,-1574,-1559,-1545,-1532,-1520,-1509,-1498,-1487,-1477,-1466,-1454,-1442,-1429,-1416,-1402,-1388,
+-1373,-1358,-1343,-1328,-1313,-1298,-1283,-1268,-1254,-1242,-1231,-1222,-1214,-1207,-1200,-1192,-1181,-1167,-1148,-1125,-1098,
+-1066,-1031,-994,-956,-917,-878,-840,-802,-764,-726,-687,-647,-606,-564,-522,-479,-436,-393,-349,-304,-258,
+-210,-160,-108,-56,-4,44,89,129,162,187,206,219,229,237,247,260,278,301,330,364,402,
+441,480,519,556,591,622,651,675,695,708,712,707,689,659,615,560,495,423,348,274,206,
+146,97,59,31,11,-1,-11,-19,-28,-39,-52,-66,-79,-91,-100,-105,-106,-104,-100,-95,-90,
+-87,-85,-86,-89,-92,-95,-97,-97,-95,-92,-87,-83,-80,-79,-80,-83,-88,-94,-101,-106,-109,
+-109,-107,-102,-96,-90,-85,-81,-79,-80,-84,-90,-98,-106,-114,-122,-129,-135,-140,-144,-147,-150,
+-152,-154,-156,-157,-158,-158,-158,-158,-158,-158,-159,-161,-164,-168,-172,-177,-181,-185,-188,-189,-189,
+-188,-186,-183,-180,-177,-174,-171,-169,-166,-164,-162,-159,-156,-153,-149,-146,-142,-139,-136,-133,-130,
+-127,-124,-121,-118,-114,-111,-107,-104,-101,-99,-98,-98,-99,-101,-103,-105,-107,-109,-111,-112,-112,
+-111,-109,-107,-104,-101,-98,-95,-92,-90,-88,-88,-88,-90,-91,-93,-95,-97,-97,-96,-94,-91,
+-87,-83,-79,-75,-71,-67,-64,-61,-57,-52,-46,-39,-31,-21,-11,-1,9,19,29,39,51,
+64,81,101,126,155,189,225,265,306,348,391,432,473,513,552,590,628,664,698,728,754,
+775,789,796,799,797,794,792,794,801,817,840,870,904,940,974,1002,1022,1033,1035,1029,1018,
+1006,998,998,1008,1031,1066,1112,1165,1221,1276,1325,1366,1395,1412,1418,1414,1404,1390,1375,1360,1348,
+1339,1332,1326,1320,1313,1304,1294,1282,1269,1257,1247,1240,1236,1236,1240,1246,1374,1381,1389,1398,1408,
+1419,1430,1442,1456,1472,1491,1513,1538,1567,1599,1634,1671,1709,1747,1784,1819,1850,1877,1897,1911,1916,
+1913,1901,1881,1854,1822,1786,1750,1715,1684,1659,1643,1635,1636,1644,1659,1677,1696,1715,1731,1743,1750,
+1754,1754,1752,1750,1749,1750,1753,1758,1764,1770,1774,1776,1775,1772,1768,1763,1761,1762,1768,1780,1795,
+1814,1834,1850,1862,1866,1862,1849,1830,1808,1786,1768,1757,1757,1766,1785,1812,1842,1873,1902,1926,1945,
+1960,1975,1994,2021,2059,2111,2176,2253,2335,2416,2489,2545,2577,2582,2558,2508,2437,2352,2263,2178,2106,
+2052,2020,2009,2017,2040,2071,2105,2137,2162,2178,2186,2186,2182,2176,2172,2172,2177,2188,2203,2223,2244,
+2267,2289,2311,2332,2353,2374,2395,2417,2440,2462,2482,2500,2513,2522,2526,2526,2524,2520,2516,2515,2516,
+2522,2532,2544,2557,2571,2582,2590,2593,2592,2587,2578,2566,2552,2537,2520,2502,2481,2457,2428,2394,2355,
+2312,2267,2221,2179,2143,2116,2101,2098,2109,2131,2163,2202,2243,2283,2320,2351,2374,2389,2398,2402,2402,
+2401,2399,2398,2398,2398,2397,2393,2385,2372,2353,2329,2300,2268,2234,2201,2171,2146,2125,2109,2097,2089,
+2083,2078,2072,2064,2055,2044,2032,2019,2008,1998,1991,1986,1983,1982,1983,1984,1984,1984,1983,1982,1981,
+1981,1983,1988,1995,2004,2015,2028,2039,2050,2057,2061,2060,2055,2047,2037,2025,2014,2004,1996,1992,1991,
+1992,1996,2001,2007,2014,2020,2025,2030,2033,2034,2031,2025,2013,1994,1966,1929,1882,1826,1762,1692,1619,
+1546,1477,1415,1361,1319,1287,1266,1254,1249,1249,1252,1256,1260,1265,1271,1279,1289,1304,1323,1346,1372,
+1401,1430,1457,1480,1499,1512,1519,1520,1518,1513,1507,1501,1496,1492,1490,1488,1486,1483,1477,1469,1459,
+1445,1429,1412,1393,1375,1356,1338,1319,1301,1283,1263,1243,1221,1198,1174,1149,1124,1100,1076,1053,1031,
+1009,988,966,944,920,895,868,839,808,776,743,709,676,644,615,588,564,545,529,516,507,
+499,493,487,480,471,459,444,425,401,374,344,311,276,240,203,166,129,93,57,21,-14,
+-51,-89,-128,-169,-210,-253,-297,-342,-386,-430,-473,-515,-556,-595,-634,-672,-710,-748,-788,-829,-872,
+-917,-963,-1012,-1061,-1110,-1159,-1207,-1253,-1297,-1339,-1380,-1420,-1459,-1499,-1540,-1582,-1627,-1673,-1720,-1768,-1816,
+-1862,-1907,-1949,-1989,-2027,-2064,-2100,-2137,-2177,-2221,-2269,-2321,-2377,-2436,-2496,-2555,-2610,-2660,-2703,-2737,-2762,
+-2780,-2790,-2795,-2797,-2799,-2803,-2809,-2820,-2835,-2855,-2878,-2904,-2931,-2958,-2983,-3006,-3027,-3046,-3062,-3077,-3092,
+-3107,-3122,-3138,-3154,-3171,-3186,-3201,-3213,-3223,-3230,-3235,-3237,-3239,-3241,-3244,-3249,-3257,-3268,-3284,-3302,-3324,
+-3347,-3370,-3394,-3416,-3437,-3456,-3475,-3494,-3514,-3538,-3567,-3600,-3639,-3681,-3727,-3772,-3815,-3851,-3877,-3892,-3894,
+-3882,-3859,-3827,-3790,-3752,-3719,-3695,-3683,-3685,-3702,-3732,-3772,-3818,-3866,-3911,-3950,-3981,-4002,-4014,-4020,-4021,
+-4023,-4027,-4036,-4053,-4077,-4108,-4143,-4181,-4218,-4252,-4283,-4309,-4332,-4354,-4377,-4404,-4438,-4481,-4533,-4594,-4664,
+-4738,-4813,-4886,-4952,-5009,-5053,-5083,-5098,-5100,-5088,-5067,-5039,-5007,-4975,-4945,-4922,-4906,-4899,-4902,-4914,-4934,
+-4961,-4993,-5026,-5059,-5089,-5116,-5138,-5156,-5169,-5181,-5191,-5202,-5214,-5230,-5250,-5273,-5300,-5330,-5362,-5396,-5430,
+-5465,-5500,-5534,-5566,-5597,-5624,-5647,-5665,-5678,-5685,-5687,-5686,-5682,-5678,-5677,-5679,-5687,-5701,-5720,-5742,-5766,
+-5789,-5808,-5821,-5826,-5824,-5816,-5804,-5790,-5776,-5765,-5758,-5756,-5756,-5757,-5757,-5751,-5738,-5716,-5684,-5643,-5596,
+-5546,-5497,-5452,-5416,-5392,-5380,-5383,-5398,-5424,-5458,-5497,-5536,-5572,-5602,-5624,-5634,-5633,-5620,-5595,-5563,-5525,
+-5486,-5450,-5421,-5403,-5399,-5411,-5437,-5476,-5523,-5573,-5621,-5660,-5685,-5694,-5685,-5660,-5622,-5575,-5526,-5482,-5448,
+-5428,-5426,-5441,-5471,-5514,-5564,-5617,-5666,-5708,-5740,-5760,-5769,-5768,-5759,-5747,-5733,-5723,-5718,-5719,-5729,-5748,
+-5774,-5808,-5846,-5889,-5933,-5977,-6019,-6058,-6093,-6122,-6145,-6163,-6176,-6185,-6190,-6193,-6194,-6194,-6193,-6192,-6190,
+-6187,-6184,-6179,-6174,-6169,-6165,-6161,-6161,-6163,-6169,-6179,-6193,-6210,-6229,-6249,-6270,-6290,-6310,-6329,-6348,-6368,
+-6389,-6411,-6436,-6462,-6490,-6518,-6544,-6567,-6586,-6600,-6608,-6609,-6606,-6599,-6589,-6578,-6568,-6558,-6551,-6547,-6544,
+-6544,-6544,-6544,-6544,-6542,-6540,-6537,-6534,-6531,-6528,-6525,-6523,-6522,-6520,-6519,-6516,-6512,-6507,-6501,-6494,-6486,
+-6478,-6470,-6464,-6458,-6453,-6448,-6443,-6439,-6433,-6426,-6419,-6411,-6402,-6393,-6384,-6376,-6369,-6363,-6358,-6353,-6349,
+-6345,-6340,-6334,-6327,-6320,-6312,-6303,-6295,-6287,-6280,-6273,-6267,-6261,-6255,-6249,-6242,-6234,-6226,-6216,-6206,-6195,
+-6184,-6172,-6161,-6150,-6138,-6127,-6116,-6105,-6094,-6083,-6073,-6063,-6053,-6045,-6037,-6029,-6022,-6015,-6008,-6000,-5992,
+-5983,-5972,-5960,-5947,-5933,-5918,-5901,-5884,-5866,-5847,-5827,-5807,-5786,-5765,-5745,-5725,-5705,-5687,-5669,-5653,-5638,
+-5623,-5609,-5596,-5582,-5568,-5554,-5539,-5523,-5507,-5492,-5476,-5460,-5444,-5428,-5412,-5395,-5377,-5359,-5339,-5318,-5297,
+-5276,-5255,-5234,-5215,-5198,-5183,-5170,-5157,-5146,-5134,-5122,-5108,-5092,-5073,-5052,-5028,-5003,-4977,-4951,-4925,-4900,
+-4877,-4856,-4835,-4816,-4797,-4778,-4758,-4737,-4716,-4693,-4671,-4649,-4628,-4608,-4590,-4572,-4556,-4539,-4522,-4503,-4483,
+-4460,-4436,-4410,-4385,-4361,-4340,-4322,-4308,-4298,-4292,-4287,-4283,-4278,-4270,-4257,-4238,-4215,-4187,-4155,-4122,-4088,
+-4056,-4025,-3998,-3972,-3947,-3922,-3895,-3864,-3829,-3790,-3747,-3702,-3657,-3613,-3574,-3541,-3514,-3494,-3479,-3468,-3460,
+-3451,-3441,-3428,-3411,-3392,-3371,-3350,-3329,-3312,-3298,-3289,-3283,-3279,-3278,-3276,-3273,-3268,-3260,-3251,-3240,-3228,
+-3217,-3207,-3200,-3195,-3191,-3187,-3183,-3178,-3169,-3157,-3141,-3122,-3101,-3079,-3057,-3036,-3017,-3000,-2986,-2974,-2963,
+-2952,-2940,-2927,-2912,-2894,-2874,-2852,-2829,-2803,-2776,-2747,-2718,-2686,-2654,-2621,-2587,-2552,-2519,-2486,-2455,-2426,
+-2400,-2376,-2356,-2337,-2321,-2307,-2294,-2281,-2269,-2258,-2246,-2235,-2223,-2211,-2198,-2184,-2170,-2156,-2143,-2132,-2123,
+-2119,-2121,-2129,-2144,-2166,-2192,-2222,-2253,-2281,-2304,-2318,-2321,-2311,-2288,-2252,-2205,-2150,-2090,-2030,-1971,-1918,
+-1873,-1837,-1809,-1791,-1779,-1771,-1767,-1762,-1756,-1747,-1734,-1717,-1697,-1674,-1650,-1627,-1606,-1587,-1572,-1560,-1550,
+-1543,-1537,-1530,-1522,-1512,-1499,-1484,-1467,-1449,-1432,-1416,-1402,-1391,-1383,-1378,-1374,-1371,-1368,-1362,-1354,-1342,
+-1327,-1309,-1289,-1267,-1245,-1223,-1202,-1182,-1163,-1145,-1128,-1110,-1090,-1069,-1046,-1020,-992,-961,-928,-893,-857,
+-819,-780,-741,-702,-663,-625,-587,-549,-511,-471,-430,-386,-339,-288,-234,-179,-122,-67,-14,32,73,
+106,131,149,161,169,175,182,192,206,226,250,280,313,349,385,423,459,494,528,559,586,
+608,623,630,625,608,576,531,472,403,325,245,164,89,23,-32,-75,-107,-127,-140,-146,-150,
+-154,-158,-164,-171,-179,-187,-192,-195,-195,-191,-184,-175,-166,-157,-149,-143,-139,-136,-134,-133,-130,
+-126,-121,-115,-108,-102,-96,-91,-87,-85,-85,-85,-85,-85,-83,-81,-78,-74,-70,-66,-64,-63,
+-64,-67,-72,-79,-87,-96,-105,-114,-122,-130,-137,-144,-150,-155,-161,-165,-170,-174,-177,-180,-184,
+-187,-191,-195,-201,-207,-214,-222,-229,-237,-243,-248,-252,-255,-256,-255,-253,-250,-247,-244,-241,-237,
+-234,-232,-229,-227,-225,-224,-222,-221,-220,-219,-217,-215,-213,-210,-206,-202,-197,-191,-186,-180,-175,
+-171,-168,-166,-166,-166,-168,-171,-174,-177,-180,-181,-182,-181,-178,-174,-169,-163,-156,-149,-142,-135,
+-130,-126,-124,-122,-122,-122,-123,-124,-124,-124,-123,-121,-119,-117,-115,-113,-112,-111,-111,-109,-107,
+-102,-96,-86,-74,-60,-44,-27,-10,5,21,36,50,65,82,101,125,154,187,226,270,316,
+365,414,462,507,549,587,622,653,680,704,724,741,754,763,767,768,765,760,755,751,750,
+755,767,785,809,838,870,902,931,956,975,988,997,1002,1007,1015,1030,1052,1085,1127,1177,1232,
+1289,1345,1394,1434,1463,1480,1485,1481,1468,1451,1433,1415,1399,1388,1380,1376,1374,1374,1374,1374,1373,
+1371,1368,1366,1364,1363,1365,1368,1374,1448,1452,1457,1464,1473,1484,1496,1510,1527,1545,1566,1589,1614,
+1641,1671,1703,1737,1772,1809,1845,1880,1913,1942,1965,1982,1989,1988,1978,1958,1930,1896,1859,1821,1785,
+1754,1730,1715,1710,1715,1728,1747,1770,1795,1819,1840,1856,1868,1876,1880,1881,1882,1882,1884,1886,1889,
+1893,1896,1897,1897,1895,1892,1888,1886,1887,1890,1898,1909,1923,1938,1951,1960,1963,1960,1949,1932,1911,
+1890,1871,1857,1851,1854,1865,1882,1903,1925,1943,1957,1966,1971,1974,1980,1994,2022,2066,2128,2208,2302,
+2403,2503,2593,2664,2709,2722,2702,2652,2576,2483,2382,2283,2195,2125,2077,2053,2050,2064,2091,2123,2154,
+2181,2201,2211,2214,2211,2206,2202,2201,2205,2216,2233,2255,2280,2307,2333,2358,2380,2400,2416,2431,2443,
+2453,2461,2467,2471,2472,2471,2467,2463,2458,2453,2452,2453,2459,2469,2483,2500,2519,2538,2554,2568,2576,
+2579,2577,2569,2558,2542,2524,2504,2482,2458,2432,2402,2370,2334,2296,2257,2219,2183,2152,2128,2113,2108,
+2114,2130,2155,2186,2221,2258,2294,2326,2354,2377,2394,2405,2411,2413,2411,2406,2397,2385,2368,2348,2324,
+2297,2267,2235,2202,2171,2142,2117,2095,2078,2065,2054,2045,2037,2027,2017,2004,1991,1977,1963,1951,1941,
+1935,1932,1932,1934,1938,1941,1944,1944,1943,1940,1936,1933,1932,1936,1943,1956,1974,1996,2020,2044,2066,
+2083,2094,2099,2096,2088,2075,2058,2041,2025,2010,1998,1989,1984,1980,1979,1978,1978,1979,1981,1985,1990,
+1998,2006,2015,2021,2023,2018,2002,1974,1932,1876,1807,1728,1643,1557,1474,1400,1337,1289,1256,1238,1233,
+1238,1249,1264,1279,1294,1307,1318,1328,1339,1352,1369,1389,1413,1439,1467,1493,1516,1535,1547,1553,1554,
+1549,1541,1531,1521,1511,1503,1497,1491,1484,1477,1468,1456,1441,1423,1403,1381,1359,1337,1317,1298,1281,
+1264,1248,1231,1213,1192,1169,1143,1116,1088,1059,1031,1004,979,956,934,914,893,872,849,823,795,
+765,732,698,664,631,600,572,549,529,515,504,496,491,487,483,477,469,458,444,426,404,
+379,351,321,289,256,222,187,153,118,84,50,15,-19,-54,-91,-129,-169,-210,-253,-298,-344,
+-390,-437,-483,-528,-571,-613,-652,-690,-727,-765,-802,-842,-884,-929,-977,-1027,-1079,-1132,-1185,-1237,-1286,
+-1334,-1378,-1420,-1461,-1501,-1541,-1582,-1625,-1670,-1718,-1767,-1816,-1866,-1915,-1961,-2006,-2048,-2088,-2128,-2168,-2210,
+-2255,-2304,-2358,-2416,-2477,-2540,-2603,-2663,-2718,-2766,-2805,-2834,-2854,-2866,-2870,-2870,-2866,-2863,-2862,-2865,-2872,
+-2886,-2905,-2928,-2954,-2983,-3012,-3040,-3065,-3088,-3108,-3124,-3138,-3151,-3162,-3172,-3183,-3194,-3205,-3217,-3228,-3239,
+-3248,-3256,-3262,-3267,-3270,-3273,-3276,-3281,-3289,-3299,-3313,-3330,-3350,-3373,-3396,-3421,-3444,-3467,-3489,-3510,-3532,
+-3555,-3582,-3613,-3650,-3692,-3739,-3789,-3838,-3885,-3925,-3954,-3970,-3972,-3958,-3931,-3893,-3849,-3804,-3763,-3730,-3711,
+-3707,-3718,-3745,-3783,-3829,-3878,-3926,-3968,-4003,-4028,-4045,-4054,-4059,-4062,-4067,-4078,-4094,-4117,-4146,-4180,-4216,
+-4251,-4284,-4313,-4339,-4361,-4383,-4406,-4434,-4468,-4511,-4564,-4625,-4693,-4766,-4840,-4910,-4972,-5023,-5061,-5083,-5091,
+-5084,-5065,-5037,-5003,-4968,-4935,-4906,-4884,-4872,-4869,-4877,-4893,-4917,-4947,-4981,-5016,-5051,-5083,-5113,-5139,-5161,
+-5180,-5197,-5213,-5229,-5246,-5265,-5287,-5312,-5339,-5369,-5402,-5436,-5470,-5505,-5539,-5572,-5602,-5630,-5653,-5672,-5685,
+-5694,-5698,-5699,-5697,-5695,-5693,-5695,-5701,-5712,-5727,-5747,-5769,-5792,-5814,-5832,-5844,-5851,-5852,-5847,-5839,-5828,
+-5818,-5809,-5803,-5800,-5798,-5797,-5794,-5788,-5776,-5756,-5729,-5694,-5654,-5609,-5564,-5521,-5484,-5454,-5435,-5427,-5430,
+-5443,-5464,-5491,-5520,-5548,-5571,-5586,-5592,-5586,-5568,-5540,-5504,-5464,-5423,-5387,-5361,-5348,-5353,-5375,-5415,-5469,
+-5533,-5601,-5667,-5724,-5767,-5792,-5798,-5784,-5755,-5715,-5670,-5626,-5589,-5564,-5554,-5560,-5580,-5612,-5651,-5691,-5729,
+-5761,-5782,-5792,-5791,-5781,-5764,-5744,-5723,-5707,-5697,-5695,-5703,-5721,-5749,-5784,-5826,-5871,-5918,-5966,-6011,-6052,
+-6089,-6120,-6146,-6166,-6180,-6189,-6195,-6197,-6197,-6195,-6191,-6187,-6182,-6176,-6169,-6163,-6157,-6151,-6148,-6147,-6149,
+-6154,-6164,-6177,-6193,-6212,-6233,-6254,-6276,-6296,-6316,-6334,-6352,-6370,-6389,-6409,-6431,-6455,-6480,-6505,-6529,-6550,
+-6568,-6581,-6588,-6590,-6586,-6579,-6569,-6559,-6549,-6541,-6535,-6533,-6534,-6537,-6541,-6545,-6549,-6552,-6553,-6551,-6549,
+-6545,-6541,-6536,-6533,-6530,-6528,-6527,-6526,-6525,-6524,-6521,-6518,-6513,-6507,-6501,-6494,-6486,-6479,-6472,-6465,-6459,
+-6452,-6445,-6439,-6432,-6425,-6419,-6412,-6406,-6401,-6397,-6393,-6389,-6385,-6381,-6376,-6370,-6364,-6356,-6348,-6338,-6329,
+-6320,-6311,-6303,-6296,-6289,-6283,-6277,-6271,-6265,-6257,-6249,-6239,-6228,-6216,-6203,-6190,-6176,-6163,-6150,-6138,-6127,
+-6117,-6108,-6101,-6094,-6088,-6082,-6077,-6072,-6066,-6059,-6052,-6043,-6033,-6021,-6008,-5993,-5976,-5958,-5938,-5917,-5895,
+-5872,-5848,-5825,-5801,-5779,-5758,-5739,-5722,-5707,-5693,-5681,-5670,-5658,-5647,-5635,-5622,-5608,-5592,-5576,-5559,-5542,
+-5526,-5511,-5497,-5483,-5470,-5457,-5443,-5429,-5412,-5393,-5372,-5350,-5327,-5303,-5280,-5258,-5239,-5222,-5207,-5194,-5182,
+-5170,-5157,-5142,-5124,-5103,-5079,-5053,-5026,-4998,-4971,-4946,-4925,-4906,-4890,-4876,-4863,-4851,-4837,-4822,-4803,-4782,
+-4758,-4731,-4704,-4677,-4651,-4627,-4604,-4584,-4564,-4544,-4523,-4500,-4473,-4443,-4411,-4376,-4341,-4308,-4279,-4254,-4235,
+-4223,-4216,-4214,-4214,-4214,-4212,-4205,-4193,-4174,-4148,-4117,-4083,-4046,-4009,-3972,-3938,-3905,-3874,-3844,-3814,-3782,
+-3747,-3711,-3672,-3634,-3595,-3560,-3529,-3503,-3484,-3472,-3465,-3463,-3462,-3462,-3460,-3455,-3447,-3434,-3418,-3400,-3381,
+-3363,-3347,-3333,-3321,-3312,-3305,-3300,-3294,-3288,-3282,-3275,-3268,-3262,-3256,-3252,-3249,-3248,-3247,-3245,-3242,-3237,
+-3228,-3215,-3198,-3177,-3153,-3127,-3100,-3073,-3047,-3023,-3000,-2980,-2961,-2943,-2926,-2910,-2893,-2876,-2859,-2840,-2819,
+-2797,-2773,-2746,-2716,-2684,-2649,-2613,-2576,-2540,-2505,-2472,-2444,-2419,-2399,-2383,-2370,-2359,-2349,-2340,-2329,-2318,
+-2304,-2290,-2275,-2260,-2245,-2231,-2219,-2208,-2198,-2188,-2179,-2171,-2164,-2158,-2155,-2156,-2162,-2173,-2191,-2213,-2240,
+-2268,-2295,-2317,-2331,-2335,-2326,-2303,-2267,-2219,-2163,-2100,-2037,-1976,-1921,-1875,-1839,-1814,-1797,-1787,-1781,-1777,
+-1771,-1761,-1747,-1728,-1704,-1677,-1650,-1624,-1601,-1583,-1571,-1563,-1560,-1559,-1559,-1557,-1552,-1543,-1529,-1511,-1490,
+-1468,-1446,-1427,-1412,-1401,-1396,-1396,-1398,-1401,-1404,-1403,-1398,-1387,-1370,-1347,-1320,-1289,-1258,-1226,-1197,-1170,
+-1148,-1128,-1112,-1098,-1084,-1071,-1056,-1038,-1017,-993,-965,-933,-899,-863,-826,-789,-751,-715,-680,-645,-610,
+-574,-537,-497,-454,-407,-356,-302,-246,-189,-135,-84,-38,0,30,54,70,82,92,100,110,124,
+141,163,190,220,253,287,321,353,385,414,441,466,488,506,519,525,522,508,482,443,392,
+329,258,182,104,29,-39,-99,-148,-186,-213,-231,-243,-250,-254,-259,-265,-271,-279,-286,-292,-295,
+-295,-291,-283,-272,-259,-245,-231,-218,-207,-199,-192,-186,-180,-175,-169,-161,-153,-143,-133,-122,-112,
+-104,-96,-90,-85,-81,-78,-75,-73,-71,-69,-67,-66,-66,-66,-68,-71,-75,-81,-87,-95,-103,
+-111,-120,-129,-137,-145,-154,-161,-169,-176,-183,-190,-197,-205,-213,-221,-230,-239,-249,-259,-269,-278,
+-287,-295,-302,-307,-311,-314,-315,-315,-315,-314,-313,-311,-309,-307,-306,-304,-303,-303,-302,-302,-302,
+-302,-302,-301,-300,-298,-294,-290,-284,-277,-270,-262,-255,-248,-241,-236,-233,-230,-229,-229,-229,-230,
+-231,-231,-230,-229,-225,-221,-215,-207,-199,-190,-181,-172,-164,-157,-152,-148,-145,-144,-144,-145,-146,
+-146,-147,-147,-146,-145,-144,-142,-140,-139,-137,-134,-130,-124,-116,-106,-92,-76,-58,-39,-19,0,
+18,35,51,66,82,99,120,145,176,214,258,307,360,415,470,523,572,615,651,681,704,
+721,733,742,747,750,752,753,753,753,753,753,754,757,763,771,783,798,816,835,856,876,
+896,914,932,949,967,988,1013,1044,1082,1127,1178,1235,1293,1352,1406,1454,1493,1521,1537,1541,1536,
+1522,1503,1481,1459,1440,1424,1413,1407,1405,1407,1411,1417,1422,1428,1432,1436,1439,1441,1443,1445,1448,
+1408,1414,1422,1432,1444,1459,1476,1496,1518,1541,1566,1591,1618,1645,1672,1700,1729,1759,1790,1821,1851,
+1880,1907,1929,1946,1957,1959,1954,1940,1920,1894,1866,1836,1808,1785,1768,1757,1755,1760,1771,1787,1805,
+1823,1841,1856,1868,1877,1884,1889,1894,1899,1905,1912,1920,1927,1934,1939,1942,1942,1940,1937,1933,1930,
+1930,1934,1941,1952,1965,1978,1991,2000,2004,2003,1996,1984,1970,1956,1944,1938,1937,1942,1952,1965,1979,
+1989,1995,1994,1987,1976,1963,1954,1955,1969,2001,2052,2121,2205,2297,2392,2478,2549,2598,2620,2612,2577,
+2519,2445,2363,2280,2206,2147,2105,2082,2076,2085,2104,2127,2149,2167,2178,2182,2180,2175,2168,2163,2162,
+2167,2179,2197,2219,2245,2271,2295,2317,2334,2347,2356,2362,2364,2365,2364,2363,2360,2357,2354,2350,2345,
+2342,2340,2340,2343,2350,2362,2377,2395,2416,2437,2456,2473,2486,2493,2495,2492,2483,2470,2454,2435,2415,
+2392,2369,2344,2317,2290,2261,2232,2203,2176,2152,2132,2118,2110,2110,2116,2128,2146,2168,2193,2218,2243,
+2265,2285,2302,2315,2323,2328,2328,2324,2315,2302,2285,2264,2240,2213,2185,2157,2129,2104,2081,2061,2045,
+2031,2019,2008,1997,1986,1973,1959,1945,1930,1918,1907,1900,1897,1897,1900,1905,1911,1916,1918,1917,1913,
+1907,1900,1893,1889,1890,1898,1913,1935,1963,1995,2028,2060,2086,2106,2118,2121,2115,2102,2085,2066,2046,
+2029,2015,2005,1998,1995,1994,1993,1992,1991,1989,1988,1989,1991,1995,2002,2009,2015,2018,2012,1997,1968,
+1924,1865,1793,1711,1622,1532,1447,1371,1308,1262,1233,1221,1222,1235,1255,1279,1304,1326,1346,1362,1377,
+1391,1405,1422,1441,1462,1484,1506,1526,1541,1551,1555,1552,1543,1530,1514,1497,1481,1467,1456,1448,1441,
+1435,1428,1418,1405,1388,1368,1346,1321,1297,1274,1253,1234,1219,1205,1193,1180,1166,1149,1130,1107,1081,
+1053,1024,996,969,944,921,900,881,862,842,820,796,768,737,704,669,634,601,571,545,525,
+509,499,492,488,486,482,477,469,456,439,417,391,362,331,298,265,231,198,167,136,106,
+78,50,22,-6,-35,-66,-100,-135,-174,-216,-261,-309,-358,-409,-460,-510,-558,-604,-646,-685,-721,
+-755,-789,-822,-857,-894,-935,-979,-1026,-1076,-1128,-1180,-1232,-1283,-1331,-1376,-1419,-1461,-1501,-1541,-1582,-1625,
+-1669,-1714,-1761,-1809,-1856,-1903,-1948,-1991,-2033,-2075,-2116,-2160,-2206,-2256,-2311,-2370,-2433,-2498,-2564,-2629,-2690,
+-2744,-2791,-2828,-2855,-2872,-2881,-2882,-2879,-2872,-2866,-2861,-2860,-2864,-2873,-2888,-2908,-2933,-2960,-2988,-3016,-3043,
+-3068,-3089,-3108,-3124,-3137,-3149,-3161,-3172,-3184,-3197,-3211,-3225,-3239,-3253,-3266,-3277,-3286,-3294,-3300,-3306,-3312,
+-3320,-3330,-3344,-3361,-3382,-3406,-3432,-3459,-3486,-3512,-3537,-3560,-3582,-3604,-3628,-3655,-3687,-3723,-3764,-3809,-3856,
+-3902,-3942,-3975,-3996,-4003,-3996,-3976,-3944,-3904,-3861,-3820,-3786,-3764,-3756,-3764,-3788,-3824,-3871,-3924,-3977,-4028,
+-4072,-4108,-4134,-4151,-4162,-4168,-4173,-4178,-4187,-4199,-4216,-4237,-4260,-4285,-4310,-4334,-4358,-4381,-4405,-4432,-4463,
+-4501,-4546,-4598,-4656,-4719,-4784,-4847,-4906,-4957,-4998,-5026,-5042,-5045,-5037,-5020,-4997,-4970,-4944,-4920,-4901,-4889,
+-4884,-4887,-4898,-4915,-4938,-4964,-4994,-5024,-5055,-5085,-5113,-5140,-5165,-5188,-5211,-5233,-5256,-5279,-5303,-5329,-5356,
+-5385,-5415,-5446,-5477,-5508,-5539,-5569,-5597,-5623,-5646,-5666,-5681,-5693,-5701,-5706,-5708,-5709,-5710,-5711,-5715,-5721,
+-5730,-5742,-5757,-5773,-5790,-5805,-5819,-5829,-5835,-5838,-5839,-5836,-5833,-5830,-5827,-5824,-5823,-5821,-5818,-5812,-5802,
+-5787,-5767,-5739,-5706,-5669,-5628,-5585,-5544,-5506,-5474,-5448,-5430,-5420,-5417,-5421,-5429,-5439,-5448,-5455,-5456,-5451,
+-5438,-5416,-5389,-5357,-5323,-5294,-5271,-5260,-5264,-5284,-5323,-5377,-5445,-5521,-5601,-5676,-5743,-5795,-5830,-5845,-5841,
+-5822,-5791,-5753,-5714,-5681,-5656,-5643,-5643,-5655,-5677,-5705,-5736,-5765,-5789,-5806,-5814,-5814,-5806,-5794,-5779,-5764,
+-5753,-5748,-5749,-5758,-5774,-5798,-5827,-5860,-5896,-5933,-5970,-6004,-6036,-6064,-6088,-6108,-6123,-6135,-6143,-6148,-6151,
+-6151,-6149,-6147,-6143,-6139,-6135,-6131,-6128,-6126,-6126,-6129,-6134,-6142,-6154,-6169,-6187,-6207,-6229,-6252,-6274,-6296,
+-6317,-6336,-6353,-6370,-6386,-6403,-6420,-6439,-6459,-6480,-6502,-6522,-6541,-6557,-6569,-6577,-6581,-6581,-6577,-6572,-6565,
+-6559,-6554,-6551,-6550,-6551,-6553,-6556,-6559,-6562,-6562,-6561,-6558,-6554,-6550,-6545,-6540,-6537,-6535,-6534,-6534,-6534,
+-6535,-6535,-6533,-6531,-6526,-6521,-6514,-6506,-6499,-6491,-6484,-6478,-6473,-6468,-6464,-6459,-6455,-6450,-6445,-6440,-6434,
+-6428,-6423,-6418,-6413,-6408,-6404,-6399,-6393,-6387,-6380,-6372,-6364,-6355,-6345,-6336,-6327,-6319,-6311,-6304,-6298,-6292,
+-6286,-6279,-6272,-6264,-6254,-6244,-6232,-6220,-6208,-6196,-6184,-6173,-6163,-6154,-6146,-6138,-6131,-6124,-6117,-6109,-6101,
+-6092,-6082,-6072,-6060,-6047,-6033,-6018,-6002,-5984,-5965,-5944,-5922,-5899,-5875,-5851,-5828,-5806,-5785,-5766,-5750,-5736,
+-5725,-5714,-5705,-5695,-5685,-5673,-5659,-5644,-5626,-5608,-5588,-5569,-5551,-5535,-5520,-5508,-5497,-5487,-5476,-5465,-5452,
+-5437,-5418,-5398,-5374,-5350,-5325,-5301,-5279,-5259,-5241,-5225,-5212,-5199,-5186,-5171,-5154,-5134,-5112,-5087,-5061,-5034,
+-5009,-4985,-4965,-4947,-4933,-4921,-4910,-4899,-4886,-4870,-4849,-4824,-4795,-4763,-4728,-4693,-4659,-4627,-4598,-4572,-4550,
+-4528,-4507,-4485,-4459,-4430,-4396,-4358,-4317,-4275,-4235,-4198,-4166,-4141,-4124,-4114,-4110,-4111,-4113,-4114,-4112,-4105,
+-4092,-4072,-4046,-4015,-3981,-3945,-3910,-3876,-3845,-3815,-3788,-3762,-3736,-3710,-3683,-3655,-3626,-3598,-3572,-3547,-3527,
+-3511,-3500,-3493,-3490,-3489,-3488,-3488,-3485,-3479,-3471,-3460,-3446,-3431,-3415,-3399,-3384,-3370,-3359,-3349,-3340,-3333,
+-3327,-3321,-3316,-3311,-3307,-3303,-3299,-3296,-3292,-3287,-3281,-3273,-3264,-3252,-3238,-3222,-3204,-3185,-3165,-3144,-3123,
+-3101,-3079,-3055,-3032,-3007,-2983,-2958,-2933,-2908,-2884,-2861,-2838,-2815,-2792,-2768,-2743,-2715,-2684,-2652,-2617,-2583,
+-2549,-2517,-2489,-2466,-2448,-2435,-2425,-2419,-2413,-2407,-2398,-2387,-2372,-2354,-2334,-2312,-2292,-2273,-2258,-2247,-2239,
+-2234,-2230,-2227,-2222,-2216,-2208,-2198,-2187,-2178,-2171,-2169,-2172,-2181,-2195,-2211,-2228,-2242,-2250,-2248,-2235,-2210,
+-2173,-2125,-2071,-2014,-1958,-1906,-1862,-1829,-1806,-1793,-1787,-1787,-1788,-1789,-1785,-1777,-1762,-1742,-1718,-1693,-1668,
+-1647,-1630,-1619,-1614,-1613,-1614,-1616,-1616,-1613,-1604,-1590,-1572,-1550,-1526,-1503,-1483,-1466,-1454,-1448,-1445,-1445,
+-1446,-1446,-1442,-1434,-1420,-1400,-1374,-1345,-1313,-1280,-1249,-1220,-1194,-1173,-1155,-1139,-1126,-1114,-1100,-1085,-1068,
+-1047,-1023,-996,-967,-936,-903,-871,-839,-808,-777,-746,-716,-684,-651,-615,-575,-532,-485,-435,-383,-330,
+-277,-227,-181,-140,-106,-77,-55,-36,-20,-5,10,29,51,77,107,140,173,206,238,267,292,
+314,332,348,361,372,381,387,389,385,373,352,320,277,224,162,93,22,-49,-115,-176,-226,
+-267,-297,-317,-331,-338,-343,-347,-351,-356,-363,-370,-377,-382,-385,-384,-378,-369,-356,-340,-324,-307,
+-292,-277,-265,-255,-245,-237,-228,-219,-209,-198,-185,-173,-160,-148,-137,-128,-120,-114,-110,-107,-105,
+-103,-101,-99,-96,-94,-92,-91,-90,-91,-93,-97,-103,-109,-117,-125,-134,-142,-151,-159,-166,-174,
+-182,-190,-199,-209,-220,-231,-244,-257,-270,-283,-295,-307,-317,-327,-335,-343,-349,-355,-360,-364,-369,
+-373,-376,-380,-382,-384,-386,-387,-387,-387,-387,-386,-385,-384,-383,-381,-378,-374,-369,-363,-356,-348,
+-339,-329,-319,-309,-300,-291,-283,-277,-272,-267,-263,-260,-258,-255,-252,-248,-244,-240,-234,-228,-221,
+-214,-206,-198,-190,-182,-176,-171,-167,-164,-164,-164,-166,-168,-171,-173,-175,-175,-174,-172,-168,-163,
+-156,-148,-139,-127,-114,-100,-83,-64,-44,-23,-2,18,38,56,73,89,104,119,137,157,183,
+215,252,296,346,399,455,509,561,608,648,680,704,720,729,733,734,733,732,732,734,738,
+744,751,758,766,774,780,786,791,796,801,806,813,821,832,846,864,886,914,946,985,1029,
+1078,1133,1190,1249,1308,1365,1416,1460,1496,1521,1535,1540,1534,1521,1501,1478,1453,1428,1406,1387,1373,
+1364,1359,1357,1359,1364,1369,1376,1382,1387,1393,1398,1402,1408,1310,1326,1343,1363,1384,1407,1431,1457,
+1483,1510,1536,1561,1586,1609,1632,1654,1675,1697,1720,1742,1765,1788,1809,1828,1843,1854,1859,1859,1853,
+1842,1828,1812,1796,1781,1770,1763,1761,1763,1770,1779,1791,1802,1813,1822,1829,1835,1840,1845,1850,1857,
+1867,1878,1891,1905,1918,1929,1936,1940,1940,1937,1931,1924,1919,1917,1919,1925,1936,1950,1966,1982,1997,
+2007,2013,2014,2010,2003,1994,1987,1981,1978,1979,1982,1986,1989,1989,1984,1974,1957,1937,1916,1898,1886,
+1886,1899,1927,1970,2026,2089,2155,2218,2271,2309,2330,2332,2315,2284,2242,2196,2150,2110,2079,2059,2051,
+2051,2059,2070,2080,2087,2088,2084,2075,2062,2049,2037,2030,2029,2035,2047,2066,2088,2111,2133,2152,2166,
+2175,2179,2179,2175,2169,2163,2157,2152,2148,2146,2145,2145,2145,2147,2150,2155,2162,2172,2186,2204,2224,
+2247,2272,2295,2317,2336,2350,2358,2361,2358,2351,2339,2325,2308,2291,2273,2254,2236,2218,2201,2183,2166,
+2150,2136,2122,2112,2103,2098,2096,2097,2100,2105,2112,2120,2127,2135,2142,2148,2153,2156,2159,2160,2159,
+2156,2152,2145,2136,2125,2112,2098,2083,2068,2052,2038,2024,2010,1997,1985,1972,1958,1945,1931,1918,1906,
+1896,1889,1885,1884,1887,1891,1897,1903,1906,1907,1904,1898,1889,1878,1869,1864,1863,1871,1887,1912,1944,
+1983,2023,2064,2100,2129,2148,2158,2156,2146,2129,2108,2086,2065,2049,2036,2029,2027,2027,2030,2032,2033,
+2032,2029,2025,2021,2017,2014,2013,2012,2010,2004,1992,1970,1937,1891,1832,1761,1681,1595,1510,1428,1356,
+1296,1252,1224,1212,1215,1229,1251,1278,1308,1338,1366,1393,1419,1443,1468,1491,1515,1536,1555,1570,1578,
+1579,1571,1556,1533,1504,1473,1440,1410,1384,1362,1347,1336,1329,1324,1319,1311,1300,1285,1266,1244,1220,
+1195,1172,1151,1134,1120,1109,1100,1092,1083,1071,1057,1040,1019,996,972,948,924,903,883,866,849,
+832,814,793,769,741,710,675,640,604,571,542,518,499,486,479,475,473,471,467,460,447,
+429,405,375,341,303,263,223,183,145,109,76,47,20,-4,-26,-48,-71,-94,-119,-147,-179,
+-215,-255,-299,-346,-396,-448,-500,-551,-600,-646,-687,-725,-759,-791,-820,-849,-880,-912,-948,-987,-1029,
+-1075,-1123,-1172,-1221,-1270,-1317,-1363,-1406,-1449,-1491,-1533,-1575,-1618,-1661,-1706,-1751,-1796,-1839,-1882,-1923,-1962,
+-2001,-2040,-2080,-2122,-2168,-2218,-2273,-2333,-2396,-2462,-2529,-2594,-2655,-2711,-2759,-2798,-2828,-2849,-2861,-2866,-2866,
+-2862,-2857,-2852,-2849,-2850,-2854,-2864,-2878,-2896,-2917,-2941,-2965,-2989,-3012,-3033,-3052,-3069,-3084,-3097,-3111,-3125,
+-3140,-3156,-3174,-3194,-3215,-3236,-3258,-3278,-3296,-3313,-3328,-3341,-3354,-3368,-3383,-3402,-3423,-3447,-3475,-3505,-3536,
+-3567,-3596,-3622,-3646,-3667,-3687,-3706,-3726,-3749,-3776,-3808,-3844,-3883,-3922,-3960,-3992,-4016,-4029,-4029,-4017,-3993,
+-3961,-3925,-3888,-3858,-3837,-3829,-3838,-3863,-3903,-3955,-4017,-4082,-4146,-4206,-4257,-4296,-4324,-4341,-4348,-4347,-4340,
+-4332,-4324,-4317,-4314,-4316,-4322,-4333,-4349,-4369,-4393,-4422,-4456,-4495,-4538,-4586,-4637,-4690,-4742,-4793,-4840,-4881,
+-4914,-4939,-4954,-4961,-4961,-4954,-4944,-4931,-4919,-4908,-4901,-4897,-4899,-4905,-4916,-4930,-4948,-4968,-4990,-5013,-5038,
+-5063,-5089,-5115,-5141,-5168,-5196,-5225,-5253,-5283,-5312,-5342,-5372,-5402,-5431,-5461,-5489,-5518,-5545,-5571,-5596,-5619,
+-5641,-5661,-5678,-5693,-5705,-5715,-5722,-5728,-5732,-5735,-5738,-5742,-5746,-5751,-5758,-5765,-5774,-5783,-5792,-5801,-5810,
+-5818,-5826,-5833,-5840,-5846,-5851,-5856,-5859,-5860,-5858,-5853,-5844,-5830,-5812,-5788,-5761,-5729,-5694,-5657,-5618,-5579,
+-5541,-5504,-5470,-5437,-5406,-5378,-5351,-5325,-5300,-5275,-5249,-5222,-5194,-5165,-5138,-5113,-5092,-5078,-5073,-5080,-5101,
+-5138,-5189,-5255,-5333,-5418,-5507,-5594,-5675,-5743,-5797,-5832,-5850,-5851,-5837,-5813,-5783,-5752,-5724,-5703,-5691,-5689,
+-5697,-5712,-5732,-5755,-5777,-5797,-5812,-5821,-5826,-5827,-5825,-5821,-5819,-5819,-5823,-5830,-5842,-5857,-5876,-5897,-5919,
+-5941,-5963,-5983,-6002,-6018,-6033,-6045,-6055,-6063,-6070,-6074,-6077,-6079,-6081,-6082,-6082,-6084,-6086,-6089,-6093,-6100,
+-6108,-6119,-6132,-6147,-6163,-6182,-6203,-6224,-6246,-6268,-6289,-6309,-6329,-6347,-6363,-6379,-6393,-6407,-6422,-6436,-6452,
+-6467,-6484,-6500,-6516,-6531,-6544,-6555,-6563,-6569,-6572,-6573,-6574,-6573,-6572,-6572,-6572,-6573,-6574,-6576,-6576,-6576,
+-6575,-6572,-6568,-6563,-6557,-6552,-6547,-6543,-6541,-6539,-6539,-6540,-6540,-6540,-6539,-6537,-6533,-6527,-6521,-6514,-6506,
+-6499,-6493,-6489,-6485,-6482,-6480,-6478,-6475,-6472,-6468,-6462,-6455,-6448,-6440,-6432,-6424,-6417,-6411,-6406,-6402,-6398,
+-6394,-6389,-6384,-6379,-6372,-6364,-6356,-6347,-6339,-6330,-6322,-6314,-6307,-6300,-6293,-6286,-6279,-6272,-6264,-6255,-6246,
+-6237,-6227,-6217,-6208,-6198,-6189,-6179,-6169,-6159,-6148,-6137,-6125,-6112,-6099,-6085,-6071,-6057,-6042,-6027,-6012,-5995,
+-5978,-5960,-5941,-5921,-5900,-5879,-5857,-5837,-5818,-5801,-5785,-5772,-5760,-5750,-5740,-5730,-5720,-5707,-5693,-5676,-5657,
+-5637,-5616,-5595,-5576,-5558,-5543,-5531,-5521,-5512,-5505,-5498,-5489,-5477,-5463,-5445,-5425,-5401,-5376,-5350,-5324,-5299,
+-5277,-5257,-5238,-5222,-5207,-5192,-5177,-5161,-5144,-5125,-5105,-5085,-5065,-5045,-5027,-5010,-4994,-4978,-4962,-4944,-4923,
+-4899,-4870,-4836,-4799,-4759,-4717,-4675,-4635,-4598,-4565,-4536,-4511,-4488,-4467,-4445,-4420,-4392,-4358,-4320,-4276,-4230,
+-4182,-4136,-4094,-4058,-4029,-4009,-3997,-3992,-3993,-3997,-4001,-4004,-4002,-3996,-3984,-3966,-3944,-3918,-3891,-3864,-3839,
+-3816,-3795,-3777,-3761,-3746,-3732,-3716,-3700,-3682,-3663,-3644,-3624,-3606,-3589,-3575,-3563,-3554,-3548,-3543,-3540,-3537,
+-3533,-3529,-3522,-3514,-3505,-3493,-3481,-3467,-3454,-3440,-3427,-3414,-3403,-3392,-3382,-3373,-3364,-3356,-3347,-3337,-3326,
+-3314,-3301,-3286,-3270,-3253,-3237,-3221,-3207,-3193,-3181,-3170,-3159,-3148,-3136,-3121,-3103,-3081,-3056,-3028,-2997,-2965,
+-2933,-2902,-2872,-2844,-2818,-2792,-2768,-2742,-2715,-2687,-2657,-2626,-2594,-2564,-2536,-2513,-2493,-2479,-2470,-2464,-2459,
+-2454,-2447,-2436,-2420,-2400,-2375,-2347,-2320,-2293,-2271,-2255,-2244,-2240,-2240,-2243,-2246,-2248,-2245,-2237,-2224,-2205,
+-2183,-2160,-2138,-2120,-2106,-2099,-2096,-2097,-2099,-2100,-2096,-2085,-2066,-2038,-2003,-1962,-1920,-1878,-1842,-1812,-1792,
+-1783,-1782,-1789,-1800,-1812,-1823,-1829,-1828,-1821,-1808,-1789,-1768,-1746,-1726,-1710,-1699,-1693,-1691,-1691,-1693,-1693,
+-1691,-1685,-1674,-1659,-1641,-1621,-1601,-1582,-1566,-1552,-1541,-1533,-1525,-1516,-1506,-1493,-1476,-1454,-1429,-1402,-1373,
+-1343,-1316,-1290,-1268,-1248,-1232,-1217,-1203,-1189,-1174,-1157,-1138,-1116,-1091,-1066,-1039,-1011,-985,-959,-934,-909,
+-886,-862,-837,-811,-782,-749,-713,-673,-628,-581,-532,-482,-432,-384,-340,-299,-263,-231,-203,-179,-156,
+-133,-110,-84,-55,-24,9,45,80,115,147,175,198,217,231,242,250,256,261,265,267,265,
+259,246,225,193,151,99,38,-29,-100,-171,-238,-298,-349,-388,-417,-434,-443,-445,-443,-440,-437,
+-436,-438,-442,-447,-452,-457,-458,-457,-451,-441,-428,-413,-396,-378,-361,-346,-331,-318,-306,-295,-283,
+-272,-259,-247,-234,-221,-209,-199,-190,-182,-176,-172,-168,-165,-161,-157,-152,-147,-141,-135,-130,-127,
+-125,-125,-127,-132,-138,-145,-153,-160,-168,-174,-180,-186,-191,-197,-204,-212,-222,-234,-248,-263,-278,
+-294,-309,-324,-337,-348,-358,-367,-375,-383,-390,-398,-406,-414,-423,-431,-439,-446,-452,-456,-459,-461,
+-461,-459,-457,-454,-450,-445,-439,-432,-424,-416,-405,-394,-382,-370,-357,-344,-331,-319,-308,-298,-290,
+-282,-275,-268,-262,-256,-251,-246,-241,-236,-232,-227,-223,-218,-214,-209,-203,-198,-193,-188,-184,-182,
+-180,-181,-183,-187,-191,-196,-200,-203,-204,-203,-198,-191,-181,-167,-151,-133,-113,-92,-69,-46,-22,
+1,25,48,71,92,112,132,151,169,188,208,230,256,286,319,357,398,442,486,529,569,
+604,633,656,671,680,684,685,683,682,682,684,690,698,709,722,734,746,756,762,765,766,
+764,761,758,757,759,766,779,799,826,860,901,948,999,1054,1110,1167,1223,1276,1326,1369,1406,
+1436,1457,1470,1474,1470,1459,1442,1420,1394,1367,1339,1313,1290,1270,1254,1243,1237,1234,1236,1241,1248,
+1258,1269,1281,1295,1310,1237,1263,1291,1320,1350,1380,1411,1441,1470,1497,1523,1546,1567,1586,1603,1619,
+1634,1649,1664,1679,1695,1711,1726,1740,1751,1760,1764,1766,1764,1760,1754,1747,1742,1738,1738,1741,1747,
+1757,1768,1780,1792,1802,1811,1817,1822,1826,1829,1834,1840,1849,1860,1875,1890,1906,1921,1932,1940,1944,
+1942,1937,1930,1921,1914,1910,1911,1917,1929,1945,1965,1986,2005,2022,2035,2042,2043,2040,2032,2023,2012,
+2002,1992,1984,1976,1968,1958,1945,1930,1913,1893,1874,1856,1843,1836,1838,1849,1868,1895,1927,1961,1993,
+2021,2042,2054,2058,2055,2046,2033,2021,2011,2006,2005,2009,2017,2025,2032,2036,2034,2025,2010,1989,1965,
+1940,1918,1900,1890,1887,1893,1907,1925,1946,1967,1985,1999,2007,2009,2005,1998,1987,1975,1964,1954,1947,
+1942,1939,1939,1940,1943,1946,1952,1959,1968,1981,1998,2019,2043,2070,2099,2129,2157,2183,2204,2219,2229,
+2233,2231,2224,2214,2202,2188,2175,2162,2150,2140,2131,2123,2116,2110,2104,2098,2092,2087,2081,2074,2068,
+2061,2054,2047,2039,2031,2023,2015,2008,2002,1997,1994,1993,1994,1996,1999,2003,2006,2008,2009,2009,2006,
+2002,1995,1986,1976,1964,1950,1936,1922,1908,1895,1883,1874,1867,1863,1862,1864,1869,1875,1880,1885,1887,
+1887,1882,1875,1865,1854,1844,1838,1837,1845,1861,1886,1920,1961,2006,2052,2095,2132,2160,2178,2184,2181,
+2169,2150,2129,2107,2088,2073,2063,2059,2059,2062,2067,2071,2073,2072,2069,2062,2054,2045,2035,2025,2015,
+2003,1988,1968,1940,1904,1857,1800,1734,1661,1583,1506,1432,1366,1311,1268,1239,1225,1224,1234,1254,1282,
+1314,1350,1388,1427,1467,1506,1544,1579,1610,1635,1653,1660,1657,1642,1615,1578,1533,1482,1430,1379,1332,
+1292,1260,1237,1221,1211,1205,1200,1193,1185,1172,1155,1135,1113,1091,1069,1050,1035,1022,1013,1006,1000,
+994,986,975,961,945,927,907,887,868,851,835,820,805,790,773,753,729,701,669,635,599,
+563,529,500,476,457,444,436,432,429,426,420,410,395,373,346,312,273,231,187,142,98,
+57,18,-16,-47,-74,-99,-121,-141,-162,-183,-206,-231,-260,-293,-330,-371,-415,-462,-511,-560,-608,
+-654,-697,-736,-772,-805,-835,-863,-891,-919,-950,-983,-1019,-1057,-1099,-1142,-1187,-1233,-1278,-1323,-1367,-1411,
+-1455,-1498,-1543,-1588,-1633,-1679,-1725,-1771,-1815,-1858,-1898,-1936,-1973,-2008,-2043,-2079,-2117,-2159,-2205,-2256,-2312,
+-2372,-2434,-2498,-2561,-2621,-2677,-2726,-2769,-2803,-2830,-2848,-2860,-2866,-2868,-2866,-2864,-2861,-2860,-2862,-2866,-2874,
+-2886,-2900,-2917,-2936,-2956,-2975,-2994,-3012,-3028,-3043,-3057,-3071,-3086,-3102,-3120,-3140,-3163,-3189,-3217,-3246,-3275,
+-3304,-3332,-3358,-3383,-3407,-3430,-3454,-3479,-3505,-3534,-3565,-3597,-3629,-3661,-3691,-3719,-3743,-3764,-3783,-3799,-3816,
+-3834,-3855,-3880,-3908,-3940,-3972,-4004,-4033,-4055,-4068,-4070,-4061,-4042,-4014,-3982,-3950,-3922,-3903,-3898,-3908,-3936,
+-3981,-4040,-4111,-4189,-4267,-4342,-4408,-4461,-4499,-4522,-4529,-4521,-4503,-4477,-4447,-4417,-4390,-4369,-4356,-4352,-4358,
+-4375,-4401,-4435,-4477,-4524,-4574,-4625,-4676,-4724,-4767,-4804,-4835,-4858,-4874,-4883,-4886,-4885,-4881,-4877,-4873,-4870,
+-4871,-4875,-4883,-4894,-4907,-4923,-4941,-4959,-4978,-4996,-5015,-5034,-5054,-5075,-5097,-5121,-5147,-5175,-5205,-5237,-5270,
+-5304,-5338,-5372,-5406,-5438,-5469,-5499,-5527,-5554,-5579,-5603,-5626,-5647,-5666,-5684,-5700,-5715,-5728,-5740,-5750,-5758,
+-5764,-5770,-5774,-5777,-5779,-5781,-5784,-5787,-5791,-5797,-5804,-5813,-5824,-5836,-5850,-5864,-5879,-5893,-5904,-5913,-5919,
+-5920,-5916,-5908,-5895,-5878,-5857,-5833,-5808,-5780,-5752,-5723,-5692,-5660,-5625,-5586,-5544,-5497,-5445,-5387,-5325,-5259,
+-5190,-5121,-5053,-4989,-4931,-4882,-4844,-4820,-4811,-4819,-4844,-4887,-4947,-5023,-5112,-5210,-5315,-5420,-5522,-5616,-5698,
+-5765,-5815,-5847,-5862,-5862,-5850,-5830,-5805,-5780,-5758,-5741,-5732,-5729,-5734,-5743,-5757,-5773,-5788,-5803,-5815,-5825,
+-5832,-5838,-5843,-5848,-5855,-5863,-5874,-5886,-5900,-5914,-5929,-5943,-5957,-5968,-5978,-5987,-5993,-5999,-6003,-6007,-6009,
+-6012,-6014,-6015,-6017,-6019,-6022,-6026,-6032,-6039,-6049,-6061,-6076,-6093,-6113,-6134,-6157,-6180,-6204,-6227,-6250,-6272,
+-6292,-6312,-6329,-6346,-6362,-6376,-6390,-6403,-6416,-6428,-6440,-6452,-6463,-6474,-6484,-6494,-6503,-6511,-6519,-6526,-6532,
+-6539,-6545,-6552,-6558,-6565,-6572,-6579,-6585,-6590,-6594,-6597,-6597,-6595,-6591,-6586,-6580,-6573,-6567,-6561,-6557,-6554,
+-6552,-6552,-6553,-6554,-6554,-6553,-6550,-6546,-6540,-6532,-6523,-6515,-6506,-6499,-6493,-6488,-6485,-6483,-6482,-6481,-6479,
+-6476,-6472,-6465,-6457,-6448,-6439,-6429,-6420,-6413,-6406,-6402,-6399,-6397,-6396,-6395,-6394,-6391,-6388,-6383,-6376,-6368,
+-6360,-6350,-6341,-6332,-6323,-6314,-6307,-6299,-6291,-6284,-6276,-6268,-6260,-6251,-6242,-6232,-6222,-6211,-6201,-6190,-6179,
+-6167,-6155,-6143,-6130,-6117,-6103,-6089,-6074,-6059,-6043,-6026,-6009,-5990,-5971,-5952,-5931,-5910,-5890,-5870,-5851,-5834,
+-5818,-5805,-5793,-5783,-5773,-5765,-5756,-5746,-5734,-5720,-5705,-5687,-5668,-5648,-5628,-5609,-5592,-5577,-5565,-5555,-5547,
+-5540,-5534,-5526,-5517,-5504,-5489,-5470,-5447,-5422,-5394,-5365,-5337,-5309,-5282,-5258,-5236,-5217,-5199,-5184,-5171,-5158,
+-5146,-5135,-5124,-5112,-5100,-5087,-5071,-5054,-5033,-5008,-4979,-4945,-4907,-4864,-4818,-4769,-4720,-4672,-4626,-4584,-4548,
+-4516,-4489,-4467,-4447,-4428,-4408,-4384,-4356,-4322,-4282,-4236,-4187,-4135,-4084,-4035,-3992,-3956,-3928,-3908,-3897,-3893,
+-3894,-3898,-3903,-3907,-3908,-3904,-3897,-3885,-3870,-3852,-3834,-3817,-3801,-3788,-3777,-3769,-3764,-3759,-3755,-3750,-3744,
+-3736,-3725,-3713,-3699,-3685,-3670,-3656,-3645,-3635,-3628,-3623,-3620,-3619,-3619,-3618,-3617,-3614,-3608,-3600,-3588,-3574,
+-3557,-3538,-3517,-3496,-3475,-3455,-3436,-3417,-3400,-3382,-3365,-3348,-3329,-3309,-3289,-3267,-3245,-3224,-3204,-3187,-3173,
+-3161,-3153,-3147,-3142,-3137,-3130,-3120,-3105,-3086,-3063,-3035,-3003,-2970,-2937,-2904,-2873,-2844,-2818,-2794,-2770,-2747,
+-2722,-2696,-2669,-2640,-2610,-2581,-2555,-2532,-2513,-2498,-2488,-2480,-2473,-2465,-2454,-2438,-2417,-2391,-2360,-2326,-2293,
+-2262,-2235,-2215,-2202,-2197,-2198,-2203,-2209,-2213,-2213,-2207,-2194,-2173,-2147,-2116,-2085,-2054,-2026,-2003,-1986,-1972,
+-1963,-1954,-1945,-1933,-1917,-1897,-1873,-1847,-1821,-1797,-1778,-1765,-1761,-1764,-1774,-1789,-1806,-1823,-1836,-1844,-1844,
+-1838,-1825,-1807,-1786,-1765,-1746,-1731,-1721,-1716,-1716,-1719,-1724,-1729,-1733,-1734,-1732,-1727,-1718,-1707,-1695,-1681,
+-1668,-1653,-1638,-1622,-1605,-1584,-1561,-1534,-1505,-1474,-1442,-1411,-1381,-1355,-1332,-1313,-1298,-1285,-1275,-1265,-1254,
+-1241,-1225,-1206,-1184,-1160,-1134,-1108,-1083,-1059,-1037,-1018,-999,-982,-964,-945,-924,-899,-870,-836,-799,-757,
+-713,-667,-621,-575,-530,-488,-449,-413,-380,-349,-320,-291,-262,-232,-201,-167,-132,-96,-59,-24,9,
+40,67,90,109,125,137,148,158,166,174,181,185,185,179,165,140,104,56,-1,-68,-142,
+-219,-295,-365,-428,-479,-518,-545,-559,-564,-560,-552,-541,-532,-524,-519,-518,-519,-522,-525,-527,-526,
+-522,-515,-504,-491,-475,-458,-441,-424,-409,-394,-380,-366,-353,-340,-326,-313,-300,-288,-276,-266,-258,
+-251,-245,-241,-236,-232,-227,-221,-214,-206,-198,-191,-184,-178,-175,-175,-177,-181,-186,-193,-200,-206,
+-211,-215,-218,-221,-223,-226,-230,-237,-245,-256,-269,-284,-300,-317,-332,-347,-360,-372,-382,-391,-399,
+-407,-416,-425,-434,-445,-455,-465,-475,-483,-489,-493,-496,-496,-494,-491,-486,-481,-474,-467,-459,-449,
+-439,-427,-413,-399,-383,-367,-350,-334,-319,-304,-291,-278,-267,-257,-249,-240,-233,-226,-220,-214,-210,
+-206,-203,-201,-200,-199,-198,-197,-195,-194,-192,-190,-189,-188,-188,-190,-194,-199,-204,-210,-216,-219,
+-220,-217,-211,-200,-185,-166,-143,-119,-93,-66,-38,-12,13,39,64,88,112,136,160,185,209,
+234,260,285,311,338,364,391,418,444,470,494,516,535,551,564,573,579,582,584,586,588,
+591,597,606,619,633,649,666,682,695,706,712,715,714,711,707,703,703,706,715,732,755,
+787,825,869,917,968,1021,1073,1124,1172,1217,1257,1292,1322,1347,1365,1379,1386,1387,1382,1371,1355,
+1334,1309,1282,1254,1227,1201,1178,1159,1146,1137,1134,1137,1144,1156,1172,1191,1213,1237,1199,1225,1253,
+1283,1314,1347,1380,1412,1443,1472,1499,1523,1544,1562,1577,1591,1603,1615,1626,1637,1649,1660,1671,1681,
+1689,1696,1700,1701,1701,1699,1697,1696,1696,1698,1704,1713,1725,1739,1754,1769,1784,1797,1808,1816,1822,
+1827,1832,1837,1844,1853,1865,1878,1893,1907,1921,1932,1939,1943,1942,1938,1932,1926,1920,1918,1920,1927,
+1939,1956,1977,1999,2020,2040,2055,2066,2070,2069,2063,2052,2038,2022,2005,1988,1971,1954,1938,1922,1906,
+1891,1876,1863,1852,1844,1840,1840,1844,1852,1863,1875,1888,1900,1909,1917,1921,1925,1927,1931,1936,1945,
+1956,1972,1989,2006,2022,2033,2039,2036,2025,2006,1980,1949,1916,1885,1858,1838,1826,1824,1830,1842,1860,
+1880,1899,1915,1926,1932,1932,1926,1917,1905,1892,1879,1868,1858,1850,1845,1840,1838,1836,1835,1836,1839,
+1846,1857,1872,1892,1916,1945,1976,2009,2041,2070,2095,2114,2128,2135,2137,2133,2126,2116,2105,2095,2086,
+2078,2073,2069,2067,2066,2065,2064,2063,2060,2056,2050,2042,2033,2022,2010,1996,1981,1966,1951,1936,1923,
+1912,1903,1897,1895,1895,1898,1904,1911,1919,1927,1933,1937,1938,1936,1931,1923,1912,1900,1886,1871,1857,
+1844,1833,1824,1819,1816,1816,1818,1822,1827,1832,1835,1837,1836,1832,1825,1817,1807,1799,1793,1792,1797,
+1809,1830,1858,1893,1932,1974,2014,2052,2083,2106,2121,2126,2123,2113,2099,2082,2067,2053,2044,2039,2038,
+2041,2046,2052,2057,2059,2059,2056,2050,2041,2030,2017,2002,1986,1967,1945,1918,1885,1845,1797,1743,1682,
+1617,1549,1483,1420,1364,1317,1281,1256,1243,1241,1250,1268,1294,1326,1363,1404,1448,1493,1538,1581,1620,
+1654,1679,1693,1696,1685,1661,1625,1578,1522,1462,1400,1341,1287,1240,1202,1173,1152,1138,1128,1120,1112,
+1103,1091,1077,1059,1041,1022,1004,989,976,965,957,951,945,938,930,919,906,891,873,855,837,
+820,804,790,776,763,748,732,712,689,662,631,597,562,527,494,464,438,417,401,389,380,
+373,365,355,341,323,299,270,237,199,158,115,72,30,-10,-47,-82,-113,-142,-168,-192,-215,
+-238,-261,-285,-312,-342,-374,-410,-449,-490,-533,-577,-621,-663,-705,-743,-779,-813,-844,-873,-902,-931,
+-960,-991,-1025,-1060,-1097,-1136,-1177,-1218,-1259,-1300,-1342,-1383,-1425,-1468,-1512,-1557,-1604,-1651,-1700,-1748,-1795,
+-1840,-1884,-1924,-1962,-1997,-2032,-2065,-2100,-2136,-2176,-2220,-2268,-2320,-2376,-2434,-2494,-2553,-2610,-2663,-2711,-2753,
+-2789,-2817,-2839,-2854,-2864,-2869,-2871,-2871,-2871,-2870,-2872,-2875,-2881,-2891,-2903,-2918,-2935,-2953,-2972,-2991,-3009,
+-3026,-3042,-3056,-3070,-3085,-3100,-3118,-3138,-3161,-3188,-3217,-3249,-3283,-3318,-3352,-3386,-3418,-3449,-3478,-3507,-3535,
+-3563,-3592,-3621,-3651,-3682,-3712,-3741,-3768,-3793,-3816,-3836,-3855,-3874,-3893,-3914,-3937,-3962,-3990,-4018,-4045,-4069,
+-4088,-4099,-4101,-4094,-4078,-4054,-4027,-3999,-3974,-3957,-3953,-3963,-3990,-4034,-4093,-4164,-4244,-4327,-4408,-4481,-4542,
+-4588,-4617,-4628,-4622,-4601,-4569,-4531,-4489,-4450,-4416,-4392,-4379,-4379,-4392,-4417,-4454,-4499,-4550,-4603,-4657,-4708,
+-4754,-4793,-4824,-4846,-4861,-4868,-4869,-4866,-4861,-4856,-4853,-4852,-4856,-4863,-4875,-4890,-4908,-4928,-4949,-4970,-4990,
+-5010,-5028,-5045,-5063,-5080,-5099,-5119,-5141,-5166,-5193,-5223,-5255,-5288,-5323,-5359,-5394,-5429,-5463,-5496,-5527,-5556,
+-5583,-5608,-5632,-5653,-5673,-5691,-5708,-5723,-5737,-5750,-5762,-5772,-5781,-5788,-5794,-5798,-5802,-5804,-5806,-5808,-5810,
+-5814,-5820,-5828,-5839,-5852,-5868,-5886,-5904,-5922,-5938,-5950,-5958,-5961,-5959,-5950,-5937,-5919,-5898,-5876,-5853,-5831,
+-5810,-5790,-5770,-5750,-5726,-5699,-5664,-5621,-5568,-5504,-5429,-5344,-5251,-5153,-5053,-4956,-4866,-4788,-4724,-4680,-4657,
+-4657,-4681,-4728,-4796,-4883,-4986,-5099,-5218,-5338,-5454,-5562,-5656,-5736,-5798,-5842,-5870,-5881,-5880,-5869,-5852,-5832,
+-5812,-5796,-5783,-5776,-5774,-5777,-5784,-5793,-5803,-5813,-5822,-5830,-5836,-5842,-5848,-5854,-5861,-5869,-5879,-5890,-5902,
+-5915,-5927,-5939,-5949,-5958,-5965,-5970,-5974,-5977,-5979,-5980,-5981,-5981,-5982,-5983,-5984,-5986,-5989,-5994,-6001,-6010,
+-6023,-6038,-6057,-6079,-6103,-6129,-6156,-6183,-6210,-6235,-6259,-6281,-6300,-6318,-6334,-6349,-6363,-6377,-6391,-6405,-6419,
+-6432,-6444,-6455,-6465,-6472,-6478,-6481,-6484,-6485,-6486,-6488,-6490,-6495,-6501,-6510,-6521,-6534,-6549,-6563,-6578,-6590,
+-6601,-6608,-6612,-6612,-6609,-6603,-6595,-6587,-6579,-6571,-6566,-6562,-6561,-6561,-6563,-6566,-6568,-6569,-6568,-6565,-6559,
+-6551,-6541,-6529,-6517,-6506,-6495,-6487,-6480,-6476,-6473,-6471,-6470,-6469,-6467,-6464,-6460,-6454,-6447,-6439,-6431,-6424,
+-6417,-6412,-6409,-6406,-6405,-6405,-6405,-6404,-6402,-6399,-6394,-6388,-6381,-6372,-6363,-6354,-6344,-6335,-6326,-6318,-6309,
+-6301,-6293,-6284,-6275,-6265,-6255,-6244,-6232,-6221,-6209,-6198,-6188,-6178,-6169,-6160,-6151,-6142,-6132,-6121,-6109,-6095,
+-6078,-6059,-6039,-6016,-5991,-5965,-5939,-5914,-5889,-5867,-5846,-5829,-5814,-5802,-5793,-5786,-5781,-5775,-5770,-5763,-5755,
+-5744,-5732,-5717,-5701,-5685,-5667,-5651,-5635,-5620,-5607,-5595,-5584,-5574,-5562,-5550,-5536,-5519,-5499,-5476,-5451,-5422,
+-5392,-5360,-5328,-5296,-5265,-5237,-5210,-5187,-5167,-5150,-5137,-5128,-5121,-5117,-5114,-5111,-5107,-5101,-5090,-5075,-5052,
+-5023,-4985,-4940,-4889,-4833,-4774,-4714,-4655,-4601,-4552,-4511,-4478,-4452,-4433,-4419,-4407,-4395,-4381,-4362,-4336,-4304,
+-4264,-4219,-4168,-4115,-4063,-4013,-3968,-3929,-3898,-3876,-3860,-3852,-3848,-3848,-3849,-3849,-3847,-3842,-3834,-3823,-3809,
+-3794,-3779,-3764,-3751,-3741,-3733,-3729,-3727,-3727,-3728,-3730,-3732,-3732,-3732,-3730,-3726,-3722,-3716,-3711,-3707,-3703,
+-3701,-3700,-3701,-3703,-3706,-3709,-3710,-3709,-3706,-3698,-3686,-3670,-3649,-3624,-3596,-3565,-3534,-3501,-3470,-3440,-3412,
+-3386,-3361,-3338,-3316,-3294,-3272,-3250,-3228,-3206,-3186,-3167,-3151,-3138,-3127,-3119,-3113,-3108,-3103,-3096,-3085,-3071,
+-3053,-3031,-3005,-2977,-2948,-2919,-2891,-2866,-2843,-2823,-2804,-2786,-2768,-2748,-2726,-2701,-2675,-2646,-2618,-2591,-2565,
+-2543,-2525,-2509,-2496,-2483,-2470,-2453,-2433,-2408,-2377,-2343,-2306,-2268,-2232,-2200,-2174,-2154,-2141,-2135,-2132,-2132,
+-2131,-2128,-2120,-2106,-2087,-2062,-2034,-2004,-1974,-1946,-1922,-1901,-1885,-1871,-1860,-1849,-1838,-1826,-1812,-1797,-1782,
+-1768,-1756,-1748,-1746,-1748,-1755,-1765,-1777,-1788,-1796,-1799,-1796,-1787,-1771,-1751,-1727,-1704,-1682,-1664,-1652,-1646,
+-1646,-1653,-1664,-1678,-1693,-1708,-1721,-1731,-1738,-1741,-1741,-1738,-1731,-1721,-1708,-1691,-1669,-1644,-1614,-1580,-1543,
+-1504,-1464,-1425,-1390,-1359,-1333,-1313,-1298,-1288,-1282,-1276,-1271,-1264,-1254,-1240,-1222,-1202,-1179,-1154,-1130,-1106,
+-1085,-1065,-1047,-1031,-1014,-996,-977,-954,-927,-897,-863,-826,-786,-746,-706,-667,-629,-594,-561,-529,-499,
+-469,-439,-408,-374,-339,-303,-265,-226,-188,-151,-116,-85,-57,-33,-13,3,17,30,43,55,68,
+82,94,105,112,113,106,89,61,20,-32,-94,-165,-241,-318,-393,-461,-521,-570,-607,-631,-644,
+-648,-645,-638,-628,-619,-612,-607,-604,-604,-605,-605,-604,-601,-595,-587,-575,-562,-547,-531,-515,-500,
+-485,-471,-458,-445,-431,-418,-404,-390,-376,-363,-350,-340,-330,-323,-317,-312,-308,-303,-298,-293,-286,
+-278,-270,-262,-255,-249,-246,-244,-245,-248,-251,-256,-260,-264,-266,-268,-268,-268,-267,-268,-270,-274,
+-280,-288,-299,-311,-324,-338,-350,-362,-372,-381,-389,-397,-404,-411,-419,-427,-436,-446,-455,-464,-472,
+-477,-481,-483,-482,-479,-476,-470,-465,-458,-451,-443,-435,-425,-413,-400,-385,-368,-350,-330,-310,-290,
+-271,-253,-237,-222,-209,-198,-188,-179,-172,-165,-160,-156,-153,-152,-152,-154,-157,-161,-165,-169,-173,
+-177,-179,-181,-183,-185,-187,-190,-194,-199,-204,-209,-213,-215,-214,-209,-199,-185,-167,-144,-119,-92,
+-64,-36,-10,15,38,60,81,103,124,148,172,199,227,257,287,317,345,371,394,413,428,
+439,446,451,452,452,451,449,449,449,451,456,464,475,489,506,526,547,570,592,613,632,
+648,661,669,674,675,675,674,675,678,684,696,714,738,768,803,843,886,930,976,1020,1063,
+1104,1142,1178,1210,1239,1265,1287,1306,1320,1330,1335,1334,1328,1316,1300,1279,1256,1232,1207,1183,1162,
+1145,1132,1124,1121,1123,1130,1141,1157,1176,1199,1152,1163,1179,1198,1222,1250,1281,1313,1346,1379,1410,
+1438,1463,1484,1502,1517,1529,1539,1548,1557,1565,1574,1583,1592,1600,1607,1614,1619,1623,1626,1629,1632,
+1636,1642,1650,1660,1672,1686,1701,1717,1732,1745,1757,1767,1775,1782,1788,1795,1801,1810,1819,1830,1842,
+1855,1866,1877,1885,1891,1894,1894,1894,1892,1892,1892,1896,1903,1913,1927,1943,1961,1978,1995,2009,2019,
+2025,2027,2024,2017,2007,1994,1979,1963,1946,1930,1913,1898,1884,1871,1860,1851,1845,1842,1842,1844,1848,
+1854,1861,1867,1873,1878,1881,1884,1886,1889,1893,1900,1910,1923,1940,1958,1977,1995,2008,2017,2018,2012,
+1998,1976,1949,1920,1889,1861,1838,1822,1813,1811,1817,1829,1844,1860,1876,1889,1899,1905,1906,1903,1897,
+1889,1880,1871,1862,1854,1846,1839,1831,1823,1816,1809,1803,1800,1801,1806,1816,1832,1852,1878,1906,1936,
+1965,1993,2016,2035,2048,2055,2056,2054,2048,2041,2033,2026,2020,2016,2014,2014,2016,2017,2018,2018,2017,
+2014,2009,2001,1991,1980,1966,1952,1937,1921,1906,1891,1878,1867,1857,1851,1848,1847,1850,1855,1862,1870,
+1878,1885,1890,1893,1893,1889,1883,1873,1861,1847,1833,1819,1805,1793,1782,1775,1769,1766,1764,1764,1764,
+1765,1765,1764,1763,1759,1754,1749,1743,1738,1734,1733,1735,1741,1752,1768,1787,1810,1835,1860,1884,1905,
+1923,1936,1944,1947,1946,1941,1935,1929,1923,1919,1918,1919,1922,1927,1933,1939,1944,1948,1950,1949,1946,
+1941,1933,1923,1909,1892,1871,1845,1813,1775,1730,1680,1625,1567,1507,1449,1393,1343,1301,1267,1243,1228,
+1223,1227,1239,1257,1280,1307,1337,1370,1404,1438,1471,1502,1530,1553,1569,1576,1574,1562,1540,1507,1467,
+1421,1371,1320,1271,1225,1185,1152,1125,1104,1088,1075,1064,1053,1042,1029,1015,1000,984,969,956,944,
+934,926,919,913,907,899,890,879,865,850,834,817,801,785,771,757,745,732,719,704,686,
+665,640,613,583,551,520,490,461,436,414,395,379,364,351,336,319,300,276,249,217,182,
+144,104,63,22,-17,-55,-91,-124,-155,-184,-211,-237,-262,-288,-314,-341,-370,-401,-435,-471,-508,
+-547,-587,-626,-665,-703,-739,-773,-805,-835,-865,-894,-923,-954,-985,-1019,-1054,-1090,-1128,-1167,-1205,-1244,
+-1282,-1320,-1358,-1396,-1434,-1474,-1515,-1558,-1602,-1648,-1694,-1741,-1786,-1830,-1872,-1911,-1949,-1984,-2019,-2054,-2090,
+-2129,-2171,-2217,-2267,-2321,-2377,-2435,-2493,-2550,-2604,-2654,-2698,-2737,-2769,-2795,-2816,-2831,-2842,-2850,-2855,-2859,
+-2864,-2869,-2875,-2883,-2894,-2907,-2923,-2941,-2960,-2981,-3003,-3024,-3045,-3064,-3083,-3100,-3116,-3133,-3150,-3168,-3188,
+-3211,-3236,-3264,-3295,-3327,-3359,-3392,-3423,-3453,-3482,-3508,-3533,-3558,-3581,-3605,-3629,-3655,-3681,-3709,-3736,-3763,
+-3790,-3816,-3840,-3864,-3886,-3909,-3932,-3956,-3980,-4006,-4031,-4056,-4079,-4098,-4111,-4119,-4119,-4112,-4100,-4083,-4065,
+-4049,-4038,-4035,-4043,-4063,-4098,-4145,-4204,-4271,-4343,-4416,-4484,-4545,-4594,-4628,-4648,-4652,-4641,-4619,-4589,-4554,
+-4518,-4485,-4459,-4442,-4437,-4445,-4464,-4495,-4534,-4581,-4631,-4683,-4733,-4778,-4818,-4850,-4874,-4890,-4900,-4903,-4903,
+-4900,-4897,-4895,-4896,-4900,-4907,-4918,-4933,-4950,-4969,-4989,-5010,-5031,-5051,-5070,-5089,-5108,-5126,-5146,-5167,-5189,
+-5213,-5239,-5267,-5297,-5328,-5360,-5393,-5426,-5459,-5491,-5522,-5551,-5579,-5604,-5628,-5649,-5669,-5687,-5703,-5717,-5731,
+-5743,-5755,-5766,-5775,-5784,-5792,-5798,-5803,-5807,-5809,-5812,-5814,-5817,-5821,-5827,-5835,-5846,-5860,-5876,-5893,-5911,
+-5927,-5941,-5950,-5955,-5954,-5947,-5934,-5916,-5895,-5871,-5847,-5824,-5802,-5783,-5766,-5749,-5733,-5714,-5689,-5658,-5617,
+-5564,-5500,-5424,-5338,-5243,-5144,-5044,-4947,-4859,-4785,-4727,-4690,-4676,-4686,-4720,-4776,-4853,-4946,-5052,-5166,-5282,
+-5397,-5505,-5603,-5688,-5757,-5810,-5848,-5870,-5880,-5880,-5872,-5861,-5847,-5834,-5824,-5817,-5814,-5815,-5819,-5825,-5833,
+-5841,-5848,-5855,-5860,-5864,-5868,-5871,-5874,-5878,-5883,-5888,-5895,-5903,-5911,-5919,-5927,-5935,-5942,-5948,-5954,-5959,
+-5963,-5967,-5970,-5974,-5976,-5979,-5982,-5985,-5989,-5994,-6000,-6010,-6022,-6037,-6055,-6076,-6099,-6124,-6150,-6176,-6202,
+-6225,-6247,-6267,-6285,-6301,-6316,-6330,-6345,-6360,-6376,-6393,-6410,-6427,-6444,-6458,-6470,-6479,-6484,-6486,-6484,-6481,
+-6476,-6472,-6468,-6468,-6470,-6477,-6488,-6502,-6519,-6538,-6556,-6574,-6589,-6600,-6606,-6608,-6606,-6599,-6590,-6579,-6567,
+-6557,-6549,-6544,-6542,-6543,-6546,-6552,-6557,-6563,-6566,-6567,-6565,-6560,-6551,-6539,-6526,-6512,-6498,-6485,-6474,-6466,
+-6460,-6457,-6456,-6456,-6457,-6458,-6458,-6458,-6456,-6453,-6449,-6445,-6440,-6435,-6430,-6426,-6422,-6418,-6415,-6412,-6408,
+-6403,-6398,-6391,-6384,-6376,-6367,-6358,-6350,-6342,-6334,-6327,-6321,-6314,-6308,-6300,-6293,-6284,-6274,-6262,-6251,-6238,
+-6226,-6214,-6203,-6193,-6185,-6177,-6171,-6165,-6158,-6151,-6141,-6129,-6114,-6096,-6073,-6048,-6020,-5990,-5959,-5929,-5901,
+-5875,-5853,-5835,-5821,-5811,-5804,-5800,-5797,-5794,-5791,-5786,-5779,-5770,-5758,-5744,-5728,-5711,-5694,-5677,-5661,-5644,
+-5629,-5613,-5596,-5578,-5558,-5536,-5511,-5484,-5453,-5420,-5386,-5350,-5313,-5276,-5241,-5206,-5174,-5144,-5117,-5093,-5073,
+-5056,-5044,-5036,-5032,-5032,-5034,-5038,-5041,-5042,-5039,-5030,-5012,-4985,-4948,-4902,-4846,-4784,-4718,-4651,-4586,-4526,
+-4474,-4432,-4400,-4379,-4366,-4360,-4357,-4355,-4350,-4339,-4321,-4295,-4261,-4220,-4173,-4123,-4074,-4027,-3985,-3950,-3921,
+-3901,-3887,-3878,-3872,-3869,-3865,-3859,-3850,-3838,-3823,-3805,-3786,-3766,-3746,-3728,-3713,-3700,-3691,-3684,-3680,-3679,
+-3679,-3680,-3682,-3685,-3688,-3692,-3696,-3701,-3707,-3713,-3721,-3729,-3738,-3747,-3756,-3764,-3769,-3773,-3774,-3771,-3763,
+-3752,-3735,-3713,-3687,-3657,-3622,-3586,-3547,-3508,-3469,-3431,-3395,-3362,-3331,-3303,-3278,-3254,-3232,-3211,-3191,-3172,
+-3153,-3137,-3121,-3108,-3097,-3087,-3079,-3072,-3065,-3057,-3047,-3035,-3020,-3002,-2981,-2958,-2935,-2912,-2889,-2870,-2852,
+-2838,-2826,-2815,-2804,-2793,-2780,-2764,-2744,-2722,-2697,-2670,-2643,-2616,-2591,-2568,-2547,-2527,-2509,-2489,-2468,-2444,
+-2417,-2386,-2351,-2314,-2276,-2239,-2204,-2172,-2145,-2122,-2103,-2088,-2076,-2063,-2051,-2036,-2019,-2000,-1979,-1956,-1934,
+-1912,-1893,-1876,-1862,-1851,-1841,-1833,-1825,-1816,-1806,-1796,-1785,-1774,-1765,-1758,-1753,-1752,-1753,-1756,-1759,-1761,
+-1761,-1756,-1745,-1729,-1708,-1683,-1655,-1627,-1601,-1579,-1563,-1554,-1552,-1558,-1571,-1588,-1608,-1629,-1650,-1670,-1687,
+-1700,-1710,-1716,-1717,-1715,-1708,-1696,-1679,-1656,-1629,-1596,-1558,-1518,-1476,-1434,-1395,-1359,-1329,-1305,-1288,-1277,
+-1271,-1267,-1266,-1264,-1260,-1252,-1241,-1225,-1205,-1182,-1157,-1131,-1105,-1080,-1056,-1032,-1010,-987,-963,-937,-909,
+-879,-847,-813,-779,-746,-714,-684,-656,-631,-608,-586,-564,-542,-517,-489,-458,-423,-384,-344,-303,-261,
+-222,-186,-154,-127,-105,-87,-74,-63,-54,-47,-39,-31,-23,-15,-8,-5,-7,-15,-31,-57,-93,
+-137,-191,-250,-314,-379,-443,-502,-554,-599,-633,-659,-676,-685,-689,-690,-689,-687,-686,-687,-689,-691,
+-693,-694,-693,-689,-682,-672,-660,-646,-631,-615,-600,-587,-574,-563,-552,-542,-531,-520,-508,-495,-481,
+-466,-452,-438,-426,-416,-408,-401,-396,-392,-389,-385,-380,-375,-368,-361,-354,-347,-341,-337,-333,-332,
+-331,-331,-332,-333,-333,-332,-330,-328,-325,-322,-321,-320,-321,-324,-329,-335,-342,-350,-357,-363,-369,
+-374,-378,-381,-385,-389,-393,-399,-405,-412,-419,-426,-431,-435,-437,-437,-435,-432,-426,-420,-414,-407,
+-401,-394,-386,-378,-369,-357,-343,-327,-308,-287,-265,-242,-219,-197,-177,-158,-142,-128,-117,-107,-100,
+-94,-89,-86,-85,-86,-88,-92,-98,-106,-115,-125,-134,-144,-152,-159,-165,-170,-173,-177,-180,-183,
+-186,-189,-191,-192,-192,-188,-181,-170,-154,-135,-113,-88,-62,-36,-12,10,30,48,64,79,93,
+109,126,146,169,194,221,250,278,304,327,345,359,366,369,367,361,353,345,338,333,332,
+336,344,357,375,398,423,451,479,509,537,563,587,608,626,641,652,661,668,673,678,684,
+691,701,713,729,748,771,797,826,858,892,927,964,1001,1039,1076,1113,1149,1184,1217,1247,1274,
+1298,1317,1330,1339,1341,1339,1331,1320,1304,1287,1268,1248,1229,1211,1194,1179,1166,1156,1149,1144,1143,
+1146,1152,1090,1080,1076,1080,1092,1112,1138,1170,1205,1242,1278,1311,1341,1366,1386,1401,1411,1418,1422,
+1426,1429,1434,1441,1449,1460,1472,1484,1497,1510,1523,1534,1545,1555,1565,1575,1585,1596,1607,1619,1631,
+1643,1655,1666,1677,1686,1695,1703,1711,1719,1727,1736,1746,1756,1766,1776,1786,1795,1803,1809,1814,1819,
+1822,1825,1828,1831,1835,1840,1847,1854,1861,1869,1877,1884,1890,1895,1898,1900,1900,1898,1895,1890,1883,
+1875,1866,1856,1846,1835,1825,1817,1810,1805,1802,1803,1805,1810,1815,1822,1828,1834,1839,1842,1845,1847,
+1849,1852,1857,1863,1871,1880,1891,1901,1910,1916,1918,1916,1908,1896,1880,1861,1840,1820,1803,1789,1780,
+1776,1777,1782,1790,1800,1811,1821,1829,1835,1839,1840,1840,1839,1837,1834,1832,1829,1826,1822,1817,1811,
+1804,1795,1787,1779,1773,1771,1773,1780,1792,1809,1830,1853,1879,1903,1926,1945,1960,1970,1975,1976,1973,
+1969,1964,1959,1955,1953,1953,1955,1958,1962,1966,1969,1970,1968,1963,1956,1946,1933,1918,1902,1885,1868,
+1852,1837,1823,1812,1804,1799,1797,1799,1804,1812,1821,1832,1844,1855,1864,1871,1875,1875,1872,1865,1855,
+1844,1830,1816,1801,1787,1774,1762,1752,1742,1734,1727,1720,1714,1708,1703,1698,1693,1689,1686,1683,1682,
+1682,1683,1685,1687,1691,1694,1698,1701,1704,1706,1707,1708,1707,1707,1706,1704,1703,1703,1703,1704,1707,
+1710,1714,1718,1723,1728,1733,1738,1743,1748,1752,1757,1761,1764,1767,1767,1765,1758,1747,1728,1703,1669,
+1628,1581,1527,1470,1412,1355,1302,1255,1216,1186,1166,1156,1154,1160,1172,1187,1205,1223,1241,1257,1272,
+1285,1296,1305,1312,1318,1321,1321,1318,1312,1301,1286,1266,1243,1217,1190,1161,1133,1107,1082,1061,1042,
+1026,1011,998,985,972,959,945,931,917,903,891,880,870,862,856,850,845,839,833,825,816,
+805,794,782,770,758,746,736,726,716,706,695,682,667,650,630,608,584,560,536,512,490,
+470,451,434,417,401,384,364,342,316,286,253,215,175,132,87,42,-2,-45,-86,-125,-161,
+-194,-225,-254,-282,-309,-335,-362,-390,-419,-450,-483,-517,-553,-589,-625,-661,-695,-729,-761,-791,-821,
+-849,-878,-907,-938,-970,-1003,-1039,-1076,-1114,-1153,-1191,-1230,-1267,-1303,-1338,-1373,-1407,-1442,-1478,-1515,-1553,
+-1593,-1634,-1675,-1716,-1756,-1795,-1832,-1867,-1902,-1935,-1969,-2005,-2043,-2085,-2132,-2182,-2237,-2295,-2355,-2416,-2476,
+-2533,-2586,-2634,-2676,-2712,-2742,-2766,-2786,-2803,-2817,-2830,-2842,-2855,-2868,-2883,-2899,-2917,-2936,-2956,-2978,-3000,
+-3022,-3045,-3068,-3091,-3113,-3135,-3156,-3177,-3198,-3219,-3241,-3263,-3287,-3311,-3337,-3363,-3390,-3417,-3442,-3467,-3489,
+-3510,-3529,-3546,-3561,-3577,-3593,-3611,-3630,-3652,-3676,-3703,-3731,-3760,-3790,-3819,-3847,-3874,-3899,-3923,-3946,-3968,
+-3990,-4012,-4035,-4059,-4082,-4104,-4125,-4143,-4157,-4168,-4174,-4177,-4178,-4177,-4177,-4179,-4187,-4201,-4223,-4253,-4291,
+-4336,-4387,-4441,-4495,-4546,-4592,-4630,-4658,-4675,-4680,-4676,-4662,-4642,-4617,-4592,-4569,-4550,-4538,-4536,-4542,-4559,
+-4585,-4619,-4658,-4702,-4748,-4793,-4835,-4872,-4904,-4930,-4949,-4962,-4970,-4974,-4975,-4975,-4975,-4977,-4980,-4987,-4996,
+-5008,-5023,-5040,-5060,-5080,-5102,-5124,-5147,-5170,-5193,-5217,-5241,-5266,-5291,-5317,-5343,-5370,-5397,-5425,-5452,-5480,
+-5506,-5532,-5556,-5579,-5600,-5620,-5637,-5654,-5669,-5683,-5696,-5709,-5721,-5733,-5745,-5756,-5767,-5778,-5787,-5794,-5800,
+-5805,-5808,-5811,-5812,-5814,-5817,-5822,-5829,-5838,-5849,-5863,-5877,-5892,-5906,-5918,-5926,-5929,-5928,-5920,-5908,-5891,
+-5870,-5847,-5823,-5798,-5774,-5750,-5727,-5703,-5678,-5651,-5618,-5579,-5533,-5479,-5416,-5346,-5271,-5192,-5112,-5036,-4966,
+-4906,-4859,-4828,-4815,-4821,-4846,-4889,-4949,-5022,-5106,-5198,-5293,-5388,-5480,-5565,-5641,-5706,-5759,-5800,-5829,-5848,
+-5858,-5860,-5858,-5852,-5846,-5841,-5837,-5836,-5838,-5843,-5850,-5858,-5868,-5877,-5886,-5893,-5899,-5903,-5906,-5907,-5908,
+-5907,-5907,-5907,-5907,-5908,-5910,-5913,-5916,-5921,-5927,-5934,-5941,-5949,-5957,-5965,-5973,-5981,-5988,-5995,-6001,-6008,
+-6015,-6023,-6033,-6045,-6059,-6075,-6093,-6114,-6135,-6157,-6179,-6200,-6220,-6238,-6254,-6269,-6282,-6296,-6309,-6324,-6340,
+-6358,-6377,-6398,-6420,-6440,-6460,-6476,-6489,-6497,-6501,-6501,-6497,-6490,-6483,-6475,-6470,-6468,-6470,-6476,-6487,-6501,
+-6517,-6535,-6551,-6566,-6577,-6583,-6585,-6581,-6574,-6563,-6549,-6536,-6523,-6512,-6505,-6501,-6502,-6506,-6512,-6521,-6530,
+-6538,-6544,-6547,-6547,-6542,-6535,-6525,-6512,-6499,-6486,-6474,-6464,-6457,-6453,-6451,-6451,-6453,-6456,-6459,-6462,-6464,
+-6465,-6464,-6462,-6459,-6454,-6449,-6443,-6437,-6431,-6425,-6419,-6412,-6406,-6398,-6391,-6382,-6374,-6365,-6357,-6349,-6342,
+-6336,-6330,-6325,-6321,-6317,-6313,-6309,-6303,-6296,-6288,-6278,-6267,-6254,-6242,-6229,-6216,-6205,-6194,-6185,-6176,-6168,
+-6159,-6150,-6138,-6125,-6108,-6089,-6067,-6042,-6016,-5989,-5963,-5939,-5917,-5898,-5883,-5872,-5864,-5859,-5855,-5851,-5846,
+-5838,-5828,-5814,-5797,-5776,-5754,-5730,-5705,-5680,-5656,-5634,-5612,-5591,-5571,-5549,-5525,-5499,-5469,-5436,-5399,-5359,
+-5317,-5274,-5231,-5188,-5147,-5109,-5074,-5042,-5013,-4988,-4966,-4947,-4931,-4919,-4910,-4906,-4904,-4906,-4910,-4916,-4921,
+-4923,-4921,-4912,-4895,-4867,-4830,-4782,-4726,-4665,-4600,-4535,-4475,-4421,-4376,-4342,-4320,-4307,-4302,-4303,-4305,-4307,
+-4304,-4294,-4276,-4251,-4217,-4178,-4136,-4093,-4052,-4016,-3986,-3963,-3947,-3937,-3932,-3929,-3926,-3922,-3915,-3903,-3888,
+-3868,-3846,-3822,-3797,-3774,-3752,-3734,-3718,-3706,-3696,-3688,-3681,-3676,-3671,-3666,-3663,-3661,-3662,-3665,-3672,-3682,
+-3695,-3712,-3730,-3750,-3770,-3787,-3802,-3812,-3817,-3816,-3808,-3794,-3775,-3749,-3719,-3686,-3649,-3610,-3570,-3529,-3489,
+-3450,-3412,-3375,-3341,-3309,-3278,-3249,-3223,-3197,-3174,-3151,-3130,-3110,-3092,-3076,-3062,-3049,-3038,-3029,-3021,-3013,
+-3004,-2995,-2984,-2971,-2955,-2938,-2918,-2898,-2878,-2859,-2842,-2827,-2815,-2806,-2799,-2794,-2789,-2784,-2777,-2767,-2754,
+-2738,-2720,-2698,-2675,-2651,-2626,-2602,-2579,-2556,-2534,-2512,-2489,-2464,-2438,-2410,-2380,-2349,-2316,-2284,-2252,-2220,
+-2191,-2163,-2137,-2112,-2088,-2065,-2042,-2019,-1997,-1975,-1954,-1935,-1919,-1904,-1893,-1884,-1877,-1871,-1866,-1860,-1853,
+-1845,-1835,-1824,-1812,-1801,-1791,-1783,-1777,-1773,-1772,-1771,-1770,-1767,-1761,-1751,-1737,-1717,-1693,-1666,-1639,-1611,
+-1587,-1566,-1552,-1544,-1542,-1547,-1556,-1569,-1584,-1600,-1616,-1630,-1642,-1651,-1657,-1660,-1660,-1656,-1649,-1638,-1622,
+-1602,-1577,-1548,-1515,-1480,-1443,-1407,-1373,-1344,-1319,-1300,-1288,-1280,-1277,-1277,-1277,-1277,-1274,-1266,-1254,-1237,
+-1214,-1188,-1158,-1126,-1093,-1060,-1026,-993,-961,-928,-895,-862,-828,-794,-761,-729,-698,-671,-646,-626,-609,
+-594,-582,-571,-559,-544,-527,-505,-479,-447,-412,-374,-334,-295,-257,-222,-191,-165,-144,-127,-116,-108,
+-104,-102,-102,-106,-111,-120,-134,-152,-176,-206,-243,-285,-333,-384,-437,-489,-540,-586,-626,-659,-685,
+-703,-714,-721,-723,-724,-725,-726,-729,-735,-742,-751,-760,-768,-773,-775,-774,-768,-758,-746,-731,-714,
+-698,-683,-670,-659,-650,-642,-636,-629,-622,-613,-603,-591,-578,-564,-550,-537,-524,-514,-505,-499,-494,
+-490,-487,-484,-480,-476,-470,-464,-457,-451,-444,-438,-433,-429,-426,-423,-420,-417,-413,-409,-405,-400,
+-394,-389,-385,-381,-379,-378,-378,-379,-379,-380,-381,-380,-379,-378,-376,-374,-373,-372,-373,-375,-378,
+-381,-384,-387,-388,-389,-387,-383,-378,-371,-364,-356,-348,-340,-333,-326,-318,-309,-299,-286,-272,-254,
+-234,-212,-189,-166,-142,-120,-100,-83,-68,-56,-46,-39,-33,-30,-28,-28,-29,-32,-37,-44,-53,
+-64,-76,-88,-101,-113,-124,-134,-141,-146,-150,-152,-154,-155,-156,-156,-156,-156,-154,-151,-144,-135,
+-123,-107,-88,-68,-47,-25,-5,12,28,41,51,60,69,77,87,99,114,131,151,172,194,
+214,233,248,259,267,270,270,269,267,266,267,272,282,296,316,339,367,397,428,459,489,
+517,544,567,588,607,624,640,655,669,683,697,711,725,739,753,768,782,798,814,831,850,
+871,895,922,952,985,1021,1059,1099,1140,1180,1218,1254,1286,1313,1335,1352,1363,1369,1370,1367,1361,
+1352,1342,1330,1316,1301,1284,1265,1245,1223,1199,1175,1150,1127,1106,1090,1041,1014,997,989,993,1007,
+1030,1062,1099,1140,1180,1217,1250,1277,1297,1309,1315,1316,1314,1310,1308,1307,1310,1318,1329,1345,1364,
+1386,1408,1430,1451,1471,1488,1502,1515,1525,1535,1543,1552,1561,1570,1581,1592,1604,1616,1628,1640,1652,
+1663,1674,1684,1694,1703,1712,1720,1728,1736,1743,1750,1757,1762,1768,1772,1775,1777,1778,1778,1777,1775,
+1772,1770,1768,1766,1765,1766,1768,1771,1775,1779,1784,1789,1792,1794,1795,1793,1789,1784,1778,1772,1765,
+1760,1755,1753,1753,1755,1759,1764,1769,1774,1779,1783,1786,1788,1789,1790,1790,1790,1791,1792,1793,1793,
+1793,1792,1789,1784,1777,1769,1759,1749,1739,1731,1724,1719,1717,1717,1718,1721,1725,1729,1732,1734,1736,
+1737,1737,1737,1737,1738,1739,1742,1745,1748,1750,1751,1751,1748,1744,1738,1731,1725,1720,1718,1719,1725,
+1735,1749,1767,1788,1810,1831,1851,1868,1881,1891,1896,1897,1896,1893,1889,1887,1885,1885,1887,1891,1896,
+1902,1908,1913,1916,1917,1914,1909,1900,1887,1872,1855,1836,1817,1798,1779,1763,1750,1741,1736,1736,1740,
+1748,1761,1776,1793,1811,1828,1843,1856,1864,1869,1869,1864,1856,1845,1831,1816,1800,1784,1769,1753,1739,
+1725,1712,1699,1687,1676,1666,1657,1650,1645,1642,1641,1642,1645,1649,1653,1656,1657,1656,1652,1644,1632,
+1617,1599,1580,1561,1542,1525,1511,1500,1494,1491,1492,1496,1502,1508,1515,1521,1525,1529,1531,1533,1536,
+1539,1543,1550,1558,1568,1579,1588,1595,1598,1594,1583,1562,1532,1493,1446,1393,1337,1280,1226,1177,1136,
+1105,1084,1073,1072,1079,1091,1107,1124,1139,1150,1158,1160,1157,1150,1139,1126,1112,1098,1085,1072,1062,
+1052,1044,1036,1028,1020,1011,1002,992,981,969,958,946,934,922,910,897,884,871,858,844,830,
+817,805,793,783,774,766,760,754,749,745,740,736,731,726,721,716,710,705,699,693,687,
+679,671,661,650,637,623,607,591,574,558,542,527,514,501,489,477,464,450,432,412,387,
+358,323,284,241,194,144,93,41,-10,-61,-109,-155,-198,-237,-273,-306,-336,-365,-392,-419,-446,
+-473,-502,-531,-562,-593,-625,-657,-689,-721,-751,-781,-811,-840,-869,-899,-930,-963,-997,-1033,-1070,-1109,
+-1147,-1186,-1224,-1260,-1295,-1329,-1361,-1393,-1425,-1456,-1489,-1523,-1558,-1594,-1630,-1667,-1704,-1739,-1773,-1805,-1836,
+-1866,-1896,-1928,-1962,-2000,-2043,-2090,-2143,-2200,-2260,-2322,-2385,-2446,-2503,-2556,-2604,-2645,-2681,-2712,-2738,-2761,
+-2782,-2803,-2824,-2846,-2870,-2895,-2921,-2948,-2975,-3001,-3027,-3052,-3075,-3097,-3118,-3138,-3159,-3179,-3201,-3223,-3247,
+-3272,-3300,-3328,-3357,-3386,-3416,-3444,-3471,-3496,-3518,-3537,-3554,-3567,-3577,-3586,-3594,-3601,-3610,-3621,-3635,-3653,
+-3674,-3699,-3728,-3759,-3792,-3825,-3857,-3888,-3916,-3941,-3964,-3984,-4002,-4019,-4037,-4056,-4077,-4100,-4125,-4152,-4180,
+-4209,-4236,-4261,-4284,-4304,-4320,-4333,-4345,-4355,-4366,-4380,-4396,-4417,-4443,-4473,-4508,-4546,-4586,-4625,-4661,-4693,
+-4719,-4736,-4745,-4746,-4738,-4723,-4704,-4682,-4660,-4641,-4627,-4619,-4620,-4631,-4650,-4678,-4713,-4753,-4797,-4842,-4885,
+-4926,-4961,-4991,-5015,-5032,-5043,-5050,-5053,-5053,-5053,-5054,-5056,-5061,-5069,-5080,-5095,-5114,-5135,-5159,-5184,-5211,
+-5239,-5266,-5294,-5322,-5349,-5375,-5401,-5427,-5451,-5475,-5497,-5519,-5539,-5558,-5576,-5591,-5605,-5618,-5630,-5641,-5651,
+-5661,-5671,-5682,-5694,-5707,-5721,-5735,-5749,-5764,-5777,-5789,-5799,-5807,-5812,-5816,-5819,-5820,-5821,-5823,-5826,-5831,
+-5837,-5847,-5858,-5870,-5884,-5897,-5908,-5917,-5923,-5926,-5924,-5917,-5907,-5893,-5875,-5855,-5831,-5805,-5776,-5744,-5709,
+-5669,-5624,-5574,-5519,-5459,-5395,-5329,-5262,-5196,-5134,-5078,-5030,-4994,-4969,-4959,-4962,-4979,-5009,-5051,-5103,-5164,
+-5230,-5300,-5371,-5441,-5508,-5571,-5628,-5679,-5722,-5757,-5785,-5806,-5821,-5830,-5835,-5837,-5837,-5836,-5836,-5838,-5841,
+-5846,-5853,-5863,-5874,-5886,-5898,-5910,-5921,-5930,-5936,-5941,-5942,-5941,-5938,-5934,-5928,-5922,-5917,-5912,-5909,-5908,
+-5909,-5913,-5918,-5926,-5935,-5946,-5958,-5970,-5982,-5994,-6006,-6018,-6030,-6042,-6055,-6068,-6083,-6100,-6117,-6135,-6154,
+-6172,-6190,-6207,-6223,-6237,-6250,-6261,-6272,-6284,-6296,-6310,-6326,-6344,-6364,-6387,-6410,-6433,-6455,-6475,-6491,-6503,
+-6510,-6512,-6511,-6506,-6499,-6492,-6485,-6480,-6479,-6481,-6486,-6495,-6506,-6518,-6530,-6541,-6548,-6552,-6553,-6548,-6540,
+-6530,-6517,-6504,-6491,-6481,-6473,-6469,-6469,-6472,-6478,-6486,-6495,-6503,-6511,-6516,-6518,-6518,-6514,-6508,-6501,-6492,
+-6483,-6474,-6467,-6462,-6459,-6457,-6458,-6459,-6462,-6465,-6467,-6468,-6468,-6466,-6463,-6459,-6454,-6448,-6442,-6436,-6430,
+-6425,-6420,-6415,-6410,-6405,-6400,-6394,-6387,-6380,-6373,-6365,-6357,-6350,-6343,-6337,-6332,-6327,-6323,-6319,-6315,-6310,
+-6304,-6296,-6287,-6276,-6264,-6250,-6236,-6221,-6207,-6192,-6179,-6166,-6153,-6140,-6128,-6115,-6101,-6086,-6070,-6054,-6037,
+-6020,-6004,-5990,-5977,-5966,-5958,-5951,-5945,-5939,-5932,-5922,-5908,-5890,-5867,-5838,-5805,-5768,-5728,-5687,-5646,-5607,
+-5571,-5538,-5508,-5481,-5456,-5432,-5407,-5381,-5352,-5319,-5283,-5244,-5203,-5160,-5118,-5076,-5038,-5002,-4970,-4942,-4917,
+-4895,-4875,-4858,-4842,-4827,-4814,-4802,-4793,-4786,-4781,-4779,-4779,-4780,-4779,-4776,-4768,-4753,-4731,-4701,-4663,-4617,
+-4567,-4513,-4461,-4411,-4367,-4330,-4303,-4284,-4274,-4269,-4268,-4268,-4266,-4259,-4247,-4227,-4201,-4169,-4134,-4097,-4062,
+-4031,-4005,-3985,-3972,-3964,-3961,-3961,-3961,-3959,-3954,-3946,-3933,-3916,-3895,-3873,-3850,-3829,-3809,-3792,-3777,-3765,
+-3754,-3744,-3734,-3723,-3711,-3699,-3686,-3674,-3664,-3658,-3657,-3662,-3673,-3690,-3713,-3738,-3765,-3791,-3813,-3830,-3839,
+-3840,-3832,-3815,-3789,-3756,-3718,-3677,-3633,-3589,-3546,-3504,-3466,-3430,-3396,-3365,-3335,-3307,-3279,-3251,-3224,-3196,
+-3168,-3140,-3113,-3087,-3063,-3040,-3020,-3003,-2987,-2975,-2964,-2954,-2944,-2935,-2925,-2913,-2899,-2884,-2867,-2848,-2829,
+-2810,-2792,-2775,-2761,-2749,-2740,-2734,-2730,-2727,-2724,-2721,-2717,-2711,-2703,-2692,-2679,-2663,-2646,-2627,-2607,-2586,
+-2566,-2545,-2523,-2502,-2481,-2459,-2437,-2414,-2391,-2368,-2344,-2320,-2294,-2268,-2241,-2213,-2185,-2155,-2125,-2095,-2065,
+-2038,-2012,-1989,-1970,-1955,-1943,-1935,-1929,-1924,-1920,-1916,-1910,-1902,-1891,-1879,-1865,-1850,-1836,-1823,-1813,-1805,
+-1801,-1799,-1798,-1798,-1797,-1794,-1787,-1777,-1764,-1746,-1726,-1705,-1683,-1662,-1644,-1630,-1619,-1611,-1608,-1607,-1608,
+-1611,-1613,-1616,-1617,-1617,-1615,-1613,-1609,-1604,-1597,-1588,-1577,-1563,-1546,-1526,-1503,-1477,-1449,-1421,-1393,-1368,
+-1346,-1328,-1316,-1309,-1305,-1305,-1307,-1308,-1308,-1304,-1295,-1280,-1260,-1234,-1203,-1168,-1130,-1090,-1049,-1008,-968,
+-928,-888,-850,-813,-776,-740,-707,-675,-647,-622,-601,-584,-571,-561,-554,-549,-543,-536,-526,-513,-496,
+-474,-448,-418,-386,-352,-318,-285,-254,-226,-202,-182,-167,-157,-153,-154,-162,-176,-196,-224,-259,-301,
+-349,-403,-460,-520,-579,-636,-688,-734,-772,-800,-819,-829,-832,-827,-819,-809,-799,-790,-785,-785,-788,
+-795,-805,-815,-826,-835,-840,-842,-839,-832,-822,-808,-794,-779,-765,-752,-742,-734,-728,-723,-718,-713,
+-708,-700,-691,-680,-668,-655,-642,-630,-619,-610,-603,-597,-592,-589,-586,-582,-578,-573,-568,-562,-555,
+-548,-542,-536,-530,-526,-521,-517,-513,-508,-502,-496,-488,-480,-472,-464,-456,-449,-442,-437,-432,-428,
+-424,-420,-416,-411,-405,-399,-393,-387,-381,-376,-372,-369,-367,-365,-363,-361,-358,-354,-348,-340,-332,
+-323,-313,-303,-294,-285,-276,-267,-258,-248,-237,-224,-209,-191,-172,-152,-131,-109,-89,-70,-53,-39,
+-27,-18,-11,-6,-3,-2,-1,-2,-4,-8,-13,-20,-29,-40,-51,-64,-76,-88,-98,-107,-113,
+-117,-118,-118,-117,-115,-113,-112,-111,-111,-110,-110,-107,-104,-97,-89,-78,-64,-50,-34,-19,-4,
+8,18,27,33,38,43,48,53,60,69,80,92,106,120,134,148,161,173,185,196,208,
+222,238,256,279,304,333,364,396,428,460,489,515,539,559,576,591,604,618,632,648,667,
+688,711,736,763,789,815,838,860,879,895,909,922,935,949,966,986,1009,1037,1070,1105,1143,
+1182,1221,1257,1289,1317,1339,1356,1367,1373,1375,1373,1370,1365,1360,1354,1348,1340,1331,1318,1302,1280,
+1254,1222,1187,1149,1111,1074,1041,1007,976,953,942,942,954,976,1008,1046,1088,1130,1169,1203,1230,
+1249,1260,1264,1262,1256,1248,1241,1236,1237,1242,1253,1270,1291,1316,1343,1370,1396,1420,1441,1458,1472,
+1482,1491,1498,1505,1512,1521,1531,1543,1556,1571,1587,1603,1619,1635,1648,1661,1671,1680,1688,1694,1700,
+1706,1711,1717,1722,1728,1734,1739,1743,1746,1748,1747,1745,1740,1735,1728,1722,1715,1710,1707,1706,1707,
+1711,1716,1723,1731,1739,1746,1752,1756,1757,1757,1754,1750,1745,1739,1734,1730,1728,1727,1727,1729,1732,
+1735,1739,1742,1744,1746,1747,1747,1746,1744,1741,1739,1735,1731,1727,1723,1718,1713,1707,1702,1696,1692,
+1688,1684,1682,1681,1680,1680,1679,1679,1678,1676,1673,1670,1667,1663,1661,1659,1660,1662,1665,1670,1676,
+1682,1687,1691,1692,1691,1688,1682,1675,1667,1659,1654,1651,1652,1657,1667,1680,1697,1715,1735,1754,1772,
+1788,1800,1809,1815,1818,1818,1817,1815,1813,1812,1812,1814,1817,1822,1828,1834,1840,1845,1848,1848,1845,
+1839,1829,1816,1799,1780,1760,1739,1719,1701,1687,1678,1674,1676,1684,1697,1715,1737,1759,1782,1803,1821,
+1834,1843,1845,1843,1835,1823,1808,1791,1772,1754,1735,1718,1701,1686,1672,1658,1646,1634,1623,1614,1607,
+1602,1599,1599,1601,1604,1608,1613,1615,1615,1612,1604,1590,1572,1550,1523,1495,1466,1438,1413,1392,1375,
+1364,1358,1356,1358,1362,1367,1372,1376,1379,1381,1381,1381,1381,1383,1387,1394,1404,1417,1430,1444,1455,
+1462,1462,1455,1439,1413,1378,1336,1289,1238,1188,1140,1098,1064,1039,1024,1018,1020,1029,1041,1055,1067,
+1076,1081,1079,1072,1060,1043,1022,1001,980,960,942,928,918,910,905,902,901,899,897,893,889,
+883,875,866,857,846,836,825,814,802,791,780,768,756,745,733,722,711,701,693,685,678,
+673,669,667,665,664,664,663,663,661,659,655,650,644,636,626,616,604,592,579,567,555,
+544,534,524,516,507,499,490,479,466,450,431,407,379,347,309,268,223,174,123,70,16,
+-36,-89,-140,-189,-234,-277,-317,-353,-386,-417,-446,-473,-499,-525,-551,-577,-603,-630,-658,-686,-715,
+-744,-773,-802,-832,-863,-895,-928,-963,-999,-1037,-1075,-1114,-1153,-1191,-1229,-1264,-1298,-1329,-1359,-1388,-1416,
+-1444,-1473,-1503,-1535,-1568,-1603,-1638,-1674,-1709,-1743,-1775,-1805,-1834,-1862,-1890,-1920,-1952,-1987,-2027,-2073,-2123,
+-2177,-2235,-2295,-2355,-2413,-2469,-2520,-2566,-2607,-2644,-2675,-2704,-2731,-2757,-2784,-2812,-2842,-2874,-2907,-2940,-2974,
+-3007,-3037,-3065,-3090,-3112,-3132,-3150,-3168,-3185,-3204,-3224,-3247,-3273,-3302,-3334,-3367,-3402,-3436,-3470,-3501,-3529,
+-3554,-3574,-3590,-3602,-3611,-3617,-3621,-3625,-3629,-3636,-3646,-3659,-3677,-3699,-3726,-3756,-3788,-3822,-3857,-3890,-3921,
+-3950,-3975,-3997,-4016,-4033,-4049,-4065,-4081,-4100,-4122,-4147,-4175,-4206,-4239,-4273,-4306,-4338,-4367,-4393,-4415,-4433,
+-4448,-4461,-4473,-4485,-4500,-4517,-4538,-4563,-4592,-4624,-4658,-4692,-4724,-4753,-4775,-4791,-4798,-4798,-4789,-4774,-4753,
+-4731,-4708,-4688,-4673,-4666,-4667,-4677,-4697,-4727,-4763,-4805,-4850,-4896,-4940,-4981,-5017,-5047,-5070,-5086,-5097,-5103,
+-5106,-5108,-5109,-5112,-5117,-5125,-5137,-5153,-5172,-5194,-5219,-5245,-5273,-5301,-5330,-5358,-5385,-5411,-5437,-5462,-5486,
+-5508,-5530,-5550,-5568,-5584,-5599,-5612,-5622,-5631,-5639,-5645,-5651,-5657,-5664,-5672,-5682,-5694,-5707,-5722,-5737,-5753,
+-5769,-5784,-5797,-5808,-5817,-5823,-5828,-5830,-5832,-5833,-5835,-5837,-5841,-5847,-5855,-5864,-5875,-5887,-5898,-5909,-5919,
+-5927,-5933,-5936,-5937,-5935,-5930,-5922,-5910,-5893,-5872,-5844,-5810,-5768,-5720,-5664,-5601,-5533,-5462,-5389,-5318,-5250,
+-5190,-5139,-5100,-5075,-5063,-5066,-5082,-5111,-5150,-5197,-5250,-5307,-5364,-5421,-5475,-5525,-5572,-5613,-5650,-5682,-5710,
+-5734,-5754,-5771,-5784,-5795,-5803,-5809,-5814,-5817,-5820,-5822,-5826,-5830,-5837,-5845,-5855,-5868,-5882,-5896,-5911,-5925,
+-5937,-5947,-5954,-5957,-5957,-5953,-5947,-5939,-5929,-5919,-5909,-5901,-5895,-5892,-5892,-5895,-5901,-5910,-5921,-5934,-5948,
+-5964,-5980,-5996,-6013,-6030,-6047,-6065,-6083,-6102,-6120,-6138,-6155,-6172,-6187,-6201,-6213,-6224,-6234,-6243,-6252,-6261,
+-6272,-6285,-6301,-6318,-6339,-6361,-6384,-6407,-6429,-6449,-6466,-6479,-6488,-6493,-6494,-6491,-6487,-6481,-6476,-6471,-6469,
+-6469,-6472,-6477,-6483,-6490,-6497,-6503,-6507,-6509,-6507,-6503,-6496,-6487,-6478,-6469,-6460,-6454,-6449,-6447,-6448,-6451,
+-6456,-6461,-6467,-6472,-6476,-6479,-6480,-6478,-6476,-6472,-6468,-6463,-6460,-6457,-6456,-6456,-6457,-6459,-6462,-6465,-6467,
+-6468,-6468,-6466,-6462,-6456,-6450,-6442,-6435,-6427,-6420,-6415,-6410,-6408,-6406,-6406,-6406,-6407,-6408,-6408,-6406,-6403,
+-6399,-6393,-6386,-6378,-6369,-6360,-6351,-6342,-6334,-6326,-6319,-6312,-6305,-6297,-6288,-6279,-6268,-6257,-6244,-6230,-6216,
+-6201,-6187,-6173,-6160,-6147,-6135,-6123,-6112,-6101,-6090,-6080,-6069,-6059,-6050,-6041,-6033,-6025,-6017,-6009,-5999,-5986,
+-5970,-5949,-5923,-5891,-5853,-5809,-5760,-5707,-5651,-5595,-5541,-5489,-5442,-5400,-5364,-5332,-5305,-5281,-5259,-5237,-5213,
+-5188,-5160,-5129,-5096,-5062,-5028,-4995,-4965,-4937,-4913,-4892,-4873,-4857,-4842,-4826,-4809,-4791,-4771,-4750,-4728,-4707,
+-4687,-4670,-4656,-4646,-4638,-4633,-4629,-4624,-4616,-4605,-4588,-4566,-4538,-4506,-4471,-4435,-4399,-4366,-4336,-4312,-4293,
+-4278,-4267,-4257,-4247,-4235,-4220,-4200,-4176,-4147,-4116,-4084,-4052,-4022,-3997,-3977,-3963,-3954,-3949,-3947,-3947,-3946,
+-3943,-3937,-3928,-3915,-3900,-3883,-3866,-3849,-3835,-3822,-3812,-3804,-3797,-3789,-3781,-3769,-3755,-3737,-3717,-3697,-3676,
+-3658,-3645,-3639,-3639,-3648,-3665,-3688,-3715,-3745,-3773,-3797,-3815,-3823,-3822,-3810,-3787,-3755,-3716,-3672,-3625,-3577,
+-3531,-3488,-3449,-3414,-3384,-3356,-3332,-3308,-3286,-3262,-3238,-3211,-3183,-3154,-3124,-3094,-3064,-3036,-3011,-2987,-2967,
+-2949,-2934,-2921,-2910,-2899,-2887,-2876,-2863,-2848,-2832,-2814,-2795,-2775,-2756,-2737,-2719,-2703,-2689,-2677,-2668,-2662,
+-2658,-2655,-2653,-2651,-2649,-2646,-2642,-2637,-2629,-2620,-2608,-2595,-2581,-2565,-2549,-2532,-2514,-2497,-2480,-2463,-2447,
+-2431,-2414,-2397,-2379,-2359,-2337,-2312,-2286,-2256,-2225,-2192,-2159,-2127,-2096,-2068,-2043,-2023,-2007,-1995,-1986,-1980,
+-1975,-1971,-1966,-1959,-1949,-1937,-1923,-1907,-1890,-1874,-1859,-1847,-1838,-1832,-1829,-1828,-1828,-1829,-1829,-1826,-1821,
+-1813,-1802,-1788,-1772,-1755,-1738,-1721,-1705,-1691,-1678,-1668,-1658,-1650,-1643,-1636,-1629,-1622,-1614,-1607,-1600,-1593,
+-1585,-1577,-1568,-1557,-1545,-1529,-1512,-1492,-1470,-1447,-1424,-1402,-1382,-1366,-1354,-1346,-1343,-1343,-1345,-1349,-1351,
+-1351,-1346,-1337,-1321,-1299,-1270,-1237,-1199,-1159,-1116,-1073,-1030,-987,-947,-907,-869,-832,-797,-763,-730,-699,
+-671,-645,-622,-603,-588,-576,-568,-561,-557,-552,-548,-541,-532,-519,-503,-483,-460,-434,-406,-376,-347,
+-319,-294,-272,-255,-244,-240,-245,-258,-280,-311,-351,-400,-455,-516,-580,-645,-708,-768,-821,-866,-902,
+-927,-942,-947,-944,-935,-922,-906,-891,-877,-868,-862,-861,-863,-869,-876,-884,-890,-895,-897,-895,-890,
+-882,-872,-860,-849,-838,-829,-821,-814,-810,-805,-801,-797,-792,-785,-776,-766,-755,-743,-732,-721,-712,
+-704,-697,-692,-689,-686,-683,-679,-675,-670,-664,-658,-650,-643,-636,-629,-624,-619,-615,-611,-607,-602,
+-596,-589,-581,-571,-560,-548,-537,-525,-514,-504,-496,-488,-481,-474,-468,-461,-454,-447,-438,-430,-421,
+-411,-402,-394,-386,-379,-371,-364,-357,-349,-341,-331,-321,-310,-299,-288,-277,-267,-256,-246,-237,-227,
+-217,-206,-193,-180,-165,-149,-132,-114,-98,-82,-67,-54,-43,-35,-28,-22,-18,-16,-14,-12,-12,
+-13,-16,-20,-25,-33,-42,-52,-63,-74,-84,-92,-99,-103,-104,-103,-100,-96,-91,-86,-83,-80,
+-80,-80,-81,-82,-83,-83,-81,-77,-71,-62,-53,-42,-30,-20,-10,-2,3,8,11,13,14,
+16,19,22,27,34,43,54,67,82,100,120,144,170,199,232,267,305,344,383,422,459,
+492,522,547,567,582,594,603,611,619,630,644,663,687,716,750,786,824,863,899,932,961,
+985,1004,1019,1031,1040,1049,1059,1072,1089,1109,1133,1161,1190,1220,1249,1276,1298,1315,1327,1333,1335,
+1332,1327,1321,1314,1309,1305,1303,1301,1299,1296,1289,1278,1260,1236,1206,1169,1129,1087,1045,1007,968,
+938,916,903,901,909,928,955,989,1026,1065,1101,1133,1159,1178,1189,1194,1193,1189,1182,1176,1172,
+1172,1176,1186,1200,1219,1242,1267,1292,1316,1339,1358,1375,1388,1398,1406,1413,1419,1425,1433,1443,1454,
+1468,1483,1500,1517,1534,1550,1564,1577,1588,1597,1605,1611,1616,1621,1626,1632,1638,1645,1653,1660,1668,
+1675,1681,1685,1688,1688,1687,1685,1681,1678,1674,1671,1670,1671,1673,1677,1682,1689,1696,1703,1709,1714,
+1718,1719,1720,1718,1716,1713,1710,1707,1705,1704,1704,1704,1706,1708,1711,1714,1717,1720,1722,1724,1725,
+1725,1725,1724,1723,1720,1718,1714,1710,1706,1701,1696,1691,1686,1680,1675,1671,1666,1661,1655,1650,1644,
+1637,1630,1624,1617,1612,1608,1605,1605,1608,1613,1620,1628,1637,1646,1654,1659,1662,1661,1656,1647,1636,
+1622,1607,1593,1581,1571,1566,1564,1568,1577,1590,1606,1625,1644,1664,1682,1698,1711,1721,1726,1729,1728,
+1725,1721,1716,1711,1708,1707,1708,1711,1716,1722,1729,1735,1740,1742,1740,1734,1724,1710,1692,1672,1651,
+1631,1613,1600,1593,1591,1597,1609,1627,1650,1675,1701,1725,1747,1763,1773,1777,1775,1767,1753,1737,1718,
+1698,1679,1660,1643,1629,1615,1604,1593,1583,1574,1564,1555,1547,1539,1533,1528,1525,1523,1522,1522,1522,
+1520,1516,1508,1497,1481,1462,1439,1413,1387,1360,1335,1312,1294,1280,1270,1265,1264,1265,1269,1274,1279,
+1283,1288,1291,1294,1298,1303,1309,1316,1324,1333,1342,1350,1354,1354,1348,1336,1316,1289,1256,1218,1176,
+1134,1093,1056,1024,999,982,972,969,972,977,985,992,997,998,994,986,974,959,941,922,904,
+888,875,865,858,855,853,853,854,853,852,849,844,836,827,817,806,795,784,774,765,757,
+750,743,736,728,719,710,700,689,678,668,658,649,642,637,634,632,632,633,634,634,633,
+631,627,621,612,602,591,579,567,555,545,535,527,520,514,508,502,494,484,472,456,436,
+411,383,350,314,275,234,191,146,101,55,10,-34,-79,-123,-166,-208,-249,-288,-326,-363,-397,
+-430,-461,-490,-517,-544,-569,-593,-618,-641,-666,-690,-715,-741,-767,-795,-824,-855,-887,-921,-957,-995,
+-1035,-1075,-1116,-1156,-1196,-1234,-1269,-1303,-1333,-1362,-1388,-1413,-1438,-1463,-1489,-1516,-1546,-1578,-1611,-1646,-1681,
+-1716,-1751,-1783,-1814,-1843,-1872,-1900,-1928,-1959,-1993,-2030,-2072,-2117,-2167,-2220,-2274,-2329,-2383,-2435,-2483,-2527,
+-2567,-2603,-2635,-2665,-2694,-2723,-2752,-2783,-2816,-2850,-2885,-2920,-2955,-2989,-3020,-3048,-3074,-3096,-3117,-3136,-3154,
+-3173,-3193,-3216,-3241,-3270,-3301,-3334,-3369,-3404,-3439,-3472,-3502,-3529,-3552,-3571,-3587,-3598,-3607,-3614,-3620,-3626,
+-3632,-3640,-3651,-3664,-3681,-3700,-3723,-3748,-3776,-3805,-3835,-3865,-3894,-3923,-3950,-3975,-3998,-4020,-4041,-4061,-4082,
+-4103,-4125,-4148,-4173,-4199,-4226,-4253,-4280,-4307,-4332,-4356,-4377,-4397,-4414,-4431,-4448,-4465,-4483,-4505,-4529,-4556,
+-4587,-4620,-4655,-4690,-4724,-4754,-4779,-4799,-4811,-4816,-4814,-4806,-4792,-4776,-4758,-4742,-4730,-4724,-4724,-4733,-4750,
+-4774,-4806,-4842,-4881,-4922,-4961,-4998,-5031,-5059,-5082,-5099,-5113,-5122,-5130,-5137,-5145,-5154,-5165,-5179,-5196,-5215,
+-5237,-5260,-5285,-5309,-5334,-5359,-5382,-5405,-5427,-5449,-5470,-5492,-5513,-5534,-5555,-5575,-5594,-5611,-5627,-5641,-5653,
+-5662,-5670,-5676,-5682,-5687,-5693,-5700,-5708,-5717,-5728,-5740,-5753,-5767,-5780,-5792,-5803,-5812,-5819,-5824,-5827,-5830,
+-5832,-5833,-5835,-5838,-5841,-5845,-5850,-5856,-5863,-5869,-5876,-5882,-5888,-5893,-5899,-5904,-5909,-5913,-5916,-5917,-5915,
+-5909,-5898,-5880,-5853,-5818,-5773,-5720,-5660,-5593,-5523,-5453,-5385,-5324,-5272,-5232,-5206,-5194,-5198,-5216,-5246,-5287,
+-5334,-5386,-5439,-5491,-5539,-5582,-5619,-5649,-5674,-5693,-5708,-5720,-5730,-5739,-5747,-5755,-5763,-5771,-5779,-5786,-5793,
+-5798,-5803,-5808,-5813,-5819,-5825,-5834,-5844,-5856,-5869,-5884,-5899,-5913,-5926,-5937,-5945,-5949,-5950,-5947,-5941,-5932,
+-5921,-5910,-5898,-5888,-5880,-5874,-5871,-5871,-5875,-5882,-5892,-5904,-5919,-5935,-5954,-5973,-5993,-6014,-6036,-6057,-6078,
+-6098,-6117,-6135,-6150,-6163,-6175,-6184,-6191,-6198,-6203,-6209,-6216,-6225,-6236,-6250,-6266,-6285,-6306,-6328,-6349,-6370,
+-6388,-6404,-6416,-6424,-6428,-6429,-6427,-6423,-6419,-6414,-6411,-6409,-6409,-6411,-6415,-6420,-6424,-6429,-6432,-6433,-6433,
+-6430,-6426,-6421,-6415,-6409,-6404,-6400,-6398,-6398,-6400,-6404,-6409,-6413,-6418,-6421,-6423,-6423,-6422,-6419,-6416,-6412,
+-6408,-6406,-6405,-6407,-6410,-6416,-6423,-6432,-6440,-6448,-6455,-6460,-6463,-6462,-6459,-6453,-6445,-6436,-6426,-6416,-6406,
+-6399,-6393,-6389,-6387,-6388,-6390,-6393,-6397,-6401,-6404,-6406,-6406,-6405,-6401,-6395,-6388,-6379,-6369,-6359,-6349,-6338,
+-6328,-6319,-6310,-6301,-6292,-6284,-6275,-6267,-6258,-6248,-6239,-6229,-6220,-6211,-6202,-6194,-6186,-6179,-6172,-6165,-6157,
+-6149,-6140,-6129,-6118,-6105,-6090,-6074,-6056,-6037,-6015,-5990,-5962,-5931,-5895,-5855,-5810,-5761,-5707,-5650,-5591,-5531,
+-5473,-5416,-5363,-5316,-5274,-5238,-5208,-5182,-5160,-5140,-5121,-5102,-5080,-5057,-5031,-5003,-4974,-4945,-4918,-4892,-4869,
+-4850,-4834,-4821,-4809,-4798,-4785,-4770,-4752,-4730,-4704,-4674,-4643,-4611,-4580,-4552,-4528,-4510,-4497,-4490,-4488,-4488,
+-4490,-4492,-4492,-4488,-4481,-4469,-4453,-4433,-4411,-4388,-4364,-4341,-4318,-4296,-4274,-4252,-4229,-4204,-4177,-4148,-4116,
+-4084,-4051,-4020,-3991,-3965,-3945,-3929,-3917,-3910,-3906,-3904,-3902,-3899,-3893,-3886,-3875,-3862,-3848,-3834,-3821,-3810,
+-3801,-3794,-3790,-3788,-3785,-3781,-3775,-3765,-3751,-3732,-3710,-3685,-3661,-3638,-3619,-3606,-3601,-3604,-3615,-3633,-3656,
+-3682,-3707,-3729,-3746,-3755,-3754,-3744,-3724,-3695,-3658,-3617,-3573,-3529,-3486,-3446,-3409,-3377,-3348,-3323,-3300,-3278,
+-3257,-3235,-3211,-3187,-3160,-3133,-3105,-3077,-3051,-3025,-3002,-2981,-2962,-2946,-2931,-2918,-2905,-2893,-2880,-2866,-2851,
+-2834,-2817,-2798,-2779,-2759,-2740,-2721,-2703,-2686,-2672,-2659,-2648,-2640,-2633,-2627,-2624,-2621,-2619,-2617,-2615,-2612,
+-2609,-2604,-2598,-2590,-2581,-2570,-2558,-2545,-2531,-2517,-2502,-2488,-2474,-2459,-2445,-2430,-2413,-2395,-2375,-2353,-2328,
+-2301,-2271,-2241,-2210,-2179,-2150,-2124,-2100,-2081,-2065,-2053,-2044,-2037,-2031,-2026,-2019,-2011,-2000,-1988,-1973,-1957,
+-1941,-1924,-1909,-1896,-1885,-1877,-1871,-1867,-1864,-1861,-1858,-1854,-1847,-1838,-1827,-1813,-1798,-1782,-1765,-1748,-1733,
+-1718,-1705,-1693,-1683,-1674,-1666,-1659,-1653,-1647,-1642,-1637,-1633,-1628,-1622,-1615,-1607,-1597,-1585,-1569,-1552,-1532,
+-1511,-1490,-1468,-1449,-1433,-1420,-1412,-1408,-1408,-1411,-1417,-1422,-1427,-1428,-1424,-1415,-1400,-1378,-1350,-1316,-1278,
+-1237,-1195,-1152,-1110,-1070,-1031,-995,-960,-927,-895,-863,-833,-803,-774,-746,-720,-696,-674,-655,-639,-626,
+-615,-606,-598,-590,-581,-570,-558,-543,-525,-505,-483,-460,-437,-416,-398,-384,-377,-376,-383,-399,-424,
+-458,-500,-549,-603,-661,-720,-778,-833,-883,-926,-960,-985,-1001,-1008,-1008,-1001,-990,-977,-963,-950,-939,
+-932,-928,-927,-930,-934,-940,-944,-948,-950,-949,-946,-940,-933,-924,-916,-907,-900,-895,-891,-888,-885,
+-883,-881,-877,-871,-864,-855,-845,-834,-822,-811,-801,-793,-787,-783,-780,-779,-778,-777,-775,-772,-768,
+-762,-755,-747,-738,-729,-721,-714,-708,-703,-698,-694,-689,-683,-676,-668,-657,-645,-632,-618,-604,-590,
+-577,-566,-555,-546,-538,-530,-523,-515,-507,-498,-488,-478,-466,-454,-442,-430,-418,-407,-396,-385,-375,
+-365,-355,-345,-334,-323,-312,-301,-290,-280,-270,-260,-250,-241,-232,-222,-212,-201,-189,-177,-164,-152,
+-139,-127,-117,-107,-98,-91,-85,-80,-75,-71,-68,-66,-65,-65,-66,-68,-73,-79,-87,-95,-105,
+-114,-122,-129,-133,-135,-134,-131,-126,-119,-111,-104,-97,-92,-89,-87,-87,-89,-91,-92,-93,-93,
+-91,-87,-81,-73,-65,-56,-48,-40,-34,-29,-26,-25,-25,-25,-26,-26,-24,-21,-15,-7,5,
+21,41,66,95,128,165,205,248,292,336,379,420,457,491,519,542,560,574,585,595,605,
+617,633,653,679,710,746,787,829,873,916,955,990,1020,1044,1061,1073,1081,1086,1089,1093,1099,
+1108,1120,1135,1153,1172,1191,1209,1224,1235,1242,1244,1242,1236,1228,1218,1209,1202,1197,1196,1196,1199,
+1202,1204,1203,1198,1187,1169,1144,1114,1079,1041,1003,968,925,898,876,860,853,854,863,879,901,
+926,953,980,1005,1026,1043,1055,1062,1065,1065,1064,1062,1062,1063,1068,1076,1087,1101,1118,1137,1156,
+1175,1193,1209,1223,1235,1245,1254,1261,1268,1276,1283,1292,1302,1313,1326,1339,1353,1367,1380,1393,1404,
+1415,1425,1433,1441,1448,1456,1463,1472,1480,1490,1500,1511,1521,1532,1542,1550,1558,1565,1570,1574,1577,
+1579,1581,1583,1585,1588,1592,1596,1601,1606,1612,1618,1623,1628,1632,1635,1638,1640,1642,1644,1645,1647,
+1649,1651,1654,1657,1661,1665,1669,1673,1677,1681,1684,1688,1691,1694,1696,1698,1699,1700,1700,1698,1696,
+1693,1688,1682,1675,1666,1657,1646,1635,1622,1609,1596,1582,1568,1555,1542,1531,1521,1514,1510,1509,1511,
+1517,1526,1537,1551,1565,1580,1592,1602,1609,1611,1607,1599,1586,1568,1548,1526,1504,1483,1466,1454,1447,
+1446,1451,1462,1478,1498,1521,1544,1567,1587,1603,1615,1622,1623,1620,1613,1603,1591,1580,1570,1562,1558,
+1557,1560,1565,1572,1579,1585,1589,1589,1586,1578,1565,1550,1532,1514,1498,1485,1477,1476,1481,1494,1512,
+1536,1562,1590,1617,1641,1659,1672,1678,1677,1671,1659,1644,1626,1608,1591,1575,1562,1550,1541,1533,1525,
+1517,1508,1498,1486,1473,1458,1444,1430,1417,1405,1396,1388,1382,1377,1373,1367,1360,1351,1339,1324,1307,
+1287,1267,1246,1226,1208,1193,1182,1175,1173,1175,1180,1189,1200,1213,1227,1242,1256,1270,1283,1294,1303,
+1310,1313,1313,1307,1297,1281,1259,1232,1200,1165,1126,1087,1049,1012,980,953,932,917,908,903,903,
+904,907,908,907,902,894,883,868,852,835,818,803,792,783,779,777,779,782,787,790,793,
+793,790,785,776,766,755,743,732,722,714,708,704,701,699,697,695,691,686,678,670,660,
+649,638,629,621,615,611,610,610,612,613,614,613,610,604,595,584,571,557,543,530,519,
+511,506,504,504,505,505,504,499,490,473,450,418,379,333,282,226,167,108,51,-4,-56,
+-103,-145,-183,-217,-247,-274,-300,-325,-350,-375,-401,-427,-454,-481,-509,-536,-563,-589,-614,-638,-661,
+-684,-706,-728,-751,-774,-798,-824,-851,-881,-912,-946,-982,-1020,-1060,-1101,-1142,-1182,-1222,-1260,-1295,-1329,
+-1359,-1387,-1413,-1438,-1462,-1486,-1511,-1537,-1565,-1594,-1625,-1658,-1691,-1724,-1756,-1788,-1818,-1847,-1876,-1904,-1933,
+-1964,-1996,-2032,-2071,-2113,-2159,-2207,-2257,-2307,-2357,-2405,-2452,-2495,-2535,-2572,-2607,-2639,-2671,-2702,-2733,-2764,
+-2796,-2829,-2863,-2896,-2929,-2961,-2991,-3020,-3047,-3072,-3096,-3120,-3144,-3168,-3194,-3221,-3250,-3280,-3311,-3344,-3375,
+-3406,-3435,-3463,-3488,-3510,-3529,-3546,-3561,-3575,-3587,-3598,-3609,-3619,-3629,-3639,-3650,-3661,-3672,-3684,-3697,-3711,
+-3728,-3745,-3765,-3788,-3813,-3840,-3869,-3900,-3932,-3964,-3996,-4026,-4056,-4083,-4108,-4130,-4150,-4169,-4185,-4200,-4214,
+-4227,-4241,-4255,-4270,-4287,-4305,-4326,-4349,-4375,-4405,-4437,-4472,-4509,-4549,-4590,-4631,-4671,-4709,-4744,-4775,-4801,
+-4821,-4835,-4844,-4847,-4846,-4842,-4837,-4832,-4828,-4827,-4830,-4838,-4850,-4867,-4888,-4912,-4938,-4964,-4990,-5015,-5038,
+-5058,-5076,-5092,-5107,-5121,-5135,-5151,-5168,-5187,-5208,-5230,-5255,-5280,-5305,-5330,-5354,-5376,-5396,-5414,-5430,-5446,
+-5460,-5475,-5491,-5507,-5525,-5544,-5565,-5586,-5607,-5629,-5649,-5667,-5684,-5698,-5709,-5719,-5726,-5732,-5737,-5742,-5747,
+-5753,-5759,-5765,-5773,-5780,-5787,-5794,-5801,-5806,-5810,-5814,-5816,-5817,-5818,-5819,-5819,-5819,-5819,-5819,-5819,-5818,
+-5817,-5816,-5814,-5813,-5813,-5814,-5816,-5820,-5826,-5833,-5842,-5850,-5857,-5860,-5859,-5852,-5837,-5814,-5781,-5741,-5692,
+-5639,-5583,-5527,-5475,-5429,-5393,-5369,-5357,-5359,-5375,-5402,-5439,-5482,-5529,-5577,-5623,-5663,-5698,-5725,-5744,-5756,
+-5762,-5763,-5761,-5757,-5753,-5751,-5750,-5752,-5756,-5762,-5770,-5779,-5787,-5796,-5804,-5812,-5819,-5827,-5835,-5843,-5852,
+-5862,-5873,-5885,-5896,-5907,-5916,-5924,-5929,-5931,-5930,-5926,-5920,-5911,-5901,-5890,-5880,-5870,-5863,-5857,-5854,-5854,
+-5857,-5863,-5872,-5883,-5898,-5914,-5933,-5954,-5976,-5999,-6023,-6046,-6068,-6089,-6107,-6123,-6136,-6146,-6153,-6157,-6160,
+-6162,-6163,-6166,-6171,-6178,-6188,-6201,-6216,-6234,-6252,-6271,-6288,-6303,-6316,-6324,-6329,-6330,-6328,-6324,-6318,-6312,
+-6306,-6302,-6300,-6300,-6301,-6305,-6309,-6314,-6318,-6321,-6323,-6322,-6320,-6316,-6312,-6307,-6303,-6301,-6300,-6301,-6304,
+-6309,-6315,-6322,-6328,-6333,-6336,-6337,-6336,-6334,-6330,-6326,-6323,-6321,-6321,-6325,-6331,-6341,-6354,-6369,-6386,-6402,
+-6418,-6431,-6442,-6449,-6452,-6452,-6447,-6441,-6432,-6422,-6412,-6403,-6395,-6390,-6386,-6384,-6384,-6385,-6387,-6389,-6391,
+-6391,-6390,-6388,-6384,-6379,-6372,-6365,-6357,-6349,-6341,-6334,-6327,-6321,-6315,-6309,-6303,-6296,-6290,-6283,-6276,-6268,
+-6260,-6253,-6246,-6240,-6235,-6231,-6228,-6225,-6223,-6220,-6217,-6211,-6204,-6193,-6178,-6160,-6138,-6111,-6080,-6046,-6008,
+-5967,-5923,-5876,-5828,-5778,-5726,-5672,-5618,-5563,-5508,-5455,-5403,-5353,-5307,-5265,-5228,-5196,-5168,-5145,-5124,-5106,
+-5088,-5069,-5049,-5026,-4999,-4970,-4937,-4903,-4868,-4834,-4802,-4773,-4748,-4728,-4711,-4697,-4686,-4674,-4662,-4647,-4628,
+-4605,-4577,-4546,-4512,-4478,-4444,-4414,-4388,-4369,-4356,-4350,-4350,-4356,-4366,-4378,-4391,-4401,-4409,-4413,-4412,-4406,
+-4395,-4380,-4361,-4338,-4311,-4283,-4252,-4219,-4184,-4147,-4110,-4072,-4035,-4000,-3966,-3937,-3912,-3892,-3877,-3867,-3861,
+-3859,-3858,-3858,-3857,-3853,-3847,-3838,-3826,-3812,-3796,-3781,-3768,-3757,-3749,-3745,-3743,-3744,-3746,-3747,-3746,-3741,
+-3733,-3719,-3701,-3679,-3656,-3632,-3610,-3592,-3578,-3571,-3571,-3577,-3588,-3603,-3620,-3636,-3649,-3657,-3659,-3654,-3641,
+-3621,-3595,-3565,-3530,-3494,-3458,-3421,-3387,-3354,-3323,-3294,-3267,-3241,-3216,-3191,-3166,-3142,-3118,-3095,-3073,-3053,
+-3034,-3017,-3001,-2987,-2975,-2963,-2951,-2939,-2926,-2912,-2896,-2880,-2862,-2844,-2825,-2806,-2788,-2770,-2753,-2737,-2723,
+-2710,-2697,-2686,-2676,-2666,-2658,-2650,-2642,-2635,-2629,-2623,-2618,-2613,-2607,-2602,-2596,-2590,-2582,-2574,-2564,-2553,
+-2541,-2529,-2516,-2502,-2488,-2474,-2459,-2444,-2428,-2411,-2393,-2374,-2354,-2332,-2310,-2287,-2263,-2240,-2218,-2198,-2179,
+-2163,-2149,-2137,-2127,-2118,-2109,-2100,-2090,-2079,-2067,-2054,-2039,-2024,-2008,-1993,-1979,-1966,-1955,-1945,-1936,-1928,
+-1920,-1912,-1903,-1892,-1880,-1866,-1850,-1834,-1816,-1799,-1782,-1766,-1751,-1739,-1728,-1720,-1713,-1709,-1705,-1704,-1703,
+-1702,-1702,-1702,-1701,-1700,-1697,-1692,-1684,-1674,-1662,-1646,-1629,-1610,-1589,-1569,-1551,-1534,-1522,-1514,-1510,-1511,
+-1515,-1523,-1532,-1542,-1549,-1552,-1551,-1543,-1528,-1507,-1479,-1445,-1407,-1366,-1324,-1282,-1241,-1202,-1166,-1133,-1101,
+-1072,-1043,-1015,-987,-959,-929,-899,-869,-839,-809,-780,-753,-727,-703,-682,-662,-643,-625,-607,-589,-571,
+-553,-535,-519,-504,-493,-486,-484,-490,-504,-526,-556,-596,-642,-695,-752,-812,-871,-927,-979,-1024,-1060,
+-1087,-1103,-1110,-1107,-1097,-1081,-1061,-1039,-1018,-1000,-985,-975,-970,-969,-973,-979,-987,-995,-1002,-1007,-1009,
+-1008,-1004,-998,-991,-982,-974,-967,-961,-958,-956,-956,-957,-957,-957,-955,-951,-945,-937,-927,-915,-904,
+-892,-882,-874,-868,-864,-863,-863,-864,-865,-865,-864,-862,-858,-851,-843,-834,-825,-815,-806,-797,-790,
+-783,-777,-770,-764,-756,-747,-737,-725,-712,-698,-684,-669,-656,-643,-631,-621,-612,-603,-595,-587,-578,
+-569,-558,-546,-533,-519,-505,-491,-477,-464,-452,-440,-430,-420,-411,-402,-393,-383,-374,-364,-354,-345,
+-335,-325,-316,-307,-299,-291,-283,-275,-268,-259,-251,-243,-234,-226,-218,-210,-203,-197,-191,-186,-181,
+-177,-174,-171,-169,-168,-168,-168,-170,-173,-177,-182,-187,-193,-199,-203,-207,-208,-207,-204,-199,-192,
+-183,-174,-165,-156,-149,-143,-140,-138,-137,-138,-139,-140,-141,-140,-139,-135,-130,-124,-117,-109,-102,
+-95,-89,-84,-80,-77,-75,-74,-72,-70,-66,-60,-52,-40,-24,-5,18,46,77,112,150,190,
+230,271,311,348,383,414,442,467,488,508,526,545,565,588,614,644,678,715,756,798,840,
+881,919,953,981,1004,1020,1031,1037,1039,1039,1039,1039,1041,1045,1053,1062,1074,1086,1097,1107,1115,
+1119,1119,1116,1109,1101,1091,1082,1074,1069,1067,1069,1073,1080,1088,1095,1099,1100,1096,1085,1069,1046,
+1019,988,956,925,897,872,850,831,818,810,807,810,817,828,841,856,871,885,898,908,917,
+924,929,933,937,941,945,951,958,966,976,987,999,1012,1025,1038,1051,1064,1076,1088,1099,1109,
+1119,1129,1138,1147,1156,1166,1175,1184,1193,1203,1212,1222,1231,1241,1252,1262,1273,1284,1295,1307,1319,
+1331,1343,1354,1365,1376,1386,1395,1404,1412,1420,1427,1434,1441,1447,1454,1461,1468,1475,1482,1489,1495,
+1502,1508,1514,1519,1524,1529,1533,1538,1543,1549,1555,1562,1569,1577,1585,1593,1600,1607,1614,1620,1625,
+1629,1632,1635,1637,1639,1640,1642,1643,1645,1646,1646,1646,1645,1643,1639,1633,1625,1615,1602,1587,1570,
+1551,1530,1509,1487,1465,1444,1424,1407,1393,1382,1375,1373,1375,1382,1393,1407,1424,1443,1462,1480,1495,
+1507,1514,1516,1511,1502,1486,1467,1445,1421,1397,1376,1358,1345,1339,1339,1346,1359,1378,1401,1425,1451,
+1474,1495,1510,1520,1524,1521,1513,1501,1485,1468,1451,1436,1424,1416,1412,1412,1415,1420,1425,1430,1433,
+1433,1430,1423,1413,1401,1388,1376,1368,1363,1364,1372,1385,1405,1429,1457,1486,1514,1539,1561,1576,1586,
+1589,1587,1580,1569,1557,1543,1530,1518,1508,1500,1493,1486,1479,1470,1460,1446,1430,1411,1390,1367,1345,
+1323,1302,1285,1270,1259,1250,1244,1239,1235,1229,1223,1214,1202,1188,1172,1155,1137,1120,1105,1094,1087,
+1085,1088,1098,1113,1132,1156,1182,1210,1238,1264,1287,1305,1319,1325,1324,1316,1299,1275,1244,1207,1166,
+1121,1075,1031,988,950,917,890,870,856,848,844,843,843,844,842,838,830,818,802,784,764,
+744,725,708,694,685,680,678,680,684,689,694,697,698,697,692,685,676,665,655,646,638,
+633,631,630,632,635,638,640,640,639,635,628,619,609,599,590,582,576,573,573,575,578,
+581,584,584,582,576,566,553,538,521,504,490,478,471,469,472,478,488,498,506,510,507,
+495,473,438,392,335,268,194,115,35,-43,-118,-186,-246,-297,-339,-372,-397,-415,-429,-440,-449,
+-459,-470,-483,-499,-518,-538,-561,-585,-610,-634,-659,-683,-706,-728,-750,-771,-793,-814,-837,-861,-886,
+-913,-942,-972,-1005,-1040,-1076,-1113,-1151,-1190,-1228,-1265,-1301,-1336,-1369,-1401,-1431,-1459,-1487,-1514,-1541,-1568,
+-1595,-1623,-1652,-1680,-1709,-1738,-1766,-1795,-1822,-1850,-1877,-1905,-1933,-1964,-1996,-2030,-2067,-2107,-2149,-2193,-2239,
+-2286,-2333,-2380,-2426,-2470,-2512,-2553,-2593,-2631,-2667,-2703,-2738,-2772,-2806,-2839,-2871,-2903,-2933,-2962,-2991,-3019,
+-3046,-3073,-3100,-3128,-3156,-3186,-3216,-3247,-3279,-3310,-3340,-3370,-3397,-3422,-3445,-3465,-3484,-3501,-3516,-3531,-3546,
+-3561,-3577,-3592,-3608,-3622,-3636,-3647,-3657,-3665,-3670,-3673,-3676,-3679,-3682,-3689,-3699,-3713,-3734,-3759,-3790,-3826,
+-3866,-3907,-3949,-3990,-4028,-4062,-4090,-4114,-4131,-4143,-4151,-4155,-4158,-4161,-4165,-4171,-4181,-4196,-4216,-4240,-4270,
+-4305,-4343,-4385,-4429,-4475,-4523,-4570,-4616,-4662,-4705,-4745,-4783,-4816,-4846,-4871,-4892,-4909,-4922,-4932,-4939,-4943,
+-4947,-4950,-4952,-4956,-4960,-4966,-4973,-4981,-4991,-5001,-5012,-5024,-5036,-5050,-5064,-5080,-5097,-5116,-5138,-5162,-5188,
+-5216,-5245,-5276,-5306,-5336,-5364,-5389,-5412,-5431,-5447,-5460,-5471,-5480,-5489,-5498,-5509,-5521,-5535,-5553,-5572,-5594,
+-5617,-5641,-5665,-5687,-5707,-5725,-5740,-5752,-5761,-5768,-5772,-5775,-5776,-5778,-5779,-5780,-5782,-5785,-5788,-5792,-5795,
+-5798,-5801,-5803,-5804,-5804,-5803,-5800,-5797,-5792,-5785,-5778,-5770,-5761,-5753,-5744,-5736,-5730,-5726,-5725,-5727,-5732,
+-5740,-5750,-5761,-5773,-5784,-5792,-5795,-5793,-5784,-5767,-5743,-5713,-5677,-5639,-5599,-5562,-5529,-5504,-5488,-5482,-5489,
+-5506,-5533,-5569,-5610,-5654,-5699,-5741,-5777,-5807,-5829,-5842,-5847,-5845,-5837,-5825,-5812,-5797,-5785,-5774,-5768,-5765,
+-5765,-5769,-5776,-5785,-5796,-5807,-5818,-5830,-5841,-5851,-5861,-5870,-5880,-5888,-5896,-5903,-5909,-5913,-5915,-5915,-5913,
+-5909,-5903,-5895,-5887,-5877,-5867,-5858,-5850,-5844,-5839,-5836,-5836,-5838,-5842,-5849,-5859,-5871,-5885,-5902,-5921,-5942,
+-5964,-5988,-6012,-6035,-6057,-6078,-6096,-6110,-6121,-6129,-6133,-6134,-6134,-6133,-6131,-6131,-6133,-6138,-6145,-6155,-6167,
+-6180,-6194,-6207,-6218,-6226,-6231,-6232,-6229,-6223,-6215,-6205,-6195,-6185,-6178,-6173,-6170,-6171,-6173,-6178,-6184,-6189,
+-6194,-6198,-6200,-6200,-6199,-6196,-6193,-6191,-6189,-6189,-6190,-6193,-6198,-6204,-6211,-6217,-6222,-6226,-6227,-6227,-6225,
+-6223,-6220,-6218,-6219,-6223,-6230,-6242,-6258,-6277,-6300,-6324,-6348,-6371,-6392,-6409,-6423,-6431,-6435,-6436,-6432,-6427,
+-6420,-6413,-6407,-6402,-6398,-6396,-6396,-6397,-6397,-6398,-6397,-6395,-6391,-6385,-6377,-6367,-6357,-6347,-6337,-6329,-6322,
+-6317,-6314,-6313,-6312,-6313,-6314,-6313,-6312,-6308,-6303,-6295,-6286,-6275,-6263,-6251,-6239,-6228,-6219,-6211,-6205,-6199,
+-6194,-6188,-6181,-6171,-6157,-6139,-6116,-6087,-6052,-6012,-5966,-5917,-5865,-5810,-5753,-5697,-5640,-5585,-5532,-5481,-5432,
+-5386,-5344,-5305,-5269,-5237,-5209,-5184,-5163,-5144,-5127,-5112,-5096,-5079,-5060,-5037,-5010,-4979,-4943,-4904,-4861,-4816,
+-4770,-4726,-4685,-4647,-4613,-4585,-4562,-4543,-4527,-4513,-4499,-4485,-4468,-4448,-4425,-4399,-4371,-4342,-4313,-4286,-4262,
+-4243,-4230,-4224,-4223,-4228,-4238,-4251,-4266,-4281,-4294,-4305,-4312,-4315,-4311,-4303,-4288,-4268,-4243,-4213,-4179,-4141,
+-4101,-4059,-4017,-3976,-3937,-3902,-3871,-3846,-3827,-3815,-3808,-3807,-3810,-3815,-3821,-3827,-3829,-3829,-3823,-3814,-3800,
+-3783,-3765,-3746,-3729,-3715,-3704,-3699,-3697,-3700,-3705,-3712,-3718,-3722,-3722,-3717,-3707,-3693,-3674,-3652,-3628,-3605,
+-3583,-3565,-3552,-3543,-3540,-3541,-3545,-3552,-3560,-3567,-3571,-3572,-3569,-3560,-3546,-3527,-3504,-3476,-3445,-3412,-3377,
+-3341,-3305,-3270,-3235,-3202,-3170,-3141,-3115,-3091,-3070,-3053,-3038,-3027,-3017,-3010,-3004,-2998,-2992,-2984,-2975,-2964,
+-2950,-2935,-2917,-2897,-2877,-2857,-2838,-2819,-2802,-2788,-2775,-2764,-2754,-2746,-2738,-2730,-2722,-2713,-2703,-2693,-2681,
+-2670,-2658,-2646,-2635,-2624,-2614,-2605,-2596,-2588,-2580,-2572,-2563,-2554,-2544,-2533,-2521,-2508,-2495,-2482,-2468,-2454,
+-2441,-2427,-2414,-2400,-2387,-2374,-2360,-2347,-2333,-2320,-2306,-2292,-2279,-2265,-2252,-2238,-2224,-2210,-2196,-2181,-2166,
+-2151,-2135,-2120,-2105,-2090,-2076,-2064,-2052,-2042,-2032,-2022,-2013,-2003,-1992,-1979,-1965,-1950,-1933,-1914,-1895,-1875,
+-1856,-1838,-1821,-1806,-1793,-1783,-1775,-1770,-1766,-1765,-1765,-1766,-1768,-1770,-1772,-1773,-1773,-1772,-1770,-1765,-1757,
+-1748,-1736,-1721,-1705,-1689,-1672,-1655,-1641,-1630,-1623,-1620,-1621,-1627,-1636,-1648,-1660,-1672,-1681,-1686,-1685,-1678,
+-1664,-1642,-1615,-1581,-1544,-1504,-1463,-1423,-1384,-1348,-1316,-1286,-1259,-1235,-1211,-1188,-1164,-1138,-1110,-1079,-1045,
+-1009,-971,-932,-892,-852,-813,-775,-739,-705,-673,-644,-617,-593,-572,-555,-543,-536,-537,-545,-562,-588,
+-623,-668,-722,-783,-850,-920,-990,-1058,-1122,-1177,-1222,-1256,-1276,-1284,-1279,-1264,-1239,-1208,-1173,-1137,-1102,
+-1072,-1047,-1030,-1019,-1015,-1018,-1025,-1035,-1046,-1057,-1066,-1072,-1075,-1075,-1071,-1065,-1057,-1049,-1042,-1036,-1031,
+-1029,-1029,-1030,-1031,-1032,-1032,-1031,-1027,-1021,-1013,-1004,-993,-982,-971,-962,-954,-948,-944,-943,-942,-942,
+-942,-942,-941,-937,-933,-926,-919,-910,-901,-891,-882,-873,-864,-856,-848,-840,-831,-822,-811,-800,-788,
+-775,-761,-748,-735,-723,-712,-702,-692,-683,-675,-666,-657,-647,-636,-624,-611,-597,-582,-568,-554,-541,
+-529,-519,-509,-501,-494,-487,-480,-473,-465,-457,-448,-438,-429,-419,-410,-401,-393,-386,-380,-374,-369,
+-365,-360,-356,-352,-347,-343,-338,-334,-330,-327,-324,-321,-319,-317,-316,-315,-314,-314,-313,-312,-312,
+-311,-311,-311,-310,-309,-308,-306,-303,-299,-293,-287,-279,-271,-262,-252,-243,-235,-228,-222,-218,-216,
+-216,-216,-218,-220,-222,-223,-223,-221,-218,-213,-207,-199,-190,-180,-170,-160,-150,-141,-133,-125,-118,
+-110,-103,-94,-84,-72,-57,-40,-20,2,28,56,86,119,152,185,219,251,282,312,340,368,
+394,421,448,476,507,539,574,611,650,691,731,770,807,841,870,894,913,926,934,939,940,
+940,939,938,939,942,948,956,965,975,985,994,1001,1004,1005,1002,997,989,981,972,965,960,
+958,959,964,972,983,994,1005,1014,1019,1020,1016,1007,992,972,949,923,897,855,834,815,797,
+782,770,762,757,756,757,762,768,776,786,795,806,816,826,835,844,853,862,869,877,884,
+891,898,906,913,921,930,939,950,961,973,986,1000,1013,1027,1040,1053,1064,1075,1084,1092,1100,
+1106,1113,1119,1126,1134,1143,1153,1164,1177,1191,1206,1221,1236,1250,1264,1276,1287,1297,1305,1312,1318,
+1324,1330,1336,1342,1349,1356,1365,1374,1384,1394,1404,1414,1423,1431,1438,1445,1450,1455,1460,1465,1471,
+1477,1484,1493,1503,1514,1525,1537,1549,1561,1571,1580,1587,1592,1595,1597,1597,1596,1595,1593,1591,1590,
+1589,1589,1590,1590,1591,1590,1588,1584,1577,1567,1554,1538,1519,1496,1472,1445,1418,1391,1365,1341,1319,
+1301,1288,1279,1275,1276,1281,1291,1304,1321,1338,1356,1374,1389,1401,1410,1414,1413,1407,1397,1383,1366,
+1347,1328,1310,1295,1285,1279,1278,1284,1295,1311,1330,1352,1375,1397,1416,1431,1441,1445,1443,1436,1425,
+1409,1392,1374,1358,1343,1331,1323,1319,1318,1320,1323,1326,1329,1331,1330,1326,1321,1314,1307,1300,1296,
+1295,1298,1306,1320,1338,1360,1385,1411,1437,1462,1483,1500,1512,1519,1522,1520,1515,1508,1500,1491,1483,
+1475,1468,1462,1455,1447,1437,1424,1409,1391,1370,1347,1322,1297,1273,1250,1229,1212,1198,1187,1179,1173,
+1167,1162,1156,1148,1138,1126,1112,1096,1080,1064,1050,1039,1033,1032,1037,1049,1066,1089,1116,1147,1179,
+1211,1241,1267,1288,1301,1307,1303,1290,1269,1239,1202,1160,1114,1066,1019,974,933,897,868,845,829,
+818,812,809,808,807,805,800,791,779,764,745,725,704,684,665,649,637,628,623,622,622,
+624,625,626,625,622,616,609,599,589,580,571,565,561,561,562,566,572,577,582,585,586,
+584,579,571,562,552,542,534,528,525,525,528,533,538,543,546,546,542,533,521,505,486,
+467,449,434,424,419,421,429,441,456,472,485,492,491,479,454,415,362,297,221,137,49,
+-40,-127,-208,-281,-344,-396,-437,-467,-488,-501,-509,-514,-517,-521,-526,-534,-546,-560,-577,-597,-619,
+-642,-665,-689,-712,-735,-758,-780,-802,-825,-848,-871,-895,-920,-946,-973,-1001,-1030,-1060,-1091,-1124,-1157,
+-1192,-1227,-1263,-1299,-1336,-1372,-1408,-1443,-1478,-1511,-1543,-1574,-1603,-1632,-1659,-1685,-1710,-1734,-1758,-1782,-1805,
+-1829,-1854,-1879,-1906,-1933,-1963,-1994,-2027,-2062,-2098,-2136,-2176,-2217,-2259,-2302,-2345,-2389,-2434,-2478,-2523,-2567,
+-2611,-2655,-2697,-2739,-2778,-2816,-2852,-2885,-2917,-2946,-2973,-2999,-3024,-3049,-3075,-3102,-3130,-3160,-3192,-3224,-3257,
+-3291,-3323,-3354,-3382,-3408,-3431,-3451,-3469,-3484,-3499,-3513,-3528,-3543,-3560,-3577,-3595,-3613,-3630,-3646,-3659,-3668,
+-3675,-3678,-3678,-3676,-3674,-3673,-3675,-3681,-3693,-3712,-3737,-3770,-3807,-3850,-3895,-3940,-3984,-4024,-4059,-4087,-4109,
+-4124,-4132,-4136,-4137,-4137,-4137,-4139,-4145,-4156,-4173,-4196,-4224,-4258,-4296,-4338,-4382,-4428,-4474,-4521,-4567,-4613,
+-4657,-4700,-4742,-4783,-4821,-4857,-4891,-4922,-4949,-4973,-4992,-5007,-5018,-5024,-5027,-5028,-5026,-5022,-5018,-5015,-5012,
+-5011,-5012,-5016,-5022,-5032,-5045,-5061,-5080,-5102,-5127,-5154,-5184,-5215,-5247,-5279,-5312,-5343,-5372,-5399,-5423,-5444,
+-5461,-5476,-5487,-5496,-5504,-5512,-5519,-5528,-5539,-5552,-5567,-5586,-5607,-5629,-5653,-5676,-5699,-5720,-5739,-5754,-5767,
+-5776,-5782,-5785,-5786,-5785,-5784,-5782,-5781,-5780,-5781,-5782,-5784,-5787,-5790,-5793,-5794,-5795,-5793,-5789,-5783,-5774,
+-5763,-5750,-5736,-5722,-5707,-5694,-5682,-5673,-5667,-5665,-5667,-5672,-5680,-5691,-5703,-5715,-5726,-5734,-5739,-5738,-5731,
+-5718,-5699,-5675,-5648,-5619,-5590,-5563,-5542,-5527,-5521,-5524,-5537,-5559,-5590,-5627,-5670,-5714,-5758,-5798,-5834,-5863,
+-5884,-5896,-5900,-5897,-5887,-5872,-5855,-5836,-5817,-5800,-5786,-5776,-5769,-5767,-5768,-5772,-5780,-5789,-5801,-5813,-5827,
+-5840,-5854,-5867,-5879,-5890,-5899,-5907,-5911,-5913,-5912,-5909,-5902,-5893,-5882,-5870,-5858,-5846,-5834,-5824,-5816,-5810,
+-5807,-5806,-5808,-5811,-5817,-5824,-5834,-5844,-5857,-5871,-5887,-5904,-5924,-5944,-5966,-5989,-6011,-6032,-6052,-6068,-6082,
+-6093,-6100,-6104,-6105,-6104,-6102,-6100,-6098,-6099,-6101,-6105,-6112,-6120,-6128,-6137,-6144,-6149,-6151,-6149,-6144,-6136,
+-6125,-6112,-6099,-6086,-6074,-6065,-6059,-6057,-6057,-6060,-6066,-6072,-6079,-6085,-6090,-6094,-6096,-6097,-6097,-6096,-6095,
+-6095,-6096,-6097,-6100,-6104,-6107,-6111,-6113,-6114,-6114,-6112,-6109,-6106,-6103,-6102,-6103,-6108,-6117,-6131,-6150,-6174,
+-6201,-6230,-6261,-6291,-6318,-6343,-6363,-6379,-6389,-6395,-6397,-6396,-6394,-6391,-6388,-6386,-6387,-6388,-6392,-6396,-6400,
+-6403,-6405,-6404,-6401,-6395,-6386,-6375,-6363,-6351,-6339,-6329,-6322,-6317,-6316,-6316,-6319,-6323,-6327,-6329,-6329,-6326,
+-6319,-6307,-6292,-6272,-6249,-6224,-6199,-6173,-6148,-6125,-6104,-6085,-6068,-6053,-6038,-6022,-6004,-5983,-5958,-5929,-5895,
+-5857,-5814,-5768,-5719,-5669,-5618,-5568,-5519,-5473,-5429,-5389,-5352,-5318,-5287,-5259,-5234,-5210,-5189,-5169,-5151,-5133,
+-5116,-5099,-5081,-5061,-5040,-5015,-4987,-4955,-4919,-4879,-4836,-4789,-4741,-4692,-4644,-4598,-4556,-4518,-4484,-4456,-4432,
+-4413,-4397,-4382,-4369,-4355,-4340,-4322,-4303,-4281,-4258,-4234,-4210,-4187,-4167,-4150,-4137,-4128,-4124,-4124,-4129,-4136,
+-4145,-4156,-4166,-4174,-4180,-4182,-4180,-4172,-4159,-4140,-4115,-4086,-4051,-4013,-3973,-3932,-3892,-3855,-3822,-3795,-3774,
+-3760,-3753,-3752,-3757,-3766,-3777,-3788,-3797,-3803,-3804,-3800,-3791,-3776,-3758,-3738,-3717,-3697,-3681,-3669,-3663,-3662,
+-3666,-3674,-3684,-3696,-3706,-3714,-3717,-3714,-3706,-3692,-3672,-3649,-3623,-3596,-3571,-3549,-3530,-3517,-3509,-3506,-3507,
+-3512,-3518,-3525,-3531,-3534,-3533,-3527,-3515,-3497,-3473,-3444,-3410,-3373,-3332,-3291,-3249,-3208,-3170,-3135,-3104,-3079,
+-3058,-3043,-3033,-3027,-3024,-3025,-3027,-3028,-3029,-3028,-3024,-3017,-3006,-2991,-2973,-2953,-2931,-2909,-2887,-2866,-2848,
+-2832,-2819,-2808,-2800,-2794,-2788,-2783,-2777,-2771,-2762,-2752,-2740,-2726,-2711,-2695,-2679,-2664,-2649,-2635,-2623,-2612,
+-2602,-2593,-2584,-2576,-2568,-2559,-2549,-2539,-2528,-2516,-2504,-2492,-2480,-2469,-2458,-2448,-2439,-2431,-2423,-2415,-2407,
+-2399,-2390,-2381,-2370,-2357,-2343,-2327,-2310,-2292,-2273,-2253,-2234,-2214,-2196,-2178,-2162,-2148,-2136,-2125,-2115,-2107,
+-2099,-2091,-2082,-2073,-2062,-2048,-2033,-2016,-1997,-1977,-1956,-1934,-1913,-1894,-1876,-1860,-1846,-1835,-1827,-1821,-1818,
+-1816,-1816,-1816,-1818,-1819,-1821,-1822,-1822,-1822,-1820,-1817,-1812,-1805,-1796,-1786,-1774,-1761,-1748,-1735,-1723,-1714,
+-1707,-1704,-1704,-1708,-1716,-1726,-1738,-1751,-1762,-1770,-1775,-1774,-1767,-1753,-1733,-1707,-1677,-1643,-1607,-1572,-1538,
+-1506,-1478,-1453,-1433,-1415,-1399,-1385,-1370,-1353,-1333,-1309,-1280,-1246,-1207,-1163,-1116,-1067,-1016,-965,-915,-867,
+-822,-781,-744,-712,-686,-665,-650,-643,-643,-651,-668,-694,-729,-773,-825,-885,-950,-1019,-1089,-1159,-1223,
+-1282,-1331,-1368,-1394,-1406,-1404,-1391,-1367,-1335,-1297,-1257,-1216,-1178,-1145,-1118,-1099,-1088,-1084,-1086,-1093,-1103,
+-1115,-1126,-1136,-1144,-1148,-1148,-1146,-1141,-1135,-1127,-1120,-1114,-1109,-1106,-1104,-1104,-1104,-1104,-1104,-1102,-1100,
+-1095,-1089,-1082,-1074,-1065,-1056,-1047,-1040,-1033,-1028,-1023,-1019,-1016,-1013,-1010,-1006,-1001,-995,-988,-981,-974,
+-965,-957,-949,-941,-933,-924,-915,-906,-896,-885,-873,-861,-849,-836,-823,-811,-799,-788,-779,-769,-761,
+-753,-745,-736,-727,-716,-705,-694,-681,-669,-656,-645,-634,-624,-616,-608,-602,-597,-591,-586,-580,-574,
+-567,-558,-549,-540,-530,-521,-512,-505,-498,-493,-489,-486,-485,-483,-483,-482,-481,-480,-479,-477,-476,
+-474,-473,-472,-472,-472,-472,-472,-472,-472,-471,-470,-467,-463,-459,-453,-446,-439,-431,-422,-413,-404,
+-395,-385,-375,-365,-354,-344,-335,-326,-317,-310,-304,-300,-297,-296,-296,-298,-300,-302,-304,-304,-303,
+-300,-295,-288,-277,-265,-251,-236,-220,-204,-188,-173,-159,-146,-135,-124,-114,-105,-95,-84,-71,-56,
+-39,-19,3,28,55,84,114,144,175,206,236,266,296,326,356,388,420,454,490,526,564,
+602,639,675,708,738,764,785,802,814,822,827,829,830,830,831,834,839,845,854,864,875,
+886,896,904,910,912,911,908,902,895,888,881,876,873,873,876,883,892,903,914,925,935,
+941,944,943,937,927,913,896,876,855,749,734,720,707,697,688,683,679,678,679,682,687,
+694,702,712,723,735,748,761,774,787,800,811,821,830,837,844,849,854,859,865,871,879,
+888,899,912,926,941,957,973,988,1002,1014,1025,1034,1041,1046,1051,1056,1060,1065,1072,1080,1090,
+1103,1117,1132,1149,1166,1183,1199,1215,1228,1240,1251,1259,1267,1273,1280,1286,1292,1299,1307,1317,1327,
+1337,1348,1359,1370,1380,1389,1396,1402,1408,1412,1416,1421,1425,1431,1438,1447,1457,1469,1482,1496,1510,
+1524,1536,1546,1555,1561,1565,1567,1566,1564,1561,1558,1555,1553,1552,1552,1553,1554,1556,1557,1557,1554,
+1548,1540,1527,1510,1490,1466,1439,1411,1382,1354,1327,1303,1282,1265,1254,1247,1245,1247,1254,1264,1276,
+1289,1303,1316,1327,1337,1343,1346,1346,1343,1336,1327,1316,1303,1291,1278,1267,1259,1253,1251,1252,1257,
+1266,1278,1293,1308,1324,1340,1353,1363,1370,1373,1372,1367,1358,1347,1334,1321,1307,1296,1286,1279,1274,
+1272,1272,1273,1275,1277,1279,1279,1278,1275,1272,1268,1265,1263,1262,1265,1271,1280,1293,1309,1326,1346,
+1365,1384,1402,1417,1429,1438,1443,1446,1446,1444,1440,1436,1430,1425,1419,1412,1405,1396,1386,1374,1359,
+1343,1325,1305,1284,1263,1243,1223,1206,1190,1176,1165,1156,1148,1140,1133,1126,1118,1109,1098,1087,1076,
+1064,1054,1045,1039,1037,1038,1043,1053,1066,1083,1103,1124,1145,1165,1183,1197,1207,1210,1207,1197,1180,
+1157,1127,1094,1057,1018,978,940,904,872,844,822,803,790,780,773,768,763,758,752,743,732,
+719,704,687,670,654,639,626,615,607,602,599,598,598,597,595,592,586,579,569,558,547,
+536,526,518,513,511,511,514,519,524,530,534,535,535,531,525,516,507,497,488,482,478,
+477,479,483,489,495,500,503,502,497,487,473,456,437,417,399,385,375,372,374,382,395,
+410,426,438,444,442,429,404,366,315,252,180,101,19,-64,-144,-218,-285,-342,-390,-427,-455,
+-475,-489,-498,-505,-512,-519,-528,-539,-553,-570,-589,-609,-631,-653,-676,-699,-722,-744,-767,-791,-815,
+-839,-865,-891,-918,-946,-974,-1002,-1031,-1060,-1089,-1119,-1149,-1180,-1212,-1246,-1281,-1318,-1355,-1394,-1433,-1471,
+-1509,-1546,-1581,-1613,-1643,-1670,-1694,-1716,-1736,-1755,-1773,-1791,-1809,-1829,-1850,-1873,-1897,-1924,-1953,-1983,-2014,
+-2046,-2080,-2114,-2148,-2183,-2219,-2256,-2294,-2334,-2376,-2419,-2465,-2511,-2559,-2608,-2656,-2703,-2748,-2791,-2830,-2866,
+-2899,-2928,-2955,-2979,-3003,-3026,-3050,-3075,-3103,-3133,-3165,-3199,-3235,-3270,-3306,-3340,-3372,-3401,-3427,-3449,-3469,
+-3487,-3503,-3518,-3534,-3550,-3566,-3584,-3602,-3620,-3638,-3655,-3670,-3683,-3692,-3699,-3704,-3708,-3712,-3716,-3724,-3735,
+-3750,-3771,-3797,-3829,-3864,-3902,-3941,-3979,-4015,-4046,-4073,-4094,-4109,-4119,-4125,-4128,-4130,-4133,-4137,-4145,-4158,
+-4176,-4199,-4227,-4259,-4294,-4332,-4371,-4410,-4450,-4488,-4526,-4564,-4601,-4638,-4676,-4714,-4753,-4793,-4832,-4870,-4906,
+-4940,-4969,-4994,-5013,-5027,-5035,-5038,-5037,-5032,-5025,-5018,-5012,-5007,-5005,-5007,-5014,-5024,-5039,-5058,-5081,-5106,
+-5134,-5163,-5193,-5224,-5255,-5285,-5314,-5342,-5369,-5394,-5417,-5438,-5458,-5475,-5490,-5503,-5515,-5525,-5535,-5545,-5556,
+-5568,-5581,-5596,-5613,-5631,-5651,-5672,-5692,-5713,-5732,-5748,-5763,-5774,-5782,-5787,-5789,-5789,-5787,-5783,-5780,-5777,
+-5775,-5774,-5774,-5775,-5777,-5778,-5780,-5780,-5778,-5774,-5767,-5758,-5745,-5731,-5715,-5698,-5682,-5666,-5654,-5644,-5638,
+-5636,-5638,-5644,-5653,-5664,-5675,-5685,-5693,-5697,-5697,-5691,-5679,-5662,-5640,-5614,-5587,-5559,-5534,-5512,-5497,-5489,
+-5490,-5500,-5519,-5547,-5581,-5620,-5663,-5707,-5749,-5788,-5821,-5849,-5868,-5880,-5885,-5883,-5875,-5863,-5848,-5831,-5813,
+-5796,-5781,-5767,-5756,-5748,-5743,-5741,-5742,-5746,-5752,-5761,-5772,-5785,-5799,-5815,-5831,-5846,-5860,-5872,-5882,-5888,
+-5890,-5888,-5882,-5873,-5861,-5846,-5831,-5815,-5801,-5788,-5778,-5772,-5769,-5769,-5772,-5777,-5785,-5794,-5804,-5815,-5827,
+-5839,-5851,-5865,-5879,-5894,-5910,-5927,-5945,-5963,-5981,-5998,-6013,-6026,-6036,-6044,-6049,-6052,-6053,-6053,-6052,-6052,
+-6053,-6054,-6058,-6062,-6068,-6073,-6078,-6082,-6083,-6082,-6077,-6070,-6060,-6047,-6033,-6019,-6006,-5994,-5985,-5979,-5976,
+-5975,-5978,-5982,-5988,-5995,-6001,-6007,-6012,-6015,-6017,-6018,-6018,-6017,-6017,-6017,-6016,-6016,-6016,-6015,-6013,-6010,
+-6005,-6000,-5993,-5986,-5980,-5976,-5974,-5976,-5983,-5995,-6012,-6035,-6063,-6094,-6128,-6162,-6196,-6227,-6254,-6277,-6295,
+-6309,-6317,-6322,-6324,-6325,-6326,-6327,-6330,-6334,-6340,-6348,-6357,-6365,-6373,-6379,-6383,-6384,-6381,-6377,-6370,-6361,
+-6353,-6344,-6337,-6332,-6330,-6329,-6329,-6330,-6331,-6330,-6326,-6318,-6305,-6287,-6263,-6233,-6199,-6160,-6120,-6078,-6037,
+-5998,-5961,-5927,-5897,-5870,-5845,-5823,-5802,-5780,-5758,-5734,-5708,-5679,-5648,-5615,-5580,-5545,-5509,-5475,-5442,-5411,
+-5382,-5356,-5331,-5308,-5286,-5264,-5242,-5220,-5197,-5173,-5149,-5123,-5097,-5070,-5043,-5015,-4987,-4959,-4930,-4899,-4867,
+-4833,-4797,-4759,-4719,-4678,-4637,-4596,-4555,-4517,-4482,-4450,-4421,-4397,-4377,-4359,-4345,-4332,-4320,-4307,-4293,-4278,
+-4261,-4241,-4220,-4196,-4172,-4148,-4125,-4104,-4086,-4071,-4060,-4053,-4051,-4052,-4056,-4063,-4070,-4078,-4084,-4087,-4087,
+-4082,-4071,-4054,-4031,-4003,-3971,-3935,-3897,-3859,-3822,-3789,-3761,-3738,-3721,-3711,-3707,-3708,-3712,-3719,-3727,-3733,
+-3737,-3737,-3733,-3724,-3712,-3697,-3680,-3663,-3648,-3637,-3630,-3628,-3631,-3639,-3651,-3665,-3680,-3693,-3704,-3710,-3711,
+-3705,-3693,-3675,-3653,-3629,-3602,-3577,-3554,-3535,-3521,-3513,-3510,-3512,-3517,-3526,-3534,-3542,-3547,-3547,-3542,-3531,
+-3512,-3486,-3454,-3417,-3375,-3331,-3286,-3242,-3200,-3163,-3130,-3104,-3085,-3072,-3065,-3064,-3068,-3075,-3084,-3093,-3102,
+-3108,-3110,-3109,-3102,-3092,-3076,-3058,-3036,-3013,-2989,-2965,-2943,-2923,-2905,-2891,-2878,-2869,-2860,-2853,-2846,-2839,
+-2831,-2821,-2809,-2796,-2781,-2766,-2749,-2732,-2716,-2701,-2686,-2673,-2661,-2651,-2642,-2633,-2624,-2615,-2606,-2596,-2585,
+-2574,-2561,-2549,-2536,-2523,-2511,-2499,-2488,-2478,-2469,-2460,-2452,-2443,-2434,-2424,-2412,-2400,-2385,-2369,-2351,-2331,
+-2311,-2290,-2270,-2250,-2231,-2214,-2199,-2185,-2174,-2165,-2157,-2150,-2143,-2136,-2128,-2118,-2107,-2093,-2076,-2057,-2037,
+-2015,-1992,-1969,-1947,-1926,-1907,-1891,-1877,-1866,-1858,-1853,-1850,-1848,-1848,-1849,-1850,-1852,-1853,-1854,-1854,-1854,
+-1853,-1851,-1848,-1844,-1838,-1830,-1822,-1812,-1802,-1791,-1780,-1771,-1763,-1757,-1755,-1755,-1759,-1765,-1774,-1785,-1796,
+-1805,-1813,-1817,-1817,-1812,-1802,-1786,-1766,-1742,-1716,-1689,-1663,-1639,-1618,-1601,-1588,-1579,-1574,-1570,-1567,-1563,
+-1556,-1545,-1528,-1505,-1475,-1439,-1397,-1350,-1299,-1246,-1192,-1140,-1090,-1044,-1003,-968,-939,-916,-900,-891,-889,
+-893,-904,-922,-945,-975,-1011,-1052,-1097,-1145,-1195,-1246,-1295,-1340,-1380,-1413,-1437,-1452,-1457,-1452,-1437,-1414,
+-1385,-1351,-1316,-1280,-1247,-1217,-1193,-1175,-1164,-1159,-1160,-1165,-1173,-1183,-1193,-1202,-1210,-1214,-1216,-1214,-1210,
+-1204,-1197,-1190,-1182,-1175,-1170,-1165,-1162,-1160,-1159,-1159,-1158,-1158,-1156,-1154,-1151,-1147,-1142,-1137,-1131,-1125,
+-1118,-1112,-1106,-1099,-1093,-1086,-1080,-1073,-1066,-1060,-1053,-1046,-1039,-1033,-1026,-1019,-1011,-1003,-995,-985,-975,
+-964,-952,-939,-926,-912,-899,-886,-874,-863,-853,-843,-835,-827,-819,-811,-803,-794,-785,-776,-767,-758,
+-749,-740,-733,-726,-720,-716,-712,-708,-705,-701,-697,-692,-686,-678,-670,-662,-653,-645,-638,-631,-626,
+-623,-621,-620,-620,-621,-623,-624,-625,-626,-625,-625,-623,-622,-620,-619,-618,-617,-617,-616,-616,-616,
+-614,-612,-609,-605,-599,-591,-583,-573,-562,-551,-540,-528,-516,-504,-493,-480,-468,-455,-441,-428,-414,
+-400,-387,-375,-364,-354,-346,-340,-335,-332,-329,-327,-324,-320,-315,-307,-296,-283,-267,-249,-229,-209,
+-189,-170,-153,-138,-127,-118,-112,-108,-105,-102,-99,-94,-87,-76,-61,-42,-19,7,37,70,103,
+138,173,207,240,272,304,334,364,394,424,454,484,515,545,574,602,628,651,671,687,700,
+709,716,720,722,724,726,729,733,739,746,755,765,775,785,793,800,805,808,808,806,802,
+798,793,789,786,786,787,790,795,802,809,816,822,826,828,827,823,816,806,793,779,764,
+749,590,580,573,567,564,562,562,564,567,571,577,584,591,600,610,621,633,646,660,674,
+688,702,715,727,738,747,754,759,764,768,772,776,782,789,797,808,821,835,851,867,882,
+898,911,923,933,940,945,948,950,952,954,956,961,967,976,988,1002,1019,1038,1058,1078,1099,
+1119,1138,1155,1171,1185,1197,1208,1218,1228,1237,1246,1256,1266,1276,1286,1296,1305,1314,1323,1330,1336,
+1341,1345,1349,1353,1358,1364,1371,1379,1390,1402,1415,1430,1445,1460,1474,1486,1497,1506,1512,1517,1519,
+1520,1519,1519,1518,1518,1519,1520,1523,1525,1528,1529,1528,1525,1518,1507,1492,1472,1448,1421,1392,1362,
+1332,1304,1279,1258,1242,1231,1226,1226,1231,1240,1253,1267,1281,1295,1308,1317,1324,1327,1327,1323,1316,
+1307,1296,1285,1273,1262,1251,1243,1236,1231,1229,1229,1232,1236,1241,1248,1256,1264,1272,1279,1285,1290,
+1293,1293,1292,1290,1285,1279,1272,1265,1258,1251,1244,1239,1235,1233,1231,1230,1230,1230,1230,1229,1229,
+1227,1225,1223,1221,1220,1219,1219,1222,1226,1232,1239,1249,1260,1271,1284,1296,1308,1318,1328,1336,1342,
+1347,1350,1351,1351,1349,1346,1341,1335,1328,1319,1309,1297,1284,1270,1256,1240,1224,1209,1193,1178,1164,
+1151,1139,1128,1118,1109,1101,1093,1087,1081,1076,1072,1069,1068,1068,1070,1073,1077,1083,1090,1097,1104,
+1111,1117,1121,1123,1123,1119,1113,1103,1089,1072,1052,1030,1005,978,951,922,894,867,841,816,794,
+774,757,742,728,717,707,697,687,677,667,655,643,629,616,602,590,578,568,560,555,552,
+550,550,551,552,552,551,547,542,534,524,513,500,488,476,466,459,454,452,452,455,458,
+462,466,468,468,466,462,456,448,440,433,426,422,420,421,425,431,437,444,449,452,451,
+447,438,427,412,397,381,367,356,349,347,350,357,368,380,391,398,400,394,379,353,316,
+269,213,149,81,10,-59,-126,-188,-244,-292,-333,-366,-392,-413,-430,-445,-459,-474,-489,-507,-526,
+-547,-569,-592,-615,-639,-662,-684,-706,-727,-749,-771,-794,-819,-844,-872,-901,-932,-964,-996,-1029,-1062,
+-1095,-1129,-1162,-1196,-1230,-1265,-1301,-1338,-1377,-1416,-1456,-1496,-1535,-1572,-1607,-1639,-1668,-1693,-1713,-1730,-1744,
+-1756,-1766,-1775,-1785,-1796,-1810,-1826,-1845,-1868,-1893,-1920,-1950,-1980,-2012,-2044,-2075,-2107,-2139,-2171,-2204,-2238,
+-2274,-2313,-2354,-2397,-2444,-2492,-2542,-2592,-2641,-2689,-2735,-2778,-2816,-2852,-2883,-2911,-2937,-2962,-2986,-3011,-3038,
+-3067,-3099,-3133,-3170,-3209,-3249,-3288,-3327,-3363,-3397,-3428,-3455,-3478,-3499,-3518,-3534,-3550,-3566,-3582,-3599,-3616,
+-3634,-3653,-3672,-3690,-3708,-3725,-3741,-3757,-3772,-3788,-3804,-3822,-3842,-3864,-3888,-3914,-3941,-3968,-3995,-4020,-4043,
+-4061,-4077,-4088,-4095,-4099,-4101,-4103,-4105,-4110,-4118,-4130,-4147,-4170,-4197,-4228,-4262,-4298,-4335,-4371,-4405,-4438,
+-4468,-4497,-4524,-4551,-4579,-4608,-4639,-4672,-4709,-4747,-4787,-4828,-4868,-4905,-4939,-4967,-4990,-5006,-5016,-5021,-5020,
+-5017,-5011,-5006,-5002,-5000,-5003,-5011,-5024,-5042,-5064,-5090,-5119,-5149,-5181,-5212,-5242,-5271,-5298,-5324,-5348,-5371,
+-5393,-5414,-5434,-5454,-5473,-5491,-5509,-5526,-5542,-5557,-5571,-5585,-5597,-5610,-5623,-5636,-5651,-5665,-5681,-5697,-5714,
+-5730,-5746,-5760,-5772,-5782,-5789,-5794,-5796,-5795,-5792,-5788,-5783,-5778,-5774,-5769,-5766,-5763,-5761,-5759,-5756,-5753,
+-5747,-5740,-5731,-5719,-5706,-5692,-5677,-5662,-5649,-5638,-5630,-5625,-5625,-5628,-5634,-5642,-5651,-5660,-5666,-5669,-5668,
+-5661,-5648,-5630,-5607,-5579,-5550,-5520,-5492,-5467,-5449,-5438,-5436,-5443,-5460,-5485,-5517,-5555,-5596,-5639,-5681,-5720,
+-5754,-5783,-5805,-5821,-5829,-5832,-5829,-5823,-5813,-5802,-5789,-5777,-5765,-5754,-5744,-5735,-5727,-5721,-5716,-5712,-5710,
+-5709,-5711,-5716,-5723,-5733,-5746,-5760,-5776,-5793,-5809,-5823,-5834,-5842,-5845,-5844,-5838,-5828,-5814,-5798,-5782,-5765,
+-5750,-5738,-5730,-5725,-5725,-5728,-5735,-5745,-5757,-5770,-5782,-5795,-5807,-5818,-5828,-5837,-5846,-5855,-5865,-5875,-5886,
+-5898,-5910,-5923,-5935,-5947,-5957,-5966,-5973,-5979,-5983,-5987,-5990,-5992,-5995,-5999,-6003,-6007,-6012,-6016,-6020,-6022,
+-6023,-6021,-6016,-6009,-6000,-5988,-5976,-5963,-5951,-5940,-5931,-5924,-5920,-5918,-5919,-5921,-5925,-5929,-5933,-5937,-5940,
+-5942,-5944,-5944,-5943,-5942,-5940,-5938,-5935,-5932,-5928,-5923,-5918,-5911,-5903,-5894,-5884,-5876,-5868,-5863,-5861,-5863,
+-5870,-5883,-5901,-5925,-5953,-5985,-6019,-6053,-6087,-6118,-6146,-6170,-6189,-6203,-6212,-6218,-6222,-6224,-6225,-6227,-6230,
+-6235,-6242,-6251,-6261,-6272,-6283,-6292,-6301,-6307,-6311,-6312,-6312,-6310,-6307,-6304,-6300,-6297,-6295,-6292,-6289,-6284,
+-6278,-6268,-6254,-6236,-6211,-6182,-6146,-6106,-6062,-6015,-5967,-5919,-5872,-5828,-5788,-5752,-5721,-5694,-5671,-5651,-5633,
+-5617,-5601,-5585,-5568,-5550,-5530,-5510,-5489,-5469,-5448,-5428,-5409,-5390,-5373,-5356,-5338,-5319,-5299,-5277,-5252,-5225,
+-5194,-5160,-5124,-5086,-5048,-5009,-4970,-4932,-4896,-4862,-4829,-4798,-4768,-4739,-4710,-4680,-4651,-4621,-4590,-4559,-4529,
+-4498,-4470,-4443,-4418,-4396,-4377,-4360,-4345,-4333,-4321,-4310,-4298,-4285,-4270,-4253,-4234,-4213,-4189,-4165,-4141,-4117,
+-4095,-4076,-4060,-4049,-4041,-4039,-4040,-4044,-4051,-4059,-4067,-4073,-4076,-4076,-4069,-4058,-4039,-4015,-3985,-3951,-3913,
+-3874,-3834,-3795,-3758,-3726,-3697,-3674,-3656,-3642,-3632,-3626,-3621,-3616,-3612,-3608,-3602,-3595,-3588,-3581,-3575,-3571,
+-3570,-3572,-3578,-3588,-3602,-3619,-3637,-3656,-3674,-3689,-3700,-3706,-3706,-3700,-3689,-3673,-3653,-3632,-3611,-3591,-3574,
+-3561,-3553,-3550,-3551,-3557,-3565,-3575,-3583,-3590,-3592,-3589,-3580,-3563,-3540,-3510,-3475,-3435,-3393,-3349,-3307,-3267,
+-3231,-3201,-3177,-3160,-3150,-3147,-3150,-3158,-3170,-3184,-3198,-3212,-3224,-3233,-3237,-3237,-3232,-3222,-3207,-3189,-3167,
+-3144,-3119,-3093,-3069,-3045,-3023,-3003,-2985,-2969,-2954,-2941,-2928,-2916,-2904,-2891,-2878,-2864,-2849,-2835,-2820,-2805,
+-2791,-2777,-2764,-2751,-2740,-2728,-2717,-2706,-2695,-2683,-2670,-2657,-2642,-2627,-2611,-2594,-2578,-2561,-2545,-2529,-2515,
+-2501,-2487,-2475,-2463,-2451,-2438,-2426,-2412,-2398,-2382,-2366,-2349,-2331,-2313,-2296,-2279,-2263,-2248,-2235,-2223,-2214,
+-2205,-2198,-2191,-2184,-2176,-2167,-2156,-2143,-2128,-2110,-2090,-2069,-2046,-2023,-1999,-1977,-1956,-1938,-1922,-1908,-1898,
+-1890,-1885,-1883,-1882,-1882,-1883,-1885,-1886,-1888,-1889,-1890,-1890,-1889,-1887,-1885,-1881,-1876,-1870,-1862,-1853,-1843,
+-1832,-1820,-1809,-1798,-1789,-1783,-1779,-1778,-1780,-1786,-1795,-1806,-1818,-1830,-1842,-1851,-1857,-1859,-1857,-1851,-1841,
+-1828,-1813,-1797,-1781,-1767,-1756,-1749,-1745,-1744,-1747,-1752,-1757,-1761,-1762,-1760,-1752,-1738,-1717,-1690,-1656,-1617,
+-1575,-1530,-1484,-1440,-1398,-1360,-1327,-1300,-1279,-1264,-1255,-1251,-1253,-1259,-1268,-1281,-1296,-1314,-1334,-1356,-1378,
+-1402,-1425,-1448,-1469,-1488,-1504,-1515,-1521,-1522,-1516,-1503,-1485,-1462,-1435,-1405,-1373,-1342,-1313,-1287,-1265,-1247,
+-1235,-1229,-1227,-1229,-1234,-1241,-1248,-1255,-1261,-1265,-1267,-1265,-1262,-1256,-1248,-1239,-1230,-1222,-1214,-1208,-1203,
+-1199,-1198,-1197,-1198,-1200,-1202,-1204,-1206,-1206,-1206,-1205,-1203,-1200,-1196,-1190,-1184,-1178,-1170,-1163,-1156,-1148,
+-1141,-1134,-1128,-1121,-1115,-1108,-1101,-1094,-1086,-1078,-1068,-1058,-1046,-1034,-1021,-1007,-994,-981,-968,-956,-944,
+-934,-924,-916,-908,-900,-893,-886,-879,-872,-865,-858,-851,-844,-839,-834,-830,-826,-823,-821,-819,-817,
+-815,-812,-808,-803,-798,-792,-786,-780,-774,-769,-765,-763,-761,-761,-762,-764,-766,-768,-769,-770,-770,
+-769,-767,-764,-760,-756,-752,-749,-745,-743,-740,-738,-735,-733,-729,-725,-720,-714,-706,-698,-688,-678,
+-668,-658,-647,-636,-625,-613,-600,-586,-570,-552,-531,-509,-485,-460,-434,-408,-382,-359,-337,-318,-301,
+-287,-275,-265,-256,-246,-236,-224,-210,-194,-175,-155,-135,-114,-94,-77,-64,-54,-50,-50,-54,-61,
+-70,-80,-89,-96,-98,-94,-84,-68,-45,-15,18,56,96,138,179,218,255,288,319,346,371,
+393,413,433,452,471,490,509,528,547,564,580,593,604,613,620,624,627,628,629,630,632,
+634,638,642,648,654,660,666,671,676,679,682,684,684,685,685,685,686,688,690,692,694,
+696,697,697,695,690,684,676,665,653,640,627,614,601,590,454,448,446,445,447,450,455,
+461,467,473,480,487,494,501,509,518,527,538,549,562,575,587,600,612,623,633,641,648,
+653,657,661,665,670,675,683,692,703,715,730,745,760,775,789,801,811,819,823,826,826,
+825,824,823,823,826,831,840,852,868,888,910,934,960,986,1012,1038,1061,1083,1102,1119,1133,
+1146,1157,1167,1176,1184,1192,1200,1207,1215,1222,1229,1235,1242,1247,1253,1259,1264,1271,1278,1286,1296,
+1308,1320,1334,1350,1365,1381,1397,1411,1424,1436,1445,1453,1459,1463,1467,1470,1473,1476,1479,1483,1486,
+1489,1492,1492,1489,1483,1473,1459,1440,1416,1389,1358,1326,1294,1263,1234,1210,1192,1179,1173,1174,1181,
+1194,1210,1229,1249,1268,1286,1301,1312,1318,1319,1317,1310,1301,1289,1276,1263,1250,1239,1229,1221,1216,
+1212,1210,1209,1210,1211,1212,1213,1215,1216,1217,1218,1218,1219,1219,1220,1220,1219,1219,1217,1216,1213,
+1210,1206,1201,1196,1191,1185,1180,1175,1170,1166,1163,1160,1158,1156,1155,1154,1153,1153,1153,1153,1153,
+1154,1156,1158,1162,1167,1173,1180,1188,1198,1208,1219,1229,1240,1249,1258,1264,1269,1272,1272,1270,1265,
+1258,1249,1238,1226,1213,1199,1185,1171,1156,1142,1128,1115,1102,1089,1076,1065,1054,1044,1036,1030,1026,
+1025,1027,1032,1040,1052,1066,1082,1099,1117,1134,1148,1160,1167,1170,1166,1157,1142,1121,1095,1065,1032,
+996,960,923,888,855,824,797,772,751,733,718,705,694,683,674,664,653,642,630,617,602,
+586,570,554,538,523,509,496,486,478,473,470,469,469,471,473,475,476,475,473,468,460,
+451,440,428,416,405,395,386,380,376,374,375,377,379,382,384,385,385,383,379,374,369,
+364,359,357,356,357,361,367,374,382,390,396,400,401,400,395,388,380,370,361,354,349,
+348,350,355,363,371,380,387,389,386,375,356,328,291,246,194,136,76,14,-45,-102,-156,
+-203,-245,-281,-312,-338,-362,-383,-404,-425,-447,-471,-496,-522,-550,-578,-605,-631,-657,-680,-702,-723,
+-743,-763,-783,-804,-827,-852,-880,-910,-943,-978,-1015,-1053,-1092,-1132,-1173,-1214,-1256,-1297,-1340,-1382,-1425,
+-1467,-1509,-1550,-1590,-1627,-1660,-1690,-1716,-1737,-1752,-1763,-1770,-1773,-1774,-1774,-1774,-1774,-1778,-1784,-1794,-1809,
+-1827,-1850,-1876,-1905,-1935,-1967,-2000,-2033,-2065,-2098,-2131,-2164,-2199,-2234,-2272,-2312,-2355,-2400,-2447,-2495,-2544,
+-2593,-2641,-2687,-2730,-2770,-2807,-2841,-2873,-2902,-2931,-2959,-2988,-3019,-3052,-3087,-3124,-3164,-3205,-3247,-3288,-3328,
+-3367,-3402,-3434,-3463,-3488,-3510,-3529,-3547,-3563,-3579,-3595,-3612,-3629,-3649,-3669,-3691,-3714,-3739,-3764,-3789,-3816,
+-3842,-3869,-3896,-3923,-3949,-3975,-4000,-4022,-4043,-4060,-4074,-4083,-4089,-4090,-4088,-4083,-4077,-4070,-4065,-4062,-4064,
+-4071,-4084,-4104,-4130,-4161,-4196,-4235,-4275,-4315,-4353,-4388,-4420,-4449,-4474,-4496,-4517,-4537,-4558,-4582,-4609,-4640,
+-4675,-4714,-4755,-4798,-4841,-4881,-4918,-4951,-4977,-4996,-5009,-5016,-5018,-5017,-5013,-5010,-5008,-5010,-5015,-5026,-5042,
+-5063,-5088,-5116,-5147,-5179,-5211,-5242,-5271,-5299,-5324,-5348,-5371,-5392,-5412,-5433,-5453,-5474,-5495,-5516,-5537,-5557,
+-5576,-5593,-5609,-5624,-5637,-5649,-5659,-5670,-5680,-5690,-5701,-5713,-5725,-5738,-5751,-5763,-5774,-5784,-5791,-5796,-5799,
+-5800,-5798,-5793,-5788,-5781,-5774,-5766,-5758,-5751,-5743,-5735,-5727,-5718,-5708,-5698,-5686,-5674,-5661,-5648,-5636,-5626,
+-5618,-5613,-5611,-5612,-5616,-5622,-5630,-5637,-5643,-5646,-5645,-5639,-5627,-5610,-5586,-5558,-5527,-5495,-5463,-5435,-5411,
+-5395,-5387,-5389,-5401,-5423,-5452,-5489,-5530,-5574,-5617,-5659,-5696,-5727,-5752,-5770,-5780,-5784,-5783,-5778,-5770,-5761,
+-5751,-5743,-5735,-5729,-5724,-5720,-5717,-5715,-5712,-5709,-5705,-5702,-5698,-5695,-5694,-5695,-5699,-5705,-5715,-5726,-5740,
+-5755,-5769,-5781,-5791,-5797,-5798,-5795,-5787,-5774,-5758,-5741,-5722,-5704,-5689,-5677,-5669,-5667,-5669,-5676,-5687,-5701,
+-5716,-5733,-5748,-5763,-5775,-5786,-5794,-5800,-5805,-5809,-5813,-5818,-5823,-5829,-5837,-5846,-5855,-5866,-5877,-5887,-5897,
+-5906,-5915,-5922,-5929,-5935,-5941,-5947,-5952,-5957,-5961,-5965,-5968,-5969,-5969,-5967,-5963,-5957,-5949,-5939,-5929,-5918,
+-5907,-5897,-5889,-5882,-5876,-5873,-5871,-5871,-5872,-5873,-5875,-5877,-5878,-5879,-5879,-5878,-5877,-5875,-5873,-5870,-5867,
+-5863,-5859,-5855,-5850,-5844,-5837,-5831,-5824,-5818,-5814,-5812,-5812,-5816,-5825,-5837,-5855,-5876,-5900,-5927,-5955,-5984,
+-6011,-6036,-6058,-6076,-6089,-6098,-6103,-6104,-6103,-6100,-6097,-6094,-6093,-6093,-6096,-6100,-6106,-6114,-6123,-6132,-6141,
+-6149,-6155,-6161,-6164,-6167,-6168,-6168,-6167,-6165,-6162,-6158,-6151,-6143,-6132,-6117,-6098,-6074,-6046,-6014,-5978,-5938,
+-5896,-5853,-5810,-5769,-5730,-5694,-5663,-5637,-5615,-5597,-5583,-5573,-5564,-5557,-5550,-5543,-5535,-5525,-5514,-5502,-5488,
+-5474,-5458,-5443,-5427,-5410,-5393,-5375,-5356,-5334,-5310,-5283,-5252,-5218,-5181,-5140,-5097,-5052,-5007,-4961,-4916,-4873,
+-4832,-4793,-4758,-4725,-4695,-4667,-4640,-4615,-4590,-4566,-4542,-4518,-4494,-4471,-4448,-4427,-4406,-4388,-4371,-4356,-4343,
+-4331,-4321,-4310,-4300,-4288,-4276,-4262,-4246,-4228,-4209,-4190,-4170,-4150,-4132,-4116,-4103,-4093,-4086,-4083,-4084,-4087,
+-4092,-4098,-4104,-4109,-4110,-4108,-4102,-4089,-4071,-4047,-4017,-3983,-3943,-3901,-3857,-3812,-3767,-3723,-3682,-3643,-3608,
+-3577,-3549,-3525,-3505,-3488,-3474,-3463,-3455,-3451,-3450,-3454,-3461,-3472,-3488,-3507,-3529,-3554,-3581,-3608,-3634,-3658,
+-3678,-3694,-3704,-3709,-3708,-3702,-3691,-3676,-3660,-3644,-3628,-3615,-3605,-3598,-3596,-3598,-3604,-3611,-3619,-3627,-3633,
+-3635,-3633,-3625,-3611,-3591,-3566,-3536,-3502,-3466,-3429,-3393,-3360,-3330,-3306,-3286,-3273,-3266,-3265,-3269,-3277,-3289,
+-3303,-3318,-3333,-3346,-3357,-3364,-3368,-3368,-3363,-3354,-3340,-3323,-3303,-3280,-3255,-3229,-3201,-3174,-3147,-3121,-3096,
+-3072,-3050,-3029,-3010,-2992,-2975,-2960,-2945,-2931,-2918,-2906,-2894,-2882,-2870,-2858,-2846,-2834,-2821,-2807,-2793,-2778,
+-2762,-2744,-2726,-2707,-2686,-2666,-2645,-2623,-2602,-2582,-2562,-2543,-2525,-2508,-2492,-2477,-2463,-2450,-2437,-2425,-2412,
+-2399,-2387,-2374,-2360,-2347,-2334,-2321,-2308,-2296,-2284,-2273,-2263,-2253,-2244,-2235,-2225,-2215,-2204,-2191,-2177,-2162,
+-2144,-2125,-2105,-2084,-2063,-2042,-2021,-2002,-1985,-1970,-1957,-1946,-1938,-1932,-1928,-1926,-1925,-1924,-1925,-1925,-1926,
+-1926,-1927,-1927,-1926,-1924,-1922,-1919,-1914,-1907,-1899,-1889,-1877,-1864,-1849,-1834,-1818,-1803,-1790,-1780,-1772,-1769,
+-1770,-1776,-1786,-1800,-1818,-1837,-1858,-1879,-1898,-1914,-1927,-1937,-1942,-1944,-1943,-1939,-1934,-1929,-1924,-1920,-1919,
+-1919,-1922,-1926,-1931,-1935,-1939,-1940,-1937,-1930,-1919,-1903,-1882,-1857,-1829,-1798,-1767,-1736,-1707,-1680,-1657,-1638,
+-1623,-1612,-1606,-1603,-1603,-1606,-1611,-1616,-1623,-1630,-1637,-1644,-1651,-1657,-1662,-1666,-1668,-1668,-1666,-1660,-1651,
+-1638,-1621,-1599,-1574,-1545,-1514,-1481,-1448,-1415,-1384,-1357,-1333,-1313,-1299,-1289,-1284,-1283,-1285,-1290,-1295,-1300,
+-1305,-1307,-1308,-1307,-1303,-1297,-1289,-1280,-1270,-1261,-1253,-1246,-1240,-1237,-1235,-1236,-1238,-1241,-1245,-1249,-1254,
+-1257,-1260,-1261,-1262,-1261,-1258,-1255,-1251,-1246,-1240,-1234,-1228,-1223,-1217,-1211,-1205,-1199,-1193,-1186,-1178,-1170,
+-1161,-1150,-1139,-1127,-1115,-1102,-1089,-1076,-1064,-1052,-1041,-1032,-1023,-1015,-1007,-1001,-994,-989,-983,-977,-971,
+-965,-959,-953,-948,-943,-939,-935,-931,-929,-926,-924,-922,-920,-918,-915,-912,-909,-905,-902,-899,-896,
+-894,-893,-892,-893,-894,-895,-897,-898,-899,-899,-898,-896,-892,-888,-883,-877,-871,-865,-860,-855,-850,
+-846,-842,-838,-833,-827,-821,-813,-803,-793,-781,-768,-755,-742,-729,-716,-704,-691,-678,-663,-648,-629,
+-608,-584,-556,-525,-490,-453,-415,-376,-338,-301,-267,-237,-211,-189,-170,-155,-141,-129,-117,-104,-89,
+-73,-56,-37,-18,0,16,29,37,40,37,29,15,-2,-22,-43,-62,-77,-86,-89,-83,-68,
+-45,-14,23,66,111,158,203,245,283,316,344,366,383,396,406,415,422,430,439,449,460,
+473,486,499,512,523,533,540,545,548,549,548,546,544,542,540,539,539,540,542,546,550,
+555,560,565,571,576,581,586,590,594,597,599,600,599,597,593,587,578,568,556,542,528,
+513,498,484,472,462,454,372,369,368,369,373,377,383,390,396,403,410,417,423,429,436,
+443,451,459,469,480,491,502,514,526,537,547,556,564,570,576,581,586,591,597,604,612,
+622,634,647,662,676,691,705,717,727,735,740,743,743,742,740,738,737,738,742,749,760,
+775,794,816,842,869,898,928,956,983,1008,1030,1050,1066,1080,1091,1100,1107,1113,1119,1124,1130,
+1135,1141,1148,1154,1161,1168,1176,1183,1191,1200,1209,1219,1230,1242,1255,1270,1285,1301,1316,1332,1347,
+1361,1374,1385,1394,1402,1408,1414,1419,1423,1427,1431,1435,1439,1442,1444,1443,1440,1434,1423,1409,1389,
+1366,1339,1309,1278,1246,1216,1189,1166,1148,1137,1132,1134,1142,1155,1173,1193,1214,1235,1254,1269,1281,
+1289,1292,1291,1286,1278,1267,1256,1244,1233,1223,1214,1207,1201,1197,1193,1190,1188,1185,1183,1180,1177,
+1174,1171,1169,1168,1167,1168,1169,1172,1174,1177,1179,1180,1180,1178,1175,1169,1162,1153,1144,1133,1124,
+1114,1106,1099,1094,1091,1089,1089,1090,1092,1094,1096,1097,1099,1100,1100,1101,1101,1103,1105,1109,1115,
+1122,1132,1143,1155,1168,1181,1194,1205,1215,1222,1226,1227,1225,1220,1212,1201,1189,1175,1160,1145,1130,
+1114,1099,1084,1069,1054,1040,1026,1013,1001,990,982,976,974,975,981,991,1006,1025,1047,1071,1096,
+1121,1144,1163,1177,1185,1186,1178,1163,1140,1110,1073,1033,989,945,901,858,819,785,754,729,709,
+693,681,672,665,658,651,644,634,623,610,594,577,559,539,520,501,484,468,455,444,436,
+431,428,427,427,428,429,429,428,425,421,414,406,396,385,373,361,350,340,332,326,322,
+320,320,321,323,325,327,328,327,326,323,319,315,311,307,305,304,305,309,314,321,329,
+337,345,351,355,358,357,355,351,346,341,336,333,332,333,337,343,350,357,364,367,367,
+360,347,326,298,262,219,171,118,64,9,-44,-95,-142,-185,-224,-257,-287,-314,-339,-364,-388,
+-413,-439,-467,-497,-527,-559,-590,-620,-649,-676,-702,-725,-746,-766,-785,-805,-825,-847,-871,-898,-928,
+-962,-999,-1039,-1081,-1126,-1173,-1221,-1270,-1319,-1369,-1418,-1467,-1514,-1560,-1604,-1645,-1683,-1717,-1746,-1771,-1790,
+-1804,-1812,-1816,-1815,-1811,-1805,-1798,-1792,-1786,-1784,-1785,-1790,-1800,-1814,-1833,-1855,-1882,-1911,-1942,-1975,-2009,
+-2043,-2078,-2114,-2151,-2188,-2226,-2266,-2307,-2350,-2394,-2439,-2485,-2531,-2577,-2621,-2664,-2705,-2745,-2782,-2817,-2850,
+-2883,-2916,-2948,-2981,-3016,-3052,-3090,-3129,-3169,-3210,-3250,-3290,-3328,-3363,-3396,-3427,-3454,-3478,-3500,-3520,-3538,
+-3556,-3574,-3592,-3611,-3631,-3653,-3676,-3701,-3728,-3756,-3786,-3816,-3847,-3878,-3910,-3940,-3971,-3999,-4025,-4049,-4069,
+-4085,-4096,-4102,-4103,-4100,-4092,-4082,-4070,-4057,-4046,-4038,-4035,-4037,-4046,-4062,-4086,-4115,-4151,-4190,-4232,-4274,
+-4315,-4354,-4389,-4420,-4447,-4470,-4490,-4508,-4526,-4545,-4567,-4593,-4623,-4657,-4696,-4737,-4781,-4825,-4867,-4907,-4942,
+-4971,-4993,-5010,-5020,-5025,-5026,-5024,-5022,-5021,-5022,-5027,-5036,-5050,-5068,-5091,-5117,-5146,-5176,-5206,-5236,-5266,
+-5294,-5321,-5346,-5371,-5394,-5417,-5440,-5462,-5485,-5508,-5530,-5551,-5572,-5591,-5608,-5623,-5637,-5648,-5658,-5666,-5674,
+-5681,-5689,-5698,-5707,-5717,-5728,-5740,-5751,-5762,-5772,-5781,-5788,-5792,-5794,-5793,-5790,-5785,-5778,-5769,-5760,-5750,
+-5739,-5727,-5715,-5703,-5690,-5677,-5663,-5649,-5636,-5623,-5611,-5601,-5593,-5588,-5586,-5586,-5589,-5594,-5599,-5605,-5609,
+-5610,-5607,-5600,-5587,-5568,-5544,-5515,-5483,-5450,-5418,-5389,-5365,-5349,-5340,-5342,-5353,-5374,-5403,-5440,-5481,-5524,
+-5568,-5610,-5647,-5679,-5704,-5721,-5731,-5735,-5734,-5728,-5720,-5712,-5703,-5696,-5691,-5687,-5686,-5687,-5688,-5690,-5691,
+-5692,-5691,-5689,-5687,-5683,-5681,-5679,-5680,-5682,-5688,-5696,-5706,-5719,-5731,-5743,-5753,-5760,-5762,-5760,-5753,-5740,
+-5724,-5704,-5682,-5660,-5640,-5623,-5610,-5602,-5599,-5603,-5611,-5624,-5641,-5659,-5678,-5697,-5713,-5728,-5739,-5748,-5754,
+-5758,-5760,-5762,-5764,-5766,-5770,-5776,-5784,-5793,-5804,-5816,-5828,-5840,-5852,-5864,-5874,-5884,-5892,-5899,-5905,-5911,
+-5915,-5918,-5921,-5922,-5922,-5921,-5918,-5914,-5909,-5902,-5894,-5885,-5876,-5867,-5858,-5850,-5844,-5839,-5835,-5832,-5831,
+-5831,-5831,-5832,-5833,-5834,-5834,-5834,-5834,-5834,-5833,-5832,-5831,-5830,-5830,-5829,-5828,-5827,-5826,-5826,-5825,-5826,
+-5826,-5828,-5832,-5837,-5844,-5854,-5866,-5879,-5895,-5912,-5930,-5948,-5964,-5979,-5991,-6000,-6006,-6007,-6005,-5999,-5991,
+-5981,-5970,-5959,-5948,-5938,-5931,-5926,-5923,-5922,-5924,-5927,-5931,-5936,-5941,-5946,-5950,-5954,-5957,-5959,-5959,-5959,
+-5958,-5955,-5951,-5945,-5938,-5927,-5914,-5899,-5880,-5858,-5833,-5806,-5777,-5747,-5717,-5688,-5660,-5635,-5614,-5595,-5581,
+-5570,-5562,-5557,-5554,-5552,-5550,-5548,-5544,-5539,-5531,-5522,-5510,-5496,-5480,-5463,-5445,-5426,-5406,-5385,-5363,-5340,
+-5315,-5288,-5259,-5228,-5194,-5158,-5119,-5078,-5035,-4991,-4947,-4903,-4860,-4818,-4778,-4740,-4704,-4671,-4640,-4611,-4585,
+-4559,-4536,-4514,-4492,-4472,-4453,-4435,-4419,-4403,-4388,-4375,-4363,-4352,-4341,-4331,-4320,-4310,-4298,-4287,-4274,-4260,
+-4246,-4231,-4215,-4201,-4187,-4174,-4162,-4153,-4146,-4141,-4138,-4137,-4137,-4138,-4138,-4138,-4137,-4133,-4126,-4115,-4100,
+-4081,-4057,-4028,-3996,-3959,-3919,-3876,-3831,-3785,-3738,-3692,-3646,-3602,-3561,-3522,-3487,-3456,-3430,-3409,-3394,-3384,
+-3381,-3385,-3395,-3410,-3431,-3457,-3487,-3519,-3552,-3585,-3616,-3645,-3669,-3688,-3702,-3711,-3713,-3711,-3704,-3694,-3682,
+-3669,-3657,-3646,-3637,-3632,-3629,-3630,-3633,-3638,-3643,-3649,-3652,-3653,-3651,-3645,-3634,-3619,-3601,-3579,-3554,-3529,
+-3503,-3478,-3454,-3433,-3416,-3402,-3393,-3387,-3386,-3387,-3392,-3399,-3407,-3417,-3426,-3435,-3443,-3449,-3452,-3454,-3452,
+-3447,-3439,-3428,-3414,-3396,-3376,-3352,-3327,-3300,-3271,-3242,-3213,-3184,-3156,-3129,-3104,-3081,-3060,-3041,-3025,-3010,
+-2998,-2986,-2975,-2965,-2955,-2945,-2934,-2922,-2909,-2894,-2878,-2861,-2841,-2821,-2799,-2777,-2753,-2729,-2704,-2680,-2656,
+-2632,-2609,-2586,-2565,-2545,-2527,-2510,-2494,-2479,-2466,-2454,-2443,-2432,-2422,-2412,-2402,-2392,-2381,-2370,-2359,-2347,
+-2335,-2322,-2309,-2296,-2283,-2269,-2255,-2241,-2226,-2211,-2196,-2180,-2164,-2146,-2129,-2111,-2093,-2075,-2057,-2039,-2023,
+-2007,-1992,-1979,-1968,-1957,-1949,-1942,-1937,-1932,-1930,-1929,-1929,-1930,-1931,-1934,-1936,-1939,-1941,-1942,-1942,-1939,
+-1934,-1926,-1915,-1901,-1884,-1864,-1842,-1819,-1796,-1775,-1756,-1741,-1730,-1725,-1727,-1736,-1750,-1771,-1797,-1827,-1860,
+-1893,-1927,-1959,-1987,-2012,-2033,-2049,-2060,-2067,-2070,-2070,-2068,-2065,-2061,-2056,-2052,-2048,-2045,-2041,-2037,-2033,
+-2027,-2020,-2011,-2000,-1987,-1972,-1956,-1939,-1921,-1904,-1886,-1870,-1855,-1841,-1829,-1818,-1810,-1803,-1797,-1793,-1790,
+-1789,-1788,-1789,-1790,-1791,-1792,-1793,-1793,-1791,-1787,-1780,-1770,-1755,-1737,-1714,-1687,-1657,-1623,-1587,-1550,-1514,
+-1478,-1445,-1415,-1390,-1369,-1353,-1343,-1336,-1334,-1335,-1338,-1341,-1345,-1349,-1350,-1350,-1348,-1343,-1337,-1330,-1321,
+-1313,-1304,-1297,-1292,-1288,-1286,-1285,-1287,-1290,-1293,-1298,-1302,-1306,-1309,-1312,-1313,-1313,-1312,-1311,-1308,-1306,
+-1303,-1300,-1297,-1294,-1291,-1288,-1285,-1281,-1276,-1271,-1264,-1256,-1246,-1235,-1223,-1211,-1198,-1184,-1171,-1159,-1147,
+-1137,-1127,-1119,-1112,-1106,-1101,-1096,-1091,-1087,-1083,-1078,-1073,-1068,-1063,-1058,-1053,-1048,-1043,-1039,-1035,-1031,
+-1028,-1026,-1023,-1021,-1018,-1016,-1014,-1011,-1009,-1008,-1007,-1006,-1006,-1006,-1008,-1009,-1011,-1012,-1013,-1013,-1012,
+-1009,-1006,-1001,-994,-988,-980,-972,-965,-958,-952,-947,-942,-938,-933,-928,-922,-914,-904,-891,-876,-859,
+-839,-817,-794,-771,-748,-725,-703,-682,-662,-642,-622,-600,-578,-552,-524,-493,-458,-421,-381,-341,-299,
+-259,-222,-187,-157,-131,-109,-92,-79,-68,-59,-50,-41,-31,-19,-6,8,24,38,51,61,66,
+65,59,48,31,11,-11,-34,-56,-73,-83,-87,-81,-66,-42,-10,28,72,118,165,210,251,
+287,317,340,356,367,373,375,376,375,375,377,381,388,396,407,419,431,442,453,461,467,
+470,471,470,466,462,457,452,448,446,444,445,447,451,457,463,470,477,485,492,498,504,
+509,512,513,513,511,508,502,494,485,473,461,448,434,420,407,396,386,378,372,290,285,
+282,281,282,284,288,293,300,307,314,322,331,340,349,359,370,381,392,404,416,429,441,
+453,465,476,485,494,502,509,516,523,529,536,544,553,563,575,587,601,615,629,642,654,
+664,673,679,683,685,686,686,685,686,687,691,698,708,722,739,760,783,809,835,862,889,
+915,938,960,978,995,1008,1019,1029,1037,1044,1050,1056,1063,1069,1076,1084,1092,1100,1108,1116,1125,
+1134,1143,1152,1162,1173,1184,1197,1210,1225,1240,1255,1270,1284,1298,1310,1321,1331,1338,1345,1350,1354,
+1357,1360,1363,1366,1369,1371,1372,1373,1371,1368,1361,1351,1338,1321,1302,1279,1255,1231,1206,1184,1164,
+1148,1136,1130,1129,1132,1140,1151,1164,1179,1194,1207,1219,1228,1233,1236,1235,1232,1226,1218,1210,1201,
+1193,1185,1179,1173,1168,1164,1160,1156,1153,1149,1145,1141,1137,1133,1131,1129,1128,1129,1132,1136,1140,
+1145,1150,1154,1157,1157,1155,1150,1143,1134,1122,1109,1096,1082,1070,1060,1051,1046,1043,1043,1045,1049,
+1054,1059,1064,1069,1072,1074,1074,1073,1072,1070,1069,1069,1070,1074,1080,1088,1099,1111,1125,1139,1153,
+1165,1176,1184,1189,1191,1190,1186,1179,1169,1157,1144,1130,1114,1099,1083,1068,1052,1037,1021,1007,993,
+980,968,959,952,948,949,953,961,974,990,1010,1031,1053,1074,1094,1109,1120,1125,1123,1113,1097,
+1074,1045,1011,973,934,894,856,821,789,761,738,719,705,694,685,678,672,665,656,646,633,
+618,600,581,560,539,518,498,481,466,453,444,438,434,433,433,435,436,437,437,435,432,
+426,417,407,396,384,371,359,348,339,331,326,323,322,323,325,327,329,331,331,330,327,
+322,316,310,302,295,289,284,280,279,280,282,286,290,295,298,301,301,300,296,290,282,
+274,265,256,250,245,242,241,243,246,250,253,254,252,246,235,218,195,166,132,93,51,
+7,-36,-80,-122,-162,-198,-231,-261,-289,-314,-338,-362,-386,-412,-439,-468,-499,-530,-563,-596,-629,
+-660,-690,-718,-744,-768,-791,-813,-834,-857,-880,-906,-935,-967,-1002,-1041,-1083,-1129,-1177,-1228,-1281,-1334,
+-1388,-1441,-1494,-1544,-1593,-1639,-1681,-1720,-1755,-1786,-1811,-1832,-1848,-1859,-1866,-1869,-1868,-1865,-1860,-1854,-1848,
+-1843,-1840,-1840,-1842,-1848,-1858,-1871,-1888,-1908,-1932,-1958,-1987,-2017,-2050,-2085,-2121,-2159,-2198,-2239,-2280,-2323,
+-2366,-2409,-2453,-2496,-2538,-2580,-2620,-2659,-2697,-2733,-2768,-2803,-2837,-2871,-2906,-2941,-2977,-3015,-3053,-3092,-3131,
+-3170,-3209,-3247,-3283,-3318,-3350,-3380,-3408,-3434,-3458,-3481,-3503,-3524,-3545,-3567,-3589,-3612,-3635,-3660,-3685,-3710,
+-3737,-3764,-3791,-3820,-3848,-3877,-3906,-3935,-3963,-3990,-4016,-4040,-4061,-4078,-4091,-4100,-4105,-4105,-4102,-4095,-4087,
+-4078,-4070,-4065,-4063,-4066,-4075,-4091,-4112,-4139,-4172,-4207,-4245,-4284,-4322,-4357,-4390,-4419,-4444,-4465,-4484,-4502,
+-4519,-4537,-4557,-4581,-4609,-4640,-4676,-4715,-4757,-4799,-4841,-4880,-4916,-4947,-4973,-4993,-5007,-5017,-5022,-5024,-5024,
+-5025,-5026,-5030,-5037,-5047,-5062,-5081,-5103,-5128,-5155,-5183,-5213,-5243,-5272,-5300,-5328,-5355,-5380,-5405,-5429,-5452,
+-5475,-5496,-5517,-5537,-5555,-5572,-5587,-5601,-5613,-5624,-5635,-5644,-5653,-5663,-5673,-5683,-5694,-5705,-5717,-5729,-5740,
+-5751,-5761,-5769,-5775,-5779,-5780,-5780,-5777,-5773,-5766,-5759,-5750,-5741,-5730,-5719,-5707,-5694,-5680,-5666,-5651,-5636,
+-5621,-5607,-5593,-5581,-5572,-5564,-5559,-5556,-5555,-5555,-5555,-5555,-5554,-5550,-5542,-5529,-5513,-5491,-5465,-5436,-5406,
+-5375,-5346,-5321,-5302,-5290,-5285,-5290,-5304,-5325,-5354,-5389,-5427,-5466,-5506,-5542,-5574,-5601,-5622,-5637,-5646,-5650,
+-5649,-5646,-5641,-5635,-5630,-5626,-5624,-5623,-5624,-5625,-5627,-5629,-5630,-5630,-5629,-5627,-5625,-5623,-5622,-5623,-5627,
+-5633,-5642,-5654,-5667,-5682,-5697,-5711,-5722,-5729,-5731,-5728,-5719,-5705,-5686,-5664,-5640,-5615,-5592,-5573,-5557,-5547,
+-5543,-5545,-5553,-5565,-5581,-5599,-5619,-5638,-5656,-5672,-5686,-5696,-5704,-5710,-5714,-5718,-5721,-5725,-5731,-5738,-5746,
+-5757,-5769,-5782,-5795,-5808,-5821,-5834,-5845,-5854,-5862,-5868,-5874,-5877,-5880,-5881,-5882,-5882,-5881,-5879,-5876,-5872,
+-5867,-5862,-5856,-5849,-5842,-5835,-5828,-5821,-5816,-5811,-5808,-5806,-5804,-5804,-5804,-5805,-5807,-5808,-5810,-5811,-5812,
+-5813,-5814,-5815,-5817,-5818,-5820,-5822,-5824,-5827,-5831,-5835,-5840,-5845,-5851,-5858,-5865,-5873,-5882,-5891,-5900,-5910,
+-5920,-5929,-5937,-5944,-5949,-5951,-5951,-5948,-5942,-5933,-5921,-5907,-5892,-5875,-5858,-5841,-5825,-5810,-5797,-5787,-5778,
+-5772,-5768,-5765,-5764,-5763,-5764,-5764,-5764,-5764,-5764,-5764,-5762,-5761,-5759,-5756,-5752,-5748,-5743,-5737,-5730,-5721,
+-5710,-5699,-5685,-5671,-5655,-5639,-5623,-5608,-5593,-5580,-5569,-5559,-5551,-5545,-5541,-5537,-5534,-5531,-5528,-5523,-5517,
+-5509,-5499,-5486,-5472,-5456,-5438,-5418,-5398,-5377,-5356,-5335,-5313,-5291,-5268,-5245,-5221,-5195,-5168,-5139,-5108,-5075,
+-5040,-5004,-4966,-4927,-4888,-4849,-4810,-4772,-4736,-4701,-4668,-4638,-4610,-4584,-4561,-4540,-4521,-4503,-4488,-4474,-4461,
+-4448,-4437,-4426,-4414,-4403,-4391,-4379,-4366,-4352,-4338,-4324,-4310,-4295,-4281,-4267,-4254,-4242,-4230,-4220,-4212,-4204,
+-4198,-4192,-4187,-4182,-4177,-4172,-4165,-4158,-4149,-4138,-4125,-4110,-4093,-4073,-4051,-4026,-3998,-3968,-3936,-3901,-3864,
+-3825,-3784,-3743,-3702,-3661,-3620,-3582,-3547,-3516,-3489,-3468,-3452,-3443,-3441,-3446,-3456,-3473,-3494,-3520,-3547,-3577,
+-3606,-3633,-3659,-3680,-3697,-3709,-3717,-3719,-3718,-3712,-3704,-3695,-3684,-3674,-3665,-3657,-3652,-3648,-3647,-3647,-3648,
+-3650,-3652,-3652,-3651,-3648,-3643,-3635,-3625,-3613,-3600,-3585,-3570,-3555,-3541,-3527,-3515,-3505,-3497,-3490,-3485,-3481,
+-3478,-3477,-3476,-3476,-3476,-3476,-3477,-3478,-3479,-3479,-3479,-3479,-3477,-3474,-3469,-3462,-3452,-3439,-3424,-3406,-3385,
+-3362,-3336,-3310,-3282,-3255,-3228,-3202,-3178,-3156,-3136,-3118,-3102,-3089,-3077,-3066,-3056,-3046,-3036,-3025,-3013,-3000,
+-2985,-2970,-2953,-2934,-2915,-2894,-2873,-2851,-2829,-2806,-2782,-2758,-2734,-2710,-2687,-2663,-2640,-2617,-2595,-2575,-2555,
+-2537,-2521,-2505,-2491,-2478,-2466,-2455,-2443,-2431,-2419,-2406,-2392,-2377,-2360,-2343,-2325,-2307,-2288,-2269,-2250,-2231,
+-2213,-2196,-2179,-2162,-2146,-2130,-2113,-2096,-2079,-2061,-2042,-2023,-2003,-1982,-1962,-1943,-1924,-1907,-1892,-1880,-1870,
+-1864,-1861,-1862,-1866,-1874,-1884,-1897,-1910,-1925,-1939,-1951,-1962,-1968,-1971,-1968,-1960,-1946,-1927,-1903,-1875,-1843,
+-1810,-1776,-1744,-1716,-1692,-1674,-1664,-1663,-1670,-1686,-1710,-1742,-1779,-1822,-1867,-1913,-1958,-2000,-2039,-2072,-2099,
+-2119,-2133,-2139,-2140,-2135,-2126,-2114,-2099,-2082,-2066,-2049,-2034,-2019,-2007,-1996,-1986,-1978,-1971,-1964,-1957,-1950,
+-1942,-1932,-1922,-1910,-1897,-1882,-1866,-1850,-1833,-1817,-1802,-1789,-1778,-1769,-1764,-1761,-1760,-1762,-1766,-1770,-1775,
+-1779,-1780,-1779,-1774,-1764,-1750,-1731,-1707,-1679,-1648,-1614,-1579,-1545,-1512,-1482,-1455,-1433,-1415,-1402,-1393,-1388,
+-1386,-1387,-1389,-1392,-1394,-1394,-1394,-1391,-1387,-1381,-1374,-1366,-1359,-1351,-1345,-1340,-1337,-1336,-1336,-1338,-1341,
+-1345,-1349,-1353,-1356,-1359,-1360,-1360,-1360,-1359,-1357,-1355,-1354,-1353,-1352,-1352,-1353,-1354,-1356,-1357,-1357,-1356,
+-1354,-1350,-1344,-1336,-1327,-1316,-1303,-1290,-1276,-1262,-1249,-1237,-1226,-1216,-1207,-1200,-1194,-1189,-1184,-1180,-1176,
+-1172,-1167,-1163,-1159,-1154,-1149,-1145,-1141,-1137,-1134,-1131,-1129,-1126,-1125,-1123,-1121,-1119,-1117,-1116,-1114,-1112,
+-1111,-1111,-1110,-1111,-1112,-1114,-1115,-1117,-1118,-1119,-1118,-1116,-1113,-1108,-1101,-1093,-1083,-1074,-1064,-1054,-1045,
+-1037,-1030,-1024,-1018,-1012,-1005,-997,-986,-973,-955,-934,-909,-881,-849,-815,-779,-743,-707,-672,-639,-608,
+-580,-553,-529,-506,-483,-460,-435,-410,-383,-354,-323,-292,-261,-231,-203,-178,-156,-138,-124,-113,-105,
+-99,-95,-91,-86,-80,-72,-62,-51,-39,-28,-17,-9,-4,-4,-8,-17,-30,-45,-63,-80,-96,
+-108,-114,-114,-106,-89,-65,-34,2,43,85,127,168,204,235,259,278,290,296,298,297,293,
+289,286,285,286,289,295,303,312,322,332,340,347,351,353,353,350,346,341,336,331,327,
+325,324,326,329,334,340,348,356,364,372,379,386,391,395,398,400,400,399,397,393,388,
+381,374,365,356,345,335,324,314,305,297,290,164,153,143,136,131,128,128,130,135,143,
+152,164,176,190,205,220,236,252,267,282,297,312,325,339,351,363,374,384,394,403,412,
+421,430,439,449,460,471,483,495,508,521,534,546,557,567,575,582,587,591,593,595,597,
+600,603,608,615,624,636,650,666,685,705,726,748,770,792,813,833,851,868,884,898,911,
+924,937,949,960,972,984,995,1006,1017,1027,1036,1045,1053,1061,1069,1077,1086,1095,1104,1115,1127,
+1141,1155,1169,1184,1198,1212,1225,1236,1246,1254,1260,1264,1267,1269,1271,1272,1273,1274,1275,1277,1278,
+1279,1279,1277,1274,1269,1262,1252,1240,1226,1211,1196,1180,1166,1153,1142,1133,1128,1125,1125,1126,1130,
+1134,1139,1143,1146,1148,1149,1147,1145,1140,1135,1129,1123,1117,1112,1108,1104,1101,1099,1097,1096,1094,
+1093,1091,1089,1087,1086,1085,1085,1086,1088,1091,1096,1101,1107,1113,1118,1122,1124,1123,1120,1114,1105,
+1093,1080,1065,1051,1036,1024,1013,1005,1001,999,1001,1005,1011,1019,1027,1034,1040,1045,1047,1047,1044,
+1041,1036,1030,1025,1022,1020,1020,1024,1030,1039,1050,1062,1076,1090,1103,1114,1124,1131,1136,1137,1135,
+1131,1124,1115,1104,1092,1078,1064,1050,1035,1020,1006,992,978,966,954,945,938,933,931,932,936,
+943,952,963,976,988,1000,1010,1017,1020,1018,1012,1001,984,963,939,912,883,854,826,799,775,
+754,737,722,711,702,694,686,679,669,658,645,629,610,589,566,543,519,496,475,457,442,
+431,424,420,420,423,427,433,439,444,448,449,448,444,438,429,418,407,394,383,372,364,
+357,354,353,354,357,361,366,370,373,375,374,370,364,355,343,330,316,302,288,276,264,
+255,248,242,238,234,231,227,222,214,205,193,179,163,146,128,110,93,78,66,56,49,
+45,42,41,40,39,37,32,23,12,-3,-22,-44,-69,-96,-125,-153,-181,-209,-235,-260,-283,
+-305,-327,-348,-370,-394,-418,-445,-474,-504,-536,-569,-603,-637,-671,-703,-734,-764,-792,-819,-846,-872,
+-899,-927,-956,-988,-1023,-1061,-1103,-1148,-1196,-1246,-1298,-1351,-1405,-1459,-1511,-1562,-1610,-1656,-1698,-1737,-1773,
+-1804,-1831,-1855,-1876,-1892,-1906,-1917,-1925,-1931,-1935,-1937,-1938,-1938,-1938,-1938,-1938,-1939,-1941,-1945,-1951,-1959,
+-1969,-1982,-1999,-2019,-2042,-2069,-2099,-2133,-2169,-2208,-2248,-2291,-2334,-2378,-2422,-2464,-2506,-2547,-2586,-2623,-2659,
+-2694,-2728,-2762,-2796,-2830,-2865,-2901,-2938,-2976,-3015,-3055,-3095,-3135,-3173,-3211,-3247,-3282,-3315,-3346,-3375,-3403,
+-3430,-3456,-3482,-3508,-3534,-3560,-3586,-3613,-3639,-3665,-3691,-3715,-3739,-3763,-3785,-3807,-3829,-3851,-3873,-3896,-3920,
+-3945,-3971,-3997,-4024,-4049,-4073,-4095,-4114,-4130,-4141,-4149,-4154,-4155,-4154,-4152,-4151,-4150,-4152,-4158,-4167,-4181,
+-4200,-4222,-4248,-4276,-4306,-4336,-4365,-4393,-4418,-4441,-4461,-4479,-4496,-4512,-4529,-4547,-4567,-4591,-4618,-4648,-4682,
+-4718,-4756,-4794,-4831,-4867,-4899,-4928,-4952,-4972,-4988,-4999,-5007,-5013,-5018,-5022,-5028,-5035,-5045,-5058,-5074,-5094,
+-5116,-5140,-5167,-5195,-5224,-5252,-5281,-5308,-5334,-5360,-5383,-5405,-5426,-5446,-5464,-5481,-5498,-5513,-5528,-5543,-5557,
+-5571,-5586,-5600,-5615,-5631,-5646,-5662,-5677,-5693,-5707,-5721,-5733,-5744,-5753,-5760,-5764,-5767,-5767,-5766,-5763,-5759,
+-5754,-5748,-5743,-5737,-5730,-5723,-5716,-5708,-5698,-5688,-5676,-5663,-5649,-5633,-5617,-5601,-5586,-5571,-5557,-5545,-5534,
+-5524,-5516,-5508,-5500,-5491,-5480,-5467,-5451,-5431,-5409,-5384,-5357,-5330,-5303,-5279,-5257,-5241,-5231,-5228,-5232,-5243,
+-5261,-5284,-5312,-5343,-5376,-5408,-5439,-5467,-5490,-5510,-5525,-5535,-5542,-5545,-5546,-5545,-5544,-5542,-5540,-5539,-5537,
+-5536,-5535,-5534,-5532,-5530,-5527,-5524,-5522,-5520,-5520,-5522,-5527,-5536,-5548,-5563,-5582,-5602,-5623,-5644,-5662,-5678,
+-5689,-5695,-5695,-5689,-5677,-5660,-5639,-5616,-5592,-5569,-5548,-5531,-5519,-5512,-5510,-5514,-5522,-5535,-5550,-5566,-5584,
+-5601,-5617,-5631,-5644,-5655,-5664,-5672,-5680,-5687,-5695,-5704,-5714,-5725,-5737,-5750,-5764,-5777,-5790,-5802,-5813,-5822,
+-5830,-5836,-5840,-5844,-5846,-5847,-5848,-5848,-5848,-5847,-5846,-5845,-5843,-5841,-5837,-5834,-5829,-5824,-5818,-5813,-5807,
+-5801,-5797,-5792,-5789,-5787,-5785,-5785,-5785,-5786,-5788,-5790,-5792,-5794,-5797,-5799,-5801,-5803,-5805,-5807,-5810,-5813,
+-5816,-5819,-5823,-5828,-5833,-5838,-5844,-5850,-5856,-5862,-5868,-5874,-5880,-5885,-5889,-5891,-5893,-5892,-5890,-5885,-5879,
+-5870,-5859,-5847,-5833,-5818,-5803,-5787,-5772,-5757,-5743,-5731,-5720,-5710,-5702,-5694,-5688,-5682,-5677,-5672,-5668,-5662,
+-5657,-5652,-5646,-5640,-5634,-5628,-5622,-5617,-5611,-5607,-5602,-5597,-5593,-5589,-5584,-5579,-5574,-5568,-5562,-5556,-5549,
+-5543,-5536,-5529,-5523,-5517,-5510,-5504,-5497,-5490,-5482,-5473,-5463,-5452,-5440,-5426,-5412,-5396,-5379,-5362,-5345,-5327,
+-5310,-5293,-5276,-5260,-5244,-5227,-5211,-5194,-5176,-5156,-5135,-5113,-5088,-5061,-5033,-5002,-4971,-4938,-4905,-4871,-4838,
+-4806,-4775,-4746,-4720,-4695,-4673,-4652,-4634,-4618,-4604,-4590,-4577,-4564,-4551,-4538,-4524,-4508,-4492,-4475,-4457,-4438,
+-4419,-4401,-4382,-4365,-4349,-4334,-4321,-4309,-4299,-4291,-4283,-4277,-4271,-4265,-4259,-4252,-4244,-4234,-4223,-4211,-4197,
+-4181,-4164,-4146,-4126,-4106,-4085,-4062,-4039,-4015,-3990,-3963,-3936,-3907,-3876,-3845,-3813,-3781,-3748,-3717,-3688,-3661,
+-3637,-3617,-3602,-3593,-3588,-3589,-3594,-3605,-3619,-3636,-3654,-3674,-3693,-3711,-3726,-3738,-3746,-3751,-3752,-3749,-3743,
+-3735,-3725,-3715,-3704,-3693,-3684,-3676,-3669,-3664,-3660,-3658,-3656,-3654,-3652,-3649,-3646,-3642,-3636,-3630,-3623,-3615,
+-3607,-3600,-3592,-3585,-3578,-3572,-3567,-3562,-3557,-3551,-3546,-3540,-3533,-3525,-3518,-3510,-3502,-3494,-3487,-3481,-3477,
+-3474,-3472,-3471,-3471,-3471,-3472,-3471,-3470,-3466,-3460,-3452,-3441,-3427,-3411,-3392,-3372,-3351,-3330,-3309,-3288,-3268,
+-3250,-3232,-3217,-3202,-3189,-3176,-3163,-3150,-3137,-3124,-3110,-3096,-3081,-3065,-3050,-3034,-3019,-3004,-2989,-2973,-2958,
+-2942,-2926,-2909,-2890,-2870,-2849,-2826,-2801,-2776,-2749,-2722,-2696,-2669,-2644,-2620,-2597,-2575,-2554,-2535,-2516,-2498,
+-2479,-2460,-2441,-2420,-2398,-2376,-2352,-2328,-2304,-2279,-2256,-2233,-2212,-2192,-2173,-2156,-2139,-2122,-2106,-2088,-2069,
+-2049,-2026,-2001,-1975,-1946,-1916,-1886,-1857,-1829,-1804,-1782,-1766,-1755,-1750,-1751,-1760,-1775,-1795,-1820,-1849,-1881,
+-1913,-1944,-1973,-1998,-2018,-2031,-2036,-2034,-2023,-2004,-1977,-1944,-1905,-1863,-1819,-1774,-1732,-1695,-1663,-1638,-1622,
+-1616,-1620,-1635,-1659,-1691,-1731,-1777,-1826,-1877,-1928,-1975,-2019,-2057,-2087,-2109,-2122,-2126,-2122,-2111,-2093,-2071,
+-2044,-2016,-1987,-1959,-1933,-1911,-1892,-1877,-1865,-1858,-1853,-1850,-1848,-1847,-1844,-1840,-1833,-1824,-1811,-1796,-1779,
+-1759,-1739,-1720,-1701,-1685,-1672,-1662,-1656,-1655,-1657,-1663,-1671,-1680,-1689,-1697,-1703,-1706,-1705,-1699,-1688,-1673,
+-1654,-1632,-1607,-1582,-1556,-1532,-1510,-1490,-1474,-1462,-1453,-1447,-1444,-1443,-1442,-1442,-1442,-1440,-1437,-1433,-1426,
+-1419,-1411,-1402,-1394,-1386,-1380,-1375,-1372,-1372,-1373,-1375,-1379,-1383,-1387,-1390,-1393,-1395,-1395,-1395,-1393,-1391,
+-1389,-1387,-1386,-1386,-1387,-1389,-1393,-1397,-1402,-1408,-1412,-1416,-1419,-1420,-1418,-1414,-1408,-1400,-1389,-1378,-1365,
+-1352,-1339,-1327,-1315,-1304,-1294,-1285,-1278,-1271,-1265,-1259,-1254,-1248,-1243,-1238,-1234,-1229,-1226,-1222,-1220,-1218,
+-1217,-1217,-1218,-1218,-1219,-1220,-1221,-1221,-1220,-1219,-1218,-1216,-1214,-1213,-1212,-1211,-1211,-1212,-1213,-1214,-1216,
+-1217,-1217,-1215,-1213,-1208,-1201,-1193,-1182,-1171,-1158,-1145,-1132,-1119,-1107,-1095,-1083,-1072,-1060,-1046,-1031,-1013,
+-992,-966,-937,-904,-867,-827,-784,-741,-697,-655,-615,-578,-544,-515,-491,-470,-452,-437,-425,-413,-401,
+-389,-376,-362,-347,-332,-316,-301,-286,-272,-260,-250,-241,-233,-227,-221,-214,-207,-199,-190,-179,-168,
+-156,-145,-134,-125,-119,-116,-116,-120,-126,-134,-143,-152,-159,-164,-164,-159,-148,-132,-110,-83,-52,
+-19,14,47,79,106,130,149,162,171,175,176,174,171,168,165,164,164,165,169,173,178,
+182,186,189,190,189,187,183,177,171,165,159,155,152,151,152,155,161,167,175,184,193,
+202,211,219,226,232,238,242,246,249,252,253,254,254,252,250,245,239,231,222,212,200,
+188,176,164,28,10,-5,-19,-31,-38,-42,-42,-38,-31,-20,-6,9,27,46,65,84,102,
+120,137,152,167,181,193,206,218,229,241,253,265,278,290,303,316,330,343,357,370,383,
+395,407,418,428,437,445,452,458,463,467,471,474,478,482,486,491,498,506,515,526,538,
+552,567,582,599,617,635,653,672,691,710,729,749,769,789,808,828,847,866,884,900,916,
+929,942,952,961,969,976,982,989,995,1003,1011,1021,1032,1045,1059,1074,1089,1105,1120,1134,1146,
+1157,1166,1172,1177,1180,1182,1183,1183,1183,1183,1184,1186,1187,1190,1192,1194,1195,1195,1194,1191,1187,
+1181,1173,1164,1153,1143,1132,1121,1112,1103,1095,1088,1082,1077,1073,1069,1065,1061,1057,1052,1047,1041,
+1035,1030,1025,1020,1017,1014,1013,1012,1013,1014,1016,1018,1020,1023,1025,1027,1030,1032,1035,1038,1042,
+1047,1052,1058,1064,1069,1074,1078,1080,1080,1078,1073,1065,1054,1042,1027,1012,997,983,970,960,952,
+948,947,949,953,960,968,976,984,991,995,997,997,994,989,982,975,967,960,954,950,949,
+951,957,965,975,988,1001,1016,1030,1043,1054,1064,1070,1074,1075,1072,1067,1060,1051,1039,1027,1013,
+999,985,972,958,946,935,925,918,912,908,907,908,911,915,921,928,935,941,945,948,948,
+945,938,928,915,899,880,859,837,816,794,775,757,741,728,717,707,699,692,684,675,665,
+652,636,617,595,571,545,518,491,465,441,420,403,390,381,378,378,382,389,398,407,416,
+424,430,434,434,432,426,418,409,399,388,379,371,366,363,363,366,371,378,386,394,400,
+405,407,406,401,392,379,363,344,323,301,279,258,238,219,203,188,176,164,152,141,128,
+114,98,80,59,36,11,-13,-40,-65,-89,-111,-130,-145,-157,-166,-171,-173,-173,-172,-171,-169,
+-169,-170,-174,-179,-187,-196,-208,-221,-236,-252,-268,-285,-303,-321,-341,-361,-384,-407,-433,-460,-489,
+-521,-553,-587,-621,-656,-690,-724,-757,-789,-820,-850,-880,-910,-941,-972,-1006,-1041,-1079,-1120,-1163,-1209,
+-1257,-1307,-1358,-1409,-1460,-1511,-1560,-1606,-1651,-1692,-1731,-1766,-1799,-1828,-1856,-1881,-1904,-1925,-1945,-1963,-1980,
+-1994,-2007,-2018,-2027,-2033,-2037,-2039,-2039,-2037,-2034,-2031,-2027,-2025,-2024,-2027,-2032,-2042,-2057,-2076,-2101,-2131,
+-2165,-2202,-2244,-2287,-2332,-2377,-2422,-2466,-2509,-2549,-2588,-2625,-2660,-2694,-2728,-2761,-2795,-2830,-2866,-2903,-2941,
+-2981,-3021,-3062,-3103,-3143,-3182,-3220,-3256,-3290,-3322,-3353,-3383,-3412,-3440,-3469,-3498,-3527,-3557,-3587,-3618,-3648,
+-3677,-3705,-3731,-3756,-3779,-3799,-3818,-3836,-3852,-3869,-3886,-3905,-3926,-3948,-3973,-4001,-4029,-4060,-4090,-4119,-4147,
+-4172,-4193,-4211,-4224,-4232,-4237,-4239,-4239,-4237,-4235,-4235,-4237,-4241,-4249,-4261,-4276,-4295,-4316,-4338,-4361,-4385,
+-4407,-4428,-4448,-4466,-4483,-4499,-4515,-4531,-4549,-4568,-4590,-4615,-4643,-4673,-4705,-4738,-4773,-4807,-4840,-4870,-4898,
+-4923,-4945,-4963,-4978,-4991,-5002,-5012,-5021,-5031,-5042,-5056,-5071,-5088,-5108,-5131,-5155,-5180,-5207,-5233,-5260,-5285,
+-5310,-5333,-5354,-5373,-5391,-5408,-5423,-5438,-5452,-5467,-5482,-5498,-5515,-5533,-5552,-5572,-5594,-5615,-5637,-5659,-5679,
+-5698,-5715,-5730,-5741,-5750,-5755,-5758,-5758,-5755,-5751,-5746,-5740,-5735,-5729,-5725,-5721,-5718,-5715,-5713,-5711,-5708,
+-5703,-5698,-5690,-5680,-5668,-5654,-5638,-5620,-5602,-5583,-5564,-5545,-5526,-5509,-5492,-5476,-5459,-5442,-5425,-5406,-5386,
+-5364,-5341,-5317,-5292,-5268,-5245,-5225,-5208,-5195,-5187,-5185,-5189,-5199,-5214,-5234,-5257,-5283,-5310,-5337,-5363,-5387,
+-5408,-5426,-5440,-5450,-5458,-5462,-5465,-5465,-5464,-5462,-5460,-5457,-5454,-5450,-5446,-5442,-5437,-5433,-5429,-5425,-5423,
+-5423,-5426,-5431,-5440,-5453,-5469,-5488,-5511,-5534,-5559,-5583,-5604,-5623,-5638,-5647,-5650,-5648,-5641,-5628,-5612,-5592,
+-5572,-5551,-5531,-5514,-5501,-5491,-5486,-5485,-5488,-5494,-5504,-5516,-5529,-5543,-5557,-5571,-5585,-5598,-5610,-5622,-5634,
+-5646,-5658,-5671,-5684,-5698,-5712,-5726,-5739,-5752,-5764,-5774,-5784,-5791,-5797,-5802,-5806,-5808,-5811,-5813,-5815,-5817,
+-5819,-5821,-5823,-5824,-5825,-5826,-5825,-5823,-5820,-5816,-5811,-5805,-5798,-5791,-5784,-5778,-5772,-5767,-5763,-5761,-5759,
+-5759,-5761,-5763,-5765,-5769,-5772,-5776,-5779,-5782,-5785,-5787,-5788,-5789,-5789,-5790,-5789,-5789,-5789,-5788,-5788,-5788,
+-5788,-5789,-5790,-5791,-5793,-5794,-5796,-5797,-5798,-5799,-5798,-5797,-5795,-5792,-5787,-5782,-5775,-5768,-5759,-5750,-5741,
+-5731,-5722,-5712,-5703,-5694,-5685,-5676,-5667,-5658,-5649,-5640,-5630,-5620,-5609,-5598,-5587,-5575,-5564,-5552,-5542,-5531,
+-5522,-5514,-5507,-5501,-5497,-5494,-5491,-5490,-5489,-5488,-5487,-5487,-5486,-5484,-5481,-5478,-5473,-5468,-5461,-5452,-5443,
+-5432,-5420,-5408,-5394,-5380,-5366,-5351,-5337,-5322,-5308,-5295,-5282,-5270,-5259,-5248,-5238,-5228,-5218,-5208,-5197,-5185,
+-5172,-5158,-5141,-5124,-5104,-5083,-5061,-5037,-5013,-4988,-4963,-4939,-4915,-4893,-4872,-4853,-4836,-4819,-4805,-4791,-4778,
+-4764,-4751,-4737,-4721,-4704,-4685,-4664,-4642,-4617,-4592,-4565,-4538,-4512,-4486,-4462,-4441,-4421,-4405,-4391,-4380,-4372,
+-4367,-4363,-4360,-4358,-4355,-4352,-4347,-4341,-4332,-4320,-4306,-4290,-4271,-4250,-4228,-4204,-4179,-4154,-4128,-4102,-4075,
+-4049,-4022,-3995,-3968,-3941,-3914,-3886,-3859,-3833,-3809,-3786,-3766,-3749,-3735,-3726,-3720,-3719,-3722,-3729,-3738,-3751,
+-3764,-3778,-3792,-3804,-3814,-3821,-3826,-3826,-3823,-3817,-3808,-3796,-3783,-3769,-3754,-3740,-3727,-3714,-3703,-3693,-3685,
+-3677,-3671,-3665,-3659,-3653,-3647,-3641,-3634,-3627,-3621,-3614,-3608,-3603,-3599,-3596,-3593,-3591,-3589,-3588,-3586,-3583,
+-3579,-3573,-3566,-3557,-3547,-3535,-3523,-3510,-3498,-3486,-3477,-3469,-3463,-3459,-3458,-3459,-3462,-3465,-3470,-3474,-3477,
+-3479,-3479,-3476,-3472,-3465,-3456,-3445,-3433,-3419,-3405,-3390,-3375,-3360,-3346,-3331,-3316,-3301,-3286,-3270,-3253,-3236,
+-3218,-3200,-3182,-3164,-3147,-3132,-3118,-3105,-3094,-3085,-3077,-3070,-3064,-3057,-3049,-3039,-3027,-3012,-2994,-2973,-2949,
+-2922,-2893,-2862,-2831,-2798,-2766,-2735,-2704,-2675,-2646,-2619,-2592,-2565,-2538,-2511,-2482,-2453,-2423,-2392,-2361,-2329,
+-2299,-2269,-2241,-2216,-2192,-2171,-2151,-2134,-2117,-2100,-2083,-2064,-2042,-2018,-1990,-1958,-1924,-1887,-1848,-1809,-1771,
+-1736,-1706,-1681,-1664,-1655,-1656,-1666,-1685,-1713,-1748,-1790,-1836,-1883,-1931,-1977,-2020,-2056,-2085,-2105,-2115,-2116,
+-2107,-2088,-2061,-2026,-1985,-1939,-1891,-1843,-1795,-1751,-1712,-1680,-1655,-1639,-1633,-1636,-1649,-1671,-1700,-1736,-1777,
+-1821,-1867,-1911,-1953,-1990,-2021,-2045,-2060,-2067,-2064,-2054,-2035,-2011,-1982,-1949,-1915,-1881,-1850,-1821,-1797,-1777,
+-1763,-1753,-1748,-1747,-1749,-1752,-1755,-1757,-1757,-1754,-1748,-1739,-1726,-1711,-1693,-1675,-1657,-1640,-1625,-1613,-1605,
+-1600,-1600,-1603,-1609,-1617,-1626,-1636,-1644,-1651,-1655,-1655,-1652,-1646,-1636,-1624,-1610,-1594,-1579,-1563,-1549,-1537,
+-1526,-1518,-1512,-1507,-1503,-1500,-1496,-1493,-1488,-1483,-1476,-1467,-1458,-1449,-1439,-1430,-1422,-1415,-1410,-1406,-1405,
+-1405,-1406,-1408,-1411,-1413,-1415,-1416,-1416,-1415,-1413,-1410,-1407,-1404,-1402,-1400,-1400,-1401,-1404,-1409,-1415,-1422,
+-1430,-1438,-1444,-1450,-1454,-1456,-1455,-1453,-1447,-1440,-1431,-1421,-1410,-1399,-1388,-1378,-1368,-1360,-1352,-1345,-1338,
+-1332,-1327,-1321,-1316,-1311,-1306,-1302,-1298,-1295,-1293,-1292,-1292,-1294,-1296,-1299,-1302,-1306,-1310,-1312,-1314,-1315,
+-1315,-1313,-1311,-1307,-1304,-1300,-1296,-1294,-1292,-1290,-1290,-1290,-1291,-1291,-1291,-1289,-1286,-1280,-1272,-1262,-1249,
+-1234,-1217,-1198,-1179,-1158,-1138,-1118,-1097,-1077,-1056,-1035,-1012,-988,-961,-932,-899,-864,-827,-787,-747,-706,
+-666,-628,-593,-562,-536,-515,-499,-488,-482,-480,-481,-484,-488,-492,-495,-497,-496,-494,-489,-482,-473,
+-462,-450,-437,-423,-408,-394,-378,-363,-347,-331,-315,-299,-283,-268,-254,-242,-231,-222,-216,-212,-210,
+-210,-211,-213,-214,-214,-212,-208,-200,-189,-175,-158,-138,-116,-93,-70,-48,-28,-10,5,17,26,
+32,35,37,38,38,38,38,38,39,40,42,43,44,44,42,38,33,27,19,10,2,
+-6,-14,-20,-24,-26,-26,-24,-19,-12,-4,4,13,23,33,42,51,60,68,76,84,92,
+99,107,114,120,125,128,130,129,125,118,108,96,81,64,46,28,-63,-84,-103,-120,-133,
+-142,-147,-147,-142,-134,-121,-106,-88,-69,-49,-29,-10,7,24,39,53,65,77,88,99,111,
+123,135,149,164,180,196,213,230,247,263,279,293,307,319,329,338,346,353,359,364,368,
+372,376,381,385,390,395,401,408,415,423,431,441,450,461,472,485,498,512,527,544,562,
+581,602,623,646,669,693,717,741,764,786,807,825,842,857,869,879,888,895,901,907,912,
+918,926,934,944,956,969,984,999,1015,1031,1046,1061,1074,1085,1094,1101,1106,1109,1111,1112,1112,
+1113,1113,1114,1116,1118,1121,1125,1128,1131,1134,1135,1135,1133,1130,1124,1118,1109,1100,1089,1078,1067,
+1056,1045,1035,1025,1016,1007,999,992,984,977,971,964,958,952,948,944,941,939,938,938,940,
+942,946,950,954,959,964,969,974,979,984,990,995,1001,1006,1012,1018,1024,1029,1033,1035,1037,
+1036,1032,1026,1018,1008,996,982,967,953,939,926,916,908,902,900,900,903,908,914,921,928,
+933,938,940,941,939,935,929,922,915,908,903,899,897,898,901,908,918,929,943,958,973,
+988,1002,1014,1023,1030,1034,1035,1032,1026,1018,1008,995,981,967,952,938,925,912,902,894,888,
+885,883,884,888,892,898,905,911,918,922,925,926,924,919,911,900,886,870,853,834,815,
+797,779,763,749,736,725,716,708,700,691,682,671,658,643,624,603,579,553,526,498,471,
+445,421,401,385,373,365,362,362,366,373,381,390,399,406,411,414,414,411,406,399,390,
+381,372,364,358,355,354,356,361,368,376,386,395,402,408,410,408,403,393,378,360,339,
+315,289,263,237,213,189,168,149,132,116,101,87,72,56,39,19,-2,-26,-52,-80,-109,
+-137,-165,-192,-215,-236,-252,-265,-273,-278,-278,-276,-271,-265,-258,-252,-246,-241,-239,-238,-240,-245,
+-252,-262,-275,-289,-306,-325,-346,-369,-394,-421,-449,-479,-511,-543,-577,-611,-645,-680,-714,-748,-781,
+-813,-845,-877,-908,-940,-972,-1006,-1040,-1077,-1115,-1156,-1198,-1242,-1287,-1334,-1381,-1428,-1474,-1520,-1564,-1606,
+-1647,-1685,-1722,-1756,-1789,-1821,-1852,-1882,-1912,-1940,-1968,-1995,-2021,-2044,-2065,-2084,-2098,-2109,-2116,-2118,-2117,
+-2112,-2104,-2094,-2084,-2073,-2065,-2059,-2057,-2060,-2069,-2084,-2105,-2132,-2165,-2202,-2244,-2288,-2333,-2380,-2425,-2470,
+-2512,-2553,-2591,-2627,-2662,-2695,-2728,-2761,-2795,-2829,-2865,-2903,-2942,-2982,-3023,-3064,-3105,-3144,-3183,-3220,-3254,
+-3287,-3318,-3348,-3377,-3405,-3433,-3461,-3491,-3521,-3552,-3584,-3616,-3648,-3680,-3710,-3739,-3765,-3789,-3811,-3830,-3848,
+-3865,-3881,-3897,-3915,-3934,-3956,-3980,-4006,-4035,-4065,-4097,-4128,-4157,-4185,-4209,-4229,-4245,-4256,-4263,-4265,-4265,
+-4262,-4258,-4254,-4251,-4250,-4253,-4258,-4268,-4281,-4297,-4316,-4336,-4358,-4380,-4402,-4422,-4442,-4460,-4476,-4492,-4508,
+-4524,-4541,-4560,-4581,-4604,-4629,-4657,-4687,-4718,-4750,-4783,-4815,-4845,-4873,-4899,-4923,-4943,-4961,-4977,-4990,-5003,
+-5015,-5028,-5041,-5055,-5071,-5089,-5109,-5130,-5153,-5177,-5201,-5225,-5249,-5272,-5294,-5315,-5334,-5351,-5368,-5383,-5399,
+-5414,-5430,-5446,-5464,-5484,-5504,-5527,-5550,-5575,-5599,-5623,-5647,-5668,-5687,-5704,-5717,-5727,-5734,-5737,-5737,-5734,
+-5730,-5724,-5718,-5712,-5706,-5701,-5698,-5696,-5695,-5695,-5695,-5695,-5695,-5693,-5690,-5685,-5677,-5667,-5654,-5639,-5622,
+-5604,-5584,-5563,-5542,-5521,-5500,-5479,-5458,-5437,-5415,-5393,-5370,-5346,-5322,-5298,-5273,-5250,-5228,-5208,-5192,-5179,
+-5171,-5168,-5171,-5178,-5191,-5208,-5229,-5253,-5278,-5304,-5328,-5352,-5372,-5390,-5404,-5415,-5421,-5425,-5426,-5424,-5420,
+-5415,-5410,-5404,-5398,-5392,-5386,-5381,-5377,-5373,-5371,-5369,-5369,-5370,-5373,-5378,-5386,-5397,-5410,-5426,-5444,-5464,
+-5485,-5506,-5526,-5544,-5560,-5573,-5581,-5586,-5585,-5581,-5572,-5561,-5546,-5531,-5514,-5498,-5484,-5471,-5461,-5454,-5450,
+-5449,-5451,-5455,-5462,-5471,-5481,-5493,-5505,-5518,-5531,-5545,-5559,-5574,-5589,-5605,-5620,-5636,-5651,-5666,-5681,-5695,
+-5707,-5718,-5728,-5736,-5744,-5750,-5755,-5760,-5764,-5768,-5772,-5777,-5782,-5787,-5792,-5796,-5801,-5804,-5806,-5807,-5806,
+-5804,-5799,-5793,-5786,-5777,-5768,-5759,-5750,-5742,-5734,-5729,-5725,-5723,-5723,-5724,-5727,-5731,-5737,-5742,-5748,-5753,
+-5758,-5762,-5765,-5766,-5766,-5764,-5761,-5757,-5751,-5745,-5738,-5731,-5724,-5718,-5712,-5707,-5703,-5700,-5699,-5699,-5700,
+-5702,-5704,-5708,-5711,-5714,-5717,-5719,-5720,-5720,-5718,-5716,-5711,-5706,-5699,-5691,-5682,-5673,-5663,-5652,-5641,-5630,
+-5618,-5606,-5593,-5581,-5567,-5554,-5540,-5526,-5511,-5497,-5483,-5469,-5456,-5444,-5433,-5424,-5417,-5412,-5408,-5406,-5406,
+-5407,-5409,-5412,-5416,-5419,-5421,-5423,-5423,-5421,-5417,-5412,-5404,-5394,-5383,-5370,-5356,-5341,-5326,-5311,-5296,-5283,
+-5270,-5259,-5249,-5240,-5233,-5226,-5221,-5215,-5209,-5203,-5196,-5188,-5178,-5167,-5154,-5140,-5124,-5107,-5089,-5071,-5054,
+-5037,-5021,-5006,-4993,-4982,-4973,-4966,-4960,-4955,-4950,-4945,-4939,-4932,-4922,-4910,-4894,-4875,-4852,-4825,-4796,-4763,
+-4729,-4693,-4657,-4621,-4587,-4556,-4527,-4502,-4482,-4465,-4453,-4445,-4440,-4438,-4438,-4438,-4439,-4440,-4438,-4435,-4429,
+-4420,-4408,-4392,-4374,-4352,-4328,-4302,-4275,-4246,-4216,-4185,-4154,-4123,-4092,-4060,-4029,-3998,-3968,-3939,-3911,-3884,
+-3860,-3839,-3820,-3805,-3794,-3788,-3785,-3787,-3792,-3801,-3812,-3826,-3840,-3854,-3867,-3878,-3886,-3892,-3894,-3892,-3887,
+-3878,-3867,-3853,-3837,-3821,-3803,-3786,-3769,-3753,-3738,-3724,-3711,-3699,-3687,-3676,-3665,-3654,-3643,-3633,-3622,-3613,
+-3604,-3597,-3590,-3586,-3582,-3581,-3580,-3580,-3581,-3582,-3582,-3581,-3579,-3575,-3569,-3560,-3550,-3538,-3525,-3511,-3497,
+-3484,-3472,-3462,-3455,-3450,-3448,-3448,-3451,-3455,-3461,-3467,-3473,-3478,-3483,-3486,-3487,-3486,-3484,-3480,-3474,-3467,
+-3459,-3450,-3440,-3429,-3417,-3405,-3391,-3376,-3359,-3342,-3322,-3302,-3281,-3259,-3237,-3217,-3197,-3179,-3164,-3152,-3142,
+-3135,-3130,-3127,-3126,-3124,-3122,-3119,-3113,-3104,-3091,-3075,-3055,-3031,-3004,-2975,-2943,-2910,-2877,-2844,-2811,-2778,
+-2747,-2715,-2684,-2653,-2621,-2588,-2554,-2518,-2480,-2442,-2402,-2363,-2324,-2287,-2252,-2219,-2190,-2165,-2143,-2123,-2106,
+-2090,-2074,-2057,-2038,-2015,-1988,-1956,-1920,-1880,-1836,-1791,-1746,-1703,-1664,-1632,-1607,-1593,-1589,-1597,-1616,-1647,
+-1688,-1737,-1793,-1852,-1914,-1973,-2030,-2080,-2123,-2156,-2179,-2191,-2193,-2183,-2164,-2137,-2103,-2063,-2020,-1975,-1930,
+-1887,-1847,-1811,-1781,-1757,-1741,-1731,-1729,-1734,-1746,-1764,-1788,-1815,-1845,-1877,-1908,-1938,-1966,-1989,-2007,-2019,
+-2024,-2022,-2014,-1999,-1978,-1953,-1925,-1895,-1864,-1835,-1808,-1784,-1765,-1750,-1741,-1736,-1735,-1737,-1742,-1748,-1754,
+-1759,-1761,-1761,-1758,-1751,-1741,-1729,-1714,-1698,-1682,-1667,-1653,-1641,-1632,-1626,-1623,-1623,-1625,-1629,-1634,-1639,
+-1644,-1648,-1651,-1652,-1650,-1647,-1642,-1635,-1627,-1619,-1610,-1601,-1592,-1584,-1577,-1570,-1564,-1558,-1551,-1545,-1538,
+-1530,-1522,-1514,-1505,-1497,-1489,-1481,-1474,-1469,-1464,-1461,-1459,-1458,-1458,-1457,-1457,-1457,-1455,-1453,-1450,-1445,
+-1441,-1435,-1430,-1425,-1421,-1418,-1417,-1418,-1421,-1425,-1431,-1438,-1446,-1454,-1461,-1466,-1470,-1472,-1471,-1468,-1463,
+-1456,-1448,-1438,-1428,-1419,-1409,-1401,-1393,-1387,-1382,-1378,-1375,-1373,-1371,-1370,-1368,-1367,-1366,-1364,-1363,-1363,
+-1363,-1363,-1365,-1367,-1371,-1375,-1379,-1383,-1387,-1390,-1392,-1393,-1392,-1389,-1385,-1380,-1373,-1367,-1360,-1353,-1348,
+-1343,-1340,-1338,-1336,-1335,-1333,-1331,-1327,-1321,-1312,-1301,-1285,-1267,-1245,-1221,-1195,-1167,-1138,-1109,-1080,-1052,
+-1025,-998,-973,-949,-924,-900,-875,-849,-822,-794,-766,-737,-708,-680,-654,-630,-610,-594,-582,-575,-573,
+-575,-581,-590,-602,-615,-628,-640,-650,-658,-662,-663,-660,-653,-643,-629,-612,-593,-572,-550,-527,-504,
+-480,-457,-435,-415,-395,-377,-361,-347,-335,-324,-315,-308,-302,-297,-293,-289,-284,-278,-272,-264,-255,
+-245,-233,-220,-207,-193,-179,-166,-154,-142,-133,-124,-117,-111,-106,-102,-99,-95,-92,-88,-85,-81,
+-78,-75,-73,-72,-73,-75,-79,-85,-92,-100,-109,-118,-127,-135,-141,-145,-148,-148,-147,-143,-138,
+-131,-124,-115,-107,-98,-90,-81,-73,-64,-55,-45,-35,-24,-13,-1,9,20,29,37,41,43,
+41,36,26,13,-2,-21,-42,-63,-125,-144,-161,-176,-187,-194,-196,-194,-186,-175,-160,-142,-122,
+-102,-81,-62,-43,-26,-11,1,12,22,32,41,51,61,72,85,100,116,133,151,170,188,
+207,224,240,255,267,278,287,295,301,306,310,314,318,322,327,333,339,346,354,363,372,
+382,392,402,412,422,432,443,454,466,478,492,506,522,540,558,578,599,620,642,664,685,
+706,725,742,758,772,783,793,801,808,814,820,826,833,840,849,859,871,884,898,913,929,
+944,959,973,985,996,1005,1011,1016,1019,1021,1022,1022,1022,1022,1023,1024,1027,1030,1034,1039,1043,
+1047,1051,1053,1054,1054,1051,1047,1041,1033,1024,1013,1003,991,980,969,959,949,940,932,925,918,
+913,907,903,899,895,892,890,888,887,886,887,888,890,892,895,899,902,906,911,915,919,
+924,929,934,939,944,950,956,962,968,973,978,982,984,985,984,981,975,968,959,949,938,
+926,914,903,893,885,878,874,872,872,874,877,882,886,891,895,898,899,900,898,896,893,
+889,886,883,882,882,885,890,897,907,919,933,948,963,979,993,1007,1018,1026,1031,1033,1032,
+1027,1019,1009,997,982,967,952,936,922,909,897,888,881,877,875,876,878,882,887,892,897,
+901,904,905,903,900,893,884,872,858,843,826,809,792,775,759,745,731,720,710,701,692,
+684,676,667,656,644,630,613,594,574,551,528,504,481,459,439,422,407,396,389,385,384,
+386,390,395,400,406,410,413,413,412,409,404,397,389,381,374,367,362,360,359,361,365,
+371,378,385,392,397,401,401,398,391,381,366,349,328,305,281,256,231,208,186,166,148,
+132,118,105,92,79,66,51,34,15,-6,-30,-56,-83,-111,-138,-165,-190,-212,-231,-247,-258,
+-265,-268,-268,-265,-260,-253,-246,-239,-233,-229,-227,-228,-231,-239,-249,-262,-279,-299,-321,-346,-372,
+-401,-431,-463,-496,-530,-564,-599,-634,-669,-703,-737,-771,-805,-838,-870,-902,-934,-967,-999,-1033,-1067,
+-1101,-1137,-1174,-1212,-1251,-1290,-1330,-1369,-1409,-1448,-1487,-1525,-1562,-1599,-1635,-1671,-1706,-1742,-1779,-1816,-1853,
+-1891,-1929,-1966,-2002,-2037,-2070,-2099,-2125,-2145,-2161,-2172,-2177,-2178,-2173,-2166,-2155,-2144,-2132,-2122,-2115,-2112,
+-2114,-2122,-2136,-2156,-2181,-2213,-2248,-2287,-2329,-2371,-2414,-2456,-2497,-2535,-2571,-2605,-2638,-2668,-2699,-2728,-2759,
+-2791,-2824,-2859,-2896,-2934,-2974,-3014,-3054,-3094,-3133,-3170,-3205,-3238,-3269,-3297,-3325,-3350,-3376,-3401,-3427,-3453,
+-3482,-3511,-3542,-3574,-3606,-3638,-3670,-3701,-3731,-3758,-3783,-3807,-3828,-3848,-3866,-3885,-3904,-3923,-3944,-3966,-3990,
+-4016,-4043,-4070,-4098,-4124,-4149,-4171,-4190,-4206,-4217,-4225,-4229,-4230,-4230,-4228,-4226,-4225,-4226,-4229,-4235,-4244,
+-4256,-4272,-4289,-4309,-4330,-4352,-4373,-4394,-4413,-4432,-4449,-4465,-4481,-4497,-4513,-4531,-4550,-4572,-4595,-4621,-4650,
+-4680,-4712,-4744,-4776,-4808,-4839,-4867,-4893,-4916,-4937,-4955,-4971,-4985,-4998,-5010,-5022,-5035,-5048,-5063,-5080,-5098,
+-5118,-5140,-5162,-5185,-5208,-5231,-5253,-5275,-5296,-5316,-5335,-5353,-5371,-5389,-5407,-5426,-5445,-5465,-5486,-5508,-5531,
+-5553,-5576,-5597,-5618,-5637,-5653,-5667,-5679,-5687,-5693,-5696,-5697,-5697,-5694,-5691,-5687,-5684,-5681,-5678,-5676,-5674,
+-5673,-5672,-5671,-5670,-5667,-5664,-5659,-5652,-5643,-5633,-5621,-5608,-5594,-5578,-5562,-5545,-5528,-5510,-5492,-5472,-5452,
+-5431,-5408,-5385,-5360,-5334,-5308,-5282,-5256,-5232,-5211,-5193,-5179,-5170,-5167,-5169,-5178,-5192,-5211,-5234,-5260,-5288,
+-5317,-5345,-5371,-5394,-5413,-5427,-5437,-5442,-5442,-5438,-5431,-5421,-5410,-5398,-5385,-5374,-5363,-5354,-5347,-5342,-5339,
+-5338,-5339,-5342,-5346,-5351,-5358,-5366,-5375,-5385,-5396,-5408,-5420,-5433,-5446,-5459,-5470,-5481,-5490,-5498,-5503,-5505,
+-5505,-5503,-5498,-5491,-5482,-5472,-5462,-5451,-5441,-5432,-5424,-5417,-5413,-5410,-5410,-5411,-5415,-5420,-5428,-5436,-5447,
+-5458,-5471,-5485,-5499,-5515,-5531,-5547,-5563,-5579,-5595,-5610,-5624,-5637,-5650,-5661,-5670,-5679,-5687,-5694,-5701,-5707,
+-5713,-5720,-5726,-5732,-5739,-5746,-5752,-5757,-5762,-5766,-5768,-5768,-5767,-5763,-5758,-5751,-5743,-5734,-5724,-5714,-5705,
+-5696,-5689,-5684,-5681,-5679,-5680,-5682,-5687,-5692,-5699,-5706,-5714,-5720,-5727,-5731,-5735,-5736,-5736,-5734,-5730,-5724,
+-5716,-5708,-5698,-5688,-5677,-5667,-5658,-5650,-5643,-5638,-5634,-5633,-5633,-5634,-5637,-5641,-5645,-5650,-5654,-5658,-5660,
+-5661,-5660,-5658,-5653,-5647,-5639,-5629,-5618,-5605,-5592,-5578,-5564,-5550,-5536,-5522,-5509,-5495,-5482,-5469,-5456,-5443,
+-5430,-5417,-5405,-5393,-5382,-5372,-5364,-5356,-5351,-5347,-5346,-5347,-5349,-5353,-5359,-5365,-5372,-5379,-5385,-5390,-5393,
+-5394,-5392,-5388,-5380,-5371,-5358,-5344,-5329,-5312,-5295,-5279,-5263,-5249,-5236,-5225,-5216,-5208,-5202,-5198,-5194,-5191,
+-5187,-5182,-5177,-5169,-5161,-5150,-5138,-5124,-5110,-5095,-5080,-5066,-5053,-5043,-5035,-5029,-5027,-5027,-5030,-5035,-5041,
+-5048,-5055,-5060,-5062,-5062,-5057,-5048,-5033,-5013,-4989,-4959,-4925,-4887,-4847,-4806,-4764,-4724,-4685,-4650,-4618,-4591,
+-4568,-4550,-4537,-4527,-4521,-4518,-4516,-4515,-4514,-4513,-4509,-4504,-4496,-4485,-4471,-4454,-4435,-4413,-4388,-4362,-4334,
+-4305,-4274,-4243,-4211,-4179,-4147,-4114,-4082,-4050,-4019,-3989,-3961,-3935,-3911,-3890,-3873,-3860,-3851,-3846,-3844,-3847,
+-3852,-3861,-3871,-3882,-3893,-3904,-3914,-3921,-3926,-3927,-3926,-3921,-3913,-3903,-3890,-3876,-3860,-3843,-3826,-3808,-3791,
+-3774,-3757,-3741,-3724,-3708,-3693,-3677,-3661,-3646,-3631,-3616,-3603,-3591,-3581,-3572,-3566,-3561,-3559,-3558,-3558,-3560,
+-3562,-3563,-3564,-3564,-3561,-3557,-3550,-3540,-3529,-3517,-3503,-3489,-3475,-3462,-3450,-3441,-3433,-3429,-3426,-3426,-3428,
+-3432,-3437,-3443,-3448,-3454,-3458,-3462,-3465,-3466,-3465,-3464,-3461,-3457,-3452,-3445,-3437,-3428,-3418,-3405,-3391,-3375,
+-3358,-3338,-3317,-3296,-3273,-3251,-3229,-3209,-3190,-3174,-3161,-3150,-3142,-3137,-3133,-3130,-3128,-3126,-3122,-3116,-3108,
+-3096,-3080,-3062,-3040,-3015,-2988,-2959,-2930,-2900,-2870,-2841,-2813,-2785,-2757,-2729,-2701,-2670,-2638,-2603,-2566,-2526,
+-2483,-2439,-2394,-2349,-2305,-2262,-2223,-2188,-2157,-2131,-2109,-2090,-2074,-2058,-2043,-2025,-2004,-1979,-1948,-1911,-1868,
+-1821,-1770,-1717,-1664,-1615,-1571,-1536,-1511,-1498,-1499,-1515,-1545,-1588,-1643,-1709,-1781,-1857,-1935,-2010,-2080,-2142,
+-2194,-2235,-2263,-2278,-2281,-2273,-2254,-2227,-2194,-2156,-2115,-2074,-2034,-1997,-1963,-1935,-1911,-1894,-1882,-1875,-1874,
+-1878,-1886,-1897,-1912,-1929,-1947,-1965,-1984,-2001,-2017,-2030,-2040,-2046,-2048,-2046,-2039,-2028,-2013,-1995,-1973,-1951,
+-1927,-1904,-1881,-1861,-1844,-1830,-1819,-1812,-1809,-1808,-1810,-1813,-1817,-1821,-1824,-1825,-1824,-1820,-1813,-1804,-1792,
+-1778,-1763,-1747,-1731,-1716,-1703,-1691,-1680,-1673,-1667,-1664,-1663,-1663,-1664,-1665,-1667,-1668,-1670,-1670,-1669,-1668,
+-1665,-1661,-1657,-1651,-1645,-1638,-1631,-1623,-1615,-1607,-1598,-1590,-1581,-1573,-1565,-1558,-1552,-1546,-1542,-1538,-1536,
+-1535,-1534,-1534,-1534,-1534,-1534,-1533,-1530,-1526,-1522,-1515,-1508,-1501,-1493,-1485,-1478,-1473,-1469,-1467,-1467,-1469,
+-1474,-1479,-1485,-1492,-1499,-1504,-1508,-1510,-1509,-1506,-1500,-1491,-1481,-1469,-1456,-1442,-1430,-1418,-1407,-1399,-1393,
+-1389,-1387,-1387,-1388,-1391,-1395,-1399,-1403,-1408,-1412,-1416,-1420,-1424,-1427,-1431,-1435,-1439,-1443,-1446,-1450,-1452,
+-1454,-1454,-1453,-1450,-1446,-1440,-1433,-1425,-1417,-1408,-1399,-1391,-1384,-1378,-1373,-1369,-1365,-1361,-1356,-1349,-1340,
+-1329,-1313,-1294,-1270,-1243,-1213,-1179,-1144,-1108,-1071,-1036,-1002,-971,-943,-918,-897,-879,-864,-851,-840,-830,
+-819,-809,-798,-786,-774,-761,-748,-735,-723,-713,-705,-700,-698,-699,-703,-710,-719,-730,-741,-752,-763,
+-771,-777,-780,-779,-775,-766,-755,-739,-722,-701,-679,-657,-633,-610,-588,-567,-547,-528,-512,-497,-484,
+-473,-462,-453,-445,-437,-429,-421,-413,-405,-396,-386,-376,-366,-356,-345,-335,-325,-315,-307,-299,-291,
+-285,-279,-274,-269,-264,-259,-254,-249,-243,-237,-231,-225,-220,-215,-211,-208,-206,-206,-207,-210,-214,
+-218,-222,-227,-231,-235,-237,-238,-237,-235,-231,-226,-221,-215,-208,-202,-195,-189,-183,-177,-171,-165,
+-157,-149,-140,-129,-117,-104,-90,-76,-63,-50,-40,-32,-28,-28,-32,-40,-52,-67,-85,-105,-125,
+-201,-218,-233,-246,-254,-258,-257,-251,-241,-226,-209,-189,-167,-145,-123,-102,-83,-66,-51,-38,-27,
+-17,-8,0,7,17,27,39,52,67,83,100,117,134,151,167,182,195,206,216,224,231,
+236,241,246,250,256,262,269,277,286,297,308,320,332,345,357,369,381,393,404,415,426,
+437,448,460,472,485,499,514,529,545,561,577,593,607,621,633,644,654,662,669,675,680,
+686,691,697,704,713,723,734,747,762,777,793,809,825,839,852,864,873,880,885,887,887,
+886,884,881,878,875,873,872,873,874,877,881,886,891,896,900,904,906,907,906,903,899,
+894,887,879,871,862,854,847,840,834,829,825,822,820,819,819,819,820,821,822,824,825,
+827,829,830,832,834,835,837,839,840,842,843,845,847,849,852,855,859,864,869,874,881,
+887,894,901,908,914,919,922,924,924,923,920,915,909,902,894,887,879,872,866,861,858,
+856,855,856,858,861,864,867,870,873,876,877,879,880,881,882,884,887,891,897,905,914,
+925,938,952,967,982,998,1012,1025,1036,1045,1051,1054,1054,1051,1045,1035,1024,1011,996,981,965,
+949,935,921,909,899,890,883,878,874,870,868,865,863,859,854,848,841,831,820,807,793,
+777,761,744,728,712,697,683,670,659,649,640,633,627,620,614,608,600,591,581,570,557,
+543,527,511,494,478,462,448,435,424,416,409,405,404,404,405,408,411,413,416,418,418,
+418,416,414,410,406,402,398,395,393,392,392,393,396,399,402,405,407,408,406,402,396,
+387,374,359,342,323,303,282,261,241,222,205,189,175,162,151,141,131,120,109,96,81,
+64,44,23,0,-26,-52,-79,-106,-131,-154,-174,-191,-205,-216,-222,-226,-227,-225,-222,-219,-215,
+-212,-211,-211,-214,-221,-230,-242,-258,-277,-299,-323,-350,-379,-411,-443,-477,-512,-547,-583,-619,-656,
+-692,-728,-764,-800,-835,-869,-903,-937,-970,-1003,-1035,-1067,-1099,-1130,-1161,-1192,-1223,-1254,-1284,-1314,-1344,
+-1374,-1404,-1434,-1465,-1496,-1528,-1561,-1596,-1632,-1670,-1710,-1752,-1795,-1840,-1885,-1930,-1975,-2019,-2060,-2097,-2131,
+-2160,-2183,-2202,-2215,-2223,-2226,-2226,-2223,-2219,-2215,-2212,-2210,-2213,-2219,-2229,-2244,-2265,-2289,-2317,-2348,-2382,
+-2416,-2451,-2486,-2519,-2550,-2580,-2607,-2633,-2658,-2682,-2707,-2732,-2759,-2787,-2818,-2851,-2887,-2924,-2963,-3003,-3043,
+-3083,-3121,-3158,-3192,-3224,-3253,-3280,-3305,-3329,-3352,-3374,-3397,-3420,-3445,-3471,-3499,-3529,-3559,-3591,-3623,-3654,
+-3685,-3715,-3743,-3769,-3794,-3817,-3838,-3859,-3879,-3899,-3919,-3940,-3961,-3984,-4007,-4030,-4053,-4076,-4098,-4118,-4136,
+-4151,-4165,-4175,-4184,-4190,-4195,-4198,-4202,-4206,-4211,-4217,-4225,-4236,-4248,-4263,-4279,-4296,-4315,-4333,-4352,-4370,
+-4388,-4405,-4422,-4438,-4454,-4471,-4489,-4508,-4528,-4551,-4576,-4604,-4634,-4665,-4698,-4731,-4765,-4798,-4830,-4860,-4887,
+-4912,-4935,-4954,-4971,-4985,-4998,-5010,-5021,-5032,-5043,-5056,-5069,-5084,-5101,-5120,-5139,-5160,-5182,-5204,-5227,-5250,
+-5272,-5294,-5316,-5337,-5358,-5378,-5398,-5418,-5438,-5457,-5477,-5496,-5515,-5533,-5551,-5568,-5583,-5598,-5610,-5621,-5631,
+-5639,-5645,-5650,-5654,-5656,-5658,-5659,-5659,-5659,-5659,-5658,-5656,-5654,-5651,-5647,-5642,-5637,-5630,-5622,-5613,-5604,
+-5594,-5584,-5573,-5563,-5553,-5544,-5534,-5525,-5515,-5504,-5492,-5478,-5462,-5444,-5424,-5401,-5375,-5348,-5320,-5291,-5263,
+-5237,-5215,-5196,-5184,-5177,-5177,-5184,-5198,-5218,-5244,-5274,-5306,-5341,-5375,-5407,-5436,-5460,-5479,-5492,-5498,-5498,
+-5492,-5481,-5466,-5448,-5428,-5407,-5387,-5368,-5352,-5338,-5328,-5321,-5318,-5317,-5319,-5324,-5330,-5337,-5344,-5352,-5361,
+-5368,-5376,-5383,-5390,-5396,-5401,-5407,-5412,-5416,-5420,-5423,-5425,-5427,-5428,-5427,-5426,-5424,-5420,-5416,-5412,-5406,
+-5401,-5396,-5391,-5386,-5383,-5380,-5379,-5380,-5382,-5386,-5392,-5399,-5408,-5418,-5430,-5443,-5457,-5472,-5487,-5502,-5518,
+-5533,-5547,-5561,-5574,-5586,-5597,-5608,-5617,-5626,-5634,-5642,-5650,-5657,-5664,-5671,-5678,-5685,-5691,-5697,-5701,-5705,
+-5708,-5710,-5710,-5708,-5705,-5700,-5695,-5688,-5680,-5673,-5665,-5657,-5651,-5645,-5640,-5637,-5636,-5636,-5638,-5641,-5645,
+-5650,-5655,-5661,-5666,-5671,-5675,-5679,-5681,-5682,-5681,-5679,-5675,-5671,-5665,-5658,-5651,-5643,-5635,-5628,-5621,-5614,
+-5609,-5605,-5602,-5601,-5600,-5601,-5603,-5605,-5607,-5610,-5612,-5613,-5613,-5611,-5608,-5602,-5595,-5586,-5575,-5563,-5549,
+-5535,-5520,-5504,-5488,-5473,-5458,-5444,-5430,-5418,-5405,-5394,-5383,-5373,-5364,-5355,-5347,-5339,-5333,-5327,-5323,-5321,
+-5320,-5321,-5324,-5329,-5335,-5344,-5353,-5363,-5373,-5382,-5391,-5397,-5401,-5402,-5401,-5395,-5387,-5375,-5360,-5343,-5324,
+-5304,-5284,-5264,-5245,-5227,-5212,-5199,-5188,-5180,-5173,-5169,-5165,-5162,-5160,-5156,-5152,-5146,-5139,-5130,-5119,-5108,
+-5095,-5083,-5071,-5060,-5051,-5045,-5041,-5041,-5045,-5051,-5061,-5073,-5086,-5100,-5113,-5125,-5134,-5139,-5140,-5135,-5125,
+-5110,-5088,-5061,-5030,-4995,-4957,-4917,-4877,-4837,-4799,-4764,-4732,-4703,-4678,-4657,-4640,-4627,-4616,-4607,-4599,-4593,
+-4586,-4578,-4570,-4559,-4547,-4533,-4517,-4498,-4478,-4456,-4433,-4408,-4383,-4356,-4329,-4302,-4274,-4246,-4217,-4189,-4161,
+-4133,-4106,-4080,-4055,-4032,-4011,-3993,-3977,-3964,-3955,-3948,-3944,-3943,-3944,-3946,-3949,-3953,-3957,-3960,-3961,-3961,
+-3959,-3954,-3948,-3939,-3929,-3917,-3903,-3889,-3873,-3858,-3841,-3825,-3808,-3791,-3774,-3757,-3739,-3721,-3702,-3684,-3665,
+-3646,-3629,-3611,-3596,-3582,-3569,-3559,-3552,-3546,-3543,-3541,-3541,-3541,-3542,-3543,-3542,-3540,-3536,-3530,-3522,-3512,
+-3500,-3486,-3471,-3456,-3441,-3427,-3414,-3403,-3394,-3388,-3384,-3382,-3382,-3384,-3387,-3391,-3396,-3401,-3406,-3411,-3415,
+-3417,-3419,-3420,-3419,-3417,-3413,-3408,-3400,-3391,-3380,-3367,-3351,-3334,-3316,-3296,-3275,-3253,-3232,-3212,-3192,-3175,
+-3159,-3146,-3135,-3126,-3119,-3113,-3108,-3103,-3097,-3090,-3080,-3067,-3052,-3034,-3013,-2989,-2964,-2937,-2910,-2882,-2856,
+-2830,-2806,-2784,-2762,-2741,-2720,-2698,-2674,-2647,-2618,-2584,-2547,-2507,-2463,-2417,-2370,-2323,-2278,-2235,-2195,-2160,
+-2130,-2104,-2083,-2065,-2049,-2032,-2015,-1994,-1967,-1935,-1895,-1847,-1793,-1733,-1668,-1602,-1538,-1477,-1425,-1383,-1354,
+-1342,-1347,-1370,-1412,-1470,-1543,-1629,-1724,-1824,-1925,-2024,-2117,-2200,-2271,-2327,-2368,-2394,-2404,-2400,-2384,-2357,
+-2322,-2282,-2240,-2197,-2156,-2118,-2086,-2059,-2038,-2024,-2016,-2013,-2015,-2022,-2031,-2043,-2056,-2070,-2085,-2098,-2111,
+-2122,-2131,-2138,-2143,-2145,-2144,-2140,-2133,-2124,-2111,-2096,-2078,-2059,-2038,-2017,-1995,-1975,-1955,-1938,-1922,-1910,
+-1899,-1891,-1886,-1882,-1880,-1879,-1878,-1877,-1875,-1872,-1866,-1859,-1850,-1839,-1826,-1811,-1796,-1780,-1764,-1749,-1735,
+-1723,-1712,-1703,-1696,-1691,-1688,-1687,-1687,-1688,-1691,-1693,-1696,-1698,-1699,-1700,-1699,-1697,-1694,-1689,-1683,-1676,
+-1668,-1659,-1650,-1640,-1632,-1623,-1616,-1611,-1606,-1604,-1602,-1602,-1604,-1606,-1608,-1611,-1613,-1614,-1614,-1613,-1610,
+-1605,-1599,-1592,-1584,-1575,-1567,-1559,-1553,-1549,-1546,-1546,-1547,-1551,-1556,-1562,-1568,-1574,-1579,-1582,-1582,-1580,
+-1574,-1565,-1554,-1539,-1523,-1505,-1487,-1469,-1451,-1436,-1422,-1412,-1404,-1399,-1398,-1399,-1402,-1407,-1415,-1423,-1432,
+-1441,-1450,-1459,-1467,-1475,-1482,-1488,-1493,-1498,-1501,-1504,-1505,-1505,-1504,-1501,-1497,-1491,-1485,-1477,-1468,-1459,
+-1450,-1442,-1434,-1426,-1420,-1414,-1409,-1404,-1398,-1390,-1381,-1369,-1353,-1334,-1310,-1282,-1249,-1213,-1174,-1132,-1089,
+-1047,-1006,-969,-935,-906,-883,-865,-854,-848,-847,-851,-857,-866,-875,-884,-891,-897,-900,-900,-897,-892,
+-885,-876,-867,-858,-849,-842,-837,-833,-832,-832,-835,-838,-842,-845,-848,-850,-850,-847,-842,-835,-825,
+-813,-799,-784,-767,-751,-734,-717,-702,-687,-674,-662,-652,-642,-633,-625,-618,-611,-603,-595,-587,-579,
+-570,-560,-551,-541,-531,-521,-512,-503,-495,-487,-481,-474,-469,-463,-458,-453,-448,-443,-437,-431,-425,
+-419,-412,-406,-400,-395,-390,-387,-384,-383,-382,-381,-381,-382,-381,-381,-379,-376,-372,-367,-361,-353,
+-345,-336,-327,-318,-310,-302,-295,-290,-284,-280,-275,-271,-265,-259,-251,-241,-230,-217,-202,-187,-171,
+-156,-142,-130,-121,-116,-114,-117,-124,-135,-149,-165,-183,-201,-291,-308,-322,-333,-341,-344,-342,-335,
+-324,-309,-291,-270,-247,-224,-201,-179,-158,-140,-124,-110,-98,-88,-79,-70,-62,-54,-45,-34,-23,
+-11,2,16,31,45,60,74,87,99,109,119,127,134,141,148,154,161,169,177,187,198,
+209,222,235,249,263,277,290,303,316,328,339,350,360,370,380,390,401,411,422,434,445,
+456,467,478,488,497,505,512,518,522,526,530,533,537,541,547,553,562,572,584,598,614,
+630,648,665,682,698,712,725,735,742,746,748,747,744,739,733,726,719,713,707,703,701,
+699,700,701,704,708,711,715,719,722,724,725,724,723,720,717,714,710,706,702,699,697,
+696,696,697,699,703,707,711,716,722,727,733,738,743,747,751,755,758,760,762,763,764,
+765,765,765,765,766,767,768,770,773,777,782,787,794,802,810,819,828,837,846,854,860,
+866,870,872,873,872,870,866,862,858,852,848,843,840,837,835,835,835,836,838,841,844,
+848,852,857,861,866,871,877,883,891,899,908,919,930,943,957,971,986,1001,1015,1028,1041,
+1051,1059,1065,1068,1069,1067,1062,1055,1045,1034,1021,1007,992,977,962,947,932,918,904,891,879,
+866,854,842,830,817,803,789,774,758,742,725,708,690,673,656,639,624,610,597,585,575,
+567,559,554,549,544,541,537,533,529,524,518,511,504,495,486,476,465,455,445,436,427,
+419,413,408,404,402,401,401,402,404,406,409,412,414,417,420,422,424,426,429,431,433,
+435,437,439,441,443,444,443,442,439,434,427,418,407,394,379,363,345,327,309,291,273,
+257,241,227,215,204,193,184,175,165,155,143,130,115,98,78,56,33,8,-17,-44,-70,
+-94,-118,-139,-157,-173,-186,-195,-202,-206,-209,-210,-210,-210,-210,-212,-215,-220,-228,-238,-251,-267,
+-286,-308,-333,-360,-389,-421,-454,-488,-525,-562,-600,-638,-677,-716,-755,-794,-832,-870,-907,-943,-977,
+-1011,-1043,-1074,-1104,-1132,-1159,-1184,-1209,-1232,-1255,-1277,-1298,-1319,-1341,-1363,-1385,-1409,-1435,-1462,-1492,-1524,
+-1559,-1596,-1636,-1679,-1724,-1770,-1818,-1866,-1914,-1962,-2007,-2049,-2089,-2124,-2156,-2183,-2205,-2224,-2239,-2251,-2261,
+-2269,-2277,-2285,-2294,-2306,-2319,-2335,-2354,-2375,-2399,-2424,-2450,-2477,-2504,-2530,-2555,-2579,-2601,-2621,-2641,-2659,
+-2677,-2696,-2715,-2736,-2760,-2786,-2814,-2846,-2880,-2917,-2955,-2994,-3034,-3074,-3112,-3149,-3183,-3215,-3245,-3272,-3297,
+-3320,-3342,-3363,-3385,-3407,-3429,-3453,-3479,-3506,-3534,-3563,-3593,-3623,-3653,-3683,-3711,-3739,-3765,-3789,-3813,-3835,
+-3856,-3877,-3897,-3918,-3938,-3959,-3980,-4002,-4023,-4044,-4065,-4085,-4103,-4120,-4136,-4150,-4162,-4172,-4182,-4190,-4197,
+-4205,-4212,-4219,-4228,-4237,-4248,-4259,-4271,-4284,-4298,-4313,-4328,-4343,-4359,-4375,-4391,-4408,-4426,-4445,-4465,-4488,
+-4512,-4538,-4566,-4596,-4628,-4662,-4696,-4731,-4766,-4800,-4832,-4863,-4892,-4918,-4942,-4962,-4981,-4997,-5010,-5023,-5034,
+-5045,-5056,-5067,-5079,-5091,-5105,-5121,-5137,-5155,-5174,-5195,-5215,-5237,-5259,-5281,-5303,-5325,-5347,-5368,-5389,-5409,
+-5428,-5447,-5464,-5481,-5497,-5511,-5525,-5537,-5548,-5558,-5567,-5576,-5583,-5589,-5595,-5601,-5606,-5610,-5614,-5617,-5620,
+-5622,-5623,-5623,-5621,-5619,-5614,-5608,-5601,-5593,-5584,-5575,-5565,-5556,-5547,-5539,-5532,-5527,-5523,-5519,-5517,-5514,
+-5511,-5507,-5501,-5492,-5480,-5465,-5446,-5423,-5397,-5369,-5339,-5309,-5280,-5253,-5230,-5212,-5201,-5196,-5200,-5211,-5229,
+-5255,-5286,-5322,-5361,-5400,-5439,-5475,-5506,-5532,-5551,-5563,-5567,-5564,-5554,-5537,-5516,-5491,-5464,-5437,-5409,-5384,
+-5361,-5342,-5326,-5315,-5307,-5303,-5302,-5304,-5307,-5312,-5318,-5323,-5329,-5334,-5338,-5341,-5344,-5347,-5349,-5351,-5353,
+-5355,-5357,-5360,-5363,-5365,-5368,-5370,-5372,-5373,-5373,-5372,-5371,-5369,-5366,-5362,-5359,-5355,-5353,-5350,-5350,-5350,
+-5352,-5356,-5362,-5369,-5379,-5389,-5401,-5415,-5428,-5443,-5457,-5472,-5486,-5499,-5512,-5524,-5535,-5546,-5556,-5565,-5574,
+-5582,-5590,-5598,-5605,-5612,-5619,-5626,-5632,-5637,-5642,-5645,-5647,-5649,-5648,-5647,-5644,-5641,-5636,-5631,-5626,-5620,
+-5614,-5609,-5605,-5602,-5599,-5597,-5597,-5597,-5598,-5599,-5601,-5604,-5606,-5608,-5610,-5611,-5612,-5612,-5612,-5611,-5610,
+-5609,-5607,-5606,-5604,-5602,-5600,-5598,-5597,-5595,-5594,-5593,-5592,-5591,-5591,-5590,-5590,-5590,-5590,-5590,-5589,-5589,
+-5588,-5586,-5584,-5581,-5578,-5573,-5567,-5559,-5551,-5541,-5530,-5518,-5505,-5492,-5478,-5463,-5449,-5435,-5422,-5408,-5396,
+-5383,-5372,-5361,-5352,-5342,-5334,-5327,-5320,-5315,-5311,-5308,-5308,-5309,-5311,-5316,-5323,-5331,-5341,-5352,-5364,-5376,
+-5388,-5399,-5408,-5415,-5418,-5419,-5416,-5409,-5398,-5384,-5366,-5346,-5324,-5301,-5277,-5253,-5231,-5211,-5193,-5177,-5164,
+-5154,-5147,-5142,-5138,-5136,-5135,-5133,-5131,-5127,-5123,-5117,-5109,-5101,-5092,-5082,-5073,-5064,-5058,-5053,-5051,-5052,
+-5056,-5063,-5073,-5085,-5098,-5112,-5126,-5139,-5149,-5156,-5160,-5158,-5152,-5141,-5125,-5104,-5079,-5051,-5019,-4986,-4952,
+-4917,-4884,-4852,-4822,-4794,-4770,-4748,-4728,-4711,-4696,-4683,-4671,-4659,-4647,-4635,-4622,-4607,-4592,-4575,-4557,-4538,
+-4517,-4496,-4474,-4451,-4427,-4403,-4379,-4355,-4330,-4306,-4282,-4259,-4235,-4213,-4191,-4170,-4151,-4133,-4117,-4102,-4090,
+-4079,-4070,-4063,-4057,-4053,-4049,-4045,-4042,-4038,-4034,-4028,-4021,-4013,-4004,-3993,-3981,-3968,-3953,-3939,-3923,-3908,
+-3892,-3876,-3860,-3844,-3828,-3811,-3794,-3776,-3758,-3739,-3719,-3699,-3678,-3658,-3638,-3619,-3601,-3584,-3570,-3557,-3547,
+-3539,-3532,-3528,-3525,-3522,-3520,-3518,-3515,-3511,-3505,-3497,-3488,-3477,-3464,-3450,-3435,-3419,-3403,-3388,-3374,-3362,
+-3351,-3343,-3336,-3332,-3331,-3331,-3333,-3337,-3342,-3347,-3354,-3360,-3366,-3372,-3376,-3380,-3381,-3381,-3378,-3374,-3366,
+-3357,-3344,-3329,-3313,-3294,-3274,-3253,-3231,-3210,-3189,-3170,-3152,-3137,-3123,-3112,-3102,-3094,-3087,-3080,-3073,-3065,
+-3055,-3043,-3028,-3010,-2989,-2966,-2941,-2915,-2888,-2860,-2834,-2809,-2785,-2764,-2744,-2727,-2710,-2694,-2677,-2659,-2638,
+-2614,-2586,-2554,-2518,-2478,-2435,-2390,-2344,-2298,-2254,-2213,-2176,-2143,-2115,-2091,-2071,-2053,-2035,-2017,-1995,-1968,
+-1934,-1892,-1841,-1782,-1715,-1641,-1563,-1484,-1408,-1337,-1275,-1227,-1196,-1184,-1192,-1223,-1275,-1347,-1437,-1543,-1660,
+-1784,-1910,-2033,-2150,-2256,-2348,-2424,-2481,-2519,-2538,-2540,-2527,-2500,-2463,-2419,-2370,-2321,-2273,-2229,-2190,-2159,
+-2135,-2119,-2111,-2109,-2114,-2124,-2138,-2154,-2171,-2189,-2206,-2222,-2237,-2248,-2257,-2264,-2267,-2267,-2264,-2259,-2250,
+-2238,-2224,-2207,-2187,-2166,-2142,-2118,-2092,-2067,-2041,-2017,-1994,-1973,-1954,-1938,-1925,-1914,-1905,-1899,-1895,-1892,
+-1890,-1888,-1886,-1882,-1878,-1872,-1865,-1855,-1844,-1832,-1818,-1804,-1789,-1775,-1761,-1749,-1738,-1730,-1723,-1718,-1716,
+-1716,-1717,-1720,-1724,-1728,-1732,-1736,-1739,-1740,-1740,-1738,-1735,-1730,-1724,-1716,-1708,-1700,-1691,-1684,-1677,-1671,
+-1667,-1665,-1664,-1665,-1667,-1670,-1673,-1676,-1679,-1681,-1681,-1680,-1678,-1674,-1669,-1662,-1655,-1647,-1640,-1634,-1628,
+-1625,-1623,-1623,-1624,-1627,-1632,-1637,-1641,-1645,-1648,-1648,-1646,-1641,-1633,-1622,-1607,-1590,-1571,-1551,-1530,-1509,
+-1489,-1470,-1454,-1441,-1430,-1423,-1420,-1419,-1422,-1427,-1434,-1443,-1453,-1465,-1476,-1487,-1499,-1509,-1518,-1527,-1534,
+-1539,-1543,-1546,-1546,-1545,-1542,-1538,-1532,-1525,-1518,-1509,-1501,-1493,-1485,-1477,-1471,-1465,-1459,-1454,-1449,-1443,
+-1435,-1426,-1413,-1397,-1377,-1352,-1323,-1290,-1252,-1211,-1168,-1123,-1079,-1036,-996,-960,-930,-907,-891,-882,-880,
+-885,-897,-913,-933,-955,-977,-999,-1019,-1036,-1049,-1057,-1060,-1059,-1053,-1044,-1032,-1017,-1002,-986,-971,-957,
+-944,-934,-926,-920,-916,-913,-911,-909,-907,-905,-902,-897,-892,-885,-877,-868,-858,-848,-837,-827,-817,
+-808,-799,-791,-783,-777,-770,-764,-759,-753,-747,-741,-734,-727,-720,-713,-706,-699,-692,-685,-679,-673,
+-667,-662,-657,-652,-647,-642,-637,-631,-626,-619,-613,-606,-600,-593,-587,-581,-576,-572,-569,-566,-564,
+-563,-562,-560,-559,-557,-553,-548,-542,-534,-525,-514,-503,-490,-477,-464,-452,-440,-430,-420,-412,-405,
+-400,-394,-389,-383,-376,-368,-358,-346,-333,-318,-301,-284,-266,-250,-235,-222,-213,-207,-205,-208,-215,
+-226,-240,-256,-273,-291,-362,-377,-391,-401,-408,-411,-409,-403,-393,-379,-361,-341,-319,-297,-275,-253,
+-232,-214,-197,-183,-170,-159,-149,-140,-132,-124,-115,-106,-96,-85,-74,-61,-48,-35,-22,-9,2,
+14,25,36,45,54,63,71,80,89,99,109,120,131,143,156,169,183,196,209,222,234,
+246,257,267,277,287,296,305,315,324,334,344,353,363,373,382,391,399,407,413,418,423,
+426,429,432,435,438,442,448,455,463,474,487,501,516,533,550,567,584,600,614,626,636,
+643,647,649,648,645,640,634,627,619,612,605,599,594,590,588,587,587,588,590,592,594,
+596,598,599,599,599,599,598,596,595,594,593,593,593,594,596,599,603,607,613,618,625,
+631,638,644,650,656,662,667,672,676,680,682,685,687,688,690,691,692,694,695,697,700,
+704,708,714,720,728,736,745,755,765,775,785,794,803,811,817,822,826,827,828,827,826,
+823,820,816,813,809,806,804,802,802,802,803,805,808,812,817,823,830,837,845,853,863,
+874,885,897,910,923,938,952,967,981,996,1009,1021,1032,1042,1049,1055,1058,1059,1058,1054,1049,
+1041,1032,1022,1010,997,984,970,955,940,925,909,893,877,860,843,825,807,789,770,751,732,
+712,693,674,656,638,621,605,590,577,565,555,545,537,531,525,520,516,512,509,506,502,
+499,495,491,486,481,476,470,463,457,450,443,437,431,425,420,415,412,409,407,405,405,
+406,408,410,414,418,423,429,435,442,449,456,462,469,475,480,483,486,487,486,484,479,
+472,463,452,439,425,409,392,375,357,339,322,305,289,275,262,249,238,228,218,209,199,
+188,177,164,150,134,116,96,75,52,28,3,-21,-45,-69,-91,-112,-130,-146,-160,-172,-181,
+-189,-194,-199,-202,-205,-209,-213,-218,-224,-232,-243,-256,-271,-289,-310,-334,-360,-389,-420,-454,-490,
+-527,-567,-607,-648,-690,-733,-775,-816,-857,-897,-935,-971,-1006,-1038,-1068,-1097,-1123,-1147,-1169,-1190,-1209,
+-1227,-1245,-1262,-1279,-1296,-1314,-1333,-1354,-1375,-1399,-1425,-1453,-1484,-1517,-1552,-1589,-1628,-1670,-1712,-1755,-1799,
+-1843,-1886,-1928,-1968,-2007,-2043,-2076,-2107,-2136,-2161,-2185,-2207,-2228,-2248,-2267,-2286,-2306,-2326,-2348,-2370,-2393,
+-2417,-2441,-2466,-2490,-2514,-2537,-2558,-2579,-2598,-2616,-2633,-2649,-2665,-2681,-2698,-2717,-2738,-2760,-2785,-2813,-2844,
+-2876,-2911,-2947,-2985,-3022,-3060,-3096,-3131,-3165,-3196,-3225,-3252,-3278,-3302,-3325,-3347,-3368,-3390,-3413,-3437,-3461,
+-3487,-3514,-3541,-3570,-3598,-3627,-3656,-3684,-3711,-3738,-3763,-3788,-3811,-3834,-3856,-3878,-3900,-3921,-3943,-3964,-3986,
+-4007,-4028,-4048,-4068,-4086,-4104,-4120,-4135,-4148,-4159,-4169,-4178,-4186,-4193,-4200,-4206,-4213,-4220,-4228,-4236,-4245,
+-4256,-4267,-4279,-4293,-4307,-4323,-4339,-4357,-4376,-4397,-4419,-4442,-4467,-4494,-4522,-4551,-4582,-4614,-4647,-4681,-4715,
+-4748,-4781,-4813,-4843,-4872,-4899,-4923,-4946,-4967,-4985,-5002,-5017,-5031,-5044,-5057,-5069,-5081,-5093,-5105,-5119,-5133,
+-5148,-5164,-5181,-5199,-5218,-5237,-5257,-5278,-5298,-5319,-5340,-5360,-5380,-5398,-5416,-5433,-5448,-5461,-5473,-5484,-5493,
+-5501,-5507,-5513,-5518,-5522,-5525,-5529,-5532,-5535,-5539,-5542,-5545,-5547,-5549,-5550,-5551,-5550,-5548,-5545,-5541,-5535,
+-5529,-5523,-5516,-5509,-5504,-5499,-5495,-5493,-5491,-5491,-5492,-5492,-5493,-5492,-5489,-5484,-5476,-5465,-5450,-5431,-5410,
+-5385,-5358,-5331,-5304,-5278,-5256,-5238,-5227,-5222,-5224,-5234,-5252,-5277,-5308,-5345,-5385,-5426,-5468,-5508,-5544,-5576,
+-5600,-5617,-5627,-5628,-5621,-5607,-5586,-5561,-5531,-5500,-5467,-5435,-5405,-5377,-5353,-5333,-5316,-5303,-5294,-5289,-5286,
+-5285,-5285,-5287,-5289,-5291,-5293,-5294,-5296,-5297,-5299,-5300,-5302,-5304,-5307,-5310,-5314,-5318,-5322,-5326,-5330,-5333,
+-5334,-5335,-5335,-5333,-5331,-5327,-5323,-5319,-5315,-5312,-5309,-5309,-5309,-5312,-5317,-5325,-5334,-5345,-5357,-5371,-5385,
+-5400,-5415,-5430,-5444,-5457,-5470,-5481,-5491,-5501,-5510,-5518,-5526,-5533,-5540,-5548,-5555,-5562,-5569,-5575,-5581,-5586,
+-5590,-5594,-5595,-5596,-5595,-5592,-5589,-5585,-5580,-5575,-5570,-5565,-5560,-5557,-5555,-5554,-5554,-5555,-5557,-5560,-5563,
+-5567,-5569,-5572,-5574,-5574,-5574,-5572,-5570,-5567,-5563,-5559,-5555,-5551,-5548,-5545,-5544,-5544,-5545,-5547,-5551,-5555,
+-5559,-5564,-5569,-5574,-5577,-5580,-5582,-5583,-5582,-5580,-5577,-5573,-5567,-5561,-5554,-5546,-5539,-5530,-5522,-5514,-5505,
+-5496,-5488,-5479,-5471,-5462,-5453,-5444,-5434,-5425,-5415,-5405,-5394,-5384,-5373,-5363,-5352,-5342,-5332,-5323,-5315,-5307,
+-5301,-5297,-5294,-5293,-5294,-5297,-5303,-5310,-5319,-5330,-5341,-5354,-5366,-5378,-5388,-5396,-5403,-5406,-5405,-5401,-5394,
+-5382,-5367,-5349,-5328,-5306,-5282,-5257,-5233,-5210,-5189,-5170,-5153,-5140,-5129,-5121,-5115,-5112,-5110,-5109,-5108,-5108,
+-5107,-5106,-5103,-5100,-5095,-5090,-5084,-5078,-5073,-5068,-5065,-5064,-5064,-5067,-5071,-5078,-5086,-5095,-5104,-5114,-5122,
+-5129,-5133,-5134,-5132,-5127,-5117,-5103,-5086,-5066,-5042,-5016,-4989,-4960,-4931,-4903,-4875,-4849,-4825,-4802,-4781,-4763,
+-4746,-4730,-4716,-4702,-4689,-4677,-4663,-4650,-4635,-4619,-4602,-4585,-4565,-4545,-4524,-4502,-4479,-4455,-4431,-4407,-4383,
+-4359,-4335,-4312,-4290,-4269,-4249,-4230,-4213,-4197,-4183,-4171,-4161,-4152,-4144,-4138,-4132,-4128,-4123,-4118,-4113,-4107,
+-4100,-4092,-4082,-4071,-4059,-4046,-4031,-4015,-3999,-3983,-3966,-3949,-3932,-3916,-3900,-3883,-3867,-3851,-3834,-3817,-3799,
+-3781,-3761,-3741,-3720,-3699,-3678,-3656,-3636,-3616,-3597,-3580,-3564,-3550,-3539,-3529,-3521,-3514,-3508,-3503,-3499,-3494,
+-3489,-3482,-3475,-3467,-3457,-3446,-3434,-3421,-3407,-3393,-3380,-3367,-3354,-3343,-3334,-3326,-3321,-3317,-3316,-3317,-3319,
+-3323,-3329,-3335,-3342,-3350,-3356,-3363,-3367,-3370,-3371,-3370,-3365,-3358,-3347,-3334,-3318,-3299,-3279,-3257,-3234,-3211,
+-3188,-3166,-3146,-3128,-3112,-3098,-3085,-3075,-3066,-3057,-3048,-3039,-3028,-3015,-3001,-2984,-2964,-2942,-2918,-2893,-2867,
+-2841,-2816,-2792,-2769,-2749,-2730,-2714,-2698,-2683,-2669,-2653,-2635,-2614,-2589,-2561,-2529,-2492,-2453,-2410,-2366,-2321,
+-2277,-2236,-2197,-2162,-2132,-2105,-2083,-2063,-2046,-2027,-2007,-1983,-1953,-1916,-1871,-1816,-1753,-1683,-1606,-1526,-1445,
+-1366,-1295,-1234,-1187,-1157,-1148,-1160,-1194,-1251,-1329,-1427,-1539,-1664,-1797,-1932,-2065,-2191,-2306,-2407,-2491,-2555,
+-2600,-2625,-2630,-2619,-2593,-2555,-2509,-2457,-2404,-2351,-2303,-2260,-2224,-2197,-2178,-2168,-2167,-2172,-2183,-2198,-2217,
+-2237,-2258,-2278,-2296,-2312,-2325,-2335,-2342,-2345,-2344,-2340,-2333,-2322,-2309,-2293,-2274,-2253,-2229,-2204,-2177,-2148,
+-2119,-2090,-2061,-2033,-2007,-1983,-1961,-1942,-1927,-1914,-1905,-1899,-1896,-1895,-1895,-1896,-1898,-1899,-1900,-1899,-1896,
+-1891,-1884,-1875,-1863,-1851,-1837,-1823,-1809,-1795,-1783,-1772,-1763,-1756,-1752,-1750,-1750,-1751,-1755,-1759,-1763,-1768,
+-1772,-1775,-1776,-1777,-1776,-1773,-1769,-1764,-1758,-1752,-1745,-1740,-1735,-1731,-1728,-1726,-1726,-1727,-1729,-1731,-1733,
+-1735,-1737,-1737,-1737,-1735,-1732,-1727,-1722,-1716,-1710,-1703,-1697,-1692,-1687,-1684,-1682,-1682,-1682,-1683,-1685,-1687,
+-1687,-1687,-1685,-1681,-1675,-1666,-1654,-1640,-1624,-1605,-1586,-1566,-1545,-1525,-1506,-1489,-1474,-1462,-1453,-1446,-1443,
+-1443,-1445,-1450,-1457,-1466,-1477,-1488,-1500,-1513,-1524,-1536,-1546,-1555,-1563,-1568,-1572,-1574,-1574,-1573,-1569,-1564,
+-1558,-1551,-1543,-1535,-1528,-1520,-1513,-1507,-1501,-1495,-1490,-1484,-1477,-1469,-1458,-1445,-1429,-1409,-1385,-1357,-1326,
+-1292,-1255,-1217,-1179,-1141,-1106,-1073,-1046,-1024,-1008,-999,-996,-1001,-1011,-1026,-1046,-1068,-1092,-1117,-1139,-1160,
+-1176,-1188,-1195,-1197,-1194,-1186,-1173,-1157,-1138,-1118,-1097,-1076,-1055,-1037,-1020,-1005,-993,-984,-976,-970,-966,
+-962,-960,-957,-954,-951,-948,-943,-939,-933,-927,-921,-915,-908,-902,-895,-889,-883,-877,-871,-865,-859,
+-853,-847,-841,-835,-829,-823,-818,-813,-808,-804,-800,-797,-794,-791,-789,-786,-784,-780,-777,-772,-767,
+-761,-755,-748,-741,-733,-726,-719,-713,-707,-702,-698,-694,-691,-688,-686,-683,-679,-674,-669,-662,-653,
+-643,-632,-619,-606,-592,-578,-564,-551,-539,-528,-519,-510,-502,-495,-488,-481,-473,-464,-454,-442,-428,
+-412,-395,-377,-359,-341,-324,-309,-296,-287,-281,-280,-283,-290,-300,-313,-329,-345,-362,-416,-427,-437,
+-444,-448,-449,-446,-439,-428,-415,-398,-380,-360,-339,-319,-299,-280,-262,-246,-232,-219,-208,-198,-189,
+-180,-171,-162,-153,-143,-132,-120,-108,-96,-83,-70,-57,-44,-32,-20,-9,0,10,20,29,38,
+48,57,67,78,89,100,112,124,136,147,159,171,182,193,203,213,223,232,241,251,260,
+270,280,290,301,311,321,331,341,350,358,366,372,378,383,388,392,396,400,405,411,417,
+425,434,445,457,470,484,498,513,528,542,555,567,577,585,591,595,597,598,597,594,591,
+587,583,578,574,571,568,566,565,564,564,565,565,566,566,567,567,566,565,564,562,560,
+557,555,553,551,549,547,547,546,547,548,549,551,554,557,561,565,569,573,577,582,586,
+591,595,599,603,607,611,615,619,623,627,631,636,642,648,654,662,670,678,688,697,707,
+717,727,737,746,755,762,769,774,778,780,781,781,780,778,776,773,769,766,763,760,758,
+756,756,756,757,759,762,766,772,778,785,793,803,813,824,837,850,864,878,893,909,924,
+940,955,969,982,994,1005,1014,1021,1026,1030,1031,1030,1028,1023,1017,1010,1001,990,979,967,953,
+940,925,910,894,877,861,844,826,808,790,772,754,736,719,702,686,670,655,641,628,616,
+604,594,584,575,567,559,551,544,538,531,525,520,514,509,503,499,494,489,485,481,477,
+473,469,466,462,458,455,451,448,445,442,439,438,436,436,436,438,440,444,449,454,460,
+467,475,482,489,496,502,506,510,511,511,509,504,498,489,478,466,452,437,421,404,388,
+371,355,339,325,311,298,286,275,264,254,244,234,223,212,200,187,172,157,139,121,102,
+81,60,38,17,-4,-25,-45,-64,-82,-98,-113,-126,-138,-149,-158,-166,-174,-181,-187,-194,-202,
+-211,-220,-232,-245,-260,-278,-299,-322,-348,-377,-409,-444,-481,-521,-562,-605,-649,-694,-738,-783,-826,
+-868,-908,-945,-981,-1013,-1043,-1071,-1096,-1118,-1139,-1158,-1176,-1193,-1210,-1227,-1244,-1262,-1282,-1302,-1325,-1349,
+-1374,-1401,-1430,-1460,-1491,-1524,-1557,-1591,-1626,-1660,-1695,-1730,-1764,-1798,-1832,-1864,-1896,-1927,-1957,-1987,-2015,
+-2043,-2070,-2096,-2122,-2148,-2174,-2200,-2226,-2253,-2279,-2306,-2333,-2360,-2387,-2413,-2439,-2465,-2489,-2513,-2535,-2557,
+-2578,-2598,-2618,-2637,-2657,-2677,-2697,-2719,-2743,-2767,-2794,-2822,-2851,-2882,-2914,-2947,-2980,-3013,-3046,-3078,-3109,
+-3138,-3167,-3194,-3220,-3244,-3268,-3291,-3314,-3337,-3360,-3384,-3408,-3433,-3459,-3485,-3512,-3540,-3568,-3597,-3625,-3653,
+-3680,-3707,-3733,-3759,-3784,-3809,-3833,-3856,-3879,-3902,-3925,-3947,-3968,-3989,-4009,-4029,-4047,-4065,-4081,-4095,-4108,
+-4120,-4130,-4139,-4146,-4153,-4160,-4166,-4172,-4178,-4185,-4192,-4201,-4211,-4222,-4234,-4248,-4263,-4279,-4297,-4315,-4335,
+-4356,-4378,-4401,-4425,-4449,-4475,-4501,-4528,-4556,-4585,-4613,-4643,-4672,-4702,-4731,-4760,-4789,-4817,-4843,-4869,-4894,
+-4918,-4940,-4961,-4980,-4998,-5015,-5031,-5046,-5060,-5073,-5086,-5099,-5112,-5125,-5138,-5152,-5167,-5182,-5199,-5216,-5233,
+-5252,-5271,-5289,-5308,-5327,-5344,-5361,-5376,-5389,-5401,-5411,-5419,-5425,-5430,-5432,-5434,-5434,-5434,-5433,-5432,-5431,
+-5430,-5429,-5429,-5430,-5430,-5431,-5432,-5433,-5434,-5435,-5435,-5434,-5433,-5432,-5430,-5429,-5427,-5426,-5424,-5423,-5423,
+-5423,-5422,-5422,-5420,-5418,-5415,-5409,-5402,-5392,-5379,-5365,-5348,-5330,-5311,-5293,-5275,-5259,-5247,-5239,-5236,-5239,
+-5249,-5265,-5288,-5317,-5351,-5389,-5430,-5472,-5514,-5554,-5590,-5621,-5646,-5664,-5674,-5676,-5670,-5657,-5637,-5612,-5582,
+-5549,-5515,-5480,-5446,-5414,-5385,-5359,-5337,-5318,-5303,-5291,-5283,-5276,-5272,-5269,-5267,-5266,-5265,-5264,-5264,-5264,
+-5264,-5265,-5266,-5268,-5271,-5274,-5278,-5282,-5287,-5291,-5295,-5298,-5300,-5301,-5301,-5299,-5296,-5292,-5287,-5281,-5276,
+-5271,-5267,-5264,-5264,-5266,-5270,-5276,-5285,-5296,-5309,-5323,-5338,-5354,-5370,-5385,-5400,-5414,-5427,-5438,-5448,-5457,
+-5465,-5472,-5478,-5485,-5491,-5497,-5503,-5510,-5517,-5523,-5529,-5535,-5540,-5544,-5547,-5548,-5548,-5547,-5544,-5540,-5535,
+-5530,-5525,-5520,-5516,-5512,-5511,-5510,-5511,-5513,-5516,-5521,-5525,-5530,-5535,-5539,-5542,-5544,-5544,-5543,-5541,-5537,
+-5532,-5527,-5521,-5516,-5511,-5508,-5506,-5505,-5506,-5509,-5514,-5519,-5526,-5533,-5541,-5548,-5553,-5558,-5560,-5561,-5559,
+-5555,-5549,-5540,-5530,-5518,-5505,-5492,-5478,-5465,-5452,-5440,-5429,-5419,-5411,-5404,-5399,-5394,-5390,-5387,-5384,-5381,
+-5377,-5374,-5369,-5364,-5358,-5351,-5344,-5335,-5327,-5318,-5309,-5301,-5294,-5287,-5282,-5278,-5276,-5276,-5278,-5282,-5288,
+-5295,-5304,-5313,-5323,-5333,-5342,-5350,-5356,-5360,-5361,-5359,-5355,-5346,-5335,-5321,-5304,-5285,-5264,-5243,-5221,-5199,
+-5178,-5158,-5140,-5124,-5110,-5099,-5091,-5084,-5080,-5077,-5076,-5075,-5075,-5076,-5076,-5075,-5075,-5074,-5072,-5070,-5069,
+-5067,-5066,-5065,-5066,-5067,-5069,-5073,-5077,-5082,-5087,-5091,-5096,-5099,-5100,-5100,-5097,-5091,-5082,-5070,-5056,-5038,
+-5018,-4996,-4973,-4948,-4922,-4897,-4872,-4847,-4824,-4802,-4782,-4764,-4747,-4731,-4717,-4705,-4692,-4681,-4669,-4657,-4644,
+-4631,-4616,-4601,-4583,-4565,-4544,-4523,-4500,-4476,-4452,-4426,-4401,-4375,-4349,-4324,-4300,-4278,-4256,-4237,-4219,-4204,
+-4190,-4179,-4169,-4162,-4156,-4151,-4147,-4144,-4142,-4139,-4136,-4132,-4126,-4120,-4112,-4102,-4091,-4078,-4064,-4050,-4034,
+-4018,-4002,-3985,-3969,-3953,-3937,-3922,-3907,-3892,-3877,-3861,-3846,-3829,-3812,-3795,-3776,-3756,-3736,-3716,-3695,-3674,
+-3654,-3634,-3615,-3598,-3582,-3568,-3555,-3544,-3535,-3528,-3521,-3516,-3511,-3507,-3503,-3498,-3493,-3488,-3481,-3474,-3465,
+-3456,-3446,-3435,-3425,-3414,-3403,-3393,-3384,-3376,-3370,-3365,-3361,-3360,-3359,-3361,-3363,-3367,-3371,-3375,-3379,-3382,
+-3383,-3383,-3380,-3375,-3366,-3355,-3341,-3324,-3305,-3284,-3261,-3237,-3213,-3190,-3167,-3145,-3125,-3107,-3091,-3076,-3063,
+-3050,-3039,-3027,-3015,-3002,-2987,-2971,-2953,-2933,-2911,-2888,-2864,-2840,-2816,-2792,-2770,-2750,-2730,-2713,-2696,-2681,
+-2665,-2650,-2632,-2613,-2591,-2565,-2536,-2503,-2467,-2428,-2387,-2345,-2302,-2261,-2222,-2186,-2153,-2124,-2099,-2078,-2060,
+-2043,-2026,-2007,-1985,-1959,-1927,-1888,-1842,-1788,-1729,-1665,-1598,-1530,-1466,-1408,-1358,-1321,-1299,-1294,-1307,-1340,
+-1392,-1462,-1548,-1648,-1758,-1875,-1994,-2112,-2223,-2326,-2416,-2491,-2549,-2590,-2614,-2621,-2613,-2592,-2560,-2520,-2476,
+-2430,-2384,-2342,-2304,-2273,-2248,-2231,-2222,-2219,-2222,-2230,-2242,-2256,-2272,-2287,-2302,-2315,-2326,-2334,-2340,-2343,
+-2343,-2340,-2335,-2328,-2318,-2307,-2294,-2278,-2261,-2243,-2222,-2200,-2176,-2151,-2126,-2100,-2073,-2048,-2023,-2001,-1980,
+-1962,-1947,-1936,-1927,-1922,-1919,-1919,-1921,-1923,-1927,-1930,-1933,-1934,-1934,-1931,-1926,-1918,-1908,-1896,-1882,-1868,
+-1853,-1838,-1823,-1810,-1799,-1789,-1782,-1778,-1775,-1775,-1777,-1780,-1784,-1789,-1793,-1798,-1802,-1804,-1806,-1807,-1806,
+-1805,-1802,-1800,-1797,-1794,-1791,-1789,-1787,-1786,-1786,-1787,-1788,-1789,-1790,-1791,-1791,-1791,-1790,-1788,-1786,-1782,
+-1778,-1773,-1768,-1763,-1758,-1753,-1749,-1745,-1742,-1740,-1737,-1735,-1733,-1730,-1727,-1722,-1716,-1707,-1698,-1686,-1672,
+-1656,-1639,-1621,-1601,-1581,-1562,-1543,-1525,-1508,-1494,-1481,-1471,-1464,-1460,-1458,-1460,-1463,-1470,-1478,-1488,-1499,
+-1511,-1523,-1536,-1548,-1560,-1570,-1579,-1587,-1592,-1596,-1597,-1597,-1594,-1591,-1585,-1579,-1572,-1565,-1557,-1549,-1542,
+-1535,-1528,-1520,-1513,-1505,-1497,-1487,-1476,-1463,-1448,-1431,-1412,-1391,-1369,-1346,-1322,-1299,-1277,-1257,-1240,-1226,
+-1216,-1210,-1208,-1210,-1216,-1226,-1238,-1253,-1267,-1282,-1296,-1307,-1315,-1319,-1320,-1316,-1307,-1294,-1278,-1258,-1235,
+-1211,-1186,-1161,-1136,-1113,-1091,-1072,-1055,-1041,-1030,-1021,-1014,-1010,-1007,-1005,-1004,-1003,-1003,-1004,-1004,-1003,
+-1003,-1002,-1000,-998,-996,-993,-989,-985,-980,-975,-968,-962,-954,-947,-939,-930,-922,-914,-907,-900,-893,
+-888,-884,-880,-877,-875,-874,-873,-872,-871,-869,-867,-864,-861,-856,-851,-844,-837,-830,-822,-814,-806,
+-799,-791,-784,-778,-772,-766,-760,-753,-747,-740,-731,-723,-713,-702,-691,-678,-666,-653,-641,-629,-617,
+-607,-597,-588,-580,-572,-565,-557,-550,-541,-531,-520,-507,-493,-478,-461,-444,-426,-410,-394,-380,-369,
+-360,-355,-353,-355,-360,-368,-378,-390,-403,-416,-484,-490,-494,-496,-495,-491,-485,-476,-464,-450,-434,
+-417,-399,-380,-362,-344,-327,-311,-296,-283,-271,-259,-249,-239,-229,-220,-210,-200,-189,-177,-165,-152,
+-139,-126,-113,-100,-88,-76,-64,-53,-43,-34,-25,-16,-8,0,8,17,26,36,46,56,67,
+78,89,101,112,123,134,145,156,166,176,186,196,206,216,227,237,247,258,268,278,288,
+298,308,317,325,333,340,347,353,360,366,372,379,386,393,402,411,421,431,443,454,466,
+478,490,501,512,522,531,538,545,551,555,558,561,563,564,564,565,565,566,566,567,567,
+568,568,569,569,569,568,567,565,563,560,556,551,546,540,534,528,521,515,509,503,497,
+492,488,484,481,479,477,477,477,478,480,483,486,490,494,499,504,510,516,523,530,537,
+545,553,561,570,579,589,598,609,619,630,641,652,663,673,683,693,701,709,716,721,725,
+728,730,731,731,730,728,725,722,719,716,713,710,708,706,704,704,704,705,706,708,712,
+716,721,727,734,743,752,763,775,789,803,818,835,852,869,887,905,922,939,954,969,982,
+993,1002,1009,1014,1016,1016,1014,1010,1003,995,985,973,960,946,931,916,899,883,866,849,833,
+817,801,785,771,756,743,730,717,705,693,681,670,658,647,635,624,612,599,587,575,563,
+551,539,528,518,508,500,493,487,482,478,475,473,472,472,472,473,473,473,474,474,473,
+472,472,471,470,469,468,468,468,470,471,474,478,482,486,491,496,500,504,507,509,510,
+509,507,503,497,490,481,471,459,447,434,420,407,393,380,367,355,343,332,321,311,301,
+291,282,272,261,250,239,226,213,199,184,168,152,135,117,99,81,62,44,25,7,-9,
+-27,-43,-59,-74,-89,-102,-115,-128,-139,-150,-161,-172,-183,-194,-206,-219,-234,-250,-269,-290,-314,
+-340,-370,-403,-438,-477,-518,-561,-605,-651,-697,-743,-788,-831,-873,-912,-948,-982,-1012,-1039,-1064,-1086,
+-1106,-1125,-1143,-1160,-1177,-1195,-1215,-1235,-1258,-1282,-1308,-1336,-1366,-1398,-1430,-1464,-1498,-1532,-1565,-1598,-1630,
+-1661,-1690,-1719,-1746,-1772,-1797,-1821,-1844,-1867,-1890,-1913,-1937,-1960,-1984,-2009,-2034,-2060,-2087,-2115,-2142,-2171,
+-2199,-2228,-2256,-2285,-2313,-2341,-2369,-2396,-2423,-2449,-2475,-2501,-2526,-2551,-2576,-2602,-2627,-2653,-2679,-2705,-2732,
+-2760,-2788,-2817,-2846,-2876,-2905,-2934,-2964,-2992,-3021,-3048,-3075,-3101,-3126,-3150,-3174,-3197,-3220,-3242,-3265,-3288,
+-3311,-3334,-3358,-3383,-3409,-3435,-3461,-3489,-3516,-3544,-3572,-3600,-3627,-3655,-3682,-3709,-3735,-3761,-3787,-3812,-3836,
+-3860,-3884,-3906,-3928,-3949,-3969,-3988,-4006,-4022,-4038,-4051,-4064,-4075,-4085,-4094,-4102,-4110,-4117,-4124,-4131,-4139,
+-4148,-4157,-4167,-4179,-4192,-4206,-4222,-4238,-4256,-4274,-4293,-4313,-4333,-4354,-4374,-4395,-4416,-4437,-4459,-4480,-4502,
+-4524,-4547,-4571,-4595,-4619,-4645,-4671,-4698,-4725,-4752,-4780,-4808,-4835,-4861,-4887,-4912,-4936,-4958,-4979,-4998,-5016,
+-5032,-5047,-5060,-5073,-5085,-5097,-5108,-5120,-5131,-5144,-5157,-5171,-5185,-5201,-5216,-5232,-5248,-5264,-5279,-5293,-5305,
+-5316,-5325,-5332,-5336,-5338,-5339,-5337,-5334,-5329,-5324,-5317,-5311,-5305,-5299,-5294,-5290,-5287,-5285,-5285,-5285,-5286,
+-5288,-5291,-5294,-5297,-5300,-5303,-5305,-5307,-5309,-5310,-5310,-5310,-5308,-5306,-5303,-5298,-5293,-5286,-5279,-5270,-5260,
+-5250,-5240,-5229,-5220,-5211,-5205,-5202,-5202,-5206,-5214,-5228,-5247,-5271,-5301,-5335,-5374,-5415,-5459,-5503,-5547,-5588,
+-5626,-5659,-5687,-5707,-5721,-5726,-5724,-5714,-5697,-5674,-5646,-5614,-5580,-5544,-5507,-5472,-5438,-5408,-5380,-5355,-5334,
+-5317,-5303,-5291,-5282,-5275,-5269,-5265,-5261,-5257,-5254,-5251,-5248,-5245,-5244,-5242,-5242,-5242,-5244,-5246,-5249,-5252,
+-5256,-5260,-5263,-5265,-5267,-5267,-5266,-5263,-5259,-5255,-5249,-5243,-5238,-5233,-5230,-5228,-5228,-5230,-5235,-5243,-5252,
+-5264,-5277,-5292,-5308,-5323,-5339,-5354,-5368,-5381,-5393,-5403,-5412,-5420,-5426,-5432,-5437,-5442,-5447,-5452,-5458,-5464,
+-5469,-5475,-5481,-5487,-5492,-5496,-5498,-5500,-5500,-5499,-5497,-5493,-5489,-5484,-5479,-5475,-5471,-5468,-5467,-5467,-5468,
+-5470,-5474,-5479,-5484,-5489,-5494,-5499,-5502,-5504,-5505,-5504,-5502,-5498,-5494,-5489,-5483,-5478,-5474,-5470,-5468,-5468,
+-5469,-5472,-5476,-5482,-5488,-5495,-5502,-5507,-5512,-5515,-5515,-5513,-5509,-5501,-5491,-5479,-5465,-5449,-5432,-5415,-5397,
+-5380,-5365,-5351,-5338,-5328,-5320,-5314,-5310,-5308,-5308,-5308,-5310,-5311,-5313,-5315,-5316,-5316,-5316,-5314,-5312,-5308,
+-5304,-5300,-5295,-5290,-5286,-5283,-5280,-5278,-5277,-5278,-5280,-5283,-5287,-5292,-5298,-5304,-5309,-5314,-5318,-5321,-5322,
+-5321,-5318,-5312,-5304,-5294,-5282,-5267,-5251,-5234,-5215,-5196,-5176,-5157,-5139,-5122,-5106,-5091,-5079,-5068,-5058,-5051,
+-5045,-5040,-5037,-5034,-5033,-5032,-5031,-5031,-5031,-5031,-5032,-5033,-5034,-5035,-5038,-5040,-5044,-5047,-5051,-5056,-5060,
+-5064,-5068,-5071,-5072,-5072,-5070,-5066,-5060,-5051,-5040,-5026,-5010,-4992,-4972,-4950,-4927,-4904,-4881,-4857,-4835,-4813,
+-4792,-4773,-4755,-4738,-4723,-4710,-4697,-4685,-4673,-4662,-4650,-4638,-4625,-4611,-4595,-4578,-4560,-4540,-4519,-4496,-4472,
+-4446,-4420,-4394,-4367,-4341,-4315,-4290,-4266,-4244,-4224,-4206,-4189,-4175,-4164,-4154,-4146,-4141,-4136,-4133,-4131,-4129,
+-4127,-4125,-4123,-4119,-4114,-4108,-4101,-4092,-4083,-4071,-4059,-4046,-4033,-4019,-4006,-3992,-3979,-3965,-3953,-3941,-3929,
+-3918,-3906,-3894,-3883,-3870,-3857,-3843,-3828,-3812,-3796,-3778,-3760,-3742,-3724,-3706,-3688,-3671,-3656,-3641,-3628,-3617,
+-3608,-3600,-3594,-3590,-3586,-3584,-3582,-3581,-3580,-3578,-3576,-3573,-3569,-3564,-3558,-3550,-3541,-3531,-3520,-3509,-3497,
+-3485,-3474,-3463,-3453,-3444,-3436,-3429,-3424,-3420,-3416,-3413,-3410,-3407,-3404,-3399,-3392,-3384,-3374,-3361,-3347,-3330,
+-3311,-3291,-3269,-3247,-3224,-3201,-3179,-3158,-3138,-3119,-3101,-3085,-3070,-3055,-3040,-3026,-3010,-2994,-2977,-2958,-2937,
+-2915,-2892,-2868,-2843,-2818,-2793,-2769,-2746,-2724,-2704,-2684,-2666,-2649,-2632,-2614,-2596,-2576,-2554,-2530,-2502,-2472,
+-2440,-2405,-2368,-2331,-2293,-2256,-2221,-2188,-2157,-2130,-2107,-2086,-2068,-2052,-2037,-2021,-2004,-1985,-1962,-1935,-1903,
+-1867,-1827,-1784,-1739,-1694,-1651,-1612,-1579,-1554,-1540,-1537,-1548,-1572,-1609,-1658,-1719,-1790,-1868,-1951,-2036,-2120,
+-2201,-2275,-2342,-2398,-2443,-2477,-2499,-2510,-2510,-2502,-2487,-2467,-2443,-2417,-2392,-2368,-2347,-2330,-2316,-2306,-2300,
+-2298,-2298,-2299,-2302,-2306,-2308,-2310,-2311,-2310,-2308,-2304,-2299,-2293,-2287,-2280,-2273,-2267,-2261,-2255,-2249,-2243,
+-2236,-2229,-2220,-2210,-2198,-2185,-2169,-2152,-2133,-2112,-2092,-2071,-2050,-2030,-2013,-1997,-1983,-1973,-1965,-1960,-1957,
+-1956,-1957,-1958,-1960,-1962,-1963,-1962,-1960,-1955,-1948,-1939,-1928,-1916,-1902,-1887,-1872,-1857,-1843,-1830,-1820,-1811,
+-1805,-1801,-1799,-1799,-1801,-1805,-1809,-1814,-1820,-1825,-1830,-1835,-1838,-1841,-1843,-1844,-1845,-1845,-1844,-1844,-1843,
+-1843,-1843,-1843,-1843,-1844,-1845,-1846,-1847,-1848,-1848,-1848,-1848,-1848,-1847,-1846,-1844,-1842,-1840,-1837,-1835,-1832,
+-1829,-1826,-1822,-1818,-1813,-1807,-1800,-1791,-1781,-1770,-1756,-1741,-1725,-1706,-1687,-1666,-1644,-1622,-1600,-1578,-1557,
+-1538,-1520,-1504,-1490,-1479,-1471,-1465,-1463,-1463,-1467,-1473,-1481,-1491,-1503,-1516,-1529,-1544,-1558,-1571,-1584,-1595,
+-1604,-1612,-1618,-1622,-1624,-1623,-1621,-1617,-1612,-1606,-1598,-1590,-1581,-1573,-1564,-1555,-1546,-1537,-1529,-1520,-1512,
+-1504,-1496,-1488,-1481,-1473,-1466,-1460,-1455,-1451,-1448,-1447,-1447,-1449,-1453,-1458,-1465,-1472,-1480,-1487,-1494,-1499,
+-1503,-1504,-1502,-1497,-1488,-1475,-1459,-1439,-1416,-1390,-1361,-1331,-1301,-1270,-1239,-1210,-1183,-1157,-1135,-1115,-1098,
+-1084,-1072,-1064,-1058,-1055,-1053,-1053,-1054,-1057,-1060,-1064,-1069,-1073,-1078,-1082,-1086,-1090,-1093,-1095,-1096,-1095,
+-1094,-1090,-1086,-1080,-1073,-1064,-1055,-1044,-1033,-1022,-1012,-1001,-991,-983,-975,-968,-963,-959,-956,-954,-953,
+-952,-952,-951,-950,-948,-946,-943,-939,-934,-928,-922,-915,-907,-899,-891,-883,-875,-866,-858,-849,-841,
+-831,-822,-812,-802,-791,-780,-769,-757,-746,-734,-723,-712,-702,-692,-683,-675,-667,-659,-651,-643,-634,
+-625,-614,-603,-591,-577,-563,-548,-533,-518,-504,-490,-479,-469,-461,-456,-453,-453,-455,-459,-465,-471,
+-478,-484,-570,-570,-569,-566,-561,-554,-545,-535,-522,-508,-492,-476,-459,-442,-426,-410,-394,-380,-366,
+-354,-342,-331,-320,-310,-300,-290,-279,-268,-256,-244,-232,-219,-206,-193,-180,-167,-155,-143,-132,-122,
+-112,-103,-95,-87,-79,-72,-64,-56,-48,-39,-30,-20,-10,0,11,23,35,46,58,69,81,
+92,102,113,123,133,142,152,161,170,180,189,198,207,216,225,234,243,252,261,269,278,
+286,295,303,312,321,330,339,349,359,369,379,390,401,411,422,432,442,452,461,469,477,
+484,491,497,502,507,512,516,519,523,526,528,531,533,534,536,536,536,535,533,531,527,
+523,517,511,503,495,486,477,467,457,447,438,428,419,411,403,397,391,387,384,381,381,
+381,382,385,388,393,398,405,412,420,428,437,447,457,468,480,492,504,517,530,543,556,
+570,583,596,609,620,632,642,651,659,666,671,675,678,680,680,680,679,677,675,672,670,
+667,665,663,661,660,659,658,658,658,659,660,661,663,665,668,671,675,681,687,695,705,
+716,729,744,761,779,799,820,842,865,888,910,932,952,971,988,1002,1013,1021,1026,1027,1025,
+1020,1012,1002,988,973,956,938,920,901,881,863,845,828,811,797,783,770,759,748,737,727,
+717,707,696,684,672,658,644,628,611,594,576,558,540,523,506,490,476,463,453,444,438,
+433,431,430,432,434,438,442,447,452,457,461,465,468,470,472,473,474,475,475,475,476,
+477,478,480,482,485,487,490,493,495,496,497,497,495,493,489,484,478,470,462,453,443,
+433,423,412,402,392,383,374,365,356,348,340,331,322,313,304,294,283,271,259,246,232,
+218,203,188,172,156,139,123,106,89,72,55,38,22,5,-11,-28,-45,-61,-77,-93,-108,
+-123,-137,-152,-165,-179,-193,-208,-223,-240,-258,-277,-299,-324,-351,-381,-414,-450,-488,-529,-572,-616,
+-661,-707,-752,-796,-838,-878,-916,-951,-983,-1011,-1037,-1060,-1081,-1100,-1118,-1136,-1154,-1172,-1192,-1213,-1236,
+-1261,-1289,-1319,-1351,-1385,-1420,-1455,-1491,-1527,-1563,-1597,-1630,-1661,-1690,-1718,-1743,-1767,-1789,-1811,-1831,-1851,
+-1870,-1890,-1910,-1931,-1952,-1975,-1999,-2023,-2049,-2075,-2102,-2129,-2157,-2185,-2212,-2240,-2267,-2294,-2321,-2348,-2374,
+-2400,-2427,-2454,-2481,-2508,-2536,-2565,-2594,-2624,-2654,-2685,-2716,-2747,-2778,-2810,-2840,-2871,-2900,-2929,-2957,-2984,
+-3010,-3035,-3059,-3082,-3104,-3126,-3147,-3168,-3189,-3210,-3232,-3253,-3276,-3298,-3322,-3346,-3370,-3395,-3421,-3447,-3474,
+-3501,-3528,-3555,-3582,-3609,-3636,-3664,-3690,-3717,-3743,-3769,-3795,-3819,-3844,-3867,-3890,-3911,-3932,-3951,-3969,-3985,
+-4001,-4014,-4027,-4038,-4049,-4058,-4067,-4075,-4083,-4092,-4100,-4110,-4120,-4131,-4143,-4156,-4171,-4186,-4203,-4220,-4238,
+-4256,-4275,-4293,-4312,-4331,-4349,-4367,-4384,-4401,-4419,-4436,-4453,-4471,-4489,-4508,-4528,-4549,-4572,-4596,-4621,-4647,
+-4675,-4703,-4732,-4762,-4791,-4821,-4849,-4877,-4904,-4929,-4952,-4973,-4993,-5010,-5026,-5040,-5052,-5064,-5074,-5084,-5094,
+-5103,-5113,-5123,-5133,-5145,-5156,-5168,-5180,-5192,-5204,-5215,-5225,-5233,-5240,-5244,-5247,-5248,-5246,-5242,-5236,-5229,
+-5220,-5210,-5200,-5189,-5179,-5169,-5161,-5154,-5148,-5144,-5142,-5141,-5142,-5144,-5147,-5152,-5157,-5162,-5167,-5172,-5176,
+-5179,-5181,-5181,-5181,-5178,-5174,-5169,-5163,-5155,-5147,-5138,-5130,-5123,-5116,-5112,-5110,-5111,-5116,-5125,-5139,-5158,
+-5182,-5212,-5246,-5286,-5329,-5376,-5425,-5476,-5526,-5575,-5621,-5664,-5701,-5732,-5756,-5772,-5780,-5780,-5772,-5757,-5735,
+-5707,-5674,-5638,-5600,-5561,-5523,-5485,-5450,-5418,-5388,-5363,-5341,-5323,-5307,-5295,-5285,-5276,-5269,-5263,-5257,-5251,
+-5245,-5240,-5234,-5228,-5223,-5218,-5214,-5211,-5209,-5208,-5209,-5210,-5212,-5214,-5217,-5219,-5222,-5223,-5224,-5223,-5222,
+-5219,-5216,-5212,-5208,-5204,-5200,-5198,-5197,-5198,-5201,-5206,-5213,-5222,-5233,-5246,-5259,-5274,-5289,-5303,-5317,-5331,
+-5343,-5354,-5363,-5372,-5379,-5385,-5390,-5395,-5399,-5404,-5408,-5412,-5417,-5421,-5426,-5431,-5435,-5439,-5442,-5444,-5445,
+-5445,-5444,-5442,-5439,-5435,-5431,-5427,-5423,-5420,-5418,-5416,-5416,-5417,-5420,-5423,-5427,-5431,-5436,-5441,-5445,-5448,
+-5450,-5451,-5451,-5449,-5446,-5442,-5438,-5433,-5428,-5424,-5421,-5418,-5417,-5418,-5419,-5422,-5426,-5431,-5436,-5441,-5445,
+-5449,-5451,-5451,-5448,-5444,-5437,-5428,-5416,-5403,-5389,-5373,-5357,-5341,-5325,-5311,-5297,-5286,-5276,-5268,-5263,-5259,
+-5257,-5257,-5258,-5260,-5262,-5265,-5268,-5272,-5274,-5277,-5279,-5280,-5282,-5282,-5283,-5284,-5285,-5286,-5288,-5290,-5293,
+-5296,-5300,-5304,-5308,-5312,-5315,-5318,-5320,-5321,-5321,-5319,-5315,-5309,-5302,-5293,-5282,-5269,-5255,-5239,-5223,-5205,
+-5188,-5170,-5152,-5135,-5118,-5102,-5087,-5074,-5061,-5050,-5039,-5030,-5022,-5014,-5008,-5002,-4997,-4993,-4989,-4986,-4984,
+-4982,-4981,-4981,-4982,-4983,-4986,-4989,-4993,-4998,-5003,-5008,-5013,-5018,-5023,-5027,-5029,-5030,-5029,-5026,-5021,-5014,
+-5004,-4993,-4979,-4964,-4947,-4929,-4910,-4890,-4870,-4851,-4832,-4813,-4796,-4779,-4764,-4749,-4736,-4723,-4711,-4699,-4687,
+-4674,-4662,-4648,-4633,-4617,-4599,-4580,-4559,-4536,-4513,-4487,-4461,-4434,-4406,-4379,-4351,-4324,-4298,-4273,-4249,-4227,
+-4207,-4189,-4174,-4160,-4148,-4139,-4131,-4125,-4121,-4117,-4114,-4112,-4110,-4108,-4105,-4102,-4098,-4093,-4087,-4080,-4073,
+-4064,-4055,-4045,-4034,-4024,-4014,-4003,-3993,-3984,-3974,-3966,-3957,-3949,-3942,-3934,-3926,-3918,-3910,-3901,-3891,-3880,
+-3868,-3856,-3843,-3829,-3815,-3800,-3786,-3771,-3758,-3745,-3733,-3722,-3713,-3705,-3699,-3694,-3691,-3689,-3688,-3688,-3689,
+-3690,-3690,-3690,-3689,-3687,-3684,-3679,-3672,-3664,-3654,-3642,-3629,-3614,-3599,-3583,-3567,-3551,-3535,-3520,-3506,-3492,
+-3479,-3467,-3455,-3444,-3434,-3423,-3412,-3400,-3387,-3374,-3359,-3343,-3326,-3308,-3289,-3269,-3249,-3229,-3209,-3189,-3170,
+-3152,-3135,-3118,-3102,-3086,-3070,-3054,-3037,-3019,-3000,-2980,-2958,-2934,-2909,-2882,-2855,-2827,-2798,-2770,-2743,-2716,
+-2691,-2667,-2645,-2624,-2605,-2586,-2568,-2550,-2531,-2511,-2490,-2468,-2443,-2417,-2389,-2359,-2329,-2298,-2267,-2236,-2207,
+-2179,-2154,-2131,-2110,-2091,-2074,-2058,-2043,-2029,-2014,-1998,-1980,-1960,-1939,-1915,-1890,-1864,-1837,-1812,-1789,-1768,
+-1753,-1742,-1738,-1741,-1752,-1770,-1796,-1828,-1866,-1909,-1956,-2005,-2054,-2103,-2150,-2193,-2233,-2268,-2297,-2322,-2342,
+-2357,-2368,-2376,-2382,-2385,-2388,-2389,-2391,-2392,-2393,-2394,-2395,-2395,-2394,-2391,-2387,-2380,-2371,-2360,-2347,-2332,
+-2316,-2298,-2281,-2265,-2249,-2236,-2224,-2215,-2210,-2206,-2206,-2207,-2210,-2214,-2218,-2221,-2223,-2224,-2221,-2216,-2208,
+-2197,-2183,-2166,-2147,-2127,-2107,-2086,-2066,-2048,-2031,-2017,-2006,-1997,-1991,-1987,-1985,-1984,-1985,-1985,-1986,-1985,
+-1983,-1980,-1975,-1968,-1959,-1948,-1936,-1923,-1909,-1896,-1882,-1870,-1860,-1850,-1843,-1838,-1835,-1834,-1835,-1838,-1841,
+-1846,-1852,-1858,-1864,-1870,-1876,-1881,-1885,-1888,-1891,-1893,-1895,-1896,-1897,-1898,-1899,-1899,-1900,-1902,-1903,-1905,
+-1907,-1910,-1912,-1915,-1918,-1921,-1923,-1926,-1928,-1930,-1931,-1931,-1931,-1929,-1926,-1922,-1917,-1910,-1901,-1889,-1877,
+-1861,-1844,-1825,-1804,-1781,-1757,-1732,-1705,-1679,-1652,-1625,-1600,-1575,-1552,-1532,-1513,-1498,-1485,-1475,-1469,-1466,
+-1466,-1469,-1474,-1483,-1493,-1506,-1519,-1534,-1550,-1566,-1582,-1597,-1611,-1623,-1635,-1644,-1651,-1656,-1659,-1660,-1658,
+-1655,-1650,-1643,-1636,-1627,-1617,-1607,-1597,-1586,-1577,-1568,-1560,-1554,-1549,-1546,-1544,-1545,-1547,-1552,-1559,-1568,
+-1579,-1591,-1605,-1620,-1635,-1651,-1666,-1680,-1692,-1702,-1709,-1713,-1713,-1709,-1700,-1688,-1670,-1649,-1624,-1595,-1564,
+-1530,-1495,-1459,-1423,-1387,-1353,-1320,-1290,-1262,-1237,-1215,-1197,-1181,-1168,-1158,-1151,-1146,-1142,-1141,-1142,-1143,
+-1146,-1150,-1155,-1160,-1166,-1172,-1178,-1185,-1191,-1196,-1201,-1205,-1208,-1209,-1209,-1207,-1203,-1197,-1190,-1181,-1171,
+-1160,-1148,-1136,-1124,-1112,-1100,-1090,-1080,-1072,-1066,-1060,-1056,-1053,-1051,-1050,-1049,-1049,-1049,-1048,-1048,-1046,
+-1044,-1042,-1038,-1034,-1029,-1023,-1017,-1010,-1002,-995,-986,-977,-968,-958,-948,-938,-927,-916,-904,-893,-881,
+-869,-858,-847,-836,-825,-814,-804,-794,-784,-775,-765,-754,-744,-732,-721,-708,-695,-682,-668,-654,-640,
+-627,-614,-602,-592,-583,-576,-570,-567,-564,-564,-564,-566,-567,-569,-570,-640,-638,-634,-629,-623,-615,
+-606,-595,-583,-569,-555,-540,-524,-509,-493,-478,-464,-450,-437,-424,-413,-401,-391,-380,-370,-359,-348,
+-338,-326,-314,-302,-290,-277,-265,-252,-240,-228,-216,-205,-194,-185,-175,-166,-158,-150,-142,-134,-126,
+-118,-110,-101,-91,-82,-71,-61,-50,-39,-27,-16,-5,6,17,27,38,48,57,66,75,84,
+92,101,109,117,125,133,141,150,158,167,175,185,194,203,213,223,233,243,254,265,276,
+287,298,309,320,331,342,353,363,373,383,392,401,409,417,424,431,437,443,448,453,457,
+461,465,468,470,472,474,475,475,474,472,469,465,460,454,447,439,430,421,410,400,389,
+378,367,356,346,337,329,322,315,311,307,305,304,304,306,309,313,318,324,331,339,347,
+357,367,378,389,401,414,428,442,456,471,486,501,516,531,546,560,573,585,596,605,614,
+620,625,629,631,631,631,630,628,625,623,620,618,616,615,614,614,615,616,618,620,622,
+624,627,629,631,632,634,635,637,639,642,645,651,657,666,677,691,707,725,746,769,794,
+820,847,874,901,927,951,973,992,1007,1019,1026,1029,1028,1022,1013,1000,985,966,946,925,902,
+880,859,838,819,802,786,772,760,750,740,732,724,716,708,699,689,678,664,649,632,614,
+594,573,552,530,508,487,467,449,433,420,409,401,396,393,393,395,399,405,411,418,426,
+433,440,446,452,456,460,463,465,467,469,470,471,473,475,477,479,482,486,489,492,495,
+497,499,499,499,497,493,489,483,476,468,460,451,441,431,422,412,403,395,386,379,371,
+364,357,349,342,333,325,315,305,294,281,268,254,240,225,209,193,176,160,143,127,110,
+93,77,60,44,27,10,-6,-23,-39,-56,-73,-90,-106,-123,-139,-155,-171,-188,-204,-221,-238,
+-257,-277,-298,-321,-347,-375,-405,-438,-473,-510,-549,-590,-633,-675,-718,-761,-802,-843,-881,-916,-949,
+-980,-1008,-1033,-1056,-1077,-1097,-1116,-1134,-1153,-1172,-1192,-1214,-1238,-1264,-1292,-1322,-1354,-1387,-1421,-1456,-1491,
+-1526,-1560,-1593,-1625,-1655,-1684,-1711,-1737,-1761,-1784,-1807,-1828,-1849,-1871,-1892,-1914,-1937,-1960,-1984,-2009,-2034,
+-2060,-2086,-2112,-2139,-2165,-2191,-2217,-2242,-2267,-2291,-2315,-2340,-2364,-2389,-2414,-2440,-2467,-2495,-2524,-2554,-2584,
+-2616,-2648,-2681,-2714,-2746,-2779,-2811,-2842,-2872,-2901,-2929,-2956,-2982,-3006,-3029,-3051,-3072,-3093,-3113,-3133,-3153,
+-3173,-3194,-3215,-3236,-3258,-3280,-3303,-3327,-3350,-3375,-3400,-3425,-3450,-3476,-3502,-3528,-3554,-3581,-3607,-3634,-3661,
+-3688,-3714,-3741,-3767,-3793,-3818,-3842,-3865,-3888,-3909,-3928,-3946,-3963,-3978,-3992,-4004,-4015,-4025,-4034,-4042,-4050,
+-4059,-4067,-4076,-4086,-4097,-4108,-4121,-4135,-4149,-4165,-4182,-4199,-4216,-4234,-4252,-4270,-4287,-4304,-4321,-4337,-4353,
+-4368,-4384,-4399,-4415,-4431,-4449,-4467,-4486,-4507,-4529,-4553,-4579,-4605,-4633,-4662,-4692,-4723,-4753,-4784,-4813,-4842,
+-4870,-4896,-4920,-4943,-4963,-4982,-4998,-5013,-5026,-5037,-5047,-5057,-5065,-5073,-5081,-5089,-5097,-5105,-5112,-5120,-5128,
+-5136,-5143,-5149,-5155,-5159,-5162,-5163,-5162,-5160,-5156,-5150,-5142,-5133,-5123,-5113,-5102,-5090,-5079,-5069,-5060,-5052,
+-5046,-5041,-5038,-5037,-5038,-5040,-5044,-5049,-5055,-5061,-5067,-5073,-5078,-5083,-5086,-5088,-5088,-5087,-5084,-5080,-5075,
+-5069,-5062,-5056,-5051,-5048,-5046,-5048,-5053,-5062,-5076,-5095,-5119,-5149,-5184,-5225,-5269,-5318,-5369,-5422,-5476,-5529,
+-5580,-5627,-5671,-5708,-5739,-5763,-5779,-5786,-5785,-5776,-5760,-5737,-5709,-5675,-5639,-5600,-5560,-5520,-5481,-5445,-5411,
+-5380,-5353,-5330,-5310,-5293,-5279,-5267,-5257,-5249,-5242,-5234,-5228,-5220,-5213,-5206,-5198,-5191,-5184,-5177,-5171,-5166,
+-5163,-5160,-5159,-5159,-5160,-5162,-5165,-5167,-5170,-5173,-5174,-5176,-5176,-5176,-5175,-5173,-5171,-5169,-5168,-5167,-5167,
+-5168,-5171,-5176,-5182,-5190,-5199,-5210,-5222,-5235,-5248,-5262,-5275,-5287,-5299,-5310,-5320,-5328,-5336,-5342,-5348,-5353,
+-5357,-5361,-5364,-5367,-5371,-5373,-5376,-5379,-5381,-5382,-5383,-5384,-5383,-5382,-5380,-5378,-5375,-5372,-5368,-5365,-5362,
+-5360,-5358,-5358,-5358,-5359,-5362,-5365,-5368,-5372,-5376,-5380,-5384,-5387,-5389,-5390,-5390,-5389,-5387,-5384,-5380,-5376,
+-5372,-5368,-5365,-5362,-5361,-5360,-5361,-5363,-5366,-5369,-5373,-5377,-5381,-5384,-5386,-5387,-5387,-5385,-5382,-5377,-5370,
+-5362,-5352,-5342,-5331,-5320,-5308,-5298,-5288,-5278,-5270,-5263,-5257,-5253,-5249,-5246,-5245,-5244,-5244,-5244,-5245,-5246,
+-5247,-5249,-5250,-5253,-5255,-5258,-5262,-5266,-5271,-5276,-5282,-5289,-5296,-5302,-5309,-5315,-5321,-5326,-5329,-5331,-5331,
+-5329,-5325,-5319,-5310,-5300,-5288,-5274,-5258,-5242,-5225,-5207,-5189,-5171,-5153,-5136,-5120,-5105,-5091,-5078,-5066,-5055,
+-5045,-5035,-5027,-5018,-5010,-5002,-4995,-4988,-4981,-4974,-4967,-4961,-4955,-4950,-4946,-4943,-4941,-4940,-4940,-4941,-4943,
+-4946,-4949,-4953,-4957,-4961,-4964,-4966,-4967,-4967,-4965,-4961,-4956,-4949,-4940,-4929,-4917,-4904,-4890,-4875,-4860,-4845,
+-4831,-4817,-4803,-4791,-4779,-4769,-4758,-4749,-4739,-4730,-4720,-4710,-4699,-4686,-4672,-4656,-4638,-4618,-4596,-4572,-4547,
+-4519,-4490,-4461,-4430,-4399,-4369,-4339,-4310,-4282,-4256,-4231,-4209,-4189,-4172,-4156,-4143,-4132,-4123,-4116,-4110,-4106,
+-4102,-4099,-4097,-4095,-4093,-4090,-4087,-4084,-4080,-4076,-4070,-4065,-4058,-4051,-4044,-4037,-4029,-4022,-4014,-4007,-3999,
+-3992,-3985,-3978,-3971,-3965,-3958,-3951,-3944,-3937,-3929,-3921,-3912,-3903,-3893,-3883,-3872,-3861,-3850,-3839,-3829,-3819,
+-3809,-3800,-3792,-3785,-3779,-3775,-3771,-3769,-3768,-3767,-3768,-3769,-3770,-3771,-3772,-3772,-3772,-3770,-3766,-3761,-3754,
+-3746,-3736,-3724,-3710,-3695,-3679,-3661,-3643,-3624,-3605,-3586,-3567,-3548,-3530,-3512,-3494,-3477,-3460,-3442,-3425,-3408,
+-3390,-3372,-3354,-3336,-3317,-3297,-3278,-3259,-3240,-3222,-3203,-3186,-3169,-3153,-3137,-3121,-3106,-3091,-3075,-3058,-3040,
+-3021,-3001,-2978,-2954,-2928,-2901,-2872,-2842,-2811,-2780,-2750,-2720,-2691,-2663,-2637,-2613,-2591,-2570,-2551,-2534,-2517,
+-2500,-2484,-2467,-2450,-2431,-2411,-2389,-2367,-2342,-2317,-2291,-2265,-2239,-2214,-2189,-2165,-2143,-2123,-2104,-2087,-2071,
+-2056,-2043,-2029,-2016,-2003,-1990,-1976,-1961,-1947,-1932,-1917,-1903,-1890,-1878,-1868,-1861,-1857,-1857,-1859,-1866,-1876,
+-1889,-1906,-1926,-1948,-1973,-1999,-2026,-2055,-2084,-2113,-2142,-2171,-2200,-2228,-2256,-2283,-2309,-2335,-2359,-2382,-2403,
+-2421,-2438,-2451,-2460,-2466,-2467,-2465,-2458,-2446,-2431,-2412,-2391,-2367,-2343,-2318,-2294,-2271,-2250,-2233,-2219,-2209,
+-2203,-2201,-2202,-2207,-2213,-2222,-2230,-2239,-2247,-2252,-2255,-2255,-2252,-2245,-2235,-2221,-2205,-2186,-2166,-2146,-2125,
+-2105,-2086,-2069,-2054,-2042,-2032,-2025,-2021,-2018,-2017,-2017,-2018,-2018,-2018,-2017,-2014,-2010,-2005,-1997,-1988,-1978,
+-1967,-1955,-1942,-1930,-1919,-1908,-1899,-1892,-1886,-1882,-1881,-1881,-1883,-1886,-1891,-1897,-1904,-1911,-1918,-1925,-1932,
+-1938,-1944,-1949,-1953,-1957,-1961,-1963,-1966,-1968,-1970,-1972,-1975,-1977,-1980,-1983,-1986,-1990,-1994,-1998,-2002,-2006,
+-2009,-2013,-2015,-2016,-2016,-2015,-2012,-2006,-1999,-1989,-1977,-1962,-1944,-1924,-1901,-1877,-1850,-1821,-1792,-1761,-1730,
+-1699,-1669,-1640,-1613,-1587,-1564,-1544,-1526,-1512,-1502,-1494,-1490,-1490,-1492,-1497,-1505,-1516,-1528,-1541,-1556,-1572,
+-1588,-1604,-1620,-1635,-1649,-1662,-1673,-1683,-1691,-1697,-1701,-1703,-1703,-1701,-1696,-1691,-1683,-1674,-1665,-1654,-1643,
+-1632,-1622,-1612,-1604,-1597,-1592,-1590,-1590,-1594,-1600,-1609,-1621,-1636,-1653,-1672,-1693,-1714,-1736,-1757,-1778,-1796,
+-1811,-1823,-1831,-1835,-1833,-1827,-1816,-1800,-1780,-1755,-1726,-1695,-1662,-1627,-1591,-1555,-1521,-1487,-1456,-1427,-1401,
+-1378,-1358,-1341,-1327,-1316,-1307,-1300,-1295,-1291,-1289,-1287,-1286,-1286,-1286,-1286,-1287,-1288,-1289,-1291,-1292,-1294,
+-1296,-1298,-1300,-1301,-1302,-1302,-1302,-1300,-1297,-1293,-1287,-1280,-1272,-1263,-1253,-1242,-1231,-1220,-1208,-1197,-1187,
+-1177,-1169,-1161,-1155,-1150,-1145,-1142,-1140,-1138,-1137,-1136,-1135,-1135,-1134,-1132,-1130,-1128,-1125,-1121,-1117,-1111,
+-1105,-1098,-1091,-1083,-1074,-1064,-1054,-1044,-1033,-1021,-1010,-998,-986,-974,-962,-950,-938,-927,-915,-904,-892,
+-881,-869,-858,-846,-833,-820,-807,-794,-780,-766,-752,-738,-725,-712,-700,-688,-678,-670,-662,-656,-652,
+-648,-646,-644,-643,-643,-642,-640,-680,-678,-674,-670,-664,-657,-649,-639,-628,-616,-603,-589,-574,-560,
+-545,-530,-515,-501,-488,-475,-463,-451,-440,-430,-419,-409,-399,-389,-378,-368,-357,-346,-334,-323,-311,
+-299,-287,-275,-264,-253,-242,-232,-222,-213,-204,-195,-187,-178,-170,-162,-154,-146,-138,-129,-120,-111,
+-101,-92,-81,-71,-61,-50,-39,-29,-18,-8,2,12,22,32,41,51,60,69,77,86,94,
+103,111,120,128,137,145,154,164,173,183,193,203,214,225,236,247,259,270,281,292,303,
+314,324,334,343,352,361,369,376,383,389,395,401,405,410,414,417,420,422,423,424,423,
+422,420,416,412,406,400,392,384,375,365,354,344,333,322,311,302,292,284,277,271,266,
+262,260,259,260,262,265,269,274,280,287,294,303,312,322,332,343,355,367,380,394,408,
+422,437,452,467,482,497,511,524,537,548,557,565,571,576,579,580,580,578,576,573,570,
+567,564,562,560,560,560,561,564,567,571,576,581,586,591,595,599,602,604,605,606,607,
+607,608,609,612,616,622,631,642,656,673,693,716,741,768,796,825,854,882,908,932,952,
+969,982,990,993,992,986,976,962,945,926,904,882,860,837,816,797,779,764,751,740,731,
+724,719,714,709,705,699,692,683,673,660,645,627,608,587,565,542,519,497,476,456,438,
+423,411,402,396,393,393,395,399,405,413,420,429,437,444,451,457,462,466,469,471,473,
+475,476,478,480,483,487,491,496,502,508,514,520,526,530,534,536,537,535,532,527,520,
+512,502,491,479,466,453,440,428,416,404,393,383,373,364,356,347,339,330,321,311,301,
+290,277,264,251,236,221,205,188,172,155,138,121,104,88,71,55,38,22,6,-9,-25,
+-42,-58,-74,-91,-108,-125,-142,-160,-177,-196,-214,-234,-254,-275,-298,-321,-347,-374,-402,-433,-465,
+-499,-535,-572,-610,-649,-689,-728,-767,-805,-842,-877,-911,-942,-972,-999,-1025,-1049,-1072,-1093,-1114,-1134,
+-1155,-1176,-1198,-1220,-1244,-1269,-1296,-1324,-1353,-1383,-1414,-1446,-1477,-1509,-1540,-1570,-1600,-1629,-1657,-1684,-1710,
+-1736,-1761,-1785,-1809,-1833,-1857,-1882,-1907,-1932,-1957,-1983,-2009,-2035,-2061,-2087,-2112,-2138,-2162,-2187,-2211,-2234,
+-2258,-2281,-2304,-2328,-2352,-2377,-2402,-2429,-2456,-2485,-2514,-2545,-2576,-2608,-2641,-2673,-2706,-2738,-2770,-2800,-2830,
+-2859,-2886,-2912,-2936,-2960,-2982,-3004,-3024,-3044,-3064,-3084,-3103,-3123,-3143,-3163,-3184,-3205,-3227,-3249,-3271,-3294,
+-3317,-3340,-3364,-3387,-3411,-3435,-3459,-3483,-3508,-3533,-3558,-3584,-3611,-3637,-3664,-3691,-3718,-3745,-3772,-3798,-3823,
+-3847,-3869,-3891,-3910,-3928,-3944,-3959,-3971,-3983,-3993,-4001,-4009,-4017,-4024,-4032,-4040,-4048,-4058,-4068,-4079,-4092,
+-4106,-4121,-4137,-4153,-4171,-4188,-4206,-4224,-4242,-4260,-4277,-4294,-4311,-4327,-4343,-4360,-4376,-4393,-4410,-4428,-4447,
+-4467,-4488,-4511,-4535,-4560,-4586,-4614,-4642,-4671,-4700,-4729,-4758,-4787,-4815,-4841,-4866,-4890,-4912,-4932,-4950,-4966,
+-4981,-4994,-5005,-5015,-5023,-5031,-5037,-5043,-5049,-5053,-5058,-5062,-5066,-5069,-5072,-5075,-5077,-5078,-5078,-5078,-5077,
+-5075,-5071,-5067,-5062,-5056,-5049,-5042,-5035,-5028,-5021,-5014,-5008,-5003,-4999,-4996,-4995,-4995,-4997,-5000,-5004,-5010,
+-5016,-5023,-5030,-5037,-5044,-5050,-5055,-5059,-5062,-5064,-5063,-5062,-5059,-5056,-5052,-5048,-5044,-5042,-5041,-5043,-5048,
+-5056,-5069,-5086,-5107,-5134,-5165,-5201,-5240,-5283,-5328,-5375,-5421,-5468,-5512,-5553,-5589,-5621,-5647,-5666,-5678,-5683,
+-5681,-5672,-5656,-5635,-5609,-5579,-5546,-5512,-5477,-5442,-5408,-5375,-5346,-5318,-5294,-5273,-5255,-5240,-5227,-5216,-5206,
+-5198,-5190,-5183,-5177,-5170,-5163,-5156,-5149,-5142,-5135,-5129,-5124,-5120,-5117,-5114,-5114,-5114,-5115,-5118,-5121,-5124,
+-5128,-5131,-5135,-5138,-5140,-5142,-5143,-5144,-5144,-5145,-5145,-5146,-5147,-5149,-5152,-5156,-5161,-5168,-5175,-5184,-5194,
+-5204,-5215,-5226,-5238,-5249,-5259,-5269,-5278,-5286,-5293,-5300,-5305,-5310,-5314,-5317,-5319,-5322,-5323,-5324,-5325,-5326,
+-5326,-5326,-5325,-5324,-5322,-5321,-5318,-5316,-5313,-5311,-5308,-5306,-5304,-5303,-5302,-5302,-5303,-5304,-5307,-5309,-5312,
+-5316,-5319,-5322,-5325,-5327,-5329,-5329,-5329,-5328,-5327,-5325,-5322,-5319,-5316,-5313,-5310,-5308,-5307,-5306,-5306,-5307,
+-5309,-5312,-5315,-5318,-5322,-5325,-5328,-5330,-5332,-5333,-5332,-5331,-5329,-5326,-5322,-5317,-5311,-5306,-5300,-5294,-5287,
+-5281,-5276,-5270,-5265,-5261,-5256,-5252,-5248,-5245,-5241,-5238,-5235,-5233,-5231,-5230,-5229,-5229,-5230,-5232,-5235,-5239,
+-5244,-5249,-5256,-5263,-5271,-5279,-5286,-5293,-5299,-5304,-5307,-5309,-5308,-5306,-5301,-5294,-5285,-5275,-5262,-5248,-5233,
+-5218,-5202,-5186,-5170,-5155,-5140,-5127,-5115,-5103,-5093,-5084,-5076,-5068,-5061,-5054,-5047,-5040,-5032,-5025,-5016,-5008,
+-4998,-4989,-4979,-4969,-4959,-4950,-4942,-4934,-4927,-4921,-4916,-4913,-4910,-4909,-4908,-4908,-4907,-4907,-4907,-4906,-4904,
+-4901,-4897,-4891,-4884,-4876,-4866,-4856,-4844,-4832,-4820,-4808,-4796,-4784,-4774,-4764,-4755,-4747,-4740,-4733,-4728,-4722,
+-4716,-4710,-4703,-4694,-4684,-4673,-4658,-4642,-4623,-4602,-4578,-4552,-4523,-4494,-4463,-4431,-4398,-4366,-4334,-4304,-4275,
+-4247,-4222,-4199,-4178,-4160,-4144,-4131,-4119,-4110,-4103,-4097,-4093,-4090,-4087,-4085,-4083,-4081,-4079,-4078,-4075,-4073,
+-4070,-4066,-4063,-4059,-4054,-4049,-4044,-4039,-4034,-4028,-4022,-4015,-4009,-4002,-3994,-3987,-3978,-3970,-3961,-3951,-3941,
+-3931,-3921,-3910,-3899,-3888,-3878,-3868,-3858,-3848,-3840,-3832,-3824,-3818,-3813,-3809,-3806,-3803,-3802,-3802,-3802,-3803,
+-3805,-3807,-3809,-3811,-3813,-3814,-3814,-3814,-3813,-3810,-3806,-3801,-3794,-3786,-3776,-3765,-3752,-3737,-3722,-3705,-3688,
+-3670,-3650,-3631,-3611,-3590,-3569,-3548,-3527,-3505,-3484,-3462,-3440,-3418,-3395,-3373,-3351,-3329,-3307,-3285,-3264,-3243,
+-3224,-3204,-3186,-3169,-3152,-3136,-3120,-3104,-3089,-3073,-3056,-3039,-3020,-3000,-2979,-2955,-2931,-2904,-2876,-2848,-2818,
+-2788,-2757,-2727,-2698,-2671,-2644,-2620,-2597,-2576,-2557,-2540,-2524,-2510,-2496,-2483,-2470,-2456,-2441,-2425,-2409,-2390,
+-2371,-2350,-2328,-2306,-2283,-2260,-2238,-2216,-2196,-2177,-2159,-2143,-2130,-2118,-2107,-2098,-2090,-2083,-2077,-2071,-2066,
+-2060,-2053,-2047,-2040,-2032,-2025,-2017,-2009,-2002,-1996,-1991,-1987,-1984,-1984,-1985,-1989,-1996,-2004,-2016,-2030,-2047,
+-2067,-2089,-2113,-2139,-2168,-2197,-2228,-2260,-2291,-2323,-2353,-2382,-2409,-2433,-2454,-2471,-2483,-2492,-2495,-2494,-2489,
+-2479,-2466,-2449,-2429,-2408,-2385,-2363,-2341,-2320,-2302,-2286,-2273,-2263,-2257,-2254,-2253,-2256,-2260,-2265,-2271,-2277,
+-2282,-2286,-2287,-2286,-2283,-2276,-2267,-2255,-2241,-2225,-2207,-2189,-2171,-2153,-2136,-2120,-2106,-2094,-2084,-2076,-2070,
+-2066,-2063,-2062,-2061,-2060,-2060,-2059,-2057,-2054,-2049,-2044,-2037,-2029,-2019,-2010,-1999,-1989,-1979,-1969,-1961,-1953,
+-1948,-1943,-1941,-1940,-1942,-1945,-1949,-1955,-1962,-1970,-1979,-1988,-1997,-2006,-2015,-2023,-2031,-2038,-2045,-2051,-2056,
+-2060,-2063,-2067,-2069,-2072,-2074,-2076,-2078,-2080,-2082,-2084,-2086,-2087,-2089,-2090,-2090,-2089,-2087,-2084,-2079,-2072,
+-2063,-2051,-2037,-2021,-2002,-1980,-1956,-1930,-1902,-1872,-1842,-1811,-1780,-1750,-1720,-1692,-1666,-1642,-1622,-1604,-1589,
+-1578,-1570,-1566,-1565,-1566,-1571,-1578,-1587,-1597,-1609,-1622,-1636,-1650,-1663,-1677,-1689,-1701,-1712,-1722,-1731,-1738,
+-1744,-1748,-1750,-1751,-1750,-1748,-1744,-1738,-1732,-1723,-1714,-1704,-1694,-1683,-1673,-1663,-1654,-1647,-1641,-1638,-1637,
+-1639,-1644,-1652,-1663,-1677,-1694,-1712,-1732,-1754,-1775,-1796,-1816,-1834,-1849,-1860,-1868,-1871,-1870,-1864,-1853,-1837,
+-1817,-1794,-1767,-1738,-1708,-1677,-1645,-1614,-1585,-1558,-1534,-1512,-1493,-1478,-1465,-1456,-1449,-1444,-1441,-1439,-1438,
+-1438,-1437,-1437,-1435,-1433,-1431,-1427,-1423,-1418,-1412,-1406,-1400,-1393,-1387,-1381,-1375,-1369,-1364,-1359,-1353,-1348,
+-1343,-1338,-1332,-1325,-1319,-1311,-1303,-1295,-1286,-1277,-1267,-1257,-1247,-1238,-1229,-1220,-1211,-1204,-1197,-1190,-1185,
+-1180,-1176,-1172,-1168,-1165,-1162,-1159,-1156,-1153,-1149,-1145,-1140,-1135,-1129,-1122,-1114,-1106,-1097,-1088,-1078,-1067,
+-1056,-1045,-1034,-1022,-1010,-999,-987,-976,-965,-955,-944,-934,-923,-913,-902,-892,-881,-869,-858,-845,-833,
+-820,-807,-794,-781,-768,-756,-744,-734,-724,-715,-707,-701,-696,-692,-689,-687,-685,-683,-682,-680,-708,
+-706,-704,-701,-697,-692,-685,-678,-668,-658,-646,-634,-620,-606,-592,-577,-562,-548,-534,-521,-509,-497,
+-485,-475,-465,-455,-446,-437,-428,-419,-409,-400,-390,-380,-370,-359,-348,-336,-325,-314,-303,-292,-281,
+-271,-262,-252,-244,-236,-228,-221,-214,-208,-201,-194,-188,-181,-173,-165,-157,-148,-138,-128,-117,-105,
+-93,-81,-68,-55,-42,-30,-17,-5,7,18,29,40,50,59,68,76,85,92,100,108,115,
+123,131,139,148,157,166,176,187,197,208,220,231,242,254,265,276,287,298,308,318,327,
+336,344,351,358,365,371,376,380,384,387,389,390,390,389,386,383,379,373,366,358,350,
+340,330,319,308,297,287,276,266,257,249,243,237,233,230,228,228,229,231,235,239,245,
+251,258,265,274,282,292,302,312,323,334,346,359,372,385,399,413,426,440,453,465,476,
+487,496,503,510,514,518,519,520,519,517,515,512,510,507,506,505,505,506,508,512,516,
+522,527,534,540,546,551,556,559,562,563,563,562,561,559,558,557,557,559,563,570,579,
+592,608,627,649,673,700,729,758,787,816,843,868,890,908,921,931,936,936,931,923,911,
+896,878,859,839,819,800,782,766,751,739,729,722,716,712,708,706,703,699,695,688,680,
+669,656,640,622,602,581,559,536,513,492,471,453,437,425,415,408,404,404,405,410,416,
+423,431,440,448,456,463,470,475,479,482,484,486,488,490,492,495,500,505,511,519,527,
+537,547,557,567,576,584,590,595,597,596,593,587,578,567,554,538,521,503,485,466,447,
+429,412,395,380,366,353,341,330,320,310,300,290,280,269,258,246,234,220,206,191,176,
+160,143,127,110,94,78,61,46,30,14,0,-16,-31,-47,-63,-79,-95,-112,-130,-148,-166,
+-186,-206,-228,-250,-273,-297,-323,-349,-377,-406,-436,-467,-499,-532,-566,-601,-636,-671,-707,-742,-777,
+-811,-844,-877,-908,-939,-968,-996,-1022,-1048,-1073,-1097,-1121,-1144,-1167,-1191,-1215,-1239,-1263,-1289,-1315,-1341,
+-1368,-1395,-1423,-1450,-1478,-1506,-1533,-1560,-1587,-1614,-1640,-1666,-1692,-1718,-1743,-1768,-1794,-1819,-1845,-1871,-1897,
+-1922,-1948,-1974,-2000,-2026,-2051,-2076,-2101,-2125,-2149,-2173,-2197,-2220,-2244,-2268,-2293,-2318,-2344,-2371,-2399,-2428,
+-2458,-2489,-2521,-2553,-2586,-2619,-2651,-2684,-2716,-2747,-2776,-2805,-2832,-2858,-2883,-2906,-2928,-2950,-2970,-2990,-3009,
+-3028,-3047,-3066,-3085,-3104,-3124,-3144,-3165,-3186,-3207,-3228,-3250,-3271,-3292,-3313,-3334,-3354,-3375,-3396,-3417,-3438,
+-3459,-3481,-3504,-3527,-3551,-3576,-3602,-3629,-3656,-3683,-3710,-3737,-3764,-3790,-3815,-3838,-3860,-3880,-3898,-3915,-3929,
+-3941,-3952,-3962,-3970,-3978,-3984,-3991,-3998,-4006,-4014,-4023,-4033,-4045,-4058,-4072,-4088,-4105,-4123,-4141,-4161,-4180,
+-4200,-4219,-4239,-4258,-4276,-4294,-4312,-4329,-4346,-4362,-4379,-4396,-4413,-4431,-4449,-4469,-4489,-4511,-4534,-4558,-4583,
+-4609,-4636,-4663,-4691,-4718,-4746,-4773,-4799,-4824,-4847,-4869,-4889,-4908,-4924,-4938,-4950,-4960,-4969,-4975,-4980,-4984,
+-4986,-4988,-4989,-4989,-4989,-4989,-4989,-4990,-4990,-4990,-4991,-4992,-4993,-4994,-4995,-4996,-4996,-4997,-4997,-4997,-4997,
+-4997,-4996,-4995,-4995,-4995,-4995,-4995,-4997,-4999,-5002,-5007,-5012,-5018,-5025,-5033,-5041,-5050,-5058,-5067,-5074,-5081,
+-5086,-5090,-5093,-5093,-5092,-5089,-5085,-5080,-5074,-5068,-5063,-5058,-5055,-5054,-5055,-5060,-5068,-5080,-5096,-5116,-5140,
+-5167,-5196,-5228,-5261,-5295,-5329,-5361,-5391,-5418,-5441,-5460,-5473,-5482,-5485,-5483,-5476,-5464,-5448,-5429,-5407,-5382,
+-5357,-5331,-5305,-5281,-5257,-5235,-5216,-5198,-5183,-5170,-5159,-5149,-5141,-5135,-5129,-5124,-5119,-5115,-5110,-5106,-5102,
+-5098,-5094,-5091,-5088,-5086,-5085,-5084,-5084,-5085,-5087,-5089,-5093,-5096,-5100,-5105,-5109,-5113,-5117,-5121,-5124,-5127,
+-5130,-5133,-5135,-5138,-5140,-5143,-5147,-5151,-5155,-5161,-5166,-5173,-5179,-5186,-5194,-5201,-5209,-5216,-5223,-5230,-5236,
+-5241,-5246,-5251,-5254,-5258,-5260,-5263,-5264,-5266,-5267,-5268,-5268,-5269,-5269,-5269,-5269,-5268,-5268,-5267,-5266,-5265,
+-5264,-5263,-5263,-5262,-5261,-5261,-5261,-5262,-5262,-5263,-5265,-5266,-5267,-5269,-5270,-5271,-5272,-5272,-5272,-5271,-5269,
+-5267,-5265,-5263,-5260,-5257,-5254,-5251,-5249,-5247,-5245,-5245,-5245,-5245,-5246,-5248,-5250,-5253,-5255,-5258,-5261,-5263,
+-5266,-5268,-5269,-5270,-5271,-5271,-5271,-5270,-5270,-5269,-5267,-5266,-5264,-5263,-5261,-5259,-5257,-5255,-5253,-5250,-5247,
+-5244,-5241,-5238,-5234,-5231,-5227,-5224,-5221,-5219,-5218,-5217,-5217,-5218,-5220,-5223,-5226,-5231,-5235,-5240,-5245,-5250,
+-5254,-5258,-5260,-5261,-5261,-5259,-5256,-5252,-5246,-5239,-5230,-5221,-5211,-5202,-5192,-5182,-5172,-5164,-5156,-5148,-5142,
+-5136,-5131,-5126,-5121,-5117,-5112,-5106,-5100,-5093,-5085,-5076,-5066,-5055,-5042,-5029,-5015,-5001,-4986,-4972,-4958,-4945,
+-4933,-4922,-4911,-4902,-4894,-4887,-4882,-4876,-4871,-4867,-4862,-4857,-4852,-4846,-4839,-4831,-4822,-4812,-4801,-4790,-4778,
+-4766,-4753,-4741,-4730,-4719,-4709,-4701,-4693,-4686,-4680,-4675,-4670,-4665,-4660,-4655,-4648,-4641,-4631,-4620,-4607,-4591,
+-4572,-4552,-4529,-4504,-4477,-4448,-4419,-4389,-4359,-4329,-4300,-4272,-4245,-4220,-4198,-4177,-4159,-4143,-4130,-4118,-4109,
+-4101,-4095,-4090,-4086,-4083,-4080,-4078,-4076,-4074,-4072,-4070,-4068,-4065,-4062,-4059,-4056,-4053,-4049,-4045,-4041,-4037,
+-4032,-4027,-4021,-4014,-4007,-3999,-3990,-3981,-3971,-3959,-3948,-3935,-3923,-3910,-3897,-3884,-3871,-3860,-3848,-3838,-3829,
+-3821,-3815,-3810,-3806,-3804,-3803,-3803,-3805,-3807,-3811,-3814,-3819,-3823,-3827,-3831,-3835,-3838,-3841,-3842,-3843,-3842,
+-3840,-3837,-3833,-3827,-3820,-3811,-3802,-3791,-3779,-3765,-3750,-3734,-3718,-3700,-3681,-3661,-3640,-3618,-3596,-3572,-3549,
+-3524,-3499,-3474,-3449,-3423,-3397,-3372,-3347,-3322,-3297,-3274,-3251,-3229,-3209,-3188,-3169,-3151,-3133,-3115,-3098,-3081,
+-3063,-3045,-3027,-3007,-2986,-2964,-2941,-2917,-2891,-2864,-2837,-2809,-2780,-2752,-2725,-2698,-2672,-2648,-2626,-2605,-2587,
+-2570,-2555,-2541,-2529,-2518,-2508,-2498,-2488,-2477,-2466,-2454,-2440,-2426,-2411,-2394,-2377,-2360,-2342,-2325,-2308,-2293,
+-2279,-2267,-2257,-2249,-2243,-2240,-2239,-2239,-2242,-2245,-2250,-2255,-2260,-2264,-2268,-2271,-2273,-2273,-2272,-2269,-2265,
+-2259,-2252,-2245,-2237,-2229,-2222,-2215,-2209,-2205,-2203,-2202,-2204,-2208,-2215,-2224,-2236,-2250,-2266,-2284,-2303,-2324,
+-2345,-2366,-2388,-2408,-2427,-2444,-2460,-2473,-2483,-2490,-2494,-2495,-2494,-2489,-2482,-2472,-2461,-2449,-2435,-2421,-2408,
+-2394,-2382,-2371,-2361,-2353,-2346,-2341,-2337,-2335,-2333,-2332,-2331,-2330,-2329,-2326,-2323,-2318,-2311,-2303,-2294,-2283,
+-2270,-2257,-2243,-2228,-2214,-2199,-2185,-2172,-2160,-2148,-2138,-2130,-2122,-2116,-2111,-2107,-2103,-2100,-2097,-2094,-2091,
+-2088,-2085,-2080,-2076,-2071,-2065,-2060,-2054,-2048,-2042,-2037,-2032,-2029,-2026,-2024,-2023,-2024,-2027,-2030,-2035,-2041,
+-2048,-2057,-2066,-2076,-2086,-2096,-2107,-2117,-2127,-2136,-2145,-2152,-2159,-2165,-2169,-2173,-2176,-2178,-2179,-2179,-2179,
+-2178,-2177,-2176,-2175,-2173,-2172,-2170,-2168,-2165,-2162,-2157,-2152,-2146,-2138,-2129,-2117,-2104,-2088,-2071,-2051,-2030,
+-2007,-1982,-1957,-1930,-1904,-1878,-1852,-1827,-1804,-1783,-1764,-1747,-1733,-1722,-1714,-1708,-1705,-1705,-1706,-1710,-1715,
+-1721,-1728,-1736,-1744,-1752,-1760,-1767,-1774,-1780,-1786,-1791,-1794,-1797,-1799,-1800,-1800,-1799,-1797,-1794,-1789,-1784,
+-1778,-1772,-1764,-1756,-1747,-1738,-1730,-1721,-1714,-1707,-1702,-1699,-1697,-1698,-1702,-1708,-1716,-1727,-1740,-1755,-1772,
+-1789,-1806,-1823,-1838,-1852,-1864,-1872,-1876,-1877,-1873,-1865,-1853,-1836,-1816,-1793,-1766,-1738,-1709,-1679,-1650,-1622,
+-1595,-1571,-1550,-1532,-1517,-1506,-1498,-1493,-1491,-1491,-1492,-1495,-1498,-1502,-1505,-1507,-1508,-1507,-1504,-1500,-1494,
+-1486,-1477,-1466,-1454,-1442,-1429,-1416,-1403,-1391,-1379,-1368,-1357,-1348,-1339,-1331,-1323,-1316,-1308,-1302,-1295,-1288,
+-1280,-1273,-1265,-1256,-1248,-1239,-1229,-1220,-1211,-1202,-1193,-1184,-1175,-1167,-1160,-1153,-1147,-1141,-1135,-1130,-1125,
+-1120,-1115,-1110,-1105,-1099,-1093,-1086,-1079,-1072,-1063,-1054,-1045,-1035,-1025,-1015,-1005,-995,-985,-975,-966,-957,
+-948,-940,-932,-924,-917,-910,-903,-895,-887,-879,-871,-861,-852,-841,-830,-819,-808,-796,-785,-774,-764,
+-754,-745,-737,-730,-725,-720,-717,-714,-712,-710,-709,-708,-742,-741,-740,-738,-736,-733,-728,-722,-716,
+-707,-698,-687,-676,-663,-650,-636,-623,-609,-596,-583,-570,-559,-548,-537,-528,-519,-510,-502,-494,-486,
+-478,-470,-462,-453,-444,-434,-425,-414,-404,-393,-382,-371,-361,-351,-341,-332,-323,-315,-308,-301,-295,
+-289,-283,-278,-272,-267,-261,-254,-247,-239,-229,-220,-209,-197,-184,-171,-157,-142,-127,-112,-97,-83,
+-68,-54,-41,-29,-17,-6,3,12,21,29,37,45,52,59,67,75,83,92,101,111,121,
+133,144,156,169,182,195,208,221,234,247,259,271,283,294,304,314,323,331,338,345,350,
+355,359,361,362,362,361,359,355,349,343,335,327,317,306,295,284,272,260,249,238,228,
+218,210,203,198,194,191,190,190,192,194,198,203,209,216,223,231,240,249,258,267,277,
+288,298,309,320,332,343,355,366,378,389,399,409,418,427,434,440,445,449,452,453,454,
+455,454,454,453,453,453,454,456,459,462,467,472,478,484,490,496,502,507,511,514,515,
+516,515,512,509,506,502,498,496,494,495,498,504,513,525,541,560,582,608,635,664,695,
+725,756,784,811,835,855,872,884,892,895,894,889,881,870,856,841,824,808,792,776,762,
+750,739,730,722,716,711,707,703,698,692,685,676,665,652,637,620,600,580,558,535,513,
+491,470,452,435,421,410,402,397,395,396,399,405,411,419,428,437,445,453,460,466,471,
+476,479,482,485,488,492,496,501,508,516,526,536,548,561,574,588,600,612,622,630,636,
+639,638,634,627,617,603,586,567,546,524,500,476,452,429,406,385,365,347,330,315,301,
+289,278,267,257,247,238,227,217,205,193,181,167,153,138,123,107,91,76,60,44,28,
+13,-2,-17,-32,-47,-63,-78,-95,-111,-129,-147,-166,-187,-208,-231,-254,-279,-305,-333,-361,-390,
+-419,-450,-481,-513,-545,-577,-609,-642,-674,-706,-738,-770,-801,-831,-862,-891,-921,-949,-978,-1005,-1033,
+-1060,-1086,-1113,-1139,-1165,-1191,-1217,-1242,-1268,-1294,-1319,-1345,-1370,-1395,-1420,-1445,-1470,-1494,-1519,-1543,-1568,
+-1592,-1616,-1640,-1664,-1689,-1714,-1739,-1764,-1789,-1814,-1840,-1866,-1892,-1917,-1943,-1968,-1994,-2018,-2043,-2068,-2092,
+-2116,-2140,-2164,-2189,-2213,-2239,-2265,-2292,-2320,-2349,-2379,-2410,-2442,-2475,-2508,-2542,-2576,-2610,-2644,-2677,-2709,
+-2740,-2770,-2798,-2825,-2850,-2874,-2897,-2918,-2938,-2958,-2977,-2996,-3014,-3032,-3051,-3070,-3089,-3109,-3128,-3149,-3169,
+-3189,-3209,-3229,-3249,-3268,-3286,-3304,-3322,-3338,-3355,-3371,-3387,-3404,-3421,-3438,-3457,-3476,-3497,-3519,-3542,-3566,
+-3592,-3618,-3646,-3673,-3701,-3728,-3754,-3780,-3804,-3827,-3848,-3867,-3884,-3899,-3912,-3924,-3933,-3942,-3950,-3957,-3964,
+-3971,-3978,-3987,-3996,-4007,-4019,-4033,-4048,-4064,-4082,-4100,-4120,-4140,-4160,-4181,-4201,-4221,-4240,-4259,-4277,-4295,
+-4312,-4328,-4344,-4360,-4376,-4392,-4408,-4426,-4444,-4463,-4484,-4505,-4528,-4553,-4578,-4604,-4631,-4658,-4685,-4712,-4739,
+-4764,-4788,-4810,-4831,-4849,-4865,-4878,-4889,-4897,-4904,-4908,-4910,-4910,-4910,-4908,-4906,-4903,-4901,-4899,-4898,-4898,
+-4899,-4901,-4904,-4908,-4913,-4919,-4926,-4933,-4940,-4948,-4955,-4962,-4968,-4974,-4979,-4983,-4987,-4991,-4994,-4997,-5001,
+-5005,-5009,-5014,-5021,-5028,-5036,-5045,-5055,-5066,-5077,-5087,-5098,-5107,-5115,-5122,-5127,-5129,-5129,-5126,-5120,-5112,
+-5102,-5090,-5077,-5062,-5048,-5034,-5021,-5010,-5002,-4996,-4994,-4996,-5001,-5011,-5024,-5040,-5060,-5082,-5106,-5131,-5156,
+-5180,-5203,-5224,-5242,-5257,-5268,-5276,-5280,-5279,-5275,-5268,-5258,-5245,-5230,-5214,-5197,-5180,-5164,-5148,-5133,-5119,
+-5107,-5097,-5088,-5081,-5076,-5072,-5068,-5066,-5065,-5063,-5063,-5062,-5061,-5061,-5060,-5059,-5059,-5058,-5058,-5058,-5058,
+-5059,-5060,-5062,-5064,-5066,-5069,-5073,-5077,-5082,-5086,-5091,-5096,-5101,-5106,-5111,-5116,-5121,-5126,-5131,-5135,-5140,
+-5144,-5148,-5152,-5156,-5160,-5163,-5166,-5169,-5172,-5174,-5176,-5178,-5180,-5181,-5183,-5184,-5186,-5187,-5189,-5190,-5192,
+-5194,-5196,-5198,-5200,-5203,-5205,-5208,-5210,-5213,-5215,-5218,-5220,-5222,-5224,-5226,-5227,-5228,-5230,-5230,-5231,-5232,
+-5232,-5232,-5232,-5232,-5231,-5230,-5229,-5227,-5225,-5222,-5219,-5216,-5212,-5208,-5204,-5200,-5196,-5192,-5188,-5184,-5181,
+-5178,-5175,-5173,-5172,-5171,-5171,-5172,-5173,-5174,-5175,-5177,-5179,-5181,-5183,-5186,-5188,-5190,-5192,-5195,-5197,-5200,
+-5202,-5205,-5208,-5211,-5213,-5216,-5219,-5222,-5224,-5227,-5228,-5230,-5231,-5231,-5231,-5230,-5229,-5227,-5225,-5222,-5219,
+-5216,-5214,-5211,-5209,-5207,-5205,-5204,-5204,-5204,-5204,-5205,-5206,-5207,-5207,-5208,-5209,-5209,-5209,-5208,-5206,-5204,
+-5202,-5199,-5197,-5193,-5190,-5187,-5184,-5182,-5179,-5177,-5176,-5174,-5173,-5172,-5171,-5169,-5166,-5163,-5159,-5154,-5147,
+-5139,-5129,-5117,-5104,-5090,-5074,-5057,-5039,-5021,-5002,-4984,-4965,-4948,-4931,-4915,-4900,-4887,-4875,-4864,-4854,-4844,
+-4836,-4828,-4821,-4813,-4805,-4797,-4789,-4779,-4770,-4759,-4748,-4737,-4725,-4713,-4702,-4690,-4679,-4669,-4659,-4650,-4642,
+-4634,-4628,-4622,-4616,-4610,-4603,-4597,-4589,-4580,-4570,-4558,-4544,-4529,-4511,-4491,-4470,-4447,-4422,-4397,-4371,-4344,
+-4318,-4292,-4267,-4243,-4220,-4199,-4180,-4163,-4148,-4134,-4123,-4113,-4105,-4098,-4092,-4087,-4083,-4079,-4076,-4072,-4069,
+-4066,-4062,-4059,-4055,-4051,-4047,-4043,-4039,-4035,-4030,-4026,-4021,-4016,-4011,-4005,-3999,-3992,-3984,-3976,-3967,-3957,
+-3947,-3936,-3924,-3912,-3900,-3887,-3875,-3863,-3851,-3841,-3831,-3823,-3816,-3811,-3807,-3804,-3804,-3804,-3806,-3809,-3813,
+-3818,-3824,-3830,-3836,-3841,-3847,-3852,-3856,-3860,-3862,-3863,-3864,-3863,-3860,-3857,-3852,-3846,-3839,-3830,-3820,-3809,
+-3797,-3783,-3768,-3752,-3734,-3715,-3695,-3674,-3651,-3628,-3603,-3578,-3552,-3525,-3498,-3471,-3443,-3416,-3389,-3363,-3338,
+-3313,-3289,-3266,-3244,-3223,-3203,-3184,-3165,-3147,-3129,-3111,-3093,-3074,-3054,-3034,-3012,-2990,-2966,-2941,-2915,-2888,
+-2860,-2832,-2803,-2775,-2747,-2720,-2695,-2671,-2648,-2628,-2609,-2593,-2578,-2566,-2555,-2546,-2538,-2530,-2523,-2517,-2510,
+-2502,-2494,-2486,-2476,-2466,-2455,-2443,-2431,-2420,-2409,-2399,-2390,-2383,-2378,-2376,-2375,-2378,-2383,-2391,-2401,-2413,
+-2426,-2441,-2457,-2472,-2488,-2503,-2516,-2528,-2538,-2546,-2551,-2553,-2553,-2551,-2546,-2539,-2531,-2521,-2511,-2499,-2488,
+-2476,-2466,-2456,-2447,-2439,-2433,-2429,-2426,-2425,-2425,-2427,-2431,-2435,-2441,-2447,-2454,-2461,-2468,-2475,-2481,-2487,
+-2493,-2497,-2500,-2503,-2504,-2504,-2504,-2502,-2499,-2495,-2490,-2485,-2479,-2473,-2466,-2460,-2453,-2446,-2438,-2431,-2424,
+-2417,-2410,-2403,-2396,-2389,-2382,-2374,-2366,-2357,-2349,-2339,-2330,-2319,-2309,-2297,-2286,-2274,-2262,-2250,-2238,-2226,
+-2214,-2202,-2191,-2181,-2171,-2161,-2153,-2145,-2138,-2132,-2126,-2122,-2118,-2115,-2113,-2112,-2110,-2110,-2110,-2110,-2111,
+-2112,-2113,-2114,-2116,-2117,-2120,-2122,-2125,-2128,-2132,-2136,-2141,-2147,-2153,-2160,-2168,-2176,-2185,-2194,-2203,-2212,
+-2222,-2230,-2239,-2246,-2253,-2259,-2264,-2268,-2271,-2272,-2273,-2272,-2271,-2269,-2267,-2264,-2261,-2258,-2255,-2253,-2250,
+-2248,-2245,-2243,-2240,-2238,-2234,-2230,-2224,-2218,-2209,-2200,-2188,-2175,-2160,-2143,-2125,-2106,-2085,-2064,-2043,-2021,
+-2000,-1980,-1961,-1943,-1926,-1911,-1898,-1888,-1878,-1871,-1865,-1861,-1858,-1856,-1855,-1855,-1855,-1855,-1855,-1855,-1855,
+-1855,-1855,-1854,-1853,-1851,-1849,-1847,-1844,-1841,-1838,-1834,-1830,-1826,-1821,-1816,-1810,-1805,-1799,-1793,-1787,-1782,
+-1777,-1773,-1769,-1768,-1767,-1768,-1771,-1776,-1782,-1791,-1800,-1811,-1823,-1835,-1847,-1858,-1868,-1877,-1882,-1885,-1885,
+-1881,-1873,-1862,-1846,-1827,-1804,-1778,-1750,-1720,-1689,-1658,-1627,-1598,-1570,-1544,-1522,-1503,-1487,-1475,-1466,-1461,
+-1458,-1459,-1461,-1465,-1470,-1475,-1480,-1485,-1488,-1489,-1489,-1486,-1482,-1475,-1466,-1456,-1444,-1430,-1416,-1401,-1386,
+-1371,-1357,-1343,-1330,-1317,-1306,-1296,-1287,-1279,-1271,-1264,-1257,-1251,-1244,-1238,-1231,-1224,-1216,-1208,-1199,-1190,
+-1181,-1172,-1162,-1153,-1144,-1135,-1127,-1119,-1112,-1105,-1099,-1094,-1089,-1085,-1081,-1077,-1073,-1069,-1065,-1060,-1055,
+-1050,-1044,-1038,-1031,-1024,-1017,-1009,-1001,-993,-986,-978,-971,-964,-958,-952,-947,-941,-936,-931,-926,-921,
+-916,-910,-903,-896,-888,-879,-870,-860,-849,-838,-827,-816,-806,-795,-786,-777,-769,-762,-757,-752,-749,
+-746,-744,-743,-742,-789,-788,-786,-785,-783,-781,-778,-774,-769,-763,-756,-747,-738,-727,-716,-705,-692,
+-680,-668,-656,-644,-633,-622,-612,-603,-594,-586,-578,-570,-563,-556,-549,-541,-534,-526,-518,-509,-500,
+-491,-481,-471,-461,-451,-442,-432,-423,-415,-407,-399,-392,-385,-379,-373,-367,-361,-355,-349,-342,-335,
+-327,-319,-309,-298,-287,-275,-262,-248,-234,-219,-204,-189,-174,-160,-145,-132,-119,-106,-94,-83,-72,
+-62,-52,-43,-34,-25,-16,-6,3,13,23,35,47,59,72,86,100,114,130,145,160,175,
+190,205,220,234,247,260,272,284,294,304,312,320,326,331,335,338,339,338,336,333,328,
+322,315,306,296,285,274,262,249,237,225,213,202,192,182,174,168,163,159,157,156,157,
+159,163,167,173,180,187,195,203,212,221,230,239,249,258,268,277,286,296,305,314,322,
+331,339,346,353,360,365,370,375,378,381,383,385,387,388,389,390,392,394,397,400,404,
+409,414,420,426,433,439,446,451,456,460,463,465,465,464,462,459,455,451,446,443,440,
+439,440,443,449,459,472,488,507,530,555,582,612,642,673,703,732,760,784,806,824,839,
+849,856,858,857,852,844,834,823,809,795,781,767,754,742,730,720,711,702,694,687,679,
+671,662,652,640,627,613,596,578,559,539,519,498,478,458,440,424,410,398,389,383,379,
+378,380,383,389,395,403,411,419,427,434,441,447,453,457,462,466,470,475,480,486,493,
+501,511,522,534,547,560,574,587,600,611,621,629,633,635,634,629,621,609,594,576,556,
+533,509,484,458,432,407,383,360,338,318,300,283,268,255,243,231,221,211,201,191,180,
+170,158,146,133,119,105,91,76,60,45,30,14,0,-15,-30,-45,-60,-75,-90,-106,-123,
+-140,-158,-178,-198,-220,-244,-268,-294,-322,-350,-379,-410,-441,-472,-504,-536,-568,-600,-631,-662,-693,
+-723,-752,-781,-810,-838,-865,-892,-919,-946,-973,-1000,-1027,-1053,-1080,-1107,-1134,-1161,-1189,-1216,-1242,-1269,
+-1295,-1321,-1346,-1371,-1396,-1420,-1443,-1466,-1488,-1511,-1533,-1555,-1577,-1599,-1621,-1643,-1666,-1689,-1713,-1737,-1761,
+-1786,-1812,-1837,-1862,-1888,-1914,-1939,-1964,-1989,-2014,-2038,-2063,-2087,-2111,-2135,-2160,-2185,-2211,-2237,-2264,-2293,
+-2322,-2352,-2383,-2416,-2449,-2482,-2516,-2550,-2584,-2618,-2651,-2683,-2714,-2744,-2773,-2800,-2825,-2850,-2873,-2894,-2915,
+-2935,-2954,-2973,-2991,-3010,-3029,-3048,-3067,-3086,-3106,-3126,-3146,-3166,-3186,-3206,-3224,-3243,-3260,-3276,-3292,-3307,
+-3321,-3335,-3348,-3361,-3374,-3387,-3402,-3417,-3433,-3451,-3470,-3491,-3514,-3538,-3563,-3590,-3617,-3645,-3674,-3702,-3729,
+-3756,-3781,-3804,-3826,-3846,-3864,-3880,-3894,-3906,-3917,-3926,-3934,-3942,-3949,-3956,-3964,-3972,-3981,-3991,-4002,-4015,
+-4028,-4043,-4059,-4076,-4094,-4112,-4131,-4150,-4168,-4187,-4205,-4223,-4241,-4258,-4275,-4292,-4308,-4325,-4342,-4360,-4378,
+-4397,-4417,-4439,-4461,-4485,-4509,-4534,-4560,-4587,-4613,-4640,-4665,-4690,-4713,-4735,-4755,-4772,-4787,-4800,-4809,-4817,
+-4822,-4824,-4825,-4824,-4822,-4819,-4815,-4812,-4809,-4807,-4806,-4806,-4808,-4811,-4816,-4823,-4831,-4840,-4851,-4862,-4873,
+-4884,-4896,-4906,-4916,-4925,-4933,-4939,-4945,-4950,-4954,-4958,-4961,-4965,-4969,-4974,-4980,-4988,-4996,-5007,-5018,-5031,
+-5045,-5059,-5073,-5087,-5100,-5112,-5121,-5128,-5132,-5132,-5129,-5122,-5111,-5097,-5079,-5058,-5036,-5011,-4986,-4962,-4938,
+-4916,-4896,-4880,-4868,-4860,-4857,-4858,-4864,-4875,-4889,-4907,-4928,-4952,-4976,-5001,-5026,-5049,-5071,-5090,-5107,-5120,
+-5129,-5135,-5138,-5137,-5133,-5127,-5118,-5108,-5097,-5085,-5073,-5062,-5051,-5042,-5033,-5027,-5021,-5018,-5015,-5014,-5014,
+-5015,-5016,-5018,-5019,-5021,-5023,-5024,-5025,-5025,-5025,-5024,-5023,-5022,-5022,-5021,-5020,-5020,-5021,-5022,-5024,-5027,
+-5030,-5034,-5039,-5044,-5050,-5057,-5063,-5070,-5077,-5083,-5089,-5095,-5100,-5105,-5108,-5111,-5113,-5115,-5116,-5116,-5115,
+-5115,-5113,-5112,-5111,-5110,-5109,-5108,-5108,-5108,-5109,-5110,-5112,-5115,-5118,-5122,-5126,-5131,-5136,-5141,-5146,-5152,
+-5157,-5162,-5167,-5171,-5175,-5179,-5183,-5186,-5188,-5190,-5192,-5193,-5194,-5195,-5195,-5194,-5193,-5192,-5191,-5188,-5186,
+-5183,-5180,-5176,-5172,-5167,-5162,-5157,-5152,-5147,-5142,-5137,-5132,-5127,-5123,-5119,-5116,-5113,-5110,-5108,-5107,-5106,
+-5105,-5105,-5105,-5106,-5107,-5108,-5110,-5112,-5114,-5117,-5119,-5123,-5126,-5130,-5134,-5139,-5143,-5148,-5153,-5158,-5163,
+-5168,-5173,-5178,-5182,-5185,-5188,-5190,-5192,-5193,-5194,-5193,-5193,-5191,-5189,-5187,-5185,-5182,-5179,-5176,-5174,-5171,
+-5168,-5166,-5164,-5162,-5161,-5159,-5158,-5157,-5155,-5155,-5154,-5153,-5152,-5152,-5151,-5151,-5151,-5151,-5152,-5152,-5153,
+-5154,-5156,-5157,-5158,-5158,-5158,-5158,-5157,-5155,-5151,-5146,-5140,-5132,-5123,-5112,-5099,-5085,-5069,-5052,-5034,-5015,
+-4996,-4976,-4957,-4938,-4919,-4901,-4884,-4868,-4853,-4839,-4826,-4814,-4804,-4794,-4784,-4775,-4767,-4758,-4750,-4741,-4732,
+-4723,-4714,-4704,-4695,-4685,-4675,-4666,-4656,-4647,-4639,-4630,-4623,-4616,-4609,-4602,-4595,-4589,-4582,-4574,-4566,-4557,
+-4547,-4535,-4522,-4507,-4490,-4472,-4453,-4432,-4409,-4386,-4362,-4338,-4314,-4290,-4267,-4244,-4223,-4203,-4184,-4167,-4152,
+-4139,-4127,-4116,-4107,-4100,-4093,-4087,-4082,-4077,-4072,-4068,-4063,-4059,-4054,-4050,-4045,-4040,-4035,-4029,-4024,-4019,
+-4013,-4008,-4003,-3997,-3992,-3986,-3980,-3974,-3968,-3961,-3954,-3946,-3938,-3929,-3920,-3910,-3900,-3890,-3880,-3870,-3861,
+-3852,-3843,-3836,-3829,-3824,-3819,-3816,-3814,-3813,-3813,-3814,-3817,-3819,-3822,-3826,-3830,-3834,-3837,-3841,-3844,-3846,
+-3848,-3849,-3849,-3848,-3846,-3843,-3840,-3835,-3829,-3822,-3813,-3804,-3793,-3781,-3767,-3752,-3735,-3717,-3697,-3677,-3654,
+-3631,-3606,-3580,-3554,-3527,-3499,-3472,-3445,-3418,-3392,-3366,-3342,-3319,-3297,-3276,-3257,-3238,-3221,-3204,-3188,-3172,
+-3156,-3140,-3124,-3106,-3088,-3068,-3047,-3024,-2999,-2974,-2947,-2919,-2890,-2860,-2831,-2801,-2773,-2745,-2719,-2694,-2671,
+-2651,-2632,-2616,-2603,-2591,-2581,-2573,-2567,-2561,-2556,-2552,-2547,-2543,-2538,-2532,-2526,-2519,-2511,-2503,-2495,-2486,
+-2479,-2472,-2466,-2463,-2461,-2461,-2463,-2469,-2477,-2487,-2500,-2515,-2532,-2551,-2570,-2590,-2611,-2630,-2649,-2666,-2682,
+-2695,-2706,-2715,-2720,-2723,-2723,-2721,-2716,-2710,-2701,-2691,-2680,-2668,-2655,-2642,-2629,-2617,-2605,-2593,-2583,-2573,
+-2564,-2556,-2550,-2544,-2539,-2535,-2533,-2531,-2530,-2530,-2530,-2531,-2533,-2535,-2538,-2541,-2543,-2546,-2549,-2551,-2553,
+-2554,-2555,-2554,-2553,-2551,-2547,-2543,-2537,-2531,-2523,-2515,-2506,-2496,-2486,-2476,-2466,-2455,-2445,-2435,-2425,-2415,
+-2406,-2397,-2389,-2380,-2371,-2363,-2354,-2344,-2335,-2324,-2313,-2302,-2290,-2278,-2265,-2252,-2239,-2226,-2213,-2201,-2189,
+-2179,-2170,-2162,-2156,-2151,-2148,-2147,-2147,-2149,-2152,-2156,-2161,-2167,-2173,-2179,-2186,-2193,-2199,-2205,-2211,-2217,
+-2222,-2227,-2231,-2236,-2241,-2246,-2251,-2256,-2262,-2268,-2275,-2282,-2290,-2297,-2305,-2312,-2319,-2326,-2332,-2337,-2341,
+-2344,-2347,-2348,-2348,-2348,-2346,-2344,-2342,-2340,-2337,-2335,-2333,-2332,-2331,-2330,-2330,-2330,-2330,-2330,-2330,-2329,
+-2327,-2325,-2321,-2316,-2309,-2300,-2289,-2277,-2263,-2247,-2230,-2212,-2193,-2174,-2154,-2135,-2115,-2097,-2079,-2062,-2046,
+-2032,-2019,-2007,-1997,-1987,-1978,-1971,-1964,-1957,-1951,-1945,-1939,-1934,-1928,-1923,-1917,-1912,-1906,-1901,-1895,-1890,
+-1885,-1880,-1875,-1871,-1866,-1862,-1858,-1854,-1851,-1847,-1844,-1841,-1838,-1836,-1834,-1833,-1833,-1834,-1835,-1837,-1841,
+-1845,-1850,-1855,-1861,-1867,-1873,-1879,-1883,-1887,-1888,-1888,-1885,-1879,-1871,-1859,-1844,-1826,-1805,-1782,-1755,-1728,
+-1698,-1668,-1638,-1608,-1579,-1552,-1526,-1504,-1484,-1467,-1454,-1444,-1437,-1432,-1431,-1431,-1434,-1437,-1441,-1446,-1450,
+-1453,-1455,-1455,-1454,-1451,-1446,-1439,-1430,-1419,-1408,-1395,-1381,-1367,-1353,-1340,-1326,-1313,-1302,-1291,-1281,-1272,
+-1264,-1256,-1250,-1244,-1238,-1232,-1226,-1220,-1214,-1207,-1200,-1192,-1184,-1176,-1167,-1158,-1150,-1141,-1133,-1125,-1118,
+-1111,-1105,-1100,-1096,-1093,-1090,-1088,-1087,-1085,-1084,-1083,-1082,-1080,-1078,-1075,-1072,-1069,-1064,-1060,-1055,-1049,
+-1043,-1037,-1031,-1026,-1020,-1014,-1009,-1004,-999,-994,-989,-984,-979,-974,-968,-962,-955,-947,-939,-930,-920,
+-909,-899,-887,-876,-865,-854,-844,-834,-825,-817,-810,-804,-799,-796,-793,-791,-789,-853,-850,-848,-845,
+-843,-840,-836,-832,-828,-822,-816,-808,-800,-791,-782,-771,-760,-749,-738,-727,-716,-705,-694,-684,-675,
+-666,-657,-650,-642,-635,-629,-622,-616,-610,-603,-597,-590,-584,-577,-569,-562,-554,-547,-539,-531,-524,
+-516,-509,-501,-494,-487,-480,-473,-465,-458,-450,-443,-434,-426,-416,-406,-396,-384,-372,-360,-346,-333,
+-319,-304,-290,-275,-261,-246,-232,-219,-205,-192,-180,-168,-156,-144,-133,-122,-111,-100,-89,-78,-66,
+-54,-42,-29,-15,-1,12,28,43,59,75,91,108,124,141,157,173,189,204,218,232,245,
+257,268,279,287,295,302,307,310,312,313,312,309,305,299,292,284,275,265,254,242,231,
+219,208,196,186,176,168,160,154,150,146,144,144,144,146,149,153,158,164,170,177,184,
+191,198,206,213,221,228,235,242,249,255,262,267,273,278,283,288,292,295,298,301,302,
+304,305,306,307,307,308,309,310,311,313,316,319,323,328,333,339,345,352,358,364,370,
+375,379,383,385,386,386,386,384,382,380,378,377,376,377,379,384,390,400,412,426,444,
+464,486,510,535,561,588,614,639,663,685,705,721,735,745,752,756,757,754,749,742,734,
+724,713,701,689,678,667,656,647,637,628,620,612,604,595,586,576,566,554,542,528,514,
+499,484,468,452,437,423,410,398,388,380,374,370,369,369,370,374,378,384,390,397,404,
+411,417,424,429,435,440,445,450,455,460,466,473,480,488,497,507,518,529,540,552,562,
+572,580,587,592,594,593,590,583,574,562,547,529,509,488,465,441,417,393,369,345,323,
+302,282,264,247,231,217,203,191,179,167,156,144,133,121,109,96,83,69,56,42,27,
+13,0,-14,-28,-42,-55,-69,-83,-96,-110,-125,-140,-157,-174,-193,-213,-234,-258,-282,-309,-337,
+-366,-397,-428,-460,-493,-526,-559,-592,-624,-656,-687,-717,-746,-774,-802,-828,-854,-879,-904,-928,-952,
+-977,-1001,-1026,-1051,-1076,-1102,-1128,-1154,-1181,-1208,-1235,-1261,-1288,-1314,-1340,-1365,-1390,-1413,-1437,-1459,-1481,
+-1503,-1524,-1544,-1565,-1585,-1606,-1626,-1647,-1669,-1691,-1713,-1736,-1760,-1784,-1808,-1832,-1857,-1882,-1907,-1931,-1956,
+-1980,-2004,-2028,-2052,-2076,-2100,-2123,-2148,-2172,-2197,-2223,-2249,-2277,-2305,-2334,-2365,-2395,-2427,-2459,-2491,-2524,
+-2556,-2588,-2620,-2651,-2680,-2709,-2736,-2763,-2788,-2811,-2834,-2855,-2876,-2896,-2916,-2935,-2954,-2973,-2992,-3012,-3031,
+-3051,-3071,-3092,-3112,-3132,-3152,-3171,-3190,-3208,-3226,-3242,-3258,-3273,-3287,-3301,-3314,-3327,-3340,-3354,-3368,-3383,
+-3399,-3416,-3435,-3455,-3477,-3501,-3526,-3552,-3579,-3607,-3636,-3664,-3693,-3720,-3747,-3773,-3797,-3820,-3841,-3860,-3877,
+-3892,-3905,-3916,-3927,-3936,-3944,-3951,-3959,-3966,-3973,-3981,-3989,-3998,-4008,-4019,-4030,-4043,-4056,-4070,-4085,-4100,
+-4116,-4132,-4148,-4165,-4182,-4199,-4217,-4235,-4254,-4273,-4293,-4313,-4335,-4357,-4380,-4404,-4428,-4453,-4479,-4504,-4530,
+-4555,-4580,-4604,-4626,-4647,-4666,-4683,-4698,-4711,-4721,-4729,-4734,-4737,-4739,-4739,-4737,-4735,-4732,-4729,-4727,-4725,
+-4724,-4724,-4726,-4730,-4735,-4742,-4750,-4759,-4769,-4781,-4792,-4804,-4815,-4826,-4835,-4844,-4852,-4858,-4863,-4866,-4869,
+-4871,-4872,-4874,-4876,-4878,-4882,-4888,-4895,-4903,-4914,-4927,-4942,-4958,-4975,-4993,-5011,-5028,-5044,-5058,-5069,-5077,
+-5081,-5080,-5075,-5065,-5051,-5032,-5008,-4981,-4952,-4920,-4887,-4854,-4821,-4791,-4763,-4739,-4720,-4705,-4696,-4693,-4695,
+-4703,-4717,-4735,-4757,-4783,-4811,-4841,-4872,-4902,-4931,-4958,-4983,-5004,-5022,-5037,-5047,-5053,-5056,-5056,-5053,-5047,
+-5040,-5031,-5022,-5012,-5003,-4994,-4987,-4981,-4976,-4973,-4971,-4970,-4971,-4973,-4976,-4979,-4982,-4985,-4988,-4990,-4992,
+-4993,-4993,-4992,-4991,-4990,-4988,-4985,-4983,-4981,-4980,-4979,-4979,-4979,-4981,-4983,-4986,-4991,-4995,-5001,-5007,-5013,
+-5019,-5025,-5031,-5036,-5040,-5044,-5047,-5050,-5051,-5052,-5051,-5051,-5050,-5048,-5046,-5045,-5043,-5042,-5042,-5042,-5042,
+-5044,-5046,-5049,-5053,-5057,-5062,-5067,-5073,-5079,-5085,-5091,-5097,-5102,-5108,-5112,-5117,-5120,-5124,-5126,-5129,-5131,
+-5133,-5134,-5135,-5136,-5137,-5138,-5139,-5140,-5141,-5141,-5142,-5142,-5142,-5142,-5141,-5140,-5139,-5137,-5135,-5132,-5129,
+-5125,-5121,-5117,-5113,-5108,-5103,-5099,-5094,-5090,-5086,-5082,-5079,-5076,-5073,-5071,-5069,-5068,-5067,-5067,-5067,-5067,
+-5068,-5069,-5070,-5072,-5074,-5076,-5078,-5081,-5084,-5087,-5090,-5093,-5096,-5099,-5102,-5105,-5108,-5110,-5113,-5115,-5117,
+-5118,-5119,-5120,-5120,-5121,-5120,-5120,-5119,-5118,-5117,-5116,-5115,-5113,-5112,-5110,-5109,-5107,-5106,-5104,-5102,-5101,
+-5099,-5097,-5095,-5094,-5092,-5091,-5089,-5088,-5086,-5085,-5084,-5083,-5082,-5081,-5080,-5079,-5078,-5076,-5074,-5071,-5068,
+-5064,-5059,-5053,-5047,-5039,-5030,-5019,-5008,-4996,-4983,-4969,-4955,-4940,-4924,-4909,-4893,-4878,-4863,-4848,-4834,-4821,
+-4808,-4796,-4785,-4774,-4763,-4754,-4744,-4735,-4727,-4718,-4710,-4701,-4693,-4685,-4677,-4669,-4661,-4653,-4645,-4638,-4631,
+-4625,-4618,-4612,-4607,-4601,-4596,-4590,-4584,-4578,-4571,-4564,-4555,-4545,-4534,-4522,-4508,-4492,-4475,-4457,-4437,-4416,
+-4394,-4371,-4348,-4325,-4302,-4279,-4257,-4236,-4216,-4197,-4180,-4164,-4150,-4137,-4126,-4116,-4107,-4100,-4093,-4088,-4082,
+-4078,-4073,-4069,-4065,-4061,-4057,-4052,-4048,-4043,-4039,-4034,-4029,-4024,-4019,-4014,-4009,-4004,-3999,-3994,-3988,-3983,
+-3977,-3971,-3965,-3958,-3951,-3943,-3935,-3927,-3918,-3909,-3900,-3891,-3882,-3873,-3864,-3856,-3848,-3840,-3833,-3827,-3821,
+-3816,-3812,-3808,-3804,-3801,-3798,-3796,-3794,-3792,-3790,-3788,-3786,-3783,-3781,-3778,-3775,-3772,-3768,-3764,-3760,-3754,
+-3748,-3741,-3734,-3725,-3715,-3704,-3691,-3677,-3662,-3645,-3627,-3607,-3586,-3564,-3541,-3517,-3492,-3467,-3442,-3417,-3393,
+-3369,-3346,-3325,-3304,-3285,-3268,-3251,-3236,-3222,-3210,-3197,-3185,-3173,-3161,-3148,-3135,-3120,-3104,-3086,-3067,-3046,
+-3023,-2999,-2974,-2947,-2920,-2892,-2864,-2837,-2811,-2785,-2761,-2739,-2719,-2701,-2685,-2671,-2660,-2650,-2643,-2636,-2631,
+-2627,-2623,-2619,-2615,-2611,-2606,-2600,-2594,-2587,-2579,-2571,-2562,-2554,-2546,-2538,-2532,-2526,-2523,-2521,-2522,-2524,
+-2529,-2537,-2546,-2557,-2570,-2584,-2599,-2615,-2631,-2647,-2662,-2677,-2690,-2702,-2712,-2720,-2726,-2730,-2733,-2733,-2732,
+-2729,-2725,-2720,-2714,-2707,-2700,-2692,-2684,-2677,-2669,-2661,-2654,-2647,-2641,-2635,-2630,-2625,-2621,-2618,-2615,-2612,
+-2611,-2610,-2610,-2610,-2612,-2613,-2615,-2618,-2620,-2623,-2625,-2628,-2629,-2630,-2630,-2629,-2627,-2624,-2619,-2613,-2606,
+-2598,-2588,-2578,-2567,-2555,-2543,-2531,-2520,-2508,-2498,-2487,-2478,-2469,-2461,-2454,-2447,-2441,-2435,-2429,-2423,-2416,
+-2409,-2401,-2392,-2382,-2370,-2358,-2345,-2331,-2317,-2302,-2287,-2273,-2259,-2246,-2234,-2223,-2215,-2208,-2202,-2199,-2198,
+-2199,-2202,-2206,-2211,-2217,-2225,-2232,-2240,-2248,-2256,-2264,-2271,-2278,-2284,-2290,-2295,-2300,-2305,-2310,-2315,-2320,
+-2325,-2331,-2337,-2344,-2351,-2358,-2365,-2373,-2380,-2388,-2394,-2401,-2406,-2411,-2415,-2418,-2420,-2421,-2421,-2421,-2420,
+-2419,-2417,-2416,-2415,-2413,-2413,-2412,-2412,-2411,-2411,-2411,-2411,-2411,-2409,-2407,-2404,-2400,-2394,-2387,-2378,-2368,
+-2356,-2343,-2329,-2313,-2297,-2280,-2262,-2245,-2227,-2210,-2193,-2177,-2162,-2148,-2135,-2122,-2110,-2100,-2089,-2079,-2070,
+-2061,-2052,-2043,-2033,-2024,-2015,-2005,-1996,-1986,-1977,-1967,-1958,-1950,-1942,-1934,-1928,-1921,-1916,-1912,-1908,-1905,
+-1903,-1901,-1900,-1899,-1899,-1899,-1899,-1900,-1900,-1900,-1901,-1901,-1901,-1901,-1901,-1900,-1899,-1897,-1894,-1891,-1887,
+-1881,-1874,-1866,-1856,-1844,-1831,-1816,-1799,-1781,-1761,-1740,-1718,-1695,-1672,-1648,-1625,-1603,-1581,-1561,-1543,-1527,
+-1513,-1501,-1491,-1483,-1478,-1475,-1473,-1472,-1473,-1474,-1476,-1477,-1479,-1479,-1478,-1476,-1473,-1468,-1461,-1453,-1444,
+-1434,-1422,-1410,-1398,-1385,-1372,-1360,-1348,-1337,-1327,-1317,-1309,-1302,-1295,-1289,-1284,-1279,-1274,-1270,-1265,-1260,
+-1255,-1249,-1243,-1236,-1228,-1220,-1212,-1204,-1195,-1187,-1179,-1171,-1164,-1157,-1152,-1147,-1143,-1140,-1138,-1137,-1136,
+-1135,-1135,-1135,-1135,-1134,-1134,-1133,-1131,-1128,-1125,-1122,-1117,-1113,-1107,-1101,-1095,-1089,-1083,-1077,-1071,-1065,
+-1059,-1053,-1048,-1043,-1037,-1032,-1026,-1020,-1014,-1007,-999,-992,-983,-974,-965,-956,-946,-936,-926,-916,-907,
+-898,-890,-882,-876,-870,-865,-860,-856,-853,-930,-925,-920,-916,-911,-906,-901,-896,-890,-884,-877,-869,
+-861,-852,-843,-833,-823,-812,-801,-790,-780,-769,-759,-749,-740,-731,-723,-715,-708,-702,-696,-691,-686,
+-682,-679,-675,-672,-669,-666,-662,-659,-656,-652,-649,-644,-640,-635,-630,-624,-618,-612,-605,-597,-589,
+-580,-570,-559,-548,-536,-524,-511,-497,-482,-467,-451,-436,-419,-403,-386,-370,-353,-337,-321,-306,-291,
+-276,-262,-249,-236,-223,-211,-199,-187,-176,-165,-154,-143,-131,-120,-108,-96,-83,-70,-57,-43,-28,
+-14,1,16,32,48,65,81,98,114,131,147,162,177,191,205,218,229,240,249,257,263,
+268,272,273,274,272,269,265,260,253,246,237,228,219,210,200,191,182,174,166,160,154,
+149,145,142,140,139,139,139,141,142,145,148,151,154,158,161,165,169,173,178,182,186,
+190,194,198,202,205,209,212,215,217,219,221,222,222,222,222,221,220,219,217,216,215,
+214,214,214,215,217,219,222,225,229,234,239,244,249,254,259,263,267,271,274,276,278,
+280,281,283,284,286,289,292,297,303,311,320,331,343,357,372,389,406,424,442,460,478,
+494,509,523,535,545,553,559,563,564,564,562,558,553,548,541,534,527,520,514,507,501,
+495,490,485,480,475,471,466,460,454,448,441,433,426,417,409,400,391,383,375,368,362,
+357,353,350,349,348,349,351,354,358,363,368,374,380,386,392,398,403,409,415,421,427,
+433,439,446,453,460,469,477,486,494,503,512,520,527,533,538,541,542,541,538,533,525,
+515,502,488,471,453,433,412,391,369,346,324,302,281,260,240,221,203,186,169,153,138,
+123,109,94,80,66,52,38,24,11,-2,-15,-28,-41,-53,-65,-76,-87,-98,-109,-120,-130,
+-141,-153,-166,-180,-194,-211,-229,-249,-271,-295,-320,-348,-377,-408,-440,-473,-507,-541,-575,-609,-643,
+-676,-707,-738,-768,-796,-823,-849,-873,-897,-920,-942,-964,-986,-1008,-1030,-1052,-1075,-1099,-1123,-1147,-1172,
+-1198,-1224,-1251,-1277,-1304,-1330,-1356,-1382,-1407,-1431,-1455,-1477,-1500,-1521,-1542,-1563,-1583,-1602,-1622,-1642,-1662,
+-1682,-1702,-1722,-1743,-1765,-1786,-1808,-1831,-1853,-1876,-1898,-1921,-1943,-1965,-1988,-2010,-2032,-2054,-2076,-2099,-2121,
+-2144,-2168,-2192,-2217,-2243,-2270,-2297,-2326,-2355,-2385,-2415,-2445,-2476,-2507,-2538,-2568,-2598,-2627,-2655,-2682,-2708,
+-2733,-2756,-2779,-2801,-2822,-2843,-2863,-2883,-2902,-2921,-2941,-2960,-2980,-2999,-3019,-3040,-3060,-3080,-3101,-3121,-3141,
+-3160,-3179,-3197,-3215,-3232,-3249,-3265,-3280,-3296,-3311,-3327,-3343,-3359,-3376,-3394,-3413,-3434,-3455,-3477,-3501,-3526,
+-3552,-3579,-3606,-3634,-3662,-3690,-3717,-3744,-3770,-3795,-3819,-3841,-3861,-3880,-3898,-3914,-3928,-3941,-3953,-3963,-3973,
+-3981,-3990,-3997,-4005,-4012,-4020,-4027,-4035,-4044,-4053,-4062,-4072,-4083,-4095,-4107,-4120,-4134,-4150,-4166,-4183,-4201,
+-4221,-4241,-4262,-4285,-4308,-4333,-4357,-4383,-4409,-4434,-4460,-4485,-4510,-4533,-4555,-4576,-4595,-4612,-4627,-4640,-4650,
+-4658,-4665,-4669,-4672,-4673,-4673,-4672,-4671,-4669,-4668,-4667,-4667,-4668,-4670,-4674,-4679,-4685,-4692,-4700,-4708,-4718,
+-4727,-4736,-4744,-4752,-4759,-4764,-4768,-4770,-4771,-4771,-4770,-4768,-4765,-4763,-4760,-4759,-4759,-4760,-4764,-4770,-4778,
+-4789,-4802,-4817,-4834,-4853,-4872,-4892,-4911,-4929,-4945,-4957,-4967,-4972,-4972,-4967,-4957,-4941,-4921,-4895,-4865,-4831,
+-4795,-4757,-4717,-4679,-4641,-4607,-4575,-4549,-4528,-4512,-4504,-4501,-4506,-4517,-4535,-4558,-4586,-4618,-4654,-4691,-4730,
+-4769,-4807,-4843,-4876,-4906,-4933,-4955,-4973,-4986,-4996,-5001,-5003,-5001,-4997,-4992,-4984,-4976,-4968,-4960,-4953,-4947,
+-4942,-4939,-4938,-4937,-4938,-4941,-4944,-4948,-4953,-4957,-4962,-4966,-4970,-4972,-4975,-4976,-4976,-4976,-4975,-4973,-4971,
+-4969,-4967,-4964,-4963,-4961,-4960,-4960,-4961,-4961,-4963,-4965,-4967,-4970,-4973,-4975,-4978,-4980,-4982,-4983,-4984,-4985,
+-4985,-4984,-4984,-4983,-4983,-4982,-4982,-4982,-4983,-4984,-4986,-4989,-4992,-4996,-5001,-5007,-5013,-5020,-5026,-5033,-5039,
+-5045,-5051,-5056,-5061,-5064,-5067,-5070,-5071,-5072,-5072,-5072,-5072,-5071,-5070,-5070,-5070,-5070,-5070,-5072,-5073,-5076,
+-5078,-5082,-5085,-5089,-5093,-5097,-5101,-5105,-5108,-5111,-5113,-5114,-5115,-5115,-5114,-5112,-5110,-5107,-5103,-5100,-5095,
+-5091,-5087,-5083,-5078,-5074,-5071,-5067,-5064,-5061,-5059,-5057,-5055,-5054,-5053,-5051,-5050,-5050,-5049,-5048,-5047,-5046,
+-5045,-5043,-5042,-5041,-5039,-5038,-5037,-5036,-5034,-5033,-5032,-5032,-5031,-5031,-5031,-5031,-5032,-5033,-5034,-5035,-5036,
+-5038,-5039,-5040,-5042,-5043,-5044,-5045,-5045,-5046,-5045,-5045,-5043,-5042,-5040,-5037,-5034,-5030,-5026,-5022,-5017,-5012,
+-5007,-5001,-4996,-4990,-4984,-4978,-4972,-4966,-4960,-4954,-4948,-4942,-4936,-4929,-4923,-4916,-4910,-4903,-4895,-4888,-4880,
+-4872,-4864,-4856,-4847,-4839,-4830,-4821,-4813,-4804,-4796,-4787,-4779,-4770,-4762,-4754,-4746,-4738,-4730,-4722,-4713,-4705,
+-4697,-4689,-4680,-4672,-4664,-4656,-4648,-4640,-4632,-4625,-4617,-4611,-4604,-4598,-4592,-4587,-4581,-4576,-4570,-4565,-4559,
+-4552,-4545,-4537,-4528,-4518,-4507,-4494,-4480,-4465,-4449,-4432,-4413,-4394,-4374,-4353,-4333,-4312,-4291,-4271,-4252,-4233,
+-4216,-4199,-4184,-4171,-4158,-4147,-4138,-4129,-4122,-4115,-4110,-4105,-4101,-4098,-4094,-4091,-4088,-4086,-4083,-4080,-4077,
+-4074,-4070,-4067,-4064,-4060,-4056,-4052,-4048,-4044,-4039,-4035,-4029,-4024,-4018,-4012,-4005,-3998,-3990,-3982,-3973,-3963,
+-3953,-3943,-3932,-3920,-3909,-3897,-3885,-3872,-3860,-3848,-3836,-3824,-3812,-3801,-3790,-3778,-3768,-3757,-3747,-3737,-3728,
+-3718,-3709,-3701,-3692,-3684,-3676,-3668,-3661,-3654,-3647,-3640,-3633,-3626,-3618,-3611,-3603,-3594,-3585,-3575,-3565,-3553,
+-3540,-3526,-3511,-3495,-3478,-3460,-3441,-3422,-3403,-3383,-3363,-3343,-3324,-3306,-3288,-3272,-3256,-3242,-3229,-3217,-3206,
+-3196,-3186,-3178,-3169,-3160,-3151,-3142,-3131,-3120,-3107,-3093,-3078,-3062,-3044,-3024,-3004,-2983,-2962,-2940,-2918,-2897,
+-2877,-2857,-2839,-2822,-2807,-2793,-2782,-2772,-2763,-2756,-2750,-2745,-2740,-2736,-2732,-2728,-2723,-2718,-2712,-2705,-2697,
+-2688,-2678,-2667,-2656,-2645,-2633,-2622,-2611,-2602,-2593,-2585,-2580,-2575,-2573,-2572,-2573,-2575,-2580,-2585,-2591,-2599,
+-2607,-2615,-2624,-2632,-2641,-2649,-2656,-2662,-2668,-2673,-2678,-2681,-2684,-2687,-2689,-2690,-2691,-2692,-2692,-2693,-2693,
+-2693,-2693,-2693,-2693,-2693,-2693,-2693,-2693,-2693,-2694,-2694,-2694,-2695,-2696,-2697,-2698,-2700,-2702,-2704,-2706,-2708,
+-2710,-2712,-2713,-2714,-2714,-2713,-2711,-2708,-2703,-2698,-2691,-2683,-2673,-2662,-2651,-2638,-2626,-2612,-2599,-2586,-2573,
+-2561,-2550,-2540,-2531,-2523,-2516,-2510,-2505,-2501,-2497,-2493,-2489,-2485,-2481,-2475,-2469,-2462,-2453,-2443,-2432,-2420,
+-2407,-2393,-2379,-2364,-2350,-2336,-2322,-2310,-2299,-2289,-2281,-2275,-2270,-2268,-2267,-2267,-2270,-2273,-2278,-2283,-2290,
+-2296,-2303,-2311,-2318,-2325,-2332,-2339,-2346,-2352,-2359,-2365,-2371,-2378,-2385,-2392,-2399,-2407,-2415,-2422,-2430,-2438,
+-2446,-2454,-2461,-2468,-2474,-2480,-2485,-2489,-2492,-2495,-2496,-2498,-2498,-2498,-2498,-2497,-2497,-2496,-2494,-2493,-2492,
+-2490,-2488,-2486,-2484,-2481,-2477,-2472,-2466,-2460,-2452,-2443,-2433,-2423,-2411,-2398,-2385,-2371,-2357,-2343,-2329,-2315,
+-2302,-2289,-2277,-2265,-2254,-2244,-2234,-2225,-2216,-2207,-2199,-2190,-2181,-2171,-2161,-2150,-2138,-2126,-2113,-2100,-2087,
+-2073,-2059,-2045,-2032,-2020,-2009,-1998,-1990,-1982,-1976,-1971,-1968,-1966,-1966,-1966,-1968,-1969,-1972,-1974,-1976,-1977,
+-1978,-1978,-1977,-1974,-1970,-1965,-1958,-1949,-1939,-1927,-1914,-1900,-1885,-1868,-1851,-1833,-1814,-1795,-1776,-1757,-1738,
+-1720,-1701,-1684,-1667,-1651,-1636,-1623,-1610,-1599,-1589,-1581,-1574,-1569,-1564,-1561,-1559,-1558,-1557,-1557,-1557,-1557,
+-1557,-1557,-1555,-1553,-1549,-1545,-1539,-1531,-1523,-1513,-1502,-1491,-1478,-1465,-1451,-1438,-1425,-1412,-1399,-1388,-1377,
+-1367,-1359,-1352,-1345,-1340,-1335,-1331,-1328,-1325,-1322,-1319,-1316,-1313,-1309,-1304,-1299,-1293,-1286,-1279,-1271,-1263,
+-1255,-1246,-1238,-1230,-1223,-1216,-1209,-1204,-1199,-1195,-1192,-1189,-1187,-1186,-1185,-1183,-1182,-1181,-1179,-1177,-1175,
+-1171,-1167,-1163,-1157,-1151,-1145,-1138,-1131,-1124,-1116,-1109,-1102,-1095,-1089,-1083,-1077,-1072,-1067,-1063,-1059,-1054,
+-1050,-1046,-1042,-1038,-1033,-1028,-1023,-1017,-1011,-1004,-998,-991,-984,-977,-970,-964,-957,-951,-945,-940,-935,
+-930,-991,-986,-980,-974,-968,-962,-956,-949,-942,-935,-928,-920,-911,-903,-894,-884,-875,-865,-855,-845,
+-835,-825,-816,-807,-798,-790,-783,-776,-770,-765,-761,-758,-755,-753,-752,-752,-752,-752,-753,-754,-755,
+-756,-757,-758,-758,-757,-755,-753,-750,-746,-741,-734,-727,-718,-708,-696,-684,-670,-655,-639,-622,-604,
+-586,-567,-547,-527,-507,-486,-466,-446,-426,-407,-388,-370,-353,-336,-321,-306,-292,-278,-266,-254,-242,
+-232,-221,-211,-202,-192,-183,-173,-163,-153,-142,-131,-119,-107,-95,-81,-67,-52,-37,-21,-5,11,
+28,45,62,79,96,112,128,143,157,170,182,192,201,209,215,220,223,225,225,224,221,
+218,213,208,202,195,188,181,174,167,160,153,147,141,136,131,127,123,119,116,113,111,
+109,107,106,105,104,103,103,103,103,104,106,107,109,112,115,118,122,125,129,132,136,
+139,142,144,146,147,148,148,147,145,143,141,138,135,132,129,126,123,121,120,119,119,
+120,122,124,127,130,135,139,144,149,154,158,163,168,172,176,180,184,187,191,195,199,
+203,208,214,220,227,234,242,250,259,269,278,288,297,306,315,323,331,337,343,348,351,
+354,356,357,357,357,356,355,353,352,350,349,347,346,345,343,343,342,341,340,339,337,
+336,334,332,329,326,323,320,317,313,310,307,304,302,300,299,298,298,299,301,303,305,
+309,313,317,322,328,333,339,345,352,359,366,373,381,388,396,405,413,422,431,439,448,
+456,464,471,477,482,486,489,490,489,486,482,475,467,456,444,430,414,397,379,360,340,
+319,298,277,255,234,213,192,171,151,131,111,92,73,55,37,19,2,-14,-30,-46,-61,
+-75,-89,-101,-113,-124,-134,-144,-152,-160,-168,-176,-183,-191,-199,-208,-219,-230,-243,-259,-276,-295,
+-316,-340,-366,-394,-423,-454,-487,-520,-555,-589,-624,-658,-692,-725,-756,-787,-816,-844,-870,-894,-918,
+-940,-962,-982,-1003,-1023,-1043,-1063,-1083,-1105,-1126,-1149,-1172,-1196,-1221,-1246,-1272,-1298,-1324,-1350,-1377,-1403,
+-1428,-1453,-1477,-1501,-1523,-1546,-1567,-1587,-1607,-1627,-1646,-1665,-1684,-1702,-1721,-1739,-1758,-1776,-1795,-1814,-1833,
+-1853,-1872,-1892,-1911,-1931,-1950,-1970,-1990,-2010,-2030,-2050,-2071,-2092,-2114,-2137,-2160,-2184,-2209,-2234,-2261,-2289,
+-2317,-2346,-2375,-2405,-2435,-2466,-2496,-2526,-2555,-2584,-2612,-2639,-2666,-2691,-2716,-2739,-2761,-2783,-2804,-2824,-2844,
+-2864,-2883,-2902,-2921,-2941,-2960,-2980,-3000,-3021,-3041,-3062,-3082,-3103,-3124,-3144,-3164,-3184,-3203,-3222,-3240,-3258,
+-3275,-3292,-3309,-3326,-3343,-3360,-3377,-3395,-3413,-3432,-3452,-3473,-3495,-3518,-3542,-3566,-3592,-3618,-3645,-3672,-3699,
+-3727,-3754,-3781,-3807,-3832,-3857,-3880,-3902,-3923,-3942,-3960,-3977,-3991,-4005,-4017,-4027,-4037,-4045,-4053,-4059,-4065,
+-4071,-4077,-4083,-4088,-4095,-4102,-4110,-4119,-4129,-4141,-4154,-4169,-4186,-4204,-4223,-4244,-4267,-4290,-4315,-4341,-4366,
+-4393,-4418,-4444,-4469,-4492,-4514,-4535,-4554,-4571,-4586,-4598,-4609,-4617,-4624,-4628,-4631,-4633,-4634,-4634,-4634,-4634,
+-4634,-4634,-4635,-4637,-4640,-4644,-4648,-4653,-4659,-4665,-4672,-4678,-4683,-4689,-4693,-4696,-4697,-4697,-4696,-4693,-4689,
+-4683,-4677,-4670,-4663,-4657,-4651,-4646,-4643,-4642,-4643,-4646,-4653,-4662,-4674,-4688,-4704,-4721,-4739,-4758,-4776,-4793,
+-4807,-4819,-4827,-4830,-4829,-4823,-4811,-4794,-4771,-4743,-4710,-4674,-4634,-4592,-4550,-4507,-4465,-4426,-4391,-4359,-4334,
+-4314,-4301,-4296,-4298,-4307,-4323,-4346,-4375,-4409,-4448,-4490,-4535,-4581,-4627,-4672,-4715,-4756,-4793,-4827,-4856,-4880,
+-4900,-4915,-4926,-4933,-4936,-4936,-4934,-4930,-4925,-4919,-4912,-4907,-4902,-4898,-4895,-4894,-4894,-4896,-4900,-4904,-4909,
+-4916,-4922,-4929,-4935,-4942,-4947,-4952,-4957,-4960,-4962,-4964,-4964,-4964,-4963,-4961,-4959,-4957,-4954,-4952,-4949,-4947,
+-4944,-4942,-4940,-4938,-4935,-4933,-4931,-4929,-4927,-4925,-4922,-4920,-4918,-4916,-4914,-4912,-4911,-4910,-4910,-4911,-4912,
+-4915,-4918,-4922,-4928,-4934,-4941,-4948,-4956,-4964,-4972,-4980,-4988,-4996,-5002,-5008,-5013,-5017,-5020,-5022,-5023,-5023,
+-5023,-5021,-5020,-5018,-5016,-5014,-5013,-5012,-5011,-5012,-5013,-5015,-5018,-5022,-5027,-5032,-5038,-5044,-5051,-5057,-5063,
+-5069,-5074,-5079,-5083,-5086,-5088,-5089,-5089,-5089,-5088,-5086,-5083,-5080,-5077,-5073,-5069,-5066,-5062,-5059,-5056,-5053,
+-5051,-5048,-5046,-5045,-5043,-5041,-5039,-5037,-5035,-5033,-5030,-5027,-5024,-5020,-5016,-5012,-5008,-5003,-4998,-4993,-4988,
+-4983,-4979,-4975,-4972,-4969,-4966,-4964,-4963,-4962,-4962,-4963,-4964,-4965,-4967,-4969,-4971,-4974,-4976,-4978,-4979,-4980,
+-4981,-4981,-4980,-4978,-4976,-4973,-4968,-4964,-4958,-4951,-4944,-4936,-4928,-4919,-4910,-4900,-4891,-4881,-4871,-4862,-4852,
+-4843,-4834,-4825,-4817,-4809,-4801,-4794,-4787,-4781,-4775,-4769,-4764,-4759,-4755,-4751,-4747,-4743,-4739,-4736,-4732,-4729,
+-4725,-4722,-4718,-4715,-4711,-4707,-4702,-4698,-4693,-4687,-4682,-4676,-4669,-4662,-4655,-4648,-4641,-4633,-4625,-4617,-4609,
+-4601,-4593,-4586,-4578,-4571,-4563,-4556,-4548,-4541,-4534,-4526,-4518,-4510,-4501,-4492,-4483,-4472,-4461,-4449,-4436,-4423,
+-4409,-4394,-4379,-4363,-4347,-4330,-4314,-4297,-4281,-4266,-4251,-4236,-4223,-4210,-4198,-4187,-4177,-4169,-4161,-4154,-4148,
+-4142,-4137,-4133,-4130,-4126,-4124,-4121,-4118,-4116,-4113,-4110,-4108,-4105,-4102,-4099,-4095,-4092,-4088,-4084,-4080,-4076,
+-4071,-4065,-4060,-4054,-4047,-4040,-4032,-4024,-4015,-4005,-3994,-3983,-3971,-3959,-3946,-3932,-3918,-3903,-3888,-3873,-3857,
+-3841,-3825,-3809,-3793,-3777,-3761,-3746,-3730,-3715,-3699,-3684,-3670,-3655,-3641,-3627,-3613,-3600,-3587,-3575,-3563,-3551,
+-3540,-3529,-3518,-3508,-3499,-3489,-3480,-3471,-3461,-3452,-3443,-3433,-3423,-3413,-3402,-3391,-3379,-3367,-3355,-3342,-3329,
+-3316,-3302,-3289,-3276,-3263,-3251,-3239,-3228,-3217,-3207,-3198,-3189,-3181,-3173,-3166,-3159,-3152,-3145,-3138,-3130,-3122,
+-3113,-3104,-3093,-3082,-3070,-3058,-3044,-3031,-3016,-3002,-2988,-2974,-2960,-2947,-2935,-2923,-2912,-2903,-2894,-2887,-2880,
+-2874,-2869,-2864,-2860,-2855,-2851,-2846,-2840,-2834,-2827,-2819,-2810,-2800,-2790,-2778,-2765,-2752,-2739,-2725,-2712,-2698,
+-2685,-2673,-2662,-2651,-2642,-2634,-2627,-2622,-2618,-2616,-2614,-2614,-2615,-2617,-2620,-2623,-2627,-2632,-2637,-2642,-2647,
+-2653,-2658,-2664,-2670,-2676,-2682,-2688,-2693,-2699,-2705,-2710,-2715,-2720,-2725,-2730,-2734,-2738,-2741,-2744,-2747,-2749,
+-2751,-2753,-2755,-2757,-2758,-2760,-2761,-2763,-2765,-2767,-2769,-2771,-2773,-2775,-2776,-2778,-2778,-2778,-2777,-2775,-2771,
+-2767,-2761,-2754,-2745,-2736,-2725,-2713,-2700,-2686,-2672,-2658,-2644,-2631,-2617,-2605,-2594,-2583,-2574,-2566,-2559,-2553,
+-2548,-2544,-2540,-2537,-2534,-2531,-2527,-2523,-2519,-2513,-2506,-2499,-2490,-2480,-2470,-2458,-2446,-2434,-2422,-2410,-2398,
+-2387,-2376,-2367,-2359,-2353,-2347,-2344,-2341,-2341,-2341,-2343,-2347,-2351,-2356,-2363,-2369,-2377,-2384,-2392,-2400,-2408,
+-2417,-2425,-2433,-2441,-2449,-2456,-2464,-2471,-2478,-2485,-2492,-2499,-2505,-2511,-2516,-2522,-2527,-2531,-2535,-2539,-2543,
+-2546,-2549,-2551,-2553,-2555,-2557,-2558,-2559,-2560,-2560,-2561,-2560,-2560,-2558,-2556,-2554,-2550,-2546,-2540,-2534,-2526,
+-2518,-2508,-2498,-2487,-2475,-2463,-2450,-2438,-2425,-2413,-2401,-2390,-2379,-2369,-2360,-2352,-2344,-2337,-2331,-2324,-2318,
+-2312,-2305,-2297,-2289,-2280,-2270,-2258,-2245,-2231,-2216,-2199,-2182,-2165,-2147,-2129,-2112,-2095,-2080,-2065,-2053,-2042,
+-2034,-2028,-2023,-2021,-2021,-2023,-2026,-2030,-2035,-2040,-2045,-2049,-2052,-2054,-2054,-2052,-2048,-2040,-2031,-2018,-2003,
+-1985,-1965,-1943,-1920,-1894,-1868,-1841,-1814,-1787,-1761,-1736,-1712,-1690,-1669,-1651,-1635,-1622,-1611,-1602,-1595,-1591,
+-1588,-1588,-1589,-1591,-1594,-1597,-1601,-1605,-1609,-1611,-1613,-1614,-1614,-1612,-1608,-1603,-1596,-1587,-1576,-1564,-1551,
+-1536,-1521,-1504,-1488,-1471,-1454,-1438,-1422,-1407,-1393,-1381,-1370,-1360,-1351,-1344,-1339,-1334,-1331,-1328,-1327,-1325,
+-1324,-1323,-1322,-1320,-1318,-1316,-1312,-1308,-1303,-1298,-1291,-1284,-1277,-1270,-1262,-1254,-1246,-1239,-1232,-1226,-1221,
+-1216,-1211,-1208,-1204,-1202,-1200,-1198,-1196,-1194,-1191,-1189,-1186,-1182,-1178,-1173,-1168,-1161,-1155,-1147,-1140,-1132,
+-1124,-1116,-1108,-1100,-1093,-1086,-1080,-1075,-1071,-1067,-1064,-1061,-1059,-1057,-1056,-1055,-1055,-1054,-1053,-1052,-1050,
+-1048,-1046,-1043,-1040,-1037,-1033,-1028,-1024,-1019,-1013,-1008,-1003,-997,-991,-1019,-1014,-1008,-1003,-997,-991,-985,
+-979,-973,-966,-959,-952,-944,-937,-929,-921,-913,-904,-896,-888,-879,-871,-863,-856,-849,-842,-836,-831,
+-827,-823,-820,-818,-817,-817,-817,-818,-820,-822,-825,-828,-831,-834,-836,-839,-840,-841,-841,-840,-838,
+-835,-830,-824,-817,-808,-797,-786,-772,-758,-742,-725,-706,-687,-667,-647,-626,-605,-583,-562,-540,-519,
+-498,-478,-459,-440,-422,-405,-389,-374,-359,-346,-333,-321,-310,-299,-289,-279,-270,-260,-251,-241,-232,
+-222,-211,-200,-188,-176,-163,-149,-134,-119,-103,-86,-69,-51,-33,-15,2,20,38,55,71,87,
+102,115,128,139,149,157,164,169,173,175,177,177,175,173,170,166,162,157,152,146,141,
+135,129,123,118,112,107,101,96,91,85,80,75,70,65,60,55,51,47,43,40,37,
+35,33,32,32,33,35,37,40,44,48,52,57,62,67,71,75,79,82,84,85,86,
+85,84,82,79,75,71,67,63,59,55,51,48,45,44,43,43,44,45,48,51,55,
+60,65,70,76,81,86,92,97,101,106,110,114,117,121,124,127,131,134,137,141,145,
+149,154,159,164,169,175,181,186,192,197,203,208,213,217,222,225,229,232,234,236,238,
+240,241,242,243,243,243,244,244,243,243,243,242,241,241,240,239,238,236,235,234,233,
+232,231,230,229,229,229,229,229,230,232,234,236,239,242,245,250,254,259,265,271,277,
+284,292,299,308,316,325,334,343,352,361,370,379,387,394,401,407,412,416,418,419,418,
+416,412,407,399,391,380,368,355,340,324,307,289,270,250,230,210,189,168,147,125,104,
+83,62,40,20,0,-20,-40,-60,-78,-97,-114,-130,-146,-161,-174,-187,-198,-209,-218,-226,-234,
+-241,-248,-254,-261,-267,-275,-283,-293,-304,-317,-331,-348,-366,-387,-410,-435,-462,-490,-521,-552,-584,
+-617,-651,-684,-717,-750,-782,-812,-842,-870,-897,-922,-947,-969,-991,-1012,-1033,-1052,-1072,-1091,-1111,-1130,
+-1150,-1171,-1193,-1215,-1237,-1261,-1285,-1309,-1334,-1359,-1385,-1410,-1435,-1460,-1484,-1508,-1531,-1554,-1575,-1596,-1617,
+-1636,-1655,-1674,-1692,-1710,-1727,-1744,-1761,-1778,-1795,-1812,-1829,-1846,-1863,-1880,-1898,-1915,-1933,-1951,-1969,-1987,
+-2006,-2025,-2045,-2064,-2085,-2106,-2128,-2151,-2174,-2198,-2223,-2249,-2276,-2303,-2332,-2360,-2389,-2419,-2448,-2477,-2507,
+-2536,-2564,-2592,-2619,-2645,-2670,-2695,-2718,-2741,-2762,-2784,-2804,-2824,-2844,-2863,-2882,-2902,-2921,-2941,-2961,-2981,
+-3001,-3022,-3043,-3064,-3085,-3106,-3127,-3147,-3168,-3188,-3207,-3226,-3244,-3261,-3278,-3294,-3310,-3325,-3341,-3356,-3371,
+-3386,-3402,-3419,-3436,-3454,-3474,-3494,-3516,-3539,-3564,-3590,-3617,-3644,-3673,-3703,-3733,-3763,-3793,-3822,-3851,-3879,
+-3906,-3932,-3955,-3977,-3997,-4015,-4031,-4045,-4056,-4066,-4073,-4079,-4084,-4087,-4090,-4092,-4094,-4096,-4099,-4102,-4107,
+-4113,-4121,-4131,-4143,-4157,-4173,-4191,-4211,-4233,-4256,-4281,-4307,-4333,-4359,-4386,-4412,-4437,-4461,-4483,-4504,-4522,
+-4539,-4553,-4565,-4575,-4583,-4589,-4593,-4596,-4597,-4598,-4598,-4597,-4597,-4597,-4597,-4598,-4599,-4601,-4603,-4606,-4610,
+-4613,-4617,-4620,-4623,-4625,-4627,-4627,-4626,-4623,-4619,-4614,-4608,-4601,-4593,-4585,-4576,-4568,-4561,-4554,-4550,-4547,
+-4546,-4547,-4551,-4558,-4566,-4577,-4589,-4603,-4618,-4632,-4647,-4660,-4671,-4679,-4684,-4686,-4683,-4675,-4662,-4644,-4621,
+-4593,-4561,-4526,-4487,-4446,-4403,-4361,-4319,-4280,-4243,-4210,-4182,-4160,-4144,-4135,-4132,-4137,-4150,-4168,-4194,-4225,
+-4261,-4301,-4344,-4390,-4437,-4484,-4530,-4575,-4618,-4657,-4693,-4724,-4752,-4775,-4794,-4809,-4819,-4827,-4831,-4833,-4832,
+-4831,-4828,-4825,-4822,-4820,-4818,-4818,-4818,-4820,-4823,-4828,-4833,-4840,-4847,-4855,-4864,-4872,-4880,-4888,-4895,-4901,
+-4906,-4911,-4915,-4917,-4919,-4919,-4919,-4918,-4917,-4915,-4912,-4909,-4906,-4902,-4898,-4894,-4890,-4885,-4881,-4876,-4871,
+-4867,-4862,-4858,-4853,-4849,-4845,-4842,-4839,-4837,-4835,-4835,-4835,-4836,-4839,-4842,-4847,-4852,-4858,-4865,-4873,-4881,
+-4890,-4899,-4907,-4916,-4924,-4932,-4939,-4945,-4950,-4955,-4958,-4961,-4963,-4964,-4965,-4966,-4966,-4965,-4965,-4966,-4966,
+-4967,-4969,-4971,-4974,-4977,-4981,-4985,-4990,-4996,-5001,-5007,-5012,-5018,-5023,-5027,-5031,-5034,-5036,-5038,-5039,-5039,
+-5038,-5037,-5036,-5033,-5031,-5028,-5026,-5023,-5021,-5018,-5016,-5014,-5013,-5012,-5011,-5010,-5009,-5008,-5007,-5007,-5005,
+-5004,-5002,-5000,-4997,-4994,-4990,-4985,-4981,-4976,-4970,-4964,-4958,-4953,-4947,-4941,-4936,-4931,-4927,-4923,-4919,-4917,
+-4915,-4913,-4912,-4912,-4911,-4912,-4912,-4913,-4913,-4913,-4913,-4913,-4912,-4911,-4909,-4906,-4902,-4898,-4893,-4887,-4880,
+-4873,-4865,-4856,-4847,-4837,-4827,-4817,-4807,-4797,-4787,-4776,-4767,-4757,-4748,-4739,-4730,-4722,-4715,-4708,-4701,-4695,
+-4690,-4684,-4680,-4675,-4671,-4668,-4665,-4662,-4659,-4656,-4654,-4651,-4649,-4647,-4645,-4643,-4640,-4638,-4635,-4633,-4630,
+-4627,-4623,-4620,-4616,-4612,-4608,-4603,-4598,-4593,-4587,-4582,-4576,-4569,-4563,-4556,-4549,-4541,-4534,-4526,-4517,-4508,
+-4499,-4490,-4480,-4470,-4459,-4448,-4436,-4424,-4412,-4399,-4386,-4372,-4359,-4345,-4332,-4318,-4305,-4291,-4279,-4266,-4254,
+-4243,-4232,-4223,-4213,-4205,-4197,-4190,-4183,-4177,-4172,-4167,-4163,-4159,-4155,-4151,-4147,-4144,-4140,-4136,-4132,-4128,
+-4124,-4120,-4115,-4110,-4105,-4100,-4094,-4089,-4083,-4077,-4070,-4063,-4056,-4049,-4041,-4033,-4024,-4015,-4006,-3995,-3985,
+-3973,-3961,-3949,-3936,-3922,-3908,-3893,-3878,-3863,-3847,-3831,-3815,-3799,-3783,-3767,-3751,-3735,-3719,-3703,-3687,-3672,
+-3657,-3641,-3626,-3611,-3597,-3582,-3568,-3553,-3539,-3525,-3511,-3497,-3484,-3471,-3458,-3445,-3433,-3421,-3410,-3399,-3389,
+-3378,-3369,-3359,-3350,-3341,-3332,-3324,-3315,-3307,-3299,-3291,-3282,-3274,-3266,-3258,-3250,-3242,-3234,-3226,-3218,-3210,
+-3203,-3195,-3188,-3180,-3173,-3166,-3159,-3152,-3145,-3138,-3130,-3123,-3115,-3107,-3099,-3091,-3082,-3074,-3065,-3056,-3047,
+-3038,-3029,-3021,-3012,-3004,-2997,-2990,-2983,-2976,-2970,-2965,-2959,-2954,-2949,-2944,-2939,-2933,-2928,-2922,-2915,-2908,
+-2900,-2891,-2882,-2872,-2861,-2849,-2837,-2825,-2812,-2799,-2786,-2773,-2761,-2749,-2737,-2726,-2716,-2706,-2698,-2690,-2684,
+-2679,-2674,-2671,-2669,-2668,-2667,-2668,-2669,-2672,-2675,-2678,-2683,-2687,-2693,-2699,-2705,-2711,-2718,-2725,-2732,-2739,
+-2745,-2752,-2758,-2764,-2769,-2774,-2778,-2782,-2785,-2787,-2789,-2790,-2790,-2791,-2791,-2790,-2790,-2790,-2789,-2789,-2790,
+-2790,-2792,-2793,-2795,-2797,-2799,-2802,-2804,-2806,-2808,-2809,-2809,-2808,-2807,-2804,-2799,-2793,-2786,-2778,-2768,-2757,
+-2745,-2732,-2719,-2705,-2691,-2677,-2663,-2650,-2638,-2626,-2616,-2606,-2597,-2590,-2583,-2578,-2573,-2569,-2565,-2561,-2557,
+-2554,-2550,-2545,-2540,-2534,-2528,-2521,-2513,-2505,-2496,-2486,-2477,-2467,-2458,-2449,-2441,-2433,-2426,-2421,-2416,-2413,
+-2411,-2410,-2411,-2413,-2417,-2421,-2426,-2433,-2440,-2447,-2456,-2464,-2472,-2481,-2489,-2497,-2505,-2512,-2519,-2525,-2530,
+-2535,-2539,-2542,-2545,-2548,-2550,-2551,-2553,-2554,-2555,-2556,-2557,-2558,-2559,-2561,-2563,-2565,-2567,-2570,-2572,-2575,
+-2577,-2580,-2582,-2583,-2584,-2584,-2583,-2581,-2579,-2575,-2569,-2563,-2555,-2547,-2537,-2527,-2516,-2504,-2493,-2481,-2469,
+-2458,-2448,-2438,-2429,-2421,-2414,-2407,-2402,-2397,-2393,-2388,-2384,-2380,-2375,-2369,-2362,-2354,-2344,-2332,-2319,-2305,
+-2288,-2270,-2251,-2231,-2210,-2189,-2168,-2148,-2128,-2110,-2094,-2079,-2067,-2057,-2050,-2046,-2044,-2044,-2046,-2050,-2056,
+-2062,-2069,-2075,-2081,-2086,-2088,-2089,-2087,-2082,-2075,-2064,-2049,-2032,-2011,-1988,-1962,-1935,-1905,-1875,-1844,-1813,
+-1782,-1753,-1725,-1699,-1676,-1655,-1637,-1622,-1610,-1601,-1595,-1591,-1590,-1591,-1594,-1599,-1604,-1610,-1616,-1621,-1626,
+-1630,-1632,-1633,-1631,-1628,-1622,-1614,-1603,-1591,-1577,-1560,-1543,-1524,-1504,-1483,-1463,-1442,-1422,-1402,-1383,-1366,
+-1350,-1335,-1323,-1311,-1302,-1294,-1288,-1283,-1280,-1278,-1276,-1275,-1275,-1275,-1274,-1274,-1272,-1271,-1268,-1265,-1262,
+-1257,-1252,-1246,-1239,-1232,-1225,-1218,-1211,-1204,-1197,-1191,-1185,-1180,-1176,-1172,-1169,-1167,-1165,-1163,-1161,-1160,
+-1159,-1157,-1155,-1153,-1150,-1147,-1143,-1138,-1133,-1127,-1120,-1113,-1106,-1098,-1091,-1084,-1076,-1070,-1064,-1058,-1053,
+-1049,-1046,-1043,-1042,-1041,-1040,-1040,-1041,-1042,-1043,-1045,-1046,-1047,-1048,-1049,-1049,-1049,-1048,-1047,-1045,-1042,
+-1039,-1036,-1032,-1028,-1024,-1019,-1032,-1028,-1024,-1020,-1015,-1011,-1006,-1000,-995,-989,-983,-977,-971,-964,-958,
+-951,-945,-938,-932,-925,-919,-913,-907,-902,-897,-892,-888,-885,-882,-879,-878,-877,-876,-876,-877,-878,
+-879,-881,-883,-885,-886,-888,-889,-890,-890,-889,-888,-885,-882,-878,-872,-865,-858,-848,-838,-827,-815,
+-802,-787,-772,-757,-741,-724,-707,-690,-672,-655,-637,-620,-603,-587,-570,-554,-539,-524,-510,-496,-482,
+-469,-457,-444,-432,-420,-408,-396,-385,-372,-360,-348,-334,-321,-307,-292,-277,-261,-244,-227,-209,-190,
+-171,-151,-132,-111,-91,-71,-51,-32,-13,5,22,39,54,69,82,93,104,112,120,126,130,
+133,135,136,136,135,133,130,127,123,119,115,110,106,101,96,91,86,81,76,71,65,
+59,53,47,41,34,27,20,14,7,0,-5,-11,-16,-21,-25,-28,-31,-32,-33,-33,-32,
+-30,-27,-24,-20,-16,-12,-8,-4,-1,1,4,6,7,7,6,5,2,0,-3,-7,-11,
+-15,-19,-23,-26,-29,-31,-33,-33,-33,-32,-30,-28,-24,-20,-16,-11,-5,0,5,11,16,
+21,26,31,35,39,43,47,51,54,57,61,65,69,73,78,83,89,94,101,107,114,
+121,128,135,142,148,155,160,166,171,175,178,181,183,185,185,185,185,183,182,180,177,
+175,172,169,166,163,161,158,156,154,153,151,150,150,150,150,151,152,153,155,157,159,
+162,165,168,171,175,179,184,188,193,198,204,210,216,222,229,236,243,250,258,265,272,
+280,286,293,299,304,309,312,315,317,317,316,314,311,306,299,292,283,273,261,249,235,
+221,206,190,173,156,139,121,102,84,65,47,28,9,-9,-28,-47,-66,-85,-103,-121,-139,
+-157,-174,-191,-207,-222,-237,-251,-264,-276,-288,-299,-309,-318,-328,-337,-346,-355,-364,-374,-385,-396,
+-409,-423,-438,-456,-474,-495,-517,-540,-565,-591,-619,-647,-677,-706,-736,-767,-797,-826,-855,-884,-911,
+-938,-964,-989,-1013,-1036,-1058,-1079,-1100,-1121,-1141,-1161,-1182,-1202,-1223,-1243,-1265,-1287,-1309,-1331,-1354,-1377,
+-1401,-1424,-1448,-1471,-1494,-1517,-1540,-1562,-1583,-1604,-1624,-1644,-1663,-1682,-1700,-1718,-1735,-1752,-1769,-1785,-1802,
+-1818,-1835,-1851,-1868,-1884,-1901,-1918,-1935,-1952,-1970,-1988,-2005,-2023,-2042,-2061,-2080,-2099,-2119,-2140,-2161,-2182,
+-2205,-2227,-2251,-2275,-2300,-2325,-2351,-2377,-2404,-2430,-2457,-2484,-2511,-2537,-2563,-2589,-2614,-2638,-2662,-2686,-2708,
+-2730,-2752,-2772,-2793,-2813,-2833,-2853,-2872,-2892,-2912,-2932,-2952,-2973,-2994,-3015,-3036,-3057,-3079,-3100,-3121,-3141,
+-3162,-3181,-3200,-3219,-3236,-3253,-3269,-3284,-3299,-3313,-3327,-3341,-3354,-3368,-3382,-3397,-3413,-3429,-3447,-3467,-3488,
+-3510,-3534,-3560,-3587,-3616,-3646,-3677,-3709,-3741,-3774,-3806,-3838,-3869,-3898,-3926,-3952,-3976,-3997,-4016,-4032,-4045,
+-4056,-4064,-4069,-4073,-4075,-4075,-4074,-4072,-4070,-4068,-4066,-4066,-4067,-4070,-4075,-4082,-4092,-4104,-4118,-4135,-4155,
+-4176,-4200,-4224,-4250,-4277,-4304,-4331,-4357,-4383,-4407,-4429,-4449,-4467,-4483,-4497,-4508,-4516,-4523,-4527,-4529,-4530,
+-4530,-4528,-4526,-4524,-4521,-4519,-4517,-4515,-4514,-4514,-4514,-4515,-4516,-4518,-4520,-4522,-4524,-4525,-4526,-4526,-4525,
+-4523,-4521,-4517,-4513,-4507,-4502,-4496,-4490,-4484,-4479,-4474,-4471,-4469,-4468,-4469,-4471,-4476,-4481,-4488,-4496,-4504,
+-4513,-4521,-4528,-4534,-4538,-4540,-4539,-4534,-4527,-4515,-4499,-4480,-4457,-4430,-4400,-4368,-4334,-4299,-4263,-4228,-4194,
+-4162,-4132,-4107,-4086,-4069,-4059,-4053,-4054,-4061,-4073,-4091,-4114,-4141,-4173,-4208,-4246,-4286,-4326,-4367,-4408,-4447,
+-4485,-4520,-4552,-4582,-4608,-4630,-4650,-4666,-4679,-4689,-4697,-4703,-4707,-4710,-4712,-4713,-4714,-4716,-4718,-4720,-4723,
+-4727,-4732,-4738,-4744,-4751,-4759,-4767,-4774,-4782,-4790,-4797,-4804,-4810,-4815,-4820,-4824,-4827,-4830,-4831,-4832,-4833,
+-4833,-4832,-4831,-4830,-4829,-4827,-4825,-4823,-4821,-4819,-4816,-4813,-4811,-4808,-4805,-4802,-4799,-4796,-4793,-4791,-4788,
+-4786,-4785,-4783,-4783,-4783,-4784,-4785,-4788,-4791,-4794,-4799,-4804,-4810,-4816,-4823,-4830,-4837,-4844,-4851,-4858,-4865,
+-4871,-4877,-4883,-4888,-4893,-4897,-4902,-4905,-4909,-4913,-4916,-4919,-4923,-4926,-4930,-4933,-4937,-4941,-4945,-4950,-4954,
+-4958,-4962,-4966,-4969,-4972,-4975,-4977,-4979,-4980,-4980,-4980,-4980,-4979,-4977,-4975,-4973,-4971,-4969,-4967,-4964,-4962,
+-4960,-4959,-4957,-4956,-4955,-4955,-4954,-4954,-4954,-4953,-4953,-4953,-4952,-4951,-4950,-4948,-4946,-4943,-4940,-4936,-4932,
+-4928,-4924,-4919,-4914,-4909,-4904,-4900,-4895,-4891,-4887,-4884,-4881,-4878,-4875,-4873,-4872,-4870,-4869,-4868,-4866,-4865,
+-4863,-4861,-4859,-4856,-4853,-4849,-4844,-4839,-4833,-4827,-4820,-4812,-4804,-4796,-4787,-4778,-4769,-4759,-4750,-4741,-4731,
+-4723,-4714,-4706,-4698,-4690,-4683,-4676,-4669,-4663,-4657,-4652,-4647,-4642,-4637,-4633,-4628,-4624,-4620,-4616,-4612,-4608,
+-4604,-4600,-4596,-4592,-4588,-4584,-4580,-4576,-4572,-4569,-4565,-4562,-4558,-4555,-4552,-4549,-4546,-4544,-4541,-4538,-4535,
+-4532,-4529,-4526,-4522,-4519,-4514,-4510,-4505,-4499,-4493,-4486,-4478,-4470,-4462,-4452,-4442,-4431,-4420,-4408,-4396,-4383,
+-4370,-4357,-4344,-4331,-4318,-4305,-4293,-4280,-4269,-4258,-4248,-4238,-4229,-4221,-4214,-4208,-4202,-4196,-4192,-4188,-4184,
+-4180,-4177,-4174,-4171,-4167,-4164,-4160,-4156,-4152,-4147,-4142,-4136,-4130,-4124,-4117,-4110,-4102,-4094,-4085,-4076,-4067,
+-4058,-4048,-4038,-4028,-4017,-4006,-3995,-3984,-3972,-3959,-3947,-3934,-3921,-3907,-3893,-3878,-3864,-3849,-3834,-3819,-3804,
+-3789,-3774,-3759,-3745,-3730,-3716,-3702,-3689,-3676,-3663,-3651,-3639,-3627,-3615,-3603,-3592,-3580,-3568,-3557,-3545,-3533,
+-3521,-3509,-3497,-3484,-3472,-3460,-3447,-3435,-3422,-3411,-3399,-3387,-3376,-3366,-3355,-3346,-3336,-3327,-3319,-3311,-3303,
+-3296,-3289,-3282,-3275,-3268,-3261,-3254,-3247,-3240,-3233,-3225,-3217,-3209,-3201,-3193,-3184,-3175,-3166,-3157,-3147,-3138,
+-3129,-3120,-3111,-3102,-3093,-3085,-3077,-3069,-3062,-3055,-3048,-3042,-3036,-3031,-3026,-3021,-3016,-3012,-3008,-3004,-3000,
+-2996,-2992,-2988,-2983,-2979,-2974,-2969,-2963,-2956,-2950,-2942,-2934,-2926,-2917,-2908,-2898,-2888,-2878,-2868,-2857,-2846,
+-2836,-2825,-2815,-2806,-2796,-2787,-2779,-2771,-2764,-2757,-2751,-2746,-2741,-2738,-2735,-2732,-2731,-2730,-2730,-2731,-2732,
+-2735,-2738,-2741,-2745,-2750,-2756,-2762,-2768,-2775,-2782,-2789,-2796,-2802,-2809,-2815,-2821,-2826,-2830,-2834,-2837,-2838,
+-2839,-2839,-2839,-2837,-2835,-2832,-2829,-2825,-2822,-2818,-2815,-2812,-2809,-2808,-2807,-2806,-2807,-2808,-2809,-2812,-2814,
+-2817,-2820,-2823,-2826,-2828,-2829,-2830,-2829,-2827,-2824,-2820,-2814,-2807,-2799,-2790,-2779,-2768,-2756,-2744,-2731,-2718,
+-2706,-2694,-2682,-2671,-2661,-2652,-2643,-2636,-2629,-2623,-2618,-2613,-2608,-2604,-2600,-2596,-2591,-2586,-2581,-2575,-2569,
+-2562,-2555,-2547,-2539,-2531,-2522,-2514,-2505,-2497,-2490,-2483,-2477,-2472,-2468,-2466,-2464,-2464,-2465,-2467,-2470,-2474,
+-2479,-2485,-2491,-2498,-2505,-2512,-2519,-2525,-2532,-2537,-2542,-2546,-2550,-2553,-2554,-2555,-2556,-2555,-2555,-2553,-2552,
+-2550,-2548,-2546,-2544,-2543,-2542,-2541,-2540,-2540,-2540,-2541,-2541,-2542,-2543,-2543,-2543,-2543,-2542,-2541,-2538,-2535,
+-2530,-2525,-2519,-2511,-2503,-2494,-2485,-2475,-2465,-2455,-2446,-2437,-2428,-2420,-2413,-2408,-2403,-2400,-2397,-2395,-2394,
+-2394,-2394,-2394,-2393,-2392,-2390,-2387,-2382,-2375,-2367,-2356,-2343,-2328,-2312,-2293,-2272,-2250,-2228,-2204,-2181,-2158,
+-2135,-2114,-2095,-2077,-2062,-2049,-2038,-2030,-2025,-2022,-2022,-2023,-2026,-2030,-2035,-2040,-2045,-2049,-2051,-2052,-2051,
+-2047,-2040,-2031,-2019,-2003,-1986,-1965,-1943,-1918,-1892,-1865,-1838,-1811,-1785,-1759,-1735,-1713,-1693,-1676,-1662,-1650,
+-1641,-1635,-1631,-1630,-1631,-1634,-1638,-1642,-1648,-1653,-1658,-1662,-1665,-1666,-1665,-1662,-1657,-1649,-1639,-1626,-1611,
+-1594,-1575,-1554,-1532,-1508,-1484,-1460,-1436,-1412,-1389,-1367,-1347,-1328,-1310,-1294,-1281,-1269,-1258,-1250,-1243,-1238,
+-1234,-1231,-1228,-1227,-1225,-1224,-1222,-1221,-1218,-1216,-1212,-1208,-1203,-1198,-1191,-1185,-1177,-1170,-1162,-1154,-1147,
+-1140,-1133,-1126,-1120,-1115,-1111,-1107,-1104,-1102,-1100,-1099,-1098,-1097,-1097,-1096,-1096,-1095,-1094,-1092,-1090,-1087,
+-1084,-1080,-1076,-1071,-1066,-1061,-1056,-1050,-1045,-1040,-1035,-1031,-1027,-1024,-1022,-1020,-1019,-1019,-1019,-1020,-1021,
+-1023,-1025,-1027,-1030,-1033,-1035,-1037,-1039,-1041,-1042,-1043,-1043,-1043,-1043,-1041,-1040,-1037,-1035,-1032,-1064,-1062,
+-1059,-1056,-1052,-1048,-1044,-1039,-1033,-1028,-1022,-1016,-1010,-1004,-998,-992,-986,-981,-975,-970,-966,-961,-957,
+-954,-951,-948,-946,-944,-943,-942,-941,-941,-941,-942,-942,-942,-943,-943,-943,-943,-942,-941,-939,-936,
+-933,-929,-925,-920,-914,-907,-900,-892,-883,-874,-865,-855,-845,-835,-824,-813,-803,-792,-781,-771,-761,
+-751,-741,-731,-721,-712,-702,-693,-683,-674,-664,-654,-644,-634,-623,-611,-599,-587,-574,-560,-545,-530,
+-514,-496,-479,-460,-440,-420,-399,-377,-355,-332,-309,-285,-261,-237,-213,-189,-165,-142,-119,-97,-75,
+-55,-36,-17,0,15,29,42,53,63,72,79,85,90,93,96,97,98,97,96,95,93,
+91,88,85,81,78,74,70,66,62,57,52,47,41,35,28,22,14,7,0,-9,-17,
+-26,-34,-43,-51,-59,-67,-74,-81,-87,-92,-96,-100,-103,-105,-107,-108,-109,-109,-109,-108,-108,
+-108,-108,-108,-109,-110,-111,-113,-115,-118,-121,-124,-127,-131,-134,-137,-140,-143,-145,-146,-147,-147,
+-146,-145,-143,-140,-137,-133,-128,-124,-119,-113,-108,-102,-97,-91,-86,-80,-75,-70,-65,-60,-54,
+-49,-43,-37,-31,-25,-18,-10,-3,5,13,22,32,41,51,60,69,78,87,94,101,108,
+113,117,120,122,123,123,122,120,117,113,109,104,98,93,87,82,77,72,67,63,60,
+57,56,55,55,55,56,59,61,65,69,73,78,83,88,94,100,105,111,117,123,129,
+135,141,147,153,159,164,170,175,181,186,190,195,199,202,205,207,209,209,209,208,206,
+202,198,192,185,177,168,158,148,136,123,110,96,82,68,53,38,23,8,-6,-21,-36,
+-50,-65,-79,-93,-107,-121,-135,-149,-163,-177,-191,-205,-220,-234,-249,-263,-278,-292,-307,-322,-336,
+-351,-365,-379,-393,-407,-421,-435,-449,-463,-477,-492,-507,-522,-538,-555,-572,-590,-609,-629,-650,-671,
+-693,-716,-740,-764,-789,-814,-839,-864,-890,-915,-940,-965,-990,-1015,-1039,-1063,-1086,-1110,-1133,-1155,-1178,
+-1200,-1223,-1245,-1268,-1290,-1313,-1336,-1359,-1381,-1404,-1427,-1450,-1473,-1496,-1518,-1540,-1562,-1584,-1604,-1625,-1645,
+-1664,-1684,-1702,-1720,-1738,-1755,-1772,-1789,-1806,-1822,-1839,-1855,-1872,-1888,-1905,-1922,-1939,-1956,-1973,-1991,-2008,
+-2026,-2044,-2061,-2079,-2097,-2116,-2134,-2153,-2171,-2190,-2209,-2229,-2248,-2268,-2289,-2309,-2330,-2352,-2373,-2395,-2418,
+-2440,-2463,-2485,-2508,-2531,-2554,-2576,-2599,-2621,-2643,-2665,-2686,-2707,-2728,-2748,-2769,-2789,-2809,-2829,-2849,-2869,
+-2890,-2910,-2931,-2952,-2973,-2994,-3015,-3037,-3058,-3080,-3101,-3122,-3142,-3162,-3182,-3201,-3219,-3236,-3253,-3269,-3285,
+-3300,-3315,-3329,-3343,-3357,-3372,-3387,-3403,-3420,-3438,-3457,-3478,-3500,-3524,-3549,-3576,-3604,-3634,-3665,-3696,-3729,
+-3761,-3793,-3825,-3856,-3886,-3914,-3940,-3964,-3986,-4004,-4020,-4033,-4043,-4051,-4055,-4057,-4057,-4055,-4052,-4047,-4042,
+-4037,-4032,-4028,-4025,-4024,-4024,-4027,-4033,-4040,-4051,-4064,-4080,-4098,-4119,-4141,-4165,-4189,-4215,-4241,-4266,-4291,
+-4314,-4336,-4356,-4374,-4390,-4404,-4414,-4423,-4428,-4432,-4433,-4433,-4430,-4427,-4423,-4417,-4412,-4407,-4401,-4397,-4393,
+-4390,-4387,-4386,-4386,-4386,-4388,-4390,-4392,-4395,-4398,-4401,-4403,-4406,-4407,-4408,-4408,-4407,-4406,-4404,-4401,-4398,
+-4395,-4392,-4388,-4385,-4382,-4380,-4378,-4377,-4376,-4376,-4376,-4377,-4378,-4379,-4379,-4379,-4378,-4375,-4371,-4366,-4358,
+-4349,-4337,-4323,-4307,-4288,-4268,-4247,-4224,-4201,-4177,-4153,-4130,-4109,-4089,-4072,-4057,-4046,-4038,-4034,-4034,-4038,
+-4046,-4058,-4074,-4093,-4116,-4141,-4169,-4198,-4229,-4260,-4292,-4323,-4354,-4384,-4412,-4439,-4464,-4486,-4507,-4525,-4542,
+-4556,-4569,-4580,-4589,-4598,-4605,-4612,-4618,-4624,-4629,-4635,-4641,-4646,-4652,-4659,-4665,-4671,-4677,-4684,-4690,-4696,
+-4701,-4707,-4711,-4716,-4719,-4723,-4726,-4728,-4730,-4732,-4733,-4734,-4736,-4737,-4738,-4739,-4741,-4743,-4744,-4746,-4748,
+-4750,-4753,-4755,-4757,-4759,-4761,-4763,-4764,-4765,-4766,-4767,-4767,-4767,-4767,-4767,-4766,-4765,-4765,-4764,-4764,-4764,
+-4764,-4764,-4765,-4767,-4768,-4770,-4773,-4776,-4780,-4783,-4788,-4792,-4797,-4802,-4807,-4812,-4818,-4823,-4829,-4834,-4839,
+-4845,-4850,-4856,-4861,-4867,-4872,-4877,-4882,-4887,-4892,-4896,-4900,-4904,-4908,-4912,-4915,-4917,-4920,-4921,-4923,-4924,
+-4924,-4924,-4924,-4923,-4922,-4921,-4919,-4918,-4916,-4914,-4913,-4911,-4910,-4908,-4907,-4906,-4904,-4903,-4903,-4902,-4901,
+-4900,-4899,-4898,-4897,-4895,-4894,-4892,-4890,-4887,-4885,-4882,-4879,-4876,-4873,-4870,-4866,-4863,-4860,-4857,-4855,-4853,
+-4851,-4849,-4847,-4846,-4845,-4845,-4844,-4844,-4843,-4843,-4842,-4841,-4839,-4837,-4835,-4832,-4828,-4824,-4819,-4814,-4807,
+-4800,-4793,-4785,-4776,-4767,-4758,-4748,-4738,-4729,-4719,-4709,-4700,-4691,-4682,-4674,-4666,-4659,-4652,-4646,-4640,-4634,
+-4629,-4624,-4620,-4615,-4611,-4607,-4603,-4599,-4595,-4591,-4587,-4582,-4578,-4573,-4568,-4563,-4558,-4552,-4547,-4541,-4535,
+-4530,-4524,-4519,-4513,-4508,-4503,-4498,-4494,-4489,-4485,-4482,-4478,-4474,-4471,-4468,-4465,-4461,-4458,-4454,-4450,-4446,
+-4442,-4437,-4431,-4425,-4419,-4412,-4404,-4396,-4387,-4378,-4368,-4358,-4347,-4337,-4326,-4315,-4305,-4294,-4284,-4274,-4265,
+-4256,-4248,-4240,-4233,-4227,-4221,-4216,-4212,-4208,-4205,-4202,-4200,-4197,-4195,-4193,-4191,-4188,-4186,-4183,-4180,-4176,
+-4171,-4167,-4161,-4155,-4148,-4141,-4133,-4124,-4115,-4106,-4095,-4085,-4074,-4062,-4050,-4037,-4024,-4011,-3997,-3983,-3969,
+-3954,-3939,-3924,-3908,-3893,-3877,-3861,-3845,-3829,-3814,-3798,-3783,-3768,-3753,-3739,-3725,-3712,-3700,-3688,-3676,-3665,
+-3655,-3645,-3636,-3627,-3618,-3609,-3601,-3593,-3584,-3576,-3567,-3558,-3549,-3539,-3529,-3519,-3508,-3497,-3486,-3475,-3463,
+-3451,-3440,-3428,-3416,-3405,-3394,-3383,-3372,-3362,-3352,-3343,-3333,-3324,-3315,-3306,-3297,-3288,-3279,-3270,-3260,-3250,
+-3240,-3229,-3219,-3207,-3195,-3183,-3170,-3157,-3144,-3131,-3118,-3105,-3092,-3080,-3067,-3056,-3045,-3035,-3026,-3017,-3010,
+-3003,-2998,-2993,-2989,-2986,-2984,-2982,-2981,-2980,-2980,-2979,-2979,-2979,-2978,-2977,-2976,-2975,-2973,-2970,-2967,-2963,
+-2958,-2953,-2947,-2941,-2934,-2927,-2920,-2912,-2904,-2897,-2889,-2881,-2873,-2866,-2859,-2852,-2846,-2839,-2834,-2828,-2823,
+-2819,-2815,-2811,-2808,-2805,-2803,-2801,-2800,-2800,-2799,-2800,-2801,-2803,-2805,-2809,-2812,-2817,-2822,-2828,-2835,-2842,
+-2849,-2857,-2865,-2873,-2881,-2888,-2895,-2902,-2908,-2913,-2917,-2919,-2921,-2922,-2921,-2919,-2917,-2913,-2908,-2902,-2896,
+-2890,-2883,-2877,-2870,-2864,-2858,-2853,-2849,-2846,-2843,-2842,-2841,-2841,-2842,-2843,-2845,-2848,-2850,-2852,-2854,-2855,
+-2856,-2856,-2856,-2854,-2851,-2847,-2843,-2837,-2831,-2823,-2815,-2807,-2798,-2789,-2780,-2771,-2762,-2753,-2745,-2738,-2730,
+-2724,-2718,-2712,-2706,-2701,-2696,-2691,-2686,-2681,-2676,-2670,-2663,-2656,-2648,-2640,-2631,-2621,-2611,-2601,-2590,-2579,
+-2569,-2558,-2548,-2538,-2529,-2521,-2513,-2507,-2502,-2498,-2495,-2493,-2493,-2493,-2495,-2498,-2501,-2505,-2509,-2514,-2519,
+-2523,-2528,-2532,-2536,-2540,-2543,-2545,-2546,-2547,-2547,-2546,-2545,-2543,-2540,-2537,-2534,-2530,-2526,-2522,-2517,-2513,
+-2507,-2502,-2497,-2491,-2485,-2478,-2471,-2464,-2456,-2447,-2438,-2429,-2419,-2408,-2397,-2386,-2375,-2365,-2354,-2344,-2334,
+-2326,-2318,-2312,-2307,-2304,-2302,-2302,-2304,-2307,-2311,-2316,-2323,-2330,-2338,-2345,-2353,-2359,-2365,-2368,-2371,-2370,
+-2368,-2363,-2355,-2345,-2332,-2316,-2298,-2277,-2255,-2231,-2206,-2180,-2154,-2128,-2103,-2079,-2056,-2035,-2017,-2000,-1986,
+-1975,-1966,-1959,-1954,-1952,-1950,-1950,-1951,-1952,-1953,-1953,-1953,-1951,-1948,-1943,-1937,-1928,-1918,-1906,-1892,-1877,
+-1861,-1843,-1825,-1807,-1789,-1772,-1756,-1741,-1728,-1716,-1707,-1700,-1695,-1692,-1691,-1692,-1694,-1698,-1703,-1708,-1714,
+-1720,-1725,-1729,-1731,-1732,-1731,-1727,-1722,-1713,-1702,-1689,-1673,-1654,-1633,-1611,-1587,-1561,-1534,-1507,-1480,-1453,
+-1426,-1400,-1375,-1352,-1330,-1310,-1291,-1275,-1260,-1247,-1237,-1227,-1220,-1213,-1208,-1203,-1200,-1196,-1193,-1190,-1187,
+-1184,-1180,-1175,-1170,-1165,-1159,-1152,-1145,-1137,-1129,-1121,-1113,-1105,-1097,-1090,-1083,-1076,-1070,-1065,-1060,-1057,
+-1053,-1051,-1049,-1047,-1046,-1046,-1045,-1045,-1045,-1045,-1044,-1044,-1043,-1042,-1041,-1039,-1037,-1035,-1033,-1030,-1028,
+-1025,-1023,-1021,-1019,-1018,-1017,-1016,-1016,-1016,-1017,-1019,-1021,-1023,-1026,-1029,-1033,-1037,-1040,-1044,-1048,-1052,
+-1055,-1058,-1061,-1063,-1065,-1067,-1067,-1067,-1067,-1066,-1064,-1120,-1118,-1116,-1114,-1110,-1106,-1102,-1096,-1091,-1085,
+-1079,-1072,-1066,-1059,-1053,-1047,-1041,-1035,-1030,-1025,-1021,-1017,-1014,-1012,-1010,-1008,-1007,-1007,-1007,-1007,-1007,
+-1008,-1008,-1009,-1009,-1009,-1008,-1007,-1006,-1003,-1001,-997,-993,-988,-982,-975,-968,-961,-953,-945,-936,-927,
+-919,-910,-901,-893,-885,-878,-871,-865,-859,-854,-849,-845,-842,-838,-835,-832,-830,-827,-824,-821,-817,
+-812,-807,-801,-794,-786,-776,-766,-754,-741,-726,-710,-692,-674,-654,-632,-610,-586,-562,-537,-511,-484,
+-457,-430,-402,-374,-347,-319,-292,-266,-240,-215,-190,-167,-144,-123,-103,-84,-66,-49,-34,-21,-8,
+2,12,21,29,35,41,45,49,52,54,55,56,56,56,55,53,52,49,47,44,40,
+36,32,27,22,16,9,2,-4,-12,-20,-29,-38,-48,-57,-67,-77,-87,-97,-107,-116,-125,
+-134,-143,-151,-158,-165,-172,-179,-185,-190,-195,-200,-205,-210,-215,-219,-224,-228,-233,-238,-242,-247,
+-251,-256,-260,-264,-268,-271,-274,-276,-278,-280,-280,-280,-280,-279,-277,-275,-272,-269,-265,-261,-256,
+-252,-247,-242,-237,-231,-226,-221,-215,-210,-204,-198,-192,-186,-179,-172,-165,-157,-148,-139,-129,-119,
+-108,-97,-86,-75,-63,-52,-40,-30,-19,-10,-1,6,13,19,23,26,28,29,28,26,23,
+19,14,8,2,-3,-10,-17,-23,-29,-35,-40,-44,-47,-49,-51,-51,-51,-49,-46,-43,-38,
+-33,-27,-21,-14,-7,0,8,16,24,31,39,47,54,61,68,75,81,87,92,97,102,
+106,109,112,114,115,116,115,114,112,109,105,100,94,86,78,68,58,47,34,22,8,
+-5,-19,-34,-49,-63,-78,-92,-106,-120,-133,-146,-158,-170,-181,-191,-201,-211,-221,-230,-239,-249,
+-258,-268,-278,-288,-299,-311,-323,-336,-349,-364,-378,-394,-410,-426,-443,-461,-479,-497,-515,-534,-553,
+-571,-590,-609,-628,-647,-666,-685,-703,-722,-741,-760,-779,-798,-817,-836,-855,-875,-895,-915,-935,-955,
+-976,-997,-1018,-1039,-1061,-1083,-1106,-1128,-1151,-1175,-1198,-1222,-1246,-1271,-1296,-1321,-1346,-1371,-1396,-1421,-1446,
+-1471,-1495,-1520,-1544,-1567,-1590,-1613,-1634,-1656,-1676,-1697,-1716,-1735,-1754,-1771,-1789,-1806,-1823,-1839,-1856,-1872,
+-1888,-1904,-1920,-1937,-1953,-1969,-1986,-2003,-2020,-2037,-2054,-2072,-2089,-2106,-2124,-2141,-2159,-2176,-2194,-2211,-2229,
+-2246,-2263,-2281,-2298,-2315,-2333,-2351,-2368,-2386,-2405,-2423,-2441,-2460,-2479,-2498,-2517,-2537,-2556,-2576,-2595,-2615,
+-2635,-2654,-2674,-2694,-2714,-2733,-2753,-2773,-2793,-2812,-2832,-2853,-2873,-2893,-2914,-2934,-2955,-2976,-2997,-3018,-3039,
+-3060,-3081,-3102,-3122,-3142,-3162,-3181,-3199,-3217,-3235,-3252,-3268,-3285,-3301,-3316,-3332,-3348,-3364,-3381,-3398,-3416,
+-3435,-3456,-3477,-3499,-3523,-3549,-3575,-3603,-3632,-3661,-3692,-3723,-3754,-3785,-3815,-3845,-3874,-3901,-3926,-3950,-3971,
+-3989,-4005,-4018,-4028,-4036,-4040,-4043,-4043,-4041,-4037,-4032,-4027,-4020,-4014,-4008,-4003,-3999,-3997,-3996,-3997,-4001,
+-4008,-4016,-4027,-4040,-4056,-4073,-4092,-4112,-4133,-4155,-4177,-4198,-4219,-4238,-4256,-4273,-4288,-4300,-4310,-4318,-4324,
+-4327,-4328,-4328,-4325,-4321,-4316,-4310,-4304,-4297,-4291,-4285,-4279,-4274,-4270,-4267,-4265,-4264,-4264,-4266,-4268,-4270,
+-4274,-4277,-4281,-4285,-4288,-4291,-4294,-4295,-4296,-4297,-4296,-4294,-4292,-4289,-4285,-4280,-4275,-4270,-4264,-4258,-4252,
+-4246,-4240,-4234,-4228,-4222,-4216,-4210,-4203,-4197,-4190,-4182,-4174,-4166,-4157,-4147,-4136,-4125,-4113,-4101,-4089,-4077,
+-4065,-4053,-4042,-4032,-4023,-4015,-4009,-4006,-4004,-4005,-4008,-4013,-4021,-4032,-4044,-4059,-4077,-4096,-4116,-4138,-4161,
+-4185,-4210,-4234,-4259,-4283,-4307,-4330,-4352,-4373,-4393,-4412,-4429,-4446,-4461,-4475,-4488,-4501,-4512,-4523,-4533,-4543,
+-4552,-4561,-4569,-4577,-4584,-4592,-4598,-4605,-4611,-4616,-4621,-4626,-4630,-4633,-4636,-4639,-4641,-4643,-4644,-4645,-4646,
+-4646,-4647,-4648,-4649,-4650,-4652,-4654,-4657,-4660,-4663,-4667,-4672,-4676,-4682,-4687,-4693,-4698,-4704,-4710,-4715,-4720,
+-4725,-4729,-4733,-4737,-4739,-4742,-4743,-4744,-4745,-4745,-4745,-4744,-4743,-4742,-4742,-4741,-4740,-4739,-4738,-4738,-4738,
+-4738,-4739,-4740,-4742,-4744,-4746,-4749,-4752,-4755,-4759,-4763,-4767,-4772,-4776,-4781,-4786,-4791,-4796,-4801,-4806,-4810,
+-4815,-4820,-4824,-4828,-4832,-4836,-4840,-4843,-4846,-4849,-4851,-4853,-4855,-4856,-4857,-4858,-4859,-4859,-4860,-4860,-4860,
+-4859,-4859,-4859,-4858,-4858,-4857,-4857,-4856,-4855,-4854,-4854,-4853,-4851,-4850,-4849,-4847,-4846,-4844,-4842,-4840,-4838,
+-4835,-4833,-4831,-4828,-4826,-4824,-4822,-4820,-4819,-4818,-4817,-4817,-4816,-4817,-4817,-4818,-4819,-4820,-4822,-4823,-4825,
+-4826,-4827,-4828,-4829,-4829,-4828,-4827,-4825,-4823,-4819,-4815,-4810,-4804,-4797,-4789,-4781,-4772,-4763,-4752,-4742,-4731,
+-4720,-4709,-4698,-4687,-4676,-4665,-4655,-4645,-4636,-4627,-4619,-4611,-4604,-4598,-4592,-4586,-4581,-4576,-4572,-4568,-4564,
+-4561,-4557,-4554,-4550,-4547,-4543,-4539,-4535,-4530,-4526,-4521,-4515,-4510,-4504,-4498,-4491,-4484,-4478,-4471,-4464,-4457,
+-4450,-4442,-4435,-4429,-4422,-4415,-4409,-4402,-4396,-4390,-4384,-4378,-4372,-4366,-4361,-4355,-4349,-4343,-4337,-4331,-4325,
+-4319,-4313,-4306,-4300,-4294,-4287,-4281,-4275,-4268,-4262,-4257,-4251,-4246,-4241,-4237,-4233,-4229,-4226,-4223,-4220,-4218,
+-4216,-4215,-4213,-4212,-4211,-4210,-4209,-4208,-4207,-4205,-4203,-4201,-4198,-4195,-4191,-4187,-4182,-4176,-4170,-4163,-4156,
+-4147,-4138,-4129,-4118,-4107,-4095,-4083,-4070,-4056,-4042,-4027,-4012,-3997,-3981,-3964,-3948,-3931,-3914,-3897,-3880,-3863,
+-3847,-3831,-3815,-3799,-3784,-3770,-3756,-3743,-3731,-3719,-3707,-3697,-3687,-3677,-3668,-3660,-3651,-3643,-3635,-3627,-3619,
+-3611,-3602,-3594,-3585,-3575,-3565,-3555,-3544,-3533,-3522,-3510,-3498,-3485,-3473,-3460,-3447,-3435,-3422,-3410,-3398,-3386,
+-3374,-3362,-3350,-3339,-3327,-3316,-3304,-3292,-3280,-3268,-3255,-3242,-3229,-3215,-3200,-3185,-3170,-3154,-3137,-3120,-3104,
+-3087,-3070,-3053,-3037,-3021,-3006,-2992,-2979,-2967,-2956,-2946,-2938,-2932,-2926,-2922,-2920,-2918,-2918,-2919,-2921,-2924,
+-2927,-2931,-2936,-2940,-2945,-2949,-2953,-2957,-2960,-2962,-2964,-2966,-2966,-2966,-2965,-2964,-2962,-2959,-2956,-2952,-2948,
+-2944,-2940,-2936,-2931,-2927,-2922,-2918,-2913,-2909,-2905,-2901,-2898,-2894,-2891,-2888,-2885,-2882,-2879,-2877,-2875,-2873,
+-2872,-2872,-2872,-2872,-2874,-2876,-2879,-2883,-2887,-2893,-2899,-2906,-2914,-2922,-2931,-2940,-2949,-2959,-2968,-2977,-2985,
+-2992,-2999,-3004,-3009,-3012,-3014,-3014,-3013,-3010,-3006,-3001,-2994,-2987,-2978,-2969,-2960,-2950,-2941,-2931,-2922,-2914,
+-2906,-2899,-2893,-2888,-2884,-2881,-2878,-2877,-2877,-2877,-2878,-2879,-2880,-2882,-2883,-2885,-2886,-2886,-2886,-2886,-2884,
+-2883,-2880,-2877,-2873,-2869,-2865,-2860,-2855,-2849,-2844,-2838,-2833,-2827,-2821,-2816,-2811,-2805,-2800,-2794,-2788,-2782,
+-2776,-2769,-2762,-2754,-2745,-2736,-2726,-2715,-2704,-2692,-2679,-2666,-2653,-2639,-2626,-2612,-2599,-2586,-2574,-2562,-2551,
+-2541,-2533,-2525,-2518,-2513,-2509,-2506,-2505,-2504,-2505,-2506,-2509,-2511,-2515,-2518,-2522,-2526,-2530,-2534,-2537,-2539,
+-2541,-2543,-2543,-2542,-2541,-2538,-2535,-2530,-2524,-2518,-2510,-2500,-2490,-2479,-2466,-2453,-2439,-2423,-2407,-2390,-2373,
+-2355,-2337,-2318,-2300,-2281,-2264,-2246,-2230,-2215,-2201,-2188,-2177,-2169,-2162,-2158,-2156,-2156,-2159,-2164,-2171,-2181,
+-2192,-2205,-2219,-2234,-2250,-2266,-2281,-2296,-2309,-2321,-2331,-2338,-2343,-2344,-2343,-2338,-2330,-2319,-2304,-2286,-2266,
+-2243,-2219,-2192,-2164,-2136,-2107,-2079,-2051,-2024,-1998,-1974,-1952,-1932,-1915,-1899,-1886,-1875,-1866,-1859,-1853,-1849,
+-1845,-1843,-1840,-1838,-1836,-1833,-1829,-1825,-1820,-1815,-1808,-1801,-1793,-1784,-1775,-1766,-1758,-1749,-1742,-1735,-1730,
+-1725,-1722,-1721,-1721,-1723,-1726,-1731,-1736,-1743,-1750,-1758,-1765,-1772,-1779,-1784,-1788,-1790,-1791,-1789,-1784,-1777,
+-1767,-1754,-1739,-1721,-1700,-1678,-1653,-1627,-1599,-1570,-1540,-1510,-1480,-1450,-1421,-1393,-1366,-1340,-1316,-1294,-1274,
+-1256,-1240,-1226,-1214,-1203,-1194,-1186,-1180,-1175,-1170,-1166,-1163,-1159,-1156,-1153,-1150,-1146,-1142,-1137,-1132,-1127,
+-1121,-1115,-1109,-1102,-1096,-1089,-1082,-1076,-1070,-1064,-1059,-1054,-1049,-1046,-1042,-1040,-1038,-1036,-1035,-1034,-1034,
+-1034,-1034,-1034,-1034,-1035,-1035,-1036,-1036,-1036,-1036,-1036,-1036,-1036,-1037,-1037,-1037,-1037,-1038,-1039,-1040,-1042,
+-1043,-1046,-1048,-1051,-1055,-1059,-1063,-1067,-1072,-1077,-1082,-1087,-1092,-1097,-1101,-1105,-1109,-1113,-1115,-1118,-1119,
+-1120,-1120,-1120,-1174,-1174,-1173,-1171,-1169,-1166,-1162,-1157,-1152,-1147,-1141,-1135,-1128,-1122,-1115,-1109,-1103,-1097,
+-1092,-1087,-1083,-1079,-1076,-1074,-1071,-1070,-1069,-1068,-1068,-1068,-1068,-1068,-1067,-1067,-1066,-1065,-1063,-1061,-1058,
+-1054,-1049,-1044,-1038,-1031,-1024,-1016,-1008,-999,-990,-981,-973,-964,-956,-948,-941,-935,-929,-924,-920,-917,
+-915,-914,-913,-913,-914,-915,-917,-918,-920,-921,-921,-921,-921,-919,-916,-911,-906,-898,-889,-878,-866,
+-852,-836,-818,-798,-778,-755,-731,-707,-681,-654,-626,-598,-569,-541,-512,-483,-454,-426,-398,-371,-344,
+-319,-294,-270,-247,-225,-204,-184,-165,-148,-131,-115,-101,-88,-75,-64,-54,-44,-36,-28,-22,-16,
+-11,-6,-3,0,1,3,4,4,3,2,1,-1,-4,-7,-11,-16,-21,-27,-34,-40,-48,
+-55,-63,-72,-81,-90,-99,-108,-118,-127,-137,-147,-157,-166,-176,-185,-195,-204,-213,-222,-231,-240,
+-249,-258,-266,-275,-283,-291,-300,-308,-315,-323,-330,-338,-344,-351,-357,-362,-367,-371,-375,-378,-381,
+-382,-384,-384,-384,-383,-382,-380,-377,-375,-371,-368,-364,-360,-356,-352,-348,-343,-339,-334,-330,-325,
+-320,-315,-310,-304,-298,-291,-284,-276,-268,-259,-250,-240,-229,-219,-207,-196,-184,-172,-161,-150,-139,
+-128,-118,-110,-102,-95,-89,-84,-81,-79,-78,-78,-80,-82,-86,-90,-95,-100,-106,-112,-118,-124,
+-129,-134,-138,-142,-144,-146,-147,-147,-145,-143,-140,-136,-132,-126,-120,-113,-106,-98,-91,-83,-75,
+-67,-59,-51,-43,-36,-29,-22,-16,-11,-6,-1,2,6,8,11,12,12,12,11,9,6,
+2,-2,-8,-15,-23,-32,-41,-52,-64,-76,-89,-103,-117,-131,-146,-160,-175,-189,-203,-216,-229,
+-242,-254,-265,-276,-286,-295,-304,-312,-320,-328,-335,-342,-350,-357,-365,-373,-382,-392,-402,-413,-426,
+-439,-453,-468,-483,-500,-518,-536,-555,-575,-595,-615,-635,-656,-677,-697,-718,-738,-757,-777,-796,-814,
+-832,-850,-867,-884,-900,-917,-933,-949,-965,-980,-997,-1013,-1030,-1047,-1064,-1082,-1101,-1120,-1140,-1161,-1183,
+-1205,-1228,-1251,-1275,-1300,-1325,-1350,-1376,-1402,-1428,-1455,-1481,-1507,-1532,-1558,-1583,-1607,-1631,-1654,-1677,-1698,
+-1720,-1740,-1760,-1779,-1798,-1816,-1833,-1851,-1867,-1884,-1900,-1916,-1932,-1948,-1964,-1980,-1996,-2012,-2028,-2044,-2060,
+-2077,-2093,-2110,-2126,-2143,-2160,-2176,-2193,-2209,-2226,-2242,-2258,-2274,-2290,-2306,-2322,-2338,-2354,-2370,-2386,-2402,
+-2418,-2435,-2451,-2468,-2485,-2502,-2520,-2537,-2555,-2573,-2591,-2610,-2628,-2647,-2665,-2684,-2703,-2722,-2741,-2760,-2780,
+-2799,-2818,-2838,-2858,-2877,-2897,-2917,-2937,-2957,-2977,-2997,-3017,-3037,-3056,-3076,-3095,-3114,-3132,-3150,-3168,-3185,
+-3203,-3219,-3236,-3252,-3268,-3284,-3300,-3316,-3333,-3350,-3367,-3385,-3404,-3423,-3444,-3466,-3489,-3512,-3537,-3563,-3590,
+-3618,-3646,-3675,-3704,-3734,-3762,-3791,-3818,-3845,-3870,-3893,-3915,-3934,-3952,-3967,-3979,-3989,-3997,-4003,-4006,-4007,
+-4007,-4005,-4002,-3997,-3993,-3988,-3983,-3979,-3975,-3973,-3972,-3972,-3975,-3978,-3984,-3992,-4002,-4013,-4025,-4040,-4055,
+-4071,-4087,-4104,-4121,-4137,-4152,-4167,-4181,-4193,-4203,-4212,-4219,-4225,-4229,-4231,-4231,-4231,-4228,-4225,-4222,-4217,
+-4212,-4207,-4202,-4198,-4193,-4189,-4186,-4184,-4182,-4181,-4181,-4181,-4181,-4183,-4184,-4185,-4187,-4188,-4189,-4190,-4190,
+-4190,-4188,-4186,-4184,-4180,-4176,-4171,-4165,-4158,-4151,-4144,-4136,-4128,-4119,-4110,-4101,-4092,-4083,-4074,-4065,-4056,
+-4047,-4038,-4029,-4020,-4010,-4001,-3992,-3984,-3975,-3966,-3958,-3950,-3943,-3936,-3931,-3926,-3922,-3919,-3917,-3917,-3919,
+-3922,-3926,-3932,-3940,-3950,-3961,-3974,-3989,-4004,-4021,-4039,-4058,-4078,-4098,-4119,-4140,-4161,-4181,-4202,-4222,-4241,
+-4260,-4278,-4296,-4313,-4329,-4344,-4359,-4372,-4386,-4398,-4410,-4421,-4432,-4442,-4452,-4461,-4470,-4478,-4486,-4494,-4501,
+-4507,-4513,-4519,-4524,-4528,-4533,-4536,-4540,-4543,-4546,-4548,-4551,-4553,-4555,-4557,-4559,-4562,-4565,-4567,-4571,-4574,
+-4578,-4582,-4587,-4592,-4597,-4602,-4608,-4614,-4620,-4626,-4632,-4637,-4643,-4648,-4653,-4658,-4663,-4666,-4670,-4673,-4676,
+-4678,-4680,-4681,-4683,-4683,-4684,-4685,-4685,-4685,-4686,-4686,-4686,-4686,-4687,-4688,-4688,-4689,-4691,-4692,-4694,-4696,
+-4698,-4700,-4702,-4705,-4708,-4711,-4714,-4717,-4720,-4724,-4727,-4730,-4734,-4737,-4741,-4744,-4748,-4751,-4754,-4757,-4760,
+-4763,-4766,-4768,-4771,-4773,-4775,-4777,-4779,-4780,-4782,-4783,-4784,-4785,-4786,-4786,-4787,-4787,-4788,-4788,-4788,-4788,
+-4788,-4788,-4788,-4788,-4787,-4787,-4786,-4785,-4785,-4784,-4783,-4782,-4781,-4780,-4779,-4778,-4777,-4776,-4775,-4775,-4774,
+-4774,-4774,-4774,-4775,-4776,-4777,-4778,-4779,-4781,-4783,-4785,-4787,-4789,-4791,-4793,-4794,-4795,-4796,-4797,-4797,-4796,
+-4795,-4792,-4790,-4786,-4781,-4776,-4769,-4762,-4754,-4745,-4736,-4726,-4715,-4703,-4691,-4679,-4667,-4654,-4642,-4629,-4617,
+-4605,-4593,-4582,-4572,-4562,-4552,-4544,-4536,-4529,-4523,-4517,-4512,-4508,-4504,-4501,-4499,-4496,-4494,-4492,-4490,-4488,
+-4485,-4483,-4480,-4477,-4473,-4469,-4464,-4459,-4453,-4446,-4439,-4432,-4423,-4415,-4406,-4397,-4387,-4378,-4368,-4358,-4348,
+-4339,-4329,-4320,-4312,-4303,-4295,-4288,-4281,-4274,-4268,-4262,-4257,-4252,-4248,-4244,-4240,-4237,-4234,-4231,-4229,-4226,
+-4224,-4222,-4221,-4219,-4217,-4216,-4215,-4213,-4212,-4211,-4210,-4209,-4208,-4207,-4207,-4206,-4205,-4204,-4204,-4203,-4202,
+-4201,-4200,-4199,-4197,-4195,-4193,-4190,-4187,-4183,-4179,-4175,-4169,-4163,-4157,-4149,-4141,-4132,-4123,-4112,-4101,-4089,
+-4077,-4064,-4050,-4035,-4020,-4005,-3989,-3973,-3957,-3941,-3924,-3908,-3892,-3876,-3860,-3845,-3831,-3816,-3803,-3790,-3777,
+-3765,-3754,-3743,-3732,-3722,-3712,-3702,-3693,-3683,-3674,-3664,-3655,-3645,-3634,-3624,-3612,-3601,-3589,-3576,-3563,-3549,
+-3535,-3521,-3506,-3492,-3477,-3462,-3447,-3432,-3417,-3402,-3388,-3373,-3359,-3346,-3332,-3319,-3305,-3292,-3279,-3266,-3253,
+-3239,-3226,-3211,-3197,-3182,-3167,-3151,-3135,-3118,-3101,-3084,-3067,-3050,-3032,-3015,-2998,-2982,-2967,-2952,-2938,-2926,
+-2915,-2905,-2896,-2889,-2884,-2880,-2878,-2877,-2878,-2880,-2883,-2888,-2893,-2899,-2906,-2913,-2920,-2928,-2935,-2942,-2949,
+-2956,-2961,-2967,-2971,-2975,-2978,-2981,-2983,-2984,-2984,-2984,-2983,-2982,-2981,-2979,-2976,-2974,-2971,-2968,-2965,-2962,
+-2958,-2955,-2951,-2948,-2944,-2941,-2937,-2933,-2930,-2927,-2924,-2921,-2919,-2917,-2915,-2914,-2914,-2915,-2916,-2918,-2921,
+-2925,-2930,-2936,-2943,-2950,-2958,-2967,-2976,-2985,-2995,-3004,-3013,-3022,-3030,-3037,-3043,-3048,-3052,-3054,-3055,-3055,
+-3052,-3049,-3044,-3037,-3030,-3021,-3011,-3001,-2990,-2979,-2968,-2957,-2947,-2937,-2927,-2919,-2911,-2905,-2900,-2895,-2892,
+-2890,-2889,-2888,-2889,-2890,-2891,-2893,-2895,-2897,-2899,-2901,-2903,-2904,-2904,-2904,-2903,-2902,-2900,-2897,-2894,-2890,
+-2886,-2881,-2875,-2870,-2864,-2857,-2851,-2844,-2837,-2830,-2822,-2815,-2807,-2799,-2791,-2783,-2774,-2765,-2756,-2746,-2736,
+-2725,-2714,-2703,-2692,-2680,-2668,-2656,-2644,-2632,-2620,-2609,-2598,-2587,-2577,-2568,-2559,-2552,-2545,-2539,-2534,-2530,
+-2527,-2525,-2524,-2523,-2523,-2523,-2524,-2526,-2527,-2529,-2530,-2531,-2532,-2532,-2531,-2530,-2527,-2523,-2519,-2513,-2505,
+-2496,-2486,-2474,-2461,-2446,-2430,-2413,-2394,-2374,-2353,-2331,-2309,-2286,-2263,-2240,-2217,-2195,-2173,-2153,-2134,-2116,
+-2100,-2087,-2075,-2067,-2060,-2057,-2056,-2058,-2062,-2070,-2079,-2091,-2105,-2121,-2138,-2156,-2175,-2194,-2212,-2230,-2247,
+-2262,-2275,-2286,-2294,-2299,-2301,-2300,-2296,-2288,-2277,-2263,-2246,-2226,-2204,-2180,-2154,-2126,-2098,-2070,-2041,-2013,
+-1986,-1959,-1934,-1911,-1889,-1870,-1852,-1836,-1822,-1810,-1800,-1791,-1784,-1778,-1772,-1768,-1764,-1761,-1757,-1754,-1751,
+-1747,-1744,-1740,-1736,-1732,-1728,-1724,-1721,-1717,-1715,-1713,-1712,-1712,-1713,-1716,-1719,-1724,-1730,-1737,-1744,-1753,
+-1762,-1771,-1780,-1789,-1796,-1803,-1809,-1813,-1815,-1816,-1813,-1809,-1801,-1791,-1778,-1763,-1745,-1724,-1701,-1676,-1649,
+-1621,-1592,-1561,-1530,-1499,-1468,-1438,-1408,-1379,-1352,-1326,-1302,-1280,-1260,-1242,-1226,-1212,-1199,-1189,-1180,-1173,
+-1167,-1162,-1159,-1156,-1153,-1152,-1150,-1148,-1147,-1145,-1143,-1140,-1138,-1134,-1131,-1127,-1123,-1118,-1113,-1108,-1103,
+-1098,-1094,-1089,-1085,-1081,-1077,-1074,-1071,-1069,-1067,-1066,-1065,-1065,-1065,-1065,-1066,-1067,-1068,-1070,-1071,-1073,
+-1074,-1076,-1077,-1079,-1080,-1081,-1083,-1084,-1085,-1087,-1088,-1089,-1091,-1093,-1095,-1098,-1100,-1103,-1107,-1110,-1114,
+-1118,-1123,-1128,-1132,-1137,-1142,-1147,-1152,-1156,-1160,-1164,-1167,-1170,-1172,-1173,-1174,-1219,-1220,-1221,-1222,-1221,
+-1220,-1218,-1216,-1213,-1209,-1205,-1200,-1195,-1190,-1185,-1179,-1174,-1169,-1163,-1159,-1154,-1150,-1146,-1142,-1139,-1136,
+-1134,-1132,-1130,-1128,-1125,-1123,-1121,-1119,-1116,-1112,-1109,-1104,-1099,-1094,-1088,-1081,-1074,-1066,-1058,-1050,-1041,
+-1033,-1024,-1016,-1008,-1000,-993,-987,-982,-977,-974,-971,-970,-969,-970,-971,-973,-976,-979,-982,-986,-989,
+-993,-996,-998,-999,-1000,-999,-996,-993,-987,-980,-971,-960,-947,-932,-915,-897,-877,-855,-832,-807,-782,
+-755,-728,-700,-672,-643,-615,-586,-558,-530,-503,-476,-450,-425,-400,-377,-354,-333,-312,-292,-274,-256,
+-239,-223,-209,-195,-181,-169,-158,-147,-137,-128,-120,-112,-105,-99,-94,-89,-85,-82,-80,-78,-77,
+-77,-77,-78,-80,-82,-85,-89,-93,-97,-102,-107,-113,-120,-126,-133,-140,-147,-155,-163,-171,-179,
+-187,-195,-204,-213,-221,-230,-239,-248,-258,-267,-277,-286,-296,-306,-316,-325,-335,-345,-355,-364,-374,
+-383,-392,-400,-408,-415,-422,-429,-434,-439,-443,-447,-450,-451,-453,-453,-453,-452,-451,-449,-447,-444,
+-441,-438,-434,-430,-426,-423,-419,-415,-411,-407,-403,-399,-395,-390,-386,-381,-376,-371,-365,-359,-353,
+-346,-338,-330,-322,-313,-304,-294,-285,-275,-265,-256,-246,-237,-229,-221,-214,-208,-202,-197,-194,-191,
+-190,-189,-189,-190,-192,-195,-198,-202,-206,-210,-214,-218,-222,-225,-228,-230,-232,-233,-233,-232,-231,
+-228,-225,-221,-216,-211,-205,-199,-192,-185,-178,-171,-164,-157,-150,-143,-137,-131,-126,-121,-117,-113,
+-110,-108,-106,-105,-105,-106,-107,-109,-111,-114,-118,-123,-129,-135,-142,-150,-159,-168,-178,-189,-200,
+-212,-224,-237,-250,-263,-277,-290,-303,-317,-330,-343,-355,-367,-379,-390,-401,-411,-420,-429,-438,-446,
+-454,-462,-470,-477,-485,-493,-501,-510,-519,-529,-539,-550,-562,-575,-588,-603,-618,-634,-650,-667,-685,
+-703,-721,-740,-759,-778,-797,-815,-834,-852,-869,-887,-904,-920,-936,-951,-967,-981,-996,-1010,-1024,-1037,
+-1051,-1065,-1079,-1094,-1109,-1124,-1140,-1156,-1173,-1191,-1209,-1229,-1249,-1269,-1291,-1313,-1335,-1358,-1382,-1406,-1430,
+-1454,-1479,-1503,-1528,-1552,-1576,-1600,-1623,-1646,-1668,-1690,-1711,-1732,-1752,-1771,-1790,-1809,-1827,-1844,-1862,-1878,
+-1895,-1911,-1928,-1944,-1960,-1975,-1991,-2007,-2023,-2038,-2054,-2070,-2086,-2102,-2117,-2133,-2149,-2164,-2180,-2195,-2211,
+-2226,-2241,-2257,-2272,-2287,-2302,-2318,-2333,-2348,-2364,-2379,-2395,-2411,-2427,-2443,-2460,-2476,-2493,-2511,-2528,-2546,
+-2564,-2582,-2600,-2618,-2637,-2655,-2674,-2693,-2712,-2731,-2750,-2769,-2788,-2807,-2826,-2845,-2864,-2883,-2902,-2921,-2940,
+-2959,-2978,-2997,-3015,-3033,-3052,-3069,-3087,-3104,-3121,-3138,-3154,-3171,-3186,-3202,-3217,-3232,-3247,-3262,-3277,-3292,
+-3308,-3324,-3340,-3356,-3374,-3392,-3411,-3430,-3451,-3472,-3495,-3518,-3542,-3566,-3591,-3617,-3643,-3669,-3694,-3720,-3745,
+-3769,-3792,-3814,-3835,-3854,-3872,-3887,-3901,-3913,-3923,-3931,-3937,-3942,-3944,-3946,-3946,-3945,-3944,-3942,-3939,-3937,
+-3935,-3933,-3932,-3932,-3933,-3935,-3938,-3943,-3949,-3956,-3964,-3974,-3985,-3996,-4008,-4021,-4034,-4047,-4061,-4073,-4086,
+-4097,-4108,-4118,-4127,-4135,-4142,-4147,-4151,-4154,-4156,-4157,-4157,-4156,-4155,-4153,-4150,-4147,-4144,-4140,-4137,-4133,
+-4130,-4126,-4123,-4120,-4118,-4115,-4113,-4111,-4108,-4106,-4104,-4102,-4100,-4098,-4095,-4093,-4090,-4087,-4083,-4080,-4076,
+-4071,-4067,-4061,-4056,-4050,-4044,-4038,-4031,-4023,-4015,-4007,-3998,-3989,-3979,-3969,-3959,-3948,-3936,-3925,-3913,-3901,
+-3889,-3877,-3866,-3854,-3844,-3833,-3824,-3815,-3808,-3802,-3797,-3793,-3792,-3791,-3793,-3796,-3801,-3808,-3816,-3826,-3837,
+-3850,-3864,-3880,-3896,-3913,-3931,-3949,-3968,-3987,-4006,-4024,-4042,-4060,-4077,-4094,-4110,-4126,-4140,-4154,-4167,-4180,
+-4192,-4203,-4214,-4224,-4234,-4244,-4253,-4263,-4272,-4281,-4290,-4298,-4307,-4316,-4325,-4334,-4343,-4352,-4361,-4370,-4379,
+-4388,-4397,-4405,-4414,-4422,-4431,-4438,-4446,-4454,-4461,-4468,-4475,-4481,-4487,-4493,-4499,-4505,-4510,-4515,-4520,-4524,
+-4529,-4533,-4537,-4541,-4545,-4548,-4552,-4555,-4559,-4562,-4565,-4569,-4572,-4575,-4578,-4581,-4585,-4588,-4591,-4594,-4598,
+-4601,-4604,-4607,-4610,-4613,-4617,-4620,-4622,-4625,-4628,-4631,-4634,-4636,-4639,-4641,-4644,-4646,-4648,-4651,-4653,-4656,
+-4658,-4661,-4663,-4666,-4668,-4671,-4673,-4676,-4679,-4681,-4684,-4687,-4689,-4692,-4694,-4696,-4698,-4700,-4701,-4703,-4704,
+-4705,-4706,-4706,-4707,-4707,-4707,-4707,-4707,-4707,-4706,-4706,-4705,-4705,-4705,-4705,-4704,-4704,-4704,-4704,-4704,-4705,
+-4705,-4705,-4706,-4706,-4707,-4707,-4708,-4708,-4709,-4709,-4709,-4710,-4710,-4711,-4711,-4711,-4711,-4712,-4712,-4712,-4713,
+-4713,-4714,-4714,-4715,-4716,-4716,-4717,-4717,-4718,-4718,-4719,-4719,-4719,-4718,-4717,-4716,-4714,-4711,-4708,-4704,-4699,
+-4694,-4687,-4680,-4673,-4664,-4654,-4644,-4634,-4622,-4611,-4598,-4586,-4573,-4561,-4548,-4536,-4524,-4512,-4501,-4490,-4481,
+-4471,-4463,-4456,-4449,-4444,-4439,-4435,-4432,-4429,-4427,-4426,-4425,-4424,-4423,-4423,-4422,-4421,-4419,-4418,-4415,-4412,
+-4409,-4404,-4399,-4394,-4387,-4380,-4372,-4364,-4355,-4345,-4336,-4326,-4316,-4306,-4296,-4286,-4277,-4268,-4259,-4251,-4244,
+-4237,-4231,-4225,-4220,-4216,-4212,-4209,-4207,-4205,-4203,-4202,-4200,-4200,-4199,-4198,-4197,-4197,-4196,-4195,-4194,-4193,
+-4192,-4190,-4188,-4187,-4185,-4183,-4180,-4178,-4176,-4173,-4171,-4169,-4166,-4164,-4161,-4159,-4156,-4154,-4151,-4148,-4145,
+-4142,-4138,-4134,-4130,-4125,-4119,-4114,-4107,-4100,-4092,-4083,-4074,-4064,-4053,-4042,-4030,-4018,-4004,-3991,-3977,-3963,
+-3949,-3934,-3920,-3906,-3891,-3877,-3864,-3850,-3837,-3825,-3813,-3801,-3790,-3779,-3768,-3758,-3748,-3738,-3729,-3719,-3709,
+-3699,-3689,-3678,-3667,-3656,-3644,-3631,-3618,-3604,-3590,-3575,-3560,-3544,-3527,-3510,-3493,-3476,-3458,-3440,-3423,-3405,
+-3388,-3371,-3354,-3338,-3322,-3306,-3290,-3275,-3260,-3246,-3232,-3217,-3203,-3189,-3175,-3161,-3147,-3133,-3119,-3104,-3090,
+-3075,-3060,-3046,-3031,-3017,-3002,-2988,-2975,-2962,-2950,-2939,-2928,-2919,-2911,-2904,-2898,-2894,-2891,-2889,-2888,-2889,
+-2891,-2894,-2897,-2902,-2907,-2913,-2920,-2926,-2933,-2940,-2946,-2952,-2958,-2964,-2969,-2973,-2977,-2980,-2982,-2984,-2985,
+-2986,-2986,-2985,-2984,-2982,-2980,-2977,-2975,-2972,-2968,-2965,-2962,-2958,-2954,-2950,-2947,-2943,-2939,-2935,-2932,-2928,
+-2925,-2922,-2919,-2916,-2914,-2912,-2910,-2910,-2909,-2910,-2911,-2912,-2915,-2918,-2922,-2927,-2932,-2938,-2945,-2952,-2959,
+-2966,-2974,-2981,-2988,-2995,-3001,-3006,-3010,-3014,-3016,-3017,-3017,-3015,-3013,-3009,-3003,-2997,-2989,-2981,-2972,-2962,
+-2952,-2942,-2932,-2921,-2912,-2902,-2894,-2886,-2879,-2873,-2868,-2864,-2861,-2859,-2858,-2858,-2859,-2861,-2862,-2865,-2867,
+-2869,-2872,-2873,-2875,-2876,-2876,-2875,-2874,-2871,-2868,-2864,-2858,-2852,-2845,-2838,-2829,-2820,-2811,-2801,-2791,-2781,
+-2770,-2760,-2750,-2740,-2731,-2722,-2713,-2704,-2696,-2688,-2681,-2674,-2668,-2661,-2656,-2650,-2644,-2639,-2634,-2629,-2624,
+-2619,-2614,-2609,-2604,-2599,-2594,-2590,-2585,-2580,-2575,-2570,-2565,-2561,-2556,-2551,-2546,-2542,-2537,-2532,-2527,-2522,
+-2517,-2511,-2506,-2500,-2493,-2486,-2479,-2470,-2462,-2452,-2442,-2430,-2418,-2406,-2392,-2377,-2361,-2345,-2328,-2310,-2292,
+-2273,-2253,-2234,-2214,-2194,-2175,-2156,-2138,-2120,-2104,-2089,-2075,-2063,-2053,-2045,-2038,-2034,-2032,-2032,-2034,-2039,
+-2045,-2053,-2063,-2075,-2087,-2101,-2115,-2130,-2144,-2159,-2173,-2185,-2197,-2207,-2215,-2221,-2224,-2225,-2224,-2220,-2214,
+-2205,-2194,-2180,-2164,-2147,-2127,-2106,-2085,-2062,-2039,-2016,-1992,-1970,-1947,-1926,-1906,-1887,-1869,-1853,-1838,-1824,
+-1812,-1802,-1792,-1784,-1776,-1770,-1764,-1758,-1754,-1749,-1745,-1741,-1737,-1733,-1729,-1725,-1721,-1718,-1715,-1712,-1710,
+-1708,-1707,-1707,-1708,-1710,-1713,-1717,-1722,-1728,-1735,-1743,-1751,-1760,-1770,-1779,-1788,-1797,-1805,-1812,-1818,-1822,
+-1824,-1825,-1823,-1819,-1813,-1805,-1793,-1780,-1764,-1746,-1725,-1703,-1679,-1654,-1627,-1600,-1572,-1544,-1516,-1489,-1462,
+-1435,-1410,-1387,-1365,-1344,-1325,-1309,-1293,-1280,-1268,-1259,-1250,-1243,-1238,-1233,-1229,-1226,-1224,-1222,-1220,-1219,
+-1217,-1215,-1213,-1210,-1207,-1204,-1200,-1196,-1191,-1186,-1181,-1175,-1169,-1164,-1158,-1153,-1148,-1143,-1139,-1135,-1131,
+-1129,-1127,-1125,-1124,-1124,-1124,-1125,-1126,-1127,-1129,-1131,-1133,-1136,-1138,-1140,-1142,-1144,-1146,-1147,-1148,-1150,
+-1150,-1151,-1152,-1152,-1153,-1153,-1154,-1154,-1155,-1156,-1158,-1160,-1162,-1164,-1167,-1170,-1174,-1177,-1181,-1186,-1190,
+-1194,-1199,-1203,-1207,-1211,-1214,-1217,-1219,-1265,-1269,-1271,-1274,-1275,-1276,-1277,-1276,-1275,-1274,-1272,-1269,-1265,
+-1262,-1257,-1253,-1248,-1243,-1238,-1233,-1228,-1223,-1219,-1214,-1209,-1205,-1201,-1196,-1192,-1188,-1184,-1180,-1175,-1171,
+-1166,-1161,-1155,-1149,-1143,-1136,-1130,-1122,-1115,-1107,-1100,-1092,-1084,-1076,-1069,-1062,-1056,-1050,-1045,-1040,-1037,
+-1034,-1032,-1032,-1032,-1033,-1035,-1038,-1041,-1045,-1050,-1054,-1059,-1064,-1068,-1071,-1074,-1076,-1077,-1077,-1075,-1071,
+-1066,-1059,-1051,-1040,-1028,-1013,-997,-979,-959,-938,-916,-892,-867,-841,-814,-787,-759,-732,-704,-676,-648,
+-621,-595,-569,-544,-519,-496,-473,-452,-431,-411,-393,-375,-358,-343,-328,-314,-301,-288,-277,-266,-256,
+-247,-238,-230,-223,-216,-210,-205,-200,-196,-193,-190,-188,-186,-185,-184,-185,-185,-187,-188,-191,-193,
+-197,-200,-204,-209,-214,-219,-225,-230,-237,-243,-250,-257,-264,-272,-279,-287,-296,-304,-313,-322,-332,
+-341,-351,-361,-371,-381,-392,-402,-413,-423,-433,-443,-453,-462,-471,-479,-487,-495,-501,-508,-513,-517,
+-521,-524,-527,-528,-529,-529,-528,-527,-525,-523,-520,-517,-513,-509,-506,-502,-498,-493,-489,-485,-481,
+-477,-473,-469,-465,-461,-457,-453,-449,-444,-440,-435,-430,-424,-419,-413,-407,-400,-394,-387,-381,-374,
+-367,-361,-354,-348,-343,-338,-333,-330,-326,-324,-322,-321,-321,-321,-322,-323,-325,-328,-330,-333,-336,
+-339,-341,-344,-346,-347,-348,-348,-347,-345,-343,-340,-336,-331,-325,-319,-312,-304,-296,-288,-279,-271,
+-262,-254,-246,-239,-232,-226,-220,-216,-212,-209,-207,-206,-207,-208,-210,-213,-217,-223,-228,-235,-243,
+-251,-260,-270,-280,-291,-302,-313,-325,-338,-350,-363,-376,-389,-402,-415,-429,-442,-455,-468,-481,-493,
+-506,-518,-530,-541,-552,-563,-573,-583,-593,-603,-612,-621,-630,-639,-647,-656,-665,-673,-682,-691,-701,
+-711,-721,-731,-742,-753,-765,-777,-790,-803,-816,-830,-844,-859,-873,-888,-903,-917,-932,-947,-961,-976,
+-990,-1004,-1018,-1032,-1045,-1058,-1071,-1084,-1097,-1109,-1122,-1135,-1147,-1160,-1174,-1187,-1201,-1215,-1230,-1245,-1260,
+-1276,-1293,-1310,-1327,-1345,-1364,-1383,-1402,-1422,-1442,-1462,-1482,-1502,-1523,-1543,-1564,-1584,-1604,-1624,-1644,-1663,
+-1683,-1702,-1720,-1739,-1757,-1775,-1792,-1809,-1827,-1843,-1860,-1877,-1893,-1909,-1926,-1942,-1958,-1973,-1989,-2005,-2021,
+-2036,-2052,-2067,-2082,-2098,-2113,-2128,-2142,-2157,-2172,-2186,-2201,-2215,-2230,-2244,-2258,-2273,-2288,-2302,-2317,-2332,
+-2347,-2363,-2378,-2395,-2411,-2428,-2444,-2462,-2479,-2497,-2515,-2534,-2552,-2571,-2590,-2609,-2629,-2648,-2667,-2687,-2706,
+-2726,-2745,-2764,-2783,-2803,-2822,-2841,-2860,-2878,-2897,-2916,-2934,-2952,-2971,-2989,-3007,-3025,-3042,-3060,-3077,-3094,
+-3110,-3127,-3143,-3159,-3174,-3190,-3205,-3220,-3234,-3249,-3263,-3277,-3291,-3305,-3320,-3334,-3349,-3364,-3380,-3396,-3412,
+-3429,-3447,-3465,-3484,-3503,-3523,-3544,-3564,-3585,-3606,-3628,-3649,-3670,-3690,-3710,-3730,-3748,-3766,-3782,-3797,-3811,
+-3824,-3835,-3844,-3853,-3860,-3865,-3870,-3873,-3875,-3876,-3877,-3877,-3877,-3876,-3876,-3876,-3876,-3877,-3878,-3881,-3884,
+-3888,-3893,-3899,-3906,-3914,-3923,-3932,-3943,-3954,-3965,-3977,-3989,-4001,-4013,-4024,-4035,-4046,-4055,-4064,-4072,-4079,
+-4085,-4090,-4094,-4096,-4098,-4098,-4098,-4096,-4094,-4091,-4087,-4083,-4078,-4073,-4067,-4062,-4057,-4051,-4046,-4041,-4037,
+-4033,-4029,-4026,-4024,-4022,-4020,-4019,-4019,-4019,-4019,-4019,-4020,-4021,-4022,-4022,-4022,-4022,-4021,-4020,-4018,-4014,
+-4010,-4004,-3998,-3990,-3980,-3969,-3957,-3944,-3929,-3913,-3895,-3877,-3858,-3838,-3818,-3797,-3777,-3757,-3737,-3718,-3700,
+-3683,-3667,-3653,-3641,-3631,-3623,-3617,-3614,-3612,-3613,-3616,-3622,-3629,-3638,-3649,-3661,-3675,-3690,-3706,-3723,-3740,
+-3757,-3775,-3792,-3809,-3825,-3841,-3856,-3871,-3885,-3897,-3910,-3921,-3932,-3942,-3952,-3961,-3970,-3979,-3987,-3996,-4005,
+-4015,-4025,-4036,-4047,-4059,-4071,-4085,-4099,-4114,-4129,-4145,-4161,-4178,-4196,-4213,-4230,-4248,-4265,-4282,-4298,-4314,
+-4329,-4343,-4357,-4369,-4381,-4392,-4401,-4410,-4418,-4425,-4431,-4436,-4441,-4445,-4448,-4451,-4454,-4456,-4458,-4460,-4462,
+-4464,-4466,-4469,-4472,-4475,-4478,-4481,-4485,-4489,-4494,-4498,-4503,-4508,-4513,-4518,-4523,-4529,-4534,-4538,-4543,-4548,
+-4552,-4556,-4560,-4564,-4567,-4570,-4573,-4576,-4579,-4582,-4585,-4587,-4590,-4593,-4596,-4599,-4602,-4605,-4609,-4612,-4616,
+-4619,-4623,-4626,-4630,-4633,-4637,-4640,-4643,-4645,-4647,-4649,-4650,-4651,-4652,-4652,-4652,-4651,-4650,-4649,-4647,-4645,
+-4643,-4641,-4639,-4636,-4634,-4632,-4630,-4628,-4627,-4625,-4624,-4623,-4623,-4623,-4623,-4623,-4623,-4624,-4625,-4626,-4627,
+-4628,-4629,-4630,-4630,-4631,-4631,-4631,-4632,-4631,-4631,-4631,-4630,-4629,-4628,-4627,-4626,-4625,-4624,-4624,-4623,-4622,
+-4622,-4621,-4621,-4621,-4620,-4620,-4620,-4619,-4619,-4618,-4617,-4615,-4613,-4611,-4608,-4604,-4599,-4594,-4588,-4581,-4574,
+-4566,-4557,-4547,-4537,-4527,-4516,-4504,-4493,-4481,-4470,-4459,-4448,-4438,-4428,-4418,-4410,-4402,-4395,-4389,-4383,-4379,
+-4375,-4372,-4370,-4368,-4367,-4366,-4366,-4366,-4365,-4365,-4365,-4364,-4363,-4362,-4360,-4357,-4354,-4350,-4346,-4341,-4335,
+-4329,-4322,-4315,-4308,-4300,-4293,-4285,-4277,-4269,-4262,-4255,-4248,-4242,-4236,-4231,-4226,-4222,-4218,-4214,-4211,-4209,
+-4206,-4204,-4202,-4200,-4198,-4197,-4195,-4193,-4190,-4188,-4185,-4182,-4178,-4174,-4170,-4166,-4161,-4156,-4151,-4146,-4141,
+-4135,-4130,-4125,-4119,-4114,-4109,-4105,-4100,-4096,-4091,-4087,-4083,-4079,-4075,-4071,-4067,-4063,-4059,-4054,-4049,-4043,
+-4037,-4031,-4023,-4016,-4007,-3998,-3989,-3979,-3968,-3957,-3946,-3934,-3922,-3910,-3897,-3885,-3872,-3860,-3847,-3836,-3824,
+-3813,-3802,-3791,-3781,-3772,-3762,-3753,-3745,-3736,-3728,-3720,-3712,-3703,-3695,-3686,-3677,-3668,-3657,-3647,-3636,-3624,
+-3611,-3598,-3584,-3569,-3553,-3537,-3520,-3503,-3486,-3467,-3449,-3430,-3411,-3392,-3373,-3354,-3336,-3317,-3299,-3280,-3262,
+-3245,-3227,-3210,-3194,-3177,-3161,-3145,-3130,-3115,-3100,-3086,-3071,-3058,-3044,-3031,-3019,-3007,-2996,-2985,-2975,-2966,
+-2957,-2949,-2943,-2937,-2932,-2928,-2925,-2923,-2922,-2922,-2923,-2924,-2927,-2930,-2933,-2937,-2941,-2946,-2950,-2955,-2959,
+-2964,-2968,-2971,-2974,-2977,-2979,-2980,-2981,-2981,-2980,-2979,-2977,-2975,-2972,-2969,-2966,-2962,-2957,-2953,-2949,-2944,
+-2940,-2935,-2931,-2926,-2922,-2918,-2914,-2910,-2907,-2904,-2901,-2898,-2896,-2894,-2892,-2890,-2889,-2888,-2887,-2887,-2887,
+-2888,-2889,-2890,-2892,-2895,-2897,-2900,-2904,-2908,-2912,-2916,-2920,-2924,-2929,-2933,-2936,-2940,-2943,-2945,-2946,-2947,
+-2947,-2946,-2944,-2941,-2937,-2932,-2926,-2919,-2912,-2903,-2894,-2885,-2875,-2865,-2855,-2846,-2836,-2827,-2818,-2811,-2804,
+-2797,-2792,-2788,-2784,-2782,-2781,-2780,-2780,-2781,-2782,-2783,-2785,-2787,-2788,-2790,-2791,-2791,-2790,-2789,-2787,-2784,
+-2780,-2774,-2768,-2760,-2752,-2742,-2732,-2721,-2710,-2698,-2686,-2673,-2661,-2649,-2638,-2626,-2616,-2606,-2598,-2590,-2583,
+-2578,-2573,-2570,-2568,-2567,-2567,-2567,-2569,-2571,-2574,-2577,-2581,-2584,-2588,-2591,-2594,-2597,-2599,-2600,-2600,-2600,
+-2598,-2596,-2592,-2587,-2581,-2574,-2565,-2556,-2545,-2533,-2521,-2507,-2493,-2478,-2462,-2445,-2428,-2411,-2394,-2376,-2358,
+-2340,-2322,-2304,-2287,-2269,-2252,-2235,-2219,-2203,-2187,-2172,-2158,-2144,-2131,-2118,-2106,-2095,-2085,-2076,-2067,-2059,
+-2053,-2047,-2042,-2039,-2036,-2035,-2034,-2035,-2036,-2039,-2042,-2046,-2051,-2057,-2063,-2070,-2076,-2083,-2090,-2097,-2103,
+-2109,-2114,-2118,-2122,-2124,-2125,-2125,-2123,-2120,-2116,-2110,-2103,-2094,-2084,-2074,-2062,-2049,-2036,-2022,-2007,-1993,
+-1978,-1964,-1949,-1935,-1922,-1908,-1896,-1884,-1873,-1863,-1853,-1844,-1836,-1828,-1821,-1814,-1808,-1802,-1796,-1790,-1784,
+-1779,-1773,-1767,-1762,-1756,-1750,-1745,-1740,-1735,-1730,-1726,-1722,-1719,-1717,-1716,-1716,-1717,-1719,-1722,-1726,-1731,
+-1737,-1744,-1751,-1760,-1769,-1778,-1787,-1795,-1804,-1812,-1819,-1825,-1829,-1832,-1834,-1834,-1832,-1828,-1822,-1814,-1804,
+-1792,-1778,-1763,-1746,-1728,-1709,-1688,-1668,-1647,-1625,-1604,-1583,-1563,-1543,-1525,-1507,-1490,-1475,-1461,-1448,-1437,
+-1427,-1418,-1410,-1403,-1397,-1392,-1387,-1383,-1379,-1375,-1371,-1367,-1363,-1358,-1353,-1348,-1341,-1335,-1327,-1320,-1312,
+-1303,-1294,-1285,-1276,-1267,-1258,-1249,-1240,-1232,-1225,-1218,-1212,-1207,-1203,-1199,-1196,-1195,-1193,-1193,-1193,-1194,
+-1195,-1197,-1199,-1201,-1204,-1206,-1208,-1210,-1212,-1214,-1215,-1216,-1217,-1217,-1217,-1216,-1216,-1215,-1214,-1213,-1212,
+-1211,-1211,-1211,-1211,-1211,-1212,-1213,-1215,-1217,-1220,-1223,-1227,-1231,-1235,-1239,-1244,-1248,-1253,-1257,-1261,-1265,
+-1316,-1320,-1324,-1327,-1330,-1331,-1333,-1333,-1333,-1332,-1331,-1329,-1326,-1323,-1319,-1314,-1310,-1305,-1299,-1294,-1288,
+-1283,-1277,-1271,-1266,-1260,-1255,-1249,-1244,-1239,-1234,-1228,-1223,-1218,-1212,-1207,-1201,-1195,-1189,-1183,-1177,-1171,
+-1164,-1157,-1151,-1144,-1138,-1132,-1126,-1121,-1116,-1111,-1108,-1105,-1102,-1101,-1100,-1100,-1101,-1102,-1104,-1107,-1111,
+-1115,-1119,-1123,-1128,-1132,-1136,-1140,-1142,-1145,-1146,-1145,-1144,-1141,-1137,-1131,-1123,-1114,-1102,-1089,-1075,-1058,
+-1040,-1021,-1000,-978,-954,-930,-905,-879,-852,-826,-799,-772,-746,-719,-693,-668,-643,-619,-596,-574,-552,
+-532,-513,-494,-477,-461,-445,-431,-418,-405,-394,-383,-373,-363,-355,-347,-340,-333,-327,-321,-316,-312,
+-307,-304,-301,-298,-296,-294,-292,-292,-291,-291,-292,-292,-294,-296,-298,-301,-304,-308,-312,-317,-322,
+-328,-334,-341,-348,-356,-364,-372,-381,-391,-400,-411,-421,-432,-443,-454,-465,-476,-488,-499,-510,-521,
+-532,-542,-552,-561,-570,-579,-586,-593,-600,-605,-610,-614,-617,-619,-621,-622,-622,-621,-620,-618,-616,
+-614,-611,-607,-604,-600,-596,-592,-588,-584,-579,-575,-571,-567,-563,-559,-555,-551,-547,-543,-539,-535,
+-531,-526,-522,-517,-512,-508,-503,-498,-493,-488,-483,-479,-474,-470,-467,-463,-461,-459,-457,-456,-455,
+-455,-456,-458,-460,-462,-465,-468,-472,-475,-479,-483,-486,-489,-492,-493,-495,-495,-495,-493,-491,-487,
+-482,-477,-470,-462,-453,-444,-434,-423,-411,-400,-388,-376,-365,-353,-343,-333,-324,-316,-309,-303,-299,
+-296,-295,-295,-296,-299,-304,-310,-318,-327,-337,-348,-361,-374,-388,-403,-419,-435,-451,-468,-484,-501,
+-518,-534,-551,-567,-583,-598,-613,-628,-642,-656,-669,-682,-694,-706,-717,-728,-739,-750,-760,-769,-779,
+-789,-798,-807,-816,-825,-834,-843,-852,-862,-871,-881,-890,-900,-910,-920,-930,-940,-951,-961,-972,-983,
+-994,-1005,-1016,-1027,-1038,-1049,-1060,-1071,-1082,-1093,-1104,-1114,-1125,-1136,-1147,-1157,-1168,-1179,-1190,-1201,-1212,
+-1224,-1235,-1247,-1259,-1271,-1284,-1297,-1310,-1323,-1337,-1351,-1365,-1380,-1395,-1410,-1426,-1441,-1457,-1473,-1489,-1505,
+-1521,-1537,-1553,-1569,-1585,-1601,-1617,-1633,-1649,-1665,-1680,-1696,-1712,-1727,-1742,-1758,-1773,-1789,-1804,-1820,-1835,
+-1851,-1867,-1882,-1898,-1914,-1930,-1946,-1961,-1977,-1993,-2008,-2024,-2039,-2054,-2069,-2084,-2099,-2113,-2127,-2141,-2155,
+-2169,-2182,-2195,-2209,-2222,-2235,-2249,-2262,-2276,-2289,-2303,-2318,-2333,-2348,-2363,-2379,-2395,-2412,-2429,-2447,-2465,
+-2484,-2503,-2522,-2541,-2561,-2581,-2601,-2621,-2641,-2661,-2682,-2702,-2722,-2742,-2762,-2781,-2801,-2820,-2839,-2858,-2877,
+-2895,-2914,-2932,-2950,-2968,-2986,-3004,-3022,-3039,-3057,-3074,-3092,-3109,-3126,-3142,-3159,-3176,-3192,-3208,-3223,-3239,
+-3254,-3269,-3284,-3298,-3313,-3327,-3341,-3355,-3369,-3383,-3396,-3410,-3424,-3439,-3453,-3467,-3482,-3497,-3512,-3527,-3543,
+-3559,-3574,-3590,-3606,-3621,-3637,-3652,-3667,-3681,-3695,-3708,-3720,-3732,-3743,-3753,-3762,-3770,-3777,-3783,-3789,-3794,
+-3797,-3801,-3804,-3806,-3808,-3809,-3811,-3813,-3814,-3817,-3819,-3822,-3825,-3829,-3834,-3840,-3846,-3853,-3861,-3869,-3878,
+-3888,-3898,-3908,-3919,-3929,-3940,-3950,-3961,-3970,-3979,-3988,-3995,-4002,-4008,-4012,-4016,-4018,-4019,-4020,-4019,-4017,
+-4014,-4010,-4006,-4001,-3996,-3990,-3984,-3978,-3972,-3966,-3961,-3957,-3953,-3949,-3947,-3945,-3945,-3945,-3946,-3948,-3951,
+-3954,-3958,-3963,-3967,-3972,-3977,-3981,-3985,-3988,-3991,-3992,-3991,-3989,-3986,-3980,-3973,-3964,-3952,-3938,-3922,-3904,
+-3884,-3863,-3839,-3814,-3788,-3761,-3733,-3704,-3676,-3648,-3620,-3593,-3567,-3543,-3521,-3500,-3482,-3465,-3452,-3441,-3433,
+-3428,-3425,-3425,-3427,-3432,-3439,-3448,-3459,-3471,-3485,-3499,-3515,-3531,-3547,-3564,-3580,-3596,-3611,-3626,-3640,-3653,
+-3666,-3677,-3688,-3698,-3708,-3717,-3725,-3734,-3742,-3750,-3759,-3768,-3778,-3789,-3801,-3813,-3827,-3842,-3858,-3875,-3894,
+-3914,-3934,-3956,-3978,-4001,-4025,-4049,-4073,-4097,-4121,-4144,-4167,-4188,-4209,-4229,-4248,-4265,-4281,-4296,-4309,-4321,
+-4331,-4340,-4348,-4355,-4361,-4366,-4370,-4373,-4376,-4378,-4381,-4383,-4385,-4387,-4390,-4392,-4395,-4398,-4402,-4406,-4410,
+-4415,-4420,-4425,-4430,-4436,-4441,-4447,-4452,-4457,-4462,-4467,-4471,-4475,-4479,-4483,-4486,-4489,-4491,-4494,-4496,-4498,
+-4500,-4503,-4505,-4508,-4510,-4513,-4516,-4520,-4524,-4528,-4533,-4538,-4543,-4549,-4555,-4561,-4567,-4572,-4578,-4584,-4589,
+-4594,-4599,-4603,-4606,-4609,-4611,-4612,-4613,-4613,-4612,-4611,-4609,-4607,-4604,-4600,-4597,-4593,-4589,-4584,-4580,-4576,
+-4572,-4569,-4566,-4563,-4560,-4558,-4556,-4555,-4554,-4554,-4553,-4553,-4554,-4554,-4555,-4556,-4556,-4557,-4557,-4558,-4558,
+-4558,-4558,-4558,-4558,-4557,-4556,-4555,-4554,-4553,-4552,-4551,-4550,-4549,-4548,-4547,-4546,-4545,-4545,-4544,-4544,-4543,
+-4543,-4542,-4542,-4541,-4540,-4538,-4537,-4534,-4532,-4528,-4524,-4520,-4515,-4509,-4503,-4496,-4488,-4480,-4471,-4462,-4453,
+-4443,-4433,-4424,-4414,-4404,-4395,-4386,-4378,-4370,-4363,-4356,-4350,-4344,-4340,-4336,-4332,-4329,-4327,-4325,-4324,-4323,
+-4322,-4321,-4320,-4320,-4319,-4318,-4316,-4315,-4313,-4310,-4307,-4304,-4300,-4296,-4292,-4287,-4282,-4277,-4272,-4266,-4261,
+-4255,-4250,-4244,-4239,-4235,-4230,-4226,-4222,-4218,-4215,-4211,-4208,-4205,-4202,-4200,-4197,-4194,-4191,-4188,-4184,-4180,
+-4176,-4172,-4167,-4162,-4156,-4150,-4143,-4137,-4130,-4122,-4115,-4107,-4100,-4092,-4085,-4077,-4070,-4063,-4056,-4049,-4043,
+-4037,-4032,-4027,-4022,-4017,-4012,-4008,-4003,-3999,-3995,-3990,-3985,-3980,-3975,-3969,-3963,-3956,-3949,-3941,-3932,-3923,
+-3914,-3904,-3894,-3883,-3872,-3860,-3849,-3837,-3825,-3814,-3802,-3791,-3780,-3770,-3760,-3750,-3741,-3732,-3724,-3717,-3709,
+-3703,-3696,-3690,-3685,-3679,-3674,-3668,-3662,-3657,-3650,-3644,-3636,-3629,-3620,-3611,-3601,-3591,-3579,-3567,-3553,-3539,
+-3524,-3508,-3491,-3473,-3455,-3436,-3416,-3396,-3376,-3355,-3334,-3312,-3291,-3269,-3248,-3227,-3206,-3185,-3164,-3145,-3125,
+-3107,-3088,-3071,-3055,-3039,-3024,-3011,-2998,-2986,-2976,-2966,-2958,-2951,-2945,-2940,-2937,-2934,-2933,-2932,-2933,-2934,
+-2936,-2939,-2942,-2946,-2950,-2955,-2960,-2964,-2969,-2973,-2977,-2981,-2984,-2987,-2989,-2990,-2991,-2991,-2990,-2989,-2987,
+-2984,-2981,-2977,-2972,-2968,-2962,-2957,-2951,-2946,-2940,-2934,-2928,-2923,-2918,-2913,-2908,-2904,-2900,-2896,-2893,-2890,
+-2887,-2885,-2884,-2882,-2881,-2880,-2880,-2880,-2880,-2880,-2881,-2882,-2883,-2884,-2885,-2887,-2889,-2891,-2893,-2895,-2897,
+-2899,-2901,-2903,-2904,-2906,-2907,-2908,-2908,-2908,-2908,-2906,-2905,-2902,-2899,-2894,-2889,-2884,-2877,-2870,-2861,-2853,
+-2843,-2833,-2823,-2812,-2801,-2790,-2778,-2767,-2757,-2746,-2737,-2727,-2719,-2711,-2704,-2697,-2692,-2687,-2683,-2680,-2678,
+-2676,-2675,-2674,-2673,-2673,-2672,-2672,-2671,-2669,-2668,-2665,-2662,-2658,-2653,-2648,-2642,-2635,-2627,-2618,-2609,-2599,
+-2589,-2579,-2568,-2558,-2548,-2539,-2530,-2521,-2514,-2508,-2503,-2499,-2496,-2495,-2495,-2497,-2499,-2504,-2509,-2515,-2523,
+-2531,-2540,-2549,-2558,-2568,-2577,-2585,-2593,-2600,-2606,-2610,-2613,-2615,-2614,-2612,-2607,-2601,-2592,-2581,-2568,-2553,
+-2537,-2518,-2497,-2475,-2452,-2428,-2402,-2376,-2349,-2322,-2294,-2267,-2241,-2214,-2189,-2165,-2141,-2119,-2098,-2079,-2062,
+-2046,-2032,-2019,-2009,-2000,-1992,-1987,-1983,-1980,-1979,-1980,-1981,-1984,-1987,-1991,-1996,-2001,-2007,-2013,-2019,-2026,
+-2032,-2037,-2043,-2048,-2052,-2056,-2059,-2062,-2063,-2064,-2064,-2063,-2061,-2059,-2055,-2051,-2046,-2040,-2033,-2026,-2018,
+-2010,-2002,-1993,-1984,-1975,-1965,-1956,-1947,-1938,-1930,-1921,-1913,-1906,-1899,-1892,-1886,-1880,-1875,-1870,-1865,-1861,
+-1857,-1853,-1849,-1845,-1841,-1837,-1832,-1828,-1823,-1818,-1812,-1806,-1800,-1793,-1786,-1779,-1772,-1765,-1758,-1751,-1744,
+-1738,-1732,-1727,-1723,-1720,-1717,-1716,-1715,-1716,-1718,-1721,-1725,-1730,-1736,-1742,-1750,-1757,-1766,-1774,-1783,-1791,
+-1799,-1806,-1813,-1818,-1823,-1827,-1829,-1829,-1829,-1827,-1823,-1818,-1811,-1803,-1794,-1784,-1772,-1760,-1747,-1733,-1720,
+-1706,-1692,-1678,-1664,-1651,-1639,-1627,-1616,-1605,-1596,-1587,-1579,-1572,-1565,-1559,-1553,-1548,-1543,-1539,-1534,-1529,
+-1524,-1518,-1512,-1506,-1499,-1491,-1483,-1474,-1464,-1453,-1443,-1431,-1419,-1407,-1395,-1382,-1370,-1358,-1346,-1334,-1323,
+-1313,-1304,-1295,-1287,-1281,-1275,-1270,-1266,-1263,-1261,-1260,-1259,-1259,-1260,-1261,-1262,-1263,-1265,-1267,-1268,-1270,
+-1271,-1272,-1272,-1273,-1273,-1272,-1271,-1270,-1269,-1268,-1266,-1264,-1263,-1262,-1260,-1260,-1259,-1259,-1260,-1261,-1262,
+-1264,-1267,-1270,-1274,-1278,-1282,-1287,-1292,-1297,-1302,-1307,-1311,-1316,-1364,-1369,-1372,-1375,-1378,-1380,-1381,-1381,
+-1381,-1380,-1378,-1376,-1373,-1369,-1365,-1360,-1355,-1350,-1344,-1338,-1332,-1326,-1320,-1314,-1308,-1303,-1297,-1291,-1286,
+-1281,-1276,-1271,-1266,-1261,-1256,-1251,-1246,-1241,-1236,-1231,-1226,-1220,-1215,-1209,-1204,-1198,-1193,-1188,-1182,-1178,
+-1173,-1169,-1165,-1162,-1159,-1157,-1155,-1154,-1154,-1154,-1155,-1156,-1158,-1160,-1163,-1165,-1168,-1171,-1174,-1176,-1178,
+-1180,-1181,-1180,-1179,-1177,-1174,-1169,-1163,-1155,-1146,-1135,-1123,-1109,-1094,-1077,-1059,-1040,-1019,-997,-975,-951,
+-927,-903,-878,-853,-827,-802,-778,-753,-729,-706,-683,-662,-641,-621,-602,-584,-567,-551,-536,-522,-509,
+-496,-485,-475,-466,-457,-449,-442,-435,-429,-423,-418,-413,-409,-405,-401,-398,-395,-392,-389,-387,-386,
+-384,-383,-383,-382,-383,-383,-385,-386,-389,-392,-395,-399,-404,-410,-416,-423,-430,-438,-447,-456,-465,
+-476,-486,-497,-509,-520,-532,-544,-556,-568,-579,-591,-602,-613,-623,-633,-642,-651,-659,-666,-673,-678,
+-683,-687,-691,-693,-695,-696,-697,-696,-696,-694,-693,-691,-688,-685,-682,-679,-676,-672,-669,-665,-662,
+-658,-655,-652,-648,-645,-641,-638,-634,-630,-627,-623,-619,-615,-611,-606,-602,-597,-593,-588,-583,-579,
+-574,-570,-566,-562,-559,-556,-554,-552,-551,-550,-550,-551,-552,-554,-557,-560,-564,-568,-573,-578,-583,
+-588,-593,-597,-602,-605,-608,-611,-612,-612,-612,-610,-607,-602,-597,-590,-582,-573,-563,-552,-540,-528,
+-515,-502,-488,-475,-462,-450,-438,-427,-417,-408,-401,-395,-391,-388,-387,-388,-390,-394,-401,-408,-418,
+-429,-441,-455,-470,-486,-503,-520,-538,-557,-576,-595,-614,-633,-652,-670,-689,-706,-723,-739,-755,-770,
+-784,-798,-811,-824,-835,-847,-858,-868,-878,-888,-897,-906,-916,-925,-934,-942,-951,-961,-970,-979,-988,
+-998,-1007,-1017,-1027,-1037,-1047,-1057,-1067,-1077,-1087,-1097,-1107,-1117,-1127,-1136,-1146,-1156,-1165,-1174,-1183,-1193,
+-1202,-1211,-1220,-1229,-1238,-1247,-1256,-1266,-1276,-1286,-1296,-1306,-1317,-1328,-1339,-1351,-1362,-1375,-1387,-1400,-1413,
+-1426,-1439,-1453,-1467,-1481,-1494,-1508,-1522,-1536,-1550,-1563,-1577,-1590,-1604,-1617,-1630,-1643,-1656,-1669,-1682,-1694,
+-1707,-1720,-1732,-1745,-1758,-1771,-1785,-1798,-1812,-1826,-1840,-1855,-1869,-1884,-1899,-1914,-1930,-1945,-1960,-1976,-1991,
+-2007,-2022,-2037,-2052,-2067,-2081,-2095,-2109,-2123,-2136,-2149,-2162,-2174,-2186,-2198,-2210,-2222,-2234,-2246,-2258,-2270,
+-2283,-2296,-2309,-2323,-2337,-2352,-2367,-2382,-2399,-2416,-2433,-2451,-2469,-2488,-2508,-2527,-2547,-2567,-2588,-2608,-2629,
+-2650,-2670,-2691,-2711,-2731,-2751,-2771,-2790,-2810,-2828,-2847,-2865,-2884,-2902,-2919,-2937,-2954,-2972,-2989,-3006,-3023,
+-3041,-3058,-3075,-3092,-3109,-3127,-3144,-3161,-3178,-3195,-3212,-3229,-3246,-3263,-3279,-3295,-3311,-3327,-3342,-3357,-3372,
+-3386,-3400,-3414,-3428,-3441,-3454,-3466,-3479,-3491,-3503,-3515,-3526,-3538,-3549,-3560,-3571,-3582,-3592,-3603,-3613,-3623,
+-3632,-3642,-3650,-3659,-3667,-3675,-3683,-3690,-3696,-3702,-3708,-3713,-3718,-3722,-3727,-3731,-3735,-3738,-3742,-3745,-3749,
+-3753,-3756,-3761,-3765,-3770,-3775,-3780,-3786,-3792,-3799,-3806,-3814,-3821,-3829,-3838,-3846,-3854,-3863,-3871,-3879,-3886,
+-3893,-3900,-3906,-3911,-3915,-3919,-3922,-3924,-3925,-3925,-3924,-3923,-3920,-3917,-3914,-3910,-3906,-3901,-3896,-3892,-3887,
+-3883,-3879,-3876,-3873,-3871,-3870,-3870,-3870,-3872,-3874,-3877,-3880,-3884,-3889,-3894,-3899,-3905,-3910,-3914,-3918,-3922,
+-3924,-3925,-3924,-3922,-3918,-3913,-3905,-3895,-3883,-3869,-3852,-3834,-3813,-3791,-3767,-3741,-3715,-3687,-3658,-3629,-3600,
+-3570,-3542,-3514,-3487,-3461,-3437,-3415,-3395,-3377,-3361,-3348,-3338,-3329,-3324,-3321,-3321,-3322,-3326,-3332,-3340,-3349,
+-3360,-3372,-3384,-3397,-3411,-3425,-3438,-3452,-3465,-3478,-3490,-3502,-3513,-3524,-3534,-3543,-3552,-3561,-3570,-3579,-3587,
+-3597,-3606,-3617,-3628,-3640,-3653,-3667,-3683,-3700,-3718,-3737,-3758,-3780,-3803,-3827,-3851,-3877,-3903,-3929,-3955,-3982,
+-4007,-4033,-4058,-4081,-4104,-4126,-4146,-4165,-4182,-4198,-4213,-4226,-4238,-4248,-4257,-4265,-4271,-4277,-4282,-4287,-4291,
+-4294,-4298,-4301,-4305,-4308,-4312,-4317,-4321,-4326,-4332,-4338,-4344,-4351,-4358,-4365,-4372,-4379,-4386,-4393,-4400,-4406,
+-4412,-4418,-4423,-4427,-4431,-4434,-4436,-4438,-4440,-4441,-4442,-4442,-4442,-4442,-4442,-4442,-4443,-4443,-4444,-4446,-4448,
+-4450,-4453,-4457,-4462,-4467,-4472,-4478,-4485,-4492,-4499,-4506,-4513,-4520,-4527,-4534,-4540,-4546,-4552,-4556,-4560,-4563,
+-4565,-4567,-4567,-4567,-4566,-4564,-4562,-4559,-4555,-4551,-4547,-4542,-4538,-4533,-4528,-4524,-4520,-4516,-4512,-4509,-4506,
+-4503,-4502,-4500,-4499,-4498,-4498,-4498,-4499,-4499,-4500,-4501,-4502,-4503,-4504,-4505,-4506,-4507,-4508,-4508,-4509,-4509,
+-4509,-4509,-4508,-4508,-4507,-4507,-4506,-4505,-4504,-4503,-4502,-4501,-4499,-4498,-4496,-4495,-4493,-4491,-4488,-4486,-4483,
+-4480,-4476,-4472,-4467,-4463,-4457,-4452,-4445,-4439,-4432,-4425,-4418,-4410,-4402,-4394,-4387,-4379,-4371,-4363,-4356,-4349,
+-4342,-4336,-4329,-4324,-4319,-4314,-4309,-4305,-4302,-4298,-4295,-4293,-4290,-4288,-4285,-4283,-4281,-4278,-4276,-4273,-4270,
+-4267,-4264,-4260,-4256,-4252,-4248,-4243,-4239,-4234,-4229,-4224,-4219,-4215,-4210,-4205,-4201,-4197,-4193,-4189,-4185,-4182,
+-4179,-4176,-4173,-4170,-4168,-4165,-4162,-4159,-4157,-4153,-4150,-4146,-4142,-4138,-4133,-4128,-4122,-4116,-4109,-4103,-4095,
+-4088,-4080,-4072,-4064,-4056,-4048,-4040,-4032,-4024,-4016,-4009,-4002,-3995,-3989,-3983,-3977,-3972,-3967,-3962,-3958,-3953,
+-3949,-3945,-3940,-3936,-3931,-3926,-3921,-3915,-3909,-3903,-3895,-3888,-3879,-3871,-3861,-3851,-3841,-3830,-3819,-3808,-3797,
+-3785,-3773,-3762,-3750,-3739,-3729,-3718,-3708,-3699,-3690,-3683,-3675,-3669,-3662,-3657,-3652,-3648,-3644,-3641,-3638,-3635,
+-3632,-3630,-3627,-3624,-3620,-3616,-3612,-3607,-3601,-3594,-3586,-3577,-3567,-3555,-3543,-3529,-3515,-3499,-3482,-3463,-3444,
+-3424,-3403,-3381,-3359,-3336,-3312,-3289,-3265,-3241,-3217,-3193,-3170,-3148,-3126,-3105,-3084,-3065,-3047,-3030,-3015,-3001,
+-2988,-2976,-2966,-2958,-2951,-2945,-2941,-2938,-2936,-2935,-2936,-2937,-2939,-2942,-2946,-2950,-2954,-2958,-2963,-2967,-2972,
+-2976,-2980,-2983,-2986,-2988,-2989,-2990,-2990,-2989,-2988,-2986,-2983,-2980,-2976,-2972,-2967,-2962,-2957,-2951,-2946,-2940,
+-2934,-2929,-2923,-2918,-2913,-2909,-2905,-2901,-2898,-2895,-2892,-2890,-2888,-2886,-2885,-2884,-2883,-2883,-2882,-2882,-2883,
+-2883,-2883,-2883,-2884,-2885,-2885,-2886,-2886,-2887,-2888,-2888,-2889,-2890,-2890,-2891,-2891,-2891,-2891,-2891,-2891,-2890,
+-2889,-2887,-2885,-2882,-2879,-2875,-2871,-2866,-2860,-2854,-2846,-2839,-2830,-2821,-2811,-2801,-2790,-2779,-2768,-2756,-2744,
+-2733,-2721,-2709,-2698,-2687,-2676,-2666,-2656,-2647,-2638,-2630,-2623,-2616,-2610,-2604,-2599,-2594,-2589,-2585,-2580,-2576,
+-2572,-2568,-2564,-2560,-2555,-2550,-2545,-2539,-2533,-2527,-2521,-2514,-2507,-2501,-2494,-2487,-2481,-2475,-2470,-2465,-2461,
+-2458,-2455,-2454,-2454,-2455,-2457,-2461,-2466,-2472,-2479,-2487,-2496,-2506,-2516,-2527,-2539,-2550,-2561,-2572,-2582,-2592,
+-2600,-2607,-2612,-2616,-2618,-2618,-2615,-2611,-2604,-2594,-2583,-2568,-2552,-2533,-2512,-2489,-2464,-2438,-2410,-2381,-2351,
+-2320,-2289,-2258,-2228,-2197,-2168,-2139,-2112,-2086,-2062,-2040,-2020,-2002,-1986,-1973,-1962,-1953,-1946,-1942,-1940,-1939,
+-1941,-1944,-1949,-1955,-1963,-1971,-1980,-1989,-1999,-2009,-2019,-2028,-2036,-2044,-2052,-2058,-2063,-2067,-2069,-2071,-2071,
+-2069,-2067,-2063,-2058,-2052,-2045,-2037,-2028,-2018,-2008,-1998,-1987,-1976,-1965,-1955,-1944,-1934,-1924,-1915,-1906,-1898,
+-1891,-1884,-1878,-1873,-1868,-1864,-1860,-1857,-1854,-1852,-1850,-1848,-1845,-1843,-1841,-1838,-1835,-1832,-1828,-1824,-1820,
+-1814,-1809,-1803,-1796,-1789,-1782,-1775,-1767,-1760,-1752,-1745,-1738,-1732,-1726,-1721,-1717,-1713,-1711,-1709,-1708,-1709,
+-1710,-1712,-1716,-1720,-1725,-1731,-1737,-1744,-1751,-1759,-1766,-1773,-1780,-1787,-1793,-1798,-1802,-1806,-1808,-1810,-1810,
+-1809,-1807,-1804,-1800,-1795,-1789,-1782,-1774,-1766,-1757,-1748,-1738,-1728,-1719,-1709,-1699,-1690,-1682,-1673,-1665,-1658,
+-1651,-1645,-1639,-1633,-1628,-1623,-1618,-1614,-1609,-1604,-1600,-1594,-1589,-1583,-1577,-1570,-1562,-1554,-1546,-1536,-1526,
+-1516,-1505,-1494,-1482,-1470,-1458,-1446,-1434,-1422,-1411,-1400,-1389,-1379,-1370,-1361,-1354,-1347,-1341,-1335,-1331,-1327,
+-1325,-1322,-1321,-1320,-1319,-1319,-1319,-1319,-1320,-1320,-1321,-1321,-1321,-1321,-1320,-1319,-1318,-1317,-1316,-1314,-1312,
+-1310,-1308,-1306,-1305,-1303,-1302,-1301,-1300,-1300,-1301,-1302,-1303,-1305,-1308,-1311,-1315,-1319,-1324,-1328,-1334,-1339,
+-1344,-1350,-1355,-1360,-1364,-1413,-1417,-1421,-1424,-1426,-1428,-1429,-1430,-1430,-1429,-1428,-1425,-1423,-1419,-1416,-1412,
+-1407,-1402,-1397,-1392,-1387,-1381,-1376,-1371,-1365,-1360,-1355,-1350,-1345,-1341,-1336,-1331,-1327,-1322,-1317,-1313,-1308,
+-1303,-1298,-1293,-1287,-1282,-1276,-1270,-1264,-1257,-1251,-1245,-1238,-1232,-1226,-1220,-1214,-1209,-1204,-1199,-1195,-1192,
+-1189,-1186,-1185,-1183,-1183,-1182,-1183,-1183,-1184,-1185,-1187,-1188,-1189,-1190,-1191,-1191,-1191,-1190,-1188,-1185,-1181,
+-1176,-1169,-1162,-1153,-1143,-1131,-1118,-1104,-1089,-1072,-1054,-1035,-1015,-995,-974,-952,-930,-907,-884,-862,-839,
+-817,-795,-774,-753,-733,-713,-695,-677,-661,-645,-630,-617,-604,-592,-581,-571,-562,-554,-546,-539,-533,
+-527,-522,-517,-513,-509,-505,-501,-498,-495,-493,-490,-488,-486,-484,-482,-481,-480,-480,-480,-480,-481,
+-482,-484,-486,-489,-493,-498,-503,-508,-515,-522,-529,-537,-546,-555,-565,-575,-585,-595,-606,-617,-627,
+-638,-648,-658,-667,-676,-685,-693,-701,-707,-714,-719,-724,-728,-731,-733,-735,-736,-737,-737,-736,-735,
+-734,-732,-730,-727,-725,-722,-719,-716,-714,-711,-708,-705,-702,-699,-697,-694,-691,-688,-685,-683,-680,
+-676,-673,-670,-666,-662,-658,-654,-650,-645,-641,-636,-632,-627,-622,-618,-614,-610,-607,-604,-602,-600,
+-599,-598,-598,-599,-600,-602,-605,-608,-611,-616,-620,-625,-630,-635,-640,-645,-649,-653,-657,-660,-662,
+-663,-663,-662,-660,-657,-653,-648,-642,-635,-627,-618,-608,-598,-587,-576,-565,-554,-543,-533,-523,-513,
+-505,-497,-491,-486,-483,-480,-480,-481,-484,-488,-493,-501,-509,-520,-531,-544,-557,-572,-587,-604,-620,
+-637,-655,-672,-690,-707,-724,-741,-758,-774,-789,-804,-818,-832,-845,-858,-869,-881,-892,-902,-912,-922,
+-932,-941,-950,-959,-968,-977,-986,-995,-1004,-1013,-1023,-1032,-1042,-1052,-1062,-1072,-1082,-1092,-1103,-1113,-1124,
+-1134,-1144,-1155,-1165,-1175,-1185,-1195,-1204,-1214,-1223,-1233,-1242,-1252,-1261,-1270,-1280,-1289,-1299,-1308,-1318,-1328,
+-1339,-1349,-1360,-1371,-1383,-1394,-1406,-1419,-1431,-1444,-1457,-1470,-1483,-1496,-1510,-1523,-1536,-1550,-1563,-1576,-1589,
+-1602,-1615,-1627,-1640,-1652,-1664,-1676,-1687,-1699,-1710,-1722,-1733,-1745,-1756,-1768,-1779,-1791,-1804,-1816,-1829,-1842,
+-1855,-1868,-1882,-1896,-1910,-1925,-1940,-1955,-1970,-1985,-2000,-2015,-2030,-2045,-2059,-2074,-2088,-2102,-2115,-2128,-2141,
+-2153,-2165,-2177,-2188,-2200,-2210,-2221,-2232,-2242,-2253,-2264,-2275,-2286,-2297,-2309,-2321,-2334,-2347,-2361,-2376,-2391,
+-2406,-2423,-2440,-2457,-2475,-2494,-2513,-2532,-2552,-2571,-2591,-2612,-2632,-2652,-2672,-2692,-2712,-2732,-2751,-2770,-2788,
+-2807,-2825,-2842,-2860,-2877,-2894,-2910,-2927,-2943,-2960,-2976,-2992,-3008,-3025,-3041,-3058,-3074,-3091,-3108,-3126,-3143,
+-3161,-3178,-3196,-3214,-3232,-3249,-3267,-3285,-3302,-3319,-3336,-3353,-3369,-3384,-3400,-3415,-3429,-3443,-3456,-3469,-3481,
+-3493,-3504,-3515,-3525,-3535,-3544,-3553,-3561,-3569,-3577,-3584,-3591,-3598,-3604,-3610,-3616,-3622,-3628,-3633,-3638,-3643,
+-3648,-3653,-3657,-3662,-3666,-3671,-3675,-3679,-3684,-3688,-3692,-3697,-3701,-3706,-3710,-3715,-3720,-3725,-3731,-3736,-3742,
+-3748,-3754,-3760,-3766,-3772,-3778,-3784,-3790,-3796,-3802,-3807,-3812,-3817,-3822,-3826,-3830,-3833,-3836,-3838,-3840,-3841,
+-3841,-3842,-3841,-3840,-3839,-3838,-3836,-3834,-3832,-3830,-3828,-3826,-3825,-3823,-3822,-3821,-3821,-3821,-3821,-3822,-3824,
+-3826,-3828,-3830,-3833,-3836,-3839,-3842,-3845,-3848,-3850,-3851,-3852,-3852,-3851,-3848,-3845,-3840,-3833,-3826,-3816,-3805,
+-3793,-3779,-3764,-3747,-3729,-3709,-3689,-3668,-3646,-3624,-3601,-3578,-3556,-3534,-3512,-3491,-3471,-3452,-3434,-3418,-3403,
+-3390,-3378,-3368,-3360,-3353,-3348,-3345,-3343,-3343,-3343,-3345,-3348,-3352,-3357,-3362,-3368,-3374,-3380,-3386,-3393,-3400,
+-3406,-3413,-3420,-3426,-3433,-3440,-3447,-3455,-3463,-3471,-3481,-3491,-3502,-3514,-3527,-3542,-3558,-3575,-3593,-3613,-3634,
+-3657,-3681,-3705,-3731,-3757,-3785,-3812,-3840,-3868,-3896,-3923,-3950,-3976,-4001,-4025,-4047,-4069,-4088,-4106,-4123,-4137,
+-4150,-4162,-4172,-4180,-4188,-4194,-4198,-4203,-4206,-4209,-4212,-4214,-4217,-4220,-4223,-4227,-4231,-4237,-4243,-4250,-4257,
+-4266,-4276,-4286,-4297,-4308,-4320,-4333,-4345,-4357,-4370,-4382,-4393,-4404,-4414,-4424,-4432,-4440,-4446,-4451,-4456,-4459,
+-4460,-4461,-4461,-4461,-4459,-4457,-4454,-4451,-4448,-4445,-4441,-4438,-4436,-4433,-4432,-4431,-4430,-4431,-4432,-4433,-4436,
+-4439,-4442,-4447,-4451,-4457,-4462,-4467,-4473,-4478,-4484,-4489,-4494,-4498,-4502,-4505,-4507,-4509,-4510,-4511,-4511,-4510,
+-4508,-4506,-4504,-4501,-4498,-4494,-4490,-4487,-4483,-4479,-4475,-4472,-4468,-4466,-4463,-4461,-4459,-4457,-4456,-4456,-4455,
+-4455,-4456,-4457,-4458,-4459,-4460,-4462,-4464,-4465,-4467,-4469,-4471,-4472,-4474,-4475,-4476,-4477,-4478,-4478,-4479,-4479,
+-4479,-4478,-4478,-4477,-4476,-4474,-4472,-4470,-4468,-4465,-4463,-4459,-4456,-4452,-4448,-4444,-4439,-4434,-4429,-4423,-4418,
+-4412,-4406,-4400,-4393,-4387,-4380,-4374,-4367,-4360,-4354,-4348,-4341,-4335,-4329,-4323,-4317,-4312,-4306,-4301,-4296,-4291,
+-4286,-4281,-4277,-4272,-4267,-4263,-4258,-4253,-4248,-4243,-4238,-4232,-4227,-4221,-4216,-4210,-4204,-4198,-4192,-4186,-4180,
+-4174,-4168,-4163,-4157,-4152,-4147,-4142,-4138,-4134,-4130,-4127,-4124,-4121,-4118,-4116,-4113,-4111,-4109,-4107,-4105,-4103,
+-4101,-4098,-4095,-4092,-4089,-4085,-4081,-4076,-4071,-4066,-4060,-4054,-4047,-4040,-4033,-4026,-4018,-4010,-4003,-3995,-3988,
+-3980,-3973,-3966,-3959,-3953,-3947,-3942,-3936,-3931,-3927,-3923,-3919,-3915,-3911,-3908,-3905,-3901,-3898,-3894,-3890,-3886,
+-3881,-3876,-3870,-3864,-3857,-3850,-3842,-3833,-3824,-3814,-3804,-3794,-3783,-3772,-3761,-3749,-3738,-3727,-3715,-3704,-3694,
+-3684,-3674,-3665,-3657,-3649,-3642,-3635,-3629,-3624,-3620,-3616,-3613,-3610,-3607,-3605,-3603,-3600,-3598,-3596,-3593,-3590,
+-3586,-3582,-3576,-3570,-3563,-3555,-3546,-3536,-3524,-3511,-3498,-3483,-3466,-3449,-3431,-3412,-3392,-3371,-3350,-3328,-3306,
+-3283,-3261,-3238,-3216,-3195,-3173,-3153,-3133,-3114,-3096,-3080,-3064,-3050,-3036,-3024,-3014,-3004,-2996,-2990,-2984,-2979,
+-2976,-2973,-2972,-2971,-2970,-2971,-2971,-2972,-2973,-2974,-2975,-2976,-2977,-2977,-2977,-2977,-2976,-2975,-2973,-2970,-2968,
+-2964,-2960,-2956,-2952,-2947,-2942,-2936,-2931,-2925,-2920,-2915,-2909,-2904,-2900,-2895,-2891,-2887,-2884,-2881,-2878,-2875,
+-2873,-2872,-2870,-2869,-2869,-2868,-2867,-2867,-2867,-2867,-2866,-2866,-2866,-2866,-2866,-2866,-2865,-2865,-2865,-2865,-2864,
+-2864,-2864,-2864,-2864,-2864,-2864,-2865,-2865,-2866,-2866,-2867,-2867,-2868,-2869,-2869,-2869,-2870,-2869,-2869,-2868,-2867,
+-2865,-2863,-2860,-2856,-2852,-2847,-2841,-2835,-2828,-2821,-2813,-2804,-2795,-2785,-2775,-2764,-2753,-2742,-2731,-2720,-2709,
+-2697,-2686,-2675,-2664,-2654,-2644,-2634,-2624,-2614,-2605,-2596,-2588,-2579,-2571,-2563,-2555,-2547,-2540,-2532,-2524,-2517,
+-2509,-2502,-2494,-2487,-2480,-2473,-2466,-2459,-2453,-2447,-2442,-2437,-2433,-2430,-2427,-2426,-2425,-2426,-2427,-2430,-2434,
+-2438,-2444,-2451,-2459,-2467,-2476,-2486,-2497,-2507,-2518,-2529,-2539,-2549,-2559,-2567,-2575,-2581,-2586,-2589,-2591,-2590,
+-2588,-2584,-2577,-2569,-2558,-2546,-2531,-2515,-2496,-2476,-2455,-2432,-2408,-2383,-2357,-2332,-2306,-2280,-2254,-2229,-2205,
+-2182,-2160,-2140,-2121,-2104,-2089,-2076,-2065,-2056,-2049,-2044,-2041,-2040,-2040,-2043,-2047,-2052,-2058,-2065,-2073,-2082,
+-2090,-2099,-2108,-2117,-2125,-2132,-2139,-2145,-2149,-2153,-2155,-2156,-2155,-2154,-2150,-2146,-2141,-2134,-2126,-2117,-2107,
+-2097,-2086,-2074,-2062,-2049,-2037,-2024,-2012,-2000,-1988,-1976,-1965,-1954,-1944,-1934,-1925,-1917,-1909,-1901,-1894,-1887,
+-1880,-1874,-1868,-1863,-1857,-1851,-1845,-1840,-1834,-1828,-1822,-1816,-1809,-1803,-1796,-1790,-1783,-1777,-1770,-1764,-1758,
+-1752,-1747,-1742,-1737,-1734,-1731,-1728,-1727,-1726,-1726,-1727,-1729,-1732,-1735,-1739,-1743,-1748,-1754,-1760,-1766,-1772,
+-1779,-1785,-1791,-1796,-1802,-1806,-1810,-1813,-1816,-1817,-1818,-1818,-1817,-1815,-1812,-1808,-1803,-1798,-1792,-1785,-1778,
+-1770,-1762,-1754,-1746,-1738,-1729,-1721,-1713,-1705,-1697,-1689,-1682,-1675,-1669,-1662,-1656,-1650,-1644,-1639,-1633,-1627,
+-1622,-1616,-1610,-1603,-1597,-1590,-1582,-1575,-1567,-1559,-1550,-1541,-1532,-1523,-1513,-1503,-1494,-1484,-1475,-1465,-1456,
+-1448,-1440,-1432,-1425,-1418,-1412,-1406,-1401,-1397,-1394,-1391,-1388,-1386,-1384,-1383,-1382,-1381,-1381,-1380,-1380,-1379,
+-1379,-1378,-1377,-1376,-1374,-1373,-1371,-1369,-1366,-1364,-1361,-1359,-1356,-1353,-1351,-1349,-1347,-1345,-1344,-1343,-1343,
+-1343,-1344,-1345,-1347,-1350,-1353,-1357,-1361,-1365,-1370,-1376,-1381,-1387,-1392,-1398,-1403,-1408,-1413,-1463,-1467,-1471,
+-1474,-1477,-1480,-1482,-1483,-1484,-1484,-1484,-1484,-1483,-1482,-1480,-1478,-1476,-1473,-1471,-1468,-1465,-1461,-1458,-1455,
+-1451,-1448,-1444,-1440,-1437,-1433,-1428,-1424,-1420,-1415,-1410,-1404,-1399,-1393,-1386,-1379,-1372,-1365,-1357,-1348,-1340,
+-1331,-1322,-1313,-1303,-1294,-1285,-1276,-1267,-1258,-1250,-1243,-1235,-1229,-1223,-1218,-1213,-1209,-1206,-1204,-1203,-1202,
+-1201,-1202,-1202,-1203,-1205,-1206,-1208,-1209,-1210,-1211,-1211,-1211,-1210,-1208,-1206,-1202,-1197,-1191,-1184,-1175,-1166,
+-1155,-1143,-1130,-1115,-1100,-1083,-1066,-1048,-1029,-1010,-991,-971,-951,-931,-911,-891,-872,-853,-834,-817,-800,
+-783,-768,-754,-740,-727,-715,-704,-694,-685,-676,-669,-662,-655,-650,-644,-640,-635,-631,-628,-624,-621,
+-618,-615,-613,-610,-608,-606,-604,-602,-601,-600,-599,-598,-598,-598,-598,-599,-601,-603,-605,-608,-612,
+-616,-620,-625,-631,-637,-644,-651,-658,-665,-673,-681,-689,-696,-704,-712,-719,-726,-733,-739,-745,-750,
+-755,-759,-763,-766,-768,-770,-771,-772,-772,-771,-770,-769,-767,-765,-763,-760,-758,-755,-752,-749,-746,
+-743,-740,-737,-734,-731,-729,-726,-723,-720,-718,-715,-712,-709,-706,-703,-700,-697,-693,-689,-686,-682,
+-678,-674,-670,-666,-661,-657,-654,-650,-646,-643,-640,-638,-636,-634,-633,-632,-632,-633,-634,-635,-637,
+-640,-642,-646,-649,-653,-656,-660,-664,-667,-670,-673,-676,-678,-679,-680,-680,-680,-678,-676,-673,-670,
+-666,-661,-655,-649,-642,-636,-629,-621,-614,-607,-600,-594,-588,-583,-578,-574,-571,-569,-568,-568,-570,
+-572,-576,-580,-586,-593,-601,-610,-620,-630,-642,-654,-666,-679,-692,-706,-720,-733,-747,-761,-774,-788,
+-801,-813,-826,-838,-850,-861,-872,-883,-894,-904,-914,-923,-933,-943,-952,-961,-971,-980,-990,-999,-1009,
+-1019,-1029,-1039,-1049,-1059,-1070,-1080,-1091,-1102,-1112,-1123,-1134,-1145,-1156,-1166,-1177,-1188,-1198,-1209,-1219,-1230,
+-1240,-1250,-1261,-1271,-1281,-1292,-1302,-1313,-1324,-1335,-1346,-1357,-1369,-1380,-1392,-1405,-1417,-1430,-1443,-1456,-1469,
+-1483,-1497,-1510,-1524,-1538,-1552,-1566,-1580,-1593,-1607,-1620,-1633,-1646,-1659,-1672,-1684,-1696,-1708,-1720,-1731,-1742,
+-1754,-1765,-1776,-1787,-1798,-1809,-1821,-1832,-1844,-1856,-1868,-1880,-1893,-1905,-1919,-1932,-1945,-1959,-1973,-1987,-2001,
+-2016,-2030,-2044,-2058,-2072,-2086,-2099,-2113,-2126,-2138,-2151,-2162,-2174,-2185,-2196,-2207,-2217,-2227,-2237,-2246,-2256,
+-2266,-2275,-2285,-2295,-2305,-2316,-2327,-2338,-2350,-2362,-2375,-2388,-2403,-2417,-2432,-2448,-2465,-2482,-2499,-2517,-2535,
+-2554,-2573,-2592,-2611,-2630,-2649,-2669,-2688,-2707,-2725,-2744,-2762,-2780,-2798,-2815,-2832,-2849,-2865,-2881,-2897,-2913,
+-2929,-2945,-2960,-2976,-2992,-3008,-3024,-3040,-3056,-3073,-3090,-3107,-3124,-3142,-3159,-3177,-3195,-3214,-3232,-3250,-3269,
+-3287,-3305,-3323,-3340,-3358,-3375,-3391,-3407,-3423,-3438,-3452,-3466,-3479,-3492,-3504,-3515,-3526,-3536,-3546,-3555,-3563,
+-3571,-3578,-3585,-3591,-3597,-3603,-3609,-3614,-3619,-3623,-3628,-3632,-3636,-3640,-3644,-3648,-3652,-3656,-3660,-3664,-3667,
+-3671,-3675,-3679,-3683,-3687,-3691,-3695,-3699,-3703,-3707,-3711,-3715,-3719,-3723,-3727,-3731,-3735,-3739,-3743,-3747,-3751,
+-3755,-3758,-3762,-3765,-3768,-3772,-3775,-3777,-3780,-3782,-3785,-3786,-3788,-3790,-3792,-3793,-3794,-3795,-3796,-3797,-3798,
+-3799,-3800,-3800,-3801,-3802,-3803,-3803,-3804,-3805,-3806,-3807,-3808,-3809,-3810,-3811,-3811,-3812,-3813,-3813,-3813,-3812,
+-3811,-3810,-3808,-3806,-3803,-3800,-3795,-3791,-3785,-3779,-3772,-3764,-3756,-3747,-3737,-3727,-3716,-3705,-3693,-3681,-3669,
+-3657,-3644,-3631,-3619,-3606,-3594,-3581,-3569,-3557,-3546,-3535,-3524,-3514,-3504,-3494,-3485,-3476,-3467,-3459,-3451,-3443,
+-3435,-3428,-3421,-3414,-3407,-3400,-3393,-3387,-3381,-3376,-3370,-3366,-3362,-3359,-3357,-3355,-3355,-3357,-3359,-3363,-3369,
+-3377,-3386,-3398,-3411,-3427,-3444,-3464,-3486,-3509,-3535,-3562,-3591,-3621,-3652,-3685,-3718,-3751,-3785,-3819,-3852,-3885,
+-3917,-3948,-3977,-4005,-4031,-4056,-4078,-4098,-4115,-4131,-4144,-4155,-4163,-4170,-4175,-4178,-4179,-4179,-4178,-4176,-4174,
+-4171,-4169,-4166,-4165,-4163,-4163,-4164,-4167,-4171,-4176,-4183,-4192,-4202,-4214,-4227,-4242,-4259,-4276,-4294,-4313,-4333,
+-4353,-4373,-4393,-4412,-4431,-4449,-4466,-4481,-4495,-4508,-4519,-4528,-4536,-4541,-4545,-4547,-4548,-4547,-4544,-4541,-4536,
+-4530,-4523,-4515,-4507,-4499,-4491,-4482,-4474,-4467,-4459,-4453,-4447,-4442,-4437,-4434,-4431,-4429,-4428,-4428,-4428,-4429,
+-4431,-4433,-4436,-4438,-4441,-4444,-4447,-4450,-4453,-4455,-4457,-4459,-4460,-4461,-4462,-4462,-4461,-4460,-4459,-4457,-4455,
+-4452,-4449,-4446,-4443,-4440,-4437,-4434,-4431,-4428,-4425,-4423,-4421,-4419,-4417,-4416,-4415,-4415,-4415,-4415,-4416,-4416,
+-4418,-4419,-4421,-4423,-4425,-4428,-4430,-4433,-4436,-4438,-4441,-4444,-4446,-4449,-4451,-4453,-4455,-4457,-4458,-4459,-4460,
+-4460,-4460,-4460,-4459,-4458,-4457,-4455,-4453,-4450,-4447,-4443,-4439,-4435,-4431,-4426,-4420,-4415,-4409,-4403,-4397,-4390,
+-4383,-4377,-4370,-4362,-4355,-4348,-4340,-4333,-4325,-4317,-4310,-4302,-4294,-4286,-4278,-4270,-4262,-4254,-4246,-4238,-4229,
+-4221,-4213,-4205,-4196,-4188,-4180,-4172,-4163,-4156,-4148,-4140,-4133,-4126,-4119,-4113,-4107,-4101,-4095,-4090,-4086,-4081,
+-4078,-4074,-4071,-4068,-4065,-4063,-4061,-4059,-4057,-4055,-4053,-4052,-4049,-4047,-4045,-4042,-4039,-4036,-4032,-4028,-4023,
+-4019,-4013,-4008,-4002,-3996,-3989,-3982,-3976,-3969,-3962,-3955,-3948,-3941,-3935,-3929,-3923,-3917,-3912,-3907,-3903,-3899,
+-3896,-3893,-3890,-3888,-3886,-3884,-3883,-3882,-3880,-3879,-3878,-3876,-3874,-3872,-3869,-3866,-3863,-3858,-3854,-3848,-3842,
+-3835,-3828,-3820,-3811,-3802,-3792,-3782,-3772,-3761,-3750,-3739,-3728,-3716,-3705,-3694,-3684,-3674,-3664,-3654,-3646,-3637,
+-3629,-3622,-3615,-3609,-3603,-3598,-3593,-3589,-3584,-3580,-3576,-3572,-3568,-3563,-3558,-3553,-3547,-3541,-3534,-3527,-3518,
+-3509,-3499,-3489,-3477,-3464,-3451,-3437,-3422,-3407,-3391,-3374,-3357,-3340,-3322,-3305,-3287,-3270,-3252,-3235,-3219,-3202,
+-3187,-3172,-3157,-3144,-3131,-3119,-3107,-3097,-3087,-3078,-3070,-3062,-3055,-3048,-3042,-3037,-3031,-3026,-3021,-3017,-3012,
+-3007,-3002,-2997,-2991,-2986,-2980,-2973,-2967,-2960,-2953,-2945,-2937,-2930,-2922,-2914,-2905,-2897,-2889,-2882,-2874,-2867,
+-2860,-2853,-2847,-2842,-2837,-2832,-2828,-2825,-2822,-2820,-2819,-2817,-2817,-2817,-2817,-2817,-2818,-2819,-2820,-2821,-2823,
+-2824,-2826,-2827,-2828,-2830,-2831,-2832,-2833,-2834,-2835,-2836,-2837,-2838,-2839,-2840,-2841,-2843,-2844,-2846,-2848,-2851,
+-2853,-2856,-2860,-2863,-2867,-2870,-2874,-2878,-2882,-2887,-2890,-2894,-2898,-2901,-2904,-2907,-2909,-2910,-2911,-2911,-2910,
+-2909,-2907,-2904,-2900,-2896,-2890,-2884,-2877,-2870,-2862,-2853,-2844,-2834,-2824,-2814,-2803,-2792,-2781,-2769,-2757,-2746,
+-2734,-2722,-2710,-2698,-2686,-2674,-2662,-2649,-2637,-2625,-2613,-2600,-2588,-2575,-2563,-2550,-2538,-2526,-2513,-2501,-2489,
+-2477,-2466,-2455,-2445,-2435,-2426,-2417,-2410,-2403,-2398,-2393,-2390,-2388,-2387,-2387,-2389,-2392,-2396,-2402,-2409,-2416,
+-2425,-2434,-2445,-2455,-2467,-2478,-2490,-2502,-2513,-2524,-2534,-2544,-2552,-2560,-2566,-2571,-2574,-2576,-2577,-2575,-2572,
+-2568,-2561,-2553,-2544,-2533,-2521,-2508,-2493,-2478,-2462,-2446,-2429,-2413,-2396,-2379,-2363,-2348,-2333,-2320,-2307,-2296,
+-2285,-2276,-2269,-2263,-2258,-2254,-2252,-2251,-2251,-2253,-2255,-2258,-2262,-2267,-2271,-2277,-2282,-2287,-2292,-2296,-2300,
+-2304,-2307,-2308,-2309,-2309,-2308,-2305,-2302,-2297,-2291,-2284,-2276,-2267,-2256,-2245,-2233,-2220,-2206,-2191,-2176,-2161,
+-2145,-2129,-2113,-2096,-2080,-2064,-2047,-2031,-2015,-2000,-1984,-1970,-1955,-1941,-1927,-1914,-1901,-1889,-1877,-1866,-1855,
+-1845,-1835,-1826,-1818,-1810,-1803,-1796,-1790,-1785,-1780,-1776,-1773,-1771,-1769,-1768,-1768,-1768,-1770,-1772,-1774,-1778,
+-1782,-1786,-1791,-1797,-1802,-1809,-1815,-1822,-1828,-1835,-1841,-1847,-1853,-1859,-1864,-1868,-1872,-1876,-1878,-1880,-1881,
+-1882,-1881,-1880,-1878,-1875,-1872,-1868,-1863,-1858,-1852,-1845,-1839,-1832,-1824,-1817,-1809,-1801,-1794,-1786,-1778,-1770,
+-1763,-1755,-1748,-1740,-1733,-1726,-1718,-1711,-1704,-1697,-1690,-1682,-1675,-1667,-1660,-1652,-1643,-1635,-1627,-1618,-1609,
+-1600,-1591,-1581,-1572,-1563,-1553,-1544,-1535,-1527,-1518,-1510,-1502,-1495,-1488,-1482,-1476,-1471,-1466,-1462,-1458,-1455,
+-1453,-1451,-1449,-1448,-1447,-1446,-1445,-1445,-1444,-1444,-1443,-1443,-1442,-1441,-1440,-1439,-1437,-1435,-1433,-1431,-1429,
+-1426,-1423,-1420,-1418,-1415,-1412,-1410,-1407,-1405,-1404,-1403,-1402,-1401,-1402,-1402,-1404,-1405,-1408,-1410,-1414,-1417,
+-1421,-1425,-1430,-1435,-1440,-1445,-1449,-1454,-1459,-1463,-1504,-1506,-1509,-1512,-1514,-1516,-1519,-1521,-1523,-1525,-1526,
+-1528,-1529,-1531,-1532,-1533,-1534,-1534,-1535,-1535,-1536,-1536,-1535,-1535,-1534,-1533,-1532,-1531,-1528,-1526,-1523,-1520,
+-1516,-1511,-1506,-1500,-1493,-1486,-1478,-1470,-1460,-1451,-1440,-1429,-1418,-1406,-1394,-1382,-1370,-1357,-1345,-1333,-1321,
+-1309,-1298,-1288,-1278,-1269,-1260,-1253,-1246,-1240,-1236,-1232,-1229,-1227,-1226,-1226,-1227,-1228,-1230,-1232,-1235,-1237,
+-1240,-1243,-1246,-1248,-1250,-1252,-1252,-1252,-1251,-1249,-1246,-1242,-1237,-1230,-1222,-1214,-1204,-1192,-1180,-1167,-1153,
+-1138,-1122,-1106,-1089,-1072,-1054,-1037,-1019,-1001,-984,-967,-950,-934,-918,-903,-888,-875,-862,-850,-838,-828,
+-818,-809,-801,-793,-786,-780,-774,-768,-763,-759,-755,-751,-747,-744,-741,-738,-735,-732,-730,-727,-725,
+-723,-720,-718,-717,-715,-714,-713,-712,-712,-712,-712,-713,-714,-716,-718,-721,-724,-727,-731,-735,-740,
+-745,-750,-755,-760,-766,-771,-777,-782,-787,-792,-797,-802,-806,-810,-813,-816,-819,-821,-822,-823,-824,
+-824,-824,-823,-822,-820,-818,-816,-814,-811,-808,-805,-802,-799,-796,-792,-789,-786,-782,-779,-776,-772,
+-769,-766,-763,-760,-757,-753,-750,-747,-744,-741,-738,-735,-731,-728,-725,-722,-719,-716,-713,-711,-708,
+-706,-703,-701,-700,-698,-697,-696,-696,-696,-696,-696,-697,-698,-699,-700,-702,-704,-706,-708,-710,-712,
+-713,-715,-717,-718,-719,-720,-720,-720,-719,-718,-717,-715,-713,-711,-708,-704,-701,-697,-693,-689,-685,
+-681,-677,-673,-670,-666,-664,-661,-660,-658,-658,-658,-658,-660,-662,-665,-669,-673,-678,-684,-690,-697,
+-705,-713,-722,-731,-740,-750,-760,-770,-781,-791,-802,-813,-824,-834,-845,-856,-866,-877,-887,-898,-908,
+-918,-928,-939,-949,-959,-969,-980,-990,-1000,-1010,-1021,-1031,-1042,-1053,-1063,-1074,-1085,-1096,-1107,-1117,-1128,
+-1139,-1150,-1161,-1172,-1183,-1194,-1204,-1215,-1226,-1236,-1247,-1258,-1268,-1279,-1290,-1300,-1311,-1322,-1333,-1345,-1356,
+-1368,-1380,-1392,-1404,-1417,-1430,-1443,-1456,-1470,-1484,-1498,-1512,-1526,-1541,-1555,-1570,-1584,-1599,-1613,-1627,-1642,
+-1656,-1669,-1683,-1696,-1710,-1722,-1735,-1747,-1759,-1771,-1783,-1794,-1805,-1816,-1827,-1838,-1849,-1859,-1870,-1881,-1892,
+-1903,-1914,-1925,-1937,-1948,-1960,-1972,-1984,-1996,-2008,-2021,-2034,-2046,-2059,-2071,-2084,-2096,-2109,-2121,-2133,-2145,
+-2156,-2168,-2179,-2189,-2200,-2210,-2220,-2229,-2239,-2248,-2257,-2266,-2275,-2284,-2293,-2302,-2312,-2321,-2331,-2341,-2352,
+-2363,-2374,-2386,-2399,-2412,-2425,-2439,-2454,-2469,-2485,-2501,-2517,-2534,-2552,-2569,-2587,-2605,-2623,-2641,-2660,-2678,
+-2696,-2714,-2732,-2750,-2768,-2785,-2803,-2820,-2837,-2853,-2870,-2886,-2903,-2919,-2935,-2951,-2967,-2983,-2999,-3015,-3031,
+-3048,-3064,-3081,-3098,-3115,-3132,-3150,-3167,-3185,-3203,-3221,-3239,-3257,-3274,-3292,-3310,-3327,-3345,-3362,-3378,-3395,
+-3411,-3426,-3441,-3456,-3470,-3483,-3496,-3509,-3520,-3532,-3542,-3552,-3562,-3571,-3579,-3588,-3595,-3602,-3609,-3615,-3622,
+-3627,-3633,-3638,-3643,-3647,-3652,-3656,-3660,-3664,-3667,-3671,-3674,-3677,-3680,-3683,-3686,-3689,-3692,-3694,-3697,-3699,
+-3701,-3703,-3706,-3708,-3710,-3712,-3714,-3715,-3718,-3719,-3721,-3723,-3726,-3728,-3730,-3732,-3734,-3737,-3739,-3742,-3744,
+-3747,-3750,-3753,-3756,-3758,-3761,-3764,-3767,-3770,-3773,-3776,-3778,-3781,-3783,-3786,-3788,-3790,-3791,-3793,-3794,-3795,
+-3795,-3796,-3796,-3795,-3795,-3794,-3793,-3791,-3790,-3788,-3785,-3783,-3780,-3777,-3774,-3771,-3767,-3764,-3760,-3757,-3753,
+-3749,-3746,-3742,-3738,-3735,-3731,-3728,-3724,-3721,-3718,-3714,-3711,-3707,-3704,-3700,-3696,-3692,-3688,-3683,-3678,-3672,
+-3666,-3659,-3651,-3643,-3633,-3623,-3612,-3601,-3588,-3574,-3560,-3545,-3529,-3512,-3495,-3477,-3459,-3440,-3422,-3404,-3386,
+-3369,-3352,-3337,-3322,-3310,-3298,-3289,-3282,-3277,-3274,-3275,-3278,-3284,-3292,-3304,-3319,-3337,-3358,-3382,-3408,-3437,
+-3469,-3503,-3538,-3576,-3614,-3654,-3694,-3735,-3775,-3815,-3855,-3893,-3930,-3965,-3998,-4029,-4057,-4082,-4105,-4125,-4141,
+-4155,-4165,-4173,-4178,-4180,-4180,-4177,-4172,-4166,-4159,-4150,-4141,-4131,-4121,-4112,-4104,-4096,-4090,-4085,-4082,-4082,
+-4083,-4087,-4093,-4102,-4113,-4126,-4142,-4160,-4180,-4201,-4225,-4250,-4275,-4302,-4329,-4356,-4383,-4410,-4436,-4461,-4484,
+-4506,-4527,-4545,-4561,-4575,-4587,-4597,-4604,-4609,-4611,-4611,-4609,-4605,-4600,-4592,-4584,-4573,-4562,-4551,-4538,-4525,
+-4512,-4499,-4487,-4474,-4463,-4452,-4442,-4432,-4424,-4417,-4411,-4406,-4402,-4399,-4397,-4396,-4396,-4396,-4398,-4400,-4402,
+-4404,-4407,-4410,-4413,-4415,-4418,-4420,-4422,-4423,-4424,-4425,-4425,-4424,-4423,-4421,-4419,-4416,-4413,-4409,-4405,-4401,
+-4397,-4392,-4388,-4383,-4379,-4375,-4371,-4367,-4364,-4361,-4359,-4357,-4355,-4355,-4355,-4355,-4356,-4358,-4360,-4363,-4367,
+-4371,-4376,-4381,-4386,-4392,-4398,-4404,-4410,-4417,-4423,-4429,-4435,-4441,-4447,-4452,-4457,-4462,-4465,-4469,-4471,-4473,
+-4475,-4475,-4475,-4474,-4473,-4470,-4467,-4463,-4458,-4453,-4447,-4440,-4433,-4425,-4416,-4407,-4398,-4388,-4377,-4366,-4355,
+-4344,-4332,-4321,-4309,-4297,-4285,-4272,-4260,-4248,-4236,-4224,-4213,-4201,-4190,-4179,-4168,-4157,-4147,-4137,-4128,-4119,
+-4110,-4101,-4094,-4086,-4079,-4072,-4066,-4060,-4055,-4050,-4045,-4041,-4037,-4033,-4030,-4027,-4024,-4021,-4018,-4016,-4013,
+-4011,-4008,-4005,-4002,-3999,-3996,-3992,-3988,-3984,-3980,-3975,-3970,-3965,-3959,-3954,-3948,-3942,-3936,-3929,-3923,-3917,
+-3911,-3905,-3899,-3894,-3889,-3884,-3880,-3876,-3872,-3869,-3867,-3865,-3863,-3862,-3862,-3861,-3862,-3862,-3863,-3864,-3865,
+-3866,-3867,-3868,-3868,-3868,-3868,-3868,-3867,-3865,-3863,-3860,-3857,-3852,-3847,-3841,-3835,-3827,-3819,-3811,-3801,-3792,
+-3781,-3771,-3760,-3748,-3737,-3725,-3714,-3702,-3691,-3679,-3669,-3658,-3648,-3638,-3629,-3620,-3611,-3603,-3596,-3589,-3582,
+-3575,-3569,-3563,-3557,-3552,-3546,-3540,-3535,-3529,-3522,-3516,-3509,-3502,-3494,-3486,-3478,-3468,-3459,-3448,-3438,-3427,
+-3415,-3403,-3390,-3377,-3364,-3351,-3338,-3324,-3310,-3297,-3283,-3270,-3257,-3244,-3231,-3219,-3207,-3195,-3183,-3172,-3162,
+-3151,-3141,-3131,-3122,-3112,-3103,-3093,-3084,-3075,-3066,-3056,-3047,-3037,-3027,-3017,-3006,-2995,-2984,-2973,-2961,-2950,
+-2938,-2926,-2914,-2902,-2890,-2878,-2866,-2854,-2843,-2832,-2822,-2812,-2803,-2794,-2786,-2779,-2773,-2767,-2762,-2758,-2755,
+-2753,-2751,-2751,-2751,-2751,-2752,-2754,-2757,-2760,-2763,-2767,-2771,-2775,-2779,-2784,-2788,-2793,-2798,-2803,-2807,-2812,
+-2817,-2822,-2826,-2831,-2836,-2841,-2845,-2850,-2855,-2860,-2865,-2871,-2876,-2882,-2887,-2893,-2899,-2905,-2912,-2918,-2924,
+-2930,-2936,-2942,-2948,-2954,-2959,-2964,-2969,-2973,-2977,-2980,-2983,-2984,-2986,-2986,-2986,-2985,-2984,-2981,-2978,-2974,
+-2970,-2965,-2959,-2952,-2945,-2938,-2930,-2921,-2912,-2902,-2892,-2881,-2871,-2859,-2848,-2835,-2823,-2810,-2797,-2783,-2769,
+-2755,-2740,-2725,-2710,-2694,-2677,-2660,-2643,-2626,-2608,-2590,-2573,-2554,-2536,-2518,-2501,-2483,-2466,-2450,-2434,-2419,
+-2405,-2392,-2381,-2370,-2361,-2353,-2347,-2343,-2340,-2339,-2340,-2343,-2347,-2353,-2361,-2370,-2381,-2393,-2407,-2421,-2436,
+-2452,-2469,-2486,-2503,-2520,-2537,-2554,-2569,-2584,-2598,-2611,-2623,-2633,-2642,-2649,-2655,-2659,-2661,-2661,-2660,-2657,
+-2653,-2647,-2640,-2632,-2622,-2612,-2601,-2589,-2577,-2564,-2552,-2539,-2527,-2515,-2503,-2492,-2482,-2473,-2465,-2457,-2451,
+-2445,-2441,-2437,-2435,-2433,-2432,-2432,-2433,-2434,-2435,-2437,-2439,-2441,-2443,-2444,-2446,-2446,-2446,-2445,-2444,-2441,
+-2437,-2432,-2426,-2419,-2410,-2400,-2389,-2377,-2363,-2348,-2331,-2314,-2296,-2276,-2256,-2235,-2213,-2191,-2169,-2146,-2123,
+-2100,-2076,-2054,-2031,-2009,-1988,-1967,-1947,-1928,-1910,-1893,-1877,-1862,-1848,-1836,-1825,-1816,-1808,-1801,-1795,-1792,
+-1789,-1788,-1788,-1789,-1791,-1795,-1799,-1804,-1811,-1818,-1825,-1834,-1842,-1851,-1861,-1870,-1879,-1889,-1898,-1907,-1915,
+-1923,-1931,-1938,-1944,-1949,-1954,-1958,-1961,-1963,-1964,-1965,-1964,-1963,-1962,-1959,-1956,-1952,-1947,-1942,-1937,-1931,
+-1925,-1919,-1912,-1905,-1898,-1892,-1885,-1878,-1871,-1864,-1858,-1851,-1845,-1839,-1832,-1826,-1820,-1813,-1807,-1800,-1794,
+-1787,-1780,-1773,-1765,-1758,-1750,-1741,-1733,-1724,-1715,-1705,-1695,-1685,-1675,-1665,-1655,-1644,-1634,-1623,-1613,-1603,
+-1593,-1584,-1575,-1566,-1558,-1550,-1543,-1536,-1530,-1525,-1520,-1516,-1512,-1509,-1506,-1504,-1502,-1501,-1499,-1499,-1498,
+-1498,-1497,-1497,-1497,-1497,-1497,-1496,-1496,-1495,-1495,-1494,-1493,-1492,-1490,-1489,-1487,-1486,-1484,-1482,-1481,-1479,
+-1478,-1477,-1476,-1475,-1474,-1474,-1473,-1474,-1474,-1475,-1476,-1477,-1479,-1480,-1483,-1485,-1487,-1490,-1492,-1495,-1498,
+-1501,-1504,-1524,-1524,-1525,-1525,-1526,-1527,-1529,-1530,-1532,-1534,-1536,-1539,-1542,-1545,-1548,-1551,-1554,-1558,-1561,
+-1564,-1568,-1571,-1574,-1576,-1578,-1580,-1582,-1582,-1583,-1582,-1581,-1579,-1576,-1573,-1568,-1563,-1557,-1550,-1542,-1533,
+-1523,-1512,-1501,-1489,-1477,-1463,-1450,-1436,-1422,-1408,-1394,-1380,-1366,-1353,-1340,-1328,-1316,-1306,-1296,-1287,-1278,
+-1271,-1265,-1260,-1257,-1254,-1252,-1251,-1251,-1252,-1254,-1256,-1259,-1262,-1265,-1269,-1273,-1276,-1280,-1283,-1285,-1287,
+-1289,-1289,-1289,-1288,-1285,-1282,-1278,-1272,-1266,-1258,-1249,-1240,-1229,-1217,-1205,-1192,-1178,-1164,-1149,-1134,-1119,
+-1103,-1088,-1072,-1057,-1042,-1027,-1013,-999,-986,-973,-961,-950,-939,-928,-919,-910,-902,-894,-887,-880,-874,
+-868,-863,-858,-853,-849,-845,-841,-837,-833,-830,-826,-823,-820,-817,-814,-811,-808,-805,-803,-800,-798,
+-797,-795,-794,-793,-792,-792,-792,-793,-794,-796,-797,-800,-802,-805,-809,-813,-816,-821,-825,-830,-834,
+-839,-844,-848,-853,-857,-861,-866,-869,-873,-876,-878,-881,-883,-884,-885,-886,-886,-886,-886,-885,-884,
+-882,-880,-878,-876,-873,-870,-867,-864,-861,-858,-854,-851,-847,-844,-840,-837,-834,-830,-827,-824,-821,
+-818,-815,-813,-810,-808,-806,-804,-802,-800,-798,-797,-796,-794,-793,-793,-792,-792,-791,-791,-791,-792,
+-792,-793,-793,-794,-795,-796,-797,-798,-799,-800,-801,-802,-803,-803,-804,-804,-804,-804,-804,-804,-803,
+-802,-801,-800,-798,-797,-795,-793,-791,-788,-786,-783,-781,-779,-776,-774,-772,-770,-769,-767,-766,-766,
+-765,-766,-766,-767,-769,-771,-773,-776,-779,-783,-788,-793,-798,-804,-810,-816,-823,-831,-838,-846,-854,
+-863,-871,-880,-889,-899,-908,-918,-927,-937,-947,-957,-968,-978,-988,-999,-1009,-1020,-1031,-1042,-1052,-1063,
+-1074,-1085,-1096,-1107,-1118,-1129,-1140,-1151,-1162,-1173,-1184,-1194,-1205,-1216,-1226,-1237,-1247,-1257,-1268,-1278,-1288,
+-1298,-1308,-1318,-1329,-1339,-1349,-1360,-1370,-1381,-1392,-1403,-1414,-1426,-1438,-1450,-1462,-1474,-1487,-1500,-1514,-1527,
+-1541,-1555,-1569,-1583,-1598,-1612,-1627,-1641,-1655,-1670,-1684,-1698,-1712,-1726,-1740,-1753,-1766,-1779,-1792,-1804,-1816,
+-1828,-1839,-1850,-1861,-1872,-1882,-1893,-1903,-1913,-1923,-1933,-1942,-1952,-1962,-1972,-1982,-1992,-2002,-2012,-2023,-2033,
+-2044,-2054,-2065,-2076,-2087,-2098,-2109,-2120,-2130,-2141,-2152,-2163,-2173,-2183,-2194,-2204,-2213,-2223,-2233,-2242,-2251,
+-2260,-2269,-2278,-2287,-2296,-2305,-2313,-2322,-2332,-2341,-2350,-2360,-2370,-2381,-2392,-2403,-2414,-2426,-2439,-2452,-2465,
+-2479,-2493,-2508,-2523,-2538,-2554,-2570,-2587,-2603,-2620,-2637,-2655,-2672,-2690,-2707,-2725,-2742,-2760,-2777,-2795,-2812,
+-2829,-2846,-2863,-2880,-2897,-2913,-2930,-2946,-2963,-2979,-2995,-3012,-3028,-3044,-3060,-3076,-3093,-3109,-3125,-3142,-3158,
+-3174,-3191,-3207,-3223,-3239,-3255,-3272,-3288,-3303,-3319,-3334,-3350,-3365,-3379,-3394,-3408,-3422,-3436,-3449,-3461,-3474,
+-3486,-3497,-3509,-3520,-3530,-3540,-3550,-3559,-3568,-3576,-3584,-3592,-3599,-3606,-3613,-3619,-3625,-3630,-3635,-3640,-3645,
+-3649,-3653,-3657,-3660,-3663,-3666,-3668,-3671,-3672,-3674,-3676,-3677,-3678,-3679,-3680,-3681,-3682,-3683,-3683,-3684,-3685,
+-3686,-3686,-3687,-3688,-3690,-3691,-3693,-3694,-3696,-3699,-3701,-3704,-3706,-3709,-3713,-3716,-3719,-3723,-3726,-3730,-3734,
+-3737,-3740,-3744,-3747,-3750,-3752,-3754,-3757,-3758,-3759,-3760,-3760,-3760,-3760,-3759,-3757,-3756,-3753,-3751,-3748,-3745,
+-3741,-3738,-3734,-3730,-3726,-3722,-3719,-3715,-3712,-3709,-3707,-3704,-3703,-3701,-3700,-3700,-3700,-3701,-3702,-3703,-3705,
+-3707,-3709,-3711,-3714,-3716,-3718,-3720,-3722,-3723,-3723,-3723,-3722,-3719,-3716,-3711,-3705,-3697,-3689,-3678,-3667,-3653,
+-3638,-3622,-3604,-3586,-3566,-3545,-3523,-3500,-3477,-3454,-3431,-3408,-3386,-3365,-3344,-3325,-3308,-3293,-3279,-3268,-3260,
+-3255,-3252,-3253,-3257,-3265,-3275,-3289,-3306,-3327,-3351,-3377,-3407,-3438,-3473,-3509,-3546,-3585,-3625,-3666,-3707,-3747,
+-3787,-3826,-3864,-3899,-3933,-3965,-3994,-4020,-4043,-4063,-4080,-4093,-4103,-4110,-4113,-4114,-4111,-4106,-4098,-4088,-4076,
+-4063,-4048,-4033,-4017,-4001,-3985,-3970,-3956,-3944,-3933,-3924,-3918,-3914,-3912,-3913,-3918,-3925,-3935,-3948,-3964,-3982,
+-4003,-4026,-4051,-4079,-4107,-4137,-4168,-4199,-4230,-4262,-4293,-4323,-4352,-4380,-4406,-4430,-4452,-4472,-4489,-4504,-4517,
+-4527,-4534,-4539,-4541,-4541,-4539,-4534,-4528,-4520,-4510,-4499,-4487,-4475,-4462,-4448,-4434,-4421,-4407,-4395,-4383,-4371,
+-4361,-4352,-4344,-4337,-4331,-4326,-4323,-4321,-4320,-4320,-4321,-4323,-4325,-4328,-4332,-4336,-4340,-4345,-4349,-4353,-4357,
+-4360,-4364,-4366,-4368,-4369,-4369,-4369,-4368,-4366,-4363,-4360,-4356,-4352,-4346,-4341,-4335,-4329,-4323,-4317,-4310,-4304,
+-4299,-4293,-4289,-4284,-4281,-4278,-4276,-4275,-4274,-4275,-4276,-4279,-4282,-4287,-4292,-4298,-4305,-4312,-4321,-4329,-4339,
+-4348,-4358,-4368,-4378,-4388,-4398,-4408,-4417,-4425,-4434,-4441,-4448,-4453,-4458,-4462,-4465,-4467,-4468,-4467,-4466,-4463,
+-4460,-4455,-4449,-4442,-4434,-4425,-4415,-4405,-4394,-4382,-4369,-4356,-4342,-4329,-4314,-4300,-4286,-4271,-4257,-4242,-4228,
+-4214,-4200,-4187,-4174,-4161,-4149,-4137,-4126,-4115,-4105,-4095,-4086,-4077,-4069,-4061,-4054,-4047,-4041,-4035,-4029,-4024,
+-4019,-4014,-4010,-4006,-4002,-3997,-3994,-3990,-3986,-3982,-3978,-3973,-3969,-3965,-3960,-3955,-3950,-3945,-3940,-3934,-3929,
+-3923,-3917,-3911,-3905,-3899,-3893,-3887,-3881,-3876,-3870,-3865,-3860,-3855,-3851,-3847,-3843,-3840,-3837,-3835,-3833,-3832,
+-3831,-3831,-3831,-3831,-3832,-3833,-3834,-3836,-3837,-3839,-3841,-3843,-3844,-3845,-3846,-3847,-3847,-3847,-3846,-3845,-3842,
+-3840,-3836,-3832,-3827,-3821,-3814,-3807,-3799,-3790,-3781,-3771,-3761,-3750,-3739,-3728,-3716,-3704,-3693,-3681,-3670,-3659,
+-3647,-3637,-3627,-3617,-3608,-3599,-3590,-3583,-3575,-3569,-3562,-3557,-3551,-3546,-3542,-3538,-3533,-3529,-3526,-3522,-3518,
+-3514,-3509,-3504,-3500,-3494,-3488,-3482,-3475,-3468,-3460,-3451,-3442,-3432,-3422,-3411,-3400,-3389,-3376,-3364,-3351,-3338,
+-3325,-3312,-3298,-3285,-3271,-3258,-3245,-3232,-3219,-3206,-3193,-3181,-3169,-3157,-3145,-3133,-3122,-3111,-3100,-3088,-3077,
+-3066,-3055,-3044,-3033,-3022,-3011,-2999,-2987,-2975,-2963,-2951,-2939,-2926,-2914,-2901,-2888,-2876,-2863,-2850,-2838,-2826,
+-2814,-2802,-2791,-2781,-2771,-2761,-2752,-2744,-2736,-2730,-2724,-2719,-2715,-2711,-2709,-2707,-2707,-2707,-2708,-2709,-2712,
+-2715,-2719,-2723,-2729,-2734,-2741,-2747,-2754,-2762,-2770,-2778,-2786,-2795,-2803,-2812,-2821,-2830,-2839,-2848,-2857,-2867,
+-2876,-2884,-2893,-2902,-2910,-2919,-2927,-2935,-2943,-2950,-2957,-2964,-2971,-2977,-2983,-2988,-2993,-2997,-3001,-3004,-3007,
+-3010,-3011,-3012,-3013,-3013,-3013,-3011,-3010,-3008,-3005,-3002,-2998,-2994,-2989,-2984,-2978,-2973,-2966,-2960,-2953,-2946,
+-2938,-2930,-2922,-2914,-2905,-2895,-2886,-2876,-2865,-2854,-2843,-2831,-2818,-2805,-2792,-2777,-2762,-2747,-2730,-2713,-2696,
+-2678,-2659,-2640,-2620,-2600,-2580,-2560,-2539,-2519,-2499,-2479,-2460,-2441,-2423,-2406,-2391,-2376,-2363,-2351,-2341,-2332,
+-2326,-2321,-2318,-2318,-2319,-2322,-2328,-2335,-2344,-2355,-2368,-2383,-2399,-2416,-2434,-2453,-2473,-2494,-2514,-2535,-2556,
+-2576,-2596,-2615,-2633,-2650,-2665,-2679,-2692,-2702,-2712,-2719,-2724,-2728,-2729,-2729,-2727,-2723,-2718,-2711,-2703,-2694,
+-2683,-2672,-2660,-2647,-2635,-2622,-2608,-2596,-2583,-2571,-2559,-2549,-2539,-2530,-2522,-2515,-2509,-2504,-2500,-2497,-2495,
+-2494,-2493,-2493,-2494,-2495,-2497,-2498,-2500,-2501,-2502,-2502,-2502,-2500,-2498,-2495,-2490,-2485,-2477,-2469,-2458,-2446,
+-2433,-2418,-2401,-2383,-2363,-2342,-2320,-2296,-2272,-2246,-2220,-2193,-2166,-2138,-2111,-2083,-2056,-2029,-2003,-1978,-1953,
+-1930,-1908,-1888,-1869,-1851,-1836,-1822,-1810,-1800,-1792,-1786,-1782,-1779,-1779,-1780,-1783,-1787,-1793,-1800,-1809,-1818,
+-1829,-1840,-1851,-1864,-1876,-1889,-1901,-1913,-1925,-1937,-1948,-1958,-1968,-1976,-1984,-1991,-1997,-2001,-2005,-2007,-2008,
+-2009,-2008,-2006,-2003,-2000,-1995,-1990,-1985,-1979,-1972,-1965,-1958,-1951,-1943,-1936,-1928,-1921,-1914,-1907,-1901,-1894,
+-1888,-1882,-1877,-1872,-1867,-1862,-1858,-1853,-1849,-1845,-1841,-1837,-1832,-1828,-1823,-1818,-1813,-1807,-1801,-1794,-1787,
+-1780,-1772,-1764,-1755,-1746,-1737,-1727,-1717,-1706,-1696,-1685,-1674,-1664,-1653,-1643,-1632,-1622,-1613,-1604,-1595,-1587,
+-1579,-1572,-1565,-1559,-1554,-1549,-1545,-1542,-1539,-1536,-1535,-1533,-1532,-1532,-1532,-1532,-1533,-1534,-1535,-1536,-1537,
+-1538,-1539,-1541,-1542,-1543,-1544,-1544,-1545,-1546,-1546,-1546,-1546,-1546,-1545,-1545,-1544,-1543,-1542,-1541,-1540,-1538,
+-1537,-1536,-1534,-1533,-1532,-1530,-1529,-1528,-1527,-1526,-1525,-1525,-1524,-1524,-1524,-1536,-1533,-1531,-1530,-1529,-1528,
+-1528,-1529,-1530,-1531,-1533,-1536,-1538,-1542,-1545,-1549,-1554,-1558,-1563,-1567,-1572,-1577,-1581,-1586,-1590,-1593,-1597,
+-1599,-1601,-1602,-1603,-1603,-1602,-1600,-1597,-1593,-1588,-1582,-1575,-1567,-1559,-1549,-1539,-1528,-1516,-1504,-1491,-1478,
+-1464,-1451,-1437,-1424,-1410,-1397,-1384,-1372,-1360,-1350,-1339,-1330,-1321,-1314,-1307,-1301,-1297,-1293,-1290,-1288,-1287,
+-1287,-1288,-1289,-1291,-1293,-1296,-1299,-1302,-1305,-1308,-1311,-1313,-1315,-1317,-1318,-1319,-1319,-1318,-1316,-1313,-1309,
+-1305,-1300,-1293,-1286,-1278,-1269,-1259,-1249,-1238,-1226,-1214,-1202,-1189,-1176,-1163,-1150,-1136,-1123,-1110,-1098,-1085,
+-1073,-1061,-1050,-1039,-1029,-1019,-1010,-1001,-992,-984,-977,-970,-963,-957,-951,-945,-940,-935,-930,-925,-921,
+-916,-912,-908,-904,-900,-896,-892,-888,-884,-880,-877,-874,-870,-867,-864,-862,-860,-858,-856,-855,-854,
+-853,-853,-853,-854,-855,-857,-859,-861,-864,-867,-871,-874,-878,-882,-887,-891,-896,-901,-905,-910,-915,
+-919,-923,-927,-931,-935,-938,-941,-943,-946,-948,-949,-950,-951,-951,-951,-951,-950,-949,-948,-947,-945,
+-943,-941,-938,-936,-933,-930,-928,-925,-922,-919,-917,-914,-912,-910,-907,-905,-903,-902,-900,-899,-898,
+-897,-896,-896,-895,-895,-895,-895,-896,-896,-897,-898,-899,-900,-901,-902,-903,-904,-906,-907,-908,-909,
+-910,-911,-912,-913,-914,-915,-915,-915,-916,-916,-916,-916,-915,-915,-914,-914,-913,-912,-911,-910,-909,
+-908,-907,-906,-905,-904,-903,-902,-902,-901,-901,-901,-901,-902,-902,-903,-905,-906,-908,-911,-913,-916,
+-919,-923,-927,-931,-936,-941,-946,-951,-957,-964,-970,-977,-984,-991,-999,-1007,-1015,-1024,-1032,-1041,-1050,
+-1059,-1069,-1079,-1088,-1098,-1108,-1119,-1129,-1140,-1150,-1161,-1171,-1182,-1193,-1203,-1214,-1225,-1235,-1246,-1257,-1267,
+-1278,-1288,-1298,-1308,-1318,-1328,-1338,-1348,-1357,-1367,-1377,-1386,-1396,-1405,-1415,-1424,-1434,-1443,-1453,-1463,-1473,
+-1483,-1494,-1504,-1515,-1526,-1537,-1549,-1561,-1572,-1585,-1597,-1610,-1623,-1636,-1649,-1662,-1675,-1689,-1702,-1716,-1729,
+-1743,-1756,-1770,-1783,-1796,-1809,-1821,-1834,-1846,-1858,-1869,-1881,-1892,-1903,-1913,-1923,-1934,-1943,-1953,-1962,-1972,
+-1981,-1990,-1999,-2008,-2017,-2026,-2035,-2043,-2052,-2061,-2071,-2080,-2089,-2098,-2108,-2118,-2127,-2137,-2147,-2157,-2167,
+-2177,-2187,-2197,-2207,-2216,-2226,-2236,-2246,-2256,-2265,-2275,-2284,-2294,-2303,-2312,-2322,-2331,-2340,-2349,-2358,-2368,
+-2377,-2386,-2396,-2406,-2416,-2426,-2436,-2447,-2458,-2469,-2480,-2492,-2504,-2517,-2529,-2543,-2556,-2570,-2584,-2599,-2613,
+-2628,-2644,-2659,-2675,-2691,-2707,-2723,-2740,-2756,-2773,-2789,-2806,-2822,-2839,-2855,-2872,-2888,-2904,-2921,-2937,-2953,
+-2968,-2984,-3000,-3015,-3031,-3046,-3061,-3076,-3091,-3105,-3120,-3134,-3149,-3163,-3177,-3191,-3205,-3219,-3232,-3246,-3259,
+-3272,-3285,-3298,-3311,-3324,-3336,-3348,-3361,-3372,-3384,-3396,-3407,-3418,-3429,-3440,-3450,-3460,-3470,-3479,-3489,-3498,
+-3507,-3515,-3523,-3531,-3539,-3546,-3553,-3559,-3565,-3571,-3577,-3582,-3587,-3591,-3595,-3599,-3602,-3605,-3608,-3610,-3612,
+-3614,-3616,-3617,-3618,-3619,-3620,-3621,-3621,-3622,-3622,-3623,-3624,-3624,-3625,-3626,-3627,-3629,-3630,-3632,-3634,-3636,
+-3639,-3642,-3645,-3648,-3651,-3655,-3659,-3663,-3667,-3671,-3675,-3679,-3683,-3687,-3690,-3694,-3697,-3700,-3702,-3704,-3706,
+-3707,-3708,-3708,-3708,-3707,-3706,-3704,-3702,-3699,-3697,-3693,-3690,-3686,-3682,-3678,-3674,-3670,-3666,-3663,-3659,-3656,
+-3654,-3652,-3650,-3649,-3648,-3649,-3649,-3651,-3653,-3656,-3659,-3663,-3667,-3672,-3676,-3682,-3687,-3692,-3697,-3702,-3706,
+-3710,-3713,-3715,-3716,-3717,-3716,-3714,-3711,-3706,-3700,-3693,-3684,-3673,-3662,-3649,-3634,-3619,-3602,-3585,-3567,-3548,
+-3529,-3510,-3491,-3472,-3454,-3436,-3420,-3405,-3392,-3380,-3370,-3362,-3357,-3354,-3354,-3356,-3361,-3368,-3378,-3391,-3407,
+-3425,-3445,-3468,-3492,-3519,-3546,-3575,-3605,-3636,-3666,-3697,-3728,-3757,-3786,-3813,-3839,-3863,-3885,-3904,-3921,-3935,
+-3947,-3955,-3961,-3963,-3963,-3960,-3954,-3945,-3935,-3922,-3907,-3890,-3872,-3853,-3834,-3814,-3794,-3774,-3756,-3738,-3721,
+-3706,-3693,-3683,-3674,-3669,-3665,-3665,-3668,-3674,-3682,-3694,-3708,-3725,-3744,-3766,-3790,-3816,-3843,-3872,-3902,-3932,
+-3963,-3994,-4025,-4055,-4085,-4113,-4140,-4166,-4189,-4211,-4231,-4249,-4264,-4277,-4287,-4295,-4301,-4305,-4306,-4306,-4303,
+-4299,-4294,-4287,-4279,-4270,-4260,-4250,-4240,-4229,-4219,-4209,-4200,-4191,-4184,-4177,-4171,-4166,-4163,-4160,-4159,-4159,
+-4161,-4163,-4166,-4170,-4176,-4181,-4188,-4195,-4202,-4209,-4217,-4224,-4232,-4239,-4245,-4251,-4256,-4261,-4265,-4268,-4270,
+-4271,-4272,-4271,-4270,-4268,-4265,-4262,-4258,-4253,-4248,-4243,-4238,-4233,-4227,-4222,-4217,-4213,-4209,-4206,-4203,-4201,
+-4200,-4200,-4200,-4202,-4205,-4208,-4213,-4218,-4224,-4231,-4239,-4247,-4256,-4266,-4275,-4285,-4296,-4306,-4316,-4326,-4336,
+-4345,-4354,-4362,-4369,-4376,-4381,-4386,-4390,-4392,-4394,-4394,-4394,-4392,-4389,-4385,-4379,-4373,-4366,-4358,-4349,-4339,
+-4328,-4317,-4305,-4293,-4280,-4268,-4254,-4241,-4228,-4215,-4202,-4189,-4176,-4163,-4151,-4140,-4128,-4118,-4107,-4097,-4088,
+-4079,-4070,-4062,-4055,-4047,-4040,-4034,-4028,-4022,-4016,-4010,-4005,-3999,-3994,-3989,-3983,-3978,-3972,-3967,-3961,-3955,
+-3949,-3942,-3936,-3929,-3922,-3916,-3909,-3901,-3894,-3887,-3880,-3873,-3865,-3859,-3852,-3845,-3839,-3833,-3828,-3822,-3818,
+-3813,-3809,-3806,-3803,-3801,-3799,-3798,-3797,-3797,-3797,-3797,-3798,-3800,-3801,-3803,-3805,-3807,-3809,-3811,-3812,-3814,
+-3815,-3816,-3816,-3816,-3815,-3814,-3812,-3809,-3805,-3801,-3795,-3789,-3782,-3774,-3765,-3756,-3746,-3735,-3723,-3711,-3699,
+-3686,-3673,-3659,-3646,-3632,-3619,-3606,-3593,-3581,-3569,-3557,-3547,-3536,-3527,-3519,-3511,-3504,-3498,-3493,-3489,-3486,
+-3483,-3481,-3480,-3480,-3480,-3480,-3481,-3482,-3483,-3485,-3486,-3487,-3488,-3488,-3488,-3487,-3486,-3484,-3481,-3477,-3472,
+-3467,-3460,-3453,-3444,-3435,-3424,-3413,-3401,-3388,-3374,-3360,-3345,-3330,-3314,-3298,-3282,-3265,-3249,-3232,-3216,-3199,
+-3183,-3167,-3152,-3137,-3122,-3108,-3094,-3081,-3068,-3056,-3044,-3033,-3022,-3011,-3001,-2991,-2982,-2972,-2963,-2954,-2945,
+-2936,-2927,-2918,-2909,-2900,-2891,-2882,-2872,-2863,-2853,-2843,-2833,-2823,-2813,-2803,-2793,-2783,-2773,-2763,-2754,-2745,
+-2736,-2728,-2720,-2712,-2705,-2699,-2694,-2689,-2685,-2681,-2679,-2677,-2676,-2676,-2677,-2679,-2682,-2685,-2690,-2695,-2701,
+-2708,-2716,-2724,-2733,-2742,-2753,-2763,-2774,-2785,-2797,-2809,-2821,-2833,-2845,-2857,-2869,-2881,-2892,-2904,-2914,-2925,
+-2935,-2944,-2953,-2961,-2968,-2975,-2981,-2986,-2990,-2994,-2997,-2999,-3000,-3000,-3000,-2999,-2997,-2995,-2991,-2988,-2984,
+-2979,-2973,-2968,-2962,-2955,-2949,-2942,-2935,-2927,-2920,-2912,-2904,-2897,-2889,-2881,-2872,-2864,-2856,-2847,-2838,-2829,
+-2820,-2810,-2800,-2789,-2778,-2767,-2754,-2742,-2729,-2715,-2700,-2685,-2669,-2653,-2636,-2618,-2600,-2582,-2563,-2544,-2525,
+-2505,-2486,-2467,-2448,-2430,-2412,-2396,-2380,-2365,-2351,-2338,-2327,-2318,-2310,-2304,-2299,-2297,-2296,-2298,-2301,-2306,
+-2313,-2321,-2332,-2344,-2357,-2372,-2388,-2405,-2423,-2441,-2460,-2479,-2498,-2517,-2536,-2554,-2572,-2588,-2604,-2618,-2631,
+-2643,-2652,-2661,-2667,-2672,-2675,-2677,-2676,-2674,-2671,-2666,-2659,-2652,-2643,-2633,-2623,-2612,-2601,-2589,-2577,-2565,
+-2554,-2543,-2532,-2523,-2514,-2505,-2498,-2492,-2487,-2483,-2480,-2478,-2478,-2478,-2479,-2481,-2483,-2486,-2490,-2493,-2497,
+-2500,-2504,-2507,-2509,-2510,-2511,-2510,-2508,-2505,-2500,-2494,-2486,-2476,-2464,-2450,-2435,-2418,-2399,-2378,-2356,-2333,
+-2307,-2281,-2254,-2226,-2197,-2167,-2137,-2108,-2078,-2048,-2019,-1991,-1964,-1938,-1913,-1889,-1868,-1848,-1829,-1813,-1799,
+-1787,-1777,-1769,-1763,-1759,-1757,-1757,-1759,-1763,-1769,-1775,-1784,-1793,-1804,-1815,-1827,-1839,-1852,-1865,-1878,-1890,
+-1902,-1914,-1925,-1935,-1945,-1953,-1961,-1967,-1972,-1976,-1978,-1980,-1980,-1979,-1977,-1974,-1970,-1965,-1959,-1953,-1946,
+-1938,-1930,-1922,-1913,-1905,-1896,-1888,-1880,-1872,-1864,-1857,-1850,-1844,-1838,-1832,-1827,-1823,-1819,-1815,-1812,-1809,
+-1807,-1805,-1803,-1801,-1799,-1797,-1795,-1792,-1790,-1787,-1784,-1781,-1777,-1772,-1768,-1762,-1756,-1750,-1743,-1736,-1728,
+-1720,-1712,-1703,-1694,-1684,-1675,-1665,-1656,-1647,-1637,-1628,-1620,-1611,-1603,-1596,-1588,-1582,-1576,-1571,-1566,-1562,
+-1558,-1556,-1553,-1552,-1551,-1551,-1551,-1552,-1553,-1554,-1556,-1558,-1561,-1563,-1566,-1569,-1572,-1575,-1578,-1580,-1583,
+-1585,-1587,-1588,-1589,-1590,-1591,-1591,-1591,-1590,-1589,-1588,-1586,-1584,-1581,-1579,-1576,-1572,-1569,-1566,-1562,-1558,
+-1555,-1551,-1547,-1544,-1541,-1538,-1536,-1549,-1546,-1543,-1541,-1540,-1539,-1538,-1538,-1538,-1539,-1540,-1542,-1545,-1548,
+-1551,-1555,-1559,-1563,-1567,-1572,-1577,-1581,-1586,-1590,-1595,-1598,-1602,-1605,-1607,-1610,-1611,-1611,-1611,-1610,-1609,
+-1606,-1603,-1598,-1593,-1587,-1581,-1573,-1565,-1556,-1547,-1537,-1527,-1516,-1505,-1494,-1483,-1471,-1460,-1449,-1439,-1428,
+-1418,-1409,-1400,-1392,-1385,-1378,-1372,-1366,-1362,-1358,-1355,-1353,-1351,-1350,-1350,-1350,-1351,-1352,-1353,-1355,-1356,
+-1358,-1360,-1362,-1364,-1365,-1366,-1367,-1367,-1366,-1365,-1364,-1361,-1358,-1355,-1350,-1345,-1340,-1333,-1326,-1318,-1310,
+-1301,-1292,-1282,-1272,-1261,-1250,-1240,-1229,-1217,-1206,-1195,-1184,-1174,-1163,-1153,-1143,-1133,-1124,-1115,-1106,-1098,
+-1090,-1082,-1075,-1068,-1062,-1055,-1049,-1043,-1038,-1033,-1027,-1022,-1017,-1013,-1008,-1003,-999,-994,-989,-985,-981,
+-976,-972,-967,-963,-959,-955,-951,-948,-944,-941,-938,-935,-933,-931,-929,-927,-926,-926,-925,-925,-926,
+-927,-928,-930,-932,-934,-937,-940,-943,-947,-950,-954,-958,-962,-967,-971,-975,-979,-983,-987,-991,-995,
+-998,-1002,-1005,-1007,-1010,-1012,-1014,-1016,-1017,-1018,-1019,-1020,-1020,-1020,-1020,-1020,-1019,-1018,-1018,-1017,-1016,
+-1014,-1013,-1012,-1011,-1010,-1009,-1008,-1007,-1006,-1005,-1004,-1004,-1003,-1003,-1003,-1003,-1003,-1003,-1004,-1004,-1005,
+-1006,-1007,-1008,-1009,-1010,-1011,-1013,-1014,-1015,-1017,-1018,-1020,-1021,-1022,-1024,-1025,-1026,-1028,-1029,-1030,-1031,
+-1032,-1033,-1034,-1034,-1035,-1036,-1036,-1037,-1038,-1038,-1039,-1039,-1040,-1040,-1041,-1042,-1042,-1043,-1044,-1045,-1046,
+-1047,-1049,-1050,-1052,-1054,-1056,-1058,-1060,-1063,-1066,-1069,-1072,-1075,-1079,-1083,-1087,-1091,-1096,-1101,-1106,-1111,
+-1117,-1123,-1129,-1135,-1142,-1149,-1156,-1163,-1171,-1178,-1186,-1195,-1203,-1211,-1220,-1229,-1238,-1248,-1257,-1266,-1276,
+-1286,-1296,-1306,-1316,-1326,-1336,-1346,-1356,-1366,-1376,-1386,-1396,-1405,-1415,-1425,-1435,-1444,-1454,-1463,-1473,-1482,
+-1491,-1501,-1510,-1519,-1528,-1537,-1547,-1556,-1565,-1575,-1584,-1594,-1603,-1613,-1623,-1633,-1643,-1654,-1664,-1675,-1686,
+-1697,-1708,-1719,-1731,-1743,-1754,-1766,-1778,-1790,-1802,-1814,-1826,-1838,-1849,-1861,-1873,-1884,-1896,-1907,-1918,-1929,
+-1939,-1950,-1960,-1970,-1979,-1989,-1998,-2007,-2016,-2025,-2034,-2042,-2051,-2059,-2067,-2075,-2084,-2092,-2100,-2108,-2116,
+-2125,-2133,-2141,-2150,-2159,-2167,-2176,-2186,-2195,-2204,-2213,-2223,-2233,-2242,-2252,-2262,-2272,-2282,-2292,-2302,-2312,
+-2322,-2332,-2342,-2352,-2362,-2372,-2382,-2392,-2402,-2412,-2421,-2431,-2441,-2450,-2460,-2470,-2480,-2490,-2500,-2510,-2520,
+-2530,-2541,-2552,-2563,-2574,-2585,-2596,-2608,-2620,-2632,-2645,-2658,-2671,-2684,-2697,-2711,-2725,-2739,-2753,-2767,-2782,
+-2796,-2811,-2826,-2841,-2856,-2871,-2886,-2901,-2916,-2930,-2945,-2960,-2975,-2989,-3004,-3018,-3032,-3046,-3060,-3073,-3087,
+-3100,-3113,-3126,-3139,-3151,-3163,-3176,-3188,-3199,-3211,-3222,-3234,-3245,-3256,-3266,-3277,-3287,-3298,-3308,-3318,-3328,
+-3338,-3347,-3357,-3366,-3375,-3384,-3393,-3401,-3410,-3418,-3426,-3434,-3441,-3449,-3456,-3463,-3469,-3476,-3482,-3488,-3493,
+-3498,-3503,-3508,-3512,-3516,-3520,-3523,-3526,-3529,-3532,-3534,-3536,-3538,-3540,-3541,-3543,-3544,-3545,-3546,-3547,-3548,
+-3549,-3550,-3552,-3553,-3554,-3556,-3558,-3560,-3562,-3565,-3568,-3571,-3574,-3578,-3582,-3586,-3590,-3594,-3599,-3604,-3609,
+-3613,-3618,-3623,-3628,-3632,-3637,-3641,-3645,-3649,-3652,-3655,-3658,-3660,-3661,-3662,-3663,-3663,-3663,-3663,-3661,-3660,
+-3658,-3656,-3653,-3651,-3648,-3645,-3642,-3639,-3636,-3633,-3630,-3628,-3626,-3624,-3623,-3622,-3622,-3622,-3624,-3625,-3627,
+-3630,-3634,-3638,-3642,-3647,-3652,-3658,-3664,-3670,-3676,-3683,-3689,-3695,-3700,-3706,-3710,-3714,-3718,-3720,-3722,-3723,
+-3723,-3722,-3720,-3717,-3713,-3707,-3701,-3694,-3686,-3678,-3669,-3659,-3649,-3638,-3627,-3617,-3606,-3596,-3586,-3577,-3568,
+-3561,-3554,-3549,-3544,-3541,-3540,-3540,-3541,-3544,-3549,-3555,-3563,-3571,-3582,-3593,-3605,-3619,-3633,-3647,-3662,-3677,
+-3692,-3707,-3721,-3734,-3747,-3758,-3769,-3777,-3785,-3790,-3794,-3795,-3795,-3793,-3788,-3782,-3773,-3763,-3750,-3736,-3721,
+-3704,-3686,-3667,-3647,-3627,-3606,-3586,-3565,-3546,-3527,-3509,-3492,-3477,-3463,-3452,-3442,-3435,-3430,-3427,-3427,-3429,
+-3434,-3442,-3451,-3463,-3478,-3494,-3512,-3533,-3554,-3577,-3601,-3626,-3651,-3677,-3703,-3729,-3754,-3779,-3803,-3826,-3847,
+-3868,-3887,-3904,-3919,-3933,-3945,-3955,-3963,-3970,-3975,-3978,-3979,-3979,-3978,-3976,-3972,-3968,-3963,-3958,-3952,-3946,
+-3940,-3935,-3929,-3925,-3921,-3917,-3915,-3914,-3913,-3914,-3916,-3919,-3923,-3928,-3934,-3942,-3950,-3959,-3969,-3979,-3990,
+-4002,-4013,-4025,-4037,-4049,-4061,-4072,-4083,-4094,-4104,-4113,-4122,-4130,-4137,-4143,-4149,-4153,-4157,-4160,-4162,-4164,
+-4164,-4165,-4164,-4164,-4163,-4162,-4160,-4159,-4158,-4156,-4155,-4154,-4154,-4154,-4154,-4155,-4157,-4159,-4162,-4165,-4168,
+-4173,-4178,-4183,-4189,-4195,-4201,-4208,-4215,-4222,-4229,-4235,-4242,-4248,-4255,-4260,-4265,-4270,-4274,-4277,-4280,-4282,
+-4283,-4283,-4283,-4281,-4279,-4276,-4272,-4267,-4262,-4256,-4249,-4242,-4234,-4226,-4217,-4208,-4199,-4189,-4179,-4169,-4160,
+-4150,-4140,-4130,-4121,-4112,-4103,-4094,-4085,-4077,-4069,-4061,-4054,-4047,-4040,-4033,-4026,-4019,-4013,-4007,-4000,-3994,
+-3987,-3981,-3974,-3968,-3961,-3953,-3946,-3939,-3931,-3923,-3915,-3906,-3897,-3889,-3880,-3871,-3862,-3853,-3844,-3835,-3826,
+-3817,-3809,-3801,-3793,-3786,-3779,-3773,-3768,-3763,-3758,-3754,-3752,-3749,-3747,-3747,-3746,-3747,-3747,-3749,-3751,-3753,
+-3756,-3759,-3763,-3766,-3770,-3773,-3776,-3779,-3782,-3784,-3786,-3787,-3787,-3787,-3786,-3783,-3780,-3775,-3770,-3763,-3756,
+-3747,-3737,-3726,-3714,-3701,-3687,-3672,-3657,-3641,-3624,-3607,-3590,-3572,-3554,-3537,-3520,-3503,-3486,-3471,-3456,-3441,
+-3428,-3416,-3405,-3395,-3387,-3379,-3374,-3369,-3366,-3364,-3363,-3364,-3365,-3368,-3372,-3377,-3382,-3388,-3395,-3401,-3409,
+-3416,-3423,-3429,-3436,-3442,-3447,-3451,-3455,-3457,-3459,-3459,-3458,-3455,-3451,-3446,-3439,-3431,-3421,-3410,-3398,-3385,
+-3370,-3354,-3337,-3320,-3302,-3283,-3263,-3243,-3223,-3203,-3183,-3162,-3143,-3123,-3104,-3086,-3068,-3051,-3034,-3019,-3004,
+-2990,-2977,-2966,-2954,-2944,-2935,-2927,-2919,-2912,-2905,-2899,-2894,-2889,-2884,-2880,-2875,-2871,-2867,-2863,-2858,-2853,
+-2848,-2843,-2837,-2831,-2824,-2817,-2810,-2802,-2794,-2785,-2776,-2766,-2757,-2747,-2737,-2727,-2717,-2707,-2697,-2688,-2679,
+-2670,-2662,-2654,-2648,-2641,-2636,-2632,-2628,-2626,-2624,-2624,-2625,-2626,-2629,-2633,-2638,-2645,-2652,-2660,-2669,-2679,
+-2690,-2701,-2714,-2726,-2740,-2753,-2767,-2781,-2796,-2810,-2824,-2838,-2851,-2865,-2877,-2889,-2901,-2912,-2922,-2931,-2939,
+-2947,-2953,-2959,-2963,-2967,-2969,-2971,-2971,-2971,-2970,-2968,-2965,-2961,-2956,-2951,-2945,-2939,-2932,-2924,-2917,-2908,
+-2900,-2891,-2881,-2872,-2862,-2852,-2842,-2832,-2821,-2811,-2800,-2789,-2777,-2765,-2754,-2741,-2729,-2716,-2703,-2689,-2675,
+-2660,-2645,-2630,-2614,-2597,-2581,-2563,-2546,-2528,-2510,-2492,-2474,-2455,-2437,-2419,-2401,-2384,-2367,-2350,-2335,-2320,
+-2306,-2293,-2282,-2271,-2262,-2255,-2249,-2244,-2241,-2239,-2239,-2241,-2244,-2249,-2256,-2263,-2273,-2283,-2294,-2307,-2320,
+-2335,-2349,-2364,-2380,-2395,-2411,-2426,-2441,-2456,-2469,-2482,-2494,-2505,-2515,-2524,-2532,-2538,-2543,-2546,-2548,-2549,
+-2549,-2547,-2545,-2541,-2536,-2531,-2525,-2519,-2512,-2504,-2497,-2490,-2483,-2476,-2470,-2464,-2459,-2455,-2452,-2449,-2448,
+-2447,-2448,-2449,-2451,-2455,-2459,-2464,-2470,-2476,-2483,-2490,-2497,-2504,-2511,-2518,-2524,-2529,-2534,-2537,-2539,-2540,
+-2540,-2538,-2534,-2528,-2521,-2511,-2500,-2486,-2471,-2454,-2434,-2413,-2391,-2366,-2340,-2313,-2285,-2255,-2225,-2194,-2163,
+-2131,-2099,-2068,-2037,-2007,-1977,-1949,-1921,-1895,-1871,-1848,-1827,-1808,-1790,-1775,-1762,-1750,-1741,-1734,-1728,-1725,
+-1723,-1724,-1726,-1729,-1733,-1739,-1746,-1754,-1763,-1772,-1782,-1791,-1801,-1811,-1821,-1830,-1839,-1847,-1854,-1861,-1867,
+-1872,-1876,-1879,-1880,-1881,-1881,-1880,-1878,-1875,-1871,-1866,-1861,-1855,-1848,-1842,-1834,-1827,-1819,-1812,-1804,-1797,
+-1789,-1782,-1776,-1770,-1764,-1758,-1753,-1749,-1745,-1742,-1739,-1737,-1735,-1733,-1732,-1731,-1730,-1730,-1729,-1729,-1728,
+-1728,-1727,-1727,-1726,-1725,-1723,-1721,-1719,-1716,-1713,-1709,-1705,-1700,-1695,-1690,-1684,-1678,-1672,-1665,-1658,-1651,
+-1644,-1637,-1630,-1623,-1616,-1610,-1603,-1597,-1592,-1586,-1582,-1577,-1573,-1570,-1567,-1565,-1564,-1563,-1562,-1562,-1563,
+-1564,-1565,-1567,-1569,-1571,-1574,-1577,-1580,-1583,-1586,-1589,-1592,-1595,-1598,-1600,-1602,-1604,-1606,-1607,-1607,-1607,
+-1607,-1607,-1606,-1604,-1602,-1600,-1597,-1594,-1591,-1587,-1583,-1579,-1575,-1571,-1567,-1563,-1559,-1556,-1552,-1549,-1560,
+-1558,-1557,-1555,-1554,-1554,-1554,-1554,-1555,-1556,-1557,-1559,-1561,-1563,-1566,-1569,-1572,-1575,-1579,-1583,-1586,-1590,
+-1593,-1597,-1600,-1603,-1605,-1608,-1610,-1611,-1612,-1612,-1612,-1611,-1610,-1608,-1606,-1603,-1599,-1594,-1590,-1584,-1578,
+-1572,-1565,-1558,-1550,-1543,-1535,-1527,-1519,-1511,-1503,-1495,-1488,-1480,-1473,-1467,-1460,-1455,-1449,-1444,-1440,-1436,
+-1433,-1430,-1428,-1426,-1425,-1424,-1424,-1424,-1424,-1425,-1426,-1426,-1427,-1428,-1429,-1430,-1431,-1432,-1432,-1432,-1431,
+-1431,-1429,-1428,-1425,-1423,-1419,-1415,-1411,-1406,-1400,-1394,-1388,-1381,-1374,-1366,-1358,-1349,-1340,-1331,-1322,-1313,
+-1304,-1294,-1285,-1276,-1266,-1257,-1248,-1240,-1231,-1223,-1215,-1207,-1199,-1192,-1185,-1178,-1172,-1165,-1159,-1154,-1148,
+-1143,-1137,-1132,-1127,-1122,-1118,-1113,-1108,-1104,-1099,-1095,-1090,-1086,-1081,-1077,-1072,-1068,-1063,-1059,-1055,-1050,
+-1046,-1042,-1038,-1035,-1031,-1028,-1025,-1022,-1019,-1017,-1015,-1014,-1012,-1011,-1010,-1010,-1010,-1011,-1011,-1012,-1014,
+-1015,-1017,-1019,-1022,-1024,-1027,-1030,-1034,-1037,-1040,-1044,-1048,-1051,-1055,-1059,-1062,-1066,-1069,-1072,-1076,-1079,
+-1082,-1085,-1087,-1090,-1092,-1094,-1096,-1098,-1100,-1101,-1103,-1104,-1105,-1106,-1107,-1108,-1109,-1109,-1110,-1110,-1111,
+-1111,-1112,-1112,-1113,-1113,-1114,-1115,-1115,-1116,-1117,-1117,-1118,-1119,-1120,-1121,-1122,-1123,-1124,-1125,-1126,-1127,
+-1128,-1130,-1131,-1132,-1134,-1135,-1136,-1138,-1139,-1140,-1142,-1143,-1144,-1146,-1147,-1149,-1150,-1152,-1153,-1154,-1156,
+-1158,-1159,-1161,-1162,-1164,-1166,-1168,-1169,-1171,-1173,-1176,-1178,-1180,-1182,-1185,-1188,-1190,-1193,-1196,-1199,-1202,
+-1206,-1209,-1213,-1216,-1220,-1224,-1229,-1233,-1238,-1242,-1247,-1253,-1258,-1263,-1269,-1275,-1281,-1287,-1294,-1301,-1307,
+-1314,-1322,-1329,-1337,-1345,-1353,-1361,-1369,-1378,-1386,-1395,-1404,-1413,-1422,-1431,-1441,-1450,-1460,-1469,-1479,-1488,
+-1498,-1508,-1517,-1527,-1537,-1546,-1556,-1566,-1575,-1585,-1594,-1604,-1613,-1623,-1632,-1641,-1651,-1660,-1670,-1679,-1689,
+-1698,-1707,-1717,-1727,-1736,-1746,-1756,-1766,-1776,-1786,-1796,-1806,-1816,-1826,-1836,-1847,-1857,-1867,-1878,-1888,-1899,
+-1909,-1919,-1930,-1940,-1950,-1960,-1970,-1980,-1989,-1999,-2008,-2017,-2027,-2035,-2044,-2053,-2061,-2069,-2078,-2085,-2093,
+-2101,-2109,-2116,-2124,-2131,-2138,-2146,-2153,-2160,-2168,-2175,-2182,-2190,-2198,-2205,-2213,-2221,-2229,-2238,-2246,-2255,
+-2263,-2272,-2281,-2291,-2300,-2309,-2319,-2329,-2338,-2348,-2358,-2368,-2378,-2388,-2398,-2409,-2419,-2429,-2439,-2449,-2459,
+-2469,-2479,-2489,-2499,-2509,-2519,-2529,-2539,-2549,-2559,-2569,-2579,-2589,-2599,-2609,-2619,-2630,-2640,-2650,-2661,-2672,
+-2683,-2694,-2705,-2716,-2728,-2739,-2751,-2763,-2775,-2788,-2800,-2813,-2826,-2839,-2852,-2865,-2878,-2891,-2904,-2918,-2931,
+-2945,-2958,-2971,-2985,-2998,-3011,-3025,-3038,-3050,-3063,-3076,-3088,-3101,-3113,-3125,-3137,-3148,-3160,-3171,-3182,-3193,
+-3204,-3214,-3224,-3234,-3244,-3254,-3263,-3273,-3282,-3291,-3299,-3308,-3316,-3324,-3332,-3340,-3348,-3355,-3362,-3369,-3376,
+-3383,-3389,-3396,-3402,-3408,-3413,-3419,-3424,-3429,-3433,-3438,-3442,-3446,-3450,-3453,-3457,-3460,-3463,-3465,-3468,-3470,
+-3472,-3474,-3476,-3477,-3479,-3480,-3482,-3483,-3485,-3486,-3487,-3489,-3490,-3492,-3494,-3496,-3498,-3500,-3503,-3506,-3509,
+-3512,-3515,-3519,-3523,-3527,-3532,-3536,-3541,-3546,-3551,-3556,-3562,-3567,-3572,-3578,-3583,-3588,-3593,-3598,-3603,-3607,
+-3611,-3615,-3619,-3622,-3625,-3627,-3629,-3631,-3632,-3633,-3634,-3634,-3634,-3633,-3633,-3632,-3630,-3629,-3628,-3626,-3625,
+-3623,-3622,-3621,-3620,-3619,-3619,-3619,-3619,-3620,-3621,-3623,-3625,-3627,-3631,-3634,-3638,-3643,-3648,-3653,-3659,-3665,
+-3671,-3678,-3684,-3691,-3698,-3704,-3711,-3717,-3723,-3729,-3734,-3739,-3743,-3747,-3750,-3752,-3754,-3756,-3756,-3756,-3756,
+-3754,-3753,-3750,-3748,-3744,-3741,-3737,-3733,-3728,-3724,-3719,-3715,-3711,-3707,-3703,-3699,-3696,-3693,-3690,-3688,-3686,
+-3685,-3684,-3684,-3684,-3684,-3685,-3686,-3687,-3688,-3689,-3690,-3690,-3691,-3691,-3691,-3690,-3688,-3686,-3683,-3679,-3673,
+-3667,-3660,-3652,-3643,-3632,-3620,-3608,-3594,-3580,-3564,-3548,-3531,-3514,-3496,-3478,-3460,-3442,-3424,-3407,-3390,-3373,
+-3358,-3343,-3330,-3318,-3307,-3298,-3290,-3284,-3280,-3277,-3277,-3278,-3281,-3286,-3292,-3300,-3310,-3321,-3334,-3348,-3363,
+-3379,-3395,-3413,-3431,-3449,-3467,-3485,-3503,-3521,-3538,-3555,-3571,-3586,-3599,-3612,-3624,-3635,-3644,-3652,-3659,-3665,
+-3669,-3672,-3675,-3676,-3676,-3676,-3675,-3673,-3671,-3669,-3666,-3664,-3661,-3659,-3657,-3656,-3655,-3655,-3655,-3657,-3659,
+-3662,-3667,-3672,-3678,-3686,-3694,-3704,-3714,-3725,-3737,-3750,-3763,-3778,-3792,-3807,-3822,-3838,-3854,-3869,-3885,-3900,
+-3915,-3930,-3944,-3958,-3971,-3984,-3996,-4007,-4018,-4028,-4037,-4046,-4054,-4061,-4067,-4073,-4079,-4083,-4088,-4092,-4095,
+-4099,-4102,-4104,-4107,-4110,-4112,-4114,-4117,-4119,-4122,-4124,-4127,-4130,-4132,-4135,-4138,-4141,-4144,-4147,-4150,-4153,
+-4156,-4159,-4161,-4164,-4166,-4167,-4169,-4170,-4171,-4171,-4171,-4170,-4169,-4167,-4165,-4162,-4159,-4155,-4151,-4147,-4142,
+-4136,-4131,-4125,-4118,-4111,-4105,-4097,-4090,-4083,-4075,-4068,-4060,-4053,-4045,-4038,-4030,-4023,-4015,-4008,-4001,-3994,
+-3986,-3979,-3972,-3965,-3958,-3951,-3944,-3936,-3929,-3921,-3914,-3906,-3897,-3889,-3880,-3872,-3862,-3853,-3844,-3834,-3824,
+-3814,-3804,-3793,-3783,-3772,-3762,-3752,-3742,-3732,-3722,-3713,-3704,-3696,-3688,-3680,-3674,-3668,-3663,-3658,-3654,-3652,
+-3650,-3649,-3648,-3649,-3650,-3652,-3655,-3659,-3663,-3668,-3673,-3678,-3684,-3690,-3696,-3702,-3708,-3714,-3719,-3724,-3728,
+-3731,-3734,-3736,-3736,-3736,-3734,-3731,-3727,-3722,-3715,-3707,-3698,-3687,-3675,-3662,-3647,-3632,-3615,-3598,-3580,-3561,
+-3542,-3522,-3502,-3482,-3462,-3442,-3422,-3404,-3385,-3368,-3351,-3336,-3321,-3308,-3297,-3286,-3278,-3271,-3265,-3261,-3259,
+-3258,-3259,-3261,-3265,-3269,-3276,-3283,-3291,-3300,-3309,-3319,-3329,-3340,-3350,-3361,-3371,-3380,-3389,-3396,-3403,-3409,
+-3414,-3417,-3419,-3419,-3417,-3414,-3410,-3403,-3395,-3386,-3374,-3362,-3347,-3332,-3315,-3297,-3278,-3258,-3237,-3215,-3193,
+-3171,-3149,-3126,-3104,-3082,-3060,-3039,-3018,-2999,-2980,-2962,-2945,-2930,-2915,-2902,-2889,-2878,-2868,-2860,-2852,-2846,
+-2840,-2836,-2832,-2829,-2827,-2825,-2824,-2823,-2822,-2822,-2821,-2821,-2820,-2819,-2817,-2815,-2813,-2810,-2806,-2802,-2797,
+-2791,-2785,-2778,-2770,-2762,-2753,-2743,-2733,-2722,-2712,-2701,-2689,-2678,-2667,-2656,-2645,-2635,-2625,-2615,-2607,-2599,
+-2592,-2586,-2581,-2577,-2574,-2572,-2572,-2573,-2575,-2578,-2582,-2588,-2595,-2603,-2613,-2623,-2634,-2646,-2659,-2673,-2687,
+-2702,-2717,-2733,-2749,-2764,-2780,-2796,-2811,-2827,-2841,-2855,-2869,-2882,-2894,-2905,-2916,-2925,-2934,-2941,-2948,-2953,
+-2958,-2961,-2963,-2964,-2964,-2963,-2961,-2958,-2954,-2950,-2944,-2937,-2930,-2922,-2913,-2903,-2893,-2882,-2870,-2858,-2845,
+-2832,-2818,-2804,-2789,-2774,-2758,-2742,-2725,-2708,-2691,-2673,-2655,-2637,-2618,-2599,-2579,-2560,-2540,-2520,-2500,-2480,
+-2460,-2440,-2420,-2401,-2381,-2362,-2344,-2326,-2308,-2292,-2276,-2261,-2246,-2233,-2221,-2210,-2201,-2192,-2185,-2179,-2175,
+-2172,-2170,-2170,-2171,-2174,-2178,-2183,-2189,-2196,-2205,-2214,-2224,-2235,-2246,-2258,-2270,-2283,-2296,-2308,-2321,-2333,
+-2345,-2357,-2368,-2379,-2388,-2397,-2405,-2413,-2419,-2425,-2429,-2433,-2436,-2438,-2439,-2440,-2440,-2439,-2438,-2437,-2435,
+-2433,-2431,-2429,-2428,-2426,-2425,-2424,-2424,-2425,-2426,-2428,-2431,-2434,-2439,-2444,-2450,-2456,-2463,-2471,-2480,-2489,
+-2498,-2508,-2518,-2527,-2537,-2546,-2555,-2563,-2570,-2576,-2582,-2586,-2588,-2590,-2589,-2587,-2583,-2577,-2570,-2560,-2548,
+-2535,-2519,-2501,-2482,-2460,-2437,-2412,-2386,-2358,-2329,-2299,-2268,-2236,-2204,-2171,-2139,-2106,-2073,-2041,-2009,-1978,
+-1948,-1919,-1891,-1864,-1839,-1816,-1794,-1774,-1756,-1739,-1725,-1712,-1701,-1691,-1684,-1678,-1674,-1671,-1669,-1669,-1671,
+-1673,-1676,-1680,-1685,-1690,-1695,-1701,-1707,-1713,-1719,-1725,-1730,-1736,-1740,-1745,-1748,-1751,-1754,-1755,-1757,-1757,
+-1757,-1756,-1754,-1752,-1750,-1747,-1743,-1739,-1735,-1731,-1727,-1722,-1717,-1713,-1708,-1704,-1700,-1696,-1692,-1689,-1685,
+-1683,-1680,-1678,-1676,-1675,-1674,-1673,-1673,-1672,-1672,-1672,-1672,-1673,-1673,-1673,-1674,-1674,-1674,-1674,-1673,-1673,
+-1672,-1671,-1670,-1668,-1666,-1664,-1661,-1658,-1655,-1651,-1648,-1644,-1639,-1635,-1631,-1626,-1622,-1617,-1613,-1608,-1604,
+-1600,-1596,-1592,-1589,-1586,-1583,-1581,-1579,-1577,-1576,-1575,-1574,-1574,-1574,-1574,-1575,-1576,-1577,-1578,-1580,-1582,
+-1583,-1585,-1587,-1589,-1591,-1593,-1594,-1596,-1597,-1598,-1599,-1599,-1599,-1599,-1599,-1598,-1597,-1596,-1594,-1592,-1590,
+-1588,-1586,-1583,-1580,-1578,-1575,-1572,-1569,-1567,-1564,-1562,-1560,-1584,-1583,-1583,-1583,-1583,-1584,-1584,-1585,-1586,
+-1587,-1589,-1590,-1592,-1594,-1596,-1598,-1600,-1603,-1605,-1607,-1609,-1611,-1613,-1615,-1616,-1618,-1619,-1619,-1620,-1620,
+-1620,-1619,-1618,-1617,-1615,-1613,-1610,-1607,-1604,-1600,-1596,-1591,-1587,-1582,-1577,-1571,-1566,-1561,-1555,-1549,-1544,
+-1538,-1533,-1528,-1523,-1518,-1513,-1509,-1505,-1501,-1498,-1495,-1492,-1490,-1488,-1487,-1485,-1485,-1484,-1484,-1484,-1484,
+-1484,-1485,-1486,-1486,-1487,-1488,-1488,-1489,-1489,-1489,-1489,-1489,-1488,-1487,-1486,-1484,-1482,-1480,-1477,-1473,-1469,
+-1465,-1461,-1455,-1450,-1444,-1438,-1431,-1424,-1417,-1410,-1402,-1395,-1387,-1379,-1371,-1362,-1354,-1346,-1338,-1330,-1323,
+-1315,-1307,-1300,-1293,-1286,-1279,-1273,-1266,-1260,-1254,-1248,-1243,-1238,-1233,-1228,-1223,-1218,-1214,-1209,-1205,-1200,
+-1196,-1192,-1188,-1184,-1180,-1176,-1172,-1168,-1165,-1161,-1157,-1153,-1149,-1146,-1142,-1139,-1135,-1132,-1129,-1126,-1123,
+-1120,-1118,-1115,-1113,-1111,-1109,-1108,-1107,-1106,-1105,-1105,-1105,-1105,-1105,-1106,-1107,-1108,-1110,-1112,-1114,-1116,
+-1118,-1121,-1124,-1127,-1130,-1133,-1136,-1140,-1143,-1147,-1150,-1154,-1157,-1161,-1164,-1168,-1171,-1175,-1178,-1181,-1185,
+-1188,-1191,-1194,-1196,-1199,-1201,-1204,-1206,-1208,-1211,-1213,-1214,-1216,-1218,-1220,-1221,-1223,-1224,-1225,-1227,-1228,
+-1229,-1230,-1231,-1233,-1234,-1235,-1236,-1237,-1238,-1239,-1240,-1241,-1242,-1243,-1244,-1245,-1246,-1247,-1249,-1250,-1251,
+-1252,-1253,-1255,-1256,-1257,-1259,-1260,-1262,-1263,-1265,-1267,-1268,-1270,-1272,-1274,-1276,-1278,-1280,-1282,-1284,-1286,
+-1289,-1291,-1294,-1296,-1299,-1301,-1304,-1307,-1310,-1313,-1316,-1320,-1323,-1326,-1330,-1334,-1337,-1341,-1345,-1350,-1354,
+-1358,-1363,-1368,-1373,-1378,-1383,-1389,-1394,-1400,-1406,-1412,-1418,-1425,-1431,-1438,-1445,-1452,-1459,-1467,-1475,-1482,
+-1490,-1498,-1507,-1515,-1524,-1532,-1541,-1550,-1559,-1568,-1577,-1586,-1596,-1605,-1614,-1624,-1634,-1643,-1653,-1662,-1672,
+-1681,-1691,-1701,-1710,-1720,-1730,-1739,-1749,-1759,-1768,-1778,-1788,-1797,-1807,-1816,-1826,-1836,-1845,-1855,-1864,-1874,
+-1884,-1893,-1903,-1913,-1922,-1932,-1941,-1951,-1960,-1970,-1979,-1988,-1997,-2007,-2016,-2025,-2033,-2042,-2051,-2059,-2068,
+-2076,-2084,-2092,-2100,-2108,-2115,-2123,-2130,-2137,-2144,-2151,-2158,-2165,-2172,-2179,-2185,-2192,-2198,-2205,-2211,-2218,
+-2225,-2231,-2238,-2245,-2252,-2259,-2266,-2273,-2280,-2288,-2295,-2303,-2311,-2319,-2327,-2335,-2344,-2352,-2361,-2370,-2379,
+-2388,-2397,-2406,-2416,-2425,-2435,-2444,-2454,-2464,-2474,-2483,-2493,-2503,-2513,-2523,-2532,-2542,-2552,-2562,-2571,-2581,
+-2591,-2601,-2610,-2620,-2630,-2640,-2650,-2659,-2669,-2679,-2689,-2699,-2710,-2720,-2730,-2740,-2751,-2762,-2772,-2783,-2794,
+-2805,-2816,-2828,-2839,-2851,-2862,-2874,-2886,-2898,-2910,-2922,-2934,-2946,-2958,-2970,-2982,-2994,-3006,-3018,-3030,-3042,
+-3054,-3066,-3078,-3089,-3101,-3112,-3123,-3134,-3145,-3156,-3166,-3176,-3187,-3196,-3206,-3216,-3225,-3234,-3243,-3252,-3260,
+-3268,-3276,-3284,-3292,-3299,-3306,-3313,-3320,-3327,-3333,-3339,-3345,-3351,-3356,-3361,-3366,-3371,-3376,-3380,-3385,-3389,
+-3393,-3396,-3400,-3403,-3406,-3409,-3412,-3415,-3417,-3419,-3422,-3424,-3426,-3428,-3430,-3432,-3433,-3435,-3437,-3439,-3440,
+-3442,-3444,-3446,-3449,-3451,-3453,-3456,-3458,-3461,-3464,-3467,-3470,-3474,-3478,-3481,-3486,-3490,-3494,-3499,-3503,-3508,
+-3513,-3518,-3522,-3527,-3532,-3537,-3542,-3547,-3552,-3556,-3561,-3565,-3569,-3573,-3576,-3580,-3583,-3586,-3588,-3590,-3592,
+-3594,-3596,-3597,-3598,-3598,-3599,-3599,-3599,-3599,-3599,-3599,-3599,-3599,-3599,-3599,-3599,-3599,-3600,-3601,-3602,-3603,
+-3604,-3606,-3609,-3611,-3614,-3617,-3621,-3625,-3629,-3634,-3639,-3645,-3650,-3656,-3662,-3668,-3674,-3681,-3687,-3694,-3700,
+-3706,-3712,-3718,-3724,-3729,-3734,-3739,-3743,-3747,-3751,-3754,-3756,-3758,-3760,-3761,-3762,-3762,-3761,-3761,-3760,-3758,
+-3756,-3754,-3751,-3748,-3745,-3741,-3737,-3733,-3729,-3724,-3719,-3715,-3710,-3704,-3699,-3694,-3688,-3682,-3676,-3670,-3664,
+-3657,-3650,-3643,-3636,-3628,-3620,-3611,-3602,-3593,-3583,-3573,-3563,-3552,-3540,-3528,-3516,-3503,-3490,-3477,-3463,-3450,
+-3436,-3422,-3408,-3393,-3379,-3366,-3352,-3339,-3326,-3314,-3302,-3291,-3281,-3271,-3263,-3255,-3249,-3243,-3239,-3235,-3233,
+-3232,-3232,-3233,-3235,-3239,-3243,-3248,-3255,-3262,-3270,-3279,-3288,-3298,-3309,-3319,-3330,-3342,-3353,-3364,-3375,-3386,
+-3396,-3406,-3416,-3425,-3434,-3442,-3449,-3455,-3461,-3466,-3471,-3474,-3477,-3480,-3481,-3483,-3483,-3484,-3484,-3483,-3483,
+-3482,-3481,-3481,-3480,-3480,-3480,-3480,-3481,-3483,-3485,-3488,-3491,-3495,-3500,-3506,-3512,-3519,-3528,-3536,-3546,-3557,
+-3568,-3580,-3592,-3605,-3619,-3633,-3647,-3662,-3677,-3693,-3708,-3723,-3739,-3754,-3769,-3784,-3799,-3814,-3828,-3841,-3854,
+-3867,-3879,-3891,-3903,-3913,-3924,-3933,-3942,-3951,-3959,-3967,-3974,-3981,-3987,-3993,-3999,-4004,-4009,-4013,-4017,-4021,
+-4025,-4029,-4032,-4035,-4037,-4040,-4042,-4044,-4046,-4048,-4049,-4050,-4051,-4052,-4052,-4052,-4052,-4052,-4051,-4050,-4048,
+-4046,-4044,-4042,-4039,-4035,-4032,-4028,-4024,-4019,-4014,-4009,-4003,-3997,-3991,-3985,-3979,-3972,-3965,-3958,-3950,-3943,
+-3935,-3928,-3920,-3912,-3904,-3896,-3888,-3879,-3871,-3863,-3854,-3846,-3837,-3828,-3819,-3810,-3801,-3792,-3783,-3773,-3763,
+-3753,-3743,-3733,-3722,-3712,-3701,-3690,-3679,-3668,-3657,-3646,-3635,-3624,-3613,-3603,-3592,-3582,-3572,-3562,-3553,-3545,
+-3536,-3529,-3522,-3516,-3510,-3506,-3502,-3499,-3497,-3496,-3495,-3496,-3497,-3500,-3503,-3507,-3512,-3518,-3524,-3531,-3539,
+-3547,-3555,-3563,-3572,-3581,-3590,-3598,-3606,-3614,-3621,-3628,-3634,-3639,-3643,-3646,-3649,-3649,-3649,-3647,-3644,-3640,
+-3634,-3627,-3618,-3609,-3597,-3585,-3572,-3557,-3541,-3525,-3507,-3489,-3470,-3451,-3432,-3413,-3393,-3374,-3355,-3337,-3319,
+-3302,-3286,-3270,-3256,-3243,-3232,-3222,-3213,-3206,-3200,-3196,-3193,-3192,-3192,-3194,-3197,-3202,-3208,-3214,-3222,-3231,
+-3240,-3250,-3261,-3272,-3282,-3293,-3304,-3314,-3324,-3333,-3341,-3348,-3354,-3359,-3363,-3365,-3366,-3365,-3362,-3358,-3353,
+-3345,-3336,-3326,-3314,-3300,-3285,-3269,-3252,-3233,-3214,-3193,-3172,-3151,-3129,-3107,-3084,-3062,-3040,-3018,-2997,-2976,
+-2956,-2936,-2918,-2901,-2884,-2869,-2855,-2842,-2831,-2820,-2811,-2803,-2797,-2791,-2787,-2783,-2781,-2779,-2778,-2778,-2778,
+-2779,-2780,-2781,-2783,-2784,-2786,-2787,-2788,-2789,-2789,-2788,-2788,-2786,-2784,-2781,-2778,-2773,-2768,-2763,-2756,-2749,
+-2742,-2734,-2725,-2716,-2707,-2698,-2688,-2678,-2668,-2659,-2649,-2640,-2632,-2624,-2616,-2610,-2604,-2598,-2594,-2591,-2589,
+-2588,-2588,-2589,-2591,-2594,-2598,-2604,-2611,-2618,-2627,-2637,-2647,-2658,-2671,-2683,-2697,-2711,-2725,-2739,-2754,-2769,
+-2784,-2799,-2814,-2828,-2842,-2856,-2869,-2881,-2893,-2904,-2914,-2924,-2932,-2940,-2946,-2952,-2956,-2960,-2962,-2963,-2963,
+-2962,-2960,-2956,-2952,-2946,-2940,-2932,-2923,-2914,-2903,-2891,-2879,-2865,-2851,-2836,-2820,-2803,-2786,-2768,-2750,-2731,
+-2711,-2691,-2670,-2649,-2628,-2606,-2585,-2563,-2541,-2519,-2497,-2475,-2453,-2431,-2410,-2389,-2369,-2349,-2330,-2311,-2293,
+-2276,-2260,-2245,-2230,-2217,-2205,-2193,-2184,-2175,-2167,-2161,-2156,-2152,-2150,-2148,-2148,-2149,-2151,-2155,-2159,-2164,
+-2171,-2178,-2185,-2194,-2203,-2213,-2223,-2233,-2243,-2254,-2265,-2275,-2286,-2296,-2306,-2316,-2325,-2334,-2342,-2350,-2357,
+-2364,-2370,-2375,-2380,-2385,-2388,-2392,-2395,-2397,-2399,-2401,-2403,-2405,-2407,-2408,-2410,-2412,-2414,-2417,-2420,-2423,
+-2427,-2431,-2436,-2442,-2448,-2454,-2462,-2469,-2477,-2486,-2495,-2505,-2514,-2524,-2534,-2544,-2554,-2563,-2573,-2581,-2589,
+-2597,-2603,-2608,-2613,-2616,-2618,-2618,-2617,-2614,-2609,-2603,-2595,-2585,-2574,-2561,-2545,-2529,-2510,-2490,-2468,-2444,
+-2419,-2393,-2366,-2337,-2308,-2278,-2247,-2216,-2185,-2153,-2121,-2090,-2058,-2027,-1997,-1968,-1939,-1912,-1885,-1860,-1836,
+-1813,-1792,-1772,-1753,-1737,-1721,-1707,-1695,-1685,-1675,-1668,-1661,-1656,-1652,-1649,-1647,-1646,-1647,-1647,-1649,-1651,
+-1653,-1656,-1660,-1663,-1667,-1670,-1674,-1677,-1680,-1684,-1687,-1689,-1691,-1693,-1695,-1696,-1697,-1697,-1697,-1697,-1696,
+-1695,-1694,-1693,-1691,-1689,-1688,-1686,-1684,-1681,-1679,-1677,-1675,-1673,-1672,-1670,-1668,-1667,-1666,-1664,-1664,-1663,
+-1662,-1662,-1661,-1661,-1661,-1661,-1661,-1661,-1661,-1661,-1661,-1661,-1661,-1661,-1661,-1660,-1660,-1659,-1658,-1657,-1656,
+-1655,-1653,-1652,-1650,-1648,-1646,-1644,-1642,-1640,-1637,-1635,-1632,-1630,-1628,-1626,-1623,-1621,-1619,-1617,-1615,-1614,
+-1612,-1611,-1609,-1608,-1607,-1607,-1606,-1605,-1605,-1605,-1605,-1605,-1605,-1605,-1605,-1605,-1605,-1605,-1605,-1605,-1605,
+-1605,-1605,-1605,-1605,-1604,-1604,-1603,-1602,-1601,-1600,-1599,-1598,-1597,-1596,-1594,-1593,-1592,-1590,-1589,-1588,-1587,
+-1586,-1585,-1584,-1584,-1665,-1666,-1666,-1667,-1667,-1668,-1669,-1670,-1671,-1672,-1673,-1674,-1675,-1676,-1677,-1678,-1679,
+-1680,-1680,-1681,-1681,-1682,-1682,-1682,-1681,-1680,-1680,-1679,-1677,-1675,-1673,-1671,-1669,-1666,-1663,-1659,-1655,-1652,
+-1648,-1643,-1639,-1634,-1629,-1624,-1619,-1614,-1609,-1604,-1599,-1594,-1589,-1584,-1580,-1575,-1571,-1567,-1563,-1559,-1556,
+-1553,-1551,-1548,-1546,-1544,-1543,-1541,-1540,-1540,-1539,-1539,-1539,-1539,-1539,-1539,-1540,-1540,-1540,-1541,-1541,-1542,
+-1542,-1542,-1542,-1541,-1541,-1540,-1539,-1537,-1536,-1534,-1531,-1528,-1525,-1522,-1518,-1514,-1510,-1505,-1500,-1495,-1489,
+-1483,-1477,-1471,-1464,-1458,-1451,-1444,-1437,-1430,-1423,-1416,-1409,-1402,-1395,-1388,-1381,-1374,-1368,-1361,-1355,-1349,
+-1343,-1338,-1332,-1327,-1322,-1317,-1312,-1307,-1303,-1298,-1294,-1290,-1287,-1283,-1279,-1276,-1273,-1270,-1267,-1264,-1261,
+-1258,-1256,-1253,-1251,-1248,-1246,-1244,-1242,-1240,-1238,-1237,-1235,-1233,-1232,-1231,-1230,-1229,-1228,-1228,-1227,-1227,
+-1227,-1227,-1227,-1228,-1228,-1229,-1230,-1231,-1233,-1234,-1236,-1238,-1240,-1242,-1244,-1247,-1249,-1252,-1255,-1257,-1260,
+-1263,-1267,-1270,-1273,-1276,-1279,-1282,-1285,-1289,-1292,-1295,-1298,-1301,-1304,-1306,-1309,-1312,-1314,-1317,-1319,-1321,
+-1323,-1326,-1327,-1329,-1331,-1333,-1335,-1336,-1338,-1339,-1340,-1342,-1343,-1344,-1345,-1346,-1347,-1348,-1350,-1351,-1352,
+-1353,-1354,-1355,-1356,-1357,-1358,-1359,-1361,-1362,-1363,-1365,-1366,-1368,-1369,-1371,-1372,-1374,-1376,-1378,-1380,-1382,
+-1384,-1386,-1388,-1390,-1393,-1395,-1398,-1400,-1403,-1405,-1408,-1411,-1413,-1416,-1419,-1422,-1425,-1428,-1431,-1435,-1438,
+-1441,-1444,-1448,-1451,-1455,-1459,-1462,-1466,-1470,-1474,-1478,-1482,-1486,-1490,-1495,-1499,-1504,-1509,-1513,-1518,-1523,
+-1529,-1534,-1539,-1545,-1551,-1557,-1563,-1569,-1575,-1582,-1588,-1595,-1602,-1609,-1616,-1623,-1631,-1638,-1646,-1654,-1662,
+-1670,-1678,-1686,-1694,-1703,-1711,-1720,-1728,-1737,-1745,-1754,-1763,-1772,-1781,-1789,-1798,-1807,-1816,-1825,-1834,-1843,
+-1852,-1861,-1870,-1879,-1888,-1897,-1906,-1915,-1924,-1933,-1942,-1951,-1960,-1969,-1978,-1987,-1996,-2004,-2013,-2022,-2030,
+-2039,-2047,-2056,-2064,-2072,-2081,-2089,-2097,-2105,-2113,-2120,-2128,-2136,-2143,-2150,-2158,-2165,-2172,-2179,-2186,-2193,
+-2200,-2206,-2213,-2219,-2226,-2232,-2239,-2245,-2252,-2258,-2264,-2271,-2277,-2284,-2290,-2297,-2303,-2310,-2317,-2323,-2330,
+-2337,-2344,-2352,-2359,-2366,-2374,-2382,-2390,-2397,-2406,-2414,-2422,-2430,-2439,-2447,-2456,-2465,-2474,-2483,-2491,-2501,
+-2510,-2519,-2528,-2537,-2546,-2556,-2565,-2574,-2584,-2593,-2603,-2612,-2621,-2631,-2640,-2650,-2659,-2668,-2678,-2687,-2697,
+-2706,-2716,-2725,-2735,-2745,-2754,-2764,-2774,-2783,-2793,-2803,-2813,-2823,-2833,-2843,-2853,-2864,-2874,-2884,-2895,-2905,
+-2916,-2926,-2937,-2947,-2958,-2968,-2979,-2989,-3000,-3010,-3021,-3031,-3041,-3052,-3062,-3072,-3082,-3092,-3101,-3111,-3121,
+-3130,-3139,-3148,-3157,-3166,-3174,-3183,-3191,-3199,-3207,-3215,-3222,-3229,-3236,-3243,-3250,-3257,-3263,-3269,-3275,-3281,
+-3286,-3292,-3297,-3302,-3307,-3312,-3317,-3321,-3325,-3330,-3334,-3338,-3341,-3345,-3348,-3352,-3355,-3358,-3361,-3364,-3367,
+-3370,-3373,-3376,-3378,-3381,-3384,-3386,-3389,-3392,-3394,-3397,-3400,-3402,-3405,-3408,-3411,-3414,-3417,-3420,-3423,-3426,
+-3429,-3433,-3436,-3440,-3444,-3447,-3451,-3455,-3459,-3463,-3467,-3471,-3475,-3479,-3483,-3486,-3490,-3494,-3498,-3502,-3505,
+-3509,-3512,-3515,-3518,-3521,-3524,-3526,-3529,-3531,-3533,-3535,-3537,-3538,-3540,-3541,-3542,-3543,-3544,-3545,-3545,-3546,
+-3547,-3547,-3548,-3549,-3549,-3550,-3551,-3552,-3553,-3554,-3556,-3557,-3559,-3561,-3564,-3566,-3569,-3572,-3575,-3579,-3583,
+-3587,-3591,-3595,-3600,-3605,-3610,-3615,-3620,-3625,-3631,-3636,-3641,-3647,-3652,-3657,-3662,-3666,-3671,-3675,-3679,-3683,
+-3687,-3690,-3693,-3695,-3697,-3699,-3700,-3701,-3701,-3701,-3701,-3700,-3698,-3697,-3695,-3692,-3689,-3686,-3682,-3678,-3673,
+-3668,-3663,-3658,-3652,-3646,-3640,-3633,-3626,-3619,-3611,-3604,-3596,-3588,-3580,-3571,-3562,-3554,-3544,-3535,-3526,-3516,
+-3507,-3497,-3487,-3477,-3467,-3456,-3446,-3436,-3425,-3415,-3405,-3395,-3385,-3375,-3365,-3356,-3347,-3338,-3329,-3321,-3313,
+-3306,-3299,-3292,-3286,-3281,-3276,-3272,-3268,-3265,-3263,-3261,-3260,-3260,-3260,-3261,-3262,-3264,-3267,-3270,-3273,-3278,
+-3282,-3287,-3292,-3297,-3303,-3309,-3315,-3321,-3328,-3334,-3340,-3346,-3352,-3358,-3363,-3368,-3373,-3378,-3383,-3387,-3390,
+-3394,-3397,-3400,-3403,-3405,-3407,-3408,-3410,-3411,-3412,-3413,-3414,-3415,-3416,-3417,-3418,-3420,-3421,-3423,-3424,-3427,
+-3429,-3432,-3435,-3439,-3443,-3447,-3452,-3457,-3463,-3469,-3476,-3483,-3491,-3499,-3507,-3515,-3524,-3534,-3543,-3553,-3563,
+-3573,-3583,-3594,-3604,-3615,-3625,-3636,-3646,-3656,-3667,-3677,-3686,-3696,-3706,-3715,-3724,-3733,-3741,-3750,-3758,-3765,
+-3773,-3780,-3787,-3794,-3800,-3807,-3813,-3818,-3824,-3829,-3834,-3839,-3844,-3848,-3852,-3856,-3860,-3864,-3867,-3870,-3873,
+-3875,-3878,-3880,-3882,-3883,-3884,-3885,-3886,-3886,-3886,-3886,-3885,-3884,-3882,-3880,-3878,-3876,-3873,-3869,-3865,-3861,
+-3857,-3852,-3847,-3841,-3835,-3829,-3822,-3815,-3808,-3800,-3793,-3784,-3776,-3767,-3758,-3749,-3739,-3729,-3719,-3709,-3698,
+-3688,-3677,-3666,-3655,-3643,-3632,-3620,-3608,-3596,-3584,-3572,-3560,-3548,-3536,-3523,-3511,-3499,-3487,-3475,-3463,-3452,
+-3440,-3429,-3419,-3408,-3398,-3389,-3380,-3371,-3363,-3356,-3350,-3344,-3338,-3334,-3330,-3328,-3326,-3325,-3325,-3325,-3327,
+-3329,-3333,-3337,-3342,-3348,-3354,-3362,-3370,-3378,-3387,-3397,-3406,-3416,-3427,-3437,-3447,-3457,-3467,-3477,-3486,-3495,
+-3503,-3511,-3517,-3523,-3528,-3532,-3535,-3536,-3537,-3536,-3534,-3531,-3526,-3521,-3514,-3505,-3496,-3485,-3474,-3461,-3448,
+-3433,-3418,-3403,-3386,-3370,-3353,-3336,-3319,-3302,-3286,-3269,-3254,-3239,-3224,-3210,-3198,-3186,-3175,-3166,-3158,-3151,
+-3145,-3141,-3138,-3136,-3136,-3137,-3139,-3143,-3147,-3153,-3160,-3167,-3175,-3184,-3194,-3203,-3213,-3223,-3233,-3243,-3253,
+-3262,-3271,-3279,-3286,-3292,-3298,-3302,-3305,-3307,-3307,-3306,-3304,-3300,-3295,-3288,-3280,-3271,-3260,-3248,-3235,-3220,
+-3205,-3188,-3171,-3153,-3134,-3115,-3096,-3076,-3056,-3036,-3016,-2997,-2977,-2959,-2940,-2923,-2906,-2890,-2874,-2860,-2847,
+-2835,-2823,-2813,-2804,-2796,-2790,-2784,-2779,-2775,-2773,-2771,-2770,-2769,-2769,-2770,-2772,-2773,-2775,-2778,-2780,-2783,
+-2785,-2788,-2790,-2792,-2794,-2796,-2797,-2797,-2798,-2797,-2797,-2795,-2793,-2791,-2788,-2785,-2781,-2777,-2773,-2768,-2763,
+-2758,-2752,-2747,-2742,-2736,-2731,-2725,-2721,-2716,-2712,-2708,-2704,-2701,-2699,-2697,-2696,-2696,-2696,-2697,-2699,-2702,
+-2705,-2709,-2713,-2718,-2724,-2731,-2738,-2745,-2753,-2762,-2771,-2780,-2789,-2798,-2808,-2818,-2827,-2837,-2846,-2855,-2864,
+-2872,-2880,-2888,-2894,-2901,-2906,-2911,-2915,-2919,-2921,-2923,-2924,-2923,-2922,-2920,-2917,-2913,-2908,-2903,-2896,-2888,
+-2879,-2869,-2859,-2847,-2835,-2822,-2808,-2793,-2778,-2761,-2745,-2727,-2709,-2691,-2672,-2653,-2633,-2613,-2593,-2573,-2553,
+-2533,-2512,-2492,-2472,-2452,-2433,-2414,-2395,-2377,-2360,-2343,-2327,-2311,-2296,-2283,-2270,-2257,-2246,-2236,-2227,-2219,
+-2212,-2206,-2201,-2197,-2194,-2192,-2191,-2191,-2192,-2194,-2196,-2200,-2204,-2209,-2215,-2221,-2228,-2235,-2243,-2251,-2259,
+-2267,-2275,-2284,-2292,-2301,-2309,-2317,-2325,-2333,-2340,-2347,-2354,-2360,-2366,-2372,-2377,-2382,-2387,-2391,-2395,-2399,
+-2403,-2406,-2410,-2413,-2416,-2419,-2423,-2426,-2430,-2433,-2437,-2442,-2446,-2451,-2456,-2462,-2468,-2474,-2481,-2488,-2496,
+-2504,-2512,-2520,-2528,-2537,-2546,-2554,-2563,-2571,-2579,-2587,-2595,-2602,-2608,-2614,-2618,-2622,-2625,-2627,-2628,-2628,
+-2626,-2623,-2619,-2613,-2606,-2598,-2588,-2577,-2564,-2550,-2534,-2517,-2499,-2480,-2459,-2437,-2415,-2391,-2367,-2342,-2316,
+-2290,-2264,-2237,-2210,-2184,-2157,-2130,-2104,-2079,-2053,-2029,-2005,-1982,-1960,-1939,-1919,-1899,-1881,-1864,-1849,-1834,
+-1821,-1809,-1798,-1788,-1779,-1771,-1765,-1759,-1754,-1751,-1748,-1745,-1744,-1743,-1743,-1743,-1743,-1744,-1745,-1747,-1748,
+-1750,-1752,-1754,-1756,-1757,-1759,-1760,-1761,-1762,-1763,-1764,-1764,-1764,-1764,-1763,-1763,-1762,-1761,-1759,-1758,-1756,
+-1754,-1752,-1750,-1748,-1746,-1744,-1741,-1739,-1737,-1734,-1732,-1730,-1728,-1726,-1724,-1723,-1721,-1719,-1718,-1717,-1715,
+-1714,-1713,-1712,-1712,-1711,-1710,-1710,-1709,-1708,-1708,-1707,-1707,-1707,-1706,-1706,-1705,-1705,-1705,-1704,-1704,-1703,
+-1703,-1702,-1702,-1701,-1701,-1700,-1700,-1699,-1698,-1698,-1697,-1696,-1696,-1695,-1694,-1694,-1693,-1692,-1692,-1691,-1690,
+-1689,-1689,-1688,-1687,-1687,-1686,-1685,-1685,-1684,-1683,-1682,-1681,-1680,-1680,-1679,-1678,-1677,-1676,-1675,-1674,-1673,
+-1673,-1672,-1671,-1670,-1669,-1668,-1668,-1667,-1667,-1666,-1666,-1665,-1665,-1665,-1665,-1665,-1665,-1815,-1815,-1816,-1816,
+-1817,-1817,-1818,-1818,-1818,-1819,-1819,-1819,-1819,-1819,-1819,-1818,-1818,-1817,-1816,-1815,-1813,-1812,-1810,-1808,-1805,
+-1803,-1800,-1797,-1793,-1790,-1786,-1782,-1777,-1772,-1768,-1762,-1757,-1752,-1746,-1740,-1734,-1729,-1722,-1716,-1710,-1704,
+-1698,-1692,-1686,-1680,-1675,-1669,-1664,-1659,-1654,-1649,-1645,-1641,-1637,-1633,-1630,-1626,-1624,-1621,-1619,-1617,-1615,
+-1614,-1613,-1612,-1611,-1610,-1610,-1609,-1609,-1609,-1609,-1609,-1609,-1609,-1609,-1609,-1609,-1609,-1609,-1608,-1607,-1607,
+-1605,-1604,-1603,-1601,-1599,-1596,-1594,-1591,-1588,-1584,-1581,-1577,-1572,-1568,-1563,-1558,-1553,-1548,-1542,-1537,-1531,
+-1525,-1519,-1513,-1507,-1500,-1494,-1488,-1482,-1475,-1469,-1463,-1457,-1452,-1446,-1440,-1435,-1430,-1424,-1420,-1415,-1410,
+-1406,-1402,-1398,-1394,-1391,-1387,-1384,-1381,-1379,-1376,-1374,-1372,-1370,-1369,-1367,-1366,-1365,-1364,-1364,-1363,-1363,
+-1363,-1363,-1363,-1364,-1364,-1365,-1366,-1367,-1368,-1369,-1371,-1372,-1374,-1376,-1378,-1380,-1382,-1384,-1386,-1389,-1391,
+-1393,-1396,-1398,-1401,-1404,-1406,-1409,-1411,-1414,-1417,-1419,-1422,-1424,-1427,-1429,-1431,-1434,-1436,-1438,-1440,-1442,
+-1444,-1446,-1447,-1449,-1450,-1452,-1453,-1454,-1455,-1456,-1457,-1458,-1459,-1459,-1460,-1460,-1461,-1461,-1461,-1462,-1462,
+-1462,-1463,-1463,-1463,-1464,-1464,-1464,-1465,-1465,-1466,-1467,-1467,-1468,-1469,-1470,-1471,-1472,-1474,-1475,-1477,-1479,
+-1481,-1483,-1485,-1487,-1490,-1492,-1495,-1498,-1501,-1504,-1507,-1510,-1514,-1518,-1521,-1525,-1529,-1533,-1537,-1541,-1545,
+-1549,-1554,-1558,-1562,-1567,-1571,-1576,-1580,-1585,-1589,-1594,-1598,-1603,-1607,-1612,-1616,-1621,-1625,-1630,-1635,-1639,
+-1644,-1648,-1653,-1657,-1662,-1666,-1671,-1675,-1680,-1685,-1689,-1694,-1698,-1703,-1708,-1713,-1718,-1723,-1728,-1733,-1738,
+-1743,-1748,-1754,-1759,-1765,-1770,-1776,-1782,-1787,-1793,-1799,-1805,-1811,-1818,-1824,-1830,-1837,-1843,-1850,-1856,-1863,
+-1869,-1876,-1883,-1890,-1897,-1904,-1911,-1918,-1925,-1932,-1939,-1946,-1954,-1961,-1968,-1976,-1983,-1990,-1998,-2005,-2012,
+-2020,-2027,-2035,-2042,-2050,-2057,-2064,-2072,-2079,-2087,-2094,-2101,-2109,-2116,-2124,-2131,-2138,-2146,-2153,-2160,-2167,
+-2174,-2181,-2189,-2196,-2203,-2210,-2217,-2224,-2231,-2237,-2244,-2251,-2258,-2265,-2271,-2278,-2285,-2292,-2298,-2305,-2312,
+-2319,-2326,-2332,-2339,-2346,-2353,-2360,-2367,-2374,-2381,-2388,-2396,-2403,-2410,-2418,-2425,-2433,-2441,-2448,-2456,-2464,
+-2472,-2480,-2489,-2497,-2505,-2514,-2522,-2531,-2539,-2548,-2557,-2565,-2574,-2583,-2592,-2601,-2610,-2619,-2628,-2637,-2646,
+-2655,-2664,-2673,-2682,-2691,-2700,-2709,-2718,-2727,-2736,-2745,-2754,-2763,-2772,-2781,-2789,-2798,-2807,-2816,-2825,-2834,
+-2843,-2851,-2860,-2869,-2878,-2887,-2895,-2904,-2913,-2922,-2930,-2939,-2948,-2956,-2965,-2974,-2982,-2991,-2999,-3007,-3016,
+-3024,-3032,-3041,-3049,-3057,-3065,-3073,-3080,-3088,-3096,-3103,-3110,-3118,-3125,-3132,-3139,-3145,-3152,-3159,-3165,-3171,
+-3177,-3183,-3189,-3195,-3201,-3206,-3211,-3217,-3222,-3227,-3232,-3237,-3241,-3246,-3250,-3255,-3259,-3263,-3267,-3272,-3276,
+-3279,-3283,-3287,-3291,-3294,-3298,-3302,-3305,-3309,-3312,-3316,-3319,-3322,-3326,-3329,-3333,-3336,-3340,-3343,-3346,-3350,
+-3353,-3357,-3360,-3363,-3367,-3370,-3374,-3377,-3381,-3384,-3388,-3391,-3395,-3398,-3402,-3405,-3409,-3412,-3416,-3419,-3422,
+-3426,-3429,-3432,-3435,-3438,-3442,-3444,-3447,-3450,-3453,-3455,-3458,-3460,-3463,-3465,-3467,-3469,-3471,-3472,-3474,-3476,
+-3477,-3478,-3480,-3481,-3482,-3483,-3484,-3485,-3486,-3487,-3488,-3489,-3490,-3490,-3492,-3493,-3494,-3495,-3496,-3497,-3499,
+-3501,-3502,-3504,-3506,-3508,-3511,-3513,-3515,-3518,-3521,-3524,-3527,-3531,-3534,-3538,-3541,-3545,-3549,-3553,-3557,-3561,
+-3565,-3568,-3572,-3576,-3580,-3584,-3587,-3591,-3594,-3597,-3600,-3603,-3605,-3608,-3610,-3611,-3613,-3614,-3615,-3616,-3616,
+-3616,-3616,-3615,-3614,-3613,-3612,-3610,-3608,-3605,-3602,-3599,-3596,-3593,-3589,-3585,-3580,-3576,-3571,-3566,-3561,-3555,
+-3550,-3544,-3538,-3532,-3526,-3520,-3514,-3507,-3501,-3494,-3488,-3481,-3474,-3467,-3461,-3454,-3447,-3440,-3433,-3426,-3420,
+-3413,-3407,-3400,-3394,-3387,-3381,-3375,-3369,-3364,-3358,-3353,-3348,-3343,-3338,-3334,-3330,-3326,-3322,-3319,-3316,-3314,
+-3311,-3309,-3308,-3306,-3305,-3304,-3304,-3304,-3304,-3305,-3305,-3307,-3308,-3309,-3311,-3313,-3316,-3318,-3321,-3323,-3326,
+-3329,-3332,-3336,-3339,-3342,-3346,-3349,-3352,-3356,-3359,-3363,-3366,-3369,-3372,-3376,-3379,-3382,-3385,-3388,-3391,-3394,
+-3397,-3400,-3403,-3405,-3408,-3411,-3414,-3416,-3419,-3422,-3425,-3428,-3430,-3433,-3436,-3439,-3442,-3445,-3449,-3452,-3455,
+-3458,-3462,-3465,-3468,-3472,-3475,-3479,-3483,-3486,-3490,-3494,-3497,-3501,-3505,-3508,-3512,-3516,-3519,-3523,-3527,-3531,
+-3534,-3538,-3542,-3545,-3549,-3553,-3557,-3560,-3564,-3568,-3572,-3576,-3580,-3584,-3588,-3592,-3597,-3601,-3605,-3610,-3614,
+-3619,-3623,-3628,-3633,-3637,-3642,-3647,-3652,-3656,-3661,-3666,-3670,-3675,-3679,-3683,-3687,-3691,-3695,-3698,-3701,-3704,
+-3707,-3709,-3711,-3713,-3714,-3715,-3715,-3715,-3714,-3713,-3712,-3710,-3707,-3704,-3700,-3696,-3692,-3687,-3681,-3675,-3668,
+-3661,-3653,-3645,-3636,-3627,-3617,-3607,-3597,-3586,-3574,-3563,-3551,-3539,-3526,-3513,-3500,-3487,-3473,-3460,-3446,-3433,
+-3419,-3405,-3392,-3378,-3365,-3351,-3338,-3326,-3313,-3301,-3289,-3278,-3267,-3257,-3247,-3238,-3229,-3221,-3214,-3207,-3202,
+-3197,-3192,-3189,-3186,-3185,-3184,-3184,-3185,-3186,-3189,-3192,-3196,-3201,-3207,-3213,-3220,-3227,-3236,-3244,-3253,-3263,
+-3272,-3282,-3292,-3303,-3313,-3323,-3333,-3343,-3352,-3361,-3369,-3377,-3384,-3391,-3396,-3401,-3405,-3408,-3411,-3412,-3412,
+-3411,-3408,-3405,-3401,-3396,-3389,-3382,-3374,-3364,-3354,-3343,-3332,-3319,-3306,-3293,-3279,-3265,-3251,-3236,-3222,-3208,
+-3194,-3180,-3167,-3154,-3141,-3130,-3119,-3109,-3100,-3091,-3084,-3078,-3073,-3069,-3066,-3065,-3064,-3065,-3067,-3069,-3073,
+-3078,-3083,-3090,-3097,-3105,-3113,-3122,-3131,-3141,-3150,-3160,-3170,-3179,-3189,-3198,-3206,-3214,-3221,-3227,-3233,-3238,
+-3242,-3244,-3246,-3246,-3246,-3244,-3241,-3237,-3232,-3225,-3218,-3209,-3199,-3188,-3177,-3164,-3151,-3137,-3122,-3107,-3092,
+-3076,-3060,-3043,-3027,-3011,-2995,-2979,-2963,-2948,-2933,-2918,-2905,-2892,-2880,-2868,-2857,-2848,-2839,-2830,-2823,-2817,
+-2812,-2807,-2803,-2801,-2798,-2797,-2797,-2797,-2798,-2799,-2801,-2803,-2806,-2809,-2813,-2816,-2820,-2824,-2828,-2832,-2836,
+-2840,-2844,-2848,-2851,-2854,-2857,-2860,-2862,-2865,-2866,-2868,-2869,-2870,-2870,-2871,-2871,-2871,-2870,-2870,-2869,-2868,
+-2867,-2866,-2865,-2863,-2862,-2861,-2860,-2859,-2858,-2857,-2856,-2856,-2855,-2855,-2855,-2855,-2856,-2856,-2857,-2858,-2859,
+-2861,-2862,-2864,-2865,-2867,-2869,-2871,-2872,-2874,-2876,-2878,-2879,-2880,-2881,-2882,-2883,-2883,-2883,-2883,-2882,-2881,
+-2879,-2877,-2874,-2871,-2867,-2863,-2858,-2853,-2847,-2840,-2833,-2825,-2817,-2808,-2798,-2788,-2778,-2766,-2754,-2742,-2729,
+-2716,-2702,-2688,-2674,-2659,-2644,-2629,-2613,-2597,-2582,-2566,-2550,-2534,-2518,-2502,-2486,-2471,-2455,-2441,-2426,-2412,
+-2398,-2385,-2372,-2360,-2348,-2337,-2326,-2317,-2308,-2299,-2292,-2285,-2279,-2273,-2269,-2265,-2262,-2259,-2258,-2257,-2257,
+-2257,-2258,-2260,-2263,-2265,-2269,-2273,-2277,-2282,-2287,-2292,-2298,-2303,-2309,-2316,-2322,-2328,-2334,-2341,-2347,-2353,
+-2359,-2365,-2371,-2377,-2383,-2388,-2394,-2399,-2404,-2409,-2414,-2419,-2423,-2428,-2432,-2437,-2442,-2446,-2451,-2455,-2460,
+-2465,-2470,-2475,-2481,-2486,-2492,-2498,-2504,-2511,-2518,-2524,-2531,-2539,-2546,-2554,-2561,-2569,-2576,-2584,-2591,-2599,
+-2606,-2613,-2620,-2626,-2632,-2637,-2642,-2646,-2650,-2653,-2655,-2656,-2657,-2656,-2655,-2652,-2649,-2645,-2639,-2633,-2625,
+-2617,-2607,-2597,-2585,-2573,-2559,-2545,-2529,-2513,-2497,-2479,-2461,-2443,-2424,-2404,-2385,-2365,-2344,-2324,-2304,-2284,
+-2264,-2244,-2225,-2206,-2187,-2169,-2151,-2134,-2118,-2102,-2087,-2073,-2060,-2047,-2035,-2024,-2014,-2004,-1995,-1987,-1980,
+-1973,-1968,-1962,-1958,-1954,-1950,-1947,-1945,-1942,-1941,-1939,-1938,-1937,-1936,-1935,-1934,-1933,-1933,-1932,-1931,-1930,
+-1929,-1928,-1927,-1925,-1924,-1922,-1920,-1918,-1915,-1912,-1910,-1907,-1903,-1900,-1896,-1893,-1889,-1885,-1881,-1877,-1873,
+-1869,-1864,-1860,-1856,-1852,-1848,-1844,-1840,-1837,-1833,-1830,-1827,-1824,-1821,-1818,-1816,-1813,-1811,-1809,-1807,-1806,
+-1805,-1804,-1803,-1802,-1801,-1801,-1800,-1800,-1800,-1800,-1801,-1801,-1801,-1802,-1802,-1803,-1804,-1805,-1805,-1806,-1807,
+-1808,-1809,-1810,-1810,-1811,-1812,-1813,-1813,-1814,-1815,-1815,-1816,-1816,-1816,-1817,-1817,-1817,-1817,-1817,-1817,-1817,
+-1817,-1817,-1817,-1817,-1816,-1816,-1816,-1816,-1815,-1815,-1814,-1814,-1814,-1814,-1813,-1813,-1813,-1813,-1813,-1813,-1813,
+-1813,-1813,-1813,-1813,-1814,-1814,-1814,-1814,-1815,-1967,-1967,-1968,-1968,-1968,-1968,-1968,-1968,-1967,-1967,-1966,-1965,
+-1964,-1963,-1961,-1959,-1957,-1955,-1953,-1950,-1947,-1944,-1940,-1937,-1932,-1928,-1924,-1919,-1914,-1908,-1903,-1897,-1891,
+-1885,-1878,-1872,-1865,-1858,-1851,-1844,-1837,-1830,-1823,-1816,-1809,-1802,-1795,-1788,-1781,-1774,-1767,-1761,-1755,-1749,
+-1743,-1738,-1732,-1727,-1723,-1718,-1714,-1710,-1707,-1703,-1700,-1698,-1695,-1693,-1691,-1690,-1688,-1687,-1686,-1686,-1685,
+-1685,-1684,-1684,-1684,-1684,-1684,-1684,-1684,-1684,-1684,-1684,-1684,-1684,-1683,-1683,-1682,-1681,-1680,-1679,-1678,-1676,
+-1674,-1672,-1669,-1667,-1664,-1661,-1657,-1654,-1650,-1646,-1642,-1637,-1633,-1628,-1623,-1618,-1613,-1607,-1602,-1597,-1591,
+-1586,-1580,-1575,-1569,-1564,-1558,-1553,-1548,-1542,-1537,-1533,-1528,-1523,-1519,-1515,-1511,-1508,-1504,-1501,-1498,-1496,
+-1493,-1491,-1489,-1488,-1487,-1486,-1485,-1485,-1485,-1485,-1485,-1486,-1487,-1488,-1490,-1491,-1493,-1495,-1497,-1500,-1503,
+-1505,-1508,-1511,-1515,-1518,-1521,-1525,-1528,-1532,-1536,-1539,-1543,-1546,-1550,-1554,-1557,-1560,-1564,-1567,-1570,-1573,
+-1576,-1579,-1581,-1584,-1586,-1588,-1590,-1592,-1594,-1595,-1596,-1597,-1598,-1599,-1599,-1600,-1600,-1600,-1600,-1600,-1599,
+-1599,-1598,-1597,-1596,-1595,-1594,-1593,-1592,-1591,-1590,-1589,-1587,-1586,-1585,-1584,-1583,-1583,-1582,-1581,-1581,-1581,
+-1580,-1580,-1581,-1581,-1582,-1582,-1583,-1585,-1586,-1588,-1590,-1592,-1594,-1597,-1600,-1603,-1606,-1610,-1614,-1618,-1622,
+-1627,-1631,-1636,-1641,-1647,-1652,-1658,-1663,-1669,-1675,-1681,-1687,-1694,-1700,-1706,-1713,-1719,-1726,-1732,-1739,-1745,
+-1752,-1758,-1765,-1771,-1777,-1784,-1790,-1796,-1802,-1808,-1814,-1820,-1825,-1831,-1836,-1842,-1847,-1852,-1857,-1863,-1868,
+-1872,-1877,-1882,-1887,-1891,-1896,-1900,-1905,-1909,-1913,-1918,-1922,-1926,-1930,-1934,-1939,-1943,-1947,-1951,-1955,-1959,
+-1963,-1968,-1972,-1976,-1980,-1985,-1989,-1993,-1998,-2002,-2007,-2011,-2016,-2020,-2025,-2030,-2034,-2039,-2044,-2049,-2054,
+-2059,-2064,-2069,-2074,-2079,-2084,-2090,-2095,-2100,-2106,-2111,-2116,-2122,-2127,-2133,-2139,-2144,-2150,-2156,-2162,-2167,
+-2173,-2179,-2185,-2191,-2197,-2203,-2209,-2215,-2221,-2227,-2233,-2240,-2246,-2252,-2258,-2265,-2271,-2277,-2284,-2290,-2296,
+-2303,-2309,-2316,-2323,-2329,-2336,-2343,-2349,-2356,-2363,-2370,-2377,-2384,-2391,-2398,-2405,-2412,-2419,-2427,-2434,-2442,
+-2449,-2457,-2464,-2472,-2480,-2488,-2496,-2504,-2512,-2520,-2528,-2536,-2545,-2553,-2561,-2570,-2578,-2587,-2595,-2604,-2613,
+-2622,-2630,-2639,-2648,-2657,-2665,-2674,-2683,-2692,-2701,-2710,-2718,-2727,-2736,-2745,-2753,-2762,-2771,-2779,-2788,-2796,
+-2805,-2813,-2822,-2830,-2838,-2846,-2855,-2863,-2871,-2879,-2887,-2895,-2902,-2910,-2918,-2925,-2933,-2941,-2948,-2955,-2963,
+-2970,-2977,-2984,-2991,-2998,-3005,-3012,-3018,-3025,-3032,-3038,-3044,-3051,-3057,-3063,-3069,-3075,-3081,-3087,-3093,-3098,
+-3104,-3109,-3115,-3120,-3125,-3130,-3135,-3140,-3145,-3150,-3154,-3159,-3164,-3168,-3172,-3177,-3181,-3185,-3189,-3193,-3197,
+-3201,-3205,-3208,-3212,-3216,-3220,-3223,-3227,-3230,-3234,-3237,-3241,-3244,-3248,-3251,-3254,-3258,-3261,-3265,-3268,-3272,
+-3275,-3278,-3282,-3285,-3289,-3292,-3296,-3299,-3303,-3306,-3310,-3313,-3316,-3320,-3323,-3327,-3330,-3334,-3337,-3341,-3344,
+-3347,-3351,-3354,-3357,-3361,-3364,-3367,-3370,-3373,-3376,-3379,-3382,-3385,-3387,-3390,-3393,-3395,-3397,-3400,-3402,-3404,
+-3406,-3409,-3410,-3412,-3414,-3416,-3418,-3419,-3421,-3422,-3423,-3425,-3426,-3427,-3429,-3430,-3431,-3432,-3433,-3434,-3435,
+-3436,-3437,-3438,-3440,-3441,-3442,-3443,-3445,-3446,-3447,-3449,-3450,-3452,-3454,-3455,-3457,-3459,-3461,-3463,-3465,-3467,
+-3469,-3472,-3474,-3476,-3479,-3481,-3484,-3486,-3489,-3491,-3494,-3496,-3499,-3501,-3504,-3506,-3508,-3510,-3513,-3515,-3516,
+-3518,-3520,-3521,-3523,-3524,-3525,-3526,-3527,-3527,-3528,-3528,-3528,-3528,-3528,-3527,-3527,-3526,-3525,-3524,-3523,-3521,
+-3520,-3518,-3516,-3514,-3512,-3510,-3508,-3505,-3502,-3500,-3497,-3494,-3491,-3488,-3485,-3481,-3478,-3474,-3471,-3467,-3464,
+-3460,-3456,-3452,-3448,-3444,-3440,-3436,-3432,-3428,-3424,-3419,-3415,-3411,-3406,-3402,-3397,-3393,-3389,-3384,-3380,-3375,
+-3371,-3366,-3362,-3358,-3353,-3349,-3345,-3341,-3337,-3333,-3329,-3325,-3322,-3318,-3315,-3312,-3309,-3306,-3304,-3301,-3299,
+-3297,-3295,-3294,-3292,-3291,-3290,-3290,-3290,-3289,-3290,-3290,-3291,-3292,-3293,-3294,-3296,-3297,-3300,-3302,-3304,-3307,
+-3310,-3313,-3316,-3320,-3323,-3327,-3331,-3335,-3339,-3343,-3347,-3351,-3355,-3360,-3364,-3368,-3372,-3377,-3381,-3385,-3389,
+-3393,-3397,-3400,-3404,-3407,-3410,-3414,-3416,-3419,-3422,-3424,-3426,-3428,-3430,-3432,-3433,-3434,-3435,-3436,-3436,-3437,
+-3437,-3437,-3437,-3437,-3436,-3436,-3435,-3435,-3434,-3433,-3433,-3432,-3431,-3430,-3430,-3429,-3429,-3429,-3428,-3428,-3429,
+-3429,-3430,-3430,-3431,-3433,-3434,-3436,-3438,-3441,-3443,-3446,-3450,-3453,-3457,-3461,-3465,-3470,-3475,-3480,-3485,-3490,
+-3496,-3501,-3507,-3513,-3518,-3524,-3530,-3536,-3541,-3546,-3552,-3557,-3561,-3566,-3570,-3574,-3578,-3581,-3583,-3585,-3587,
+-3588,-3589,-3589,-3588,-3587,-3585,-3583,-3580,-3576,-3572,-3567,-3561,-3555,-3548,-3541,-3533,-3524,-3515,-3505,-3494,-3484,
+-3472,-3460,-3448,-3436,-3422,-3409,-3396,-3382,-3368,-3354,-3340,-3326,-3312,-3298,-3284,-3270,-3256,-3243,-3230,-3217,-3204,
+-3193,-3181,-3170,-3160,-3150,-3141,-3132,-3124,-3117,-3111,-3105,-3100,-3096,-3093,-3090,-3089,-3088,-3088,-3088,-3090,-3092,
+-3095,-3099,-3103,-3108,-3113,-3119,-3126,-3133,-3140,-3148,-3156,-3164,-3173,-3181,-3190,-3198,-3206,-3215,-3222,-3230,-3237,
+-3244,-3251,-3257,-3262,-3266,-3270,-3273,-3276,-3277,-3278,-3278,-3277,-3276,-3273,-3269,-3265,-3260,-3254,-3247,-3240,-3232,
+-3223,-3214,-3204,-3193,-3182,-3171,-3160,-3148,-3136,-3124,-3113,-3101,-3089,-3078,-3067,-3057,-3047,-3037,-3028,-3020,-3013,
+-3006,-3000,-2995,-2991,-2988,-2985,-2984,-2983,-2984,-2985,-2987,-2991,-2994,-2999,-3005,-3011,-3018,-3025,-3033,-3041,-3050,
+-3059,-3068,-3077,-3087,-3096,-3105,-3114,-3123,-3131,-3139,-3146,-3153,-3159,-3164,-3169,-3173,-3176,-3178,-3179,-3180,-3179,
+-3177,-3175,-3172,-3167,-3162,-3156,-3149,-3141,-3132,-3123,-3113,-3103,-3092,-3080,-3068,-3056,-3044,-3031,-3018,-3005,-2992,
+-2979,-2967,-2955,-2942,-2931,-2920,-2909,-2898,-2889,-2880,-2871,-2863,-2856,-2850,-2844,-2839,-2835,-2832,-2829,-2827,-2826,
+-2826,-2826,-2827,-2828,-2831,-2833,-2837,-2840,-2845,-2849,-2854,-2859,-2865,-2871,-2877,-2883,-2889,-2896,-2902,-2908,-2915,
+-2921,-2927,-2933,-2938,-2944,-2949,-2954,-2959,-2964,-2968,-2972,-2975,-2979,-2982,-2984,-2986,-2988,-2990,-2991,-2992,-2993,
+-2993,-2993,-2993,-2993,-2992,-2991,-2990,-2988,-2986,-2984,-2982,-2980,-2977,-2974,-2971,-2968,-2964,-2961,-2957,-2953,-2948,
+-2944,-2939,-2935,-2930,-2925,-2919,-2914,-2908,-2902,-2896,-2889,-2883,-2876,-2869,-2861,-2854,-2846,-2838,-2830,-2821,-2812,
+-2803,-2794,-2784,-2775,-2764,-2754,-2744,-2733,-2722,-2711,-2699,-2688,-2676,-2664,-2652,-2640,-2628,-2615,-2603,-2590,-2578,
+-2565,-2553,-2541,-2528,-2516,-2504,-2492,-2480,-2468,-2457,-2446,-2435,-2424,-2414,-2404,-2394,-2385,-2376,-2368,-2360,-2353,
+-2346,-2339,-2333,-2328,-2323,-2318,-2314,-2311,-2308,-2305,-2303,-2302,-2301,-2301,-2301,-2301,-2302,-2303,-2305,-2307,-2310,
+-2312,-2315,-2319,-2323,-2327,-2331,-2335,-2340,-2345,-2350,-2355,-2360,-2365,-2371,-2376,-2382,-2388,-2394,-2399,-2405,-2411,
+-2417,-2423,-2430,-2436,-2442,-2449,-2455,-2461,-2468,-2475,-2481,-2488,-2495,-2502,-2509,-2516,-2524,-2531,-2539,-2546,-2554,
+-2561,-2569,-2577,-2584,-2592,-2600,-2608,-2615,-2623,-2630,-2637,-2644,-2651,-2657,-2663,-2669,-2674,-2679,-2684,-2688,-2691,
+-2694,-2697,-2698,-2699,-2700,-2700,-2699,-2697,-2694,-2691,-2687,-2683,-2677,-2671,-2664,-2656,-2648,-2638,-2629,-2618,-2607,
+-2595,-2583,-2570,-2557,-2543,-2529,-2515,-2501,-2486,-2471,-2456,-2441,-2425,-2410,-2395,-2380,-2366,-2351,-2337,-2323,-2309,
+-2296,-2283,-2270,-2258,-2247,-2236,-2225,-2215,-2205,-2196,-2187,-2179,-2172,-2165,-2158,-2151,-2146,-2140,-2135,-2130,-2126,
+-2122,-2118,-2114,-2110,-2107,-2104,-2101,-2098,-2095,-2092,-2089,-2086,-2083,-2080,-2077,-2073,-2070,-2066,-2063,-2059,-2055,
+-2051,-2046,-2042,-2037,-2033,-2028,-2023,-2018,-2012,-2007,-2002,-1996,-1991,-1985,-1979,-1974,-1968,-1963,-1957,-1952,-1947,
+-1942,-1937,-1932,-1928,-1923,-1919,-1915,-1911,-1908,-1904,-1901,-1898,-1896,-1894,-1892,-1890,-1888,-1887,-1886,-1885,-1885,
+-1884,-1884,-1884,-1885,-1885,-1886,-1887,-1888,-1889,-1891,-1892,-1894,-1895,-1897,-1899,-1901,-1903,-1905,-1907,-1909,-1911,
+-1913,-1915,-1917,-1919,-1921,-1923,-1925,-1927,-1928,-1930,-1932,-1934,-1935,-1937,-1938,-1940,-1941,-1943,-1944,-1945,-1947,
+-1948,-1949,-1950,-1951,-1952,-1953,-1954,-1955,-1956,-1957,-1958,-1959,-1960,-1961,-1962,-1963,-1964,-1964,-1965,-1966,-1966,
+-1967,-2057,-2058,-2058,-2058,-2058,-2057,-2057,-2056,-2055,-2054,-2052,-2051,-2049,-2047,-2044,-2042,-2039,-2036,-2032,-2029,
+-2025,-2021,-2016,-2012,-2007,-2002,-1996,-1991,-1985,-1979,-1973,-1967,-1960,-1954,-1947,-1940,-1933,-1926,-1919,-1912,-1904,
+-1897,-1890,-1883,-1876,-1869,-1862,-1855,-1848,-1842,-1835,-1829,-1823,-1817,-1811,-1806,-1801,-1796,-1791,-1787,-1783,-1779,
+-1775,-1772,-1769,-1767,-1764,-1762,-1760,-1758,-1757,-1756,-1755,-1754,-1753,-1753,-1753,-1752,-1752,-1752,-1753,-1753,-1753,
+-1753,-1753,-1754,-1754,-1754,-1754,-1754,-1754,-1753,-1753,-1752,-1752,-1751,-1750,-1748,-1747,-1745,-1743,-1741,-1738,-1736,
+-1733,-1730,-1727,-1723,-1720,-1716,-1712,-1707,-1703,-1699,-1694,-1689,-1685,-1680,-1675,-1670,-1665,-1660,-1655,-1650,-1645,
+-1640,-1636,-1631,-1627,-1622,-1618,-1614,-1610,-1607,-1604,-1600,-1598,-1595,-1593,-1591,-1589,-1588,-1587,-1586,-1585,-1585,
+-1585,-1585,-1586,-1587,-1588,-1590,-1591,-1593,-1596,-1598,-1601,-1604,-1607,-1610,-1614,-1618,-1621,-1625,-1629,-1633,-1637,
+-1642,-1646,-1650,-1654,-1658,-1662,-1666,-1670,-1674,-1678,-1682,-1685,-1688,-1692,-1695,-1697,-1700,-1703,-1705,-1707,-1709,
+-1710,-1711,-1713,-1714,-1714,-1715,-1715,-1715,-1715,-1715,-1714,-1714,-1713,-1712,-1711,-1710,-1709,-1707,-1706,-1704,-1703,
+-1701,-1700,-1698,-1697,-1696,-1694,-1693,-1692,-1691,-1690,-1689,-1689,-1688,-1688,-1688,-1689,-1689,-1690,-1691,-1692,-1694,
+-1695,-1698,-1700,-1703,-1705,-1709,-1712,-1716,-1720,-1724,-1729,-1733,-1738,-1744,-1749,-1755,-1761,-1767,-1773,-1780,-1786,
+-1793,-1800,-1807,-1814,-1821,-1829,-1836,-1843,-1851,-1858,-1866,-1873,-1880,-1888,-1895,-1902,-1909,-1917,-1923,-1930,-1937,
+-1944,-1951,-1957,-1963,-1969,-1976,-1981,-1987,-1993,-1998,-2004,-2009,-2014,-2019,-2024,-2028,-2033,-2037,-2042,-2046,-2050,
+-2054,-2058,-2061,-2065,-2069,-2072,-2076,-2079,-2083,-2086,-2089,-2093,-2096,-2099,-2102,-2105,-2109,-2112,-2115,-2118,-2121,
+-2125,-2128,-2131,-2135,-2138,-2141,-2145,-2148,-2152,-2155,-2159,-2163,-2166,-2170,-2174,-2178,-2182,-2186,-2190,-2194,-2198,
+-2202,-2206,-2210,-2215,-2219,-2223,-2228,-2232,-2237,-2241,-2246,-2251,-2255,-2260,-2265,-2270,-2275,-2280,-2285,-2290,-2295,
+-2300,-2305,-2310,-2315,-2321,-2326,-2331,-2337,-2342,-2348,-2353,-2359,-2365,-2371,-2376,-2382,-2388,-2394,-2400,-2406,-2413,
+-2419,-2425,-2432,-2438,-2445,-2451,-2458,-2465,-2472,-2479,-2486,-2493,-2500,-2507,-2515,-2522,-2530,-2537,-2545,-2552,-2560,
+-2568,-2576,-2584,-2592,-2600,-2608,-2616,-2624,-2633,-2641,-2649,-2658,-2666,-2674,-2683,-2691,-2700,-2708,-2717,-2725,-2733,
+-2742,-2750,-2759,-2767,-2775,-2783,-2792,-2800,-2808,-2816,-2824,-2832,-2840,-2848,-2855,-2863,-2871,-2878,-2886,-2893,-2900,
+-2908,-2915,-2922,-2929,-2936,-2943,-2949,-2956,-2962,-2969,-2975,-2981,-2988,-2994,-3000,-3006,-3011,-3017,-3023,-3028,-3034,
+-3039,-3044,-3050,-3055,-3060,-3065,-3070,-3074,-3079,-3084,-3088,-3093,-3097,-3102,-3106,-3110,-3114,-3118,-3122,-3126,-3130,
+-3134,-3137,-3141,-3145,-3148,-3152,-3155,-3159,-3162,-3166,-3169,-3172,-3175,-3179,-3182,-3185,-3188,-3191,-3194,-3197,-3200,
+-3203,-3207,-3210,-3213,-3215,-3219,-3222,-3225,-3228,-3231,-3234,-3237,-3240,-3243,-3246,-3249,-3252,-3255,-3258,-3261,-3264,
+-3267,-3270,-3273,-3276,-3279,-3282,-3285,-3288,-3290,-3293,-3296,-3299,-3302,-3305,-3308,-3310,-3313,-3316,-3318,-3321,-3324,
+-3326,-3329,-3331,-3333,-3336,-3338,-3340,-3342,-3345,-3347,-3349,-3351,-3353,-3354,-3356,-3358,-3360,-3361,-3363,-3365,-3366,
+-3368,-3369,-3371,-3372,-3374,-3375,-3377,-3378,-3379,-3381,-3382,-3383,-3384,-3386,-3387,-3388,-3389,-3391,-3392,-3393,-3395,
+-3396,-3397,-3398,-3400,-3401,-3402,-3403,-3405,-3406,-3407,-3409,-3410,-3411,-3412,-3414,-3415,-3416,-3417,-3418,-3419,-3420,
+-3421,-3422,-3423,-3424,-3425,-3426,-3426,-3427,-3428,-3428,-3429,-3429,-3429,-3430,-3430,-3430,-3430,-3430,-3430,-3430,-3430,
+-3429,-3429,-3429,-3428,-3428,-3427,-3426,-3426,-3425,-3424,-3423,-3422,-3422,-3421,-3420,-3419,-3418,-3416,-3415,-3414,-3413,
+-3411,-3410,-3409,-3407,-3406,-3404,-3403,-3401,-3400,-3398,-3396,-3394,-3392,-3390,-3388,-3386,-3384,-3382,-3379,-3377,-3374,
+-3371,-3368,-3365,-3362,-3359,-3356,-3352,-3349,-3345,-3341,-3338,-3334,-3330,-3326,-3321,-3317,-3313,-3308,-3304,-3300,-3295,
+-3291,-3286,-3282,-3277,-3273,-3269,-3264,-3260,-3256,-3252,-3248,-3245,-3241,-3238,-3235,-3232,-3229,-3227,-3225,-3223,-3221,
+-3220,-3219,-3218,-3217,-3217,-3217,-3217,-3218,-3219,-3220,-3222,-3223,-3226,-3228,-3230,-3233,-3236,-3240,-3243,-3247,-3251,
+-3255,-3259,-3263,-3268,-3272,-3277,-3281,-3286,-3290,-3295,-3299,-3304,-3308,-3312,-3317,-3320,-3324,-3328,-3331,-3334,-3337,
+-3340,-3343,-3345,-3347,-3349,-3350,-3351,-3352,-3353,-3354,-3354,-3354,-3353,-3353,-3352,-3352,-3351,-3349,-3348,-3347,-3345,
+-3344,-3342,-3340,-3339,-3337,-3336,-3334,-3333,-3332,-3330,-3329,-3329,-3328,-3328,-3328,-3328,-3328,-3329,-3330,-3332,-3333,
+-3335,-3338,-3340,-3343,-3346,-3350,-3354,-3358,-3362,-3367,-3372,-3377,-3382,-3387,-3393,-3398,-3404,-3410,-3416,-3422,-3427,
+-3433,-3438,-3444,-3449,-3454,-3459,-3463,-3467,-3471,-3474,-3477,-3479,-3481,-3483,-3483,-3484,-3484,-3483,-3481,-3479,-3477,
+-3473,-3470,-3465,-3460,-3454,-3448,-3441,-3433,-3425,-3416,-3407,-3397,-3387,-3377,-3365,-3354,-3342,-3330,-3318,-3305,-3293,
+-3280,-3267,-3254,-3241,-3228,-3215,-3202,-3189,-3177,-3165,-3153,-3142,-3130,-3120,-3110,-3100,-3091,-3082,-3074,-3067,-3060,
+-3054,-3048,-3043,-3039,-3036,-3033,-3031,-3029,-3028,-3028,-3029,-3030,-3031,-3034,-3036,-3039,-3043,-3047,-3052,-3057,-3062,
+-3067,-3073,-3078,-3084,-3090,-3096,-3102,-3107,-3113,-3118,-3124,-3128,-3133,-3137,-3141,-3144,-3147,-3149,-3151,-3152,-3153,
+-3153,-3152,-3151,-3149,-3147,-3144,-3140,-3136,-3131,-3126,-3120,-3113,-3106,-3099,-3092,-3084,-3075,-3067,-3058,-3050,-3041,
+-3032,-3023,-3014,-3006,-2997,-2989,-2981,-2974,-2966,-2960,-2954,-2948,-2943,-2938,-2934,-2931,-2928,-2926,-2925,-2925,-2925,
+-2925,-2927,-2929,-2932,-2935,-2939,-2944,-2949,-2955,-2961,-2967,-2974,-2981,-2988,-2995,-3003,-3011,-3018,-3026,-3034,-3041,
+-3048,-3055,-3061,-3068,-3073,-3078,-3083,-3087,-3091,-3094,-3096,-3098,-3099,-3099,-3099,-3098,-3096,-3093,-3090,-3086,-3081,
+-3076,-3070,-3064,-3057,-3050,-3042,-3033,-3025,-3016,-3006,-2997,-2987,-2977,-2968,-2958,-2948,-2938,-2929,-2920,-2910,-2902,
+-2893,-2885,-2878,-2871,-2864,-2858,-2852,-2847,-2843,-2839,-2836,-2833,-2831,-2830,-2830,-2830,-2830,-2831,-2833,-2836,-2839,
+-2842,-2846,-2851,-2856,-2861,-2867,-2873,-2879,-2886,-2893,-2900,-2907,-2914,-2922,-2929,-2936,-2944,-2951,-2958,-2966,-2972,
+-2979,-2986,-2992,-2998,-3003,-3009,-3014,-3018,-3022,-3026,-3029,-3032,-3035,-3037,-3038,-3039,-3040,-3040,-3040,-3039,-3038,
+-3036,-3034,-3031,-3028,-3025,-3021,-3017,-3012,-3007,-3002,-2996,-2990,-2983,-2977,-2970,-2962,-2955,-2947,-2939,-2930,-2922,
+-2913,-2904,-2894,-2885,-2875,-2866,-2856,-2846,-2836,-2825,-2815,-2804,-2794,-2783,-2772,-2761,-2751,-2740,-2729,-2718,-2707,
+-2696,-2684,-2673,-2662,-2651,-2640,-2629,-2618,-2607,-2596,-2585,-2575,-2564,-2553,-2543,-2532,-2522,-2512,-2502,-2492,-2482,
+-2473,-2464,-2455,-2446,-2437,-2429,-2421,-2413,-2405,-2398,-2391,-2384,-2377,-2371,-2365,-2360,-2355,-2350,-2346,-2342,-2338,
+-2334,-2331,-2329,-2327,-2325,-2323,-2322,-2321,-2321,-2321,-2321,-2322,-2322,-2324,-2325,-2327,-2330,-2332,-2335,-2339,-2342,
+-2346,-2350,-2355,-2359,-2364,-2369,-2375,-2380,-2386,-2392,-2399,-2405,-2412,-2419,-2426,-2433,-2441,-2448,-2456,-2464,-2472,
+-2480,-2488,-2497,-2505,-2514,-2522,-2531,-2539,-2548,-2557,-2565,-2574,-2582,-2591,-2599,-2608,-2616,-2624,-2631,-2639,-2646,
+-2653,-2660,-2667,-2673,-2679,-2684,-2689,-2694,-2698,-2701,-2705,-2707,-2709,-2711,-2712,-2713,-2713,-2712,-2711,-2709,-2706,
+-2703,-2699,-2695,-2690,-2684,-2678,-2671,-2664,-2656,-2648,-2639,-2630,-2620,-2610,-2599,-2588,-2577,-2565,-2553,-2541,-2529,
+-2517,-2504,-2491,-2479,-2466,-2453,-2440,-2428,-2415,-2403,-2390,-2378,-2367,-2355,-2344,-2333,-2322,-2312,-2301,-2292,-2282,
+-2273,-2264,-2256,-2248,-2240,-2233,-2226,-2219,-2213,-2207,-2201,-2196,-2190,-2185,-2181,-2176,-2171,-2167,-2163,-2159,-2155,
+-2151,-2147,-2144,-2140,-2136,-2132,-2129,-2125,-2121,-2117,-2113,-2109,-2105,-2101,-2096,-2092,-2087,-2083,-2078,-2073,-2068,
+-2063,-2058,-2053,-2048,-2043,-2038,-2033,-2028,-2023,-2018,-2013,-2008,-2003,-1998,-1993,-1989,-1984,-1980,-1976,-1972,-1968,
+-1964,-1961,-1958,-1955,-1952,-1949,-1947,-1945,-1943,-1942,-1940,-1939,-1938,-1938,-1937,-1937,-1937,-1937,-1938,-1939,-1939,
+-1940,-1942,-1943,-1945,-1946,-1948,-1950,-1952,-1955,-1957,-1959,-1962,-1964,-1967,-1970,-1972,-1975,-1978,-1981,-1984,-1986,
+-1989,-1992,-1995,-1998,-2000,-2003,-2006,-2009,-2011,-2014,-2017,-2019,-2022,-2024,-2026,-2029,-2031,-2033,-2035,-2037,-2039,
+-2041,-2043,-2045,-2047,-2048,-2050,-2051,-2052,-2053,-2054,-2055,-2056,-2057,-2057,-2112,-2112,-2112,-2111,-2111,-2110,-2109,
+-2107,-2106,-2104,-2102,-2100,-2098,-2096,-2093,-2090,-2087,-2084,-2080,-2077,-2073,-2069,-2065,-2060,-2056,-2051,-2046,-2041,
+-2036,-2031,-2025,-2020,-2014,-2009,-2003,-1997,-1991,-1985,-1979,-1973,-1967,-1961,-1955,-1950,-1944,-1938,-1932,-1927,-1922,
+-1916,-1911,-1906,-1901,-1897,-1892,-1888,-1884,-1880,-1876,-1873,-1870,-1867,-1864,-1861,-1859,-1857,-1855,-1853,-1851,-1850,
+-1848,-1847,-1846,-1846,-1845,-1844,-1844,-1844,-1843,-1843,-1843,-1843,-1843,-1843,-1843,-1843,-1843,-1842,-1842,-1842,-1841,
+-1841,-1840,-1839,-1839,-1838,-1836,-1835,-1833,-1832,-1830,-1828,-1825,-1823,-1820,-1818,-1814,-1811,-1808,-1805,-1801,-1797,
+-1793,-1789,-1785,-1781,-1776,-1772,-1768,-1763,-1759,-1754,-1749,-1745,-1740,-1736,-1732,-1727,-1723,-1719,-1715,-1711,-1708,
+-1704,-1701,-1698,-1695,-1692,-1690,-1688,-1686,-1684,-1683,-1682,-1681,-1680,-1680,-1680,-1680,-1681,-1682,-1683,-1684,-1686,
+-1688,-1689,-1692,-1694,-1697,-1700,-1703,-1706,-1709,-1713,-1716,-1720,-1723,-1727,-1731,-1735,-1739,-1743,-1747,-1751,-1755,
+-1758,-1762,-1766,-1769,-1773,-1776,-1779,-1782,-1785,-1788,-1790,-1793,-1795,-1797,-1799,-1801,-1803,-1804,-1805,-1806,-1807,
+-1808,-1809,-1809,-1809,-1810,-1810,-1810,-1810,-1809,-1809,-1809,-1808,-1808,-1808,-1807,-1807,-1806,-1806,-1806,-1805,-1805,
+-1805,-1805,-1806,-1806,-1806,-1807,-1808,-1809,-1810,-1811,-1813,-1814,-1816,-1818,-1821,-1823,-1826,-1829,-1832,-1836,-1839,
+-1843,-1847,-1852,-1856,-1861,-1866,-1871,-1876,-1881,-1887,-1892,-1898,-1904,-1910,-1916,-1922,-1928,-1935,-1941,-1947,-1954,
+-1960,-1966,-1973,-1979,-1986,-1992,-1998,-2004,-2010,-2016,-2022,-2028,-2034,-2040,-2045,-2051,-2056,-2061,-2067,-2072,-2077,
+-2081,-2086,-2090,-2095,-2099,-2103,-2107,-2111,-2115,-2119,-2123,-2126,-2130,-2133,-2136,-2140,-2143,-2146,-2149,-2152,-2155,
+-2158,-2161,-2164,-2167,-2170,-2173,-2176,-2179,-2182,-2185,-2188,-2191,-2194,-2197,-2200,-2203,-2206,-2210,-2213,-2216,-2220,
+-2223,-2227,-2230,-2234,-2237,-2241,-2245,-2249,-2252,-2256,-2260,-2264,-2268,-2272,-2277,-2281,-2285,-2289,-2294,-2298,-2302,
+-2307,-2311,-2315,-2320,-2324,-2329,-2334,-2338,-2343,-2347,-2352,-2357,-2361,-2366,-2371,-2376,-2380,-2385,-2390,-2395,-2400,
+-2405,-2410,-2415,-2420,-2425,-2430,-2435,-2440,-2446,-2451,-2456,-2462,-2467,-2473,-2478,-2484,-2490,-2495,-2501,-2507,-2513,
+-2519,-2525,-2531,-2537,-2544,-2550,-2557,-2563,-2570,-2576,-2583,-2590,-2596,-2603,-2610,-2617,-2624,-2631,-2639,-2646,-2653,
+-2660,-2668,-2675,-2682,-2690,-2697,-2705,-2712,-2720,-2727,-2734,-2742,-2749,-2757,-2764,-2772,-2779,-2786,-2794,-2801,-2808,
+-2816,-2823,-2830,-2837,-2844,-2851,-2858,-2865,-2871,-2878,-2885,-2891,-2898,-2904,-2910,-2917,-2923,-2929,-2935,-2941,-2946,
+-2952,-2958,-2963,-2969,-2974,-2980,-2985,-2990,-2995,-3000,-3005,-3010,-3015,-3019,-3024,-3028,-3033,-3037,-3041,-3046,-3050,
+-3054,-3058,-3062,-3066,-3070,-3074,-3077,-3081,-3085,-3088,-3092,-3095,-3099,-3102,-3105,-3109,-3112,-3115,-3118,-3122,-3125,
+-3128,-3131,-3134,-3137,-3140,-3143,-3146,-3148,-3151,-3154,-3157,-3160,-3162,-3165,-3168,-3171,-3173,-3176,-3179,-3181,-3184,
+-3187,-3189,-3192,-3195,-3197,-3200,-3202,-3205,-3208,-3210,-3213,-3215,-3218,-3220,-3223,-3225,-3228,-3230,-3233,-3235,-3238,
+-3240,-3242,-3245,-3247,-3250,-3252,-3254,-3257,-3259,-3261,-3264,-3266,-3268,-3270,-3272,-3275,-3277,-3279,-3281,-3283,-3285,
+-3287,-3289,-3291,-3293,-3295,-3297,-3299,-3301,-3303,-3305,-3307,-3308,-3310,-3312,-3314,-3315,-3317,-3318,-3320,-3322,-3323,
+-3325,-3326,-3328,-3329,-3330,-3332,-3333,-3334,-3336,-3337,-3338,-3339,-3340,-3341,-3342,-3343,-3344,-3345,-3345,-3346,-3347,
+-3347,-3348,-3348,-3349,-3349,-3349,-3350,-3350,-3350,-3350,-3350,-3350,-3350,-3350,-3350,-3349,-3349,-3349,-3348,-3348,-3347,
+-3347,-3346,-3346,-3345,-3344,-3344,-3343,-3342,-3342,-3341,-3340,-3339,-3339,-3338,-3337,-3336,-3335,-3335,-3334,-3333,-3332,
+-3332,-3331,-3330,-3330,-3329,-3329,-3328,-3328,-3327,-3326,-3326,-3325,-3325,-3324,-3324,-3323,-3323,-3322,-3322,-3321,-3321,
+-3320,-3319,-3318,-3318,-3317,-3316,-3315,-3313,-3312,-3311,-3309,-3308,-3306,-3304,-3303,-3301,-3298,-3296,-3294,-3291,-3289,
+-3286,-3283,-3280,-3277,-3273,-3270,-3266,-3263,-3259,-3255,-3251,-3247,-3243,-3239,-3235,-3231,-3227,-3223,-3219,-3215,-3211,
+-3207,-3203,-3200,-3196,-3192,-3189,-3186,-3183,-3180,-3177,-3174,-3172,-3170,-3168,-3166,-3165,-3164,-3163,-3162,-3161,-3161,
+-3161,-3162,-3162,-3163,-3164,-3165,-3166,-3168,-3170,-3172,-3174,-3177,-3179,-3182,-3185,-3188,-3191,-3194,-3197,-3200,-3204,
+-3207,-3210,-3213,-3217,-3220,-3223,-3226,-3229,-3231,-3234,-3236,-3239,-3241,-3243,-3245,-3246,-3248,-3249,-3250,-3251,-3252,
+-3252,-3253,-3253,-3253,-3252,-3252,-3252,-3251,-3250,-3249,-3248,-3247,-3246,-3245,-3244,-3243,-3242,-3241,-3240,-3239,-3238,
+-3237,-3236,-3236,-3235,-3235,-3235,-3235,-3235,-3236,-3237,-3238,-3239,-3240,-3242,-3244,-3246,-3249,-3252,-3254,-3258,-3261,
+-3264,-3268,-3272,-3276,-3280,-3285,-3289,-3293,-3298,-3303,-3307,-3312,-3316,-3321,-3325,-3329,-3333,-3337,-3340,-3344,-3347,
+-3350,-3352,-3355,-3357,-3358,-3359,-3360,-3360,-3360,-3359,-3358,-3357,-3355,-3352,-3349,-3346,-3342,-3338,-3333,-3327,-3322,
+-3315,-3309,-3302,-3295,-3287,-3279,-3270,-3262,-3253,-3244,-3235,-3225,-3216,-3206,-3196,-3186,-3177,-3167,-3157,-3148,-3138,
+-3129,-3120,-3111,-3103,-3094,-3086,-3079,-3071,-3065,-3058,-3052,-3046,-3041,-3036,-3032,-3028,-3025,-3022,-3020,-3018,-3016,
+-3015,-3014,-3014,-3014,-3015,-3016,-3017,-3019,-3021,-3023,-3025,-3028,-3031,-3034,-3037,-3040,-3043,-3046,-3049,-3053,-3056,
+-3058,-3061,-3064,-3066,-3068,-3070,-3072,-3073,-3074,-3075,-3075,-3075,-3075,-3074,-3073,-3071,-3069,-3067,-3064,-3061,-3057,
+-3054,-3049,-3045,-3040,-3035,-3030,-3024,-3019,-3013,-3007,-3001,-2995,-2989,-2983,-2977,-2971,-2965,-2959,-2953,-2948,-2943,
+-2938,-2933,-2929,-2925,-2922,-2918,-2916,-2913,-2911,-2910,-2909,-2908,-2908,-2908,-2908,-2909,-2911,-2913,-2915,-2918,-2921,
+-2924,-2927,-2931,-2935,-2939,-2944,-2948,-2953,-2957,-2962,-2967,-2971,-2976,-2980,-2985,-2989,-2992,-2996,-2999,-3002,-3005,
+-3007,-3009,-3011,-3012,-3012,-3013,-3012,-3012,-3010,-3009,-3007,-3004,-3001,-2998,-2994,-2990,-2985,-2980,-2975,-2969,-2963,
+-2957,-2951,-2944,-2938,-2931,-2924,-2917,-2910,-2903,-2896,-2890,-2883,-2876,-2870,-2864,-2858,-2853,-2848,-2843,-2838,-2834,
+-2830,-2827,-2824,-2822,-2820,-2818,-2817,-2816,-2816,-2817,-2817,-2819,-2820,-2823,-2825,-2828,-2831,-2835,-2839,-2843,-2848,
+-2853,-2858,-2864,-2869,-2875,-2881,-2887,-2893,-2899,-2905,-2911,-2916,-2922,-2928,-2934,-2939,-2944,-2949,-2954,-2958,-2963,
+-2966,-2970,-2973,-2976,-2978,-2980,-2982,-2983,-2984,-2984,-2984,-2984,-2983,-2982,-2980,-2978,-2975,-2972,-2969,-2965,-2961,
+-2956,-2951,-2946,-2940,-2934,-2928,-2921,-2914,-2907,-2899,-2892,-2884,-2876,-2867,-2859,-2850,-2841,-2832,-2823,-2814,-2804,
+-2795,-2785,-2776,-2766,-2756,-2747,-2737,-2727,-2717,-2708,-2698,-2688,-2679,-2669,-2660,-2650,-2641,-2631,-2622,-2613,-2604,
+-2595,-2586,-2577,-2568,-2559,-2551,-2542,-2534,-2526,-2518,-2510,-2502,-2494,-2487,-2479,-2472,-2465,-2458,-2451,-2445,-2438,
+-2432,-2426,-2420,-2414,-2409,-2403,-2398,-2393,-2389,-2384,-2380,-2376,-2373,-2369,-2366,-2363,-2361,-2358,-2356,-2354,-2353,
+-2352,-2351,-2350,-2350,-2350,-2350,-2351,-2352,-2353,-2355,-2357,-2359,-2361,-2364,-2367,-2371,-2374,-2378,-2383,-2387,-2392,
+-2397,-2403,-2408,-2414,-2420,-2427,-2433,-2440,-2447,-2454,-2462,-2469,-2477,-2485,-2492,-2500,-2508,-2516,-2524,-2532,-2541,
+-2549,-2557,-2565,-2572,-2580,-2588,-2595,-2602,-2609,-2616,-2623,-2629,-2635,-2641,-2646,-2651,-2656,-2660,-2664,-2668,-2671,
+-2674,-2676,-2677,-2679,-2679,-2679,-2679,-2678,-2677,-2675,-2673,-2670,-2666,-2662,-2658,-2653,-2648,-2642,-2635,-2629,-2621,
+-2614,-2605,-2597,-2588,-2579,-2569,-2560,-2550,-2539,-2529,-2518,-2507,-2496,-2485,-2474,-2462,-2451,-2440,-2429,-2417,-2406,
+-2395,-2384,-2373,-2362,-2352,-2342,-2331,-2322,-2312,-2303,-2293,-2285,-2276,-2268,-2260,-2252,-2244,-2237,-2230,-2224,-2218,
+-2212,-2206,-2200,-2195,-2190,-2185,-2181,-2177,-2172,-2168,-2165,-2161,-2158,-2154,-2151,-2148,-2145,-2142,-2139,-2137,-2134,
+-2131,-2128,-2126,-2123,-2120,-2118,-2115,-2112,-2110,-2107,-2104,-2101,-2098,-2096,-2093,-2090,-2087,-2084,-2081,-2078,-2075,
+-2072,-2069,-2066,-2063,-2060,-2058,-2055,-2052,-2049,-2047,-2044,-2042,-2039,-2037,-2035,-2033,-2031,-2029,-2027,-2026,-2025,
+-2023,-2022,-2021,-2020,-2020,-2019,-2019,-2019,-2019,-2019,-2019,-2019,-2020,-2020,-2021,-2022,-2023,-2024,-2026,-2027,-2028,
+-2030,-2032,-2034,-2035,-2037,-2039,-2041,-2044,-2046,-2048,-2050,-2053,-2055,-2057,-2060,-2062,-2064,-2067,-2069,-2072,-2074,
+-2076,-2078,-2081,-2083,-2085,-2087,-2089,-2091,-2093,-2095,-2097,-2099,-2101,-2102,-2104,-2105,-2106,-2108,-2109,-2110,-2110,
+-2111,-2112,-2112,-2112,-2112,-2112,-2197,-2196,-2194,-2193,-2191,-2190,-2188,-2186,-2184,-2182,-2180,-2177,-2175,-2172,-2170,
+-2167,-2164,-2161,-2158,-2155,-2152,-2148,-2145,-2141,-2138,-2134,-2130,-2126,-2122,-2119,-2115,-2111,-2107,-2102,-2098,-2094,
+-2090,-2086,-2082,-2078,-2074,-2070,-2066,-2062,-2058,-2054,-2051,-2047,-2044,-2040,-2037,-2033,-2030,-2027,-2024,-2021,-2019,
+-2016,-2014,-2011,-2009,-2007,-2005,-2003,-2001,-1999,-1998,-1996,-1995,-1993,-1992,-1991,-1990,-1989,-1988,-1987,-1986,-1985,
+-1984,-1983,-1982,-1981,-1980,-1980,-1979,-1978,-1977,-1975,-1974,-1973,-1972,-1970,-1969,-1967,-1965,-1963,-1961,-1959,-1957,
+-1954,-1952,-1949,-1946,-1943,-1940,-1937,-1934,-1930,-1927,-1923,-1919,-1916,-1912,-1907,-1904,-1899,-1895,-1891,-1887,-1882,
+-1878,-1874,-1870,-1865,-1861,-1857,-1853,-1849,-1845,-1841,-1837,-1834,-1830,-1827,-1824,-1821,-1818,-1815,-1813,-1811,-1809,
+-1807,-1805,-1804,-1803,-1802,-1801,-1800,-1800,-1800,-1800,-1801,-1801,-1802,-1803,-1804,-1806,-1807,-1809,-1811,-1813,-1816,
+-1818,-1821,-1823,-1826,-1829,-1832,-1835,-1838,-1842,-1845,-1848,-1852,-1855,-1858,-1862,-1865,-1868,-1872,-1875,-1878,-1882,
+-1885,-1888,-1891,-1894,-1897,-1899,-1902,-1905,-1907,-1909,-1912,-1914,-1916,-1918,-1920,-1922,-1923,-1925,-1927,-1928,-1930,
+-1931,-1932,-1934,-1935,-1936,-1938,-1939,-1940,-1941,-1943,-1944,-1945,-1946,-1948,-1949,-1950,-1952,-1953,-1955,-1957,-1958,
+-1960,-1962,-1964,-1966,-1969,-1971,-1973,-1976,-1979,-1981,-1984,-1987,-1990,-1993,-1997,-2000,-2004,-2007,-2011,-2014,-2018,
+-2022,-2026,-2030,-2034,-2038,-2042,-2046,-2050,-2055,-2059,-2063,-2067,-2071,-2076,-2080,-2084,-2088,-2092,-2096,-2100,-2104,
+-2108,-2112,-2116,-2119,-2123,-2127,-2130,-2134,-2137,-2140,-2144,-2147,-2150,-2153,-2156,-2159,-2162,-2165,-2168,-2170,-2173,
+-2176,-2178,-2181,-2184,-2186,-2189,-2191,-2194,-2196,-2199,-2201,-2204,-2206,-2209,-2212,-2214,-2217,-2220,-2222,-2225,-2228,
+-2231,-2234,-2237,-2240,-2243,-2246,-2250,-2253,-2256,-2260,-2263,-2267,-2271,-2274,-2278,-2282,-2286,-2290,-2294,-2298,-2303,
+-2307,-2311,-2315,-2320,-2324,-2329,-2333,-2338,-2342,-2347,-2352,-2356,-2361,-2366,-2371,-2375,-2380,-2385,-2390,-2394,-2399,
+-2404,-2409,-2414,-2418,-2423,-2428,-2433,-2438,-2442,-2447,-2452,-2457,-2461,-2466,-2471,-2476,-2481,-2485,-2490,-2495,-2500,
+-2505,-2510,-2514,-2519,-2524,-2529,-2534,-2539,-2544,-2549,-2554,-2559,-2565,-2570,-2575,-2580,-2586,-2591,-2596,-2602,-2607,
+-2613,-2619,-2624,-2630,-2636,-2641,-2647,-2653,-2659,-2665,-2671,-2677,-2683,-2689,-2695,-2701,-2707,-2713,-2720,-2726,-2732,
+-2738,-2744,-2751,-2757,-2763,-2769,-2776,-2782,-2788,-2794,-2800,-2807,-2813,-2819,-2825,-2831,-2837,-2843,-2849,-2855,-2860,
+-2866,-2872,-2878,-2883,-2889,-2894,-2900,-2905,-2910,-2915,-2921,-2926,-2931,-2936,-2940,-2945,-2950,-2955,-2959,-2964,-2968,
+-2973,-2977,-2981,-2986,-2990,-2994,-2998,-3002,-3006,-3009,-3013,-3017,-3021,-3024,-3028,-3031,-3035,-3038,-3041,-3045,-3048,
+-3051,-3054,-3058,-3061,-3064,-3067,-3070,-3073,-3076,-3078,-3081,-3084,-3087,-3090,-3092,-3095,-3098,-3100,-3103,-3106,-3108,
+-3111,-3113,-3116,-3118,-3121,-3123,-3126,-3128,-3130,-3133,-3135,-3138,-3140,-3142,-3145,-3147,-3149,-3151,-3154,-3156,-3158,
+-3161,-3163,-3165,-3167,-3170,-3172,-3174,-3176,-3178,-3181,-3183,-3185,-3187,-3190,-3192,-3194,-3196,-3198,-3200,-3203,-3205,
+-3207,-3209,-3211,-3214,-3216,-3218,-3220,-3222,-3224,-3227,-3229,-3231,-3233,-3235,-3237,-3239,-3242,-3244,-3246,-3248,-3250,
+-3252,-3254,-3256,-3258,-3260,-3262,-3264,-3265,-3267,-3269,-3271,-3272,-3274,-3276,-3277,-3279,-3281,-3282,-3283,-3285,-3286,
+-3287,-3289,-3290,-3291,-3292,-3293,-3294,-3294,-3295,-3296,-3297,-3297,-3298,-3298,-3299,-3299,-3299,-3299,-3299,-3300,-3300,
+-3299,-3299,-3299,-3299,-3299,-3299,-3298,-3298,-3297,-3297,-3297,-3296,-3296,-3295,-3294,-3294,-3293,-3293,-3292,-3292,-3291,
+-3290,-3290,-3290,-3289,-3289,-3288,-3288,-3287,-3287,-3287,-3286,-3286,-3286,-3286,-3286,-3286,-3286,-3286,-3286,-3286,-3286,
+-3286,-3286,-3286,-3286,-3286,-3287,-3287,-3287,-3287,-3287,-3288,-3288,-3288,-3288,-3288,-3288,-3288,-3288,-3288,-3287,-3287,
+-3286,-3286,-3285,-3285,-3284,-3283,-3282,-3281,-3280,-3278,-3277,-3275,-3274,-3272,-3270,-3268,-3265,-3263,-3261,-3258,-3256,
+-3253,-3250,-3247,-3245,-3242,-3238,-3235,-3232,-3229,-3226,-3222,-3219,-3216,-3213,-3209,-3206,-3203,-3200,-3197,-3194,-3191,
+-3188,-3185,-3182,-3180,-3177,-3175,-3173,-3170,-3168,-3167,-3165,-3163,-3162,-3160,-3159,-3158,-3157,-3157,-3156,-3155,-3155,
+-3155,-3154,-3154,-3154,-3155,-3155,-3155,-3155,-3156,-3156,-3157,-3157,-3158,-3158,-3159,-3159,-3160,-3160,-3161,-3161,-3161,
+-3161,-3162,-3162,-3162,-3162,-3162,-3161,-3161,-3161,-3160,-3159,-3159,-3158,-3157,-3156,-3155,-3154,-3152,-3151,-3150,-3148,
+-3147,-3145,-3144,-3142,-3140,-3139,-3137,-3136,-3134,-3133,-3131,-3130,-3129,-3128,-3127,-3126,-3125,-3124,-3124,-3123,-3123,
+-3123,-3123,-3123,-3124,-3124,-3125,-3126,-3127,-3129,-3130,-3132,-3134,-3136,-3138,-3140,-3142,-3145,-3148,-3150,-3153,-3156,
+-3159,-3162,-3165,-3169,-3172,-3175,-3178,-3181,-3184,-3187,-3190,-3192,-3195,-3197,-3200,-3202,-3204,-3206,-3207,-3208,-3210,
+-3210,-3211,-3211,-3211,-3211,-3211,-3210,-3209,-3208,-3207,-3205,-3203,-3201,-3198,-3195,-3192,-3189,-3186,-3182,-3178,-3174,
+-3170,-3166,-3162,-3157,-3153,-3148,-3143,-3139,-3134,-3129,-3124,-3120,-3115,-3110,-3106,-3102,-3097,-3093,-3089,-3085,-3082,
+-3078,-3075,-3072,-3069,-3066,-3064,-3062,-3060,-3058,-3056,-3055,-3054,-3053,-3052,-3052,-3051,-3051,-3051,-3052,-3052,-3052,
+-3053,-3054,-3055,-3055,-3056,-3057,-3058,-3059,-3060,-3061,-3062,-3063,-3064,-3064,-3065,-3065,-3065,-3065,-3065,-3065,-3065,
+-3064,-3063,-3062,-3061,-3059,-3058,-3056,-3054,-3051,-3049,-3046,-3043,-3039,-3036,-3032,-3029,-3025,-3021,-3016,-3012,-3008,
+-3003,-2998,-2994,-2989,-2985,-2980,-2975,-2971,-2966,-2962,-2957,-2953,-2949,-2945,-2941,-2937,-2934,-2931,-2928,-2925,-2922,
+-2920,-2918,-2916,-2914,-2913,-2912,-2911,-2910,-2910,-2909,-2909,-2909,-2910,-2910,-2911,-2912,-2913,-2914,-2915,-2917,-2918,
+-2920,-2921,-2923,-2924,-2926,-2927,-2929,-2930,-2931,-2932,-2933,-2934,-2935,-2935,-2936,-2936,-2936,-2936,-2935,-2934,-2933,
+-2932,-2931,-2929,-2927,-2925,-2923,-2921,-2918,-2915,-2912,-2909,-2905,-2902,-2898,-2894,-2890,-2886,-2882,-2878,-2873,-2869,
+-2865,-2861,-2857,-2853,-2849,-2845,-2841,-2837,-2834,-2830,-2827,-2824,-2821,-2818,-2816,-2814,-2812,-2810,-2809,-2808,-2807,
+-2806,-2806,-2806,-2806,-2806,-2807,-2808,-2809,-2810,-2812,-2813,-2815,-2817,-2819,-2822,-2824,-2827,-2829,-2832,-2835,-2838,
+-2841,-2843,-2846,-2849,-2852,-2854,-2857,-2859,-2862,-2864,-2866,-2867,-2869,-2871,-2872,-2873,-2873,-2874,-2874,-2874,-2874,
+-2873,-2873,-2871,-2870,-2868,-2866,-2864,-2862,-2859,-2856,-2852,-2849,-2845,-2841,-2836,-2832,-2827,-2822,-2817,-2811,-2806,
+-2800,-2794,-2788,-2782,-2775,-2769,-2762,-2755,-2749,-2742,-2735,-2728,-2721,-2714,-2707,-2700,-2693,-2686,-2679,-2672,-2665,
+-2658,-2651,-2644,-2637,-2631,-2624,-2617,-2611,-2604,-2598,-2592,-2586,-2579,-2573,-2567,-2562,-2556,-2550,-2544,-2539,-2533,
+-2528,-2523,-2518,-2512,-2507,-2503,-2498,-2493,-2488,-2484,-2479,-2475,-2471,-2467,-2462,-2458,-2455,-2451,-2447,-2444,-2440,
+-2437,-2434,-2431,-2428,-2426,-2423,-2421,-2419,-2416,-2415,-2413,-2411,-2410,-2409,-2408,-2407,-2407,-2406,-2406,-2406,-2407,
+-2407,-2408,-2409,-2410,-2412,-2414,-2416,-2418,-2420,-2423,-2426,-2429,-2432,-2436,-2439,-2443,-2447,-2452,-2456,-2461,-2466,
+-2471,-2476,-2481,-2487,-2492,-2498,-2503,-2509,-2515,-2521,-2526,-2532,-2538,-2544,-2550,-2555,-2561,-2566,-2572,-2577,-2582,
+-2587,-2592,-2596,-2601,-2605,-2609,-2612,-2615,-2618,-2621,-2623,-2625,-2627,-2628,-2629,-2630,-2630,-2630,-2629,-2628,-2627,
+-2625,-2623,-2621,-2618,-2614,-2611,-2607,-2602,-2597,-2592,-2587,-2581,-2575,-2568,-2561,-2554,-2547,-2540,-2532,-2524,-2516,
+-2507,-2499,-2490,-2481,-2472,-2463,-2454,-2445,-2436,-2427,-2418,-2409,-2400,-2391,-2382,-2373,-2365,-2356,-2348,-2340,-2332,
+-2324,-2317,-2309,-2302,-2295,-2288,-2282,-2276,-2270,-2264,-2258,-2253,-2248,-2243,-2239,-2235,-2231,-2227,-2223,-2220,-2217,
+-2214,-2211,-2209,-2206,-2204,-2202,-2201,-2199,-2198,-2196,-2195,-2194,-2193,-2192,-2191,-2191,-2190,-2190,-2189,-2189,-2188,
+-2188,-2188,-2187,-2187,-2187,-2187,-2187,-2186,-2186,-2186,-2186,-2186,-2185,-2185,-2185,-2185,-2185,-2185,-2184,-2184,-2184,
+-2184,-2183,-2183,-2183,-2183,-2183,-2183,-2182,-2182,-2182,-2182,-2182,-2182,-2182,-2182,-2182,-2182,-2182,-2182,-2182,-2182,
+-2182,-2183,-2183,-2183,-2184,-2184,-2184,-2185,-2185,-2186,-2186,-2187,-2187,-2188,-2188,-2189,-2190,-2190,-2191,-2192,-2192,
+-2193,-2194,-2194,-2195,-2196,-2196,-2197,-2198,-2198,-2199,-2200,-2200,-2201,-2201,-2202,-2202,-2203,-2203,-2204,-2204,-2204,
+-2204,-2205,-2205,-2205,-2205,-2205,-2205,-2204,-2204,-2204,-2203,-2203,-2202,-2202,-2201,-2200,-2199,-2198,-2197,-2305,-2303,
+-2300,-2298,-2295,-2292,-2290,-2287,-2285,-2282,-2279,-2277,-2274,-2271,-2268,-2266,-2263,-2260,-2257,-2255,-2252,-2249,-2246,
+-2243,-2241,-2238,-2235,-2232,-2229,-2227,-2224,-2221,-2219,-2216,-2213,-2211,-2208,-2205,-2203,-2200,-2198,-2195,-2193,-2191,
+-2188,-2186,-2184,-2181,-2179,-2177,-2175,-2173,-2171,-2169,-2167,-2165,-2164,-2162,-2160,-2158,-2157,-2155,-2154,-2152,-2150,
+-2149,-2147,-2146,-2144,-2143,-2141,-2140,-2139,-2137,-2135,-2134,-2132,-2131,-2129,-2128,-2126,-2124,-2122,-2120,-2118,-2117,
+-2114,-2112,-2110,-2108,-2106,-2103,-2101,-2098,-2095,-2093,-2090,-2087,-2084,-2081,-2077,-2074,-2071,-2067,-2064,-2060,-2057,
+-2053,-2049,-2045,-2042,-2038,-2034,-2030,-2026,-2022,-2018,-2014,-2010,-2006,-2002,-1998,-1994,-1990,-1987,-1983,-1979,-1976,
+-1972,-1969,-1965,-1962,-1959,-1956,-1954,-1951,-1948,-1946,-1944,-1942,-1940,-1938,-1937,-1935,-1934,-1933,-1932,-1932,-1931,
+-1931,-1930,-1931,-1931,-1931,-1932,-1933,-1934,-1935,-1936,-1937,-1939,-1940,-1942,-1944,-1946,-1949,-1951,-1953,-1956,-1959,
+-1961,-1964,-1967,-1970,-1973,-1976,-1979,-1982,-1986,-1989,-1992,-1995,-1998,-2002,-2005,-2008,-2012,-2015,-2018,-2021,-2025,
+-2028,-2031,-2034,-2037,-2040,-2043,-2046,-2049,-2052,-2055,-2058,-2060,-2063,-2066,-2069,-2071,-2074,-2076,-2079,-2081,-2084,
+-2086,-2089,-2091,-2094,-2096,-2099,-2101,-2103,-2106,-2108,-2110,-2113,-2115,-2118,-2120,-2122,-2125,-2127,-2130,-2132,-2134,
+-2137,-2139,-2142,-2144,-2147,-2149,-2152,-2154,-2157,-2159,-2162,-2164,-2166,-2169,-2171,-2174,-2176,-2179,-2181,-2183,-2186,
+-2188,-2190,-2193,-2195,-2197,-2199,-2201,-2204,-2206,-2208,-2210,-2212,-2214,-2215,-2217,-2219,-2221,-2223,-2224,-2226,-2228,
+-2229,-2231,-2233,-2234,-2236,-2237,-2239,-2240,-2242,-2243,-2245,-2247,-2248,-2250,-2251,-2253,-2254,-2256,-2258,-2259,-2261,
+-2263,-2265,-2267,-2269,-2271,-2273,-2275,-2277,-2279,-2282,-2284,-2287,-2289,-2292,-2295,-2298,-2300,-2303,-2307,-2310,-2313,
+-2316,-2320,-2323,-2327,-2330,-2334,-2338,-2342,-2346,-2350,-2354,-2358,-2362,-2367,-2371,-2375,-2380,-2384,-2389,-2393,-2398,
+-2403,-2407,-2412,-2417,-2421,-2426,-2431,-2436,-2441,-2445,-2450,-2455,-2460,-2465,-2470,-2474,-2479,-2484,-2489,-2494,-2498,
+-2503,-2508,-2513,-2517,-2522,-2527,-2532,-2536,-2541,-2546,-2550,-2555,-2559,-2564,-2569,-2573,-2578,-2583,-2587,-2592,-2596,
+-2601,-2606,-2610,-2615,-2619,-2624,-2629,-2633,-2638,-2643,-2648,-2652,-2657,-2662,-2667,-2671,-2676,-2681,-2686,-2691,-2696,
+-2701,-2706,-2711,-2716,-2721,-2726,-2731,-2736,-2741,-2746,-2751,-2756,-2761,-2766,-2772,-2777,-2782,-2787,-2792,-2797,-2802,
+-2807,-2812,-2817,-2822,-2827,-2832,-2837,-2842,-2847,-2852,-2857,-2862,-2867,-2871,-2876,-2881,-2885,-2890,-2894,-2899,-2903,
+-2908,-2912,-2916,-2920,-2925,-2929,-2933,-2937,-2941,-2945,-2949,-2952,-2956,-2960,-2963,-2967,-2971,-2974,-2978,-2981,-2984,
+-2988,-2991,-2994,-2997,-3000,-3003,-3006,-3009,-3012,-3015,-3018,-3021,-3023,-3026,-3029,-3031,-3034,-3037,-3039,-3042,-3044,
+-3047,-3049,-3051,-3054,-3056,-3058,-3061,-3063,-3065,-3067,-3070,-3072,-3074,-3076,-3078,-3081,-3083,-3085,-3087,-3089,-3091,
+-3093,-3095,-3097,-3099,-3101,-3103,-3106,-3108,-3110,-3112,-3114,-3116,-3118,-3120,-3122,-3124,-3126,-3128,-3130,-3132,-3134,
+-3136,-3138,-3140,-3142,-3144,-3146,-3148,-3150,-3152,-3154,-3156,-3158,-3161,-3163,-3165,-3167,-3169,-3171,-3173,-3175,-3177,
+-3179,-3182,-3184,-3186,-3188,-3190,-3192,-3194,-3196,-3198,-3200,-3202,-3204,-3206,-3208,-3210,-3212,-3214,-3216,-3218,-3220,
+-3222,-3224,-3226,-3227,-3229,-3231,-3232,-3234,-3236,-3237,-3239,-3240,-3242,-3243,-3244,-3246,-3247,-3248,-3249,-3251,-3252,
+-3253,-3254,-3254,-3255,-3256,-3257,-3258,-3259,-3259,-3260,-3261,-3261,-3262,-3262,-3263,-3263,-3264,-3264,-3264,-3265,-3265,
+-3265,-3266,-3266,-3266,-3267,-3267,-3267,-3267,-3268,-3268,-3268,-3269,-3269,-3269,-3270,-3270,-3270,-3271,-3271,-3271,-3272,
+-3272,-3273,-3273,-3274,-3275,-3275,-3276,-3276,-3277,-3278,-3278,-3279,-3280,-3280,-3281,-3282,-3282,-3283,-3284,-3284,-3285,
+-3286,-3286,-3287,-3287,-3288,-3288,-3289,-3289,-3289,-3289,-3290,-3290,-3290,-3290,-3289,-3289,-3289,-3288,-3288,-3287,-3286,
+-3286,-3285,-3284,-3283,-3281,-3280,-3279,-3277,-3275,-3274,-3272,-3270,-3268,-3265,-3263,-3261,-3259,-3256,-3253,-3251,-3248,
+-3245,-3242,-3239,-3236,-3233,-3230,-3227,-3224,-3221,-3218,-3215,-3211,-3208,-3205,-3202,-3198,-3195,-3192,-3189,-3186,-3183,
+-3180,-3177,-3173,-3170,-3168,-3165,-3162,-3159,-3156,-3153,-3151,-3148,-3145,-3143,-3140,-3137,-3135,-3132,-3130,-3127,-3125,
+-3122,-3120,-3118,-3115,-3113,-3110,-3108,-3105,-3103,-3101,-3098,-3096,-3093,-3090,-3088,-3085,-3083,-3080,-3077,-3074,-3072,
+-3069,-3066,-3063,-3060,-3057,-3055,-3052,-3049,-3046,-3043,-3040,-3037,-3034,-3031,-3028,-3025,-3022,-3020,-3017,-3014,-3012,
+-3009,-3006,-3004,-3002,-3000,-2998,-2996,-2994,-2992,-2990,-2989,-2988,-2986,-2985,-2984,-2984,-2983,-2983,-2982,-2982,-2982,
+-2983,-2983,-2984,-2984,-2985,-2986,-2987,-2989,-2990,-2992,-2994,-2996,-2998,-3000,-3002,-3004,-3007,-3009,-3012,-3014,-3017,
+-3020,-3023,-3026,-3028,-3031,-3034,-3037,-3040,-3043,-3045,-3048,-3051,-3054,-3056,-3059,-3061,-3064,-3066,-3068,-3070,-3072,
+-3074,-3076,-3078,-3079,-3081,-3082,-3084,-3085,-3086,-3087,-3088,-3089,-3090,-3090,-3091,-3091,-3092,-3092,-3092,-3093,-3093,
+-3093,-3093,-3093,-3093,-3093,-3093,-3093,-3092,-3092,-3092,-3092,-3092,-3092,-3092,-3092,-3091,-3091,-3091,-3091,-3091,-3091,
+-3091,-3091,-3091,-3091,-3091,-3091,-3091,-3091,-3091,-3091,-3091,-3091,-3091,-3091,-3091,-3091,-3091,-3091,-3090,-3090,-3089,
+-3089,-3088,-3087,-3087,-3086,-3085,-3083,-3082,-3081,-3079,-3078,-3076,-3074,-3072,-3069,-3067,-3065,-3062,-3059,-3056,-3053,
+-3050,-3047,-3043,-3040,-3036,-3032,-3028,-3024,-3020,-3016,-3012,-3008,-3003,-2999,-2995,-2990,-2986,-2981,-2977,-2972,-2968,
+-2964,-2959,-2955,-2951,-2947,-2943,-2939,-2935,-2931,-2928,-2924,-2921,-2917,-2914,-2911,-2908,-2906,-2903,-2900,-2898,-2896,
+-2894,-2892,-2890,-2888,-2887,-2885,-2884,-2883,-2882,-2881,-2880,-2879,-2878,-2878,-2877,-2876,-2876,-2875,-2875,-2874,-2874,
+-2873,-2873,-2873,-2872,-2872,-2871,-2871,-2870,-2869,-2869,-2868,-2867,-2866,-2865,-2864,-2863,-2862,-2861,-2859,-2858,-2857,
+-2855,-2854,-2852,-2850,-2849,-2847,-2845,-2843,-2841,-2839,-2837,-2836,-2834,-2832,-2830,-2828,-2826,-2824,-2822,-2820,-2818,
+-2817,-2815,-2813,-2812,-2810,-2809,-2808,-2806,-2805,-2804,-2803,-2802,-2801,-2800,-2800,-2799,-2798,-2798,-2798,-2797,-2797,
+-2797,-2797,-2796,-2796,-2796,-2796,-2796,-2796,-2796,-2796,-2796,-2796,-2796,-2796,-2796,-2796,-2796,-2795,-2795,-2795,-2794,
+-2793,-2793,-2792,-2791,-2790,-2789,-2787,-2786,-2784,-2782,-2780,-2778,-2776,-2774,-2772,-2769,-2766,-2763,-2760,-2757,-2754,
+-2750,-2747,-2743,-2739,-2735,-2731,-2727,-2723,-2719,-2714,-2710,-2705,-2701,-2696,-2691,-2687,-2682,-2677,-2672,-2667,-2663,
+-2658,-2653,-2648,-2643,-2639,-2634,-2629,-2625,-2620,-2616,-2611,-2607,-2603,-2598,-2594,-2590,-2586,-2582,-2578,-2574,-2571,
+-2567,-2563,-2560,-2557,-2553,-2550,-2547,-2544,-2541,-2538,-2535,-2532,-2529,-2527,-2524,-2522,-2519,-2517,-2515,-2512,-2510,
+-2508,-2506,-2504,-2502,-2500,-2498,-2496,-2494,-2492,-2491,-2489,-2487,-2486,-2484,-2483,-2482,-2480,-2479,-2478,-2477,-2476,
+-2475,-2474,-2473,-2473,-2472,-2471,-2471,-2471,-2471,-2471,-2471,-2471,-2471,-2471,-2472,-2472,-2473,-2474,-2475,-2476,-2477,
+-2479,-2480,-2482,-2484,-2486,-2488,-2490,-2492,-2494,-2497,-2500,-2502,-2505,-2508,-2511,-2514,-2517,-2520,-2523,-2527,-2530,
+-2533,-2537,-2540,-2543,-2547,-2550,-2553,-2557,-2560,-2563,-2566,-2569,-2572,-2575,-2577,-2580,-2582,-2584,-2586,-2588,-2590,
+-2592,-2593,-2594,-2595,-2595,-2596,-2596,-2596,-2596,-2595,-2595,-2593,-2592,-2591,-2589,-2587,-2585,-2582,-2579,-2576,-2573,
+-2569,-2566,-2562,-2557,-2553,-2548,-2544,-2539,-2533,-2528,-2522,-2517,-2511,-2505,-2499,-2493,-2487,-2481,-2474,-2468,-2462,
+-2455,-2449,-2442,-2436,-2430,-2423,-2417,-2411,-2405,-2399,-2393,-2387,-2381,-2376,-2370,-2365,-2360,-2355,-2350,-2345,-2341,
+-2337,-2333,-2329,-2325,-2322,-2319,-2316,-2313,-2310,-2308,-2306,-2304,-2302,-2300,-2299,-2298,-2297,-2296,-2295,-2295,-2294,
+-2294,-2294,-2295,-2295,-2295,-2296,-2297,-2298,-2299,-2300,-2301,-2302,-2304,-2305,-2307,-2309,-2310,-2312,-2314,-2316,-2318,
+-2319,-2321,-2323,-2325,-2327,-2329,-2331,-2333,-2335,-2337,-2339,-2341,-2343,-2345,-2347,-2349,-2350,-2352,-2354,-2355,-2357,
+-2359,-2360,-2362,-2363,-2364,-2365,-2367,-2368,-2369,-2370,-2371,-2372,-2372,-2373,-2374,-2374,-2375,-2375,-2376,-2376,-2376,
+-2376,-2376,-2376,-2376,-2376,-2376,-2376,-2375,-2375,-2375,-2374,-2373,-2373,-2372,-2371,-2370,-2370,-2369,-2368,-2367,-2365,
+-2364,-2363,-2362,-2360,-2359,-2357,-2356,-2354,-2353,-2351,-2349,-2348,-2346,-2344,-2342,-2340,-2338,-2336,-2334,-2332,-2330,
+-2328,-2326,-2324,-2322,-2319,-2317,-2315,-2312,-2310,-2308,-2305,-2381,-2378,-2375,-2371,-2368,-2365,-2362,-2359,-2356,-2353,
+-2350,-2347,-2344,-2341,-2338,-2336,-2333,-2330,-2327,-2325,-2322,-2320,-2317,-2315,-2312,-2310,-2307,-2305,-2303,-2301,-2299,
+-2296,-2294,-2292,-2290,-2288,-2286,-2284,-2283,-2281,-2279,-2277,-2276,-2274,-2272,-2271,-2269,-2267,-2266,-2264,-2263,-2261,
+-2260,-2258,-2257,-2255,-2254,-2252,-2251,-2249,-2248,-2246,-2245,-2243,-2242,-2240,-2239,-2237,-2235,-2234,-2232,-2230,-2228,
+-2227,-2225,-2223,-2221,-2219,-2217,-2215,-2213,-2210,-2208,-2206,-2203,-2201,-2198,-2196,-2193,-2191,-2188,-2185,-2182,-2179,
+-2176,-2173,-2170,-2167,-2164,-2161,-2158,-2154,-2151,-2148,-2144,-2141,-2138,-2134,-2131,-2127,-2124,-2120,-2117,-2113,-2110,
+-2106,-2103,-2100,-2096,-2093,-2090,-2086,-2083,-2080,-2077,-2074,-2071,-2069,-2066,-2063,-2061,-2058,-2056,-2054,-2052,-2050,
+-2048,-2046,-2044,-2043,-2042,-2040,-2039,-2038,-2038,-2037,-2036,-2036,-2036,-2036,-2036,-2036,-2036,-2037,-2037,-2038,-2039,
+-2040,-2041,-2042,-2044,-2045,-2047,-2049,-2051,-2053,-2055,-2057,-2059,-2062,-2064,-2067,-2070,-2072,-2075,-2078,-2081,-2084,
+-2087,-2090,-2094,-2097,-2100,-2103,-2107,-2110,-2114,-2117,-2121,-2124,-2127,-2131,-2134,-2138,-2141,-2145,-2148,-2152,-2155,
+-2159,-2162,-2166,-2169,-2172,-2176,-2179,-2182,-2186,-2189,-2192,-2195,-2198,-2202,-2205,-2208,-2211,-2214,-2217,-2220,-2222,
+-2225,-2228,-2231,-2234,-2236,-2239,-2242,-2244,-2247,-2249,-2252,-2254,-2256,-2259,-2261,-2263,-2265,-2268,-2270,-2272,-2274,
+-2276,-2278,-2280,-2282,-2283,-2285,-2287,-2289,-2290,-2292,-2293,-2295,-2296,-2298,-2299,-2300,-2302,-2303,-2304,-2305,-2307,
+-2308,-2309,-2310,-2311,-2312,-2313,-2314,-2315,-2316,-2317,-2317,-2318,-2319,-2320,-2321,-2322,-2323,-2323,-2324,-2325,-2326,
+-2327,-2328,-2329,-2330,-2331,-2332,-2333,-2334,-2335,-2336,-2338,-2339,-2340,-2342,-2343,-2345,-2346,-2348,-2350,-2352,-2354,
+-2355,-2357,-2360,-2362,-2364,-2366,-2369,-2371,-2374,-2376,-2379,-2382,-2385,-2388,-2391,-2394,-2397,-2400,-2404,-2407,-2411,
+-2414,-2418,-2421,-2425,-2429,-2433,-2437,-2441,-2445,-2449,-2453,-2457,-2461,-2465,-2469,-2474,-2478,-2482,-2487,-2491,-2495,
+-2500,-2504,-2509,-2513,-2517,-2522,-2526,-2531,-2535,-2540,-2544,-2549,-2553,-2557,-2562,-2566,-2571,-2575,-2579,-2584,-2588,
+-2592,-2597,-2601,-2605,-2610,-2614,-2618,-2622,-2627,-2631,-2635,-2639,-2643,-2648,-2652,-2656,-2660,-2664,-2669,-2673,-2677,
+-2681,-2685,-2689,-2694,-2698,-2702,-2706,-2710,-2714,-2719,-2723,-2727,-2731,-2735,-2739,-2744,-2748,-2752,-2756,-2760,-2764,
+-2769,-2773,-2777,-2781,-2785,-2789,-2794,-2798,-2802,-2806,-2810,-2814,-2818,-2822,-2827,-2831,-2835,-2839,-2843,-2847,-2851,
+-2855,-2859,-2862,-2866,-2870,-2874,-2878,-2882,-2885,-2889,-2893,-2896,-2900,-2903,-2907,-2910,-2914,-2917,-2921,-2924,-2927,
+-2931,-2934,-2937,-2940,-2943,-2946,-2949,-2952,-2955,-2958,-2961,-2964,-2967,-2970,-2972,-2975,-2978,-2980,-2983,-2985,-2988,
+-2990,-2993,-2995,-2998,-3000,-3002,-3005,-3007,-3009,-3011,-3013,-3016,-3018,-3020,-3022,-3024,-3026,-3028,-3030,-3032,-3034,
+-3036,-3038,-3040,-3042,-3044,-3046,-3048,-3050,-3051,-3053,-3055,-3057,-3059,-3061,-3062,-3064,-3066,-3068,-3070,-3071,-3073,
+-3075,-3077,-3079,-3080,-3082,-3084,-3086,-3087,-3089,-3091,-3093,-3095,-3096,-3098,-3100,-3102,-3103,-3105,-3107,-3109,-3111,
+-3112,-3114,-3116,-3118,-3120,-3121,-3123,-3125,-3127,-3129,-3130,-3132,-3134,-3136,-3138,-3139,-3141,-3143,-3145,-3146,-3148,
+-3150,-3152,-3153,-3155,-3157,-3159,-3160,-3162,-3164,-3165,-3167,-3169,-3170,-3172,-3174,-3175,-3177,-3178,-3180,-3181,-3183,
+-3184,-3186,-3187,-3189,-3190,-3191,-3193,-3194,-3195,-3197,-3198,-3199,-3201,-3202,-3203,-3204,-3205,-3206,-3207,-3209,-3210,
+-3211,-3212,-3213,-3214,-3215,-3216,-3217,-3218,-3219,-3219,-3220,-3221,-3222,-3223,-3224,-3225,-3226,-3227,-3228,-3228,-3229,
+-3230,-3231,-3232,-3233,-3233,-3234,-3235,-3236,-3237,-3238,-3239,-3239,-3240,-3241,-3242,-3243,-3244,-3244,-3245,-3246,-3247,
+-3247,-3248,-3249,-3250,-3250,-3251,-3251,-3252,-3253,-3253,-3254,-3254,-3254,-3255,-3255,-3255,-3255,-3256,-3256,-3256,-3256,
+-3255,-3255,-3255,-3255,-3254,-3254,-3253,-3253,-3252,-3251,-3250,-3249,-3248,-3247,-3245,-3244,-3243,-3241,-3239,-3238,-3236,
+-3234,-3232,-3230,-3228,-3225,-3223,-3221,-3218,-3215,-3213,-3210,-3207,-3204,-3201,-3198,-3195,-3192,-3188,-3185,-3182,-3178,
+-3175,-3171,-3168,-3164,-3160,-3157,-3153,-3149,-3145,-3142,-3138,-3134,-3130,-3126,-3122,-3118,-3114,-3110,-3107,-3103,-3099,
+-3095,-3091,-3087,-3083,-3079,-3075,-3071,-3067,-3063,-3059,-3055,-3051,-3047,-3043,-3039,-3035,-3031,-3027,-3023,-3019,-3015,
+-3011,-3007,-3003,-2999,-2995,-2991,-2987,-2983,-2979,-2975,-2971,-2967,-2963,-2959,-2955,-2952,-2948,-2944,-2940,-2936,-2933,
+-2929,-2925,-2922,-2918,-2915,-2911,-2908,-2904,-2901,-2898,-2895,-2892,-2889,-2886,-2883,-2881,-2878,-2876,-2873,-2871,-2869,
+-2867,-2865,-2863,-2862,-2860,-2859,-2858,-2857,-2856,-2855,-2855,-2854,-2854,-2854,-2854,-2854,-2855,-2855,-2856,-2857,-2858,
+-2859,-2860,-2862,-2863,-2865,-2867,-2869,-2871,-2873,-2875,-2878,-2881,-2883,-2886,-2889,-2892,-2895,-2898,-2902,-2905,-2908,
+-2912,-2915,-2919,-2922,-2926,-2930,-2933,-2937,-2941,-2945,-2948,-2952,-2956,-2960,-2963,-2967,-2971,-2974,-2978,-2982,-2985,
+-2989,-2992,-2996,-2999,-3003,-3006,-3009,-3012,-3015,-3018,-3021,-3024,-3027,-3030,-3033,-3035,-3038,-3041,-3043,-3045,-3048,
+-3050,-3052,-3054,-3056,-3058,-3060,-3061,-3063,-3064,-3066,-3067,-3068,-3070,-3071,-3072,-3073,-3073,-3074,-3075,-3075,-3076,
+-3076,-3076,-3076,-3076,-3076,-3076,-3076,-3075,-3075,-3074,-3073,-3072,-3071,-3070,-3069,-3068,-3066,-3064,-3063,-3061,-3059,
+-3057,-3055,-3052,-3050,-3047,-3045,-3042,-3039,-3036,-3033,-3030,-3027,-3024,-3020,-3017,-3013,-3009,-3006,-3002,-2998,-2994,
+-2990,-2986,-2982,-2978,-2974,-2970,-2966,-2962,-2957,-2953,-2949,-2945,-2941,-2937,-2933,-2929,-2925,-2921,-2917,-2913,-2909,
+-2905,-2902,-2898,-2895,-2891,-2888,-2885,-2881,-2878,-2875,-2872,-2869,-2867,-2864,-2861,-2859,-2856,-2854,-2852,-2850,-2848,
+-2846,-2844,-2842,-2840,-2839,-2837,-2836,-2834,-2833,-2832,-2830,-2829,-2828,-2827,-2826,-2825,-2824,-2823,-2823,-2822,-2821,
+-2820,-2820,-2819,-2818,-2818,-2817,-2817,-2816,-2815,-2815,-2814,-2814,-2813,-2813,-2812,-2812,-2811,-2811,-2810,-2810,-2809,
+-2808,-2808,-2807,-2807,-2806,-2806,-2805,-2805,-2804,-2804,-2803,-2803,-2802,-2802,-2801,-2801,-2800,-2800,-2799,-2799,-2798,
+-2798,-2797,-2797,-2796,-2795,-2795,-2794,-2794,-2793,-2792,-2792,-2791,-2790,-2789,-2789,-2788,-2787,-2786,-2785,-2784,-2783,
+-2782,-2781,-2779,-2778,-2777,-2775,-2774,-2772,-2771,-2769,-2767,-2765,-2763,-2761,-2759,-2757,-2755,-2752,-2750,-2747,-2745,
+-2742,-2739,-2736,-2733,-2730,-2727,-2724,-2721,-2718,-2714,-2711,-2707,-2704,-2700,-2696,-2693,-2689,-2685,-2681,-2677,-2674,
+-2670,-2666,-2662,-2658,-2654,-2650,-2646,-2642,-2639,-2635,-2631,-2627,-2624,-2620,-2616,-2613,-2609,-2606,-2602,-2599,-2596,
+-2592,-2589,-2586,-2583,-2580,-2577,-2575,-2572,-2569,-2567,-2564,-2562,-2560,-2558,-2556,-2553,-2552,-2550,-2548,-2546,-2544,
+-2543,-2541,-2540,-2538,-2537,-2536,-2535,-2534,-2532,-2531,-2530,-2529,-2529,-2528,-2527,-2526,-2525,-2525,-2524,-2524,-2523,
+-2523,-2522,-2522,-2521,-2521,-2520,-2520,-2520,-2520,-2519,-2519,-2519,-2519,-2519,-2519,-2519,-2519,-2519,-2519,-2520,-2520,
+-2520,-2520,-2521,-2521,-2522,-2522,-2523,-2524,-2524,-2525,-2526,-2527,-2528,-2529,-2530,-2531,-2532,-2533,-2535,-2536,-2537,
+-2539,-2540,-2542,-2543,-2545,-2546,-2548,-2550,-2551,-2553,-2555,-2557,-2558,-2560,-2562,-2563,-2565,-2567,-2569,-2570,-2572,
+-2573,-2575,-2576,-2578,-2579,-2580,-2581,-2582,-2583,-2584,-2585,-2586,-2586,-2587,-2587,-2587,-2587,-2587,-2587,-2587,-2586,
+-2585,-2585,-2584,-2582,-2581,-2580,-2578,-2576,-2574,-2572,-2570,-2568,-2565,-2562,-2560,-2557,-2554,-2550,-2547,-2543,-2540,
+-2536,-2532,-2528,-2524,-2520,-2516,-2511,-2507,-2503,-2498,-2494,-2489,-2485,-2480,-2475,-2471,-2466,-2462,-2457,-2452,-2448,
+-2443,-2439,-2435,-2430,-2426,-2422,-2418,-2414,-2411,-2407,-2403,-2400,-2397,-2394,-2391,-2388,-2385,-2383,-2380,-2378,-2376,
+-2374,-2372,-2371,-2369,-2368,-2367,-2366,-2366,-2365,-2365,-2365,-2365,-2365,-2365,-2365,-2366,-2367,-2368,-2369,-2370,-2371,
+-2373,-2375,-2376,-2378,-2380,-2382,-2384,-2387,-2389,-2391,-2394,-2397,-2399,-2402,-2405,-2408,-2410,-2413,-2416,-2419,-2422,
+-2425,-2428,-2431,-2434,-2437,-2439,-2442,-2445,-2448,-2450,-2453,-2456,-2458,-2461,-2463,-2465,-2468,-2470,-2472,-2474,-2476,
+-2478,-2479,-2481,-2482,-2484,-2485,-2486,-2487,-2488,-2489,-2490,-2490,-2491,-2491,-2491,-2491,-2491,-2491,-2491,-2490,-2490,
+-2489,-2488,-2487,-2486,-2485,-2484,-2483,-2481,-2480,-2478,-2476,-2475,-2473,-2471,-2468,-2466,-2464,-2462,-2459,-2457,-2454,
+-2452,-2449,-2446,-2443,-2440,-2438,-2435,-2432,-2429,-2425,-2422,-2419,-2416,-2413,-2410,-2407,-2403,-2400,-2397,-2394,-2391,
+-2387,-2384,-2381,-2424,-2421,-2418,-2415,-2413,-2410,-2407,-2404,-2401,-2398,-2396,-2393,-2390,-2388,-2385,-2383,-2380,-2378,
+-2375,-2373,-2371,-2368,-2366,-2364,-2362,-2359,-2357,-2355,-2353,-2351,-2349,-2348,-2346,-2344,-2342,-2340,-2339,-2337,-2335,
+-2334,-2332,-2331,-2329,-2328,-2326,-2325,-2323,-2322,-2320,-2319,-2317,-2316,-2314,-2313,-2312,-2310,-2309,-2307,-2306,-2304,
+-2303,-2301,-2300,-2298,-2297,-2295,-2293,-2292,-2290,-2288,-2287,-2285,-2283,-2281,-2279,-2277,-2275,-2273,-2271,-2269,-2267,
+-2265,-2263,-2261,-2258,-2256,-2254,-2251,-2249,-2246,-2244,-2241,-2239,-2236,-2234,-2231,-2228,-2226,-2223,-2220,-2218,-2215,
+-2212,-2209,-2207,-2204,-2201,-2198,-2196,-2193,-2190,-2188,-2185,-2182,-2180,-2177,-2174,-2172,-2170,-2167,-2165,-2162,-2160,
+-2158,-2156,-2154,-2152,-2150,-2148,-2146,-2145,-2143,-2141,-2140,-2139,-2137,-2136,-2135,-2134,-2133,-2133,-2132,-2131,-2131,
+-2131,-2130,-2130,-2130,-2130,-2130,-2131,-2131,-2132,-2132,-2133,-2134,-2135,-2136,-2137,-2138,-2140,-2141,-2143,-2144,-2146,
+-2148,-2150,-2152,-2154,-2156,-2158,-2161,-2163,-2166,-2168,-2171,-2173,-2176,-2179,-2182,-2185,-2188,-2191,-2194,-2197,-2200,
+-2203,-2206,-2209,-2212,-2216,-2219,-2222,-2225,-2229,-2232,-2235,-2239,-2242,-2245,-2249,-2252,-2255,-2259,-2262,-2265,-2268,
+-2272,-2275,-2278,-2281,-2284,-2287,-2290,-2293,-2296,-2299,-2302,-2305,-2308,-2311,-2314,-2316,-2319,-2322,-2324,-2327,-2330,
+-2332,-2334,-2337,-2339,-2341,-2344,-2346,-2348,-2350,-2352,-2354,-2356,-2358,-2360,-2362,-2364,-2365,-2367,-2369,-2370,-2372,
+-2373,-2375,-2376,-2378,-2379,-2380,-2382,-2383,-2384,-2385,-2386,-2387,-2388,-2390,-2391,-2392,-2393,-2394,-2395,-2395,-2396,
+-2397,-2398,-2399,-2400,-2401,-2402,-2403,-2404,-2405,-2406,-2406,-2407,-2408,-2409,-2410,-2411,-2413,-2414,-2415,-2416,-2417,
+-2418,-2420,-2421,-2422,-2424,-2425,-2427,-2428,-2430,-2431,-2433,-2435,-2436,-2438,-2440,-2442,-2444,-2446,-2448,-2451,-2453,
+-2455,-2457,-2460,-2462,-2465,-2468,-2470,-2473,-2476,-2478,-2481,-2484,-2487,-2490,-2493,-2496,-2500,-2503,-2506,-2509,-2513,
+-2516,-2519,-2523,-2526,-2530,-2533,-2537,-2541,-2544,-2548,-2551,-2555,-2559,-2563,-2566,-2570,-2574,-2578,-2581,-2585,-2589,
+-2593,-2596,-2600,-2604,-2608,-2612,-2615,-2619,-2623,-2627,-2631,-2634,-2638,-2642,-2646,-2649,-2653,-2657,-2661,-2664,-2668,
+-2672,-2675,-2679,-2683,-2686,-2690,-2693,-2697,-2701,-2704,-2708,-2711,-2715,-2718,-2722,-2726,-2729,-2733,-2736,-2740,-2743,
+-2746,-2750,-2753,-2757,-2760,-2764,-2767,-2771,-2774,-2777,-2781,-2784,-2788,-2791,-2794,-2798,-2801,-2804,-2808,-2811,-2814,
+-2818,-2821,-2824,-2827,-2831,-2834,-2837,-2840,-2843,-2847,-2850,-2853,-2856,-2859,-2862,-2865,-2868,-2871,-2875,-2878,-2881,
+-2884,-2886,-2889,-2892,-2895,-2898,-2901,-2904,-2907,-2909,-2912,-2915,-2918,-2920,-2923,-2926,-2928,-2931,-2933,-2936,-2938,
+-2941,-2943,-2946,-2948,-2951,-2953,-2955,-2958,-2960,-2962,-2965,-2967,-2969,-2971,-2974,-2976,-2978,-2980,-2982,-2984,-2986,
+-2988,-2990,-2992,-2994,-2996,-2998,-3000,-3002,-3004,-3006,-3008,-3010,-3012,-3013,-3015,-3017,-3019,-3021,-3022,-3024,-3026,
+-3028,-3029,-3031,-3033,-3035,-3036,-3038,-3040,-3041,-3043,-3044,-3046,-3048,-3049,-3051,-3053,-3054,-3056,-3057,-3059,-3060,
+-3062,-3064,-3065,-3067,-3068,-3070,-3071,-3073,-3074,-3076,-3077,-3079,-3080,-3082,-3083,-3084,-3086,-3087,-3089,-3090,-3092,
+-3093,-3094,-3096,-3097,-3099,-3100,-3101,-3103,-3104,-3106,-3107,-3108,-3110,-3111,-3112,-3113,-3115,-3116,-3117,-3119,-3120,
+-3121,-3122,-3124,-3125,-3126,-3127,-3129,-3130,-3131,-3132,-3133,-3134,-3136,-3137,-3138,-3139,-3140,-3141,-3142,-3143,-3144,
+-3146,-3147,-3148,-3149,-3150,-3151,-3152,-3153,-3154,-3155,-3156,-3157,-3158,-3159,-3160,-3160,-3161,-3162,-3163,-3164,-3165,
+-3166,-3167,-3168,-3168,-3169,-3170,-3171,-3172,-3172,-3173,-3174,-3175,-3175,-3176,-3177,-3177,-3178,-3179,-3179,-3180,-3180,
+-3181,-3182,-3182,-3183,-3183,-3183,-3184,-3184,-3185,-3185,-3185,-3185,-3186,-3186,-3186,-3186,-3186,-3186,-3186,-3186,-3186,
+-3186,-3186,-3185,-3185,-3185,-3184,-3184,-3183,-3183,-3182,-3181,-3180,-3180,-3179,-3178,-3177,-3176,-3174,-3173,-3172,-3170,
+-3169,-3167,-3166,-3164,-3162,-3161,-3159,-3157,-3155,-3153,-3151,-3148,-3146,-3144,-3141,-3139,-3136,-3134,-3131,-3128,-3125,
+-3123,-3120,-3117,-3114,-3111,-3107,-3104,-3101,-3098,-3094,-3091,-3088,-3084,-3081,-3077,-3074,-3070,-3067,-3063,-3059,-3056,
+-3052,-3048,-3045,-3041,-3037,-3033,-3030,-3026,-3022,-3018,-3014,-3011,-3007,-3003,-2999,-2995,-2991,-2988,-2984,-2980,-2976,
+-2972,-2969,-2965,-2961,-2957,-2954,-2950,-2946,-2943,-2939,-2935,-2932,-2928,-2924,-2921,-2917,-2914,-2910,-2907,-2903,-2900,
+-2896,-2893,-2889,-2886,-2883,-2880,-2876,-2873,-2870,-2867,-2864,-2861,-2858,-2855,-2852,-2850,-2847,-2844,-2842,-2839,-2836,
+-2834,-2832,-2829,-2827,-2825,-2823,-2821,-2819,-2818,-2816,-2814,-2813,-2811,-2810,-2809,-2808,-2807,-2806,-2805,-2804,-2804,
+-2803,-2803,-2803,-2803,-2803,-2803,-2803,-2803,-2804,-2804,-2805,-2806,-2807,-2808,-2809,-2810,-2811,-2813,-2814,-2816,-2818,
+-2820,-2822,-2824,-2826,-2828,-2831,-2833,-2836,-2838,-2841,-2844,-2847,-2849,-2852,-2855,-2859,-2862,-2865,-2868,-2871,-2875,
+-2878,-2882,-2885,-2888,-2892,-2895,-2899,-2902,-2906,-2910,-2913,-2917,-2920,-2924,-2927,-2930,-2934,-2937,-2941,-2944,-2947,
+-2951,-2954,-2957,-2960,-2963,-2966,-2969,-2972,-2975,-2978,-2980,-2983,-2986,-2988,-2990,-2993,-2995,-2997,-2999,-3001,-3003,
+-3005,-3007,-3008,-3010,-3011,-3013,-3014,-3015,-3016,-3017,-3018,-3019,-3019,-3020,-3020,-3021,-3021,-3021,-3021,-3021,-3021,
+-3020,-3020,-3020,-3019,-3018,-3018,-3017,-3016,-3015,-3013,-3012,-3011,-3009,-3008,-3006,-3005,-3003,-3001,-2999,-2997,-2995,
+-2993,-2990,-2988,-2986,-2983,-2981,-2978,-2976,-2973,-2970,-2967,-2965,-2962,-2959,-2956,-2953,-2950,-2947,-2944,-2941,-2938,
+-2935,-2932,-2929,-2926,-2923,-2920,-2917,-2914,-2911,-2908,-2905,-2902,-2899,-2896,-2893,-2890,-2887,-2885,-2882,-2879,-2877,
+-2874,-2872,-2869,-2867,-2864,-2862,-2860,-2857,-2855,-2853,-2851,-2849,-2847,-2845,-2843,-2842,-2840,-2838,-2837,-2835,-2834,
+-2832,-2831,-2830,-2829,-2827,-2826,-2825,-2824,-2823,-2822,-2821,-2820,-2820,-2819,-2818,-2818,-2817,-2816,-2816,-2815,-2815,
+-2814,-2814,-2814,-2813,-2813,-2813,-2812,-2812,-2812,-2812,-2811,-2811,-2811,-2811,-2811,-2811,-2811,-2811,-2811,-2810,-2810,
+-2810,-2810,-2810,-2810,-2810,-2810,-2810,-2810,-2809,-2809,-2809,-2809,-2809,-2809,-2808,-2808,-2808,-2807,-2807,-2807,-2806,
+-2806,-2805,-2805,-2804,-2803,-2803,-2802,-2801,-2800,-2799,-2798,-2797,-2796,-2795,-2794,-2793,-2791,-2790,-2788,-2787,-2785,
+-2784,-2782,-2780,-2778,-2776,-2774,-2772,-2770,-2768,-2766,-2763,-2761,-2758,-2756,-2753,-2751,-2748,-2745,-2743,-2740,-2737,
+-2734,-2731,-2728,-2725,-2722,-2719,-2715,-2712,-2709,-2706,-2703,-2699,-2696,-2693,-2689,-2686,-2683,-2680,-2676,-2673,-2670,
+-2666,-2663,-2660,-2657,-2654,-2651,-2647,-2644,-2641,-2638,-2636,-2633,-2630,-2627,-2624,-2622,-2619,-2616,-2614,-2611,-2609,
+-2607,-2604,-2602,-2600,-2598,-2596,-2594,-2592,-2590,-2588,-2587,-2585,-2583,-2582,-2580,-2579,-2578,-2576,-2575,-2574,-2573,
+-2572,-2571,-2570,-2569,-2568,-2567,-2567,-2566,-2565,-2565,-2564,-2564,-2563,-2563,-2563,-2563,-2562,-2562,-2562,-2562,-2562,
+-2562,-2562,-2562,-2562,-2562,-2562,-2563,-2563,-2563,-2564,-2564,-2564,-2565,-2565,-2566,-2566,-2567,-2568,-2568,-2569,-2570,
+-2571,-2572,-2572,-2573,-2574,-2575,-2576,-2577,-2578,-2579,-2580,-2581,-2582,-2584,-2585,-2586,-2587,-2588,-2589,-2590,-2592,
+-2593,-2594,-2595,-2596,-2597,-2598,-2599,-2600,-2601,-2602,-2603,-2604,-2605,-2606,-2606,-2607,-2608,-2608,-2609,-2609,-2610,
+-2610,-2610,-2610,-2610,-2610,-2610,-2610,-2609,-2609,-2608,-2608,-2607,-2606,-2605,-2604,-2603,-2601,-2600,-2599,-2597,-2595,
+-2593,-2591,-2589,-2587,-2585,-2582,-2580,-2577,-2575,-2572,-2569,-2566,-2563,-2560,-2556,-2553,-2550,-2546,-2543,-2539,-2536,
+-2532,-2528,-2525,-2521,-2517,-2513,-2509,-2505,-2502,-2498,-2494,-2490,-2486,-2483,-2479,-2475,-2472,-2468,-2464,-2461,-2458,
+-2454,-2451,-2448,-2445,-2442,-2439,-2436,-2433,-2431,-2428,-2426,-2424,-2422,-2420,-2418,-2416,-2415,-2413,-2412,-2411,-2410,
+-2409,-2408,-2408,-2407,-2407,-2407,-2407,-2407,-2407,-2407,-2408,-2408,-2409,-2410,-2411,-2412,-2413,-2415,-2416,-2418,-2419,
+-2421,-2423,-2425,-2427,-2429,-2431,-2434,-2436,-2438,-2441,-2443,-2445,-2448,-2451,-2453,-2456,-2458,-2461,-2464,-2466,-2469,
+-2471,-2474,-2476,-2479,-2481,-2484,-2486,-2488,-2491,-2493,-2495,-2497,-2499,-2501,-2503,-2505,-2506,-2508,-2509,-2511,-2512,
+-2513,-2514,-2515,-2516,-2517,-2517,-2518,-2518,-2519,-2519,-2519,-2519,-2519,-2518,-2518,-2517,-2517,-2516,-2515,-2514,-2513,
+-2512,-2511,-2509,-2508,-2506,-2505,-2503,-2501,-2499,-2497,-2495,-2493,-2491,-2488,-2486,-2484,-2481,-2479,-2476,-2473,-2471,
+-2468,-2465,-2462,-2459,-2457,-2454,-2451,-2448,-2445,-2442,-2439,-2436,-2433,-2430,-2427,-2424,-2489,-2487,-2485,-2483,-2481,
+-2479,-2477,-2476,-2474,-2472,-2470,-2468,-2466,-2464,-2462,-2460,-2459,-2457,-2455,-2453,-2452,-2450,-2448,-2447,-2445,-2443,
+-2442,-2440,-2439,-2437,-2436,-2434,-2433,-2431,-2430,-2428,-2427,-2425,-2424,-2423,-2421,-2420,-2419,-2417,-2416,-2415,-2413,
+-2412,-2411,-2409,-2408,-2407,-2406,-2404,-2403,-2402,-2400,-2399,-2398,-2396,-2395,-2393,-2392,-2391,-2389,-2388,-2386,-2385,
+-2383,-2382,-2380,-2379,-2377,-2376,-2374,-2372,-2371,-2369,-2367,-2366,-2364,-2362,-2360,-2359,-2357,-2355,-2353,-2351,-2349,
+-2347,-2345,-2344,-2342,-2340,-2338,-2336,-2334,-2332,-2330,-2328,-2326,-2324,-2322,-2320,-2318,-2316,-2314,-2312,-2310,-2308,
+-2306,-2304,-2302,-2301,-2299,-2297,-2295,-2293,-2292,-2290,-2289,-2287,-2285,-2284,-2283,-2281,-2280,-2279,-2277,-2276,-2275,
+-2274,-2273,-2272,-2271,-2271,-2270,-2269,-2269,-2268,-2268,-2267,-2267,-2267,-2267,-2266,-2266,-2267,-2267,-2267,-2267,-2267,
+-2268,-2268,-2269,-2270,-2270,-2271,-2272,-2273,-2274,-2275,-2276,-2277,-2279,-2280,-2281,-2283,-2284,-2286,-2288,-2289,-2291,
+-2293,-2295,-2297,-2299,-2301,-2303,-2305,-2307,-2309,-2311,-2314,-2316,-2318,-2321,-2323,-2325,-2328,-2330,-2333,-2335,-2338,
+-2340,-2343,-2345,-2348,-2350,-2353,-2356,-2358,-2361,-2363,-2366,-2368,-2371,-2374,-2376,-2379,-2381,-2384,-2386,-2389,-2391,
+-2393,-2396,-2398,-2401,-2403,-2405,-2408,-2410,-2412,-2414,-2416,-2419,-2421,-2423,-2425,-2427,-2429,-2431,-2433,-2435,-2437,
+-2439,-2440,-2442,-2444,-2446,-2447,-2449,-2451,-2452,-2454,-2455,-2457,-2458,-2460,-2461,-2463,-2464,-2466,-2467,-2468,-2469,
+-2471,-2472,-2473,-2475,-2476,-2477,-2478,-2479,-2481,-2482,-2483,-2484,-2485,-2486,-2487,-2489,-2490,-2491,-2492,-2493,-2494,
+-2495,-2497,-2498,-2499,-2500,-2502,-2503,-2504,-2505,-2507,-2508,-2509,-2511,-2512,-2513,-2515,-2516,-2518,-2519,-2521,-2523,
+-2524,-2526,-2528,-2529,-2531,-2533,-2535,-2537,-2539,-2540,-2542,-2544,-2547,-2549,-2551,-2553,-2555,-2557,-2560,-2562,-2564,
+-2567,-2569,-2571,-2574,-2576,-2579,-2582,-2584,-2587,-2589,-2592,-2595,-2598,-2600,-2603,-2606,-2609,-2612,-2615,-2617,-2620,
+-2623,-2626,-2629,-2632,-2635,-2638,-2641,-2644,-2647,-2650,-2654,-2657,-2660,-2663,-2666,-2669,-2672,-2675,-2678,-2681,-2684,
+-2687,-2691,-2694,-2697,-2700,-2703,-2706,-2709,-2712,-2715,-2718,-2721,-2724,-2727,-2730,-2733,-2736,-2739,-2742,-2745,-2748,
+-2751,-2754,-2757,-2760,-2763,-2765,-2768,-2771,-2774,-2777,-2780,-2782,-2785,-2788,-2791,-2794,-2796,-2799,-2802,-2805,-2807,
+-2810,-2813,-2815,-2818,-2821,-2823,-2826,-2829,-2831,-2834,-2837,-2839,-2842,-2844,-2847,-2849,-2852,-2855,-2857,-2860,-2862,
+-2865,-2867,-2870,-2872,-2874,-2877,-2879,-2882,-2884,-2887,-2889,-2891,-2894,-2896,-2898,-2901,-2903,-2905,-2908,-2910,-2912,
+-2914,-2917,-2919,-2921,-2923,-2926,-2928,-2930,-2932,-2934,-2936,-2939,-2941,-2943,-2945,-2947,-2949,-2951,-2953,-2955,-2957,
+-2959,-2961,-2963,-2965,-2967,-2969,-2971,-2973,-2975,-2977,-2979,-2981,-2983,-2985,-2987,-2988,-2990,-2992,-2994,-2996,-2997,
+-2999,-3001,-3003,-3005,-3006,-3008,-3010,-3011,-3013,-3015,-3016,-3018,-3020,-3021,-3023,-3025,-3026,-3028,-3029,-3031,-3033,
+-3034,-3036,-3037,-3039,-3040,-3042,-3043,-3045,-3046,-3048,-3049,-3050,-3052,-3053,-3055,-3056,-3057,-3059,-3060,-3062,-3063,
+-3064,-3065,-3067,-3068,-3069,-3071,-3072,-3073,-3074,-3076,-3077,-3078,-3079,-3080,-3081,-3083,-3084,-3085,-3086,-3087,-3088,
+-3089,-3090,-3092,-3093,-3094,-3095,-3096,-3097,-3098,-3099,-3100,-3101,-3102,-3103,-3104,-3105,-3106,-3107,-3107,-3108,-3109,
+-3110,-3111,-3112,-3113,-3114,-3115,-3115,-3116,-3117,-3118,-3119,-3120,-3120,-3121,-3122,-3123,-3123,-3124,-3125,-3126,-3126,
+-3127,-3128,-3128,-3129,-3130,-3130,-3131,-3132,-3132,-3133,-3133,-3134,-3134,-3135,-3136,-3136,-3136,-3137,-3137,-3138,-3138,
+-3139,-3139,-3139,-3140,-3140,-3140,-3140,-3141,-3141,-3141,-3141,-3141,-3141,-3141,-3141,-3141,-3141,-3141,-3141,-3141,-3141,
+-3141,-3140,-3140,-3140,-3139,-3139,-3138,-3138,-3137,-3137,-3136,-3136,-3135,-3134,-3133,-3132,-3132,-3131,-3130,-3129,-3128,
+-3126,-3125,-3124,-3123,-3121,-3120,-3119,-3117,-3116,-3114,-3113,-3111,-3109,-3107,-3106,-3104,-3102,-3100,-3098,-3096,-3094,
+-3092,-3090,-3088,-3085,-3083,-3081,-3078,-3076,-3074,-3071,-3069,-3066,-3064,-3061,-3059,-3056,-3053,-3051,-3048,-3045,-3043,
+-3040,-3037,-3035,-3032,-3029,-3026,-3023,-3021,-3018,-3015,-3012,-3009,-3006,-3003,-3001,-2998,-2995,-2992,-2989,-2986,-2984,
+-2981,-2978,-2975,-2972,-2970,-2967,-2964,-2961,-2959,-2956,-2953,-2951,-2948,-2945,-2943,-2940,-2938,-2935,-2933,-2930,-2928,
+-2925,-2923,-2921,-2918,-2916,-2913,-2911,-2909,-2907,-2905,-2902,-2900,-2898,-2896,-2894,-2892,-2890,-2888,-2886,-2884,-2882,
+-2881,-2879,-2877,-2876,-2874,-2872,-2871,-2869,-2868,-2866,-2865,-2864,-2862,-2861,-2860,-2859,-2857,-2856,-2855,-2854,-2853,
+-2853,-2852,-2851,-2850,-2850,-2849,-2848,-2848,-2848,-2847,-2847,-2847,-2846,-2846,-2846,-2846,-2846,-2846,-2846,-2847,-2847,
+-2847,-2848,-2848,-2849,-2849,-2850,-2850,-2851,-2852,-2853,-2854,-2855,-2856,-2857,-2858,-2859,-2860,-2862,-2863,-2865,-2866,
+-2867,-2869,-2871,-2872,-2874,-2876,-2877,-2879,-2881,-2883,-2885,-2887,-2888,-2890,-2892,-2894,-2896,-2898,-2900,-2903,-2905,
+-2907,-2909,-2911,-2913,-2915,-2917,-2919,-2922,-2924,-2926,-2928,-2930,-2932,-2934,-2936,-2938,-2940,-2942,-2944,-2946,-2948,
+-2950,-2952,-2953,-2955,-2957,-2959,-2960,-2962,-2963,-2965,-2966,-2968,-2969,-2971,-2972,-2973,-2975,-2976,-2977,-2978,-2979,
+-2980,-2981,-2982,-2983,-2983,-2984,-2985,-2985,-2986,-2986,-2987,-2987,-2987,-2987,-2988,-2988,-2988,-2988,-2988,-2988,-2988,
+-2987,-2987,-2987,-2986,-2986,-2986,-2985,-2984,-2984,-2983,-2982,-2982,-2981,-2980,-2979,-2978,-2977,-2976,-2975,-2974,-2973,
+-2971,-2970,-2969,-2968,-2966,-2965,-2964,-2962,-2961,-2959,-2958,-2956,-2955,-2953,-2952,-2950,-2948,-2947,-2945,-2944,-2942,
+-2940,-2939,-2937,-2935,-2934,-2932,-2930,-2929,-2927,-2925,-2924,-2922,-2920,-2919,-2917,-2915,-2914,-2912,-2911,-2909,-2908,
+-2906,-2905,-2903,-2902,-2900,-2899,-2897,-2896,-2895,-2893,-2892,-2891,-2889,-2888,-2887,-2886,-2885,-2884,-2883,-2881,-2880,
+-2879,-2878,-2877,-2877,-2876,-2875,-2874,-2873,-2872,-2872,-2871,-2870,-2870,-2869,-2868,-2868,-2867,-2867,-2866,-2865,-2865,
+-2865,-2864,-2864,-2863,-2863,-2862,-2862,-2862,-2861,-2861,-2861,-2860,-2860,-2860,-2860,-2859,-2859,-2859,-2858,-2858,-2858,
+-2858,-2857,-2857,-2857,-2856,-2856,-2856,-2855,-2855,-2855,-2854,-2854,-2853,-2853,-2852,-2852,-2851,-2851,-2850,-2849,-2849,
+-2848,-2847,-2846,-2845,-2845,-2844,-2843,-2842,-2841,-2839,-2838,-2837,-2836,-2835,-2833,-2832,-2831,-2829,-2828,-2826,-2824,
+-2823,-2821,-2819,-2817,-2815,-2814,-2812,-2810,-2808,-2806,-2803,-2801,-2799,-2797,-2794,-2792,-2790,-2787,-2785,-2782,-2780,
+-2777,-2775,-2772,-2770,-2767,-2764,-2762,-2759,-2756,-2753,-2751,-2748,-2745,-2743,-2740,-2737,-2734,-2731,-2729,-2726,-2723,
+-2720,-2718,-2715,-2712,-2710,-2707,-2704,-2702,-2699,-2697,-2694,-2692,-2689,-2687,-2684,-2682,-2680,-2677,-2675,-2673,-2671,
+-2669,-2666,-2664,-2662,-2661,-2659,-2657,-2655,-2653,-2652,-2650,-2648,-2647,-2645,-2644,-2642,-2641,-2640,-2639,-2637,-2636,
+-2635,-2634,-2633,-2633,-2632,-2631,-2630,-2630,-2629,-2629,-2628,-2628,-2627,-2627,-2627,-2626,-2626,-2626,-2626,-2626,-2626,
+-2626,-2627,-2627,-2627,-2627,-2628,-2628,-2628,-2629,-2629,-2630,-2631,-2631,-2632,-2633,-2633,-2634,-2635,-2636,-2637,-2638,
+-2638,-2639,-2640,-2641,-2642,-2643,-2644,-2645,-2646,-2647,-2648,-2649,-2650,-2651,-2652,-2653,-2654,-2655,-2656,-2657,-2657,
+-2658,-2659,-2660,-2661,-2661,-2662,-2662,-2663,-2663,-2664,-2664,-2664,-2665,-2665,-2665,-2665,-2665,-2665,-2665,-2664,-2664,
+-2664,-2663,-2663,-2662,-2661,-2660,-2660,-2659,-2658,-2656,-2655,-2654,-2652,-2651,-2649,-2648,-2646,-2644,-2642,-2640,-2638,
+-2636,-2634,-2632,-2629,-2627,-2624,-2622,-2619,-2616,-2614,-2611,-2608,-2605,-2602,-2599,-2596,-2593,-2590,-2587,-2584,-2581,
+-2578,-2575,-2571,-2568,-2565,-2562,-2559,-2556,-2553,-2550,-2547,-2544,-2541,-2538,-2535,-2532,-2529,-2526,-2524,-2521,-2519,
+-2516,-2514,-2511,-2509,-2507,-2505,-2503,-2501,-2499,-2497,-2495,-2494,-2492,-2491,-2490,-2488,-2487,-2486,-2485,-2485,-2484,
+-2483,-2483,-2482,-2482,-2482,-2482,-2482,-2482,-2482,-2482,-2482,-2483,-2483,-2484,-2485,-2485,-2486,-2487,-2488,-2489,-2490,
+-2491,-2492,-2493,-2495,-2496,-2497,-2499,-2500,-2502,-2503,-2505,-2506,-2508,-2509,-2511,-2512,-2514,-2515,-2517,-2518,-2520,
+-2521,-2523,-2524,-2526,-2527,-2528,-2530,-2531,-2532,-2533,-2535,-2536,-2537,-2538,-2538,-2539,-2540,-2541,-2541,-2542,-2543,
+-2543,-2543,-2544,-2544,-2544,-2544,-2544,-2544,-2544,-2544,-2543,-2543,-2543,-2542,-2542,-2541,-2540,-2539,-2539,-2538,-2537,
+-2536,-2535,-2533,-2532,-2531,-2530,-2528,-2527,-2525,-2524,-2522,-2521,-2519,-2517,-2516,-2514,-2512,-2510,-2508,-2507,-2505,
+-2503,-2501,-2499,-2497,-2495,-2493,-2491,-2489,-2583,-2582,-2581,-2580,-2579,-2578,-2577,-2576,-2575,-2574,-2573,-2572,-2571,
+-2570,-2569,-2568,-2567,-2566,-2565,-2564,-2563,-2562,-2561,-2560,-2559,-2558,-2557,-2556,-2555,-2554,-2553,-2552,-2551,-2550,
+-2549,-2548,-2547,-2546,-2545,-2544,-2543,-2542,-2542,-2541,-2540,-2539,-2538,-2537,-2536,-2535,-2534,-2533,-2532,-2531,-2530,
+-2529,-2528,-2527,-2526,-2525,-2524,-2523,-2522,-2521,-2520,-2519,-2518,-2517,-2516,-2515,-2514,-2513,-2512,-2511,-2510,-2508,
+-2507,-2506,-2505,-2504,-2503,-2501,-2500,-2499,-2498,-2497,-2495,-2494,-2493,-2492,-2490,-2489,-2488,-2486,-2485,-2484,-2483,
+-2481,-2480,-2479,-2478,-2476,-2475,-2474,-2473,-2471,-2470,-2469,-2468,-2466,-2465,-2464,-2463,-2462,-2461,-2460,-2458,-2457,
+-2456,-2455,-2454,-2453,-2452,-2452,-2451,-2450,-2449,-2448,-2447,-2447,-2446,-2445,-2445,-2444,-2444,-2443,-2443,-2442,-2442,
+-2441,-2441,-2441,-2441,-2440,-2440,-2440,-2440,-2440,-2440,-2440,-2440,-2440,-2441,-2441,-2441,-2441,-2442,-2442,-2443,-2443,
+-2444,-2444,-2445,-2446,-2446,-2447,-2448,-2449,-2450,-2450,-2451,-2452,-2453,-2454,-2455,-2457,-2458,-2459,-2460,-2461,-2463,
+-2464,-2465,-2466,-2468,-2469,-2471,-2472,-2473,-2475,-2476,-2478,-2479,-2481,-2482,-2484,-2486,-2487,-2489,-2490,-2492,-2493,
+-2495,-2497,-2498,-2500,-2501,-2503,-2505,-2506,-2508,-2510,-2511,-2513,-2514,-2516,-2518,-2519,-2521,-2522,-2524,-2525,-2527,
+-2528,-2530,-2531,-2533,-2534,-2536,-2537,-2539,-2540,-2542,-2543,-2544,-2546,-2547,-2548,-2550,-2551,-2552,-2554,-2555,-2556,
+-2558,-2559,-2560,-2561,-2562,-2564,-2565,-2566,-2567,-2568,-2570,-2571,-2572,-2573,-2574,-2575,-2576,-2577,-2579,-2580,-2581,
+-2582,-2583,-2584,-2585,-2586,-2587,-2589,-2590,-2591,-2592,-2593,-2594,-2595,-2596,-2598,-2599,-2600,-2601,-2602,-2603,-2605,
+-2606,-2607,-2608,-2610,-2611,-2612,-2614,-2615,-2616,-2618,-2619,-2621,-2622,-2623,-2625,-2626,-2628,-2629,-2631,-2633,-2634,
+-2636,-2637,-2639,-2641,-2642,-2644,-2646,-2648,-2649,-2651,-2653,-2655,-2657,-2659,-2661,-2663,-2665,-2667,-2669,-2671,-2673,
+-2675,-2677,-2679,-2681,-2683,-2685,-2687,-2690,-2692,-2694,-2696,-2698,-2701,-2703,-2705,-2707,-2710,-2712,-2714,-2717,-2719,
+-2721,-2724,-2726,-2728,-2731,-2733,-2735,-2738,-2740,-2743,-2745,-2747,-2750,-2752,-2754,-2757,-2759,-2762,-2764,-2766,-2769,
+-2771,-2774,-2776,-2778,-2781,-2783,-2785,-2788,-2790,-2792,-2795,-2797,-2799,-2802,-2804,-2806,-2808,-2811,-2813,-2815,-2818,
+-2820,-2822,-2824,-2827,-2829,-2831,-2833,-2835,-2838,-2840,-2842,-2844,-2846,-2848,-2850,-2853,-2855,-2857,-2859,-2861,-2863,
+-2865,-2867,-2869,-2871,-2873,-2875,-2877,-2879,-2881,-2884,-2886,-2887,-2889,-2891,-2893,-2895,-2897,-2899,-2901,-2903,-2905,
+-2907,-2909,-2911,-2913,-2915,-2917,-2918,-2920,-2922,-2924,-2926,-2928,-2930,-2931,-2933,-2935,-2937,-2939,-2941,-2942,-2944,
+-2946,-2948,-2950,-2951,-2953,-2955,-2957,-2958,-2960,-2962,-2964,-2965,-2967,-2969,-2971,-2972,-2974,-2976,-2977,-2979,-2981,
+-2982,-2984,-2986,-2987,-2989,-2991,-2992,-2994,-2996,-2997,-2999,-3000,-3002,-3004,-3005,-3007,-3008,-3010,-3011,-3013,-3015,
+-3016,-3018,-3019,-3021,-3022,-3024,-3025,-3027,-3028,-3030,-3031,-3032,-3034,-3035,-3037,-3038,-3040,-3041,-3042,-3044,-3045,
+-3046,-3048,-3049,-3050,-3052,-3053,-3054,-3056,-3057,-3058,-3059,-3061,-3062,-3063,-3064,-3066,-3067,-3068,-3069,-3070,-3071,
+-3073,-3074,-3075,-3076,-3077,-3078,-3079,-3080,-3081,-3083,-3084,-3085,-3086,-3087,-3088,-3089,-3090,-3091,-3092,-3093,-3094,
+-3095,-3095,-3096,-3097,-3098,-3099,-3100,-3101,-3102,-3103,-3103,-3104,-3105,-3106,-3107,-3107,-3108,-3109,-3110,-3111,-3111,
+-3112,-3113,-3113,-3114,-3115,-3115,-3116,-3117,-3117,-3118,-3119,-3119,-3120,-3120,-3121,-3121,-3122,-3122,-3123,-3123,-3124,
+-3124,-3125,-3125,-3125,-3126,-3126,-3126,-3127,-3127,-3127,-3127,-3128,-3128,-3128,-3128,-3128,-3128,-3128,-3128,-3128,-3128,
+-3128,-3128,-3128,-3128,-3128,-3128,-3128,-3127,-3127,-3127,-3127,-3126,-3126,-3125,-3125,-3125,-3124,-3124,-3123,-3122,-3122,
+-3121,-3120,-3120,-3119,-3118,-3117,-3116,-3116,-3115,-3114,-3113,-3112,-3111,-3110,-3109,-3107,-3106,-3105,-3104,-3103,-3101,
+-3100,-3099,-3097,-3096,-3095,-3093,-3092,-3090,-3089,-3087,-3085,-3084,-3082,-3081,-3079,-3077,-3076,-3074,-3072,-3070,-3069,
+-3067,-3065,-3063,-3062,-3060,-3058,-3056,-3054,-3052,-3050,-3049,-3047,-3045,-3043,-3041,-3039,-3037,-3035,-3034,-3032,-3030,
+-3028,-3026,-3024,-3022,-3020,-3019,-3017,-3015,-3013,-3011,-3010,-3008,-3006,-3004,-3002,-3001,-2999,-2997,-2996,-2994,-2992,
+-2991,-2989,-2987,-2986,-2984,-2983,-2981,-2980,-2978,-2977,-2975,-2974,-2972,-2971,-2970,-2968,-2967,-2966,-2964,-2963,-2962,
+-2961,-2959,-2958,-2957,-2956,-2955,-2954,-2953,-2951,-2950,-2949,-2948,-2947,-2946,-2946,-2945,-2944,-2943,-2942,-2941,-2940,
+-2940,-2939,-2938,-2937,-2937,-2936,-2935,-2935,-2934,-2933,-2933,-2932,-2932,-2931,-2931,-2930,-2930,-2929,-2929,-2929,-2928,
+-2928,-2928,-2927,-2927,-2927,-2927,-2926,-2926,-2926,-2926,-2926,-2926,-2926,-2926,-2926,-2926,-2926,-2926,-2926,-2926,-2926,
+-2926,-2926,-2927,-2927,-2927,-2927,-2928,-2928,-2928,-2928,-2929,-2929,-2930,-2930,-2930,-2931,-2931,-2932,-2932,-2933,-2934,
+-2934,-2935,-2935,-2936,-2937,-2937,-2938,-2939,-2939,-2940,-2941,-2942,-2942,-2943,-2944,-2945,-2946,-2946,-2947,-2948,-2949,
+-2950,-2951,-2951,-2952,-2953,-2954,-2955,-2956,-2957,-2958,-2959,-2960,-2960,-2961,-2962,-2963,-2964,-2965,-2966,-2967,-2968,
+-2969,-2969,-2970,-2971,-2972,-2973,-2974,-2975,-2975,-2976,-2977,-2978,-2979,-2979,-2980,-2981,-2982,-2982,-2983,-2984,-2984,
+-2985,-2986,-2986,-2987,-2987,-2988,-2989,-2989,-2990,-2990,-2990,-2991,-2991,-2992,-2992,-2992,-2993,-2993,-2993,-2994,-2994,
+-2994,-2994,-2994,-2994,-2994,-2995,-2995,-2995,-2995,-2995,-2995,-2994,-2994,-2994,-2994,-2994,-2994,-2994,-2993,-2993,-2993,
+-2992,-2992,-2992,-2991,-2991,-2990,-2990,-2989,-2989,-2988,-2988,-2987,-2987,-2986,-2986,-2985,-2984,-2984,-2983,-2982,-2981,
+-2981,-2980,-2979,-2978,-2978,-2977,-2976,-2975,-2974,-2974,-2973,-2972,-2971,-2970,-2969,-2968,-2967,-2967,-2966,-2965,-2964,
+-2963,-2962,-2961,-2960,-2959,-2958,-2958,-2957,-2956,-2955,-2954,-2953,-2952,-2951,-2951,-2950,-2949,-2948,-2947,-2946,-2946,
+-2945,-2944,-2943,-2942,-2942,-2941,-2940,-2939,-2939,-2938,-2937,-2937,-2936,-2935,-2935,-2934,-2933,-2933,-2932,-2931,-2931,
+-2930,-2930,-2929,-2928,-2928,-2927,-2927,-2926,-2926,-2925,-2924,-2924,-2923,-2923,-2922,-2922,-2921,-2921,-2920,-2920,-2919,
+-2918,-2918,-2917,-2917,-2916,-2915,-2915,-2914,-2914,-2913,-2912,-2911,-2911,-2910,-2909,-2908,-2908,-2907,-2906,-2905,-2904,
+-2903,-2902,-2901,-2900,-2899,-2898,-2897,-2896,-2895,-2894,-2892,-2891,-2890,-2889,-2887,-2886,-2884,-2883,-2881,-2880,-2878,
+-2877,-2875,-2873,-2872,-2870,-2868,-2866,-2865,-2863,-2861,-2859,-2857,-2855,-2853,-2851,-2849,-2847,-2845,-2842,-2840,-2838,
+-2836,-2834,-2831,-2829,-2827,-2824,-2822,-2820,-2817,-2815,-2813,-2810,-2808,-2805,-2803,-2801,-2798,-2796,-2793,-2791,-2789,
+-2786,-2784,-2781,-2779,-2777,-2774,-2772,-2770,-2767,-2765,-2763,-2761,-2758,-2756,-2754,-2752,-2750,-2748,-2746,-2744,-2742,
+-2740,-2738,-2736,-2734,-2732,-2731,-2729,-2727,-2726,-2724,-2723,-2721,-2720,-2718,-2717,-2716,-2715,-2713,-2712,-2711,-2710,
+-2709,-2708,-2707,-2707,-2706,-2705,-2704,-2704,-2703,-2703,-2702,-2702,-2702,-2701,-2701,-2701,-2701,-2701,-2701,-2701,-2701,
+-2701,-2701,-2701,-2701,-2702,-2702,-2702,-2703,-2703,-2704,-2704,-2705,-2705,-2706,-2706,-2707,-2708,-2708,-2709,-2710,-2710,
+-2711,-2712,-2713,-2713,-2714,-2715,-2716,-2716,-2717,-2718,-2719,-2719,-2720,-2721,-2722,-2722,-2723,-2724,-2724,-2725,-2725,
+-2726,-2726,-2727,-2727,-2728,-2728,-2728,-2729,-2729,-2729,-2729,-2729,-2729,-2729,-2729,-2729,-2729,-2729,-2729,-2728,-2728,
+-2728,-2727,-2727,-2726,-2725,-2725,-2724,-2723,-2722,-2721,-2720,-2719,-2718,-2717,-2716,-2715,-2713,-2712,-2711,-2709,-2708,
+-2706,-2705,-2703,-2701,-2700,-2698,-2696,-2694,-2693,-2691,-2689,-2687,-2685,-2683,-2681,-2679,-2677,-2675,-2673,-2671,-2669,
+-2667,-2665,-2663,-2661,-2658,-2656,-2654,-2652,-2650,-2648,-2646,-2644,-2643,-2641,-2639,-2637,-2635,-2633,-2632,-2630,-2628,
+-2626,-2625,-2623,-2622,-2620,-2619,-2618,-2616,-2615,-2614,-2612,-2611,-2610,-2609,-2608,-2607,-2606,-2606,-2605,-2604,-2603,
+-2603,-2602,-2602,-2601,-2601,-2600,-2600,-2600,-2599,-2599,-2599,-2599,-2599,-2599,-2599,-2599,-2599,-2599,-2599,-2599,-2599,
+-2600,-2600,-2600,-2600,-2601,-2601,-2601,-2602,-2602,-2602,-2603,-2603,-2603,-2604,-2604,-2605,-2605,-2605,-2606,-2606,-2607,
+-2607,-2607,-2608,-2608,-2608,-2609,-2609,-2609,-2609,-2610,-2610,-2610,-2610,-2610,-2610,-2610,-2610,-2610,-2610,-2610,-2610,
+-2610,-2610,-2610,-2610,-2609,-2609,-2609,-2609,-2608,-2608,-2607,-2607,-2607,-2606,-2606,-2605,-2604,-2604,-2603,-2603,-2602,
+-2601,-2600,-2600,-2599,-2598,-2597,-2596,-2596,-2595,-2594,-2593,-2592,-2591,-2590,-2589,-2588,-2587,-2586,-2585,-2584,-2583,
+-2658,-2657,-2657,-2656,-2655,-2655,-2654,-2654,-2653,-2653,-2652,-2651,-2651,-2650,-2650,-2649,-2649,-2648,-2648,-2647,-2646,
+-2646,-2645,-2645,-2644,-2644,-2643,-2643,-2642,-2642,-2641,-2641,-2640,-2639,-2639,-2638,-2638,-2637,-2637,-2636,-2636,-2635,
+-2635,-2634,-2634,-2633,-2633,-2632,-2632,-2631,-2631,-2630,-2630,-2629,-2629,-2628,-2628,-2627,-2627,-2626,-2626,-2625,-2625,
+-2624,-2623,-2623,-2622,-2622,-2621,-2621,-2620,-2620,-2619,-2619,-2618,-2617,-2617,-2616,-2616,-2615,-2615,-2614,-2613,-2613,
+-2612,-2612,-2611,-2611,-2610,-2609,-2609,-2608,-2608,-2607,-2607,-2606,-2605,-2605,-2604,-2604,-2603,-2603,-2602,-2601,-2601,
+-2600,-2600,-2599,-2599,-2598,-2598,-2597,-2597,-2596,-2596,-2596,-2595,-2595,-2594,-2594,-2593,-2593,-2593,-2592,-2592,-2592,
+-2591,-2591,-2591,-2591,-2590,-2590,-2590,-2590,-2589,-2589,-2589,-2589,-2589,-2589,-2589,-2589,-2589,-2589,-2589,-2589,-2589,
+-2589,-2589,-2589,-2589,-2589,-2590,-2590,-2590,-2590,-2591,-2591,-2591,-2591,-2592,-2592,-2592,-2593,-2593,-2594,-2594,-2595,
+-2595,-2596,-2596,-2597,-2597,-2598,-2599,-2599,-2600,-2600,-2601,-2602,-2602,-2603,-2604,-2605,-2605,-2606,-2607,-2608,-2608,
+-2609,-2610,-2611,-2612,-2613,-2613,-2614,-2615,-2616,-2617,-2618,-2619,-2619,-2620,-2621,-2622,-2623,-2624,-2625,-2626,-2627,
+-2628,-2629,-2629,-2630,-2631,-2632,-2633,-2634,-2635,-2636,-2637,-2638,-2639,-2640,-2640,-2641,-2642,-2643,-2644,-2645,-2646,
+-2647,-2647,-2648,-2649,-2650,-2651,-2652,-2653,-2653,-2654,-2655,-2656,-2657,-2658,-2658,-2659,-2660,-2661,-2662,-2663,-2663,
+-2664,-2665,-2666,-2667,-2667,-2668,-2669,-2670,-2671,-2671,-2672,-2673,-2674,-2675,-2675,-2676,-2677,-2678,-2679,-2679,-2680,
+-2681,-2682,-2683,-2684,-2684,-2685,-2686,-2687,-2688,-2689,-2690,-2690,-2691,-2692,-2693,-2694,-2695,-2696,-2697,-2698,-2699,
+-2700,-2701,-2702,-2703,-2704,-2705,-2706,-2707,-2708,-2709,-2710,-2711,-2713,-2714,-2715,-2716,-2717,-2718,-2720,-2721,-2722,
+-2723,-2724,-2726,-2727,-2728,-2730,-2731,-2732,-2734,-2735,-2736,-2738,-2739,-2740,-2742,-2743,-2745,-2746,-2748,-2749,-2751,
+-2752,-2754,-2755,-2757,-2758,-2760,-2761,-2763,-2765,-2766,-2768,-2769,-2771,-2773,-2774,-2776,-2777,-2779,-2781,-2782,-2784,
+-2786,-2787,-2789,-2791,-2793,-2794,-2796,-2798,-2799,-2801,-2803,-2804,-2806,-2808,-2810,-2811,-2813,-2815,-2817,-2818,-2820,
+-2822,-2823,-2825,-2827,-2829,-2830,-2832,-2834,-2836,-2837,-2839,-2841,-2842,-2844,-2846,-2848,-2849,-2851,-2853,-2854,-2856,
+-2858,-2860,-2861,-2863,-2865,-2866,-2868,-2870,-2871,-2873,-2875,-2876,-2878,-2880,-2881,-2883,-2885,-2886,-2888,-2890,-2891,
+-2893,-2895,-2896,-2898,-2899,-2901,-2903,-2904,-2906,-2907,-2909,-2911,-2912,-2914,-2915,-2917,-2918,-2920,-2922,-2923,-2925,
+-2926,-2928,-2929,-2931,-2932,-2934,-2936,-2937,-2939,-2940,-2942,-2943,-2945,-2946,-2948,-2949,-2951,-2952,-2954,-2955,-2957,
+-2958,-2960,-2961,-2963,-2964,-2965,-2967,-2968,-2970,-2971,-2973,-2974,-2976,-2977,-2978,-2980,-2981,-2983,-2984,-2985,-2987,
+-2988,-2990,-2991,-2992,-2994,-2995,-2997,-2998,-2999,-3001,-3002,-3003,-3005,-3006,-3007,-3009,-3010,-3011,-3013,-3014,-3015,
+-3016,-3018,-3019,-3020,-3022,-3023,-3024,-3025,-3026,-3028,-3029,-3030,-3031,-3033,-3034,-3035,-3036,-3037,-3038,-3040,-3041,
+-3042,-3043,-3044,-3045,-3046,-3048,-3049,-3050,-3051,-3052,-3053,-3054,-3055,-3056,-3057,-3058,-3059,-3060,-3061,-3062,-3063,
+-3064,-3065,-3066,-3067,-3068,-3069,-3070,-3071,-3072,-3073,-3074,-3074,-3075,-3076,-3077,-3078,-3079,-3079,-3080,-3081,-3082,
+-3083,-3083,-3084,-3085,-3086,-3086,-3087,-3088,-3089,-3089,-3090,-3091,-3091,-3092,-3092,-3093,-3094,-3094,-3095,-3095,-3096,
+-3096,-3097,-3097,-3098,-3098,-3099,-3099,-3100,-3100,-3100,-3101,-3101,-3102,-3102,-3102,-3102,-3103,-3103,-3103,-3103,-3104,
+-3104,-3104,-3104,-3104,-3104,-3105,-3105,-3105,-3105,-3105,-3105,-3105,-3105,-3105,-3105,-3104,-3104,-3104,-3104,-3104,-3104,
+-3103,-3103,-3103,-3103,-3102,-3102,-3102,-3101,-3101,-3100,-3100,-3099,-3099,-3098,-3098,-3097,-3097,-3096,-3096,-3095,-3094,
+-3094,-3093,-3092,-3092,-3091,-3090,-3089,-3088,-3088,-3087,-3086,-3085,-3084,-3083,-3082,-3081,-3080,-3079,-3078,-3078,-3076,
+-3075,-3074,-3073,-3072,-3071,-3070,-3069,-3068,-3067,-3066,-3065,-3063,-3062,-3061,-3060,-3059,-3058,-3057,-3055,-3054,-3053,
+-3052,-3051,-3049,-3048,-3047,-3046,-3045,-3043,-3042,-3041,-3040,-3039,-3038,-3036,-3035,-3034,-3033,-3032,-3030,-3029,-3028,
+-3027,-3026,-3025,-3024,-3023,-3021,-3020,-3019,-3018,-3017,-3016,-3015,-3014,-3013,-3012,-3011,-3010,-3009,-3008,-3007,-3006,
+-3005,-3004,-3003,-3002,-3001,-3000,-2999,-2999,-2998,-2997,-2996,-2995,-2994,-2994,-2993,-2992,-2991,-2990,-2990,-2989,-2988,
+-2988,-2987,-2986,-2985,-2985,-2984,-2983,-2983,-2982,-2981,-2981,-2980,-2980,-2979,-2978,-2978,-2977,-2977,-2976,-2976,-2975,
+-2975,-2974,-2974,-2973,-2973,-2972,-2972,-2971,-2971,-2970,-2970,-2970,-2969,-2969,-2968,-2968,-2968,-2967,-2967,-2967,-2966,
+-2966,-2966,-2965,-2965,-2965,-2964,-2964,-2964,-2964,-2963,-2963,-2963,-2963,-2963,-2962,-2962,-2962,-2962,-2962,-2962,-2962,
+-2961,-2961,-2961,-2961,-2961,-2961,-2961,-2961,-2961,-2961,-2961,-2961,-2961,-2961,-2961,-2961,-2961,-2961,-2962,-2962,-2962,
+-2962,-2962,-2962,-2962,-2963,-2963,-2963,-2963,-2964,-2964,-2964,-2964,-2965,-2965,-2965,-2966,-2966,-2966,-2967,-2967,-2968,
+-2968,-2968,-2969,-2969,-2970,-2970,-2971,-2971,-2972,-2972,-2973,-2973,-2974,-2974,-2975,-2975,-2976,-2976,-2977,-2978,-2978,
+-2979,-2979,-2980,-2980,-2981,-2982,-2982,-2983,-2983,-2984,-2985,-2985,-2986,-2986,-2987,-2988,-2988,-2989,-2989,-2990,-2991,
+-2991,-2992,-2992,-2993,-2994,-2994,-2995,-2995,-2996,-2996,-2997,-2997,-2998,-2998,-2999,-2999,-3000,-3000,-3001,-3001,-3001,
+-3002,-3002,-3002,-3003,-3003,-3003,-3004,-3004,-3004,-3005,-3005,-3005,-3005,-3005,-3006,-3006,-3006,-3006,-3006,-3006,-3006,
+-3006,-3007,-3007,-3007,-3007,-3007,-3006,-3006,-3006,-3006,-3006,-3006,-3006,-3006,-3006,-3005,-3005,-3005,-3005,-3005,-3004,
+-3004,-3004,-3003,-3003,-3003,-3002,-3002,-3002,-3001,-3001,-3001,-3000,-3000,-2999,-2999,-2998,-2998,-2997,-2997,-2997,-2996,
+-2996,-2995,-2995,-2994,-2994,-2993,-2992,-2992,-2991,-2991,-2990,-2990,-2989,-2989,-2988,-2988,-2987,-2987,-2986,-2985,-2985,
+-2984,-2984,-2983,-2983,-2982,-2981,-2981,-2980,-2980,-2979,-2979,-2978,-2977,-2977,-2976,-2976,-2975,-2975,-2974,-2973,-2973,
+-2972,-2972,-2971,-2971,-2970,-2969,-2969,-2968,-2968,-2967,-2966,-2966,-2965,-2964,-2964,-2963,-2962,-2962,-2961,-2960,-2960,
+-2959,-2958,-2957,-2957,-2956,-2955,-2954,-2954,-2953,-2952,-2951,-2950,-2949,-2948,-2947,-2946,-2945,-2944,-2943,-2942,-2941,
+-2940,-2939,-2938,-2937,-2936,-2935,-2933,-2932,-2931,-2930,-2928,-2927,-2926,-2924,-2923,-2921,-2920,-2918,-2917,-2915,-2914,
+-2912,-2911,-2909,-2907,-2906,-2904,-2902,-2901,-2899,-2897,-2895,-2894,-2892,-2890,-2888,-2886,-2884,-2882,-2880,-2878,-2876,
+-2874,-2872,-2870,-2868,-2866,-2864,-2862,-2860,-2858,-2856,-2854,-2852,-2850,-2848,-2846,-2844,-2842,-2840,-2838,-2835,-2833,
+-2831,-2829,-2827,-2825,-2823,-2821,-2819,-2817,-2815,-2814,-2812,-2810,-2808,-2806,-2804,-2802,-2801,-2799,-2797,-2795,-2794,
+-2792,-2791,-2789,-2787,-2786,-2784,-2783,-2782,-2780,-2779,-2778,-2776,-2775,-2774,-2773,-2772,-2771,-2769,-2768,-2768,-2767,
+-2766,-2765,-2764,-2763,-2763,-2762,-2761,-2761,-2760,-2760,-2759,-2759,-2758,-2758,-2758,-2757,-2757,-2757,-2757,-2756,-2756,
+-2756,-2756,-2756,-2756,-2756,-2756,-2756,-2756,-2757,-2757,-2757,-2757,-2757,-2758,-2758,-2758,-2758,-2759,-2759,-2760,-2760,
+-2760,-2761,-2761,-2761,-2762,-2762,-2763,-2763,-2764,-2764,-2764,-2765,-2765,-2766,-2766,-2767,-2767,-2767,-2768,-2768,-2768,
+-2769,-2769,-2769,-2770,-2770,-2770,-2770,-2771,-2771,-2771,-2771,-2771,-2771,-2772,-2772,-2772,-2772,-2772,-2772,-2772,-2771,
+-2771,-2771,-2771,-2771,-2770,-2770,-2770,-2770,-2769,-2769,-2768,-2768,-2768,-2767,-2767,-2766,-2765,-2765,-2764,-2764,-2763,
+-2762,-2761,-2761,-2760,-2759,-2758,-2758,-2757,-2756,-2755,-2754,-2753,-2752,-2751,-2750,-2749,-2748,-2747,-2746,-2745,-2744,
+-2743,-2742,-2741,-2740,-2739,-2738,-2737,-2736,-2735,-2734,-2733,-2732,-2731,-2730,-2729,-2728,-2727,-2726,-2725,-2724,-2723,
+-2722,-2721,-2720,-2719,-2718,-2717,-2716,-2715,-2714,-2713,-2713,-2712,-2711,-2710,-2709,-2709,-2708,-2707,-2706,-2706,-2705,
+-2704,-2703,-2703,-2702,-2701,-2701,-2700,-2700,-2699,-2698,-2698,-2697,-2697,-2696,-2696,-2695,-2695,-2694,-2694,-2693,-2693,
+-2692,-2692,-2691,-2691,-2691,-2690,-2690,-2689,-2689,-2689,-2688,-2688,-2687,-2687,-2687,-2686,-2686,-2686,-2685,-2685,-2684,
+-2684,-2684,-2683,-2683,-2682,-2682,-2682,-2681,-2681,-2680,-2680,-2680,-2679,-2679,-2678,-2678,-2678,-2677,-2677,-2676,-2676,
+-2675,-2675,-2674,-2674,-2673,-2673,-2672,-2672,-2671,-2671,-2670,-2670,-2669,-2669,-2668,-2668,-2667,-2667,-2666,-2666,-2665,
+-2664,-2664,-2663,-2663,-2662,-2662,-2661,-2661,-2660,-2659,-2659,-2658,-2658,-2708,-2708,-2708,-2707,-2707,-2706,-2706,-2705,
+-2705,-2705,-2704,-2704,-2704,-2703,-2703,-2702,-2702,-2702,-2701,-2701,-2701,-2700,-2700,-2700,-2699,-2699,-2699,-2699,-2698,
+-2698,-2698,-2697,-2697,-2697,-2697,-2696,-2696,-2696,-2696,-2695,-2695,-2695,-2695,-2695,-2694,-2694,-2694,-2694,-2694,-2693,
+-2693,-2693,-2693,-2693,-2692,-2692,-2692,-2692,-2692,-2692,-2692,-2691,-2691,-2691,-2691,-2691,-2691,-2691,-2691,-2690,-2690,
+-2690,-2690,-2690,-2690,-2690,-2690,-2690,-2690,-2689,-2689,-2689,-2689,-2689,-2689,-2689,-2689,-2689,-2689,-2689,-2689,-2689,
 -2689,-2689,-2689,-2689,-2689,-2689,-2689,-2689,-2689,-2689,-2689,-2689,-2689,-2689,-2689,-2689,-2689,-2689,-2689,-2689,-2689,
--2689,-2689,-2689,-2689,-2689,-2689,-2689,-2689,-2689,-2689,-2690,-2690,-2690,-2690,-2690,-2690,-2690,-2690,-2690,-2691,-2691,
--2691,-2691,-2691,-2691,-2692,-2692,-2692,-2692,-2692,-2693,-2693,-2693,-2693,-2694,-2694,-2694,-2694,-2695,-2695,-2695,-2696,
--2696,-2696,-2697,-2697,-2697,-2698,-2698,-2698,-2699,-2699,-2699,-2700,-2700,-2701,-2701,-2701,-2702,-2702,-2703,-2703,-2704,
--2704,-2705,-2705,-2705,-2706,-2706,-2707,-2707,-2708,-2708,-2709,-2709,-2710,-2710,-2711,-2711,-2712,-2712,-2713,-2714,-2714,
--2715,-2715,-2716,-2716,-2717,-2717,-2718,-2718,-2719,-2720,-2720,-2721,-2721,-2722,-2722,-2723,-2723,-2724,-2725,-2725,-2726,
--2726,-2727,-2727,-2728,-2728,-2729,-2730,-2730,-2731,-2731,-2732,-2732,-2733,-2733,-2734,-2734,-2735,-2735,-2736,-2737,-2737,
--2738,-2738,-2739,-2739,-2740,-2740,-2741,-2741,-2742,-2742,-2743,-2743,-2744,-2744,-2745,-2745,-2746,-2746,-2746,-2747,-2747,
--2748,-2748,-2749,-2749,-2750,-2750,-2751,-2751,-2752,-2752,-2753,-2753,-2754,-2754,-2755,-2755,-2755,-2756,-2756,-2757,-2757,
--2758,-2758,-2759,-2759,-2760,-2760,-2761,-2761,-2762,-2762,-2763,-2763,-2764,-2764,-2765,-2765,-2766,-2766,-2767,-2768,-2768,
--2769,-2769,-2770,-2770,-2771,-2772,-2772,-2773,-2773,-2774,-2775,-2775,-2776,-2777,-2777,-2778,-2778,-2779,-2780,-2781,-2781,
--2782,-2783,-2783,-2784,-2785,-2786,-2786,-2787,-2788,-2789,-2789,-2790,-2791,-2792,-2793,-2794,-2794,-2795,-2796,-2797,-2798,
--2799,-2800,-2801,-2801,-2802,-2803,-2804,-2805,-2806,-2807,-2808,-2809,-2810,-2811,-2812,-2813,-2814,-2815,-2816,-2817,-2818,
--2819,-2820,-2821,-2822,-2823,-2825,-2826,-2827,-2828,-2829,-2830,-2831,-2832,-2833,-2835,-2836,-2837,-2838,-2839,-2840,-2841,
--2843,-2844,-2845,-2846,-2847,-2849,-2850,-2851,-2852,-2853,-2855,-2856,-2857,-2858,-2860,-2861,-2862,-2863,-2865,-2866,-2867,
--2868,-2870,-2871,-2872,-2873,-2875,-2876,-2877,-2878,-2880,-2881,-2882,-2883,-2885,-2886,-2887,-2889,-2890,-2891,-2892,-2894,
--2895,-2896,-2897,-2899,-2900,-2901,-2903,-2904,-2905,-2906,-2908,-2909,-2910,-2912,-2913,-2914,-2915,-2917,-2918,-2919,-2920,
--2922,-2923,-2924,-2926,-2927,-2928,-2929,-2931,-2932,-2933,-2934,-2936,-2937,-2938,-2939,-2941,-2942,-2943,-2944,-2946,-2947,
--2948,-2949,-2950,-2952,-2953,-2954,-2955,-2956,-2958,-2959,-2960,-2961,-2962,-2964,-2965,-2966,-2967,-2968,-2970,-2971,-2972,
--2973,-2974,-2975,-2976,-2978,-2979,-2980,-2981,-2982,-2983,-2984,-2985,-2987,-2988,-2989,-2990,-2991,-2992,-2993,-2994,-2995,
--2996,-2997,-2998,-2999,-3000,-3001,-3002,-3003,-3004,-3005,-3006,-3007,-3008,-3009,-3010,-3011,-3012,-3013,-3014,-3015,-3016,
--3017,-3018,-3019,-3020,-3020,-3021,-3022,-3023,-3024,-3025,-3026,-3027,-3027,-3028,-3029,-3030,-3031,-3031,-3032,-3033,-3034,
--3034,-3035,-3036,-3037,-3037,-3038,-3039,-3039,-3040,-3041,-3042,-3042,-3043,-3043,-3044,-3045,-3045,-3046,-3047,-3047,-3048,
--3048,-3049,-3049,-3050,-3050,-3051,-3051,-3052,-3052,-3053,-3053,-3054,-3054,-3055,-3055,-3055,-3056,-3056,-3057,-3057,-3057,
--3058,-3058,-3058,-3058,-3059,-3059,-3059,-3059,-3060,-3060,-3060,-3060,-3061,-3061,-3061,-3061,-3061,-3061,-3061,-3061,-3061,
--3062,-3062,-3062,-3062,-3062,-3062,-3062,-3062,-3062,-3061,-3061,-3061,-3061,-3061,-3061,-3061,-3061,-3061,-3060,-3060,-3060,
--3060,-3059,-3059,-3059,-3059,-3058,-3058,-3058,-3057,-3057,-3057,-3056,-3056,-3056,-3055,-3055,-3054,-3054,-3054,-3053,-3053,
--3052,-3052,-3051,-3051,-3050,-3050,-3049,-3048,-3048,-3047,-3047,-3046,-3046,-3045,-3044,-3044,-3043,-3042,-3042,-3041,-3040,
--3040,-3039,-3038,-3038,-3037,-3036,-3036,-3035,-3034,-3034,-3033,-3032,-3031,-3031,-3030,-3029,-3028,-3028,-3027,-3026,-3025,
--3025,-3024,-3023,-3022,-3022,-3021,-3020,-3019,-3019,-3018,-3017,-3016,-3016,-3015,-3014,-3013,-3013,-3012,-3011,-3010,-3010,
--3009,-3008,-3007,-3007,-3006,-3005,-3005,-3004,-3003,-3003,-3002,-3001,-3000,-3000,-2999,-2998,-2998,-2997,-2997,-2996,-2995,
--2995,-2994,-2993,-2993,-2992,-2992,-2991,-2990,-2990,-2989,-2989,-2988,-2988,-2987,-2987,-2986,-2986,-2985,-2985,-2984,-2984,
--2983,-2983,-2982,-2982,-2981,-2981,-2980,-2980,-2979,-2979,-2979,-2978,-2978,-2977,-2977,-2977,-2976,-2976,-2976,-2975,-2975,
--2975,-2974,-2974,-2974,-2973,-2973,-2973,-2972,-2972,-2972,-2972,-2971,-2971,-2971,-2971,-2970,-2970,-2970,-2970,-2970,-2969,
--2969,-2969,-2969,-2969,-2969,-2969,-2968,-2968,-2968,-2968,-2968,-2968,-2968,-2968,-2968,-2968,-2968,-2968,-2968,-2968,-2968,
--2968,-2968,-2968,-2968,-2968,-2968,-2968,-2968,-2968,-2968,-2968,-2968,-2968,-2968,-2968,-2969,-2969,-2969,-2969,-2969,-2969,
--2970,-2970,-2970,-2970,-2970,-2971,-2971,-2971,-2971,-2972,-2972,-2972,-2973,-2973,-2973,-2974,-2974,-2974,-2975,-2975,-2975,
--2976,-2976,-2977,-2977,-2977,-2978,-2978,-2979,-2979,-2979,-2980,-2980,-2981,-2981,-2982,-2982,-2983,-2983,-2984,-2984,-2985,
--2985,-2986,-2986,-2987,-2987,-2988,-2988,-2989,-2990,-2990,-2991,-2991,-2992,-2992,-2993,-2993,-2994,-2994,-2995,-2996,-2996,
--2997,-2997,-2998,-2998,-2999,-2999,-3000,-3000,-3001,-3001,-3002,-3003,-3003,-3004,-3004,-3005,-3005,-3005,-3006,-3006,-3007,
--3007,-3008,-3008,-3009,-3009,-3010,-3010,-3010,-3011,-3011,-3011,-3012,-3012,-3013,-3013,-3013,-3014,-3014,-3014,-3014,-3015,
--3015,-3015,-3015,-3016,-3016,-3016,-3016,-3016,-3017,-3017,-3017,-3017,-3017,-3017,-3017,-3018,-3018,-3018,-3018,-3018,-3018,
--3018,-3018,-3018,-3018,-3018,-3018,-3018,-3018,-3018,-3018,-3018,-3018,-3018,-3017,-3017,-3017,-3017,-3017,-3017,-3017,-3016,
--3016,-3016,-3016,-3016,-3015,-3015,-3015,-3015,-3014,-3014,-3014,-3014,-3013,-3013,-3013,-3012,-3012,-3012,-3012,-3011,-3011,
--3010,-3010,-3010,-3009,-3009,-3009,-3008,-3008,-3007,-3007,-3007,-3006,-3006,-3005,-3005,-3004,-3004,-3003,-3003,-3002,-3002,
--3001,-3001,-3000,-3000,-2999,-2998,-2998,-2997,-2997,-2996,-2995,-2995,-2994,-2993,-2993,-2992,-2991,-2991,-2990,-2989,-2989,
--2988,-2987,-2986,-2985,-2985,-2984,-2983,-2982,-2981,-2980,-2980,-2979,-2978,-2977,-2976,-2975,-2974,-2973,-2972,-2971,-2970,
--2969,-2968,-2967,-2966,-2964,-2963,-2962,-2961,-2960,-2959,-2957,-2956,-2955,-2954,-2952,-2951,-2950,-2948,-2947,-2946,-2944,
--2943,-2941,-2940,-2938,-2937,-2936,-2934,-2933,-2931,-2929,-2928,-2926,-2925,-2923,-2922,-2920,-2918,-2917,-2915,-2913,-2912,
--2910,-2908,-2907,-2905,-2903,-2902,-2900,-2898,-2896,-2895,-2893,-2891,-2889,-2888,-2886,-2884,-2883,-2881,-2879,-2877,-2876,
--2874,-2872,-2870,-2869,-2867,-2865,-2863,-2862,-2860,-2858,-2857,-2855,-2853,-2852,-2850,-2849,-2847,-2845,-2844,-2842,-2841,
--2839,-2838,-2836,-2835,-2833,-2832,-2830,-2829,-2828,-2826,-2825,-2824,-2822,-2821,-2820,-2819,-2817,-2816,-2815,-2814,-2813,
--2812,-2811,-2810,-2809,-2808,-2807,-2806,-2805,-2804,-2803,-2802,-2801,-2801,-2800,-2799,-2798,-2798,-2797,-2796,-2796,-2795,
--2795,-2794,-2794,-2793,-2793,-2792,-2792,-2791,-2791,-2791,-2790,-2790,-2790,-2790,-2789,-2789,-2789,-2789,-2789,-2788,-2788,
--2788,-2788,-2788,-2788,-2788,-2788,-2788,-2788,-2788,-2788,-2788,-2788,-2788,-2788,-2788,-2788,-2788,-2788,-2788,-2788,-2788,
--2788,-2789,-2789,-2789,-2789,-2789,-2789,-2789,-2789,-2789,-2789,-2790,-2790,-2790,-2790,-2790,-2790,-2790,-2790,-2790,-2790,
--2790,-2790,-2790,-2790,-2791,-2791,-2791,-2791,-2791,-2791,-2791,-2790,-2790,-2790,-2790,-2790,-2790,-2790,-2790,-2790,-2790,
--2790,-2789,-2789,-2789,-2789,-2789,-2789,-2788,-2788,-2788,-2788,-2787,-2787,-2787,-2787,-2786,-2786,-2786,-2785,-2785,-2785,
--2784,-2784,-2784,-2783,-2783,-2782,-2782,-2781,-2781,-2781,-2780,-2780,-2779,-2779,-2778,-2778,-2777,-2777,-2776,-2776,-2775,
--2775,-2774,-2774,-2773,-2773,-2772,-2771,-2771,-2770,-2770,-2769,-2769,-2768,-2767,-2767,-2766,-2766,-2765,-2764,-2764,-2763,
--2763,-2762,-2761,-2761,-2760,-2760,-2759,-2758,-2758,-2757,-2757,-2756,-2755,-2755,-2754,-2754,-2753,-2752,-2752,-2751,-2750,
--2750,-2749,-2749,-2748,-2747,-2747,-2746,-2746,-2745,-2744,-2744,-2743,-2743,-2742,-2741,-2741,-2740,-2740,-2739,-2738,-2738,
--2737,-2737,-2736,-2735,-2735,-2734,-2734,-2733,-2732,-2732,-2731,-2731,-2730,-2729,-2729,-2728,-2728,-2727,-2727,-2726,-2726,
--2725,-2724,-2724,-2723,-2723,-2722,-2722,-2721,-2721,-2720,-2720,-2719,-2718,-2718,-2717,-2717,-2716,-2716,-2715,-2715,-2714,
--2714,-2713,-2713,-2712,-2712,-2712,-2711,-2711,-2710,-2710,-2709,-2709,-2708,-2788,-2787,-2787,-2787,-2787,-2787,-2786,-2786,
--2786,-2786,-2786,-2786,-2785,-2785,-2785,-2785,-2785,-2785,-2785,-2784,-2784,-2784,-2784,-2784,-2784,-2784,-2784,-2784,-2784,
--2784,-2783,-2783,-2783,-2783,-2783,-2783,-2783,-2783,-2783,-2783,-2783,-2783,-2783,-2783,-2783,-2783,-2783,-2783,-2783,-2783,
--2783,-2783,-2783,-2783,-2784,-2784,-2784,-2784,-2784,-2784,-2784,-2784,-2784,-2784,-2784,-2784,-2785,-2785,-2785,-2785,-2785,
--2785,-2785,-2786,-2786,-2786,-2786,-2786,-2786,-2787,-2787,-2787,-2787,-2787,-2787,-2788,-2788,-2788,-2788,-2788,-2789,-2789,
--2789,-2789,-2790,-2790,-2790,-2790,-2791,-2791,-2791,-2791,-2792,-2792,-2792,-2792,-2793,-2793,-2793,-2794,-2794,-2794,-2794,
--2795,-2795,-2795,-2796,-2796,-2796,-2797,-2797,-2797,-2798,-2798,-2798,-2799,-2799,-2799,-2800,-2800,-2800,-2801,-2801,-2801,
--2802,-2802,-2802,-2803,-2803,-2804,-2804,-2804,-2805,-2805,-2805,-2806,-2806,-2806,-2807,-2807,-2808,-2808,-2808,-2809,-2809,
--2810,-2810,-2810,-2811,-2811,-2811,-2812,-2812,-2813,-2813,-2813,-2814,-2814,-2815,-2815,-2815,-2816,-2816,-2817,-2817,-2817,
--2818,-2818,-2818,-2819,-2819,-2820,-2820,-2820,-2821,-2821,-2821,-2822,-2822,-2823,-2823,-2823,-2824,-2824,-2824,-2825,-2825,
--2825,-2826,-2826,-2827,-2827,-2827,-2828,-2828,-2828,-2829,-2829,-2829,-2830,-2830,-2830,-2831,-2831,-2831,-2831,-2832,-2832,
--2832,-2833,-2833,-2833,-2834,-2834,-2834,-2834,-2835,-2835,-2835,-2836,-2836,-2836,-2836,-2837,-2837,-2837,-2837,-2838,-2838,
--2838,-2838,-2839,-2839,-2839,-2839,-2840,-2840,-2840,-2840,-2840,-2841,-2841,-2841,-2841,-2842,-2842,-2842,-2842,-2842,-2843,
--2843,-2843,-2843,-2843,-2844,-2844,-2844,-2844,-2844,-2845,-2845,-2845,-2845,-2845,-2846,-2846,-2846,-2846,-2846,-2847,-2847,
--2847,-2847,-2848,-2848,-2848,-2848,-2848,-2849,-2849,-2849,-2849,-2850,-2850,-2850,-2850,-2850,-2851,-2851,-2851,-2852,-2852,
--2852,-2852,-2853,-2853,-2853,-2853,-2854,-2854,-2854,-2855,-2855,-2855,-2855,-2856,-2856,-2856,-2857,-2857,-2857,-2858,-2858,
--2859,-2859,-2859,-2860,-2860,-2860,-2861,-2861,-2862,-2862,-2862,-2863,-2863,-2864,-2864,-2865,-2865,-2866,-2866,-2866,-2867,
--2867,-2868,-2868,-2869,-2869,-2870,-2870,-2871,-2872,-2872,-2873,-2873,-2874,-2874,-2875,-2875,-2876,-2877,-2877,-2878,-2878,
--2879,-2880,-2880,-2881,-2882,-2882,-2883,-2884,-2884,-2885,-2886,-2886,-2887,-2888,-2888,-2889,-2890,-2891,-2891,-2892,-2893,
--2894,-2894,-2895,-2896,-2897,-2897,-2898,-2899,-2900,-2900,-2901,-2902,-2903,-2904,-2904,-2905,-2906,-2907,-2908,-2909,-2909,
--2910,-2911,-2912,-2913,-2914,-2915,-2915,-2916,-2917,-2918,-2919,-2920,-2921,-2922,-2922,-2923,-2924,-2925,-2926,-2927,-2928,
--2929,-2930,-2930,-2931,-2932,-2933,-2934,-2935,-2936,-2937,-2938,-2939,-2940,-2941,-2941,-2942,-2943,-2944,-2945,-2946,-2947,
--2948,-2949,-2950,-2951,-2952,-2952,-2953,-2954,-2955,-2956,-2957,-2958,-2959,-2960,-2961,-2962,-2963,-2963,-2964,-2965,-2966,
--2967,-2968,-2969,-2970,-2971,-2971,-2972,-2973,-2974,-2975,-2976,-2977,-2978,-2978,-2979,-2980,-2981,-2982,-2983,-2984,-2984,
--2985,-2986,-2987,-2988,-2989,-2989,-2990,-2991,-2992,-2993,-2993,-2994,-2995,-2996,-2996,-2997,-2998,-2999,-2999,-3000,-3001,
--3002,-3002,-3003,-3004,-3005,-3005,-3006,-3007,-3007,-3008,-3009,-3009,-3010,-3011,-3011,-3012,-3013,-3013,-3014,-3015,-3015,
--3016,-3016,-3017,-3017,-3018,-3019,-3019,-3020,-3020,-3021,-3021,-3022,-3022,-3023,-3023,-3024,-3024,-3025,-3025,-3026,-3026,
--3027,-3027,-3028,-3028,-3028,-3029,-3029,-3030,-3030,-3030,-3031,-3031,-3032,-3032,-3032,-3033,-3033,-3033,-3034,-3034,-3034,
--3034,-3035,-3035,-3035,-3035,-3036,-3036,-3036,-3036,-3037,-3037,-3037,-3037,-3037,-3037,-3038,-3038,-3038,-3038,-3038,-3038,
--3038,-3038,-3039,-3039,-3039,-3039,-3039,-3039,-3039,-3039,-3039,-3039,-3039,-3039,-3039,-3039,-3039,-3039,-3039,-3039,-3039,
--3039,-3039,-3039,-3038,-3038,-3038,-3038,-3038,-3038,-3038,-3038,-3038,-3037,-3037,-3037,-3037,-3037,-3037,-3036,-3036,-3036,
--3036,-3036,-3035,-3035,-3035,-3035,-3034,-3034,-3034,-3034,-3033,-3033,-3033,-3032,-3032,-3032,-3032,-3031,-3031,-3031,-3030,
--3030,-3030,-3029,-3029,-3029,-3028,-3028,-3028,-3027,-3027,-3027,-3026,-3026,-3026,-3025,-3025,-3025,-3024,-3024,-3023,-3023,
--3023,-3022,-3022,-3022,-3021,-3021,-3020,-3020,-3020,-3019,-3019,-3019,-3018,-3018,-3017,-3017,-3017,-3016,-3016,-3016,-3015,
--3015,-3015,-3014,-3014,-3013,-3013,-3013,-3012,-3012,-3012,-3011,-3011,-3011,-3010,-3010,-3010,-3009,-3009,-3009,-3008,-3008,
--3008,-3008,-3007,-3007,-3007,-3006,-3006,-3006,-3006,-3005,-3005,-3005,-3005,-3004,-3004,-3004,-3004,-3003,-3003,-3003,-3003,
--3003,-3002,-3002,-3002,-3002,-3002,-3002,-3001,-3001,-3001,-3001,-3001,-3001,-3000,-3000,-3000,-3000,-3000,-3000,-3000,-3000,
--3000,-3000,-3000,-2999,-2999,-2999,-2999,-2999,-2999,-2999,-2999,-2999,-2999,-2999,-2999,-2999,-2999,-2999,-2999,-2999,-2999,
--2999,-3000,-3000,-3000,-3000,-3000,-3000,-3000,-3000,-3000,-3000,-3000,-3001,-3001,-3001,-3001,-3001,-3001,-3001,-3002,-3002,
--3002,-3002,-3002,-3003,-3003,-3003,-3003,-3003,-3004,-3004,-3004,-3004,-3005,-3005,-3005,-3005,-3006,-3006,-3006,-3007,-3007,
--3007,-3007,-3008,-3008,-3008,-3009,-3009,-3009,-3010,-3010,-3010,-3011,-3011,-3011,-3012,-3012,-3013,-3013,-3013,-3014,-3014,
--3015,-3015,-3015,-3016,-3016,-3017,-3017,-3017,-3018,-3018,-3019,-3019,-3020,-3020,-3020,-3021,-3021,-3022,-3022,-3023,-3023,
--3024,-3024,-3024,-3025,-3025,-3026,-3026,-3027,-3027,-3028,-3028,-3029,-3029,-3030,-3030,-3030,-3031,-3031,-3032,-3032,-3033,
--3033,-3034,-3034,-3035,-3035,-3035,-3036,-3036,-3037,-3037,-3038,-3038,-3039,-3039,-3039,-3040,-3040,-3041,-3041,-3042,-3042,
--3042,-3043,-3043,-3044,-3044,-3044,-3045,-3045,-3045,-3046,-3046,-3047,-3047,-3047,-3048,-3048,-3048,-3048,-3049,-3049,-3049,
--3050,-3050,-3050,-3051,-3051,-3051,-3051,-3052,-3052,-3052,-3052,-3052,-3053,-3053,-3053,-3053,-3053,-3054,-3054,-3054,-3054,
--3054,-3054,-3054,-3054,-3055,-3055,-3055,-3055,-3055,-3055,-3055,-3055,-3055,-3055,-3055,-3055,-3055,-3055,-3055,-3055,-3055,
--3055,-3055,-3055,-3055,-3054,-3054,-3054,-3054,-3054,-3054,-3054,-3054,-3053,-3053,-3053,-3053,-3053,-3052,-3052,-3052,-3052,
--3051,-3051,-3051,-3051,-3050,-3050,-3050,-3049,-3049,-3049,-3048,-3048,-3048,-3047,-3047,-3046,-3046,-3046,-3045,-3045,-3044,
--3044,-3043,-3043,-3042,-3042,-3041,-3041,-3040,-3040,-3039,-3039,-3038,-3037,-3037,-3036,-3036,-3035,-3034,-3034,-3033,-3032,
--3032,-3031,-3030,-3029,-3029,-3028,-3027,-3027,-3026,-3025,-3024,-3023,-3023,-3022,-3021,-3020,-3019,-3018,-3017,-3017,-3016,
--3015,-3014,-3013,-3012,-3011,-3010,-3009,-3008,-3007,-3006,-3005,-3004,-3003,-3002,-3001,-3000,-2998,-2997,-2996,-2995,-2994,
--2993,-2992,-2991,-2989,-2988,-2987,-2986,-2985,-2983,-2982,-2981,-2980,-2978,-2977,-2976,-2974,-2973,-2972,-2971,-2969,-2968,
--2967,-2965,-2964,-2963,-2961,-2960,-2958,-2957,-2956,-2954,-2953,-2951,-2950,-2949,-2947,-2946,-2944,-2943,-2942,-2940,-2939,
--2937,-2936,-2934,-2933,-2931,-2930,-2929,-2927,-2926,-2924,-2923,-2921,-2920,-2919,-2917,-2916,-2914,-2913,-2911,-2910,-2909,
--2907,-2906,-2904,-2903,-2902,-2900,-2899,-2898,-2896,-2895,-2893,-2892,-2891,-2889,-2888,-2887,-2886,-2884,-2883,-2882,-2881,
--2879,-2878,-2877,-2876,-2874,-2873,-2872,-2871,-2870,-2869,-2868,-2866,-2865,-2864,-2863,-2862,-2861,-2860,-2859,-2858,-2857,
--2856,-2855,-2854,-2853,-2853,-2852,-2851,-2850,-2849,-2848,-2847,-2847,-2846,-2845,-2844,-2844,-2843,-2842,-2842,-2841,-2840,
--2840,-2839,-2838,-2838,-2837,-2837,-2836,-2836,-2835,-2835,-2834,-2834,-2833,-2833,-2832,-2832,-2831,-2831,-2831,-2830,-2830,
--2830,-2829,-2829,-2829,-2828,-2828,-2828,-2827,-2827,-2827,-2827,-2826,-2826,-2826,-2826,-2826,-2826,-2825,-2825,-2825,-2825,
--2825,-2825,-2824,-2824,-2824,-2824,-2824,-2824,-2824,-2824,-2824,-2824,-2824,-2823,-2823,-2823,-2823,-2823,-2823,-2823,-2823,
--2823,-2823,-2823,-2823,-2823,-2823,-2823,-2823,-2823,-2823,-2823,-2823,-2823,-2823,-2823,-2823,-2823,-2823,-2822,-2822,-2822,
--2822,-2822,-2822,-2822,-2822,-2822,-2822,-2822,-2822,-2822,-2822,-2822,-2822,-2822,-2822,-2821,-2821,-2821,-2821,-2821,-2821,
--2821,-2821,-2821,-2821,-2820,-2820,-2820,-2820,-2820,-2820,-2820,-2820,-2819,-2819,-2819,-2819,-2819,-2819,-2818,-2818,-2818,
--2818,-2818,-2818,-2817,-2817,-2817,-2817,-2816,-2816,-2816,-2816,-2816,-2815,-2815,-2815,-2815,-2814,-2814,-2814,-2814,-2813,
--2813,-2813,-2813,-2812,-2812,-2812,-2811,-2811,-2811,-2811,-2810,-2810,-2810,-2809,-2809,-2809,-2809,-2808,-2808,-2808,-2807,
--2807,-2807,-2806,-2806,-2806,-2805,-2805,-2805,-2804,-2804,-2804,-2804,-2803,-2803,-2803,-2802,-2802,-2802,-2801,-2801,-2801,
--2800,-2800,-2800,-2799,-2799,-2799,-2798,-2798,-2798,-2797,-2797,-2797,-2796,-2796,-2796,-2796,-2795,-2795,-2795,-2794,-2794,
--2794,-2794,-2793,-2793,-2793,-2792,-2792,-2792,-2792,-2791,-2791,-2791,-2791,-2790,-2790,-2790,-2790,-2789,-2789,-2789,-2789,
--2788,-2788,-2788,-2788,-2788,-2896,-2896,-2896,-2896,-2896,-2896,-2897,-2897,-2897,-2897,-2897,-2897,-2897,-2897,-2898,-2898,
--2898,-2898,-2898,-2898,-2898,-2898,-2899,-2899,-2899,-2899,-2899,-2899,-2899,-2900,-2900,-2900,-2900,-2900,-2900,-2900,-2901,
--2901,-2901,-2901,-2901,-2901,-2902,-2902,-2902,-2902,-2902,-2902,-2903,-2903,-2903,-2903,-2903,-2903,-2904,-2904,-2904,-2904,
--2904,-2905,-2905,-2905,-2905,-2905,-2906,-2906,-2906,-2906,-2906,-2907,-2907,-2907,-2907,-2907,-2908,-2908,-2908,-2908,-2908,
--2909,-2909,-2909,-2909,-2910,-2910,-2910,-2910,-2910,-2911,-2911,-2911,-2911,-2912,-2912,-2912,-2912,-2913,-2913,-2913,-2913,
--2913,-2914,-2914,-2914,-2914,-2915,-2915,-2915,-2915,-2916,-2916,-2916,-2916,-2917,-2917,-2917,-2917,-2917,-2918,-2918,-2918,
--2918,-2919,-2919,-2919,-2919,-2920,-2920,-2920,-2920,-2921,-2921,-2921,-2921,-2921,-2922,-2922,-2922,-2922,-2923,-2923,-2923,
--2923,-2924,-2924,-2924,-2924,-2924,-2925,-2925,-2925,-2925,-2925,-2926,-2926,-2926,-2926,-2927,-2927,-2927,-2927,-2927,-2928,
--2928,-2928,-2928,-2928,-2928,-2929,-2929,-2929,-2929,-2929,-2930,-2930,-2930,-2930,-2930,-2930,-2931,-2931,-2931,-2931,-2931,
--2931,-2932,-2932,-2932,-2932,-2932,-2932,-2932,-2933,-2933,-2933,-2933,-2933,-2933,-2933,-2934,-2934,-2934,-2934,-2934,-2934,
--2934,-2934,-2934,-2935,-2935,-2935,-2935,-2935,-2935,-2935,-2935,-2935,-2935,-2935,-2936,-2936,-2936,-2936,-2936,-2936,-2936,
--2936,-2936,-2936,-2936,-2936,-2936,-2936,-2936,-2936,-2937,-2937,-2937,-2937,-2937,-2937,-2937,-2937,-2937,-2937,-2937,-2937,
--2937,-2937,-2937,-2937,-2937,-2937,-2937,-2937,-2937,-2937,-2937,-2937,-2937,-2937,-2937,-2937,-2937,-2937,-2937,-2937,-2937,
--2937,-2937,-2937,-2937,-2938,-2938,-2938,-2938,-2938,-2938,-2938,-2938,-2938,-2938,-2938,-2938,-2938,-2938,-2938,-2938,-2938,
--2938,-2938,-2938,-2938,-2938,-2938,-2938,-2938,-2938,-2938,-2938,-2938,-2938,-2938,-2938,-2939,-2939,-2939,-2939,-2939,-2939,
--2939,-2939,-2939,-2939,-2939,-2939,-2939,-2940,-2940,-2940,-2940,-2940,-2940,-2940,-2940,-2940,-2940,-2941,-2941,-2941,-2941,
--2941,-2941,-2941,-2942,-2942,-2942,-2942,-2942,-2942,-2943,-2943,-2943,-2943,-2943,-2943,-2944,-2944,-2944,-2944,-2944,-2945,
--2945,-2945,-2945,-2946,-2946,-2946,-2946,-2947,-2947,-2947,-2947,-2948,-2948,-2948,-2948,-2949,-2949,-2949,-2950,-2950,-2950,
--2950,-2951,-2951,-2951,-2952,-2952,-2952,-2953,-2953,-2953,-2954,-2954,-2955,-2955,-2955,-2956,-2956,-2956,-2957,-2957,-2958,
--2958,-2958,-2959,-2959,-2960,-2960,-2960,-2961,-2961,-2962,-2962,-2963,-2963,-2964,-2964,-2964,-2965,-2965,-2966,-2966,-2967,
--2967,-2968,-2968,-2969,-2969,-2970,-2970,-2971,-2971,-2972,-2972,-2973,-2973,-2974,-2974,-2975,-2975,-2976,-2976,-2977,-2977,
--2978,-2978,-2979,-2979,-2980,-2980,-2981,-2981,-2982,-2983,-2983,-2984,-2984,-2985,-2985,-2986,-2986,-2987,-2987,-2988,-2989,
--2989,-2990,-2990,-2991,-2991,-2992,-2992,-2993,-2994,-2994,-2995,-2995,-2996,-2996,-2997,-2997,-2998,-2998,-2999,-3000,-3000,
--3001,-3001,-3002,-3002,-3003,-3003,-3004,-3004,-3005,-3005,-3006,-3007,-3007,-3008,-3008,-3009,-3009,-3010,-3010,-3011,-3011,
--3012,-3012,-3013,-3013,-3014,-3014,-3015,-3015,-3016,-3016,-3017,-3017,-3018,-3018,-3019,-3019,-3020,-3020,-3021,-3021,-3022,
--3022,-3022,-3023,-3023,-3024,-3024,-3025,-3025,-3026,-3026,-3026,-3027,-3027,-3028,-3028,-3028,-3029,-3029,-3030,-3030,-3030,
--3031,-3031,-3032,-3032,-3032,-3033,-3033,-3033,-3034,-3034,-3034,-3035,-3035,-3035,-3036,-3036,-3036,-3037,-3037,-3037,-3038,
--3038,-3038,-3039,-3039,-3039,-3039,-3040,-3040,-3040,-3040,-3041,-3041,-3041,-3041,-3042,-3042,-3042,-3042,-3043,-3043,-3043,
--3043,-3043,-3044,-3044,-3044,-3044,-3044,-3045,-3045,-3045,-3045,-3045,-3046,-3046,-3046,-3046,-3046,-3046,-3046,-3047,-3047,
--3047,-3047,-3047,-3047,-3047,-3047,-3047,-3048,-3048,-3048,-3048,-3048,-3048,-3048,-3048,-3048,-3048,-3048,-3049,-3049,-3049,
--3049,-3049,-3049,-3049,-3049,-3049,-3049,-3049,-3049,-3049,-3049,-3049,-3049,-3049,-3049,-3049,-3049,-3049,-3049,-3049,-3049,
--3049,-3049,-3049,-3049,-3049,-3049,-3050,-3050,-3050,-3050,-3050,-3050,-3050,-3050,-3049,-3049,-3049,-3049,-3049,-3049,-3049,
+-2689,-2689,-2690,-2690,-2690,-2690,-2690,-2690,-2690,-2690,-2690,-2691,-2691,-2691,-2691,-2691,-2691,-2692,-2692,-2692,-2692,
+-2692,-2693,-2693,-2693,-2693,-2694,-2694,-2694,-2694,-2695,-2695,-2695,-2696,-2696,-2696,-2697,-2697,-2697,-2698,-2698,-2698,
+-2699,-2699,-2699,-2700,-2700,-2701,-2701,-2701,-2702,-2702,-2703,-2703,-2704,-2704,-2705,-2705,-2705,-2706,-2706,-2707,-2707,
+-2708,-2708,-2709,-2709,-2710,-2710,-2711,-2711,-2712,-2712,-2713,-2714,-2714,-2715,-2715,-2716,-2716,-2717,-2717,-2718,-2718,
+-2719,-2720,-2720,-2721,-2721,-2722,-2722,-2723,-2723,-2724,-2725,-2725,-2726,-2726,-2727,-2727,-2728,-2728,-2729,-2730,-2730,
+-2731,-2731,-2732,-2732,-2733,-2733,-2734,-2734,-2735,-2735,-2736,-2737,-2737,-2738,-2738,-2739,-2739,-2740,-2740,-2741,-2741,
+-2742,-2742,-2743,-2743,-2744,-2744,-2745,-2745,-2746,-2746,-2746,-2747,-2747,-2748,-2748,-2749,-2749,-2750,-2750,-2751,-2751,
+-2752,-2752,-2753,-2753,-2754,-2754,-2755,-2755,-2755,-2756,-2756,-2757,-2757,-2758,-2758,-2759,-2759,-2760,-2760,-2761,-2761,
+-2762,-2762,-2763,-2763,-2764,-2764,-2765,-2765,-2766,-2766,-2767,-2768,-2768,-2769,-2769,-2770,-2770,-2771,-2772,-2772,-2773,
+-2773,-2774,-2775,-2775,-2776,-2777,-2777,-2778,-2778,-2779,-2780,-2781,-2781,-2782,-2783,-2783,-2784,-2785,-2786,-2786,-2787,
+-2788,-2789,-2789,-2790,-2791,-2792,-2793,-2794,-2794,-2795,-2796,-2797,-2798,-2799,-2800,-2801,-2801,-2802,-2803,-2804,-2805,
+-2806,-2807,-2808,-2809,-2810,-2811,-2812,-2813,-2814,-2815,-2816,-2817,-2818,-2819,-2820,-2821,-2822,-2823,-2825,-2826,-2827,
+-2828,-2829,-2830,-2831,-2832,-2833,-2835,-2836,-2837,-2838,-2839,-2840,-2841,-2843,-2844,-2845,-2846,-2847,-2849,-2850,-2851,
+-2852,-2853,-2855,-2856,-2857,-2858,-2860,-2861,-2862,-2863,-2865,-2866,-2867,-2868,-2870,-2871,-2872,-2873,-2875,-2876,-2877,
+-2878,-2880,-2881,-2882,-2883,-2885,-2886,-2887,-2889,-2890,-2891,-2892,-2894,-2895,-2896,-2897,-2899,-2900,-2901,-2903,-2904,
+-2905,-2906,-2908,-2909,-2910,-2912,-2913,-2914,-2915,-2917,-2918,-2919,-2920,-2922,-2923,-2924,-2926,-2927,-2928,-2929,-2931,
+-2932,-2933,-2934,-2936,-2937,-2938,-2939,-2941,-2942,-2943,-2944,-2946,-2947,-2948,-2949,-2950,-2952,-2953,-2954,-2955,-2956,
+-2958,-2959,-2960,-2961,-2962,-2964,-2965,-2966,-2967,-2968,-2970,-2971,-2972,-2973,-2974,-2975,-2976,-2978,-2979,-2980,-2981,
+-2982,-2983,-2984,-2985,-2987,-2988,-2989,-2990,-2991,-2992,-2993,-2994,-2995,-2996,-2997,-2998,-2999,-3000,-3001,-3002,-3003,
+-3004,-3005,-3006,-3007,-3008,-3009,-3010,-3011,-3012,-3013,-3014,-3015,-3016,-3017,-3018,-3019,-3020,-3020,-3021,-3022,-3023,
+-3024,-3025,-3026,-3027,-3027,-3028,-3029,-3030,-3031,-3031,-3032,-3033,-3034,-3034,-3035,-3036,-3037,-3037,-3038,-3039,-3039,
+-3040,-3041,-3042,-3042,-3043,-3043,-3044,-3045,-3045,-3046,-3047,-3047,-3048,-3048,-3049,-3049,-3050,-3050,-3051,-3051,-3052,
+-3052,-3053,-3053,-3054,-3054,-3055,-3055,-3055,-3056,-3056,-3057,-3057,-3057,-3058,-3058,-3058,-3058,-3059,-3059,-3059,-3059,
+-3060,-3060,-3060,-3060,-3061,-3061,-3061,-3061,-3061,-3061,-3061,-3061,-3061,-3062,-3062,-3062,-3062,-3062,-3062,-3062,-3062,
+-3062,-3061,-3061,-3061,-3061,-3061,-3061,-3061,-3061,-3061,-3060,-3060,-3060,-3060,-3059,-3059,-3059,-3059,-3058,-3058,-3058,
+-3057,-3057,-3057,-3056,-3056,-3056,-3055,-3055,-3054,-3054,-3054,-3053,-3053,-3052,-3052,-3051,-3051,-3050,-3050,-3049,-3048,
+-3048,-3047,-3047,-3046,-3046,-3045,-3044,-3044,-3043,-3042,-3042,-3041,-3040,-3040,-3039,-3038,-3038,-3037,-3036,-3036,-3035,
+-3034,-3034,-3033,-3032,-3031,-3031,-3030,-3029,-3028,-3028,-3027,-3026,-3025,-3025,-3024,-3023,-3022,-3022,-3021,-3020,-3019,
+-3019,-3018,-3017,-3016,-3016,-3015,-3014,-3013,-3013,-3012,-3011,-3010,-3010,-3009,-3008,-3007,-3007,-3006,-3005,-3005,-3004,
+-3003,-3003,-3002,-3001,-3000,-3000,-2999,-2998,-2998,-2997,-2997,-2996,-2995,-2995,-2994,-2993,-2993,-2992,-2992,-2991,-2990,
+-2990,-2989,-2989,-2988,-2988,-2987,-2987,-2986,-2986,-2985,-2985,-2984,-2984,-2983,-2983,-2982,-2982,-2981,-2981,-2980,-2980,
+-2979,-2979,-2979,-2978,-2978,-2977,-2977,-2977,-2976,-2976,-2976,-2975,-2975,-2975,-2974,-2974,-2974,-2973,-2973,-2973,-2972,
+-2972,-2972,-2972,-2971,-2971,-2971,-2971,-2970,-2970,-2970,-2970,-2970,-2969,-2969,-2969,-2969,-2969,-2969,-2969,-2968,-2968,
+-2968,-2968,-2968,-2968,-2968,-2968,-2968,-2968,-2968,-2968,-2968,-2968,-2968,-2968,-2968,-2968,-2968,-2968,-2968,-2968,-2968,
+-2968,-2968,-2968,-2968,-2968,-2968,-2968,-2969,-2969,-2969,-2969,-2969,-2969,-2970,-2970,-2970,-2970,-2970,-2971,-2971,-2971,
+-2971,-2972,-2972,-2972,-2973,-2973,-2973,-2974,-2974,-2974,-2975,-2975,-2975,-2976,-2976,-2977,-2977,-2977,-2978,-2978,-2979,
+-2979,-2979,-2980,-2980,-2981,-2981,-2982,-2982,-2983,-2983,-2984,-2984,-2985,-2985,-2986,-2986,-2987,-2987,-2988,-2988,-2989,
+-2990,-2990,-2991,-2991,-2992,-2992,-2993,-2993,-2994,-2994,-2995,-2996,-2996,-2997,-2997,-2998,-2998,-2999,-2999,-3000,-3000,
+-3001,-3001,-3002,-3003,-3003,-3004,-3004,-3005,-3005,-3005,-3006,-3006,-3007,-3007,-3008,-3008,-3009,-3009,-3010,-3010,-3010,
+-3011,-3011,-3011,-3012,-3012,-3013,-3013,-3013,-3014,-3014,-3014,-3014,-3015,-3015,-3015,-3015,-3016,-3016,-3016,-3016,-3016,
+-3017,-3017,-3017,-3017,-3017,-3017,-3017,-3018,-3018,-3018,-3018,-3018,-3018,-3018,-3018,-3018,-3018,-3018,-3018,-3018,-3018,
+-3018,-3018,-3018,-3018,-3018,-3017,-3017,-3017,-3017,-3017,-3017,-3017,-3016,-3016,-3016,-3016,-3016,-3015,-3015,-3015,-3015,
+-3014,-3014,-3014,-3014,-3013,-3013,-3013,-3012,-3012,-3012,-3012,-3011,-3011,-3010,-3010,-3010,-3009,-3009,-3009,-3008,-3008,
+-3007,-3007,-3007,-3006,-3006,-3005,-3005,-3004,-3004,-3003,-3003,-3002,-3002,-3001,-3001,-3000,-3000,-2999,-2998,-2998,-2997,
+-2997,-2996,-2995,-2995,-2994,-2993,-2993,-2992,-2991,-2991,-2990,-2989,-2989,-2988,-2987,-2986,-2985,-2985,-2984,-2983,-2982,
+-2981,-2980,-2980,-2979,-2978,-2977,-2976,-2975,-2974,-2973,-2972,-2971,-2970,-2969,-2968,-2967,-2966,-2964,-2963,-2962,-2961,
+-2960,-2959,-2957,-2956,-2955,-2954,-2952,-2951,-2950,-2948,-2947,-2946,-2944,-2943,-2941,-2940,-2938,-2937,-2936,-2934,-2933,
+-2931,-2929,-2928,-2926,-2925,-2923,-2922,-2920,-2918,-2917,-2915,-2913,-2912,-2910,-2908,-2907,-2905,-2903,-2902,-2900,-2898,
+-2896,-2895,-2893,-2891,-2889,-2888,-2886,-2884,-2883,-2881,-2879,-2877,-2876,-2874,-2872,-2870,-2869,-2867,-2865,-2863,-2862,
+-2860,-2858,-2857,-2855,-2853,-2852,-2850,-2849,-2847,-2845,-2844,-2842,-2841,-2839,-2838,-2836,-2835,-2833,-2832,-2830,-2829,
+-2828,-2826,-2825,-2824,-2822,-2821,-2820,-2819,-2817,-2816,-2815,-2814,-2813,-2812,-2811,-2810,-2809,-2808,-2807,-2806,-2805,
+-2804,-2803,-2802,-2801,-2801,-2800,-2799,-2798,-2798,-2797,-2796,-2796,-2795,-2795,-2794,-2794,-2793,-2793,-2792,-2792,-2791,
+-2791,-2791,-2790,-2790,-2790,-2790,-2789,-2789,-2789,-2789,-2789,-2788,-2788,-2788,-2788,-2788,-2788,-2788,-2788,-2788,-2788,
+-2788,-2788,-2788,-2788,-2788,-2788,-2788,-2788,-2788,-2788,-2788,-2788,-2788,-2788,-2789,-2789,-2789,-2789,-2789,-2789,-2789,
+-2789,-2789,-2789,-2790,-2790,-2790,-2790,-2790,-2790,-2790,-2790,-2790,-2790,-2790,-2790,-2790,-2790,-2791,-2791,-2791,-2791,
+-2791,-2791,-2791,-2790,-2790,-2790,-2790,-2790,-2790,-2790,-2790,-2790,-2790,-2790,-2789,-2789,-2789,-2789,-2789,-2789,-2788,
+-2788,-2788,-2788,-2787,-2787,-2787,-2787,-2786,-2786,-2786,-2785,-2785,-2785,-2784,-2784,-2784,-2783,-2783,-2782,-2782,-2781,
+-2781,-2781,-2780,-2780,-2779,-2779,-2778,-2778,-2777,-2777,-2776,-2776,-2775,-2775,-2774,-2774,-2773,-2773,-2772,-2771,-2771,
+-2770,-2770,-2769,-2769,-2768,-2767,-2767,-2766,-2766,-2765,-2764,-2764,-2763,-2763,-2762,-2761,-2761,-2760,-2760,-2759,-2758,
+-2758,-2757,-2757,-2756,-2755,-2755,-2754,-2754,-2753,-2752,-2752,-2751,-2750,-2750,-2749,-2749,-2748,-2747,-2747,-2746,-2746,
+-2745,-2744,-2744,-2743,-2743,-2742,-2741,-2741,-2740,-2740,-2739,-2738,-2738,-2737,-2737,-2736,-2735,-2735,-2734,-2734,-2733,
+-2732,-2732,-2731,-2731,-2730,-2729,-2729,-2728,-2728,-2727,-2727,-2726,-2726,-2725,-2724,-2724,-2723,-2723,-2722,-2722,-2721,
+-2721,-2720,-2720,-2719,-2718,-2718,-2717,-2717,-2716,-2716,-2715,-2715,-2714,-2714,-2713,-2713,-2712,-2712,-2712,-2711,-2711,
+-2710,-2710,-2709,-2709,-2708,-2788,-2787,-2787,-2787,-2787,-2787,-2786,-2786,-2786,-2786,-2786,-2786,-2785,-2785,-2785,-2785,
+-2785,-2785,-2785,-2784,-2784,-2784,-2784,-2784,-2784,-2784,-2784,-2784,-2784,-2784,-2783,-2783,-2783,-2783,-2783,-2783,-2783,
+-2783,-2783,-2783,-2783,-2783,-2783,-2783,-2783,-2783,-2783,-2783,-2783,-2783,-2783,-2783,-2783,-2783,-2784,-2784,-2784,-2784,
+-2784,-2784,-2784,-2784,-2784,-2784,-2784,-2784,-2785,-2785,-2785,-2785,-2785,-2785,-2785,-2786,-2786,-2786,-2786,-2786,-2786,
+-2787,-2787,-2787,-2787,-2787,-2787,-2788,-2788,-2788,-2788,-2788,-2789,-2789,-2789,-2789,-2790,-2790,-2790,-2790,-2791,-2791,
+-2791,-2791,-2792,-2792,-2792,-2792,-2793,-2793,-2793,-2794,-2794,-2794,-2794,-2795,-2795,-2795,-2796,-2796,-2796,-2797,-2797,
+-2797,-2798,-2798,-2798,-2799,-2799,-2799,-2800,-2800,-2800,-2801,-2801,-2801,-2802,-2802,-2802,-2803,-2803,-2804,-2804,-2804,
+-2805,-2805,-2805,-2806,-2806,-2806,-2807,-2807,-2808,-2808,-2808,-2809,-2809,-2810,-2810,-2810,-2811,-2811,-2811,-2812,-2812,
+-2813,-2813,-2813,-2814,-2814,-2815,-2815,-2815,-2816,-2816,-2817,-2817,-2817,-2818,-2818,-2818,-2819,-2819,-2820,-2820,-2820,
+-2821,-2821,-2821,-2822,-2822,-2823,-2823,-2823,-2824,-2824,-2824,-2825,-2825,-2825,-2826,-2826,-2827,-2827,-2827,-2828,-2828,
+-2828,-2829,-2829,-2829,-2830,-2830,-2830,-2831,-2831,-2831,-2831,-2832,-2832,-2832,-2833,-2833,-2833,-2834,-2834,-2834,-2834,
+-2835,-2835,-2835,-2836,-2836,-2836,-2836,-2837,-2837,-2837,-2837,-2838,-2838,-2838,-2838,-2839,-2839,-2839,-2839,-2840,-2840,
+-2840,-2840,-2840,-2841,-2841,-2841,-2841,-2842,-2842,-2842,-2842,-2842,-2843,-2843,-2843,-2843,-2843,-2844,-2844,-2844,-2844,
+-2844,-2845,-2845,-2845,-2845,-2845,-2846,-2846,-2846,-2846,-2846,-2847,-2847,-2847,-2847,-2848,-2848,-2848,-2848,-2848,-2849,
+-2849,-2849,-2849,-2850,-2850,-2850,-2850,-2850,-2851,-2851,-2851,-2852,-2852,-2852,-2852,-2853,-2853,-2853,-2853,-2854,-2854,
+-2854,-2855,-2855,-2855,-2855,-2856,-2856,-2856,-2857,-2857,-2857,-2858,-2858,-2859,-2859,-2859,-2860,-2860,-2860,-2861,-2861,
+-2862,-2862,-2862,-2863,-2863,-2864,-2864,-2865,-2865,-2866,-2866,-2866,-2867,-2867,-2868,-2868,-2869,-2869,-2870,-2870,-2871,
+-2872,-2872,-2873,-2873,-2874,-2874,-2875,-2875,-2876,-2877,-2877,-2878,-2878,-2879,-2880,-2880,-2881,-2882,-2882,-2883,-2884,
+-2884,-2885,-2886,-2886,-2887,-2888,-2888,-2889,-2890,-2891,-2891,-2892,-2893,-2894,-2894,-2895,-2896,-2897,-2897,-2898,-2899,
+-2900,-2900,-2901,-2902,-2903,-2904,-2904,-2905,-2906,-2907,-2908,-2909,-2909,-2910,-2911,-2912,-2913,-2914,-2915,-2915,-2916,
+-2917,-2918,-2919,-2920,-2921,-2922,-2922,-2923,-2924,-2925,-2926,-2927,-2928,-2929,-2930,-2930,-2931,-2932,-2933,-2934,-2935,
+-2936,-2937,-2938,-2939,-2940,-2941,-2941,-2942,-2943,-2944,-2945,-2946,-2947,-2948,-2949,-2950,-2951,-2952,-2952,-2953,-2954,
+-2955,-2956,-2957,-2958,-2959,-2960,-2961,-2962,-2963,-2963,-2964,-2965,-2966,-2967,-2968,-2969,-2970,-2971,-2971,-2972,-2973,
+-2974,-2975,-2976,-2977,-2978,-2978,-2979,-2980,-2981,-2982,-2983,-2984,-2984,-2985,-2986,-2987,-2988,-2989,-2989,-2990,-2991,
+-2992,-2993,-2993,-2994,-2995,-2996,-2996,-2997,-2998,-2999,-2999,-3000,-3001,-3002,-3002,-3003,-3004,-3005,-3005,-3006,-3007,
+-3007,-3008,-3009,-3009,-3010,-3011,-3011,-3012,-3013,-3013,-3014,-3015,-3015,-3016,-3016,-3017,-3017,-3018,-3019,-3019,-3020,
+-3020,-3021,-3021,-3022,-3022,-3023,-3023,-3024,-3024,-3025,-3025,-3026,-3026,-3027,-3027,-3028,-3028,-3028,-3029,-3029,-3030,
+-3030,-3030,-3031,-3031,-3032,-3032,-3032,-3033,-3033,-3033,-3034,-3034,-3034,-3034,-3035,-3035,-3035,-3035,-3036,-3036,-3036,
+-3036,-3037,-3037,-3037,-3037,-3037,-3037,-3038,-3038,-3038,-3038,-3038,-3038,-3038,-3038,-3039,-3039,-3039,-3039,-3039,-3039,
+-3039,-3039,-3039,-3039,-3039,-3039,-3039,-3039,-3039,-3039,-3039,-3039,-3039,-3039,-3039,-3039,-3038,-3038,-3038,-3038,-3038,
+-3038,-3038,-3038,-3038,-3037,-3037,-3037,-3037,-3037,-3037,-3036,-3036,-3036,-3036,-3036,-3035,-3035,-3035,-3035,-3034,-3034,
+-3034,-3034,-3033,-3033,-3033,-3032,-3032,-3032,-3032,-3031,-3031,-3031,-3030,-3030,-3030,-3029,-3029,-3029,-3028,-3028,-3028,
+-3027,-3027,-3027,-3026,-3026,-3026,-3025,-3025,-3025,-3024,-3024,-3023,-3023,-3023,-3022,-3022,-3022,-3021,-3021,-3020,-3020,
+-3020,-3019,-3019,-3019,-3018,-3018,-3017,-3017,-3017,-3016,-3016,-3016,-3015,-3015,-3015,-3014,-3014,-3013,-3013,-3013,-3012,
+-3012,-3012,-3011,-3011,-3011,-3010,-3010,-3010,-3009,-3009,-3009,-3008,-3008,-3008,-3008,-3007,-3007,-3007,-3006,-3006,-3006,
+-3006,-3005,-3005,-3005,-3005,-3004,-3004,-3004,-3004,-3003,-3003,-3003,-3003,-3003,-3002,-3002,-3002,-3002,-3002,-3002,-3001,
+-3001,-3001,-3001,-3001,-3001,-3000,-3000,-3000,-3000,-3000,-3000,-3000,-3000,-3000,-3000,-3000,-2999,-2999,-2999,-2999,-2999,
+-2999,-2999,-2999,-2999,-2999,-2999,-2999,-2999,-2999,-2999,-2999,-2999,-2999,-2999,-3000,-3000,-3000,-3000,-3000,-3000,-3000,
+-3000,-3000,-3000,-3000,-3001,-3001,-3001,-3001,-3001,-3001,-3001,-3002,-3002,-3002,-3002,-3002,-3003,-3003,-3003,-3003,-3003,
+-3004,-3004,-3004,-3004,-3005,-3005,-3005,-3005,-3006,-3006,-3006,-3007,-3007,-3007,-3007,-3008,-3008,-3008,-3009,-3009,-3009,
+-3010,-3010,-3010,-3011,-3011,-3011,-3012,-3012,-3013,-3013,-3013,-3014,-3014,-3015,-3015,-3015,-3016,-3016,-3017,-3017,-3017,
+-3018,-3018,-3019,-3019,-3020,-3020,-3020,-3021,-3021,-3022,-3022,-3023,-3023,-3024,-3024,-3024,-3025,-3025,-3026,-3026,-3027,
+-3027,-3028,-3028,-3029,-3029,-3030,-3030,-3030,-3031,-3031,-3032,-3032,-3033,-3033,-3034,-3034,-3035,-3035,-3035,-3036,-3036,
+-3037,-3037,-3038,-3038,-3039,-3039,-3039,-3040,-3040,-3041,-3041,-3042,-3042,-3042,-3043,-3043,-3044,-3044,-3044,-3045,-3045,
+-3045,-3046,-3046,-3047,-3047,-3047,-3048,-3048,-3048,-3048,-3049,-3049,-3049,-3050,-3050,-3050,-3051,-3051,-3051,-3051,-3052,
+-3052,-3052,-3052,-3052,-3053,-3053,-3053,-3053,-3053,-3054,-3054,-3054,-3054,-3054,-3054,-3054,-3054,-3055,-3055,-3055,-3055,
+-3055,-3055,-3055,-3055,-3055,-3055,-3055,-3055,-3055,-3055,-3055,-3055,-3055,-3055,-3055,-3055,-3055,-3054,-3054,-3054,-3054,
+-3054,-3054,-3054,-3054,-3053,-3053,-3053,-3053,-3053,-3052,-3052,-3052,-3052,-3051,-3051,-3051,-3051,-3050,-3050,-3050,-3049,
+-3049,-3049,-3048,-3048,-3048,-3047,-3047,-3046,-3046,-3046,-3045,-3045,-3044,-3044,-3043,-3043,-3042,-3042,-3041,-3041,-3040,
+-3040,-3039,-3039,-3038,-3037,-3037,-3036,-3036,-3035,-3034,-3034,-3033,-3032,-3032,-3031,-3030,-3029,-3029,-3028,-3027,-3027,
+-3026,-3025,-3024,-3023,-3023,-3022,-3021,-3020,-3019,-3018,-3017,-3017,-3016,-3015,-3014,-3013,-3012,-3011,-3010,-3009,-3008,
+-3007,-3006,-3005,-3004,-3003,-3002,-3001,-3000,-2998,-2997,-2996,-2995,-2994,-2993,-2992,-2991,-2989,-2988,-2987,-2986,-2985,
+-2983,-2982,-2981,-2980,-2978,-2977,-2976,-2974,-2973,-2972,-2971,-2969,-2968,-2967,-2965,-2964,-2963,-2961,-2960,-2958,-2957,
+-2956,-2954,-2953,-2951,-2950,-2949,-2947,-2946,-2944,-2943,-2942,-2940,-2939,-2937,-2936,-2934,-2933,-2931,-2930,-2929,-2927,
+-2926,-2924,-2923,-2921,-2920,-2919,-2917,-2916,-2914,-2913,-2911,-2910,-2909,-2907,-2906,-2904,-2903,-2902,-2900,-2899,-2898,
+-2896,-2895,-2893,-2892,-2891,-2889,-2888,-2887,-2886,-2884,-2883,-2882,-2881,-2879,-2878,-2877,-2876,-2874,-2873,-2872,-2871,
+-2870,-2869,-2868,-2866,-2865,-2864,-2863,-2862,-2861,-2860,-2859,-2858,-2857,-2856,-2855,-2854,-2853,-2853,-2852,-2851,-2850,
+-2849,-2848,-2847,-2847,-2846,-2845,-2844,-2844,-2843,-2842,-2842,-2841,-2840,-2840,-2839,-2838,-2838,-2837,-2837,-2836,-2836,
+-2835,-2835,-2834,-2834,-2833,-2833,-2832,-2832,-2831,-2831,-2831,-2830,-2830,-2830,-2829,-2829,-2829,-2828,-2828,-2828,-2827,
+-2827,-2827,-2827,-2826,-2826,-2826,-2826,-2826,-2826,-2825,-2825,-2825,-2825,-2825,-2825,-2824,-2824,-2824,-2824,-2824,-2824,
+-2824,-2824,-2824,-2824,-2824,-2823,-2823,-2823,-2823,-2823,-2823,-2823,-2823,-2823,-2823,-2823,-2823,-2823,-2823,-2823,-2823,
+-2823,-2823,-2823,-2823,-2823,-2823,-2823,-2823,-2823,-2823,-2822,-2822,-2822,-2822,-2822,-2822,-2822,-2822,-2822,-2822,-2822,
+-2822,-2822,-2822,-2822,-2822,-2822,-2822,-2821,-2821,-2821,-2821,-2821,-2821,-2821,-2821,-2821,-2821,-2820,-2820,-2820,-2820,
+-2820,-2820,-2820,-2820,-2819,-2819,-2819,-2819,-2819,-2819,-2818,-2818,-2818,-2818,-2818,-2818,-2817,-2817,-2817,-2817,-2816,
+-2816,-2816,-2816,-2816,-2815,-2815,-2815,-2815,-2814,-2814,-2814,-2814,-2813,-2813,-2813,-2813,-2812,-2812,-2812,-2811,-2811,
+-2811,-2811,-2810,-2810,-2810,-2809,-2809,-2809,-2809,-2808,-2808,-2808,-2807,-2807,-2807,-2806,-2806,-2806,-2805,-2805,-2805,
+-2804,-2804,-2804,-2804,-2803,-2803,-2803,-2802,-2802,-2802,-2801,-2801,-2801,-2800,-2800,-2800,-2799,-2799,-2799,-2798,-2798,
+-2798,-2797,-2797,-2797,-2796,-2796,-2796,-2796,-2795,-2795,-2795,-2794,-2794,-2794,-2794,-2793,-2793,-2793,-2792,-2792,-2792,
+-2792,-2791,-2791,-2791,-2791,-2790,-2790,-2790,-2790,-2789,-2789,-2789,-2789,-2788,-2788,-2788,-2788,-2788,-2896,-2896,-2896,
+-2896,-2896,-2896,-2897,-2897,-2897,-2897,-2897,-2897,-2897,-2897,-2898,-2898,-2898,-2898,-2898,-2898,-2898,-2898,-2899,-2899,
+-2899,-2899,-2899,-2899,-2899,-2900,-2900,-2900,-2900,-2900,-2900,-2900,-2901,-2901,-2901,-2901,-2901,-2901,-2902,-2902,-2902,
+-2902,-2902,-2902,-2903,-2903,-2903,-2903,-2903,-2903,-2904,-2904,-2904,-2904,-2904,-2905,-2905,-2905,-2905,-2905,-2906,-2906,
+-2906,-2906,-2906,-2907,-2907,-2907,-2907,-2907,-2908,-2908,-2908,-2908,-2908,-2909,-2909,-2909,-2909,-2910,-2910,-2910,-2910,
+-2910,-2911,-2911,-2911,-2911,-2912,-2912,-2912,-2912,-2913,-2913,-2913,-2913,-2913,-2914,-2914,-2914,-2914,-2915,-2915,-2915,
+-2915,-2916,-2916,-2916,-2916,-2917,-2917,-2917,-2917,-2917,-2918,-2918,-2918,-2918,-2919,-2919,-2919,-2919,-2920,-2920,-2920,
+-2920,-2921,-2921,-2921,-2921,-2921,-2922,-2922,-2922,-2922,-2923,-2923,-2923,-2923,-2924,-2924,-2924,-2924,-2924,-2925,-2925,
+-2925,-2925,-2925,-2926,-2926,-2926,-2926,-2927,-2927,-2927,-2927,-2927,-2928,-2928,-2928,-2928,-2928,-2928,-2929,-2929,-2929,
+-2929,-2929,-2930,-2930,-2930,-2930,-2930,-2930,-2931,-2931,-2931,-2931,-2931,-2931,-2932,-2932,-2932,-2932,-2932,-2932,-2932,
+-2933,-2933,-2933,-2933,-2933,-2933,-2933,-2934,-2934,-2934,-2934,-2934,-2934,-2934,-2934,-2934,-2935,-2935,-2935,-2935,-2935,
+-2935,-2935,-2935,-2935,-2935,-2935,-2936,-2936,-2936,-2936,-2936,-2936,-2936,-2936,-2936,-2936,-2936,-2936,-2936,-2936,-2936,
+-2936,-2937,-2937,-2937,-2937,-2937,-2937,-2937,-2937,-2937,-2937,-2937,-2937,-2937,-2937,-2937,-2937,-2937,-2937,-2937,-2937,
+-2937,-2937,-2937,-2937,-2937,-2937,-2937,-2937,-2937,-2937,-2937,-2937,-2937,-2937,-2937,-2937,-2937,-2938,-2938,-2938,-2938,
+-2938,-2938,-2938,-2938,-2938,-2938,-2938,-2938,-2938,-2938,-2938,-2938,-2938,-2938,-2938,-2938,-2938,-2938,-2938,-2938,-2938,
+-2938,-2938,-2938,-2938,-2938,-2938,-2938,-2939,-2939,-2939,-2939,-2939,-2939,-2939,-2939,-2939,-2939,-2939,-2939,-2939,-2940,
+-2940,-2940,-2940,-2940,-2940,-2940,-2940,-2940,-2940,-2941,-2941,-2941,-2941,-2941,-2941,-2941,-2942,-2942,-2942,-2942,-2942,
+-2942,-2943,-2943,-2943,-2943,-2943,-2943,-2944,-2944,-2944,-2944,-2944,-2945,-2945,-2945,-2945,-2946,-2946,-2946,-2946,-2947,
+-2947,-2947,-2947,-2948,-2948,-2948,-2948,-2949,-2949,-2949,-2950,-2950,-2950,-2950,-2951,-2951,-2951,-2952,-2952,-2952,-2953,
+-2953,-2953,-2954,-2954,-2955,-2955,-2955,-2956,-2956,-2956,-2957,-2957,-2958,-2958,-2958,-2959,-2959,-2960,-2960,-2960,-2961,
+-2961,-2962,-2962,-2963,-2963,-2964,-2964,-2964,-2965,-2965,-2966,-2966,-2967,-2967,-2968,-2968,-2969,-2969,-2970,-2970,-2971,
+-2971,-2972,-2972,-2973,-2973,-2974,-2974,-2975,-2975,-2976,-2976,-2977,-2977,-2978,-2978,-2979,-2979,-2980,-2980,-2981,-2981,
+-2982,-2983,-2983,-2984,-2984,-2985,-2985,-2986,-2986,-2987,-2987,-2988,-2989,-2989,-2990,-2990,-2991,-2991,-2992,-2992,-2993,
+-2994,-2994,-2995,-2995,-2996,-2996,-2997,-2997,-2998,-2998,-2999,-3000,-3000,-3001,-3001,-3002,-3002,-3003,-3003,-3004,-3004,
+-3005,-3005,-3006,-3007,-3007,-3008,-3008,-3009,-3009,-3010,-3010,-3011,-3011,-3012,-3012,-3013,-3013,-3014,-3014,-3015,-3015,
+-3016,-3016,-3017,-3017,-3018,-3018,-3019,-3019,-3020,-3020,-3021,-3021,-3022,-3022,-3022,-3023,-3023,-3024,-3024,-3025,-3025,
+-3026,-3026,-3026,-3027,-3027,-3028,-3028,-3028,-3029,-3029,-3030,-3030,-3030,-3031,-3031,-3032,-3032,-3032,-3033,-3033,-3033,
+-3034,-3034,-3034,-3035,-3035,-3035,-3036,-3036,-3036,-3037,-3037,-3037,-3038,-3038,-3038,-3039,-3039,-3039,-3039,-3040,-3040,
+-3040,-3040,-3041,-3041,-3041,-3041,-3042,-3042,-3042,-3042,-3043,-3043,-3043,-3043,-3043,-3044,-3044,-3044,-3044,-3044,-3045,
+-3045,-3045,-3045,-3045,-3046,-3046,-3046,-3046,-3046,-3046,-3046,-3047,-3047,-3047,-3047,-3047,-3047,-3047,-3047,-3047,-3048,
+-3048,-3048,-3048,-3048,-3048,-3048,-3048,-3048,-3048,-3048,-3049,-3049,-3049,-3049,-3049,-3049,-3049,-3049,-3049,-3049,-3049,
+-3049,-3049,-3049,-3049,-3049,-3049,-3049,-3049,-3049,-3049,-3049,-3049,-3049,-3049,-3049,-3049,-3049,-3049,-3049,-3050,-3050,
+-3050,-3050,-3050,-3050,-3050,-3050,-3049,-3049,-3049,-3049,-3049,-3049,-3049,-3049,-3049,-3049,-3049,-3049,-3049,-3049,-3049,
 -3049,-3049,-3049,-3049,-3049,-3049,-3049,-3049,-3049,-3049,-3049,-3049,-3049,-3049,-3049,-3049,-3049,-3049,-3049,-3049,-3049,
--3049,-3049,-3049,-3049,-3049,-3049,-3049,-3049,-3049,-3049,-3049,-3049,-3049,-3049,-3049,-3049,-3049,-3049,-3049,-3049,-3050,
--3050,-3050,-3050,-3050,-3050,-3050,-3050,-3050,-3050,-3050,-3050,-3050,-3050,-3050,-3050,-3050,-3050,-3050,-3050,-3050,-3051,
--3051,-3051,-3051,-3051,-3051,-3051,-3051,-3051,-3051,-3051,-3052,-3052,-3052,-3052,-3052,-3052,-3052,-3052,-3053,-3053,-3053,
--3053,-3053,-3053,-3053,-3054,-3054,-3054,-3054,-3054,-3054,-3055,-3055,-3055,-3055,-3055,-3055,-3056,-3056,-3056,-3056,-3056,
--3057,-3057,-3057,-3057,-3057,-3058,-3058,-3058,-3058,-3059,-3059,-3059,-3059,-3060,-3060,-3060,-3060,-3061,-3061,-3061,-3061,
--3062,-3062,-3062,-3062,-3063,-3063,-3063,-3063,-3064,-3064,-3064,-3065,-3065,-3065,-3065,-3066,-3066,-3066,-3067,-3067,-3067,
--3068,-3068,-3068,-3068,-3069,-3069,-3069,-3070,-3070,-3070,-3071,-3071,-3071,-3072,-3072,-3072,-3073,-3073,-3073,-3074,-3074,
--3074,-3075,-3075,-3075,-3075,-3076,-3076,-3076,-3077,-3077,-3077,-3078,-3078,-3078,-3079,-3079,-3079,-3080,-3080,-3080,-3081,
--3081,-3081,-3082,-3082,-3082,-3083,-3083,-3083,-3083,-3084,-3084,-3084,-3085,-3085,-3085,-3086,-3086,-3086,-3086,-3087,-3087,
--3087,-3088,-3088,-3088,-3088,-3089,-3089,-3089,-3089,-3090,-3090,-3090,-3090,-3091,-3091,-3091,-3091,-3092,-3092,-3092,-3092,
--3092,-3093,-3093,-3093,-3093,-3093,-3094,-3094,-3094,-3094,-3094,-3094,-3095,-3095,-3095,-3095,-3095,-3095,-3095,-3096,-3096,
--3096,-3096,-3096,-3096,-3096,-3096,-3096,-3096,-3096,-3096,-3096,-3097,-3097,-3097,-3097,-3097,-3097,-3097,-3097,-3097,-3097,
--3097,-3097,-3097,-3097,-3096,-3096,-3096,-3096,-3096,-3096,-3096,-3096,-3096,-3096,-3096,-3096,-3095,-3095,-3095,-3095,-3095,
--3095,-3094,-3094,-3094,-3094,-3094,-3093,-3093,-3093,-3093,-3093,-3092,-3092,-3092,-3092,-3091,-3091,-3091,-3090,-3090,-3090,
--3089,-3089,-3089,-3088,-3088,-3088,-3087,-3087,-3087,-3086,-3086,-3085,-3085,-3084,-3084,-3084,-3083,-3083,-3082,-3082,-3081,
--3081,-3080,-3080,-3079,-3079,-3078,-3078,-3077,-3077,-3076,-3076,-3075,-3074,-3074,-3073,-3073,-3072,-3071,-3071,-3070,-3069,
--3069,-3068,-3067,-3067,-3066,-3065,-3065,-3064,-3063,-3063,-3062,-3061,-3060,-3060,-3059,-3058,-3057,-3057,-3056,-3055,-3054,
--3053,-3053,-3052,-3051,-3050,-3049,-3049,-3048,-3047,-3046,-3045,-3044,-3043,-3042,-3042,-3041,-3040,-3039,-3038,-3037,-3036,
--3035,-3034,-3033,-3032,-3031,-3030,-3030,-3029,-3028,-3027,-3026,-3025,-3024,-3023,-3022,-3021,-3020,-3019,-3018,-3017,-3016,
--3015,-3013,-3012,-3011,-3010,-3009,-3008,-3007,-3006,-3005,-3004,-3003,-3002,-3001,-3000,-2999,-2998,-2997,-2996,-2994,-2993,
--2992,-2991,-2990,-2989,-2988,-2987,-2986,-2985,-2984,-2983,-2981,-2980,-2979,-2978,-2977,-2976,-2975,-2974,-2973,-2972,-2971,
--2970,-2969,-2968,-2966,-2965,-2964,-2963,-2962,-2961,-2960,-2959,-2958,-2957,-2956,-2955,-2954,-2953,-2952,-2951,-2950,-2949,
--2948,-2947,-2946,-2945,-2944,-2943,-2942,-2941,-2940,-2939,-2938,-2937,-2936,-2935,-2934,-2934,-2933,-2932,-2931,-2930,-2929,
--2928,-2927,-2927,-2926,-2925,-2924,-2923,-2922,-2922,-2921,-2920,-2919,-2918,-2918,-2917,-2916,-2915,-2915,-2914,-2913,-2913,
--2912,-2911,-2911,-2910,-2909,-2909,-2908,-2907,-2907,-2906,-2905,-2905,-2904,-2904,-2903,-2903,-2902,-2901,-2901,-2900,-2900,
--2899,-2899,-2898,-2898,-2897,-2897,-2897,-2896,-2896,-2895,-2895,-2894,-2894,-2894,-2893,-2893,-2893,-2892,-2892,-2892,-2891,
--2891,-2891,-2890,-2890,-2890,-2889,-2889,-2889,-2889,-2888,-2888,-2888,-2888,-2888,-2887,-2887,-2887,-2887,-2887,-2886,-2886,
--2886,-2886,-2886,-2886,-2886,-2885,-2885,-2885,-2885,-2885,-2885,-2885,-2885,-2885,-2885,-2884,-2884,-2884,-2884,-2884,-2884,
--2884,-2884,-2884,-2884,-2884,-2884,-2884,-2884,-2884,-2884,-2884,-2884,-2884,-2884,-2884,-2884,-2884,-2884,-2884,-2884,-2884,
--2884,-2884,-2884,-2884,-2884,-2885,-2885,-2885,-2885,-2885,-2885,-2885,-2885,-2885,-2885,-2885,-2885,-2885,-2885,-2885,-2886,
--2886,-2886,-2886,-2886,-2886,-2886,-2886,-2886,-2886,-2886,-2886,-2887,-2887,-2887,-2887,-2887,-2887,-2887,-2887,-2887,-2887,
--2887,-2888,-2888,-2888,-2888,-2888,-2888,-2888,-2888,-2888,-2888,-2888,-2888,-2889,-2889,-2889,-2889,-2889,-2889,-2889,-2889,
--2889,-2889,-2889,-2890,-2890,-2890,-2890,-2890,-2890,-2890,-2890,-2890,-2890,-2890,-2890,-2891,-2891,-2891,-2891,-2891,-2891,
--2891,-2891,-2891,-2891,-2891,-2891,-2891,-2892,-2892,-2892,-2892,-2892,-2892,-2892,-2892,-2892,-2892,-2892,-2892,-2892,-2893,
--2893,-2893,-2893,-2893,-2893,-2893,-2893,-2893,-2893,-2893,-2893,-2893,-2894,-2894,-2894,-2894,-2894,-2894,-2894,-2894,-2894,
--2894,-2894,-2895,-2895,-2895,-2895,-2895,-2895,-2895,-2895,-2895,-2895,-2895,-2896,-2896,-2896,-2896,-2896,-2960,-2960,-2961,
--2961,-2961,-2961,-2961,-2962,-2962,-2962,-2962,-2962,-2963,-2963,-2963,-2963,-2963,-2964,-2964,-2964,-2964,-2964,-2965,-2965,
--2965,-2965,-2966,-2966,-2966,-2966,-2966,-2967,-2967,-2967,-2967,-2967,-2968,-2968,-2968,-2968,-2968,-2968,-2969,-2969,-2969,
--2969,-2969,-2970,-2970,-2970,-2970,-2970,-2971,-2971,-2971,-2971,-2971,-2972,-2972,-2972,-2972,-2972,-2972,-2973,-2973,-2973,
--2973,-2973,-2973,-2974,-2974,-2974,-2974,-2974,-2974,-2975,-2975,-2975,-2975,-2975,-2975,-2976,-2976,-2976,-2976,-2976,-2976,
--2977,-2977,-2977,-2977,-2977,-2977,-2977,-2978,-2978,-2978,-2978,-2978,-2978,-2978,-2979,-2979,-2979,-2979,-2979,-2979,-2979,
--2980,-2980,-2980,-2980,-2980,-2980,-2980,-2980,-2981,-2981,-2981,-2981,-2981,-2981,-2981,-2981,-2981,-2982,-2982,-2982,-2982,
--2982,-2982,-2982,-2982,-2982,-2982,-2983,-2983,-2983,-2983,-2983,-2983,-2983,-2983,-2983,-2983,-2983,-2984,-2984,-2984,-2984,
--2984,-2984,-2984,-2984,-2984,-2984,-2984,-2984,-2984,-2984,-2984,-2985,-2985,-2985,-2985,-2985,-2985,-2985,-2985,-2985,-2985,
--2985,-2985,-2985,-2985,-2985,-2985,-2985,-2985,-2985,-2985,-2985,-2985,-2985,-2985,-2985,-2985,-2985,-2986,-2986,-2986,-2986,
--2986,-2986,-2986,-2986,-2986,-2986,-2986,-2986,-2986,-2986,-2986,-2986,-2986,-2986,-2986,-2986,-2986,-2986,-2986,-2986,-2986,
--2986,-2986,-2986,-2986,-2986,-2985,-2985,-2985,-2985,-2985,-2985,-2985,-2985,-2985,-2985,-2985,-2985,-2985,-2985,-2985,-2985,
--2985,-2985,-2985,-2985,-2985,-2985,-2985,-2985,-2985,-2985,-2985,-2985,-2985,-2985,-2985,-2985,-2985,-2985,-2984,-2984,-2984,
--2984,-2984,-2984,-2984,-2984,-2984,-2984,-2984,-2984,-2984,-2984,-2984,-2984,-2984,-2984,-2984,-2984,-2984,-2984,-2984,-2984,
--2984,-2984,-2984,-2983,-2983,-2983,-2983,-2983,-2983,-2983,-2983,-2983,-2983,-2983,-2983,-2983,-2983,-2983,-2983,-2983,-2983,
+-3049,-3049,-3049,-3049,-3049,-3049,-3049,-3049,-3049,-3049,-3049,-3049,-3050,-3050,-3050,-3050,-3050,-3050,-3050,-3050,-3050,
+-3050,-3050,-3050,-3050,-3050,-3050,-3050,-3050,-3050,-3050,-3050,-3050,-3051,-3051,-3051,-3051,-3051,-3051,-3051,-3051,-3051,
+-3051,-3051,-3052,-3052,-3052,-3052,-3052,-3052,-3052,-3052,-3053,-3053,-3053,-3053,-3053,-3053,-3053,-3054,-3054,-3054,-3054,
+-3054,-3054,-3055,-3055,-3055,-3055,-3055,-3055,-3056,-3056,-3056,-3056,-3056,-3057,-3057,-3057,-3057,-3057,-3058,-3058,-3058,
+-3058,-3059,-3059,-3059,-3059,-3060,-3060,-3060,-3060,-3061,-3061,-3061,-3061,-3062,-3062,-3062,-3062,-3063,-3063,-3063,-3063,
+-3064,-3064,-3064,-3065,-3065,-3065,-3065,-3066,-3066,-3066,-3067,-3067,-3067,-3068,-3068,-3068,-3068,-3069,-3069,-3069,-3070,
+-3070,-3070,-3071,-3071,-3071,-3072,-3072,-3072,-3073,-3073,-3073,-3074,-3074,-3074,-3075,-3075,-3075,-3075,-3076,-3076,-3076,
+-3077,-3077,-3077,-3078,-3078,-3078,-3079,-3079,-3079,-3080,-3080,-3080,-3081,-3081,-3081,-3082,-3082,-3082,-3083,-3083,-3083,
+-3083,-3084,-3084,-3084,-3085,-3085,-3085,-3086,-3086,-3086,-3086,-3087,-3087,-3087,-3088,-3088,-3088,-3088,-3089,-3089,-3089,
+-3089,-3090,-3090,-3090,-3090,-3091,-3091,-3091,-3091,-3092,-3092,-3092,-3092,-3092,-3093,-3093,-3093,-3093,-3093,-3094,-3094,
+-3094,-3094,-3094,-3094,-3095,-3095,-3095,-3095,-3095,-3095,-3095,-3096,-3096,-3096,-3096,-3096,-3096,-3096,-3096,-3096,-3096,
+-3096,-3096,-3096,-3097,-3097,-3097,-3097,-3097,-3097,-3097,-3097,-3097,-3097,-3097,-3097,-3097,-3097,-3096,-3096,-3096,-3096,
+-3096,-3096,-3096,-3096,-3096,-3096,-3096,-3096,-3095,-3095,-3095,-3095,-3095,-3095,-3094,-3094,-3094,-3094,-3094,-3093,-3093,
+-3093,-3093,-3093,-3092,-3092,-3092,-3092,-3091,-3091,-3091,-3090,-3090,-3090,-3089,-3089,-3089,-3088,-3088,-3088,-3087,-3087,
+-3087,-3086,-3086,-3085,-3085,-3084,-3084,-3084,-3083,-3083,-3082,-3082,-3081,-3081,-3080,-3080,-3079,-3079,-3078,-3078,-3077,
+-3077,-3076,-3076,-3075,-3074,-3074,-3073,-3073,-3072,-3071,-3071,-3070,-3069,-3069,-3068,-3067,-3067,-3066,-3065,-3065,-3064,
+-3063,-3063,-3062,-3061,-3060,-3060,-3059,-3058,-3057,-3057,-3056,-3055,-3054,-3053,-3053,-3052,-3051,-3050,-3049,-3049,-3048,
+-3047,-3046,-3045,-3044,-3043,-3042,-3042,-3041,-3040,-3039,-3038,-3037,-3036,-3035,-3034,-3033,-3032,-3031,-3030,-3030,-3029,
+-3028,-3027,-3026,-3025,-3024,-3023,-3022,-3021,-3020,-3019,-3018,-3017,-3016,-3015,-3013,-3012,-3011,-3010,-3009,-3008,-3007,
+-3006,-3005,-3004,-3003,-3002,-3001,-3000,-2999,-2998,-2997,-2996,-2994,-2993,-2992,-2991,-2990,-2989,-2988,-2987,-2986,-2985,
+-2984,-2983,-2981,-2980,-2979,-2978,-2977,-2976,-2975,-2974,-2973,-2972,-2971,-2970,-2969,-2968,-2966,-2965,-2964,-2963,-2962,
+-2961,-2960,-2959,-2958,-2957,-2956,-2955,-2954,-2953,-2952,-2951,-2950,-2949,-2948,-2947,-2946,-2945,-2944,-2943,-2942,-2941,
+-2940,-2939,-2938,-2937,-2936,-2935,-2934,-2934,-2933,-2932,-2931,-2930,-2929,-2928,-2927,-2927,-2926,-2925,-2924,-2923,-2922,
+-2922,-2921,-2920,-2919,-2918,-2918,-2917,-2916,-2915,-2915,-2914,-2913,-2913,-2912,-2911,-2911,-2910,-2909,-2909,-2908,-2907,
+-2907,-2906,-2905,-2905,-2904,-2904,-2903,-2903,-2902,-2901,-2901,-2900,-2900,-2899,-2899,-2898,-2898,-2897,-2897,-2897,-2896,
+-2896,-2895,-2895,-2894,-2894,-2894,-2893,-2893,-2893,-2892,-2892,-2892,-2891,-2891,-2891,-2890,-2890,-2890,-2889,-2889,-2889,
+-2889,-2888,-2888,-2888,-2888,-2888,-2887,-2887,-2887,-2887,-2887,-2886,-2886,-2886,-2886,-2886,-2886,-2886,-2885,-2885,-2885,
+-2885,-2885,-2885,-2885,-2885,-2885,-2885,-2884,-2884,-2884,-2884,-2884,-2884,-2884,-2884,-2884,-2884,-2884,-2884,-2884,-2884,
+-2884,-2884,-2884,-2884,-2884,-2884,-2884,-2884,-2884,-2884,-2884,-2884,-2884,-2884,-2884,-2884,-2884,-2884,-2885,-2885,-2885,
+-2885,-2885,-2885,-2885,-2885,-2885,-2885,-2885,-2885,-2885,-2885,-2885,-2886,-2886,-2886,-2886,-2886,-2886,-2886,-2886,-2886,
+-2886,-2886,-2886,-2887,-2887,-2887,-2887,-2887,-2887,-2887,-2887,-2887,-2887,-2887,-2888,-2888,-2888,-2888,-2888,-2888,-2888,
+-2888,-2888,-2888,-2888,-2888,-2889,-2889,-2889,-2889,-2889,-2889,-2889,-2889,-2889,-2889,-2889,-2890,-2890,-2890,-2890,-2890,
+-2890,-2890,-2890,-2890,-2890,-2890,-2890,-2891,-2891,-2891,-2891,-2891,-2891,-2891,-2891,-2891,-2891,-2891,-2891,-2891,-2892,
+-2892,-2892,-2892,-2892,-2892,-2892,-2892,-2892,-2892,-2892,-2892,-2892,-2893,-2893,-2893,-2893,-2893,-2893,-2893,-2893,-2893,
+-2893,-2893,-2893,-2893,-2894,-2894,-2894,-2894,-2894,-2894,-2894,-2894,-2894,-2894,-2894,-2895,-2895,-2895,-2895,-2895,-2895,
+-2895,-2895,-2895,-2895,-2895,-2896,-2896,-2896,-2896,-2896,-2960,-2960,-2961,-2961,-2961,-2961,-2961,-2962,-2962,-2962,-2962,
+-2962,-2963,-2963,-2963,-2963,-2963,-2964,-2964,-2964,-2964,-2964,-2965,-2965,-2965,-2965,-2966,-2966,-2966,-2966,-2966,-2967,
+-2967,-2967,-2967,-2967,-2968,-2968,-2968,-2968,-2968,-2968,-2969,-2969,-2969,-2969,-2969,-2970,-2970,-2970,-2970,-2970,-2971,
+-2971,-2971,-2971,-2971,-2972,-2972,-2972,-2972,-2972,-2972,-2973,-2973,-2973,-2973,-2973,-2973,-2974,-2974,-2974,-2974,-2974,
+-2974,-2975,-2975,-2975,-2975,-2975,-2975,-2976,-2976,-2976,-2976,-2976,-2976,-2977,-2977,-2977,-2977,-2977,-2977,-2977,-2978,
+-2978,-2978,-2978,-2978,-2978,-2978,-2979,-2979,-2979,-2979,-2979,-2979,-2979,-2980,-2980,-2980,-2980,-2980,-2980,-2980,-2980,
+-2981,-2981,-2981,-2981,-2981,-2981,-2981,-2981,-2981,-2982,-2982,-2982,-2982,-2982,-2982,-2982,-2982,-2982,-2982,-2983,-2983,
+-2983,-2983,-2983,-2983,-2983,-2983,-2983,-2983,-2983,-2984,-2984,-2984,-2984,-2984,-2984,-2984,-2984,-2984,-2984,-2984,-2984,
+-2984,-2984,-2984,-2985,-2985,-2985,-2985,-2985,-2985,-2985,-2985,-2985,-2985,-2985,-2985,-2985,-2985,-2985,-2985,-2985,-2985,
+-2985,-2985,-2985,-2985,-2985,-2985,-2985,-2985,-2985,-2986,-2986,-2986,-2986,-2986,-2986,-2986,-2986,-2986,-2986,-2986,-2986,
+-2986,-2986,-2986,-2986,-2986,-2986,-2986,-2986,-2986,-2986,-2986,-2986,-2986,-2986,-2986,-2986,-2986,-2986,-2985,-2985,-2985,
+-2985,-2985,-2985,-2985,-2985,-2985,-2985,-2985,-2985,-2985,-2985,-2985,-2985,-2985,-2985,-2985,-2985,-2985,-2985,-2985,-2985,
+-2985,-2985,-2985,-2985,-2985,-2985,-2985,-2985,-2985,-2985,-2984,-2984,-2984,-2984,-2984,-2984,-2984,-2984,-2984,-2984,-2984,
+-2984,-2984,-2984,-2984,-2984,-2984,-2984,-2984,-2984,-2984,-2984,-2984,-2984,-2984,-2984,-2984,-2983,-2983,-2983,-2983,-2983,
 -2983,-2983,-2983,-2983,-2983,-2983,-2983,-2983,-2983,-2983,-2983,-2983,-2983,-2983,-2983,-2983,-2983,-2983,-2983,-2983,-2983,
 -2983,-2983,-2983,-2983,-2983,-2983,-2983,-2983,-2983,-2983,-2983,-2983,-2983,-2983,-2983,-2983,-2983,-2983,-2983,-2983,-2983,
--2983,-2983,-2983,-2983,-2983,-2983,-2984,-2984,-2984,-2984,-2984,-2984,-2984,-2984,-2984,-2984,-2984,-2984,-2984,-2984,-2984,
--2985,-2985,-2985,-2985,-2985,-2985,-2985,-2985,-2985,-2985,-2985,-2986,-2986,-2986,-2986,-2986,-2986,-2986,-2986,-2986,-2987,
--2987,-2987,-2987,-2987,-2987,-2987,-2987,-2988,-2988,-2988,-2988,-2988,-2988,-2989,-2989,-2989,-2989,-2989,-2989,-2989,-2990,
--2990,-2990,-2990,-2990,-2990,-2991,-2991,-2991,-2991,-2991,-2992,-2992,-2992,-2992,-2992,-2993,-2993,-2993,-2993,-2993,-2994,
--2994,-2994,-2994,-2994,-2995,-2995,-2995,-2995,-2996,-2996,-2996,-2996,-2996,-2997,-2997,-2997,-2997,-2998,-2998,-2998,-2998,
--2999,-2999,-2999,-2999,-3000,-3000,-3000,-3000,-3001,-3001,-3001,-3001,-3002,-3002,-3002,-3002,-3003,-3003,-3003,-3003,-3004,
--3004,-3004,-3004,-3005,-3005,-3005,-3005,-3006,-3006,-3006,-3007,-3007,-3007,-3007,-3008,-3008,-3008,-3008,-3009,-3009,-3009,
--3010,-3010,-3010,-3010,-3011,-3011,-3011,-3012,-3012,-3012,-3012,-3013,-3013,-3013,-3013,-3014,-3014,-3014,-3015,-3015,-3015,
--3015,-3016,-3016,-3016,-3017,-3017,-3017,-3017,-3018,-3018,-3018,-3019,-3019,-3019,-3019,-3020,-3020,-3020,-3020,-3021,-3021,
--3021,-3022,-3022,-3022,-3022,-3023,-3023,-3023,-3023,-3024,-3024,-3024,-3025,-3025,-3025,-3025,-3026,-3026,-3026,-3026,-3027,
--3027,-3027,-3027,-3028,-3028,-3028,-3028,-3029,-3029,-3029,-3029,-3030,-3030,-3030,-3030,-3031,-3031,-3031,-3031,-3032,-3032,
--3032,-3032,-3033,-3033,-3033,-3033,-3034,-3034,-3034,-3034,-3035,-3035,-3035,-3035,-3036,-3036,-3036,-3036,-3036,-3037,-3037,
--3037,-3037,-3038,-3038,-3038,-3038,-3039,-3039,-3039,-3039,-3039,-3040,-3040,-3040,-3040,-3040,-3041,-3041,-3041,-3041,-3042,
--3042,-3042,-3042,-3042,-3043,-3043,-3043,-3043,-3043,-3044,-3044,-3044,-3044,-3044,-3045,-3045,-3045,-3045,-3045,-3046,-3046,
--3046,-3046,-3046,-3047,-3047,-3047,-3047,-3047,-3048,-3048,-3048,-3048,-3048,-3048,-3049,-3049,-3049,-3049,-3049,-3050,-3050,
--3050,-3050,-3050,-3051,-3051,-3051,-3051,-3051,-3051,-3052,-3052,-3052,-3052,-3052,-3053,-3053,-3053,-3053,-3053,-3053,-3054,
--3054,-3054,-3054,-3054,-3055,-3055,-3055,-3055,-3055,-3055,-3056,-3056,-3056,-3056,-3056,-3057,-3057,-3057,-3057,-3057,-3057,
--3058,-3058,-3058,-3058,-3058,-3059,-3059,-3059,-3059,-3059,-3059,-3060,-3060,-3060,-3060,-3060,-3061,-3061,-3061,-3061,-3061,
--3062,-3062,-3062,-3062,-3062,-3062,-3063,-3063,-3063,-3063,-3063,-3064,-3064,-3064,-3064,-3064,-3065,-3065,-3065,-3065,-3065,
--3065,-3066,-3066,-3066,-3066,-3066,-3067,-3067,-3067,-3067,-3067,-3068,-3068,-3068,-3068,-3068,-3068,-3069,-3069,-3069,-3069,
--3069,-3070,-3070,-3070,-3070,-3070,-3071,-3071,-3071,-3071,-3071,-3072,-3072,-3072,-3072,-3072,-3072,-3073,-3073,-3073,-3073,
--3073,-3074,-3074,-3074,-3074,-3074,-3074,-3075,-3075,-3075,-3075,-3075,-3076,-3076,-3076,-3076,-3076,-3076,-3077,-3077,-3077,
--3077,-3077,-3078,-3078,-3078,-3078,-3078,-3078,-3079,-3079,-3079,-3079,-3079,-3079,-3079,-3080,-3080,-3080,-3080,-3080,-3080,
--3081,-3081,-3081,-3081,-3081,-3081,-3081,-3082,-3082,-3082,-3082,-3082,-3082,-3082,-3083,-3083,-3083,-3083,-3083,-3083,-3083,
--3083,-3083,-3084,-3084,-3084,-3084,-3084,-3084,-3084,-3084,-3084,-3084,-3085,-3085,-3085,-3085,-3085,-3085,-3085,-3085,-3085,
--3085,-3085,-3085,-3085,-3085,-3086,-3086,-3086,-3086,-3086,-3086,-3086,-3086,-3086,-3086,-3086,-3086,-3086,-3086,-3086,-3086,
--3086,-3086,-3086,-3086,-3086,-3086,-3086,-3086,-3086,-3086,-3086,-3086,-3086,-3086,-3086,-3086,-3086,-3086,-3085,-3085,-3085,
--3085,-3085,-3085,-3085,-3085,-3085,-3085,-3085,-3085,-3085,-3084,-3084,-3084,-3084,-3084,-3084,-3084,-3084,-3083,-3083,-3083,
--3083,-3083,-3083,-3083,-3082,-3082,-3082,-3082,-3082,-3081,-3081,-3081,-3081,-3081,-3080,-3080,-3080,-3080,-3080,-3079,-3079,
--3079,-3079,-3078,-3078,-3078,-3078,-3077,-3077,-3077,-3077,-3076,-3076,-3076,-3076,-3075,-3075,-3075,-3074,-3074,-3074,-3073,
--3073,-3073,-3072,-3072,-3072,-3071,-3071,-3071,-3070,-3070,-3070,-3069,-3069,-3068,-3068,-3068,-3067,-3067,-3067,-3066,-3066,
--3065,-3065,-3064,-3064,-3064,-3063,-3063,-3062,-3062,-3061,-3061,-3061,-3060,-3060,-3059,-3059,-3058,-3058,-3057,-3057,-3056,
--3056,-3055,-3055,-3054,-3054,-3053,-3053,-3052,-3052,-3051,-3051,-3050,-3050,-3049,-3049,-3048,-3048,-3047,-3046,-3046,-3045,
--3045,-3044,-3044,-3043,-3043,-3042,-3041,-3041,-3040,-3040,-3039,-3039,-3038,-3037,-3037,-3036,-3036,-3035,-3034,-3034,-3033,
--3033,-3032,-3031,-3031,-3030,-3029,-3029,-3028,-3028,-3027,-3026,-3026,-3025,-3024,-3024,-3023,-3023,-3022,-3021,-3021,-3020,
--3019,-3019,-3018,-3017,-3017,-3016,-3015,-3015,-3014,-3014,-3013,-3012,-3012,-3011,-3010,-3010,-3009,-3008,-3008,-3007,-3006,
--3006,-3005,-3004,-3004,-3003,-3002,-3002,-3001,-3001,-3000,-2999,-2999,-2998,-2997,-2997,-2996,-2995,-2995,-2994,-2993,-2993,
--2992,-2992,-2991,-2990,-2990,-2989,-2988,-2988,-2987,-2986,-2986,-2985,-2985,-2984,-2983,-2983,-2982,-2982,-2981,-2980,-2980,
--2979,-2979,-2978,-2977,-2977,-2976,-2976,-2975,-2974,-2974,-2973,-2973,-2972,-2972,-2971,-2970,-2970,-2969,-2969,-2968,-2968,
--2967,-2967,-2966,-2966,-2965,-2965,-2964,-2964,-2963,-2963,-2962,-2962,-2961,-2961,-2960,-2960,-2959,-2959,-2958,-2958,-2957,
--2957,-2956,-2956,-2955,-2955,-2955,-2954,-2954,-2953,-2953,-2952,-2952,-2952,-2951,-2951,-2950,-2950,-2950,-2949,-2949,-2949,
--2948,-2948,-2947,-2947,-2947,-2946,-2946,-2946,-2945,-2945,-2945,-2944,-2944,-2944,-2944,-2943,-2943,-2943,-2942,-2942,-2942,
--2942,-2941,-2941,-2941,-2941,-2940,-2940,-2940,-2940,-2939,-2939,-2939,-2939,-2939,-2938,-2938,-2938,-2938,-2938,-2938,-2937,
--2937,-2937,-2937,-2937,-2937,-2936,-2936,-2936,-2936,-2936,-2936,-2936,-2936,-2936,-2935,-2935,-2935,-2935,-2935,-2935,-2935,
--2935,-2935,-2935,-2935,-2935,-2935,-2934,-2934,-2934,-2934,-2934,-2934,-2934,-2934,-2934,-2934,-2934,-2934,-2934,-2934,-2934,
--2934,-2934,-2934,-2934,-2934,-2934,-2934,-2934,-2935,-2935,-2935,-2935,-2935,-2935,-2935,-2935,-2935,-2935,-2935,-2935,-2935,
--2935,-2935,-2936,-2936,-2936,-2936,-2936,-2936,-2936,-2936,-2936,-2936,-2937,-2937,-2937,-2937,-2937,-2937,-2937,-2937,-2938,
--2938,-2938,-2938,-2938,-2938,-2938,-2938,-2939,-2939,-2939,-2939,-2939,-2939,-2940,-2940,-2940,-2940,-2940,-2940,-2941,-2941,
--2941,-2941,-2941,-2941,-2942,-2942,-2942,-2942,-2942,-2942,-2943,-2943,-2943,-2943,-2943,-2944,-2944,-2944,-2944,-2944,-2945,
--2945,-2945,-2945,-2945,-2946,-2946,-2946,-2946,-2946,-2947,-2947,-2947,-2947,-2947,-2948,-2948,-2948,-2948,-2948,-2949,-2949,
--2949,-2949,-2950,-2950,-2950,-2950,-2950,-2951,-2951,-2951,-2951,-2951,-2952,-2952,-2952,-2952,-2953,-2953,-2953,-2953,-2953,
--2954,-2954,-2954,-2954,-2954,-2955,-2955,-2955,-2955,-2956,-2956,-2956,-2956,-2956,-2957,-2957,-2957,-2957,-2957,-2958,-2958,
--2958,-2958,-2959,-2959,-2959,-2959,-2959,-2960,-2960,-2960,-2954,-2954,-2954,-2955,-2955,-2955,-2955,-2955,-2955,-2955,-2955,
--2955,-2955,-2955,-2956,-2956,-2956,-2956,-2956,-2956,-2956,-2956,-2956,-2956,-2956,-2957,-2957,-2957,-2957,-2957,-2957,-2957,
--2957,-2957,-2957,-2957,-2958,-2958,-2958,-2958,-2958,-2958,-2958,-2958,-2958,-2958,-2958,-2958,-2959,-2959,-2959,-2959,-2959,
--2959,-2959,-2959,-2959,-2959,-2959,-2959,-2960,-2960,-2960,-2960,-2960,-2960,-2960,-2960,-2960,-2960,-2960,-2960,-2961,-2961,
--2961,-2961,-2961,-2961,-2961,-2961,-2961,-2961,-2961,-2961,-2961,-2962,-2962,-2962,-2962,-2962,-2962,-2962,-2962,-2962,-2962,
--2962,-2962,-2962,-2962,-2962,-2963,-2963,-2963,-2963,-2963,-2963,-2963,-2963,-2963,-2963,-2963,-2963,-2963,-2963,-2963,-2963,
--2964,-2964,-2964,-2964,-2964,-2964,-2964,-2964,-2964,-2964,-2964,-2964,-2964,-2964,-2964,-2964,-2964,-2964,-2965,-2965,-2965,
--2965,-2965,-2965,-2965,-2965,-2965,-2965,-2965,-2965,-2965,-2965,-2965,-2965,-2965,-2965,-2965,-2965,-2965,-2965,-2965,-2966,
--2966,-2966,-2966,-2966,-2966,-2966,-2966,-2966,-2966,-2966,-2966,-2966,-2966,-2966,-2966,-2966,-2966,-2966,-2966,-2966,-2966,
--2966,-2966,-2966,-2966,-2966,-2966,-2966,-2967,-2967,-2967,-2967,-2967,-2967,-2967,-2967,-2967,-2967,-2967,-2967,-2967,-2967,
+-2983,-2983,-2983,-2983,-2983,-2983,-2983,-2983,-2983,-2983,-2983,-2983,-2983,-2983,-2983,-2983,-2983,-2983,-2983,-2984,-2984,
+-2984,-2984,-2984,-2984,-2984,-2984,-2984,-2984,-2984,-2984,-2984,-2984,-2984,-2985,-2985,-2985,-2985,-2985,-2985,-2985,-2985,
+-2985,-2985,-2985,-2986,-2986,-2986,-2986,-2986,-2986,-2986,-2986,-2986,-2987,-2987,-2987,-2987,-2987,-2987,-2987,-2987,-2988,
+-2988,-2988,-2988,-2988,-2988,-2989,-2989,-2989,-2989,-2989,-2989,-2989,-2990,-2990,-2990,-2990,-2990,-2990,-2991,-2991,-2991,
+-2991,-2991,-2992,-2992,-2992,-2992,-2992,-2993,-2993,-2993,-2993,-2993,-2994,-2994,-2994,-2994,-2994,-2995,-2995,-2995,-2995,
+-2996,-2996,-2996,-2996,-2996,-2997,-2997,-2997,-2997,-2998,-2998,-2998,-2998,-2999,-2999,-2999,-2999,-3000,-3000,-3000,-3000,
+-3001,-3001,-3001,-3001,-3002,-3002,-3002,-3002,-3003,-3003,-3003,-3003,-3004,-3004,-3004,-3004,-3005,-3005,-3005,-3005,-3006,
+-3006,-3006,-3007,-3007,-3007,-3007,-3008,-3008,-3008,-3008,-3009,-3009,-3009,-3010,-3010,-3010,-3010,-3011,-3011,-3011,-3012,
+-3012,-3012,-3012,-3013,-3013,-3013,-3013,-3014,-3014,-3014,-3015,-3015,-3015,-3015,-3016,-3016,-3016,-3017,-3017,-3017,-3017,
+-3018,-3018,-3018,-3019,-3019,-3019,-3019,-3020,-3020,-3020,-3020,-3021,-3021,-3021,-3022,-3022,-3022,-3022,-3023,-3023,-3023,
+-3023,-3024,-3024,-3024,-3025,-3025,-3025,-3025,-3026,-3026,-3026,-3026,-3027,-3027,-3027,-3027,-3028,-3028,-3028,-3028,-3029,
+-3029,-3029,-3029,-3030,-3030,-3030,-3030,-3031,-3031,-3031,-3031,-3032,-3032,-3032,-3032,-3033,-3033,-3033,-3033,-3034,-3034,
+-3034,-3034,-3035,-3035,-3035,-3035,-3036,-3036,-3036,-3036,-3036,-3037,-3037,-3037,-3037,-3038,-3038,-3038,-3038,-3039,-3039,
+-3039,-3039,-3039,-3040,-3040,-3040,-3040,-3040,-3041,-3041,-3041,-3041,-3042,-3042,-3042,-3042,-3042,-3043,-3043,-3043,-3043,
+-3043,-3044,-3044,-3044,-3044,-3044,-3045,-3045,-3045,-3045,-3045,-3046,-3046,-3046,-3046,-3046,-3047,-3047,-3047,-3047,-3047,
+-3048,-3048,-3048,-3048,-3048,-3048,-3049,-3049,-3049,-3049,-3049,-3050,-3050,-3050,-3050,-3050,-3051,-3051,-3051,-3051,-3051,
+-3051,-3052,-3052,-3052,-3052,-3052,-3053,-3053,-3053,-3053,-3053,-3053,-3054,-3054,-3054,-3054,-3054,-3055,-3055,-3055,-3055,
+-3055,-3055,-3056,-3056,-3056,-3056,-3056,-3057,-3057,-3057,-3057,-3057,-3057,-3058,-3058,-3058,-3058,-3058,-3059,-3059,-3059,
+-3059,-3059,-3059,-3060,-3060,-3060,-3060,-3060,-3061,-3061,-3061,-3061,-3061,-3062,-3062,-3062,-3062,-3062,-3062,-3063,-3063,
+-3063,-3063,-3063,-3064,-3064,-3064,-3064,-3064,-3065,-3065,-3065,-3065,-3065,-3065,-3066,-3066,-3066,-3066,-3066,-3067,-3067,
+-3067,-3067,-3067,-3068,-3068,-3068,-3068,-3068,-3068,-3069,-3069,-3069,-3069,-3069,-3070,-3070,-3070,-3070,-3070,-3071,-3071,
+-3071,-3071,-3071,-3072,-3072,-3072,-3072,-3072,-3072,-3073,-3073,-3073,-3073,-3073,-3074,-3074,-3074,-3074,-3074,-3074,-3075,
+-3075,-3075,-3075,-3075,-3076,-3076,-3076,-3076,-3076,-3076,-3077,-3077,-3077,-3077,-3077,-3078,-3078,-3078,-3078,-3078,-3078,
+-3079,-3079,-3079,-3079,-3079,-3079,-3079,-3080,-3080,-3080,-3080,-3080,-3080,-3081,-3081,-3081,-3081,-3081,-3081,-3081,-3082,
+-3082,-3082,-3082,-3082,-3082,-3082,-3083,-3083,-3083,-3083,-3083,-3083,-3083,-3083,-3083,-3084,-3084,-3084,-3084,-3084,-3084,
+-3084,-3084,-3084,-3084,-3085,-3085,-3085,-3085,-3085,-3085,-3085,-3085,-3085,-3085,-3085,-3085,-3085,-3085,-3086,-3086,-3086,
+-3086,-3086,-3086,-3086,-3086,-3086,-3086,-3086,-3086,-3086,-3086,-3086,-3086,-3086,-3086,-3086,-3086,-3086,-3086,-3086,-3086,
+-3086,-3086,-3086,-3086,-3086,-3086,-3086,-3086,-3086,-3086,-3085,-3085,-3085,-3085,-3085,-3085,-3085,-3085,-3085,-3085,-3085,
+-3085,-3085,-3084,-3084,-3084,-3084,-3084,-3084,-3084,-3084,-3083,-3083,-3083,-3083,-3083,-3083,-3083,-3082,-3082,-3082,-3082,
+-3082,-3081,-3081,-3081,-3081,-3081,-3080,-3080,-3080,-3080,-3080,-3079,-3079,-3079,-3079,-3078,-3078,-3078,-3078,-3077,-3077,
+-3077,-3077,-3076,-3076,-3076,-3076,-3075,-3075,-3075,-3074,-3074,-3074,-3073,-3073,-3073,-3072,-3072,-3072,-3071,-3071,-3071,
+-3070,-3070,-3070,-3069,-3069,-3068,-3068,-3068,-3067,-3067,-3067,-3066,-3066,-3065,-3065,-3064,-3064,-3064,-3063,-3063,-3062,
+-3062,-3061,-3061,-3061,-3060,-3060,-3059,-3059,-3058,-3058,-3057,-3057,-3056,-3056,-3055,-3055,-3054,-3054,-3053,-3053,-3052,
+-3052,-3051,-3051,-3050,-3050,-3049,-3049,-3048,-3048,-3047,-3046,-3046,-3045,-3045,-3044,-3044,-3043,-3043,-3042,-3041,-3041,
+-3040,-3040,-3039,-3039,-3038,-3037,-3037,-3036,-3036,-3035,-3034,-3034,-3033,-3033,-3032,-3031,-3031,-3030,-3029,-3029,-3028,
+-3028,-3027,-3026,-3026,-3025,-3024,-3024,-3023,-3023,-3022,-3021,-3021,-3020,-3019,-3019,-3018,-3017,-3017,-3016,-3015,-3015,
+-3014,-3014,-3013,-3012,-3012,-3011,-3010,-3010,-3009,-3008,-3008,-3007,-3006,-3006,-3005,-3004,-3004,-3003,-3002,-3002,-3001,
+-3001,-3000,-2999,-2999,-2998,-2997,-2997,-2996,-2995,-2995,-2994,-2993,-2993,-2992,-2992,-2991,-2990,-2990,-2989,-2988,-2988,
+-2987,-2986,-2986,-2985,-2985,-2984,-2983,-2983,-2982,-2982,-2981,-2980,-2980,-2979,-2979,-2978,-2977,-2977,-2976,-2976,-2975,
+-2974,-2974,-2973,-2973,-2972,-2972,-2971,-2970,-2970,-2969,-2969,-2968,-2968,-2967,-2967,-2966,-2966,-2965,-2965,-2964,-2964,
+-2963,-2963,-2962,-2962,-2961,-2961,-2960,-2960,-2959,-2959,-2958,-2958,-2957,-2957,-2956,-2956,-2955,-2955,-2955,-2954,-2954,
+-2953,-2953,-2952,-2952,-2952,-2951,-2951,-2950,-2950,-2950,-2949,-2949,-2949,-2948,-2948,-2947,-2947,-2947,-2946,-2946,-2946,
+-2945,-2945,-2945,-2944,-2944,-2944,-2944,-2943,-2943,-2943,-2942,-2942,-2942,-2942,-2941,-2941,-2941,-2941,-2940,-2940,-2940,
+-2940,-2939,-2939,-2939,-2939,-2939,-2938,-2938,-2938,-2938,-2938,-2938,-2937,-2937,-2937,-2937,-2937,-2937,-2936,-2936,-2936,
+-2936,-2936,-2936,-2936,-2936,-2936,-2935,-2935,-2935,-2935,-2935,-2935,-2935,-2935,-2935,-2935,-2935,-2935,-2935,-2934,-2934,
+-2934,-2934,-2934,-2934,-2934,-2934,-2934,-2934,-2934,-2934,-2934,-2934,-2934,-2934,-2934,-2934,-2934,-2934,-2934,-2934,-2934,
+-2935,-2935,-2935,-2935,-2935,-2935,-2935,-2935,-2935,-2935,-2935,-2935,-2935,-2935,-2935,-2936,-2936,-2936,-2936,-2936,-2936,
+-2936,-2936,-2936,-2936,-2937,-2937,-2937,-2937,-2937,-2937,-2937,-2937,-2938,-2938,-2938,-2938,-2938,-2938,-2938,-2938,-2939,
+-2939,-2939,-2939,-2939,-2939,-2940,-2940,-2940,-2940,-2940,-2940,-2941,-2941,-2941,-2941,-2941,-2941,-2942,-2942,-2942,-2942,
+-2942,-2942,-2943,-2943,-2943,-2943,-2943,-2944,-2944,-2944,-2944,-2944,-2945,-2945,-2945,-2945,-2945,-2946,-2946,-2946,-2946,
+-2946,-2947,-2947,-2947,-2947,-2947,-2948,-2948,-2948,-2948,-2948,-2949,-2949,-2949,-2949,-2950,-2950,-2950,-2950,-2950,-2951,
+-2951,-2951,-2951,-2951,-2952,-2952,-2952,-2952,-2953,-2953,-2953,-2953,-2953,-2954,-2954,-2954,-2954,-2954,-2955,-2955,-2955,
+-2955,-2956,-2956,-2956,-2956,-2956,-2957,-2957,-2957,-2957,-2957,-2958,-2958,-2958,-2958,-2959,-2959,-2959,-2959,-2959,-2960,
+-2960,-2960,-2954,-2954,-2954,-2955,-2955,-2955,-2955,-2955,-2955,-2955,-2955,-2955,-2955,-2955,-2956,-2956,-2956,-2956,-2956,
+-2956,-2956,-2956,-2956,-2956,-2956,-2957,-2957,-2957,-2957,-2957,-2957,-2957,-2957,-2957,-2957,-2957,-2958,-2958,-2958,-2958,
+-2958,-2958,-2958,-2958,-2958,-2958,-2958,-2958,-2959,-2959,-2959,-2959,-2959,-2959,-2959,-2959,-2959,-2959,-2959,-2959,-2960,
+-2960,-2960,-2960,-2960,-2960,-2960,-2960,-2960,-2960,-2960,-2960,-2961,-2961,-2961,-2961,-2961,-2961,-2961,-2961,-2961,-2961,
+-2961,-2961,-2961,-2962,-2962,-2962,-2962,-2962,-2962,-2962,-2962,-2962,-2962,-2962,-2962,-2962,-2962,-2962,-2963,-2963,-2963,
+-2963,-2963,-2963,-2963,-2963,-2963,-2963,-2963,-2963,-2963,-2963,-2963,-2963,-2964,-2964,-2964,-2964,-2964,-2964,-2964,-2964,
+-2964,-2964,-2964,-2964,-2964,-2964,-2964,-2964,-2964,-2964,-2965,-2965,-2965,-2965,-2965,-2965,-2965,-2965,-2965,-2965,-2965,
+-2965,-2965,-2965,-2965,-2965,-2965,-2965,-2965,-2965,-2965,-2965,-2965,-2966,-2966,-2966,-2966,-2966,-2966,-2966,-2966,-2966,
+-2966,-2966,-2966,-2966,-2966,-2966,-2966,-2966,-2966,-2966,-2966,-2966,-2966,-2966,-2966,-2966,-2966,-2966,-2966,-2966,-2967,
+-2967,-2967,-2967,-2967,-2967,-2967,-2967,-2967,-2967,-2967,-2967,-2967,-2967,-2967,-2967,-2967,-2967,-2967,-2967,-2967,-2967,
 -2967,-2967,-2967,-2967,-2967,-2967,-2967,-2967,-2967,-2967,-2967,-2967,-2967,-2967,-2967,-2967,-2967,-2967,-2967,-2967,-2967,
--2967,-2967,-2967,-2967,-2967,-2967,-2967,-2967,-2967,-2967,-2967,-2968,-2968,-2968,-2968,-2968,-2968,-2968,-2968,-2968,-2968,
+-2967,-2967,-2967,-2968,-2968,-2968,-2968,-2968,-2968,-2968,-2968,-2968,-2968,-2968,-2968,-2968,-2968,-2968,-2968,-2968,-2968,
 -2968,-2968,-2968,-2968,-2968,-2968,-2968,-2968,-2968,-2968,-2968,-2968,-2968,-2968,-2968,-2968,-2968,-2968,-2968,-2968,-2968,
 -2968,-2968,-2968,-2968,-2968,-2968,-2968,-2968,-2968,-2968,-2968,-2968,-2968,-2968,-2968,-2968,-2968,-2968,-2968,-2968,-2968,
--2968,-2968,-2968,-2968,-2968,-2968,-2968,-2968,-2968,-2968,-2969,-2969,-2969,-2969,-2969,-2969,-2969,-2969,-2969,-2969,-2969,
--2969,-2969,-2969,-2969,-2969,-2969,-2969,-2969,-2969,-2969,-2969,-2969,-2969,-2969,-2969,-2969,-2969,-2969,-2969,-2969,-2969,
--2969,-2969,-2969,-2969,-2969,-2969,-2969,-2970,-2970,-2970,-2970,-2970,-2970,-2970,-2970,-2970,-2970,-2970,-2970,-2970,-2970,
--2970,-2970,-2970,-2970,-2970,-2970,-2970,-2970,-2970,-2970,-2970,-2970,-2971,-2971,-2971,-2971,-2971,-2971,-2971,-2971,-2971,
--2971,-2971,-2971,-2971,-2971,-2971,-2971,-2971,-2971,-2971,-2971,-2972,-2972,-2972,-2972,-2972,-2972,-2972,-2972,-2972,-2972,
--2972,-2972,-2972,-2972,-2972,-2972,-2972,-2973,-2973,-2973,-2973,-2973,-2973,-2973,-2973,-2973,-2973,-2973,-2973,-2973,-2973,
--2973,-2974,-2974,-2974,-2974,-2974,-2974,-2974,-2974,-2974,-2974,-2974,-2974,-2974,-2975,-2975,-2975,-2975,-2975,-2975,-2975,
--2975,-2975,-2975,-2975,-2975,-2976,-2976,-2976,-2976,-2976,-2976,-2976,-2976,-2976,-2976,-2976,-2977,-2977,-2977,-2977,-2977,
--2977,-2977,-2977,-2977,-2977,-2977,-2978,-2978,-2978,-2978,-2978,-2978,-2978,-2978,-2978,-2978,-2979,-2979,-2979,-2979,-2979,
--2979,-2979,-2979,-2979,-2980,-2980,-2980,-2980,-2980,-2980,-2980,-2980,-2980,-2981,-2981,-2981,-2981,-2981,-2981,-2981,-2981,
--2981,-2982,-2982,-2982,-2982,-2982,-2982,-2982,-2982,-2982,-2983,-2983,-2983,-2983,-2983,-2983,-2983,-2983,-2983,-2984,-2984,
--2984,-2984,-2984,-2984,-2984,-2984,-2985,-2985,-2985,-2985,-2985,-2985,-2985,-2985,-2986,-2986,-2986,-2986,-2986,-2986,-2986,
--2986,-2987,-2987,-2987,-2987,-2987,-2987,-2987,-2987,-2988,-2988,-2988,-2988,-2988,-2988,-2988,-2988,-2989,-2989,-2989,-2989,
--2989,-2989,-2989,-2989,-2990,-2990,-2990,-2990,-2990,-2990,-2990,-2990,-2991,-2991,-2991,-2991,-2991,-2991,-2991,-2991,-2992,
--2992,-2992,-2992,-2992,-2992,-2992,-2992,-2993,-2993,-2993,-2993,-2993,-2993,-2993,-2993,-2994,-2994,-2994,-2994,-2994,-2994,
--2994,-2995,-2995,-2995,-2995,-2995,-2995,-2995,-2995,-2996,-2996,-2996,-2996,-2996,-2996,-2996,-2996,-2997,-2997,-2997,-2997,
--2997,-2997,-2997,-2997,-2998,-2998,-2998,-2998,-2998,-2998,-2998,-2998,-2998,-2999,-2999,-2999,-2999,-2999,-2999,-2999,-2999,
--3000,-3000,-3000,-3000,-3000,-3000,-3000,-3000,-3001,-3001,-3001,-3001,-3001,-3001,-3001,-3001,-3001,-3002,-3002,-3002,-3002,
--3002,-3002,-3002,-3002,-3003,-3003,-3003,-3003,-3003,-3003,-3003,-3003,-3003,-3004,-3004,-3004,-3004,-3004,-3004,-3004,-3004,
--3004,-3004,-3005,-3005,-3005,-3005,-3005,-3005,-3005,-3005,-3005,-3006,-3006,-3006,-3006,-3006,-3006,-3006,-3006,-3006,-3006,
--3007,-3007,-3007,-3007,-3007,-3007,-3007,-3007,-3007,-3007,-3007,-3008,-3008,-3008,-3008,-3008,-3008,-3008,-3008,-3008,-3008,
--3008,-3009,-3009,-3009,-3009,-3009,-3009,-3009,-3009,-3009,-3009,-3009,-3009,-3009,-3010,-3010,-3010,-3010,-3010,-3010,-3010,
--3010,-3010,-3010,-3010,-3010,-3010,-3011,-3011,-3011,-3011,-3011,-3011,-3011,-3011,-3011,-3011,-3011,-3011,-3011,-3011,-3011,
--3011,-3011,-3012,-3012,-3012,-3012,-3012,-3012,-3012,-3012,-3012,-3012,-3012,-3012,-3012,-3012,-3012,-3012,-3012,-3012,-3012,
--3012,-3012,-3012,-3013,-3013,-3013,-3013,-3013,-3013,-3013,-3013,-3013,-3013,-3013,-3013,-3013,-3013,-3013,-3013,-3013,-3013,
+-2968,-2968,-2969,-2969,-2969,-2969,-2969,-2969,-2969,-2969,-2969,-2969,-2969,-2969,-2969,-2969,-2969,-2969,-2969,-2969,-2969,
+-2969,-2969,-2969,-2969,-2969,-2969,-2969,-2969,-2969,-2969,-2969,-2969,-2969,-2969,-2969,-2969,-2969,-2969,-2969,-2969,-2970,
+-2970,-2970,-2970,-2970,-2970,-2970,-2970,-2970,-2970,-2970,-2970,-2970,-2970,-2970,-2970,-2970,-2970,-2970,-2970,-2970,-2970,
+-2970,-2970,-2970,-2970,-2971,-2971,-2971,-2971,-2971,-2971,-2971,-2971,-2971,-2971,-2971,-2971,-2971,-2971,-2971,-2971,-2971,
+-2971,-2971,-2971,-2972,-2972,-2972,-2972,-2972,-2972,-2972,-2972,-2972,-2972,-2972,-2972,-2972,-2972,-2972,-2972,-2972,-2973,
+-2973,-2973,-2973,-2973,-2973,-2973,-2973,-2973,-2973,-2973,-2973,-2973,-2973,-2973,-2974,-2974,-2974,-2974,-2974,-2974,-2974,
+-2974,-2974,-2974,-2974,-2974,-2974,-2975,-2975,-2975,-2975,-2975,-2975,-2975,-2975,-2975,-2975,-2975,-2975,-2976,-2976,-2976,
+-2976,-2976,-2976,-2976,-2976,-2976,-2976,-2976,-2977,-2977,-2977,-2977,-2977,-2977,-2977,-2977,-2977,-2977,-2977,-2978,-2978,
+-2978,-2978,-2978,-2978,-2978,-2978,-2978,-2978,-2979,-2979,-2979,-2979,-2979,-2979,-2979,-2979,-2979,-2980,-2980,-2980,-2980,
+-2980,-2980,-2980,-2980,-2980,-2981,-2981,-2981,-2981,-2981,-2981,-2981,-2981,-2981,-2982,-2982,-2982,-2982,-2982,-2982,-2982,
+-2982,-2982,-2983,-2983,-2983,-2983,-2983,-2983,-2983,-2983,-2983,-2984,-2984,-2984,-2984,-2984,-2984,-2984,-2984,-2985,-2985,
+-2985,-2985,-2985,-2985,-2985,-2985,-2986,-2986,-2986,-2986,-2986,-2986,-2986,-2986,-2987,-2987,-2987,-2987,-2987,-2987,-2987,
+-2987,-2988,-2988,-2988,-2988,-2988,-2988,-2988,-2988,-2989,-2989,-2989,-2989,-2989,-2989,-2989,-2989,-2990,-2990,-2990,-2990,
+-2990,-2990,-2990,-2990,-2991,-2991,-2991,-2991,-2991,-2991,-2991,-2991,-2992,-2992,-2992,-2992,-2992,-2992,-2992,-2992,-2993,
+-2993,-2993,-2993,-2993,-2993,-2993,-2993,-2994,-2994,-2994,-2994,-2994,-2994,-2994,-2995,-2995,-2995,-2995,-2995,-2995,-2995,
+-2995,-2996,-2996,-2996,-2996,-2996,-2996,-2996,-2996,-2997,-2997,-2997,-2997,-2997,-2997,-2997,-2997,-2998,-2998,-2998,-2998,
+-2998,-2998,-2998,-2998,-2998,-2999,-2999,-2999,-2999,-2999,-2999,-2999,-2999,-3000,-3000,-3000,-3000,-3000,-3000,-3000,-3000,
+-3001,-3001,-3001,-3001,-3001,-3001,-3001,-3001,-3001,-3002,-3002,-3002,-3002,-3002,-3002,-3002,-3002,-3003,-3003,-3003,-3003,
+-3003,-3003,-3003,-3003,-3003,-3004,-3004,-3004,-3004,-3004,-3004,-3004,-3004,-3004,-3004,-3005,-3005,-3005,-3005,-3005,-3005,
+-3005,-3005,-3005,-3006,-3006,-3006,-3006,-3006,-3006,-3006,-3006,-3006,-3006,-3007,-3007,-3007,-3007,-3007,-3007,-3007,-3007,
+-3007,-3007,-3007,-3008,-3008,-3008,-3008,-3008,-3008,-3008,-3008,-3008,-3008,-3008,-3009,-3009,-3009,-3009,-3009,-3009,-3009,
+-3009,-3009,-3009,-3009,-3009,-3009,-3010,-3010,-3010,-3010,-3010,-3010,-3010,-3010,-3010,-3010,-3010,-3010,-3010,-3011,-3011,
+-3011,-3011,-3011,-3011,-3011,-3011,-3011,-3011,-3011,-3011,-3011,-3011,-3011,-3011,-3011,-3012,-3012,-3012,-3012,-3012,-3012,
+-3012,-3012,-3012,-3012,-3012,-3012,-3012,-3012,-3012,-3012,-3012,-3012,-3012,-3012,-3012,-3012,-3013,-3013,-3013,-3013,-3013,
 -3013,-3013,-3013,-3013,-3013,-3013,-3013,-3013,-3013,-3013,-3013,-3013,-3013,-3013,-3013,-3013,-3013,-3013,-3013,-3013,-3013,
 -3013,-3013,-3013,-3013,-3013,-3013,-3013,-3013,-3013,-3013,-3013,-3013,-3013,-3013,-3013,-3013,-3013,-3013,-3013,-3013,-3013,
--3013,-3013,-3013,-3013,-3013,-3013,-3013,-3013,-3012,-3012,-3012,-3012,-3012,-3012,-3012,-3012,-3012,-3012,-3012,-3012,-3012,
--3012,-3012,-3012,-3012,-3012,-3012,-3011,-3011,-3011,-3011,-3011,-3011,-3011,-3011,-3011,-3011,-3011,-3011,-3011,-3011,-3010,
--3010,-3010,-3010,-3010,-3010,-3010,-3010,-3010,-3010,-3010,-3009,-3009,-3009,-3009,-3009,-3009,-3009,-3009,-3009,-3009,-3008,
--3008,-3008,-3008,-3008,-3008,-3008,-3008,-3008,-3007,-3007,-3007,-3007,-3007,-3007,-3007,-3007,-3006,-3006,-3006,-3006,-3006,
--3006,-3006,-3005,-3005,-3005,-3005,-3005,-3005,-3005,-3004,-3004,-3004,-3004,-3004,-3004,-3003,-3003,-3003,-3003,-3003,-3003,
--3003,-3002,-3002,-3002,-3002,-3002,-3002,-3001,-3001,-3001,-3001,-3001,-3000,-3000,-3000,-3000,-3000,-3000,-2999,-2999,-2999,
--2999,-2999,-2998,-2998,-2998,-2998,-2998,-2998,-2997,-2997,-2997,-2997,-2997,-2996,-2996,-2996,-2996,-2996,-2995,-2995,-2995,
--2995,-2995,-2994,-2994,-2994,-2994,-2993,-2993,-2993,-2993,-2993,-2992,-2992,-2992,-2992,-2992,-2991,-2991,-2991,-2991,-2990,
--2990,-2990,-2990,-2990,-2989,-2989,-2989,-2989,-2988,-2988,-2988,-2988,-2987,-2987,-2987,-2987,-2987,-2986,-2986,-2986,-2986,
--2985,-2985,-2985,-2985,-2984,-2984,-2984,-2984,-2984,-2983,-2983,-2983,-2983,-2982,-2982,-2982,-2982,-2981,-2981,-2981,-2981,
--2980,-2980,-2980,-2980,-2980,-2979,-2979,-2979,-2979,-2978,-2978,-2978,-2978,-2977,-2977,-2977,-2977,-2976,-2976,-2976,-2976,
--2975,-2975,-2975,-2975,-2975,-2974,-2974,-2974,-2974,-2973,-2973,-2973,-2973,-2972,-2972,-2972,-2972,-2971,-2971,-2971,-2971,
--2971,-2970,-2970,-2970,-2970,-2969,-2969,-2969,-2969,-2968,-2968,-2968,-2968,-2968,-2967,-2967,-2967,-2967,-2966,-2966,-2966,
--2966,-2966,-2965,-2965,-2965,-2965,-2965,-2964,-2964,-2964,-2964,-2963,-2963,-2963,-2963,-2963,-2962,-2962,-2962,-2962,-2962,
--2961,-2961,-2961,-2961,-2961,-2960,-2960,-2960,-2960,-2960,-2959,-2959,-2959,-2959,-2959,-2958,-2958,-2958,-2958,-2958,-2958,
--2957,-2957,-2957,-2957,-2957,-2957,-2956,-2956,-2956,-2956,-2956,-2956,-2955,-2955,-2955,-2955,-2955,-2955,-2954,-2954,-2954,
--2954,-2954,-2954,-2953,-2953,-2953,-2953,-2953,-2953,-2953,-2952,-2952,-2952,-2952,-2952,-2952,-2952,-2952,-2951,-2951,-2951,
--2951,-2951,-2951,-2951,-2951,-2950,-2950,-2950,-2950,-2950,-2950,-2950,-2950,-2950,-2949,-2949,-2949,-2949,-2949,-2949,-2949,
--2949,-2949,-2949,-2948,-2948,-2948,-2948,-2948,-2948,-2948,-2948,-2948,-2948,-2948,-2948,-2947,-2947,-2947,-2947,-2947,-2947,
--2947,-2947,-2947,-2947,-2947,-2947,-2947,-2947,-2947,-2947,-2947,-2946,-2946,-2946,-2946,-2946,-2946,-2946,-2946,-2946,-2946,
--2946,-2946,-2946,-2946,-2946,-2946,-2946,-2946,-2946,-2946,-2946,-2946,-2946,-2946,-2946,-2946,-2946,-2946,-2946,-2946,-2946,
+-3013,-3013,-3013,-3013,-3013,-3013,-3013,-3013,-3013,-3013,-3013,-3013,-3013,-3013,-3013,-3013,-3013,-3013,-3013,-3013,-3013,
+-3012,-3012,-3012,-3012,-3012,-3012,-3012,-3012,-3012,-3012,-3012,-3012,-3012,-3012,-3012,-3012,-3012,-3012,-3012,-3011,-3011,
+-3011,-3011,-3011,-3011,-3011,-3011,-3011,-3011,-3011,-3011,-3011,-3011,-3010,-3010,-3010,-3010,-3010,-3010,-3010,-3010,-3010,
+-3010,-3010,-3009,-3009,-3009,-3009,-3009,-3009,-3009,-3009,-3009,-3009,-3008,-3008,-3008,-3008,-3008,-3008,-3008,-3008,-3008,
+-3007,-3007,-3007,-3007,-3007,-3007,-3007,-3007,-3006,-3006,-3006,-3006,-3006,-3006,-3006,-3005,-3005,-3005,-3005,-3005,-3005,
+-3005,-3004,-3004,-3004,-3004,-3004,-3004,-3003,-3003,-3003,-3003,-3003,-3003,-3003,-3002,-3002,-3002,-3002,-3002,-3002,-3001,
+-3001,-3001,-3001,-3001,-3000,-3000,-3000,-3000,-3000,-3000,-2999,-2999,-2999,-2999,-2999,-2998,-2998,-2998,-2998,-2998,-2998,
+-2997,-2997,-2997,-2997,-2997,-2996,-2996,-2996,-2996,-2996,-2995,-2995,-2995,-2995,-2995,-2994,-2994,-2994,-2994,-2993,-2993,
+-2993,-2993,-2993,-2992,-2992,-2992,-2992,-2992,-2991,-2991,-2991,-2991,-2990,-2990,-2990,-2990,-2990,-2989,-2989,-2989,-2989,
+-2988,-2988,-2988,-2988,-2987,-2987,-2987,-2987,-2987,-2986,-2986,-2986,-2986,-2985,-2985,-2985,-2985,-2984,-2984,-2984,-2984,
+-2984,-2983,-2983,-2983,-2983,-2982,-2982,-2982,-2982,-2981,-2981,-2981,-2981,-2980,-2980,-2980,-2980,-2980,-2979,-2979,-2979,
+-2979,-2978,-2978,-2978,-2978,-2977,-2977,-2977,-2977,-2976,-2976,-2976,-2976,-2975,-2975,-2975,-2975,-2975,-2974,-2974,-2974,
+-2974,-2973,-2973,-2973,-2973,-2972,-2972,-2972,-2972,-2971,-2971,-2971,-2971,-2971,-2970,-2970,-2970,-2970,-2969,-2969,-2969,
+-2969,-2968,-2968,-2968,-2968,-2968,-2967,-2967,-2967,-2967,-2966,-2966,-2966,-2966,-2966,-2965,-2965,-2965,-2965,-2965,-2964,
+-2964,-2964,-2964,-2963,-2963,-2963,-2963,-2963,-2962,-2962,-2962,-2962,-2962,-2961,-2961,-2961,-2961,-2961,-2960,-2960,-2960,
+-2960,-2960,-2959,-2959,-2959,-2959,-2959,-2958,-2958,-2958,-2958,-2958,-2958,-2957,-2957,-2957,-2957,-2957,-2957,-2956,-2956,
+-2956,-2956,-2956,-2956,-2955,-2955,-2955,-2955,-2955,-2955,-2954,-2954,-2954,-2954,-2954,-2954,-2953,-2953,-2953,-2953,-2953,
+-2953,-2953,-2952,-2952,-2952,-2952,-2952,-2952,-2952,-2952,-2951,-2951,-2951,-2951,-2951,-2951,-2951,-2951,-2950,-2950,-2950,
+-2950,-2950,-2950,-2950,-2950,-2950,-2949,-2949,-2949,-2949,-2949,-2949,-2949,-2949,-2949,-2949,-2948,-2948,-2948,-2948,-2948,
+-2948,-2948,-2948,-2948,-2948,-2948,-2948,-2947,-2947,-2947,-2947,-2947,-2947,-2947,-2947,-2947,-2947,-2947,-2947,-2947,-2947,
+-2947,-2947,-2947,-2946,-2946,-2946,-2946,-2946,-2946,-2946,-2946,-2946,-2946,-2946,-2946,-2946,-2946,-2946,-2946,-2946,-2946,
 -2946,-2946,-2946,-2946,-2946,-2946,-2946,-2946,-2946,-2946,-2946,-2946,-2946,-2946,-2946,-2946,-2946,-2946,-2946,-2946,-2946,
 -2946,-2946,-2946,-2946,-2946,-2946,-2946,-2946,-2946,-2946,-2946,-2946,-2946,-2946,-2946,-2946,-2946,-2946,-2946,-2946,-2946,
--2946,-2946,-2946,-2947,-2947,-2947,-2947,-2947,-2947,-2947,-2947,-2947,-2947,-2947,-2947,-2947,-2947,-2947,-2947,-2947,-2947,
--2947,-2948,-2948,-2948,-2948,-2948,-2948,-2948,-2948,-2948,-2948,-2948,-2948,-2948,-2948,-2948,-2948,-2949,-2949,-2949,-2949,
--2949,-2949,-2949,-2949,-2949,-2949,-2949,-2949,-2949,-2950,-2950,-2950,-2950,-2950,-2950,-2950,-2950,-2950,-2950,-2950,-2950,
--2950,-2951,-2951,-2951,-2951,-2951,-2951,-2951,-2951,-2951,-2951,-2951,-2952,-2952,-2952,-2952,-2952,-2952,-2952,-2952,-2952,
--2952,-2952,-2952,-2953,-2953,-2953,-2953,-2953,-2953,-2953,-2953,-2953,-2953,-2953,-2954,-2954,-2954,-2954,-2954,-2954,-2954,
--2954,-2954,-2953,-2953,-2953,-2953,-2953,-2953,-2953,-2953,-2953,-2953,-2953,-2953,-2953,-2953,-2953,-2953,-2953,-2953,-2953,
+-2946,-2946,-2946,-2946,-2946,-2946,-2946,-2946,-2946,-2946,-2946,-2946,-2946,-2946,-2946,-2946,-2947,-2947,-2947,-2947,-2947,
+-2947,-2947,-2947,-2947,-2947,-2947,-2947,-2947,-2947,-2947,-2947,-2947,-2947,-2947,-2948,-2948,-2948,-2948,-2948,-2948,-2948,
+-2948,-2948,-2948,-2948,-2948,-2948,-2948,-2948,-2948,-2949,-2949,-2949,-2949,-2949,-2949,-2949,-2949,-2949,-2949,-2949,-2949,
+-2949,-2950,-2950,-2950,-2950,-2950,-2950,-2950,-2950,-2950,-2950,-2950,-2950,-2950,-2951,-2951,-2951,-2951,-2951,-2951,-2951,
+-2951,-2951,-2951,-2951,-2952,-2952,-2952,-2952,-2952,-2952,-2952,-2952,-2952,-2952,-2952,-2952,-2953,-2953,-2953,-2953,-2953,
+-2953,-2953,-2953,-2953,-2953,-2953,-2954,-2954,-2954,-2954,-2954,-2954,-2954,-2954,-2954,-2953,-2953,-2953,-2953,-2953,-2953,
+-2953,-2953,-2953,-2953,-2953,-2953,-2953,-2953,-2953,-2953,-2953,-2953,-2953,-2953,-2953,-2953,-2953,-2953,-2953,-2953,-2953,
 -2953,-2953,-2953,-2953,-2953,-2953,-2953,-2953,-2953,-2953,-2953,-2953,-2953,-2953,-2953,-2953,-2953,-2953,-2953,-2953,-2953,
 -2953,-2953,-2953,-2953,-2953,-2953,-2953,-2953,-2953,-2953,-2953,-2953,-2953,-2953,-2953,-2953,-2953,-2953,-2953,-2953,-2953,
 -2953,-2953,-2953,-2953,-2953,-2953,-2953,-2953,-2953,-2953,-2953,-2953,-2953,-2953,-2953,-2953,-2953,-2953,-2953,-2953,-2953,
@@ -49551,7 +49504,7 @@ static short s_egm96grid[] = {
 -2953,-2953,-2953,-2953,-2953,-2953,-2953,-2953,-2953,-2953,-2953,-2953,-2953,-2953,-2953,-2953,-2953,-2953,-2953,-2953,-2953,
 -2953,-2953,-2953,-2953,-2953,-2953,-2953,-2953,-2953,-2953,-2953,-2953,-2953,-2953,-2953,-2953,-2953,-2953,-2953,-2953,-2953,
 -2953,-2953,-2953,-2953,-2953,-2953,-2953,-2953,-2953,-2953,-2953,-2953,-2953,-2953,-2953,-2953,-2953,-2953,-2953,-2953,-2953,
--2953,-2953,-2953,-2953,-2953,-2953,-2953,-2953,-2953,-2953,-2953,-2953,-2953,-2953,-2953 };
+-2953,-2953,-2953,-2953,-2953,-2953,-2953 };
 
 }
 
diff --git a/src/osgEarthDrivers/viewpoints/CMakeLists.txt b/src/osgEarthDrivers/viewpoints/CMakeLists.txt
new file mode 100644
index 0000000..76d3d2c
--- /dev/null
+++ b/src/osgEarthDrivers/viewpoints/CMakeLists.txt
@@ -0,0 +1,24 @@
+#
+# Viewpoints plugin
+#
+
+SET(TARGET_SRC
+	ViewpointsPlugin.cpp
+	ViewpointsExtension.cpp)
+	
+SET(LIB_PUBLIC_HEADERS
+	ViewpointsExtension)
+	
+SET(TARGET_H
+	${LIB_PUBLIC_HEADERS} )
+
+SET(TARGET_COMMON_LIBRARIES ${TARGET_COMMON_LIBRARIES}
+    osgEarthUtil)
+	
+setup_plugin(osgearth_viewpoints)
+
+# to install public driver includes:
+SET(LIB_NAME viewpoints)
+
+#INCLUDE(ModuleInstallOsgEarthExtensionIncludes OPTIONAL)
+
diff --git a/src/osgEarthDrivers/viewpoints/ViewpointsExtension b/src/osgEarthDrivers/viewpoints/ViewpointsExtension
new file mode 100644
index 0000000..40064f2
--- /dev/null
+++ b/src/osgEarthDrivers/viewpoints/ViewpointsExtension
@@ -0,0 +1,86 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+ * Copyright 2016 Pelican Mapping
+ * http://osgearth.org
+ *
+ * osgEarth is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ */
+#ifndef OSGEARTH_VIEWPOINTS_EXTENSION
+#define OSGEARTH_VIEWPOINTS_EXTENSION 1
+
+#include <osgEarth/Extension>
+#include <osgEarth/Viewpoint>
+#include <osgEarthUtil/Controls>
+#include <osgGA/GUIEventAdapter>
+#include <osg/View>
+#include <vector>
+
+namespace osgEarth { namespace Viewpoints
+{
+    using namespace osgEarth;
+    using namespace osgEarth::Util::Controls;
+
+    /**
+     * Loads a collection of viewpoints and makes them available
+     * through a Controls UI.
+     */
+    class ViewpointsExtension : public Extension,
+                                public ExtensionInterface<osg::View>,
+                                public ExtensionInterface<Control>,
+                                public ConfigOptions
+    {
+    public:
+        META_Object(osgearth_ext_viewpoints, ViewpointsExtension);
+
+        // CTORs
+        ViewpointsExtension();
+        ViewpointsExtension(const ConfigOptions& options);
+
+        // DTOR
+        virtual ~ViewpointsExtension();
+
+
+    public: // Extension
+
+        void setDBOptions(const osgDB::Options* dbOptions);
+
+        // Use "this" since this class derives from ConfigOptions.
+        const ConfigOptions& getConfigOptions() const { return *this; }
+
+
+    public: // ExtensionInterface<osg::View>
+
+        bool connect(osg::View* view);
+
+        bool disconnect(osg::View* view);
+
+
+    public: // ExtensionInterface<Control>
+
+        bool connect(Control* control);
+
+        bool disconnect(Control* control);
+
+
+    protected: // Object
+        ViewpointsExtension(const ViewpointsExtension& rhs, const osg::CopyOp& op) { }
+
+    private:
+        osg::ref_ptr<const osgDB::Options>   _dbOptions;
+        osg::ref_ptr<osgGA::GUIEventHandler> _handler;
+    };
+
+} } // namespace osgEarth::Viewpoints
+
+#endif // OSGEARTH_VIEWPOINTS_EXTENSION
diff --git a/src/osgEarthDrivers/viewpoints/ViewpointsExtension.cpp b/src/osgEarthDrivers/viewpoints/ViewpointsExtension.cpp
new file mode 100644
index 0000000..94859d8
--- /dev/null
+++ b/src/osgEarthDrivers/viewpoints/ViewpointsExtension.cpp
@@ -0,0 +1,244 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+ * Copyright 2016 Pelican Mapping
+ * http://osgearth.org
+ *
+ * osgEarth is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ */
+#include "ViewpointsExtension"
+#include <osgEarth/Viewpoint>
+#include <osgEarth/XmlUtils>
+#include <osgEarthUtil/EarthManipulator>
+#include <osgViewer/View>
+
+using namespace osgEarth;
+using namespace osgEarth::Util;
+using namespace osgEarth::Util::Controls;
+using namespace osgEarth::Viewpoints;
+
+#define LC "[ViewpointsExtension] "
+
+
+#define VP_MIN_DURATION      2.0     // minimum fly time.
+#define VP_METERS_PER_SECOND 2500.0  // fly speed
+#define VP_MAX_DURATION      2.0     // maximum fly time.
+
+namespace
+{
+    void flyToViewpoint(EarthManipulator* manip, const Viewpoint& vp, float t)
+    {
+        Viewpoint currentVP = manip->getViewpoint();
+        GeoPoint vp0 = currentVP.focalPoint().get();
+        GeoPoint vp1 = vp.focalPoint().get();
+        double distance = vp0.distanceTo(vp1);
+        double duration = osg::clampBetween(distance / VP_METERS_PER_SECOND, VP_MIN_DURATION, (double)t);
+        manip->setViewpoint( vp, duration );
+    }
+
+
+    struct ViewpointsHandler : public osgGA::GUIEventHandler
+    {
+        ViewpointsHandler(const std::vector<Viewpoint>& viewpoints, float t)
+            : _viewpoints( viewpoints ), _t(t) { }
+
+        bool handle( const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa )
+        {
+            if ( ea.getEventType() == ea.KEYDOWN )
+            {
+                if ( !_viewpoints.empty() )
+                {
+                    int index = (int)ea.getKey() - (int)'1';
+                    if ( index >= 0 && index < (int)_viewpoints.size() )
+                    {
+                        EarthManipulator* manip = getManip(aa);
+                        if ( manip )
+                            flyToViewpoint( manip, _viewpoints[index], _t );
+                    }
+                }
+                if ( ea.getKey() == 'v' )
+                {
+                    osgViewer::View* view = dynamic_cast<osgViewer::View*>(aa.asView());
+                    if ( view )
+                    {
+                        EarthManipulator* manip = getManip(aa);
+                        if ( manip )
+                        {
+                            XmlDocument xml( manip->getViewpoint().getConfig() );
+                            xml.store( std::cout );
+                            std::cout << std::endl;
+                        }
+                    }
+                }
+                aa.requestRedraw();
+            }
+
+            else if ( ea.getEventType() == ea.FRAME && _flyTo.isSet() )
+            {
+                EarthManipulator* manip = getManip(aa);
+                if ( manip )
+                    flyToViewpoint(manip, *_flyTo, _t);
+                _flyTo.unset();
+            }
+
+            return false;
+        }
+
+        EarthManipulator* getManip(osgGA::GUIActionAdapter& aa)
+        {
+            osgViewer::View* view = dynamic_cast<osgViewer::View*>(aa.asView());
+            return view ? dynamic_cast<EarthManipulator*>(view->getCameraManipulator()) : 0L;
+        }
+
+        std::vector<Viewpoint> _viewpoints;
+        optional<Viewpoint>    _flyTo;
+        float                  _t;
+    };
+
+
+    // flies to a viewpoint in response to control event (click)
+    struct ClickViewpointHandler : public ControlEventHandler
+    {
+        ClickViewpointHandler(const Viewpoint& vp, ViewpointsHandler* handler) :
+            _vp(vp), _handler(handler) { }
+
+        Viewpoint          _vp;
+        ViewpointsHandler* _handler;
+
+        virtual void onClick(Control* control)
+        {
+            _handler->_flyTo = _vp;
+        }
+    };
+
+
+    Control* createViewpointControl(ViewpointsHandler* handler)
+    {
+        Grid* grid = 0L;
+
+        if ( handler->_viewpoints.size() > 0 )
+        {
+            // the viewpoint container:
+            grid = new Grid();
+            grid->setChildSpacing( 0 );
+            grid->setChildVertAlign( Control::ALIGN_CENTER );
+
+            for( unsigned i=0; i<handler->_viewpoints.size(); ++i )
+            {
+                const Viewpoint& vp = handler->_viewpoints[i];
+                Control* num = new LabelControl(Stringify() << (i+1), 16.0f, osg::Vec4f(1,1,0,1));
+                num->setPadding( 4 );
+                grid->setControl( 0, i, num );
+
+                Control* vpc = new LabelControl(vp.name()->empty() ? "<no name>" : vp.name().get(), 16.0f);
+                vpc->setPadding( 4 );
+                vpc->setHorizFill( true );
+                vpc->setActiveColor( osg::Vec4(0.4,0.4,1.0,1.0) ); // blue
+                vpc->addEventHandler( new ClickViewpointHandler(vp, handler) );
+                grid->setControl( 1, i, vpc );
+            }
+        }
+
+        return grid;
+    }
+}
+
+//.........................................................................
+
+
+ViewpointsExtension::ViewpointsExtension()
+{
+    //NOP
+}
+
+ViewpointsExtension::ViewpointsExtension(const ConfigOptions& options) :
+ConfigOptions( options )
+{
+    // backwards-compatibility: read viewpoints at the top level???
+    const Config& viewpointsConf = options.getConfig();
+    float t = viewpointsConf.value("time", VP_MAX_DURATION);
+
+    std::vector<Viewpoint> viewpoints;
+
+    const ConfigSet& children = viewpointsConf.children("viewpoint");
+    if ( children.size() > 0 )
+    {
+        for( ConfigSet::const_iterator i = children.begin(); i != children.end(); ++i )
+        {
+            viewpoints.push_back( Viewpoint(*i) );
+        }
+    }
+
+    OE_INFO << LC << "Read " << viewpoints.size() << " viewpoints\n";
+
+    _handler = new ViewpointsHandler(viewpoints, t);
+}
+
+ViewpointsExtension::~ViewpointsExtension()
+{
+    //nop
+}
+
+void
+ViewpointsExtension::setDBOptions(const osgDB::Options* dbOptions)
+{
+    _dbOptions = dbOptions;
+}
+
+bool
+ViewpointsExtension::connect(osg::View* view)
+{
+    osgViewer::View* v = dynamic_cast<osgViewer::View*>(view);
+    if ( v && _handler.valid() )
+    {
+        v->addEventHandler( _handler.get() );
+    }
+    return true;
+}
+
+bool
+ViewpointsExtension::disconnect(osg::View* view)
+{
+    //TODO: remove the event handler
+    osgViewer::View* v = dynamic_cast<osgViewer::View*>(view);
+    if ( v && _handler.valid() )
+    {
+        v->removeEventHandler( _handler.get() );
+    }
+    return true;
+}
+
+bool
+ViewpointsExtension::connect(Control* control)
+{
+    //TODO add a UI.
+    Container* container = dynamic_cast<Container*>(control);
+    if ( container )
+    {
+        ViewpointsHandler* vh = static_cast<ViewpointsHandler*>(_handler.get());
+        if ( vh->_viewpoints.size() > 0 )
+        {
+            Control* c = createViewpointControl( vh );
+            if ( c )
+                container->addControl( c );
+        }
+    }
+    return true;
+}
+
+bool
+ViewpointsExtension::disconnect(Control* control)
+{
+    // TODO: remove the UI
+    return true;
+}
diff --git a/src/osgEarthDrivers/viewpoints/ViewpointsPlugin.cpp b/src/osgEarthDrivers/viewpoints/ViewpointsPlugin.cpp
new file mode 100644
index 0000000..d5f4645
--- /dev/null
+++ b/src/osgEarthDrivers/viewpoints/ViewpointsPlugin.cpp
@@ -0,0 +1,55 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+ * Copyright 2016 Pelican Mapping
+ * http://osgearth.org
+ *
+ * osgEarth is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ */
+#include "ViewpointsExtension"
+
+#include <osgDB/ReaderWriter>
+#include <osgDB/Registry>
+#include <osgDB/FileNameUtils>
+
+namespace osgEarth { namespace Viewpoints
+{
+    /**
+     * Plugin entry point
+     */
+    class ViewpointsPlugin : public osgDB::ReaderWriter
+    {
+    public: // Plugin stuff
+
+        ViewpointsPlugin() {
+            supportsExtension( "osgearth_viewpoints", "osgEarth Viewpoints Extension" );
+        }
+        
+        const char* className() const {
+            return "osgEarth Viewpoints Extension";
+        }
+
+        virtual ~ViewpointsPlugin() { }
+
+        ReadResult readObject(const std::string& filename, const osgDB::Options* dbOptions) const
+        {
+          if ( !acceptsExtension(osgDB::getLowerCaseFileExtension(filename)) )
+                return ReadResult::FILE_NOT_HANDLED;
+
+          return ReadResult( new ViewpointsExtension(Extension::getConfigOptions(dbOptions)) );
+        }
+    };
+
+    REGISTER_OSGPLUGIN(osgearth_viewpoints, ViewpointsPlugin)
+
+} } // namespace osgEarth::Viewpoints
diff --git a/src/osgEarthDrivers/vpb/ReaderWriterVPB.cpp b/src/osgEarthDrivers/vpb/ReaderWriterVPB.cpp
index e16b280..b202e62 100644
--- a/src/osgEarthDrivers/vpb/ReaderWriterVPB.cpp
+++ b/src/osgEarthDrivers/vpb/ReaderWriterVPB.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -627,7 +627,7 @@ class VPBSourceFactory : public TileSourceDriver
             supportsExtension( "osgearth_vpb", "VirtualPlanetBuilder data" );
         }
 
-        virtual const char* className()
+        virtual const char* className() const
         {
             return "VirtualPlanetBuilder ReaderWriter";
         }
diff --git a/src/osgEarthDrivers/vpb/VPBOptions b/src/osgEarthDrivers/vpb/VPBOptions
index 9f2b3d1..68766e2 100644
--- a/src/osgEarthDrivers/vpb/VPBOptions
+++ b/src/osgEarthDrivers/vpb/VPBOptions
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthDrivers/wcs/CMakeLists.txt b/src/osgEarthDrivers/wcs/CMakeLists.txt
index 34525c2..fe3c8bc 100644
--- a/src/osgEarthDrivers/wcs/CMakeLists.txt
+++ b/src/osgEarthDrivers/wcs/CMakeLists.txt
@@ -3,7 +3,9 @@ OPTION(CURL_IS_STATIC "on if curl is a static lib " ON)
 MARK_AS_ADVANCED(CURL_IS_STATIC)
 
 IF(WIN32)
-    SET(CMAKE_SHARED_LINKER_FLAGS_DEBUG "${CMAKE_SHARED_LINKER_FLAGS_DEBUG} /NODEFAULTLIB:MSVCRT")
+    IF(MSVC)
+        SET(CMAKE_SHARED_LINKER_FLAGS_DEBUG "${CMAKE_SHARED_LINKER_FLAGS_DEBUG} /NODEFAULTLIB:MSVCRT")
+    ENDIF(MSVC)
     IF(CURL_IS_STATIC)
         ADD_DEFINITIONS(-DCURL_STATICLIB)
         SET(TARGET_EXTERNAL_LIBRARIES ws2_32 winmm)
diff --git a/src/osgEarthDrivers/wcs/ReaderWriterWCS.cpp b/src/osgEarthDrivers/wcs/ReaderWriterWCS.cpp
index ff425b6..276ff26 100644
--- a/src/osgEarthDrivers/wcs/ReaderWriterWCS.cpp
+++ b/src/osgEarthDrivers/wcs/ReaderWriterWCS.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -32,7 +32,7 @@ class WCSSourceFactory : public TileSourceDriver
 public:
     WCSSourceFactory() {}
 
-    virtual const char* className()
+    virtual const char* className() const
     {
         return "WCS 1.1.0 Reader";
     }
diff --git a/src/osgEarthDrivers/wcs/WCS11Source.cpp b/src/osgEarthDrivers/wcs/WCS11Source.cpp
index 68d621e..bad44a9 100644
--- a/src/osgEarthDrivers/wcs/WCS11Source.cpp
+++ b/src/osgEarthDrivers/wcs/WCS11Source.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -43,7 +43,7 @@ _options  ( options )
 
 
 
-osgEarth::TileSource::Status WCS11Source::initialize(const osgDB::Options* dbOptions)
+osgEarth::Status WCS11Source::initialize(const osgDB::Options* dbOptions)
 {        
     //TODO: fetch GetCapabilities and set profile from there.
     setProfile( osgEarth::Registry::instance()->getGlobalGeodeticProfile() );
diff --git a/src/osgEarthDrivers/wcs/WCS11Source.h b/src/osgEarthDrivers/wcs/WCS11Source.h
index 2db2654..d5a4f50 100644
--- a/src/osgEarthDrivers/wcs/WCS11Source.h
+++ b/src/osgEarthDrivers/wcs/WCS11Source.h
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthDrivers/wcs/WCSOptions b/src/osgEarthDrivers/wcs/WCSOptions
index 031bd39..fbe661f 100644
--- a/src/osgEarthDrivers/wcs/WCSOptions
+++ b/src/osgEarthDrivers/wcs/WCSOptions
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthDrivers/wms/ReaderWriterWMS.cpp b/src/osgEarthDrivers/wms/ReaderWriterWMS.cpp
index 95326e5..ade62fc 100644
--- a/src/osgEarthDrivers/wms/ReaderWriterWMS.cpp
+++ b/src/osgEarthDrivers/wms/ReaderWriterWMS.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -117,7 +117,7 @@ public:
         osg::ref_ptr<WMSCapabilities> capabilities = WMSCapabilitiesReader::read( capUrl.full(), dbOptions );
         if ( !capabilities.valid() )
         {
-            return Status::Error( "Unable to read WMS GetCapabilities." );
+            return Status::Error( Status::ResourceUnavailable, "Unable to read WMS GetCapabilities." );
         }
         else
         {
@@ -274,7 +274,7 @@ public:
             // set up the cache options properly for a TileSource.
             _dbOptions = Registry::instance()->cloneOrCreateOptions( dbOptions );            
 
-            return STATUS_OK;
+            return Status::OK();
         }
         else
         {
@@ -579,7 +579,7 @@ class WMSSourceFactory : public TileSourceDriver
     public:
         WMSSourceFactory() {}
 
-        virtual const char* className()
+        virtual const char* className() const
         {
             return "WMS Reader";
         }
diff --git a/src/osgEarthDrivers/wms/TileService b/src/osgEarthDrivers/wms/TileService
index 921e2c2..6097d3b 100644
--- a/src/osgEarthDrivers/wms/TileService
+++ b/src/osgEarthDrivers/wms/TileService
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthDrivers/wms/TileService.cpp b/src/osgEarthDrivers/wms/TileService.cpp
index bdc7023..adaa628 100644
--- a/src/osgEarthDrivers/wms/TileService.cpp
+++ b/src/osgEarthDrivers/wms/TileService.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthDrivers/wms/WMSOptions b/src/osgEarthDrivers/wms/WMSOptions
index eedbd6e..b2f259c 100644
--- a/src/osgEarthDrivers/wms/WMSOptions
+++ b/src/osgEarthDrivers/wms/WMSOptions
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthDrivers/xyz/ReaderWriterXYZ.cpp b/src/osgEarthDrivers/xyz/ReaderWriterXYZ.cpp
index a60ffa9..a331b08 100644
--- a/src/osgEarthDrivers/xyz/ReaderWriterXYZ.cpp
+++ b/src/osgEarthDrivers/xyz/ReaderWriterXYZ.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
@@ -50,7 +50,7 @@ class XYZSource : public TileSource
 {
 public:
     XYZSource(const TileSourceOptions& options) : 
-      TileSource(options), _options(options), _rotate_iter(0u)
+        TileSource(options), _options(options), _rotate_iter(0u), _rotateStart(0), _rotateEnd(0)
     {
         //nop
     }
@@ -63,13 +63,13 @@ public:
         URI xyzURI = _options.url().value();
         if ( xyzURI.empty() )
         {
-            return Status::Error( "Fail: driver requires a valid \"url\" property" );
+            return Status::Error( Status::ConfigurationError, "Fail: driver requires a valid \"url\" property" );
         }
 
         // driver requires a profile.
         if ( !getProfile() )
         {
-            return Status::Error( "An explicit profile definition is required by the XYZ driver." );
+            return Status::Error( Status::ConfigurationError, "An explicit profile definition is required by the XYZ driver." );
         }
 
         _template = xyzURI.full();
@@ -162,7 +162,7 @@ public:
         supportsExtension( "osgearth_xyz", "XYZ Driver" );
     }
 
-    virtual const char* className()
+    virtual const char* className() const
     {
         return "XYZ Driver";
     }
diff --git a/src/osgEarthDrivers/xyz/XYZOptions b/src/osgEarthDrivers/xyz/XYZOptions
index f3d5460..f6b6cbf 100644
--- a/src/osgEarthDrivers/xyz/XYZOptions
+++ b/src/osgEarthDrivers/xyz/XYZOptions
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthDrivers/yahoo/ReaderWriterYahoo.cpp b/src/osgEarthDrivers/yahoo/ReaderWriterYahoo.cpp
index ad9d3f6..f3408aa 100644
--- a/src/osgEarthDrivers/yahoo/ReaderWriterYahoo.cpp
+++ b/src/osgEarthDrivers/yahoo/ReaderWriterYahoo.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -43,11 +43,10 @@ public:
     }
 
     // Yahoo! uses spherical mercator, but the top LOD is a 2x2 tile set.
-    Status initialize(const osgDB::Options* dbOptions)
+    Status initialize(const osgDB::Options* readOptions)
     {
         // no caching of source tiles.  Yahoo TOS does not allow it.
-        _dbOptions = Registry::instance()->cloneOrCreateOptions( dbOptions );
-        CachePolicy::NO_CACHE.apply( _dbOptions.get() );
+        _readOptions = readOptions;
 
         // always a sperhical mercator profile
         setProfile( Profile::create( "spherical-mercator", "", 2, 2 ) );
@@ -55,13 +54,8 @@ public:
         return STATUS_OK;
     }
 
-    osg::Image* createImage(const TileKey&        key,
-                            ProgressCallback*     progress )
+    osg::Image* createImage(const TileKey& key, ProgressCallback* progress)
     {
-        //Return NULL if we are given a non global-mercator key
-        //Not applicable
-        //if ( !key.getProfile()->getProfileType() == Profile::TYPE_MERCATOR ) return 0;
-
         std::stringstream buf;
 
         std::string dataset = 
@@ -102,7 +96,7 @@ public:
 
         OE_DEBUG << key.str() << "=" << base << std::endl;
 
-        return URI(base).readImage( _dbOptions.get() ).releaseImage();
+        return URI(base).readImage( _readOptions.get() ).releaseImage();
     }
 
     osg::HeightField* createHeightField(const TileKey&        key,
@@ -126,8 +120,8 @@ public:
     }
 
 private:
-    const YahooOptions           _options;
-    osg::ref_ptr<osgDB::Options> _dbOptions;
+    const YahooOptions                 _options;
+    osg::ref_ptr<const osgDB::Options> _readOptions;
 };
 
 
@@ -139,7 +133,7 @@ class ReaderWriterYahoo : public TileSourceDriver
             supportsExtension( "osgearth_yahoo", "Yahoo maps data" );
         }
 
-        virtual const char* className()
+        virtual const char* className() const
         {
             return "Yahoo Imagery ReaderWriter";
         }
diff --git a/src/osgEarthDrivers/yahoo/YahooOptions b/src/osgEarthDrivers/yahoo/YahooOptions
index 77a2c16..097b85b 100644
--- a/src/osgEarthDrivers/yahoo/YahooOptions
+++ b/src/osgEarthDrivers/yahoo/YahooOptions
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthDriversDisabled/geobuf/CMakeLists.txt b/src/osgEarthDriversDisabled/geobuf/CMakeLists.txt
new file mode 100644
index 0000000..ee7b5cc
--- /dev/null
+++ b/src/osgEarthDriversDisabled/geobuf/CMakeLists.txt
@@ -0,0 +1,22 @@
+FIND_PACKAGE(Protobuf)
+
+IF(PROTOBUF_FOUND)
+
+INCLUDE_DIRECTORIES( ${PROTOBUF_INCLUDE_DIR} ${CMAKE_CURRENT_BINARY_DIR})
+
+PROTOBUF_GENERATE_CPP(PROTO_CPP PROTO_H geobuf.proto)
+
+SET(TARGET_SRC
+    ReaderWriterGeobuf.cpp
+    ${PROTO_CPP}
+)
+
+SET(TARGET_H   	
+    ${PROTO_H}
+)
+
+SET(TARGET_COMMON_LIBRARIES ${TARGET_COMMON_LIBRARIES} osgEarthFeatures osgEarthSymbology osgEarthUtil)
+SET(TARGET_LIBRARIES_VARSPROTOBUF_LIBRARY)
+SETUP_PLUGIN(geobuf)
+
+ENDIF(PROTOBUF_FOUND)
\ No newline at end of file
diff --git a/src/osgEarthDriversDisabled/geobuf/ReaderWriterGeobuf.cpp b/src/osgEarthDriversDisabled/geobuf/ReaderWriterGeobuf.cpp
new file mode 100644
index 0000000..8f0388a
--- /dev/null
+++ b/src/osgEarthDriversDisabled/geobuf/ReaderWriterGeobuf.cpp
@@ -0,0 +1,90 @@
+#include <osg/Notify>
+#include <osgDB/ReaderWriter>
+#include <osgDB/FileUtils>
+#include <osgDB/FileNameUtils>
+#include <osgDB/WriteFile>
+#include <osgEarth/JsonUtils>
+#include <osgEarthFeatures/FeatureListSource>
+
+#include "geobuf.pb.h"
+
+using namespace osgEarth;
+using namespace osgEarth::Features;
+
+class GeoBufReaderWriter: public osgDB::ReaderWriter
+{
+    public:
+        GeoBufReaderWriter()
+        {
+            supportsExtension("geobuf","GeoBuf");
+        }
+
+        virtual const char* className() { return "GeoJSON Feature Reader"; }
+
+        virtual bool acceptsExtension(const std::string& extension) const
+        {
+            return osgDB::equalCaseInsensitive(extension,"geobuf");
+        }
+
+        virtual ReadResult readObject(const std::string& fileName,const Options* options) const
+        {
+            if ( !acceptsExtension(osgDB::getLowerCaseFileExtension(fileName)) )
+                return ReadResult::FILE_NOT_HANDLED;
+
+            if (osgDB::fileExists(fileName) && (osgDB::fileType(fileName) == osgDB::REGULAR_FILE))
+            {
+                std::ifstream in( fileName.c_str() );
+                return readObject(in, options);
+            }
+            return ReadResult::ERROR_IN_READING_FILE;
+        }
+
+        virtual ReadResult readObject(std::istream& fin,const Options* options) const
+        {
+            osg::ref_ptr< FeatureListSource > featureSource = new FeatureListSource();
+
+            if (Feature::featuresFromGeoJSON( fin, featureSource->getFeatures()))
+            {
+                return featureSource.release();
+            }
+            return ReadResult::ERROR_IN_READING_FILE;
+        }
+
+        virtual WriteResult writeObject(const osg::Object& object, const std::string& fileName, const osgDB::Options* options ) const
+        {
+            if ( !acceptsExtension( osgDB::getFileExtension(fileName) ) )
+                return WriteResult::FILE_NOT_HANDLED;
+
+            std::ofstream out( fileName.c_str());
+            if ( out.is_open() )
+                return writeObject( object, out, options );
+
+            return WriteResult::ERROR_IN_WRITING_FILE;            
+        }
+
+        virtual WriteResult writeObject(const osg::Object& object, std::ostream& out, const osgDB::Options* options ) const
+        {
+
+          
+            FeatureSource* featureSource = const_cast<FeatureSource*>(dynamic_cast<const FeatureSource*>(&object));
+            if (!featureSource)
+            {
+                return WriteResult::ERROR_IN_WRITING_FILE; // i.e., no MapNode found in the graph.
+            }
+
+            Data data;                
+
+            osgEarth::Features::FeatureList features;
+            osg::ref_ptr< FeatureCursor > cursor = featureSource->createFeatureCursor();
+            while (cursor.valid() && cursor->hasMore())
+            {
+                Data_Feature* feature = data.mutable_feature_collection()->mutable_features()->Add();
+                feature->mutable_geometry()->set_type(Data_Geometry_Type::Data_Geometry_Type_POLYGON);
+                feature->mutable_geometry()->add_coords(62.0);
+            }
+            
+            return WriteResult::FILE_SAVED;
+        }
+};
+
+REGISTER_OSGPLUGIN(geobuf, GeoBufReaderWriter)
diff --git a/src/osgEarthDriversDisabled/geobuf/geobuf.proto b/src/osgEarthDriversDisabled/geobuf/geobuf.proto
new file mode 100644
index 0000000..26b742b
--- /dev/null
+++ b/src/osgEarthDriversDisabled/geobuf/geobuf.proto
@@ -0,0 +1,66 @@
+option optimize_for = LITE_RUNTIME;
+
+message Data {
+    repeated string keys = 1; // global arrays of unique keys
+
+    optional uint32 dimensions = 2 [default = 2]; // max coordinate dimensions
+    optional uint32 precision = 3 [default = 6]; // number of digits after decimal point for coordinates
+
+    oneof data_type {
+        FeatureCollection feature_collection = 4;
+        Feature feature = 5;
+        Geometry geometry = 6;
+    }
+
+    message Feature {
+        required Geometry geometry = 1;
+
+        oneof id_type {
+            string id = 11;
+            sint64 int_id = 12;
+        }
+
+        repeated Value values = 13; // unique values
+        repeated uint32 properties = 14 [packed = true]; // pairs of key/value indexes
+        repeated uint32 custom_properties = 15 [packed = true]; // arbitrary properties
+    }
+
+    message Geometry {
+        required Type type = 1;
+
+        repeated uint32 lengths = 2 [packed = true]; // coordinate structure in lengths
+        repeated sint64 coords = 3 [packed = true]; // delta-encoded integer values
+        repeated Geometry geometries = 4;
+
+        repeated Value values = 13;
+        repeated uint32 custom_properties = 15 [packed = true];
+
+        enum Type {
+            POINT = 0;
+            MULTIPOINT = 1;
+            LINESTRING = 2;
+            MULTILINESTRING = 3;
+            POLYGON = 4;
+            MULTIPOLYGON = 5;
+            GEOMETRYCOLLECTION = 6;
+        }
+    }
+
+    message FeatureCollection {
+        repeated Feature features = 1;
+
+        repeated Value values = 13;
+        repeated uint32 custom_properties = 15 [packed = true];
+    }
+
+    message Value {
+        oneof value_type {
+            string string_value = 1;
+            double double_value = 2;
+            uint64 pos_int_value = 3;
+            uint64 neg_int_value = 4;
+            bool bool_value = 5;
+            string json_value = 6;
+        }
+    }
+}
diff --git a/src/osgEarthDrivers/model_feature_stencil/CMakeLists.txt b/src/osgEarthDriversDisabled/model_feature_stencil/CMakeLists.txt
similarity index 100%
rename from src/osgEarthDrivers/model_feature_stencil/CMakeLists.txt
rename to src/osgEarthDriversDisabled/model_feature_stencil/CMakeLists.txt
diff --git a/src/osgEarthDrivers/model_feature_stencil/FeatureStencilModelOptions b/src/osgEarthDriversDisabled/model_feature_stencil/FeatureStencilModelOptions
similarity index 100%
rename from src/osgEarthDrivers/model_feature_stencil/FeatureStencilModelOptions
rename to src/osgEarthDriversDisabled/model_feature_stencil/FeatureStencilModelOptions
diff --git a/src/osgEarthDriversDisabled/model_feature_stencil/FeatureStencilModelSource.cpp b/src/osgEarthDriversDisabled/model_feature_stencil/FeatureStencilModelSource.cpp
new file mode 100644
index 0000000..ae89f1c
--- /dev/null
+++ b/src/osgEarthDriversDisabled/model_feature_stencil/FeatureStencilModelSource.cpp
@@ -0,0 +1,380 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+ * Copyright 2015 Pelican Mapping
+ * http://osgearth.org
+ *
+ * osgEarth is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+#include <osgEarth/Registry>
+#include <osgEarth/Map>
+#include <osgEarthFeatures/FeatureModelSource>
+#include <osgEarthFeatures/FeatureSource>
+#include <osgEarthFeatures/AltitudeFilter>
+#include <osgEarthFeatures/BufferFilter>
+#include <osgEarthFeatures/TransformFilter>
+#include <osgEarthFeatures/ResampleFilter>
+#include <osgEarthFeatures/ConvertTypeFilter>
+#include <osgEarthFeatures/ExtrudeGeometryFilter>
+#include <osgEarthSymbology/StencilVolumeNode>
+#include <osgEarthSymbology/Style>
+#include <osg/Notify>
+#include <osg/MatrixTransform>
+#include <osg/ClusterCullingCallback>
+#include <osg/Geode>
+#include <osg/Projection>
+#include <osgUtil/Tessellator>
+#include <osg/MatrixTransform>
+#include <osgDB/FileNameUtils>
+#include <OpenThreads/Mutex>
+#include <OpenThreads/ScopedLock>
+
+#include "FeatureStencilModelOptions"
+
+using namespace osgEarth;
+using namespace osgEarth::Features;
+using namespace osgEarth::Symbology;
+using namespace osgEarth::Drivers;
+using namespace OpenThreads;
+
+#define LC "[FeatureStencilModelSource] "
+
+#define RENDER_BIN_START 100
+#define MAX_NUM_STYLES   100
+#define OFF_PROTECTED osg::StateAttribute::OFF | osg::StateAttribute::PROTECTED
+
+namespace
+{
+    /** Creates a full-screen quad to fill in the colors on the stencil volume. */
+    osg::Node* createColorNode( const osg::Vec4f& color )
+    {
+        // make a full screen quad:
+        osg::Geometry* quad = new osg::Geometry();
+        quad->setUseVertexBufferObjects(true);
+
+        osg::Vec3Array* verts = new osg::Vec3Array(4);
+        (*verts)[0].set( 0, 1, 0 );
+        (*verts)[1].set( 0, 0, 0 );
+        (*verts)[2].set( 1, 0, 0 );
+        (*verts)[3].set( 1, 1, 0 );
+        quad->setVertexArray( verts );
+        if ( verts->getVertexBufferObject() )
+            verts->getVertexBufferObject()->setUsage(GL_STATIC_DRAW_ARB);
+
+        quad->addPrimitiveSet( new osg::DrawArrays( osg::PrimitiveSet::QUADS, 0, 4 ) );
+        osg::Vec4Array* colors = new osg::Vec4Array(1);
+        (*colors)[0] = color;
+        quad->setColorArray( colors );
+        quad->setColorBinding( osg::Geometry::BIND_OVERALL );
+        osg::Geode* quad_geode = new osg::Geode();
+        quad_geode->addDrawable( quad );
+
+        osg::StateSet* quad_ss = quad->getOrCreateStateSet();
+        quad_ss->setMode( GL_CULL_FACE, OFF_PROTECTED );
+        quad_ss->setMode( GL_DEPTH_TEST, OFF_PROTECTED );
+        quad_ss->setMode( GL_LIGHTING, OFF_PROTECTED );
+        osg::MatrixTransform* abs = new osg::MatrixTransform();
+        abs->setReferenceFrame( osg::Transform::ABSOLUTE_RF );
+        abs->setMatrix( osg::Matrix::identity() );
+        abs->addChild( quad_geode );
+
+        osg::Projection* proj = new osg::Projection();
+        proj->setMatrix( osg::Matrix::ortho(0, 1, 0, 1, 0, -1) );
+        proj->addChild( abs );
+
+        proj->getOrCreateStateSet()->setMode( GL_BLEND, 1 );    
+
+        return proj;
+    }
+
+    struct BuildData // : public osg::Referenced
+    {
+        //BuildData() { }
+        BuildData( int renderBinStart ) : _renderBin( renderBinStart ) { }
+
+        typedef std::pair<std::string, osg::ref_ptr<StencilVolumeNode> > StyleGroup;
+        int                       _renderBin;
+        Threading::ReadWriteMutex _mutex;
+        std::vector<StyleGroup>   _styleGroups;  // NOTE: DO NOT ACCESS without a mutex!
+
+
+        bool getStyleNode( const std::string& styleName, StencilVolumeNode*& out_svn, bool useLock )
+        {
+            if ( useLock )
+            {
+                Threading::ScopedReadLock lock( _mutex );
+                return getStyleNodeWithoutLocking( styleName, out_svn );
+            }
+            else
+            {
+                return getStyleNodeWithoutLocking( styleName, out_svn );
+            }
+        }
+
+    private:
+        bool getStyleNodeWithoutLocking( const std::string& styleName, StencilVolumeNode*& out_svn )
+        {
+            for(std::vector<StyleGroup>::iterator i = _styleGroups.begin(); i != _styleGroups.end(); ++i )
+            {
+                if( i->first == styleName )
+                {
+                    out_svn = i->second.get();
+                    return true;
+                }
+            }
+            return false;
+        }
+    };
+
+    class StencilVolumeNodeFactory : public FeatureNodeFactory
+    {
+    protected:
+        const FeatureStencilModelOptions _options;
+        int                              _renderBinStart;
+        BuildData                        _buildData;
+
+    public:
+        StencilVolumeNodeFactory( const FeatureStencilModelOptions& options, int renderBinStart )
+            : _options(options),
+              _buildData( renderBinStart )
+        { }
+
+        //override
+        bool createOrUpdateNode(
+            FeatureCursor*            cursor,
+            const Style&              style,
+            const FilterContext&      context,
+            osg::ref_ptr<osg::Node>&  node )
+        {
+            const MapInfo& mi = context.getSession()->getMapInfo();
+            
+            // A processing context to use locally
+            FilterContext cx = context;
+
+            // make a working copy of the feature data.
+            FeatureList featureList;
+            cursor->fill( featureList );
+
+            // establish the extrusion distance for the stencil volumes
+            double extrusionDistance = 1;
+            double densificationThreshold = 1.0;
+            if ( _options.extrusionDistance().isSet() )
+            {
+                extrusionDistance = *_options.extrusionDistance();
+            }
+            else
+            {
+                if ( mi.isGeocentric() )
+                    extrusionDistance = 300000.0; // meters geocentric
+                else if ( mi.getProfile()->getSRS()->isGeographic() )
+                    extrusionDistance = 5.0; // degrees-as-meters
+                else
+                    extrusionDistance = 12000.0; // meters
+            }
+
+            densificationThreshold = *_options.densificationThreshold();
+
+            // Scan the geometry to see if it includes line data, since that will require buffering:
+            bool hasLines = style.has<LineSymbol>() && !style.has<PolygonSymbol>();
+
+            // If the geometry is lines, we need to buffer them before they will work with stenciling
+            if ( hasLines )
+            {
+                const LineSymbol* line = style.getSymbol<LineSymbol>();
+                if (line)
+                {
+                    BufferFilter buffer;
+                    buffer.distance() = 0.5 * line->stroke()->width().value();
+                    buffer.capStyle() = line->stroke()->lineCap().value();
+                    cx = buffer.push( featureList, cx );
+                }
+            }
+
+            // Extrude and cap the geometry in both directions to build a stencil volume:
+
+            Style bs;
+            bs.getOrCreate<AltitudeSymbol>()->verticalOffset() = -extrusionDistance;
+            bs.getOrCreate<ExtrusionSymbol>()->height() = extrusionDistance * 2.0;
+            
+            AltitudeFilter alt;
+            alt.setPropertiesFromStyle( bs );
+            cx = alt.push( featureList, cx );
+
+            ExtrudeGeometryFilter extrude;
+            extrude.setStyle( bs );
+            extrude.setMakeStencilVolume( true );
+            osg::Node* volumes = extrude.push( featureList, cx );           
+
+            if ( volumes )
+            {
+                // Apply an LOD if required:
+                if ( _options.minRange().isSet() || _options.maxRange().isSet() )
+                {
+                    osg::LOD* lod = new osg::LOD();
+                    lod->addChild( volumes, _options.minRange().value(), _options.maxRange().value() );
+                    volumes = lod;
+                }
+
+                // Add the volumes to the appropriate style group.
+                osg::Group* styleGroup = getOrCreateStyleGroup( style, cx.getSession() );
+                StencilVolumeNode* svNode = dynamic_cast<StencilVolumeNode*>( styleGroup );
+                if ( svNode )
+                    svNode->addVolumes( volumes );
+                else
+                    styleGroup->addChild( volumes );
+            }
+
+            node = 0L; // always return null, since we added our geom to the style group.
+            return volumes != 0L;
+        }
+
+        //override
+        osg::Group* getOrCreateStyleGroup( const Style& style, Session* session )
+        {
+            if ( _options.showVolumes() == true )
+            {
+                return new osg::Group();
+            }
+            else
+            {
+                StencilVolumeNode* styleNode = 0L;
+                if ( !_buildData.getStyleNode(style.getName(), styleNode, true) )
+                {
+                    // did not find; write-lock it and try again (double-check pattern)
+                    Threading::ScopedWriteLock exclusiveLock( _buildData._mutex );
+
+                    if ( !_buildData.getStyleNode(style.getName(), styleNode, false) )
+                    {
+                        OE_INFO << LC << "Create style group \"" << style.getName() << "\"" << std::endl;
+
+                        styleNode = new StencilVolumeNode( *_options.mask(), *_options.inverted() );
+
+                        if ( _options.mask() == false )
+                        {
+                            osg::Vec4f maskColor = osg::Vec4(1,1,0,1);
+
+                            if (/*hasLines &&*/ style.getSymbol<LineSymbol>())
+                            {
+                                const LineSymbol* line = style.getSymbol<LineSymbol>();
+                                maskColor = line->stroke()->color();
+                            } 
+                            else
+                            {
+                                const PolygonSymbol* poly = style.getSymbol<PolygonSymbol>();
+                                if (poly)
+                                    maskColor = poly->fill()->color();
+                            }
+                            styleNode->addChild( createColorNode(maskColor) );
+                            
+                            osg::StateSet* ss = styleNode->getOrCreateStateSet();
+
+                            ss->setMode( GL_LIGHTING, _options.enableLighting() == true?
+                                 osg::StateAttribute::ON | osg::StateAttribute::PROTECTED :
+                                 osg::StateAttribute::OFF | osg::StateAttribute::PROTECTED );
+                        }
+
+                        _buildData._renderBin = styleNode->setBaseRenderBin( _buildData._renderBin );
+                        _buildData._styleGroups.push_back( BuildData::StyleGroup(style.getName(), styleNode) );
+                    }
+                }
+
+                return styleNode;
+            }
+        }
+    };
+
+
+    class FeatureStencilModelSource : public FeatureModelSource
+    {
+    public:
+        FeatureStencilModelSource( const ModelSourceOptions& options, int renderBinStart ) :
+            FeatureModelSource( options ),
+            _options( options ),
+            _renderBinStart( renderBinStart )
+        {
+            // make sure we have stencil bits. Note, this only works before
+            // a viewer gets created. You may need to allocate stencil bits
+            // yourself if you make this object after realizing a viewer.
+            if ( osg::DisplaySettings::instance()->getMinimumNumStencilBits() < 8 )
+            {
+                osg::DisplaySettings::instance()->setMinimumNumStencilBits( 8 );
+            }
+        }
+        
+    public: // FeatureModelSource
+
+        virtual const FeatureModelSourceOptions& getFeatureModelOptions() const
+        {
+            return _options;
+        }
+
+        Status initialize( const osgDB::Options* dbOptions )
+        {
+            return FeatureModelSource::initialize( dbOptions );
+        }
+
+        FeatureNodeFactory* createFeatureNodeFactory()
+        {
+            return new StencilVolumeNodeFactory( _options, _renderBinStart );
+        }
+
+    protected:
+        int _renderBinStart;
+        const FeatureStencilModelOptions _options;
+    };
+}
+
+
+class FeatureStencilModelSourceDriver : public ModelSourceDriver
+{
+public:
+    FeatureStencilModelSourceDriver() :
+        _renderBinStart( RENDER_BIN_START )
+    {
+        supportsExtension( "osgearth_model_feature_stencil", "osgEarth feature stencil plugin" );
+    }
+
+    virtual const char* className()
+    {
+        return "osgEarth Feature Stencil Model Plugin";
+    }
+
+    FeatureStencilModelSource* create( const Options* options )
+    {
+        ScopedLock<Mutex> lock( _createMutex );
+
+        FeatureStencilModelSource* obj = new FeatureStencilModelSource( 
+            getModelSourceOptions(options), 
+            _renderBinStart );
+
+        _renderBinStart += MAX_NUM_STYLES*4;
+
+        return obj;
+    }
+
+    virtual ReadResult readObject(const std::string& file_name, const Options* options) const
+    {
+        if ( !acceptsExtension(osgDB::getLowerCaseFileExtension( file_name )))
+            return ReadResult::FILE_NOT_HANDLED;
+
+        FeatureStencilModelSourceDriver* nonConstThis = const_cast<FeatureStencilModelSourceDriver*>(this);
+        return nonConstThis->create( options );
+    }
+
+protected:
+    Mutex _createMutex;
+    int _renderBinStart;
+};
+
+REGISTER_OSGPLUGIN(osgearth_model_feature_stencil, FeatureStencilModelSourceDriver)
diff --git a/src/osgEarthDrivers/model_feature_stencil/StencilUtils.cpp b/src/osgEarthDriversDisabled/model_feature_stencil/StencilUtils.cpp
similarity index 100%
rename from src/osgEarthDrivers/model_feature_stencil/StencilUtils.cpp
rename to src/osgEarthDriversDisabled/model_feature_stencil/StencilUtils.cpp
diff --git a/src/osgEarthDrivers/model_feature_stencil/StencilUtils.h b/src/osgEarthDriversDisabled/model_feature_stencil/StencilUtils.h
similarity index 100%
rename from src/osgEarthDrivers/model_feature_stencil/StencilUtils.h
rename to src/osgEarthDriversDisabled/model_feature_stencil/StencilUtils.h
diff --git a/src/osgEarthExtensions/billboard/BillboardExtension b/src/osgEarthExtensions/billboard/BillboardExtension
deleted file mode 100644
index 570b586..0000000
--- a/src/osgEarthExtensions/billboard/BillboardExtension
+++ /dev/null
@@ -1,71 +0,0 @@
-/* -*-c++-*- */
-/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
- * http://osgearth.org
- *
- * osgEarth is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>
- */
-#ifndef OSGEARTH_BILLBOARD_BILLBOARD_EXTENSION
-#define OSGEARTH_BILLBOARD_BILLBOARD_EXTENSION 1
-
-#include "BillboardOptions"
-#include <osgEarth/Extension>
-#include <osgEarth/MapNode>
-#include <osgEarthFeatures/FeatureSource>
-
-namespace osgEarth { namespace Billboard
-{
-    using namespace osgEarth;
-    using namespace osgEarth::Features;
-
-    /**
-     * Extension for loading the splatting effect on demand.
-     */
-    class BillboardExtension : public Extension, public ExtensionInterface<MapNode>
-    {
-    public:
-        META_Object(osgearth_ext_billboard, BillboardExtension);
-
-        // CTORs
-        BillboardExtension();
-        BillboardExtension(const BillboardOptions& options);
-
-        // DTOR
-        virtual ~BillboardExtension();
-
-
-    public: // Extension
-
-        void setDBOptions(const osgDB::Options* dbOptions);
-
-
-    public: // ExtensionInterface<MapNode>
-
-        bool connect(MapNode* mapNode);
-
-        bool disconnect(MapNode* mapNode);
-
-
-    protected: // Object
-        BillboardExtension(const BillboardExtension& rhs, const osg::CopyOp& op) { }
-
-    private:
-        const BillboardOptions                 _options;
-        osg::ref_ptr<const osgDB::Options>     _dbOptions;
-        osg::ref_ptr<FeatureSource>            _features;
-    };
-
-} } // namespace osgEarth::Billboard
-
-#endif // OSGEARTH_BILLBOARD_BILLBOARD_EXTENSION
diff --git a/src/osgEarthExtensions/billboard/BillboardExtension.cpp b/src/osgEarthExtensions/billboard/BillboardExtension.cpp
deleted file mode 100644
index 8fe3b52..0000000
--- a/src/osgEarthExtensions/billboard/BillboardExtension.cpp
+++ /dev/null
@@ -1,288 +0,0 @@
-/* -*-c++-*- */
-/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
- * http://osgearth.org
- *
- * osgEarth is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>
- */
-#include "BillboardExtension"
-#include "BillboardShaders"
-
-#include <osg/Point>
-#include <osg/Texture2D>
-
-#include <osgEarth/ElevationQuery>
-#include <osgEarth/MapNode>
-#include <osgEarth/Registry>
-#include <osgEarth/ShaderGenerator>
-#include <osgEarth/VirtualProgram>
-#include <osgEarth/Random>
-#include <osgEarthFeatures/TransformFilter>
-#include <osgEarthFeatures/ScatterFilter>
-
-using namespace osgEarth;
-using namespace osgEarth::Billboard;
-using namespace osgEarth::Features;
-
-#define LC "[BillboardExtension] "
-
-
-BillboardExtension::BillboardExtension()
-{
-    //nop
-}
-
-BillboardExtension::BillboardExtension(const BillboardOptions& options) :
-_options( options )
-{
-    //nop
-}
-
-BillboardExtension::~BillboardExtension()
-{
-    //nop
-}
-
-void
-BillboardExtension::setDBOptions(const osgDB::Options* dbOptions)
-{
-    _dbOptions = dbOptions;
-}
-
-bool
-BillboardExtension::connect(MapNode* mapNode)
-{
-    if ( !mapNode )
-    {
-        OE_WARN << LC << "Illegal: MapNode cannot be null." << std::endl;
-        return false;
-    }
-
-    OE_INFO << LC << "Connecting to MapNode.\n";
-
-    if ( !_options.imageURI().isSet() )
-    {
-        OE_WARN << LC << "Illegal: image URI is required" << std::endl;
-        return false;
-    }
-
-    if ( !_options.featureOptions().isSet() )
-    {
-        OE_WARN << LC << "Illegal: feature source is required" << std::endl;
-        return false;
-    }
-    
-    _features = FeatureSourceFactory::create( _options.featureOptions().value() );
-    if ( !_features.valid() )
-    {
-        OE_WARN << LC << "Illegal: no valid feature source provided" << std::endl;
-        return false;
-    }
-
-    //if ( _features->getGeometryType() != osgEarth::Symbology::Geometry::TYPE_POINTSET )
-    //{
-    //    OE_WARN << LC << "Illegal: only points currently supported" << std::endl;
-    //    return false;
-    //}
-
-    _features->initialize( _dbOptions );
-
-    osg::Vec3dArray* verts;
-    if ( _features->getFeatureProfile() )
-    {
-        verts = new osg::Vec3dArray();
-        
-        OE_NOTICE << "Reading features...\n";
-        osg::ref_ptr<FeatureCursor> cursor = _features->createFeatureCursor();
-        while ( cursor.valid() && cursor->hasMore() )
-        {
-            Feature* f = cursor->nextFeature();
-            if ( f && f->getGeometry() )
-            {
-                if ( f->getGeometry()->getComponentType() == Geometry::TYPE_POLYGON )
-                {
-                    FilterContext cx;
-                    cx.setProfile( new FeatureProfile(_features->getFeatureProfile()->getExtent()) );
-
-                    ScatterFilter scatter;
-                    scatter.setDensity( _options.density().get() );
-                    scatter.setRandom( true );
-                    FeatureList featureList;
-                    featureList.push_back(f);
-                    scatter.push( featureList, cx );
-                }
-
-                // Init a filter to tranform feature in desired SRS 
-                if (!mapNode->getMapSRS()->isEquivalentTo(_features->getFeatureProfile()->getSRS()))
-                {
-                    FilterContext cx;
-                    cx.setProfile( new FeatureProfile(_features->getFeatureProfile()->getExtent()) );
-
-                    TransformFilter xform( mapNode->getMapSRS() );
-                    FeatureList featureList;
-                    featureList.push_back(f);
-                    cx = xform.push(featureList, cx);
-                }
-
-                GeometryIterator iter(f->getGeometry());
-                while(iter.hasMore()) {
-                    const Geometry* geom = iter.next();
-                    osg::ref_ptr<osg::Vec3dArray> fVerts = geom->toVec3dArray();
-                    verts->insert(verts->end(), fVerts->begin(), fVerts->end());
-                }
-            }
-        }
-    }
-    else
-    {
-        OE_WARN << LC << "Illegal: feature source has no SRS" << std::endl;
-        return false;
-    }
-
-
-    if ( verts && verts->size() > 0 )
-    {
-        OE_NOTICE << LC << "Read " << verts->size() << " points.\n";
-
-        //localize all the verts
-        GeoPoint centroid;
-        _features->getFeatureProfile()->getExtent().getCentroid(centroid);
-        centroid = centroid.transform(mapNode->getMapSRS());
-
-        OE_NOTICE << "Centroid = " << centroid.x() << ", " << centroid.y() << "\n";
-
-        osg::Matrixd l2w, w2l;
-        centroid.createLocalToWorld(l2w);
-        w2l.invert(l2w);
-
-        osg::MatrixTransform* mt = new osg::MatrixTransform;
-        mt->setMatrix(l2w);
-
-        OE_NOTICE << "Clamping elevations...\n";
-        osgEarth::ElevationQuery eq(mapNode->getMap());
-        eq.setFallBackOnNoData( true );
-        eq.getElevations(verts->asVector(), mapNode->getMapSRS(), true, 0.005);
-        
-        OE_NOTICE << "Building geometry...\n";
-        osg::Vec3Array* normals = new osg::Vec3Array(verts->size());
-
-        osg::Vec4Array* colors = new osg::Vec4Array(verts->size());
-        Random rng;
-
-        for (int i=0; i < verts->size(); i++)
-        {
-            GeoPoint vert(mapNode->getMapSRS(), (*verts)[i], osgEarth::ALTMODE_ABSOLUTE);
-
-            osg::Vec3d world;
-            vert.toWorld(world);
-            (*verts)[i] = world * w2l;
-
-            osg::Vec3 normal = world;
-            normal.normalize();
-            (*normals)[i] = osg::Matrix::transform3x3(normal, w2l);
-
-            double n = rng.next();
-            (*colors)[i].set( n, n, n, 1 );
-        }
-
-        //create geom and primitive sets
-        osg::Geometry* geometry = new osg::Geometry();
-        geometry->setVertexArray( verts );
-        geometry->setNormalArray( normals );
-        geometry->setNormalBinding( osg::Geometry::BIND_PER_VERTEX );
-        geometry->setColorArray(colors);
-        geometry->setColorBinding( osg::Geometry::BIND_PER_VERTEX );
-
-        geometry->addPrimitiveSet( new osg::DrawArrays( GL_POINTS, 0, verts->size() ) );
-
-        //create image and texture to render to
-        osg::Texture2D* tex = new osg::Texture2D(_options.imageURI()->getImage(_dbOptions));
-        tex->setResizeNonPowerOfTwoHint(false);
-        tex->setFilter( osg::Texture::MIN_FILTER, osg::Texture::LINEAR_MIPMAP_LINEAR );
-        tex->setFilter( osg::Texture::MAG_FILTER, osg::Texture::LINEAR );
-        tex->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP_TO_EDGE);
-        tex->setWrap(osg::Texture::WRAP_T, osg::Texture::CLAMP_TO_EDGE);
-
-        geometry->setName("BillboardPoints");
-
-        osg::Geode* geode = new osg::Geode;
-        geode->addDrawable(geometry);
-
-        //osg::ref_ptr<StateSetCache> cache = new StateSetCache();
-        //Registry::shaderGenerator().run(geode, cache.get());
-
-        //set the texture related uniforms
-        osg::StateSet* geode_ss = geode->getOrCreateStateSet();
-        geode_ss->setTextureAttributeAndModes( 2, tex, 1 );
-        geode_ss->getOrCreateUniform("billboard_tex", osg::Uniform::SAMPLER_2D)->set( 2 );
-
-        float bbWidth = (float)tex->getImage()->s() / 2.0f;
-        float bbHeight = (float)tex->getImage()->t();
-        float aspect = (float)tex->getImage()->s() / (float)tex->getImage()->t();
-        if (_options.height().isSet())
-        {
-            bbHeight = _options.height().get();
-            if (!_options.width().isSet())
-            {
-                bbWidth = bbHeight * aspect / 2.0f;
-            }
-        }
-        if (_options.width().isSet())
-        {
-            bbWidth = _options.width().get() / 2.0f;
-            if (!_options.height().isSet())
-            {
-                bbHeight = _options.width().get() / aspect;
-            }
-        }
-
-        geode_ss->getOrCreateUniform("billboard_width", osg::Uniform::FLOAT)->set( bbWidth );
-        geode_ss->getOrCreateUniform("billboard_height", osg::Uniform::FLOAT)->set( bbHeight );
-        geode_ss->setMode(GL_BLEND, osg::StateAttribute::ON);
-
-        //for now just using an osg::Program
-        //TODO: need to add GeometryShader support to the shader comp setup
-        osg::Program* pgm = new osg::Program;
-        pgm->setName("billboard_program");
-        pgm->addShader( new osg::Shader( osg::Shader::VERTEX, billboardVertShader ) );
-        pgm->addShader( new osg::Shader( osg::Shader::GEOMETRY, billboardGeomShader ) );
-        pgm->addShader( new osg::Shader( osg::Shader::FRAGMENT, billboardFragmentShader ) );
-        pgm->setParameter( GL_GEOMETRY_VERTICES_OUT_EXT, 4 );
-        pgm->setParameter( GL_GEOMETRY_INPUT_TYPE_EXT, GL_POINTS );
-        pgm->setParameter( GL_GEOMETRY_OUTPUT_TYPE_EXT, GL_TRIANGLE_STRIP );
-        geode_ss->setAttribute(pgm);
-
-        geode_ss->setMode( GL_CULL_FACE, osg::StateAttribute::OFF );
-        geode->setCullingActive(false);
-
-        mt->addChild(geode);
-        mapNode->getModelLayerGroup()->addChild(mt);
-
-        return true;
-    }
-
-    return false;
-}
-
-bool
-BillboardExtension::disconnect(MapNode* mapNode)
-{
-    if ( mapNode )
-    {
-        //TODO
-    }
-
-    return true;
-}
-
diff --git a/src/osgEarthExtensions/billboard/BillboardOptions b/src/osgEarthExtensions/billboard/BillboardOptions
deleted file mode 100644
index f1af67c..0000000
--- a/src/osgEarthExtensions/billboard/BillboardOptions
+++ /dev/null
@@ -1,111 +0,0 @@
-/* -*-c++-*- */
-/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
- * http://osgearth.org
- *
- * osgEarth is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>
- */
-#ifndef OSGEARTH_DRIVER_BILLBOARD_OPTIONS
-#define OSGEARTH_DRIVER_BILLBOARD_OPTIONS 1
-
-#include <osgEarth/Common>
-#include <osgEarth/URI>
-#include <osgEarthFeatures/FeatureSource>
-
-namespace osgEarth { namespace Billboard
-{
-    using namespace osgEarth;
-    using namespace osgEarth::Features;
-
-    /**
-     * Options governing the classification splatting engine.
-     */
-    class /*header-only*/ BillboardOptions : public DriverConfigOptions
-    {
-    public:
-        /** URI of the billboard image file */
-        optional<URI>& imageURI() { return _imageURI; }
-        const optional<URI>& imageURI() const { return _imageURI; }
-        
-        /** scale  */
-        optional<float>& scale() { return _scale; }
-        const optional<float>& scale() const { return _scale; }
-
-        /** width and height */
-        optional<float>& width() { return _width; }
-        const optional<float>& width() const { return _width; }
-
-        optional<float>& height() { return _height; }
-        const optional<float>& height() const { return _height; }
-
-        optional<float>& density() { return _density; }
-        const optional<float>& density() const { return _density; }
-
-        /** Feature source from which to read the feature data */
-        optional<FeatureSourceOptions>& featureOptions() { return _featureOptions; }
-        const optional<FeatureSourceOptions>& featureOptions() const { return _featureOptions; }
-
-
-    public:
-        BillboardOptions( const ConfigOptions& opt =ConfigOptions() ) : DriverConfigOptions( opt )
-        {
-            setDriver( "billboard" );
-            _scale.init(1.0f);
-            _density.init(100.0f);
-            fromConfig( _conf );
-        }
-
-        virtual ~BillboardOptions() { }
-
-    public:
-        Config getConfig() const {
-            Config conf = DriverConfigOptions::getConfig();
-            conf.updateIfSet("image",  _imageURI);
-            conf.updateIfSet("scale",  _scale);
-            conf.updateIfSet("width",  _width);
-            conf.updateIfSet("height",  _height);
-            conf.updateIfSet("density", _density);
-            conf.updateObjIfSet( "features", _featureOptions );
-            return conf;
-        }
-
-    protected:
-        void mergeConfig( const Config& conf ) {
-            DriverConfigOptions::mergeConfig( conf );
-            fromConfig( conf );
-        }
-
-    private:
-        void fromConfig( const Config& conf ) {
-            conf.getIfSet("image",  _imageURI);
-            conf.getIfSet("scale",  _scale);
-            conf.getIfSet("width",  _width);
-            conf.getIfSet("height",  _height);
-            conf.getIfSet("density", _density);
-
-            if ( conf.hasChild("features") )
-                _featureOptions->merge( conf.child("features") );
-        }
-
-        optional<URI>                   _imageURI;
-        optional<float>                 _scale;
-        optional<float>                 _width;
-        optional<float>                 _height;
-        optional<float>                 _density;
-        optional<FeatureSourceOptions>  _featureOptions;
-    };
-
-} } // namespace osgEarth::Billboard
-
-#endif // OSGEARTH_DRIVER_BILLBOARD_OPTIONS
diff --git a/src/osgEarthExtensions/billboard/BillboardPlugin.cpp b/src/osgEarthExtensions/billboard/BillboardPlugin.cpp
deleted file mode 100644
index abcd69c..0000000
--- a/src/osgEarthExtensions/billboard/BillboardPlugin.cpp
+++ /dev/null
@@ -1,56 +0,0 @@
-/* -*-c++-*- */
-/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
- * http://osgearth.org
- *
- * osgEarth is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>
- */
-#include "BillboardOptions"
-#include "BillboardExtension"
-
-#include <osgDB/ReaderWriter>
-#include <osgDB/Registry>
-#include <osgDB/FileNameUtils>
-
-namespace osgEarth { namespace Billboard
-{
-    /**
-     * Plugin entry point
-     */
-    class BillboardPlugin : public osgDB::ReaderWriter
-    {
-    public: // Plugin stuff
-
-        BillboardPlugin() {
-            supportsExtension( "osgearth_billboard", "osgEarth Billboard Extension Plugin" );
-        }
-        
-        const char* className() {
-            return "osgEarth Billboard Extension Plugin";
-        }
-
-        virtual ~BillboardPlugin() { }
-
-        ReadResult readObject(const std::string& filename, const osgDB::Options* dbOptions) const
-        {
-          if ( !acceptsExtension(osgDB::getLowerCaseFileExtension(filename)) )
-                return ReadResult::FILE_NOT_HANDLED;
-
-          return ReadResult( new BillboardExtension(Extension::getConfigOptions(dbOptions)) );
-        }
-    };
-
-    REGISTER_OSGPLUGIN(osgearth_billboard, BillboardPlugin)
-
-} } // namespace osgEarth::Billboard
diff --git a/src/osgEarthExtensions/billboard/BillboardShaders b/src/osgEarthExtensions/billboard/BillboardShaders
deleted file mode 100644
index 8324de9..0000000
--- a/src/osgEarthExtensions/billboard/BillboardShaders
+++ /dev/null
@@ -1,106 +0,0 @@
-/* -*-c++-*- */
-/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2008-2012 Pelican Mapping
-* http://osgearth.org
-*
-* osgEarth is free software; you can redistribute it and/or modify
-* it under the terms of the GNU Lesser General Public License as published by
-* the Free Software Foundation; either version 2 of the License, or
-* (at your option) any later version.
-*
-* 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.
-*
-* You should have received a copy of the GNU Lesser General Public License
-* along with this program.  If not, see <http://www.gnu.org/licenses/>
-*/
-#ifndef OSGEARTH_BILLBOARD_SHADERS
-#define OSGEARTH_BILLBOARD_SHADERS 1
-
-#include <osgEarth/VirtualProgram>
-
-using namespace osgEarth;
-
-namespace
-{
-
-    const char* billboardVertShader =
-        "#version " GLSL_VERSION_STR "\n"
-        //"#extension GL_EXT_geometry_shader4 : enable\n"
-        GLSL_DEFAULT_PRECISION_FLOAT "\n"
-        "varying out vec3 normal;\n"
-        "varying out vec4 color;\n"
-        "void main(void)\n"
-        "{\n"
-        "    normal = gl_Normal;\n"
-        "    color = gl_Color;\n"
-        "    gl_Position = gl_Vertex;\n"
-        "}\n";
-
-
-    /**
-     * 
-     */
-    const char* billboardGeomShader =
-        "#version " GLSL_VERSION_STR "\n"
-        "#extension GL_EXT_geometry_shader4 : enable\n"
-        GLSL_DEFAULT_PRECISION_FLOAT "\n"
-        "varying out vec2 tex_coord;\n"
-        "varying out float brightness;\n"
-        "varying in vec3 normal[];\n"
-        "varying in vec4 color[];\n"
-        "uniform float billboard_width; \n"
-        "uniform float billboard_height; \n"
-        "uniform sampler2D billboard_tex; \n"
-        "void main(void)\n"
-        "{\n"
-        "    vec4 v = gl_ModelViewMatrix * gl_PositionIn[0];\n"
-        "    vec4 v2 = gl_ModelViewMatrix * (gl_PositionIn[0] + vec4(normal[0]*billboard_height, 0.0));\n"
-        "    \n"
-        // TODO: this width calculation isn't great but works for now
-        "    vec4 center_v = gl_ModelViewMatrix * vec4(0.,0.,0.,1.);\n"
-        "    vec4 right_v = gl_ModelViewMatrix * vec4(billboard_width,0.,0.,1.);\n"
-        "    float width = distance(right_v, center_v);\n"
-        "    \n"
-        "    brightness = color[0].r;\n"
-        "    gl_Position = gl_ProjectionMatrix * (v + vec4(width, 0., 0., 0.)); \n"
-        "    tex_coord = vec2(1.0, 0.0); \n"
-        "    EmitVertex(); \n"
-        "    gl_Position = gl_ProjectionMatrix * (v + vec4(-width, 0., 0., 0.)); \n"
-        "    tex_coord = vec2(0.0, 0.0); \n"
-        "    brightness = color[0].r;\n"
-        "    EmitVertex(); \n"
-        
-        "    brightness = color[0].r*2.0;\n"
-        "    gl_Position = gl_ProjectionMatrix * (v2 + vec4(width, 0., 0., 0.)); \n"
-        "    tex_coord = vec2(1.0, 1.0); \n"
-        "    EmitVertex(); \n"
-        "    gl_Position = gl_ProjectionMatrix * (v2 + vec4(-width, 0., 0., 0.)); \n"
-        "    tex_coord = vec2(0.0, 1.0); \n"
-        "    EmitVertex(); \n"
-        "    EndPrimitive(); \n"
-        "}\n";
-
-
-    const char* billboardFragmentShader =
-        "#version " GLSL_VERSION_STR "\n"
-        //"#extension GL_EXT_geometry_shader4 : enable\n"
-        GLSL_DEFAULT_PRECISION_FLOAT "\n"
-        "uniform sampler2D billboard_tex; \n"
-        "varying vec2 tex_coord;\n"
-        "varying float brightness;\n"
-        "void main(void) {\n"
-        "    float contrast = clamp(1.0-brightness, 0.85, 1.0);\n"
-        "    vec4 color = texture2D(billboard_tex, tex_coord);\n"
-        "    color.rgb = clamp(((color.rgb-0.5)*contrast + 0.5) * (1.0+brightness), 0.0, 1.0);\n"
-        "    if ( color.a < 0.5 ) discard; \n"
-        "    gl_FragColor = color; \n"
-        "}\n";
-}
-
-#endif // OSGEARTH_BILLBOARD_SHADERS
\ No newline at end of file
diff --git a/src/osgEarthExtensions/billboard/CMakeLists.txt b/src/osgEarthExtensions/billboard/CMakeLists.txt
deleted file mode 100644
index eb36568..0000000
--- a/src/osgEarthExtensions/billboard/CMakeLists.txt
+++ /dev/null
@@ -1,27 +0,0 @@
-#
-# image billboarding plugin
-#
-
-SET(TARGET_SRC
-        BillboardPlugin.cpp
-	BillboardExtension.cpp)
-	
-SET(LIB_PUBLIC_HEADERS
-	BillboardExtension
-	BillboardOptions)
-	
-SET(TARGET_H
-	${LIB_PUBLIC_HEADERS}
-	BillboardShaders)
-
-SET(TARGET_COMMON_LIBRARIES ${TARGET_COMMON_LIBRARIES}
-    osgEarthUtil
-    osgEarthFeatures)
-	
-SETUP_EXTENSION(osgearth_billboard)
-
-# to install public driver includes:
-SET(LIB_NAME billboard)
-
-INCLUDE(ModuleInstallOsgEarthExtensionIncludes OPTIONAL)
-
diff --git a/src/osgEarthExtensions/bumpmap/BumpMap.frag.common.glsl b/src/osgEarthExtensions/bumpmap/BumpMap.frag.common.glsl
deleted file mode 100644
index 63a34ac..0000000
--- a/src/osgEarthExtensions/bumpmap/BumpMap.frag.common.glsl
+++ /dev/null
@@ -1,26 +0,0 @@
-#pragma vp_define "OE_USE_NORMAL_MAP"
-
-#ifdef OE_USE_NORMAL_MAP
-
-// normal map version:
-uniform sampler2D oe_nmap_normalTex;
-in vec4 oe_nmap_normalCoords;
-
-float oe_bumpmap_getSlope()
-{
-    vec4 encodedNormal = texture2D(oe_nmap_normalTex, oe_nmap_normalCoords.st);
-    vec3 normalTangent = normalize(encodedNormal.xyz*2.0-1.0);
-    return clamp((1.0-normalTangent.z)/0.8, 0.0, 1.0);
-}
-
-#else // OE_USE_NORMAL_MAP
-
-// non- normal map version:
-in float oe_bumpmap_slope;
-
-float oe_bumpmap_getSlope()
-{
-    return oe_bumpmap_slope;
-}
-
-#endif // OE_USE_NORMAL_MAP
diff --git a/src/osgEarthExtensions/bumpmap/BumpMap.frag.progressive.glsl b/src/osgEarthExtensions/bumpmap/BumpMap.frag.progressive.glsl
deleted file mode 100644
index 1c5f58d..0000000
--- a/src/osgEarthExtensions/bumpmap/BumpMap.frag.progressive.glsl
+++ /dev/null
@@ -1,56 +0,0 @@
-#version 110
-
-#pragma vp_entryPoint "oe_bumpmap_fragment"
-#pragma vp_location   "fragment_coloring"
-#pragma vp_order      "0.3"
-
-#pragma include "BumpMap.frag.common.glsl"
-
-uniform sampler2D oe_bumpmap_tex;
-uniform float oe_bumpmap_intensity;
-uniform int oe_bumpmap_octaves;
-uniform float oe_bumpmap_maxRange;
-
-// stage global
-vec3 oe_global_Normal;
-
-// from BumpMap.model.vert.glsl
-in vec2 oe_bumpmap_coords;
-
-// from BumpMap.view.vert.glsl
-in float oe_bumpmap_range;
-
-// Entry point for progressive blended bump maps
-void oe_bumpmap_fragment(inout vec4 color)
-{
-	// sample the bump map
-    const float amplitudeDecay = 1.0; // no decay.
-    float maxLOD = float(oe_bumpmap_octaves)+1.0;
-
-    // starter vector:
-    vec3 bump = vec3(0.0);    
-    float scale = 1.0;
-    float amplitude = 1.0;
-    float limit = oe_bumpmap_range;
-    float range = oe_bumpmap_maxRange;
-    float lastRange = oe_bumpmap_maxRange;
-    for(float lod = 1.0; lod < maxLOD; lod += 1.0, scale *= 2.0, amplitude *= amplitudeDecay)
-    {
-        float fadeIn = 1.0;
-        if ( range <= limit && limit < oe_bumpmap_maxRange )
-            fadeIn = clamp((lastRange-limit)/(lastRange-range), 0.0, 1.0);
-        bump += (texture2D(oe_bumpmap_tex, oe_bumpmap_coords*scale).xyz*2.0-1.0)*amplitude*fadeIn;
-        if ( range <= limit )
-            break;
-        lastRange = range;
-        range = oe_bumpmap_maxRange/exp(lod);
-    }
-
-    // finally, transform into view space and normalize the vector.
-    bump = normalize(gl_NormalMatrix*bump);
-
-    float slope = oe_bumpmap_getSlope();
-
-	// permute the normal with the bump.
-	oe_global_Normal = normalize(oe_global_Normal + bump*oe_bumpmap_intensity*slope);
-}
diff --git a/src/osgEarthExtensions/bumpmap/BumpMap.frag.simple.glsl b/src/osgEarthExtensions/bumpmap/BumpMap.frag.simple.glsl
deleted file mode 100644
index 77dc404..0000000
--- a/src/osgEarthExtensions/bumpmap/BumpMap.frag.simple.glsl
+++ /dev/null
@@ -1,23 +0,0 @@
-#version 110
-
-#pragma vp_entryPoint "oe_bumpmap_fragment"
-#pragma vp_location   "fragment_coloring"
-#pragma vp_order      "0.3"
-
-#pragma include "BumpMap.frag.common.glsl"
-
-vec3 oe_global_Normal;
-
-uniform sampler2D oe_bumpmap_tex;
-uniform float oe_bumpmap_intensity;
-in vec2 oe_bumpmap_coords;
-
-void oe_bumpmap_fragment(inout vec4 color)
-{
-	// sample the bump map
-    vec3 bump = gl_NormalMatrix * normalize(texture2D(oe_bumpmap_tex, oe_bumpmap_coords).xyz*2.0-1.0);
-
-	// permute the normal with the bump.
-    float slope = oe_bumpmap_getSlope();
-	oe_global_Normal = normalize(oe_global_Normal + bump*oe_bumpmap_intensity*slope);
-}
diff --git a/src/osgEarthExtensions/bumpmap/BumpMap.vert.model.glsl b/src/osgEarthExtensions/bumpmap/BumpMap.vert.model.glsl
deleted file mode 100644
index d60e751..0000000
--- a/src/osgEarthExtensions/bumpmap/BumpMap.vert.model.glsl
+++ /dev/null
@@ -1,60 +0,0 @@
-#version 110
-
-#pragma vp_entryPoint "oe_bumpmap_vertexModel"
-#pragma vp_location   "vertex_model"
-#pragma vp_order      "0.5"
-#pragma vp_define     "OE_USE_NORMAL_MAP"
-
-uniform vec4 oe_tile_key;
-uniform float oe_bumpmap_scale;
-
-varying vec4 oe_layer_tilec;
-varying vec3 oe_Normal;
-
-varying vec2 oe_bumpmap_coords;
-varying float oe_bumpmap_range;
-
-#ifdef OE_USE_NORMAL_MAP
-uniform mat4 oe_nmap_normalTexMatrix;
-varying vec4 oe_bumpmap_normalCoords;
-#else
-varying float oe_bumpmap_slope;
-#endif
-
-vec2 oe_bumpmap_scaleCoords(in vec2 coords, in float targetLOD)
-{
-    float dL = oe_tile_key.z - targetLOD;
-    float factor = exp2(dL);
-    float invFactor = 1.0/factor;
-    vec2 scale = vec2(invFactor);
-    vec2 result = coords * scale;
-
-    // For upsampling we need to calculate an offset as well
-    float upSampleToggle = factor >= 1.0 ? 1.0 : 0.0;
-    {
-        vec2 a = floor(oe_tile_key.xy * invFactor);
-        vec2 b = a * factor;
-        vec2 c = (a+1.0) * factor;
-        vec2 offset = (oe_tile_key.xy-b)/(c-b);
-        result += upSampleToggle * offset;
-    }
-
-    return result;
-}
-
-void oe_bumpmap_vertexModel(inout vec4 VertexMODEL)
-{            
-    // quantize the scale factor
-    float iscale = float(int(oe_bumpmap_scale));
-
-    // scale sampling coordinates to a target LOD.
-    const float targetLOD = 13.0;
-    oe_bumpmap_coords = oe_bumpmap_scaleCoords(oe_layer_tilec.st, targetLOD) * iscale;
-
-#ifdef OE_USE_NORMAL_MAP
-    oe_bumpmap_normalCoords = oe_nmap_normalTexMatrix * oe_layer_tilec;
-#else
-    // calcluate slope and augment it.
-    oe_bumpmap_slope = clamp(2.5*(1.0-oe_Normal.z), 0.0, 1.0);
-#endif
-}
diff --git a/src/osgEarthExtensions/bumpmap/BumpMap.vert.view.glsl b/src/osgEarthExtensions/bumpmap/BumpMap.vert.view.glsl
deleted file mode 100644
index 9e37147..0000000
--- a/src/osgEarthExtensions/bumpmap/BumpMap.vert.view.glsl
+++ /dev/null
@@ -1,12 +0,0 @@
-#version 110
-
-#pragma vp_entryPoint "oe_bumpmap_vertexView"
-#pragma vp_location   "vertex_view"
-#pragma vp_order      "0.5"
-
-varying float oe_bumpmap_range;
-
-void oe_bumpmap_vertexView(inout vec4 vertexView)
-{
-    oe_bumpmap_range = -vertexView.z;
-}
diff --git a/src/osgEarthExtensions/bumpmap/BumpMapExtension b/src/osgEarthExtensions/bumpmap/BumpMapExtension
deleted file mode 100644
index 813022d..0000000
--- a/src/osgEarthExtensions/bumpmap/BumpMapExtension
+++ /dev/null
@@ -1,73 +0,0 @@
-/* -*-c++-*- */
-/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
- * http://osgearth.org
- *
- * osgEarth is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>
- */
-#ifndef OSGEARTH_BUMPMAP_EXTENSION
-#define OSGEARTH_BUMPMAP_EXTENSION 1
-
-#include "BumpMapOptions"
-#include "BumpMapTerrainEffect"
-#include <osgEarth/Extension>
-#include <osgEarth/MapNode>
-#include <osgEarthUtil/Controls>
-
-namespace osgEarth { namespace BumpMap
-{
-    using namespace osgEarth;
-    using namespace osgEarth::Util::Controls;
-
-    /**
-     * Extension for loading the normal mapping effect on demand.
-     */
-    class BumpMapExtension : public Extension,
-                             public ExtensionInterface<MapNode>
-    {
-    public:
-        META_Object(osgearth_ext_BumpMap, BumpMapExtension);
-
-        // CTORs
-        BumpMapExtension();
-        BumpMapExtension(const BumpMapOptions& options);
-
-        // DTOR
-        virtual ~BumpMapExtension();
-
-
-    public: // Extension
-
-        void setDBOptions(const osgDB::Options* dbOptions);
-
-
-    public: // ExtensionInterface<MapNode>
-
-        bool connect(MapNode* mapNode);
-
-        bool disconnect(MapNode* mapNode);
-
-
-    protected: // Object
-        BumpMapExtension(const BumpMapExtension& rhs, const osg::CopyOp& op) { }
-
-    private:
-        const BumpMapOptions                 _options;
-        osg::ref_ptr<const osgDB::Options>   _dbOptions;
-        osg::ref_ptr<BumpMapTerrainEffect>   _effect;
-    };
-
-} } // namespace osgEarth::BumpMap
-
-#endif // OSGEARTH_BUMPMAP_EXTENSION
diff --git a/src/osgEarthExtensions/bumpmap/BumpMapExtension.cpp b/src/osgEarthExtensions/bumpmap/BumpMapExtension.cpp
deleted file mode 100644
index 30e9e07..0000000
--- a/src/osgEarthExtensions/bumpmap/BumpMapExtension.cpp
+++ /dev/null
@@ -1,98 +0,0 @@
-/* -*-c++-*- */
-/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
- * http://osgearth.org
- *
- * osgEarth is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>
- */
-#include "BumpMapExtension"
-#include "BumpMapTerrainEffect"
-
-#include <osgEarth/MapNode>
-
-using namespace osgEarth;
-using namespace osgEarth::BumpMap;
-
-#define LC "[BumpMapExtension] "
-
-
-BumpMapExtension::BumpMapExtension()
-{
-    //nop
-}
-
-BumpMapExtension::BumpMapExtension(const BumpMapOptions& options) :
-_options( options )
-{
-    //nop
-}
-
-BumpMapExtension::~BumpMapExtension()
-{
-    //nop
-}
-
-void
-BumpMapExtension::setDBOptions(const osgDB::Options* dbOptions)
-{
-    _dbOptions = dbOptions;
-}
-
-bool
-BumpMapExtension::connect(MapNode* mapNode)
-{
-    if ( !mapNode )
-    {
-        OE_WARN << LC << "Illegal: MapNode cannot be null." << std::endl;
-        return false;
-    }
-    
-    osg::ref_ptr<osg::Image> image = _options.imageURI()->getImage( _dbOptions.get() );
-    if ( !image.valid() )
-    {
-        OE_WARN << LC << "Failed; unable to load normal map image from "
-            << _options.imageURI()->full() << "\n";
-        return false;
-    }
-
-    _effect = new BumpMapTerrainEffect( _dbOptions.get() );
-    _effect->setBumpMapImage( image.get() );
-
-    if (_options.intensity().isSet())
-        _effect->getIntensityUniform()->set( _options.intensity().get() );
-
-    if (_options.scale().isSet())
-        _effect->getScaleUniform()->set( _options.scale().get() );
-
-    if ( _options.octaves().isSet() )
-        _effect->setOctaves( _options.octaves().get() );
-
-    mapNode->getTerrainEngine()->addEffect( _effect.get() );
-    
-    OE_INFO << LC << "Installed.\n";
-
-    return true;
-}
-
-bool
-BumpMapExtension::disconnect(MapNode* mapNode)
-{
-    if ( mapNode )
-    {
-        mapNode->getTerrainEngine()->removeEffect( _effect.get() );
-    }
-    _effect = 0L;
-    return true;
-}
-
diff --git a/src/osgEarthExtensions/bumpmap/BumpMapOptions b/src/osgEarthExtensions/bumpmap/BumpMapOptions
deleted file mode 100644
index c38cd0f..0000000
--- a/src/osgEarthExtensions/bumpmap/BumpMapOptions
+++ /dev/null
@@ -1,110 +0,0 @@
-/* -*-c++-*- */
-/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
- * http://osgearth.org
- *
- * osgEarth is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>
- */
-#ifndef OSGEARTH_DRIVER_BUMPMAP_OPTIONS
-#define OSGEARTH_DRIVER_BUMPMAP_OPTIONS 1
-
-#include <osgEarth/Common>
-#include <osgEarth/URI>
-
-namespace osgEarth { namespace BumpMap
-{
-    using namespace osgEarth;
-
-    /**
-     * Options governing bump mapping of the terrain.
-     * A Bump Map is a repeating normal texture that modifies the
-     * existing normal vector per fragment.
-     */
-    class BumpMapOptions : public DriverConfigOptions // NO EXPORT; header only
-    {
-    public:
-        // bump map texture to load.
-        optional<URI>& imageURI() { return _imageURI; }
-        const optional<URI>& imageURI() const { return _imageURI; }
-
-        // Intensity of normal map effect.
-        optional<float>& intensity() { return _intensity; }
-        const optional<float>& intensity() const { return _intensity; }
-
-        // Scale factor for the normal map texture.
-        optional<float>& scale() { return _scale; }
-        const optional<float>& scale() const { return _scale; }
-
-        /** Number of times to proressively scale and multisample the bump map
-            based on camera range. Default is 1. */
-        optional<int>& octaves() { return _octaves; }
-        const optional<int>& octaves() const { return _octaves; }
-
-        /** Camera range at which to render one octave (outer range). */
-        optional<float>& maxRange() { return _maxRange; }
-        const optional<float>& maxRange() const { return _maxRange; }
-
-    public:
-        BumpMapOptions( const ConfigOptions& opt =ConfigOptions() ) : DriverConfigOptions( opt )
-        {
-            setDriver( "bumpmap" );
-
-            // Defaults.
-            _intensity.init( 1.0f );
-            _scale.init    ( 1.0f );
-            _octaves.init  ( 1 );
-            _maxRange.init (25000.0f);
-
-            fromConfig( _conf );
-        }
-
-        virtual ~BumpMapOptions() { }
-
-    public:
-        Config getConfig() const {
-            Config conf = DriverConfigOptions::getConfig();
-            conf.updateIfSet("image",     _imageURI);
-            conf.updateIfSet("intensity", _intensity);
-            conf.updateIfSet("scale",     _scale);
-            conf.updateIfSet("octaves",   _octaves);
-            conf.updateIfSet("max_range", _maxRange);
-            return conf;
-        }
-
-    protected:
-        void mergeConfig( const Config& conf ) {
-            DriverConfigOptions::mergeConfig( conf );
-            fromConfig( conf );
-        }
-
-    private:
-        void fromConfig( const Config& conf ) {
-            conf.getIfSet("image",     _imageURI);
-            conf.getIfSet("intensity", _intensity);
-            conf.getIfSet("scale",     _scale);
-            conf.getIfSet("octaves",   _octaves);
-            conf.getIfSet("max_range", _maxRange);
-        }
-
-        optional<URI>   _imageURI;
-        optional<float> _intensity;
-        optional<float> _scale;
-        optional<int>   _octaves;
-        optional<float> _maxRange;
-    };
-
-} } // namespace osgEarth::BumpMap
-
-#endif // OSGEARTH_DRIVER_BUMPMAP_OPTIONS
-
diff --git a/src/osgEarthExtensions/bumpmap/BumpMapPlugin.cpp b/src/osgEarthExtensions/bumpmap/BumpMapPlugin.cpp
deleted file mode 100644
index a0ebbd2..0000000
--- a/src/osgEarthExtensions/bumpmap/BumpMapPlugin.cpp
+++ /dev/null
@@ -1,56 +0,0 @@
-/* -*-c++-*- */
-/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
- * http://osgearth.org
- *
- * osgEarth is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>
- */
-#include "BumpMapOptions"
-#include "BumpMapExtension"
-
-#include <osgDB/ReaderWriter>
-#include <osgDB/Registry>
-#include <osgDB/FileNameUtils>
-
-namespace osgEarth { namespace BumpMap
-{
-    /**
-     * Plugin entry point
-     */
-    class BumpMapPlugin : public osgDB::ReaderWriter
-    {
-    public: // Plugin stuff
-
-        BumpMapPlugin() {
-            supportsExtension( "osgearth_bumpmap", "osgEarth Bump Map Extension Plugin" );
-        }
-        
-        const char* className() {
-            return "osgEarth Bump Map Extension Plugin";
-        }
-
-        virtual ~BumpMapPlugin() { }
-
-        ReadResult readObject(const std::string& filename, const osgDB::Options* dbOptions) const
-        {
-          if ( !acceptsExtension(osgDB::getLowerCaseFileExtension(filename)) )
-                return ReadResult::FILE_NOT_HANDLED;
-
-          return ReadResult( new BumpMapExtension(Extension::getConfigOptions(dbOptions)) );
-        }
-    };
-
-    REGISTER_OSGPLUGIN(osgearth_bumpmap, BumpMapPlugin)
-
-} } // namespace osgEarth::BumpMap
diff --git a/src/osgEarthExtensions/bumpmap/BumpMapShaders b/src/osgEarthExtensions/bumpmap/BumpMapShaders
deleted file mode 100644
index d835e7e..0000000
--- a/src/osgEarthExtensions/bumpmap/BumpMapShaders
+++ /dev/null
@@ -1,39 +0,0 @@
-// ***DO NOT EDIT THIS FILE - IT IS AUTOMATICALLY GENERATED BY CMAKE***
-/* -*-c++-*- */
-/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2008-2012 Pelican Mapping
-* http://osgearth.org
-*
-* osgEarth is free software; you can redistribute it and/or modify
-* it under the terms of the GNU Lesser General Public License as published by
-* the Free Software Foundation; either version 2 of the License, or
-* (at your option) any later version.
-*
-* 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.
-*
-* You should have received a copy of the GNU Lesser General Public License
-* along with this program.  If not, see <http://www.gnu.org/licenses/>
-*/
-#ifndef OSGEARTH_BUMPMAP_SHADERS
-#define OSGEARTH_BUMPMAP_SHADERS 1
-
-#include <osgEarth/ShaderLoader>
-
-namespace osgEarth { namespace BumpMap
-{
-    struct Shaders : public osgEarth::ShaderPackage
-	{
-        Shaders();
-        std::string VertexModel, VertexView;
-        std::string FragmentSimple, FragmentProgressive, FragmentCommon;
-	};
-	
-} } // namespace osgEarth/BumpMap
-
-#endif // OSGEARTH_BUMPMAP_SHADERS
\ No newline at end of file
diff --git a/src/osgEarthExtensions/bumpmap/BumpMapShaders.cpp.in b/src/osgEarthExtensions/bumpmap/BumpMapShaders.cpp.in
deleted file mode 100644
index e4cf5a7..0000000
--- a/src/osgEarthExtensions/bumpmap/BumpMapShaders.cpp.in
+++ /dev/null
@@ -1,24 +0,0 @@
-/** CMake Template File - compiled into AutoGenShaders.cpp */
-#include <osgEarthExtensions/bumpmap/BumpMapShaders>
-
-#define MULTILINE(...) #__VA_ARGS__
-
-using namespace osgEarth::BumpMap;
-
-Shaders::Shaders()
-{
-    VertexModel = "BumpMap.vert.model.glsl";
-    _sources[VertexModel] = MULTILINE(@BumpMap.vert.model.glsl@);
-
-    VertexView = "BumpMap.vert.view.glsl";
-    _sources[VertexView] = MULTILINE(@BumpMap.vert.view.glsl@);
-
-    FragmentSimple = "BumpMap.frag.simple.glsl";
-    _sources[FragmentSimple] = MULTILINE(@BumpMap.frag.simple.glsl@);
-
-    FragmentProgressive = "BumpMap.frag.progressive.glsl";
-    _sources[FragmentProgressive] = MULTILINE(@BumpMap.frag.progressive.glsl@);
-
-    FragmentCommon = "BumpMap.frag.common.glsl";
-    _sources[FragmentCommon] = MULTILINE(@BumpMap.frag.common.glsl@);
-};
diff --git a/src/osgEarthExtensions/bumpmap/BumpMapTerrainEffect b/src/osgEarthExtensions/bumpmap/BumpMapTerrainEffect
deleted file mode 100644
index b426c30..0000000
--- a/src/osgEarthExtensions/bumpmap/BumpMapTerrainEffect
+++ /dev/null
@@ -1,82 +0,0 @@
-/* -*-c++-*- */
-/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2008-2012 Pelican Mapping
-* http://osgearth.org
-*
-* osgEarth is free software; you can redistribute it and/or modify
-* it under the terms of the GNU Lesser General Public License as published by
-* the Free Software Foundation; either version 2 of the License, or
-* (at your option) any later version.
-*
-* 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.
-*
-* You should have received a copy of the GNU Lesser General Public License
-* along with this program.  If not, see <http://www.gnu.org/licenses/>
-*/
-#ifndef OSGEARTH_BumpMap_TERRAIN_EFFECT_H
-#define OSGEARTH_BumpMap_TERRAIN_EFFECT_H
-
-#include <osgEarth/TerrainEffect>
-#include <osgEarth/ImageLayer>
-#include <osg/Image>
-#include <osg/Uniform>
-#include <osg/Texture2D>
-
-using namespace osgEarth;
-
-namespace osgEarth { namespace BumpMap
-{
-    /**
-     * Effect that applies bump mapping to the terrain.
-     */
-    class BumpMapTerrainEffect : public TerrainEffect
-    {
-    public:
-        /** construct a new terrain effect. */
-        BumpMapTerrainEffect(const osgDB::Options* dbOptions);
-
-        /** Sets the image containing the normal offsets. */
-        void setBumpMapImage(osg::Image* image);
-
-        /** Sets the number of progressive octaves. */
-        void setOctaves(int value) { _octaves = value; }
-
-        /** Sets the range of the first octave. */
-        void setMaxRange(float value) { _maxRange = value; }
-
-        /** UNiform that controls intensity */
-        osg::Uniform* getIntensityUniform() const { return _intensityUniform.get(); }
-
-        /** Uniform that controls scale factor */
-        osg::Uniform* getScaleUniform() const { return _scaleUniform.get(); }
-
-
-    public: // TerrainEffect interface
-
-        void onInstall(TerrainEngineNode* engine);
-
-        void onUninstall(TerrainEngineNode* engine);
-
-
-    protected:
-        virtual ~BumpMapTerrainEffect() { }
-
-        bool  _ok;
-        int   _bumpMapUnit;
-        int   _octaves;
-        float _maxRange;
-        osg::ref_ptr<osg::Texture2D> _bumpMapTex;
-        osg::ref_ptr<osg::Uniform>   _bumpMapTexUniform;
-        osg::ref_ptr<osg::Uniform>   _scaleUniform;
-        osg::ref_ptr<osg::Uniform>   _intensityUniform;
-    };
-
-} } // namespace osgEarth::BumpMap
-
-#endif // OSGEARTH_BumpMap_TERRAIN_EFFECT_H
diff --git a/src/osgEarthExtensions/bumpmap/BumpMapTerrainEffect.cpp b/src/osgEarthExtensions/bumpmap/BumpMapTerrainEffect.cpp
deleted file mode 100644
index 9a2f737..0000000
--- a/src/osgEarthExtensions/bumpmap/BumpMapTerrainEffect.cpp
+++ /dev/null
@@ -1,140 +0,0 @@
-/* -*-c++-*- */
-/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2008-2012 Pelican Mapping
-* http://osgearth.org
-*
-* osgEarth is free software; you can redistribute it and/or modify
-* it under the terms of the GNU Lesser General Public License as published by
-* the Free Software Foundation; either version 2 of the License, or
-* (at your option) any later version.
-*
-* 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.
-*
-* You should have received a copy of the GNU Lesser General Public License
-* along with this program.  If not, see <http://www.gnu.org/licenses/>
-*/
-#include "BumpMapTerrainEffect"
-#include "BumpMapOptions"
-
-#include <osgEarth/Registry>
-#include <osgEarth/Capabilities>
-#include <osgEarth/VirtualProgram>
-#include <osgEarth/TerrainEngineNode>
-#include <osgEarth/TerrainTileNode>
-
-#include "BumpMapShaders"
-
-#define LC "[BumpMap] "
-
-#define BUMP_SAMPLER   "oe_bumpmap_tex"
-
-using namespace osgEarth;
-using namespace osgEarth::BumpMap;
-
-
-BumpMapTerrainEffect::BumpMapTerrainEffect(const osgDB::Options* dbOptions)
-{
-    BumpMapOptions defaults;
-    _octaves = defaults.octaves().get();
-    _maxRange = defaults.maxRange().get();
-
-    _scaleUniform     = new osg::Uniform("oe_bumpmap_scale", defaults.scale().get());
-    _intensityUniform = new osg::Uniform("oe_bumpmap_intensity", defaults.intensity().get());
-}
-
-void
-BumpMapTerrainEffect::setBumpMapImage(osg::Image* image)
-{
-    if ( image )
-    {
-        _bumpMapTex = new osg::Texture2D(image);
-        _bumpMapTex->setWrap(osg::Texture::WRAP_S, osg::Texture::REPEAT);
-        _bumpMapTex->setWrap(osg::Texture::WRAP_T, osg::Texture::REPEAT);
-        _bumpMapTex->setFilter(osg::Texture::MIN_FILTER, osg::Texture::LINEAR);
-        _bumpMapTex->setFilter(osg::Texture::MAG_FILTER, osg::Texture::LINEAR);
-        _bumpMapTex->setMaxAnisotropy(1.0f);
-        _bumpMapTex->setUnRefImageDataAfterApply(true);
-        _bumpMapTex->setResizeNonPowerOfTwoHint(false);
-    }
-    else
-    {
-        OE_WARN << LC << "Failed to load the bump map texture\n";
-    }
-}
-
-void
-BumpMapTerrainEffect::onInstall(TerrainEngineNode* engine)
-{
-    if ( engine && _bumpMapTex.valid() )
-    {
-        osg::StateSet* stateset = engine->getTerrainStateSet();
-
-        // install the NormalMap texture array:
-        if ( engine->getResources()->reserveTextureImageUnit(_bumpMapUnit, "BumpMap") )
-        {
-            // NormalMap sampler
-            _bumpMapTexUniform = stateset->getOrCreateUniform(BUMP_SAMPLER, osg::Uniform::SAMPLER_2D);
-            _bumpMapTexUniform->set( _bumpMapUnit );
-            stateset->setTextureAttribute( _bumpMapUnit, _bumpMapTex.get(), osg::StateAttribute::ON );
-
-            // configure shaders
-            VirtualProgram* vp = VirtualProgram::getOrCreate(stateset);
-
-            Shaders package;            
-            package.define( "OE_USE_NORMAL_MAP", engine->normalTexturesRequired() );
-
-            package.load( vp, package.VertexModel );
-            package.load( vp, package.VertexView );
-            package.load( vp, _octaves <= 1? package.FragmentSimple : package.FragmentProgressive );
-
-            if ( _octaves > 1 )
-                stateset->addUniform(new osg::Uniform("oe_bumpmap_octaves", _octaves));
-
-            stateset->addUniform(new osg::Uniform("oe_bumpmap_maxRange", _maxRange));
-
-            stateset->addUniform( _scaleUniform.get() );
-            stateset->addUniform( _intensityUniform.get() );
-        }
-    }
-}
-
-
-void
-BumpMapTerrainEffect::onUninstall(TerrainEngineNode* engine)
-{
-    osg::StateSet* stateset = engine->getStateSet();
-    if ( stateset )
-    {
-        if ( _bumpMapTex.valid() )
-        {
-            stateset->removeUniform("oe_bumpmap_maxRange");
-            stateset->removeUniform("oe_bumpmap_octaves");
-            stateset->removeUniform( _scaleUniform.get() );
-            stateset->removeUniform( _intensityUniform.get() );
-            stateset->removeUniform( _bumpMapTexUniform.get() );
-            stateset->removeTextureAttribute( _bumpMapUnit, osg::StateAttribute::TEXTURE );
-        }
-
-        VirtualProgram* vp = VirtualProgram::get(stateset);
-        if ( vp )
-        {
-            Shaders pkg;
-            pkg.unload( vp, pkg.VertexModel );
-            pkg.unload( vp, pkg.VertexView );
-            pkg.unload( vp, pkg.FragmentSimple );
-            pkg.unload( vp, pkg.FragmentProgressive );
-        }
-    }
-    
-    if ( _bumpMapUnit >= 0 )
-    {
-        engine->getResources()->releaseTextureImageUnit( _bumpMapUnit );
-        _bumpMapUnit = -1;
-    }
-}
diff --git a/src/osgEarthExtensions/bumpmap/CMakeLists.txt b/src/osgEarthExtensions/bumpmap/CMakeLists.txt
deleted file mode 100644
index 7bd9ce6..0000000
--- a/src/osgEarthExtensions/bumpmap/CMakeLists.txt
+++ /dev/null
@@ -1,46 +0,0 @@
-#
-# bump mapping plugin
-#
-
-set(TARGET_GLSL
-    BumpMap.vert.model.glsl
-	BumpMap.vert.view.glsl
-    BumpMap.frag.simple.glsl
-    BumpMap.frag.progressive.glsl
-    BumpMap.frag.common.glsl)
-
-set(SHADERS_CPP "${CMAKE_CURRENT_BINARY_DIR}/AutoGenShaders.cpp")
-
-set(TARGET_IN
-    BumpMapShaders.cpp.in)
-
-configure_shaders(
-    BumpMapShaders.cpp.in
-    ${SHADERS_CPP}
-    ${TARGET_GLSL} )
-
-set(TARGET_SRC
-	BumpMapPlugin.cpp
-	BumpMapExtension.cpp
-	BumpMapTerrainEffect.cpp
-	${SHADERS_CPP} )
-	
-set(LIB_PUBLIC_HEADERS
-	BumpMapExtension
-	BumpMapOptions
-	BumpMapTerrainEffect)
-	
-set(TARGET_H
-	${LIB_PUBLIC_HEADERS}
-	BumpMapShaders )
-
-
-set(TARGET_COMMON_LIBRARIES ${TARGET_COMMON_LIBRARIES}
-    osgEarthUtil)
-	
-setup_extension(osgearth_bumpmap)
-
-# to install public driver includes:
-set(LIB_NAME bumpmap)
-
-#include(ModuleInstallOsgEarthExtensionIncludes OPTIONAL)
diff --git a/src/osgEarthExtensions/mapinspector/CMakeLists.txt b/src/osgEarthExtensions/mapinspector/CMakeLists.txt
deleted file mode 100644
index 6fad79a..0000000
--- a/src/osgEarthExtensions/mapinspector/CMakeLists.txt
+++ /dev/null
@@ -1,27 +0,0 @@
-#
-# MapInspector Extension
-#
-
-SET(TARGET_SRC
-	MapInspectorPlugin.cpp
-	MapInspectorExtension.cpp
-	MapInspectorUI.cpp)
-	
-SET(LIB_PUBLIC_HEADERS
-	MapInspectorExtension
-	MapInspectorUI)
-	
-SET(TARGET_H
-	${LIB_PUBLIC_HEADERS} )
-
-SET(TARGET_COMMON_LIBRARIES ${TARGET_COMMON_LIBRARIES}
-    osgEarthUtil
-	osgEarthFeatures
-	osgEarthSymbology)
-	
-SETUP_EXTENSION(osgearth_mapinspector)
-
-SET(LIB_NAME mapinspector)
-
-INCLUDE(ModuleInstallOsgEarthExtensionIncludes OPTIONAL)
-
diff --git a/src/osgEarthExtensions/mapinspector/MapInspectorExtension b/src/osgEarthExtensions/mapinspector/MapInspectorExtension
deleted file mode 100644
index b2e4a37..0000000
--- a/src/osgEarthExtensions/mapinspector/MapInspectorExtension
+++ /dev/null
@@ -1,84 +0,0 @@
-/* -*-c++-*- */
-/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
- * http://osgearth.org
- *
- * osgEarth is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>
- */
-#ifndef OSGEARTH_MAPINSPECTOR_EXTENSION
-#define OSGEARTH_MAPINSPECTOR_EXTENSION 1
-
-#include <osgEarth/Extension>
-#include <osgEarth/MapNode>
-#include <osgEarth/MapCallback>
-#include <osgEarthUtil/Controls>
-
-namespace osgEarth { namespace MapInspector
-{
-    using namespace osgEarth;
-    using namespace osgEarth::Util::Controls;
-
-    /**
-     * Displays visual metadata about the visible layers in a map.
-     */
-    class MapInspectorExtension : public Extension,
-                                  public ExtensionInterface<MapNode>,
-                                  public ExtensionInterface<Control>,
-                                  public MapCallback
-    {
-    public:
-        META_Object(osgearth_ext_MapInspector, MapInspectorExtension);
-
-        // CTORs
-        MapInspectorExtension();
-        MapInspectorExtension(const ConfigOptions& options);
-
-        // DTOR
-        virtual ~MapInspectorExtension();
-
-
-    public: // ExtensionInterface<MapNode>
-
-        bool connect(MapNode* mapNode);
-
-        bool disconnect(MapNode* mapNode);
-
-
-    public: // ExtensionInterface<Control>
-
-        bool connect(Control* control);
-
-        bool disconnect(Control* control);
-
-        
-    public: // MapCallback
-
-        void onMapModelChanged(const MapModelChange& change);
-
-
-    protected: // Object
-
-        MapInspectorExtension(const MapInspectorExtension& rhs, const osg::CopyOp& op) { }
-
-
-    private:
-        osg::observer_ptr<MapNode> _mapNode;
-        osg::ref_ptr<Control>      _ui;
-
-        void ctor();
-    };
-
-} } // namespace osgEarth::MapInspector
-
-#endif // OSGEARTH_MAPINSPECTOR_EXTENSION
diff --git a/src/osgEarthExtensions/mapinspector/MapInspectorExtension.cpp b/src/osgEarthExtensions/mapinspector/MapInspectorExtension.cpp
deleted file mode 100644
index a581b0e..0000000
--- a/src/osgEarthExtensions/mapinspector/MapInspectorExtension.cpp
+++ /dev/null
@@ -1,112 +0,0 @@
-/* -*-c++-*- */
-/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
- * http://osgearth.org
- *
- * osgEarth is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>
- */
-#include "MapInspectorExtension"
-#include "MapInspectorUI"
-
-#include <osgEarthFeatures/FeatureSource>
-#include <osgEarthDrivers/feature_ogr/OGRFeatureOptions>
-#include <osgEarthAnnotation/FeatureNode>
-#include <osgEarthSymbology/Style>
-
-using namespace osgEarth;
-using namespace osgEarth::Util;
-using namespace osgEarth::Util::Controls;
-using namespace osgEarth::MapInspector;
-
-#define LC "[MapInspector] "
-
-MapInspectorExtension::MapInspectorExtension()
-{
-    ctor();
-}
-
-MapInspectorExtension::MapInspectorExtension(const ConfigOptions& options)
-{
-    ctor();
-}
-
-MapInspectorExtension::~MapInspectorExtension()
-{
-    // nop
-}
-
-void
-MapInspectorExtension::ctor()
-{
-    OE_INFO << LC << "loaded\n";
-    _ui = new MapInspectorUI();
-}
-
-
-void 
-MapInspectorExtension::onMapModelChanged(const MapModelChange& change)
-{
-    osg::ref_ptr<MapNode> mapNode;
-    _mapNode.lock(mapNode);
-    static_cast<MapInspectorUI*>(_ui.get())->reinit(mapNode.get());
-}
-
-bool
-MapInspectorExtension::connect(MapNode* mapNode)
-{
-    OE_INFO << LC << "connected\n";
-    if ( mapNode )
-    {
-        _mapNode = mapNode;
-        _mapNode->getMap()->addMapCallback(this);
-        static_cast<MapInspectorUI*>(_ui.get())->reinit(mapNode);
-    }
-    
-    return true;
-}
-
-bool
-MapInspectorExtension::disconnect(MapNode* mapNode)
-{
-    OE_INFO << LC << "disconnected\n";
-
-    if ( mapNode )
-        mapNode->getMap()->removeMapCallback(this);
-
-    static_cast<MapInspectorUI*>(_ui.get())->reinit(0L);
-    return true;
-}
-
-bool
-MapInspectorExtension::connect(Control* control)
-{
-    Container* container = dynamic_cast<Container*>(control);
-    if ( container && _ui.valid() )
-    {
-        container->addControl( _ui.get() );
-    }
-
-    return true;
-}
-
-bool
-MapInspectorExtension::disconnect(Control* control)
-{
-    Container* container = dynamic_cast<Container*>(control);
-    if ( container && _ui.valid() )
-    {
-        container->removeChild( _ui.get() );
-    }
-    return true;
-}
diff --git a/src/osgEarthExtensions/mapinspector/MapInspectorPlugin.cpp b/src/osgEarthExtensions/mapinspector/MapInspectorPlugin.cpp
deleted file mode 100644
index 94ae2bd..0000000
--- a/src/osgEarthExtensions/mapinspector/MapInspectorPlugin.cpp
+++ /dev/null
@@ -1,55 +0,0 @@
-/* -*-c++-*- */
-/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
- * http://osgearth.org
- *
- * osgEarth is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>
- */
-#include "MapInspectorExtension"
-
-#include <osgDB/ReaderWriter>
-#include <osgDB/Registry>
-#include <osgDB/FileNameUtils>
-
-namespace osgEarth { namespace MapInspector
-{
-    /**
-     * Plugin entry point
-     */
-    class MapInspectorPlugin : public osgDB::ReaderWriter
-    {
-    public: // Plugin stuff
-
-        MapInspectorPlugin() {
-            supportsExtension( "osgearth_mapinspector", "osgEarth MapInspector Extension" );
-        }
-        
-        const char* className() {
-            return "osgEarth MapInspector Extension";
-        }
-
-        virtual ~MapInspectorPlugin() { }
-
-        ReadResult readObject(const std::string& filename, const osgDB::Options* dbOptions) const
-        {
-          if ( !acceptsExtension(osgDB::getLowerCaseFileExtension(filename)) )
-                return ReadResult::FILE_NOT_HANDLED;
-
-          return ReadResult( new MapInspectorExtension(Extension::getConfigOptions(dbOptions)) );
-        }
-    };
-
-    REGISTER_OSGPLUGIN(osgearth_mapinspector, MapInspectorPlugin)
-
-} } // namespace osgEarth::MapInspector
diff --git a/src/osgEarthExtensions/mapinspector/MapInspectorUI b/src/osgEarthExtensions/mapinspector/MapInspectorUI
deleted file mode 100644
index e825c40..0000000
--- a/src/osgEarthExtensions/mapinspector/MapInspectorUI
+++ /dev/null
@@ -1,49 +0,0 @@
-/* -*-c++-*- */
-/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
- * http://osgearth.org
- *
- * osgEarth is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>
- */
-#ifndef OSGEARTH_MAPINSPECTOR_UI
-#define OSGEARTH_MAPINSPECTOR_UI 1
-
-#include <osgEarth/MapCallback>
-#include <osgEarth/MapNode>
-#include <osgEarthUtil/Controls>
-#include <osg/View>
-
-namespace osgEarth { namespace MapInspector
-{
-    using namespace osgEarth;
-
-    class MapInspectorUI : public osgEarth::Util::Controls::Grid
-    {
-    public:
-        /** create UI */
-        MapInspectorUI();
-
-        /** rebuild everything */
-        void reinit(MapNode* mapNode);
-
-    private:
-        osg::ref_ptr<osg::Group>    _annos;
-
-        void addTerrainLayer(class TerrainLayer* layer, MapNode* mapNode);
-        void addModelLayer  (class ModelLayer*   layer, MapNode* mapNode);
-    };
-
-} } // namespace
-
-#endif // OSGEARTH_MAPINSPECTOR_UI
\ No newline at end of file
diff --git a/src/osgEarthExtensions/mapinspector/MapInspectorUI.cpp b/src/osgEarthExtensions/mapinspector/MapInspectorUI.cpp
deleted file mode 100644
index e9ee281..0000000
--- a/src/osgEarthExtensions/mapinspector/MapInspectorUI.cpp
+++ /dev/null
@@ -1,162 +0,0 @@
-/* -*-c++-*- */
-/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
- * http://osgearth.org
- *
- * osgEarth is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>
- */
-#include "MapInspectorUI"
-#include <osgEarth/GeoData>
-#include <osgEarthAnnotation/FeatureNode>
-#include <osgEarthAnnotation/LabelNode>
-#include <osgEarthFeatures/Feature>
-#include <osgEarthSymbology/Style>
-#include <osgEarthSymbology/Geometry>
-
-using namespace osgEarth;
-using namespace osgEarth::Annotation;
-using namespace osgEarth::Features;
-using namespace osgEarth::Symbology;
-using namespace osgEarth::MapInspector;
-
-namespace ui = osgEarth::Util::Controls;
-
-#define LC "[MapInspectorUI] "
-
-MapInspectorUI::MapInspectorUI()
-{
-    //nop
-}
-
-void
-MapInspectorUI::reinit(MapNode* mapNode)
-{
-    if ( !_annos.valid() )
-        _annos = new osg::Group();
-
-    _annos->removeChildren(0, _annos->getNumChildren());
-
-    this->clearControls();
-
-    if ( mapNode )
-    {
-        // install annotation group as neccesary
-        if (_annos->getNumParents() == 0 || _annos->getParent(0) != mapNode)
-        {
-            if ( _annos->getNumParents() > 0 )
-            {
-                _annos->getParent(0)->removeChild(_annos.get());
-            }
-            mapNode->addChild( _annos.get() );
-        }
-        
-        Map* map = mapNode->getMap();
-
-        for(int i=0; i<map->getNumElevationLayers(); ++i)
-        {
-            ElevationLayer* layer = map->getElevationLayerAt(i);
-            addTerrainLayer( layer, mapNode );
-        }
-
-        for(int i=0; i<map->getNumImageLayers(); ++i)
-        {
-            ImageLayer* layer = map->getImageLayerAt(i);
-            addTerrainLayer( layer, mapNode );
-        }
-
-        for(int i=0; i<map->getNumModelLayers(); ++i)
-        {
-            ModelLayer* layer = map->getModelLayerAt(i);
-            addModelLayer( layer, mapNode );
-        }
-    }
-    else
-    {
-        OE_INFO << LC << "MapNode is null\n";
-    }
-}
-
-void
-MapInspectorUI::addTerrainLayer(TerrainLayer* layer,
-                                MapNode*      mapNode)
-{
-    if ( layer->getTileSource() == 0L )
-        return;
-
-    const Color colors[6] = {
-        Color::White,
-        Color::Yellow,
-        Color::Cyan,
-        Color::Lime,
-        Color::Red,
-        Color::Magenta
-    };
-    Color color = colors[(int)layer->getUID()%6];
-
-    osg::ref_ptr<MultiGeometry> collection = new MultiGeometry();
-
-    const DataExtentList& exlist = layer->getTileSource()->getDataExtents();
-    for(DataExtentList::const_iterator i = exlist.begin(); i != exlist.end(); ++i)
-    {
-        const DataExtent& e = *i;
-        Polygon* p = new Polygon();
-        p->push_back( e.xMin(), e.yMin() );
-        p->push_back( e.xMax(), e.yMin() );
-        p->push_back( e.xMax(), e.yMax() );
-        p->push_back( e.xMin(), e.yMax() );
-        collection->add( p );
-    }
-
-    // poly:
-    {
-        Style style;
-        style.getOrCreate<LineSymbol>()->stroke()->color() = color;
-        style.getOrCreate<LineSymbol>()->stroke()->width() = 2;
-        style.getOrCreate<AltitudeSymbol>()->clamping() = AltitudeSymbol::CLAMP_TO_TERRAIN;
-        style.getOrCreate<AltitudeSymbol>()->technique() = AltitudeSymbol::TECHNIQUE_DRAPE;
-        style.getOrCreate<RenderSymbol>()->lighting() = false;
-
-        Feature* feature = new Feature(collection.get(), layer->getProfile()->getSRS(), style);
-        FeatureNode* node = new FeatureNode( mapNode, feature );
-        _annos->addChild( node );
-    }
-
-    // label:
-    std::string text = 
-        !layer->getName().empty()? layer->getName() :
-        Stringify() << "Layer " << layer->getUID();
-
-    {
-        Style style;
-        TextSymbol* ts = style.getOrCreate<TextSymbol>();
-        ts->halo()->color().set(0,0,0,1);
-        ts->declutter() = true;
-        ts->alignment() = TextSymbol::ALIGN_CENTER_CENTER;
-        
-        osg::Vec2d center = collection->getBounds().center2d();
-        GeoPoint position(layer->getProfile()->getSRS(), center.x(), center.y(), 0.0, ALTMODE_ABSOLUTE);
-
-        LabelNode* label = new LabelNode(mapNode, position, text, style);
-        _annos->addChild( label );
-    }
-
-    unsigned r = this->getNumRows();
-    setControl(0, r, new ui::LabelControl(text, color));
-}
-
-void
-MapInspectorUI::addModelLayer(ModelLayer* layer,
-                              MapNode*    mapNode)
-{
-}
diff --git a/src/osgEarthExtensions/noise/CMakeLists.txt b/src/osgEarthExtensions/noise/CMakeLists.txt
deleted file mode 100644
index 1fb5617..0000000
--- a/src/osgEarthExtensions/noise/CMakeLists.txt
+++ /dev/null
@@ -1,25 +0,0 @@
-#
-# Noise generator plugin
-#
-
-set(TARGET_SRC
-	NoisePlugin.cpp
-	NoiseExtension.cpp
-	NoiseTerrainEffect.cpp
-	${SHADERS_CPP} )
-	
-set(LIB_PUBLIC_HEADERS
-	NoiseExtension
-	NoiseOptions
-	NoiseTerrainEffect)
-	
-set(TARGET_H
-	${LIB_PUBLIC_HEADERS} )
-
-set(TARGET_COMMON_LIBRARIES ${TARGET_COMMON_LIBRARIES}
-    osgEarthUtil)
-	
-setup_extension(osgearth_noise)
-
-# to install public driver includes:
-set(LIB_NAME noise)
diff --git a/src/osgEarthExtensions/noise/NoiseExtension b/src/osgEarthExtensions/noise/NoiseExtension
deleted file mode 100644
index 1a2fcd1..0000000
--- a/src/osgEarthExtensions/noise/NoiseExtension
+++ /dev/null
@@ -1,73 +0,0 @@
-/* -*-c++-*- */
-/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
- * http://osgearth.org
- *
- * osgEarth is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>
- */
-#ifndef OSGEARTH_NOISE_EXTENSION
-#define OSGEARTH_NOISE_EXTENSION 1
-
-#include "NoiseOptions"
-#include "NoiseTerrainEffect"
-#include <osgEarth/Extension>
-#include <osgEarth/MapNode>
-#include <osgEarthUtil/Controls>
-
-namespace osgEarth { namespace Noise
-{
-    using namespace osgEarth;
-    using namespace osgEarth::Util::Controls;
-
-    /**
-     * Extension for loading the normal mapping effect on demand.
-     */
-    class NoiseExtension : public Extension,
-                               public ExtensionInterface<MapNode>
-    {
-    public:
-        META_Object(osgearth_ext_normalmap, NoiseExtension);
-
-        // CTORs
-        NoiseExtension();
-        NoiseExtension(const NoiseOptions& options);
-
-        // DTOR
-        virtual ~NoiseExtension();
-
-
-    public: // Extension
-
-        void setDBOptions(const osgDB::Options* dbOptions);
-
-
-    public: // ExtensionInterface<MapNode>
-
-        bool connect(MapNode* mapNode);
-
-        bool disconnect(MapNode* mapNode);
-
-
-    protected: // Object
-        NoiseExtension(const NoiseExtension& rhs, const osg::CopyOp& op) { }
-
-    private:
-        const NoiseOptions                 _options;
-        osg::ref_ptr<const osgDB::Options>     _dbOptions;
-        osg::ref_ptr<NoiseTerrainEffect>   _effect;
-    };
-
-} } // namespace osgEarth::Noise
-
-#endif // OSGEARTH_NOISE_EXTENSION
diff --git a/src/osgEarthExtensions/noise/NoiseExtension.cpp b/src/osgEarthExtensions/noise/NoiseExtension.cpp
deleted file mode 100644
index b7bcd44..0000000
--- a/src/osgEarthExtensions/noise/NoiseExtension.cpp
+++ /dev/null
@@ -1,78 +0,0 @@
-/* -*-c++-*- */
-/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
- * http://osgearth.org
- *
- * osgEarth is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>
- */
-#include "NoiseExtension"
-#include "NoiseTerrainEffect"
-
-using namespace osgEarth;
-using namespace osgEarth::Noise;
-
-#define LC "[NoiseExtension] "
-
-
-NoiseExtension::NoiseExtension()
-{
-    //nop
-}
-
-NoiseExtension::NoiseExtension(const NoiseOptions& options) :
-_options( options )
-{
-    //nop
-}
-
-NoiseExtension::~NoiseExtension()
-{
-    //nop
-}
-
-void
-NoiseExtension::setDBOptions(const osgDB::Options* dbOptions)
-{
-    _dbOptions = dbOptions;
-}
-
-bool
-NoiseExtension::connect(MapNode* mapNode)
-{
-    if ( !mapNode )
-    {
-        OE_WARN << LC << "Illegal: MapNode cannot be null." << std::endl;
-        return false;
-    }
-
-    _effect = new NoiseTerrainEffect( _dbOptions.get() );
-
-    mapNode->getTerrainEngine()->addEffect( _effect.get() );
-    
-    OE_INFO << LC << "Installed!\n";
-
-    return true;
-}
-
-bool
-NoiseExtension::disconnect(MapNode* mapNode)
-{
-    if ( mapNode )
-    {
-        mapNode->getTerrainEngine()->removeEffect( _effect.get() );
-    }
-    _effect = 0L;
-    return true;
-}
-
diff --git a/src/osgEarthExtensions/noise/NoiseOptions b/src/osgEarthExtensions/noise/NoiseOptions
deleted file mode 100644
index d7e316c..0000000
--- a/src/osgEarthExtensions/noise/NoiseOptions
+++ /dev/null
@@ -1,68 +0,0 @@
-/* -*-c++-*- */
-/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
- * http://osgearth.org
- *
- * osgEarth is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>
- */
-#ifndef OSGEARTH_DRIVER_NOISE_OPTIONS
-#define OSGEARTH_DRIVER_NOISE_OPTIONS 1
-
-#include <osgEarth/Common>
-#include <osgEarth/URI>
-
-namespace osgEarth { namespace Noise
-{
-    using namespace osgEarth;
-
-    /**
-     * Options governing the terrain noise texture.
-     */
-    class NoiseOptions : public DriverConfigOptions // NO EXPORT; header only
-    {
-    public:
-        // No properties.
-
-    public:
-        NoiseOptions( const ConfigOptions& opt =ConfigOptions() ) : DriverConfigOptions( opt )
-        {
-            setDriver( "noise" );
-            fromConfig( _conf );
-        }
-
-        virtual ~NoiseOptions() { }
-
-    public:
-        Config getConfig() const {
-            Config conf = DriverConfigOptions::getConfig();
-            // future props.
-            return conf;
-        }
-
-    protected:
-        void mergeConfig( const Config& conf ) {
-            DriverConfigOptions::mergeConfig( conf );
-            fromConfig( conf );
-        }
-
-    private:
-        void fromConfig( const Config& conf ) {
-            //future props
-        }
-    };
-
-} } // namespace osgEarth::Noise
-
-#endif // OSGEARTH_DRIVER_NOISE_OPTIONS
-
diff --git a/src/osgEarthExtensions/noise/NoisePlugin.cpp b/src/osgEarthExtensions/noise/NoisePlugin.cpp
deleted file mode 100644
index 31ebfe3..0000000
--- a/src/osgEarthExtensions/noise/NoisePlugin.cpp
+++ /dev/null
@@ -1,56 +0,0 @@
-/* -*-c++-*- */
-/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
- * http://osgearth.org
- *
- * osgEarth is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>
- */
-#include "NoiseOptions"
-#include "NoiseExtension"
-
-#include <osgDB/ReaderWriter>
-#include <osgDB/Registry>
-#include <osgDB/FileNameUtils>
-
-namespace osgEarth { namespace Noise
-{
-    /**
-     * Plugin entry point
-     */
-    class NoisePlugin : public osgDB::ReaderWriter
-    {
-    public: // Plugin stuff
-
-        NoisePlugin() {
-            supportsExtension( "osgearth_noise", "osgEarth Noise Generator Extension" );
-        }
-        
-        const char* className() {
-            return "osgEarth Noise Generator Extension";
-        }
-
-        virtual ~NoisePlugin() { }
-
-        ReadResult readObject(const std::string& filename, const osgDB::Options* dbOptions) const
-        {
-          if ( !acceptsExtension(osgDB::getLowerCaseFileExtension(filename)) )
-                return ReadResult::FILE_NOT_HANDLED;
-
-          return ReadResult( new NoiseExtension(Extension::getConfigOptions(dbOptions)) );
-        }
-    };
-
-    REGISTER_OSGPLUGIN(osgearth_noise, NoisePlugin)
-
-} } // namespace osgEarth::Noise
diff --git a/src/osgEarthExtensions/noise/NoiseTerrainEffect b/src/osgEarthExtensions/noise/NoiseTerrainEffect
deleted file mode 100644
index 26b73b3..0000000
--- a/src/osgEarthExtensions/noise/NoiseTerrainEffect
+++ /dev/null
@@ -1,62 +0,0 @@
-/* -*-c++-*- */
-/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2008-2012 Pelican Mapping
-* http://osgearth.org
-*
-* osgEarth is free software; you can redistribute it and/or modify
-* it under the terms of the GNU Lesser General Public License as published by
-* the Free Software Foundation; either version 2 of the License, or
-* (at your option) any later version.
-*
-* 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.
-*
-* You should have received a copy of the GNU Lesser General Public License
-* along with this program.  If not, see <http://www.gnu.org/licenses/>
-*/
-#ifndef OSGEARTH_NOISE_TERRAIN_EFFECT_H
-#define OSGEARTH_NOISE_TERRAIN_EFFECT_H
-
-#include <osgEarth/TerrainEffect>
-#include <osg/Uniform>
-#include <osg/Texture2D>
-
-using namespace osgEarth;
-
-namespace osgEarth { namespace Noise
-{
-    /**
-     * Effect that activates a multi-resolution noise texture on the terrain.
-     */
-    class NoiseTerrainEffect : public TerrainEffect
-    {
-    public:
-        /** construct a new terrain effect. */
-        NoiseTerrainEffect(const osgDB::Options* dbOptions);
-
-
-    public: // TerrainEffect interface
-
-        void onInstall(TerrainEngineNode* engine);
-
-        void onUninstall(TerrainEngineNode* engine);
-
-
-    protected:
-        virtual ~NoiseTerrainEffect() { }
-
-        osg::Texture* createNoiseTexture() const;
-
-        int                          _texImageUnit;
-        osg::ref_ptr<osg::Texture>   _tex;
-        osg::ref_ptr<osg::Uniform>   _samplerUniform;
-    };
-
-} } // namespace osgEarth::Noise
-
-#endif // OSGEARTH_NOISE_TERRAIN_EFFECT_H
diff --git a/src/osgEarthExtensions/noise/NoiseTerrainEffect.cpp b/src/osgEarthExtensions/noise/NoiseTerrainEffect.cpp
deleted file mode 100644
index a1b91e2..0000000
--- a/src/osgEarthExtensions/noise/NoiseTerrainEffect.cpp
+++ /dev/null
@@ -1,166 +0,0 @@
-/* -*-c++-*- */
-/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2008-2012 Pelican Mapping
-* http://osgearth.org
-*
-* osgEarth is free software; you can redistribute it and/or modify
-* it under the terms of the GNU Lesser General Public License as published by
-* the Free Software Foundation; either version 2 of the License, or
-* (at your option) any later version.
-*
-* 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.
-*
-* You should have received a copy of the GNU Lesser General Public License
-* along with this program.  If not, see <http://www.gnu.org/licenses/>
-*/
-#include "NoiseTerrainEffect"
-
-#include <osgEarth/Registry>
-#include <osgEarth/Capabilities>
-#include <osgEarth/TerrainEngineNode>
-#include <osgEarth/ImageUtils>
-#include <osgEarthUtil/SimplexNoise>
-
-#include <osgDB/WriteFile>
-
-#define LC "[Noise] "
-
-#define SAMPLER_NAME "oe_noise_tex"
-//#define MATRIX_NAME  "oe_nmap_normalTexMatrix"
-
-using namespace osgEarth;
-using namespace osgEarth::Noise;
-
-NoiseTerrainEffect::NoiseTerrainEffect(const osgDB::Options* dbOptions) :
-_texImageUnit( -1 )
-{
-    _tex = createNoiseTexture();
-}
-
-void
-NoiseTerrainEffect::onInstall(TerrainEngineNode* engine)
-{
-    if ( engine )
-    {
-        engine->getResources()->reserveTextureImageUnit(_texImageUnit, "Noise");
-        if ( _texImageUnit >= 0 )
-        {        
-            osg::StateSet* stateset = engine->getOrCreateStateSet();
-            stateset->setTextureAttribute( _texImageUnit, _tex.get() );
-            stateset->addUniform( new osg::Uniform(SAMPLER_NAME, _texImageUnit) );
-            OE_INFO << LC << "Noise generator installed!\n";
-        }
-        else
-        {
-            OE_WARN << LC << "No texture image units available; noise disabled.\n";
-        }
-    }
-}
-
-
-void
-NoiseTerrainEffect::onUninstall(TerrainEngineNode* engine)
-{
-    if ( engine && _texImageUnit >= 0 )
-    {
-        osg::StateSet* stateset = engine->getStateSet();
-        if ( stateset )
-        {
-            stateset->removeUniform( SAMPLER_NAME );
-            stateset->removeTextureAttribute( _texImageUnit, _tex.get() );
-        }
-
-        engine->getResources()->releaseTextureImageUnit( _texImageUnit );
-        _texImageUnit = -1;
-    }
-}
-
-
-osg::Texture*
-NoiseTerrainEffect::createNoiseTexture() const
-{
-    const int size = 1024;
-    const int slices = 1;
-
-    GLenum type = slices > 2 ? GL_RGBA : GL_LUMINANCE;
-    
-    osg::Image* image = new osg::Image();
-    image->allocateImage(size, size, 1, type, GL_UNSIGNED_BYTE);
-
-    // 0 = rocky mountains..
-    // 1 = warping...
-    const float F[4] = { 4.0f, 16.0f, 4.0f, 8.0f };
-    const float P[4] = { 0.8f,  0.6f, 0.8f, 0.9f };
-    const float L[4] = { 2.2f,  1.7f, 3.0f, 4.0f };
-    
-    for(int k=0; k<slices; ++k)
-    {
-        // Configure the noise function:
-        osgEarth::Util::SimplexNoise noise;
-        noise.setNormalize( true );
-        noise.setRange( 0.0, 1.0 );
-        noise.setFrequency( F[k] );
-        noise.setPersistence( P[k] );
-        noise.setLacunarity( L[k] );
-        noise.setOctaves( 8 );
-
-        float nmin = 10.0f;
-        float nmax = -10.0f;
-
-        // write repeating noise to the image:
-        ImageUtils::PixelReader read ( image );
-        ImageUtils::PixelWriter write( image );
-        for(int t=0; t<size; ++t)
-        {
-            double rt = (double)t/size;
-            for(int s=0; s<size; ++s)
-            {
-                double rs = (double)s/(double)size;
-
-                double n = noise.getTiledValue(rs, rt);
-
-                n = osg::clampBetween(n, 0.0, 1.0);
-
-                if ( n < nmin ) nmin = n;
-                if ( n > nmax ) nmax = n;
-                osg::Vec4f v = read(s, t);
-                v[k] = n;
-                write(v, s, t);
-            }
-        }
-   
-        // histogram stretch to [0..1]
-        for(int x=0; x<size*size; ++x)
-        {
-            int s = x%size, t = x/size;
-            osg::Vec4f v = read(s, t);
-            v[k] = osg::clampBetween((v[k]-nmin)/(nmax-nmin), 0.0f, 1.0f);
-            write(v, s, t);
-        }
-
-        //OE_INFO << LC << "Noise: MIN = " << nmin << "; MAX = " << nmax << "\n";
-    }
-
-#if 1
-    std::string filename("noise.png");
-    osgDB::writeImageFile(*image, filename);
-    OE_NOTICE << LC << "Wrote noise texture to " << filename << "\n";
-#endif
-
-    // make a texture:
-    osg::Texture2D* tex = new osg::Texture2D( image );
-    tex->setWrap(tex->WRAP_S, tex->REPEAT);
-    tex->setWrap(tex->WRAP_T, tex->REPEAT);
-    tex->setFilter(tex->MIN_FILTER, tex->LINEAR_MIPMAP_LINEAR);
-    tex->setFilter(tex->MAG_FILTER, tex->LINEAR);
-    tex->setMaxAnisotropy( 4.0f );
-    tex->setUnRefImageDataAfterApply( true );
-
-    return tex;
-}
diff --git a/src/osgEarthExtensions/normalmap/CMakeLists.txt b/src/osgEarthExtensions/normalmap/CMakeLists.txt
deleted file mode 100644
index 528f4a1..0000000
--- a/src/osgEarthExtensions/normalmap/CMakeLists.txt
+++ /dev/null
@@ -1,43 +0,0 @@
-#
-# normal mapping plugin
-#
-
-set(TARGET_GLSL
-    NormalMap.vert.glsl
-    NormalMap.frag.glsl)
-
-set(TARGET_IN
-    NormalMapShaders.cpp.in)
-
-set(SHADERS_CPP "${CMAKE_CURRENT_BINARY_DIR}/AutoGenShaders.cpp")
-
-configure_shaders(
-    NormalMapShaders.cpp.in
-    ${SHADERS_CPP}
-    ${TARGET_GLSL} )
-
-set(TARGET_SRC
-	NormalMapPlugin.cpp
-	NormalMapExtension.cpp
-	NormalMapTerrainEffect.cpp
-	${SHADERS_CPP} )
-	
-set(LIB_PUBLIC_HEADERS
-	NormalMapExtension
-	NormalMapOptions
-	NormalMapTerrainEffect)
-	
-set(TARGET_H
-	${LIB_PUBLIC_HEADERS}
-	NormalMapShaders )
-
-
-set(TARGET_COMMON_LIBRARIES ${TARGET_COMMON_LIBRARIES}
-    osgEarthUtil)
-	
-setup_extension(osgearth_normalmap)
-
-# to install public driver includes:
-set(LIB_NAME normalmap)
-
-#include(ModuleInstallOsgEarthExtensionIncludes OPTIONAL)
diff --git a/src/osgEarthExtensions/normalmap/NormalMap.frag.glsl b/src/osgEarthExtensions/normalmap/NormalMap.frag.glsl
deleted file mode 100644
index 1124ebc..0000000
--- a/src/osgEarthExtensions/normalmap/NormalMap.frag.glsl
+++ /dev/null
@@ -1,27 +0,0 @@
-#version 110
-#pragma vp_entryPoint "oe_nmap_fragment"
-#pragma vp_location   "fragment_coloring"
-#pragma vp_order      "0.2"
-
-// stage global:
-vec3 oe_global_Normal;
-
-uniform vec4 oe_tile_key;
-uniform sampler2D oe_nmap_normalTex;
-varying vec4 oe_nmap_normalCoords;
-varying mat3 oe_nmap_TBN;
-
-void oe_nmap_fragment(inout vec4 color)
-{
-    vec4 encodedNormal = texture2D(oe_nmap_normalTex, oe_nmap_normalCoords.st);
-    vec3 normalTangent = normalize(encodedNormal.xyz*2.0-1.0);
-    oe_global_Normal = normalize(oe_nmap_TBN * normalTangent);
-
-    // visualize curvature:
-    //color.rgb = vec3(0,0,0);
-    //if(decoded.a >= 0.4) color.r = 1.0;
-    //if(decoded.a <= -0.4) color.b = 1.0;
-
-    // visualize normals:
-    //color.rgb = encodedNormal.xyz;
-}
diff --git a/src/osgEarthExtensions/normalmap/NormalMap.vert.glsl b/src/osgEarthExtensions/normalmap/NormalMap.vert.glsl
deleted file mode 100644
index 26dde1c..0000000
--- a/src/osgEarthExtensions/normalmap/NormalMap.vert.glsl
+++ /dev/null
@@ -1,25 +0,0 @@
-#version 110
-#pragma vp_entryPoint "oe_nmap_vertex"
-#pragma vp_location   "vertex_model"
-#pragma vp_order      "0.5"
-
-varying vec3 oe_Normal;
-varying vec4 oe_layer_tilec;
-
-uniform mat4 oe_nmap_normalTexMatrix;
-varying vec4 oe_nmap_normalCoords;
-varying mat3 oe_nmap_TBN;
-
-void oe_nmap_vertex(inout vec4 VertexMODEL)
-{
-    // calculate the sampling coordinates for the normal texture
-    oe_nmap_normalCoords = oe_nmap_normalTexMatrix * oe_layer_tilec;
-
-    // form the matrix that will transform a normal vector from
-    // tangent space to model space in the fragment shader.
-    // We expect the vertex normal to be a simple UP vector.
-    vec3 B = vec3(0,1,0);
-    vec3 N = oe_Normal;
-    vec3 T = normalize(cross(B,N));
-    oe_nmap_TBN = gl_NormalMatrix * mat3(T, B, N);
-}
\ No newline at end of file
diff --git a/src/osgEarthExtensions/normalmap/NormalMapExtension b/src/osgEarthExtensions/normalmap/NormalMapExtension
deleted file mode 100644
index 241486b..0000000
--- a/src/osgEarthExtensions/normalmap/NormalMapExtension
+++ /dev/null
@@ -1,73 +0,0 @@
-/* -*-c++-*- */
-/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
- * http://osgearth.org
- *
- * osgEarth is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>
- */
-#ifndef OSGEARTH_NORMALMAP_EXTENSION
-#define OSGEARTH_NORMALMAP_EXTENSION 1
-
-#include "NormalMapOptions"
-#include "NormalMapTerrainEffect"
-#include <osgEarth/Extension>
-#include <osgEarth/MapNode>
-#include <osgEarthUtil/Controls>
-
-namespace osgEarth { namespace NormalMap
-{
-    using namespace osgEarth;
-    using namespace osgEarth::Util::Controls;
-
-    /**
-     * Extension for loading the normal mapping effect on demand.
-     */
-    class NormalMapExtension : public Extension,
-                               public ExtensionInterface<MapNode>
-    {
-    public:
-        META_Object(osgearth_ext_normalmap, NormalMapExtension);
-
-        // CTORs
-        NormalMapExtension();
-        NormalMapExtension(const NormalMapOptions& options);
-
-        // DTOR
-        virtual ~NormalMapExtension();
-
-
-    public: // Extension
-
-        void setDBOptions(const osgDB::Options* dbOptions);
-
-
-    public: // ExtensionInterface<MapNode>
-
-        bool connect(MapNode* mapNode);
-
-        bool disconnect(MapNode* mapNode);
-
-
-    protected: // Object
-        NormalMapExtension(const NormalMapExtension& rhs, const osg::CopyOp& op) { }
-
-    private:
-        const NormalMapOptions                 _options;
-        osg::ref_ptr<const osgDB::Options>     _dbOptions;
-        osg::ref_ptr<NormalMapTerrainEffect>   _effect;
-    };
-
-} } // namespace osgEarth::NormalMap
-
-#endif // OSGEARTH_NORMALMAP_EXTENSION
diff --git a/src/osgEarthExtensions/normalmap/NormalMapExtension.cpp b/src/osgEarthExtensions/normalmap/NormalMapExtension.cpp
deleted file mode 100644
index b1f565b..0000000
--- a/src/osgEarthExtensions/normalmap/NormalMapExtension.cpp
+++ /dev/null
@@ -1,80 +0,0 @@
-/* -*-c++-*- */
-/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
- * http://osgearth.org
- *
- * osgEarth is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>
- */
-#include "NormalMapExtension"
-#include "NormalMapTerrainEffect"
-
-#include <osgEarth/MapNode>
-
-using namespace osgEarth;
-using namespace osgEarth::NormalMap;
-
-#define LC "[NormalMapExtension] "
-
-
-NormalMapExtension::NormalMapExtension()
-{
-    //nop
-}
-
-NormalMapExtension::NormalMapExtension(const NormalMapOptions& options) :
-_options( options )
-{
-    //nop
-}
-
-NormalMapExtension::~NormalMapExtension()
-{
-    //nop
-}
-
-void
-NormalMapExtension::setDBOptions(const osgDB::Options* dbOptions)
-{
-    _dbOptions = dbOptions;
-}
-
-bool
-NormalMapExtension::connect(MapNode* mapNode)
-{
-    if ( !mapNode )
-    {
-        OE_WARN << LC << "Illegal: MapNode cannot be null." << std::endl;
-        return false;
-    }
-
-    _effect = new NormalMapTerrainEffect( _dbOptions.get() );
-
-    mapNode->getTerrainEngine()->addEffect( _effect.get() );
-    
-    OE_INFO << LC << "Installed!\n";
-
-    return true;
-}
-
-bool
-NormalMapExtension::disconnect(MapNode* mapNode)
-{
-    if ( mapNode )
-    {
-        mapNode->getTerrainEngine()->removeEffect( _effect.get() );
-    }
-    _effect = 0L;
-    return true;
-}
-
diff --git a/src/osgEarthExtensions/normalmap/NormalMapOptions b/src/osgEarthExtensions/normalmap/NormalMapOptions
deleted file mode 100644
index 248f1c4..0000000
--- a/src/osgEarthExtensions/normalmap/NormalMapOptions
+++ /dev/null
@@ -1,72 +0,0 @@
-/* -*-c++-*- */
-/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
- * http://osgearth.org
- *
- * osgEarth is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>
- */
-#ifndef OSGEARTH_DRIVER_NORMALMAP_OPTIONS
-#define OSGEARTH_DRIVER_NORMALMAP_OPTIONS 1
-
-#include <osgEarth/Common>
-#include <osgEarth/URI>
-
-namespace osgEarth { namespace NormalMap
-{
-    using namespace osgEarth;
-
-    /**
-     * Options governing normal mapping of the terrain.
-     */
-    class NormalMapOptions : public DriverConfigOptions // NO EXPORT; header only
-    {
-    public:
-        // No properties.
-
-    public:
-        NormalMapOptions( const ConfigOptions& opt =ConfigOptions() ) : DriverConfigOptions( opt )
-        {
-            setDriver( "normalmap" );
-            fromConfig( _conf );
-        }
-
-        virtual ~NormalMapOptions() { }
-
-    public:
-        Config getConfig() const {
-            Config conf = DriverConfigOptions::getConfig();
-            // future props.
-            return conf;
-        }
-
-    protected:
-        void mergeConfig( const Config& conf ) {
-            DriverConfigOptions::mergeConfig( conf );
-            fromConfig( conf );
-        }
-
-    private:
-        void fromConfig( const Config& conf ) {
-            //future props
-        }
-
-        optional<URI>   _imageURI;
-        optional<float> _intensity;
-        optional<float> _scale;
-    };
-
-} } // namespace osgEarth::NormalMap
-
-#endif // OSGEARTH_DRIVER_NORMALMAP_OPTIONS
-
diff --git a/src/osgEarthExtensions/normalmap/NormalMapPlugin.cpp b/src/osgEarthExtensions/normalmap/NormalMapPlugin.cpp
deleted file mode 100644
index 18de306..0000000
--- a/src/osgEarthExtensions/normalmap/NormalMapPlugin.cpp
+++ /dev/null
@@ -1,56 +0,0 @@
-/* -*-c++-*- */
-/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
- * http://osgearth.org
- *
- * osgEarth is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>
- */
-#include "NormalMapOptions"
-#include "NormalMapExtension"
-
-#include <osgDB/ReaderWriter>
-#include <osgDB/Registry>
-#include <osgDB/FileNameUtils>
-
-namespace osgEarth { namespace NormalMap
-{
-    /**
-     * Plugin entry point
-     */
-    class NormalMapPlugin : public osgDB::ReaderWriter
-    {
-    public: // Plugin stuff
-
-        NormalMapPlugin() {
-            supportsExtension( "osgearth_normalmap", "osgEarth Normal Map Extension Plugin" );
-        }
-        
-        const char* className() {
-            return "osgEarth Normal Map Extension Plugin";
-        }
-
-        virtual ~NormalMapPlugin() { }
-
-        ReadResult readObject(const std::string& filename, const osgDB::Options* dbOptions) const
-        {
-          if ( !acceptsExtension(osgDB::getLowerCaseFileExtension(filename)) )
-                return ReadResult::FILE_NOT_HANDLED;
-
-          return ReadResult( new NormalMapExtension(Extension::getConfigOptions(dbOptions)) );
-        }
-    };
-
-    REGISTER_OSGPLUGIN(osgearth_normalmap, NormalMapPlugin)
-
-} } // namespace osgEarth::NormalMap
diff --git a/src/osgEarthExtensions/normalmap/NormalMapShaders b/src/osgEarthExtensions/normalmap/NormalMapShaders
deleted file mode 100644
index 95d1616..0000000
--- a/src/osgEarthExtensions/normalmap/NormalMapShaders
+++ /dev/null
@@ -1,33 +0,0 @@
-// ***DO NOT EDIT THIS FILE - IT IS AUTOMATICALLY GENERATED BY CMAKE***
-/* -*-c++-*- */
-/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2008-2012 Pelican Mapping
-* http://osgearth.org
-*
-* osgEarth is free software; you can redistribute it and/or modify
-* it under the terms of the GNU Lesser General Public License as published by
-* the Free Software Foundation; either version 2 of the License, or
-* (at your option) any later version.
-*
-* 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.
-*
-* You should have received a copy of the GNU Lesser General Public License
-* along with this program.  If not, see <http://www.gnu.org/licenses/>
-*/
-#include <osgEarth/ShaderLoader>
-
-namespace osgEarth { namespace NormalMap
-{
-    struct Shaders : public osgEarth::ShaderPackage
-	{
-        Shaders();
-        std::string Vertex, Fragment;
-	};
-	
-} } // namespace osgEarth/NormalMap
diff --git a/src/osgEarthExtensions/normalmap/NormalMapShaders.cpp.in b/src/osgEarthExtensions/normalmap/NormalMapShaders.cpp.in
deleted file mode 100644
index e7549b2..0000000
--- a/src/osgEarthExtensions/normalmap/NormalMapShaders.cpp.in
+++ /dev/null
@@ -1,14 +0,0 @@
-// ***DO NOT EDIT THIS FILE - IT IS AUTOMATICALLY GENERATED BY CMAKE***
-
-#include <osgEarthExtensions/normalmap/NormalMapShaders>
-
-using namespace osgEarth::NormalMap;
-
-Shaders::Shaders()
-{
-    Vertex = "NormalMap.vert.glsl";
-    _sources[Vertex] = OE_MULTILINE(@NormalMap.vert.glsl@);
-
-    Fragment = "NormalMap.frag.glsl";
-    _sources[Fragment] = OE_MULTILINE(@NormalMap.frag.glsl@);
-}
diff --git a/src/osgEarthExtensions/normalmap/NormalMapTerrainEffect b/src/osgEarthExtensions/normalmap/NormalMapTerrainEffect
deleted file mode 100644
index 34f6770..0000000
--- a/src/osgEarthExtensions/normalmap/NormalMapTerrainEffect
+++ /dev/null
@@ -1,64 +0,0 @@
-/* -*-c++-*- */
-/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2008-2012 Pelican Mapping
-* http://osgearth.org
-*
-* osgEarth is free software; you can redistribute it and/or modify
-* it under the terms of the GNU Lesser General Public License as published by
-* the Free Software Foundation; either version 2 of the License, or
-* (at your option) any later version.
-*
-* 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.
-*
-* You should have received a copy of the GNU Lesser General Public License
-* along with this program.  If not, see <http://www.gnu.org/licenses/>
-*/
-#ifndef OSGEARTH_NORMALMAP_TERRAIN_EFFECT_H
-#define OSGEARTH_NORMALMAP_TERRAIN_EFFECT_H
-
-#include <osgEarth/TerrainEffect>
-#include <osgEarth/ImageLayer>
-#include <osg/Image>
-#include <osg/Uniform>
-#include <osg/Texture2D>
-
-using namespace osgEarth;
-
-namespace osgEarth { namespace NormalMap
-{
-    /**
-     * Effect that applies normal mapping to the terrain.
-     */
-    class NormalMapTerrainEffect : public TerrainEffect
-    {
-    public:
-        /** construct a new terrain effect. */
-        NormalMapTerrainEffect(
-            const osgDB::Options* dbOptions);
-
-
-    public: // TerrainEffect interface
-
-        void onInstall(TerrainEngineNode* engine);
-
-        void onUninstall(TerrainEngineNode* engine);
-
-
-    protected:
-        virtual ~NormalMapTerrainEffect() { }
-
-        bool _ok;
-        int  _normalMapUnit;
-        osg::ref_ptr<osg::Texture2D> _normalMapTex;
-        osg::ref_ptr<osg::Uniform>   _normalMapTexUniform;
-    };
-
-} } // namespace osgEarth::NormalMap
-
-#endif // OSGEARTH_NORMALMAP_TERRAIN_EFFECT_H
diff --git a/src/osgEarthExtensions/normalmap/NormalMapTerrainEffect.cpp b/src/osgEarthExtensions/normalmap/NormalMapTerrainEffect.cpp
deleted file mode 100644
index 4d444b7..0000000
--- a/src/osgEarthExtensions/normalmap/NormalMapTerrainEffect.cpp
+++ /dev/null
@@ -1,136 +0,0 @@
-/* -*-c++-*- */
-/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2008-2012 Pelican Mapping
-* http://osgearth.org
-*
-* osgEarth is free software; you can redistribute it and/or modify
-* it under the terms of the GNU Lesser General Public License as published by
-* the Free Software Foundation; either version 2 of the License, or
-* (at your option) any later version.
-*
-* 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.
-*
-* You should have received a copy of the GNU Lesser General Public License
-* along with this program.  If not, see <http://www.gnu.org/licenses/>
-*/
-#include "NormalMapTerrainEffect"
-
-#include <osgEarth/Registry>
-#include <osgEarth/Capabilities>
-#include <osgEarth/VirtualProgram>
-#include <osgEarth/TerrainEngineNode>
-#include <osgEarth/TerrainTileNode>
-#include <osgEarth/ShaderLoader>
-
-#include "NormalMapShaders"
-
-#define LC "[NormalMap] "
-
-#define NORMAL_SAMPLER "oe_nmap_normalTex"
-#define NORMAL_MATRIX  "oe_nmap_normalTexMatrix"
-
-using namespace osgEarth;
-using namespace osgEarth::NormalMap;
-
-namespace
-{
-    class NormalTexInstaller : public TerrainTileNodeCallback
-    {
-    public:
-        NormalTexInstaller(NormalMapTerrainEffect* effect, int unit)
-            : _effect(effect), _unit(unit) { }
-        
-    public: // TileNodeCallback
-        void operator()(const TileKey& key, osg::Node* node)
-        {
-            TerrainTileNode* tile = osgEarth::findTopMostNodeOfType<TerrainTileNode>(node);
-            if ( !tile )
-                return;
-            
-            osg::StateSet* ss = node->getOrCreateStateSet();
-            osg::Texture* tex = tile->getNormalTexture();
-            if ( tex )
-            {
-                ss->setTextureAttribute(_unit, tex);
-            }
-
-            osg::RefMatrixf* mat = tile->getNormalTextureMatrix();
-            osg::Matrixf fmat;
-            if ( mat )
-            {
-                fmat = osg::Matrixf(*mat);
-            }
-            else
-            {
-                // special marker indicating that there's no valid normal texture.
-                fmat(0,0) = 0.0f;
-            }
-
-            ss->addUniform(new osg::Uniform(NORMAL_MATRIX, fmat) );
-        }
-
-    private:
-        osg::observer_ptr<NormalMapTerrainEffect> _effect;
-        int _unit;
-    };
-}
-
-
-NormalMapTerrainEffect::NormalMapTerrainEffect(const osgDB::Options* dbOptions) :
-_normalMapUnit( -1 )
-{
-    //nop
-}
-
-void
-NormalMapTerrainEffect::onInstall(TerrainEngineNode* engine)
-{
-    if ( engine )
-    {
-        engine->requireNormalTextures();
-
-        engine->getResources()->reserveTextureImageUnit(_normalMapUnit, "NormalMap");
-        engine->addTileNodeCallback( new NormalTexInstaller(this, _normalMapUnit) );
-        
-        // shader components
-        osg::StateSet* stateset = engine->getTerrainStateSet();
-        VirtualProgram* vp = VirtualProgram::getOrCreate(stateset);
-
-        // configure shaders
-        Shaders package;
-        package.load( vp, package.Vertex );
-        package.load( vp, package.Fragment );
-        
-        stateset->addUniform( new osg::Uniform(NORMAL_SAMPLER, _normalMapUnit) );
-    }
-}
-
-
-void
-NormalMapTerrainEffect::onUninstall(TerrainEngineNode* engine)
-{
-    osg::StateSet* stateset = engine->getStateSet();
-    if ( stateset )
-    {
-        VirtualProgram* vp = VirtualProgram::get(stateset);
-        if ( vp )
-        {
-            Shaders package;
-            package.unload( vp, package.Vertex );
-            package.unload( vp, package.Fragment );
-        }
-        stateset->removeUniform( NORMAL_SAMPLER );
-    }
-    
-    if ( _normalMapUnit >= 0 )
-    {
-        engine->getResources()->releaseTextureImageUnit( _normalMapUnit );
-        _normalMapUnit = -1;
-    }
-}
diff --git a/src/osgEarthExtensions/splat/Biome b/src/osgEarthExtensions/splat/Biome
deleted file mode 100644
index 684ad7a..0000000
--- a/src/osgEarthExtensions/splat/Biome
+++ /dev/null
@@ -1,83 +0,0 @@
-/* -*-c++-*- */
-/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
- * http://osgearth.org
- *
- * osgEarth is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>
- */
-#ifndef OSGEARTH_SPLAT_BIOME_H
-#define OSGEARTH_SPLAT_BIOME_H 1
-
-#include "SplatExport"
-#include "SplatCatalog"
-#include <osgEarth/GeoData>
-#include <vector>
-
-namespace osgEarth { namespace Splat
-{
-    /**
-     * Defines a set of geospatial extents under which to apply a particular
-     * procedural catalog.
-     */
-    class Biome
-    {
-    public: // types        
-        struct Region
-        {
-            GeoExtent extent;
-            double    zmin, zmin2;
-            double    zmax, zmax2;
-            double    meanRadius2;
-            osg::Polytope tope;
-        };
-
-    public:
-        /** Construct an empty biome. */
-        Biome();
-
-        /** Deserialize a biome. */
-        Biome(const Config& conf);
-
-        /** Get the list of bounding boxes enclosing this biome. */
-        std::vector<Region>& getRegions() { return _regions; }
-        const std::vector<Region>& getRegions() const { return _regions; }
-
-        /** Name of this biome. */
-        optional<std::string>& name() { return _name; }
-        const optional<std::string>& name() const { return _name; }
-
-        /** URI of the catalog mapped to this biome */
-        optional<URI>& catalogURI() { return _catalogURI; }
-        const optional<URI>& catalogURI() const { return _catalogURI; }
-
-        /** The catalog to apply for this biome. */
-        void setCatalog(SplatCatalog* catalog) { _catalog = catalog; }
-        SplatCatalog* getCatalog() const { return _catalog.get(); }
-
-        /** Serialize this biome's primitive members. */
-        Config getConfig() const;
-
-    protected:
-
-        optional<std::string>      _name;
-        optional<URI>              _catalogURI;
-        std::vector<Region>        _regions;
-        osg::ref_ptr<SplatCatalog> _catalog;
-    };
-
-    typedef std::vector<Biome> BiomeVector;
-
-} } // namespace osgEarth::Splat
-
-#endif // OSGEARTH_SPLAT_BIOME_H
diff --git a/src/osgEarthExtensions/splat/Biome.cpp b/src/osgEarthExtensions/splat/Biome.cpp
deleted file mode 100644
index e977ff4..0000000
--- a/src/osgEarthExtensions/splat/Biome.cpp
+++ /dev/null
@@ -1,73 +0,0 @@
-/* -*-c++-*- */
-/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
- * http://osgearth.org
- *
- * osgEarth is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>
- */
-#include "Biome"
-
-using namespace osgEarth;
-using namespace osgEarth::Splat;
-
-#define LC "[Biome] "
-
-#define SPLAT_BIOME_CURRENT_VERSION 1
-
-
-//............................................................................
-
-Biome::Biome()
-{
-    //nop
-}
-
-Biome::Biome(const Config& conf)
-{
-    conf.getIfSet( "name", _name );
-    conf.getIfSet( "catalog", _catalogURI );
-    
-    // only supports lat long for now
-    const SpatialReference* srs = SpatialReference::create("wgs84");
-    
-    const Config& extentsConf = conf.child("regions");
-    for(ConfigSet::const_iterator i = extentsConf.children().begin();
-        i != extentsConf.children().end();
-        ++i)
-    {
-        double xmin = i->value("xmin", -DBL_MAX);
-        double xmax = i->value("xmax",  DBL_MAX);
-        double ymin = i->value("ymin", -DBL_MAX);
-        double ymax = i->value("ymax",  DBL_MAX);
-        double zmin = i->value("zmin", -DBL_MAX);
-        double zmax = i->value("zmax",  DBL_MAX);
-        
-        _regions.push_back( Region() );
-        _regions.back().extent = GeoExtent(srs, xmin, ymin, xmax, ymax);
-        _regions.back().zmin  = zmin;
-        _regions.back().zmax  = zmax;
-    }
-}
-
-Config
-Biome::getConfig() const
-{
-    Config conf("biome");
-    conf.addIfSet( "name",    _name );
-    conf.addIfSet( "catalog", _catalogURI );
-    // TODO: add regions
-    OE_WARN << LC << "INTERNAL: Biome::getConfig() not fully implemented.\n";
-    return conf;
-}
-
diff --git a/src/osgEarthExtensions/splat/BiomeSelector b/src/osgEarthExtensions/splat/BiomeSelector
deleted file mode 100644
index c4c4838..0000000
--- a/src/osgEarthExtensions/splat/BiomeSelector
+++ /dev/null
@@ -1,53 +0,0 @@
-/* -*-c++-*- */
-/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
- * http://osgearth.org
- *
- * osgEarth is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>
- */
-#ifndef OSGEARTH_SPLAT_BIOME_SELECTOR_CALLBACK
-#define OSGEARTH_SPLAT_BIOME_SELECTOR_CALLBACK 1
-
-#include "Biome"
-#include <osg/NodeCallback>
-#include <osg/Polytope>
-
-namespace osgEarth { namespace Splat
-{
-    /**
-     * Cull callback that applies the approprate stateset based on what
-     * it determines to be the active Biome.
-     */
-    class BiomeSelector : public osg::NodeCallback
-    {
-    public:
-        BiomeSelector(
-            const BiomeVector&           biomes,
-            const SplatTextureDefVector& textureDefs,
-            osg::StateSet*               basicStateSet,
-            int                          textureImageUnit);
-
-    public: // osg::NodeCallback
-
-        void operator()(osg::Node* node, osg::NodeVisitor* nv);
-
-    protected:
-        BiomeVector                                _biomes;
-        std::vector< osg::ref_ptr<osg::StateSet> > _stateSets;
-        std::vector< osg::Polytope >               _topes;
-    };
-
-} } // namespace osgEarth::Splat
-
-#endif // OSGEARTH_SPLAT_BIOME_SELECTOR_CALLBACK
diff --git a/src/osgEarthExtensions/splat/BiomeSelector.cpp b/src/osgEarthExtensions/splat/BiomeSelector.cpp
deleted file mode 100644
index 56e5194..0000000
--- a/src/osgEarthExtensions/splat/BiomeSelector.cpp
+++ /dev/null
@@ -1,143 +0,0 @@
-/* -*-c++-*- */
-/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
- * http://osgearth.org
- *
- * osgEarth is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>
- */
-#include "BiomeSelector"
-
-#include <osgEarth/CullingUtils>
-#include <osgEarth/VirtualProgram>
-#include <osgEarth/GeoData>
-
-using namespace osgEarth;
-using namespace osgEarth::Splat;
-
-#define LC "[BiomeSelector] "
-
-BiomeSelector::BiomeSelector(const BiomeVector&           biomes,
-                             const SplatTextureDefVector& textureDefs,
-                             osg::StateSet*               stateSet,
-                             int                          textureImageUnit) :
-_biomes( biomes )
-{
-    for(unsigned i=0; i<_biomes.size(); ++i)
-    {
-        Biome& biome = _biomes[i];
-
-        // pre-calculate optimized values for each biome region.
-        std::vector<Biome::Region>& regions = biome.getRegions();
-        for(unsigned r=0; r<regions.size(); ++r)
-        {
-            Biome::Region& region = regions[r];
-            region.extent.createPolytope( region.tope );
-            region.zmin2 = region.zmin > -DBL_MAX ? region.zmin*region.zmin : region.zmin;
-            region.zmax2 = region.zmax < DBL_MAX ? region.zmax*region.zmax : region.zmax;
-
-            // this only needs to be very approximate.
-            region.meanRadius2 = region.extent.getSRS()->isGeographic() ?
-                region.extent.getSRS()->getEllipsoid()->getRadiusEquator() : 0.0;
-            region.meanRadius2 *= region.meanRadius2;
-        }
-
-        // next, set up a stateset with the approprate texture and program
-        // for this biome.
-        const SplatTextureDef& textureDef = textureDefs[i];
-
-        // shallow-copy the stateset in prepration for customization:
-        osg::StateSet* biomeSS = 
-            i == 0 ? stateSet :
-            osg::clone(stateSet, osg::CopyOp::SHALLOW_COPY);
-
-        // install his biome's texture set:
-        biomeSS->setTextureAttribute(textureImageUnit, textureDef._texture.get());
-
-        // install this biome's sampling function. Use cloneOrCreate since each
-        // stateset needs a different shader set in its VP.
-        VirtualProgram* vp = VirtualProgram::cloneOrCreate( biomeSS );
-        osg::Shader* shader = new osg::Shader(osg::Shader::FRAGMENT, textureDef._samplingFunction);
-        vp->setShader( "oe_splat_getRenderInfo", shader );
-
-        // put it on the list for fast access in the cull traversal.
-        _stateSets.push_back( biomeSS );
-    }
-}
-
-void
-BiomeSelector::operator()(osg::Node* node, osg::NodeVisitor* nv)
-{
-    osgUtil::CullVisitor* cv = Culling::asCullVisitor(nv);
-
-    osg::Vec3d vp = cv->getViewPoint();
-    double z2 = vp.length2();
-    
-    osg::StateSet* stateSet = 0L;
-
-    for(unsigned b=0; b<_biomes.size() && stateSet == 0L; ++b)
-    {
-        const Biome& biome = _biomes[b];        
-        bool match = false;
-            
-        if ( biome.getRegions().size() == 0 )
-        {
-            // empty biome is a match.
-            //OE_INFO << "matched " << b << "b/c biome has no regions\n";
-            match = true;
-        }
-        else
-        {
-            // check each region of the biome:
-            for(unsigned r=0; r<biome.getRegions().size() && !match; ++r)
-            {
-                const Biome::Region& region = biome.getRegions()[r];
-
-                // empty extent/tope is a match:
-                if ( region.tope.empty() )
-                {
-                    //OE_INFO << "matched " << b << "b/c tope is empty\n";
-                    match = true;
-                }
-
-                // otherwise, check for intersection:
-                else if ( region.tope.contains(vp) )
-                {
-                    double hat2 = z2 - region.meanRadius2;
-                    if ( hat2 >= region.zmin2 && hat2 <= region.zmax2 )
-                    {
-                        //OE_INFO << "matched " << b << "b/c eyepoint intersects\n";
-                        match = true;
-                    }
-                }
-            }
-        }
-
-        if ( match )
-        {
-            stateSet = _stateSets[b].get();
-        }
-    }
-
-    if ( stateSet )
-    {
-        cv->pushStateSet( stateSet );
-    }
-
-    traverse(node, nv);
-
-    if ( stateSet )
-    {
-        cv->popStateSet();
-    }
-}
diff --git a/src/osgEarthExtensions/splat/CMakeLists.txt b/src/osgEarthExtensions/splat/CMakeLists.txt
deleted file mode 100644
index bc77317..0000000
--- a/src/osgEarthExtensions/splat/CMakeLists.txt
+++ /dev/null
@@ -1,60 +0,0 @@
-#
-# texture splatting plugin
-#
-
-set(TARGET_GLSL
-    Splat.types.glsl
-    Splat.Noise.glsl
-    Splat.vert.model.glsl
-    Splat.vert.view.glsl
-    Splat.frag.glsl
-    Splat.frag.common.glsl
-    Splat.frag.getRenderInfo.glsl
-    Splat.util.glsl )
-
-set(SHADERS_CPP "${CMAKE_CURRENT_BINARY_DIR}/AutoGenShaders.cpp")
-
-configure_shaders(
-    SplatShaders.cpp.in
-    ${SHADERS_CPP}
-    ${TARGET_GLSL} )
-
-set(TARGET_IN    
-    SplatShaders.cpp.in)
-
-set(TARGET_SRC
-    Biome.cpp
-	BiomeSelector.cpp
-    LandUseTileSource.cpp
-	SplatPlugin.cpp
-	SplatExtension.cpp
-	SplatCatalog.cpp
-	SplatTerrainEffect.cpp
-	SplatCoverageLegend.cpp
-    ${SHADERS_CPP})
-	
-set(LIB_PUBLIC_HEADERS
-    Biome
-	BiomeSelector
-    LandUseTileSource
-	SplatCoverageLegend
-	SplatCatalog
-	SplatExtension
-	SplatOptions
-	SplatTerrainEffect)
-	
-SET(TARGET_H
-	${LIB_PUBLIC_HEADERS}
-	SplatExport
-	SplatShaders)
-
-SET(TARGET_COMMON_LIBRARIES ${TARGET_COMMON_LIBRARIES}
-    osgEarthUtil)
-	
-setup_extension(osgearth_splat)
-
-# to install public driver includes:
-set(LIB_NAME splat)
-
-include(ModuleInstallOsgEarthExtensionIncludes OPTIONAL)
-
diff --git a/src/osgEarthExtensions/splat/LandUseTileSource b/src/osgEarthExtensions/splat/LandUseTileSource
deleted file mode 100644
index 972e43c..0000000
--- a/src/osgEarthExtensions/splat/LandUseTileSource
+++ /dev/null
@@ -1,180 +0,0 @@
-/* -*-c++-*- */
-/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
- * http://osgearth.org
- *
- * osgEarth is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>
- */
-#ifndef OSGEARTH_SPLAT_LAND_USE_TILE_SOURCE
-#define OSGEARTH_SPLAT_LAND_USE_TILE_SOURCE 1
-
-#include <osgEarth/TileSource>
-#include <osgEarth/ImageLayer>
-#include <osgEarthUtil/SimplexNoise>
-#include <osgDB/FileNameUtils>
-
-namespace osgEarth { namespace Splat
-{
-    /**
-     * Configuration options for the land use tile source
-     */
-    class LandUseOptions : public osgEarth::TileSourceOptions    
-    {
-    public:
-        LandUseOptions(const osgEarth::TileSourceOptions& options)
-            : osgEarth::TileSourceOptions(options)
-        {
-            setDriver("landuse");
-            baseLOD().init( 32u );
-            warpFactor().init( 0.01f );
-            fromConfig( _conf );
-        }
-
-    public:
-        
-        /**
-         * Image layer from which to read source coverage data.
-         */
-        optional<ImageLayerOptions>& imageLayerOptions() { return _imageLayerOptions; }
-        const optional<ImageLayerOptions>& imageLayerOptions() const { return _imageLayerOptions; }
-
-        std::vector<ImageLayerOptions>& imageLayerOptionsVector() { return _imageLayerOptionsVec; }
-        const std::vector<ImageLayerOptions>& imageLayerOptionsVector() const { return _imageLayerOptionsVec; }
-
-        /**
-         * Amount by which to warp texture coordinates of coverage data.
-         * Try 0.01 as a starting point.
-         */
-        optional<float>& warpFactor() { return _warp; }
-        const optional<float>& warpFactor() const { return _warp; }
-
-        /**
-         * LOD at which to calculate the noise function for warping.
-         */
-        optional<unsigned>& baseLOD() { return _baseLOD; }
-        const optional<unsigned>& baseLOD() const { return _baseLOD; }
-
-        /**
-         * Bit size of the encoded data. The default is 32 (for a 32-bit signed
-         * floating point value) but you can set it to 16 if you know your data
-         * values are all within the range of a signed 16-bit float.
-         */
-        optional<unsigned>& bits() { return _bits; }
-        const optional<unsigned>& bits() const { return _bits; }
-
-    public:
-        Config getConfig() const
-        {
-            Config conf;
-            conf.addIfSet("warp",      _warp);
-            conf.addIfSet("base_lod",  _baseLOD);
-            conf.addIfSet("bits",      _bits);
-            conf.addObjIfSet( "image", _imageLayerOptions );
-            
-            for(std::vector<ImageLayerOptions>::const_iterator i = _imageLayerOptionsVec.begin();
-                i != _imageLayerOptionsVec.end(); 
-                ++i)
-            {
-                conf.add( "image", i->getConfig() );
-            }
-            return conf;
-        }
-
-    protected:
-        void mergeConfig( const Config& conf ) {
-            TileSourceOptions::mergeConfig( conf );
-            fromConfig( conf );
-        }
-
-    private:
-        void fromConfig( const Config& conf )
-        {
-            conf.getIfSet("warp", _warp);
-            conf.getIfSet("base_lod", _baseLOD);
-            conf.getIfSet("bits",      _bits);
-            conf.getObjIfSet( "image", _imageLayerOptions );
-            
-            ConfigSet layerConfs = conf.children("image");
-            for(ConfigSet::const_iterator i = layerConfs.begin(); i != layerConfs.end(); ++i)
-            {
-                _imageLayerOptionsVec.push_back( ImageLayerOptions(*i) );
-            }
-        }
-        
-    private:
-        optional<float>             _warp;
-        optional<unsigned>          _baseLOD;
-        optional<unsigned>          _bits;
-        optional<ImageLayerOptions> _imageLayerOptions;
-        std::vector<ImageLayerOptions> _imageLayerOptionsVec;
-    };
-
-    /**
-     * Tile source that will read from ANOTHER tile source and perform
-     * various pre-processing syntheses operations like warping and detailing.
-     */
-    class LandUseTileSource : public osgEarth::TileSource
-    {
-    public:
-        LandUseTileSource(const LandUseOptions& options);
-
-    public: // TileSource
-
-        // Initialize the tile source.
-        Status initialize(const osgDB::Options* options);
-
-        // Create an image.
-        osg::Image* createImage(const osgEarth::TileKey& key, osgEarth::ProgressCallback* progress);
-
-    protected:
-        virtual ~LandUseTileSource() { }
-
-        osg::ref_ptr<osgDB::Options> _dbOptions;
-        LandUseOptions               _options;        
-        osg::ref_ptr<ImageLayer>     _imageLayer;
-        ImageLayerVector             _imageLayers;
-        std::vector<float>           _warps;
-        osgEarth::Util::SimplexNoise _noiseGen;
-    };
-
-    /**
-     * Driver plugin used to load a land use tile source.
-     */
-    class LandUseDriver : public osgEarth::TileSourceDriver
-    {
-    public:
-        LandUseDriver()
-        {
-            supportsExtension( "osgearth_landuse", "Land Use Driver" );
-        }
-
-        virtual const char* className()
-        {
-            return "Land Use Driver";
-        }
-
-        virtual ReadResult readObject(const std::string& file_name, const Options* options) const
-        {
-            if ( !acceptsExtension(osgDB::getLowerCaseFileExtension( file_name )))
-                return ReadResult::FILE_NOT_HANDLED;
-
-            return new LandUseTileSource( getTileSourceOptions(options) );
-        }
-    };
-
-    REGISTER_OSGPLUGIN(osgearth_landuse, LandUseDriver);
-
-} } // namespace osgEarth::Splat
-
-#endif // OSGEARTH_SPLAT_LAND_USE_TILE_SOURCE
diff --git a/src/osgEarthExtensions/splat/LandUseTileSource.cpp b/src/osgEarthExtensions/splat/LandUseTileSource.cpp
deleted file mode 100644
index 94ad4f6..0000000
--- a/src/osgEarthExtensions/splat/LandUseTileSource.cpp
+++ /dev/null
@@ -1,283 +0,0 @@
-/* -*-c++-*- */
-/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
- * http://osgearth.org
- *
- * osgEarth is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>
- */
-#include "LandUseTileSource"
-#include <osgEarth/ImageLayer>
-#include <osgEarth/MapFrame>
-#include <osgEarth/Registry>
-#include <osgEarth/ImageUtils>
-#include <osgEarthUtil/SimplexNoise>
-
-using namespace osgEarth;
-using namespace osgEarth::Splat;
-
-#define LC "[LandUseTileSource] "
-
-namespace
-{
-    osg::Vec2 getSplatCoords(const TileKey& key, float baseLOD, const osg::Vec2& covUV)
-    {
-        osg::Vec2 out;
-
-        float dL = (float)key.getLOD() - baseLOD;
-        float factor = pow(2.0f, dL);
-        float invFactor = 1.0/factor;
-        out.set( covUV.x()*invFactor, covUV.y()*invFactor ); 
-
-        // For upsampling we need to calculate an offset as well
-        if ( factor >= 1.0 )
-        {
-            unsigned wide, high;
-            key.getProfile()->getNumTiles(key.getLOD(), wide, high);
-
-            float tileX = (float)key.getTileX();
-            float tileY = (float)(wide-1-key.getTileY()); // swap Y. (not done in the shader version.)
-
-            osg::Vec2 a( floor(tileX*invFactor), floor(tileY*invFactor) );
-            osg::Vec2 b( a.x()*factor, a.y()*factor );
-            osg::Vec2 c( (a.x()+1.0f)*factor, (a.y()+1.0f)*factor );
-            osg::Vec2 offset( (tileX-b.x())/(c.x()-b.x()), (tileY-b.y())/(c.y()-b.y()) );
-
-            out += offset;
-        }
-
-        return out;
-    }
-
-    osg::Vec2 warpCoverageCoords(const osg::Vec2& covIn, float noise, float warp)
-    {
-        float n1 = 2.0 * noise - 1.0;
-        return osg::Vec2(
-            osg::clampBetween( covIn.x() + n1*warp, 0.0f, 1.0f ),
-            osg::clampBetween( covIn.y() + n1*warp, 0.0f, 1.0f ) );
-    }
-
-    float getNoise(osgEarth::Util::SimplexNoise& noiseGen, const osg::Vec2& uv)
-    {
-        // TODO: check that u and v are 0..s and not 0..s-1
-        double n = noiseGen.getTiledValue(uv.x(), uv.y());
-        n = osg::clampBetween(n, 0.0, 1.0);
-        //out = n;
-        return n;
-    }
-}
-
-
-LandUseTileSource::LandUseTileSource(const LandUseOptions& options) :
-TileSource( options ),
-_options  ( options )
-{
-    //nop
-}
-
-TileSource::Status
-LandUseTileSource::initialize(const osgDB::Options* dbOptions)
-{
-    _dbOptions = Registry::instance()->cloneOrCreateOptions(dbOptions);
-
-    const Profile* profile = getProfile();
-    if ( !profile )
-    {
-        profile = osgEarth::Registry::instance()->getGlobalGeodeticProfile();
-        setProfile( profile );
-    }
-
-    // load the image layer:
-    if ( _options.imageLayerOptions().isSet() )
-    {
-        ImageLayerOptions ilo = _options.imageLayerOptions().get();
-        ilo.cachePolicy() = CachePolicy::NO_CACHE;
-        _imageLayer = new ImageLayer( ilo );
-        _imageLayer->setTargetProfileHint( profile );
-    }
-
-    // load all the image layers:
-    _imageLayers.assign( _options.imageLayerOptionsVector().size(), 0L );
-    _warps.assign( _options.imageLayerOptionsVector().size(), 0.0f );
-
-    for(unsigned i=0; i<_options.imageLayerOptionsVector().size(); ++i)
-    {
-        ImageLayerOptions ilo = _options.imageLayerOptionsVector()[i];
-        ilo.cachePolicy() = CachePolicy::NO_CACHE;
-        ImageLayer* layer = new ImageLayer( ilo );
-        layer->setTargetProfileHint( profile );
-        _imageLayers[i] = layer;
-
-        Config conf = ilo.getConfig();
-        _warps[i] = conf.value("warp", _options.warpFactor().get());
-    }
-
-    // set up the IO options so that we do not cache input data.
-    CachePolicy::NO_CACHE.apply( _dbOptions.get() );
-
-    // set up the noise generator.
-    const float F[4] = { 4.0f, 16.0f, 4.0f, 8.0f };
-    const float P[4] = { 0.8f,  0.6f, 0.8f, 0.9f };
-    const float L[4] = { 2.2f,  1.7f, 3.0f, 4.0f };
-    
-    // Configure the noise function:
-    _noiseGen.setNormalize  ( true );
-    _noiseGen.setRange      ( 0.0, 1.0 );
-    _noiseGen.setFrequency  ( F[0] );
-    _noiseGen.setPersistence( P[0] );
-    _noiseGen.setLacunarity ( L[0] );
-    _noiseGen.setOctaves    ( 8 );
-
-    return STATUS_OK;
-}
-
-namespace
-{
-    struct ILayer 
-    {
-        GeoImage  image;
-        float     scale;
-        osg::Vec2 bias;
-        bool      valid;
-        float     warp;
-        ImageUtils::PixelReader* read;
-
-        ILayer() : valid(true), read(0L) { }
-
-        ~ILayer() { if (read) delete read; }
-
-        void load(const TileKey& key, ImageLayer* sourceLayer, float sourceWarp, ProgressCallback* progress)
-        {
-            if ( sourceLayer->getEnabled() && sourceLayer->getVisible() && sourceLayer->isKeyInRange(key) )
-            {
-                for(TileKey k = key; k.valid() && !image.valid(); k = k.createParentKey())
-                {
-                    image = sourceLayer->createImage(k, progress);
-                } 
-            }
-
-            valid = image.valid();
-
-            if ( valid )
-            {
-                scale = key.getExtent().width() / image.getExtent().width();
-                bias.x() = (key.getExtent().xMin() - image.getExtent().xMin()) / image.getExtent().width();
-                bias.y() = (key.getExtent().yMin() - image.getExtent().yMin()) / image.getExtent().height();
-
-                read = new ImageUtils::PixelReader(image.getImage());
-
-                warp = sourceWarp;
-            }
-        }
-    };
-}
-
-osg::Image*
-LandUseTileSource::createImage(const TileKey&    key,
-                               ProgressCallback* progress)
-{
-    if ( _imageLayers.empty() )
-        return 0L;
-
-    std::vector<ILayer> layers(_imageLayers.size());
-
-    // Allocate the new coverage image; it will contain unnormalized values.
-    osg::Image* out = new osg::Image();
-    ImageUtils::markAsUnNormalized(out, true);
-
-    // Allocate a suitable format:
-    GLenum dataType;
-    GLint  internalFormat;
-    
-    if ( _options.bits().isSetTo(16u) )
-    {
-        // 16-bit float:
-        dataType       = GL_FLOAT;
-        internalFormat = GL_LUMINANCE16F_ARB;
-    }
-    else //if ( _options.bits().isSetTo(32u) )
-    {
-        // 32-bit float:
-        dataType       = GL_FLOAT;
-        internalFormat = GL_LUMINANCE32F_ARB;
-    }
-    
-    int tilesize = getPixelsPerTile();
-
-    out->allocateImage(tilesize, tilesize, 1, GL_LUMINANCE, dataType);
-    out->setInternalTextureFormat(internalFormat);
-
-    float noiseLOD = _options.baseLOD().get();
-    float warp     = _options.warpFactor().get();
-
-    osg::Vec2 cov;    // coverage coordinates
-    float     noise;  // noise value
-    osg::Vec2 noiseCoords;
-
-    ImageUtils::PixelWriter write( out );
-
-    float du = 1.0f / (float)(out->s()-1);
-    float dv = 1.0f / (float)(out->t()-1);
-
-    osg::Vec4 nodata;
-    if (internalFormat == GL_LUMINANCE16F_ARB)
-        nodata.set(-32768, -32768, -32768, -32768);
-    else
-        nodata.set(NO_DATA_VALUE, NO_DATA_VALUE, NO_DATA_VALUE, NO_DATA_VALUE);
-
-    for(float u=0.0f; u<=1.0f; u+=du)
-    {
-        for(float v=0.0f; v<=1.0f; v+=dv)
-        {
-            bool wrotePixel = false;
-            for(int L = layers.size()-1; L >= 0 && !wrotePixel; --L)
-            {
-                ILayer& layer = layers[L];
-                if ( !layer.valid )
-                    continue;
-
-                if ( !layer.image.valid() )
-                    layer.load(key, _imageLayers[L], _warps[L], progress);
-
-                if ( !layer.valid )
-                    continue;
-
-                osg::Vec2 cov(layer.scale*u + layer.bias.x(), layer.scale*v + layer.bias.y());
-
-                if ( cov.x() >= 0.0f && cov.x() <= 1.0f && cov.y() >= 0.0f && cov.y() <= 1.0f )
-                {
-                    // Noise is like a repeating overlay at the noiseLOD. So sample it using
-                    // straight U/V tile coordinates.
-                    noiseCoords = getSplatCoords( key, noiseLOD, osg::Vec2(u,v) );
-                    noise = getNoise( _noiseGen, noiseCoords );
-
-                    cov = warpCoverageCoords(cov, noise, layer.warp);
-
-                    osg::Vec4 texel = (*layer.read)(cov.x(), cov.y());
-                    if ( texel.r() != NO_DATA_VALUE )
-                    {
-                        write.f(texel, u, v);
-                        wrotePixel = true;
-                    }
-                }
-            }
-
-            if ( !wrotePixel )
-            {
-                write.f(nodata, u, v);
-            }
-        }
-    }
-
-    return out;
-}
diff --git a/src/osgEarthExtensions/splat/Splat.frag.common.glsl b/src/osgEarthExtensions/splat/Splat.frag.common.glsl
deleted file mode 100644
index a0e0488..0000000
--- a/src/osgEarthExtensions/splat/Splat.frag.common.glsl
+++ /dev/null
@@ -1,29 +0,0 @@
-// begin: Splat.frag.common.glsl
-
-#pragma vp_define "OE_USE_NORMAL_MAP"
-#ifdef OE_USE_NORMAL_MAP
-
-// normal map version:
-uniform sampler2D oe_nmap_normalTex;
-in vec4 oe_nmap_normalCoords;
-
-float oe_splat_getSlope()
-{
-    vec4 encodedNormal = texture2D(oe_nmap_normalTex, oe_nmap_normalCoords.st);
-    vec3 normalTangent = normalize(encodedNormal.xyz*2.0-1.0);
-    return clamp((1.0-normalTangent.z)/0.8, 0.0, 1.0);
-}
-
-#else // !OE_USE_NORMAL_MAP
-
-// non- normal map version:
-in float oe_splat_slope;
-
-float oe_splat_getSlope()
-{
-    return oe_splat_slope;
-}
-
-#endif // OE_USE_NORMAL_MAP
-
-// end: Splat.frag.common.glsl
\ No newline at end of file
diff --git a/src/osgEarthExtensions/splat/Splat.frag.getRenderInfo.glsl b/src/osgEarthExtensions/splat/Splat.frag.getRenderInfo.glsl
deleted file mode 100644
index 3ee6f7b..0000000
--- a/src/osgEarthExtensions/splat/Splat.frag.getRenderInfo.glsl
+++ /dev/null
@@ -1,18 +0,0 @@
-#version 330
-
-#pragma include "Splat.types.glsl"
-
-// Samples the coverage data and returns main and detail indices.
-oe_SplatRenderInfo oe_splat_getRenderInfo(in float value, in oe_SplatEnv env)
-{
-    float primary = -1.0;   // primary texture index
-    float detail = -1.0;    // detail texture index
-    float brightness = 1.0; // default noise function brightness factor
-    float contrast = 1.0;   // default noise function contrast factor
-    float threshold = 0.0;  // default noise function threshold
-    float slope = 0.0;      // default minimum slope
-
-    $CODE_INJECTION_POINT
-
-    return oe_SplatRenderInfo(primary, detail, brightness, contrast, threshold, slope);
-}
diff --git a/src/osgEarthExtensions/splat/Splat.frag.glsl b/src/osgEarthExtensions/splat/Splat.frag.glsl
deleted file mode 100644
index 63e867f..0000000
--- a/src/osgEarthExtensions/splat/Splat.frag.glsl
+++ /dev/null
@@ -1,275 +0,0 @@
-#version 330
-
-#pragma vp_entryPoint "oe_splat_complex"
-#pragma vp_location   "fragment_coloring"
-#pragma vp_order      "0.4"                 // before terrain image layers
-
-// define to activate 'edit' mode in which uniforms control
-// the splatting parameters.
-#pragma vp_define "SPLAT_EDIT"
-
-// define to activate GPU-generated noise instead of a noise texture.
-#pragma vp_define "SPLAT_GPU_NOISE"
-
-// include files
-#pragma include "Splat.types.glsl"
-#pragma include "Splat.frag.common.glsl"
-
-// ref: Splat.getRenderInfo.frag.glsl
-oe_SplatRenderInfo oe_splat_getRenderInfo(in float value, in oe_SplatEnv env);
-
-// from: Splat.util.glsl
-void oe_splat_getLodBlend(in float range, in float baseLOD, out float lod0, out float lod1, out float blend);
-vec2 oe_splat_getSplatCoords(in vec2 coords, in float lod);
-
-// from the terrain engine:
-in vec4 oe_layer_tilec;
-uniform vec4 oe_tile_key;
-
-// from the vertex shader:
-in vec2 oe_splat_covtc;
-in float oe_splat_range;
-
-// from SplatTerrainEffect:
-uniform float oe_splat_warp;
-uniform float oe_splat_blur;
-uniform sampler2D oe_splat_coverageTex;
-uniform sampler2DArray oe_splatTex;
-uniform float oe_splat_scaleOffset;
-
-uniform float oe_splat_detailRange;
-uniform float oe_splat_noiseScale;
-uniform float oe_splat_useBilinear; // 1=true, -1=false
-
-#ifdef SPLAT_EDIT
-uniform float oe_splat_brightness;
-uniform float oe_splat_contrast;
-uniform float oe_splat_threshold;
-uniform float oe_splat_minSlope;
-#endif
-
-// Warps the coverage sampling coordinates to mitigate blockiness.
-vec2 oe_splat_warpCoverageCoords(in vec2 splat_tc, in oe_SplatEnv env)
-{
-    vec2 seed = oe_splat_covtc;
-    float n1 = 2.0*env.noise.y-1.0;
-    vec2 tc = oe_splat_covtc + n1*oe_splat_warp;
-    return clamp(tc, 0.0, 1.0);
-}
-
-vec4 oe_splat_getTexel(in float index, in vec2 tc)
-{
-    return texture(oe_splatTex, vec3(tc, index));
-}
-
-// Samples a detail texel using its render info parameters.
-// Returns the weighting factor in the alpha channel.
-vec4 oe_splat_getDetailTexel(in oe_SplatRenderInfo ri, in vec2 tc, in oe_SplatEnv env)
-{
-    float hasDetail = ri.detailIndex >= 0.0 ? 1.0 : 0.0;
-
-#ifdef SPLAT_EDIT
-    float brightness = oe_splat_brightness;
-    float contrast = oe_splat_contrast;
-    float threshold = oe_splat_threshold;
-    float minSlope = oe_splat_minSlope;
-#else
-    float brightness = ri.brightness;
-    float contrast = ri.contrast;
-    float threshold = ri.threshold;
-    float minSlope = ri.minSlope;
-#endif
-
-    // start with the noise value
-    float n = env.noise.x;
-	
-    // apply slope limiter, then reclamp and threshold:
-    float s;
-    if ( env.slope >= minSlope )
-        s = 1.0;
-    else if ( env.slope < 0.1*minSlope )
-        s = 0.0;
-    else
-        s = (env.slope-0.1*minSlope)/(minSlope-0.1*minSlope);
-
-    brightness *= s;
-
-    // apply brightness and contrast, then reclamp
-    n = clamp(((n-0.5)*contrast + 0.5) * brightness, 0.0, 1.0);
-    
-    // apply final threshold:
-	n = n < threshold ? 0.0 : n;
-
-    // sample the texel and return it.
-    vec4 result = oe_splat_getTexel( max(ri.detailIndex,0), tc);
-    return vec4(result.rgb, hasDetail*n);
-}
-
-// Generates a texel using nearest-neighbor coverage sampling.
-vec4 oe_splat_nearest(in vec2 splat_tc, in oe_SplatEnv env)
-{
-    vec2 tc = oe_splat_covtc; //oe_splat_warpCoverageCoords(splat_tc, env);
-    float coverageValue = texture2D(oe_splat_coverageTex, tc).r;
-    oe_SplatRenderInfo ri = oe_splat_getRenderInfo(coverageValue, env);
-    vec4 primary = oe_splat_getTexel(ri.primaryIndex, splat_tc);
-    float detailToggle = ri.detailIndex >= 0 ? 1.0 : 0.0;
-    vec4 detail  = oe_splat_getDetailTexel(ri, splat_tc, env) * detailToggle;    
-    return vec4( mix(primary.rgb, detail.rgb, detail.a), 1.0 );
-}
-
-// Generates a texel using bilinear filtering on the coverage data.
-vec4 oe_splat_bilinear(in vec2 splat_tc, in oe_SplatEnv env)
-{
-    vec4 texel = vec4(0,0,0,1);
-
-    //TODO: coverage warping is slow due to the noise function. Consider removing/reworking.
-    vec2 tc = oe_splat_covtc; //oe_splat_warpCoverageCoords(splat_tc, env);
-
-    float a = oe_splat_blur;
-    float pixelWidth = a/256.0; // 256 = hard-coded cov tex size //TODO 
-    float halfPixelWidth = 0.5*pixelWidth;
-    float pixelWidth2 = pixelWidth*pixelWidth;
-
-    // Find the four quantized coverage coordinates that form a box around the actual
-    // coverage coordinates, where each quantized coord is at the center of a coverage texel.
-    vec2 rem = mod(tc, pixelWidth);
-    vec2 sw;
-    sw.x = tc.x - rem.x + (rem.x >= halfPixelWidth ? halfPixelWidth : -halfPixelWidth);
-    sw.y = tc.y - rem.y + (rem.y >= halfPixelWidth ? halfPixelWidth : -halfPixelWidth);
-    vec2 ne = sw + pixelWidth;
-    vec2 nw = vec2(sw.x, ne.y);
-    vec2 se = vec2(ne.x, sw.y);
-
-    // Calculate the weighting for each corner.
-    vec2 dsw = tc-sw;
-    vec2 dse = tc-se;
-    vec2 dne = tc-ne;
-    vec2 dnw = tc-nw;
-
-    float sw_weight = max(pixelWidth2-dot(dsw,dsw),0.0);
-    float se_weight = max(pixelWidth2-dot(dse,dse),0.0);
-    float ne_weight = max(pixelWidth2-dot(dne,dne),0.0);
-    float nw_weight = max(pixelWidth2-dot(dnw,dnw),0.0);
-
-    // normalize the weights so they total 1.0
-    float invTotalWeight = 1.0/(sw_weight+se_weight+ne_weight+nw_weight);
-    sw_weight *= invTotalWeight;
-    se_weight *= invTotalWeight;
-    ne_weight *= invTotalWeight;
-    nw_weight *= invTotalWeight;
-
-    // Sample coverage values using quantized corner coords:
-    float value_sw = texture2D(oe_splat_coverageTex, clamp(sw, 0.0, 1.0)).r;
-    float value_se = texture2D(oe_splat_coverageTex, clamp(se, 0.0, 1.0)).r;
-    float value_ne = texture2D(oe_splat_coverageTex, clamp(ne, 0.0, 1.0)).r;
-    float value_nw = texture2D(oe_splat_coverageTex, clamp(nw, 0.0, 1.0)).r;
-
-    // Build the render info data for each corner:
-    oe_SplatRenderInfo ri_sw = oe_splat_getRenderInfo(value_sw, env);
-    oe_SplatRenderInfo ri_se = oe_splat_getRenderInfo(value_se, env);
-    oe_SplatRenderInfo ri_ne = oe_splat_getRenderInfo(value_ne, env);
-    oe_SplatRenderInfo ri_nw = oe_splat_getRenderInfo(value_nw, env);
-
-    // Primary splat:
-    vec3 sw_primary = oe_splat_getTexel(ri_sw.primaryIndex, splat_tc).rgb;
-    vec3 se_primary = oe_splat_getTexel(ri_se.primaryIndex, splat_tc).rgb;
-    vec3 ne_primary = oe_splat_getTexel(ri_ne.primaryIndex, splat_tc).rgb;
-    vec3 nw_primary = oe_splat_getTexel(ri_nw.primaryIndex, splat_tc).rgb;
-
-    // Detail splat - weighting is in the alpha channel
-    // TODO: Pointless to have a detail range? -gw
-    // TODO: If noise is a texture, just try to single-sample it instead
-    float detailToggle =env.range < oe_splat_detailRange ? 1.0 : 0.0;
-    vec4 sw_detail = detailToggle * oe_splat_getDetailTexel(ri_sw, splat_tc, env);
-    vec4 se_detail = detailToggle * oe_splat_getDetailTexel(ri_se, splat_tc, env);
-    vec4 ne_detail = detailToggle * oe_splat_getDetailTexel(ri_ne, splat_tc, env);
-    vec4 nw_detail = detailToggle * oe_splat_getDetailTexel(ri_nw, splat_tc, env);   
-
-    // Combine everything based on weighting:
-    texel.rgb =
-        sw_weight * mix(sw_primary, sw_detail.rgb, sw_detail.a) +
-        se_weight * mix(se_primary, se_detail.rgb, se_detail.a) +
-        ne_weight * mix(ne_primary, ne_detail.rgb, ne_detail.a) +
-        nw_weight * mix(nw_primary, nw_detail.rgb, nw_detail.a);
-
-    return texel;
-}
-
-#ifdef SPLAT_GPU_NOISE
-
-uniform float oe_splat_freq;
-uniform float oe_splat_pers;
-uniform float oe_splat_lac;
-uniform float oe_splat_octaves;
-
-// see: Splat.Noise.glsl
-float oe_noise_fractal4D(in vec2 seed, in float frequency, in float persistence, in float lacunarity, in int octaves);
-
-vec4 oe_splat_getNoise(in vec2 tc)
-{
-    return vec4(oe_noise_fractal4D(tc, oe_splat_freq, oe_splat_pers, oe_splat_lac, int(oe_splat_octaves)));
-}
-
-#else // !SPLAT_GPU_NOISE
-
-uniform sampler2D oe_splat_noiseTex;
-vec4 oe_splat_getNoise(in vec2 tc)
-{
-    return texture(oe_splat_noiseTex, tc.st);
-}
-
-#endif // SPLAT_GPU_NOISE
-
-// Simplified entry point with does no filtering or range blending. (much faster.)
-void oe_splat_simple(inout vec4 color)
-{
-    float noiseLOD = floor(oe_splat_noiseScale);
-    vec2 noiseCoords = oe_splat_getSplatCoords(oe_layer_tilec.st, noiseLOD);
-
-    oe_SplatEnv env;
-    env.range = oe_splat_range;
-    env.slope = oe_splat_getSlope();
-    env.noise = oe_splat_getNoise(noiseCoords);
-    env.elevation = 0.0;
-
-    color = oe_splat_bilinear(oe_layer_tilec.st, env);
-}
-
-// Main entry point for fragment shader.
-void oe_splat_complex(inout vec4 color)
-{
-    // Noise coords.
-    float noiseLOD = floor(oe_splat_noiseScale);
-    vec2 noiseCoords = oe_splat_getSplatCoords(oe_layer_tilec.st, noiseLOD); //TODO: move to VS for slight speedup
-
-    oe_SplatEnv env;
-    env.range = oe_splat_range;
-    env.slope = oe_splat_getSlope();
-    env.noise = oe_splat_getNoise(noiseCoords);
-    env.elevation = 0.0;
-
-    // quantize the scale offset so we take the hit in the FS
-    float scaleOffset = oe_splat_scaleOffset >= 0.0 ? ceil(oe_splat_scaleOffset) : floor(oe_splat_scaleOffset);
-        
-    // Calculate the 2 LODs we need to blend. We have to do this in the FS because 
-    // it's quite possible for a single triangle to span more than 2 LODs.
-    float lod0;
-    float lod1;
-    float lodBlend = -1.0;
-    oe_splat_getLodBlend(oe_splat_range, scaleOffset, lod0, lod1, lodBlend);
-
-    // Sample the two LODs:
-    vec2 tc0 = oe_splat_getSplatCoords(oe_layer_tilec.st, lod0);
-    vec4 texel0 = oe_splat_bilinear(tc0, env);
-    
-    vec2 tc1 = oe_splat_getSplatCoords(oe_layer_tilec.st, lod1);
-    vec4 texel1 = oe_splat_bilinear(tc1, env);
-    
-    // Blend:
-    vec4 texel = mix(texel0, texel1, lodBlend);
-
-    color = mix(color, texel, texel.a);
-
-    // uncomment to visualize slope.
-    //color.rgba = vec4(env.slope,0,0,1);
-}
diff --git a/src/osgEarthExtensions/splat/Splat.types.glsl b/src/osgEarthExtensions/splat/Splat.types.glsl
deleted file mode 100644
index 299a978..0000000
--- a/src/osgEarthExtensions/splat/Splat.types.glsl
+++ /dev/null
@@ -1,21 +0,0 @@
-// begin: Splat.types.glsl
-
-// Environment structure passed around locally.
-struct oe_SplatEnv {
-    float range;
-    float elevation;
-    float slope;
-    vec4 noise;
-};
-
-// Rendering parameters for splat texture and noise-based detail texture.
-struct oe_SplatRenderInfo {
-    float primaryIndex;
-    float detailIndex;
-    float brightness;
-    float contrast;
-    float threshold;
-    float minSlope;
-};
-
-// end: Splat.types.glsl
\ No newline at end of file
diff --git a/src/osgEarthExtensions/splat/Splat.util.glsl b/src/osgEarthExtensions/splat/Splat.util.glsl
deleted file mode 100644
index 4bd0d3a..0000000
--- a/src/osgEarthExtensions/splat/Splat.util.glsl
+++ /dev/null
@@ -1,64 +0,0 @@
-#version 120
-#pragma vp_location "fragment_coloring"
-
-uniform vec4 oe_tile_key;  // osgEarth TileKey
-
-
-// Mapping of view ranges to splat texture levels of detail.
-#define RANGE_COUNT 11
-const float oe_SplatRanges[RANGE_COUNT] = float[](  50.0, 125.0, 250.0, 500.0, 1000.0, 4000.0, 30000.0, 150000.0, 300000.0, 1000000.0, 5000000.0 );
-const float oe_SplatLevels[RANGE_COUNT] = float[](  20.0,  19.0,  18.0,  17.0,   16.0,   14.0,    12.0,     10.0,      8.0,       6.0,       4.0 );
-
-/**
- * Given a camera distance, return the two LODs it falls between and
- * the blend factor [0..1] between then.
- * in  range   = camera distace to fragment
- * in  baseLOD = LOD at which texture scale is 1.0
- * out LOD0    = near LOD
- * out LOD1    = far LOD
- * out blend   = Blend factor between LOD0 and LOD1 [0..1]
- */
-void
-oe_splat_getLodBlend(in float range, in float baseLOD, out float out_LOD0, out float out_LOD1, out float out_blend)
-{
-    float clampedRange = clamp(range, oe_SplatRanges[0], oe_SplatRanges[RANGE_COUNT-1]);
-
-    out_blend = -1.0;
-    for(int i=0; i<RANGE_COUNT-1 && out_blend < 0; ++i)
-    {
-        if ( clampedRange >= oe_SplatRanges[i] && clampedRange <= oe_SplatRanges[i+1] )
-        {
-            out_LOD0 = oe_SplatLevels[i]   + baseLOD;
-            out_LOD1 = oe_SplatLevels[i+1] + baseLOD;
-            out_blend = clamp((clampedRange-oe_SplatRanges[i])/(oe_SplatRanges[i+1]-oe_SplatRanges[i]), 0.0, 1.0);
-        }
-    }
-}
-
-/**
- * Scales the incoming tile splat coordinates to match the requested
- * LOD level. We offset the level from the current tile key's LOD (.z)
- * because otherwise you run into single-precision jitter at high LODs.
- */
-vec2 
-oe_splat_getSplatCoords(in vec2 tc, float lod)
-{
-    float dL = oe_tile_key.z - lod;
-    float factor = exp2(dL);
-    float invFactor = 1.0/factor;
-    vec2 scale = vec2(invFactor); 
-    vec2 result = tc * scale;
-
-    // For upsampling we need to calculate an offset as well
-    if ( factor >= 1.0 )
-    {
-        vec2 a = floor(oe_tile_key.xy * invFactor);
-        vec2 b = a * factor;
-        vec2 c = (a+1.0) * factor;
-        vec2 offset = (oe_tile_key.xy-b)/(c-b);
-        result += offset;
-    }
-
-    return result;
-}
-
diff --git a/src/osgEarthExtensions/splat/Splat.vert.model.glsl b/src/osgEarthExtensions/splat/Splat.vert.model.glsl
deleted file mode 100644
index 065f8ac..0000000
--- a/src/osgEarthExtensions/splat/Splat.vert.model.glsl
+++ /dev/null
@@ -1,14 +0,0 @@
-#version 330
-#pragma vp_entryPoint "oe_splat_vertex_model"
-#pragma vp_location   "vertex_model"
-#pragma vp_order      "0.5"
-
-out vec3 vp_Normal;
-out float oe_splat_slope;
-
-void oe_splat_vertex_model(inout vec4 VertexMODEL)
-{
-    // calculate slope from the Z component of the current normal
-    // since the terrain is in LTP space.
-    oe_splat_slope = 1.0-vp_Normal.z;
-}
diff --git a/src/osgEarthExtensions/splat/Splat.vert.view.glsl b/src/osgEarthExtensions/splat/Splat.vert.view.glsl
deleted file mode 100644
index db81a15..0000000
--- a/src/osgEarthExtensions/splat/Splat.vert.view.glsl
+++ /dev/null
@@ -1,24 +0,0 @@
-#version 330
-
-#pragma vp_entryPoint "oe_splat_vertex_view"
-#pragma vp_location   "vertex_view"
-#pragma vp_order      "0.5"
-
-#pragma include "Splat.types.glsl"
-
-out vec4 oe_layer_tilec;
-out float oe_splat_range;
-out vec2 oe_splat_covtc;
-
-uniform mat4 $COVERAGE_TEXMAT_UNIFORM;   // assigned at runtime
-
-
-void oe_splat_vertex_view(inout vec4 VertexVIEW)
-{
-    // range from camera to vertex
-    oe_splat_range = -VertexVIEW.z;
-
-    // calculate the coverage sampling coordinates. The texture matrix accounts
-    // for any super-sampling that might be in effect for the current LOD.
-    oe_splat_covtc = ($COVERAGE_TEXMAT_UNIFORM * oe_layer_tilec).st;
-}
diff --git a/src/osgEarthExtensions/splat/SplatCatalog b/src/osgEarthExtensions/splat/SplatCatalog
deleted file mode 100644
index 0b65677..0000000
--- a/src/osgEarthExtensions/splat/SplatCatalog
+++ /dev/null
@@ -1,178 +0,0 @@
-/* -*-c++-*- */
-/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
- * http://osgearth.org
- *
- * osgEarth is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>
- */
-#ifndef OSGEARTH_SPLAT_SPLAT_CATALOG
-#define OSGEARTH_SPLAT_SPLAT_CATALOG 1
-
-#include "SplatExport"
-#include <osg/Referenced>
-#include <osg/Texture2DArray>
-#include <osgEarth/Containers>
-#include <osgEarth/URI>
-
-namespace osgDB {
-    class Options;
-}
-
-namespace osgEarth { namespace Splat
-{
-    /**
-     * Defines the parameters for noise-generated detail splatting
-     * for a given class/range.
-     */
-    struct SplatDetailData
-    {
-        optional<URI>   _imageURI;
-        optional<float> _brightness;
-        optional<float> _contrast;
-        optional<float> _threshold;
-        optional<float> _slope;
-
-        // catalog will populate this value
-        int _textureIndex;
-
-        SplatDetailData();
-        SplatDetailData(const Config& conf);
-        Config getConfig() const;
-    };
-
-    /**
-     * Defines a single splatting appearance that will be used if its
-     * selector expression evaluates to true.
-     */
-    struct SplatRangeData
-    {
-        optional<float>           _minRange;
-        optional<URI>             _imageURI;
-        optional<URI>             _modelURI;
-        optional<int>             _modelCount;
-        optional<int>             _modelLevel;
-        optional<SplatDetailData> _detail;
-
-        // catalog will populate this value
-        int _textureIndex;
-
-        SplatRangeData();
-        SplatRangeData(const Config& conf);
-        Config getConfig() const;
-    };
-
-    typedef std::vector<SplatRangeData> SplatRangeDataVector;
-
-    /**
-     * A single splatting class. One class may have multiple
-     * data definitions, which are evaluated in order of appearance.
-     */
-    struct SplatClass
-    {
-        std::string          _name;
-        SplatRangeDataVector _ranges;
-
-        SplatClass();
-        SplatClass(const Config& conf);
-        Config getConfig() const;
-    };
-    
-    typedef osgEarth::fast_map<std::string, SplatClass> SplatClassMap;
-    
-    // Associates a selector expression that, if it evaluates to true, will
-    // select the specified splat texture
-    typedef std::pair<std::string /*expression*/, SplatRangeData> SplatSelector;
-
-    // Vector of selectors
-    typedef std::vector<SplatSelector> SplatSelectorVector;
-
-    // Maps splat class names to texture data renderers
-    typedef osgEarth::fast_map<std::string /*className*/, SplatSelectorVector> SplatLUT;
-
-    // Defines the splatting texture and associated lookup table.
-    struct SplatTextureDef
-    {
-        osg::ref_ptr<osg::Texture2DArray> _texture;
-        SplatLUT                          _splatLUT;
-        std::string                       _samplingFunction;
-    };
-    
-    typedef std::vector<SplatTextureDef> SplatTextureDefVector;
-
-    /**
-     * Catalog of texture-splatting classes. Usually these correspond
-     * to land use.
-     */
-    class SplatCatalog : public osg::Referenced
-    {
-    public:
-        /**
-         * Construct an empty catalog.
-         */
-        SplatCatalog();
-
-        /**
-         * The splatting classifications set.
-         */
-        const SplatClassMap& getClasses() const { return _classes; }
-
-        /**
-         * Whether the catalog is empty
-         */
-        bool empty() const { return _classes.empty(); }
-
-        /**
-         * Create a texture array from the images in the catalog, along
-         * with a definition of how to map classifications to texture
-         * array indices.
-         */        
-        bool createSplatTextureDef(const osgDB::Options* options,
-                                   SplatTextureDef&      out);
-
-    public: // properties
-
-        /** Name of this catalog */
-        optional<std::string>& name() { return _name; }
-        const optional<std::string>& name() const { return _name; }
-
-
-    public: // serialization
-
-        // populate this object from a Config
-        void fromConfig(const Config& conf);
-
-        // serialize this object to a Config.
-        Config getConfig() const;
-        
-
-    public: // static utility
-
-        /** Reads a splat catalog from a URI. */
-        static SplatCatalog* read(const URI& uri, const osgDB::Options* options);
-
-
-    protected:
-
-        virtual ~SplatCatalog() { }
-
-        optional<int>         _version;
-        optional<std::string> _name;
-        optional<std::string> _description;
-        SplatClassMap         _classes;
-        SplatTextureDef       _textureDef;
-    };
-
-} } // namespace osgEarth::Splat
-
-#endif // OSGEARTH_SPLAT_SPLAT_CATALOG
diff --git a/src/osgEarthExtensions/splat/SplatCatalog.cpp b/src/osgEarthExtensions/splat/SplatCatalog.cpp
deleted file mode 100644
index 55b82ec..0000000
--- a/src/osgEarthExtensions/splat/SplatCatalog.cpp
+++ /dev/null
@@ -1,389 +0,0 @@
-/* -*-c++-*- */
-/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
- * http://osgearth.org
- *
- * osgEarth is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>
- */
-#include "SplatCatalog"
-#include <osgEarth/Config>
-#include <osgEarth/ImageUtils>
-#include <osgEarth/XmlUtils>
-#include <osg/Texture2DArray>
-
-using namespace osgEarth;
-using namespace osgEarth::Splat;
-
-#define LC "[SplatCatalog] "
-
-#define SPLAT_CATALOG_CURRENT_VERSION 1
-
-
-//............................................................................
-
-SplatDetailData::SplatDetailData() :
-_textureIndex( -1 )
-{
-    //nop
-}
-
-SplatDetailData::SplatDetailData(const Config& conf) :
-_textureIndex( -1 )
-{
-    conf.getIfSet("image",      _imageURI);
-    conf.getIfSet("brightness", _brightness);
-    conf.getIfSet("contrast",   _contrast);
-    conf.getIfSet("threshold",  _threshold);
-    conf.getIfSet("slope",      _slope);
-}
-
-Config
-SplatDetailData::getConfig() const
-{
-    Config conf;
-    conf.addIfSet("image",      _imageURI);
-    conf.addIfSet("brightness", _brightness);
-    conf.addIfSet("contrast",   _contrast);
-    conf.addIfSet("threshold",  _threshold);
-    conf.addIfSet("slope",      _slope);
-    return conf;
-}
-
-//............................................................................
-
-SplatRangeData::SplatRangeData() :
-_textureIndex( -1 )
-{
-    //nop
-}
-
-SplatRangeData::SplatRangeData(const Config& conf) :
-_textureIndex( -1 )
-{
-    conf.getIfSet("image",      _imageURI);
-    conf.getIfSet("model",      _modelURI);
-    conf.getIfSet("modelCount", _modelCount);
-    conf.getIfSet("modelLevel", _modelLevel);
-
-    if ( conf.hasChild("detail") )
-        _detail = SplatDetailData(conf.child("detail"));
-}
-
-Config
-SplatRangeData::getConfig() const
-{
-    Config conf;
-    conf.addIfSet("image",      _imageURI);
-    conf.addIfSet("model",      _modelURI);
-    conf.addIfSet("modelCount", _modelCount);
-    conf.addIfSet("modelLevel", _modelLevel);
-    if ( _detail.isSet() )
-        conf.add( "detail", _detail->getConfig() );
-
-    return conf;
-}
-
-//............................................................................
-
-SplatClass::SplatClass()
-{
-    //nop
-}
-
-SplatClass::SplatClass(const Config& conf)
-{
-    _name = conf.value("name");
-
-    if ( conf.hasChild("range") )
-    {
-        // read the data definitions in order:
-        for(ConfigSet::const_iterator i = conf.children().begin(); i != conf.children().end(); ++i)
-        {
-            if ( !i->empty() )
-            {
-                _ranges.push_back(SplatRangeData(*i));
-            }
-        }
-    }
-    else
-    {
-        // just one.
-        _ranges.push_back( SplatRangeData(conf) );
-    }
-}
-
-Config
-SplatClass::getConfig() const
-{
-    Config conf( _name );
-    for(SplatRangeDataVector::const_iterator i = _ranges.begin(); i != _ranges.end(); ++i)
-    {
-        conf.add( "range", i->getConfig() );
-    }
-    return conf;
-}
-
-//............................................................................
-
-SplatCatalog::SplatCatalog()
-{
-    _version = SPLAT_CATALOG_CURRENT_VERSION;
-}
-
-void
-SplatCatalog::fromConfig(const Config& conf)
-{
-    conf.getIfSet("version",     _version);
-    conf.getIfSet("name",        _name);
-    conf.getIfSet("description", _description);
-
-    Config classesConf = conf.child("classes");
-    if ( !classesConf.empty() )
-    {
-        for(ConfigSet::const_iterator i = classesConf.children().begin(); i != classesConf.children().end(); ++i)
-        {
-            SplatClass sclass(*i);
-            if ( !sclass._name.empty() )
-            {
-                _classes[sclass._name] = sclass;
-            }
-        }
-    }
-}
-
-Config
-SplatCatalog::getConfig() const
-{
-    Config conf;
-    conf.addIfSet("version",     _version);
-    conf.addIfSet("name",        _name);
-    conf.addIfSet("description", _description);
-    
-    Config classes("classes");
-    {
-        for(SplatClassMap::const_iterator i = _classes.begin(); i != _classes.end(); ++i)
-        {
-            classes.add( "class", i->second.getConfig() );
-        }
-    }    
-    conf.add( classes );
-
-    return conf;
-}
-
-namespace
-{
-    osg::Image* loadImage(const URI& uri, const osgDB::Options* dbOptions, osg::Image* firstImage)
-    {
-        // try to load the image:
-        ReadResult result = uri.readImage(dbOptions);
-        if ( result.succeeded() )
-        {
-            // if this is the first image loaded, remember it so we can ensure that
-            // all images are copatible.
-            if ( firstImage == 0L )
-            {
-                firstImage = result.getImage();
-            }
-            else
-            {
-                // ensure compatibility, a requirement for texture arrays.
-                // In the future perhaps we can resize/convert instead.
-                if ( !ImageUtils::textureArrayCompatible(result.getImage(), firstImage) )
-                {
-                    OE_WARN << LC << "Image " << uri.base()
-                        << " was found, but cannot be used because it is not compatible with "
-                        << "other splat images (same dimensions, pixel format, etc.)\n";
-
-                    return 0L;
-                }
-            }
-        }
-        else
-        {
-            OE_WARN << LC
-                << "Image in the splat catalog failed to load: "
-                << uri.full() << "; message = " << result.getResultCodeString()
-                << std::endl;
-        }
-
-        return result.releaseImage();
-    }
-}
-
-bool
-SplatCatalog::createSplatTextureDef(const osgDB::Options* dbOptions,
-                                    SplatTextureDef&      out)
-{
-    // Reset all texture indices to default
-    for(SplatClassMap::iterator i = _classes.begin(); i != _classes.end(); ++i)
-    {
-        SplatClass& c = i->second;
-        for(SplatRangeDataVector::iterator range = c._ranges.begin(); range != c._ranges.end(); ++range)
-        {
-            range->_textureIndex = -1;
-            if ( range->_detail.isSet() )
-            {
-                range->_detail->_textureIndex = -1;
-            }
-        }
-    }
-
-    typedef osgEarth::fast_map<URI, int> ImageIndexTable; // track images to prevent dupes
-    ImageIndexTable imageIndices;
-    std::vector< osg::ref_ptr<osg::Image> > imagesInOrder;
-    int index = 0;
-    osg::Image* firstImage  = 0L;
-
-    // Load all referenced images in the catalog, and assign each a unique index.
-    for(SplatClassMap::iterator i = _classes.begin(); i != _classes.end(); ++i)
-    {
-        SplatClass& c = i->second;
-
-        for(SplatRangeDataVector::iterator range = c._ranges.begin(); range != c._ranges.end(); ++range)
-        {
-            // Load the main image and assign it an index:
-            if (range->_imageURI.isSet())
-            {
-                int texIndex = -1;
-                ImageIndexTable::iterator k = imageIndices.find(range->_imageURI.get());
-                if ( k == imageIndices.end() )
-                {
-                    osg::ref_ptr<osg::Image> image = loadImage( range->_imageURI.get(), dbOptions, firstImage );
-                    if ( image.valid() )
-                    {
-                        if ( !firstImage )
-                            firstImage = image.get();
-
-                        imageIndices[range->_imageURI.get()] = texIndex = index++;
-                        imagesInOrder.push_back( image.get() );
-                    }
-                }
-                else
-                {
-                    texIndex = k->second;
-                }
-                range->_textureIndex = texIndex;
-            }
-
-            // Load the detail texture if it exists:
-            if (range->_detail.isSet() &&
-                range->_detail->_imageURI.isSet())
-            {
-                int texIndex = -1;
-                ImageIndexTable::iterator k = imageIndices.find(range->_detail->_imageURI.get());
-                if ( k == imageIndices.end() )
-                {
-                    osg::ref_ptr<osg::Image> image = loadImage( range->_detail->_imageURI.get(), dbOptions, firstImage );
-                    if ( image.valid() )
-                    {
-                        if ( !firstImage )
-                            firstImage = image.get();
-            
-                        imageIndices[range->_detail->_imageURI.get()] = texIndex = index++;
-                        imagesInOrder.push_back( image.get() );
-                    }
-                }
-                else
-                {
-                    texIndex = k->second;
-                }
-                range->_detail->_textureIndex = texIndex;
-            }
-        }
-    }
-
-    // Next, go through the classes and build the splat lookup table.
-    for(SplatClassMap::const_iterator i = _classes.begin(); i != _classes.end(); ++i)
-    {
-        const SplatClass& c = i->second;
-
-        // selectors for this class (ordered):
-        SplatSelectorVector selectors;
-
-        // check each data element:
-        for(SplatRangeDataVector::const_iterator range = c._ranges.begin(); range != c._ranges.end(); ++range)
-        {
-            // If the primary image exists, look up its index and add it to the selector set.
-            ImageIndexTable::const_iterator k = imageIndices.find( range->_imageURI.get() );
-            if ( k != imageIndices.end() )
-            {
-                std::string expression;
-                if ( range->_minRange.isSet() )
-                {
-                    expression = Stringify()
-                        << "env.range >= float(" << range->_minRange.get() << ")";
-                }
-
-                // insert into the lookup table.
-                out._splatLUT[c._name].push_back( SplatSelector(expression, *range) );
-            }
-        }
-    }
-
-    // Create the texture array.
-    if ( imagesInOrder.size() > 0 )
-    {
-        out._texture = new osg::Texture2DArray();
-        out._texture->setTextureSize( firstImage->s(), firstImage->t(), imagesInOrder.size() );
-        out._texture->setWrap( osg::Texture::WRAP_S, osg::Texture::REPEAT );
-        out._texture->setWrap( osg::Texture::WRAP_T, osg::Texture::REPEAT );
-        out._texture->setFilter( osg::Texture::MIN_FILTER, osg::Texture::LINEAR_MIPMAP_LINEAR );
-        out._texture->setFilter( osg::Texture::MAG_FILTER, osg::Texture::LINEAR );
-        out._texture->setResizeNonPowerOfTwoHint( false );
-        out._texture->setMaxAnisotropy( 4.0f );
-
-        for(unsigned i=0; i<imagesInOrder.size(); ++i)
-        {
-            out._texture->setImage( i, imagesInOrder[i].get() );
-        }
-
-        OE_INFO << LC << "Catalog \"" << this->name().get()
-            << "\" texture size = "<< imagesInOrder.size()
-            << std::endl;
-    }
-
-    return out._texture.valid();
-}
-
-SplatCatalog*
-SplatCatalog::read(const URI&            uri,
-                   const osgDB::Options* options)
-{
-    osg::ref_ptr<SplatCatalog> catalog;
-
-    osg::ref_ptr<XmlDocument> doc = XmlDocument::load( uri, options );
-    if ( doc.valid() )
-    {
-        catalog = new SplatCatalog();
-        catalog->fromConfig( doc->getConfig().child("catalog") );
-        if ( catalog->empty() )
-        {
-            OE_WARN << LC << "Catalog is empty! (" << uri.full() << ")\n";
-            catalog = 0L;
-        }
-        else
-        {
-            OE_INFO << LC << "Catalog \"" << catalog->name().get() << "\""
-                << " contains " << catalog->getClasses().size()
-                << " classes.\n";
-        }
-    }
-    else
-    {
-        OE_WARN << LC << "Failed to read catalog from " << uri.full() << "\n";
-    }
-
-    return catalog.release();
-}
\ No newline at end of file
diff --git a/src/osgEarthExtensions/splat/SplatCoverageLegend b/src/osgEarthExtensions/splat/SplatCoverageLegend
deleted file mode 100644
index 1f5f0ab..0000000
--- a/src/osgEarthExtensions/splat/SplatCoverageLegend
+++ /dev/null
@@ -1,108 +0,0 @@
-/* -*-c++-*- */
-/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
- * http://osgearth.org
- *
- * osgEarth is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>
- */
-#ifndef OSGEARTH_SPLAT_COVERAGE_LEGEND
-#define OSGEARTH_SPLAT_COVERAGE_LEGEND 1
-
-#include "SplatExport"
-#include <osgEarth/Config>
-#include <osg/Referenced>
-#include <string>
-
-namespace osgEarth { namespace Splat
-{
-    /**
-     * Associates a specific source data coverage value to the name
-     * of a splat class.
-     */
-    template<typename T>
-    class CoverageValuePredicateT : public osg::Referenced
-    {
-    public:
-        optional<T> _exactValue;
-        optional<T> _minValue;
-        optional<T> _maxValue;
-
-        optional<std::string> _description;
-        optional<std::string> _mappedClassName;
-
-        bool match(const T& testValue) const
-        {
-            if ( _exactValue.isSetTo(testValue) )
-                return true;
-            if ( !_minValue.isSet() && !_maxValue.isSet() )
-                return false;
-            if ( _minValue.isSet() && _minValue.get() > testValue )
-                return false;
-            if ( _maxValue.isSet() && _maxValue.get() < testValue )
-                return false;
-
-            return true;
-        }
-    };
-
-    typedef CoverageValuePredicateT<std::string> CoverageValuePredicate;
-
-    /**
-     * Collection of coverage value predicates.
-     */
-
-    /**
-     * Legend that maps coverage values (or value predicates) to splat
-     * catalog classes.
-     */
-    class SplatCoverageLegend : public osg::Referenced
-    {
-    public:
-        SplatCoverageLegend();
-
-    public:
-        typedef std::vector< osg::ref_ptr<CoverageValuePredicate> > Predicates;
-
-        /**
-         * The collection of value->class mapping predicates
-         */
-        const Predicates& getPredicates() const { return _predicates; }
-
-        /**
-         * Whether this legend is empty.
-         */
-        bool empty() const { return _predicates.empty(); }
-
-    public: // serialization
-
-        // populate this object from a Config
-        void fromConfig(const Config& conf);
-
-        // serialize this object to a Config.
-        Config getConfig() const;
-
-
-    protected:
-
-        virtual ~SplatCoverageLegend() { }
-
-        optional<std::string> _name;
-        optional<std::string> _source;
-
-        Predicates _predicates;
-    };
-
-} } // namespace osgEarth::Splat
-
-#endif // OSGEARTH_SPLAT_COVERAGE_LEGEND
diff --git a/src/osgEarthExtensions/splat/SplatCoverageLegend.cpp b/src/osgEarthExtensions/splat/SplatCoverageLegend.cpp
deleted file mode 100644
index bb0bda1..0000000
--- a/src/osgEarthExtensions/splat/SplatCoverageLegend.cpp
+++ /dev/null
@@ -1,78 +0,0 @@
-/* -*-c++-*- */
-/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
- * http://osgearth.org
- *
- * osgEarth is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>
- */
-#include "SplatCoverageLegend"
-#include <osgEarth/Config>
-
-using namespace osgEarth;
-using namespace osgEarth::Splat;
-
-#define LC "[SplatCoverageLegend] "
-
-//............................................................................
-
-SplatCoverageLegend::SplatCoverageLegend()
-{
-    //nop
-}
-
-void
-SplatCoverageLegend::fromConfig(const Config& conf)
-{
-    conf.getIfSet("name",   _name);
-    conf.getIfSet("source", _source);
-
-    ConfigSet predicatesConf = conf.child("mappings").children();
-    for(ConfigSet::const_iterator i = predicatesConf.begin(); i != predicatesConf.end(); ++i)
-    {
-        osg::ref_ptr<CoverageValuePredicate> p = new CoverageValuePredicate();
-
-        i->getIfSet( "name",  p->_description );
-        i->getIfSet( "value", p->_exactValue );
-        i->getIfSet( "class", p->_mappedClassName );
-        
-        if ( p->_mappedClassName.isSet() )
-        {
-            _predicates.push_back( p.get() );
-        }
-    }
-}
-
-Config
-SplatCoverageLegend::getConfig() const
-{
-    Config conf;
-    
-    conf.addIfSet("name",   _name);
-    conf.addIfSet("source", _source);
-
-    Config preds;
-    for(Predicates::const_iterator i = _predicates.begin(); i != _predicates.end(); ++i)
-    {
-        CoverageValuePredicate* p = i->get();
-        Config pred;
-        pred.addIfSet( "name",  p->_description );
-        pred.addIfSet( "value", p->_exactValue );
-        pred.addIfSet( "class", p->_mappedClassName );
-        preds.add( "mapping", pred );
-    }
-    conf.add( "mappings", preds );
-
-    return conf;
-}
-
diff --git a/src/osgEarthExtensions/splat/SplatExport b/src/osgEarthExtensions/splat/SplatExport
deleted file mode 100644
index 1001fa0..0000000
--- a/src/osgEarthExtensions/splat/SplatExport
+++ /dev/null
@@ -1,63 +0,0 @@
-/* -*-c++-*- */
-/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
- * http://osgearth.org
- *
- * osgEarth is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>
- */
-
-/* -*-c++-*- 
- * Derived from osg/Export
- */
-
-#ifndef OSGEARTH_SPLAT_EXPORT_H
-#define OSGEARTH_SPLAT_EXPORT_H 1
-
-// define USE_DEPRECATED_API is used to include in API which is being phased out
-// if you can compile your apps with this turned off you are
-// well placed for compatibility with future versions.
-#define USE_DEPRECATED_API
-
-#if defined(_MSC_VER)
-    #pragma warning( disable : 4244 )
-    #pragma warning( disable : 4251 )
-    #pragma warning( disable : 4267 )
-    #pragma warning( disable : 4275 )
-    #pragma warning( disable : 4290 )
-    #pragma warning( disable : 4786 )
-    #pragma warning( disable : 4305 )
-    #pragma warning( disable : 4996 )
-#endif
-
-#if defined(_MSC_VER) || defined(__CYGWIN__) || defined(__MINGW32__) || defined( __BCPLUSPLUS__)  || defined( __MWERKS__)
-    #  if defined( OSGEARTH_SPLAT_LIBRARY_STATIC )
-    #    define OSGEARTH_SPLAT_EXPORT
-    #  elif defined( OSGEARTH_SPLAT_LIBRARY )
-    #    define OSGEARTH_SPLAT_EXPORT   __declspec(dllexport)
-    #  else
-    #    define OSGEARTH_SPLAT_EXPORT   __declspec(dllimport)
-    #  endif
-#else
-    #  define OSGEARTH_SPLAT_EXPORT
-#endif  
-
-// set up define for whether member templates are supported by VisualStudio compilers.
-#ifdef _MSC_VER
-# if (_MSC_VER >= 1300)
-#  define __STL_MEMBER_TEMPLATES
-# endif
-#endif
-
-#endif
-
diff --git a/src/osgEarthExtensions/splat/SplatExtension b/src/osgEarthExtensions/splat/SplatExtension
deleted file mode 100644
index 868505a..0000000
--- a/src/osgEarthExtensions/splat/SplatExtension
+++ /dev/null
@@ -1,83 +0,0 @@
-/* -*-c++-*- */
-/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
- * http://osgearth.org
- *
- * osgEarth is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>
- */
-#ifndef OSGEARTH_SPLAT_SPLAT_EXTENSION
-#define OSGEARTH_SPLAT_SPLAT_EXTENSION 1
-
-#include "SplatExport"
-#include "SplatOptions"
-#include "SplatTerrainEffect"
-#include <osgEarth/Extension>
-#include <osgEarth/MapNode>
-#include <osgEarthUtil/Controls>
-
-namespace osgEarth { namespace Splat
-{
-    using namespace osgEarth;
-    using namespace osgEarth::Util::Controls;
-
-    /**
-     * Extension for loading the splatting effect on demand.
-     */
-    class SplatExtension : public Extension,
-                           public ExtensionInterface<MapNode>,
-                           public ExtensionInterface<Control>
-    {
-    public:
-        META_Object(osgearth_ext_splat, SplatExtension);
-
-        // CTORs
-        SplatExtension();
-        SplatExtension(const SplatOptions& options);
-
-        // DTOR
-        virtual ~SplatExtension();
-
-
-    public: // Extension
-
-        void setDBOptions(const osgDB::Options* dbOptions);
-
-
-    public: // ExtensionInterface<MapNode>
-
-        bool connect(MapNode* mapNode);
-
-        bool disconnect(MapNode* mapNode);
-
-
-    public: // ExtensionInterface<Control>
-
-        bool connect(Control* control);
-
-        bool disconnect(Control* control);
-
-
-    protected: // Object
-        SplatExtension(const SplatExtension& rhs, const osg::CopyOp& op) { }
-
-    private:
-        const SplatOptions                 _options;
-        osg::ref_ptr<const osgDB::Options> _dbOptions;
-        osg::ref_ptr<SplatTerrainEffect>   _effect;
-        osg::ref_ptr<ImageLayer>           _coverageLayer;
-    };
-
-} } // namespace osgEarth::Splat
-
-#endif // OSGEARTH_SPLAT_SPLAT_EXTENSION
diff --git a/src/osgEarthExtensions/splat/SplatExtension.cpp b/src/osgEarthExtensions/splat/SplatExtension.cpp
deleted file mode 100644
index 591ee4f..0000000
--- a/src/osgEarthExtensions/splat/SplatExtension.cpp
+++ /dev/null
@@ -1,239 +0,0 @@
-/* -*-c++-*- */
-/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
- * http://osgearth.org
- *
- * osgEarth is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>
- */
-#include "SplatExtension"
-#include "SplatCatalog"
-#include "Biome"
-#include "SplatCoverageLegend"
-#include "SplatTerrainEffect"
-
-#include <osgEarth/MapNode>
-#include <osgEarth/TerrainEngineNode>
-#include <osgEarth/XmlUtils>
-
-using namespace osgEarth;
-using namespace osgEarth::Splat;
-
-#define LC "[SplatExtension] "
-
-//.........................................................................
-
-namespace
-{
-}
-
-//.........................................................................
-
-SplatExtension::SplatExtension()
-{
-    //nop
-}
-
-SplatExtension::SplatExtension(const SplatOptions& options) :
-_options( options )
-{
-    //nop
-}
-
-SplatExtension::~SplatExtension()
-{
-    //nop
-}
-
-void
-SplatExtension::setDBOptions(const osgDB::Options* dbOptions)
-{
-    _dbOptions = dbOptions;
-}
-
-bool
-SplatExtension::connect(MapNode* mapNode)
-{
-    if ( !mapNode )
-    {
-        OE_WARN << LC << "Illegal: MapNode cannot be null." << std::endl;
-        return false;
-    }
-
-    OE_INFO << LC << "Connecting to MapNode.\n";
-
-    if ( !_options.catalogURI().isSet() && !_options.biomesURI().isSet() )
-    {
-        OE_WARN << LC << "Illegal: either a catalog URI or a biomes URI is required.\n";
-        return false;
-    }
-
-    if ( !_options.legendURI().isSet() )
-    {
-        OE_WARN << LC << "Illegal: a legend URI is required.\n";
-        return false;
-    }
-
-    if ( !_options.coverageLayerName().isSet() )
-    {
-        OE_WARN << LC << "Illegal: a coverage layer name is required.\n";
-        return false;
-    }
-
-    // Locate the coverage layer in the map.
-    const Map* map = mapNode->getMap();
-    const ImageLayer* coverageLayer = map->getImageLayerByName( _options.coverageLayerName().get() );
-    if ( !coverageLayer )
-    {
-        OE_WARN << LC << "Coverage layer \""
-            << _options.coverageLayerName().get()
-            << "\" not found in map.\n";
-        return false;
-    }
-
-    // Read in the legend.
-    osg::ref_ptr<SplatCoverageLegend> legend = new SplatCoverageLegend();
-    {
-        osg::ref_ptr<XmlDocument> doc = XmlDocument::load(
-            _options.legendURI().get(),
-            _dbOptions.get() );
-
-        if ( doc.valid() )
-        {
-            legend->fromConfig( doc->getConfig().child("legend") );
-        }
-
-        if ( legend->empty() )
-        {
-            OE_WARN << LC
-                << "Failed to read required legend from \""
-                << _options.legendURI()->full() << "\"\n";
-            return false;
-        }
-        else
-        {
-            OE_INFO << LC << "Legend: found " << legend->getPredicates().size() << " mappings \n";
-        }
-    }
-
-    BiomeVector biomes;
-
-    // If there is a biome file, read it; it will point to one or more catalog files.
-    if ( _options.biomesURI().isSet() )
-    {
-        osg::ref_ptr<XmlDocument> doc = XmlDocument::load(
-            _options.biomesURI().get(),
-            _dbOptions.get() );
-
-        if ( doc.valid() )
-        {
-            Config conf = doc->getConfig().child("biomes");
-            if ( !conf.empty() )
-            {
-                for(ConfigSet::const_iterator i = conf.children().begin();
-                    i != conf.children().end();
-                    ++i)
-                {
-                    Biome biome( *i );
-                    if ( biome.catalogURI().isSet() )
-                    {
-                        SplatCatalog* catalog = SplatCatalog::read( biome.catalogURI().get(), _dbOptions.get() );
-                        if ( catalog )
-                        {
-                            biome.setCatalog( catalog );
-                            biomes.push_back( biome );
-                        }
-                    }
-                }
-            }
-        }
-    }
-
-    // Otherwise, no biome file, so read a single catalog directly:
-    if ( biomes.empty() )
-    {
-        // Read in the catalog.
-        SplatCatalog* catalog = SplatCatalog::read(
-            _options.catalogURI().get(),
-            _dbOptions.get() );
-
-        if ( catalog )
-        {
-            biomes.push_back( Biome() );
-            biomes.back().setCatalog( catalog );
-        }
-    }
-
-    if ( !biomes.empty() )
-    {
-        // Terrain effect that implements splatting.
-        _effect = new SplatTerrainEffect( biomes, legend, _dbOptions.get() );
-
-        // set the coverage layer (mandatory)
-        _effect->setCoverageLayer( coverageLayer );
-
-        // set the render order (optional)
-        if ( _options.drawAfterImageLayers() == true )
-            _effect->setRenderOrder( 1.0f );
-
-        // set the various rendering options.
-        if ( _options.coverageWarp().isSet() )
-            _effect->getCoverageWarpUniform()->set( _options.coverageWarp().get() );
-    
-        if ( _options.coverageBlur().isSet() )
-            _effect->getCoverageBlurUniform()->set( _options.coverageBlur().get() );
-
-        if ( _options.scaleLevelOffset().isSet() )
-            _effect->getScaleLevelOffsetUniform()->set( (float)_options.scaleLevelOffset().get() );
-
-        // add it to the terrain.
-        mapNode->getTerrainEngine()->addEffect( _effect.get() );
-    }
-
-    else
-    {
-        OE_WARN << LC << "Extension not installed become there are no valid biomes.\n";
-    }
-
-    return true;
-}
-
-bool
-SplatExtension::disconnect(MapNode* mapNode)
-{
-    if ( mapNode && _effect.valid() )
-    {
-        mapNode->getTerrainEngine()->removeEffect( _effect.get() );
-    }
-    _effect = 0L;
-    return true;
-}
-
-bool
-SplatExtension::connect(Control* control)
-{
-    //TODO add a UI.
-    Container* container = dynamic_cast<Container*>(control);
-    if ( container )
-    {
-        container->addControl( new LabelControl("Splatting is on!") );
-    }
-    return true;
-}
-
-bool
-SplatExtension::disconnect(Control* control)
-{
-    // NOP
-    return true;
-}
diff --git a/src/osgEarthExtensions/splat/SplatOptions b/src/osgEarthExtensions/splat/SplatOptions
deleted file mode 100644
index 52c717a..0000000
--- a/src/osgEarthExtensions/splat/SplatOptions
+++ /dev/null
@@ -1,151 +0,0 @@
-/* -*-c++-*- */
-/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
- * http://osgearth.org
- *
- * osgEarth is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>
- */
-#ifndef OSGEARTH_DRIVER_SPLAT_OPTIONS
-#define OSGEARTH_DRIVER_SPLAT_OPTIONS 1
-
-#include <osgEarth/Common>
-#include <osgEarth/URI>
-
-namespace osgEarth { namespace Splat
-{
-    using namespace osgEarth;
-
-    /**
-     * Options governing the classification splatting engine.
-     */
-    class /*header-only*/ SplatOptions : public DriverConfigOptions
-    {
-    public:
-        /** URI of the splat texture catalog description file;
-            If you set a biomesURI, this will be ignored. */
-        optional<URI>& catalogURI() { return _catalogURI; }
-        const optional<URI>& catalogURI() const { return _catalogURI; }
-
-        /** URI of a biomes definition file.
-            Required is you do not specify a catalogURI. */
-        optional<URI>& biomesURI() { return _biomesURI; }
-        const optional<URI>& biomesURI() const { return _biomesURI; }
-        
-        /** URI of the legend that describes the values in the coverage layer
-            and maps them to the catalog. Required. */
-        optional<URI>& legendURI() { return _legendURI; }
-        const optional<URI>& legendURI() const { return _legendURI; }
-
-        /** Name of the coverage layer. The layer should be installed in the Map and
-            should be marked as shared. */
-        optional<std::string>& coverageLayerName() { return _coverageLayerName; }
-        const optional<std::string>& coverageLayerName() const { return _coverageLayerName; }
-
-        /** Whether to splat the terrain after drawing the map's image layers. The default
-            setting is to splat first and then draw imagery. */
-        optional<bool>& drawAfterImageLayers() { return _drawAfterImageLayers; }
-        const optional<bool>& drawAfterImageLayers() const { return _drawAfterImageLayers; }
-
-        /** Warping factor for coverage sampling. Please refer to
-            SplatTerrainEffect::getCoverageWarpUniform() for details. */
-        optional<float>& coverageWarp() { return _coverageWarp; }
-        const optional<float>& coverageWarp() const { return _coverageWarp; }
-
-        /** Blurring factor for coverage sampling. Please refer to
-            SplatTerrainEffect::getCoverageBlurUniform() for details. */
-        optional<float>& coverageBlur() { return _coverageBlur; }
-        const optional<float>& coverageBlur() const { return _coverageBlur; }
-
-        /** Level-of-detail offset for scaling the splat textures. */
-        optional<int>& scaleLevelOffset() { return _scaleLevelOffset; }
-        const optional<int>& scaleLevelOffset() const { return _scaleLevelOffset; }
-
-        /** Whether to use bilinear sampling to smooth the coverage data.
-            Default is true; set to false for higher performance. */
-        optional<bool>& bilinearSampling() { return _bilinearSampling; }
-        const optional<bool>& bilinearSampling() const { return _bilinearSampling; }
-
-        /** Maximum distance from the camera at which to render detail splats. */
-        optional<float>& detailMaxRange() { return _detailMaxRange; }
-        const optional<float>& detailMaxRange() const { return _detailMaxRange; }
-
-    public:
-        SplatOptions( const ConfigOptions& opt =ConfigOptions() ) : DriverConfigOptions( opt )
-        {
-            setDriver( "splat" );
-
-            // Set default values:
-            _coverageWarp.init(0.01f);
-            _coverageBlur.init(1.0f);
-            _scaleLevelOffset.init(0);
-            _drawAfterImageLayers.init(false);
-            _bilinearSampling.init(true);
-            _detailMaxRange.init(1000000.0f);
-
-            fromConfig( _conf );
-        }
-
-        virtual ~SplatOptions() { }
-
-    public:
-        Config getConfig() const {
-            Config conf = DriverConfigOptions::getConfig();
-            conf.updateIfSet("catalog",  _catalogURI);
-            conf.updateIfSet("biomes",   _biomesURI);
-            conf.updateIfSet("legend",   _legendURI);
-            conf.updateIfSet("coverage", _coverageLayerName );
-            conf.updateIfSet("draw_after_image_layers", _drawAfterImageLayers);
-            conf.updateIfSet("coverage_warp", _coverageWarp );
-            conf.updateIfSet("coverage_blur", _coverageBlur );
-            conf.updateIfSet("scale_level_offset", _scaleLevelOffset );
-            conf.updateIfSet("bilinear_sampling", _bilinearSampling);
-            conf.updateIfSet("detail_max_range", _detailMaxRange);
-            return conf;
-        }
-
-    protected:
-        void mergeConfig( const Config& conf ) {
-            DriverConfigOptions::mergeConfig( conf );
-            fromConfig( conf );
-        }
-
-    private:
-        void fromConfig( const Config& conf ) {
-            conf.getIfSet("catalog",  _catalogURI);
-            conf.getIfSet("biomes",   _biomesURI);
-            conf.getIfSet("legend",   _legendURI);
-            conf.getIfSet("coverage", _coverageLayerName );
-            conf.getIfSet("draw_after_image_layers", _drawAfterImageLayers);
-            conf.getIfSet("coverage_warp", _coverageWarp );
-            conf.getIfSet("coverage_blur", _coverageBlur );
-            conf.getIfSet("scale_level_offset", _scaleLevelOffset );
-            conf.getIfSet("bilinear_sampling", _bilinearSampling);
-            conf.getIfSet("detail_max_range", _detailMaxRange);
-        }
-
-        optional<URI>         _catalogURI;
-        optional<URI>         _biomesURI;
-        optional<URI>         _legendURI;
-        optional<std::string> _coverageLayerName;
-        optional<bool>        _drawAfterImageLayers;
-        optional<float>       _coverageWarp;
-        optional<float>       _coverageBlur;
-        optional<int>         _scaleLevelOffset;
-        optional<bool>        _bilinearSampling;
-        optional<float>       _detailMaxRange;
-    };
-
-} } // namespace osgEarth::Splat
-
-#endif // OSGEARTH_DRIVER_SPLAT_OPTIONS
diff --git a/src/osgEarthExtensions/splat/SplatPlugin.cpp b/src/osgEarthExtensions/splat/SplatPlugin.cpp
deleted file mode 100644
index cc7d888..0000000
--- a/src/osgEarthExtensions/splat/SplatPlugin.cpp
+++ /dev/null
@@ -1,56 +0,0 @@
-/* -*-c++-*- */
-/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
- * http://osgearth.org
- *
- * osgEarth is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>
- */
-#include "SplatOptions"
-#include "SplatExtension"
-
-#include <osgDB/ReaderWriter>
-#include <osgDB/Registry>
-#include <osgDB/FileNameUtils>
-
-namespace osgEarth { namespace Splat
-{
-    /**
-     * Plugin entry point
-     */
-    class SplatPlugin : public osgDB::ReaderWriter
-    {
-    public: // Plugin stuff
-
-        SplatPlugin() {
-            supportsExtension( "osgearth_splat", "osgEarth Splat Extension Plugin" );
-        }
-        
-        const char* className() {
-            return "osgEarth Splat Extension Plugin";
-        }
-
-        virtual ~SplatPlugin() { }
-
-        ReadResult readObject(const std::string& filename, const osgDB::Options* dbOptions) const
-        {
-          if ( !acceptsExtension(osgDB::getLowerCaseFileExtension(filename)) )
-                return ReadResult::FILE_NOT_HANDLED;
-
-          return ReadResult( new SplatExtension(Extension::getConfigOptions(dbOptions)) );
-        }
-    };
-
-    REGISTER_OSGPLUGIN(osgearth_splat, SplatPlugin)
-
-} } // namespace osgEarth::Splat
diff --git a/src/osgEarthExtensions/splat/SplatShaders b/src/osgEarthExtensions/splat/SplatShaders
deleted file mode 100644
index c147c5a..0000000
--- a/src/osgEarthExtensions/splat/SplatShaders
+++ /dev/null
@@ -1,46 +0,0 @@
-/* -*-c++-*- */
-/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2008-2012 Pelican Mapping
-* http://osgearth.org
-*
-* osgEarth is free software; you can redistribute it and/or modify
-* it under the terms of the GNU Lesser General Public License as published by
-* the Free Software Foundation; either version 2 of the License, or
-* (at your option) any later version.
-*
-* 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.
-*
-* You should have received a copy of the GNU Lesser General Public License
-* along with this program.  If not, see <http://www.gnu.org/licenses/>
-*/
-#ifndef OSGEARTH_SPLAT_SHADERS
-#define OSGEARTH_SPLAT_SHADERS 1
-
-#include <osgEarth/ShaderLoader>
-
-namespace osgEarth { namespace Splat
-{
-    struct Shaders : public osgEarth::ShaderPackage
-	{
-        Shaders();
-
-        std::string
-            Types,
-            Noise,
-            VertModel,
-            VertView,
-            Frag,
-            FragCommon,
-            FragGetRenderInfo,
-            Util;
-	};
-	
-} } // namespace osgEarth::Splat
-
-#endif // OSGEARTH_SPLAT_SHADERS
diff --git a/src/osgEarthExtensions/splat/SplatShaders.cpp.in b/src/osgEarthExtensions/splat/SplatShaders.cpp.in
deleted file mode 100644
index b6d40af..0000000
--- a/src/osgEarthExtensions/splat/SplatShaders.cpp.in
+++ /dev/null
@@ -1,34 +0,0 @@
-// CMake will compile this file into AutoGenShaders.cpp
-
-#include <osgEarthExtensions/splat/SplatShaders>
-
-#define MULTILINE(...) #__VA_ARGS__
-
-using namespace osgEarth::Splat;
-
-Shaders::Shaders()
-{
-    Types = "Splat.types.glsl";
-    _sources[Types] = MULTILINE(@Splat.types.glsl@);
-
-    Noise = "Splat.Noise.glsl";
-    _sources[Noise] = MULTILINE(@Splat.Noise.glsl@);
-
-    VertModel = "Splat.vert.model.glsl";
-    _sources[VertModel] = MULTILINE(@Splat.vert.model.glsl@);
-
-    VertView = "Splat.vert.view.glsl";
-    _sources[VertView] = MULTILINE(@Splat.vert.view.glsl@);
-
-    Frag = "Splat.frag.glsl";
-    _sources[Frag] = MULTILINE(@Splat.frag.glsl@);
-
-    FragCommon = "Splat.frag.common.glsl";
-    _sources[FragCommon] = MULTILINE(@Splat.frag.common.glsl@);
-
-    FragGetRenderInfo = "Splat.frag.getRenderInfo.glsl";
-    _sources[FragGetRenderInfo] = MULTILINE(@Splat.frag.getRenderInfo.glsl@);
-
-    Util = "Splat.util.glsl";
-    _sources[Util] = MULTILINE(@Splat.util.glsl@);
-}
\ No newline at end of file
diff --git a/src/osgEarthExtensions/splat/SplatTerrainEffect b/src/osgEarthExtensions/splat/SplatTerrainEffect
deleted file mode 100644
index d77fd63..0000000
--- a/src/osgEarthExtensions/splat/SplatTerrainEffect
+++ /dev/null
@@ -1,138 +0,0 @@
-/* -*-c++-*- */
-/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2008-2012 Pelican Mapping
-* http://osgearth.org
-*
-* osgEarth is free software; you can redistribute it and/or modify
-* it under the terms of the GNU Lesser General Public License as published by
-* the Free Software Foundation; either version 2 of the License, or
-* (at your option) any later version.
-*
-* 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.
-*
-* You should have received a copy of the GNU Lesser General Public License
-* along with this program.  If not, see <http://www.gnu.org/licenses/>
-*/
-#ifndef OSGEARTH_SPLAT_SPLAT_TERRAIN_EFFECT_H
-#define OSGEARTH_SPLAT_SPLAT_TERRAIN_EFFECT_H
-
-#include "SplatCatalog"
-#include "SplatCoverageLegend"
-#include "Biome"
-#include "BiomeSelector"
-#include "SplatShaders"
-
-#include <osgEarth/TerrainEffect>
-#include <osgEarth/ImageLayer>
-#include <osg/Image>
-#include <osg/Uniform>
-#include <osg/Texture2DArray>
-
-using namespace osgEarth;
-
-namespace osgEarth { namespace Splat
-{
-    /**
-     * Effect that applies texture splatting to the terrain.
-     */
-    class SplatTerrainEffect : public TerrainEffect
-    {
-    public:
-        /** construct a new terrain effect. */
-        SplatTerrainEffect(
-            const BiomeVector&    biomes,
-            SplatCoverageLegend*  legend,
-            const osgDB::Options* dbOptions);
-
-        /**
-         * Sets the image layer that supplies the coverage values. This value
-         * is mandatory, and you must call it prior to installing the effect.
-         */
-        void setCoverageLayer(const ImageLayer* layer) { _coverageLayer = layer; }
-        const ImageLayer* getCoverageLayer() { return _coverageLayer.get(); }
-
-        /**
-         * Sets the draw priority of the splat effect. Default is -1.0, which means
-         * the splat will render before the terrain engine renders any image layers.
-         * You can set it to 1.0 to splat after drawing image layers.
-         *
-         * This is options, but if you call it you must do so prior to installing
-         * the effect.
-         */
-        void setRenderOrder(float value) { _renderOrder = value; }
-        float getRenderOrder() const { return _renderOrder; }
-
-        /**
-         * Uniform that governs coverage sample warping. The value is type FLOAT.
-         * This warps the texture coordinates used to sample the coverage data
-         * using a simplex noise function. This can help to mitigate the "blockiness"
-         * that somes from low resolution coverage data.
-         * Reasonable values are in the range [0 .. 0.01]
-         */
-        osg::Uniform* getCoverageWarpUniform() { return _warpUniform.get(); }
-
-        /**
-         * Uniform that governs the bilinear sampling of the coverage texture.
-         * The default is 1.0, at which normal bilinear sampling occurs.
-         * Higher values will blur the splatting, and lower values will sharpen it.
-         */
-        osg::Uniform* getCoverageBlurUniform() { return _blurUniform.get(); }
-
-        /**
-         * Uniform that governs the scale level-of-detail offset when sampling 
-         * splat textures. Defaults to 0. This is an integer such that for a
-         * value of N, the texture coordinates are scaled by 2^N when sampling
-         * splat textures.
-         */
-        osg::Uniform* getScaleLevelOffsetUniform() { return _scaleOffsetUniform.get(); }
-
-
-    public: // TerrainEffect interface
-
-        void onInstall(TerrainEngineNode* engine);
-
-        void onUninstall(TerrainEngineNode* engine);
-
-
-    protected:
-        virtual ~SplatTerrainEffect() { }
-
-        void installCoverageSamplingFunction(SplatTextureDef& textureDef);
-        osg::Texture* createNoiseTexture() const;
-
-        // these 2 vectors are index-aligned:
-        BiomeVector                         _biomes;
-        SplatTextureDefVector               _textureDefs;
-
-        bool                                _ok;
-        int                                 _splatTexUnit;
-        osg::ref_ptr<osg::Uniform>          _splatTexUniform;
-        osg::ref_ptr<osg::Uniform>          _coverageTexUniform;
-        osg::ref_ptr<osg::Uniform>          _scaleOffsetUniform;
-        osg::ref_ptr<osg::Uniform>          _warpUniform;
-        osg::ref_ptr<osg::Uniform>          _blurUniform;
-        osg::ref_ptr<SplatCoverageLegend>   _legend;
-        osg::observer_ptr<const ImageLayer> _coverageLayer;
-        float                               _renderOrder;
-        int                                 _noiseTexUnit;
-        osg::ref_ptr<osg::Texture>          _noiseTex;
-        osg::ref_ptr<osg::Uniform>          _noiseTexUniform;
-        osg::ref_ptr<osg::Uniform>          _noiseScaleUniform;
-        osg::ref_ptr<osg::Uniform>          _useBilinearUniform;
-
-        osg::ref_ptr<BiomeSelector>         _biomeSelector;
-
-        bool                                _editMode;
-        bool                                _gpuNoise;
-
-    };
-
-} } // namespace osgEarth::Splat
-
-#endif // OSGEARTH_SPLAT_SPLAT_TERRAIN_EFFECT_H
diff --git a/src/osgEarthExtensions/splat/SplatTerrainEffect.cpp b/src/osgEarthExtensions/splat/SplatTerrainEffect.cpp
deleted file mode 100644
index d116771..0000000
--- a/src/osgEarthExtensions/splat/SplatTerrainEffect.cpp
+++ /dev/null
@@ -1,513 +0,0 @@
-/* -*-c++-*- */
-/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2008-2012 Pelican Mapping
-* http://osgearth.org
-*
-* osgEarth is free software; you can redistribute it and/or modify
-* it under the terms of the GNU Lesser General Public License as published by
-* the Free Software Foundation; either version 2 of the License, or
-* (at your option) any later version.
-*
-* 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.
-*
-* You should have received a copy of the GNU Lesser General Public License
-* along with this program.  If not, see <http://www.gnu.org/licenses/>
-*/
-#include "SplatTerrainEffect"
-#include "SplatOptions"
-
-#include <osgEarth/Registry>
-#include <osgEarth/Capabilities>
-#include <osgEarth/VirtualProgram>
-#include <osgEarth/TerrainEngineNode>
-#include <osgEarth/ImageUtils>
-#include <osgEarth/URI>
-#include <osgEarth/ShaderLoader>
-#include <osgEarthUtil/SimplexNoise>
-
-#include <osg/Texture2D>
-#include <osgDB/WriteFile>
-
-#include "SplatShaders"
-
-#define LC "[Splat] "
-
-#define COVERAGE_SAMPLER "oe_splat_coverageTex"
-#define SPLAT_SAMPLER    "oe_splatTex"
-#define NOISE_SAMPLER    "oe_splat_noiseTex"
-
-using namespace osgEarth;
-using namespace osgEarth::Splat;
-
-SplatTerrainEffect::SplatTerrainEffect(const BiomeVector&    biomes,
-                                       SplatCoverageLegend*  legend,
-                                       const osgDB::Options* dbOptions) :
-_biomes     ( biomes ),
-_legend     ( legend ),
-_renderOrder( -1.0f ),
-_ok         ( false ),
-_editMode   ( false ),
-_gpuNoise   ( false )
-{
-    if ( biomes.size() == 0 )
-    {
-        OE_WARN << LC << "Internal: no biomes.\n";
-    }
-
-    // Create a texture def for each biome.
-    for(unsigned b = 0; b < biomes.size(); ++b)
-    {
-        const Biome& biome = biomes[b];
-        SplatTextureDef def;
-
-        if ( biome.getCatalog() )
-        {
-            if ( biome.getCatalog()->createSplatTextureDef(dbOptions, def) )
-            {
-                // install the sampling function.
-                installCoverageSamplingFunction( def );
-            }
-            else
-            {
-                OE_WARN << LC << "Failed to create a texture for a catalog (" 
-                    << biome.getCatalog()->name().get() << ")\n";
-            }
-
-        }
-        else
-        {
-            OE_WARN << LC << "Biome \""
-                << biome.name().get() << "\"" 
-                << " has an empty catalog and will be ignored.\n";
-        }
-
-        // put it on the list either way, since the vector indicies of biomes
-        // and texturedefs need to line up
-        _textureDefs.push_back( def );
-
-        if ( !_ok )
-        {
-            _ok = def._texture.valid();
-        }
-    }
-
-    SplatOptions def;
-
-    _scaleOffsetUniform    = new osg::Uniform("oe_splat_scaleOffsetInt",   *def.scaleLevelOffset());
-    _warpUniform           = new osg::Uniform("oe_splat_warp",             *def.coverageWarp());
-    _blurUniform           = new osg::Uniform("oe_splat_blur",             *def.coverageBlur());
-    _useBilinearUniform    = new osg::Uniform("oe_splat_useBilinear",      (def.bilinearSampling()==true?1.0f:0.0f));
-    _noiseScaleUniform     = new osg::Uniform("oe_splat_noiseScale",       12.0f);
-
-    _editMode = (::getenv("OSGEARTH_SPLAT_EDIT") != 0L);
-    _gpuNoise = (::getenv("OSGEARTH_SPLAT_GPU_NOISE") != 0L);
-}
-
-void
-SplatTerrainEffect::onInstall(TerrainEngineNode* engine)
-{
-    if ( engine && _ok )
-    {
-        if ( !_coverageLayer.valid() )
-        {
-            OE_WARN << LC << "No coverage layer set\n";
-            return;
-        }
-
-        // Do not need this until/unless the splatting algorithm uses elevation.
-        //engine->requireElevationTextures();
-
-        // install the splat texture array:
-        if ( engine->getResources()->reserveTextureImageUnit(_splatTexUnit, "Splat Coverage") )
-        {
-            osg::StateSet* stateset;
-
-#ifdef REX // note, rex doesn't support the biome selector cull callback yet b/c of the render binning
-            if ( _biomes.size() == 1 )
-                stateset = engine->getSurfaceStateSet();
-            else
-                stateset = new osg::StateSet();
-#else
-            stateset = new osg::StateSet();
-#endif
-
-            // TODO: reinstate "biomes"
-            //osg::StateSet* stateset = new osg::StateSet();
-
-            // splat sampler
-            _splatTexUniform = stateset->getOrCreateUniform( SPLAT_SAMPLER, osg::Uniform::SAMPLER_2D_ARRAY );
-            _splatTexUniform->set( _splatTexUnit );
-            stateset->setTextureAttribute( _splatTexUnit, _textureDefs[0]._texture.get() );
-
-            // coverage sampler
-            _coverageTexUniform = stateset->getOrCreateUniform( COVERAGE_SAMPLER, osg::Uniform::SAMPLER_2D );
-            _coverageTexUniform->set( _coverageLayer->shareImageUnit().get() );
-
-            // control uniforms
-            stateset->addUniform( _scaleOffsetUniform.get() );
-            stateset->addUniform( _warpUniform.get() );
-            stateset->addUniform( _blurUniform.get() );
-            stateset->addUniform( _noiseScaleUniform.get() );
-            stateset->addUniform( _useBilinearUniform.get() );
-
-            stateset->addUniform(new osg::Uniform("oe_splat_detailRange",  1000000.0f));
-
-
-            Shaders package;
-
-            package.define( "SPLAT_EDIT",        _editMode );
-            package.define( "SPLAT_GPU_NOISE",   _gpuNoise );
-            package.define( "OE_USE_NORMAL_MAP", engine->normalTexturesRequired() );
-
-            package.replace( "$COVERAGE_TEXMAT_UNIFORM", _coverageLayer->shareTexMatUniformName().get() );
-            
-            VirtualProgram* vp = VirtualProgram::getOrCreate(stateset);
-            package.load( vp, package.VertModel );
-            package.load( vp, package.VertView );
-            package.load( vp, package.Frag );
-            package.load( vp, package.Util );
-
-            // GPU noise is expensive, so only use it to tweak noise function values that you
-            // can later bake into the noise texture generator.
-            if ( _gpuNoise )
-            {                
-                //osgEarth::replaceIn( fragmentShader, "#undef SPLAT_GPU_NOISE", "#define SPLAT_GPU_NOISE" );
-
-                // Use --uniform on the command line to tweak these values:
-                stateset->addUniform(new osg::Uniform("oe_splat_freq",   32.0f));
-                stateset->addUniform(new osg::Uniform("oe_splat_pers",    0.8f));
-                stateset->addUniform(new osg::Uniform("oe_splat_lac",     2.2f));
-                stateset->addUniform(new osg::Uniform("oe_splat_octaves", 8.0f));
-            }
-            else // use a noise texture (the default)
-            {
-                if (engine->getResources()->reserveTextureImageUnit(_noiseTexUnit, "Splat Noise"))
-                {
-                    _noiseTex = createNoiseTexture();
-                    stateset->setTextureAttribute( _noiseTexUnit, _noiseTex.get() );
-                    _noiseTexUniform = stateset->getOrCreateUniform( NOISE_SAMPLER, osg::Uniform::SAMPLER_2D );
-                    _noiseTexUniform->set( _noiseTexUnit );
-                }
-            }
-
-            if ( _gpuNoise )
-            {
-                // support shaders
-                std::string noiseShaderSource = ShaderLoader::load( package.Noise, package );
-                osg::Shader* noiseShader = new osg::Shader(osg::Shader::FRAGMENT, noiseShaderSource);
-                vp->setShader( "oe_splat_noiseshaders", noiseShader );
-            }
-
-#ifdef REX
-            // TODO: I disabled BIOMES temporarily because the callback impl applies the splatting shader
-            // to the land cover bin as well as the surface bin, which we do not want -- find another way!
-            if ( _biomes.size() == 1 )
-            {
-                // install his biome's texture set:
-                stateset->setTextureAttribute(_splatTexUnit, _textureDefs[0]._texture.get());
-
-                // install this biome's sampling function. Use cloneOrCreate since each
-                // stateset needs a different shader set in its VP.
-                VirtualProgram* vp = VirtualProgram::cloneOrCreate( stateset );
-                osg::Shader* shader = new osg::Shader(osg::Shader::FRAGMENT, _textureDefs[0]._samplingFunction);
-                vp->setShader( "oe_splat_getRenderInfo", shader );
-            }
-
-            else
-#endif
-            {
-                //OE_WARN << LC << "Multi-biome setup needs re-implementing (reminder)\n";
-
-                // install the cull callback that will select the appropriate
-                // state based on the position of the camera.
-                _biomeSelector = new BiomeSelector(
-                    _biomes,
-                    _textureDefs,
-                    stateset,
-                    _splatTexUnit );
-
-                engine->addCullCallback( _biomeSelector.get() );
-            }
-        }
-    }
-}
-
-
-void
-SplatTerrainEffect::onUninstall(TerrainEngineNode* engine)
-{
-    if ( engine )
-    {
-        if ( _noiseTexUnit >= 0 )
-        {
-            engine->getResources()->releaseTextureImageUnit( _noiseTexUnit );
-            _noiseTexUnit = -1;
-        }
-    
-        if ( _splatTexUnit >= 0 )
-        {
-            engine->getResources()->releaseTextureImageUnit( _splatTexUnit );
-            _splatTexUnit = -1;
-        }
-
-        if ( _biomeSelector.valid() )
-        {
-            engine->removeCullCallback( _biomeSelector.get() );
-            _biomeSelector = 0L;
-        }
-    }
-}
-
-#define IND "    "
-
-void
-SplatTerrainEffect::installCoverageSamplingFunction(SplatTextureDef& textureDef)
-{
-    if ( !textureDef._texture.valid() )
-    {
-        OE_WARN << LC << "Internal: texture is not set; cannot create a sampling function\n";
-        return;
-    }
-
-    std::stringstream
-        weightBuf,
-        primaryBuf,
-        detailBuf,
-        brightnessBuf,
-        contrastBuf,
-        thresholdBuf,
-        slopeBuf;
-
-    unsigned
-        primaryCount    = 0,
-        detailCount     = 0,
-        brightnessCount = 0,
-        contrastCount   = 0,
-        thresholdCount  = 0,
-        slopeCount      = 0;
-
-    const SplatCoverageLegend::Predicates& preds = _legend->getPredicates();
-    for(SplatCoverageLegend::Predicates::const_iterator p = preds.begin(); p != preds.end(); ++p)
-    {
-        const CoverageValuePredicate* pred = p->get();
-
-        if ( pred->_exactValue.isSet() )
-        {
-            // Look up by class name:
-            const std::string& className = pred->_mappedClassName.get();
-            const SplatLUT::const_iterator i = textureDef._splatLUT.find(className);
-            if ( i != textureDef._splatLUT.end() )
-            {
-                // found it; loop over the range selectors:
-                int selectorCount = 0;
-                const SplatSelectorVector& selectors = i->second;
-
-                OE_DEBUG << LC << "Class " << className << " has " << selectors.size() << " selectors.\n";
-
-                for(SplatSelectorVector::const_iterator selector = selectors.begin();
-                    selector != selectors.end();
-                    ++selector)
-                {
-                    const std::string&    expression = selector->first;
-                    const SplatRangeData& rangeData  = selector->second;
-
-                    std::string val = pred->_exactValue.get();
-
-                    weightBuf
-                        << IND "float w" << val
-                        << " = (1.0-clamp(abs(value-" << val << ".0),0.0,1.0));\n";
-
-                    // Primary texture index:
-                    if ( primaryCount == 0 )
-                        primaryBuf << IND "primary += ";
-                    else
-                        primaryBuf << " + ";
-
-                    // the "+1" is because "primary" starts out at -1.
-                    primaryBuf << "w"<<val << "*" << (rangeData._textureIndex + 1) << ".0";
-                    primaryCount++;
-
-                    // Detail texture index:
-                    if ( rangeData._detail.isSet() )
-                    {
-                        if ( detailCount == 0 )
-                            detailBuf << IND "detail += ";
-                        else
-                            detailBuf << " + ";
-                        // the "+1" is because "detail" starts out at -1.
-                        detailBuf << "w"<<val << "*" << (rangeData._detail->_textureIndex + 1) << ".0";
-                        detailCount++;
-
-                        if ( rangeData._detail->_brightness.isSet() )
-                        {
-                            if ( brightnessCount == 0 )
-                                brightnessBuf << IND "brightness += ";
-                            else
-                                brightnessBuf << " + ";
-                            brightnessBuf << "w"<<val << "*" << rangeData._detail->_brightness.get();
-                            brightnessCount++;
-                        }
-
-                        if ( rangeData._detail->_contrast.isSet() )
-                        {
-                            if ( contrastCount == 0 )
-                                contrastBuf << IND "contrast += ";
-                            else
-                                contrastBuf << " + ";
-                            contrastBuf << "w"<<val << "*" << rangeData._detail->_contrast.get();
-                            contrastCount++;
-                        }
-
-                        if ( rangeData._detail->_threshold.isSet() )
-                        {
-                            if ( thresholdCount == 0 )
-                                thresholdBuf << IND "threshold += ";
-                            else
-                                thresholdBuf << " + ";
-                            thresholdBuf << "w"<<val << "*" << rangeData._detail->_threshold.get();
-                            thresholdCount++;
-                        }
-
-                        if ( rangeData._detail->_slope.isSet() )
-                        {
-                            if ( slopeCount == 0 )
-                                slopeBuf << IND "slope += ";
-                            else
-                                slopeBuf << " + ";
-                            slopeBuf << "w"<<val << "*" << rangeData._detail->_slope.get();
-                            slopeCount++;
-                        }
-                    }                    
-                }
-            }
-        }
-    }
-
-    if ( primaryCount > 0 )
-        primaryBuf << ";\n";
-
-    if ( detailCount > 0 )
-        detailBuf << ";\n";
-
-    if ( brightnessCount > 0 )
-        brightnessBuf << ";\n";
-
-    if ( contrastCount > 0 )
-        contrastBuf << ";\n";
-
-    if ( thresholdCount > 0 )
-        thresholdBuf << ";\n";
-
-    if ( slopeCount > 0 )
-        slopeBuf << ";\n";
-
-    Shaders package;
-    std::string code = ShaderLoader::load(
-        package.FragGetRenderInfo,
-        package);
-
-    std::string codeToInject = Stringify()
-        << IND
-        << weightBuf.str()
-        << primaryBuf.str()
-        << detailBuf.str()
-        << brightnessBuf.str()
-        << contrastBuf.str()
-        << thresholdBuf.str()
-        << slopeBuf.str();
-
-    osgEarth::replaceIn(code, "$CODE_INJECTION_POINT", codeToInject);
-
-    textureDef._samplingFunction = code;
-
-    OE_DEBUG << LC << "Sampling function = \n" << code << "\n\n";
-}
-
-osg::Texture*
-SplatTerrainEffect::createNoiseTexture() const
-{
-    const int size = 1024;
-    const int slices = 1;
-
-    GLenum type = slices > 2 ? GL_RGBA : GL_LUMINANCE;
-    
-    osg::Image* image = new osg::Image();
-    image->allocateImage(size, size, 1, type, GL_UNSIGNED_BYTE);
-
-    // 0 = rocky mountains..
-    // 1 = warping...
-    const float F[4] = { 4.0f, 16.0f, 4.0f, 8.0f };
-    const float P[4] = { 0.8f,  0.6f, 0.8f, 0.9f };
-    const float L[4] = { 2.2f,  1.7f, 3.0f, 4.0f };
-    
-    for(int k=0; k<slices; ++k)
-    {
-        // Configure the noise function:
-        osgEarth::Util::SimplexNoise noise;
-        noise.setNormalize( true );
-        noise.setRange( 0.0, 1.0 );
-        noise.setFrequency( F[k] );
-        noise.setPersistence( P[k] );
-        noise.setLacunarity( L[k] );
-        noise.setOctaves( 8 );
-
-        float nmin = 10.0f;
-        float nmax = -10.0f;
-
-        // write repeating noise to the image:
-        ImageUtils::PixelReader read ( image );
-        ImageUtils::PixelWriter write( image );
-        for(int t=0; t<size; ++t)
-        {
-            double rt = (double)t/size;
-            for(int s=0; s<size; ++s)
-            {
-                double rs = (double)s/(double)size;
-
-                double n = noise.getTiledValue(rs, rt);
-
-                n = osg::clampBetween(n, 0.0, 1.0);
-
-                if ( n < nmin ) nmin = n;
-                if ( n > nmax ) nmax = n;
-                osg::Vec4f v = read(s, t);
-                v[k] = n;
-                write(v, s, t);
-            }
-        }
-   
-        // histogram stretch to [0..1]
-        for(int x=0; x<size*size; ++x)
-        {
-            int s = x%size, t = x/size;
-            osg::Vec4f v = read(s, t);
-            v[k] = osg::clampBetween((v[k]-nmin)/(nmax-nmin), 0.0f, 1.0f);
-            write(v, s, t);
-        }
-
-        OE_INFO << LC << "Noise: MIN = " << nmin << "; MAX = " << nmax << "\n";
-    }
-
-#if 0
-    std::string filename("noise.png");
-    osgDB::writeImageFile(*image, filename);
-    OE_NOTICE << LC << "Wrote noise texture to " << filename << "\n";
-#endif
-
-    // make a texture:
-    osg::Texture2D* tex = new osg::Texture2D( image );
-    tex->setWrap(tex->WRAP_S, tex->REPEAT);
-    tex->setWrap(tex->WRAP_T, tex->REPEAT);
-    tex->setFilter(tex->MIN_FILTER, tex->LINEAR_MIPMAP_LINEAR);
-    tex->setFilter(tex->MAG_FILTER, tex->LINEAR);
-    tex->setMaxAnisotropy( 1.0f );
-    tex->setUnRefImageDataAfterApply( true );
-
-    return tex;
-}
diff --git a/src/osgEarthExtensions/terrainshader/CMakeLists.txt b/src/osgEarthExtensions/terrainshader/CMakeLists.txt
deleted file mode 100644
index f6bf94d..0000000
--- a/src/osgEarthExtensions/terrainshader/CMakeLists.txt
+++ /dev/null
@@ -1,24 +0,0 @@
-#
-# terrain shader plugin
-#
-set(TARGET_SRC
-	TerrainShaderPlugin.cpp
-	TerrainShaderExtension.cpp
-	${SHADERS_CPP} )
-	
-set(LIB_PUBLIC_HEADERS
-	TerrainShaderExtension
-	TerrainShaderOptions)
-	
-set(TARGET_H
-	${LIB_PUBLIC_HEADERS})
-
-
-set(TARGET_COMMON_LIBRARIES ${TARGET_COMMON_LIBRARIES}
-    osgEarthUtil)
-	
-setup_extension(osgearth_terrainshader)
-
-# to install public driver includes:
-set(LIB_NAME terrainshader)
-
diff --git a/src/osgEarthExtensions/terrainshader/TerrainShaderExtension b/src/osgEarthExtensions/terrainshader/TerrainShaderExtension
deleted file mode 100644
index 207d32f..0000000
--- a/src/osgEarthExtensions/terrainshader/TerrainShaderExtension
+++ /dev/null
@@ -1,68 +0,0 @@
-/* -*-c++-*- */
-/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
- * http://osgearth.org
- *
- * osgEarth is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>
- */
-#ifndef OSGEARTH_EXT_TERRAIN_SHADER_H
-#define OSGEARTH_EXT_TERRAIN_SHADER_H 1
-
-#include "TerrainShaderOptions"
-#include <osgEarth/Extension>
-#include <osgEarth/MapNode>
-#include <osgEarthUtil/Controls>
-
-namespace osgEarth { namespace TerrainShader
-{
-    using namespace osgEarth;
-
-    class TerrainShaderExtension : public Extension,
-                                   public ExtensionInterface<MapNode>
-    {
-    public:
-        META_Object(osgearth_ext_terrainshader, TerrainShaderExtension);
-
-        // CTORs
-        TerrainShaderExtension();
-        TerrainShaderExtension(const TerrainShaderOptions& options);
-
-        // DTOR
-        virtual ~TerrainShaderExtension();
-
-
-    public: // Extension
-
-        void setDBOptions(const osgDB::Options* dbOptions);
-
-
-    public: // ExtensionInterface<MapNode>
-
-        bool connect(MapNode* mapNode);
-
-        bool disconnect(MapNode* mapNode);
-
-
-    protected: // Object
-        TerrainShaderExtension(const TerrainShaderExtension& rhs, const osg::CopyOp& op) { }
-
-    private:
-        const TerrainShaderOptions           _options;
-        osg::ref_ptr<const osgDB::Options>   _dbOptions;
-        osg::ref_ptr<class TerrainEffect>    _effect;
-    };
-
-} } // namespace osgEarth::TerrainShader
-
-#endif // OSGEARTH_EXT_TERRAIN_SHADER_H
diff --git a/src/osgEarthExtensions/terrainshader/TerrainShaderExtension.cpp b/src/osgEarthExtensions/terrainshader/TerrainShaderExtension.cpp
deleted file mode 100644
index d577172..0000000
--- a/src/osgEarthExtensions/terrainshader/TerrainShaderExtension.cpp
+++ /dev/null
@@ -1,121 +0,0 @@
-/* -*-c++-*- */
-/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
- * http://osgearth.org
- *
- * osgEarth is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>
- */
-#include "TerrainShaderExtension"
-#include <osgEarth/TerrainEffect>
-#include <osgEarth/MapNode>
-#include <osgEarth/VirtualProgram>
-#include <osgEarth/ShaderLoader>
-
-using namespace osgEarth;
-using namespace osgEarth::TerrainShader;
-
-#define LC "[TerrainShaderExtension] "
-
-namespace
-{
-    class GLSLEffect : public TerrainEffect
-    {
-    public:
-        GLSLEffect(const std::vector<TerrainShaderOptions::Code>& code,
-                   const osgDB::Options*                          dbOptions ) : _code(code), _dbOptions(dbOptions)
-        {
-            for(unsigned i=0; i<code.size(); ++i)
-            {
-                std::string fn = code[i]._uri.isSet() ? code[i]._uri->full() : "$code." + i;
-                _package.add( fn, code[i]._source );
-            }
-        }
-
-        void onInstall(TerrainEngineNode* engine)
-        {
-            if ( !engine ) return;
-
-            VirtualProgram* vp = VirtualProgram::getOrCreate(engine->getOrCreateStateSet());
-            _package.loadAll( vp, _dbOptions.get() );
-        }
-
-        void onUninstall(TerrainEngineNode* engine)
-        {
-            if ( engine && engine->getStateSet() )
-            {
-                VirtualProgram* vp = VirtualProgram::get(engine->getStateSet());
-                if ( vp )
-                {
-                    _package.unloadAll( vp, _dbOptions.get() );
-                }
-            }
-        }
-
-        std::vector<TerrainShaderOptions::Code> _code;
-        ShaderPackage                           _package;
-        osg::ref_ptr<const osgDB::Options>      _dbOptions;
-    };
-}
-
-
-TerrainShaderExtension::TerrainShaderExtension()
-{
-    //nop
-}
-
-TerrainShaderExtension::TerrainShaderExtension(const TerrainShaderOptions& options) :
-_options( options )
-{
-    //nop
-}
-
-TerrainShaderExtension::~TerrainShaderExtension()
-{
-    //nop
-}
-
-void
-TerrainShaderExtension::setDBOptions(const osgDB::Options* dbOptions)
-{
-    _dbOptions = dbOptions;
-}
-
-bool
-TerrainShaderExtension::connect(MapNode* mapNode)
-{
-    if ( !mapNode )
-    {
-        OE_WARN << LC << "Illegal: MapNode cannot be null." << std::endl;
-        return false;
-    }
-    _effect = new GLSLEffect( _options.code(), _dbOptions.get() );
-    mapNode->getTerrainEngine()->addEffect( _effect.get() );
-    
-    OE_INFO << LC << "Installed.\n";
-
-    return true;
-}
-
-bool
-TerrainShaderExtension::disconnect(MapNode* mapNode)
-{
-    if ( mapNode && _effect.valid() )
-    {
-        mapNode->getTerrainEngine()->removeEffect( _effect.get() );
-        _effect = 0L;
-    }
-
-    return true;
-}
-
diff --git a/src/osgEarthExtensions/terrainshader/TerrainShaderOptions b/src/osgEarthExtensions/terrainshader/TerrainShaderOptions
deleted file mode 100644
index a58bc8b..0000000
--- a/src/osgEarthExtensions/terrainshader/TerrainShaderOptions
+++ /dev/null
@@ -1,87 +0,0 @@
-/* -*-c++-*- */
-/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
- * http://osgearth.org
- *
- * osgEarth is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>
- */
-#ifndef OSGEARTH_EXT_TERRAIN_SHADER_OPTIONS
-#define OSGEARTH_EXT_TERRAIN_SHADER_OPTIONS 1
-
-#include <osgEarth/Config>
-#include <osgEarth/URI>
-#include <vector>
-
-namespace osgEarth { namespace TerrainShader
-{
-    using namespace osgEarth;
-
-    /**
-     * Options for applying an inline shader to the terrain.
-     */
-    class TerrainShaderOptions : public DriverConfigOptions // NO EXPORT; header only
-    {
-    public:
-        struct Code
-        {
-            std::string   _source;
-            optional<URI> _uri;
-        };
-
-        std::vector<Code>& code() { return _code; }
-        const std::vector<Code>& code() const { return _code; }
-
-    public:
-        TerrainShaderOptions( const ConfigOptions& opt =ConfigOptions() ) : DriverConfigOptions( opt )
-        {
-            setDriver( "terrainshader" );
-            fromConfig( _conf );
-        }
-
-        virtual ~TerrainShaderOptions() { }
-
-    public:
-        Config getConfig() const {
-            Config conf = DriverConfigOptions::getConfig();
-            for(unsigned i=0; i<_code.size(); ++i) {
-                Config c("code", _code[i]._source);
-                c.addIfSet("url", _code[i]._uri);
-                conf.add( c );
-            }
-            return conf;
-        }
-
-    protected:
-        void mergeConfig( const Config& conf ) {
-            DriverConfigOptions::mergeConfig( conf );
-            fromConfig( conf );
-        }
-
-    private:
-        void fromConfig( const Config& conf ) {
-            ConfigSet s = conf.children("code");
-            for(ConfigSet::const_iterator i = s.begin(); i != s.end(); ++i) {
-                _code.push_back(Code());
-                _code.back()._source = i->value();
-                i->getIfSet("url", _code.back()._uri);
-            }
-        }
-
-        std::vector<Code> _code;
-    };
-
-} } // namespace osgEarth::TerrainShader
-
-#endif // OSGEARTH_EXT_TERRAIN_SHADER_OPTIONS
-
diff --git a/src/osgEarthExtensions/terrainshader/TerrainShaderPlugin.cpp b/src/osgEarthExtensions/terrainshader/TerrainShaderPlugin.cpp
deleted file mode 100644
index be96b77..0000000
--- a/src/osgEarthExtensions/terrainshader/TerrainShaderPlugin.cpp
+++ /dev/null
@@ -1,56 +0,0 @@
-/* -*-c++-*- */
-/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
- * http://osgearth.org
- *
- * osgEarth is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>
- */
-#include "TerrainShaderOptions"
-#include "TerrainShaderExtension"
-
-#include <osgDB/ReaderWriter>
-#include <osgDB/Registry>
-#include <osgDB/FileNameUtils>
-
-namespace osgEarth { namespace TerrainShader
-{
-    /**
-     * Plugin entry point
-     */
-    class TerrainShaderPlugin : public osgDB::ReaderWriter
-    {
-    public: // Plugin stuff
-
-        TerrainShaderPlugin() {
-            supportsExtension( "osgearth_terrainshader", "osgEarth Terrain Shader Extension Plugin" );
-        }
-        
-        const char* className() {
-            return "osgEarth Terrain Shader Extension Plugin";
-        }
-
-        virtual ~TerrainShaderPlugin() { }
-
-        ReadResult readObject(const std::string& filename, const osgDB::Options* dbOptions) const
-        {
-          if ( !acceptsExtension(osgDB::getLowerCaseFileExtension(filename)) )
-                return ReadResult::FILE_NOT_HANDLED;
-
-          return ReadResult( new TerrainShaderExtension(Extension::getConfigOptions(dbOptions)) );
-        }
-    };
-
-    REGISTER_OSGPLUGIN(osgearth_terrainshader, TerrainShaderPlugin)
-
-} } // namespace osgEarth::BumpMap
diff --git a/src/osgEarthExtensions/viewpoints/CMakeLists.txt b/src/osgEarthExtensions/viewpoints/CMakeLists.txt
deleted file mode 100644
index 65c7f60..0000000
--- a/src/osgEarthExtensions/viewpoints/CMakeLists.txt
+++ /dev/null
@@ -1,24 +0,0 @@
-#
-# Viewpoints plugin
-#
-
-SET(TARGET_SRC
-	ViewpointsPlugin.cpp
-	ViewpointsExtension.cpp)
-	
-SET(LIB_PUBLIC_HEADERS
-	ViewpointsExtension)
-	
-SET(TARGET_H
-	${LIB_PUBLIC_HEADERS} )
-
-SET(TARGET_COMMON_LIBRARIES ${TARGET_COMMON_LIBRARIES}
-    osgEarthUtil)
-	
-SETUP_EXTENSION(osgearth_viewpoints)
-
-# to install public driver includes:
-SET(LIB_NAME viewpoints)
-
-INCLUDE(ModuleInstallOsgEarthExtensionIncludes OPTIONAL)
-
diff --git a/src/osgEarthExtensions/viewpoints/ViewpointsExtension b/src/osgEarthExtensions/viewpoints/ViewpointsExtension
deleted file mode 100644
index 08dfada..0000000
--- a/src/osgEarthExtensions/viewpoints/ViewpointsExtension
+++ /dev/null
@@ -1,83 +0,0 @@
-/* -*-c++-*- */
-/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
- * http://osgearth.org
- *
- * osgEarth is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>
- */
-#ifndef OSGEARTH_VIEWPOINTS_EXTENSION
-#define OSGEARTH_VIEWPOINTS_EXTENSION 1
-
-#include <osgEarth/Extension>
-#include <osgEarth/Viewpoint>
-#include <osgEarthUtil/Controls>
-#include <osgGA/GUIEventAdapter>
-#include <osg/View>
-#include <vector>
-
-namespace osgEarth { namespace Viewpoints
-{
-    using namespace osgEarth;
-    using namespace osgEarth::Util::Controls;
-
-    /**
-     * Loads a collection of viewpoints and makes them available
-     * through a Controls UI.
-     */
-    class ViewpointsExtension : public Extension,
-                                public ExtensionInterface<osg::View>,
-                                public ExtensionInterface<Control>
-    {
-    public:
-        META_Object(osgearth_ext_viewpoints, ViewpointsExtension);
-
-        // CTORs
-        ViewpointsExtension();
-        ViewpointsExtension(const ConfigOptions& options);
-
-        // DTOR
-        virtual ~ViewpointsExtension();
-
-
-    public: // Extension
-
-        void setDBOptions(const osgDB::Options* dbOptions);
-
-
-    public: // ExtensionInterface<osg::View>
-
-        bool connect(osg::View* view);
-
-        bool disconnect(osg::View* view);
-
-
-    public: // ExtensionInterface<Control>
-
-        bool connect(Control* control);
-
-        bool disconnect(Control* control);
-
-
-    protected: // Object
-        ViewpointsExtension(const ViewpointsExtension& rhs, const osg::CopyOp& op) { }
-
-    private:
-        osg::ref_ptr<const osgDB::Options>   _dbOptions;
-        std::vector<Viewpoint>               _viewpoints;
-        osg::ref_ptr<osgGA::GUIEventHandler> _handler;
-    };
-
-} } // namespace osgEarth::Viewpoints
-
-#endif // OSGEARTH_VIEWPOINTS_EXTENSION
diff --git a/src/osgEarthExtensions/viewpoints/ViewpointsExtension.cpp b/src/osgEarthExtensions/viewpoints/ViewpointsExtension.cpp
deleted file mode 100644
index 3766553..0000000
--- a/src/osgEarthExtensions/viewpoints/ViewpointsExtension.cpp
+++ /dev/null
@@ -1,242 +0,0 @@
-/* -*-c++-*- */
-/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
- * http://osgearth.org
- *
- * osgEarth is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>
- */
-#include "ViewpointsExtension"
-#include <osgEarth/Viewpoint>
-#include <osgEarth/XmlUtils>
-#include <osgEarthUtil/EarthManipulator>
-#include <osgViewer/View>
-
-using namespace osgEarth;
-using namespace osgEarth::Util;
-using namespace osgEarth::Util::Controls;
-using namespace osgEarth::Viewpoints;
-
-#define LC "[ViewpointsExtension] "
-
-
-#define VP_MIN_DURATION      2.0     // minimum fly time.
-#define VP_METERS_PER_SECOND 2500.0  // fly speed
-#define VP_MAX_DURATION      2.0     // maximum fly time.
-
-namespace
-{
-    void flyToViewpoint(EarthManipulator* manip, const Viewpoint& vp)
-    {
-        Viewpoint currentVP = manip->getViewpoint();
-        GeoPoint vp0 = currentVP.focalPoint().get();
-        GeoPoint vp1 = vp.focalPoint().get();
-        double distance = vp0.distanceTo(vp1);
-        double duration = osg::clampBetween(distance / VP_METERS_PER_SECOND, VP_MIN_DURATION, VP_MAX_DURATION);
-        manip->setViewpoint( vp, duration );
-    }
-
-
-    struct ViewpointsHandler : public osgGA::GUIEventHandler
-    {
-        ViewpointsHandler(const std::vector<Viewpoint>& viewpoints)
-            : _viewpoints( viewpoints ) { } 
-
-        bool handle( const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa )
-        {
-            if ( ea.getEventType() == ea.KEYDOWN )
-            {
-                if ( !_viewpoints.empty() )
-                {
-                    int index = (int)ea.getKey() - (int)'1';
-                    if ( index >= 0 && index < (int)_viewpoints.size() )
-                    {
-                        EarthManipulator* manip = getManip(aa);
-                        if ( manip )
-                            flyToViewpoint( manip, _viewpoints[index] );
-                    }
-                }
-                if ( ea.getKey() == 'v' )
-                {
-                    osgViewer::View* view = dynamic_cast<osgViewer::View*>(aa.asView());
-                    if ( view )
-                    {
-                        EarthManipulator* manip = getManip(aa);
-                        if ( manip )
-                        {
-                            XmlDocument xml( manip->getViewpoint().getConfig() );
-                            xml.store( std::cout );
-                            std::cout << std::endl;
-                        }
-                    }
-                }
-                aa.requestRedraw();
-            }
-
-            else if ( ea.getEventType() == ea.FRAME && _flyTo.isSet() )
-            {
-                EarthManipulator* manip = getManip(aa);
-                if ( manip )
-                    flyToViewpoint(manip, *_flyTo);
-                _flyTo.unset();
-            }
-
-            return false;
-        }
-
-        EarthManipulator* getManip(osgGA::GUIActionAdapter& aa)
-        {
-            osgViewer::View* view = dynamic_cast<osgViewer::View*>(aa.asView());
-            return view ? dynamic_cast<EarthManipulator*>(view->getCameraManipulator()) : 0L;
-        }
-
-        std::vector<Viewpoint> _viewpoints;
-        optional<Viewpoint>    _flyTo;
-    };
-
-
-    // flies to a viewpoint in response to control event (click)
-    struct ClickViewpointHandler : public ControlEventHandler
-    {
-        ClickViewpointHandler(const Viewpoint& vp, ViewpointsHandler* handler) :
-            _vp(vp), _handler(handler) { }
-
-        Viewpoint          _vp;
-        ViewpointsHandler* _handler;
-
-        virtual void onClick(Control* control)
-        {
-            _handler->_flyTo = _vp;
-        }
-    };
-
-
-    Control* createViewpointControl(ViewpointsHandler* handler)
-    {
-        Grid* grid = 0L;
-
-        if ( handler->_viewpoints.size() > 0 )
-        {
-            // the viewpoint container:
-            grid = new Grid();
-            grid->setChildSpacing( 0 );
-            grid->setChildVertAlign( Control::ALIGN_CENTER );
-
-            for( unsigned i=0; i<handler->_viewpoints.size(); ++i )
-            {
-                const Viewpoint& vp = handler->_viewpoints[i];
-                Control* num = new LabelControl(Stringify() << (i+1), 16.0f, osg::Vec4f(1,1,0,1));
-                num->setPadding( 4 );
-                grid->setControl( 0, i, num );
-
-                Control* vpc = new LabelControl(vp.name()->empty() ? "<no name>" : vp.name().get(), 16.0f);
-                vpc->setPadding( 4 );
-                vpc->setHorizFill( true );
-                vpc->setActiveColor( osg::Vec4(0.4,0.4,1.0,1.0) ); // blue
-                vpc->addEventHandler( new ClickViewpointHandler(vp, handler) );
-                grid->setControl( 1, i, vpc );
-            }
-        }
-
-        return grid;
-    }
-}
-
-//.........................................................................
-
-
-ViewpointsExtension::ViewpointsExtension()
-{
-    //NOP
-}
-
-ViewpointsExtension::ViewpointsExtension(const ConfigOptions& options)
-{
-    // backwards-compatibility: read viewpoints at the top level???
-    const Config& viewpointsConf = options.getConfig();
-
-    std::vector<Viewpoint> viewpoints;
-
-    const ConfigSet& children = viewpointsConf.children("viewpoint");
-    if ( children.size() > 0 )
-    {
-        for( ConfigSet::const_iterator i = children.begin(); i != children.end(); ++i )
-        {
-
-            viewpoints.push_back( Viewpoint(*i) );
-        }
-    }
-
-    OE_INFO << LC << "Read " << _viewpoints.size() << " viewpoints\n";
-
-    _handler = new ViewpointsHandler(viewpoints);
-}
-
-ViewpointsExtension::~ViewpointsExtension()
-{
-    //nop
-}
-
-void
-ViewpointsExtension::setDBOptions(const osgDB::Options* dbOptions)
-{
-    _dbOptions = dbOptions;
-}
-
-bool
-ViewpointsExtension::connect(osg::View* view)
-{
-    osgViewer::View* v = dynamic_cast<osgViewer::View*>(view);
-    if ( v && _handler.valid() )
-    {
-        v->addEventHandler( _handler.get() );
-    }
-    return true;
-}
-
-bool
-ViewpointsExtension::disconnect(osg::View* view)
-{
-    //TODO: remove the event handler
-    osgViewer::View* v = dynamic_cast<osgViewer::View*>(view);
-    if ( v && _handler.valid() )
-    {
-        v->removeEventHandler( _handler.get() );
-    }
-    return true;
-}
-
-bool
-ViewpointsExtension::connect(Control* control)
-{
-    //TODO add a UI.
-    Container* container = dynamic_cast<Container*>(control);
-    if ( container )
-    {
-        ViewpointsHandler* vh = static_cast<ViewpointsHandler*>(_handler.get());
-        if ( vh->_viewpoints.size() > 0 )
-        {
-            Control* c = createViewpointControl( vh );
-            if ( c )
-                container->addControl( c );
-        }
-    }
-    return true;
-}
-
-bool
-ViewpointsExtension::disconnect(Control* control)
-{
-    // TODO: remove the UI
-    return true;
-}
diff --git a/src/osgEarthExtensions/viewpoints/ViewpointsPlugin.cpp b/src/osgEarthExtensions/viewpoints/ViewpointsPlugin.cpp
deleted file mode 100644
index fcfe110..0000000
--- a/src/osgEarthExtensions/viewpoints/ViewpointsPlugin.cpp
+++ /dev/null
@@ -1,55 +0,0 @@
-/* -*-c++-*- */
-/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
- * http://osgearth.org
- *
- * osgEarth is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>
- */
-#include "ViewpointsExtension"
-
-#include <osgDB/ReaderWriter>
-#include <osgDB/Registry>
-#include <osgDB/FileNameUtils>
-
-namespace osgEarth { namespace Viewpoints
-{
-    /**
-     * Plugin entry point
-     */
-    class ViewpointsPlugin : public osgDB::ReaderWriter
-    {
-    public: // Plugin stuff
-
-        ViewpointsPlugin() {
-            supportsExtension( "osgearth_viewpoints", "osgEarth Viewpoints Extension" );
-        }
-        
-        const char* className() {
-            return "osgEarth Viewpoints Extension";
-        }
-
-        virtual ~ViewpointsPlugin() { }
-
-        ReadResult readObject(const std::string& filename, const osgDB::Options* dbOptions) const
-        {
-          if ( !acceptsExtension(osgDB::getLowerCaseFileExtension(filename)) )
-                return ReadResult::FILE_NOT_HANDLED;
-
-          return ReadResult( new ViewpointsExtension(Extension::getConfigOptions(dbOptions)) );
-        }
-    };
-
-    REGISTER_OSGPLUGIN(osgearth_viewpoints, ViewpointsPlugin)
-
-} } // namespace osgEarth::Viewpoints
diff --git a/src/osgEarthFeatures/AltitudeFilter b/src/osgEarthFeatures/AltitudeFilter
index 4b5d7af..7ab6bcc 100644
--- a/src/osgEarthFeatures/AltitudeFilter
+++ b/src/osgEarthFeatures/AltitudeFilter
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthFeatures/AltitudeFilter.cpp b/src/osgEarthFeatures/AltitudeFilter.cpp
index 5264e8d..2f8385d 100644
--- a/src/osgEarthFeatures/AltitudeFilter.cpp
+++ b/src/osgEarthFeatures/AltitudeFilter.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -77,6 +77,10 @@ AltitudeFilter::pushAndDontClamp( FeatureList& features, FilterContext& cx )
         _altitude.valid() &&
         _altitude->technique() == _altitude->TECHNIQUE_GPU;
 
+    bool ignoreZ =
+        gpuClamping && 
+        _altitude->clamping() == _altitude->CLAMP_TO_TERRAIN;
+
     for( FeatureList::iterator i = features.begin(); i != features.end(); ++i )
     {
         Feature* feature = i->get();
@@ -95,9 +99,9 @@ AltitudeFilter::pushAndDontClamp( FeatureList& features, FilterContext& cx )
         if ( _altitude.valid() && _altitude->verticalScale().isSet() )
             scaleZ = feature->eval( scaleExpr, &cx );
 
-        double offsetZ = 0.0;
+        optional<double> offsetZ( 0.0 );
         if ( _altitude.valid() && _altitude->verticalOffset().isSet() )
-            offsetZ = feature->eval( offsetExpr, &cx );
+            offsetZ = feature->eval( offsetExpr, &cx );       
         
         GeometryIterator gi( feature->getGeometry() );
         while( gi.hasMore() )
@@ -105,10 +109,15 @@ AltitudeFilter::pushAndDontClamp( FeatureList& features, FilterContext& cx )
             Geometry* geom = gi.next();
             for( Geometry::iterator g = geom->begin(); g != geom->end(); ++g )
             {
+                if ( ignoreZ )
+                {
+                    g->z() = 0.0;
+                }
+
                 if ( !gpuClamping )
                 {
                     g->z() *= scaleZ;
-                    g->z() += offsetZ;
+                    g->z() += offsetZ.get();
                 }
 
                 if ( g->z() < minHAT )
@@ -128,7 +137,7 @@ AltitudeFilter::pushAndDontClamp( FeatureList& features, FilterContext& cx )
         if ( gpuClamping )
         {
             feature->set("__oe_verticalScale",  scaleZ);
-            feature->set("__oe_verticalOffset", offsetZ);
+            feature->set("__oe_verticalOffset", offsetZ.get());
         }
     }
 }
@@ -174,7 +183,6 @@ AltitudeFilter::pushAndClamp( FeatureList& features, FilterContext& cx )
         featureSRS->isVertEquivalentTo( mapSRS );
 
 
-
     for( FeatureList::iterator i = features.begin(); i != features.end(); ++i )
     {
         Feature* feature = i->get();
@@ -198,6 +206,19 @@ AltitudeFilter::pushAndClamp( FeatureList& features, FilterContext& cx )
         double offsetZ = 0.0;
         if ( _altitude.valid() && _altitude->verticalOffset().isSet() )
             offsetZ = feature->eval( offsetExpr, &cx );
+
+        osgEarth::Bounds bounds = feature->getGeometry()->getBounds();
+        const osg::Vec2d& center = bounds.center2d();
+        GeoPoint centroid(featureSRS, center.x(), center.y());
+        double   centroidElevation = 0.0;
+
+        // If we aren't doing per vertex clamping go ahead and get the centroid.
+        // We do this now instead of within the geometry iterator to ensure that multipolygons
+        // are clamped to the whole multipolygon and not per polygon.
+        if (!perVertex)
+        {
+            eq.getElevation( centroid, centroidElevation, _maxRes );
+        }
         
         GeometryIterator gi( feature->getGeometry() );
         while( gi.hasMore() )
@@ -247,40 +268,32 @@ AltitudeFilter::pushAndClamp( FeatureList& features, FilterContext& cx )
                 }
                 else // per centroid
                 {
-                    osgEarth::Bounds bounds = geom->getBounds();
-                    const osg::Vec2d& center = bounds.center2d();
-                    GeoPoint centroid(featureSRS, center.x(), center.y());
-                    double   centroidElevation;
-
-                    if ( eq.getElevation( centroid, centroidElevation, _maxRes ) )
+                    for( unsigned i=0; i<geom->size(); ++i )
                     {
-                        for( unsigned i=0; i<geom->size(); ++i )
-                        {
-                            osg::Vec3d& p = (*geom)[i];
-                            p.z() *= scaleZ;
-                            p.z() += offsetZ;
+                        osg::Vec3d& p = (*geom)[i];
+                        p.z() *= scaleZ;
+                        p.z() += offsetZ;
 
-                            double z = p.z();
-                            if ( !vertEquiv )
-                            {
-                                osg::Vec3d tempgeo;
-                                if ( !featureSRS->transform(p, mapSRS->getGeographicSRS(), tempgeo) )
-                                    z = tempgeo.z();
-                            }
-
-                            double hat = z - centroidElevation;
-
-                            if ( hat > maxHAT )
-                                maxHAT = hat;
-                            if ( hat < minHAT )
-                                minHAT = hat;
+                        double z = p.z();
+                        if ( !vertEquiv )
+                        {
+                            osg::Vec3d tempgeo;
+                            if ( !featureSRS->transform(p, mapSRS->getGeographicSRS(), tempgeo) )
+                                z = tempgeo.z();
                         }
 
-                        if ( centroidElevation > maxTerrainZ )
-                            maxTerrainZ = centroidElevation;
-                        if ( centroidElevation < minTerrainZ )
-                            minTerrainZ = centroidElevation;
+                        double hat = z - centroidElevation;
+
+                        if ( hat > maxHAT )
+                            maxHAT = hat;
+                        if ( hat < minHAT )
+                            minHAT = hat;
                     }
+
+                    if ( centroidElevation > maxTerrainZ )
+                        maxTerrainZ = centroidElevation;
+                    if ( centroidElevation < minTerrainZ )
+                        minTerrainZ = centroidElevation;
                 }
             }
 
@@ -329,40 +342,32 @@ AltitudeFilter::pushAndClamp( FeatureList& features, FilterContext& cx )
                 }
                 else // per-centroid
                 {
-                    osgEarth::Bounds bounds = geom->getBounds();
-                    const osg::Vec2d& center = bounds.center2d();
-                    GeoPoint centroid(featureSRS, center.x(), center.y());
-                    double   centroidElevation;
-
-                    if ( eq.getElevation( centroid, centroidElevation, _maxRes ) )
+                    for( unsigned i=0; i<geom->size(); ++i )
                     {
-                        for( unsigned i=0; i<geom->size(); ++i )
-                        {
-                            osg::Vec3d& p = (*geom)[i];
-                            p.z() *= scaleZ;
-                            p.z() += offsetZ;
-
-                            double hat = p.z();
-                            p.z() = centroidElevation + p.z();
+                        osg::Vec3d& p = (*geom)[i];
+                        p.z() *= scaleZ;
+                        p.z() += offsetZ;
 
-                            // if necessary, convert the Z value (which is now in the map's SRS) back to
-                            // the feature's SRS.
-                            if ( !vertEquiv )
-                            {
-                                featureSRSwithMapVertDatum->transform(p, featureSRS, p);
-                            }
+                        double hat = p.z();
+                        p.z() = centroidElevation + p.z();
 
-                            if ( hat > maxHAT )
-                                maxHAT = hat;
-                            if ( hat < minHAT )
-                                minHAT = hat;
+                        // if necessary, convert the Z value (which is now in the map's SRS) back to
+                        // the feature's SRS.
+                        if ( !vertEquiv )
+                        {
+                            featureSRSwithMapVertDatum->transform(p, featureSRS, p);
                         }
 
-                        if ( centroidElevation > maxTerrainZ )
-                            maxTerrainZ = centroidElevation;
-                        if ( centroidElevation < minTerrainZ )
-                            minTerrainZ = centroidElevation;
+                        if ( hat > maxHAT )
+                            maxHAT = hat;
+                        if ( hat < minHAT )
+                            minHAT = hat;
                     }
+
+                    if ( centroidElevation > maxTerrainZ )
+                        maxTerrainZ = centroidElevation;
+                    if ( centroidElevation < minTerrainZ )
+                        minTerrainZ = centroidElevation;
                 }
             }
 
@@ -390,25 +395,17 @@ AltitudeFilter::pushAndClamp( FeatureList& features, FilterContext& cx )
                 }
                 else // per-centroid
                 {
-                    osgEarth::Bounds bounds = geom->getBounds();
-                    const osg::Vec2d& center = bounds.center2d();
-                    GeoPoint centroid(featureSRS, center.x(), center.y());
-                    double   centroidElevation;
-
                     osg::ref_ptr<const SpatialReference> featureSRSWithMapVertDatum;
                     if ( !vertEquiv )
                         featureSRSWithMapVertDatum = SpatialReference::create(featureSRS->getHorizInitString(), mapSRS->getVertInitString());
 
-                    if ( eq.getElevation( centroid, centroidElevation, _maxRes ) )
+                    for( unsigned i=0; i<geom->size(); ++i )
                     {
-                        for( unsigned i=0; i<geom->size(); ++i )
+                        osg::Vec3d& p = (*geom)[i];
+                        p.z() = centroidElevation;
+                        if ( !vertEquiv )
                         {
-                            osg::Vec3d& p = (*geom)[i];
-                            p.z() = centroidElevation;
-                            if ( !vertEquiv )
-                            {
-                                featureSRSWithMapVertDatum->transform(p, featureSRS, p);
-                            }
+                            featureSRSWithMapVertDatum->transform(p, featureSRS, p);
                         }
                     }
                 }
diff --git a/src/osgEarthFeatures/BufferFilter b/src/osgEarthFeatures/BufferFilter
index bcbccf9..a761f6d 100644
--- a/src/osgEarthFeatures/BufferFilter
+++ b/src/osgEarthFeatures/BufferFilter
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthFeatures/BufferFilter.cpp b/src/osgEarthFeatures/BufferFilter.cpp
index eef4614..461f152 100644
--- a/src/osgEarthFeatures/BufferFilter.cpp
+++ b/src/osgEarthFeatures/BufferFilter.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthFeatures/BuildGeometryFilter b/src/osgEarthFeatures/BuildGeometryFilter
index 5c65b9f..8d818d3 100644
--- a/src/osgEarthFeatures/BuildGeometryFilter
+++ b/src/osgEarthFeatures/BuildGeometryFilter
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -74,12 +74,20 @@ namespace osgEarth { namespace Features
         optional<StringExpression>& featureName() { return _featureNameExpr; }
         const optional<StringExpression>& featureName() const { return _featureNameExpr; }
 
+        /**
+         * When a geocentric polygon is very large, the filter has to tile it up in order to
+         * properly tessellate it. This is the maximum size of each tile (in degrees).
+         */        
+        optional<float>& maxPolygonTilingAngle() { return _maxPolyTilingAngle_deg; }
+        const optional<float>& maxPolygonTilingAngle() const { return _maxPolyTilingAngle_deg; }
+
     protected:
         Style                      _style;
 
         optional<double>           _maxAngle_deg;
         optional<GeoInterpolation> _geoInterp;
         optional<StringExpression> _featureNameExpr;
+        optional<float>            _maxPolyTilingAngle_deg;
         
         void tileAndBuildPolygon(
             Geometry*               input,
@@ -95,7 +103,6 @@ namespace osgEarth { namespace Features
             const SpatialReference* featureSRS,
             const SpatialReference* mapSRS,
             bool                    makeECEF,
-            bool                    tessellate,
             osg::Geometry*          osgGeom,
             const osg::Matrixd      &world2local);
 
diff --git a/src/osgEarthFeatures/BuildGeometryFilter.cpp b/src/osgEarthFeatures/BuildGeometryFilter.cpp
index fa579f4..fdb0ea0 100644
--- a/src/osgEarthFeatures/BuildGeometryFilter.cpp
+++ b/src/osgEarthFeatures/BuildGeometryFilter.cpp
@@ -1,6 +1,6 @@
-/* -*-c++-*- */
+/* -*_maxPolyTilingAngle_deg-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -26,6 +26,7 @@
 #include <osgEarthSymbology/PolygonSymbol>
 #include <osgEarthSymbology/MeshSubdivider>
 #include <osgEarthSymbology/ResourceCache>
+#include <osgEarthSymbology/MeshConsolidator>
 #include <osgEarth/Tessellator>
 #include <osgEarth/Utils>
 #include <osgEarth/Clamping>
@@ -95,7 +96,8 @@ namespace
 BuildGeometryFilter::BuildGeometryFilter( const Style& style ) :
 _style        ( style ),
 _maxAngle_deg ( 180.0 ),
-_geoInterp    ( GEOINTERP_RHUMB_LINE )
+_geoInterp    ( GEOINTERP_RHUMB_LINE ),
+_maxPolyTilingAngle_deg( 45.0f )
 {
     //nop
 }
@@ -126,8 +128,10 @@ BuildGeometryFilter::processPolygons(FeatureList& features, FilterContext& conte
             input->style().isSet() && input->style()->has<PolygonSymbol>() ? input->style()->get<PolygonSymbol>() :
             _style.get<PolygonSymbol>();
 
-        if ( !poly )
+        if ( !poly ) {
+            OE_TEST << LC << "Discarding feature with no poly symbol\n";
             continue;
+        }
 
         // run a symbol script if present.
         if ( poly->script().isSet() )
@@ -144,15 +148,17 @@ BuildGeometryFilter::processPolygons(FeatureList& features, FilterContext& conte
             part->removeDuplicates();
 
             // skip geometry that is invalid for a polygon
-            if ( part->size() < 3 )
+            if ( part->size() < 3 ) {
+                OE_TEST << LC << "Discarding illegal part (less than 3 verts)\n";
                 continue;
+            }
 
             // resolve the color:
             osg::Vec4f primaryColor = poly->fill()->color();
             
             osg::ref_ptr<osg::Geometry> osgGeom = new osg::Geometry();
-            //osgGeom->setUseVertexBufferObjects( true );
-            //osgGeom->setUseDisplayList( false );
+            osgGeom->setUseVertexBufferObjects( true );
+            osgGeom->setUseDisplayList( false );
 
             // are we embedding a feature name?
             if ( _featureNameExpr.isSet() )
@@ -177,6 +183,11 @@ BuildGeometryFilter::processPolygons(FeatureList& features, FilterContext& conte
                 l2w = _local2world;
             }
 
+            // collect all the pre-transformation HAT (Z) values.
+            osg::ref_ptr<osg::FloatArray> hats = new osg::FloatArray();
+            hats->reserve( part->size() );
+            for(Geometry::const_iterator i = part->begin(); i != part->end(); ++i )
+                hats->push_back( i->z() );
 
             // build the geometry:
             tileAndBuildPolygon(part, featureSRS, mapSRS, makeECEF, true, osgGeom, w2l);
@@ -201,7 +212,7 @@ BuildGeometryFilter::processPolygons(FeatureList& features, FilterContext& conte
                     }
 
                     double threshold = osg::DegreesToRadians( *_maxAngle_deg );
-                    OE_DEBUG << "Running mesh subdivider with threshold " << *_maxAngle_deg << std::endl;
+                    OE_TEST << "Running mesh subdivider with threshold " << *_maxAngle_deg << std::endl;
 
                     MeshSubdivider ms( _world2local, _local2world );
                     if ( input->geoInterp().isSet() )
@@ -227,13 +238,18 @@ BuildGeometryFilter::processPolygons(FeatureList& features, FilterContext& conte
                 // install clamping attributes if necessary
                 if (_style.has<AltitudeSymbol>() &&
                     _style.get<AltitudeSymbol>()->technique() == AltitudeSymbol::TECHNIQUE_GPU)
-                {            
+                {
                     Clamping::applyDefaultClampingAttrs( osgGeom, input->getDouble("__oe_verticalOffset", 0.0) );
                 }
             }
+            else
+            {
+                OE_TEST << LC << "Oh no. buildAndTilePolygon returned nothing.\n";
+            }
         }
     }
     
+    OE_TEST << LC << "Num drawables = " << geode->getNumDrawables() << "\n";
     return geode;
 }
 
@@ -296,6 +312,12 @@ BuildGeometryFilter::processPolygonizedLines(FeatureList&   features,
             if ( part->size() < 2 )
                 continue;
 
+            // collect all the pre-transformation HAT (Z) values.
+            osg::ref_ptr<osg::FloatArray> hats = new osg::FloatArray();
+            hats->reserve( part->size() );
+            for(Geometry::const_iterator i = part->begin(); i != part->end(); ++i )
+                hats->push_back( i->z() );
+
             // transform the geometry into the target SRS and localize it about 
             // a local reference point.
             osg::ref_ptr<osg::Vec3Array> verts   = new osg::Vec3Array();
@@ -318,6 +340,7 @@ BuildGeometryFilter::processPolygonizedLines(FeatureList&   features,
                 _style.get<AltitudeSymbol>()->technique() == AltitudeSymbol::TECHNIQUE_GPU)
             {
                 Clamping::applyDefaultClampingAttrs( geom, input->getDouble("__oe_verticalOffset", 0.0) );
+                Clamping::setHeights( geom, hats.get() );
             }
         }
 
@@ -372,6 +395,12 @@ BuildGeometryFilter::processLines(FeatureList& features, FilterContext& context)
             if ( part->size() < 2 )
                 continue;
 
+            // collect all the pre-transformation HAT (Z) values.
+            osg::ref_ptr<osg::FloatArray> hats = new osg::FloatArray();
+            hats->reserve( part->size() );
+            for(Geometry::const_iterator i = part->begin(); i != part->end(); ++i )
+                hats->push_back( i->z() );
+
             // if the underlying geometry is a ring (or a polygon), use a line loop; otherwise
             // use a line strip.
             GLenum primMode = dynamic_cast<Ring*>(part) ? GL_LINE_LOOP : GL_LINE_STRIP;
@@ -380,8 +409,8 @@ BuildGeometryFilter::processLines(FeatureList& features, FilterContext& context)
             osg::Vec4f primaryColor = line->stroke()->color();
             
             osg::ref_ptr<osg::Geometry> osgGeom = new osg::Geometry();
-            //osgGeom->setUseVertexBufferObjects( true );
-            //osgGeom->setUseDisplayList( false );
+            osgGeom->setUseVertexBufferObjects( true );
+            osgGeom->setUseDisplayList( false );
 
             // embed the feature name if requested. Warning: blocks geometry merge optimization!
             if ( _featureNameExpr.isSet() )
@@ -437,6 +466,7 @@ BuildGeometryFilter::processLines(FeatureList& features, FilterContext& context)
                 _style.get<AltitudeSymbol>()->technique() == AltitudeSymbol::TECHNIQUE_GPU)
             {
                 Clamping::applyDefaultClampingAttrs( osgGeom, input->getDouble("__oe_verticalOffset", 0.0) );
+                Clamping::setHeights( osgGeom, hats.get() );
             }
         }
     }
@@ -479,12 +509,18 @@ BuildGeometryFilter::processPoints(FeatureList& features, FilterContext& context
             if ( !point )
                 continue;
 
+            // collect all the pre-transformation HAT (Z) values.
+            osg::ref_ptr<osg::FloatArray> hats = new osg::FloatArray();
+            hats->reserve( part->size() );
+            for(Geometry::const_iterator i = part->begin(); i != part->end(); ++i )
+                hats->push_back( i->z() );
+
             // resolve the color:
             osg::Vec4f primaryColor = point->fill()->color();
             
             osg::ref_ptr<osg::Geometry> osgGeom = new osg::Geometry();
-            //osgGeom->setUseVertexBufferObjects( true );
-            //osgGeom->setUseDisplayList( false );
+            osgGeom->setUseVertexBufferObjects( true );
+            osgGeom->setUseDisplayList( false );
 
             // embed the feature name if requested. Warning: blocks geometry merge optimization!
             if ( _featureNameExpr.isSet() )
@@ -524,6 +560,7 @@ BuildGeometryFilter::processPoints(FeatureList& features, FilterContext& context
                 _style.get<AltitudeSymbol>()->technique() == AltitudeSymbol::TECHNIQUE_GPU)
             {            
                 Clamping::applyDefaultClampingAttrs( osgGeom, input->getDouble("__oe_verticalOffset", 0.0) );
+                Clamping::setHeights( osgGeom, hats.get() );
             }
         }
     }
@@ -531,132 +568,346 @@ BuildGeometryFilter::processPoints(FeatureList& features, FilterContext& context
     return geode;
 }
 
-#define CROP_POLYS_BEFORE_TESSELLATING 1
+// Borrowed from MeshConsolidator.cpp
+template<typename FROM, typename TO>
+osg::PrimitiveSet* copy( FROM* src, unsigned offset )
+{
+    TO* newDE = new TO( src->getMode() );
+    newDE->reserve( src->size() );
+    for( typename FROM::const_iterator i = src->begin(); i != src->end(); ++i )
+        newDE->push_back( (*i) + offset );
+    return newDE;
+}
 
-void
-BuildGeometryFilter::tileAndBuildPolygon(Geometry*               ring,
-                                         const SpatialReference* featureSRS,
-                                         const SpatialReference* mapSRS,
-                                         bool                    makeECEF,
-                                         bool                    tessellate,
-                                         osg::Geometry*          osgGeom,
-                                         const osg::Matrixd      &world2local)
+
+/**
+ * Converts an osg::Geometry to use osg::DrawElementsUInt if it doesn't already.
+ * This only works on Geometries that are already using DrawElementsUInt, DrawElementsUByte, or DrawElementsUShort
+ * We do this to normalize the primitive set types so that we can merge multiple geometries 
+ * into one later down the road.
+ */
+void convertToDrawElementsUInt(osg::Geometry* geometry)
 {
-#ifdef CROP_POLYS_BEFORE_TESSELLATING
+    for (unsigned int i = 0; i < geometry->getNumPrimitiveSets(); i++)
+    {
+        osg::PrimitiveSet* ps = geometry->getPrimitiveSet(i);
+        // See if it's already a DrawElementsUInt and do nothing if it is.
+        osg::DrawElementsUInt* deUint = dynamic_cast<osg::DrawElementsUInt*>(ps);
+        if (!deUint)
+        {
+            // Copy values from the existing primitive set to a new DrawElementsUInt
+            osg::PrimitiveSet* newPS = 0;
+            if (dynamic_cast<osg::DrawElementsUByte*>(ps))
+            {
+                newPS = copy<osg::DrawElementsUByte, osg::DrawElementsUInt>(static_cast<osg::DrawElementsUByte*>(ps), 0);
+            }
+            else if (dynamic_cast<osg::DrawElementsUShort*>(ps))
+            {             
+                newPS = copy<osg::DrawElementsUShort, osg::DrawElementsUInt>(static_cast<osg::DrawElementsUShort*>(ps), 0);
+            }
 
-#define MAX_POINTS_PER_CROP_TILE 1024
+            // Set the new primitive set
+            if (newPS)
+            {
+                geometry->setPrimitiveSet(i, newPS);
+            }
+        }
+    }
+}
 
-    bool built = false;
-    unsigned count = ring->getTotalPointCount();
-    if ( count > MAX_POINTS_PER_CROP_TILE )
+/**
+ * Tesselates an osg::Geometry using the osgEarth tesselator.
+ * If it fails, fall back to the osgUtil tesselator.
+ */
+bool tesselateGeometry(osg::Geometry* geometry)
+{
+    osgEarth::Tessellator oeTess;
+    if ( !oeTess.tessellateGeometry(*geometry) )
     {
-        unsigned tiles = (count / MAX_POINTS_PER_CROP_TILE) + 1u;
-        double tx = ceil(sqrt((double)tiles));
-        double ty = tx;
-        Bounds b = ring->getBounds();
-        double tw = b.width() / tx;
-        double th = b.height() / ty;
+        osgUtil::Tessellator tess;
+        tess.setTessellationType( osgUtil::Tessellator::TESS_TYPE_GEOMETRY );
+        tess.setWindingType( osgUtil::Tessellator::TESS_WINDING_POSITIVE );
+        tess.retessellatePolygons( *geometry );
+    }
 
-        OE_DEBUG << "Found " << count << " points; cropping to " << tx << " x " << ty << std::endl;
+    // Make sure all of the primitive sets are osg::DrawElementsUInt
+    // The osgEarth tesselator will occassionally fail, and we fall back to the osgUtil::Tesselator which can produce a mix
+    // of DrawElementsUInt, DrawElementsUByte and DrawElementsUShort depending on the number of vertices.
+    convertToDrawElementsUInt(geometry);
+    return true;
+}
 
-        // Get the average Z, since GEOS will set teh Z of new verts to that of the cropping polygon,
-        // which is stupid but that's how it is.
-        double z = 0.0;
-        for(unsigned i=0; i<ring->size(); ++i)
-            z += ring->at(i).z();
-        z /= ring->size();
+/**
+ * Tiles the Geometry into the given number of columns and rows
+ */
+void tileGeometry(Geometry* geometry, const SpatialReference* featureSRS, unsigned int numCols, unsigned int numRows, GeometryCollection& out)
+{
+    // Clear the output list.
+    out.clear();
+
+    Bounds b = geometry->getBounds();
+    double tw = b.width() / (double)numCols;
+    double th = b.height() / (double)numRows;
+
+    // Get the average Z, since GEOS will set teh Z of new verts to that of the cropping polygon,
+    // which is stupid but that's how it is.
+    double z = 0.0;
+    for(unsigned i=0; i<geometry->size(); ++i)
+        z += geometry->at(i).z();
+    z /= geometry->size();
 
-        osg::ref_ptr<Polygon> poly = new Polygon;
-        poly->resize( 4 );
+    osg::ref_ptr<Polygon> poly = new Polygon;
+    poly->resize( 4 );        
 
-        built = true;
-        for(int x=0; x<(int)tx; ++x)
+    for(int x=0; x<(int)numCols; ++x)
+    {
+        for(int y=0; y<(int)numRows; ++y)
         {
-            for(int y=0; y<(int)ty; ++y)
+            (*poly)[0].set( b.xMin() + tw*(double)x,     b.yMin() + th*(double)y,     z );
+            (*poly)[1].set( b.xMin() + tw*(double)(x+1), b.yMin() + th*(double)y,     z );
+            (*poly)[2].set( b.xMin() + tw*(double)(x+1), b.yMin() + th*(double)(y+1), z );
+            (*poly)[3].set( b.xMin() + tw*(double)x,     b.yMin() + th*(double)(y+1), z );
+
+            osg::ref_ptr<Geometry> ringTile;
+            if ( geometry->crop(poly.get(), ringTile) )
             {
-                (*poly)[0].set( b.xMin() + tw*(double)x,     b.yMin() + th*(double)y,     z );
-                (*poly)[1].set( b.xMin() + tw*(double)(x+1), b.yMin() + th*(double)y,     z );
-                (*poly)[2].set( b.xMin() + tw*(double)(x+1), b.yMin() + th*(double)(y+1), z );
-                (*poly)[3].set( b.xMin() + tw*(double)x,     b.yMin() + th*(double)(y+1), z );
-                
-                osg::ref_ptr<Geometry> ringTile;
-                if ( ring->crop(poly.get(), ringTile) )
+                // Use an iterator since crop could return a multi-polygon
+                GeometryIterator gi( ringTile.get(), false );
+                while( gi.hasMore() )
                 {
-                    // Use an iterator since crop could return a multi-polygon
-                    GeometryIterator gi( ringTile.get(), false );
-                    while( gi.hasMore() )
-                    {
-                        Geometry* geom = gi.next();
-                        buildPolygon(geom, featureSRS, mapSRS, makeECEF, tessellate, osgGeom, world2local);
-                    }
+                    Geometry* geom = gi.next();
+                    out.push_back( geom );                                                
                 }
-                else 
-                {
-                    // If crop resulted in empty geometry (valid case) ringTile will still be valid,
-                    // otherwise we need to process the entire polygon without tiling.
-                    if (!ringTile.valid())
-                    {
-                        //clean up geometry
-                        osgGeom->setVertexArray(0L);
-                        if (osgGeom->getNumPrimitiveSets())
-                            osgGeom->removePrimitiveSet(0, osgGeom->getNumPrimitiveSets());
+            }
+        }
+    }
+}
 
-                        OE_NOTICE << LC << "GEOS crop failed, tessellating feature without tiling." << std::endl;
+/**
+ * Tiles the geometry up until all the cells have less than given number of points.
+ */
+void downsizeGeometry(Geometry* geometry, const SpatialReference* featureSRS, unsigned int maxPoints, GeometryCollection& out)
+{
+    // If the geometyr is greater than the maximum number of points, we need to tile it up further.
+    if (geometry->size() > maxPoints)
+    {
+        OE_NOTICE << "Downsizing geometry of size " << geometry->size() << std::endl;
+        // Tile the geometry.
+        GeometryCollection tmp;
+        tileGeometry(geometry, featureSRS, 2, 2, tmp );
+        
+        for (unsigned int i = 0; i < tmp.size(); i++)
+        {
+            Geometry* g = tmp[i].get();
 
-                        built = false;
-                        break;
-                    }
-                }
+            // If the generated geometry still has too many points, continue to downsample it recursively.
+            if (g->size() > maxPoints)
+            {
+                // We pass "out" as the destination here since downsizeGeometry will only append tiles that are less than the max size.
+                downsizeGeometry( g, featureSRS, maxPoints, out );
             }
+            else
+            {
+                // Append the geometry to the output list.
+                out.push_back( g );
+            }
+        }
+    }
+    else
+    {
+        // The geometry is valid, so add it to the output list.
+        out.push_back( geometry );
+    }
+}
 
-            // GEOS failed 
-            if (!built)
-                break;
+/**
+ * Prepares a geometry into a grid if it is too big geospatially to have a sensible local tangent plane
+ * We will also tile the geometry if it just has too many points to speed up the tesselator.
+ */
+void prepareForTesselation(Geometry* geometry, const SpatialReference* featureSRS, double targetTileSizeDeg, unsigned int maxPointsPerTile, GeometryCollection& out)
+{
+    // Clear the output list.
+    GeometryCollection tiles;
+    
+    unsigned int count = geometry->size();
+
+    unsigned int tx = 1;
+    unsigned int ty = 1;
+
+    // Tile the geometry if it's geospatial size is too large to have a sensible local tangent plane.
+    GeoExtent featureExtentDeg = GeoExtent(featureSRS, geometry->getBounds()).transform(SpatialReference::create("wgs84"));
+
+    // Tile based on the extent
+    if ( featureExtentDeg.width() > targetTileSizeDeg  || featureExtentDeg.height() > targetTileSizeDeg)
+    {
+        // Determine the tile size based on the extent.
+        tx = ceil( featureExtentDeg.width() / targetTileSizeDeg );
+        ty = ceil (featureExtentDeg.height() / targetTileSizeDeg );        
+    }
+    else if (count > maxPointsPerTile)
+    {
+        // Determine the size based on the number of points.
+        unsigned numTiles = ((double)count / (double)maxPointsPerTile) + 1u;
+        tx = ceil(sqrt((double)numTiles));
+        ty = tx;        
+    }
+
+    if (tx == 1 && ty == 1)
+    {
+        // The geometry doesn't need modified so just add it to the list.
+        tiles.push_back( geometry );
+    }
+    else
+    {
+        tileGeometry( geometry, featureSRS, tx, ty, tiles );
+    }
+
+    out.clear();
+
+#if 1
+    // Just copy the output tiles to the output.
+    std::copy(tiles.begin(), tiles.end(), std::back_inserter(out));
+#else
+    // Calling this code will recursively subdivide the cells based on the number of points they have.
+    // This works but it will produces a non-regular grid which doesn't render well in geocentric
+    // due to the curvature of the earth so we disable it for now.
+    //
+    // Reduce the size of the tiles if needed.
+    for (unsigned int i = 0; i < tiles.size(); i++)
+    {
+        if (tiles[i]->size() > maxPointsPerTile)
+        {
+            GeometryCollection tmp;
+            downsizeGeometry(tiles[i].get(), featureSRS, maxPointsPerTile, tmp);
+            std::copy(tmp.begin(), tmp.end(), std::back_inserter(out));
+        }
+        else
+        {
+            out.push_back( tiles[i].get() );
         }
     }
+#endif
+}
+
+void
+BuildGeometryFilter::tileAndBuildPolygon(Geometry*               ring,
+                                         const SpatialReference* featureSRS,
+                                         const SpatialReference* mapSRS,
+                                         bool                    makeECEF,
+                                         bool                    tessellate,
+                                         osg::Geometry*          osgGeom,
+                                         const osg::Matrixd      &world2local)
+{
+#define MAX_POINTS_PER_CROP_TILE 1024
+//#define TARGET_TILE_SIZE_EXTENT_DEGREES 5
 
-    if ( !built )
+    if ( ring == 0L )
     {
-        buildPolygon(ring, featureSRS, mapSRS, makeECEF, tessellate, osgGeom, world2local);
+        OE_WARN << LC << "Ring is NULL.\n";
+        return;
     }
     
+    // Tile the incoming polygon if necessary
+    // NB: this breaks down at higher latitudes; see https://github.com/gwaldron/osgearth/issues/746
 
-    if ( tessellate )
+    GeometryCollection tiles;
+    if (_maxPolyTilingAngle_deg.isSet())
+        prepareForTesselation( ring, featureSRS, _maxPolyTilingAngle_deg.get(), MAX_POINTS_PER_CROP_TILE, tiles);    
+    else
+        tiles.push_back( ring );
+
+    osg::ref_ptr<osg::Geode> geode = new osg::Geode;
+
+    //OE_NOTICE << LC << "TABP: tiles = " << tiles.size() << "\n";
+
+    // Process each ring independently
+    for (int ringIndex = 0; ringIndex < tiles.size(); ringIndex++)
     {
-        osgEarth::Tessellator oeTess;
-        if (!oeTess.tessellateGeometry(*osgGeom))
+        Geometry* geom = tiles[ringIndex].get();
+        if (geom)
         {
-            //fallback to osg tessellator
-            OE_DEBUG << LC << "Falling back on OSG tessellator (" << osgGeom->getName() << ")" << std::endl;
+            // temporary target geometry for this cell:
+            osg::ref_ptr<osg::Geometry> temp = new osg::Geometry();
+            temp->setVertexArray( new osg::Vec3Array() );
+
+            // establish a local plane for this cell based on its centroid:
+            GeoPoint cellCenter(featureSRS, geom->getBounds().center());
+            cellCenter.transform(mapSRS, cellCenter);                        
+            osg::Matrix world2cell;
+            cellCenter.createWorldToLocal( world2cell );
 
-            osgUtil::Tessellator tess;
-            tess.setTessellationType( osgUtil::Tessellator::TESS_TYPE_GEOMETRY );
-            tess.setWindingType( osgUtil::Tessellator::TESS_WINDING_POSITIVE );
-            tess.retessellatePolygons( *osgGeom );
+            // build the localized polygon:
+            buildPolygon(geom, featureSRS, mapSRS, makeECEF, temp.get(), world2cell);
+
+            // if successful, transform the verts back into our master LTP:
+            if ( temp->getNumPrimitiveSets() > 0 )
+            {
+                // Tesselate the polygon while the coordinates are still in the LTP
+                if (tesselateGeometry( temp.get() ))
+                {
+                    osg::Vec3Array* verts = static_cast<osg::Vec3Array*>(temp->getVertexArray());
+                    if ( verts->getNumElements() > 0 )
+                    {
+                        // Convert the coordinates back to the master LTP.
+                        // This is ok, but you will probably run into precision errors if the tile size is very large.
+                        osg::Matrix cell2world;
+                        cell2world.invert( world2cell );
+                        osg::Matrix cell2local = cell2world * world2local; // pre-multiply to avoid precision loss
+
+                        for(int i=0; i<verts->size(); ++i)
+                        {
+                            (*verts)[i] = (*verts)[i] * cell2local;
+                        }
+                        geode->addDrawable(temp.get());
+                    }
+                }
+            }
         }
-    }    
-    
-    osgUtil::SmoothingVisitor::smooth( *osgGeom );
+        else
+        {
+            OE_TEST << LC << "TABP: Uh oh. found a non-Ring geometry: " << geom->toString(geom->getComponentType()) << "\n";
+        }
+    }
 
-#else
+    // The geode is going to contain all of our polygons now, so merge them into one.
+    osgUtil::Optimizer optimizer;
+    osgUtil::Optimizer::MergeGeometryVisitor mgv;
+    // We only want one Geometry, so don't limit the number of vertices.
+    mgv.setTargetMaximumNumberOfVertices(UINT_MAX);
+    mgv.apply( *geode.get() );
 
-    // non-cropped way
-    buildPolygon(ring, featureSRS, mapSRS, makeECEF, tessellate, osgGeom, world2local);
-    if ( tessellate )
+    // and copy them into the output geometry.
+    if ( geode->getNumDrawables() > 0 )
     {
-        osgEarth::Tessellator oeTess;
-        if (!oeTess.tessellateGeometry(*osgGeom))
+        // If we have more than one drawable after the MergeGeometryVisitor ran, we have a problem so
+        // dump out some info to help debug.
+        if (geode->getNumDrawables() != 1)
         {
-            //fallback to osg tessellator
-            OE_INFO << LC << "OE Tessellation failed! Using OSG tessellator. (" << osgGeom->getName() << ")" << std::endl;
-
-            osgUtil::Tessellator tess;
-            tess.setTessellationType( osgUtil::Tessellator::TESS_TYPE_GEOMETRY );
-            tess.setWindingType( osgUtil::Tessellator::TESS_WINDING_POSITIVE );
-            tess.retessellatePolygons( *osgGeom );
+            OE_WARN << LC << "MergeGeometryVisitor failed to merge geometries into a single one.  Num drawables " << geode->getNumDrawables() << std::endl;            
+            for (unsigned int i = 0; i < geode->getNumDrawables(); i++)
+            {
+                osg::Geometry* g = geode->getDrawable(i)->asGeometry();
+                if (g)
+                {
+                    osg::Vec3Array* verts = dynamic_cast<osg::Vec3Array*>(g->getVertexArray());
+                    if (verts)
+                    {
+                        OE_WARN << "Geometry " << i << " has " << verts->size() << " verts" << std::endl;
+                        OE_WARN << "Geometry " << i << " has " << g->getNumPrimitiveSets() << " primitive sets" << std::endl;
+                        for (unsigned int j = 0; j < g->getNumPrimitiveSets(); j++)
+                        {
+                            osg::PrimitiveSet* ps = g->getPrimitiveSet(j);
+                            OE_WARN << "PrimitiveSet " << j << ps->className() << std::endl;
+                        }
+                    }
+                }
+            }
         }
+        osgGeom->setVertexArray( geode->getDrawable(0)->asGeometry()->getVertexArray() );
+        osgGeom->setPrimitiveSetList( geode->getDrawable(0)->asGeometry()->getPrimitiveSetList() );
     }
-#endif
+
+    osgUtil::SmoothingVisitor::smooth( *osgGeom );
 }
 
 // builds and tessellates a polygon (with or without holes)
@@ -665,7 +916,6 @@ BuildGeometryFilter::buildPolygon(Geometry*               ring,
                                   const SpatialReference* featureSRS,
                                   const SpatialReference* mapSRS,
                                   bool                    makeECEF,
-                                  bool                    tessellate,
                                   osg::Geometry*          osgGeom,
                                   const osg::Matrixd      &world2local)
 {
@@ -895,6 +1145,7 @@ BuildGeometryFilter::push( FeatureList& input, FilterContext& context )
         {
             switch( f->getGeometry()->getComponentType() )
             {
+            default:
             case Geometry::TYPE_LINESTRING:
             case Geometry::TYPE_RING:
                 f->style()->add( new LineSymbol() );
@@ -934,9 +1185,12 @@ BuildGeometryFilter::push( FeatureList& input, FilterContext& context )
         osg::ref_ptr<osg::Geode> geode = processPolygons(polygons, context);
         if ( geode->getNumDrawables() > 0 )
         {
+            osgUtil::Optimizer::MergeGeometryVisitor mg;
+            mg.setTargetMaximumNumberOfVertices(65536);
+            geode->accept(mg);
+
             osgUtil::Optimizer o;
             o.optimize( geode.get(), 
-                osgUtil::Optimizer::MERGE_GEOMETRY |
                 osgUtil::Optimizer::INDEX_MESH |
                 osgUtil::Optimizer::VERTEX_PRETRANSFORM |
                 osgUtil::Optimizer::VERTEX_POSTTRANSFORM );
@@ -952,9 +1206,12 @@ BuildGeometryFilter::push( FeatureList& input, FilterContext& context )
         osg::ref_ptr<osg::Geode> geode = processPolygonizedLines(polygonizedLines, twosided, context);
         if ( geode->getNumDrawables() > 0 )
         {
+            osgUtil::Optimizer::MergeGeometryVisitor mg;
+            mg.setTargetMaximumNumberOfVertices(65536);
+            geode->accept(mg);
+
             osgUtil::Optimizer o;
             o.optimize( geode.get(), 
-                osgUtil::Optimizer::MERGE_GEOMETRY |
                 osgUtil::Optimizer::INDEX_MESH |
                 osgUtil::Optimizer::VERTEX_PRETRANSFORM |
                 osgUtil::Optimizer::VERTEX_POSTTRANSFORM );
@@ -969,9 +1226,9 @@ BuildGeometryFilter::push( FeatureList& input, FilterContext& context )
         osg::ref_ptr<osg::Geode> geode = processLines(lines, context);
         if ( geode->getNumDrawables() > 0 )
         {
-            osgUtil::Optimizer o;
-            o.optimize( geode.get(), 
-                osgUtil::Optimizer::MERGE_GEOMETRY );
+            osgUtil::Optimizer::MergeGeometryVisitor mg;
+            mg.setTargetMaximumNumberOfVertices(65536);
+            geode->accept(mg);
 
             applyLineSymbology( geode->getOrCreateStateSet(), line );
             result->addChild( geode.get() );
@@ -984,9 +1241,9 @@ BuildGeometryFilter::push( FeatureList& input, FilterContext& context )
         osg::ref_ptr<osg::Geode> geode = processPoints(points, context);
         if ( geode->getNumDrawables() > 0 )
         {
-            osgUtil::Optimizer o;
-            o.optimize( geode.get(), 
-                osgUtil::Optimizer::MERGE_GEOMETRY );
+            osgUtil::Optimizer::MergeGeometryVisitor mg;
+            mg.setTargetMaximumNumberOfVertices(65536);
+            geode->accept(mg);
 
             applyPointSymbology( geode->getOrCreateStateSet(), point );
             result->addChild( geode.get() );
@@ -1014,4 +1271,4 @@ BuildGeometryFilter::push( FeatureList& input, FilterContext& context )
     {
         return 0L;
     }
-}
+}
\ No newline at end of file
diff --git a/src/osgEarthFeatures/BuildTextFilter b/src/osgEarthFeatures/BuildTextFilter
index 0389a33..c214f47 100644
--- a/src/osgEarthFeatures/BuildTextFilter
+++ b/src/osgEarthFeatures/BuildTextFilter
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthFeatures/BuildTextFilter.cpp b/src/osgEarthFeatures/BuildTextFilter.cpp
index 8d2db19..71305df 100644
--- a/src/osgEarthFeatures/BuildTextFilter.cpp
+++ b/src/osgEarthFeatures/BuildTextFilter.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthFeatures/BuildTextOperator b/src/osgEarthFeatures/BuildTextOperator
deleted file mode 100644
index 602796e..0000000
--- a/src/osgEarthFeatures/BuildTextOperator
+++ /dev/null
@@ -1,54 +0,0 @@
-/* -*-c++-*- */
-/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
-* http://osgearth.org
-*
-* osgEarth is free software; you can redistribute it and/or modify
-* it under the terms of the GNU Lesser General Public License as published by
-* the Free Software Foundation; either version 2 of the License, or
-* (at your option) any later version.
-*
-* 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.
-*
-* You should have received a copy of the GNU Lesser General Public License
-* along with this program.  If not, see <http://www.gnu.org/licenses/>
-*/
-
-#ifndef OSGEARTHSYMBOLOGY_MARKER_SYMBOLIZER_H
-#define OSGEARTHSYMBOLOGY_MARKER_SYMBOLIZER_H 1
-
-#include <osgEarthFeatures/Common>
-#include <osgEarthFeatures/Feature>
-#include <osgEarthFeatures/Filter>
-#include <osgEarthSymbology/TextSymbol>
-#include <osg/Node>
-
-namespace osgEarth { namespace Features
-{
-    /**
-     * Creates a text node that labels feature data.
-     */
-    class OSGEARTHFEATURES_EXPORT BuildTextOperator
-    {
-    public:
-        BuildTextOperator(bool hideClutter=false) : _hideClutter(hideClutter) { };
-        virtual ~BuildTextOperator() { }
-    public:
-        osg::Node* operator()(
-            const FeatureList& features, 
-            const osgEarth::Symbology::TextSymbol *symbol,
-            const FilterContext& context);
-
-    protected:
-        bool _hideClutter;
-    };
-
-} } // namespace osgEarth::Features
-
-#endif
diff --git a/src/osgEarthFeatures/BuildTextOperator.cpp b/src/osgEarthFeatures/BuildTextOperator.cpp
deleted file mode 100644
index 9faca1f..0000000
--- a/src/osgEarthFeatures/BuildTextOperator.cpp
+++ /dev/null
@@ -1,241 +0,0 @@
-/* -*-c++-*- */
-/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
- * http://osgearth.org
- *
- * osgEarth is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>
- */
-#if 0
-#include <osgEarthFeatures/BuildTextOperator>
-#include <osgEarth/Utils>
-#include <osgDB/ReadFile>
-#include <osgDB/ReaderWriter>
-#include <osg/Geometry>
-#include <osg/MatrixTransform>
-#include <osg/Material>
-#include <osg/Geode>
-#include <osg/Version>
-#include <osg/Geometry>
-#include <osg/LineWidth>
-#include <osg/Point>
-#include <osg/Depth>
-#include <osg/PolygonOffset>
-#include <osg/ClusterCullingCallback>
-#include <osgText/Text>
-#include <osgUtil/IntersectionVisitor>
-#include <osgUtil/PolytopeIntersector>
-
-#define LC "[BuildTextOperator] "
-
-using namespace osgEarth::Symbology;
-using namespace osgEarth::Features;
-
-// Parse a content string and replace attributes (marked with delim) with their value
-// eg. "City [name], [state]" -> "City San Fransisco, California" if delim is "[]"
-static std::string parseAttributes(Feature*           feature, 
-                                   const std::string& content,
-                                   const std::string& delim)
-{
-    if (delim.size()<2)
-        return content;
-
-    std::string out;
-    size_t pos = 0;
-    while(true) {
-        // Search for an attribute delimiter
-        size_t d = content.find_first_of(delim[0], pos);
-        if (d==std::string::npos) {
-            // No more delimiters? Add remaining text and we're done
-            out += content.substr(pos);
-            break;
-        }
-        // An attribute was found!
-        // Add non-attribute text
-        out += content.substr(pos, d-pos);
-        pos = d+1;
-        // Extract attribute name
-        d = content.find_first_of(delim[1], pos);
-        if (d==std::string::npos) {
-            // No more delimiters? Add remaining text and we're done
-            out += content.substr(pos);
-            break;
-        }
-        // Add attribute and continue
-        out += feature->getString( content.substr(pos, d-pos) );
-        pos = d+1;
-    }
-
-    return out;
-}
-
-osg::Node* BuildTextOperator::operator()(const FeatureList&   features, 
-                                         const TextSymbol*    symbol,
-                                         const FilterContext& context)
-{
-    if (!symbol) return 0;
-
-    std::set< std::string > labelNames;
-
-    bool removeDuplicateLabels = symbol->removeDuplicateLabels().isSet() ? symbol->removeDuplicateLabels().get() : false;
-
-    StringExpression contentExpr = *symbol->content();
-
-    osg::Geode* result = new osg::Geode;
-    for (FeatureList::const_iterator itr = features.begin(); itr != features.end(); ++itr)
-    {
-        Feature* feature = itr->get();
-        if (!feature->getGeometry()) continue;
-
-        std::string text;
-        if (symbol->content().isSet())
-        {
-            //Get the text from the specified content and referenced attributes
-            text = feature->eval( contentExpr, &context );
-        }
-
-        if (text.empty()) continue;
-
-        //See if there is a duplicate name
-        if (removeDuplicateLabels && labelNames.find(text) != labelNames.end()) continue;
-
-        bool rotateToScreen = symbol->rotateToScreen().isSet() ? symbol->rotateToScreen().value() : false;
-
-        // find the centroid
-        osg::Vec3d position;
-        osg::Quat orientation;
-
-        GeometryIterator gi( feature->getGeometry() );
-        while( gi.hasMore() )
-        {
-            Geometry* geom = gi.next();
-
-            TextSymbol::LinePlacement linePlacement = symbol->linePlacement().isSet() ? symbol->linePlacement().get() : TextSymbol::LINEPLACEMENT_ALONG_LINE;
-            if (geom->getType() == Symbology::Geometry::TYPE_LINESTRING && linePlacement == TextSymbol::LINEPLACEMENT_ALONG_LINE)
-            {
-                //Compute the "middle" of the line string
-                LineString* lineString = static_cast<LineString*>(geom);
-                double length = lineString->getLength();
-                double center = length / 2.0;
-                osg::Vec3d start, end;
-                if (lineString->getSegment(center, start, end))
-                {
-                    TextSymbol::LineOrientation lineOrientation = symbol->lineOrientation().isSet() ? symbol->lineOrientation().get() : TextSymbol::LINEORIENTATION_HORIZONTAL;
-
-                    position = (end + start) / 2.0;
-                    //We don't want to orient the text at all if we are rotating to the screen
-                    if (!rotateToScreen && lineOrientation != TextSymbol::LINEORIENTATION_HORIZONTAL)
-                    {
-                        osg::Vec3d dir = (end-start);
-                        dir.normalize();
-
-                        if (lineOrientation == TextSymbol::LINEORIENTATION_PERPENDICULAR)
-                        {
-                            osg::Vec3d up(0,0,1);
-                            const SpatialReference* srs = context.profile()->getSRS();
-                            if (srs && context.isGeocentric() && srs->getEllipsoid())
-                            {
-                                osg::Vec3d w = context.toWorld( position );
-                                up = srs->getEllipsoid()->computeLocalUpVector(w.x(), w.y(), w.z());
-                            }
-                            dir = up ^ dir;
-                        }
-                        orientation.makeRotate(osg::Vec3d(1,0,0), dir);
-                    }                
-                }
-                else
-                {
-                    //Fall back on using the center
-                    position = lineString->getBounds().center();
-                }
-            }
-            else
-            {
-                position = geom->getBounds().center();
-            }
-        }
-
-        osgText::Text* t = new osgText::Text();
-        t->setText( text );
-
-        std::string font = "fonts/arial.ttf";
-        if (symbol->font().isSet() && !symbol->font().get().empty())
-        {
-            font = symbol->font().value();
-        }
-
-        t->setFont( font );
-        t->setAutoRotateToScreen( rotateToScreen );
-
-        TextSymbol::SizeMode sizeMode = symbol->sizeMode().isSet() ? symbol->sizeMode().get() : TextSymbol::SIZEMODE_SCREEN;
-        if (sizeMode == TextSymbol::SIZEMODE_SCREEN) {
-            t->setCharacterSizeMode( osgText::TextBase::SCREEN_COORDS );
-        }
-        else if (sizeMode == TextSymbol::SIZEMODE_OBJECT) {
-            t->setCharacterSizeMode( osgText::TextBase::OBJECT_COORDS );
-        }
-        float size = symbol->size().isSet() ? symbol->size().get() : 32.0f;
-        t->setCharacterSize( size );
-        /*
-        //TODO:  We need to do something to account for autotransformed text that is under a LOD.  Setting the initial bound works sometimes but not all the time.
-        if (rotateToScreen)
-        {
-        //Set the initial bound so that OSG will traverse the text even if it's under an LOD.
-        osg::BoundingBox bb;
-        bb.expandBy( osg::BoundingSphere(position, size));
-        t->setInitialBound( bb);
-        }*/
-        //t->setCharacterSizeMode( osgText::TextBase::OBJECT_COORDS_WITH_MAXIMUM_SCREEN_SIZE_CAPPED_BY_FONT_HEIGHT );
-        //t->setCharacterSize( 300000.0f );
-        t->setPosition( position );
-        t->setRotation( orientation);
-        t->setAlignment( osgText::TextBase::CENTER_CENTER );
-        t->getOrCreateStateSet()->setAttributeAndModes( new osg::Depth(osg::Depth::ALWAYS), osg::StateAttribute::ON );
-        t->getOrCreateStateSet()->setRenderBinDetails( 99999, "RenderBin", osg::StateSet::OVERRIDE_RENDERBIN_DETAILS );
-
-        // apply styling as appropriate:
-        osg::Vec4f textColor = symbol->fill()->color();
-        osg::Vec4f haloColor = symbol->halo()->color();
-
-        t->setColor( textColor );
-        t->setBackdropColor( haloColor );
-        t->setBackdropType( osgText::Text::OUTLINE );
-
-        if ( context.isGeocentric() )
-        {
-            // install a cluster culler
-            t->setCullCallback( new CullDrawableByNormal(position * context.inverseReferenceFrame()) );
-        }
-
-        if (_hideClutter)
-        {
-            osg::BoundingBox tBound = t->getBound();
-            osg::ref_ptr<osgUtil::PolytopeIntersector> intersector = new osgUtil::PolytopeIntersector(osgUtil::Intersector::MODEL, tBound.xMin(), tBound.yMin(), tBound.xMax(), tBound.yMax());
-            osgUtil::IntersectionVisitor intersectVisitor(intersector.get());
-            result->accept(intersectVisitor);
-
-            if (!intersector->containsIntersections())
-            {
-                result->addDrawable( t );
-                if (removeDuplicateLabels) labelNames.insert(text);
-            }
-        }
-        else
-        {
-            result->addDrawable( t );
-            if (removeDuplicateLabels) labelNames.insert(text);
-        }
-    }
-    return result;
-}
-#endif
diff --git a/src/osgEarthFeatures/CMakeLists.txt b/src/osgEarthFeatures/CMakeLists.txt
index c3868e0..b7c9575 100644
--- a/src/osgEarthFeatures/CMakeLists.txt
+++ b/src/osgEarthFeatures/CMakeLists.txt
@@ -10,13 +10,13 @@ ENDIF(GEOS_FOUND)
 
 SET(LIB_NAME osgEarthFeatures)
 
+
 SET(HEADER_PATH ${OSGEARTH_SOURCE_DIR}/include/${LIB_NAME})
 SET(LIB_PUBLIC_HEADERS
     AltitudeFilter
     BufferFilter
     BuildGeometryFilter  
     BuildTextFilter
-    BuildTextOperator
     CentroidFilter
     Common
     ConvertTypeFilter
@@ -38,7 +38,7 @@ SET(LIB_PUBLIC_HEADERS
     GeometryCompiler
     GeometryUtils
     LabelSource
-    MeshClamper
+    MVT
     OgrUtils
     OptimizerHints
     PolygonizeLines
@@ -48,6 +48,7 @@ SET(LIB_PUBLIC_HEADERS
     ScatterFilter
     Script
     ScriptEngine
+    ScriptFilter
     SubstituteModelFilter
     TessellateOperator
     TextSymbolizer
@@ -55,13 +56,11 @@ SET(LIB_PUBLIC_HEADERS
     VirtualFeatureSource
 )
 
-ADD_LIBRARY(${LIB_NAME} ${OSGEARTH_USER_DEFINED_DYNAMIC_OR_STATIC}
-    ${LIB_PUBLIC_HEADERS}
+SET(TARGET_SRC
     AltitudeFilter.cpp
     BufferFilter.cpp
     BuildGeometryFilter.cpp 
     BuildTextFilter.cpp
-    BuildTextOperator.cpp
     CentroidFilter.cpp
     ConvertTypeFilter.cpp
     CropFilter.cpp
@@ -70,7 +69,7 @@ ADD_LIBRARY(${LIB_NAME} ${OSGEARTH_USER_DEFINED_DYNAMIC_OR_STATIC}
     FeatureCursor.cpp
     FeatureDisplayLayout.cpp
     FeatureDrawSet.cpp
-	FeatureListSource.cpp
+    FeatureListSource.cpp
     FeatureModelGraph.cpp
     FeatureModelSource.cpp
     FeatureSource.cpp
@@ -79,9 +78,9 @@ ADD_LIBRARY(${LIB_NAME} ${OSGEARTH_USER_DEFINED_DYNAMIC_OR_STATIC}
     Filter.cpp
     FilterContext.cpp
     GeometryCompiler.cpp
-	GeometryUtils.cpp
+    GeometryUtils.cpp
     LabelSource.cpp
-    MeshClamper.cpp
+    MVT.cpp
     OgrUtils.cpp
     OptimizerHints.cpp
     PolygonizeLines.cpp
@@ -90,14 +89,39 @@ ADD_LIBRARY(${LIB_NAME} ${OSGEARTH_USER_DEFINED_DYNAMIC_OR_STATIC}
     Session.cpp
     ScatterFilter.cpp
     ScriptEngine.cpp
+    ScriptFilter.cpp
     SubstituteModelFilter.cpp
     TessellateOperator.cpp
     TextSymbolizer.cpp
     TransformFilter.cpp
-    VirtualFeatureSource.cpp
+    VirtualFeatureSource.cpp    
 )
 
-INCLUDE_DIRECTORIES(${GDAL_INCLUDE_DIR} )
+IF(PROTOBUF_FOUND AND PROTOBUF_PROTOC_EXECUTABLE)
+
+  INCLUDE_DIRECTORIES(${PROTOBUF_INCLUDE_DIR} ${CMAKE_CURRENT_BINARY_DIR})
+  PROTOBUF_GENERATE_CPP(PROTO_VECTOR_TILE_CPP PROTO_VECTOR_TILE_H vector_tile.proto)
+
+  SET(LIB_PUBLIC_HEADERS
+    ${LIB_PUBLIC_HEADERS}
+    ${PROTO_VECTOR_TILE_H}
+  )
+
+  SET(TARGET_SRC
+    ${TARGET_SRC}
+    ${PROTO_VECTOR_TILE_CPP}
+  )
+
+  ADD_DEFINITIONS(-DOSGEARTH_HAVE_MVT)
+
+ENDIF()
+
+ADD_LIBRARY(${LIB_NAME} ${OSGEARTH_USER_DEFINED_DYNAMIC_OR_STATIC}
+    ${LIB_PUBLIC_HEADERS}
+    ${TARGET_SRC}
+)
+
+INCLUDE_DIRECTORIES(${GDAL_INCLUDE_DIR})
 
 
 IF (WIN32)
@@ -111,7 +135,14 @@ LINK_INTERNAL(${LIB_NAME}
     osgEarthSymbology
 )
 
-LINK_WITH_VARIABLES(${LIB_NAME} OSG_LIBRARY OSGUTIL_LIBRARY OSGSIM_LIBRARY OSGTERRAIN_LIBRARY OSGDB_LIBRARY OSGFX_LIBRARY OSGVIEWER_LIBRARY OSGTEXT_LIBRARY OSGGA_LIBRARY OPENTHREADS_LIBRARY)
+SET(LINK_VARS OSG_LIBRARY OSGUTIL_LIBRARY OSGSIM_LIBRARY OSGTERRAIN_LIBRARY OSGDB_LIBRARY OSGFX_LIBRARY OSGVIEWER_LIBRARY OSGTEXT_LIBRARY OSGGA_LIBRARY OPENTHREADS_LIBRARY)
+IF(PROTOBUF_FOUND AND PROTOBUF_PROTOC_EXECUTABLE)
+  SET(LINK_VARS ${LINK_VARS} PROTOBUF_LIBRARY)
+ENDIF()
+
+
+
+LINK_WITH_VARIABLES(${LIB_NAME} ${LINK_VARS})
 
 LINK_CORELIB_DEFAULT(${LIB_NAME} ${CMAKE_THREAD_LIBS_INIT} ${MATH_LIBRARY})
 
diff --git a/src/osgEarthFeatures/CentroidFilter b/src/osgEarthFeatures/CentroidFilter
index 536b99e..814c5d2 100644
--- a/src/osgEarthFeatures/CentroidFilter
+++ b/src/osgEarthFeatures/CentroidFilter
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthFeatures/CentroidFilter.cpp b/src/osgEarthFeatures/CentroidFilter.cpp
index 1695038..78057c7 100644
--- a/src/osgEarthFeatures/CentroidFilter.cpp
+++ b/src/osgEarthFeatures/CentroidFilter.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthFeatures/Common b/src/osgEarthFeatures/Common
index e4ded2f..5ee2257 100644
--- a/src/osgEarthFeatures/Common
+++ b/src/osgEarthFeatures/Common
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthFeatures/ConvertTypeFilter b/src/osgEarthFeatures/ConvertTypeFilter
index 327aec2..d78458c 100644
--- a/src/osgEarthFeatures/ConvertTypeFilter
+++ b/src/osgEarthFeatures/ConvertTypeFilter
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthFeatures/ConvertTypeFilter.cpp b/src/osgEarthFeatures/ConvertTypeFilter.cpp
index def3597..62aec86 100644
--- a/src/osgEarthFeatures/ConvertTypeFilter.cpp
+++ b/src/osgEarthFeatures/ConvertTypeFilter.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthFeatures/CropFilter b/src/osgEarthFeatures/CropFilter
index 0da8958..ec2f9bf 100644
--- a/src/osgEarthFeatures/CropFilter
+++ b/src/osgEarthFeatures/CropFilter
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthFeatures/CropFilter.cpp b/src/osgEarthFeatures/CropFilter.cpp
index dc937ea..88331cb 100644
--- a/src/osgEarthFeatures/CropFilter.cpp
+++ b/src/osgEarthFeatures/CropFilter.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthFeatures/ExtrudeGeometryFilter b/src/osgEarthFeatures/ExtrudeGeometryFilter
index 13617ea..a927bb1 100644
--- a/src/osgEarthFeatures/ExtrudeGeometryFilter
+++ b/src/osgEarthFeatures/ExtrudeGeometryFilter
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -70,7 +70,8 @@ namespace osgEarth { namespace Features
         /**
          * Sets the maximum wall angle that doesn't require a new normal vector
          */
-        void setWallAngleThreshold( float angle_deg ) { _wallAngleThresh_deg = angle_deg; }
+        void setWallAngleThreshold(float value) { _wallAngleThresh_deg = value; }
+        float getWallAngleThreshold() const { return _wallAngleThresh_deg; }
 
         /**
          * Sets whether to render a bottom top. Useful for creating stencil volumes.
@@ -85,16 +86,10 @@ namespace osgEarth { namespace Features
         const StringExpression& getFeatureNameExpr() const { return _featureNameExpr; }
 
         /**
-         * Whether or not to use vertex buffer objects
+         * Whether to merge geometry for better rendering performance
          */
-        optional<bool>& useVertexBufferObjects() { return _useVertexBufferObjects;}
-        const optional<bool>& useVertexBufferObjects() const { return _useVertexBufferObjects;}
-
-        /**
-         * Whether or not to use TextureArrays for the wall and roof skins
-         */
-        optional<bool>& useTextureArrays() { return _useTextureArrays;}
-        const optional<bool>& useTextureArrays() const { return _useTextureArrays;}
+        void setMergeGeometry(bool value) { _mergeGeometry = value; }
+        bool getMergeGeometry() const { return _mergeGeometry; }
 
 
     protected:
@@ -156,19 +151,16 @@ namespace osgEarth { namespace Features
         SortedGeodeMap                 _geodes;
         osg::ref_ptr<osg::StateSet>    _noTextureStateSet;
 
-        optional<double>               _maxAngle_deg;
-        optional<bool>                 _mergeGeometry;
+        bool                           _mergeGeometry;
         float                          _wallAngleThresh_deg;
         float                          _cosWallAngleThresh;
         StringExpression               _featureNameExpr;
         osg::ref_ptr<HeightCallback>   _heightCallback;
         optional<NumericExpression>    _heightExpr;
         bool                           _makeStencilVolume;
-        optional<bool>                 _useVertexBufferObjects;
 
         Style                          _style;
         bool                           _styleDirty;
-        optional<bool>                 _useTextureArrays;
         bool                           _gpuClamping;
 
         osg::ref_ptr<const ExtrusionSymbol> _extrusionSymbol;
diff --git a/src/osgEarthFeatures/ExtrudeGeometryFilter.cpp b/src/osgEarthFeatures/ExtrudeGeometryFilter.cpp
index 53e5499..28f1e15 100644
--- a/src/osgEarthFeatures/ExtrudeGeometryFilter.cpp
+++ b/src/osgEarthFeatures/ExtrudeGeometryFilter.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -75,16 +75,13 @@ namespace
 //------------------------------------------------------------------------
 
 ExtrudeGeometryFilter::ExtrudeGeometryFilter() :
-_maxAngle_deg          ( 5.0 ),
 _mergeGeometry         ( true ),
 _wallAngleThresh_deg   ( 60.0 ),
 _styleDirty            ( true ),
 _makeStencilVolume     ( false ),
-_useVertexBufferObjects( true ),
-_useTextureArrays      ( true ),
 _gpuClamping           ( false )
 {
-    //NOP
+    _cosWallAngleThresh = cos( _wallAngleThresh_deg );
 }
 
 void
@@ -377,8 +374,11 @@ ExtrudeGeometryFilter::buildStructure(const Geometry*         input,
             }
 
             // transform into target SRS.
-            transformAndLocalize( corner->base, srs, corner->base, mapSRS, _world2local, makeECEF );
-            transformAndLocalize( corner->roof, srs, corner->roof, mapSRS, _world2local, makeECEF );
+            if (srs)
+            {
+                transformAndLocalize( corner->base, srs, corner->base, mapSRS, _world2local, makeECEF );
+                transformAndLocalize( corner->roof, srs, corner->roof, mapSRS, _world2local, makeECEF );
+            }
 
             // cache the length for later use.
             corner->height = (corner->roof - corner->base).length();
@@ -950,7 +950,6 @@ ExtrudeGeometryFilter::process( FeatureList& features, FilterContext& context )
             Geometry* part = iter.next();
 
             osg::ref_ptr<osg::Geometry> walls = new osg::Geometry();
-            //walls->setUseVertexBufferObjects( _useVertexBufferObjects.get() );
             
             osg::ref_ptr<osg::Geometry> rooflines = 0L;
             osg::ref_ptr<osg::Geometry> baselines = 0L;
@@ -1067,7 +1066,7 @@ ExtrudeGeometryFilter::process( FeatureList& features, FilterContext& context )
                 if ( wallSkin )
                 {
                     // Get a stateset for the individual wall stateset
-                    context.resourceCache()->getOrCreateStateSet( wallSkin, wallStateSet );
+                    context.resourceCache()->getOrCreateStateSet(wallSkin, wallStateSet, context.getDBOptions());
                 }
             }
 
@@ -1085,7 +1084,7 @@ ExtrudeGeometryFilter::process( FeatureList& features, FilterContext& context )
                 if ( roofSkin )
                 {
                     // Get a stateset for the individual roof skin
-                    context.resourceCache()->getOrCreateStateSet( roofSkin, roofStateSet );
+                    context.resourceCache()->getOrCreateStateSet(roofSkin, roofStateSet, context.getDBOptions());
                 }
             }
 
@@ -1204,19 +1203,19 @@ ExtrudeGeometryFilter::push( FeatureList& input, FilterContext& context )
 
     if ( _mergeGeometry == true && _featureNameExpr.empty() )
     {
-        osgUtil::Optimizer o;
-
-        unsigned mask = osgUtil::Optimizer::MERGE_GEOMETRY;
+        osgUtil::Optimizer::MergeGeometryVisitor mg;
+        mg.setTargetMaximumNumberOfVertices(65536);
+        group->accept(mg);
 
         // Because the mesh optimizers damaga line geometry.
         if ( !_outlineSymbol.valid() )
         {
-            mask |= osgUtil::Optimizer::INDEX_MESH;
-            mask |= osgUtil::Optimizer::VERTEX_PRETRANSFORM;
-            mask |= osgUtil::Optimizer::VERTEX_POSTTRANSFORM;
+            osgUtil::Optimizer o;
+            o.optimize(group,
+                osgUtil::Optimizer::INDEX_MESH |
+                osgUtil::Optimizer::VERTEX_PRETRANSFORM |
+                osgUtil::Optimizer::VERTEX_POSTTRANSFORM );
         }
-
-        o.optimize( group, mask );
     }
 
     // Prepare buffer objects.
diff --git a/src/osgEarthFeatures/Feature b/src/osgEarthFeatures/Feature
index 808fdd7..136e158 100644
--- a/src/osgEarthFeatures/Feature
+++ b/src/osgEarthFeatures/Feature
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -35,6 +35,7 @@ namespace osgEarth { namespace Features
     using namespace osgEarth;
     using namespace osgEarth::Symbology;
     class FilterContext;
+    class Session;
 
     /**
      * Metadata and schema information for feature data.
@@ -155,6 +156,11 @@ namespace osgEarth { namespace Features
         FeatureID getFID() const;
 
         /**
+         * Set the FID of this feature.
+         */
+        void setFID(FeatureID fid);
+
+        /**
          * The geometry in this feature.
          */
         void setGeometry( Symbology::Geometry* geom );
@@ -193,6 +199,7 @@ namespace osgEarth { namespace Features
         void set( const std::string& name, double value );
         void set( const std::string& name, int value );
         void set( const std::string& name, bool value );
+        void set( const std::string& name, const AttributeValue& value);
 
         /** Sets the attribute to NULL */         
         void setNull( const std::string& name );
@@ -219,10 +226,12 @@ namespace osgEarth { namespace Features
         const optional<GeoInterpolation>& geoInterp() const { return _geoInterp; }
 
         /** populates the variables of an expression with attribute values and evals the expression. */
-        double eval( NumericExpression& expr, FilterContext const* context=0L ) const;
+        double eval(NumericExpression& expr, FilterContext const* context=0L) const;
+        double eval(NumericExpression& expr, Session* session) const;
         
         /** populates the variables of an expression with attribute values and evals the expression. */
-        const std::string& eval( StringExpression& expr, FilterContext const* context=0L ) const;
+        const std::string& eval(StringExpression& expr, FilterContext const* context=0L) const;
+        const std::string& eval(StringExpression& expr, Session* session) const;
 
     public:
         /** Gets a GeoJSON representation of this Feature */
diff --git a/src/osgEarthFeatures/Feature.cpp b/src/osgEarthFeatures/Feature.cpp
index fbe6e47..998f5f0 100644
--- a/src/osgEarthFeatures/Feature.cpp
+++ b/src/osgEarthFeatures/Feature.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -17,8 +17,9 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>
  */
 #include <osgEarthFeatures/Feature>
-#include <osgEarth/StringUtils>
+#include <osgEarthFeatures/Session>
 #include <osgEarthFeatures/GeometryUtils>
+#include <osgEarth/StringUtils>
 #include <osgEarth/JsonUtils>
 #include <algorithm>
 
@@ -182,6 +183,12 @@ Feature::getFID() const
 }
 
 void
+Feature::setFID(FeatureID fid)
+{
+    _fid = fid;
+}
+
+void
 Feature::setSRS( const SpatialReference* srs )
 {
     _srs = srs;
@@ -231,6 +238,12 @@ Feature::set( const std::string& name, int value )
 }
 
 void
+Feature::set( const std::string& name, const AttributeValue& value)
+{
+    _attrs[ name ] = value;
+}
+
+void
 Feature::set( const std::string& name, bool value )
 {
     AttributeValue& a = _attrs[name];
@@ -310,7 +323,7 @@ Feature::eval( NumericExpression& expr, FilterContext const* context ) const
       {
         val = ai->second.getDouble(0.0);
       }
-      else if (context)
+      else if (context && context->getSession())
       {
         //No attr found, look for script
         ScriptEngine* engine = context->getSession()->getScriptEngine();
@@ -331,6 +344,42 @@ Feature::eval( NumericExpression& expr, FilterContext const* context ) const
     return expr.eval();
 }
 
+double
+Feature::eval(NumericExpression& expr, Session* session) const
+{
+    const NumericExpression::Variables& vars = expr.variables();
+    for( NumericExpression::Variables::const_iterator i = vars.begin(); i != vars.end(); ++i )
+    {
+        double val = 0.0;
+        AttributeTable::const_iterator ai = _attrs.find(toLower(i->first));
+        if (ai != _attrs.end())
+        {
+            val = ai->second.getDouble(0.0);
+        }
+        else if (session)
+        {
+            //No attr found, look for script
+            ScriptEngine* engine = session->getScriptEngine();
+            if (engine)
+            {
+                ScriptResult result = engine->run(i->first, this);
+                if (result.success())
+                {
+                    val = result.asDouble();
+                }
+                else
+                {
+                    OE_WARN << LC << "Feature Script error on '" << expr.expr() << "': " << result.message() << std::endl;
+                }
+            }
+        }
+
+        expr.set( *i, val );
+    }
+
+    return expr.eval();
+}
+
 const std::string&
 Feature::eval( StringExpression& expr, FilterContext const* context ) const
 {
@@ -343,7 +392,7 @@ Feature::eval( StringExpression& expr, FilterContext const* context ) const
       {
         val = ai->second.getString();
       }
-      else if (context)
+      else if (context && context->getSession())
       {
         //No attr found, look for script
         ScriptEngine* engine = context->getSession()->getScriptEngine();
@@ -363,6 +412,38 @@ Feature::eval( StringExpression& expr, FilterContext const* context ) const
     return expr.eval();
 }
 
+const std::string&
+Feature::eval(StringExpression& expr, Session* session) const
+{
+    const StringExpression::Variables& vars = expr.variables();
+    for( StringExpression::Variables::const_iterator i = vars.begin(); i != vars.end(); ++i )
+    {
+        std::string val = "";
+        AttributeTable::const_iterator ai = _attrs.find(toLower(i->first));
+        if (ai != _attrs.end())
+        {
+            val = ai->second.getString();
+        }
+        else if (session)
+        {
+            //No attr found, look for script
+            ScriptEngine* engine = session->getScriptEngine();
+            if (engine)
+            {
+                ScriptResult result = engine->run(i->first, this);
+                if (result.success())
+                    val = result.asString();
+                else
+                    OE_WARN << LC << "Feature Script error on '" << expr.expr() << "': " << result.message() << std::endl;
+            }
+        }
+
+        expr.set( *i, val );
+    }
+
+    return expr.eval();
+}
+
 
 bool
 Feature::getWorldBound(const SpatialReference* srs,
diff --git a/src/osgEarthFeatures/FeatureCursor b/src/osgEarthFeatures/FeatureCursor
index da3ca6f..8fcc347 100644
--- a/src/osgEarthFeatures/FeatureCursor
+++ b/src/osgEarthFeatures/FeatureCursor
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -52,7 +52,7 @@ namespace osgEarth { namespace Features
     class OSGEARTHFEATURES_EXPORT FeatureListCursor : public FeatureCursor
     {
     public:
-        FeatureListCursor( const FeatureList& input, bool cloneFeatures =false );
+        FeatureListCursor(const FeatureList& input);
         
         virtual ~FeatureListCursor() { }
 
diff --git a/src/osgEarthFeatures/FeatureCursor.cpp b/src/osgEarthFeatures/FeatureCursor.cpp
index 76db756..2c0050d 100644
--- a/src/osgEarthFeatures/FeatureCursor.cpp
+++ b/src/osgEarthFeatures/FeatureCursor.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -35,9 +35,9 @@ FeatureCursor::fill( FeatureList& list )
 
 //---------------------------------------------------------------------------
 
-FeatureListCursor::FeatureListCursor( const FeatureList& features, bool clone ) :
+FeatureListCursor::FeatureListCursor(const FeatureList& features) :
 _features( features ),
-_clone   ( clone )
+_clone   ( false )
 {
     _iter = _features.begin();
 }
@@ -58,7 +58,7 @@ FeatureListCursor::nextFeature()
 
 //---------------------------------------------------------------------------
 
-GeometryFeatureCursor::GeometryFeatureCursor( Geometry* geom ) :
+GeometryFeatureCursor::GeometryFeatureCursor(Geometry* geom) :
 _geom( geom )
 {
     //nop
@@ -92,13 +92,22 @@ GeometryFeatureCursor::nextFeature()
 
         FilterContext cx;
         cx.setProfile( _featureProfile.get() );
+
         FeatureList list;
         list.push_back( _lastFeature.get() );
+
         for( FeatureFilterList::const_iterator i = _filters.begin(); i != _filters.end(); ++i )
         {
             cx = i->get()->push( list, cx );
         }
+
+        if ( list.empty() )
+        {
+            _lastFeature = 0L;
+        }
+
         _geom = 0L;
     }
+
     return _lastFeature.get();
 }
diff --git a/src/osgEarthFeatures/FeatureDisplayLayout b/src/osgEarthFeatures/FeatureDisplayLayout
index 024a124..a097de9 100644
--- a/src/osgEarthFeatures/FeatureDisplayLayout
+++ b/src/osgEarthFeatures/FeatureDisplayLayout
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -143,6 +143,14 @@ namespace osgEarth { namespace Features
         optional<float>& priorityScale() { return _priorityScale; }
         const optional<float>& priorityScale() const { return _priorityScale; }
 
+        /**
+         * Minimum time, in second, before a feature tile is eligible for pageout.
+         * Set this to a negative number to disable expiration altogether (i.e., tiles
+         * will never page out).
+         */
+        optional<float>& minExpiryTime() { return _minExpiryTime; }
+        const optional<float>& minExpiryTime() const { return _minExpiryTime; }
+
 
         /** Adds a new feature level */
         void addLevel( const FeatureLevel& level );
@@ -153,9 +161,6 @@ namespace osgEarth { namespace Features
         /** Gets the nth level */
         const FeatureLevel* getLevel( unsigned i ) const;
 
-        /** Gets the maximum range of the schema */
-        //float getMaxRange() const;
-
         /**
          * Calculates the "best" quadtree LOD for the specified level, given the radius 
          * of the full extent of the dataset.
@@ -173,6 +178,7 @@ namespace osgEarth { namespace Features
         optional<bool>  _cropFeatures;
         optional<float> _priorityOffset;
         optional<float> _priorityScale;
+        optional<float> _minExpiryTime;
         typedef std::multimap<float,FeatureLevel> Levels;
         Levels _levels;
 
diff --git a/src/osgEarthFeatures/FeatureDisplayLayout.cpp b/src/osgEarthFeatures/FeatureDisplayLayout.cpp
index fbfb110..39e2f70 100644
--- a/src/osgEarthFeatures/FeatureDisplayLayout.cpp
+++ b/src/osgEarthFeatures/FeatureDisplayLayout.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -72,7 +72,8 @@ _minRange      ( 0.0f ),
 _maxRange      ( 0.0f ),
 _cropFeatures  ( false ),
 _priorityOffset( 0.0f ),
-_priorityScale ( 1.0f )
+_priorityScale ( 1.0f ),
+_minExpiryTime ( 0.0f )
 {
     fromConfig( conf );
 }
@@ -85,6 +86,7 @@ FeatureDisplayLayout::fromConfig( const Config& conf )
     conf.getIfSet( "crop_features",    _cropFeatures );
     conf.getIfSet( "priority_offset",  _priorityOffset );
     conf.getIfSet( "priority_scale",   _priorityScale );
+    conf.getIfSet( "min_expiry_time",  _minExpiryTime );
     conf.getIfSet( "min_range",        _minRange );
     conf.getIfSet( "max_range",        _maxRange );
     ConfigSet children = conf.children( "level" );
@@ -101,6 +103,7 @@ FeatureDisplayLayout::getConfig() const
     conf.addIfSet( "crop_features",    _cropFeatures );
     conf.addIfSet( "priority_offset",  _priorityOffset );
     conf.addIfSet( "priority_scale",   _priorityScale );
+    conf.addIfSet( "min_expiry_time",  _minExpiryTime );
     conf.addIfSet( "min_range",        _minRange );
     conf.addIfSet( "max_range",        _maxRange );
     for( Levels::const_iterator i = _levels.begin(); i != _levels.end(); ++i )
diff --git a/src/osgEarthFeatures/FeatureDrawSet b/src/osgEarthFeatures/FeatureDrawSet
index 87dd9d4..e918e35 100644
--- a/src/osgEarthFeatures/FeatureDrawSet
+++ b/src/osgEarthFeatures/FeatureDrawSet
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthFeatures/FeatureDrawSet.cpp b/src/osgEarthFeatures/FeatureDrawSet.cpp
index 9f59217..9076b84 100644
--- a/src/osgEarthFeatures/FeatureDrawSet.cpp
+++ b/src/osgEarthFeatures/FeatureDrawSet.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthFeatures/FeatureIndex b/src/osgEarthFeatures/FeatureIndex
index f849255..ccd505d 100644
--- a/src/osgEarthFeatures/FeatureIndex
+++ b/src/osgEarthFeatures/FeatureIndex
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -37,6 +37,9 @@ namespace osgEarth { namespace Features
         /** Get a feature given an object id. */
         virtual Feature* getFeature(ObjectID oid) const =0;
 
+        /** Get the object ID corresponding to a feature ID. */
+        virtual ObjectID getObjectID(FeatureID fid) const =0;
+
         /** Number of features in the index */
         virtual int size() const =0;
     };
diff --git a/src/osgEarthFeatures/FeatureListSource b/src/osgEarthFeatures/FeatureListSource
index 6ab0729..8afb80c 100644
--- a/src/osgEarthFeatures/FeatureListSource
+++ b/src/osgEarthFeatures/FeatureListSource
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
@@ -33,6 +33,9 @@
 
 namespace osgEarth { namespace Features
 {   
+    /**
+     * @deprecated - use a FeatureNode instead
+     */
     class OSGEARTHFEATURES_EXPORT FeatureListSource : public osgEarth::Features::FeatureSource
     {
     public:
diff --git a/src/osgEarthFeatures/FeatureListSource.cpp b/src/osgEarthFeatures/FeatureListSource.cpp
index c54f990..c653e83 100644
--- a/src/osgEarthFeatures/FeatureListSource.cpp
+++ b/src/osgEarthFeatures/FeatureListSource.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -36,6 +36,9 @@ _defaultExtent( defaultExtent )
 FeatureCursor*
 FeatureListSource::createFeatureCursor( const Symbology::Query& query )
 {
+    if (getFeatureProfile() == 0L)
+        setFeatureProfile(createFeatureProfile());
+
     //Create a copy of all of the features before returning the cursor.
     //The processing filters in osgEarth can modify the features as they are operating and we don't want our original data destroyed.
     FeatureList cursorFeatures;
diff --git a/src/osgEarthFeatures/FeatureModelGraph b/src/osgEarthFeatures/FeatureModelGraph
index 2ea3988..903b302 100644
--- a/src/osgEarthFeatures/FeatureModelGraph
+++ b/src/osgEarthFeatures/FeatureModelGraph
@@ -1,6 +1,6 @@
 /* --*-c++-*-- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -34,7 +34,6 @@
 
 namespace osgEarth {
     class ClampableNode;
-    class DrapeableNode;
 }
 
 namespace osgEarth { namespace Features
@@ -85,7 +84,10 @@ namespace osgEarth { namespace Features
         /**
          * Loads and returns a subnode. Used internally for paging.
          */
-        osg::Node* load( unsigned lod, unsigned tileX, unsigned tileY, const std::string& uri );
+        osg::Node* load(
+            unsigned lod, unsigned tileX, unsigned tileY,
+            const std::string& uri,
+            const osgDB::Options* readOptions);
 
         /**
          * Style sheet associated with this feature graph.
@@ -127,16 +129,18 @@ namespace osgEarth { namespace Features
 
         osg::Node* setupPaging();
 
-        osg::Group* buildLevel( 
-            const FeatureLevel& level, 
-            const GeoExtent&    extent, 
-            const TileKey*      key);
+        osg::Group* buildTile( 
+            const FeatureLevel&   level, 
+            const GeoExtent&      extent, 
+            const TileKey*        key,
+            const osgDB::Options* readOptions);
 
         osg::Group* build( 
-            const Style&         baseStyle, 
-            const Query&         baseQuery, 
-            const GeoExtent&     extent, 
-            FeatureIndexBuilder* index);
+            const Style&          baseStyle, 
+            const Query&          baseQuery, 
+            const GeoExtent&      extent, 
+            FeatureIndexBuilder*  index,
+            const osgDB::Options* readOptions);
 
 
     private:
@@ -144,26 +148,30 @@ namespace osgEarth { namespace Features
         void ctor();
         
         osg::Group* createStyleGroup(
-            const Style&         style, 
-            const Query&         query, 
-            FeatureIndexBuilder* index);
+            const Style&          style, 
+            const Query&          query, 
+            FeatureIndexBuilder*  index,
+            const osgDB::Options* readOptions);
 
         osg::Group* createStyleGroup(
-            const Style&         style, 
-            FeatureList&         workingSet, 
-            const FilterContext& contextPrototype);
+            const Style&          style, 
+            FeatureList&          workingSet, 
+            const FilterContext&  contextPrototype,
+            const osgDB::Options* readOptions);
 
         void buildStyleGroups(
-            const StyleSelector* selector,
-            const Query&         baseQuery,
-            FeatureIndexBuilder* index,
-            osg::Group*          parent);
+            const StyleSelector*  selector,
+            const Query&          baseQuery,
+            FeatureIndexBuilder*  index,
+            osg::Group*           parent,
+            const osgDB::Options* readOptions);
 
         void queryAndSortIntoStyleGroups(
             const Query&            query,
             const StringExpression& styleExpr,
             FeatureIndexBuilder*    index,
-            osg::Group*             parent);
+            osg::Group*             parent,
+            const osgDB::Options*   readOptions);
 
         osg::Group* getOrCreateStyleGroupFromFactory(
             const Style& style);
@@ -174,7 +182,18 @@ namespace osgEarth { namespace Features
 
         void buildSubTilePagedLODs(
             unsigned lod, unsigned tileX, unsigned tileY,
-            const MapFrame* mapFrame, osg::Group* parent);
+            const MapFrame* mapFrame, osg::Group* parent,
+            const osgDB::Options* readOptions);
+
+        
+        osg::Group* readTileFromCache(
+            const std::string&    cacheKey,
+            const osgDB::Options* readOptions);
+
+        bool writeTileToCache(
+            const std::string&    cacheKey,
+            osg::Group*           tile,
+            const osgDB::Options* readOptions);
 
         void redraw();
 
@@ -194,13 +213,16 @@ namespace osgEarth { namespace Features
         bool                             _dirty;
         bool                             _pendingUpdate;
         std::vector<const FeatureLevel*> _lodmap;
+        OpenThreads::Mutex               _clampableMutex;
 
         osg::Group*                      _overlayInstalled;
-        osg::Group*                      _overlayPlaceholder;
-        ClampableNode*                   _clampable;
-        DrapeableNode*                   _drapeable;
+        osg::ref_ptr<osg::Group>         _overlayPlaceholder;
+        osg::ref_ptr<ClampableNode>      _clampable;
         DepthOffsetAdapter               _depthOffsetAdapter;
 
+        OpenThreads::Atomic _cacheReads;
+        OpenThreads::Atomic _cacheHits;
+
         enum OverlayChange {
             OVERLAY_NO_CHANGE,
             OVERLAY_INSTALL_PLACEHOLDER,
@@ -220,8 +242,10 @@ namespace osgEarth { namespace Features
 
         void runPreMergeOperations(osg::Node* node);
         void runPostMergeOperations(osg::Node* node);
+        void applyRenderSymbology(const Style& style, osg::Node* node);
         void checkForGlobalStyles(const Style& style);
         void changeOverlay();
+        bool createOrUpdateNode(FeatureCursor*, const Style&, FilterContext&, const osgDB::Options*, osg::ref_ptr<osg::Node>& output);
     };
 
 } } // namespace osgEarth::Features
diff --git a/src/osgEarthFeatures/FeatureModelGraph.cpp b/src/osgEarthFeatures/FeatureModelGraph.cpp
index f54c96f..1d08f0a 100644
--- a/src/osgEarthFeatures/FeatureModelGraph.cpp
+++ b/src/osgEarthFeatures/FeatureModelGraph.cpp
@@ -1,6 +1,6 @@
 /* --*-c++-*-- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -27,7 +27,6 @@
 #include <osgEarth/Clamping>
 #include <osgEarth/ClampableNode>
 #include <osgEarth/CullingUtils>
-#include <osgEarth/DrapeableNode>
 #include <osgEarth/ElevationLOD>
 #include <osgEarth/ElevationQuery>
 #include <osgEarth/FadeEffect>
@@ -46,7 +45,7 @@
 #include <algorithm>
 #include <iterator>
 
-#define LC "[FeatureModelGraph] " << getName()
+#define LC "[FeatureModelGraph] " << getName() << ": "
 
 using namespace osgEarth;
 using namespace osgEarth::Features;
@@ -94,29 +93,37 @@ namespace
                                 const std::string& uri, 
                                 float minRange, 
                                 float maxRange, 
-                                float priOffset, 
-                                float priScale,
+                                const FeatureDisplayLayout& layout,
                                 RefNodeOperationVector* postMergeOps,
-                                osgDB::FileLocationCallback* flc)
+                                osgDB::FileLocationCallback* flc,
+                                const osgDB::Options* readOptions)
     {
 #ifdef USE_PROXY_NODE_FOR_TESTING
-        osg::ProxyNode* p = new osg::ProxyNode();
+        ProxyNode* p = new ProxyNode();
         p->setCenter( bs.center() );
         p->setRadius( bs.radius() );
         p->setFileName( 0, uri );
+        p->setRange( 0, minRange, maxRange );
+        p->setPriorityOffset( 0, layout.priorityOffset().get() );
+        p->setPriorityScale(0, layout.priorityScale().get() );
 #else
         PagedLODWithNodeOperations* p = new PagedLODWithNodeOperations(postMergeOps);
         p->setCenter( bs.center() );
-        p->setRadius( bs.radius() ); //maxRange + bs.radius() );
-        //p->setRadius(-1);
+        p->setRadius( bs.radius() );
         p->setFileName( 0, uri );
         p->setRange( 0, minRange, maxRange );
-        p->setPriorityOffset( 0, priOffset );
-        p->setPriorityScale( 0, priScale );
+        p->setPriorityOffset( 0, layout.priorityOffset().get() );
+        p->setPriorityScale(0, layout.priorityScale().get() );
+        if (layout.minExpiryTime().isSet())
+        {
+            float value = layout.minExpiryTime() >= 0.0f ? layout.minExpiryTime().get() : FLT_MAX;
+            p->setMinimumExpiryTime(0, value);
+        }
+            
 #endif
 
         // force onto the high-latency thread pool.
-        osgDB::Options* options = Registry::instance()->cloneOrCreateOptions();
+        osgDB::Options* options = Registry::instance()->cloneOrCreateOptions(readOptions);
         options->setFileLocationCallback( flc );
         p->setDatabaseOptions( options );
 
@@ -135,12 +142,12 @@ struct osgEarthFeatureModelPseudoLoader : public osgDB::ReaderWriter
         supportsExtension( "osgearth_pseudo_fmg", "Feature model pseudo-loader" );
     }
 
-    const char* className()
+    const char* className() const
     { // override
         return "osgEarth Feature Model Pseudo-Loader";
     }
 
-    ReadResult readNode(const std::string& uri, const Options* options) const
+    ReadResult readNode(const std::string& uri, const osgDB::Options* readOptions) const
     {
         if ( !acceptsExtension( osgDB::getLowerCaseFileExtension(uri) ) )
             return ReadResult::FILE_NOT_HANDLED;
@@ -157,7 +164,7 @@ struct osgEarthFeatureModelPseudoLoader : public osgDB::ReaderWriter
             if (map.valid() == true)
             {
                 Registry::instance()->startActivity(uri);
-                osg::Node* node = graph->load( lod, x, y, uri );
+                osg::Node* node = graph->load(lod, x, y, uri, readOptions);
                 Registry::instance()->endActivity(uri);
                 return ReadResult(node);
             }
@@ -188,12 +195,6 @@ struct osgEarthFeatureModelPseudoLoader : public osgDB::ReaderWriter
         FMGRegistry::const_iterator i = _fmgRegistry.find( uid );
         return i != _fmgRegistry.end() ? i->second.get() : 0L;
     }
-
-    /** User data structure for traversing the feature graph. */
-    struct CullUserData : public osg::Referenced
-    {
-        double _cameraElevation;
-    };
 };
 
 REGISTER_OSGPLUGIN(osgearth_pseudo_fmg, osgEarthFeatureModelPseudoLoader);
@@ -248,9 +249,6 @@ _postMergeOperations( postMergeOperations ),
 _dirty              ( false ),
 _pendingUpdate      ( false ),
 _overlayInstalled   ( 0L ),
-_overlayPlaceholder ( 0L ),
-_clampable          ( 0L ),
-_drapeable          ( 0L ),
 _overlayChange      ( OVERLAY_NO_CHANGE )
 {
     ctor();
@@ -270,9 +268,6 @@ _postMergeOperations( postMergeOperations ),
 _dirty              ( false ),
 _pendingUpdate      ( false ),
 _overlayInstalled   ( 0L ),
-_overlayPlaceholder ( 0L ),
-_clampable          ( 0L ),
-_drapeable          ( 0L ),
 _overlayChange      ( OVERLAY_NO_CHANGE )
 {
     ctor();
@@ -314,7 +309,8 @@ FeatureModelGraph::ctor()
     // take care in dealing with them in a multi-threaded environment.
     if ( !_session->getResourceCache() && _options.sessionWideResourceCache() == true )
     {
-        _session->setResourceCache( new ResourceCache(_session->getDBOptions()) );
+        //_session->setResourceCache( new ResourceCache(_session->getDBOptions()) );
+        _session->setResourceCache(new ResourceCache());
     }
     
     // Calculate the usable extent (in both feature and map coordinates) and bounds.
@@ -383,7 +379,7 @@ FeatureModelGraph::ctor()
                 //The tilesize factor must be at least 1.0 to avoid culling the tile when you are within it's bounding sphere. 
                 tileSizeFactor = osg::maximum( tileSizeFactor, 1.0f);
                 OE_INFO << LC << "Computed a tilesize factor of " << tileSizeFactor << " with max range setting of " <<  userMaxRange << std::endl;
-                _options.layout()->tileSizeFactor() = tileSizeFactor * 1.5; // approx sqrt(2)
+                _options.layout()->tileSizeFactor() = tileSizeFactor;
             }
         }
     }
@@ -439,7 +435,7 @@ FeatureModelGraph::ctor()
         _lodmap.resize(featureProfile->getMaxLevel() + 1);
          
         // Compute the max range of all the feature levels.  Each subsequent level if half of the parent.
-        for (unsigned int i = 0; i < featureProfile->getMaxLevel()+1; i++)
+        for (int i = 0; i < featureProfile->getMaxLevel()+1; i++)
         {
             OE_INFO << LC << "Computed max range " << maxRange << " for lod " << i << std::endl;
             FeatureLevel* level = new FeatureLevel(0.0, maxRange);
@@ -539,32 +535,6 @@ FeatureModelGraph::getBoundInWorldCoords(const GeoExtent& extent,
 
     if ( _session->getMapInfo().isGeocentric() )
     {
-#if 0
-        // Convert the extent to lat/long and center it on the equator; this will ensure
-        // that all tiles in the same LOD have the same bounding radius.
-        GeoExtent eq = workingExtent.transform( workingExtent.getSRS()->getGeographicSRS() );
-
-        GeoExtent equatorialExtent(
-            eq.getSRS(),
-            eq.west(),
-            -eq.height()/2.0,
-            eq.east(),
-            eq.height()/2.0 );
-        
-        GeoPoint centerPoint( workingExtent.getSRS(), center, ALTMODE_ABSOLUTE );
-        centerPoint.toWorld( center );
-
-        return osg::BoundingSphered( center, equatorialExtent.getBoundingGeoCircle().getRadius() );
-#else
-        
-        /*
-        GeoPoint centerPoint( workingExtent.getSRS(), center, ALTMODE_ABSOLUTE );
-        centerPoint.toWorld( center );
-        double radius = workingExtent.getBoundingGeoCircle().getRadius();
-        //OE_WARN << LC << "Extent=" << workingExtent.toString() << "; center=" << center << "; radius=" << radius << "\n";
-        return osg::BoundingSphered( center, radius );  
-        */
-
         // Compute the bounding sphere by sampling points along the extent.
         int samples = 6;
 
@@ -572,45 +542,18 @@ FeatureModelGraph::getBoundInWorldCoords(const GeoExtent& extent,
         double ySample = workingExtent.height() / (double)samples;
 
         osg::BoundingSphered bs;
-        for (unsigned int c = 0; c < samples+1; c++)
+        for (int c = 0; c < samples+1; c++)
         {
             double x = workingExtent.xMin() + (double)c * xSample;
-            for (unsigned int r = 0; r < samples+1; r++)
+            for (int r = 0; r < samples+1; r++)
             {
                 double y = workingExtent.yMin() + (double)r * ySample;
                 osg::Vec3d world;
-                GeoPoint(workingExtent.getSRS(), x, y, 0, ALTMODE_ABSOLUTE).toWorld(world);
+                GeoPoint(workingExtent.getSRS(), x, y, center.z(), ALTMODE_ABSOLUTE).toWorld(world);
                 bs.expandBy(world);
             }
         }
         return bs;
-              
-
-        /*
-        // Compute the bounding sphere by sampling the corners.
-        osg::Vec3d sw, se, ne, nw, e, w, s, n;
-        GeoPoint(workingExtent.getSRS(), workingExtent.west(), workingExtent.south(), 0, ALTMODE_ABSOLUTE).toWorld(sw);
-        GeoPoint(workingExtent.getSRS(), workingExtent.east(), workingExtent.south(), 0, ALTMODE_ABSOLUTE).toWorld(se);
-        GeoPoint(workingExtent.getSRS(), workingExtent.east(), workingExtent.north(), 0, ALTMODE_ABSOLUTE).toWorld(ne);
-        GeoPoint(workingExtent.getSRS(), workingExtent.west(), workingExtent.north(), 0, ALTMODE_ABSOLUTE).toWorld(nw);
-        GeoPoint(workingExtent.getSRS(), workingExtent.west(), center.y(),            0, ALTMODE_ABSOLUTE).toWorld(w);
-        GeoPoint(workingExtent.getSRS(), workingExtent.east(), center.y(),            0, ALTMODE_ABSOLUTE).toWorld(e);
-        GeoPoint(workingExtent.getSRS(), center.x(),           workingExtent.north(), 0, ALTMODE_ABSOLUTE).toWorld(n);
-        GeoPoint(workingExtent.getSRS(), center.x(),           workingExtent.south(), 0, ALTMODE_ABSOLUTE).toWorld(s);
-      
-        osg::BoundingSphered bs;
-        bs.expandBy(center);
-        bs.expandBy(sw);
-        bs.expandBy(se);
-        bs.expandBy(ne);
-        bs.expandBy(nw);
-        bs.expandBy(w);
-        bs.expandBy(e);
-        bs.expandBy(n);
-        bs.expandBy(s);
-       
-        */ 
-#endif
     }
 
     if (workingExtent.getSRS()->isGeographic() &&
@@ -665,10 +608,12 @@ FeatureModelGraph::setupPaging()
         uri, 
         0.0f, 
         maxRange, 
-        *_options.layout()->priorityOffset(), 
-        *_options.layout()->priorityScale(),
+        _options.layout().get(),
+        //*_options.layout()->priorityOffset(), 
+        //*_options.layout()->priorityScale(),
         _postMergeOperations.get(),
-        _defaultFileLocationCallback.get() );
+        _defaultFileLocationCallback.get(),
+        getSession()->getDBOptions() );
 
     return pagedNode;
 }
@@ -678,7 +623,9 @@ FeatureModelGraph::setupPaging()
  * Called by the pseudo-loader, this method attempts to load a single tile of features.
  */
 osg::Node*
-FeatureModelGraph::load( unsigned lod, unsigned tileX, unsigned tileY, const std::string& uri )
+FeatureModelGraph::load(unsigned lod, unsigned tileX, unsigned tileY,
+                        const std::string& uri,
+                        const osgDB::Options* readOptions)
 {
     OE_DEBUG << LC
         << "load: " << lod << "_" << tileX << "_" << tileY << std::endl;
@@ -711,15 +658,20 @@ FeatureModelGraph::load( unsigned lod, unsigned tileX, unsigned tileY, const std
             //OE_NOTICE << "  extent = " << tileExtent.width() << "x" << tileExtent.height() << std::endl;
             //OE_NOTICE << "  tileFactor = " << tileFactor << " maxRange=" << maxRange << " radius=" << tileBound.radius() << std::endl;
             
-            // Construct a tile key that will be used to query the source for this tile.
-#if 0
+
+#if 1
+            // Construct a tile key that will be used to query the source for this tile.            
+            // The tilekey x, y, z that is computed in the FeatureModelGraph uses a lower left origin,
+            // osgEarth tilekeys use a lower left so we need to invert it.
             unsigned int w, h;
             featureProfile->getProfile()->getNumTiles(lod, w, h);
-            tileY = h - tileY - 1;
-#endif
+            int invertedTileY = h - tileY - 1;
 
+            TileKey key(lod, tileX, invertedTileY, featureProfile->getProfile());
+#else
             TileKey key(lod, tileX, tileY, featureProfile->getProfile());
-            geometry = buildLevel( level, tileExtent, &key );
+#endif
+            geometry = buildTile( level, tileExtent, &key, readOptions );
             result = geometry;
         }
 
@@ -736,7 +688,7 @@ FeatureModelGraph::load( unsigned lod, unsigned tileX, unsigned tileY, const std
                 if ( geometry != 0L || (int)lod < featureProfile->getFirstLevel() )
                 {
                     MapFrame mapf = _session->createMapFrame();
-                    buildSubTilePagedLODs( lod, tileX, tileY, &mapf, group.get() );
+                    buildSubTilePagedLODs( lod, tileX, tileY, &mapf, group.get(), readOptions);
                     group->addChild( geometry );
                 }
 
@@ -752,7 +704,7 @@ FeatureModelGraph::load( unsigned lod, unsigned tileX, unsigned tileY, const std
         // maximum camera range.
 
         FeatureLevel all( 0.0f, FLT_MAX );
-        result = buildLevel( all, GeoExtent::INVALID, 0 );
+        result = buildTile( all, GeoExtent::INVALID, (const TileKey*)0L, readOptions );
     }
 
     else if ( (int)lod < _lodmap.size() )
@@ -773,7 +725,7 @@ FeatureModelGraph::load( unsigned lod, unsigned tileX, unsigned tileY, const std
                 s_getTileExtent( lod, tileX, tileY, _usableFeatureExtent ) :
                 _usableFeatureExtent;
                 
-            geometry = buildLevel( *level, tileExtent, 0 );
+            geometry = buildTile( *level, tileExtent, (const TileKey*)0L, readOptions );
             result = geometry;
         }
 
@@ -784,7 +736,7 @@ FeatureModelGraph::load( unsigned lod, unsigned tileX, unsigned tileY, const std
             osg::ref_ptr<osg::Group> group = new osg::Group();
 
             MapFrame mapf = _session->createMapFrame();
-            buildSubTilePagedLODs( lod, tileX, tileY, &mapf, group.get() );
+            buildSubTilePagedLODs( lod, tileX, tileY, &mapf, group.get(), readOptions );
 
             if ( geometry )
                 group->addChild( geometry );
@@ -826,7 +778,8 @@ FeatureModelGraph::buildSubTilePagedLODs(unsigned        parentLOD,
                                          unsigned        parentTileX,
                                          unsigned        parentTileY,
                                          const MapFrame* mapf,
-                                         osg::Group*     parent)
+                                         osg::Group*     parent,
+                                         const osgDB::Options* readOptions)
 {
     unsigned subtileLOD = parentLOD + 1;
     unsigned subtileX = parentTileX * 2;
@@ -898,10 +851,12 @@ FeatureModelGraph::buildSubTilePagedLODs(unsigned        parentLOD,
                     subtile_bs, 
                     uri, 
                     0.0f, maxRange, 
-                    *_options.layout()->priorityOffset(), 
-                    *_options.layout()->priorityScale(),
+                    _options.layout().get(),
+                    //*_options.layout()->priorityOffset(), 
+                    //*_options.layout()->priorityScale(),
                     _postMergeOperations.get(),
-                    _defaultFileLocationCallback.get() );
+                    _defaultFileLocationCallback.get(),
+                    readOptions);
 
                 parent->addChild( pagedNode );
             }
@@ -909,6 +864,104 @@ FeatureModelGraph::buildSubTilePagedLODs(unsigned        parentLOD,
     }
 }
 
+namespace
+{
+    std::string makeCacheKey(const FeatureLevel& level,
+                             const GeoExtent& extent,
+                             const TileKey* key)
+    {
+        if (key)
+        {
+            return key->str();
+        }
+        else
+        {
+            return Stringify() << osgEarth::hashString(
+                Stringify() << extent.toString() << level.styleName().get());
+        }
+    }
+}
+
+osg::Group*
+FeatureModelGraph::readTileFromCache(const std::string&    cacheKey,
+                                     const osgDB::Options* readOptions)
+{
+    osg::ref_ptr<osg::Group> group;
+
+    osg::ref_ptr<CacheBin> cacheBin;
+    optional<CachePolicy> policy;
+    if (CacheSettings* cacheSettings = CacheSettings::get(readOptions))
+    {
+        policy = cacheSettings->cachePolicy();
+        cacheBin = cacheSettings->getCacheBin();
+    }
+
+    if (cacheBin && policy->isCacheReadable())
+    {
+        ++_cacheReads;
+        
+        ReadResult rr = cacheBin->readObject(cacheKey, readOptions);
+
+        if (policy.isSet() && policy->isExpired(rr.lastModifiedTime()))
+        {
+            OE_DEBUG << LC << "Tile " << cacheKey << " is cached but expired.\n";
+            return 0L;
+        }
+
+        if (rr.succeeded())
+        {
+            group = dynamic_cast<osg::Group*>(rr.getNode());
+            OE_DEBUG << LC << "Loaded from the cache (key = " << cacheKey << ")\n";
+            ++_cacheHits;
+
+            // remap the feature index.
+            if (group.valid() && _featureIndex.valid())
+            {
+                FeatureSourceIndexNode::reconstitute(group.get(), _featureIndex.get());
+            }
+        }
+        else if (rr.code() == ReadResult::RESULT_NOT_FOUND)
+        {
+            //nop -- object not in cache
+            OE_DEBUG << LC << "Object not in cache (cacheKey=" << cacheKey << ") " << rr.getResultCodeString() << "; " << rr.errorDetail() << "\n";
+        }
+        else
+        {
+            // some other error.
+            OE_WARN << LC << "Cache read error (cacheKey=" << cacheKey << ") " << rr.getResultCodeString() << "; " << rr.errorDetail() << "\n";
+        }
+
+        OE_DEBUG << "cache hit ratio = " << float(_cacheHits) / float(_cacheReads) << "\n";
+    }
+    else
+    {
+        OE_DEBUG << LC << "No cachebin in the readOptions - caching not enabled for this layer\n";
+    }
+
+    return group.release();
+}
+
+bool
+FeatureModelGraph::writeTileToCache(const std::string&    cacheKey,
+                                    osg::Group*           node,
+                                    const osgDB::Options* writeOptions)
+{
+    osg::ref_ptr<CacheBin> cacheBin;
+    optional<CachePolicy> policy;
+    if (CacheSettings* cacheSettings = CacheSettings::get(writeOptions))
+    {
+        policy = cacheSettings->cachePolicy();
+        cacheBin = cacheSettings->getCacheBin();
+    }
+
+    if (cacheBin && policy->isCacheWriteable())
+    {
+        cacheBin->writeNode(cacheKey, node, Config(), writeOptions);
+        OE_DEBUG << LC << "Wrote " << cacheKey << " to cache\n";
+    }
+    return true;
+}
+
 /**
  * Builds geometry for feature data at a particular level, and constrained by an extent.
  * The extent is either (a) expressed in "extent" literally, as is the case in a non-tiled
@@ -916,77 +969,92 @@ FeatureModelGraph::buildSubTilePagedLODs(unsigned        parentLOD,
  * data source.
  */
 osg::Group*
-FeatureModelGraph::buildLevel( const FeatureLevel& level, const GeoExtent& extent, const TileKey* key )
+FeatureModelGraph::buildTile(const FeatureLevel& level,
+                             const GeoExtent& extent,
+                             const TileKey* key,
+                             const osgDB::Options* readOptions)
 {
-    // set up for feature indexing if appropriate:
     osg::ref_ptr<osg::Group> group;
-    FeatureSourceIndexNode* index = 0L;
-
-    FeatureSource* featureSource = _session->getFeatureSource();
 
-    if (featureSource)
+    // Try to read it from a cache:
+    std::string cacheKey = makeCacheKey(level, extent, key);
+    group = readTileFromCache(cacheKey, readOptions);
+    
+    // Not there? Build it
+    if (!group.valid())
     {
-        const FeatureProfile* fp = featureSource->getFeatureProfile();
+        // set up for feature indexing if appropriate:
+        FeatureSourceIndexNode* index = 0L;
+
+        FeatureSource* featureSource = _session->getFeatureSource();
 
-        if ( _featureIndex.valid() )
+        if (featureSource)
         {
-            index = new FeatureSourceIndexNode( _featureIndex.get() );
-            group = index;
+            const FeatureProfile* fp = featureSource->getFeatureProfile();
+
+            if ( _featureIndex.valid() )
+            {
+                index = new FeatureSourceIndexNode( _featureIndex.get() );
+                group = index;
+            }
         }
-    }
 
-    if ( !group.valid() )
-    {
-        group = new osg::Group();
-    }
+        if ( !group.valid() )
+        {
+            group = new osg::Group();
+        }
 
-    // form the baseline query, which does a spatial query based on the working extent.
-    Query query;
-    if ( extent.isValid() )
-        query.bounds() = extent.bounds();
+        // form the baseline query, which does a spatial query based on the working extent.
+        Query query;
+        if ( extent.isValid() )
+            query.bounds() = extent.bounds();
 
-    // add a tile key to the query if there is one, to support TFS-style queries
-    if ( key )
-        query.tileKey() = *key;
+        // add a tile key to the query if there is one, to support TFS-style queries
+        if ( key )
+            query.tileKey() = *key;
 
-    query.setMap( _session->getMap() );
+        query.setMap( _session->getMap() );
 
-    // does the level have a style name set?
-    if ( level.styleName().isSet() )
-    {
-        osg::Node* node = 0L;
-        const Style* style = _session->styles()->getStyle( *level.styleName(), false );
-        if ( style )
+        // does the level have a style name set?
+        if ( level.styleName().isSet() )
         {
-            // found a specific style to use.
-            node = createStyleGroup( *style, query, index );
-            if ( node )
-                group->addChild( node );
+            osg::Node* node = 0L;
+            const Style* style = _session->styles()->getStyle( *level.styleName(), false );
+            if ( style )
+            {
+                // found a specific style to use.
+                node = createStyleGroup( *style, query, index, readOptions );
+                if ( node )
+                    group->addChild( node );
+            }
+            else
+            {
+                const StyleSelector* selector = _session->styles()->getSelector( *level.styleName() );
+                if ( selector )
+                {
+                    buildStyleGroups( selector, query, index, group.get(), readOptions );
+                }
+            }
         }
+
         else
         {
-            const StyleSelector* selector = _session->styles()->getSelector( *level.styleName() );
-            if ( selector )
+            Style defaultStyle;
+
+            if ( _session->styles()->selectors().size() == 0 )
             {
-                buildStyleGroups( selector, query, index, group.get() );
+                // attempt to glean the style from the feature source name:
+                defaultStyle = *_session->styles()->getStyle( 
+                    *_session->getFeatureSource()->getFeatureSourceOptions().name() );
             }
-        }
-    }
 
-    else
-    {
-        Style defaultStyle;
-
-        if ( _session->styles()->selectors().size() == 0 )
-        {
-            // attempt to glean the style from the feature source name:
-            defaultStyle = *_session->styles()->getStyle( 
-                *_session->getFeatureSource()->getFeatureSourceOptions().name() );
+            osg::Node* node = build(defaultStyle, query, extent, index, readOptions);
+            if ( node )
+                group->addChild( node );
         }
 
-        osg::Node* node = build( defaultStyle, query, extent, index );
-        if ( node )
-            group->addChild( node );
+        // cache it if appropriate.
+        writeTileToCache(cacheKey, group.get(), readOptions);
     }
 
     if ( group->getNumChildren() > 0 )
@@ -1019,7 +1087,6 @@ FeatureModelGraph::buildLevel( const FeatureLevel& level, const GeoExtent& exten
 
                     osg::Vec3d centerECEF;
                     ccExtent.getSRS()->transform( tileCenter, _session->getMapSRS()->getECEF(), centerECEF );
-                    //ccExtent.getSRS()->transformToECEF( tileCenter, centerECEF );
 
                     osg::NodeCallback* ccc = ClusterCullingFactory::create2( group.get(), centerECEF );
                     if ( ccc )
@@ -1039,10 +1106,11 @@ FeatureModelGraph::buildLevel( const FeatureLevel& level, const GeoExtent& exten
 
 
 osg::Group*
-FeatureModelGraph::build(const Style&         defaultStyle, 
-                         const Query&         baseQuery, 
-                         const GeoExtent&     workingExtent,
-                         FeatureIndexBuilder* index)
+FeatureModelGraph::build(const Style&          defaultStyle, 
+                         const Query&          baseQuery, 
+                         const GeoExtent&      workingExtent,
+                         FeatureIndexBuilder*  index,
+                         const osgDB::Options* readOptions)
 {
     osg::ref_ptr<osg::Group> group = new osg::Group();
 
@@ -1081,7 +1149,7 @@ FeatureModelGraph::build(const Style&         defaultStyle,
                     }
                 }
 
-                if ( _factory->createOrUpdateNode( cursor.get(), *feature->style(), context, node ) )
+                if ( createOrUpdateNode(cursor.get(), *feature->style(), context, readOptions, node))
                 {
                     if ( node.valid() )
                     {
@@ -1118,7 +1186,7 @@ FeatureModelGraph::build(const Style&         defaultStyle,
                     combinedQuery.setMap( _session->getMap() );
 
                     // query, sort, and add each style group to th parent:
-                    queryAndSortIntoStyleGroups( combinedQuery, *sel.styleExpression(), index, group );
+                    queryAndSortIntoStyleGroups( combinedQuery, *sel.styleExpression(), index, group, readOptions );
                 }
 
                 // otherwise, all feature returned by this query will have the same style:
@@ -1133,7 +1201,7 @@ FeatureModelGraph::build(const Style&         defaultStyle,
                     combinedQuery.setMap( _session->getMap() );
 
                     // then create the node.
-                    osg::Group* styleGroup = createStyleGroup( combinedStyle, combinedQuery, index );
+                    osg::Group* styleGroup = createStyleGroup( combinedStyle, combinedQuery, index, readOptions );
 
                     if ( styleGroup && !group->containsNode(styleGroup) )
                         group->addChild( styleGroup );
@@ -1160,7 +1228,7 @@ FeatureModelGraph::build(const Style&         defaultStyle,
             if ( defaultStyle.empty() )
                 combinedStyle = *styles->getDefaultStyle();
 
-            osg::Group* styleGroup = createStyleGroup( combinedStyle, baseQuery, index );
+            osg::Group* styleGroup = createStyleGroup( combinedStyle, baseQuery, index, readOptions );
 
             if ( styleGroup && !group->containsNode(styleGroup) )
                 group->addChild( styleGroup );
@@ -1170,15 +1238,26 @@ FeatureModelGraph::build(const Style&         defaultStyle,
     return group->getNumChildren() > 0 ? group.release() : 0L;
 }
 
+bool
+FeatureModelGraph::createOrUpdateNode(FeatureCursor*           cursor,
+                                      const Style&             style,
+                                      FilterContext&           context,
+                                      const osgDB::Options*    readOptions,
+                                      osg::ref_ptr<osg::Node>& output)
+{
+    bool ok = _factory->createOrUpdateNode(cursor, style, context, output);
+    return ok;
+}
 
 /**
  * Builds a collection of style groups by processing a StyleSelector.
  */
 void
-FeatureModelGraph::buildStyleGroups(const StyleSelector* selector,
-                                    const Query&         baseQuery,
-                                    FeatureIndexBuilder* index,
-                                    osg::Group*          parent)
+FeatureModelGraph::buildStyleGroups(const StyleSelector*  selector,
+                                    const Query&          baseQuery,
+                                    FeatureIndexBuilder*  index,
+                                    osg::Group*           parent,
+                                    const osgDB::Options* readOptions)
 {
     OE_TEST << LC << "buildStyleGroups: " << selector->name() << std::endl;
 
@@ -1191,7 +1270,7 @@ FeatureModelGraph::buildStyleGroups(const StyleSelector* selector,
         combinedQuery.setMap( _session->getMap() );
 
         // query, sort, and add each style group to the parent:
-        queryAndSortIntoStyleGroups( combinedQuery, *selector->styleExpression(), index, parent );
+        queryAndSortIntoStyleGroups( combinedQuery, *selector->styleExpression(), index, parent, readOptions );
     }
 
     // otherwise, all feature returned by this query will have the same style:
@@ -1208,7 +1287,7 @@ FeatureModelGraph::buildStyleGroups(const StyleSelector* selector,
         combinedQuery.setMap( _session->getMap() );
 
         // then create the node.
-        osg::Node* node = createStyleGroup( style, combinedQuery, index );
+        osg::Node* node = createStyleGroup(style, combinedQuery, index, readOptions);
         if ( node && !parent->containsNode(node) )
             parent->addChild( node );
     }
@@ -1226,7 +1305,8 @@ void
 FeatureModelGraph::queryAndSortIntoStyleGroups(const Query&            query,
                                                const StringExpression& styleExpr,
                                                FeatureIndexBuilder*    index,
-                                               osg::Group*             parent)
+                                               osg::Group*             parent,
+                                               const osgDB::Options*   readOptions)
 {
     // the profile of the features
     const FeatureProfile* featureProfile = _session->getFeatureSource()->getFeatureProfile();
@@ -1252,7 +1332,10 @@ FeatureModelGraph::queryAndSortIntoStyleGroups(const Query&            query,
         if ( feature.valid() )
         {
             const std::string& styleString = feature->eval( styleExprCopy, &context );
-            styleBins[styleString].push_back( feature.get() );
+            if (!styleString.empty() && styleString != "null")
+            {
+                styleBins[styleString].push_back( feature.get() );
+            }
         }
     }
 
@@ -1289,7 +1372,7 @@ FeatureModelGraph::queryAndSortIntoStyleGroups(const Query&            query,
         // the feature.)
         if ( !combinedStyle.empty() )
         {
-            osg::Group* styleGroup = createStyleGroup(combinedStyle, workingSet, context);
+            osg::Group* styleGroup = createStyleGroup(combinedStyle, workingSet, context, readOptions);
             if ( styleGroup )
                 parent->addChild( styleGroup );
         }
@@ -1298,9 +1381,10 @@ FeatureModelGraph::queryAndSortIntoStyleGroups(const Query&            query,
 
 
 osg::Group*
-FeatureModelGraph::createStyleGroup(const Style&         style, 
-                                    FeatureList&         workingSet, 
-                                    const FilterContext& contextPrototype)
+FeatureModelGraph::createStyleGroup(const Style&          style, 
+                                    FeatureList&          workingSet, 
+                                    const FilterContext&  contextPrototype,
+                                    const osgDB::Options* readOptions)
 {
     osg::Group* styleGroup = 0L;
 
@@ -1342,7 +1426,7 @@ FeatureModelGraph::createStyleGroup(const Style&         style,
         osg::ref_ptr<osg::Node> node;
         osg::ref_ptr<FeatureCursor> newCursor = new FeatureListCursor(workingSet);
 
-        if ( _factory->createOrUpdateNode( newCursor.get(), style, context, node ) )
+        if ( createOrUpdateNode( newCursor.get(), style, context, readOptions, node ) )
         {
             if ( !styleGroup )
                 styleGroup = getOrCreateStyleGroupFromFactory( style );
@@ -1358,9 +1442,10 @@ FeatureModelGraph::createStyleGroup(const Style&         style,
 
 
 osg::Group*
-FeatureModelGraph::createStyleGroup(const Style&         style, 
-                                    const Query&         query, 
-                                    FeatureIndexBuilder* index)
+FeatureModelGraph::createStyleGroup(const Style&          style, 
+                                    const Query&          query, 
+                                    FeatureIndexBuilder*  index,
+                                    const osgDB::Options* readOptions)
 {
     osg::Group* styleGroup = 0L;
 
@@ -1386,7 +1471,7 @@ FeatureModelGraph::createStyleGroup(const Style&         style,
         FeatureList workingSet;
         cursor->fill( workingSet );
 
-        styleGroup = createStyleGroup(style, workingSet, context);
+        styleGroup = createStyleGroup(style, workingSet, context, readOptions);
     }
 
 
@@ -1397,29 +1482,25 @@ FeatureModelGraph::createStyleGroup(const Style&         style,
 void
 FeatureModelGraph::checkForGlobalStyles( const Style& style )
 {
+    OpenThreads::ScopedLock< OpenThreads::Mutex > lk(_clampableMutex);
+
     const AltitudeSymbol* alt = style.get<AltitudeSymbol>();
     if ( alt )
     {
         if (alt->clamping() == AltitudeSymbol::CLAMP_TO_TERRAIN || 
             alt->clamping() == AltitudeSymbol::CLAMP_RELATIVE_TO_TERRAIN)
         {
-            if ( alt->technique() == AltitudeSymbol::TECHNIQUE_GPU && !_clampable )
+            if ( alt->technique() == AltitudeSymbol::TECHNIQUE_GPU && !_clampable.valid() )
             {
                 _clampable = new ClampableNode( 0L );
                 _overlayChange = OVERLAY_INSTALL_CLAMPABLE;
             }
-
-            else if ( alt->technique() == AltitudeSymbol::TECHNIQUE_DRAPE && !_drapeable )
-            {
-                _drapeable = new DrapeableNode( 0L );
-                _overlayChange = OVERLAY_INSTALL_DRAPEABLE;
-            }
         }
     }
     
     const RenderSymbol* render = style.get<RenderSymbol>();
 
-    if ( _clampable )
+    if ( _clampable.valid() )
     {
         // if we're using extrusion, don't perform depth offsetting:
         const ExtrusionSymbol* extrusion = style.get<ExtrusionSymbol>();
@@ -1439,6 +1520,7 @@ FeatureModelGraph::checkForGlobalStyles( const Style& style )
         }
     }
 
+#if 0
     else 
     {
         if ( render && render->depthOffset().isSet() )
@@ -1447,20 +1529,66 @@ FeatureModelGraph::checkForGlobalStyles( const Style& style )
             _depthOffsetAdapter.setDepthOffsetOptions( *render->depthOffset() );
         }
 
-        // apply render order when draping:
-        if ( _drapeable && render && render->order().isSet() )
+        if ( render && render->renderBin().isSet() )
         {
-            _drapeable->setRenderOrder( render->order()->eval() );
+            osg::StateSet* ss = getOrCreateStateSet();
+            ss->setRenderBinDetails(
+                ss->getBinNumber(),
+                render->renderBin().get() );
         }
 
-        if ( render && render->renderBin().isSet() )
+        if ( render && render->order().isSet() )
+        {
+            osg::StateSet* ss = getOrCreateStateSet();
+            ss->setRenderBinDetails(
+                (int)render->order()->eval(),
+                ss->getBinName().empty() ? "DepthSortedBin" : ss->getBinName() );
+        }
+
+        if ( render && render->transparent() == true )
         {
             osg::StateSet* ss = getOrCreateStateSet();
-            ss->setRenderBinDetails(ss->getBinNumber(), render->renderBin().get());
+            ss->setRenderingHint( ss->TRANSPARENT_BIN );
         }
     }
+#endif
 }
 
+void
+FeatureModelGraph::applyRenderSymbology(const Style& style, osg::Node* node)
+{
+    const RenderSymbol* render = style.get<RenderSymbol>();
+    if (render && node)
+    {
+        if ( render->depthOffset().isSet() )
+        {
+            _depthOffsetAdapter.setGraph( this );
+            _depthOffsetAdapter.setDepthOffsetOptions( *render->depthOffset() );
+        }
+
+        if ( render->renderBin().isSet() )
+        {
+            osg::StateSet* ss = node->getOrCreateStateSet();
+            ss->setRenderBinDetails(
+                ss->getBinNumber(),
+                render->renderBin().get() );
+        }
+
+        if ( render->order().isSet() )
+        {
+            osg::StateSet* ss = node->getOrCreateStateSet();
+            ss->setRenderBinDetails(
+                (int)render->order()->eval(),
+                ss->getBinName().empty() ? "DepthSortedBin" : ss->getBinName() );
+        }
+
+        if ( render->transparent() == true )
+        {
+            osg::StateSet* ss = node->getOrCreateStateSet();
+            ss->setRenderingHint( ss->TRANSPARENT_BIN );
+        }
+    }
+}
 
 osg::Group*
 FeatureModelGraph::getOrCreateStyleGroupFromFactory(const Style& style)
@@ -1469,8 +1597,12 @@ FeatureModelGraph::getOrCreateStyleGroupFromFactory(const Style& style)
 
     // Check the style and see if we need to active GPU clamping. GPU clamping
     // is currently all-or-nothing for a single FMG.
+    // Warning. This needs attention w.r.t. caching, since the "global" styles don't cache. -gw
     checkForGlobalStyles( style );
 
+    // Apply render symbology at the style group level.
+    applyRenderSymbology(style, styleGroup);
+
     return styleGroup;
 }
 
@@ -1547,41 +1679,43 @@ FeatureModelGraph::runPostMergeOperations(osg::Node* node)
 void
 FeatureModelGraph::changeOverlay()
 {
+    OpenThreads::ScopedLock< OpenThreads::Mutex > lk(_clampableMutex);
+
     if (_overlayChange == OVERLAY_INSTALL_CLAMPABLE &&
-        _clampable                                  && 
-        _clampable != _overlayInstalled )
+        _clampable.valid()                          && 
+        _clampable.get() != _overlayInstalled )
     {
-        runPostMergeOperations( _clampable );
-        osgEarth::replaceGroup( _overlayInstalled, _clampable );
-        _overlayInstalled   = _clampable;
-        _drapeable          = 0L;
+        runPostMergeOperations( _clampable.get() );
+        osgEarth::replaceGroup( _overlayInstalled, _clampable.get() );
+        _overlayInstalled   = _clampable.get();
+        //_drapeable          = 0L;
         _overlayPlaceholder = 0L;
-        OE_INFO << LC << "Installed clampable decorator on layer " << getName() << std::endl;
+        OE_DEBUG << LC << "Installed clampable decorator on layer " << getName() << std::endl;
     }
 
-    else if (
-        _overlayChange == OVERLAY_INSTALL_DRAPEABLE && 
-        _drapeable                                  && 
-        _drapeable != _overlayInstalled )
-    {
-        runPostMergeOperations( _drapeable );
-        osgEarth::replaceGroup( _overlayInstalled, _drapeable );
-        _overlayInstalled   = _drapeable;
-        _overlayPlaceholder = 0L;
-        _clampable          = 0L;
-        OE_INFO << LC << "Installed drapeable decorator on layer " << getName() << std::endl;
-    }
+    //else if (
+    //    _overlayChange == OVERLAY_INSTALL_DRAPEABLE && 
+    //    _drapeable.valid()                          && 
+    //    _drapeable.get() != _overlayInstalled )
+    //{
+    //    runPostMergeOperations( _drapeable.get() );
+    //    osgEarth::replaceGroup( _overlayInstalled, _drapeable.get() );
+    //    _overlayInstalled   = _drapeable.get();
+    //    _overlayPlaceholder = 0L;
+    //    _clampable          = 0L;
+    //    OE_DEBUG << LC << "Installed drapeable decorator on layer " << getName() << std::endl;
+    //}
 
     else if (
         _overlayChange == OVERLAY_INSTALL_PLACEHOLDER && 
-        _overlayPlaceholder                           && 
-        _overlayPlaceholder != _overlayInstalled)
+        _overlayPlaceholder.valid()                   && 
+        _overlayPlaceholder.get() != _overlayInstalled)
     {
-        runPostMergeOperations( _overlayPlaceholder );
-        osgEarth::replaceGroup( _overlayInstalled, _overlayPlaceholder );
-        _overlayInstalled = _overlayPlaceholder;
+        runPostMergeOperations( _overlayPlaceholder.get() );
+        osgEarth::replaceGroup( _overlayInstalled, _overlayPlaceholder.get() );
+        _overlayInstalled = _overlayPlaceholder.get();
         _clampable        = 0L;
-        _drapeable        = 0L;
+        //_drapeable        = 0L;
         OE_INFO << LC << "Installed null decorator on layer " << getName() << std::endl;
     }
 }
@@ -1590,6 +1724,8 @@ FeatureModelGraph::changeOverlay()
 void
 FeatureModelGraph::redraw()
 {
+    OpenThreads::ScopedLock< OpenThreads::Mutex > lk(_clampableMutex);
+
     // clear it out
     removeChildren( 0, getNumChildren() );
 
@@ -1604,7 +1740,7 @@ FeatureModelGraph::redraw()
 
     // zero out any decorators
     _clampable          = 0L;
-    _drapeable          = 0L;
+    //_drapeable          = 0L;
     _overlayPlaceholder = new osg::Group();
     _overlayInstalled   = _overlayPlaceholder;
 
@@ -1619,7 +1755,7 @@ FeatureModelGraph::redraw()
         FeatureLevel defaultLevel( 0.0f, FLT_MAX );
         
         //Remove all current children
-        node = buildLevel( defaultLevel, GeoExtent::INVALID, 0 );
+        node = buildTile(defaultLevel, GeoExtent::INVALID, 0, _session->getDBOptions());
     }
 
     float minRange = -FLT_MAX;
diff --git a/src/osgEarthFeatures/FeatureModelSource b/src/osgEarthFeatures/FeatureModelSource
index abe0a6d..8c08852 100644
--- a/src/osgEarthFeatures/FeatureModelSource
+++ b/src/osgEarthFeatures/FeatureModelSource
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -53,24 +53,24 @@ namespace osgEarth { namespace Features
         optional<double>& maxGranularity() { return _maxGranularity_deg; }
         const optional<double>& maxGranularity() const { return _maxGranularity_deg; }
 
-        /** Whether to merge geometry from multiple features */
-        optional<bool>& mergeGeometry() { return _mergeGeometry; }
-        const optional<bool>& mergeGeometry() const { return _mergeGeometry; }
-
         /** Whether to explicity set/clear GL lighting on the result */
         optional<bool>& enableLighting() { return _lit; }
         const optional<bool>& enableLighting() const { return _lit; }
 
+        /** Information that controls paging and tiling of the dataset */
         optional<FeatureDisplayLayout>& layout() { return _layout; }
         const optional<FeatureDisplayLayout>& layout() const { return _layout; }
 
         optional<bool>& clusterCulling() { return _clusterCulling; }
         const optional<bool>& clusterCulling() const { return _clusterCulling; }
 
+        /** Expression that will assign a node name to geometry built from each feature.
+            Note; this may disable various scene graph optimizations. */
         optional<StringExpression>& featureName() { return _featureNameExpr; }
         const optional<StringExpression>& featureName() const { return _featureNameExpr; }
 
-        /** Whether to create feature indexes (unset = no) */
+        /** Whether to index feature data for use with the global ObjectIndex (default = yes)
+            for the purposes of search, picking, etc. */
         optional<FeatureSourceIndexOptions>& featureIndexing() { return _featureIndexing; }
         const optional<FeatureSourceIndexOptions>& featureIndexing() const { return _featureIndexing; }
 
@@ -120,7 +120,6 @@ namespace osgEarth { namespace Features
         optional<StringExpression>          _featureNameExpr;
         optional<bool>                      _lit;
         optional<double>                    _maxGranularity_deg;
-        optional<bool>                      _mergeGeometry;
         optional<bool>                      _clusterCulling;
         optional<bool>                      _backfaceCulling;
         optional<bool>                      _alphaBlending;
@@ -169,7 +168,9 @@ namespace osgEarth { namespace Features
     class OSGEARTHFEATURES_EXPORT GeomFeatureNodeFactory : public FeatureNodeFactory
     {
     public:
-        GeomFeatureNodeFactory( const GeometryCompilerOptions& options = GeometryCompilerOptions() );
+        GeomFeatureNodeFactory(
+            const GeometryCompilerOptions& options);
+
 
         bool createOrUpdateNode(       
             FeatureCursor*            features,
@@ -193,15 +194,19 @@ namespace osgEarth { namespace Features
          */
         FeatureModelSource( const FeatureModelSourceOptions& options =FeatureModelSourceOptions() );
 
+        /**
+         * Sets a new read options.
+         */
+        void setReadOptions(const osgDB::Options* readOptions);
+
 
-    public: // ModelSource
+    protected: // ModelSource
 
-        virtual void initialize( const osgDB::Options* dbOptions =0L );
+        virtual Status initialize(const osgDB::Options* readOptions);
 
         virtual osg::Node* createNodeImplementation(
             const Map*        map,
             ProgressCallback* progress );
-    
 
     public:
 
@@ -241,7 +246,7 @@ namespace osgEarth { namespace Features
         osg::observer_ptr<const Map>       _map;
         const FeatureModelSourceOptions    _options;
         osg::ref_ptr<FeatureNodeFactory>   _factory;
-        osg::ref_ptr<const osgDB::Options> _dbOptions;
+        osg::ref_ptr<osgDB::Options>       _readOptions;
 
     };
 
diff --git a/src/osgEarthFeatures/FeatureModelSource.cpp b/src/osgEarthFeatures/FeatureModelSource.cpp
index da0a5f6..b03138c 100644
--- a/src/osgEarthFeatures/FeatureModelSource.cpp
+++ b/src/osgEarthFeatures/FeatureModelSource.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -23,6 +23,7 @@
 #include <osgEarth/ShaderUtils>
 #include <osgEarth/Registry>
 #include <osgEarth/Capabilities>
+#include <osgEarth/DrapeableNode>
 #include <osg/Notify>
 
 using namespace osgEarth;
@@ -37,7 +38,6 @@ FeatureModelSourceOptions::FeatureModelSourceOptions( const ConfigOptions& optio
 ModelSourceOptions ( options ),
 _lit               ( true ),
 _maxGranularity_deg( 1.0 ),
-_mergeGeometry     ( false ),
 _clusterCulling    ( true ),
 _backfaceCulling   ( true ),
 _alphaBlending     ( true ),
@@ -62,7 +62,6 @@ FeatureModelSourceOptions::fromConfig( const Config& conf )
 
     conf.getIfSet( "lighting",         _lit );
     conf.getIfSet( "max_granularity",  _maxGranularity_deg );
-    conf.getIfSet( "merge_geometry",   _mergeGeometry );
     conf.getIfSet( "cluster_culling",  _clusterCulling );
     conf.getIfSet( "backface_culling", _backfaceCulling );
     conf.getIfSet( "alpha_blending",   _alphaBlending );
@@ -89,7 +88,6 @@ FeatureModelSourceOptions::getConfig() const
 
     conf.updateIfSet( "lighting",         _lit );
     conf.updateIfSet( "max_granularity",  _maxGranularity_deg );
-    conf.updateIfSet( "merge_geometry",   _mergeGeometry );
     conf.updateIfSet( "cluster_culling",  _clusterCulling );
     conf.updateIfSet( "backface_culling", _backfaceCulling );
     conf.updateIfSet( "alpha_blending",   _alphaBlending );
@@ -121,10 +119,11 @@ FeatureModelSource::setFeatureSource( FeatureSource* source )
     }
 }
 
-void 
-FeatureModelSource::initialize(const osgDB::Options* dbOptions)
+Status
+FeatureModelSource::initialize(const osgDB::Options* readOptions)
 {
-    ModelSource::initialize( dbOptions );
+    if (readOptions)
+        setReadOptions(readOptions);
     
     // the data source from which to pull features:
     if ( _options.featureSource().valid() )
@@ -134,36 +133,46 @@ FeatureModelSource::initialize(const osgDB::Options* dbOptions)
     else if ( _options.featureOptions().isSet() )
     {
         _features = FeatureSourceFactory::create( _options.featureOptions().value() );
-        if ( !_features.valid() )
-        {
-            OE_WARN << LC << "No valid feature source provided!" << std::endl;
-        }
     }
 
-    // initialize the feature source if it exists:
-    if ( _features.valid() )
-    {
-        _features->initialize( dbOptions );
+    if (!_features.valid())
+        return Status::Error(Status::ServiceUnavailable, "Failed to create a feature driver");
 
-        // Try to fill the DataExtent list using the FeatureProfile
-        const FeatureProfile* featureProfile = _features->getFeatureProfile();
-        if (featureProfile != NULL)
-        {
-            if (featureProfile->getProfile() != NULL)
-            {
-                // Use specified profile's GeoExtent
-                getDataExtents().push_back(DataExtent(featureProfile->getProfile()->getExtent()));
-            }
-            else if (featureProfile->getExtent().isValid() == true)
-            {
-                // Use FeatureProfile's GeoExtent
-                getDataExtents().push_back(DataExtent(featureProfile->getExtent()));
-            }
-        }
+    // open the feature source if it exists:
+    const Status& featuresStatus = _features->open(_readOptions.get());
+    if (featuresStatus.isError())
+        return featuresStatus;
+
+    // Try to fill the DataExtent list using the FeatureProfile
+    const FeatureProfile* featureProfile = _features->getFeatureProfile();
+    if (featureProfile == NULL)
+        return Status::Error("Failed to establish a feature profile");
+
+    if (featureProfile->getProfile() != NULL)
+    {
+        // Use specified profile's GeoExtent
+        getDataExtents().push_back(DataExtent(featureProfile->getProfile()->getExtent()));
     }
-    else
+    else if (featureProfile->getExtent().isValid() == true)
+    {
+        // Use FeatureProfile's GeoExtent
+        getDataExtents().push_back(DataExtent(featureProfile->getExtent()));
+    }
+
+    return Status::OK();
+}
+
+void
+FeatureModelSource::setReadOptions(const osgDB::Options* readOptions)
+{
+    _readOptions = Registry::cloneOrCreateOptions(readOptions);
+    
+    // for texture atlas support
+    _readOptions->setObjectCacheHint(osgDB::Options::CACHE_IMAGES);
+
+    if (_features.valid())
     {
-        OE_WARN << LC << "No FeatureSource; nothing will be rendered (" << getName() << ")" << std::endl;
+        _features->setReadOptions(_readOptions.get());
     }
 }
 
@@ -171,6 +180,10 @@ osg::Node*
 FeatureModelSource::createNodeImplementation(const Map*        map,
                                              ProgressCallback* progress )
 {
+    // trivial bailout.
+    if (!getStatus().isOK())
+        return 0L;
+
     // user must provide a valid map.
     if ( !map )
     {
@@ -181,7 +194,6 @@ FeatureModelSource::createNodeImplementation(const Map*        map,
     // make sure the feature source initialized properly:
     if ( !_features.valid() || !_features->getFeatureProfile() )
     {
-        OE_WARN << LC << "Invalid feature source" << std::endl;
         return 0L;
     }
 
@@ -190,6 +202,7 @@ FeatureModelSource::createNodeImplementation(const Map*        map,
     if ( !factory )
     {
         OE_WARN << LC << "Unable to create a feature node factory!" << std::endl;
+        setStatus(Status::Error(Status::ServiceUnavailable, "Failed to create a feature node factory"));
         return 0L;
     }
 
@@ -198,7 +211,7 @@ FeatureModelSource::createNodeImplementation(const Map*        map,
         map, 
         _options.styles().get(), 
         _features.get(), 
-        _dbOptions.get() );
+        _readOptions.get() );
 
     // Name the session (for debugging purposes)
     session->setName( this->getName() );
@@ -229,7 +242,22 @@ osg::Group*
 FeatureNodeFactory::getOrCreateStyleGroup(const Style& style,
                                           Session*     session)
 {
-    osg::Group* group = new osg::Group();
+    osg::Group* group = 0L;
+
+    // If we're draping, the style group will be a DrapeableNode.
+    const AltitudeSymbol* alt = style.get<AltitudeSymbol>();
+    if (alt &&
+        alt->clamping() == AltitudeSymbol::CLAMP_TO_TERRAIN &&
+        alt->technique() == AltitudeSymbol::TECHNIQUE_DRAPE )
+    {
+        group = new DrapeableNode();
+    }
+
+    // Otherwise, a normal group.
+    if ( !group )
+    {
+        group = new osg::Group();
+    }
 
     // apply necessary render styles.
     const RenderSymbol* render = style.get<RenderSymbol>();
diff --git a/src/osgEarthFeatures/FeatureSource b/src/osgEarthFeatures/FeatureSource
index 30c1eb3..096ca1a 100644
--- a/src/osgEarthFeatures/FeatureSource
+++ b/src/osgEarthFeatures/FeatureSource
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -54,9 +54,9 @@ namespace osgEarth { namespace Features
         optional<std::string>& name() { return _name; }
         const optional<std::string>& name() const { return _name; }
 
-        /** List of filteres to apply to features read from this source */
-        FeatureFilterList& filters() { return _filters; }
-        const FeatureFilterList& filters() const { return _filters; }
+        /** Set of FeatureFilter options. */
+        std::vector<ConfigOptions>& filters() { return _filterOptions; }
+        const std::vector<ConfigOptions>& filters() const { return _filterOptions; }
 
         /** Opens the feature data for writing, if supported */
         optional<bool>& openWrite() { return _openWrite; }
@@ -70,6 +70,10 @@ namespace osgEarth { namespace Features
         optional<GeoInterpolation>& geoInterp() { return _geoInterp; }
         const optional<GeoInterpolation>& geoInterp() const { return _geoInterp; }
 
+        /** The feature attribute to use as the fid for the features from this FeatureSource*/
+        optional<std::string>& fidAttribute() { return _fidAttribute; }
+        const optional<std::string>& fidAttribute() const { return _fidAttribute; }
+
     public:
         FeatureSourceOptions( const ConfigOptions& options =ConfigOptions() );
         virtual ~FeatureSourceOptions();
@@ -84,12 +88,13 @@ namespace osgEarth { namespace Features
     private:
         void fromConfig( const Config& conf );
 
-        FeatureFilterList          _filters;
+        std::vector<ConfigOptions> _filterOptions;
         optional<std::string>      _name;
         optional< bool >           _openWrite;
         optional<ProfileOptions>   _profile;
         optional<CachePolicy>      _cachePolicy;
         optional<GeoInterpolation> _geoInterp;
+        optional<std::string>      _fidAttribute;
     };
 
     /**
@@ -104,14 +109,25 @@ namespace osgEarth { namespace Features
          */
         FeatureSource(
             const ConfigOptions&  options =ConfigOptions(),
-            const osgDB::Options* dbOptions =0L );
+            const osgDB::Options* readOptions =0L );
+
+        /**
+         * Opens the feature source and returns an initial status.
+         */
+        const Status& open(const osgDB::Options* readOptions);
+        const Status& open() { return open(0L); }
+
+        /**
+         * Status of the feature source
+         */
+        const Status& getStatus() const { return _status; }
 
         /**
          * Gets a reference to the metadata that describes features that you can
          * get from this FeatureSource. A valid feature profile indiciates that the
          * feature source successfully initialized.
          */
-        const FeatureProfile* getFeatureProfile() const;
+        const FeatureProfile* getFeatureProfile() const { return _featureProfile.get(); }
 
         /**
          * Gets the options that were passed into this object's CTOR.
@@ -124,7 +140,8 @@ namespace osgEarth { namespace Features
          *
          * Caller takes ownership of the returned object.
          */
-        virtual FeatureCursor* createFeatureCursor( const Symbology::Query& query =Symbology::Query() ) =0;
+        virtual FeatureCursor* createFeatureCursor(const Symbology::Query& query) =0;
+        FeatureCursor* createFeatureCursor() { return createFeatureCursor(Symbology::Query()); }
 
         /**
          * Whether this FeatureSource supports inserting and deleting features
@@ -200,6 +217,12 @@ namespace osgEarth { namespace Features
          */
         bool isBlacklisted( FeatureID fid ) const; 
 
+        /**
+         * Sets the feature profile for this source.
+         * This is required. Usually the subclass should call this from initialize().
+         */
+        void setFeatureProfile(const FeatureProfile* profile);
+
 
     public: // Styling
 
@@ -228,23 +251,28 @@ namespace osgEarth { namespace Features
         virtual const char* className() const { return "FeatureSource"; }
         virtual const char* libraryName() const { return "osgEarthFeatures"; }
 
-
         /**
-         * Initialize the FeatureSource.
+         * Dirties the feature profile
          */
-        virtual void initialize( const osgDB::Options* dbOptions =0L ) { }
-
-        /** Dirties the feature profile */
         void dirtyFeatureProfile() { _featureProfile = 0;}
 
+        
+        void setReadOptions(const osgDB::Options* readOptions) { _readOptions = readOptions; }
+        
     protected:
+        
+        /**
+         * Initialize the FeatureSource.
+         * If you override this function, please call this base implementation from within.
+         */
+        virtual Status initialize(const osgDB::Options* readOptions) =0;
 
         /**
          * Creates and returns a metadata structure describing the features in a named
          * feature class. This method is called by the public function getFeatureProfile()
          * in this same object to create the metadata structure.
          */
-        virtual const FeatureProfile* createFeatureProfile() =0;
+        //virtual const FeatureProfile* createFeatureProfile(int dummy) =0;
 
         /**
          * DTOR is protected to prevent this object from being allocated on the stack.
@@ -252,25 +280,31 @@ namespace osgEarth { namespace Features
         virtual ~FeatureSource();
 
         /** Access the raw DB options that came in */
-        const osgDB::Options* dbOptions() const { return _dbOptions.get(); }
+        const osgDB::Options* getReadOptions() const { return _readOptions.get(); }
 
         /** The URI context (for resolving relative paths) */
         const URIContext& uriContext() const { return _uriContext; }
 
-        /** The Cache passed in via the dbOptions */
-        Cache* getCache() const { return _cache.get(); }            
+        /** Convenience function to apply the filters to a FeatureList */
+        void applyFilters(FeatureList& features, const GeoExtent& extent) const;
+
+        /** Subclass can call this if the status changes */
+        void setStatus(const Status& value) { _status = value; }
 
     private:
         const FeatureSourceOptions         _options;
         osg::ref_ptr<const FeatureProfile> _featureProfile;
         Threading::Mutex                   _createMutex;
 
-        osg::ref_ptr<const osgDB::Options> _dbOptions;
+        osg::ref_ptr<const osgDB::Options> _readOptions;
         URIContext                         _uriContext;
-        osg::observer_ptr<Cache>           _cache;
 
         Threading::ReadWriteMutex          _blacklistMutex;
         std::set<FeatureID>                _blacklist;
+        
+        FeatureFilterList                  _filters;
+
+        Status                             _status;
 
         friend class Map;
         friend class FeatureSourceFactory;
diff --git a/src/osgEarthFeatures/FeatureSource.cpp b/src/osgEarthFeatures/FeatureSource.cpp
index f5411fa..2371bf7 100644
--- a/src/osgEarthFeatures/FeatureSource.cpp
+++ b/src/osgEarthFeatures/FeatureSource.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -39,10 +39,11 @@ DriverConfigOptions( options )
 
 FeatureSourceOptions::~FeatureSourceOptions()
 {
+    //nop
 }
 
 void
-FeatureSourceOptions::fromConfig( const Config& conf )
+FeatureSourceOptions::fromConfig(const Config& conf)
 {
     unsigned numResamples = 0;
 
@@ -52,40 +53,20 @@ FeatureSourceOptions::fromConfig( const Config& conf )
     conf.getObjIfSet( "cache_policy", _cachePolicy );
     conf.getIfSet   ( "geo_interpolation", "great_circle", _geoInterp, GEOINTERP_GREAT_CIRCLE );
     conf.getIfSet   ( "geo_interpolation", "rhumb_line",   _geoInterp, GEOINTERP_RHUMB_LINE );
-
-    const ConfigSet& children = conf.children();
-    for( ConfigSet::const_iterator i = children.begin(); i != children.end(); ++i )
-    {
-        const Config& child = *i;
-
-        if (!child.empty())
-        {
-            FeatureFilter* filter = FeatureFilterRegistry::instance()->create( child );
-            if (filter)
-            {
-                //Do some checks to make sure resample filters are applied before buffering.
-                ResampleFilter* resample = dynamic_cast< ResampleFilter*>( filter );
-                BufferFilter* buffer = dynamic_cast< BufferFilter*>(filter );
-                if (resample)
-                {
-                    numResamples++;
-                }
-                else if (buffer)
-                {
-                    if ( numResamples > 0 )
-                    {
-                        OE_WARN << LC 
-                            << "Warning: Resampling should be applied after buffering, as buffering"
-                            << " will remove colinear segments created by the resample operation."
-                            << std::endl;
-                    }
-                }
-
-                OE_DEBUG << "Added FeatureFilter " << filter->getConfig().toJSON(true) << std::endl;
-                _filters.push_back( filter );
-            }
-        }        
+    conf.getIfSet   ( "fid_attribute", _fidAttribute );
+
+    // For backwards-compatibility (before adding the "filters" block)
+    // TODO: Remove at some point in the distant future.
+    const std::string bcstrings[3] = { "resample", "buffer", "convert" };
+    for(unsigned i=0; i<3; ++i) {
+        if ( conf.hasChild(bcstrings[i]) ) {
+            _filterOptions.push_back( conf.child(bcstrings[i]) );
+        }
     }
+
+    const Config& filters = conf.child("filters");
+    for(ConfigSet::const_iterator i = filters.children().begin(); i != filters.children().end(); ++i)
+        _filterOptions.push_back( *i );
 }
 
 Config
@@ -99,10 +80,16 @@ FeatureSourceOptions::getConfig() const
     conf.updateObjIfSet( "cache_policy", _cachePolicy );
     conf.updateIfSet   ( "geo_interpolation", "great_circle", _geoInterp, GEOINTERP_GREAT_CIRCLE );
     conf.updateIfSet   ( "geo_interpolation", "rhumb_line",   _geoInterp, GEOINTERP_RHUMB_LINE );
-    
-    for( FeatureFilterList::const_iterator i = _filters.begin(); i != _filters.end(); ++i )
+    conf.updateIfSet   ( "fid_attribute", _fidAttribute );
+
+    if ( !_filterOptions.empty() )
     {
-        conf.update( i->get()->getConfig() );        
+        Config filters;
+        for(unsigned i=0; i<_filterOptions.size(); ++i)
+        {
+            filters.add( _filterOptions[i].getConfig() );
+        }
+        conf.update( "filters", filters );
     }
 
     return conf;
@@ -111,41 +98,50 @@ FeatureSourceOptions::getConfig() const
 //------------------------------------------------------------------------
 
 FeatureSource::FeatureSource(const ConfigOptions&  options,
-                             const osgDB::Options* dbOptions) :
+                             const osgDB::Options* readOptions) :
 _options( options )
 {    
-    _dbOptions  = dbOptions;
-    _uriContext = URIContext( dbOptions );
-    _cache      = Cache::get( dbOptions );
+    _readOptions  = readOptions;
+    _uriContext  = URIContext( _readOptions.get() );
 }
 
 FeatureSource::~FeatureSource()
 {
+    //nop
 }
 
-const FeatureProfile*
-FeatureSource::getFeatureProfile() const
+const Status&
+FeatureSource::open(const osgDB::Options* readOptions)
 {
-    if ( !_featureProfile.valid() )
+    if ( readOptions )
+        _readOptions = readOptions;
+    
+    // Create and initialize the filters.
+    for(unsigned i=0; i<_options.filters().size(); ++i)
     {
-        FeatureSource* nonConstThis = const_cast<FeatureSource*>(this);
-
-        ScopedLock<Mutex> doubleCheckLock( nonConstThis->_createMutex );
+        const ConfigOptions& conf = _options.filters().at(i);
+        FeatureFilter* filter = FeatureFilterRegistry::instance()->create( conf.getConfig(), 0L );
+        if ( filter )
         {
-            if ( !_featureProfile.valid() )
-            {
-                // caching pattern                
-                nonConstThis->_featureProfile = nonConstThis->createFeatureProfile();
-            }
+            _filters.push_back( filter );
+            filter->initialize( readOptions );
         }
     }
-    return _featureProfile.get();
+
+    _status = initialize(readOptions);
+    return _status;
+}
+
+void
+FeatureSource::setFeatureProfile(const FeatureProfile* fp)
+{
+    _featureProfile = fp;
 }
 
 const FeatureFilterList&
 FeatureSource::getFilters() const
 {
-    return _options.filters();
+    return _filters;
 }
 
 const FeatureSchema&
@@ -183,6 +179,22 @@ FeatureSource::isBlacklisted( FeatureID fid ) const
     return _blacklist.find( fid ) != _blacklist.end();
 }
 
+void
+FeatureSource::applyFilters(FeatureList& features, const GeoExtent& extent) const
+{
+    // apply filters before returning.
+    if ( !getFilters().empty() )
+    {
+        FilterContext cx;
+        cx.setProfile( getFeatureProfile() );
+        cx.extent() = extent;
+        for(FeatureFilterList::const_iterator filter = getFilters().begin(); filter != getFilters().end(); ++filter)
+        {
+            cx = filter->get()->push( features, cx );
+        }
+    }
+}
+
 //------------------------------------------------------------------------
 
 #undef  LC
@@ -227,5 +239,7 @@ FeatureSourceFactory::create( const FeatureSourceOptions& options )
 const FeatureSourceOptions&
 FeatureSourceDriver::getFeatureSourceOptions( const osgDB::ReaderWriter::Options* rwopt ) const
 {
-    return *static_cast<const FeatureSourceOptions*>( rwopt->getPluginData( FEATURE_SOURCE_OPTIONS_TAG ) );
+    static FeatureSourceOptions s_default;
+    const void* data = rwopt->getPluginData(FEATURE_SOURCE_OPTIONS_TAG);
+    return data ? *static_cast<const FeatureSourceOptions*>(data) : s_default;
 }
diff --git a/src/osgEarthFeatures/FeatureSourceIndexNode b/src/osgEarthFeatures/FeatureSourceIndexNode
index 19732ee..06cae37 100644
--- a/src/osgEarthFeatures/FeatureSourceIndexNode
+++ b/src/osgEarthFeatures/FeatureSourceIndexNode
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -86,6 +86,8 @@ namespace osgEarth { namespace Features
 
         Feature* getFeature(ObjectID oid) const;
 
+        ObjectID getObjectID(FeatureID fid) const;
+
         int size() const { return _fids.size(); }
 
     public: // Functions called by FeatureSourceIndexNode
@@ -135,6 +137,11 @@ namespace osgEarth { namespace Features
         OIDMap     _oids;
         FIDMap     _fids;
         FeatureMap _embeddedFeatures;
+
+        void update(osg::Drawable*, std::map<ObjectID,ObjectID>&, const FIDMap&, FIDMap&);
+        void update(osg::Node*,     std::map<ObjectID,ObjectID>&, const FIDMap&, FIDMap&);
+
+        friend class FeatureSourceIndexNode;
     };
 
 
@@ -146,33 +153,59 @@ namespace osgEarth { namespace Features
                                                            public FeatureIndexBuilder
     {
     public:
+        META_Node(osgEarth::Features, FeatureSourceIndexNode);
+        typedef std::map<FeatureID, osg::ref_ptr<RefIDPair> > FIDMap;
+
+        /** default ctor */
+        FeatureSourceIndexNode();
+
+        /** Construct with an index */
         FeatureSourceIndexNode(FeatureSourceIndex* index);
 
+        /** Copy */
+        FeatureSourceIndexNode(const FeatureSourceIndexNode& rhs, const osg::CopyOp& copy);
+
         /** The index referenced by this node. */
+        void setIndex(FeatureSourceIndex* index) { _index = index; }
         FeatureSourceIndex* getIndex() { return _index.get(); }
 
         /** Fetches the entire set of FIDs registered with the index by this node. */
         bool getAllFIDs(std::vector<FeatureID>& output) const;
 
+        /** Finds a FeatureSourceIndexNode in a scene graph. */
+        static FeatureSourceIndexNode* get(osg::Node* graph);
+
     public: // FeatureIndexBuilder
 
         ObjectID tagDrawable    (osg::Drawable* drawable, Feature* feature);
         ObjectID tagAllDrawables(osg::Node*     node,     Feature* feature);
         ObjectID tagNode        (osg::Node*     node,     Feature* feature);
 
+    public: // To support serialization only - do not use directly
+
+        const FIDMap& getFIDMap() const { return _fids; }
+        void setFIDMap(const FIDMap& fids);
+
+        void reIndex(std::map<ObjectID,ObjectID>&);
+        void reIndexDrawable(osg::Drawable* drawable, std::map<ObjectID,ObjectID>& oldNew, FIDMap& newFIDMap);
+        void reIndexNode(osg::Node* node, std::map<ObjectID,ObjectID>& oldNew, FIDMap& newFIDMap);
+
+        /**
+         * Call this after deserializing a scene graph that may contain FeatureSourceIndexNodes.
+         * It will locate them, assign the index, and reconsistute the object IDs in the index.
+         */
+        static void reconstitute(osg::Node* graph, FeatureSourceIndex* index);
+
     protected:
         
         /** dtor - unregisters any FIDs added by this node. */
         virtual ~FeatureSourceIndexNode();
 
-    private:
-        typedef std::map<FeatureID, osg::ref_ptr<RefIDPair> > FIDMap;
-        osg::ref_ptr<FeatureSourceIndex> _index;
+    private: // serializable
         FIDMap _fids;
 
-    public:
-        virtual const char* className()   const { return "FeatureSourceIndexNode"; }
-        virtual const char* libraryName() const { return "osgEarthFeatures"; }
+    private: // transient
+        osg::ref_ptr<FeatureSourceIndex> _index;
     };
 
 } } // namespace osgEarth::Features
diff --git a/src/osgEarthFeatures/FeatureSourceIndexNode.cpp b/src/osgEarthFeatures/FeatureSourceIndexNode.cpp
index 393e1e2..4f1e12e 100644
--- a/src/osgEarthFeatures/FeatureSourceIndexNode.cpp
+++ b/src/osgEarthFeatures/FeatureSourceIndexNode.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -74,13 +74,22 @@ FeatureSourceIndexOptions::getConfig() const
 #undef  LC
 #define LC "[FeatureSourceIndexNode] "
 
+FeatureSourceIndexNode::FeatureSourceIndexNode()
+{
+    //nop
+}
+
+FeatureSourceIndexNode::FeatureSourceIndexNode(const FeatureSourceIndexNode& rhs, const osg::CopyOp& copy) :
+osg::Group(rhs, copy)
+{
+    _index = rhs._index.get();
+    _fids  = rhs._fids;
+}
+
 FeatureSourceIndexNode::FeatureSourceIndexNode(FeatureSourceIndex* index) :
 _index( index )
 {
-    if ( !index )
-    {
-        OE_WARN << LC << "INTERNAL ERROR: created a feature source index node with a NULL index.\n";
-    }
+    //nop
 }
 
 FeatureSourceIndexNode::~FeatureSourceIndexNode()
@@ -137,6 +146,200 @@ FeatureSourceIndexNode::getAllFIDs(std::vector<FeatureID>& output) const
     return true;
 }
 
+void
+FeatureSourceIndexNode::setFIDMap(const FeatureSourceIndexNode::FIDMap& fids)
+{
+    _fids = fids;
+    //todo
+}
+
+namespace
+{
+    /** Visitor that finds FeatureSourceIndexNodes, assigns their index, and 
+     *  reconstitutes their object ID maps. */
+    struct Reconstitute : public osg::NodeVisitor
+    {
+        FeatureSourceIndex* _index;
+        std::map<ObjectID,ObjectID> _oldToNew;
+
+        Reconstitute(FeatureSourceIndex* index) :
+            _index(index)
+        {
+            setNodeMaskOverride(~0);
+            setTraversalMode(TRAVERSE_ALL_CHILDREN);
+        }
+
+        void apply(osg::Node& node)
+        {
+            FeatureSourceIndexNode* indexNode = dynamic_cast<FeatureSourceIndexNode*>(&node);
+            if (indexNode)
+            {
+                //OE_INFO << LC << "Reconstituting index...\n";
+                indexNode->setIndex(_index);
+                indexNode->reIndex(_oldToNew);
+            }
+            traverse(node);
+        }
+    };
+
+    /** Visitor that re-indexes objects after deserialization. */
+    struct ReIndex : public osg::NodeVisitor
+    {
+        FeatureSourceIndexNode*        _indexNode;
+        FeatureSourceIndexNode::FIDMap _newFIDMap;
+        std::map<ObjectID,ObjectID>&   _oldToNew;
+
+        ReIndex(FeatureSourceIndexNode* indexNode, std::map<ObjectID,ObjectID>& oldToNew) :
+            _indexNode(indexNode), _oldToNew(oldToNew)
+        {
+            setTraversalMode(TRAVERSE_ALL_CHILDREN);
+            setNodeMaskOverride(~0);
+        }
+
+        void apply(osg::Node& node)
+        {
+            _indexNode->reIndexNode(&node, _oldToNew, _newFIDMap);
+            traverse(node);
+        }
+
+        void apply(osg::Geode& geode)
+        {
+            _indexNode->reIndexNode(&geode, _oldToNew, _newFIDMap);
+            for (unsigned i = 0; i < geode.getNumDrawables(); ++i)
+            {
+                _indexNode->reIndexDrawable(geode.getDrawable(i), _oldToNew, _newFIDMap);
+            }
+            traverse(geode);
+        }
+    };
+}
+
+void
+FeatureSourceIndexNode::reconstitute(osg::Node* graph, FeatureSourceIndex* index)
+{
+    if ( !graph || !index )
+    {
+        OE_WARN << LC << "INTERNAL ERROR cannot call reconsitute with null graph or null index\n";
+        return;
+    }
+
+    Reconstitute visitor(index);
+    graph->accept(visitor);
+}
+
+void
+FeatureSourceIndexNode::reIndex(std::map<ObjectID,ObjectID>& oidmappings)
+{
+    ReIndex visitor(this, oidmappings);
+    this->accept(visitor);
+    _fids = visitor._newFIDMap;
+    //OE_INFO << LC << "Reindexed " << _fids.size() << " mappings\n";
+}
+
+void
+FeatureSourceIndexNode::reIndexDrawable(osg::Drawable* drawable, std::map<ObjectID,ObjectID>& oldNew, FIDMap& newFIDMap)
+{
+    if ( !drawable || !_index.valid() ) return;
+
+    _index->update(drawable, oldNew, _fids, newFIDMap);
+}
+
+void
+FeatureSourceIndexNode::reIndexNode(osg::Node* node, std::map<ObjectID,ObjectID>& oldNew, FIDMap& newFIDMap)
+{
+    if (!node || !_index.valid()) return;
+
+    _index->update(node, oldNew, _fids, newFIDMap);
+}
+
+FeatureSourceIndexNode* FeatureSourceIndexNode::get(osg::Node* graph)
+{
+    return graph ? osgEarth::findTopMostNodeOfType<FeatureSourceIndexNode>(graph) : 0L;
+}
+
+//-----------------------------------------------------------------------------
+
+#undef  LC
+#define LC "[FeatureSourceIndex Serializer] "
+
+// OSG SERIALIZER for FeatureSourceIndexNode
+#include <osgDB/ObjectWrapper>
+#include <osgDB/InputStream>
+#include <osgDB/OutputStream>
+
+namespace
+{
+    bool checkFIDMap(const FeatureSourceIndexNode& node)
+    {
+        return !node.getFIDMap().empty();
+    }
+
+    bool writeFIDMap(osgDB::OutputStream& os, const FeatureSourceIndexNode& node)
+    {
+        const FeatureSourceIndexNode::FIDMap& fids = node.getFIDMap();
+
+        os.writeSize(fids.size());
+        os << os.BEGIN_BRACKET << std::endl;
+        {
+            for (FeatureSourceIndexNode::FIDMap::const_iterator i = fids.begin(); i != fids.end(); ++i)
+            {
+                const RefIDPair* idPair = i->second.get();
+                os << idPair->_fid << idPair->_oid;
+            }
+        }
+        os << os.END_BRACKET << std::endl;
+
+        return true;
+    }
+
+    bool readFIDMap(osgDB::InputStream& is, FeatureSourceIndexNode& node)
+    {
+        FeatureSourceIndexNode::FIDMap fids;
+        FeatureID fid;
+        ObjectID oid;
+
+        unsigned size = is.readSize();
+        is >> is.BEGIN_BRACKET;
+        {
+            for (unsigned i=0; i<size; ++i)
+            {
+                is >> fid >> oid;
+                fids[fid] = new RefIDPair(fid, oid);
+            }
+        }
+        is >> is.END_BRACKET;
+        node.setFIDMap(fids);
+
+        return true;
+    }
+
+#if 0
+    bool checkEmbeddedFeatures(const FeatureSourceIndexNode& node)
+    {
+        return false; //todo
+    }
+
+    bool writeEmbeddedFeatures(osgDB::OutputStream& os, const FeatureSourceIndexNode& node)
+    {
+        return true;
+    }
+
+    bool readEmbeddedFeatures(osgDB::InputStream& is, FeatureSourceIndexNode& node)
+    {
+        return true;
+    }
+#endif
+
+    REGISTER_OBJECT_WRAPPER(
+        FeatureSourceIndexNode,
+        new osgEarth::Features::FeatureSourceIndexNode,
+        osgEarth::Features::FeatureSourceIndexNode,
+        "osg::Object osg::Node osg::Group osgEarth::Features::FeatureSourceIndexNode")
+    {
+        ADD_USER_SERIALIZER(FIDMap);
+    }
+}
+
 //-----------------------------------------------------------------------------
 
 #undef  LC
@@ -292,3 +495,74 @@ FeatureSourceIndex::getFeature(ObjectID oid) const
     }
     return feature;
 }
+
+ObjectID
+FeatureSourceIndex::getObjectID(FeatureID fid) const
+{
+    Threading::ScopedMutexLock lock(_mutex);
+    FIDMap::const_iterator i = _fids.find(fid);
+    if ( i != _fids.end() )
+        return i->second->_oid;
+    else
+        return OSGEARTH_OBJECTID_EMPTY;
+}
+
+// When Feature index data is deserialized, the old serialized ObjectIDs are 
+// no longer valid. This method will re-install the mappings in the master index
+// and write new local mappings with new ObjectIDs.
+void
+FeatureSourceIndex::update(osg::Drawable* drawable, std::map<ObjectID,ObjectID>& oldToNew, const FIDMap& oldFIDMap, FIDMap& newFIDMap)
+{
+    unsigned count = 0;
+    if (_masterIndex->updateObjectIDs(drawable, oldToNew, this))
+    {
+        for (std::map<ObjectID, ObjectID>::const_iterator i = oldToNew.begin(); i != oldToNew.end(); ++i)
+        {
+            const ObjectID& oldoid = i->first;
+            const ObjectID& newoid = i->second;
+
+            for (FIDMap::const_iterator j = oldFIDMap.begin(); j != oldFIDMap.end(); ++j)
+            {
+                const RefIDPair* rip = j->second.get();
+                if (rip && rip->_oid == oldoid)
+                {
+                    RefIDPair* newrip = new RefIDPair(rip->_fid, newoid);
+                    _oids[newoid] = rip->_fid;
+                    _fids[rip->_fid] = newrip;
+                    newFIDMap[rip->_fid] = newrip;
+                    ++count;
+                }
+            }
+        }
+    }
+}
+
+// When Feature index data is deserialized, the old serialized ObjectIDs are 
+// no longer valid. This method will re-install the mappings in the master index
+// and write new local mappings with new ObjectIDs.
+void
+FeatureSourceIndex::update(osg::Node* node, std::map<ObjectID,ObjectID>& oldToNew, const FIDMap& oldFIDMap, FIDMap& newFIDMap)
+{
+    unsigned count = 0;
+    if (_masterIndex->updateObjectID(node, oldToNew, this))
+    {
+        for (std::map<ObjectID, ObjectID>::const_iterator i = oldToNew.begin(); i != oldToNew.end(); ++i)
+        {
+            const ObjectID& oldoid = i->first;
+            const ObjectID& newoid = i->second;
+
+            for (FIDMap::const_iterator j = oldFIDMap.begin(); j != oldFIDMap.end(); ++j)
+            {
+                const RefIDPair* rip = j->second.get();
+                if (rip && rip->_oid == oldoid)
+                {
+                    RefIDPair* newrip = new RefIDPair(rip->_fid, newoid);
+                    _oids[newoid] = rip->_fid;
+                    _fids[rip->_fid] = newrip;
+                    newFIDMap[rip->_fid] = newrip;
+                    ++count;
+                }
+            }
+        }
+    }
+}
diff --git a/src/osgEarthFeatures/FeatureTileSource b/src/osgEarthFeatures/FeatureTileSource
index 32adf72..4f4ef6b 100644
--- a/src/osgEarthFeatures/FeatureTileSource
+++ b/src/osgEarthFeatures/FeatureTileSource
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -159,6 +159,12 @@ namespace osgEarth { namespace Features
             osg::Image* image,
             osg::Referenced* buildData ) { return true; }
 
+        /**
+         * Gets all of the features to be rendered for the given query.
+         * If a TileKey is specified on the query this will attempt to fallback on previous levels to get feature data.
+         */
+        void getFeatures(const Query& query, const GeoExtent& imageExtent, FeatureList& features);
+
     public:
 
         // META_Object specialization:
diff --git a/src/osgEarthFeatures/FeatureTileSource.cpp b/src/osgEarthFeatures/FeatureTileSource.cpp
index 44a5001..dc7d844 100644
--- a/src/osgEarthFeatures/FeatureTileSource.cpp
+++ b/src/osgEarthFeatures/FeatureTileSource.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -90,6 +90,7 @@ _initialized( false )
     {
         _features = _options.featureSource().get();
     }
+
     else if ( _options.featureOptions().isSet() )
     {
         _features = FeatureSourceFactory::create( _options.featureOptions().value() );
@@ -100,44 +101,44 @@ _initialized( false )
     }
 }
 
-TileSource::Status 
-FeatureTileSource::initialize(const osgDB::Options* dbOptions)
+Status 
+FeatureTileSource::initialize(const osgDB::Options* readOptions)
 {
     if ( !getProfile() )
     {
         setProfile( osgEarth::Registry::instance()->getGlobalGeodeticProfile() );
     }            
 
-    if ( _features.valid() )
-    {
-        _features->initialize( dbOptions );
+    if ( !_features.valid() )
+        return Status::Error(Status::ServiceUnavailable, "No feature source");
+
+    // attempt to open the feature source:
+    const Status& sourceStatus = _features->open(readOptions);
+    if (sourceStatus.isError())
+        return sourceStatus;
 
-        // Try to fill the DataExtent list using the FeatureProfile
-        const FeatureProfile* featureProfile = _features->getFeatureProfile();
-        if (featureProfile != NULL)
+    // Try to fill the DataExtent list using the FeatureProfile
+    const FeatureProfile* featureProfile = _features->getFeatureProfile();
+    if (featureProfile != NULL)
+    {
+        if (featureProfile->getProfile() != NULL)
         {
-            if (featureProfile->getProfile() != NULL)
-            {
-                // Use specified profile's GeoExtent
-                getDataExtents().push_back(DataExtent(featureProfile->getProfile()->getExtent()));
-            }
-            else if (featureProfile->getExtent().isValid() == true)
-            {
-                // Use FeatureProfile's GeoExtent
-                getDataExtents().push_back(DataExtent(featureProfile->getExtent()));
-            }
+            // Use specified profile's GeoExtent
+            getDataExtents().push_back(DataExtent(featureProfile->getProfile()->getExtent()));
+        }
+        else if (featureProfile->getExtent().isValid() == true)
+        {
+            // Use FeatureProfile's GeoExtent
+            getDataExtents().push_back(DataExtent(featureProfile->getExtent()));
         }
-    }
-    else
-    {
-        return Status::Error("No FeatureSource provided; nothing will be rendered");
     }
 
     // Create a session for feature processing. No map.
-    _session = new Session( 0L, _options.styles().get(), _features.get(), dbOptions );
+    _session = new Session( 0L, _options.styles().get(), _features.get(), readOptions );
 
     _initialized = true;
-    return STATUS_OK;
+
+    return Status::OK();
 }
 
 void
@@ -175,11 +176,15 @@ FeatureTileSource::createImage( const TileKey& key, ProgressCallback* progress )
 
     preProcess( image.get(), buildData.get() );
 
+    Query defaultQuery;
+    defaultQuery.tileKey() = key;
+
     // figure out if and how to style the geometry.
     if ( _features->hasEmbeddedStyles() )
     {
+
         // Each feature has its own embedded style data, so use that:
-        osg::ref_ptr<FeatureCursor> cursor = _features->createFeatureCursor( Query() );
+        osg::ref_ptr<FeatureCursor> cursor = _features->createFeatureCursor(defaultQuery);
         while( cursor.valid() && cursor->hasMore() )
         {
             osg::ref_ptr< Feature > feature = cursor->nextFeature();
@@ -205,19 +210,84 @@ FeatureTileSource::createImage( const TileKey& key, ProgressCallback* progress )
             for( StyleSelectorList::const_iterator i = styles->selectors().begin(); i != styles->selectors().end(); ++i )
             {
                 const StyleSelector& sel = *i;
-                const Style* style = styles->getStyle( sel.getSelectedStyleName() );
-                queryAndRenderFeaturesForStyle( *style, sel.query().value(), buildData.get(), key.getExtent(), image.get() );
+
+                if ( sel.styleExpression().isSet() )
+                {
+                    const FeatureProfile* featureProfile = _features->getFeatureProfile();
+
+                    // establish the working bounds and a context:
+                    FilterContext context( _session.get(), featureProfile);
+                    StringExpression styleExprCopy(  sel.styleExpression().get() );
+
+                    FeatureList features;
+                    getFeatures(defaultQuery, key.getExtent(), features);
+                    if (!features.empty())
+                    {
+                        for (FeatureList::iterator itr = features.begin(); itr != features.end(); ++itr)
+                        {
+                            Feature* feature = itr->get();
+
+                            const std::string& styleString = feature->eval( styleExprCopy, &context );
+                            if (!styleString.empty() && styleString != "null")
+                            {
+                                // resolve the style:
+                                Style combinedStyle;
+
+                                // if the style string begins with an open bracket, it's an inline style definition.
+                                if ( styleString.length() > 0 && styleString.at(0) == '{' )
+                                {
+                                    Config conf( "style", styleString );
+                                    conf.setReferrer( sel.styleExpression().get().uriContext().referrer() );
+                                    conf.set( "type", "text/css" );
+                                    combinedStyle = Style(conf);
+                                }
+
+                                // otherwise, look up the style in the stylesheet. Do NOT fall back on a default
+                                // style in this case: for style expressions, the user must be explicity about 
+                                // default styling; this is because there is no other way to exclude unwanted
+                                // features.
+                                else
+                                {
+                                    const Style* selectedStyle = _session->styles()->getStyle(styleString, false);
+                                    if ( selectedStyle )
+                                        combinedStyle = *selectedStyle;
+                                }
+
+                                if (!combinedStyle.empty())
+                                {
+                                    FeatureList list;
+                                    list.push_back( feature );
+
+                                    renderFeaturesForStyle(
+                                        _session.get(),
+                                        combinedStyle,
+                                        list,
+                                        buildData.get(),
+                                        key.getExtent(),
+                                        image.get() );
+                                }
+                            }
+                        }
+                    }                    
+                }
+                else
+                {
+                    const Style* style = styles->getStyle( sel.getSelectedStyleName() );
+                    Query query = sel.query().get();
+                    query.tileKey() = key;
+                    queryAndRenderFeaturesForStyle( *style, query, buildData.get(), key.getExtent(), image.get() );
+                }
             }
         }
         else
         {
             const Style* style = styles->getDefaultStyle();
-            queryAndRenderFeaturesForStyle( *style, Query(), buildData.get(), key.getExtent(), image.get() );
+            queryAndRenderFeaturesForStyle( *style, defaultQuery, buildData.get(), key.getExtent(), image.get() );
         }
     }
     else
     {
-        queryAndRenderFeaturesForStyle( Style(), Query(), buildData.get(), key.getExtent(), image.get() );
+        queryAndRenderFeaturesForStyle( Style(), defaultQuery, buildData.get(), key.getExtent(), image.get() );
     }
 
     // final tile processing after all styles are done
@@ -234,6 +304,20 @@ FeatureTileSource::queryAndRenderFeaturesForStyle(const Style&     style,
                                                   const GeoExtent& imageExtent,
                                                   osg::Image*      out_image)
 {   
+    // Get the features
+    FeatureList features;
+    getFeatures(query, imageExtent, features );
+    if (!features.empty())
+    {
+        // Render them.
+        return renderFeaturesForStyle( _session.get(), style, features, data, imageExtent, out_image );
+    }
+    return false;
+}
+
+void
+FeatureTileSource::getFeatures(const Query& query, const GeoExtent& imageExtent, FeatureList& features)
+{
     // first we need the overall extent of the layer:
     const GeoExtent& featuresExtent = getFeatureSource()->getFeatureProfile()->getExtent();
     
@@ -251,45 +335,50 @@ FeatureTileSource::queryAndRenderFeaturesForStyle(const Style&     style,
             query.bounds().isSet() ? query.bounds()->unionWith( queryExtent.bounds() ) :
             queryExtent.bounds();
 
-        // query the feature source:
-        osg::ref_ptr<FeatureCursor> cursor = _features->createFeatureCursor( localQuery );
-
         // now copy the resulting feature set into a list, converting the data
         // types along the way if a geometry override is in place:
-        FeatureList cellFeatures;
-        while( cursor.valid() && cursor->hasMore() )
+        while (features.empty())
         {
-            Feature* feature = cursor->nextFeature();
-            Geometry* geom = feature->getGeometry();
-            if ( geom )
+            // query the feature source:
+            osg::ref_ptr<FeatureCursor> cursor = _features->createFeatureCursor( localQuery );
+
+            while( cursor.valid() && cursor->hasMore() )
             {
-                // apply a type override if requested:
-                if (_options.geometryTypeOverride().isSet() &&
-                    _options.geometryTypeOverride() != geom->getComponentType() )
+                Feature* feature = cursor->nextFeature();
+                Geometry* geom = feature->getGeometry();
+                if ( geom )
+                {
+                    // apply a type override if requested:
+                    if (_options.geometryTypeOverride().isSet() &&
+                        _options.geometryTypeOverride() != geom->getComponentType() )
+                    {
+                        geom = geom->cloneAs( _options.geometryTypeOverride().value() );
+                        if ( geom )
+                            feature->setGeometry( geom );
+                    }
+                }
+                if ( geom )
                 {
-                    geom = geom->cloneAs( _options.geometryTypeOverride().value() );
-                    if ( geom )
-                        feature->setGeometry( geom );
+                    features.push_back( feature );
                 }
             }
-            if ( geom )
+
+            // If we didn't get any features and we have a tilekey set, try falling back.
+            if (features.empty() && localQuery.tileKey().isSet())
+            {
+                localQuery.tileKey() = localQuery.tileKey().get().createParentKey();
+                if (!localQuery.tileKey()->valid())
+                {
+                    // We fell back all the way to lod 0 and got nothing, so bail.
+                    break;
+                }
+            }
+            else
             {
-                cellFeatures.push_back( feature );
+                // Just bail, we didn't get any features and aren't using tilekeys
+                break;
             }
         }
-
-        //OE_NOTICE
-        //    << "Rendering "
-        //    << cellFeatures.size()
-        //    << " features in ("
-        //    << queryExtent.toString() << ")"
-        //    << std::endl;
-
-        return renderFeaturesForStyle( _session.get(), style, cellFeatures, data, imageExtent, out_image );
-    }
-    else
-    {
-        return false;
     }
 }
 
diff --git a/src/osgEarthFeatures/Filter b/src/osgEarthFeatures/Filter
index 9a3ea8f..5c089ee 100644
--- a/src/osgEarthFeatures/Filter
+++ b/src/osgEarthFeatures/Filter
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -33,10 +33,15 @@ namespace osgEarth { namespace Features
     /**
      * Base class for a filter.
      */
-    class OSGEARTHFEATURES_EXPORT Filter : public osg::Referenced
+    class OSGEARTHFEATURES_EXPORT Filter : public osg::Object
     {
+    public:
+        META_Object(osgEarthFeatures, Filter);
+
     protected:
         virtual ~Filter();
+        Filter() : osg::Object() { }
+        Filter(const Filter& rhs, const osg::CopyOp& copyop) : osg::Object(rhs, copyop) { }
     };
 
     /**
@@ -45,13 +50,24 @@ namespace osgEarth { namespace Features
     class OSGEARTHFEATURES_EXPORT FeatureFilter : public Filter
     {
     public:
+        /**
+         * Push a list of features through the filter.
+         */
         virtual FilterContext push( FeatureList& input, FilterContext& context ) =0;
 
         /**
+         * Optionally initialize the filter.
+         */
+        virtual Status initialize(const osgDB::Options* readOptions) { return Status::OK(); }
+
+        /**
          * Serialize this FeatureFilter
          */
         virtual Config getConfig() const { return Config(); }
 
+    protected:
+        FeatureFilter() { }
+        FeatureFilter(const FeatureFilter& rhs, const osg::CopyOp& c) : Filter(rhs, c) { }
         virtual ~FeatureFilter();
     };
 
@@ -87,7 +103,7 @@ namespace osgEarth { namespace Features
         /**
          * Creates a FeatureFilter with the registered plugins from the given Config
          */
-        FeatureFilter* create( const Config& conf );
+        FeatureFilter* create(const Config& conf, const osgDB::Options* dbo);
 
     protected:
         FeatureFilterRegistry();
@@ -120,7 +136,17 @@ namespace osgEarth { namespace Features
 
 #define OSGEARTH_REGISTER_SIMPLE_FEATUREFILTER( KEY, CLASSNAME)\
     static osgEarth::Features::RegisterFeatureFilterProxy< osgEarth::Features::SimpleFeatureFilterFactory<CLASSNAME> > s_osgEarthRegisterFeatureFilterProxy_##CLASSNAME##KEY(new osgEarth::Features::SimpleFeatureFilterFactory<CLASSNAME>(#KEY));
+    
+
+    //--------------------------------------------------------------------
+
+    class OSGEARTHFEATURES_EXPORT FeatureFilterDriver : public osgDB::ReaderWriter
+    {
+    protected:
+        const ConfigOptions& getConfigOptions(const osgDB::Options* options) const;
+    };
 
+    //--------------------------------------------------------------------
 
     template<typename T>
     class TemplateFeatureFilter : public Filter, public T
diff --git a/src/osgEarthFeatures/Filter.cpp b/src/osgEarthFeatures/Filter.cpp
index 1d847d2..242ac9e 100644
--- a/src/osgEarthFeatures/Filter.cpp
+++ b/src/osgEarthFeatures/Filter.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -20,6 +20,7 @@
 #include <osgEarthSymbology/LineSymbol>
 #include <osgEarthSymbology/PointSymbol>
 #include <osgEarth/ECEF>
+#include <osgEarth/Registry>
 #include <osg/MatrixTransform>
 #include <osg/Point>
 #include <osg/LineWidth>
@@ -41,6 +42,9 @@ FeatureFilter::~FeatureFilter()
 
 /********************************************************************************/
         
+#undef  LC
+#define LC "[FeatureFilterRegistry] "
+
 FeatureFilterRegistry::FeatureFilterRegistry()
 {
 }
@@ -70,21 +74,62 @@ FeatureFilterRegistry::add( FeatureFilterFactory* factory )
     _factories.push_back( factory );
 }
 
+#define FEATURE_FILTER_OPTIONS_TAG "__osgEarth::FeatureFilterOptions"
+
 FeatureFilter*
-FeatureFilterRegistry::create( const Config& conf )
+FeatureFilterRegistry::create(const Config& conf, const osgDB::Options* dbo)
 {
-    for (FeatureFilterFactoryList::iterator itr = _factories.begin(); itr != _factories.end(); itr++)
+    std::string driver = conf.key();
+
+    osg::ref_ptr<FeatureFilter> result;
+
+    for (FeatureFilterFactoryList::iterator itr = _factories.begin(); result == 0L && itr != _factories.end(); itr++)
+    {
+        result = itr->get()->create( conf );
+    }
+
+    if ( !result.valid() )
+    {
+        // not found; try to load from plugin.
+        if ( driver.empty() )
+        {
+            OE_WARN << LC << "ILLEGAL- no driver set for feature filter" << std::endl;
+            return 0L;
+        }
+
+        ConfigOptions options(conf);
+
+        osg::ref_ptr<osgDB::Options> dbopt = Registry::instance()->cloneOrCreateOptions(dbo);
+        dbopt->setPluginData( FEATURE_FILTER_OPTIONS_TAG, (void*)&options );
+
+        std::string driverExt = std::string( ".osgearth_featurefilter_" ) + driver;
+        result = dynamic_cast<FeatureFilter*>( osgDB::readObjectFile( driverExt, dbopt.get() ) );
+    }
+
+    if ( !result.valid() )
     {
-        FeatureFilter* filter = itr->get()->create( conf );
-        if (filter) return filter;
+        OE_WARN << LC << "Failed to load FeatureFilter driver \"" << driver << "\"" << std::endl;
     }
-    return 0;
+
+    return result.release();
 } 
 
+const ConfigOptions&
+FeatureFilterDriver::getConfigOptions(const osgDB::Options* options) const
+{
+    static ConfigOptions s_default;
+    const void* data = options->getPluginData(FEATURE_FILTER_OPTIONS_TAG);
+    return data ? *static_cast<const ConfigOptions*>(data) : s_default;
+}
+
 /********************************************************************************/
 
+#undef  LC
+#define LC "[FeaturesToNodeFilter] "
+
 FeaturesToNodeFilter::~FeaturesToNodeFilter()
 {
+    //nop
 }
 
 void
diff --git a/src/osgEarthFeatures/FilterContext b/src/osgEarthFeatures/FilterContext
index 4cc6c45..b363076 100644
--- a/src/osgEarthFeatures/FilterContext
+++ b/src/osgEarthFeatures/FilterContext
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthFeatures/FilterContext.cpp b/src/osgEarthFeatures/FilterContext.cpp
index 0a1bbad..5c0e23b 100644
--- a/src/osgEarthFeatures/FilterContext.cpp
+++ b/src/osgEarthFeatures/FilterContext.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -42,7 +42,7 @@ _shaderPolicy( osgEarth::SHADERPOLICY_GENERATE )
         }
         else
         {
-            _resourceCache = new ResourceCache( session->getDBOptions() );
+            _resourceCache = new ResourceCache(); // session->getDBOptions() );
         }
     }
 
diff --git a/src/osgEarthFeatures/GeometryCompiler b/src/osgEarthFeatures/GeometryCompiler
index 9e295c2..5c16579 100644
--- a/src/osgEarthFeatures/GeometryCompiler
+++ b/src/osgEarthFeatures/GeometryCompiler
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -84,10 +84,6 @@ namespace osgEarth { namespace Features
         optional<bool>& useVertexBufferObjects() { return _useVertexBufferObjects;}
         const optional<bool>& useVertexBufferObjects() const { return _useVertexBufferObjects;}
 
-        /** Whether to combine resource library textures into a single texture array */        
-        optional<bool>& useTextureArrays() { return _useTextureArrays;}
-        const optional<bool>& useTextureArrays() const { return _useTextureArrays;}
-
         /** Whether to generate shader components on compiled geometry */
         optional<ShaderPolicy>& shaderPolicy() { return _shaderPolicy; }
         const optional<ShaderPolicy>& shaderPolicy() const { return _shaderPolicy; }
@@ -105,6 +101,11 @@ namespace osgEarth { namespace Features
         optional<bool>& validate() { return _validate; }
         const optional<bool>& validate() const { return _validate; }
 
+        /** Maximum size (angle, degrees) of a polygon tile, when breaking up a large polygon for tessellation;
+        only applies to geocentric maps - detault = 5.0 */
+        optional<float>& maxPolygonTilingAngle() { return _maxPolyTilingAngle; }
+        const optional<float>& maxPolygonTilingAngle() const { return _maxPolyTilingAngle; }
+
     public:
         Config getConfig() const;
         void mergeConfig( const Config& conf );
@@ -121,10 +122,10 @@ namespace osgEarth { namespace Features
         optional<bool>                 _ignoreAlt;
         optional<bool>                 _useVertexBufferObjects;
         optional<ShaderPolicy>         _shaderPolicy;
-        optional<bool>                 _useTextureArrays;
         optional<bool>                 _optimizeStateSharing;
         optional<bool>                 _optimize;
         optional<bool>                 _validate;
+        optional<float>                _maxPolyTilingAngle;
 
         void fromConfig( const Config& conf );
 
@@ -179,7 +180,11 @@ namespace osgEarth { namespace Features
 
         osg::Node* compile(
             Geometry*             geom,
-            const FilterContext&  context );
+            const Style&          style);
+
+        osg::Node* compile(
+            Geometry*             geom,
+            const FilterContext&  context);
 
         osg::Node* compile(
             FeatureList&          mungeableInput,
diff --git a/src/osgEarthFeatures/GeometryCompiler.cpp b/src/osgEarthFeatures/GeometryCompiler.cpp
index 9bfd420..c32037d 100644
--- a/src/osgEarthFeatures/GeometryCompiler.cpp
+++ b/src/osgEarthFeatures/GeometryCompiler.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -61,17 +61,17 @@ GeometryCompilerOptions::setDefaults(const GeometryCompilerOptions& defaults)
 // defaults.
 GeometryCompilerOptions::GeometryCompilerOptions(bool stockDefaults) :
 _maxGranularity_deg    ( 10.0 ),
-_mergeGeometry         ( false ),
+_mergeGeometry         ( true ),
 _clustering            ( false ),
 _instancing            ( false ),
 _ignoreAlt             ( false ),
 _useVertexBufferObjects( true ),
-_useTextureArrays      ( true ),
 _shaderPolicy          ( SHADERPOLICY_GENERATE ),
 _geoInterp             ( GEOINTERP_GREAT_CIRCLE ),
 _optimizeStateSharing  ( true ),
 _optimize              ( false ),
-_validate              ( false )
+_validate              ( false ),
+_maxPolyTilingAngle    ( 45.0f )
 {
    //nop
 }
@@ -86,12 +86,12 @@ _clustering            ( s_defaults.clustering().value() ),
 _instancing            ( s_defaults.instancing().value() ),
 _ignoreAlt             ( s_defaults.ignoreAltitudeSymbol().value() ),
 _useVertexBufferObjects( s_defaults.useVertexBufferObjects().value() ),
-_useTextureArrays      ( s_defaults.useTextureArrays().value() ),
 _shaderPolicy          ( s_defaults.shaderPolicy().value() ),
 _geoInterp             ( s_defaults.geoInterp().value() ),
 _optimizeStateSharing  ( s_defaults.optimizeStateSharing().value() ),
 _optimize              ( s_defaults.optimize().value() ),
-_validate              ( s_defaults.validate().value() )
+_validate              ( s_defaults.validate().value() ),
+_maxPolyTilingAngle    ( s_defaults.maxPolygonTilingAngle().value() )
 {
     fromConfig(_conf);
 }
@@ -108,10 +108,10 @@ GeometryCompilerOptions::fromConfig( const Config& conf )
     conf.getIfSet   ( "geo_interpolation", "great_circle", _geoInterp, GEOINTERP_GREAT_CIRCLE );
     conf.getIfSet   ( "geo_interpolation", "rhumb_line",   _geoInterp, GEOINTERP_RHUMB_LINE );
     conf.getIfSet   ( "use_vbo", _useVertexBufferObjects);
-    conf.getIfSet   ( "use_texture_arrays", _useTextureArrays );
     conf.getIfSet   ( "optimize_state_sharing", _optimizeStateSharing );
     conf.getIfSet   ( "optimize", _optimize );
     conf.getIfSet   ( "validate", _validate );
+    conf.getIfSet   ( "max_polygon_tiling_angle", _maxPolyTilingAngle );
 
     conf.getIfSet( "shader_policy", "disable",  _shaderPolicy, SHADERPOLICY_DISABLE );
     conf.getIfSet( "shader_policy", "inherit",  _shaderPolicy, SHADERPOLICY_INHERIT );
@@ -131,10 +131,10 @@ GeometryCompilerOptions::getConfig() const
     conf.addIfSet   ( "geo_interpolation", "great_circle", _geoInterp, GEOINTERP_GREAT_CIRCLE );
     conf.addIfSet   ( "geo_interpolation", "rhumb_line",   _geoInterp, GEOINTERP_RHUMB_LINE );
     conf.addIfSet   ( "use_vbo", _useVertexBufferObjects);
-    conf.addIfSet   ( "use_texture_arrays", _useTextureArrays );
     conf.addIfSet   ( "optimize_state_sharing", _optimizeStateSharing );
     conf.addIfSet   ( "optimize", _optimize );
     conf.addIfSet   ( "validate", _validate );
+    conf.addIfSet   ( "max_polygon_tiling_angle", _maxPolyTilingAngle );
 
     conf.addIfSet( "shader_policy", "disable",  _shaderPolicy, SHADERPOLICY_DISABLE );
     conf.addIfSet( "shader_policy", "inherit",  _shaderPolicy, SHADERPOLICY_INHERIT );
@@ -173,6 +173,14 @@ GeometryCompiler::compile(Geometry*             geometry,
 
 osg::Node*
 GeometryCompiler::compile(Geometry*             geometry,
+                          const Style&          style)
+{
+    osg::ref_ptr<Feature> f = new Feature(geometry, 0L); // no SRS!
+    return compile(f.get(), style, FilterContext(0L) );
+}
+
+osg::Node*
+GeometryCompiler::compile(Geometry*             geometry,
                           const FilterContext&  context)
 {
     return compile( geometry, Style(), context );
@@ -377,7 +385,7 @@ GeometryCompiler::compile(FeatureList&          workingSet,
     // instance substitution (replaces marker)
     else if ( model )
     {
-        const InstanceSymbol* instance = model ? (const InstanceSymbol*)model : (const InstanceSymbol*)icon;
+        const InstanceSymbol* instance = (const InstanceSymbol*)model;
 
         // use a separate filter context since we'll be munging the data
         FilterContext localCX = sharedCX;
@@ -452,17 +460,12 @@ GeometryCompiler::compile(FeatureList&          workingSet,
         ExtrudeGeometryFilter extrude;
         extrude.setStyle( style );
 
-        // Activate texture arrays if the GPU supports them and if the user
-        // hasn't disabled them.        
-        extrude.useTextureArrays() =
-            Registry::capabilities().supportsTextureArrays() &&
-            _options.useTextureArrays() == true;
-
         // apply per-feature naming if requested.
         if ( _options.featureName().isSet() )
             extrude.setFeatureNameExpr( *_options.featureName() );
-        if ( _options.useVertexBufferObjects().isSet())
-            extrude.useVertexBufferObjects() = *_options.useVertexBufferObjects();
+
+        if ( _options.mergeGeometry().isSet() )
+            extrude.setMergeGeometry( *_options.mergeGeometry() );
 
         osg::Node* node = extrude.push( workingSet, sharedCX );
         if ( node )
@@ -489,6 +492,9 @@ GeometryCompiler::compile(FeatureList&          workingSet,
         filter.maxGranularity() = *_options.maxGranularity();
         filter.geoInterp()      = *_options.geoInterp();
 
+        if (_options.maxPolygonTilingAngle().isSet())
+            filter.maxPolygonTilingAngle() = *_options.maxPolygonTilingAngle();
+
         if ( _options.featureName().isSet() )
             filter.featureName() = *_options.featureName();
 
@@ -571,13 +577,18 @@ GeometryCompiler::compile(FeatureList&          workingSet,
             osgUtil::Optimizer::REMOVE_REDUNDANT_NODES |
             osgUtil::Optimizer::COMBINE_ADJACENT_LODS |
             osgUtil::Optimizer::SHARE_DUPLICATE_STATE |
-            osgUtil::Optimizer::MERGE_GEOMETRY |
+            //osgUtil::Optimizer::MERGE_GEOMETRY |
             osgUtil::Optimizer::CHECK_GEOMETRY |
             osgUtil::Optimizer::MERGE_GEODES |
             osgUtil::Optimizer::STATIC_OBJECT_DETECTION;
 
         osgUtil::Optimizer opt;
         opt.optimize(resultGroup.get(), optimizations);
+
+        osgUtil::Optimizer::MergeGeometryVisitor mg;
+        mg.setTargetMaximumNumberOfVertices(65536);
+        resultGroup->accept(mg);
+
         OE_DEBUG << LC << "optimize complete" << std::endl;
 
         if ( trackHistory ) history.push_back( "optimize" );
diff --git a/src/osgEarthFeatures/GeometryUtils b/src/osgEarthFeatures/GeometryUtils
index 8222da2..aca3951 100644
--- a/src/osgEarthFeatures/GeometryUtils
+++ b/src/osgEarthFeatures/GeometryUtils
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthFeatures/GeometryUtils.cpp b/src/osgEarthFeatures/GeometryUtils.cpp
index 94c1c36..61f51f6 100644
--- a/src/osgEarthFeatures/GeometryUtils.cpp
+++ b/src/osgEarthFeatures/GeometryUtils.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
@@ -157,7 +157,7 @@ osgEarth::Features::GeometryUtils::getGeometryArea( const Geometry* geometry )
     double result = 0.0;
     if (g)
     {
-        result = OGR_G_GetArea( g );
+        result = OGR_G_Area( g );
         OGR_G_DestroyGeometry( g );
     }
     return result;
diff --git a/src/osgEarthFeatures/LabelSource b/src/osgEarthFeatures/LabelSource
index 9345172..31710b2 100644
--- a/src/osgEarthFeatures/LabelSource
+++ b/src/osgEarthFeatures/LabelSource
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthFeatures/LabelSource.cpp b/src/osgEarthFeatures/LabelSource.cpp
index 0cebd38..690fb6f 100644
--- a/src/osgEarthFeatures/LabelSource.cpp
+++ b/src/osgEarthFeatures/LabelSource.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -100,5 +100,7 @@ LabelSourceFactory::create( const LabelSourceOptions& options )
 const LabelSourceOptions&
 LabelSourceDriver::getLabelSourceOptions( const osgDB::ReaderWriter::Options* options ) const
 {
-    return *static_cast<const LabelSourceOptions*>( options->getPluginData( LABEL_SOURCE_OPTIONS_TAG ) );
+    static LabelSourceOptions s_default;
+    const void* data = options->getPluginData(LABEL_SOURCE_OPTIONS_TAG);
+    return data ? *static_cast<const LabelSourceOptions*>(data) : s_default;
 }
diff --git a/src/osgEarthFeatures/MVT b/src/osgEarthFeatures/MVT
new file mode 100644
index 0000000..70eec40
--- /dev/null
+++ b/src/osgEarthFeatures/MVT
@@ -0,0 +1,40 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+ * Copyright 2008-2014 Pelican Mapping
+ * http://osgearth.org
+ *
+ * osgEarth is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ */
+#ifndef OSGEARTH_FEATURES_MVT
+#define OSGEARTH_FEATURES_MVT 1
+
+#include <osgEarthFeatures/Common>
+#include <osgEarthFeatures/FeatureSource>
+
+namespace osgEarth { namespace Features
+{
+    using namespace osgEarth;
+
+    /**
+     * Utility class for reading features from mapnik vector tiles.
+     */
+    class OSGEARTHFEATURES_EXPORT MVT
+    {
+    public:
+        static bool read(std::istream& in, const TileKey& key, FeatureList& features);
+    };
+} }
+
+#endif // OSGEARTH_FEATURES_MVT
+
diff --git a/src/osgEarthFeatures/MVT.cpp b/src/osgEarthFeatures/MVT.cpp
new file mode 100644
index 0000000..fea0267
--- /dev/null
+++ b/src/osgEarthFeatures/MVT.cpp
@@ -0,0 +1,242 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+* Copyright 2008-2014 Pelican Mapping
+* http://osgearth.org
+*
+* osgEarth is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public License
+* along with this program.  If not, see <http://www.gnu.org/licenses/>
+*/
+#include <osgEarthFeatures/MVT>
+
+#include <osgEarth/Registry>
+#include <osgEarth/FileUtils>
+#include <osgEarth/GeoData>
+#include <osgEarthFeatures/FeatureSource>
+#include <list>
+#include <stdio.h>
+#include <stdlib.h>
+
+#ifdef OSGEARTH_HAVE_MVT
+#include "vector_tile.pb.h"
+#endif
+
+using namespace osgEarth;
+using namespace osgEarth::Features;
+
+#define CMD_BITS 3
+#define CMD_MOVETO 1
+#define CMD_LINETO 2
+#define CMD_CLOSEPATH 7
+
+// https://github.com/mapbox/mapnik-vector-tile/blob/master/examples/c%2B%2B/tileinfo.cpp
+enum CommandType {
+    SEG_END    = 0,
+    SEG_MOVETO = 1,
+    SEG_LINETO = 2,
+    SEG_CLOSE = (0x40 | 0x0f)
+};
+
+enum eGeomType {
+    Unknown = 0,
+    Point = 1,
+    LineString = 2,
+    Polygon = 3
+};
+
+int zig_zag_decode(int n)
+{
+    return (n >> 1) ^ (-(n & 1));
+}
+
+
+bool
+    MVT::read(std::istream& in, const TileKey& key, FeatureList& features)
+{
+    features.clear();
+
+#ifdef OSGEARTH_HAVE_MVT
+
+    // Get the compressor
+    osg::ref_ptr< osgDB::BaseCompressor> compressor = osgDB::Registry::instance()->getObjectWrapperManager()->findCompressor("zlib");
+    if (!compressor.valid())
+    {
+        return false;
+    }
+
+    // Decompress the tile
+    std::string value;
+    if ( !compressor->decompress(in, value) )
+    {
+        OE_WARN << "Decompression failed" << std::endl;
+        return false;
+    }
+
+
+    mapnik::vector::tile tile;
+
+    if (tile.ParseFromString(value))
+    {
+        for (unsigned int i = 0; i < tile.layers().size(); i++)
+        {
+            const mapnik::vector::tile_layer &layer = tile.layers().Get(i);
+
+            for (unsigned int j = 0; j < layer.features().size(); j++)
+            {
+                const mapnik::vector::tile_feature &feature = layer.features().Get(j);
+
+                osg::ref_ptr< osgEarth::Symbology::Geometry > geometry; 
+
+                eGeomType geomType = static_cast<eGeomType>(feature.type());
+                if (geomType == ::Polygon)
+                {
+                    geometry = new osgEarth::Symbology::Polygon();
+                }
+                else if (geomType == ::LineString)
+                {
+                    geometry = new osgEarth::Symbology::LineString();
+                }
+                else if (geomType == ::Point)
+                {
+                    geometry = new osgEarth::Symbology::PointSet();
+                }
+                else
+                {
+                    geometry = new osgEarth::Symbology::LineString();
+                }
+
+                osg::ref_ptr< Feature > oeFeature = new Feature(geometry, key.getProfile()->getSRS());
+                features.push_back(oeFeature.get());                    
+
+                // Read attributes
+                for (unsigned int k = 0; k < feature.tags().size(); k+=2)
+                {
+                    std::string key = layer.keys().Get(feature.tags().Get(k));
+                    mapnik::vector::tile_value value = layer.values().Get(feature.tags().Get(k+1));
+
+                    if (value.has_bool_value())
+                    {
+                        oeFeature->set(key, value.bool_value());
+                    }
+                    else if (value.has_double_value())
+                    {
+                        oeFeature->set(key, value.double_value());
+                    }
+                    else if (value.has_float_value())
+                    {
+                        oeFeature->set(key, value.float_value());
+                    }
+                    else if (value.has_int_value())
+                    {
+                        oeFeature->set(key, (int)value.int_value());
+                    }
+                    else if (value.has_sint_value())
+                    {
+                        oeFeature->set(key, (int)value.sint_value());
+                    }
+                    else if (value.has_string_value())
+                    {
+                        oeFeature->set(key, value.string_value());
+                    }
+                    else if (value.has_uint_value())
+                    {
+                        oeFeature->set(key, (int)value.uint_value());
+                    }
+
+                    // Special path for getting heights from our test dataset.
+                    if (key == "other_tags")
+                    {
+                        std::string other_tags = value.string_value();
+
+                        StringTokenizer tok("=>");
+                        StringVector tized;
+                        tok.tokenize(other_tags, tized);            
+                        if (tized.size() == 3)
+                        {
+                            if (tized[0] == "height")
+                            {
+                                std::string value = tized[2];
+                                // Remove quotes from the height
+                                float height = as<float>(value, FLT_MAX);
+                                if (height != FLT_MAX)
+                                {
+                                    oeFeature->set("height", height);                                            
+                                }
+                            }
+                        }
+                    }
+                }
+
+
+                unsigned int length = 0;
+                int cmd = -1;
+                const int cmd_bits = 3;
+
+                unsigned int tileres = layer.extent();
+
+                int x = 0;
+                int y = 0;
+
+                for (int k = 0; k < feature.geometry_size();)
+                {
+                    if (!length)
+                    {
+                        unsigned int cmd_length = feature.geometry(k++);
+                        cmd = cmd_length & ((1 << cmd_bits) - 1);
+                        length = cmd_length >> cmd_bits;
+                    } 
+                    if (length > 0)
+                    {
+                        length--;
+                        if (cmd == SEG_MOVETO || cmd == SEG_LINETO)
+                        {
+                            int px = feature.geometry(k++);
+                            int py = feature.geometry(k++);
+                            px = zig_zag_decode(px);
+                            py = zig_zag_decode(py);
+
+                            x += px;
+                            y += py;
+
+                            double width = key.getExtent().width();
+                            double height = key.getExtent().height();
+
+                            double geoX = key.getExtent().xMin() + (width/(double)tileres) * (double)x;
+                            double geoY = key.getExtent().yMax() - (height/(double)tileres) * (double)y;
+                            geometry->push_back(geoX, geoY, 0);
+                        }
+                        else if (cmd == (SEG_CLOSE & ((1 << cmd_bits) - 1)))
+                        {
+                            geometry->push_back(geometry->front());
+                        }
+                    }
+                }
+
+                if (geometry->getType() == Geometry::TYPE_POLYGON)
+                {
+                    geometry->rewind(osgEarth::Symbology::Geometry::ORIENTATION_CCW);                                               
+                }
+            }
+        }
+    }
+    else
+    {
+        OE_WARN << "Failed to parse mvt" << key.str() << std::endl;
+        return false;
+    }
+
+    return true;
+#else
+    OE_NOTICE << "Mapnik Vector Tiles NOT SUPPORTED - please compile osgEarth with protobuf to enable." << std::endl;
+    return false;
+#endif
+}
diff --git a/src/osgEarthFeatures/MarkerFactory b/src/osgEarthFeatures/MarkerFactory
deleted file mode 100644
index 6495a0d..0000000
--- a/src/osgEarthFeatures/MarkerFactory
+++ /dev/null
@@ -1,71 +0,0 @@
-/* -*-c++-*- */
-/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2008-2010 Pelican Mapping
- * http://osgearth.org
- *
- * osgEarth is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>
- */
-
-#ifndef OSGEARTHFEATURES_MARKER_FACTORY_H
-#define OSGEARTHFEATURES_MARKER_FACTORY_H 1
-
-#if 0
-
-#include <osgEarthFeatures/Common>
-#include <osgEarthFeatures/Session>
-#include <osgEarthFeatures/Feature>
-#include <osgEarthSymbology/MarkerSymbol>
-#include <osg/Node>
-
-namespace osgEarth { namespace Features
-{
-    using namespace osgEarth;
-    using namespace osgEarth::Symbology;
-
-    /**
-     * Creates OSG nodes from Marker symbols.
-     */
-    class OSGEARTHFEATURES_EXPORT MarkerFactory
-    {
-    public:
-        /**
-         * Constructs a marker factory tied to the specified Session.
-         */
-        MarkerFactory(Session* session =0L);
-
-        osg::Node* getOrCreateNode( const Feature* feature, const MarkerSymbol* symbol, bool useCache =true );
-
-        /** Tries to create a new image from the marker's image() URI if it has one */
-        osg::Image* getOrCreateImage( const MarkerSymbol* symbol, bool useCache =true );
-
-        //URI getRawURI( const MarkerSymbol* symbol ) const;
-
-        /**
-         * Generates a marker node for a given URI.
-         */
-        //osg::Node* getOrCreateNode( const std::string& markerURI, bool useCache =true );
-
-    protected:
-        osg::Node* createFromURI( const URI& uri ) const;
-        osg::Image* createImageFromURI( const URI& uri ) const;
-
-    protected:
-        osg::ref_ptr<Session> _session;
-    };
-
-} } // namespace osgEarth::Features
-
-#endif
-
-#endif // OSGEARTHFEATURES_MARKER_FACTORY_H
diff --git a/src/osgEarthFeatures/MarkerFactory.cpp b/src/osgEarthFeatures/MarkerFactory.cpp
deleted file mode 100644
index ebad6b9..0000000
--- a/src/osgEarthFeatures/MarkerFactory.cpp
+++ /dev/null
@@ -1,208 +0,0 @@
-/* -*-c++-*- */
-/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2008-2010 Pelican Mapping
- * http://osgearth.org
- *
- * osgEarth is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>
- */
-#if 0
-#include <osgEarthFeatures/MarkerFactory>
-#include <osgEarth/Utils>
-#include <osg/TextureRectangle>
-#include <osg/Depth>
-#include <osg/AutoTransform>
-
-using namespace osgEarth;
-using namespace osgEarth::Features;
-using namespace osgEarth::Symbology;
-
-//----------------------------------------------------------------------------
-
-namespace
-{
-    osg::Node* buildImageModel(osg::Image* image)
-    {
-        float width = image->s();
-        float height = image->t();
-
-        osg::Geometry* geometry = new osg::Geometry;
-
-        osg::Vec3Array* verts = new osg::Vec3Array(4);
-        (*verts)[0] = osg::Vec3(-width/2.0f, -height/2.0, 0.0f);
-        (*verts)[1] = osg::Vec3(width/2.0f, -height/2.0, 0.0f);
-        (*verts)[2] = osg::Vec3(width/2.0f, height/2.0, 0.0f);
-        (*verts)[3] = osg::Vec3(-width/2.0f,height/2.0, 0.0f);
-        geometry->setVertexArray( verts );
-
-        bool flip = image->getOrigin()==osg::Image::TOP_LEFT;
-
-        osg::Vec2Array* texcoords = new osg::Vec2Array(4);
-        (*texcoords)[0].set(0.0f,flip ? height-1.0f : 0.0f);
-        (*texcoords)[1].set(width-1.0f,flip ? height-1.0f : 0.0f);
-        (*texcoords)[2].set(width-1.0f,flip ? 0.0 : height-1.0f);
-        (*texcoords)[3].set(0.0f,flip ? 0.0 : height-1.0f);
-        geometry->setTexCoordArray(0, texcoords);
-
-        osg::Vec4Array* colors = new osg::Vec4Array(1);
-        (*colors)[0].set(1,1,1,1);
-        geometry->setColorArray( colors );
-        geometry->setColorBinding( osg::Geometry::BIND_OVERALL );
-
-        geometry->addPrimitiveSet( new osg::DrawArrays(GL_QUADS, 0, 4));
-
-        osg::StateSet* stateSet = geometry->getOrCreateStateSet();
-
-        osg::TextureRectangle* texture = new osg::TextureRectangle( image );
-        stateSet->setTextureAttributeAndModes(0, texture, osg::StateAttribute::ON);
-
-        stateSet->setMode( GL_BLEND, 1 );
-        stateSet->setRenderBinDetails( 95, "RenderBin" );
-        stateSet->setAttributeAndModes( new osg::Depth(osg::Depth::ALWAYS,false), 1 );
-
-        osg::Geode* geode = new osg::Geode;
-        geode->addDrawable( geometry );
-
-        //PixelAutoTransform* at = new PixelAutoTransform;
-        //at->setMinPixelWidth( width );
-        osg::AutoTransform* at = new osg::AutoTransform;
-        at->setAutoScaleToScreen( true );
-        at->setAutoRotateMode( osg::AutoTransform::ROTATE_TO_SCREEN );
-        at->addChild( geode );
-        return at;
-    }
-}
-
-//----------------------------------------------------------------------------
-
-MarkerFactory::MarkerFactory( Session* session ) :
-_session( session )
-{
-    //nop
-}
-
-osg::Node*
-MarkerFactory::getOrCreateNode( const Feature* feature, const MarkerSymbol* symbol, bool useCache )
-{
-    osg::Node* result =0L;
-
-    if ( symbol )
-    {
-        if ( symbol->getNode() )
-        {
-            result = symbol->getNode();
-        }
-        else if ( symbol->getImage() )
-        {
-            const std::string& fileName = symbol->getImage()->getFileName();
-            if ( !fileName.empty() && _session.valid() && useCache )
-            {
-                result = _session->getResource<osg::Node>( fileName );
-            }
-
-            if ( !result )
-            {
-                result = buildImageModel( symbol->getImage() );
-            }
-
-            if ( result && _session.valid() && useCache && !fileName.empty() )
-            {
-                _session->putResource(fileName, result);
-            }
-        }
-        else if ( symbol->url().isSet() && !symbol->url()->empty() )
-        {            
-            StringExpression expr = symbol->url().get();
-            std::string val = feature->eval( expr  );//symbol->url()->full();
-            URI uri( val, expr.uriContext() );
-
-            OE_DEBUG << "Using model URL " << uri.full() << std::endl;
-            if ( _session.valid() && useCache )
-            {
-                result = _session->getResource<osg::Node>( uri.full() );
-            }
-
-            if ( !result )
-            {                
-                result = createFromURI( uri );
-            }
-
-            if ( result && _session.valid() && useCache )
-            {
-                _session->putResource( uri.full(), result );
-            }
-        }
-    }
-
-    return result;
-}
-
-osg::Image*
-MarkerFactory::getOrCreateImage( const MarkerSymbol* symbol, bool useCache )
-{
-    if ( symbol->getImage() )
-    {
-        return symbol->getImage();
-    }
-    else if ( symbol->url().isSet() && !symbol->url()->empty() )
-    {
-        return createImageFromURI( symbol->url()->expr() );
-    }
-    return 0L;
-}
-
-osg::Node*
-MarkerFactory::createFromURI( const URI& uri ) const
-{
-    osg::ref_ptr<osg::Object> obj = uri.readObject();
-    if ( obj.valid() )
-    {
-        if ( dynamic_cast<osg::Image*>( obj.get() ) )
-        {
-            return buildImageModel( dynamic_cast<osg::Image*>( obj.get() ) );
-        }
-        else if ( dynamic_cast<osg::Node*>( obj.get() ) )
-        {
-            return dynamic_cast<osg::Node*>( obj.release() );
-        }
-    }
-
-    else // failing that, fall back on the old encoding format..
-    {
-        StringVector tok;
-        StringTokenizer( *uri, tok, "()" );
-        if (tok.size() >= 2)
-            return createFromURI( URI(tok[1]) );
-    }
-
-    // fail
-    return 0L;
-}
-
-
-osg::Image*
-MarkerFactory::createImageFromURI( const URI& uri ) const
-{
-    StringVector tok;
-    StringTokenizer( *uri, tok, "()" );
-
-    if ( tok.size() > 0 )
-    {
-        URI imageURI( tok[tok.size()-1], uri.context() );
-        return imageURI.readImage();
-    }
-
-    return 0L;
-}
-
-#endif
\ No newline at end of file
diff --git a/src/osgEarthFeatures/MeshClamper b/src/osgEarthFeatures/MeshClamper
deleted file mode 100644
index 1c5fa6c..0000000
--- a/src/osgEarthFeatures/MeshClamper
+++ /dev/null
@@ -1,88 +0,0 @@
-/* -*-c++-*- */
-/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
- * http://osgearth.org
- *
- * osgEarth is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>
- */
-
-#ifndef OSGEARTHFEATURES_MESH_CLAMPER_H
-#define OSGEARTHFEATURES_MESH_CLAMPER_H 1
-
-#include <osgEarthFeatures/Common>
-#include <osgEarth/SpatialReference>
-#include <osg/NodeVisitor>
-#include <osg/fast_back_stack>
-
-namespace osgEarth { namespace Features
-{
-    using namespace osgEarth;
-
-    /**
-     * Utility that takes existing OSG geometry and modifies it so that
-     * it "conforms" with a terrain patch.
-     */
-    class OSGEARTHFEATURES_EXPORT MeshClamper : public osg::NodeVisitor
-    {
-    public:
-        /**
-         * Construct a new mesh clamper.
-         *
-         * @param terrainPatch
-         *      Node graph to which to clamp visited geometry.
-         * @param terrainSRS
-         *      Spatial reference of the map represented by the terrain patch.
-         * @param geocentric
-         *      Whether the terrain is geocentric (ECEF)
-         * @param preserveZ
-         *      Whether to preserve the original Z (the height above sea level) as an offset
-         * @param scale
-         *      (optional) Scale factor for the clamped height value
-         * @param offset
-         *      (optional) Static offset for the clamped height value
-         */
-        MeshClamper( 
-            osg::Node*              terrainPatch, 
-            const SpatialReference* terrainSRS, 
-            bool                    geocentric,
-            bool                    preserveZ     =false,
-            double                  scale         =1.0,
-            double                  offset        =0.0 );
-
-        virtual ~MeshClamper() { }
-
-        osg::Node* getTerrainPatch() const { return _terrainPatch.get(); }
-
-        const SpatialReference* getTerrainSRS() const { return _terrainSRS.get(); }
-
-        bool isGeocentric() const { return _geocentric; }
-
-    public: // osg::NodeVisitor
-
-        void apply( osg::Geode& );
-        void apply( osg::Transform& );
-
-    protected:
-        osg::ref_ptr<osg::Node>              _terrainPatch;
-        osg::ref_ptr<const SpatialReference> _terrainSRS;
-        bool                                 _geocentric;
-        bool                                 _preserveZ;
-        double                               _scale;
-        double                               _offset;
-        osg::fast_back_stack<osg::Matrixd>   _matrixStack;
-    };
-
-} } // namespace osgEarth::Features
-
-#endif // OSGEARTHFEATURES_MESH_CLAMPER_H
diff --git a/src/osgEarthFeatures/MeshClamper.cpp b/src/osgEarthFeatures/MeshClamper.cpp
deleted file mode 100644
index 67b7779..0000000
--- a/src/osgEarthFeatures/MeshClamper.cpp
+++ /dev/null
@@ -1,207 +0,0 @@
-/* -*-c++-*- */
-/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
- * http://osgearth.org
- *
- * osgEarth is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>
- */
-#include <osgEarthFeatures/MeshClamper>
-
-#include <osgEarth/DPLineSegmentIntersector>
-
-#include <osgUtil/IntersectionVisitor>
-#include <osgUtil/LineSegmentIntersector>
-
-#include <osg/TemplatePrimitiveFunctor>
-#include <osg/Geode>
-#include <osg/Geometry>
-#include <osg/UserDataContainer>
-
-#define LC "[MeshClamper] "
-
-using namespace osgEarth;
-using namespace osgEarth::Features;
-
-#define ZOFFSETS_NAME "MeshClamper::zOffsets"
-
-//-----------------------------------------------------------------------
-
-MeshClamper::MeshClamper(osg::Node*              terrainPatch,
-                         const SpatialReference* terrainSRS,
-                         bool                    geocentric,
-                         bool                    preserveZ,
-                         double                  scale,
-                         double                  offset) :
-
-osg::NodeVisitor( osg::NodeVisitor::TRAVERSE_ALL_CHILDREN ),
-_terrainPatch   ( terrainPatch ),
-_terrainSRS     ( terrainSRS ),
-_geocentric     ( geocentric ),
-_preserveZ      ( preserveZ ),
-_scale          ( scale ),
-_offset         ( offset )
-{
-    //nop
-}
-
-void
-MeshClamper::apply( osg::Transform& xform )
-{
-    osg::Matrixd matrix;
-    if ( !_matrixStack.empty() ) matrix = _matrixStack.back();
-    xform.computeLocalToWorldMatrix( matrix, this );
-    _matrixStack.push_back( matrix );
-    traverse(xform);
-    _matrixStack.pop_back();
-}
-
-void
-MeshClamper::apply( osg::Geode& geode )
-{
-    const osg::Matrixd& local2world = _matrixStack.back();
-    osg::Matrix world2local;
-    world2local.invert( local2world );
-
-    const osg::EllipsoidModel* em = _terrainSRS->getEllipsoid();
-    osg::Vec3d n_vector(0,0,1), start, end, msl;
-
-    // use a double-precision intersector b/c our intersection segment will be really long :)
-    DPLineSegmentIntersector* lsi = new DPLineSegmentIntersector(start, end);
-    osgUtil::IntersectionVisitor iv( lsi );
-
-    double r = std::min( em->getRadiusEquator(), em->getRadiusPolar() );
-    //double r = 50000;
-
-    unsigned count = 0;
-
-    for( unsigned i=0; i<geode.getNumDrawables(); ++i )
-    {
-        bool geomDirty = false;
-        osg::Geometry* geom = geode.getDrawable(i)->asGeometry();
-        if ( geom )
-        {
-            osg::Vec3Array*  verts = static_cast<osg::Vec3Array*>(geom->getVertexArray());
-            osg::FloatArray* zOffsets = 0L;
-
-            // if preserve-Z is on, check for our elevations array. Create it if is doesn't
-            // already exist.
-            bool buildZOffsets = false;
-            if ( _preserveZ )
-            {
-                osg::UserDataContainer* udc = geom->getOrCreateUserDataContainer();
-                unsigned n = udc->getUserObjectIndex( ZOFFSETS_NAME );
-                if ( n < udc->getNumUserObjects() )
-                {
-                    zOffsets = dynamic_cast<osg::FloatArray*>(udc->getUserObject(n));
-                }
-
-                else
-                {
-                    zOffsets = new osg::FloatArray();
-                    zOffsets->setName( ZOFFSETS_NAME );
-                    zOffsets->reserve( verts->size() );
-                    udc->addUserObject( zOffsets );
-                    buildZOffsets = true;
-                }
-            }
-
-            for( unsigned k=0; k<verts->size(); ++k )
-            {
-                osg::Vec3d vw = (*verts)[k];
-                vw = vw * local2world;
-
-                if ( _geocentric )
-                {
-                    // normal to the ellipsoid:
-                    n_vector = em->computeLocalUpVector(vw.x(),vw.y(),vw.z());
-
-                    // if we need to build to z-offsets array, calculate the z offset now:
-                    if ( buildZOffsets || _scale != 1.0 )
-                    {
-                        double lat,lon,hae;
-                        em->convertXYZToLatLongHeight(vw.x(), vw.y(), vw.z(), lat, lon, hae);
-
-                        if ( buildZOffsets )
-                        {
-                            zOffsets->push_back( float(hae) );
-                        }
-
-                        if ( _scale != 1.0 )
-                        {
-                            msl = vw - n_vector*hae;
-                        }
-                    }
-                }
-
-                else if ( buildZOffsets ) // flat map
-                {
-                    zOffsets->push_back( float(vw.z()) );
-                }
-
-#if 0
-                    // if we're scaling, we need to know the MSL coord
-                    if ( _scale != 1.0 )
-                    {
-                        double lat,lon,height;
-                        em->convertXYZToLatLongHeight(vw.x(), vw.y(), vw.z(), lat, lon, height);
-                        msl = vw - n_vector*height;
-                    }
-                }
-#endif
-
-                lsi->reset();
-                lsi->setStart( vw + n_vector*r*_scale );
-                lsi->setEnd( vw - n_vector*r );
-
-                _terrainPatch->accept( iv );
-
-                if ( lsi->containsIntersections() )
-                {
-                    osg::Vec3d fw = lsi->getFirstIntersection().getWorldIntersectPoint();
-                    if ( _scale != 1.0 )
-                    {
-                        osg::Vec3d delta = fw - msl;
-                        fw += delta*_scale;
-                    }
-                    if ( _offset != 0.0 )
-                    {
-                        fw += n_vector*_offset;
-                    }
-                    if ( _preserveZ )
-                    {
-                        fw += n_vector * (*zOffsets)[k];
-                    }
-
-                    (*verts)[k] = (fw * world2local);
-                    geomDirty = true;
-                    ++count;
-                }
-            }
-
-            if ( geomDirty )
-            {
-                geom->dirtyBound();
-                if ( geom->getUseVertexBufferObjects() )
-                {
-                    verts->getVertexBufferObject()->setUsage( GL_DYNAMIC_DRAW_ARB );
-                    verts->dirty();
-                }
-                else
-                    geom->dirtyDisplayList();
-            }
-        }
-
-        //OE_NOTICE << LC << "clamped " << count << " verts." << std::endl;
-    }
-}
diff --git a/src/osgEarthFeatures/OgrUtils b/src/osgEarthFeatures/OgrUtils
index aeb8015..2594a1e 100644
--- a/src/osgEarthFeatures/OgrUtils
+++ b/src/osgEarthFeatures/OgrUtils
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthFeatures/OgrUtils.cpp b/src/osgEarthFeatures/OgrUtils.cpp
index 54dbec8..b583fc5 100644
--- a/src/osgEarthFeatures/OgrUtils.cpp
+++ b/src/osgEarthFeatures/OgrUtils.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
@@ -204,11 +204,14 @@ OgrUtils::createOgrGeometry(const osgEarth::Symbology::Geometry* geometry, OGRwk
         case Geometry::TYPE_MULTI: 
             {
                 const osgEarth::Symbology::MultiGeometry* multi = dynamic_cast<const MultiGeometry*>(geometry);
-                osgEarth::Symbology::Geometry::Type componentType = multi->getComponentType();
-                requestedType = componentType == Geometry::TYPE_POLYGON ? wkbMultiPolygon : 
-                    componentType == Geometry::TYPE_POINTSET ? wkbMultiPoint :
-                    componentType == Geometry::TYPE_LINESTRING ? wkbMultiLineString :
-                    wkbNone;                    
+                if (multi)
+                {
+                    osgEarth::Symbology::Geometry::Type componentType = multi->getComponentType();
+                    requestedType = componentType == Geometry::TYPE_POLYGON ? wkbMultiPolygon : 
+                        componentType == Geometry::TYPE_POINTSET ? wkbMultiPoint :
+                        componentType == Geometry::TYPE_LINESTRING ? wkbMultiLineString :
+                        wkbNone;                    
+                }
             }
             break;
         }
diff --git a/src/osgEarthFeatures/OptimizerHints b/src/osgEarthFeatures/OptimizerHints
index 4367db3..cfb5602 100644
--- a/src/osgEarthFeatures/OptimizerHints
+++ b/src/osgEarthFeatures/OptimizerHints
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthFeatures/OptimizerHints.cpp b/src/osgEarthFeatures/OptimizerHints.cpp
index fc1aeb5..cedcfff 100644
--- a/src/osgEarthFeatures/OptimizerHints.cpp
+++ b/src/osgEarthFeatures/OptimizerHints.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthFeatures/PolygonizeLines b/src/osgEarthFeatures/PolygonizeLines
index 14c5168..15fcb54 100644
--- a/src/osgEarthFeatures/PolygonizeLines
+++ b/src/osgEarthFeatures/PolygonizeLines
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -67,7 +67,6 @@ namespace osgEarth { namespace Features
 
     protected:
         Stroke _stroke;
-        bool   _makeScalable;
         friend class PolygonizeLinesFilter;
     };
 
@@ -92,7 +91,6 @@ namespace osgEarth { namespace Features
     protected:
 
         Style _style;
-        bool  _makeScalable;
     };
 
 } } // namespace osgEarth::Features
diff --git a/src/osgEarthFeatures/PolygonizeLines.cpp b/src/osgEarthFeatures/PolygonizeLines.cpp
index eb54c85..ea897f8 100644
--- a/src/osgEarthFeatures/PolygonizeLines.cpp
+++ b/src/osgEarthFeatures/PolygonizeLines.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -480,7 +480,7 @@ namespace
             osgUtil::CullVisitor* cv = Culling::asCullVisitor(nv);
 
             // temporary patch to prevent uniform overwrite -gw
-            if ( nv->getFrameStamp() && nv->getFrameStamp()->getFrameNumber() > _frameNumber )
+            if ( nv->getFrameStamp() && (int)nv->getFrameStamp()->getFrameNumber() > _frameNumber )
             {
                 _pixelSizeVectorUniform->set( cv->getCurrentCullingSet().getPixelSizeVector() );    
                 _frameNumber = nv->getFrameStamp()->getFrameNumber();
@@ -581,10 +581,6 @@ PolygonizeLinesOperator::installShaders(osg::Node* node) const
 
     // this will install and update the oe_PixelSizeVector uniform.
     node->addCullCallback( new PixelSizeVectorCullCallback(stateset) );
-
-    // DYNAMIC since we will be altering the uniforms and we don't want 
-    // the stateset to get shared via statesetcache optimization.
-    stateset->setDataVariance(osg::Object::DYNAMIC);
 }
 
 
diff --git a/src/osgEarthFeatures/ResampleFilter b/src/osgEarthFeatures/ResampleFilter
index cd12c59..0d67c19 100644
--- a/src/osgEarthFeatures/ResampleFilter
+++ b/src/osgEarthFeatures/ResampleFilter
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -29,11 +29,61 @@ namespace osgEarth { namespace Features
 {
     using namespace osgEarth;
 
+    class ResampleFilterOptions : public ConfigOptions
+    {
+    public:
+        ResampleFilterOptions(const ConfigOptions& co =ConfigOptions()) : ConfigOptions(co) {
+            _minLen.init(0.0);
+            _maxLen.init(DBL_MAX);
+            _mode.init  (RESAMPLE_LINEAR);
+            fromConfig(_conf);
+        }
+
+        enum ResampleMode
+        {
+            RESAMPLE_LINEAR,
+            RESAMPLE_GREATCIRCLE,
+            RESAMPLE_RHUMB
+        };
+
+        optional<double>& minLength() { return _minLen; }
+        const optional<double>& minLength() const { return _minLen; }
+
+        optional<double>& maxLength() { return _maxLen; }
+        const optional<double>& maxLength() const { return _maxLen; }
+
+        optional<ResampleMode>& resampleMode() { return _mode;}
+        const optional<ResampleMode>& resampleMode() const { return _mode; }
+
+        void fromConfig(const Config& conf) {
+            conf.getIfSet("min_length", _minLen);
+            conf.getIfSet("max_length", _maxLen);
+            conf.getIfSet("mode", "linear",       _mode, RESAMPLE_LINEAR);
+            conf.getIfSet("mode", "great_circle", _mode, RESAMPLE_GREATCIRCLE);
+            conf.getIfSet("mode", "rhumb_line",   _mode, RESAMPLE_RHUMB);
+        }
+
+        Config getConfig() const {
+            Config conf = ConfigOptions::getConfig();
+            conf.addIfSet("min_length", _minLen);
+            conf.addIfSet("max_length", _maxLen);
+            conf.addIfSet("mode", "linear",       _mode, RESAMPLE_LINEAR);
+            conf.addIfSet("mode", "great_circle", _mode, RESAMPLE_GREATCIRCLE);
+            conf.addIfSet("mode", "rhumb_line",   _mode, RESAMPLE_RHUMB);
+            return conf;
+        }
+
+    protected:
+        optional<double> _minLen, _maxLen, _perturbThresh;
+        optional<ResampleMode> _mode;
+    };
+
     /**
      * This filter will resample line segments so they are between
      * the min and max specified length.
      */
-    class OSGEARTHFEATURES_EXPORT ResampleFilter : public FeatureFilter
+    class OSGEARTHFEATURES_EXPORT ResampleFilter : public FeatureFilter,
+                                                   public ResampleFilterOptions
     {
     public:
         // Call this determine whether this filter is available.
@@ -42,49 +92,14 @@ namespace osgEarth { namespace Features
     public:
         ResampleFilter();
         ResampleFilter( double minLength, double maxLength );
-
         ResampleFilter( const Config& conf );
 
-        /**
-         * Serialize this FeatureFilter
-         */
-        virtual Config getConfig() const;
-
-
-
         virtual ~ResampleFilter() { }
 
     public:
-
-        optional<double>& minLength() { return _minLen; }
-        const optional<double>& minLength() const { return _minLen; }
-
-        optional<double>& maxLength() { return _maxLen; }
-        const optional<double>& maxLength() const { return _maxLen; }
-
-        optional<double>& perturbationThreshold() { return _perturbThresh; }
-        const optional<double>& perturbationThreshold() const { return _perturbThresh; }
-
-
-
-        enum ResampleMode
-        {
-            RESAMPLE_LINEAR,
-            RESAMPLE_GREATCIRCLE,
-            RESAMPLE_RHUMB
-        };
-
-        optional<ResampleMode>& resampleMode() { return _resampleMode;}
-        const optional<ResampleMode>& resampleMode() const { return _resampleMode;}
-
-
-    public:
         virtual FilterContext push( FeatureList& input, FilterContext& context );
 
     protected:
-        optional<double> _minLen, _maxLen, _perturbThresh;
-        optional<ResampleMode> _resampleMode;
-
         bool push( Feature* input, FilterContext& context );
     };
 
diff --git a/src/osgEarthFeatures/ResampleFilter.cpp b/src/osgEarthFeatures/ResampleFilter.cpp
index 386625c..722789d 100644
--- a/src/osgEarthFeatures/ResampleFilter.cpp
+++ b/src/osgEarthFeatures/ResampleFilter.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -36,46 +36,25 @@ ResampleFilter::isSupported()
 }
 
 ResampleFilter::ResampleFilter() :
-_minLen( 0 ),
-_maxLen( DBL_MAX ),
-_perturbThresh( 0 ),
-_resampleMode(RESAMPLE_LINEAR)
+ResampleFilterOptions()
 {
     //NOP
 }
 
 ResampleFilter::ResampleFilter( double minLen, double maxLen ) :
-_minLen( minLen ),
-_maxLen( maxLen ),
-_perturbThresh( 0 ),
-_resampleMode(RESAMPLE_LINEAR)
+ResampleFilterOptions()
 {
-    // NOP
+    _minLen = minLen;
+    _maxLen = maxLen;
 }
 
-ResampleFilter::ResampleFilter( const Config& conf):
-_minLen( 0 ),
-_maxLen( DBL_MAX ),
-_perturbThresh( 0 ),
-_resampleMode(RESAMPLE_LINEAR)
+ResampleFilter::ResampleFilter( const Config& conf ):
+ResampleFilterOptions( conf )
 {
-    if (conf.key() == "resample")
-    {
-        conf.getIfSet( "min_length", _minLen );
-        conf.getIfSet( "max_length", _maxLen );
-    }
-}
-
-Config ResampleFilter::getConfig() const
-{
-    Config config( "resample" );
-    config.addIfSet( "min_length", _minLen);
-    config.addIfSet( "max_length", _maxLen);
-    return config;
+    //nop
 }
 
 
-
 bool
 ResampleFilter::push( Feature* input, FilterContext& context )
 {
@@ -116,11 +95,9 @@ ResampleFilter::push( Feature* input, FilterContext& context )
             bool lastSeg = v1 == last;
             osg::Vec3d seg = p1 - p0;
 
-            //OE_NOTICE << "p0=" << p0 << " to " << "p1=" << p1 << std::endl;
-
             osg::Vec3d p0Rad, p1Rad;
 
-            if (_resampleMode.value() == RESAMPLE_GREATCIRCLE || _resampleMode.value() == RESAMPLE_RHUMB)
+            if (resampleMode().value() == RESAMPLE_GREATCIRCLE || resampleMode().value() == RESAMPLE_RHUMB)
             {
                 p0Rad = osg::Vec3d(osg::DegreesToRadians(p0.x()), osg::DegreesToRadians(p0.y()), p0.z());
                 p1Rad = osg::Vec3d(osg::DegreesToRadians(p1.x()), osg::DegreesToRadians(p1.y()), p1.z());
@@ -128,7 +105,7 @@ ResampleFilter::push( Feature* input, FilterContext& context )
                        
             //Compute the length of the segment
             double segLen = 0.0;
-            switch (_resampleMode.value())
+            switch (resampleMode().value())
             {
             case RESAMPLE_LINEAR:
                 segLen = seg.length();
@@ -154,7 +131,7 @@ ResampleFilter::push( Feature* input, FilterContext& context )
                 seg.normalize();
                 osg::Vec3d newPt;
                 double newHeight;
-                switch (_resampleMode.value())
+                switch (resampleMode().value())
                 {
                 case RESAMPLE_LINEAR:
                     {
@@ -196,13 +173,6 @@ ResampleFilter::push( Feature* input, FilterContext& context )
         part->clear();
         part->reserve( plist.size() );
         part->insert( part->begin(), plist.begin(), plist.end() );
-
-        /*
-        if ( origSize != part->size() )
-        {
-            OE_NOTICE << "Resampled part from " << origSize << " to " << part->size() << " points" << std::endl;
-        }
-        */
     }
     return success;
 }
diff --git a/src/osgEarthFeatures/ScaleFilter b/src/osgEarthFeatures/ScaleFilter
index 9d7b7f8..9516538 100644
--- a/src/osgEarthFeatures/ScaleFilter
+++ b/src/osgEarthFeatures/ScaleFilter
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthFeatures/ScaleFilter.cpp b/src/osgEarthFeatures/ScaleFilter.cpp
index fe3611c..7b35859 100644
--- a/src/osgEarthFeatures/ScaleFilter.cpp
+++ b/src/osgEarthFeatures/ScaleFilter.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthFeatures/ScatterFilter b/src/osgEarthFeatures/ScatterFilter
index c81b4a6..1eec6a6 100644
--- a/src/osgEarthFeatures/ScatterFilter
+++ b/src/osgEarthFeatures/ScatterFilter
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -74,6 +74,7 @@ namespace osgEarth { namespace Features
             const FilterContext&    context, 
             PointSet*               output);
 
+
     private:
         float    _density;
         bool     _random;
diff --git a/src/osgEarthFeatures/ScatterFilter.cpp b/src/osgEarthFeatures/ScatterFilter.cpp
index a725945..d5a42ea 100644
--- a/src/osgEarthFeatures/ScatterFilter.cpp
+++ b/src/osgEarthFeatures/ScatterFilter.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -202,24 +202,24 @@ ScatterFilter::push(FeatureList& features, FilterContext& context )
 
         const SpatialReference* geomSRS = context.profile()->getSRS();
 
-        PointSet* points = new PointSet();
+        osg::ref_ptr< PointSet > points = new PointSet();
 
         if ( geom->getComponentType() == Geometry::TYPE_POLYGON )
         {
-            polyScatter( geom, geomSRS, context, points );
+            polyScatter( geom, geomSRS, context, points.get() );
         }
         else if (
             geom->getComponentType() == Geometry::TYPE_LINESTRING ||
             geom->getComponentType() == Geometry::TYPE_RING )            
         {
-            lineScatter( geom, geomSRS, context, points );
+            lineScatter( geom, geomSRS, context, points.get() );
         }
-        else {
-            OE_WARN << LC << "Sorry, don't know how to scatter a PointSet yet" << std::endl;
+        else {            
+            points = static_cast< PointSet*>(geom->cloneAs(Geometry::TYPE_POINTSET));
         }
 
         // replace the source geometry with the scattered points.
-        f->setGeometry( points );
+        f->setGeometry( points.get() );
     }
 
     return context;
diff --git a/src/osgEarthFeatures/Script b/src/osgEarthFeatures/Script
index 1531785..dab773c 100644
--- a/src/osgEarthFeatures/Script
+++ b/src/osgEarthFeatures/Script
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -120,9 +120,11 @@ namespace osgEarth { namespace Features
 
     const std::string& message() const { return _msg; }
 
-    std::string asString() { return _value; }
+    const std::string& asString() const { return _value; }
 
-    double asDouble(double defaultValue=0.0) { return _value.length() > 0 ? ::atof(_value.c_str()) : defaultValue; }
+    double asDouble(double defaultValue=0.0) const { return _value.length() > 0 ? ::atof(_value.c_str()) : defaultValue; }
+
+    bool asBool() const { return _value.compare("true")==0; }
 
   protected:
     std::string _value;
diff --git a/src/osgEarthFeatures/ScriptEngine b/src/osgEarthFeatures/ScriptEngine
index 1516269..9afa228 100644
--- a/src/osgEarthFeatures/ScriptEngine
+++ b/src/osgEarthFeatures/ScriptEngine
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -36,7 +36,10 @@ namespace osgEarth { namespace Features
   {
   public:
       ScriptEngineOptions( const ConfigOptions& options =ConfigOptions() ) : 
-        DriverConfigOptions( options ) { fromConfig(_conf); }
+        DriverConfigOptions( options )
+      {
+          fromConfig(_conf);
+      }
 
     virtual ~ScriptEngineOptions() { }
 
@@ -77,6 +80,10 @@ namespace osgEarth { namespace Features
         return script ? supported(script->getLanguage()) : false;
     }
 
+    /** Impl-specific profile to set. */
+    void setProfile(const std::string& profile) { _profile = profile; }
+    const std::string& getProfile() const { return _profile; }
+
     /** Runs a code snippet. */
     virtual ScriptResult run(const std::string& code, Feature const* feature=0L, FilterContext const* context=0L) =0;
 
@@ -103,6 +110,7 @@ namespace osgEarth { namespace Features
   protected:
     // common script to be included in each call to run()
     optional<Script> _script;
+    std::string _profile;
   };
 
   typedef std::list< osg::ref_ptr<ScriptEngine> > ScriptEngineList;
@@ -125,6 +133,7 @@ namespace osgEarth { namespace Features
 
     static ScriptEngine* create( const std::string& language, const std::string& engineName="", bool quiet =false);
     static ScriptEngine* create( const Script& script, const std::string& engineName="", bool quiet =false);
+    static ScriptEngine* createWithProfile( const Script& script, const std::string& profile, const std::string& engineName="", bool quiet =false);
     static ScriptEngine* create( const ScriptEngineOptions& options, bool quiet =false);
 
   protected:
diff --git a/src/osgEarthFeatures/ScriptEngine.cpp b/src/osgEarthFeatures/ScriptEngine.cpp
index 12442f2..da81895 100644
--- a/src/osgEarthFeatures/ScriptEngine.cpp
+++ b/src/osgEarthFeatures/ScriptEngine.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -107,6 +107,19 @@ ScriptEngineFactory::create( const Script& script, const std::string& engineName
 }
 
 ScriptEngine*
+ScriptEngineFactory::createWithProfile( const Script& script, const std::string& profile, const std::string& engineName, bool quiet)
+{
+  ScriptEngineOptions opts;
+  opts.setDriver(script.getLanguage() + (engineName.empty() ? "" : (std::string("_") + engineName)));
+  opts.script() = script;
+
+  ScriptEngine* e = create(opts, quiet);
+  if ( e )
+      e->setProfile( profile );
+  return e;
+}
+
+ScriptEngine*
 ScriptEngineFactory::create( const ScriptEngineOptions& options, bool quiet)
 {
     ScriptEngine* scriptEngine = 0L;
@@ -152,5 +165,7 @@ ScriptEngineFactory::create( const ScriptEngineOptions& options, bool quiet)
 const ScriptEngineOptions&
 ScriptEngineDriver::getScriptEngineOptions( const osgDB::ReaderWriter::Options* options ) const
 {
-    return *static_cast<const ScriptEngineOptions*>( options->getPluginData( SCRIPT_ENGINE_OPTIONS_TAG ) );
+    static ScriptEngineOptions s_default;
+    const void* data = options->getPluginData(SCRIPT_ENGINE_OPTIONS_TAG);
+    return data ? *static_cast<const ScriptEngineOptions*>(data) : s_default;
 }
diff --git a/src/osgEarthFeatures/ScriptFilter b/src/osgEarthFeatures/ScriptFilter
new file mode 100644
index 0000000..cad1976
--- /dev/null
+++ b/src/osgEarthFeatures/ScriptFilter
@@ -0,0 +1,105 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+ * Copyright 2016 Pelican Mapping
+ * http://osgearth.org
+ *
+ * osgEarth is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+#ifndef OSGEARTHFEATURES_SCRIPT_FILTER_H
+#define OSGEARTHFEATURES_SCRIPT_FILTER_H 1
+
+#include <osgEarthFeatures/Common>
+#include <osgEarthFeatures/Feature>
+#include <osgEarthFeatures/Filter>
+#include <osgEarthFeatures/ScriptEngine>
+
+namespace osgEarth { namespace Features
+{
+    using namespace osgEarth;
+
+    /**
+     * Options structure for serializing/configuring the ScriptFilter.
+     */
+    class ScriptFilterOptions : public ConfigOptions
+    {
+    public:
+        ScriptFilterOptions(const ConfigOptions& co =ConfigOptions()) : ConfigOptions(co) {
+            _language.init("javascript");
+            fromConfig(_conf);
+        }
+
+        /** Expression that will return true or false. */
+        optional<std::string>& expression() { return _expression; }
+        const optional<std::string>& expression() const { return _expression; }
+
+        /** Language in which the expression is written (default = javascript) */
+        optional<std::string>& language() { return _language; }
+        const optional<std::string>& language() const { return _language; }
+
+        /** Profile - set to "full" to enable property and geometry editing. */
+        optional<std::string>& profile() { return _profile; }
+        const optional<std::string>& profile() const { return _profile; }
+
+        void fromConfig(const Config& conf) {
+            _expression = conf.value();
+            conf.getIfSet("language", _language);
+            conf.getIfSet("profile", _profile);
+        }
+
+        Config getConfig() const {
+            Config conf = ConfigOptions::getConfig();
+            conf.value() = _expression.get();
+            conf.addIfSet("language", _language);
+            conf.addIfSet("profile", _profile);
+            return conf;
+        }
+
+    protected:
+        optional<std::string> _expression;
+        optional<std::string> _language;
+        optional<std::string> _profile;
+    };
+
+    /**
+     * This filter will modify the FeatureList using a script that return true or false.
+     * The script should contain a single expression returning the boolean.
+     */
+    class OSGEARTHFEATURES_EXPORT ScriptFilter : public FeatureFilter,
+                                                 public ScriptFilterOptions
+    {
+    public:
+        // Call this determine whether this filter is available.
+        static bool isSupported();    
+
+    public:
+        ScriptFilter();
+        ScriptFilter( const Config& conf );
+
+        virtual ~ScriptFilter() { }
+
+    public:
+        virtual FilterContext push( FeatureList& input, FilterContext& context );
+
+    protected:
+        bool push( Feature* input, FilterContext& context );
+
+    private:
+        void ctor();
+        osg::ref_ptr<ScriptEngine> _engine;
+    };
+
+} } // namespace osgEarth::Features
+
+#endif // OSGEARTHFEATURES_SCRIPT_FILTER_H
diff --git a/src/osgEarthFeatures/ScriptFilter.cpp b/src/osgEarthFeatures/ScriptFilter.cpp
new file mode 100644
index 0000000..f6bf233
--- /dev/null
+++ b/src/osgEarthFeatures/ScriptFilter.cpp
@@ -0,0 +1,104 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+ * Copyright 2016 Pelican Mapping
+ * http://osgearth.org
+ *
+ * osgEarth is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ */
+#include <osgEarthFeatures/ScriptFilter>
+
+using namespace osgEarth;
+using namespace osgEarth::Features;
+using namespace osgEarth::Symbology;
+
+OSGEARTH_REGISTER_SIMPLE_FEATUREFILTER(script, ScriptFilter);
+
+#define LC "[ScriptFilter] "
+
+bool
+ScriptFilter::isSupported()
+{
+    return true;
+}
+
+ScriptFilter::ScriptFilter() :
+ScriptFilterOptions()
+{
+    ctor();
+}
+
+ScriptFilter::ScriptFilter( const Config& conf ):
+ScriptFilterOptions( conf )
+{
+    ctor();
+}
+
+void
+ScriptFilter::ctor()
+{
+    _engine = ScriptEngineFactory::create(language().get());
+    if (_engine.valid())
+    {
+        if (profile().isSet())
+        {
+            _engine->setProfile(profile().get());
+        }
+    }
+}
+
+bool
+ScriptFilter::push(Feature* input, FilterContext& context)
+{
+    bool keep = true;
+
+    if (!input || !input->getGeometry() || !_engine.valid())
+        return false;
+
+    ScriptResult result = _engine->run(_expression.get(), input, &context);
+    keep = result.asBool();
+
+    return keep;
+}
+
+
+FilterContext
+ScriptFilter::push( FeatureList& input, FilterContext& context )
+{
+    if ( !isSupported() )
+    {
+        OE_WARN << "ScriptFilter support not enabled" << std::endl;
+        return context;
+    }
+
+    if (!_engine.valid())
+    {
+        OE_WARN << "No scripting engine\n";
+        return context;
+    }
+
+    bool ok = true;
+    for( FeatureList::iterator i = input.begin(); i != input.end(); )
+    {
+        if ( push( i->get(), context ) )
+        {
+            ++i;
+        }
+        else
+        {
+            i = input.erase(i);
+        }
+    }
+
+    return context;
+}
diff --git a/src/osgEarthFeatures/Session b/src/osgEarthFeatures/Session
index 71fb329..e008c5c 100644
--- a/src/osgEarthFeatures/Session
+++ b/src/osgEarthFeatures/Session
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthFeatures/Session.cpp b/src/osgEarthFeatures/Session.cpp
index 9d76aa0..913a893 100644
--- a/src/osgEarthFeatures/Session.cpp
+++ b/src/osgEarthFeatures/Session.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -50,7 +50,7 @@ _dbOptions     ( dbOptions )
 
     // if the caller did not provide a dbOptions, take it from the map.
     if ( map && !dbOptions )
-        _dbOptions = map->getDBOptions();
+        _dbOptions = map->getReadOptions();
 
     // A new cache to optimize state changes. Since the cache lives in the Session, any
     // geometry created under this session takes advantage of it. That's reasonable since
@@ -107,10 +107,12 @@ Session::setStyles( StyleSheet* value )
     {
         if (_styles->script())
         {
-            _styleScriptEngine = ScriptEngineFactory::create( Script(
-                _styles->script()->code, 
-                _styles->script()->language, 
-                _styles->script()->name ) );
+            _styleScriptEngine = ScriptEngineFactory::createWithProfile(
+                Script(
+                    _styles->script()->code, 
+                    _styles->script()->language, 
+                    _styles->script()->name ),
+                _styles->script()->profile );
         }
         else
         {
diff --git a/src/osgEarthFeatures/SubstituteModelFilter b/src/osgEarthFeatures/SubstituteModelFilter
index 1746148..5c213ea 100644
--- a/src/osgEarthFeatures/SubstituteModelFilter
+++ b/src/osgEarthFeatures/SubstituteModelFilter
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthFeatures/SubstituteModelFilter.cpp b/src/osgEarthFeatures/SubstituteModelFilter.cpp
index f7661ef..ac9e47a 100644
--- a/src/osgEarthFeatures/SubstituteModelFilter.cpp
+++ b/src/osgEarthFeatures/SubstituteModelFilter.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -25,9 +25,8 @@
 #include <osgEarth/ECEF>
 #include <osgEarth/VirtualProgram>
 #include <osgEarth/DrawInstanced>
-#include <osgEarth/Registry>
 #include <osgEarth/Capabilities>
-#include <osgEarth/Decluttering>
+#include <osgEarth/ScreenSpaceLayout>
 #include <osgEarth/CullingUtils>
 
 #include <osg/AutoTransform>
@@ -39,18 +38,6 @@
 #include <osg/AlphaFunc>
 #include <osg/Billboard>
 
-#include <osgSim/LightPointNode>
-
-#include <osgDB/FileNameUtils>
-#include <osgDB/Registry>
-#include <osgDB/WriteFile>
-
-#include <osgUtil/Optimizer>
-#include <osgUtil/MeshOptimizers>
-
-#include <list>
-#include <deque>
-
 #define LC "[SubstituteModelFilter] "
 
 using namespace osgEarth;
@@ -149,15 +136,24 @@ SubstituteModelFilter::process(const FeatureList&           features,
     // keep track of failed URIs so we don't waste time or warning messages on them
     std::set< URI > missing;
 
-    StringExpression  uriEx   = *symbol->url();
-    NumericExpression scaleEx = *symbol->scale();
+    StringExpression  uriEx    = *symbol->url();
+    NumericExpression scaleEx  = *symbol->scale();
 
     const ModelSymbol* modelSymbol = dynamic_cast<const ModelSymbol*>(symbol);
     const IconSymbol*  iconSymbol  = dynamic_cast<const IconSymbol*> (symbol);
 
-    NumericExpression headingEx;
+    NumericExpression headingEx;    
+    NumericExpression scaleXEx;
+    NumericExpression scaleYEx;
+    NumericExpression scaleZEx;
+
     if ( modelSymbol )
+    {
         headingEx = *modelSymbol->heading();
+        scaleXEx  = *modelSymbol->scaleX();
+        scaleYEx  = *modelSymbol->scaleY();
+        scaleZEx  = *modelSymbol->scaleZ();
+    }
 
     for( FeatureList::const_iterator f = features.begin(); f != features.end(); ++f )
     {
@@ -185,16 +181,34 @@ SubstituteModelFilter::process(const FeatureList&           features,
 
         // evalute the scale expression (if there is one)
         float scale = 1.0f;
+        osg::Vec3d scaleVec(1.0, 1.0, 1.0);
         osg::Matrixd scaleMatrix;
         if ( symbol->scale().isSet() )
         {
             scale = input->eval( scaleEx, &context );
-            if ( scale == 0.0 )
-                scale = 1.0;
-            if ( scale != 1.0 )
-                _normalScalingRequired = true;
-            scaleMatrix = osg::Matrix::scale( scale, scale, scale );
+            scaleVec.set(scale, scale, scale);
         }
+        if ( modelSymbol )
+        {
+            if ( modelSymbol->scaleX().isSet() )
+            {
+                scaleVec.x() *= input->eval( scaleXEx, &context );
+            }
+            if ( modelSymbol->scaleY().isSet() )
+            {
+                scaleVec.y() *= input->eval( scaleYEx, &context );
+            }
+            if ( modelSymbol->scaleZ().isSet() )
+            {
+                scaleVec.z() *= input->eval( scaleZEx, &context );
+            }
+        }
+
+        if ( scaleVec.x() == 0.0 ) scaleVec.x() = 1.0;
+        if ( scaleVec.y() == 0.0 ) scaleVec.y() = 1.0;
+        if ( scaleVec.z() == 0.0 ) scaleVec.z() = 1.0;
+
+        scaleMatrix = osg::Matrix::scale( scaleVec );
         
         osg::Matrixd rotationMatrix;
         if ( modelSymbol && modelSymbol->heading().isSet() )
@@ -204,7 +218,7 @@ SubstituteModelFilter::process(const FeatureList&           features,
         }
 
 		// how that we have a marker source, create a node for it
-		std::pair<URI,float> key( instanceURI, iconSymbol? scale : 1.0f );//use 1.0 for models, since we don't want unique models based on scaling
+		std::pair<URI,float> key( instanceURI, iconSymbol? scale : 1.0f ); //use 1.0 for models, since we don't want unique models based on scaling
 
         // cache nodes per instance.
         osg::ref_ptr<osg::Node>& model = uniqueModels[key];
@@ -212,14 +226,14 @@ SubstituteModelFilter::process(const FeatureList&           features,
         {
             // Always clone the cached instance so we're not processing data that's
             // already in the scene graph. -gw
-            context.resourceCache()->cloneOrCreateInstanceNode(instance.get(), model);
+            context.resourceCache()->cloneOrCreateInstanceNode(instance.get(), model, context.getDBOptions());
 
             // if icon decluttering is off, install an AutoTransform.
             if ( iconSymbol )
             {
                 if ( iconSymbol->declutter() == true )
                 {
-                    Decluttering::setEnabled( model->getOrCreateStateSet(), true );
+                    ScreenSpaceLayout::activate(model->getOrCreateStateSet());
                 }
                 else if ( dynamic_cast<osg::AutoTransform*>(model.get()) == 0L )
                 {
@@ -250,16 +264,36 @@ SubstituteModelFilter::process(const FeatureList&           features,
                     osg::Matrixd mat;
 
                     // need to recalcluate expression-based data per-point, not just per-feature!
+                    float scale = 1.0f;
+                    osg::Vec3d scaleVec(1.0, 1.0, 1.0);
+                    osg::Matrixd scaleMatrix;
                     if ( symbol->scale().isSet() )
                     {
-                        scale = input->eval(scaleEx, &context);
-                        if ( scale == 0.0 )
-                            scale = 1.0;
-                        if ( scale != 1.0 )
-                            _normalScalingRequired = true;
-                        scaleMatrix = osg::Matrix::scale( scale, scale, scale );
+                        scale = input->eval( scaleEx, &context );
+                        scaleVec.set(scale, scale, scale);
+                    }
+                    if ( modelSymbol )
+                    {
+                        if ( modelSymbol->scaleX().isSet() )
+                        {
+                            scaleVec.x() *= input->eval( scaleXEx, &context );
+                        }
+                        if ( modelSymbol->scaleY().isSet() )
+                        {
+                            scaleVec.y() *= input->eval( scaleYEx, &context );
+                        }
+                        if ( modelSymbol->scaleZ().isSet() )
+                        {
+                            scaleVec.z() *= input->eval( scaleZEx, &context );
+                        }
                     }
 
+                    if ( scaleVec.x() == 0.0 ) scaleVec.x() = 1.0;
+                    if ( scaleVec.y() == 0.0 ) scaleVec.y() = 1.0;
+                    if ( scaleVec.z() == 0.0 ) scaleVec.z() = 1.0;
+
+                    scaleMatrix = osg::Matrix::scale( scaleVec );
+
                     if ( modelSymbol->heading().isSet() )
                     {
                         float heading = input->eval(headingEx, &context);
@@ -274,7 +308,7 @@ SubstituteModelFilter::process(const FeatureList&           features,
                         // but if the tile is big enough the up vectors won't be quite right.
                         osg::Matrixd rotation;
                         ECEF::transformAndGetRotationMatrix( point, context.profile()->getSRS(), point, targetSRS, rotation );
-                        mat = rotationMatrix * rotation * scaleMatrix * osg::Matrixd::translate( point ) * _world2local;
+                        mat = rotationMatrix * scaleMatrix * rotation * osg::Matrixd::translate( point ) * _world2local;
                     }
                     else
                     {
@@ -310,7 +344,7 @@ SubstituteModelFilter::process(const FeatureList&           features,
         // activate decluttering for icons if requested
         if ( iconSymbol->declutter() == true )
         {
-            Decluttering::setEnabled( attachPoint->getOrCreateStateSet(), true );
+            ScreenSpaceLayout::activate(attachPoint->getOrCreateStateSet());
         }
 
         // activate horizon culling if we are in geocentric space
@@ -322,7 +356,7 @@ SubstituteModelFilter::process(const FeatureList&           features,
     }
 
     // active DrawInstanced if required:
-    if ( _useDrawInstanced && Registry::capabilities().supportsDrawInstanced() )
+    if ( _useDrawInstanced )
     {
         DrawInstanced::convertGraphToUseDrawInstanced( attachPoint );
 
@@ -417,7 +451,7 @@ SubstituteModelFilter::push(FeatureList& features, FilterContext& context)
 
     const StyleSheet* sheet = context.getSession() ? context.getSession()->styles() : 0L;
 
-    if ( symbol->library().isSet() )
+    if ( sheet && symbol->library().isSet() )
     {
         _resourceLib = sheet->getResourceLibrary( symbol->library()->expr() );
 
diff --git a/src/osgEarthFeatures/TessellateOperator b/src/osgEarthFeatures/TessellateOperator
index 2e5ac33..695fb7b 100644
--- a/src/osgEarthFeatures/TessellateOperator
+++ b/src/osgEarthFeatures/TessellateOperator
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthFeatures/TessellateOperator.cpp b/src/osgEarthFeatures/TessellateOperator.cpp
index 99bcaf8..c51ed39 100644
--- a/src/osgEarthFeatures/TessellateOperator.cpp
+++ b/src/osgEarthFeatures/TessellateOperator.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthFeatures/TextSymbolizer b/src/osgEarthFeatures/TextSymbolizer
index 66bb49f..69b445e 100644
--- a/src/osgEarthFeatures/TextSymbolizer
+++ b/src/osgEarthFeatures/TextSymbolizer
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthFeatures/TextSymbolizer.cpp b/src/osgEarthFeatures/TextSymbolizer.cpp
index afa36b0..ce7b392 100644
--- a/src/osgEarthFeatures/TextSymbolizer.cpp
+++ b/src/osgEarthFeatures/TextSymbolizer.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthFeatures/TransformFilter b/src/osgEarthFeatures/TransformFilter
index c7eaedd..c85a34f 100644
--- a/src/osgEarthFeatures/TransformFilter
+++ b/src/osgEarthFeatures/TransformFilter
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthFeatures/TransformFilter.cpp b/src/osgEarthFeatures/TransformFilter.cpp
index f24ff78..9c26a38 100644
--- a/src/osgEarthFeatures/TransformFilter.cpp
+++ b/src/osgEarthFeatures/TransformFilter.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthFeatures/VirtualFeatureSource b/src/osgEarthFeatures/VirtualFeatureSource
index f1712e2..96b1852 100644
--- a/src/osgEarthFeatures/VirtualFeatureSource
+++ b/src/osgEarthFeatures/VirtualFeatureSource
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -27,7 +27,6 @@
 namespace osgEarth { namespace Features
 {
     using namespace osgEarth;
-    using namespace osgEarth::Features;
     using namespace osgEarth::Symbology;
 
     /**
@@ -67,13 +66,17 @@ namespace osgEarth { namespace Features
 
     public: // FeatureSource
         virtual FeatureCursor* createFeatureCursor( const Query& query );
-        virtual void initialize( const osgDB::Options* options );
-        virtual const FeatureProfile* createFeatureProfile();
         virtual const FeatureSchema& getSchema() const;
         virtual Feature* getFeature( FeatureID id ) { return 0L; }
 
     protected:
+        virtual Status initialize(const osgDB::Options* readOptions);
+
+    protected:
         FeatureSourceMappingVector _sources;
+
+    private:
+        const FeatureProfile* createFeatureProfile();
     };
 
 } } // namespace osgEarth::Features
diff --git a/src/osgEarthFeatures/VirtualFeatureSource.cpp b/src/osgEarthFeatures/VirtualFeatureSource.cpp
index cfc3de1..fd71596 100644
--- a/src/osgEarthFeatures/VirtualFeatureSource.cpp
+++ b/src/osgEarthFeatures/VirtualFeatureSource.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -110,6 +110,9 @@ VirtualFeatureSource::add( FeatureSource* source, FeaturePredicate* predicate )
 {
     _sources.push_back( FeatureSourceMapping(source, predicate) );
     dirty();
+
+    if (_sources.size() == 1)
+        setFeatureProfile(createFeatureProfile());
 }
 
 FeatureCursor* 
@@ -118,13 +121,20 @@ VirtualFeatureSource::createFeatureCursor( const Query& query )
     return new VirtualFeatureCursor( _sources, query );
 }
 
-void 
-VirtualFeatureSource::initialize( const osgDB::Options* dbOptions )
+Status 
+VirtualFeatureSource::initialize( const osgDB::Options* readOptions )
 {
+    //FeatureSource::initialize( dbOptions );
+
     for( FeatureSourceMappingVector::iterator i = _sources.begin(); i != _sources.end(); ++i )
     {
-        i->_source->initialize( dbOptions );
+        const Status& sourceStatus = i->_source->open(readOptions);
+        if (sourceStatus.isError())
+            return sourceStatus;
+        //i->_source->initialize( dbOptions );
     }
+
+    return Status::OK();
 }
 
 const FeatureProfile* 
diff --git a/src/osgEarthFeatures/vector_tile.proto b/src/osgEarthFeatures/vector_tile.proto
new file mode 100644
index 0000000..e25ac3b
--- /dev/null
+++ b/src/osgEarthFeatures/vector_tile.proto
@@ -0,0 +1,92 @@
+// Protocol Version 1
+
+package mapnik.vector;
+
+option optimize_for = LITE_RUNTIME;
+
+message tile {
+        enum GeomType {
+             Unknown = 0;
+             Point = 1;
+             LineString = 2;
+             Polygon = 3;
+        }
+
+        // Variant type encoding
+        message value {
+                // Exactly one of these values may be present in a valid message
+                optional string string_value = 1;
+                optional float float_value = 2;
+                optional double double_value = 3;
+                optional int64 int_value = 4;
+                optional uint64 uint_value = 5;
+                optional sint64 sint_value = 6;
+                optional bool bool_value = 7;
+
+                extensions 8 to max;
+        }
+
+        message feature {
+                optional uint64 id = 1;
+
+                // Tags of this feature. Even numbered values refer to the nth
+                // value in the keys list on the tile message, odd numbered
+                // values refer to the nth value in the values list on the tile
+                // message.
+                repeated uint32 tags = 2 [ packed = true ];
+
+                // The type of geometry stored in this feature.
+                optional GeomType type = 3 [ default = Unknown ];
+
+                // Contains a stream of commands and parameters (vertices). The
+                // repeat count is shifted to the left by 3 bits. This means
+                // that the command has 3 bits (0-7). The repeat count
+                // indicates how often this command is to be repeated. Defined
+                // commands are:
+                // - MoveTo:    1   (2 parameters follow)
+                // - LineTo:    2   (2 parameters follow)
+                // - ClosePath: 7   (no parameters follow)
+                //
+                // Ex.: MoveTo(3, 6), LineTo(8, 12), LineTo(20, 34), ClosePath
+                // Encoded as: [ 9 3 6 18 5 6 12 22 7 ]
+                //                                  == command type 7 (ClosePath)
+                //                             ===== relative LineTo(+12, +22) == LineTo(20, 34)
+                //                         === relative LineTo(+5, +6) == LineTo(8, 12)
+                //                      == [00010 010] = command type 2 (LineTo), length 2
+                //                  === relative MoveTo(+3, +6)
+                //              == [00001 001] = command type 1 (MoveTo), length 1
+                // Commands are encoded as uint32 varints, vertex parameters are
+                // encoded as sint32 varints (zigzag). Vertex parameters are
+                // also encoded as deltas to the previous position. The original
+                // position is (0,0)
+                repeated uint32 geometry = 4 [ packed = true ];
+        }
+
+        message layer {
+                // Any compliant implementation must first read the version
+                // number encoded in this message and choose the correct
+                // implementation for this version number before proceeding to
+                // decode other parts of this message.
+                required uint32 version = 15 [ default = 1 ];
+
+                required string name = 1;
+
+                // The actual features in this tile.
+                repeated feature features = 2;
+
+                // Dictionary encoding for keys
+                repeated string keys = 3;
+
+                // Dictionary encoding for values
+                repeated value values = 4;
+
+                // The bounding box in this tile spans from 0..4095 units
+                optional uint32 extent = 5 [ default = 4096 ];
+
+                extensions 16 to max;
+        }
+
+        repeated layer layers = 3;
+
+        extensions 16 to 8191;
+}
diff --git a/src/osgEarthProcedural/CMakeLists.txt b/src/osgEarthProcedural/CMakeLists.txt
new file mode 100644
index 0000000..52a72d5
--- /dev/null
+++ b/src/osgEarthProcedural/CMakeLists.txt
@@ -0,0 +1,67 @@
+IF   (DYNAMIC_OSGEARTH)
+    ADD_DEFINITIONS(-DOSGEARTHPROCEDURAL_LIBRARY)
+ELSE (DYNAMIC_OSGEARTH)
+    ADD_DEFINITIONS(-DOSGEARTHPROCEDURAL_LIBRARY_STATIC)
+ENDIF(DYNAMIC_OSGEARTH)
+
+SET(LIB_NAME osgEarthProcedural)
+
+
+set(TARGET_GLSL )
+
+set(SHADERS_CPP "${CMAKE_CURRENT_BINARY_DIR}/AutoGenShaders.cpp")
+
+configure_shaders(
+    Shaders.cpp.in
+    ${SHADERS_CPP}
+    ${TARGET_GLSL} )
+
+SET(HEADER_PATH ${OSGEARTH_SOURCE_DIR}/include/${LIB_NAME})
+SET(LIB_PUBLIC_HEADERS
+#   header files go here
+    Common
+	Export
+	CoverageLegend
+	Shaders
+	SimplexNoise
+	SplatCatalog
+)
+
+ADD_LIBRARY(${LIB_NAME} ${OSGEARTH_USER_DEFINED_DYNAMIC_OR_STATIC}
+    ${LIB_PUBLIC_HEADERS}
+#  .cpp files go here
+	CoverageLegend.cpp
+	SplatCatalog.cpp
+	SimplexNoise.cpp
+	${SHADERS_CPP}
+)
+
+INCLUDE_DIRECTORIES(
+	${OSG_INCLUDE_DIR} 
+	${OSGEARTH_SOURCE_DIR} )
+
+LINK_EXTERNAL(
+	${LIB_NAME}
+	${TARGET_EXTERNAL_LIBRARIES}
+	${CMAKE_THREAD_LIBS_INIT}
+	${MATH_LIBRARY} )
+
+LINK_INTERNAL(
+	${LIB_NAME}
+    osgEarth
+)
+
+LINK_WITH_VARIABLES(
+	${LIB_NAME} 
+	OSG_LIBRARY
+	OSGDB_LIBRARY
+	OSGTEXT_LIBRARY
+	OSGUTIL_LIBRARY
+	OPENTHREADS_LIBRARY )
+
+LINK_CORELIB_DEFAULT(
+	${LIB_NAME}
+	${CMAKE_THREAD_LIBS_INIT}
+	${MATH_LIBRARY} )
+
+INCLUDE(ModuleInstall OPTIONAL)
diff --git a/src/osgEarthProcedural/Common b/src/osgEarthProcedural/Common
new file mode 100644
index 0000000..18bce16
--- /dev/null
+++ b/src/osgEarthProcedural/Common
@@ -0,0 +1,32 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+ * Copyright 2008-2014 Pelican Mapping
+ * http://osgearth.org
+ *
+ * osgEarth is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+#ifndef OSGEARTH_PROCEDURAL_COMMON_H
+#define OSGEARTH_PROCEDURAL_COMMON_H 1
+
+#include <osgEarth/Common>
+#include <osgEarthProcedural/Export>
+
+// common utilities
+namespace osgEarth { namespace Procedural
+{
+    
+} } // namespace osgEarth::Procedural
+
+#endif // OSGEARTH_PROCEDURAL_COMMON_H
diff --git a/src/osgEarthProcedural/CoverageLegend b/src/osgEarthProcedural/CoverageLegend
new file mode 100644
index 0000000..76e3a85
--- /dev/null
+++ b/src/osgEarthProcedural/CoverageLegend
@@ -0,0 +1,99 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+ * Copyright 2008-2014 Pelican Mapping
+ * http://osgearth.org
+ *
+ * osgEarth is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ */
+#ifndef OSGEARTH_PROCEDURAL_COVERAGE_LEGEND
+#define OSGEARTH_PROCEDURAL_COVERAGE_LEGEND 1
+
+#include "Common"
+#include <osgEarth/Config>
+#include <osg/Referenced>
+#include <string>
+
+namespace osgEarth { namespace Procedural
+{
+    /**
+     * Associates a specific source data coverage value to the name
+     * of a splat class.
+     */
+    template<typename T>
+    class CoverageValuePredicateT : public osg::Referenced
+    {
+    public:
+        optional<T> _exactValue;
+        optional<T> _minValue;
+        optional<T> _maxValue;
+
+        optional<std::string> _description;
+        optional<std::string> _mappedClassName;
+
+        bool match(const T& testValue) const
+        {
+            if ( _exactValue.isSetTo(testValue) )
+                return true;
+            if ( !_minValue.isSet() && !_maxValue.isSet() )
+                return false;
+            if ( _minValue.isSet() && _minValue.get() > testValue )
+                return false;
+            if ( _maxValue.isSet() && _maxValue.get() < testValue )
+                return false;
+
+            return true;
+        }
+    };
+
+    typedef CoverageValuePredicateT<std::string> CoverageValuePredicate;
+    
+    /**
+     * Legend that maps coverage values (or value predicates) to splat
+     * catalog classes.
+     */
+    class CoverageLegend : public osg::Referenced
+    {
+    public:
+        CoverageLegend();
+
+    public:
+        typedef std::vector< osg::ref_ptr<CoverageValuePredicate> > Predicates;
+
+        /**
+         * The collection of value->class mapping predicates
+         */
+        const Predicates& getPredicates() const { return _predicates; }
+
+    public: // serialization
+
+        // populate this object from a Config
+        void fromConfig(const Config& conf);
+
+        // serialize this object to a Config.
+        Config getConfig() const;
+
+
+    protected:
+
+        virtual ~CoverageLegend() { }
+
+        optional<std::string> _name;
+        optional<std::string> _source;
+
+        Predicates _predicates;
+    };
+
+} } // namespace osgEarth::Procedural
+
+#endif // OSGEARTH_PROCEDURAL_COVERAGE_LEGEND
diff --git a/src/osgEarthProcedural/CoverageLegend.cpp b/src/osgEarthProcedural/CoverageLegend.cpp
new file mode 100644
index 0000000..5d193b0
--- /dev/null
+++ b/src/osgEarthProcedural/CoverageLegend.cpp
@@ -0,0 +1,77 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+ * Copyright 2008-2014 Pelican Mapping
+ * http://osgearth.org
+ *
+ * osgEarth is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ */
+#include "CoverageLegend"
+#include <osgEarth/Config>
+
+using namespace osgEarth;
+using namespace osgEarth::Procedural;
+
+#define LC "[CoverageLegend] "
+
+//............................................................................
+
+CoverageLegend::CoverageLegend()
+{
+    //nop
+}
+
+void
+CoverageLegend::fromConfig(const Config& conf)
+{
+    conf.getIfSet("name",   _name);
+    conf.getIfSet("source", _source);
+
+    ConfigSet predicatesConf = conf.child("mappings").children();
+    for(ConfigSet::const_iterator i = predicatesConf.begin(); i != predicatesConf.end(); ++i)
+    {
+        osg::ref_ptr<CoverageValuePredicate> p = new CoverageValuePredicate();
+
+        i->getIfSet( "name",  p->_description );
+        i->getIfSet( "value", p->_exactValue );
+        i->getIfSet( "class", p->_mappedClassName );
+        
+        if ( p->_mappedClassName.isSet() )
+        {
+            _predicates.push_back( p.get() );
+        }
+    }
+}
+
+Config
+CoverageLegend::getConfig() const
+{
+    Config conf;
+    
+    conf.addIfSet("name",   _name);
+    conf.addIfSet("source", _source);
+
+    Config preds;
+    for(Predicates::const_iterator i = _predicates.begin(); i != _predicates.end(); ++i)
+    {
+        CoverageValuePredicate* p = i->get();
+        Config pred;
+        pred.addIfSet( "name",  p->_description );
+        pred.addIfSet( "value", p->_exactValue );
+        pred.addIfSet( "class", p->_mappedClassName );
+        preds.add(pred);
+    }
+    conf.add( "mappings", preds );
+
+    return conf;
+}
diff --git a/src/osgEarthProcedural/Export b/src/osgEarthProcedural/Export
new file mode 100644
index 0000000..83b2d60
--- /dev/null
+++ b/src/osgEarthProcedural/Export
@@ -0,0 +1,74 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+ * Copyright 2008-2014 Pelican Mapping
+ * http://osgearth.org
+ *
+ * osgEarth is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/* -*-c++-*- 
+ * Derived from osg/Export
+ */
+
+#ifndef OSGEARTH_PROCEDURAL_EXPORT_H
+#define OSGEARTH_PROCEDURAL_EXPORT_H 1
+
+// define USE_DEPRECATED_API is used to include in API which is being fazed out
+// if you can compile your apps with this turned off you are
+// well placed for compatibility with future versions.
+#define USE_DEPRECATED_API
+
+#if defined(_MSC_VER)
+    #pragma warning( disable : 4244 )
+    #pragma warning( disable : 4251 )
+    #pragma warning( disable : 4267 )
+    #pragma warning( disable : 4275 )
+    #pragma warning( disable : 4290 )
+    #pragma warning( disable : 4786 )
+    #pragma warning( disable : 4305 )
+    #pragma warning( disable : 4996 )
+#endif
+
+#if defined(_MSC_VER) || defined(__CYGWIN__) || defined(__MINGW32__) || defined( __BCPLUSPLUS__)  || defined( __MWERKS__)
+    #  if defined( OSGEARTHPROCEDURAL_LIBRARY_STATIC )
+    #    define OSGEARTHPROCEDURAL_EXPORT
+    #  elif defined( OSGEARTHPROCEDURAL_LIBRARY )
+    #    define OSGEARTHPROCEDURAL_EXPORT   __declspec(dllexport)
+    #  else
+    #    define OSGEARTHPROCEDURAL_EXPORT   __declspec(dllimport)
+    #  endif
+#else
+    #  define OSGEARTHPROCEDURAL_EXPORT
+#endif  
+
+// set up define for whether member templates are supported by VisualStudio compilers.
+#ifdef _MSC_VER
+# if (_MSC_VER >= 1300)
+#  define __STL_MEMBER_TEMPLATES
+# endif
+#endif
+
+/* Define NULL pointer value */
+
+#ifndef NULL
+    #ifdef  __cplusplus
+        #define NULL    0
+    #else
+        #define NULL    ((void *)0)
+    #endif
+#endif
+
+
+#endif // OSGEARTH_PROCEDURAL_EXPORT_H
+
diff --git a/src/osgEarthProcedural/Shaders b/src/osgEarthProcedural/Shaders
new file mode 100644
index 0000000..90be788
--- /dev/null
+++ b/src/osgEarthProcedural/Shaders
@@ -0,0 +1,31 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+* Copyright 2008-2012 Pelican Mapping
+* http://osgearth.org
+*
+* osgEarth is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public License
+* along with this program.  If not, see <http://www.gnu.org/licenses/>
+*/
+#ifndef OSGEARTH_PROCEDURAL_SHADERS
+#define OSGEARTH_PROCEDURAL_SHADERS 1
+
+#include <osgEarthProcedural/Common>
+
+namespace osgEarth { namespace Procedural
+{
+    struct OSGEARTHPROCEDURAL_EXPORT Shaders
+	{
+	};
+} } // namespace osgEarth::Procedural
+
+#endif // OSGEARTH_PROCEDURAL_SHADERS
diff --git a/src/osgEarthProcedural/Shaders.cpp.in b/src/osgEarthProcedural/Shaders.cpp.in
new file mode 100644
index 0000000..25543db
--- /dev/null
+++ b/src/osgEarthProcedural/Shaders.cpp.in
@@ -0,0 +1,9 @@
+// ***DO NOT EDIT THIS FILE - IT IS AUTOMATICALLY GENERATED BY CMAKE***
+
+#include <osgEarthProcedural/Shaders>
+
+#define MULTILINE(...) #__VA_ARGS__
+
+using namespace osgEarth::Procedural;
+
+
diff --git a/src/osgEarthProcedural/SimplexNoise b/src/osgEarthProcedural/SimplexNoise
new file mode 100644
index 0000000..07b16ab
--- /dev/null
+++ b/src/osgEarthProcedural/SimplexNoise
@@ -0,0 +1,159 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+* Copyright 2008-2014 Pelican Mapping
+* http://osgearth.org
+*
+* osgEarth is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public License
+* along with this program.  If not, see <http://www.gnu.org/licenses/>
+*/
+#ifndef OSGEARTH_PROCEDURAL_SIMPLEX_NOISE_H
+#define OSGEARTH_PROCEDURAL_SIMPLEX_NOISE_H 1
+
+#include <osgEarthProcedural/Common>
+
+namespace osgEarth { namespace Procedural
+{
+    /**
+     * Simplex Noise Generator.
+     * Adapted from https://github.com/Taywee/Noise
+     */
+    class OSGEARTHPROCEDURAL_EXPORT SimplexNoise
+    {
+    public:
+        SimplexNoise();
+        virtual ~SimplexNoise() { }
+
+        static const double DefaultFrequency;
+        static const double DefaultPersistence;
+        static const double DefaultLacunarity;
+        static const double DefaultRangeLow;
+        static const double DefaultRangeHigh;
+        static const unsigned DefaultOctaves;
+
+        /**
+         * Frequency is how often the noise pattern resets to zero across
+         * the input domain. For example, if your input range from 
+         * -100 < x < 100, a frequency of 1/200 will cause the noise function to
+         * reset every 200 units, i.e., the extent of the input domain. (It will
+         * be zero at -100 and zero again at 100. It may cross zero in between,
+         * but that is not guaranteed.)
+         *
+         * In mapping terms, say your map is 100000m wide. A frequency of 1/100000
+         * will result in a pattern that resets (and wraps around) every 100000m.
+         *
+         * Default = 1.0.
+         */ 
+        void setFrequency(double freq) { _freq = freq; }
+        double getFrequency() const { return _freq; }
+
+        /**
+         * Persietence is the factor by which the noise function's amplitude
+         * decreases with each successive octave.
+         *   i.e.: Amp(Oct2) = Amp(Oct1) * Persistance.
+         * Default = 0.5.
+         * Effect: Higher persistence: noisiness persists as you get more detail;
+         *         Lower persistence: data smooths out faster as you get more detail.
+         */
+        void setPersistence(double pers) { _pers = pers; }
+        double getPersistence() const { return _pers; }
+
+        /**
+         * Lacunarity is the factor by which the noise function's frequency
+         * increases with each successive octave.
+         *   i.e.: Freq(Oct2) = Freq(Oct1) * Lacunarity.
+         * Default = 2.0.
+         * Effect: Higher lacunarity: more "plateaus" in the output;
+         *         Lower lacunarity:  more "chopiness" in the output.
+         */
+        void setLacunarity(double lac) { _lacunarity = lac; }
+        double getLacunarity() const { return _lacunarity; }
+
+        /**
+         * The output range for noise data.
+         * Default = [-1..1].
+         */
+        void setRange(double low, double high) { _low = low, _high = high; }
+        double getRangeLow() const { return _low; }
+        double getRangeHigh() const { return _high; }
+
+        /**
+         * Number of iterations over which to generate noise. The frequency starts
+         * where you set it, and over each successive iteration, it is scaled by
+         * the persistence. This lets you control the rate at which the "noisiness"
+         * decreases with each octave.
+         * Default = 1.
+         */
+        void setOctaves(unsigned octaves) { _octaves = octaves; }
+        unsigned getOctaves() const { return _octaves; }
+
+        /**
+         * Generates 2D simplex Noise
+         */
+        double getValue(double xin, double yin) const;
+
+        /**
+         * Generates 3D simplex Noise
+         */
+        double getValue(double xin, double yin, double zin) const;
+
+        /**
+         * Generates 4D simplex Noise
+         */
+        double getValue(double x, double y, double z, double w) const;
+
+    private:
+        // Inner class to speed up gradient computations
+        // (array access is a lot slower than member access)
+        struct Grad
+        {
+            Grad(double x, double y, double z);
+            Grad(double x, double y, double z, double w);
+            double x, y, z, w;
+        };
+
+        const static Grad grad3[12];
+        const static Grad grad4[32];
+        const static unsigned char perm[512];
+
+        // Skewing and unskewing factors for 2, 3, and 4 dimensions
+        static double const F2;
+        static double const G2;
+        static double const F3;
+        static double const G3;
+        static double const F4;
+        static double const G4;
+
+        unsigned char permMod12[512];
+        bool permMod12Computed;
+        void ComputePermMod12();
+
+        // This method is a *lot* faster than using (int)Math.floor(x)
+        inline static int FastFloor(double x);
+        static double Dot(Grad const & g, double x, double y);
+        static double Dot(Grad const & g, double x, double y, double z);
+        static double Dot(Grad const & g, double x, double y, double z, double w);
+
+        double Noise(double x, double y) const;
+        double Noise(double x, double y, double z) const;
+        double Noise(double x, double y, double z, double w) const;
+
+        double _freq;
+        double _pers;
+        double _lacunarity;
+        double _low, _high;
+        unsigned _octaves;
+    };
+
+} } // namespace osgEarth::Procedural
+
+#endif //OSGEARTH_PROCEDURAL_SIMPLEX_NOISE_H
diff --git a/src/osgEarthProcedural/SimplexNoise.cpp b/src/osgEarthProcedural/SimplexNoise.cpp
new file mode 100644
index 0000000..1865838
--- /dev/null
+++ b/src/osgEarthProcedural/SimplexNoise.cpp
@@ -0,0 +1,556 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+ * Copyright 2008-2014 Pelican Mapping
+ * http://osgearth.org
+ *
+ * osgEarth is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+#include <osgEarthProcedural/SimplexNoise>
+#include <algorithm>
+
+#define POW2(x) ((double)(x==0 ? 1 : (2 << (x-1))))
+
+using namespace osgEarth::Procedural;
+
+const SimplexNoise::Grad SimplexNoise::grad3[12] = {
+    Grad(1, 1, 0), Grad(-1, 1, 0), Grad(1, -1, 0), Grad(-1, -1, 0),
+    Grad(1, 0, 1), Grad(-1, 0, 1), Grad(1, 0, -1), Grad(-1, 0, -1),
+    Grad(0, 1, 1), Grad(0, -1, 1), Grad(0, 1, -1), Grad(0, -1, -1)
+};
+
+const SimplexNoise::Grad SimplexNoise::grad4[32] =  {
+    Grad(0, 1, 1, 1), Grad(0, 1, 1, -1), Grad(0, 1, -1, 1), Grad(0, 1, -1, -1),
+    Grad(0, -1, 1, 1), Grad(0, -1, 1, -1), Grad(0, -1, -1, 1), Grad(0, -1, -1, -1),
+    Grad(1, 0, 1, 1), Grad(1, 0, 1, -1), Grad(1, 0, -1, 1), Grad(1, 0, -1, -1),
+    Grad(-1, 0, 1, 1), Grad(-1, 0, 1, -1), Grad(-1, 0, -1, 1), Grad(-1, 0, -1, -1),
+    Grad(1, 1, 0, 1), Grad(1, 1, 0, -1), Grad(1, -1, 0, 1), Grad(1, -1, 0, -1),
+    Grad(-1, 1, 0, 1), Grad(-1, 1, 0, -1), Grad(-1, -1, 0, 1), Grad(-1, -1, 0, -1),
+    Grad(1, 1, 1, 0), Grad(1, 1, -1, 0), Grad(1, -1, 1, 0), Grad(1, -1, -1, 0),
+    Grad(-1, 1, 1, 0), Grad(-1, 1, -1, 0), Grad(-1, -1, 1, 0), Grad(-1, -1, -1, 0)
+};
+
+const unsigned char SimplexNoise::perm[512] = {
+    151, 160, 137, 91, 90, 15,
+    131, 13, 201, 95, 96, 53, 194, 233, 7, 225, 140, 36, 103, 30, 69, 142, 8, 99, 37, 240, 21, 10, 23,
+    190, 6, 148, 247, 120, 234, 75, 0, 26, 197, 62, 94, 252, 219, 203, 117, 35, 11, 32, 57, 177, 33,
+    88, 237, 149, 56, 87, 174, 20, 125, 136, 171, 168, 68, 175, 74, 165, 71, 134, 139, 48, 27, 166,
+    77, 146, 158, 231, 83, 111, 229, 122, 60, 211, 133, 230, 220, 105, 92, 41, 55, 46, 245, 40, 244,
+    102, 143, 54, 65, 25, 63, 161, 1, 216, 80, 73, 209, 76, 132, 187, 208, 89, 18, 169, 200, 196,
+    135, 130, 116, 188, 159, 86, 164, 100, 109, 198, 173, 186, 3, 64, 52, 217, 226, 250, 124, 123,
+    5, 202, 38, 147, 118, 126, 255, 82, 85, 212, 207, 206, 59, 227, 47, 16, 58, 17, 182, 189, 28, 42,
+    223, 183, 170, 213, 119, 248, 152, 2, 44, 154, 163, 70, 221, 153, 101, 155, 167, 43, 172, 9,
+    129, 22, 39, 253, 19, 98, 108, 110, 79, 113, 224, 232, 178, 185, 112, 104, 218, 246, 97, 228,
+    251, 34, 242, 193, 238, 210, 144, 12, 191, 179, 162, 241, 81, 51, 145, 235, 249, 14, 239, 107,
+    49, 192, 214, 31, 181, 199, 106, 157, 184, 84, 204, 176, 115, 121, 50, 45, 127, 4, 150, 254,
+    138, 236, 205, 93, 222, 114, 67, 29, 24, 72, 243, 141, 128, 195, 78, 66, 215, 61, 156, 180,
+
+    151, 160, 137, 91, 90, 15,
+    131, 13, 201, 95, 96, 53, 194, 233, 7, 225, 140, 36, 103, 30, 69, 142, 8, 99, 37, 240, 21, 10, 23,
+    190, 6, 148, 247, 120, 234, 75, 0, 26, 197, 62, 94, 252, 219, 203, 117, 35, 11, 32, 57, 177, 33,
+    88, 237, 149, 56, 87, 174, 20, 125, 136, 171, 168, 68, 175, 74, 165, 71, 134, 139, 48, 27, 166,
+    77, 146, 158, 231, 83, 111, 229, 122, 60, 211, 133, 230, 220, 105, 92, 41, 55, 46, 245, 40, 244,
+    102, 143, 54, 65, 25, 63, 161, 1, 216, 80, 73, 209, 76, 132, 187, 208, 89, 18, 169, 200, 196,
+    135, 130, 116, 188, 159, 86, 164, 100, 109, 198, 173, 186, 3, 64, 52, 217, 226, 250, 124, 123,
+    5, 202, 38, 147, 118, 126, 255, 82, 85, 212, 207, 206, 59, 227, 47, 16, 58, 17, 182, 189, 28, 42,
+    223, 183, 170, 213, 119, 248, 152, 2, 44, 154, 163, 70, 221, 153, 101, 155, 167, 43, 172, 9,
+    129, 22, 39, 253, 19, 98, 108, 110, 79, 113, 224, 232, 178, 185, 112, 104, 218, 246, 97, 228,
+    251, 34, 242, 193, 238, 210, 144, 12, 191, 179, 162, 241, 81, 51, 145, 235, 249, 14, 239, 107,
+    49, 192, 214, 31, 181, 199, 106, 157, 184, 84, 204, 176, 115, 121, 50, 45, 127, 4, 150, 254,
+    138, 236, 205, 93, 222, 114, 67, 29, 24, 72, 243, 141, 128, 195, 78, 66, 215, 61, 156, 180
+};
+
+// Skewing and unskewing factors for 2, 3, and 4 dimensions
+double const SimplexNoise::F2 = 0.5*(sqrt(3.0)-1.0);
+double const SimplexNoise::G2 = (3.0-sqrt(3.0))/6.0;
+double const SimplexNoise::F3 = 1.0/3.0;
+double const SimplexNoise::G3 = 1.0/6.0;
+double const SimplexNoise::F4 = (sqrt(5.0)-1.0)/4.0;
+double const SimplexNoise::G4 = (5.0-sqrt(5.0))/20.0;
+
+SimplexNoise::Grad::Grad(double x, double y, double z)
+{
+    this->x = x;
+    this->y = y;
+    this->z = z;
+}
+
+SimplexNoise::Grad::Grad(double x, double y, double z, double w)
+{
+    this->x = x;
+    this->y = y;
+    this->z = z;
+    this->w = w;
+}
+
+// This method is a *lot* faster than using (int)Math.floor(x)
+int SimplexNoise::FastFloor(double x)
+{
+    int xi = (int)x;
+    return x<xi ? xi-1 : xi;
+}
+
+double SimplexNoise::Dot(Grad const & g, double x, double y)
+{
+    return g.x*x + g.y*y;
+}
+
+double SimplexNoise::Dot(Grad const & g, double x, double y, double z)
+{
+    return g.x*x + g.y*y + g.z*z;
+}
+
+double SimplexNoise::Dot(Grad const & g, double x, double y, double z, double w)
+{
+    return g.x*x + g.y*y + g.z*z + g.w*w;
+}
+
+
+const double   SimplexNoise::DefaultFrequency    =  1.0;
+const double   SimplexNoise::DefaultPersistence  =  0.5;
+const double   SimplexNoise::DefaultLacunarity   =  2.0;
+const double   SimplexNoise::DefaultRangeLow     = -1.0;
+const double   SimplexNoise::DefaultRangeHigh    =  1.0;
+const unsigned SimplexNoise::DefaultOctaves      =  10;
+
+
+SimplexNoise::SimplexNoise() :
+_octaves   ( DefaultOctaves ),
+_freq      ( DefaultFrequency ),
+_pers      ( DefaultPersistence ),
+_lacunarity( DefaultLacunarity ),
+_low       ( DefaultRangeLow ),
+_high      ( DefaultRangeHigh )
+{
+    for(unsigned int i=0; i<512; i++)
+    {
+        permMod12[i] = (unsigned char)(perm[i] % 12);
+    }
+}
+
+double SimplexNoise::getValue(double xin, double yin) const
+{
+    double freq = _freq;
+    double o = std::max(1u, _octaves);
+    double amp = 1.0;
+    double maxamp = 0.0;
+    double n = 0.0;
+
+    for(unsigned i=0; i<o; ++i)
+    {
+        n += Noise(xin*freq, yin*freq) * amp;
+        maxamp += amp;
+        amp *= _pers;
+        freq *= _lacunarity;
+    }
+    n /= maxamp;
+    n = n * (_high-_low)/2.0 + (_high+_low)/2.0;
+    return n;
+}
+
+double SimplexNoise::getValue(double xin, double yin, double zin) const
+{
+    double freq = _freq;
+    double o = std::max(1u, _octaves);
+    double amp = 1.0;
+    double maxamp = 0.0;
+    double n = 0.0;
+
+    for(unsigned i=0; i<o; ++i)
+    {
+        n += Noise(xin*freq, yin*freq, zin*freq) * amp;
+        maxamp += amp;
+        amp *= _pers;
+        freq *= _lacunarity;
+    }
+    n /= maxamp;
+    n = n * (_high-_low)/2.0 + (_high+_low)/2.0;
+    return n;
+}
+
+double SimplexNoise::getValue(double xin, double yin, double zin, double win) const
+{
+    double freq = _freq;
+    double o = std::max(1u, _octaves);
+    double amp = 1.0;
+    double maxamp = 0.0;
+    double n = 0.0;
+
+    for(unsigned i=0; i<o; ++i)
+    {
+        n += Noise(xin*freq, yin*freq, zin*freq, win*freq) * amp;
+        maxamp += amp;
+        amp *= _pers;
+        freq *= _lacunarity;
+    }
+    n /= maxamp;
+    n = n * (_high-_low)/2.0 + (_high+_low)/2.0;
+    return n;
+}
+
+
+// 2D simplex noise
+double SimplexNoise::Noise(double xin, double yin) const
+{
+    double n0, n1, n2; // Noise contributions from the three corners
+    // Skew the input space to determine which simplex cell we're in
+    double s = (xin+yin)*F2; // Hairy factor for 2D
+    int i = FastFloor(xin+s);
+    int j = FastFloor(yin+s);
+    double t = (i+j)*G2;
+    double X0 = i-t; // Unskew the cell origin back to (x,y) space
+    double Y0 = j-t;
+    double x0 = xin-X0; // The x,y distances from the cell origin
+    double y0 = yin-Y0;
+    // For the 2D case, the simplex shape is an equilateral triangle.
+    // Determine which simplex we are in.
+    int i1, j1; // Offsets for second (middle) corner of simplex in (i,j) coords
+    if(x0>y0)
+    {
+        i1=1;    // lower triangle, XY order: (0,0)->(1,0)->(1,1)
+        j1=0;
+    } else
+    {
+        i1=0;    // upper triangle, YX order: (0,0)->(0,1)->(1,1)
+        j1=1;
+    }
+    // A step of (1,0) in (i,j) means a step of (1-c,-c) in (x,y), and
+    // a step of (0,1) in (i,j) means a step of (-c,1-c) in (x,y), where
+    // c = (3-sqrt(3))/6
+    double x1 = x0 - i1 + G2; // Offsets for middle corner in (x,y) unskewed coords
+    double y1 = y0 - j1 + G2;
+    double x2 = x0 - 1.0 + 2.0 * G2; // Offsets for last corner in (x,y) unskewed coords
+    double y2 = y0 - 1.0 + 2.0 * G2;
+    // Work out the hashed gradient indices of the three simplex corners
+    int ii = i & 255;
+    int jj = j & 255;
+    int gi0 = permMod12[ii+perm[jj]];
+    int gi1 = permMod12[ii+i1+perm[jj+j1]];
+    int gi2 = permMod12[ii+1+perm[jj+1]];
+    // Calculate the contribution from the three corners
+    double t0 = 0.5 - x0*x0-y0*y0;
+    if(t0<0) n0 = 0.0;
+    else
+    {
+        t0 *= t0;
+        n0 = t0 * t0 * Dot(grad3[gi0], x0, y0);    // (x,y) of grad3 used for 2D gradient
+    }
+    double t1 = 0.5 - x1*x1-y1*y1;
+    if(t1<0) n1 = 0.0;
+    else
+    {
+        t1 *= t1;
+        n1 = t1 * t1 * Dot(grad3[gi1], x1, y1);
+    }
+    double t2 = 0.5 - x2*x2-y2*y2;
+    if(t2<0) n2 = 0.0;
+    else
+    {
+        t2 *= t2;
+        n2 = t2 * t2 * Dot(grad3[gi2], x2, y2);
+    }
+    // Add contributions from each corner to get the final noise value.
+    // The result is scaled to return values in the interval [-1,1].
+    return 70.0 * (n0 + n1 + n2);
+}
+
+
+// 3D simplex noise
+double SimplexNoise::Noise(double xin, double yin, double zin) const
+{
+    double n0, n1, n2, n3; // Noise contributions from the four corners
+    // Skew the input space to determine which simplex cell we're in
+    double s = (xin+yin+zin)*F3; // Very nice and simple skew factor for 3D
+    int i = FastFloor(xin+s);
+    int j = FastFloor(yin+s);
+    int k = FastFloor(zin+s);
+    double t = (i+j+k)*G3;
+    double X0 = i-t; // Unskew the cell origin back to (x,y,z) space
+    double Y0 = j-t;
+    double Z0 = k-t;
+    double x0 = xin-X0; // The x,y,z distances from the cell origin
+    double y0 = yin-Y0;
+    double z0 = zin-Z0;
+    // For the 3D case, the simplex shape is a slightly irregular tetrahedron.
+    // Determine which simplex we are in.
+    int i1, j1, k1; // Offsets for second corner of simplex in (i,j,k) coords
+    int i2, j2, k2; // Offsets for third corner of simplex in (i,j,k) coords
+    if(x0>=y0)
+    {
+        if(y0>=z0)
+        {
+            i1=1;    // X Y Z order
+            j1=0;
+            k1=0;
+            i2=1;
+            j2=1;
+            k2=0;
+        } else if(x0>=z0)
+        {
+            i1=1;    // X Z Y order
+            j1=0;
+            k1=0;
+            i2=1;
+            j2=0;
+            k2=1;
+        } else
+        {
+            i1=0;    // Z X Y order
+            j1=0;
+            k1=1;
+            i2=1;
+            j2=0;
+            k2=1;
+        }
+    } else     // x0<y0
+    {
+        if(y0<z0)
+        {
+            i1=0;    // Z Y X order
+            j1=0;
+            k1=1;
+            i2=0;
+            j2=1;
+            k2=1;
+        } else if(x0<z0)
+        {
+            i1=0;    // Y Z X order
+            j1=1;
+            k1=0;
+            i2=0;
+            j2=1;
+            k2=1;
+        } else
+        {
+            i1=0;    // Y X Z order
+            j1=1;
+            k1=0;
+            i2=1;
+            j2=1;
+            k2=0;
+        }
+    }
+    // A step of (1,0,0) in (i,j,k) means a step of (1-c,-c,-c) in (x,y,z),
+    // a step of (0,1,0) in (i,j,k) means a step of (-c,1-c,-c) in (x,y,z), and
+    // a step of (0,0,1) in (i,j,k) means a step of (-c,-c,1-c) in (x,y,z), where
+    // c = 1/6.
+    double x1 = x0 - i1 + G3; // Offsets for second corner in (x,y,z) coords
+    double y1 = y0 - j1 + G3;
+    double z1 = z0 - k1 + G3;
+    double x2 = x0 - i2 + 2.0*G3; // Offsets for third corner in (x,y,z) coords
+    double y2 = y0 - j2 + 2.0*G3;
+    double z2 = z0 - k2 + 2.0*G3;
+    double x3 = x0 - 1.0 + 3.0*G3; // Offsets for last corner in (x,y,z) coords
+    double y3 = y0 - 1.0 + 3.0*G3;
+    double z3 = z0 - 1.0 + 3.0*G3;
+    // Work out the hashed gradient indices of the four simplex corners
+    int ii = i & 255;
+    int jj = j & 255;
+    int kk = k & 255;
+    int gi0 = permMod12[ii+perm[jj+perm[kk]]];
+    int gi1 = permMod12[ii+i1+perm[jj+j1+perm[kk+k1]]];
+    int gi2 = permMod12[ii+i2+perm[jj+j2+perm[kk+k2]]];
+    int gi3 = permMod12[ii+1+perm[jj+1+perm[kk+1]]];
+    // Calculate the contribution from the four corners
+    double t0 = 0.6 - x0*x0 - y0*y0 - z0*z0;
+    if(t0<0) n0 = 0.0;
+    else
+    {
+        t0 *= t0;
+        n0 = t0 * t0 * Dot(grad3[gi0], x0, y0, z0);
+    }
+    double t1 = 0.6 - x1*x1 - y1*y1 - z1*z1;
+    if(t1<0) n1 = 0.0;
+    else
+    {
+        t1 *= t1;
+        n1 = t1 * t1 * Dot(grad3[gi1], x1, y1, z1);
+    }
+    double t2 = 0.6 - x2*x2 - y2*y2 - z2*z2;
+    if(t2<0) n2 = 0.0;
+    else
+    {
+        t2 *= t2;
+        n2 = t2 * t2 * Dot(grad3[gi2], x2, y2, z2);
+    }
+    double t3 = 0.6 - x3*x3 - y3*y3 - z3*z3;
+    if(t3<0) n3 = 0.0;
+    else
+    {
+        t3 *= t3;
+        n3 = t3 * t3 * Dot(grad3[gi3], x3, y3, z3);
+    }
+    // Add contributions from each corner to get the final noise value.
+    // The result is scaled to stay just inside [-1,1]
+    return 32.0*(n0 + n1 + n2 + n3);
+}
+
+double SimplexNoise::Noise(double x, double y, double z, double w) const
+{
+    double n0, n1, n2, n3, n4; // Noise contributions from the five corners
+    // Skew the (x,y,z,w) space to determine which cell of 24 simplices we're in
+    double s = (x + y + z + w) * F4; // Factor for 4D skewing
+    int i = FastFloor(x + s);
+    int j = FastFloor(y + s);
+    int k = FastFloor(z + s);
+    int l = FastFloor(w + s);
+    double t = (i + j + k + l) * G4; // Factor for 4D unskewing
+    double X0 = i - t; // Unskew the cell origin back to (x,y,z,w) space
+    double Y0 = j - t;
+    double Z0 = k - t;
+    double W0 = l - t;
+    double x0 = x - X0;    // The x,y,z,w distances from the cell origin
+    double y0 = y - Y0;
+    double z0 = z - Z0;
+    double w0 = w - W0;
+    // For the 4D case, the simplex is a 4D shape I won't even try to describe.
+    // To find out which of the 24 possible simplices we're in, we need to
+    // determine the magnitude ordering of x0, y0, z0 and w0.
+    // Six pair-wise comparisons are performed between each possible pair
+    // of the four coordinates, and the results are used to rank the numbers.
+    int rankx = 0;
+    int ranky = 0;
+    int rankz = 0;
+    int rankw = 0;
+    if(x0 > y0)
+    {
+        rankx++;
+    } else
+    {
+        ranky++;
+    }
+
+    if(x0 > z0)
+    {
+        rankx++;
+    } else
+    {
+        rankz++;
+    }
+
+    if(x0 > w0)
+    {
+        rankx++;
+    } else
+    {
+        rankw++;
+    }
+
+    if(y0 > z0)
+    {
+        ranky++;
+    } else
+    {
+        rankz++;
+    }
+
+    if(y0 > w0)
+    {
+        ranky++;
+    } else
+    {
+        rankw++;
+    }
+
+    if(z0 > w0)
+    {
+        rankz++;
+    } else
+    {
+        rankw++;
+    }
+
+    int i1, j1, k1, l1; // The integer offsets for the second simplex corner
+    int i2, j2, k2, l2; // The integer offsets for the third simplex corner
+    int i3, j3, k3, l3; // The integer offsets for the fourth simplex corner
+    // simplex[c] is a 4-vector with the numbers 0, 1, 2 and 3 in some order.
+    // Many values of c will never occur, since e.g. x>y>z>w makes x<z, y<w and x<w
+    // impossible. Only the 24 indices which have non-zero entries make any sense.
+    // We use a thresholding to set the coordinates in turn from the largest magnitude.
+    // Rank 3 denotes the largest coordinate.
+    i1 = rankx >= 3 ? 1 : 0;
+    j1 = ranky >= 3 ? 1 : 0;
+    k1 = rankz >= 3 ? 1 : 0;
+    l1 = rankw >= 3 ? 1 : 0;
+    // Rank 2 denotes the second largest coordinate.
+    i2 = rankx >= 2 ? 1 : 0;
+    j2 = ranky >= 2 ? 1 : 0;
+    k2 = rankz >= 2 ? 1 : 0;
+    l2 = rankw >= 2 ? 1 : 0;
+    // Rank 1 denotes the second smallest coordinate.
+    i3 = rankx >= 1 ? 1 : 0;
+    j3 = ranky >= 1 ? 1 : 0;
+    k3 = rankz >= 1 ? 1 : 0;
+    l3 = rankw >= 1 ? 1 : 0;
+    // The fifth corner has all coordinate offsets = 1, so no need to compute that.
+    double x1 = x0 - i1 + G4; // Offsets for second corner in (x,y,z,w) coords
+    double y1 = y0 - j1 + G4;
+    double z1 = z0 - k1 + G4;
+    double w1 = w0 - l1 + G4;
+    double x2 = x0 - i2 + 2.0*G4; // Offsets for third corner in (x,y,z,w) coords
+    double y2 = y0 - j2 + 2.0*G4;
+    double z2 = z0 - k2 + 2.0*G4;
+    double w2 = w0 - l2 + 2.0*G4;
+    double x3 = x0 - i3 + 3.0*G4; // Offsets for fourth corner in (x,y,z,w) coords
+    double y3 = y0 - j3 + 3.0*G4;
+    double z3 = z0 - k3 + 3.0*G4;
+    double w3 = w0 - l3 + 3.0*G4;
+    double x4 = x0 - 1.0 + 4.0*G4; // Offsets for last corner in (x,y,z,w) coords
+    double y4 = y0 - 1.0 + 4.0*G4;
+    double z4 = z0 - 1.0 + 4.0*G4;
+    double w4 = w0 - 1.0 + 4.0*G4;
+    // Work out the hashed gradient indices of the five simplex corners
+    int ii = i & 255;
+    int jj = j & 255;
+    int kk = k & 255;
+    int ll = l & 255;
+    int gi0 = perm[ii+perm[jj+perm[kk+perm[ll]]]] % 32;
+    int gi1 = perm[ii+i1+perm[jj+j1+perm[kk+k1+perm[ll+l1]]]] % 32;
+    int gi2 = perm[ii+i2+perm[jj+j2+perm[kk+k2+perm[ll+l2]]]] % 32;
+    int gi3 = perm[ii+i3+perm[jj+j3+perm[kk+k3+perm[ll+l3]]]] % 32;
+    int gi4 = perm[ii+1+perm[jj+1+perm[kk+1+perm[ll+1]]]] % 32;
+    // Calculate the contribution from the five corners
+    double t0 = 0.6 - x0*x0 - y0*y0 - z0*z0 - w0*w0;
+    if(t0<0) n0 = 0.0;
+    else {
+        t0 *= t0;
+        n0 = t0 * t0 * Dot(grad4[gi0], x0, y0, z0, w0);
+    }
+    double t1 = 0.6 - x1*x1 - y1*y1 - z1*z1 - w1*w1;
+    if(t1<0) n1 = 0.0;
+    else {
+        t1 *= t1;
+        n1 = t1 * t1 * Dot(grad4[gi1], x1, y1, z1, w1);
+    }
+    double t2 = 0.6 - x2*x2 - y2*y2 - z2*z2 - w2*w2;
+    if(t2<0) n2 = 0.0;
+    else {
+        t2 *= t2;
+        n2 = t2 * t2 * Dot(grad4[gi2], x2, y2, z2, w2);
+    }
+    double t3 = 0.6 - x3*x3 - y3*y3 - z3*z3 - w3*w3;
+    if(t3<0) n3 = 0.0;
+    else {
+        t3 *= t3;
+        n3 = t3 * t3 * Dot(grad4[gi3], x3, y3, z3, w3);
+    }
+    double t4 = 0.6 - x4*x4 - y4*y4 - z4*z4 - w4*w4;
+    if(t4<0) n4 = 0.0;
+    else {
+        t4 *= t4;
+        n4 = t4 * t4 * Dot(grad4[gi4], x4, y4, z4, w4);
+    }
+    // Sum up and scale the result to cover the range [-1,1]
+    return 27.0 * (n0 + n1 + n2 + n3 + n4);
+}
diff --git a/src/osgEarthProcedural/SplatCatalog b/src/osgEarthProcedural/SplatCatalog
new file mode 100644
index 0000000..ff56066
--- /dev/null
+++ b/src/osgEarthProcedural/SplatCatalog
@@ -0,0 +1,161 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+ * Copyright 2008-2014 Pelican Mapping
+ * http://osgearth.org
+ *
+ * osgEarth is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ */
+#ifndef OSGEARTH_PROCEDURAL_SPLAT_CATALOG
+#define OSGEARTH_PROCEDURAL_SPLAT_CATALOG 1
+
+#include "Common"
+#include <osg/Referenced>
+
+#include <osgEarth/Containers>
+#include <osgEarth/URI>
+
+// forward declarations
+namespace osg {
+    class Texture2DArray;
+}
+namespace osgDB {
+    class Options;
+}
+
+namespace osgEarth { namespace Procedural
+{
+    /**
+     * Defines the parameters for noise-generated detail splatting
+     * for a given class/range.
+     */
+    struct SplatDetailData
+    {
+        optional<URI>         _imageURI;
+        optional<float>       _saturation;
+        optional<float>       _threshold;
+        optional<float>       _slope;
+
+        // catalog will populate this value
+        int _textureIndex;
+
+        SplatDetailData();
+        SplatDetailData(const Config& conf);
+        Config getConfig() const;
+    };
+
+    /**
+     * Defines a single splatting appearance that will be used if its
+     * selector expression evaluates to true.
+     */
+    struct SplatRangeData
+    {
+        optional<float>           _minRange;
+        optional<URI>             _imageURI;
+        optional<URI>             _modelURI;
+        optional<int>             _modelCount;
+        optional<int>             _modelLevel;
+        optional<SplatDetailData> _detail;
+
+        // catalog will populate this value
+        int _textureIndex;
+
+        SplatRangeData();
+        SplatRangeData(const Config& conf);
+        Config getConfig() const;
+    };
+
+    typedef std::vector<SplatRangeData> SplatRangeDataVector;
+
+    /**
+     * A single splatting class. One class may have multiple
+     * data definitions, which are evaluated in order of appearance.
+     */
+    struct SplatClass
+    {
+        std::string          _name;
+        SplatRangeDataVector _ranges;
+
+        SplatClass();
+        SplatClass(const Config& conf);
+        Config getConfig() const;
+    };
+    
+    typedef osgEarth::fast_map<std::string, SplatClass> SplatClassMap;
+    
+    // Associates a selector expression that, if it evaluates to true, will
+    // select the specified splat texture
+    typedef std::pair<std::string /*expression*/, SplatRangeData> SplatSelector;
+
+    // Vector of selectors
+    typedef std::vector<SplatSelector> SplatSelectorVector;
+
+    // Maps splat class names to texture data renderers
+    typedef osgEarth::fast_map<std::string /*className*/, SplatSelectorVector> SplatLUT;
+
+    // Defines the splatting texture and associated lookup table.
+    struct SplatTextureDef
+    {
+        osg::ref_ptr<osg::Texture2DArray> _texture;
+        SplatLUT                          _splatLUT;
+    };
+
+
+    /**
+     * Catalog of texture-splatting classes. Usually these correspond
+     * to land use.
+     */
+    class SplatCatalog : public osg::Referenced
+    {
+    public:
+        /**
+         * Construct an empty catalog.
+         */
+        SplatCatalog();
+
+        /**
+         * The splatting classifications set.
+         */
+        const SplatClassMap& getClasses() const { return _classes; }
+
+        /**
+         * Create a texture array from the images in the catalog, along
+         * with a definition of how to map classifications to texture
+         * array indices.
+         */
+        bool createSplatTextureDef(const osgDB::Options* options,
+                                   SplatTextureDef&      out_def );
+
+
+    public: // serialization
+
+        // populate this object from a Config
+        void fromConfig(const Config& conf);
+
+        // serialize this object to a Config.
+        Config getConfig() const;
+
+
+    protected:
+
+        virtual ~SplatCatalog() { }
+
+        optional<int>         _version;
+        optional<std::string> _name;
+        optional<std::string> _description;
+        SplatClassMap         _classes;
+    };
+
+} } // namespace osgEarth::Procedural
+
+#endif // OSGEARTH_PROCEDURAL_SPLAT_CATALOG
diff --git a/src/osgEarthProcedural/SplatCatalog.cpp b/src/osgEarthProcedural/SplatCatalog.cpp
new file mode 100644
index 0000000..55fd3cb
--- /dev/null
+++ b/src/osgEarthProcedural/SplatCatalog.cpp
@@ -0,0 +1,343 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+ * Copyright 2008-2014 Pelican Mapping
+ * http://osgearth.org
+ *
+ * osgEarth is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ */
+#include "SplatCatalog"
+#include <osgEarth/Config>
+#include <osgEarth/ImageUtils>
+#include <osg/Texture2DArray>
+
+using namespace osgEarth;
+using namespace osgEarth::Procedural;
+
+#define LC "[SplatCatalog] "
+
+#define SPLAT_CATALOG_CURRENT_VERSION 1
+
+
+//............................................................................
+
+SplatDetailData::SplatDetailData() :
+_textureIndex( -1 )
+{
+    //nop
+}
+
+SplatDetailData::SplatDetailData(const Config& conf) :
+_textureIndex( -1 )
+{
+    conf.getIfSet("image",      _imageURI);
+    conf.getIfSet("saturation", _saturation);
+    conf.getIfSet("threshold",  _threshold);
+    conf.getIfSet("slope",      _slope);
+}
+
+Config
+SplatDetailData::getConfig() const
+{
+    Config conf;
+    conf.addIfSet("image",      _imageURI);
+    conf.addIfSet("saturation", _saturation);
+    conf.addIfSet("threshold",  _threshold);
+    conf.addIfSet("slope",      _slope);
+    return conf;
+}
+
+//............................................................................
+
+SplatRangeData::SplatRangeData() :
+_textureIndex( -1 )
+{
+    //nop
+}
+
+SplatRangeData::SplatRangeData(const Config& conf) :
+_textureIndex( -1 )
+{
+    conf.getIfSet("image",      _imageURI);
+    conf.getIfSet("model",      _modelURI);
+    conf.getIfSet("modelCount", _modelCount);
+    conf.getIfSet("modelLevel", _modelLevel);
+
+    if ( conf.hasChild("detail") )
+        _detail = SplatDetailData(conf.child("detail"));
+}
+
+Config
+SplatRangeData::getConfig() const
+{
+    Config conf;
+    conf.addIfSet("image",      _imageURI);
+    conf.addIfSet("model",      _modelURI);
+    conf.addIfSet("modelCount", _modelCount);
+    conf.addIfSet("modelLevel", _modelLevel);
+    if ( _detail.isSet() )
+        conf.add( "detail", _detail->getConfig() );
+
+    return conf;
+}
+
+//............................................................................
+
+SplatClass::SplatClass()
+{
+    //nop
+}
+
+SplatClass::SplatClass(const Config& conf)
+{
+    _name = conf.key();
+
+    // read the data definitions in order:
+    for(ConfigSet::const_iterator i = conf.children().begin(); i != conf.children().end(); ++i)
+    {
+        if ( !i->empty() )
+        {
+            _ranges.push_back(SplatRangeData(*i));
+        }
+    }
+}
+
+Config
+SplatClass::getConfig() const
+{
+    Config conf( _name );
+    for(SplatRangeDataVector::const_iterator i = _ranges.begin(); i != _ranges.end(); ++i)
+    {
+        conf.add( i->getConfig() );
+    }
+    return conf;
+}
+
+//............................................................................
+
+SplatCatalog::SplatCatalog()
+{
+    _version = SPLAT_CATALOG_CURRENT_VERSION;
+}
+
+void
+SplatCatalog::fromConfig(const Config& conf)
+{
+    conf.getIfSet("version",     _version);
+    conf.getIfSet("name",        _name);
+    conf.getIfSet("description", _description);
+
+    Config classesConf = conf.child("classes");
+    if ( !classesConf.empty() )
+    {
+        for(ConfigSet::const_iterator i = classesConf.children().begin(); i != classesConf.children().end(); ++i)
+        {
+            if ( !i->key().empty() )
+            {
+                _classes[i->key()] = SplatClass(*i);
+            }
+        }
+    }
+}
+
+Config
+SplatCatalog::getConfig() const
+{
+    Config conf;
+    conf.addIfSet("version",     _version);
+    conf.addIfSet("name",        _name);
+    conf.addIfSet("description", _description);
+    
+    Config classes("classes");
+    {
+        for(SplatClassMap::const_iterator i = _classes.begin(); i != _classes.end(); ++i)
+        {
+            classes.add( i->second.getConfig() );
+        }
+    }    
+    conf.add( classes );
+
+    return conf;
+}
+
+namespace
+{
+    osg::Image* loadImage(const URI& uri, const osgDB::Options* dbOptions, osg::Image* firstImage)
+    {
+        // try to load the image:
+        ReadResult result = uri.readImage(dbOptions);
+        if ( result.succeeded() )
+        {
+            // if this is the first image loaded, remember it so we can ensure that
+            // all images are copatible.
+            if ( firstImage == 0L )
+            {
+                firstImage = result.getImage();
+            }
+            else
+            {
+                // ensure compatibility, a requirement for texture arrays.
+                // In the future perhaps we can resize/convert instead.
+                if ( !ImageUtils::textureArrayCompatible(result.getImage(), firstImage) )
+                {
+                    OE_WARN << LC << "Image " << uri.base()
+                        << " was found, but cannot be used because it is not compatible with "
+                        << "other splat images (same dimensions, pixel format, etc.)\n";
+
+                    return 0L;
+                }
+            }
+        }
+        else
+        {
+            OE_WARN << LC
+                << "Image in the splat catalog failed to load: "
+                << uri.full() << "; message = " << result.getResultCodeString()
+                << std::endl;
+        }
+
+        return result.releaseImage();
+    }
+}
+
+bool
+SplatCatalog::createSplatTextureDef(const osgDB::Options* dbOptions,
+                                    SplatTextureDef&      out      )
+{
+    // Reset all texture indices to default
+    for(SplatClassMap::iterator i = _classes.begin(); i != _classes.end(); ++i)
+    {
+        SplatClass& c = i->second;
+        for(SplatRangeDataVector::iterator range = c._ranges.begin(); range != c._ranges.end(); ++range)
+        {
+            range->_textureIndex = -1;
+            if ( range->_detail.isSet() )
+            {
+                range->_detail->_textureIndex = -1;
+            }
+        }
+    }
+
+    typedef osgEarth::fast_map<URI, int> ImageIndexTable; // track images to prevent dupes
+    ImageIndexTable imageIndices;
+    std::vector< osg::ref_ptr<osg::Image> > imagesInOrder;
+    int index = 0;
+    osg::Image* firstImage  = 0L;
+
+    // Load all referenced images in the catalog, and assign each a unique index.
+    for(SplatClassMap::iterator i = _classes.begin(); i != _classes.end(); ++i)
+    {
+        SplatClass& c = i->second;
+
+        for(SplatRangeDataVector::iterator range = c._ranges.begin(); range != c._ranges.end(); ++range)
+        {
+            // Load the main image and assign it an index:
+            if (range->_imageURI.isSet())
+            {
+                int texIndex = -1;
+                ImageIndexTable::iterator k = imageIndices.find(range->_imageURI.get());
+                if ( k == imageIndices.end() )
+                {
+                    osg::ref_ptr<osg::Image> image = loadImage( range->_imageURI.get(), dbOptions, firstImage );
+                    if ( image.valid() )
+                    {
+                        if ( !firstImage )
+                            firstImage = image.get();
+
+                        imageIndices[range->_imageURI.get()] = texIndex = index++;
+                        imagesInOrder.push_back( image.get() );
+                    }
+                }
+                else
+                {
+                    texIndex = k->second;
+                }
+                range->_textureIndex = texIndex;
+            }
+
+            // Load the detail texture if it exists:
+            if (range->_detail.isSet() &&
+                range->_detail->_imageURI.isSet())
+            {
+                int texIndex = -1;
+                ImageIndexTable::iterator k = imageIndices.find(range->_detail->_imageURI.get());
+                if ( k == imageIndices.end() )
+                {
+                    osg::ref_ptr<osg::Image> image = loadImage( range->_detail->_imageURI.get(), dbOptions, firstImage );
+                    if ( image.valid() )
+                    {
+                        if ( !firstImage )
+                            firstImage = image.get();
+            
+                        imageIndices[range->_detail->_imageURI.get()] = texIndex = index++;
+                        imagesInOrder.push_back( image.get() );
+                    }
+                }
+                else
+                {
+                    texIndex = k->second;
+                }
+                range->_detail->_textureIndex = texIndex;
+            }
+        }
+    }
+
+    // Next, go through the classes and build the splat lookup table.
+    for(SplatClassMap::const_iterator i = _classes.begin(); i != _classes.end(); ++i)
+    {
+        const SplatClass& c = i->second;
+
+        // selectors for this class (ordered):
+        SplatSelectorVector selectors;
+
+        // check each data element:
+        for(SplatRangeDataVector::const_iterator range = c._ranges.begin(); range != c._ranges.end(); ++range)
+        {
+            // If the primary image exists, look up its index and add it to the selector set.
+            ImageIndexTable::const_iterator k = imageIndices.find( range->_imageURI.get() );
+            if ( k != imageIndices.end() )
+            {
+                std::string expression;
+                if ( range->_minRange.isSet() )
+                {
+                    expression = Stringify()
+                        << "env.range >= float(" << range->_minRange.get() << ")";
+                }
+
+                // insert into the lookup table.
+                out._splatLUT[c._name].push_back( SplatSelector(expression, *range) );
+            }
+        }
+    }
+
+    // Create the texture array.
+    if ( imagesInOrder.size() > 0 )
+    {
+        out._texture = new osg::Texture2DArray();
+        out._texture->setTextureSize( firstImage->s(), firstImage->t(), imagesInOrder.size() );
+        out._texture->setWrap( osg::Texture::WRAP_S, osg::Texture::REPEAT );
+        out._texture->setWrap( osg::Texture::WRAP_T, osg::Texture::REPEAT );
+        out._texture->setFilter( osg::Texture::MIN_FILTER, osg::Texture::LINEAR_MIPMAP_LINEAR );
+        out._texture->setFilter( osg::Texture::MAG_FILTER, osg::Texture::LINEAR );
+        out._texture->setResizeNonPowerOfTwoHint( false );
+        out._texture->setMaxAnisotropy( 4.0f );
+
+        for(unsigned i=0; i<imagesInOrder.size(); ++i)
+        {
+            out._texture->setImage( i, imagesInOrder[i].get() );
+        }
+
+    }
+
+    return out._texture.valid();
+}
diff --git a/src/osgEarthQt/Actions b/src/osgEarthQt/Actions
index 431db0f..9f438a5 100644
--- a/src/osgEarthQt/Actions
+++ b/src/osgEarthQt/Actions
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthQt/AnnotationListWidget.cpp b/src/osgEarthQt/AnnotationListWidget.cpp
index 5a47417..4c4a2d4 100644
--- a/src/osgEarthQt/AnnotationListWidget.cpp
+++ b/src/osgEarthQt/AnnotationListWidget.cpp
@@ -190,7 +190,6 @@ void AnnotationListWidget::refresh()
   {
     _annoList->clear();
 
-    osgEarth::Annotation::AnnotationData* annoData = 0L;
     bool annoDataSet = false;
 
     AnnotationVector annos;
@@ -198,28 +197,19 @@ void AnnotationListWidget::refresh()
     for (AnnotationVector::const_iterator it = annos.begin(); it != annos.end(); ++it)
     {
       AnnotationListItem* item = new AnnotationListItem(*it);
-      item->setText(QString(tr((*it)->getAnnotationData() ? (*it)->getAnnotationData()->getName().c_str() : "Annotation")));
+      item->setText( QString(tr((*it)->getName())) );
       item->setCheckState((*it)->getNodeMask() != 0 ? Qt::Checked : Qt::Unchecked);
 
       _annoList->addItem(item);
 
       if (_manager->isSelected(*it))
       {
-        if (!annoDataSet)
-        {
-          annoData = (*it)->getAnnotationData();
-          annoDataSet = true;
-        }
-        else
-          annoData = 0L;
-
         item->setSelected(true);
       }
     }
 
     _nameField->setText(tr(annoData ? annoData->getName().c_str() : "-----"));
     _priorityField->setText(annoData ? QString::number(annoData->getPriority()) : tr("-----"));
-    _viewpointField->setText(tr(annoData && annoData->getViewpoint() ? annoData->getViewpoint()->toString().c_str() : "-----"));
     _descriptionField->setText(tr(annoData ? annoData->getDescription().c_str() : ""));
   }
 
diff --git a/src/osgEarthQt/CMakeLists.txt b/src/osgEarthQt/CMakeLists.txt
index dd451bb..2d07d74 100644
--- a/src/osgEarthQt/CMakeLists.txt
+++ b/src/osgEarthQt/CMakeLists.txt
@@ -1,3 +1,6 @@
+IF (Qt5Widgets_FOUND OR QT4_FOUND AND NOT ANDROID AND OSGEARTH_USE_QT)
+
+
 IF   (DYNAMIC_OSGEARTH)
     ADD_DEFINITIONS(-DOSGEARTHQT_LIBRARY)
 ELSE (DYNAMIC_OSGEARTH)
@@ -8,42 +11,49 @@ SET(LIB_NAME osgEarthQt)
 
 SET(HEADER_PATH ${OSGEARTH_SOURCE_DIR}/include/${LIB_NAME})
 
-# Header files that need moc'd
-set(LIB_MOC_HDRS
-    AnnotationDialogs
-    AnnotationListWidget
-    AnnotationToolbar
-    CollapsiblePairWidget
-    DataManager
-    LayerManagerWidget
-    LOSControlWidget
-    LOSCreationDialog
-    MapCatalogWidget
-    TerrainProfileGraph
-    TerrainProfileWidget
-    ViewerWidget
-)
-
-# Qt resource files
-set(LIB_QT_RCS
-    images.qrc
-)
-
-# Qt UI files
-set(LIB_QT_UIS
-    ui/LOSCreationDialog.ui
-)
+if(OSGEARTH_QT_BUILD_LEGACY_WIDGETS)
+    # Header files that need moc'd
+    set(LIB_MOC_HDRS
+        #AnnotationDialogs
+        #AnnotationListWidget
+        #AnnotationToolbar
+        CollapsiblePairWidget
+        DataManager
+        LayerManagerWidget
+        LOSControlWidget
+        LOSCreationDialog
+        MapCatalogWidget
+        TerrainProfileGraph
+        TerrainProfileWidget
+        ViewerWidget
+    )
+
+    # Qt resource files
+    set(LIB_QT_RCS
+        images.qrc
+    )
+
+    # Qt UI files
+    set(LIB_QT_UIS
+        ui/LOSCreationDialog.ui
+    )
+else(OSGEARTH_QT_BUILD_LEGACY_WIDGETS)
+    # Header files that need moc'd
+    set(LIB_MOC_HDRS
+        ViewerWidget
+    )
+endif(OSGEARTH_QT_BUILD_LEGACY_WIDGETS)
 
 IF(Qt5Widgets_FOUND)
     QT5_ADD_RESOURCES( LIB_RC_SRCS ${LIB_QT_RCS} )
     QT5_WRAP_UI( LIB_UI_HDRS ${LIB_QT_UIS} )
-    IF(Qt5Widgets_VERSION VERSION_LESS 5.2.0)
-        QT5_WRAP_CPP( LIB_UI_SRCS ${LIB_UI_HDRS} OPTIONS "-f" )
-        QT5_WRAP_CPP( LIB_MOC_SRCS ${LIB_MOC_HDRS} OPTIONS "-f" )
-    ELSE()
-        QT5_WRAP_CPP( LIB_UI_SRCS ${LIB_UI_HDRS} )
-        QT5_WRAP_CPP( LIB_MOC_SRCS ${LIB_MOC_HDRS} )
-    ENDIF()
+    QT5_WRAP_CPP( LIB_UI_SRCS ${LIB_UI_HDRS} )
+    SET(LIB_MOC_SRCS)
+    FOREACH( LIB_MOC_HDR ${LIB_MOC_HDRS} )
+        GET_FILENAME_COMPONENT( LIB_MOC_HDR_ABS ${LIB_MOC_HDR} ABSOLUTE )
+        QT5_WRAP_CPP( LIB_MOC_SRC ${LIB_MOC_HDR} OPTIONS "-f${LIB_MOC_HDR_ABS}" )
+        LIST( APPEND LIB_MOC_SRCS ${LIB_MOC_SRC} )
+    ENDFOREACH()
 ELSE()
     INCLUDE( ${QT_USE_FILE} )
     QT4_ADD_RESOURCES( LIB_RC_SRCS ${LIB_QT_RCS} )
@@ -52,49 +62,71 @@ ELSE()
     QT4_WRAP_CPP( LIB_MOC_SRCS ${LIB_MOC_HDRS} OPTIONS "-f" )
 ENDIF()
 
-SET(LIB_PUBLIC_HEADERS
-#   header files go here
-    Actions
-    AnnotationDialogs
-    AnnotationListWidget
-    AnnotationToolbar
-    CollapsiblePairWidget
-    Common
-    DataManager
-    GuiActions
-    LayerManagerWidget
-    LOSControlWidget
-    LOSCreationDialog
-    MapCatalogWidget
-    TerrainProfileGraph
-    TerrainProfileWidget
-    ViewWidget
-    ViewerWidget
-    ${LIB_UI_HDRS}
-    ${LIB_QT_UIS}
-    ${LIB_QT_RCS}
-)
-
-ADD_LIBRARY(${LIB_NAME} SHARED
-    ${LIB_PUBLIC_HEADERS}
-#  .cpp files go here
-    ${LIB_RC_SRCS}
-    ${LIB_UI_SRCS}
-    ${LIB_MOC_SRCS}
-    AnnotationDialogs.cpp
-    AnnotationListWidget.cpp
-    AnnotationToolbar.cpp
-    CollapsiblePairWidget.cpp
-    DataManager.cpp
-    LayerManagerWidget.cpp
-    LOSControlWidget.cpp
-    LOSCreationDialog.cpp
-    MapCatalogWidget.cpp
-    TerrainProfileGraph.cpp
-    TerrainProfileWidget.cpp
-    ViewWidget.cpp
-    ViewerWidget.cpp
-)
+if(OSGEARTH_QT_BUILD_LEGACY_WIDGETS)
+    SET(LIB_PUBLIC_HEADERS
+    #   header files go here
+        Actions
+        #AnnotationDialogs
+        #AnnotationListWidget
+        #AnnotationToolbar
+        CollapsiblePairWidget
+        Common
+        DataManager
+        GuiActions
+        LayerManagerWidget
+        LOSControlWidget
+        LOSCreationDialog
+        MapCatalogWidget
+        TerrainProfileGraph
+        TerrainProfileWidget
+        ViewWidget
+        ViewerWidget
+        ${LIB_UI_HDRS}
+        ${LIB_QT_UIS}
+        ${LIB_QT_RCS}
+    )
+
+    ADD_LIBRARY(${LIB_NAME} SHARED
+        ${LIB_PUBLIC_HEADERS}
+    #  .cpp files go here
+        ${LIB_RC_SRCS}
+        ${LIB_UI_SRCS}
+        ${LIB_MOC_SRCS}
+        #AnnotationDialogs.cpp
+        #AnnotationListWidget.cpp
+        #AnnotationToolbar.cpp
+        CollapsiblePairWidget.cpp
+        DataManager.cpp
+        LayerManagerWidget.cpp
+        LOSControlWidget.cpp
+        LOSCreationDialog.cpp
+        MapCatalogWidget.cpp
+        TerrainProfileGraph.cpp
+        TerrainProfileWidget.cpp
+        ViewWidget.cpp
+        ViewerWidget.cpp
+    )
+else(OSGEARTH_QT_BUILD_LEGACY_WIDGETS)
+    SET(LIB_PUBLIC_HEADERS
+    #   header files go here
+        Common
+        ViewWidget
+        ViewerWidget
+        ${LIB_UI_HDRS}
+        ${LIB_QT_UIS}
+        ${LIB_QT_RCS}
+    )
+
+    ADD_LIBRARY(${LIB_NAME} SHARED
+        ${LIB_PUBLIC_HEADERS}
+    #  .cpp files go here
+        ${LIB_RC_SRCS}
+        ${LIB_UI_SRCS}
+        ${LIB_MOC_SRCS}
+        ViewWidget.cpp
+        ViewerWidget.cpp
+    )
+endif(OSGEARTH_QT_BUILD_LEGACY_WIDGETS)
 
 INCLUDE_DIRECTORIES(${OSG_INCLUDE_DIR} ${OSGEARTH_SOURCE_DIR} ${QT_INCLUDES} ${CMAKE_CURRENT_BINARY_DIR})
 
@@ -104,14 +136,24 @@ ELSE(WIN32)
   LINK_EXTERNAL(${LIB_NAME} ${TARGET_EXTERNAL_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} ${MATH_LIBRARY})
 ENDIF(WIN32)
 
-LINK_INTERNAL(${LIB_NAME}
-    osgEarth
-    osgEarthAnnotation
-    osgEarthUtil
-    ${QT_QTCORE_LIBRARY}
-    ${QT_QTGUI_LIBRARY}
-    ${QT_QTOPENGL_LIBRARY}
-)
+if(OSGEARTH_QT_BUILD_LEGACY_WIDGETS)
+    link_internal(${LIB_NAME}
+        osgEarth
+        osgEarthAnnotation
+        osgEarthUtil
+        ${QT_QTCORE_LIBRARY}
+        ${QT_QTGUI_LIBRARY}
+        ${QT_QTOPENGL_LIBRARY}
+    )
+else(OSGEARTH_QT_BUILD_LEGACY_WIDGETS)
+    link_internal(${LIB_NAME}
+        osgEarth
+        osgEarthUtil
+        ${QT_QTCORE_LIBRARY}
+        ${QT_QTGUI_LIBRARY}
+        ${QT_QTOPENGL_LIBRARY}
+    )
+endif(OSGEARTH_QT_BUILD_LEGACY_WIDGETS)
 
 LINK_WITH_VARIABLES(${LIB_NAME} OSG_LIBRARY OSGWIDGET_LIBRARY OSGUTIL_LIBRARY OSGSIM_LIBRARY OSGTERRAIN_LIBRARY OSGDB_LIBRARY OSGFX_LIBRARY OSGVIEWER_LIBRARY OSGTEXT_LIBRARY OSGGA_LIBRARY OSGQT_LIBRARY OPENTHREADS_LIBRARY)
 
@@ -121,4 +163,9 @@ IF ( Qt5Widgets_FOUND )
     qt5_use_modules( ${LIB_NAME} Gui Widgets OpenGL )
 ENDIF( Qt5Widgets_FOUND )
 
+# Add this project to the NodeKits solution folder
+set_property( TARGET ${LIB_NAME} PROPERTY FOLDER "NodeKits" )
+
 INCLUDE(ModuleInstall OPTIONAL)
+
+ENDIF (Qt5Widgets_FOUND OR QT4_FOUND AND NOT ANDROID AND OSGEARTH_USE_QT)
\ No newline at end of file
diff --git a/src/osgEarthQt/CollapsiblePairWidget b/src/osgEarthQt/CollapsiblePairWidget
index 4755584..9a55070 100644
--- a/src/osgEarthQt/CollapsiblePairWidget
+++ b/src/osgEarthQt/CollapsiblePairWidget
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthQt/CollapsiblePairWidget.cpp b/src/osgEarthQt/CollapsiblePairWidget.cpp
index a9f04a9..556f88f 100644
--- a/src/osgEarthQt/CollapsiblePairWidget.cpp
+++ b/src/osgEarthQt/CollapsiblePairWidget.cpp
@@ -1,5 +1,5 @@
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthQt/Common b/src/osgEarthQt/Common
index 73147d9..5f0851f 100644
--- a/src/osgEarthQt/Common
+++ b/src/osgEarthQt/Common
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthQt/DataManager b/src/osgEarthQt/DataManager
index 6390749..eed02af 100644
--- a/src/osgEarthQt/DataManager
+++ b/src/osgEarthQt/DataManager
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthQt/DataManager.cpp b/src/osgEarthQt/DataManager.cpp
index 7b87b58..52f7296 100644
--- a/src/osgEarthQt/DataManager.cpp
+++ b/src/osgEarthQt/DataManager.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
@@ -159,7 +159,7 @@ void DataManager::addSelectedAnnotation(osgEarth::Annotation::AnnotationNode* an
 
     if (added)
     {
-      annotation->setDecoration(_selectedDecoration);
+      //annotation->setDecoration(_selectedDecoration);
       _selection.push_back(annotation);
     }
   }
@@ -179,7 +179,7 @@ void DataManager::removeSelectedAnnotation(osgEarth::Annotation::AnnotationNode*
     AnnotationVector::iterator found = std::find(_selection.begin(), _selection.end(), annotation);
     if (found != _selection.end())
     {
-      annotation->clearDecoration();
+      //annotation->clearDecoration();
       _selection.erase(found);
       removed = true;
     }
@@ -201,7 +201,7 @@ void DataManager::setSelectedAnnotations(const AnnotationVector& annotations)
 
     for (AnnotationVector::const_iterator itNew = annotations.begin(); itNew != annotations.end(); ++itNew)
     {
-      (*itNew)->setDecoration(_selectedDecoration);
+      //(*itNew)->setDecoration(_selectedDecoration);
       _selection.push_back(*itNew);
     }
   }
@@ -217,8 +217,8 @@ void DataManager::clearSelectedAnnotations()
   {
     Threading::ScopedWriteLock lock(const_cast<DataManager*>(this)->_dataMutex);
 
-    for (AnnotationVector::iterator itOld = _selection.begin(); itOld != _selection.end(); ++itOld)
-      (*itOld)->clearDecoration();
+    //for (AnnotationVector::iterator itOld = _selection.begin(); itOld != _selection.end(); ++itOld)
+    //  (*itOld)->clearDecoration();
 
     _selection.clear();
   }
diff --git a/src/osgEarthQt/GuiActions b/src/osgEarthQt/GuiActions
index 628ce2a..a9fd477 100644
--- a/src/osgEarthQt/GuiActions
+++ b/src/osgEarthQt/GuiActions
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthQt/LOSControlWidget b/src/osgEarthQt/LOSControlWidget
index f500ec8..111a4b8 100644
--- a/src/osgEarthQt/LOSControlWidget
+++ b/src/osgEarthQt/LOSControlWidget
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthQt/LOSControlWidget.cpp b/src/osgEarthQt/LOSControlWidget.cpp
index 4214c23..7568c44 100644
--- a/src/osgEarthQt/LOSControlWidget.cpp
+++ b/src/osgEarthQt/LOSControlWidget.cpp
@@ -1,5 +1,5 @@
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthQt/LOSCreationDialog b/src/osgEarthQt/LOSCreationDialog
index eb38c08..e40471a 100644
--- a/src/osgEarthQt/LOSCreationDialog
+++ b/src/osgEarthQt/LOSCreationDialog
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthQt/LOSCreationDialog.cpp b/src/osgEarthQt/LOSCreationDialog.cpp
index 0be65e2..21cc3f3 100644
--- a/src/osgEarthQt/LOSCreationDialog.cpp
+++ b/src/osgEarthQt/LOSCreationDialog.cpp
@@ -1,5 +1,5 @@
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
@@ -101,8 +101,8 @@ void LOSCreationDialog::initUi(const std::string& name, osg::Group* los)
   //       to the on__TypeChange() methods.  Currently doing here for efficiency.
   for (AnnotationVector::const_iterator it = _annotations.begin(); it != _annotations.end(); ++it)
   {
-    osgEarth::Annotation::AnnotationData* annoData = (*it)->getAnnotationData();
-    std::string annoName = annoData && annoData->getName().size() > 0 ? annoData->getName() : "Annotation";
+    std::string annoName = (*it)->getName();
+    if ( annoName.empty() ) annoName = "Annotation";
     _ui.p1NodeCombo->addItem(tr(annoName.c_str()));
     _ui.p2NodeCombo->addItem(tr(annoName.c_str()));
     _ui.radNodeCombo->addItem(tr(annoName.c_str()));
@@ -751,9 +751,11 @@ void LOSCreationDialog::centerMapOnNode(osg::Node* node)
   if (node && _map.valid() && _manager.valid() && _views)
   {
     AnnotationNode* annoNode = dynamic_cast<AnnotationNode*>(node);
-    if (annoNode && annoNode->getAnnotationData() && annoNode->getAnnotationData()->getViewpoint())
+    if (annoNode)
     {
-      _manager->doAction(this, new SetViewpointAction(osgEarth::Viewpoint(*annoNode->getAnnotationData()->getViewpoint()), *_views));
+      osgEarth::Viewpoint vp;
+      vp.setNode( annoNode );
+      _manager->doAction(this, new SetViewpointAction(vp, *_views));
     }
     else
     {
diff --git a/src/osgEarthQt/LayerManagerWidget b/src/osgEarthQt/LayerManagerWidget
index a46906a..26179aa 100644
--- a/src/osgEarthQt/LayerManagerWidget
+++ b/src/osgEarthQt/LayerManagerWidget
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthQt/LayerManagerWidget.cpp b/src/osgEarthQt/LayerManagerWidget.cpp
index ce1a8e7..63d2dcf 100644
--- a/src/osgEarthQt/LayerManagerWidget.cpp
+++ b/src/osgEarthQt/LayerManagerWidget.cpp
@@ -1,5 +1,5 @@
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
@@ -619,7 +619,7 @@ Action* ModelLayerControlWidget::getDoubleClickAction(const ViewVector& views)
 {
   if (!_doubleClick.valid() && _layer.valid() && _map.valid())
   {
-    osg::ref_ptr<osg::Node> temp = _layer->getOrCreateSceneGraph( _map.get(), _map->getDBOptions(), 0L );
+    osg::ref_ptr<osg::Node> temp = _layer->getOrCreateSceneGraph( _map.get(), _map->getReadOptions(), 0L );
     if (temp.valid())
     {
       osg::NodePathList nodePaths = temp->getParentalNodePaths();
diff --git a/src/osgEarthQt/MapCatalogWidget b/src/osgEarthQt/MapCatalogWidget
index 8c9e31e..8e5d898 100644
--- a/src/osgEarthQt/MapCatalogWidget
+++ b/src/osgEarthQt/MapCatalogWidget
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthQt/MapCatalogWidget.cpp b/src/osgEarthQt/MapCatalogWidget.cpp
index 01d088c..32cf276 100644
--- a/src/osgEarthQt/MapCatalogWidget.cpp
+++ b/src/osgEarthQt/MapCatalogWidget.cpp
@@ -1,5 +1,5 @@
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
@@ -113,7 +113,7 @@ namespace
           osgEarth::ModelLayer* model = dynamic_cast<osgEarth::ModelLayer*>(_layer.get());
           if (model && _map.valid())
           {
-            osg::ref_ptr<osg::Node> temp = model->getOrCreateSceneGraph( _map.get(), _map->getDBOptions(), 0L );
+            osg::ref_ptr<osg::Node> temp = model->getOrCreateSceneGraph( _map.get(), _map->getReadOptions(), 0L );
             if (temp.valid())
             {
               osg::NodePathList nodePaths = temp->getParentalNodePaths();
@@ -181,29 +181,28 @@ namespace
 
     Action* getDoubleClickAction(const ViewVector& views)
     {
-      if (_annotation.valid())
-      {
-        if (_annotation->getAnnotationData() && _annotation->getAnnotationData()->getViewpoint())
+        if (_annotation.valid())
         {
-          return new SetViewpointAction(osgEarth::Viewpoint(*_annotation->getAnnotationData()->getViewpoint()), views);
+            osgEarth::Viewpoint vp;
+            vp.setNode( _annotation.get() );
+            return new SetViewpointAction( vp, views );
         }
         else if (_map.valid())
         {
-          osg::Vec3d center = _annotation->getBound().center();
+            osg::Vec3d center = _annotation->getBound().center();
 
-          GeoPoint output;
-          output.fromWorld( _map->getSRS(), center );
-          //_map->worldPointToMapPoint(center, output);
+            GeoPoint output;
+            output.fromWorld( _map->getSRS(), center );
+            //_map->worldPointToMapPoint(center, output);
 
-          osgEarth::Viewpoint vp;
-          vp.focalPoint() = output;
-          vp.range() = 1e5;
-          vp.heading() = 0.0;
-          vp.pitch() = -90.0;
+            osgEarth::Viewpoint vp;
+            vp.focalPoint() = output;
+            vp.range() = 1e5;
+            vp.heading() = 0.0;
+            vp.pitch() = -90.0;
 
-          return new SetViewpointAction(vp, views);
+            return new SetViewpointAction(vp, views);
         }
-      }
 
       return 0L;
     }
@@ -534,11 +533,10 @@ void MapCatalogWidget::refreshAnnotations()
     _manager->getAnnotations(annos);
     for (AnnotationVector::const_iterator it = annos.begin(); it != annos.end(); ++it)
     {
-      AnnotationTreeItem* annoItem = new AnnotationTreeItem(*it, _map);
-      annoItem->setText(0, QString(((*it)->getAnnotationData() ? (*it)->getAnnotationData()->getName().c_str() : "Annotation")));
-			annoItem->setCheckState(0, (*it)->getNodeMask() != 0 ? Qt::Checked : Qt::Unchecked);
-
-			_annotationsItem->addChild(annoItem);
+        AnnotationTreeItem* annoItem = new AnnotationTreeItem(*it, _map);
+        annoItem->setText(0, QString( (*it)->getName().c_str() ) );
+        annoItem->setCheckState(0, (*it)->getNodeMask() != 0 ? Qt::Checked : Qt::Unchecked);
+        _annotationsItem->addChild(annoItem);
 
       if (_manager->isSelected(*it))
         annoItem->setSelected(true);
diff --git a/src/osgEarthQt/TerrainProfileGraph b/src/osgEarthQt/TerrainProfileGraph
index d0932eb..57ea1ca 100644
--- a/src/osgEarthQt/TerrainProfileGraph
+++ b/src/osgEarthQt/TerrainProfileGraph
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthQt/TerrainProfileGraph.cpp b/src/osgEarthQt/TerrainProfileGraph.cpp
index cee6bd9..61cd82c 100644
--- a/src/osgEarthQt/TerrainProfileGraph.cpp
+++ b/src/osgEarthQt/TerrainProfileGraph.cpp
@@ -1,5 +1,5 @@
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthQt/TerrainProfileWidget b/src/osgEarthQt/TerrainProfileWidget
index bce1bef..f8e017c 100644
--- a/src/osgEarthQt/TerrainProfileWidget
+++ b/src/osgEarthQt/TerrainProfileWidget
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthQt/TerrainProfileWidget.cpp b/src/osgEarthQt/TerrainProfileWidget.cpp
index a767d2f..765340e 100644
--- a/src/osgEarthQt/TerrainProfileWidget.cpp
+++ b/src/osgEarthQt/TerrainProfileWidget.cpp
@@ -1,5 +1,5 @@
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthQt/ViewWidget b/src/osgEarthQt/ViewWidget
index 6aeed19..aa1894c 100644
--- a/src/osgEarthQt/ViewWidget
+++ b/src/osgEarthQt/ViewWidget
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthQt/ViewWidget.cpp b/src/osgEarthQt/ViewWidget.cpp
index 700fd86..6a0bbb0 100644
--- a/src/osgEarthQt/ViewWidget.cpp
+++ b/src/osgEarthQt/ViewWidget.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthQt/ViewerWidget b/src/osgEarthQt/ViewerWidget
index f7125c3..1a64dde 100644
--- a/src/osgEarthQt/ViewerWidget
+++ b/src/osgEarthQt/ViewerWidget
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthQt/ViewerWidget.cpp b/src/osgEarthQt/ViewerWidget.cpp
index 8c36c2a..773d7b1 100644
--- a/src/osgEarthQt/ViewerWidget.cpp
+++ b/src/osgEarthQt/ViewerWidget.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
@@ -115,7 +115,7 @@ void ViewerWidget::createViewer()
     // creates a simple basic viewer.
     osgViewer::Viewer* viewer = new osgViewer::Viewer();
 
-    viewer->setThreadingModel(osgViewer::Viewer::DrawThreadPerContext);
+    viewer->setThreadingModel(osgViewer::Viewer::SingleThreaded);
     viewer->setCameraManipulator(new osgEarth::Util::EarthManipulator());
 
     viewer->addEventHandler(new osgViewer::StatsHandler());
diff --git a/src/osgEarthSilverLining/CMakeLists.txt b/src/osgEarthSilverLining/CMakeLists.txt
new file mode 100644
index 0000000..198c668
--- /dev/null
+++ b/src/osgEarthSilverLining/CMakeLists.txt
@@ -0,0 +1,71 @@
+IF(SILVERLINING_FOUND)
+
+IF   (DYNAMIC_OSGEARTH)
+    ADD_DEFINITIONS(-DOSGEARTHSILVERLINING_LIBRARY)
+ELSE (DYNAMIC_OSGEARTH)
+    ADD_DEFINITIONS(-DOSGEARTHSILVERLINING_LIBRARY_STATIC)
+ENDIF(DYNAMIC_OSGEARTH)
+
+SET(LIB_NAME osgEarthSilverLining)
+
+SET(HEADER_PATH ${OSGEARTH_SOURCE_DIR}/include/${LIB_NAME})
+
+SET(LIB_PUBLIC_HEADERS
+#   header files go here
+    Common
+    Export
+    SilverLiningOptions
+    SilverLiningNode
+    SilverLiningContext
+    SilverLiningSkyDrawable
+    SilverLiningCloudsDrawable
+    SilverLiningAPIWrapper
+    SilverLiningCallback
+	SilverLiningContextNode
+)
+
+ADD_LIBRARY(${LIB_NAME} ${OSGEARTH_USER_DEFINED_DYNAMIC_OR_STATIC}
+    ${LIB_PUBLIC_HEADERS}
+#  .cpp files go here
+    SilverLiningNode.cpp
+    SilverLiningContext.cpp
+    SilverLiningSkyDrawable.cpp
+    SilverLiningCloudsDrawable.cpp
+    SilverLiningAPIWrapper.cpp
+	SilverLiningContextNode.cpp
+)
+
+INCLUDE_DIRECTORIES( 
+    ${OSG_INCLUDE_DIR}
+    ${OSGEARTH_SOURCE_DIR}
+    ${SILVERLINING_INCLUDE_DIR}
+)
+
+LINK_EXTERNAL(
+	${LIB_NAME}
+	${TARGET_EXTERNAL_LIBRARIES}
+	${CMAKE_THREAD_LIBS_INIT} )
+
+LINK_INTERNAL(
+    ${LIB_NAME}
+    osgEarth
+    osgEarthUtil
+)
+
+LINK_WITH_VARIABLES(
+	${LIB_NAME} 
+	OSG_LIBRARY
+	OSGDB_LIBRARY
+	OPENTHREADS_LIBRARY
+    SILVERLINING_LIBRARY)
+
+LINK_CORELIB_DEFAULT(
+	${LIB_NAME}
+	${CMAKE_THREAD_LIBS_INIT} )
+
+# Add this project to the NodeKits solution folder
+set_property( TARGET ${LIB_NAME} PROPERTY FOLDER "NodeKits" )
+
+INCLUDE(ModuleInstall OPTIONAL)
+
+ENDIF(SILVERLINING_FOUND)
diff --git a/src/osgEarthSilverLining/Common b/src/osgEarthSilverLining/Common
new file mode 100644
index 0000000..6ea6daf
--- /dev/null
+++ b/src/osgEarthSilverLining/Common
@@ -0,0 +1,32 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+ * Copyright 2008-2014 Pelican Mapping
+ * http://osgearth.org
+ *
+ * osgEarth is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+#ifndef OSGEARTH_SILVERLINING_COMMON_H
+#define OSGEARTH_SILVERLINING_COMMON_H 1
+
+#include <osgEarth/Common>
+#include "Export"
+
+// common utilities
+//namespace osgEarth { namespace SilverLining
+//{
+//    
+//} } // namespace osgEarth::SilverLining
+
+#endif // OSGEARTH_SILVERLINING_COMMON_H
diff --git a/src/osgEarthSilverLining/Export b/src/osgEarthSilverLining/Export
new file mode 100644
index 0000000..1f0d78c
--- /dev/null
+++ b/src/osgEarthSilverLining/Export
@@ -0,0 +1,74 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+ * Copyright 2008-2014 Pelican Mapping
+ * http://osgearth.org
+ *
+ * osgEarth is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/* -*-c++-*- 
+ * Derived from osg/Export
+ */
+
+#ifndef OSGEARTH_SILVERLINING_EXPORT_H
+#define OSGEARTH_SILVERLINING_EXPORT_H 1
+
+// define USE_DEPRECATED_API is used to include in API which is being fazed out
+// if you can compile your apps with this turned off you are
+// well placed for compatibility with future versions.
+#define USE_DEPRECATED_API
+
+#if defined(_MSC_VER)
+    #pragma warning( disable : 4244 )
+    #pragma warning( disable : 4251 )
+    #pragma warning( disable : 4267 )
+    #pragma warning( disable : 4275 )
+    #pragma warning( disable : 4290 )
+    #pragma warning( disable : 4786 )
+    #pragma warning( disable : 4305 )
+    #pragma warning( disable : 4996 )
+#endif
+
+#if defined(_MSC_VER) || defined(__CYGWIN__) || defined(__MINGW32__) || defined( __BCPLUSPLUS__)  || defined( __MWERKS__)
+    #  if defined( OSGEARTHSILVERLINING_LIBRARY_STATIC )
+    #    define OSGEARTHSILVERLINING_EXPORT
+    #  elif defined( OSGEARTHSILVERLINING_LIBRARY )
+    #    define OSGEARTHSILVERLINING_EXPORT   __declspec(dllexport)
+    #  else
+    #    define OSGEARTHSILVERLINING_EXPORT   __declspec(dllimport)
+    #  endif
+#else
+    #  define OSGEARTHSILVERLINING_EXPORT
+#endif  
+
+// set up define for whether member templates are supported by VisualStudio compilers.
+#ifdef _MSC_VER
+# if (_MSC_VER >= 1300)
+#  define __STL_MEMBER_TEMPLATES
+# endif
+#endif
+
+/* Define NULL pointer value */
+
+#ifndef NULL
+    #ifdef  __cplusplus
+        #define NULL    0
+    #else
+        #define NULL    ((void *)0)
+    #endif
+#endif
+
+
+#endif // OSGEARTH_SILVERLINING_EXPORT_H
+
diff --git a/src/osgEarthSilverLining/SilverLiningAPIWrapper b/src/osgEarthSilverLining/SilverLiningAPIWrapper
new file mode 100644
index 0000000..e76f2fc
--- /dev/null
+++ b/src/osgEarthSilverLining/SilverLiningAPIWrapper
@@ -0,0 +1,202 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+ * Copyright 2016 Pelican Mapping
+ * http://osgearth.org
+ *
+ * osgEarth is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ */
+#ifndef OSGEARTH_SILVERLINING_API_WRAPPER
+#define OSGEARTH_SILVERLINING_API_WRAPPER 1
+
+#include "Common"
+#include <stdint.h> // for uintptr_t
+
+
+namespace osgEarth { namespace SilverLining
+{
+    class Atmosphere;
+
+    enum CloudTypes
+    {
+        CIRROCUMULUS,               /*!<  High planar cloud puffs */
+        CIRRUS_FIBRATUS,            /*!<  High, thicker and fibrous clouds that signal changing weather */
+        STRATUS,                    /*!<  Low clouds represented as a slab */
+        CUMULUS_MEDIOCRIS,          /*!<  Low, puffy clouds on fair days */
+        CUMULUS_CONGESTUS,          /*!<  Large cumulus clouds, built for performance. */
+        CUMULUS_CONGESTUS_HI_RES,   /*!<  Large cumulus clouds represented with high-resolution puff textures. */
+        CUMULONIMBUS_CAPPILATUS,    /*!<  Big storm clouds. */
+        STRATOCUMULUS,              /*!<  Low, dense, puffy clouds with some sun breaks between them. */
+        TOWERING_CUMULUS,           /*!<  Very large, tall cumulus clouds in the process of becoming a thunderstorm.*/
+        SANDSTORM,                  /*!<  A "haboob" cloud of dust intended to be positioned at ground level. */
+        NUM_CLOUD_TYPES             /*!<  Total number of cloud types. */
+    };
+
+    class OSGEARTHSILVERLINING_EXPORT CloudLayer
+    {
+    public:
+        enum PrecipitationTypes
+        {
+            NONE,
+            RAIN,
+            DRY_SNOW,
+            WET_SNOW,
+            SLEET,
+            NUM_PRECIP_TYPES
+        };
+
+    public:
+        CloudLayer(uintptr_t handle) : _handle(handle) { }
+
+        void SetEnabled(bool value);
+        bool GetEnabled() const;
+
+        void SetBaseWidth(double value);
+        double GetBaseWidth() const;
+
+        void SetBaseLength(double value);
+        double GetBaseLength() const;
+
+        void SetBaseAltitude(double value);
+        double GetBaseAltitude() const;
+
+        void SetThickness(double value);
+        double GetThickness() const;
+
+        void SetDensity(double value);
+        double GetDensity() const;
+
+        void SetLayerPosition(double east, double north);
+        void GetLayerPosition(double& east, double& north) const;
+
+        void SetIsInfinite(bool value);
+        bool GetIsInfinite() const;
+
+        void SetWind(double windEast, double windSouth);
+        void GetWind(double& windEast, double& windSouth) const;
+
+        void SetCloudWrapping(bool value);
+        bool GetCloudWrapping() const;
+
+        void SetFadeTowardEdges(bool value);
+        bool GetFadeTowardEdges() const;
+
+        void SetAlpha(double value);
+        double GetAlpha() const;
+
+        void SetCloudAnimationEffects(double, bool, int c=0, int d=0);
+        void GetCloudAnimationEffects(double&, bool&, int&, int&);
+
+        void SeedClouds(Atmosphere&);
+
+        uintptr_t _handle;
+    };
+
+    class OSGEARTHSILVERLINING_EXPORT CloudLayerFactory
+    {
+    public:
+        static CloudLayer Create(int kind);
+    };
+
+    class OSGEARTHSILVERLINING_EXPORT WindVolume
+    {
+    public:
+        WindVolume();
+        WindVolume(double windSpeed, double direction);
+
+        void SetMinAltitude(double metersMSL);
+        double GetMinAltitude() const;
+        void SetMaxAltitude(double metersMSL);
+        double GetMaxAltitude() const;
+        void SetWindSpeed(double metersPerSecond);
+        double GetWindSpeed() const;
+        void SetDirection(double degreesFromNorth);
+        double GetDirection() const;
+
+    private:
+        double _minAltitude;
+        double _maxAltitude;
+        double _windSpeed;
+        double _direction;
+    };
+
+    class OSGEARTHSILVERLINING_EXPORT AtmosphericConditions
+    {
+    public:
+        int AddCloudLayer(class CloudLayer&);
+        bool RemoveCloudLayer(int layerHandle);
+        void RemoveAllCloudLayers();
+
+        void SetVisibility(double vis);
+        double GetVisibility() const;
+
+        void SetTurbidity(double turb);
+        double GetTurbidity() const;
+
+        void SetLightPollution(double wattsPerSqm);
+        double GetLightPollution() const;
+
+        void SetPrecipitation(int type, double rate);
+
+        int SetWind(double metersPerSecond, double degreesFromNorth);
+        int SetWind(const WindVolume& windVolume);
+        bool RemoveWindVolume(int windVolumeHandle);
+        void ClearWindVolumes();
+
+        enum ConditionPresets
+        {
+            FAIR = 0,
+            PARTLY_CLOUDY,
+            MOSTLY_CLOUDY,
+            OVERCAST
+        };
+        void SetPresetConditions(ConditionPresets preset, Atmosphere& atm);
+
+        void EnableTimePassage(bool enabled, long relightFrequencyMS);
+
+    public:
+        AtmosphericConditions(uintptr_t handle) : _handle(handle) { }
+        uintptr_t _handle;
+    };
+
+    class OSGEARTHSILVERLINING_EXPORT Atmosphere
+    {
+    public:
+        void EnableLensFlare(bool value);
+        bool GetLensFlareEnabled() const;
+
+        enum SkyModel
+        {
+            PREETHAM,
+            HOSEK_WILKIE
+        };
+
+        void SetSkyModel(SkyModel skyModel);
+        SkyModel GetSkyModel() const;
+
+        void SetGamma(double gamma);
+        double GetGamma() const;
+
+        void SetInfraRedMode(bool infraRed);
+        bool GetInfraRedMode() const;
+
+        AtmosphericConditions GetConditions() const;
+
+    public:
+        Atmosphere(uintptr_t handle) : _handle(handle) { }
+        uintptr_t _handle;
+    };
+
+} } // namespace osgEarth::SilverLining
+
+#endif // OSGEARTH_SILVERLINING_API_WRAPPER
diff --git a/src/osgEarthSilverLining/SilverLiningAPIWrapper.cpp b/src/osgEarthSilverLining/SilverLiningAPIWrapper.cpp
new file mode 100644
index 0000000..87cec67
--- /dev/null
+++ b/src/osgEarthSilverLining/SilverLiningAPIWrapper.cpp
@@ -0,0 +1,128 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+ * Copyright 2016 Pelican Mapping
+ * http://osgearth.org
+ *
+ * osgEarth is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ */
+#include "SilverLiningAPIWrapper"
+#include <SilverLining.h>
+
+#define LC "[SilverLiningAPI] "
+
+using namespace osgEarth::SilverLining;
+
+#define SETGET_EXPLICIT(NS, SETTER, GETTER, TYPE) \
+    void NS :: SETTER (TYPE value) { HANDLE-> SETTER (value); } \
+    TYPE NS :: GETTER () const     { return HANDLE -> GETTER (); }
+
+#define SETGET(NS, FUNC, TYPE) \
+    SETGET_EXPLICIT(NS, Set##FUNC, Get##FUNC, TYPE)
+
+//................................
+#undef  HANDLE
+#define HANDLE ((::SilverLining::Atmosphere*)_handle)
+
+SETGET_EXPLICIT(Atmosphere, EnableLensFlare, GetLensFlareEnabled, bool);
+void Atmosphere::SetSkyModel(SkyModel skyModel) { HANDLE->SetSkyModel(static_cast< ::SkyModel >(skyModel)); }
+Atmosphere::SkyModel Atmosphere::GetSkyModel() const { return static_cast<SkyModel>(HANDLE->GetSkyModel()); }
+AtmosphericConditions Atmosphere::GetConditions() const { return AtmosphericConditions((uintptr_t)HANDLE->GetConditions()); }
+SETGET(Atmosphere, Gamma, double);
+SETGET(Atmosphere, InfraRedMode, bool);
+
+//................................
+#undef  HANDLE
+#define HANDLE ((::SilverLining::AtmosphericConditions*)_handle)
+
+SETGET(AtmosphericConditions, Visibility, double);
+SETGET(AtmosphericConditions, Turbidity, double);
+SETGET(AtmosphericConditions, LightPollution, double);
+
+void AtmosphericConditions::SetPrecipitation(int type, double rate) {
+    HANDLE->SetPrecipitation((::CloudLayer::PrecipitationTypes)type, rate);
+}
+
+int AtmosphericConditions::AddCloudLayer(CloudLayer& layer) { return HANDLE->AddCloudLayer((::SilverLining::CloudLayer*)layer._handle); }
+bool AtmosphericConditions::RemoveCloudLayer(int layerHandle) { return HANDLE->RemoveCloudLayer(layerHandle); }
+void AtmosphericConditions::RemoveAllCloudLayers() { HANDLE->RemoveAllCloudLayers(); }
+
+int AtmosphericConditions::SetWind(const WindVolume& windVolume)
+{
+    ::SilverLining::WindVolume slVolume;
+    slVolume.SetMinAltitude(windVolume.GetMinAltitude());
+    slVolume.SetMaxAltitude(windVolume.GetMaxAltitude());
+    slVolume.SetWindSpeed(windVolume.GetWindSpeed());
+    slVolume.SetDirection(windVolume.GetDirection());
+    return HANDLE->SetWind(slVolume);
+}
+int AtmosphericConditions::SetWind(double metersPerSecond, double degreesFromNorth) { return SetWind(WindVolume(metersPerSecond, degreesFromNorth)); }
+bool AtmosphericConditions::RemoveWindVolume(int layerHandle) { return HANDLE->RemoveWindVolume(layerHandle); }
+void AtmosphericConditions::ClearWindVolumes() { HANDLE->ClearWindVolumes(); }
+void AtmosphericConditions::SetPresetConditions(ConditionPresets preset, Atmosphere& atm) { HANDLE->SetPresetConditions(static_cast< ::SilverLining::AtmosphericConditions::ConditionPresets >(preset), *(::SilverLining::Atmosphere*)atm._handle); }
+void AtmosphericConditions::EnableTimePassage(bool enabled, long relightFrequencyMS) { HANDLE->EnableTimePassage(enabled, relightFrequencyMS); }
+
+//................................
+WindVolume::WindVolume() :
+_minAltitude( 0.0 ),
+_maxAltitude( 100000.0 ),
+_windSpeed  ( 0.0 ),
+_direction  ( 0.0 )
+{
+}
+WindVolume::WindVolume(double windSpeed, double direction) :
+_minAltitude( 0.0 ),
+_maxAltitude( 100000.0 ),
+_windSpeed  ( windSpeed ),
+_direction  ( direction )
+{
+}
+void WindVolume::SetMinAltitude(double metersMSL) { _minAltitude = metersMSL; }
+double WindVolume::GetMinAltitude() const { return _minAltitude; }
+void WindVolume::SetMaxAltitude(double metersMSL) { _maxAltitude = metersMSL; }
+double WindVolume::GetMaxAltitude() const { return _maxAltitude; }
+void WindVolume::SetWindSpeed(double metersPerSecond) { _windSpeed = metersPerSecond; }
+double WindVolume::GetWindSpeed() const { return _windSpeed; }
+void WindVolume::SetDirection(double degreesFromNorth) { _direction = degreesFromNorth; }
+double WindVolume::GetDirection() const { return _direction; }
+
+//................................
+#undef  HANDLE
+#define HANDLE ((::SilverLining::CloudLayer*)_handle)
+
+SETGET(CloudLayer, Enabled, bool)
+SETGET(CloudLayer, BaseWidth, double)
+SETGET(CloudLayer, BaseLength, double)
+SETGET(CloudLayer, BaseAltitude, double)
+SETGET(CloudLayer, Thickness, double)
+SETGET(CloudLayer, Density, double)
+SETGET(CloudLayer, IsInfinite, bool)
+SETGET(CloudLayer, CloudWrapping, bool)
+SETGET(CloudLayer, FadeTowardEdges, bool)
+SETGET(CloudLayer, Alpha, double)
+
+void CloudLayer::SetLayerPosition(double e, double n) { HANDLE->SetLayerPosition(e, n); }
+void CloudLayer::GetLayerPosition(double& e, double& n) const { HANDLE->GetLayerPosition(e, n); }
+
+void CloudLayer::SetWind(double windEast, double windSouth) { HANDLE->SetWind(windEast, windSouth); }
+void CloudLayer::GetWind(double& windEast, double& windSouth) const { HANDLE->GetWind(windEast, windSouth); }
+
+void CloudLayer::SetCloudAnimationEffects(double a, bool b, int c, int d) { HANDLE->SetCloudAnimationEffects(a, b, c, d); }
+void CloudLayer::GetCloudAnimationEffects(double& a, bool& b, int& c, int& d) { HANDLE->SetCloudAnimationEffects(a, b, c, d); }
+
+void CloudLayer::SeedClouds(Atmosphere& a) { HANDLE->SeedClouds(*(::SilverLining::Atmosphere*)a._handle); }
+
+//................................
+CloudLayer CloudLayerFactory::Create(int kind) {
+    return CloudLayer((uintptr_t)::SilverLining::CloudLayerFactory::Create((::CloudTypes)kind));
+}
diff --git a/src/osgEarthSilverLining/SilverLiningCallback b/src/osgEarthSilverLining/SilverLiningCallback
new file mode 100644
index 0000000..93b171d
--- /dev/null
+++ b/src/osgEarthSilverLining/SilverLiningCallback
@@ -0,0 +1,48 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+ * Copyright 2016 Pelican Mapping
+ * http://osgearth.org
+ *
+ * osgEarth is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ */
+#ifndef OSGEARTH_SILVERLINING_CALLBACK_H
+#define OSGEARTH_SILVERLINING_CALLBACK_H 1
+
+#include "Common"
+#include "SilverLiningAPIWrapper"
+
+namespace osgEarth { namespace SilverLining
+{
+    /**
+     * A callback that lets you execute code at initialization
+     */
+    class OSGEARTHSILVERLINING_EXPORT Callback : public osg::Referenced
+    {
+    public:
+        virtual void onInitialize(Atmosphere& atmosphere) { }
+
+        virtual void onDrawSky(Atmosphere& atmosphere) { }
+
+        virtual void onDrawClouds(Atmosphere& atmosphere) { }
+
+        /**
+         * Returns elapsed milliseconds from epoch for clouds animation.
+         * Use a return value of 0 to use an automatic real-time synchronization.
+         */
+        virtual unsigned long getMilliseconds() const { return 0; }
+    };
+
+} } // namespace osgEarth::SilverLining
+
+#endif // OSGEARTH_SILVERLINING_CALLBACK_H
diff --git a/src/osgEarthSilverLining/SilverLiningCloudsDrawable b/src/osgEarthSilverLining/SilverLiningCloudsDrawable
new file mode 100644
index 0000000..07daadb
--- /dev/null
+++ b/src/osgEarthSilverLining/SilverLiningCloudsDrawable
@@ -0,0 +1,66 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+ * Copyright 2016 Pelican Mapping
+ * http://osgearth.org
+ *
+ * osgEarth is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ */
+#include <osg/Drawable>
+#include <osg/RenderInfo>
+#include <osg/Version>
+#include <osgEarth/NativeProgramAdapter>
+#include <vector>
+#include <map>
+
+namespace osgEarth { namespace SilverLining
+{
+    class SilverLiningContext;
+	class SilverLiningContextNode;
+
+    /**
+     * Custom drawable for rendering the SilverLining clouds
+     */
+    class CloudsDrawable : public osg::Drawable
+    {
+    public:
+        CloudsDrawable(SilverLiningContextNode* contexNode =0L);
+        META_Object(SilverLining, CloudsDrawable);
+
+		/* Sets whether to draw this item */
+		void setDraw(bool draw);
+     
+    public: // osg::Drawable
+
+        // custom draw (called with an active GC)
+        void drawImplementation(osg::RenderInfo& ri) const;
+        
+        // custom bounds computation
+#if OSG_VERSION_GREATER_THAN(3,3,1)
+        osg::BoundingBox computeBoundingBox() const;
+#else
+        osg::BoundingBox computeBound() const;
+#endif
+
+    protected:
+        virtual ~CloudsDrawable() { }
+
+        osg::observer_ptr<SilverLiningContext> _SL;
+		SilverLiningContextNode* _contextNode;
+
+        mutable osg::buffered_object<osgEarth::NativeProgramAdapterCollection> _adapters;
+        
+        CloudsDrawable(const CloudsDrawable& copy, const osg::CopyOp& op=osg::CopyOp::SHALLOW_COPY) { }
+    };
+
+} } // namespace osgEarth::SilverLining
diff --git a/src/osgEarthSilverLining/SilverLiningCloudsDrawable.cpp b/src/osgEarthSilverLining/SilverLiningCloudsDrawable.cpp
new file mode 100644
index 0000000..06f89b8
--- /dev/null
+++ b/src/osgEarthSilverLining/SilverLiningCloudsDrawable.cpp
@@ -0,0 +1,103 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+ * Copyright 2016 Pelican Mapping
+ * http://osgearth.org
+ *
+ * osgEarth is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ */
+#include <SilverLining.h>
+#include "SilverLiningCloudsDrawable"
+#include "SilverLiningContext"
+#include "SilverLiningContextNode"
+#include <osgEarth/SpatialReference>
+
+#undef  LC
+#define LC "[SilverLining:SkyDrawable] "
+
+using namespace osgEarth::SilverLining;
+
+
+CloudsDrawable::CloudsDrawable(SilverLiningContextNode* contexNode) :
+_SL(contexNode->getSLContext()),
+_contextNode(contexNode)
+{
+    // call this to ensure draw() gets called every frame.
+    setSupportsDisplayList( false );
+    
+    // not MT-safe (camera updates, etc)
+    this->setDataVariance(osg::Object::DYNAMIC);
+    
+    setName("SilverLining::CloudsDrawable");
+}
+
+void
+CloudsDrawable::drawImplementation(osg::RenderInfo& renderInfo) const
+{
+	osg::Camera* camera = renderInfo.getCurrentCamera();
+#ifndef SL_USE_CULL_MASK
+	if(_contextNode->getTargetCamera() == camera)
+#endif
+	{
+	if ( _SL->ready())
+	{
+	    osg::State* state = renderInfo.getState();
+
+        // adapt the SL shaders so they can accept OSG uniforms:
+        osgEarth::NativeProgramAdapterCollection& adapters = _adapters[ state->getContextID() ]; // thread safe.
+        if ( adapters.empty() )
+        {
+            adapters.push_back( new osgEarth::NativeProgramAdapter(state, _SL->getAtmosphere()->GetSkyShader()) );
+            adapters.push_back( new osgEarth::NativeProgramAdapter(state, _SL->getAtmosphere()->GetBillboardShader()) );
+            adapters.push_back( new osgEarth::NativeProgramAdapter(state, _SL->getAtmosphere()->GetStarShader()) );
+            adapters.push_back( new osgEarth::NativeProgramAdapter(state, _SL->getAtmosphere()->GetPrecipitationShader()) );
+            //adapters.push_back(new osgEarth::NativeProgramAdapter(state, _SL->getAtmosphere()->GetAtmosphericLimbShader()) );
+
+            SL_VECTOR(unsigned) handles = _SL->getAtmosphere()->GetActivePlanarCloudShaders();
+            for(int i=0; i<handles.size(); ++i)          
+                adapters.push_back( new osgEarth::NativeProgramAdapter(state, handles[i]) );
+        }
+        adapters.apply( state );
+
+        // invoke the user callback if it exists
+        if (_SL->getCallback())
+            _SL->getCallback()->onDrawClouds(_SL->getAtmosphereWrapper());
+
+        renderInfo.getState()->disableAllVertexArrays();
+        _SL->getAtmosphere()->DrawObjects( true, true, true );
+
+        // Restore the GL state to where it was before.
+        state->dirtyAllVertexArrays();
+        state->dirtyAllAttributes();
+
+        state->apply();
+    }
+	}
+}
+
+osg::BoundingBox
+#if OSG_VERSION_GREATER_THAN(3,3,1)
+CloudsDrawable::computeBoundingBox() const
+#else
+CloudsDrawable::computeBound() const
+#endif
+{
+    osg::BoundingBox cloudBoundBox;
+    if ( !_SL->ready() )
+        return cloudBoundBox;
+    
+    double minX, minY, minZ, maxX, maxY, maxZ;
+    _SL->getAtmosphere()->GetCloudBounds( minX, minY, minZ, maxX, maxY, maxZ );
+    cloudBoundBox.set( osg::Vec3d(minX, minY, minZ), osg::Vec3d(maxX, maxY, maxZ) );
+    return cloudBoundBox;
+}
diff --git a/src/osgEarthSilverLining/SilverLiningContext b/src/osgEarthSilverLining/SilverLiningContext
new file mode 100644
index 0000000..b63cf42
--- /dev/null
+++ b/src/osgEarthSilverLining/SilverLiningContext
@@ -0,0 +1,123 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+ * Copyright 2016 Pelican Mapping
+ * http://osgearth.org
+ *
+ * osgEarth is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ */
+#include "Common"
+#include "SilverLiningOptions"
+#include "SilverLiningAPIWrapper"
+#include "SilverLiningCallback"
+#include <osg/Referenced>
+#include <osg/Light>
+#include <osg/Camera>
+#include <osgEarth/ThreadingUtils>
+
+namespace SilverLining {
+    class Atmosphere;
+    class CloudLayer;
+    class MillisecondTimer;
+}
+namespace osgEarth {
+    class SpatialReference;
+}
+
+namespace osgEarth { namespace SilverLining
+{
+    /**
+     * Contains all the SilverLining SDK pointers.
+     */
+    class SilverLiningContext : public osg::Referenced
+    {
+    public:
+        SilverLiningContext(const SilverLiningOptions& options);
+
+        /** Sets the light source that will represent the sun */
+        void setLight(osg::Light* light);
+
+        /** Sets the spatial reference system of the map */
+        void setSRS(const SpatialReference* srs);
+
+        /** Sets the minimum ambient lighting value */
+        void setMinimumAmbient(const osg::Vec4f& value);
+
+        /** Installs a user callback for SL initialization */
+        void setCallback(Callback*);
+        Callback* getCallback() const { return _callback.get(); }
+
+    public: // accessors
+
+        bool ready() const { return _initAttempted && !_initFailed; }
+
+        ::SilverLining::Atmosphere* getAtmosphere() { return _atmosphere; }
+
+        Atmosphere& getAtmosphereWrapper() { return *_atmosphereWrapper; }
+
+        /** Spatial reference of the map */
+        const SpatialReference* getSRS() const { return _srs.get(); }
+
+        void setSkyBoxSize(double size) { _skyBoxSize = size; }
+        double getSkyBoxSize() const { return _skyBoxSize; }
+
+        void initialize(osg::RenderInfo& renderInfo);
+
+        void updateLocation();
+
+        void updateLight();
+
+        /** Set/get the cached camers. NOT THREAD/MULTI-CAM SAFE. */
+        /** TODO */
+        void setCamera(osg::Camera* camera) { _camera = camera; }
+        osg::Camera* getCamera() { return _camera.get(); }
+
+        void setCameraPosition(const osg::Vec3d& pos) { _cameraPos = pos; }
+        const osg::Vec3d& getCameraPosition() const { return _cameraPos; }
+
+    protected:
+
+        virtual ~SilverLiningContext();
+
+    private:
+
+        void setupClouds();
+
+    private:
+        ::SilverLining::Atmosphere* _atmosphere;
+
+        double _skyBoxSize;
+
+        osg::observer_ptr<osg::Light>                  _light;
+        osg::ref_ptr<const osgEarth::SpatialReference> _srs;
+
+        bool                       _initAttempted;
+        bool                       _initFailed;
+        osgEarth::Threading::Mutex _initMutex;
+
+        double _maxAmbientLightingAlt;
+
+        osg::observer_ptr<osg::Camera> _camera;
+        osg::Vec3d                     _cameraPos; // eye point
+        osg::Vec4f                     _minAmbient;
+
+        SilverLiningOptions _options;
+
+        osg::ref_ptr<Callback> _callback;
+
+        Atmosphere* _atmosphereWrapper;
+
+        ::SilverLining::MillisecondTimer* _msTimer;
+    };
+
+} } // namespace osgEarth::SilverLining
diff --git a/src/osgEarthSilverLining/SilverLiningContext.cpp b/src/osgEarthSilverLining/SilverLiningContext.cpp
new file mode 100644
index 0000000..1258284
--- /dev/null
+++ b/src/osgEarthSilverLining/SilverLiningContext.cpp
@@ -0,0 +1,295 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+ * Copyright 2016 Pelican Mapping
+ * http://osgearth.org
+ *
+ * osgEarth is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ */
+#include <SilverLining.h> // SilverLining SDK
+#include "SilverLiningContext"
+#include "SilverLiningNode"
+#include <osg/Light>
+#include <osgDB/FileNameUtils>
+#include <osgEarth/SpatialReference>
+#include <cstdlib>
+
+#define LC "[SilverLiningContext] "
+
+using namespace osgEarth::SilverLining;
+
+
+/**
+ * Adapter that converts the return value of osgEarth::SilverLining::Callback::getMilliseconds()
+ * into a usable value for SilverLining using the SilverLining MillisecondTimer callback.
+ */
+class MillisecondTimerAdapter : public ::SilverLining::MillisecondTimer
+{
+public:
+    MillisecondTimerAdapter(SilverLiningContext* context) :
+    _context(context),
+    _defaultTimer(new ::SilverLining::MillisecondTimer)
+    {
+    }
+
+    virtual ~MillisecondTimerAdapter()
+    {
+        delete _defaultTimer;
+    }
+
+    virtual unsigned long SILVERLINING_API GetMilliseconds() const
+    {
+        osg::ref_ptr<SilverLiningContext> context;
+        unsigned long milliseconds = 0;
+        if (_context.lock(context))
+        {
+            osg::ref_ptr<Callback> callback = context->getCallback();
+            if (callback.valid())
+                milliseconds = callback->getMilliseconds();
+        }
+
+        // As per documentation, use the default SilverLining timer instead of returning 0
+        if (milliseconds != 0)
+            return milliseconds;
+        return _defaultTimer->GetMilliseconds();
+    }
+
+private:
+    osg::observer_ptr<SilverLiningContext> _context;
+    ::SilverLining::MillisecondTimer* _defaultTimer;
+};
+
+SilverLiningContext::SilverLiningContext(const SilverLiningOptions& options) :
+_options              ( options ),
+_initAttempted        ( false ),
+_initFailed           ( false ),
+_maxAmbientLightingAlt( -1.0 ),
+_atmosphere           ( 0L ),
+_minAmbient           ( 0,0,0,0 )
+{
+    // Create the millisecond timer that we'll use to control time
+    _msTimer = new MillisecondTimerAdapter(this);
+
+    // Create a SL atmosphere (the main SL object).
+    _atmosphere = new ::SilverLining::Atmosphere(
+        options.user()->c_str(),
+        options.licenseCode()->c_str() );
+
+    _atmosphereWrapper = new Atmosphere((uintptr_t)_atmosphere);
+}
+
+SilverLiningContext::~SilverLiningContext()
+{
+    delete _atmosphereWrapper;
+    delete _atmosphere;
+    delete _msTimer;
+
+    OE_INFO << LC << "Destroyed\n";
+}
+
+void
+SilverLiningContext::setCallback(Callback* cb)
+{
+    _callback = cb;
+}
+
+void
+SilverLiningContext::setLight(osg::Light* light)
+{
+    _light = light;
+}
+
+void
+SilverLiningContext::setSRS(const osgEarth::SpatialReference* srs)
+{
+    _srs = srs;
+}
+
+void
+SilverLiningContext::setMinimumAmbient(const osg::Vec4f& value)
+{
+    _minAmbient = value;
+}
+
+void
+SilverLiningContext::initialize(osg::RenderInfo& renderInfo)
+{
+    if ( !_initAttempted && !_initFailed )
+    {
+        // lock/double-check:
+        Threading::ScopedMutexLock excl(_initMutex);
+        if ( !_initAttempted && !_initFailed )
+        {
+            _initAttempted = true;
+
+            // constant random seed ensures consistent clouds across windows
+            // TODO: replace this with something else since this is global! -gw
+            ::srand(1234);
+
+            std::string resourcePath = _options.resourcePath().get();
+            if (resourcePath.empty() && ::getenv("SILVERLINING_PATH"))
+            {
+                resourcePath = osgDB::concatPaths(::getenv("SILVERLINING_PATH"), "Resources");
+            }
+
+            int result = _atmosphere->Initialize(
+                ::SilverLining::Atmosphere::OPENGL,
+                resourcePath.c_str(),
+                true,
+                0 );
+
+            if ( result != ::SilverLining::Atmosphere::E_NOERROR )
+            {
+                _initFailed = true;
+                OE_WARN << LC << "SilverLining failed to initialize: " << result << std::endl;
+            }
+            else
+            {
+                OE_INFO << LC << "SilverLining initialized OK!" << std::endl;
+
+                // Defaults for a projected terrain. ECEF terrain vectors are set
+                // in updateLocation().
+                _atmosphere->SetUpVector( 0.0, 0.0, 1.0 );
+                _atmosphere->SetRightVector( 1.0, 0.0, 0.0 );
+
+                // Configure the timer used for animations
+                _atmosphere->GetConditions()->SetMillisecondTimer(_msTimer);
+
+#if 0 // todo: review this
+                _maxAmbientLightingAlt =
+                    _atmosphere->GetConfigOptionDouble("atmosphere-height");
+#endif
+                if ( _options.drawClouds() == true )
+                {
+                    OE_INFO << LC << "Initializing clouds\n";
+                    setupClouds();
+                }
+
+                // user callback for initialization
+                if (_callback.valid())
+                {
+                    _callback->onInitialize( *_atmosphereWrapper );
+                }
+            }
+        }
+    }
+}
+
+void
+SilverLiningContext::setupClouds()
+{
+    ::SilverLining::CloudLayer* clouds = ::SilverLining::CloudLayerFactory::Create( ::CUMULUS_CONGESTUS );
+    clouds->SetIsInfinite( true );
+    clouds->SetFadeTowardEdges(true);
+    clouds->SetBaseAltitude( 2000 );
+    clouds->SetThickness( 200 );
+    clouds->SetBaseLength( 100000 );
+    clouds->SetBaseWidth( 100000 );
+    clouds->SetDensity( 0.6 );
+    clouds->SetAlpha( 0.8 );
+
+    clouds->SeedClouds( *_atmosphere );
+    clouds->GenerateShadowMaps( false );
+
+    clouds->SetLayerPosition(0, 0);
+
+    _atmosphere->GetConditions()->AddCloudLayer( clouds );
+}
+
+void
+SilverLiningContext::updateLight()
+{
+    if ( !ready() || !_light.valid() || !_srs.valid() )
+        return;
+
+    float ra, ga, ba, rd, gd, bd, x, y, z;
+
+    // Clamp the camera's altitude while fetching the colors so the
+    // lighting's ambient component doesn't fade to black at high altitude.
+    ::SilverLining::Location savedLoc = _atmosphere->GetConditions()->GetLocation();
+    ::SilverLining::Location clampedLoc = savedLoc;
+    if ( _maxAmbientLightingAlt > 0.0 )
+    {
+        clampedLoc.SetAltitude( std::min(clampedLoc.GetAltitude(), _maxAmbientLightingAlt) );
+        _atmosphere->GetConditions()->SetLocation( clampedLoc );
+    }
+
+    _atmosphere->GetAmbientColor( &ra, &ga, &ba );
+    _atmosphere->GetSunColor( &rd, &gd, &bd );
+
+    // Restore the actual altitude.
+    if ( _maxAmbientLightingAlt > 0.0 )
+    {
+        _atmosphere->GetConditions()->SetLocation( savedLoc );
+    }
+
+    if ( _srs->isGeographic() )
+    {
+        _atmosphere->GetSunPositionGeographic( &x, &y, &z );
+    }
+    else
+    {
+        _atmosphere->GetSunPosition(&x, &y, &z);
+    }
+
+    osg::Vec3 direction(x, y, z);
+    direction.normalize();
+
+    osg::Vec4 ambient(
+        osg::clampAbove(ra, _minAmbient.r()),
+        osg::clampAbove(ba, _minAmbient.g()),
+        osg::clampAbove(ga, _minAmbient.b()),
+        1.0);
+
+    _light->setAmbient( ambient );
+    _light->setDiffuse( osg::Vec4(rd, gd, bd, 1.0f) );
+    _light->setPosition( osg::Vec4(direction, 0.0f) ); //w=0 means "at infinity"
+}
+
+void
+SilverLiningContext::updateLocation()
+{
+    if ( !ready() || !_srs.valid() )
+        return;
+
+    if ( _srs->isGeographic() )
+    {
+        // Get new local orientation
+        osg::Vec3d up = _cameraPos;
+        up.normalize();
+        osg::Vec3d north = osg::Vec3d(0, 1, 0);
+        osg::Vec3d east = north ^ up;
+
+        // Check for edge case of north or south pole
+        if (east.length2() == 0)
+        {
+            east = osg::Vec3d(1, 0, 0);
+        }
+
+        east.normalize();
+
+        _atmosphere->SetUpVector(up.x(), up.y(), up.z());
+        _atmosphere->SetRightVector(east.x(), east.y(), east.z());
+
+        // Get new lat / lon / altitude
+        osg::Vec3d latLonAlt;
+        _srs->transformFromWorld(_cameraPos, latLonAlt);
+
+        ::SilverLining::Location loc;
+        loc.SetAltitude ( latLonAlt.z() );
+        loc.SetLongitude( latLonAlt.x() ); //osg::DegreesToRadians(latLonAlt.x()) );
+        loc.SetLatitude ( latLonAlt.y() ); //osg::DegreesToRadians(latLonAlt.y()) );
+
+        _atmosphere->GetConditions()->SetLocation( loc );
+    }
+}
diff --git a/src/osgEarthSilverLining/SilverLiningContextNode b/src/osgEarthSilverLining/SilverLiningContextNode
new file mode 100644
index 0000000..e5a79ae
--- /dev/null
+++ b/src/osgEarthSilverLining/SilverLiningContextNode
@@ -0,0 +1,80 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+ * Copyright 2016 Pelican Mapping
+ * http://osgearth.org
+ *
+ * osgEarth is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+#include "Common"
+#include "SilverLiningOptions"
+#include "SilverLiningCallback"
+#include "SilverLiningAPIWrapper"
+#include <osgEarthUtil/Sky>
+#include <osgEarth/Map>
+#include <osgEarth/PhongLightingEffect>
+#include <osg/Light>
+#include <osg/LightSource>
+
+namespace osgEarth { namespace SilverLining
+{
+    class SilverLiningContext;
+    class SilverLiningNode;
+
+    /**
+     * Node that roots the silverlining adapter.
+     */
+    class SilverLiningContextNode : public osg::Group
+    {
+    public:
+        SilverLiningContextNode(
+            SilverLiningNode*          node,
+            osg::Camera*               camera,
+            osg::Light*                light,
+            const osgEarth::SpatialReference*    mapSRS,
+            const SilverLiningOptions& options,
+            Callback*                  callback =0L);
+
+    public: 
+        void attach(osg::View* view, int lightNum);
+
+        // callbacks from SilverLiningNode.
+        void onSetDateTime();
+        void onSetMinimumAmbient();
+        //get target camera
+        osg::Camera* getTargetCamera() const {return _camera;}
+        osg::ref_ptr<osg::Geode> getSLGeode() {return _geode;}
+        SilverLiningContext* getSLContext() {return _SL.get();}
+
+        osg::StateSet* getCloudsStateSet() const { return _cloudsDrawable.valid() ? _cloudsDrawable->getStateSet() : 0L; }
+        osg::StateSet* getSkyStateSet() const { return _skyDrawable.valid() ? _skyDrawable->getStateSet() : 0L; }
+
+    public: // osg::Node
+
+        void traverse(osg::NodeVisitor&);
+
+    protected:
+        virtual ~SilverLiningContextNode();
+
+        osg::ref_ptr<SilverLiningContext> _SL;
+        osg::ref_ptr<osg::Geode> _geode;
+        osg::ref_ptr<osg::Drawable> _skyDrawable;
+        osg::ref_ptr<osg::Drawable> _cloudsDrawable;
+        SilverLiningNode* _silverLiningNode;
+        double _lastAltitude;
+        const SilverLiningOptions _options;
+        osg::Camera* _camera;
+    };
+
+} } // namespace osgEarth::SilverLining
\ No newline at end of file
diff --git a/src/osgEarthSilverLining/SilverLiningContextNode.cpp b/src/osgEarthSilverLining/SilverLiningContextNode.cpp
new file mode 100644
index 0000000..57c6c8a
--- /dev/null
+++ b/src/osgEarthSilverLining/SilverLiningContextNode.cpp
@@ -0,0 +1,158 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+ * Copyright 2016 Pelican Mapping
+ * http://osgearth.org
+ *
+ * osgEarth is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ */
+#include <SilverLining.h>
+
+#include "SilverLiningContextNode"
+#include "SilverLiningNode"
+#include "SilverLiningContext"
+#include "SilverLiningSkyDrawable"
+#include "SilverLiningCloudsDrawable"
+
+#include <osg/Light>
+#include <osg/LightSource>
+#include <osgEarth/CullingUtils>
+
+#undef  LC
+#define LC "[SilverLiningContextNode] "
+
+using namespace osgEarth::SilverLining;
+
+SilverLiningContextNode::SilverLiningContextNode(SilverLiningNode* node,
+								   osg::Camera*               camera,
+                                   osg::Light*                light,
+	                               const osgEarth::SpatialReference*    mapSRS,
+                                   const SilverLiningOptions& options,
+                                   Callback*                  callback) :
+_silverLiningNode (node),
+_camera           (camera),
+_options          (options),
+_lastAltitude(DBL_MAX)
+{
+    // The main silver lining data:
+    _SL = new SilverLiningContext( options );
+    _SL->setLight( light);
+    _SL->setSRS  ( mapSRS );
+    _SL->setCallback( callback );
+    _SL->setMinimumAmbient( node->getMinimumAmbient() );
+
+    // Geode to hold each of the SL drawables:
+    _geode = new osg::Geode();
+    _geode->setCullingActive( false );
+
+    // Draws the sky before everything else
+    _skyDrawable = new SkyDrawable(this);
+    _skyDrawable->getOrCreateStateSet()->setRenderBinDetails( -99, "RenderBin" );
+    _geode->addDrawable(_skyDrawable.get());
+
+    // Clouds draw after everything else
+    _cloudsDrawable = new CloudsDrawable(this);
+    _cloudsDrawable->getOrCreateStateSet()->setRenderBinDetails( 99, "DepthSortedBin" );
+    _geode->addDrawable(_cloudsDrawable.get());
+
+    // SL requires an update pass.
+    ADJUST_UPDATE_TRAV_COUNT(this, +1);
+
+    // initialize date/time
+    onSetDateTime();
+}
+
+
+SilverLiningContextNode::~SilverLiningContextNode()
+{
+
+}
+
+void
+SilverLiningContextNode::onSetDateTime()
+{
+    // set the SL local time to UTC/epoch.
+    ::SilverLining::LocalTime utcTime;
+    utcTime.SetFromEpochSeconds( _silverLiningNode->getDateTime().asTimeStamp() );
+    _SL->getAtmosphere()->GetConditions()->SetTime( utcTime );
+}
+
+void
+SilverLiningContextNode::onSetMinimumAmbient()
+{
+    _SL->setMinimumAmbient( _silverLiningNode->getMinimumAmbient() );
+}
+
+void
+SilverLiningContextNode::traverse(osg::NodeVisitor& nv)
+{
+    if ( _SL && _SL->ready() )
+    {
+        if ( nv.getVisitorType() == nv.UPDATE_VISITOR )
+        {
+			int frameNumber = nv.getFrameStamp()->getFrameNumber();
+            _skyDrawable->dirtyBound();
+
+            if( _cloudsDrawable )
+            {
+                if ( _lastAltitude <= *_options.cloudsMaxAltitude() )
+                {
+                    if ( _cloudsDrawable->getNumParents() == 0 )
+                        _geode->addDrawable( _cloudsDrawable.get() );
+
+                    _cloudsDrawable->dirtyBound();
+                }
+                else
+                {
+                    if ( _cloudsDrawable->getNumParents() > 0 )
+                        _geode->removeDrawable( _cloudsDrawable.get() );
+                }
+            }
+        }
+
+        else if ( nv.getVisitorType() == nv.CULL_VISITOR )
+        {
+			osgUtil::CullVisitor* cv = Culling::asCullVisitor(nv);
+			osg::Camera* camera  = cv->getCurrentCamera();
+			if ( camera )
+			{
+#ifndef SL_USE_CULL_MASK
+				//Check if this is the target camera for this context
+				if(getTargetCamera() == camera)
+#endif
+     			{
+
+					// TODO: make this multi-camera safe
+					_SL->setCameraPosition( nv.getEyePoint() );
+					osgUtil::CullVisitor* cv = Culling::asCullVisitor(nv);
+					_SL->getAtmosphere()->SetCameraMatrix( cv->getModelViewMatrix()->ptr() );
+					_SL->getAtmosphere()->SetProjectionMatrix( cv->getProjectionMatrix()->ptr() );
+
+					_lastAltitude = _SL->getSRS()->isGeographic() ?
+						cv->getEyePoint().length() - _SL->getSRS()->getEllipsoid()->getRadiusEquator() :
+					cv->getEyePoint().z();
+
+					_SL->updateLocation();
+					_SL->updateLight();
+					//_SL->getAtmosphere()->UpdateSkyAndClouds();
+					//_SL->getAtmosphere()->CullObjects();
+				}
+			}
+        }
+    }
+
+    if ( _geode.valid() )
+    {
+        _geode->accept(nv);
+    }
+}
\ No newline at end of file
diff --git a/src/osgEarthSilverLining/SilverLiningNode b/src/osgEarthSilverLining/SilverLiningNode
new file mode 100644
index 0000000..5c6c243
--- /dev/null
+++ b/src/osgEarthSilverLining/SilverLiningNode
@@ -0,0 +1,91 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+ * Copyright 2016 Pelican Mapping
+ * http://osgearth.org
+ *
+ * osgEarth is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+#include "Common"
+#include "SilverLiningOptions"
+#include "SilverLiningCallback"
+#include "SilverLiningAPIWrapper"
+#include <osgEarthUtil/Sky>
+#include <osgEarth/Map>
+#include <osgEarth/Containers>
+#include <osgEarth/PhongLightingEffect>
+#include <osg/Light>
+#include <osg/LightSource>
+
+namespace osgEarth { namespace SilverLining
+{
+    class SilverLiningContext;
+	class SilverLiningContextNode;
+
+    /**
+     * Node that roots the silverlining adapter.
+     */
+    class OSGEARTHSILVERLINING_EXPORT SilverLiningNode : public osgEarth::Util::SkyNode
+    {
+    public:
+        SilverLiningNode(
+            const osgEarth::SpatialReference* mapSRS,
+            const SilverLiningOptions& options,
+            Callback*                  callback =0L);
+
+    public: // SkyNode
+
+        /** The (sun) light that this node controls */
+        osg::Light* getSunLight() { return _light.get(); }
+
+        /** Attach to a view so that this node controls its light. */
+        void attach(osg::View* view, int lightNum);
+
+        /** Number of contexts (each context is tied to a camera/viewport) */
+        unsigned getNumContexts() const;
+
+        /** Access the clouds stateset for context "index" so you can modify its render bin details, etc. */
+        osg::StateSet* getCloudsStateSet(unsigned contextIndex) const;
+
+        /** Access the sky stateset for context "index" */
+        osg::StateSet* getSkyStateSet(unsigned contextIndex) const;
+
+    public:
+        // callbacks from base class.
+        void onSetDateTime();
+        void onSetMinimumAmbient();
+
+    public: // osg::Node
+
+        void traverse(osg::NodeVisitor&);
+
+    protected:
+        virtual ~SilverLiningNode();
+
+        osg::ref_ptr<osg::LightSource> _lightSource;
+        osg::ref_ptr<osg::Light> _light;
+        const SilverLiningOptions _options;
+        osg::ref_ptr<osgEarth::PhongLightingEffect> _lighting;
+        const osgEarth::SpatialReference* _mapSRS;
+        osg::ref_ptr<Callback> _callback;
+
+        typedef std::map<osg::Camera*, osg::ref_ptr<osg::Node> > CameraContextMap;
+        CameraContextMap _contexts;
+        osg::NodeList _contextList;
+
+        typedef std::set<osg::ref_ptr<osg::Camera> > CameraSet;
+        CameraSet _camerasToAdd;
+    };
+
+} } // namespace osgEarth::SilverLining
diff --git a/src/osgEarthSilverLining/SilverLiningNode.cpp b/src/osgEarthSilverLining/SilverLiningNode.cpp
new file mode 100644
index 0000000..aa08b9a
--- /dev/null
+++ b/src/osgEarthSilverLining/SilverLiningNode.cpp
@@ -0,0 +1,199 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+ * Copyright 2016 Pelican Mapping
+ * http://osgearth.org
+ *
+ * osgEarth is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ */
+#include <SilverLining.h>
+
+#include "SilverLiningNode"
+#include "SilverLiningContextNode"
+#include "SilverLiningContext"
+#include "SilverLiningSkyDrawable"
+#include "SilverLiningCloudsDrawable"
+
+#include <osg/Light>
+#include <osg/LightSource>
+#include <osgEarth/CullingUtils>
+
+#undef  LC
+#define LC "[SilverLiningNode] "
+
+using namespace osgEarth::SilverLining;
+
+SilverLiningNode::SilverLiningNode(const osgEarth::SpatialReference*    mapSRS,
+                                   const SilverLiningOptions& options,
+                                   Callback*                  callback) :
+_options(options),
+_mapSRS(mapSRS),
+_callback(callback)
+{
+    // Create a new Light for the Sun.
+    _light = new osg::Light();
+    _light->setLightNum( 0 );
+    _light->setDiffuse( osg::Vec4(1,1,1,1) );
+    _light->setAmbient( osg::Vec4(0.2f, 0.2f, 0.2f, 1) );
+    _light->setPosition( osg::Vec4(1, 0, 0, 0) ); // w=0 means infinity
+    _light->setDirection( osg::Vec3(-1,0,0) );
+
+    _lightSource = new osg::LightSource();
+    _lightSource->setLight( _light.get() );
+    _lightSource->setReferenceFrame(osg::LightSource::RELATIVE_RF);
+
+    // scene lighting
+    osg::StateSet* stateset = this->getOrCreateStateSet();
+    _lighting = new PhongLightingEffect();
+    _lighting->setCreateLightingUniform( false );
+    _lighting->attach( stateset );
+
+    // need update traversal.
+    ADJUST_UPDATE_TRAV_COUNT(this, +1);
+}
+
+
+SilverLiningNode::~SilverLiningNode()
+{
+    if ( _lighting.valid() )
+        _lighting->detach();
+}
+
+void
+SilverLiningNode::attach(osg::View* view, int lightNum)
+{
+    _light->setLightNum( lightNum );
+    view->setLight( _light.get() );
+    view->setLightingMode( osg::View::SKY_LIGHT );
+}
+
+unsigned
+SilverLiningNode::getNumContexts() const
+{
+    return static_cast<unsigned>(_contextList.size());
+}
+
+osg::StateSet*
+SilverLiningNode::getCloudsStateSet(unsigned index) const
+{
+    if (index < getNumContexts())
+    {
+        const SilverLiningContextNode* node = dynamic_cast<const SilverLiningContextNode*>(_contextList[index].get());
+        if ( node )
+            return node->getCloudsStateSet();
+    }
+    return 0L;
+}
+
+osg::StateSet*
+SilverLiningNode::getSkyStateSet(unsigned index) const
+{
+    if (index < getNumContexts())
+    {
+        const SilverLiningContextNode* node = dynamic_cast<const SilverLiningContextNode*>(_contextList[index].get());
+        if ( node )
+            return node->getSkyStateSet();
+    }
+    return 0L;
+}
+
+void
+SilverLiningNode::onSetDateTime()
+{
+    for (CameraContextMap::const_iterator itr = _contexts.begin();
+        itr != _contexts.end();
+        ++itr)
+    {
+        SilverLiningContextNode* node = dynamic_cast<SilverLiningContextNode* > ((*itr).second.get());
+        if(node)
+            node->onSetDateTime();
+    }
+}
+
+void
+SilverLiningNode::onSetMinimumAmbient()
+{
+    for (CameraContextMap::const_iterator itr = _contexts.begin();
+        itr != _contexts.end();
+        ++itr)
+    {
+        SilverLiningContextNode* node = dynamic_cast<SilverLiningContextNode* > ((*itr).second.get());
+        if(node)
+            node->onSetMinimumAmbient();
+    }
+}
+
+void
+SilverLiningNode::traverse(osg::NodeVisitor& nv)
+{
+    static Threading::Mutex s_mutex;
+
+    if ( nv.getVisitorType() == nv.CULL_VISITOR )
+    {
+        osgUtil::CullVisitor* cv = Culling::asCullVisitor(nv);
+        osg::Camera* camera = cv->getCurrentCamera();
+        if ( camera )
+        {
+            Threading::ScopedMutexLock lock(s_mutex);
+
+            CameraContextMap::const_iterator i = _contexts.find(camera);
+            if (i == _contexts.end())
+            {
+                _camerasToAdd.insert(camera);
+            }
+
+            else
+            {
+                i->second->accept(nv);
+            }
+        }
+    }
+
+    else if (nv.getVisitorType() == nv.UPDATE_VISITOR)
+    {
+        {
+            Threading::ScopedMutexLock lock(s_mutex);
+            if (!_camerasToAdd.empty())
+            {
+                for (CameraSet::const_iterator i = _camerasToAdd.begin(); i != _camerasToAdd.end(); ++i)
+                {
+                    SilverLiningContextNode* newNode = new SilverLiningContextNode(this, i->get(), _light, _mapSRS, _options, _callback);
+                    _contexts[i->get()] = newNode;
+                    _contextList.push_back(newNode);
+                }
+                _camerasToAdd.clear();
+            }
+        }
+
+        for (CameraContextMap::const_iterator i = _contexts.begin(); i != _contexts.end(); ++i)
+        {
+            i->second->accept(nv);
+        }
+    }
+
+    else
+    {
+        Threading::ScopedMutexLock lock(s_mutex);
+        for (CameraContextMap::const_iterator i = _contexts.begin(); i != _contexts.end(); ++i)
+        {
+            i->second->accept(nv);
+        }
+    }
+
+    if ( _lightSource.valid() )
+    {
+        _lightSource->accept(nv);
+    }
+
+    osgEarth::Util::SkyNode::traverse(nv);
+}
diff --git a/src/osgEarthSilverLining/SilverLiningOptions b/src/osgEarthSilverLining/SilverLiningOptions
new file mode 100644
index 0000000..ea9cd75
--- /dev/null
+++ b/src/osgEarthSilverLining/SilverLiningOptions
@@ -0,0 +1,102 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+ * Copyright 2016 Pelican Mapping
+ * http://osgearth.org
+ *
+ * osgEarth is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ */
+#ifndef OSGEARTH_DRIVER_SILVERLINING_OPTIONS
+#define OSGEARTH_DRIVER_SILVERLINING_OPTIONS 1
+
+#include "Common"
+#include <osgEarthUtil/Sky>
+
+namespace osgEarth { namespace SilverLining
+{
+    /**
+     * Options for creating a SilverLining environment node
+     */
+    class /*header only*/ SilverLiningOptions : public osgEarth::Util::SkyOptions
+    {
+    public:
+        SilverLiningOptions(const osgEarth::Util::SkyOptions& options =osgEarth::Util::SkyOptions()) :
+          osgEarth::Util::SkyOptions(options),
+          _drawClouds(false),
+          _cloudsMaxAltitude(20000)
+        {
+            setDriver( "silverlining" );
+            fromConfig( _conf );
+        }
+        virtual ~SilverLiningOptions() { }
+
+    public: // properties
+
+        /* User name for license activation */
+        optional<std::string>& user() { return _user; }
+        const optional<std::string>& user() const { return _user; }
+
+        /* License code string */
+        optional<std::string>& licenseCode() { return _licenseCode; }
+        const optional<std::string>& licenseCode() const { return _licenseCode; }
+
+        /* SilverLining resource path */
+        optional<std::string>& resourcePath() { return _resourcePath; }
+        const optional<std::string>& resourcePath() const { return _resourcePath; }
+
+        /* Whether to draw clouds */
+        optional<bool>& drawClouds() { return _drawClouds; }
+        const optional<bool>& drawClouds() const { return _drawClouds; }
+
+		/* Max altitude at which to draw/update clouds */
+		optional<double>& cloudsMaxAltitude() { return _cloudsMaxAltitude; }
+		const optional<double>& cloudsMaxAltitude() const { return _cloudsMaxAltitude; }
+
+    public:
+        osgEarth::Config getConfig() const {
+            osgEarth::Config conf = osgEarth::Util::SkyOptions::getConfig();
+            conf.addIfSet("user", _user);
+            conf.addIfSet("license_code", _licenseCode);
+            conf.addIfSet("resource_path", _resourcePath);
+            conf.addIfSet("clouds", _drawClouds);
+			conf.addIfSet("clouds_max_altitude", _cloudsMaxAltitude);
+            return conf;
+        }
+
+    protected:
+        void mergeConfig( const osgEarth::Config& conf ) {
+            osgEarth::Util::SkyOptions::mergeConfig( conf );
+            fromConfig(conf);
+        }
+
+    private:
+        void fromConfig( const osgEarth::Config& conf ) {
+            conf.getIfSet("user", _user);
+            conf.getIfSet("license_code", _licenseCode);
+            conf.getIfSet("resource_path", _resourcePath);
+            conf.getIfSet("clouds", _drawClouds);
+			conf.getIfSet("clouds_max_altitude", _cloudsMaxAltitude);
+        }
+
+        osgEarth::optional<std::string> _user;
+        osgEarth::optional<std::string> _licenseCode;
+        osgEarth::optional<std::string> _resourcePath;
+        osgEarth::optional<bool>        _drawClouds;
+		osgEarth::optional<double>      _cloudsMaxAltitude;
+		int                             _lastCullFrameNumber;
+    };
+
+} } // namespace osgEarth::SilverLiningPlugin
+
+#endif // OSGEARTH_DRIVER_SILVERLINING_OPTIONS
+
diff --git a/src/osgEarthSilverLining/SilverLiningSkyDrawable b/src/osgEarthSilverLining/SilverLiningSkyDrawable
new file mode 100644
index 0000000..5ce187d
--- /dev/null
+++ b/src/osgEarthSilverLining/SilverLiningSkyDrawable
@@ -0,0 +1,57 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+ * Copyright 2016 Pelican Mapping
+ * http://osgearth.org
+ *
+ * osgEarth is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ */
+#include <osg/Drawable>
+#include <osg/RenderInfo>
+#include <osg/Version>
+
+namespace osgEarth { namespace SilverLining
+{
+    class SilverLiningContext;
+	class SilverLiningContextNode;
+    /**
+     * Custom drawable for rendering the SilverLining effects
+     */
+    class SkyDrawable : public osg::Drawable
+    {
+    public:
+        SkyDrawable(SilverLiningContextNode* contextNode =0L);
+        META_Object(SilverLining, SkyDrawable);
+     
+    public: // osg::Drawable
+
+        // custom draw (called with an active GC)
+        void drawImplementation(osg::RenderInfo& ri) const;
+
+        // custom bounds computation
+#if OSG_VERSION_GREATER_THAN(3,3,1)
+        osg::BoundingBox computeBoundingBox() const;
+#else
+        osg::BoundingBox computeBound() const;
+#endif
+
+    protected:
+        virtual ~SkyDrawable() { }
+
+        osg::observer_ptr<SilverLiningContext> _SL;
+		SilverLiningContextNode* _contextNode;
+        
+        SkyDrawable(const SkyDrawable& copy, const osg::CopyOp& op=osg::CopyOp::SHALLOW_COPY) { }
+    };
+
+} } // namespace osgEarth::SilverLining
diff --git a/src/osgEarthSilverLining/SilverLiningSkyDrawable.cpp b/src/osgEarthSilverLining/SilverLiningSkyDrawable.cpp
new file mode 100644
index 0000000..8d25e1c
--- /dev/null
+++ b/src/osgEarthSilverLining/SilverLiningSkyDrawable.cpp
@@ -0,0 +1,139 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+ * Copyright 2016 Pelican Mapping
+ * http://osgearth.org
+ *
+ * osgEarth is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ */
+#include <SilverLining.h>
+#include "SilverLiningSkyDrawable"
+#include "SilverLiningContext"
+#include "SilverLiningContextNode"
+#include <osgEarth/SpatialReference>
+
+#define LC "[SilverLining:SkyDrawable] "
+
+using namespace osgEarth::SilverLining;
+
+
+SkyDrawable::SkyDrawable(SilverLiningContextNode* contexNode) :
+_SL(contexNode->getSLContext()),
+_contextNode(contexNode)
+
+{
+    // call this to ensure draw() gets called every frame.
+    setSupportsDisplayList( false );
+
+    // not MT-safe (camera updates, etc)
+    this->setDataVariance( osg::Object::DYNAMIC );
+
+    setName("SilverLining::SkyDrawable");;
+}
+
+void
+SkyDrawable::drawImplementation(osg::RenderInfo& renderInfo) const
+{
+    osg::Camera* camera = renderInfo.getCurrentCamera();
+#ifndef SL_USE_CULL_MASK
+	//Check if this is the target camera
+	if (_contextNode->getTargetCamera() == camera) 
+#endif 
+	{
+	if ( camera)
+    {
+        renderInfo.getState()->disableAllVertexArrays();
+
+        _SL->initialize( renderInfo );
+
+        // convey the sky box size (far plane) to SL:
+        double fovy, ar, znear, zfar;
+        _SL->setCamera(camera);
+        camera->getProjectionMatrixAsPerspective(fovy, ar, znear, zfar);
+        _SL->setSkyBoxSize( zfar < 100000.0 ? zfar : 100000.0 );
+
+        // invoke the user callback if it exists
+        if (_SL->getCallback())
+            _SL->getCallback()->onDrawSky(_SL->getAtmosphereWrapper());
+
+        // draw the sky.
+        _SL->getAtmosphere()->DrawSky(
+            true,
+            _SL->getSRS()->isGeographic(),
+            _SL->getSkyBoxSize(),
+            true,
+            false );
+
+        // Dirty the state and the program tracking to prevent GL state conflicts.
+        renderInfo.getState()->dirtyAllVertexArrays();
+        renderInfo.getState()->dirtyAllAttributes();
+
+#if 0
+#if OSG_VERSION_GREATER_OR_EQUAL(3,4,0)
+        osg::GLExtensions* api = renderInfo.getState()->get<osg::GLExtensions>();
+#else
+        osg::GL2Extensions* api = osg::GL2Extensions::Get(renderInfo.getState()->getContextID(), true);
+#endif
+        api->glUseProgram((GLuint)0);
+        renderInfo.getState()->setLastAppliedProgramObject(0L);
+#endif
+
+        renderInfo.getState()->apply();
+    }
+	}
+}
+
+osg::BoundingBox
+#if OSG_VERSION_GREATER_THAN(3,3,1)
+SkyDrawable::computeBoundingBox() const
+#else
+SkyDrawable::computeBound() const
+#endif
+{
+    osg::BoundingBox skyBoundBox;
+    if ( !_SL->ready() )
+        return skyBoundBox;
+
+    ::SilverLining::Atmosphere* atmosphere = _SL->getAtmosphere();
+    double skyboxSize = _SL->getSkyBoxSize();
+    if ( skyboxSize == 0.0 )
+        skyboxSize = 1000.0;
+
+    osg::Vec3d radiusVec = osg::Vec3d(skyboxSize, skyboxSize, skyboxSize) * 0.5;
+    osg::Vec3d camPos = _SL->getCameraPosition();
+    if (_SL->getCamera())
+    {
+        osg::Vec3f eye, center, up;
+        _SL->getCamera()->getViewMatrixAsLookAt(eye, center, up);
+        camPos = osg::Vec3d(eye.x(), eye.y(), eye.z());
+    }
+
+    skyBoundBox.set( camPos-radiusVec, camPos+radiusVec );
+
+    // this enables the "blue ring" around the earth when viewing from space.
+    bool hasLimb = atmosphere->GetConfigOptionBoolean("enable-atmosphere-from-space");
+    if ( hasLimb )
+    {
+        // Compute bounds of atmospheric limb centered at (0,0,0)
+        double earthRadius = atmosphere->GetConfigOptionDouble("earth-radius-meters");
+        double atmosphereHeight = earthRadius + atmosphere->GetConfigOptionDouble("atmosphere-height");
+        double atmosphereThickness = atmosphere->GetConfigOptionDouble("atmosphere-scale-height-meters") + earthRadius;
+
+        osg::BoundingBox atmosphereBox;
+        osg::Vec3d atmMin(-atmosphereThickness, -atmosphereThickness, -atmosphereThickness);
+        osg::Vec3d atmMax(atmosphereThickness, atmosphereThickness, atmosphereThickness);
+        atmosphereBox.set( atmMin, atmMax );
+        skyBoundBox.expandBy( atmosphereBox );
+    }
+    return skyBoundBox;
+}
diff --git a/src/osgEarthSplat/BiomeRegion b/src/osgEarthSplat/BiomeRegion
new file mode 100644
index 0000000..6816bae
--- /dev/null
+++ b/src/osgEarthSplat/BiomeRegion
@@ -0,0 +1,84 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+ * Copyright 2015 Pelican Mapping
+ * http://osgearth.org
+ *
+ * osgEarth is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ */
+#ifndef OSGEARTH_SPLAT_BIOME_H
+#define OSGEARTH_SPLAT_BIOME_H 1
+
+#include "Export"
+#include "SplatCatalog"
+#include <osgEarth/GeoData>
+#include <vector>
+
+namespace osgEarth { namespace Splat
+{
+    /**
+     * Defines a set of geospatial extents under which to apply a particular
+     * procedural catalog.
+     */
+    class OSGEARTHSPLAT_EXPORT BiomeRegion
+    {
+    public: // types        
+        struct Region
+        {
+            GeoExtent extent;
+            double    zmin, zmin2;
+            double    zmax, zmax2;
+            double    meanRadius2;
+            osg::Polytope tope;
+        };
+
+    public:
+        /** Construct an empty biome. */
+        BiomeRegion();
+
+        /** Get the list of bounding boxes enclosing this biome. */
+        std::vector<Region>& getRegions() { return _regions; }
+        const std::vector<Region>& getRegions() const { return _regions; }
+
+        /** Name of this biome. */
+        optional<std::string>& name() { return _name; }
+        const optional<std::string>& name() const { return _name; }
+
+        /** URI of the catalog mapped to this biome */
+        optional<URI>& catalogURI() { return _catalogURI; }
+        const optional<URI>& catalogURI() const { return _catalogURI; }
+
+        /** The catalog to apply for this biome. */
+        void setCatalog(SplatCatalog* catalog) { _catalog = catalog; }
+        SplatCatalog* getCatalog() const { return _catalog.get(); }
+
+
+    public:
+        /** Serialize this biome's primitive members. */
+        Config getConfig() const;
+
+        bool configure(const Config& conf);
+
+    protected:
+
+        optional<std::string>      _name;
+        optional<URI>              _catalogURI;
+        std::vector<Region>        _regions;
+        osg::ref_ptr<SplatCatalog> _catalog;
+    };
+
+    typedef std::vector<BiomeRegion> BiomeRegionVector;
+
+} } // namespace osgEarth::Splat
+
+#endif // OSGEARTH_SPLAT_BIOME_H
diff --git a/src/osgEarthSplat/BiomeRegion.cpp b/src/osgEarthSplat/BiomeRegion.cpp
new file mode 100644
index 0000000..f6308f6
--- /dev/null
+++ b/src/osgEarthSplat/BiomeRegion.cpp
@@ -0,0 +1,76 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+ * Copyright 2015 Pelican Mapping
+ * http://osgearth.org
+ *
+ * osgEarth is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ */
+#include "BiomeRegion"
+
+using namespace osgEarth;
+using namespace osgEarth::Splat;
+
+#define LC "[BiomeRegion] "
+
+#define SPLAT_BIOME_CURRENT_VERSION 1
+
+
+//............................................................................
+
+BiomeRegion::BiomeRegion()
+{
+    //nop
+}
+
+bool
+BiomeRegion::configure(const Config& conf)
+{
+    conf.getIfSet( "name", _name );
+    conf.getIfSet( "catalog", _catalogURI );
+    
+    // only supports lat long for now
+    const SpatialReference* srs = SpatialReference::create("wgs84");
+    
+    const Config& extentsConf = conf.child("regions");
+    for(ConfigSet::const_iterator i = extentsConf.children().begin();
+        i != extentsConf.children().end();
+        ++i)
+    {
+        double xmin = i->value("xmin", -DBL_MAX);
+        double xmax = i->value("xmax",  DBL_MAX);
+        double ymin = i->value("ymin", -DBL_MAX);
+        double ymax = i->value("ymax",  DBL_MAX);
+        double zmin = i->value("zmin", -DBL_MAX);
+        double zmax = i->value("zmax",  DBL_MAX);
+        
+        _regions.push_back( Region() );
+        _regions.back().extent = GeoExtent(srs, xmin, ymin, xmax, ymax);
+        _regions.back().zmin  = zmin;
+        _regions.back().zmax  = zmax;
+    }
+
+    return true;
+}
+
+Config
+BiomeRegion::getConfig() const
+{
+    Config conf("biome");
+    conf.addIfSet( "name",    _name );
+    conf.addIfSet( "catalog", _catalogURI );
+    // TODO: add regions
+    OE_WARN << LC << "INTERNAL: Biome::getConfig() not fully implemented.\n";
+    return conf;
+}
+
diff --git a/src/osgEarthSplat/BiomeRegionSelector b/src/osgEarthSplat/BiomeRegionSelector
new file mode 100644
index 0000000..291de2b
--- /dev/null
+++ b/src/osgEarthSplat/BiomeRegionSelector
@@ -0,0 +1,56 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+ * Copyright 2015 Pelican Mapping
+ * http://osgearth.org
+ *
+ * osgEarth is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ */
+#ifndef OSGEARTH_SPLAT_BIOME_SELECTOR_CALLBACK
+#define OSGEARTH_SPLAT_BIOME_SELECTOR_CALLBACK 1
+
+#include "BiomeRegion"
+#include "Export"
+#include <osg/NodeCallback>
+#include <osg/Polytope>
+
+namespace osgEarth { namespace Splat
+{
+    // TODO: THIS WILL BECOME THE "SURFACE SELECTOR"
+
+    /**
+     * Cull callback that applies the approprate stateset based on what
+     * it determines to be the active Biome.
+     */
+    class OSGEARTHSPLAT_EXPORT BiomeRegionSelector : public osg::NodeCallback
+    {
+    public:
+        BiomeRegionSelector(
+            const BiomeRegionVector&     biomeRegions,
+            const SplatTextureDefVector& textureDefs,
+            osg::StateSet*               basicStateSet,
+            int                          textureImageUnit);
+
+    public: // osg::NodeCallback
+
+        void operator()(osg::Node* node, osg::NodeVisitor* nv);
+
+    protected:
+        BiomeRegionVector                          _biomeRegions;
+        std::vector< osg::ref_ptr<osg::StateSet> > _stateSets;
+        std::vector< osg::Polytope >               _topes;
+    };
+
+} } // namespace osgEarth::Splat
+
+#endif // OSGEARTH_SPLAT_BIOME_SELECTOR_CALLBACK
diff --git a/src/osgEarthSplat/BiomeRegionSelector.cpp b/src/osgEarthSplat/BiomeRegionSelector.cpp
new file mode 100644
index 0000000..7440af5
--- /dev/null
+++ b/src/osgEarthSplat/BiomeRegionSelector.cpp
@@ -0,0 +1,143 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+ * Copyright 2015 Pelican Mapping
+ * http://osgearth.org
+ *
+ * osgEarth is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ */
+#include "BiomeRegionSelector"
+
+#include <osgEarth/CullingUtils>
+#include <osgEarth/VirtualProgram>
+#include <osgEarth/GeoData>
+
+using namespace osgEarth;
+using namespace osgEarth::Splat;
+
+#define LC "[BiomeSelector] "
+
+BiomeRegionSelector::BiomeRegionSelector(const BiomeRegionVector&     biomeRegions,
+                                         const SplatTextureDefVector& textureDefs,
+                                         osg::StateSet*               stateSet,
+                                         int                          textureImageUnit) :
+_biomeRegions( biomeRegions )
+{
+    for(unsigned i=0; i<_biomeRegions.size(); ++i)
+    {
+        BiomeRegion& biomeRegion = _biomeRegions[i];
+
+        // pre-calculate optimized values for each biome region.
+        std::vector<BiomeRegion::Region>& regions = biomeRegion.getRegions();
+        for(unsigned r=0; r<regions.size(); ++r)
+        {
+            BiomeRegion::Region& region = regions[r];
+            region.extent.createPolytope( region.tope );
+            region.zmin2 = region.zmin > -DBL_MAX ? region.zmin*region.zmin : region.zmin;
+            region.zmax2 = region.zmax < DBL_MAX ? region.zmax*region.zmax : region.zmax;
+
+            // this only needs to be very approximate.
+            region.meanRadius2 = region.extent.getSRS()->isGeographic() ?
+                region.extent.getSRS()->getEllipsoid()->getRadiusEquator() : 0.0;
+            region.meanRadius2 *= region.meanRadius2;
+        }
+
+        // next, set up a stateset with the approprate texture and program
+        // for this biome.
+        const SplatTextureDef& textureDef = textureDefs[i];
+
+        // shallow-copy the stateset in prepration for customization:
+        osg::StateSet* biomeSS = 
+            i == 0 ? stateSet :
+            osg::clone(stateSet, osg::CopyOp::SHALLOW_COPY);
+
+        // install his biome's texture set:
+        biomeSS->setTextureAttribute(textureImageUnit, textureDef._texture.get());
+
+        // install this biome's sampling function. Use cloneOrCreate since each
+        // stateset needs a different shader set in its VP.
+        VirtualProgram* vp = VirtualProgram::cloneOrCreate( biomeSS );
+        osg::Shader* shader = new osg::Shader(osg::Shader::FRAGMENT, textureDef._samplingFunction);
+        vp->setShader( "oe_splat_getRenderInfo", shader );
+
+        // put it on the list for fast access in the cull traversal.
+        _stateSets.push_back( biomeSS );
+    }
+}
+
+void
+BiomeRegionSelector::operator()(osg::Node* node, osg::NodeVisitor* nv)
+{
+    osgUtil::CullVisitor* cv = Culling::asCullVisitor(nv);
+
+    osg::Vec3d vp = cv->getViewPoint();
+    double z2 = vp.length2();
+    
+    osg::StateSet* stateSet = 0L;
+
+    for(unsigned b=0; b<_biomeRegions.size() && stateSet == 0L; ++b)
+    {
+        const BiomeRegion& biomeRegion = _biomeRegions[b];        
+        bool match = false;
+            
+        if ( biomeRegion.getRegions().size() == 0 )
+        {
+            // empty biome is a match.
+            //OE_INFO << "matched " <<biomeRegion.name().get() << " b/c biome has no regions\n";
+            match = true;
+        }
+        else
+        {
+            // check each region of the biome:
+            for(unsigned r=0; r<biomeRegion.getRegions().size() && !match; ++r)
+            {
+                const BiomeRegion::Region& region = biomeRegion.getRegions()[r];
+
+                // empty extent/tope is a match:
+                if ( region.tope.empty() )
+                {
+                    //OE_INFO << "matched " << biomeRegion.name().get() << " b/c tope is empty\n";
+                    match = true;
+                }
+
+                // otherwise, check for intersection:
+                else if ( region.tope.contains(vp) )
+                {
+                    double hat2 = z2 - region.meanRadius2;
+                    if ( hat2 >= region.zmin2 && hat2 <= region.zmax2 )
+                    {
+                        //OE_INFO << "matched " << biomeRegion.name().get() << " b/c eyepoint intersects\n";
+                        match = true;
+                    }
+                }
+            }
+        }
+
+        if ( match )
+        {
+            stateSet = _stateSets[b].get();
+        }
+    }
+
+    if ( stateSet )
+    {
+        cv->pushStateSet( stateSet );
+    }
+
+    traverse(node, nv);
+
+    if ( stateSet )
+    {
+        cv->popStateSet();
+    }
+}
diff --git a/src/osgEarthSplat/CMakeLists.txt b/src/osgEarthSplat/CMakeLists.txt
new file mode 100644
index 0000000..8dd6f4b
--- /dev/null
+++ b/src/osgEarthSplat/CMakeLists.txt
@@ -0,0 +1,99 @@
+#
+# texture splatting plugin
+#
+
+IF   (DYNAMIC_OSGEARTH)
+    ADD_DEFINITIONS(-DOSGEARTHSPLAT_LIBRARY)
+ELSE (DYNAMIC_OSGEARTH)
+    ADD_DEFINITIONS(-DOSGEARTHSPLAT_LIBRARY_STATIC)
+ENDIF(DYNAMIC_OSGEARTH)
+
+SET(LIB_NAME osgEarthSplat)
+
+set(TARGET_GLSL
+    Splat.types.glsl
+    Splat.Noise.glsl
+    Splat.vert.model.glsl
+    Splat.vert.view.glsl
+    Splat.frag.glsl
+    Splat.frag.common.glsl
+    Splat.util.glsl
+    LandCover.TCS.glsl
+    LandCover.TES.glsl
+    LandCover.GS.glsl
+    LandCover.FS.glsl )
+
+set(SHADERS_CPP "${CMAKE_CURRENT_BINARY_DIR}/AutoGenShaders.cpp")
+
+configure_shaders(
+    SplatShaders.cpp.in
+    ${SHADERS_CPP}
+    ${TARGET_GLSL} )
+
+set(TARGET_IN    
+    SplatShaders.cpp.in)
+
+set(TARGET_SRC
+    Coverage.cpp
+    LandCover.cpp
+    LandCoverTerrainEffect.cpp
+    LandCoverTilePatchCallback.cpp
+    LandUseTileSource.cpp
+    NoiseTextureFactory.cpp
+	SplatExtension.cpp
+	SplatCatalog.cpp
+	SplatTerrainEffect.cpp
+	SplatCoverageLegend.cpp
+    Surface.cpp
+    Zone.cpp
+    ${SHADERS_CPP})
+	
+set(LIB_PUBLIC_HEADERS
+    Coverage
+	Export
+    LandCover
+    LandCoverTerrainEffect
+    LandCoverTilePatchCallback
+    LandUseTileSource
+    NoiseTextureFactory
+	SplatCoverageLegend
+	SplatCatalog
+	SplatExtension
+	SplatOptions
+    SplatShaders
+	SplatTerrainEffect
+    Surface
+    Zone)
+	
+SET(TARGET_H
+	${LIB_PUBLIC_HEADERS}
+	SplatShaders)
+
+ADD_LIBRARY(${LIB_NAME} ${OSGEARTH_USER_DEFINED_DYNAMIC_OR_STATIC}
+    ${LIB_PUBLIC_HEADERS}
+    ${TARGET_SRC}
+    ${TARGET_GLSL}
+    ${TARGET_IN}
+)
+
+IF (WIN32)
+  LINK_EXTERNAL(${LIB_NAME} ${TARGET_EXTERNAL_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} ${MATH_LIBRARY})
+ELSE(WIN32)
+  LINK_EXTERNAL(${LIB_NAME} ${TARGET_EXTERNAL_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} ${MATH_LIBRARY})
+ENDIF(WIN32)
+
+LINK_INTERNAL(${LIB_NAME}
+    osgEarth
+    osgEarthFeatures
+    osgEarthSymbology
+    osgEarthAnnotation
+    osgEarthUtil
+)
+
+LINK_WITH_VARIABLES(${LIB_NAME} OSG_LIBRARY OSGUTIL_LIBRARY OSGSIM_LIBRARY OSGTERRAIN_LIBRARY OSGDB_LIBRARY OSGFX_LIBRARY OSGMANIPULATOR_LIBRARY OSGVIEWER_LIBRARY OSGTEXT_LIBRARY OSGGA_LIBRARY OSGSHADOW_LIBRARY OPENTHREADS_LIBRARY)
+LINK_CORELIB_DEFAULT(${LIB_NAME} ${CMAKE_THREAD_LIBS_INIT} ${MATH_LIBRARY})
+
+# Add this project to the NodeKits solution folder
+set_property( TARGET ${LIB_NAME} PROPERTY FOLDER "NodeKits" )
+
+INCLUDE(ModuleInstall OPTIONAL)
\ No newline at end of file
diff --git a/src/osgEarthSplat/Coverage b/src/osgEarthSplat/Coverage
new file mode 100644
index 0000000..04fdfb4
--- /dev/null
+++ b/src/osgEarthSplat/Coverage
@@ -0,0 +1,118 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+ * Copyright 2016 Pelican Mapping
+ * http://osgearth.org
+ *
+ * osgEarth is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ */
+#ifndef OSGEARTH_PROCEDURAL_COVERAGE
+#define OSGEARTH_PROCEDURAL_COVERAGE 1
+
+#include "Export"
+#include "SplatCoverageLegend"
+#include <osgEarth/Config>
+#include <osgEarth/URI>
+
+namespace osgDB {
+    class Options;
+}
+
+namespace osgEarth {
+    class ImageLayer;
+    class Map;
+}
+
+namespace osgEarth { namespace Splat
+{       
+    /**
+     * Serializable options for the coverage data.
+     */
+    class CoverageOptions : public ConfigOptions
+    {
+    public:
+        CoverageOptions(const ConfigOptions& conf = ConfigOptions()) : ConfigOptions(conf) {            
+            fromConfig( _conf );
+        }
+
+        /** Name of the ImageLayer providing the classification coverage. */
+        optional<std::string>& layer() { return _coverageLayer; }
+        const optional<std::string>& layer() const { return _coverageLayer; }
+
+        /** URI of the legend file. */
+        optional<URI>& legend() { return _legendURI; }
+        const optional<URI>& legend() const { return _legendURI; }
+
+    protected:
+        optional<std::string> _coverageLayer;
+        optional<URI>         _legendURI;
+
+    public:
+        void fromConfig(const Config& conf) {
+            conf.getIfSet("layer", _coverageLayer);
+            conf.getIfSet("legend", _legendURI);
+        }
+        
+        Config getConfig() const {
+            Config conf = ConfigOptions::getConfig();
+            conf.key() = "coverage";
+            conf.updateIfSet("layer", _coverageLayer);
+            conf.updateIfSet("legend", _legendURI);
+            return conf;
+        }
+
+        void mergeConfig( const Config& conf ) {
+            ConfigOptions::mergeConfig( conf );
+            fromConfig( conf );
+        }
+    };
+
+    /**
+     * Coverage data model. This defines the coverage layer and an associated legend that is
+     * used to interpret the coverage code values in the raster.
+     */
+    class OSGEARTHSPLAT_EXPORT Coverage : public osg::Referenced
+    {
+    public:
+        /** Construct the coverage data */
+        Coverage();
+
+    public:
+        /** Image layer providing the coverage data. */
+        void setLayer(ImageLayer* layer);
+        bool lockLayer(osg::ref_ptr<ImageLayer>& safePtr) const; // semantics of observer_ptr.lock
+        bool hasLayer() const { return _layer.valid(); }
+
+        /** The Legend maps classification codes from this coverage data into the common
+          * classification ontology. */
+        void setLegend(SplatCoverageLegend* legend);
+        SplatCoverageLegend* getLegend() const;
+
+    protected:
+        /** dtor */
+        virtual ~Coverage() { }
+
+    protected:
+        osg::observer_ptr<ImageLayer>     _layer;
+        osg::ref_ptr<SplatCoverageLegend> _legend;
+        const CoverageOptions             _options;
+
+    public:
+
+        /** Initialize from a config stucture */
+        bool configure(const ConfigOptions& options, const Map* map, const osgDB::Options* dbo);
+    };
+
+} } // namespace osgEarth::Splat
+
+#endif // OSGEARTH_PROCEDURAL_COVERAGE
diff --git a/src/osgEarthSplat/Coverage.cpp b/src/osgEarthSplat/Coverage.cpp
new file mode 100644
index 0000000..7dc1f67
--- /dev/null
+++ b/src/osgEarthSplat/Coverage.cpp
@@ -0,0 +1,103 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+ * Copyright 2016 Pelican Mapping
+ * http://osgearth.org
+ *
+ * osgEarth is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ */
+#include "Coverage"
+#include "SplatCoverageLegend"
+#include <osgEarth/Map>
+#include <osgEarth/XmlUtils>
+#include <osgDB/Options>
+
+using namespace osgEarth;
+using namespace osgEarth::Splat;
+
+#define LC "[Coverage] "
+
+Coverage::Coverage()
+{
+    //nop
+}
+
+void
+Coverage::setLayer(ImageLayer* layer)
+{
+    _layer = layer;
+}
+
+bool 
+Coverage::lockLayer(osg::ref_ptr<ImageLayer>& layer) const
+{
+    return _layer.lock(layer);
+}
+
+void
+Coverage::setLegend(SplatCoverageLegend* value)
+{
+    _legend = value;
+}
+
+SplatCoverageLegend*
+Coverage::getLegend() const
+{
+    return _legend.get();
+}
+
+bool
+Coverage::configure(const ConfigOptions& conf, const Map* map, const osgDB::Options* dbo)
+{
+    CoverageOptions in( conf );
+    
+    if ( !in.layer().isSet() || in.layer()->empty() )
+    {
+        OE_WARN << LC << "Coverage much reference a map layer.\n";
+        return false;
+    }
+
+    // Find the classification layer in the map:
+    _layer = map->getImageLayerByName( in.layer().get() );
+    if ( !_layer.valid() )
+    {
+        OE_WARN << LC << "Layer \"" << in.layer().get() << "\" not found in the map\n";
+        return false;
+    }
+
+    if ( !in.legend().isSet() )
+    {
+        OE_WARN << LC << "Legend is required\n";
+        return false;
+    }
+
+    // Load the legend from XML:
+    osg::ref_ptr<XmlDocument> doc = XmlDocument::load( in.legend().get(), dbo );
+    if ( doc.valid() )
+    {
+        _legend = new SplatCoverageLegend();
+        _legend->fromConfig( doc->getConfig().child("legend") );
+    }
+
+    if ( !_legend.valid() || _legend->empty() )
+    {
+        OE_WARN << LC << "Failed to read required legend from \"" << in.legend()->full() << "\"\n";
+        return false;
+    }
+    else
+    {
+        OE_INFO << LC << "Legend: found " << _legend->getPredicates().size() << " mappings \n";
+    }
+
+    return true;
+}
diff --git a/src/osgEarthSplat/Export b/src/osgEarthSplat/Export
new file mode 100644
index 0000000..df6b48a
--- /dev/null
+++ b/src/osgEarthSplat/Export
@@ -0,0 +1,63 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+ * Copyright 2016 Pelican Mapping
+ * http://osgearth.org
+ *
+ * osgEarth is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/* -*-c++-*- 
+ * Derived from osg/Export
+ */
+
+#ifndef OSGEARTH_SPLAT_EXPORT_H
+#define OSGEARTH_SPLAT_EXPORT_H 1
+
+// define USE_DEPRECATED_API is used to include in API which is being phased out
+// if you can compile your apps with this turned off you are
+// well placed for compatibility with future versions.
+#define USE_DEPRECATED_API
+
+#if defined(_MSC_VER)
+    #pragma warning( disable : 4244 )
+    #pragma warning( disable : 4251 )
+    #pragma warning( disable : 4267 )
+    #pragma warning( disable : 4275 )
+    #pragma warning( disable : 4290 )
+    #pragma warning( disable : 4786 )
+    #pragma warning( disable : 4305 )
+    #pragma warning( disable : 4996 )
+#endif
+
+#if defined(_MSC_VER) || defined(__CYGWIN__) || defined(__MINGW32__) || defined( __BCPLUSPLUS__)  || defined( __MWERKS__)
+    #  if defined( OSGEARTHSPLAT_LIBRARY_STATIC )
+    #    define OSGEARTH_SPLAT_EXPORT
+    #  elif defined( OSGEARTHSPLAT_LIBRARY )
+    #    define OSGEARTHSPLAT_EXPORT   __declspec(dllexport)
+    #  else
+    #    define OSGEARTHSPLAT_EXPORT   __declspec(dllimport)
+    #  endif
+#else
+    #  define OSGEARTHSPLAT_EXPORT
+#endif  
+
+// set up define for whether member templates are supported by VisualStudio compilers.
+#ifdef _MSC_VER
+# if (_MSC_VER >= 1300)
+#  define __STL_MEMBER_TEMPLATES
+# endif
+#endif
+
+#endif
+
diff --git a/src/osgEarthSplat/LandCover b/src/osgEarthSplat/LandCover
new file mode 100644
index 0000000..757ca3c
--- /dev/null
+++ b/src/osgEarthSplat/LandCover
@@ -0,0 +1,445 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+ * Copyright 2016 Pelican Mapping
+ * http://osgearth.org
+ *
+ * osgEarth is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ */
+#ifndef OSGEARTH_PROCEDURAL_LANDCOVER
+#define OSGEARTH_PROCEDURAL_LANDCOVER 1
+
+#include "Export"
+#include <osgEarth/Config>
+#include <osgEarth/ImageLayer>
+#include <osgEarthSymbology/ResourceLibrary>
+#include <osgEarthSymbology/Symbol>
+#include <osg/BoundingBox>
+#include <osg/Shader>
+
+namespace osgDB {
+    class Options;
+}
+namespace osgEarth {
+    class Map;
+}
+
+namespace osgEarth { namespace Splat
+{
+    using namespace osgEarth;
+    using namespace osgEarth::Symbology;
+
+    class Coverage;
+    class SplatCoverageLegend;
+
+
+    class OSGEARTHSPLAT_EXPORT LandCoverBillboard
+    {
+    public:
+        LandCoverBillboard(osg::Image* image, float width, float height)
+            : _image(image), _width(width), _height(height) { }
+
+        osg::ref_ptr<osg::Image> _image;
+        float                    _width;
+        float                    _height;
+    };
+
+    typedef std::vector<LandCoverBillboard> LandCoverBillboards;
+
+
+    class OSGEARTHSPLAT_EXPORT LandCoverBiome : public osg::Referenced
+    {
+    public:
+        LandCoverBiome() : _code(0) { }
+
+        /** classification names for this biome (space separated) */
+        void setClasses( const std::string& value ) { _classNames = value; }
+        const std::string& getClasses() const { return _classNames; }
+
+        /** Resources that may be used to render land cover in this biome */
+        LandCoverBillboards& getBillboards() { return _billboards; }
+        const LandCoverBillboards& getBillboards() const { return _billboards; }
+
+    protected:
+        virtual ~LandCoverBiome() { }
+
+        std::string    _classNames;
+        int            _code;
+        LandCoverBillboards _billboards;
+
+    public:
+        bool configure(const ConfigOptions& conf, const osgDB::Options* dbo);
+    };
+
+    typedef std::vector< osg::ref_ptr<LandCoverBiome> > LandCoverBiomes;
+
+
+    /**
+     * A layer of land cover data.
+     */
+    class OSGEARTHSPLAT_EXPORT LandCoverLayer : public osg::Referenced
+    {
+    public:
+        LandCoverLayer() : _lod(14), _castShadows(false), _maxDistance(1000.0f), _density(1.0f), _fill(1.0f), _wind(0.0f), _brightness(1.0f), _contrast(0.5f) { }
+
+        /** Name of this layer */
+        void setName(const std::string& name) { _name = name; }
+        const std::string& getName() const { return _name; }
+
+        /** Bounds within which this layer should render (map coordinates) */
+        void setBounds(const Bounds& bounds) { _bounds = bounds; }
+        const Bounds& getBounds() const { return _bounds; }
+
+        /** Terrain LOD at which this layer should render */
+        void setLOD(unsigned lod) { _lod = lod; }
+        unsigned getLOD() const { return _lod; }
+
+        /** Whether this layer should cast shadows when enabled */
+        void setCastShadows(bool value) { _castShadows = value; }
+        bool getCastShadows() const { return _castShadows; }
+
+        /** Maximum visibility distance from camera */
+        void setMaxDistance(float value) { _maxDistance = value; }
+        float getMaxDistance() const { return _maxDistance; }
+
+        /** Density of land cover; i.e. instances per unit of area [1..5+] */
+        void setDensity(float value) { _density = value; }
+        float getDensity() const { return _density; }
+
+        /** Fill percentage of land cover instances [0..1] */
+        void setFill(float value) { _fill = value; }
+        float getFill() const { return _fill; }
+
+        /** Wind effect (0..1) */
+        void setWind(float value) { _wind = value; }
+        float getWind() const { return _wind; }
+
+        /** Brightness [0..2+] .. 1 = default */
+        void setBrightness(float value) { _brightness = value; }
+        float getBrightness() const { return _brightness; }
+
+        /** Contrast [0..1] .. 0 = default */
+        void setContrast(float value) { _contrast = value; }
+        float getContrast() const { return _contrast; }
+
+        /** Biomes comprising this layer. */
+        LandCoverBiomes& getBiomes() { return _biomes; }
+        const LandCoverBiomes& getBiomes() const { return _biomes; }
+
+    public:
+
+        int getTotalNumBillboards() const;
+
+        /** Creates the shader that contains the GLSL APOI for accessing this layer's information */
+        osg::Shader* createShader() const;
+
+        /** Creates the shader that resolves land cover information into billboard data. */
+        osg::Shader* createPredicateShader(const Coverage*) const;
+
+        /** Builds the texture object containing all the data for this layer. */
+        osg::Texture* createTexture() const;
+
+        /** The stateset containing the shaders and state for rendering this layer. */
+        osg::StateSet* getOrCreateStateSet();
+        osg::StateSet* getStateSet() const { return _stateSet.get(); }
+
+    protected:
+        virtual ~LandCoverLayer() { }
+
+        std::string     _name;
+        Bounds          _bounds;
+        unsigned        _lod;
+        bool            _castShadows;
+        float           _maxDistance;
+        float           _density;
+        float           _fill;
+        float           _wind;
+        float           _brightness;
+        float           _contrast;
+        LandCoverBiomes _biomes;
+
+        osg::ref_ptr<osg::StateSet> _stateSet;
+
+    public:
+        bool configure(const ConfigOptions& conf, const osgDB::Options* dbo);
+    };
+
+    typedef std::vector< osg::ref_ptr<LandCoverLayer> > LandCoverLayers;
+
+    /**
+     * Describes all land cover for the scene.
+     */
+    class OSGEARTHSPLAT_EXPORT LandCover : public osg::Referenced
+    {
+    public:
+        LandCover() { }
+
+        /** Resource library containing resources for the land cover assets */
+        void setLibrary(ResourceLibrary* lib) { _lib = lib; }
+        const ResourceLibrary* getLibrary() const { return _lib.get(); }
+
+        /** Land cover layers */
+        LandCoverLayers& getLayers() { return _layers; }
+        const LandCoverLayers& getLayers() const { return _layers; }
+
+        /** Layer that will mask out land cover */
+        void setMaskLayer(ImageLayer* layer) { _maskLayer = layer; }
+        ImageLayer* getMaskLayer() { return _maskLayer.get(); }
+        const ImageLayer* getMaskLayer() const { return _maskLayer.get(); }
+
+    protected:
+        virtual ~LandCover() { }
+
+        osg::ref_ptr<ResourceLibrary> _lib;
+        LandCoverLayers               _layers;
+        osg::ref_ptr<ImageLayer>      _maskLayer;
+        
+    public:
+        bool configure(const ConfigOptions& conf, const Map* map, const osgDB::Options* dbo);
+    };
+
+    typedef std::vector< osg::ref_ptr<LandCover> > LandCovers;
+
+
+    //........................................................................
+
+
+    /**
+     * Configures one biome within a land cover layer.
+     */
+    class LandCoverBiomeOptions : public ConfigOptions
+    {
+    public:
+        LandCoverBiomeOptions(const ConfigOptions& conf = ConfigOptions()) : ConfigOptions(conf) {
+            fromConfig( _conf );
+        }
+
+        /** Name of the biome classes to use. This is one or more class names from the legend,
+          * separated by whitespace. e.g.: "forest grassland swamp" */
+        optional<std::string>& biomeClasses() { return _biomeClasses; }
+        const optional<std::string>& biomeClasses() const { return _biomeClasses; }
+
+        /** Symbology used to conigure rendering in this biome */
+        SymbolVector& symbols() { return _symbols; }
+        const SymbolVector& symbols() const { return _symbols; }
+
+    protected:
+        optional<std::string> _biomeClasses;
+        SymbolVector _symbols;
+
+    public:    
+        void fromConfig(const Config& conf) {
+            conf.getIfSet( "classes", _biomeClasses );
+            const ConfigSet& symbols = conf.children();
+            for(ConfigSet::const_iterator i = symbols.begin(); i != symbols.end(); ++i) {
+                Symbol* s = SymbolRegistry::instance()->create(*i);
+                if ( s ) { 
+                    _symbols.push_back( s );
+                }
+            }
+        }
+
+        Config getConfig() const {
+            Config conf("biome");
+            conf.updateIfSet( "classes", _biomeClasses );
+            for(int i=0; i<_symbols.size(); ++i) {
+                Config symbolConf = _symbols[i]->getConfig();
+                if ( !symbolConf.empty() ) {
+                    conf.add( symbolConf );
+                }
+            }
+            return conf;
+        }
+
+        void mergeConfig( const Config& conf ) {
+            ConfigOptions::mergeConfig( conf );
+            fromConfig( conf );
+        }
+    };
+
+    /**
+     * Configures one layer of land cover data. 
+     */
+    class LandCoverLayerOptions : public ConfigOptions
+    {
+    public:
+        LandCoverLayerOptions(const ConfigOptions& conf = ConfigOptions()) : ConfigOptions(conf) {
+            fromConfig( _conf );
+        }
+
+        /** Name of the land cover layer */
+        optional<std::string>& name() { return _name; }
+        const optional<std::string>& name() const { return _name; }
+
+        /** Equivalent terrain LOD at which this layer will render */
+        optional<unsigned>& lod() { return _lod; }
+        const optional<unsigned>& lod() const { return _lod; }
+
+        /** Whether objects in this layer should cast shadows. */
+        optional<bool>& castShadows() { return _castShadows; }
+        const optional<bool>& castShadows() const { return _castShadows; }
+
+        /** Maximum viewing distance from camera */
+        optional<float>& maxDistance() { return _maxDistance; }
+        const optional<float>& maxDistance() const { return _maxDistance; }
+
+        /** Wind speed [0..1] */
+        optional<float>& wind() { return _wind; }
+        const optional<float>& wind() const { return _wind; }
+
+        /** Metric that controls the number of land cover instances will render
+          * in a given area. [1..5] */
+        optional<float>& density() { return _density; }
+        const optional<float>& density() const { return _density; }
+
+        /** Percentage of land that this layer's instances will cover [0..1]. Lower
+          * values will result is more "patchiness" of placement. */
+        optional<float>& fill() { return _fill; }
+        const optional<float>& fill() const { return _fill; }
+
+        /** Brightness factor for rendering [1..], 1 = default */
+        optional<float>& brightness() { return _brightness; }
+        const optional<float>& brightness() const { return _brightness; }
+
+        /** Contrast factor for rendering [0..], 0 = default */
+        optional<float>& contrast() { return _contrast; }
+        const optional<float>& contrast() const { return _contrast; }
+
+        /** Biomes comprising this layer. */
+        std::vector<LandCoverBiomeOptions>& biomes() { return _biomes; }
+        const std::vector<LandCoverBiomeOptions>& biomes() const { return _biomes; }
+
+    protected:
+        optional<std::string>              _name;
+        optional<unsigned>                 _lod;
+        optional<bool>                     _castShadows;
+        optional<float>                    _maxDistance;
+        optional<float>                    _density;
+        optional<float>                    _fill;
+        optional<float>                    _wind;
+        optional<float>                    _brightness;
+        optional<float>                    _contrast;
+        std::vector<LandCoverBiomeOptions> _biomes;
+
+    public:
+        void fromConfig(const Config& conf) {
+            conf.getIfSet( "name", _name );
+            conf.getIfSet( "lod",  _lod  );
+            conf.getIfSet( "cast_shadows", _castShadows );
+            conf.getIfSet( "max_distance", _maxDistance );
+            conf.getIfSet( "density", _density );
+            conf.getIfSet( "fill", _fill );
+            conf.getIfSet( "wind", _wind );
+            conf.getIfSet( "brightness", _brightness );
+            conf.getIfSet( "contrast", _contrast );
+            const Config* biomes = conf.child_ptr("biomes");
+            if ( biomes ) {
+                const ConfigSet& biomesVec = biomes->children();
+                for( ConfigSet::const_iterator i = biomesVec.begin(); i != biomesVec.end(); ++i ) {
+                    _biomes.push_back( LandCoverBiomeOptions(*i) );
+                }
+            }
+        }
+        
+        Config getConfig() const {
+            Config conf = ConfigOptions::getConfig();
+            conf.key() = "layer";
+            conf.updateIfSet( "name", _name );
+            conf.updateIfSet( "lod",  _lod );
+            conf.updateIfSet( "cast_shadows", _castShadows );
+            conf.updateIfSet( "max_distance", _maxDistance );
+            conf.updateIfSet( "density", _density );
+            conf.updateIfSet( "fill", _fill );
+            conf.updateIfSet( "wind", _wind );
+            conf.updateIfSet( "brightness", _brightness );
+            conf.updateIfSet( "contrast", _contrast );
+            if ( _biomes.size() > 0 ) {
+                Config biomes("biomes");
+                for(int i=0; i<_biomes.size(); ++i) {
+                    biomes.add( "biome", _biomes[i].getConfig() );
+                }
+                conf.update( biomes );
+            }
+            return conf;
+        }
+
+        void mergeConfig( const Config& conf ) {
+            ConfigOptions::mergeConfig( conf );
+            fromConfig( conf );
+        }
+    };
+
+    /**
+     * Options for rendering land cover (environmental features that sit on the terrain
+     * surface like trees, rocks, grass, etc.)
+     */
+    class LandCoverOptions : public ConfigOptions
+    {
+    public:
+        LandCoverOptions(const ConfigOptions& conf = ConfigOptions()) : ConfigOptions(conf) {
+            fromConfig( _conf );
+        }
+
+        /** URI of an resource library to use for land cover data */
+        optional<URI>& library() { return _resourceLibURI; }
+        const optional<URI>& library() const { return _resourceLibURI; }
+
+        /** Layers of land cover data */
+        std::vector<LandCoverLayerOptions>& layers() { return _layers; }
+        const std::vector<LandCoverLayerOptions>& layers() const { return _layers; }
+
+        /** Name of a map layer to use for masking out land cover. */
+        optional<std::string>& maskLayerName() { return _maskLayerName; }
+        const optional<std::string>& maskLayerName() const { return _maskLayerName; }
+
+    protected:        
+        optional<URI>                      _resourceLibURI; 
+        optional<std::string>              _maskLayerName;
+        std::vector<LandCoverLayerOptions> _layers;
+
+    public:
+        void fromConfig(const Config& conf) {
+            conf.getIfSet( "library", _resourceLibURI );
+            conf.getIfSet( "mask_layer", _maskLayerName );
+            const Config* layers = conf.child_ptr("layers");
+            if ( layers ) {
+                const ConfigSet& layerVec = layers->children();
+                for(ConfigSet::const_iterator i = layerVec.begin(); i != layerVec.end(); ++i ) {
+                    _layers.push_back( LandCoverLayerOptions(*i) );
+                }
+            }
+        }
+        
+        Config getConfig() const {
+            Config conf = ConfigOptions::getConfig();
+            conf.key() = "land_cover";
+            conf.updateIfSet( "library", _resourceLibURI );
+            conf.updateIfSet( "mask_layer", _maskLayerName );
+            if ( !_layers.empty() ) {
+                Config layers("layers");
+                for(int i=0; i<_layers.size(); ++i) {
+                    layers.add("layer", _layers[i].getConfig());
+                }
+            }
+            return conf;
+        }
+
+        void mergeConfig( const Config& conf ) {
+            ConfigOptions::mergeConfig( conf );
+            fromConfig( conf );
+        }
+    };
+
+} } // namespace osgEarth::Splat
+
+#endif // OSGEARTH_PROCEDURAL_LANDCOVER
diff --git a/src/osgEarthSplat/LandCover.FS.glsl b/src/osgEarthSplat/LandCover.FS.glsl
new file mode 100644
index 0000000..4e0cb8e
--- /dev/null
+++ b/src/osgEarthSplat/LandCover.FS.glsl
@@ -0,0 +1,49 @@
+#version 330
+#pragma vp_name       Land cover billboard texture application
+#pragma vp_entryPoint oe_landcover_fragment
+#pragma vp_location   fragment_coloring
+
+#define IS_ARRAY
+                     
+uniform bool oe_terrain_hasMultiSamples;
+
+#ifdef IS_ARRAY
+
+uniform sampler2DArray oe_landcover_texArray;
+uniform float oe_landcover_exposure;
+in vec2 oe_landcover_texCoord;
+in vec4 oe_layer_tilec;
+
+flat in float oe_landcover_arrayIndex; // from LandCover.GS.glsl
+
+void oe_landcover_fragment(inout vec4 color)
+{    
+    // modulate the texture
+    color = texture(oe_landcover_texArray, vec3(oe_landcover_texCoord, oe_landcover_arrayIndex)) * color;
+    color.rgb *= oe_landcover_exposure;
+    
+    // if multisampling is off, use alpha-discard.
+    if ( !oe_terrain_hasMultiSamples && color.a < 0.15 )
+        discard;
+}
+
+#else
+
+uniform sampler2D oe_landcover_tex;
+uniform float oe_landcover_exposure;
+
+in vec2 oe_landcover_texCoord;
+in vec4 oe_layer_tilec;
+
+void oe_landcover_fragment(inout vec4 color)
+{    
+    // modulate the texture
+    color = texture(oe_landcover_tex, oe_landcover_texCoord) * color;
+    color.rgb *= oe_landcover_exposure;
+    
+    // if multisampling is off, use alpha-discard.
+    if ( !oe_terrain_hasMultiSamples && color.a < 0.15 )
+        discard;
+}
+
+#endif
\ No newline at end of file
diff --git a/src/osgEarthSplat/LandCover.GS.glsl b/src/osgEarthSplat/LandCover.GS.glsl
new file mode 100644
index 0000000..806975d
--- /dev/null
+++ b/src/osgEarthSplat/LandCover.GS.glsl
@@ -0,0 +1,334 @@
+#version $GLSL_VERSION_STR
+#pragma vp_name       LandCover geometry shader
+#pragma vp_entryPoint oe_landcover_geom
+#pragma vp_location   geometry
+                
+layout(triangles)        in;        // triangles from the TileDrawable
+layout(triangle_strip)   out;       // output a triangle-strip billboard
+layout(max_vertices = 8) out;       // four verts per billboard
+                
+// VP helper functions:
+void VP_LoadVertex(in int);
+void VP_EmitViewVertex();
+
+uniform float osg_FrameTime;            // Frame time (seconds) used for wind animation
+                
+uniform float oe_landcover_width;           // width of each billboard
+uniform float oe_landcover_height;          // height of each billboard
+uniform float oe_landcover_ao;              // fake ambient occlusion of ground verts (0=full)
+
+uniform float oe_landcover_fill;            // percentage of points that make it through, based on noise function
+uniform float oe_landcover_windFactor;      // wind blowing the foliage
+uniform float oe_landcover_maxDistance;     // distance at which flora disappears
+
+uniform float oe_landcover_contrast;
+uniform float oe_landcover_brightness;
+
+uniform sampler2D oe_tile_elevationTex;
+uniform mat4      oe_tile_elevationTexMatrix;
+uniform float     oe_tile_elevationSize;
+
+uniform bool oe_isShadowCamera;
+
+// Noise texture:
+uniform sampler2D oe_splat_noiseTex;
+
+// different noise texture channels:
+#define NOISE_SMOOTH   0
+#define NOISE_RANDOM   1
+#define NOISE_RANDOM_2 2
+#define NOISE_CLUMPY   3
+
+// Input tile coordinates [0..1]
+in vec4 oe_layer_tilec;
+
+// Output grass texture coordinates to the fragment shader
+out vec2 oe_landcover_texCoord;
+
+// Input from the TCS that 
+//flat in int oe_landcover_biomeIndex;
+
+// Output that selects the land cover texture from the texture array (non interpolated)
+flat out float oe_landcover_arrayIndex;
+
+struct oe_landcover_Biome {
+    int firstBillboardIndex;
+    int numBillboards;
+    float density;
+    float fill;
+    vec2 maxWidthHeight;
+};
+void oe_landcover_getBiome(in int biomeIndex, out oe_landcover_Biome biome);
+
+struct oe_landcover_Billboard {
+    int arrayIndex;
+    float width;
+    float height;
+};
+void oe_landcover_getBillboard(in int billboardIndex, out oe_landcover_Billboard bb);
+
+
+// Output colors/normals:
+out vec4 vp_Color;
+out vec3 vp_Normal;
+
+// Up vector for clamping.
+in vec3 oe_UpVectorView;
+
+// SDK import
+float oe_terrain_getElevation(in vec2);
+
+// Generated in code
+int oe_landcover_getBiomeIndex(in vec4);
+
+uniform bool oe_landcover_useMask;
+uniform sampler2D MASK_SAMPLER;
+uniform mat4 MASK_TEXTURE;
+
+
+// Sample the elevation texture and move the vertex accordingly.
+void
+oe_landcover_clamp(inout vec4 vert_view, in vec3 up, vec2 UV)
+{
+    float elev = oe_terrain_getElevation( UV );
+    vert_view.xyz += up*elev;
+}
+
+// Generate a pseudo-random value in the specified range:
+float
+oe_landcover_rangeRand(float minValue, float maxValue, vec2 co)
+{
+    float t = fract(sin(dot(co.xy ,vec2(12.9898,78.233))) * 43758.5453);
+    return minValue + t*(maxValue-minValue);
+}
+
+// Generate a wind-perturbation value
+float
+oe_landcover_applyWind(float time, float factor, float randOffset)
+{
+   return sin(time + randOffset) * factor;
+}
+
+// Generate a pseudo-random barycentric point inside a triangle.
+vec3
+oe_landcover_getRandomBarycentricPoint(vec2 seed)
+{
+    vec3 b;
+    b[0] = oe_landcover_rangeRand(0.0, 1.0, seed.xy);
+    b[1] = oe_landcover_rangeRand(0.0, 1.0, seed.yx);
+    if (b[0]+b[1] >= 1.0)
+    {
+        b[0] = 1.0 - b[0];
+        b[1] = 1.0 - b[1];
+    }
+    b[2] = 1.0 - b[0] - b[1];
+    return b;
+}
+
+// MAIN ENTRY POINT  
+void
+oe_landcover_geom()
+{    
+    vec4 center = vec4(0,0,0,1);
+    vec2 tileUV = vec2(0,0);
+    
+    // gen a random point within the input triangle
+    vec3 b = oe_landcover_getRandomBarycentricPoint(gl_in[0].gl_Position.xy);
+    
+    // Load the triangle data and compute the new position and tile coords
+    // using the barycentric coordinates.
+    for(int i=0; i < 3; ++i)
+    {
+        VP_LoadVertex(i);      
+        
+        center.x += b[i] * gl_in[i].gl_Position.x;
+        center.y += b[i] * gl_in[i].gl_Position.y;
+        center.z += b[i] * gl_in[i].gl_Position.z;
+        
+        tileUV.x += b[i] * oe_layer_tilec.x;
+        tileUV.y += b[i] * oe_layer_tilec.y;
+    }
+   
+    // Look up the biome at this point:
+    int biomeIndex = oe_landcover_getBiomeIndex(vec4(tileUV,0,1));
+    if ( biomeIndex < 0 )
+    {
+        // No biome defined; bail out without emitting any geometry.
+        return;
+    }
+    
+    // If we're using a mask texture, sample it now:
+    if ( oe_landcover_useMask )
+    {
+        float mask = texture(MASK_SAMPLER, (MASK_TEXTURE*vec4(tileUV,0,1)).st).a;
+        if ( mask > 0.0 )
+        {
+            // Failed to pass the mask; no geometry emitted.
+            return;
+        }
+    }
+    
+    // Transform to view space.
+    vec4 center_view = gl_ModelViewMatrix * center;
+    vec3 up_view     = oe_UpVectorView;
+    
+    // Clamp the center point to the elevation.
+    oe_landcover_clamp(center_view, up_view, tileUV);
+
+    // Calculate the normalized camera range:
+    float nRange = clamp(-center_view.z/oe_landcover_maxDistance, 0.0, 1.0);
+
+    // Distance culling:
+    if ( nRange == 1.0 )
+        return;
+
+    // look up biome:
+    oe_landcover_Biome biome;
+    oe_landcover_getBiome(biomeIndex, biome);
+
+    // sample the noise texture.
+    vec4 noise = texture(oe_splat_noiseTex, tileUV);
+
+    // a pseudo-random scale factor to the width and height of a billboard
+    float sizeScale = abs(1.0 + noise[NOISE_RANDOM_2]);
+    
+    // Viewpoint culling:
+    // TODO: remove hard-coded max width/height and replace with a vp_define or a uniform.
+    // Note: this value must account for the height variation introduced by the noise function
+    // later in this shader!
+    vec4 cullPoint = center_view;
+    //vec2 maxWidthHeight = biome.maxWidthHeight * sizeScale;
+    cullPoint.xy -= sign(cullPoint.xy) * min(biome.maxWidthHeight*sizeScale, abs(cullPoint.xy));
+    cullPoint = gl_ProjectionMatrix * cullPoint;
+    float absw = abs(cullPoint.w);
+    if ( abs(cullPoint.x) > absw || abs(cullPoint.y) > absw )// || abs(cullPoint.z) > absw )
+        return;
+
+    // discard instances based on noise value threshold (coverage). If it passes,
+    // scale the noise value back up to [0..1]
+    if ( noise[NOISE_SMOOTH] > oe_landcover_fill )
+        return;
+    else
+        noise[NOISE_SMOOTH] /= oe_landcover_fill;
+
+    // select a billboard seemingly at random. Need to scale n to account for the fill limit first though.
+    int billboardIndex = biome.firstBillboardIndex + int( floor(noise[NOISE_RANDOM] * float(biome.numBillboards) ) );
+    billboardIndex = min(billboardIndex, biome.firstBillboardIndex + biome.numBillboards - 1);
+
+    oe_landcover_Billboard billboard;
+    oe_landcover_getBillboard(billboardIndex, billboard);
+    
+    // pass the billboard's array index along to the fragment shader.
+    oe_landcover_arrayIndex = float(billboard.arrayIndex);
+    
+	
+    // push the falloff closer to the max distance.
+    float falloff = 1.0-(nRange*nRange*nRange);
+
+    // billboard width, which shrinks into the distance
+    float width = billboard.width * falloff * sizeScale;
+    
+    float height = billboard.height * falloff * sizeScale;
+
+    // vary the height of each instance and shrink it as it disappears into the distance.
+    // TODO: consider parameterizing this so we can toggle the feature
+    //height *= sizeScale;
+
+    // shrink land cover as it dissappears into the distance:
+    //height *= falloff;
+
+	// compute the billboard corners in view space.
+    vec4 LL, LR, UL, UR;
+    
+    if ( oe_isShadowCamera == false )
+    {
+        vec3 tangentVector = normalize(cross(vec3(0,0,-1), up_view));
+        vec3 halfWidthTangentVector = tangentVector * 0.5 * width;
+        vec3 heightVector = up_view*height;
+        
+        LL = vec4(center_view.xyz - halfWidthTangentVector, 1.0);
+        LR = vec4(center_view.xyz + halfWidthTangentVector, 1.0);
+        UL = vec4(LL.xyz + heightVector, 1.0);
+        UR = vec4(LR.xyz + heightVector, 1.0);
+                      
+        // TODO: animate based on wind parameters.
+        float nw = noise[NOISE_SMOOTH];
+        float wind = width*oe_landcover_windFactor*nw;
+        UL.x += oe_landcover_applyWind(osg_FrameTime*(1+nw), wind, UL.x);
+        UR.x += oe_landcover_applyWind(osg_FrameTime*(1-nw), wind, tileUV.t);
+    
+        // Color variation, brightness, and contrast:
+        vec3 color = vec3( noise[NOISE_RANDOM_2] );
+        color = ( ((color - 0.5) * oe_landcover_contrast + 0.5) * oe_landcover_brightness);
+
+        vp_Color = vec4(color*oe_landcover_ao, falloff);
+
+        // calculates normals:
+        vec3 faceNormalVector = normalize(cross(tangentVector, heightVector));
+        float blend = 0.25 + (noise[NOISE_RANDOM_2]*0.25);
+        vec3 Lnormal = mix(-tangentVector, faceNormalVector, blend);
+        vec3 Rnormal = mix( tangentVector, faceNormalVector, blend);
+
+        gl_Position = LL;
+        oe_landcover_texCoord = vec2(0,0);
+        vp_Normal = Lnormal;
+        VP_EmitViewVertex();
+    
+        gl_Position = LR;
+        oe_landcover_texCoord = vec2(1,0);
+        vp_Normal = Rnormal;
+        VP_EmitViewVertex();
+
+        vp_Color = vec4(color, falloff);      
+
+        gl_Position = UL;
+        oe_landcover_texCoord = vec2(0,1);
+        vp_Normal = Lnormal;
+        VP_EmitViewVertex();
+
+        oe_landcover_texCoord = vec2(1,1);
+        vp_Normal = Rnormal;
+        gl_Position = UR;
+        VP_EmitViewVertex();
+                    
+        EndPrimitive();
+    }
+    else
+    {
+        // generating cross-hatch geometry (for shadowing)
+
+        vec3 eastVector = gl_NormalMatrix * vec3(1,0,0);
+        vec3 halfWidthTangentVector = cross(eastVector, up_view) * 0.5 * width;
+        vec3 heightVector = up_view*height;
+
+        vp_Color = vec4(1,1,1,falloff);
+
+        for(int i=0; i<2; ++i)
+        {
+            LL = vec4(center_view.xyz - halfWidthTangentVector, 1.0);
+            LR = vec4(center_view.xyz + halfWidthTangentVector, 1.0);
+            UL = vec4(LL.xyz + heightVector, 1.0);
+            UR = vec4(LR.xyz + heightVector, 1.0);
+    
+            gl_Position = LL;
+            oe_landcover_texCoord = vec2(0,0);
+            VP_EmitViewVertex();
+    
+            gl_Position = LR;
+            oe_landcover_texCoord = vec2(1,0);
+            VP_EmitViewVertex();    
+
+            gl_Position = UL;
+            oe_landcover_texCoord = vec2(0,1);
+            VP_EmitViewVertex();
+
+            oe_landcover_texCoord = vec2(1,1);
+            gl_Position = UR;
+            VP_EmitViewVertex();
+                    
+            EndPrimitive();
+
+            halfWidthTangentVector = cross(halfWidthTangentVector, up_view);
+        }
+    }
+}
diff --git a/src/osgEarthSplat/LandCover.TCS.glsl b/src/osgEarthSplat/LandCover.TCS.glsl
new file mode 100644
index 0000000..933ebff
--- /dev/null
+++ b/src/osgEarthSplat/LandCover.TCS.glsl
@@ -0,0 +1,55 @@
+#version 400
+
+/**
+ * TCS that assigns a patch grid density.
+ */
+ 
+#pragma vp_name       LandCover tessellation control shader
+#pragma vp_entryPoint oe_landcover_configureTess
+#pragma vp_location   tess_control
+
+layout(vertices=3) out;
+
+uniform float oe_landcover_density;
+
+// per-vertex tile coordinates
+vec4 oe_layer_tilec;
+
+// SDK function to sample the coverage data
+int oe_landcover_getBiomeIndex(in vec4);
+
+// SDK function to load per-vertex data
+void VP_LoadVertex(in int);
+
+// MAIN ENTRY POINT                
+void oe_landcover_configureTess()
+{
+	if (gl_InvocationID == 0)
+	{
+        float d = oe_landcover_density;
+
+        VP_LoadVertex(0);
+        if ( oe_landcover_getBiomeIndex(oe_layer_tilec) >= 0 ) {
+            d = oe_landcover_density;
+        }
+        else {
+            VP_LoadVertex(1);
+            if ( oe_landcover_getBiomeIndex(oe_layer_tilec) >= 0 ) {
+                d = oe_landcover_density;
+                VP_LoadVertex(0);
+            }
+            else {
+                VP_LoadVertex(2);
+                if ( oe_landcover_getBiomeIndex(oe_layer_tilec) >= 0 ) {
+                    d = oe_landcover_density;
+                    VP_LoadVertex(0);
+                }
+            }
+        }
+
+        gl_TessLevelOuter[0] = d;
+        gl_TessLevelOuter[1] = d;
+        gl_TessLevelOuter[2] = d;
+        gl_TessLevelInner[0] = d;
+	}
+}
diff --git a/src/osgEarthSplat/LandCover.TES.glsl b/src/osgEarthSplat/LandCover.TES.glsl
new file mode 100644
index 0000000..6f465e4
--- /dev/null
+++ b/src/osgEarthSplat/LandCover.TES.glsl
@@ -0,0 +1,50 @@
+#version 410
+
+#pragma vp_name       LandCover TES Shader
+#pragma vp_entryPoint oe_landcover_tessellate
+#pragma vp_location   tess_eval
+
+// osgEarth terrain is always CCW winding
+layout(triangles, fractional_odd_spacing, ccw) in;
+
+// Internal helpers:
+void VP_Interpolate3();
+void VP_EmitVertex();
+
+float VP_Interpolate3(float a, float b, float c) 
+{
+    return dot(gl_TessCoord.xyz, vec3(a,b,c));
+}
+
+vec2 VP_Interpolate3(vec2 a, vec2 b, vec2 c) 
+{
+    return vec2(dot(gl_TessCoord.xyz, vec3(a.x,b.x,c.x)),
+	dot(gl_TessCoord.xyz, vec3(a.y,b.y,c.y)));
+}
+
+vec3 VP_Interpolate3(vec3 a, vec3 b, vec3 c) 
+{
+    return vec3(dot(gl_TessCoord.xyz, vec3(a.x,b.x,c.x)),
+	dot(gl_TessCoord.xyz, vec3(a.y,b.y,c.y)),
+	dot(gl_TessCoord.xyz, vec3(a.z,b.z,c.z)));
+}
+
+vec4 VP_Interpolate3(vec4 a, vec4 b, vec4 c) 
+{
+    return vec4(dot(gl_TessCoord.xyz, vec3(a.x,b.x,c.x)),
+				dot(gl_TessCoord.xyz, vec3(a.y,b.y,c.y)),
+				dot(gl_TessCoord.xyz, vec3(a.z,b.z,c.z)),
+				dot(gl_TessCoord.xyz, vec3(a.w,b.w,c.w)));
+}
+
+                
+vec3 vp_Normal;
+
+// simplest possible pass-though:
+void oe_landcover_tessellate()
+{
+    VP_Interpolate3();
+    // Must re-normalize the normal vector since interpolation was linear?
+	//vp_Normal = normalize(vp_Normal);
+    VP_EmitVertex();
+}
diff --git a/src/osgEarthSplat/LandCover.cpp b/src/osgEarthSplat/LandCover.cpp
new file mode 100644
index 0000000..fa0f5f0
--- /dev/null
+++ b/src/osgEarthSplat/LandCover.cpp
@@ -0,0 +1,438 @@
+#include "LandCover"
+#include "Coverage"
+#include "SplatCatalog"
+#include "SplatCoverageLegend"
+
+#include <osgEarth/Map>
+#include <osgEarth/ImageLayer>
+#include <osgEarth/ImageUtils>
+#include <osgEarthSymbology/BillboardSymbol>
+#include <osgEarthSymbology/BillboardResource>
+
+#include <osg/Texture2DArray>
+
+using namespace osgEarth;
+using namespace osgEarth::Splat;
+using namespace osgEarth::Symbology;
+
+#define LC "[LandCover] "
+
+bool
+LandCover::configure(const ConfigOptions& conf, const Map* map, const osgDB::Options* dbo)
+{
+    LandCoverOptions in( conf );
+    
+    if ( in.library().isSet() )
+    {
+        _lib = new ResourceLibrary( "default", in.library().get() );
+        if ( !_lib->initialize( dbo ) )
+        {
+            OE_WARN << LC << "Failed to load resource library \"" << in.library()->full() << "\"\n";
+            return false;
+        }
+    }
+
+    if ( in.layers().empty() )
+    {
+        OE_WARN << LC << "No land cover layers defined\n";
+        return false;
+    }
+    else
+    {
+        for(int i=0; i<in.layers().size(); ++i)
+        {
+            osg::ref_ptr<LandCoverLayer> layer = new LandCoverLayer();
+
+            if ( layer->configure( in.layers().at(i), dbo ) )
+            {
+                _layers.push_back( layer.get() );
+                OE_INFO << LC << "Configured land cover layer \"" << layer->getName() << "\"\n";
+            }
+            else
+            {
+                OE_WARN << LC << "Land cover layer \"" << layer->getName() << "\" is improperly configured\n";
+                return false;
+            }
+        }
+    }
+
+    if ( in.maskLayerName().isSet() )
+    {
+        ImageLayer* layer = map->getImageLayerByName( in.maskLayerName().get() );
+        if ( layer )
+        {
+            setMaskLayer( layer );
+        }
+        else
+        {
+            OE_WARN << LC << "Masking layer \"" << in.maskLayerName().get() << "\" not found in the map." << std::endl;
+            return false;
+        }
+    }
+
+    return true;
+}
+
+
+//............................................................................
+
+bool
+LandCoverLayer::configure(const ConfigOptions& conf, const osgDB::Options* dbo)
+{
+    LandCoverLayerOptions in( conf );
+
+    if ( in.name().isSet() )
+        setName( in.name().get() );
+    if ( in.lod().isSet() )
+        setLOD( in.lod().get() );
+    if ( in.castShadows().isSet() )
+        setCastShadows( in.castShadows().get() );
+    if ( in.maxDistance().isSet() )
+        setMaxDistance( in.maxDistance().get() );
+    if ( in.density().isSet() )
+        setDensity( in.density().get() );
+    if ( in.fill().isSet() )
+        setFill( in.fill().get() );
+    if ( in.wind().isSet() )
+        setWind( in.wind().get() );
+    if ( in.brightness().isSet() )
+        setBrightness( in.brightness().get() );
+    if ( in.contrast().isSet() )
+        setContrast( in.contrast().get() );
+
+    if ( in.biomes().size() == 0 )
+    {
+        OE_WARN << LC << "No biomes defined in layer \"" << getName() << "\"\n";
+        return false;
+    }
+
+    for(int i=0; i<in.biomes().size(); ++i)
+    {
+        osg::ref_ptr<LandCoverBiome> biome = new LandCoverBiome();
+
+        if ( biome->configure( in.biomes().at(i), dbo ) )
+        {
+            _biomes.push_back( biome.get() );
+        }
+        else
+        {
+            OE_WARN << LC << "One of the biomes in layer \"" << getName() << "\" is improperly configured\n";
+            return false;
+        }
+    }
+
+    return true;
+}
+
+int
+LandCoverLayer::getTotalNumBillboards() const
+{
+    int count = 0;
+    for(int i=0; i<getBiomes().size(); ++i)
+    {
+        count += getBiomes().at(i)->getBillboards().size();
+    }
+    return count;
+}
+
+osg::StateSet*
+LandCoverLayer::getOrCreateStateSet()
+{
+    if ( !_stateSet.valid() )
+        _stateSet = new osg::StateSet();
+    return _stateSet.get();
+}
+
+osg::Shader*
+LandCoverLayer::createShader() const
+{
+    std::stringstream biomeBuf;
+    std::stringstream billboardBuf;
+
+    int totalBillboards = getTotalNumBillboards();
+
+    // encode all the biome data.
+    biomeBuf << 
+        "struct oe_landcover_Biome { \n"
+        "    int firstBillboardIndex; \n"
+        "    int numBillboards; \n"
+        "    float density; \n"
+        "    float fill; \n"
+        "    vec2 maxWidthHeight; \n"
+        "}; \n"
+
+        "const oe_landcover_Biome oe_landcover_biomes[" << getBiomes().size() << "] = oe_landcover_Biome[" << getBiomes().size() << "] ( \n";
+
+    billboardBuf <<
+        "struct oe_landcover_Billboard { \n"
+        "    int arrayIndex; \n"
+        "    float width; \n"
+        "    float height; \n"
+        "}; \n"
+
+        "const oe_landcover_Billboard oe_landcover_billboards[" << totalBillboards << "] = oe_landcover_Billboard[" << totalBillboards << "](\n";
+    
+    int index = 0;
+    for(int i=0; i<getBiomes().size(); ++i)
+    {
+        const LandCoverBiome* biome = getBiomes().at(i).get();
+
+        float maxWidth = 0.0f, maxHeight = 0.0f;
+        
+        int firstIndex = index;
+
+        for(int j=0; j<biome->getBillboards().size(); ++j)
+        {
+            const LandCoverBillboard& bb = biome->getBillboards().at(j);
+
+            billboardBuf
+                << "    oe_landcover_Billboard("
+                << index 
+                << ", float(" << bb._width << ")"
+                << ", float(" << bb._height << ")"
+                << ")";
+            
+            ++index;
+            if ( index < totalBillboards )
+                billboardBuf << ",\n";
+
+            maxWidth = std::max(maxWidth, bb._width);
+            maxHeight = std::max(maxHeight, bb._height);
+        }
+
+        // We multiply the height x 2 below because billboards have their origin
+        // at the bottom center of the image. The GPU culling code considers the
+        // distance from this anchor point. For width, it's in the middle, but for
+        // height, it's at the bottom so we need to double it. It doubles in both
+        // directions, but that's OK since we are rarely if ever going to GPU-cull
+        // a billboard at the top of the viewport. -gw
+
+        biomeBuf << "    oe_landcover_Biome(" 
+            << firstIndex << ", "
+            << biome->getBillboards().size() 
+            << ", float(" << getDensity() << ")"
+            << ", float(" << getFill() << ")"
+            << ", vec2(float(" << maxWidth << "),float(" << maxHeight*2.0f << ")))";
+
+        if ( (i+1) < getBiomes().size() )
+            biomeBuf << ",\n";
+    }
+
+    biomeBuf
+        << "\n);\n";
+
+    billboardBuf
+        << "\n); \n";
+
+    biomeBuf 
+        << "void oe_landcover_getBiome(in int biomeIndex, out oe_landcover_Biome biome) { \n"
+        << "    biome = oe_landcover_biomes[biomeIndex]; \n"
+        << "} \n";
+        
+    billboardBuf
+        << "void oe_landcover_getBillboard(in int billboardIndex, out oe_landcover_Billboard billboard) { \n"
+        << "    billboard = oe_landcover_billboards[billboardIndex]; \n"
+        << "} \n";
+    
+    osg::ref_ptr<ImageLayer> layer;
+
+    osg::Shader* shader = new osg::Shader();
+    shader->setName( "LandCoverLayer" );
+    shader->setShaderSource( Stringify() << "#version 330\n" << biomeBuf.str() << "\n" << billboardBuf.str() );
+    return shader;
+}
+
+osg::Shader*
+LandCoverLayer::createPredicateShader(const Coverage* coverage) const
+{
+    const char* defaultCode = "int oe_landcover_getBiomeIndex(in vec4 coords) { return -1; }\n";
+
+    std::stringstream buf;
+    buf << "#version 330\n";
+    
+    osg::ref_ptr<ImageLayer> layer;
+
+    if ( !coverage )
+    {
+        buf << defaultCode;
+        OE_INFO << LC << "No coverage; generating default coverage predicate\n";
+    }
+    else if ( !coverage->getLegend() )
+    {
+        buf << defaultCode;
+        OE_INFO << LC << "No legend; generating default coverage predicate\n";
+    }
+    else if ( !coverage->lockLayer(layer) )
+    {
+        buf << defaultCode;
+        OE_INFO << LC << "No classification layer; generating default coverage predicate\n";
+    }
+    else
+    {
+        const std::string& sampler = layer->shareTexUniformName().get();
+        const std::string& matrix  = layer->shareTexMatUniformName().get();
+
+        buf << "uniform sampler2D " << sampler << ";\n"
+            << "uniform mat4 " << matrix << ";\n"
+            << "int oe_landcover_getBiomeIndex(in vec4 coords) { \n"
+            << "    float value = textureLod(" << sampler << ", (" << matrix << " * coords).st, 0).r;\n";
+
+        for(int biomeIndex=0; biomeIndex<getBiomes().size(); ++biomeIndex)
+        {
+            const LandCoverBiome* biome = getBiomes().at(biomeIndex).get();
+
+            if ( !biome->getClasses().empty() )
+            {
+                StringVector classes;
+                StringTokenizer(biome->getClasses(), classes, " ", "\"", false);
+
+                for(int i=0; i<classes.size(); ++i)
+                {
+                    std::vector<const CoverageValuePredicate*> predicates;
+                    if ( coverage->getLegend()->getPredicatesForClass(classes[i], predicates) )
+                    {
+                        for(std::vector<const CoverageValuePredicate*>::const_iterator p = predicates.begin();
+                            p != predicates.end(); 
+                            ++p)
+                        {
+                            const CoverageValuePredicate* predicate = *p;
+
+                            if ( predicate->_exactValue.isSet() )
+                            {
+                                buf << "    if (value == " << predicate->_exactValue.get() << ") return " << biomeIndex << "; \n";
+                            }
+                            else if ( predicate->_minValue.isSet() && predicate->_maxValue.isSet() )
+                            {
+                                buf << "    if (value >= " << predicate->_minValue.get() << " && value <= " << predicate->_maxValue.get() << ") return " << biomeIndex << "; \n";
+                            }
+                            else if ( predicate->_minValue.isSet() )
+                            {
+                                buf << "    if (value >= " << predicate->_minValue.get() << ")  return " << biomeIndex << "; \n";
+                            }
+                            else if ( predicate->_maxValue.isSet() )
+                            {
+                                buf << "    if (value <= " << predicate->_maxValue.get() << ") return " << biomeIndex << "; \n";
+                            }
+
+                            else 
+                            {
+                                OE_WARN << LC << "Class \"" << classes[i] << "\" found, but no exact/min/max value was set in the legend\n";
+                            }
+                        }
+                    }
+                    else
+                    {
+                        OE_WARN << LC << "Class \"" << classes[i] << "\" not found in the legend!\n";
+                    }
+                }
+            }
+        }
+        buf << "    return -1; \n";
+        buf << "}\n";
+    }
+    
+    osg::Shader* shader = new osg::Shader();
+    shader->setName("oe Landcover predicate function");
+    shader->setShaderSource( buf.str() );
+
+    return shader;
+}
+
+//............................................................................
+
+bool
+LandCoverBiome::configure(const ConfigOptions& conf, const osgDB::Options* dbo)
+{
+    LandCoverBiomeOptions in( conf );
+
+    if ( in.biomeClasses().isSet() )
+        setClasses( in.biomeClasses().get() );
+
+    for(SymbolVector::const_iterator i = in.symbols().begin(); i != in.symbols().end(); ++i)
+    {
+        const BillboardSymbol* bs = dynamic_cast<BillboardSymbol*>( i->get() );
+        if ( bs )
+        {
+            URI imageURI = bs->url()->evalURI();
+
+            osg::Image* image = const_cast<osg::Image*>( bs->getImage() );
+            if ( !image )
+            {
+                image = imageURI.getImage(dbo);
+            }
+
+            if ( image )
+            {
+                getBillboards().push_back( LandCoverBillboard(image, bs->width().get(), bs->height().get()) );
+            }
+            else
+            {
+                OE_WARN << LC << "Failed to load billboard image from \"" << imageURI.full() << "\"\n";
+            }
+        } 
+        else
+        {
+            OE_WARN << LC << "Unrecognized symbol in land cover biome\n";
+        }
+    }
+
+    if ( getBillboards().size() == 0 )
+    {
+        OE_WARN << LC << "A biome failed to install any billboards.\n";
+        return false;
+    }
+
+    return true;
+}
+
+osg::Texture*
+LandCoverLayer::createTexture() const
+{
+    osg::Texture2DArray* tex = new osg::Texture2DArray();
+
+    int arrayIndex = 0;
+    float s = -1.0f, t = -1.0f;
+
+    for(int b=0; b<getBiomes().size(); ++b)
+    {
+        const LandCoverBiome* biome = getBiomes().at(b);
+
+        for(int i=0; i<biome->getBillboards().size(); ++i, ++arrayIndex)
+        {
+            const LandCoverBillboard& bb = biome->getBillboards().at(i);
+
+            osg::ref_ptr<osg::Image> im;
+
+            if ( s < 0 )
+            {
+                s  = bb._image->s();
+                t  = bb._image->t();
+                im = bb._image.get();
+                tex->setTextureSize(s, t, getTotalNumBillboards());                              
+            }
+            else
+            {
+                if ( bb._image->s() != s || bb._image->t() != t )
+                {
+                    ImageUtils::resizeImage( bb._image.get(), s, t, im );
+                }
+                else
+                {
+                    im = bb._image.get();
+                }
+            }
+
+            tex->setImage( arrayIndex, im.get() );
+        }
+    }
+
+    tex->setFilter(tex->MIN_FILTER, tex->NEAREST_MIPMAP_LINEAR);
+    tex->setFilter(tex->MAG_FILTER, tex->LINEAR);
+    tex->setWrap  (tex->WRAP_S, tex->CLAMP_TO_EDGE);
+    tex->setWrap  (tex->WRAP_T, tex->CLAMP_TO_EDGE);
+    tex->setUnRefImageDataAfterApply( true );
+    tex->setMaxAnisotropy( 4.0 );
+    tex->setResizeNonPowerOfTwoHint( false );
+
+    return tex;
+}
diff --git a/src/osgEarthSplat/LandCoverTerrainEffect b/src/osgEarthSplat/LandCoverTerrainEffect
new file mode 100644
index 0000000..0842f55
--- /dev/null
+++ b/src/osgEarthSplat/LandCoverTerrainEffect
@@ -0,0 +1,87 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+* Copyright 2008-2012 Pelican Mapping
+* http://osgearth.org
+*
+* osgEarth is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* 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.
+*
+* You should have received a copy of the GNU Lesser General Public License
+* along with this program.  If not, see <http://www.gnu.org/licenses/>
+*/
+#ifndef OSGEARTH_SPLAT_LANDCOVER_TERRAIN_EFFECT_H
+#define OSGEARTH_SPLAT_LANDCOVER_TERRAIN_EFFECT_H
+
+#include "Export"
+#include "Coverage"
+#include "Zone"
+#include "LandCoverTilePatchCallback"
+
+#include <osgEarth/TerrainEffect>
+#include <osg/Uniform>
+#include <osgDB/Options>
+
+using namespace osgEarth;
+
+namespace osgEarth { namespace Splat
+{
+    /**
+     * Effect that renders land cover data (trees, grass, rocks, etc.)
+     */
+    class OSGEARTHSPLAT_EXPORT LandCoverTerrainEffect : public TerrainEffect
+    {
+    public:
+        /** constructor */
+        LandCoverTerrainEffect();
+
+        /**
+         * Sets the OSG DB options to use when performing I/O
+         */
+        void setDBOptions(const osgDB::Options* dbo);
+
+        /**
+         * Sets the coverage/surface zones.
+         */
+        void setZones(const Zones& zones) { _zones = zones; }
+        const Zones& getZones() const { return _zones; }
+
+        /**
+         * Sets the coverage source. This is optional, if you do not install
+         * a coverage source the land cover will render everywhere unconstrained.
+         */
+        void setCoverage(Coverage* coverage) { _coverage = coverage; }
+        Coverage* getCoverage() const { return _coverage.get(); }
+
+    public: // TerrainEffect interface
+
+        void onInstall(TerrainEngineNode* engine);
+
+        void onUninstall(TerrainEngineNode* engine);
+
+
+    protected:
+        virtual ~LandCoverTerrainEffect() { }
+
+        osg::ref_ptr<const osgDB::Options> _dbo;
+
+        osg::ref_ptr<Coverage> _coverage;
+        Zones _zones;
+        int _noiseTexUnit;
+        int _landCoverTexUnit;
+
+        osg::ref_ptr<LandCoverTilePatchCallback> _tilePatchCallback;
+    };
+
+} } // namespace osgEarth::Splat
+
+#endif // OSGEARTH_SPLAT_LANDCOVER_TERRAIN_EFFECT_H
diff --git a/src/osgEarthSplat/LandCoverTerrainEffect.cpp b/src/osgEarthSplat/LandCoverTerrainEffect.cpp
new file mode 100644
index 0000000..40e9b17
--- /dev/null
+++ b/src/osgEarthSplat/LandCoverTerrainEffect.cpp
@@ -0,0 +1,238 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+* Copyright 2008-2012 Pelican Mapping
+* http://osgearth.org
+*
+* osgEarth is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* 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.
+*
+* You should have received a copy of the GNU Lesser General Public License
+* along with this program.  If not, see <http://www.gnu.org/licenses/>
+*/
+#include "LandCoverTerrainEffect"
+#include "SplatOptions"
+#include "NoiseTextureFactory"
+
+#include <osgEarth/Registry>
+#include <osgEarth/Capabilities>
+#include <osgEarth/VirtualProgram>
+#include <osgEarth/TerrainEngineNode>
+#include <osgEarth/URI>
+#include <osgEarth/ShaderLoader>
+#include <osgEarth/ImageUtils>
+
+#include <osg/Texture2D>
+#include <osg/BlendFunc>
+#include <osg/Multisample>
+#include <osgUtil/Optimizer>
+
+#include "SplatShaders"
+
+#define LC "[LandCoverTerrainEffect] "
+
+using namespace osgEarth;
+using namespace osgEarth::Splat;
+
+LandCoverTerrainEffect::LandCoverTerrainEffect() :
+_noiseTexUnit    ( -1 ),
+_landCoverTexUnit( -1 )
+{
+    //nop
+}
+
+void
+LandCoverTerrainEffect::setDBOptions(const osgDB::Options* dbo)
+{
+    _dbo = dbo;
+}
+
+void
+LandCoverTerrainEffect::onInstall(TerrainEngineNode* engine)
+{
+    if ( !engine )
+        return;
+
+    if ( engine )
+    {
+        // first make sure there is land cover data available:
+        bool landCoverActive = false;
+        for(Zones::const_iterator z = _zones.begin(); z != _zones.end(); ++z)
+        {
+            Zone* zone = z->get();
+            LandCover* landcover = zone->getLandCover();
+            if ( landcover )
+            {
+                landCoverActive = true;
+            }
+        }
+
+        if ( landCoverActive )
+        {
+            // install a noise texture if we haven't already.
+            osg::StateSet* terrainStateSet = engine->getOrCreateStateSet();
+
+            // check whether it's already installed by another extension:
+            if ( terrainStateSet->getUniform("oe_splat_noiseTex") == 0L )
+            {
+                // reserve a texture unit:
+                if (engine->getResources()->reserveTextureImageUnit(_noiseTexUnit, "Splat Noise"))
+                {
+                    NoiseTextureFactory noise;
+                    terrainStateSet->setTextureAttribute( _noiseTexUnit, noise.create(256u, 4u) );
+                    terrainStateSet->addUniform( new osg::Uniform("oe_splat_noiseTex", _noiseTexUnit) );
+                }
+                else
+                {
+                    OE_WARN << LC << "No texture image unit available for LandCover Noise. Aborting.\n";
+                    return;
+                }
+            }
+            
+            int _landCoverTexUnit;
+            if ( !engine->getResources()->reserveTextureImageUnit(_landCoverTexUnit, "LandCover") )
+            {
+                OE_WARN << LC << "No texture image unit available for LandCover." << std::endl;
+                return;
+            }
+
+            // The patch callback that will render the land cover:
+            _tilePatchCallback = new LandCoverTilePatchCallback();
+            _tilePatchCallback->_zones = _zones;
+
+            engine->addTilePatchCallback( _tilePatchCallback.get() );
+
+            for(Zones::iterator z = _zones.begin(); z != _zones.end(); ++z)
+            {
+                Zone* zone = z->get();
+                LandCover* landCover = zone->getLandCover();
+                if ( landCover )
+                {
+                    for(LandCoverLayers::iterator i = landCover->getLayers().begin();
+                        i != landCover->getLayers().end();
+                        ++i)
+                    {
+                        LandCoverLayer* layer = i->get();
+                        if ( layer )
+                        {
+                            if ( !layer->getBiomes().empty() || layer->getTotalNumBillboards() > 0 )
+                            {
+                                osg::StateSet* stateset = layer->getOrCreateStateSet();
+
+                                bool useMask = (landCover->getMaskLayer() != 0L);
+
+                                // Install the land cover shaders on the state set
+                                VirtualProgram* vp = VirtualProgram::getOrCreate(stateset);
+                                vp->setName("Land Cover (" + layer->getName() + ")");
+                                LandCoverShaders shaders;
+                                if ( useMask )
+                                {
+                                    shaders.replace("MASK_SAMPLER", landCover->getMaskLayer()->shareTexUniformName().get());
+                                    shaders.replace("MASK_TEXTURE", landCover->getMaskLayer()->shareTexMatUniformName().get());
+                                }
+                                shaders.loadAll( vp, _dbo.get() );
+
+                                // Generate the coverage acceptor shader
+                                osg::Shader* covTest = layer->createPredicateShader( getCoverage() );
+                                covTest->setName( covTest->getName() + "_GEOMETRY" );
+                                covTest->setType( osg::Shader::GEOMETRY );
+                                vp->setShader( covTest );
+
+                                osg::Shader* covTest2 = layer->createPredicateShader( getCoverage() );
+                                covTest->setName( covTest->getName() + "_TESSCONTROL" );
+                                covTest2->setType( osg::Shader::TESSCONTROL );
+                                vp->setShader( covTest2 );
+
+                                osg::ref_ptr<osg::Shader> layerShader = layer->createShader();
+                                layerShader->setType( osg::Shader::GEOMETRY );
+                                vp->setShader( layerShader );
+
+                                OE_INFO << LC << "Adding land cover layer: " << layer->getName() << " to Zone " << zone->getName() << " at LOD " << layer->getLOD() << "\n";
+
+                                // Install the uniforms
+                                stateset->addUniform( new osg::Uniform("oe_landcover_windFactor", layer->getWind()) );
+                                stateset->addUniform( new osg::Uniform("oe_landcover_noise", 1.0f) );
+                                stateset->addUniform( new osg::Uniform("oe_landcover_ao", 0.5f) );
+                                stateset->addUniform( new osg::Uniform("oe_landcover_exposure", 1.0f) );
+                    
+                                stateset->addUniform( new osg::Uniform("oe_landcover_density",     layer->getDensity()) );
+                                stateset->addUniform( new osg::Uniform("oe_landcover_fill",        layer->getFill()) );
+                                stateset->addUniform( new osg::Uniform("oe_landcover_maxDistance", layer->getMaxDistance()) );
+
+                                stateset->addUniform( new osg::Uniform("oe_landcover_brightness",  layer->getBrightness()) );
+                                stateset->addUniform( new osg::Uniform("oe_landcover_contrast",    layer->getContrast()) );
+
+                                stateset->addUniform( new osg::Uniform("oe_landcover_useMask", useMask) );
+
+                                // enable alpha-to-coverage multisampling for vegetation.
+                                stateset->setMode(GL_SAMPLE_ALPHA_TO_COVERAGE_ARB, 1);
+
+                                // uniform that communicates the availability of multisampling.
+                                stateset->addUniform( new osg::Uniform(
+                                    "oe_terrain_hasMultiSamples",
+                                    osg::DisplaySettings::instance()->getMultiSamples()) );
+
+                                stateset->setAttributeAndModes(
+                                    new osg::BlendFunc(GL_ONE, GL_ZERO, GL_ONE, GL_ZERO),
+                                    osg::StateAttribute::OVERRIDE );
+
+                                stateset->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
+
+                                osg::Texture* tex = layer->createTexture();
+
+                                stateset->setTextureAttribute(_landCoverTexUnit, tex);
+                                stateset->addUniform(new osg::Uniform("oe_landcover_texArray", _landCoverTexUnit) );
+                            }
+                            else
+                            {
+                                OE_WARN << LC << "ILLEGAL: land cover layer with no biomes or no billboards defined\n";
+                            }
+                        }
+                        else
+                        {
+                            OE_WARN << LC << "ILLEGAL: empty layer found in land cover layer list\n";
+                        }
+                    }
+                }
+                else
+                {
+                    // not an error.
+                    OE_DEBUG << LC << "zone contains no land cover information\n";
+                }
+            }
+        }
+        else
+        {
+            OE_DEBUG << LC << "No land cover information found\n";
+        }
+    }
+}
+
+
+
+void
+LandCoverTerrainEffect::onUninstall(TerrainEngineNode* engine)
+{
+    if ( engine )
+    {
+        if ( _tilePatchCallback.valid() )
+        {
+            engine->removeTilePatchCallback( _tilePatchCallback.get() );
+
+            if ( _landCoverTexUnit >= 0 )
+                engine->getResources()->releaseTextureImageUnit( _landCoverTexUnit );
+
+            if ( _noiseTexUnit >= 0 )
+                engine->getResources()->releaseTextureImageUnit( _noiseTexUnit );
+        }
+    }
+}
diff --git a/src/osgEarthSplat/LandCoverTilePatchCallback b/src/osgEarthSplat/LandCoverTilePatchCallback
new file mode 100644
index 0000000..1c367ff
--- /dev/null
+++ b/src/osgEarthSplat/LandCoverTilePatchCallback
@@ -0,0 +1,58 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+* Copyright 2008-2012 Pelican Mapping
+* http://osgearth.org
+*
+* osgEarth is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* 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.
+*
+* You should have received a copy of the GNU Lesser General Public License
+* along with this program.  If not, see <http://www.gnu.org/licenses/>
+*/
+#ifndef OSGEARTH_SPLAT_LANDCOVER_TILE_PATCH_CALLBACK_H
+#define OSGEARTH_SPLAT_LANDCOVER_TILE_PATCH_CALLBACK_H
+
+#include "Export"
+#include "Zone"
+#include <osgEarth/TilePatchCallback>
+
+using namespace osgEarth;
+
+namespace osgEarth { namespace Splat
+{
+    /**
+     * Tile Patch callback that renders the land cover data.
+     */
+    class LandCoverTilePatchCallback : public TilePatchCallback
+    {
+    public:
+        /** constructor */
+        LandCoverTilePatchCallback() { }
+
+        Zones _zones;
+
+    public: // TilePatchCallback
+
+        void cull(
+            osgUtil::CullVisitor* cv,
+            const TileKey&        key,
+            osg::StateSet*        stateSet,
+            osg::Node*            tilePatch);
+
+        void release(
+            const TileKey& key);
+    };
+
+} } // namespace osgEarth::Splat
+
+#endif // OSGEARTH_SPLAT_LANDCOVER_TILE_PATCH_CALLBACK_H
diff --git a/src/osgEarthSplat/LandCoverTilePatchCallback.cpp b/src/osgEarthSplat/LandCoverTilePatchCallback.cpp
new file mode 100644
index 0000000..3a5bdbe
--- /dev/null
+++ b/src/osgEarthSplat/LandCoverTilePatchCallback.cpp
@@ -0,0 +1,89 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+* Copyright 2008-2012 Pelican Mapping
+* http://osgearth.org
+*
+* osgEarth is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* 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.
+*
+* You should have received a copy of the GNU Lesser General Public License
+* along with this program.  If not, see <http://www.gnu.org/licenses/>
+*/
+#include "LandCoverTilePatchCallback"
+#include <osgEarth/TraversalData>
+#include <osgEarth/Shadowing>
+#include <osgUtil/CullVisitor>
+
+using namespace osgEarth;
+using namespace osgEarth::Splat;
+
+#define LC "[LandCoverTilePatchCallback] "
+
+void
+LandCoverTilePatchCallback::cull(osgUtil::CullVisitor* cv,
+                                 const TileKey&        key,
+                                 osg::StateSet*        tileStateSet,
+                                 osg::Node*            tilePatch)
+{
+    RefUID* zoneIndex = VisitorData::fetch<RefUID>(*cv, "oe.LandCover.zoneIndex");
+    if ( zoneIndex && (*zoneIndex) < _zones.size() )
+    {
+        // Figure out what type of camera this is:
+        unsigned clearMask = cv->getCurrentCamera()->getClearMask();
+        bool isDepthCamera = ((clearMask & GL_COLOR_BUFFER_BIT) == 0u) && ((clearMask & GL_DEPTH_BUFFER_BIT) != 0u);
+        bool isShadowCamera = osgEarth::Shadowing::isShadowCamera(cv->getCurrentCamera());
+
+        // only consider land cover if we are capturing color OR shadow map.
+        if ( isShadowCamera || !isDepthCamera )
+        {
+            bool pushedTileStateSet = false;
+
+            //ZoneData& zone = _zones[*zoneIndex];
+            Zone* zone = _zones[*zoneIndex].get();
+
+            LandCoverLayers& layers = zone->getLandCover()->getLayers();
+            for(int i=0; i<layers.size(); ++i)
+            {
+                //LayerData& layerData = zone._layers[i];
+                LandCoverLayer* layer = layers[i].get();
+
+                if ( layer->getLOD() == key.getLOD() &&
+                    (!isShadowCamera || layer->getCastShadows()) )
+                {
+                    if ( !pushedTileStateSet )
+                    {
+                        cv->pushStateSet( tileStateSet );
+                        pushedTileStateSet = true;
+                    }
+
+                    cv->pushStateSet( layer->getStateSet() );
+
+                    tilePatch->accept( *cv );
+
+                    cv->popStateSet();
+                }
+            }
+
+            if ( pushedTileStateSet )
+            {
+                cv->popStateSet();
+            }
+        }
+    }
+}
+
+void
+LandCoverTilePatchCallback::release(const TileKey& key)
+{
+    // nop - implementation is stateless.
+}
diff --git a/src/osgEarthSplat/LandUseTileSource b/src/osgEarthSplat/LandUseTileSource
new file mode 100644
index 0000000..e4d5eac
--- /dev/null
+++ b/src/osgEarthSplat/LandUseTileSource
@@ -0,0 +1,184 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+ * Copyright 2016 Pelican Mapping
+ * http://osgearth.org
+ *
+ * osgEarth is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ */
+#ifndef OSGEARTH_SPLAT_LAND_USE_TILE_SOURCE
+#define OSGEARTH_SPLAT_LAND_USE_TILE_SOURCE 1
+
+#include <osgEarth/TileSource>
+#include <osgEarth/ImageLayer>
+#include <osgEarthUtil/SimplexNoise>
+#include <osgDB/FileNameUtils>
+#include "Export"
+
+namespace osgEarth { namespace Splat
+{
+    /**
+     * Configuration options for the land use tile source
+     */
+    class OSGEARTHSPLAT_EXPORT LandUseOptions : public osgEarth::TileSourceOptions    
+    {
+    public:
+        LandUseOptions(const osgEarth::TileSourceOptions& options)
+            : osgEarth::TileSourceOptions(options)
+        {
+            setDriver("landuse");
+            baseLOD().init( 32u );
+            warpFactor().init( 0.01f );
+            fromConfig( _conf );
+        }
+
+    public:
+        
+        /**
+         * Images layer from which to read source coverage data.
+         */
+        std::vector<ImageLayerOptions>& imageLayerOptionsVector() { return _imageLayerOptionsVec; }
+        const std::vector<ImageLayerOptions>& imageLayerOptionsVector() const { return _imageLayerOptionsVec; }
+
+        /**
+         * Amount by which to warp texture coordinates of coverage data.
+         * Try 0.01 as a starting point.
+         */
+        optional<float>& warpFactor() { return _warp; }
+        const optional<float>& warpFactor() const { return _warp; }
+
+        /**
+         * LOD at which to calculate the noise function for warping.
+         */
+        optional<unsigned>& baseLOD() { return _baseLOD; }
+        const optional<unsigned>& baseLOD() const { return _baseLOD; }
+
+        /**
+         * Bit size of the encoded data. The default is 32 (for a 32-bit signed
+         * floating point value) but you can set it to 16 if you know your data
+         * values are all within the range of a signed 16-bit float.
+         */
+        optional<unsigned>& bits() { return _bits; }
+        const optional<unsigned>& bits() const { return _bits; }
+
+    public:
+        Config getConfig() const
+        {
+            Config conf;
+            conf.addIfSet("warp",      _warp);
+            conf.addIfSet("base_lod",  _baseLOD);
+            conf.addIfSet("bits",      _bits);
+
+            // multiple
+            if ( _imageLayerOptionsVec.size() > 0 )
+            {
+                Config images("images");
+                for(std::vector<ImageLayerOptions>::const_iterator i = _imageLayerOptionsVec.begin();
+                    i != _imageLayerOptionsVec.end(); 
+                    ++i)
+                {
+                    images.add( "image", i->getConfig() );
+                }
+                conf.add( images );
+            }
+
+            return conf;
+        }
+
+    protected:
+        void mergeConfig( const Config& conf ) {
+            TileSourceOptions::mergeConfig( conf );
+            fromConfig( conf );
+        }
+
+    private:
+        void fromConfig( const Config& conf )
+        {
+            conf.getIfSet("warp", _warp);
+            conf.getIfSet("base_lod", _baseLOD);
+            conf.getIfSet("bits",      _bits);
+            
+            ConfigSet layerConfs = conf.child("images").children("image");
+            for(ConfigSet::const_iterator i = layerConfs.begin(); i != layerConfs.end(); ++i)
+            {
+                _imageLayerOptionsVec.push_back( ImageLayerOptions(*i) );
+            }
+        }
+        
+    private:
+        optional<float>                _warp;
+        optional<unsigned>             _baseLOD;
+        optional<unsigned>             _bits;
+        std::vector<ImageLayerOptions> _imageLayerOptionsVec;
+    };
+
+    /**
+     * Tile source that will read from ANOTHER tile source and perform
+     * various pre-processing syntheses operations like warping and detailing.
+     */
+    class OSGEARTHSPLAT_EXPORT LandUseTileSource : public osgEarth::TileSource
+    {
+    public:
+        LandUseTileSource(const LandUseOptions& options);
+
+    public: // TileSource
+
+        // Initialize the tile source.
+        Status initialize(const osgDB::Options* options);
+
+        // Create an image.
+        osg::Image* createImage(const osgEarth::TileKey& key, osgEarth::ProgressCallback* progress);
+
+        CachePolicy getCachePolicyHint() const;
+
+    protected:
+        virtual ~LandUseTileSource() { }
+
+        osg::ref_ptr<osgDB::Options> _dbOptions;
+        LandUseOptions               _options;        
+        osg::ref_ptr<ImageLayer>     _imageLayer;
+        ImageLayerVector             _imageLayers;
+        std::vector<float>           _warps;
+        osgEarth::Util::SimplexNoise _noiseGen;
+    };
+
+    /**
+     * Driver plugin used to load a land use tile source.
+     */
+    class OSGEARTHSPLAT_EXPORT LandUseDriver : public osgEarth::TileSourceDriver
+    {
+    public:
+        LandUseDriver()
+        {
+            supportsExtension( "osgearth_landuse", "Land Use Driver" );
+        }
+
+        virtual const char* className() const
+        {
+            return "Land Use Driver";
+        }
+
+        virtual ReadResult readObject(const std::string& file_name, const Options* options) const
+        {
+            if ( !acceptsExtension(osgDB::getLowerCaseFileExtension( file_name )))
+                return ReadResult::FILE_NOT_HANDLED;
+
+            return new LandUseTileSource( getTileSourceOptions(options) );
+        }
+    };
+
+    REGISTER_OSGPLUGIN(osgearth_landuse, LandUseDriver);
+
+} } // namespace osgEarth::Splat
+
+#endif // OSGEARTH_SPLAT_LAND_USE_TILE_SOURCE
diff --git a/src/osgEarthSplat/LandUseTileSource.cpp b/src/osgEarthSplat/LandUseTileSource.cpp
new file mode 100644
index 0000000..a5568dc
--- /dev/null
+++ b/src/osgEarthSplat/LandUseTileSource.cpp
@@ -0,0 +1,282 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+ * Copyright 2016 Pelican Mapping
+ * http://osgearth.org
+ *
+ * osgEarth is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ */
+#include "LandUseTileSource"
+#include <osgEarth/ImageLayer>
+#include <osgEarth/MapFrame>
+#include <osgEarth/Registry>
+#include <osgEarth/ImageUtils>
+#include <osgEarthUtil/SimplexNoise>
+
+using namespace osgEarth;
+using namespace osgEarth::Splat;
+
+#define LC "[LandUseTileSource] "
+
+namespace
+{
+    osg::Vec2 getSplatCoords(const TileKey& key, float baseLOD, const osg::Vec2& covUV)
+    {
+        osg::Vec2 out;
+
+        float dL = (float)key.getLOD() - baseLOD;
+        float factor = pow(2.0f, dL);
+        float invFactor = 1.0/factor;
+        out.set( covUV.x()*invFactor, covUV.y()*invFactor ); 
+
+        // For upsampling we need to calculate an offset as well
+        if ( factor >= 1.0 )
+        {
+            unsigned wide, high;
+            key.getProfile()->getNumTiles(key.getLOD(), wide, high);
+
+            float tileX = (float)key.getTileX();
+            float tileY = (float)(wide-1-key.getTileY()); // swap Y. (not done in the shader version.)
+
+            osg::Vec2 a( floor(tileX*invFactor), floor(tileY*invFactor) );
+            osg::Vec2 b( a.x()*factor, a.y()*factor );
+            osg::Vec2 c( (a.x()+1.0f)*factor, (a.y()+1.0f)*factor );
+            osg::Vec2 offset( (tileX-b.x())/(c.x()-b.x()), (tileY-b.y())/(c.y()-b.y()) );
+
+            out += offset;
+        }
+
+        return out;
+    }
+
+    osg::Vec2 warpCoverageCoords(const osg::Vec2& covIn, float noise, float warp)
+    {
+        float n1 = 2.0 * noise - 1.0;
+        return osg::Vec2(
+            osg::clampBetween( covIn.x() + n1*warp, 0.0f, 1.0f ),
+            osg::clampBetween( covIn.y() + n1*warp, 0.0f, 1.0f ) );
+    }
+
+    float getNoise(osgEarth::Util::SimplexNoise& noiseGen, const osg::Vec2& uv)
+    {
+        // TODO: check that u and v are 0..s and not 0..s-1
+        double n = noiseGen.getTiledValue(uv.x(), uv.y());
+        n = osg::clampBetween(n, 0.0, 1.0);
+        //out = n;
+        return n;
+    }
+}
+
+
+LandUseTileSource::LandUseTileSource(const LandUseOptions& options) :
+TileSource( options ),
+_options  ( options )
+{
+    //nop
+}
+
+Status
+LandUseTileSource::initialize(const osgDB::Options* dbOptions)
+{
+    _dbOptions = Registry::instance()->cloneOrCreateOptions(dbOptions);
+
+    const Profile* profile = getProfile();
+    if ( !profile )
+    {
+        profile = osgEarth::Registry::instance()->getGlobalGeodeticProfile();
+        setProfile( profile );
+    }
+
+    // load all the image layers:
+    _imageLayers.assign( _options.imageLayerOptionsVector().size(), 0L );
+    _warps.assign( _options.imageLayerOptionsVector().size(), 0.0f );
+
+    for(unsigned i=0; i<_options.imageLayerOptionsVector().size(); ++i)
+    {
+        ImageLayerOptions ilo = _options.imageLayerOptionsVector()[i];
+        ilo.cachePolicy() = CachePolicy::NO_CACHE;
+        ImageLayer* layer = new ImageLayer( ilo );
+        layer->setTargetProfileHint( profile );
+        layer->setReadOptions(_dbOptions.get());
+        layer->open();
+        _imageLayers[i] = layer;
+
+        Config conf = ilo.getConfig();
+        _warps[i] = conf.value("warp", _options.warpFactor().get());
+    }
+
+    // set up the noise generator.
+    const float F[4] = { 4.0f, 16.0f, 4.0f, 8.0f };
+    const float P[4] = { 0.8f,  0.6f, 0.8f, 0.9f };
+    const float L[4] = { 2.2f,  1.7f, 3.0f, 4.0f };
+    
+    // Configure the noise function:
+    _noiseGen.setNormalize  ( true );
+    _noiseGen.setRange      ( 0.0, 1.0 );
+    _noiseGen.setFrequency  ( F[0] );
+    _noiseGen.setPersistence( P[0] );
+    _noiseGen.setLacunarity ( L[0] );
+    _noiseGen.setOctaves    ( 8 );
+
+    return STATUS_OK;
+}
+
+CachePolicy
+LandUseTileSource::getCachePolicyHint() const
+{
+    return CachePolicy::NO_CACHE;
+}
+
+namespace
+{
+    struct ILayer 
+    {
+        GeoImage  image;
+        float     scale;
+        osg::Vec2 bias;
+        bool      valid;
+        float     warp;
+        ImageUtils::PixelReader* read;
+
+        ILayer() : valid(true), read(0L), scale(1.0f), warp(0.0f) { }
+
+        ~ILayer() { if (read) delete read; }
+
+        void load(const TileKey& key, ImageLayer* sourceLayer, float sourceWarp, ProgressCallback* progress)
+        {
+            if ( sourceLayer->getEnabled() && sourceLayer->getVisible() && sourceLayer->isKeyInRange(key) )
+            {
+                for(TileKey k = key; k.valid() && !image.valid(); k = k.createParentKey())
+                {
+                    image = sourceLayer->createImage(k, progress);
+                } 
+            }
+
+            valid = image.valid();
+
+            if ( valid )
+            {
+                scale = key.getExtent().width() / image.getExtent().width();
+                bias.x() = (key.getExtent().xMin() - image.getExtent().xMin()) / image.getExtent().width();
+                bias.y() = (key.getExtent().yMin() - image.getExtent().yMin()) / image.getExtent().height();
+
+                read = new ImageUtils::PixelReader(image.getImage());
+
+                // cannot interpolate coverage data:
+                read->setBilinear( false );
+
+                warp = sourceWarp;
+            }
+        }
+    };
+}
+
+osg::Image*
+LandUseTileSource::createImage(const TileKey&    key,
+                               ProgressCallback* progress)
+{
+    if ( _imageLayers.empty() )
+        return 0L;
+
+    std::vector<ILayer> layers(_imageLayers.size());
+
+    // Allocate the new coverage image; it will contain unnormalized values.
+    osg::Image* out = new osg::Image();
+    ImageUtils::markAsUnNormalized(out, true);
+
+    // Allocate a suitable format:
+    GLenum dataType;
+    GLint  internalFormat;
+    
+    if ( _options.bits().isSetTo(16u) )
+    {
+        // 16-bit float:
+        dataType       = GL_FLOAT;
+        internalFormat = GL_LUMINANCE16F_ARB;
+    }
+    else //if ( _options.bits().isSetTo(32u) )
+    {
+        // 32-bit float:
+        dataType       = GL_FLOAT;
+        internalFormat = GL_LUMINANCE32F_ARB;
+    }
+    
+    int tilesize = getPixelsPerTile();
+
+    out->allocateImage(tilesize, tilesize, 1, GL_LUMINANCE, dataType);
+    out->setInternalTextureFormat(internalFormat);
+
+    float noiseLOD = _options.baseLOD().get();
+    float warp     = _options.warpFactor().get();
+
+    osg::Vec2 cov;    // coverage coordinates
+    float     noise;  // noise value
+    osg::Vec2 noiseCoords;
+
+    ImageUtils::PixelWriter write( out );
+
+    float du = 1.0f / (float)(out->s()-1);
+    float dv = 1.0f / (float)(out->t()-1);
+
+    osg::Vec4 nodata;
+    if (internalFormat == GL_LUMINANCE16F_ARB)
+        nodata.set(-32768, -32768, -32768, -32768);
+    else
+        nodata.set(NO_DATA_VALUE, NO_DATA_VALUE, NO_DATA_VALUE, NO_DATA_VALUE);
+
+    for(float u=0.0f; u<=1.0f; u+=du)
+    {
+        for(float v=0.0f; v<=1.0f; v+=dv)
+        {
+            bool wrotePixel = false;
+            for(int L = layers.size()-1; L >= 0 && !wrotePixel; --L)
+            {
+                ILayer& layer = layers[L];
+                if ( !layer.valid )
+                    continue;
+
+                if ( !layer.image.valid() )
+                    layer.load(key, _imageLayers[L], _warps[L], progress);
+
+                if ( !layer.valid )
+                    continue;
+
+                osg::Vec2 cov(layer.scale*u + layer.bias.x(), layer.scale*v + layer.bias.y());
+
+                if ( cov.x() >= 0.0f && cov.x() <= 1.0f && cov.y() >= 0.0f && cov.y() <= 1.0f )
+                {
+                    // Noise is like a repeating overlay at the noiseLOD. So sample it using
+                    // straight U/V tile coordinates.
+                    noiseCoords = getSplatCoords( key, noiseLOD, osg::Vec2(u,v) );
+                    noise = getNoise( _noiseGen, noiseCoords );
+
+                    cov = warpCoverageCoords(cov, noise, layer.warp);
+
+                    osg::Vec4 texel = (*layer.read)(cov.x(), cov.y());
+                    if ( texel.r() != NO_DATA_VALUE )
+                    {
+                        write.f(texel, u, v);
+                        wrotePixel = true;
+                    }
+                }
+            }
+
+            if ( !wrotePixel )
+            {
+                write.f(nodata, u, v);
+            }
+        }
+    }
+
+    return out;
+}
diff --git a/src/osgEarthExtensions/splat/ModelSplatter b/src/osgEarthSplat/ModelSplatter
similarity index 100%
rename from src/osgEarthExtensions/splat/ModelSplatter
rename to src/osgEarthSplat/ModelSplatter
diff --git a/src/osgEarthExtensions/splat/ModelSplatter.cpp b/src/osgEarthSplat/ModelSplatter.cpp
similarity index 100%
rename from src/osgEarthExtensions/splat/ModelSplatter.cpp
rename to src/osgEarthSplat/ModelSplatter.cpp
diff --git a/src/osgEarthSplat/NoiseTextureFactory b/src/osgEarthSplat/NoiseTextureFactory
new file mode 100644
index 0000000..7c4e509
--- /dev/null
+++ b/src/osgEarthSplat/NoiseTextureFactory
@@ -0,0 +1,39 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+ * Copyright 2016 Pelican Mapping
+ * http://osgearth.org
+ *
+ * osgEarth is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ */
+#ifndef OSGEARTH_SPLAT_NOISE_TEXTURE_FACTORY
+#define OSGEARTH_SPLAT_NOISE_TEXTURE_FACTORY 1
+
+#include "Export"
+#include <osg/Texture>
+
+namespace osgEarth { namespace Splat
+{
+    using namespace osgEarth;
+    
+    class OSGEARTHSPLAT_EXPORT NoiseTextureFactory
+    {
+    public:
+        NoiseTextureFactory() { }
+
+        osg::Texture* create(unsigned dim, unsigned numChannels) const;
+    };
+
+} } // namespace osgEarth::Splat
+
+#endif // OSGEARTH_SPLAT_NOISE_TEXTURE_FACTORY
diff --git a/src/osgEarthSplat/NoiseTextureFactory.cpp b/src/osgEarthSplat/NoiseTextureFactory.cpp
new file mode 100644
index 0000000..457df95
--- /dev/null
+++ b/src/osgEarthSplat/NoiseTextureFactory.cpp
@@ -0,0 +1,119 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+ * Copyright 2016 Pelican Mapping
+ * http://osgearth.org
+ *
+ * osgEarth is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ */
+#include "NoiseTextureFactory"
+
+#include <osgEarth/ImageUtils>
+#include <osgEarth/Random>
+#include <osgEarthUtil/SimplexNoise>
+#include <osg/Texture2D>
+
+using namespace osgEarth;
+using namespace osgEarth::Splat;
+
+
+#define LC "[NoiseTextureFactory] "
+
+osg::Texture*
+NoiseTextureFactory::create(unsigned dim, unsigned chans) const
+{
+    chans = osg::clampBetween(chans, 1u, 4u);
+
+    GLenum type = chans >= 2u ? GL_RGBA : GL_LUMINANCE;
+    
+    osg::Image* image = new osg::Image();
+    image->allocateImage(dim, dim, 1, type, GL_UNSIGNED_BYTE);
+
+    // 0 = rocky mountains
+    // 1 = white noise   (not used)
+    // 2 = white noise 2 (not used)
+    // 3 = super-clumpy
+    const float F[4] = { 4.0f, 64.0f, 33.0f, 1.2f };
+    const float P[4] = { 0.8f,  1.0f,  0.9f, 0.9f };
+    const float L[4] = { 2.2f,  1.0f,  1.0f, 4.0f };
+
+    osgEarth::Random random(0, Random::METHOD_FAST);
+    
+    for(int k=0; k<chans; ++k)
+    {
+        // Configure the noise function:
+        osgEarth::Util::SimplexNoise noise;
+        noise.setNormalize( true );
+        noise.setRange( 0.0, 1.0 );
+        noise.setFrequency( F[k] );
+        noise.setPersistence( P[k] );
+        noise.setLacunarity( L[k] );
+        noise.setOctaves( 8 );
+
+        float nmin = 10.0f;
+        float nmax = -10.0f;
+
+        // write repeating noise to the image:
+        ImageUtils::PixelReader read ( image );
+        ImageUtils::PixelWriter write( image );
+        for(int t=0; t<(int)dim; ++t)
+        {
+            double rt = (double)t/(double)dim;
+            for(int s=0; s<(int)dim; ++s)
+            {
+                double rs = (double)s/(double)dim;
+                osg::Vec4f v = read(s, t);
+                double n;
+
+                if ( k == 1 || k == 2 )
+                {
+                    n = (float)random.next();
+                }
+                else
+                {
+                    n = noise.getTiledValue(rs, rt);
+                    n = osg::clampBetween(n, 0.0, 1.0);
+                }
+
+                if ( n < nmin ) nmin = n;
+                if ( n > nmax ) nmax = n;
+                
+                v[k] = n;
+                write(v, s, t);
+            }
+        }
+   
+        // histogram stretch to [0..1] for simplex noise
+        if ( k != 1 && k != 2 )
+        {
+            for(int x=0; x<(int)(dim*dim); ++x)
+            {
+                int s = x%int(dim), t = x/(int)dim;
+                osg::Vec4f v = read(s, t);
+                v[k] = osg::clampBetween((v[k]-nmin)/(nmax-nmin), 0.0f, 1.0f);
+                write(v, s, t);
+            }
+        }
+    }
+
+    // make a texture:
+    osg::Texture2D* tex = new osg::Texture2D( image );
+    tex->setWrap(tex->WRAP_S, tex->REPEAT);
+    tex->setWrap(tex->WRAP_T, tex->REPEAT);
+    tex->setFilter(tex->MIN_FILTER, tex->LINEAR_MIPMAP_LINEAR);
+    tex->setFilter(tex->MAG_FILTER, tex->LINEAR);
+    tex->setMaxAnisotropy( 4.0f );
+    tex->setUnRefImageDataAfterApply( true );
+
+    return tex;
+}
diff --git a/src/osgEarthExtensions/splat/Splat.Noise.glsl b/src/osgEarthSplat/Splat.Noise.glsl
similarity index 100%
rename from src/osgEarthExtensions/splat/Splat.Noise.glsl
rename to src/osgEarthSplat/Splat.Noise.glsl
diff --git a/src/osgEarthSplat/Splat.frag.common.glsl b/src/osgEarthSplat/Splat.frag.common.glsl
new file mode 100644
index 0000000..9a53f20
--- /dev/null
+++ b/src/osgEarthSplat/Splat.frag.common.glsl
@@ -0,0 +1,35 @@
+// begin: Splat.frag.common.glsl
+
+// TODO:
+// Encapsulate the "use normal map" define logic in the terrain SDK itself.
+
+#pragma vp_define OE_USE_NORMAL_MAP
+
+#ifdef OE_USE_NORMAL_MAP
+
+// import SDK
+vec4 oe_terrain_getNormalAndCurvature(in vec2);
+
+// normal map version:
+in vec2 oe_normalMapCoords;
+
+float oe_splat_getSlope()
+{
+    vec4 encodedNormal = oe_terrain_getNormalAndCurvature( oe_normalMapCoords );
+    vec3 normalTangent = normalize(encodedNormal.xyz*2.0-1.0);
+    return clamp((1.0-normalTangent.z)/0.8, 0.0, 1.0);
+}
+
+#else // !OE_USE_NORMAL_MAP
+
+// non- normal map version:
+in float oe_splat_slope;
+
+float oe_splat_getSlope()
+{
+    return oe_splat_slope;
+}
+
+#endif // OE_USE_NORMAL_MAP
+
+// end: Splat.frag.common.glsl
\ No newline at end of file
diff --git a/src/osgEarthSplat/Splat.frag.glsl b/src/osgEarthSplat/Splat.frag.glsl
new file mode 100644
index 0000000..78787a1
--- /dev/null
+++ b/src/osgEarthSplat/Splat.frag.glsl
@@ -0,0 +1,309 @@
+#version 330
+
+#pragma vp_entryPoint oe_splat_complex
+#pragma vp_location   fragment_coloring
+#pragma vp_order      0.4
+
+// define to activate 'edit' mode in which uniforms control
+// the splatting parameters.
+#pragma vp_define SPLAT_EDIT
+
+// define to activate GPU-generated noise instead of a noise texture.
+#pragma vp_define SPLAT_GPU_NOISE
+
+// include files
+#pragma include Splat.types.glsl
+#pragma include Splat.frag.common.glsl
+
+// ref: Splat.getRenderInfo.frag.glsl
+//oe_SplatRenderInfo oe_splat_getRenderInfo(in float value, inout oe_SplatEnv env);
+
+// from: Splat.util.glsl
+void oe_splat_getLodBlend(in float range, out float lod0, out float rangeOuter, out float rangeInner, out float clampedRange);
+vec2 oe_splat_getSplatCoords(in vec2 coords, in float lod);
+
+// from the terrain engine:
+in vec4 oe_layer_tilec;
+uniform vec4 oe_tile_key;
+
+// from the vertex shader:
+in vec2 oe_splat_covtc;
+in float oe_splat_range;
+
+// from SplatTerrainEffect:
+uniform float oe_splat_warp;
+uniform float oe_splat_blur;
+uniform sampler2D oe_splat_coverageTex;
+uniform sampler2DArray oe_splatTex;
+uniform float oe_splat_scaleOffset;
+
+uniform float oe_splat_detailRange;
+uniform float oe_splat_noiseScale;
+uniform float oe_splat_useBilinear; // 1=true, -1=false
+
+#ifdef SPLAT_EDIT
+uniform float oe_splat_brightness;
+uniform float oe_splat_contrast;
+uniform float oe_splat_threshold;
+uniform float oe_splat_minSlope;
+#endif
+
+
+uniform samplerBuffer oe_splat_coverageLUT;
+
+// reads the encoded splatting render information for a coverage value.
+// this data was encoded in Surface::createLUTBUffer().
+void oe_splat_getRenderInfo(in float value, in oe_SplatEnv env, out oe_SplatRenderInfo ri)
+{
+    const int num_lods = 26;
+    const float inv255 = 1.0/255.0;
+
+    int index = int(value)*num_lods + int(env.lod);
+
+    // fetch the splatting parameters:
+    vec4 t = texelFetch(oe_splat_coverageLUT, index);
+
+    ri.primaryIndex = t[0];
+    ri.detailIndex  = t[1];
+
+    // brightness and contrast are packed into one float:
+    ri.brightness   = trunc(t[2])/100.0;
+    ri.contrast     = fract(t[2])*100.0;
+
+    // threshold and slope are packed into one float:
+    ri.threshold    = trunc(t[3])/100.0;
+    ri.minSlope     = fract(t[3])*100.0;
+}
+
+// Warps the coverage sampling coordinates to mitigate blockiness.
+vec2 oe_splat_warpCoverageCoords(in vec2 splat_tc, in oe_SplatEnv env)
+{
+    vec2 seed = oe_splat_covtc;
+    float n1 = 2.0*env.noise.y-1.0;
+    vec2 tc = oe_splat_covtc + n1*oe_splat_warp;
+    return clamp(tc, 0.0, 1.0);
+}
+
+vec4 oe_splat_getTexel(in float index, in vec2 tc)
+{
+    return texture(oe_splatTex, vec3(tc, index));
+}
+
+// Samples a detail texel using its render info parameters.
+// Returns the weighting factor in the alpha channel.
+vec4 oe_splat_getDetailTexel(in oe_SplatRenderInfo ri, in vec2 tc, in oe_SplatEnv env)
+{
+    float hasDetail = clamp(ri.detailIndex+1.0, 0.0, 1.0); //ri.detailIndex >= 0.0 ? 1.0 : 0.0;
+
+#ifdef SPLAT_EDIT
+    float brightness = oe_splat_brightness;
+    float contrast = oe_splat_contrast;
+    float threshold = oe_splat_threshold;
+    float minSlope = oe_splat_minSlope;
+#else
+    float brightness = ri.brightness;
+    float contrast = ri.contrast;
+    float threshold = ri.threshold;
+    float minSlope = ri.minSlope;
+#endif
+
+    // start with the noise value
+    float n = env.noise.x;
+	
+    // apply slope limiter, then reclamp and threshold:
+    float s;
+    if ( env.slope >= minSlope )
+        s = 1.0;
+    else if ( env.slope < 0.1*minSlope )
+        s = 0.0;
+    else
+        s = (env.slope-0.1*minSlope)/(minSlope-0.1*minSlope);
+
+    brightness *= s;
+
+    // apply brightness and contrast, then reclamp
+    n = clamp(((n-0.5)*contrast + 0.5) * brightness, 0.0, 1.0);
+    
+    // apply final threshold:
+	n = n < threshold ? 0.0 : n;
+
+    // sample the texel and return it.
+    vec4 result = oe_splat_getTexel( ri.detailIndex, tc);
+    //vec4 result = oe_splat_getTexel( max(ri.detailIndex,0), tc);
+    return vec4(result.rgb, hasDetail*n);
+}
+
+// Generates a texel using nearest-neighbor coverage sampling.
+vec4 oe_splat_nearest(in vec2 splat_tc, inout oe_SplatEnv env)
+{
+    vec2 tc = oe_splat_covtc; //oe_splat_warpCoverageCoords(splat_tc, env);
+    float coverageValue = texture2D(oe_splat_coverageTex, tc).r;
+    oe_SplatRenderInfo ri;
+    oe_splat_getRenderInfo(coverageValue, env, ri);
+    vec4 primary = oe_splat_getTexel(ri.primaryIndex, splat_tc);
+    float detailToggle = ri.detailIndex >= 0 ? 1.0 : 0.0;
+    vec4 detail  = oe_splat_getDetailTexel(ri, splat_tc, env) * detailToggle;    
+    return vec4( mix(primary.rgb, detail.rgb, detail.a), 1.0 );
+}
+
+// Generates a texel using bilinear filtering on the coverage data.
+vec4 oe_splat_bilinear(in vec2 splat_tc, inout oe_SplatEnv env)
+{
+    vec4 texel = vec4(0,0,0,1);
+
+    //TODO: coverage warping is slow due to the noise function. Consider removing/reworking.
+    vec2 tc = oe_splat_covtc; //oe_splat_warpCoverageCoords(splat_tc, env);
+
+    float a = oe_splat_blur;
+    float pixelWidth = a/256.0; // 256 = hard-coded cov tex size //TODO 
+    float halfPixelWidth = 0.5*pixelWidth;
+    float pixelWidth2 = pixelWidth*pixelWidth;
+
+    // Find the four quantized coverage coordinates that form a box around the actual
+    // coverage coordinates, where each quantized coord is at the center of a coverage texel.
+    vec2 rem = mod(tc, pixelWidth);
+    vec2 sw;
+    sw.x = tc.x - rem.x + (rem.x >= halfPixelWidth ? halfPixelWidth : -halfPixelWidth);
+    sw.y = tc.y - rem.y + (rem.y >= halfPixelWidth ? halfPixelWidth : -halfPixelWidth); 
+    vec2 ne = sw + pixelWidth;
+    vec2 nw = vec2(sw.x, ne.y);
+    vec2 se = vec2(ne.x, sw.y);
+
+    // Calculate the weighting for each corner.
+    vec2 dsw = tc-sw;
+    vec2 dse = tc-se;
+    vec2 dne = tc-ne;
+    vec2 dnw = tc-nw;
+
+    float sw_weight = max(pixelWidth2-dot(dsw,dsw),0.0);
+    float se_weight = max(pixelWidth2-dot(dse,dse),0.0);
+    float ne_weight = max(pixelWidth2-dot(dne,dne),0.0);
+    float nw_weight = max(pixelWidth2-dot(dnw,dnw),0.0);
+
+    // normalize the weights so they total 1.0
+    float invTotalWeight = 1.0/(sw_weight+se_weight+ne_weight+nw_weight);
+    sw_weight *= invTotalWeight;
+    se_weight *= invTotalWeight;
+    ne_weight *= invTotalWeight;
+    nw_weight *= invTotalWeight;
+
+    // Sample coverage values using quantized corner coords:
+    float value_sw = texture(oe_splat_coverageTex, clamp(sw, 0.0, 1.0)).r;
+    float value_se = texture(oe_splat_coverageTex, clamp(se, 0.0, 1.0)).r;
+    float value_ne = texture(oe_splat_coverageTex, clamp(ne, 0.0, 1.0)).r;
+    float value_nw = texture(oe_splat_coverageTex, clamp(nw, 0.0, 1.0)).r;
+
+    // Build the render info data for each corner:
+    oe_SplatRenderInfo ri_sw; oe_splat_getRenderInfo(value_sw, env, ri_sw);
+    oe_SplatRenderInfo ri_se; oe_splat_getRenderInfo(value_se, env, ri_se);
+    oe_SplatRenderInfo ri_ne; oe_splat_getRenderInfo(value_ne, env, ri_ne);
+    oe_SplatRenderInfo ri_nw; oe_splat_getRenderInfo(value_nw, env, ri_nw);
+
+    // Primary splat:
+    vec3 sw_primary = oe_splat_getTexel(ri_sw.primaryIndex, splat_tc).rgb;
+    vec3 se_primary = oe_splat_getTexel(ri_se.primaryIndex, splat_tc).rgb;
+    vec3 ne_primary = oe_splat_getTexel(ri_ne.primaryIndex, splat_tc).rgb;
+    vec3 nw_primary = oe_splat_getTexel(ri_nw.primaryIndex, splat_tc).rgb;
+
+    // Detail splat - weighting is in the alpha channel
+    // TODO: Pointless to have a detail range? -gw
+    // TODO: If noise is a texture, just try to single-sample it instead
+    float detailToggle =env.range < oe_splat_detailRange ? 1.0 : 0.0;
+    vec4 sw_detail = detailToggle * oe_splat_getDetailTexel(ri_sw, splat_tc, env);
+    vec4 se_detail = detailToggle * oe_splat_getDetailTexel(ri_se, splat_tc, env);
+    vec4 ne_detail = detailToggle * oe_splat_getDetailTexel(ri_ne, splat_tc, env);
+    vec4 nw_detail = detailToggle * oe_splat_getDetailTexel(ri_nw, splat_tc, env);   
+
+    // Combine everything based on weighting:
+    texel.rgb =
+        sw_weight * mix(sw_primary, sw_detail.rgb, sw_detail.a) +
+        se_weight * mix(se_primary, se_detail.rgb, se_detail.a) +
+        ne_weight * mix(ne_primary, ne_detail.rgb, ne_detail.a) +
+        nw_weight * mix(nw_primary, nw_detail.rgb, nw_detail.a);
+
+    return texel;
+}
+
+#ifdef SPLAT_GPU_NOISE
+
+uniform float oe_splat_freq;
+uniform float oe_splat_pers;
+uniform float oe_splat_lac;
+uniform float oe_splat_octaves;
+
+// see: Splat.Noise.glsl
+float oe_noise_fractal4D(in vec2 seed, in float frequency, in float persistence, in float lacunarity, in int octaves);
+
+vec4 oe_splat_getNoise(in vec2 tc)
+{
+    return vec4(oe_noise_fractal4D(tc, oe_splat_freq, oe_splat_pers, oe_splat_lac, int(oe_splat_octaves)));
+}
+
+#else // !SPLAT_GPU_NOISE
+
+uniform sampler2D oe_splat_noiseTex;
+vec4 oe_splat_getNoise(in vec2 tc)
+{
+    return texture(oe_splat_noiseTex, tc.st);
+}
+
+#endif // SPLAT_GPU_NOISE
+
+// Simplified entry point with does no filtering or range blending. (much faster.)
+void oe_splat_simple(inout vec4 color)
+{
+    float noiseLOD = floor(oe_splat_noiseScale);
+    vec2 noiseCoords = oe_splat_getSplatCoords(oe_layer_tilec.st, noiseLOD);
+
+    oe_SplatEnv env;
+    env.range = oe_splat_range;
+    env.slope = oe_splat_getSlope();
+    env.noise = oe_splat_getNoise(noiseCoords);
+    env.elevation = 0.0;
+
+    color = oe_splat_bilinear(oe_layer_tilec.st, env);
+}
+
+// Main entry point for fragment shader.
+void oe_splat_complex(inout vec4 color)
+{
+    // Noise coords.
+    float noiseLOD = floor(oe_splat_noiseScale);
+    vec2 noiseCoords = oe_splat_getSplatCoords(oe_layer_tilec.st, noiseLOD); //TODO: move to VS for slight speedup
+
+    oe_SplatEnv env;
+    env.range = oe_splat_range;
+    env.slope = oe_splat_getSlope();
+    env.noise = oe_splat_getNoise(noiseCoords);
+    env.elevation = 0.0;
+
+    // quantize the scale offset so we take the hit in the FS
+    float scaleOffset = oe_splat_scaleOffset >= 0.0 ? ceil(oe_splat_scaleOffset) : floor(oe_splat_scaleOffset);
+        
+    // Calculate the 2 LODs we need to blend. We have to do this in the FS because 
+    // it's quite possible for a single triangle to span more than 2 LODs.
+    float lod0, lod1;
+    float rangeOuter, rangeInner;
+    oe_splat_getLodBlend(oe_splat_range, lod0, rangeOuter, rangeInner, env.range);
+    
+    // Sample the two LODs:
+    vec2 tc0 = oe_splat_getSplatCoords(oe_layer_tilec.st, lod0 + scaleOffset);
+    env.lod = lod0;
+    vec4 texel0 = oe_splat_bilinear(tc0, env);
+    
+    vec2 tc1 = oe_splat_getSplatCoords(oe_layer_tilec.st, lod0 + 1.0 + scaleOffset);
+    env.lod = lod0+1.0;
+    vec4 texel1 = oe_splat_bilinear(tc1, env);
+
+    // recalcluate blending ratio
+    float lodBlend = clamp((rangeOuter - env.range) / (rangeOuter - rangeInner), 0, 1);
+       
+    // Blend:
+    vec4 texel = mix(texel0, texel1, lodBlend);
+
+    color = mix(color, texel, texel.a);
+    color.a = 1.0;
+
+    // uncomment to visualize slope.
+    //color.rgba = vec4(env.slope,0,0,1);
+}
diff --git a/src/osgEarthSplat/Splat.types.glsl b/src/osgEarthSplat/Splat.types.glsl
new file mode 100644
index 0000000..5aa3df9
--- /dev/null
+++ b/src/osgEarthSplat/Splat.types.glsl
@@ -0,0 +1,22 @@
+// begin: Splat.types.glsl
+
+// Environment structure passed around locally.
+struct oe_SplatEnv {
+    float lod;
+    float range;
+    float elevation;
+    float slope;
+    vec4 noise;
+};
+
+// Rendering parameters for splat texture and noise-based detail texture.
+struct oe_SplatRenderInfo {
+    float primaryIndex;
+    float detailIndex;
+    float brightness;
+    float contrast;
+    float threshold;
+    float minSlope;
+};
+
+// end: Splat.types.glsl
\ No newline at end of file
diff --git a/src/osgEarthSplat/Splat.util.glsl b/src/osgEarthSplat/Splat.util.glsl
new file mode 100644
index 0000000..170a872
--- /dev/null
+++ b/src/osgEarthSplat/Splat.util.glsl
@@ -0,0 +1,99 @@
+#version 120
+#pragma vp_location fragment_coloring
+
+uniform vec4 oe_tile_key;  // osgEarth TileKey
+
+// Number of LOD range. Do not increase this past 25; doing so will result in precision errors
+// and rendering artifacts when the camera is very close to the ground.
+#define LOD_COUNT 25
+
+const float oe_SplatRanges[LOD_COUNT] = float[](
+       100000000.0, // 0
+        75000000.0, // 1
+        50000000.0, // 2
+        10000000.0, // 3
+         7500000.0, // 4
+         5000000.0, // 5
+         2500000.0, // 6
+         1000000.0, // 7
+          500000.0, // 8
+          225000.0, // 9
+          150000.0, // 10
+           80000.0, // 11
+           30000.0, // 12
+           14000.0, // 13
+            4000.0, // 14
+            2500.0, // 15
+            1000.0, // 16
+             500.0, // 17
+             250.0, // 18
+             125.0, // 19
+              50.0, // 20
+              25.0, // 21
+              12.0, // 22
+               6.0, // 23
+               3.0  // 24
+    );
+
+/**
+ * Given a camera distance, return the two LODs it falls between and
+ * the blend factor [0..1] between then.
+ * in  range   = camera distace to fragment
+ * in  baseLOD = LOD at which texture scale is 1.0
+ * out LOD0    = near LOD
+ * out LOD1    = far LOD
+ * out blend   = Blend factor between LOD0 and LOD1 [0..1]
+ */
+void
+oe_splat_getLodBlend(in float range, out float out_LOD0, out float out_rangeOuter, out float out_rangeInner, out float out_clampedRange)
+{
+    out_clampedRange = clamp(range, oe_SplatRanges[LOD_COUNT-1], oe_SplatRanges[0]);
+
+    out_LOD0 = 0;
+
+    for(int i=0; i<LOD_COUNT-1; ++i)
+    {
+        if ( out_clampedRange < oe_SplatRanges[i] && out_clampedRange >= oe_SplatRanges[i+1] )
+        {
+            out_LOD0 = float(i); //   + baseLOD;
+            break;
+        }
+    }
+
+    out_rangeOuter = oe_SplatRanges[int(out_LOD0)];
+    out_rangeInner = oe_SplatRanges[int(out_LOD0)+1];
+}
+
+float
+oe_splat_getRangeForLod(in float lod)
+{
+    return oe_SplatRanges[int(lod)];
+}
+
+/**
+ * Scales the incoming tile splat coordinates to match the requested
+ * LOD level. We offset the level from the current tile key's LOD (.z)
+ * because otherwise you run into single-precision jitter at high LODs.
+ */
+vec2 
+oe_splat_getSplatCoords(in vec2 tc, float lod)
+{
+    float dL = oe_tile_key.z - lod;
+    float factor = exp2(dL);
+    float invFactor = 1.0/factor;
+    vec2 scale = vec2(invFactor); 
+    vec2 result = tc * scale;
+
+    // For upsampling we need to calculate an offset as well
+    vec2 a = floor(oe_tile_key.xy * invFactor);
+    vec2 b = a * factor;
+    vec2 c = (a+1.0) * factor;
+    vec2 offset = (oe_tile_key.xy-b)/(c-b);
+
+    // only apply offset if factor >= 1.0
+    float m = floor(clamp(factor,0.0,1.0));
+    result += (m*offset);
+
+    return result;
+}
+
diff --git a/src/osgEarthSplat/Splat.vert.model.glsl b/src/osgEarthSplat/Splat.vert.model.glsl
new file mode 100644
index 0000000..a0b88cc
--- /dev/null
+++ b/src/osgEarthSplat/Splat.vert.model.glsl
@@ -0,0 +1,15 @@
+#version 330
+#pragma vp_entryPoint oe_splat_vertex_model
+#pragma vp_location   vertex_model
+#pragma vp_order      0.5
+
+vec3 vp_Normal; // stage global
+out float oe_splat_slope;
+
+void oe_splat_vertex_model(inout vec4 VertexMODEL)
+{
+    // calculate slope from the Z component of the current normal
+    // since the terrain is in LTP space. This is only used when normal maps
+    // are not available, which is hopefully never :/
+    oe_splat_slope = 1.0-vp_Normal.z;
+}
diff --git a/src/osgEarthSplat/Splat.vert.view.glsl b/src/osgEarthSplat/Splat.vert.view.glsl
new file mode 100644
index 0000000..a4f9dd5
--- /dev/null
+++ b/src/osgEarthSplat/Splat.vert.view.glsl
@@ -0,0 +1,24 @@
+#version 330
+
+#pragma vp_entryPoint oe_splat_vertex_view
+#pragma vp_location   vertex_view
+#pragma vp_order      0.5
+
+#pragma include Splat.types.glsl
+
+out vec4 oe_layer_tilec;
+out float oe_splat_range;
+out vec2 oe_splat_covtc;
+
+uniform mat4 COVERAGE_TEXTURE_MATRIX;   // assigned at runtime
+
+
+void oe_splat_vertex_view(inout vec4 VertexVIEW)
+{
+    // range from camera to vertex
+    oe_splat_range = -VertexVIEW.z;
+
+    // calculate the coverage sampling coordinates. The texture matrix accounts
+    // for any super-sampling that might be in effect for the current LOD.
+    oe_splat_covtc = (COVERAGE_TEXTURE_MATRIX * oe_layer_tilec).st;
+}
diff --git a/src/osgEarthSplat/SplatCatalog b/src/osgEarthSplat/SplatCatalog
new file mode 100644
index 0000000..ea360d4
--- /dev/null
+++ b/src/osgEarthSplat/SplatCatalog
@@ -0,0 +1,172 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+ * Copyright 2016 Pelican Mapping
+ * http://osgearth.org
+ *
+ * osgEarth is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ */
+#ifndef OSGEARTH_SPLAT_SPLAT_CATALOG
+#define OSGEARTH_SPLAT_SPLAT_CATALOG 1
+
+#include "Export"
+#include <osg/Referenced>
+#include <osg/Texture2DArray>
+#include <osgEarth/Containers>
+#include <osgEarth/URI>
+
+namespace osgDB {
+    class Options;
+}
+
+namespace osgEarth { namespace Splat
+{
+    /**
+     * Defines the parameters for noise-generated detail splatting
+     * for a given class/range.
+     */
+    struct OSGEARTHSPLAT_EXPORT SplatDetailData
+    {
+        optional<URI>   _imageURI;
+        optional<float> _brightness;
+        optional<float> _contrast;
+        optional<float> _threshold;
+        optional<float> _slope;
+
+        // catalog will populate this value
+        int _textureIndex;
+
+        SplatDetailData();
+        SplatDetailData(const Config& conf);
+        Config getConfig() const;
+    };
+
+    /**
+     * Defines a single splatting appearance that will be used if its
+     * selector expression evaluates to true.
+     */
+    struct OSGEARTHSPLAT_EXPORT SplatRangeData
+    {
+        optional<unsigned>        _maxLOD;
+        //optional<float>           _minRange;
+        optional<URI>             _imageURI;
+        optional<URI>             _modelURI;
+        optional<int>             _modelCount;
+        optional<int>             _modelLevel;
+        optional<SplatDetailData> _detail;
+
+        // catalog will populate this value
+        int _textureIndex;
+
+        SplatRangeData();
+        SplatRangeData(const Config& conf);
+        Config getConfig() const;
+    };
+
+    typedef std::vector<SplatRangeData> SplatRangeDataVector;
+
+    /**
+     * A single splatting class. One class may have multiple
+     * data definitions, which are evaluated in order of appearance.
+     */
+    struct OSGEARTHSPLAT_EXPORT SplatClass
+    {
+        std::string          _name;
+        SplatRangeDataVector _ranges;
+
+        SplatClass();
+        SplatClass(const Config& conf);
+        Config getConfig() const;
+    };
+    
+    typedef osgEarth::fast_map<std::string, SplatClass> SplatClassMap;
+  
+    typedef osgEarth::fast_map<std::string /*className*/, SplatRangeDataVector> SplatLUT;
+
+    // Defines the splatting texture and associated lookup table.
+    struct SplatTextureDef
+    {
+        osg::ref_ptr<osg::Texture2DArray> _texture;
+        SplatLUT                          _splatLUT;
+        osg::ref_ptr<osg::Texture>        _splatLUTBuffer;
+        std::string                       _samplingFunction;
+    };
+    
+    typedef std::vector<SplatTextureDef> SplatTextureDefVector;
+
+    /**
+     * Catalog of texture-splatting classes. Usually these correspond
+     * to land use.
+     */
+    class OSGEARTHSPLAT_EXPORT SplatCatalog : public osg::Referenced
+    {
+    public:
+        /**
+         * Construct an empty catalog.
+         */
+        SplatCatalog();
+
+        /**
+         * The splatting classifications set.
+         */
+        const SplatClassMap& getClasses() const { return _classes; }
+
+        /**
+         * Whether the catalog is empty
+         */
+        bool empty() const { return _classes.empty(); }
+
+        /**
+         * Create a texture array from the images in the catalog, along
+         * with a definition of how to map classifications to texture
+         * array indices.
+         */        
+        bool createSplatTextureDef(const osgDB::Options* options,
+                                   SplatTextureDef&      out);
+
+    public: // properties
+
+        /** Name of this catalog */
+        optional<std::string>& name() { return _name; }
+        const optional<std::string>& name() const { return _name; }
+
+
+    public: // serialization
+
+        // populate this object from a Config
+        void fromConfig(const Config& conf);
+
+        // serialize this object to a Config.
+        Config getConfig() const;
+        
+
+    public: // static utility
+
+        /** Reads a splat catalog from a URI. */
+        static SplatCatalog* read(const URI& uri, const osgDB::Options* options);
+
+
+    protected:
+
+        virtual ~SplatCatalog() { }
+
+        optional<int>         _version;
+        optional<std::string> _name;
+        optional<std::string> _description;
+        SplatClassMap         _classes;
+        SplatTextureDef       _textureDef;
+    };
+
+} } // namespace osgEarth::Splat
+
+#endif // OSGEARTH_SPLAT_SPLAT_CATALOG
diff --git a/src/osgEarthSplat/SplatCatalog.cpp b/src/osgEarthSplat/SplatCatalog.cpp
new file mode 100644
index 0000000..cf48774
--- /dev/null
+++ b/src/osgEarthSplat/SplatCatalog.cpp
@@ -0,0 +1,390 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+ * Copyright 2016 Pelican Mapping
+ * http://osgearth.org
+ *
+ * osgEarth is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ */
+#include "SplatCatalog"
+#include <osgEarth/Config>
+#include <osgEarth/ImageUtils>
+#include <osgEarth/XmlUtils>
+#include <osg/Texture2DArray>
+
+using namespace osgEarth;
+using namespace osgEarth::Splat;
+
+#define LC "[SplatCatalog] "
+
+#define SPLAT_CATALOG_CURRENT_VERSION 1
+
+
+//............................................................................
+
+SplatDetailData::SplatDetailData() :
+_textureIndex( -1 )
+{
+    //nop
+}
+
+SplatDetailData::SplatDetailData(const Config& conf) :
+_textureIndex( -1 )
+{
+    conf.getIfSet("image",      _imageURI);
+    conf.getIfSet("brightness", _brightness);
+    conf.getIfSet("contrast",   _contrast);
+    conf.getIfSet("threshold",  _threshold);
+    conf.getIfSet("slope",      _slope);
+}
+
+Config
+SplatDetailData::getConfig() const
+{
+    Config conf;
+    conf.addIfSet("image",      _imageURI);
+    conf.addIfSet("brightness", _brightness);
+    conf.addIfSet("contrast",   _contrast);
+    conf.addIfSet("threshold",  _threshold);
+    conf.addIfSet("slope",      _slope);
+    return conf;
+}
+
+//............................................................................
+
+SplatRangeData::SplatRangeData() :
+_textureIndex( -1 )
+{
+    //nop
+}
+
+SplatRangeData::SplatRangeData(const Config& conf) :
+_textureIndex( -1 )
+{
+    conf.getIfSet("max_lod",    _maxLOD);
+    conf.getIfSet("image",      _imageURI);
+    conf.getIfSet("model",      _modelURI);
+    conf.getIfSet("modelCount", _modelCount);
+    conf.getIfSet("modelLevel", _modelLevel);
+
+    if ( conf.hasChild("detail") )
+        _detail = SplatDetailData(conf.child("detail"));
+}
+
+Config
+SplatRangeData::getConfig() const
+{
+    Config conf;
+    conf.addIfSet("max_lod",    _maxLOD);
+    conf.addIfSet("image",      _imageURI);
+    conf.addIfSet("model",      _modelURI);
+    conf.addIfSet("modelCount", _modelCount);
+    conf.addIfSet("modelLevel", _modelLevel);
+    if ( _detail.isSet() )
+        conf.add( "detail", _detail->getConfig() );
+
+    return conf;
+}
+
+//............................................................................
+
+SplatClass::SplatClass()
+{
+    //nop
+}
+
+SplatClass::SplatClass(const Config& conf)
+{
+    _name = conf.value("name");
+
+    if ( conf.hasChild("range") )
+    {
+        ConfigSet children = conf.children("range");
+
+        // read the data definitions in order:
+        for(ConfigSet::const_iterator i = children.begin(); i != children.end(); ++i)
+        {
+            if ( !i->empty() )
+            {
+                _ranges.push_back(SplatRangeData(*i));
+            }
+        }
+    }
+    else
+    {
+        // just one.
+        _ranges.push_back( SplatRangeData(conf) );
+    }
+}
+
+Config
+SplatClass::getConfig() const
+{
+    Config conf( _name );
+    for(SplatRangeDataVector::const_iterator i = _ranges.begin(); i != _ranges.end(); ++i)
+    {
+        conf.add( "range", i->getConfig() );
+    }
+    return conf;
+}
+
+//............................................................................
+
+SplatCatalog::SplatCatalog()
+{
+    _version = SPLAT_CATALOG_CURRENT_VERSION;
+}
+
+void
+SplatCatalog::fromConfig(const Config& conf)
+{
+    conf.getIfSet("version",     _version);
+    conf.getIfSet("name",        _name);
+    conf.getIfSet("description", _description);
+
+    Config classesConf = conf.child("classes");
+    if ( !classesConf.empty() )
+    {
+        for(ConfigSet::const_iterator i = classesConf.children().begin(); i != classesConf.children().end(); ++i)
+        {
+            SplatClass sclass(*i);
+            if ( !sclass._name.empty() )
+            {
+                _classes[sclass._name] = sclass;
+            }
+        }
+    }
+}
+
+Config
+SplatCatalog::getConfig() const
+{
+    Config conf;
+    conf.addIfSet("version",     _version);
+    conf.addIfSet("name",        _name);
+    conf.addIfSet("description", _description);
+    
+    Config classes("classes");
+    {
+        for(SplatClassMap::const_iterator i = _classes.begin(); i != _classes.end(); ++i)
+        {
+            classes.add( "class", i->second.getConfig() );
+        }
+    }    
+    conf.add( classes );
+
+    return conf;
+}
+
+namespace
+{
+    osg::Image* loadImage(const URI& uri, const osgDB::Options* dbOptions, osg::Image* firstImage)
+    {
+        // try to load the image:
+        ReadResult result = uri.readImage(dbOptions);
+        if ( result.succeeded() )
+        {
+            // if this is the first image loaded, remember it so we can ensure that
+            // all images are copatible.
+            if ( firstImage == 0L )
+            {
+                firstImage = result.getImage();
+            }
+            else
+            {
+                // ensure compatibility, a requirement for texture arrays.
+                // In the future perhaps we can resize/convert instead.
+                if ( !ImageUtils::textureArrayCompatible(result.getImage(), firstImage) )
+                {
+                    osg::ref_ptr<osg::Image> conv = ImageUtils::convert(result.getImage(), firstImage->getPixelFormat(), firstImage->getDataType());
+
+                    if ( conv->s() != firstImage->s() || conv->t() != firstImage->t() )
+                    {
+                        osg::ref_ptr<osg::Image> conv2;
+                        if ( ImageUtils::resizeImage(conv.get(), firstImage->s(), firstImage->t(), conv2) )
+                        {
+                            conv = conv2.get();
+                        }
+                    }
+
+                    if ( ImageUtils::textureArrayCompatible(conv.get(), firstImage) )
+                    {
+                        conv->setInternalTextureFormat( firstImage->getInternalTextureFormat() );
+                        return conv.release();
+                    }
+                    else
+                    {
+                        OE_WARN << LC << "Image " << uri.base()
+                            << " was found, but cannot be used because it is not compatible with "
+                            << "other splat images (same dimensions, pixel format, etc.)\n";
+                        return 0L;
+                    }
+                }
+            }
+        }
+        else
+        {
+            OE_WARN << LC
+                << "Image in the splat catalog failed to load: "
+                << uri.full() << "; message = " << result.getResultCodeString()
+                << std::endl;
+        }
+
+        return result.releaseImage();
+    }
+}
+
+bool
+SplatCatalog::createSplatTextureDef(const osgDB::Options* dbOptions,
+                                    SplatTextureDef&      out)
+{
+    // Reset all texture indices to default
+    for(SplatClassMap::iterator i = _classes.begin(); i != _classes.end(); ++i)
+    {
+        SplatClass& c = i->second;
+        for(SplatRangeDataVector::iterator range = c._ranges.begin(); range != c._ranges.end(); ++range)
+        {
+            range->_textureIndex = -1;
+            if ( range->_detail.isSet() )
+            {
+                range->_detail->_textureIndex = -1;
+            }
+        }
+    }
+
+    typedef osgEarth::fast_map<URI, int> ImageIndexTable; // track images to prevent dupes
+    ImageIndexTable imageIndices;
+    std::vector< osg::ref_ptr<osg::Image> > imagesInOrder;
+    int index = 0;
+    osg::Image* firstImage  = 0L;
+
+    // Load all referenced images in the catalog, and assign each a unique index.
+    for(SplatClassMap::iterator i = _classes.begin(); i != _classes.end(); ++i)
+    {
+        SplatClass& c = i->second;
+
+        for(SplatRangeDataVector::iterator range = c._ranges.begin(); range != c._ranges.end(); ++range)
+        {
+            // Load the main image and assign it an index:
+            if (range->_imageURI.isSet())
+            {
+                int texIndex = -1;
+                ImageIndexTable::iterator k = imageIndices.find(range->_imageURI.get());
+                if ( k == imageIndices.end() )
+                {
+                    osg::ref_ptr<osg::Image> image = loadImage( range->_imageURI.get(), dbOptions, firstImage );
+                    if ( image.valid() )
+                    {
+                        if ( !firstImage )
+                            firstImage = image.get();
+
+                        imageIndices[range->_imageURI.get()] = texIndex = index++;
+                        imagesInOrder.push_back( image.get() );
+                    }
+                }
+                else
+                {
+                    texIndex = k->second;
+                }
+                range->_textureIndex = texIndex;
+            }
+
+            // Load the detail texture if it exists:
+            if (range->_detail.isSet() &&
+                range->_detail->_imageURI.isSet())
+            {
+                int texIndex = -1;
+                ImageIndexTable::iterator k = imageIndices.find(range->_detail->_imageURI.get());
+                if ( k == imageIndices.end() )
+                {
+                    osg::ref_ptr<osg::Image> image = loadImage( range->_detail->_imageURI.get(), dbOptions, firstImage );
+                    if ( image.valid() )
+                    {
+                        if ( !firstImage )
+                            firstImage = image.get();
+            
+                        imageIndices[range->_detail->_imageURI.get()] = texIndex = index++;
+                        imagesInOrder.push_back( image.get() );
+                    }
+                }
+                else
+                {
+                    texIndex = k->second;
+                }
+                range->_detail->_textureIndex = texIndex;
+            }
+        }
+    }
+
+    // Next, go through the classes and build the splat lookup table.
+    for(SplatClassMap::const_iterator i = _classes.begin(); i != _classes.end(); ++i)
+    {
+        const SplatClass& c = i->second;
+        out._splatLUT[c._name] = c._ranges;
+    }
+
+    // Create the texture array.
+    if ( imagesInOrder.size() > 0 && firstImage )
+    {
+        out._texture = new osg::Texture2DArray();
+        out._texture->setTextureSize( firstImage->s(), firstImage->t(), imagesInOrder.size() );
+        out._texture->setWrap( osg::Texture::WRAP_S, osg::Texture::REPEAT );
+        out._texture->setWrap( osg::Texture::WRAP_T, osg::Texture::REPEAT );
+        out._texture->setFilter( osg::Texture::MIN_FILTER, osg::Texture::LINEAR_MIPMAP_LINEAR );
+        out._texture->setFilter( osg::Texture::MAG_FILTER, osg::Texture::LINEAR );
+        out._texture->setResizeNonPowerOfTwoHint( false );
+        out._texture->setMaxAnisotropy( 4.0f );
+
+        for(unsigned i=0; i<imagesInOrder.size(); ++i)
+        {
+            out._texture->setImage( i, imagesInOrder[i].get() );
+        }
+
+        OE_INFO << LC << "Catalog \"" << this->name().get()
+            << "\" texture size = "<< imagesInOrder.size()
+            << std::endl;
+    }
+
+    return out._texture.valid();
+}
+
+SplatCatalog*
+SplatCatalog::read(const URI&            uri,
+                   const osgDB::Options* options)
+{
+    osg::ref_ptr<SplatCatalog> catalog;
+
+    osg::ref_ptr<XmlDocument> doc = XmlDocument::load( uri, options );
+    if ( doc.valid() )
+    {
+        catalog = new SplatCatalog();
+        catalog->fromConfig( doc->getConfig().child("catalog") );
+        if ( catalog->empty() )
+        {
+            OE_WARN << LC << "Catalog is empty! (" << uri.full() << ")\n";
+            catalog = 0L;
+        }
+        else
+        {
+            OE_INFO << LC << "Catalog \"" << catalog->name().get() << "\""
+                << " contains " << catalog->getClasses().size()
+                << " classes.\n";
+        }
+    }
+    else
+    {
+        OE_WARN << LC << "Failed to read catalog from " << uri.full() << "\n";
+    }
+
+    return catalog.release();
+}
\ No newline at end of file
diff --git a/src/osgEarthSplat/SplatCoverageLegend b/src/osgEarthSplat/SplatCoverageLegend
new file mode 100644
index 0000000..528035f
--- /dev/null
+++ b/src/osgEarthSplat/SplatCoverageLegend
@@ -0,0 +1,112 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+ * Copyright 2016 Pelican Mapping
+ * http://osgearth.org
+ *
+ * osgEarth is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ */
+#ifndef OSGEARTH_SPLAT_COVERAGE_LEGEND
+#define OSGEARTH_SPLAT_COVERAGE_LEGEND 1
+
+#include "Export"
+#include <osgEarth/Config>
+#include <osg/Referenced>
+#include <string>
+
+namespace osgEarth { namespace Splat
+{
+    /**
+     * Associates a specific source data coverage value to the name
+     * of a splat class.
+     */
+    template<typename T>
+    class OSGEARTHSPLAT_EXPORT CoverageValuePredicateT : public osg::Referenced
+    {
+    public:
+        optional<T> _exactValue;
+        optional<T> _minValue;
+        optional<T> _maxValue;
+
+        optional<std::string> _description;
+        optional<std::string> _mappedClassName;
+
+        bool match(const T& testValue) const
+        {
+            if ( _exactValue.isSetTo(testValue) )
+                return true;
+            if ( !_minValue.isSet() && !_maxValue.isSet() )
+                return false;
+            if ( _minValue.isSet() && _minValue.get() > testValue )
+                return false;
+            if ( _maxValue.isSet() && _maxValue.get() < testValue )
+                return false;
+
+            return true;
+        }
+    };
+
+    typedef CoverageValuePredicateT<std::string> CoverageValuePredicate;
+
+
+    /**
+     * Legend that maps coverage values (or value predicates) to splat
+     * catalog classes.
+     */
+    class OSGEARTHSPLAT_EXPORT SplatCoverageLegend : public osg::Referenced
+    {
+    public:
+        SplatCoverageLegend();
+
+    public:
+        // Collection of coverage value predicated
+        typedef std::vector< osg::ref_ptr<CoverageValuePredicate> > Predicates;
+
+        /**
+         * The collection of value->class mapping predicates
+         */
+        const Predicates& getPredicates() const { return _predicates; }
+
+        /**
+         * Whether this legend is empty.
+         */
+        bool empty() const { return _predicates.empty(); }
+
+        /**
+         * Looks up a precidate for the given class name, or returns NULL
+         * if there isn't one.
+         */
+        bool getPredicatesForClass(const std::string& className, std::vector<const CoverageValuePredicate*>& output) const;
+
+    public: // serialization
+
+        // populate this object from a Config
+        void fromConfig(const Config& conf);
+
+        // serialize this object to a Config.
+        Config getConfig() const;
+
+
+    protected:
+
+        virtual ~SplatCoverageLegend() { }
+
+        optional<std::string> _name;
+        optional<std::string> _source;
+
+        Predicates _predicates;
+    };
+
+} } // namespace osgEarth::Splat
+
+#endif // OSGEARTH_SPLAT_COVERAGE_LEGEND
diff --git a/src/osgEarthSplat/SplatCoverageLegend.cpp b/src/osgEarthSplat/SplatCoverageLegend.cpp
new file mode 100644
index 0000000..194ec08
--- /dev/null
+++ b/src/osgEarthSplat/SplatCoverageLegend.cpp
@@ -0,0 +1,93 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+ * Copyright 2016 Pelican Mapping
+ * http://osgearth.org
+ *
+ * osgEarth is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ */
+#include "SplatCoverageLegend"
+#include <osgEarth/Config>
+
+using namespace osgEarth;
+using namespace osgEarth::Splat;
+
+#define LC "[SplatCoverageLegend] "
+
+//............................................................................
+
+SplatCoverageLegend::SplatCoverageLegend()
+{
+    //nop
+}
+
+bool
+SplatCoverageLegend::getPredicatesForClass(const std::string& className,
+                                           std::vector<const CoverageValuePredicate*>& output) const
+{
+    output.clear();
+    for(Predicates::const_iterator i = _predicates.begin(); i != _predicates.end(); ++i)
+    {
+        if ( i->get()->_mappedClassName == className )
+        {
+            output.push_back( i->get() );
+        }
+    }
+    return output.size() > 0;
+}
+
+void
+SplatCoverageLegend::fromConfig(const Config& conf)
+{
+    conf.getIfSet("name",   _name);
+    conf.getIfSet("source", _source);
+
+    ConfigSet predicatesConf = conf.child("mappings").children();
+    for(ConfigSet::const_iterator i = predicatesConf.begin(); i != predicatesConf.end(); ++i)
+    {
+        osg::ref_ptr<CoverageValuePredicate> p = new CoverageValuePredicate();
+
+        i->getIfSet( "name",  p->_description );
+        i->getIfSet( "value", p->_exactValue );
+        i->getIfSet( "class", p->_mappedClassName );
+        
+        if ( p->_mappedClassName.isSet() )
+        {
+            _predicates.push_back( p.get() );
+        }
+    }
+}
+
+Config
+SplatCoverageLegend::getConfig() const
+{
+    Config conf;
+    
+    conf.addIfSet("name",   _name);
+    conf.addIfSet("source", _source);
+
+    Config preds;
+    for(Predicates::const_iterator i = _predicates.begin(); i != _predicates.end(); ++i)
+    {
+        CoverageValuePredicate* p = i->get();
+        Config pred;
+        pred.addIfSet( "name",  p->_description );
+        pred.addIfSet( "value", p->_exactValue );
+        pred.addIfSet( "class", p->_mappedClassName );
+        preds.add( "mapping", pred );
+    }
+    conf.add( "mappings", preds );
+
+    return conf;
+}
+
diff --git a/src/osgEarthSplat/SplatExtension b/src/osgEarthSplat/SplatExtension
new file mode 100644
index 0000000..ea93edc
--- /dev/null
+++ b/src/osgEarthSplat/SplatExtension
@@ -0,0 +1,90 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+ * Copyright 2016 Pelican Mapping
+ * http://osgearth.org
+ *
+ * osgEarth is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ */
+#ifndef OSGEARTH_SPLAT_SPLAT_EXTENSION
+#define OSGEARTH_SPLAT_SPLAT_EXTENSION 1
+
+#include "Export"
+#include "SplatOptions"
+#include "SplatTerrainEffect"
+#include "LandCoverTerrainEffect"
+#include "Zone"
+
+#include <osgEarth/Extension>
+#include <osgEarth/MapNode>
+#include <osgEarthUtil/Controls>
+
+namespace osgEarth { namespace Splat
+{
+    using namespace osgEarth;
+    using namespace osgEarth::Util::Controls;
+    
+
+    /**
+     * Extension for loading the splatting effect on demand.
+     */
+    class OSGEARTHSPLAT_EXPORT SplatExtension : public Extension,
+                                                public ExtensionInterface<MapNode>,
+                                                public ExtensionInterface<Control>,
+                                                public SplatOptions
+    {
+    public:
+        META_Object(osgearth_ext_splat, SplatExtension);
+
+        // CTORs
+        SplatExtension();
+        SplatExtension(const SplatOptions& options);
+
+        // DTOR
+        virtual ~SplatExtension();
+
+
+    public: // Extension
+
+        void setDBOptions(const osgDB::Options* dbOptions);
+
+        const ConfigOptions& getConfigOptions() const { return *this; }
+
+
+    public: // ExtensionInterface<MapNode>
+
+        bool connect(MapNode* mapNode);
+
+        bool disconnect(MapNode* mapNode);
+
+
+    public: // ExtensionInterface<Control>
+
+        bool connect(Control* control);
+
+        bool disconnect(Control* control);
+
+
+    protected: // Object
+        SplatExtension(const SplatExtension& rhs, const osg::CopyOp& op) { }
+
+    private:
+        osg::ref_ptr<const osgDB::Options>   _dbo;
+        osg::ref_ptr<SplatTerrainEffect>     _splatEffect;
+        osg::ref_ptr<LandCoverTerrainEffect> _landCoverEffect;
+        osg::ref_ptr<ZoneSwitcher>           _zoneSwitcher;
+    };
+
+} } // namespace osgEarth::Splat
+
+#endif // OSGEARTH_SPLAT_SPLAT_EXTENSION
diff --git a/src/osgEarthSplat/SplatExtension.cpp b/src/osgEarthSplat/SplatExtension.cpp
new file mode 100644
index 0000000..4e69e29
--- /dev/null
+++ b/src/osgEarthSplat/SplatExtension.cpp
@@ -0,0 +1,177 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+ * Copyright 2016 Pelican Mapping
+ * http://osgearth.org
+ *
+ * osgEarth is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ */
+#include "SplatExtension"
+#include "SplatCatalog"
+#include "SplatCoverageLegend"
+#include "SplatTerrainEffect"
+
+#include <osgEarth/MapNode>
+#include <osgEarth/TerrainEngineNode>
+#include <osgEarth/XmlUtils>
+
+using namespace osgEarth;
+using namespace osgEarth::Splat;
+
+#define LC "[SplatExtension] "
+
+//.........................................................................
+
+REGISTER_OSGEARTH_EXTENSION(osgearth_splat, SplatExtension);
+
+
+SplatExtension::SplatExtension()
+{
+    //nop
+}
+
+SplatExtension::SplatExtension(const SplatOptions& options) :
+SplatOptions( options )
+{
+    //nop
+}
+
+SplatExtension::~SplatExtension()
+{
+    //nop
+}
+
+void
+SplatExtension::setDBOptions(const osgDB::Options* dbOptions)
+{
+    _dbo = dbOptions;
+}
+
+bool
+SplatExtension::connect(MapNode* mapNode)
+{
+    if ( !mapNode )
+    {
+        OE_WARN << LC << "Illegal: MapNode cannot be null." << std::endl;
+        return false;
+    }
+
+    OE_INFO << LC << "Connecting to MapNode.\n";
+
+    // Coverage source data
+    osg::ref_ptr<Coverage> myCoverage;
+    if ( coverage().isSet() )
+    {
+        myCoverage = new Coverage();
+        if ( !myCoverage->configure( coverage().get(), mapNode->getMap(), _dbo.get() ) )
+        {
+            OE_WARN << LC << "Coverage is not properly configured; land cover disabled.\n";
+            return false;
+        }
+    }
+
+    bool enableSurfaceEffect = false;
+    bool enableLandCoverEffect = false;
+
+    // Zone definitions
+    Zones myZones;
+    for(int i=0; i<zones().size(); ++i)
+    {
+        osg::ref_ptr<Zone> zone = new Zone();
+        if ( zone->configure(zones().at(i), mapNode->getMap(), _dbo.get()) )
+        {
+            myZones.push_back( zone.get() );
+
+            if ( zone->getSurface() != 0L )
+            {
+                enableSurfaceEffect = true;
+            }
+
+            if ( zone->getLandCover() != 0L )
+            {
+                enableLandCoverEffect = true;
+            }
+        }
+    }
+
+    if ( enableSurfaceEffect )
+    {
+        OE_INFO << LC << "Enabling the surface splatting effect\n";
+        _splatEffect = new SplatTerrainEffect();
+        _splatEffect->setDBOptions( _dbo.get() );
+        _splatEffect->setZones( myZones );
+        _splatEffect->setCoverage( myCoverage.get() );
+
+        mapNode->getTerrainEngine()->addEffect( _splatEffect.get() );
+    }
+
+    if ( enableLandCoverEffect )
+    {
+        OE_INFO << LC << "Enabling the land cover effect\n";
+        _landCoverEffect = new LandCoverTerrainEffect();
+        _landCoverEffect->setDBOptions( _dbo.get() );
+        _landCoverEffect->setZones( myZones );
+        _landCoverEffect->setCoverage( myCoverage.get() );
+        
+        mapNode->getTerrainEngine()->addEffect( _landCoverEffect.get() );
+    }
+
+    // Install the zone switcher; this will select the best zone based on
+    // the camera position.
+    _zoneSwitcher = new ZoneSwitcher(myZones);
+    mapNode->getTerrainEngine()->addCullCallback( _zoneSwitcher.get() );
+
+    return true;
+}
+
+bool
+SplatExtension::disconnect(MapNode* mapNode)
+{
+    if ( mapNode )
+    {
+        if ( _splatEffect.valid() )
+        {
+            mapNode->getTerrainEngine()->removeEffect( _splatEffect.get() );
+            _splatEffect = 0L;
+        }
+
+        if ( _landCoverEffect.valid() )
+        {
+            mapNode->getTerrainEngine()->removeEffect( _landCoverEffect.get() );
+            _landCoverEffect = 0L;
+        }
+
+        mapNode->getTerrainEngine()->removeCullCallback( _zoneSwitcher.get() );
+    }
+
+    return true;
+}
+
+bool
+SplatExtension::connect(Control* control)
+{
+    ////TODO add a UI.
+    //Container* container = dynamic_cast<Container*>(control);
+    //if ( container )
+    //{
+    //    container->addControl( new LabelControl("Prodecural Terrain Extension Active") );
+    //}
+    return true;
+}
+
+bool
+SplatExtension::disconnect(Control* control)
+{
+    // NOP
+    return true;
+}
diff --git a/src/osgEarthSplat/SplatOptions b/src/osgEarthSplat/SplatOptions
new file mode 100644
index 0000000..a872a46
--- /dev/null
+++ b/src/osgEarthSplat/SplatOptions
@@ -0,0 +1,94 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+ * Copyright 2016 Pelican Mapping
+ * http://osgearth.org
+ *
+ * osgEarth is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ */
+#ifndef OSGEARTH_DRIVER_SPLAT_OPTIONS
+#define OSGEARTH_DRIVER_SPLAT_OPTIONS 1
+
+#include <osgEarth/Common>
+#include "Export"
+#include "Coverage"
+#include "Zone"
+
+namespace osgEarth { namespace Splat
+{
+    using namespace osgEarth;
+
+
+    /**
+     * Options governing the classification splatting engine.
+     */
+    class OSGEARTHSPLAT_EXPORT SplatOptions : public DriverConfigOptions
+    {
+    public:
+        /** Classification coverage options */
+        optional<CoverageOptions>& coverage() { return _coverage; }
+        const optional<CoverageOptions>& coverage() const { return _coverage; }
+
+        /** Zone definitions */
+        ZoneOptionsVector& zones() { return _zones; }
+        const ZoneOptionsVector& zones() const { return _zones; }
+
+    public:
+        SplatOptions( const ConfigOptions& opt =ConfigOptions() ) : DriverConfigOptions( opt ) {
+            setDriver( "splat" );
+            fromConfig( _conf );
+        }
+
+        virtual ~SplatOptions() { }
+
+    public:
+        Config getConfig() const {
+            Config conf = DriverConfigOptions::getConfig();
+            conf.updateObjIfSet( "coverage", _coverage );
+            Config zones("zones");
+            for(int i=0; i<_zones.size(); ++i) {
+                Config zone = _zones[i].getConfig();
+                if ( !zone.empty() )
+                    zones.add(zone);
+            }
+            if ( !zones.empty() )
+                conf.add(zones);
+            return conf;
+        }
+
+    protected:
+        void mergeConfig( const Config& conf ) {
+            DriverConfigOptions::mergeConfig( conf );
+            fromConfig( conf );
+        }
+
+    private:
+        void fromConfig( const Config& conf ) {
+            conf.getObjIfSet( "coverage", _coverage );
+            const Config* zones = conf.child_ptr("zones");
+            if ( zones ) {
+                const ConfigSet& children = zones->children();
+                for(ConfigSet::const_iterator i = children.begin(); i != children.end(); ++i) {
+                    _zones.push_back( ZoneOptions(*i) );
+                }
+            }
+        }
+
+        
+        optional<CoverageOptions>  _coverage;
+        ZoneOptionsVector          _zones;
+    };
+
+} } // namespace osgEarth::Splat
+
+#endif // OSGEARTH_DRIVER_SPLAT_OPTIONS
diff --git a/src/osgEarthSplat/SplatShaders b/src/osgEarthSplat/SplatShaders
new file mode 100644
index 0000000..b419a8c
--- /dev/null
+++ b/src/osgEarthSplat/SplatShaders
@@ -0,0 +1,57 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+* Copyright 2008-2012 Pelican Mapping
+* http://osgearth.org
+*
+* osgEarth is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* 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.
+*
+* You should have received a copy of the GNU Lesser General Public License
+* along with this program.  If not, see <http://www.gnu.org/licenses/>
+*/
+#ifndef OSGEARTH_SPLAT_SHADERS
+#define OSGEARTH_SPLAT_SHADERS 1
+
+#include <osgEarth/ShaderLoader>
+
+namespace osgEarth { namespace Splat
+{
+    struct SplattingShaders : public osgEarth::ShaderPackage
+	{
+        SplattingShaders();
+
+        std::string
+            Types,
+            Noise,
+            VertModel,
+            VertView,
+            Frag,
+            FragCommon,
+            //FragGetRenderInfo,
+            Util;
+	};
+
+    struct LandCoverShaders : public osgEarth::ShaderPackage
+	{
+        LandCoverShaders();
+
+        std::string
+            LandCover_TCS,
+            LandCover_TES,
+            LandCover_GS,
+            LandCover_FS;
+	};
+	
+} } // namespace osgEarth::Splat
+
+#endif // OSGEARTH_SPLAT_SHADERS
diff --git a/src/osgEarthSplat/SplatShaders.cpp.in b/src/osgEarthSplat/SplatShaders.cpp.in
new file mode 100644
index 0000000..27e7637
--- /dev/null
+++ b/src/osgEarthSplat/SplatShaders.cpp.in
@@ -0,0 +1,47 @@
+// CMake will compile this file into AutoGenShaders.c""
+
+#include <osgEarthSplat/SplatShaders>
+
+//#define MULTILINE(...) #__VA_ARGS__
+
+using namespace osgEarth::Splat;
+
+SplattingShaders::SplattingShaders()
+{
+    Types = "Splat.types.glsl";
+    _sources[Types] = "@Splat.types.glsl@";
+
+    Noise = "Splat.Noise.glsl";
+    _sources[Noise] = "@Splat.Noise.glsl@";
+
+    VertModel = "Splat.vert.model.glsl";
+    _sources[VertModel] = "@Splat.vert.model.glsl@";
+
+    VertView = "Splat.vert.view.glsl";
+    _sources[VertView] = "@Splat.vert.view.glsl@";
+
+    Frag = "Splat.frag.glsl";
+    _sources[Frag] = "@Splat.frag.glsl@";
+
+    FragCommon = "Splat.frag.common.glsl";
+    _sources[FragCommon] = "@Splat.frag.common.glsl@";
+
+    Util = "Splat.util.glsl";
+    _sources[Util] = "@Splat.util.glsl@";
+}
+
+
+LandCoverShaders::LandCoverShaders()
+{
+    LandCover_TCS = "LandCover.TCS.glsl";
+    _sources[LandCover_TCS] = "@LandCover.TCS.glsl@";
+
+    LandCover_TES = "LandCover.TES.glsl";
+    _sources[LandCover_TES] = "@LandCover.TES.glsl@";
+
+    LandCover_GS = "LandCover.GS.glsl";
+    _sources[LandCover_GS] = "@LandCover.GS.glsl@";
+
+    LandCover_FS = "LandCover.FS.glsl";
+    _sources[LandCover_FS] = "@LandCover.FS.glsl@";
+}
diff --git a/src/osgEarthSplat/SplatTerrainEffect b/src/osgEarthSplat/SplatTerrainEffect
new file mode 100644
index 0000000..b1316f5
--- /dev/null
+++ b/src/osgEarthSplat/SplatTerrainEffect
@@ -0,0 +1,111 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+* Copyright 2008-2012 Pelican Mapping
+* http://osgearth.org
+*
+* osgEarth is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* 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.
+*
+* You should have received a copy of the GNU Lesser General Public License
+* along with this program.  If not, see <http://www.gnu.org/licenses/>
+*/
+#ifndef OSGEARTH_SPLAT_SPLAT_TERRAIN_EFFECT_H
+#define OSGEARTH_SPLAT_SPLAT_TERRAIN_EFFECT_H
+
+#include "SplatCatalog"
+#include "SplatCoverageLegend"
+#include "SplatShaders"
+#include "Export"
+
+#include "Coverage"
+#include "Zone"
+
+#include <osgEarth/TerrainEffect>
+#include <osg/Image>
+#include <osg/Uniform>
+#include <osg/Texture2DArray>
+#include <osgDB/Options>
+
+using namespace osgEarth;
+
+namespace osgEarth { namespace Splat
+{
+    /**
+     * Effect that applies texture splatting to the terrain.
+     */
+    class OSGEARTHSPLAT_EXPORT SplatTerrainEffect : public TerrainEffect
+    {
+    public:
+        /** constructor */
+        SplatTerrainEffect();
+
+        /**
+         * Sets the OSG DB options to use when performing I/O
+         */
+        void setDBOptions(const osgDB::Options* dbo);
+
+        /**
+         * Sets the coverage source
+         */
+        void setCoverage(Coverage* coverage) { _coverage = coverage; }
+        Coverage* getCoverage() const { return _coverage.get(); }
+
+        /**
+         * Sets the splatting zones
+         */
+        void setZones(const Zones& zones) { _zones = zones; }
+        const Zones& getZones() const { return _zones; }
+
+
+    public: // TerrainEffect interface
+
+        void onInstall(TerrainEngineNode* engine);
+
+        void onUninstall(TerrainEngineNode* engine);
+
+
+    protected:
+        virtual ~SplatTerrainEffect() { }
+
+        // index-aligned with the surface biome region vector:
+        SplatTextureDefVector               _textureDefs;
+
+        int                                 _splatTexUnit;
+        osg::ref_ptr<osg::Uniform>          _splatTexUniform;
+        osg::ref_ptr<osg::Uniform>          _coverageTexUniform;
+        int                                 _lutTexUnit;
+        osg::ref_ptr<osg::Uniform>          _lutTexUniform;
+        osg::ref_ptr<osg::Uniform>          _scaleOffsetUniform;
+        osg::ref_ptr<osg::Uniform>          _warpUniform;
+        osg::ref_ptr<osg::Uniform>          _blurUniform;
+        float                               _renderOrder;
+        int                                 _noiseTexUnit;
+        osg::ref_ptr<osg::Texture>          _noiseTex;
+        osg::ref_ptr<osg::Uniform>          _noiseTexUniform;
+        osg::ref_ptr<osg::Uniform>          _noiseScaleUniform;
+        osg::ref_ptr<osg::Uniform>          _useBilinearUniform;
+
+        bool                                _editMode;
+        bool                                _gpuNoise;
+
+        osg::ref_ptr<const osgDB::Options>  _dbo;
+
+        osg::ref_ptr<Coverage>              _coverage;
+
+        Zones                               _zones;
+
+    };
+
+} } // namespace osgEarth::Splat
+
+#endif // OSGEARTH_SPLAT_SPLAT_TERRAIN_EFFECT_H
diff --git a/src/osgEarthSplat/SplatTerrainEffect.cpp b/src/osgEarthSplat/SplatTerrainEffect.cpp
new file mode 100644
index 0000000..87c2603
--- /dev/null
+++ b/src/osgEarthSplat/SplatTerrainEffect.cpp
@@ -0,0 +1,232 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+* Copyright 2008-2012 Pelican Mapping
+* http://osgearth.org
+*
+* osgEarth is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* 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.
+*
+* You should have received a copy of the GNU Lesser General Public License
+* along with this program.  If not, see <http://www.gnu.org/licenses/>
+*/
+#include "SplatTerrainEffect"
+#include "SplatOptions"
+#include "NoiseTextureFactory"
+
+#include <osgEarth/Registry>
+#include <osgEarth/Capabilities>
+#include <osgEarth/VirtualProgram>
+#include <osgEarth/TerrainEngineNode>
+#include <osgEarth/ImageUtils>
+#include <osgEarth/URI>
+#include <osgEarth/ShaderLoader>
+#include <osgEarthUtil/SimplexNoise>
+
+#include <osg/Texture2D>
+#include <osg/TextureBuffer>
+#include <osgDB/WriteFile>
+
+#include "SplatShaders"
+
+#define LC "[Splat] "
+
+#define COVERAGE_SAMPLER "oe_splat_coverageTex"
+#define SPLAT_SAMPLER    "oe_splatTex"
+#define NOISE_SAMPLER    "oe_noise_tex"
+#define LUT_SAMPLER      "oe_splat_coverageLUT"
+
+using namespace osgEarth;
+using namespace osgEarth::Splat;
+
+SplatTerrainEffect::SplatTerrainEffect() :
+_renderOrder ( -1.0f ),
+_editMode    ( false ),
+_gpuNoise    ( false ),
+_splatTexUnit(-1),
+_lutTexUnit(-1),
+_noiseTexUnit(-1)
+{
+    _scaleOffsetUniform = new osg::Uniform("oe_splat_scaleOffsetInt", 0 );
+    _warpUniform        = new osg::Uniform("oe_splat_warp",           0.0f );
+    _blurUniform        = new osg::Uniform("oe_splat_blur",           1.0f );
+    _useBilinearUniform = new osg::Uniform("oe_splat_useBilinear",    1.0f );
+    _noiseScaleUniform  = new osg::Uniform("oe_splat_noiseScale",    12.0f );
+
+    _editMode = (::getenv("OSGEARTH_SPLAT_EDIT") != 0L);
+    _gpuNoise = (::getenv("OSGEARTH_SPLAT_GPU_NOISE") != 0L);
+}
+
+void
+SplatTerrainEffect::setDBOptions(const osgDB::Options* dbo)
+{
+    _dbo = dbo;
+}
+
+void
+SplatTerrainEffect::onInstall(TerrainEngineNode* engine)
+{
+    if ( engine )
+    {
+        // Check that we have coverage data (required for now - later masking data will be an option)
+        if ( !_coverage.valid() || !_coverage->hasLayer() )
+        {
+            OE_WARN << LC << "ILLEGAL: coverage data is required\n";
+            return;
+        }
+
+        bool splattingOK = false;
+
+        for(Zones::const_iterator z = _zones.begin(); z != _zones.end(); ++z)
+        {
+            Zone* zone = z->get();
+            Surface* surface = zone->getSurface();
+            if ( surface )
+            {
+                if ( surface->loadTextures(_coverage.get(), _dbo.get()) )
+                {
+                    splattingOK = true;
+                }
+            }
+        }
+
+        if ( splattingOK )
+        {
+            // First install a shared noise texture.
+            if ( _gpuNoise == false )
+            {
+                osg::StateSet* terrainStateSet = engine->getOrCreateStateSet();
+                if ( terrainStateSet->getUniform("oe_splat_noiseTex") == 0L )
+                {
+                    // reserve a texture unit:
+                    if (engine->getResources()->reserveTextureImageUnit(_noiseTexUnit, "Splat Noise"))
+                    {
+                        NoiseTextureFactory noise;
+                        terrainStateSet->setTextureAttribute( _noiseTexUnit, noise.create(256u, 4u) );
+                        terrainStateSet->addUniform( new osg::Uniform("oe_splat_noiseTex", _noiseTexUnit) );
+                    }
+                }
+            }
+
+            bool coverageOK =  engine->getResources()->reserveTextureImageUnit(_splatTexUnit, "Splat Coverage Data");
+
+            bool lutOK = engine->getResources()->reserveTextureImageUnit(_lutTexUnit, "Splat LUT");
+
+            // Set up surface splatting:
+            if ( coverageOK && lutOK )
+            {
+                // Set up the zone-specific elements:
+                for(Zones::iterator z = _zones.begin(); z != _zones.end(); ++z)
+                {
+                    Zone* zone = z->get();
+
+                    // The texture array for the zone:
+                    const SplatTextureDef& texdef = zone->getSurface()->getTextureDef();
+                    osg::StateSet* zoneStateset = zone->getOrCreateStateSet();
+
+                    // apply the splatting texture catalog:
+                    zoneStateset->setTextureAttribute( _splatTexUnit, texdef._texture.get() );
+
+                    // apply the buffer containing the coverage-to-splat LUT:
+                    zoneStateset->setTextureAttribute(_lutTexUnit, texdef._splatLUTBuffer.get());
+
+                    // The zone's sampling function:
+                    //VirtualProgram* vp = VirtualProgram::cloneOrCreate( zoneStateset );
+                    //osg::Shader* shader = new osg::Shader(osg::Shader::FRAGMENT, texdef._samplingFunction);
+                    //vp->setShader( "oe_splat_getRenderInfo", shader );
+
+                    OE_INFO << LC << "Installed getRenderInfo for zone \"" << zone->getName() << "\" (uid=" << zone->getUID() << ")\n";
+                }
+
+                // Next set up the elements that apply to all zones:
+                osg::StateSet* stateset = engine->getSurfaceStateSet();
+
+                // Bind the texture image unit:
+                _splatTexUniform = new osg::Uniform(SPLAT_SAMPLER, _splatTexUnit);
+                stateset->addUniform( _splatTexUniform.get() );
+
+                // install the uniform for the splat LUT.
+                _lutTexUniform = stateset->getOrCreateUniform( LUT_SAMPLER, osg::Uniform::SAMPLER_BUFFER );
+                _lutTexUniform->set(_lutTexUnit);
+
+                // coverage code sampler:
+                osg::ref_ptr<ImageLayer> coverageLayer;
+                _coverage->lockLayer( coverageLayer );
+
+                _coverageTexUniform = stateset->getOrCreateUniform( COVERAGE_SAMPLER, osg::Uniform::SAMPLER_2D );
+                _coverageTexUniform->set( coverageLayer->shareImageUnit().get() );
+
+                // control uniforms (TODO: simplify and deprecate unneeded uniforms)
+                stateset->addUniform( _scaleOffsetUniform.get() );
+                stateset->addUniform( _warpUniform.get() );
+                stateset->addUniform( _blurUniform.get() );
+                stateset->addUniform( _noiseScaleUniform.get() );
+                stateset->addUniform( _useBilinearUniform.get() );
+
+                stateset->addUniform(new osg::Uniform("oe_splat_detailRange",  1000000.0f));
+
+
+                SplattingShaders splatting;
+
+                splatting.define( "SPLAT_EDIT",        _editMode );
+                splatting.define( "SPLAT_GPU_NOISE",   _gpuNoise );
+                splatting.define( "OE_USE_NORMAL_MAP", engine->normalTexturesRequired() );
+
+                splatting.replace( "COVERAGE_TEXTURE_MATRIX", coverageLayer->shareTexMatUniformName().get() );
+            
+                VirtualProgram* vp = VirtualProgram::getOrCreate(stateset);
+                splatting.load( vp, splatting.VertModel );
+                splatting.load( vp, splatting.VertView );
+                splatting.load( vp, splatting.Frag );
+                splatting.load( vp, splatting.Util );
+
+                // GPU noise is expensive, so only use it to tweak noise function values that you
+                // can later bake into the noise texture generator.
+                if ( _gpuNoise )
+                {                
+                    //osgEarth::replaceIn( fragmentShader, "#undef SPLAT_GPU_NOISE", "#define SPLAT_GPU_NOISE" );
+
+                    // Use --uniform on the command line to tweak these values:
+                    stateset->addUniform(new osg::Uniform("oe_splat_freq",   32.0f));
+                    stateset->addUniform(new osg::Uniform("oe_splat_pers",    0.8f));
+                    stateset->addUniform(new osg::Uniform("oe_splat_lac",     2.2f));
+                    stateset->addUniform(new osg::Uniform("oe_splat_octaves", 8.0f));
+
+                    // support shaders
+                    std::string noiseShaderSource = ShaderLoader::load( splatting.Noise, splatting );
+                    osg::Shader* noiseShader = new osg::Shader(osg::Shader::FRAGMENT, noiseShaderSource);
+                    vp->setShader( "oe_splat_noiseshaders", noiseShader );
+                }
+            }
+        }
+    }
+}
+
+
+void
+SplatTerrainEffect::onUninstall(TerrainEngineNode* engine)
+{
+    if ( engine )
+    {
+        if ( _noiseTexUnit >= 0 )
+        {
+            engine->getResources()->releaseTextureImageUnit( _noiseTexUnit );
+            _noiseTexUnit = -1;
+        }
+    
+        if ( _splatTexUnit >= 0 )
+        {
+            engine->getResources()->releaseTextureImageUnit( _splatTexUnit );
+            _splatTexUnit = -1;
+        }
+    }
+}
diff --git a/src/osgEarthSplat/Surface b/src/osgEarthSplat/Surface
new file mode 100644
index 0000000..ab8d92d
--- /dev/null
+++ b/src/osgEarthSplat/Surface
@@ -0,0 +1,115 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+ * Copyright 2016 Pelican Mapping
+ * http://osgearth.org
+ *
+ * osgEarth is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ */
+#ifndef OSGEARTH_PROCEDURAL_SURFACE
+#define OSGEARTH_PROCEDURAL_SURFACE 1
+
+#include "Export"
+#include "Coverage"
+#include "SplatCatalog"
+#include <osgEarth/Common>
+#include <osgEarth/Config>
+#include <osgEarth/URI>
+
+namespace osgEarth {
+    class Map;
+}
+
+namespace osgEarth { namespace Splat
+{
+    using namespace osgEarth;
+
+    /**
+     * Options pertaining to the terrain surface raster splatting.
+     */
+    class SurfaceOptions : public ConfigOptions
+    {
+    public:
+        SurfaceOptions(const ConfigOptions& conf = ConfigOptions()) : ConfigOptions(conf) {
+            fromConfig( _conf );
+        }
+
+        /** URI of the catalog file that describes the classification codes in the coverage data.
+            Define either this OR biomesURI. */
+        optional<URI>& catalogURI() { return _catalogURI; }
+        const optional<URI>& catalogURI() const { return _catalogURI; }
+
+    protected:
+        optional<URI> _catalogURI;
+
+    public:
+        void fromConfig(const Config& conf) {
+            conf.getIfSet("catalog", _catalogURI);
+        }
+        
+        Config getConfig() const {
+            Config conf = ConfigOptions::getConfig();
+            conf.key() = "surface";
+            conf.updateIfSet("catalog", _catalogURI);
+            return conf;
+        }
+
+        void mergeConfig( const Config& conf ) {
+            ConfigOptions::mergeConfig( conf );
+            fromConfig( conf );
+        }
+    };
+
+    /**
+     * Surface splatting configuration.
+     */
+    class OSGEARTHSPLAT_EXPORT Surface : public osg::Referenced
+    {
+    public:
+        /** Construct and empty data model */
+        Surface();
+
+    public:
+        /** Catalog that maps coverage codes to textures */
+        void setCatalog(SplatCatalog* catalog) { _catalog = catalog; }
+        SplatCatalog* getCatalog() const { return _catalog.get(); }
+
+        /**
+         * Loads textures for splatting and generates a sampling function.
+         * Returns false if something goes wrong
+         */
+        bool loadTextures(const Coverage* coverage, const osgDB::Options* dbo);
+
+        /** Gets the texture definition creates by loadTextures */
+        const SplatTextureDef& getTextureDef() const { return _textureDef; }
+
+    protected:
+        virtual ~Surface() { }
+
+    protected:
+        osg::ref_ptr<SplatCatalog> _catalog;
+        SplatTextureDef            _textureDef;
+
+        //bool createGLSLSamplingCode(const Coverage* coverage, std::string& output) const;
+
+        osg::Texture* createLUTBuffer(const Coverage* coverage) const;
+
+    public:
+
+        /** Initialize this Surface from a config. */
+        bool configure(const ConfigOptions& conf, const Map* map, const osgDB::Options* dbo);
+    };
+
+} } // namespace osgEarth::Splat
+
+#endif // OSGEARTH_PROCEDURAL_SURFACE
diff --git a/src/osgEarthSplat/Surface.cpp b/src/osgEarthSplat/Surface.cpp
new file mode 100644
index 0000000..8306743
--- /dev/null
+++ b/src/osgEarthSplat/Surface.cpp
@@ -0,0 +1,227 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+ * Copyright 2016 Pelican Mapping
+ * http://osgearth.org
+ *
+ * osgEarth is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ */
+#include "Surface"
+#include "SplatCatalog"
+#include "SplatShaders"
+#include <osgEarth/Map>
+#include <osgEarth/ShaderGenerator>
+#include <osgDB/Options>
+#include <osg/TextureBuffer>
+
+using namespace osgEarth;
+using namespace osgEarth::Splat;
+
+#define LC "[Surface] "
+
+Surface::Surface()
+{
+    //nop
+}
+
+bool
+Surface::configure(const ConfigOptions& conf, const Map* map, const osgDB::Options* dbo)
+{
+    SurfaceOptions in(conf);
+
+    // Read in the catalog.
+    _catalog = SplatCatalog::read( in.catalogURI().get(), dbo );
+    if ( !_catalog.valid() )
+    {
+        OE_WARN << LC << "Failed to read catalog for surface\n";
+        return false;
+    }
+    
+    return true;
+}
+
+bool
+Surface::loadTextures(const Coverage* coverage, const osgDB::Options* dbo)
+{
+    int numValidTextures = 0;
+
+    if ( coverage == 0L || !_catalog.valid() )
+        return false;
+
+    if ( _catalog->createSplatTextureDef(dbo, _textureDef) )
+    {
+        _textureDef._splatLUTBuffer = createLUTBuffer(coverage);
+#if 0
+        // loaded, now create a sampling function.
+        std::string code;
+        if ( !createGLSLSamplingCode(coverage, code) )
+        {
+            OE_WARN << LC << "Failed to generate sampling code\n";
+            return false;
+        }
+
+        _textureDef._samplingFunction = code;
+#endif
+    }
+    else
+    {
+        OE_WARN << LC << "Failed to create a texture for a catalog (" << _catalog->name().get() << ")\n";
+        return false;
+    }
+
+    return true;
+}
+
+namespace
+{
+#define INDENTATION 4
+    struct indent {
+        indent(int level) :_level(level){}
+        int _level;
+        friend std::ostream& operator<<(std::ostream& os, const indent& val) {
+            for (int i=0; i<val._level * INDENTATION; ++i) 
+                os << ' ';
+            return os;
+        }
+    };
+
+    void write(std::ostream& buf, const SplatRangeData* rangeData, int I)
+    {
+        buf << indent(I) << "primary = " << (rangeData->_textureIndex) << ".0;\n";
+        //if (rangeData->_detail.isSet()) {
+        //    buf << indent(I) << "detail = " << (rangeData->_detail->_textureIndex) << ".0;\n";
+        //    if (rangeData->_detail->_brightness.isSet())
+        //        buf << indent(I) << "brightness = " << rangeData->_detail->_brightness.get() << ";\n";
+        //    if (rangeData->_detail->_contrast.isSet())
+        //        buf << indent(I) << "contrast = " << rangeData->_detail->_contrast.get() << ";\n";
+        //    if (rangeData->_detail->_threshold.isSet())
+        //        buf << indent(I) << "threshold = " << rangeData->_detail->_threshold.get() << ";\n";
+        //    if (rangeData->_detail->_slope.isSet())
+        //        buf << indent(I) << "slope = " << rangeData->_detail->_slope.get() << ";\n";
+        //}
+    }
+}
+
+#define NUM_FLOATS_PER_LOD 6
+#define NUM_LODS 26
+#define NUM_CLASSES 256
+
+namespace
+{
+    struct LOD {
+        LOD() : primary(-1.0f), detail(-1.0f), brightness(1.0f), contrast(1.0f), threshold(0.0f), slope(0.0f) { }
+        float primary, detail, brightness, contrast, threshold, slope;
+    };
+
+    void write(LOD& lod, const SplatRangeData& data)
+    {
+        lod.primary = (float)data._textureIndex;
+        if (data._detail.isSet())
+        {
+            lod.detail = (float)data._detail->_textureIndex;
+            if (data._detail->_brightness.isSet())
+                lod.brightness = data._detail->_brightness.get();
+            if (data._detail->_contrast.isSet())
+                lod.contrast = data._detail->_contrast.get();
+            if (data._detail->_threshold.isSet())
+                lod.threshold = data._detail->_threshold.get();
+            if (data._detail->_slope.isSet())
+                lod.slope = data._detail->_slope.get();
+        }
+    }
+}
+
+osg::Texture*
+Surface::createLUTBuffer(const Coverage* coverage) const
+{
+    typedef LOD CoverageClass[NUM_LODS];
+
+    typedef CoverageClass LUT[NUM_CLASSES];
+
+    LUT lut;
+
+    // Build the LUT!
+    const SplatCoverageLegend::Predicates& preds = coverage->getLegend()->getPredicates();
+    for (SplatCoverageLegend::Predicates::const_iterator p = preds.begin(); p != preds.end(); ++p)
+    {
+        const CoverageValuePredicate* pred = p->get();
+
+        if (pred->_exactValue.isSet())
+        {
+            int coverageIndex = (int)(::atoi(pred->_exactValue.get().c_str()));
+            if (coverageIndex >= 0 && coverageIndex < NUM_CLASSES)
+            {
+                CoverageClass& coverageClass = lut[coverageIndex];
+            
+                // Look up by class name:
+                const std::string& className = pred->_mappedClassName.get();
+                const SplatLUT::const_iterator i = _textureDef._splatLUT.find(className);
+                if (i != _textureDef._splatLUT.end())
+                {
+                    const SplatRangeDataVector& ranges = i->second;
+                    unsigned r = 0;
+                    for (unsigned lod = 0; lod < NUM_LODS; ++lod)
+                    {
+                        const SplatRangeData& range = ranges[r];
+                        write(coverageClass[lod], range);
+                        if (range._maxLOD.isSet() && lod == range._maxLOD.get() && (r + 1) < ranges.size())
+                            ++r;
+                    }
+                }
+            }
+        }
+    }
+
+    // Encode the LUT into a texture buffer.
+    osg::Image* image = new osg::Image();
+    image->allocateImage(NUM_CLASSES * NUM_LODS, 1, 1, GL_RGBA32F_ARB, GL_FLOAT);
+
+    // Populate the LUT image. Each LOD fits into a single RGBA GL_FLOAT vec4
+    // by packing 6 floats into 4. See below for packing approach
+    GLfloat* ptr = reinterpret_cast<GLfloat*>( image->data() );
+    for (unsigned c=0; c<NUM_CLASSES; ++c)
+    {
+        for (unsigned lod=0; lod<NUM_LODS; ++lod)
+        {
+            LOD& record = lut[c][lod];
+
+            *ptr++ = record.primary;
+            *ptr++ = record.detail;
+
+            // Pack two values into one float. First each value is truncated to a maximum
+            // of 2 decimal places; then the first value goes left of the decimal, and the
+            // second value goes to the right. The shader will unpack after reading.
+            // We do this so that a single texelFetch call will retrieve the entire record.
+
+            float b = (int)(record.brightness*100.0);
+            float c = (int)(record.contrast*100.0);
+            *ptr++ = b + (c/1000.0f);
+
+            float t = (int)(record.threshold*100.0);
+            float s = (int)(record.slope*100.0);
+            *ptr++ = t + (s/1000.0f);
+        }
+    }
+
+    // create a buffer object
+    osg::TextureBuffer* buf = new osg::TextureBuffer();
+    buf->setImage(image);
+    buf->setInternalFormat(GL_RGBA32F_ARB);
+    buf->setInternalFormatMode(osg::Texture::USE_IMAGE_DATA_FORMAT);
+    buf->setUnRefImageDataAfterApply(true);
+
+    // Tell the shader generator to skip the positioning texture.
+    ShaderGenerator::setIgnoreHint(buf, true);
+
+    return buf;
+}
diff --git a/src/osgEarthSplat/Zone b/src/osgEarthSplat/Zone
new file mode 100644
index 0000000..a98a0a3
--- /dev/null
+++ b/src/osgEarthSplat/Zone
@@ -0,0 +1,155 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+ * Copyright 2016 Pelican Mapping
+ * http://osgearth.org
+ *
+ * osgEarth is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ */
+#ifndef OSGEARTH_PROCEDURAL_ZONE
+#define OSGEARTH_PROCEDURAL_ZONE 1
+
+#include "Export"
+#include "Surface"
+#include "LandCover"
+#include <osgEarth/TerrainEngineNode>
+#include <osg/BoundingBox>
+#include <osg/Polytope>
+#include <osg/StateSet>
+#include <osg/NodeCallback>
+#include <vector>
+
+namespace osgDB {
+    class Options;
+}
+
+namespace osgEarth { namespace Splat
+{
+    using namespace osgEarth;
+
+    /**
+     * A zone limits a particular surface or land cover layer to a set of
+     * geographic boundaries.
+     */
+    class OSGEARTHSPLAT_EXPORT Zone : public osg::Referenced
+    {
+    public:
+        struct Boundary
+        {
+            GeoExtent     extent;
+            double        zmin, zmin2;
+            double        zmax, zmax2;
+            double        meanRadius2;
+            osg::Polytope tope;
+        };
+        typedef std::vector<Boundary> Boundaries;
+
+    public:
+        Zone() : _uid(0) { }
+
+        void setName(const std::string& name) { _name = name; }
+        const std::string& getName() const { return _name; }
+
+        Boundaries& getBoundaries() { return _boundaries; }
+        const Boundaries& getBoundaries() const { return _boundaries; }
+
+        Surface* getSurface() const { return _surface.get(); }
+
+        LandCover* getLandCover() const { return _landCover.get(); }
+
+        osg::StateSet* getStateSet() { return _stateSet.get(); }
+
+        osg::StateSet* getOrCreateStateSet();
+
+        bool contains(const osg::Vec3& points) const;
+
+        void setUID(UID uid) { _uid = uid; }
+        UID getUID() const { return _uid; }
+
+    protected:
+        virtual ~Zone() { }
+        std::string                 _name;
+        UID                         _uid;
+        Boundaries                  _boundaries;
+        osg::ref_ptr<Surface>       _surface;
+        osg::ref_ptr<LandCover>     _landCover;
+        osg::ref_ptr<osg::StateSet> _stateSet;
+
+    public:
+        bool configure(const ConfigOptions& conf, const Map* map, const osgDB::Options* dbo);
+    };
+
+    typedef std::vector<osg::ref_ptr<Zone> > Zones;
+
+    
+    /**
+     * Cull callback that will select the most appropriate Zone based on the camera position
+     * Internal - no export
+     */
+    class OSGEARTHSPLAT_EXPORT ZoneSwitcher : public osg::NodeCallback
+    {
+    public:
+        ZoneSwitcher(const Zones& zones) : _zones(zones) { }
+
+    public: // NodeCallback
+        void operator()(osg::Node* node, osg::NodeVisitor* nv);
+
+    protected:
+        Zones _zones;
+    };
+
+    //........................................................................
+
+    /**
+     * Serializable options data for a Zone object
+     */
+    class OSGEARTHSPLAT_EXPORT ZoneOptions : public ConfigOptions
+    {
+    public:
+        ZoneOptions(const ConfigOptions& conf = ConfigOptions()) : ConfigOptions(conf) {
+            fromConfig(_conf);
+        }
+
+        /** Name of this zone (readable) */
+        optional<std::string> name() { return _name; }
+        const optional<std::string> name() const { return _name; }
+
+        /** Boundary set for this zone (optional) */
+        std::vector<osg::BoundingBox>& boundaries() { return _boundaries; }
+        const std::vector<osg::BoundingBox>& boundaries() const { return _boundaries; }
+
+        /** Surface rendering options */
+        optional<SurfaceOptions>& surface() { return _surface; }
+        const optional<SurfaceOptions>& surface() const { return _surface; }
+
+        /** Land Cover rendering options */
+        optional<LandCoverOptions>& landCover() { return _landCover; }
+        const optional<LandCoverOptions>& landCover() const { return _landCover; }
+
+    protected:
+        optional<std::string>         _name;
+        std::vector<osg::BoundingBox> _boundaries;
+        optional<SurfaceOptions>      _surface;
+        optional<LandCoverOptions>    _landCover;
+
+    public:
+        void fromConfig(const Config& conf);
+        Config getConfig() const;
+    };
+
+    typedef std::vector<ZoneOptions> ZoneOptionsVector;
+
+
+} } // namespace osgEarth::Splat
+
+#endif // OSGEARTH_PROCEDURAL_ZONE
diff --git a/src/osgEarthSplat/Zone.cpp b/src/osgEarthSplat/Zone.cpp
new file mode 100644
index 0000000..2403a7e
--- /dev/null
+++ b/src/osgEarthSplat/Zone.cpp
@@ -0,0 +1,196 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+ * Copyright 2016 Pelican Mapping
+ * http://osgearth.org
+ *
+ * osgEarth is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ */
+#include "Zone"
+#include <osgEarth/TraversalData>
+#include <osgUtil/CullVisitor>
+
+#define LC "[Zone] "
+
+using namespace osgEarth;
+using namespace osgEarth::Splat;
+
+bool
+Zone::configure(const ConfigOptions& options, const Map* map, const osgDB::Options* dbo)
+{
+    ZoneOptions in(options);
+
+    if ( in.name().isSet() )
+        setName( in.name().get() );
+
+    for(int i=0; i<in.boundaries().size(); ++i)
+    {
+        const osg::BoundingBox& box = in.boundaries().at(i);
+        _boundaries.push_back( Boundary() );
+        Boundary& b = _boundaries.back();
+        
+        GeoExtent extent(
+            map->getSRS()->getGeographicSRS(),
+            osg::clampBetween(box.xMin(), -180.0f, 180.0f),
+            osg::clampBetween(box.yMin(),  -90.0f,  90.0f),
+            osg::clampBetween(box.xMax(), -180.0f, 180.0f),
+            osg::clampBetween(box.yMax(),  -90.0f,  90.0f));
+
+        extent.createPolytope( b.tope );
+        b.zmin2 = box.zMin() > -FLT_MAX ? box.zMin()*box.zMin() : box.zMin();
+        b.zmax2 = box.zMax() <  FLT_MAX ? box.zMax()*box.zMax() : box.zMax();
+
+        // this only needs to be very approximate.
+        double meanRadius = extent.getSRS()->isGeographic() ?
+            extent.getSRS()->getEllipsoid()->getRadiusEquator() : 0.0;
+        b.meanRadius2 = meanRadius*meanRadius;
+    }
+    
+    if ( in.surface().isSet() )
+    {
+        _surface = new Surface();
+        if ( !_surface->configure(in.surface().get(), map, dbo) )
+        {
+            OE_WARN << LC << "Surface data is not properly configured; surface splatting disabled.\n";
+            _surface = 0L;
+        }
+    }
+
+    if ( in.landCover().isSet() )
+    {
+        _landCover = new LandCover();
+        if ( !_landCover->configure(in.landCover().get(), map, dbo) )
+        {
+            OE_WARN << LC << "Land cover is not properly configured; land cover disabled.\n";
+            _landCover = 0L;
+        }
+    }
+
+    return true;
+}
+
+bool
+Zone::contains(const osg::Vec3& point) const
+{
+    for(Boundaries::const_iterator b = _boundaries.begin(); b != _boundaries.end(); ++b)
+    {
+        if ( b->tope.empty() )
+        {
+            return true;
+        }
+
+        else if ( b->tope.contains(point) )
+        {
+            double hat2 = point.length2() - b->meanRadius2; // assumes round earth
+            if ( hat2 >= b->zmin2 && hat2 <= b->zmax2 )
+            {
+                return true;
+            }
+        }
+    }
+
+    return false;
+}
+
+osg::StateSet*
+Zone::getOrCreateStateSet() 
+{
+    if ( !_stateSet.valid() )
+        _stateSet = new osg::StateSet();
+    return _stateSet.get();
+}
+
+void
+ZoneOptions::fromConfig(const Config& conf)
+{
+    conf.getIfSet("name", _name);
+    const Config* boundaries = conf.child_ptr("boundaries");
+    if ( boundaries ) {
+        for(ConfigSet::const_iterator i = boundaries->children().begin(); i != boundaries->children().end(); ++i) {
+            _boundaries.push_back(osg::BoundingBox(
+                i->value("xmin", -FLT_MAX), i->value("ymin", -FLT_MAX), i->value("zmin", -FLT_MAX),
+                i->value("xmax",  FLT_MAX), i->value("ymax",  FLT_MAX), i->value("zmax",  FLT_MAX)));
+        }
+    }
+    conf.getObjIfSet( "surface",    _surface );
+    conf.getObjIfSet( "land_cover", _landCover );
+}
+
+Config
+ZoneOptions::getConfig() const
+{
+    Config conf("zone");
+    conf.addIfSet("name", _name);
+    if ( _boundaries.size() > 0 ) {
+        Config regions("boundaries");
+        for(int i=0; i<_boundaries.size(); ++i) {
+            Config region("boundary");
+            if ( _boundaries[i].xMin() > -FLT_MAX ) region.set("xmin", _boundaries[i].xMin());
+            if ( _boundaries[i].yMin() > -FLT_MAX ) region.set("ymin", _boundaries[i].yMin());
+            if ( _boundaries[i].zMin() > -FLT_MAX ) region.set("zmin", _boundaries[i].zMin());
+            if ( _boundaries[i].xMax() <  FLT_MAX ) region.set("xmax", _boundaries[i].xMax());
+            if ( _boundaries[i].yMax() <  FLT_MAX ) region.set("ymax", _boundaries[i].yMax());
+            if ( _boundaries[i].zMax() <  FLT_MAX ) region.set("zmax", _boundaries[i].zMax());
+            regions.add(region);
+        }
+        conf.add(regions);
+    }
+    conf.updateObjIfSet( "surface",    _surface );
+    conf.updateObjIfSet( "land_cover", _landCover );
+    return conf;
+}
+
+void
+ZoneSwitcher::operator()(osg::Node* node, osg::NodeVisitor* nv)
+{
+    osg::StateSet* stateset = 0L;
+
+    if ( _zones.size() > 0 )
+    {
+        osg::Vec3d vp = nv->getViewPoint();
+        double z2 = vp.length2();
+
+        unsigned zoneIndex = 0;
+        unsigned finalZoneIndex = ~0;
+
+        for(unsigned z=0; z<_zones.size() && !stateset; ++z)
+        {
+            if ( _zones[z]->contains(vp) )
+            {
+                stateset = _zones[z]->getStateSet();
+                finalZoneIndex      = zoneIndex;
+            }
+            if ( _zones[z]->getLandCover() )
+            {
+                zoneIndex++;
+            }
+        }
+
+        if ( !stateset )
+        {
+            stateset = _zones[0]->getStateSet();
+            finalZoneIndex = 0;
+        }                
+        
+        // Relays the zone index to the Patch callback.
+        VisitorData::store(*nv, "oe.LandCover.zoneIndex", new RefUID(finalZoneIndex));
+    }
+
+    if ( stateset )
+        static_cast<osgUtil::CullVisitor*>(nv)->pushStateSet( stateset );
+
+    traverse(node, nv);
+
+    if ( stateset )
+        static_cast<osgUtil::CullVisitor*>(nv)->popStateSet();
+}
diff --git a/src/osgEarthSymbology/AltitudeSymbol b/src/osgEarthSymbology/AltitudeSymbol
index 0f612b4..175180b 100644
--- a/src/osgEarthSymbology/AltitudeSymbol
+++ b/src/osgEarthSymbology/AltitudeSymbol
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthSymbology/AltitudeSymbol.cpp b/src/osgEarthSymbology/AltitudeSymbol.cpp
index 6358c1c..b27b21b 100644
--- a/src/osgEarthSymbology/AltitudeSymbol.cpp
+++ b/src/osgEarthSymbology/AltitudeSymbol.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -98,24 +98,38 @@ void
 AltitudeSymbol::parseSLD(const Config& c, Style& style)
 {
     if ( match(c.key(), "altitude-clamping") ) {
-        if      ( match(c.value(), "none") )     
+        if      ( match(c.value(), "none") ) {
             style.getOrCreate<AltitudeSymbol>()->clamping() = CLAMP_NONE;
-        else if ( match(c.value(), "terrain") )  
+        }
+        else if ( match(c.value(), "terrain") )  {
             style.getOrCreate<AltitudeSymbol>()->clamping() = CLAMP_TO_TERRAIN;
-        else if ( match(c.value(), "absolute") ) 
+        }
+        else if ( match(c.value(), "absolute") ) {
             style.getOrCreate<AltitudeSymbol>()->clamping() = CLAMP_ABSOLUTE;
-        else if ( match(c.value(), "relative") ) 
+        }
+        else if ( match(c.value(), "relative") ) {
             style.getOrCreate<AltitudeSymbol>()->clamping() = CLAMP_RELATIVE_TO_TERRAIN;
-        else if ( match(c.value(), "terrain-drape") )
-        {
+        }
+        else if ( match(c.value(), "relative-gpu") ) {
+            style.getOrCreate<AltitudeSymbol>()->clamping() = CLAMP_RELATIVE_TO_TERRAIN;
+            style.getOrCreate<AltitudeSymbol>()->technique() = TECHNIQUE_GPU;
+        }
+        else if ( match(c.value(), "terrain-drape") ) {
             style.getOrCreate<AltitudeSymbol>()->clamping()  = CLAMP_TO_TERRAIN;
             style.getOrCreate<AltitudeSymbol>()->technique() = TECHNIQUE_DRAPE;
         }
-        else if ( match(c.value(), "terrain-gpu") )
-        {
+        else if ( match(c.value(), "terrain-gpu") ) {
             style.getOrCreate<AltitudeSymbol>()->clamping()  = CLAMP_TO_TERRAIN;
             style.getOrCreate<AltitudeSymbol>()->technique() = TECHNIQUE_GPU;
         }
+        else if ( match(c.value(), "terrain-scene") ) {
+            style.getOrCreate<AltitudeSymbol>()->clamping()  = CLAMP_TO_TERRAIN;
+            style.getOrCreate<AltitudeSymbol>()->technique() = TECHNIQUE_SCENE;
+        }
+        else if ( match(c.value(), "relative-scene") ) {
+            style.getOrCreate<AltitudeSymbol>()->clamping()  = CLAMP_RELATIVE_TO_TERRAIN;
+            style.getOrCreate<AltitudeSymbol>()->technique() = TECHNIQUE_SCENE;
+        }
     }
     else if ( match(c.key(), "altitude-technique") ) {
         if      ( match(c.value(), "map") )
diff --git a/src/osgEarthSymbology/BBoxSymbol b/src/osgEarthSymbology/BBoxSymbol
new file mode 100644
index 0000000..a07db31
--- /dev/null
+++ b/src/osgEarthSymbology/BBoxSymbol
@@ -0,0 +1,80 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+ * Copyright 2016 Pelican Mapping
+ * http://osgearth.org
+ *
+ * osgEarth is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+#ifndef OSGEARTHSYMBOLOGY_BBOX_SYMBOL_H
+#define OSGEARTHSYMBOLOGY_BBOX_SYMBOL_H 1
+
+#include <osgEarthSymbology/Symbol>
+#include <osgEarthSymbology/Expression>
+#include <osgEarthSymbology/Fill>
+#include <osgEarthSymbology/Stroke>
+
+namespace osgEarth { namespace Symbology
+{
+    /**
+     * Symbol that describes how to render bounding boxes around text labels.
+     */
+    class OSGEARTHSYMBOLOGY_EXPORT BBoxSymbol : public Symbol
+    {
+    public:
+
+        enum BboxGeom {
+            GEOM_BOX,
+            GEOM_BOX_ORIENTED
+        };
+
+        META_Object(osgEarthSymbology, BBoxSymbol);
+    	
+        BBoxSymbol(const BBoxSymbol& rhs,const osg::CopyOp& copyop=osg::CopyOp::SHALLOW_COPY);
+        BBoxSymbol( const Config& conf =Config() );
+
+        /** dtor */
+        virtual ~BBoxSymbol() { }
+
+        /** Bounding box fill color. */
+        optional<Fill>& fill() { return _fill; }
+        const optional<Fill>& fill() const { return _fill; }
+
+        /** Bounding box border color. */
+        optional<Stroke>& border() { return _border; }
+        const optional<Stroke>& border() const { return _border; }
+
+        /** Bounding box border margin. */
+        optional<float>& margin() { return _margin; }
+        const optional<float>& margin() const { return _margin; }
+
+        /** Bounding box geom to draw. */
+        optional<BboxGeom>& geom() { return _bboxGeom; }
+        const optional<BboxGeom>& geom() const { return _bboxGeom; }
+
+    public:
+        virtual Config getConfig() const;
+        virtual void mergeConfig( const Config& conf );
+        static void parseSLD(const Config& c, class Style& style);
+
+    protected:
+        optional<Fill>              _fill;
+        optional<Stroke>            _border;
+        optional<float>             _margin;
+        optional<BboxGeom>          _bboxGeom;
+    };
+
+} } // namespace osgEarth::Symbology
+
+#endif // OSGEARTHSYMBOLOGY_BBOX_SYMBOL_H
diff --git a/src/osgEarthSymbology/BBoxSymbol.cpp b/src/osgEarthSymbology/BBoxSymbol.cpp
new file mode 100644
index 0000000..2dd6885
--- /dev/null
+++ b/src/osgEarthSymbology/BBoxSymbol.cpp
@@ -0,0 +1,94 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+ * Copyright 2016 Pelican Mapping
+ * http://osgearth.org
+ *
+ * osgEarth is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ */
+#include <osgEarthSymbology/BBoxSymbol>
+#include <osgEarthSymbology/Style>
+
+using namespace osgEarth;
+using namespace osgEarth::Symbology;
+
+OSGEARTH_REGISTER_SIMPLE_SYMBOL(bbox, BBoxSymbol);
+
+BBoxSymbol::BBoxSymbol( const Config& conf ) :
+Symbol                ( conf ),
+_fill                 ( Fill( 1, 1, 1, 1 ) ),
+_border               ( Stroke( 0.3, 0.3, 0.3, 1) ),
+_margin               ( 3 ),
+_bboxGeom             ( GEOM_BOX )
+{
+    mergeConfig(conf);
+}
+
+BBoxSymbol::BBoxSymbol(const BBoxSymbol& rhs,const osg::CopyOp& copyop):
+Symbol(rhs, copyop),
+_fill                 ( rhs._fill ),
+_border               ( rhs._border ),
+_margin               ( rhs._margin ),
+_bboxGeom             ( rhs._bboxGeom )
+{
+
+}
+
+Config
+BBoxSymbol::getConfig() const
+{
+    Config conf = Symbol::getConfig();
+    conf.key() = "text-bbox";
+    conf.addObjIfSet( "fill", _fill );
+    conf.addObjIfSet( "border", _border );
+    conf.addIfSet( "margin", _margin );
+
+    conf.addIfSet( "geom", "box", _bboxGeom, GEOM_BOX );
+    conf.addIfSet( "geom", "box_oriented", _bboxGeom, GEOM_BOX_ORIENTED );
+
+    return conf;
+}
+
+void
+BBoxSymbol::mergeConfig( const Config& conf )
+{
+    conf.getObjIfSet( "fill", _fill );
+    conf.getObjIfSet( "border", _border );
+    conf.getIfSet( "margin", _margin );
+
+    conf.getIfSet( "geom", "box", _bboxGeom, GEOM_BOX );
+    conf.getIfSet( "geom", "box_oriented", _bboxGeom, GEOM_BOX_ORIENTED );
+}
+
+void
+BBoxSymbol::parseSLD(const Config& c, Style& style)
+{
+    if ( match(c.key(), "text-bbox-fill") ) {
+       style.getOrCreate<BBoxSymbol>()->fill()->color() = Color(c.value());
+    }
+    else if ( match(c.key(), "text-bbox-border") ) {
+        style.getOrCreate<BBoxSymbol>()->border()->color() = Color(c.value());
+    }
+    else if ( match(c.key(), "text-bbox-border-width") ) {
+        style.getOrCreate<BBoxSymbol>()->border()->width() = as<float>( c.value(), 1.0f );
+    }
+    else if ( match(c.key(), "text-bbox-margin") ) {
+        style.getOrCreate<BBoxSymbol>()->margin() = as<float>(c.value(), 3.0f);
+    }
+    else if ( match(c.key(), "text-bbox-geom") ) {
+        if      ( match(c.value(), "box") )
+            style.getOrCreate<BBoxSymbol>()->geom() = GEOM_BOX;
+        else if ( match(c.value(), "box_oriented") )
+            style.getOrCreate<BBoxSymbol>()->geom() = GEOM_BOX_ORIENTED;
+    }
+}
diff --git a/src/osgEarthSymbology/BillboardResource b/src/osgEarthSymbology/BillboardResource
new file mode 100644
index 0000000..87fdb74
--- /dev/null
+++ b/src/osgEarthSymbology/BillboardResource
@@ -0,0 +1,70 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+ * Copyright 2016 Pelican Mapping
+ * http://osgearth.org
+ *
+ * osgEarth is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+#ifndef OSGEARTHSYMBOLOGY_BILLBOARD_RESOURCE_H
+#define OSGEARTHSYMBOLOGY_BILLBOARD_RESOURCE_H 1
+
+#include <osgEarthSymbology/Common>
+#include <osgEarthSymbology/InstanceResource>
+
+namespace osgEarth { namespace Symbology
+{
+    using namespace osgEarth;
+
+    /**
+     * A resource that represents a real-world-sized image that can be used as
+     * a billboard (camera-facing 2D object)
+     */
+    class OSGEARTHSYMBOLOGY_EXPORT BillboardResource : public InstanceResource
+    {
+    public:
+        /** Constructs a new resource. */
+        BillboardResource( const Config& conf =Config() );
+
+        /** dtor */
+        virtual ~BillboardResource() { }      
+
+        bool is2D() const { return false; }
+
+    public: // properties
+
+        /** Width of the billboard image in meters */
+        optional<float>& width() { return _width; }
+        const optional<float>& width() const { return _width; }
+
+        /** Height of the billboard image in meters */
+        optional<float>& height() { return _height; }
+        const optional<float>& height() const { return _height; }
+
+    public: // serialization methods
+
+        virtual Config getConfig() const;
+        void mergeConfig( const Config& conf );
+
+    protected: // InstanceResource
+
+        virtual osg::Node* createNodeFromURI(const URI& uri, const osgDB::Options* dbOptions) const;
+
+        optional<float> _width;
+        optional<float> _height;
+    };
+
+} } // namespace osgEarth::Symbology
+
+#endif // OSGEARTHSYMBOLOGY_BILLBOARD_RESOURCE_H
diff --git a/src/osgEarthSymbology/BillboardResource.cpp b/src/osgEarthSymbology/BillboardResource.cpp
new file mode 100644
index 0000000..14c762e
--- /dev/null
+++ b/src/osgEarthSymbology/BillboardResource.cpp
@@ -0,0 +1,57 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+ * Copyright 2016 Pelican Mapping
+ * http://osgearth.org
+ *
+ * osgEarth is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ */
+#include <osgEarthSymbology/BillboardResource>
+
+#define LC "[BillboardResource] "
+
+using namespace osgEarth;
+using namespace osgEarth::Symbology;
+
+
+BillboardResource::BillboardResource(const Config& conf) :
+InstanceResource( conf )
+{
+    mergeConfig( conf );
+}
+
+void
+BillboardResource::mergeConfig(const Config& conf)
+{
+    conf.getIfSet( "width", _width );
+    conf.getIfSet( "height", _height );
+}
+
+Config
+BillboardResource::getConfig() const
+{
+    Config conf = InstanceResource::getConfig();
+    conf.key() = "billboard";
+    conf.addIfSet( "width", _width );
+    conf.addIfSet( "height", _height );
+    //nop
+    return conf;
+}
+
+osg::Node*
+BillboardResource::createNodeFromURI(const URI& uri, const osgDB::Options* dbOptions) const
+{
+    // unsupported atm.
+    osg::Node* node = 0L;
+    return node;
+}
diff --git a/src/osgEarthSymbology/BillboardSymbol b/src/osgEarthSymbology/BillboardSymbol
new file mode 100644
index 0000000..b44aab0
--- /dev/null
+++ b/src/osgEarthSymbology/BillboardSymbol
@@ -0,0 +1,82 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+ * Copyright 2016 Pelican Mapping
+ * http://osgearth.org
+ *
+ * osgEarth is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+#ifndef OSGEARTHSYMBOLOGY_BILLBOARD_SYMBOL_H
+#define OSGEARTHSYMBOLOGY_BILLBOARD_SYMBOL_H 1
+
+#include <climits>
+
+#include <osgEarth/Common>
+#include <osgEarthSymbology/InstanceSymbol>
+#include <osg/Vec3f>
+
+namespace osgEarth { namespace Symbology
+{
+    class InstanceResource;
+
+    /**
+     * Represents a 2D camera-facing image
+     */
+    class OSGEARTHSYMBOLOGY_EXPORT BillboardSymbol : public InstanceSymbol
+    {
+    public:
+        META_Object(osgEarthSymbology, BillboardSymbol);
+
+        BillboardSymbol(const BillboardSymbol& rhs,const osg::CopyOp& copyop=osg::CopyOp::SHALLOW_COPY);
+        BillboardSymbol( const Config& conf =Config() );
+
+        /** dtor */
+        virtual ~BillboardSymbol() { }
+
+    public: // properties
+
+        /** Width of the billboard image in meters */
+        optional<float>& width() { return _width; }
+        const optional<float>& width() const { return _width; }
+
+        /** Height of the billboard image in meters */
+        optional<float>& height() { return _height; }
+        const optional<float>& height() const { return _height; }
+        
+        
+    public: // non-serialized properties (for programmatic use only)
+
+        /** Explicit model to use for model placement */
+        void setImage(osg::Image* image) { _image = image; }
+        const osg::Image* getImage() const { return _image.get(); }
+
+    public:
+        virtual Config getConfig() const;
+        virtual void mergeConfig( const Config& conf );
+        static void parseSLD(const Config& c, class Style& style);
+    
+    public: // InstanceSymbol
+
+        /** Creates a new (empty) resource appropriate for this symbol */
+        virtual InstanceResource* createResource() const;
+
+    protected:
+        optional<float> _width;
+        optional<float> _height;
+        osg::ref_ptr<osg::Image> _image;
+    };
+
+} } // namespace osgEarth::Symbology
+
+#endif
diff --git a/src/osgEarthSymbology/BillboardSymbol.cpp b/src/osgEarthSymbology/BillboardSymbol.cpp
new file mode 100644
index 0000000..e71a902
--- /dev/null
+++ b/src/osgEarthSymbology/BillboardSymbol.cpp
@@ -0,0 +1,81 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+ * Copyright 2016 Pelican Mapping
+ * http://osgearth.org
+ *
+ * osgEarth is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ */
+#include <osgEarthSymbology/BillboardSymbol>
+#include <osgEarthSymbology/BillboardResource>
+#include <osgEarthSymbology/Style>
+
+using namespace osgEarth;
+using namespace osgEarth::Symbology;
+
+OSGEARTH_REGISTER_SIMPLE_SYMBOL(billboard, BillboardSymbol);
+
+
+BillboardSymbol::BillboardSymbol(const BillboardSymbol& rhs,const osg::CopyOp& copyop):
+InstanceSymbol(rhs, copyop),
+_image        (rhs._image.get())
+{
+    //nop
+}
+
+BillboardSymbol::BillboardSymbol( const Config& conf ) :
+InstanceSymbol( conf )
+{
+    mergeConfig( conf );
+}
+
+Config 
+BillboardSymbol::getConfig() const
+{
+    Config conf = InstanceSymbol::getConfig();
+    conf.key() = "billboard";
+    conf.addIfSet( "width", _width );
+    conf.addIfSet( "height", _height );
+    conf.addNonSerializable( "BillboardSymbol::image", _image.get() );
+    return conf;
+}
+
+void 
+BillboardSymbol::mergeConfig( const Config& conf )
+{
+    conf.getIfSet( "width", _width );
+    conf.getIfSet( "height", _height );
+    _image = conf.getNonSerializable<osg::Image>( "BillboardSymbol::image" );
+}
+
+InstanceResource*
+BillboardSymbol::createResource() const
+{
+    return new BillboardResource();
+}
+
+void
+BillboardSymbol::parseSLD(const Config& c, Style& style)
+{
+    if ( match(c.key(), "billboard-image") ) {
+        style.getOrCreate<BillboardSymbol>()->url() = c.value();
+        style.getOrCreate<BillboardSymbol>()->url()->setURIContext( c.referrer() );
+    }
+    else if ( match(c.key(), "billboard-width") ) {
+        style.getOrCreate<BillboardSymbol>()->width() = as<float>(c.value(), 10.0f);
+    }
+    else if ( match(c.key(), "billboard-height") ) {
+        style.getOrCreate<BillboardSymbol>()->height() = as<float>(c.value(), 10.0f);
+    }
+}
+
diff --git a/src/osgEarthSymbology/CMakeLists.txt b/src/osgEarthSymbology/CMakeLists.txt
index 58b09ab..36005ea 100644
--- a/src/osgEarthSymbology/CMakeLists.txt
+++ b/src/osgEarthSymbology/CMakeLists.txt
@@ -15,6 +15,9 @@ SET(LIB_PUBLIC_HEADERS
 #   header files go here
     AGG.h
     AltitudeSymbol
+    BBoxSymbol
+    BillboardResource
+    BillboardSymbol
     Common
     Color
     CoverageSymbol
@@ -60,6 +63,9 @@ ADD_LIBRARY(${LIB_NAME} ${OSGEARTH_USER_DEFINED_DYNAMIC_OR_STATIC}
     ${LIB_PUBLIC_HEADERS}
 #  .cpp files go here
     AltitudeSymbol.cpp
+    BBoxSymbol.cpp
+    BillboardResource.cpp
+    BillboardSymbol.cpp
     Color.cpp
     CoverageSymbol.cpp
     CssUtils.cpp
diff --git a/src/osgEarthSymbology/Color b/src/osgEarthSymbology/Color
index 507a85a..5773aee 100644
--- a/src/osgEarthSymbology/Color
+++ b/src/osgEarthSymbology/Color
@@ -1,6 +1,6 @@
 /* --*-c++-*-- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthSymbology/Color.cpp b/src/osgEarthSymbology/Color.cpp
index f8ff0b0..ea0db27 100644
--- a/src/osgEarthSymbology/Color.cpp
+++ b/src/osgEarthSymbology/Color.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthSymbology/Common b/src/osgEarthSymbology/Common
index 124ef99..20a4156 100644
--- a/src/osgEarthSymbology/Common
+++ b/src/osgEarthSymbology/Common
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthSymbology/CoverageSymbol b/src/osgEarthSymbology/CoverageSymbol
index cc0e09c..f13f138 100644
--- a/src/osgEarthSymbology/CoverageSymbol
+++ b/src/osgEarthSymbology/CoverageSymbol
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthSymbology/CoverageSymbol.cpp b/src/osgEarthSymbology/CoverageSymbol.cpp
index c5176b0..7e96bd4 100644
--- a/src/osgEarthSymbology/CoverageSymbol.cpp
+++ b/src/osgEarthSymbology/CoverageSymbol.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthSymbology/CssUtils b/src/osgEarthSymbology/CssUtils
index a3b6add..20a267c 100644
--- a/src/osgEarthSymbology/CssUtils
+++ b/src/osgEarthSymbology/CssUtils
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthSymbology/CssUtils.cpp b/src/osgEarthSymbology/CssUtils.cpp
index 5fa7c46..9322ce2 100644
--- a/src/osgEarthSymbology/CssUtils.cpp
+++ b/src/osgEarthSymbology/CssUtils.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthSymbology/Expression b/src/osgEarthSymbology/Expression
index 3e4a61f..7d10504 100644
--- a/src/osgEarthSymbology/Expression
+++ b/src/osgEarthSymbology/Expression
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -38,7 +38,7 @@ namespace osgEarth { namespace Symbology
         typedef std::vector<Variable> Variables;
 
     public:
-        NumericExpression() { }
+        NumericExpression();
 
         NumericExpression( const Config& conf );
 
@@ -103,7 +103,7 @@ namespace osgEarth { namespace Symbology
         typedef std::vector<Variable> Variables;
 
     public:
-        StringExpression() { }
+        StringExpression();
 
         StringExpression( const Config& conf );
 
@@ -137,6 +137,10 @@ namespace osgEarth { namespace Symbology
         /** Evaluate the expression. */
         const std::string& eval() const;
 
+        /** Evaluate the expression as a URI. 
+            TODO: it would be better to have a whole new subclass URIExpression */
+        URI evalURI() const;
+
         /** Gets the expression string. */
         const std::string& expr() const { return _src; }
 
@@ -165,6 +169,7 @@ namespace osgEarth { namespace Symbology
         void init();
     };
 
+
 } } // namespace osgEarth::Symbology
 
 #endif // OSGEARTHSYMBOLOGY_EXPRESSION_H
diff --git a/src/osgEarthSymbology/Expression.cpp b/src/osgEarthSymbology/Expression.cpp
index f94dbfd..33e691e 100644
--- a/src/osgEarthSymbology/Expression.cpp
+++ b/src/osgEarthSymbology/Expression.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
@@ -28,6 +28,13 @@ using namespace osgEarth::Symbology;
 
 #define LC "[Expression] "
 
+NumericExpression::NumericExpression() :
+_value(0.0),
+_dirty(true)
+{
+    //nop
+}
+
 NumericExpression::NumericExpression( const std::string& expr ) : 
 _src  ( expr ),
 _value( 0.0 ),
@@ -54,7 +61,9 @@ _dirty( false )
     init();
 }
 
-NumericExpression::NumericExpression( const Config& conf )
+NumericExpression::NumericExpression( const Config& conf ) :
+_value( 0.0 ),
+_dirty( true )
 {
     mergeConfig( conf );
     init();
@@ -357,6 +366,12 @@ NumericExpression::eval() const
 
 //------------------------------------------------------------------------
 
+StringExpression::StringExpression() :
+_dirty(true)
+{
+    //nop
+}
+
 StringExpression::StringExpression( const std::string& expr ) : 
 _src( expr ),
 _dirty( true )
@@ -545,3 +560,9 @@ StringExpression::eval() const
 
     return _value;
 }
+
+URI
+StringExpression::evalURI() const
+{
+    return URI(eval(), _uriContext);
+}
diff --git a/src/osgEarthSymbology/ExtrusionSymbol b/src/osgEarthSymbology/ExtrusionSymbol
index b680ca7..9619368 100644
--- a/src/osgEarthSymbology/ExtrusionSymbol
+++ b/src/osgEarthSymbology/ExtrusionSymbol
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthSymbology/ExtrusionSymbol.cpp b/src/osgEarthSymbology/ExtrusionSymbol.cpp
index 69f10a0..47bc939 100644
--- a/src/osgEarthSymbology/ExtrusionSymbol.cpp
+++ b/src/osgEarthSymbology/ExtrusionSymbol.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthSymbology/Fill b/src/osgEarthSymbology/Fill
index 512d778..190f09d 100644
--- a/src/osgEarthSymbology/Fill
+++ b/src/osgEarthSymbology/Fill
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthSymbology/Fill.cpp b/src/osgEarthSymbology/Fill.cpp
index 392498b..a123133 100644
--- a/src/osgEarthSymbology/Fill.cpp
+++ b/src/osgEarthSymbology/Fill.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthSymbology/GEOS b/src/osgEarthSymbology/GEOS
index b695bb7..9921e65 100644
--- a/src/osgEarthSymbology/GEOS
+++ b/src/osgEarthSymbology/GEOS
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthSymbology/GEOS.cpp b/src/osgEarthSymbology/GEOS.cpp
index cf04e33..8941ae6 100644
--- a/src/osgEarthSymbology/GEOS.cpp
+++ b/src/osgEarthSymbology/GEOS.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -42,6 +42,7 @@ using namespace osgEarth::Symbology;
 using namespace geos;
 using namespace geos::operation;
 
+#define LC "[GEOS] "
 
 namespace
 {
@@ -138,15 +139,18 @@ namespace
                     {
                         const Symbology::Polygon* poly = static_cast<const Symbology::Polygon*>(input);
                         std::vector<geom::Geometry*>* holes = poly->getHoles().size() > 0 ? new std::vector<geom::Geometry*>() : 0L;
-                        for( Symbology::RingCollection::const_iterator r = poly->getHoles().begin(); r != poly->getHoles().end(); ++r )
+                        if (holes)
                         {
-                            geom::Geometry* hole = import( r->get(), f );
-                            if ( hole ) holes->push_back( hole );
-                        }
-                        if ( holes && holes->size() == 0 )
-                        {
-                            delete holes;
-                            holes = 0L;
+                            for( Symbology::RingCollection::const_iterator r = poly->getHoles().begin(); r != poly->getHoles().end(); ++r )
+                            {
+                                geom::Geometry* hole = import( r->get(), f );
+                                if ( hole ) holes->push_back( hole );
+                            }
+                            if (holes->size() == 0)
+                            {
+                                delete holes;
+                                holes = 0L;
+                            }
                         }
                         output = f->createPolygon( shell, holes );
                     }
@@ -160,7 +164,7 @@ namespace
                 //if ( seq )
                 //    delete seq;
 
-                OE_NOTICE << "GEOS::import: Removed degenerate geometry" << std::endl;
+                OE_DEBUG << "GEOS::import: Removed degenerate geometry" << std::endl;
             }
         }
 
@@ -248,7 +252,7 @@ GEOSContext::exportGeometry(const geom::Geometry* input)
 
     if ( dynamic_cast<const geom::Point*>( input ) )
     {
-        OE_NOTICE << "GEOS 'Point' NYI" << std::endl;        
+        OE_NOTICE << LC << "GEOS 'Point' NYI" << std::endl;        
     }
     else if ( dynamic_cast<const geom::MultiPoint*>( input ) )
     {
diff --git a/src/osgEarthSymbology/Geometry b/src/osgEarthSymbology/Geometry
index 5e41302..234f083 100644
--- a/src/osgEarthSymbology/Geometry
+++ b/src/osgEarthSymbology/Geometry
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -120,13 +120,13 @@ namespace osgEarth { namespace Symbology
          * Creates a new Vec3Array (single-precision), copies the part into it, and
          * returns the new object. 
          */
-        osg::Vec3Array* toVec3Array() const;
+        osg::Vec3Array* createVec3Array() const;
 
         /**
          * Creates a new Vec3dArray (double-precision), copies the part into it, and
          * returns the new object.
          */
-        osg::Vec3dArray* toVec3dArray() const;
+        osg::Vec3dArray* createVec3dArray() const;
 
         /**
          * Gets the bounds of this geometry
@@ -161,6 +161,14 @@ namespace osgEarth { namespace Symbology
             osg::ref_ptr<Geometry>& output ) const;
 
         /**
+         * Crops this geometry to the bounds, returning the result in the output parameter.
+         * Returns true if the op succeeded.
+         */
+        bool crop(
+            const Bounds& bounds,
+            osg::ref_ptr<Geometry>& output) const;
+
+        /**
          * Creates the union of this geometry with the other geometry, returning
          * the result in the output parameter. Returns true if the op succeeded.
          */
@@ -177,6 +185,13 @@ namespace osgEarth { namespace Symbology
             osg::ref_ptr<Geometry>& output ) const;
 
         /**
+         * Whether this geometry intersects with another geometry
+         */
+        bool intersects(
+            const class Geometry* other
+            ) const;
+
+        /**
          * Localizes this geometry relative to its centroid, and returns the localization
          * offset.
          */
@@ -199,6 +214,12 @@ namespace osgEarth { namespace Symbology
         virtual void removeDuplicates();
 
         /**
+         * Removes any colinear points, i.e. points that can be safely removed without
+         * affecting the shape/area of the geometry.
+         */
+        virtual void removeColinearPoints();
+
+        /**
          * Get the winding orientation of the geometry (if you consider the last point
          * to connect back to the first in a ring.)
          */
@@ -336,6 +357,8 @@ namespace osgEarth { namespace Symbology
 
         virtual void removeDuplicates();
 
+        virtual void removeColinearPoints();
+
     public:
         RingCollection& getHoles() { return _holes; }
         const RingCollection& getHoles() const { return _holes; }
@@ -373,6 +396,7 @@ namespace osgEarth { namespace Symbology
         virtual bool isValid() const;
         virtual Bounds getBounds() const;
         virtual void rewind( Orientation ori );
+        virtual void removeColinearPoints();
 
     public:
         GeometryCollection& getComponents() { return _parts; }
diff --git a/src/osgEarthSymbology/Geometry.cpp b/src/osgEarthSymbology/Geometry.cpp
index 6d1053c..46b7c05 100644
--- a/src/osgEarthSymbology/Geometry.cpp
+++ b/src/osgEarthSymbology/Geometry.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
@@ -37,6 +37,8 @@ using namespace geos;
 using namespace geos::operation;
 #endif
 
+#define GEOS_OUT OE_DEBUG
+
 #define LC "[Geometry] "
 
 
@@ -105,7 +107,7 @@ Geometry::cloneAs( const Geometry::Type& newType ) const
 }
 
 osg::Vec3Array*
-Geometry::toVec3Array() const 
+Geometry::createVec3Array() const 
 {
     osg::Vec3Array* result = new osg::Vec3Array( this->size() );
     std::copy( begin(), end(), result->begin() );
@@ -113,7 +115,7 @@ Geometry::toVec3Array() const
 }
 
 osg::Vec3dArray*
-Geometry::toVec3dArray() const 
+Geometry::createVec3dArray() const 
 {
     osg::Vec3dArray* result = new osg::Vec3dArray( this->size() );
     std::copy( begin(), end(), result->begin() );
@@ -251,8 +253,14 @@ Geometry::crop( const Polygon* cropPoly, osg::ref_ptr<Geometry>& output ) const
                 cropGeom,
                 overlay::OverlayOp::opINTERSECTION );
         }
+        catch (const geos::util::TopologyException& ex) {
+            GEOS_OUT << LC << "Crop(GEOS): "
+                << (ex.what()? ex.what() : " no error message")
+                << std::endl;
+            outGeom = 0L;
+        }
         catch(const geos::util::GEOSException& ex) {
-            OE_NOTICE << LC << "Crop(GEOS): "
+            OE_INFO << LC << "Crop(GEOS): "
                 << (ex.what()? ex.what() : " no error message")
                 << std::endl;
             outGeom = 0L;
@@ -303,6 +311,18 @@ Geometry::crop( const Polygon* cropPoly, osg::ref_ptr<Geometry>& output ) const
 }
 
 bool
+Geometry::crop( const Bounds& bounds, osg::ref_ptr<Geometry>& output ) const
+{
+    osg::ref_ptr<Polygon> poly = new Polygon;
+    poly->resize( 4 );        
+    (*poly)[0].set(bounds.xMin(), bounds.yMin(), 0);
+    (*poly)[1].set(bounds.xMax(), bounds.yMin(), 0);
+    (*poly)[2].set(bounds.xMax(), bounds.yMax(), 0);
+    (*poly)[3].set(bounds.xMin(), bounds.yMax(), 0);
+    return crop(poly, output);
+}
+
+bool
 Geometry::geounion( const Geometry* other, osg::ref_ptr<Geometry>& output ) const
 {
 #ifdef OSGEARTH_HAVE_GEOS
@@ -324,8 +344,14 @@ Geometry::geounion( const Geometry* other, osg::ref_ptr<Geometry>& output ) cons
                 otherGeom,
                 overlay::OverlayOp::opUNION );
         }
+        catch (const geos::util::TopologyException& ex) {
+            GEOS_OUT << LC << "Crop(GEOS): "
+                << (ex.what()? ex.what() : " no error message")
+                << std::endl;
+            outGeom = 0L;
+        }
         catch(const geos::util::GEOSException& ex) {
-            OE_NOTICE << LC << "Union(GEOS): "
+            OE_INFO << LC << "Union(GEOS): "
                 << (ex.what()? ex.what() : " no error message")
                 << std::endl;
             outGeom = 0L;
@@ -395,8 +421,14 @@ Geometry::difference( const Polygon* diffPolygon, osg::ref_ptr<Geometry>& output
                 diffGeom,
                 overlay::OverlayOp::opDIFFERENCE );
         }
+        catch (const geos::util::TopologyException& ex) {
+            GEOS_OUT << LC << "Crop(GEOS): "
+                << (ex.what()? ex.what() : " no error message")
+                << std::endl;
+            outGeom = 0L;
+        }
         catch(const geos::util::GEOSException& ex) {
-            OE_NOTICE << LC << "Diff(GEOS): "
+            OE_INFO << LC << "Diff(GEOS): "
                 << (ex.what()? ex.what() : " no error message")
                 << std::endl;
             outGeom = 0L;
@@ -428,6 +460,35 @@ Geometry::difference( const Polygon* diffPolygon, osg::ref_ptr<Geometry>& output
 #endif // OSGEARTH_HAVE_GEOS
 }
 
+bool
+Geometry::intersects(
+            const class Geometry* other
+            ) const
+{
+#ifdef OSGEARTH_HAVE_GEOS
+
+    GEOSContext gc;
+
+    //Create the GEOS Geometries
+    geom::Geometry* inGeom   = gc.importGeometry( this );
+    geom::Geometry* otherGeom = gc.importGeometry( other );
+
+    bool intersects = inGeom->intersects( otherGeom );
+
+    //Destroy the geometry
+    gc.disposeGeometry( otherGeom );
+    gc.disposeGeometry( inGeom );
+
+    return intersects;
+
+#else // OSGEARTH_HAVE_GEOS
+
+    OE_WARN << LC << "Intersects failed - GEOS not available" << std::endl;
+    return false;
+
+#endif // OSGEARTH_HAVE_GEOS
+}
+
 osg::Vec3d
 Geometry::localize()
 {
@@ -497,6 +558,30 @@ void Geometry::removeDuplicates()
     }
 }
 
+void
+Geometry::removeColinearPoints()
+{
+    if ( size() >= 3 )
+    {
+        std::vector<unsigned> ind;
+
+        for(unsigned i=0; i<size()-2; ++i)
+        {
+            osg::Vec3d v0( at(i+1) - at(i) );
+            v0.normalize();
+            osg::Vec3d v1( at(i+2) - at(i) );
+            v1.normalize();
+            if ( osg::equivalent(v0*v1, 1.0) )
+                ind.push_back(i+1);
+        }
+
+        for(std::vector<unsigned>::reverse_iterator r = ind.rbegin(); r != ind.rend(); ++r)
+        {
+            erase( begin() + (*r) );
+        }
+    }
+}
+
 Geometry::Orientation 
 Geometry::getOrientation() const
 {
@@ -785,6 +870,14 @@ Polygon::removeDuplicates()
         (*i)->removeDuplicates();
 }
 
+void
+Polygon::removeColinearPoints()
+{
+    Ring::removeColinearPoints();
+    for( RingCollection::const_iterator i = _holes.begin(); i != _holes.end(); ++i )
+        (*i)->removeColinearPoints();
+}
+
 //----------------------------------------------------------------------------
 
 MultiGeometry::MultiGeometry( const MultiGeometry& rhs ) :
@@ -886,6 +979,15 @@ MultiGeometry::rewind( Orientation orientation )
     }
 }
 
+void
+MultiGeometry::removeColinearPoints()
+{
+    for( GeometryCollection::const_iterator i = _parts.begin(); i != _parts.end(); ++i )
+    {
+        i->get()->removeColinearPoints();
+    }
+}
+
 //----------------------------------------------------------------------------
 
 GeometryIterator::GeometryIterator( Geometry* geom, bool holes ) :
diff --git a/src/osgEarthSymbology/GeometryExtrudeSymbolizer.cpp b/src/osgEarthSymbology/GeometryExtrudeSymbolizer.cpp
deleted file mode 100644
index a5c9a6a..0000000
--- a/src/osgEarthSymbology/GeometryExtrudeSymbolizer.cpp
+++ /dev/null
@@ -1,298 +0,0 @@
-/* -*-c++-*- */
-/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2008-2010 Pelican Mapping
- * http://osgearth.org
- *
- * osgEarth is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>
- */
-
-#include <osgEarthSymbology/GeometryExtrudeSymbolizer>
-#include <osgEarthSymbology/ExtrudedSymbol>
-#include <osgUtil/Tessellator>
-#include <osg/Geometry>
-#include <osg/Point>
-#include <osg/LineWidth>
-#include <osg/Material>
-#include <osg/Geode>
-
-using namespace osgEarth::Symbology;
-
-GeometryExtrudeSymbolizer::GeometryExtrudeSymbolizer()
-{
-}
-
-
-void GeometryExtrudeSymbolizer::tessellate( osg::Geometry* geom )
-{
-    osgUtil::Tessellator tess;
-    tess.setTessellationType( osgUtil::Tessellator::TESS_TYPE_GEOMETRY );
-    tess.setWindingType( osgUtil::Tessellator::TESS_WINDING_ODD );
-//    tess.setWindingType( osgUtil::Tessellator::TESS_WINDING_POSITIVE );
-    tess.retessellatePolygons( *geom );
-}
-
-bool 
-GeometryExtrudeSymbolizer::compile(State<GeometryContent>* state,
-                                   osg::Group* attachPoint)
-{
-    if ( !state || !attachPoint || !state->getContent() || !state->getStyle() )
-        return false;
-
-    osg::ref_ptr<osg::Group> newSymbolized = new osg::Group;
-
-    const GeometryList& geometryList = state->getContent()->getGeometryList();
-    for (GeometryList::const_iterator it = geometryList.begin(); it != geometryList.end(); ++it)
-    {
-        Geometry* geometry = *it;
-        if (!geometry)
-            continue;
-
-        GeometryIterator geomIterator( geometry );
-        geomIterator.traverseMultiGeometry() = true;
-        geomIterator.traversePolygonHoles() = true;
-        while( geomIterator.hasMore() )
-        {
-            Geometry* part = geomIterator.next();
-            if (!part)
-                continue;
-
-            osg::Vec4 color = osg::Vec4(1.0, 0.0, 1.0, 1.);
-            float height = 1.0;
-            float offset = 1.0;
-
-            switch( part->getType())
-            {
-            case Geometry::TYPE_LINESTRING:
-            case Geometry::TYPE_RING:
-            {
-                const ExtrudedLineSymbol* line = state->getStyle()->getSymbol<ExtrudedLineSymbol>();
-                if (line) 
-                {
-                    color = line->stroke()->color();
-                    height = line->extrude()->height();
-                    offset = line->extrude()->offset();
-                }
-            }
-            break;
-
-            case Geometry::TYPE_POLYGON:
-            {
-                const ExtrudedPolygonSymbol* polygon = state->getStyle()->getSymbol<ExtrudedPolygonSymbol>();
-                if (polygon)
-                {
-                    color  = polygon->fill()->color();
-                    height = polygon->extrude()->height();
-                    offset = polygon->extrude()->offset();
-                }
-            }
-            break;
-            default:
-                continue;
-                break;
-            }
-
-            osg::Geode* geode = extrude(part, offset, height, state->getContext() );
-            if (geode && geode->getNumDrawables()) 
-            {
-                osg::Material* material = new osg::Material;
-                material->setDiffuse(osg::Material::FRONT_AND_BACK, color);
-                geode->getOrCreateStateSet()->setAttributeAndModes(material);
-                newSymbolized->addChild(geode);
-            }
-        }
-    }
-
-    if (newSymbolized->getNumChildren())
-    {
-        attachPoint->removeChildren(0, attachPoint->getNumChildren());
-        attachPoint->addChild(newSymbolized.get());
-        return true;
-    }
-
-    return false;
-}
-
-osg::Geode* GeometryExtrudeSymbolizer::extrude(Geometry* geom, double offset, double height, SymbolizerContext* context )
-{
-    if ( !geom ) return 0L;
-
-    int numRings = 0;
-
-    // start by offsetting the input data.
-    {
-        GeometryIterator i( geom );
-        i.traverseMultiGeometry() = true;
-        i.traversePolygonHoles() = true;
-        while( i.hasMore() )
-        {
-            Geometry* part = i.next();
-            if (offset != 0.0)
-            {
-                for( osg::Vec3dArray::iterator j = part->begin(); j != part->end(); j++ )
-                {
-                    {
-                        (*j).z() += offset;
-                    }
-                }
-            }
-
-            // in the meantime, count the # of closed geoms. We will need to know this in 
-            // order to pre-allocate the proper # of verts.
-            if ( part->getType() == Geometry::TYPE_POLYGON || part->getType() == Geometry::TYPE_RING )
-            {
-                numRings++;
-            }
-        }
-    }
-
-    // now, go thru and remove any coplanar segments from the geometry. The tesselator will
-    // not work include a vert connecting two colinear segments in the tesselation, and this
-    // will break the stenciling logic.
-#define PARALLEL_EPSILON 0.01
-    GeometryIterator i( geom );
-    i.traverseMultiGeometry() = true;
-    i.traversePolygonHoles() = true;
-    while( i.hasMore() )
-    {
-        Geometry* part = i.next();
-        if ( part->size() >= 3 )
-        {
-            osg::Vec3d prevVec = part->front() - part->back();
-            prevVec.normalize();
-
-            for( osg::Vec3dArray::iterator j = part->begin(); part->size() >= 3 && j != part->end(); )
-            {
-                osg::Vec3d& p0 = *j;
-                osg::Vec3d& p1 = j+1 != part->end() ? *(j+1) : part->front();
-                osg::Vec3d vec = p1-p0; vec.normalize();
-
-                // if the vectors are essentially parallel, remove the extraneous vertex.
-                if ( (prevVec ^ vec).length() < PARALLEL_EPSILON )
-                {
-                    j = part->erase( j );
-                    //OE_NOTICE << "removed colinear segment" << std::endl;
-                }
-                else
-                {
-                    ++j;
-                    prevVec = vec;
-                }
-            }
-        }
-    }
-
-
-    bool made_geom = true;
-
-    // total up all the points so we can pre-allocate the vertex arrays.
-    int num_cap_verts = geom->getTotalPointCount();
-    int num_wall_verts = 2 * (num_cap_verts + numRings); // add in numRings b/c we need to close each wall
-
-    osg::Geometry* walls = new osg::Geometry();
-    osg::Vec3Array* verts = new osg::Vec3Array( num_wall_verts );
-    walls->setVertexArray( verts );
-
-    osg::Geometry* top_cap = new osg::Geometry();
-    osg::Vec3Array* top_verts = new osg::Vec3Array( num_cap_verts );
-    top_cap->setVertexArray( top_verts );
-
-    osg::Geometry* bottom_cap = new osg::Geometry();
-    osg::Vec3Array* bottom_verts = new osg::Vec3Array( num_cap_verts );
-    bottom_cap->setVertexArray( bottom_verts );
-
-    int wall_vert_ptr = 0;
-    int top_vert_ptr = 0;
-    int bottom_vert_ptr = 0;
-
-    //double target_len = height;
-
-    // now generate the extruded geometry.
-    GeometryIterator k( geom );
-    while( k.hasMore() )
-    {
-        Geometry* part = k.next();
-
-        unsigned int wall_part_ptr = wall_vert_ptr;
-        unsigned int top_part_ptr = top_vert_ptr;
-        unsigned int bottom_part_ptr = bottom_vert_ptr;
-        double part_len = 0.0;
-
-        GLenum prim_type = part->getType() == Geometry::TYPE_POINTSET ? GL_LINES : GL_TRIANGLE_STRIP;
-
-        for( osg::Vec3dArray::const_iterator m = part->begin(); m != part->end(); ++m )
-        {
-            osg::Vec3d extrude_vec;
-            {
-                extrude_vec.set( m->x(), m->y(), height );
-            }
-
-            (*top_verts)[top_vert_ptr++] = extrude_vec;
-            (*bottom_verts)[bottom_vert_ptr++] = *m;
-             
-            part_len += wall_vert_ptr > wall_part_ptr?
-                (extrude_vec - (*verts)[wall_vert_ptr-2]).length() :
-                0.0;
-
-            int p;
-
-            p = wall_vert_ptr++;
-            (*verts)[p] = extrude_vec;
-
-            p = wall_vert_ptr++;
-            (*verts)[p] = *m;
-        }
-
-        // close the wall if it's a ring/poly:
-        if ( part->getType() == Geometry::TYPE_RING || part->getType() == Geometry::TYPE_POLYGON )
-        {
-            part_len += wall_vert_ptr > wall_part_ptr?
-                ((*verts)[wall_part_ptr] - (*verts)[wall_vert_ptr-2]).length() :
-                0.0;
-
-            int p;
-
-            p = wall_vert_ptr++;
-            (*verts)[p] = (*verts)[wall_part_ptr];
-
-            p = wall_vert_ptr++;
-            (*verts)[p] = (*verts)[wall_part_ptr+1];
-        }
-
-        walls->addPrimitiveSet( new osg::DrawArrays(
-                                    prim_type,
-                                    wall_part_ptr, wall_vert_ptr - wall_part_ptr ) );
-
-        top_cap->addPrimitiveSet( new osg::DrawArrays(
-                                      osg::PrimitiveSet::LINE_LOOP,
-                                      top_part_ptr, top_vert_ptr - top_part_ptr ) );
-
-        // reverse the bottom verts so the front face is down:
-        std::reverse( bottom_verts->begin()+bottom_part_ptr, bottom_verts->begin()+bottom_vert_ptr );
-
-        bottom_cap->addPrimitiveSet( new osg::DrawArrays(
-                                         osg::PrimitiveSet::LINE_LOOP,
-                                         bottom_part_ptr, bottom_vert_ptr - bottom_part_ptr ) );
-    }
-
-    // build solid surfaces for the caps:
-    tessellate( top_cap );
-    tessellate( bottom_cap );
-
-    osg::Geode* geode = new osg::Geode();
-    geode->addDrawable( walls );
-    geode->addDrawable( top_cap );
-    geode->addDrawable( bottom_cap );
-
-    return geode;
-}
diff --git a/src/osgEarthSymbology/GeometryFactory b/src/osgEarthSymbology/GeometryFactory
index e196cee..5e2ce86 100644
--- a/src/osgEarthSymbology/GeometryFactory
+++ b/src/osgEarthSymbology/GeometryFactory
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthSymbology/GeometryFactory.cpp b/src/osgEarthSymbology/GeometryFactory.cpp
index 32e1d3c..6254dc2 100644
--- a/src/osgEarthSymbology/GeometryFactory.cpp
+++ b/src/osgEarthSymbology/GeometryFactory.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthSymbology/GeometryRasterizer b/src/osgEarthSymbology/GeometryRasterizer
index 97b80be..4fe1f9a 100644
--- a/src/osgEarthSymbology/GeometryRasterizer
+++ b/src/osgEarthSymbology/GeometryRasterizer
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthSymbology/GeometryRasterizer.cpp b/src/osgEarthSymbology/GeometryRasterizer.cpp
index 2abc1ce..eaf2d96 100644
--- a/src/osgEarthSymbology/GeometryRasterizer.cpp
+++ b/src/osgEarthSymbology/GeometryRasterizer.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthSymbology/IconResource b/src/osgEarthSymbology/IconResource
index 3ed5112..162382e 100644
--- a/src/osgEarthSymbology/IconResource
+++ b/src/osgEarthSymbology/IconResource
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthSymbology/IconResource.cpp b/src/osgEarthSymbology/IconResource.cpp
index fe74518..88aefc2 100644
--- a/src/osgEarthSymbology/IconResource.cpp
+++ b/src/osgEarthSymbology/IconResource.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -113,11 +113,6 @@ namespace
         geode->addDrawable( geometry );
 
         return geode;
-        //osg::AutoTransform* at = new osg::AutoTransform;
-        //at->setAutoScaleToScreen( true );
-        //at->setAutoRotateMode( osg::AutoTransform::ROTATE_TO_SCREEN );
-        //at->addChild( geode );
-        //return at;
     }
 }
 
diff --git a/src/osgEarthSymbology/IconSymbol b/src/osgEarthSymbology/IconSymbol
index f1f0549..a15f6ef 100644
--- a/src/osgEarthSymbology/IconSymbol
+++ b/src/osgEarthSymbology/IconSymbol
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthSymbology/IconSymbol.cpp b/src/osgEarthSymbology/IconSymbol.cpp
index d6ad467..f74bf2e 100644
--- a/src/osgEarthSymbology/IconSymbol.cpp
+++ b/src/osgEarthSymbology/IconSymbol.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -44,7 +44,7 @@ IconSymbol::IconSymbol( const Config& conf ) :
 InstanceSymbol        ( conf ),
 _alignment            ( ALIGN_CENTER_BOTTOM ),
 _heading              ( NumericExpression(0.0) ),
-_declutter            ( false ),
+_declutter            ( true ),
 _occlusionCull        ( false ),
 _occlusionCullAltitude( 200000 )
 {
@@ -112,7 +112,7 @@ IconSymbol::getImage( unsigned maxSize ) const
         {
             osg::ref_ptr<osgDB::Options> dbOptions = Registry::instance()->cloneOrCreateOptions();
             dbOptions->setObjectCacheHint( osgDB::Options::CACHE_IMAGES );
-            _image = URI(_url->eval(), _url->uriContext()).getImage( dbOptions.get() );
+            _image = _url->evalURI().getImage( dbOptions.get() );
             if ( _image.valid() && (maxSize < (unsigned int)_image->s() || maxSize < (unsigned int)_image->t()) )
             {
                 unsigned new_s, new_t;
diff --git a/src/osgEarthSymbology/InstanceResource b/src/osgEarthSymbology/InstanceResource
index ec1e664..2bb5085 100644
--- a/src/osgEarthSymbology/InstanceResource
+++ b/src/osgEarthSymbology/InstanceResource
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -45,7 +45,7 @@ namespace osgEarth { namespace Symbology
         /**
          * Creates a new Node representing the instance.
          */
-        osg::Node* createNode( const osgDB::Options* dbOptions ) const;
+        osg::Node* createNode(const osgDB::Options* readOptions) const;
 
         /** Whether this instance type is 2D (orthographic screen space) */
         virtual bool is2D() const =0;
diff --git a/src/osgEarthSymbology/InstanceResource.cpp b/src/osgEarthSymbology/InstanceResource.cpp
index 8c9297d..10396fc 100644
--- a/src/osgEarthSymbology/InstanceResource.cpp
+++ b/src/osgEarthSymbology/InstanceResource.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthSymbology/InstanceSymbol b/src/osgEarthSymbology/InstanceSymbol
index a72c41e..47f0b7e 100644
--- a/src/osgEarthSymbology/InstanceSymbol
+++ b/src/osgEarthSymbology/InstanceSymbol
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -24,6 +24,7 @@
 
 #include <osgEarth/Common>
 #include <osgEarthSymbology/Symbol>
+#include <osgEarthSymbology/Tags>
 #include <osgEarthSymbology/Expression>
 #include <osg/Vec3f>
 
@@ -37,7 +38,7 @@ namespace osgEarth { namespace Symbology
      * Base class for symbols that represent an instance of an external resource
      * like an icon or a model and can be placed at a location.
      */
-    class OSGEARTHSYMBOLOGY_EXPORT InstanceSymbol : public Symbol
+    class OSGEARTHSYMBOLOGY_EXPORT InstanceSymbol : public Taggable<Symbol>
     {
     public:
         /**
diff --git a/src/osgEarthSymbology/InstanceSymbol.cpp b/src/osgEarthSymbology/InstanceSymbol.cpp
index 782850a..803206b 100644
--- a/src/osgEarthSymbology/InstanceSymbol.cpp
+++ b/src/osgEarthSymbology/InstanceSymbol.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -24,7 +24,6 @@ using namespace osgEarth;
 using namespace osgEarth::Symbology;
 
 InstanceSymbol::InstanceSymbol( const Config& conf ) :
-Symbol     ( conf ),
 _placement ( PLACEMENT_VERTEX ),
 _density   ( 25.0f ),
 _randomSeed( 0 ),
@@ -34,7 +33,7 @@ _scale     ( NumericExpression(1.0) )
 }
 
 InstanceSymbol::InstanceSymbol(const InstanceSymbol& rhs,const osg::CopyOp& copyop):
-Symbol(rhs, copyop),
+Taggable<Symbol>(rhs, copyop),
 _url(rhs._url),
 _library(rhs._library),
 _scale(rhs._scale),
@@ -49,7 +48,7 @@ _script(rhs._script)
 Config 
 InstanceSymbol::getConfig() const
 {
-    Config conf = Symbol::getConfig();
+    Config conf = Taggable<Symbol>::getConfig();
     conf.key() = "instance";
     conf.addObjIfSet( "url", _url );
     conf.addObjIfSet( "library", _library );
@@ -61,6 +60,11 @@ InstanceSymbol::getConfig() const
     conf.addIfSet   ( "placement", "centroid",  _placement, PLACEMENT_CENTROID );
     conf.addIfSet   ( "density", _density );
     conf.addIfSet   ( "random_seed", _randomSeed );
+
+    std::string tagstring = this->tagString();
+    if ( !tagstring.empty() )
+        conf.set("tags", tagstring);
+
     return conf;
 }
 
@@ -77,6 +81,8 @@ InstanceSymbol::mergeConfig( const Config& conf )
     conf.getIfSet   ( "placement", "centroid", _placement, PLACEMENT_CENTROID );
     conf.getIfSet   ( "density", _density );
     conf.getIfSet   ( "random_seed", _randomSeed );
+    
+    addTags( conf.value("tags") );
 }
 
 
diff --git a/src/osgEarthSymbology/LineSymbol b/src/osgEarthSymbology/LineSymbol
index ced4040..371e351 100644
--- a/src/osgEarthSymbology/LineSymbol
+++ b/src/osgEarthSymbology/LineSymbol
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthSymbology/LineSymbol.cpp b/src/osgEarthSymbology/LineSymbol.cpp
index 0cb5636..2e138af 100644
--- a/src/osgEarthSymbology/LineSymbol.cpp
+++ b/src/osgEarthSymbology/LineSymbol.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthSymbology/MarkerResource b/src/osgEarthSymbology/MarkerResource
index 8d7a7e7..e093c4d 100644
--- a/src/osgEarthSymbology/MarkerResource
+++ b/src/osgEarthSymbology/MarkerResource
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthSymbology/MarkerResource.cpp b/src/osgEarthSymbology/MarkerResource.cpp
index 04b3975..4dc73b6 100644
--- a/src/osgEarthSymbology/MarkerResource.cpp
+++ b/src/osgEarthSymbology/MarkerResource.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthSymbology/MarkerSymbol b/src/osgEarthSymbology/MarkerSymbol
index f2e4f63..f22d2a8 100644
--- a/src/osgEarthSymbology/MarkerSymbol
+++ b/src/osgEarthSymbology/MarkerSymbol
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthSymbology/MarkerSymbol.cpp b/src/osgEarthSymbology/MarkerSymbol.cpp
index d3f9846..3ecbad4 100644
--- a/src/osgEarthSymbology/MarkerSymbol.cpp
+++ b/src/osgEarthSymbology/MarkerSymbol.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -129,7 +129,7 @@ MarkerSymbol::getImage( unsigned maxSize ) const
         {
             osg::ref_ptr<osgDB::Options> dbOptions = Registry::instance()->cloneOrCreateOptions();
             dbOptions->setObjectCacheHint( osgDB::Options::CACHE_IMAGES );
-            _image = URI(_url->eval(), _url->uriContext()).getImage( dbOptions.get() );
+            _image = _url->evalURI().getImage( dbOptions.get() );
             if ( _image.valid() && (maxSize < (unsigned int)_image->s() || maxSize < (unsigned int)_image->t()) )
             {
                 unsigned new_s, new_t;
diff --git a/src/osgEarthSymbology/MeshConsolidator b/src/osgEarthSymbology/MeshConsolidator
index c541c03..82ddf75 100644
--- a/src/osgEarthSymbology/MeshConsolidator
+++ b/src/osgEarthSymbology/MeshConsolidator
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthSymbology/MeshConsolidator.cpp b/src/osgEarthSymbology/MeshConsolidator.cpp
index c506e63..6422873 100644
--- a/src/osgEarthSymbology/MeshConsolidator.cpp
+++ b/src/osgEarthSymbology/MeshConsolidator.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
@@ -48,7 +48,7 @@ namespace
         unsigned _maxSize;
         T* _current;
 
-        Collector() : _current(0L) { }
+        Collector() : _current(0L), _newPrimSets(0L), _maxSize(0u) { }
 
         void operator()( unsigned i0, unsigned i1, unsigned i2 )
         {
diff --git a/src/osgEarthSymbology/MeshFlattener b/src/osgEarthSymbology/MeshFlattener
index 5608952..94cae04 100644
--- a/src/osgEarthSymbology/MeshFlattener
+++ b/src/osgEarthSymbology/MeshFlattener
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -64,6 +64,9 @@ namespace osgEarth { namespace Symbology
         typedef std::map< StateSetStack, GeometryVector > StateSetStackToGeometryMap;
 
         StateSetStackToGeometryMap _geometries;
+
+        bool _mergeGeometry;
+        unsigned _maxVertsPerCluster;
     };
 
 
@@ -80,6 +83,9 @@ namespace osgEarth { namespace Symbology
     {
     public:
         static void run( osg::Group* group );
+
+        /** Run the flattener and indicate the target vertex cound for the MergeGeometry stage. */
+        static void run(osg::Group* group, unsigned maxVertsPerCluster);
     };
 
 
diff --git a/src/osgEarthSymbology/MeshFlattener.cpp b/src/osgEarthSymbology/MeshFlattener.cpp
index 5ded310..e86325c 100644
--- a/src/osgEarthSymbology/MeshFlattener.cpp
+++ b/src/osgEarthSymbology/MeshFlattener.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
@@ -34,6 +34,29 @@ using namespace osgEarth::Symbology;
 
 using namespace osgEarth;
 
+namespace
+{
+    struct RemoveEmptyGeometries : public osg::NodeVisitor
+    {
+        RemoveEmptyGeometries() {
+            setTraversalMode(TRAVERSE_ALL_CHILDREN);
+            setNodeMaskOverride(~0);
+        }
+        void apply(osg::Geode& geode) {
+            std::vector<osg::Drawable*> empties;
+            for (unsigned i = 0; i < geode.getNumDrawables(); ++i) {
+                osg::Geometry* g = geode.getDrawable(i)->asGeometry();
+                if (g) {
+                    if (g->getVertexArray() == 0L || g->getNumPrimitiveSets() == 0)
+                        empties.push_back(g);
+                }
+            }
+            for (unsigned i = 0; i < empties.size(); ++i) {
+                geode.removeDrawable(empties[i]);
+            }
+        }
+    };
+}
 
 /********************************/
 PrepareForOptimizationVisitor::PrepareForOptimizationVisitor():
@@ -55,10 +78,12 @@ void PrepareForOptimizationVisitor::apply(osg::Node& node)
 }
 
 /********************************/
-    FlattenSceneGraphVisitor::FlattenSceneGraphVisitor():
+FlattenSceneGraphVisitor::FlattenSceneGraphVisitor():
 osg::NodeVisitor( osg::NodeVisitor::TRAVERSE_ALL_CHILDREN )
 {
     setNodeMaskOverride(~0);
+    _mergeGeometry = true;
+    _maxVertsPerCluster = 250000u;
 }
 
     void FlattenSceneGraphVisitor::apply(osg::Node& node)
@@ -85,7 +110,7 @@ osg::NodeVisitor( osg::NodeVisitor::TRAVERSE_ALL_CHILDREN )
         }
 
         osg::ref_ptr< osg::StateSet > ss = geode.getStateSet();
-        if (ss)
+        if (ss.valid())
         {
             pushStateSet(ss.get());
         }
@@ -96,7 +121,7 @@ osg::NodeVisitor( osg::NodeVisitor::TRAVERSE_ALL_CHILDREN )
             if (geometry)
             {
                 osg::ref_ptr< osg::StateSet > geomSS = geometry->getStateSet();
-                if (geomSS.get())
+                if (geomSS.valid())
                 {
                     pushStateSet( geomSS.get() );
                 }
@@ -104,7 +129,7 @@ osg::NodeVisitor( osg::NodeVisitor::TRAVERSE_ALL_CHILDREN )
                 GeometryVector& geometries = _geometries[_ssStack];
                 geometries.push_back(geometry);
 
-                if (geomSS.get())
+                if (geomSS.valid())
                 {
                     popStateSet();
                 }
@@ -113,7 +138,7 @@ osg::NodeVisitor( osg::NodeVisitor::TRAVERSE_ALL_CHILDREN )
             }
         }
         
-        if (ss)
+        if (ss.valid())
         {
             popStateSet();
         }
@@ -165,20 +190,27 @@ osg::NodeVisitor( osg::NodeVisitor::TRAVERSE_ALL_CHILDREN )
             MeshConsolidator::run(*geode);
         }
 
-        // Run MERGE_GEOMETRY so that it will merge all the primitive sets
-        osgUtil::Optimizer opt;
-        opt.optimize( result, 
-            osgUtil::Optimizer::MERGE_GEOMETRY
-            );
+        if (_mergeGeometry)
+        {
+            // Run MERGE_GEOMETRY so that it will merge all the primitive sets
+            osgUtil::Optimizer::MergeGeometryVisitor mg;
+            mg.setTargetMaximumNumberOfVertices(std::max(_maxVertsPerCluster, 1000u));
+            result->accept( mg );
+
+            // Remove any empty geoetries. For some reason the MergeGeometryVisitor sometimes 
+            // leaves them around.
+            RemoveEmptyGeometries reg;
+            result->accept( reg );
+        }
        
-        //osgDB::writeNodeFile(*result, "clustered.osg");
+        //osgDB::writeNodeFile(*result, "clustered.osgt");
 
         return result;
     }
 
 
 /********************************/
-void MeshFlattener::run( osg::Group* group )
+void MeshFlattener::run(osg::Group* group, unsigned maxVertsPerCluster)
 {
     // Do all that we can so the optimizer will actually do it's job.
     PrepareForOptimizationVisitor v;
@@ -194,6 +226,7 @@ void MeshFlattener::run( osg::Group* group )
 
     // Now, collect all the geodes and merge them
     FlattenSceneGraphVisitor flatten;
+    flatten._maxVertsPerCluster = maxVertsPerCluster;
     group->accept(flatten);
 
     // Remove all the old children.
@@ -202,3 +235,8 @@ void MeshFlattener::run( osg::Group* group )
     // Add the new flat graph.
     group->addChild(flatten.build());
 }
+
+void MeshFlattener::run(osg::Group* group)
+{
+    run(group, 250000u);
+}
\ No newline at end of file
diff --git a/src/osgEarthSymbology/MeshSubdivider b/src/osgEarthSymbology/MeshSubdivider
index d562d98..010524e 100644
--- a/src/osgEarthSymbology/MeshSubdivider
+++ b/src/osgEarthSymbology/MeshSubdivider
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthSymbology/MeshSubdivider.cpp b/src/osgEarthSymbology/MeshSubdivider.cpp
index 5655468..ea22b45 100644
--- a/src/osgEarthSymbology/MeshSubdivider.cpp
+++ b/src/osgEarthSymbology/MeshSubdivider.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -260,7 +260,7 @@ namespace
                 _i0 < rhs._i0 ? true :
                 _i0 > rhs._i0 ? false :
                 _i1 < rhs._i1 ? true :
-                _i1 > rhs._i1 ? false :
+                //_i1 > rhs._i1 ? false : // redundant :)
                 false;
         }
         bool operator == (const Edge& rhs) const { return _i0==rhs._i0 && _i1==rhs._i1; }
@@ -296,11 +296,16 @@ namespace
 
                 numElementsInCurrentEBO = 0;
             }
-            ebo->push_back( static_cast<VTYPE>( i->_i0 ) );
-            ebo->push_back( static_cast<VTYPE>( i->_i1 ) );
-            ebo->push_back( static_cast<VTYPE>( i->_i2 ) );
 
-            numElementsInCurrentEBO += 3;
+            if (ebo)
+            {
+                ebo->push_back( static_cast<VTYPE>( i->_i0 ) );
+                ebo->push_back( static_cast<VTYPE>( i->_i1 ) );
+                ebo->push_back( static_cast<VTYPE>( i->_i2 ) );
+
+                numElementsInCurrentEBO += 3;
+            }
+
             ++totalTrisWritten;
         }
 
@@ -476,10 +481,15 @@ namespace
 
                 numElementsInCurrentEBO = 0;
             }
-            ebo->push_back( static_cast<VTYPE>( i->_i0 ) );
-            ebo->push_back( static_cast<VTYPE>( i->_i1 ) );
 
-            numElementsInCurrentEBO += 3;
+            if (ebo)
+            {
+                ebo->push_back( static_cast<VTYPE>( i->_i0 ) );
+                ebo->push_back( static_cast<VTYPE>( i->_i1 ) );
+
+                numElementsInCurrentEBO += 3;
+            }
+
             ++totalLinesWritten;
         }
 
@@ -851,6 +861,9 @@ namespace
         const osg::Matrixd&  L2W, // local=>world xform
         unsigned int         maxElementsPerEBO )
     {
+        if ( geom.getNumPrimitiveSets() == 0 )
+            return;
+
         GLenum mode = geom.getPrimitiveSet(0)->getMode();
 
         if ( mode == GL_POINTS )
diff --git a/src/osgEarthSymbology/ModelResource b/src/osgEarthSymbology/ModelResource
index 1c9701a..d918b76 100644
--- a/src/osgEarthSymbology/ModelResource
+++ b/src/osgEarthSymbology/ModelResource
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -43,6 +43,18 @@ namespace osgEarth { namespace Symbology
 
         virtual bool is2D() const { return false; }
 
+        const osg::BoundingBox& getBoundingBox(const osgDB::Options*);
+
+        /** Whether this model instance honors "scale-to-fit" in the X and Y dimensions,
+         * if applicable. Scale-to-fit is a hint to an implementation that may want to
+         * automatically scale a model to fit a region, as to whether that should be allowed
+         * (for example when the artist has designed the model for specific dimensions.) */
+        optional<bool>& canScaleToFitXY() { return _canScaleToFitXY; }
+        const optional<bool>& canScaleToFitXY() const { return _canScaleToFitXY; }
+
+        optional<bool>& canScaleToFitZ() { return _canScaleToFitZ; }
+        const optional<bool>& canScaleToFitZ() const { return _canScaleToFitZ; }
+
     public: // serialization methods
 
         virtual Config getConfig() const;
@@ -50,9 +62,16 @@ namespace osgEarth { namespace Symbology
 
     protected: // InstanceResource
 
-        virtual osg::Node* createNodeFromURI( const URI& uri, const osgDB::Options* dbOptions ) const;
+        virtual osg::Node* createNodeFromURI(const URI& uri, const osgDB::Options* dbOptions) const;
+
+        osg::BoundingBox _bbox;
+        Threading::Mutex _mutex;
+        optional<bool>   _canScaleToFitXY;
+        optional<bool>   _canScaleToFitZ;
     };
 
+    typedef std::vector<osg::ref_ptr<ModelResource> > ModelResourceVector;
+
 } } // namespace osgEarth::Symbology
 
 #endif // OSGEARTHSYMBOLOGY_MODEL_RESOURCE_H
diff --git a/src/osgEarthSymbology/ModelResource.cpp b/src/osgEarthSymbology/ModelResource.cpp
index acdc104..632f779 100644
--- a/src/osgEarthSymbology/ModelResource.cpp
+++ b/src/osgEarthSymbology/ModelResource.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -21,7 +21,9 @@
 #include <osgEarth/Utils>
 #include <osgEarth/Registry>
 #include <osgEarth/Capabilities>
+#include <osgEarth/ImageUtils>
 #include <osgUtil/Optimizer>
+#include <osg/ComputeBoundsVisitor>
 
 #define LC "[ModelResource] "
 
@@ -31,7 +33,9 @@ using namespace osgEarth::Symbology;
 //---------------------------------------------------------------------------
 
 ModelResource::ModelResource( const Config& conf ) :
-InstanceResource( conf )
+InstanceResource( conf ),
+_canScaleToFitXY(true),
+_canScaleToFitZ(true)
 {
     mergeConfig( conf );
 }
@@ -39,7 +43,8 @@ InstanceResource( conf )
 void
 ModelResource::mergeConfig( const Config& conf )
 {
-    //nop
+    conf.getIfSet("can_scale_to_fit_xy", _canScaleToFitXY);
+    conf.getIfSet("can_scale_to_fit_z",  _canScaleToFitZ);
 }
 
 Config
@@ -47,17 +52,59 @@ ModelResource::getConfig() const
 {
     Config conf = InstanceResource::getConfig();
     conf.key() = "model";
-    //nop
+    conf.addIfSet("can_scale_to_fit_xy", _canScaleToFitXY);
+    conf.addIfSet("can_scale_to_fit_z",  _canScaleToFitZ);
     return conf;
 }
 
+const osg::BoundingBox&
+ModelResource::getBoundingBox(const osgDB::Options* dbo)
+{
+    if ( !_bbox.valid() )
+    {
+        Threading::ScopedMutexLock lock(_mutex);
+        if ( !_bbox.valid() )
+        {
+            osg::ref_ptr<osg::Node> node = createNodeFromURI( uri().get(), dbo );
+            if ( node.valid() )
+            {
+                osg::ComputeBoundsVisitor cbv;
+                node->accept(cbv);
+                _bbox = cbv.getBoundingBox();
+            }
+        }
+    }
+    return _bbox;
+}
+
+namespace
+{
+    struct SetUnRefPolicyToFalse : public TextureAndImageVisitor
+    {
+        void apply(osg::Texture& texture)
+        {
+            texture.setUnRefImageDataAfterApply(false);
+        }
+    };
+}
+
 osg::Node*
 ModelResource::createNodeFromURI( const URI& uri, const osgDB::Options* dbOptions ) const
 {
-    osg::ref_ptr< osgDB::Options > options = dbOptions ? new osgDB::Options( *dbOptions ) : 0;
+    osg::ref_ptr< osgDB::Options > options = dbOptions ? new osgDB::Options( *dbOptions ) : 0L;
 
     // Explicitly cache images so that models that share images will only load one copy.
-    options->setObjectCacheHint( osgDB::Options::CACHE_IMAGES );
+    // If the options struture doesn't contain an object cache, OSG will use the global
+    // object cache stored in the Registry. Without this, models that share textures or
+    // use an atlas will duplicate memory usage.
+    //
+    // I don't like having this here - it seems like it belongs elsewhere and the caller
+    // should be passing it in. But it needs to be set, so keep for now.
+    if ( options.valid() )
+    {
+        options->setObjectCacheHint( osgDB::Options::CACHE_IMAGES );
+    }
+
     osg::Node* node = 0L;
 
     ReadResult r = uri.readNode( options.get() );
@@ -70,10 +117,20 @@ ModelResource::createNodeFromURI( const URI& uri, const osgDB::Options* dbOption
 
         osgUtil::Optimizer o;
         o.optimize( node,
-            o.DEFAULT_OPTIMIZATIONS |
-            o.INDEX_MESH |
-            o.VERTEX_PRETRANSFORM |
+            o.REMOVE_REDUNDANT_NODES |
+            o.COMBINE_ADJACENT_LODS  |
+            o.MERGE_GEOMETRY         |
+            o.MAKE_FAST_GEOMETRY     |
+            o.CHECK_GEOMETRY         |
+            o.SHARE_DUPLICATE_STATE  |
+            o.INDEX_MESH             |
+            o.VERTEX_PRETRANSFORM    |
             o.VERTEX_POSTTRANSFORM );
+        
+
+        // Disable automatic texture unref since resources can be shared/paged.
+        SetUnRefPolicyToFalse visitor;
+        node->accept( visitor );
     }
     else // failing that, fall back on the old encoding format..
     {
diff --git a/src/osgEarthSymbology/ModelSymbol b/src/osgEarthSymbology/ModelSymbol
index b63e5e7..fc22629 100644
--- a/src/osgEarthSymbology/ModelSymbol
+++ b/src/osgEarthSymbology/ModelSymbol
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -59,6 +59,39 @@ namespace osgEarth { namespace Symbology
         /** whether to automatically scale the model from meters to pixels */
         optional<bool>& autoScale() { return _autoScale; }
         const optional<bool>& autoScale() const { return _autoScale; }
+
+		/** minimum scale of the model when autoscale is enabled */
+        optional<double>& minAutoScale() { return _minAutoScale; }
+        const optional<double>& minAutoScale() const { return _minAutoScale; }
+		
+		/** maximum scale of the model when autoscale is enabled */
+        optional<double>& maxAutoScale() { return _maxAutoScale; }
+        const optional<double>& maxAutoScale() const { return _maxAutoScale; }
+		
+        /** Name of a specific model in the catalog */
+        optional<StringExpression>& name() { return _name; }
+        const optional<StringExpression>& name() const { return _name; }
+        
+        /** Maximum acceptable model length (size in the X dimension) */
+        optional<float>& maxSizeX() { return _maxSizeX; }
+        const optional<float>& maxSizeX() const { return _maxSizeX; }
+        
+        /** Maximum acceptable model width (size in the Y dimension) */
+        optional<float>& maxSizeY() { return _maxSizeY; }
+        const optional<float>& maxSizeY() const { return _maxSizeY; }
+
+        /** Model instance scale factor */
+        optional<NumericExpression>& scaleX() { return _scaleX; }
+        const optional<NumericExpression>& scaleX() const { return _scaleX; }
+
+        /** Model instance scale factor */
+        optional<NumericExpression>& scaleY() { return _scaleY; }
+        const optional<NumericExpression>& scaleY() const { return _scaleY; }
+
+        /** Model instance scale factor */
+        optional<NumericExpression>& scaleZ() { return _scaleZ; }
+        const optional<NumericExpression>& scaleZ() const { return _scaleZ; }
+
         
         
     public: // non-serialized properties (for programmatic use only)
@@ -81,7 +114,15 @@ namespace osgEarth { namespace Symbology
         optional<NumericExpression>  _pitch;
         optional<NumericExpression>  _roll;
         optional<bool>               _autoScale;
+		optional<double>			 _minAutoScale;
+		optional<double>			 _maxAutoScale;
         osg::ref_ptr<osg::Node>      _node;
+        optional<StringExpression>   _name;
+        optional<float>              _maxSizeX;
+        optional<float>              _maxSizeY;
+        optional<NumericExpression>  _scaleX;
+        optional<NumericExpression>  _scaleY;
+        optional<NumericExpression>  _scaleZ;
     };
 
 } } // namespace osgEarth::Symbology
diff --git a/src/osgEarthSymbology/ModelSymbol.cpp b/src/osgEarthSymbology/ModelSymbol.cpp
index c7b9562..3994765 100644
--- a/src/osgEarthSymbology/ModelSymbol.cpp
+++ b/src/osgEarthSymbology/ModelSymbol.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -31,8 +31,17 @@ _heading(rhs._heading),
 _pitch(rhs._pitch),
 _roll(rhs._roll),
 _autoScale(rhs._autoScale),
-_node(rhs._node)
+_minAutoScale(rhs._minAutoScale),
+_maxAutoScale(rhs._maxAutoScale),
+_name(rhs._name),
+_node(rhs._node),
+_maxSizeX(rhs._maxSizeX),
+_maxSizeY(rhs._maxSizeY),
+_scaleX( rhs._scaleX ),
+_scaleY( rhs._scaleY ),
+_scaleZ( rhs._scaleZ )
 {
+    // nop
 }
 
 ModelSymbol::ModelSymbol( const Config& conf ) :
@@ -40,7 +49,14 @@ InstanceSymbol( conf ),
 _heading  ( NumericExpression(0.0) ),
 _pitch    ( NumericExpression(0.0) ),
 _roll     ( NumericExpression(0.0) ),
-_autoScale( false )
+_autoScale( false ),
+_minAutoScale	( 0.0 ),
+_maxAutoScale	( DBL_MAX ),
+_maxSizeX ( FLT_MAX ),
+_maxSizeY ( FLT_MAX ),
+_scaleX    ( NumericExpression(1.0) ),
+_scaleY    ( NumericExpression(1.0) ),
+_scaleZ    ( NumericExpression(1.0) )
 {
     mergeConfig( conf );
 }
@@ -53,10 +69,20 @@ ModelSymbol::getConfig() const
     conf.addObjIfSet( "heading",    _heading );
     conf.addObjIfSet( "pitch",      _pitch );
     conf.addObjIfSet( "roll",       _roll );
+    conf.addObjIfSet( "name",       _name );
     
     conf.addIfSet( "auto_scale", _autoScale );
+	conf.addIfSet( "min_auto_scale", _minAutoScale );
+	conf.addIfSet( "max_auto_scale", _maxAutoScale );
     conf.addIfSet( "alias_map", _uriAliasMap );
 
+    conf.addIfSet( "max_size_x", _maxSizeX );
+    conf.addIfSet( "max_size_y", _maxSizeY );
+    
+    conf.addObjIfSet( "scale_x", _scaleX );
+    conf.addObjIfSet( "scale_y", _scaleY );
+    conf.addObjIfSet( "scale_z", _scaleZ );
+
     conf.addNonSerializable( "ModelSymbol::node", _node.get() );
     return conf;
 }
@@ -67,9 +93,19 @@ ModelSymbol::mergeConfig( const Config& conf )
     conf.getObjIfSet( "heading", _heading );
     conf.getObjIfSet( "pitch",   _pitch );
     conf.getObjIfSet( "roll",    _roll );
+    conf.getObjIfSet( "name",    _name );
+
+    conf.getIfSet( "max_size_x", _maxSizeX );
+    conf.getIfSet( "max_size_y", _maxSizeY );
 
     conf.getIfSet( "auto_scale", _autoScale );
+	conf.getIfSet( "min_auto_scale", _minAutoScale);
+	conf.getIfSet( "max_auto_scale", _maxAutoScale);
     conf.getIfSet( "alias_map", _uriAliasMap );
+    
+    conf.getObjIfSet( "scale_x", _scaleX );
+    conf.getObjIfSet( "scale_y", _scaleY );
+    conf.getObjIfSet( "scale_z", _scaleZ );
 
     _node = conf.getNonSerializable<osg::Node>( "ModelSymbol::node" );
 }
@@ -112,11 +148,35 @@ ModelSymbol::parseSLD(const Config& c, Style& style)
         else
             style.getOrCreate<ModelSymbol>()->scale() = NumericExpression(c.value());
     }
+	else if (match(c.key(), "model-min-auto-scale")) {
+		style.getOrCreate<ModelSymbol>()->minAutoScale() = as<double>(c.value(), 0.0f);
+	}
+	else if (match(c.key(), "model-max-auto-scale")) {
+		style.getOrCreate<ModelSymbol>()->maxAutoScale() = as<double>(c.value(), DBL_MAX);
+	}
+    else if ( match(c.key(), "model-scale-x") ) {
+        style.getOrCreate<ModelSymbol>()->scaleX() = NumericExpression(c.value());
+    }
+    else if ( match(c.key(), "model-scale-y") ) {
+        style.getOrCreate<ModelSymbol>()->scaleY() = NumericExpression(c.value());
+    }
+    else if ( match(c.key(), "model-scale-z") ) {
+        style.getOrCreate<ModelSymbol>()->scaleZ() = NumericExpression(c.value());
+    }
     else if ( match(c.key(), "model-heading") ) {
         style.getOrCreate<ModelSymbol>()->heading() = NumericExpression(c.value());
     }
     else if ( match(c.key(), "model-script") ) {
         style.getOrCreate<ModelSymbol>()->script() = StringExpression(c.value());
     }
+    else if ( match(c.key(), "model-name") ) {
+        style.getOrCreate<ModelSymbol>()->name() = StringExpression(c.value());
+    }
+    else if ( match(c.key(), "model-max-size-x") ) {
+        style.getOrCreate<ModelSymbol>()->maxSizeX() = as<float>(c.value(), FLT_MAX);
+    }
+    else if ( match(c.key(), "model-max-size-y") ) {
+        style.getOrCreate<ModelSymbol>()->maxSizeY() = as<float>(c.value(), FLT_MAX);
+    }
 }
 
diff --git a/src/osgEarthSymbology/PointSymbol b/src/osgEarthSymbology/PointSymbol
index 38d9a9a..8fe5a29 100644
--- a/src/osgEarthSymbology/PointSymbol
+++ b/src/osgEarthSymbology/PointSymbol
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthSymbology/PointSymbol.cpp b/src/osgEarthSymbology/PointSymbol.cpp
index e3408b5..7fe9d1b 100644
--- a/src/osgEarthSymbology/PointSymbol.cpp
+++ b/src/osgEarthSymbology/PointSymbol.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthSymbology/PolygonSymbol b/src/osgEarthSymbology/PolygonSymbol
index e1b183c..3415034 100644
--- a/src/osgEarthSymbology/PolygonSymbol
+++ b/src/osgEarthSymbology/PolygonSymbol
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthSymbology/PolygonSymbol.cpp b/src/osgEarthSymbology/PolygonSymbol.cpp
index d40584f..47fad5f 100644
--- a/src/osgEarthSymbology/PolygonSymbol.cpp
+++ b/src/osgEarthSymbology/PolygonSymbol.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthSymbology/Query b/src/osgEarthSymbology/Query
index 6d3e449..1fd899e 100644
--- a/src/osgEarthSymbology/Query
+++ b/src/osgEarthSymbology/Query
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -28,6 +28,8 @@
 
 namespace osgEarth { namespace Symbology
 {
+    using namespace osgEarth;
+
     /**
      * A query filter that you can use to limit a set of symbology to process.
      */
@@ -36,6 +38,8 @@ namespace osgEarth { namespace Symbology
     public:
         Query( const Config& conf =Config() );
 
+        Query(const Query& rhs);
+
         virtual ~Query() { }
 
     public: // properties
diff --git a/src/osgEarthSymbology/Query.cpp b/src/osgEarthSymbology/Query.cpp
index b21bdad..ccb70de 100644
--- a/src/osgEarthSymbology/Query.cpp
+++ b/src/osgEarthSymbology/Query.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -27,6 +27,16 @@ _map(0)
     mergeConfig( conf );
 }
 
+Query::Query(const Query& rhs) :
+_bounds(rhs._bounds),
+_expression(rhs._expression),
+_orderby(rhs._orderby),
+_tileKey(rhs._tileKey),
+_map(rhs._map)
+{
+    //nop
+}
+
 void
 Query::mergeConfig( const Config& conf )
 {
diff --git a/src/osgEarthSymbology/RenderSymbol b/src/osgEarthSymbology/RenderSymbol
index 01f8df0..43c6c85 100644
--- a/src/osgEarthSymbology/RenderSymbol
+++ b/src/osgEarthSymbology/RenderSymbol
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -69,6 +69,10 @@ namespace osgEarth { namespace Symbology
         optional<float>& minAlpha() { return _minAlpha; }
         const optional<float>& minAlpha() const { return _minAlpha; }
 
+        /** hint to render in the transparent (depth-sorted) bin */
+        optional<bool>& transparent() { return _transparent; }
+        const optional<bool>& transparent() const { return _transparent; }
+
         /** render bin to use for sorting */
         optional<std::string>& renderBin() { return _renderBin; }
         const optional<std::string>& renderBin() const { return _renderBin; }
@@ -87,6 +91,7 @@ namespace osgEarth { namespace Symbology
         optional<unsigned>           _clipPlane;
         optional<float>              _minAlpha;
         optional<std::string>        _renderBin;
+        optional<bool>               _transparent;
         
         /** dtor */
         virtual ~RenderSymbol() { }
diff --git a/src/osgEarthSymbology/RenderSymbol.cpp b/src/osgEarthSymbology/RenderSymbol.cpp
index b526d1a..d029f16 100644
--- a/src/osgEarthSymbology/RenderSymbol.cpp
+++ b/src/osgEarthSymbology/RenderSymbol.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -33,7 +33,8 @@ _backfaceCulling(rhs._backfaceCulling),
 _order(rhs._order),
 _clipPlane(rhs._clipPlane),
 _minAlpha(rhs._minAlpha),
-_renderBin(rhs._renderBin)
+_renderBin(rhs._renderBin),
+_transparent(rhs._transparent)
 {
 }
 
@@ -44,7 +45,8 @@ _lighting       ( true ),
 _backfaceCulling( true ),
 _order          ( 0 ),
 _clipPlane      ( 0 ),
-_minAlpha       ( 0.0f )
+_minAlpha       ( 0.0f ),
+_transparent    ( false )
 {
     mergeConfig(conf);
 }
@@ -62,6 +64,7 @@ RenderSymbol::getConfig() const
     conf.addIfSet   ( "clip_plane",       _clipPlane );
     conf.addIfSet   ( "min_alpha",        _minAlpha );
     conf.addIfSet   ( "render_bin",       _renderBin );
+    conf.addIfSet   ( "transparent",      _transparent );
     return conf;
 }
 
@@ -76,6 +79,7 @@ RenderSymbol::mergeConfig( const Config& conf )
     conf.getIfSet   ( "clip_plane",       _clipPlane );
     conf.getIfSet   ( "min_alpha",        _minAlpha );
     conf.getIfSet   ( "render_bin",       _renderBin );
+    conf.getIfSet   ( "transparent",      _transparent );
 }
 
 void
@@ -123,4 +127,7 @@ RenderSymbol::parseSLD(const Config& c, Style& style)
     else if ( match(c.key(), "render-bin") ) {
         style.getOrCreate<RenderSymbol>()->renderBin() = c.value();
     }
+    else if ( match(c.key(), "render-transparent") ) {
+        style.getOrCreate<RenderSymbol>()->transparent() = as<bool>(c.value(), *defaults.transparent() );
+    }
 }
diff --git a/src/osgEarthSymbology/Resource b/src/osgEarthSymbology/Resource
index a8a1441..6269b6c 100644
--- a/src/osgEarthSymbology/Resource
+++ b/src/osgEarthSymbology/Resource
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -23,6 +23,7 @@
 #include <osgEarthSymbology/Common>
 #include <osgEarthSymbology/Tags>
 #include <osgEarth/Config>
+#include <vector>
 
 namespace osgEarth { namespace Symbology
 {
@@ -61,6 +62,8 @@ namespace osgEarth { namespace Symbology
         std::string _name;
     };
 
+    typedef std::vector< osg::ref_ptr<Resource> > ResourceVector;
+
 } } // namespace osgEarth::Symbology
 
 #endif // OSGEARTHSYMBOLOGY_SKIN_RESOURCE_H
diff --git a/src/osgEarthSymbology/Resource.cpp b/src/osgEarthSymbology/Resource.cpp
index d118770..cf3060d 100644
--- a/src/osgEarthSymbology/Resource.cpp
+++ b/src/osgEarthSymbology/Resource.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthSymbology/ResourceCache b/src/osgEarthSymbology/ResourceCache
index 704199d..758c150 100644
--- a/src/osgEarthSymbology/ResourceCache
+++ b/src/osgEarthSymbology/ResourceCache
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -44,15 +44,14 @@ namespace osgEarth { namespace Symbology
         /** 
          * Constructs a new resource cache.
          */
-        ResourceCache( 
-            const osgDB::Options* dbOptions );
+        ResourceCache();
 
         /**
          * Fetches the StateSet implementation corresponding to a Skin.
          * @param skin   Skin resource for which to get or create a state set.
          * @param output Result goes here.
          */
-        bool getOrCreateStateSet( SkinResource* skin, osg::ref_ptr<osg::StateSet>& output );
+        bool getOrCreateStateSet(SkinResource* skin, osg::ref_ptr<osg::StateSet>& output, const osgDB::Options* readOptions);
 
         /**
          * Get the statistics collected from the skin cache.
@@ -64,20 +63,22 @@ namespace osgEarth { namespace Symbology
          * @param skin   Instance resource for which to get or create a Node.
          * @param output Result goes here.
          */
-        bool getOrCreateInstanceNode( InstanceResource* instance, osg::ref_ptr<osg::Node>& output );
-        bool cloneOrCreateInstanceNode( InstanceResource* instance, osg::ref_ptr<osg::Node>& output );
+        bool getOrCreateInstanceNode( InstanceResource* instance, osg::ref_ptr<osg::Node>& output, const osgDB::Options* readOptions );
+        bool cloneOrCreateInstanceNode( InstanceResource* instance, osg::ref_ptr<osg::Node>& output, const osgDB::Options* readOptions );
+
+        const CacheStats getInstanceStats() const { return _instanceCache.getStats(); }
 
         /**
          * Fetches the StateSet implemention for an entire ResourceLibrary.  This will contain a Texture2DArray with all of the skins merged into it.
          * @param library    The library 
          * @param output     Result goes here. 
          */
-        bool getOrCreateStateSet( ResourceLibrary* library,  osg::ref_ptr<osg::StateSet>& output );
+        bool getOrCreateStateSet( ResourceLibrary* library,  osg::ref_ptr<osg::StateSet>& output, const osgDB::Options* readOptions );
 
     protected:
         virtual ~ResourceCache() { }
 
-        osg::ref_ptr<const osgDB::Options> _dbOptions;
+        //osg::ref_ptr<const osgDB::Options> _dbOptions;
 
         //typedef LRUCache<std::string, osg::observer_ptr<osg::StateSet> > SkinCache;
         typedef LRUCache<std::string, osg::ref_ptr<osg::StateSet> > SkinCache;
diff --git a/src/osgEarthSymbology/ResourceCache.cpp b/src/osgEarthSymbology/ResourceCache.cpp
index df04bda..2a5fb5c 100644
--- a/src/osgEarthSymbology/ResourceCache.cpp
+++ b/src/osgEarthSymbology/ResourceCache.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -23,8 +23,8 @@ using namespace osgEarth::Symbology;
 
 
 // internal thread-safety not required since we mutex it in this object.
-ResourceCache::ResourceCache(const osgDB::Options* dbOptions ) :
-_dbOptions    ( dbOptions ),
+ResourceCache::ResourceCache() : // const osgDB::Options* dbOptions ) :
+//_dbOptions    ( dbOptions ),
 _skinCache    ( false ),
 _instanceCache( false ),
 _resourceLibraryCache( false )
@@ -34,7 +34,8 @@ _resourceLibraryCache( false )
 
 bool
 ResourceCache::getOrCreateStateSet(SkinResource*                skin,
-                                   osg::ref_ptr<osg::StateSet>& output)
+                                   osg::ref_ptr<osg::StateSet>& output,
+                                   const osgDB::Options*        readOptions)
 {
     output = 0L;
     //std::string key = skin->getConfig().toJSON(false);
@@ -58,7 +59,7 @@ ResourceCache::getOrCreateStateSet(SkinResource*                skin,
         else
         {
             // still not there, make it.
-            output = skin->createStateSet( _dbOptions.get() );
+            output = skin->createStateSet(readOptions);
             if ( output.valid() )
             {
                 _skinCache.insert( key, output.get() );
@@ -72,7 +73,8 @@ ResourceCache::getOrCreateStateSet(SkinResource*                skin,
 
 bool
 ResourceCache::getOrCreateInstanceNode(InstanceResource*        res,
-                                       osg::ref_ptr<osg::Node>& output)
+                                       osg::ref_ptr<osg::Node>& output,
+                                       const osgDB::Options*    readOptions)
 {
     output = 0L;
     std::string key = res->getConfig().toJSON(false);
@@ -90,7 +92,7 @@ ResourceCache::getOrCreateInstanceNode(InstanceResource*        res,
         else
         {
             // still not there, make it.
-            output = res->createNode( _dbOptions.get() );
+            output = res->createNode(readOptions);
             if ( output.valid() )
             {
                 _instanceCache.insert( key, output.get() );
@@ -103,7 +105,8 @@ ResourceCache::getOrCreateInstanceNode(InstanceResource*        res,
 
 bool
 ResourceCache::cloneOrCreateInstanceNode(InstanceResource*        res,
-                                         osg::ref_ptr<osg::Node>& output)
+                                         osg::ref_ptr<osg::Node>& output,
+                                         const osgDB::Options*    readOptions)
 {
     output = 0L;
     std::string key = res->getConfig().toJSON(false);
@@ -113,7 +116,7 @@ ResourceCache::cloneOrCreateInstanceNode(InstanceResource*        res,
         Threading::ScopedMutexLock exclusive( _instanceMutex );
 
         // Deep copy everything except for images.  Some models may share imagery so we only want one copy of it at a time.
-        osg::CopyOp copyOp = osg::CopyOp::DEEP_COPY_ALL & ~osg::CopyOp::DEEP_COPY_IMAGES;
+        osg::CopyOp copyOp = osg::CopyOp::DEEP_COPY_ALL & ~osg::CopyOp::DEEP_COPY_IMAGES & ~osg::CopyOp::DEEP_COPY_TEXTURES;
 
         // double check to avoid race condition
         InstanceCache::Record rec;
@@ -124,7 +127,7 @@ ResourceCache::cloneOrCreateInstanceNode(InstanceResource*        res,
         else
         {
             // still not there, make it.
-            output = res->createNode( _dbOptions.get() );
+            output = res->createNode(readOptions);
             if ( output.valid() )
             {
                 _instanceCache.insert( key, output.get() );
diff --git a/src/osgEarthSymbology/ResourceLibrary b/src/osgEarthSymbology/ResourceLibrary
index 5a8ad6d..0c1c032 100644
--- a/src/osgEarthSymbology/ResourceLibrary
+++ b/src/osgEarthSymbology/ResourceLibrary
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -24,6 +24,8 @@
 #include <osgEarthSymbology/Skins>
 #include <osgEarthSymbology/MarkerResource>
 #include <osgEarthSymbology/InstanceResource>
+#include <osgEarthSymbology/ModelResource>
+#include <osgEarthSymbology/ModelSymbol>
 #include <osgEarth/ThreadingUtils>
 #include <osgEarth/Random>
 #include <map>
@@ -35,9 +37,6 @@ namespace osgEarth { namespace Symbology
     /** 
      * ResourceLibrary manages a collection of external resources that a
      * build system can use the construct geometries.
-     *
-     * TODO: This class PROBABLY NEEDS the ability to share a mutex with
-     * whatever session is using it... like in osgGIS...
      */
     class OSGEARTHSYMBOLOGY_EXPORT ResourceLibrary : public osg::Referenced
     {
@@ -126,7 +125,18 @@ namespace osgEarth { namespace Symbology
          * Finds an instance-resource by name.
          */
         InstanceResource* getInstance( const std::string& name, const osgDB::Options* dbOptions =0L ) const;
+        
+        ModelResource* getModel( const ModelSymbol* ms, const osgDB::Options* dbOptions =0L ) const;
 
+        /**
+         * Returns a list of all Model resources.
+         */
+        void getModels( ModelResourceVector& output, const osgDB::Options* dbOptions =0L ) const;
+        
+        /**
+         * Returns a list of models that match the input symbol.
+         */
+        void getModels(const ModelSymbol* ms, ModelResourceVector& output, const osgDB::Options* dbOptions =0L) const;
 
     public: // serialization functions
 
diff --git a/src/osgEarthSymbology/ResourceLibrary.cpp b/src/osgEarthSymbology/ResourceLibrary.cpp
index dffdbba..2718ed6 100644
--- a/src/osgEarthSymbology/ResourceLibrary.cpp
+++ b/src/osgEarthSymbology/ResourceLibrary.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -347,3 +347,69 @@ ResourceLibrary::getInstance( const std::string& name, const osgDB::Options* dbO
     ResourceMap<InstanceResource>::const_iterator i = _instances.find( name );
     return i != _instances.end() ? i->second.get() : 0L;
 }
+
+ModelResource*
+ResourceLibrary::getModel( const ModelSymbol* ms, const osgDB::Options* dbOptions ) const
+{
+    const_cast<ResourceLibrary*>(this)->initialize( dbOptions );
+    Threading::ScopedReadLock shared( _mutex );
+    ResourceMap<InstanceResource>::const_iterator i = _instances.find( ms->name()->eval() );
+    return i != _instances.end() ? dynamic_cast<ModelResource*>(i->second.get()) : 0L;
+}
+
+void
+ResourceLibrary::getModels( ModelResourceVector& output, const osgDB::Options* dbOptions ) const
+{
+    const_cast<ResourceLibrary*>(this)->initialize( dbOptions );
+    Threading::ScopedReadLock shared( _mutex );
+    output.reserve( _instances.size() );
+    for( ResourceMap<InstanceResource>::const_iterator i = _instances.begin(); i != _instances.end(); ++i ) {
+        ModelResource* m = dynamic_cast<ModelResource*>(i->second.get());
+        if ( m ) output.push_back( m );
+    }
+}
+
+void
+ResourceLibrary::getModels(const ModelSymbol* ms, ModelResourceVector& output, const osgDB::Options* dbOptions) const
+{
+    if ( !ms ) return;
+
+    // if a name is set, use the other getter.
+    if ( ms->name().isSet() )
+    {
+        ModelResource* mr = getModel(ms, dbOptions);
+        if ( mr )
+            output.push_back( mr );
+    }
+
+    else
+    {
+        const_cast<ResourceLibrary*>(this)->initialize( dbOptions );
+
+        Threading::ScopedReadLock shared( _mutex );
+
+        output.reserve( _instances.size() );
+        for( ResourceMap<InstanceResource>::const_iterator i = _instances.begin(); i != _instances.end(); ++i )
+        {
+            ModelResource* m = dynamic_cast<ModelResource*>(i->second.get());
+            if ( m )
+            {
+                if (ms && ms->tags().size() > 0 && !m->containsTags(ms->tags()) )
+                    continue;
+
+                // if there's a size restriction, pre-load the model so we can know its size.
+                if (ms && ms->maxSizeX().isSet() && ms->maxSizeY().isSet())
+                {
+                    const osg::BoundingBox& bbox = m->getBoundingBox( dbOptions );
+                    if ( ms->maxSizeX().get() < (bbox.xMax() - bbox.xMin()) )
+                        continue;
+                    if ( ms->maxSizeY().get() < (bbox.yMax() - bbox.yMin()) )
+                        continue;
+                }
+
+                // good, return it
+                output.push_back( m );
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/osgEarthSymbology/Skins b/src/osgEarthSymbology/Skins
index a9a216b..4261784 100644
--- a/src/osgEarthSymbology/Skins
+++ b/src/osgEarthSymbology/Skins
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -25,7 +25,7 @@
 #include <osgEarthSymbology/Symbol>
 #include <osgEarth/URI>
 #include <osg/TexEnv>
-#include <osg/Texture2DArray>
+#include <osg/Image>
 
 namespace osgEarth { namespace Symbology
 {
@@ -52,7 +52,11 @@ namespace osgEarth { namespace Symbology
         /**
          * Creates an image for this SkinResource.
          */
-        osg::Image* createImage( const osgDB::Options* options ) const;
+        osg::ref_ptr<osg::Image> createImage( const osgDB::Options* options ) const;
+        
+        osg::Texture* createTexture(const osgDB::Options* readOptions) const;
+
+        osg::Texture* createTexture(osg::Image* image) const;
 
         /** 
          * A key string that can uniquely identify this object for the purposes
@@ -61,6 +65,10 @@ namespace osgEarth { namespace Symbology
         std::string getUniqueID() const;
 
     public:
+        /** inline image (not serializable) */
+        osg::ref_ptr<osg::Image>& image() { return _image; }
+        const osg::ref_ptr<osg::Image>& image() const { return _image; }
+
         /** Source location of the actual texture image.  */
         optional<URI>& imageURI() { return _imageURI; }
         const optional<URI>& imageURI() const { return _imageURI; }
@@ -113,6 +121,14 @@ namespace osgEarth { namespace Symbology
         optional<unsigned> maxTextureSpan() { return _maxTexSpan; }
         const optional<unsigned> maxTextureSpan() const { return _maxTexSpan; }
 
+        /** Whether this image is suitable for texture atlasing */
+        optional<bool>& atlasHint() { return _atlasHint; }
+        const optional<bool>& atlasHint() const { return _atlasHint; }
+
+        /** Options string to pass in when reading the image */
+        optional<std::string>& readOptions() { return _readOptions; }
+        const optional<std::string>& readOptions() const { return _readOptions; }
+
     public: // serialization methods
 
         virtual Config getConfig() const;
@@ -138,6 +154,10 @@ namespace osgEarth { namespace Symbology
         optional<unsigned>          _imageLayer;
         optional<float>             _imageScaleS;
         optional<float>             _imageScaleT;
+        optional<bool>              _atlasHint;
+        optional<std::string>       _readOptions;
+
+        osg::ref_ptr<osg::Image>    _image;
     };
 
 
@@ -203,37 +223,6 @@ namespace osgEarth { namespace Symbology
 
     typedef std::vector< osg::ref_ptr<SkinResource> > SkinResourceVector;
 
-#if 0
-    /**
-     * Utility class that builds a Texture2DArray from a list of SkinResources
-     */
-    class OSGEARTHSYMBOLOGY_EXPORT SkinTextureArray : public osg::Referenced
-    {
-    public:
-        SkinTextureArray();
-
-        /**
-         * Gets the Texture2DArray for this SkinTextureArray
-         */
-        osg::Texture2DArray* getTexture();
-
-        /**
-         * Gets the index into the texture array for the given SkinResource.
-         */
-        int getSkinIndex( const SkinResource* skin );
-
-        /**
-         * Builds a Texture2DArray from the given SkinResources.
-         */
-        void build(SkinResourceVector& skins, const osgDB::Options* dbOptions);
-
-    protected:
-
-        typedef std::map< std::string, int > LayerIndex;
-        LayerIndex _layerIndex;
-        osg::ref_ptr< osg::Texture2DArray > _texture;
-    };
-#endif
 
 } } // namespace osgEarth::Symbology
 
diff --git a/src/osgEarthSymbology/Skins.cpp b/src/osgEarthSymbology/Skins.cpp
index b51ccab..31a76a0 100644
--- a/src/osgEarthSymbology/Skins.cpp
+++ b/src/osgEarthSymbology/Skins.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -24,6 +24,7 @@
 
 #include <osg/BlendFunc>
 #include <osg/Texture2D>
+#include <osg/Texture2DArray>
 
 #define LC "[SkinResource] "
 
@@ -45,7 +46,8 @@ _imageBiasS       ( 0.0f ),
 _imageBiasT       ( 0.0f ),
 _imageLayer       ( 0 ),
 _imageScaleS      ( 1.0f ),
-_imageScaleT      ( 1.0f )
+_imageScaleT      ( 1.0f ),
+_atlasHint        ( true )
 {
     mergeConfig( conf );
 }
@@ -72,6 +74,9 @@ SkinResource::mergeConfig( const Config& conf )
     conf.getIfSet( "image_layer",         _imageLayer );
     conf.getIfSet( "image_scale_s",       _imageScaleS );
     conf.getIfSet( "image_scale_t",       _imageScaleT );
+
+    conf.getIfSet( "atlas", _atlasHint );
+    conf.getIfSet( "read_options", _readOptions );
 }
 
 Config
@@ -99,6 +104,9 @@ SkinResource::getConfig() const
     conf.updateIfSet( "image_layer",         _imageLayer );
     conf.updateIfSet( "image_scale_s",       _imageScaleS );
     conf.updateIfSet( "image_scale_t",       _imageScaleT );
+    
+    conf.updateIfSet( "atlas", _atlasHint );
+    conf.updateIfSet( "read_options", _readOptions );
 
     return conf;
 }
@@ -109,11 +117,65 @@ SkinResource::getUniqueID() const
     return imageURI()->full();
 }
 
+osg::Texture*
+SkinResource::createTexture(const osgDB::Options* readOptions) const
+{
+    OE_DEBUG << LC << "Creating skin texture for " << imageURI()->full() << std::endl;
+    osg::ref_ptr<osg::Image> image = createImage(readOptions);
+    return createTexture(image.get());
+}
+
+osg::Texture*
+SkinResource::createTexture(osg::Image* image) const
+{
+    if ( !image ) return 0L;
+
+    osg::Texture* tex;
+
+    if (image->r() > 1)
+    {
+        osg::Texture2DArray* ta = new osg::Texture2DArray();
+
+        ta->setTextureDepth(image->r());
+        ta->setTextureWidth(image->s());
+        ta->setTextureHeight(image->t());
+        ta->setInternalFormatMode(osg::Texture::USE_IMAGE_DATA_FORMAT);
+        tex = ta;
+
+        std::vector<osg::ref_ptr<osg::Image> > layers;
+        ImageUtils::flattenImage(image, layers);
+        for (unsigned i = 0; i < layers.size(); ++i)
+        {
+            tex->setImage(i, layers[i].get());
+        }
+        tex->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP_TO_EDGE);
+        tex->setWrap(osg::Texture::WRAP_T, osg::Texture::CLAMP_TO_EDGE);
+    }
+    else
+    {
+        tex = new osg::Texture2D(image);
+        tex->setWrap(osg::Texture::WRAP_S, osg::Texture::REPEAT);
+        tex->setWrap(osg::Texture::WRAP_T, osg::Texture::REPEAT);
+    }
+
+    tex->setFilter(osg::Texture::MIN_FILTER, osg::Texture::LINEAR_MIPMAP_LINEAR);
+    tex->setFilter(osg::Texture::MAG_FILTER, osg::Texture::LINEAR);
+
+    // skin textures are likely to be shared, paged, etc. so keep them in memory.
+    tex->setUnRefImageDataAfterApply(false);
+
+    // don't resize them, let it be
+    tex->setResizeNonPowerOfTwoHint(false);
+
+    return tex;
+}
+
 osg::StateSet*
-SkinResource::createStateSet( const osgDB::Options* dbOptions ) const
+SkinResource::createStateSet(const osgDB::Options* readOptions) const
 {
     OE_DEBUG << LC << "Creating skin state set for " << imageURI()->full() << std::endl;
-    return createStateSet( createImage(dbOptions) );
+    osg::ref_ptr<osg::Image> image = createImage(readOptions);
+    return createStateSet(image.get());
 }
 
 osg::StateSet*
@@ -124,66 +186,47 @@ SkinResource::createStateSet( osg::Image* image ) const
     {
         stateSet = new osg::StateSet();
         
-        osg::Texture* tex;
-
-        if ( image->r() > 1 )
+        osg::Texture* tex = createTexture(image);
+        if ( tex )
         {
-            osg::Texture2DArray* ta = new osg::Texture2DArray();
-            
-            ta->setTextureDepth( image->r() );
-            ta->setTextureWidth( image->s() );
-            ta->setTextureHeight( image->t() );
-            ta->setInternalFormatMode(osg::Texture::USE_IMAGE_DATA_FORMAT);
-            tex = ta;
-
-            std::vector<osg::ref_ptr<osg::Image> > layers;
-            ImageUtils::flattenImage(image, layers);
-            for(unsigned i=0; i<layers.size(); ++i)
+            stateSet->setTextureAttributeAndModes(0, tex, osg::StateAttribute::ON);
+
+            if ( _texEnvMode.isSet() )
             {
-                tex->setImage(i, layers[i].get());
+                osg::TexEnv* texenv = new osg::TexEnv();
+                texenv = new osg::TexEnv();
+                texenv->setMode( *_texEnvMode );
+                stateSet->setTextureAttributeAndModes( 0, texenv, osg::StateAttribute::ON );
             }
-            tex->setWrap( osg::Texture::WRAP_S, osg::Texture::CLAMP_TO_EDGE );
-            tex->setWrap( osg::Texture::WRAP_T, osg::Texture::CLAMP_TO_EDGE );
-            stateSet->setTextureAttribute( 0, tex, osg::StateAttribute::ON );
-        }
-        else
-        {
-            tex = new osg::Texture2D( image );
-            tex->setWrap( osg::Texture::WRAP_S, osg::Texture::REPEAT );
-            tex->setWrap( osg::Texture::WRAP_T, osg::Texture::REPEAT );     
-            stateSet->setTextureAttributeAndModes( 0, tex, osg::StateAttribute::ON );
-        }
-        
-        tex->setFilter(osg::Texture::MIN_FILTER,osg::Texture::LINEAR_MIPMAP_LINEAR);
-        tex->setFilter(osg::Texture::MAG_FILTER,osg::Texture::LINEAR);
-
-        tex->setUnRefImageDataAfterApply(true);
-        tex->setResizeNonPowerOfTwoHint(false);
 
-        if ( _texEnvMode.isSet() )
-        {
-            osg::TexEnv* texenv = new osg::TexEnv();
-            texenv = new osg::TexEnv();
-            texenv->setMode( *_texEnvMode );
-            stateSet->setTextureAttributeAndModes( 0, texenv, osg::StateAttribute::ON );
-        }
-
-        if ( ImageUtils::hasAlphaChannel( image ) )
-        {
-            osg::BlendFunc* blendFunc = new osg::BlendFunc();
-            blendFunc->setFunction( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
-            stateSet->setAttributeAndModes( blendFunc, osg::StateAttribute::ON );
-            stateSet->setRenderingHint( osg::StateSet::TRANSPARENT_BIN );
+            if ( ImageUtils::hasAlphaChannel( image ) )
+            {
+                osg::BlendFunc* blendFunc = new osg::BlendFunc();
+                blendFunc->setFunction( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
+                stateSet->setAttributeAndModes( blendFunc, osg::StateAttribute::ON );
+                stateSet->setRenderingHint( osg::StateSet::TRANSPARENT_BIN );
+            }
         }
     }
 
     return stateSet;
 }
 
-osg::Image*
+osg::ref_ptr<osg::Image>
 SkinResource::createImage( const osgDB::Options* dbOptions ) const
 {
-    return _imageURI->readImage(dbOptions).releaseImage();
+    ReadResult result;
+    if (_readOptions.isSet())
+    {
+        osg::ref_ptr<osgDB::Options> ro = Registry::cloneOrCreateOptions(dbOptions);
+        ro->setOptionString(Stringify() << _readOptions.get() << " " << ro->getOptionString());
+        result = _imageURI->readImage(ro.get());
+    }
+    else
+    {
+        result = _imageURI->readImage(dbOptions);
+    }
+    return result.releaseImage();
 }
 
 //---------------------------------------------------------------------------
diff --git a/src/osgEarthSymbology/StencilVolumeNode b/src/osgEarthSymbology/StencilVolumeNode
index 5a9fde9..2b9772d 100644
--- a/src/osgEarthSymbology/StencilVolumeNode
+++ b/src/osgEarthSymbology/StencilVolumeNode
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthSymbology/StencilVolumeNode.cpp b/src/osgEarthSymbology/StencilVolumeNode.cpp
index e88dcb2..9796dc3 100644
--- a/src/osgEarthSymbology/StencilVolumeNode.cpp
+++ b/src/osgEarthSymbology/StencilVolumeNode.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -262,7 +262,7 @@ StencilVolumeNode::init()
     // zFail=true if more compute intensive, but lets you get inside the volume.
     // Again, a custom node will give us a better opportunity to choose between zFail and zPass based on
     // the eye location (you only need zFail if you camera is inside the volume).
-    bool zFail = true;
+#define zFail true
 
     OE_DEBUG << "Stencil buffer wrap = " << s_EXT_stencil_wrap << std::endl;
 
diff --git a/src/osgEarthSymbology/Stroke b/src/osgEarthSymbology/Stroke
index e0c2fe4..8a02b01 100644
--- a/src/osgEarthSymbology/Stroke
+++ b/src/osgEarthSymbology/Stroke
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthSymbology/Stroke.cpp b/src/osgEarthSymbology/Stroke.cpp
index 64b0d80..279a00c 100644
--- a/src/osgEarthSymbology/Stroke.cpp
+++ b/src/osgEarthSymbology/Stroke.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthSymbology/Style b/src/osgEarthSymbology/Style
index 7d6c9a7..372ba39 100644
--- a/src/osgEarthSymbology/Style
+++ b/src/osgEarthSymbology/Style
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthSymbology/Style.cpp b/src/osgEarthSymbology/Style.cpp
index 39a27f3..010ae7f 100644
--- a/src/osgEarthSymbology/Style.cpp
+++ b/src/osgEarthSymbology/Style.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthSymbology/StyleSelector b/src/osgEarthSymbology/StyleSelector
index 9650f02..deb41ba 100644
--- a/src/osgEarthSymbology/StyleSelector
+++ b/src/osgEarthSymbology/StyleSelector
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthSymbology/StyleSelector.cpp b/src/osgEarthSymbology/StyleSelector.cpp
index c308aa4..bcb542f 100644
--- a/src/osgEarthSymbology/StyleSelector.cpp
+++ b/src/osgEarthSymbology/StyleSelector.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthSymbology/StyleSheet b/src/osgEarthSymbology/StyleSheet
index f3e110f..57ddda9 100644
--- a/src/osgEarthSymbology/StyleSheet
+++ b/src/osgEarthSymbology/StyleSheet
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -45,6 +45,7 @@ namespace osgEarth { namespace Symbology
         std::string code;
         std::string language;
         std::string name;
+        std::string profile;
         optional<URI> uri;
       };
 
@@ -85,6 +86,9 @@ namespace osgEarth { namespace Symbology
         /** Gets a resource library by name. */
         ResourceLibrary* getResourceLibrary( const std::string& name ) const;
 
+        /** Gets the first library. */
+        ResourceLibrary* getDefaultResourceLibrary() const;
+
         /** Script accessors */
         void setScript( ScriptDef* script );
         ScriptDef* script() const { return _script.get(); }
diff --git a/src/osgEarthSymbology/StyleSheet.cpp b/src/osgEarthSymbology/StyleSheet.cpp
index f2aa948..d8d6ce5 100644
--- a/src/osgEarthSymbology/StyleSheet.cpp
+++ b/src/osgEarthSymbology/StyleSheet.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
@@ -157,6 +157,17 @@ StyleSheet::getResourceLibrary( const std::string& name ) const
         return 0L;
 }
 
+ResourceLibrary*
+StyleSheet::getDefaultResourceLibrary() const
+{
+    Threading::ScopedReadLock shared( const_cast<StyleSheet*>(this)->_resLibsMutex );
+    if ( _resLibs.size() > 0 )
+        return _resLibs.begin()->second.get();
+    else
+        return 0L;
+}
+
+
 void StyleSheet::setScript( ScriptDef* script )
 {
   _script = script;
@@ -199,8 +210,10 @@ StyleSheet::getConfig() const
             scriptConf.set( "name", _script->name );
         if ( !_script->language.empty() )
             scriptConf.set( "language", _script->language );
-        if ( !_script->uri.isSet() )
+        if ( _script->uri.isSet() )
             scriptConf.set( "url", _script->uri->base() );
+        if ( !_script->profile.empty() )
+            scriptConf.set( "profile", _script->profile );
         else if ( !_script->code.empty() )
             scriptConf.value() = _script->code;
 
@@ -246,6 +259,9 @@ StyleSheet::mergeConfig( const Config& conf )
 
         std::string lang = i->value("language");
         _script->language = lang.empty() ? "javascript" : lang;
+
+        std::string profile = i->value("profile");
+        _script->profile = profile;
     }
 
     // read any style class definitions. either "class" or "selector" is allowed
diff --git a/src/osgEarthSymbology/Symbol b/src/osgEarthSymbology/Symbol
index 3076478..b0294da 100644
--- a/src/osgEarthSymbology/Symbol
+++ b/src/osgEarthSymbology/Symbol
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -64,6 +64,8 @@ namespace osgEarth { namespace Symbology
 
         virtual ~Symbol() { }
     };
+
+    typedef std::vector<osg::ref_ptr<Symbol> > SymbolVector;
     typedef std::vector<osg::ref_ptr<Symbol> > SymbolList;
 
 
diff --git a/src/osgEarthSymbology/Symbol.cpp b/src/osgEarthSymbology/Symbol.cpp
index 57a4a18..b13285f 100644
--- a/src/osgEarthSymbology/Symbol.cpp
+++ b/src/osgEarthSymbology/Symbol.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthSymbology/Tags b/src/osgEarthSymbology/Tags
index cf52071..0e6b9cf 100644
--- a/src/osgEarthSymbology/Tags
+++ b/src/osgEarthSymbology/Tags
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -21,6 +21,7 @@
 #define OSGEARTHSYMBOLOGY_TAGS_H 1
 
 #include <osgEarthSymbology/Common>
+#include <osgEarth/Config>
 #include <osgEarth/StringUtils>
 #include <osg/CopyOp>
 #include <vector>
@@ -36,9 +37,9 @@ namespace osgEarth { namespace Symbology
     class Taggable : public T
     {
     public:
-        Taggable()
-        {
-        }
+        Taggable() { }
+
+        //Taggable(const osgEarth::Config& conf) : T(conf) { }
         
         Taggable(const Taggable& rhs,const osg::CopyOp& copyop=osg::CopyOp::SHALLOW_COPY):
         T(rhs, copyop)
diff --git a/src/osgEarthSymbology/TextSymbol b/src/osgEarthSymbology/TextSymbol
index 51c6ea2..8bd1a39 100644
--- a/src/osgEarthSymbology/TextSymbol
+++ b/src/osgEarthSymbology/TextSymbol
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -20,6 +20,7 @@
 #ifndef OSGEARTHSYMBOLOGY_TEXT_SYMBOL_H
 #define OSGEARTHSYMBOLOGY_TEXT_SYMBOL_H 1
 
+#include <osgText/Text>
 #include <osgEarthSymbology/Symbol>
 #include <osgEarthSymbology/Expression>
 #include <osgEarthSymbology/Fill>
@@ -53,16 +54,16 @@ namespace osgEarth { namespace Symbology
             ALIGN_RIGHT_TOP,
             ALIGN_RIGHT_CENTER,
             ALIGN_RIGHT_BOTTOM,
-            
+
             ALIGN_LEFT_BASE_LINE,
             ALIGN_CENTER_BASE_LINE,
             ALIGN_RIGHT_BASE_LINE,
-        
+
             ALIGN_LEFT_BOTTOM_BASE_LINE,
             ALIGN_CENTER_BOTTOM_BASE_LINE,
             ALIGN_RIGHT_BOTTOM_BASE_LINE,
-        
-            ALIGN_BASE_LINE = ALIGN_LEFT_BASE_LINE /// default.        
+
+            ALIGN_BASE_LINE = ALIGN_LEFT_BASE_LINE /// default.
         };
 
         enum Layout {
@@ -91,6 +92,14 @@ namespace osgEarth { namespace Symbology
         optional<float>& haloOffset() { return _haloOffset; }
         const optional<float>& haloOffset() const { return _haloOffset; }
 
+        /** Halo backdrop type */
+        optional<osgText::Text::BackdropType>& haloBackdropType() { return _haloBackdropType; }
+        const optional<osgText::Text::BackdropType>& haloBackdropType() const { return _haloBackdropType; }
+
+        /** Halo backdrop implementation */
+        optional<osgText::Text::BackdropImplementation>& haloImplementation() { return _haloImplementation; }
+        const optional<osgText::Text::BackdropImplementation>& haloImplementation() const { return _haloImplementation; }
+
         /** Name of text font. */
         optional<std::string>& font() { return _font; }
         const optional<std::string>& font() const { return _font; }
@@ -111,6 +120,14 @@ namespace osgEarth { namespace Symbology
         optional<osg::Vec2s>& pixelOffset() { return _pixelOffset; }
         const optional<osg::Vec2s>& pixelOffset() const { return _pixelOffset; }
 
+        /** On screen rotation **/
+        optional<NumericExpression>& onScreenRotation() { return _onScreenRotation; }
+        const optional<NumericExpression>& onScreenRotation() const { return _onScreenRotation; }
+
+        /** Label orientation for following a fixed course on the map. */
+        optional<NumericExpression>& geographicCourse() { return _geographicCourse; }
+        const optional<NumericExpression>& geographicCourse() const { return _geographicCourse; }
+
         /** Alignment of the label relative to (0,0) pixels */
         optional<Alignment>& alignment() { return _alignment; }
         const optional<Alignment>& alignment() const { return _alignment; }
@@ -152,12 +169,16 @@ namespace osgEarth { namespace Symbology
         optional<Fill>              _fill;
         optional<Stroke>            _halo;
         optional<float>             _haloOffset;
+        optional<osgText::Text::BackdropType> _haloBackdropType;
+        optional<osgText::Text::BackdropImplementation> _haloImplementation;
         optional<std::string>       _font;
         optional<NumericExpression> _size;
         optional<StringExpression>  _content;
         optional<NumericExpression> _priority;
         optional<bool>              _removeDuplicateLabels;
         optional<osg::Vec2s>        _pixelOffset;
+        optional<NumericExpression> _onScreenRotation;
+        optional<NumericExpression> _geographicCourse;
         optional<std::string>       _provider;
         optional<Encoding>          _encoding;
         optional<Alignment>         _alignment;
diff --git a/src/osgEarthSymbology/TextSymbol.cpp b/src/osgEarthSymbology/TextSymbol.cpp
index ebc491d..ed7291f 100644
--- a/src/osgEarthSymbology/TextSymbol.cpp
+++ b/src/osgEarthSymbology/TextSymbol.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
@@ -32,12 +32,16 @@ Symbol(rhs, copyop),
 _fill(rhs._fill),
 _halo(rhs._halo),
 _haloOffset(rhs._haloOffset),
+_haloBackdropType(rhs._haloBackdropType),
+_haloImplementation(rhs._haloImplementation),
 _font(rhs._font),
 _size(rhs._size),
 _content(rhs._content),
 _priority(rhs._priority),
 _removeDuplicateLabels(rhs._removeDuplicateLabels),
 _pixelOffset(rhs._pixelOffset),
+_onScreenRotation(rhs._onScreenRotation),
+_geographicCourse(rhs._geographicCourse),
 _provider(rhs._provider),
 _encoding(rhs._encoding),
 _alignment(rhs._alignment),
@@ -52,7 +56,9 @@ TextSymbol::TextSymbol( const Config& conf ) :
 Symbol                ( conf ),
 _fill                 ( Fill( 1, 1, 1, 1 ) ),
 _halo                 ( Stroke( 0.3, 0.3, 0.3, 1) ),
-_haloOffset           ( 0.07f ),
+_haloOffset           ( 0.0625f ),
+_haloBackdropType     ( osgText::Text::OUTLINE ),
+_haloImplementation   ( osgText::Text::DELAYED_DEPTH_WRITES ),
 _size                 ( 16.0f ),
 _removeDuplicateLabels( false ),
 _alignment            ( ALIGN_BASE_LINE ),
@@ -61,12 +67,14 @@ _provider             ( "annotation" ),
 _encoding             ( ENCODING_ASCII ),
 _declutter            ( true ),
 _occlusionCull        ( false ),
-_occlusionCullAltitude( 200000 )
+_occlusionCullAltitude( 200000 ),
+_onScreenRotation     ( 0.0 ),
+_geographicCourse     ( 0.0 )
 {
     mergeConfig(conf);
 }
 
-Config 
+Config
 TextSymbol::getConfig() const
 {
     Config conf = Symbol::getConfig();
@@ -74,6 +82,21 @@ TextSymbol::getConfig() const
     conf.addObjIfSet( "fill", _fill );
     conf.addObjIfSet( "halo", _halo );
     conf.addIfSet( "halo_offset", _haloOffset );
+    conf.addIfSet( "halo_backdrop_type", "bottom_right",  _haloBackdropType, osgText::Text::DROP_SHADOW_BOTTOM_RIGHT );
+    conf.addIfSet( "halo_backdrop_type", "center_right",  _haloBackdropType, osgText::Text::DROP_SHADOW_CENTER_RIGHT );
+    conf.addIfSet( "halo_backdrop_type", "top_right",     _haloBackdropType, osgText::Text::DROP_SHADOW_TOP_RIGHT );
+    conf.addIfSet( "halo_backdrop_type", "bottom_center", _haloBackdropType, osgText::Text::DROP_SHADOW_BOTTOM_CENTER );
+    conf.addIfSet( "halo_backdrop_type", "top_center",    _haloBackdropType, osgText::Text::DROP_SHADOW_TOP_CENTER );
+    conf.addIfSet( "halo_backdrop_type", "bottom_left",   _haloBackdropType, osgText::Text::DROP_SHADOW_BOTTOM_LEFT );
+    conf.addIfSet( "halo_backdrop_type", "center_left",   _haloBackdropType, osgText::Text::DROP_SHADOW_CENTER_LEFT );
+    conf.addIfSet( "halo_backdrop_type", "top_left",      _haloBackdropType, osgText::Text::DROP_SHADOW_TOP_LEFT );
+    conf.addIfSet( "halo_backdrop_type", "outline",       _haloBackdropType, osgText::Text::OUTLINE );
+    conf.addIfSet( "halo_backdrop_type", "none",          _haloBackdropType, osgText::Text::NONE );
+    conf.addIfSet( "halo_implementation", "polygon_offset",       _haloImplementation, osgText::Text::POLYGON_OFFSET );
+    conf.addIfSet( "halo_implementation", "no_depth_buffer",      _haloImplementation, osgText::Text::NO_DEPTH_BUFFER );
+    conf.addIfSet( "halo_implementation", "depth_range",          _haloImplementation, osgText::Text::DEPTH_RANGE );
+    conf.addIfSet( "halo_implementation", "stencil_buffer",       _haloImplementation, osgText::Text::STENCIL_BUFFER );
+    conf.addIfSet( "halo_implementation", "delayed_depth_writes", _haloImplementation, osgText::Text::DELAYED_DEPTH_WRITES );
     conf.addIfSet( "font", _font );
     conf.addObjIfSet( "size", _size );
     conf.addObjIfSet( "content", _content );
@@ -114,18 +137,36 @@ TextSymbol::getConfig() const
         conf.add( "pixel_offset_y", toString(_pixelOffset->y()) );
     }
 
+    conf.addObjIfSet( "rotation", _onScreenRotation );
+    conf.addObjIfSet( "geographic-course", _geographicCourse );
+
     conf.addIfSet( "text-occlusion-cull", _occlusionCull );
     conf.addIfSet( "text-occlusion-cull-altitude", _occlusionCullAltitude );
 
     return conf;
 }
 
-void 
+void
 TextSymbol::mergeConfig( const Config& conf )
 {
     conf.getObjIfSet( "fill", _fill );
     conf.getObjIfSet( "halo", _halo );
     conf.getIfSet( "halo_offset", _haloOffset );
+    conf.getIfSet( "halo_backdrop_type", "right_bottom",  _haloBackdropType, osgText::Text::DROP_SHADOW_BOTTOM_RIGHT );
+    conf.getIfSet( "halo_backdrop_type", "right_center",  _haloBackdropType, osgText::Text::DROP_SHADOW_CENTER_RIGHT );
+    conf.getIfSet( "halo_backdrop_type", "right_top",     _haloBackdropType, osgText::Text::DROP_SHADOW_TOP_RIGHT );
+    conf.getIfSet( "halo_backdrop_type", "center_bottom", _haloBackdropType, osgText::Text::DROP_SHADOW_BOTTOM_CENTER );
+    conf.getIfSet( "halo_backdrop_type", "center_top",    _haloBackdropType, osgText::Text::DROP_SHADOW_TOP_CENTER );
+    conf.getIfSet( "halo_backdrop_type", "left_bottom",   _haloBackdropType, osgText::Text::DROP_SHADOW_BOTTOM_LEFT );
+    conf.getIfSet( "halo_backdrop_type", "left_center",   _haloBackdropType, osgText::Text::DROP_SHADOW_CENTER_LEFT );
+    conf.getIfSet( "halo_backdrop_type", "left_top",      _haloBackdropType, osgText::Text::DROP_SHADOW_TOP_LEFT );
+    conf.getIfSet( "halo_backdrop_type", "outline",       _haloBackdropType, osgText::Text::OUTLINE );
+    conf.getIfSet( "halo_backdrop_type", "none",          _haloBackdropType, osgText::Text::NONE );
+    conf.getIfSet( "halo_implementation", "polygon_offset",       _haloImplementation, osgText::Text::POLYGON_OFFSET );
+    conf.getIfSet( "halo_implementation", "no_depth_buffer",      _haloImplementation, osgText::Text::NO_DEPTH_BUFFER );
+    conf.getIfSet( "halo_implementation", "depth_range",          _haloImplementation, osgText::Text::DEPTH_RANGE );
+    conf.getIfSet( "halo_implementation", "stencil_buffer",       _haloImplementation, osgText::Text::STENCIL_BUFFER );
+    conf.getIfSet( "halo_implementation", "delayed_depth_writes", _haloImplementation, osgText::Text::DELAYED_DEPTH_WRITES );
     conf.getIfSet( "font", _font );
     conf.getObjIfSet( "size", _size );
     conf.getObjIfSet( "content", _content );
@@ -166,6 +207,9 @@ TextSymbol::mergeConfig( const Config& conf )
     if ( conf.hasValue( "pixel_offset_y" ) )
         _pixelOffset = osg::Vec2s( _pixelOffset->x(), conf.value<short>("pixel_offset_y",0) );
 
+    conf.getObjIfSet( "rotation", _onScreenRotation );
+    conf.getObjIfSet( "geographic-course", _geographicCourse );
+
     conf.getIfSet( "text-occlusion-cull", _occlusionCull );
     conf.getIfSet( "text-occlusion-cull-altitude", _occlusionCullAltitude );
 }
@@ -174,7 +218,9 @@ TextSymbol::mergeConfig( const Config& conf )
 void
 TextSymbol::parseSLD(const Config& c, Style& style)
 {
-    if ( match(c.key(), "text-fill") ) {
+    TextSymbol defaults;
+
+    if ( match(c.key(), "text-fill") || match(c.key(), "text-color") ) {
         style.getOrCreate<TextSymbol>()->fill()->color() = Color(c.value());
     }
     else if ( match(c.key(), "text-fill-opacity") ) {
@@ -186,50 +232,84 @@ TextSymbol::parseSLD(const Config& c, Style& style)
     else if ( match(c.key(), "text-font") ) {
         style.getOrCreate<TextSymbol>()->font() = c.value();
     }
-    else if ( match(c.key(), "text-halo") ) {
+    else if ( match(c.key(), "text-halo") || match(c.key(), "text-halo-color") ) {
         style.getOrCreate<TextSymbol>()->halo()->color() = htmlColorToVec4f( c.value() );
     }
     else if ( match(c.key(), "text-halo-offset") ) {
-        style.getOrCreate<TextSymbol>()->haloOffset() = as<float>(c.value(), 0.07f);
+        style.getOrCreate<TextSymbol>()->haloOffset() = as<float>(c.value(), defaults.haloOffset().get() );
+    }
+    else if ( match(c.key(), "text-halo-backdrop-type") ) {
+        if      ( match(c.value(), "right-bottom") )
+            style.getOrCreate<TextSymbol>()->haloBackdropType() = osgText::Text::DROP_SHADOW_BOTTOM_RIGHT;
+        else if ( match(c.value(), "right-center") )
+            style.getOrCreate<TextSymbol>()->haloBackdropType() = osgText::Text::DROP_SHADOW_CENTER_RIGHT;
+        else if ( match(c.value(), "right-top") )
+            style.getOrCreate<TextSymbol>()->haloBackdropType() = osgText::Text::DROP_SHADOW_TOP_RIGHT;
+        else if ( match(c.value(), "center-bottom") )
+            style.getOrCreate<TextSymbol>()->haloBackdropType() = osgText::Text::DROP_SHADOW_BOTTOM_CENTER;
+        else if ( match(c.value(), "center-top") )
+            style.getOrCreate<TextSymbol>()->haloBackdropType() = osgText::Text::DROP_SHADOW_TOP_CENTER;
+        else if ( match(c.value(), "left-bottom") )
+            style.getOrCreate<TextSymbol>()->haloBackdropType() = osgText::Text::DROP_SHADOW_BOTTOM_LEFT;
+        else if ( match(c.value(), "left-center") )
+            style.getOrCreate<TextSymbol>()->haloBackdropType() = osgText::Text::DROP_SHADOW_CENTER_LEFT;
+        else if ( match(c.value(), "left-top") )
+            style.getOrCreate<TextSymbol>()->haloBackdropType() = osgText::Text::DROP_SHADOW_TOP_LEFT;
+        else if ( match(c.value(), "outline") )
+            style.getOrCreate<TextSymbol>()->haloBackdropType() = osgText::Text::OUTLINE;
+        else if ( match(c.value(), "none") )
+            style.getOrCreate<TextSymbol>()->haloBackdropType() = osgText::Text::NONE;
+    }
+    else if ( match(c.key(), "text-halo-implementation") ) {
+        if      ( match(c.value(), "polygon-offset") )
+            style.getOrCreate<TextSymbol>()->haloImplementation() = osgText::Text::POLYGON_OFFSET;
+        else if ( match(c.value(), "no-depth-buffer") )
+            style.getOrCreate<TextSymbol>()->haloImplementation() = osgText::Text::NO_DEPTH_BUFFER;
+        else if ( match(c.value(), "depth-range") )
+            style.getOrCreate<TextSymbol>()->haloImplementation() = osgText::Text::DEPTH_RANGE;
+        else if ( match(c.value(), "stencil-buffer") )
+            style.getOrCreate<TextSymbol>()->haloImplementation() = osgText::Text::STENCIL_BUFFER;
+        else if ( match(c.value(), "delayed-depth-writes") )
+            style.getOrCreate<TextSymbol>()->haloImplementation() = osgText::Text::DELAYED_DEPTH_WRITES;
     }
     else if ( match(c.key(), "text-remove-duplicate-labels") ) {
         if ( c.value() == "true" )
             style.getOrCreate<TextSymbol>()->removeDuplicateLabels() = true;
         else if (c.value() == "false")
             style.getOrCreate<TextSymbol>()->removeDuplicateLabels() = false;
-    } 
+    }
     else if ( match(c.key(), "text-align") ) {
-        if      ( match(c.value(), "left-top") ) 
+        if      ( match(c.value(), "left-top") )
             style.getOrCreate<TextSymbol>()->alignment() = TextSymbol::ALIGN_LEFT_TOP;
-        else if ( match(c.value(), "left-center") ) 
+        else if ( match(c.value(), "left-center") )
             style.getOrCreate<TextSymbol>()->alignment() = TextSymbol::ALIGN_LEFT_CENTER;
-        else if ( match(c.value(), "left-bottom") ) 
+        else if ( match(c.value(), "left-bottom") )
             style.getOrCreate<TextSymbol>()->alignment() = TextSymbol::ALIGN_LEFT_BOTTOM;
-        else if ( match(c.value(), "center-top")  ) 
+        else if ( match(c.value(), "center-top")  )
             style.getOrCreate<TextSymbol>()->alignment() = TextSymbol::ALIGN_CENTER_TOP;
-        else if ( match(c.value(), "center-center") ) 
+        else if ( match(c.value(), "center-center") )
             style.getOrCreate<TextSymbol>()->alignment() = TextSymbol::ALIGN_CENTER_CENTER;
-        else if ( match(c.value(), "center-bottom") ) 
+        else if ( match(c.value(), "center-bottom") )
             style.getOrCreate<TextSymbol>()->alignment() = TextSymbol::ALIGN_CENTER_BOTTOM;
-        else if ( match(c.value(), "right-top") ) 
+        else if ( match(c.value(), "right-top") )
             style.getOrCreate<TextSymbol>()->alignment() = TextSymbol::ALIGN_RIGHT_TOP;
-        else if ( match(c.value(), "right-center") ) 
+        else if ( match(c.value(), "right-center") )
             style.getOrCreate<TextSymbol>()->alignment() = TextSymbol::ALIGN_RIGHT_CENTER;
-        else if ( match(c.value(), "right-bottom") ) 
+        else if ( match(c.value(), "right-bottom") )
             style.getOrCreate<TextSymbol>()->alignment() = TextSymbol::ALIGN_RIGHT_BOTTOM;
-        else if ( match(c.value(), "left-base-line") ) 
+        else if ( match(c.value(), "left-base-line") )
             style.getOrCreate<TextSymbol>()->alignment() = TextSymbol::ALIGN_LEFT_BASE_LINE;
-        else if ( match(c.value(), "center-base-line") ) 
+        else if ( match(c.value(), "center-base-line") )
             style.getOrCreate<TextSymbol>()->alignment() = TextSymbol::ALIGN_CENTER_BASE_LINE;
-        else if ( match(c.value(), "right-base-line") ) 
+        else if ( match(c.value(), "right-base-line") )
             style.getOrCreate<TextSymbol>()->alignment() = TextSymbol::ALIGN_RIGHT_BASE_LINE;
-        else if ( match(c.value(), "left-bottom-base-line") ) 
+        else if ( match(c.value(), "left-bottom-base-line") )
             style.getOrCreate<TextSymbol>()->alignment() = TextSymbol::ALIGN_LEFT_BOTTOM_BASE_LINE;
-        else if ( match(c.value(), "center-bottom-base-line") ) 
+        else if ( match(c.value(), "center-bottom-base-line") )
             style.getOrCreate<TextSymbol>()->alignment() = TextSymbol::ALIGN_CENTER_BOTTOM_BASE_LINE;
-        else if ( match(c.value(), "right-bottom-base-line") ) 
+        else if ( match(c.value(), "right-bottom-base-line") )
             style.getOrCreate<TextSymbol>()->alignment() = TextSymbol::ALIGN_RIGHT_BOTTOM_BASE_LINE;
-        else if ( match(c.value(), "base-line" ) ) 
+        else if ( match(c.value(), "base-line" ) )
             style.getOrCreate<TextSymbol>()->alignment() = TextSymbol::ALIGN_BASE_LINE;
     }
     else if ( match(c.key(), "text-layout") ) {
@@ -240,7 +320,7 @@ TextSymbol::parseSLD(const Config& c, Style& style)
         else if ( match(c.value(), "vertical" ) )
             style.getOrCreate<TextSymbol>()->layout() = TextSymbol::LAYOUT_VERTICAL;
     }
-    else if ( match(c.key(), "text-content") ) {        
+    else if ( match(c.key(), "text-content") || match(c.key(), "text") ) {
         style.getOrCreate<TextSymbol>()->content() = StringExpression( c.value() );
     }
     else if ( match(c.key(), "text-priority") ) {
@@ -250,27 +330,39 @@ TextSymbol::parseSLD(const Config& c, Style& style)
         style.getOrCreate<TextSymbol>()->provider() = c.value();
     }
     else if ( match(c.key(), "text-encoding") ) {
-        if      (match(c.value(), "utf-8"))  
+        if      (match(c.value(), "utf-8"))
             style.getOrCreate<TextSymbol>()->encoding() = TextSymbol::ENCODING_UTF8;
-        else if (match(c.value(), "utf-16")) 
+        else if (match(c.value(), "utf-16"))
             style.getOrCreate<TextSymbol>()->encoding() = TextSymbol::ENCODING_UTF16;
-        else if (match(c.value(), "utf-32")) 
+        else if (match(c.value(), "utf-32"))
             style.getOrCreate<TextSymbol>()->encoding() = TextSymbol::ENCODING_UTF32;
-        else if (match(c.value(), "ascii"))  
+        else if (match(c.value(), "ascii"))
             style.getOrCreate<TextSymbol>()->encoding() = TextSymbol::ENCODING_ASCII;
-        else 
+        else
             style.getOrCreate<TextSymbol>()->encoding() = TextSymbol::ENCODING_ASCII;
     }
     else if ( match(c.key(), "text-declutter") ) {
-        style.getOrCreate<TextSymbol>()->declutter() = as<bool>(c.value(), true);
+        style.getOrCreate<TextSymbol>()->declutter() = as<bool>(c.value(), defaults.declutter().get() );
     }
     else if ( match(c.key(), "text-occlusion-cull") ) {
-        style.getOrCreate<TextSymbol>()->occlusionCull() = as<bool>(c.value(), false);
+        style.getOrCreate<TextSymbol>()->occlusionCull() = as<bool>(c.value(), defaults.occlusionCull().get() );
     }
     else if ( match(c.key(), "text-occlusion-cull-altitude") ) {
-        style.getOrCreate<TextSymbol>()->occlusionCullAltitude() = as<double>(c.value(), 200000.0);
+        style.getOrCreate<TextSymbol>()->occlusionCullAltitude() = as<double>(c.value(), defaults.occlusionCullAltitude().get() );
     }
     else if ( match(c.key(), "text-script") ) {
         style.getOrCreate<TextSymbol>()->script() = StringExpression(c.value());
     }
+    else if ( match(c.key(), "text-offset-x") ) {
+        style.getOrCreate<TextSymbol>()->pixelOffset()->x() = as<double>(c.value(), defaults.pixelOffset()->x() );
+    }
+    else if ( match(c.key(), "text-offset-y") ) {
+        style.getOrCreate<TextSymbol>()->pixelOffset()->y() = as<double>(c.value(), defaults.pixelOffset()->y() );
+    }
+    else if ( match(c.key(), "text-rotation") ) {
+        style.getOrCreate<TextSymbol>()->onScreenRotation() = NumericExpression( c.value() );
+    }
+    else if ( match(c.key(), "text-geographic-course") ) {
+        style.getOrCreate<TextSymbol>()->geographicCourse() = NumericExpression( c.value() );
+    }
 }
diff --git a/src/osgEarthTriton/CMakeLists.txt b/src/osgEarthTriton/CMakeLists.txt
new file mode 100644
index 0000000..97bae35
--- /dev/null
+++ b/src/osgEarthTriton/CMakeLists.txt
@@ -0,0 +1,69 @@
+IF(TRITON_FOUND)
+
+IF   (DYNAMIC_OSGEARTH)
+    ADD_DEFINITIONS(-DOSGEARTHTRITON_LIBRARY)
+ELSE (DYNAMIC_OSGEARTH)
+    ADD_DEFINITIONS(-DOSGEARTHTRITON_LIBRARY_STATIC)
+ENDIF(DYNAMIC_OSGEARTH)
+
+SET(LIB_NAME osgEarthTriton)
+
+SET(HEADER_PATH ${OSGEARTH_SOURCE_DIR}/include/${LIB_NAME})
+
+SET(LIB_PUBLIC_HEADERS
+#   header files go here
+    Common
+    Export
+    TritonNode
+    TritonOptions
+    TritonContext
+    TritonDrawable
+    TritonAPIWrapper
+    TritonCallback
+)
+
+ADD_LIBRARY(${LIB_NAME} ${OSGEARTH_USER_DEFINED_DYNAMIC_OR_STATIC}
+    ${LIB_PUBLIC_HEADERS}
+#  .cpp files go here
+    TritonNode.cpp
+    TritonContext.cpp
+    TritonDrawable.cpp
+    TritonAPIWrapper.cpp
+)
+
+INCLUDE_DIRECTORIES( 
+    ${OSG_INCLUDE_DIR}
+    ${OSGEARTH_SOURCE_DIR}
+    ${TRITON_INCLUDE_DIR}
+)
+
+LINK_EXTERNAL(
+	${LIB_NAME}
+	${TARGET_EXTERNAL_LIBRARIES}
+	${CMAKE_THREAD_LIBS_INIT} )
+
+LINK_INTERNAL(
+    ${LIB_NAME}
+    osgEarth
+    osgEarthUtil
+)
+
+LINK_WITH_VARIABLES(
+	${LIB_NAME} 
+	OSG_LIBRARY
+	OSGDB_LIBRARY
+	OSGTEXT_LIBRARY
+	OSGUTIL_LIBRARY
+	OPENTHREADS_LIBRARY
+    TRITON_LIBRARY )
+
+LINK_CORELIB_DEFAULT(
+	${LIB_NAME}
+	${CMAKE_THREAD_LIBS_INIT} )
+
+# Add this project to the NodeKits solution folder
+set_property( TARGET ${LIB_NAME} PROPERTY FOLDER "NodeKits" )
+
+INCLUDE(ModuleInstall OPTIONAL)
+
+ENDIF(TRITON_FOUND)
diff --git a/src/osgEarthTriton/Common b/src/osgEarthTriton/Common
new file mode 100644
index 0000000..5e0bf6d
--- /dev/null
+++ b/src/osgEarthTriton/Common
@@ -0,0 +1,32 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+ * Copyright 2008-2014 Pelican Mapping
+ * http://osgearth.org
+ *
+ * osgEarth is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+#ifndef OSGEARTH_TRITON_COMMON_H
+#define OSGEARTH_TRITON_COMMON_H 1
+
+#include <osgEarth/Common>
+#include "Export"
+
+// common utilities
+//namespace osgEarth { namespace Triton
+//{
+//    
+//} } // namespace osgEarth::Triton
+
+#endif // OSGEARTH_TRITON_COMMON_H
diff --git a/src/osgEarthTriton/Export b/src/osgEarthTriton/Export
new file mode 100644
index 0000000..3669b67
--- /dev/null
+++ b/src/osgEarthTriton/Export
@@ -0,0 +1,74 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+ * Copyright 2008-2014 Pelican Mapping
+ * http://osgearth.org
+ *
+ * osgEarth is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/* -*-c++-*- 
+ * Derived from osg/Export
+ */
+
+#ifndef OSGEARTH_TRITON_EXPORT_H
+#define OSGEARTH_TRITON_EXPORT_H 1
+
+// define USE_DEPRECATED_API is used to include in API which is being fazed out
+// if you can compile your apps with this turned off you are
+// well placed for compatibility with future versions.
+#define USE_DEPRECATED_API
+
+#if defined(_MSC_VER)
+    #pragma warning( disable : 4244 )
+    #pragma warning( disable : 4251 )
+    #pragma warning( disable : 4267 )
+    #pragma warning( disable : 4275 )
+    #pragma warning( disable : 4290 )
+    #pragma warning( disable : 4786 )
+    #pragma warning( disable : 4305 )
+    #pragma warning( disable : 4996 )
+#endif
+
+#if defined(_MSC_VER) || defined(__CYGWIN__) || defined(__MINGW32__) || defined( __BCPLUSPLUS__)  || defined( __MWERKS__)
+    #  if defined( OSGEARTHTRITON_LIBRARY_STATIC )
+    #    define OSGEARTHTRITON_EXPORT
+    #  elif defined( OSGEARTHTRITON_LIBRARY )
+    #    define OSGEARTHTRITON_EXPORT   __declspec(dllexport)
+    #  else
+    #    define OSGEARTHTRITON_EXPORT   __declspec(dllimport)
+    #  endif
+#else
+    #  define OSGEARTHTRITON_EXPORT
+#endif  
+
+// set up define for whether member templates are supported by VisualStudio compilers.
+#ifdef _MSC_VER
+# if (_MSC_VER >= 1300)
+#  define __STL_MEMBER_TEMPLATES
+# endif
+#endif
+
+/* Define NULL pointer value */
+
+#ifndef NULL
+    #ifdef  __cplusplus
+        #define NULL    0
+    #else
+        #define NULL    ((void *)0)
+    #endif
+#endif
+
+
+#endif // OSGEARTH_TRITON_EXPORT_H
+
diff --git a/src/osgEarthTriton/Shaders/user-functions.glsl b/src/osgEarthTriton/Shaders/user-functions.glsl
new file mode 100644
index 0000000..d18012d
--- /dev/null
+++ b/src/osgEarthTriton/Shaders/user-functions.glsl
@@ -0,0 +1,81 @@
+
+#ifdef OPENGL32
+out vec4 fragColor;
+#endif
+
+uniform float oe_ocean_alpha;
+
+// Light, view, and normal vectors are all in world space.
+// This function may be used to modify the ambient, diffuse, and specular light computed by Triton's fragment shaders.
+void user_lighting(in vec3 L
+                   , in vec3 vVertex_World_Space, in vec3 vNormal_World_Space
+                   , in vec4 vVertex_Projection_Space
+                   , inout vec3 ambient, inout vec3 diffuse, inout vec3 specular)
+{
+
+}
+
+// View in world space. The final waterColor will be alpha-blended with the fogColor by fogBlend.
+void user_fog(in vec3 vNorm, inout vec4 waterColor, inout vec4 fogColor, inout float fogBlend)
+{
+
+}
+
+// The final computed color is normally just clamped to (0,1), but you may override this behavior here.
+void user_tonemap(in vec4 preToneMapColor, inout vec4 postToneMapColor)
+{
+
+}
+
+// Override spray particle colors. Note these are drawn with an additive blending
+// mode, so darker colors just result in more transparent particles. You're given
+// the position in eye and world coordinates, and the texture lookup results for the
+// spray particle. "Transparency" represents the overall transparency of the particles.
+// "Decay" is used to fade out the particle over time. The final output color should
+// be written to additive Color.
+// The default implementation is:
+// additiveColor = texColor * lightColor * decay * transparency
+
+void user_particle_color(in vec3 vEye, in vec3 vWorld, in vec4 texColor,
+                         in vec4 lightColor, in float transparency, in float decay,
+                         inout vec4 additiveColor)
+{
+
+}
+
+// Override the shading of volumetric decals on the water. You are given the texture lookup value,
+// alpha value for the decal, and light color for the decal. The incoming default finalColor
+// is the textureColor times the lightColor, with the alpha component further multiplied by alpha.
+void user_decal_color(in vec4 textureColor, in float alpha, in vec4 lightColor, inout vec4 finalColor)
+{
+
+}
+
+//adjust the reflection color prior to it being used by triton.
+void user_reflection_adjust(in vec4 envColor, in vec4 planarColor, in float planarReflectionBlend, inout vec4 reflectedColor)
+{
+}
+
+// Shadows the fragment; 1.0 = no shadow, 0 = black.
+float user_cloud_shadow_fragment()
+{
+    return 1.0;
+}
+
+// Adjust the water diffuse to include color from breaking waves, propeller wash, and some refraction
+void user_diffuse_color( inout vec3 Cdiffuse, in vec3 CiNoLight, in vec4 reflectedColor,
+                         in float reflectivity )
+{
+}
+
+// Output to MRT
+void writeFragmentData(in vec4 finalColor, in vec4 Cdiffuse, in vec3 lightColor, in vec3 nNorm )
+{
+    // Modify the final alpha with the value of the oe_ocean_alpha uniform.
+    finalColor.a = finalColor.a * oe_ocean_alpha;
+#ifdef OPENGL32
+    fragColor = finalColor;
+#else
+    gl_FragColor = finalColor;
+#endif
+}
diff --git a/src/osgEarthTriton/TritonAPIWrapper b/src/osgEarthTriton/TritonAPIWrapper
new file mode 100644
index 0000000..94aaa12
--- /dev/null
+++ b/src/osgEarthTriton/TritonAPIWrapper
@@ -0,0 +1,102 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+ * Copyright 2016 Pelican Mapping
+ * http://osgearth.org
+ *
+ * osgEarth is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ */
+#ifndef OSGEARTH_TRITON_API_WRAPPER
+#define OSGEARTH_TRITON_API_WRAPPER 1
+
+#include "Common"
+#include <osg/Vec3>
+#include <stdint.h> // for uintptr_t
+
+
+namespace osgEarth { namespace Triton
+{
+    /** Enumerates the ocean quality settings used in Ocean::SetQuality() */
+    enum OceanQuality {
+        GOOD,
+        BETTER,
+        BEST
+    };
+
+    class OSGEARTHTRITON_EXPORT BreakingWavesParameters
+    {
+    public:
+        void SetSteepness(float);
+        float GetSteepness() const;
+
+        void SetWavelength(float);
+        float GetWavelength() const;
+
+    public:
+        BreakingWavesParameters(uintptr_t handle) : _handle(handle) { }
+        uintptr_t _handle;
+    };
+
+    class OSGEARTHTRITON_EXPORT Environment
+    {
+    public:
+        void SetDirectionalLight(const osg::Vec3& dir, const osg::Vec3& color);
+        osg::Vec3 GetLightDirection() const;
+        osg::Vec3 GetDirectionalLightColor() const;
+
+        void SetAmbientLight(const osg::Vec3& color);
+        osg::Vec3 GetAmbientLightColor() const;
+
+        void SetSunIntensity(float intensity);
+        float GetSunIntensity() const;
+
+        BreakingWavesParameters GetBreakingWavesParameters() const;
+
+        void SimulateSeaState(double bs, double winddir);
+
+    public:
+        Environment(uintptr_t handle) : _handle(handle) { }
+        uintptr_t _handle;
+    };
+
+    class OSGEARTHTRITON_EXPORT Ocean
+    {
+    public:
+        void SetChoppiness(float);
+        float GetChoppiness() const;
+
+        void EnableWireframe(bool wireframe);
+
+        void SetQuality(OceanQuality value);
+        OceanQuality GetQuality() const;
+
+        //void SetMaximumWavePeriod(double value);
+        //double GetMaximumWavePeriod() const;
+
+        void EnableSpray(bool enabled);
+        bool SprayEnabled() const;
+
+        void EnableGodRays(bool enabled);
+        bool GodRaysEnabled() const;
+
+        void SetGodRaysFade(float fadeAmount);
+        float GetGodRaysFade() const;
+
+    public:
+        Ocean(uintptr_t handle) : _handle(handle) { }
+        uintptr_t _handle;
+    };
+
+} } // namespace osgEarth::SilverLining
+
+#endif // OSGEARTH_TRITON_API_WRAPPER
diff --git a/src/osgEarthTriton/TritonAPIWrapper.cpp b/src/osgEarthTriton/TritonAPIWrapper.cpp
new file mode 100644
index 0000000..57ba88d
--- /dev/null
+++ b/src/osgEarthTriton/TritonAPIWrapper.cpp
@@ -0,0 +1,85 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+ * Copyright 2016 Pelican Mapping
+ * http://osgearth.org
+ *
+ * osgEarth is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ */
+#include "TritonAPIWrapper"
+#include <Triton.h>
+
+#define LC "[TritonAPI] "
+
+using namespace osgEarth::Triton;
+
+#define SETGET_EXPLICIT(NS, SETTER, GETTER, TYPE) \
+    void NS :: SETTER (TYPE value) { HANDLE-> SETTER (value); } \
+    TYPE NS :: GETTER () const     { return HANDLE -> GETTER (); }
+
+#define SETGET(NS, FUNC, TYPE) \
+    SETGET_EXPLICIT(NS, Set##FUNC, Get##FUNC, TYPE)
+
+#define TOVEC3(X)   ::Triton::Vector3(X.x(),X.y(),X.z())
+#define FROMVEC3(X) osg::Vec3(X.x,X.y,X.z)
+
+//................................
+#undef  HANDLE
+#define HANDLE ((::Triton::BreakingWavesParameters*)_handle)
+
+SETGET(BreakingWavesParameters, Steepness, float);
+SETGET(BreakingWavesParameters, Wavelength, float);
+
+//................................
+#undef  HANDLE
+#define HANDLE ((::Triton::Environment*)_handle)
+
+BreakingWavesParameters Environment::GetBreakingWavesParameters() const {
+    return BreakingWavesParameters((uintptr_t)&HANDLE->GetBreakingWavesParameters());
+}
+void Environment::SetDirectionalLight(const osg::Vec3& dir, const osg::Vec3& color) {
+    HANDLE->SetDirectionalLight(TOVEC3(dir), TOVEC3(color));
+}
+osg::Vec3 Environment::GetLightDirection() const {
+    const ::Triton::Vector3& v = HANDLE->GetLightDirection();
+    return FROMVEC3(v);
+}
+osg::Vec3 Environment::GetDirectionalLightColor() const {
+    const ::Triton::Vector3& v = HANDLE->GetDirectionalLightColor();
+    return FROMVEC3(v);
+}
+void Environment::SetAmbientLight(const osg::Vec3& color) {
+    HANDLE->SetAmbientLight(TOVEC3(color));
+}
+osg::Vec3 Environment::GetAmbientLightColor() const {
+    const ::Triton::Vector3& v = HANDLE->GetAmbientLightColor();
+    return FROMVEC3(v);
+}
+void Environment::SimulateSeaState(double bscale, double winddir) {
+    HANDLE->SimulateSeaState(bscale, winddir);
+}
+SETGET(Environment, SunIntensity, float);
+
+//................................
+#undef  HANDLE
+#define HANDLE ((::Triton::Ocean*)_handle)
+
+SETGET(Ocean, Choppiness, float);
+//SETGET(Ocean, MaximumWavePeriod, double);
+SETGET_EXPLICIT(Ocean, EnableSpray, SprayEnabled, bool);
+SETGET_EXPLICIT(Ocean, EnableGodRays, GodRaysEnabled, bool);
+SETGET(Ocean, GodRaysFade, float);
+
+void Ocean::EnableWireframe(bool wireframe) { HANDLE->EnableWireframe(wireframe); }
+void Ocean::SetQuality(OceanQuality value) { HANDLE->SetQuality((::Triton::OceanQuality)value); }
+OceanQuality Ocean::GetQuality() const { return (OceanQuality)HANDLE->GetQuality(); }
diff --git a/src/osgEarthTriton/TritonCallback b/src/osgEarthTriton/TritonCallback
new file mode 100644
index 0000000..533d0eb
--- /dev/null
+++ b/src/osgEarthTriton/TritonCallback
@@ -0,0 +1,40 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+ * Copyright 2016 Pelican Mapping
+ * http://osgearth.org
+ *
+ * osgEarth is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ */
+#ifndef OSGEARTH_TRITON_CALLBACK_H
+#define OSGEARTH_TRITON_CALLBACK_H 1
+
+#include "Common"
+#include "TritonAPIWrapper"
+
+namespace osgEarth { namespace Triton
+{
+    /**
+     * A callback that lets you execute code in the proper context.
+     */
+    class OSGEARTHTRITON_EXPORT Callback : public osg::Referenced
+    {
+    public:
+        virtual void onInitialize(Environment& env, Ocean& ocean) { }
+
+        virtual void onDrawOcean(Environment& env, Ocean& ocean) { }
+    };
+
+} } // namespace osgEarth::Triton
+
+#endif // OSGEARTH_TRITON_CALLBACK_H
diff --git a/src/osgEarthTriton/TritonContext b/src/osgEarthTriton/TritonContext
new file mode 100644
index 0000000..9bd3015
--- /dev/null
+++ b/src/osgEarthTriton/TritonContext
@@ -0,0 +1,99 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+ * Copyright 2016 Pelican Mapping
+ * http://osgearth.org
+ *
+ * osgEarth is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ */
+#ifndef OSGEARTH_TRITON_CONTEXT_H
+#define OSGEARTH_TRITON_CONTEXT_H
+
+#include "Common"
+#include "TritonOptions"
+#include "TritonAPIWrapper"
+#include "TritonCallback"
+#include <osg/Referenced>
+#include <osg/Light>
+#include <osgEarth/ThreadingUtils>
+#include <Triton.h>
+
+namespace osgEarth {
+    class SpatialReference;
+}
+
+namespace osgEarth { namespace Triton
+{
+    /**
+     * Contains all the Triton SDK handles.
+     */
+    class TritonContext : public osg::Referenced
+    {
+    public:
+        TritonContext(const TritonOptions& options);
+
+        /** Sets the spatial reference system of the map */
+        void setSRS(const osgEarth::SpatialReference* srs);
+
+        /** Sets the user callback */
+        void setCallback(Callback* callback);
+        Callback* getCallback() const { return _callback.get(); }
+
+    public: // accessors
+
+        bool ready() const { return _initAttempted && !_initFailed; }
+
+        /** Spatial reference of the map */
+        const osgEarth::SpatialReference* getSRS() const { return _srs.get(); }
+
+        void initialize(osg::RenderInfo& renderInfo);
+
+        void update(double simTime);
+
+        ::Triton::Environment* getEnvironment() { return _environment; }
+        Environment& getEnvironmentWrapper() const { return *_environmentWrapper; }
+
+        ::Triton::Ocean* getOcean() { return _ocean; }
+        Ocean& getOceanWrapper() const { return *_oceanWrapper; }
+
+        bool passHeightMapToTriton() const;
+
+        int getHeightMapSize() const;
+
+    protected:
+
+        virtual ~TritonContext();
+
+
+    private:
+        TritonOptions    _options;
+
+        bool             _initAttempted;
+        bool             _initFailed;
+        Threading::Mutex _initMutex;
+
+        osg::ref_ptr<const osgEarth::SpatialReference> _srs;
+
+        ::Triton::ResourceLoader* _resourceLoader;
+        ::Triton::Environment*    _environment;
+        ::Triton::Ocean*          _ocean;
+
+        Environment* _environmentWrapper;
+        Ocean*       _oceanWrapper;
+
+        osg::ref_ptr<Callback> _callback;
+    };
+
+} } // namespace osgEarth::Triton
+
+#endif // OSGEARTH_TRITON_CONTEXT_H
\ No newline at end of file
diff --git a/src/osgEarthTriton/TritonContext.cpp b/src/osgEarthTriton/TritonContext.cpp
new file mode 100644
index 0000000..095186f
--- /dev/null
+++ b/src/osgEarthTriton/TritonContext.cpp
@@ -0,0 +1,185 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+ * Copyright 2016 Pelican Mapping
+ * http://osgearth.org
+ *
+ * osgEarth is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ */
+#include <Triton.h>
+#include "TritonContext"
+#include <osg/GLExtensions>
+#include <osg/Math>
+#include <osgDB/FileNameUtils>
+#include <osgEarth/SpatialReference>
+#include <cstdlib>
+
+#define LC "[TritonContext] "
+
+using namespace osgEarth::Triton;
+
+
+TritonContext::TritonContext(const TritonOptions& options) :
+_options              ( options ),
+_initAttempted        ( false ),
+_initFailed           ( false ),
+_resourceLoader       ( 0L ),
+_environment          ( 0L ),
+_environmentWrapper   ( 0L ),
+_ocean                ( 0L ),
+_oceanWrapper         ( 0L )
+{    
+    //nop
+}
+
+TritonContext::~TritonContext()
+{
+    if ( _oceanWrapper )
+        delete _oceanWrapper;
+
+    if ( _environmentWrapper )
+        delete _environmentWrapper;
+
+    if ( _ocean )
+        delete _ocean;
+
+    if ( _environment )
+        delete _environment;
+
+    if ( _resourceLoader )
+        delete _resourceLoader;
+}
+
+void
+TritonContext::setSRS(const osgEarth::SpatialReference* srs)
+{
+    _srs = srs;
+}
+
+void
+TritonContext::setCallback(Callback* callback)
+{
+    _callback = callback;
+}
+
+bool
+TritonContext::passHeightMapToTriton() const
+{
+    return _options.useHeightMap() == true;
+}
+
+int
+TritonContext::getHeightMapSize() const
+{
+    return osg::clampBetween(_options.heightMapSize().get(), 64, 2048);
+}
+
+void
+TritonContext::initialize(osg::RenderInfo& renderInfo)
+{
+    if ( !_initAttempted && !_initFailed )
+    {
+        // lock/double-check:
+        Threading::ScopedMutexLock excl(_initMutex);
+        if ( !_initAttempted && !_initFailed )
+        {
+            _initAttempted = true;
+
+            std::string resourcePath = _options.resourcePath().get();
+            if (resourcePath.empty() && ::getenv("TRITON_PATH"))
+            {
+                resourcePath = osgDB::concatPaths(::getenv("TRITON_PATH"), "Resources");
+            }
+
+            _resourceLoader = new ::Triton::ResourceLoader(resourcePath.c_str());
+
+            _environment = new ::Triton::Environment();
+
+            _environmentWrapper = new Environment((uintptr_t)_environment);
+
+            _environment->SetLicenseCode(
+                _options.user()->c_str(),
+                _options.licenseCode()->c_str() );
+
+            // "WGS84" is used to represent any ellipsoid.
+            ::Triton::CoordinateSystem cs =
+                _srs->isGeographic() ? ::Triton::WGS84_ZUP :
+                ::Triton::FLAT_ZUP;
+
+            // Set the ellipsoid to match the one in our map's SRS.
+            if ( _srs->isGeographic() )
+            {
+                const osg::EllipsoidModel* ellipsoid = _srs->getEllipsoid();
+                
+                std::string eqRadius = Stringify() << ellipsoid->getRadiusEquator();
+                std::string poRadius = Stringify() << ellipsoid->getRadiusPolar();
+
+                _environment->SetConfigOption( "equatorial-earth-radius-meters", eqRadius.c_str() );
+                _environment->SetConfigOption( "polar-earth-radius-meters",      poRadius.c_str() );
+            }
+
+            float openGLVersion = osg::getGLVersionNumber();
+            enum ::Triton::Renderer tritonOpenGlVersion = ::Triton::OPENGL_2_0;
+            if( openGLVersion == 4.1 )
+                tritonOpenGlVersion = ::Triton::OPENGL_4_1;
+            else if( openGLVersion == 4.0 )
+                tritonOpenGlVersion = ::Triton::OPENGL_4_0;
+            else if( openGLVersion == 3.2 )
+                tritonOpenGlVersion = ::Triton::OPENGL_3_2;
+
+            ::Triton::EnvironmentError err = _environment->Initialize(
+                cs,
+                tritonOpenGlVersion,
+                _resourceLoader );
+
+            if ( err == ::Triton::SUCCEEDED )
+            {
+                ::Triton::WindFetch wf;
+                wf.SetWind( 10.0, 0.0 );
+                _environment->AddWindFetch( wf );
+
+                _ocean = ::Triton::Ocean::Create(
+                    _environment, 
+                    ::Triton::JONSWAP );
+            }
+
+            if ( _ocean )
+            {
+                _oceanWrapper = new Ocean((uintptr_t)_ocean);
+
+                // fire init callback if available
+                if (_callback.valid())
+                {
+                    _callback->onInitialize(getEnvironmentWrapper(), getOceanWrapper());
+                }
+
+                OE_INFO << LC << "Triton initialized OK!" << std::endl;                
+            }
+            else
+            {
+                _initFailed = true;
+                OE_WARN << LC << "Triton initialization failed- err=" << err << std::endl;
+            }
+        }
+    }
+}
+
+void
+TritonContext::update(double simTime)
+{
+    if ( _ocean )
+    {
+        // fmod requires b/c CUDA is limited to single-precision values
+        _ocean->UpdateSimulation( fmod(simTime, 86400.0) );
+    }
+}
diff --git a/src/osgEarthTriton/TritonDrawable b/src/osgEarthTriton/TritonDrawable
new file mode 100644
index 0000000..79b8ac4
--- /dev/null
+++ b/src/osgEarthTriton/TritonDrawable
@@ -0,0 +1,95 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+ * Copyright 2016 Pelican Mapping
+ * http://osgearth.org
+ *
+ * osgEarth is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ */
+#ifndef OSGEARTH_TRITON_DRAWABLE_H
+#define OSGEARTH_TRITON_DRAWABLE_H
+
+#include "Common"
+#include <osg/Drawable>
+#include <osg/RenderInfo>
+#include <osg/TextureCubeMap>
+#include <osg/Version>
+#include <osg/Texture2D>
+#include <osg/buffered_value>
+
+#include <osgEarth/MapNode>
+#include <osgEarth/Terrain>
+#include <osgEarth/NativeProgramAdapter>
+
+const unsigned int TRITON_OCEAN_MASK = 0x4; // 0100
+
+namespace osgEarth { namespace Triton
+{
+    class TritonContext;
+
+    /**
+     * Custom drawable for rendering the Triton ocean effects
+     */
+    class OSGEARTHTRITON_EXPORT TritonDrawable : public osg::Drawable
+    {
+    public:
+        TritonDrawable(osgEarth::MapNode* mapNode=NULL, TritonContext* TRITON =0L);
+        META_Object(Triton, TritonDrawable);
+
+    public: // osg::Drawable
+
+        // custom draw (called with an active GC)
+        void drawImplementation(osg::RenderInfo& ri) const;
+
+        void setupHeightMap(osg::State& state);
+
+        void updateHeightMap(osg::RenderInfo& renderInfo) const;
+
+        void dirtyAllContexts();
+
+#if OSG_VERSION_GREATER_THAN(3,3,1)
+        osg::BoundingBox computeBoundingBox() const
+#else
+        osg::BoundingBox computeBound() const
+#endif
+            { return osg::BoundingBox(); }
+
+        void SetPlanarReflectionMap(osg::Texture2D* map) {_planarReflectionMap = map;};
+        void SetPlanarReflectionProjection(osg::RefMatrix * proj) {_planarReflectionProjection = proj;};
+
+    protected:
+        virtual ~TritonDrawable();
+
+        osg::observer_ptr<TritonContext>  _TRITON;
+        osg::observer_ptr<osgEarth::MapNode> _mapNode;
+        osg::ref_ptr<osg::TextureCubeMap> _cubeMap;
+        osg::BoundingBox                  _bbox;
+        osg::ref_ptr<osg::Texture2D> _heightMap;
+        osg::ref_ptr<osg::Camera> _heightCamera;
+        osg::observer_ptr<osgEarth::TerrainCallback> _terrainChangedCallback;
+
+        osg::ref_ptr< osg::Texture2D >       _planarReflectionMap;
+        osg::ref_ptr< osg::RefMatrix >       _planarReflectionProjection;
+
+        mutable osg::buffered_object<int>         _contextDirty;
+        mutable osg::Matrix                       _viewMatrix;
+        mutable osg::Matrix                       _projMatrix;
+
+        mutable osg::buffered_object<osgEarth::NativeProgramAdapterCollection> _adapters;
+
+        TritonDrawable(const TritonDrawable& copy, const osg::CopyOp& op=osg::CopyOp::SHALLOW_COPY) { }
+    };
+
+} } // namespace osgEarth::Triton
+
+#endif // OSGEARTH_TRITON_DRAWABLE_H
diff --git a/src/osgEarthTriton/TritonDrawable.cpp b/src/osgEarthTriton/TritonDrawable.cpp
new file mode 100644
index 0000000..4a47c29
--- /dev/null
+++ b/src/osgEarthTriton/TritonDrawable.cpp
@@ -0,0 +1,718 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+ * Copyright 2016 Pelican Mapping
+ * http://osgearth.org
+ *
+ * osgEarth is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ */
+#include <Triton.h>
+
+#include "TritonDrawable"
+#include "TritonContext"
+#include <osg/MatrixTransform>
+#include <osg/FrameBufferObject>
+
+#include <osgEarth/SpatialReference>
+#include <osgEarth/VirtualProgram>
+#include <osgEarth/MapNode>
+#include <osgEarth/TerrainEngineNode>
+
+#undef  LC
+#define LC "[TritonDrawable] "
+
+//#define DEBUG_HEIGHTMAP
+
+using namespace osgEarth::Triton;
+
+namespace
+{
+
+/** Default size of _contextDirty */
+static const size_t NUM_CONTEXTS = 64;
+
+#ifdef DEBUG_HEIGHTMAP
+    osg::Node*
+    makeFrustumFromCamera( osg::Camera* camera )
+    {
+        osg::Matrixd proj;
+        osg::Matrixd mv;
+        if (camera)
+        {
+            proj = camera->getProjectionMatrix();
+            mv = camera->getViewMatrix();
+        }
+        else
+        {
+            proj.makePerspective( 30., 1., 1., 10. );
+            // leave mv as identity
+        }
+
+        double near=0.0, far=0.0;
+        double left=0.0, right=0.0, bottom=0.0, top=0.0;
+        double fovy=0.0, aspectRatio=0.0;
+        double nLeft=0.0, nRight=0.0, nBottom=0.0, nTop=0.0;
+        double fLeft=0.0, fRight=0.0, fBottom=0.0, fTop=0.0;
+
+        osg::Geode* geode = new osg::Geode;
+
+        if( proj.getPerspective(fovy, aspectRatio, near, far) )
+        {
+            near = proj(3,2) / (proj(2,2)-1.0);
+            far = proj(3,2) / (1.0+proj(2,2));
+
+            nLeft = near * (proj(2,0)-1.0) / proj(0,0);
+            nRight = near * (1.0+proj(2,0)) / proj(0,0);
+            nTop = near * (1.0+proj(2,1)) / proj(1,1);
+            nBottom = near * (proj(2,1)-1.0) / proj(1,1);
+
+            fLeft = far * (proj(2,0)-1.0) / proj(0,0);
+            fRight = far * (1.0+proj(2,0)) / proj(0,0);
+            fTop = far * (1.0+proj(2,1)) / proj(1,1);
+            fBottom = far * (proj(2,1)-1.0) / proj(1,1);
+
+            osg::Vec3Array* v = new osg::Vec3Array;
+            v->resize( 9 );
+            (*v)[0].set( 0., 0., 0. );
+
+            (*v)[1].set( nLeft, nBottom, -near );
+            (*v)[2].set( nRight, nBottom, -near );
+            (*v)[3].set( nRight, nTop, -near );
+            (*v)[4].set( nLeft, nTop, -near );
+            (*v)[5].set( fLeft, fBottom, -far );
+            (*v)[6].set( fRight, fBottom, -far );
+            (*v)[7].set( fRight, fTop, -far );
+            (*v)[8].set( fLeft, fTop, -far );
+
+            osg::Geometry* geom = new osg::Geometry;
+            geom->setVertexArray( v );
+
+            GLushort idxLines[8] = {
+                0, 5, 0, 6, 0, 7, 0, 8 };
+            GLushort idxLoops0[4] = {
+                1, 2, 3, 4 };
+            GLushort idxLoops1[4] = {
+                5, 6, 7, 8 };
+            geom->addPrimitiveSet( new osg::DrawElementsUShort( osg::PrimitiveSet::LINES, 8, idxLines ) );
+            geom->addPrimitiveSet( new osg::DrawElementsUShort( osg::PrimitiveSet::LINE_LOOP, 4, idxLoops0 ) );
+            geom->addPrimitiveSet( new osg::DrawElementsUShort( osg::PrimitiveSet::LINE_LOOP, 4, idxLoops1 ) );
+
+            geode->addDrawable( geom );
+        }
+        else if(proj.getOrtho( left, right, bottom, top, near, far) )
+        {
+            nLeft = left;//near * (proj(2,0)-1.0) / proj(0,0);
+            nRight = right;//near * (1.0+proj(2,0)) / proj(0,0);
+            nTop = top;//near * (1.0+proj(2,1)) / proj(1,1);
+            nBottom = bottom;//near * (proj(2,1)-1.0) / proj(1,1);
+
+            fLeft = left;//far * (proj(2,0)-1.0) / proj(0,0);
+            fRight = right;//far * (1.0+proj(2,0)) / proj(0,0);
+            fTop = top;//far * (1.0+proj(2,1)) / proj(1,1);
+            fBottom = bottom;//far * (proj(2,1)-1.0) / proj(1,1);
+
+            osg::Vec3Array* v = new osg::Vec3Array;
+            v->resize( 9 );
+            (*v)[0].set( 0., 0., 0. );
+
+            (*v)[1].set( nLeft, nBottom, -near );
+            (*v)[2].set( nRight, nBottom, -near );
+            (*v)[3].set( nRight, nTop, -near );
+            (*v)[4].set( nLeft, nTop, -near );
+            (*v)[5].set( fLeft, fBottom, -far );
+            (*v)[6].set( fRight, fBottom, -far );
+            (*v)[7].set( fRight, fTop, -far );
+            (*v)[8].set( fLeft, fTop, -far );
+
+            osg::Geometry* geom = new osg::Geometry;
+            geom->setVertexArray( v );
+
+            GLushort idxLines[8] = {
+                1, 5, 2, 6, 3, 7, 4, 8 };
+            GLushort idxLoops0[4] = {
+                1, 2, 3, 4 };
+            GLushort idxLoops1[4] = {
+                5, 6, 7, 8 };
+            geom->addPrimitiveSet( new osg::DrawElementsUShort( osg::PrimitiveSet::LINES, 8, idxLines ) );
+            geom->addPrimitiveSet( new osg::DrawElementsUShort( osg::PrimitiveSet::LINE_LOOP, 4, idxLoops0 ) );
+            geom->addPrimitiveSet( new osg::DrawElementsUShort( osg::PrimitiveSet::LINE_LOOP, 4, idxLoops1 ) );
+
+            geode->addDrawable( geom );
+        }
+
+        geode->getOrCreateStateSet()->setMode( GL_LIGHTING, osg::StateAttribute::OFF );
+
+
+
+        osg::MatrixTransform* mt = new osg::MatrixTransform;
+        osg::Matrixd mvi = osg::Matrixd::inverse( mv );
+        mt->setMatrix( mvi );
+        mt->addChild( geode );
+
+        return mt;
+    }
+
+    osg::Camera *
+    CreateTextureQuadOverlay( osg::Texture * texture, float x, float y, float w, float h )
+    {
+        osg::Camera * camera = new osg::Camera;
+
+        // set up the background color and clear mask.
+        camera->setClearMask( GL_DEPTH_BUFFER_BIT );
+
+        // set viewport
+        camera->setProjectionMatrixAsOrtho2D( 0, 1, 0, 1 );
+        camera->setViewMatrix( osg::Matrix::identity() );
+        camera->setReferenceFrame( osg::Transform::ABSOLUTE_RF );
+
+        osg::Geode * geode = new osg::Geode();
+        camera->addChild( geode );
+    /*
+        osg::Geometry * background = osg::createTexturedQuadGeometry( osg::Vec3( x,y,0 ),osg::Vec3( w,0,0 ), osg::Vec3( 0,h,0 ) );
+        geode->addDrawable( background );
+
+        osg::Vec4Array* colors = new osg::Vec4Array;
+        colors->push_back( osg::Vec4( 1,1,0,0.3 ) );
+        background->setColorArray( colors );
+        background->setColorBinding( osg::Geometry::BIND_OVERALL );
+        background->getOrCreateStateSet()->setMode( GL_BLEND, osg::StateAttribute::ON );
+        background->getOrCreateStateSet()->setMode( GL_DEPTH_TEST, osg::StateAttribute::OFF );
+    */
+        osg::Geometry * quad = osg::createTexturedQuadGeometry( osg::Vec3( x,y,0 ),osg::Vec3( w,0,0 ), osg::Vec3( 0,h,0 ) );
+        geode->addDrawable( quad );
+        quad->getOrCreateStateSet()->setTextureAttributeAndModes( 0, texture, osg::StateAttribute::ON );
+        quad->getOrCreateStateSet()->setMode( GL_BLEND, osg::StateAttribute::ON );
+        quad->getOrCreateStateSet()->setMode( GL_LIGHTING, osg::StateAttribute::OFF );
+        quad->getOrCreateStateSet()->setMode( GL_DEPTH_TEST, osg::StateAttribute::OFF );
+
+        camera->getOrCreateStateSet()->setAttribute(new osg::Program());
+
+
+        // set the camera to render after the main camera.
+        camera->setRenderOrder(osg::Camera::POST_RENDER);
+
+        return camera;
+    }
+#endif /* DEBUG_HEIGHTMAP */
+
+
+    struct PassHeightMapToTritonCallback : public osg::Camera::DrawCallback
+    {
+        PassHeightMapToTritonCallback(TritonContext* triton) : _TRITON(triton), _enable(false), _id(0) { _ptrEnable = const_cast<bool*> (&_enable); };
+        virtual void operator()( osg::RenderInfo& renderInfo ) const
+        {
+            if( _enable )
+            {
+                *_ptrEnable = false; // cannot directly change _enable because of const
+
+                //osg::notify( osg::ALWAYS ) << "passing heightmap to Triton" << std::endl;
+                if(_TRITON->ready())
+                    _TRITON->getEnvironment()->SetHeightMap((::Triton::TextureHandle)_id,_heightMapMatrix);
+            }
+        }
+
+        unsigned int _frameNumber;
+        bool _enable;
+        bool* _ptrEnable;
+        int _id;
+        ::Triton::Matrix4 _heightMapMatrix;
+
+    private:
+        osg::observer_ptr<TritonContext>  _TRITON;
+    };
+
+
+    /**
+     * Responds to tile-added events by telling the Triton drawable that it needs to update
+     * its height map.
+     */
+    class OceanTerrainChangedCallback : public osgEarth::TerrainCallback
+    {
+    public:
+        OceanTerrainChangedCallback(TritonDrawable* drawable)
+            : _drawable(drawable) { }
+
+    public: // osgEarth::TerrainCallback
+
+        // Called when the terrain engine loads a new tile (or new tile heightfield data).
+        // When this happens we need to update the Triton height map.
+        void onTileAdded(const osgEarth::TileKey& tileKey, osg::Node* terrain, osgEarth::TerrainCallbackContext& context)
+        {
+            osg::ref_ptr<TritonDrawable> drawable;
+            if ( _drawable.lock(drawable) )
+                drawable->dirtyAllContexts();
+        }
+
+    private:
+        osg::observer_ptr<TritonDrawable> _drawable;
+    };
+
+
+    const char* vertexShader =
+        "#version " GLSL_VERSION_STR "\n"
+        GLSL_DEFAULT_PRECISION_FLOAT "\n"
+
+        "// terrain SDK:\n"
+        "float oe_terrain_getElevation(); \n"
+
+        "varying float oe_triton_elev;\n"
+
+        "void setupContour(inout vec4 VertexModel) \n"
+        "{ \n"
+        "    oe_triton_elev = oe_terrain_getElevation(); \n"
+        "} \n";
+
+    // The fragment shader simply takes the texture index that we generated
+    // in the vertex shader and does a texture lookup. In this case we're
+    // just wholesale replacing the color, so if the map had any existing
+    // imagery, this will overwrite it.
+
+    const char* fragmentShader =
+        "#version " GLSL_VERSION_STR "\n"
+        GLSL_DEFAULT_PRECISION_FLOAT "\n"
+
+        "varying float oe_triton_elev;\n"
+
+        "void colorContour( inout vec4 color ) \n"
+        "{ \n"
+#ifdef DEBUG_HEIGHTMAP
+          // Map to black = -500m, white = +500m
+          "   float nHeight = clamp(oe_triton_elev / 1000.0 + 0.5, 0.0, 1.0);\n"
+#else
+          "   float nHeight = oe_triton_elev;\n"
+#endif
+        "    gl_FragColor = vec4( nHeight, 0.0, 0.0, 1.0 ); \n"
+        "} \n";
+}
+
+
+TritonDrawable::TritonDrawable(osgEarth::MapNode* mapNode, TritonContext* TRITON) :
+_TRITON(TRITON),
+_mapNode(mapNode)
+{
+    // call this to ensure draw() gets called every frame.
+    setSupportsDisplayList( false );
+    setUseVertexBufferObjects( false );
+
+    // dynamic variance prevents update/cull overlap when drawing this
+    setDataVariance( osg::Object::DYNAMIC );
+
+    _contextDirty.resize(NUM_CONTEXTS);
+    dirtyAllContexts();
+}
+
+TritonDrawable::~TritonDrawable()
+{
+    osg::ref_ptr<MapNode> mapNode;
+    osg::ref_ptr<osgEarth::TerrainCallback> callback;
+    if ( _mapNode.lock(mapNode) && _terrainChangedCallback.lock(callback) && mapNode->getTerrain() )
+    {
+        _mapNode->getTerrain()->removeTerrainCallback( callback );
+    }
+}
+
+void
+TritonDrawable::dirtyAllContexts()
+{
+    _contextDirty.setAllElementsTo(1);
+}
+
+void
+TritonDrawable::updateHeightMap(osg::RenderInfo& renderInfo) const
+{
+    if ( !_TRITON->ready() )
+        return;
+
+    osg::ref_ptr<MapNode> mapNode;
+    if (!_mapNode.lock(mapNode))
+        return;
+
+    const osg::Matrix& viewMatrix = renderInfo.getCurrentCamera()->getViewMatrix();
+    const osg::Matrix& projectionMatrix = renderInfo.getCurrentCamera()->getProjectionMatrix();
+
+    osg::Vec3d eye, center, up;
+    viewMatrix.getLookAt(eye, center, up);
+    double fovyDEG=0.0, aspectRatio=0.0, zNear=0.0, zFar=0.0;
+    projectionMatrix.getPerspective(fovyDEG, aspectRatio,zNear,zFar);
+
+    // aspect_ratio = tan( HFOV/2 ) / tan( VFOV/2 )
+    // tan( HFOV/2 ) = tan( VFOV/2 ) * aspect_ratio
+    // HFOV/2 = atan( tan( VFOV/2 ) * aspect_ratio )
+    // HFOV = 2.0 * atan( tan( VFOV/2 ) * aspect_ratio )
+    double fovxDEG = osg::RadiansToDegrees( 2.0 * atan( tan(osg::DegreesToRadians(fovyDEG))/2.0 * aspectRatio ));
+
+    double eyeLat=0.0, eyeLon=0.0, eyeHeight=0.0;
+    mapNode->getMap()->getSRS()->getEllipsoid()->convertXYZToLatLongHeight(eye.x(), eye.y(), eye.z(), eyeLat, eyeLon, eyeHeight);
+    double clampedEyeX=0.0, clampedEyeY=0.0,clampedEyeZ=0.0;
+    mapNode->getMap()->getSRS()->getEllipsoid()->convertLatLongHeightToXYZ(eyeLat, eyeLon, 0.0, clampedEyeX, clampedEyeY, clampedEyeZ);
+    osg::Vec3 mslEye(clampedEyeX,clampedEyeY,clampedEyeZ);
+    double lookAtLat=0.0, lookAtLon=0.0, lookAtHeight=0.0;
+    mapNode->getMap()->getSRS()->getEllipsoid()->convertXYZToLatLongHeight(center.x(), center.y(), center.z(), lookAtLat, lookAtLon, lookAtHeight);
+
+    // Calculate the distance to the horizon from the eyepoint
+    double eyeLen = eye.length();
+    double radE = mslEye.length();
+    double hmax = radE + 8848.0;
+    double hmin = radE - 12262.0;
+    double hasl = osg::maximum(0.1, eyeLen - radE);
+    double radius = eyeLen - hasl;
+    double horizonDistance = osg::minimum(radE, sqrt( 2.0*radius*hasl + hasl*hasl ));
+
+    osg::Vec3d heightCamEye(eye);
+
+    double near = osg::maximum(1.0, heightCamEye.length() - hmax);
+    double far = osg::maximum(10.0, heightCamEye.length() - hmin + radE);
+    //osg::notify( osg::ALWAYS ) << "near = " << near << "; far = " << far << std::endl;
+
+    //horizonDistance *= 0.25;
+
+    _heightCamera->setProjectionMatrix(osg::Matrix::ortho(-horizonDistance,horizonDistance,-horizonDistance,horizonDistance,near,far) );
+    _heightCamera->setViewMatrixAsLookAt( heightCamEye, osg::Vec3d(0.0,0.0,0.0), osg::Vec3d(0.0,0.0,1.0));
+
+    const osg::Matrixd bias(0.5, 0.0, 0.0, 0.0,
+        0.0, 0.5, 0.0, 0.0,
+        0.0, 0.0, 0.5, 0.0,
+        0.5, 0.5, 0.5, 1.0);
+
+    osg::Matrix hMM = _heightCamera->getViewMatrix() * _heightCamera->getProjectionMatrix() * bias;
+    ::Triton::Matrix4 heightMapMatrix(hMM(0,0),hMM(0,1),hMM(0,2),hMM(0,3),
+        hMM(1,0),hMM(1,1),hMM(1,2),hMM(1,3),
+        hMM(2,0),hMM(2,1),hMM(2,2),hMM(2,3),
+        hMM(3,0),hMM(3,1),hMM(3,2),hMM(3,3));
+
+    osg::Texture::TextureObject* texObj = _heightMap->getTextureObject(renderInfo.getContextID());
+
+    if(texObj)
+    {
+        PassHeightMapToTritonCallback* cb = dynamic_cast<PassHeightMapToTritonCallback*>(_heightCamera->getFinalDrawCallback());
+        if( cb )
+        {
+            cb->_enable = true;
+            cb->_id = texObj->id();
+            cb->_heightMapMatrix = heightMapMatrix;
+        }
+    }
+    else
+    {
+        // may happen on the first frame; ignore
+        //OE_WARN << LC << "Texture object is NULL (Internal error)" << std::endl;
+    }
+
+#ifdef DEBUG_HEIGHTMAP
+    mapNode->getParent(0)->removeChild(0, 1);
+    mapNode->getParent(0)->insertChild(0, makeFrustumFromCamera(_heightCam));
+#endif /* DEBUG_HEIGHTMAP */
+}
+
+void
+TritonDrawable::drawImplementation(osg::RenderInfo& renderInfo) const
+{
+    osg::State* state = renderInfo.getState();
+
+    state->disableAllVertexArrays();
+
+    _TRITON->initialize( renderInfo );
+    if ( !_TRITON->ready() )
+        return;
+
+    if ( _TRITON->passHeightMapToTriton() && !_terrainChangedCallback.valid() )
+    {
+        const_cast<TritonDrawable*>(this)->setupHeightMap(*state);
+    }
+
+    ::Triton::Environment* environment = _TRITON->getEnvironment();
+
+    osgEarth::NativeProgramAdapterCollection& adapters = _adapters[ state->getContextID() ];
+    if ( adapters.empty() )
+    {
+        const char* prefix = "oe_";
+        adapters.push_back( new osgEarth::NativeProgramAdapter(state, (GLint)_TRITON->getOcean()->GetShaderObject(::Triton::GOD_RAYS), prefix));
+        adapters.push_back( new osgEarth::NativeProgramAdapter(state, (GLint)_TRITON->getOcean()->GetShaderObject(::Triton::SPRAY_PARTICLES), prefix));
+        adapters.push_back( new osgEarth::NativeProgramAdapter(state, (GLint)_TRITON->getOcean()->GetShaderObject(::Triton::WAKE_SPRAY_PARTICLES), prefix));
+        adapters.push_back( new osgEarth::NativeProgramAdapter(state, (GLint)_TRITON->getOcean()->GetShaderObject(::Triton::WATER_DECALS), prefix));
+        adapters.push_back( new osgEarth::NativeProgramAdapter(state, (GLint)_TRITON->getOcean()->GetShaderObject(::Triton::WATER_SURFACE_PATCH), prefix));
+        adapters.push_back( new osgEarth::NativeProgramAdapter(state, (GLint)_TRITON->getOcean()->GetShaderObject(::Triton::WATER_SURFACE), prefix));
+    }
+    adapters.apply( state );
+
+    // Pass the final view and projection matrices into Triton.
+    if ( environment )
+    {
+        environment->SetCameraMatrix( state->getModelViewMatrix().ptr() );
+        environment->SetProjectionMatrix( state->getProjectionMatrix().ptr() );
+    }
+
+    if ( _TRITON->passHeightMapToTriton() )
+    {
+        unsigned cid = renderInfo.getContextID();
+        const bool validCid = (cid < _contextDirty.size());
+
+        bool dirty =
+            ( validCid && _contextDirty[cid] ) ||
+            ( renderInfo.getView()->getCamera()->getViewMatrix()       != _viewMatrix ) ||
+            ( renderInfo.getView()->getCamera()->getProjectionMatrix() != _projMatrix );
+
+        if ( dirty )
+        {
+            updateHeightMap( renderInfo );
+            if ( validCid )
+                _contextDirty[renderInfo.getContextID()] = 0;
+            _viewMatrix = renderInfo.getView()->getCamera()->getViewMatrix();
+            _projMatrix = renderInfo.getView()->getCamera()->getProjectionMatrix();
+        }
+    }
+
+    state->dirtyAllVertexArrays();
+
+    // Now light and draw the ocean:
+    if ( environment )
+    {
+        // User pre-draw callback:
+        if (_TRITON->getCallback())
+        {
+            _TRITON->getCallback()->onDrawOcean(
+                _TRITON->getEnvironmentWrapper(),
+                _TRITON->getOceanWrapper());
+        }
+
+        // The sun position is roughly where it is in our skybox texture:
+
+        // Since this is a simple example we will just assume that Sun is the light from View light source
+        // TODO: fix this...
+        osg::Light* light = renderInfo.getView() ? renderInfo.getView()->getLight() : NULL;
+
+        // This is the light attached to View so there are no transformations above..
+        // But in general case you would need to accumulate all transforms above the light into this matrix
+        osg::Matrix lightLocalToWorldMatrix = osg::Matrix::identity();
+
+        // If you don't know where the sun lightsource is attached and don't know its local to world matrix you may use
+        // following elaborate scheme to grab the light source while drawing Triton ocean:
+        // - Install cull callback to catch CullVisitor and record pointer to its associated RenderStage
+        //   I was hoping RenderStage can be found from renderInfo in drawImplementation but I didn't figure how ...
+        // - When TritonDrawable::drawImplementation is called all lights will be already applied to OpenGL
+        //   then just find proper infinite directional light by scanning renderStage->PositionalStateContainer.
+        // - Note that we canot scan for the lights inside cull because they may not be traversed before Triton drawable
+        // - When you found interesting ligt source that can work as Sun, read its modelview matrix and lighting params
+        //   Multiply light position by ( modelview * inverse camera view ) and pass this to Triton with lighting colors
+
+        if ( light && light->getPosition().w() == 0 )
+        {
+            osg::Vec4 ambient = light->getAmbient();
+            osg::Vec4 diffuse = light->getDiffuse();
+            osg::Vec4 position = light->getPosition();
+
+            // Compute light position/direction in the world
+            position = position * lightLocalToWorldMatrix;
+
+            // Diffuse direction and color
+            environment->SetDirectionalLight(
+                ::Triton::Vector3( position[0], position[1], position[2] ),
+                ::Triton::Vector3( diffuse[0],  diffuse[1],  diffuse[2] ) );
+
+            // Sun-based ambient value:
+            osg::Vec3d up = osg::Vec3d(0,0,0) * renderInfo.getCurrentCamera()->getInverseViewMatrix();
+            up.normalize();
+            osg::Vec3d pos3 = osg::Vec3d(position.x(), position.y(), position.z());
+            pos3.normalize();
+            float dot = osg::clampAbove(up*pos3, 0.0); dot*=dot;
+            float sunAmbient = (float)osg::clampBetween( dot, 0.0f, 0.88f );
+            float fa = std::max(sunAmbient, ambient[0]);
+
+            // Ambient color based on the zenith color in the cube map
+            environment->SetAmbientLight( ::Triton::Vector3(fa, fa, fa) );
+            //::Triton::Vector3( ambient[0], ambient[1], ambient[2] ) );
+        }
+
+        else
+        {
+            environment->SetDirectionalLight( ::Triton::Vector3(0,0,1), ::Triton::Vector3(1,1,1) );
+            environment->SetAmbientLight( ::Triton::Vector3(0.88f, 0.88f, 0.88f) );
+        }
+
+        // Build transform from our cube map orientation space to native Triton orientation
+        // See worldToCubeMap function used in SkyBox to orient sky texture so that sky is up and earth is down
+        osg::Matrix m = osg::Matrix::rotate( osg::PI_2, osg::X_AXIS ); // = worldToCubeMap
+
+        ::Triton::Matrix3 transformFromYUpToZUpCubeMapCoords(
+            m(0,0), m(0,1), m(0,2),
+            m(1,0), m(1,1), m(1,2),
+            m(2,0), m(2,1), m(2,2) );
+
+        // Grab the cube map from our sky box and give it to Triton to use as an _environment map
+        // GLenum texture = renderInfo.getState()->getLastAppliedTextureAttribute( _stage, osg::StateAttribute::TEXTURE );
+        if ( _cubeMap.valid() )
+        {
+            environment->SetEnvironmentMap(
+                (::Triton::TextureHandle)_cubeMap->getTextureObject( state->getContextID() )->id(), transformFromYUpToZUpCubeMapCoords );
+
+            if( _planarReflectionMap.valid() && _planarReflectionProjection.valid() )
+            {
+                osg::Matrix & p = *_planarReflectionProjection;
+
+                ::Triton::Matrix3 planarProjection( p(0,0), p(0,1), p(0,2),
+                                                    p(1,0), p(1,1), p(1,2),
+                                                    p(2,0), p(2,1), p(2,2) );
+
+                environment->SetPlanarReflectionMap( (::Triton::TextureHandle)
+                                                      _planarReflectionMap->getTextureObject( state->getContextID() )->id(),
+                                                      planarProjection, 0.125  );
+            }
+        }
+
+        // Draw the ocean for the current time sample
+        if ( _TRITON->getOcean() )
+        {
+            _TRITON->getOcean()->Draw( renderInfo.getView()->getFrameStamp()->getSimulationTime() );
+        }
+    }
+
+    // Put GL back in a state that won't confuse the OSG state tracking:
+    state->dirtyAllVertexArrays();
+    state->dirtyAllAttributes();
+    //osg::GL2Extensions* api = osg::GL2Extensions::Get(state->getContextID(), true);
+    //api->glUseProgram((GLuint)0);
+    //state->setLastAppliedProgramObject( 0L );
+    state->apply();
+}
+
+namespace
+{
+#ifdef GL_LUMINANCE_FLOAT16_ATI
+#   define GL_LUMINANCE_FLOAT16_ATI 0x881E
+#endif
+    /** Choose a supported FBO format by testing suitable ones until we find one that works. */
+    bool getBestFBOConfiguration(GLint* out_internalFormat, GLenum* out_sourceFormat, osg::State& state)
+    {
+#define NUM_FORMATS 7
+
+        struct Format {
+            GLint internalFormat;
+            GLenum sourceFormat;
+            std::string name;
+        };
+
+        const Format formats[NUM_FORMATS] = {
+            { GL_LUMINANCE16F_ARB,      GL_LUMINANCE, "GL_LUMINANCE16F_ARB" },
+            { GL_LUMINANCE_FLOAT16_ATI, GL_LUMINANCE, "GL_LUMINANCE_FLOAT16_ATI" },
+            { GL_LUMINANCE32F_ARB,      GL_LUMINANCE, "GL_LUMINANCE32F_ARB" },
+            { GL_RGB16F_ARB,            GL_RGB,       "GL_RGB16F_ARB" },
+            { GL_RGBA16F_ARB,           GL_RGBA,      "GL_RGBA16F_ARB" },
+            { GL_RGB32F_ARB,            GL_RGB,       "GL_RGB32F_ARB" },
+            { GL_RGBA32F_ARB,           GL_RGBA,      "GL_RGBA32F_ARB" }
+        };
+
+#if OSG_VERSION_GREATER_OR_EQUAL(3,4,0)
+        osg::GLExtensions* ext = osg::GLExtensions::Get(state.getContextID(), true);
+#else
+        osg::FBOExtensions* ext = osg::FBOExtensions::instance(state.getContextID(), true);
+#endif
+
+        osg::State::CheckForGLErrors check = state.getCheckForGLErrors();
+        state.setCheckForGLErrors(state.NEVER_CHECK_GL_ERRORS);
+
+        bool found = false;
+
+        for(int i=0; i<NUM_FORMATS && !found; ++i)
+        {
+            const Format& format = formats[i];
+
+            osg::ref_ptr<osg::Texture2D> tex = new osg::Texture2D();
+            tex->setTextureSize(1, 1);
+            tex->setInternalFormat( format.internalFormat );
+            tex->setSourceFormat  ( format.sourceFormat );
+
+            osg::ref_ptr<osg::FrameBufferObject> fbo = new osg::FrameBufferObject();
+            fbo->setAttachment( osg::Camera::COLOR_BUFFER, osg::FrameBufferAttachment(tex.get()) );
+
+            fbo->apply( state );
+
+            GLenum status = ext->glCheckFramebufferStatus(GL_FRAMEBUFFER_EXT);
+
+            fbo->releaseGLObjects( &state );
+            tex->releaseGLObjects( &state );
+
+            if ( status == GL_FRAMEBUFFER_COMPLETE_EXT )
+            {
+                if ( out_internalFormat) *out_internalFormat = format.internalFormat;
+                if ( out_sourceFormat )  *out_sourceFormat   = format.sourceFormat;
+                OE_INFO << LC << "Height map format => " << format.name << std::endl;
+                found = true;
+            }
+        }
+
+        state.setCheckForGLErrors(check);
+
+        return found;
+    }
+}
+
+void TritonDrawable::setupHeightMap(osg::State& state)
+{
+    osg::ref_ptr<MapNode> mapNode;
+    if (!_mapNode.lock(mapNode))
+        return;
+
+    int textureUnit = 0;
+    int textureSize = _TRITON->getHeightMapSize();
+
+    // Discover a suitable FBO format for floating point values:
+    GLint internalFormat;
+    GLenum sourceFormat;
+    if ( !getBestFBOConfiguration(&internalFormat, &sourceFormat, state) )
+    {
+        OE_WARN << LC << "No supported FBO format available for height map; height map disabled!\n";
+        return;
+    }
+
+    // Create our height map texture
+    _heightMap = new osg::Texture2D;
+    _heightMap->setTextureSize(textureSize, textureSize);
+    _heightMap->setInternalFormat( internalFormat );
+    _heightMap->setSourceFormat( sourceFormat );
+    _heightMap->setFilter(osg::Texture2D::MIN_FILTER, osg::Texture2D::LINEAR);
+    _heightMap->setFilter(osg::Texture2D::MAG_FILTER, osg::Texture2D::LINEAR);
+
+    // Create its camera and render to it
+    _heightCamera = new osg::Camera;
+    _heightCamera->setReferenceFrame(osg::Transform::ABSOLUTE_RF_INHERIT_VIEWPOINT);
+    _heightCamera->setClearMask(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
+    _heightCamera->setClearColor(osg::Vec4(-1000.0, -1000.0, -1000.0, 1.0f));
+    _heightCamera->setViewport(0, 0, textureSize, textureSize);
+    _heightCamera->setRenderOrder(osg::Camera::PRE_RENDER);
+    _heightCamera->setRenderTargetImplementation( osg::Camera::FRAME_BUFFER_OBJECT );
+    _heightCamera->setImplicitBufferAttachmentMask(0, 0);
+    _heightCamera->attach(osg::Camera::COLOR_BUFFER, _heightMap);
+    _heightCamera->setCullMask( ~TRITON_OCEAN_MASK );
+    _heightCamera->setAllowEventFocus(false);
+    _heightCamera->setFinalDrawCallback(new PassHeightMapToTritonCallback(_TRITON.get()));
+
+    // Install the shaders. We also bind osgEarth's elevation data attribute, which the
+    // terrain engine automatically generates at the specified location.
+    osg::StateSet* stateSet = _heightCamera->getOrCreateStateSet();
+    osgEarth::VirtualProgram* heightProgram = osgEarth::VirtualProgram::getOrCreate(stateSet);
+    heightProgram->setFunction( "setupContour", vertexShader,   osgEarth::ShaderComp::LOCATION_VERTEX_MODEL);
+    heightProgram->setFunction( "colorContour", fragmentShader, osgEarth::ShaderComp::LOCATION_FRAGMENT_OUTPUT);
+
+    _heightCamera->addChild( mapNode->getTerrainEngine() );
+    _terrainChangedCallback = new OceanTerrainChangedCallback(this);
+    if ( mapNode->getTerrain() )
+        mapNode->getTerrain()->addTerrainCallback( _terrainChangedCallback.get() );
+
+    osg::Group* root = osgEarth::findTopMostNodeOfType<osg::Group>(mapNode);
+    root->addChild(_heightCamera.get());
+
+#ifdef DEBUG_HEIGHTMAP
+    mapNode->getParent(0)->addChild(CreateTextureQuadOverlay(_heightMap, 0.65, 0.05, 0.3, 0.3));
+    mapNode->getParent(0)->insertChild(0, makeFrustumFromCamera(_heightCamera));
+#endif /* DEBUG_HEIGHTMAP */
+}
diff --git a/src/osgEarthTriton/TritonNode b/src/osgEarthTriton/TritonNode
new file mode 100644
index 0000000..709a302
--- /dev/null
+++ b/src/osgEarthTriton/TritonNode
@@ -0,0 +1,70 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+ * Copyright 2016 Pelican Mapping
+ * http://osgearth.org
+ *
+ * osgEarth is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ */
+#ifndef OSGEARTH_TRITON_NODE
+#define OSGEARTH_TRITON_NODE 1
+
+#include "Common"
+#include "TritonOptions"
+#include "TritonAPIWrapper"
+#include "TritonCallback"
+#include <osgEarthUtil/Ocean>
+#include <osgEarth/MapNode>
+#include <osg/Drawable>
+
+namespace osgEarth { namespace Triton
+{
+    class TritonContext;
+
+    /**
+     * Node that roots the Triton adapter.
+     */
+    class OSGEARTHTRITON_EXPORT TritonNode : public osgEarth::Util::OceanNode
+    {
+    public:
+        TritonNode(
+            osgEarth::MapNode*   mapNode,
+            const TritonOptions& options,
+            Callback*            userCallback =0L);
+
+    protected: // OceanNode
+
+        void onSetSeaLevel();
+
+        void onSetAlpha();
+
+    public: // osg::Node
+
+        osg::BoundingSphere computeBound() const;
+
+        void traverse(osg::NodeVisitor&);
+
+    protected:
+        virtual ~TritonNode();
+
+        osg::ref_ptr<TritonContext> _TRITON;
+        TritonOptions               _options;
+        osg::Drawable*              _drawable;
+        osg::ref_ptr<osg::Uniform>  _alphaUniform;
+
+        //Environment* _environmentWrapper;
+    };
+
+} } // namespace osgEarth::Triton
+
+#endif // OSGEARTH_TRITON_NODE
diff --git a/src/osgEarthTriton/TritonNode.cpp b/src/osgEarthTriton/TritonNode.cpp
new file mode 100644
index 0000000..85ce60a
--- /dev/null
+++ b/src/osgEarthTriton/TritonNode.cpp
@@ -0,0 +1,100 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+ * Copyright 2016 Pelican Mapping
+ * http://osgearth.org
+ *
+ * osgEarth is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+#include <Triton.h>
+#include "TritonNode"
+#include "TritonContext"
+#include "TritonDrawable"
+#include <osgEarth/CullingUtils>
+
+#define LC "[TritonNode] "
+
+using namespace osgEarth::Triton;
+
+TritonNode::TritonNode(osgEarth::MapNode*   mapNode,
+                       const TritonOptions& options,
+                       Callback*            callback) :
+OceanNode( options ),
+_options ( options )
+{
+    const osgEarth::Map* map = mapNode->getMap();
+    if ( map )
+        setSRS( map->getSRS() );
+
+    _TRITON = new TritonContext( options );
+
+    if ( map )
+        _TRITON->setSRS( map->getSRS() );
+
+    if ( callback )
+        _TRITON->setCallback( callback );
+
+    _drawable = new TritonDrawable(mapNode, _TRITON);
+    _alphaUniform = getOrCreateStateSet()->getOrCreateUniform("oe_ocean_alpha", osg::Uniform::FLOAT);
+    _alphaUniform->set(getAlpha());
+
+    osg::Geode* geode = new osg::Geode();
+    geode->addDrawable( _drawable );
+    geode->setNodeMask( TRITON_OCEAN_MASK );
+
+    this->addChild( geode );
+
+    this->setNumChildrenRequiringUpdateTraversal(1);
+
+    // Place in the depth-sorted bin and set a rendering order.
+    // We want Triton to render after the terrain.
+    _drawable->getOrCreateStateSet()->setRenderBinDetails( options.renderBinNumber().get(), "DepthSortedBin" );
+}
+
+TritonNode::~TritonNode()
+{
+    //nop
+}
+
+void
+TritonNode::onSetSeaLevel()
+{
+    if ( _TRITON->ready() )
+    {
+        _TRITON->getEnvironment()->SetSeaLevel( getSeaLevel() );
+    }
+    dirtyBound();
+}
+
+void
+TritonNode::onSetAlpha()
+{
+    _alphaUniform->set(getAlpha());
+}
+
+osg::BoundingSphere
+TritonNode::computeBound() const
+{
+    return osg::BoundingSphere();
+}
+
+void
+TritonNode::traverse(osg::NodeVisitor& nv)
+{
+    if ( nv.getVisitorType() == nv.UPDATE_VISITOR && _TRITON->ready() )
+    {
+        _TRITON->update(nv.getFrameStamp()->getSimulationTime());
+    }
+    osgEarth::Util::OceanNode::traverse(nv);
+}
diff --git a/src/osgEarthTriton/TritonOptions b/src/osgEarthTriton/TritonOptions
new file mode 100644
index 0000000..f87635c
--- /dev/null
+++ b/src/osgEarthTriton/TritonOptions
@@ -0,0 +1,109 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+ * Copyright 2016 Pelican Mapping
+ * http://osgearth.org
+ *
+ * osgEarth is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ */
+#ifndef OSGEARTH_TRITON_OPTIONS
+#define OSGEARTH_TRITON_OPTIONS 1
+
+#include "Common"
+#include <osgEarthUtil/Ocean>
+
+namespace osgEarth { namespace Triton
+{
+    /**
+     * Options for controlling the ocean surface node.
+     */
+    class /*header-only*/ TritonOptions : public osgEarth::Util::OceanOptions
+    {
+    public:
+        TritonOptions(const osgEarth::Util::OceanOptions& conf = osgEarth::Util::OceanOptions()) :
+            osgEarth::Util::OceanOptions( conf )
+        {
+            setDriver( "triton" );
+            _useHeightMap.init( true );
+            _heightMapSize.init( 1024 );
+            _renderBinNumber.init( 12 );
+            fromConfig( _conf );
+        }
+
+        virtual ~TritonOptions() { }
+
+        /* User name for license activation */
+        osgEarth::optional<std::string>& user() { return _user; }
+        const osgEarth::optional<std::string>& user() const { return _user; }
+
+        /* License code string */
+        osgEarth::optional<std::string>& licenseCode() { return _licenseCode; }
+        const osgEarth::optional<std::string>& licenseCode() const { return _licenseCode; }
+
+        /* Triton resource path */
+        osgEarth::optional<std::string>& resourcePath() { return _resourcePath; }
+        const osgEarth::optional<std::string>& resourcePath() const { return _resourcePath; }
+
+        /** Whether to pass a heightmap raster to Triton to mitigate coastline interference */
+        osgEarth::optional<bool>& useHeightMap() { return _useHeightMap; }
+        const osgEarth::optional<bool>& useHeightMap() const { return _useHeightMap; }
+
+        /** Texture size to use for the height map */
+        osgEarth::optional<int>& heightMapSize() { return _heightMapSize; }
+        const osgEarth::optional<int>& heightMapSize() const { return _heightMapSize; }
+
+        /** Render bin number to assign to the ocean (in DepthSortedBin) */
+        optional<int>& renderBinNumber() { return _renderBinNumber; }
+        const optional<int>& renderBinNumber() const { return _renderBinNumber; }
+
+
+    public:
+        osgEarth::Config getConfig() const {
+            osgEarth::Config conf = osgEarth::Util::OceanOptions::newConfig();
+            conf.addIfSet("user", _user);
+            conf.addIfSet("license_code", _licenseCode);
+            conf.addIfSet("resource_path", _resourcePath);
+            conf.addIfSet("use_height_map", _useHeightMap);
+            conf.addIfSet("height_map_size", _heightMapSize);
+            conf.addIfSet("render_bin_number",   _renderBinNumber);
+            return conf;
+        }
+
+    protected:
+        void mergeConfig( const osgEarth::Config& conf ) {
+            osgEarth::Util::OceanOptions::mergeConfig( conf );
+            fromConfig( conf );
+        }
+
+    private:
+        void fromConfig( const osgEarth::Config& conf ) {
+            conf.getIfSet("user", _user);
+            conf.getIfSet("license_code", _licenseCode);
+            conf.getIfSet("resource_path", _resourcePath);
+            conf.getIfSet("use_height_map", _useHeightMap);
+            conf.getIfSet("height_map_size", _heightMapSize);
+            conf.getIfSet("render_bin_number",   _renderBinNumber);
+        }
+
+    private:
+        osgEarth::optional<std::string> _user;
+        osgEarth::optional<std::string> _licenseCode;
+        osgEarth::optional<std::string> _resourcePath;
+        osgEarth::optional<bool>        _useHeightMap;
+        osgEarth::optional<int>         _heightMapSize;
+        osgEarth::optional<int>         _renderBinNumber;
+    };
+
+} } // namespace osgEarth::Triton
+
+#endif // OSGEARTH_TRITON_OPTIONS
diff --git a/src/osgEarthUtil/ActivityMonitorTool b/src/osgEarthUtil/ActivityMonitorTool
index 51c6154..a3d2802 100644
--- a/src/osgEarthUtil/ActivityMonitorTool
+++ b/src/osgEarthUtil/ActivityMonitorTool
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthUtil/ActivityMonitorTool.cpp b/src/osgEarthUtil/ActivityMonitorTool.cpp
index e38350e..922eaf3 100644
--- a/src/osgEarthUtil/ActivityMonitorTool.cpp
+++ b/src/osgEarthUtil/ActivityMonitorTool.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthUtil/AnnotationEvents b/src/osgEarthUtil/AnnotationEvents
index 8484209..d22b33c 100644
--- a/src/osgEarthUtil/AnnotationEvents
+++ b/src/osgEarthUtil/AnnotationEvents
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
@@ -35,7 +35,6 @@
  */
 namespace osgEarth { namespace Util
 {	
-    using namespace osgEarth::Util;
     using namespace osgEarth::Annotation;
 
     /**
@@ -46,6 +45,7 @@ namespace osgEarth { namespace Util
     {
         struct EventArgs
         {
+            EventArgs() : x(0.0f), y(0.0f), buttons(0), modkeys(0) { }
             float x, y;
             int   buttons;   // see osgGA::GUIEventAdapter::MouseButtonMask
             int   modkeys;   // see osgGA::GUIEventAdapter::ModKeyMask
diff --git a/src/osgEarthUtil/AnnotationEvents.cpp b/src/osgEarthUtil/AnnotationEvents.cpp
index de8c224..4937476 100644
--- a/src/osgEarthUtil/AnnotationEvents.cpp
+++ b/src/osgEarthUtil/AnnotationEvents.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthUtil/ArcGIS b/src/osgEarthUtil/ArcGIS
index 9ad620d..cff35e5 100644
--- a/src/osgEarthUtil/ArcGIS
+++ b/src/osgEarthUtil/ArcGIS
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthUtil/ArcGIS.cpp b/src/osgEarthUtil/ArcGIS.cpp
index 32d9daf..7f8b275 100644
--- a/src/osgEarthUtil/ArcGIS.cpp
+++ b/src/osgEarthUtil/ArcGIS.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthUtil/AtlasBuilder b/src/osgEarthUtil/AtlasBuilder
index 394099c..acc3e87 100644
--- a/src/osgEarthUtil/AtlasBuilder
+++ b/src/osgEarthUtil/AtlasBuilder
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthUtil/AtlasBuilder.cpp b/src/osgEarthUtil/AtlasBuilder.cpp
index 71a9059..0ab4388 100644
--- a/src/osgEarthUtil/AtlasBuilder.cpp
+++ b/src/osgEarthUtil/AtlasBuilder.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -132,8 +132,8 @@ AtlasBuilder::build(const ResourceLibrary* inputLib,
     {
         SkinResource* skin = i->get();
 
-        // skip tiled skins for now.
-        if ( skin->isTiled() == true )
+        // skip skins that say "no atlas please"
+        if ( skin->atlasHint() == false )
         {
             continue;
         }
@@ -256,6 +256,10 @@ AtlasBuilder::build(const ResourceLibrary* inputLib,
             maxT = t;
     }
 
+    // protecte against a div0
+    maxS = std::max(maxS, 1u);
+    maxT = std::max(maxT, 1u);
+
     OE_INFO << LC <<
         "Final atlas size will be (" << maxS << ", " << maxT << ")" << std::endl;
 
@@ -303,6 +307,9 @@ AtlasBuilder::build(const ResourceLibrary* inputLib,
     
     // for each source in this atlas layer, apply its texture matrix info
     // to the new catalog.
+    maxS = std::max(maxS, 1u);
+    maxT = std::max(maxT, 1u);
+
     for(int r=0; r<(int)mainAtlasList.size(); ++r)
     {
         for(int k=0; k<mainAtlasList[r]->_sourceList.size(); ++k)
diff --git a/src/osgEarthUtil/AutoClipPlaneHandler b/src/osgEarthUtil/AutoClipPlaneHandler
index f59acfc..0e20b83 100644
--- a/src/osgEarthUtil/AutoClipPlaneHandler
+++ b/src/osgEarthUtil/AutoClipPlaneHandler
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthUtil/AutoClipPlaneHandler.cpp b/src/osgEarthUtil/AutoClipPlaneHandler.cpp
index 7aef102..911c821 100644
--- a/src/osgEarthUtil/AutoClipPlaneHandler.cpp
+++ b/src/osgEarthUtil/AutoClipPlaneHandler.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -221,7 +221,7 @@ AutoClipPlaneCullCallback::operator()( osg::Node* node, osg::NodeVisitor* nv )
                 CustomProjClamper* c = static_cast<CustomProjClamper*>(clamper.get());
 
                 osg::Vec3d eye, center, up;
-                cam->getViewMatrixAsLookAt( eye, center, up );
+                cv->getModelViewMatrix()->getLookAt( eye, center, up );
 
                 // clamp the far clipping plane to the approximate horizon distance
                 if ( _autoFarPlaneClamping )
diff --git a/src/osgEarthUtil/BrightnessContrastColorFilter b/src/osgEarthUtil/BrightnessContrastColorFilter
index bfaf0b7..e8a5e84 100644
--- a/src/osgEarthUtil/BrightnessContrastColorFilter
+++ b/src/osgEarthUtil/BrightnessContrastColorFilter
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthUtil/BrightnessContrastColorFilter.cpp b/src/osgEarthUtil/BrightnessContrastColorFilter.cpp
index 9ed1b0f..999d933 100644
--- a/src/osgEarthUtil/BrightnessContrastColorFilter.cpp
+++ b/src/osgEarthUtil/BrightnessContrastColorFilter.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthUtil/CMYKColorFilter b/src/osgEarthUtil/CMYKColorFilter
index 2b1d7a3..1d54167 100644
--- a/src/osgEarthUtil/CMYKColorFilter
+++ b/src/osgEarthUtil/CMYKColorFilter
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthUtil/CMYKColorFilter.cpp b/src/osgEarthUtil/CMYKColorFilter.cpp
index 37baaf6..558dbf5 100644
--- a/src/osgEarthUtil/CMYKColorFilter.cpp
+++ b/src/osgEarthUtil/CMYKColorFilter.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthUtil/CMakeLists.txt b/src/osgEarthUtil/CMakeLists.txt
index 859fa41..8fe8c01 100644
--- a/src/osgEarthUtil/CMakeLists.txt
+++ b/src/osgEarthUtil/CMakeLists.txt
@@ -49,6 +49,7 @@ SET(HEADERS_ROOT
     Shaders
 	Shadowing
 	SimplexNoise
+    SimplePager
     Sky
     SpatialData
     StarData
@@ -81,7 +82,9 @@ set(TARGET_GLSL
     Graticule.frag.glsl
     LogDepthBuffer.vert.glsl
     LogDepthBuffer.VertOnly.vert.glsl    
-    LogDepthBuffer.frag.glsl )
+    LogDepthBuffer.frag.glsl
+    Shadowing.vert.glsl
+    Shadowing.frag.glsl)
 
 set(TARGET_IN
     Shaders.cpp.in)
@@ -127,6 +130,7 @@ SET(SOURCES_ROOT
     RTTPicker.cpp
 	Shadowing.cpp
 	SimplexNoise.cpp
+    SimplePager.cpp
     SpatialData.cpp
     Sky.cpp
     TerrainProfile.cpp
diff --git a/src/osgEarthUtil/ChromaKeyColorFilter b/src/osgEarthUtil/ChromaKeyColorFilter
index cd06c13..1ea40cc 100644
--- a/src/osgEarthUtil/ChromaKeyColorFilter
+++ b/src/osgEarthUtil/ChromaKeyColorFilter
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthUtil/ChromaKeyColorFilter.cpp b/src/osgEarthUtil/ChromaKeyColorFilter.cpp
index cee482a..e75ba90 100644
--- a/src/osgEarthUtil/ChromaKeyColorFilter.cpp
+++ b/src/osgEarthUtil/ChromaKeyColorFilter.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthUtil/ClampCallback b/src/osgEarthUtil/ClampCallback
index db40bba..34e8ff3 100644
--- a/src/osgEarthUtil/ClampCallback
+++ b/src/osgEarthUtil/ClampCallback
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthUtil/ClampCallback.cpp b/src/osgEarthUtil/ClampCallback.cpp
index ea4db48..5748b0f 100644
--- a/src/osgEarthUtil/ClampCallback.cpp
+++ b/src/osgEarthUtil/ClampCallback.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
@@ -43,6 +43,22 @@ ClampCallback::ClampCallback(osg::Node* terrainNode)
     _intersectionMask = 0xffffffff;
 }
 
+
+unsigned int
+ClampCallback::getIntersectionMask() const
+{
+    return _intersectionMask;
+}
+
+void
+ClampCallback::setIntersectionMask(unsigned int intersectionMask)
+{
+    _intersectionMask = intersectionMask;
+}
+
+
+
+
 bool ClampCallback::clamp(const osg::Vec3d& pos, osg::Vec3d& out) const
 {
     //Return if there is no terrain node assigned
diff --git a/src/osgEarthUtil/Common b/src/osgEarthUtil/Common
index 42221e1..c1c50bb 100644
--- a/src/osgEarthUtil/Common
+++ b/src/osgEarthUtil/Common
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthUtil/ContourMap b/src/osgEarthUtil/ContourMap
index b930042..aa3a1b3 100644
--- a/src/osgEarthUtil/ContourMap
+++ b/src/osgEarthUtil/ContourMap
@@ -25,43 +25,73 @@
 #include <osgEarthUtil/Common>
 #include <osgEarth/TerrainEffect>
 #include <osgEarth/ImageLayer>
+#include <osgEarth/Extension>
 #include <osg/Texture1D>
 #include <osg/TransferFunction>
 
 namespace osgEarth {
     class Map;
+    class MapNode;
 }
 
 namespace osgEarth { namespace Util
 {
+    class OSGEARTHUTIL_EXPORT ContourMapOptions : public ConfigOptions
+    {
+    public:
+        ContourMapOptions(const ConfigOptions& conf =ConfigOptions()) : ConfigOptions(conf),
+            _opacity(1.0f), _grayscale(false)
+        {
+            fromConfig(_conf);
+        }
+    public:
+        optional<float>& opacity() { return _opacity; }
+        const optional<float>& opacity() const { return _opacity; }
+
+        optional<bool>& grayscale() { return _grayscale; }
+        const optional<bool>& grayscale() const { return _grayscale; }
+
+    public:
+        void fromConfig(const Config& conf) {
+            conf.getIfSet("opacity", _opacity);
+            conf.getIfSet("grayscale", _grayscale);
+        }
+        Config getConfig() const {
+            Config conf;
+            conf.addIfSet("opacity", _opacity);
+            conf.addIfSet("grayscale", _grayscale);
+            return conf;
+        }
+        
+    private:
+        optional<float> _opacity;
+        optional<bool>  _grayscale;
+    };
+
     /**
      * Terrain effect that applies a 1D contour coloring texture
      * to the terrain based an on elevation->color map.
      */
-    class OSGEARTHUTIL_EXPORT ContourMap : public TerrainEffect
+    class OSGEARTHUTIL_EXPORT ContourMap : public TerrainEffect,
+                                           public ContourMapOptions
     {
     public:
         /** construct a new effect */
         ContourMap();
+        ContourMap(const ConfigOptions& co);
 
         /** Sets a custom transfer function. */
         void setTransferFunction(osg::TransferFunction1D* xf);
         osg::TransferFunction1D* getTransferFunction() const { return _xfer.get(); }
 
-        /** Sets the opacity of the effect (default = 1.0) */
-        void setOpacity(float value);
+        /** rebuild after changing one of the options */
+        void dirty();
 
     public: // TerrainEffect interface
 
         void onInstall(TerrainEngineNode* engine);
         void onUninstall(TerrainEngineNode* engine);
 
-    public: // serialization
-
-        ContourMap(const Config& conf);
-        void mergeConfig(const Config& conf);
-        virtual Config getConfig() const;
-
     protected:
         virtual ~ContourMap();
         void init();
@@ -73,10 +103,36 @@ namespace osgEarth { namespace Util
         osg::ref_ptr<osg::Uniform>            _xferMin;
         osg::ref_ptr<osg::Uniform>            _xferRange;
         osg::ref_ptr<osg::Uniform>            _opacityUniform;
+    };
 
-        optional<float> _opacity;
+    /** Activates contour map from the earth file. */
+    class OSGEARTHUTIL_EXPORT ContourMapExtension : public Extension,
+                                                    public ExtensionInterface<MapNode>,
+                                                    public ContourMapOptions
+    {
+    public:
+        META_Object(osgEarthUtil, ContourMapExtension);
+
+        ContourMapExtension() { }
+        ContourMapExtension(const ConfigOptions& co) : ContourMapOptions(co) { }
+
+    public: // ExtensionInterface<MapNode>
+        bool connect(MapNode*);
+        bool disconnect(MapNode*);
+
+    public: // Extension
+        
+        // for serialization
+        virtual const ConfigOptions& getConfigOptions() const { return *this; }
+
+    protected:
+        ContourMapExtension(const ContourMapExtension& rhs, const osg::CopyOp& op) { } // unused
+        virtual ~ContourMapExtension() { }
+
+        osg::ref_ptr<ContourMap> _effect;
     };
 
+
 } } // namespace osgEarth::Util
 
 #endif // OSGEARTHUTIL_CONTOUR_MAP_H
diff --git a/src/osgEarthUtil/ContourMap.cpp b/src/osgEarthUtil/ContourMap.cpp
index db67b08..66bc67a 100644
--- a/src/osgEarthUtil/ContourMap.cpp
+++ b/src/osgEarthUtil/ContourMap.cpp
@@ -25,6 +25,7 @@
 #include <osgEarth/Capabilities>
 #include <osgEarth/VirtualProgram>
 #include <osgEarth/TerrainEngineNode>
+#include <osgEarth/MapNode>
 
 #define LC "[ContourMap] "
 
@@ -38,14 +39,13 @@ TerrainEffect()
     init();
 }
 
-ContourMap::ContourMap(const Config& conf) :
-TerrainEffect()
+ContourMap::ContourMap(const ConfigOptions& co) :
+TerrainEffect(),
+ContourMapOptions(co)
 {
-    mergeConfig(conf);
     init();
 }
 
-
 void
 ContourMap::init()
 {
@@ -57,7 +57,6 @@ ContourMap::init()
     _xferRange   = new osg::Uniform(osg::Uniform::FLOAT,      "oe_contour_range" );
     _xferSampler = new osg::Uniform(osg::Uniform::SAMPLER_1D, "oe_contour_xfer" );
     _opacityUniform = new osg::Uniform(osg::Uniform::FLOAT,   "oe_contour_opacity" );
-    _opacityUniform->set( _opacity.getOrUse(1.0f) );
 
     // Create a 1D texture from the transfer function's image.
     _xferTexture = new osg::Texture1D();
@@ -66,30 +65,82 @@ ContourMap::init()
     _xferTexture->setFilter( osg::Texture::MAG_FILTER, osg::Texture::LINEAR );
     _xferTexture->setWrap( osg::Texture::WRAP_S, osg::Texture::CLAMP_TO_EDGE );
 
+#if 0
     // build a default transfer function.
     // TODO: think about scale/bias controls.
     osg::TransferFunction1D* xfer = new osg::TransferFunction1D();
     float s = 2500.0f;
-    xfer->setColor( -1.0000 * s, osg::Vec4f(0, 0, 0.5, 1), false);
-    xfer->setColor( -0.2500 * s, osg::Vec4f(0, 0, 1, 1), false);
-    xfer->setColor(  0.0000 * s, osg::Vec4f(0, .5, 1, 1), false);
-    xfer->setColor(  0.0062 * s, osg::Vec4f(.84,.84,.25,1), false);
-    //xfer->setColor(  0.0625 * s, osg::Vec4f(.94,.94,.25,1), false);
-    xfer->setColor(  0.1250 * s, osg::Vec4f(.125,.62,0,1), false);
-    xfer->setColor(  0.3250 * s, osg::Vec4f(.80,.70,.47,1), false);
-    xfer->setColor(  0.7500 * s, osg::Vec4f(.5,.5,.5,1), false);
-    xfer->setColor(  1.0000 * s, osg::Vec4f(1,1,1,1), false);
+
+    if ( grayscale() == true )
+    {
+        xfer->setColor( -1.0000 * s, osg::Vec4f(.125,.125,.125, 1), false);
+        xfer->setColor( -0.2500 * s, osg::Vec4f(.25,.25,.25, 1), false);
+        xfer->setColor(  0.0000 * s, osg::Vec4f(.375,.375,.375, 1), false);
+        xfer->setColor(  0.0062 * s, osg::Vec4f(.5,.5,.5,1), false);
+        xfer->setColor(  0.1250 * s, osg::Vec4f(.625,.625,.625,1), false);
+        xfer->setColor(  0.3250 * s, osg::Vec4f(.75,.75,.75,1), false);
+        xfer->setColor(  0.7500 * s, osg::Vec4f(.875,.875,.875,1), false);
+        xfer->setColor(  1.0000 * s, osg::Vec4f(1,1,1,1), false);
+    }
+    else
+    {
+        xfer->setColor( -1.0000 * s, osg::Vec4f(0, 0, 0.5, 1), false);
+        xfer->setColor( -0.2500 * s, osg::Vec4f(0, 0, 1, 1), false);
+        xfer->setColor(  0.0000 * s, osg::Vec4f(0, .5, 1, 1), false);
+        xfer->setColor(  0.0062 * s, osg::Vec4f(.84,.84,.25,1), false);
+        xfer->setColor(  0.1250 * s, osg::Vec4f(.125,.62,0,1), false);
+        xfer->setColor(  0.3250 * s, osg::Vec4f(.80,.70,.47,1), false);
+        xfer->setColor(  0.7500 * s, osg::Vec4f(.5,.5,.5,1), false);
+        xfer->setColor(  1.0000 * s, osg::Vec4f(1,1,1,1), false);
+    }
     xfer->updateImage();
     this->setTransferFunction( xfer );
+    _opacityUniform->set( opacity().getOrUse(1.0f) );
+#endif
+
+    dirty();
 }
 
+void
+ContourMap::dirty()
+{
+    _opacityUniform->set(opacity().getOrUse(1.0f));
+    
+    // build a transfer function.
+    osg::TransferFunction1D* xfer = new osg::TransferFunction1D();
+    float s = 2500.0f;
+
+    if ( grayscale() == true )
+    {
+        xfer->setColor( -1.0000 * s, osg::Vec4f(.125,.125,.125, 1), false);
+        xfer->setColor( -0.2500 * s, osg::Vec4f(.25,.25,.25, 1), false);
+        xfer->setColor(  0.0000 * s, osg::Vec4f(.375,.375,.375, 1), false);
+        xfer->setColor(  0.0062 * s, osg::Vec4f(.5,.5,.5,1), false);
+        xfer->setColor(  0.1250 * s, osg::Vec4f(.625,.625,.625,1), false);
+        xfer->setColor(  0.3250 * s, osg::Vec4f(.75,.75,.75,1), false);
+        xfer->setColor(  0.7500 * s, osg::Vec4f(.875,.875,.875,1), false);
+        xfer->setColor(  1.0000 * s, osg::Vec4f(1,1,1,1), false);
+    }
+    else
+    {
+        xfer->setColor( -1.0000 * s, osg::Vec4f(0, 0, 0.5, 1), false);
+        xfer->setColor( -0.2500 * s, osg::Vec4f(0, 0, 1, 1), false);
+        xfer->setColor(  0.0000 * s, osg::Vec4f(0, .5, 1, 1), false);
+        xfer->setColor(  0.0062 * s, osg::Vec4f(.84,.84,.25,1), false);
+        xfer->setColor(  0.1250 * s, osg::Vec4f(.125,.62,0,1), false);
+        xfer->setColor(  0.3250 * s, osg::Vec4f(.80,.70,.47,1), false);
+        xfer->setColor(  0.7500 * s, osg::Vec4f(.5,.5,.5,1), false);
+        xfer->setColor(  1.0000 * s, osg::Vec4f(1,1,1,1), false);
+    }
+    xfer->updateImage();
+    this->setTransferFunction( xfer );
+}
 
 ContourMap::~ContourMap()
 {
     //nop
 }
 
-
 void
 ContourMap::setTransferFunction(osg::TransferFunction1D* xfer)
 {
@@ -100,15 +151,6 @@ ContourMap::setTransferFunction(osg::TransferFunction1D* xfer)
     _xferRange->set( _xfer->getMaximum() - _xfer->getMinimum() );
 }
 
-
-void
-ContourMap::setOpacity(float opacity)
-{
-    _opacity = osg::clampBetween(opacity, 0.0f, 1.0f);
-    _opacityUniform->set( _opacity.get() );
-}
-
-
 void
 ContourMap::onInstall(TerrainEngineNode* engine)
 {
@@ -133,7 +175,7 @@ ContourMap::onInstall(TerrainEngineNode* engine)
         VirtualProgram* vp = VirtualProgram::getOrCreate(stateset);
 
         Shaders pkg;
-        pkg.load(vp, pkg.ContourMap_Vertex);
+        //pkg.load(vp, pkg.ContourMap_Vertex);
         pkg.load(vp, pkg.ContourMap_Fragment);
 
         // Install some uniforms that tell the shader the height range of the color map.
@@ -180,19 +222,25 @@ ContourMap::onUninstall(TerrainEngineNode* engine)
     }
 }
 
-
 //-------------------------------------------------------------
 
-void
-ContourMap::mergeConfig(const Config& conf)
+REGISTER_OSGEARTH_EXTENSION(osgearth_contourmap,  ContourMapExtension);
+REGISTER_OSGEARTH_EXTENSION(osgearth_contour_map, ContourMapExtension);
+
+bool
+ContourMapExtension::connect(MapNode* mapNode)
 {
-    conf.getIfSet("opacity", _opacity);
+    if ( !_effect.valid() )
+        _effect = new ContourMap(*this);
+
+    mapNode->getTerrainEngine()->addEffect( _effect.get() );
+    return true;
 }
 
-Config
-ContourMap::getConfig() const
+bool
+ContourMapExtension::disconnect(MapNode* mapNode)
 {
-    Config conf("contour_map");
-    conf.addIfSet("opacity", _opacity);
-    return conf;
+    if ( mapNode )
+        mapNode->getTerrainEngine()->removeEffect( _effect.get() );
+    return true;
 }
diff --git a/src/osgEarthUtil/ContourMap.frag.glsl b/src/osgEarthUtil/ContourMap.frag.glsl
index 43035cc..c9ab5bf 100644
--- a/src/osgEarthUtil/ContourMap.frag.glsl
+++ b/src/osgEarthUtil/ContourMap.frag.glsl
@@ -1,16 +1,23 @@
 #version $GLSL_VERSION_STR
 $GLSL_DEFAULT_PRECISION_FLOAT
 
-#pragma vp_entryPoint "oe_contour_fragment"
-#pragma vp_location   "fragment_coloring"
-#pragma vp_order      "0.2"
+#pragma vp_entryPoint oe_contour_fragment
+#pragma vp_location   fragment_coloring
+#pragma vp_order      0.2
 
+varying vec4 oe_layer_tilec;
 uniform sampler1D oe_contour_xfer;
 uniform float oe_contour_opacity;
-varying float oe_contour_lookup;
+uniform float oe_contour_min;
+uniform float oe_contour_range;
+
+float oe_terrain_getElevation(in vec2 uv);
 
 void oe_contour_fragment( inout vec4 color )
 {
-    vec4 texel = texture1D( oe_contour_xfer, oe_contour_lookup );
+    float height = oe_terrain_getElevation(oe_layer_tilec.st);
+    float height_normalized = (height-oe_contour_min)/oe_contour_range;
+    float lookup = clamp( height_normalized, 0.0, 1.0 );
+    vec4 texel = texture1D( oe_contour_xfer, lookup );
     color.rgb = mix(color.rgb, texel.rgb, texel.a * oe_contour_opacity);
 }
\ No newline at end of file
diff --git a/src/osgEarthUtil/ContourMap.vert.glsl b/src/osgEarthUtil/ContourMap.vert.glsl
index 2ac4c2a..5fefaa7 100644
--- a/src/osgEarthUtil/ContourMap.vert.glsl
+++ b/src/osgEarthUtil/ContourMap.vert.glsl
@@ -1,18 +1,22 @@
 #version $GLSL_VERSION_STR
 $GLSL_DEFAULT_PRECISION_FLOAT
 
-#pragma vp_entryPoint "oe_contour_vertex"
-#pragma vp_location   "vertex_model"
-#pragma vp_order      "0.5"
+    // NOTE: This vertex shader is no longer used.
 
-attribute vec4 oe_terrain_attr;
+#pragma vp_entryPoint oe_contour_vertex
+#pragma vp_location   vertex_model
+#pragma vp_order      0.5
+
+varying vec4 oe_layer_tilec;
 uniform float oe_contour_min;
 uniform float oe_contour_range;
 varying float oe_contour_lookup;
 
+float oe_terrain_getElevation(in vec2 uv);
+
 void oe_contour_vertex(inout vec4 VertexModel)
 {
-    float height = oe_terrain_attr[3];
+    float height = oe_terrain_getElevation(oe_layer_tilec.st);
     float height_normalized = (height-oe_contour_min)/oe_contour_range;
     oe_contour_lookup = clamp( height_normalized, 0.0, 1.0 );
 }
\ No newline at end of file
diff --git a/src/osgEarthUtil/Controls b/src/osgEarthUtil/Controls
index 9afc1ec..98d42c6 100644
--- a/src/osgEarthUtil/Controls
+++ b/src/osgEarthUtil/Controls
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -55,7 +55,7 @@ namespace osgEarth { namespace Util { namespace Controls
     // internal state class
     struct ControlContext
     {
-        ControlContext() : _viewContextID(~0) { }
+        ControlContext() : _viewContextID(~0), _frameStamp(0L), _view(0L) { }
         osg::View* _view;
         osg::ref_ptr<const osg::Viewport> _vp;
         unsigned int _viewContextID;
@@ -151,7 +151,7 @@ namespace osgEarth { namespace Util { namespace Controls
         virtual void onValueChanged( class Control* control, const std::string& value ) { onValueChanged(control); }
         virtual void onValueChanged( class Control* control, void* value ) { onValueChanged(control); }
         virtual void onValueChanged( class Control* control ) { }
-        
+
         /** dtor */
         virtual ~ControlEventHandler() { }
     };
@@ -232,7 +232,7 @@ namespace osgEarth { namespace Util { namespace Controls
         void setVertFill( bool value, float minHeight =0.0f );
         bool vertFill() const { return _vfill; }
 
-        void setVisible( bool value );
+        virtual void setVisible( bool value );
         bool visible() const { return _visible; }
         bool parentIsVisible() const;
 
@@ -272,7 +272,7 @@ namespace osgEarth { namespace Util { namespace Controls
         void addEventHandler( ControlEventHandler* handler, bool fire =false );
 
     public:
-        
+
         // mark the control as dirty so that it will regenerate on the next pass.
         virtual void dirty();
         bool isDirty() const { return _dirty; }
@@ -423,7 +423,7 @@ namespace osgEarth { namespace Util { namespace Controls
             const osg::Vec4f&    activeColor =osg::Vec4f(0.5,0.5,1,1),
             float                fontSize    =18.0f,
             ControlEventHandler* handler     =0L );
-        
+
         ButtonControl(
             const std::string&   text,
             ControlEventHandler* handler );
@@ -571,7 +571,7 @@ namespace osgEarth { namespace Util { namespace Controls
 
         /** dtor */
         virtual ~Container() { }
-        
+
         // space between children
         void setChildSpacing( float value );
         float childSpacing() const { return _spacing; }
@@ -586,7 +586,7 @@ namespace osgEarth { namespace Util { namespace Controls
 
         // adds a control.
         template<typename T>
-        T* addControl( T* control, int index =-1 ) { 
+        T* addControl( T* control, int index =-1 ) {
             return dynamic_cast<T*>( addControlImpl(control, index) ); }
 
         // default multiple-add function.
@@ -598,6 +598,9 @@ namespace osgEarth { namespace Util { namespace Controls
         // gets a vector of pointers to the container's immediate children
         virtual void getChildren(std::vector<Control*>& out);
 
+	// change the visibility of the grid and its controls
+	virtual void setVisible( bool value );
+
     public:
         virtual void calcSize( const ControlContext& context, osg::Vec2f& out_size );
         virtual void calcFill( const ControlContext& context );
@@ -612,16 +615,16 @@ namespace osgEarth { namespace Util { namespace Controls
         virtual bool handle( const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa, ControlContext& cx );
 
         void applyChildAligns();
-        
+
         //void setChildRenderSize( Control* child, float w, float h ) { child->_renderSize.set( w, h ); }
         float& renderWidth(Control* child) { return child->_renderSize.x(); }
         float& renderHeight(Control* child) { return child->_renderSize.y(); }
 
-    private:        
+    private:
         float _spacing;
         optional<Alignment> _childhalign;
         optional<Alignment> _childvalign;
-        
+
         //ControlList& mutable_children() { return const_cast<ControlList&>(children()); }
     };
 
@@ -640,7 +643,7 @@ namespace osgEarth { namespace Util { namespace Controls
     public: // Container
         virtual void clearControls();
 
-    public: // Control        
+    public: // Control
         virtual void calcSize( const ControlContext& context, osg::Vec2f& out_size );
         virtual void calcFill( const ControlContext& context );
         virtual void calcPos ( const ControlContext& context, const osg::Vec2f& cursor, const osg::Vec2f& parentSize );
@@ -669,7 +672,7 @@ namespace osgEarth { namespace Util { namespace Controls
         //virtual const ControlList& children() const { return _controls; }
         virtual void clearControls();
 
-    public: // Control        
+    public: // Control
         virtual void calcSize( const ControlContext& context, osg::Vec2f& out_size );
         virtual void calcFill( const ControlContext& context );
         virtual void calcPos ( const ControlContext& context, const osg::Vec2f& cursor, const osg::Vec2f& parentSize );
@@ -704,12 +707,14 @@ namespace osgEarth { namespace Util { namespace Controls
     public: // Container
         virtual void clearControls();
 
+
+
         // adds the controls as a row at the bottom of the grid.
         virtual void addControls( const ControlVector& controls );
 
         virtual void getChildren(std::vector<Control*>& out);
 
-    public: // Control        
+    public: // Control
         virtual void calcSize( const ControlContext& context, osg::Vec2f& out_size );
         virtual void calcFill( const ControlContext& context );
         virtual void calcPos ( const ControlContext& context, const osg::Vec2f& cursor, const osg::Vec2f& parentSize );
@@ -723,7 +728,7 @@ namespace osgEarth { namespace Util { namespace Controls
         void expandToInclude(int cols, int rows);
 
         osg::Group* getRow(unsigned index);
-        
+
         std::vector<float> _rowHeights, _colWidths;
         unsigned _maxCols;
     };
@@ -839,14 +844,14 @@ namespace osgEarth { namespace Util { namespace Controls
     public:
         /** Accesses the control canvas attached the the specified view. */
         static ControlCanvas* get(osg::View* view);
-        
+
         /** Accesses the control canvas attached the the specified view. */
         static ControlCanvas* getOrCreate(osg::View* view);
 
     public:
         /** adds a top-level control to this surface. */
         template<typename T>
-        T* addControl( T* control ) { 
+        T* addControl( T* control ) {
             return dynamic_cast<T*>( addControlImpl( control ) ); }
 
         /** removes a top-level control. */
@@ -880,7 +885,7 @@ namespace osgEarth { namespace Util { namespace Controls
         ControlContext  _context;
         bool            _contextDirty;
         bool            _updatePending;
-        
+
         typedef std::map< osg::observer_ptr<osgGA::GUIEventHandler>, osg::observer_ptr<osgViewer::View> > EventHandlersMap;
         EventHandlersMap _eventHandlersMap;
 
diff --git a/src/osgEarthUtil/Controls.cpp b/src/osgEarthUtil/Controls.cpp
index c6467bf..a32cb37 100755
--- a/src/osgEarthUtil/Controls.cpp
+++ b/src/osgEarthUtil/Controls.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -1656,6 +1656,27 @@ Container::addControls( const ControlVector& controls )
     }
 }
 
+
+
+
+
+
+void Container::setVisible(bool visibility) 
+{ 
+        Control::setVisible(visibility); 
+        std::vector<osgEarth::Util::Controls::Control*> out; 
+        getChildren(out); 
+        for (int i = 0; i < (int) out.size(); i++) 
+        { 
+                Container* container = dynamic_cast<Container*>( out.at(i) ); 
+                if (container) { 
+                        container->setVisible(visibility); 
+                } else { 
+                        out.at(i)->setVisible(visibility); 
+                } 
+        } 
+}
+
 // ---------------------------------------------------------------------------
 
 VBox::VBox()
@@ -1778,8 +1799,7 @@ VBox::calcPos(const ControlContext& cx, const osg::Vec2f& cursor, const osg::Vec
 void
 VBox::draw( const ControlContext& cx )
 {
-    if ( visible() )
-    {
+   
         Container::draw( cx );
 
         for( unsigned i=1; i<getNumChildren(); ++i )
@@ -1788,7 +1808,7 @@ VBox::draw( const ControlContext& cx )
             if ( c )
                 c->draw( cx );
         }
-    }
+     
 }
 
 // ---------------------------------------------------------------------------
@@ -1848,6 +1868,10 @@ HBox::calcSize(const ControlContext& cx, osg::Vec2f& out_size)
 
         Container::calcSize( cx, out_size );
     }
+    else
+    {
+        out_size.set(0,0);
+    }
 }
 
 void
@@ -1912,8 +1936,7 @@ HBox::calcPos(const ControlContext& cx, const osg::Vec2f& cursor, const osg::Vec
 void
 HBox::draw( const ControlContext& cx )
 {
-    if ( visible() )
-    {
+    
         Container::draw( cx );
 
         for( unsigned i=1; i<getNumChildren(); ++i )
@@ -1922,7 +1945,7 @@ HBox::draw( const ControlContext& cx )
             if ( c )
                 c->draw( cx );
         }
-    }
+    
 }
 
 // ---------------------------------------------------------------------------
@@ -2069,8 +2092,7 @@ Grid::clearControls()
 void
 Grid::calcSize( const ControlContext& cx, osg::Vec2f& out_size )
 {
-    if ( visible() )
-    {
+    
         _renderSize.set( 0, 0 );
 
         int nRows = (int)getNumRows();
@@ -2109,7 +2131,7 @@ Grid::calcSize( const ControlContext& cx, osg::Vec2f& out_size )
         }
 
         Container::calcSize( cx, out_size );
-    }
+    
 }
 
 void
@@ -2164,11 +2186,14 @@ Grid::calcPos( const ControlContext& cx, const osg::Vec2f& cursor, const osg::Ve
     }
 }
 
+
+
+
+
 void
 Grid::draw( const ControlContext& cx )
 {
-    if ( visible() )
-    {
+    
         Container::draw( cx );
 
         for( unsigned i=1; i<getNumChildren(); ++i )
@@ -2186,7 +2211,7 @@ Grid::draw( const ControlContext& cx )
                 }
             }
         }
-    }
+ 
 }
 
 // ---------------------------------------------------------------------------
@@ -2352,7 +2377,8 @@ ControlNode::traverse( osg::NodeVisitor& nv )
 ControlNode::TravSpecificData::TravSpecificData() :
 _obscured   ( true ),
 _visibleTime( 0.0 ),
-_screenPos  ( 0.0, 0.0, 0.0 )
+_screenPos  ( 0.0, 0.0, 0.0 ),
+_visitFrame(0)
 {
     //nop
 }
@@ -2421,18 +2447,25 @@ ControlNodeBin::draw( const ControlContext& context, bool newContext, int bin )
 
     if ( _sortingEnabled && _sortByDistance )
     {
-        for( ControlNodeCollection::iterator i = _controlNodes.begin(); i != _controlNodes.end(); i++) 
+        for( ControlNodeCollection::iterator i = _controlNodes.begin(); i != _controlNodes.end();)
         {
             ControlNode* node = i->second.get();
             if ( node->getNumParents() == 0 )
             {
+              // Save the iterator and erase it before we increment it.  erase will invalidate i so we can't increment it directly.
+              ControlNodeCollection::iterator saveItr = i;
+              ++saveItr;
               _renderNodes.erase( node );
+              // Erase the current iterator
               _controlNodes.erase( i );
+              // Assign i to the incremented iterator
+              i = saveItr;
             }
             else
             {
                 ControlNode::TravSpecificData& nodeData = node->getData( context._view->getCamera() );
                 byDepth.insert( ControlNodePair(nodeData._screenPos.z(), node) );
+                i++;
             }
         }
 
@@ -2879,6 +2912,7 @@ ControlCanvas::traverse(osg::NodeVisitor& nv)
         }
         break;
 
+    default:
     case osg::NodeVisitor::CULL_VISITOR:
         {
         }
diff --git a/src/osgEarthUtil/DataScanner b/src/osgEarthUtil/DataScanner
index 4133373..2bbc0b5 100644
--- a/src/osgEarthUtil/DataScanner
+++ b/src/osgEarthUtil/DataScanner
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthUtil/DataScanner.cpp b/src/osgEarthUtil/DataScanner.cpp
index 00cfbd9..710ad07 100644
--- a/src/osgEarthUtil/DataScanner.cpp
+++ b/src/osgEarthUtil/DataScanner.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthUtil/EarthManipulator b/src/osgEarthUtil/EarthManipulator
index a4748ce..d56ddd5 100644
--- a/src/osgEarthUtil/EarthManipulator
+++ b/src/osgEarthUtil/EarthManipulator
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -27,6 +27,7 @@
 #include <osgEarth/Terrain>
 #include <osgEarth/MapNode>
 #include <osg/Timer>
+#include <osg/ArgumentParser>
 #include <osgGA/CameraManipulator>
 #include <map>
 #include <list>
@@ -36,11 +37,11 @@ namespace osgEarth { namespace Util
 {
     using namespace osgEarth;
 
-    /** 
+    /**
      * A programmable manipulator suitable for use with geospatial terrains.
      *
      * You can use the "Settings" class to define custom input device bindings
-     * and navigation parameters. Create one or more of these and call 
+     * and navigation parameters. Create one or more of these and call
      * applySettings() to "program" the manipulator at runtime.
      */
     class OSGEARTHUTIL_EXPORT EarthManipulator : public osgGA::CameraManipulator
@@ -92,7 +93,7 @@ namespace osgEarth { namespace Util
 
         /** Action options. Certain options are only meaningful to certain Actions.
             See the bind* documentation for information. */
-        enum ActionOptionType {            
+        enum ActionOptionType {
             OPTION_SCALE_X,             // Sensitivity multiplier for horizontal input movements
             OPTION_SCALE_Y,             // Sensitivity multiplier for vertical input movements
             OPTION_CONTINUOUS,          // Whether to act as long as the button or key is depressed
@@ -143,7 +144,7 @@ namespace osgEarth { namespace Util
         };
 
     protected:
-        struct InputSpec 
+        struct InputSpec
         {
             InputSpec( int event_type, int input_mask, int modkey_mask )
                 : _event_type(event_type), _input_mask(input_mask), _modkey_mask( modkey_mask ) { }
@@ -151,8 +152,8 @@ namespace osgEarth { namespace Util
                 : _event_type(rhs._event_type), _input_mask(rhs._input_mask), _modkey_mask(rhs._modkey_mask) { }
 
             bool operator == ( const InputSpec& rhs ) const {
-                return _event_type == rhs._event_type && 
-                       _input_mask == rhs._input_mask && 
+                return _event_type == rhs._event_type &&
+                       _input_mask == rhs._input_mask &&
                        ((_modkey_mask|osgGA::GUIEventAdapter::MODKEY_NUM_LOCK) == (rhs._modkey_mask|osgGA::GUIEventAdapter::MODKEY_NUM_LOCK));
             }
 
@@ -194,7 +195,7 @@ namespace osgEarth { namespace Util
         };
 
         void dumpActionInfo( const Action& action, osg::NotifySeverity level ) const;
-        
+
         static Action NullAction;
 
     public:
@@ -211,6 +212,9 @@ namespace osgEarth { namespace Util
             /** dtor */
             virtual ~Settings() { }
 
+            // look for settings in an AP
+            void apply(osg::ArgumentParser& args);
+
             /**
              * Assigns behavior to the action of dragging the mouse while depressing one or
              * more mouse buttons and modifier keys.
@@ -223,13 +227,13 @@ namespace osgEarth { namespace Util
              *      Mask of osgGA::GUIEventAdapter::MouseButtonMask values
              *
              * @param modkey_mask (default = 0L)
-             *      A mask of osgGA::GUIEventAdapter::ModKeyMask values defining a modifier key 
+             *      A mask of osgGA::GUIEventAdapter::ModKeyMask values defining a modifier key
              *      combination to associate with the action.
              *
              * @param options
              *      Action options. Valid options are:
              *      OPTION_CONTINUOUS, OPTION_SCALE_X, OPTION_SCALE_Y
-             */             
+             */
             void bindMouse(
                 ActionType action, int button_mask,
                 int modkey_mask = 0L,
@@ -246,7 +250,7 @@ namespace osgEarth { namespace Util
              *      Mask of osgGA::GUIEventAdapter::MouseButtonMask values
              *
              * @param modkey_mask (default = 0L)
-             *      A mask of osgGA::GUIEventAdapter::ModKeyMask values defining a modifier key 
+             *      A mask of osgGA::GUIEventAdapter::ModKeyMask values defining a modifier key
              *      combination to associate with the action.
              *
              * @param options
@@ -269,7 +273,7 @@ namespace osgEarth { namespace Util
              *      Mask of osgGA::GUIEventAdapter::MouseButtonMask values
              *
              * @param modkey_mask (default = 0L)
-             *      A mask of osgGA::GUIEventAdapter::ModKeyMask values defining a modifier key 
+             *      A mask of osgGA::GUIEventAdapter::ModKeyMask values defining a modifier key
              *      combination to associate with the action.
              *
              * @param options
@@ -292,7 +296,7 @@ namespace osgEarth { namespace Util
              *      A osgGA::GUIEventAdapter::KeySymbol value
              *
              * @param modkey_mask (default = 0L)
-             *      A mask of osgGA::GUIEventAdapter::ModKeyMask values defining a modifier key 
+             *      A mask of osgGA::GUIEventAdapter::ModKeyMask values defining a modifier key
              *      combination to associate with the action.
              *
              * @param options
@@ -303,7 +307,7 @@ namespace osgEarth { namespace Util
                 ActionType action, int key,
                 int modkey_mask =0L,
                 const ActionOptions& options =ActionOptions() );
-            
+
             /**
              * Assigns a bevahior to operation of the mouse's scroll wheel.
              *
@@ -315,7 +319,7 @@ namespace osgEarth { namespace Util
              *      A osgGA::GUIEventAdapter::ScrollingMotion value
              *
              * @param modkey_mask (default = 0L)
-             *      A mask of osgGA::GUIEventAdapter::ModKeyMask values defining a modifier key 
+             *      A mask of osgGA::GUIEventAdapter::ModKeyMask values defining a modifier key
              *      combination to associate with the action.
              *
              * @param options
@@ -330,11 +334,11 @@ namespace osgEarth { namespace Util
 
             void bindPinch(
                 ActionType action, const ActionOptions& =ActionOptions() );
-                
+
             void bindTwist(
                 ActionType action, const ActionOptions& =ActionOptions() );
 
-   
+
             void bindMultiDrag(
                 ActionType action, const ActionOptions& =ActionOptions() );
 
@@ -351,7 +355,7 @@ namespace osgEarth { namespace Util
              * Gets the overall mouse sensitivity scale factor. Default = 1.0.
              */
             double getMouseSensitivity() const { return _mouse_sens; }
-            
+
             /**
              * Sets an overall touch sensitivity factor.
              *
@@ -386,7 +390,7 @@ namespace osgEarth { namespace Util
             /**
              * Sets the scroll-wheel sensitivity factor. This applies to navigation actions
              * that are bound to scrolling events. For example, you may bind the scroll wheel to
-             * the ACTION_ZOOM_IN action; this factor adjusts how much zooming will occur each time 
+             * the ACTION_ZOOM_IN action; this factor adjusts how much zooming will occur each time
              * you click the scroll wheel.
              *
              * @param value
@@ -400,8 +404,8 @@ namespace osgEarth { namespace Util
              */
             double getScrollSensitivity() const { return _scroll_sens; }
 
-            /** 
-             * When set to true, prevents simultaneous control of pitch and azimuth. 
+            /**
+             * When set to true, prevents simultaneous control of pitch and azimuth.
              *
              * Usually you can alter pitch and azimuth at the same time. When this flag
              * is set, you can only control one at a time - if you start slewing the azimuth of the camera,
@@ -411,7 +415,7 @@ namespace osgEarth { namespace Util
              */
             void setSingleAxisRotation( bool value ) { _single_axis_rotation = value; }
 
-            /** 
+            /**
              * Gets whether simultaneous control over pitch and azimuth is disabled.
              * Default = false.
              */
@@ -443,21 +447,21 @@ namespace osgEarth { namespace Util
             double getMinPitch() const { return _min_pitch; }
 
             /** Gets the maximum allowable local pitch, in degrees. */
-            double getMaxPitch() const { return _max_pitch; }        
+            double getMaxPitch() const { return _max_pitch; }
 
-            /** Gets the max x offset in world coordates */
+            /** Gets the max x offset in world coordinates */
             double getMaxXOffset() const { return _max_x_offset; }
 
-            /** Gets the max y offset in world coordates */
+            /** Gets the max y offset in world coordinates */
             double getMaxYOffset() const { return _max_y_offset; }
 
             /** Gets the minimum distance from the focal point in world coordinates */
             double getMinDistance() const {return _min_distance; }
-            
+
             /** Gets the maximum distance from the focal point in world coordinates */
             double getMaxDistance() const {return _max_distance; }
 
-            /** Sets the min and max distance from the focal point in world coordiantes */
+            /** Sets the min and max distance from the focal point in world coordinates */
             void setMinMaxDistance( double min_distance, double max_distance);
 
             /**
@@ -494,8 +498,8 @@ namespace osgEarth { namespace Util
 
             /** Frustum offset (in pixels) */
             void setCameraFrustumOffsets( const osg::Vec2s& offsets );
-            const osg::Vec2s& getCameraFrustumOffsets() const { return _camFrustOffsets; }     
-#endif       
+            const osg::Vec2s& getCameraFrustumOffsets() const { return _camFrustOffsets; }
+#endif
 
             /** Whether to automatically adjust an orthographic camera so that it "tracks" the last known FOV and Aspect Ratio. */
             bool getOrthoTracksPerspective() const { return _orthoTracksPerspective; }
@@ -505,9 +509,13 @@ namespace osgEarth { namespace Util
             bool getTerrainAvoidanceEnabled() const { return _terrainAvoidanceEnabled; }
             void setTerrainAvoidanceEnabled( bool value ) { _terrainAvoidanceEnabled = value; }
 
+            /** Minimum range for terrain avoidance checks in world coordinates */
+            double getTerrainAvoidanceMinimumDistance() const {return _terrainAvoidanceMinDistance; }
+            void setTerrainAvoidanceMinimumDistance(double minDistance) { _terrainAvoidanceMinDistance = minDistance; }
+
             void setThrowingEnabled(bool throwingEnabled) { _throwingEnabled = throwingEnabled; }
             bool getThrowingEnabled () const { return _throwingEnabled; }
-            
+
             void setThrowDecayRate(double throwDecayRate) { _throwDecayRate = osg::clampBetween(throwDecayRate, 0.0, 1.0); }
             double getThrowDecayRate () const { return _throwDecayRate; }
 
@@ -552,6 +560,7 @@ namespace osgEarth { namespace Util
             bool _orthoTracksPerspective;
 
             bool _terrainAvoidanceEnabled;
+            double _terrainAvoidanceMinDistance;
 
             bool _throwingEnabled;
             double _throwDecayRate;
@@ -559,7 +568,8 @@ namespace osgEarth { namespace Util
 
     public:
         EarthManipulator();
-        EarthManipulator( const EarthManipulator& rhs );
+        EarthManipulator(osg::ArgumentParser& args);
+        EarthManipulator(const EarthManipulator& rhs);
 
         /**
          * Applies a new settings object to the manipulator, which takes effect immediately.
@@ -574,13 +584,13 @@ namespace osgEarth { namespace Util
         /**
          * Gets the current camera position.
          */
-        Viewpoint getViewpoint() const;        
+        Viewpoint getViewpoint() const;
 
         /**
          * Sets the camera position, optionally moving it there over time.
          */
         virtual void setViewpoint( const Viewpoint& vp, double duration_s =0.0 );
-        
+
         /**
          * @deprecated Please use clearViewpoint() instead.
          *
@@ -622,11 +632,11 @@ namespace osgEarth { namespace Util
          *      The duration that the camera should transition when tethering to the node.
          */
         void setTetherNode(osg::Node* node, double duration_s =0.0);
-        
+
         /**
          * @deprecated Please use setViewpoint() instead.
          *
-         * Same as setTether(node, duration) but you also specify the final 
+         * Same as setTether(node, duration) but you also specify the final
          * heading, pitch, and range offset from the tethered node.
          */
         void setTetherNode(
@@ -680,7 +690,7 @@ namespace osgEarth { namespace Util
          * Drag the earth using deltas
          */
         virtual void drag( double dx, double dy, osg::View* view);
-        
+
         /**
          * Converts screen coordinates (relative to the view's viewpoint) to world
          * coordinates. Note, this method will use the mask set by setTraversalMask().
@@ -722,15 +732,15 @@ namespace osgEarth { namespace Util
         osg::Node::NodeMask getFindNodeTraversalMask( ) { return _findNodeTraversalMask; }
 
         /**
-         * Sets the traversal node mask used to find root MapNode and CoordinateSystemNode. Default is 0x1. 
-         * Use this method if you change MapNode or CoordinateSystemNode mask and want manipulator to work with them correctly.  
+         * Sets the traversal node mask used to find root MapNode and CoordinateSystemNode. Default is 0x1.
+         * Use this method if you change MapNode or CoordinateSystemNode mask and want manipulator to work with them correctly.
          */
         void  setFindNodeTraversalMask( const osg::Node::NodeMask & nodeMask ) { _findNodeTraversalMask = nodeMask; }
 
     public: // osgGA::CameraManipulator
 
         virtual const char* className() const { return "EarthManipulator"; }
-        
+
         /** set the position of the matrix manipulator using a 4x4 Matrix.*/
         virtual void setByMatrix(const osg::Matrixd& matrix);
 
@@ -743,6 +753,10 @@ namespace osgEarth { namespace Util
         /** get the position of the manipulator as a inverse matrix of the manipulator, typically used as a model view matrix.*/
         virtual osg::Matrixd getInverseMatrix() const;
 
+        /** update the camera with the current values from this manipulator. Overloaded to support tethering, this method is
+            called by Viewer or ComppositeViewer at the end of the udpate traversal. */
+        virtual void updateCamera(osg::Camera& camera);
+
         // Gets the stereo convergance mode.
         virtual osgUtil::SceneView::FusionDistanceMode getFusionDistanceMode() const { return osgUtil::SceneView::USE_FUSION_DISTANCE_VALUE; }
 
@@ -758,7 +772,7 @@ namespace osgEarth { namespace Util
         // Move the camera to the default position.
         virtual void home(double /*unused*/);
         virtual void home(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& us);
-        
+
         // Start/restart the manipulator.
         virtual void init(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& us);
 
@@ -769,7 +783,7 @@ namespace osgEarth { namespace Util
         virtual void getUsage(osg::ApplicationUsage& usage) const;
 
         virtual void computeHomePosition();
-        
+
         // react to a tile-added event from the Terrain
         virtual void handleTileAdded(const TileKey& key, osg::Node* tile, TerrainCallbackContext& context);
 
@@ -779,7 +793,7 @@ namespace osgEarth { namespace Util
     protected:
 
         virtual ~EarthManipulator();
-        
+
         bool intersect(const osg::Vec3d& start, const osg::Vec3d& end, osg::Vec3d& intersection, osg::Vec3d& normal) const;
 
         bool intersectLookVector(osg::Vec3d& eye, osg::Vec3d& out_target, osg::Vec3d& up) const;
@@ -858,7 +872,7 @@ namespace osgEarth { namespace Util
         void updateHandCam( const osg::Timer_t& now );
 
         bool isMouseClick( const osgGA::GUIEventAdapter* mouse_up_event ) const;
-        
+
         void applyOptionsToDeltas( const Action& action, double& dx, double& dy );
 
         void configureDefaultSettings();
@@ -877,7 +891,7 @@ namespace osgEarth { namespace Util
         ActionType getActionTypeForEvent( const osgGA::GUIEventAdapter& ea ) const;
 
     public:
-            
+
         void recalculateCenter() { recalculateCenter(_centerLocalToWorld); }
 
         const GeoPoint& centerMap() const { return _centerMap; }
@@ -929,8 +943,8 @@ namespace osgEarth { namespace Util
         osg::ref_ptr<const osgEarth::SpatialReference> _srs;
 
         double                  _time_s_last_frame;
-        double                  _time_s_now;        
-        double                  _delta_t;        
+        double                  _time_s_now;
+        double                  _delta_t;
         bool                    _thrown;
         double                  _throw_dx;
         double                  _throw_dy;
@@ -1011,42 +1025,24 @@ namespace osgEarth { namespace Util
 
         unsigned _frameCount;
 
-        osg::ref_ptr<Settings> _settings;		
+        osg::ref_ptr<Settings> _settings;
 
         osgEarth::optional<Viewpoint> _homeViewpoint;
         double _homeViewpointDuration;
 
         Action _last_action;
-        
+
         EventType _last_event;
         double    _time_s_last_event;
-        
 
-        // to support updating the camera after the update traversal (e.g., for tethering)
-        osg::observer_ptr<osg::Camera> _viewCamera;
         double _vfov;
-        double _tanHalfVFOV;
-        optional<osg::CullSettings::ComputeNearFarMode> _savedCNFMode;
-        Revision _viewCameraSettingsMonitor;
-        
-        struct CameraPostUpdateCallback : public osg::NodeCallback {
-            CameraPostUpdateCallback(EarthManipulator* m) : _m(m) { }
-            virtual void operator()(osg::Node* node, osg::NodeVisitor* nv) { 
-                osg::ref_ptr<EarthManipulator> m;
-                if ( _m.lock(m) ) m->postUpdate();
-                traverse(node,nv);
-            }
-            osg::observer_ptr<EarthManipulator> _m;
-        };
-        void postUpdate();
-        friend struct CameraUpdateCallback;
 
-        osg::observer_ptr<CameraPostUpdateCallback> _cameraUpdateCB;
+        /** updates a camera to switch between prospective and ortho. */
+        void updateProjection( osg::Camera* eventCamera );
 
-        void updateCamera( osg::Camera* eventCamera );
         // Support snappy transition when the pointer leaves and
         // returns to earth during a drag
-        osg::Vec3d               _lastPointOnEarth;
+        osg::Vec3d _lastPointOnEarth;
 
 
         osg::ref_ptr< TerrainCallback > _terrainCallback;
@@ -1057,6 +1053,8 @@ namespace osgEarth { namespace Util
         osg::ref_ptr<TetherCallback> _tetherCallback;
 
         void collisionDetect();
+
+        void ctor_init();
     };
 
 } } // namespace osgEarth::Util
diff --git a/src/osgEarthUtil/EarthManipulator.cpp b/src/osgEarthUtil/EarthManipulator.cpp
index 215ee06..b4c8f95 100644
--- a/src/osgEarthUtil/EarthManipulator.cpp
+++ b/src/osgEarthUtil/EarthManipulator.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -20,6 +20,7 @@
 #include <osgEarth/MapNode>
 #include <osgEarth/NodeUtils>
 #include <osgEarth/GeoMath>
+#include <osgEarth/TerrainEngineNode>
 #include <osg/Quat>
 #include <osg/Notify>
 #include <osg/MatrixTransform>
@@ -119,7 +120,7 @@ namespace
             if ( _manip.lock(safe) )
             {
                 safe->handleTileAdded(key, tile, context);
-            }            
+            }
         }
         osg::observer_ptr<EarthManipulator> _manip;
     };
@@ -130,7 +131,7 @@ namespace
 EarthManipulator::Action::Action( ActionType type, const ActionOptions& options ) :
 _type( type ),
 _options( options )
-{ 
+{
     init();
 }
 
@@ -159,7 +160,7 @@ _options( rhs._options )
     //nop
 }
 
-bool 
+bool
 EarthManipulator::Action::getBoolOption( int option, bool defaultValue ) const
 {
     for(ActionOptions::const_iterator i = _options.begin(); i != _options.end(); i++ ) {
@@ -169,7 +170,7 @@ EarthManipulator::Action::getBoolOption( int option, bool defaultValue ) const
     return defaultValue;
 }
 
-int 
+int
 EarthManipulator::Action::getIntOption( int option, int defaultValue ) const
 {
     for(ActionOptions::const_iterator i = _options.begin(); i != _options.end(); i++ ) {
@@ -179,7 +180,7 @@ EarthManipulator::Action::getIntOption( int option, int defaultValue ) const
     return defaultValue;
 }
 
-double 
+double
 EarthManipulator::Action::getDoubleOption( int option, double defaultValue ) const
 {
     for(ActionOptions::const_iterator i = _options.begin(); i != _options.end(); i++ ) {
@@ -247,8 +248,9 @@ _auto_vp_duration               ( false ),
 _min_vp_duration_s              ( 3.0 ),
 _max_vp_duration_s              ( 8.0 ),
 _orthoTracksPerspective         ( true ),
-_throwingEnabled                ( false ),
 _terrainAvoidanceEnabled        ( true ),
+_terrainAvoidanceMinDistance    ( 1.0 ),
+_throwingEnabled                ( false ),
 _throwDecayRate                 ( 0.05 )
 {
     //NOP
@@ -278,12 +280,33 @@ _max_vp_duration_s( rhs._max_vp_duration_s ),
 _orthoTracksPerspective( rhs._orthoTracksPerspective ),
 _breakTetherActions( rhs._breakTetherActions ),
 _terrainAvoidanceEnabled( rhs._terrainAvoidanceEnabled ),
+_terrainAvoidanceMinDistance( rhs._terrainAvoidanceMinDistance ),
 _throwingEnabled( rhs._throwingEnabled ),
 _throwDecayRate( rhs._throwDecayRate )
 {
     //NOP
 }
 
+void
+EarthManipulator::Settings::apply(osg::ArgumentParser& args)
+{
+    bool   boolval;
+    double doubleval;
+
+    if ( args.read("--manip-terrain-avoidance", boolval) )
+        setTerrainAvoidanceEnabled( boolval );
+    if ( args.read("--manip-terrain-avoidance-min-distance", doubleval) )
+        setTerrainAvoidanceMinimumDistance( doubleval );
+    if ( args.read("--manip-min-distance", doubleval) )
+        setMinMaxDistance(doubleval, _max_distance);
+    if ( args.read("--manip-max-distance", doubleval) )
+        setMinMaxDistance(_min_distance, doubleval);
+    if ( args.read("--manip-min-pitch", doubleval) )
+        setMinMaxPitch(doubleval, _max_pitch);
+    if ( args.read("--manip-max-pitch", doubleval) )
+        setMinMaxPitch(_min_pitch, doubleval);
+}
+
 #define HASMODKEY( W, V ) (( W & V ) == V )
 
 // expands one input spec into many if necessary, to deal with modifier key combos.
@@ -413,7 +436,7 @@ const EarthManipulator::Action&
 EarthManipulator::Settings::getAction(int event_type, int input_mask, int modkey_mask) const
 {
     //Build the input spec but remove the numlock and caps lock from the modkey mask.  On Linux these seem to be passed in as part of the modkeymask
-    //if they are on.  So if you bind an action like SCROLL to a modkey mask of 0 or a modkey mask of ctrl it will never match the spec exactly b/c 
+    //if they are on.  So if you bind an action like SCROLL to a modkey mask of 0 or a modkey mask of ctrl it will never match the spec exactly b/c
     //the modkey mask also includes capslock and numlock.
     InputSpec spec( event_type, input_mask, modkey_mask & ~osgGA::GUIEventAdapter::MODKEY_NUM_LOCK & ~osgGA::GUIEventAdapter::MODKEY_CAPS_LOCK);
     ActionBindings::const_iterator i = _bindings.find(spec);
@@ -468,25 +491,56 @@ EarthManipulator::Settings::setAutoViewpointDurationLimits( double minSeconds, d
 
 /************************************************************************/
 
+void
+EarthManipulator::ctor_init()
+{
+    _last_action = ACTION_NULL;
+    _last_event = EVENT_MOUSE_DOUBLE_CLICK;
+    _time_s_last_event = 0.0;
+    _frameCount = 0;
+    _findNodeTraversalMask = 0x01;
+    _time_s_last_frame = 0.0;
+    _time_s_now = 0.0;
+    _centerHeight = 0.0;
+    _time_last_frame = 0.0;
+    _continuous_dx = 0;
+    _continuous_dy = 0;
+    _last_continuous_action_time = 0.0;
+    _single_axis_x = 0;
+    _single_axis_y = 0;
+    _setVPAccel = 0;
+    _setVPAccel2 = 0;
+    _lastTetherMode = TETHER_CENTER;
+    _homeViewpointDuration = 0;
+}
 
 EarthManipulator::EarthManipulator() :
-osgGA::CameraManipulator(),
-_last_action           ( ACTION_NULL ),
-_last_event            ( EVENT_MOUSE_DOUBLE_CLICK ),
-_time_s_last_event     ( 0.0 ),
-_frameCount            ( 0 ),
-_findNodeTraversalMask ( 0x01 )
+osgGA::CameraManipulator()
+{
+    ctor_init();
+    reinitialize();
+    configureDefaultSettings();
+    if (_settings.valid())
+        _lastTetherMode = _settings->getTetherMode();
+}
+
+EarthManipulator::EarthManipulator(osg::ArgumentParser& args) :
+osgGA::CameraManipulator()
 {
+    ctor_init();
     reinitialize();
     configureDefaultSettings();
-    _lastTetherMode = _settings->getTetherMode();
+    if (_settings.valid())
+        _lastTetherMode = _settings->getTetherMode();
+
+    getSettings()->apply( args );
 }
 
 EarthManipulator::EarthManipulator( const EarthManipulator& rhs ) :
 osgGA::CameraManipulator( rhs ),
 _last_action            ( ACTION_NULL ),
 _last_event             ( EVENT_MOUSE_DOUBLE_CLICK ),
-_time_s_last_event      (0.0),
+_time_s_last_event      ( 0.0 ),
 _frameCount             ( 0 ),
 _settings               ( new Settings(*rhs.getSettings()) ),
 _findNodeTraversalMask  ( rhs._findNodeTraversalMask )
@@ -498,10 +552,10 @@ _findNodeTraversalMask  ( rhs._findNodeTraversalMask )
 EarthManipulator::~EarthManipulator()
 {
     osg::ref_ptr<MapNode> mapNode = _mapNode;
-    if (mapNode.valid() && _terrainCallback)
+    if (mapNode.valid() && _terrainCallback && mapNode->getTerrain())
     {
         mapNode->getTerrain()->removeTerrainCallback( _terrainCallback );
-    }    
+    }
 }
 
 void
@@ -612,14 +666,13 @@ EarthManipulator::reinitialize()
     _last_action = ACTION_NULL;
     _srs = 0L;
     //_setting_viewpoint = false;
-    _delta_t = 0.0;    
+    _delta_t = 0.0;
     _pendingViewpoint.unset();
     _setVP0.unset();
     _setVP1.unset();
     _lastPointOnEarth.set(0.0, 0.0, 0.0);
     _setVPArcHeight = 0.0;
     _vfov = 30.0;
-    _tanHalfVFOV = tan(0.5*osg::DegreesToRadians(_vfov));
 }
 
 
@@ -640,12 +693,13 @@ EarthManipulator::established()
         return false;
 
     // resetablish the terrain callback on the map node:
-    if ( _terrainCallback.valid() )
+    if ( _terrainCallback.valid() && _mapNode->getTerrain() )
     {
         _mapNode->getTerrain()->removeTerrainCallback( _terrainCallback.get() );
     }
     _terrainCallback = new ManipTerrainCallback( this );
-    _mapNode->getTerrain()->addTerrainCallback( _terrainCallback ); 
+    if (_mapNode->getTerrain())
+        _mapNode->getTerrain()->addTerrainCallback( _terrainCallback );
 
     // Cache the SRS.
     _srs = _mapNode->getMapSRS();
@@ -668,7 +722,7 @@ EarthManipulator::established()
             vp.positionOffset()->set(0,0,0);
             setHomeViewpoint( vp );
         }
-        else 
+        else
         {
             Viewpoint vp;
             vp.focalPoint() = GeoPoint(_srs.get(), safeNode->getBound().center(), ALTMODE_ABSOLUTE);
@@ -696,11 +750,11 @@ EarthManipulator::established()
 }
 
 
-void 
+void
 EarthManipulator::handleTileAdded(const TileKey& key, osg::Node* tile, TerrainCallbackContext& context)
 {
     // Only do collision avoidance if it's enabled, we're not tethering and
-    // we're not in the middle of setting a viewpoint.            
+    // we're not in the middle of setting a viewpoint.
     if (getSettings()->getTerrainAvoidanceEnabled() &&
         !isTethering() &&
         !isSettingViewpoint() )
@@ -720,7 +774,7 @@ EarthManipulator::createLocalCoordFrame( const osg::Vec3d& worldPos, osg::Coordi
     if ( _srs.valid() )
     {
         osg::Vec3d mapPos;
-        _srs->transformFromWorld( worldPos, mapPos ); 
+        _srs->transformFromWorld( worldPos, mapPos );
         _srs->createLocalToWorld( mapPos, out_frame );
     }
     return _srs.valid();
@@ -755,14 +809,6 @@ EarthManipulator::setNode(osg::Node* node)
         _mapNode = 0L;
         _srs     = 0L;
 
-        if ( _viewCamera.valid() && _cameraUpdateCB.valid() )
-        {
-            _viewCamera->removeUpdateCallback( _cameraUpdateCB.get() );
-            _cameraUpdateCB = 0L;
-        }
-
-        _viewCamera = 0L;
-
         reinitialize();
         established();
     }
@@ -829,7 +875,7 @@ EarthManipulator::getViewpoint() const
     {
         vp.focalPoint()->fromWorld( _srs.get(), _center );
     }
-    
+
     // If we are stationary:
     else
     {
@@ -882,14 +928,9 @@ EarthManipulator::setViewpoint(const Viewpoint& vp, double duration_seconds)
         // ending viewpoint
         _setVP1 = vp;
 
-        // If we're no longer going to be tethering, reset the tethering offset quat.
-        //if ( !_setVP1->nodeIsSet() )
-        {
-            //_tetherRotationOffset.unset();
-            //_tetherRotation = osg::Quat();
-            _tetherRotationVP0 = _tetherRotation;
-            _tetherRotationVP1 = osg::Quat();
-        }
+        // Reset the tethering offset quat.
+        _tetherRotationVP0 = _tetherRotation;
+        _tetherRotationVP1 = osg::Quat();
 
         // Fill in any missing end-point data with defaults matching the current camera setup.
         // Then all fields are guaranteed to contain usable data during transition.
@@ -919,7 +960,7 @@ EarthManipulator::setViewpoint(const Viewpoint& vp, double duration_seconds)
         OE_DEBUG << LC << "setViewpoint:\n"
             << "    from " << _setVP0->toString() << "\n"
             << "    to   " << _setVP1->toString() << "\n";
-        
+
         // access the new tether node if it exists:
         osg::ref_ptr<osg::Node> endNode;
         _setVP1->getNode(endNode);
@@ -958,7 +999,7 @@ EarthManipulator::setViewpoint(const Viewpoint& vp, double duration_seconds)
 
             // maximum height during viewpoint transition
             if ( _settings->getArcViewpointTransitions() )
-            {         
+            {
                 _setVPArcHeight = osg::maximum( de - fabs(dh), 0.0 );
             }
 
@@ -1047,7 +1088,7 @@ EarthManipulator::setViewpointFrame(double time_s)
         // Remaining time is the full duration minus the time since initiation:
         double elapsed = time_s - _setVPStartTime->as(Units::SECONDS);
         double t = std::min(1.0, elapsed / _setVPDuration.as(Units::SECONDS));
-        
+
         double tp = t;
 
         if ( _setVPArcHeight > 0.0 )
@@ -1063,7 +1104,7 @@ EarthManipulator::setViewpointFrame(double time_s)
                 tp = 0.5+(0.5*t2);
             }
 
-            // the more smoothsteps you do, the more pronounced the fade-in/out effect        
+            // the more smoothsteps you do, the more pronounced the fade-in/out effect
             tp = smoothStepInterp( tp );
         }
         else if ( t > 0.0 )
@@ -1081,7 +1122,7 @@ EarthManipulator::setViewpointFrame(double time_s)
         else if ( d_azim.as(Units::RADIANS) < -osg::PI )
             d_azim = d_azim + Angle(2.0*osg::PI, Units::RADIANS);
         double newAzim = _setVP0->heading()->as(Units::RADIANS) + tp*d_azim.as(Units::RADIANS);
-             
+
         // Calculate the new pitch:
         Angle d_pitch = _setVP1->pitch().get() - _setVP0->pitch().get();
         double newPitch = _setVP0->pitch()->as(Units::RADIANS) + tp*d_pitch.as(Units::RADIANS);
@@ -1105,7 +1146,7 @@ EarthManipulator::setViewpointFrame(double time_s)
 
         // At t=1 the transition is complete.
         if ( t >= 1.0 )
-        {            
+        {
             _setVP0.unset();
 
             // If this was a transition into a tether, keep the endpoint around so we can
@@ -1115,7 +1156,7 @@ EarthManipulator::setViewpointFrame(double time_s)
                 _setVP1.unset();
             }
         }
-    
+
         return tp;
     }
 }
@@ -1157,7 +1198,7 @@ EarthManipulator::resetLookAt()
 
     osg::Vec3d eye = getMatrix().getTrans();
 
-    // calculate the center point in front of the eye. The reference frame here 
+    // calculate the center point in front of the eye. The reference frame here
     // is the view plane of the camera.
     osg::Matrix m( _rotation * _centerRotation );
     recalculateCenter( m );
@@ -1276,9 +1317,10 @@ void EarthManipulator::collisionDetect()
     // Try to intersect the terrain with a vector going straight up and down.
     double r = std::min( _srs->getEllipsoid()->getRadiusEquator(), _srs->getEllipsoid()->getRadiusPolar() );
     osg::Vec3d ip, normal;
+
     if (intersect(eye + eyeUp * r, eye - eyeUp * r, ip, normal))
     {
-        double eps = _settings->getMinDistance();
+        double eps = _settings->getTerrainAvoidanceMinimumDistance();
         // Now determine if the point is above the ground or not
         osg::Vec3d v0 = eyeUp;
         v0.normalize();
@@ -1291,6 +1333,8 @@ void EarthManipulator::collisionDetect()
         {
             setByLookAtRaw(ip + adjVector * eps, _center, eyeUp);
         }
+
+        //OE_INFO << "hit at " << ip.x() << ", " << ip.y() << ", " << ip.z() << "\n";
     }
 
 }
@@ -1300,7 +1344,7 @@ bool
 EarthManipulator::intersect(const osg::Vec3d& start, const osg::Vec3d& end, osg::Vec3d& intersection, osg::Vec3d& normal) const
 {
     osg::ref_ptr<MapNode> mapNode;
-    if ( _mapNode.lock(mapNode) )
+    if ( _mapNode.lock(mapNode) && mapNode->getTerrainEngine() )
     {
 		osg::ref_ptr<osgUtil::LineSegmentIntersector> lsi = NULL;
 
@@ -1309,7 +1353,6 @@ EarthManipulator::intersect(const osg::Vec3d& start, const osg::Vec3d& end, osg:
         osgUtil::IntersectionVisitor iv(lsi.get());
         iv.setTraversalMask(_intersectTraversalMask);
 
-        //safeNode->accept(iv);
         mapNode->getTerrainEngine()->accept(iv);
 
         if (lsi->containsIntersections())
@@ -1328,9 +1371,9 @@ EarthManipulator::intersectLookVector(osg::Vec3d& out_eye,
                                       osg::Vec3d& out_up ) const
 {
     bool success = false;
-    
+
     osg::ref_ptr<MapNode> mapNode;
-    if ( _mapNode.lock(mapNode) )
+    if ( _mapNode.lock(mapNode) && mapNode->getTerrainEngine() )
     {
         double R = _centerHeight;
 
@@ -1342,7 +1385,7 @@ EarthManipulator::intersectLookVector(osg::Vec3d& out_eye,
 
         lsi->setIntersectionLimit(lsi->LIMIT_NEAREST);
 
-        osgUtil::IntersectionVisitor iv(lsi.get());        
+        osgUtil::IntersectionVisitor iv(lsi.get());
         iv.setTraversalMask(_intersectTraversalMask);
 
         mapNode->getTerrainEngine()->accept(iv);
@@ -1420,7 +1463,7 @@ EarthManipulator::home(const osgGA::GUIEventAdapter& ,osgGA::GUIActionAdapter& u
 
 void
 EarthManipulator::computeHomePosition()
-{    
+{
     if( getNode() )
     {
         const osg::BoundingSphere& boundingSphere = getNode()->getBound();
@@ -1454,7 +1497,7 @@ EarthManipulator::resetMouse( osgGA::GUIActionAdapter& aa, bool flushEventStack
 {
     if (flushEventStack)
       flushMouseEventStack();
-    
+
     aa.requestContinuousUpdate( false );
     _thrown = false;
     _continuous = false;
@@ -1464,9 +1507,6 @@ EarthManipulator::resetMouse( osgGA::GUIActionAdapter& aa, bool flushEventStack
 }
 
 
-// this method will automatically install or uninstall the camera post-update callback 
-// depending on whether there's a tether node.
-//
 // Camera updates get called AFTER the scene gets its update traversal. So, if you have
 // tethering enabled (or some other feature that tracks scene graph nodes), this will
 // update the camera after the scene graph. This is important in order to maintain
@@ -1476,50 +1516,24 @@ EarthManipulator::resetMouse( osgGA::GUIActionAdapter& aa, bool flushEventStack
 // support OSG's "ON_DEMAND" frame scheme, which disables itself is there are any
 // update callbacks in the scene graph.
 void
-EarthManipulator::updateCamera( osg::Camera* eventCamera )
+EarthManipulator::updateProjection(osg::Camera* eventCamera)
 {
-    // check to see if the camera has changed, and update the callback if necessary
-    if ( _viewCamera.get() != eventCamera )
-    {
-        if ( _cameraUpdateCB.valid() && _viewCamera.valid() )
-            _viewCamera->removeUpdateCallback( _cameraUpdateCB.get() );
-
-        _viewCamera = eventCamera;
-
-        if ( _cameraUpdateCB.valid() && _viewCamera.valid() )
-            _viewCamera->addUpdateCallback( _cameraUpdateCB.get() );
-    }
-
     // check to see if we need to install a new camera callback:
-    if ( _viewCamera.valid() )
+    if ( eventCamera )
     {
-        if ( isTethering() && !_cameraUpdateCB.valid() )
-        {
-            _cameraUpdateCB = new CameraPostUpdateCallback(this);
-            _viewCamera->addUpdateCallback( _cameraUpdateCB.get() );
-        }
-        else if ( !isTethering() && _cameraUpdateCB.valid() )
-        {
-            _viewCamera->removeUpdateCallback( _cameraUpdateCB.get() );
-            _cameraUpdateCB = 0L;
-        }
-
-        // check whether a settings change requires an update:
-        bool settingsChanged = _settings->outOfSyncWith(_viewCameraSettingsMonitor);
-
         // update the projection matrix if necessary
-        osg::Viewport* vp = _viewCamera->getViewport();
+        osg::Viewport* vp = eventCamera->getViewport();
         if ( vp )
         {
-            const osg::Matrixd& proj = _viewCamera->getProjectionMatrix();
+            const osg::Matrixd& proj = eventCamera->getProjectionMatrix();
             bool isOrtho = osg::equivalent(proj(3,3), 1.0);
 
-            // For a perspective camera, remember the last known VFOV. We will need it if we 
+            // For a perspective camera, remember the last known VFOV. We will need it if we
             // detect a switch to orthographic.
             if ( !isOrtho )
             {
                 double vfov, ar, zn, zf;
-                if (_viewCamera->getProjectionMatrixAsPerspective(vfov, ar, zn, zf))
+                if (eventCamera->getProjectionMatrixAsPerspective(vfov, ar, zn, zf))
                 {
                     _vfov = vfov;
                 }
@@ -1546,22 +1560,20 @@ EarthManipulator::updateCamera( osg::Camera* eventCamera )
 
                 double ignore, N, F;
                 proj.getOrtho(ignore, ignore, ignore, ignore, N, F);
-                _viewCamera->setProjectionMatrixAsOrtho( px-x, px+x, py-y, py+y, N, F);
+                eventCamera->setProjectionMatrixAsOrtho( px-x, px+x, py-y, py+y, N, F);
 #else
                 double ignore, N, F;
                 proj.getOrtho(ignore, ignore, ignore, ignore, N, F);
-                _viewCamera->setProjectionMatrixAsOrtho( -x, +x, -y, +y, N, F );
+                eventCamera->setProjectionMatrixAsOrtho( -x, +x, -y, +y, N, F );
 #endif
 
-                //OE_WARN << "ORTHO: "
-                //    << "ar = " << ar << ", width=" << vp->width() << ", height=" << vp->height()
-                //    << ", dist = " << _distance << ", vfov=" << _vfov
-                //    << ", X = " << x << ", Y = " << y
-                //    << std::endl;
+                OE_DEBUG << "ORTHO: "
+                    << "ar = " << ar << ", width=" << vp->width() << ", height=" << vp->height()
+                    << ", dist = " << _distance << ", vfov=" << _vfov
+                    << ", X = " << x << ", Y = " << y
+                    << std::endl;
             }
         }
-
-        _settings->sync( _viewCameraSettingsMonitor );
     }
 }
 
@@ -1570,14 +1582,14 @@ bool
 EarthManipulator::handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa)
 {
     bool handled = false;
-    
+
     // first order of business: make sure the CSN is established.
     if ( !established() )
         return false;
 
     // make sure the camera callback is up to date:
     osg::View* view = aa.asView();
-    updateCamera( view->getCamera() );
+    updateProjection( view->getCamera() );
 
     double time_s_now = osg::Timer::instance()->time_s();
 
@@ -1586,7 +1598,7 @@ EarthManipulator::handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapt
         _time_s_last_frame = _time_s_now;
         _time_s_now = time_s_now;
         _delta_t = _time_s_now - _time_s_last_frame;
-        
+
         if ( _node.valid() )
         {
             if ( _pendingViewpoint.isSet() )
@@ -1600,50 +1612,50 @@ EarthManipulator::handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapt
             {
                 if ( _frameCount < 2 )
                     _setVPStartTime->set(_time_s_now, Units::SECONDS);
-            
+
                 setViewpointFrame( time_s_now );
             }
 
-            aa.requestContinuousUpdate( isSettingViewpoint() );
-        }
+            if (_thrown)
+            {
+                double decayFactor = 1.0 - _settings->getThrowDecayRate();
 
-        else if (_thrown)
-        {
-            double decayFactor = 1.0 - _settings->getThrowDecayRate();
+                _throw_dx = osg::absolute(_throw_dx) > osg::absolute(_dx * 0.01) ? _throw_dx * decayFactor : 0.0;
+                _throw_dy = osg::absolute(_throw_dy) > osg::absolute(_dy * 0.01) ? _throw_dy * decayFactor : 0.0;
 
-            _throw_dx = osg::absolute(_throw_dx) > osg::absolute(_dx * 0.01) ? _throw_dx * decayFactor : 0.0;
-            _throw_dy = osg::absolute(_throw_dy) > osg::absolute(_dy * 0.01) ? _throw_dy * decayFactor : 0.0;
+                if (_throw_dx == 0.0 && _throw_dy == 0.0)
+                    _thrown = false;
+                else
+                    handleMovementAction(_last_action._type, _throw_dx, _throw_dy, aa.asView());
+            }
 
-            if (_throw_dx == 0.0 && _throw_dy == 0.0)
-                _thrown = false;
-            else            
-                handleMovementAction(_last_action._type, _throw_dx, _throw_dy, aa.asView());
-        }
+            aa.requestContinuousUpdate( isSettingViewpoint() || _thrown );
 
-        if ( _continuous )
-        {
-            handleContinuousAction( _last_action, aa.asView() );
-            aa.requestRedraw();
-        }
-        else
-        {
-            _continuous_dx = 0.0;
-            _continuous_dy = 0.0;
-        }
-        
-        if ( _task.valid() && _task->_type != TASK_NONE )
-        {
-            bool stillRunning = serviceTask();
-            if ( stillRunning ) 
+            if ( _continuous )
             {
-                aa.requestContinuousUpdate( true );
+                handleContinuousAction( _last_action, aa.asView() );
+                aa.requestRedraw();
             }
             else
             {
-                // turn off the continuous, but we still need one last redraw
-                // to process the final state.
-                aa.requestContinuousUpdate( false );
-                aa.requestRedraw();
+                _continuous_dx = 0.0;
+                _continuous_dy = 0.0;
+            }
+
+            if ( _task.valid() && _task->_type != TASK_NONE )
+            {
+                bool stillRunning = serviceTask();
+                if ( stillRunning )
+                {
+                    aa.requestContinuousUpdate( true );
+                }
+                else
+                {
+                    // turn off the continuous, but we still need one last redraw
+                    // to process the final state.
+                    aa.requestContinuousUpdate( false );
+                    aa.requestRedraw();
+                }
             }
         }
 
@@ -1659,11 +1671,11 @@ EarthManipulator::handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapt
     {
         return false;
     }
-   
+
     // form the current Action based on the event type:
     Action action = ACTION_NULL;
 
-    // if tethering is active, check to see whether the incoming event 
+    // if tethering is active, check to see whether the incoming event
     // will break the tether.
     if ( isTethering() )
     {
@@ -1683,7 +1695,7 @@ EarthManipulator::handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapt
     {
         // not a mouse event; clear the mouse queue.
         resetMouse( aa, false );
-        
+
         // queue up a touch event set and figure out the current state:
         addTouchEvents(ea);
         TouchEvents te;
@@ -1692,36 +1704,36 @@ EarthManipulator::handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapt
             for( TouchEvents::iterator i = te.begin(); i != te.end(); ++i )
             {
                 action = _settings->getAction(i->_eventType, i->_mbmask, 0);
-                
+
                 if (action._type != ACTION_NULL)
                 {
                     _last_event = i->_eventType;
-                    
+
                     // here we adjust for action scale, global sensitivy
                     double dx = i->_dx, dy = i->_dy;
                     dx *= _settings->getMouseSensitivity();
                     dy *= _settings->getMouseSensitivity();
                     applyOptionsToDeltas( action, dx, dy );
-                
+
                     _dx = dx;
                     _dy = dy;
-                
+
                     if (action._type == ACTION_GOTO)
                         handlePointAction(action, ea.getX(), ea.getY(), view);
                     else
                         handleMovementAction(action._type, dx, dy, view);
-                
+
                     aa.requestRedraw();
                 }
             }
-            
+
             handled = true;
         }
         else
         {
             // The only multitouch event we want passed on if not handled is a release
             handled = ea.getEventType() != osgGA::GUIEventAdapter::RELEASE;
-            
+
             // if a new push occurs we want to reset the dx/dy values to stop/prevent throwing
             if (ea.getEventType() == osgGA::GUIEventAdapter::PUSH)
                 _dx = _dy = 0.0;
@@ -1741,8 +1753,8 @@ EarthManipulator::handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapt
                 _mouse_down_event = &ea;
                 aa.requestRedraw();
                 handled = true;
-                break;       
-            
+                break;
+
             case osgGA::GUIEventAdapter::RELEASE:
                 if ( _continuous )
                 {
@@ -1753,10 +1765,10 @@ EarthManipulator::handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapt
                 else
                 {
                     action = _last_action;
-                    
+
                     _throw_dx = fabs(_dx) > 0.01 ? _dx : 0.0;
                     _throw_dy = fabs(_dy) > 0.01 ? _dy : 0.0;
-                    
+
                     if (_settings->getThrowingEnabled() && ( time_s_now - _time_s_last_event < 0.05 ) && (_throw_dx != 0.0 || _throw_dy != 0.0))
                     {
                         _thrown = true;
@@ -1782,7 +1794,7 @@ EarthManipulator::handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapt
                 }
                 handled = true;
                 break;
-                
+
             case osgGA::GUIEventAdapter::DOUBLECLICK:
                 // bail out of continuous mode if necessary:
                 _continuous = false;
@@ -1829,7 +1841,7 @@ EarthManipulator::handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapt
                     handled = true;
                 }
                 break;
-                
+
             case osgGA::GUIEventAdapter::KEYUP:
                 resetMouse( aa );
                 _task->_type = TASK_NONE;
@@ -1863,12 +1875,6 @@ EarthManipulator::handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapt
     return handled;
 }
 
-void
-EarthManipulator::postUpdate()
-{
-    updateTether();
-}
-
 namespace
 {
     /// Helper class for generating NodePathList.
@@ -1944,23 +1950,15 @@ EarthManipulator::updateTether()
             _previousUp = getUpVector( _centerLocalToWorld );
         };
 
-        osg::Quat newTetherRotation;
-
-        bool tetherModeChanged = _settings->getTetherMode() != _lastTetherMode;
-        if ( tetherModeChanged )
-        {
-            _tetherRotationOffset.unset();
-        }
-
-        //Just track the center
         if (_settings->getTetherMode() == TETHER_CENTER)
         {
-            if ( tetherModeChanged )
+            if ( _lastTetherMode == TETHER_CENTER_AND_ROTATION )
             {
-                resetLookAt();
-                //collapseTetherRotationIntoRotation();
+                // level out the camera so we don't leave the camera is weird state.
+                osg::Matrixd localToFrame(L2W*osg::Matrixd::inverse( _centerLocalToWorld ));
+                double azim = atan2(-localToFrame(0,1),localToFrame(0,0));
+                _tetherRotation.makeRotate(-azim, 0.0, 0.0, 1.0);
             }
-            _tetherRotationOffset.unset();
         }
         else
         {
@@ -1976,48 +1974,18 @@ EarthManipulator::updateTether()
                 osg::Matrixd localToFrame(L2W*osg::Matrixd::inverse( _centerLocalToWorld ));
                 double azim = atan2(-localToFrame(0,1),localToFrame(0,0));
 
-                newTetherRotation.makeRotate(-azim, 0.0, 0.0, 1.0);
-
-                newTetherRotation.slerp(t, _tetherRotationVP0, newTetherRotation);
-
-                //osg::Quat final;
-                //final.makeRotate(-azim, 0, 0, 1);
-                //newTetherRotation.slerp(t, osg::Quat(), final);
-            
-                // Recalculate rotation to compensate, making for a smooth transition:
-                if ( !_tetherRotationOffset.isSet() )
-                {
-                    //_tetherRotationOffset = newTetherRotation.inverse();
-                    //_tetherRotationOffset = osg::Quat();
-                    //_rotation = osg::Quat();
-                }
+                osg::Quat finalTetherRotation;
+                finalTetherRotation.makeRotate(-azim, 0.0, 0.0, 1.0);
+                _tetherRotation.slerp(t, _tetherRotationVP0, finalTetherRotation);
             }
 
             // Track all rotations
             else if (_settings->getTetherMode() == TETHER_CENTER_AND_ROTATION)
             {
-                newTetherRotation = L2W.getRotate() * _centerRotation.inverse();
-
-                // Recalculate rotation to compensate, making for a smooth transition.
-                // In this case the new tether rotation might include roll so we need to
-                // extract that.
-#if 0
-                // TODO: doesn't work properly; for now the eye will "jump" when you activate this mode. 
-                if ( !_tetherRotationOffset.isSet() )
-                {
-                    double azim, pitch;
-                    getEulerAngles( newTetherRotation, &azim, &pitch );
-                    _tetherRotationOffset = getQuaternion(azim, pitch).inverse();
-                }
-#endif
-            }   
+                _tetherRotation = L2W.getRotate() * _centerRotation.inverse();
+            }
         }
 
-        if ( _tetherRotationOffset.isSet() )
-            _tetherRotation = newTetherRotation * _tetherRotationOffset.get();
-        else
-            _tetherRotation = newTetherRotation;
-
         _lastTetherMode = _settings->getTetherMode();
     }
 }
@@ -2129,7 +2097,7 @@ EarthManipulator::addTouchEvents(const osgGA::GUIEventAdapter& ea)
 {
     _ga_t1 = _ga_t0;
     _ga_t0 = &ea;
-    
+
     // first, push the old event to the back of the queue.
     while ( _touchPointQueue.size() > 1 )
         _touchPointQueue.pop_front();
@@ -2152,7 +2120,7 @@ EarthManipulator::addTouchEvents(const osgGA::GUIEventAdapter& ea)
 
 bool
 EarthManipulator::parseTouchEvents( TouchEvents& output )
-{    
+{
     double sens = this->getSettings()->getTouchSensitivity();
 
     if (_touchPointQueue.size() == 2 )
@@ -2178,7 +2146,7 @@ EarthManipulator::parseTouchEvents( TouchEvents& output )
                 osg::Vec2f vec0 = osg::Vec2f(p0[1].x,p0[1].y)-osg::Vec2f(p0[0].x,p0[0].y);
                 osg::Vec2f vec1 = osg::Vec2f(p1[1].x,p1[1].y)-osg::Vec2f(p1[0].x,p1[0].y);
                 float deltaDistance = vec1.length() - vec0.length();
-                
+
                 float angle[2];
                 angle[0] = atan2(p0[0].y - p0[1].y, p0[0].x - p0[1].x);
                 angle[1] = atan2(p1[0].y - p1[1].y, p1[0].x - p1[1].x);
@@ -2188,19 +2156,19 @@ EarthManipulator::parseTouchEvents( TouchEvents& output )
                 // Threshold in pixels for determining if a two finger drag happened.
                 float dragThres = 1.0f;
 
-                // now see if that corresponds to any touch events:                
-                if (osg::equivalent( vec0.x(), vec1.x(), dragThres) && 
+                // now see if that corresponds to any touch events:
+                if (osg::equivalent( vec0.x(), vec1.x(), dragThres) &&
                     osg::equivalent( vec0.y(), vec1.y(), dragThres))
-                {                    
+                {
                     // two-finger drag.
                     output.push_back(TouchEvent());
                     TouchEvent& ev = output.back();
                     ev._eventType = EVENT_MULTI_DRAG;
                     ev._dx = 0.5 * (dx[0]+dx[1]) * sens;
                     ev._dy = 0.5 * (dy[0]+dy[1]) * sens;
-                }                                                
+                }
                 else
-                {                                 
+                {
                     // otherwise it's a pinch and/or a zoom.  You can do them together.
                     if (fabs(deltaDistance) > (1.0 * 0.0005 / sens ) )
                     {
@@ -2216,12 +2184,12 @@ EarthManipulator::parseTouchEvents( TouchEvents& output )
                         // angle between vectors changed: a twist.
                         output.push_back(TouchEvent());
                         TouchEvent& ev = output.back();
-                        ev._eventType = EVENT_MULTI_TWIST;                    
+                        ev._eventType = EVENT_MULTI_TWIST;
                         ev._dx = da;
                         //ev._dy = 0.5 * (dy[0]+dy[1]) * _touch_sens;
                         ev._dy = 0.0;
                     }
-                }             
+                }
             }
         }
 
@@ -2274,7 +2242,7 @@ EarthManipulator::setByMatrix(const osg::Matrixd& matrix)
     {
         setCenter( eye + lookVector );
         setDistance( lookVector.length() );
-        _rotation = matrix.getRotate().inverse() * _centerRotation.inverse();	
+        _rotation = matrix.getRotate().inverse() * _centerRotation.inverse();
         return;
     }
 
@@ -2283,7 +2251,7 @@ EarthManipulator::setByMatrix(const osg::Matrixd& matrix)
     float distance = (eye-bs.center()).length() + safeNode->getBound().radius();
     osg::Vec3d start_segment = eye;
     osg::Vec3d end_segment = eye + lookVector*distance;
-    
+
     osg::Vec3d ip, normal;
     bool hitFound = false;
     if (intersect(start_segment, end_segment, ip, normal))
@@ -2349,6 +2317,19 @@ EarthManipulator::getInverseMatrix() const
 }
 
 void
+EarthManipulator::updateCamera(osg::Camera& camera)
+{
+    // update the camera to reflect the current tether node
+    if ( isTethering() )
+    {
+        updateTether();
+    }
+
+    // then update the camera as usual.
+    osgGA::CameraManipulator::updateCamera(camera);
+}
+
+void
 EarthManipulator::setByLookAt(const osg::Vec3d& eye,const osg::Vec3d& center,const osg::Vec3d& up)
 {
     osg::ref_ptr<osg::Node> safeNode;
@@ -2370,7 +2351,7 @@ EarthManipulator::setByLookAt(const osg::Vec3d& eye,const osg::Vec3d& center,con
             ++i, endPoint = farPosition)
         {
             // compute the intersection with the scene.
-            
+
             osg::Vec3d ip, normal;
             if (intersect(eye, endPoint, ip, normal))
             {
@@ -2387,8 +2368,8 @@ EarthManipulator::setByLookAt(const osg::Vec3d& eye,const osg::Vec3d& center,con
     osg::Matrixd rotation_matrix = osg::Matrixd::lookAt(eye,center,up);
 
     _centerRotation = computeCenterRotation(_center);// getRotation( _center ).getRotate().inverse();
-    _rotation = rotation_matrix.getRotate().inverse() * _centerRotation.inverse();	
-    
+    _rotation = rotation_matrix.getRotate().inverse() * _centerRotation.inverse();
+
     _previousUp = getUpVector(_centerLocalToWorld);
 
     _posOffset.set(0,0,0);
@@ -2416,7 +2397,7 @@ EarthManipulator::setByLookAtRaw(const osg::Vec3d& eye,const osg::Vec3d& center,
 
 bool
 EarthManipulator::recalculateCenterFromLookVector()
-{    
+{
     // just re-applying the lookat parameters will calculate a new coordinate
     // frame based on a look-at intersection.
     osg::Vec3d eye, target, up;
@@ -2518,7 +2499,7 @@ EarthManipulator::pan( double dx, double dy )
             // in azimuth-lock mode, _centerRotation maintains a consistent north vector
             _centerRotation = computeCenterRotation( _center );
         }
-        
+
         else
         {
             // otherwise, we need to rotate _centerRotation manually.
@@ -2578,7 +2559,7 @@ EarthManipulator::rotate( double dx, double dy )
     double maxp = osg::DegreesToRadians( osg::clampBelow(_settings->getMaxPitch(),  89.9) );
 
 #if 0
-    OE_NOTICE << LC 
+    OE_NOTICE << LC
         << "LocalPitch=" << osg::RadiansToDegrees(_local_pitch)
         << ", dy=" << osg::RadiansToDegrees(dy)
         << ", dy+lp=" << osg::RadiansToDegrees(_local_pitch+dy)
@@ -2620,7 +2601,7 @@ EarthManipulator::rotate( double dx, double dy )
 
 void
 EarthManipulator::zoom( double dx, double dy )
-{   
+{
     // in normal (non-tethered mode) we need a valid zoom point.
     if ( !isTethering() )
     {
@@ -2641,7 +2622,7 @@ EarthManipulator::screenToWorld(float x, float y, osg::View* theView, osg::Vec3d
         return false;
 
     osg::ref_ptr<MapNode> mapNode;
-    if ( !_mapNode.lock(mapNode) )
+    if ( !_mapNode.lock(mapNode) || !mapNode->getTerrain() )
         return false;
 
     return mapNode->getTerrain()->getWorldCoordsUnderMouse(view, x, y, out_coords);
@@ -2670,7 +2651,7 @@ EarthManipulator::dumpActionInfo( const EarthManipulator::Action& action, osg::N
         osgEarth::notify(level)
             << s_actionOptionNames[option.option()] << "=" << val << ", ";
     }
-    osgEarth::notify(level) << std::endl;        
+    osgEarth::notify(level) << std::endl;
 }
 
 void
@@ -2722,7 +2703,7 @@ EarthManipulator::handlePointAction( const Action& action, float mx, float my, o
         {
             case ACTION_GOTO:
             {
-                Viewpoint here = getViewpoint();                
+                Viewpoint here = getViewpoint();
                 here.focalPoint()->fromWorld(_srs.get(), point);
 
                 //osg::Vec3d pointVP;
@@ -2801,7 +2782,7 @@ EarthManipulator::handleMouseAction( const Action& action, osg::View* view )
     }
     else
     {
-        
+
         _dx = dx;
         _dy = dy;
         handleMovementAction( action._type, dx, dy, view );
@@ -2952,7 +2933,7 @@ EarthManipulator::getCompositeEulerAngles( double* out_azim, double* out_pitch )
     osg::Matrix m = getMatrix() * osg::Matrixd::inverse(_centerLocalToWorld);
     osg::Vec3d look = -getUpVector( m );
     osg::Vec3d up   =  getFrontVector( m );
-    
+
     look.normalize();
     up.normalize();
 
@@ -2983,7 +2964,7 @@ EarthManipulator::getEulerAngles(const osg::Quat& q, double* out_azim, double* o
 
     osg::Vec3d look = -getUpVector( m );
     osg::Vec3d up   =  getFrontVector( m );
-    
+
     look.normalize();
     up.normalize();
 
@@ -3022,9 +3003,9 @@ EarthManipulator::collapseTetherRotationIntoRotation()
 
     double azim, pitch;
     getCompositeEulerAngles(&azim, &pitch); // TODO replace with getEulerAngles(_rotation*_tetherRotation, ...)
-    
+
     pitch = osg::clampBetween(
-        pitch, 
+        pitch,
         osg::DegreesToRadians(_settings->getMinPitch()),
         osg::DegreesToRadians(_settings->getMaxPitch()) );
 
@@ -3127,7 +3108,7 @@ namespace // Utility functions for drag()
         radial = radial * resRad;
         Vec3d result = resCtr + radial;
         return result;
-        
+
     }
     // Calculate a pointer click in eye coordinates
     osg::Vec3d getWindowPoint(osgViewer::View* view, float x, float y)
@@ -3313,7 +3294,7 @@ EarthManipulator::drag(double dx, double dy, osg::View* theView)
             // point that was dragged, worldEndDrag.
             //
             // Rotate Me so that its x axis is parallel to the z=0
-            // plane. 
+            // plane.
             // Find cone with worldEndDrag->center axis and x
             // axis of coordinate frame as generator of the conical
             // surface.
diff --git a/src/osgEarthUtil/Ephemeris b/src/osgEarthUtil/Ephemeris
index d1ad8ac..16db446 100644
--- a/src/osgEarthUtil/Ephemeris
+++ b/src/osgEarthUtil/Ephemeris
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthUtil/Ephemeris.cpp b/src/osgEarthUtil/Ephemeris.cpp
index d4598dd..d01587b 100644
--- a/src/osgEarthUtil/Ephemeris.cpp
+++ b/src/osgEarthUtil/Ephemeris.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
@@ -37,28 +37,22 @@ namespace
 
 #define d2r(X) osg::DegreesToRadians(X)
 #define r2d(X) osg::RadiansToDegrees(X)
-#define nrad(X) { while( X > TWO_PI ) X -= TWO_PI; while( X < 0.0 ) X += TWO_PI; }
+#define nrad(X) { while( X >= TWO_PI ) X -= TWO_PI; while( X < 0.0 ) X += TWO_PI; }
 #define nrad2(X) { while( X <= -osg::PI ) X += TWO_PI; while( X > osg::PI ) X -= TWO_PI; }
 
     static const double TWO_PI = (2.0*osg::PI);
     static const double JD2000 = 2451545.0;
-
-    struct CelestialPosition
-    {
-        osg::Vec3d _ecef;
-        double     _rightAscension;
-        double     _declination;
-        double     _localAzimuth;
-        double     _localElevation;
-        double     _localLatitude;
-        double     _localLongitude;
-    };
     
     osg::Vec3d getPositionFromRADecl(double ra, double decl, double range)
     {
-        return osg::Vec3(0,range,0) * 
-            osg::Matrix::rotate( decl, 1, 0, 0 ) * 
-            osg::Matrix::rotate( ra - osg::PI_2, 0, 0, 1 );
+        return osg::Vec3d(
+                range * cos(decl) * cos(ra),
+                range * cos(decl) * sin(ra),
+                range * sin(decl) );
+
+        //return osg::Vec3(0,range,0) * 
+        //    osg::Matrix::rotate( decl, 1, 0, 0 ) * 
+        //    osg::Matrix::rotate( ra, 0, 0, 1 ); // - osg::PI_2, 0, 0, 1 );
     }
 
 
@@ -231,24 +225,37 @@ namespace
             return buf.str();
         }
 
-        // From http://www.stjarnhimlen.se/comp/ppcomp.html
-        osg::Vec3d getPosition(int year, int month, int date, double hoursUTC ) const
+        // Math: http://www.stjarnhimlen.se/comp/ppcomp.html
+        // More: http://www.stjarnhimlen.se/comp/tutorial.html#7
+        // Test: http://www.satellite-calculations.com/Satellite/suncalc.htm
+        // Test: http://www.timeanddate.com/astronomy/moon/light.html
+        osg::Vec3d getEarthLonLatRange(int year, int month, int date, double hoursUTC ) const
         {
-            //double julianDate = getJulianDate( year, month, date );
-            //julianDate += hoursUTC /24.0;
-            double d = 367*year - 7 * ( year + (month+9)/12 ) / 4 + 275*month/9 + date - 730530;
-            d += (hoursUTC / 24.0);                     
-
-            double ecl = osg::DegreesToRadians(23.4393 - 3.563E-7 * d);
+            int di = 367*year - 7 * ( year + (month+9)/12 ) / 4 + 275*month/9 + date - 730530;
+            double d = (double)di;
+            double time_r = hoursUTC/24.0; // 0..1            
+            d += time_r;
 
-            double N = osg::DegreesToRadians(125.1228 - 0.0529538083 * d);
-            double i = osg::DegreesToRadians(5.1454);
-            double w = osg::DegreesToRadians(318.0634 + 0.1643573223 * d);
+            double N = d2r(125.1228 - 0.0529538083 * d);  nrad(N);
+            double i = d2r(5.1454);                       
+            double w = d2r(318.0634 + 0.1643573223 * d);  nrad(w);
             double a = 60.2666;//  (Earth radii)
             double e = 0.054900;
-            double M = osg::DegreesToRadians(115.3654 + 13.0649929509 * d);
-
-            double E = M + e*(180.0/osg::PI) * sin(M) * ( 1.0 + e * cos(M) );
+            double M = d2r(115.3654 + 13.0649929509 * d); nrad(M);
+
+            double E = M + e * sin(M) * ( 1.0 + e * cos(M) );
+            double E0 = E, E1 = 0.0;
+            double epsilon = d2r(0.001);
+            int count = 0;
+            do {
+                E1 = E0 - (E0 - e*sin(E0) - M) / (1.0 - e*cos(E0) );
+                E = E1;
+                std::swap(E0, E1);
+                ++count;
+            }
+            while( fabs(E1-E0) > epsilon && count < 10 );
+            
+            //E = E - (E - e*sin(E) - M) / (1.0 - e*cos(E) );
             
             double xv = a * ( cos(E) - e );
             double yv = a * ( sqrt(1.0 - e*e) * sin(E) );
@@ -262,36 +269,104 @@ namespace
             double zh = r * ( sin(v+w) * sin(i) );
 
             // calculate the ecliptic latitude and longitude here
-            double lonEcl = atan2 (yh, xh);
+            double lonEcl = atan2(yh, xh);
             double latEcl = atan2(zh, sqrt(xh*xh + yh*yh));
 
-            double xg = r * cos(lonEcl) * cos(latEcl);
-            double yg = r * sin(lonEcl) * cos(latEcl);
-            double zg = r * sin(latEcl);
-
+            //Just use the average distance from the earth
+            double rg = 6378137.0 * a;
+
+            // add in the perturbations.
+            double Mm = M;
+            double Ms = d2r(356.0470 + 0.9856002585 * d); //nrad(Ms); // mean anomaly of the sun
+            double ws = d2r(282.9404 + 4.70935E-5   * d); //nrad(ws); // sun's longitude of perihelion
+            double Ls = ws + Ms;    //nrad(Ls);
+            double Lm = N + w + Mm; //nrad(Lm);
+            double D = Lm - Ls;     //nrad(D);
+            double F = Lm - N;      //nrad(F);
+
+            lonEcl = lonEcl
+                + d2r(-1.274) * sin(Mm - 2*D)    // (Evection)
+                + d2r(+0.658) * sin(2*D)         //(Variation)
+                + d2r(-0.186) * sin(Ms)          // (Yearly equation)
+                + d2r(-0.059) * sin(2*Mm - 2*D)
+                + d2r(-0.057) * sin(Mm - 2*D + Ms)
+                + d2r(+0.053) * sin(Mm + 2*D)
+                + d2r(+0.046) * sin(2*D - Ms)
+                + d2r(+0.041) * sin(Mm - Ms)
+                + d2r(-0.035) * sin(D)           // (Parallactic equation)
+                + d2r(-0.031) * sin(Mm + Ms)
+                + d2r(-0.015) * sin(2*F - 2*D)
+                + d2r(+0.011) * sin(Mm - 4*D);
+
+            latEcl = latEcl
+                + d2r(-0.173) * sin(F - 2*D)
+                + d2r(-0.055) * sin(Mm - F - 2*D)
+                + d2r(-0.046) * sin(Mm + F - 2*D)
+                + d2r(+0.033) * sin(F + 2*D)
+                + d2r(+0.017) * sin(2*Mm + F);
+
+            r = r +
+                -0.58 * cos(Mm - 2*D)
+                -0.46 * cos(2*D);
+
+            // R is in "earth radii", so resolve to meters:
+            r *= 6378137.0;
+
+            // convert to elliptic geocentric (unit)
+            double xg = cos(lonEcl) * cos(latEcl);
+            double yg = sin(lonEcl) * cos(latEcl);
+            double zg = sin(latEcl);
+
+            // and then to rectangular equatorial (unit)
+            double ecl = d2r(23.4393 - 3.563E-7 * d); // obliquity of elliptic (tilt of earth)
             double xe = xg;
-            double ye = yg * cos(ecl) -zg * sin(ecl);
-            double ze = yg * sin(ecl) +zg * cos(ecl);
-
-            double RA    = atan2(ye, xe);
-            double Dec = atan2(ze, sqrt(xe*xe + ye*ye));
-
-            //Just use the average distance from the earth            
-            double rg = 6378137.0 + 384400000.0;
+            double ye = yg*cos(ecl) - zg*sin(ecl);
+            double ze = yg*sin(ecl) + zg*cos(ecl);
+
+            // get the ra/decl:
+            double RA   = atan2(ye, xe);
+            double Decl = atan2(ze, sqrt(xe*xe + ye*ye));
+
+            nrad(RA);
+            double RAdeg  = r2d(RA);
+            double Decdeg = r2d(Decl);
+          
+            // finally, adjust for the time of day (rotation of the earth).
+            double UT = d - floor(d);
+            double GMST0 = Ls + d2r(180.0);
+            double siteLon = 0.0, siteLat = 0.0;
+            double siderealTime = GMST0 + d2r(UT*360.0) + siteLon;
+            double hourAngle = siderealTime - RA;
+            nrad2(hourAngle);
+
+            double x = cos(hourAngle) * cos(Decl);
+            double y = sin(hourAngle) * cos(Decl);
+            double z = sin(Decl);
             
-            // finally, adjust for the time of day (rotation of the earth)
-            double time_r = hoursUTC/24.0; // 0..1            
-            double moon_r = RA/TWO_PI; // convert to 0..1
-
-            // rotational difference between UTC and current time
-            double diff_r = moon_r - time_r;
-            double diff_lon = TWO_PI * diff_r;
-
-            RA -= diff_lon;
-
-            nrad2(RA);
+            double earthLat = atan2(z, sqrt(x*x + y*y) );
+            
+            // calculate the topographic right ascension and declination:
+            double mpar  = asin(1.0/r);
+            double gclat = siteLat - d2r(0.1924)*sin(2.0*siteLat);
+            double rho   = 0.99833 + 0.00167*cos(2.0*siteLat);
+            double g     = atan( tan(gclat) / cos(hourAngle) );
+            double topRA   = RA - (mpar * rho * cos(gclat) * sin(hourAngle) / cos(Decl));
+            double topDecl = Decl - (mpar * rho * sin(gclat) * sin(g - Decl) / sin(g));
+
+            // use that to calculate the 
+            double earthLon = topRA - GMST0 - d2r(UT*360.0);
+
+            return osg::Vec3d(earthLon, earthLat, r);
+        }
 
-            return getPositionFromRADecl( RA, Dec, rg );
+        osg::Vec3d getECEF(int year, int month, int date, double hoursUTC) const
+        {            
+            osg::Vec3d LLA = getEarthLonLatRange(year, month, date, hoursUTC);
+            
+            return osg::Vec3d(
+                    LLA.z() * cos(LLA.y()) * cos(LLA.x()),
+                    LLA.z() * cos(LLA.y()) * sin(LLA.x()),
+                    LLA.z() * sin(LLA.y()) ); 
         }
     };
 }
@@ -315,7 +390,9 @@ osg::Vec3d
 Ephemeris::getMoonPositionECEF(const DateTime& date) const
 {
     Moon moon;
-    return moon.getPosition( date.year(), date.month(), date.day(), date.hours() );
+    //osg::Vec3d rdr = moon.getRaDeclRange(date.year(), date.month(), date.day(), date.hours());
+    //OE_NOTICE << "Moon: Y=" << date.year() << ", M=" << date.month() << ", D=" << date.day() << ", H=" << date.hours() << ": RA=" << osg::RadiansToDegrees(rdr.x()) << "; Decl=" << osg::RadiansToDegrees(rdr.y()) << "; Range=" << rdr.z() << std::endl;
+    return moon.getECEF( date.year(), date.month(), date.day(), date.hours() );
 }
 
 osg::Vec3d
diff --git a/src/osgEarthUtil/ExampleResources b/src/osgEarthUtil/ExampleResources
index 81bcd36..eaadac3 100644
--- a/src/osgEarthUtil/ExampleResources
+++ b/src/osgEarthUtil/ExampleResources
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
@@ -61,9 +61,18 @@ namespace osgEarth { namespace Util
          * arguemnts and XML externals.
          */
         osg::Group* load(
-            osg::ArgumentParser& args, 
+            osg::ArgumentParser& args,
             osgViewer::View*     view,
-            Container*           userContainer =0L ) const;
+            Container*           userContainer = 0L) const
+        {
+            return load(args, view, userContainer, 0L);
+        }
+
+        osg::Group* load(
+            osg::ArgumentParser&  args, 
+            osgViewer::View*      view,
+            Container*            userContainer,
+            const osgDB::Options* readOptions) const;
 
         /**
          * Takes an existing map node and processes all the built-in example command
@@ -139,9 +148,7 @@ namespace osgEarth { namespace Util
     class OSGEARTHUTIL_EXPORT SkyControlFactory
     {
     public:
-        Control* create( 
-            SkyNode*         sky,
-            osgViewer::View* view ) const;
+        static Control* create(SkyNode* sky);
     };
 
 
diff --git a/src/osgEarthUtil/ExampleResources.cpp b/src/osgEarthUtil/ExampleResources.cpp
index 3e90c64..bc0feef 100644
--- a/src/osgEarthUtil/ExampleResources.cpp
+++ b/src/osgEarthUtil/ExampleResources.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
@@ -32,14 +32,15 @@
 #include <osgEarthUtil/Shadowing>
 #include <osgEarthUtil/ActivityMonitorTool>
 #include <osgEarthUtil/LogarithmicDepthBuffer>
+#include <osgEarthUtil/ContourMap>
 
 #include <osgEarthUtil/LODBlending>
 #include <osgEarthUtil/VerticalScale>
-#include <osgEarthUtil/ContourMap>
 
 #include <osgEarthAnnotation/AnnotationData>
 #include <osgEarthAnnotation/AnnotationRegistry>
-#include <osgEarth/Decluttering>
+#include <osgEarth/ScreenSpaceLayout>
+#include <osgEarth/TerrainEngineNode>
 
 #include <osgEarth/XmlUtils>
 #include <osgEarth/StringUtils>
@@ -66,6 +67,8 @@ using namespace osgEarth::Symbology;
 using namespace osgEarth::Annotation;
 using namespace osgEarth::Drivers;
 
+namespace ui = osgEarth::Util::Controls;
+
 //------------------------------------------------------------------------
 
 /** Shared event handlers. */
@@ -112,6 +115,37 @@ namespace
         osg::observer_ptr<osg::Node> _node;
     };
 
+    /**
+     * Toggles the main control canvas on and off.
+     */
+    struct ToggleCanvasEventHandler : public osgGA::GUIEventHandler
+    {
+        ToggleCanvasEventHandler(osg::Node* canvas, char key) :
+            _canvas(canvas), _key(key)
+        {
+        }
+
+        bool handle( const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa )
+        {
+            if (ea.getEventType() == osgGA::GUIEventAdapter::KEYDOWN)
+            {
+                if (ea.getKey() == _key)
+                {
+                    osg::ref_ptr< osg::Node > safeNode = _canvas.get();
+                    if (safeNode.valid())
+                    {
+                        safeNode->setNodeMask( safeNode->getNodeMask() ? 0 : ~0 );
+                    }
+                    return true;
+                }
+            }
+            return false;
+        }
+
+        osg::observer_ptr<osg::Node> _canvas;
+        char _key;
+    };
+
     // sets a user-specified uniform.
     struct ApplyValueUniform : public ControlEventHandler
     {
@@ -147,152 +181,6 @@ MouseCoordsControlFactory::create(MapNode*         mapNode,
 
 namespace
 {
-    struct SkyTimeSliderHandler : public ControlEventHandler
-    {
-        SkyTimeSliderHandler(SkyNode* sky) : _sky(sky)  { }
-
-        SkyNode* _sky;
-
-        virtual void onValueChanged( class Control* control, float value )
-        {
-            DateTime d = _sky->getDateTime();
-            _sky->setDateTime(DateTime(d.year(), d.month(), d.day(), value));
-        }
-    };
-
-//#undef USE_AMBIENT_SLIDER
-#define USE_AMBIENT_SLIDER 1
-
-#ifdef USE_AMBIENT_SLIDER
-    struct AmbientBrightnessHandler : public ControlEventHandler
-    {
-        AmbientBrightnessHandler(SkyNode* sky) : _sky(sky) { }
-
-        SkyNode* _sky;
-
-        virtual void onValueChanged( class Control* control, float value )
-        {
-            _sky->setMinimumAmbient(osg::Vec4(value,value,value,1));
-        }
-    };
-#endif
-
-    struct AnimateSkyUpdateCallback : public osg::NodeCallback
-    {    
-        /**
-        * Creates an AnimateSkyCallback.  
-        * @param rate    The time multipler from real time.  Default of 1440 means 1 minute real time will equal 1 day simulation time.
-        */
-        AnimateSkyUpdateCallback( double rate = 1440 ):
-            _rate( rate ),
-            _prevTime( -1 ),
-            _accumTime( 0.0 )
-        {
-        }
-
-        virtual void operator()(osg::Node* node, osg::NodeVisitor* nv)
-        {             
-            SkyNode* sky = dynamic_cast< SkyNode* >( node );
-            if (sky)
-            {            
-                double time = nv->getFrameStamp()->getSimulationTime();            
-                if (_prevTime > 0)
-                {                
-                    TimeStamp t = sky->getDateTime().asTimeStamp();                  
-                    double delta = ceil((time - _prevTime) * _rate);
-                    _accumTime += delta;
-                    // The time stamp only works in seconds so we wait until we've accumulated at least 1 second to change the date.
-                    if (_accumTime > 1.0)
-                    {
-                        double deltaS = floor(_accumTime );                    
-                        _accumTime -= deltaS;
-                        t += deltaS;
-                        sky->setDateTime( t );                        
-                    }                
-                }            
-                _prevTime = time;
-            }
-            traverse( node, nv );
-        }
-
-        double _accumTime;
-        double _prevTime;    
-        double _rate;
-    };
-
-}
-
-Control*
-SkyControlFactory::create(SkyNode*         sky,
-                          osgViewer::View* view) const
-{
-    Grid* grid = new Grid();
-    grid->setChildVertAlign( Control::ALIGN_CENTER );
-    grid->setChildSpacing( 10 );
-    grid->setHorizFill( true );
-
-    grid->setControl( 0, 0, new LabelControl("Time (Hours UTC): ", 16) );
-
-    DateTime dt = sky->getDateTime();
-
-    HSliderControl* skySlider = grid->setControl(1, 0, new HSliderControl( 0.0f, 24.0f, dt.hours() ));
-    skySlider->setHorizFill( true, 300 );
-    skySlider->addEventHandler( new SkyTimeSliderHandler(sky) );
-
-    grid->setControl(2, 0, new LabelControl(skySlider) );
-
-#ifdef USE_AMBIENT_SLIDER
-    grid->setControl(0, 1, new LabelControl("Min.Ambient: ", 16) );
-    HSliderControl* ambient = grid->setControl(1, 1, new HSliderControl(0.0f, 1.0f, sky->getSunLight()->getAmbient().r()));
-    ambient->addEventHandler( new AmbientBrightnessHandler(sky) );
-    grid->setControl(2, 1, new LabelControl(ambient) );
-#endif
-
-    return grid;
-}
-
-//------------------------------------------------------------------------
-
-namespace
-{
-    struct ChangeSeaLevel : public ControlEventHandler
-    {
-        ChangeSeaLevel( OceanNode* ocean ) : _ocean(ocean) { }
-
-        OceanNode* _ocean;
-
-        virtual void onValueChanged( class Control* control, float value )
-        {
-            _ocean->setSeaLevel( value );
-        }
-    };
-}
-
-Control*
-OceanControlFactory::create(OceanNode* ocean) const
-{
-    VBox* main = new VBox();
-
-    HBox* oceanBox1 = main->addControl(new HBox());
-    oceanBox1->setChildVertAlign( Control::ALIGN_CENTER );
-    oceanBox1->setChildSpacing( 10 );
-    oceanBox1->setHorizFill( true );
-
-    oceanBox1->addControl( new LabelControl("Sea Level: ", 16) );
-
-    HSliderControl* mslSlider = oceanBox1->addControl(new HSliderControl( -250.0f, 250.0f, 0.0f ));
-    mslSlider->setBackColor( Color::Gray );
-    mslSlider->setHeight( 12 );
-    mslSlider->setHorizFill( true, 200 );
-    mslSlider->addEventHandler( new ChangeSeaLevel(ocean) );
-
-    return main;
-}
-
-//------------------------------------------------------------------------
-
-namespace
-{
     struct AnnoControlBuilder : public osg::NodeVisitor
     {
         AnnoControlBuilder(osgViewer::View* view)
@@ -359,17 +247,17 @@ AnnotationGraphControlFactory::create(osg::Node*       graph,
 #define LC "[MapNodeHelper] "
 
 osg::Group*
-MapNodeHelper::load(osg::ArgumentParser& args,
-                    osgViewer::View*     view,
-                    Container*           userContainer ) const
+MapNodeHelper::load(osg::ArgumentParser&  args,
+                    osgViewer::View*      view,
+                    Container*            userContainer,
+                    const osgDB::Options* readOptions) const
 {
     // do this first before scanning for an earth file
     std::string outEarth;
     args.read( "--out-earth", outEarth );
 
-    osg::ref_ptr<osgDB::Options> options = new osgDB::Options();
+    osg::ref_ptr<osgDB::Options> myReadOptions = Registry::cloneOrCreateOptions(readOptions);
     
-#if 1
     Config c;
     c.add("elevation_smoothing", false);
     TerrainOptions to(c);
@@ -377,25 +265,15 @@ MapNodeHelper::load(osg::ArgumentParser& args,
     MapNodeOptions defMNO;
     defMNO.setTerrainOptions( to );
 
-    options->setPluginStringData("osgEarth.defaultOptions", defMNO.getConfig().toJSON());
-#endif
+    myReadOptions->setPluginStringData("osgEarth.defaultOptions", defMNO.getConfig().toJSON());
 
     // read in the Earth file:
-    osg::Node* node = 0L;
-    for( int i=0; i<args.argc(); ++i )
-    {
-        if ( osgDB::getLowerCaseFileExtension(args[i]) == "earth" )
-        {
-            node = osgDB::readNodeFile( args[i], options );
-            args.remove(i);
-            break;
-        }
-    }
+    osg::Node* node = osgDB::readNodeFiles(args, myReadOptions.get());
 
     osg::ref_ptr<MapNode> mapNode;
     if ( !node )
     {
-        if ( !args.find("--images") )
+        if ( args.find("--images") < 0 )
         {
             OE_WARN << LC << "No earth file." << std::endl;
             return 0L;
@@ -428,7 +306,7 @@ MapNodeHelper::load(osg::ArgumentParser& args,
     // a root node to hold everything:
     osg::Group* root = new osg::Group();
     
-    root->addChild( mapNode.get() );
+    root->addChild( node );
 
     // parses common cmdline arguments.
     if ( view )
@@ -484,21 +362,17 @@ MapNodeHelper::parse(MapNode*             mapNode,
     osg::ref_ptr<osgDB::Options> dbOptions = Registry::instance()->cloneOrCreateOptions();
 
     // parse out custom example arguments first:
-    bool useSky        = args.read("--sky");
-    bool useOcean      = args.read("--ocean");
     bool useMGRS       = args.read("--mgrs");
     bool useDMS        = args.read("--dms");
     bool useDD         = args.read("--dd");
     bool useCoords     = args.read("--coords") || useMGRS || useDMS || useDD;
-    bool useOrtho      = args.read("--ortho");
+
     bool useAutoClip   = args.read("--autoclip");
-    bool useShadows    = args.read("--shadows");
     bool animateSky    = args.read("--animate-sky");
     bool showActivity  = args.read("--activity");
     bool useLogDepth   = args.read("--logdepth");
     bool useLogDepth2  = args.read("--logdepth2");
     bool kmlUI         = args.read("--kmlui");
-    bool inspect       = args.read("--inspect");
 
     if (args.read("--verbose"))
         osgEarth::setNotifyLevel(osg::INFO);
@@ -543,92 +417,15 @@ MapNodeHelper::parse(MapNode*             mapNode,
     }
     canvas->addControl( mainContainer );
 
+    // Add an event handler to toggle the canvas with a key press;
+    view->addEventHandler(new ToggleCanvasEventHandler(canvas, 'y'));
 
     // look for external data in the map node:
     const Config& externals = mapNode->externalConfig();
 
-    const Config& skyConf         = externals.child("sky");
-    const Config& oceanConf       = externals.child("ocean");
-    const Config& annoConf        = externals.child("annotations");
-    const Config& declutterConf   = externals.child("decluttering");
-
     // some terrain effects.
     // TODO: Most of these are likely to move into extensions.
-    const Config& lodBlendingConf = externals.child("lod_blending");
     const Config& vertScaleConf   = externals.child("vertical_scale");
-    const Config& contourMapConf  = externals.child("contour_map");
-
-    // Adding a sky model:
-    if ( useSky || !skyConf.empty() )
-    {
-        SkyOptions options(skyConf);
-        if ( options.getDriver().empty() )
-        {
-            if ( mapNode->getMapSRS()->isGeographic() )
-                options.setDriver("simple");
-            else
-                options.setDriver("gl");
-        }
-
-        SkyNode* sky = SkyNode::create(options, mapNode);
-        if ( sky )
-        {
-            sky->attach( view, 0 );
-            if ( mapNode->getNumParents() > 0 )
-            {
-                osgEarth::insertGroup(sky, mapNode->getParent(0));
-            }
-            else
-            {
-                sky->addChild( mapNode );
-                root = sky;
-            }
-                
-            Control* c = SkyControlFactory().create(sky, view);
-            if ( c )
-                mainContainer->addControl( c );
-
-            if (animateSky)
-            {
-                sky->setUpdateCallback( new AnimateSkyUpdateCallback() );
-            }
-
-        }
-    }
-
-    // Adding an ocean model:
-    if ( useOcean || !oceanConf.empty() )
-    {
-        OceanNode* ocean = OceanNode::create(OceanOptions(oceanConf), mapNode);
-        if ( ocean )
-        {
-            // if there's a sky, we want to ocean under it
-            osg::Group* parent = osgEarth::findTopMostNodeOfType<SkyNode>(root);
-            if ( !parent ) parent = root;
-            parent->addChild( ocean );
-
-            Control* c = OceanControlFactory().create(ocean);
-            if ( c )
-                mainContainer->addControl(c);
-        }
-    }
-
-    // Shadowing.
-    if ( useShadows )
-    {
-        ShadowCaster* caster = new ShadowCaster();
-        caster->setLight( view->getLight() );
-        caster->getShadowCastingGroup()->addChild( mapNode->getModelLayerGroup() );
-        if ( mapNode->getNumParents() > 0 )
-        {
-            insertGroup(caster, mapNode->getParent(0));
-        }
-        else
-        {
-            caster->addChild(mapNode);
-            root = caster;
-        }
-    }
 
     // Loading KML from the command line:
     if ( !kmlFile.empty() )
@@ -641,6 +438,10 @@ MapNodeHelper::parse(MapNode*             mapNode,
         defaultIcon->url()->setLiteral(KML_PUSHPIN_URL);
         kml_options.defaultIconSymbol() = defaultIcon;
 
+        TextSymbol* defaultText = new TextSymbol();
+        defaultText->halo() = Stroke(0.3,0.3,0.3,1.0);
+        kml_options.defaultTextSymbol() = defaultText;
+
         osg::Node* kml = KML::load( URI(kmlFile), mapNode, kml_options );
         if ( kml )
         {
@@ -661,23 +462,11 @@ MapNodeHelper::parse(MapNode*             mapNode,
         }
     }
 
-    // Annotations in the map node externals:
-    if ( !annoConf.empty() )
-    {
-        osg::Group* annotations = 0L;
-        AnnotationRegistry::instance()->create( mapNode, annoConf, dbOptions.get(), annotations );
-        if ( annotations )
-        {
-            mapNode->addChild( annotations );
-            //root->addChild( annotations );
-        }
-    }
-
-    // Configure the de-cluttering engine for labels and annotations:
-    if ( !declutterConf.empty() )
-    {
-        Decluttering::setOptions( DeclutteringOptions(declutterConf) );
-    }
+    //// Configure the de-cluttering engine for labels and annotations:
+    //if ( !screenSpaceLayoutConf.empty() )
+    //{
+    //    ScreenSpaceLayout::setOptions( ScreenSpaceLayoutOptions(screenSpaceLayoutConf) );
+    //}
 
     // Configure the mouse coordinate readout:
     if ( useCoords )
@@ -701,14 +490,9 @@ MapNodeHelper::parse(MapNode*             mapNode,
     }
 
     // Configure for an ortho camera:
-    if ( useOrtho )
+    if ( args.read("--ortho") )
     {
         view->getCamera()->setProjectionMatrixAsOrtho(-1, 1, -1, 1, 0, 1);
-        //EarthManipulator* manip = dynamic_cast<EarthManipulator*>(view->getCameraManipulator());
-        //if ( manip )
-        //{
-        //    manip->getSettings()->setCameraProjection( EarthManipulator::PROJ_ORTHOGRAPHIC );
-        //}
     }
 
     // activity monitor (debugging)
@@ -771,12 +555,6 @@ MapNodeHelper::parse(MapNode*             mapNode,
         OE_INFO << LC << "...found " << imageLayers.size() << " image layers." << std::endl;
     }
 
-    // Install elevation morphing
-    if ( !lodBlendingConf.empty() )
-    {
-        mapNode->getTerrainEngine()->addEffect( new LODBlending(lodBlendingConf) );
-    }
-
     // Install vertical scaler
     if ( !vertScaleConf.empty() )
     {
@@ -784,9 +562,14 @@ MapNodeHelper::parse(MapNode*             mapNode,
     }
 
     // Install a contour map effect.
-    if ( !contourMapConf.empty() )
+    if (args.read("--contourmap"))
     {
-        mapNode->getTerrainEngine()->addEffect( new ContourMap(contourMapConf) );
+        mapNode->addExtension(Extension::create("contourmap", ConfigOptions()));
+
+        // with the cmdline switch, hids all the image layer so we can see the contour map.
+        for (unsigned i = 0; i < mapNode->getMap()->getNumImageLayers(); ++i) {
+            mapNode->getMap()->getImageLayerAt(i)->setVisible(false);
+        }
     }
 
     // Generic named value uniform with min/max.
@@ -817,13 +600,41 @@ MapNodeHelper::parse(MapNode*             mapNode,
         }
     }
 
-    if ( inspect )
+    // Map inspector:
+    if (args.read("--inspect"))
     {
         mapNode->addExtension( Extension::create("mapinspector", ConfigOptions()) );
     }
+
+    // Memory monitor:
+    if (args.read("--monitor"))
+    {
+        mapNode->addExtension(Extension::create("monitor", ConfigOptions()) );
+    }
+
+    // Simple sky model:
+    if (args.read("--sky"))
+    {
+        mapNode->addExtension(Extension::create("sky_simple", ConfigOptions()) );
+    }
+
+    // Simple ocean model:
+    if (args.read("--ocean"))
+    {
+        mapNode->addExtension(Extension::create("ocean_simple", ConfigOptions()));
+    }
+
+    // Arbitrary extension:
+    std::string extname;
+    if (args.read("--extension", extname))
+    {
+        Extension* ext = Extension::create(extname, ConfigOptions());
+        if (ext)
+            mapNode->addExtension(ext);
+    }
     
 
-    // Process extensions.
+    // Hook up the extensions!
     for(std::vector<osg::ref_ptr<Extension> >::const_iterator eiter = mapNode->getExtensions().begin();
         eiter != mapNode->getExtensions().end();
         ++eiter)
@@ -841,6 +652,32 @@ MapNodeHelper::parse(MapNode*             mapNode,
             controlIF->connect( mainContainer );
     }
 
+
+    // Shadowing. This is last because it needs access to a light which may be provided
+    // by one of the Sky extensions.
+    if (args.read("--shadows"))
+    {
+        int unit;
+        if ( mapNode->getTerrainEngine()->getResources()->reserveTextureImageUnit(unit, "ShadowCaster") )
+        {
+            ShadowCaster* caster = new ShadowCaster();
+            caster->setTextureImageUnit( unit );
+            caster->setLight( view->getLight() );
+            caster->getShadowCastingGroup()->addChild( mapNode->getModelLayerGroup() );
+            //insertParent(caster, mapNode);
+            //root = findTopOfGraph(caster)->asGroup();
+            if ( mapNode->getNumParents() > 0 )
+            {
+                insertGroup(caster, mapNode->getParent(0));
+            }
+            else
+            {
+                caster->addChild(mapNode);
+                root = caster;
+            }
+        }
+    }
+
     root->addChild( canvas );
 }
 
@@ -855,6 +692,7 @@ MapNodeHelper::configureView( osgViewer::View* view ) const
     view->addEventHandler(new osgViewer::LODScaleHandler());
     view->addEventHandler(new osgGA::StateSetManipulator(view->getCamera()->getOrCreateStateSet()));
     view->addEventHandler(new osgViewer::RecordCameraPathHandler());
+    view->addEventHandler(new osgViewer::ScreenCaptureHandler());
 }
 
 
@@ -878,3 +716,104 @@ MapNodeHelper::usage() const
         << "  --uniform [name] [min] [max]  : create a uniform controller with min/max values\n"
         << "  --path [file]                 : load and playback an animation path\n";
 }
+
+
+//........................................................................
+
+
+namespace
+{
+    struct SkyHoursSlider : public ui::ControlEventHandler
+    {
+        SkyHoursSlider(SkyNode* sky) : _sky(sky)  { }
+        SkyNode* _sky;
+        void onValueChanged(ui::Control* control, float value )
+        {
+            DateTime d = _sky->getDateTime();
+            _sky->setDateTime(DateTime(d.year(), d.month(), d.day(), value));
+        }
+    };
+    
+    static std::string s_month[12] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
+
+    struct SkyMonthSlider : public ui::ControlEventHandler
+    {
+        SkyMonthSlider(SkyNode* sky, ui::LabelControl* label) : _sky(sky), _label(label) { }
+        SkyNode* _sky;
+        ui::LabelControl* _label;
+        void onValueChanged(ui::Control* control, float value )
+        {
+            int m = std::min((int)value, 11);
+            DateTime d = _sky->getDateTime();            
+            _sky->setDateTime(DateTime(d.year(), m, d.day(), d.hours()));
+            _label->setText(s_month[m]);
+        }
+    };
+
+    struct SkyYearSlider : public ui::ControlEventHandler
+    {
+        SkyYearSlider(SkyNode* sky, ui::LabelControl* label) : _sky(sky), _label(label) { }
+        SkyNode* _sky;
+        ui::LabelControl* _label;
+        void onValueChanged(ui::Control* control, float value )
+        {
+            DateTime d = _sky->getDateTime();            
+            _sky->setDateTime(DateTime((int)value, d.month(), d.day(), d.hours()));
+            _label->setText(Stringify() << (int)value);
+        }
+    };
+
+    struct AmbientBrightnessHandler : public ui::ControlEventHandler
+    {
+        AmbientBrightnessHandler(SkyNode* sky) : _sky(sky) { }
+
+        SkyNode* _sky;
+
+        void onValueChanged(ui::Control* control, float value )
+        {
+            _sky->setMinimumAmbient(osg::Vec4(value,value,value,1));
+        }
+    };
+}
+
+ui::Control* SkyControlFactory::create(SkyNode* sky)
+{
+    ui::Grid* grid = new ui::Grid();
+    grid->setChildVertAlign( ui::Control::ALIGN_CENTER );
+    grid->setChildSpacing( 10 );
+    grid->setHorizFill( true );
+
+    if (sky)
+    {
+        DateTime dt = sky->getDateTime();
+
+        int r=0;
+        grid->setControl( 0, r, new ui::LabelControl("Hours UTC: ", 16) );
+        ui::HSliderControl* skyHoursSlider = grid->setControl(1, r, new ui::HSliderControl( 0.0f, 24.0f, dt.hours() ));
+        skyHoursSlider->setHorizFill( true, 250 );
+        skyHoursSlider->addEventHandler( new SkyHoursSlider(sky) );
+        grid->setControl(2, r, new ui::LabelControl(skyHoursSlider) );
+    
+        ++r;
+        grid->setControl( 0, r, new ui::LabelControl("Month: ", 16) );
+        ui::HSliderControl* skyMonthSlider = grid->setControl(1, r, new ui::HSliderControl( 0.0f, 12.0f, dt.month() ));
+        skyMonthSlider->setHorizFill( true, 250 );
+        ui::LabelControl* monthLabel = grid->setControl(2, r, new ui::LabelControl(s_month[dt.month()]));
+        skyMonthSlider->addEventHandler( new SkyMonthSlider(sky, monthLabel) );
+    
+        ++r;
+        grid->setControl( 0, r, new ui::LabelControl("Year: ", 16) );
+        ui::HSliderControl* skyYearSlider = grid->setControl(1, r, new ui::HSliderControl( 1970.0f, 2061.0f, dt.year() ));
+        skyYearSlider->setHorizFill( true, 250 );
+        ui::LabelControl* yearLabel = grid->setControl(2, r, new ui::LabelControl(Stringify()<<dt.year()));
+        skyYearSlider->addEventHandler( new SkyYearSlider(sky, yearLabel) );
+
+        ++r;
+        grid->setControl(0, r, new ui::LabelControl("Min.Ambient: ", 16) );
+        ui::HSliderControl* ambient = grid->setControl(1, r, new ui::HSliderControl(0.0f, 1.0f, sky->getSunLight()->getAmbient().r()));
+        ambient->addEventHandler( new AmbientBrightnessHandler(sky) );
+        grid->setControl(2, r, new ui::LabelControl(ambient) );
+    }
+
+    return grid;
+}
diff --git a/src/osgEarthUtil/Export b/src/osgEarthUtil/Export
index 80c5648..a2d4e98 100644
--- a/src/osgEarthUtil/Export
+++ b/src/osgEarthUtil/Export
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthUtil/FeatureQueryTool b/src/osgEarthUtil/FeatureQueryTool
index 204cb2d..b449ca9 100644
--- a/src/osgEarthUtil/FeatureQueryTool
+++ b/src/osgEarthUtil/FeatureQueryTool
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthUtil/FeatureQueryTool.cpp b/src/osgEarthUtil/FeatureQueryTool.cpp
index f996236..8766d3b 100644
--- a/src/osgEarthUtil/FeatureQueryTool.cpp
+++ b/src/osgEarthUtil/FeatureQueryTool.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthUtil/Fog b/src/osgEarthUtil/Fog
index aee79da..db752ee 100644
--- a/src/osgEarthUtil/Fog
+++ b/src/osgEarthUtil/Fog
@@ -31,6 +31,18 @@
 
 namespace osgEarth { namespace Util
 {
+    /**
+    * Utility callback to add uniforms and track them for shader based osg::Fog.
+    * You must install this callback as an update callback on any osg::Fog you want to track in your application.
+    * ex:
+    * fog->setUpdateCallback(new osgEarth::Util::FogCallback());
+    */
+    class OSGEARTHUTIL_EXPORT FogCallback : public osg::StateAttributeCallback
+    {
+    public:
+        virtual void operator() (osg::StateAttribute* attr, osg::NodeVisitor* nv);        
+    };
+
      /**
      * Utility class for injecting fog capabilities into a VirtualProgram
      */
diff --git a/src/osgEarthUtil/Fog.cpp b/src/osgEarthUtil/Fog.cpp
index 86cdb69..c269883 100644
--- a/src/osgEarthUtil/Fog.cpp
+++ b/src/osgEarthUtil/Fog.cpp
@@ -20,6 +20,7 @@
 * along with this program.  If not, see <http://www.gnu.org/licenses/>
 */
 #include <osgEarthUtil/Fog>
+#include <osg/Fog>
 #include <osgEarthUtil/Shaders>
 #include <osgEarth/Registry>
 #include <osgEarth/Capabilities>
@@ -32,6 +33,30 @@ using namespace osgEarth;
 using namespace osgEarth::Util;
 
 
+void FogCallback::operator() (osg::StateAttribute* attr, osg::NodeVisitor* nv)
+{
+    // Update the oe_fog_algo uniform to reflect the current algorithm.
+    osg::Fog* fog = static_cast<osg::Fog*>(attr);
+    for (unsigned int i = 0; i < attr->getNumParents(); i++)
+    {
+        osg::StateSet* stateSet = attr->getParent(i);
+
+        if (fog->getMode() == osg::Fog::LINEAR)
+        {
+            stateSet->getOrCreateUniform("oe_fog_algo", osg::Uniform::INT)->set(0);
+        }
+        else if (fog->getMode() == osg::Fog::EXP)
+        {
+            stateSet->getOrCreateUniform("oe_fog_algo", osg::Uniform::INT)->set(1);
+        }
+        else if (fog->getMode() == osg::Fog::EXP2)
+        {
+            stateSet->getOrCreateUniform("oe_fog_algo", osg::Uniform::INT)->set(2);
+        }
+    }
+}
+
+
 FogEffect::FogEffect()
 {
 }
diff --git a/src/osgEarthUtil/Fog.frag.glsl b/src/osgEarthUtil/Fog.frag.glsl
index ca04503..64fdb27 100644
--- a/src/osgEarthUtil/Fog.frag.glsl
+++ b/src/osgEarthUtil/Fog.frag.glsl
@@ -1,13 +1,13 @@
 #version $GLSL_VERSION_STR
 $GLSL_DEFAULT_PRECISION_FLOAT
 
-#pragma vp_entryPoint "oe_fog_frag"
-#pragma vp_location   "fragment_lighting"
-#pragma vp_order      "0.7"
+#pragma vp_entryPoint oe_fog_frag
+#pragma vp_location   fragment_lighting
+#pragma vp_order      1.1
 
-varying float oe_fog_fogFactor;
+varying float oe_fogFactor;
 
 void oe_fog_frag(inout vec4 color)
 {        
-    color.rgb = mix( gl_Fog.color.rgb, color.rgb, oe_fog_fogFactor);
+    color.rgb = mix( gl_Fog.color.rgb, color.rgb, oe_fogFactor);
 }
\ No newline at end of file
diff --git a/src/osgEarthUtil/Fog.vert.glsl b/src/osgEarthUtil/Fog.vert.glsl
index d96eac7..fcd86a3 100644
--- a/src/osgEarthUtil/Fog.vert.glsl
+++ b/src/osgEarthUtil/Fog.vert.glsl
@@ -1,16 +1,31 @@
 #version $GLSL_VERSION_STR
 $GLSL_DEFAULT_PRECISION_FLOAT
 
-#pragma vp_entryPoint "oe_fog_vertex"
-#pragma vp_location   "vertex_view"
-#pragma vp_order      "0.5"
+#pragma vp_entryPoint oe_fog_vertex
+#pragma vp_location   vertex_view
 
-varying float oe_fog_fogFactor;
+uniform int oe_fog_algo;
+
+varying float oe_fogFactor;
 
 void oe_fog_vertex(inout vec4 vertexVIEW)
 {
     float z = length( vertexVIEW.xyz );
-    const float LOG2 = 1.442695;
-    oe_fog_fogFactor = exp2( -gl_Fog.density * gl_Fog.density * z * z * LOG2 );
-    oe_fog_fogFactor = clamp(oe_fog_fogFactor, 0.0, 1.0);
+
+	// linear fog
+	if (oe_fog_algo == 0)
+	{
+	  oe_fogFactor = clamp((gl_Fog.end - z) / (gl_Fog.end - gl_Fog.start), 0.0, 1.0);
+	}
+	// exp fog
+	else if (oe_fog_algo == 1)
+	{	
+	  oe_fogFactor = clamp(exp( -gl_Fog.density * z ), 0.0, 1.0);
+	}	
+	else
+	// exp2 fog
+	{
+        const float LOG2 = 1.442695;
+        oe_fogFactor = clamp(exp2( -gl_Fog.density * gl_Fog.density * z * z * LOG2 ), 0.0, 1.0);
+	}	
 }
\ No newline at end of file
diff --git a/src/osgEarthUtil/Formatter b/src/osgEarthUtil/Formatter
index c703ba2..ccbcf2d 100644
--- a/src/osgEarthUtil/Formatter
+++ b/src/osgEarthUtil/Formatter
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthUtil/GLSLColorFilter b/src/osgEarthUtil/GLSLColorFilter
index a43db11..c765b8c 100644
--- a/src/osgEarthUtil/GLSLColorFilter
+++ b/src/osgEarthUtil/GLSLColorFilter
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthUtil/GLSLColorFilter.cpp b/src/osgEarthUtil/GLSLColorFilter.cpp
index 725b987..0d514f4 100644
--- a/src/osgEarthUtil/GLSLColorFilter.cpp
+++ b/src/osgEarthUtil/GLSLColorFilter.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthUtil/GammaColorFilter b/src/osgEarthUtil/GammaColorFilter
index 8ae9eb8..04e32ee 100644
--- a/src/osgEarthUtil/GammaColorFilter
+++ b/src/osgEarthUtil/GammaColorFilter
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthUtil/GammaColorFilter.cpp b/src/osgEarthUtil/GammaColorFilter.cpp
index 37446a8..a8cd1b7 100644
--- a/src/osgEarthUtil/GammaColorFilter.cpp
+++ b/src/osgEarthUtil/GammaColorFilter.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthUtil/GeodeticGraticule b/src/osgEarthUtil/GeodeticGraticule
index d1fd3bf..c24ced4 100644
--- a/src/osgEarthUtil/GeodeticGraticule
+++ b/src/osgEarthUtil/GeodeticGraticule
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthUtil/GeodeticGraticule.cpp b/src/osgEarthUtil/GeodeticGraticule.cpp
index c36b373..627589e 100644
--- a/src/osgEarthUtil/GeodeticGraticule.cpp
+++ b/src/osgEarthUtil/GeodeticGraticule.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -23,7 +23,6 @@
 #include <osgEarthSymbology/Geometry>
 #include <osgEarthAnnotation/LabelNode>
 
-#include <osgEarth/Decluttering>
 #include <osgEarth/Registry>
 #include <osgEarth/NodeUtils>
 #include <osgEarth/Utils>
@@ -204,7 +203,9 @@ GeodeticGraticule::rebuild()
         }
     }
 
-    _root = new DrapeableNode( _mapNode.get(), false );
+    DrapeableNode* drapeable = new DrapeableNode();
+    drapeable->setDrapingEnabled( false );
+    _root = drapeable;
     this->addChild( _root );
 
     // need at least one level
@@ -268,8 +269,6 @@ GeodeticGraticule::buildTile( const TileKey& key, Map* map ) const
     if ( hasText )
     {
         labels = new osg::Group();
-        //TODO:  This is a bug, if you don't turn on decluttering the text labels are giant.  Need to determine what is wrong with LabelNodes without decluttering.
-        Decluttering::setEnabled( labels->getOrCreateStateSet(), true );
     }
 
     // spatial ref for features:
@@ -439,18 +438,24 @@ namespace osgEarth { namespace Util
     class GeodeticGraticuleFactory : public osgDB::ReaderWriter
     {
     public:
-        virtual const char* className()
+        GeodeticGraticuleFactory()
         {
             supportsExtension( GRATICULE_EXTENSION, "osgEarth graticule" );
+        }
+
+    public: // osgDB::ReaderWriter
+
+        const char* className() const
+        {
             return "osgEarth graticule LOD loader";
         }
 
-        virtual bool acceptsExtension(const std::string& extension) const
+        bool acceptsExtension(const std::string& extension) const
         {
             return osgDB::equalCaseInsensitive(extension, GRATICULE_EXTENSION);
         }
 
-        virtual ReadResult readNode(const std::string& uri, const Options* options) const
+        ReadResult readNode(const std::string& uri, const Options* options) const
         {        
             std::string ext = osgDB::getFileExtension( uri );
             if ( !acceptsExtension( ext ) )
@@ -474,7 +479,10 @@ namespace osgEarth { namespace Util
                     graticule = i->second.get();
             }
 
-            osg::Node* result = graticule->buildChildren( levelNum, x, y );
+            osg::Node* result = 0L;
+            if (graticule)
+                result = graticule->buildChildren( levelNum, x, y );
+
             return result ? ReadResult(result) : ReadResult::ERROR_IN_READING_FILE;
         }
     };
diff --git a/src/osgEarthUtil/Graticule.frag.glsl b/src/osgEarthUtil/Graticule.frag.glsl
index db9e591..33fdfc7 100644
--- a/src/osgEarthUtil/Graticule.frag.glsl
+++ b/src/osgEarthUtil/Graticule.frag.glsl
@@ -1,14 +1,15 @@
-#version 110
-#pragma vp_entryPoint "oe_graticule_fragment"
-#pragma vp_location   "fragment_coloring"
-#pragma vp_order      "0.6"
+#version $GLSL_VERSION_STR
+
+#pragma vp_entryPoint oe_graticule_fragment
+#pragma vp_location   fragment_lighting
+#pragma vp_order      1.1
 
 uniform float oe_graticule_lineWidth;
 uniform float oe_graticule_resolution;
 uniform vec4  oe_graticule_color;
 uniform mat4 osg_ViewMatrixInverse;
 
-varying vec2 oe_graticule_coord;
+in vec2 oe_graticule_coord;
 
 void oe_graticule_fragment(inout vec4 color)
 {
@@ -21,11 +22,15 @@ void oe_graticule_fragment(inout vec4 color)
 
     if ( any(lessThan(distanceToLine, dF)))
     {
+        // calculate some anti-aliasing
+        vec2 f = distanceToLine/dF;
+        float antialias = 1.0 - 2.0*abs(0.5 - min(f.x,f.y));
+
         // Fade out the lines as you get closer to the ground.
         vec3 eye = osg_ViewMatrixInverse[3].xyz;
         float hae = length(eye) - 6378137.0;
         float maxHAE = 2000.0;
-        float alpha = clamp(hae / maxHAE, 0.0, 1.0);
+        float alpha = clamp(hae / maxHAE, 0.0, 1.0) * antialias;
         color.rgb = mix(color.rgb, oe_graticule_color.rgb, oe_graticule_color.a * alpha);
     }
 }
\ No newline at end of file
diff --git a/src/osgEarthUtil/Graticule.vert.glsl b/src/osgEarthUtil/Graticule.vert.glsl
index 53121eb..20c53f5 100644
--- a/src/osgEarthUtil/Graticule.vert.glsl
+++ b/src/osgEarthUtil/Graticule.vert.glsl
@@ -1,12 +1,12 @@
-#version 110
-#pragma vp_entryPoint "oe_graticule_vertex"
-#pragma vp_location   "vertex_view"
-#pragma vp_order      "0.5"
+#version $GLSL_VERSION_STR
 
-uniform vec4 oe_tile_key;
-varying vec4 oe_layer_tilec;
+#pragma vp_entryPoint oe_graticule_vertex
+#pragma vp_location   vertex_view
+#pragma vp_order      0.5
 
-varying vec2 oe_graticule_coord;
+uniform vec4 oe_tile_key;
+out vec4 oe_layer_tilec;
+out vec2 oe_graticule_coord;
 
 void oe_graticule_vertex(inout vec4 vertex)
 {
diff --git a/src/osgEarthUtil/GraticuleExtension b/src/osgEarthUtil/GraticuleExtension
index 80081d7..be86b98 100644
--- a/src/osgEarthUtil/GraticuleExtension
+++ b/src/osgEarthUtil/GraticuleExtension
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -34,7 +34,8 @@ namespace osgEarth { namespace Util
      * Extension for loading the graticule node on demand.
      */
     class GraticuleExtension : public Extension,
-                               public ExtensionInterface<MapNode>
+                               public ExtensionInterface<MapNode>,
+                               public GraticuleOptions
     {
     public:
         META_Object(osgearth_ext_graticule, GraticuleExtension);
@@ -49,8 +50,9 @@ namespace osgEarth { namespace Util
 
     public: // Extension
 
-        void setDBOptions(const osgDB::Options* dbOptions);
+        virtual void setDBOptions(const osgDB::Options* dbOptions);
 
+        virtual const ConfigOptions& getConfigOptions() const { return *this; }
 
     public: // ExtensionInterface<MapNode>
 
@@ -63,7 +65,6 @@ namespace osgEarth { namespace Util
         GraticuleExtension(const GraticuleExtension& rhs, const osg::CopyOp& op) { }
 
     private:
-        const GraticuleOptions                 _options;
         osg::ref_ptr<const osgDB::Options>     _dbOptions;
         osg::ref_ptr<GraticuleTerrainEffect>   _effect;
         osg::ref_ptr<GraticuleNode>            _node;
diff --git a/src/osgEarthUtil/GraticuleExtension.cpp b/src/osgEarthUtil/GraticuleExtension.cpp
index b98f064..e6718aa 100644
--- a/src/osgEarthUtil/GraticuleExtension.cpp
+++ b/src/osgEarthUtil/GraticuleExtension.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -21,6 +21,7 @@
 #include "GraticuleNode"
 
 #include <osgEarth/MapNode>
+#include <osgEarth/TerrainEngineNode>
 #include <osgDB/FileNameUtils>
 
 using namespace osgEarth;
@@ -28,6 +29,8 @@ using namespace osgEarth::Util;
 
 #define LC "[GraticuleExtension] "
 
+REGISTER_OSGEARTH_EXTENSION( osgearth_graticule, GraticuleExtension );
+
 
 GraticuleExtension::GraticuleExtension()
 {
@@ -35,7 +38,7 @@ GraticuleExtension::GraticuleExtension()
 }
 
 GraticuleExtension::GraticuleExtension(const GraticuleOptions& options) :
-_options( options )
+GraticuleOptions( options )
 {
     //nop
 }
@@ -60,7 +63,7 @@ GraticuleExtension::connect(MapNode* mapNode)
         return false;
     }
 
-   _node = new GraticuleNode(mapNode, _options);
+   _node = new GraticuleNode(mapNode, *this);
     mapNode->addChild(_node.get());
     
     OE_INFO << LC << "Installed!\n";
@@ -78,32 +81,3 @@ GraticuleExtension::disconnect(MapNode* mapNode)
     _node = 0L;
     return true;
 }
-
-
-
-// Register the GraticuleExtension as a plugin
-class GraticulePlugin : public osgDB::ReaderWriter
-{
-public: // Plugin stuff
-
-    GraticulePlugin() {
-        supportsExtension( "osgearth_graticule", "osgEarth Graticule Extension" );
-    }
-
-    const char* className() {
-        return "osgEarth Graticule Extension";
-    }
-
-    virtual ~GraticulePlugin() { }
-
-    ReadResult readObject(const std::string& filename, const osgDB::Options* dbOptions) const
-    {
-        if ( !acceptsExtension(osgDB::getLowerCaseFileExtension(filename)) )
-            return ReadResult::FILE_NOT_HANDLED;
-
-        return ReadResult( new GraticuleExtension(Extension::getConfigOptions(dbOptions)) );
-    }
-};
-
-REGISTER_OSGPLUGIN(osgearth_graticule, GraticulePlugin)
-
diff --git a/src/osgEarthUtil/GraticuleNode b/src/osgEarthUtil/GraticuleNode
index 72b2002..7244149 100644
--- a/src/osgEarthUtil/GraticuleNode
+++ b/src/osgEarthUtil/GraticuleNode
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
@@ -107,6 +107,7 @@ namespace osgEarth { namespace Util
         const GraticuleOptions _options;
         bool _visible;
         double _metersPerPixel;
+        osg::Matrixd _viewMatrix;
 
         std::vector< double > _resolutions;
 
diff --git a/src/osgEarthUtil/GraticuleNode.cpp b/src/osgEarthUtil/GraticuleNode.cpp
index b0df0e7..a2094af 100644
--- a/src/osgEarthUtil/GraticuleNode.cpp
+++ b/src/osgEarthUtil/GraticuleNode.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
@@ -20,6 +20,7 @@
 * along with this program.  If not, see <http://www.gnu.org/licenses/>
 */
 #include "GraticuleNode"
+#include <osgEarth/TerrainEngineNode>
 
 using namespace osgEarth;
 using namespace osgEarth::Util;
@@ -84,7 +85,7 @@ _mapNode(mapNode),
     _formatter = new LatLongFormatter(osgEarth::Util::LatLongFormatter::FORMAT_DEGREES_MINUTES_SECONDS_TERSE, LatLongFormatter::USE_SYMBOLS |LatLongFormatter::USE_PREFIXES);
 
     // Initialize the resolution uniform
-    _resolutionUniform = mapNode->getTerrainEngine()->getTerrainStateSet()->getOrCreateUniform(GraticuleOptions::resolutionUniformName(), osg::Uniform::FLOAT);
+    _resolutionUniform = mapNode->getTerrainEngine()->getSurfaceStateSet()->getOrCreateUniform(GraticuleOptions::resolutionUniformName(), osg::Uniform::FLOAT);
     _resolutionUniform->set((float)_resolution);
 
     initLabelPool();
@@ -114,7 +115,7 @@ void GraticuleNode::setVisible(bool visible)
             setNodeMask(~0u);
             _mapNode->getTerrainEngine()->addEffect(_effect.get());
             // We need to re-initilize the uniform b/c the uniform may have been removed when the effect was removed.
-            _resolutionUniform = _mapNode->getTerrainEngine()->getTerrainStateSet()->getOrCreateUniform(GraticuleOptions::resolutionUniformName(), osg::Uniform::FLOAT);
+            _resolutionUniform = _mapNode->getTerrainEngine()->getSurfaceStateSet()->getOrCreateUniform(GraticuleOptions::resolutionUniformName(), osg::Uniform::FLOAT);
             _resolutionUniform->set((float)_resolution);
         }
         else
@@ -213,7 +214,7 @@ void GraticuleNode::updateLabels()
         int maxLatIndex = ceil(((extent.yMax() + 90)/resDegrees));
 
         // Generate horizontal labels
-        for (unsigned int i = minLonIndex; i <= maxLonIndex; i++)
+        for (int i = minLonIndex; i <= maxLonIndex; i++)
         {
             GeoPoint point(srs, -180.0 + (double)i * resDegrees, _lat + (_centerOffset.y() * degOffset), 0, ALTMODE_ABSOLUTE);
             LabelNode* label = _labelPool[labelIndex++];
@@ -231,7 +232,7 @@ void GraticuleNode::updateLabels()
 
 
         // Generate the vertical labels
-        for (unsigned int i = minLatIndex; i <= maxLatIndex; i++)
+        for (int i = minLatIndex; i <= maxLatIndex; i++)
         {
             GeoPoint point(srs, _lon + (_centerOffset.x() * degOffset), -90.0 + (double)i * resDegrees, 0, ALTMODE_ABSOLUTE);
             // Skip drawing labels at the poles
@@ -264,64 +265,71 @@ void GraticuleNode::traverse(osg::NodeVisitor& nv)
 
         osg::Vec3d vp = cv->getViewPoint();
 
+        osg::Matrixd viewMatrix = *cv->getModelViewMatrix();
 
-        GeoPoint eyeGeo;
-        eyeGeo.fromWorld( _mapNode->getMapSRS(), vp );
-        _lon = eyeGeo.x();
-        _lat = eyeGeo.y();
+        // Only update if the view matrix has changed.
+        if (viewMatrix != _viewMatrix)
+        {            
+            GeoPoint eyeGeo;
+            eyeGeo.fromWorld( _mapNode->getMapSRS(), vp );
+            _lon = eyeGeo.x();
+            _lat = eyeGeo.y();            
 
-        osg::Viewport* viewport = cv->getViewport();
+            osg::Viewport* viewport = cv->getViewport();
 
-        float centerX = viewport->x() + viewport->width() / 2.0;
-        float centerY = viewport->y() + viewport->height() / 2.0;
+            float centerX = viewport->x() + viewport->width() / 2.0;
+            float centerY = viewport->y() + viewport->height() / 2.0;
 
-        float offsetCenterX = centerX;
-        float offsetCenterY = centerY;
+            float offsetCenterX = centerX;
+            float offsetCenterY = centerY;
 
-        bool hitValid = false;
+            bool hitValid = false;
 
-        // Try the center of the screen.
-        if(_mapNode->getTerrain()->getWorldCoordsUnderMouse(cv->getCurrentCamera()->getView(), centerX, centerY, _focalPoint))
-        {
-            hitValid = true;
-        }
+            // Try the center of the screen.
+            if(_mapNode->getTerrain()->getWorldCoordsUnderMouse(cv->getCurrentCamera()->getView(), centerX, centerY, _focalPoint))
+            {
+                hitValid = true;
+            }
 
-        if (hitValid)
-        {
-            GeoPoint focalGeo;
-            focalGeo.fromWorld( _mapNode->getMapSRS(), _focalPoint );
-            _lon = focalGeo.x();
-            _lat = focalGeo.y();
-        }
-       
-    
-        double targetResolution = (_viewExtent.height() / 180.0) / _options.gridLines().get();
+            if (hitValid)
+            {
+                GeoPoint focalGeo;
+                focalGeo.fromWorld( _mapNode->getMapSRS(), _focalPoint );
+                _lon = focalGeo.x();
+                _lat = focalGeo.y();
+                // We only store the previous view matrix if we actually got a hit.  Otherwise we still need to update.
+                _viewMatrix = viewMatrix;
+            }
 
-        double resolution = _resolutions[0];
-        for (unsigned int i = 0; i < _resolutions.size(); i++)
-        {
-            resolution = _resolutions[i];
-            if (resolution <= targetResolution)
+
+            double targetResolution = (_viewExtent.height() / 180.0) / _options.gridLines().get();
+
+            double resolution = _resolutions[0];
+            for (unsigned int i = 0; i < _resolutions.size(); i++)
             {
-                break;
+                resolution = _resolutions[i];
+                if (resolution <= targetResolution)
+                {
+                    break;
+                }
             }
-        }
 
-        // Trippy
-        //resolution = targetResolution;
+            // Trippy
+            //resolution = targetResolution;
 
-        _viewExtent = getViewExtent( cv );
+            _viewExtent = getViewExtent( cv );
 
-        // Try to compute an approximate meters to pixel value at this view.
-        double fovy, aspectRatio, zNear, zFar;
-        cv->getProjectionMatrix()->getPerspective(fovy, aspectRatio, zNear, zFar);
-        double dist = osg::clampAbove(eyeGeo.z(), 1.0);
-        double halfWidth = osg::absolute( tan(osg::DegreesToRadians(fovy/2.0)) * dist );
-        _metersPerPixel = (2.0 * halfWidth) / (double)viewport->height();
+            // Try to compute an approximate meters to pixel value at this view.
+            double fovy, aspectRatio, zNear, zFar;
+            cv->getProjectionMatrix()->getPerspective(fovy, aspectRatio, zNear, zFar);
+            double dist = osg::clampAbove(eyeGeo.z(), 1.0);
+            double halfWidth = osg::absolute( tan(osg::DegreesToRadians(fovy/2.0)) * dist );
+            _metersPerPixel = (2.0 * halfWidth) / (double)viewport->height();
 
-        if (_resolution != resolution)
-        {
-            setResolution(resolution);
+            if (_resolution != resolution)
+            {
+                setResolution(resolution);
+            }
         }
     }
     osg::Group::traverse(nv);
diff --git a/src/osgEarthUtil/GraticuleOptions b/src/osgEarthUtil/GraticuleOptions
index bacba47..f7c76f0 100644
--- a/src/osgEarthUtil/GraticuleOptions
+++ b/src/osgEarthUtil/GraticuleOptions
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -66,7 +66,7 @@ namespace osgEarth { namespace Util
         GraticuleOptions( const ConfigOptions& opt =ConfigOptions() ) : DriverConfigOptions( opt )
         {
             setDriver( "graticule" );
-            _lineWidth.init ( 1.0f );
+            _lineWidth.init ( 2.0f );
             _color.init     ( Color(Color::Yellow, 0.5f) );
             _labelColor.init ( Color::White );
             _gridLines.init(10);
diff --git a/src/osgEarthUtil/GraticuleTerrainEffect.cpp b/src/osgEarthUtil/GraticuleTerrainEffect.cpp
index c4f75c3..37dea57 100644
--- a/src/osgEarthUtil/GraticuleTerrainEffect.cpp
+++ b/src/osgEarthUtil/GraticuleTerrainEffect.cpp
@@ -46,7 +46,7 @@ GraticuleTerrainEffect::onInstall(TerrainEngineNode* engine)
     if ( engine )
     {
         // shader components
-        osg::StateSet* stateset = engine->getTerrainStateSet();
+        osg::StateSet* stateset = engine->getSurfaceStateSet();
         VirtualProgram* vp = VirtualProgram::getOrCreate(stateset);
 
         // configure shaders
@@ -69,7 +69,7 @@ GraticuleTerrainEffect::onInstall(TerrainEngineNode* engine)
 void
 GraticuleTerrainEffect::onUninstall(TerrainEngineNode* engine)
 {
-    osg::StateSet* stateset = engine->getTerrainStateSet();
+    osg::StateSet* stateset = engine->getSurfaceStateSet();
     if ( stateset )
     {
         VirtualProgram* vp = VirtualProgram::get(stateset);
diff --git a/src/osgEarthUtil/HSLColorFilter b/src/osgEarthUtil/HSLColorFilter
index 3f6f69d..ea59461 100644
--- a/src/osgEarthUtil/HSLColorFilter
+++ b/src/osgEarthUtil/HSLColorFilter
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthUtil/HSLColorFilter.cpp b/src/osgEarthUtil/HSLColorFilter.cpp
index f77fe79..0296a1a 100644
--- a/src/osgEarthUtil/HSLColorFilter.cpp
+++ b/src/osgEarthUtil/HSLColorFilter.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthUtil/HTM b/src/osgEarthUtil/HTM
index b74584f..d3ad97a 100644
--- a/src/osgEarthUtil/HTM
+++ b/src/osgEarthUtil/HTM
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
@@ -31,49 +31,41 @@
 
 namespace osgEarth { namespace Util
 {
-    class HTMNode;
+    struct HTMSettings
+    {
+        unsigned _maxLeaves;
+        float _maxLeafRange;
+        int _debugCount;
+        int _debugFrame;
+    };
 
     /**
-     * Hierarchical Triangular Mesh group
+     * Hierarchical Triangular Mesh group - for geocentric maps only
      * http://www.geog.ucsb.edu/~hu/papers/spatialIndex.pdf
      *
      * An osg::Group that automatically organizes its contents spatially
-     * in order to improve culling performance and proximity search.
-     *
-     * Note! This group will improve performance when you have a huge
-     * number of entities and you zoom in to a smaller area. It will NOT
-     * improve the performance when viewing the entire set from a far
-     * range.
+     * in order to improve culling performance.
      */
     class OSGEARTHUTIL_EXPORT HTMGroup : public osg::Group
     {
     public:
         HTMGroup();
 
-        /** total number of objects in the group. */
-        unsigned dataCount() const { return _dataCount; }
-
-        /** The maximum number of objects to hold in an index cell before
-            splitting it up into smaller parts. */
-        unsigned getSplitThreshold() const { return _splitThreshold; }
+        /**
+         * Sets the maximum number of leaf nodes that can exist at a
+         * given level in the graph before it subdivides into a more refined
+         * index. The default is 16.
+         */
+        void setMaxLeaves(unsigned value);
+        float getMaxLeaves() const { return _settings._maxLeaves; }
 
-        /** The minimum number of objects across a set of child cells before
-            merging them back into a single cell. */
-        unsigned getMergeThreshold() const { return _mergeThreshold; }
+        /**
+         * Sets the maximum visibility range of any leaf node in this graph.
+         * @param[in ] range Maximum visibile range (meters); default is 50,000m.
+         */
+        void setMaxLeafRange(float range);
+        float getMaxLeafRange() const { return _settings._maxLeafRange; }
 
-        /** enable or disable clustering (experimental) */
-        void setCluster( bool value ) { _cluster = value; }
-        bool getCluster() const       { return _cluster; }
-
-        /** activate debugging mode */
-        void setDebug() { _debug = true; }
-        bool getDebug() const { return _debug; }
-
-        /** check a node to see whether we need to move it. */
-        bool refresh(osg::Node* node);
-
-        /** removes a node from the group. */
-        bool remove(osg::Node* node);
 
     public: // osg::Group
 
@@ -91,22 +83,14 @@ namespace osgEarth { namespace Util
         virtual bool replaceChild(osg::Node* origChild, osg::Node* newChild);
         virtual bool setChild(unsigned index, osg::Node* node);
 
-        /** custom traversal */
-        virtual void traverse(osg::NodeVisitor& nv);
-
     protected:
         virtual ~HTMGroup() { }
 
         bool insert(osg::Node* node);
 
-        unsigned _dataCount;
-        bool     _debug;
-        bool     _cluster;
-        unsigned _splitThreshold;
-        unsigned _mergeThreshold;
+        void reinitialize();
 
-        typedef std::map<osg::Node*, HTMNode*> NodeMap;
-        NodeMap _nodeTable;
+        HTMSettings _settings;
     };
 
 
@@ -116,47 +100,29 @@ namespace osgEarth { namespace Util
     class HTMNode : public osg::Group
     {
     public:
-        HTMNode(HTMGroup* root, const osg::Vec3d& v0, const osg::Vec3d& v1, const osg::Vec3d& v2);
+        HTMNode(HTMSettings& settings,
+                const osg::Vec3d& v0, const osg::Vec3d& v1, const osg::Vec3d& v2);
+        
+        bool contains(const osg::Vec3d& p) const {
+            return _tri.contains(p);
+        }
 
-    public: // osg::Group
+        void insert(osg::Node* node);
 
-        virtual void traverse(osg::NodeVisitor& nv);
+    public:
+        void traverse(osg::NodeVisitor& nv);
 
     protected:
         virtual ~HTMNode() { }
 
-        HTMNode* insert(osg::Node* node);
-
-        bool remove(osg::Node* node);
-
-        bool refresh(osg::Node* node);
-
         void split();
 
-        void merge();
-
-        bool isLeaf() const {
-            return getNumChildren() == 0;
-        }
-
-        bool contains(const osg::Vec3d& p) const {
-            return _tri.contains(p);
-        }
-
-        unsigned dataCount() const {
-            return _dataCount;
-        }
-
-        HTMNode* findLeaf(osg::Node*);
-
         // test whether the node's triangle lies entirely withing a frustum
         bool entirelyWithin(const osg::Polytope& tope) const;
         
         // test whether the node's triangle intersects a frustum
         bool intersects(const osg::Polytope& tope) const;
 
-        osg::BoundingSphere computeBound() const;
-
     private:
 
         struct PolytopeDP : public osg::Polytope
@@ -179,17 +145,10 @@ namespace osgEarth { namespace Util
             }
         };
 
-        typedef std::list<osg::ref_ptr<osg::Node> > NodeList;
-
-        Triangle      _tri;
-        NodeList      _data;
-        unsigned      _dataCount;
-        HTMGroup*     _root;
-        osg::ref_ptr<osg::Geode> _debugGeode;
-        osg::ref_ptr<osg::Node>  _clusterNode;
-        osg::BoundingSphere      _bs;
 
-        friend class HTMGroup;
+        Triangle _tri;
+        bool     _isLeaf;
+        HTMSettings& _settings;
     };
 
 } } // namesapce osgEarth::Util
diff --git a/src/osgEarthUtil/HTM.cpp b/src/osgEarthUtil/HTM.cpp
index 5f26eab..6efbee1 100644
--- a/src/osgEarthUtil/HTM.cpp
+++ b/src/osgEarthUtil/HTM.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
@@ -27,14 +27,15 @@
 #include <osg/Geometry>
 #include <osgText/Text>
 
-#define LC "[HTMGroup] "
-
 using namespace osgEarth;
 using namespace osgEarth::Util;
 using namespace osgEarth::Annotation;
 
 //-----------------------------------------------------------------------
 
+#undef  LC
+#define LC "[HTMGroup] "
+
 bool
 HTMNode::PolytopeDP::contains(const osg::Vec3d& p) const
 {
@@ -90,197 +91,80 @@ HTMNode::Triangle::getMidpoints(osg::Vec3d* w) const
 
 //-----------------------------------------------------------------------
 
-HTMNode::HTMNode(HTMGroup*         root,
-                 const osg::Vec3d& v0, 
-                 const osg::Vec3d& v1, 
-                 const osg::Vec3d& v2)
+HTMNode::HTMNode(HTMSettings& settings,
+                 const osg::Vec3d& v0, const osg::Vec3d& v1, const osg::Vec3d& v2) :
+_settings(settings)
 {
-    this->setCullingActive(false);
-
-    _root = root;
+    _isLeaf = true;
     _tri.set( v0, v1, v2 );
-    _dataCount = 0;
-
-    // init the bounding sphere
-    _bs.expandBy( _tri._v[0] * 6380000);
-    _bs.expandBy( _tri._v[1] * 6380000);
-    _bs.expandBy( _tri._v[2] * 6380000);
-
-    if ( true )
-    {
-        _debugGeode = new osg::Geode();
-        osg::Geometry* g = new osg::Geometry();
-        osg::Vec3Array* v = new osg::Vec3Array();
-        v->push_back( v0 * 6372000 );
-        v->push_back( v1 * 6372000 );
-        v->push_back( v2 * 6372000 );
-        g->setVertexArray( v );
-        osg::Vec4Array* c = new osg::Vec4Array();
-        c->push_back( osg::Vec4(1,1,0,1) );
-        g->setColorArray( c );
-        g->setColorBinding( osg::Geometry::BIND_OVERALL );
-        g->addPrimitiveSet( new osg::DrawArrays(GL_LINE_LOOP, 0, 3) );
-        g->getOrCreateStateSet()->setMode(GL_LIGHTING, 0);
-        _debugGeode->addDrawable( g );
-        _debugGeode->getOrCreateStateSet()->setRenderBinDetails(INT_MAX, "DepthSortedBin");
-        _debugGeode->getOrCreateStateSet()->setMode(GL_DEPTH_TEST, 0);
-    }
-
-    {
-        osgText::Text* text = new osgText::Text();
-        text->setText("Hi.");
-        text->setCharacterSizeMode(osgText::Text::SCREEN_COORDS);
-        text->setCharacterSize(48.0f);
-        text->setAutoRotateToScreen(true);
-        text->setPosition( ((v0+v1+v2)/(v0+v1+v2).length()) * 6400000 );
-        text->setDataVariance(osg::Object::DYNAMIC);
-        text->setFont( Registry::instance()->getDefaultFont() );
-        text->setStateSet(new osg::StateSet());
-        osg::Geode* geode = new osg::Geode();
-        geode->addDrawable(text);
-        geode->getOrCreateStateSet()->setRenderBinDetails(INT_MAX, "DepthSortedBin");
-        geode->getOrCreateStateSet()->setMode(GL_DEPTH_TEST, 0);
-        geode->setCullingActive( false );
-        _clusterNode = geode;
-    }
 }
 
-HTMNode*
-HTMNode::insert(osg::Node* node)
+void
+HTMNode::traverse(osg::NodeVisitor& nv)
 {
-    HTMNode* leaf = this;
-
-    dirtyBound();
-
-    _data.push_back( node );
-
-    if (_data.size() >= _root->getSplitThreshold() &&
-        getNumChildren() == 0 )
-    {
-        split();
-    }
-
-    if ( _children.size() > 0 )
+    if ( nv.getVisitorType() == nv.CULL_VISITOR )
     {
-        const osg::Vec3d& p = node->getBound().center();
-
-        for(unsigned i=0; i<_children.size(); ++i)
+#if 0
+        if ( _isLeaf )
         {
-            HTMNode* child = dynamic_cast<HTMNode*>(_children[i].get());
-            if ( child && child->contains(p) )
+            if (_settings._debugFrame != nv.getFrameStamp()->getFrameNumber())
             {
-                leaf = child->insert(node);
-                break;
+                OE_NOTICE << "Frame " << _settings._debugFrame << ": " << _settings._debugCount << std::endl;
+                _settings._debugCount = 0;
+                _settings._debugFrame = nv.getFrameStamp()->getFrameNumber();
             }
+            _settings._debugCount += getNumChildren();
         }
-    }
-
-    _dataCount++;
+#endif
 
-    dynamic_cast<osgText::Text*>(dynamic_cast<osg::Geode*>(_clusterNode.get())->getDrawable(0))
-        ->setText( Stringify() << _dataCount );
+        const osg::BoundingSphere& bs = getBound();
 
-    return leaf;
-}
-
-bool
-HTMNode::remove(osg::Node* node)
-{
-    NodeList::iterator i = std::find( _data.begin(), _data.end(), node );
-    if ( i != _data.end() )
-    {
-        dirtyBound();
-
-        _data.erase( i );
-        _dataCount--;
-
-        bool found = false;
-        for(unsigned i=0; i<_children.size() && !found; ++i)
+        if ( nv.getDistanceToViewPoint(bs.center(), true) <= (bs.radius() + _settings._maxLeafRange) )
         {
-            HTMNode* child = dynamic_cast<HTMNode*>(_children[i].get());
-            if ( child )
-            {
-                found = child->remove( node );
-            }
+            osg::Group::traverse( nv );
         }
-
-        return found;
     }
     else
     {
-        return false;
+        osg::Group::traverse( nv );
     }
 }
 
-HTMNode*
-HTMNode::findLeaf(osg::Node* node)
+void
+HTMNode::insert(osg::Node* node)
 {
-    HTMNode* leaf = 0L;
-
-    NodeList::iterator i = std::find( _data.begin(), _data.end(), node );
-    if ( i != _data.end() )
+    if ( _isLeaf )
     {
-        leaf = this;
-        for(unsigned i=0; i<_children.size(); ++i)
+        if ((getNumChildren() < _settings._maxLeaves) ||
+            (getBound().radius() < _settings._maxLeafRange))
         {
-            HTMNode* child = dynamic_cast<HTMNode*>(_children[i].get());
-            HTMNode* leaf2 = child->findLeaf( node );
-            if ( leaf2 )
-            {
-                leaf = leaf2;
-                break;
-            }
+            addChild( node );
         }
-    }
 
-    return leaf;
-}
-
-bool
-HTMNode::refresh(osg::Node* node)
-{
-    const osg::Vec3d& p = node->getBound().center();
-
-    if ( contains(p) )
-    {
-        // already in this node; if there are children, re-insert
-        // into the new child.
-        if ( _children.size() > 0 )
+        else
         {
-            for(unsigned i=0; i<_children.size(); ++i)
-            {
-                HTMNode* child = dynamic_cast<HTMNode*>(_children[i].get());
-                if ( child && child->contains(p) )
-                {
-                    child->insert(node);
-                    break;
-                }
-            }
+            split();
+            insert( node );
         }
-        return true; // done.
     }
+
     else
     {
-        std::remove( _data.begin(), _data.end(), node );
-        _dataCount--;
+        const osg::Vec3d& p = node->getBound().center();
 
-        HTMNode* parentNode = dynamic_cast<HTMNode*>( getParent(0) );
-        if ( parentNode )
-        {
-            return parentNode->refresh( node );
-        }
-        HTMGroup* parentGroup = dynamic_cast<HTMGroup*>( getParent(0) );
-        if ( parentGroup )
+        for(unsigned i=0; i<_children.size(); ++i)
         {
-            return parentGroup->addChild( node );
+            HTMNode* child = dynamic_cast<HTMNode*>(_children[i].get());
+            if ( child && child->contains(p) )
+            {
+                child->insert(node);
+                break;
+            }
         }
-
-        // should never get here
-        OE_WARN << LC << "trouble." << std::endl;
-        return false;
     }
 }
 
+
 void
 HTMNode::split()
 {
@@ -292,19 +176,16 @@ HTMNode::split()
 
     // split into four children, each wound CCW
     HTMNode* c[4];
-    c[0] = new HTMNode(_root, _tri._v[0], w[0], w[2]);
-    c[1] = new HTMNode(_root, _tri._v[1], w[1], w[0]);
-    c[2] = new HTMNode(_root, _tri._v[2], w[2], w[1]);
-    c[3] = new HTMNode(_root, w[0], w[1], w[2]);
-
+    c[0] = new HTMNode(_settings, _tri._v[0], w[0], w[2]);
+    c[1] = new HTMNode(_settings, _tri._v[1], w[1], w[0]);
+    c[2] = new HTMNode(_settings, _tri._v[2], w[2], w[1]);
+    c[3] = new HTMNode(_settings, w[0], w[1], w[2]);
+    
     // distibute the data amongst the children
-    for(NodeList::iterator i = _data.begin(); i != _data.end(); ++i)
+    for(osg::NodeList::iterator i = _children.begin(); i != _children.end(); ++i)
     {
-        osg::Node* node = i->get();
-        const osg::BoundingSphere& bs = node->getBound();
-        
-        osg::Vec3d p = bs.center();
-        p.normalize(); // need?
+        osg::Node* node = i->get();        
+        const osg::Vec3d& p = node->getBound().center();
 
         for(unsigned j=0; j<4; ++j)
         {
@@ -316,263 +197,97 @@ HTMNode::split()
         }
     }
 
-    // add the node children
+    // remove the leaves from this node
+    osg::Group::removeChildren(0, getNumChildren());
+
+    // add the new subnodes to this node.
     for(unsigned i=0; i<4; ++i)
     {
         c[i]->setName( Stringify() << getName() << i );
         osg::Group::addChild( c[i] );
-
-        OE_DEBUG << LC << "  htmid " << c[i]->getName() << " size = " << c[i]->dataCount() << std::endl;
     }
-}
-
-void
-HTMNode::merge()
-{
-    dirtyBound();
 
-    OE_INFO << LC << "Merging htmid:" << getName() << std::endl;
-    //todo
+    _isLeaf = false;
 }
 
-bool
-HTMNode::entirelyWithin(const osg::Polytope& tope) const
-{
-    const osg::Polytope::PlaneList& planes = tope.getPlaneList();
-    for(unsigned i=0; i<3; ++i)
-    {
-        osg::Vec3d v = _tri._v[i] * 6372000;
-        for( osg::Polytope::PlaneList::const_iterator plane = planes.begin(); plane != planes.end(); ++plane )
-        {
-            if ( plane->distance(v) < 0.0 )
-                return false;
-        }
-    }
-    return true;
-}
+//-----------------------------------------------------------------------
 
-bool
-HTMNode::intersects(const osg::Polytope& tope) const
+HTMGroup::HTMGroup()
 {
-    const osg::Polytope::PlaneList& planes = tope.getPlaneList();
+    _settings._maxLeaves = 16;
+    _settings._maxLeafRange = 50000.0f;
 
-    for( osg::Polytope::PlaneList::const_iterator plane = planes.begin(); plane != planes.end(); ++plane )
-    {
-        unsigned pointsVisibleToPlane = 0;
-
-        for(unsigned i=0; i<3; ++i)
-        {
-            osg::Vec3d v;
-            
-            v = _tri._v[i] * 6000000;
-            if ( plane->distance(v) >= 0.0 )
-                ++pointsVisibleToPlane;
-
-            v = _tri._v[i] * 12000000;
-            if ( plane->distance(v) >= 0.0 )
-                ++pointsVisibleToPlane;
-        }
-
-        // if none of the points are visible to any one plane, intersection fails.
-        if ( pointsVisibleToPlane == 0 )
-            return false;
-    }
+    // hopefully prevent the OSG optimizer from altering this graph:
+    setDataVariance( osg::Object::DYNAMIC );
 
-    return true;
+    reinitialize();
 }
 
 void
-HTMNode::traverse(osg::NodeVisitor& nv)
+HTMGroup::setMaxLeaves(unsigned maxLeaves)
 {
-    bool accepted   = true;
-    bool inRange    = true;
-    bool cull       = nv.getVisitorType()   == nv.CULL_VISITOR;
-    bool activeOnly = nv.getTraversalMode() == nv.TRAVERSE_ACTIVE_CHILDREN;
-
-    osg::Polytope* frustum = 0L;
-
-    if ( activeOnly )
-    {
-        // first make sure this node is in range.
-        //float alt = nv.getViewPoint().length() - 6300000;
-        //inRange = alt <= _bs.radius()*5.0f;
-        
-        //float d = nv.getDistanceToViewPoint(_bs.center(),true);
-        //inRange = d <= _bs.radius()*5.0f;
-
-        // if this isn't a leaf node (i.e. has child nodes), check whether we
-        // can "trivially accept" them all.
-        if ( !isLeaf() && inRange )
-        {
-            osgUtil::CullVisitor* cv = Culling::asCullVisitor(nv);
-            if ( cv )
-            {
-                frustum = &cv->getCurrentCullingSet().getFrustum();
-                if ( entirelyWithin(*frustum) )
-                {
-                    OE_DEBUG << LC << getName() << ": trivially accepted. yay!" << std::endl;
-                }
-                else
-                {
-                    accepted = false;
-                }
-            }
-        }
-    }
+    _settings._maxLeaves = maxLeaves;
 
-    if ( accepted )
-    {
-        // should we draw a clustering node instead of the data?
-        if ( _root->getCluster() && (!isLeaf() || !inRange) )
-        {
-            _clusterNode->accept(nv);
-        }
-
-        // draw the data itself?
-        else if ( inRange )
-        {
-            for(NodeList::iterator i = _data.begin(); i != _data.end(); ++i)
-            {
-                i->get()->accept( nv );
-            }
-        }
-
-        // draw a debugging node?
-        if ( _debugGeode.valid() )
-        {
-            _debugGeode->accept( nv );
-        }
-    }
-    else
-    {
-        // traverse the children.
-        if ( frustum )
-        {
-            // A frustum is available, so cull against it
-            for(unsigned i=0; i<_children.size(); ++i)
-            {
-                HTMNode* child = static_cast<HTMNode*>(_children[i].get());
-                //if ( frustum->contains(child->getBound()) )
-                if ( child->intersects(*frustum) )
-                {
-                    child->accept( nv );
-                }
-            }
-        }
-        else
-        {
-            // no frustum, just traverse them all as normal
-            osg::Group::traverse( nv );
-        }
-    }
+    reinitialize();
 }
 
-osg::BoundingSphere
-HTMNode::computeBound() const
+void
+HTMGroup::setMaxLeafRange(float range)
 {
-    return _bs;
-}
-
+    _settings._maxLeafRange = range;
 
-//-----------------------------------------------------------------------
+    reinitialize();
+}
 
-HTMGroup::HTMGroup() :
-_dataCount     ( 0 ),
-_splitThreshold( 48 ),
-_mergeThreshold( 48 ),
-_debug         ( false ),
-_cluster       ( false )
+void
+HTMGroup::reinitialize()
 {
-    // hopefully prevent the OSG optimizer from altering this graph:
-    setDataVariance( osg::Object::DYNAMIC );
+    _children.clear();
+
+    double rx = 1.0;
+    double ry = 1.0;
+    double rz = 1.0;
 
     // assemble the base manifold of 8 triangles.
-    osg::Vec3d v0( 0, 0, 1);      // lat= 90  long=  0
-    osg::Vec3d v1( 1, 0, 0);      // lat=  0  long=  0
-    osg::Vec3d v2( 0, 1, 0);      // lat=  0  long= 90
-    osg::Vec3d v3(-1, 0, 0);      // lat=  0  long=180
-    osg::Vec3d v4( 0,-1, 0);      // lat=  0  long=-90
-    osg::Vec3d v5( 0, 0,-1);      // lat=-90  long=  0
+    osg::Vec3d v0( 0,   0,   rz);     // lat= 90  long=  0
+    osg::Vec3d v1( rx,  0,   0);      // lat=  0  long=  0
+    osg::Vec3d v2( 0,   ry,  0);      // lat=  0  long= 90
+    osg::Vec3d v3(-rx,  0,   0);      // lat=  0  long=180
+    osg::Vec3d v4( 0,  -ry,  0);      // lat=  0  long=-90
+    osg::Vec3d v5( 0,   0,  -rz);     // lat=-90  long=  0
 
     // CCW triangles.
-    osg::Group::addChild( new HTMNode(this, v0, v1, v2) );
-    osg::Group::addChild( new HTMNode(this, v0, v2, v3) );
-    osg::Group::addChild( new HTMNode(this, v0, v3, v4) );
-    osg::Group::addChild( new HTMNode(this, v0, v4, v1) );
-    osg::Group::addChild( new HTMNode(this, v5, v1, v4) );
-    osg::Group::addChild( new HTMNode(this, v5, v4, v3) );
-    osg::Group::addChild( new HTMNode(this, v5, v3, v2) );
-    osg::Group::addChild( new HTMNode(this, v5, v2, v1) );
-
-    // HTMIDs.
-    for(unsigned i=0; i<8; ++i)
-    {
-        getChild(i)->setName( Stringify() << i );
-    }
+    osg::Group::addChild( new HTMNode(_settings, v0, v1, v2) );
+    osg::Group::addChild( new HTMNode(_settings, v0, v2, v3) );
+    osg::Group::addChild( new HTMNode(_settings, v0, v3, v4) );
+    osg::Group::addChild( new HTMNode(_settings, v0, v4, v1) );
+    osg::Group::addChild( new HTMNode(_settings, v5, v1, v4) );
+    osg::Group::addChild( new HTMNode(_settings, v5, v4, v3) );
+    osg::Group::addChild( new HTMNode(_settings, v5, v3, v2) );
+    osg::Group::addChild( new HTMNode(_settings, v5, v2, v1) );
 }
 
 bool
 HTMGroup::insert(osg::Node* node)
 {
     osg::Vec3d p = node->getBound().center();
-    p.normalize();
+    p.normalize(); // need?
 
     bool inserted = false;
 
-    for(unsigned i=0; i<8; ++i)
+    for(unsigned i=0; i<_children.size(); ++i)
     {
         HTMNode* child = static_cast<HTMNode*>(_children[i].get());
         if ( child->contains(p) )
         {
             child->insert(node);
             inserted = true;
-            //_dataCount++;
             break;
         }
     }
 
     return inserted;
 }
-
-bool
-HTMGroup::remove(osg::Node* node)
-{
-    bool found = false;
-
-    for(unsigned i=0; i<8 && !found; ++i)
-    {
-        HTMNode* child = static_cast<HTMNode*>(_children[i].get());
-        found = child->remove( node );
-    }
-
-    return found;
-}
-
-bool
-HTMGroup::refresh(osg::Node* node)
-{
-    HTMNode* leaf = 0L;
-
-    for(unsigned i=0; i<8 && !leaf; ++i)
-    {
-        HTMNode* child = static_cast<HTMNode*>(_children[i].get());
-        leaf = child->findLeaf( node );
-        if ( leaf )
-        {
-            leaf->refresh( node );
-            break;
-        }
-    }
-
-    return leaf != 0L;
-}
-
-void 
-HTMGroup::traverse(osg::NodeVisitor& nv)
-{
-    osg::Group::traverse(nv);
-}
-
 bool 
 HTMGroup::addChild(osg::Node* child)
 {
diff --git a/src/osgEarthUtil/LODBlending b/src/osgEarthUtil/LODBlending
index 5efef86..b745bbc 100644
--- a/src/osgEarthUtil/LODBlending
+++ b/src/osgEarthUtil/LODBlending
@@ -30,6 +30,78 @@
 
 namespace osgEarth { namespace Util
 {
+    class LODBlendingOptions : public ConfigOptions
+    {
+    public:
+        LODBlendingOptions( const ConfigOptions& opt =ConfigOptions() ) :
+            ConfigOptions( opt ),
+            _delay         ( 0.0f ),
+            _duration      ( 0.25f ),
+            _vscale        ( 1.0f ),
+            _blendImagery  ( true ),
+            _blendElevation( true )
+        {
+            fromConfig( _conf );
+        }
+
+    public:
+
+        /** Sets the delay (in seconds) between the time the tile appears
+            and when it starts its transition */
+        optional<float>& delay() { return _delay; }
+        const optional<float>& delay() const { return _delay; }
+
+        /** Sets the duration of the transition */
+        optional<float>& duration() { return _duration; }
+        const optional<float>& duration() const { return _duration; }
+
+        /** Vertical scale factor to apply to elevation */
+        optional<float>& verticalScale() { return _vscale; }
+        const optional<float>& verticalScale() const { return _vscale; }
+
+        /** Whether to blend imagery (default=true) */
+        optional<bool>& blendImagery() { return _blendImagery; }
+        const optional<bool>& blendImagery() const { return _blendImagery; }
+
+        /** Whether to blend elevation (default=true) */
+        optional<bool>& blendElevation() { return _blendElevation; }
+        const optional<bool>& blendElevation() const { return _blendElevation; }
+
+    public:
+        Config getConfig() const {
+            Config conf = ConfigOptions::getConfig();
+            conf.addIfSet("delay", _delay);
+            conf.addIfSet("duration", _duration);
+            conf.addIfSet("vertical_scale", _vscale);
+            conf.addIfSet("blend_imagery", _blendImagery);
+            conf.addIfSet("blend_elevation", _blendElevation);
+            return conf;
+        }
+
+    protected:
+        void mergeConfig( const Config& conf ) {
+            ConfigOptions::mergeConfig( conf );
+            fromConfig( conf );
+        }
+
+    private:
+        void fromConfig( const Config& conf ) {
+            conf.getIfSet("delay", _delay);
+            conf.getIfSet("duration", _duration);
+            conf.getIfSet("vertical_scale", _vscale);
+            conf.getIfSet("blend_imagery", _blendImagery);
+            conf.getIfSet("blend_elevation", _blendElevation);
+        }
+
+    private:
+        optional<float> _delay;
+        optional<float> _duration;
+        optional<float> _vscale;
+        optional<bool>  _blendImagery;
+        optional<bool>  _blendElevation;
+
+    };
+
     /**
      * Terrain effect that blends terrain levels of detail for a 
      * smooth transition effect. Operates on elevation data and
@@ -40,53 +112,25 @@ namespace osgEarth { namespace Util
      * (b) a transparent globe color. It will not work properly with
      * untextures (but colored) terrain tiles.
      */
-    class OSGEARTHUTIL_EXPORT LODBlending : public TerrainEffect
+    class OSGEARTHUTIL_EXPORT LODBlending : public TerrainEffect,
+                                            public LODBlendingOptions
     {
     public:
         /** construct a new blending effect */
         LODBlending();
 
-        /** Sets the delay (in seconds) between the time the tile appears
-            and when it starts its transition */
-        void setDelay( float value );
-        float getDelay() const { return _delay.get(); }
-
-        /** Sets the duration of the transition */
-        void setDuration( float value );
-        float getDuration() const { return _duration.get(); }
-
-        /** Vertical scale factor to apply to elevation */
-        void setVerticalScale( float value );
-        float getVerticalScale() const { return _vscale.get(); }
-
-        /** Whether to blend imagery (default=true) */
-        void setBlendImagery( bool value );
-        bool getBlendImagery() const { return _blendImagery.get(); }
-
-        /** Whether to blend elevation (default=true) */
-        void setBlendElevation( bool value );
-        bool getBlendElevation() const { return _blendElevation.get(); }
+        LODBlending(const LODBlendingOptions& options);
 
     public: // TerrainEffect interface
 
         void onInstall(TerrainEngineNode* engine);
         void onUninstall(TerrainEngineNode* engine);
 
-    public: // serialization
-
-        LODBlending(const Config& conf);
-        void mergeConfig(const Config& conf);
-        virtual Config getConfig() const;
 
     protected:
         virtual ~LODBlending() { }
         void init();
 
-        optional<float>              _delay;
-        optional<float>              _duration;
-        optional<float>              _vscale;
-        optional<bool>               _blendImagery;
-        optional<bool>               _blendElevation;
         osg::ref_ptr<osg::Uniform>   _delayUniform;
         osg::ref_ptr<osg::Uniform>   _durationUniform;
         osg::ref_ptr<osg::Uniform>   _vscaleUniform;
diff --git a/src/osgEarthUtil/LODBlending.cpp b/src/osgEarthUtil/LODBlending.cpp
index 0da442f..b14d715 100644
--- a/src/osgEarthUtil/LODBlending.cpp
+++ b/src/osgEarthUtil/LODBlending.cpp
@@ -24,6 +24,8 @@
 #include <osgEarth/Capabilities>
 #include <osgEarth/VirtualProgram>
 #include <osgEarth/TerrainEngineNode>
+#include <osgEarth/Extension>
+#include <osgEarth/MapNode>
 
 #define LC "[LODBlending] "
 
@@ -86,7 +88,7 @@ namespace
 
         "attribute vec4 oe_terrain_attr; \n"
         "attribute vec4 oe_terrain_attr2; \n"
-        "varying vec3 oe_Normal; \n"
+        "varying vec3 vp_Normal; \n"
 
         "uniform float oe_min_tile_range_factor; \n"
         "uniform vec4 oe_tile_key; \n"
@@ -123,7 +125,7 @@ namespace
 
         "attribute vec4 oe_terrain_attr; \n"
         "attribute vec4 oe_terrain_attr2; \n"
-        "varying vec3 oe_Normal; \n"
+        "varying vec3 vp_Normal; \n"
 
         "uniform float oe_min_tile_range_factor; \n"
         "uniform vec4 oe_tile_key; \n"
@@ -161,7 +163,7 @@ namespace
         "    oe_lodblend_texc = oe_layer_parent_texmat * oe_layer_texc; \n"
         "    oe_lodblend_r    = oe_layer_parent_texmat[0][0] > 0.0 ? r : 0.0; \n" // obe?
 
-        "    oe_Normal = normalize(mix(normalize(oe_Normal), oe_terrain_attr2.xyz, r)); \n"
+        "    vp_Normal = normalize(mix(normalize(vp_Normal), oe_terrain_attr2.xyz, r)); \n"
         "} \n";
 
     const char* fs_imagery =
@@ -188,94 +190,26 @@ namespace
 }
 
 
-LODBlending::LODBlending() :
-TerrainEffect(),
-_delay         ( 0.0f ),
-_duration      ( 0.25f ),
-_vscale        ( 1.0f ),
-_blendImagery  ( true ),
-_blendElevation( true )
+LODBlending::LODBlending(const LODBlendingOptions& options) :
+LODBlendingOptions(options)
 {
     init();
 }
 
 
-LODBlending::LODBlending(const Config& conf) :
-TerrainEffect(),
-_delay         ( 0.0f ),
-_duration      ( 0.25f ),
-_vscale        ( 1.0f ),
-_blendImagery  ( true ),
-_blendElevation( true )
-{
-    mergeConfig(conf);
-    init();
-}
-
-
 void
 LODBlending::init()
 {
     _delayUniform = new osg::Uniform(osg::Uniform::FLOAT, "oe_lodblend_delay");
-    _delayUniform->set( (float)*_delay );
+    _delayUniform->set( osg::clampAbove(delay().get(), 0.0f));
 
     _durationUniform = new osg::Uniform(osg::Uniform::FLOAT, "oe_lodblend_duration");
-    _durationUniform->set( (float)*_duration );
+    _durationUniform->set( osg::clampAbove(duration().get(), 0.0f) );
 
     _vscaleUniform = new osg::Uniform(osg::Uniform::FLOAT, "oe_lodblend_vscale");
-    _vscaleUniform->set( (float)*_vscale );
-}
-
-
-void
-LODBlending::setDelay(float delay)
-{
-    if ( delay != _delay.get() )
-    {
-        _delay = osg::clampAbove( delay, 0.0f );
-        _delayUniform->set( _delay.get() );
-    }
-}
-
-
-void
-LODBlending::setDuration(float duration)
-{
-    if ( duration != _duration.get() )
-    {
-        _duration = osg::clampAbove( duration, 0.0f );
-        _durationUniform->set( _duration.get() );
-    }
-}
-
-
-void
-LODBlending::setVerticalScale(float vscale)
-{
-    if ( vscale != _vscale.get() )
-    {
-        _vscale = osg::clampAbove( vscale, 0.0f );
-        _vscaleUniform->set( _vscale.get() );
-    }
-}
-
-void
-LODBlending::setBlendImagery(bool value)
-{
-   if ( value != _blendImagery.get() )
-   {
-      _blendImagery = value;
-   }
+    _vscaleUniform->set(osg::clampAbove(verticalScale().get(), 0.0f));
 }
 
-void
-LODBlending::setBlendElevation(bool value)
-{
-   if ( value != _blendElevation.get() )
-   {
-      _blendElevation = value;
-   }
-}
 
 void
 LODBlending::onInstall(TerrainEngineNode* engine)
@@ -294,12 +228,12 @@ LODBlending::onInstall(TerrainEngineNode* engine)
         VirtualProgram* vp = VirtualProgram::getOrCreate(stateset);
         vp->setName( "osgEarth::Util::LODBlending" );
 
-        if ( _blendElevation == true )
+        if ( blendElevation() == true )
         {
             vp->setFunction("oe_lodblend_elevation_vertex", vs_elevation, ShaderComp::LOCATION_VERTEX_MODEL );
         }
 
-        if ( _blendImagery == true )
+        if ( blendImagery() == true )
         {
             vp->setFunction("oe_lodblend_imagery_vertex", vs_imagery, ShaderComp::LOCATION_VERTEX_VIEW);
             vp->setFunction("oe_lodblend_imagery_fragment", fs_imagery, ShaderComp::LOCATION_FRAGMENT_COLORING);
@@ -334,27 +268,63 @@ LODBlending::onUninstall(TerrainEngineNode* engine)
 }
 
 
-//-------------------------------------------------------------
+//--------------------------------------------------------------
 
 
-void
-LODBlending::mergeConfig(const Config& conf)
-{
-    conf.getIfSet( "delay",    _delay );
-    conf.getIfSet( "duration", _duration );
-    conf.getIfSet( "vertical_scale", _vscale );
-    conf.getIfSet( "blend_imagery",  _blendImagery );
-    conf.getIfSet( "blend_elevation", _blendElevation );
-}
+#undef  LC
+#define LC "[LODBlendingExtension] "
 
-Config
-LODBlending::getConfig() const
+/**
+    * Extension for loading the graticule node on demand.
+    */
+class LODBlendingExtension : public Extension,
+                             public ExtensionInterface<MapNode>,
+                             public LODBlendingOptions
 {
-    Config conf("lod_blending");
-    conf.addIfSet( "delay",    _delay );
-    conf.addIfSet( "duration", _duration );
-    conf.addIfSet( "vertical_scale", _vscale );
-    conf.addIfSet( "blend_imagery",  _blendImagery );
-    conf.addIfSet( "blend_elevation", _blendElevation );
-    return conf;
-}
+public:
+    META_Object(osgearth_ext_lodblending, LODBlendingExtension);
+
+    // CTORs
+    LODBlendingExtension() { }
+    LODBlendingExtension(const ConfigOptions& options) : LODBlendingOptions(options) { }
+
+    // DTOR
+    virtual ~LODBlendingExtension() { }
+
+
+public: // Extension
+
+    virtual const ConfigOptions& getConfigOptions() const { return *this; }
+
+
+public: // ExtensionInterface<MapNode>
+
+    bool connect(MapNode* mapNode)
+    {
+        if (!_effect.valid())
+        {
+            _effect = new LODBlending(*this);
+            mapNode->getTerrainEngine()->addEffect(_effect.get());
+        }
+        return true;
+    }
+
+    bool disconnect(MapNode* mapNode)
+    {
+        if (mapNode && _effect.valid())
+        {
+            mapNode->getTerrainEngine()->removeEffect(_effect.get());
+            _effect = 0L;
+        }
+        return true;
+    }
+
+
+protected: // Object
+    LODBlendingExtension(const LODBlendingExtension& rhs, const osg::CopyOp& op) { }
+
+private:
+    osg::ref_ptr<LODBlending> _effect;
+};
+
+REGISTER_OSGEARTH_EXTENSION( osgearth_lod_blending, LODBlendingExtension );
diff --git a/src/osgEarthUtil/LatLongFormatter b/src/osgEarthUtil/LatLongFormatter
index 05cd06d..1c0781e 100644
--- a/src/osgEarthUtil/LatLongFormatter
+++ b/src/osgEarthUtil/LatLongFormatter
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthUtil/LatLongFormatter.cpp b/src/osgEarthUtil/LatLongFormatter.cpp
index 54ee64b..e81f652 100644
--- a/src/osgEarthUtil/LatLongFormatter.cpp
+++ b/src/osgEarthUtil/LatLongFormatter.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthUtil/LineOfSight b/src/osgEarthUtil/LineOfSight
index 3148861..fc66a55 100644
--- a/src/osgEarthUtil/LineOfSight
+++ b/src/osgEarthUtil/LineOfSight
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthUtil/LinearLineOfSight b/src/osgEarthUtil/LinearLineOfSight
index 76e85ec..0befab0 100644
--- a/src/osgEarthUtil/LinearLineOfSight
+++ b/src/osgEarthUtil/LinearLineOfSight
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthUtil/LinearLineOfSight.cpp b/src/osgEarthUtil/LinearLineOfSight.cpp
index a66ff1b..dc65500 100644
--- a/src/osgEarthUtil/LinearLineOfSight.cpp
+++ b/src/osgEarthUtil/LinearLineOfSight.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthUtil/LogDepthBuffer.VertOnly.vert.glsl b/src/osgEarthUtil/LogDepthBuffer.VertOnly.vert.glsl
index bb92779..cc6089f 100644
--- a/src/osgEarthUtil/LogDepthBuffer.VertOnly.vert.glsl
+++ b/src/osgEarthUtil/LogDepthBuffer.VertOnly.vert.glsl
@@ -1,8 +1,8 @@
 #version 110
 
-#pragma vp_entryPoint "oe_logDepth_vert"
-#pragma vp_location   "vertex_clip"
-#pragma vp_order      "0.99"
+#pragma vp_entryPoint oe_logDepth_vert
+#pragma vp_location   vertex_clip
+#pragma vp_order      0.99
 
 uniform float oe_logDepth_FC;
 
diff --git a/src/osgEarthUtil/LogDepthBuffer.frag.glsl b/src/osgEarthUtil/LogDepthBuffer.frag.glsl
index 8e7600d..a72414f 100644
--- a/src/osgEarthUtil/LogDepthBuffer.frag.glsl
+++ b/src/osgEarthUtil/LogDepthBuffer.frag.glsl
@@ -1,8 +1,8 @@
 #version 110
 
-#pragma vp_entryPoint "oe_logDepth_frag"
-#pragma vp_location   "fragment_lighting"
-#pragma vp_order      "0.99"
+#pragma vp_entryPoint oe_logDepth_frag
+#pragma vp_location   fragment_lighting
+#pragma vp_order      0.99
 
 uniform float oe_logDepth_FC;
 varying float oe_logDepth_clipz;
diff --git a/src/osgEarthUtil/LogDepthBuffer.vert.glsl b/src/osgEarthUtil/LogDepthBuffer.vert.glsl
index 3b1dc7b..b219109 100644
--- a/src/osgEarthUtil/LogDepthBuffer.vert.glsl
+++ b/src/osgEarthUtil/LogDepthBuffer.vert.glsl
@@ -1,8 +1,8 @@
 #version 110
 
-#pragma vp_entryPoint "oe_logDepth_vert"
-#pragma vp_location   "vertex_clip"
-#pragma vp_order      "0.99"
+#pragma vp_entryPoint oe_logDepth_vert
+#pragma vp_location   vertex_clip
+#pragma vp_order      0.99
 
 uniform float oe_logDepth_FC;
 varying float oe_logDepth_clipz;
diff --git a/src/osgEarthUtil/LogarithmicDepthBuffer b/src/osgEarthUtil/LogarithmicDepthBuffer
index 82eab7f..f20c697 100644
--- a/src/osgEarthUtil/LogarithmicDepthBuffer
+++ b/src/osgEarthUtil/LogarithmicDepthBuffer
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthUtil/LogarithmicDepthBuffer.cpp b/src/osgEarthUtil/LogarithmicDepthBuffer.cpp
index 64ae0d4..f8eb7c0 100644
--- a/src/osgEarthUtil/LogarithmicDepthBuffer.cpp
+++ b/src/osgEarthUtil/LogarithmicDepthBuffer.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthUtil/MGRSFormatter b/src/osgEarthUtil/MGRSFormatter
index 83a1d51..e8ad847 100644
--- a/src/osgEarthUtil/MGRSFormatter
+++ b/src/osgEarthUtil/MGRSFormatter
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthUtil/MGRSFormatter.cpp b/src/osgEarthUtil/MGRSFormatter.cpp
index 759ee8d..7e0cc35 100644
--- a/src/osgEarthUtil/MGRSFormatter.cpp
+++ b/src/osgEarthUtil/MGRSFormatter.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthUtil/MGRSGraticule b/src/osgEarthUtil/MGRSGraticule
index cb41b09..b3fc60c 100644
--- a/src/osgEarthUtil/MGRSGraticule
+++ b/src/osgEarthUtil/MGRSGraticule
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthUtil/MGRSGraticule.cpp b/src/osgEarthUtil/MGRSGraticule.cpp
index 966f010..af1b098 100644
--- a/src/osgEarthUtil/MGRSGraticule.cpp
+++ b/src/osgEarthUtil/MGRSGraticule.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -562,18 +562,22 @@ namespace osgEarth { namespace Util
     class MGRSGraticuleFactory : public osgDB::ReaderWriter
     {
     public:
-        virtual const char* className()
+        MGRSGraticuleFactory()
         {
             supportsExtension( MGRS_GRATICULE_EXTENSION, "osgEarth MGRS graticule" );
+        }
+
+        const char* className() const
+        {
             return "osgEarth MGRS graticule LOD loader";
         }
 
-        virtual bool acceptsExtension(const std::string& extension) const
+        bool acceptsExtension(const std::string& extension) const
         {
             return osgDB::equalCaseInsensitive(extension, MGRS_GRATICULE_EXTENSION);
         }
 
-        virtual ReadResult readNode(const std::string& uri, const Options* options) const
+        ReadResult readNode(const std::string& uri, const Options* options) const
         {        
             std::string ext = osgDB::getFileExtension( uri );
             if ( !acceptsExtension( ext ) )
diff --git a/src/osgEarthUtil/MeasureTool b/src/osgEarthUtil/MeasureTool
index 7cb7525..5a2dfc2 100644
--- a/src/osgEarthUtil/MeasureTool
+++ b/src/osgEarthUtil/MeasureTool
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthUtil/MeasureTool.cpp b/src/osgEarthUtil/MeasureTool.cpp
index 2326f40..63b1760 100644
--- a/src/osgEarthUtil/MeasureTool.cpp
+++ b/src/osgEarthUtil/MeasureTool.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -93,13 +93,12 @@ MeasureToolHandler::rebuild()
     // clamp to the terrain skin as it pages in
     AltitudeSymbol* alt = _feature->style()->getOrCreate<AltitudeSymbol>();
     alt->clamping() = alt->CLAMP_TO_TERRAIN;
-    //alt->technique() = alt->TECHNIQUE_GPU;
     alt->technique() = alt->TECHNIQUE_SCENE;
 
     // offset to mitigate Z fighting
     RenderSymbol* render = _feature->style()->getOrCreate<RenderSymbol>();
     render->depthOffset()->enabled() = true;
-    render->depthOffset()->minBias() = 1000;
+    render->depthOffset()->automatic() = true;
 
     // define a style for the line
     LineSymbol* ls = _feature->style()->getOrCreate<LineSymbol>();
@@ -110,14 +109,14 @@ MeasureToolHandler::rebuild()
 
     _featureNode = new FeatureNode( getMapNode(), _feature.get() );
     _featureNode->getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
-    _featureNode->setClusterCulling(false);
+    //_featureNode->setClusterCulling(false);
 
     _group->addChild (_featureNode.get() );
 
 #ifdef SHOW_EXTENT
 
     // Define the extent feature:
-    _extentFeature = new Feature( new Polygon(), mapNode->getMapSRS() );
+    _extentFeature = new Feature( new Polygon(), getMapNode()->getMapSRS() );
     _extentFeature->geoInterp() = GEOINTERP_RHUMB_LINE;
     _extentFeature->style()->add( alt );
     LineSymbol* extentLine = _extentFeature->style()->getOrCreate<LineSymbol>();
@@ -125,7 +124,7 @@ MeasureToolHandler::rebuild()
     extentLine->stroke()->width() = 2.0f;
     extentLine->tessellation() = 20;
 
-    _extentFeatureNode = new FeatureNode( _mapNode.get(), _extentFeature.get() );
+    _extentFeatureNode = new FeatureNode( getMapNode(), _extentFeature.get() );
     
     _group->addChild( _extentFeatureNode.get() );
 #endif
@@ -194,7 +193,7 @@ bool MeasureToolHandler::handle( const osgGA::GUIEventAdapter& ea, osgGA::GUIAct
     {        
         float eps = 1.0f;
         _mouseDown = false;
-        if (osg::equivalent(ea.getX(), _mouseDownX) && osg::equivalent(ea.getY(), _mouseDownY))
+        if (osg::equivalent(ea.getX(), _mouseDownX, eps) && osg::equivalent(ea.getY(), _mouseDownY, eps))
         {
             double lon, lat;
             if (getLocationAt(view, ea.getX(), ea.getY(), lon, lat))
@@ -226,8 +225,8 @@ bool MeasureToolHandler::handle( const osgGA::GUIEventAdapter& ea, osgGA::GUIAct
                     }
 
 #ifdef SHOW_EXTENT
-                    const GeoExtent& ex = _feature->getExtent();
-                    OE_INFO << "extent = " << ex.toString() << std::endl;
+                    const GeoExtent ex( _feature->getSRS(), _feature->getGeometry()->getBounds() );
+                    //OE_INFO << "extent = " << ex.toString() << std::endl;
                     Geometry* eg = _extentFeature->getGeometry();
                     osg::Vec3d fc = ex.getCentroid();
                     eg->clear();
diff --git a/src/osgEarthUtil/MouseCoordsTool b/src/osgEarthUtil/MouseCoordsTool
index eed96d2..92fd1be 100644
--- a/src/osgEarthUtil/MouseCoordsTool
+++ b/src/osgEarthUtil/MouseCoordsTool
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthUtil/MouseCoordsTool.cpp b/src/osgEarthUtil/MouseCoordsTool.cpp
index ed97421..b39c652 100644
--- a/src/osgEarthUtil/MouseCoordsTool.cpp
+++ b/src/osgEarthUtil/MouseCoordsTool.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -23,6 +23,7 @@
 #include <osgEarth/Terrain>
 #include <osgEarth/TerrainEngineNode>
 #include <osgViewer/View>
+#include <osgEarth/DPLineSegmentIntersector>
 
 using namespace osgEarth;
 using namespace osgEarth::Util;
@@ -65,6 +66,22 @@ MouseCoordsTool::handle( const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapt
             for( Callbacks::iterator i = _callbacks.begin(); i != _callbacks.end(); ++i )
                 i->get()->reset( aa.asView(), _mapNode );
         }
+
+#if 0 // testing AGL
+        osg::Vec3d eye, center, up;
+        aa.asView()->getCamera()->getViewMatrixAsLookAt(eye, center, up);
+        DPLineSegmentIntersector* lsi = new DPLineSegmentIntersector(eye, osg::Vec3d(0,0,0));
+        osgUtil::IntersectionVisitor iv(lsi);
+        lsi->setIntersectionLimit(lsi->LIMIT_NEAREST);
+        iv.setUserData( new Map() );
+        _mapNode->accept(iv);
+
+        if ( !lsi->getIntersections().empty() )
+        {            
+            double agl = (eye - lsi->getFirstIntersection().getWorldIntersectPoint()).length();
+            OE_NOTICE << "AGL = " << agl << "m" << std::endl;
+        }
+#endif
     }
 
     return false;
diff --git a/src/osgEarthUtil/NightColorFilter b/src/osgEarthUtil/NightColorFilter
index b5c9e38..e20958e 100644
--- a/src/osgEarthUtil/NightColorFilter
+++ b/src/osgEarthUtil/NightColorFilter
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthUtil/NightColorFilter.cpp b/src/osgEarthUtil/NightColorFilter.cpp
index bcce898..00706f4 100644
--- a/src/osgEarthUtil/NightColorFilter.cpp
+++ b/src/osgEarthUtil/NightColorFilter.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthUtil/ObjectLocator b/src/osgEarthUtil/ObjectLocator
index 94c36cd..71f01fb 100644
--- a/src/osgEarthUtil/ObjectLocator
+++ b/src/osgEarthUtil/ObjectLocator
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthUtil/Ocean b/src/osgEarthUtil/Ocean
index 46f43e2..03f8de0 100644
--- a/src/osgEarthUtil/Ocean
+++ b/src/osgEarthUtil/Ocean
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
@@ -26,6 +26,7 @@
 #include <osgEarth/DateTime>
 #include <osgEarth/Config>
 #include <osgEarth/SpatialReference>
+#include <osgEarth/Profile>
 #include <osg/Group>
 #include <osg/View>
 #include <osgDB/ReaderWriter>
@@ -95,6 +96,12 @@ namespace osgEarth { namespace Util
         void setSeaLevel(float offsetMeters);
         float getSeaLevel() const { return _seaLevel; }
 
+        /** Sets the alpha of the ocean */
+        void setAlpha(float alpha);
+        float getAlpha() const { return _alpha; }
+
+
+
     public: // osg::Group
 
         virtual void traverse(osg::NodeVisitor&);
@@ -103,9 +110,13 @@ namespace osgEarth { namespace Util
 
         virtual void onSetSeaLevel() { }
 
+        virtual void onSetAlpha() { }
+
     private:
 
         float _seaLevel;
+        float _alpha;
+
         osg::ref_ptr<const SpatialReference> _srs;
         const OceanOptions _options;
     };
@@ -121,6 +132,18 @@ namespace osgEarth { namespace Util
         const OceanOptions& getOceanOptions(const osgDB::Options* opt) const;
     };
 
+    /**
+     * Factory interface that ocean extensions need to implement. Someday we will
+     * convert the ocean extensions into proper NodeKits, at which point this method
+     * will probably be no longer necessary since you can just link with the library
+     * and create the OceanNode normally.
+     */
+    class /*header-only*/ OceanNodeFactory
+    {
+    public:
+        virtual OceanNode* createOceanNode(MapNode* mapNode) =0;
+    };
+
 } } // namespace osgEarth::Util
 
 #endif //OSGEARTHUTIL_OCEAN
diff --git a/src/osgEarthUtil/Ocean.cpp b/src/osgEarthUtil/Ocean.cpp
index 6ad8be9..36955ab 100644
--- a/src/osgEarthUtil/Ocean.cpp
+++ b/src/osgEarthUtil/Ocean.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
@@ -68,7 +68,8 @@ OceanOptions::getConfig() const
 
 OceanNode::OceanNode(const OceanOptions& options) :
 _options ( options ),
-_seaLevel( 0.0f )
+_seaLevel( 0.0f ),
+_alpha( 1.0f )
 {
     //NOP
 }
@@ -86,6 +87,13 @@ OceanNode::setSeaLevel(float value)
 }
 
 void
+OceanNode::setAlpha(float value)
+{
+    _alpha = value;
+    onSetAlpha();
+}
+
+void
 OceanNode::traverse(osg::NodeVisitor& nv)
 {
     if ( nv.getVisitorType() == nv.CULL_VISITOR && _srs.valid() )
@@ -142,36 +150,34 @@ OceanNode::traverse(osg::NodeVisitor& nv)
 #define OPTIONS_TAG "__osgEarth::Util::OceanOptions"
 
 OceanNode*
-OceanNode::create(const OceanOptions& options,
-                  MapNode*            mapNode)
+OceanNode::create(const OceanOptions& options, MapNode* mapNode)
 {
-    OceanNode* result = 0L;
-
-    std::string driver = options.getDriver();
-    if ( driver.empty() )
-    {
-        OE_INFO << LC << "No driver in options; defaulting to \"simple\"." << std::endl;
-        //OE_INFO << LC << options.getConfig().toJSON(true) << std::endl;
-        driver = "simple";
+    if ( !mapNode ) {
+        OE_WARN << LC << "Internal error; null map node passed to OceanNode::Create\n";
+        return 0L;
     }
 
-    std::string driverExt = std::string(".osgearth_ocean_") + driver;
+    std::string driverName = options.getDriver();
+    if ( driverName.empty() )
+        driverName = "simple";
 
-    osg::ref_ptr<osgDB::Options> rwopts = Registry::instance()->cloneOrCreateOptions();
-    rwopts->setPluginData( MAPNODE_TAG, (void*)mapNode );
-    rwopts->setPluginData( OPTIONS_TAG, (void*)&options );
+    std::string extensionName = std::string("ocean_") + driverName;
 
-    result = dynamic_cast<OceanNode*>( osgDB::readNodeFile( driverExt, rwopts.get() ) );
-    if ( result )
-    {
-        OE_INFO << LC << "Loaded ocean driver \"" << driver << "\" OK." << std::endl;
+    osg::ref_ptr<Extension> extension = Extension::create( extensionName, options );
+    if ( !extension.valid() ) {
+        OE_WARN << LC << "Failed to load extension for sky driver \"" << driverName << "\"\n";
+        return 0L;
     }
-    else
-    {
-        OE_WARN << LC << "FAIL, unable to load ocean driver \"" << driver << "\"" << std::endl;
+
+    OceanNodeFactory* factory = extension->as<OceanNodeFactory>();
+    if ( !factory ) {
+        OE_WARN << LC << "Internal error; extension \"" << extensionName << "\" does not implement OceanNodeFactory\n";
+        return 0L;
     }
 
-    return result;
+    osg::ref_ptr<OceanNode> result = factory->createOceanNode(mapNode);
+
+    return result.release();
 }
 
 OceanNode*
@@ -186,7 +192,9 @@ OceanNode::create(MapNode* mapNode)
 const OceanOptions&
 OceanDriver::getOceanOptions(const osgDB::Options* options) const
 {
-    return *static_cast<const OceanOptions*>( options->getPluginData(OPTIONS_TAG) );
+    static OceanOptions s_default;
+    const void* data = options->getPluginData(OPTIONS_TAG);
+    return data ? *static_cast<const OceanOptions*>(data) : s_default;
 }
 
 
diff --git a/src/osgEarthUtil/PolyhedralLineOfSight b/src/osgEarthUtil/PolyhedralLineOfSight
index c1729a7..bf0087e 100644
--- a/src/osgEarthUtil/PolyhedralLineOfSight
+++ b/src/osgEarthUtil/PolyhedralLineOfSight
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
@@ -26,7 +26,7 @@
 #include <osgEarth/MapNode>
 #include <osgEarth/GeoData>
 #include <osgEarth/Units>
-#include <osgEarthAnnotation/LocalizedNode>
+#include <osgEarthAnnotation/GeoPositionNode>
 #include <osgEarth/Terrain>
 #include <osg/Geode>
 
@@ -38,7 +38,7 @@ namespace osgEarth { namespace Util
     /**
      * A Node that display a line of sight polytope.
      */
-    class OSGEARTHUTIL_EXPORT PolyhedralLineOfSightNode : public LocalizedNode
+    class OSGEARTHUTIL_EXPORT PolyhedralLineOfSightNode : public GeoPositionNode
     {
     public:
         /**
@@ -79,10 +79,9 @@ namespace osgEarth { namespace Util
         void addChangedCallback( LOSChangedCallback* callback );
         void removeChangedCallback( LOSChangedCallback* callback );
 
-    public: // LocalizedNode
+    public: // GeoPositionNode
         
-        virtual bool setPosition( const GeoPoint& pos );
-        virtual osg::MatrixTransform* getTransform() { return _xform.get(); }
+        virtual void setPosition( const GeoPoint& pos );
 
     public: // MapNodeObserver
 
diff --git a/src/osgEarthUtil/PolyhedralLineOfSight.cpp b/src/osgEarthUtil/PolyhedralLineOfSight.cpp
index 11b35f2..6976c4b 100644
--- a/src/osgEarthUtil/PolyhedralLineOfSight.cpp
+++ b/src/osgEarthUtil/PolyhedralLineOfSight.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
@@ -48,7 +48,7 @@ namespace
 //------------------------------------------------------------------------
 
 PolyhedralLineOfSightNode::PolyhedralLineOfSightNode( MapNode* mapNode ) :
-LocalizedNode( mapNode ),
+GeoPositionNode( mapNode ),
 _startAzim   ( Angle(-45.0, Units::DEGREES) ),
 _endAzim     ( Angle( 45.0, Units::DEGREES) ),
 _startElev   ( Angle(  0.0, Units::DEGREES) ),
@@ -103,7 +103,7 @@ PolyhedralLineOfSightNode::setMapNode( MapNode* mapNode )
         }
     }
 
-    LocalizedNode::setMapNode( mapNode );
+    GeoPositionNode::setMapNode( mapNode );
 }
 
 void
@@ -164,13 +164,12 @@ PolyhedralLineOfSightNode::traverse(osg::NodeVisitor& nv)
 }
 
 
-bool
-PolyhedralLineOfSightNode::setPosition( const GeoPoint& pos )
+void
+PolyhedralLineOfSightNode::setPosition(const GeoPoint& pos)
 {
-    bool ok = LocalizedNode::setPosition( pos );
+    GeoPositionNode::setPosition( pos );
     recalculateExtent();
     updateSamples();
-    return ok;
 }
 
 
@@ -185,7 +184,7 @@ void
 PolyhedralLineOfSightNode::recalculateExtent()
 {
     // get a local2world matrix for the map position:
-    GeoPoint absMapPos = _mapPosition;
+    GeoPoint absMapPos = getPosition();
     absMapPos.makeAbsolute( getMapNode()->getTerrain() );
     osg::Matrix local2world;
     absMapPos.createLocalToWorld( local2world );
@@ -339,6 +338,8 @@ PolyhedralLineOfSightNode::updateSamples()
 
     osg::Geometry* geom  = _geode->getDrawable(0)->asGeometry();
     osg::Vec3Array* verts = dynamic_cast<osg::Vec3Array*>( geom->getVertexArray() );
+    if (!verts)
+        return;
 
     double distance = _distance.as(Units::METERS);
 
diff --git a/src/osgEarthUtil/RGBColorFilter b/src/osgEarthUtil/RGBColorFilter
index 6671916..dc6b5aa 100644
--- a/src/osgEarthUtil/RGBColorFilter
+++ b/src/osgEarthUtil/RGBColorFilter
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthUtil/RGBColorFilter.cpp b/src/osgEarthUtil/RGBColorFilter.cpp
index c239406..e25054a 100644
--- a/src/osgEarthUtil/RGBColorFilter.cpp
+++ b/src/osgEarthUtil/RGBColorFilter.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthUtil/RTTPicker b/src/osgEarthUtil/RTTPicker
index e7382fa..8801ac1 100644
--- a/src/osgEarthUtil/RTTPicker
+++ b/src/osgEarthUtil/RTTPicker
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthUtil/RTTPicker.cpp b/src/osgEarthUtil/RTTPicker.cpp
index 8693def..fe0b644 100644
--- a/src/osgEarthUtil/RTTPicker.cpp
+++ b/src/osgEarthUtil/RTTPicker.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -36,15 +36,15 @@ namespace
     // SHADERS for the RTT pick camera.
 
     const char* pickVertexEncode =
-        "#version 130\n"
+        "#version " GLSL_VERSION_STR "\n"
 
-        "#pragma vp_entryPoint \"oe_pick_encodeObjectID\" \n"
-        "#pragma vp_location   \"vertex_clip\" \n"
+        "#pragma vp_entryPoint oe_pick_encodeObjectID\n"
+        "#pragma vp_location   vertex_clip\n"
         
         "uint oe_index_objectid; \n"                        // Vertex stage global containing the Object ID; set in ObjectIndex shader.
 
         "flat out vec4 oe_pick_encoded_objectid; \n"        // output encoded oid to fragment shader
-        "flat out int  oe_pick_color_contains_objectid; \n" // whether color already contains oid (written by another RTT camera)
+        "flat out int oe_pick_color_contains_objectid; \n"  // whether color already contains oid (written by another RTT camera)
 
         "void oe_pick_encodeObjectID(inout vec4 vertex) \n"
         "{ \n"
@@ -55,19 +55,19 @@ namespace
         "        float b1 = float((oe_index_objectid & 0x00ff0000u) >> 16u); \n"
         "        float b2 = float((oe_index_objectid & 0x0000ff00u) >> 8u ); \n"
         "        float b3 = float((oe_index_objectid & 0x000000ffu)       ); \n"
-        "        oe_pick_encoded_objectid = vec4(b0, b1, b2, b3) * 0.00392156862; \n" // i.e. 1/2558
+        "        oe_pick_encoded_objectid = vec4(b0, b1, b2, b3) / 255.0; \n"
         "    } \n"
         "} \n";
 
     const char* pickFragment =
-        "#version 130\n"
+        "#version " GLSL_VERSION_STR "\n"
 
-        "#pragma vp_entryPoint \"oe_pick_renderEncodedObjectID\" \n"
-        "#pragma vp_location   \"fragment_output\" \n"
-        "#pragma vp_order      \"last\" \n"
+        "#pragma vp_entryPoint oe_pick_renderEncodedObjectID\n"
+        "#pragma vp_location   fragment_output\n"
+        "#pragma vp_order      last\n"
 
         "flat in vec4 oe_pick_encoded_objectid; \n"
-        "flat in int  oe_pick_color_contains_objectid; \n"
+        "flat in int oe_pick_color_contains_objectid; \n"
         
         "out vec4 fragColor; \n"
 
@@ -132,8 +132,9 @@ RTTPicker::getOrCreateTexture(osg::View* view)
         pc._tex = new osg::Texture2D( pc._image.get() );
         pc._tex->setTextureSize(pc._image->s(), pc._image->t());
         pc._tex->setUnRefImageDataAfterApply(false);
-        pc._tex->setFilter(pc._tex->MIN_FILTER, pc._tex->NEAREST);
-        pc._tex->setFilter(pc._tex->MAG_FILTER, pc._tex->NEAREST);
+        pc._tex->setFilter(pc._tex->MIN_FILTER, pc._tex->NEAREST); // no filtering
+        pc._tex->setFilter(pc._tex->MAG_FILTER, pc._tex->NEAREST); // no filtering
+        pc._tex->setMaxAnisotropy(1.0f); // no filtering
     }
     return pc._tex.get();
 }
@@ -160,6 +161,7 @@ RTTPicker::getOrCreatePickContext(osg::View* view)
     
     // make an RTT camera and bind it to our imag:
     c._pickCamera = new osg::Camera();
+    c._pickCamera->setName( "osgEarth::RTTPicker" );
     c._pickCamera->addChild( _group.get() );
     c._pickCamera->setClearColor( osg::Vec4(0,0,0,0) );
     c._pickCamera->setClearMask( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
@@ -168,19 +170,21 @@ RTTPicker::getOrCreatePickContext(osg::View* view)
     c._pickCamera->setRenderOrder( osg::Camera::PRE_RENDER, 1 );
     c._pickCamera->setRenderTargetImplementation( osg::Camera::FRAME_BUFFER_OBJECT );
     c._pickCamera->attach( osg::Camera::COLOR_BUFFER0, c._image.get() );
+    c._pickCamera->setSmallFeatureCullingPixelSize( -1.0f );
     
     osg::StateSet* rttSS = c._pickCamera->getOrCreateStateSet();
 
     // disable all the things that break ObjectID picking:
     osg::StateAttribute::GLModeValue disable = osg::StateAttribute::OFF | osg::StateAttribute::OVERRIDE | osg::StateAttribute::PROTECTED;
 
-    rttSS->setMode(GL_BLEND,     disable );    
+    //rttSS->setMode(GL_BLEND,     disable );    
     rttSS->setMode(GL_LIGHTING,  disable );
     rttSS->setMode(GL_CULL_FACE, disable );
+    rttSS->setMode(GL_ALPHA_TEST, disable );
     
     // Disabling GL_BLEND is not enough, because osg::Text re-enables it
     // without regard for the OVERRIDE.
-    rttSS->setAttributeAndModes(new osg::BlendFunc(GL_ONE, GL_ZERO), osg::StateAttribute::OVERRIDE);
+    rttSS->setAttributeAndModes(new osg::BlendFunc(GL_ONE, GL_ZERO, GL_ONE, GL_ZERO), osg::StateAttribute::OVERRIDE | osg::StateAttribute::PROTECTED);
 
     // install the picking shaders:
     VirtualProgram* vp = createRTTProgram();
@@ -196,6 +200,7 @@ RTTPicker::getOrCreatePickContext(osg::View* view)
     view->getCamera()->addChild( c._pickCamera.get() );
 
     // associate the RTT camara with the view's camera.
+    // (e.g., decluttering uses this to find the "true" viewport)
     c._pickCamera->setUserData( view->getCamera() );
 
     return c;
@@ -217,6 +222,15 @@ RTTPicker::handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa)
         {
             aa.requestRedraw();
         }
+
+        // synchronize the pick camera associated with this view
+        osg::Camera* cam = aa.asView()->getCamera();
+        if (cam)
+        {
+            PickContext& context = getOrCreatePickContext( aa.asView() );
+            context._pickCamera->setViewMatrix( cam->getViewMatrix() );
+            context._pickCamera->setProjectionMatrix( cam->getProjectionMatrix() );
+        }
     }
 
     else if ( _defaultCallback.valid() && _defaultCallback->accept(ea, aa) )
@@ -262,7 +276,7 @@ RTTPicker::pick(osg::View* view, float mouseX, float mouseY, Callback* callback)
 
     // install the RTT pick camera under this view's camera if it's not already:
     PickContext& context = getOrCreatePickContext( view );
-
+    
     // Create a new pick
     Pick pick;
     pick._context  = &context;
@@ -271,11 +285,6 @@ RTTPicker::pick(osg::View* view, float mouseX, float mouseY, Callback* callback)
     pick._callback = callbackToUse;
     pick._frame    = view->getFrameStamp() ? view->getFrameStamp()->getFrameNumber() : 0u;
     
-    // Synchronize the matrices
-    pick._context->_pickCamera->setNodeMask( ~0 );
-    pick._context->_pickCamera->setViewMatrix( cam->getViewMatrix() );
-    pick._context->_pickCamera->setProjectionMatrix( cam->getProjectionMatrix() );
-
     // Queue it up.
     _picks.push( pick );
     
@@ -352,15 +361,13 @@ namespace
 void
 RTTPicker::checkForPickResult(Pick& pick)
 {
-    // turn the camera off:
-    pick._context->_pickCamera->setNodeMask( 0 );
-
     // decode the results
     osg::Image* image = pick._context->_image.get();
     ImageUtils::PixelReader read( image );
 
     // uncomment to see the RTT image.
-    //osgDB::writeImageFile(*image, "out.png");
+    //osg::ref_ptr<osgDB::Options> o = new osgDB::Options();
+    //osgDB::writeImageFile(*image, "out.tif", o.get());
 
     osg::Vec4f value;
     SpiralIterator iter(image->s(), image->t(), std::max(_buffer,1), pick._u, pick._v);
diff --git a/src/osgEarthUtil/RadialLineOfSight b/src/osgEarthUtil/RadialLineOfSight
index 4093ecd..aa5749a 100644
--- a/src/osgEarthUtil/RadialLineOfSight
+++ b/src/osgEarthUtil/RadialLineOfSight
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthUtil/RadialLineOfSight.cpp b/src/osgEarthUtil/RadialLineOfSight.cpp
index 2876f97..11ad5c0 100644
--- a/src/osgEarthUtil/RadialLineOfSight.cpp
+++ b/src/osgEarthUtil/RadialLineOfSight.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
@@ -298,6 +298,9 @@ RadialLineOfSightNode::compute_line(osg::Node* node)
     for (unsigned int i = 0; i < (unsigned int)_numSpokes; i++)
     {
         DPLineSegmentIntersector* los = dynamic_cast<DPLineSegmentIntersector*>(ivGroup->getIntersectors()[i].get());
+        if ( !los )
+            continue;
+
         DPLineSegmentIntersector::Intersections& hits = los->getIntersections();
 
         osg::Vec3d start = los->getStart();
@@ -427,7 +430,8 @@ RadialLineOfSightNode::compute_fill(osg::Node* node)
         osg::Vec3d spoke = quat * (side * _radius);
         osg::Vec3d end = _centerWorld + spoke;        
         osg::ref_ptr<DPLineSegmentIntersector> dplsi = new DPLineSegmentIntersector( _centerWorld, end );
-        ivGroup->addIntersector( dplsi.get() );
+        if (dplsi)
+            ivGroup->addIntersector( dplsi.get() );
     }
 
     osgUtil::IntersectionVisitor iv;
@@ -439,6 +443,9 @@ RadialLineOfSightNode::compute_fill(osg::Node* node)
     {
         //Get the current hit
         DPLineSegmentIntersector* los = dynamic_cast<DPLineSegmentIntersector*>(ivGroup->getIntersectors()[i].get());
+        if ( !los )
+            continue;
+
         DPLineSegmentIntersector::Intersections& hits = los->getIntersections();
 
         osg::Vec3d currEnd = los->getEnd();
@@ -709,7 +716,7 @@ namespace
     {
     public:
         RadialLOSDraggerCallback(RadialLineOfSightNode* los):
-          _los(los)
+            _los(los), _start(true)
           {
           }
 
diff --git a/src/osgEarthUtil/Shaders b/src/osgEarthUtil/Shaders
index 616b49d..d41551d 100644
--- a/src/osgEarthUtil/Shaders
+++ b/src/osgEarthUtil/Shaders
@@ -43,7 +43,10 @@ namespace osgEarth { namespace Util
 
             LogDepthBuffer_VertFile,
             LogDepthBuffer_FragFile,
-            LogDepthBuffer_VertOnly_VertFile;
+            LogDepthBuffer_VertOnly_VertFile,
+
+            Shadowing_Vertex,
+            Shadowing_Fragment;
 	};	
 } } // namespace osgEarth::Util
 
diff --git a/src/osgEarthUtil/Shaders.cpp.in b/src/osgEarthUtil/Shaders.cpp.in
index 9a3275d..9545d3f 100644
--- a/src/osgEarthUtil/Shaders.cpp.in
+++ b/src/osgEarthUtil/Shaders.cpp.in
@@ -7,30 +7,35 @@ using namespace osgEarth::Util;
 Shaders::Shaders()
 {
     ContourMap_Vertex = "ContourMap.vert.glsl";
-    _sources[ContourMap_Vertex] = OE_MULTILINE(@ContourMap.vert.glsl@);
+    _sources[ContourMap_Vertex] = "@ContourMap.vert.glsl@";
 
     ContourMap_Fragment = "ContourMap.frag.glsl";
-    _sources[ContourMap_Fragment] = OE_MULTILINE(@ContourMap.frag.glsl@);
+    _sources[ContourMap_Fragment] = "@ContourMap.frag.glsl@";
 
     Fog_Vertex = "Fog.vert.glsl";
-    _sources[Fog_Vertex] = OE_MULTILINE(@Fog.vert.glsl@);
+    _sources[Fog_Vertex] = "@Fog.vert.glsl@";
 
     Fog_Fragment = "Fog.frag.glsl";
-    _sources[Fog_Fragment] = OE_MULTILINE(@Fog.frag.glsl@);
+    _sources[Fog_Fragment] = "@Fog.frag.glsl@";
 
     LogDepthBuffer_VertFile = "LogDepthBuffer.vert.glsl";
-    _sources[LogDepthBuffer_VertFile] = OE_MULTILINE(@LogDepthBuffer.vert.glsl@);
+    _sources[LogDepthBuffer_VertFile] = "@LogDepthBuffer.vert.glsl@";
 
     LogDepthBuffer_FragFile = "LogDepthBuffer.frag.glsl";
-    _sources[LogDepthBuffer_FragFile] = OE_MULTILINE(@LogDepthBuffer.frag.glsl@);
+    _sources[LogDepthBuffer_FragFile] = "@LogDepthBuffer.frag.glsl@";
 
     LogDepthBuffer_VertOnly_VertFile = "LogDepthBuffer.VertOnly.vert.glsl";
-    _sources[LogDepthBuffer_VertOnly_VertFile] = OE_MULTILINE(@LogDepthBuffer.VertOnly.vert.glsl@);
+    _sources[LogDepthBuffer_VertOnly_VertFile] = "@LogDepthBuffer.VertOnly.vert.glsl@";
 
     Graticule_Fragment = "Graticule.frag.glsl";
-    _sources[Graticule_Fragment] = OE_MULTILINE(@Graticule.frag.glsl@);
+    _sources[Graticule_Fragment] = "@Graticule.frag.glsl@";
 
     Graticule_Vertex = "Graticule.vert.glsl";
-    _sources[Graticule_Vertex] = OE_MULTILINE(@Graticule.vert.glsl@);
+    _sources[Graticule_Vertex] = "@Graticule.vert.glsl@";
 
+    Shadowing_Vertex = "Shadowing.vert.glsl";
+    _sources[Shadowing_Vertex] = "@Shadowing.vert.glsl@";
+
+    Shadowing_Fragment = "Shadowing.frag.glsl";
+    _sources[Shadowing_Fragment] = "@Shadowing.frag.glsl@";
 }
diff --git a/src/osgEarthUtil/Shadowing b/src/osgEarthUtil/Shadowing
index b335bef..f91725e 100644
--- a/src/osgEarthUtil/Shadowing
+++ b/src/osgEarthUtil/Shadowing
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
@@ -29,7 +29,6 @@
 #include <osg/Uniform>
 #include <osg/Light>
 
-
 namespace osgEarth { namespace Util 
 {
     /**
@@ -61,6 +60,13 @@ namespace osgEarth { namespace Util
         osg::Group* getShadowCastingGroup() { return _castingGroup.get(); }
 
         /**
+         * Sets the traversal mask to use when collecting shadow-casting
+         * geometry. Default is 0xFFFFFFFF (everything)
+         */
+        void setTraversalMask(unsigned mask) { _traversalMask = mask; }
+        unsigned getTraversalMask() const { return _traversalMask; }
+
+        /**
          * Slice ranges. Each slice (the space beteen each value in the list)
          * represents a single shadow map in the Cascading Shadow Maps 
          * implementation.
@@ -84,11 +90,10 @@ namespace osgEarth { namespace Util
         void setTextureSize(unsigned size);
 
         /**
-         * The ambient color of the shadow. This is blended with the fragment
-         * color to achieve shadowing. Default is 0x7f7f7fff
+         * The ambient color level of the shadow. 0.0 = black. Default is 0.4
          */
-        void setShadowColor(const osg::Vec4f& value);
-        const osg::Vec4f& getShadowColor() const { return _color; }
+        void setShadowColor(float value);
+        float getShadowColor() const { return _color; }
 
         /**
          * The blurring factor to apply to shadow PCF sampling. Using a blurring
@@ -112,13 +117,14 @@ namespace osgEarth { namespace Util
         osg::ref_ptr<osg::Group>                _castingGroup;
         unsigned                                _size;
         float                                   _blurFactor;
-        osg::Vec4f                              _color;
+        float                                   _color;
         osg::ref_ptr<osg::Light>                _light;
         osg::ref_ptr<osg::Texture2DArray>       _shadowmap;
         osg::ref_ptr<osg::StateSet>             _rttStateSet;
         std::vector<float>                      _ranges;
         std::vector<osg::ref_ptr<osg::Camera> > _rttCameras;
         osg::Matrix                             _prevProjMatrix;
+        unsigned                                _traversalMask;
 
         int                         _texImageUnit;
         osg::ref_ptr<osg::StateSet> _renderStateSet;
diff --git a/src/osgEarthUtil/Shadowing.cpp b/src/osgEarthUtil/Shadowing.cpp
index 8c0bb95..320742c 100644
--- a/src/osgEarthUtil/Shadowing.cpp
+++ b/src/osgEarthUtil/Shadowing.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
@@ -20,12 +20,15 @@
 * along with this program.  If not, see <http://www.gnu.org/licenses/>
 */
 #include <osgEarthUtil/Shadowing>
+#include <osgEarthUtil/Shaders>
 #include <osgEarth/CullingUtils>
 #include <osgEarth/VirtualProgram>
 #include <osgEarth/Registry>
 #include <osgEarth/Capabilities>
+#include <osgEarth/Shadowing>
 #include <osg/Texture2D>
 #include <osg/CullFace>
+#include <osg/ValueObject>
 #include <osgShadow/ConvexPolyhedron>
 
 #define LC "[ShadowCaster] "
@@ -33,21 +36,21 @@
 using namespace osgEarth::Util;
 
 
+
 ShadowCaster::ShadowCaster() :
-_size        ( 2048 ),
-_texImageUnit( 7 ),
-_blurFactor  ( 0.002f ),
-_color       ( osg::Vec4f(.4f, .4f, .4f, 1) )
+_size         ( 2048 ),
+_texImageUnit ( 7 ),
+_blurFactor   ( 0.0f ),
+_color        ( 0.4f ),
+_traversalMask( ~0 )
 {
     _castingGroup = new osg::Group();
 
     _supported = Registry::capabilities().supportsGLSL();
     if ( _supported )
     {
-        // defaults to 4 slices.
+        // default slices:
         _ranges.push_back(0.0f);
-        _ranges.push_back(100.0f);
-        _ranges.push_back(500.0f);
         _ranges.push_back(1750.0f);
         _ranges.push_back(5000.0f);
 
@@ -89,7 +92,7 @@ ShadowCaster::setBlurFactor(float value)
 }
 
 void
-ShadowCaster::setShadowColor(const osg::Vec4f& value)
+ShadowCaster::setShadowColor(float value)
 {
     _color = value;
     if ( _shadowColorUniform.valid() )
@@ -126,6 +129,7 @@ ShadowCaster::reinitialize()
     for(int i=0; i<numSlices; ++i)
     {
         osg::Camera* rtt = new osg::Camera();
+        Shadowing::setIsShadowCamera(rtt);
         rtt->setReferenceFrame( osg::Camera::ABSOLUTE_RF_INHERIT_VIEWPOINT );
         rtt->setClearDepth( 1.0 );
         rtt->setClearMask( GL_DEPTH_BUFFER_BIT );
@@ -146,110 +150,20 @@ ShadowCaster::reinitialize()
         new osg::CullFace(osg::CullFace::FRONT),
         osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE);
 
+    _rttStateSet->addUniform(new osg::Uniform("oe_isShadowCamera", true), osg::StateAttribute::OVERRIDE);
+
+
     _renderStateSet = new osg::StateSet();
     
-    std::string vertex = Stringify() << 
-        "#version " GLSL_VERSION_STR "\n"
-        GLSL_DEFAULT_PRECISION_FLOAT "\n"
-        "uniform mat4 oe_shadow_matrix[" << numSlices << "]; \n"
-        "varying vec4 oe_shadow_coord[" << numSlices << "]; \n"
-        "void oe_shadow_vertex(inout vec4 VertexVIEW) \n"
-        "{ \n"
-        "    for(int i=0; i<" << numSlices << "; ++i) \n"
-        "        oe_shadow_coord[i] = oe_shadow_matrix[i] * VertexVIEW;\n"
-        "} \n";
-
-    std::string fragment = Stringify() << 
-        "#version 120\n" //" GLSL_VERSION_STR "\n"
-        GLSL_DEFAULT_PRECISION_FLOAT "\n"
-        "#extension GL_EXT_texture_array : enable \n"
-
-        "uniform sampler2DArray oe_shadow_map; \n"
-        "uniform vec4 oe_shadow_color; \n"
-        "uniform float oe_shadow_blur; \n"
-        "varying vec3 oe_Normal; \n"
-        "varying vec4 oe_shadow_coord[" << numSlices << "]; \n"
-
-        //TODO-run a generator and rplace
-        "#define OE_SHADOW_NUM_SAMPLES 16\n"
-        "const vec2 oe_shadow_samples[OE_SHADOW_NUM_SAMPLES] = vec2[]( vec2( -0.942016, -0.399062 ), vec2( 0.945586, -0.768907 ), vec2( -0.094184, -0.929389 ), vec2( 0.344959, 0.293878 ), vec2( -0.915886, 0.457714 ), vec2( -0.815442, -0.879125 ), vec2( -0.382775, 0.276768 ), vec2( 0.974844, 0.756484 ), vec2( 0.443233, -0.975116 ), vec2( 0.53743, -0.473734 ), vec2( -0.264969, -0.41893 ), vec2( 0.791975, 0.190909 ), vec2( -0.241888, 0.997065 ), vec2( -0.8141, 0.914376 ), vec2( 0.199841, 0. [...]
-
-        "float oe_shadow_rand(vec2 co){\n"
-        "   return fract(sin(dot(co.xy ,vec2(12.9898,78.233))) * 43758.5453);\n"
-        "}\n"
-        
-        "vec2 oe_shadow_rot(vec2 p, float a) { \n"
-        "    vec2 sincos = vec2(sin(a), cos(a)); \n"
-        "    return vec2(dot(p, vec2(sincos.y, -sincos.x)), dot(p, sincos.xy)); \n"
-        "}\n"
-
-        // slow PCF sampling.
-        "float oe_shadow_multisample(in vec3 c, in float refvalue, in float blur) \n"
-        "{ \n"
-        "    float shadowed = 0.0; \n"
-        "    float a = 6.283185 * oe_shadow_rand(c.xy); \n"
-        "    vec4 b = vec4(oe_shadow_rot(vec2(1,0),a), oe_shadow_rot(vec2(0,1),a)); \n"
-        "    for(int i=0; i<OE_SHADOW_NUM_SAMPLES; ++i) { \n"
-        "        vec2 off = oe_shadow_samples[i];\n"
-        "        off = vec2(dot(off,b.xz), dot(off,b.yw)); \n"
-        "        vec3 pc = vec3(c.xy + off*blur, c.z); \n"
-        "        float depth = texture2DArray(oe_shadow_map, pc).r; \n"
-        "        if ( depth < 1.0 && depth < refvalue ) { \n"
-        "           shadowed += 1.0; \n"
-        "        } \n"
-        "    } \n"
-        "    return 1.0-(shadowed/OE_SHADOW_NUM_SAMPLES); \n"
-        "} \n"
-
-        "void oe_shadow_fragment( inout vec4 color )\n"
-        "{\n"
-        "    float alpha = color.a; \n"
-        "    float factor = 1.0; \n"
-
-        // pre-pixel biasing to reduce moire/acne
-        "    const float b0 = 0.001; \n"
-        "    const float b1 = 0.01; \n"
-        "    vec3 L = normalize(gl_LightSource[0].position.xyz); \n"
-        "    vec3 N = normalize(oe_Normal); \n"
-        "    float costheta = clamp(dot(L,N), 0.0, 1.0); \n"
-        "    float bias = b0*tan(acos(costheta)); \n"
-
-        // loop over the slices:
-        "    for(int i=0; i<" << numSlices << " && factor > 0.0; ++i) \n"
-        "    { \n"
-        "        vec4 c = oe_shadow_coord[i]; \n"
-        "        vec3 coord = vec3(c.x, c.y, float(i)); \n"
-
-        "        if ( oe_shadow_blur > 0.0 ) \n"
-        "        { \n"
-        "            factor = min(factor, oe_shadow_multisample(coord, c.z-bias, oe_shadow_blur)); \n"
-        "        } \n"
-        "        else \n"
-        "        { \n"
-        "            float depth = texture2DArray(oe_shadow_map, coord).r; \n"
-        "            if ( depth < 1.0 && depth < c.z-bias ) \n"
-        "                factor = 0.0; \n"
-        "        } \n"
-        "    } \n"
-
-        "    vec4 colorInFullShadow = color * oe_shadow_color; \n"
-        "    color = mix(colorInFullShadow, color, factor); \n"
-        "    color.a = alpha;\n"
-        "}\n";
 
+    // Establish a Virtual Program on the stateset.
     VirtualProgram* vp = VirtualProgram::getOrCreate(_renderStateSet.get());
 
-    vp->setFunction(
-        "oe_shadow_vertex", 
-        vertex, 
-        ShaderComp::LOCATION_VERTEX_VIEW,
-        0.9f );
-
-    vp->setFunction(
-        "oe_shadow_fragment",
-        fragment,
-        ShaderComp::LOCATION_FRAGMENT_LIGHTING,
-        0.9f );
+    // Load the shadowing shaders.
+    Shaders package;
+    package.replace("$OE_SHADOW_NUM_SLICES", Stringify()<<numSlices);
+    package.load(vp, package.Shadowing_Vertex);
+    package.load(vp, package.Shadowing_Fragment);
 
     // the texture coord generator matrix array (from the caster):
     _shadowMapTexGenUniform = _renderStateSet->getOrCreateUniform(
@@ -258,24 +172,15 @@ ShadowCaster::reinitialize()
         numSlices );
 
     // bind the shadow map texture itself:
-    _renderStateSet->setTextureAttribute(
-        _texImageUnit,
-        _shadowmap.get(),
-        osg::StateAttribute::ON );
-
+    _renderStateSet->setTextureAttribute(_texImageUnit, _shadowmap.get(), osg::StateAttribute::ON );
     _renderStateSet->addUniform( new osg::Uniform("oe_shadow_map", _texImageUnit) );
 
     // blur factor:
-    _shadowBlurUniform = _renderStateSet->getOrCreateUniform(
-        "oe_shadow_blur",
-        osg::Uniform::FLOAT);
-
+    _shadowBlurUniform = _renderStateSet->getOrCreateUniform("oe_shadow_blur", osg::Uniform::FLOAT);
     _shadowBlurUniform->set(_blurFactor);
 
     // shadow color:
-    _shadowColorUniform = _renderStateSet->getOrCreateUniform(
-        "oe_shadow_color",
-        osg::Uniform::FLOAT_VEC4);
+    _shadowColorUniform = _renderStateSet->getOrCreateUniform("oe_shadow_color", osg::Uniform::FLOAT);
 
     _shadowColorUniform->set(_color);
 }
@@ -284,6 +189,7 @@ void
 ShadowCaster::traverse(osg::NodeVisitor& nv)
 {
     if (_supported                             && 
+        _light.valid()                         &&
         nv.getVisitorType() == nv.CULL_VISITOR && 
         _castingGroup->getNumChildren() > 0    && 
         _shadowmap.valid() )
@@ -304,11 +210,16 @@ ShadowCaster::traverse(osg::NodeVisitor& nv)
             osg::Vec3d lightVectorWorld( -lp4.x(), -lp4.y(), -lp4.z() );
             lightVectorWorld.normalize();
             osg::Vec3d lightPosWorld = osg::Vec3d(0,0,0) * inverseMV;
+            //osg::Vec3d lightPosWorld( lp4.x(), lp4.y(), lp4.z() ); // jitter..
 
             // construct the view matrix for the light. The up vector doesn't really
             // matter so we'll just use the camera's.
             osg::Matrix lightViewMat;
-            lightViewMat.makeLookAt(lightPosWorld, lightPosWorld+lightVectorWorld, camUp);
+            osg::Vec3d lightUp(0,0,1);
+            osg::Vec3d side = lightVectorWorld ^ lightUp;
+            lightUp = side ^ lightVectorWorld;
+            lightUp.normalize();
+            lightViewMat.makeLookAt(lightPosWorld, lightPosWorld+lightVectorWorld, lightUp);
             
             //int i = nv.getFrameStamp()->getFrameNumber() % (_ranges.size()-1);
             int i;
@@ -320,7 +231,6 @@ ShadowCaster::traverse(osg::NodeVisitor& nv)
                 // take the camera's projection matrix and clamp it's near and far planes
                 // to our shadow map slice range.
                 osg::Matrix proj = _prevProjMatrix;
-                //cv->clampProjectionMatrix(proj, n, f);
                 double fovy,ar,zn,zf;
                 proj.getPerspective(fovy,ar,zn,zf);
                 proj.makePerspective(fovy,ar,std::max(n,zn),std::min(f,zf));
@@ -344,6 +254,7 @@ ShadowCaster::traverse(osg::NodeVisitor& nv)
                 osg::Matrix lightProjMat;
                 n = -std::max(bbox.zMin(), bbox.zMax());
                 f = -std::min(bbox.zMin(), bbox.zMax());
+                // TODO: consider extending "n" so that objects outside the main view can still cast shadows
                 lightProjMat.makeOrtho(bbox.xMin(), bbox.xMax(), bbox.yMin(), bbox.yMax(), n, f);
 
                 // configure the RTT camera for this slice:
@@ -362,6 +273,10 @@ ShadowCaster::traverse(osg::NodeVisitor& nv)
                 _shadowMapTexGenUniform->setElement(i, inverseMV * VPS);
             }
 
+            // install the shadow-casting traversal mask:
+            unsigned saveMask = cv->getTraversalMask();
+            cv->setTraversalMask( _traversalMask & saveMask );
+
             // render the shadow maps.
             cv->pushStateSet( _rttStateSet.get() );
             for(i=0; i < (int) _rttCameras.size(); ++i)
@@ -369,6 +284,9 @@ ShadowCaster::traverse(osg::NodeVisitor& nv)
                 _rttCameras[i]->accept( nv );
             }
             cv->popStateSet();
+
+            // restore the previous mask
+            cv->setTraversalMask( saveMask );
             
             // render the shadowed subgraph.
             cv->pushStateSet( _renderStateSet.get() );
diff --git a/src/osgEarthUtil/Shadowing.frag.glsl b/src/osgEarthUtil/Shadowing.frag.glsl
new file mode 100644
index 0000000..4fe5770
--- /dev/null
+++ b/src/osgEarthUtil/Shadowing.frag.glsl
@@ -0,0 +1,89 @@
+#version $GLSL_VERSION_STR
+
+#pragma vp_name       Shadowing Fragment Shader
+#pragma vp_entryPoint oe_shadow_fragment
+#pragma vp_location   fragment_lighting
+#pragma vp_order      0.9
+
+uniform sampler2DArray oe_shadow_map;
+uniform float          oe_shadow_color;
+uniform float          oe_shadow_blur;
+
+in vec3 vp_Normal; // stage global
+in vec4 oe_shadow_coord[$OE_SHADOW_NUM_SLICES];
+
+
+#define OE_SHADOW_NUM_SAMPLES 16
+
+const vec2 oe_shadow_samples[OE_SHADOW_NUM_SAMPLES] = vec2[]( vec2( -0.942016, -0.399062 ), vec2( 0.945586, -0.768907 ), vec2( -0.094184, -0.929389 ), vec2( 0.344959, 0.293878 ), vec2( -0.915886, 0.457714 ), vec2( -0.815442, -0.879125 ), vec2( -0.382775, 0.276768 ), vec2( 0.974844, 0.756484 ), vec2( 0.443233, -0.975116 ), vec2( 0.53743, -0.473734 ), vec2( -0.264969, -0.41893 ), vec2( 0.791975, 0.190909 ), vec2( -0.241888, 0.997065 ), vec2( -0.8141, 0.914376 ), vec2( 0.199841, 0.786414 ), [...]
+
+float oe_shadow_rand(vec2 co)
+{
+   return fract(sin(dot(co.xy, vec2(12.9898,78.233))) * 43758.5453);
+}
+
+vec2 oe_shadow_rot(vec2 p, float a)
+{
+    vec2 sincos = vec2(sin(a), cos(a));
+    return vec2(dot(p, vec2(sincos.y, -sincos.x)), dot(p, sincos.xy));
+}
+
+// slow PCF sampling.
+float oe_shadow_multisample(in vec3 c, in float refvalue, in float blur)
+{
+    float shadowed = 0.0;
+    float a = 6.283185 * oe_shadow_rand(c.xy);
+    vec4 b = vec4(oe_shadow_rot(vec2(1,0),a), oe_shadow_rot(vec2(0,1),a));
+    for(int i=0; i<OE_SHADOW_NUM_SAMPLES; ++i)
+    {
+        vec2 off = oe_shadow_samples[i];
+        off = vec2(dot(off,b.xz), dot(off,b.yw));
+        vec3 pc = vec3(c.xy + off*blur, c.z);
+        float depth = texture(oe_shadow_map, pc).r;
+        if ( depth < 1.0 && depth < refvalue ) {
+           shadowed += 1.0;
+        }
+    }
+    return 1.0-(shadowed/OE_SHADOW_NUM_SAMPLES);
+}
+
+void oe_shadow_fragment(inout vec4 color)
+{
+    float alpha = color.a;
+    float factor = 1.0;
+
+    // pre-pixel biasing to reduce moire/acne
+    const float b0 = 0.001;
+    const float b1 = 0.01;
+    vec3 L = normalize(gl_LightSource[0].position.xyz);
+    vec3 N = normalize(vp_Normal);
+    float costheta = clamp(dot(L,N), 0.0, 1.0);
+    float bias = b0*tan(acos(costheta));
+
+    float depth;
+
+    // loop over the slices:
+    for(int i=0; i<$OE_SHADOW_NUM_SLICES && factor > 0.0; ++i)
+    {
+        vec4 c = oe_shadow_coord[i];
+        vec3 coord = vec3(c.x, c.y, float(i));
+
+        // TODO: This causes an NVIDIA error (DUI_foreachId) - disable for now.
+        //if ( oe_shadow_blur > 0.0 )
+        //{
+        //    factor = min(factor, oe_shadow_multisample(coord, c.z-bias, oe_shadow_blur));
+        //}
+        //else
+        {
+            //float depth = texture(oe_shadow_map, coord).r;
+            depth = texture(oe_shadow_map, coord).r;
+            if ( depth < 1.0 && depth < c.z-bias )
+                factor = 0.0;
+        }
+    }
+
+    vec3 colorInFullShadow = color.rgb * oe_shadow_color;
+    color = vec4( mix(colorInFullShadow, color.rgb, factor), alpha );
+
+    //color = vec4(factor, 1.0);
+}
diff --git a/src/osgEarthUtil/Shadowing.vert.glsl b/src/osgEarthUtil/Shadowing.vert.glsl
new file mode 100644
index 0000000..16e16bd
--- /dev/null
+++ b/src/osgEarthUtil/Shadowing.vert.glsl
@@ -0,0 +1,18 @@
+#version $GLSL_VERSION_STR
+
+#pragma vp_name       Shadowing Vertex Shader
+#pragma vp_entryPoint oe_shadow_vertex
+#pragma vp_location   vertex_view
+
+
+uniform mat4 oe_shadow_matrix[$OE_SHADOW_NUM_SLICES];
+
+out vec4 oe_shadow_coord[$OE_SHADOW_NUM_SLICES];
+
+void oe_shadow_vertex(inout vec4 VertexVIEW)
+{
+    for(int i=0; i < $OE_SHADOW_NUM_SLICES; ++i)
+    {
+        oe_shadow_coord[i] = oe_shadow_matrix[i] * VertexVIEW;
+    }
+}
diff --git a/src/osgEarthUtil/SimplePager b/src/osgEarthUtil/SimplePager
new file mode 100644
index 0000000..d93ae5c
--- /dev/null
+++ b/src/osgEarthUtil/SimplePager
@@ -0,0 +1,145 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+* Copyright 2016 Pelican Mapping
+* http://osgearth.org
+*
+* osgEarth is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* 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.
+*
+* You should have received a copy of the GNU Lesser General Public License
+* along with this program.  If not, see <http://www.gnu.org/licenses/>
+*/
+#ifndef OSGEARTH_UTIL_SIMPLE_PAGER_H
+#define OSGEARTH_UTIL_SIMPLE_PAGER_H 1
+
+
+#include <osgEarthUtil/Common>
+#include <osgEarth/Profile>
+#include <osgEarth/Progress>
+#include <osg/Group>
+#include <osg/PagedLOD>
+
+namespace osgEarth { namespace Util {
+
+    using namespace osgEarth;
+
+    class OSGEARTHUTIL_EXPORT SimplePager : public osg::Group
+    {
+    public:
+        SimplePager(const osgEarth::Profile* profile);
+
+        void build();
+
+        /**
+         * Get or set whether this pager uses additive lods.
+         */
+        bool getAdditive() { return _additive; }
+        void setAdditive(bool additive) { _additive = additive; }
+
+        unsigned int getMinLevel() const { return _minLevel; }
+        void setMinLevel(unsigned int minLevel) { _minLevel = minLevel; }
+
+        unsigned int getMaxLevel() const { return _maxLevel; }
+        void setMaxLevel(unsigned int maxLevel) { _maxLevel = maxLevel; }
+
+        float getRangeFactor() const { return _rangeFactor; }
+        void setRangeFactor(float value) { _rangeFactor = value; }
+
+        float getPriorityScale() const { return _priorityScale; }
+        void setPriorityScale(float value) { _priorityScale = value; }
+
+        float getPriorityOffset() const { return _priorityOffset; }
+        void setPriorityOffset(float value) { _priorityOffset = value; }
+
+        void setFileLocationCallback(osgDB::FileLocationCallback* cb) { _fileLocationCallback = cb; }
+        osgDB::FileLocationCallback* getFileLocationCallback() const  { return _fileLocationCallback.get(); }
+
+        /**
+         * Gets the profile for the SimplePager.
+         */
+        const osgEarth::Profile* getProfile() const;
+
+        /**
+        * Creates a node for the given TileKey.  Doesn't do anything with paging, just gets the raw data.
+        * Subclasses override this method to provide their data for TileKeys
+        */
+        virtual osg::Node* createNode(const TileKey& key, ProgressCallback* progress);
+
+        /**
+         * Callback structure for pager events
+         */
+        struct Callback : public osg::Referenced
+        {
+            /**
+             * Called after a new tile is created, but before it's merged into the live
+             * scene graph. Runs in a pager thread.
+             */
+            virtual void onCreateNode(const TileKey& key, osg::Node* node) { }
+        };
+
+        /** Adds a pager callback. */
+        void addCallback(Callback* callback);
+
+        /** Removes a pager callback. */
+        void removeCallback(Callback* callback);
+
+    public:
+        struct ProgressTracker : public osg::NodeCallback {
+            ProgressTracker(osg::NodeCallback*);
+            osg::ref_ptr<ProgressCallback> _progress[4];
+            void operator()(osg::Node*, osg::NodeVisitor*);
+        };
+
+        /**
+        * Loads the PagedLOD hierarchy for this key.
+        */
+        osg::Node* loadKey(const TileKey& key, ProgressTracker* progress);
+
+    protected:
+
+        /**
+        * Gets the bounding sphere for a given TileKey.
+        */
+        osg::BoundingSphere getBounds(const TileKey& key) const;
+
+        /**
+        * The root node is a special node.
+        */
+        osg::Node* buildRootNode();
+
+        /**
+        * Creates a PagedLOD for the given TileKEy
+        */
+        osg::Node* createPagedNode(const TileKey& key, ProgressCallback* progress);
+
+        bool _additive;
+        double _rangeFactor;
+        unsigned int _minLevel;
+        unsigned int _maxLevel;
+        osg::ref_ptr< const osgEarth::Profile > _profile;
+        osg::ref_ptr< osg::NodeCallback > _progressMaster;
+        osg::ref_ptr< osgDB::FileLocationCallback > _fileLocationCallback;
+        float _priorityScale;
+        float _priorityOffset;
+        
+        mutable Threading::Mutex _mutex;
+        typedef std::vector< osg::ref_ptr<Callback> > Callbacks;
+        Callbacks _callbacks;
+
+        void fire_onCreateNode(const TileKey& key, osg::Node* node);
+    };
+
+} } // namespace osgEarth::Util
+
+
+#endif
\ No newline at end of file
diff --git a/src/osgEarthUtil/SimplePager.cpp b/src/osgEarthUtil/SimplePager.cpp
new file mode 100644
index 0000000..2bae6a9
--- /dev/null
+++ b/src/osgEarthUtil/SimplePager.cpp
@@ -0,0 +1,362 @@
+#include <osgEarthUtil/SimplePager> 
+#include <osgEarth/TileKey>
+#include <osgDB/Registry>
+#include <osgDB/FileNameUtils>
+#include <osgDB/Options>
+#include <osg/UserDataContainer>
+#include <osg/ShapeDrawable>
+#include <osg/MatrixTransform>
+#include <osg/Geode>
+
+using namespace osgEarth::Util;
+
+#define LC "[SimplerPager] "
+
+namespace
+{
+    /**
+     * The master progress tracker keeps track of the current framestamp
+     * for the entire paged scene graph.
+     */
+    struct ProgressMaster : public osg::NodeCallback
+    {
+        unsigned _frame;
+
+        void operator()(osg::Node* node, osg::NodeVisitor* nv)
+        {
+            _frame = nv->getFrameStamp() ? nv->getFrameStamp()->getFrameNumber() : 0u;
+            traverse(node, nv);
+        }
+    };
+
+    /**
+     * The ProgressCallback that gets passed to createNode() for the subclass
+     * to use. It will report cancelation if the last reported frame number is
+     * behind the current master frame number (as tracked by the ProgressMaster)
+     */
+    struct MyProgressCallback : public ProgressCallback
+    {
+        MyProgressCallback(ProgressMaster* master)
+        {
+            _master = master;
+            _lastFrame = 0u;
+        }
+
+        // override from ProgressCallback
+        bool isCanceled()
+        {
+            return (!_master.valid()) || (_master->_frame - _lastFrame > 1u);
+        }
+
+        // called by ProgressUpdater
+        void touch(const osg::FrameStamp* stamp)
+        {
+            if ( stamp )
+                _lastFrame = stamp->getFrameNumber();
+        }
+
+        unsigned _lastFrame;
+        osg::observer_ptr<ProgressMaster> _master;
+    };
+
+
+    /**
+    * A pseudo-loader for paged feature tiles.
+    */
+    struct SimplePagerPseudoLoader : public osgDB::ReaderWriter
+    {
+        SimplePagerPseudoLoader()
+        {
+            supportsExtension( "osgearth_pseudo_simple", "" );
+        }
+
+        const char* className() const
+        { // override
+            return "Simple Pager";
+        }
+
+        ReadResult readNode(const std::string& uri, const Options* options) const
+        {
+            if ( !acceptsExtension( osgDB::getLowerCaseFileExtension(uri) ) )
+                return ReadResult::FILE_NOT_HANDLED;
+
+            unsigned lod, x, y;
+            sscanf( uri.c_str(), "%d_%d_%d.%*s", &lod, &x, &y );
+
+
+            SimplePager* pager =
+                dynamic_cast<SimplePager*>(
+                    const_cast<osg::Object*>(
+                        options->getUserDataContainer()->getUserObject("osgEarth::Util::SimplerPager::this")));
+            
+            if (pager)
+            {
+                SimplePager::ProgressTracker* tracker =
+                    dynamic_cast<SimplePager::ProgressTracker*>(
+                        const_cast<osg::Object*>(
+                            options->getUserDataContainer()->getUserObject("osgEarth::Util::SimplerPager::ProgressTracker")));
+
+                return pager->loadKey(
+                    TileKey(lod, x, y, pager->getProfile()),
+                    tracker);
+            }
+
+            return ReadResult::ERROR_IN_READING_FILE;
+        }
+    };
+
+    REGISTER_OSGPLUGIN(osgearth_pseudo_simple, SimplePagerPseudoLoader);
+}
+
+
+SimplePager::ProgressTracker::ProgressTracker(osg::NodeCallback* master)
+{
+    setName( "osgEarth::Util::SimplerPager::ProgressTracker" );
+    for(int i=0; i<4; ++i)
+        _progress[i] = new MyProgressCallback( static_cast<ProgressMaster*>(master) );
+}
+
+void SimplePager::ProgressTracker::operator()(osg::Node* node, osg::NodeVisitor* nv)
+{
+    for(int i=0; i<4; ++i)
+        static_cast<MyProgressCallback*>(_progress[i].get())->touch( nv->getFrameStamp() );
+    traverse(node, nv);
+}
+
+
+SimplePager::SimplePager(const osgEarth::Profile* profile):
+_profile( profile ),
+_rangeFactor( 6.0 ),
+_additive(false),
+_minLevel(0),
+_maxLevel(30),
+_priorityScale(1.0f),
+_priorityOffset(0.0f)
+{
+    // required in order to pass our "this" pointer to the pseudo loader:
+    this->setName( "osgEarth::Util::SimplerPager::this" );
+    
+    // install the master framestamp tracker:
+    _progressMaster = new ProgressMaster();
+    addCullCallback( _progressMaster.get() );
+}
+
+void SimplePager::build()
+{
+    addChild( buildRootNode() );
+}
+
+osg::BoundingSphere SimplePager::getBounds(const TileKey& key) const
+{
+    int samples = 6;
+
+    GeoExtent extent = key.getExtent();
+
+    double xSample = extent.width() / (double)samples;
+    double ySample = extent.height() / (double)samples;
+
+    osg::BoundingSphere bs;
+    for (int c = 0; c < samples+1; c++)
+    {
+        double x = extent.xMin() + (double)c * xSample;
+        for (int r = 0; r < samples+1; r++)
+        {
+            double y = extent.yMin() + (double)r * ySample;
+            osg::Vec3d world;
+
+            GeoPoint samplePoint(extent.getSRS(), x, y, 0, ALTMODE_ABSOLUTE);
+
+            GeoPoint wgs84 = samplePoint.transform(osgEarth::SpatialReference::create("epsg:4326"));
+            wgs84.toWorld(world);
+            bs.expandBy(world);
+        }
+    }
+    return bs;
+}
+
+osg::Node* SimplePager::buildRootNode()
+{    
+    osg::Group* root = new osg::Group;
+
+    std::vector<TileKey> keys;
+    _profile->getRootKeys( keys );
+    for (unsigned int i = 0; i < keys.size(); i++)
+    {
+        osg::Node* node = createPagedNode( keys[i], 0L );
+        if ( node )
+            root->addChild( node );
+    }
+
+    return root;
+}
+
+osg::Node* SimplePager::createNode(const TileKey& key, ProgressCallback* progress)
+{
+    osg::BoundingSphere bounds = getBounds( key );
+
+    osg::MatrixTransform* mt = new osg::MatrixTransform;
+    mt->setMatrix(osg::Matrixd::translate( bounds.center() ) );
+    osg::Geode* geode = new osg::Geode;
+    osg::ShapeDrawable* sd = new osg::ShapeDrawable( new osg::Sphere(osg::Vec3f(0,0,0), bounds.radius()) );
+    sd->setColor( osg::Vec4(1,0,0,1 ) );
+    geode->addDrawable( sd );
+    mt->addChild(geode);
+    return mt;
+}
+
+osg::Node* SimplePager::createPagedNode(const TileKey& key, ProgressCallback* progress)
+{
+    osg::BoundingSphere tileBounds = getBounds( key );
+    float tileRadius = tileBounds.radius();
+
+    // restrict subdivision to max level:
+    bool hasChildren = key.getLOD() < _maxLevel;
+
+    // Create the actual data for this tile.
+    osg::ref_ptr<osg::Node> node;
+
+    // only create real node if we are at least at the min LOD:
+    if ( key.getLevelOfDetail() >= _minLevel )
+    {
+        node = createNode( key, progress );
+
+        if ( node.valid() )
+        {
+            tileBounds = node->getBound();
+        }
+        else
+        {
+            hasChildren = false;
+        }
+    }
+
+    if ( !node.valid() )
+    {
+        node = new osg::Group();
+    }
+
+    // notify any callbacks.
+    fire_onCreateNode(key, node.get());
+
+    tileRadius = std::max(tileBounds.radius(), tileRadius);
+
+    osg::PagedLOD* plod = new osg::PagedLOD;
+    plod->setCenter( tileBounds.center() ); 
+    plod->setRadius( tileRadius );
+
+    plod->addChild( node.get() );
+
+    if ( hasChildren )
+    {
+        std::stringstream buf;
+        buf << key.getLevelOfDetail() << "_" << key.getTileX() << "_" << key.getTileY() << ".osgearth_pseudo_simple";
+
+        std::string uri = buf.str();
+
+        // Now setup a filename on the PagedLOD that will load all of the children of this node.
+        plod->setFileName(1, uri);
+        plod->setPriorityOffset(1, _priorityOffset);
+        plod->setPriorityScale (1, _priorityScale);
+        
+        // install a callback that will update the progress tracker whenever the PLOD
+        // gets traversed. The children, once activated, will have access to its
+        // ProgressCallback within and be able to check for cancelation, use stats, etc.
+        ProgressTracker* tracker = new ProgressTracker( _progressMaster.get() );
+        plod->addCullCallback( tracker );
+
+        // assemble data to pass to the pseudoloader
+        osgDB::Options* options = new osgDB::Options();
+        options->getOrCreateUserDataContainer()->addUserObject( this );
+        options->getOrCreateUserDataContainer()->addUserObject( tracker );
+        plod->setDatabaseOptions( options );
+        
+        // Install an FLC if the caller provided one
+        if ( _fileLocationCallback.valid() )
+            options->setFileLocationCallback( _fileLocationCallback.get() );
+
+        // Setup the min and max ranges.
+        float minRange = (float)(tileRadius * _rangeFactor);
+
+        if (!_additive)
+        {
+            // Replace mode, the parent is replaced by its children.
+            plod->setRange( 0, minRange, FLT_MAX );
+            plod->setRange( 1, 0, minRange );
+        }
+        else
+        {
+            // Additive, the parent remains and new data is added
+            plod->setRange( 0, 0, FLT_MAX );
+            plod->setRange( 1, 0, minRange );
+        }
+    }
+    else
+    {
+        // no children, so max out the visibility range.
+        plod->setRange( 0, 0, FLT_MAX );
+    }
+
+    return plod;
+}
+
+
+/**
+* Loads the PagedLOD hierarchy for this key.
+*/
+osg::Node* SimplePager::loadKey(const TileKey& key, ProgressTracker* tracker)
+{       
+    osg::ref_ptr< osg::Group >  group = new osg::Group;
+
+    for (unsigned int i = 0; i < 4; i++)
+    {
+        TileKey childKey = key.createChildKey( i );
+
+        osg::Node* plod = createPagedNode( childKey, tracker->_progress[i].get() );
+        if (plod)
+        {
+            group->addChild( plod );
+        }
+    }
+    if (group->getNumChildren() > 0)
+    {
+        return group.release();
+    }
+    return 0;
+}
+
+const osgEarth::Profile* SimplePager::getProfile() const
+{
+    return _profile.get();
+}
+
+void SimplePager::addCallback(Callback* callback)
+{
+    if (callback)
+    {
+        Threading::ScopedMutexLock lock(_mutex);
+        _callbacks.push_back(callback);
+    }
+}
+
+void SimplePager::removeCallback(Callback* callback)
+{
+    if (callback)
+    {
+        Threading::ScopedMutexLock lock(_mutex);
+        for (Callbacks::iterator i = _callbacks.begin(); i != _callbacks.end(); ++i)
+        {
+            if (i->get() == callback)
+            {
+                _callbacks.erase(i);
+                break;
+            }
+        }
+    }
+}
+
+void SimplePager::fire_onCreateNode(const TileKey& key, osg::Node* node)
+{
+    Threading::ScopedMutexLock lock(_mutex);
+    for (Callbacks::iterator i = _callbacks.begin(); i != _callbacks.end(); ++i)
+        i->get()->onCreateNode(key, node);
+}
\ No newline at end of file
diff --git a/src/osgEarthUtil/SimplexNoise b/src/osgEarthUtil/SimplexNoise
index 35e83cf..4959b24 100644
--- a/src/osgEarthUtil/SimplexNoise
+++ b/src/osgEarthUtil/SimplexNoise
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
@@ -152,7 +152,7 @@ namespace osgEarth { namespace Util
         static double const G4;
 
         unsigned char permMod12[512];
-        bool permMod12Computed;
+        //bool permMod12Computed;
         void ComputePermMod12();
 
         // This method is a *lot* faster than using (int)Math.floor(x)
diff --git a/src/osgEarthUtil/SimplexNoise.cpp b/src/osgEarthUtil/SimplexNoise.cpp
index 8a5fa06..cd44918 100644
--- a/src/osgEarthUtil/SimplexNoise.cpp
+++ b/src/osgEarthUtil/SimplexNoise.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -84,6 +84,7 @@ SimplexNoise::Grad::Grad(double x, double y, double z)
     this->x = x;
     this->y = y;
     this->z = z;
+    this->w = 1.0;
 }
 
 SimplexNoise::Grad::Grad(double x, double y, double z, double w)
@@ -149,6 +150,9 @@ double SimplexNoise::getTiledValue(double x, double y) const
     double amp = 1.0;
     double maxamp = 0.0;
     double n = 0.0;
+
+    // trick to create tiled noise (2 ortho circles)
+    // http://www.gamedev.net/blog/33/entry-2138456-seamless-noise/
     
     double nx = cos(x*TwoPI)/TwoPI;
     double ny = cos(y*TwoPI)/TwoPI;
@@ -179,7 +183,10 @@ double SimplexNoise::getTiledValueWithTurbulence(double x, double y, double F) c
     double amp = 1.0;
     double maxamp = 0.0;
     double n = 0.0;
-    
+
+    // trick to create tiled noise (2 ortho circles)
+    // http://www.gamedev.net/blog/33/entry-2138456-seamless-noise/
+
     double nx = cos(x*TwoPI)/TwoPI;
     double ny = cos(y*TwoPI)/TwoPI;
     double nz = sin(x*TwoPI)/TwoPI;
diff --git a/src/osgEarthUtil/Sky b/src/osgEarthUtil/Sky
index 9f86fa6..b2c7b71 100644
--- a/src/osgEarthUtil/Sky
+++ b/src/osgEarthUtil/Sky
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
@@ -27,6 +27,7 @@
 #include <osgEarth/DateTime>
 #include <osgEarth/GeoData>
 #include <osgEarth/Config>
+#include <osgEarth/Profile>
 #include <osg/Group>
 #include <osg/Uniform>
 #include <osg/View>
@@ -167,6 +168,10 @@ namespace osgEarth { namespace Util
         void setStarsVisible(bool value);
         bool getStarsVisible() const { return _starsVisible; }
 
+        /** Whether the atmosphere is visible */
+        void setAtmosphereVisible(bool value);
+        bool getAtmosphereVisible() const { return _atmosphereVisible; }
+
         /** Access the osg::Light representing the sun */
         virtual osg::Light* getSunLight() = 0;
 
@@ -193,6 +198,7 @@ namespace osgEarth { namespace Util
         virtual void onSetMoonVisible() { }
         virtual void onSetStarsVisible() { }
         virtual void onSetSunVisible() { }
+        virtual void onSetAtmosphereVisible() { }
         virtual void onSetMinimumAmbient() { }
 
     private:
@@ -202,6 +208,7 @@ namespace osgEarth { namespace Util
         bool                    _sunVisible;
         bool                    _moonVisible;
         bool                    _starsVisible;
+        bool                    _atmosphereVisible;
         osg::Vec4f              _minimumAmbient;
         optional<GeoPoint>      _refpoint;
 
@@ -224,6 +231,18 @@ namespace osgEarth { namespace Util
         const SkyOptions& getSkyOptions(const osgDB::Options* opt) const;
     };
 
+    /**
+     * Factory interface that sky extensions need to implement. Someday we will
+     * convert the sky extensions into proper NodeKits, at which point this method
+     * will probably be no longer necessary since you can just link with the library
+     * and create the SkyNode normally.
+     */
+    class /*header-only*/ SkyNodeFactory
+    {
+    public:
+        virtual SkyNode* createSkyNode(const Profile* profile) =0;
+    };
+
 } } // namespace osgEarth::Util
 
 #endif // OSGEARTHUTIL_SKY
diff --git a/src/osgEarthUtil/Sky.cpp b/src/osgEarthUtil/Sky.cpp
index 1c63d3c..3721f18 100644
--- a/src/osgEarthUtil/Sky.cpp
+++ b/src/osgEarthUtil/Sky.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
@@ -24,6 +24,8 @@
 #include <osgEarth/Registry>
 #include <osgEarth/ShaderFactory>
 #include <osgEarth/ShaderUtils>
+#include <osgEarth/Extension>
+#include <osgEarth/MapNode>
 #include <osgDB/ReadFile>
 
 using namespace osgEarth;
@@ -55,6 +57,7 @@ SkyNode::baseInit(const SkyOptions& options)
     _sunVisible = true;
     _moonVisible = true;
     _starsVisible = true;
+    _atmosphereVisible = true;
     _minimumAmbient.set(0.0f, 0.0f, 0.0f, 0.0f);
 
     _lightingUniformsHelper = new UpdateLightingUniformsHelper();
@@ -130,6 +133,13 @@ SkyNode::setStarsVisible(bool value)
 }
 
 void
+SkyNode::setAtmosphereVisible(bool value)
+{
+    _atmosphereVisible = value;
+    onSetAtmosphereVisible();
+}
+
+void
 SkyNode::setMinimumAmbient(const osg::Vec4f& value)
 {
     _minimumAmbient = value;
@@ -156,32 +166,34 @@ SkyNode::traverse(osg::NodeVisitor& nv)
 #define SKY_OPTIONS_TAG "__osgEarth::Util::SkyOptions"
 
 SkyNode*
-SkyNode::create(const SkyOptions& options,
-                MapNode*          mapNode)
+SkyNode::create(const SkyOptions& options, MapNode* mapNode)
 {
-    SkyNode* result = 0L;
+    if ( !mapNode ) {
+        OE_WARN << LC << "Internal error; null map node passed to SkyNode::Create\n";
+        return 0L;
+    }
 
-    std::string driverName = options.getDriver();
+    std::string driverName = osgEarth::trim(options.getDriver());
     if ( driverName.empty() )
         driverName = "simple";
 
-    std::string driverExt = std::string(".osgearth_sky_") + driverName;
+    std::string extensionName = std::string("sky_") + driverName;
 
-    osg::ref_ptr<osgDB::Options> rwopts = Registry::instance()->cloneOrCreateOptions();
-    rwopts->setPluginData( MAPNODE_TAG, (void*)mapNode );
-    rwopts->setPluginData( SKY_OPTIONS_TAG, (void*)&options );
-
-    result = dynamic_cast<SkyNode*>( osgDB::readNodeFile( driverExt, rwopts.get() ) );
-    if ( result )
-    {
-        OE_INFO << LC << "Loaded sky driver \"" << driverName << "\" OK." << std::endl;
+    osg::ref_ptr<Extension> extension = Extension::create( extensionName, options );
+    if ( !extension.valid() ) {
+        OE_WARN << LC << "Failed to load extension for sky driver \"" << driverName << "\"\n";
+        return 0L;
     }
-    else
-    {
-        OE_WARN << LC << "FAIL, unable to load sky driver for \"" << driverName << "\"" << std::endl;
+
+    SkyNodeFactory* factory = extension->as<SkyNodeFactory>();
+    if ( !factory ) {
+        OE_WARN << LC << "Internal error; extension \"" << extensionName << "\" does not implement SkyNodeFactory\n";
+        return 0L;
     }
 
-    return result;
+    osg::ref_ptr<SkyNode> result = factory->createSkyNode(mapNode->getMap()->getProfile());
+
+    return result.release();
 }
 
 SkyNode*
@@ -205,7 +217,9 @@ SkyNode::create(const std::string& driver, MapNode* mapNode)
 const SkyOptions&
 SkyDriver::getSkyOptions(const osgDB::Options* options) const
 {
-    return *static_cast<const SkyOptions*>( options->getPluginData(SKY_OPTIONS_TAG) );
+    static SkyOptions s_default;
+    const void* data = options->getPluginData(SKY_OPTIONS_TAG);
+    return data ? *static_cast<const SkyOptions*>(data) : s_default;
 }
 
 
diff --git a/src/osgEarthUtil/SpatialData b/src/osgEarthUtil/SpatialData
index 166c54d..ef36921 100644
--- a/src/osgEarthUtil/SpatialData
+++ b/src/osgEarthUtil/SpatialData
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthUtil/SpatialData.cpp b/src/osgEarthUtil/SpatialData.cpp
index 9a921a8..5ebb8d2 100644
--- a/src/osgEarthUtil/SpatialData.cpp
+++ b/src/osgEarthUtil/SpatialData.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -103,7 +103,7 @@ namespace
 
 //------------------------------------------------------------------------
 
-GeoObject::GeoObject()
+GeoObject::GeoObject() : _priority(0.0f)
 {
     //NOP
 }
@@ -176,7 +176,8 @@ _depth( depth ),
 _minObjects( (maxObjects/10)*8 ), // 80%
 _count( 0 ),
 _boundaryPoints( 10 ),
-_frameStamp( 0 )
+_frameStamp( 0 ),
+_boundaryColor(0L)
 {
     generateBoundaries();
     //generateBoundaryGeometry();
@@ -319,13 +320,16 @@ GeoCell::traverse( osg::NodeVisitor& nv )
             // custom BSP culling function. this checks that the set of boundary points
             // for this cell intersects the viewing frustum.
             osgUtil::CullVisitor* cv = Culling::asCullVisitor(nv);
-            if ( cv && !intersects( cv->getCurrentCullingSet().getFrustum() ) )
+            if ( cv )
             {
-                return;
-            }
+                if (!intersects( cv->getCurrentCullingSet().getFrustum() ) )
+                {
+                    return;
+                }
 
-            // passed cull, so record the framestamp.
-            _frameStamp = cv->getFrameStamp()->getFrameNumber();
+                // passed cull, so record the framestamp.
+                _frameStamp = cv->getFrameStamp()->getFrameNumber();
+            }
         }
 
         if ( _objects.size() > 0 )
diff --git a/src/osgEarthUtil/StarData b/src/osgEarthUtil/StarData
index 16c6265..6916326 100644
--- a/src/osgEarthUtil/StarData
+++ b/src/osgEarthUtil/StarData
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthUtil/TFS b/src/osgEarthUtil/TFS
index 037eee7..d88f0e8 100644
--- a/src/osgEarthUtil/TFS
+++ b/src/osgEarthUtil/TFS
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthUtil/TFS.cpp b/src/osgEarthUtil/TFS.cpp
index e7279fc..65b2f2d 100644
--- a/src/osgEarthUtil/TFS.cpp
+++ b/src/osgEarthUtil/TFS.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthUtil/TFSPackager b/src/osgEarthUtil/TFSPackager
index 7878eda..0c13ded 100644
--- a/src/osgEarthUtil/TFSPackager
+++ b/src/osgEarthUtil/TFSPackager
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthUtil/TFSPackager.cpp b/src/osgEarthUtil/TFSPackager.cpp
index 86c4110..919284e 100644
--- a/src/osgEarthUtil/TFSPackager.cpp
+++ b/src/osgEarthUtil/TFSPackager.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthUtil/TMS b/src/osgEarthUtil/TMS
index a58361a..41e4f79 100644
--- a/src/osgEarthUtil/TMS
+++ b/src/osgEarthUtil/TMS
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
@@ -394,18 +394,11 @@ namespace osgEarth { namespace Util { namespace TMS
         static TileMap* create(
             const std::string& url,
             const Profile* profile,
-            //osgEarth::Profile::ProfileType type,
+            const DataExtentList& dataExtents,
             const std::string& format,
             int tile_width,
             int tile_height );
 
-        /**
-         * Creates a TileMap based on the parameters of a TileSource
-         */
-        static TileMap* create(
-            const TileSource* tileSource,
-            const Profile*    profile );
-
     protected:
         std::string _tileMapService;
         std::string _version;
diff --git a/src/osgEarthUtil/TMS.cpp b/src/osgEarthUtil/TMS.cpp
index fb58afd..aabbf91 100644
--- a/src/osgEarthUtil/TMS.cpp
+++ b/src/osgEarthUtil/TMS.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -80,7 +80,8 @@ _numTilesHigh(-1),
 _numTilesWide(-1),
 _timestamp(0),
 _version("1.0"),
-_tileMapService("http://tms.osgeo.org/1.0.0")
+_tileMapService("http://tms.osgeo.org/1.0.0"),
+_profile_type(Profile::TYPE_MERCATOR)
 {   
 }
 
@@ -393,6 +394,7 @@ std::string getHorizSRSString(const osgEarth::SpatialReference* srs)
 TileMap*
 TileMap::create(const std::string& url,
                 const Profile*     profile,
+                const DataExtentList& dataExtents,
                 const std::string& format,
                 int                tile_width,
                 int                tile_height)
@@ -423,42 +425,31 @@ TileMap::create(const std::string& url,
         tileMap->_format.setExtension( Registry::instance()->getExtensionForMimeType(format) );
     }
 
-    tileMap->generateTileSets();
-    tileMap->computeMinMaxLevel();
-
-    return tileMap;
-}
-
-TileMap* TileMap::create(const TileSource* tileSource, const Profile* profile)
-{
-    TileMap* tileMap = new TileMap();
-
-    tileMap->setTitle( tileSource->getName() );
-    tileMap->setProfileType( profile->getProfileType() );
+    //Add the data extents
+    tileMap->getDataExtents().insert(tileMap->getDataExtents().end(), dataExtents.begin(), dataExtents.end());
 
-    const GeoExtent& ex = profile->getExtent();
-    
-    tileMap->_srs = getHorizSRSString(profile->getSRS()); //srs();
-    tileMap->_vsrs = profile->getSRS()->getVertInitString(); //profile->getVerticalSRS() ? profile->getVerticalSRS()->getInitString() : 0L;
-    tileMap->_originX = ex.xMin();
-    tileMap->_originY = ex.yMin();
-    tileMap->_minX = ex.xMin();
-    tileMap->_minY = ex.yMin();
-    tileMap->_maxX = ex.xMax();
-    tileMap->_maxY = ex.yMax();
-    profile->getNumTiles( 0, tileMap->_numTilesWide, tileMap->_numTilesHigh );
+    // If we have some data extents specified then make a nicer bounds than the 
+    if (!tileMap->getDataExtents().empty())
+    {
+        // Get the union of all the extents
+        GeoExtent e(tileMap->getDataExtents()[0]);
+        for (unsigned int i = 1; i < tileMap->getDataExtents().size(); i++)
+        {
+            e.expandToInclude(tileMap->getDataExtents()[i]);
+        }
 
-    tileMap->_format.setWidth( tileSource->getPixelsPerTile() );
-    tileMap->_format.setHeight( tileSource->getPixelsPerTile() );
-    tileMap->_format.setExtension( tileSource->getExtension() );
+        // Convert the bounds to the output profile
+        GeoExtent bounds = e.transform(profile->getSRS());
+        tileMap->setExtents(bounds.xMin(), bounds.yMin(), bounds.xMax(), bounds.yMax());
+    }
 
     tileMap->generateTileSets();
+    tileMap->computeMinMaxLevel();
 
     return tileMap;
 }
 
 
-
 //----------------------------------------------------------------------------
 
 
@@ -470,7 +461,7 @@ TileMapReaderWriter::read( const std::string& location, const osgDB::ReaderWrite
     ReadResult r = URI(location).readString();
     if ( r.failed() )
     {
-        OE_WARN << LC << "Failed to read TMS tile map file from " << location << std::endl;
+        OE_DEBUG << LC << "Failed to read TMS tile map file from " << location << std::endl;
         return 0L;
     }
     
diff --git a/src/osgEarthUtil/TMSBackFiller b/src/osgEarthUtil/TMSBackFiller
index 11a6d74..0c22df2 100644
--- a/src/osgEarthUtil/TMSBackFiller
+++ b/src/osgEarthUtil/TMSBackFiller
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthUtil/TMSBackFiller.cpp b/src/osgEarthUtil/TMSBackFiller.cpp
index ab4057c..b22df3e 100644
--- a/src/osgEarthUtil/TMSBackFiller.cpp
+++ b/src/osgEarthUtil/TMSBackFiller.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
@@ -34,8 +34,12 @@
 using namespace osgEarth::Util;
 using namespace osgEarth;
 
-TMSBackFiller::TMSBackFiller()
+TMSBackFiller::TMSBackFiller() :
+_minLevel(0u),
+_maxLevel(0u),
+_verbose(false)
 {
+    //nop
 }
 
 
diff --git a/src/osgEarthUtil/TMSPackager b/src/osgEarthUtil/TMSPackager
index f64917e..08d41ae 100644
--- a/src/osgEarthUtil/TMSPackager
+++ b/src/osgEarthUtil/TMSPackager
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
@@ -139,6 +139,16 @@ namespace osgEarth { namespace Util
         void setWriteOptions( osgDB::Options* options );        
 
         /**
+         * Sets the TileSource for output. Overrides default TMS writer.
+         */
+        void setTileSource( osgEarth::TileSource* source );
+
+        /**
+         * Gets the TileSource used for output.
+         */
+        osgEarth::TileSource* getTileSource() const;
+
+        /**
          * Gets the layer name to use in the TMS XML.
          */
         const std::string& getLayerName() const;
@@ -176,6 +186,7 @@ namespace osgEarth { namespace Util
         std::string _layerName;
         bool _overwrite;
         osg::ref_ptr<osgDB::Options>    _writeOptions;
+        osg::ref_ptr<osgEarth::TileSource> _tileSource;
 
         unsigned int _width;
         unsigned int _height;
diff --git a/src/osgEarthUtil/TMSPackager.cpp b/src/osgEarthUtil/TMSPackager.cpp
index 078dfb9..7a525fb 100644
--- a/src/osgEarthUtil/TMSPackager.cpp
+++ b/src/osgEarthUtil/TMSPackager.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -64,14 +64,20 @@ bool WriteTMSTileHandler::handleTile(const TileKey& key, const TileVisitor& tv)
     // Get the path to write to
     std::string path = getPathForTile( key );
 
+    // Get the user set TileSource for output if it is set
+    osgEarth::TileSource* tileSource = _packager->getTileSource();
+
     // Don't write out a new file if we're not overwriting
-    if (osgDB::fileExists(path) && !_packager->getOverwrite())
+    if (!tileSource && osgDB::fileExists(path) && !_packager->getOverwrite())
     {
         return true;
     }
 
-    // attempt to create the output folder:        
-    osgEarth::makeDirectoryForFile( path );       
+    if (!tileSource)
+    {
+        // attempt to create the output folder:        
+        osgEarth::makeDirectoryForFile( path );       
+    }
 
 
     if (imageLayer)
@@ -98,14 +104,24 @@ bool WriteTMSTileHandler::handleTile(const TileKey& key, const TileVisitor& tv)
             }
 
             // OE_NOTICE << "Created image for " << key.str() << std::endl;
-            osg::ref_ptr< const osg::Image > final = geoImage.getImage();                        
+            osg::ref_ptr< osg::Image > final = geoImage.getImage();                        
 
             // convert to RGB if necessary            
             if ( _packager->getExtension() == "jpg" && final->getPixelFormat() != GL_RGB )
             {
                 final = ImageUtils::convertToRGB8( final );
             }            
-            return osgDB::writeImageFile(*final, path, _packager->getOptions());
+
+            // use the TileSource provided if set, else use writeImageFile
+            if (tileSource)
+            {
+                tileSource->storeImage(key, final.get(), 0L);
+                return true;
+            }
+            else
+            {
+                return osgDB::writeImageFile(*final, path, _packager->getOptions());
+            }
         }            
     }
     else if (elevationLayer )
@@ -115,8 +131,18 @@ bool WriteTMSTileHandler::handleTile(const TileKey& key, const TileVisitor& tv)
         {
             // convert the HF to an image
             ImageToHeightFieldConverter conv;
-            osg::ref_ptr< osg::Image > image = conv.convert( hf.getHeightField(), _packager->getElevationPixelDepth() );				            
-            return osgDB::writeImageFile(*image.get(), path, _packager->getOptions());
+            osg::ref_ptr< osg::Image > image = conv.convert( hf.getHeightField(), _packager->getElevationPixelDepth() );	
+
+            // use the TileSource provided if set, else use writeImageFile
+            if (tileSource)
+            {
+                tileSource->storeImage(key, image.get(), 0L);
+                return true;
+            }
+            else
+            {
+                return osgDB::writeImageFile(*image.get(), path, _packager->getOptions());
+            }
         }            
     }
         
@@ -148,7 +174,7 @@ std::string WriteTMSTileHandler::getProcessString() const
     buf << "osgearth_package --tms ";
     if (imageLayer)
     {        
-        for (unsigned int i = 0; i < _map->getNumImageLayers(); i++)
+        for (int i = 0; i < _map->getNumImageLayers(); i++)
         {
             if (imageLayer == _map->getImageLayerAt(i))
             {
@@ -159,7 +185,7 @@ std::string WriteTMSTileHandler::getProcessString() const
     }
     else if (elevationLayer)
     {
-        for (unsigned int i = 0; i < _map->getNumElevationLayers(); i++)
+        for (int i = 0; i < _map->getNumElevationLayers(); i++)
         {
             if (elevationLayer == _map->getElevationLayerAt(i))
             {
@@ -200,7 +226,8 @@ _visitor(new TileVisitor()),
     _height(0),
     _overwrite(false),
     _keepEmpties(false),
-    _applyAlphaMask(false)
+    _applyAlphaMask(false),
+    _tileSource(0L)
 {
 }
 
@@ -244,6 +271,16 @@ void TMSPackager::setWriteOptions( osgDB::Options* options )
     _writeOptions = options;
 }
 
+void TMSPackager::setTileSource( osgEarth::TileSource* source )
+{
+    _tileSource = source;
+}
+
+osgEarth::TileSource* TMSPackager::getTileSource() const
+{
+    return _tileSource.get();
+}
+
 const std::string& TMSPackager::getLayerName() const
 {
     return _layerName;
@@ -296,12 +333,6 @@ void TMSPackager::setVisitor(TileVisitor* visitor)
 
 void TMSPackager::run( TerrainLayer* layer,  Map* map  )
 {    
-    // Get a test image from the root keys
-
-    // collect the root tile keys in preparation for packaging:
-    std::vector<TileKey> rootKeys;
-    map->getProfile()->getRootKeys( rootKeys );
-
     // fetch one tile to see what the image size should be
     ImageLayer* imageLayer = dynamic_cast<ImageLayer*>(layer);
     ElevationLayer* elevationLayer = dynamic_cast<ElevationLayer*>(layer);
@@ -316,7 +347,7 @@ void TMSPackager::run( TerrainLayer* layer,  Map* map  )
         {            
             layerName << "image";
             // Get the index of the layer
-            for (unsigned int i = 0; i < map->getNumImageLayers(); i++)
+            for (int i = 0; i < map->getNumImageLayers(); i++)
             {
                 if (map->getImageLayerAt(i) == imageLayer)
                 {
@@ -329,7 +360,7 @@ void TMSPackager::run( TerrainLayer* layer,  Map* map  )
         {
             layerName << "elevation";
             // Get the index of the layer
-            for (unsigned int i = 0; i < map->getNumElevationLayers(); i++)
+            for (int i = 0; i < map->getNumElevationLayers(); i++)
             {
                 if (map->getElevationLayerAt(i) == elevationLayer)
                 {
@@ -388,10 +419,13 @@ void TMSPackager::run( TerrainLayer* layer,  Map* map  )
 
 void TMSPackager::writeXML( TerrainLayer* layer, Map* map)
 {
+    DataExtentList dataExtents;
+    layer->getDataExtents(dataExtents);
      // create the tile map metadata:
     osg::ref_ptr<TMS::TileMap> tileMap = TMS::TileMap::create(
         "",
         map->getProfile(),        
+        dataExtents,
         _extension,
         _width,
         _height
diff --git a/src/osgEarthUtil/TerrainProfile b/src/osgEarthUtil/TerrainProfile
index a4aa268..2d26c0a 100644
--- a/src/osgEarthUtil/TerrainProfile
+++ b/src/osgEarthUtil/TerrainProfile
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthUtil/TerrainProfile.cpp b/src/osgEarthUtil/TerrainProfile.cpp
index 3ebd2db..c56d8c6 100644
--- a/src/osgEarthUtil/TerrainProfile.cpp
+++ b/src/osgEarthUtil/TerrainProfile.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthUtil/TileIndex b/src/osgEarthUtil/TileIndex
index edeafb0..27d3790 100644
--- a/src/osgEarthUtil/TileIndex
+++ b/src/osgEarthUtil/TileIndex
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthUtil/TileIndex.cpp b/src/osgEarthUtil/TileIndex.cpp
index c3565b4..da0b540 100644
--- a/src/osgEarthUtil/TileIndex.cpp
+++ b/src/osgEarthUtil/TileIndex.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
@@ -46,7 +46,7 @@ TileIndex::~TileIndex()
 }
 
 TileIndex*
-    TileIndex::load(const std::string& filename)
+TileIndex::load(const std::string& filename)
 {        
     if (!osgDB::fileExists( filename ) )
     {
@@ -65,8 +65,12 @@ TileIndex*
         OE_NOTICE << "Can't load " << filename << std::endl;
         return 0;
     }
-    features->initialize();
-    features->getFeatureProfile();    
+    Status s = features->open();
+    if (s.isError())
+    {
+        OE_WARN << s.message();
+        return 0L;
+    }
 
     TileIndex* index = new TileIndex();
     index->_features = features.get();
@@ -75,7 +79,7 @@ TileIndex*
 }
 
 TileIndex*
-    TileIndex::create( const std::string& filename, const osgEarth::SpatialReference* srs )
+TileIndex::create( const std::string& filename, const osgEarth::SpatialReference* srs )
 {
     // Make sure the registry is loaded since that is where the OGR/GDAL registration happens
     osgEarth::Registry::instance();
@@ -106,7 +110,7 @@ TileIndex*
 
 
 void
-    TileIndex::getFiles(const osgEarth::GeoExtent& extent, std::vector< std::string >& files)
+TileIndex::getFiles(const osgEarth::GeoExtent& extent, std::vector< std::string >& files)
 {            
     files.clear();
     osgEarth::Symbology::Query query;    
diff --git a/src/osgEarthUtil/TileIndexBuilder b/src/osgEarthUtil/TileIndexBuilder
index a5c3c58..b965883 100644
--- a/src/osgEarthUtil/TileIndexBuilder
+++ b/src/osgEarthUtil/TileIndexBuilder
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthUtil/TileIndexBuilder.cpp b/src/osgEarthUtil/TileIndexBuilder.cpp
index 1172100..1697441 100644
--- a/src/osgEarthUtil/TileIndexBuilder.cpp
+++ b/src/osgEarthUtil/TileIndexBuilder.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthUtil/UTMGraticule b/src/osgEarthUtil/UTMGraticule
index 7f1cf6d..cf94881 100644
--- a/src/osgEarthUtil/UTMGraticule
+++ b/src/osgEarthUtil/UTMGraticule
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthUtil/UTMGraticule.cpp b/src/osgEarthUtil/UTMGraticule.cpp
index 5257549..52c1ad2 100644
--- a/src/osgEarthUtil/UTMGraticule.cpp
+++ b/src/osgEarthUtil/UTMGraticule.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthUtil/WFS b/src/osgEarthUtil/WFS
index 357b558..c745b04 100644
--- a/src/osgEarthUtil/WFS
+++ b/src/osgEarthUtil/WFS
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthUtil/WFS.cpp b/src/osgEarthUtil/WFS.cpp
index b396da7..26ecb30 100644
--- a/src/osgEarthUtil/WFS.cpp
+++ b/src/osgEarthUtil/WFS.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
@@ -63,8 +63,12 @@ WFSCapabilities::getFeatureTypeByName(const std::string& name)
 #define ATTR_MAXY              "maxy"
 
 /**************************************************************************************/
-WFSFeatureType::WFSFeatureType()
+WFSFeatureType::WFSFeatureType() :
+_tiled(false),
+_maxLevel(0),
+_firstLevel(0)
 {    
+    //nop
 }
 /**************************************************************************************/
 
diff --git a/src/osgEarthUtil/WMS b/src/osgEarthUtil/WMS
index ed2ab22..0c05097 100644
--- a/src/osgEarthUtil/WMS
+++ b/src/osgEarthUtil/WMS
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2015 Pelican Mapping
+* Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
diff --git a/src/osgEarthUtil/WMS.cpp b/src/osgEarthUtil/WMS.cpp
index e45d64f..eb6407a 100644
--- a/src/osgEarthUtil/WMS.cpp
+++ b/src/osgEarthUtil/WMS.cpp
@@ -1,6 +1,6 @@
 /* -*-c++-*- */
 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2015 Pelican Mapping
+ * Copyright 2016 Pelican Mapping
  * http://osgearth.org
  *
  * osgEarth is free software; you can redistribute it and/or modify
diff --git a/tests/annotation.earth b/tests/annotation.earth
index 389f4f7..53535bd 100644
--- a/tests/annotation.earth
+++ b/tests/annotation.earth
@@ -8,165 +8,208 @@ osgEarth Sample - Annotations
     </image>
         
     <elevation name="ReadyMap.org - Elevation" driver="tms">
-        <url>http://readymap.org/readymap/tiles/1.0.0/9/</url>
+        <url>http://readymap.org/readymap/tiles/1.0.0/116/</url>
     </elevation>
     
-    <options>
-        <terrain>
-            <lighting>false</lighting>
-            <sample_ratio>0.125</sample_ratio>
-        </terrain>
-        <!-- <cache_policy usage="cache_only"/> -->
-    </options>
+    <viewpoints>
+        <viewpoint name="Annotation Samples" 
+                   lat="33" long="-118" range="500000"
+                   heading="35.27" pitch="-35" />
+    </viewpoints>
     
-    <external>
-        <viewpoints>
-            <viewpoint name="Annotation Samples" 
-                       lat="33" long="-118" range="500000"
-                       heading="35.27" pitch="-35" />
-        </viewpoints>
+    <annotations>
+    
+        <label text="Label">
+            <position lat="34" long="-120" />
+            <style type="text/css">
+                text-align:     center_center;
+                text-size:      20;
+                text-declutter: true;
+                text-halo:      #777;
+                text-bbox-fill: #00FF0033;
+                text-bbox-margin: 3;
+                text-bbox-border: #FFFFFFFF;
+                text-bbox-border-width: 1;
+            </style>
+        </label>
+    
+        <label text="Label with offsets">
+            <position lat="16" long="-120" />
+            <style type="text/css">
+                text-align:     center_center;
+                text-size:      20;
+                text-declutter: true;
+                text-halo:      #777;
+                text-offset-x:  28;
+                text-offset-y:  -100;
+                text-bbox-fill: #00FF0033;
+                text-bbox-margin: 3;
+                text-bbox-border: #FFFFFFFF;
+                text-bbox-border-width: 1;
+            </style>
+        </label>
+        
+        <place text="Place">
+            <position lat="35" long="-110"/>
+            <icon>../data/placemark32.png</icon>
+            <style type="text/css">
+                text-declutter: true;
+                text-halo:      #777;
+            </style>
+        </place>
+        
+        <circle name="draped circle">
+            <position lat="34.051" long="-117.974"/>
+            <radius value="50" units="km"/>
+            <style type="text/css">
+                fill:               #ffff0080;
+                stroke:             #ffffff;
+                stroke-width:       2px;
+                altitude-clamping:  terrain-drape;
+            </style>
+        </circle>
+        <label text="Draped circle" lat="34.051" long="-117.974"/>
+        
+        <circle name="scene-clamped circle">
+            <position lat="22.074" long="-159.606"/>
+            <radius value="1.2" units="km"/>
+            <style type="text/css">
+                stroke:             #ffffff;
+                stroke-width:       2px;
+                altitude-clamping:  terrain-scene;
+                altitude-binding:   vertex;
+            </style>
+        </circle>
+        <label text="scene-clamped circle" lat="22.074" long="-159.606"/>
         
-        <annotations>
+        <ellipse name="ellipse relative">
+            <position lat="40" long="-100" hat="5000"/>
+            <radius_major value="50" units="km"/>
+            <radius_minor value="40" units="km"/>
+            <style type="text/css">
+                fill: #ff00ff7f;
+                stroke: #ffffff;
+            </style>
+        </ellipse>
+        <label text="HAT Ellipse" lat="40" long="-100.0"/>
         
-            <label text="Los Angeles">
-                <position lat="35.051" long="-117.974" alt="100" mode="relative"/>
-                <style type="text/css">
-                    text-align:     center_center;
-                    text-size:      20;
-                    text-declutter: false;
-                </style>
-            </label>
-            
-            <place text="San Diego">
-                <position lat="32.73" long="-117.17"/>
-                <icon>http://demo.pelicanmapping.com/icons/gmaps/yoga.png</icon>
-                <style type="text/css">
-                    text-declutter: true;
-                </style>
-            </place>
-            
-            <circle name="draped circle">
-                <position lat="34.051" long="-117.974"/>
-                <radius value="50" units="km"/>
-                <style type="text/css">
-                    fill:               #ffff0080;
-                    altitude-clamping:  terrain;
-                    altitude-technique: drape;
-                </style>
-            </circle>
-            
-            <ellipse name="ellipse relative">
-                <position lat="34.051" long="-116" hat="5000"/>
-                <radius_major value="50" units="km"/>
-                <radius_minor value="40" units="km"/>
-                <style type="text/css">
-                    fill: #ffff0080;
-                </style>
-            </ellipse>
-            
-            <ellipse name="ellipse extruded">
-                <position lat="32.73" long="-119.0"/>
-                <radius_major value="50" units="km"/>
-                <radius_minor value="20" units="km"/>
-                <style type="text/css">
-                    fill:             #ff7f007f;
-                    stroke:           #ff0000ff;
-                    extrusion-height: 5000;
-                </style>
-            </ellipse>
-            
-            <rectangle name="absolute rectangle">
-                <position lat="32.2" long="-118" alt="1000"/>
-                <width value="50" units="nm"/>
-                <height value="25" units="nm"/>
-                <style type="text/css">
-                    stroke:       #00ffff; 
-                    stroke-width: 2; 
-                </style>
-            </rectangle>
+        <ellipse name="ellipse extruded">
+            <position lat="32" long="-100.0"/>
+            <radius_major value="50" units="km"/>
+            <radius_minor value="20" units="km"/>
+            <style type="text/css">
+                fill:             #ff7f007f;
+                stroke:           #ff0000ff;
+                extrusion-height: 5000;
+            </style>
+        </ellipse>
+        <label text="Extruded Ellipse" lat="32" long="-100.0"/>
 
-            <feature name="extruded line">
-                <srs>wgs84</srs>
-                <geometry>
-                    LINESTRING(-120.37 34.039, -120.09 33.96, -119.75 34, -118.43 33.37, -118.48 32.88)
-                </geometry>
-                <style type="text/css">
-                    fill:                #ff00ff7f;
-                    stroke:              #ffff00;
-                    stroke-width:        3;
-					stroke-crease-angle: 45.0;
-                    extrusion-height:    30000;
-                    render-lighting:     false;
-                </style>
-            </feature>
+        <feature name="Extruded Line">
+            <srs>wgs84</srs>
+            <geometry>
+                LINESTRING(-80.37 34.039, -80.09 33.96, -79.75 34, -79.43 33.37, -79.48 32.88)
+            </geometry>
+            <style type="text/css">
+                fill:                #ff00ff7f;
+                stroke:              #ffff00;
+                stroke-width:        3;
+                stroke-crease-angle: 45.0;
+                extrusion-height:    30000;
+                render-lighting:     true;
+            </style>
+        </feature>
+        <label text="Extruded Line" lat="32" long="-80"/>
 
-            <feature name="gpu clamped line">
-                <srs>wgs84</srs>
-                <geometry>
-                    LINESTRING(-120 37, -120 33, -118 33, -118 32)
-                </geometry>
-                <style type="text/css">
-                    stroke:              #ff3000;
-                    stroke-width:        3;
-                    stroke-tessellation: 100;
-                    altitude-clamping:   terrain;
-                    altitude-technique:  gpu;
-                    render-lighting:     false;
-                </style>
-            </feature>
-            
-            <model name="flag model">
-                <url>../data/red_flag.osg.18000.scale</url>
-                <position lat="33" long="-117.75" hat="0"/>
-            </model>
-            
-            <imageoverlay>
-                <url>../data/fractal.png</url>
-                <alpha>1.0</alpha>
-                <geometry>POLYGON((-81 26, -80.5 26, -80.5 26.5, -81 26.5))</geometry>
-            </imageoverlay>
-            
-            <label text="image overlay">
-                <position lat="26" long="-81" />
-            </label>
-            
-            <local_geometry name="3D geometry">
-                <geometry>
-                    POLYGON((0 0 0, -1000 0 25000, -5000 0 25000, 0 0 30000, 5000 0 25000, 1000 0 25000))
-                </geometry>
-                <position lat="33.4" long="-116.6" hat="0"/>
-                <style type="text/css">
-                    fill:            #00ff00;
-                    stroke:          #ffff00;
-                    render-lighting: false;
-                </style>
-            </local_geometry>
-            
-            <circle name="scene-clamped circle">
-                <position lat="33.4" long="-116.6"/>
-                <radius value="5" units="km"/>
-                <style type="text/css">
-                    fill: #afafff9f;
-                    render-lighting: false;
-                </style>
-            </circle>
+        <feature name="GPU-Clamped Line">
+            <srs>wgs84</srs>
+            <geometry>
+                LINESTRING(-110 47, -110 43, -120 43, -120 42)
+            </geometry>
+            <style type="text/css">
+                stroke:              #ff3000;
+                stroke-width:        3;
+                stroke-tessellation-size: 1km;
+                altitude-clamping:   terrain-gpu;
+            </style>
+        </feature>
+        <label text="GPU-Clamped Line" lat="44" long="-115">
+            <style type="text/css">
+                text-align:             center_center;
+                text-geographic-course: 45.0;
+                text-bbox-fill: #FFFF0033;
+                text-bbox-margin: 8;
+                text-bbox-border: #FFFF00;
+                text-bbox-border-width: 0.5;
+            </style>
+        </label>
+        
+        <feature name="Draped Polygon">
+            <srs>wgs84</srs>
+            <geometry>
+                POLYGON((-100 47, -100 49, -95 48, -96 45 -98 42))
+            </geometry>
+            <style type="text/css">
+                fill:     #ffff007f;
+                stroke:   #ffffff;
+                stroke-width: 2px;
+                altitude-clamping: terrain-drape;
+            </style>
+        </feature>
+        <label text="Draped Polygon" lat="45" long="-98"/>
+        
+        <model name="Auto-Scaled Model">
+            <position lat="43" long="-100"/>
+            <style>
+                model:       "../data/red_flag.osg.45.scale";
+                model-scale: auto;
+            </style>
+        </model>
+        <label text="Auto-Scaled Model" lat="42.5" long="-100"/>
+        
+        <imageoverlay>
+            <url>../data/fractal.png</url>
+            <alpha>1.0</alpha>
+            <geometry>POLYGON((-81 26, -80.5 26, -80.5 26.5, -81 26.5))</geometry>
+        </imageoverlay>            
+        <label text="ImageOverlay" lat="26" long="-81"/>
+        
+        <local_geometry name="3D geometry">
+            <geometry>
+                POLYGON((0 0 0, -25000 0 45000, 0 0 75000, 25000 0 45000))
+            </geometry>
+            <position lat="33.4" long="-116.6"/>
+            <style type="text/css">
+                fill:            #00ff00;
+                stroke:          #ffff00;
+                stroke-width:    2px;
+                render-lighting: false;
+            </style>
+            <horizon_culling>true</horizon_culling>
+        </local_geometry>
+        <label text="3D Geometry" lat="33.4" long="-116.6"/>
 
-            <feature name="Long Line">
-                <srs>wgs84</srs>
-                <geometry>
-                    LINESTRING(0 0, 0 65)
-                </geometry>
-                <style type="text/css">
-                    stroke:              #ffff00;
-                    stroke-width:        3;
-                    stroke-tessellation: 90;
-                    altitude-clamping:   relative;
-					altitude-technique:  scene;
-                    render-lighting:     false;
-                </style>
-            </feature>
-            
-        </annotations>
+        <feature name="Long Line">
+            <srs>wgs84</srs>
+            <geometry>
+                LINESTRING(10 0, 10 65)
+            </geometry>
+            <style type="text/css">
+                stroke:              #ffff00;
+                stroke-width:        3;
+                stroke-tessellation-size: 10km;
+                altitude-clamping:   terrain;
+                altitude-technique:  scene;
+                render-lighting:     false;
+            </style>
+        </feature>
+        
+        <label text="Tessellated line" lat="35" long="10">
+            <style type="text/css">
+                text-align:              center_bottom;
+                text-geographic-course:  0;
+            </style>
+        </label>
         
-    </external>
+    </annotations>
 </map>
diff --git a/tests/annotation_flat.earth b/tests/annotation_flat.earth
index b5d565b..15d1056 100644
--- a/tests/annotation_flat.earth
+++ b/tests/annotation_flat.earth
@@ -3,169 +3,201 @@ osgEarth Sample - Annotations
 -->
 <map name="readymap.org" type="projected" version="2">
 
+    <options>
+        <profile>plate-carre</profile>
+    </options>
+
     <image name="ReadyMap.org - Imagery" driver="tms">
         <url>http://readymap.org/readymap/tiles/1.0.0/7/</url>
     </image>
         
     <elevation name="ReadyMap.org - Elevation" driver="tms">
-        <url>http://readymap.org/readymap/tiles/1.0.0/9/</url>
+        <url>http://readymap.org/readymap/tiles/1.0.0/116/</url>
     </elevation>
     
-    <options>
-        <terrain>
-            <lighting>false</lighting>
-        </terrain>
-		<profile>spherical-mercator</profile>
-    </options>
+    <viewpoints>
+        <viewpoint name="Annotation Samples" 
+                   lat="33" long="-118" range="500000"
+                   heading="35.27" pitch="-35" />
+    </viewpoints>
+    
+    <annotations>
     
-    <external>
-        <viewpoints>
-            <viewpoint name="Annotation Samples" 
-                       lat="33" long="-118" range="500000"
-                       heading="35.27" pitch="-35" />
-        </viewpoints>
+        <label text="Label">
+            <position lat="34" long="-120" />
+            <style type="text/css">
+                text-align:     center_center;
+                text-size:      20;
+                text-declutter: true;
+                text-halo:      #777;
+                text-bbox-fill: #00FF0033;
+                text-bbox-margin: 3;
+                text-bbox-border: #FFFFFFFF;
+                text-bbox-border-width: 1;
+            </style>
+        </label>
+        
+        <place text="Place">
+            <position lat="35" long="-110"/>
+            <icon>../data/placemark32.png</icon>
+            <style type="text/css">
+                text-declutter: true;
+                text-halo:      #777;
+            </style>
+        </place>
         
-        <annotations>
+        <circle name="draped circle">
+            <position lat="34.051" long="-117.974"/>
+            <radius value="50" units="km"/>
+            <style type="text/css">
+                fill:               #ffff0080;
+                stroke:             #ffffff;
+                stroke-width:       2px;
+                altitude-clamping:  terrain-drape;
+            </style>
+        </circle>
+        <label text="Draped circle" lat="34.051" long="-117.974"/>
         
-            <label text="Los Angeles">
-                <position lat="34.051" long="-117.974" alt="100" mode="relative"/>
-                <style type="text/css">
-                    text-align:     center_center;
-                    text-size:      20;
-                    text-declutter: true;
-                </style>
-            </label>
-            
-            <place text="San Diego">
-                <position lat="32.73" long="-117.17"/>
-                <icon>http://demo.pelicanmapping.com/icons/gmaps/yoga.png</icon>
-                <style type="text/css">
-                    text-declutter: true;
-                </style>
-            </place>
-            
-            <circle name="draped circle">
-                <position lat="34.051" long="-117.974"/>
-                <radius value="50" units="km"/>
-                <style type="text/css">
-                    fill:               #ffff0080;
-                    altitude-clamping:  terrain;
-                    altitude-technique: drape;
-                </style>
-            </circle>
-            
-            <ellipse name="ellipse relative">
-                <position lat="34.051" long="-116" hat="5000"/>
-                <radius_major value="50" units="km"/>
-                <radius_minor value="40" units="km"/>
-                <style type="text/css">
-                    fill: #ffff0080;
-                </style>
-            </ellipse>
-            
-            <ellipse name="ellipse extruded">
-                <position lat="32.73" long="-119.0"/>
-                <radius_major value="50" units="km"/>
-                <radius_minor value="20" units="km"/>
-                <style type="text/css">
-                    fill:             #ff7f007f;
-                    stroke:           #ff0000ff;
-                    extrusion-height: 5000;
-                </style>
-            </ellipse>
-            
-            <rectangle name="absolute rectangle">
-                <position lat="32.2" long="-118" alt="1000"/>
-                <width value="50" units="nm"/>
-                <height value="25" units="nm"/>
-                <style type="text/css">
-                    stroke:       #00ffff; 
-                    stroke-width: 2; 
-                </style>
-            </rectangle>
+        <circle name="scene-clamped circle">
+            <position lat="22.074" long="-159.606"/>
+            <radius value="1.2" units="km"/>
+            <style type="text/css">
+                stroke:             #ffffff;
+                stroke-width:       2px;
+                altitude-clamping:  terrain-scene;
+                altitude-binding:   vertex;
+            </style>
+        </circle>
+        <label text="scene-clamped circle" lat="22.074" long="-159.606"/>
+        
+        <ellipse name="ellipse relative">
+            <position lat="40" long="-100" hat="5000"/>
+            <radius_major value="50" units="km"/>
+            <radius_minor value="40" units="km"/>
+            <style type="text/css">
+                fill: #ff00ff7f;
+                stroke: #ffffff;
+            </style>
+        </ellipse>
+        <label text="HAT Ellipse" lat="40" long="-100.0"/>
+        
+        <ellipse name="ellipse extruded">
+            <position lat="32" long="-100.0"/>
+            <radius_major value="50" units="km"/>
+            <radius_minor value="20" units="km"/>
+            <style type="text/css">
+                fill:             #ff7f007f;
+                stroke:           #ff0000ff;
+                extrusion-height: 5000;
+            </style>
+        </ellipse>
+        <label text="Extruded Ellipse" lat="32" long="-100.0"/>
 
-            <feature name="extruded line">
-                <srs>wgs84</srs>
-                <geometry>
-                    LINESTRING(-120.37 34.039, -120.09 33.96, -119.75 34, -118.43 33.37, -118.48 32.88)
-                </geometry>
-                <style type="text/css">
-                    fill:                #ff00ff7f;
-                    stroke:              #ffff00;
-                    stroke-width:        3;
-					stroke-crease-angle: 45.0;
-                    extrusion-height:    30000;
-                    render-lighting:     false;
-                </style>
-            </feature>
+        <feature name="Extruded Line">
+            <srs>wgs84</srs>
+            <geometry>
+                LINESTRING(-80.37 34.039, -80.09 33.96, -79.75 34, -79.43 33.37, -79.48 32.88)
+            </geometry>
+            <style type="text/css">
+                fill:                #ff00ff7f;
+                stroke:              #ffff00;
+                stroke-width:        3;
+                stroke-crease-angle: 45.0;
+                extrusion-height:    30000;
+                render-lighting:     true;
+            </style>
+        </feature>
+        <label text="Extruded Line" lat="32" long="-80"/>
 
-            <feature name="gpu clamped line">
-                <srs>wgs84</srs>
-                <geometry>
-                    LINESTRING(-120 37, -120 33, -118 33, -118 32)
-                </geometry>
-                <style type="text/css">
-                    stroke:              #ff3000;
-                    stroke-width:        3;
-                    stroke-tessellation: 100;
-                    altitude-clamping:   terrain;
-                    altitude-technique:  gpu;
-                    render-lighting:     false;
-                </style>
-            </feature>
-            
-            <model name="flag model">
-                <url>../data/red_flag.osg.18000.scale</url>
-                <position lat="33" long="-117.75" hat="0"/>
-            </model>
-            
-            <imageoverlay>
-                <url>../data/fractal.png</url>
-                <alpha>1.0</alpha>
-                <geometry>POLYGON((-81 26, -80.5 26, -80.5 26.5, -81 26.5))</geometry>
-            </imageoverlay>
-            
-            <label text="image overlay">
-                <position lat="26" long="-81" />
-            </label>
-            
-            <local_geometry name="3D geometry">
-                <geometry>
-                    POLYGON((0 0 0, -1000 0 25000, -5000 0 25000, 0 0 30000, 5000 0 25000, 1000 0 25000))
-                </geometry>
-                <position lat="33.4" long="-116.6" hat="0"/>
-                <style type="text/css">
-                    fill:            #00ff00;
-                    stroke:          #ffff00;
-                    render-lighting: false;
-                </style>
-            </local_geometry>
-            
-            <circle name="scene-clamped circle">
-                <position lat="33.4" long="-116.6"/>
-                <radius value="5" units="km"/>
-                <style type="text/css">
-                    fill: #afafff9f;
-                    render-lighting: false;
-                </style>
-            </circle>
+        <feature name="GPU-Clamped Line">
+            <srs>wgs84</srs>
+            <geometry>
+                LINESTRING(-110 47, -110 43, -120 43, -120 42)
+            </geometry>
+            <style type="text/css">
+                stroke:              #ff3000;
+                stroke-width:        3;
+                stroke-tessellation-size: 1km;
+                altitude-clamping:   terrain-gpu;
+            </style>
+        </feature>
+        <label text="GPU-Clamped Line" lat="44" long="-115">
+            <style type="text/css">
+                text-align:             center_center;
+                text-geographic-course: 45.0;
+                text-bbox-fill: #FFFF0033;
+                text-bbox-margin: 8;
+                text-bbox-border: #FFFF00;
+                text-bbox-border-width: 0.5;
+            </style>
+        </label>
+        
+        <feature name="Draped Polygon">
+            <srs>wgs84</srs>
+            <geometry>
+                POLYGON((-100 47, -100 49, -95 48, -96 45 -98 42))
+            </geometry>
+            <style type="text/css">
+                fill:     #ffff007f;
+                stroke:   #ffffff;
+                stroke-width: 2px;
+                altitude-clamping: terrain-drape;
+            </style>
+        </feature>
+        <label text="Draped Polygon" lat="45" long="-98"/>
+        
+        <model name="Auto-Scaled Model">
+            <position lat="43" long="-100"/>
+            <style>
+                model:       "../data/red_flag.osg.45.scale";
+                model-scale: auto;
+            </style>
+        </model>
+        <label text="Auto-Scaled Model" lat="42.5" long="-100"/>
+        
+        <imageoverlay>
+            <url>../data/fractal.png</url>
+            <alpha>1.0</alpha>
+            <geometry>POLYGON((-81 26, -80.5 26, -80.5 26.5, -81 26.5))</geometry>
+        </imageoverlay>            
+        <label text="ImageOverlay" lat="26" long="-81"/>
+        
+        <local_geometry name="3D geometry">
+            <geometry>
+                POLYGON((0 0 0, -25000 0 45000, 0 0 75000, 25000 0 45000))
+            </geometry>
+            <position lat="33.4" long="-116.6"/>
+            <style type="text/css">
+                fill:            #00ff00;
+                stroke:          #ffff00;
+                stroke-width:    2px;
+                render-lighting: false;
+            </style>
+            <horizon_culling>true</horizon_culling>
+        </local_geometry>
+        <label text="3D Geometry" lat="33.4" long="-116.6"/>
 
-            <feature name="Long Line">
-                <srs>wgs84</srs>
-                <geometry>
-                    LINESTRING(0 0, 0 65)
-                </geometry>
-                <style type="text/css">
-                    stroke:              #ffff00;
-                    stroke-width:        3;
-                    stroke-tessellation: 90;
-                    altitude-clamping:   relative;
-					altitude-technique:  scene;
-                    render-lighting:     false;
-                </style>
-            </feature>
-            
-        </annotations>
+        <feature name="Long Line">
+            <srs>wgs84</srs>
+            <geometry>
+                LINESTRING(10 0, 10 65)
+            </geometry>
+            <style type="text/css">
+                stroke:              #ffff00;
+                stroke-width:        3;
+                stroke-tessellation-size: 10km;
+                altitude-clamping:   terrain;
+                altitude-technique:  scene;
+                render-lighting:     false;
+            </style>
+        </feature>
+        
+        <label text="Tessellated line" lat="35" long="10">
+            <style type="text/css">
+                text-align:              center_bottom;
+                text-geographic-course:  0;
+            </style>
+        </label>
         
-    </external>
+    </annotations>
 </map>
diff --git a/tests/arcgisonline.earth b/tests/arcgisonline.earth
index cdd7669..f09da7d 100644
--- a/tests/arcgisonline.earth
+++ b/tests/arcgisonline.earth
@@ -10,7 +10,7 @@ http://resources.esri.com/arcgisonlineservices/index.cfm?fa=content
 <map name="ArcGIS Online" type="geocentric" version="2">
         
     <image name="arcgis-world-imagery" driver="arcgis">
-        <url>http://services.arcgisonline.com/ArcGIS/rest/services/World_Topo_Map/MapServer</url>
+        <url>http://services.arcgisonline.com/arcgis/rest/services/World_Imagery/MapServer/</url>
 		<nodata_image>http://services.arcgisonline.com/ArcGIS/rest/services/World_Topo_Map/MapServer/tile/100/0/0.jpeg</nodata_image>
 		<cache_policy usage="no_cache"/>
     </image>
@@ -29,7 +29,4 @@ http://resources.esri.com/arcgisonlineservices/index.cfm?fa=content
         <lighting>false</lighting>
     </options>
 	
-	<extensions>
-		<lod_blending/>
-	</extensions>
 </map>
diff --git a/tests/billboard.earth b/tests/billboard.earth
deleted file mode 100644
index 0e12037..0000000
--- a/tests/billboard.earth
+++ /dev/null
@@ -1,39 +0,0 @@
-<!--
-osgEarth Sample - Geometry Shader Billboard Experimentation
--->
-<map name="geometry shader test" type="geocentric">
-    
-    <options>
-        <terrain first_lod="1"/>
-    </options>
-    
-    <image name="readymap_imagery" driver="tms">
-        <url>http://readymap.org/readymap/tiles/1.0.0/7/</url>
-    </image>
-        
-    <elevation name="readymap_elevation" driver="tms">
-        <url>http://readymap.org/readymap/tiles/1.0.0/9/</url>
-    </elevation>
-
-    <extensions>
-
-        <billboard>
-
-            <features name="points" driver="ogr">
-                <url>../data/parks.shp</url>
-            </features>
-
-            <image>../data/textures/pine.png</image>
-            <height>20.0</height>
-            <width>15.0</width>
-            <density>15000</density>
-
-        </billboard>
-
-        <viewpoints>
-            <viewpoint name="DC" heading="-23.41597142139858" height="25.89056142792106" lat="38.88766329853004" long="-76.99080836437689" pitch="-24.9647839409773" range="18580.10989103711"/>
-        </viewpoints>
-
-    </extensions>
-
-</map>
diff --git a/tests/boston-gpu.earth b/tests/boston-gpu.earth
index 185de7b..4b38cb9 100644
--- a/tests/boston-gpu.earth
+++ b/tests/boston-gpu.earth
@@ -117,11 +117,11 @@ to extruded buildings.
                     model:             "../data/streetlight.osgb";
                     model-script:      positionAlongSegments();
 					model-heading:     feature.properties.heading;
-                    altitude-clamping: terrain-gpu;                    
+                    altitude-clamping: terrain;                    
                     render-depth-offset:    false;
                 }
             </style>
-            <script language="javascript">
+            <script language="javascript" profile="full">
 				<url>../data/scripts/createLineOffsetPoints.js</url>
 			</script>
         </styles>   
@@ -148,7 +148,7 @@ to extruded buildings.
                    model-placement:        random;
                    model-density:          3000;
 				   model-heading:          Math.random() * 360.0;
-                   altitude-clamping:      terrain-gpu;
+                   altitude-clamping:      terrain;
 				   render-min-alpha:       0.15;
                    render-depth-offset:    false;
                 }
@@ -157,16 +157,13 @@ to extruded buildings.
     </model>
     
     
-    <external>
-        <viewpoints>
-            <viewpoint name="Boston Overview" heading="24.261" height="0" lat="42.34425" long="-71.076262" pitch="-21.6" range="3450"/>
-            <viewpoint name="Boston Downtown 1" heading="117" lat="42.3568" long="-71.0585" height="0" pitch="-20.4" range="1500" />
-            <viewpoint name="Boston Downtown 2" heading="-128.5" lat="42.3582" long="-71.0546" height="0" pitch="-19" range="1620" />
-            <viewpoint name="Boston Street Level" heading="-145.64081" lat="42.364015" long="-71.054149" pitch="-9.701" range="144.95"/>
-        </viewpoints>
-        <sky driver="simple" hours="14.0"/>
-        <vertical_scale/>
-        <normalmap/>
-    </external>
+    <viewpoints>
+        <viewpoint name="Boston Overview" heading="24.261" height="0" lat="42.34425" long="-71.076262" pitch="-21.6" range="3450"/>
+        <viewpoint name="Boston Downtown 1" heading="117" lat="42.3568" long="-71.0585" height="0" pitch="-20.4" range="1500" />
+        <viewpoint name="Boston Downtown 2" heading="-128.5" lat="42.3582" long="-71.0546" height="0" pitch="-19" range="1620" />
+        <viewpoint name="Boston Street Level" heading="-145.64081" lat="42.364015" long="-71.054149" pitch="-9.701" range="144.95"/>
+    </viewpoints>
+
+    <sky driver="simple" hours="14.0"/>
   
 </map>
diff --git a/tests/boston.earth b/tests/boston.earth
index e294d1a..299b6c2 100644
--- a/tests/boston.earth
+++ b/tests/boston.earth
@@ -7,6 +7,10 @@ to extruded buildings.
 
 <map name="Boston Demo" type="geocentric" version="2">
     
+    <options>
+        <terrain driver="mp"/>
+    </options>
+    
     <image name="readymap_imagery" driver="tms">
         <url>http://readymap.org/readymap/tiles/1.0.0/22/</url>
     </image>
@@ -91,6 +95,7 @@ to extruded buildings.
                     stroke-width:                 7.5m;
                     altitude-clamping:            terrain;
                     render-depth-offset-min-bias: 3.6;
+                    render-transparent:           true;
                 }
             </style>
         </styles>        
@@ -120,7 +125,7 @@ to extruded buildings.
                     altitude-clamping: terrain;
                 }
             </style>
-            <script language="javascript">
+            <script language="javascript" profile="full">
 				<url>../data/scripts/createLineOffsetPoints.js</url>
 			</script>
         </styles>   
@@ -148,21 +153,18 @@ to extruded buildings.
                    model-density:          3000;
 				   model-heading:          Math.random() * 360.0;
                    altitude-clamping:      terrain;
+                   render-transparent:     true;
 				   render-min-alpha:       0.15;
                 }
             </style>
         </styles>        
     </model>
     
-    
-    <external>
-        <viewpoints>
-            <viewpoint name="Boston Overview" heading="24.261" height="0" lat="42.34425" long="-71.076262" pitch="-21.6" range="3450"/>
-            <viewpoint name="Boston Downtown 1" heading="117" lat="42.3568" long="-71.0585" height="0" pitch="-20.4" range="1500" />
-            <viewpoint name="Boston Downtown 2" heading="-128.5" lat="42.3582" long="-71.0546" height="0" pitch="-19" range="1620" />
-            <viewpoint name="Boston Street Level" heading="-145.64081" lat="42.364015" long="-71.054149" pitch="-9.701" range="144.95"/>
-        </viewpoints>
-        <sky driver="simple" hours="14.0"/>
-    </external>
+    <viewpoints>
+        <viewpoint name="Boston Overview" heading="24.261" height="0" lat="42.34425" long="-71.076262" pitch="-21.6" range="3450"/>
+        <viewpoint name="Boston Downtown 1" heading="117" lat="42.3568" long="-71.0585" height="0" pitch="-20.4" range="1500" />
+        <viewpoint name="Boston Downtown 2" heading="-128.5" lat="42.3582" long="-71.0546" height="0" pitch="-19" range="1620" />
+        <viewpoint name="Boston Street Level" heading="-145.64081" lat="42.364015" long="-71.054149" pitch="-9.701" range="144.95"/>
+    </viewpoints>
   
 </map>
diff --git a/tests/boston_buildings.earth b/tests/boston_buildings.earth
index d75f1be..8f4c5a2 100644
--- a/tests/boston_buildings.earth
+++ b/tests/boston_buildings.earth
@@ -76,14 +76,13 @@ osgearth_viewer boston_buildings.earth --kml ../data/BostonBuildings.kmz
         <lighting>false</lighting>
     </options> 
     
-    <external>
-        <viewpoints>
-            <viewpoint name="Boston Overview" heading="24.261" height="0" lat="42.34425" long="-71.076262" pitch="-21.6" range="3450"/>
-            <viewpoint name="Boston Downtown 1" heading="117" lat="42.3568" long="-71.0585" height="0" pitch="-20.4" range="1500" />
-            <viewpoint name="Boston Downtown 2" heading="-128.5" lat="42.3582" long="-71.0546" height="0" pitch="-19" range="1620" />
-            <viewpoint name="Boston Street Level" heading="-145.85" lat="42.36460" long="-71.053612" pitch="-10.1" range="85.034"/>\
-        </viewpoints>
-        <sky hours="21.0"/>
-    </external>
+    <viewpoints>
+        <viewpoint name="Boston Overview" heading="24.261" height="0" lat="42.34425" long="-71.076262" pitch="-21.6" range="3450"/>
+        <viewpoint name="Boston Downtown 1" heading="117" lat="42.3568" long="-71.0585" height="0" pitch="-20.4" range="1500" />
+        <viewpoint name="Boston Downtown 2" heading="-128.5" lat="42.3582" long="-71.0546" height="0" pitch="-19" range="1620" />
+        <viewpoint name="Boston Street Level" heading="-145.85" lat="42.36460" long="-71.053612" pitch="-10.1" range="85.034"/>\
+    </viewpoints>
+
+    <sky_simple hours="21.0"/>
   
 </map>
diff --git a/tests/boston_projected.earth b/tests/boston_projected.earth
index 9f52542..14f7f3d 100644
--- a/tests/boston_projected.earth
+++ b/tests/boston_projected.earth
@@ -166,15 +166,11 @@ to extruded buildings.
         </styles>        
     </model>
     
-    
-    <external>
-        <viewpoints>
-            <viewpoint name="Boston Overview" heading="24.261" height="0" lat="42.34425" long="-71.076262" pitch="-21.6" range="3450"/>
-            <viewpoint name="Boston Downtown 1" heading="117" lat="42.3568" long="-71.0585" height="0" pitch="-20.4" range="1500" />
-            <viewpoint name="Boston Downtown 2" heading="-128.5" lat="42.3582" long="-71.0546" height="0" pitch="-19" range="1620" />
-            <viewpoint name="Boston Street Level" heading="-145.64081" lat="42.364015" long="-71.054149" pitch="-9.701" range="144.95"/>
-        </viewpoints>
-        <sky driver="gl" hours="14.0"/>
-    </external>
+    <viewpoints>
+        <viewpoint name="Boston Overview" heading="24.261" height="0" lat="42.34425" long="-71.076262" pitch="-21.6" range="3450"/>
+        <viewpoint name="Boston Downtown 1" heading="117" lat="42.3568" long="-71.0585" height="0" pitch="-20.4" range="1500" />
+        <viewpoint name="Boston Downtown 2" heading="-128.5" lat="42.3582" long="-71.0546" height="0" pitch="-19" range="1620" />
+        <viewpoint name="Boston Street Level" heading="-145.64081" lat="42.364015" long="-71.054149" pitch="-9.701" range="144.95"/>
+    </viewpoints>
   
 </map>
diff --git a/tests/boston_viewpoints.xml b/tests/boston_viewpoints.xml
new file mode 100644
index 0000000..9fd062e
--- /dev/null
+++ b/tests/boston_viewpoints.xml
@@ -0,0 +1,4 @@
+<viewpoint name="Boston Overview" heading="24.261" height="0" lat="42.34425" long="-71.076262" pitch="-21.6" range="3450"/>
+<viewpoint name="Boston Downtown 1" heading="117" lat="42.3568" long="-71.0585" height="0" pitch="-20.4" range="1500" />
+<viewpoint name="Boston Downtown 2" heading="-128.5" lat="42.3582" long="-71.0546" height="0" pitch="-19" range="1620" />
+<viewpoint name="Boston Street Level" heading="-145.64081" lat="42.364015" long="-71.054149" pitch="-9.701" range="144.95"/>
diff --git a/tests/bumpmap.earth b/tests/bumpmap.earth
new file mode 100644
index 0000000..5857575
--- /dev/null
+++ b/tests/bumpmap.earth
@@ -0,0 +1,27 @@
+<!--
+osgEarth Sample - Shows an elevation-derived normal map.
+-->
+<map name="readymap.org" type="geocentric">    
+
+    <options>
+        <terrain normal_maps="true"/>
+    </options>
+    
+    <image name="readymap_imagery" driver="tms">
+        <url>http://readymap.org/readymap/tiles/1.0.0/7/</url>
+    </image>
+        
+    <elevation name="readymap_elevation" driver="tms">
+        <url>http://readymap.org/readymap/tiles/1.0.0/116/</url>
+    </elevation>
+    
+    <sky driver="gl"/>
+    
+    <bumpmap>
+        <image>../data/rock_hard.jpg</image>
+        <octaves>8</octaves>
+        <intensity>2.5</intensity>
+    </bumpmap>
+    
+    <xi:include href="viewpoints.xml"/>
+</map>
diff --git a/tests/clouds.earth b/tests/clouds.earth
new file mode 100644
index 0000000..0c772ad
--- /dev/null
+++ b/tests/clouds.earth
@@ -0,0 +1,39 @@
+<map>
+    <options>
+        <profile
+            srs="+proj=longlat +a=6441918.37 +b=6420319.837342"
+            xmin="-180" xmax="180" ymin="-90" ymax="90">
+        </profile>
+        <terrain driver="rex" color="#ffffff00" bin_number="2" skirt_ratio="0" tile_size="7"/>
+    </options>
+        
+    <image name="Clouds" driver="osg" url="../data/cloud_combined_2048.jpg">
+        <profile>global-geodetic</profile>
+        <cache_policy usage="none"/>
+        
+        <color_filters>
+            <glsl>
+                color.a = color.r;
+            </glsl>
+        </color_filters>  
+        
+        <!-- concept: not yet implemented -->
+        <shader name="cloudAlpha"/>
+    </image>
+    
+    <!-- concept: not yet implemented -->
+    <shaders>
+        <shader name="cloudAlpha">
+            <code>
+              <![CDATA[
+                #pragma vp_location   fragment_coloring
+                #pragma vp_entryPoint cloudAlpha
+                
+                void cloudAlpha(inout vec4 color) {
+                    color.a = color.r;
+                }
+              ]]>
+            </code>
+        </shader>
+    </shaders>
+</map>
\ No newline at end of file
diff --git a/tests/colorramp.earth b/tests/colorramp.earth
index 0b14519..e39d111 100644
--- a/tests/colorramp.earth
+++ b/tests/colorramp.earth
@@ -7,13 +7,13 @@ Demonstrates how to apply a color ramp to an elevation ( or any other type of si
 
     <!-- Elevation as a true elevation source -->       
     <elevation name="readymap_elevation" driver="tms">
-        <url>http://readymap.org/readymap/tiles/1.0.0/9/</url>
+        <url>http://readymap.org/readymap/tiles/1.0.0/116/</url>
     </elevation>
 
     <!--Displays the same elevation using an elevaton contour-->
     <image name="color ramp" driver="colorramp">
     	<elevation name="readymap_elevation" driver="tms">
-            <url>http://readymap.org/readymap/tiles/1.0.0/9/</url>
+            <url>http://readymap.org/readymap/tiles/1.0.0/116/</url>
         </elevation>
         <ramp>..\data\colorramps\elevation.clr</ramp>
     </image>
diff --git a/tests/contourmap.earth b/tests/contourmap.earth
new file mode 100644
index 0000000..f6b70d9
--- /dev/null
+++ b/tests/contourmap.earth
@@ -0,0 +1,16 @@
+<!--
+ | osgEarth Sample - Render elevation data as a contour map
+ |-->
+ 
+<map>
+
+    <options>
+        <terrain driver="rex"/>
+    </options>
+
+    <elevation name="ReadyMap.org - Elevation" driver="tms">
+        <url>http://readymap.org/readymap/tiles/1.0.0/116/</url>
+    </elevation>
+
+    <contour_map/>
+</map>
diff --git a/tests/dc_viewpoints.xml b/tests/dc_viewpoints.xml
new file mode 100644
index 0000000..42bf978
--- /dev/null
+++ b/tests/dc_viewpoints.xml
@@ -0,0 +1,2 @@
+<viewpoint name="DC overview" heading="0" height="25.83" lat="38.9015" long="-77.0217" pitch="-89.9" range="28262"/>
+<viewpoint name="DC close up" heading="-13.48" lat="38.911" long="-77.051" pitch="-10.1" range="2711"/>
diff --git a/tests/detail_texture.earth b/tests/detail_texture.earth
new file mode 100644
index 0000000..2826653
--- /dev/null
+++ b/tests/detail_texture.earth
@@ -0,0 +1,20 @@
+<!--
+  osgEarth Sample - Detail Texturing
+
+  Run:
+
+  osgearth_viewer detail_texture.earth --uniform oe_detail_lod 0 24 --uniform oe_detail_alpha 0.0 1.0 --uniform oe_detail_maxRange 500.0 10000.0 --uniform oe_detail_attenDist 0.0 5000.0
+-->
+
+<map name="detail texturing" type="geocentric">
+        
+    <image name="readymap_imagery" driver="tms">
+        <url>http://readymap.org/readymap/tiles/1.0.0/7/</url>
+    </image>
+        
+    <elevation name="readymap_elevation" driver="tms">
+        <url>http://readymap.org/readymap/tiles/1.0.0/116/</url>
+    </elevation>
+    
+    <detail image="../data/noise3.png" lod="21" alpha="0.5" max_range="6000" attenuation="2000"/>        
+</map>
diff --git a/tests/errors.earth b/tests/errors.earth
new file mode 100644
index 0000000..e9ebff5
--- /dev/null
+++ b/tests/errors.earth
@@ -0,0 +1,32 @@
+<!-- 
+osgEarth Test - Earth File Error Reporting
+-->
+
+<map>
+
+    <image name="Bad Image Driver Test" driver="none" >
+        <url>missing_file.tif</url>
+    </image>
+    
+    <image name="Missing URL Test" driver="gdal" >
+        <url>missing_file.tif</url>
+    </image>
+    
+    <model name="Bad Model Driver Test" driver="none" >
+        <features name="world" driver="ogr">
+            <url>../data/usa.shp</url>
+        </features>
+    </model>
+    
+    <model name="Missing Feature Test" driver="feature_geom" >
+        <features name="world" driver="ogr">
+            <url>missing.shp</url>
+        </features>
+    </model>
+
+    <mask name="Bad Features Test" driver="feature">   
+        <features driver="ogr">
+        </features>
+    </mask>
+    
+</map>
\ No newline at end of file
diff --git a/tests/fade_elevation.earth b/tests/fade_elevation.earth
new file mode 100644
index 0000000..cf95402
--- /dev/null
+++ b/tests/fade_elevation.earth
@@ -0,0 +1,59 @@
+<!--
+osgEarth Sample - Fading out terrain based on the elevation.
+
+Run:
+
+  osgearth_viewer fade_elevation.earth --uniform min_elevation 0 100 --uniform fade_distance 1 1000
+
+-->
+
+<map name="readymap.org" type="geocentric">
+
+    <image name="readymap_imagery" driver="tms">
+        <url>http://readymap.org/readymap/tiles/1.0.0/22/</url>
+    </image>
+
+    <elevation name="readymap_elevation" driver="tms">
+        <url>http://readymap.org/readymap/tiles/1.0.0/116/</url>
+    </elevation>    
+
+
+    <terrainshader>
+        <code><![CDATA[
+        
+            #version 330 compatibility
+            #pragma vp_entryPoint "fadeTerrain"
+            #pragma vp_location   vertex_view
+
+            attribute vec4 oe_terrain_attr;
+
+            out float elevation;
+            
+            void fadeTerrain(inout vec4 VertexVIEW)
+            {
+                elevation = oe_terrain_attr.w;
+            }
+            
+        ]]></code>
+    </terrainshader>
+
+    <terrainshader>
+        <code><![CDATA[
+        
+            #version 330 compatibility
+            #pragma vp_entryPoint "fade"
+            #pragma vp_location   "fragment_coloring"
+
+            in float elevation;
+            uniform float min_elevation;
+            uniform float fade_distance;
+            
+            void fade(inout vec4 color)
+            {
+                color.a = 1.0 - clamp((min_elevation - elevation)/fade_distance, 0.0, 1.0);
+            }
+            
+        ]]></code>
+    </terrainshader>
+
+</map>
diff --git a/tests/feature_clip_plane.earth b/tests/feature_clip_plane.earth
index 7add5a7..87bcb0d 100644
--- a/tests/feature_clip_plane.earth
+++ b/tests/feature_clip_plane.earth
@@ -23,6 +23,7 @@ way to mitigate z-fighting issues.
                    stroke:            #ffff00;
 				   render-depth-test: false;
 				   render-clip-plane: 0;
+                   render-order:      1;
                 }                    
             </style>
         </styles>        
diff --git a/tests/feature_country_boundaries.earth b/tests/feature_country_boundaries.earth
new file mode 100644
index 0000000..a403b72
--- /dev/null
+++ b/tests/feature_country_boundaries.earth
@@ -0,0 +1,42 @@
+<!--
+osgEarth Sample
+-->
+
+<map name="Wordwide Line Vectors" type="geocentric">
+  
+    <options>
+        <lighting>false</lighting>
+        <terrain min_lod="16"/>
+    </options>
+
+    <image name="world" driver="gdal">
+        <url>../data/world.tif</url>
+        <cache_policy usage="no_cache"/>
+    </image>
+    
+    <model name="world_boundaries" driver="feature_geom">
+            
+        <features name="world" driver="ogr">
+            <url>../data/world.shp</url>
+            <build_spatial_index>true</build_spatial_index>
+            <convert type="line"/>
+        </features>
+        
+        <layout tile_size="500000" crop_features="true">
+            <level max_range="1e10"/>
+        </layout>
+                
+        <styles>
+            <style type="text/css">
+                world {
+                   stroke:                       #ffff00;
+                   stroke-width:                 2px;
+                   stroke-tessellation-size:     100km;
+                   render-depth-offset-min-bias: 1000;
+                }            
+            </style>
+        </styles>
+        
+    </model>
+  
+</map>
diff --git a/tests/feature_custom_filters.earth b/tests/feature_custom_filters.earth
index ce19220..348e26f 100644
--- a/tests/feature_custom_filters.earth
+++ b/tests/feature_custom_filters.earth
@@ -19,7 +19,9 @@ Shows how you can use a custom FeatureFilter, even one that is defined in an Ear
             <url>../data/world.shp</url>
 			
 			<!--Define a ChangeAttributeFilter, which is defined in the osgearth_featurefilter example.  This will change the cntry_name of all countries to osgEarthLand.-->
-			<change_attribute key="cntry_name" value="osgEarthLand"/>
+            <filters>
+                <change_attribute key="cntry_name" value="osgEarthLand"/>
+            </filters>
         </features>
 
         <styles>
diff --git a/tests/feature_draped_polygons.earth b/tests/feature_draped_polygons.earth
index df1ecc6..6937f2a 100644
--- a/tests/feature_draped_polygons.earth
+++ b/tests/feature_draped_polygons.earth
@@ -13,7 +13,7 @@ the feature data.
     <options>
         <lighting>false</lighting>
         <overlay_blending>false</overlay_blending>
-		<terrain min_lod="8"/>
+        <terrain min_lod="8"/>
     </options>
 
     <image name="world" driver="gdal">
@@ -24,32 +24,38 @@ the feature data.
                           
         <features name="states" driver="ogr">
             <url>../data/world.shp</url>
-            <buffer distance="-0.05"/>
-			<resample max_length="5.0"/>
+            <filters>
+                <resample max_length="5.0"/>
+                <buffer distance="-0.05"/>
+            </filters>
         </features>
         
         <styles>        
             <style type="text/css">
                 p1 {
-                   fill:               #ffff8066;
-				   render-depth-test:  false;
-				   altitude-clamping:  terrain-drape;
+                   fill:               #ffff807f;
+                   render-depth-test:  false;
+                   altitude-clamping:  terrain-drape;
                 }       
                 p2 {
-                   fill:               #80ffff66;
-				   render-depth-test:  false;
+                   fill:               #80ffff7f;
+                   render-depth-test:  false;
+                   altitude-clamping:  terrain-drape;
                 }   
                 p3 {
-                   fill:               #ff80ff66;
-				   render-depth-test:  false;
+                   fill:               #ff80ff7f;
+                   render-depth-test:  false;
+                   altitude-clamping:  terrain-drape;
                 }       
                 p4 {
-                   fill:               #ff808066;
-				   render-depth-test:  false;
+                   fill:               #ff80807f;
+                   render-depth-test:  false;
+                   altitude-clamping:  terrain-drape;
                 }     
                 p5 {
-                   fill:               #80ff8066;
-				   render-depth-test:  false;
+                   fill:               #80ff807f;
+                   render-depth-test:  false;
+                   altitude-clamping:  terrain-drape;
                 }                                      
             </style>
         
diff --git a/tests/feature_elevation.earth b/tests/feature_elevation.earth
new file mode 100644
index 0000000..def5bb4
--- /dev/null
+++ b/tests/feature_elevation.earth
@@ -0,0 +1,49 @@
+<!--
+osgEarth Sample - Feature to elevation driver.
+-->
+
+<map name="Feature Elevation Demo" type="geocentric" version="2">
+        
+    <image name="readymap_imagery" driver="tms">
+        <url>http://readymap.org/readymap/tiles/1.0.0/7/</url>
+    </image>
+
+    <!-- Add some base elevation -->
+    <elevation name="readymap_elevation" driver="tms" enabled="true">
+        <url>http://readymap.org/readymap/tiles/1.0.0/116/</url>
+    </elevation>
+
+    <!--
+        Add a shapefile to flatten the underlying elevation.
+    -->
+
+    <elevation name="flatten" driver="feature_elevation" enabled="true" attr="ELEVATION">
+        <!-- Specify a min_level so that we don't waste resources generating heightfields when they won't actually be visible -->
+        <min_level>7</min_level>
+        <!--
+        Because a feature dataset has theoretically infinite pixels resolutions, we specify a max level to keep a cap on how far down it generates data.  This is also critical for any code that uses terrain clamping so that it won't try to generate unnecessarily high
+        resolution heightfields
+        -->
+        <max_level>17</max_level>
+        <!-- Specify a profile that matches the map's profile so no unnecssary reprojection and mosaicing occurs -->
+        <profile>global-geodetic</profile>
+        <features name="flatten" driver="ogr">
+            <url>../data/flatten_mt_rainier.shp</url>
+             <build_spatial_index>true</build_spatial_index>
+        </features>
+    </elevation>
+    
+    <viewpoints>
+        <viewpoint>
+            <name>Mt Rainier</name>
+            <heading>-21.7843</heading>
+            <pitch>-27.566</pitch>
+            <range>38701.6m</range>
+            <long>-121.7706234748925</long>
+            <lat>46.84187674081022</lat>
+            <height>-0.002506599761545658</height>
+            
+        </viewpoint>
+    </viewpoints>
+
+</map>
diff --git a/tests/feature_extrude.earth b/tests/feature_extrude.earth
index c7b72f9..2886f20 100644
--- a/tests/feature_extrude.earth
+++ b/tests/feature_extrude.earth
@@ -19,36 +19,25 @@ Footprint Extrusion using the "feature_geom" driver.
             <url>../data/dcbuildings.shp</url>
             <build_spatial_index>true</build_spatial_index>
         </features>
-        
-        <!-- The stylesheet will describe how to render the feature data. -->
              
         <styles>
             <style type="text/css">
                 buildings {
-                    fill:                    #ff7f2f;
-                    extrusion-height:        15;
-                    extrusion-flatten:       true;
-                    extrusion-wall-gradient: 0.7;
-                    altitude-clamping:       terrain;
-                    altitude-resolution:     0.001;
+                    fill:              #ff7f2f;
+                    extrusion-height:  15;
+                    extrusion-flatten: true;
+                    altitude-clamping: terrain;
                 }            
             </style>
-        </styles>   
-
-        <lighting>true</lighting>
+        </styles>
     </model>
-	
-    <image name="mapquest_osm" driver="xyz" max_level="14">
-        <url>http://otile[1234].mqcdn.com/tiles/1.0.0/osm/{z}/{x}/{y}.jpg</url>
-        <profile>global-mercator</profile>
-    </image>
     
-    <image name="ReadyMap.org - Imagery" driver="tms" enabled="false">
+    <image name="ReadyMap.org - Imagery" driver="tms">
         <url>http://readymap.org/readymap/tiles/1.0.0/7/</url>
     </image>
     
     <elevation name="ReadyMap.org - Elevation" driver="tms">
-        <url>http://readymap.org/readymap/tiles/1.0.0/9/</url>
+        <url>http://readymap.org/readymap/tiles/1.0.0/116/</url>
     </elevation>
 	
 	<options>
@@ -59,7 +48,7 @@ Footprint Extrusion using the "feature_geom" driver.
 		<viewpoints>
 			<viewpoint name="Zoom to Buildings" heading="12.4" lat="38.8982" long="-77.0365" height="20.67" pitch="-51.4" range="4500" />
 		</viewpoints>
-        <sky driver="gl" hours="21.0"/>
+        <sky driver="gl" hours="20.0"/>
     </external>
   
 </map>
diff --git a/tests/feature_labels.earth b/tests/feature_labels.earth
index 38e2655..b52a10f 100644
--- a/tests/feature_labels.earth
+++ b/tests/feature_labels.earth
@@ -4,8 +4,8 @@ This shows how to label point features with an attribute.
 -->
 
 <map name="Feature Geometry Demo" type="geocentric" version="2">
-        
-    <image name="world" driver="gdal">
+            
+    <image driver="gdal">
         <url>../data/world.tif</url>
     </image>
     
@@ -13,6 +13,7 @@ This shows how to label point features with an attribute.
 
         <features name="cities" driver="ogr">
             <url>../data/ne_cities.shp</url>
+            <profile>spherical-mercator</profile>
         </features>
         
         <feature_indexing enabled="true"/>
@@ -23,33 +24,31 @@ This shows how to label point features with an attribute.
             </selector>
             <style type="text/css">              
                 cities {
-                    icon: "../data/placemark32.png";
+                    icon:           "../data/downarrow.png";
                     icon-placement: centroid;
-                    icon-scale: 1.0;
-                    icon-occlusion-cull: false;
-                    icon-occlusion-cull-altitude: 8000;
                     icon-declutter: true;
-                    text-content: [name];
-                    text-priority: [rank_max];
-                    altitude-offset: 100;
-                    altitude-clamping: terrain;
-                    altitude-technique: scene;
+                    icon-align:     center-bottom;
+                    text-content:   [name];
+                    text-priority:  [rank_max];
+                    text-align:     center-bottom;
+                    text-halo:      #3f3f3f;
+                    text-size:      12+3*([rank_max]-9);
                 }     
             </style>
         </styles>
-        
     </model>
     
     <options lighting="false"/>
     
     <external>
-        <decluttering>
+        <screen_space_layout>
             <out_animation_time>  0.0  </out_animation_time>
             <in_animation_time>   0.25 </in_animation_time>
             <min_animation_scale> 0.45 </min_animation_scale>
-            <min_animation_alpha> 0.35 </min_animation_alpha>
+            <min_animation_alpha> 0.0  </min_animation_alpha>
             <sort_by_priority>    true </sort_by_priority>
-        </decluttering>
+            <snap_to_pixel>       true </snap_to_pixel>
+        </screen_space_layout>
     </external>
   
 </map>
diff --git a/tests/feature_labels_script.earth b/tests/feature_labels_script.earth
index 6a403e5..4ab49b2 100644
--- a/tests/feature_labels_script.earth
+++ b/tests/feature_labels_script.earth
@@ -16,7 +16,7 @@ This shows how to label point features with an attribute (with some extra zing).
         </features>
 
         <styles>
-		    <script>
+		    <script profile="full">
 			    function addSomeExcitement() {
 				    feature.properties.name = '***' + feature.properties.cntry_name + '!!!';
 					feature.save();
diff --git a/tests/feature_model_scatter.earth b/tests/feature_model_scatter.earth
index 274b674..e3adac6 100644
--- a/tests/feature_model_scatter.earth
+++ b/tests/feature_model_scatter.earth
@@ -32,13 +32,18 @@ is randomized, but it is randomized exactly the same way each time.
              
         <layout>
             <crop_features>true</crop_features>
-            <level max_range="7000" style="parks-1"/>
-            <level max_range="3000" style="parks-2"/>
-            <level max_range="1000" style="parks-3"/>
+            <level max_range="25000" style="park-polygons"/>
+            <level max_range="7000"  style="parks-1"/>
+            <level max_range="3000"  style="parks-2"/>
+            <level max_range="1000"  style="parks-3"/>
         </layout>
              
         <styles>
             <style type="text/css">
+                park-polygons {
+                   fill:                #00ff007f;
+                   altitude-clamping:   terrain-drape;
+                }                
                 parks-1 {
                    model:               "../data/tree.ive";
                    model-placement:     random;
@@ -69,39 +74,17 @@ is randomized, but it is randomized exactly the same way each time.
         </styles>        
     </model>
     
-    
-    <model name="parks" driver="feature_geom" enabled="true">
-        <features name="parks" driver="ogr">
-            <url>../data/parks.shp</url>
-            <build_spatial_index>false</build_spatial_index>
-        </features>
-        <styles>
-            <style type="text/css">      
-                default {
-                   fill:                #00ff007f;
-                   altitude-clamping:   terrain-drape;
-                }                
-            </style>
-        </styles>
-    </model>
-    
-    
-    <image name="mapquest_open_aerial" driver="xyz">
-        <url>http://oatile[1234].mqcdn.com/tiles/1.0.0/sat/{z}/{x}/{y}.jpg</url>
-        <profile>spherical-mercator</profile>
-        <cache_policy usage="no_cache"/>
-        <nodata_image>http://oatile3.mqcdn.com/tiles/1.0.0/sat/13/636/6210.jpg</nodata_image>
+    <image name="ReadyMap.org - Imagery" driver="tms">
+        <url>http://readymap.org/readymap/tiles/1.0.0/7/</url>
     </image>
     
     <elevation name="ReadyMap.org - Elevation" driver="tms">
-        <url>http://readymap.org/readymap/tiles/1.0.0/9/</url>
+        <url>http://readymap.org/readymap/tiles/1.0.0/116/</url>
     </elevation>
     
-    <external>
-        <viewpoints>
-            <viewpoint name="DC overview" heading="0" height="25.83" lat="38.9015" long="-77.0217" pitch="-89.9" range="28262"/>
-            <viewpoint name="DC close up" heading="-13.48" lat="38.911" long="-77.051" pitch="-10.1" range="2711"/>
-        </viewpoints>
-    </external>
+    <viewpoints>
+        <viewpoint name="DC overview" heading="0" height="25.83" lat="38.9015" long="-77.0217" pitch="-89.9" range="28262"/>
+        <viewpoint name="DC close up" heading="-13.48" lat="38.911" long="-77.051" pitch="-10.1" range="2711"/>
+    </viewpoints>
   
 </map>
diff --git a/tests/feature_offset_polygons.earth b/tests/feature_offset_polygons.earth
index 4597ece..e6ee16e 100644
--- a/tests/feature_offset_polygons.earth
+++ b/tests/feature_offset_polygons.earth
@@ -12,38 +12,32 @@ GLSL to affect a polygon offset effect.
         <terrain min_lod="8"/>
     </options>
     
-    <extensions>
-        <terrainshader>
-            <description>
-                A GLSL snippet that pushes the terrain back to prevent high-altitude z fighting.
-            </description>          
-            <code>
-                <![CDATA[
-                    #version 110
-                    #pragma vp_entryPoint "dp_vert"        // name of entry point function
-                    #pragma vp_location   "vertex_view"    // where to insert this shader in the pipeline
+    <terrainshader>
+        <description>
+            A GLSL snippet that pushes the terrain back to prevent high-altitude z fighting.
+        </description>          
+        <code>
+            <![CDATA[
+                #version 110
+                #pragma vp_entryPoint dp_vert
+                #pragma vp_location   vertex_view
+                
+                void dp_vert(inout vec4 v)
+                {
+                    const float R    = 6371000.0;      // Approximate radius of the earth
+                    const float dmin = 100000.0;       // Minimum vertex distance at which to apply effect
+                    const float dmax = R;              // Vertex distance at which to apply maximum effect
+                    const float maxOffset = 250000.0;  // Maximum offset (applied at dmax)
                     
-                    varying out float tt;
-                    
-                    void dp_vert(inout vec4 v)
-                    {
-                        const float R    = 6371000.0;      // Approximate radius of the earth
-                        const float dmin = 100000.0;       // Minimum vertex distance at which to apply effect
-                        const float dmax = R;              // Vertex distance at which to apply maximum effect
-                        const float maxOffset = 250000.0;  // Maximum offset (applied at dmax)
-                        
-                        float d = length(v.xyz);
-                        float t = clamp( (d-dmin)/(dmax-dmin), 0.0, 1.0 );
-                        float offset = t*maxOffset;
-                        vec3 n = normalize(v.xyz);
-                        v.xyz = v.xyz + n*offset;
-                        
-                        tt = t;
-                    }
-                ]]>
-            </code>         
-        </terrainshader>
-    </extensions>
+                    float d = length(v.xyz);
+                    float t = clamp( (d-dmin)/(dmax-dmin), 0.0, 1.0 );
+                    float offset = t*maxOffset;
+                    vec3 n = normalize(v.xyz);
+                    v.xyz = v.xyz + n*offset;
+                }
+            ]]>
+        </code>         
+    </terrainshader>
 
     <image name="world" driver="gdal">
         <url>../data/world.tif</url>
@@ -53,8 +47,10 @@ GLSL to affect a polygon offset effect.
                           
         <features name="states" driver="ogr">
             <url>../data/world.shp</url>
-            <buffer distance="-0.05"/>
-            <resample max_length="5.0"/>
+            <filters>
+                <resample max_length="5.0"/>
+                <buffer distance="-0.05"/>
+            </filters>
         </features>
         
         <styles>        
diff --git a/tests/feature_poles.earth b/tests/feature_poles.earth
new file mode 100644
index 0000000..161e4b6
--- /dev/null
+++ b/tests/feature_poles.earth
@@ -0,0 +1,64 @@
+<!--
+osgEarth Sample
+
+This tests the rendering of features close to the poles.
+
+-->
+
+<map name="Feature Pole Tesselation Test" type="geocentric" version="2">
+
+    <options>
+        <lighting>false</lighting>
+    </options>
+    
+    <image name="world" driver="gdal">
+        <url>../data/world.tif</url>
+    </image>
+
+
+    <model name="polygon" driver="feature_geom">
+        <features driver="ogr">
+            <geometry>
+                POLYGON((191.026667 87.63333,114.75 78,89.5 77.333336,81.833336 75.333336,70.683334 74.5,70.916664 73.666664,68.666664 73.666664,66.291664 71.505,57.65 71.166664,58 73.9,48.616665 73,49.198334 71.43,49.5 70.5,43.266666 68.666664,32.083332 71.5,32.083332 74,35 74,35 81,32 81,32 90,191.026667 87.63333))
+            </geometry>
+        </features>
+
+        <geo_interpolation>rhumb_line</geo_interpolation>
+
+
+        <styles>
+            <style type="text/css">
+                default {
+                   fill: #ff00ff6f;
+                   stroke: #ffffff;  
+                   altitude-clamping: terrain-drape;
+                }                    
+            </style>
+        </styles>
+        
+    </model>
+
+       <model name="polygon" driver="feature_geom">
+        <features driver="ogr">
+            <geometry>
+                POLYGON((191.026667 -87.63333,114.75 -78,89.5 -77.333336,81.833336 -75.333336,70.683334 -74.5,70.916664 -73.666664,68.666664 -73.666664,66.291664 -71.505,57.65 -71.166664,58 -73.9,48.616665 -73,49.198334 -71.43,49.5 -70.5,43.266666 -68.666664,32.083332 -71.5,32.083332 -74,35 -74,35 -81,32 -81,32 -90,191.026667 -87.63333))
+            </geometry>
+        </features>
+
+        <geo_interpolation>rhumb_line</geo_interpolation>
+
+        <styles>
+            <style type="text/css">
+                default {
+                   fill: #ff00ff6f;
+                   stroke: #ffffff;
+                   altitude-clamping: terrain-drape;
+                }                    
+            </style>
+        </styles>
+        
+    </model>
+
+    
+  
+</map>
diff --git a/tests/feature_population_cylinders.earth b/tests/feature_population_cylinders.earth
index c52f406..b942ad9 100644
--- a/tests/feature_population_cylinders.earth
+++ b/tests/feature_population_cylinders.earth
@@ -16,7 +16,7 @@ Shows how to use JavaScript to create geometry parametrically.
         </features>
 
         <styles>
-            <script>
+            <script profile="full">
               <![CDATA[
                 var min_rank = 12;
                 function makePopCircles() {
diff --git a/tests/feature_raster.earth b/tests/feature_raster.earth
new file mode 100644
index 0000000..e9ed897
--- /dev/null
+++ b/tests/feature_raster.earth
@@ -0,0 +1,119 @@
+<!--
+osgEarth Sample - Raster to feature example.
+-->
+
+<map name="readymap.org" type="geocentric">
+    
+    <options>        
+        <terrain skirt_ratio="0.01" />
+    </options>
+  
+    <elevation name="readymap_elevation" driver="tms">
+        <url>http://readymap.org/readymap/tiles/1.0.0/116/</url>
+    </elevation>
+
+    
+    <image name="CLASSMAP" driver="landuse" shared="true" visible="false" coverage="true" max_data_level="15">
+        <base_lod>12</base_lod>
+        <tile_size>256</tile_size>
+        <cache_policy usage="none"/>
+        <images>
+            <image name="ESA" driver="gdal" coverage="true">
+                <url>H:/data/esa/GLOBCOVER_L4_200901_200912_V2.3_Ant_tiled.tif</url>
+                <warp>0.01</warp>
+            </image>
+        </images>
+        <shared_sampler> landUseTex       </shared_sampler>
+        <shared_matrix>  landUseTexMatrix </shared_matrix>
+    </image>
+  
+    <model name="trees" driver="feature_geom" enabled="true">
+
+        <features name="trees" driver="raster">
+            <layer>CLASSMAP</layer>
+            <level>12</level>
+        </features>
+
+         <instancing>true</instancing>
+
+       <styles>                
+            <style type="text/css">
+                forest {
+                   model:               "../data/tree.ive";
+                   model-placement:     random;
+                   model-density:       1000;
+                   model-scale:         2.0;
+                   altitude-clamping:   terrain;
+                                                            
+                }  
+
+                yellow {
+                   stroke:             #ffff00;
+                   stroke-width:       5px;
+                  
+                }
+
+                red {
+                   stroke:             #ff0000;
+                   stroke-width:       5px;
+                  
+                }  
+
+            </style>
+            
+            <selector name="default" style_expr="selectStyle()"/>
+            
+            <script language="javascript">
+              <![CDATA[
+                rotator = 0;
+                function selectStyle() {
+                    var value = parseFloat(feature.properties.value);
+                    if (value >= 40.0 && value <= 100.0) return "forest";
+                    return null;                    
+                }
+              ]]>
+            </script>
+        </styles>  
+
+    </model>
+
+    <extensions> 
+      
+         <splat>        
+            <coverage>
+                <layer> CLASSMAP </layer>
+                <legend>../data/splat/GLOBCOVER_legend.xml</legend>
+            </coverage>
+            
+            <zones>
+                <zone name="default" doc="Default Climate Zone">            
+                    <surface>
+                        <catalog>../data/splat/splat_catalog.xml</catalog>
+                    </surface>
+                </zone>                
+            </zones>
+            
+        </splat>
+
+        <viewpoints>            
+            <viewpoint name="Trees 1">
+              <heading>-66.2945</heading>
+              <pitch>-14.0905</pitch>
+              <range>3408.89m</range>
+              <long>-121.7544800272052</long>
+              <lat>46.7792209225515</lat>
+              <height>1445.844014885835</height>
+            </viewpoint>
+            
+            <viewpoint name="Trees 2">              
+              <heading>12.2384</heading>
+              <pitch>-4.26323</pitch>
+              <range>1421.77m</range>
+              <long>-121.8282019325911</long>
+              <lat>46.65132101133439</lat>
+              <height>1128.989560711198</height>
+            </viewpoint>
+        </viewpoints>
+               
+    </extensions>
+</map>
diff --git a/tests/feature_rasterize.earth b/tests/feature_rasterize.earth
index 0f9a87b..90d23d4 100644
--- a/tests/feature_rasterize.earth
+++ b/tests/feature_rasterize.earth
@@ -5,11 +5,6 @@ Demonstrates use of the "agglite" feature rasterization driver.
 
 <map name="Geometry Rasterizer Demo" type="round" version="2">
 
-    <options lighting="false">
-        <terrain first_lod="1">
-        </terrain>
-    </options>
-
     <external>
         <lod_blending/>
     </external>
diff --git a/tests/feature_rasterize_2.earth b/tests/feature_rasterize_2.earth
index 84eab4d..2c9f23f 100644
--- a/tests/feature_rasterize_2.earth
+++ b/tests/feature_rasterize_2.earth
@@ -6,16 +6,9 @@ rasterizing it into image tiles.
 -->
 
 <map name="Rasterization Example" type="geocentric" version="2">
-  
-    <options>
-        <lighting>false</lighting>
-    </options>
-    
-    <image name="mapquest_open_aerial" driver="xyz">
-        <url>http://oatile[1234].mqcdn.com/tiles/1.0.0/sat/{z}/{x}/{y}.jpg</url>
-        <profile>spherical-mercator</profile>
-        <cache_policy usage="no_cache"/>
-        <nodata_image>http://oatile3.mqcdn.com/tiles/1.0.0/sat/13/636/6210.jpg</nodata_image>
+      
+    <image name="readymap_imagery" driver="tms">
+        <url>http://readymap.org/readymap/tiles/1.0.0/7/</url>
     </image>
     
     <image name="states" driver="agglite">
@@ -32,7 +25,7 @@ rasterizing it into image tiles.
             <style type="text/css">
                 default {
                     stroke:       #ffff00;
-					stroke-width: .2km;
+					stroke-width: .5km;
                 }            
             </style>              
         </styles>
@@ -53,15 +46,11 @@ rasterizing it into image tiles.
             <style type="text/css">
                 default {
                     stroke:            #ff6666ff;
-                    stroke-width:      2km;
+                    stroke-width:      4km;
 					stroke-min-pixels: 2;
                 }            
             </style>
         </styles>
         
     </image>
-	
-	<external>
-		<lod_blending/>
-	</external>
 </map>
diff --git a/tests/feature_scripted_styling.earth b/tests/feature_scripted_styling.earth
index c32f59f..615c9bf 100644
--- a/tests/feature_scripted_styling.earth
+++ b/tests/feature_scripted_styling.earth
@@ -20,7 +20,9 @@ and a custom selector.
                           
         <features name="states" driver="ogr">
             <url>../data/world.shp</url>
-            <buffer distance="-0.05"/>
+            <filters>
+                <buffer distance="-0.05"/>
+            </filters>
         </features>
         
         <styles>            
diff --git a/tests/feature_scripted_styling_2.earth b/tests/feature_scripted_styling_2.earth
index f3a1ccc..738a1fc 100644
--- a/tests/feature_scripted_styling_2.earth
+++ b/tests/feature_scripted_styling_2.earth
@@ -19,7 +19,9 @@ Demonstrates how to select a style name using javascript.
                           
         <features name="states" driver="ogr">
             <url>../data/world.shp</url>
-            <buffer distance="-0.05"/>
+            <filters>
+                <buffer distance="-0.05"/>
+            </filters>
         </features>
         
         <styles>        
diff --git a/tests/feature_style_selector.earth b/tests/feature_style_selector.earth
index 6ffa0dc..be6fd90 100644
--- a/tests/feature_style_selector.earth
+++ b/tests/feature_style_selector.earth
@@ -19,7 +19,9 @@ Demonstrates how to select a style name using javascript.
                           
         <features name="states" driver="ogr">
             <url>../data/world.shp</url>
-            <buffer distance="-0.05"/>
+            <filters>
+                <buffer distance="-0.05"/>
+            </filters>
         </features>
         
         <styles>        
@@ -36,15 +38,15 @@ Demonstrates how to select a style name using javascript.
                 function getStyleClass()
                 {
 					// Exclude any countries beginning with the letter A: 
-					if ( feature.attributes['cntry_name'].charAt(0) === 'A' )
+					if ( feature.properties.cntry_name.charAt(0) === 'A' )
 						return null;
 						
 					// If it starts with the letter C, return an inline style:
-					if ( feature.attributes['cntry_name'].charAt(0) == 'C' )
-						return '{ fill: #ffc8389f; }';
+					if ( feature.properties.cntry_name.charAt(0) == 'C' )
+						return '{ fill: #ffc838; stroke: #8f8838; extrusion-height: 250000; }';
 						
 					// Otherwise, color by population and return a stylesheet style:
-                    var pop = parseFloat(feature.attributes['pop_cntry']);
+                    var pop = parseFloat(feature.properties.pop_cntry);
                     if      ( pop <= 14045470 )  return "p1";
                     else if ( pop <= 43410900 )  return "p2";
                     else if ( pop <= 97228750 )  return "p3";
diff --git a/tests/feature_tfs_scripting.earth b/tests/feature_tfs_scripting.earth
index 1e232fe..a676113 100644
--- a/tests/feature_tfs_scripting.earth
+++ b/tests/feature_tfs_scripting.earth
@@ -60,9 +60,8 @@ This example shows how to use the TFS driver.
     </model>
                     
  
-    <image name="mapquest_osm" driver="xyz">
-        <url>http://otile[1234].mqcdn.com/tiles/1.0.0/osm/{z}/{x}/{y}.jpg</url>
-        <profile>global-mercator</profile>
+    <image name="readymap_imagery" driver="tms">
+        <url>http://readymap.org/readymap/tiles/1.0.0/7/</url>
     </image>
     
     <external>
diff --git a/tests/feature_wfs.earth b/tests/feature_wfs.earth
index 6ee166f..4905bba 100644
--- a/tests/feature_wfs.earth
+++ b/tests/feature_wfs.earth
@@ -1,21 +1,17 @@
 <!--
 osgEarth Sample
-
-This one demonstrates how to read feature data from a WFS server
+Demonstrates how to read feature data from a WFS server
 -->
 
 <map name="WFS Feature Demo" type="geocentric" version="2">
-    
-    <options lighting="false"/>
-
-    <image name="world" driver="gdal">
+        
+    <image driver="gdal">
         <url>../data/world.tif</url>
     </image>
     
-    <model name="states" driver="feature_geom">          
-                
+    <model name="states" driver="feature_geom">
         <features name="states" driver="wfs">
-            <url> http://demo.opengeo.org/geoserver/wfs</url>     		
+            <url>http://demo.opengeo.org/geoserver/wfs</url>           
             <typename>states</typename>
             <outputformat>json</outputformat>
         </features>
@@ -26,11 +22,9 @@ This one demonstrates how to read feature data from a WFS server
                    stroke:            #ffff00;
                    stroke-opacity:    1.0;
                    stroke-width:      3.0;
-				   altitude-clamping: terrain-drape;
+                   altitude-clamping: terrain-drape;
                 }                       
-            </style>                   
-            
+            </style>
         </styles>
-        
     </model>
 </map>
diff --git a/tests/gdal_tiff.earth b/tests/gdal_tiff.earth
index 6649d29..73ef1f4 100644
--- a/tests/gdal_tiff.earth
+++ b/tests/gdal_tiff.earth
@@ -6,6 +6,6 @@ Demonstrates the simplest possible use of the GDAL driver to load a GeoTIFF imag
 <map version="2">
     <image driver="gdal" name="world-tiff" cache_enabled="false">
         <url>../data/world.tif</url>
-        <caching_policy usage="no_cache"/>
+        <cache_policy usage="no_cache"/>
     </image>
 </map>
\ No newline at end of file
diff --git a/tests/geomshader.earth b/tests/geomshader.earth
new file mode 100644
index 0000000..798c2c5
--- /dev/null
+++ b/tests/geomshader.earth
@@ -0,0 +1,62 @@
+<!--
+osgEarth Sample - Geometry Shader
+
+This example shows how to inject a GLSL Geometry Shader into the Terrain
+Rendering pipeline.
+
+-->
+<map name="readymap.org" type="geocentric">
+        
+    <image name="readymap_imagery" driver="tms">
+        <url>http://readymap.org/readymap/tiles/1.0.0/7/</url>
+    </image>
+        
+    <elevation name="readymap_elevation" driver="tms">
+        <url>http://readymap.org/readymap/tiles/1.0.0/116/</url>
+    </elevation>
+    
+    <terrainshader>
+        <code><![CDATA[
+        
+            #version 330
+            #pragma vp_entryPoint "pulsateEffect"
+            #pragma vp_location   "geometry"
+
+            layout(triangles) in;
+            layout(triangle_strip) out;
+            layout(max_vertices = 3) out;
+            
+            // Internal helper functions:
+            void VP_LoadVertex(in int);
+            void VP_EmitModelVertex();
+
+            uniform float osg_FrameTime;
+            
+            vec3 vp_Normal;
+            
+            void pulsateEffect()
+            {
+                float strength = 0.25 + sin(osg_FrameTime*2.0)*0.25;
+                vec4 cen = (gl_in[0].gl_Position + gl_in[1].gl_Position + gl_in[2].gl_Position)/3.0;
+                                    
+                // For each vertex in the input triangle:
+                for(int i=0; i < 3; ++i)
+                {
+                    // Loads per-vertex data "i" into the stage globals:
+                    VP_LoadVertex(i);
+                    
+                    // Transform the vertex:
+                    vec4 pos = gl_in[i].gl_Position;
+                    pos.xyz += vec3(0,0,1) * 1e6 * strength;
+                    //pos += vec4(normalize(cen.xyz-pos.xyz) * distance(cen, pos) * strength, 0.0);
+                    gl_Position = pos;
+                    
+                    // Copies stage globals to output and calles EmitVertex():
+                    VP_EmitModelVertex();
+                }
+                EndPrimitive();
+            }
+            
+        ]]></code>
+    </terrainshader>
+</map>
diff --git a/tests/glsl.earth b/tests/glsl.earth
index 33cf528..a8d5157 100644
--- a/tests/glsl.earth
+++ b/tests/glsl.earth
@@ -8,21 +8,19 @@ osgEarth Sample - GLSL in the Earth File.
         <caching_policy usage="no_cache"/>
     </image>
     
-    <extensions>
-        <terrainshader>
-            <code><![CDATA[
+    <terrainshader>
+        <code><![CDATA[
+        
+            #version 110
+            #pragma vp_entryPoint "adjustGamma"
+            #pragma vp_location   "fragment_coloring"
             
-                #version 110
-                #pragma vp_entryPoint "adjustGamma"
-                #pragma vp_location   "fragment_coloring"
-                
-                void adjustGamma(inout vec4 color)
-                {
-                    const float gamma = 1.3;
-                    color.rgb = pow(color.rgb, 1.0/vec3(gamma));
-                }
-                
-            ]]></code>
-        </terrainshader>
-    </extensions>
+            void adjustGamma(inout vec4 color)
+            {
+                const float gamma = 2.7;
+                color.rgb = pow(color.rgb, 1.0/vec3(gamma));
+            }
+            
+        ]]></code>
+    </terrainshader>
 </map>
\ No newline at end of file
diff --git a/tests/graticule.earth b/tests/graticule.earth
index 2ed6d51..e0f9e99 100644
--- a/tests/graticule.earth
+++ b/tests/graticule.earth
@@ -4,10 +4,6 @@ osgEarth Sample - Graticule Extension.
 -->
 <map name="Graticule demo" type="geocentric">
     
-    <options>
-        <terrain first_lod="1"/>
-    </options>
-    
     <image name="readymap_imagery" driver="tms">
         <url>http://readymap.org/readymap/tiles/1.0.0/7/</url>
     </image>
@@ -16,26 +12,25 @@ osgEarth Sample - Graticule Extension.
         <url>http://readymap.org/readymap/tiles/1.0.0/9/</url>
     </elevation>
     
-    <extensions>
-        <graticule>
-            <!-- The approximate number of grid lines that you would like to see in your view extent.
-                 This number, along with the resolutions list, will be used to select a resolution on each view.
-             -->
-            <grid_lines>10</grid_lines>
+    <graticule>
+        <!-- The approximate number of grid lines that you would like to see in your view extent.
+             This number, along with the resolutions list, will be used to select a resolution on each view.
+         -->
+        <grid_lines>10</grid_lines>
+
+        <!-- The grid resolutions, in degrees that you want to see, all separated by a space and sorted from lowest resolution to highest -->
+        <!--
+        <resolutions>10 5 2.5 1.25</resolutions>
+         -->
 
-            <!-- The grid resolutions, in degrees that you want to see, all separated by a space and sorted from lowest resolution to highest -->
-            <!--
-            <resolutions>10 5 2.5 1.25</resolutions>
-             -->
+        <!-- The grid line color -->
+        <color>#f7a73f70</color>
+        
+        <!-- The label color -->
+        <label_color>#ffff00ff</label_color>
+        
+        <!-- Specify the line width -->
+        <line_width>2</line_width>
+    </graticule>
 
-            <!-- The grid line color -->
-            <color>#f7a73f70</color>
-            
-            <!-- The label color -->
-            <label_color>#ffff00ff</label_color>
-            
-            <!-- Specify the line width -->
-            <line_width>2</line_width>
-        </graticule>
-    </extensions>
 </map>
diff --git a/tests/hires-inset.earth b/tests/hires-inset.earth
index b9cfce2..e771301 100644
--- a/tests/hires-inset.earth
+++ b/tests/hires-inset.earth
@@ -28,9 +28,7 @@ Look for hi-res insets over the cities of Boston and New York.
 		<url>../data/nyc-inset-wgs84.tif</url>
 	</image>
     
-	<external>
-	    <viewpoints>
-		    <viewpoint name="Hi-res insets" lat="41.642" long="-72.333" pitch="-71" range="657510"/>
-		</viewpoints>
-	</external>
+    <viewpoints>
+	    <viewpoint name="Hi-res insets" lat="41.642" long="-72.333" pitch="-71" range="657510"/>
+	</viewpoints>
 </map>
\ No newline at end of file
diff --git a/tests/intersect_filter.earth b/tests/intersect_filter.earth
new file mode 100644
index 0000000..e8821a9
--- /dev/null
+++ b/tests/intersect_filter.earth
@@ -0,0 +1,58 @@
+<!--
+osgEarth Sample
+Shows how to use an Intersect Filter to crop incoming features 
+to a polygon mask.
+-->
+
+<map name="Feature Geometry Demo" type="geocentric" version="2">
+            
+    <image driver="gdal">
+        <url>../data/world.tif</url>
+    </image>
+    
+    <model driver="feature_geom" comment="Outline of France">
+        <features driver="ogr">
+            <url>../data/france.shp</url>
+        </features>
+        <styles>
+            <style>
+                stroke: #ffff00;
+                altitude-clamping: terrain-scene;
+                stroke-tessellation-size: 10km;
+            </style>
+        </styles>
+    </model>
+    
+    <model name="cities" driver="feature_geom" comment="Cities in France">
+        <features name="cities" driver="ogr">
+            <url>../data/ne_cities.shp</url>
+            <profile>spherical-mercator</profile>
+            <filters>
+                <intersect>
+                    <comment>
+                        Features: geometry to intersect with;
+                        Contains: true=features fall inside geometry; false=outside
+                        Exact:    true=use exact geometry; false=use bounding boxes only
+                    </comment>
+                    
+                    <features driver="ogr">
+                        <url>../data/france.shp</url>
+                    </features>
+                    <contains>true</contains>
+                    
+                </intersect>
+            </filters>
+        </features>
+
+        <styles>
+            <style type="text/css">              
+                cities {
+                    icon:           "../data/placemark32.png";
+                    text-content:   [name];
+                    text-halo:      #3f3f3f;
+                }     
+            </style>
+        </styles>
+    </model>
+  
+</map>
diff --git a/tests/ldb.earth b/tests/ldb.earth
index 32ffd2b..962beb5 100644
--- a/tests/ldb.earth
+++ b/tests/ldb.earth
@@ -9,20 +9,18 @@ Enable the logrithmic depth buffer by running osgearth_viewer with --logdepth
         <url>http://readymap.org/readymap/tiles/1.0.0/7/</url>
     </image>
     
-    <external>
-        <viewpoints>
-            <viewpoint name="Plane" heading="0" height="-1526.619580102153" lat="0.7502917292180486" long="-90.00003984212466" pitch="-88.99970818676897" range="19080841.37590883"/>
-            <viewpoint name="Plane2" heading="9.977198612994472e-011" height="-1493.142864811234" lat="0.750286505217539" long="-90.00003984212442" pitch="-88.99958540266123" range="19003681.6859768"/>
-        </viewpoints>
-        
-        <annotations>            
-            <model name="flag model">
-                <url>../data/cessna.osgb.100.scale.(-90,-45,0).rot</url>
-                <position lat="0" long="-90" hat="19000000"/>
-                <!-- <position lat="33" long="-120" hat="1000000"/> -->
-            </model>            
-        </annotations>
-        
-        <sky driver="gl"/>
-    </external>
+    <viewpoints>
+        <viewpoint name="Plane" heading="0" height="-1526.619580102153" lat="0.7502917292180486" long="-90.00003984212466" pitch="-88.99970818676897" range="19080841.37590883"/>
+        <viewpoint name="Plane2" heading="9.977198612994472e-011" height="-1493.142864811234" lat="0.750286505217539" long="-90.00003984212442" pitch="-88.99958540266123" range="19003681.6859768"/>
+    </viewpoints>
+    
+    <annotations>            
+        <model name="flag model">
+            <url>../data/cessna.osgb.100.scale.(-90,-45,0).rot</url>
+            <position lat="0" long="-90" hat="19000000"/>
+            <!-- <position lat="33" long="-120" hat="1000000"/> -->
+        </model>            
+    </annotations>
+    
+    <sky driver="gl"/>
 </map>
diff --git a/tests/mapquest_open_aerial.earth b/tests/mapquest_open_aerial.earth
deleted file mode 100644
index 15d6b96..0000000
--- a/tests/mapquest_open_aerial.earth
+++ /dev/null
@@ -1,25 +0,0 @@
-<!-- 
-MapQuest - Open Aerial Map
-LOD 1-12 worldwide; 12+ US-only.
-http://developer.mapquest.com/web/products/open/map
-
-NOTE: You are responsible for abiding by the provider's terms of service:
-http://developer.mapquest.com/web/info/terms-of-use
-
-TIP: set your OSG_NUM_HTTP_DATABASE_THREADS to 4 or more!
--->
-
-<map name="MapQuest Open Aerial" type="geocentric" version="2">
- 
-    <image name="mapquest_open_aerial" driver="xyz">
-        <url>http://oatile[1234].mqcdn.com/tiles/1.0.0/sat/{z}/{x}/{y}.jpg</url>
-        <profile>spherical-mercator</profile>
-        <cache_policy usage="no_cache"/>
-        <nodata_image>http://oatile3.mqcdn.com/tiles/1.0.0/sat/13/636/6210.jpg</nodata_image>
-    </image>
-    
-    <options>
-        <lighting>false</lighting>
-    </options>
-    
-</map>
diff --git a/tests/mapquest_osm.earth b/tests/mapquest_osm.earth
deleted file mode 100644
index 6c70d7e..0000000
--- a/tests/mapquest_osm.earth
+++ /dev/null
@@ -1,26 +0,0 @@
-<!-- 
-MapQuest - OpenStreetMap
-http://developer.mapquest.com/web/products/open/map
-
-NOTE: You are responsible for abiding by the provider's terms of service:
-http://developer.mapquest.com/web/info/terms-of-use
-
-TIP: set your OSG_NUM_HTTP_DATABASE_THREADS to 4 or more!
--->
-
-<map name="MapQuest OpenStreetMap" type="geocentric" version="2">
- 
-    <image name="mapquest_osm" driver="xyz">
-        <url>http://otile[1234].mqcdn.com/tiles/1.0.0/osm/{z}/{x}/{y}.jpg</url>
-        <profile>global-mercator</profile>
-    </image>
-    
-    <options>
-        <lighting>false</lighting>
-        <cache_policy usage="no_cache"/>
-        <terrain>
-            <min_tile_range_factor>9</min_tile_range_factor>
-        </terrain>
-    </options>
-    
-</map>
diff --git a/tests/mapquest_with_srtm.earth b/tests/mapquest_with_srtm.earth
deleted file mode 100644
index 79580e7..0000000
--- a/tests/mapquest_with_srtm.earth
+++ /dev/null
@@ -1,30 +0,0 @@
-<!-- 
-MapQuest - Open Aerial Map
-LOD 1-12 worldwide; 12+ US-only.
-http://developer.mapquest.com/web/products/open/map
-
-NOTE: You are responsible for abiding by the provider's terms of service:
-http://developer.mapquest.com/web/info/terms-of-use
-
-TIP: set your OSG_NUM_HTTP_DATABASE_THREADS to 4 or more!
--->
-
-<map name="MapQuest Open Aerial" type="geocentric" version="2">
- 
-    <image name="mapquest_open_aerial" driver="xyz">
-        <url>http://oatile[1234].mqcdn.com/tiles/1.0.0/sat/{z}/{x}/{y}.jpg</url>
-        <profile>spherical-mercator</profile>
-        <cache_policy usage="no_cache"/>
-        <nodata_image>http://oatile3.mqcdn.com/tiles/1.0.0/sat/13/636/6210.jpg</nodata_image>
-    </image>
-        
-    <elevation name="readymap_elevation" driver="tms">
-        <url>http://readymap.org/readymap/tiles/1.0.0/9/</url>
-    </elevation>
-    
-    <options elevation_tile_size="9">
-        <terrain min_tile_range_factor="8">
-        </terrain>
-    </options>
-    
-</map>
diff --git a/tests/mb_tiles.earth b/tests/mb_tiles.earth
index d224c34..5bd2f84 100644
--- a/tests/mb_tiles.earth
+++ b/tests/mb_tiles.earth
@@ -6,18 +6,8 @@ This example shows how to access an MBTiles dataset.  The MBTiles datasets are v
 
 <map name="MBTiles" type="geocentric" version="2">    
       
-      <!--
-   <image driver="gdal" name="world-tiff">
-        <url>../data/world.tif</url>
-    </image>	   
-    -->
-	  
-    <!--
-    Add the haiti mbtiles dataset available at http://maps.internews.eu/v2/haiti-terrain-grey.mbtiles.
-    You may need to change the path to point to your download location-->	  
     <image name="haiti" driver="mbtiles">
-        <filename>../data/haiti-terrain-grey.mbtiles</filename>
-		<format>jpg</format>
+        <filename>../data/world.mbtiles</filename>
     </image>
    
 </map>
diff --git a/tests/mercator_to_plate_carre.earth b/tests/mercator_to_plate_carre.earth
index 6617c55..d718514 100644
--- a/tests/mercator_to_plate_carre.earth
+++ b/tests/mercator_to_plate_carre.earth
@@ -6,14 +6,14 @@ Plate Carre (y=lat, x=lon) by applying the <profile> tag.
 <map name="OpenStreetMap" type="projected" version="2">
 
     <options>
-        <profile>global-geodetic</profile>    
+        <profile>plate-carre</profile>    
         <lighting>false</lighting>
     </options>
     
-    <image name="mapquest_osm" driver="xyz" cache_enabled="false">
-        <url>http://otile[1234].mqcdn.com/tiles/1.0.0/osm/{z}/{x}/{y}.jpg</url>
-        <profile>global-mercator</profile>
+    <image name="osm_mapnik" driver="xyz">
+        <url>http://[abc].tile.openstreetmap.org/{z}/{x}/{y}.png</url>
+        <profile>spherical-mercator</profile>
+        <cache_policy usage="none"/>
     </image>
     
-    
 </map>
diff --git a/tests/min_max_level.earth b/tests/min_max_level.earth
index aac5649..62ca2ad 100644
--- a/tests/min_max_level.earth
+++ b/tests/min_max_level.earth
@@ -5,18 +5,15 @@ at a given levels of detail.
 Please note that usage of Yahoo! map data is subject to Yahoo!'s terms of service.
 -->
 
-<map name="Yahoo Levels" type="geocentric" version="2">
+<map name="Levels" type="geocentric" version="2">
 
-    <image name="mapquest_open_aerial" driver="xyz" max_level="5">
-        <url>http://oatile[1234].mqcdn.com/tiles/1.0.0/sat/{z}/{x}/{y}.jpg</url>
-        <profile>spherical-mercator</profile>
+    <image driver="gdal" name="world-tiff" max_level="5">
+        <url>../data/world.tif</url>
         <cache_policy usage="no_cache"/>
-        <nodata_image>http://oatile3.mqcdn.com/tiles/1.0.0/sat/13/636/6210.jpg</nodata_image>
     </image>
-	
-    <image name="mapquest_osm" driver="xyz" min_level="6">
-        <url>http://otile[1234].mqcdn.com/tiles/1.0.0/osm/{z}/{x}/{y}.jpg</url>
-        <profile>global-mercator</profile>
+    
+    <image name="readymap_imagery" driver="tms" min_level="6">
+        <url>http://readymap.org/readymap/tiles/1.0.0/7/</url>
     </image>
-   
+    
 </map>
diff --git a/tests/min_max_range.earth b/tests/min_max_range.earth
index 7ea1cd6..00d63c6 100644
--- a/tests/min_max_range.earth
+++ b/tests/min_max_range.earth
@@ -9,24 +9,13 @@ TIP: set your OSG_NUM_HTTP_DATABASE_THREADS to 4 or more!
 
 <map name="MapQuest Open Aerial" type="geocentric" version="2">
  
-    <image name="mapquest_open_aerial" driver="xyz">
-        <url>http://oatile[1234].mqcdn.com/tiles/1.0.0/sat/{z}/{x}/{y}.jpg</url>
-        <profile>spherical-mercator</profile>
+    <image driver="gdal" name="world-tiff" cache_enabled="false">
+        <url>../data/world.tif</url>
         <cache_policy usage="no_cache"/>
-        <nodata_image>http://oatile3.mqcdn.com/tiles/1.0.0/sat/13/636/6210.jpg</nodata_image>
-    </image>
-	
-    <image name="mapquest_osm" driver="xyz" max_range="1e7" min_range="1e6">
-        <url>http://otile[1234].mqcdn.com/tiles/1.0.0/osm/{z}/{x}/{y}.jpg</url>
-        <profile>global-mercator</profile>
     </image>
     
-    <options>
-        <lighting>false</lighting>
-        <cache_policy usage="no_cache"/>
-        <terrain>
-            <min_tile_range_factor>9</min_tile_range_factor>
-        </terrain>
-    </options>
+    <image name="readymap_imagery" driver="tms" max_range="1e7" min_range="1e6">
+        <url>http://readymap.org/readymap/tiles/1.0.0/7/</url>
+    </image>
     
 </map>
diff --git a/tests/min_max_range_rex.earth b/tests/min_max_range_rex.earth
new file mode 100644
index 0000000..7dc0814
--- /dev/null
+++ b/tests/min_max_range_rex.earth
@@ -0,0 +1,23 @@
+<!-- 
+Demonstrates the "min_range" and "max_range" properties.
+
+As you zoom in, you will see the aerial imagery transition into
+a street map. Zoom in further and see it transition back to aerial.
+-->
+
+<map name="Ranges" type="geocentric" version="2">
+
+    <options>
+        <terrain driver="rex"/>
+    </options>
+ 
+    <image driver="gdal" name="world-tiff" cache_enabled="false">
+        <url>../data/world.tif</url>
+        <cache_policy usage="no_cache"/>
+    </image>
+    
+    <image name="readymap_imagery" driver="tms" max_range="1e7" min_range="1e6">
+        <url>http://readymap.org/readymap/tiles/1.0.0/7/</url>
+    </image>
+    
+</map>
diff --git a/tests/multiple_heightfields.earth b/tests/multiple_heightfields.earth
index f438a59..09010a9 100644
--- a/tests/multiple_heightfields.earth
+++ b/tests/multiple_heightfields.earth
@@ -31,8 +31,5 @@ lo-res heightfield underlay.
         <cache_policy usage="no_cache"/>
     </options>
     
-    <external>
-        <contour_map opacity="0.35"/>
-        <vertical_scale scale="2.0"/>
-    </external>
+    <contour_map opacity="0.35"/>
 </map>
\ No newline at end of file
diff --git a/tests/night.earth b/tests/night.earth
index e8aca45..8df9c2a 100644
--- a/tests/night.earth
+++ b/tests/night.earth
@@ -20,8 +20,6 @@ Demonstrates the use of the night color filter, which only shows a layer in nigh
         </color_filters>
     </image>      
 
-    <external>
-        <sky driver="simple" hours="14.0" ambient="1.0"/>
-    </external>
+    <sky driver="simple" hours="14.0" ambient="1.0"/>
     
 </map>
diff --git a/tests/nodata.earth b/tests/nodata.earth
index 5b50495..ff8e6f7 100644
--- a/tests/nodata.earth
+++ b/tests/nodata.earth
@@ -16,9 +16,7 @@ Demonstrates the use of a file with nodata.  The white circle is a GeoTiff which
     
     <options lighting="false"/>
 
-     <external>
-        <viewpoints>
-            <viewpoint name="NoData" heading="0.0" height="0" lat="5.0" long="15.0" pitch="-90" range="1e6"/>
-        </viewpoints>
-    </external>
+    <viewpoints>
+        <viewpoint name="NoData" heading="0.0" height="0" lat="5.0" long="15.0" pitch="-90" range="1e6"/>
+    </viewpoints>
 </map>
diff --git a/tests/noise.earth b/tests/noise.earth
index 9078d68..ec1be7c 100644
--- a/tests/noise.earth
+++ b/tests/noise.earth
@@ -4,70 +4,74 @@ osgEarth Sample
 
 <map version="2">
 
+    <options>
+        <terrain normal_maps="true"/>
+    </options>
+
     <elevation name="readymap_elevation" driver="tms">
         <url>http://readymap.org/readymap/tiles/1.0.0/116/</url>
     </elevation>
     
-    <external>
-        <noise/>
-        <contour_map/>
-        <normal_map/>
-        <sky hours="20.0"/>
+    <noise size="1024" num_channels="1"/>
+    
+    <contour_map/>
+    
+    <sky_simple hours="20.0"/>
+    
+    <terrainshader>
+      <code><![CDATA[
+      
+        #version 330
         
-        <terrainshader>
-          <code><![CDATA[
-          
-            #version 330
-            
-            #pragma vp_entryPoint "makeSomeNoise"
-            #pragma vp_location   "fragment_coloring"
-            
-            // Try modifying these for fun.
-            uniform float baseLOD = 1;
-             
-            uniform sampler2D oe_noise_tex;
-            
-            uniform vec4 oe_tile_key;
-            in vec4 oe_layer_tilec;
-            
-            vec2 getNoiseCoords(in float lod)
-            {
-                float dL        = oe_tile_key.z - lod;
-                float factor    = exp2(dL);
-                float invFactor = 1.0/factor;
-                vec2  result    = oe_layer_tilec.st * vec2(invFactor);
-
-                // For upsampling we need to calculate an offset as well
-                if ( factor >= 1.0 )
-                {
-                    vec2 a = floor(oe_tile_key.xy * invFactor);
-                    vec2 b = a * factor;
-                    vec2 c = (a+1.0) * factor;
-                    vec2 offset = (oe_tile_key.xy-b)/(c-b);
-                    result += offset;
-                }
-                return result;
-            }
+        #pragma vp_entryPoint "makeSomeNoise"
+        #pragma vp_location   "fragment_coloring"
+        
+        // Try modifying these for fun.
+        uniform float baseLOD = 1;
+         
+        uniform sampler2D oe_noise_tex;
+        
+        uniform vec4 oe_tile_key;
+        in vec4 oe_layer_tilec;
+        
+        vec2 getNoiseCoords(in float lod)
+        {
+            float dL        = oe_tile_key.z - lod;
+            float factor    = exp2(dL);
+            float invFactor = 1.0/factor;
+            vec2  result    = oe_layer_tilec.st * vec2(invFactor);
 
-            void makeSomeNoise(inout vec4 color)
+            // For upsampling we need to calculate an offset as well
+            if ( factor >= 1.0 )
             {
-                vec2 coords = getNoiseCoords( floor(baseLOD) );
-                float n = 1.5 * texture( oe_noise_tex, coords ).r;
-                color.rgb *= n;
+                vec2 a = floor(oe_tile_key.xy * invFactor);
+                vec2 b = a * factor;
+                vec2 c = (a+1.0) * factor;
+                vec2 offset = (oe_tile_key.xy-b)/(c-b);
+                result += offset;
             }
-            
-          ]]></code>
-        </terrainshader>
+            return result;
+        }
+
+        void makeSomeNoise(inout vec4 color)
+        {
+            vec2 coords = getNoiseCoords( floor(baseLOD) );
+            float n = 1.5 * texture( oe_noise_tex, coords ).r;
+            color.rgb *= n;
+        }
         
-        <viewpoints>
-            <viewpoint name="Wash St. 430K" heading="-1.002577141807595" height="3694.875054217875" lat="46.85393268075167" long="-121.7764141794478" pitch="-89.85464953482169" range="426454.3850159062"/>
-            <viewpoint name="Mt R. Nadir 30K" heading="0.5013023037097585" height="4101.627114404924" lat="46.85909894548915" long="-121.7598368518208" pitch="-89.43249895879129" range="29029.34246828893"/>
-            <viewpoint name="Mt R. Oblique 30K" heading="17.33521725357022" height="2462.60273069609" lat="46.82181702111031" long="-121.7814936386096" pitch="-21.29241356548601" range="23926.75258864516"/>
-            <viewpoint name="Mt R. Closeup" heading="-109.6842970297122" height="3843.486737414263" lat="46.85528453766688" long="-121.7455004166102" pitch="-4.617466338845979" range="951.4780720092711"/>
-            <viewpoint name="Mt R. Trees" heading="-98.36122712710565" height="1639.304918398149" lat="46.78673277044066" long="-121.743286318636" pitch="-10.85365380742088" range="257.5853045645545"/>
-            <viewpoint name="Nepal" heading="-72.70835146844568" height="6334.845537136309" lat="27.94213038800919" long="86.9936567556778" pitch="-18.63803872963365" range="13611.24948464565"/>
-            <viewpoint name="Nepal NF" heading="-49.14546953546358" height="6334.332569343038" lat="27.9421778947837" long="86.9935949004298" pitch="-3.643325527310435" range="13302.81192964212"/>
-            <viewpoint name="Matterhorn" heading="-1.429462844200832" height="2282.858508689329" lat="45.95106319557" long="7.642741711675961" pitch="-25.12269405854052" range="26690.10606054494"/>
-        </viewpoints>
-    </external>
+      ]]></code>
+    </terrainshader>
+    
+    <viewpoints>
+        <viewpoint name="Wash St. 430K" heading="-1.002577141807595" height="3694.875054217875" lat="46.85393268075167" long="-121.7764141794478" pitch="-89.85464953482169" range="426454.3850159062"/>
+        <viewpoint name="Mt R. Nadir 30K" heading="0.5013023037097585" height="4101.627114404924" lat="46.85909894548915" long="-121.7598368518208" pitch="-89.43249895879129" range="29029.34246828893"/>
+        <viewpoint name="Mt R. Oblique 30K" heading="17.33521725357022" height="2462.60273069609" lat="46.82181702111031" long="-121.7814936386096" pitch="-21.29241356548601" range="23926.75258864516"/>
+        <viewpoint name="Mt R. Closeup" heading="-109.6842970297122" height="3843.486737414263" lat="46.85528453766688" long="-121.7455004166102" pitch="-4.617466338845979" range="951.4780720092711"/>
+        <viewpoint name="Mt R. Trees" heading="-98.36122712710565" height="1639.304918398149" lat="46.78673277044066" long="-121.743286318636" pitch="-10.85365380742088" range="257.5853045645545"/>
+        <viewpoint name="Nepal" heading="-72.70835146844568" height="6334.845537136309" lat="27.94213038800919" long="86.9936567556778" pitch="-18.63803872963365" range="13611.24948464565"/>
+        <viewpoint name="Nepal NF" heading="-49.14546953546358" height="6334.332569343038" lat="27.9421778947837" long="86.9935949004298" pitch="-3.643325527310435" range="13302.81192964212"/>
+        <viewpoint name="Matterhorn" heading="-1.429462844200832" height="2282.858508689329" lat="45.95106319557" long="7.642741711675961" pitch="-25.12269405854052" range="26690.10606054494"/>
+    </viewpoints>
+
 </map>
diff --git a/tests/normalmap.earth b/tests/normalmap.earth
index c037d78..29aed15 100644
--- a/tests/normalmap.earth
+++ b/tests/normalmap.earth
@@ -1,10 +1,10 @@
 <!--
 osgEarth Sample - Shows an elevation-derived normal map.
 -->
-<map name="readymap.org" type="geocentric">
-    
+<map name="readymap.org" type="geocentric">    
+
     <options>
-        <terrain first_lod="1"/>
+        <terrain normal_maps="true"/>
     </options>
     
     <image name="readymap_imagery" driver="tms">
@@ -15,8 +15,8 @@ osgEarth Sample - Shows an elevation-derived normal map.
         <url>http://readymap.org/readymap/tiles/1.0.0/116/</url>
     </elevation>
     
-    <extensions>
-        <normalmap/>
-        <sky/>
-    </extensions>
+    <sky_simple/>
+    
+    <xi:include href="viewpoints.xml"/>
+
 </map>
diff --git a/tests/ocean.earth b/tests/ocean.earth
index 612b1ac..4c03981 100644
--- a/tests/ocean.earth
+++ b/tests/ocean.earth
@@ -22,35 +22,27 @@ http://readymap.org
     </elevation>
     
     
-    <extensions>
+    <!-- Ocean parameters. -->
+    <ocean driver="simple">
         
-        <!-- Ocean parameters. -->
-        <ocean>
+        <!-- Masking layer to use (optional...without a masking layer, osgEarth will sample the
+             terrain elevation data to determine where the ocean is.
+        -->
+        <mask_layer driver="tms">
+            <url>http://readymap.org/readymap/tiles/1.0.0/2/</url>
+        </mask_layer>
         
-            <!-- Surface texture to use -->
-            <!--
-            <texture_url>../data/watersurface1.png</texture_url>
-            -->
-            
-            <!-- Masking layer to use (optional...without a masking layer, osgEarth will sample the
-                 terrain elevation data to determine where the ocean is.
-            -->
-            <mask_layer driver="tms">
-                <url>http://readymap.org/readymap/tiles/1.0.0/2/</url>
-            </mask_layer>
-            
-            <!-- surface color (before texturing) -->
-            <base_color>#334f7fbf</base_color>
-            
-            <max_altitude>20000</max_altitude>
-            
-        </ocean>
+        <!-- surface color -->
+        <base_color>#1c6ba0f7</base_color>
         
-        <viewpoints>
-            <viewpoint name="Los Angeles" heading="35.27" height="97.48" lat="34.051" long="-117.974" pitch="-17" range="136405"/>
-            <viewpoint name="Above water" heading="-76.17264538992794" height="-199.5569639196619" lat="33.27975381179682" long="-118.3307776586542" pitch="-10.06523772274543" range="3739.161570538204"/>
-            <viewpoint name="Below water" heading="-24.96310172368127" height="-1300.000076910481" lat="33.27360337088133" long="-118.5514448058582" pitch="-10.0770016631354" range="6375.084038302656"/>
-        </viewpoints>
+        <max_altitude>250000</max_altitude>
         
-    </extensions>
+    </ocean>
+    
+    
+    <viewpoints>
+        <viewpoint name="Los Angeles" heading="35.27" height="97.48" lat="34.051" long="-117.974" pitch="-17" range="136405"/>
+        <viewpoint name="Above water" heading="-76.17264538992794" height="-199.5569639196619" lat="33.27975381179682" long="-118.3307776586542" pitch="-10.06523772274543" range="3739.161570538204"/>
+        <viewpoint name="Below water" heading="-24.96310172368127" height="-1300.000076910481" lat="33.27360337088133" long="-118.5514448058582" pitch="-10.0770016631354" range="6375.084038302656"/>
+    </viewpoints>
 </map>
diff --git a/tests/openstreetmap_buildings.earth b/tests/openstreetmap_buildings.earth
new file mode 100644
index 0000000..9053325
--- /dev/null
+++ b/tests/openstreetmap_buildings.earth
@@ -0,0 +1,93 @@
+<!--
+osgEarth Sample - Openstreetmap buildings.
+
+This shows how to use the TFS driver to connect to a worldwide openstreetmap building dataset.
+You must have the mapnik vector tiles driver built by including the protobuf libraries in cmake.
+-->
+<map name="TFS" type="geocentric" version="2">
+
+    <options>
+        <terrain driver="rex"/>
+    </options>
+    
+    <model name="buildings" driver="feature_geom">
+    
+        <features name="buildings" driver="tfs">
+            <url>http://readymap.org/osm/osm/osm/</url>
+            <invert_y>true</invert_y>
+            <min_level>14</min_level>
+            <max_level>14</max_level>
+            <profile>spherical-mercator</profile>
+            <format>pbf</format>    
+            <filters>
+                <script>
+                 <![CDATA[
+                   ("building" in feature.properties);
+                 ]]>
+                </script>
+            </filters>           
+        </features>
+
+        <styles>                
+            <library name="us_resources">
+                <url>../data/resources/textures_us/catalog.xml</url>
+            </library>            
+
+            <style type="text/css">
+                buildings {
+                    extrusion-height:      getHeight();
+                    extrusion-flatten:     true;
+                    extrusion-wall-style:  building-wall;
+                    extrusion-roof-style:  building-rooftop;
+                    altitude-clamping:     terrain;
+                    altitude-technique:    map;
+                    altitude-binding:      vertex;
+                    altitude-resolution:   0;
+                }            
+                building-wall {
+                    skin-library:     us_resources;
+                    skin-tags:        building;
+                    skin-random-seed: 1;
+                    fill:             #ffffff;
+                }
+                building-rooftop {
+                    skin-library:     us_resources;
+                    skin-tags:        rooftop;
+                    skin-tiled:       true;
+                    skin-random-seed: 1;
+                    fill:             #ffffff;
+                }
+            </style>
+            
+            <script>
+                function getHeight() {                    
+					if ("height" in feature.properties) {
+						var h = feature.properties["height"].replace('m','');
+						return Math.max(h, 4.0);
+					} else if ("building:height" in feature.properties) {
+						var h = feature.properties["building:height"].replace('m','');
+						return Math.max(h, 4.0);
+					} else if ("building:levels" in feature.properties){
+						var l = feature.properties["building:levels"];
+						return Math.max(l * 4.0, 4.0);
+					}
+					return Math.floor((Math.random() * 5.0) + 4.0);
+                }
+            </script>
+        </styles>
+    </model>
+
+    <image name="osm_mapnik" driver="xyz">
+        <url>http://[abc].tile.openstreetmap.org/{z}/{x}/{y}.png</url>
+        <profile>spherical-mercator</profile>
+        <cache_policy usage="none"/>
+    </image>
+
+    <elevation name="readymap_elevation" driver="tms">
+        <url>http://readymap.org/readymap/tiles/1.0.0/116/</url>
+        <vdatum>egm96</vdatum>
+    </elevation>
+    
+    <xi:include href="viewpoints.xml"/>
+  
+</map>
diff --git a/tests/openstreetmap_flat.earth b/tests/openstreetmap_flat.earth
index ea57710..f918732 100644
--- a/tests/openstreetmap_flat.earth
+++ b/tests/openstreetmap_flat.earth
@@ -8,8 +8,11 @@ http://wiki.openstreetmap.org/wiki/Slippy_map_tilenames
 
     <options>
         <profile>spherical-mercator</profile>
-        <lighting>false</lighting>
-        <terrain engine="quadtree" range_mode="PIXEL_SIZE_ON_SCREEN" tile_pixel_size="256"/>
+        <terrain driver="mp" 
+            tile_size="2" 
+            range_mode="PIXEL_SIZE_ON_SCREEN"
+            tile_pixel_size="400"
+            skirt_ratio="0"/>
     </options>
     
     <image name="osm_mapnik" driver="xyz">
diff --git a/tests/openstreetmap_full.earth b/tests/openstreetmap_full.earth
new file mode 100644
index 0000000..2efaa2c
--- /dev/null
+++ b/tests/openstreetmap_full.earth
@@ -0,0 +1,239 @@
+<!--
+osgEarth Sample - Openstreetmap buildings.
+
+This shows how to use the TFS driver to connect to a worldwide openstreetmap building dataset.
+You must have the mapnik vector tiles driver built by including the protobuf libraries in cmake.
+-->
+<map name="TFS" type="geocentric" version="2">
+
+ 
+ 
+
+    <model name="osm" driver="feature_geom">
+
+   
+       <features name="osm" driver="tfs">
+            <url>http://readymap.org/osm/osm/osm/</url>
+            <invert_y>true</invert_y>
+            <min_level>14</min_level>
+            <max_level>14</max_level>
+            <profile>spherical-mercator</profile>
+            <format>pbf</format>            
+        </features>
+
+        <instancing>true</instancing>
+
+        <feature_indexing enabled="false"></feature_indexing>
+
+        <styles>
+            
+            <library name="us_resources">
+                <url>../data/resources/textures_us/catalog.xml</url>
+            </library>
+
+            <style type="text/css">
+                hospital {
+                     icon: "../data/hospital.png";
+                     icon-align:    center-center;
+                     icon-declutter: true;
+                     text-content:  getName();
+                     altitude-clamping:       terrain;
+                }     
+
+                school {
+                     icon: "../data/school.png";
+                     icon-align:    center-center;
+                     icon-declutter: true;
+                     text-content:  getName();
+                     altitude-clamping:       terrain;
+                }     
+
+                bank {
+                     icon: "../data/bank.png";
+                     icon-align:    center-center;
+                     icon-declutter: true;
+                     text-content:  getName();
+                     altitude-clamping:       terrain;
+                }
+
+                forest {
+                   model:               "../data/tree.ive";
+                   model-placement:     random;
+                   model-density:       10000;
+                   model-scale:         2.5;
+                   model-random-seed:   1;
+                   altitude-clamping:       terrain;
+                }            
+
+                grass {
+                   model:               "../data/tree.ive";
+                   model-placement:     random;
+                   model-density:       10000;
+                   model-scale:         2.5;
+                   model-random-seed:   1;
+                   altitude-clamping:       terrain;
+                }
+
+                water {
+                   fill:               #6BA8FF;
+                   render-depth-test:  false;
+                   altitude-clamping:  terrain-drape;
+                }
+
+                buildings {
+                  extrusion-height:      Math.random()*30.0 + 5.0;
+                  extrusion-flatten:     true;
+                  extrusion-wall-style:  building-wall;
+                  extrusion-roof-style:  building-rooftop;
+                }            
+
+                building-wall {
+                  skin-library:     us_resources;
+                  skin-tags:        building;
+                  skin-random-seed: 1;
+                  fill:             #ffffff;
+                }
+                building-rooftop {
+                  skin-library:     us_resources;
+                  skin-tags:        rooftop;
+                  skin-tiled:       true;
+                  skin-random-seed: 1;
+                  fill:             #ffffff;
+                }
+
+            </style>
+
+            <selector name="default" style_expr="selectStyle()"/>
+            
+            <script language="javascript">
+              <![CDATA[
+
+                function selectStyle() {
+                    if ("building" in feature.properties) {
+                        return "buildings";
+                    }
+                    else if ("landuse" in feature.properties) {
+                        var landuse = feature.properties["landuse"];
+                        if ( landuse == "forest" ||
+                             landuse == "grass" ||
+                             landuse == "meadow"
+                            ) {
+                                return "forest";
+                            }                                            
+                        else if (landuse == "reservoir") {
+                            return "water";
+                        }
+                    }
+                    else if ("natural" in feature.properties) {
+                        var natural = feature.properties["natural"];
+                        if (natural == "wood" || natural == "tree") {
+                            return "forest"
+                        }
+                        else if (natural == "water") {
+                            return "water";
+                        }
+                    }
+                    else if ("surface" in feature.properties) {
+                        var surface = feature.properties["surface"];
+                        if (surface == "grass") {
+                            return "grass";
+                        }
+                    }
+                    else if ("amenity" in feature.properties) {
+                        var amenity = feature.properties["amenity"];
+                        if (amenity == "hospital") {
+                            return "hospital";
+                        }
+                        else if (amenity == "school") {
+                            return "school";
+                        }
+                        else if (amenity == "bank") {
+                            return "bank";
+                        }
+                    }
+                    return null;                    
+                }
+
+                function getName() {
+                    if ("name" in feature.properties) {
+                        return feature.properties["name"];
+                    }
+                    return "";
+                }
+              ]]>
+            </script>
+
+        </styles>
+    </model>
+ 
+ 
+
+    <image name="esri imagery" driver="arcgis">
+        <url>http://server.arcgisonline.com/ArcGIS/rest/services/ESRI_Imagery_World_2D/MapServer</url>
+        <nodata_image>http://server.arcgisonline.com/ArcGIS/rest/services/ESRI_Imagery_World_2D/MapServer/tile/100/0/0.jpeg</nodata_image>
+    </image>
+
+    <image name="osm_roads" driver="agglite" min_level="14">
+      
+       <max_data_level>14</max_data_level>
+       
+       <profile>spherical-mercator</profile>
+        
+        <features name="roads" driver="tfs">
+            <url>http://readymap.org/osm/osm/osm/</url>
+            <invert_y>true</invert_y>
+            <min_level>14</min_level>
+            <max_level>14</max_level>
+            <profile>spherical-mercator</profile>
+            <format>pbf</format>            
+
+            <filters>
+                <script language="javascript">
+                    <![CDATA[
+                    function filter() {
+                        if ("highway" in feature.properties) {
+                            return true;             
+                        }
+                        return false;
+                    }
+
+                    filter();                    
+
+                    ]]>
+                </script>
+            </filters>
+        </features>
+
+
+        <styles>
+            <style type="text/css">
+                roads {
+                  stroke: #656363;
+                  stroke-width: 15m;
+                  stroke-linecap: square;
+                }           
+            </style>
+        </styles>
+        
+        <cache_policy usage="none"/>
+    </image>
+
+
+
+<!--
+    <image name="readymap_streets" driver="tms">
+        <url>http://readymap.org/readymap/tiles/1.0.0/119/</url>
+    </image>
+-->
+
+
+    <elevation name="readymap_elevation" driver="tms">
+        <url>http://readymap.org/readymap/tiles/1.0.0/116/</url>
+    </elevation>
+    
+    
+    <external>
+        <sky hours="20.0"/>    
+    </external>
+  
+</map>
diff --git a/tests/osgearth_server/README.md b/tests/osgearth_server/README.md
new file mode 100644
index 0000000..08ce966
--- /dev/null
+++ b/tests/osgearth_server/README.md
@@ -0,0 +1,4 @@
+Static Viewer to test osgearth_server
+======================================
+
+Simple leaflet map used to test osgearth_server.  Run osgearth_server with an earth file and load this webpage index.html to test it.
\ No newline at end of file
diff --git a/tests/osgearth_server/css/l.geosearch.css b/tests/osgearth_server/css/l.geosearch.css
new file mode 100644
index 0000000..5e62199
--- /dev/null
+++ b/tests/osgearth_server/css/l.geosearch.css
@@ -0,0 +1,65 @@
+.displayNone {
+	display: none;
+}
+
+.leaflet-control-geosearch {
+	position: relative;
+}
+
+.leaflet-control-geosearch a {
+	-webkit-border-radius: 4px;
+			border-radius: 4px;
+	border-bottom: none;
+}
+
+.leaflet-control-geosearch a.glass {
+	background-image: url(../images/geosearch.png);
+	background-size: 100% 100%;
+}
+
+.leaflet-control-geosearch a.spinner {
+	background-image: url(../images/spinner.gif);
+	background-position: 50% 50%;
+}
+
+.leaflet-control-geosearch a.alert {
+	background-image: url(../images/alert.png);
+	background-size: 64% 64%;
+}
+
+.leaflet-control-geosearch a:hover {
+	border-bottom: none;
+}
+
+.leaflet-control-geosearch form {
+	position: absolute;
+	top: 0;
+	left: 22px;
+	box-shadow: 0 1px 7px rgba(0, 0, 0, 0.65);
+	-webkit-border-radius: 4px;
+			border-radius: 0px 4px 4px 0px;
+	z-index: -1;
+	background: #FFF;
+	height: 26px;
+	padding: 0 6px 0 6px;
+}
+
+.leaflet-control-geosearch form input {
+	width: 200px;
+	border: none;
+	outline: none;
+	margin: 0;
+	padding: 0;
+	font-size: 12px;
+	margin-top: 5px;
+}
+
+.leaflet-control-geosearch .message {
+	position: absolute;
+	top: 26px;
+	left: 0px;
+	width: 226px;
+	color: #FFF;
+	background: rgb(40, 40, 40);
+	padding: 4px 0 4px 8px;
+}
diff --git a/tests/osgearth_server/images/Thumbs.db b/tests/osgearth_server/images/Thumbs.db
new file mode 100644
index 0000000..a46c51e
Binary files /dev/null and b/tests/osgearth_server/images/Thumbs.db differ
diff --git a/tests/osgearth_server/images/alert.png b/tests/osgearth_server/images/alert.png
new file mode 100644
index 0000000..d5a20ce
Binary files /dev/null and b/tests/osgearth_server/images/alert.png differ
diff --git a/tests/osgearth_server/images/geosearch.png b/tests/osgearth_server/images/geosearch.png
new file mode 100644
index 0000000..d80bbdc
Binary files /dev/null and b/tests/osgearth_server/images/geosearch.png differ
diff --git a/tests/osgearth_server/images/layers-2x.png b/tests/osgearth_server/images/layers-2x.png
new file mode 100644
index 0000000..a2cf7f9
Binary files /dev/null and b/tests/osgearth_server/images/layers-2x.png differ
diff --git a/tests/osgearth_server/images/layers.png b/tests/osgearth_server/images/layers.png
new file mode 100644
index 0000000..bca0a0e
Binary files /dev/null and b/tests/osgearth_server/images/layers.png differ
diff --git a/tests/osgearth_server/images/marker-icon-2x.png b/tests/osgearth_server/images/marker-icon-2x.png
new file mode 100644
index 0000000..0015b64
Binary files /dev/null and b/tests/osgearth_server/images/marker-icon-2x.png differ
diff --git a/tests/osgearth_server/images/marker-icon.png b/tests/osgearth_server/images/marker-icon.png
new file mode 100644
index 0000000..e2e9f75
Binary files /dev/null and b/tests/osgearth_server/images/marker-icon.png differ
diff --git a/tests/osgearth_server/images/marker-shadow.png b/tests/osgearth_server/images/marker-shadow.png
new file mode 100644
index 0000000..d1e773c
Binary files /dev/null and b/tests/osgearth_server/images/marker-shadow.png differ
diff --git a/tests/osgearth_server/images/spinner.gif b/tests/osgearth_server/images/spinner.gif
new file mode 100644
index 0000000..aa70283
Binary files /dev/null and b/tests/osgearth_server/images/spinner.gif differ
diff --git a/tests/osgearth_server/images/transparent.png b/tests/osgearth_server/images/transparent.png
new file mode 100644
index 0000000..19b9106
Binary files /dev/null and b/tests/osgearth_server/images/transparent.png differ
diff --git a/tests/osgearth_server/index.html b/tests/osgearth_server/index.html
new file mode 100644
index 0000000..b4dd4c5
--- /dev/null
+++ b/tests/osgearth_server/index.html
@@ -0,0 +1,20 @@
+<html>
+<head>
+<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, minimal-ui" />
+<link rel="stylesheet" href="leaflet.css" />
+<script src="leaflet.js"></script>
+<style type="text/css">
+body, #map {
+  height: 100%;
+}
+</style>
+</head>
+<body>
+<div id="map"></div>
+<script>
+  var map = new L.Map('map', {maxZoom: 25});
+  map.fitWorld();
+  var splat = new L.tileLayer("http://localhost:8000/{z}/{x}/{y}.png", {tms: true, maxZoom: 25}).addTo(map);  
+</script>
+</body>
+</html>
diff --git a/tests/osgearth_server/js/l.control.geosearch.js b/tests/osgearth_server/js/l.control.geosearch.js
new file mode 100644
index 0000000..28ca9f9
--- /dev/null
+++ b/tests/osgearth_server/js/l.control.geosearch.js
@@ -0,0 +1,204 @@
+/*
+ * L.Control.GeoSearch - search for an address and zoom to its location
+ * https://github.com/smeijer/leaflet.control.geosearch
+ */
+
+L.GeoSearch = {};
+L.GeoSearch.Provider = {};
+
+L.GeoSearch.Result = function (x, y, label) {
+  this.X = x;
+  this.Y = y;
+  this.Label = label;
+};
+
+L.Control.GeoSearch = L.Control.extend({
+  options: {
+    position: 'topleft'
+  },
+
+  initialize: function (options) {
+    this._config = {};
+    L.Util.extend(this.options, options);
+    this.setConfig(options);
+  },
+
+  setConfig: function (options) {
+    this._config = {
+      'provider': options.provider,
+      'searchLabel': options.searchLabel || 'Enter address',
+      'notFoundMessage' : options.notFoundMessage || 'Sorry, that address could not be found.',
+      'zoomLevel': options.zoomLevel || 17,
+      'showMarker': typeof options.showMarker !== 'undefined' ? options.showMarker : true
+    };
+  },
+
+  resetLink: function(extraClass) {
+    var link = this._container.querySelector('a');
+    link.className = 'leaflet-bar-part leaflet-bar-part-single' + ' ' + extraClass;
+  },
+
+  onAdd: function (map) {
+
+    // create the container
+    this._container = L.DomUtil.create('div', 'leaflet-bar leaflet-control leaflet-control-geosearch');
+
+    // create the link - this will contain one of the icons
+    var link = L.DomUtil.create('a', '', this._container);
+    link.href = '#';
+    link.title = this._config.searchLabel;
+
+    // set the link's icon to magnifying glass
+    this.resetLink('glass');
+
+    var displayNoneClass = 'displayNone';
+
+    // create the form that will contain the input
+    var form = L.DomUtil.create('form', displayNoneClass, this._container);
+
+    // create the input, and set its placeholder ("Enter address") text
+    var input = L.DomUtil.create('input', null, form);
+    input.placeholder = 'Enter address';
+
+    // create the error message div
+    var message = L.DomUtil.create('div', 'leaflet-bar message displayNone', this._container);
+
+    L.DomEvent
+    .on(link, 'click', L.DomEvent.stopPropagation)
+    .on(link, 'click', L.DomEvent.preventDefault)
+    .on(link, 'click', function() {
+
+      if (L.DomUtil.hasClass(form, displayNoneClass)) {
+	L.DomUtil.removeClass(form, 'displayNone'); // unhide form
+	input.focus();
+      } else {
+	L.DomUtil.addClass(form, 'displayNone'); // hide form
+      }
+
+    })
+    .on(link, 'dblclick', L.DomEvent.stopPropagation);
+
+    L.DomEvent
+    .on(input, 'keypress', this.onKeyPress, this)
+    .on(input, 'keyup', this.onKeyUp, this)
+    .on(input, 'input', this.onInput, this);
+
+    return this._container;
+  },
+
+  geosearch: function (qry) {
+    try {
+      var provider = this._config.provider;
+
+      if(typeof provider.GetLocations == 'function') {
+	var results = provider.GetLocations(qry, this._map, function(err, results) {
+	  if (err) {
+	    return this._printError(err);
+	  }
+
+	  this._processResults(results);
+	}.bind(this));
+      }
+      else {
+	var url = provider.GetServiceUrl(qry);
+
+	$.getJSON(url, function (data) {
+	  try {
+	    var results = provider.ParseJSON(data);
+	    this._processResults(results);
+	  }
+	  catch (error) {
+	    this._printError(error);
+	  }
+	}.bind(this));
+      }
+    }
+    catch (error) {
+      this._printError(error);
+    }
+  },
+
+  _processResults: function(results) {
+    if (results.length === 0)
+      throw this._config.notFoundMessage;
+
+    this.cancelSearch();
+    this._showLocation(results[0]);
+  },
+
+  _showLocation: function (location) {
+    if (this._config.showMarker) {
+      if (typeof this._positionMarker === 'undefined')
+	this._positionMarker = L.marker([location.Y, location.X]).addTo(this._map);
+      else
+	this._positionMarker.setLatLng([location.Y, location.X]);
+    }
+
+    // this._map.setView([location.Y, location.X], this._config.zoomLevel, false);
+  },
+
+  _isShowingError: false,
+
+  _printError: function(error) {
+    var message = this._container.querySelector('.message');
+    message.innerHTML = error;
+    L.DomUtil.removeClass(message, 'displayNone');
+
+    // show alert icon
+    this.resetLink('alert');
+
+    this._isShowingError = true;
+  },
+
+  cancelSearch: function() {
+    var form = this._container.querySelector('form');
+    L.DomUtil.addClass(form, 'displayNone'); // hide form
+
+    var input = form.querySelector('input');
+    input.value = ''; // clear form
+
+    // show glass icon
+    this.resetLink('glass');
+
+    var message = this._container.querySelector('.message');
+    L.DomUtil.addClass(message, 'displayNone'); // hide message
+  },
+
+  startSearch: function() {
+    // show spinner icon
+    this.resetLink('spinner');
+
+    var input = this._container.querySelector('input');
+    this.geosearch(input.value);
+  },
+
+  onInput: function() {
+    if (this._isShowingError) {
+      // show glass icon
+      this.resetLink('glass');
+
+      var message = this._container.querySelector('.message');
+      L.DomUtil.addClass(message, 'displayNone'); // hide message
+
+      this._isShowingError = false;
+    }
+  },
+
+  onKeyPress: function (e) {
+    var enterKey = 13;
+
+    if (e.keyCode === enterKey) {
+      L.DomEvent.preventDefault(e); // prevent default form submission
+
+      this.startSearch();
+    }
+  },
+
+  onKeyUp: function (e) {
+    var escapeKey = 27;
+
+    if (e.keyCode === escapeKey) {
+      this.cancelSearch();
+    }
+  }
+});
diff --git a/tests/osgearth_server/js/l.geosearch.provider.nominatim.js b/tests/osgearth_server/js/l.geosearch.provider.nominatim.js
new file mode 100644
index 0000000..a60a9b6
--- /dev/null
+++ b/tests/osgearth_server/js/l.geosearch.provider.nominatim.js
@@ -0,0 +1,70 @@
+/**
+ * L.Control.GeoSearch - search for an address and zoom to it's location
+ * L.GeoSearch.Provider.OpenStreetMap uses openstreetmap geocoding service
+ * https://github.com/smeijer/leaflet.control.geosearch
+ */
+
+L.GeoSearch.Provider.Nominatim = L.Class.extend({
+    options: {
+
+    },
+
+    initialize: function(options) {
+        options = L.Util.setOptions(this, options);
+    },
+
+    GetLocations: function(query, map, callback) {
+      callback = callback || function() {};
+
+      var url = this.GetServiceUrl(query);
+
+      $.getJSON(url, function (data) {
+	var results;
+
+	try {
+	  results = this.ParseJSON(data);
+	} catch (err) {
+	  return callback(err);
+	}
+
+	if (data.length > 0) {
+	  var bbox = data[0].boundingbox,
+	      viewport = [
+		[bbox[0], bbox[2]],
+		[bbox[1], bbox[3]]
+	      ];
+
+	  map.fitBounds(viewport, {
+	    maxZoom: 15
+	  });
+	}
+
+	return callback(null, results);
+      }.bind(this));
+    },
+
+    GetServiceUrl: function (qry) {
+        var parameters = L.Util.extend({
+            q: qry,
+            format: 'json'
+        }, this.options);
+
+        return 'http://nominatim.openstreetmap.org/search'
+            + L.Util.getParamString(parameters);
+    },
+
+    ParseJSON: function (data) {
+        if (data.length == 0)
+            return [];
+
+        var results = [];
+        for (var i = 0; i < data.length; i++) 
+            results.push(new L.GeoSearch.Result(
+                data[i].lon, 
+                data[i].lat, 
+                data[i].display_name
+            ));
+        
+        return results;
+    }
+});
diff --git a/tests/osgearth_server/leaflet.css b/tests/osgearth_server/leaflet.css
new file mode 100644
index 0000000..dea175f
--- /dev/null
+++ b/tests/osgearth_server/leaflet.css
@@ -0,0 +1,479 @@
+/* required styles */
+
+.leaflet-map-pane,
+.leaflet-tile,
+.leaflet-marker-icon,
+.leaflet-marker-shadow,
+.leaflet-tile-pane,
+.leaflet-tile-container,
+.leaflet-overlay-pane,
+.leaflet-shadow-pane,
+.leaflet-marker-pane,
+.leaflet-popup-pane,
+.leaflet-overlay-pane svg,
+.leaflet-zoom-box,
+.leaflet-image-layer,
+.leaflet-layer {
+	position: absolute;
+	left: 0;
+	top: 0;
+	}
+.leaflet-container {
+	overflow: hidden;
+	-ms-touch-action: none;
+	touch-action: none;
+	}
+.leaflet-tile,
+.leaflet-marker-icon,
+.leaflet-marker-shadow {
+	-webkit-user-select: none;
+	   -moz-user-select: none;
+	        user-select: none;
+	-webkit-user-drag: none;
+	}
+.leaflet-marker-icon,
+.leaflet-marker-shadow {
+	display: block;
+	}
+/* map is broken in FF if you have max-width: 100% on tiles */
+.leaflet-container img {
+	max-width: none !important;
+	}
+/* stupid Android 2 doesn't understand "max-width: none" properly */
+.leaflet-container img.leaflet-image-layer {
+	max-width: 15000px !important;
+	}
+.leaflet-tile {
+	filter: inherit;
+	visibility: hidden;
+	}
+.leaflet-tile-loaded {
+	visibility: inherit;
+	}
+.leaflet-zoom-box {
+	width: 0;
+	height: 0;
+	}
+/* workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=888319 */
+.leaflet-overlay-pane svg {
+	-moz-user-select: none;
+	}
+
+.leaflet-tile-pane    { z-index: 2; }
+.leaflet-objects-pane { z-index: 3; }
+.leaflet-overlay-pane { z-index: 4; }
+.leaflet-shadow-pane  { z-index: 5; }
+.leaflet-marker-pane  { z-index: 6; }
+.leaflet-popup-pane   { z-index: 7; }
+
+.leaflet-vml-shape {
+	width: 1px;
+	height: 1px;
+	}
+.lvml {
+	behavior: url(#default#VML);
+	display: inline-block;
+	position: absolute;
+	}
+
+
+/* control positioning */
+
+.leaflet-control {
+	position: relative;
+	z-index: 7;
+	pointer-events: auto;
+	}
+.leaflet-top,
+.leaflet-bottom {
+	position: absolute;
+	z-index: 1000;
+	pointer-events: none;
+	}
+.leaflet-top {
+	top: 0;
+	}
+.leaflet-right {
+	right: 0;
+	}
+.leaflet-bottom {
+	bottom: 0;
+	}
+.leaflet-left {
+	left: 0;
+	}
+.leaflet-control {
+	float: left;
+	clear: both;
+	}
+.leaflet-right .leaflet-control {
+	float: right;
+	}
+.leaflet-top .leaflet-control {
+	margin-top: 10px;
+	}
+.leaflet-bottom .leaflet-control {
+	margin-bottom: 10px;
+	}
+.leaflet-left .leaflet-control {
+	margin-left: 10px;
+	}
+.leaflet-right .leaflet-control {
+	margin-right: 10px;
+	}
+
+
+/* zoom and fade animations */
+
+.leaflet-fade-anim .leaflet-tile,
+.leaflet-fade-anim .leaflet-popup {
+	opacity: 0;
+	-webkit-transition: opacity 0.2s linear;
+	   -moz-transition: opacity 0.2s linear;
+	     -o-transition: opacity 0.2s linear;
+	        transition: opacity 0.2s linear;
+	}
+.leaflet-fade-anim .leaflet-tile-loaded,
+.leaflet-fade-anim .leaflet-map-pane .leaflet-popup {
+	opacity: 1;
+	}
+
+.leaflet-zoom-anim .leaflet-zoom-animated {
+	-webkit-transition: -webkit-transform 0.25s cubic-bezier(0,0,0.25,1);
+	   -moz-transition:    -moz-transform 0.25s cubic-bezier(0,0,0.25,1);
+	     -o-transition:      -o-transform 0.25s cubic-bezier(0,0,0.25,1);
+	        transition:         transform 0.25s cubic-bezier(0,0,0.25,1);
+	}
+.leaflet-zoom-anim .leaflet-tile,
+.leaflet-pan-anim .leaflet-tile,
+.leaflet-touching .leaflet-zoom-animated {
+	-webkit-transition: none;
+	   -moz-transition: none;
+	     -o-transition: none;
+	        transition: none;
+	}
+
+.leaflet-zoom-anim .leaflet-zoom-hide {
+	visibility: hidden;
+	}
+
+
+/* cursors */
+
+.leaflet-clickable {
+	cursor: pointer;
+	}
+.leaflet-container {
+	cursor: -webkit-grab;
+	cursor:    -moz-grab;
+	}
+.leaflet-popup-pane,
+.leaflet-control {
+	cursor: auto;
+	}
+.leaflet-dragging .leaflet-container,
+.leaflet-dragging .leaflet-clickable {
+	cursor: move;
+	cursor: -webkit-grabbing;
+	cursor:    -moz-grabbing;
+	}
+
+
+/* visual tweaks */
+
+.leaflet-container {
+	background: #ddd;
+	outline: 0;
+	}
+.leaflet-container a {
+	color: #0078A8;
+	}
+.leaflet-container a.leaflet-active {
+	outline: 2px solid orange;
+	}
+.leaflet-zoom-box {
+	border: 2px dotted #38f;
+	background: rgba(255,255,255,0.5);
+	}
+
+
+/* general typography */
+.leaflet-container {
+	font: 12px/1.5 "Helvetica Neue", Arial, Helvetica, sans-serif;
+	}
+
+
+/* general toolbar styles */
+
+.leaflet-bar {
+	box-shadow: 0 1px 5px rgba(0,0,0,0.65);
+	border-radius: 4px;
+	}
+.leaflet-bar a,
+.leaflet-bar a:hover {
+	background-color: #fff;
+	border-bottom: 1px solid #ccc;
+	width: 26px;
+	height: 26px;
+	line-height: 26px;
+	display: block;
+	text-align: center;
+	text-decoration: none;
+	color: black;
+	}
+.leaflet-bar a,
+.leaflet-control-layers-toggle {
+	background-position: 50% 50%;
+	background-repeat: no-repeat;
+	display: block;
+	}
+.leaflet-bar a:hover {
+	background-color: #f4f4f4;
+	}
+.leaflet-bar a:first-child {
+	border-top-left-radius: 4px;
+	border-top-right-radius: 4px;
+	}
+.leaflet-bar a:last-child {
+	border-bottom-left-radius: 4px;
+	border-bottom-right-radius: 4px;
+	border-bottom: none;
+	}
+.leaflet-bar a.leaflet-disabled {
+	cursor: default;
+	background-color: #f4f4f4;
+	color: #bbb;
+	}
+
+.leaflet-touch .leaflet-bar a {
+	width: 30px;
+	height: 30px;
+	line-height: 30px;
+	}
+
+
+/* zoom control */
+
+.leaflet-control-zoom-in,
+.leaflet-control-zoom-out {
+	font: bold 18px 'Lucida Console', Monaco, monospace;
+	text-indent: 1px;
+	}
+.leaflet-control-zoom-out {
+	font-size: 20px;
+	}
+
+.leaflet-touch .leaflet-control-zoom-in {
+	font-size: 22px;
+	}
+.leaflet-touch .leaflet-control-zoom-out {
+	font-size: 24px;
+	}
+
+
+/* layers control */
+
+.leaflet-control-layers {
+	box-shadow: 0 1px 5px rgba(0,0,0,0.4);
+	background: #fff;
+	border-radius: 5px;
+	}
+.leaflet-control-layers-toggle {
+	background-image: url(images/layers.png);
+	width: 36px;
+	height: 36px;
+	}
+.leaflet-retina .leaflet-control-layers-toggle {
+	background-image: url(images/layers-2x.png);
+	background-size: 26px 26px;
+	}
+.leaflet-touch .leaflet-control-layers-toggle {
+	width: 44px;
+	height: 44px;
+	}
+.leaflet-control-layers .leaflet-control-layers-list,
+.leaflet-control-layers-expanded .leaflet-control-layers-toggle {
+	display: none;
+	}
+.leaflet-control-layers-expanded .leaflet-control-layers-list {
+	display: block;
+	position: relative;
+	}
+.leaflet-control-layers-expanded {
+	padding: 6px 10px 6px 6px;
+	color: #333;
+	background: #fff;
+	}
+.leaflet-control-layers-selector {
+	margin-top: 2px;
+	position: relative;
+	top: 1px;
+	}
+.leaflet-control-layers label {
+	display: block;
+	}
+.leaflet-control-layers-separator {
+	height: 0;
+	border-top: 1px solid #ddd;
+	margin: 5px -10px 5px -6px;
+	}
+
+
+/* attribution and scale controls */
+
+.leaflet-container .leaflet-control-attribution {
+	background: #fff;
+	background: rgba(255, 255, 255, 0.7);
+	margin: 0;
+	}
+.leaflet-control-attribution,
+.leaflet-control-scale-line {
+	padding: 0 5px;
+	color: #333;
+	}
+.leaflet-control-attribution a {
+	text-decoration: none;
+	}
+.leaflet-control-attribution a:hover {
+	text-decoration: underline;
+	}
+.leaflet-container .leaflet-control-attribution,
+.leaflet-container .leaflet-control-scale {
+	font-size: 11px;
+	}
+.leaflet-left .leaflet-control-scale {
+	margin-left: 5px;
+	}
+.leaflet-bottom .leaflet-control-scale {
+	margin-bottom: 5px;
+	}
+.leaflet-control-scale-line {
+	border: 2px solid #777;
+	border-top: none;
+	line-height: 1.1;
+	padding: 2px 5px 1px;
+	font-size: 11px;
+	white-space: nowrap;
+	overflow: hidden;
+	-moz-box-sizing: content-box;
+	     box-sizing: content-box;
+
+	background: #fff;
+	background: rgba(255, 255, 255, 0.5);
+	}
+.leaflet-control-scale-line:not(:first-child) {
+	border-top: 2px solid #777;
+	border-bottom: none;
+	margin-top: -2px;
+	}
+.leaflet-control-scale-line:not(:first-child):not(:last-child) {
+	border-bottom: 2px solid #777;
+	}
+
+.leaflet-touch .leaflet-control-attribution,
+.leaflet-touch .leaflet-control-layers,
+.leaflet-touch .leaflet-bar {
+	box-shadow: none;
+	}
+.leaflet-touch .leaflet-control-layers,
+.leaflet-touch .leaflet-bar {
+	border: 2px solid rgba(0,0,0,0.2);
+	background-clip: padding-box;
+	}
+
+
+/* popup */
+
+.leaflet-popup {
+	position: absolute;
+	text-align: center;
+	}
+.leaflet-popup-content-wrapper {
+	padding: 1px;
+	text-align: left;
+	border-radius: 12px;
+	}
+.leaflet-popup-content {
+	margin: 13px 19px;
+	line-height: 1.4;
+	}
+.leaflet-popup-content p {
+	margin: 18px 0;
+	}
+.leaflet-popup-tip-container {
+	margin: 0 auto;
+	width: 40px;
+	height: 20px;
+	position: relative;
+	overflow: hidden;
+	}
+.leaflet-popup-tip {
+	width: 17px;
+	height: 17px;
+	padding: 1px;
+
+	margin: -10px auto 0;
+
+	-webkit-transform: rotate(45deg);
+	   -moz-transform: rotate(45deg);
+	    -ms-transform: rotate(45deg);
+	     -o-transform: rotate(45deg);
+	        transform: rotate(45deg);
+	}
+.leaflet-popup-content-wrapper,
+.leaflet-popup-tip {
+	background: white;
+
+	box-shadow: 0 3px 14px rgba(0,0,0,0.4);
+	}
+.leaflet-container a.leaflet-popup-close-button {
+	position: absolute;
+	top: 0;
+	right: 0;
+	padding: 4px 4px 0 0;
+	text-align: center;
+	width: 18px;
+	height: 14px;
+	font: 16px/14px Tahoma, Verdana, sans-serif;
+	color: #c3c3c3;
+	text-decoration: none;
+	font-weight: bold;
+	background: transparent;
+	}
+.leaflet-container a.leaflet-popup-close-button:hover {
+	color: #999;
+	}
+.leaflet-popup-scrolled {
+	overflow: auto;
+	border-bottom: 1px solid #ddd;
+	border-top: 1px solid #ddd;
+	}
+
+.leaflet-oldie .leaflet-popup-content-wrapper {
+	zoom: 1;
+	}
+.leaflet-oldie .leaflet-popup-tip {
+	width: 24px;
+	margin: 0 auto;
+
+	-ms-filter: "progid:DXImageTransform.Microsoft.Matrix(M11=0.70710678, M12=0.70710678, M21=-0.70710678, M22=0.70710678)";
+	filter: progid:DXImageTransform.Microsoft.Matrix(M11=0.70710678, M12=0.70710678, M21=-0.70710678, M22=0.70710678);
+	}
+.leaflet-oldie .leaflet-popup-tip-container {
+	margin-top: -1px;
+	}
+
+.leaflet-oldie .leaflet-control-zoom,
+.leaflet-oldie .leaflet-control-layers,
+.leaflet-oldie .leaflet-popup-content-wrapper,
+.leaflet-oldie .leaflet-popup-tip {
+	border: 1px solid #999;
+	}
+
+
+/* div icon */
+
+.leaflet-div-icon {
+	background: #fff;
+	border: 1px solid #666;
+	}
diff --git a/tests/osgearth_server/leaflet.js b/tests/osgearth_server/leaflet.js
new file mode 100644
index 0000000..d3d5635
--- /dev/null
+++ b/tests/osgearth_server/leaflet.js
@@ -0,0 +1,9168 @@
+/*
+ Leaflet, a JavaScript library for mobile-friendly interactive maps. http://leafletjs.com
+ (c) 2010-2013, Vladimir Agafonkin
+ (c) 2010-2011, CloudMade
+*/
+(function (window, document, undefined) {
+var oldL = window.L,
+    L = {};
+
+L.version = '0.7.7';
+
+// define Leaflet for Node module pattern loaders, including Browserify
+if (typeof module === 'object' && typeof module.exports === 'object') {
+	module.exports = L;
+
+// define Leaflet as an AMD module
+} else if (typeof define === 'function' && define.amd) {
+	define(L);
+}
+
+// define Leaflet as a global L variable, saving the original L to restore later if needed
+
+L.noConflict = function () {
+	window.L = oldL;
+	return this;
+};
+
+window.L = L;
+
+
+/*
+ * L.Util contains various utility functions used throughout Leaflet code.
+ */
+
+L.Util = {
+	extend: function (dest) { // (Object[, Object, ...]) ->
+		var sources = Array.prototype.slice.call(arguments, 1),
+		    i, j, len, src;
+
+		for (j = 0, len = sources.length; j < len; j++) {
+			src = sources[j] || {};
+			for (i in src) {
+				if (src.hasOwnProperty(i)) {
+					dest[i] = src[i];
+				}
+			}
+		}
+		return dest;
+	},
+
+	bind: function (fn, obj) { // (Function, Object) -> Function
+		var args = arguments.length > 2 ? Array.prototype.slice.call(arguments, 2) : null;
+		return function () {
+			return fn.apply(obj, args || arguments);
+		};
+	},
+
+	stamp: (function () {
+		var lastId = 0,
+		    key = '_leaflet_id';
+		return function (obj) {
+			obj[key] = obj[key] || ++lastId;
+			return obj[key];
+		};
+	}()),
+
+	invokeEach: function (obj, method, context) {
+		var i, args;
+
+		if (typeof obj === 'object') {
+			args = Array.prototype.slice.call(arguments, 3);
+
+			for (i in obj) {
+				method.apply(context, [i, obj[i]].concat(args));
+			}
+			return true;
+		}
+
+		return false;
+	},
+
+	limitExecByInterval: function (fn, time, context) {
+		var lock, execOnUnlock;
+
+		return function wrapperFn() {
+			var args = arguments;
+
+			if (lock) {
+				execOnUnlock = true;
+				return;
+			}
+
+			lock = true;
+
+			setTimeout(function () {
+				lock = false;
+
+				if (execOnUnlock) {
+					wrapperFn.apply(context, args);
+					execOnUnlock = false;
+				}
+			}, time);
+
+			fn.apply(context, args);
+		};
+	},
+
+	falseFn: function () {
+		return false;
+	},
+
+	formatNum: function (num, digits) {
+		var pow = Math.pow(10, digits || 5);
+		return Math.round(num * pow) / pow;
+	},
+
+	trim: function (str) {
+		return str.trim ? str.trim() : str.replace(/^\s+|\s+$/g, '');
+	},
+
+	splitWords: function (str) {
+		return L.Util.trim(str).split(/\s+/);
+	},
+
+	setOptions: function (obj, options) {
+		obj.options = L.extend({}, obj.options, options);
+		return obj.options;
+	},
+
+	getParamString: function (obj, existingUrl, uppercase) {
+		var params = [];
+		for (var i in obj) {
+			params.push(encodeURIComponent(uppercase ? i.toUpperCase() : i) + '=' + encodeURIComponent(obj[i]));
+		}
+		return ((!existingUrl || existingUrl.indexOf('?') === -1) ? '?' : '&') + params.join('&');
+	},
+	template: function (str, data) {
+		return str.replace(/\{ *([\w_]+) *\}/g, function (str, key) {
+			var value = data[key];
+			if (value === undefined) {
+				throw new Error('No value provided for variable ' + str);
+			} else if (typeof value === 'function') {
+				value = value(data);
+			}
+			return value;
+		});
+	},
+
+	isArray: Array.isArray || function (obj) {
+		return (Object.prototype.toString.call(obj) === '[object Array]');
+	},
+
+	emptyImageUrl: 'data:image/gif;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs='
+};
+
+(function () {
+
+	// inspired by http://paulirish.com/2011/requestanimationframe-for-smart-animating/
+
+	function getPrefixed(name) {
+		var i, fn,
+		    prefixes = ['webkit', 'moz', 'o', 'ms'];
+
+		for (i = 0; i < prefixes.length && !fn; i++) {
+			fn = window[prefixes[i] + name];
+		}
+
+		return fn;
+	}
+
+	var lastTime = 0;
+
+	function timeoutDefer(fn) {
+		var time = +new Date(),
+		    timeToCall = Math.max(0, 16 - (time - lastTime));
+
+		lastTime = time + timeToCall;
+		return window.setTimeout(fn, timeToCall);
+	}
+
+	var requestFn = window.requestAnimationFrame ||
+	        getPrefixed('RequestAnimationFrame') || timeoutDefer;
+
+	var cancelFn = window.cancelAnimationFrame ||
+	        getPrefixed('CancelAnimationFrame') ||
+	        getPrefixed('CancelRequestAnimationFrame') ||
+	        function (id) { window.clearTimeout(id); };
+
+
+	L.Util.requestAnimFrame = function (fn, context, immediate, element) {
+		fn = L.bind(fn, context);
+
+		if (immediate && requestFn === timeoutDefer) {
+			fn();
+		} else {
+			return requestFn.call(window, fn, element);
+		}
+	};
+
+	L.Util.cancelAnimFrame = function (id) {
+		if (id) {
+			cancelFn.call(window, id);
+		}
+	};
+
+}());
+
+// shortcuts for most used utility functions
+L.extend = L.Util.extend;
+L.bind = L.Util.bind;
+L.stamp = L.Util.stamp;
+L.setOptions = L.Util.setOptions;
+
+
+/*
+ * L.Class powers the OOP facilities of the library.
+ * Thanks to John Resig and Dean Edwards for inspiration!
+ */
+
+L.Class = function () {};
+
+L.Class.extend = function (props) {
+
+	// extended class with the new prototype
+	var NewClass = function () {
+
+		// call the constructor
+		if (this.initialize) {
+			this.initialize.apply(this, arguments);
+		}
+
+		// call all constructor hooks
+		if (this._initHooks) {
+			this.callInitHooks();
+		}
+	};
+
+	// instantiate class without calling constructor
+	var F = function () {};
+	F.prototype = this.prototype;
+
+	var proto = new F();
+	proto.constructor = NewClass;
+
+	NewClass.prototype = proto;
+
+	//inherit parent's statics
+	for (var i in this) {
+		if (this.hasOwnProperty(i) && i !== 'prototype') {
+			NewClass[i] = this[i];
+		}
+	}
+
+	// mix static properties into the class
+	if (props.statics) {
+		L.extend(NewClass, props.statics);
+		delete props.statics;
+	}
+
+	// mix includes into the prototype
+	if (props.includes) {
+		L.Util.extend.apply(null, [proto].concat(props.includes));
+		delete props.includes;
+	}
+
+	// merge options
+	if (props.options && proto.options) {
+		props.options = L.extend({}, proto.options, props.options);
+	}
+
+	// mix given properties into the prototype
+	L.extend(proto, props);
+
+	proto._initHooks = [];
+
+	var parent = this;
+	// jshint camelcase: false
+	NewClass.__super__ = parent.prototype;
+
+	// add method for calling all hooks
+	proto.callInitHooks = function () {
+
+		if (this._initHooksCalled) { return; }
+
+		if (parent.prototype.callInitHooks) {
+			parent.prototype.callInitHooks.call(this);
+		}
+
+		this._initHooksCalled = true;
+
+		for (var i = 0, len = proto._initHooks.length; i < len; i++) {
+			proto._initHooks[i].call(this);
+		}
+	};
+
+	return NewClass;
+};
+
+
+// method for adding properties to prototype
+L.Class.include = function (props) {
+	L.extend(this.prototype, props);
+};
+
+// merge new default options to the Class
+L.Class.mergeOptions = function (options) {
+	L.extend(this.prototype.options, options);
+};
+
+// add a constructor hook
+L.Class.addInitHook = function (fn) { // (Function) || (String, args...)
+	var args = Array.prototype.slice.call(arguments, 1);
+
+	var init = typeof fn === 'function' ? fn : function () {
+		this[fn].apply(this, args);
+	};
+
+	this.prototype._initHooks = this.prototype._initHooks || [];
+	this.prototype._initHooks.push(init);
+};
+
+
+/*
+ * L.Mixin.Events is used to add custom events functionality to Leaflet classes.
+ */
+
+var eventsKey = '_leaflet_events';
+
+L.Mixin = {};
+
+L.Mixin.Events = {
+
+	addEventListener: function (types, fn, context) { // (String, Function[, Object]) or (Object[, Object])
+
+		// types can be a map of types/handlers
+		if (L.Util.invokeEach(types, this.addEventListener, this, fn, context)) { return this; }
+
+		var events = this[eventsKey] = this[eventsKey] || {},
+		    contextId = context && context !== this && L.stamp(context),
+		    i, len, event, type, indexKey, indexLenKey, typeIndex;
+
+		// types can be a string of space-separated words
+		types = L.Util.splitWords(types);
+
+		for (i = 0, len = types.length; i < len; i++) {
+			event = {
+				action: fn,
+				context: context || this
+			};
+			type = types[i];
+
+			if (contextId) {
+				// store listeners of a particular context in a separate hash (if it has an id)
+				// gives a major performance boost when removing thousands of map layers
+
+				indexKey = type + '_idx';
+				indexLenKey = indexKey + '_len';
+
+				typeIndex = events[indexKey] = events[indexKey] || {};
+
+				if (!typeIndex[contextId]) {
+					typeIndex[contextId] = [];
+
+					// keep track of the number of keys in the index to quickly check if it's empty
+					events[indexLenKey] = (events[indexLenKey] || 0) + 1;
+				}
+
+				typeIndex[contextId].push(event);
+
+
+			} else {
+				events[type] = events[type] || [];
+				events[type].push(event);
+			}
+		}
+
+		return this;
+	},
+
+	hasEventListeners: function (type) { // (String) -> Boolean
+		var events = this[eventsKey];
+		return !!events && ((type in events && events[type].length > 0) ||
+		                    (type + '_idx' in events && events[type + '_idx_len'] > 0));
+	},
+
+	removeEventListener: function (types, fn, context) { // ([String, Function, Object]) or (Object[, Object])
+
+		if (!this[eventsKey]) {
+			return this;
+		}
+
+		if (!types) {
+			return this.clearAllEventListeners();
+		}
+
+		if (L.Util.invokeEach(types, this.removeEventListener, this, fn, context)) { return this; }
+
+		var events = this[eventsKey],
+		    contextId = context && context !== this && L.stamp(context),
+		    i, len, type, listeners, j, indexKey, indexLenKey, typeIndex, removed;
+
+		types = L.Util.splitWords(types);
+
+		for (i = 0, len = types.length; i < len; i++) {
+			type = types[i];
+			indexKey = type + '_idx';
+			indexLenKey = indexKey + '_len';
+
+			typeIndex = events[indexKey];
+
+			if (!fn) {
+				// clear all listeners for a type if function isn't specified
+				delete events[type];
+				delete events[indexKey];
+				delete events[indexLenKey];
+
+			} else {
+				listeners = contextId && typeIndex ? typeIndex[contextId] : events[type];
+
+				if (listeners) {
+					for (j = listeners.length - 1; j >= 0; j--) {
+						if ((listeners[j].action === fn) && (!context || (listeners[j].context === context))) {
+							removed = listeners.splice(j, 1);
+							// set the old action to a no-op, because it is possible
+							// that the listener is being iterated over as part of a dispatch
+							removed[0].action = L.Util.falseFn;
+						}
+					}
+
+					if (context && typeIndex && (listeners.length === 0)) {
+						delete typeIndex[contextId];
+						events[indexLenKey]--;
+					}
+				}
+			}
+		}
+
+		return this;
+	},
+
+	clearAllEventListeners: function () {
+		delete this[eventsKey];
+		return this;
+	},
+
+	fireEvent: function (type, data) { // (String[, Object])
+		if (!this.hasEventListeners(type)) {
+			return this;
+		}
+
+		var event = L.Util.extend({}, data, { type: type, target: this });
+
+		var events = this[eventsKey],
+		    listeners, i, len, typeIndex, contextId;
+
+		if (events[type]) {
+			// make sure adding/removing listeners inside other listeners won't cause infinite loop
+			listeners = events[type].slice();
+
+			for (i = 0, len = listeners.length; i < len; i++) {
+				listeners[i].action.call(listeners[i].context, event);
+			}
+		}
+
+		// fire event for the context-indexed listeners as well
+		typeIndex = events[type + '_idx'];
+
+		for (contextId in typeIndex) {
+			listeners = typeIndex[contextId].slice();
+
+			if (listeners) {
+				for (i = 0, len = listeners.length; i < len; i++) {
+					listeners[i].action.call(listeners[i].context, event);
+				}
+			}
+		}
+
+		return this;
+	},
+
+	addOneTimeEventListener: function (types, fn, context) {
+
+		if (L.Util.invokeEach(types, this.addOneTimeEventListener, this, fn, context)) { return this; }
+
+		var handler = L.bind(function () {
+			this
+			    .removeEventListener(types, fn, context)
+			    .removeEventListener(types, handler, context);
+		}, this);
+
+		return this
+		    .addEventListener(types, fn, context)
+		    .addEventListener(types, handler, context);
+	}
+};
+
+L.Mixin.Events.on = L.Mixin.Events.addEventListener;
+L.Mixin.Events.off = L.Mixin.Events.removeEventListener;
+L.Mixin.Events.once = L.Mixin.Events.addOneTimeEventListener;
+L.Mixin.Events.fire = L.Mixin.Events.fireEvent;
+
+
+/*
+ * L.Browser handles different browser and feature detections for internal Leaflet use.
+ */
+
+(function () {
+
+	var ie = 'ActiveXObject' in window,
+		ielt9 = ie && !document.addEventListener,
+
+	    // terrible browser detection to work around Safari / iOS / Android browser bugs
+	    ua = navigator.userAgent.toLowerCase(),
+	    webkit = ua.indexOf('webkit') !== -1,
+	    chrome = ua.indexOf('chrome') !== -1,
+	    phantomjs = ua.indexOf('phantom') !== -1,
+	    android = ua.indexOf('android') !== -1,
+	    android23 = ua.search('android [23]') !== -1,
+		gecko = ua.indexOf('gecko') !== -1,
+
+	    mobile = typeof orientation !== undefined + '',
+	    msPointer = !window.PointerEvent && window.MSPointerEvent,
+		pointer = (window.PointerEvent && window.navigator.pointerEnabled) ||
+				  msPointer,
+	    retina = ('devicePixelRatio' in window && window.devicePixelRatio > 1) ||
+	             ('matchMedia' in window && window.matchMedia('(min-resolution:144dpi)') &&
+	              window.matchMedia('(min-resolution:144dpi)').matches),
+
+	    doc = document.documentElement,
+	    ie3d = ie && ('transition' in doc.style),
+	    webkit3d = ('WebKitCSSMatrix' in window) && ('m11' in new window.WebKitCSSMatrix()) && !android23,
+	    gecko3d = 'MozPerspective' in doc.style,
+	    opera3d = 'OTransition' in doc.style,
+	    any3d = !window.L_DISABLE_3D && (ie3d || webkit3d || gecko3d || opera3d) && !phantomjs;
+
+	var touch = !window.L_NO_TOUCH && !phantomjs && (pointer || 'ontouchstart' in window ||
+		(window.DocumentTouch && document instanceof window.DocumentTouch));
+
+	L.Browser = {
+		ie: ie,
+		ielt9: ielt9,
+		webkit: webkit,
+		gecko: gecko && !webkit && !window.opera && !ie,
+
+		android: android,
+		android23: android23,
+
+		chrome: chrome,
+
+		ie3d: ie3d,
+		webkit3d: webkit3d,
+		gecko3d: gecko3d,
+		opera3d: opera3d,
+		any3d: any3d,
+
+		mobile: mobile,
+		mobileWebkit: mobile && webkit,
+		mobileWebkit3d: mobile && webkit3d,
+		mobileOpera: mobile && window.opera,
+
+		touch: touch,
+		msPointer: msPointer,
+		pointer: pointer,
+
+		retina: retina
+	};
+
+}());
+
+
+/*
+ * L.Point represents a point with x and y coordinates.
+ */
+
+L.Point = function (/*Number*/ x, /*Number*/ y, /*Boolean*/ round) {
+	this.x = (round ? Math.round(x) : x);
+	this.y = (round ? Math.round(y) : y);
+};
+
+L.Point.prototype = {
+
+	clone: function () {
+		return new L.Point(this.x, this.y);
+	},
+
+	// non-destructive, returns a new point
+	add: function (point) {
+		return this.clone()._add(L.point(point));
+	},
+
+	// destructive, used directly for performance in situations where it's safe to modify existing point
+	_add: function (point) {
+		this.x += point.x;
+		this.y += point.y;
+		return this;
+	},
+
+	subtract: function (point) {
+		return this.clone()._subtract(L.point(point));
+	},
+
+	_subtract: function (point) {
+		this.x -= point.x;
+		this.y -= point.y;
+		return this;
+	},
+
+	divideBy: function (num) {
+		return this.clone()._divideBy(num);
+	},
+
+	_divideBy: function (num) {
+		this.x /= num;
+		this.y /= num;
+		return this;
+	},
+
+	multiplyBy: function (num) {
+		return this.clone()._multiplyBy(num);
+	},
+
+	_multiplyBy: function (num) {
+		this.x *= num;
+		this.y *= num;
+		return this;
+	},
+
+	round: function () {
+		return this.clone()._round();
+	},
+
+	_round: function () {
+		this.x = Math.round(this.x);
+		this.y = Math.round(this.y);
+		return this;
+	},
+
+	floor: function () {
+		return this.clone()._floor();
+	},
+
+	_floor: function () {
+		this.x = Math.floor(this.x);
+		this.y = Math.floor(this.y);
+		return this;
+	},
+
+	distanceTo: function (point) {
+		point = L.point(point);
+
+		var x = point.x - this.x,
+		    y = point.y - this.y;
+
+		return Math.sqrt(x * x + y * y);
+	},
+
+	equals: function (point) {
+		point = L.point(point);
+
+		return point.x === this.x &&
+		       point.y === this.y;
+	},
+
+	contains: function (point) {
+		point = L.point(point);
+
+		return Math.abs(point.x) <= Math.abs(this.x) &&
+		       Math.abs(point.y) <= Math.abs(this.y);
+	},
+
+	toString: function () {
+		return 'Point(' +
+		        L.Util.formatNum(this.x) + ', ' +
+		        L.Util.formatNum(this.y) + ')';
+	}
+};
+
+L.point = function (x, y, round) {
+	if (x instanceof L.Point) {
+		return x;
+	}
+	if (L.Util.isArray(x)) {
+		return new L.Point(x[0], x[1]);
+	}
+	if (x === undefined || x === null) {
+		return x;
+	}
+	return new L.Point(x, y, round);
+};
+
+
+/*
+ * L.Bounds represents a rectangular area on the screen in pixel coordinates.
+ */
+
+L.Bounds = function (a, b) { //(Point, Point) or Point[]
+	if (!a) { return; }
+
+	var points = b ? [a, b] : a;
+
+	for (var i = 0, len = points.length; i < len; i++) {
+		this.extend(points[i]);
+	}
+};
+
+L.Bounds.prototype = {
+	// extend the bounds to contain the given point
+	extend: function (point) { // (Point)
+		point = L.point(point);
+
+		if (!this.min && !this.max) {
+			this.min = point.clone();
+			this.max = point.clone();
+		} else {
+			this.min.x = Math.min(point.x, this.min.x);
+			this.max.x = Math.max(point.x, this.max.x);
+			this.min.y = Math.min(point.y, this.min.y);
+			this.max.y = Math.max(point.y, this.max.y);
+		}
+		return this;
+	},
+
+	getCenter: function (round) { // (Boolean) -> Point
+		return new L.Point(
+		        (this.min.x + this.max.x) / 2,
+		        (this.min.y + this.max.y) / 2, round);
+	},
+
+	getBottomLeft: function () { // -> Point
+		return new L.Point(this.min.x, this.max.y);
+	},
+
+	getTopRight: function () { // -> Point
+		return new L.Point(this.max.x, this.min.y);
+	},
+
+	getSize: function () {
+		return this.max.subtract(this.min);
+	},
+
+	contains: function (obj) { // (Bounds) or (Point) -> Boolean
+		var min, max;
+
+		if (typeof obj[0] === 'number' || obj instanceof L.Point) {
+			obj = L.point(obj);
+		} else {
+			obj = L.bounds(obj);
+		}
+
+		if (obj instanceof L.Bounds) {
+			min = obj.min;
+			max = obj.max;
+		} else {
+			min = max = obj;
+		}
+
+		return (min.x >= this.min.x) &&
+		       (max.x <= this.max.x) &&
+		       (min.y >= this.min.y) &&
+		       (max.y <= this.max.y);
+	},
+
+	intersects: function (bounds) { // (Bounds) -> Boolean
+		bounds = L.bounds(bounds);
+
+		var min = this.min,
+		    max = this.max,
+		    min2 = bounds.min,
+		    max2 = bounds.max,
+		    xIntersects = (max2.x >= min.x) && (min2.x <= max.x),
+		    yIntersects = (max2.y >= min.y) && (min2.y <= max.y);
+
+		return xIntersects && yIntersects;
+	},
+
+	isValid: function () {
+		return !!(this.min && this.max);
+	}
+};
+
+L.bounds = function (a, b) { // (Bounds) or (Point, Point) or (Point[])
+	if (!a || a instanceof L.Bounds) {
+		return a;
+	}
+	return new L.Bounds(a, b);
+};
+
+
+/*
+ * L.Transformation is an utility class to perform simple point transformations through a 2d-matrix.
+ */
+
+L.Transformation = function (a, b, c, d) {
+	this._a = a;
+	this._b = b;
+	this._c = c;
+	this._d = d;
+};
+
+L.Transformation.prototype = {
+	transform: function (point, scale) { // (Point, Number) -> Point
+		return this._transform(point.clone(), scale);
+	},
+
+	// destructive transform (faster)
+	_transform: function (point, scale) {
+		scale = scale || 1;
+		point.x = scale * (this._a * point.x + this._b);
+		point.y = scale * (this._c * point.y + this._d);
+		return point;
+	},
+
+	untransform: function (point, scale) {
+		scale = scale || 1;
+		return new L.Point(
+		        (point.x / scale - this._b) / this._a,
+		        (point.y / scale - this._d) / this._c);
+	}
+};
+
+
+/*
+ * L.DomUtil contains various utility functions for working with DOM.
+ */
+
+L.DomUtil = {
+	get: function (id) {
+		return (typeof id === 'string' ? document.getElementById(id) : id);
+	},
+
+	getStyle: function (el, style) {
+
+		var value = el.style[style];
+
+		if (!value && el.currentStyle) {
+			value = el.currentStyle[style];
+		}
+
+		if ((!value || value === 'auto') && document.defaultView) {
+			var css = document.defaultView.getComputedStyle(el, null);
+			value = css ? css[style] : null;
+		}
+
+		return value === 'auto' ? null : value;
+	},
+
+	getViewportOffset: function (element) {
+
+		var top = 0,
+		    left = 0,
+		    el = element,
+		    docBody = document.body,
+		    docEl = document.documentElement,
+		    pos;
+
+		do {
+			top  += el.offsetTop  || 0;
+			left += el.offsetLeft || 0;
+
+			//add borders
+			top += parseInt(L.DomUtil.getStyle(el, 'borderTopWidth'), 10) || 0;
+			left += parseInt(L.DomUtil.getStyle(el, 'borderLeftWidth'), 10) || 0;
+
+			pos = L.DomUtil.getStyle(el, 'position');
+
+			if (el.offsetParent === docBody && pos === 'absolute') { break; }
+
+			if (pos === 'fixed') {
+				top  += docBody.scrollTop  || docEl.scrollTop  || 0;
+				left += docBody.scrollLeft || docEl.scrollLeft || 0;
+				break;
+			}
+
+			if (pos === 'relative' && !el.offsetLeft) {
+				var width = L.DomUtil.getStyle(el, 'width'),
+				    maxWidth = L.DomUtil.getStyle(el, 'max-width'),
+				    r = el.getBoundingClientRect();
+
+				if (width !== 'none' || maxWidth !== 'none') {
+					left += r.left + el.clientLeft;
+				}
+
+				//calculate full y offset since we're breaking out of the loop
+				top += r.top + (docBody.scrollTop  || docEl.scrollTop  || 0);
+
+				break;
+			}
+
+			el = el.offsetParent;
+
+		} while (el);
+
+		el = element;
+
+		do {
+			if (el === docBody) { break; }
+
+			top  -= el.scrollTop  || 0;
+			left -= el.scrollLeft || 0;
+
+			el = el.parentNode;
+		} while (el);
+
+		return new L.Point(left, top);
+	},
+
+	documentIsLtr: function () {
+		if (!L.DomUtil._docIsLtrCached) {
+			L.DomUtil._docIsLtrCached = true;
+			L.DomUtil._docIsLtr = L.DomUtil.getStyle(document.body, 'direction') === 'ltr';
+		}
+		return L.DomUtil._docIsLtr;
+	},
+
+	create: function (tagName, className, container) {
+
+		var el = document.createElement(tagName);
+		el.className = className;
+
+		if (container) {
+			container.appendChild(el);
+		}
+
+		return el;
+	},
+
+	hasClass: function (el, name) {
+		if (el.classList !== undefined) {
+			return el.classList.contains(name);
+		}
+		var className = L.DomUtil._getClass(el);
+		return className.length > 0 && new RegExp('(^|\\s)' + name + '(\\s|$)').test(className);
+	},
+
+	addClass: function (el, name) {
+		if (el.classList !== undefined) {
+			var classes = L.Util.splitWords(name);
+			for (var i = 0, len = classes.length; i < len; i++) {
+				el.classList.add(classes[i]);
+			}
+		} else if (!L.DomUtil.hasClass(el, name)) {
+			var className = L.DomUtil._getClass(el);
+			L.DomUtil._setClass(el, (className ? className + ' ' : '') + name);
+		}
+	},
+
+	removeClass: function (el, name) {
+		if (el.classList !== undefined) {
+			el.classList.remove(name);
+		} else {
+			L.DomUtil._setClass(el, L.Util.trim((' ' + L.DomUtil._getClass(el) + ' ').replace(' ' + name + ' ', ' ')));
+		}
+	},
+
+	_setClass: function (el, name) {
+		if (el.className.baseVal === undefined) {
+			el.className = name;
+		} else {
+			// in case of SVG element
+			el.className.baseVal = name;
+		}
+	},
+
+	_getClass: function (el) {
+		return el.className.baseVal === undefined ? el.className : el.className.baseVal;
+	},
+
+	setOpacity: function (el, value) {
+
+		if ('opacity' in el.style) {
+			el.style.opacity = value;
+
+		} else if ('filter' in el.style) {
+
+			var filter = false,
+			    filterName = 'DXImageTransform.Microsoft.Alpha';
+
+			// filters collection throws an error if we try to retrieve a filter that doesn't exist
+			try {
+				filter = el.filters.item(filterName);
+			} catch (e) {
+				// don't set opacity to 1 if we haven't already set an opacity,
+				// it isn't needed and breaks transparent pngs.
+				if (value === 1) { return; }
+			}
+
+			value = Math.round(value * 100);
+
+			if (filter) {
+				filter.Enabled = (value !== 100);
+				filter.Opacity = value;
+			} else {
+				el.style.filter += ' progid:' + filterName + '(opacity=' + value + ')';
+			}
+		}
+	},
+
+	testProp: function (props) {
+
+		var style = document.documentElement.style;
+
+		for (var i = 0; i < props.length; i++) {
+			if (props[i] in style) {
+				return props[i];
+			}
+		}
+		return false;
+	},
+
+	getTranslateString: function (point) {
+		// on WebKit browsers (Chrome/Safari/iOS Safari/Android) using translate3d instead of translate
+		// makes animation smoother as it ensures HW accel is used. Firefox 13 doesn't care
+		// (same speed either way), Opera 12 doesn't support translate3d
+
+		var is3d = L.Browser.webkit3d,
+		    open = 'translate' + (is3d ? '3d' : '') + '(',
+		    close = (is3d ? ',0' : '') + ')';
+
+		return open + point.x + 'px,' + point.y + 'px' + close;
+	},
+
+	getScaleString: function (scale, origin) {
+
+		var preTranslateStr = L.DomUtil.getTranslateString(origin.add(origin.multiplyBy(-1 * scale))),
+		    scaleStr = ' scale(' + scale + ') ';
+
+		return preTranslateStr + scaleStr;
+	},
+
+	setPosition: function (el, point, disable3D) { // (HTMLElement, Point[, Boolean])
+
+		// jshint camelcase: false
+		el._leaflet_pos = point;
+
+		if (!disable3D && L.Browser.any3d) {
+			el.style[L.DomUtil.TRANSFORM] =  L.DomUtil.getTranslateString(point);
+		} else {
+			el.style.left = point.x + 'px';
+			el.style.top = point.y + 'px';
+		}
+	},
+
+	getPosition: function (el) {
+		// this method is only used for elements previously positioned using setPosition,
+		// so it's safe to cache the position for performance
+
+		// jshint camelcase: false
+		return el._leaflet_pos;
+	}
+};
+
+
+// prefix style property names
+
+L.DomUtil.TRANSFORM = L.DomUtil.testProp(
+        ['transform', 'WebkitTransform', 'OTransform', 'MozTransform', 'msTransform']);
+
+// webkitTransition comes first because some browser versions that drop vendor prefix don't do
+// the same for the transitionend event, in particular the Android 4.1 stock browser
+
+L.DomUtil.TRANSITION = L.DomUtil.testProp(
+        ['webkitTransition', 'transition', 'OTransition', 'MozTransition', 'msTransition']);
+
+L.DomUtil.TRANSITION_END =
+        L.DomUtil.TRANSITION === 'webkitTransition' || L.DomUtil.TRANSITION === 'OTransition' ?
+        L.DomUtil.TRANSITION + 'End' : 'transitionend';
+
+(function () {
+    if ('onselectstart' in document) {
+        L.extend(L.DomUtil, {
+            disableTextSelection: function () {
+                L.DomEvent.on(window, 'selectstart', L.DomEvent.preventDefault);
+            },
+
+            enableTextSelection: function () {
+                L.DomEvent.off(window, 'selectstart', L.DomEvent.preventDefault);
+            }
+        });
+    } else {
+        var userSelectProperty = L.DomUtil.testProp(
+            ['userSelect', 'WebkitUserSelect', 'OUserSelect', 'MozUserSelect', 'msUserSelect']);
+
+        L.extend(L.DomUtil, {
+            disableTextSelection: function () {
+                if (userSelectProperty) {
+                    var style = document.documentElement.style;
+                    this._userSelect = style[userSelectProperty];
+                    style[userSelectProperty] = 'none';
+                }
+            },
+
+            enableTextSelection: function () {
+                if (userSelectProperty) {
+                    document.documentElement.style[userSelectProperty] = this._userSelect;
+                    delete this._userSelect;
+                }
+            }
+        });
+    }
+
+	L.extend(L.DomUtil, {
+		disableImageDrag: function () {
+			L.DomEvent.on(window, 'dragstart', L.DomEvent.preventDefault);
+		},
+
+		enableImageDrag: function () {
+			L.DomEvent.off(window, 'dragstart', L.DomEvent.preventDefault);
+		}
+	});
+})();
+
+
+/*
+ * L.LatLng represents a geographical point with latitude and longitude coordinates.
+ */
+
+L.LatLng = function (lat, lng, alt) { // (Number, Number, Number)
+	lat = parseFloat(lat);
+	lng = parseFloat(lng);
+
+	if (isNaN(lat) || isNaN(lng)) {
+		throw new Error('Invalid LatLng object: (' + lat + ', ' + lng + ')');
+	}
+
+	this.lat = lat;
+	this.lng = lng;
+
+	if (alt !== undefined) {
+		this.alt = parseFloat(alt);
+	}
+};
+
+L.extend(L.LatLng, {
+	DEG_TO_RAD: Math.PI / 180,
+	RAD_TO_DEG: 180 / Math.PI,
+	MAX_MARGIN: 1.0E-9 // max margin of error for the "equals" check
+});
+
+L.LatLng.prototype = {
+	equals: function (obj) { // (LatLng) -> Boolean
+		if (!obj) { return false; }
+
+		obj = L.latLng(obj);
+
+		var margin = Math.max(
+		        Math.abs(this.lat - obj.lat),
+		        Math.abs(this.lng - obj.lng));
+
+		return margin <= L.LatLng.MAX_MARGIN;
+	},
+
+	toString: function (precision) { // (Number) -> String
+		return 'LatLng(' +
+		        L.Util.formatNum(this.lat, precision) + ', ' +
+		        L.Util.formatNum(this.lng, precision) + ')';
+	},
+
+	// Haversine distance formula, see http://en.wikipedia.org/wiki/Haversine_formula
+	// TODO move to projection code, LatLng shouldn't know about Earth
+	distanceTo: function (other) { // (LatLng) -> Number
+		other = L.latLng(other);
+
+		var R = 6378137, // earth radius in meters
+		    d2r = L.LatLng.DEG_TO_RAD,
+		    dLat = (other.lat - this.lat) * d2r,
+		    dLon = (other.lng - this.lng) * d2r,
+		    lat1 = this.lat * d2r,
+		    lat2 = other.lat * d2r,
+		    sin1 = Math.sin(dLat / 2),
+		    sin2 = Math.sin(dLon / 2);
+
+		var a = sin1 * sin1 + sin2 * sin2 * Math.cos(lat1) * Math.cos(lat2);
+
+		return R * 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
+	},
+
+	wrap: function (a, b) { // (Number, Number) -> LatLng
+		var lng = this.lng;
+
+		a = a || -180;
+		b = b ||  180;
+
+		lng = (lng + b) % (b - a) + (lng < a || lng === b ? b : a);
+
+		return new L.LatLng(this.lat, lng);
+	}
+};
+
+L.latLng = function (a, b) { // (LatLng) or ([Number, Number]) or (Number, Number)
+	if (a instanceof L.LatLng) {
+		return a;
+	}
+	if (L.Util.isArray(a)) {
+		if (typeof a[0] === 'number' || typeof a[0] === 'string') {
+			return new L.LatLng(a[0], a[1], a[2]);
+		} else {
+			return null;
+		}
+	}
+	if (a === undefined || a === null) {
+		return a;
+	}
+	if (typeof a === 'object' && 'lat' in a) {
+		return new L.LatLng(a.lat, 'lng' in a ? a.lng : a.lon);
+	}
+	if (b === undefined) {
+		return null;
+	}
+	return new L.LatLng(a, b);
+};
+
+
+
+/*
+ * L.LatLngBounds represents a rectangular area on the map in geographical coordinates.
+ */
+
+L.LatLngBounds = function (southWest, northEast) { // (LatLng, LatLng) or (LatLng[])
+	if (!southWest) { return; }
+
+	var latlngs = northEast ? [southWest, northEast] : southWest;
+
+	for (var i = 0, len = latlngs.length; i < len; i++) {
+		this.extend(latlngs[i]);
+	}
+};
+
+L.LatLngBounds.prototype = {
+	// extend the bounds to contain the given point or bounds
+	extend: function (obj) { // (LatLng) or (LatLngBounds)
+		if (!obj) { return this; }
+
+		var latLng = L.latLng(obj);
+		if (latLng !== null) {
+			obj = latLng;
+		} else {
+			obj = L.latLngBounds(obj);
+		}
+
+		if (obj instanceof L.LatLng) {
+			if (!this._southWest && !this._northEast) {
+				this._southWest = new L.LatLng(obj.lat, obj.lng);
+				this._northEast = new L.LatLng(obj.lat, obj.lng);
+			} else {
+				this._southWest.lat = Math.min(obj.lat, this._southWest.lat);
+				this._southWest.lng = Math.min(obj.lng, this._southWest.lng);
+
+				this._northEast.lat = Math.max(obj.lat, this._northEast.lat);
+				this._northEast.lng = Math.max(obj.lng, this._northEast.lng);
+			}
+		} else if (obj instanceof L.LatLngBounds) {
+			this.extend(obj._southWest);
+			this.extend(obj._northEast);
+		}
+		return this;
+	},
+
+	// extend the bounds by a percentage
+	pad: function (bufferRatio) { // (Number) -> LatLngBounds
+		var sw = this._southWest,
+		    ne = this._northEast,
+		    heightBuffer = Math.abs(sw.lat - ne.lat) * bufferRatio,
+		    widthBuffer = Math.abs(sw.lng - ne.lng) * bufferRatio;
+
+		return new L.LatLngBounds(
+		        new L.LatLng(sw.lat - heightBuffer, sw.lng - widthBuffer),
+		        new L.LatLng(ne.lat + heightBuffer, ne.lng + widthBuffer));
+	},
+
+	getCenter: function () { // -> LatLng
+		return new L.LatLng(
+		        (this._southWest.lat + this._northEast.lat) / 2,
+		        (this._southWest.lng + this._northEast.lng) / 2);
+	},
+
+	getSouthWest: function () {
+		return this._southWest;
+	},
+
+	getNorthEast: function () {
+		return this._northEast;
+	},
+
+	getNorthWest: function () {
+		return new L.LatLng(this.getNorth(), this.getWest());
+	},
+
+	getSouthEast: function () {
+		return new L.LatLng(this.getSouth(), this.getEast());
+	},
+
+	getWest: function () {
+		return this._southWest.lng;
+	},
+
+	getSouth: function () {
+		return this._southWest.lat;
+	},
+
+	getEast: function () {
+		return this._northEast.lng;
+	},
+
+	getNorth: function () {
+		return this._northEast.lat;
+	},
+
+	contains: function (obj) { // (LatLngBounds) or (LatLng) -> Boolean
+		if (typeof obj[0] === 'number' || obj instanceof L.LatLng) {
+			obj = L.latLng(obj);
+		} else {
+			obj = L.latLngBounds(obj);
+		}
+
+		var sw = this._southWest,
+		    ne = this._northEast,
+		    sw2, ne2;
+
+		if (obj instanceof L.LatLngBounds) {
+			sw2 = obj.getSouthWest();
+			ne2 = obj.getNorthEast();
+		} else {
+			sw2 = ne2 = obj;
+		}
+
+		return (sw2.lat >= sw.lat) && (ne2.lat <= ne.lat) &&
+		       (sw2.lng >= sw.lng) && (ne2.lng <= ne.lng);
+	},
+
+	intersects: function (bounds) { // (LatLngBounds)
+		bounds = L.latLngBounds(bounds);
+
+		var sw = this._southWest,
+		    ne = this._northEast,
+		    sw2 = bounds.getSouthWest(),
+		    ne2 = bounds.getNorthEast(),
+
+		    latIntersects = (ne2.lat >= sw.lat) && (sw2.lat <= ne.lat),
+		    lngIntersects = (ne2.lng >= sw.lng) && (sw2.lng <= ne.lng);
+
+		return latIntersects && lngIntersects;
+	},
+
+	toBBoxString: function () {
+		return [this.getWest(), this.getSouth(), this.getEast(), this.getNorth()].join(',');
+	},
+
+	equals: function (bounds) { // (LatLngBounds)
+		if (!bounds) { return false; }
+
+		bounds = L.latLngBounds(bounds);
+
+		return this._southWest.equals(bounds.getSouthWest()) &&
+		       this._northEast.equals(bounds.getNorthEast());
+	},
+
+	isValid: function () {
+		return !!(this._southWest && this._northEast);
+	}
+};
+
+//TODO International date line?
+
+L.latLngBounds = function (a, b) { // (LatLngBounds) or (LatLng, LatLng)
+	if (!a || a instanceof L.LatLngBounds) {
+		return a;
+	}
+	return new L.LatLngBounds(a, b);
+};
+
+
+/*
+ * L.Projection contains various geographical projections used by CRS classes.
+ */
+
+L.Projection = {};
+
+
+/*
+ * Spherical Mercator is the most popular map projection, used by EPSG:3857 CRS used by default.
+ */
+
+L.Projection.SphericalMercator = {
+	MAX_LATITUDE: 85.0511287798,
+
+	project: function (latlng) { // (LatLng) -> Point
+		var d = L.LatLng.DEG_TO_RAD,
+		    max = this.MAX_LATITUDE,
+		    lat = Math.max(Math.min(max, latlng.lat), -max),
+		    x = latlng.lng * d,
+		    y = lat * d;
+
+		y = Math.log(Math.tan((Math.PI / 4) + (y / 2)));
+
+		return new L.Point(x, y);
+	},
+
+	unproject: function (point) { // (Point, Boolean) -> LatLng
+		var d = L.LatLng.RAD_TO_DEG,
+		    lng = point.x * d,
+		    lat = (2 * Math.atan(Math.exp(point.y)) - (Math.PI / 2)) * d;
+
+		return new L.LatLng(lat, lng);
+	}
+};
+
+
+/*
+ * Simple equirectangular (Plate Carree) projection, used by CRS like EPSG:4326 and Simple.
+ */
+
+L.Projection.LonLat = {
+	project: function (latlng) {
+		return new L.Point(latlng.lng, latlng.lat);
+	},
+
+	unproject: function (point) {
+		return new L.LatLng(point.y, point.x);
+	}
+};
+
+
+/*
+ * L.CRS is a base object for all defined CRS (Coordinate Reference Systems) in Leaflet.
+ */
+
+L.CRS = {
+	latLngToPoint: function (latlng, zoom) { // (LatLng, Number) -> Point
+		var projectedPoint = this.projection.project(latlng),
+		    scale = this.scale(zoom);
+
+		return this.transformation._transform(projectedPoint, scale);
+	},
+
+	pointToLatLng: function (point, zoom) { // (Point, Number[, Boolean]) -> LatLng
+		var scale = this.scale(zoom),
+		    untransformedPoint = this.transformation.untransform(point, scale);
+
+		return this.projection.unproject(untransformedPoint);
+	},
+
+	project: function (latlng) {
+		return this.projection.project(latlng);
+	},
+
+	scale: function (zoom) {
+		return 256 * Math.pow(2, zoom);
+	},
+
+	getSize: function (zoom) {
+		var s = this.scale(zoom);
+		return L.point(s, s);
+	}
+};
+
+
+/*
+ * A simple CRS that can be used for flat non-Earth maps like panoramas or game maps.
+ */
+
+L.CRS.Simple = L.extend({}, L.CRS, {
+	projection: L.Projection.LonLat,
+	transformation: new L.Transformation(1, 0, -1, 0),
+
+	scale: function (zoom) {
+		return Math.pow(2, zoom);
+	}
+});
+
+
+/*
+ * L.CRS.EPSG3857 (Spherical Mercator) is the most common CRS for web mapping
+ * and is used by Leaflet by default.
+ */
+
+L.CRS.EPSG3857 = L.extend({}, L.CRS, {
+	code: 'EPSG:3857',
+
+	projection: L.Projection.SphericalMercator,
+	transformation: new L.Transformation(0.5 / Math.PI, 0.5, -0.5 / Math.PI, 0.5),
+
+	project: function (latlng) { // (LatLng) -> Point
+		var projectedPoint = this.projection.project(latlng),
+		    earthRadius = 6378137;
+		return projectedPoint.multiplyBy(earthRadius);
+	}
+});
+
+L.CRS.EPSG900913 = L.extend({}, L.CRS.EPSG3857, {
+	code: 'EPSG:900913'
+});
+
+
+/*
+ * L.CRS.EPSG4326 is a CRS popular among advanced GIS specialists.
+ */
+
+L.CRS.EPSG4326 = L.extend({}, L.CRS, {
+	code: 'EPSG:4326',
+
+	projection: L.Projection.LonLat,
+	transformation: new L.Transformation(1 / 360, 0.5, -1 / 360, 0.5)
+});
+
+
+/*
+ * L.Map is the central class of the API - it is used to create a map.
+ */
+
+L.Map = L.Class.extend({
+
+	includes: L.Mixin.Events,
+
+	options: {
+		crs: L.CRS.EPSG3857,
+
+		/*
+		center: LatLng,
+		zoom: Number,
+		layers: Array,
+		*/
+
+		fadeAnimation: L.DomUtil.TRANSITION && !L.Browser.android23,
+		trackResize: true,
+		markerZoomAnimation: L.DomUtil.TRANSITION && L.Browser.any3d
+	},
+
+	initialize: function (id, options) { // (HTMLElement or String, Object)
+		options = L.setOptions(this, options);
+
+
+		this._initContainer(id);
+		this._initLayout();
+
+		// hack for https://github.com/Leaflet/Leaflet/issues/1980
+		this._onResize = L.bind(this._onResize, this);
+
+		this._initEvents();
+
+		if (options.maxBounds) {
+			this.setMaxBounds(options.maxBounds);
+		}
+
+		if (options.center && options.zoom !== undefined) {
+			this.setView(L.latLng(options.center), options.zoom, {reset: true});
+		}
+
+		this._handlers = [];
+
+		this._layers = {};
+		this._zoomBoundLayers = {};
+		this._tileLayersNum = 0;
+
+		this.callInitHooks();
+
+		this._addLayers(options.layers);
+	},
+
+
+	// public methods that modify map state
+
+	// replaced by animation-powered implementation in Map.PanAnimation.js
+	setView: function (center, zoom) {
+		zoom = zoom === undefined ? this.getZoom() : zoom;
+		this._resetView(L.latLng(center), this._limitZoom(zoom));
+		return this;
+	},
+
+	setZoom: function (zoom, options) {
+		if (!this._loaded) {
+			this._zoom = this._limitZoom(zoom);
+			return this;
+		}
+		return this.setView(this.getCenter(), zoom, {zoom: options});
+	},
+
+	zoomIn: function (delta, options) {
+		return this.setZoom(this._zoom + (delta || 1), options);
+	},
+
+	zoomOut: function (delta, options) {
+		return this.setZoom(this._zoom - (delta || 1), options);
+	},
+
+	setZoomAround: function (latlng, zoom, options) {
+		var scale = this.getZoomScale(zoom),
+		    viewHalf = this.getSize().divideBy(2),
+		    containerPoint = latlng instanceof L.Point ? latlng : this.latLngToContainerPoint(latlng),
+
+		    centerOffset = containerPoint.subtract(viewHalf).multiplyBy(1 - 1 / scale),
+		    newCenter = this.containerPointToLatLng(viewHalf.add(centerOffset));
+
+		return this.setView(newCenter, zoom, {zoom: options});
+	},
+
+	fitBounds: function (bounds, options) {
+
+		options = options || {};
+		bounds = bounds.getBounds ? bounds.getBounds() : L.latLngBounds(bounds);
+
+		var paddingTL = L.point(options.paddingTopLeft || options.padding || [0, 0]),
+		    paddingBR = L.point(options.paddingBottomRight || options.padding || [0, 0]),
+
+		    zoom = this.getBoundsZoom(bounds, false, paddingTL.add(paddingBR));
+
+		zoom = (options.maxZoom) ? Math.min(options.maxZoom, zoom) : zoom;
+
+		var paddingOffset = paddingBR.subtract(paddingTL).divideBy(2),
+
+		    swPoint = this.project(bounds.getSouthWest(), zoom),
+		    nePoint = this.project(bounds.getNorthEast(), zoom),
+		    center = this.unproject(swPoint.add(nePoint).divideBy(2).add(paddingOffset), zoom);
+
+		return this.setView(center, zoom, options);
+	},
+
+	fitWorld: function (options) {
+		return this.fitBounds([[-90, -180], [90, 180]], options);
+	},
+
+	panTo: function (center, options) { // (LatLng)
+		return this.setView(center, this._zoom, {pan: options});
+	},
+
+	panBy: function (offset) { // (Point)
+		// replaced with animated panBy in Map.PanAnimation.js
+		this.fire('movestart');
+
+		this._rawPanBy(L.point(offset));
+
+		this.fire('move');
+		return this.fire('moveend');
+	},
+
+	setMaxBounds: function (bounds) {
+		bounds = L.latLngBounds(bounds);
+
+		this.options.maxBounds = bounds;
+
+		if (!bounds) {
+			return this.off('moveend', this._panInsideMaxBounds, this);
+		}
+
+		if (this._loaded) {
+			this._panInsideMaxBounds();
+		}
+
+		return this.on('moveend', this._panInsideMaxBounds, this);
+	},
+
+	panInsideBounds: function (bounds, options) {
+		var center = this.getCenter(),
+			newCenter = this._limitCenter(center, this._zoom, bounds);
+
+		if (center.equals(newCenter)) { return this; }
+
+		return this.panTo(newCenter, options);
+	},
+
+	addLayer: function (layer) {
+		// TODO method is too big, refactor
+
+		var id = L.stamp(layer);
+
+		if (this._layers[id]) { return this; }
+
+		this._layers[id] = layer;
+
+		// TODO getMaxZoom, getMinZoom in ILayer (instead of options)
+		if (layer.options && (!isNaN(layer.options.maxZoom) || !isNaN(layer.options.minZoom))) {
+			this._zoomBoundLayers[id] = layer;
+			this._updateZoomLevels();
+		}
+
+		// TODO looks ugly, refactor!!!
+		if (this.options.zoomAnimation && L.TileLayer && (layer instanceof L.TileLayer)) {
+			this._tileLayersNum++;
+			this._tileLayersToLoad++;
+			layer.on('load', this._onTileLayerLoad, this);
+		}
+
+		if (this._loaded) {
+			this._layerAdd(layer);
+		}
+
+		return this;
+	},
+
+	removeLayer: function (layer) {
+		var id = L.stamp(layer);
+
+		if (!this._layers[id]) { return this; }
+
+		if (this._loaded) {
+			layer.onRemove(this);
+		}
+
+		delete this._layers[id];
+
+		if (this._loaded) {
+			this.fire('layerremove', {layer: layer});
+		}
+
+		if (this._zoomBoundLayers[id]) {
+			delete this._zoomBoundLayers[id];
+			this._updateZoomLevels();
+		}
+
+		// TODO looks ugly, refactor
+		if (this.options.zoomAnimation && L.TileLayer && (layer instanceof L.TileLayer)) {
+			this._tileLayersNum--;
+			this._tileLayersToLoad--;
+			layer.off('load', this._onTileLayerLoad, this);
+		}
+
+		return this;
+	},
+
+	hasLayer: function (layer) {
+		if (!layer) { return false; }
+
+		return (L.stamp(layer) in this._layers);
+	},
+
+	eachLayer: function (method, context) {
+		for (var i in this._layers) {
+			method.call(context, this._layers[i]);
+		}
+		return this;
+	},
+
+	invalidateSize: function (options) {
+		if (!this._loaded) { return this; }
+
+		options = L.extend({
+			animate: false,
+			pan: true
+		}, options === true ? {animate: true} : options);
+
+		var oldSize = this.getSize();
+		this._sizeChanged = true;
+		this._initialCenter = null;
+
+		var newSize = this.getSize(),
+		    oldCenter = oldSize.divideBy(2).round(),
+		    newCenter = newSize.divideBy(2).round(),
+		    offset = oldCenter.subtract(newCenter);
+
+		if (!offset.x && !offset.y) { return this; }
+
+		if (options.animate && options.pan) {
+			this.panBy(offset);
+
+		} else {
+			if (options.pan) {
+				this._rawPanBy(offset);
+			}
+
+			this.fire('move');
+
+			if (options.debounceMoveend) {
+				clearTimeout(this._sizeTimer);
+				this._sizeTimer = setTimeout(L.bind(this.fire, this, 'moveend'), 200);
+			} else {
+				this.fire('moveend');
+			}
+		}
+
+		return this.fire('resize', {
+			oldSize: oldSize,
+			newSize: newSize
+		});
+	},
+
+	// TODO handler.addTo
+	addHandler: function (name, HandlerClass) {
+		if (!HandlerClass) { return this; }
+
+		var handler = this[name] = new HandlerClass(this);
+
+		this._handlers.push(handler);
+
+		if (this.options[name]) {
+			handler.enable();
+		}
+
+		return this;
+	},
+
+	remove: function () {
+		if (this._loaded) {
+			this.fire('unload');
+		}
+
+		this._initEvents('off');
+
+		try {
+			// throws error in IE6-8
+			delete this._container._leaflet;
+		} catch (e) {
+			this._container._leaflet = undefined;
+		}
+
+		this._clearPanes();
+		if (this._clearControlPos) {
+			this._clearControlPos();
+		}
+
+		this._clearHandlers();
+
+		return this;
+	},
+
+
+	// public methods for getting map state
+
+	getCenter: function () { // (Boolean) -> LatLng
+		this._checkIfLoaded();
+
+		if (this._initialCenter && !this._moved()) {
+			return this._initialCenter;
+		}
+		return this.layerPointToLatLng(this._getCenterLayerPoint());
+	},
+
+	getZoom: function () {
+		return this._zoom;
+	},
+
+	getBounds: function () {
+		var bounds = this.getPixelBounds(),
+		    sw = this.unproject(bounds.getBottomLeft()),
+		    ne = this.unproject(bounds.getTopRight());
+
+		return new L.LatLngBounds(sw, ne);
+	},
+
+	getMinZoom: function () {
+		return this.options.minZoom === undefined ?
+			(this._layersMinZoom === undefined ? 0 : this._layersMinZoom) :
+			this.options.minZoom;
+	},
+
+	getMaxZoom: function () {
+		return this.options.maxZoom === undefined ?
+			(this._layersMaxZoom === undefined ? Infinity : this._layersMaxZoom) :
+			this.options.maxZoom;
+	},
+
+	getBoundsZoom: function (bounds, inside, padding) { // (LatLngBounds[, Boolean, Point]) -> Number
+		bounds = L.latLngBounds(bounds);
+
+		var zoom = this.getMinZoom() - (inside ? 1 : 0),
+		    maxZoom = this.getMaxZoom(),
+		    size = this.getSize(),
+
+		    nw = bounds.getNorthWest(),
+		    se = bounds.getSouthEast(),
+
+		    zoomNotFound = true,
+		    boundsSize;
+
+		padding = L.point(padding || [0, 0]);
+
+		do {
+			zoom++;
+			boundsSize = this.project(se, zoom).subtract(this.project(nw, zoom)).add(padding);
+			zoomNotFound = !inside ? size.contains(boundsSize) : boundsSize.x < size.x || boundsSize.y < size.y;
+
+		} while (zoomNotFound && zoom <= maxZoom);
+
+		if (zoomNotFound && inside) {
+			return null;
+		}
+
+		return inside ? zoom : zoom - 1;
+	},
+
+	getSize: function () {
+		if (!this._size || this._sizeChanged) {
+			this._size = new L.Point(
+				this._container.clientWidth,
+				this._container.clientHeight);
+
+			this._sizeChanged = false;
+		}
+		return this._size.clone();
+	},
+
+	getPixelBounds: function () {
+		var topLeftPoint = this._getTopLeftPoint();
+		return new L.Bounds(topLeftPoint, topLeftPoint.add(this.getSize()));
+	},
+
+	getPixelOrigin: function () {
+		this._checkIfLoaded();
+		return this._initialTopLeftPoint;
+	},
+
+	getPanes: function () {
+		return this._panes;
+	},
+
+	getContainer: function () {
+		return this._container;
+	},
+
+
+	// TODO replace with universal implementation after refactoring projections
+
+	getZoomScale: function (toZoom) {
+		var crs = this.options.crs;
+		return crs.scale(toZoom) / crs.scale(this._zoom);
+	},
+
+	getScaleZoom: function (scale) {
+		return this._zoom + (Math.log(scale) / Math.LN2);
+	},
+
+
+	// conversion methods
+
+	project: function (latlng, zoom) { // (LatLng[, Number]) -> Point
+		zoom = zoom === undefined ? this._zoom : zoom;
+		return this.options.crs.latLngToPoint(L.latLng(latlng), zoom);
+	},
+
+	unproject: function (point, zoom) { // (Point[, Number]) -> LatLng
+		zoom = zoom === undefined ? this._zoom : zoom;
+		return this.options.crs.pointToLatLng(L.point(point), zoom);
+	},
+
+	layerPointToLatLng: function (point) { // (Point)
+		var projectedPoint = L.point(point).add(this.getPixelOrigin());
+		return this.unproject(projectedPoint);
+	},
+
+	latLngToLayerPoint: function (latlng) { // (LatLng)
+		var projectedPoint = this.project(L.latLng(latlng))._round();
+		return projectedPoint._subtract(this.getPixelOrigin());
+	},
+
+	containerPointToLayerPoint: function (point) { // (Point)
+		return L.point(point).subtract(this._getMapPanePos());
+	},
+
+	layerPointToContainerPoint: function (point) { // (Point)
+		return L.point(point).add(this._getMapPanePos());
+	},
+
+	containerPointToLatLng: function (point) {
+		var layerPoint = this.containerPointToLayerPoint(L.point(point));
+		return this.layerPointToLatLng(layerPoint);
+	},
+
+	latLngToContainerPoint: function (latlng) {
+		return this.layerPointToContainerPoint(this.latLngToLayerPoint(L.latLng(latlng)));
+	},
+
+	mouseEventToContainerPoint: function (e) { // (MouseEvent)
+		return L.DomEvent.getMousePosition(e, this._container);
+	},
+
+	mouseEventToLayerPoint: function (e) { // (MouseEvent)
+		return this.containerPointToLayerPoint(this.mouseEventToContainerPoint(e));
+	},
+
+	mouseEventToLatLng: function (e) { // (MouseEvent)
+		return this.layerPointToLatLng(this.mouseEventToLayerPoint(e));
+	},
+
+
+	// map initialization methods
+
+	_initContainer: function (id) {
+		var container = this._container = L.DomUtil.get(id);
+
+		if (!container) {
+			throw new Error('Map container not found.');
+		} else if (container._leaflet) {
+			throw new Error('Map container is already initialized.');
+		}
+
+		container._leaflet = true;
+	},
+
+	_initLayout: function () {
+		var container = this._container;
+
+		L.DomUtil.addClass(container, 'leaflet-container' +
+			(L.Browser.touch ? ' leaflet-touch' : '') +
+			(L.Browser.retina ? ' leaflet-retina' : '') +
+			(L.Browser.ielt9 ? ' leaflet-oldie' : '') +
+			(this.options.fadeAnimation ? ' leaflet-fade-anim' : ''));
+
+		var position = L.DomUtil.getStyle(container, 'position');
+
+		if (position !== 'absolute' && position !== 'relative' && position !== 'fixed') {
+			container.style.position = 'relative';
+		}
+
+		this._initPanes();
+
+		if (this._initControlPos) {
+			this._initControlPos();
+		}
+	},
+
+	_initPanes: function () {
+		var panes = this._panes = {};
+
+		this._mapPane = panes.mapPane = this._createPane('leaflet-map-pane', this._container);
+
+		this._tilePane = panes.tilePane = this._createPane('leaflet-tile-pane', this._mapPane);
+		panes.objectsPane = this._createPane('leaflet-objects-pane', this._mapPane);
+		panes.shadowPane = this._createPane('leaflet-shadow-pane');
+		panes.overlayPane = this._createPane('leaflet-overlay-pane');
+		panes.markerPane = this._createPane('leaflet-marker-pane');
+		panes.popupPane = this._createPane('leaflet-popup-pane');
+
+		var zoomHide = ' leaflet-zoom-hide';
+
+		if (!this.options.markerZoomAnimation) {
+			L.DomUtil.addClass(panes.markerPane, zoomHide);
+			L.DomUtil.addClass(panes.shadowPane, zoomHide);
+			L.DomUtil.addClass(panes.popupPane, zoomHide);
+		}
+	},
+
+	_createPane: function (className, container) {
+		return L.DomUtil.create('div', className, container || this._panes.objectsPane);
+	},
+
+	_clearPanes: function () {
+		this._container.removeChild(this._mapPane);
+	},
+
+	_addLayers: function (layers) {
+		layers = layers ? (L.Util.isArray(layers) ? layers : [layers]) : [];
+
+		for (var i = 0, len = layers.length; i < len; i++) {
+			this.addLayer(layers[i]);
+		}
+	},
+
+
+	// private methods that modify map state
+
+	_resetView: function (center, zoom, preserveMapOffset, afterZoomAnim) {
+
+		var zoomChanged = (this._zoom !== zoom);
+
+		if (!afterZoomAnim) {
+			this.fire('movestart');
+
+			if (zoomChanged) {
+				this.fire('zoomstart');
+			}
+		}
+
+		this._zoom = zoom;
+		this._initialCenter = center;
+
+		this._initialTopLeftPoint = this._getNewTopLeftPoint(center);
+
+		if (!preserveMapOffset) {
+			L.DomUtil.setPosition(this._mapPane, new L.Point(0, 0));
+		} else {
+			this._initialTopLeftPoint._add(this._getMapPanePos());
+		}
+
+		this._tileLayersToLoad = this._tileLayersNum;
+
+		var loading = !this._loaded;
+		this._loaded = true;
+
+		this.fire('viewreset', {hard: !preserveMapOffset});
+
+		if (loading) {
+			this.fire('load');
+			this.eachLayer(this._layerAdd, this);
+		}
+
+		this.fire('move');
+
+		if (zoomChanged || afterZoomAnim) {
+			this.fire('zoomend');
+		}
+
+		this.fire('moveend', {hard: !preserveMapOffset});
+	},
+
+	_rawPanBy: function (offset) {
+		L.DomUtil.setPosition(this._mapPane, this._getMapPanePos().subtract(offset));
+	},
+
+	_getZoomSpan: function () {
+		return this.getMaxZoom() - this.getMinZoom();
+	},
+
+	_updateZoomLevels: function () {
+		var i,
+			minZoom = Infinity,
+			maxZoom = -Infinity,
+			oldZoomSpan = this._getZoomSpan();
+
+		for (i in this._zoomBoundLayers) {
+			var layer = this._zoomBoundLayers[i];
+			if (!isNaN(layer.options.minZoom)) {
+				minZoom = Math.min(minZoom, layer.options.minZoom);
+			}
+			if (!isNaN(layer.options.maxZoom)) {
+				maxZoom = Math.max(maxZoom, layer.options.maxZoom);
+			}
+		}
+
+		if (i === undefined) { // we have no tilelayers
+			this._layersMaxZoom = this._layersMinZoom = undefined;
+		} else {
+			this._layersMaxZoom = maxZoom;
+			this._layersMinZoom = minZoom;
+		}
+
+		if (oldZoomSpan !== this._getZoomSpan()) {
+			this.fire('zoomlevelschange');
+		}
+	},
+
+	_panInsideMaxBounds: function () {
+		this.panInsideBounds(this.options.maxBounds);
+	},
+
+	_checkIfLoaded: function () {
+		if (!this._loaded) {
+			throw new Error('Set map center and zoom first.');
+		}
+	},
+
+	// map events
+
+	_initEvents: function (onOff) {
+		if (!L.DomEvent) { return; }
+
+		onOff = onOff || 'on';
+
+		L.DomEvent[onOff](this._container, 'click', this._onMouseClick, this);
+
+		var events = ['dblclick', 'mousedown', 'mouseup', 'mouseenter',
+		              'mouseleave', 'mousemove', 'contextmenu'],
+		    i, len;
+
+		for (i = 0, len = events.length; i < len; i++) {
+			L.DomEvent[onOff](this._container, events[i], this._fireMouseEvent, this);
+		}
+
+		if (this.options.trackResize) {
+			L.DomEvent[onOff](window, 'resize', this._onResize, this);
+		}
+	},
+
+	_onResize: function () {
+		L.Util.cancelAnimFrame(this._resizeRequest);
+		this._resizeRequest = L.Util.requestAnimFrame(
+		        function () { this.invalidateSize({debounceMoveend: true}); }, this, false, this._container);
+	},
+
+	_onMouseClick: function (e) {
+		if (!this._loaded || (!e._simulated &&
+		        ((this.dragging && this.dragging.moved()) ||
+		         (this.boxZoom  && this.boxZoom.moved()))) ||
+		            L.DomEvent._skipped(e)) { return; }
+
+		this.fire('preclick');
+		this._fireMouseEvent(e);
+	},
+
+	_fireMouseEvent: function (e) {
+		if (!this._loaded || L.DomEvent._skipped(e)) { return; }
+
+		var type = e.type;
+
+		type = (type === 'mouseenter' ? 'mouseover' : (type === 'mouseleave' ? 'mouseout' : type));
+
+		if (!this.hasEventListeners(type)) { return; }
+
+		if (type === 'contextmenu') {
+			L.DomEvent.preventDefault(e);
+		}
+
+		var containerPoint = this.mouseEventToContainerPoint(e),
+		    layerPoint = this.containerPointToLayerPoint(containerPoint),
+		    latlng = this.layerPointToLatLng(layerPoint);
+
+		this.fire(type, {
+			latlng: latlng,
+			layerPoint: layerPoint,
+			containerPoint: containerPoint,
+			originalEvent: e
+		});
+	},
+
+	_onTileLayerLoad: function () {
+		this._tileLayersToLoad--;
+		if (this._tileLayersNum && !this._tileLayersToLoad) {
+			this.fire('tilelayersload');
+		}
+	},
+
+	_clearHandlers: function () {
+		for (var i = 0, len = this._handlers.length; i < len; i++) {
+			this._handlers[i].disable();
+		}
+	},
+
+	whenReady: function (callback, context) {
+		if (this._loaded) {
+			callback.call(context || this, this);
+		} else {
+			this.on('load', callback, context);
+		}
+		return this;
+	},
+
+	_layerAdd: function (layer) {
+		layer.onAdd(this);
+		this.fire('layeradd', {layer: layer});
+	},
+
+
+	// private methods for getting map state
+
+	_getMapPanePos: function () {
+		return L.DomUtil.getPosition(this._mapPane);
+	},
+
+	_moved: function () {
+		var pos = this._getMapPanePos();
+		return pos && !pos.equals([0, 0]);
+	},
+
+	_getTopLeftPoint: function () {
+		return this.getPixelOrigin().subtract(this._getMapPanePos());
+	},
+
+	_getNewTopLeftPoint: function (center, zoom) {
+		var viewHalf = this.getSize()._divideBy(2);
+		// TODO round on display, not calculation to increase precision?
+		return this.project(center, zoom)._subtract(viewHalf)._round();
+	},
+
+	_latLngToNewLayerPoint: function (latlng, newZoom, newCenter) {
+		var topLeft = this._getNewTopLeftPoint(newCenter, newZoom).add(this._getMapPanePos());
+		return this.project(latlng, newZoom)._subtract(topLeft);
+	},
+
+	// layer point of the current center
+	_getCenterLayerPoint: function () {
+		return this.containerPointToLayerPoint(this.getSize()._divideBy(2));
+	},
+
+	// offset of the specified place to the current center in pixels
+	_getCenterOffset: function (latlng) {
+		return this.latLngToLayerPoint(latlng).subtract(this._getCenterLayerPoint());
+	},
+
+	// adjust center for view to get inside bounds
+	_limitCenter: function (center, zoom, bounds) {
+
+		if (!bounds) { return center; }
+
+		var centerPoint = this.project(center, zoom),
+		    viewHalf = this.getSize().divideBy(2),
+		    viewBounds = new L.Bounds(centerPoint.subtract(viewHalf), centerPoint.add(viewHalf)),
+		    offset = this._getBoundsOffset(viewBounds, bounds, zoom);
+
+		return this.unproject(centerPoint.add(offset), zoom);
+	},
+
+	// adjust offset for view to get inside bounds
+	_limitOffset: function (offset, bounds) {
+		if (!bounds) { return offset; }
+
+		var viewBounds = this.getPixelBounds(),
+		    newBounds = new L.Bounds(viewBounds.min.add(offset), viewBounds.max.add(offset));
+
+		return offset.add(this._getBoundsOffset(newBounds, bounds));
+	},
+
+	// returns offset needed for pxBounds to get inside maxBounds at a specified zoom
+	_getBoundsOffset: function (pxBounds, maxBounds, zoom) {
+		var nwOffset = this.project(maxBounds.getNorthWest(), zoom).subtract(pxBounds.min),
+		    seOffset = this.project(maxBounds.getSouthEast(), zoom).subtract(pxBounds.max),
+
+		    dx = this._rebound(nwOffset.x, -seOffset.x),
+		    dy = this._rebound(nwOffset.y, -seOffset.y);
+
+		return new L.Point(dx, dy);
+	},
+
+	_rebound: function (left, right) {
+		return left + right > 0 ?
+			Math.round(left - right) / 2 :
+			Math.max(0, Math.ceil(left)) - Math.max(0, Math.floor(right));
+	},
+
+	_limitZoom: function (zoom) {
+		var min = this.getMinZoom(),
+		    max = this.getMaxZoom();
+
+		return Math.max(min, Math.min(max, zoom));
+	}
+});
+
+L.map = function (id, options) {
+	return new L.Map(id, options);
+};
+
+
+/*
+ * Mercator projection that takes into account that the Earth is not a perfect sphere.
+ * Less popular than spherical mercator; used by projections like EPSG:3395.
+ */
+
+L.Projection.Mercator = {
+	MAX_LATITUDE: 85.0840591556,
+
+	R_MINOR: 6356752.314245179,
+	R_MAJOR: 6378137,
+
+	project: function (latlng) { // (LatLng) -> Point
+		var d = L.LatLng.DEG_TO_RAD,
+		    max = this.MAX_LATITUDE,
+		    lat = Math.max(Math.min(max, latlng.lat), -max),
+		    r = this.R_MAJOR,
+		    r2 = this.R_MINOR,
+		    x = latlng.lng * d * r,
+		    y = lat * d,
+		    tmp = r2 / r,
+		    eccent = Math.sqrt(1.0 - tmp * tmp),
+		    con = eccent * Math.sin(y);
+
+		con = Math.pow((1 - con) / (1 + con), eccent * 0.5);
+
+		var ts = Math.tan(0.5 * ((Math.PI * 0.5) - y)) / con;
+		y = -r * Math.log(ts);
+
+		return new L.Point(x, y);
+	},
+
+	unproject: function (point) { // (Point, Boolean) -> LatLng
+		var d = L.LatLng.RAD_TO_DEG,
+		    r = this.R_MAJOR,
+		    r2 = this.R_MINOR,
+		    lng = point.x * d / r,
+		    tmp = r2 / r,
+		    eccent = Math.sqrt(1 - (tmp * tmp)),
+		    ts = Math.exp(- point.y / r),
+		    phi = (Math.PI / 2) - 2 * Math.atan(ts),
+		    numIter = 15,
+		    tol = 1e-7,
+		    i = numIter,
+		    dphi = 0.1,
+		    con;
+
+		while ((Math.abs(dphi) > tol) && (--i > 0)) {
+			con = eccent * Math.sin(phi);
+			dphi = (Math.PI / 2) - 2 * Math.atan(ts *
+			            Math.pow((1.0 - con) / (1.0 + con), 0.5 * eccent)) - phi;
+			phi += dphi;
+		}
+
+		return new L.LatLng(phi * d, lng);
+	}
+};
+
+
+
+L.CRS.EPSG3395 = L.extend({}, L.CRS, {
+	code: 'EPSG:3395',
+
+	projection: L.Projection.Mercator,
+
+	transformation: (function () {
+		var m = L.Projection.Mercator,
+		    r = m.R_MAJOR,
+		    scale = 0.5 / (Math.PI * r);
+
+		return new L.Transformation(scale, 0.5, -scale, 0.5);
+	}())
+});
+
+
+/*
+ * L.TileLayer is used for standard xyz-numbered tile layers.
+ */
+
+L.TileLayer = L.Class.extend({
+	includes: L.Mixin.Events,
+
+	options: {
+		minZoom: 0,
+		maxZoom: 18,
+		tileSize: 256,
+		subdomains: 'abc',
+		errorTileUrl: '',
+		attribution: '',
+		zoomOffset: 0,
+		opacity: 1,
+		/*
+		maxNativeZoom: null,
+		zIndex: null,
+		tms: false,
+		continuousWorld: false,
+		noWrap: false,
+		zoomReverse: false,
+		detectRetina: false,
+		reuseTiles: false,
+		bounds: false,
+		*/
+		unloadInvisibleTiles: L.Browser.mobile,
+		updateWhenIdle: L.Browser.mobile
+	},
+
+	initialize: function (url, options) {
+		options = L.setOptions(this, options);
+
+		// detecting retina displays, adjusting tileSize and zoom levels
+		if (options.detectRetina && L.Browser.retina && options.maxZoom > 0) {
+
+			options.tileSize = Math.floor(options.tileSize / 2);
+			options.zoomOffset++;
+
+			if (options.minZoom > 0) {
+				options.minZoom--;
+			}
+			this.options.maxZoom--;
+		}
+
+		if (options.bounds) {
+			options.bounds = L.latLngBounds(options.bounds);
+		}
+
+		this._url = url;
+
+		var subdomains = this.options.subdomains;
+
+		if (typeof subdomains === 'string') {
+			this.options.subdomains = subdomains.split('');
+		}
+	},
+
+	onAdd: function (map) {
+		this._map = map;
+		this._animated = map._zoomAnimated;
+
+		// create a container div for tiles
+		this._initContainer();
+
+		// set up events
+		map.on({
+			'viewreset': this._reset,
+			'moveend': this._update
+		}, this);
+
+		if (this._animated) {
+			map.on({
+				'zoomanim': this._animateZoom,
+				'zoomend': this._endZoomAnim
+			}, this);
+		}
+
+		if (!this.options.updateWhenIdle) {
+			this._limitedUpdate = L.Util.limitExecByInterval(this._update, 150, this);
+			map.on('move', this._limitedUpdate, this);
+		}
+
+		this._reset();
+		this._update();
+	},
+
+	addTo: function (map) {
+		map.addLayer(this);
+		return this;
+	},
+
+	onRemove: function (map) {
+		this._container.parentNode.removeChild(this._container);
+
+		map.off({
+			'viewreset': this._reset,
+			'moveend': this._update
+		}, this);
+
+		if (this._animated) {
+			map.off({
+				'zoomanim': this._animateZoom,
+				'zoomend': this._endZoomAnim
+			}, this);
+		}
+
+		if (!this.options.updateWhenIdle) {
+			map.off('move', this._limitedUpdate, this);
+		}
+
+		this._container = null;
+		this._map = null;
+	},
+
+	bringToFront: function () {
+		var pane = this._map._panes.tilePane;
+
+		if (this._container) {
+			pane.appendChild(this._container);
+			this._setAutoZIndex(pane, Math.max);
+		}
+
+		return this;
+	},
+
+	bringToBack: function () {
+		var pane = this._map._panes.tilePane;
+
+		if (this._container) {
+			pane.insertBefore(this._container, pane.firstChild);
+			this._setAutoZIndex(pane, Math.min);
+		}
+
+		return this;
+	},
+
+	getAttribution: function () {
+		return this.options.attribution;
+	},
+
+	getContainer: function () {
+		return this._container;
+	},
+
+	setOpacity: function (opacity) {
+		this.options.opacity = opacity;
+
+		if (this._map) {
+			this._updateOpacity();
+		}
+
+		return this;
+	},
+
+	setZIndex: function (zIndex) {
+		this.options.zIndex = zIndex;
+		this._updateZIndex();
+
+		return this;
+	},
+
+	setUrl: function (url, noRedraw) {
+		this._url = url;
+
+		if (!noRedraw) {
+			this.redraw();
+		}
+
+		return this;
+	},
+
+	redraw: function () {
+		if (this._map) {
+			this._reset({hard: true});
+			this._update();
+		}
+		return this;
+	},
+
+	_updateZIndex: function () {
+		if (this._container && this.options.zIndex !== undefined) {
+			this._container.style.zIndex = this.options.zIndex;
+		}
+	},
+
+	_setAutoZIndex: function (pane, compare) {
+
+		var layers = pane.children,
+		    edgeZIndex = -compare(Infinity, -Infinity), // -Infinity for max, Infinity for min
+		    zIndex, i, len;
+
+		for (i = 0, len = layers.length; i < len; i++) {
+
+			if (layers[i] !== this._container) {
+				zIndex = parseInt(layers[i].style.zIndex, 10);
+
+				if (!isNaN(zIndex)) {
+					edgeZIndex = compare(edgeZIndex, zIndex);
+				}
+			}
+		}
+
+		this.options.zIndex = this._container.style.zIndex =
+		        (isFinite(edgeZIndex) ? edgeZIndex : 0) + compare(1, -1);
+	},
+
+	_updateOpacity: function () {
+		var i,
+		    tiles = this._tiles;
+
+		if (L.Browser.ielt9) {
+			for (i in tiles) {
+				L.DomUtil.setOpacity(tiles[i], this.options.opacity);
+			}
+		} else {
+			L.DomUtil.setOpacity(this._container, this.options.opacity);
+		}
+	},
+
+	_initContainer: function () {
+		var tilePane = this._map._panes.tilePane;
+
+		if (!this._container) {
+			this._container = L.DomUtil.create('div', 'leaflet-layer');
+
+			this._updateZIndex();
+
+			if (this._animated) {
+				var className = 'leaflet-tile-container';
+
+				this._bgBuffer = L.DomUtil.create('div', className, this._container);
+				this._tileContainer = L.DomUtil.create('div', className, this._container);
+
+			} else {
+				this._tileContainer = this._container;
+			}
+
+			tilePane.appendChild(this._container);
+
+			if (this.options.opacity < 1) {
+				this._updateOpacity();
+			}
+		}
+	},
+
+	_reset: function (e) {
+		for (var key in this._tiles) {
+			this.fire('tileunload', {tile: this._tiles[key]});
+		}
+
+		this._tiles = {};
+		this._tilesToLoad = 0;
+
+		if (this.options.reuseTiles) {
+			this._unusedTiles = [];
+		}
+
+		this._tileContainer.innerHTML = '';
+
+		if (this._animated && e && e.hard) {
+			this._clearBgBuffer();
+		}
+
+		this._initContainer();
+	},
+
+	_getTileSize: function () {
+		var map = this._map,
+		    zoom = map.getZoom() + this.options.zoomOffset,
+		    zoomN = this.options.maxNativeZoom,
+		    tileSize = this.options.tileSize;
+
+		if (zoomN && zoom > zoomN) {
+			tileSize = Math.round(map.getZoomScale(zoom) / map.getZoomScale(zoomN) * tileSize);
+		}
+
+		return tileSize;
+	},
+
+	_update: function () {
+
+		if (!this._map) { return; }
+
+		var map = this._map,
+		    bounds = map.getPixelBounds(),
+		    zoom = map.getZoom(),
+		    tileSize = this._getTileSize();
+
+		if (zoom > this.options.maxZoom || zoom < this.options.minZoom) {
+			return;
+		}
+
+		var tileBounds = L.bounds(
+		        bounds.min.divideBy(tileSize)._floor(),
+		        bounds.max.divideBy(tileSize)._floor());
+
+		this._addTilesFromCenterOut(tileBounds);
+
+		if (this.options.unloadInvisibleTiles || this.options.reuseTiles) {
+			this._removeOtherTiles(tileBounds);
+		}
+	},
+
+	_addTilesFromCenterOut: function (bounds) {
+		var queue = [],
+		    center = bounds.getCenter();
+
+		var j, i, point;
+
+		for (j = bounds.min.y; j <= bounds.max.y; j++) {
+			for (i = bounds.min.x; i <= bounds.max.x; i++) {
+				point = new L.Point(i, j);
+
+				if (this._tileShouldBeLoaded(point)) {
+					queue.push(point);
+				}
+			}
+		}
+
+		var tilesToLoad = queue.length;
+
+		if (tilesToLoad === 0) { return; }
+
+		// load tiles in order of their distance to center
+		queue.sort(function (a, b) {
+			return a.distanceTo(center) - b.distanceTo(center);
+		});
+
+		var fragment = document.createDocumentFragment();
+
+		// if its the first batch of tiles to load
+		if (!this._tilesToLoad) {
+			this.fire('loading');
+		}
+
+		this._tilesToLoad += tilesToLoad;
+
+		for (i = 0; i < tilesToLoad; i++) {
+			this._addTile(queue[i], fragment);
+		}
+
+		this._tileContainer.appendChild(fragment);
+	},
+
+	_tileShouldBeLoaded: function (tilePoint) {
+		if ((tilePoint.x + ':' + tilePoint.y) in this._tiles) {
+			return false; // already loaded
+		}
+
+		var options = this.options;
+
+		if (!options.continuousWorld) {
+			var limit = this._getWrapTileNum();
+
+			// don't load if exceeds world bounds
+			if ((options.noWrap && (tilePoint.x < 0 || tilePoint.x >= limit.x)) ||
+				tilePoint.y < 0 || tilePoint.y >= limit.y) { return false; }
+		}
+
+		if (options.bounds) {
+			var tileSize = this._getTileSize(),
+			    nwPoint = tilePoint.multiplyBy(tileSize),
+			    sePoint = nwPoint.add([tileSize, tileSize]),
+			    nw = this._map.unproject(nwPoint),
+			    se = this._map.unproject(sePoint);
+
+			// TODO temporary hack, will be removed after refactoring projections
+			// https://github.com/Leaflet/Leaflet/issues/1618
+			if (!options.continuousWorld && !options.noWrap) {
+				nw = nw.wrap();
+				se = se.wrap();
+			}
+
+			if (!options.bounds.intersects([nw, se])) { return false; }
+		}
+
+		return true;
+	},
+
+	_removeOtherTiles: function (bounds) {
+		var kArr, x, y, key;
+
+		for (key in this._tiles) {
+			kArr = key.split(':');
+			x = parseInt(kArr[0], 10);
+			y = parseInt(kArr[1], 10);
+
+			// remove tile if it's out of bounds
+			if (x < bounds.min.x || x > bounds.max.x || y < bounds.min.y || y > bounds.max.y) {
+				this._removeTile(key);
+			}
+		}
+	},
+
+	_removeTile: function (key) {
+		var tile = this._tiles[key];
+
+		this.fire('tileunload', {tile: tile, url: tile.src});
+
+		if (this.options.reuseTiles) {
+			L.DomUtil.removeClass(tile, 'leaflet-tile-loaded');
+			this._unusedTiles.push(tile);
+
+		} else if (tile.parentNode === this._tileContainer) {
+			this._tileContainer.removeChild(tile);
+		}
+
+		// for https://github.com/CloudMade/Leaflet/issues/137
+		if (!L.Browser.android) {
+			tile.onload = null;
+			tile.src = L.Util.emptyImageUrl;
+		}
+
+		delete this._tiles[key];
+	},
+
+	_addTile: function (tilePoint, container) {
+		var tilePos = this._getTilePos(tilePoint);
+
+		// get unused tile - or create a new tile
+		var tile = this._getTile();
+
+		/*
+		Chrome 20 layouts much faster with top/left (verify with timeline, frames)
+		Android 4 browser has display issues with top/left and requires transform instead
+		(other browsers don't currently care) - see debug/hacks/jitter.html for an example
+		*/
+		L.DomUtil.setPosition(tile, tilePos, L.Browser.chrome);
+
+		this._tiles[tilePoint.x + ':' + tilePoint.y] = tile;
+
+		this._loadTile(tile, tilePoint);
+
+		if (tile.parentNode !== this._tileContainer) {
+			container.appendChild(tile);
+		}
+	},
+
+	_getZoomForUrl: function () {
+
+		var options = this.options,
+		    zoom = this._map.getZoom();
+
+		if (options.zoomReverse) {
+			zoom = options.maxZoom - zoom;
+		}
+
+		zoom += options.zoomOffset;
+
+		return options.maxNativeZoom ? Math.min(zoom, options.maxNativeZoom) : zoom;
+	},
+
+	_getTilePos: function (tilePoint) {
+		var origin = this._map.getPixelOrigin(),
+		    tileSize = this._getTileSize();
+
+		return tilePoint.multiplyBy(tileSize).subtract(origin);
+	},
+
+	// image-specific code (override to implement e.g. Canvas or SVG tile layer)
+
+	getTileUrl: function (tilePoint) {
+		return L.Util.template(this._url, L.extend({
+			s: this._getSubdomain(tilePoint),
+			z: tilePoint.z,
+			x: tilePoint.x,
+			y: tilePoint.y
+		}, this.options));
+	},
+
+	_getWrapTileNum: function () {
+		var crs = this._map.options.crs,
+		    size = crs.getSize(this._map.getZoom());
+		return size.divideBy(this._getTileSize())._floor();
+	},
+
+	_adjustTilePoint: function (tilePoint) {
+
+		var limit = this._getWrapTileNum();
+
+		// wrap tile coordinates
+		if (!this.options.continuousWorld && !this.options.noWrap) {
+			tilePoint.x = ((tilePoint.x % limit.x) + limit.x) % limit.x;
+		}
+
+		if (this.options.tms) {
+			tilePoint.y = limit.y - tilePoint.y - 1;
+		}
+
+		tilePoint.z = this._getZoomForUrl();
+	},
+
+	_getSubdomain: function (tilePoint) {
+		var index = Math.abs(tilePoint.x + tilePoint.y) % this.options.subdomains.length;
+		return this.options.subdomains[index];
+	},
+
+	_getTile: function () {
+		if (this.options.reuseTiles && this._unusedTiles.length > 0) {
+			var tile = this._unusedTiles.pop();
+			this._resetTile(tile);
+			return tile;
+		}
+		return this._createTile();
+	},
+
+	// Override if data stored on a tile needs to be cleaned up before reuse
+	_resetTile: function (/*tile*/) {},
+
+	_createTile: function () {
+		var tile = L.DomUtil.create('img', 'leaflet-tile');
+		tile.style.width = tile.style.height = this._getTileSize() + 'px';
+		tile.galleryimg = 'no';
+
+		tile.onselectstart = tile.onmousemove = L.Util.falseFn;
+
+		if (L.Browser.ielt9 && this.options.opacity !== undefined) {
+			L.DomUtil.setOpacity(tile, this.options.opacity);
+		}
+		// without this hack, tiles disappear after zoom on Chrome for Android
+		// https://github.com/Leaflet/Leaflet/issues/2078
+		if (L.Browser.mobileWebkit3d) {
+			tile.style.WebkitBackfaceVisibility = 'hidden';
+		}
+		return tile;
+	},
+
+	_loadTile: function (tile, tilePoint) {
+		tile._layer  = this;
+		tile.onload  = this._tileOnLoad;
+		tile.onerror = this._tileOnError;
+
+		this._adjustTilePoint(tilePoint);
+		tile.src     = this.getTileUrl(tilePoint);
+
+		this.fire('tileloadstart', {
+			tile: tile,
+			url: tile.src
+		});
+	},
+
+	_tileLoaded: function () {
+		this._tilesToLoad--;
+
+		if (this._animated) {
+			L.DomUtil.addClass(this._tileContainer, 'leaflet-zoom-animated');
+		}
+
+		if (!this._tilesToLoad) {
+			this.fire('load');
+
+			if (this._animated) {
+				// clear scaled tiles after all new tiles are loaded (for performance)
+				clearTimeout(this._clearBgBufferTimer);
+				this._clearBgBufferTimer = setTimeout(L.bind(this._clearBgBuffer, this), 500);
+			}
+		}
+	},
+
+	_tileOnLoad: function () {
+		var layer = this._layer;
+
+		//Only if we are loading an actual image
+		if (this.src !== L.Util.emptyImageUrl) {
+			L.DomUtil.addClass(this, 'leaflet-tile-loaded');
+
+			layer.fire('tileload', {
+				tile: this,
+				url: this.src
+			});
+		}
+
+		layer._tileLoaded();
+	},
+
+	_tileOnError: function () {
+		var layer = this._layer;
+
+		layer.fire('tileerror', {
+			tile: this,
+			url: this.src
+		});
+
+		var newUrl = layer.options.errorTileUrl;
+		if (newUrl) {
+			this.src = newUrl;
+		}
+
+		layer._tileLoaded();
+	}
+});
+
+L.tileLayer = function (url, options) {
+	return new L.TileLayer(url, options);
+};
+
+
+/*
+ * L.TileLayer.WMS is used for putting WMS tile layers on the map.
+ */
+
+L.TileLayer.WMS = L.TileLayer.extend({
+
+	defaultWmsParams: {
+		service: 'WMS',
+		request: 'GetMap',
+		version: '1.1.1',
+		layers: '',
+		styles: '',
+		format: 'image/jpeg',
+		transparent: false
+	},
+
+	initialize: function (url, options) { // (String, Object)
+
+		this._url = url;
+
+		var wmsParams = L.extend({}, this.defaultWmsParams),
+		    tileSize = options.tileSize || this.options.tileSize;
+
+		if (options.detectRetina && L.Browser.retina) {
+			wmsParams.width = wmsParams.height = tileSize * 2;
+		} else {
+			wmsParams.width = wmsParams.height = tileSize;
+		}
+
+		for (var i in options) {
+			// all keys that are not TileLayer options go to WMS params
+			if (!this.options.hasOwnProperty(i) && i !== 'crs') {
+				wmsParams[i] = options[i];
+			}
+		}
+
+		this.wmsParams = wmsParams;
+
+		L.setOptions(this, options);
+	},
+
+	onAdd: function (map) {
+
+		this._crs = this.options.crs || map.options.crs;
+
+		this._wmsVersion = parseFloat(this.wmsParams.version);
+
+		var projectionKey = this._wmsVersion >= 1.3 ? 'crs' : 'srs';
+		this.wmsParams[projectionKey] = this._crs.code;
+
+		L.TileLayer.prototype.onAdd.call(this, map);
+	},
+
+	getTileUrl: function (tilePoint) { // (Point, Number) -> String
+
+		var map = this._map,
+		    tileSize = this.options.tileSize,
+
+		    nwPoint = tilePoint.multiplyBy(tileSize),
+		    sePoint = nwPoint.add([tileSize, tileSize]),
+
+		    nw = this._crs.project(map.unproject(nwPoint, tilePoint.z)),
+		    se = this._crs.project(map.unproject(sePoint, tilePoint.z)),
+		    bbox = this._wmsVersion >= 1.3 && this._crs === L.CRS.EPSG4326 ?
+		        [se.y, nw.x, nw.y, se.x].join(',') :
+		        [nw.x, se.y, se.x, nw.y].join(','),
+
+		    url = L.Util.template(this._url, {s: this._getSubdomain(tilePoint)});
+
+		return url + L.Util.getParamString(this.wmsParams, url, true) + '&BBOX=' + bbox;
+	},
+
+	setParams: function (params, noRedraw) {
+
+		L.extend(this.wmsParams, params);
+
+		if (!noRedraw) {
+			this.redraw();
+		}
+
+		return this;
+	}
+});
+
+L.tileLayer.wms = function (url, options) {
+	return new L.TileLayer.WMS(url, options);
+};
+
+
+/*
+ * L.TileLayer.Canvas is a class that you can use as a base for creating
+ * dynamically drawn Canvas-based tile layers.
+ */
+
+L.TileLayer.Canvas = L.TileLayer.extend({
+	options: {
+		async: false
+	},
+
+	initialize: function (options) {
+		L.setOptions(this, options);
+	},
+
+	redraw: function () {
+		if (this._map) {
+			this._reset({hard: true});
+			this._update();
+		}
+
+		for (var i in this._tiles) {
+			this._redrawTile(this._tiles[i]);
+		}
+		return this;
+	},
+
+	_redrawTile: function (tile) {
+		this.drawTile(tile, tile._tilePoint, this._map._zoom);
+	},
+
+	_createTile: function () {
+		var tile = L.DomUtil.create('canvas', 'leaflet-tile');
+		tile.width = tile.height = this.options.tileSize;
+		tile.onselectstart = tile.onmousemove = L.Util.falseFn;
+		return tile;
+	},
+
+	_loadTile: function (tile, tilePoint) {
+		tile._layer = this;
+		tile._tilePoint = tilePoint;
+
+		this._redrawTile(tile);
+
+		if (!this.options.async) {
+			this.tileDrawn(tile);
+		}
+	},
+
+	drawTile: function (/*tile, tilePoint*/) {
+		// override with rendering code
+	},
+
+	tileDrawn: function (tile) {
+		this._tileOnLoad.call(tile);
+	}
+});
+
+
+L.tileLayer.canvas = function (options) {
+	return new L.TileLayer.Canvas(options);
+};
+
+
+/*
+ * L.ImageOverlay is used to overlay images over the map (to specific geographical bounds).
+ */
+
+L.ImageOverlay = L.Class.extend({
+	includes: L.Mixin.Events,
+
+	options: {
+		opacity: 1
+	},
+
+	initialize: function (url, bounds, options) { // (String, LatLngBounds, Object)
+		this._url = url;
+		this._bounds = L.latLngBounds(bounds);
+
+		L.setOptions(this, options);
+	},
+
+	onAdd: function (map) {
+		this._map = map;
+
+		if (!this._image) {
+			this._initImage();
+		}
+
+		map._panes.overlayPane.appendChild(this._image);
+
+		map.on('viewreset', this._reset, this);
+
+		if (map.options.zoomAnimation && L.Browser.any3d) {
+			map.on('zoomanim', this._animateZoom, this);
+		}
+
+		this._reset();
+	},
+
+	onRemove: function (map) {
+		map.getPanes().overlayPane.removeChild(this._image);
+
+		map.off('viewreset', this._reset, this);
+
+		if (map.options.zoomAnimation) {
+			map.off('zoomanim', this._animateZoom, this);
+		}
+	},
+
+	addTo: function (map) {
+		map.addLayer(this);
+		return this;
+	},
+
+	setOpacity: function (opacity) {
+		this.options.opacity = opacity;
+		this._updateOpacity();
+		return this;
+	},
+
+	// TODO remove bringToFront/bringToBack duplication from TileLayer/Path
+	bringToFront: function () {
+		if (this._image) {
+			this._map._panes.overlayPane.appendChild(this._image);
+		}
+		return this;
+	},
+
+	bringToBack: function () {
+		var pane = this._map._panes.overlayPane;
+		if (this._image) {
+			pane.insertBefore(this._image, pane.firstChild);
+		}
+		return this;
+	},
+
+	setUrl: function (url) {
+		this._url = url;
+		this._image.src = this._url;
+	},
+
+	getAttribution: function () {
+		return this.options.attribution;
+	},
+
+	_initImage: function () {
+		this._image = L.DomUtil.create('img', 'leaflet-image-layer');
+
+		if (this._map.options.zoomAnimation && L.Browser.any3d) {
+			L.DomUtil.addClass(this._image, 'leaflet-zoom-animated');
+		} else {
+			L.DomUtil.addClass(this._image, 'leaflet-zoom-hide');
+		}
+
+		this._updateOpacity();
+
+		//TODO createImage util method to remove duplication
+		L.extend(this._image, {
+			galleryimg: 'no',
+			onselectstart: L.Util.falseFn,
+			onmousemove: L.Util.falseFn,
+			onload: L.bind(this._onImageLoad, this),
+			src: this._url
+		});
+	},
+
+	_animateZoom: function (e) {
+		var map = this._map,
+		    image = this._image,
+		    scale = map.getZoomScale(e.zoom),
+		    nw = this._bounds.getNorthWest(),
+		    se = this._bounds.getSouthEast(),
+
+		    topLeft = map._latLngToNewLayerPoint(nw, e.zoom, e.center),
+		    size = map._latLngToNewLayerPoint(se, e.zoom, e.center)._subtract(topLeft),
+		    origin = topLeft._add(size._multiplyBy((1 / 2) * (1 - 1 / scale)));
+
+		image.style[L.DomUtil.TRANSFORM] =
+		        L.DomUtil.getTranslateString(origin) + ' scale(' + scale + ') ';
+	},
+
+	_reset: function () {
+		var image   = this._image,
+		    topLeft = this._map.latLngToLayerPoint(this._bounds.getNorthWest()),
+		    size = this._map.latLngToLayerPoint(this._bounds.getSouthEast())._subtract(topLeft);
+
+		L.DomUtil.setPosition(image, topLeft);
+
+		image.style.width  = size.x + 'px';
+		image.style.height = size.y + 'px';
+	},
+
+	_onImageLoad: function () {
+		this.fire('load');
+	},
+
+	_updateOpacity: function () {
+		L.DomUtil.setOpacity(this._image, this.options.opacity);
+	}
+});
+
+L.imageOverlay = function (url, bounds, options) {
+	return new L.ImageOverlay(url, bounds, options);
+};
+
+
+/*
+ * L.Icon is an image-based icon class that you can use with L.Marker for custom markers.
+ */
+
+L.Icon = L.Class.extend({
+	options: {
+		/*
+		iconUrl: (String) (required)
+		iconRetinaUrl: (String) (optional, used for retina devices if detected)
+		iconSize: (Point) (can be set through CSS)
+		iconAnchor: (Point) (centered by default, can be set in CSS with negative margins)
+		popupAnchor: (Point) (if not specified, popup opens in the anchor point)
+		shadowUrl: (String) (no shadow by default)
+		shadowRetinaUrl: (String) (optional, used for retina devices if detected)
+		shadowSize: (Point)
+		shadowAnchor: (Point)
+		*/
+		className: ''
+	},
+
+	initialize: function (options) {
+		L.setOptions(this, options);
+	},
+
+	createIcon: function (oldIcon) {
+		return this._createIcon('icon', oldIcon);
+	},
+
+	createShadow: function (oldIcon) {
+		return this._createIcon('shadow', oldIcon);
+	},
+
+	_createIcon: function (name, oldIcon) {
+		var src = this._getIconUrl(name);
+
+		if (!src) {
+			if (name === 'icon') {
+				throw new Error('iconUrl not set in Icon options (see the docs).');
+			}
+			return null;
+		}
+
+		var img;
+		if (!oldIcon || oldIcon.tagName !== 'IMG') {
+			img = this._createImg(src);
+		} else {
+			img = this._createImg(src, oldIcon);
+		}
+		this._setIconStyles(img, name);
+
+		return img;
+	},
+
+	_setIconStyles: function (img, name) {
+		var options = this.options,
+		    size = L.point(options[name + 'Size']),
+		    anchor;
+
+		if (name === 'shadow') {
+			anchor = L.point(options.shadowAnchor || options.iconAnchor);
+		} else {
+			anchor = L.point(options.iconAnchor);
+		}
+
+		if (!anchor && size) {
+			anchor = size.divideBy(2, true);
+		}
+
+		img.className = 'leaflet-marker-' + name + ' ' + options.className;
+
+		if (anchor) {
+			img.style.marginLeft = (-anchor.x) + 'px';
+			img.style.marginTop  = (-anchor.y) + 'px';
+		}
+
+		if (size) {
+			img.style.width  = size.x + 'px';
+			img.style.height = size.y + 'px';
+		}
+	},
+
+	_createImg: function (src, el) {
+		el = el || document.createElement('img');
+		el.src = src;
+		return el;
+	},
+
+	_getIconUrl: function (name) {
+		if (L.Browser.retina && this.options[name + 'RetinaUrl']) {
+			return this.options[name + 'RetinaUrl'];
+		}
+		return this.options[name + 'Url'];
+	}
+});
+
+L.icon = function (options) {
+	return new L.Icon(options);
+};
+
+
+/*
+ * L.Icon.Default is the blue marker icon used by default in Leaflet.
+ */
+
+L.Icon.Default = L.Icon.extend({
+
+	options: {
+		iconSize: [25, 41],
+		iconAnchor: [12, 41],
+		popupAnchor: [1, -34],
+
+		shadowSize: [41, 41]
+	},
+
+	_getIconUrl: function (name) {
+		var key = name + 'Url';
+
+		if (this.options[key]) {
+			return this.options[key];
+		}
+
+		if (L.Browser.retina && name === 'icon') {
+			name += '-2x';
+		}
+
+		var path = L.Icon.Default.imagePath;
+
+		if (!path) {
+			throw new Error('Couldn\'t autodetect L.Icon.Default.imagePath, set it manually.');
+		}
+
+		return path + '/marker-' + name + '.png';
+	}
+});
+
+L.Icon.Default.imagePath = (function () {
+	var scripts = document.getElementsByTagName('script'),
+	    leafletRe = /[\/^]leaflet[\-\._]?([\w\-\._]*)\.js\??/;
+
+	var i, len, src, matches, path;
+
+	for (i = 0, len = scripts.length; i < len; i++) {
+		src = scripts[i].src;
+		matches = src.match(leafletRe);
+
+		if (matches) {
+			path = src.split(leafletRe)[0];
+			return (path ? path + '/' : '') + 'images';
+		}
+	}
+}());
+
+
+/*
+ * L.Marker is used to display clickable/draggable icons on the map.
+ */
+
+L.Marker = L.Class.extend({
+
+	includes: L.Mixin.Events,
+
+	options: {
+		icon: new L.Icon.Default(),
+		title: '',
+		alt: '',
+		clickable: true,
+		draggable: false,
+		keyboard: true,
+		zIndexOffset: 0,
+		opacity: 1,
+		riseOnHover: false,
+		riseOffset: 250
+	},
+
+	initialize: function (latlng, options) {
+		L.setOptions(this, options);
+		this._latlng = L.latLng(latlng);
+	},
+
+	onAdd: function (map) {
+		this._map = map;
+
+		map.on('viewreset', this.update, this);
+
+		this._initIcon();
+		this.update();
+		this.fire('add');
+
+		if (map.options.zoomAnimation && map.options.markerZoomAnimation) {
+			map.on('zoomanim', this._animateZoom, this);
+		}
+	},
+
+	addTo: function (map) {
+		map.addLayer(this);
+		return this;
+	},
+
+	onRemove: function (map) {
+		if (this.dragging) {
+			this.dragging.disable();
+		}
+
+		this._removeIcon();
+		this._removeShadow();
+
+		this.fire('remove');
+
+		map.off({
+			'viewreset': this.update,
+			'zoomanim': this._animateZoom
+		}, this);
+
+		this._map = null;
+	},
+
+	getLatLng: function () {
+		return this._latlng;
+	},
+
+	setLatLng: function (latlng) {
+		this._latlng = L.latLng(latlng);
+
+		this.update();
+
+		return this.fire('move', { latlng: this._latlng });
+	},
+
+	setZIndexOffset: function (offset) {
+		this.options.zIndexOffset = offset;
+		this.update();
+
+		return this;
+	},
+
+	setIcon: function (icon) {
+
+		this.options.icon = icon;
+
+		if (this._map) {
+			this._initIcon();
+			this.update();
+		}
+
+		if (this._popup) {
+			this.bindPopup(this._popup);
+		}
+
+		return this;
+	},
+
+	update: function () {
+		if (this._icon) {
+			this._setPos(this._map.latLngToLayerPoint(this._latlng).round());
+		}
+		return this;
+	},
+
+	_initIcon: function () {
+		var options = this.options,
+		    map = this._map,
+		    animation = (map.options.zoomAnimation && map.options.markerZoomAnimation),
+		    classToAdd = animation ? 'leaflet-zoom-animated' : 'leaflet-zoom-hide';
+
+		var icon = options.icon.createIcon(this._icon),
+			addIcon = false;
+
+		// if we're not reusing the icon, remove the old one and init new one
+		if (icon !== this._icon) {
+			if (this._icon) {
+				this._removeIcon();
+			}
+			addIcon = true;
+
+			if (options.title) {
+				icon.title = options.title;
+			}
+
+			if (options.alt) {
+				icon.alt = options.alt;
+			}
+		}
+
+		L.DomUtil.addClass(icon, classToAdd);
+
+		if (options.keyboard) {
+			icon.tabIndex = '0';
+		}
+
+		this._icon = icon;
+
+		this._initInteraction();
+
+		if (options.riseOnHover) {
+			L.DomEvent
+				.on(icon, 'mouseover', this._bringToFront, this)
+				.on(icon, 'mouseout', this._resetZIndex, this);
+		}
+
+		var newShadow = options.icon.createShadow(this._shadow),
+			addShadow = false;
+
+		if (newShadow !== this._shadow) {
+			this._removeShadow();
+			addShadow = true;
+		}
+
+		if (newShadow) {
+			L.DomUtil.addClass(newShadow, classToAdd);
+		}
+		this._shadow = newShadow;
+
+
+		if (options.opacity < 1) {
+			this._updateOpacity();
+		}
+
+
+		var panes = this._map._panes;
+
+		if (addIcon) {
+			panes.markerPane.appendChild(this._icon);
+		}
+
+		if (newShadow && addShadow) {
+			panes.shadowPane.appendChild(this._shadow);
+		}
+	},
+
+	_removeIcon: function () {
+		if (this.options.riseOnHover) {
+			L.DomEvent
+			    .off(this._icon, 'mouseover', this._bringToFront)
+			    .off(this._icon, 'mouseout', this._resetZIndex);
+		}
+
+		this._map._panes.markerPane.removeChild(this._icon);
+
+		this._icon = null;
+	},
+
+	_removeShadow: function () {
+		if (this._shadow) {
+			this._map._panes.shadowPane.removeChild(this._shadow);
+		}
+		this._shadow = null;
+	},
+
+	_setPos: function (pos) {
+		L.DomUtil.setPosition(this._icon, pos);
+
+		if (this._shadow) {
+			L.DomUtil.setPosition(this._shadow, pos);
+		}
+
+		this._zIndex = pos.y + this.options.zIndexOffset;
+
+		this._resetZIndex();
+	},
+
+	_updateZIndex: function (offset) {
+		this._icon.style.zIndex = this._zIndex + offset;
+	},
+
+	_animateZoom: function (opt) {
+		var pos = this._map._latLngToNewLayerPoint(this._latlng, opt.zoom, opt.center).round();
+
+		this._setPos(pos);
+	},
+
+	_initInteraction: function () {
+
+		if (!this.options.clickable) { return; }
+
+		// TODO refactor into something shared with Map/Path/etc. to DRY it up
+
+		var icon = this._icon,
+		    events = ['dblclick', 'mousedown', 'mouseover', 'mouseout', 'contextmenu'];
+
+		L.DomUtil.addClass(icon, 'leaflet-clickable');
+		L.DomEvent.on(icon, 'click', this._onMouseClick, this);
+		L.DomEvent.on(icon, 'keypress', this._onKeyPress, this);
+
+		for (var i = 0; i < events.length; i++) {
+			L.DomEvent.on(icon, events[i], this._fireMouseEvent, this);
+		}
+
+		if (L.Handler.MarkerDrag) {
+			this.dragging = new L.Handler.MarkerDrag(this);
+
+			if (this.options.draggable) {
+				this.dragging.enable();
+			}
+		}
+	},
+
+	_onMouseClick: function (e) {
+		var wasDragged = this.dragging && this.dragging.moved();
+
+		if (this.hasEventListeners(e.type) || wasDragged) {
+			L.DomEvent.stopPropagation(e);
+		}
+
+		if (wasDragged) { return; }
+
+		if ((!this.dragging || !this.dragging._enabled) && this._map.dragging && this._map.dragging.moved()) { return; }
+
+		this.fire(e.type, {
+			originalEvent: e,
+			latlng: this._latlng
+		});
+	},
+
+	_onKeyPress: function (e) {
+		if (e.keyCode === 13) {
+			this.fire('click', {
+				originalEvent: e,
+				latlng: this._latlng
+			});
+		}
+	},
+
+	_fireMouseEvent: function (e) {
+
+		this.fire(e.type, {
+			originalEvent: e,
+			latlng: this._latlng
+		});
+
+		// TODO proper custom event propagation
+		// this line will always be called if marker is in a FeatureGroup
+		if (e.type === 'contextmenu' && this.hasEventListeners(e.type)) {
+			L.DomEvent.preventDefault(e);
+		}
+		if (e.type !== 'mousedown') {
+			L.DomEvent.stopPropagation(e);
+		} else {
+			L.DomEvent.preventDefault(e);
+		}
+	},
+
+	setOpacity: function (opacity) {
+		this.options.opacity = opacity;
+		if (this._map) {
+			this._updateOpacity();
+		}
+
+		return this;
+	},
+
+	_updateOpacity: function () {
+		L.DomUtil.setOpacity(this._icon, this.options.opacity);
+		if (this._shadow) {
+			L.DomUtil.setOpacity(this._shadow, this.options.opacity);
+		}
+	},
+
+	_bringToFront: function () {
+		this._updateZIndex(this.options.riseOffset);
+	},
+
+	_resetZIndex: function () {
+		this._updateZIndex(0);
+	}
+});
+
+L.marker = function (latlng, options) {
+	return new L.Marker(latlng, options);
+};
+
+
+/*
+ * L.DivIcon is a lightweight HTML-based icon class (as opposed to the image-based L.Icon)
+ * to use with L.Marker.
+ */
+
+L.DivIcon = L.Icon.extend({
+	options: {
+		iconSize: [12, 12], // also can be set through CSS
+		/*
+		iconAnchor: (Point)
+		popupAnchor: (Point)
+		html: (String)
+		bgPos: (Point)
+		*/
+		className: 'leaflet-div-icon',
+		html: false
+	},
+
+	createIcon: function (oldIcon) {
+		var div = (oldIcon && oldIcon.tagName === 'DIV') ? oldIcon : document.createElement('div'),
+		    options = this.options;
+
+		if (options.html !== false) {
+			div.innerHTML = options.html;
+		} else {
+			div.innerHTML = '';
+		}
+
+		if (options.bgPos) {
+			div.style.backgroundPosition =
+			        (-options.bgPos.x) + 'px ' + (-options.bgPos.y) + 'px';
+		}
+
+		this._setIconStyles(div, 'icon');
+		return div;
+	},
+
+	createShadow: function () {
+		return null;
+	}
+});
+
+L.divIcon = function (options) {
+	return new L.DivIcon(options);
+};
+
+
+/*
+ * L.Popup is used for displaying popups on the map.
+ */
+
+L.Map.mergeOptions({
+	closePopupOnClick: true
+});
+
+L.Popup = L.Class.extend({
+	includes: L.Mixin.Events,
+
+	options: {
+		minWidth: 50,
+		maxWidth: 300,
+		// maxHeight: null,
+		autoPan: true,
+		closeButton: true,
+		offset: [0, 7],
+		autoPanPadding: [5, 5],
+		// autoPanPaddingTopLeft: null,
+		// autoPanPaddingBottomRight: null,
+		keepInView: false,
+		className: '',
+		zoomAnimation: true
+	},
+
+	initialize: function (options, source) {
+		L.setOptions(this, options);
+
+		this._source = source;
+		this._animated = L.Browser.any3d && this.options.zoomAnimation;
+		this._isOpen = false;
+	},
+
+	onAdd: function (map) {
+		this._map = map;
+
+		if (!this._container) {
+			this._initLayout();
+		}
+
+		var animFade = map.options.fadeAnimation;
+
+		if (animFade) {
+			L.DomUtil.setOpacity(this._container, 0);
+		}
+		map._panes.popupPane.appendChild(this._container);
+
+		map.on(this._getEvents(), this);
+
+		this.update();
+
+		if (animFade) {
+			L.DomUtil.setOpacity(this._container, 1);
+		}
+
+		this.fire('open');
+
+		map.fire('popupopen', {popup: this});
+
+		if (this._source) {
+			this._source.fire('popupopen', {popup: this});
+		}
+	},
+
+	addTo: function (map) {
+		map.addLayer(this);
+		return this;
+	},
+
+	openOn: function (map) {
+		map.openPopup(this);
+		return this;
+	},
+
+	onRemove: function (map) {
+		map._panes.popupPane.removeChild(this._container);
+
+		L.Util.falseFn(this._container.offsetWidth); // force reflow
+
+		map.off(this._getEvents(), this);
+
+		if (map.options.fadeAnimation) {
+			L.DomUtil.setOpacity(this._container, 0);
+		}
+
+		this._map = null;
+
+		this.fire('close');
+
+		map.fire('popupclose', {popup: this});
+
+		if (this._source) {
+			this._source.fire('popupclose', {popup: this});
+		}
+	},
+
+	getLatLng: function () {
+		return this._latlng;
+	},
+
+	setLatLng: function (latlng) {
+		this._latlng = L.latLng(latlng);
+		if (this._map) {
+			this._updatePosition();
+			this._adjustPan();
+		}
+		return this;
+	},
+
+	getContent: function () {
+		return this._content;
+	},
+
+	setContent: function (content) {
+		this._content = content;
+		this.update();
+		return this;
+	},
+
+	update: function () {
+		if (!this._map) { return; }
+
+		this._container.style.visibility = 'hidden';
+
+		this._updateContent();
+		this._updateLayout();
+		this._updatePosition();
+
+		this._container.style.visibility = '';
+
+		this._adjustPan();
+	},
+
+	_getEvents: function () {
+		var events = {
+			viewreset: this._updatePosition
+		};
+
+		if (this._animated) {
+			events.zoomanim = this._zoomAnimation;
+		}
+		if ('closeOnClick' in this.options ? this.options.closeOnClick : this._map.options.closePopupOnClick) {
+			events.preclick = this._close;
+		}
+		if (this.options.keepInView) {
+			events.moveend = this._adjustPan;
+		}
+
+		return events;
+	},
+
+	_close: function () {
+		if (this._map) {
+			this._map.closePopup(this);
+		}
+	},
+
+	_initLayout: function () {
+		var prefix = 'leaflet-popup',
+			containerClass = prefix + ' ' + this.options.className + ' leaflet-zoom-' +
+			        (this._animated ? 'animated' : 'hide'),
+			container = this._container = L.DomUtil.create('div', containerClass),
+			closeButton;
+
+		if (this.options.closeButton) {
+			closeButton = this._closeButton =
+			        L.DomUtil.create('a', prefix + '-close-button', container);
+			closeButton.href = '#close';
+			closeButton.innerHTML = '×';
+			L.DomEvent.disableClickPropagation(closeButton);
+
+			L.DomEvent.on(closeButton, 'click', this._onCloseButtonClick, this);
+		}
+
+		var wrapper = this._wrapper =
+		        L.DomUtil.create('div', prefix + '-content-wrapper', container);
+		L.DomEvent.disableClickPropagation(wrapper);
+
+		this._contentNode = L.DomUtil.create('div', prefix + '-content', wrapper);
+
+		L.DomEvent.disableScrollPropagation(this._contentNode);
+		L.DomEvent.on(wrapper, 'contextmenu', L.DomEvent.stopPropagation);
+
+		this._tipContainer = L.DomUtil.create('div', prefix + '-tip-container', container);
+		this._tip = L.DomUtil.create('div', prefix + '-tip', this._tipContainer);
+	},
+
+	_updateContent: function () {
+		if (!this._content) { return; }
+
+		if (typeof this._content === 'string') {
+			this._contentNode.innerHTML = this._content;
+		} else {
+			while (this._contentNode.hasChildNodes()) {
+				this._contentNode.removeChild(this._contentNode.firstChild);
+			}
+			this._contentNode.appendChild(this._content);
+		}
+		this.fire('contentupdate');
+	},
+
+	_updateLayout: function () {
+		var container = this._contentNode,
+		    style = container.style;
+
+		style.width = '';
+		style.whiteSpace = 'nowrap';
+
+		var width = container.offsetWidth;
+		width = Math.min(width, this.options.maxWidth);
+		width = Math.max(width, this.options.minWidth);
+
+		style.width = (width + 1) + 'px';
+		style.whiteSpace = '';
+
+		style.height = '';
+
+		var height = container.offsetHeight,
+		    maxHeight = this.options.maxHeight,
+		    scrolledClass = 'leaflet-popup-scrolled';
+
+		if (maxHeight && height > maxHeight) {
+			style.height = maxHeight + 'px';
+			L.DomUtil.addClass(container, scrolledClass);
+		} else {
+			L.DomUtil.removeClass(container, scrolledClass);
+		}
+
+		this._containerWidth = this._container.offsetWidth;
+	},
+
+	_updatePosition: function () {
+		if (!this._map) { return; }
+
+		var pos = this._map.latLngToLayerPoint(this._latlng),
+		    animated = this._animated,
+		    offset = L.point(this.options.offset);
+
+		if (animated) {
+			L.DomUtil.setPosition(this._container, pos);
+		}
+
+		this._containerBottom = -offset.y - (animated ? 0 : pos.y);
+		this._containerLeft = -Math.round(this._containerWidth / 2) + offset.x + (animated ? 0 : pos.x);
+
+		// bottom position the popup in case the height of the popup changes (images loading etc)
+		this._container.style.bottom = this._containerBottom + 'px';
+		this._container.style.left = this._containerLeft + 'px';
+	},
+
+	_zoomAnimation: function (opt) {
+		var pos = this._map._latLngToNewLayerPoint(this._latlng, opt.zoom, opt.center);
+
+		L.DomUtil.setPosition(this._container, pos);
+	},
+
+	_adjustPan: function () {
+		if (!this.options.autoPan) { return; }
+
+		var map = this._map,
+		    containerHeight = this._container.offsetHeight,
+		    containerWidth = this._containerWidth,
+
+		    layerPos = new L.Point(this._containerLeft, -containerHeight - this._containerBottom);
+
+		if (this._animated) {
+			layerPos._add(L.DomUtil.getPosition(this._container));
+		}
+
+		var containerPos = map.layerPointToContainerPoint(layerPos),
+		    padding = L.point(this.options.autoPanPadding),
+		    paddingTL = L.point(this.options.autoPanPaddingTopLeft || padding),
+		    paddingBR = L.point(this.options.autoPanPaddingBottomRight || padding),
+		    size = map.getSize(),
+		    dx = 0,
+		    dy = 0;
+
+		if (containerPos.x + containerWidth + paddingBR.x > size.x) { // right
+			dx = containerPos.x + containerWidth - size.x + paddingBR.x;
+		}
+		if (containerPos.x - dx - paddingTL.x < 0) { // left
+			dx = containerPos.x - paddingTL.x;
+		}
+		if (containerPos.y + containerHeight + paddingBR.y > size.y) { // bottom
+			dy = containerPos.y + containerHeight - size.y + paddingBR.y;
+		}
+		if (containerPos.y - dy - paddingTL.y < 0) { // top
+			dy = containerPos.y - paddingTL.y;
+		}
+
+		if (dx || dy) {
+			map
+			    .fire('autopanstart')
+			    .panBy([dx, dy]);
+		}
+	},
+
+	_onCloseButtonClick: function (e) {
+		this._close();
+		L.DomEvent.stop(e);
+	}
+});
+
+L.popup = function (options, source) {
+	return new L.Popup(options, source);
+};
+
+
+L.Map.include({
+	openPopup: function (popup, latlng, options) { // (Popup) or (String || HTMLElement, LatLng[, Object])
+		this.closePopup();
+
+		if (!(popup instanceof L.Popup)) {
+			var content = popup;
+
+			popup = new L.Popup(options)
+			    .setLatLng(latlng)
+			    .setContent(content);
+		}
+		popup._isOpen = true;
+
+		this._popup = popup;
+		return this.addLayer(popup);
+	},
+
+	closePopup: function (popup) {
+		if (!popup || popup === this._popup) {
+			popup = this._popup;
+			this._popup = null;
+		}
+		if (popup) {
+			this.removeLayer(popup);
+			popup._isOpen = false;
+		}
+		return this;
+	}
+});
+
+
+/*
+ * Popup extension to L.Marker, adding popup-related methods.
+ */
+
+L.Marker.include({
+	openPopup: function () {
+		if (this._popup && this._map && !this._map.hasLayer(this._popup)) {
+			this._popup.setLatLng(this._latlng);
+			this._map.openPopup(this._popup);
+		}
+
+		return this;
+	},
+
+	closePopup: function () {
+		if (this._popup) {
+			this._popup._close();
+		}
+		return this;
+	},
+
+	togglePopup: function () {
+		if (this._popup) {
+			if (this._popup._isOpen) {
+				this.closePopup();
+			} else {
+				this.openPopup();
+			}
+		}
+		return this;
+	},
+
+	bindPopup: function (content, options) {
+		var anchor = L.point(this.options.icon.options.popupAnchor || [0, 0]);
+
+		anchor = anchor.add(L.Popup.prototype.options.offset);
+
+		if (options && options.offset) {
+			anchor = anchor.add(options.offset);
+		}
+
+		options = L.extend({offset: anchor}, options);
+
+		if (!this._popupHandlersAdded) {
+			this
+			    .on('click', this.togglePopup, this)
+			    .on('remove', this.closePopup, this)
+			    .on('move', this._movePopup, this);
+			this._popupHandlersAdded = true;
+		}
+
+		if (content instanceof L.Popup) {
+			L.setOptions(content, options);
+			this._popup = content;
+			content._source = this;
+		} else {
+			this._popup = new L.Popup(options, this)
+				.setContent(content);
+		}
+
+		return this;
+	},
+
+	setPopupContent: function (content) {
+		if (this._popup) {
+			this._popup.setContent(content);
+		}
+		return this;
+	},
+
+	unbindPopup: function () {
+		if (this._popup) {
+			this._popup = null;
+			this
+			    .off('click', this.togglePopup, this)
+			    .off('remove', this.closePopup, this)
+			    .off('move', this._movePopup, this);
+			this._popupHandlersAdded = false;
+		}
+		return this;
+	},
+
+	getPopup: function () {
+		return this._popup;
+	},
+
+	_movePopup: function (e) {
+		this._popup.setLatLng(e.latlng);
+	}
+});
+
+
+/*
+ * L.LayerGroup is a class to combine several layers into one so that
+ * you can manipulate the group (e.g. add/remove it) as one layer.
+ */
+
+L.LayerGroup = L.Class.extend({
+	initialize: function (layers) {
+		this._layers = {};
+
+		var i, len;
+
+		if (layers) {
+			for (i = 0, len = layers.length; i < len; i++) {
+				this.addLayer(layers[i]);
+			}
+		}
+	},
+
+	addLayer: function (layer) {
+		var id = this.getLayerId(layer);
+
+		this._layers[id] = layer;
+
+		if (this._map) {
+			this._map.addLayer(layer);
+		}
+
+		return this;
+	},
+
+	removeLayer: function (layer) {
+		var id = layer in this._layers ? layer : this.getLayerId(layer);
+
+		if (this._map && this._layers[id]) {
+			this._map.removeLayer(this._layers[id]);
+		}
+
+		delete this._layers[id];
+
+		return this;
+	},
+
+	hasLayer: function (layer) {
+		if (!layer) { return false; }
+
+		return (layer in this._layers || this.getLayerId(layer) in this._layers);
+	},
+
+	clearLayers: function () {
+		this.eachLayer(this.removeLayer, this);
+		return this;
+	},
+
+	invoke: function (methodName) {
+		var args = Array.prototype.slice.call(arguments, 1),
+		    i, layer;
+
+		for (i in this._layers) {
+			layer = this._layers[i];
+
+			if (layer[methodName]) {
+				layer[methodName].apply(layer, args);
+			}
+		}
+
+		return this;
+	},
+
+	onAdd: function (map) {
+		this._map = map;
+		this.eachLayer(map.addLayer, map);
+	},
+
+	onRemove: function (map) {
+		this.eachLayer(map.removeLayer, map);
+		this._map = null;
+	},
+
+	addTo: function (map) {
+		map.addLayer(this);
+		return this;
+	},
+
+	eachLayer: function (method, context) {
+		for (var i in this._layers) {
+			method.call(context, this._layers[i]);
+		}
+		return this;
+	},
+
+	getLayer: function (id) {
+		return this._layers[id];
+	},
+
+	getLayers: function () {
+		var layers = [];
+
+		for (var i in this._layers) {
+			layers.push(this._layers[i]);
+		}
+		return layers;
+	},
+
+	setZIndex: function (zIndex) {
+		return this.invoke('setZIndex', zIndex);
+	},
+
+	getLayerId: function (layer) {
+		return L.stamp(layer);
+	}
+});
+
+L.layerGroup = function (layers) {
+	return new L.LayerGroup(layers);
+};
+
+
+/*
+ * L.FeatureGroup extends L.LayerGroup by introducing mouse events and additional methods
+ * shared between a group of interactive layers (like vectors or markers).
+ */
+
+L.FeatureGroup = L.LayerGroup.extend({
+	includes: L.Mixin.Events,
+
+	statics: {
+		EVENTS: 'click dblclick mouseover mouseout mousemove contextmenu popupopen popupclose'
+	},
+
+	addLayer: function (layer) {
+		if (this.hasLayer(layer)) {
+			return this;
+		}
+
+		if ('on' in layer) {
+			layer.on(L.FeatureGroup.EVENTS, this._propagateEvent, this);
+		}
+
+		L.LayerGroup.prototype.addLayer.call(this, layer);
+
+		if (this._popupContent && layer.bindPopup) {
+			layer.bindPopup(this._popupContent, this._popupOptions);
+		}
+
+		return this.fire('layeradd', {layer: layer});
+	},
+
+	removeLayer: function (layer) {
+		if (!this.hasLayer(layer)) {
+			return this;
+		}
+		if (layer in this._layers) {
+			layer = this._layers[layer];
+		}
+
+		if ('off' in layer) {
+			layer.off(L.FeatureGroup.EVENTS, this._propagateEvent, this);
+		}
+
+		L.LayerGroup.prototype.removeLayer.call(this, layer);
+
+		if (this._popupContent) {
+			this.invoke('unbindPopup');
+		}
+
+		return this.fire('layerremove', {layer: layer});
+	},
+
+	bindPopup: function (content, options) {
+		this._popupContent = content;
+		this._popupOptions = options;
+		return this.invoke('bindPopup', content, options);
+	},
+
+	openPopup: function (latlng) {
+		// open popup on the first layer
+		for (var id in this._layers) {
+			this._layers[id].openPopup(latlng);
+			break;
+		}
+		return this;
+	},
+
+	setStyle: function (style) {
+		return this.invoke('setStyle', style);
+	},
+
+	bringToFront: function () {
+		return this.invoke('bringToFront');
+	},
+
+	bringToBack: function () {
+		return this.invoke('bringToBack');
+	},
+
+	getBounds: function () {
+		var bounds = new L.LatLngBounds();
+
+		this.eachLayer(function (layer) {
+			bounds.extend(layer instanceof L.Marker ? layer.getLatLng() : layer.getBounds());
+		});
+
+		return bounds;
+	},
+
+	_propagateEvent: function (e) {
+		e = L.extend({
+			layer: e.target,
+			target: this
+		}, e);
+		this.fire(e.type, e);
+	}
+});
+
+L.featureGroup = function (layers) {
+	return new L.FeatureGroup(layers);
+};
+
+
+/*
+ * L.Path is a base class for rendering vector paths on a map. Inherited by Polyline, Circle, etc.
+ */
+
+L.Path = L.Class.extend({
+	includes: [L.Mixin.Events],
+
+	statics: {
+		// how much to extend the clip area around the map view
+		// (relative to its size, e.g. 0.5 is half the screen in each direction)
+		// set it so that SVG element doesn't exceed 1280px (vectors flicker on dragend if it is)
+		CLIP_PADDING: (function () {
+			var max = L.Browser.mobile ? 1280 : 2000,
+			    target = (max / Math.max(window.outerWidth, window.outerHeight) - 1) / 2;
+			return Math.max(0, Math.min(0.5, target));
+		})()
+	},
+
+	options: {
+		stroke: true,
+		color: '#0033ff',
+		dashArray: null,
+		lineCap: null,
+		lineJoin: null,
+		weight: 5,
+		opacity: 0.5,
+
+		fill: false,
+		fillColor: null, //same as color by default
+		fillOpacity: 0.2,
+
+		clickable: true
+	},
+
+	initialize: function (options) {
+		L.setOptions(this, options);
+	},
+
+	onAdd: function (map) {
+		this._map = map;
+
+		if (!this._container) {
+			this._initElements();
+			this._initEvents();
+		}
+
+		this.projectLatlngs();
+		this._updatePath();
+
+		if (this._container) {
+			this._map._pathRoot.appendChild(this._container);
+		}
+
+		this.fire('add');
+
+		map.on({
+			'viewreset': this.projectLatlngs,
+			'moveend': this._updatePath
+		}, this);
+	},
+
+	addTo: function (map) {
+		map.addLayer(this);
+		return this;
+	},
+
+	onRemove: function (map) {
+		map._pathRoot.removeChild(this._container);
+
+		// Need to fire remove event before we set _map to null as the event hooks might need the object
+		this.fire('remove');
+		this._map = null;
+
+		if (L.Browser.vml) {
+			this._container = null;
+			this._stroke = null;
+			this._fill = null;
+		}
+
+		map.off({
+			'viewreset': this.projectLatlngs,
+			'moveend': this._updatePath
+		}, this);
+	},
+
+	projectLatlngs: function () {
+		// do all projection stuff here
+	},
+
+	setStyle: function (style) {
+		L.setOptions(this, style);
+
+		if (this._container) {
+			this._updateStyle();
+		}
+
+		return this;
+	},
+
+	redraw: function () {
+		if (this._map) {
+			this.projectLatlngs();
+			this._updatePath();
+		}
+		return this;
+	}
+});
+
+L.Map.include({
+	_updatePathViewport: function () {
+		var p = L.Path.CLIP_PADDING,
+		    size = this.getSize(),
+		    panePos = L.DomUtil.getPosition(this._mapPane),
+		    min = panePos.multiplyBy(-1)._subtract(size.multiplyBy(p)._round()),
+		    max = min.add(size.multiplyBy(1 + p * 2)._round());
+
+		this._pathViewport = new L.Bounds(min, max);
+	}
+});
+
+
+/*
+ * Extends L.Path with SVG-specific rendering code.
+ */
+
+L.Path.SVG_NS = 'http://www.w3.org/2000/svg';
+
+L.Browser.svg = !!(document.createElementNS && document.createElementNS(L.Path.SVG_NS, 'svg').createSVGRect);
+
+L.Path = L.Path.extend({
+	statics: {
+		SVG: L.Browser.svg
+	},
+
+	bringToFront: function () {
+		var root = this._map._pathRoot,
+		    path = this._container;
+
+		if (path && root.lastChild !== path) {
+			root.appendChild(path);
+		}
+		return this;
+	},
+
+	bringToBack: function () {
+		var root = this._map._pathRoot,
+		    path = this._container,
+		    first = root.firstChild;
+
+		if (path && first !== path) {
+			root.insertBefore(path, first);
+		}
+		return this;
+	},
+
+	getPathString: function () {
+		// form path string here
+	},
+
+	_createElement: function (name) {
+		return document.createElementNS(L.Path.SVG_NS, name);
+	},
+
+	_initElements: function () {
+		this._map._initPathRoot();
+		this._initPath();
+		this._initStyle();
+	},
+
+	_initPath: function () {
+		this._container = this._createElement('g');
+
+		this._path = this._createElement('path');
+
+		if (this.options.className) {
+			L.DomUtil.addClass(this._path, this.options.className);
+		}
+
+		this._container.appendChild(this._path);
+	},
+
+	_initStyle: function () {
+		if (this.options.stroke) {
+			this._path.setAttribute('stroke-linejoin', 'round');
+			this._path.setAttribute('stroke-linecap', 'round');
+		}
+		if (this.options.fill) {
+			this._path.setAttribute('fill-rule', 'evenodd');
+		}
+		if (this.options.pointerEvents) {
+			this._path.setAttribute('pointer-events', this.options.pointerEvents);
+		}
+		if (!this.options.clickable && !this.options.pointerEvents) {
+			this._path.setAttribute('pointer-events', 'none');
+		}
+		this._updateStyle();
+	},
+
+	_updateStyle: function () {
+		if (this.options.stroke) {
+			this._path.setAttribute('stroke', this.options.color);
+			this._path.setAttribute('stroke-opacity', this.options.opacity);
+			this._path.setAttribute('stroke-width', this.options.weight);
+			if (this.options.dashArray) {
+				this._path.setAttribute('stroke-dasharray', this.options.dashArray);
+			} else {
+				this._path.removeAttribute('stroke-dasharray');
+			}
+			if (this.options.lineCap) {
+				this._path.setAttribute('stroke-linecap', this.options.lineCap);
+			}
+			if (this.options.lineJoin) {
+				this._path.setAttribute('stroke-linejoin', this.options.lineJoin);
+			}
+		} else {
+			this._path.setAttribute('stroke', 'none');
+		}
+		if (this.options.fill) {
+			this._path.setAttribute('fill', this.options.fillColor || this.options.color);
+			this._path.setAttribute('fill-opacity', this.options.fillOpacity);
+		} else {
+			this._path.setAttribute('fill', 'none');
+		}
+	},
+
+	_updatePath: function () {
+		var str = this.getPathString();
+		if (!str) {
+			// fix webkit empty string parsing bug
+			str = 'M0 0';
+		}
+		this._path.setAttribute('d', str);
+	},
+
+	// TODO remove duplication with L.Map
+	_initEvents: function () {
+		if (this.options.clickable) {
+			if (L.Browser.svg || !L.Browser.vml) {
+				L.DomUtil.addClass(this._path, 'leaflet-clickable');
+			}
+
+			L.DomEvent.on(this._container, 'click', this._onMouseClick, this);
+
+			var events = ['dblclick', 'mousedown', 'mouseover',
+			              'mouseout', 'mousemove', 'contextmenu'];
+			for (var i = 0; i < events.length; i++) {
+				L.DomEvent.on(this._container, events[i], this._fireMouseEvent, this);
+			}
+		}
+	},
+
+	_onMouseClick: function (e) {
+		if (this._map.dragging && this._map.dragging.moved()) { return; }
+
+		this._fireMouseEvent(e);
+	},
+
+	_fireMouseEvent: function (e) {
+		if (!this._map || !this.hasEventListeners(e.type)) { return; }
+
+		var map = this._map,
+		    containerPoint = map.mouseEventToContainerPoint(e),
+		    layerPoint = map.containerPointToLayerPoint(containerPoint),
+		    latlng = map.layerPointToLatLng(layerPoint);
+
+		this.fire(e.type, {
+			latlng: latlng,
+			layerPoint: layerPoint,
+			containerPoint: containerPoint,
+			originalEvent: e
+		});
+
+		if (e.type === 'contextmenu') {
+			L.DomEvent.preventDefault(e);
+		}
+		if (e.type !== 'mousemove') {
+			L.DomEvent.stopPropagation(e);
+		}
+	}
+});
+
+L.Map.include({
+	_initPathRoot: function () {
+		if (!this._pathRoot) {
+			this._pathRoot = L.Path.prototype._createElement('svg');
+			this._panes.overlayPane.appendChild(this._pathRoot);
+
+			if (this.options.zoomAnimation && L.Browser.any3d) {
+				L.DomUtil.addClass(this._pathRoot, 'leaflet-zoom-animated');
+
+				this.on({
+					'zoomanim': this._animatePathZoom,
+					'zoomend': this._endPathZoom
+				});
+			} else {
+				L.DomUtil.addClass(this._pathRoot, 'leaflet-zoom-hide');
+			}
+
+			this.on('moveend', this._updateSvgViewport);
+			this._updateSvgViewport();
+		}
+	},
+
+	_animatePathZoom: function (e) {
+		var scale = this.getZoomScale(e.zoom),
+		    offset = this._getCenterOffset(e.center)._multiplyBy(-scale)._add(this._pathViewport.min);
+
+		this._pathRoot.style[L.DomUtil.TRANSFORM] =
+		        L.DomUtil.getTranslateString(offset) + ' scale(' + scale + ') ';
+
+		this._pathZooming = true;
+	},
+
+	_endPathZoom: function () {
+		this._pathZooming = false;
+	},
+
+	_updateSvgViewport: function () {
+
+		if (this._pathZooming) {
+			// Do not update SVGs while a zoom animation is going on otherwise the animation will break.
+			// When the zoom animation ends we will be updated again anyway
+			// This fixes the case where you do a momentum move and zoom while the move is still ongoing.
+			return;
+		}
+
+		this._updatePathViewport();
+
+		var vp = this._pathViewport,
+		    min = vp.min,
+		    max = vp.max,
+		    width = max.x - min.x,
+		    height = max.y - min.y,
+		    root = this._pathRoot,
+		    pane = this._panes.overlayPane;
+
+		// Hack to make flicker on drag end on mobile webkit less irritating
+		if (L.Browser.mobileWebkit) {
+			pane.removeChild(root);
+		}
+
+		L.DomUtil.setPosition(root, min);
+		root.setAttribute('width', width);
+		root.setAttribute('height', height);
+		root.setAttribute('viewBox', [min.x, min.y, width, height].join(' '));
+
+		if (L.Browser.mobileWebkit) {
+			pane.appendChild(root);
+		}
+	}
+});
+
+
+/*
+ * Popup extension to L.Path (polylines, polygons, circles), adding popup-related methods.
+ */
+
+L.Path.include({
+
+	bindPopup: function (content, options) {
+
+		if (content instanceof L.Popup) {
+			this._popup = content;
+		} else {
+			if (!this._popup || options) {
+				this._popup = new L.Popup(options, this);
+			}
+			this._popup.setContent(content);
+		}
+
+		if (!this._popupHandlersAdded) {
+			this
+			    .on('click', this._openPopup, this)
+			    .on('remove', this.closePopup, this);
+
+			this._popupHandlersAdded = true;
+		}
+
+		return this;
+	},
+
+	unbindPopup: function () {
+		if (this._popup) {
+			this._popup = null;
+			this
+			    .off('click', this._openPopup)
+			    .off('remove', this.closePopup);
+
+			this._popupHandlersAdded = false;
+		}
+		return this;
+	},
+
+	openPopup: function (latlng) {
+
+		if (this._popup) {
+			// open the popup from one of the path's points if not specified
+			latlng = latlng || this._latlng ||
+			         this._latlngs[Math.floor(this._latlngs.length / 2)];
+
+			this._openPopup({latlng: latlng});
+		}
+
+		return this;
+	},
+
+	closePopup: function () {
+		if (this._popup) {
+			this._popup._close();
+		}
+		return this;
+	},
+
+	_openPopup: function (e) {
+		this._popup.setLatLng(e.latlng);
+		this._map.openPopup(this._popup);
+	}
+});
+
+
+/*
+ * Vector rendering for IE6-8 through VML.
+ * Thanks to Dmitry Baranovsky and his Raphael library for inspiration!
+ */
+
+L.Browser.vml = !L.Browser.svg && (function () {
+	try {
+		var div = document.createElement('div');
+		div.innerHTML = '<v:shape adj="1"/>';
+
+		var shape = div.firstChild;
+		shape.style.behavior = 'url(#default#VML)';
+
+		return shape && (typeof shape.adj === 'object');
+
+	} catch (e) {
+		return false;
+	}
+}());
+
+L.Path = L.Browser.svg || !L.Browser.vml ? L.Path : L.Path.extend({
+	statics: {
+		VML: true,
+		CLIP_PADDING: 0.02
+	},
+
+	_createElement: (function () {
+		try {
+			document.namespaces.add('lvml', 'urn:schemas-microsoft-com:vml');
+			return function (name) {
+				return document.createElement('<lvml:' + name + ' class="lvml">');
+			};
+		} catch (e) {
+			return function (name) {
+				return document.createElement(
+				        '<' + name + ' xmlns="urn:schemas-microsoft.com:vml" class="lvml">');
+			};
+		}
+	}()),
+
+	_initPath: function () {
+		var container = this._container = this._createElement('shape');
+
+		L.DomUtil.addClass(container, 'leaflet-vml-shape' +
+			(this.options.className ? ' ' + this.options.className : ''));
+
+		if (this.options.clickable) {
+			L.DomUtil.addClass(container, 'leaflet-clickable');
+		}
+
+		container.coordsize = '1 1';
+
+		this._path = this._createElement('path');
+		container.appendChild(this._path);
+
+		this._map._pathRoot.appendChild(container);
+	},
+
+	_initStyle: function () {
+		this._updateStyle();
+	},
+
+	_updateStyle: function () {
+		var stroke = this._stroke,
+		    fill = this._fill,
+		    options = this.options,
+		    container = this._container;
+
+		container.stroked = options.stroke;
+		container.filled = options.fill;
+
+		if (options.stroke) {
+			if (!stroke) {
+				stroke = this._stroke = this._createElement('stroke');
+				stroke.endcap = 'round';
+				container.appendChild(stroke);
+			}
+			stroke.weight = options.weight + 'px';
+			stroke.color = options.color;
+			stroke.opacity = options.opacity;
+
+			if (options.dashArray) {
+				stroke.dashStyle = L.Util.isArray(options.dashArray) ?
+				    options.dashArray.join(' ') :
+				    options.dashArray.replace(/( *, *)/g, ' ');
+			} else {
+				stroke.dashStyle = '';
+			}
+			if (options.lineCap) {
+				stroke.endcap = options.lineCap.replace('butt', 'flat');
+			}
+			if (options.lineJoin) {
+				stroke.joinstyle = options.lineJoin;
+			}
+
+		} else if (stroke) {
+			container.removeChild(stroke);
+			this._stroke = null;
+		}
+
+		if (options.fill) {
+			if (!fill) {
+				fill = this._fill = this._createElement('fill');
+				container.appendChild(fill);
+			}
+			fill.color = options.fillColor || options.color;
+			fill.opacity = options.fillOpacity;
+
+		} else if (fill) {
+			container.removeChild(fill);
+			this._fill = null;
+		}
+	},
+
+	_updatePath: function () {
+		var style = this._container.style;
+
+		style.display = 'none';
+		this._path.v = this.getPathString() + ' '; // the space fixes IE empty path string bug
+		style.display = '';
+	}
+});
+
+L.Map.include(L.Browser.svg || !L.Browser.vml ? {} : {
+	_initPathRoot: function () {
+		if (this._pathRoot) { return; }
+
+		var root = this._pathRoot = document.createElement('div');
+		root.className = 'leaflet-vml-container';
+		this._panes.overlayPane.appendChild(root);
+
+		this.on('moveend', this._updatePathViewport);
+		this._updatePathViewport();
+	}
+});
+
+
+/*
+ * Vector rendering for all browsers that support canvas.
+ */
+
+L.Browser.canvas = (function () {
+	return !!document.createElement('canvas').getContext;
+}());
+
+L.Path = (L.Path.SVG && !window.L_PREFER_CANVAS) || !L.Browser.canvas ? L.Path : L.Path.extend({
+	statics: {
+		//CLIP_PADDING: 0.02, // not sure if there's a need to set it to a small value
+		CANVAS: true,
+		SVG: false
+	},
+
+	redraw: function () {
+		if (this._map) {
+			this.projectLatlngs();
+			this._requestUpdate();
+		}
+		return this;
+	},
+
+	setStyle: function (style) {
+		L.setOptions(this, style);
+
+		if (this._map) {
+			this._updateStyle();
+			this._requestUpdate();
+		}
+		return this;
+	},
+
+	onRemove: function (map) {
+		map
+		    .off('viewreset', this.projectLatlngs, this)
+		    .off('moveend', this._updatePath, this);
+
+		if (this.options.clickable) {
+			this._map.off('click', this._onClick, this);
+			this._map.off('mousemove', this._onMouseMove, this);
+		}
+
+		this._requestUpdate();
+		
+		this.fire('remove');
+		this._map = null;
+	},
+
+	_requestUpdate: function () {
+		if (this._map && !L.Path._updateRequest) {
+			L.Path._updateRequest = L.Util.requestAnimFrame(this._fireMapMoveEnd, this._map);
+		}
+	},
+
+	_fireMapMoveEnd: function () {
+		L.Path._updateRequest = null;
+		this.fire('moveend');
+	},
+
+	_initElements: function () {
+		this._map._initPathRoot();
+		this._ctx = this._map._canvasCtx;
+	},
+
+	_updateStyle: function () {
+		var options = this.options;
+
+		if (options.stroke) {
+			this._ctx.lineWidth = options.weight;
+			this._ctx.strokeStyle = options.color;
+		}
+		if (options.fill) {
+			this._ctx.fillStyle = options.fillColor || options.color;
+		}
+
+		if (options.lineCap) {
+			this._ctx.lineCap = options.lineCap;
+		}
+		if (options.lineJoin) {
+			this._ctx.lineJoin = options.lineJoin;
+		}
+	},
+
+	_drawPath: function () {
+		var i, j, len, len2, point, drawMethod;
+
+		this._ctx.beginPath();
+
+		for (i = 0, len = this._parts.length; i < len; i++) {
+			for (j = 0, len2 = this._parts[i].length; j < len2; j++) {
+				point = this._parts[i][j];
+				drawMethod = (j === 0 ? 'move' : 'line') + 'To';
+
+				this._ctx[drawMethod](point.x, point.y);
+			}
+			// TODO refactor ugly hack
+			if (this instanceof L.Polygon) {
+				this._ctx.closePath();
+			}
+		}
+	},
+
+	_checkIfEmpty: function () {
+		return !this._parts.length;
+	},
+
+	_updatePath: function () {
+		if (this._checkIfEmpty()) { return; }
+
+		var ctx = this._ctx,
+		    options = this.options;
+
+		this._drawPath();
+		ctx.save();
+		this._updateStyle();
+
+		if (options.fill) {
+			ctx.globalAlpha = options.fillOpacity;
+			ctx.fill(options.fillRule || 'evenodd');
+		}
+
+		if (options.stroke) {
+			ctx.globalAlpha = options.opacity;
+			ctx.stroke();
+		}
+
+		ctx.restore();
+
+		// TODO optimization: 1 fill/stroke for all features with equal style instead of 1 for each feature
+	},
+
+	_initEvents: function () {
+		if (this.options.clickable) {
+			this._map.on('mousemove', this._onMouseMove, this);
+			this._map.on('click dblclick contextmenu', this._fireMouseEvent, this);
+		}
+	},
+
+	_fireMouseEvent: function (e) {
+		if (this._containsPoint(e.layerPoint)) {
+			this.fire(e.type, e);
+		}
+	},
+
+	_onMouseMove: function (e) {
+		if (!this._map || this._map._animatingZoom) { return; }
+
+		// TODO don't do on each move
+		if (this._containsPoint(e.layerPoint)) {
+			this._ctx.canvas.style.cursor = 'pointer';
+			this._mouseInside = true;
+			this.fire('mouseover', e);
+
+		} else if (this._mouseInside) {
+			this._ctx.canvas.style.cursor = '';
+			this._mouseInside = false;
+			this.fire('mouseout', e);
+		}
+	}
+});
+
+L.Map.include((L.Path.SVG && !window.L_PREFER_CANVAS) || !L.Browser.canvas ? {} : {
+	_initPathRoot: function () {
+		var root = this._pathRoot,
+		    ctx;
+
+		if (!root) {
+			root = this._pathRoot = document.createElement('canvas');
+			root.style.position = 'absolute';
+			ctx = this._canvasCtx = root.getContext('2d');
+
+			ctx.lineCap = 'round';
+			ctx.lineJoin = 'round';
+
+			this._panes.overlayPane.appendChild(root);
+
+			if (this.options.zoomAnimation) {
+				this._pathRoot.className = 'leaflet-zoom-animated';
+				this.on('zoomanim', this._animatePathZoom);
+				this.on('zoomend', this._endPathZoom);
+			}
+			this.on('moveend', this._updateCanvasViewport);
+			this._updateCanvasViewport();
+		}
+	},
+
+	_updateCanvasViewport: function () {
+		// don't redraw while zooming. See _updateSvgViewport for more details
+		if (this._pathZooming) { return; }
+		this._updatePathViewport();
+
+		var vp = this._pathViewport,
+		    min = vp.min,
+		    size = vp.max.subtract(min),
+		    root = this._pathRoot;
+
+		//TODO check if this works properly on mobile webkit
+		L.DomUtil.setPosition(root, min);
+		root.width = size.x;
+		root.height = size.y;
+		root.getContext('2d').translate(-min.x, -min.y);
+	}
+});
+
+
+/*
+ * L.LineUtil contains different utility functions for line segments
+ * and polylines (clipping, simplification, distances, etc.)
+ */
+
+/*jshint bitwise:false */ // allow bitwise operations for this file
+
+L.LineUtil = {
+
+	// Simplify polyline with vertex reduction and Douglas-Peucker simplification.
+	// Improves rendering performance dramatically by lessening the number of points to draw.
+
+	simplify: function (/*Point[]*/ points, /*Number*/ tolerance) {
+		if (!tolerance || !points.length) {
+			return points.slice();
+		}
+
+		var sqTolerance = tolerance * tolerance;
+
+		// stage 1: vertex reduction
+		points = this._reducePoints(points, sqTolerance);
+
+		// stage 2: Douglas-Peucker simplification
+		points = this._simplifyDP(points, sqTolerance);
+
+		return points;
+	},
+
+	// distance from a point to a segment between two points
+	pointToSegmentDistance:  function (/*Point*/ p, /*Point*/ p1, /*Point*/ p2) {
+		return Math.sqrt(this._sqClosestPointOnSegment(p, p1, p2, true));
+	},
+
+	closestPointOnSegment: function (/*Point*/ p, /*Point*/ p1, /*Point*/ p2) {
+		return this._sqClosestPointOnSegment(p, p1, p2);
+	},
+
+	// Douglas-Peucker simplification, see http://en.wikipedia.org/wiki/Douglas-Peucker_algorithm
+	_simplifyDP: function (points, sqTolerance) {
+
+		var len = points.length,
+		    ArrayConstructor = typeof Uint8Array !== undefined + '' ? Uint8Array : Array,
+		    markers = new ArrayConstructor(len);
+
+		markers[0] = markers[len - 1] = 1;
+
+		this._simplifyDPStep(points, markers, sqTolerance, 0, len - 1);
+
+		var i,
+		    newPoints = [];
+
+		for (i = 0; i < len; i++) {
+			if (markers[i]) {
+				newPoints.push(points[i]);
+			}
+		}
+
+		return newPoints;
+	},
+
+	_simplifyDPStep: function (points, markers, sqTolerance, first, last) {
+
+		var maxSqDist = 0,
+		    index, i, sqDist;
+
+		for (i = first + 1; i <= last - 1; i++) {
+			sqDist = this._sqClosestPointOnSegment(points[i], points[first], points[last], true);
+
+			if (sqDist > maxSqDist) {
+				index = i;
+				maxSqDist = sqDist;
+			}
+		}
+
+		if (maxSqDist > sqTolerance) {
+			markers[index] = 1;
+
+			this._simplifyDPStep(points, markers, sqTolerance, first, index);
+			this._simplifyDPStep(points, markers, sqTolerance, index, last);
+		}
+	},
+
+	// reduce points that are too close to each other to a single point
+	_reducePoints: function (points, sqTolerance) {
+		var reducedPoints = [points[0]];
+
+		for (var i = 1, prev = 0, len = points.length; i < len; i++) {
+			if (this._sqDist(points[i], points[prev]) > sqTolerance) {
+				reducedPoints.push(points[i]);
+				prev = i;
+			}
+		}
+		if (prev < len - 1) {
+			reducedPoints.push(points[len - 1]);
+		}
+		return reducedPoints;
+	},
+
+	// Cohen-Sutherland line clipping algorithm.
+	// Used to avoid rendering parts of a polyline that are not currently visible.
+
+	clipSegment: function (a, b, bounds, useLastCode) {
+		var codeA = useLastCode ? this._lastCode : this._getBitCode(a, bounds),
+		    codeB = this._getBitCode(b, bounds),
+
+		    codeOut, p, newCode;
+
+		// save 2nd code to avoid calculating it on the next segment
+		this._lastCode = codeB;
+
+		while (true) {
+			// if a,b is inside the clip window (trivial accept)
+			if (!(codeA | codeB)) {
+				return [a, b];
+			// if a,b is outside the clip window (trivial reject)
+			} else if (codeA & codeB) {
+				return false;
+			// other cases
+			} else {
+				codeOut = codeA || codeB;
+				p = this._getEdgeIntersection(a, b, codeOut, bounds);
+				newCode = this._getBitCode(p, bounds);
+
+				if (codeOut === codeA) {
+					a = p;
+					codeA = newCode;
+				} else {
+					b = p;
+					codeB = newCode;
+				}
+			}
+		}
+	},
+
+	_getEdgeIntersection: function (a, b, code, bounds) {
+		var dx = b.x - a.x,
+		    dy = b.y - a.y,
+		    min = bounds.min,
+		    max = bounds.max;
+
+		if (code & 8) { // top
+			return new L.Point(a.x + dx * (max.y - a.y) / dy, max.y);
+		} else if (code & 4) { // bottom
+			return new L.Point(a.x + dx * (min.y - a.y) / dy, min.y);
+		} else if (code & 2) { // right
+			return new L.Point(max.x, a.y + dy * (max.x - a.x) / dx);
+		} else if (code & 1) { // left
+			return new L.Point(min.x, a.y + dy * (min.x - a.x) / dx);
+		}
+	},
+
+	_getBitCode: function (/*Point*/ p, bounds) {
+		var code = 0;
+
+		if (p.x < bounds.min.x) { // left
+			code |= 1;
+		} else if (p.x > bounds.max.x) { // right
+			code |= 2;
+		}
+		if (p.y < bounds.min.y) { // bottom
+			code |= 4;
+		} else if (p.y > bounds.max.y) { // top
+			code |= 8;
+		}
+
+		return code;
+	},
+
+	// square distance (to avoid unnecessary Math.sqrt calls)
+	_sqDist: function (p1, p2) {
+		var dx = p2.x - p1.x,
+		    dy = p2.y - p1.y;
+		return dx * dx + dy * dy;
+	},
+
+	// return closest point on segment or distance to that point
+	_sqClosestPointOnSegment: function (p, p1, p2, sqDist) {
+		var x = p1.x,
+		    y = p1.y,
+		    dx = p2.x - x,
+		    dy = p2.y - y,
+		    dot = dx * dx + dy * dy,
+		    t;
+
+		if (dot > 0) {
+			t = ((p.x - x) * dx + (p.y - y) * dy) / dot;
+
+			if (t > 1) {
+				x = p2.x;
+				y = p2.y;
+			} else if (t > 0) {
+				x += dx * t;
+				y += dy * t;
+			}
+		}
+
+		dx = p.x - x;
+		dy = p.y - y;
+
+		return sqDist ? dx * dx + dy * dy : new L.Point(x, y);
+	}
+};
+
+
+/*
+ * L.Polyline is used to display polylines on a map.
+ */
+
+L.Polyline = L.Path.extend({
+	initialize: function (latlngs, options) {
+		L.Path.prototype.initialize.call(this, options);
+
+		this._latlngs = this._convertLatLngs(latlngs);
+	},
+
+	options: {
+		// how much to simplify the polyline on each zoom level
+		// more = better performance and smoother look, less = more accurate
+		smoothFactor: 1.0,
+		noClip: false
+	},
+
+	projectLatlngs: function () {
+		this._originalPoints = [];
+
+		for (var i = 0, len = this._latlngs.length; i < len; i++) {
+			this._originalPoints[i] = this._map.latLngToLayerPoint(this._latlngs[i]);
+		}
+	},
+
+	getPathString: function () {
+		for (var i = 0, len = this._parts.length, str = ''; i < len; i++) {
+			str += this._getPathPartStr(this._parts[i]);
+		}
+		return str;
+	},
+
+	getLatLngs: function () {
+		return this._latlngs;
+	},
+
+	setLatLngs: function (latlngs) {
+		this._latlngs = this._convertLatLngs(latlngs);
+		return this.redraw();
+	},
+
+	addLatLng: function (latlng) {
+		this._latlngs.push(L.latLng(latlng));
+		return this.redraw();
+	},
+
+	spliceLatLngs: function () { // (Number index, Number howMany)
+		var removed = [].splice.apply(this._latlngs, arguments);
+		this._convertLatLngs(this._latlngs, true);
+		this.redraw();
+		return removed;
+	},
+
+	closestLayerPoint: function (p) {
+		var minDistance = Infinity, parts = this._parts, p1, p2, minPoint = null;
+
+		for (var j = 0, jLen = parts.length; j < jLen; j++) {
+			var points = parts[j];
+			for (var i = 1, len = points.length; i < len; i++) {
+				p1 = points[i - 1];
+				p2 = points[i];
+				var sqDist = L.LineUtil._sqClosestPointOnSegment(p, p1, p2, true);
+				if (sqDist < minDistance) {
+					minDistance = sqDist;
+					minPoint = L.LineUtil._sqClosestPointOnSegment(p, p1, p2);
+				}
+			}
+		}
+		if (minPoint) {
+			minPoint.distance = Math.sqrt(minDistance);
+		}
+		return minPoint;
+	},
+
+	getBounds: function () {
+		return new L.LatLngBounds(this.getLatLngs());
+	},
+
+	_convertLatLngs: function (latlngs, overwrite) {
+		var i, len, target = overwrite ? latlngs : [];
+
+		for (i = 0, len = latlngs.length; i < len; i++) {
+			if (L.Util.isArray(latlngs[i]) && typeof latlngs[i][0] !== 'number') {
+				return;
+			}
+			target[i] = L.latLng(latlngs[i]);
+		}
+		return target;
+	},
+
+	_initEvents: function () {
+		L.Path.prototype._initEvents.call(this);
+	},
+
+	_getPathPartStr: function (points) {
+		var round = L.Path.VML;
+
+		for (var j = 0, len2 = points.length, str = '', p; j < len2; j++) {
+			p = points[j];
+			if (round) {
+				p._round();
+			}
+			str += (j ? 'L' : 'M') + p.x + ' ' + p.y;
+		}
+		return str;
+	},
+
+	_clipPoints: function () {
+		var points = this._originalPoints,
+		    len = points.length,
+		    i, k, segment;
+
+		if (this.options.noClip) {
+			this._parts = [points];
+			return;
+		}
+
+		this._parts = [];
+
+		var parts = this._parts,
+		    vp = this._map._pathViewport,
+		    lu = L.LineUtil;
+
+		for (i = 0, k = 0; i < len - 1; i++) {
+			segment = lu.clipSegment(points[i], points[i + 1], vp, i);
+			if (!segment) {
+				continue;
+			}
+
+			parts[k] = parts[k] || [];
+			parts[k].push(segment[0]);
+
+			// if segment goes out of screen, or it's the last one, it's the end of the line part
+			if ((segment[1] !== points[i + 1]) || (i === len - 2)) {
+				parts[k].push(segment[1]);
+				k++;
+			}
+		}
+	},
+
+	// simplify each clipped part of the polyline
+	_simplifyPoints: function () {
+		var parts = this._parts,
+		    lu = L.LineUtil;
+
+		for (var i = 0, len = parts.length; i < len; i++) {
+			parts[i] = lu.simplify(parts[i], this.options.smoothFactor);
+		}
+	},
+
+	_updatePath: function () {
+		if (!this._map) { return; }
+
+		this._clipPoints();
+		this._simplifyPoints();
+
+		L.Path.prototype._updatePath.call(this);
+	}
+});
+
+L.polyline = function (latlngs, options) {
+	return new L.Polyline(latlngs, options);
+};
+
+
+/*
+ * L.PolyUtil contains utility functions for polygons (clipping, etc.).
+ */
+
+/*jshint bitwise:false */ // allow bitwise operations here
+
+L.PolyUtil = {};
+
+/*
+ * Sutherland-Hodgeman polygon clipping algorithm.
+ * Used to avoid rendering parts of a polygon that are not currently visible.
+ */
+L.PolyUtil.clipPolygon = function (points, bounds) {
+	var clippedPoints,
+	    edges = [1, 4, 2, 8],
+	    i, j, k,
+	    a, b,
+	    len, edge, p,
+	    lu = L.LineUtil;
+
+	for (i = 0, len = points.length; i < len; i++) {
+		points[i]._code = lu._getBitCode(points[i], bounds);
+	}
+
+	// for each edge (left, bottom, right, top)
+	for (k = 0; k < 4; k++) {
+		edge = edges[k];
+		clippedPoints = [];
+
+		for (i = 0, len = points.length, j = len - 1; i < len; j = i++) {
+			a = points[i];
+			b = points[j];
+
+			// if a is inside the clip window
+			if (!(a._code & edge)) {
+				// if b is outside the clip window (a->b goes out of screen)
+				if (b._code & edge) {
+					p = lu._getEdgeIntersection(b, a, edge, bounds);
+					p._code = lu._getBitCode(p, bounds);
+					clippedPoints.push(p);
+				}
+				clippedPoints.push(a);
+
+			// else if b is inside the clip window (a->b enters the screen)
+			} else if (!(b._code & edge)) {
+				p = lu._getEdgeIntersection(b, a, edge, bounds);
+				p._code = lu._getBitCode(p, bounds);
+				clippedPoints.push(p);
+			}
+		}
+		points = clippedPoints;
+	}
+
+	return points;
+};
+
+
+/*
+ * L.Polygon is used to display polygons on a map.
+ */
+
+L.Polygon = L.Polyline.extend({
+	options: {
+		fill: true
+	},
+
+	initialize: function (latlngs, options) {
+		L.Polyline.prototype.initialize.call(this, latlngs, options);
+		this._initWithHoles(latlngs);
+	},
+
+	_initWithHoles: function (latlngs) {
+		var i, len, hole;
+		if (latlngs && L.Util.isArray(latlngs[0]) && (typeof latlngs[0][0] !== 'number')) {
+			this._latlngs = this._convertLatLngs(latlngs[0]);
+			this._holes = latlngs.slice(1);
+
+			for (i = 0, len = this._holes.length; i < len; i++) {
+				hole = this._holes[i] = this._convertLatLngs(this._holes[i]);
+				if (hole[0].equals(hole[hole.length - 1])) {
+					hole.pop();
+				}
+			}
+		}
+
+		// filter out last point if its equal to the first one
+		latlngs = this._latlngs;
+
+		if (latlngs.length >= 2 && latlngs[0].equals(latlngs[latlngs.length - 1])) {
+			latlngs.pop();
+		}
+	},
+
+	projectLatlngs: function () {
+		L.Polyline.prototype.projectLatlngs.call(this);
+
+		// project polygon holes points
+		// TODO move this logic to Polyline to get rid of duplication
+		this._holePoints = [];
+
+		if (!this._holes) { return; }
+
+		var i, j, len, len2;
+
+		for (i = 0, len = this._holes.length; i < len; i++) {
+			this._holePoints[i] = [];
+
+			for (j = 0, len2 = this._holes[i].length; j < len2; j++) {
+				this._holePoints[i][j] = this._map.latLngToLayerPoint(this._holes[i][j]);
+			}
+		}
+	},
+
+	setLatLngs: function (latlngs) {
+		if (latlngs && L.Util.isArray(latlngs[0]) && (typeof latlngs[0][0] !== 'number')) {
+			this._initWithHoles(latlngs);
+			return this.redraw();
+		} else {
+			return L.Polyline.prototype.setLatLngs.call(this, latlngs);
+		}
+	},
+
+	_clipPoints: function () {
+		var points = this._originalPoints,
+		    newParts = [];
+
+		this._parts = [points].concat(this._holePoints);
+
+		if (this.options.noClip) { return; }
+
+		for (var i = 0, len = this._parts.length; i < len; i++) {
+			var clipped = L.PolyUtil.clipPolygon(this._parts[i], this._map._pathViewport);
+			if (clipped.length) {
+				newParts.push(clipped);
+			}
+		}
+
+		this._parts = newParts;
+	},
+
+	_getPathPartStr: function (points) {
+		var str = L.Polyline.prototype._getPathPartStr.call(this, points);
+		return str + (L.Browser.svg ? 'z' : 'x');
+	}
+});
+
+L.polygon = function (latlngs, options) {
+	return new L.Polygon(latlngs, options);
+};
+
+
+/*
+ * Contains L.MultiPolyline and L.MultiPolygon layers.
+ */
+
+(function () {
+	function createMulti(Klass) {
+
+		return L.FeatureGroup.extend({
+
+			initialize: function (latlngs, options) {
+				this._layers = {};
+				this._options = options;
+				this.setLatLngs(latlngs);
+			},
+
+			setLatLngs: function (latlngs) {
+				var i = 0,
+				    len = latlngs.length;
+
+				this.eachLayer(function (layer) {
+					if (i < len) {
+						layer.setLatLngs(latlngs[i++]);
+					} else {
+						this.removeLayer(layer);
+					}
+				}, this);
+
+				while (i < len) {
+					this.addLayer(new Klass(latlngs[i++], this._options));
+				}
+
+				return this;
+			},
+
+			getLatLngs: function () {
+				var latlngs = [];
+
+				this.eachLayer(function (layer) {
+					latlngs.push(layer.getLatLngs());
+				});
+
+				return latlngs;
+			}
+		});
+	}
+
+	L.MultiPolyline = createMulti(L.Polyline);
+	L.MultiPolygon = createMulti(L.Polygon);
+
+	L.multiPolyline = function (latlngs, options) {
+		return new L.MultiPolyline(latlngs, options);
+	};
+
+	L.multiPolygon = function (latlngs, options) {
+		return new L.MultiPolygon(latlngs, options);
+	};
+}());
+
+
+/*
+ * L.Rectangle extends Polygon and creates a rectangle when passed a LatLngBounds object.
+ */
+
+L.Rectangle = L.Polygon.extend({
+	initialize: function (latLngBounds, options) {
+		L.Polygon.prototype.initialize.call(this, this._boundsToLatLngs(latLngBounds), options);
+	},
+
+	setBounds: function (latLngBounds) {
+		this.setLatLngs(this._boundsToLatLngs(latLngBounds));
+	},
+
+	_boundsToLatLngs: function (latLngBounds) {
+		latLngBounds = L.latLngBounds(latLngBounds);
+		return [
+			latLngBounds.getSouthWest(),
+			latLngBounds.getNorthWest(),
+			latLngBounds.getNorthEast(),
+			latLngBounds.getSouthEast()
+		];
+	}
+});
+
+L.rectangle = function (latLngBounds, options) {
+	return new L.Rectangle(latLngBounds, options);
+};
+
+
+/*
+ * L.Circle is a circle overlay (with a certain radius in meters).
+ */
+
+L.Circle = L.Path.extend({
+	initialize: function (latlng, radius, options) {
+		L.Path.prototype.initialize.call(this, options);
+
+		this._latlng = L.latLng(latlng);
+		this._mRadius = radius;
+	},
+
+	options: {
+		fill: true
+	},
+
+	setLatLng: function (latlng) {
+		this._latlng = L.latLng(latlng);
+		return this.redraw();
+	},
+
+	setRadius: function (radius) {
+		this._mRadius = radius;
+		return this.redraw();
+	},
+
+	projectLatlngs: function () {
+		var lngRadius = this._getLngRadius(),
+		    latlng = this._latlng,
+		    pointLeft = this._map.latLngToLayerPoint([latlng.lat, latlng.lng - lngRadius]);
+
+		this._point = this._map.latLngToLayerPoint(latlng);
+		this._radius = Math.max(this._point.x - pointLeft.x, 1);
+	},
+
+	getBounds: function () {
+		var lngRadius = this._getLngRadius(),
+		    latRadius = (this._mRadius / 40075017) * 360,
+		    latlng = this._latlng;
+
+		return new L.LatLngBounds(
+		        [latlng.lat - latRadius, latlng.lng - lngRadius],
+		        [latlng.lat + latRadius, latlng.lng + lngRadius]);
+	},
+
+	getLatLng: function () {
+		return this._latlng;
+	},
+
+	getPathString: function () {
+		var p = this._point,
+		    r = this._radius;
+
+		if (this._checkIfEmpty()) {
+			return '';
+		}
+
+		if (L.Browser.svg) {
+			return 'M' + p.x + ',' + (p.y - r) +
+			       'A' + r + ',' + r + ',0,1,1,' +
+			       (p.x - 0.1) + ',' + (p.y - r) + ' z';
+		} else {
+			p._round();
+			r = Math.round(r);
+			return 'AL ' + p.x + ',' + p.y + ' ' + r + ',' + r + ' 0,' + (65535 * 360);
+		}
+	},
+
+	getRadius: function () {
+		return this._mRadius;
+	},
+
+	// TODO Earth hardcoded, move into projection code!
+
+	_getLatRadius: function () {
+		return (this._mRadius / 40075017) * 360;
+	},
+
+	_getLngRadius: function () {
+		return this._getLatRadius() / Math.cos(L.LatLng.DEG_TO_RAD * this._latlng.lat);
+	},
+
+	_checkIfEmpty: function () {
+		if (!this._map) {
+			return false;
+		}
+		var vp = this._map._pathViewport,
+		    r = this._radius,
+		    p = this._point;
+
+		return p.x - r > vp.max.x || p.y - r > vp.max.y ||
+		       p.x + r < vp.min.x || p.y + r < vp.min.y;
+	}
+});
+
+L.circle = function (latlng, radius, options) {
+	return new L.Circle(latlng, radius, options);
+};
+
+
+/*
+ * L.CircleMarker is a circle overlay with a permanent pixel radius.
+ */
+
+L.CircleMarker = L.Circle.extend({
+	options: {
+		radius: 10,
+		weight: 2
+	},
+
+	initialize: function (latlng, options) {
+		L.Circle.prototype.initialize.call(this, latlng, null, options);
+		this._radius = this.options.radius;
+	},
+
+	projectLatlngs: function () {
+		this._point = this._map.latLngToLayerPoint(this._latlng);
+	},
+
+	_updateStyle : function () {
+		L.Circle.prototype._updateStyle.call(this);
+		this.setRadius(this.options.radius);
+	},
+
+	setLatLng: function (latlng) {
+		L.Circle.prototype.setLatLng.call(this, latlng);
+		if (this._popup && this._popup._isOpen) {
+			this._popup.setLatLng(latlng);
+		}
+		return this;
+	},
+
+	setRadius: function (radius) {
+		this.options.radius = this._radius = radius;
+		return this.redraw();
+	},
+
+	getRadius: function () {
+		return this._radius;
+	}
+});
+
+L.circleMarker = function (latlng, options) {
+	return new L.CircleMarker(latlng, options);
+};
+
+
+/*
+ * Extends L.Polyline to be able to manually detect clicks on Canvas-rendered polylines.
+ */
+
+L.Polyline.include(!L.Path.CANVAS ? {} : {
+	_containsPoint: function (p, closed) {
+		var i, j, k, len, len2, dist, part,
+		    w = this.options.weight / 2;
+
+		if (L.Browser.touch) {
+			w += 10; // polyline click tolerance on touch devices
+		}
+
+		for (i = 0, len = this._parts.length; i < len; i++) {
+			part = this._parts[i];
+			for (j = 0, len2 = part.length, k = len2 - 1; j < len2; k = j++) {
+				if (!closed && (j === 0)) {
+					continue;
+				}
+
+				dist = L.LineUtil.pointToSegmentDistance(p, part[k], part[j]);
+
+				if (dist <= w) {
+					return true;
+				}
+			}
+		}
+		return false;
+	}
+});
+
+
+/*
+ * Extends L.Polygon to be able to manually detect clicks on Canvas-rendered polygons.
+ */
+
+L.Polygon.include(!L.Path.CANVAS ? {} : {
+	_containsPoint: function (p) {
+		var inside = false,
+		    part, p1, p2,
+		    i, j, k,
+		    len, len2;
+
+		// TODO optimization: check if within bounds first
+
+		if (L.Polyline.prototype._containsPoint.call(this, p, true)) {
+			// click on polygon border
+			return true;
+		}
+
+		// ray casting algorithm for detecting if point is in polygon
+
+		for (i = 0, len = this._parts.length; i < len; i++) {
+			part = this._parts[i];
+
+			for (j = 0, len2 = part.length, k = len2 - 1; j < len2; k = j++) {
+				p1 = part[j];
+				p2 = part[k];
+
+				if (((p1.y > p.y) !== (p2.y > p.y)) &&
+						(p.x < (p2.x - p1.x) * (p.y - p1.y) / (p2.y - p1.y) + p1.x)) {
+					inside = !inside;
+				}
+			}
+		}
+
+		return inside;
+	}
+});
+
+
+/*
+ * Extends L.Circle with Canvas-specific code.
+ */
+
+L.Circle.include(!L.Path.CANVAS ? {} : {
+	_drawPath: function () {
+		var p = this._point;
+		this._ctx.beginPath();
+		this._ctx.arc(p.x, p.y, this._radius, 0, Math.PI * 2, false);
+	},
+
+	_containsPoint: function (p) {
+		var center = this._point,
+		    w2 = this.options.stroke ? this.options.weight / 2 : 0;
+
+		return (p.distanceTo(center) <= this._radius + w2);
+	}
+});
+
+
+/*
+ * CircleMarker canvas specific drawing parts.
+ */
+
+L.CircleMarker.include(!L.Path.CANVAS ? {} : {
+	_updateStyle: function () {
+		L.Path.prototype._updateStyle.call(this);
+	}
+});
+
+
+/*
+ * L.GeoJSON turns any GeoJSON data into a Leaflet layer.
+ */
+
+L.GeoJSON = L.FeatureGroup.extend({
+
+	initialize: function (geojson, options) {
+		L.setOptions(this, options);
+
+		this._layers = {};
+
+		if (geojson) {
+			this.addData(geojson);
+		}
+	},
+
+	addData: function (geojson) {
+		var features = L.Util.isArray(geojson) ? geojson : geojson.features,
+		    i, len, feature;
+
+		if (features) {
+			for (i = 0, len = features.length; i < len; i++) {
+				// Only add this if geometry or geometries are set and not null
+				feature = features[i];
+				if (feature.geometries || feature.geometry || feature.features || feature.coordinates) {
+					this.addData(features[i]);
+				}
+			}
+			return this;
+		}
+
+		var options = this.options;
+
+		if (options.filter && !options.filter(geojson)) { return; }
+
+		var layer = L.GeoJSON.geometryToLayer(geojson, options.pointToLayer, options.coordsToLatLng, options);
+		layer.feature = L.GeoJSON.asFeature(geojson);
+
+		layer.defaultOptions = layer.options;
+		this.resetStyle(layer);
+
+		if (options.onEachFeature) {
+			options.onEachFeature(geojson, layer);
+		}
+
+		return this.addLayer(layer);
+	},
+
+	resetStyle: function (layer) {
+		var style = this.options.style;
+		if (style) {
+			// reset any custom styles
+			L.Util.extend(layer.options, layer.defaultOptions);
+
+			this._setLayerStyle(layer, style);
+		}
+	},
+
+	setStyle: function (style) {
+		this.eachLayer(function (layer) {
+			this._setLayerStyle(layer, style);
+		}, this);
+	},
+
+	_setLayerStyle: function (layer, style) {
+		if (typeof style === 'function') {
+			style = style(layer.feature);
+		}
+		if (layer.setStyle) {
+			layer.setStyle(style);
+		}
+	}
+});
+
+L.extend(L.GeoJSON, {
+	geometryToLayer: function (geojson, pointToLayer, coordsToLatLng, vectorOptions) {
+		var geometry = geojson.type === 'Feature' ? geojson.geometry : geojson,
+		    coords = geometry.coordinates,
+		    layers = [],
+		    latlng, latlngs, i, len;
+
+		coordsToLatLng = coordsToLatLng || this.coordsToLatLng;
+
+		switch (geometry.type) {
+		case 'Point':
+			latlng = coordsToLatLng(coords);
+			return pointToLayer ? pointToLayer(geojson, latlng) : new L.Marker(latlng);
+
+		case 'MultiPoint':
+			for (i = 0, len = coords.length; i < len; i++) {
+				latlng = coordsToLatLng(coords[i]);
+				layers.push(pointToLayer ? pointToLayer(geojson, latlng) : new L.Marker(latlng));
+			}
+			return new L.FeatureGroup(layers);
+
+		case 'LineString':
+			latlngs = this.coordsToLatLngs(coords, 0, coordsToLatLng);
+			return new L.Polyline(latlngs, vectorOptions);
+
+		case 'Polygon':
+			if (coords.length === 2 && !coords[1].length) {
+				throw new Error('Invalid GeoJSON object.');
+			}
+			latlngs = this.coordsToLatLngs(coords, 1, coordsToLatLng);
+			return new L.Polygon(latlngs, vectorOptions);
+
+		case 'MultiLineString':
+			latlngs = this.coordsToLatLngs(coords, 1, coordsToLatLng);
+			return new L.MultiPolyline(latlngs, vectorOptions);
+
+		case 'MultiPolygon':
+			latlngs = this.coordsToLatLngs(coords, 2, coordsToLatLng);
+			return new L.MultiPolygon(latlngs, vectorOptions);
+
+		case 'GeometryCollection':
+			for (i = 0, len = geometry.geometries.length; i < len; i++) {
+
+				layers.push(this.geometryToLayer({
+					geometry: geometry.geometries[i],
+					type: 'Feature',
+					properties: geojson.properties
+				}, pointToLayer, coordsToLatLng, vectorOptions));
+			}
+			return new L.FeatureGroup(layers);
+
+		default:
+			throw new Error('Invalid GeoJSON object.');
+		}
+	},
+
+	coordsToLatLng: function (coords) { // (Array[, Boolean]) -> LatLng
+		return new L.LatLng(coords[1], coords[0], coords[2]);
+	},
+
+	coordsToLatLngs: function (coords, levelsDeep, coordsToLatLng) { // (Array[, Number, Function]) -> Array
+		var latlng, i, len,
+		    latlngs = [];
+
+		for (i = 0, len = coords.length; i < len; i++) {
+			latlng = levelsDeep ?
+			        this.coordsToLatLngs(coords[i], levelsDeep - 1, coordsToLatLng) :
+			        (coordsToLatLng || this.coordsToLatLng)(coords[i]);
+
+			latlngs.push(latlng);
+		}
+
+		return latlngs;
+	},
+
+	latLngToCoords: function (latlng) {
+		var coords = [latlng.lng, latlng.lat];
+
+		if (latlng.alt !== undefined) {
+			coords.push(latlng.alt);
+		}
+		return coords;
+	},
+
+	latLngsToCoords: function (latLngs) {
+		var coords = [];
+
+		for (var i = 0, len = latLngs.length; i < len; i++) {
+			coords.push(L.GeoJSON.latLngToCoords(latLngs[i]));
+		}
+
+		return coords;
+	},
+
+	getFeature: function (layer, newGeometry) {
+		return layer.feature ? L.extend({}, layer.feature, {geometry: newGeometry}) : L.GeoJSON.asFeature(newGeometry);
+	},
+
+	asFeature: function (geoJSON) {
+		if (geoJSON.type === 'Feature') {
+			return geoJSON;
+		}
+
+		return {
+			type: 'Feature',
+			properties: {},
+			geometry: geoJSON
+		};
+	}
+});
+
+var PointToGeoJSON = {
+	toGeoJSON: function () {
+		return L.GeoJSON.getFeature(this, {
+			type: 'Point',
+			coordinates: L.GeoJSON.latLngToCoords(this.getLatLng())
+		});
+	}
+};
+
+L.Marker.include(PointToGeoJSON);
+L.Circle.include(PointToGeoJSON);
+L.CircleMarker.include(PointToGeoJSON);
+
+L.Polyline.include({
+	toGeoJSON: function () {
+		return L.GeoJSON.getFeature(this, {
+			type: 'LineString',
+			coordinates: L.GeoJSON.latLngsToCoords(this.getLatLngs())
+		});
+	}
+});
+
+L.Polygon.include({
+	toGeoJSON: function () {
+		var coords = [L.GeoJSON.latLngsToCoords(this.getLatLngs())],
+		    i, len, hole;
+
+		coords[0].push(coords[0][0]);
+
+		if (this._holes) {
+			for (i = 0, len = this._holes.length; i < len; i++) {
+				hole = L.GeoJSON.latLngsToCoords(this._holes[i]);
+				hole.push(hole[0]);
+				coords.push(hole);
+			}
+		}
+
+		return L.GeoJSON.getFeature(this, {
+			type: 'Polygon',
+			coordinates: coords
+		});
+	}
+});
+
+(function () {
+	function multiToGeoJSON(type) {
+		return function () {
+			var coords = [];
+
+			this.eachLayer(function (layer) {
+				coords.push(layer.toGeoJSON().geometry.coordinates);
+			});
+
+			return L.GeoJSON.getFeature(this, {
+				type: type,
+				coordinates: coords
+			});
+		};
+	}
+
+	L.MultiPolyline.include({toGeoJSON: multiToGeoJSON('MultiLineString')});
+	L.MultiPolygon.include({toGeoJSON: multiToGeoJSON('MultiPolygon')});
+
+	L.LayerGroup.include({
+		toGeoJSON: function () {
+
+			var geometry = this.feature && this.feature.geometry,
+				jsons = [],
+				json;
+
+			if (geometry && geometry.type === 'MultiPoint') {
+				return multiToGeoJSON('MultiPoint').call(this);
+			}
+
+			var isGeometryCollection = geometry && geometry.type === 'GeometryCollection';
+
+			this.eachLayer(function (layer) {
+				if (layer.toGeoJSON) {
+					json = layer.toGeoJSON();
+					jsons.push(isGeometryCollection ? json.geometry : L.GeoJSON.asFeature(json));
+				}
+			});
+
+			if (isGeometryCollection) {
+				return L.GeoJSON.getFeature(this, {
+					geometries: jsons,
+					type: 'GeometryCollection'
+				});
+			}
+
+			return {
+				type: 'FeatureCollection',
+				features: jsons
+			};
+		}
+	});
+}());
+
+L.geoJson = function (geojson, options) {
+	return new L.GeoJSON(geojson, options);
+};
+
+
+/*
+ * L.DomEvent contains functions for working with DOM events.
+ */
+
+L.DomEvent = {
+	/* inspired by John Resig, Dean Edwards and YUI addEvent implementations */
+	addListener: function (obj, type, fn, context) { // (HTMLElement, String, Function[, Object])
+
+		var id = L.stamp(fn),
+		    key = '_leaflet_' + type + id,
+		    handler, originalHandler, newType;
+
+		if (obj[key]) { return this; }
+
+		handler = function (e) {
+			return fn.call(context || obj, e || L.DomEvent._getEvent());
+		};
+
+		if (L.Browser.pointer && type.indexOf('touch') === 0) {
+			return this.addPointerListener(obj, type, handler, id);
+		}
+		if (L.Browser.touch && (type === 'dblclick') && this.addDoubleTapListener) {
+			this.addDoubleTapListener(obj, handler, id);
+		}
+
+		if ('addEventListener' in obj) {
+
+			if (type === 'mousewheel') {
+				obj.addEventListener('DOMMouseScroll', handler, false);
+				obj.addEventListener(type, handler, false);
+
+			} else if ((type === 'mouseenter') || (type === 'mouseleave')) {
+
+				originalHandler = handler;
+				newType = (type === 'mouseenter' ? 'mouseover' : 'mouseout');
+
+				handler = function (e) {
+					if (!L.DomEvent._checkMouse(obj, e)) { return; }
+					return originalHandler(e);
+				};
+
+				obj.addEventListener(newType, handler, false);
+
+			} else if (type === 'click' && L.Browser.android) {
+				originalHandler = handler;
+				handler = function (e) {
+					return L.DomEvent._filterClick(e, originalHandler);
+				};
+
+				obj.addEventListener(type, handler, false);
+			} else {
+				obj.addEventListener(type, handler, false);
+			}
+
+		} else if ('attachEvent' in obj) {
+			obj.attachEvent('on' + type, handler);
+		}
+
+		obj[key] = handler;
+
+		return this;
+	},
+
+	removeListener: function (obj, type, fn) {  // (HTMLElement, String, Function)
+
+		var id = L.stamp(fn),
+		    key = '_leaflet_' + type + id,
+		    handler = obj[key];
+
+		if (!handler) { return this; }
+
+		if (L.Browser.pointer && type.indexOf('touch') === 0) {
+			this.removePointerListener(obj, type, id);
+		} else if (L.Browser.touch && (type === 'dblclick') && this.removeDoubleTapListener) {
+			this.removeDoubleTapListener(obj, id);
+
+		} else if ('removeEventListener' in obj) {
+
+			if (type === 'mousewheel') {
+				obj.removeEventListener('DOMMouseScroll', handler, false);
+				obj.removeEventListener(type, handler, false);
+
+			} else if ((type === 'mouseenter') || (type === 'mouseleave')) {
+				obj.removeEventListener((type === 'mouseenter' ? 'mouseover' : 'mouseout'), handler, false);
+			} else {
+				obj.removeEventListener(type, handler, false);
+			}
+		} else if ('detachEvent' in obj) {
+			obj.detachEvent('on' + type, handler);
+		}
+
+		obj[key] = null;
+
+		return this;
+	},
+
+	stopPropagation: function (e) {
+
+		if (e.stopPropagation) {
+			e.stopPropagation();
+		} else {
+			e.cancelBubble = true;
+		}
+		L.DomEvent._skipped(e);
+
+		return this;
+	},
+
+	disableScrollPropagation: function (el) {
+		var stop = L.DomEvent.stopPropagation;
+
+		return L.DomEvent
+			.on(el, 'mousewheel', stop)
+			.on(el, 'MozMousePixelScroll', stop);
+	},
+
+	disableClickPropagation: function (el) {
+		var stop = L.DomEvent.stopPropagation;
+
+		for (var i = L.Draggable.START.length - 1; i >= 0; i--) {
+			L.DomEvent.on(el, L.Draggable.START[i], stop);
+		}
+
+		return L.DomEvent
+			.on(el, 'click', L.DomEvent._fakeStop)
+			.on(el, 'dblclick', stop);
+	},
+
+	preventDefault: function (e) {
+
+		if (e.preventDefault) {
+			e.preventDefault();
+		} else {
+			e.returnValue = false;
+		}
+		return this;
+	},
+
+	stop: function (e) {
+		return L.DomEvent
+			.preventDefault(e)
+			.stopPropagation(e);
+	},
+
+	getMousePosition: function (e, container) {
+		if (!container) {
+			return new L.Point(e.clientX, e.clientY);
+		}
+
+		var rect = container.getBoundingClientRect();
+
+		return new L.Point(
+			e.clientX - rect.left - container.clientLeft,
+			e.clientY - rect.top - container.clientTop);
+	},
+
+	getWheelDelta: function (e) {
+
+		var delta = 0;
+
+		if (e.wheelDelta) {
+			delta = e.wheelDelta / 120;
+		}
+		if (e.detail) {
+			delta = -e.detail / 3;
+		}
+		return delta;
+	},
+
+	_skipEvents: {},
+
+	_fakeStop: function (e) {
+		// fakes stopPropagation by setting a special event flag, checked/reset with L.DomEvent._skipped(e)
+		L.DomEvent._skipEvents[e.type] = true;
+	},
+
+	_skipped: function (e) {
+		var skipped = this._skipEvents[e.type];
+		// reset when checking, as it's only used in map container and propagates outside of the map
+		this._skipEvents[e.type] = false;
+		return skipped;
+	},
+
+	// check if element really left/entered the event target (for mouseenter/mouseleave)
+	_checkMouse: function (el, e) {
+
+		var related = e.relatedTarget;
+
+		if (!related) { return true; }
+
+		try {
+			while (related && (related !== el)) {
+				related = related.parentNode;
+			}
+		} catch (err) {
+			return false;
+		}
+		return (related !== el);
+	},
+
+	_getEvent: function () { // evil magic for IE
+		/*jshint noarg:false */
+		var e = window.event;
+		if (!e) {
+			var caller = arguments.callee.caller;
+			while (caller) {
+				e = caller['arguments'][0];
+				if (e && window.Event === e.constructor) {
+					break;
+				}
+				caller = caller.caller;
+			}
+		}
+		return e;
+	},
+
+	// this is a horrible workaround for a bug in Android where a single touch triggers two click events
+	_filterClick: function (e, handler) {
+		var timeStamp = (e.timeStamp || e.originalEvent.timeStamp),
+			elapsed = L.DomEvent._lastClick && (timeStamp - L.DomEvent._lastClick);
+
+		// are they closer together than 500ms yet more than 100ms?
+		// Android typically triggers them ~300ms apart while multiple listeners
+		// on the same event should be triggered far faster;
+		// or check if click is simulated on the element, and if it is, reject any non-simulated events
+
+		if ((elapsed && elapsed > 100 && elapsed < 500) || (e.target._simulatedClick && !e._simulated)) {
+			L.DomEvent.stop(e);
+			return;
+		}
+		L.DomEvent._lastClick = timeStamp;
+
+		return handler(e);
+	}
+};
+
+L.DomEvent.on = L.DomEvent.addListener;
+L.DomEvent.off = L.DomEvent.removeListener;
+
+
+/*
+ * L.Draggable allows you to add dragging capabilities to any element. Supports mobile devices too.
+ */
+
+L.Draggable = L.Class.extend({
+	includes: L.Mixin.Events,
+
+	statics: {
+		START: L.Browser.touch ? ['touchstart', 'mousedown'] : ['mousedown'],
+		END: {
+			mousedown: 'mouseup',
+			touchstart: 'touchend',
+			pointerdown: 'touchend',
+			MSPointerDown: 'touchend'
+		},
+		MOVE: {
+			mousedown: 'mousemove',
+			touchstart: 'touchmove',
+			pointerdown: 'touchmove',
+			MSPointerDown: 'touchmove'
+		}
+	},
+
+	initialize: function (element, dragStartTarget) {
+		this._element = element;
+		this._dragStartTarget = dragStartTarget || element;
+	},
+
+	enable: function () {
+		if (this._enabled) { return; }
+
+		for (var i = L.Draggable.START.length - 1; i >= 0; i--) {
+			L.DomEvent.on(this._dragStartTarget, L.Draggable.START[i], this._onDown, this);
+		}
+
+		this._enabled = true;
+	},
+
+	disable: function () {
+		if (!this._enabled) { return; }
+
+		for (var i = L.Draggable.START.length - 1; i >= 0; i--) {
+			L.DomEvent.off(this._dragStartTarget, L.Draggable.START[i], this._onDown, this);
+		}
+
+		this._enabled = false;
+		this._moved = false;
+	},
+
+	_onDown: function (e) {
+		this._moved = false;
+
+		if (e.shiftKey || ((e.which !== 1) && (e.button !== 1) && !e.touches)) { return; }
+
+		L.DomEvent.stopPropagation(e);
+
+		if (L.Draggable._disabled) { return; }
+
+		L.DomUtil.disableImageDrag();
+		L.DomUtil.disableTextSelection();
+
+		if (this._moving) { return; }
+
+		var first = e.touches ? e.touches[0] : e;
+
+		this._startPoint = new L.Point(first.clientX, first.clientY);
+		this._startPos = this._newPos = L.DomUtil.getPosition(this._element);
+
+		L.DomEvent
+		    .on(document, L.Draggable.MOVE[e.type], this._onMove, this)
+		    .on(document, L.Draggable.END[e.type], this._onUp, this);
+	},
+
+	_onMove: function (e) {
+		if (e.touches && e.touches.length > 1) {
+			this._moved = true;
+			return;
+		}
+
+		var first = (e.touches && e.touches.length === 1 ? e.touches[0] : e),
+		    newPoint = new L.Point(first.clientX, first.clientY),
+		    offset = newPoint.subtract(this._startPoint);
+
+		if (!offset.x && !offset.y) { return; }
+		if (L.Browser.touch && Math.abs(offset.x) + Math.abs(offset.y) < 3) { return; }
+
+		L.DomEvent.preventDefault(e);
+
+		if (!this._moved) {
+			this.fire('dragstart');
+
+			this._moved = true;
+			this._startPos = L.DomUtil.getPosition(this._element).subtract(offset);
+
+			L.DomUtil.addClass(document.body, 'leaflet-dragging');
+			this._lastTarget = e.target || e.srcElement;
+			L.DomUtil.addClass(this._lastTarget, 'leaflet-drag-target');
+		}
+
+		this._newPos = this._startPos.add(offset);
+		this._moving = true;
+
+		L.Util.cancelAnimFrame(this._animRequest);
+		this._animRequest = L.Util.requestAnimFrame(this._updatePosition, this, true, this._dragStartTarget);
+	},
+
+	_updatePosition: function () {
+		this.fire('predrag');
+		L.DomUtil.setPosition(this._element, this._newPos);
+		this.fire('drag');
+	},
+
+	_onUp: function () {
+		L.DomUtil.removeClass(document.body, 'leaflet-dragging');
+
+		if (this._lastTarget) {
+			L.DomUtil.removeClass(this._lastTarget, 'leaflet-drag-target');
+			this._lastTarget = null;
+		}
+
+		for (var i in L.Draggable.MOVE) {
+			L.DomEvent
+			    .off(document, L.Draggable.MOVE[i], this._onMove)
+			    .off(document, L.Draggable.END[i], this._onUp);
+		}
+
+		L.DomUtil.enableImageDrag();
+		L.DomUtil.enableTextSelection();
+
+		if (this._moved && this._moving) {
+			// ensure drag is not fired after dragend
+			L.Util.cancelAnimFrame(this._animRequest);
+
+			this.fire('dragend', {
+				distance: this._newPos.distanceTo(this._startPos)
+			});
+		}
+
+		this._moving = false;
+	}
+});
+
+
+/*
+	L.Handler is a base class for handler classes that are used internally to inject
+	interaction features like dragging to classes like Map and Marker.
+*/
+
+L.Handler = L.Class.extend({
+	initialize: function (map) {
+		this._map = map;
+	},
+
+	enable: function () {
+		if (this._enabled) { return; }
+
+		this._enabled = true;
+		this.addHooks();
+	},
+
+	disable: function () {
+		if (!this._enabled) { return; }
+
+		this._enabled = false;
+		this.removeHooks();
+	},
+
+	enabled: function () {
+		return !!this._enabled;
+	}
+});
+
+
+/*
+ * L.Handler.MapDrag is used to make the map draggable (with panning inertia), enabled by default.
+ */
+
+L.Map.mergeOptions({
+	dragging: true,
+
+	inertia: !L.Browser.android23,
+	inertiaDeceleration: 3400, // px/s^2
+	inertiaMaxSpeed: Infinity, // px/s
+	inertiaThreshold: L.Browser.touch ? 32 : 18, // ms
+	easeLinearity: 0.25,
+
+	// TODO refactor, move to CRS
+	worldCopyJump: false
+});
+
+L.Map.Drag = L.Handler.extend({
+	addHooks: function () {
+		if (!this._draggable) {
+			var map = this._map;
+
+			this._draggable = new L.Draggable(map._mapPane, map._container);
+
+			this._draggable.on({
+				'dragstart': this._onDragStart,
+				'drag': this._onDrag,
+				'dragend': this._onDragEnd
+			}, this);
+
+			if (map.options.worldCopyJump) {
+				this._draggable.on('predrag', this._onPreDrag, this);
+				map.on('viewreset', this._onViewReset, this);
+
+				map.whenReady(this._onViewReset, this);
+			}
+		}
+		this._draggable.enable();
+	},
+
+	removeHooks: function () {
+		this._draggable.disable();
+	},
+
+	moved: function () {
+		return this._draggable && this._draggable._moved;
+	},
+
+	_onDragStart: function () {
+		var map = this._map;
+
+		if (map._panAnim) {
+			map._panAnim.stop();
+		}
+
+		map
+		    .fire('movestart')
+		    .fire('dragstart');
+
+		if (map.options.inertia) {
+			this._positions = [];
+			this._times = [];
+		}
+	},
+
+	_onDrag: function () {
+		if (this._map.options.inertia) {
+			var time = this._lastTime = +new Date(),
+			    pos = this._lastPos = this._draggable._newPos;
+
+			this._positions.push(pos);
+			this._times.push(time);
+
+			if (time - this._times[0] > 200) {
+				this._positions.shift();
+				this._times.shift();
+			}
+		}
+
+		this._map
+		    .fire('move')
+		    .fire('drag');
+	},
+
+	_onViewReset: function () {
+		// TODO fix hardcoded Earth values
+		var pxCenter = this._map.getSize()._divideBy(2),
+		    pxWorldCenter = this._map.latLngToLayerPoint([0, 0]);
+
+		this._initialWorldOffset = pxWorldCenter.subtract(pxCenter).x;
+		this._worldWidth = this._map.project([0, 180]).x;
+	},
+
+	_onPreDrag: function () {
+		// TODO refactor to be able to adjust map pane position after zoom
+		var worldWidth = this._worldWidth,
+		    halfWidth = Math.round(worldWidth / 2),
+		    dx = this._initialWorldOffset,
+		    x = this._draggable._newPos.x,
+		    newX1 = (x - halfWidth + dx) % worldWidth + halfWidth - dx,
+		    newX2 = (x + halfWidth + dx) % worldWidth - halfWidth - dx,
+		    newX = Math.abs(newX1 + dx) < Math.abs(newX2 + dx) ? newX1 : newX2;
+
+		this._draggable._newPos.x = newX;
+	},
+
+	_onDragEnd: function (e) {
+		var map = this._map,
+		    options = map.options,
+		    delay = +new Date() - this._lastTime,
+
+		    noInertia = !options.inertia || delay > options.inertiaThreshold || !this._positions[0];
+
+		map.fire('dragend', e);
+
+		if (noInertia) {
+			map.fire('moveend');
+
+		} else {
+
+			var direction = this._lastPos.subtract(this._positions[0]),
+			    duration = (this._lastTime + delay - this._times[0]) / 1000,
+			    ease = options.easeLinearity,
+
+			    speedVector = direction.multiplyBy(ease / duration),
+			    speed = speedVector.distanceTo([0, 0]),
+
+			    limitedSpeed = Math.min(options.inertiaMaxSpeed, speed),
+			    limitedSpeedVector = speedVector.multiplyBy(limitedSpeed / speed),
+
+			    decelerationDuration = limitedSpeed / (options.inertiaDeceleration * ease),
+			    offset = limitedSpeedVector.multiplyBy(-decelerationDuration / 2).round();
+
+			if (!offset.x || !offset.y) {
+				map.fire('moveend');
+
+			} else {
+				offset = map._limitOffset(offset, map.options.maxBounds);
+
+				L.Util.requestAnimFrame(function () {
+					map.panBy(offset, {
+						duration: decelerationDuration,
+						easeLinearity: ease,
+						noMoveStart: true
+					});
+				});
+			}
+		}
+	}
+});
+
+L.Map.addInitHook('addHandler', 'dragging', L.Map.Drag);
+
+
+/*
+ * L.Handler.DoubleClickZoom is used to handle double-click zoom on the map, enabled by default.
+ */
+
+L.Map.mergeOptions({
+	doubleClickZoom: true
+});
+
+L.Map.DoubleClickZoom = L.Handler.extend({
+	addHooks: function () {
+		this._map.on('dblclick', this._onDoubleClick, this);
+	},
+
+	removeHooks: function () {
+		this._map.off('dblclick', this._onDoubleClick, this);
+	},
+
+	_onDoubleClick: function (e) {
+		var map = this._map,
+		    zoom = map.getZoom() + (e.originalEvent.shiftKey ? -1 : 1);
+
+		if (map.options.doubleClickZoom === 'center') {
+			map.setZoom(zoom);
+		} else {
+			map.setZoomAround(e.containerPoint, zoom);
+		}
+	}
+});
+
+L.Map.addInitHook('addHandler', 'doubleClickZoom', L.Map.DoubleClickZoom);
+
+
+/*
+ * L.Handler.ScrollWheelZoom is used by L.Map to enable mouse scroll wheel zoom on the map.
+ */
+
+L.Map.mergeOptions({
+	scrollWheelZoom: true
+});
+
+L.Map.ScrollWheelZoom = L.Handler.extend({
+	addHooks: function () {
+		L.DomEvent.on(this._map._container, 'mousewheel', this._onWheelScroll, this);
+		L.DomEvent.on(this._map._container, 'MozMousePixelScroll', L.DomEvent.preventDefault);
+		this._delta = 0;
+	},
+
+	removeHooks: function () {
+		L.DomEvent.off(this._map._container, 'mousewheel', this._onWheelScroll);
+		L.DomEvent.off(this._map._container, 'MozMousePixelScroll', L.DomEvent.preventDefault);
+	},
+
+	_onWheelScroll: function (e) {
+		var delta = L.DomEvent.getWheelDelta(e);
+
+		this._delta += delta;
+		this._lastMousePos = this._map.mouseEventToContainerPoint(e);
+
+		if (!this._startTime) {
+			this._startTime = +new Date();
+		}
+
+		var left = Math.max(40 - (+new Date() - this._startTime), 0);
+
+		clearTimeout(this._timer);
+		this._timer = setTimeout(L.bind(this._performZoom, this), left);
+
+		L.DomEvent.preventDefault(e);
+		L.DomEvent.stopPropagation(e);
+	},
+
+	_performZoom: function () {
+		var map = this._map,
+		    delta = this._delta,
+		    zoom = map.getZoom();
+
+		delta = delta > 0 ? Math.ceil(delta) : Math.floor(delta);
+		delta = Math.max(Math.min(delta, 4), -4);
+		delta = map._limitZoom(zoom + delta) - zoom;
+
+		this._delta = 0;
+		this._startTime = null;
+
+		if (!delta) { return; }
+
+		if (map.options.scrollWheelZoom === 'center') {
+			map.setZoom(zoom + delta);
+		} else {
+			map.setZoomAround(this._lastMousePos, zoom + delta);
+		}
+	}
+});
+
+L.Map.addInitHook('addHandler', 'scrollWheelZoom', L.Map.ScrollWheelZoom);
+
+
+/*
+ * Extends the event handling code with double tap support for mobile browsers.
+ */
+
+L.extend(L.DomEvent, {
+
+	_touchstart: L.Browser.msPointer ? 'MSPointerDown' : L.Browser.pointer ? 'pointerdown' : 'touchstart',
+	_touchend: L.Browser.msPointer ? 'MSPointerUp' : L.Browser.pointer ? 'pointerup' : 'touchend',
+
+	// inspired by Zepto touch code by Thomas Fuchs
+	addDoubleTapListener: function (obj, handler, id) {
+		var last,
+		    doubleTap = false,
+		    delay = 250,
+		    touch,
+		    pre = '_leaflet_',
+		    touchstart = this._touchstart,
+		    touchend = this._touchend,
+		    trackedTouches = [];
+
+		function onTouchStart(e) {
+			var count;
+
+			if (L.Browser.pointer) {
+				trackedTouches.push(e.pointerId);
+				count = trackedTouches.length;
+			} else {
+				count = e.touches.length;
+			}
+			if (count > 1) {
+				return;
+			}
+
+			var now = Date.now(),
+				delta = now - (last || now);
+
+			touch = e.touches ? e.touches[0] : e;
+			doubleTap = (delta > 0 && delta <= delay);
+			last = now;
+		}
+
+		function onTouchEnd(e) {
+			if (L.Browser.pointer) {
+				var idx = trackedTouches.indexOf(e.pointerId);
+				if (idx === -1) {
+					return;
+				}
+				trackedTouches.splice(idx, 1);
+			}
+
+			if (doubleTap) {
+				if (L.Browser.pointer) {
+					// work around .type being readonly with MSPointer* events
+					var newTouch = { },
+						prop;
+
+					// jshint forin:false
+					for (var i in touch) {
+						prop = touch[i];
+						if (typeof prop === 'function') {
+							newTouch[i] = prop.bind(touch);
+						} else {
+							newTouch[i] = prop;
+						}
+					}
+					touch = newTouch;
+				}
+				touch.type = 'dblclick';
+				handler(touch);
+				last = null;
+			}
+		}
+		obj[pre + touchstart + id] = onTouchStart;
+		obj[pre + touchend + id] = onTouchEnd;
+
+		// on pointer we need to listen on the document, otherwise a drag starting on the map and moving off screen
+		// will not come through to us, so we will lose track of how many touches are ongoing
+		var endElement = L.Browser.pointer ? document.documentElement : obj;
+
+		obj.addEventListener(touchstart, onTouchStart, false);
+		endElement.addEventListener(touchend, onTouchEnd, false);
+
+		if (L.Browser.pointer) {
+			endElement.addEventListener(L.DomEvent.POINTER_CANCEL, onTouchEnd, false);
+		}
+
+		return this;
+	},
+
+	removeDoubleTapListener: function (obj, id) {
+		var pre = '_leaflet_';
+
+		obj.removeEventListener(this._touchstart, obj[pre + this._touchstart + id], false);
+		(L.Browser.pointer ? document.documentElement : obj).removeEventListener(
+		        this._touchend, obj[pre + this._touchend + id], false);
+
+		if (L.Browser.pointer) {
+			document.documentElement.removeEventListener(L.DomEvent.POINTER_CANCEL, obj[pre + this._touchend + id],
+				false);
+		}
+
+		return this;
+	}
+});
+
+
+/*
+ * Extends L.DomEvent to provide touch support for Internet Explorer and Windows-based devices.
+ */
+
+L.extend(L.DomEvent, {
+
+	//static
+	POINTER_DOWN: L.Browser.msPointer ? 'MSPointerDown' : 'pointerdown',
+	POINTER_MOVE: L.Browser.msPointer ? 'MSPointerMove' : 'pointermove',
+	POINTER_UP: L.Browser.msPointer ? 'MSPointerUp' : 'pointerup',
+	POINTER_CANCEL: L.Browser.msPointer ? 'MSPointerCancel' : 'pointercancel',
+
+	_pointers: [],
+	_pointerDocumentListener: false,
+
+	// Provides a touch events wrapper for (ms)pointer events.
+	// Based on changes by veproza https://github.com/CloudMade/Leaflet/pull/1019
+	//ref http://www.w3.org/TR/pointerevents/ https://www.w3.org/Bugs/Public/show_bug.cgi?id=22890
+
+	addPointerListener: function (obj, type, handler, id) {
+
+		switch (type) {
+		case 'touchstart':
+			return this.addPointerListenerStart(obj, type, handler, id);
+		case 'touchend':
+			return this.addPointerListenerEnd(obj, type, handler, id);
+		case 'touchmove':
+			return this.addPointerListenerMove(obj, type, handler, id);
+		default:
+			throw 'Unknown touch event type';
+		}
+	},
+
+	addPointerListenerStart: function (obj, type, handler, id) {
+		var pre = '_leaflet_',
+		    pointers = this._pointers;
+
+		var cb = function (e) {
+			if (e.pointerType !== 'mouse' && e.pointerType !== e.MSPOINTER_TYPE_MOUSE) {
+				L.DomEvent.preventDefault(e);
+			}
+
+			var alreadyInArray = false;
+			for (var i = 0; i < pointers.length; i++) {
+				if (pointers[i].pointerId === e.pointerId) {
+					alreadyInArray = true;
+					break;
+				}
+			}
+			if (!alreadyInArray) {
+				pointers.push(e);
+			}
+
+			e.touches = pointers.slice();
+			e.changedTouches = [e];
+
+			handler(e);
+		};
+
+		obj[pre + 'touchstart' + id] = cb;
+		obj.addEventListener(this.POINTER_DOWN, cb, false);
+
+		// need to also listen for end events to keep the _pointers list accurate
+		// this needs to be on the body and never go away
+		if (!this._pointerDocumentListener) {
+			var internalCb = function (e) {
+				for (var i = 0; i < pointers.length; i++) {
+					if (pointers[i].pointerId === e.pointerId) {
+						pointers.splice(i, 1);
+						break;
+					}
+				}
+			};
+			//We listen on the documentElement as any drags that end by moving the touch off the screen get fired there
+			document.documentElement.addEventListener(this.POINTER_UP, internalCb, false);
+			document.documentElement.addEventListener(this.POINTER_CANCEL, internalCb, false);
+
+			this._pointerDocumentListener = true;
+		}
+
+		return this;
+	},
+
+	addPointerListenerMove: function (obj, type, handler, id) {
+		var pre = '_leaflet_',
+		    touches = this._pointers;
+
+		function cb(e) {
+
+			// don't fire touch moves when mouse isn't down
+			if ((e.pointerType === e.MSPOINTER_TYPE_MOUSE || e.pointerType === 'mouse') && e.buttons === 0) { return; }
+
+			for (var i = 0; i < touches.length; i++) {
+				if (touches[i].pointerId === e.pointerId) {
+					touches[i] = e;
+					break;
+				}
+			}
+
+			e.touches = touches.slice();
+			e.changedTouches = [e];
+
+			handler(e);
+		}
+
+		obj[pre + 'touchmove' + id] = cb;
+		obj.addEventListener(this.POINTER_MOVE, cb, false);
+
+		return this;
+	},
+
+	addPointerListenerEnd: function (obj, type, handler, id) {
+		var pre = '_leaflet_',
+		    touches = this._pointers;
+
+		var cb = function (e) {
+			for (var i = 0; i < touches.length; i++) {
+				if (touches[i].pointerId === e.pointerId) {
+					touches.splice(i, 1);
+					break;
+				}
+			}
+
+			e.touches = touches.slice();
+			e.changedTouches = [e];
+
+			handler(e);
+		};
+
+		obj[pre + 'touchend' + id] = cb;
+		obj.addEventListener(this.POINTER_UP, cb, false);
+		obj.addEventListener(this.POINTER_CANCEL, cb, false);
+
+		return this;
+	},
+
+	removePointerListener: function (obj, type, id) {
+		var pre = '_leaflet_',
+		    cb = obj[pre + type + id];
+
+		switch (type) {
+		case 'touchstart':
+			obj.removeEventListener(this.POINTER_DOWN, cb, false);
+			break;
+		case 'touchmove':
+			obj.removeEventListener(this.POINTER_MOVE, cb, false);
+			break;
+		case 'touchend':
+			obj.removeEventListener(this.POINTER_UP, cb, false);
+			obj.removeEventListener(this.POINTER_CANCEL, cb, false);
+			break;
+		}
+
+		return this;
+	}
+});
+
+
+/*
+ * L.Handler.TouchZoom is used by L.Map to add pinch zoom on supported mobile browsers.
+ */
+
+L.Map.mergeOptions({
+	touchZoom: L.Browser.touch && !L.Browser.android23,
+	bounceAtZoomLimits: true
+});
+
+L.Map.TouchZoom = L.Handler.extend({
+	addHooks: function () {
+		L.DomEvent.on(this._map._container, 'touchstart', this._onTouchStart, this);
+	},
+
+	removeHooks: function () {
+		L.DomEvent.off(this._map._container, 'touchstart', this._onTouchStart, this);
+	},
+
+	_onTouchStart: function (e) {
+		var map = this._map;
+
+		if (!e.touches || e.touches.length !== 2 || map._animatingZoom || this._zooming) { return; }
+
+		var p1 = map.mouseEventToLayerPoint(e.touches[0]),
+		    p2 = map.mouseEventToLayerPoint(e.touches[1]),
+		    viewCenter = map._getCenterLayerPoint();
+
+		this._startCenter = p1.add(p2)._divideBy(2);
+		this._startDist = p1.distanceTo(p2);
+
+		this._moved = false;
+		this._zooming = true;
+
+		this._centerOffset = viewCenter.subtract(this._startCenter);
+
+		if (map._panAnim) {
+			map._panAnim.stop();
+		}
+
+		L.DomEvent
+		    .on(document, 'touchmove', this._onTouchMove, this)
+		    .on(document, 'touchend', this._onTouchEnd, this);
+
+		L.DomEvent.preventDefault(e);
+	},
+
+	_onTouchMove: function (e) {
+		var map = this._map;
+
+		if (!e.touches || e.touches.length !== 2 || !this._zooming) { return; }
+
+		var p1 = map.mouseEventToLayerPoint(e.touches[0]),
+		    p2 = map.mouseEventToLayerPoint(e.touches[1]);
+
+		this._scale = p1.distanceTo(p2) / this._startDist;
+		this._delta = p1._add(p2)._divideBy(2)._subtract(this._startCenter);
+
+		if (this._scale === 1) { return; }
+
+		if (!map.options.bounceAtZoomLimits) {
+			if ((map.getZoom() === map.getMinZoom() && this._scale < 1) ||
+			    (map.getZoom() === map.getMaxZoom() && this._scale > 1)) { return; }
+		}
+
+		if (!this._moved) {
+			L.DomUtil.addClass(map._mapPane, 'leaflet-touching');
+
+			map
+			    .fire('movestart')
+			    .fire('zoomstart');
+
+			this._moved = true;
+		}
+
+		L.Util.cancelAnimFrame(this._animRequest);
+		this._animRequest = L.Util.requestAnimFrame(
+		        this._updateOnMove, this, true, this._map._container);
+
+		L.DomEvent.preventDefault(e);
+	},
+
+	_updateOnMove: function () {
+		var map = this._map,
+		    origin = this._getScaleOrigin(),
+		    center = map.layerPointToLatLng(origin),
+		    zoom = map.getScaleZoom(this._scale);
+
+		map._animateZoom(center, zoom, this._startCenter, this._scale, this._delta, false, true);
+	},
+
+	_onTouchEnd: function () {
+		if (!this._moved || !this._zooming) {
+			this._zooming = false;
+			return;
+		}
+
+		var map = this._map;
+
+		this._zooming = false;
+		L.DomUtil.removeClass(map._mapPane, 'leaflet-touching');
+		L.Util.cancelAnimFrame(this._animRequest);
+
+		L.DomEvent
+		    .off(document, 'touchmove', this._onTouchMove)
+		    .off(document, 'touchend', this._onTouchEnd);
+
+		var origin = this._getScaleOrigin(),
+		    center = map.layerPointToLatLng(origin),
+
+		    oldZoom = map.getZoom(),
+		    floatZoomDelta = map.getScaleZoom(this._scale) - oldZoom,
+		    roundZoomDelta = (floatZoomDelta > 0 ?
+		            Math.ceil(floatZoomDelta) : Math.floor(floatZoomDelta)),
+
+		    zoom = map._limitZoom(oldZoom + roundZoomDelta),
+		    scale = map.getZoomScale(zoom) / this._scale;
+
+		map._animateZoom(center, zoom, origin, scale);
+	},
+
+	_getScaleOrigin: function () {
+		var centerOffset = this._centerOffset.subtract(this._delta).divideBy(this._scale);
+		return this._startCenter.add(centerOffset);
+	}
+});
+
+L.Map.addInitHook('addHandler', 'touchZoom', L.Map.TouchZoom);
+
+
+/*
+ * L.Map.Tap is used to enable mobile hacks like quick taps and long hold.
+ */
+
+L.Map.mergeOptions({
+	tap: true,
+	tapTolerance: 15
+});
+
+L.Map.Tap = L.Handler.extend({
+	addHooks: function () {
+		L.DomEvent.on(this._map._container, 'touchstart', this._onDown, this);
+	},
+
+	removeHooks: function () {
+		L.DomEvent.off(this._map._container, 'touchstart', this._onDown, this);
+	},
+
+	_onDown: function (e) {
+		if (!e.touches) { return; }
+
+		L.DomEvent.preventDefault(e);
+
+		this._fireClick = true;
+
+		// don't simulate click or track longpress if more than 1 touch
+		if (e.touches.length > 1) {
+			this._fireClick = false;
+			clearTimeout(this._holdTimeout);
+			return;
+		}
+
+		var first = e.touches[0],
+		    el = first.target;
+
+		this._startPos = this._newPos = new L.Point(first.clientX, first.clientY);
+
+		// if touching a link, highlight it
+		if (el.tagName && el.tagName.toLowerCase() === 'a') {
+			L.DomUtil.addClass(el, 'leaflet-active');
+		}
+
+		// simulate long hold but setting a timeout
+		this._holdTimeout = setTimeout(L.bind(function () {
+			if (this._isTapValid()) {
+				this._fireClick = false;
+				this._onUp();
+				this._simulateEvent('contextmenu', first);
+			}
+		}, this), 1000);
+
+		L.DomEvent
+			.on(document, 'touchmove', this._onMove, this)
+			.on(document, 'touchend', this._onUp, this);
+	},
+
+	_onUp: function (e) {
+		clearTimeout(this._holdTimeout);
+
+		L.DomEvent
+			.off(document, 'touchmove', this._onMove, this)
+			.off(document, 'touchend', this._onUp, this);
+
+		if (this._fireClick && e && e.changedTouches) {
+
+			var first = e.changedTouches[0],
+			    el = first.target;
+
+			if (el && el.tagName && el.tagName.toLowerCase() === 'a') {
+				L.DomUtil.removeClass(el, 'leaflet-active');
+			}
+
+			// simulate click if the touch didn't move too much
+			if (this._isTapValid()) {
+				this._simulateEvent('click', first);
+			}
+		}
+	},
+
+	_isTapValid: function () {
+		return this._newPos.distanceTo(this._startPos) <= this._map.options.tapTolerance;
+	},
+
+	_onMove: function (e) {
+		var first = e.touches[0];
+		this._newPos = new L.Point(first.clientX, first.clientY);
+	},
+
+	_simulateEvent: function (type, e) {
+		var simulatedEvent = document.createEvent('MouseEvents');
+
+		simulatedEvent._simulated = true;
+		e.target._simulatedClick = true;
+
+		simulatedEvent.initMouseEvent(
+		        type, true, true, window, 1,
+		        e.screenX, e.screenY,
+		        e.clientX, e.clientY,
+		        false, false, false, false, 0, null);
+
+		e.target.dispatchEvent(simulatedEvent);
+	}
+});
+
+if (L.Browser.touch && !L.Browser.pointer) {
+	L.Map.addInitHook('addHandler', 'tap', L.Map.Tap);
+}
+
+
+/*
+ * L.Handler.ShiftDragZoom is used to add shift-drag zoom interaction to the map
+  * (zoom to a selected bounding box), enabled by default.
+ */
+
+L.Map.mergeOptions({
+	boxZoom: true
+});
+
+L.Map.BoxZoom = L.Handler.extend({
+	initialize: function (map) {
+		this._map = map;
+		this._container = map._container;
+		this._pane = map._panes.overlayPane;
+		this._moved = false;
+	},
+
+	addHooks: function () {
+		L.DomEvent.on(this._container, 'mousedown', this._onMouseDown, this);
+	},
+
+	removeHooks: function () {
+		L.DomEvent.off(this._container, 'mousedown', this._onMouseDown);
+		this._moved = false;
+	},
+
+	moved: function () {
+		return this._moved;
+	},
+
+	_onMouseDown: function (e) {
+		this._moved = false;
+
+		if (!e.shiftKey || ((e.which !== 1) && (e.button !== 1))) { return false; }
+
+		L.DomUtil.disableTextSelection();
+		L.DomUtil.disableImageDrag();
+
+		this._startLayerPoint = this._map.mouseEventToLayerPoint(e);
+
+		L.DomEvent
+		    .on(document, 'mousemove', this._onMouseMove, this)
+		    .on(document, 'mouseup', this._onMouseUp, this)
+		    .on(document, 'keydown', this._onKeyDown, this);
+	},
+
+	_onMouseMove: function (e) {
+		if (!this._moved) {
+			this._box = L.DomUtil.create('div', 'leaflet-zoom-box', this._pane);
+			L.DomUtil.setPosition(this._box, this._startLayerPoint);
+
+			//TODO refactor: move cursor to styles
+			this._container.style.cursor = 'crosshair';
+			this._map.fire('boxzoomstart');
+		}
+
+		var startPoint = this._startLayerPoint,
+		    box = this._box,
+
+		    layerPoint = this._map.mouseEventToLayerPoint(e),
+		    offset = layerPoint.subtract(startPoint),
+
+		    newPos = new L.Point(
+		        Math.min(layerPoint.x, startPoint.x),
+		        Math.min(layerPoint.y, startPoint.y));
+
+		L.DomUtil.setPosition(box, newPos);
+
+		this._moved = true;
+
+		// TODO refactor: remove hardcoded 4 pixels
+		box.style.width  = (Math.max(0, Math.abs(offset.x) - 4)) + 'px';
+		box.style.height = (Math.max(0, Math.abs(offset.y) - 4)) + 'px';
+	},
+
+	_finish: function () {
+		if (this._moved) {
+			this._pane.removeChild(this._box);
+			this._container.style.cursor = '';
+		}
+
+		L.DomUtil.enableTextSelection();
+		L.DomUtil.enableImageDrag();
+
+		L.DomEvent
+		    .off(document, 'mousemove', this._onMouseMove)
+		    .off(document, 'mouseup', this._onMouseUp)
+		    .off(document, 'keydown', this._onKeyDown);
+	},
+
+	_onMouseUp: function (e) {
+
+		this._finish();
+
+		var map = this._map,
+		    layerPoint = map.mouseEventToLayerPoint(e);
+
+		if (this._startLayerPoint.equals(layerPoint)) { return; }
+
+		var bounds = new L.LatLngBounds(
+		        map.layerPointToLatLng(this._startLayerPoint),
+		        map.layerPointToLatLng(layerPoint));
+
+		map.fitBounds(bounds);
+
+		map.fire('boxzoomend', {
+			boxZoomBounds: bounds
+		});
+	},
+
+	_onKeyDown: function (e) {
+		if (e.keyCode === 27) {
+			this._finish();
+		}
+	}
+});
+
+L.Map.addInitHook('addHandler', 'boxZoom', L.Map.BoxZoom);
+
+
+/*
+ * L.Map.Keyboard is handling keyboard interaction with the map, enabled by default.
+ */
+
+L.Map.mergeOptions({
+	keyboard: true,
+	keyboardPanOffset: 80,
+	keyboardZoomOffset: 1
+});
+
+L.Map.Keyboard = L.Handler.extend({
+
+	keyCodes: {
+		left:    [37],
+		right:   [39],
+		down:    [40],
+		up:      [38],
+		zoomIn:  [187, 107, 61, 171],
+		zoomOut: [189, 109, 173]
+	},
+
+	initialize: function (map) {
+		this._map = map;
+
+		this._setPanOffset(map.options.keyboardPanOffset);
+		this._setZoomOffset(map.options.keyboardZoomOffset);
+	},
+
+	addHooks: function () {
+		var container = this._map._container;
+
+		// make the container focusable by tabbing
+		if (container.tabIndex === -1) {
+			container.tabIndex = '0';
+		}
+
+		L.DomEvent
+		    .on(container, 'focus', this._onFocus, this)
+		    .on(container, 'blur', this._onBlur, this)
+		    .on(container, 'mousedown', this._onMouseDown, this);
+
+		this._map
+		    .on('focus', this._addHooks, this)
+		    .on('blur', this._removeHooks, this);
+	},
+
+	removeHooks: function () {
+		this._removeHooks();
+
+		var container = this._map._container;
+
+		L.DomEvent
+		    .off(container, 'focus', this._onFocus, this)
+		    .off(container, 'blur', this._onBlur, this)
+		    .off(container, 'mousedown', this._onMouseDown, this);
+
+		this._map
+		    .off('focus', this._addHooks, this)
+		    .off('blur', this._removeHooks, this);
+	},
+
+	_onMouseDown: function () {
+		if (this._focused) { return; }
+
+		var body = document.body,
+		    docEl = document.documentElement,
+		    top = body.scrollTop || docEl.scrollTop,
+		    left = body.scrollLeft || docEl.scrollLeft;
+
+		this._map._container.focus();
+
+		window.scrollTo(left, top);
+	},
+
+	_onFocus: function () {
+		this._focused = true;
+		this._map.fire('focus');
+	},
+
+	_onBlur: function () {
+		this._focused = false;
+		this._map.fire('blur');
+	},
+
+	_setPanOffset: function (pan) {
+		var keys = this._panKeys = {},
+		    codes = this.keyCodes,
+		    i, len;
+
+		for (i = 0, len = codes.left.length; i < len; i++) {
+			keys[codes.left[i]] = [-1 * pan, 0];
+		}
+		for (i = 0, len = codes.right.length; i < len; i++) {
+			keys[codes.right[i]] = [pan, 0];
+		}
+		for (i = 0, len = codes.down.length; i < len; i++) {
+			keys[codes.down[i]] = [0, pan];
+		}
+		for (i = 0, len = codes.up.length; i < len; i++) {
+			keys[codes.up[i]] = [0, -1 * pan];
+		}
+	},
+
+	_setZoomOffset: function (zoom) {
+		var keys = this._zoomKeys = {},
+		    codes = this.keyCodes,
+		    i, len;
+
+		for (i = 0, len = codes.zoomIn.length; i < len; i++) {
+			keys[codes.zoomIn[i]] = zoom;
+		}
+		for (i = 0, len = codes.zoomOut.length; i < len; i++) {
+			keys[codes.zoomOut[i]] = -zoom;
+		}
+	},
+
+	_addHooks: function () {
+		L.DomEvent.on(document, 'keydown', this._onKeyDown, this);
+	},
+
+	_removeHooks: function () {
+		L.DomEvent.off(document, 'keydown', this._onKeyDown, this);
+	},
+
+	_onKeyDown: function (e) {
+		var key = e.keyCode,
+		    map = this._map;
+
+		if (key in this._panKeys) {
+
+			if (map._panAnim && map._panAnim._inProgress) { return; }
+
+			map.panBy(this._panKeys[key]);
+
+			if (map.options.maxBounds) {
+				map.panInsideBounds(map.options.maxBounds);
+			}
+
+		} else if (key in this._zoomKeys) {
+			map.setZoom(map.getZoom() + this._zoomKeys[key]);
+
+		} else {
+			return;
+		}
+
+		L.DomEvent.stop(e);
+	}
+});
+
+L.Map.addInitHook('addHandler', 'keyboard', L.Map.Keyboard);
+
+
+/*
+ * L.Handler.MarkerDrag is used internally by L.Marker to make the markers draggable.
+ */
+
+L.Handler.MarkerDrag = L.Handler.extend({
+	initialize: function (marker) {
+		this._marker = marker;
+	},
+
+	addHooks: function () {
+		var icon = this._marker._icon;
+		if (!this._draggable) {
+			this._draggable = new L.Draggable(icon, icon);
+		}
+
+		this._draggable
+			.on('dragstart', this._onDragStart, this)
+			.on('drag', this._onDrag, this)
+			.on('dragend', this._onDragEnd, this);
+		this._draggable.enable();
+		L.DomUtil.addClass(this._marker._icon, 'leaflet-marker-draggable');
+	},
+
+	removeHooks: function () {
+		this._draggable
+			.off('dragstart', this._onDragStart, this)
+			.off('drag', this._onDrag, this)
+			.off('dragend', this._onDragEnd, this);
+
+		this._draggable.disable();
+		L.DomUtil.removeClass(this._marker._icon, 'leaflet-marker-draggable');
+	},
+
+	moved: function () {
+		return this._draggable && this._draggable._moved;
+	},
+
+	_onDragStart: function () {
+		this._marker
+		    .closePopup()
+		    .fire('movestart')
+		    .fire('dragstart');
+	},
+
+	_onDrag: function () {
+		var marker = this._marker,
+		    shadow = marker._shadow,
+		    iconPos = L.DomUtil.getPosition(marker._icon),
+		    latlng = marker._map.layerPointToLatLng(iconPos);
+
+		// update shadow position
+		if (shadow) {
+			L.DomUtil.setPosition(shadow, iconPos);
+		}
+
+		marker._latlng = latlng;
+
+		marker
+		    .fire('move', {latlng: latlng})
+		    .fire('drag');
+	},
+
+	_onDragEnd: function (e) {
+		this._marker
+		    .fire('moveend')
+		    .fire('dragend', e);
+	}
+});
+
+
+/*
+ * L.Control is a base class for implementing map controls. Handles positioning.
+ * All other controls extend from this class.
+ */
+
+L.Control = L.Class.extend({
+	options: {
+		position: 'topright'
+	},
+
+	initialize: function (options) {
+		L.setOptions(this, options);
+	},
+
+	getPosition: function () {
+		return this.options.position;
+	},
+
+	setPosition: function (position) {
+		var map = this._map;
+
+		if (map) {
+			map.removeControl(this);
+		}
+
+		this.options.position = position;
+
+		if (map) {
+			map.addControl(this);
+		}
+
+		return this;
+	},
+
+	getContainer: function () {
+		return this._container;
+	},
+
+	addTo: function (map) {
+		this._map = map;
+
+		var container = this._container = this.onAdd(map),
+		    pos = this.getPosition(),
+		    corner = map._controlCorners[pos];
+
+		L.DomUtil.addClass(container, 'leaflet-control');
+
+		if (pos.indexOf('bottom') !== -1) {
+			corner.insertBefore(container, corner.firstChild);
+		} else {
+			corner.appendChild(container);
+		}
+
+		return this;
+	},
+
+	removeFrom: function (map) {
+		var pos = this.getPosition(),
+		    corner = map._controlCorners[pos];
+
+		corner.removeChild(this._container);
+		this._map = null;
+
+		if (this.onRemove) {
+			this.onRemove(map);
+		}
+
+		return this;
+	},
+
+	_refocusOnMap: function () {
+		if (this._map) {
+			this._map.getContainer().focus();
+		}
+	}
+});
+
+L.control = function (options) {
+	return new L.Control(options);
+};
+
+
+// adds control-related methods to L.Map
+
+L.Map.include({
+	addControl: function (control) {
+		control.addTo(this);
+		return this;
+	},
+
+	removeControl: function (control) {
+		control.removeFrom(this);
+		return this;
+	},
+
+	_initControlPos: function () {
+		var corners = this._controlCorners = {},
+		    l = 'leaflet-',
+		    container = this._controlContainer =
+		            L.DomUtil.create('div', l + 'control-container', this._container);
+
+		function createCorner(vSide, hSide) {
+			var className = l + vSide + ' ' + l + hSide;
+
+			corners[vSide + hSide] = L.DomUtil.create('div', className, container);
+		}
+
+		createCorner('top', 'left');
+		createCorner('top', 'right');
+		createCorner('bottom', 'left');
+		createCorner('bottom', 'right');
+	},
+
+	_clearControlPos: function () {
+		this._container.removeChild(this._controlContainer);
+	}
+});
+
+
+/*
+ * L.Control.Zoom is used for the default zoom buttons on the map.
+ */
+
+L.Control.Zoom = L.Control.extend({
+	options: {
+		position: 'topleft',
+		zoomInText: '+',
+		zoomInTitle: 'Zoom in',
+		zoomOutText: '-',
+		zoomOutTitle: 'Zoom out'
+	},
+
+	onAdd: function (map) {
+		var zoomName = 'leaflet-control-zoom',
+		    container = L.DomUtil.create('div', zoomName + ' leaflet-bar');
+
+		this._map = map;
+
+		this._zoomInButton  = this._createButton(
+		        this.options.zoomInText, this.options.zoomInTitle,
+		        zoomName + '-in',  container, this._zoomIn,  this);
+		this._zoomOutButton = this._createButton(
+		        this.options.zoomOutText, this.options.zoomOutTitle,
+		        zoomName + '-out', container, this._zoomOut, this);
+
+		this._updateDisabled();
+		map.on('zoomend zoomlevelschange', this._updateDisabled, this);
+
+		return container;
+	},
+
+	onRemove: function (map) {
+		map.off('zoomend zoomlevelschange', this._updateDisabled, this);
+	},
+
+	_zoomIn: function (e) {
+		this._map.zoomIn(e.shiftKey ? 3 : 1);
+	},
+
+	_zoomOut: function (e) {
+		this._map.zoomOut(e.shiftKey ? 3 : 1);
+	},
+
+	_createButton: function (html, title, className, container, fn, context) {
+		var link = L.DomUtil.create('a', className, container);
+		link.innerHTML = html;
+		link.href = '#';
+		link.title = title;
+
+		var stop = L.DomEvent.stopPropagation;
+
+		L.DomEvent
+		    .on(link, 'click', stop)
+		    .on(link, 'mousedown', stop)
+		    .on(link, 'dblclick', stop)
+		    .on(link, 'click', L.DomEvent.preventDefault)
+		    .on(link, 'click', fn, context)
+		    .on(link, 'click', this._refocusOnMap, context);
+
+		return link;
+	},
+
+	_updateDisabled: function () {
+		var map = this._map,
+			className = 'leaflet-disabled';
+
+		L.DomUtil.removeClass(this._zoomInButton, className);
+		L.DomUtil.removeClass(this._zoomOutButton, className);
+
+		if (map._zoom === map.getMinZoom()) {
+			L.DomUtil.addClass(this._zoomOutButton, className);
+		}
+		if (map._zoom === map.getMaxZoom()) {
+			L.DomUtil.addClass(this._zoomInButton, className);
+		}
+	}
+});
+
+L.Map.mergeOptions({
+	zoomControl: true
+});
+
+L.Map.addInitHook(function () {
+	if (this.options.zoomControl) {
+		this.zoomControl = new L.Control.Zoom();
+		this.addControl(this.zoomControl);
+	}
+});
+
+L.control.zoom = function (options) {
+	return new L.Control.Zoom(options);
+};
+
+
+
+/*
+ * L.Control.Attribution is used for displaying attribution on the map (added by default).
+ */
+
+L.Control.Attribution = L.Control.extend({
+	options: {
+		position: 'bottomright',
+		prefix: '<a href="http://leafletjs.com" title="A JS library for interactive maps">Leaflet</a>'
+	},
+
+	initialize: function (options) {
+		L.setOptions(this, options);
+
+		this._attributions = {};
+	},
+
+	onAdd: function (map) {
+		this._container = L.DomUtil.create('div', 'leaflet-control-attribution');
+		L.DomEvent.disableClickPropagation(this._container);
+
+		for (var i in map._layers) {
+			if (map._layers[i].getAttribution) {
+				this.addAttribution(map._layers[i].getAttribution());
+			}
+		}
+		
+		map
+		    .on('layeradd', this._onLayerAdd, this)
+		    .on('layerremove', this._onLayerRemove, this);
+
+		this._update();
+
+		return this._container;
+	},
+
+	onRemove: function (map) {
+		map
+		    .off('layeradd', this._onLayerAdd)
+		    .off('layerremove', this._onLayerRemove);
+
+	},
+
+	setPrefix: function (prefix) {
+		this.options.prefix = prefix;
+		this._update();
+		return this;
+	},
+
+	addAttribution: function (text) {
+		if (!text) { return; }
+
+		if (!this._attributions[text]) {
+			this._attributions[text] = 0;
+		}
+		this._attributions[text]++;
+
+		this._update();
+
+		return this;
+	},
+
+	removeAttribution: function (text) {
+		if (!text) { return; }
+
+		if (this._attributions[text]) {
+			this._attributions[text]--;
+			this._update();
+		}
+
+		return this;
+	},
+
+	_update: function () {
+		if (!this._map) { return; }
+
+		var attribs = [];
+
+		for (var i in this._attributions) {
+			if (this._attributions[i]) {
+				attribs.push(i);
+			}
+		}
+
+		var prefixAndAttribs = [];
+
+		if (this.options.prefix) {
+			prefixAndAttribs.push(this.options.prefix);
+		}
+		if (attribs.length) {
+			prefixAndAttribs.push(attribs.join(', '));
+		}
+
+		this._container.innerHTML = prefixAndAttribs.join(' | ');
+	},
+
+	_onLayerAdd: function (e) {
+		if (e.layer.getAttribution) {
+			this.addAttribution(e.layer.getAttribution());
+		}
+	},
+
+	_onLayerRemove: function (e) {
+		if (e.layer.getAttribution) {
+			this.removeAttribution(e.layer.getAttribution());
+		}
+	}
+});
+
+L.Map.mergeOptions({
+	attributionControl: true
+});
+
+L.Map.addInitHook(function () {
+	if (this.options.attributionControl) {
+		this.attributionControl = (new L.Control.Attribution()).addTo(this);
+	}
+});
+
+L.control.attribution = function (options) {
+	return new L.Control.Attribution(options);
+};
+
+
+/*
+ * L.Control.Scale is used for displaying metric/imperial scale on the map.
+ */
+
+L.Control.Scale = L.Control.extend({
+	options: {
+		position: 'bottomleft',
+		maxWidth: 100,
+		metric: true,
+		imperial: true,
+		updateWhenIdle: false
+	},
+
+	onAdd: function (map) {
+		this._map = map;
+
+		var className = 'leaflet-control-scale',
+		    container = L.DomUtil.create('div', className),
+		    options = this.options;
+
+		this._addScales(options, className, container);
+
+		map.on(options.updateWhenIdle ? 'moveend' : 'move', this._update, this);
+		map.whenReady(this._update, this);
+
+		return container;
+	},
+
+	onRemove: function (map) {
+		map.off(this.options.updateWhenIdle ? 'moveend' : 'move', this._update, this);
+	},
+
+	_addScales: function (options, className, container) {
+		if (options.metric) {
+			this._mScale = L.DomUtil.create('div', className + '-line', container);
+		}
+		if (options.imperial) {
+			this._iScale = L.DomUtil.create('div', className + '-line', container);
+		}
+	},
+
+	_update: function () {
+		var bounds = this._map.getBounds(),
+		    centerLat = bounds.getCenter().lat,
+		    halfWorldMeters = 6378137 * Math.PI * Math.cos(centerLat * Math.PI / 180),
+		    dist = halfWorldMeters * (bounds.getNorthEast().lng - bounds.getSouthWest().lng) / 180,
+
+		    size = this._map.getSize(),
+		    options = this.options,
+		    maxMeters = 0;
+
+		if (size.x > 0) {
+			maxMeters = dist * (options.maxWidth / size.x);
+		}
+
+		this._updateScales(options, maxMeters);
+	},
+
+	_updateScales: function (options, maxMeters) {
+		if (options.metric && maxMeters) {
+			this._updateMetric(maxMeters);
+		}
+
+		if (options.imperial && maxMeters) {
+			this._updateImperial(maxMeters);
+		}
+	},
+
+	_updateMetric: function (maxMeters) {
+		var meters = this._getRoundNum(maxMeters);
+
+		this._mScale.style.width = this._getScaleWidth(meters / maxMeters) + 'px';
+		this._mScale.innerHTML = meters < 1000 ? meters + ' m' : (meters / 1000) + ' km';
+	},
+
+	_updateImperial: function (maxMeters) {
+		var maxFeet = maxMeters * 3.2808399,
+		    scale = this._iScale,
+		    maxMiles, miles, feet;
+
+		if (maxFeet > 5280) {
+			maxMiles = maxFeet / 5280;
+			miles = this._getRoundNum(maxMiles);
+
+			scale.style.width = this._getScaleWidth(miles / maxMiles) + 'px';
+			scale.innerHTML = miles + ' mi';
+
+		} else {
+			feet = this._getRoundNum(maxFeet);
+
+			scale.style.width = this._getScaleWidth(feet / maxFeet) + 'px';
+			scale.innerHTML = feet + ' ft';
+		}
+	},
+
+	_getScaleWidth: function (ratio) {
+		return Math.round(this.options.maxWidth * ratio) - 10;
+	},
+
+	_getRoundNum: function (num) {
+		var pow10 = Math.pow(10, (Math.floor(num) + '').length - 1),
+		    d = num / pow10;
+
+		d = d >= 10 ? 10 : d >= 5 ? 5 : d >= 3 ? 3 : d >= 2 ? 2 : 1;
+
+		return pow10 * d;
+	}
+});
+
+L.control.scale = function (options) {
+	return new L.Control.Scale(options);
+};
+
+
+/*
+ * L.Control.Layers is a control to allow users to switch between different layers on the map.
+ */
+
+L.Control.Layers = L.Control.extend({
+	options: {
+		collapsed: true,
+		position: 'topright',
+		autoZIndex: true
+	},
+
+	initialize: function (baseLayers, overlays, options) {
+		L.setOptions(this, options);
+
+		this._layers = {};
+		this._lastZIndex = 0;
+		this._handlingClick = false;
+
+		for (var i in baseLayers) {
+			this._addLayer(baseLayers[i], i);
+		}
+
+		for (i in overlays) {
+			this._addLayer(overlays[i], i, true);
+		}
+	},
+
+	onAdd: function (map) {
+		this._initLayout();
+		this._update();
+
+		map
+		    .on('layeradd', this._onLayerChange, this)
+		    .on('layerremove', this._onLayerChange, this);
+
+		return this._container;
+	},
+
+	onRemove: function (map) {
+		map
+		    .off('layeradd', this._onLayerChange, this)
+		    .off('layerremove', this._onLayerChange, this);
+	},
+
+	addBaseLayer: function (layer, name) {
+		this._addLayer(layer, name);
+		this._update();
+		return this;
+	},
+
+	addOverlay: function (layer, name) {
+		this._addLayer(layer, name, true);
+		this._update();
+		return this;
+	},
+
+	removeLayer: function (layer) {
+		var id = L.stamp(layer);
+		delete this._layers[id];
+		this._update();
+		return this;
+	},
+
+	_initLayout: function () {
+		var className = 'leaflet-control-layers',
+		    container = this._container = L.DomUtil.create('div', className);
+
+		//Makes this work on IE10 Touch devices by stopping it from firing a mouseout event when the touch is released
+		container.setAttribute('aria-haspopup', true);
+
+		if (!L.Browser.touch) {
+			L.DomEvent
+				.disableClickPropagation(container)
+				.disableScrollPropagation(container);
+		} else {
+			L.DomEvent.on(container, 'click', L.DomEvent.stopPropagation);
+		}
+
+		var form = this._form = L.DomUtil.create('form', className + '-list');
+
+		if (this.options.collapsed) {
+			if (!L.Browser.android) {
+				L.DomEvent
+				    .on(container, 'mouseover', this._expand, this)
+				    .on(container, 'mouseout', this._collapse, this);
+			}
+			var link = this._layersLink = L.DomUtil.create('a', className + '-toggle', container);
+			link.href = '#';
+			link.title = 'Layers';
+
+			if (L.Browser.touch) {
+				L.DomEvent
+				    .on(link, 'click', L.DomEvent.stop)
+				    .on(link, 'click', this._expand, this);
+			}
+			else {
+				L.DomEvent.on(link, 'focus', this._expand, this);
+			}
+			//Work around for Firefox android issue https://github.com/Leaflet/Leaflet/issues/2033
+			L.DomEvent.on(form, 'click', function () {
+				setTimeout(L.bind(this._onInputClick, this), 0);
+			}, this);
+
+			this._map.on('click', this._collapse, this);
+			// TODO keyboard accessibility
+		} else {
+			this._expand();
+		}
+
+		this._baseLayersList = L.DomUtil.create('div', className + '-base', form);
+		this._separator = L.DomUtil.create('div', className + '-separator', form);
+		this._overlaysList = L.DomUtil.create('div', className + '-overlays', form);
+
+		container.appendChild(form);
+	},
+
+	_addLayer: function (layer, name, overlay) {
+		var id = L.stamp(layer);
+
+		this._layers[id] = {
+			layer: layer,
+			name: name,
+			overlay: overlay
+		};
+
+		if (this.options.autoZIndex && layer.setZIndex) {
+			this._lastZIndex++;
+			layer.setZIndex(this._lastZIndex);
+		}
+	},
+
+	_update: function () {
+		if (!this._container) {
+			return;
+		}
+
+		this._baseLayersList.innerHTML = '';
+		this._overlaysList.innerHTML = '';
+
+		var baseLayersPresent = false,
+		    overlaysPresent = false,
+		    i, obj;
+
+		for (i in this._layers) {
+			obj = this._layers[i];
+			this._addItem(obj);
+			overlaysPresent = overlaysPresent || obj.overlay;
+			baseLayersPresent = baseLayersPresent || !obj.overlay;
+		}
+
+		this._separator.style.display = overlaysPresent && baseLayersPresent ? '' : 'none';
+	},
+
+	_onLayerChange: function (e) {
+		var obj = this._layers[L.stamp(e.layer)];
+
+		if (!obj) { return; }
+
+		if (!this._handlingClick) {
+			this._update();
+		}
+
+		var type = obj.overlay ?
+			(e.type === 'layeradd' ? 'overlayadd' : 'overlayremove') :
+			(e.type === 'layeradd' ? 'baselayerchange' : null);
+
+		if (type) {
+			this._map.fire(type, obj);
+		}
+	},
+
+	// IE7 bugs out if you create a radio dynamically, so you have to do it this hacky way (see http://bit.ly/PqYLBe)
+	_createRadioElement: function (name, checked) {
+
+		var radioHtml = '<input type="radio" class="leaflet-control-layers-selector" name="' + name + '"';
+		if (checked) {
+			radioHtml += ' checked="checked"';
+		}
+		radioHtml += '/>';
+
+		var radioFragment = document.createElement('div');
+		radioFragment.innerHTML = radioHtml;
+
+		return radioFragment.firstChild;
+	},
+
+	_addItem: function (obj) {
+		var label = document.createElement('label'),
+		    input,
+		    checked = this._map.hasLayer(obj.layer);
+
+		if (obj.overlay) {
+			input = document.createElement('input');
+			input.type = 'checkbox';
+			input.className = 'leaflet-control-layers-selector';
+			input.defaultChecked = checked;
+		} else {
+			input = this._createRadioElement('leaflet-base-layers', checked);
+		}
+
+		input.layerId = L.stamp(obj.layer);
+
+		L.DomEvent.on(input, 'click', this._onInputClick, this);
+
+		var name = document.createElement('span');
+		name.innerHTML = ' ' + obj.name;
+
+		label.appendChild(input);
+		label.appendChild(name);
+
+		var container = obj.overlay ? this._overlaysList : this._baseLayersList;
+		container.appendChild(label);
+
+		return label;
+	},
+
+	_onInputClick: function () {
+		var i, input, obj,
+		    inputs = this._form.getElementsByTagName('input'),
+		    inputsLen = inputs.length;
+
+		this._handlingClick = true;
+
+		for (i = 0; i < inputsLen; i++) {
+			input = inputs[i];
+			obj = this._layers[input.layerId];
+
+			if (input.checked && !this._map.hasLayer(obj.layer)) {
+				this._map.addLayer(obj.layer);
+
+			} else if (!input.checked && this._map.hasLayer(obj.layer)) {
+				this._map.removeLayer(obj.layer);
+			}
+		}
+
+		this._handlingClick = false;
+
+		this._refocusOnMap();
+	},
+
+	_expand: function () {
+		L.DomUtil.addClass(this._container, 'leaflet-control-layers-expanded');
+	},
+
+	_collapse: function () {
+		this._container.className = this._container.className.replace(' leaflet-control-layers-expanded', '');
+	}
+});
+
+L.control.layers = function (baseLayers, overlays, options) {
+	return new L.Control.Layers(baseLayers, overlays, options);
+};
+
+
+/*
+ * L.PosAnimation is used by Leaflet internally for pan animations.
+ */
+
+L.PosAnimation = L.Class.extend({
+	includes: L.Mixin.Events,
+
+	run: function (el, newPos, duration, easeLinearity) { // (HTMLElement, Point[, Number, Number])
+		this.stop();
+
+		this._el = el;
+		this._inProgress = true;
+		this._newPos = newPos;
+
+		this.fire('start');
+
+		el.style[L.DomUtil.TRANSITION] = 'all ' + (duration || 0.25) +
+		        's cubic-bezier(0,0,' + (easeLinearity || 0.5) + ',1)';
+
+		L.DomEvent.on(el, L.DomUtil.TRANSITION_END, this._onTransitionEnd, this);
+		L.DomUtil.setPosition(el, newPos);
+
+		// toggle reflow, Chrome flickers for some reason if you don't do this
+		L.Util.falseFn(el.offsetWidth);
+
+		// there's no native way to track value updates of transitioned properties, so we imitate this
+		this._stepTimer = setInterval(L.bind(this._onStep, this), 50);
+	},
+
+	stop: function () {
+		if (!this._inProgress) { return; }
+
+		// if we just removed the transition property, the element would jump to its final position,
+		// so we need to make it stay at the current position
+
+		L.DomUtil.setPosition(this._el, this._getPos());
+		this._onTransitionEnd();
+		L.Util.falseFn(this._el.offsetWidth); // force reflow in case we are about to start a new animation
+	},
+
+	_onStep: function () {
+		var stepPos = this._getPos();
+		if (!stepPos) {
+			this._onTransitionEnd();
+			return;
+		}
+		// jshint camelcase: false
+		// make L.DomUtil.getPosition return intermediate position value during animation
+		this._el._leaflet_pos = stepPos;
+
+		this.fire('step');
+	},
+
+	// you can't easily get intermediate values of properties animated with CSS3 Transitions,
+	// we need to parse computed style (in case of transform it returns matrix string)
+
+	_transformRe: /([-+]?(?:\d*\.)?\d+)\D*, ([-+]?(?:\d*\.)?\d+)\D*\)/,
+
+	_getPos: function () {
+		var left, top, matches,
+		    el = this._el,
+		    style = window.getComputedStyle(el);
+
+		if (L.Browser.any3d) {
+			matches = style[L.DomUtil.TRANSFORM].match(this._transformRe);
+			if (!matches) { return; }
+			left = parseFloat(matches[1]);
+			top  = parseFloat(matches[2]);
+		} else {
+			left = parseFloat(style.left);
+			top  = parseFloat(style.top);
+		}
+
+		return new L.Point(left, top, true);
+	},
+
+	_onTransitionEnd: function () {
+		L.DomEvent.off(this._el, L.DomUtil.TRANSITION_END, this._onTransitionEnd, this);
+
+		if (!this._inProgress) { return; }
+		this._inProgress = false;
+
+		this._el.style[L.DomUtil.TRANSITION] = '';
+
+		// jshint camelcase: false
+		// make sure L.DomUtil.getPosition returns the final position value after animation
+		this._el._leaflet_pos = this._newPos;
+
+		clearInterval(this._stepTimer);
+
+		this.fire('step').fire('end');
+	}
+
+});
+
+
+/*
+ * Extends L.Map to handle panning animations.
+ */
+
+L.Map.include({
+
+	setView: function (center, zoom, options) {
+
+		zoom = zoom === undefined ? this._zoom : this._limitZoom(zoom);
+		center = this._limitCenter(L.latLng(center), zoom, this.options.maxBounds);
+		options = options || {};
+
+		if (this._panAnim) {
+			this._panAnim.stop();
+		}
+
+		if (this._loaded && !options.reset && options !== true) {
+
+			if (options.animate !== undefined) {
+				options.zoom = L.extend({animate: options.animate}, options.zoom);
+				options.pan = L.extend({animate: options.animate}, options.pan);
+			}
+
+			// try animating pan or zoom
+			var animated = (this._zoom !== zoom) ?
+				this._tryAnimatedZoom && this._tryAnimatedZoom(center, zoom, options.zoom) :
+				this._tryAnimatedPan(center, options.pan);
+
+			if (animated) {
+				// prevent resize handler call, the view will refresh after animation anyway
+				clearTimeout(this._sizeTimer);
+				return this;
+			}
+		}
+
+		// animation didn't start, just reset the map view
+		this._resetView(center, zoom);
+
+		return this;
+	},
+
+	panBy: function (offset, options) {
+		offset = L.point(offset).round();
+		options = options || {};
+
+		if (!offset.x && !offset.y) {
+			return this;
+		}
+
+		if (!this._panAnim) {
+			this._panAnim = new L.PosAnimation();
+
+			this._panAnim.on({
+				'step': this._onPanTransitionStep,
+				'end': this._onPanTransitionEnd
+			}, this);
+		}
+
+		// don't fire movestart if animating inertia
+		if (!options.noMoveStart) {
+			this.fire('movestart');
+		}
+
+		// animate pan unless animate: false specified
+		if (options.animate !== false) {
+			L.DomUtil.addClass(this._mapPane, 'leaflet-pan-anim');
+
+			var newPos = this._getMapPanePos().subtract(offset);
+			this._panAnim.run(this._mapPane, newPos, options.duration || 0.25, options.easeLinearity);
+		} else {
+			this._rawPanBy(offset);
+			this.fire('move').fire('moveend');
+		}
+
+		return this;
+	},
+
+	_onPanTransitionStep: function () {
+		this.fire('move');
+	},
+
+	_onPanTransitionEnd: function () {
+		L.DomUtil.removeClass(this._mapPane, 'leaflet-pan-anim');
+		this.fire('moveend');
+	},
+
+	_tryAnimatedPan: function (center, options) {
+		// difference between the new and current centers in pixels
+		var offset = this._getCenterOffset(center)._floor();
+
+		// don't animate too far unless animate: true specified in options
+		if ((options && options.animate) !== true && !this.getSize().contains(offset)) { return false; }
+
+		this.panBy(offset, options);
+
+		return true;
+	}
+});
+
+
+/*
+ * L.PosAnimation fallback implementation that powers Leaflet pan animations
+ * in browsers that don't support CSS3 Transitions.
+ */
+
+L.PosAnimation = L.DomUtil.TRANSITION ? L.PosAnimation : L.PosAnimation.extend({
+
+	run: function (el, newPos, duration, easeLinearity) { // (HTMLElement, Point[, Number, Number])
+		this.stop();
+
+		this._el = el;
+		this._inProgress = true;
+		this._duration = duration || 0.25;
+		this._easeOutPower = 1 / Math.max(easeLinearity || 0.5, 0.2);
+
+		this._startPos = L.DomUtil.getPosition(el);
+		this._offset = newPos.subtract(this._startPos);
+		this._startTime = +new Date();
+
+		this.fire('start');
+
+		this._animate();
+	},
+
+	stop: function () {
+		if (!this._inProgress) { return; }
+
+		this._step();
+		this._complete();
+	},
+
+	_animate: function () {
+		// animation loop
+		this._animId = L.Util.requestAnimFrame(this._animate, this);
+		this._step();
+	},
+
+	_step: function () {
+		var elapsed = (+new Date()) - this._startTime,
+		    duration = this._duration * 1000;
+
+		if (elapsed < duration) {
+			this._runFrame(this._easeOut(elapsed / duration));
+		} else {
+			this._runFrame(1);
+			this._complete();
+		}
+	},
+
+	_runFrame: function (progress) {
+		var pos = this._startPos.add(this._offset.multiplyBy(progress));
+		L.DomUtil.setPosition(this._el, pos);
+
+		this.fire('step');
+	},
+
+	_complete: function () {
+		L.Util.cancelAnimFrame(this._animId);
+
+		this._inProgress = false;
+		this.fire('end');
+	},
+
+	_easeOut: function (t) {
+		return 1 - Math.pow(1 - t, this._easeOutPower);
+	}
+});
+
+
+/*
+ * Extends L.Map to handle zoom animations.
+ */
+
+L.Map.mergeOptions({
+	zoomAnimation: true,
+	zoomAnimationThreshold: 4
+});
+
+if (L.DomUtil.TRANSITION) {
+
+	L.Map.addInitHook(function () {
+		// don't animate on browsers without hardware-accelerated transitions or old Android/Opera
+		this._zoomAnimated = this.options.zoomAnimation && L.DomUtil.TRANSITION &&
+				L.Browser.any3d && !L.Browser.android23 && !L.Browser.mobileOpera;
+
+		// zoom transitions run with the same duration for all layers, so if one of transitionend events
+		// happens after starting zoom animation (propagating to the map pane), we know that it ended globally
+		if (this._zoomAnimated) {
+			L.DomEvent.on(this._mapPane, L.DomUtil.TRANSITION_END, this._catchTransitionEnd, this);
+		}
+	});
+}
+
+L.Map.include(!L.DomUtil.TRANSITION ? {} : {
+
+	_catchTransitionEnd: function (e) {
+		if (this._animatingZoom && e.propertyName.indexOf('transform') >= 0) {
+			this._onZoomTransitionEnd();
+		}
+	},
+
+	_nothingToAnimate: function () {
+		return !this._container.getElementsByClassName('leaflet-zoom-animated').length;
+	},
+
+	_tryAnimatedZoom: function (center, zoom, options) {
+
+		if (this._animatingZoom) { return true; }
+
+		options = options || {};
+
+		// don't animate if disabled, not supported or zoom difference is too large
+		if (!this._zoomAnimated || options.animate === false || this._nothingToAnimate() ||
+		        Math.abs(zoom - this._zoom) > this.options.zoomAnimationThreshold) { return false; }
+
+		// offset is the pixel coords of the zoom origin relative to the current center
+		var scale = this.getZoomScale(zoom),
+		    offset = this._getCenterOffset(center)._divideBy(1 - 1 / scale),
+			origin = this._getCenterLayerPoint()._add(offset);
+
+		// don't animate if the zoom origin isn't within one screen from the current center, unless forced
+		if (options.animate !== true && !this.getSize().contains(offset)) { return false; }
+
+		this
+		    .fire('movestart')
+		    .fire('zoomstart');
+
+		this._animateZoom(center, zoom, origin, scale, null, true);
+
+		return true;
+	},
+
+	_animateZoom: function (center, zoom, origin, scale, delta, backwards, forTouchZoom) {
+
+		if (!forTouchZoom) {
+			this._animatingZoom = true;
+		}
+
+		// put transform transition on all layers with leaflet-zoom-animated class
+		L.DomUtil.addClass(this._mapPane, 'leaflet-zoom-anim');
+
+		// remember what center/zoom to set after animation
+		this._animateToCenter = center;
+		this._animateToZoom = zoom;
+
+		// disable any dragging during animation
+		if (L.Draggable) {
+			L.Draggable._disabled = true;
+		}
+
+		L.Util.requestAnimFrame(function () {
+			this.fire('zoomanim', {
+				center: center,
+				zoom: zoom,
+				origin: origin,
+				scale: scale,
+				delta: delta,
+				backwards: backwards
+			});
+			// horrible hack to work around a Chrome bug https://github.com/Leaflet/Leaflet/issues/3689
+			setTimeout(L.bind(this._onZoomTransitionEnd, this), 250);
+		}, this);
+	},
+
+	_onZoomTransitionEnd: function () {
+		if (!this._animatingZoom) { return; }
+
+		this._animatingZoom = false;
+
+		L.DomUtil.removeClass(this._mapPane, 'leaflet-zoom-anim');
+
+		L.Util.requestAnimFrame(function () {
+			this._resetView(this._animateToCenter, this._animateToZoom, true, true);
+
+			if (L.Draggable) {
+				L.Draggable._disabled = false;
+			}
+		}, this);
+	}
+});
+
+
+/*
+	Zoom animation logic for L.TileLayer.
+*/
+
+L.TileLayer.include({
+	_animateZoom: function (e) {
+		if (!this._animating) {
+			this._animating = true;
+			this._prepareBgBuffer();
+		}
+
+		var bg = this._bgBuffer,
+		    transform = L.DomUtil.TRANSFORM,
+		    initialTransform = e.delta ? L.DomUtil.getTranslateString(e.delta) : bg.style[transform],
+		    scaleStr = L.DomUtil.getScaleString(e.scale, e.origin);
+
+		bg.style[transform] = e.backwards ?
+				scaleStr + ' ' + initialTransform :
+				initialTransform + ' ' + scaleStr;
+	},
+
+	_endZoomAnim: function () {
+		var front = this._tileContainer,
+		    bg = this._bgBuffer;
+
+		front.style.visibility = '';
+		front.parentNode.appendChild(front); // Bring to fore
+
+		// force reflow
+		L.Util.falseFn(bg.offsetWidth);
+
+		var zoom = this._map.getZoom();
+		if (zoom > this.options.maxZoom || zoom < this.options.minZoom) {
+			this._clearBgBuffer();
+		}
+
+		this._animating = false;
+	},
+
+	_clearBgBuffer: function () {
+		var map = this._map;
+
+		if (map && !map._animatingZoom && !map.touchZoom._zooming) {
+			this._bgBuffer.innerHTML = '';
+			this._bgBuffer.style[L.DomUtil.TRANSFORM] = '';
+		}
+	},
+
+	_prepareBgBuffer: function () {
+
+		var front = this._tileContainer,
+		    bg = this._bgBuffer;
+
+		// if foreground layer doesn't have many tiles but bg layer does,
+		// keep the existing bg layer and just zoom it some more
+
+		var bgLoaded = this._getLoadedTilesPercentage(bg),
+		    frontLoaded = this._getLoadedTilesPercentage(front);
+
+		if (bg && bgLoaded > 0.5 && frontLoaded < 0.5) {
+
+			front.style.visibility = 'hidden';
+			this._stopLoadingImages(front);
+			return;
+		}
+
+		// prepare the buffer to become the front tile pane
+		bg.style.visibility = 'hidden';
+		bg.style[L.DomUtil.TRANSFORM] = '';
+
+		// switch out the current layer to be the new bg layer (and vice-versa)
+		this._tileContainer = bg;
+		bg = this._bgBuffer = front;
+
+		this._stopLoadingImages(bg);
+
+		//prevent bg buffer from clearing right after zoom
+		clearTimeout(this._clearBgBufferTimer);
+	},
+
+	_getLoadedTilesPercentage: function (container) {
+		var tiles = container.getElementsByTagName('img'),
+		    i, len, count = 0;
+
+		for (i = 0, len = tiles.length; i < len; i++) {
+			if (tiles[i].complete) {
+				count++;
+			}
+		}
+		return count / len;
+	},
+
+	// stops loading all tiles in the background layer
+	_stopLoadingImages: function (container) {
+		var tiles = Array.prototype.slice.call(container.getElementsByTagName('img')),
+		    i, len, tile;
+
+		for (i = 0, len = tiles.length; i < len; i++) {
+			tile = tiles[i];
+
+			if (!tile.complete) {
+				tile.onload = L.Util.falseFn;
+				tile.onerror = L.Util.falseFn;
+				tile.src = L.Util.emptyImageUrl;
+
+				tile.parentNode.removeChild(tile);
+			}
+		}
+	}
+});
+
+
+/*
+ * Provides L.Map with convenient shortcuts for using browser geolocation features.
+ */
+
+L.Map.include({
+	_defaultLocateOptions: {
+		watch: false,
+		setView: false,
+		maxZoom: Infinity,
+		timeout: 10000,
+		maximumAge: 0,
+		enableHighAccuracy: false
+	},
+
+	locate: function (/*Object*/ options) {
+
+		options = this._locateOptions = L.extend(this._defaultLocateOptions, options);
+
+		if (!navigator.geolocation) {
+			this._handleGeolocationError({
+				code: 0,
+				message: 'Geolocation not supported.'
+			});
+			return this;
+		}
+
+		var onResponse = L.bind(this._handleGeolocationResponse, this),
+			onError = L.bind(this._handleGeolocationError, this);
+
+		if (options.watch) {
+			this._locationWatchId =
+			        navigator.geolocation.watchPosition(onResponse, onError, options);
+		} else {
+			navigator.geolocation.getCurrentPosition(onResponse, onError, options);
+		}
+		return this;
+	},
+
+	stopLocate: function () {
+		if (navigator.geolocation) {
+			navigator.geolocation.clearWatch(this._locationWatchId);
+		}
+		if (this._locateOptions) {
+			this._locateOptions.setView = false;
+		}
+		return this;
+	},
+
+	_handleGeolocationError: function (error) {
+		var c = error.code,
+		    message = error.message ||
+		            (c === 1 ? 'permission denied' :
+		            (c === 2 ? 'position unavailable' : 'timeout'));
+
+		if (this._locateOptions.setView && !this._loaded) {
+			this.fitWorld();
+		}
+
+		this.fire('locationerror', {
+			code: c,
+			message: 'Geolocation error: ' + message + '.'
+		});
+	},
+
+	_handleGeolocationResponse: function (pos) {
+		var lat = pos.coords.latitude,
+		    lng = pos.coords.longitude,
+		    latlng = new L.LatLng(lat, lng),
+
+		    latAccuracy = 180 * pos.coords.accuracy / 40075017,
+		    lngAccuracy = latAccuracy / Math.cos(L.LatLng.DEG_TO_RAD * lat),
+
+		    bounds = L.latLngBounds(
+		            [lat - latAccuracy, lng - lngAccuracy],
+		            [lat + latAccuracy, lng + lngAccuracy]),
+
+		    options = this._locateOptions;
+
+		if (options.setView) {
+			var zoom = Math.min(this.getBoundsZoom(bounds), options.maxZoom);
+			this.setView(latlng, zoom);
+		}
+
+		var data = {
+			latlng: latlng,
+			bounds: bounds,
+			timestamp: pos.timestamp
+		};
+
+		for (var i in pos.coords) {
+			if (typeof pos.coords[i] === 'number') {
+				data[i] = pos.coords[i];
+			}
+		}
+
+		this.fire('locationfound', data);
+	}
+});
+
+
+}(window, document));
\ No newline at end of file
diff --git a/tests/photosphere1.earth b/tests/photosphere1.earth
new file mode 100644
index 0000000..f1493b9
--- /dev/null
+++ b/tests/photosphere1.earth
@@ -0,0 +1,30 @@
+<!--
+osgEarth Sample
+
+Shows the skyview driver, which will flip an image source horizontally
+so that it's viewable from inside the globe, planetarium style.
+
+This image was shot with the "photosphere" mode with a Google Nexus 6p
+
+Run with osgearth_skyview photosphere1.earth
+-->
+<map name="photosphere" type="geocentric">
+
+    <options>
+
+        <terrain>
+            <cluster_culling>false</cluster_culling>
+            <skirt_ratio>0.0</skirt_ratio>
+        </terrain>
+
+    </options>
+
+    <!-- Wrap the image in the skyview driver to flip it-->
+    <image name="stockholm_castle" driver="skyview">
+	    <image name="stockholm_castle" driver="osg">
+	        <url>../data/skyview/stockholm_castle.jpg</url>
+	        <profile>global-geodetic</profile>
+	    </image>      
+    </image>
+
+</map>
diff --git a/tests/photosphere2.earth b/tests/photosphere2.earth
new file mode 100644
index 0000000..c0bb4a0
--- /dev/null
+++ b/tests/photosphere2.earth
@@ -0,0 +1,30 @@
+<!--
+osgEarth Sample
+
+Shows the skyview driver, which will flip an image source horizontally
+so that it's viewable from inside the globe, planetarium style.
+
+This image was shot with the "photosphere" mode with a Google Nexus 6p
+
+Run with osgearth_skyview photosphere2.earth
+-->
+<map name="photosphere" type="geocentric">
+
+    <options>
+
+        <terrain>
+            <cluster_culling>false</cluster_culling>
+            <skirt_ratio>0.0</skirt_ratio>
+        </terrain>
+
+    </options>
+
+    <!-- Wrap the image in the skyview driver to flip it-->
+    <image name="stockholm_subway" driver="skyview">
+	    <image name="stockholm_subway" driver="osg">
+	        <url>../data/skyview/stockholm_subway.jpg</url>
+	        <profile>global-geodetic</profile>
+	    </image>      
+    </image>
+
+</map>
diff --git a/tests/readymap-osm.earth b/tests/readymap-osm.earth
index 35378fe..678c9cd 100644
--- a/tests/readymap-osm.earth
+++ b/tests/readymap-osm.earth
@@ -21,7 +21,7 @@ http://readymap.org
         <url>http://readymap.org/readymap/tiles/1.0.0/119/</url>
     </image>
     
-    <extensions>
+    <viewpoints>
         <viewpoint name="Los Angeles" heading="35.27" height="97.48" lat="34.051" long="-117.974" pitch="-17" range="136405"/>
-    </extensions>
+    </viewpoints>
 </map>
diff --git a/tests/readymap-priority.earth b/tests/readymap-priority.earth
new file mode 100644
index 0000000..e04e888
--- /dev/null
+++ b/tests/readymap-priority.earth
@@ -0,0 +1,35 @@
+<!--
+osgEarth Sample - ReadyMap.ORG Server - http://readymap.org
+
+ReadyMap.ORG provides free global base map data for osgEarth developers!
+This tiled, worldwide dataset of imagery, elevation, and street map data
+is a great base map that provides global context for your own local datasets.
+It works "out of the box" with osgEarth applications.
+
+**** NOTICE ****
+YOU ARE RESPONSIBLE for abiding by the TERMS AND CONDITIONS outlined at:
+http://readymap.org
+
+-->
+<map name="readymap.org" type="geocentric">
+    
+    <options>
+        <terrain first_lod="1" driver="rex" high_resolution_first="true"/>
+    </options>
+    
+    <image name="readymap_imagery" driver="tms">
+        <url>http://readymap.org/readymap/tiles/1.0.0/7/</url>
+    </image>
+        
+    <elevation name="readymap_elevation" driver="tms">
+        <url>http://readymap.org/readymap/tiles/1.0.0/116/</url>
+    </elevation>
+    
+    <extensions>        
+        <viewpoints>
+            <viewpoint name="Washington St" heading="0.5013023037097585" height="4101.627114404924" lat="46.85909894548915" long="-121.7598368518208" pitch="-89.43249895879129" range="29029.34246828893"/>
+            <viewpoint name="Nepal" heading="-72.70835146844568" height="6334.845537136309" lat="27.94213038800919" long="86.9936567556778" pitch="-18.63803872963365" range="13611.24948464565"/>
+            <viewpoint name="Matterhorn" heading="-1.429462844200832" height="2282.858508689329" lat="45.95106319557" long="7.642741711675961" pitch="-25.12269405854052" range="26690.10606054494"/>
+        </viewpoints>
+    </extensions>
+</map>
diff --git a/tests/readymap-rex.earth b/tests/readymap-rex.earth
new file mode 100644
index 0000000..8b6e8de
--- /dev/null
+++ b/tests/readymap-rex.earth
@@ -0,0 +1,31 @@
+<!--
+ !  osgEarth Sample - REX Engine.
+ !-->
+
+<map name="rex test">
+    
+    <options>        
+        <terrain driver                = "rex"
+                 tile_size             = "17"
+                 merges_per_frame      = "4"
+                 morph_terrain         = "true"
+                 morph_imagery         = "true"
+                 high_resolution_first = "true"
+                 skirt_ratio           = "0.0"
+                 normal_maps           = "true">
+        </terrain>
+    </options>
+    
+    <image name="readymap_imagery" driver="tms">
+        <url>http://readymap.org/readymap/tiles/1.0.0/7/</url>
+    </image>
+    
+    <elevation name="readymap_elevation" driver="tms">
+        <url>http://readymap.org/readymap/tiles/1.0.0/116/</url>
+    </elevation>
+    
+    <extensions>
+        <xi:include href="viewpoints.xml"/>
+    </extensions>
+    
+</map>
diff --git a/tests/readymap.earth b/tests/readymap.earth
index 1275dda..42fd5ea 100644
--- a/tests/readymap.earth
+++ b/tests/readymap.earth
@@ -11,11 +11,7 @@ YOU ARE RESPONSIBLE for abiding by the TERMS AND CONDITIONS outlined at:
 http://readymap.org
 
 -->
-<map name="readymap.org" type="geocentric">
-    
-    <options>
-        <terrain first_lod="1" normalize_edges="true"/>
-    </options>
+<map name="readymap.org" type="geocentric">    
     
     <image name="readymap_imagery" driver="tms">
         <url>http://readymap.org/readymap/tiles/1.0.0/7/</url>
@@ -24,4 +20,6 @@ http://readymap.org
     <elevation name="readymap_elevation" driver="tms">
         <url>http://readymap.org/readymap/tiles/1.0.0/116/</url>
     </elevation>
+    
+    <xi:include href="viewpoints.xml"/>
 </map>
diff --git a/tests/readymap_elevation.xml b/tests/readymap_elevation.xml
new file mode 100644
index 0000000..739b108
--- /dev/null
+++ b/tests/readymap_elevation.xml
@@ -0,0 +1,3 @@
+ <elevation name="readymap_elevation" driver="tms">
+        <url>http://readymap.org/readymap/tiles/1.0.0/116/</url>
+ </elevation>
\ No newline at end of file
diff --git a/tests/readymap_imagery.xml b/tests/readymap_imagery.xml
new file mode 100644
index 0000000..b2220a5
--- /dev/null
+++ b/tests/readymap_imagery.xml
@@ -0,0 +1,3 @@
+<image name="readymap_imagery" driver="tms">
+        <url>http://readymap.org/readymap/tiles/1.0.0/7/</url>
+</image>
\ No newline at end of file
diff --git a/tests/readymap_include.earth b/tests/readymap_include.earth
new file mode 100644
index 0000000..3ab8b3c
--- /dev/null
+++ b/tests/readymap_include.earth
@@ -0,0 +1,12 @@
+<!--
+osgEarth Sample - xi:include.
+
+Shows how to include external XML documents to simplify your earth file.
+
+-->
+<map name="readymap.org" type="geocentric">
+    
+    <xi:include href="readymap_imagery.xml"/>
+    <xi:include href="readymap_elevation.xml"/>
+   
+</map>
diff --git a/tests/readymap_pixel_size.earth b/tests/readymap_pixel_size.earth
new file mode 100644
index 0000000..6843049
--- /dev/null
+++ b/tests/readymap_pixel_size.earth
@@ -0,0 +1,31 @@
+<!--
+osgEarth Sample - ReadyMap.ORG Server - http://readymap.org
+
+ReadyMap.ORG provides free global base map data for osgEarth developers!
+This tiled, worldwide dataset of imagery, elevation, and street map data
+is a great base map that provides global context for your own local datasets.
+It works "out of the box" with osgEarth applications.
+
+**** NOTICE ****
+YOU ARE RESPONSIBLE for abiding by the TERMS AND CONDITIONS outlined at:
+http://readymap.org
+
+-->
+<map name="readymap.org" type="geocentric">
+    
+    <options>
+        <terrain first_lod="1" tile_pixel_size="256" range_mode="PIXEL_SIZE_ON_SCREEN"/>
+    </options>
+    
+    <image name="readymap_imagery" driver="tms">
+        <url>http://readymap.org/readymap/tiles/1.0.0/7/</url>
+    </image>
+        
+    <elevation name="readymap_elevation" driver="tms">
+        <url>http://readymap.org/readymap/tiles/1.0.0/116/</url>
+    </elevation>
+    
+    <extensions>
+        <xi:include href="viewpoints.xml"/>
+    </extensions>
+</map>
diff --git a/tests/readymap_template.earth b/tests/readymap_template.earth
new file mode 100644
index 0000000..cba952b
--- /dev/null
+++ b/tests/readymap_template.earth
@@ -0,0 +1,23 @@
+<!--
+osgEarth Sample - templates
+
+Shows how to use the new template pseudoloader to run an earth file through a template preprocessor.
+
+Run with osgearth_viewer readymap_template.earth.template to invoke the psuedoloader.
+
+-->
+<map name="readymap.org" type="geocentric">
+    
+    <!-- Include imagery -->
+    {% include readymap_imagery.xml %}
+    
+    <!-- Include elevation -->
+    {% include readymap_elevation.xml %}
+
+    <viewpoints>
+        <!-- Include multiple flat lists of viewpoints -->
+        {% include boston_viewpoints.xml %}
+        {% include dc_viewpoints.xml %}
+    </viewpoints>
+
+</map>
diff --git a/tests/silverlining.earth b/tests/silverlining.earth
index de4c3bf..2a1bbe0 100644
--- a/tests/silverlining.earth
+++ b/tests/silverlining.earth
@@ -12,16 +12,14 @@ http://sundog-soft.com/sds/features/real-time-3d-clouds/
         <url>http://readymap.org/readymap/tiles/1.0.0/116/</url>
     </elevation>
 
-    <extensions>
-        <sky driver="silverlining">
-			<user></user>
-			<license_code></license_code>
-			<clouds>true</clouds>
-			<clouds_max_altitude>100000</clouds_max_altitude>
-		</sky>
-        
-        <viewpoints>
-            <viewpoint name="Clouds" heading="37.95748484316797" height="251.618257785216" lat="46.5107100574977" long="-122.1696677949447" pitch="-8.543275459971998" range="6807.567220645097"/>
-        </viewpoints>
-    </extensions>
+    <sky driver="silverlining">
+        <user>user</user>
+        <license_code>code</license_code>
+        <clouds>true</clouds>
+        <clouds_max_altitude>100000</clouds_max_altitude>
+    </sky>
+    
+    <viewpoints>
+        <viewpoint name="Clouds" heading="37.95748484316797" height="251.618257785216" lat="46.5107100574977" long="-122.1696677949447" pitch="-8.543275459971998" range="6807.567220645097"/>
+    </viewpoints>
 </map>
diff --git a/tests/simple_model.earth b/tests/simple_model.earth
index 891ad00..538bd8a 100644
--- a/tests/simple_model.earth
+++ b/tests/simple_model.earth
@@ -5,14 +5,12 @@ needs to be absolutely positioned.
 -->
 
 <map version="2">
-    <image name="mapquest_open_aerial" driver="xyz">
-        <url>http://oatile[1234].mqcdn.com/tiles/1.0.0/sat/{z}/{x}/{y}.jpg</url>
-        <profile>spherical-mercator</profile>
-        <cache_policy usage="no_cache"/>
-        <nodata_image>http://oatile3.mqcdn.com/tiles/1.0.0/sat/13/636/6210.jpg</nodata_image>
+    
+    <image name="readymap_imagery" driver="tms">
+        <url>http://readymap.org/readymap/tiles/1.0.0/7/</url>
     </image>
     
-    <model name = "cow" driver="simple">
+    <model name="model" driver="simple">
       <url>../data/red_flag.osg.100,100,100.scale</url>
       <location>-74.018 40.717 10</location>	  
     </model>
@@ -21,9 +19,7 @@ needs to be absolutely positioned.
         <terrain min_lod="12"/>
     </options>
     
-    <external>
-        <viewpoints>
-            <viewpoint name="Zoom to model" lat="40.717" long="-74.018" pitch="-60" range="6000"/>    
-        </viewpoints>
-    </external>	
+    <viewpoints>
+        <viewpoint name="Zoom to model" lat="40.717" long="-74.018" pitch="-60" range="6000"/>    
+    </viewpoints>
 </map>
diff --git a/tests/skyview1.earth b/tests/skyview1.earth
new file mode 100644
index 0000000..9d92dfb
--- /dev/null
+++ b/tests/skyview1.earth
@@ -0,0 +1,30 @@
+<!--
+osgEarth Sample
+
+Shows the skyview driver, which will flip an image source horizontally
+so that it's viewable from inside the globe, planetarium style.
+Run with osgearth_skyview skyview1.earth
+-->
+<map name="skyview" type="geocentric">
+    
+
+    <options>
+        <terrain>
+            <cluster_culling>false</cluster_culling>
+            <skirt_ratio>0.0</skirt_ratio>
+        </terrain>
+
+    </options>
+   
+    <!-- Wrap the image in the skyview driver to flip it-->
+    <image name="skyview" driver="skyview">
+	    <image name="EarthAtNight" driver="osg">
+	        <url>../data/skyview/celestial-ref.jpg</url>
+	        <profile>global-geodetic</profile>
+	    </image>      
+    </image>
+
+    
+
+
+</map>
diff --git a/tests/skyview2.earth b/tests/skyview2.earth
new file mode 100644
index 0000000..81122fd
--- /dev/null
+++ b/tests/skyview2.earth
@@ -0,0 +1,30 @@
+<!--
+osgEarth Sample
+
+Shows the skyview driver, which will flip an image source horizontally
+so that it's viewable from inside the globe, planetarium style.
+Run with osgearth_skyview skyview1.earth
+-->
+<map name="skyview" type="geocentric">
+    
+
+    <options>
+        <terrain>
+            <cluster_culling>false</cluster_culling>
+            <skirt_ratio>0.0</skirt_ratio>
+        </terrain>
+
+    </options>
+   
+    <!-- Wrap the image in the skyview driver to flip it-->
+    <image name="skyview" driver="skyview">
+	    <image name="EarthAtNight" driver="osg">
+	        <url>../data/skyview/irasAllsky-100um.jpg</url>
+	        <profile>global-geodetic</profile>
+	    </image>      
+    </image>
+
+    
+
+
+</map>
diff --git a/tests/splat-edit.bat b/tests/splat-edit.bat
index 3f42098..220e411 100644
--- a/tests/splat-edit.bat
+++ b/tests/splat-edit.bat
@@ -1,8 +1,6 @@
 setlocal
 set OSGEARTH_SPLAT_EDIT=1
-osgearth_viewer splat-test.earth ^
-	--ico ^
-	--logdepth ^
+osgearth_viewer splat.earth ^
 	--sky ^
 	--uniform oe_splat_detailRange 100000 0 ^
 	--uniform oe_splat_warp 0 0.02 ^
diff --git a/tests/splat-gpunoise.bat b/tests/splat-gpunoise.bat
index 9944b10..4be402d 100644
--- a/tests/splat-gpunoise.bat
+++ b/tests/splat-gpunoise.bat
@@ -1,7 +1,7 @@
 setlocal
 set OSGEARTH_SPLAT_EDIT=1
 set OSGEARTH_SPLAT_GPU_NOISE=1
-osgearth_viewer splat-test.earth ^
+osgearth_viewer splat.earth ^
 	--ico ^
 	--logdepth ^
 	--sky ^
diff --git a/tests/splat-ranges.earth b/tests/splat-ranges.earth
new file mode 100644
index 0000000..a652eaa
--- /dev/null
+++ b/tests/splat-ranges.earth
@@ -0,0 +1,55 @@
+<!--
+|  Procedural terrain splatting.
+|  Run with splat.bat, (or splat-edit.bat for tweakery)
+-->
+
+<map>
+        
+    <options>
+        <terrain driver="rex" 
+                 tile_size="17"
+                 high_resolution_first="true" 
+                 merges_per_frame="50"
+                 skirt_ratio="0.01">
+        </terrain>
+    </options>
+    
+    <elevation name="readymap_elevation" driver="tms" enabled="true">
+        <url>http://readymap.org/readymap/tiles/1.0.0/116/</url>
+    </elevation>
+     
+    <image name="CLASSMAP" driver="landuse" shared="true" visible="false" coverage="true" max_data_level="15">
+        <base_lod>12</base_lod>
+        <tile_size>256</tile_size>
+        <cache_policy usage="none"/>
+        <images>
+            <image name="ESA" driver="gdal" coverage="true">
+                <url>H:/data/esa/GLOBCOVER_L4_200901_200912_V2.3_Ant_tiled.tif</url>
+                <warp>0.01</warp>
+            </image>
+        </images>
+    </image>
+
+    <extensions>
+   
+        <splat>        
+            <coverage>
+                <layer> CLASSMAP </layer>
+                <legend>../data/splat/GLOBCOVER_legend.xml</legend>
+            </coverage>
+            
+            <zones>
+                <zone name="default" doc="Default Climate Zone">            
+                    <surface>
+                        <catalog>../data/splat/splat_catalog_rangetest.xml</catalog>
+                    </surface>
+                </zone>                
+            </zones>
+            
+        </splat>
+            
+        <xi:include href="viewpoints.xml"/>
+        
+    </extensions>
+
+</map>
diff --git a/tests/splat-server.earth b/tests/splat-server.earth
new file mode 100644
index 0000000..743d1da
--- /dev/null
+++ b/tests/splat-server.earth
@@ -0,0 +1,105 @@
+<!--
+|  Test for osgearth_server, generating tiles using the GPU in osgEarth and serving them out as TMS tiles!
+|  Run with osgearth_server.
+-->
+
+<map type="flat">
+        
+    <options>
+        <profile>spherical-mercator</profile>
+   </options>
+   
+    <elevation name="readymap_elevation" driver="tms" enabled="true">
+        <url>http://readymap.org/readymap/tiles/1.0.0/116/</url>
+    </elevation>
+     
+    <image name="CLASSMAP" driver="landuse" shared="true" visible="false" coverage="true" max_data_level="15">
+        <base_lod>12</base_lod>
+        <tile_size>256</tile_size>
+        <cache_policy usage="none"/>
+        <images>
+            <image name="ESA" driver="gdal" coverage="true">
+                <url>d:/geodata/splatting/GLOBCOVER_L4_200901_200912_V2.3_Ant_tiled.tif</url>
+                <warp>0.01</warp>
+            </image>
+        </images>
+    </image>
+
+    <model name="buildings" driver="feature_geom">
+             
+        <features name="buildings" driver="ogr">
+            <url>../data/boston_buildings_utm19.shp</url>
+            <build_spatial_index>true</build_spatial_index>
+        </features>
+        
+        <layout>
+            <tile_size_factor>45</tile_size_factor>
+            <level name="default" max_range="20000">
+                <selector class="buildings"/>
+            </level>
+        </layout>
+        
+        <styles>            
+            <library name="us_resources">
+                <url>../data/resources/textures_us/catalog.xml</url>
+            </library>
+            
+            <style type="text/css">
+                buildings {
+                    extrusion-height:      3.5 * max([story_ht_], 1);
+                    extrusion-flatten:     true;
+                    extrusion-wall-style:  building-wall;
+                    extrusion-roof-style:  building-rooftop;
+                    altitude-clamping:     none;
+                }            
+                building-wall {
+                    skin-library:     us_resources;
+                    skin-tags:        building;
+                    skin-random-seed: 1;
+                    fill:             #ffffff;
+                }
+                building-rooftop {
+                    skin-library:     us_resources;
+                    skin-tags:        rooftop;
+                    skin-tiled:       true;
+                    skin-random-seed: 1;
+                    fill:             #ffffff;
+                }
+            </style>
+            
+                        
+            <!--Exclude certain buildings from being rendered b/c they will be replaced with geospecific buildings -->
+            <selector class="buildings">
+                <query>
+                    <expr><![CDATA[ OBJECTID_1 <> 91506 and OBJECTID_1 <> 12921 and OBJECTID_1 <> 11460 and OBJECTID_1 <> 11474 and OBJECTID_1 <> 11471 and OBJECTID_1 <> 11439 and OBJECTID_1 <> 11432 and  OBJECTID_1 <> 91499 and OBJECTID_1 <> 10878 ]]> </expr>
+                </query>
+            </selector>         
+            
+        </styles>
+
+        <lighting>true</lighting>        
+    </model>
+
+    <extensions>
+   
+        <splat>        
+            <coverage>
+                <layer> CLASSMAP </layer>
+                <legend>../data/splat/GLOBCOVER_legend.xml</legend>
+            </coverage>
+            
+            <zones>
+                <zone name="default" doc="Default Climate Zone">            
+                    <surface>
+                        <catalog>../data/splat/splat_catalog.xml</catalog>
+                    </surface>
+                </zone>                
+            </zones>
+            
+        </splat>
+            
+        <xi:include href="viewpoints.xml"/>
+        
+    </extensions>
+
+</map>
diff --git a/tests/splat-test.earth b/tests/splat-test.earth
deleted file mode 100644
index c4ca0ef..0000000
--- a/tests/splat-test.earth
+++ /dev/null
@@ -1,57 +0,0 @@
-<!--
-|  Texture splatting test.
-|
-|  Run with splat.bat, (or splat-edit.bat for tweakery)
--->
-
-<map>
-        
-    <options>
-        <terrain max_lod="18" min_normal_map_lod="7"/>
-    </options>
-    
-    <elevation name="readymap_elevation" driver="tms" enabled="true">
-        <url>http://readymap.org/readymap/tiles/1.0.0/116/</url>
-    </elevation>
-    
-    <elevation driver="gdal" enabled="false">
-        <url>H:/data/ned/ned19_n47x00_w121x75_wa_mounttrainier_2008/ned19_n47x00_w121x75_wa_mounttrainier_2008.tif</url>
-    </elevation>
-    
-    <image name="GLOBCOVER" driver="gdal" shared="true" visible="false" coverage="true" enabled="true">
-        <url>H:/data/ESA/GLOBCOVER_L4_200901_200912_V2.3_Ant_tiled.tif</url>
-        <cache_policy usage="none"/>
-    </image>
-
-    <extensions>
-        
-        <normalmap/>    
-
-        <bumpmap>
-            <image>../data/rock_hard.jpg</image>
-            <octaves>32</octaves>
-            <intensity>1.5</intensity>
-        </bumpmap>
-    
-        <splat>
-            <coverage>GLOBCOVER</coverage>
-            <legend>../data/splat/GLOBCOVER_legend.xml</legend>
-            <catalog>../data/splat/splat_catalog.xml</catalog>
-        </splat>
-        
-        <viewpoints>
-            <viewpoint name="Wash St. 430K" heading="-1.002577141807595" height="3694.875054217875" lat="46.85393268075167" long="-121.7764141794478" pitch="-89.85464953482169" range="426454.3850159062"/>
-            <viewpoint name="Mt R. Nadir 30K" heading="0.5013023037097585" height="4101.627114404924" lat="46.85909894548915" long="-121.7598368518208" pitch="-89.43249895879129" range="29029.34246828893"/>
-            <viewpoint name="Mt R. Oblique 30K" heading="17.33521725357022" height="2462.60273069609" lat="46.82181702111031" long="-121.7814936386096" pitch="-21.29241356548601" range="23926.75258864516"/>
-            <viewpoint name="Mt R. Closeup" heading="-109.6842970297122" height="3843.486737414263" lat="46.85528453766688" long="-121.7455004166102" pitch="-4.617466338845979" range="951.4780720092711"/>
-            <viewpoint name="Mt R. Trees" heading="-98.36122712710565" height="1639.304918398149" lat="46.78673277044066" long="-121.743286318636" pitch="-10.85365380742088" range="257.5853045645545"/>
-            <viewpoint name="Nepal" heading="-72.70835146844568" height="6334.845537136309" lat="27.94213038800919" long="86.9936567556778" pitch="-18.63803872963365" range="13611.24948464565"/>
-            <viewpoint name="Nepal NF" heading="-49.14546953546358" height="6334.332569343038" lat="27.9421778947837" long="86.9935949004298" pitch="-3.643325527310435" range="13302.81192964212"/>
-            <viewpoint name="Matterhorn" heading="-1.429462844200832" height="2282.858508689329" lat="45.95106319557" long="7.642741711675961" pitch="-25.12269405854052" range="26690.10606054494"/>
-        </viewpoints>
-        
-        <sky driver="simple" hours="18.6" atmospheric_lighting="true"/>
-        
-    </extensions>
-
-</map>
diff --git a/tests/splat-with-imagery.earth b/tests/splat-with-imagery.earth
deleted file mode 100644
index cf8cdbb..0000000
--- a/tests/splat-with-imagery.earth
+++ /dev/null
@@ -1,52 +0,0 @@
-<!--
-|  Combining a normal image layer with the Splat effect.
-|  You can tweak the distances by using command-line uniforms:
-|
-|    --uniform oe_layer_minRange <min> <max>
-|    --uniform oe_layer_maxRange <min> <max>
-|    --uniform oe_layer_attenuationRange <range>
--->
-
-<map>
-
-    <options>
-        <terrain attenuation_distance="40000"/>
-    </options>
-    
-    <image name="readymap_imagery" driver="tms" min_range="65000">
-        <url>http://readymap.org/readymap/tiles/1.0.0/7/</url>
-    </image>
-    
-    <elevation name="readymap_elevation" driver="tms" enabled="true">
-        <url>http://readymap.org/readymap/tiles/1.0.0/116/</url>
-    </elevation>
-    
-    <image name="GLOBCOVER" driver="gdal" shared="true" visible="false" coverage="true" enabled="true">
-        <url>H:/data/ESA/GLOBCOVER_L4_200901_200912_V2.3_Ant_tiled.tif</url>
-        <cache_policy usage="none"/>
-    </image>
-
-    <extensions>
-        
-        <normalmap/>  
-    
-        <splat>
-            <coverage>GLOBCOVER</coverage>
-            <legend>../data/splat/GLOBCOVER_legend.xml</legend>
-            <catalog>../data/splat/splat_catalog.xml</catalog>
-        </splat>
-        
-        <viewpoints>
-            <viewpoint name="Wash St. 430K" heading="-1.002577141807595" height="3694.875054217875" lat="46.85393268075167" long="-121.7764141794478" pitch="-89.85464953482169" range="426454.3850159062"/>
-            <viewpoint name="Mt R. Nadir 30K" heading="0.5013023037097585" height="4101.627114404924" lat="46.85909894548915" long="-121.7598368518208" pitch="-89.43249895879129" range="29029.34246828893"/>
-            <viewpoint name="Mt R. Oblique 30K" heading="17.33521725357022" height="2462.60273069609" lat="46.82181702111031" long="-121.7814936386096" pitch="-21.29241356548601" range="23926.75258864516"/>
-            <viewpoint name="Mt R. Closeup" heading="-109.6842970297122" height="3843.486737414263" lat="46.85528453766688" long="-121.7455004166102" pitch="-4.617466338845979" range="951.4780720092711"/>
-            <viewpoint name="Mt R. Trees" heading="-98.36122712710565" height="1639.304918398149" lat="46.78673277044066" long="-121.743286318636" pitch="-10.85365380742088" range="257.5853045645545"/>
-            <viewpoint name="Nepal" heading="-72.70835146844568" height="6334.845537136309" lat="27.94213038800919" long="86.9936567556778" pitch="-18.63803872963365" range="13611.24948464565"/>
-            <viewpoint name="Nepal NF" heading="-49.14546953546358" height="6334.332569343038" lat="27.9421778947837" long="86.9935949004298" pitch="-3.643325527310435" range="13302.81192964212"/>
-            <viewpoint name="Matterhorn" heading="-1.429462844200832" height="2282.858508689329" lat="45.95106319557" long="7.642741711675961" pitch="-25.12269405854052" range="26690.10606054494"/>
-        </viewpoints>
-        
-    </extensions>
-
-</map>
diff --git a/tests/splat-with-vectors.earth b/tests/splat-with-vectors.earth
new file mode 100644
index 0000000..f821e74
--- /dev/null
+++ b/tests/splat-with-vectors.earth
@@ -0,0 +1,109 @@
+<!--
+|  Texture splatting test.
+|
+|  Run with splat.bat, (or splat-edit.bat for tweakery)
+-->
+
+<map>
+        
+    <options>
+        <terrain driver="rex" skirt_ratio="0" normal_maps="true"/>
+    </options>
+    
+    <elevation name="readymap_elevation" driver="tms" enabled="true">
+        <url>http://readymap.org/readymap/tiles/1.0.0/116/</url>
+    </elevation>
+        
+    <image name="CLASSMAP" driver="landuse" shared="true" visible="false" coverage="true">
+        <bits>16</bits>
+        <warp>0.01</warp>
+        <base_lod>12</base_lod>
+        
+        <images>
+            <image name="ESA" driver="gdal" coverage="true">
+                <url>H:/data/ESA/GLOBCOVER_L4_200901_200912_V2.3_Ant_tiled.tif</url>
+                <cache_policy usage="no_cache"/>
+            </image>
+            
+            <image name="Lakes" driver="agglite" coverage="true">
+                <warp>0</warp>
+                <features driver="ogr">
+                    <url>H:/data/naturalearth/vector-10m/ne_10m_lakes.shp</url>
+                </features>
+                <styles>
+                    <style type="text/css">
+                        default {
+                            coverage-value: 230;
+                        }
+                    </style>
+                </styles>
+                <cache_policy usage="no_cache"/>
+            </image>
+                    
+            <image name="Boston streets" driver="agglite" coverage="true" min_level="10" max_data_level="17">
+                <warp>0</warp>
+                <features driver="ogr" build_spatial_index="true">
+                    <url>../data/boston-scl-utm19n-meters.shp</url>
+                    <filters>
+                        <buffer distance="5"/>
+                    </filters>
+                </features>                
+                <styles>
+                    <style type="text/css">
+                        default {
+                            coverage-value: 900;
+                        }
+                    </style>
+                </styles>   
+                <cache_policy usage="no_cache"/>     
+            </image>
+            
+        </images>
+        
+        <shared_sampler> landUseTex       </shared_sampler>
+        <shared_matrix>  landUseTexMatrix </shared_matrix>
+        
+        <cache_policy usage="no_cache"></cache_policy>
+    </image>
+    
+    
+    <extensions>
+    
+        <splat>        
+            <coverage>
+                <layer> CLASSMAP </layer>
+                <legend>../data/splat/GLOBCOVER_legend.xml</legend>
+            </coverage>            
+            <zones>
+                <zone name="default" doc="Default Climate Zone">            
+                    <surface>
+                        <catalog>../data/splat/splat_catalog.xml</catalog>
+                    </surface>
+                </zone>                
+            </zones>            
+        </splat>
+        
+        <viewpoints>
+            <viewpoint name="Roads">
+                <heading>-1.71887</heading>
+                <pitch>-15.3643</pitch>
+                <range>2429.2m</range>
+                <long>-71.06130588150768</long>
+                <lat>42.35594985954756</lat>
+                <height>31.36476541217417</height>
+                <srs>+proj=longlat +ellps=WGS84 +towgs84=0,0,0,0,0,0,0 +no_defs </srs>
+            </viewpoint>
+            <viewpoint name="Lake">
+                <heading>-9.40528</heading>
+                <pitch>-34.7212</pitch>
+                <range>453747m</range>
+                <long>32.78247923080883</long>
+                <lat>-1.680124158232579</lat>
+                <height>1133.724704638124</height>
+                <srs>+proj=longlat +ellps=WGS84 +towgs84=0,0,0,0,0,0,0 +no_defs </srs>
+            </viewpoint>
+        </viewpoints>
+        
+    </extensions>
+
+</map>
diff --git a/tests/splat.bat b/tests/splat.bat
index e82fa4c..27d2112 100644
--- a/tests/splat.bat
+++ b/tests/splat.bat
@@ -1,7 +1,14 @@
-osgearth_viewer splat-test.earth ^
-	--ico ^
-	--uniform oe_splat_warp 0 0.02 ^
-	--uniform oe_splat_blur 1 4 ^
-	--uniform oe_splat_useBilinear 1 -1 ^
-	%*
-	
\ No newline at end of file
+ at echo off
+setlocal
+osgearth_viewer splat.earth ^
+    --sky ^
+    --logdepth ^
+    --samples 4 ^
+    --uniform oe_landcover_density 1 7 ^
+    --uniform oe_landcover_fill 1 0 ^
+    --uniform oe_landcover_brightness 1 3 ^
+    --uniform oe_landcover_contrast 0 1 ^
+    --uniform oe_landcover_maxDistance 7000 200 ^
+    --uniform oe_landcover_windFactor 0 3 ^
+    %*    
+endlocal
\ No newline at end of file
diff --git a/tests/splat.earth b/tests/splat.earth
new file mode 100644
index 0000000..6b94488
--- /dev/null
+++ b/tests/splat.earth
@@ -0,0 +1,78 @@
+<!--
+|  Procedural terrain splatting.
+|  Run with splat.bat, (or splat-edit.bat for tweakery)
+-->
+
+<map>
+        
+    <options>
+        <terrain driver="rex" 
+                 tile_size="17"
+                 high_resolution_first="true" 
+                 merges_per_frame="25">
+        </terrain>
+    </options>
+    
+    <elevation name="readymap_elevation" driver="tms" enabled="true">
+        <url>http://readymap.org/readymap/tiles/1.0.0/116/</url>
+    </elevation>
+     
+    <image name="CLASSMAP" driver="landuse" shared="true" visible="false" coverage="true" max_data_level="15">
+        <base_lod>12</base_lod>
+        <tile_size>256</tile_size>
+        <cache_policy usage="none"/>
+        <images>
+            <image name="ESA" driver="gdal" coverage="true">
+                <url>H:/data/esa/GLOBCOVER_L4_200901_200912_V2.3_Ant_tiled.tif</url>
+                <warp>0.01</warp>
+            </image>
+        </images>
+    </image>
+
+    <bumpmap>
+        <image>../data/rock_hard.jpg</image>
+        <octaves>8</octaves>
+        <intensity>2.2</intensity>
+    </bumpmap>
+   
+    <splat>        
+        <coverage>
+            <layer> CLASSMAP </layer>
+            <legend>../data/splat/GLOBCOVER_legend.xml</legend>
+        </coverage>
+        
+        <zones>
+            <zone name="default" doc="Default Climate Zone">            
+                <surface>
+                    <catalog>../data/splat/splat_catalog.xml</catalog>
+                </surface>
+        
+                <land_cover>
+                    <layers>
+                        <layer name="trees" lod="13" max_distance="6400" density="3.4" fill="0.45" brightness="2.0" contrast="0.5" cast_shadows="true">
+                            <biomes>
+                                <biome classes="forest forest1 forest2 forest3 forest4">
+                                    <billboard url="../data/splat/cypress.png" width="12.0" height="14.0"/>
+                                    <billboard url="../data/splat/pine.png"    width="16.0" height="22.0" />
+                                    <billboard url="../data/splat/pine2.png"   width="15.0" height="18.0"/>
+                                </biome>
+                            </biomes>
+                        </layer>
+                    
+                        <layer name="grass" lod="19" max_distance="150" density="3.8" fill="0.50" wind="0.15">
+                            <biomes>
+                                <biome name="Grass" classes="grassland grassland2 forest forest1 forest2 forest3 forest4">
+                                    <billboard url="../data/splat/grass1.png" width="0.85" height="0.4"/>
+                                </biome>
+                            </biomes>
+                        </layer>
+                    </layers>                    
+                </land_cover>
+            </zone>                
+        </zones>
+        
+    </splat>
+            
+    <xi:include href="viewpoints.xml"/>
+
+</map>
diff --git a/tests/stamen_watercolor.earth b/tests/stamen_watercolor.earth
index 525d489..5ec4aa2 100644
--- a/tests/stamen_watercolor.earth
+++ b/tests/stamen_watercolor.earth
@@ -9,7 +9,5 @@
         <url>http://readymap.org/readymap/tiles/1.0.0/9/</url>
     </elevation>
 
-    <options>
-        <lighting>false</lighting>
-    </options>
+    <lod_blending/>
 </map>
\ No newline at end of file
diff --git a/tests/dc_state_plane.earth b/tests/state_plane.earth
similarity index 100%
rename from tests/dc_state_plane.earth
rename to tests/state_plane.earth
diff --git a/tests/tess-coastlines.earth b/tests/tess-coastlines.earth
new file mode 100644
index 0000000..bac9591
--- /dev/null
+++ b/tests/tess-coastlines.earth
@@ -0,0 +1,157 @@
+<!--
+osgEarth Sample - OpenGL Tessellation Shaders
+
+This example injects a Tessellation Control Shader (TCS) and 
+Tessellation Evaluation Shader (TES) into the terrain rendering
+pipeline. This is EXPERIMENTAL so please be advised of the 
+following caveats:
+
+ * Terrain skirts will not render. Set "skirt_ratio" to zero or you
+   will get GL errors.
+ * Set gpu_tessellation="true" on the terrain options.
+ * EarthManipulator doesn't like GL_PATCHES (yet). Use the viewpoints.
+  
+Press 'w' for wireframe mode to see the tessellation!
+-->
+
+<map name="Coastlines" type="geocentric">
+    
+    <options>         
+        <terrain driver="mp" first_lod="1" skirt_ratio="0" tile_size="5" gpu_tessellation="true"/>
+    </options>
+    
+    <image name="readymap_imagery" driver="tms">
+        <url>http://readymap.org/readymap/tiles/1.0.0/7/</url>
+    </image>
+        
+    <elevation name="readymap_elevation" driver="tms">
+        <url>http://readymap.org/readymap/tiles/1.0.0/116/</url>
+    </elevation>
+    
+    <!--
+     | Rasterized feature layer that we use to mask the tessellation.
+     | The max_data_level keeps the mask lo-res enough what we don't get
+     | artifacts at high LODs.
+     |
+     | Data is from NaturalEarth (www.naturalearthdata.com)
+     -->
+    <image name="Coastlines" driver="agglite" shared="true" visible="false" max_data_level="7">
+        <features driver="ogr">
+            <url>../data/ne_10m_coastline.zip/ne_10m_coastline.shp</url>
+        </features>
+        <styles>
+            <style type="text/css">
+                default {
+                    stroke:       #ffbf007f;
+                    stroke-width: 2.5km;
+                }
+            </style>
+        </styles>
+        <cache_policy usage="no_cache"/>
+        <shared_sampler>coastlines</shared_sampler>
+        <shared_matrix>coastlinesMat</shared_matrix>
+    </image>
+
+    <terrainshader>
+        <code><![CDATA[
+        
+            #version 430 compatibility
+            #pragma vp_entryPoint "configureTess"
+            #pragma vp_location   "tess_control"
+            
+            // Access to the rasterized mask layer. In the future these
+            // will be programmable..
+            uniform sampler2D coastlines;
+            uniform mat4      coastlinesMat;
+
+            // General tile coords [0..1]
+            in vec4 oe_layer_tilec;
+
+            layout(vertices=3) out;
+            
+            // Internal helper functions:
+            void VP_LoadVertex(in int);
+            
+            void configureTess()
+            {
+                #define id gl_InvocationID
+                // Only required for the first invocation:
+                if ( id == 0 )
+                {                         
+                    vec3 v;
+                    
+                    // Sample the mask texture at all 3 verts of the triangle:
+                    for(int i=0; i<3; ++i)
+                    {
+                        VP_LoadVertex(i);
+                        v[i] = texture(coastlines, (coastlinesMat*oe_layer_tilec).st).a;
+                    }
+                    
+                    // Average the weights for each edge level:
+                    gl_TessLevelOuter[0] = 1.0 + 5.0*mix(v[1], v[2], 0.5);
+                    gl_TessLevelOuter[1] = 1.0 + 5.0*mix(v[2], v[0], 0.5);
+                    gl_TessLevelOuter[2] = 1.0 + 5.0*mix(v[0], v[1], 0.5);
+                    
+                    // Average all weights for the inner ring count:
+                    gl_TessLevelInner[0] = 1.0 + 4.0*(v.x+v.y+v.z)/3.0;
+                    
+                    // Reset the loaded vertex to the current invocation.
+                    VP_LoadVertex(0);
+                }
+            }
+            
+        ]]></code>
+    </terrainshader>
+    
+    <terrainshader>
+        <code><![CDATA[            
+            #version 410
+            #pragma vp_name       "Terrain TES Shader"
+            #pragma vp_entryPoint "generateVertex"
+            #pragma vp_location   "tess_eval"
+
+            // osgEarth terrain is always CCW winding
+            layout(triangles, equal_spacing, ccw) in;
+
+            // Internal helpers:
+            void VP_Interpolate3();
+            void VP_EmitVertex();
+            
+            // User must supply interpolators for all the base types:
+            
+            float VP_Interpolate3(float a, float b, float c) {
+                return dot(gl_TessCoord.xyz, vec3(a,b,c));
+            }
+            
+            vec2 VP_Interpolate3(vec2 a, vec2 b, vec2 c) {
+                return vec2(dot(gl_TessCoord.xyz, vec3(a.x,b.x,c.x)),
+                            dot(gl_TessCoord.xyz, vec3(a.y,b.y,c.y)));
+            }
+
+            vec3 VP_Interpolate3(vec3 a, vec3 b, vec3 c) {
+                return vec3(dot(gl_TessCoord.xyz, vec3(a.x,b.x,c.x)),
+                            dot(gl_TessCoord.xyz, vec3(a.y,b.y,c.y)),
+                            dot(gl_TessCoord.xyz, vec3(a.z,b.z,c.z)));
+            }
+
+            vec4 VP_Interpolate3(vec4 a, vec4 b, vec4 c) {
+                return vec4(dot(gl_TessCoord.xyz, vec3(a.x,b.x,c.x)),
+                            dot(gl_TessCoord.xyz, vec3(a.y,b.y,c.y)),
+                            dot(gl_TessCoord.xyz, vec3(a.z,b.z,c.z)),
+                            dot(gl_TessCoord.xyz, vec3(a.w,b.w,c.w)));
+            }
+            
+            // simplest possible pass-though:
+            void generateVertex()
+            {                    
+                VP_Interpolate3();
+                VP_EmitVertex();
+            }
+        ]]></code>
+    </terrainshader>
+    
+    <viewpoints>
+        <viewpoint name="San Francisco" heading="8.806974516644791" height="4465.397310772911" lat="37.55814749233749" long="-122.334535784141" pitch="-34.79540299384382" range="78142.53643278375" srs="+proj=longlat +ellps=WGS84 +towgs84=0,0,0,0,0,0,0 +no_defs " />
+    </viewpoints>
+        
+</map>
diff --git a/tests/tess-masking.earth b/tests/tess-masking.earth
new file mode 100644
index 0000000..2c64ba1
--- /dev/null
+++ b/tests/tess-masking.earth
@@ -0,0 +1,176 @@
+<!--
+osgEarth Sample - OpenGL Tessellation Shaders
+
+This example injects a Tessellation Control Shader (TCS) and 
+Tessellation Evaluation Shader (TES) into the terrain rendering
+pipeline. This is EXPERIMENTAL so please be advised of the 
+following caveats:
+
+ * Terrain skirts will not render. Set "skirt_ratio" to zero or you
+   will get GL errors.
+ * Set gpu_tessellation="true" on the terrain options.
+ * EarthManipulator doesn't like GL_PATCHES (yet). Use the viewpoints.
+  
+Press 'w' for wireframe mode to see the tessellation!
+-->
+
+<map name="readymap.org" type="geocentric">
+    
+    <options>         
+        <terrain driver="rex" first_lod="1" skirt_ratio="0" gpu_tessellation="true"/>
+    </options>
+    
+    <image name="readymap_imagery" driver="tms">
+        <url>http://readymap.org/readymap/tiles/1.0.0/7/</url>
+    </image>
+        
+    <elevation name="readymap_elevation" driver="tms">
+        <url>http://readymap.org/readymap/tiles/1.0.0/116/</url>
+    </elevation>    
+	
+    <image name="pavement" driver="agglite" enabled="true" shared="true" visible="false" min_level="7" max_data_level="10">  
+        <features name="world" driver="ogr">
+            <url>H:/data/xplane/aerodrome/APTBoundary_all.shp</url>
+            <build_spatial_index>true</build_spatial_index>
+        </features> 
+		<layout>
+			<level max_range="50000" class="default"/>
+		</layout>
+        <styles>
+            <style type="text/css">
+                default {
+				   fill: #ffffffff;
+                }            
+            </style>
+        </styles>    
+        <shared_sampler>maskTex</shared_sampler>
+        <shared_matrix>maskMatrix</shared_matrix>        
+    </image>	
+    
+    <extensions>
+    
+        <terrainshader>
+            <code><![CDATA[
+            
+                #version 430 compatibility
+                #pragma vp_entryPoint "configureTess"
+                #pragma vp_location   "tess_control"
+                
+                // Access to the rasterized mask layer. In the future these will be programmable..
+                uniform sampler2D maskTex;
+                uniform mat4      maskMatrix;
+
+                // General tile coords [0..1]
+                in vec4 oe_layer_tilec;
+                
+                uniform vec4 oe_tile_key;
+
+                layout(vertices=3) out;
+                
+                uniform float level = 5.0;
+                
+                // Internal helper functions:
+                void VP_LoadVertex(in int);
+                
+                void configureTess()
+                {                       
+                    // Only required for the first invocation:
+                    if ( gl_InvocationID == 0 )
+                    {                                    
+                        // Sample the mask texture at all 3 verts of the triangle:     
+                        vec3 v = vec3(0);
+
+                        if ( oe_tile_key.z >= 8 )
+                        {
+                            for(int i=0; i<3; ++i)
+                            {
+                                VP_LoadVertex(i);
+                                v[i] = texture(maskTex, (maskMatrix*oe_layer_tilec).st).a;
+                                v[i] = 1.0 - 2.0*abs(v[i]-0.5); // remap to [0..1] where 0 = in/out, 1 = on the line.
+                            }
+                        }
+                        
+                        // Average the weights for each edge level:
+                        gl_TessLevelOuter[0] = 1.0 + level*mix(v[1], v[2], 0.5);
+                        gl_TessLevelOuter[1] = 1.0 + level*mix(v[2], v[0], 0.5);
+                        gl_TessLevelOuter[2] = 1.0 + level*mix(v[0], v[1], 0.5);
+                        
+                        // Average all weights for the inner ring count:
+                        gl_TessLevelInner[0] = 1.0 + (level-1.0)*(v.x+v.y+v.z)/3.0;
+                            
+                        // Reset the loaded vertex to the current invocation.
+                        VP_LoadVertex(0);
+                    }
+                }
+                
+            ]]></code>
+        </terrainshader>
+        
+        <terrainshader>
+            <code><![CDATA[            
+                #version 410
+                #pragma vp_name       "Terrain TES Shader"
+                #pragma vp_entryPoint "generateVertex"
+                #pragma vp_location   "tess_eval"
+                
+                uniform sampler2D oe_layer_2_tex;
+                uniform mat4      oe_layer_2_texMatrix;
+                in vec4 oe_layer_tilec;
+                in vec4 vp_Vertex;
+                in vec3 vp_Normal;
+
+                // osgEarth terrain is always CCW winding
+                layout(triangles, equal_spacing, ccw) in;
+
+                // Internal helpers:
+                void VP_Interpolate3();
+                void VP_EmitVertex();
+                
+                // User must supply interpolators for all the base types:
+                
+                float VP_Interpolate3(float a, float b, float c) {
+                    return dot(gl_TessCoord.xyz, vec3(a,b,c));
+                }
+                
+                vec2 VP_Interpolate3(vec2 a, vec2 b, vec2 c) {
+                    return vec2(dot(gl_TessCoord.xyz, vec3(a.x,b.x,c.x)),
+                                dot(gl_TessCoord.xyz, vec3(a.y,b.y,c.y)));
+                }
+
+                vec3 VP_Interpolate3(vec3 a, vec3 b, vec3 c) {
+                    return vec3(dot(gl_TessCoord.xyz, vec3(a.x,b.x,c.x)),
+                                dot(gl_TessCoord.xyz, vec3(a.y,b.y,c.y)),
+                                dot(gl_TessCoord.xyz, vec3(a.z,b.z,c.z)));
+                }
+
+                vec4 VP_Interpolate3(vec4 a, vec4 b, vec4 c) {
+                    return vec4(dot(gl_TessCoord.xyz, vec3(a.x,b.x,c.x)),
+                                dot(gl_TessCoord.xyz, vec3(a.y,b.y,c.y)),
+                                dot(gl_TessCoord.xyz, vec3(a.z,b.z,c.z)),
+                                dot(gl_TessCoord.xyz, vec3(a.w,b.w,c.w)));
+                }
+                
+                uniform float offset = -100.0;
+                
+                // simplest possible pass-though:
+                void generateVertex()
+                {                    
+                    VP_Interpolate3();
+                    
+                    float mask = texture(oe_layer_2_tex, (oe_layer_2_texMatrix*oe_layer_tilec).st).a;
+                    vp_Normal = normalize(vp_Normal);
+                    vp_Vertex.xyz += vp_Normal * offset * mask;
+                    
+                    VP_EmitVertex();
+                }
+            ]]></code>
+        </terrainshader>
+        
+        <viewpoints>
+            <viewpoint name="San Francisco" heading="8.806974516644791" height="4465.397310772911" lat="37.55814749233749" long="-122.334535784141" pitch="-34.79540299384382" range="78142.53643278375" srs="+proj=longlat +ellps=WGS84 +towgs84=0,0,0,0,0,0,0 +no_defs " />
+            <viewpoint name="SFO" heading="27.57985140028968" height="4465.588079094887" lat="37.56462223501358" long="-122.4153260104297" pitch="-31.6655000582341" range="72.45169535764561"/>
+            <viewpoint name="BOS" heading="-3.005093201136807" height="10.50455343350768" lat="42.3626762635888" long="-71.01223797197133" pitch="-46.98927698631228" range="8966.122488728281"/>
+        </viewpoints>
+        
+    </extensions>
+</map>
diff --git a/tests/tess-terrain.earth b/tests/tess-terrain.earth
new file mode 100644
index 0000000..556239d
--- /dev/null
+++ b/tests/tess-terrain.earth
@@ -0,0 +1,146 @@
+<!--
+osgEarth Sample - OpenGL Tessellation Shaders
+
+This example injects a Tessellation Control Shader (TCS) and 
+Tessellation Evaluation Shader (TES) into the terrain rendering
+pipeline. This is EXPERIMENTAL so please be advised of the 
+following caveats:
+
+ * Terrain skirts will not render. Set "skirt_ratio" to zero or you
+   will get GL errors.
+ * Set gpu_tessellation="true" on the terrain options.
+ * EarthManipulator doesn't like GL_PATCHES (yet). Use the viewpoints.
+  
+Press 'w' for wireframe mode to see the tessellation!
+-->
+
+<map name="readymap.org" type="geocentric">
+    
+    <options>        
+        <terrain driver="mp" gpu_tessellation="true" min_lod="25" tile_size="9" skirt_ratio="0"/>
+    </options>
+    
+    <image name="readymap_imagery" driver="tms">
+        <url>http://readymap.org/readymap/tiles/1.0.0/7/</url>
+    </image>
+    
+    <elevation name="readymap_elevation" driver="tms">
+        <url>http://readymap.org/readymap/tiles/1.0.0/116/</url>
+    </elevation>
+    
+    <extensions>
+    
+        <terrainshader>
+            <code><![CDATA[
+            
+                #version 400 compatibility
+                #pragma vp_entryPoint "configureTess"
+                #pragma vp_location   "tess_control"
+
+                layout(vertices = 3) out;
+                
+                uniform float pixelsPerEdge = 7.5;
+                uniform vec2  viewportSize  = vec2(1024,1024);
+                                
+                // convert model position to viewport coordinates.
+                vec2 toPixels(in vec4 pos)
+                {    
+                    vec4 clip = gl_ModelViewProjectionMatrix * pos;
+                    return (clip.xy/clip.w) * (viewportSize*0.5);
+                }
+                
+                // calculate a tessellation level based on the maximum edge length uniform.
+                float tessLevel(in vec2 v0, in vec2 v1)
+                {
+                    return clamp(distance(v0,v1)/pixelsPerEdge, 1.0, 128.0);
+                }
+                
+                void configureTess()
+                {
+                    // Only required for the first invocation:
+                    if ( gl_InvocationID == 0 )
+                    {
+                        vec2 U = toPixels( gl_in[0].gl_Position );
+                        vec2 V = toPixels( gl_in[1].gl_Position );
+                        vec2 W = toPixels( gl_in[2].gl_Position );
+                        
+                        float E0 = tessLevel(V, W);
+                        float E1 = tessLevel(W, U);
+                        float E2 = tessLevel(U, V);
+                        
+                        gl_TessLevelOuter[0] = E0;
+                        gl_TessLevelOuter[1] = E1;
+                        gl_TessLevelOuter[2] = E2;
+                        
+                        gl_TessLevelInner[0] = (E0+E1+E2)/3.0;
+                    }
+                }
+                
+            ]]></code>
+        </terrainshader>
+        
+        <terrainshader>
+            <code><![CDATA[            
+                #version 410
+                #pragma vp_name       "Terrain TES Shader"
+                #pragma vp_entryPoint "generateVertex"
+                #pragma vp_location   "tess_eval"
+
+                // osgEarth terrain is always CCW winding
+                layout(triangles, equal_spacing, ccw) in;
+
+                // Internal helpers:
+                void VP_Interpolate3();
+                void VP_EmitVertex();
+                
+                
+                float VP_Interpolate3(float a, float b, float c) {
+                    return dot(gl_TessCoord.xyz, vec3(a,b,c));
+                }
+                
+                vec2 VP_Interpolate3(vec2 a, vec2 b, vec2 c) {
+                    return vec2(dot(gl_TessCoord.xyz, vec3(a.x,b.x,c.x)),
+                                dot(gl_TessCoord.xyz, vec3(a.y,b.y,c.y)));
+                }
+
+                vec3 VP_Interpolate3(vec3 a, vec3 b, vec3 c) {
+                    return vec3(dot(gl_TessCoord.xyz, vec3(a.x,b.x,c.x)),
+                                dot(gl_TessCoord.xyz, vec3(a.y,b.y,c.y)),
+                                dot(gl_TessCoord.xyz, vec3(a.z,b.z,c.z)));
+                }
+
+                vec4 VP_Interpolate3(vec4 a, vec4 b, vec4 c) {
+                    return vec4(dot(gl_TessCoord.xyz, vec3(a.x,b.x,c.x)),
+                                dot(gl_TessCoord.xyz, vec3(a.y,b.y,c.y)),
+                                dot(gl_TessCoord.xyz, vec3(a.z,b.z,c.z)),
+                                dot(gl_TessCoord.xyz, vec3(a.w,b.w,c.w)));
+                }
+                
+                vec3 vp_Normal;
+                
+                // simplest possible pass-though:
+                void generateVertex()
+                {                    
+                    VP_Interpolate3();
+                    
+                    // Must re-normalize the normal vector since interpolation was linear?
+                    vp_Normal = normalize(vp_Normal);
+                    
+                    VP_EmitVertex();
+                }
+            ]]></code>
+        </terrainshader>
+        
+        <viewpoints>
+            <viewpoint name="San Francisco" heading="8.806974516644791" height="4465.397310772911" lat="37.55814749233749" long="-122.334535784141" pitch="-34.79540299384382" range="78142.53643278375" srs="+proj=longlat +ellps=WGS84 +towgs84=0,0,0,0,0,0,0 +no_defs " />
+            <viewpoint name="Mt R. Nadir 30K" heading="0.5013023037097585" height="4101.627114404924" lat="46.85909894548915" long="-121.7598368518208" pitch="-89.43249895879129" range="29029.34246828893"/>
+            <viewpoint name="Mt R. Oblique 30K" heading="17.33521725357022" height="2462.60273069609" lat="46.82181702111031" long="-121.7814936386096" pitch="-21.29241356548601" range="23926.75258864516"/>
+            <viewpoint name="Mt R. Closeup" heading="-109.6842970297122" height="3843.486737414263" lat="46.85528453766688" long="-121.7455004166102" pitch="-4.617466338845979" range="951.4780720092711"/>
+            <viewpoint name="Mt R. Trees" heading="-98.36122712710565" height="1639.304918398149" lat="46.78673277044066" long="-121.743286318636" pitch="-10.85365380742088" range="257.5853045645545"/>
+            <viewpoint name="Nepal" heading="-72.70835146844568" height="6334.845537136309" lat="27.94213038800919" long="86.9936567556778" pitch="-18.63803872963365" range="13611.24948464565"/>
+            <viewpoint name="Nepal NF" heading="-49.14546953546358" height="6334.332569343038" lat="27.9421778947837" long="86.9935949004298" pitch="-3.643325527310435" range="13302.81192964212"/>
+            <viewpoint name="Matterhorn" heading="-1.429462844200832" height="2282.858508689329" lat="45.95106319557" long="7.642741711675961" pitch="-25.12269405854052" range="26690.10606054494"/>
+        </viewpoints>
+               
+    </extensions>
+</map>
diff --git a/tests/tess_screen_space.earth b/tests/tess_screen_space.earth
new file mode 100644
index 0000000..d7d2dd4
--- /dev/null
+++ b/tests/tess_screen_space.earth
@@ -0,0 +1,120 @@
+<!--
+osgEarth Sample - OpenGL Tessellation Shaders
+
+This example demonstrates screen-space terrain tessellation.
+-->
+
+<map name="readymap.org" type="geocentric">
+    
+    <options>        
+        <terrain max_lod="3" skirt_ratio="0" tile_size="7" gpu_tessellation="true"/>
+    </options>
+    
+    <image name="readymap_imagery" driver="tms" opacity="0.5">
+        <url>http://readymap.org/readymap/tiles/1.0.0/7/</url>
+    </image>
+        
+    <extensions>
+    
+        <terrainshader>
+            <code><![CDATA[
+            
+                #version 430 compatibility
+                #pragma vp_entryPoint "configureTess"
+                #pragma vp_location   "tess_control"
+                
+                layout(vertices=3) out;
+                
+                // http://codeflow.org/entries/2010/nov/07/opengl-4-tessellation/
+                
+                uniform float pixelsPerEdge = 64;
+                uniform vec2  viewportSize  = vec2(1024,1024);
+                                
+                // convert model position to viewport coordinates.
+                vec2 toPixels(in vec4 pos) {    
+                    vec4 clip = gl_ModelViewProjectionMatrix * pos;
+                    return clamp( (clip.xy/clip.w), -1.3, 1.3) * (viewportSize*0.5);
+                }
+                
+                // calculate a tesselation level based on the maximum edge length uniform.
+                float tessLevel(in vec2 v0, in vec2 v1) {
+                    return clamp(distance(v0,v1)/pixelsPerEdge, 1.0, 64.0);
+                }
+                
+                void configureTess()
+                {
+                    // Only required for the first invocation:
+                    if ( gl_InvocationID == 0 )
+                    {                       
+                        vec2 ss0 = toPixels( gl_in[0].gl_Position );
+                        vec2 ss1 = toPixels( gl_in[1].gl_Position );
+                        vec2 ss2 = toPixels( gl_in[2].gl_Position );
+                        
+                        float e0 = tessLevel(ss1, ss2);
+                        float e1 = tessLevel(ss2, ss0);
+                        float e2 = tessLevel(ss0, ss1);
+                        
+                        gl_TessLevelOuter[0] = e0;
+                        gl_TessLevelOuter[1] = e1;
+                        gl_TessLevelOuter[2] = e2;
+                        
+                        gl_TessLevelInner[0] = (e0+e1+e2)/3.0;
+                    }
+                }
+                
+            ]]></code>
+        </terrainshader>
+        
+        <terrainshader>
+            <code><![CDATA[            
+                #version 410
+                #pragma vp_name       "Terrain TES Shader"
+                #pragma vp_entryPoint "generateVertex"
+                #pragma vp_location   "tess_eval"
+
+                // osgEarth terrain is always CCW winding
+                layout(triangles, equal_spacing, ccw) in;
+
+                // Internal helpers:
+                void VP_Interpolate3();
+                void VP_EmitVertex();
+                
+                // User must supply interpolators for all the base types:
+                
+                float VP_Interpolate3(float a, float b, float c) {
+                    return dot(gl_TessCoord.xyz, vec3(a,b,c));
+                }
+                
+                vec2 VP_Interpolate3(vec2 a, vec2 b, vec2 c) {
+                    return vec2(dot(gl_TessCoord.xyz, vec3(a.x,b.x,c.x)),
+                                dot(gl_TessCoord.xyz, vec3(a.y,b.y,c.y)));
+                }
+
+                vec3 VP_Interpolate3(vec3 a, vec3 b, vec3 c) {
+                    return vec3(dot(gl_TessCoord.xyz, vec3(a.x,b.x,c.x)),
+                                dot(gl_TessCoord.xyz, vec3(a.y,b.y,c.y)),
+                                dot(gl_TessCoord.xyz, vec3(a.z,b.z,c.z)));
+                }
+
+                vec4 VP_Interpolate3(vec4 a, vec4 b, vec4 c) {
+                    return vec4(dot(gl_TessCoord.xyz, vec3(a.x,b.x,c.x)),
+                                dot(gl_TessCoord.xyz, vec3(a.y,b.y,c.y)),
+                                dot(gl_TessCoord.xyz, vec3(a.z,b.z,c.z)),
+                                dot(gl_TessCoord.xyz, vec3(a.w,b.w,c.w)));
+                }
+                
+                // simplest possible pass-though:
+                void generateVertex()
+                {                    
+                    VP_Interpolate3();
+                    VP_EmitVertex();
+                }
+            ]]></code>
+        </terrainshader>
+        
+        <viewpoints>
+            <viewpoint name="San Francisco" heading="8.806974516644791" height="4465.397310772911" lat="37.55814749233749" long="-122.334535784141" pitch="-34.79540299384382" range="78142.53643278375" srs="+proj=longlat +ellps=WGS84 +towgs84=0,0,0,0,0,0,0 +no_defs " />
+        </viewpoints>
+        
+    </extensions>
+</map>
diff --git a/tests/test-morphing.earth b/tests/test-morphing.earth
new file mode 100644
index 0000000..1d6530b
--- /dev/null
+++ b/tests/test-morphing.earth
@@ -0,0 +1,50 @@
+<!--
+osgEarth Sample - OpenGL Tessellation Shaders
+
+This example injects a Tessellation Control Shader (TCS) and 
+Tessellation Evaluation Shader (TES) into the terrain rendering
+pipeline. This is EXPERIMENTAL so please be advised of the 
+following caveats:
+
+ * Terrain skirts will not render. Set "skirt_ratio" to zero or you
+   will get GL errors.
+ * Set gpu_tessellation="true" on the terrain options.
+ * EarthManipulator doesn't like GL_PATCHES (yet). Use the viewpoints.
+  
+Press 'w' for wireframe mode to see the tessellation!
+-->
+
+<map name="readymap.org" type="geocentric">
+    
+    <options>        
+        <terrain driver="rex" min_lod="15" tile_size="17" skirt_ratio="0.01" />
+    </options>
+    
+    <image name="readymap_imagery" driver="tms">
+        <url>http://readymap.org/readymap/tiles/1.0.0/7/</url>
+    </image>
+	<elevation name="readymap_elevation" driver="tms">
+        <url>http://readymap.org/readymap/tiles/1.0.0/116/</url>
+    </elevation> 
+  <extensions>
+
+    <viewpoints>
+<viewpoint heading="-0.673756rad" height="2463.694609582424" lat="46.95613641063451" long="-121.7620302808055" pitch="-0.545402rad" range="16414.2m" srs="+proj=longlat +ellps=WGS84 +towgs84=0,0,0,0,0,0,0 +no_defs " />
+<viewpoint heading="-0.673756rad" height="2463.694609590806" lat="46.95613641067459" long="-121.7620302808307" pitch="-0.545402rad" range="14137.1m" srs="+proj=longlat +ellps=WGS84 +towgs84=0,0,0,0,0,0,0 +no_defs " />
+	
+	<viewpoint heading="-0.0111633rad" height="2463.63338462729" lat="46.94509938539743" long="-121.7784264529069" pitch="-0.1252rad" range="14255.2m" srs="+proj=longlat +ellps=WGS84 +towgs84=0,0,0,0,0,0,0 +no_defs " />
+
+      <viewpoint name="San Francisco" heading="8.806974516644791" height="4465.397310772911" lat="37.55814749233749" long="-122.334535784141" pitch="-34.79540299384382" range="78142.53643278375" srs="+proj=longlat +ellps=WGS84 +towgs84=0,0,0,0,0,0,0 +no_defs " />
+      <viewpoint name="Mt R. Nadir 30K" heading="0.5013023037097585" height="4101.627114404924" lat="46.85909894548915" long="-121.7598368518208" pitch="-89.43249895879129" range="29029.34246828893"/>
+	  	<viewpoint heading="-0.271177rad" height="2462.848437966779" lat="46.8358008418158" long="-121.8823059183911" pitch="-0.338073rad" range="10578.2m" srs="+proj=longlat +ellps=WGS84 +towgs84=0,0,0,0,0,0,0 +no_defs " />
+      <viewpoint name="Mt R. Oblique 30K" heading="17.33521725357022" height="2462.60273069609" lat="46.82181702111031" long="-121.7814936386096" pitch="-21.29241356548601" range="23926.75258864516"/>
+      <viewpoint name="Mt R. Closeup" heading="-109.6842970297122" height="3843.486737414263" lat="46.85528453766688" long="-121.7455004166102" pitch="-4.617466338845979" range="951.4780720092711"/>
+      <viewpoint name="Mt R. Trees" heading="-98.36122712710565" height="1639.304918398149" lat="46.78673277044066" long="-121.743286318636" pitch="-10.85365380742088" range="257.5853045645545"/>
+      <viewpoint name="Nepal" heading="-72.70835146844568" height="6334.845537136309" lat="27.94213038800919" long="86.9936567556778" pitch="-18.63803872963365" range="13611.24948464565"/>
+      <viewpoint name="Nepal NF" heading="-49.14546953546358" height="6334.332569343038" lat="27.9421778947837" long="86.9935949004298" pitch="-3.643325527310435" range="13302.81192964212"/>
+      <viewpoint name="Matterhorn" heading="-1.429462844200832" height="2282.858508689329" lat="45.95106319557" long="7.642741711675961" pitch="-25.12269405854052" range="26690.10606054494"/>
+
+    </viewpoints>
+
+  </extensions>
+</map>
diff --git a/tests/triton.earth b/tests/triton.earth
index 2f7e698..292151b 100644
--- a/tests/triton.earth
+++ b/tests/triton.earth
@@ -15,29 +15,28 @@ http://sundog-soft.com/sds/features/real-time-3d-clouds/
     <elevation name="readymap_elevation" driver="tms">
         <url>http://readymap.org/readymap/tiles/1.0.0/9/</url>
     </elevation>
-
-    <extensions>
-    
-        <ocean driver="triton"
-               user="my_user_name"
-               license_code="my_license_code"
-			   max_altitude="20000"/>
                
-        <sky hours="18" driver="gl"/>
-        
-        <viewpoints>
-            <viewpoint name="Hawaii"   heading="-29" height="-204" lat="20.6714" long="-156.5384" pitch="-4" range="3270"/>
-            <viewpoint name="Snafu"    heading="-35.42227636584842" height="-188.2792971581221" lat="20.68154179570284" long="-156.5452311560784" pitch="-14.59403736732238" range="5469.652750028356"/>
-            <viewpoint name="NearClip" heading="-0.618211rad" height="-190.1852927561849" lat="20.67586333023495" long="-156.5418074743535" pitch="-0.2546rad" range="1154.32m"/>
-            <viewpoint name="Horizon"  heading="-27.1911" height="-206.3652788307518" lat="20.69785423327782" long="-156.5550697849549" pitch="-16.0293" range="68323m"/>
-        </viewpoints>
-        
-		<annotations>
-			<model name="Object in the water">
-				<url>../data/red_flag.osg.40.scale</url>
-				<position lat="20.6714" long="-156.5384" alt="0"/>
-			</model>
-		</annotations>
+    <sky driver="gl">
+        <hours>18</hours>
+    </sky>
+    
+    <ocean driver="triton">
+        <user> my_user_name </user>
+        <license_code> my_license_code </license_code>
+        <max_altitude> 10000 </max_altitude>
+    </ocean>
+
+    <viewpoints>
+        <viewpoint name="Hawaii"   heading="-29" height="-204" lat="20.6714" long="-156.5384" pitch="-4" range="3270"/>
+        <viewpoint name="Snafu"    heading="-35.42227636584842" height="-188.2792971581221" lat="20.68154179570284" long="-156.5452311560784" pitch="-14.59403736732238" range="5469.652750028356"/>
+        <viewpoint name="NearClip" heading="-0.618211rad" height="-190.1852927561849" lat="20.67586333023495" long="-156.5418074743535" pitch="-0.2546rad" range="1154.32m"/>
+        <viewpoint name="Horizon"  heading="-27.1911" height="-206.3652788307518" lat="20.69785423327782" long="-156.5550697849549" pitch="-16.0293" range="68323m"/>
+    </viewpoints>
         
-    </extensions>
+    <annotations>
+        <model name="Object in the water">
+            <url>../data/red_flag.osg.40.scale</url>
+            <position lat="20.6714" long="-156.5384" alt="0"/>
+        </model>
+    </annotations>
 </map>
diff --git a/tests/triton_drop_shader.earth b/tests/triton_drop_shader.earth
new file mode 100644
index 0000000..528ad68
--- /dev/null
+++ b/tests/triton_drop_shader.earth
@@ -0,0 +1,73 @@
+<map name="drop the ocean">
+    
+    <options>        
+        <terrain driver="mp">
+        </terrain>
+    </options>
+    
+    <image name="readymap_imagery" driver="tms" enabled="true">
+        <url>http://readymap.org/readymap/tiles/1.0.0/7/</url>
+    </image>
+    
+    <elevation name="readymap_elevation" driver="tms">
+        <url>http://readymap.org/readymap/tiles/1.0.0/116/</url>
+    </elevation>
+    
+    <viewpoints>
+        <viewpoint name="Bay">
+          <heading>-35.951</heading>
+          <pitch>-10.6651</pitch>
+          <range>18689.6m</range>
+          <long>-76.29989904111727</long>
+          <lat>37.96073270502878</lat>
+          <height>-11.00035870634019</height>
+          <srs>+proj=longlat +ellps=WGS84 +towgs84=0,0,0,0,0,0,0 +no_defs </srs>
+        </viewpoint>            
+    </viewpoints>
+    
+    <ocean driver="triton"/>
+    
+    <terrainshader>
+      <code>
+        <![CDATA[
+          #pragma vp_entryPoint dropTheOcean
+          #pragma vp_location vertex_view
+            
+          float oe_terrain_getElevation(in vec2);   // osgEarth SDK
+          
+          vec4 oe_layer_tilec;
+          vec3 oe_UpVectorView;
+          
+          out float oe_triton_elev; // osgearth-specific
+          
+          // amount by which to perturb the ocean verts
+          const float strength = 2.9;
+          //uniform float strength;
+          
+          // Triton maximum underwater visibility distance (negated)
+          const float minElev = -100.0;
+          
+          // speed up the dropoff near the shoreline
+          float mix_decel(float y0, float y1, float t)
+          {
+              return mix(y0, y1, 1.0-(1.0-t)*(1.0-t));
+          }
+
+          void dropTheOcean(inout vec4 vert)
+          {
+            float elev = oe_terrain_getElevation(oe_layer_tilec.st);
+            if ( elev < 0.0 && elev > minElev )
+            {
+                float elev2 = max(elev - pow(abs(elev), strength), minElev);
+                float t = clamp( (minElev-elev)/minElev, 0.0, 1.0 );
+                elev2 = mix_decel(elev, elev2, t);                    
+                vert.xyz += oe_UpVectorView*(elev2-elev);
+                
+                oe_triton_elev = elev2; // osgearth specific
+            }
+          }
+        ]]>
+      </code>
+    </terrainshader>
+    
+</map>
diff --git a/tests/vertical_scale.earth b/tests/vertical_scale.earth
deleted file mode 100644
index ff9c613..0000000
--- a/tests/vertical_scale.earth
+++ /dev/null
@@ -1,29 +0,0 @@
-<!--
-osgEarth Sample
-
-VerticalScale terrain effect.
-Try running it with a controller uniform:
-
-  osgearth_viewer vertical_scale --uniform oe_vertscale_scale 1.0 4.0
-
--->
-<map name="readymap.org" type="geocentric" version="2">
-    
-    <options>
-        <elevation_tile_size>15</elevation_tile_size>
-        <terrain lighting="false" first_lod="1" min_lod="19"/>
-    </options>
-    
-    <image name="readymap_imagery" driver="tms" visible="true">
-        <url>http://readymap.org/readymap/tiles/1.0.0/7/</url>
-    </image>
-        
-    <elevation name="readymap_elevation" driver="tms">
-        <url>http://readymap.org/readymap/tiles/1.0.0/9/</url>
-    </elevation>
-	
-	<external>
-	    <vertical_scale scale="2.0"/>
-	</external>
-    
-</map>
diff --git a/tests/viewpoints.xml b/tests/viewpoints.xml
new file mode 100644
index 0000000..2d89078
--- /dev/null
+++ b/tests/viewpoints.xml
@@ -0,0 +1,65 @@
+<?xml version="1.0" ?>
+<viewpoints>
+  <viewpoint>
+    <heading>8.806974516644791</heading>
+    <height>4465.397310772911</height>
+    <lat>37.55814749233749</lat>
+    <long>-122.334535784141</long>
+    <name>San Francisco, California</name>
+    <pitch>-34.79540299384382</pitch>
+    <range>78142.53643278375</range>
+  </viewpoint>
+  <viewpoint>
+    <heading>17.33521725357022</heading>
+    <height>2462.60273069609</height>
+    <lat>46.82181702111031</lat>
+    <long>-121.7814936386096</long>
+    <name>Mt Rainier, Washington</name>
+    <pitch>-21.29241356548601</pitch>
+    <range>23926.75258864516</range>
+  </viewpoint>
+  <viewpoint>
+    <heading>-72.70835146844568</heading>
+    <height>6334.845537136309</height>
+    <lat>27.94213038800919</lat>
+    <long>86.9936567556778</long>
+    <name>Nepal</name>
+    <pitch>-18.63803872963365</pitch>
+    <range>13611.24948464565</range>
+  </viewpoint>
+  <viewpoint>
+    <heading>-1.429462844200832</heading>
+    <height>2282.858508689329</height>
+    <lat>45.95106319557</lat>
+    <long>7.642741711675961</long>
+    <name>The Matterhorn</name>
+    <pitch>-25.12269405854052</pitch>
+    <range>26690.10606054494</range>
+  </viewpoint>
+  <viewpoint>
+    <name>Hallstatt, Austria</name>
+    <heading>-21.36</heading>
+    <pitch>-35.0965</pitch>
+    <range>14786m</range>
+    <long>13.65444893405288</long>
+    <lat>47.56470451831095</lat>
+    <height>502.9998890347779</height>
+  </viewpoint>
+  <viewpoint>
+    <name>Anchorage, Alaska</name>
+    <heading>-6.513</heading>
+    <pitch>-14.4413</pitch>
+    <range>21030.5m</range>
+    <long>-149.9001345817515</long>
+    <lat>61.16407743963008</lat>
+    <height>30.04646527767181</height>
+  </viewpoint>
+  <viewpoint name="Mountainside">
+      <heading>67.9132</heading>
+      <pitch>-6.07322</pitch>
+      <range>2852.25m</range>
+      <long>-121.7712665799263</long>
+      <lat>46.79220713459502</lat>
+      <height>1636.236482798122</height>
+    </viewpoint>
+</viewpoints>

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-grass/osgearth.git



More information about the Pkg-grass-devel mailing list